summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.hgignore62
-rw-r--r--doc/contributions.txt74
-rw-r--r--etc/message.xml30
-rw-r--r--indra/CMakeLists.txt20
-rw-r--r--indra/cmake/00-Common.cmake36
-rw-r--r--indra/cmake/APR.cmake32
-rw-r--r--indra/cmake/Boost.cmake2
-rw-r--r--indra/cmake/CMakeLists.txt10
-rw-r--r--indra/cmake/Copy3rdPartyLibs.cmake395
-rw-r--r--indra/cmake/DeploySharedLibs.cmake73
-rw-r--r--indra/cmake/ExamplePlugin.cmake16
-rw-r--r--indra/cmake/Externals.cmake34
-rw-r--r--indra/cmake/FindMono.cmake2
-rw-r--r--indra/cmake/FindSVN.cmake34
-rw-r--r--indra/cmake/GStreamer010Plugin.cmake39
-rw-r--r--indra/cmake/GetPrerequisites_2_8.cmake786
-rw-r--r--indra/cmake/Glui.cmake28
-rw-r--r--indra/cmake/Glut.cmake19
-rw-r--r--indra/cmake/GoogleMock.cmake27
-rw-r--r--indra/cmake/GooglePerfTools.cmake15
-rw-r--r--indra/cmake/LLAddBuildTest.cmake388
-rw-r--r--indra/cmake/LLAudio.cmake3
-rw-r--r--indra/cmake/LLCommon.cmake8
-rw-r--r--indra/cmake/LLKDU.cmake4
-rw-r--r--indra/cmake/LLLogin.cmake7
-rw-r--r--indra/cmake/LLPlugin.cmake8
-rw-r--r--indra/cmake/LLSharedLibs.cmake74
-rw-r--r--indra/cmake/LLTestCommand.cmake13
-rw-r--r--indra/cmake/LLWindow.cmake2
-rw-r--r--indra/cmake/LLXUIXML.cmake7
-rw-r--r--indra/cmake/Linking.cmake7
-rw-r--r--indra/cmake/MediaPluginBase.cmake8
-rw-r--r--indra/cmake/PluginAPI.cmake16
-rw-r--r--indra/cmake/Pth.cmake21
-rw-r--r--indra/cmake/Python.cmake4
-rw-r--r--indra/cmake/QuickTimePlugin.cmake46
-rw-r--r--indra/cmake/TemplateCheck.cmake2
-rw-r--r--indra/cmake/Variables.cmake5
-rw-r--r--indra/cmake/WebKitLibPlugin.cmake64
-rw-r--r--indra/cmake/run_build_test.py111
-rwxr-xr-xindra/develop.py64
-rw-r--r--indra/integration_tests/CMakeLists.txt3
-rw-r--r--indra/integration_tests/llui_libtest/CMakeLists.txt108
-rw-r--r--indra/integration_tests/llui_libtest/llui_libtest.cpp221
-rw-r--r--indra/integration_tests/llui_libtest/llui_libtest.h36
-rw-r--r--indra/integration_tests/llui_libtest/llwidgetreg.cpp109
-rw-r--r--indra/integration_tests/llui_libtest/llwidgetreg.h43
-rw-r--r--indra/lib/python/indra/base/llsd.py2
-rw-r--r--indra/lib/python/indra/base/lluuid.py10
-rw-r--r--indra/lib/python/indra/util/llmanifest.py6
-rw-r--r--indra/lib/python/indra/util/llsubprocess.py11
-rw-r--r--indra/lib/python/indra/util/llversion.py39
-rw-r--r--indra/lib/python/indra/util/named_query.py4
-rw-r--r--indra/lib/python/indra/util/test_win32_manifest.py149
-rw-r--r--indra/linux_crash_logger/CMakeLists.txt2
-rw-r--r--indra/linux_updater/CMakeLists.txt58
-rw-r--r--indra/linux_updater/linux_updater.cpp818
-rw-r--r--indra/llaudio/CMakeLists.txt47
-rw-r--r--indra/llaudio/llaudiodecodemgr.cpp40
-rw-r--r--indra/llaudio/llaudioengine.cpp1751
-rw-r--r--indra/llaudio/llaudioengine.h452
-rw-r--r--indra/llaudio/llaudioengine_fmod.cpp769
-rw-r--r--indra/llaudio/llaudioengine_fmod.h129
-rw-r--r--indra/llaudio/llaudioengine_openal.cpp546
-rw-r--r--indra/llaudio/llaudioengine_openal.h114
-rw-r--r--indra/llaudio/lllistener.cpp142
-rw-r--r--indra/llaudio/lllistener.h78
-rw-r--r--indra/llaudio/lllistener_ds3d.h74
-rw-r--r--indra/llaudio/lllistener_fmod.cpp131
-rw-r--r--indra/llaudio/lllistener_fmod.h64
-rw-r--r--indra/llaudio/lllistener_openal.cpp116
-rw-r--r--indra/llaudio/lllistener_openal.h64
-rw-r--r--indra/llaudio/llstreamingaudio.h56
-rw-r--r--indra/llaudio/llstreamingaudio_fmod.cpp362
-rw-r--r--indra/llaudio/llstreamingaudio_fmod.h68
-rw-r--r--indra/llaudio/llvorbisencode.cpp505
-rw-r--r--indra/llaudio/llvorbisencode.h64
-rw-r--r--indra/llaudio/llwindgen.h136
-rw-r--r--indra/llcharacter/CMakeLists.txt10
-rw-r--r--indra/llcharacter/llbvhloader.cpp172
-rw-r--r--indra/llcharacter/llbvhloader.h56
-rw-r--r--indra/llcharacter/llcharacter.cpp44
-rw-r--r--indra/llcharacter/llcharacter.h31
-rw-r--r--indra/llcharacter/llgesture.cpp2
-rw-r--r--indra/llcharacter/llheadrotmotion.cpp11
-rw-r--r--indra/llcharacter/lljoint.h2
-rw-r--r--indra/llcharacter/lljointsolverrp3.cpp2
-rw-r--r--indra/llcharacter/lljointstate.h2
-rw-r--r--indra/llcharacter/llkeyframemotion.h1
-rw-r--r--indra/llcharacter/llkeyframemotionparam.cpp7
-rw-r--r--indra/llcharacter/llkeyframestandmotion.cpp2
-rw-r--r--indra/llcharacter/llmotioncontroller.cpp4
-rw-r--r--indra/llcharacter/llmotioncontroller.h6
-rw-r--r--indra/llcharacter/llmultigesture.cpp65
-rw-r--r--indra/llcharacter/llmultigesture.h16
-rw-r--r--indra/llcharacter/llpose.cpp4
-rw-r--r--indra/llcharacter/llpose.h6
-rw-r--r--indra/llcharacter/llvisualparam.cpp55
-rw-r--r--indra/llcharacter/llvisualparam.h46
-rw-r--r--indra/llcharacter/tests/lljoint_test.cpp246
-rw-r--r--indra/llcommon/CMakeLists.txt118
-rw-r--r--indra/llcommon/bitpack.cpp36
-rw-r--r--indra/llcommon/imageids.cpp76
-rw-r--r--indra/llcommon/imageids.h57
-rw-r--r--indra/llcommon/indra_constants.cpp46
-rw-r--r--indra/llcommon/indra_constants.h27
-rw-r--r--indra/llcommon/is_approx_equal_fraction.h23
-rw-r--r--indra/llcommon/linden_common.h31
-rw-r--r--indra/llcommon/ll_template_cast.h160
-rw-r--r--indra/llcommon/llallocator.cpp140
-rw-r--r--indra/llcommon/llallocator.h63
-rw-r--r--indra/llcommon/llallocator_heap_profile.cpp150
-rw-r--r--indra/llcommon/llallocator_heap_profile.h77
-rw-r--r--indra/llcommon/llapp.h13
-rw-r--r--indra/llcommon/llapr.cpp161
-rw-r--r--indra/llcommon/llapr.h60
-rw-r--r--indra/llcommon/llassettype.cpp288
-rw-r--r--indra/llcommon/llassettype.h158
-rw-r--r--indra/llcommon/llbase32.h4
-rw-r--r--indra/llcommon/llbase64.h4
-rw-r--r--indra/llcommon/llboost.h15
-rw-r--r--indra/llcommon/llchat.h12
-rw-r--r--indra/llcommon/llclickaction.h5
-rw-r--r--indra/llcommon/llcommon.cpp2
-rw-r--r--indra/llcommon/llcommon.h6
-rw-r--r--indra/llcommon/llcoros.cpp137
-rw-r--r--indra/llcommon/llcoros.h149
-rw-r--r--indra/llcommon/llcrc.h2
-rw-r--r--indra/llcommon/llcriticaldamp.h2
-rw-r--r--indra/llcommon/llcursortypes.cpp6
-rw-r--r--indra/llcommon/llcursortypes.h8
-rw-r--r--indra/llcommon/lldate.cpp122
-rw-r--r--indra/llcommon/lldate.h14
-rw-r--r--indra/llcommon/lldeleteutils.h53
-rw-r--r--indra/llcommon/lldependencies.cpp86
-rw-r--r--indra/llcommon/lldependencies.h782
-rw-r--r--indra/llcommon/lldictionary.cpp52
-rw-r--r--indra/llcommon/lldictionary.h99
-rwxr-xr-xindra/llcommon/lldoubledispatch.h332
-rw-r--r--indra/llcommon/llerror.cpp30
-rw-r--r--indra/llcommon/llerror.h10
-rw-r--r--indra/llcommon/llerrorcontrol.h88
-rw-r--r--indra/llcommon/llerrorlegacy.h4
-rw-r--r--indra/llcommon/llerrorthread.cpp2
-rw-r--r--indra/llcommon/llerrorthread.h2
-rw-r--r--indra/llcommon/llevent.cpp2
-rw-r--r--indra/llcommon/llevent.h17
-rw-r--r--indra/llcommon/lleventapi.cpp30
-rw-r--r--indra/llcommon/lleventapi.h66
-rw-r--r--indra/llcommon/lleventcoro.cpp129
-rw-r--r--indra/llcommon/lleventcoro.h552
-rw-r--r--indra/llcommon/lleventdispatcher.cpp149
-rw-r--r--indra/llcommon/lleventdispatcher.h193
-rw-r--r--indra/llcommon/lleventfilter.cpp149
-rw-r--r--indra/llcommon/lleventfilter.h186
-rw-r--r--indra/llcommon/llevents.cpp571
-rw-r--r--indra/llcommon/llevents.h1018
-rw-r--r--indra/llcommon/llfasttimer.h338
-rw-r--r--indra/llcommon/llfasttimer_class.cpp751
-rw-r--r--indra/llcommon/llfasttimer_class.h279
-rw-r--r--indra/llcommon/llfile.h14
-rw-r--r--indra/llcommon/llfindlocale.h4
-rw-r--r--indra/llcommon/llfixedbuffer.cpp13
-rw-r--r--indra/llcommon/llfixedbuffer.h22
-rw-r--r--indra/llcommon/llfoldertype.cpp169
-rw-r--r--indra/llcommon/llfoldertype.h112
-rw-r--r--indra/llcommon/llformat.h2
-rw-r--r--indra/llcommon/llframetimer.h2
-rw-r--r--indra/llcommon/llheartbeat.h2
-rw-r--r--indra/llcommon/llinstancetracker.h159
-rw-r--r--indra/llcommon/llkeythrottle.h57
-rw-r--r--indra/llcommon/lllazy.cpp23
-rw-r--r--indra/llcommon/lllazy.h382
-rw-r--r--indra/llcommon/lllistenerwrapper.h181
-rw-r--r--indra/llcommon/llliveappconfig.h2
-rw-r--r--indra/llcommon/lllivefile.h2
-rw-r--r--indra/llcommon/lllog.h2
-rw-r--r--indra/llcommon/lllslconstants.h14
-rw-r--r--indra/llcommon/llmd5.cpp1
-rw-r--r--indra/llcommon/llmd5.h2
-rw-r--r--indra/llcommon/llmemory.cpp208
-rw-r--r--indra/llcommon/llmemory.h431
-rw-r--r--indra/llcommon/llmemorystream.h4
-rw-r--r--indra/llcommon/llmemtype.cpp237
-rw-r--r--indra/llcommon/llmemtype.h302
-rw-r--r--indra/llcommon/llmetrics.cpp2
-rw-r--r--indra/llcommon/llmetrics.h2
-rw-r--r--indra/llcommon/llmortician.h2
-rw-r--r--indra/llcommon/lloptioninterface.cpp39
-rw-r--r--indra/llcommon/lloptioninterface.h46
-rw-r--r--indra/llcommon/llpointer.h177
-rw-r--r--indra/llcommon/llpreprocessor.h61
-rw-r--r--indra/llcommon/llprocesslauncher.cpp344
-rw-r--r--indra/llcommon/llprocesslauncher.h93
-rw-r--r--indra/llcommon/llptrto.cpp108
-rw-r--r--indra/llcommon/llptrto.h93
-rw-r--r--indra/llcommon/llqueuedthread.cpp80
-rw-r--r--indra/llcommon/llqueuedthread.h9
-rw-r--r--indra/llcommon/llrand.h12
-rw-r--r--indra/llcommon/llrefcount.cpp49
-rw-r--r--indra/llcommon/llrefcount.h79
-rw-r--r--indra/llcommon/llrun.h4
-rw-r--r--indra/llcommon/llsafehandle.h168
-rw-r--r--indra/llcommon/llsd.cpp50
-rw-r--r--indra/llcommon/llsd.h10
-rw-r--r--indra/llcommon/llsdserialize.cpp2
-rw-r--r--indra/llcommon/llsdserialize.h31
-rw-r--r--indra/llcommon/llsdserialize_xml.cpp12
-rw-r--r--indra/llcommon/llsdutil.cpp364
-rw-r--r--indra/llcommon/llsdutil.h113
-rw-r--r--indra/llcommon/llsecondlifeurls.cpp36
-rw-r--r--indra/llcommon/llsecondlifeurls.h41
-rw-r--r--indra/llcommon/llsimplehash.h2
-rw-r--r--indra/llcommon/llsingleton.cpp38
-rw-r--r--indra/llcommon/llsingleton.h207
-rw-r--r--indra/llcommon/llstacktrace.cpp142
-rw-r--r--indra/llcommon/llstacktrace.h44
-rw-r--r--indra/llcommon/llstat.cpp93
-rw-r--r--indra/llcommon/llstat.h60
-rw-r--r--indra/llcommon/llstreamtools.h36
-rw-r--r--indra/llcommon/llstring.cpp423
-rw-r--r--indra/llcommon/llstring.h211
-rw-r--r--indra/llcommon/llstringtable.cpp17
-rw-r--r--indra/llcommon/llstringtable.h36
-rw-r--r--indra/llcommon/llsys.cpp132
-rw-r--r--indra/llcommon/llsys.h18
-rw-r--r--indra/llcommon/llthread.cpp18
-rw-r--r--indra/llcommon/llthread.h19
-rw-r--r--indra/llcommon/lltimer.cpp21
-rw-r--r--indra/llcommon/lltimer.h35
-rw-r--r--indra/llcommon/lltreeiterators.h711
-rw-r--r--indra/llcommon/lluri.h4
-rw-r--r--indra/llcommon/lluuid.h9
-rw-r--r--indra/llcommon/llversionserver.h4
-rw-r--r--indra/llcommon/llversionviewer.h10
-rw-r--r--indra/llcommon/llworkerthread.cpp1
-rw-r--r--indra/llcommon/llworkerthread.h10
-rw-r--r--indra/llcommon/metaclass.h2
-rw-r--r--indra/llcommon/metaproperty.h2
-rw-r--r--indra/llcommon/metapropertyt.h13
-rw-r--r--indra/llcommon/reflective.h2
-rw-r--r--indra/llcommon/stdenums.h3
-rw-r--r--indra/llcommon/stringize.h90
-rw-r--r--indra/llcommon/tests/bitpack_test.cpp125
-rw-r--r--indra/llcommon/tests/commonmisc_test.cpp677
-rw-r--r--indra/llcommon/tests/listener.h139
-rw-r--r--indra/llcommon/tests/llallocator_heap_profile_test.cpp150
-rw-r--r--indra/llcommon/tests/llallocator_test.cpp86
-rw-r--r--indra/llcommon/tests/llbase64_test.cpp83
-rw-r--r--indra/llcommon/tests/lldate_test.cpp219
-rw-r--r--indra/llcommon/tests/lldependencies_test.cpp275
-rw-r--r--indra/llcommon/tests/llerror_test.cpp777
-rw-r--r--indra/llcommon/tests/lleventcoro_test.cpp782
-rw-r--r--indra/llcommon/tests/lleventfilter_test.cpp276
-rw-r--r--indra/llcommon/tests/llframetimer_test.cpp118
-rw-r--r--indra/llcommon/tests/llinstancetracker_test.cpp160
-rw-r--r--indra/llcommon/tests/lllazy_test.cpp227
-rw-r--r--indra/llcommon/tests/llmemtype_test.cpp123
-rw-r--r--indra/llcommon/tests/llrand_test.cpp133
-rw-r--r--indra/llcommon/tests/llsdserialize_test.cpp1504
-rw-r--r--indra/llcommon/tests/llstring_test.cpp751
-rw-r--r--indra/llcommon/tests/lltreeiterators_test.cpp1219
-rw-r--r--indra/llcommon/tests/lluri_test.cpp370
-rw-r--r--indra/llcommon/tests/reflection_test.cpp226
-rw-r--r--indra/llcommon/tests/stringize_test.cpp110
-rw-r--r--indra/llcommon/tests/wrapllerrs.h56
-rw-r--r--indra/llcommon/timing.h3
-rw-r--r--indra/llcommon/u64.h10
-rwxr-xr-xindra/llcrashlogger/llcrashlogger.cpp4
-rw-r--r--indra/llimage/CMakeLists.txt4
-rw-r--r--indra/llimage/llimage.cpp120
-rw-r--r--indra/llimage/llimage.h18
-rw-r--r--indra/llimage/llimagedxt.cpp19
-rw-r--r--indra/llimage/llimagedxt.h1
-rw-r--r--indra/llimage/llimagej2c.cpp59
-rw-r--r--indra/llimage/llimagej2c.h4
-rw-r--r--indra/llimage/llimagejpeg.cpp9
-rw-r--r--indra/llimage/llimagetga.cpp4
-rw-r--r--indra/llimage/llimageworker.cpp202
-rw-r--r--indra/llimage/llimageworker.h96
-rw-r--r--indra/llimage/tests/llimageworker_test.cpp260
-rw-r--r--indra/llimagej2coj/llimagej2coj.cpp8
-rw-r--r--indra/llinventory/CMakeLists.txt16
-rw-r--r--indra/llinventory/lleconomy.h2
-rw-r--r--indra/llinventory/llinventory.cpp257
-rw-r--r--indra/llinventory/llinventory.h59
-rw-r--r--indra/llinventory/llinventorytype.cpp210
-rw-r--r--indra/llinventory/llinventorytype.h14
-rw-r--r--indra/llinventory/lllandmark.cpp22
-rw-r--r--indra/llinventory/lllandmark.h25
-rw-r--r--indra/llinventory/llnotecard.h2
-rw-r--r--indra/llinventory/llparcel.cpp133
-rw-r--r--indra/llinventory/llparcel.h42
-rw-r--r--indra/llinventory/llpermissions.cpp87
-rw-r--r--indra/llinventory/llpermissions.h16
-rw-r--r--indra/llinventory/llpermissionsflags.h3
-rw-r--r--indra/llinventory/llsaleinfo.cpp34
-rw-r--r--indra/llinventory/llsaleinfo.h3
-rw-r--r--indra/llinventory/lltransactiontypes.h12
-rw-r--r--indra/llinventory/tests/inventorymisc_test.cpp514
-rw-r--r--indra/llinventory/tests/llparcel_test.cpp75
-rw-r--r--indra/llmath/CMakeLists.txt33
-rw-r--r--indra/llmath/llbbox.cpp162
-rw-r--r--indra/llmath/llbbox.h103
-rw-r--r--indra/llmath/llbboxlocal.h3
-rw-r--r--indra/llmath/llcamera.cpp28
-rw-r--r--indra/llmath/llcamera.h16
-rw-r--r--indra/llmath/llcoord.h9
-rw-r--r--indra/llmath/llinterp.h7
-rw-r--r--indra/llmath/llmath.h5
-rw-r--r--indra/llmath/llmodularmath.cpp36
-rw-r--r--indra/llmath/lloctree.h10
-rw-r--r--indra/llmath/llquaternion.cpp6
-rw-r--r--indra/llmath/llquaternion.h34
-rw-r--r--indra/llmath/llrect.cpp2
-rw-r--r--indra/llmath/llrect.h51
-rw-r--r--indra/llmath/llsdutil_math.cpp7
-rw-r--r--indra/llmath/llsdutil_math.h70
-rw-r--r--indra/llmath/llvolume.cpp23
-rw-r--r--indra/llmath/llvolume.h12
-rw-r--r--indra/llmath/llvolumemgr.h6
-rw-r--r--indra/llmath/m4math.cpp26
-rw-r--r--indra/llmath/m4math.h30
-rw-r--r--indra/llmath/tests/llbbox_test.cpp373
-rw-r--r--indra/llmath/tests/llbboxlocal_test.cpp238
-rw-r--r--indra/llmath/tests/llmodularmath_test.cpp82
-rw-r--r--indra/llmath/tests/llquaternion_test.cpp666
-rw-r--r--indra/llmath/tests/llrect_test.cpp532
-rw-r--r--indra/llmath/tests/m3math_test.cpp327
-rw-r--r--indra/llmath/tests/mathmisc_test.cpp727
-rw-r--r--indra/llmath/tests/v2math_test.cpp454
-rw-r--r--indra/llmath/tests/v3color_test.cpp315
-rw-r--r--indra/llmath/tests/v3dmath_test.cpp532
-rw-r--r--indra/llmath/tests/v3math_test.cpp573
-rw-r--r--indra/llmath/tests/v4color_test.cpp365
-rw-r--r--indra/llmath/tests/v4coloru_test.cpp342
-rw-r--r--indra/llmath/tests/v4math_test.cpp388
-rw-r--r--indra/llmath/tests/xform_test.cpp251
-rw-r--r--indra/llmath/v3color.cpp40
-rw-r--r--indra/llmath/v3color.h1
-rw-r--r--indra/llmath/v3dmath.h8
-rw-r--r--indra/llmath/v3math.cpp14
-rw-r--r--indra/llmath/v3math.h14
-rw-r--r--indra/llmath/v4color.cpp70
-rw-r--r--indra/llmath/v4color.h24
-rw-r--r--indra/llmath/v4coloru.h14
-rw-r--r--indra/llmath/xform.cpp5
-rw-r--r--indra/llmath/xform.h30
-rw-r--r--indra/llmessage/CMakeLists.txt62
-rw-r--r--indra/llmessage/llares.cpp8
-rw-r--r--indra/llmessage/llares.h15
-rw-r--r--indra/llmessage/llareslistener.cpp80
-rw-r--r--indra/llmessage/llareslistener.h36
-rw-r--r--indra/llmessage/llassetstorage.cpp15
-rw-r--r--indra/llmessage/llassetstorage.h17
-rw-r--r--indra/llmessage/llcachename.cpp251
-rw-r--r--indra/llmessage/llcachename.h32
-rw-r--r--indra/llmessage/llcurl.cpp73
-rw-r--r--indra/llmessage/llcurl.h26
-rw-r--r--indra/llmessage/lldatapacker.cpp12
-rw-r--r--indra/llmessage/lldatapacker.h5
-rw-r--r--indra/llmessage/llhttpassetstorage.cpp2
-rw-r--r--indra/llmessage/llhttpassetstorage.h2
-rw-r--r--indra/llmessage/llhttpclient.cpp7
-rw-r--r--indra/llmessage/llhttpclientadapter.cpp9
-rw-r--r--indra/llmessage/llhttpclientadapter.h11
-rw-r--r--indra/llmessage/llhttpclientinterface.h9
-rw-r--r--indra/llmessage/llhttpnode.cpp18
-rw-r--r--indra/llmessage/llhttpnode.h14
-rw-r--r--indra/llmessage/llhttpnodeadapter.h15
-rw-r--r--indra/llmessage/llinstantmessage.cpp4
-rw-r--r--indra/llmessage/llinstantmessage.h3
-rw-r--r--indra/llmessage/lliobuffer.cpp4
-rw-r--r--indra/llmessage/lliohttpserver.cpp15
-rw-r--r--indra/llmessage/lliohttpserver.h1
-rw-r--r--indra/llmessage/llmail.cpp18
-rw-r--r--indra/llmessage/llmessagesenderinterface.h9
-rw-r--r--indra/llmessage/llpartdata.cpp2
-rw-r--r--indra/llmessage/llpumpio.cpp4
-rw-r--r--indra/llmessage/llregionflags.h2
-rw-r--r--indra/llmessage/llregionpresenceverifier.cpp115
-rw-r--r--indra/llmessage/llregionpresenceverifier.h65
-rw-r--r--indra/llmessage/llsdappservices.cpp4
-rw-r--r--indra/llmessage/llsdhttpserver.cpp4
-rw-r--r--indra/llmessage/llsdmessage.cpp153
-rw-r--r--indra/llmessage/llsdmessage.h149
-rwxr-xr-xindra/llmessage/llsdmessagebuilder.cpp1
-rwxr-xr-xindra/llmessage/llsdmessagereader.cpp1
-rw-r--r--indra/llmessage/llstoredmessage.cpp4
-rw-r--r--indra/llmessage/llstoredmessage.h4
-rw-r--r--indra/llmessage/lltemplatemessagebuilder.cpp4
-rw-r--r--indra/llmessage/lltemplatemessagedispatcher.cpp17
-rw-r--r--indra/llmessage/lltemplatemessagedispatcher.h17
-rw-r--r--indra/llmessage/lltemplatemessagereader.cpp11
-rw-r--r--indra/llmessage/llthrottle.cpp25
-rw-r--r--indra/llmessage/llthrottle.h2
-rw-r--r--indra/llmessage/lltransfersourceasset.cpp46
-rw-r--r--indra/llmessage/lltrustedmessageservice.cpp17
-rw-r--r--indra/llmessage/lltrustedmessageservice.h17
-rw-r--r--indra/llmessage/llurlrequest.cpp55
-rw-r--r--indra/llmessage/llurlrequest.h8
-rw-r--r--indra/llmessage/llxfermanager.cpp36
-rw-r--r--indra/llmessage/machine.cpp62
-rw-r--r--indra/llmessage/machine.h28
-rw-r--r--indra/llmessage/message.cpp3
-rw-r--r--indra/llmessage/message.h2
-rw-r--r--indra/llmessage/message_prehash.cpp3
-rw-r--r--indra/llmessage/message_prehash.h1
-rw-r--r--indra/llmessage/sound_ids.cpp314
-rw-r--r--indra/llmessage/sound_ids.h504
-rw-r--r--indra/llmessage/tests/commtest.h23
-rw-r--r--indra/llmessage/tests/llareslistener_test.cpp200
-rw-r--r--indra/llmessage/tests/llcurl_stub.cpp18
-rw-r--r--indra/llmessage/tests/llhost_test.cpp256
-rw-r--r--indra/llmessage/tests/llhttpclientadapter_test.cpp9
-rw-r--r--indra/llmessage/tests/llmime_test.cpp451
-rw-r--r--indra/llmessage/tests/llmockhttpclient.h61
-rw-r--r--indra/llmessage/tests/llnamevalue_test.cpp412
-rw-r--r--indra/llmessage/tests/llpartdata_test.cpp222
-rw-r--r--indra/llmessage/tests/llregionpresenceverifier_test.cpp113
-rw-r--r--indra/llmessage/tests/llsdmessage_test.cpp140
-rw-r--r--indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp17
-rw-r--r--indra/llmessage/tests/lltesthttpclientadapter.cpp4
-rw-r--r--indra/llmessage/tests/lltesthttpclientadapter.h4
-rw-r--r--indra/llmessage/tests/lltestmessagesender.cpp4
-rw-r--r--indra/llmessage/tests/lltestmessagesender.h4
-rw-r--r--indra/llmessage/tests/lltrustedmessageservice_test.cpp17
-rw-r--r--indra/llmessage/tests/llxfer_file_test.cpp64
-rw-r--r--indra/llmessage/tests/networkio.h23
-rw-r--r--indra/llmessage/tests/test_llsdmessage_peer.py30
-rw-r--r--indra/llmessage/tests/testrunner.py53
-rw-r--r--indra/llplugin/CMakeLists.txt63
-rw-r--r--indra/llplugin/llpluginclassmedia.cpp1196
-rw-r--r--indra/llplugin/llpluginclassmedia.h369
-rw-r--r--indra/llplugin/llpluginclassmediaowner.h83
-rw-r--r--indra/llplugin/llplugininstance.cpp173
-rw-r--r--indra/llplugin/llplugininstance.h104
-rw-r--r--indra/llplugin/llpluginmessage.cpp443
-rw-r--r--indra/llplugin/llpluginmessage.h142
-rw-r--r--indra/llplugin/llpluginmessageclasses.h58
-rw-r--r--indra/llplugin/llpluginmessagepipe.cpp317
-rw-r--r--indra/llplugin/llpluginmessagepipe.h93
-rw-r--r--indra/llplugin/llpluginprocesschild.cpp497
-rw-r--r--indra/llplugin/llpluginprocesschild.h113
-rw-r--r--indra/llplugin/llpluginprocessparent.cpp715
-rw-r--r--indra/llplugin/llpluginprocessparent.h170
-rw-r--r--indra/llplugin/llpluginsharedmemory.cpp507
-rw-r--r--indra/llplugin/llpluginsharedmemory.h130
-rw-r--r--indra/llplugin/slplugin/CMakeLists.txt55
-rw-r--r--indra/llplugin/slplugin/slplugin.cpp291
-rw-r--r--indra/llplugin/slplugin/slplugin_info.plist12
-rw-r--r--indra/llprimitive/CMakeLists.txt10
-rw-r--r--indra/llprimitive/llmaterialtable.cpp11
-rw-r--r--indra/llprimitive/llmaterialtable.h2
-rw-r--r--indra/llprimitive/llmediaentry.cpp602
-rw-r--r--indra/llprimitive/llmediaentry.h228
-rw-r--r--indra/llprimitive/llprimitive.cpp269
-rw-r--r--indra/llprimitive/llprimitive.h31
-rw-r--r--indra/llprimitive/llprimtexturelist.cpp26
-rw-r--r--indra/llprimitive/llprimtexturelist.h7
-rw-r--r--indra/llprimitive/lltextureentry.cpp204
-rw-r--r--indra/llprimitive/lltextureentry.h50
-rw-r--r--indra/llprimitive/material_codes.cpp46
-rw-r--r--indra/llprimitive/material_codes.h19
-rw-r--r--indra/llprimitive/tests/llmediaentry_test.cpp490
-rw-r--r--indra/llprimitive/tests/llmessagesystem_stub.cpp30
-rw-r--r--indra/llprimitive/tests/llprimitive_test.cpp214
-rw-r--r--indra/llrender/CMakeLists.txt8
-rw-r--r--indra/llrender/llcubemap.cpp2
-rw-r--r--indra/llrender/llfontbitmapcache.cpp25
-rw-r--r--indra/llrender/llfontbitmapcache.h10
-rw-r--r--indra/llrender/llfontfreetype.cpp568
-rw-r--r--indra/llrender/llfontfreetype.h180
-rw-r--r--indra/llrender/llfontgl.cpp1253
-rw-r--r--indra/llrender/llfontgl.h231
-rw-r--r--indra/llrender/llfontregistry.cpp82
-rw-r--r--indra/llrender/llfontregistry.h15
-rw-r--r--indra/llrender/llgl.cpp267
-rw-r--r--indra/llrender/llgl.h41
-rw-r--r--indra/llrender/llglheaders.h4
-rw-r--r--indra/llrender/llglslshader.cpp10
-rw-r--r--indra/llrender/llglstates.h2
-rw-r--r--indra/llrender/llimagegl.cpp775
-rw-r--r--indra/llrender/llimagegl.h159
-rw-r--r--indra/llrender/llrender.cpp105
-rw-r--r--indra/llrender/llrender.h8
-rw-r--r--indra/llrender/llrendertarget.cpp76
-rw-r--r--indra/llrender/llrendertarget.h8
-rw-r--r--indra/llrender/lltexture.cpp37
-rw-r--r--indra/llrender/lltexture.h79
-rw-r--r--indra/llrender/llvertexbuffer.cpp150
-rw-r--r--indra/llrender/llvertexbuffer.h1
-rw-r--r--indra/llui/CMakeLists.txt119
-rw-r--r--indra/llui/llaccordionctrl.cpp578
-rw-r--r--indra/llui/llaccordionctrl.h123
-rw-r--r--indra/llui/llaccordionctrltab.cpp600
-rw-r--r--indra/llui/llaccordionctrltab.h191
-rw-r--r--indra/llui/llbutton.cpp1035
-rw-r--r--indra/llui/llbutton.h296
-rw-r--r--indra/llui/llcallbackmap.h19
-rw-r--r--indra/llui/llcheckboxctrl.cpp286
-rw-r--r--indra/llui/llcheckboxctrl.h74
-rw-r--r--indra/llui/llclipboard.cpp6
-rw-r--r--indra/llui/llclipboard.h1
-rw-r--r--indra/llui/llcombobox.cpp700
-rw-r--r--indra/llui/llcombobox.h136
-rw-r--r--indra/llui/llconsole.cpp401
-rw-r--r--indra/llui/llconsole.h162
-rw-r--r--indra/llui/llcontainerview.cpp302
-rw-r--r--indra/llui/llcontainerview.h100
-rw-r--r--indra/llui/lldockablefloater.cpp240
-rw-r--r--indra/llui/lldockablefloater.h148
-rw-r--r--indra/llui/lldockcontrol.cpp303
-rw-r--r--indra/llui/lldockcontrol.h99
-rw-r--r--indra/llui/lldraghandle.cpp135
-rw-r--r--indra/llui/lldraghandle.h51
-rw-r--r--indra/llui/llf32uictrl.cpp57
-rw-r--r--indra/llui/llf32uictrl.h83
-rw-r--r--indra/llui/llfiltereditor.cpp51
-rw-r--r--indra/llui/llfiltereditor.h65
-rw-r--r--indra/llui/llflatlistview.cpp1062
-rw-r--r--indra/llui/llflatlistview.h430
-rw-r--r--indra/llui/llfloater.cpp2179
-rw-r--r--indra/llui/llfloater.h443
-rw-r--r--indra/llui/llfloaterreg.cpp461
-rw-r--r--indra/llui/llfloaterreg.h158
-rw-r--r--indra/llui/llfloaterreglistener.cpp130
-rw-r--r--indra/llui/llfloaterreglistener.h36
-rw-r--r--indra/llui/llflyoutbutton.cpp83
-rw-r--r--indra/llui/llflyoutbutton.h74
-rw-r--r--indra/llui/llfocusmgr.cpp197
-rw-r--r--indra/llui/llfocusmgr.h62
-rw-r--r--indra/llui/llfunctorregistry.cpp1
-rw-r--r--indra/llui/llfunctorregistry.h2
-rw-r--r--indra/llui/llhandle.h171
-rw-r--r--indra/llui/llhelp.h49
-rw-r--r--indra/llui/lliconctrl.cpp135
-rw-r--r--indra/llui/lliconctrl.h44
-rw-r--r--indra/llui/llkeywords.cpp37
-rw-r--r--indra/llui/llkeywords.h7
-rw-r--r--indra/llui/lllayoutstack.cpp823
-rw-r--r--indra/llui/lllayoutstack.h130
-rw-r--r--indra/llui/lllazyvalue.h88
-rw-r--r--indra/llui/lllineeditor.cpp999
-rw-r--r--indra/llui/lllineeditor.h203
-rw-r--r--indra/llui/lllocalcliprect.cpp146
-rw-r--r--indra/llui/lllocalcliprect.h53
-rw-r--r--indra/llui/llmenubutton.cpp143
-rw-r--r--indra/llui/llmenubutton.h70
-rw-r--r--indra/llui/llmenugl.cpp3461
-rw-r--r--indra/llui/llmenugl.h663
-rw-r--r--indra/llui/llmodaldialog.cpp92
-rw-r--r--indra/llui/llmodaldialog.h21
-rw-r--r--indra/llui/llmultifloater.cpp509
-rw-r--r--indra/llui/llmultifloater.h106
-rw-r--r--indra/llui/llmultislider.cpp284
-rw-r--r--indra/llui/llmultislider.h142
-rw-r--r--indra/llui/llmultisliderctrl.cpp401
-rw-r--r--indra/llui/llmultisliderctrl.h81
-rw-r--r--indra/llui/llnotificationptr.h41
-rw-r--r--indra/llui/llnotifications.cpp251
-rw-r--r--indra/llui/llnotifications.h239
-rw-r--r--indra/llui/llnotificationslistener.cpp332
-rw-r--r--indra/llui/llnotificationslistener.h52
-rw-r--r--indra/llui/llnotificationsutil.cpp96
-rw-r--r--indra/llui/llnotificationsutil.h70
-rw-r--r--indra/llui/llpanel.cpp1464
-rw-r--r--indra/llui/llpanel.h252
-rw-r--r--indra/llui/llprogressbar.cpp137
-rw-r--r--indra/llui/llprogressbar.h39
-rw-r--r--indra/llui/llradiogroup.cpp363
-rw-r--r--indra/llui/llradiogroup.h83
-rw-r--r--indra/llui/llresizebar.cpp44
-rw-r--r--indra/llui/llresizebar.h26
-rw-r--r--indra/llui/llresizehandle.cpp144
-rw-r--r--indra/llui/llresizehandle.h18
-rw-r--r--indra/llui/llresmgr.cpp155
-rw-r--r--indra/llui/llresmgr.h25
-rw-r--r--indra/llui/llrngwriter.cpp316
-rw-r--r--indra/llui/llrngwriter.h69
-rw-r--r--indra/llui/llscrollbar.cpp321
-rw-r--r--indra/llui/llscrollbar.h90
-rw-r--r--indra/llui/llscrollcontainer.cpp645
-rw-r--r--indra/llui/llscrollcontainer.h70
-rw-r--r--indra/llui/llscrollingpanellist.cpp87
-rw-r--r--indra/llui/llscrollingpanellist.h35
-rw-r--r--indra/llui/llscrolllistcell.cpp441
-rw-r--r--indra/llui/llscrolllistcell.h227
-rw-r--r--indra/llui/llscrolllistcolumn.cpp338
-rw-r--r--indra/llui/llscrolllistcolumn.h178
-rw-r--r--indra/llui/llscrolllistctrl.cpp2135
-rw-r--r--indra/llui/llscrolllistctrl.h476
-rw-r--r--indra/llui/llscrolllistitem.cpp156
-rw-r--r--indra/llui/llscrolllistitem.h131
-rw-r--r--indra/llui/llsdparam.cpp150
-rw-r--r--indra/llui/llsdparam.h107
-rw-r--r--indra/llui/llsearcheditor.cpp165
-rw-r--r--indra/llui/llsearcheditor.h102
-rw-r--r--indra/llui/llslider.cpp343
-rw-r--r--indra/llui/llslider.h102
-rw-r--r--indra/llui/llsliderctrl.cpp347
-rw-r--r--indra/llui/llsliderctrl.h128
-rw-r--r--indra/llui/llspinctrl.cpp381
-rw-r--r--indra/llui/llspinctrl.h78
-rw-r--r--indra/llui/llstatbar.cpp293
-rw-r--r--indra/llui/llstatbar.h108
-rw-r--r--indra/llui/llstatgraph.cpp163
-rw-r--r--indra/llui/llstatgraph.h76
-rw-r--r--indra/llui/llstatview.cpp73
-rw-r--r--indra/llui/llstatview.h72
-rw-r--r--indra/llui/llstyle.cpp130
-rw-r--r--indra/llui/llstyle.h82
-rw-r--r--indra/llui/lltabcontainer.cpp1068
-rw-r--r--indra/llui/lltabcontainer.h166
-rw-r--r--indra/llui/lltextbase.cpp2640
-rw-r--r--indra/llui/lltextbase.h505
-rw-r--r--indra/llui/lltextbox.cpp419
-rw-r--r--indra/llui/lltextbox.h116
-rw-r--r--indra/llui/lltexteditor.cpp3086
-rw-r--r--indra/llui/lltexteditor.h423
-rw-r--r--indra/llui/lltextparser.cpp59
-rw-r--r--indra/llui/lltextparser.h44
-rw-r--r--indra/llui/lltoggleablemenu.cpp89
-rw-r--r--indra/llui/lltoggleablemenu.h68
-rw-r--r--indra/llui/lltooltip.cpp600
-rw-r--r--indra/llui/lltooltip.h173
-rw-r--r--indra/llui/lltransutil.cpp67
-rw-r--r--indra/llui/lltransutil.h51
-rw-r--r--indra/llui/llui.cpp641
-rw-r--r--indra/llui/llui.h718
-rw-r--r--indra/llui/lluicolortable.cpp332
-rw-r--r--indra/llui/lluicolortable.h106
-rw-r--r--indra/llui/lluictrl.cpp738
-rw-r--r--indra/llui/lluictrl.h240
-rw-r--r--indra/llui/lluictrlfactory.cpp572
-rw-r--r--indra/llui/lluictrlfactory.h390
-rw-r--r--indra/llui/lluifwd.h1
-rw-r--r--indra/llui/lluiimage.cpp205
-rw-r--r--indra/llui/lluiimage.h128
-rw-r--r--indra/llui/lluistring.cpp71
-rw-r--r--indra/llui/lluistring.h38
-rw-r--r--indra/llui/llurlaction.cpp148
-rw-r--r--indra/llui/llurlaction.h96
-rw-r--r--indra/llui/llurlentry.cpp643
-rw-r--r--indra/llui/llurlentry.h270
-rw-r--r--indra/llui/llurlmatch.cpp62
-rw-r--r--indra/llui/llurlmatch.h104
-rw-r--r--indra/llui/llurlregistry.cpp245
-rw-r--r--indra/llui/llurlregistry.h99
-rw-r--r--indra/llui/llview.cpp2079
-rw-r--r--indra/llui/llview.h535
-rw-r--r--indra/llui/llviewborder.cpp147
-rw-r--r--indra/llui/llviewborder.h57
-rw-r--r--indra/llui/llviewmodel.cpp163
-rw-r--r--indra/llui/llviewmodel.h219
-rw-r--r--indra/llui/llviewquery.h2
-rw-r--r--indra/llui/tests/llurlentry_stub.cpp64
-rw-r--r--indra/llui/tests/llurlentry_test.cpp614
-rw-r--r--indra/llui/tests/llurlmatch_test.cpp181
-rw-r--r--indra/llvfs/CMakeLists.txt15
-rw-r--r--indra/llvfs/lldir.cpp111
-rw-r--r--indra/llvfs/lldir.h44
-rw-r--r--indra/llvfs/lldir_linux.cpp48
-rw-r--r--indra/llvfs/lldir_linux.h6
-rw-r--r--indra/llvfs/lldir_mac.cpp54
-rw-r--r--indra/llvfs/lldir_mac.h6
-rw-r--r--indra/llvfs/lldir_solaris.cpp21
-rw-r--r--indra/llvfs/lldir_solaris.h3
-rw-r--r--indra/llvfs/lldir_win32.cpp51
-rw-r--r--indra/llvfs/lldir_win32.h6
-rw-r--r--indra/llvfs/lldirguard.h78
-rw-r--r--indra/llvfs/lllfsthread.cpp4
-rw-r--r--indra/llvfs/lllfsthread.h2
-rwxr-xr-xindra/llvfs/llpidlock.cpp18
-rwxr-xr-xindra/llvfs/llpidlock.h19
-rw-r--r--indra/llvfs/llvfile.cpp6
-rw-r--r--indra/llvfs/llvfs.cpp2
-rw-r--r--indra/llvfs/tests/lldir_test.cpp266
-rw-r--r--indra/llwindow/CMakeLists.txt21
-rw-r--r--indra/llwindow/lldxhardware.cpp1
-rw-r--r--indra/llwindow/llkeyboard.cpp71
-rw-r--r--indra/llwindow/llkeyboard.h9
-rw-r--r--indra/llwindow/llkeyboardmacosx.cpp2
-rw-r--r--indra/llwindow/llkeyboardsdl.cpp2
-rw-r--r--indra/llwindow/llkeyboardwin32.cpp14
-rw-r--r--indra/llwindow/llmousehandler.h11
-rw-r--r--indra/llwindow/llpreeditor.h2
-rw-r--r--indra/llwindow/llwindow.cpp233
-rw-r--r--indra/llwindow/llwindow.h85
-rw-r--r--indra/llwindow/llwindowcallbacks.cpp201
-rw-r--r--indra/llwindow/llwindowcallbacks.h85
-rw-r--r--indra/llwindow/llwindowheadless.cpp6
-rw-r--r--indra/llwindow/llwindowheadless.h11
-rw-r--r--indra/llwindow/llwindowmacosx.cpp64
-rw-r--r--indra/llwindow/llwindowmacosx.h11
-rw-r--r--indra/llwindow/llwindowmesaheadless.cpp5
-rw-r--r--indra/llwindow/llwindowmesaheadless.h5
-rw-r--r--indra/llwindow/llwindowsdl.cpp52
-rw-r--r--indra/llwindow/llwindowsdl.h11
-rw-r--r--indra/llwindow/llwindowwin32.cpp178
-rw-r--r--indra/llwindow/llwindowwin32.h9
-rw-r--r--indra/llxml/CMakeLists.txt26
-rw-r--r--indra/llxml/llcontrol.cpp711
-rw-r--r--indra/llxml/llcontrol.h291
-rw-r--r--indra/llxml/llcontrolgroupreader.h73
-rw-r--r--indra/llxml/llxmlnode.cpp288
-rw-r--r--indra/llxml/llxmlnode.h35
-rw-r--r--indra/llxml/llxmlparser.h2
-rw-r--r--indra/llxml/tests/llcontrol_test.cpp161
-rw-r--r--indra/llxuixml/CMakeLists.txt45
-rw-r--r--indra/llxuixml/llinitparam.cpp505
-rw-r--r--indra/llxuixml/llinitparam.h1831
-rw-r--r--indra/llxuixml/llregistry.h347
-rw-r--r--indra/llxuixml/lltrans.cpp261
-rw-r--r--indra/llxuixml/lltrans.h130
-rw-r--r--indra/llxuixml/lluicolor.cpp68
-rw-r--r--indra/llxuixml/lluicolor.h54
-rw-r--r--indra/llxuixml/llxuiparser.cpp970
-rw-r--r--indra/llxuixml/llxuiparser.h177
-rw-r--r--indra/lscript/lscript_byteformat.h2
-rw-r--r--indra/lscript/lscript_compile/CMakeLists.txt2
-rw-r--r--indra/lscript/lscript_compile/indra.l45
-rw-r--r--indra/lscript/lscript_compile/lscript_tree.cpp30
-rw-r--r--indra/lscript/lscript_compile/lscript_tree.h1
-rw-r--r--indra/lscript/lscript_execute.h5
-rw-r--r--indra/lscript/lscript_execute/llscriptresource.cpp2
-rw-r--r--indra/lscript/lscript_execute/lscript_execute.cpp124
-rw-r--r--indra/lscript/lscript_execute/lscript_readlso.cpp4
-rw-r--r--indra/lscript/lscript_export.h2
-rw-r--r--indra/lscript/lscript_library.h12
-rw-r--r--indra/lscript/lscript_library/lscript_library.cpp785
-rw-r--r--indra/mac_crash_logger/CMakeLists.txt4
-rw-r--r--indra/mac_updater/CMakeLists.txt1
-rw-r--r--indra/media_plugins/CMakeLists.txt13
-rw-r--r--indra/media_plugins/base/CMakeLists.txt49
-rw-r--r--indra/media_plugins/base/media_plugin_base.cpp211
-rw-r--r--indra/media_plugins/base/media_plugin_base.exp2
-rw-r--r--indra/media_plugins/base/media_plugin_base.h134
-rw-r--r--indra/media_plugins/example/CMakeLists.txt82
-rw-r--r--indra/media_plugins/example/media_plugin_example.cpp490
-rw-r--r--indra/media_plugins/gstreamer010/CMakeLists.txt79
-rw-r--r--indra/media_plugins/gstreamer010/llmediaimplgstreamer.h59
-rw-r--r--indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp173
-rw-r--r--indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h80
-rw-r--r--indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc51
-rw-r--r--indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc5
-rw-r--r--indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h61
-rw-r--r--indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp533
-rw-r--r--indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h111
-rw-r--r--indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp1215
-rw-r--r--indra/media_plugins/quicktime/CMakeLists.txt91
-rw-r--r--indra/media_plugins/quicktime/media_plugin_quicktime.cpp1112
-rw-r--r--indra/media_plugins/webkit/CMakeLists.txt90
-rw-r--r--indra/media_plugins/webkit/media_plugin_webkit.cpp1000
-rw-r--r--indra/newview/CMakeLists.txt943
-rw-r--r--indra/newview/English.lproj/InfoPlist.strings4
-rw-r--r--indra/newview/Info-SecondLife.plist2
-rw-r--r--indra/newview/app_settings/cmd_line.xml58
-rw-r--r--indra/newview/app_settings/foldertypes.xml63
-rw-r--r--indra/newview/app_settings/ignorable_dialogs.xml280
-rw-r--r--indra/newview/app_settings/keywords.ini55
-rw-r--r--indra/newview/app_settings/logcontrol.xml1
-rw-r--r--indra/newview/app_settings/settings.xml5247
-rw-r--r--indra/newview/app_settings/settings_files.xml61
-rw-r--r--indra/newview/app_settings/settings_per_account.xml27
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl57
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl8
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl13
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl42
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl8
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl5
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl28
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/giF.glsl165
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/giV.glsl22
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl5
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl15
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl20
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl64
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl178
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl66
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl57
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl79
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl10
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl69
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl177
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl111
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/treeF.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/treeV.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/waterF.glsl72
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl132
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl76
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl98
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl84
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl80
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl58
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl188
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl59
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl294
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl24
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl199
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl235
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl25
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl84
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/giF.glsl190
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl25
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/giV.glsl22
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl19
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl20
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl80
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl69
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl297
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl24
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/treeF.glsl18
-rw-r--r--indra/newview/app_settings/std_bump.ini30
-rw-r--r--indra/newview/build_win32_appConfig.py74
-rw-r--r--indra/newview/character/avatar_eye.llmbin0 -> 16011 bytes
-rw-r--r--indra/newview/character/avatar_eye_1.llmbin0 -> 5591 bytes
-rw-r--r--indra/newview/character/avatar_eyelashes.llmbin0 -> 65637 bytes
-rw-r--r--indra/newview/character/avatar_hair.llmbin0 -> 690581 bytes
-rw-r--r--indra/newview/character/avatar_hair_1.llmbin0 -> 5031 bytes
-rw-r--r--indra/newview/character/avatar_hair_2.llmbin0 -> 3261 bytes
-rw-r--r--indra/newview/character/avatar_hair_3.llmbin0 -> 1845 bytes
-rw-r--r--indra/newview/character/avatar_hair_4.llmbin0 -> 927 bytes
-rw-r--r--indra/newview/character/avatar_hair_5.llmbin0 -> 927 bytes
-rw-r--r--indra/newview/character/avatar_head.llmbin0 -> 1665493 bytes
-rw-r--r--indra/newview/character/avatar_head_1.llmbin0 -> 7875 bytes
-rw-r--r--indra/newview/character/avatar_head_2.llmbin0 -> 3675 bytes
-rw-r--r--indra/newview/character/avatar_head_3.llmbin0 -> 1797 bytes
-rw-r--r--indra/newview/character/avatar_head_4.llmbin0 -> 1239 bytes
-rw-r--r--indra/newview/character/avatar_lad.xml20292
-rw-r--r--indra/newview/character/avatar_lower_body.llmbin0 -> 337125 bytes
-rw-r--r--indra/newview/character/avatar_lower_body_1.llmbin0 -> 7083 bytes
-rw-r--r--indra/newview/character/avatar_lower_body_2.llmbin0 -> 4107 bytes
-rw-r--r--indra/newview/character/avatar_lower_body_3.llmbin0 -> 2115 bytes
-rw-r--r--indra/newview/character/avatar_lower_body_4.llmbin0 -> 1629 bytes
-rw-r--r--indra/newview/character/avatar_skirt.llmbin0 -> 72497 bytes
-rw-r--r--indra/newview/character/avatar_skirt_1.llmbin0 -> 1899 bytes
-rw-r--r--indra/newview/character/avatar_skirt_2.llmbin0 -> 1551 bytes
-rw-r--r--indra/newview/character/avatar_skirt_3.llmbin0 -> 1191 bytes
-rw-r--r--indra/newview/character/avatar_skirt_4.llmbin0 -> 843 bytes
-rw-r--r--indra/newview/character/avatar_upper_body.llmbin0 -> 929297 bytes
-rw-r--r--indra/newview/character/avatar_upper_body_1.llmbin0 -> 15627 bytes
-rw-r--r--indra/newview/character/avatar_upper_body_2.llmbin0 -> 8991 bytes
-rw-r--r--indra/newview/character/avatar_upper_body_3.llmbin0 -> 4557 bytes
-rw-r--r--indra/newview/character/avatar_upper_body_4.llmbin0 -> 3453 bytes
-rw-r--r--indra/newview/character/blush_alpha.tgabin0 -> 17352 bytes
-rw-r--r--indra/newview/character/body_skingrain.tgabin0 -> 262188 bytes
-rw-r--r--indra/newview/character/bodyfreckles_alpha.tgabin0 -> 257249 bytes
-rw-r--r--indra/newview/character/bump_face_wrinkles.tgabin0 -> 25243 bytes
-rw-r--r--indra/newview/character/bump_head_base.tgabin0 -> 105525 bytes
-rw-r--r--indra/newview/character/bump_lowerbody_base.tgabin0 -> 112782 bytes
-rw-r--r--indra/newview/character/bump_pants_wrinkles.tgabin0 -> 83183 bytes
-rw-r--r--indra/newview/character/bump_shirt_wrinkles.tgabin0 -> 81501 bytes
-rw-r--r--indra/newview/character/bump_upperbody_base.tgabin0 -> 147581 bytes
-rw-r--r--indra/newview/character/checkerboard.tgabin0 -> 16428 bytes
-rw-r--r--indra/newview/character/eyebrows_alpha.tgabin0 -> 9469 bytes
-rw-r--r--indra/newview/character/eyeliner_alpha.tgabin0 -> 4720 bytes
-rw-r--r--indra/newview/character/eyeshadow_inner_alpha.tgabin0 -> 5466 bytes
-rw-r--r--indra/newview/character/eyeshadow_outer_alpha.tgabin0 -> 7382 bytes
-rw-r--r--indra/newview/character/eyewhite.tgabin0 -> 42353 bytes
-rw-r--r--indra/newview/character/facehair_chincurtains_alpha.tgabin0 -> 34610 bytes
-rw-r--r--indra/newview/character/facehair_moustache_alpha.tgabin0 -> 14017 bytes
-rw-r--r--indra/newview/character/facehair_sideburns_alpha.tgabin0 -> 27328 bytes
-rw-r--r--indra/newview/character/facehair_soulpatch_alpha.tgabin0 -> 11277 bytes
-rw-r--r--indra/newview/character/freckles_alpha.tgabin0 -> 140558 bytes
-rw-r--r--indra/newview/character/glove_length_alpha.tgabin0 -> 49745 bytes
-rw-r--r--indra/newview/character/gloves_fingers_alpha.tgabin0 -> 39616 bytes
-rw-r--r--indra/newview/character/head_alpha.tgabin0 -> 6066 bytes
-rw-r--r--indra/newview/character/head_color.tgabin0 -> 70715 bytes
-rw-r--r--indra/newview/character/head_hair.tgabin0 -> 75600 bytes
-rw-r--r--indra/newview/character/head_highlights_alpha.tgabin0 -> 20503 bytes
-rw-r--r--indra/newview/character/head_shading_alpha.tgabin0 -> 35304 bytes
-rw-r--r--indra/newview/character/head_skingrain.tgabin0 -> 262376 bytes
-rwxr-xr-xindra/newview/character/invisible_head.tgabin0 -> 140793 bytes
-rw-r--r--indra/newview/character/jacket_length_lower_alpha.tgabin0 -> 9768 bytes
-rw-r--r--indra/newview/character/jacket_length_upper_alpha.tgabin0 -> 14617 bytes
-rw-r--r--indra/newview/character/jacket_open_lower_alpha.tgabin0 -> 19732 bytes
-rw-r--r--indra/newview/character/jacket_open_upper_alpha.tgabin0 -> 41606 bytes
-rw-r--r--indra/newview/character/lipgloss_alpha.tgabin0 -> 4738 bytes
-rw-r--r--indra/newview/character/lips_mask.tgabin0 -> 6110 bytes
-rw-r--r--indra/newview/character/lipstick_alpha.tgabin0 -> 7966 bytes
-rw-r--r--indra/newview/character/lowerbody_color.tgabin0 -> 135395 bytes
-rw-r--r--indra/newview/character/lowerbody_highlights_alpha.tgabin0 -> 8695 bytes
-rw-r--r--indra/newview/character/lowerbody_shading_alpha.tgabin0 -> 41766 bytes
-rw-r--r--indra/newview/character/nailpolish_alpha.tgabin0 -> 4656 bytes
-rw-r--r--indra/newview/character/pants_length_alpha.tgabin0 -> 26843 bytes
-rw-r--r--indra/newview/character/pants_waist_alpha.tgabin0 -> 10487 bytes
-rw-r--r--indra/newview/character/rosyface_alpha.tgabin0 -> 44382 bytes
-rw-r--r--indra/newview/character/rouge_alpha.tgabin0 -> 44382 bytes
-rw-r--r--indra/newview/character/shirt_bottom_alpha.tgabin0 -> 32242 bytes
-rw-r--r--indra/newview/character/shirt_collar_alpha.tgabin0 -> 14417 bytes
-rw-r--r--indra/newview/character/shirt_collar_back_alpha.tgabin0 -> 12789 bytes
-rw-r--r--indra/newview/character/shirt_sleeve_alpha.tgabin0 -> 72196 bytes
-rw-r--r--indra/newview/character/shoe_height_alpha.tgabin0 -> 24461 bytes
-rw-r--r--indra/newview/character/skirt_length_alpha.tgabin0 -> 4114 bytes
-rw-r--r--indra/newview/character/skirt_slit_back_alpha.tgabin0 -> 90350 bytes
-rw-r--r--indra/newview/character/skirt_slit_front_alpha.tgabin0 -> 90350 bytes
-rw-r--r--indra/newview/character/skirt_slit_left_alpha.tgabin0 -> 82006 bytes
-rw-r--r--indra/newview/character/skirt_slit_right_alpha.tgabin0 -> 91410 bytes
-rw-r--r--indra/newview/character/underpants_trial_female.tgabin0 -> 48063 bytes
-rw-r--r--indra/newview/character/underpants_trial_male.tgabin0 -> 144983 bytes
-rw-r--r--indra/newview/character/undershirt_trial_female.tgabin0 -> 81390 bytes
-rw-r--r--indra/newview/character/upperbody_color.tgabin0 -> 23348 bytes
-rw-r--r--indra/newview/character/upperbody_highlights_alpha.tgabin0 -> 6509 bytes
-rw-r--r--indra/newview/character/upperbody_shading_alpha.tgabin0 -> 25297 bytes
-rw-r--r--indra/newview/character/upperbodyfreckles_alpha.tgabin0 -> 180104 bytes
-rw-r--r--indra/newview/cursors_mac/UI_CURSOR_TOOLBUY.tifbin14776 -> 0 bytes
-rw-r--r--indra/newview/cursors_mac/UI_CURSOR_TOOLOPEN.tifbin15144 -> 0 bytes
-rw-r--r--indra/newview/cursors_mac/UI_CURSOR_TOOLSIT.tifbin15176 -> 0 bytes
-rw-r--r--indra/newview/da.lproj/language.txt1
-rw-r--r--indra/newview/es.lproj/language.txt1
-rw-r--r--indra/newview/featuretable.txt15
-rw-r--r--indra/newview/featuretable_linux.txt3
-rw-r--r--indra/newview/featuretable_mac.txt3
-rw-r--r--indra/newview/fonts/DejaVuSans-Bold.ttfbin0 -> 573136 bytes
-rw-r--r--indra/newview/fonts/DejaVuSans-BoldOblique.ttfbin0 -> 524056 bytes
-rw-r--r--indra/newview/fonts/DejaVuSans-Oblique.ttfbin0 -> 523804 bytes
-rw-r--r--indra/newview/fonts/DejaVuSans.ttfbin0 -> 622280 bytes
-rw-r--r--indra/newview/fonts/DejaVuSansMono.ttfbin319388 -> 321524 bytes
-rw-r--r--indra/newview/fr.lproj/language.txt1
-rw-r--r--indra/newview/gpu_table.txt11
-rw-r--r--indra/newview/hu.lproj/language.txt1
-rw-r--r--indra/newview/installers/darwin/firstlook-dmg/_DS_Storebin12292 -> 12292 bytes
-rw-r--r--indra/newview/installers/darwin/fix_application_icon_position.sh14
-rw-r--r--indra/newview/installers/darwin/publicnightly-dmg/_DS_Storebin12292 -> 12292 bytes
-rw-r--r--indra/newview/installers/darwin/release-dmg/_DS_Storebin12292 -> 12292 bytes
-rw-r--r--indra/newview/installers/darwin/releasecandidate-dmg/_DS_Storebin12292 -> 12292 bytes
-rw-r--r--indra/newview/installers/windows/installer_template.nsi5
-rw-r--r--indra/newview/installers/windows/lang_fr.nsibin8118 -> 8114 bytes
-rw-r--r--indra/newview/installers/windows/lang_it.nsibin7438 -> 7438 bytes
-rw-r--r--indra/newview/it.lproj/language.txt1
-rw-r--r--indra/newview/licenses-mac.txt509
-rw-r--r--indra/newview/linux_tools/client-readme-voice.txt51
-rw-r--r--indra/newview/linux_tools/client-readme.txt15
-rwxr-xr-xindra/newview/linux_tools/handle_secondlifeprotocol.sh2
-rwxr-xr-xindra/newview/linux_tools/install.sh106
-rwxr-xr-xindra/newview/linux_tools/refresh_desktop_app_entry.sh36
-rwxr-xr-xindra/newview/linux_tools/register_secondlifeprotocol.sh26
-rwxr-xr-xindra/newview/linux_tools/wrapper.sh14
-rw-r--r--indra/newview/llagent.cpp2316
-rw-r--r--indra/newview/llagent.h1688
-rw-r--r--indra/newview/llagentaccess.cpp52
-rw-r--r--indra/newview/llagentaccess.h32
-rw-r--r--indra/newview/llagentlanguage.h4
-rw-r--r--indra/newview/llagentlistener.cpp86
-rw-r--r--indra/newview/llagentlistener.h36
-rw-r--r--indra/newview/llagentpicksinfo.cpp131
-rw-r--r--indra/newview/llagentpicksinfo.h106
-rw-r--r--indra/newview/llagentpilot.cpp9
-rw-r--r--indra/newview/llagentpilot.h1
-rw-r--r--indra/newview/llagentui.cpp200
-rw-r--r--indra/newview/llagentui.h63
-rw-r--r--indra/newview/llagentwearables.cpp2575
-rw-r--r--indra/newview/llagentwearables.h276
-rw-r--r--indra/newview/llappearancemgr.cpp1333
-rw-r--r--indra/newview/llappearancemgr.h215
-rw-r--r--indra/newview/llappviewer.cpp1316
-rw-r--r--indra/newview/llappviewer.h68
-rw-r--r--indra/newview/llappviewerlinux.cpp30
-rw-r--r--indra/newview/llappviewerlinux.h5
-rw-r--r--indra/newview/llappviewerlinux_api_dbus.cpp6
-rw-r--r--indra/newview/llappviewerlistener.cpp44
-rw-r--r--indra/newview/llappviewerlistener.h36
-rw-r--r--indra/newview/llappviewermacosx.cpp72
-rw-r--r--indra/newview/llappviewermacosx.h1
-rw-r--r--indra/newview/llappviewerwin32.cpp65
-rw-r--r--indra/newview/llassetuploadresponders.cpp288
-rw-r--r--indra/newview/llassetuploadresponders.h2
-rw-r--r--indra/newview/llaudiosourcevo.h2
-rw-r--r--indra/newview/llavataractions.cpp611
-rw-r--r--indra/newview/llavataractions.h176
-rw-r--r--indra/newview/llavatariconctrl.cpp310
-rw-r--r--indra/newview/llavatariconctrl.h115
-rw-r--r--indra/newview/llavatarlist.cpp452
-rw-r--r--indra/newview/llavatarlist.h175
-rw-r--r--indra/newview/llavatarlistitem.cpp569
-rw-r--r--indra/newview/llavatarlistitem.h201
-rw-r--r--indra/newview/llavatarpropertiesprocessor.cpp651
-rw-r--r--indra/newview/llavatarpropertiesprocessor.h284
-rw-r--r--indra/newview/llbottomtray.cpp1122
-rw-r--r--indra/newview/llbottomtray.h219
-rw-r--r--indra/newview/llbreadcrumbview.cpp37
-rw-r--r--indra/newview/llbreadcrumbview.h36
-rw-r--r--indra/newview/llcallfloater.cpp744
-rw-r--r--indra/newview/llcallfloater.h264
-rw-r--r--indra/newview/llcallingcard.cpp127
-rw-r--r--indra/newview/llcallingcard.h28
-rw-r--r--indra/newview/llcapabilitylistener.cpp208
-rw-r--r--indra/newview/llcapabilitylistener.h137
-rw-r--r--indra/newview/llcapabilityprovider.h62
-rw-r--r--indra/newview/llcaphttpsender.cpp3
-rw-r--r--indra/newview/llchannelmanager.cpp240
-rw-r--r--indra/newview/llchannelmanager.h127
-rw-r--r--indra/newview/llchatbar.cpp192
-rw-r--r--indra/newview/llchatbar.h9
-rw-r--r--indra/newview/llchathistory.cpp620
-rw-r--r--indra/newview/llchathistory.h150
-rw-r--r--indra/newview/llchatitemscontainerctrl.cpp327
-rw-r--r--indra/newview/llchatitemscontainerctrl.h98
-rw-r--r--indra/newview/llchatmsgbox.cpp98
-rw-r--r--indra/newview/llchatmsgbox.h71
-rw-r--r--indra/newview/llchiclet.cpp1984
-rw-r--r--indra/newview/llchiclet.h1269
-rw-r--r--indra/newview/llclassifiedinfo.cpp36
-rw-r--r--indra/newview/llclassifiedinfo.h3
-rw-r--r--indra/newview/llclassifiedstatsresponder.cpp1
-rw-r--r--indra/newview/llclassifiedstatsresponder.h1
-rw-r--r--indra/newview/llcloud.cpp1
-rw-r--r--indra/newview/llcloud.h2
-rw-r--r--indra/newview/llcolorswatch.cpp183
-rw-r--r--indra/newview/llcolorswatch.h62
-rw-r--r--indra/newview/llcommanddispatcherlistener.cpp60
-rw-r--r--indra/newview/llcommanddispatcherlistener.h31
-rw-r--r--indra/newview/llcommandhandler.cpp128
-rw-r--r--indra/newview/llcommandhandler.h26
-rw-r--r--indra/newview/llcompilequeue.cpp273
-rw-r--r--indra/newview/llcompilequeue.h65
-rw-r--r--indra/newview/llconfirmationmanager.cpp12
-rw-r--r--indra/newview/llcurrencyuimanager.cpp145
-rw-r--r--indra/newview/llcurrencyuimanager.h9
-rw-r--r--indra/newview/lldateutil.cpp161
-rw-r--r--indra/newview/lldateutil.h49
-rw-r--r--indra/newview/lldebugmessagebox.cpp137
-rw-r--r--indra/newview/lldebugmessagebox.h5
-rw-r--r--indra/newview/lldebugview.cpp98
-rw-r--r--indra/newview/lldebugview.h16
-rw-r--r--indra/newview/lldelayedgestureerror.cpp5
-rw-r--r--indra/newview/lldirpicker.cpp1
-rw-r--r--indra/newview/lldndbutton.cpp60
-rw-r--r--indra/newview/lldndbutton.h89
-rw-r--r--indra/newview/lldrawable.cpp113
-rw-r--r--indra/newview/lldrawable.h25
-rw-r--r--indra/newview/lldrawpool.cpp21
-rw-r--r--indra/newview/lldrawpool.h29
-rw-r--r--indra/newview/lldrawpoolalpha.cpp77
-rw-r--r--indra/newview/lldrawpoolavatar.cpp55
-rw-r--r--indra/newview/lldrawpoolavatar.h2
-rw-r--r--indra/newview/lldrawpoolbump.cpp123
-rw-r--r--indra/newview/lldrawpoolbump.h16
-rw-r--r--indra/newview/lldrawpoolsimple.cpp34
-rw-r--r--indra/newview/lldrawpoolsky.cpp71
-rw-r--r--indra/newview/lldrawpoolsky.h4
-rw-r--r--indra/newview/lldrawpoolterrain.cpp95
-rw-r--r--indra/newview/lldrawpoolterrain.h16
-rw-r--r--indra/newview/lldrawpooltree.cpp36
-rw-r--r--indra/newview/lldrawpooltree.h8
-rw-r--r--indra/newview/lldrawpoolwater.cpp94
-rw-r--r--indra/newview/lldrawpoolwater.h14
-rw-r--r--indra/newview/lldrawpoolwlsky.cpp44
-rw-r--r--indra/newview/lldrawpoolwlsky.h10
-rw-r--r--indra/newview/lldriverparam.cpp194
-rw-r--r--indra/newview/lldriverparam.h19
-rw-r--r--indra/newview/lldynamictexture.cpp139
-rw-r--r--indra/newview/lldynamictexture.h46
-rw-r--r--indra/newview/llemote.cpp1
-rw-r--r--indra/newview/lleventinfo.cpp37
-rw-r--r--indra/newview/lleventinfo.h3
-rw-r--r--indra/newview/lleventnotifier.cpp99
-rw-r--r--indra/newview/lleventnotifier.h5
-rw-r--r--indra/newview/lleventpoll.h3
-rw-r--r--indra/newview/llexpandabletextbox.cpp442
-rw-r--r--indra/newview/llexpandabletextbox.h205
-rw-r--r--indra/newview/llface.cpp532
-rw-r--r--indra/newview/llface.h62
-rw-r--r--indra/newview/llface.inl7
-rw-r--r--indra/newview/llfasttimerview.cpp1176
-rw-r--r--indra/newview/llfasttimerview.h44
-rw-r--r--indra/newview/llfavoritesbar.cpp1228
-rw-r--r--indra/newview/llfavoritesbar.h153
-rw-r--r--indra/newview/llfeaturemanager.cpp9
-rw-r--r--indra/newview/llfeaturemanager.h1
-rw-r--r--indra/newview/llfilepicker.cpp8
-rw-r--r--indra/newview/llfilepicker.h5
-rw-r--r--indra/newview/llfirstuse.cpp119
-rw-r--r--indra/newview/llfirstuse.h9
-rw-r--r--indra/newview/llflexibleobject.cpp8
-rw-r--r--indra/newview/llflexibleobject.h1
-rw-r--r--indra/newview/llfloaterabout.cpp410
-rw-r--r--indra/newview/llfloaterabout.h17
-rw-r--r--indra/newview/llfloateranimpreview.cpp284
-rw-r--r--indra/newview/llfloateranimpreview.h24
-rw-r--r--indra/newview/llfloaterauction.cpp354
-rw-r--r--indra/newview/llfloaterauction.h33
-rw-r--r--indra/newview/llfloateravatarpicker.cpp403
-rw-r--r--indra/newview/llfloateravatarpicker.h53
-rw-r--r--indra/newview/llfloateravatartextures.cpp74
-rw-r--r--indra/newview/llfloateravatartextures.h4
-rw-r--r--indra/newview/llfloaterbeacons.cpp48
-rw-r--r--indra/newview/llfloaterbeacons.h10
-rw-r--r--indra/newview/llfloaterbuildoptions.cpp48
-rw-r--r--indra/newview/llfloaterbuildoptions.h15
-rw-r--r--indra/newview/llfloaterbulkpermission.cpp55
-rw-r--r--indra/newview/llfloaterbulkpermission.h18
-rw-r--r--indra/newview/llfloaterbump.cpp67
-rw-r--r--indra/newview/llfloaterbump.h15
-rw-r--r--indra/newview/llfloaterbuy.cpp130
-rw-r--r--indra/newview/llfloaterbuy.h16
-rw-r--r--indra/newview/llfloaterbuycontents.cpp101
-rw-r--r--indra/newview/llfloaterbuycontents.h15
-rw-r--r--indra/newview/llfloaterbuycurrency.cpp212
-rw-r--r--indra/newview/llfloaterbuycurrency.h4
-rw-r--r--indra/newview/llfloaterbuyland.cpp359
-rw-r--r--indra/newview/llfloaterbuyland.h5
-rw-r--r--indra/newview/llfloatercamera.cpp411
-rw-r--r--indra/newview/llfloatercamera.h78
-rw-r--r--indra/newview/llfloaterchat.cpp306
-rw-r--r--indra/newview/llfloaterchat.h35
-rw-r--r--indra/newview/llfloaterchatterbox.cpp136
-rw-r--r--indra/newview/llfloaterchatterbox.h106
-rw-r--r--indra/newview/llfloatercolorpicker.cpp270
-rw-r--r--indra/newview/llfloatercolorpicker.h13
-rw-r--r--indra/newview/llfloaterdaycycle.cpp206
-rw-r--r--indra/newview/llfloaterdaycycle.h57
-rw-r--r--indra/newview/llfloaterenvsettings.cpp183
-rw-r--r--indra/newview/llfloaterenvsettings.h42
-rw-r--r--indra/newview/llfloaterevent.cpp131
-rw-r--r--indra/newview/llfloaterfonttest.cpp25
-rw-r--r--indra/newview/llfloaterfonttest.h15
-rw-r--r--indra/newview/llfloaterfriends.cpp267
-rw-r--r--indra/newview/llfloaterfriends.h19
-rw-r--r--indra/newview/llfloatergesture.cpp701
-rw-r--r--indra/newview/llfloatergesture.h63
-rw-r--r--indra/newview/llfloatergodtools.cpp486
-rw-r--r--indra/newview/llfloatergodtools.h75
-rw-r--r--indra/newview/llfloatergroupinvite.cpp42
-rw-r--r--indra/newview/llfloatergroupinvite.h5
-rw-r--r--indra/newview/llfloatergroups.cpp189
-rw-r--r--indra/newview/llfloatergroups.h23
-rw-r--r--indra/newview/llfloaterhandler.cpp6
-rw-r--r--indra/newview/llfloaterhandler.h4
-rw-r--r--indra/newview/llfloaterhardwaresettings.cpp85
-rw-r--r--indra/newview/llfloaterhardwaresettings.h23
-rw-r--r--indra/newview/llfloaterhelpbrowser.cpp141
-rw-r--r--indra/newview/llfloaterhelpbrowser.h72
-rw-r--r--indra/newview/llfloaterhud.cpp85
-rw-r--r--indra/newview/llfloaterhud.h16
-rw-r--r--indra/newview/llfloaterimagepreview.cpp89
-rw-r--r--indra/newview/llfloaterimagepreview.h26
-rw-r--r--indra/newview/llfloaterinspect.cpp126
-rw-r--r--indra/newview/llfloaterinspect.h24
-rw-r--r--indra/newview/llfloaterinventory.cpp139
-rw-r--r--indra/newview/llfloaterinventory.h80
-rw-r--r--indra/newview/llfloaterjoystick.cpp60
-rw-r--r--indra/newview/llfloaterjoystick.h15
-rw-r--r--indra/newview/llfloaterlagmeter.cpp126
-rw-r--r--indra/newview/llfloaterlagmeter.h12
-rw-r--r--indra/newview/llfloaterland.cpp466
-rw-r--r--indra/newview/llfloaterland.h47
-rw-r--r--indra/newview/llfloaterlandholdings.cpp165
-rw-r--r--indra/newview/llfloaterlandholdings.h14
-rw-r--r--indra/newview/llfloatermap.cpp208
-rw-r--r--indra/newview/llfloatermap.h46
-rw-r--r--indra/newview/llfloatermediabrowser.cpp336
-rw-r--r--indra/newview/llfloatermediabrowser.h83
-rw-r--r--indra/newview/llfloatermediasettings.cpp308
-rw-r--r--indra/newview/llfloatermediasettings.h94
-rw-r--r--indra/newview/llfloatermemleak.cpp162
-rw-r--r--indra/newview/llfloatermemleak.h31
-rw-r--r--indra/newview/llfloaternamedesc.cpp84
-rw-r--r--indra/newview/llfloaternamedesc.h19
-rw-r--r--indra/newview/llfloaternotificationsconsole.cpp62
-rw-r--r--indra/newview/llfloaternotificationsconsole.h16
-rw-r--r--indra/newview/llfloateropenobject.cpp175
-rw-r--r--indra/newview/llfloateropenobject.h24
-rw-r--r--indra/newview/llfloaterparcel.cpp66
-rw-r--r--indra/newview/llfloaterparcel.h8
-rw-r--r--indra/newview/llfloaterpay.cpp571
-rw-r--r--indra/newview/llfloaterpay.h61
-rw-r--r--indra/newview/llfloaterperms.cpp52
-rw-r--r--indra/newview/llfloaterperms.h14
-rw-r--r--indra/newview/llfloaterpostcard.cpp105
-rw-r--r--indra/newview/llfloaterpostcard.h19
-rw-r--r--indra/newview/llfloaterpostprocess.cpp85
-rw-r--r--indra/newview/llfloaterpostprocess.h24
-rw-r--r--indra/newview/llfloaterpreference.cpp1597
-rw-r--r--indra/newview/llfloaterpreference.h169
-rw-r--r--indra/newview/llfloaterproperties.cpp314
-rw-r--r--indra/newview/llfloaterproperties.h46
-rw-r--r--indra/newview/llfloaterregioninfo.cpp562
-rw-r--r--indra/newview/llfloaterregioninfo.h82
-rw-r--r--indra/newview/llfloaterreporter.cpp565
-rw-r--r--indra/newview/llfloaterreporter.h34
-rw-r--r--indra/newview/llfloaterscriptdebug.cpp158
-rw-r--r--indra/newview/llfloaterscriptdebug.h25
-rw-r--r--indra/newview/llfloaterscriptlimits.cpp1136
-rw-r--r--indra/newview/llfloaterscriptlimits.h263
-rw-r--r--indra/newview/llfloatersearch.cpp221
-rw-r--r--indra/newview/llfloatersearch.h88
-rw-r--r--indra/newview/llfloatersellland.cpp164
-rw-r--r--indra/newview/llfloatersellland.h6
-rw-r--r--indra/newview/llfloatersettingsdebug.cpp150
-rw-r--r--indra/newview/llfloatersettingsdebug.h24
-rw-r--r--indra/newview/llfloatersnapshot.cpp260
-rw-r--r--indra/newview/llfloatersnapshot.h27
-rw-r--r--indra/newview/llfloatertelehub.cpp107
-rw-r--r--indra/newview/llfloatertelehub.h23
-rw-r--r--indra/newview/llfloatertestinspectors.cpp119
-rw-r--r--indra/newview/llfloatertestinspectors.h65
-rw-r--r--indra/newview/llfloatertestlistview.cpp41
-rw-r--r--indra/newview/llfloatertestlistview.h49
-rw-r--r--indra/newview/llfloatertools.cpp1537
-rw-r--r--indra/newview/llfloatertools.h79
-rw-r--r--indra/newview/llfloatertopobjects.cpp176
-rw-r--r--indra/newview/llfloatertopobjects.h31
-rw-r--r--indra/newview/llfloatertos.cpp136
-rw-r--r--indra/newview/llfloatertos.h27
-rw-r--r--indra/newview/llfloateruipreview.cpp1884
-rw-r--r--indra/newview/llfloateruipreview.h46
-rw-r--r--indra/newview/llfloaterurldisplay.cpp9
-rw-r--r--indra/newview/llfloaterurldisplay.h8
-rw-r--r--indra/newview/llfloaterurlentry.cpp78
-rw-r--r--indra/newview/llfloaterurlentry.h10
-rw-r--r--indra/newview/llfloatervoicedevicesettings.cpp92
-rw-r--r--indra/newview/llfloatervoicedevicesettings.h26
-rw-r--r--indra/newview/llfloaterwater.cpp280
-rw-r--r--indra/newview/llfloaterwater.h81
-rw-r--r--indra/newview/llfloaterwhitelistentry.cpp98
-rw-r--r--indra/newview/llfloaterwhitelistentry.h (renamed from indra/newview/llfloaterevent.h)38
-rw-r--r--indra/newview/llfloaterwindlight.cpp409
-rw-r--r--indra/newview/llfloaterwindlight.h69
-rw-r--r--indra/newview/llfloaterwindowsize.cpp164
-rw-r--r--indra/newview/llfloaterwindowsize.h41
-rw-r--r--indra/newview/llfloaterworldmap.cpp734
-rw-r--r--indra/newview/llfloaterworldmap.h69
-rw-r--r--indra/newview/llfolderview.cpp3699
-rw-r--r--indra/newview/llfolderview.h771
-rw-r--r--indra/newview/llfoldervieweventlistener.h105
-rw-r--r--indra/newview/llfolderviewitem.cpp2611
-rw-r--r--indra/newview/llfolderviewitem.h550
-rw-r--r--indra/newview/llfriendcard.cpp609
-rw-r--r--indra/newview/llfriendcard.h168
-rw-r--r--indra/newview/llgesturemgr.cpp198
-rw-r--r--indra/newview/llgesturemgr.h44
-rw-r--r--indra/newview/llglsandbox.cpp131
-rw-r--r--indra/newview/llgroupactions.cpp398
-rw-r--r--indra/newview/llgroupactions.h120
-rw-r--r--indra/newview/llgroupiconctrl.cpp145
-rw-r--r--indra/newview/llgroupiconctrl.h92
-rw-r--r--indra/newview/llgrouplist.cpp431
-rw-r--r--indra/newview/llgrouplist.h124
-rw-r--r--indra/newview/llgroupmgr.cpp39
-rw-r--r--indra/newview/llgroupmgr.h1
-rw-r--r--indra/newview/llhomelocationresponder.cpp4
-rw-r--r--indra/newview/llhomelocationresponder.h2
-rw-r--r--indra/newview/llhudeffect.cpp1
-rw-r--r--indra/newview/llhudeffect.h3
-rw-r--r--indra/newview/llhudeffectbeam.cpp1
-rw-r--r--indra/newview/llhudeffectlookat.cpp8
-rw-r--r--indra/newview/llhudeffectpointat.h1
-rw-r--r--indra/newview/llhudeffecttrail.cpp3
-rw-r--r--indra/newview/llhudicon.cpp36
-rw-r--r--indra/newview/llhudicon.h6
-rw-r--r--indra/newview/llhudmanager.cpp8
-rw-r--r--indra/newview/llhudmanager.h2
-rw-r--r--indra/newview/llhudobject.cpp4
-rw-r--r--indra/newview/llhudobject.h2
-rw-r--r--indra/newview/llhudrender.cpp41
-rw-r--r--indra/newview/llhudrender.h2
-rw-r--r--indra/newview/llhudtext.cpp78
-rw-r--r--indra/newview/llhudtext.h2
-rw-r--r--indra/newview/llhudview.cpp32
-rw-r--r--indra/newview/llhudview.h4
-rw-r--r--indra/newview/llimfloater.cpp1044
-rw-r--r--indra/newview/llimfloater.h172
-rw-r--r--indra/newview/llimfloatercontainer.cpp181
-rw-r--r--indra/newview/llimfloatercontainer.h78
-rw-r--r--indra/newview/llimhandler.cpp136
-rw-r--r--indra/newview/llimpanel.cpp1672
-rw-r--r--indra/newview/llimpanel.h173
-rw-r--r--indra/newview/llimview.cpp2609
-rw-r--r--indra/newview/llimview.h449
-rw-r--r--indra/newview/llinspect.cpp110
-rw-r--r--indra/newview/llinspect.h64
-rw-r--r--indra/newview/llinspectavatar.cpp758
-rw-r--r--indra/newview/llinspectavatar.h41
-rw-r--r--indra/newview/llinspectgroup.cpp331
-rw-r--r--indra/newview/llinspectgroup.h41
-rw-r--r--indra/newview/llinspectobject.cpp658
-rw-r--r--indra/newview/llinspectobject.h40
-rw-r--r--indra/newview/llinspectremoteobject.cpp200
-rw-r--r--indra/newview/llinspectremoteobject.h40
-rw-r--r--indra/newview/llinspecttoast.cpp122
-rw-r--r--indra/newview/llinspecttoast.h40
-rw-r--r--indra/newview/llinventoryactions.h47
-rw-r--r--indra/newview/llinventorybridge.cpp4169
-rw-r--r--indra/newview/llinventorybridge.h431
-rw-r--r--indra/newview/llinventoryclipboard.cpp12
-rw-r--r--indra/newview/llinventoryclipboard.h3
-rw-r--r--indra/newview/llinventoryfilter.cpp877
-rw-r--r--indra/newview/llinventoryfilter.h200
-rw-r--r--indra/newview/llinventoryfunctions.cpp369
-rw-r--r--indra/newview/llinventoryfunctions.h118
-rw-r--r--indra/newview/llinventorymodel.cpp1748
-rw-r--r--indra/newview/llinventorymodel.h503
-rw-r--r--indra/newview/llinventoryobserver.cpp596
-rw-r--r--indra/newview/llinventoryobserver.h254
-rw-r--r--indra/newview/llinventorypanel.cpp935
-rw-r--r--indra/newview/llinventorypanel.h210
-rw-r--r--indra/newview/lljoystickbutton.cpp241
-rw-r--r--indra/newview/lljoystickbutton.h86
-rw-r--r--indra/newview/lllandmarkactions.cpp425
-rw-r--r--indra/newview/lllandmarkactions.h144
-rw-r--r--indra/newview/lllandmarklist.cpp103
-rw-r--r--indra/newview/lllandmarklist.h16
-rw-r--r--indra/newview/lllistbrowser.cpp37
-rw-r--r--indra/newview/lllistbrowser.h36
-rw-r--r--indra/newview/lllistview.cpp73
-rw-r--r--indra/newview/lllistview.h66
-rw-r--r--indra/newview/lllocaltextureobject.cpp215
-rw-r--r--indra/newview/lllocaltextureobject.h93
-rw-r--r--indra/newview/lllocationhistory.cpp182
-rw-r--r--indra/newview/lllocationhistory.h137
-rw-r--r--indra/newview/lllocationinputctrl.cpp972
-rw-r--r--indra/newview/lllocationinputctrl.h179
-rw-r--r--indra/newview/lllogchat.cpp322
-rw-r--r--indra/newview/lllogchat.h66
-rw-r--r--indra/newview/llloginhandler.cpp72
-rw-r--r--indra/newview/llloginhandler.h10
-rw-r--r--indra/newview/lllogininstance.cpp474
-rw-r--r--indra/newview/lllogininstance.h114
-rw-r--r--indra/newview/lllookshistorypanel.h72
-rw-r--r--indra/newview/llmanip.cpp77
-rw-r--r--indra/newview/llmaniprotate.cpp57
-rw-r--r--indra/newview/llmanipscale.cpp15
-rw-r--r--indra/newview/llmaniptranslate.cpp91
-rw-r--r--indra/newview/llmaniptranslate.h13
-rw-r--r--indra/newview/llmediactrl.cpp1076
-rw-r--r--indra/newview/llmediactrl.h201
-rwxr-xr-xindra/newview/llmediadataclient.cpp812
-rwxr-xr-xindra/newview/llmediadataclient.h340
-rw-r--r--indra/newview/llmemoryview.cpp206
-rw-r--r--indra/newview/llmemoryview.h22
-rw-r--r--indra/newview/llmenucommands.cpp70
-rw-r--r--indra/newview/llmenucommands.h7
-rw-r--r--indra/newview/llmetricperformancetester.cpp258
-rw-r--r--indra/newview/llmetricperformancetester.h159
-rw-r--r--indra/newview/llmimetypes.cpp25
-rw-r--r--indra/newview/llmimetypes.h6
-rw-r--r--indra/newview/llmorphview.cpp18
-rw-r--r--indra/newview/llmorphview.h10
-rw-r--r--indra/newview/llmoveview.cpp630
-rw-r--r--indra/newview/llmoveview.h147
-rw-r--r--indra/newview/llmutelist.cpp119
-rw-r--r--indra/newview/llmutelist.h17
-rw-r--r--indra/newview/llnamebox.cpp53
-rw-r--r--indra/newview/llnamebox.h23
-rw-r--r--indra/newview/llnameeditor.cpp63
-rw-r--r--indra/newview/llnameeditor.h31
-rw-r--r--indra/newview/llnamelistctrl.cpp445
-rw-r--r--indra/newview/llnamelistctrl.h84
-rw-r--r--indra/newview/llnavigationbar.cpp765
-rw-r--r--indra/newview/llnavigationbar.h111
-rw-r--r--indra/newview/llnearbychat.cpp278
-rw-r--r--indra/newview/llnearbychat.h85
-rw-r--r--indra/newview/llnearbychatbar.cpp848
-rw-r--r--indra/newview/llnearbychatbar.h144
-rw-r--r--indra/newview/llnearbychathandler.cpp401
-rw-r--r--indra/newview/llnearbychathandler.h57
-rw-r--r--indra/newview/llnetmap.cpp478
-rw-r--r--indra/newview/llnetmap.h120
-rw-r--r--indra/newview/llnotificationalerthandler.cpp146
-rw-r--r--indra/newview/llnotificationgrouphandler.cpp139
-rw-r--r--indra/newview/llnotificationhandler.h326
-rw-r--r--indra/newview/llnotificationhandlerutil.cpp205
-rw-r--r--indra/newview/llnotificationmanager.cpp139
-rw-r--r--indra/newview/llnotificationmanager.h83
-rw-r--r--indra/newview/llnotificationofferhandler.cpp179
-rw-r--r--indra/newview/llnotificationscripthandler.cpp179
-rw-r--r--indra/newview/llnotificationtiphandler.cpp145
-rw-r--r--indra/newview/lloutputmonitorctrl.cpp316
-rw-r--r--indra/newview/lloutputmonitorctrl.h149
-rw-r--r--indra/newview/lloverlaybar.cpp59
-rw-r--r--indra/newview/lloverlaybar.h2
-rw-r--r--indra/newview/llpanelappearancetab.h61
-rw-r--r--indra/newview/llpanelavatar.cpp2372
-rw-r--r--indra/newview/llpanelavatar.h457
-rw-r--r--indra/newview/llpanelavatartag.cpp107
-rw-r--r--indra/newview/llpanelavatartag.h93
-rw-r--r--indra/newview/llpanelblockedlist.cpp280
-rw-r--r--indra/newview/llpanelblockedlist.h116
-rw-r--r--indra/newview/llpanelclassified.cpp738
-rw-r--r--indra/newview/llpanelclassified.h144
-rw-r--r--indra/newview/llpanelcontents.cpp82
-rw-r--r--indra/newview/llpanelcontents.h31
-rw-r--r--indra/newview/llpaneleditwearable.cpp657
-rw-r--r--indra/newview/llpaneleditwearable.h114
-rw-r--r--indra/newview/llpanelface.cpp187
-rw-r--r--indra/newview/llpanelface.h30
-rw-r--r--indra/newview/llpanelgroup.cpp874
-rw-r--r--indra/newview/llpanelgroup.h140
-rw-r--r--indra/newview/llpanelgroupgeneral.cpp381
-rw-r--r--indra/newview/llpanelgroupgeneral.h16
-rw-r--r--indra/newview/llpanelgroupinvite.cpp60
-rw-r--r--indra/newview/llpanelgroupinvite.h2
-rw-r--r--indra/newview/llpanelgrouplandmoney.cpp417
-rw-r--r--indra/newview/llpanelgrouplandmoney.h12
-rw-r--r--indra/newview/llpanelgroupnotices.cpp186
-rw-r--r--indra/newview/llpanelgroupnotices.h9
-rw-r--r--indra/newview/llpanelgrouproles.cpp494
-rw-r--r--indra/newview/llpanelgrouproles.h67
-rw-r--r--indra/newview/llpanelhome.cpp79
-rw-r--r--indra/newview/llpanelhome.h64
-rw-r--r--indra/newview/llpanelimcontrolpanel.cpp338
-rw-r--r--indra/newview/llpanelimcontrolpanel.h137
-rw-r--r--indra/newview/llpanelland.cpp13
-rw-r--r--indra/newview/llpanelland.h3
-rw-r--r--indra/newview/llpanellandaudio.cpp194
-rw-r--r--indra/newview/llpanellandaudio.h64
-rw-r--r--indra/newview/llpanellandmarkinfo.cpp464
-rw-r--r--indra/newview/llpanellandmarkinfo.h86
-rw-r--r--indra/newview/llpanellandmarks.cpp1142
-rw-r--r--indra/newview/llpanellandmarks.h173
-rw-r--r--indra/newview/llpanellandmedia.cpp155
-rw-r--r--indra/newview/llpanellandmedia.h14
-rw-r--r--indra/newview/llpanellogin.cpp398
-rw-r--r--indra/newview/llpanellogin.h29
-rw-r--r--indra/newview/llpanelloginlistener.cpp34
-rw-r--r--indra/newview/llpanelloginlistener.h30
-rw-r--r--indra/newview/llpanelmaininventory.cpp1175
-rw-r--r--indra/newview/llpanelmaininventory.h159
-rw-r--r--indra/newview/llpanelme.cpp271
-rw-r--r--indra/newview/llpanelme.h111
-rw-r--r--indra/newview/llpanelmediasettingsgeneral.cpp520
-rw-r--r--indra/newview/llpanelmediasettingsgeneral.h105
-rw-r--r--indra/newview/llpanelmediasettingspermissions.cpp269
-rw-r--r--indra/newview/llpanelmediasettingspermissions.h78
-rw-r--r--indra/newview/llpanelmediasettingssecurity.cpp362
-rw-r--r--indra/newview/llpanelmediasettingssecurity.h87
-rw-r--r--indra/newview/llpanelobject.cpp85
-rw-r--r--indra/newview/llpanelobject.h15
-rw-r--r--indra/newview/llpanelobjectinventory.cpp1964
-rw-r--r--indra/newview/llpanelobjectinventory.h105
-rw-r--r--indra/newview/llpaneloutfitsinventory.cpp633
-rw-r--r--indra/newview/llpaneloutfitsinventory.h134
-rw-r--r--indra/newview/llpanelpeople.cpp1474
-rw-r--r--indra/newview/llpanelpeople.h173
-rw-r--r--indra/newview/llpanelpeoplemenus.cpp212
-rw-r--r--indra/newview/llpanelpeoplemenus.h84
-rw-r--r--indra/newview/llpanelpermissions.cpp955
-rw-r--r--indra/newview/llpanelpermissions.h32
-rw-r--r--indra/newview/llpanelpick.cpp788
-rw-r--r--indra/newview/llpanelpick.h253
-rw-r--r--indra/newview/llpanelpicks.cpp1193
-rw-r--r--indra/newview/llpanelpicks.h283
-rw-r--r--indra/newview/llpanelplace.cpp296
-rw-r--r--indra/newview/llpanelplace.h13
-rw-r--r--indra/newview/llpanelplaceinfo.cpp282
-rw-r--r--indra/newview/llpanelplaceinfo.h130
-rw-r--r--indra/newview/llpanelplaceprofile.cpp608
-rw-r--r--indra/newview/llpanelplaceprofile.h123
-rw-r--r--indra/newview/llpanelplaces.cpp1070
-rw-r--r--indra/newview/llpanelplaces.h143
-rw-r--r--indra/newview/llpanelplacestab.cpp89
-rw-r--r--indra/newview/llpanelplacestab.h70
-rw-r--r--indra/newview/llpanelprimmediacontrols.cpp1286
-rw-r--r--indra/newview/llpanelprimmediacontrols.h211
-rw-r--r--indra/newview/llpanelprofile.cpp262
-rw-r--r--indra/newview/llpanelprofile.h85
-rw-r--r--indra/newview/llpanelprofileview.cpp207
-rw-r--r--indra/newview/llpanelprofileview.h112
-rw-r--r--indra/newview/llpanelteleporthistory.cpp1058
-rw-r--r--indra/newview/llpanelteleporthistory.h122
-rw-r--r--indra/newview/llpanelvolume.cpp159
-rw-r--r--indra/newview/llpanelvolume.h16
-rw-r--r--indra/newview/llpanelvolumepulldown.cpp154
-rw-r--r--indra/newview/llpanelvolumepulldown.h64
-rw-r--r--indra/newview/llparcelselection.h3
-rw-r--r--indra/newview/llparticipantlist.cpp700
-rw-r--r--indra/newview/llparticipantlist.h274
-rw-r--r--indra/newview/llplacesinventorybridge.cpp201
-rw-r--r--indra/newview/llplacesinventorybridge.h91
-rw-r--r--indra/newview/llplacesinventorypanel.cpp191
-rw-r--r--indra/newview/llplacesinventorypanel.h96
-rw-r--r--indra/newview/llpolymesh.cpp8
-rw-r--r--indra/newview/llpolymesh.h3
-rw-r--r--indra/newview/llpolymorph.cpp8
-rw-r--r--indra/newview/llpolymorph.h3
-rw-r--r--indra/newview/llpreview.cpp343
-rw-r--r--indra/newview/llpreview.h85
-rw-r--r--indra/newview/llpreviewanim.cpp74
-rw-r--r--indra/newview/llpreviewanim.h13
-rw-r--r--indra/newview/llpreviewgesture.cpp323
-rw-r--r--indra/newview/llpreviewgesture.h38
-rw-r--r--indra/newview/llpreviewnotecard.cpp197
-rw-r--r--indra/newview/llpreviewnotecard.h20
-rw-r--r--indra/newview/llpreviewscript.cpp965
-rw-r--r--indra/newview/llpreviewscript.h103
-rw-r--r--indra/newview/llpreviewsound.cpp42
-rw-r--r--indra/newview/llpreviewsound.h7
-rw-r--r--indra/newview/llpreviewtexture.cpp389
-rw-r--r--indra/newview/llpreviewtexture.h46
-rw-r--r--indra/newview/llprogressview.cpp58
-rw-r--r--indra/newview/llprogressview.h9
-rw-r--r--indra/newview/llrecentpeople.cpp88
-rw-r--r--indra/newview/llrecentpeople.h106
-rw-r--r--indra/newview/llremoteparcelrequest.cpp127
-rw-r--r--indra/newview/llremoteparcelrequest.h65
-rw-r--r--indra/newview/llresourcedata.h3
-rw-r--r--indra/newview/llrootview.h73
-rw-r--r--indra/newview/llsavedsettingsglue.cpp30
-rw-r--r--indra/newview/llsavedsettingsglue.h10
-rw-r--r--indra/newview/llscreenchannel.cpp832
-rw-r--r--indra/newview/llscreenchannel.h289
-rw-r--r--indra/newview/llscriptfloater.cpp445
-rw-r--r--indra/newview/llscriptfloater.h186
-rw-r--r--indra/newview/llscrollingpanelparam.cpp387
-rw-r--r--indra/newview/llscrollingpanelparam.h100
-rw-r--r--indra/newview/llsearchcombobox.cpp266
-rw-r--r--indra/newview/llsearchcombobox.h110
-rw-r--r--indra/newview/llsearchhistory.cpp154
-rw-r--r--indra/newview/llsearchhistory.h147
-rw-r--r--indra/newview/llselectmgr.cpp497
-rw-r--r--indra/newview/llselectmgr.h144
-rw-r--r--indra/newview/llsidepanelappearance.cpp405
-rw-r--r--indra/newview/llsidepanelappearance.h106
-rw-r--r--indra/newview/llsidepanelinventory.cpp303
-rw-r--r--indra/newview/llsidepanelinventory.h96
-rw-r--r--indra/newview/llsidepanelinventorysubpanel.cpp152
-rw-r--r--indra/newview/llsidepanelinventorysubpanel.h81
-rw-r--r--indra/newview/llsidepaneliteminfo.cpp939
-rw-r--r--indra/newview/llsidepaneliteminfo.h90
-rw-r--r--indra/newview/llsidepaneltaskinfo.cpp1199
-rw-r--r--indra/newview/llsidepaneltaskinfo.h126
-rw-r--r--indra/newview/llsidetray.cpp731
-rw-r--r--indra/newview/llsidetray.h195
-rw-r--r--indra/newview/llsidetraypanelcontainer.cpp92
-rw-r--r--indra/newview/llsidetraypanelcontainer.h97
-rw-r--r--indra/newview/llsky.cpp18
-rw-r--r--indra/newview/llsky.h6
-rw-r--r--indra/newview/llslurl.cpp153
-rw-r--r--indra/newview/llslurl.h106
-rw-r--r--indra/newview/llspatialpartition.cpp779
-rw-r--r--indra/newview/llspatialpartition.h122
-rw-r--r--indra/newview/llspeakbutton.cpp176
-rw-r--r--indra/newview/llspeakbutton.h96
-rw-r--r--indra/newview/llspeakers.cpp903
-rw-r--r--indra/newview/llspeakers.h311
-rw-r--r--indra/newview/llspeakingindicatormanager.cpp249
-rw-r--r--indra/newview/llspeakingindicatormanager.h67
-rw-r--r--indra/newview/llsplitbutton.cpp275
-rw-r--r--indra/newview/llsplitbutton.h112
-rw-r--r--indra/newview/llsprite.cpp2
-rw-r--r--indra/newview/llsprite.h4
-rw-r--r--indra/newview/llstartup.cpp1987
-rw-r--r--indra/newview/llstartup.h23
-rw-r--r--indra/newview/llstartuplistener.cpp34
-rw-r--r--indra/newview/llstartuplistener.h30
-rw-r--r--indra/newview/llstatusbar.cpp605
-rw-r--r--indra/newview/llstatusbar.h54
-rw-r--r--indra/newview/llstylemap.cpp77
-rw-r--r--indra/newview/llstylemap.h16
-rw-r--r--indra/newview/llsurface.cpp39
-rw-r--r--indra/newview/llsurface.h11
-rw-r--r--indra/newview/llsurfacepatch.cpp34
-rw-r--r--indra/newview/llsurfacepatch.h3
-rw-r--r--indra/newview/llsyswellitem.cpp101
-rw-r--r--indra/newview/llsyswellitem.h88
-rw-r--r--indra/newview/llsyswellwindow.cpp992
-rw-r--r--indra/newview/llsyswellwindow.h273
-rw-r--r--indra/newview/llteleporthistory.cpp201
-rw-r--r--indra/newview/llteleporthistory.h238
-rw-r--r--indra/newview/llteleporthistorystorage.cpp253
-rw-r--r--indra/newview/llteleporthistorystorage.h136
-rw-r--r--indra/newview/lltexglobalcolor.cpp157
-rw-r--r--indra/newview/lltexglobalcolor.h88
-rw-r--r--indra/newview/lltexlayer.cpp2196
-rw-r--r--indra/newview/lltexlayer.h641
-rw-r--r--indra/newview/lltexlayerparams.cpp573
-rw-r--r--indra/newview/lltexlayerparams.h191
-rw-r--r--indra/newview/lltextureatlas.cpp422
-rw-r--r--indra/newview/lltextureatlas.h95
-rw-r--r--indra/newview/lltextureatlasmanager.cpp273
-rw-r--r--indra/newview/lltextureatlasmanager.h111
-rw-r--r--indra/newview/lltexturecache.cpp1348
-rw-r--r--indra/newview/lltexturecache.h66
-rw-r--r--indra/newview/lltexturectrl.cpp618
-rw-r--r--indra/newview/lltexturectrl.h80
-rw-r--r--indra/newview/lltexturefetch.cpp1148
-rw-r--r--indra/newview/lltexturefetch.h40
-rw-r--r--indra/newview/lltextureinfo.cpp290
-rw-r--r--indra/newview/lltextureinfo.h80
-rw-r--r--indra/newview/lltextureinfodetails.cpp40
-rw-r--r--indra/newview/lltextureinfodetails.h58
-rw-r--r--indra/newview/lltexturestats.cpp61
-rw-r--r--indra/newview/lltexturestats.h41
-rw-r--r--indra/newview/lltexturestatsuploader.cpp61
-rw-r--r--indra/newview/lltexturestatsuploader.h48
-rw-r--r--indra/newview/lltextureview.cpp669
-rw-r--r--indra/newview/lltextureview.h51
-rw-r--r--indra/newview/lltoast.cpp342
-rw-r--r--indra/newview/lltoast.h190
-rw-r--r--indra/newview/lltoastalertpanel.cpp485
-rw-r--r--indra/newview/lltoastalertpanel.h125
-rw-r--r--indra/newview/lltoastgroupnotifypanel.cpp231
-rw-r--r--indra/newview/lltoastgroupnotifypanel.h85
-rw-r--r--indra/newview/lltoastimpanel.cpp121
-rw-r--r--indra/newview/lltoastimpanel.h74
-rw-r--r--indra/newview/lltoastnotifypanel.cpp307
-rw-r--r--indra/newview/lltoastnotifypanel.h99
-rw-r--r--indra/newview/lltoastpanel.cpp93
-rw-r--r--indra/newview/lltoastpanel.h68
-rw-r--r--indra/newview/lltool.cpp20
-rw-r--r--indra/newview/lltool.h7
-rw-r--r--indra/newview/lltoolbar.cpp292
-rw-r--r--indra/newview/lltoolbar.h21
-rw-r--r--indra/newview/lltoolbrush.cpp7
-rw-r--r--indra/newview/lltoolcomp.cpp25
-rw-r--r--indra/newview/lltoolcomp.h1
-rw-r--r--indra/newview/lltooldraganddrop.cpp498
-rw-r--r--indra/newview/lltooldraganddrop.h33
-rw-r--r--indra/newview/lltoolface.cpp8
-rw-r--r--indra/newview/lltoolfocus.cpp24
-rw-r--r--indra/newview/lltoolgrab.cpp27
-rw-r--r--indra/newview/lltoolgrab.h2
-rw-r--r--indra/newview/lltoolgun.cpp18
-rw-r--r--indra/newview/lltoolgun.h2
-rw-r--r--indra/newview/lltoolindividual.cpp5
-rw-r--r--indra/newview/lltoolmgr.cpp111
-rw-r--r--indra/newview/lltoolmgr.h8
-rw-r--r--indra/newview/lltoolmorph.cpp43
-rw-r--r--indra/newview/lltoolmorph.h17
-rw-r--r--indra/newview/lltoolobjpicker.cpp5
-rw-r--r--indra/newview/lltoolpie.cpp1175
-rw-r--r--indra/newview/lltoolpie.h35
-rw-r--r--indra/newview/lltoolpipette.cpp37
-rw-r--r--indra/newview/lltoolpipette.h15
-rw-r--r--indra/newview/lltoolplacer.cpp109
-rw-r--r--indra/newview/lltoolplacer.h39
-rw-r--r--indra/newview/lltoolselect.cpp8
-rw-r--r--indra/newview/lltoolselectland.cpp10
-rw-r--r--indra/newview/lltoolselectrect.cpp3
-rw-r--r--indra/newview/lltoolview.cpp4
-rw-r--r--indra/newview/lltracker.cpp30
-rw-r--r--indra/newview/lltracker.h2
-rw-r--r--indra/newview/lltransientdockablefloater.cpp105
-rw-r--r--indra/newview/lltransientdockablefloater.h59
-rw-r--r--indra/newview/lltransientfloatermgr.cpp149
-rw-r--r--indra/newview/lltransientfloatermgr.h96
-rw-r--r--indra/newview/lluilistener.cpp56
-rw-r--r--indra/newview/lluilistener.h29
-rw-r--r--indra/newview/lluploaddialog.cpp17
-rw-r--r--indra/newview/llurldispatcher.cpp222
-rw-r--r--indra/newview/llurldispatcher.h15
-rw-r--r--indra/newview/llurldispatcherlistener.cpp58
-rw-r--r--indra/newview/llurldispatcherlistener.h32
-rw-r--r--indra/newview/llurlhistory.cpp2
-rw-r--r--indra/newview/llurllineeditorctrl.cpp103
-rw-r--r--indra/newview/llurllineeditorctrl.h100
-rw-r--r--indra/newview/llurlwhitelist.cpp6
-rw-r--r--indra/newview/llversioninfo.cpp109
-rw-r--r--indra/newview/llversioninfo.h71
-rw-r--r--indra/newview/llviewchildren.cpp19
-rw-r--r--indra/newview/llviewchildren.h2
-rw-r--r--indra/newview/llviewerassetstorage.cpp8
-rw-r--r--indra/newview/llviewerassetstorage.h1
-rw-r--r--indra/newview/llviewerassettype.cpp113
-rw-r--r--indra/newview/llviewerassettype.h54
-rw-r--r--indra/newview/llvieweraudio.cpp37
-rw-r--r--indra/newview/llviewercamera.cpp161
-rw-r--r--indra/newview/llviewercamera.h41
-rw-r--r--indra/newview/llviewerchat.cpp221
-rw-r--r--indra/newview/llviewerchat.h52
-rw-r--r--indra/newview/llviewercontrol.cpp486
-rw-r--r--indra/newview/llviewercontrol.h118
-rw-r--r--indra/newview/llviewercontrollistener.cpp112
-rw-r--r--indra/newview/llviewercontrollistener.h33
-rw-r--r--indra/newview/llviewerdisplay.cpp344
-rw-r--r--indra/newview/llviewerfloaterreg.cpp271
-rw-r--r--indra/newview/llviewerfloaterreg.h43
-rw-r--r--indra/newview/llviewerfoldertype.cpp277
-rw-r--r--indra/newview/llviewerfoldertype.h59
-rw-r--r--indra/newview/llviewergenericmessage.h1
-rw-r--r--indra/newview/llviewergesture.cpp8
-rw-r--r--indra/newview/llviewerhelp.cpp156
-rw-r--r--indra/newview/llviewerhelp.h71
-rw-r--r--indra/newview/llviewerhelputil.cpp73
-rw-r--r--indra/newview/llviewerhelputil.h47
-rw-r--r--indra/newview/llviewerhome.cpp83
-rw-r--r--indra/newview/llviewerhome.h49
-rw-r--r--indra/newview/llviewerinventory.cpp813
-rw-r--r--indra/newview/llviewerinventory.h86
-rw-r--r--indra/newview/llviewerjoint.h1
-rw-r--r--indra/newview/llviewerjointattachment.cpp247
-rw-r--r--indra/newview/llviewerjointattachment.h36
-rw-r--r--indra/newview/llviewerjointmesh.cpp23
-rw-r--r--indra/newview/llviewerjointmesh.h9
-rw-r--r--indra/newview/llviewerjoystick.cpp89
-rw-r--r--indra/newview/llviewerjoystick.h8
-rw-r--r--indra/newview/llviewerkeyboard.cpp70
-rw-r--r--indra/newview/llviewermedia.cpp2863
-rw-r--r--indra/newview/llviewermedia.h364
-rw-r--r--indra/newview/llviewermedia_streamingaudio.cpp172
-rw-r--r--indra/newview/llviewermedia_streamingaudio.h69
-rw-r--r--indra/newview/llviewermediafocus.cpp566
-rw-r--r--indra/newview/llviewermediafocus.h113
-rw-r--r--indra/newview/llviewermediaobserver.h71
-rw-r--r--indra/newview/llviewermenu.cpp6758
-rw-r--r--indra/newview/llviewermenu.h103
-rw-r--r--indra/newview/llviewermenufile.cpp192
-rw-r--r--indra/newview/llviewermenufile.h7
-rw-r--r--indra/newview/llviewermessage.cpp1499
-rw-r--r--indra/newview/llviewermessage.h15
-rw-r--r--indra/newview/llviewernetwork.cpp11
-rw-r--r--indra/newview/llviewernetwork.h4
-rw-r--r--indra/newview/llviewerobject.cpp297
-rw-r--r--indra/newview/llviewerobject.h53
-rw-r--r--indra/newview/llviewerobjectlist.cpp182
-rw-r--r--indra/newview/llviewerobjectlist.h15
-rw-r--r--indra/newview/llviewerparcelmedia.cpp399
-rw-r--r--indra/newview/llviewerparcelmedia.h33
-rw-r--r--indra/newview/llviewerparcelmediaautoplay.cpp24
-rw-r--r--indra/newview/llviewerparcelmediaautoplay.h3
-rw-r--r--indra/newview/llviewerparcelmgr.cpp357
-rw-r--r--indra/newview/llviewerparcelmgr.h73
-rw-r--r--indra/newview/llviewerparceloverlay.cpp70
-rw-r--r--indra/newview/llviewerparceloverlay.h10
-rw-r--r--indra/newview/llviewerpartsim.cpp16
-rw-r--r--indra/newview/llviewerpartsim.h10
-rw-r--r--indra/newview/llviewerpartsource.cpp16
-rw-r--r--indra/newview/llviewerpartsource.h11
-rw-r--r--indra/newview/llviewerprecompiledheaders.h121
-rw-r--r--indra/newview/llviewerregion.cpp51
-rw-r--r--indra/newview/llviewerregion.h30
-rw-r--r--indra/newview/llviewershadermgr.cpp149
-rw-r--r--indra/newview/llviewershadermgr.h30
-rw-r--r--indra/newview/llviewerstats.cpp155
-rw-r--r--indra/newview/llviewerstats.h27
-rw-r--r--indra/newview/llviewertexteditor.cpp1078
-rw-r--r--indra/newview/llviewertexteditor.h43
-rw-r--r--indra/newview/llviewertexture.cpp3656
-rw-r--r--indra/newview/llviewertexture.h794
-rw-r--r--indra/newview/llviewertexturelist.cpp1582
-rw-r--r--indra/newview/llviewertexturelist.h263
-rw-r--r--indra/newview/llviewerthrottle.cpp2
-rw-r--r--indra/newview/llviewervisualparam.cpp29
-rw-r--r--indra/newview/llviewervisualparam.h11
-rw-r--r--indra/newview/llviewerwindow.cpp2237
-rw-r--r--indra/newview/llviewerwindow.h173
-rw-r--r--indra/newview/llviewerwindowlistener.cpp95
-rw-r--r--indra/newview/llviewerwindowlistener.h34
-rw-r--r--indra/newview/llvlcomposition.cpp44
-rw-r--r--indra/newview/llvlcomposition.h6
-rw-r--r--indra/newview/llvlmanager.cpp1
-rw-r--r--indra/newview/llvoavatar.cpp4056
-rw-r--r--indra/newview/llvoavatar.h1340
-rw-r--r--indra/newview/llvoavatardefines.cpp263
-rw-r--r--indra/newview/llvoavatardefines.h183
-rw-r--r--indra/newview/llvoavatarself.cpp2241
-rw-r--r--indra/newview/llvoavatarself.h333
-rw-r--r--indra/newview/llvoclouds.cpp17
-rw-r--r--indra/newview/llvoclouds.h4
-rw-r--r--indra/newview/llvograss.cpp24
-rw-r--r--indra/newview/llvograss.h4
-rw-r--r--indra/newview/llvoground.cpp3
-rw-r--r--indra/newview/llvoground.h4
-rw-r--r--indra/newview/llvoicechannel.cpp907
-rw-r--r--indra/newview/llvoicechannel.h199
-rw-r--r--indra/newview/llvoiceclient.cpp482
-rw-r--r--indra/newview/llvoiceclient.h24
-rw-r--r--indra/newview/llvoicevisualizer.cpp42
-rw-r--r--indra/newview/llvoicevisualizer.h2
-rw-r--r--indra/newview/llvopartgroup.cpp33
-rw-r--r--indra/newview/llvopartgroup.h2
-rw-r--r--indra/newview/llvosky.cpp53
-rw-r--r--indra/newview/llvosky.h20
-rw-r--r--indra/newview/llvosurfacepatch.cpp22
-rw-r--r--indra/newview/llvosurfacepatch.h3
-rw-r--r--indra/newview/llvotextbubble.cpp13
-rw-r--r--indra/newview/llvotextbubble.h2
-rw-r--r--indra/newview/llvotree.cpp21
-rw-r--r--indra/newview/llvotree.h8
-rw-r--r--indra/newview/llvotreenew.h6
-rw-r--r--indra/newview/llvovolume.cpp1461
-rw-r--r--indra/newview/llvovolume.h98
-rw-r--r--indra/newview/llvowater.cpp14
-rw-r--r--indra/newview/llvowater.h4
-rw-r--r--indra/newview/llvowlsky.cpp49
-rw-r--r--indra/newview/llwatchdog.h3
-rw-r--r--indra/newview/llwaterparammanager.cpp30
-rw-r--r--indra/newview/llwaterparamset.cpp2
-rw-r--r--indra/newview/llwearable.cpp859
-rw-r--r--indra/newview/llwearable.h154
-rw-r--r--indra/newview/llwearablelist.cpp130
-rw-r--r--indra/newview/llwearablelist.h30
-rw-r--r--indra/newview/llweb.cpp92
-rw-r--r--indra/newview/llweb.h30
-rw-r--r--indra/newview/llwind.cpp1
-rw-r--r--indra/newview/llwldaycycle.cpp8
-rw-r--r--indra/newview/llwldaycycle.h2
-rw-r--r--indra/newview/llwlparammanager.cpp42
-rw-r--r--indra/newview/llworld.cpp12
-rw-r--r--indra/newview/llworld.h8
-rw-r--r--indra/newview/llworldmap.cpp1190
-rw-r--r--indra/newview/llworldmap.h340
-rw-r--r--indra/newview/llworldmapmessage.cpp262
-rw-r--r--indra/newview/llworldmapmessage.h83
-rw-r--r--indra/newview/llworldmapview.cpp1367
-rw-r--r--indra/newview/llworldmapview.h59
-rw-r--r--indra/newview/llworldmipmap.cpp274
-rw-r--r--indra/newview/llworldmipmap.h100
-rw-r--r--indra/newview/llxmlrpclistener.cpp497
-rw-r--r--indra/newview/llxmlrpclistener.h35
-rw-r--r--indra/newview/llxmlrpctransaction.cpp28
-rw-r--r--indra/newview/llxmlrpctransaction.h6
-rw-r--r--indra/newview/macview_Prefix.h5
-rw-r--r--indra/newview/nl.lproj/language.txt1
-rw-r--r--indra/newview/pipeline.cpp3933
-rw-r--r--indra/newview/pipeline.h181
-rw-r--r--indra/newview/pl.lproj/language.txt1
-rw-r--r--indra/newview/pt.lproj/language.txt1
-rw-r--r--indra/newview/res-sdl/arrow.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/arrowcop.BMPbin0 -> 3126 bytes
-rw-r--r--indra/newview/res-sdl/arrowcopmulti.BMPbin0 -> 3126 bytes
-rw-r--r--indra/newview/res-sdl/arrowdrag.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/circleandline.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/cross.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/hand.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/ibeam.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/ll_icon.BMPbin0 -> 5174 bytes
-rw-r--r--indra/newview/res-sdl/llarrow.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/llarrowdrag.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/llarrowdragmulti.BMPbin0 -> 3126 bytes
-rw-r--r--indra/newview/res-sdl/llarrowlocked.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/llgrablocked.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/llno.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/llnolocked.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/lltoolcamera.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/lltoolcreate.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/lltoolfocus.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/lltoolgrab.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/lltoolland.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/lltoolpan.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/lltoolpipette.BMPbin0 -> 3126 bytes
-rw-r--r--indra/newview/res-sdl/lltoolrotate.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/lltoolscale.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/lltooltranslate.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/lltoolzoomin.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/lltoolzoomout.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/sizenesw.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/sizens.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/sizenwse.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/sizewe.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/toolmediaopen.BMPbin0 -> 3128 bytes
-rw-r--r--indra/newview/res-sdl/toolpause.BMPbin0 -> 3128 bytes
-rw-r--r--indra/newview/res-sdl/toolpickobject.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/toolpickobject2.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/toolpickobject3.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/toolplay.BMPbin0 -> 3128 bytes
-rw-r--r--indra/newview/res-sdl/wait.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res-sdl/working.BMPbin0 -> 2102 bytes
-rw-r--r--indra/newview/res/bitmap2.bmpbin0 -> 25118 bytes
-rw-r--r--indra/newview/res/install_icon.BMPbin0 -> 262198 bytes
-rw-r--r--indra/newview/res/loginbackground.bmpbin0 -> 336054 bytes
-rw-r--r--indra/newview/res/toolbuy.curbin2238 -> 0 bytes
-rw-r--r--indra/newview/res/toolopen.curbin2238 -> 0 bytes
-rw-r--r--indra/newview/res/toolsit.curbin2238 -> 0 bytes
-rw-r--r--indra/newview/res/uninstall_icon.BMPbin0 -> 262198 bytes
-rw-r--r--indra/newview/res/viewerRes.rc12
-rw-r--r--indra/newview/ru.lproj/language.txt1
-rw-r--r--indra/newview/skins/default/colors.xml727
-rw-r--r--indra/newview/skins/default/html/da/loading/loading.html10
-rw-r--r--indra/newview/skins/default/html/de/loading/loading.html10
-rw-r--r--indra/newview/skins/default/html/en-us/help-offline/index.html29
-rw-r--r--indra/newview/skins/default/html/es/loading/loading.html10
-rw-r--r--indra/newview/skins/default/html/fr/loading/loading.html10
-rw-r--r--indra/newview/skins/default/html/hu/loading/loading.html10
-rw-r--r--indra/newview/skins/default/html/it/loading/loading.html10
-rw-r--r--indra/newview/skins/default/html/ja/loading-error/index.html2
-rw-r--r--indra/newview/skins/default/html/ja/loading/loading.html10
-rw-r--r--indra/newview/skins/default/html/nl/loading/loading.html10
-rw-r--r--indra/newview/skins/default/html/pl/loading/loading.html10
-rw-r--r--indra/newview/skins/default/html/pt/loading/loading.html10
-rw-r--r--indra/newview/skins/default/html/ru/loading/loading.html10
-rw-r--r--indra/newview/skins/default/html/tr/loading/loading.html10
-rw-r--r--indra/newview/skins/default/html/uk/loading/loading.html10
-rw-r--r--indra/newview/skins/default/html/zh/loading-error/index.html4
-rw-r--r--indra/newview/skins/default/html/zh/loading/loading.html10
-rw-r--r--indra/newview/skins/default/textures/Blank.pngbin0 -> 110 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Avatar_Off.pngbin0 -> 527 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_FreeCam_Off.pngbin0 -> 365 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Orbit_Off.pngbin0 -> 532 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Pan_Off.pngbin0 -> 328 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Pan_Over.pngbin0 -> 275 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Preset_Back_Off.pngbin0 -> 700 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Preset_Back_On.pngbin0 -> 754 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Preset_Eye_Off.pngbin0 -> 914 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Preset_Front_Off.pngbin0 -> 959 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Preset_Front_On.pngbin0 -> 1087 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Preset_Side_Off.pngbin0 -> 945 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Preset_Side_On.pngbin0 -> 1049 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Rotate_In.pngbin0 -> 407 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Rotate_Out.pngbin0 -> 3271 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Tracking_In.pngbin0 -> 328 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Cam_Tracking_Out.pngbin0 -> 787 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/CameraView_Press.pngbin0 -> 489 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/DownArrow.pngbin0 -> 139 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Move_Fly_Off.pngbin0 -> 393 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Move_Run_Off.pngbin0 -> 496 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Move_Walk_Off.pngbin0 -> 515 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_Backward_Off.pngbin0 -> 354 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_Backward_On.pngbin0 -> 353 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_Down_Off.pngbin0 -> 419 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_Down_On.pngbin0 -> 417 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_Forward_Off.pngbin0 -> 322 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_Forward_On.pngbin0 -> 321 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_TurnLeft_Off.pngbin0 -> 431 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_TurnLeft_On.pngbin0 -> 430 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_TurnRight_Off.pngbin0 -> 432 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_TurnRight_On.pngbin0 -> 427 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_Up_Off.pngbin0 -> 371 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Movement_Up_On.pngbin0 -> 370 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Notices_Unread.pngbin0 -> 3693 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Snapshot_Off.pngbin0 -> 3204 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Unread_Chiclet.pngbin0 -> 328 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Unread_IM.pngbin0 -> 458 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1.pngbin0 -> 557 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2.pngbin0 -> 663 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl3.pngbin0 -> 607 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/VoicePTT_Off.pngbin0 -> 461 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/VoicePTT_On.pngbin0 -> 451 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/WellButton_Lit.pngbin0 -> 309 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/WellButton_Lit_Selected.pngbin0 -> 309 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Cone.pngbin0 -> 481 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Cube.pngbin0 -> 370 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Cylinder.pngbin0 -> 373 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Grass.pngbin0 -> 456 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Hemi_Cone.pngbin0 -> 441 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Hemi_Cylinder.pngbin0 -> 378 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Hemi_Sphere.pngbin0 -> 545 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Prism.pngbin0 -> 395 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Pyramid.pngbin0 -> 452 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Ring.pngbin0 -> 615 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Sphere.pngbin0 -> 737 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Tetrahedron.pngbin0 -> 411 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Torus.pngbin0 -> 803 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Tree.pngbin0 -> 737 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Object_Tube.pngbin0 -> 460 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Tool_Create.pngbin0 -> 705 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Tool_Dozer.pngbin0 -> 492 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Tool_Face.pngbin0 -> 304 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Tool_Grab.pngbin0 -> 417 bytes
-rw-r--r--indra/newview/skins/default/textures/build/Tool_Zoom.pngbin0 -> 533 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Accordion_ArrowClosed_Off.pngbin0 -> 175 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Accordion_ArrowClosed_Over.pngbin0 -> 170 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Accordion_ArrowClosed_Press.pngbin0 -> 175 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Accordion_ArrowOpened_Off.pngbin0 -> 169 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Accordion_ArrowOpened_Over.pngbin0 -> 162 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Accordion_ArrowOpened_Press.pngbin0 -> 169 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Accordion_Off.pngbin0 -> 239 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Accordion_Over.pngbin0 -> 206 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Accordion_Press.pngbin0 -> 200 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Accordion_Selected.pngbin0 -> 228 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Container.pngbin0 -> 673 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/TabTop_Left_Off.pngbin0 -> 339 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/TabTop_Left_Over.pngbin0 -> 337 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/TabTop_Left_Selected.pngbin0 -> 458 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/TabTop_Middle_Off.pngbin0 -> 258 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/TabTop_Middle_Over.pngbin0 -> 285 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/TabTop_Middle_Selected.pngbin0 -> 367 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/TabTop_Right_Off.pngbin0 -> 357 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/TabTop_Right_Over.pngbin0 -> 362 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/TabTop_Right_Selected.pngbin0 -> 474 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Left_Off.pngbin0 -> 306 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Left_Over.pngbin0 -> 310 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Left_Selected.pngbin0 -> 380 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Middle_Off.pngbin0 -> 224 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Middle_Over.pngbin0 -> 228 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Middle_Selected.pngbin0 -> 296 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Right_Off.pngbin0 -> 302 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Right_Over.pngbin0 -> 297 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Toolbar_Right_Selected.pngbin0 -> 377 bytes
-rw-r--r--indra/newview/skins/default/textures/default_profile_picture.j2cbin6128 -> 1512 bytes
-rw-r--r--indra/newview/skins/default/textures/icon_event_adult.tgabin648 -> 1006 bytes
-rw-r--r--indra/newview/skins/default/textures/icon_top_pick.tgabin858 -> 1068 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/AddItem_Disabled.pngbin0 -> 186 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/AddItem_Off.pngbin0 -> 184 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/AddItem_Over.pngbin0 -> 165 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/AddItem_Press.pngbin0 -> 181 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/AudioMute_Off.pngbin0 -> 600 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/AudioMute_Over.pngbin0 -> 587 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Audio_Off.pngbin0 -> 467 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Audio_Press.pngbin0 -> 477 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/BackArrow_Off.pngbin0 -> 227 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/BackArrow_Over.pngbin0 -> 214 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/DragHandle.pngbin0 -> 163 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/ExternalBrowser_Off.pngbin0 -> 279 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/ForSale_Badge.pngbin0 -> 5727 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/ForwardArrow_Off.pngbin0 -> 220 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/ForwardArrow_Press.pngbin0 -> 220 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Generic_Group.pngbin0 -> 3354 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Generic_Group_Large.pngbin0 -> 2282 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Generic_Object.pngbin0 -> 366 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Generic_Object_Small.pngbin0 -> 410 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Generic_Person.pngbin0 -> 3280 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Generic_Person_Large.pngbin0 -> 1630 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Icon_For_Sale.pngbin0 -> 572 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Info.pngbin0 -> 351 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Info_Over.pngbin0 -> 376 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Info_Small.pngbin0 -> 371 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Alpha.pngbin0 -> 319 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Animation.pngbin0 -> 496 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_BodyShape.pngbin0 -> 641 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_CallingCard.pngbin0 -> 295 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Clothing.pngbin0 -> 253 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Eye.pngbin0 -> 491 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_FolderClosed.pngbin0 -> 219 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_FolderOpen.pngbin0 -> 361 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Gesture.pngbin0 -> 408 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Gloves.pngbin0 -> 366 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Hair.pngbin0 -> 377 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Jacket.pngbin0 -> 591 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Landmark.pngbin0 -> 582 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_LinkFolder.pngbin0 -> 296 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_LinkItem.pngbin0 -> 296 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_LookFolderClosed.pngbin0 -> 391 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_LookFolderOpen.pngbin0 -> 538 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Notecard.pngbin0 -> 222 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Object.pngbin0 -> 333 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Pants.pngbin0 -> 377 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Script.pngbin0 -> 469 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Shirt.pngbin0 -> 402 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Shoe.pngbin0 -> 276 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Skin.pngbin0 -> 393 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Skirt.pngbin0 -> 494 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Snapshot.pngbin0 -> 535 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Socks.pngbin0 -> 358 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Sound.pngbin0 -> 404 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Tattoo.pngbin0 -> 416 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Texture.pngbin0 -> 157 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Underpants.pngbin0 -> 418 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Undershirt.pngbin0 -> 208 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Lock.pngbin0 -> 343 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Microphone_On.pngbin0 -> 340 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/MinusItem_Disabled.pngbin0 -> 173 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/MinusItem_Off.pngbin0 -> 178 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/MinusItem_Press.pngbin0 -> 172 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OptionsMenu_Disabled.pngbin0 -> 343 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OptionsMenu_Off.pngbin0 -> 336 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OptionsMenu_Over.pngbin0 -> 277 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OptionsMenu_Press.pngbin0 -> 318 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_BuildNo_Dark.pngbin0 -> 516 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_BuildNo_Light.pngbin0 -> 505 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_Build_Dark.pngbin0 -> 343 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_DamageNo_Dark.pngbin0 -> 457 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_Damage_Dark.pngbin0 -> 325 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_Damage_Light_Alt.pngbin0 -> 285 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_Exp_Color.pngbin0 -> 272 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_FlyNo_Dark.pngbin0 -> 424 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_FlyNo_Light.pngbin0 -> 429 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_Fly_Dark.pngbin0 -> 271 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_ForSale_Light.pngbin0 -> 561 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_Health_Dark.pngbin0 -> 285 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_M_Dark.pngbin0 -> 333 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_M_Light.pngbin0 -> 322 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_NoScripts_Light.pngbin0 -> 620 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_PG_Dark.pngbin0 -> 407 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_PG_Light.pngbin0 -> 387 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_PushNo_Dark.pngbin0 -> 523 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_PushNo_Light.pngbin0 -> 516 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_Push_Dark.pngbin0 -> 430 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_R_Dark.pngbin0 -> 319 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_R_Light.pngbin0 -> 309 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_ScriptsNo_Dark.pngbin0 -> 620 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_Scripts_Dark.pngbin0 -> 471 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_VoiceNo_Dark.pngbin0 -> 492 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_VoiceNo_Light.pngbin0 -> 516 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_Voice_Dark.pngbin0 -> 380 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_Voice_Light.pngbin0 -> 405 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Pause_Off.pngbin0 -> 163 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Pause_Over.pngbin0 -> 160 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Pause_Press.pngbin0 -> 156 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Play_Off.pngbin0 -> 293 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Play_Over.pngbin0 -> 258 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Play_Press.pngbin0 -> 287 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Progress_1.pngbin0 -> 464 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Progress_10.pngbin0 -> 461 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Progress_11.pngbin0 -> 471 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Progress_12.pngbin0 -> 457 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Progress_2.pngbin0 -> 461 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Progress_3.pngbin0 -> 487 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Progress_4.pngbin0 -> 466 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Progress_5.pngbin0 -> 477 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Progress_6.pngbin0 -> 460 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Progress_7.pngbin0 -> 483 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Progress_8.pngbin0 -> 467 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Progress_9.pngbin0 -> 483 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Refresh_Off.pngbin0 -> 483 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/SL_Logo.pngbin0 -> 973 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/SkipBackward_Off.pngbin0 -> 293 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/SkipForward_Off.pngbin0 -> 304 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/StopReload_Off.pngbin0 -> 533 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/StopReload_Over.pngbin0 -> 529 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Stop_Off.pngbin0 -> 148 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/TrashItem_Disabled.pngbin0 -> 196 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/TrashItem_Off.pngbin0 -> 201 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/TrashItem_Over.pngbin0 -> 201 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/TrashItem_Press.pngbin0 -> 201 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/UnZoom_Off.pngbin0 -> 423 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/VoicePTT_Lvl1.pngbin0 -> 557 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/VoicePTT_Lvl2.pngbin0 -> 663 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/VoicePTT_Lvl3.pngbin0 -> 607 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/VoicePTT_Off.pngbin0 -> 461 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/VoicePTT_On.pngbin0 -> 451 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/YouAreHere_Badge.pngbin0 -> 6143 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Zoom_Off.pngbin0 -> 435 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/avaline_default_icon.jpgbin0 -> 3951 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/parcel_color_EVRY.pngbin0 -> 393 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/parcel_color_EXP.pngbin0 -> 272 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/parcel_color_M.pngbin0 -> 306 bytes
-rw-r--r--indra/newview/skins/default/textures/image_edit_icon.tgabin0 -> 3116 bytes
-rw-r--r--indra/newview/skins/default/textures/inv_folder_inbox.tgabin0 -> 2085 bytes
-rw-r--r--indra/newview/skins/default/textures/jump_left_in.tgabin0 -> 812 bytes
-rw-r--r--indra/newview/skins/default/textures/jump_left_out.tgabin0 -> 812 bytes
-rw-r--r--indra/newview/skins/default/textures/jump_right_in.tgabin0 -> 812 bytes
-rw-r--r--indra/newview/skins/default/textures/jump_right_out.tgabin0 -> 812 bytes
-rw-r--r--indra/newview/skins/default/textures/map_avatar_16.tgabin1068 -> 1068 bytes
-rw-r--r--indra/newview/skins/default/textures/map_avatar_32.tgabin0 -> 2894 bytes
-rw-r--r--indra/newview/skins/default/textures/map_avatar_8.tgabin300 -> 300 bytes
-rw-r--r--indra/newview/skins/default/textures/map_avatar_above_32.tgabin0 -> 2909 bytes
-rw-r--r--indra/newview/skins/default/textures/map_avatar_below_32.tgabin0 -> 3037 bytes
-rw-r--r--indra/newview/skins/default/textures/map_avatar_you_32.tgabin0 -> 3395 bytes
-rw-r--r--indra/newview/skins/default/textures/map_event.tgabin1068 -> 1068 bytes
-rw-r--r--indra/newview/skins/default/textures/map_event_adult.tgabin648 -> 1006 bytes
-rw-r--r--indra/newview/skins/default/textures/map_event_mature.tgabin1068 -> 1068 bytes
-rw-r--r--indra/newview/skins/default/textures/map_home.tgabin1068 -> 1068 bytes
-rw-r--r--indra/newview/skins/default/textures/map_infohub.tgabin1068 -> 1068 bytes
-rw-r--r--indra/newview/skins/default/textures/map_telehub.tgabin1068 -> 1068 bytes
-rw-r--r--indra/newview/skins/default/textures/menu_separator.pngbin0 -> 2831 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Arrow_Left_Off.pngbin0 -> 382 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Arrow_Left_Over.pngbin0 -> 381 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Arrow_Right_Off.pngbin0 -> 380 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Arrow_Right_Over.pngbin0 -> 379 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/BuyArrow_Over.pngbin0 -> 2956 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/BuyArrow_Press.pngbin0 -> 2949 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Favorite_Link_Over.pngbin0 -> 191 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Favorite_Star_Active.pngbin0 -> 704 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Favorite_Star_Off.pngbin0 -> 444 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Favorite_Star_Over.pngbin0 -> 445 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Favorite_Star_Press.pngbin0 -> 616 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/FileMenu_Divider.pngbin0 -> 116 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Flag.pngbin0 -> 338 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Help_Over.pngbin0 -> 348 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Help_Press.pngbin0 -> 384 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Home_Off.pngbin0 -> 379 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Home_Over.pngbin0 -> 330 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Info_Off.pngbin0 -> 608 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Info_Over.pngbin0 -> 622 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Info_Press.pngbin0 -> 605 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Lock.pngbin0 -> 302 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/NavBar_BG.pngbin0 -> 195 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Row_Selection.pngbin0 -> 231 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/Search.pngbin0 -> 3182 bytes
-rw-r--r--indra/newview/skins/default/textures/places_rating_adult.tgabin0 -> 648 bytes
-rw-r--r--indra/newview/skins/default/textures/places_rating_mature.tgabin0 -> 1068 bytes
-rw-r--r--indra/newview/skins/default/textures/places_rating_pg.tgabin0 -> 1068 bytes
-rw-r--r--indra/newview/skins/default/textures/quick_tips/avatar_free_mode.pngbin0 -> 1447 bytes
-rw-r--r--indra/newview/skins/default/textures/quick_tips/camera_free_mode.pngbin0 -> 2267 bytes
-rw-r--r--indra/newview/skins/default/textures/quick_tips/camera_orbit_mode.pngbin0 -> 2381 bytes
-rw-r--r--indra/newview/skins/default/textures/quick_tips/camera_pan_mode.pngbin0 -> 2418 bytes
-rw-r--r--indra/newview/skins/default/textures/quick_tips/camera_preset_front_view.pngbin0 -> 2365 bytes
-rw-r--r--indra/newview/skins/default/textures/quick_tips/camera_preset_group_view.pngbin0 -> 2595 bytes
-rw-r--r--indra/newview/skins/default/textures/quick_tips/camera_preset_rear_view.pngbin0 -> 2221 bytes
-rw-r--r--indra/newview/skins/default/textures/quick_tips/move_fly_first.pngbin0 -> 1528 bytes
-rw-r--r--indra/newview/skins/default/textures/quick_tips/move_fly_second.pngbin0 -> 2128 bytes
-rw-r--r--indra/newview/skins/default/textures/quick_tips/move_run_first.pngbin0 -> 1554 bytes
-rw-r--r--indra/newview/skins/default/textures/quick_tips/move_run_second.pngbin0 -> 2534 bytes
-rw-r--r--indra/newview/skins/default/textures/quick_tips/move_walk_first.pngbin0 -> 2106 bytes
-rw-r--r--indra/newview/skins/default/textures/quick_tips/move_walk_second.pngbin0 -> 3108 bytes
-rw-r--r--indra/newview/skins/default/textures/show_btn.tgabin0 -> 3884 bytes
-rw-r--r--indra/newview/skins/default/textures/show_btn_selected.tgabin0 -> 3884 bytes
-rw-r--r--indra/newview/skins/default/textures/taskpanel/Activate_Checkmark.pngbin0 -> 435 bytes
-rw-r--r--indra/newview/skins/default/textures/taskpanel/TabIcon_Appearance_Off.pngbin0 -> 273 bytes
-rw-r--r--indra/newview/skins/default/textures/taskpanel/TabIcon_Appearance_Selected.pngbin0 -> 349 bytes
-rw-r--r--indra/newview/skins/default/textures/taskpanel/TabIcon_Close_Off.pngbin0 -> 305 bytes
-rw-r--r--indra/newview/skins/default/textures/taskpanel/TabIcon_Home_Off.pngbin0 -> 228 bytes
-rw-r--r--indra/newview/skins/default/textures/taskpanel/TabIcon_Home_Selected.pngbin0 -> 291 bytes
-rw-r--r--indra/newview/skins/default/textures/taskpanel/TabIcon_Me_Off.pngbin0 -> 297 bytes
-rw-r--r--indra/newview/skins/default/textures/taskpanel/TabIcon_Me_Selected.pngbin0 -> 359 bytes
-rw-r--r--indra/newview/skins/default/textures/taskpanel/TabIcon_Open_Off.pngbin0 -> 294 bytes
-rw-r--r--indra/newview/skins/default/textures/taskpanel/TabIcon_People_Off.pngbin0 -> 367 bytes
-rw-r--r--indra/newview/skins/default/textures/taskpanel/TabIcon_People_Selected.pngbin0 -> 536 bytes
-rw-r--r--indra/newview/skins/default/textures/taskpanel/TabIcon_Places_Large.pngbin0 -> 709 bytes
-rw-r--r--indra/newview/skins/default/textures/taskpanel/TabIcon_Places_Off.pngbin0 -> 405 bytes
-rw-r--r--indra/newview/skins/default/textures/taskpanel/TabIcon_Places_Selected.pngbin0 -> 653 bytes
-rw-r--r--indra/newview/skins/default/textures/taskpanel/TabIcon_Things_Off.pngbin0 -> 223 bytes
-rw-r--r--indra/newview/skins/default/textures/taskpanel/TabIcon_Things_Selected.pngbin0 -> 297 bytes
-rw-r--r--indra/newview/skins/default/textures/taskpanel/TaskPanel_Tab_Off.pngbin0 -> 272 bytes
-rw-r--r--indra/newview/skins/default/textures/taskpanel/TaskPanel_Tab_Selected.pngbin0 -> 325 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml1123
-rw-r--r--indra/newview/skins/default/textures/transparent.j2cbin0 -> 172 bytes
-rw-r--r--indra/newview/skins/default/textures/voice_meter_dot.j2cbin0 -> 499 bytes
-rw-r--r--indra/newview/skins/default/textures/voice_meter_rings.j2cbin0 -> 2518 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Arrow_Down.pngbin0 -> 3066 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Arrow_Small_Left.pngbin0 -> 223 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Arrow_Small_Right.pngbin0 -> 217 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Arrow_Small_Up.pngbin0 -> 382 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Arrow_Up.pngbin0 -> 363 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Checkbox_Disabled.pngbin0 -> 306 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Checkbox_Off.pngbin0 -> 322 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Checkbox_On.pngbin0 -> 577 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Checkbox_On_Disabled.pngbin0 -> 558 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Checkbox_On_Over.pngbin0 -> 547 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Checkbox_On_Press.pngbin0 -> 612 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Checkbox_Over.pngbin0 -> 318 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Checkbox_Press.pngbin0 -> 373 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ComboButton_Disabled.pngbin0 -> 450 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ComboButton_Off.pngbin0 -> 470 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ComboButton_On.pngbin0 -> 486 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ComboButton_Selected.pngbin0 -> 539 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ComboButton_UpOff.pngbin0 -> 466 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ComboButton_UpSelected.pngbin0 -> 536 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ComboButton_Up_On_Selected.pngbin0 -> 482 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/DisclosureArrow_Closed_Over.pngbin0 -> 164 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/DisclosureArrow_Opened_Off.pngbin0 -> 173 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/DisclosureArrow_Opened_Over.pngbin0 -> 165 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/DropDown_Disabled.pngbin0 -> 600 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/DropDown_Off.pngbin0 -> 603 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/DropDown_On.pngbin0 -> 638 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/DropDown_Press.pngbin0 -> 679 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/DropTarget.pngbin0 -> 479 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Linden_Dollar_Alert.pngbin0 -> 66186 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Linden_Dollar_Background.pngbin0 -> 56298 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ListItem_Over.pngbin0 -> 244 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ListItem_Select.pngbin0 -> 251 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ProgressBar.pngbin0 -> 220 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ProgressTrack.pngbin0 -> 192 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_Disabled.pngbin0 -> 461 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_Off.pngbin0 -> 464 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_On.pngbin0 -> 490 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_On_Over.pngbin0 -> 498 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_On_Selected.pngbin0 -> 572 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_Over.pngbin0 -> 457 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_Press.pngbin0 -> 520 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_Selected.pngbin0 -> 520 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_Selected_Disabled.pngbin0 -> 490 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_Selected_Over.pngbin0 -> 498 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/PushButton_Selected_Press.pngbin0 -> 572 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/RadioButton_Disabled.pngbin0 -> 541 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/RadioButton_Off.pngbin0 -> 563 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/RadioButton_On.pngbin0 -> 627 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/RadioButton_On_Disabled.pngbin0 -> 605 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/RadioButton_On_Over.pngbin0 -> 635 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/RadioButton_On_Press.pngbin0 -> 641 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/RadioButton_Over.pngbin0 -> 575 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/RadioButton_Press.pngbin0 -> 589 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ScrollArrow_Down.pngbin0 -> 239 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ScrollArrow_Down_Over.pngbin0 -> 257 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ScrollArrow_Left.pngbin0 -> 271 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ScrollArrow_Left_Opaque.pngbin0 -> 311 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ScrollArrow_Left_Over.pngbin0 -> 295 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ScrollArrow_Left_Over_Opaque.pngbin0 -> 330 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ScrollArrow_Right.pngbin0 -> 260 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ScrollArrow_Right_Opaque.pngbin0 -> 311 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ScrollArrow_Right_Over.pngbin0 -> 283 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ScrollArrow_Right_Over_Opaque.pngbin0 -> 324 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ScrollArrow_Up.pngbin0 -> 262 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ScrollArrow_Up_Over.pngbin0 -> 276 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ScrollThumb_Horiz.pngbin0 -> 364 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ScrollThumb_Horiz_Over.pngbin0 -> 311 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ScrollThumb_Vert.pngbin0 -> 323 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ScrollThumb_Vert_Over.pngbin0 -> 311 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ScrollTrack_Horiz.pngbin0 -> 153 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/ScrollTrack_Vert.pngbin0 -> 150 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Disabled.pngbin0 -> 378 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Off.pngbin0 -> 386 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_On.pngbin0 -> 404 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_On_Disabled.pngbin0 -> 404 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_On_Over.pngbin0 -> 394 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_On_Selected.pngbin0 -> 495 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Over.pngbin0 -> 384 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Press.pngbin0 -> 455 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected.pngbin0 -> 455 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Disabled.pngbin0 -> 404 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Over.pngbin0 -> 394 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Press.pngbin0 -> 495 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Disabled.pngbin0 -> 277 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_On.pngbin0 -> 308 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_On_Over.pngbin0 -> 300 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_On_Press.pngbin0 -> 393 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Over.pngbin0 -> 286 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected.pngbin0 -> 359 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Disabled.pngbin0 -> 308 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Over.pngbin0 -> 300 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Press.pngbin0 -> 393 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Disabled.pngbin0 -> 380 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Off.pngbin0 -> 391 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_On.pngbin0 -> 420 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_On_Over.pngbin0 -> 416 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_On_Selected.pngbin0 -> 502 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Over.pngbin0 -> 398 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Press.pngbin0 -> 459 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected.pngbin0 -> 459 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected_Disabled.pngbin0 -> 420 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected_Over.pngbin0 -> 416 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected_Press.pngbin0 -> 502 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SliderThumb_Disabled.pngbin0 -> 475 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SliderThumb_Off.pngbin0 -> 475 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SliderThumb_Over.pngbin0 -> 482 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SliderThumb_Press.pngbin0 -> 470 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SliderTrack_Horiz.pngbin0 -> 225 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/SliderTrack_Vert.pngbin0 -> 232 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Stepper_Down_Off.pngbin0 -> 300 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Stepper_Down_Over.pngbin0 -> 310 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Stepper_Down_Press.pngbin0 -> 343 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Stepper_Up_Off.pngbin0 -> 315 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Stepper_Up_Over.pngbin0 -> 314 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Stepper_Up_Press.pngbin0 -> 384 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/TextField_Active.pngbin0 -> 225 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/TextField_Disabled.pngbin0 -> 225 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/TextField_Off.pngbin0 -> 224 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/TextField_Search_Active.pngbin0 -> 923 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/TextField_Search_Disabled.pngbin0 -> 943 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/TextField_Search_Off.pngbin0 -> 958 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Tooltip.pngbin0 -> 2910 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/jump_left_in.pngbin0 -> 342 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/jump_left_out.pngbin0 -> 321 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/jump_right_in.pngbin0 -> 320 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/jump_right_out.pngbin0 -> 315 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Flyout.pngbin0 -> 820 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Flyout_Pointer.pngbin0 -> 236 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Close_Foreground.pngbin0 -> 2871 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Close_Press.pngbin0 -> 263 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Close_Toast.pngbin0 -> 460 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Dock_Foreground.pngbin0 -> 263 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Dock_Press.pngbin0 -> 263 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Gear_Background.pngbin0 -> 373 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Gear_Foreground.pngbin0 -> 373 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Gear_Over.pngbin0 -> 279 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Gear_Press.pngbin0 -> 396 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Help_Foreground.pngbin0 -> 3084 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Help_Press.pngbin0 -> 3062 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Minimize_Foreground.pngbin0 -> 2839 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Minimize_Press.pngbin0 -> 2839 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Restore_Foreground.pngbin0 -> 2955 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Restore_Press.pngbin0 -> 2971 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Undock_Foreground.pngbin0 -> 268 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Icon_Undock_Press.pngbin0 -> 267 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Inspector_Background.pngbin0 -> 348 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Inspector_Hover.pngbin0 -> 414 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Inspector_I.pngbin0 -> 548 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Resize_Corner.pngbin0 -> 137 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Toast_Background.pngbin0 -> 349 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Toast_CloseBtn.pngbin0 -> 471 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Toast_Over.pngbin0 -> 400 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Window_Background.pngbin0 -> 509 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Window_Foreground.pngbin0 -> 508 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Window_NoTitle_Background.pngbin0 -> 289 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Window_NoTitle_Foreground.pngbin0 -> 290 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/startup_logo.pngbin0 -> 2457 bytes
-rw-r--r--indra/newview/skins/default/textures/world/BeaconArrow.pngbin0 -> 1965 bytes
-rw-r--r--indra/newview/skins/default/textures/world/NoEntryLines.pngbin0 -> 3523 bytes
-rw-r--r--indra/newview/skins/default/textures/world/NoEntryPassLines.pngbin0 -> 1267 bytes
-rw-r--r--indra/newview/skins/default/xui/da/floater_about.xml71
-rw-r--r--indra/newview/skins/default/xui/da/floater_about_land.xml581
-rw-r--r--indra/newview/skins/default/xui/da/floater_animation_preview.xml161
-rw-r--r--indra/newview/skins/default/xui/da/floater_auction.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_avatar_picker.xml49
-rw-r--r--indra/newview/skins/default/xui/da/floater_avatar_textures.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_beacons.xml4
-rw-r--r--indra/newview/skins/default/xui/da/floater_build_options.xml6
-rw-r--r--indra/newview/skins/default/xui/da/floater_bulk_perms.xml44
-rw-r--r--indra/newview/skins/default/xui/da/floater_bumps.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_buy_contents.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_buy_currency.xml6
-rw-r--r--indra/newview/skins/default/xui/da/floater_buy_land.xml74
-rw-r--r--indra/newview/skins/default/xui/da/floater_buy_object.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_camera.xml18
-rw-r--r--indra/newview/skins/default/xui/da/floater_choose_group.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_color_picker.xml4
-rw-r--r--indra/newview/skins/default/xui/da/floater_customize.xml512
-rw-r--r--indra/newview/skins/default/xui/da/floater_day_cycle_options.xml50
-rw-r--r--indra/newview/skins/default/xui/da/floater_device_settings.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_env_settings.xml12
-rw-r--r--indra/newview/skins/default/xui/da/floater_font_test.xml6
-rw-r--r--indra/newview/skins/default/xui/da/floater_gesture.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_hardware_settings.xml32
-rw-r--r--indra/newview/skins/default/xui/da/floater_hud.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_image_preview.xml40
-rw-r--r--indra/newview/skins/default/xui/da/floater_inspect.xml18
-rw-r--r--indra/newview/skins/default/xui/da/floater_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_inventory_item_properties.xml10
-rw-r--r--indra/newview/skins/default/xui/da/floater_inventory_view_finder.xml4
-rw-r--r--indra/newview/skins/default/xui/da/floater_joystick.xml70
-rw-r--r--indra/newview/skins/default/xui/da/floater_lagmeter.xml18
-rw-r--r--indra/newview/skins/default/xui/da/floater_land_holdings.xml21
-rw-r--r--indra/newview/skins/default/xui/da/floater_live_lsleditor.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_lsl_guide.xml4
-rw-r--r--indra/newview/skins/default/xui/da/floater_map.xml51
-rw-r--r--indra/newview/skins/default/xui/da/floater_media_browser.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_mem_leaking.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_moveview.xml4
-rw-r--r--indra/newview/skins/default/xui/da/floater_mute_object.xml14
-rw-r--r--indra/newview/skins/default/xui/da/floater_my_friends.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_openobject.xml4
-rw-r--r--indra/newview/skins/default/xui/da/floater_pay.xml8
-rw-r--r--indra/newview/skins/default/xui/da/floater_pay_object.xml14
-rw-r--r--indra/newview/skins/default/xui/da/floater_perm_prefs.xml16
-rw-r--r--indra/newview/skins/default/xui/da/floater_postcard.xml4
-rw-r--r--indra/newview/skins/default/xui/da/floater_preferences.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_preview_animation.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_preview_classified.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_preview_event.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_preview_gesture.xml44
-rw-r--r--indra/newview/skins/default/xui/da/floater_preview_notecard.xml13
-rw-r--r--indra/newview/skins/default/xui/da/floater_preview_sound.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_preview_texture.xml4
-rw-r--r--indra/newview/skins/default/xui/da/floater_region_info.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_report_abuse.xml195
-rw-r--r--indra/newview/skins/default/xui/da/floater_script_debug.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_script_preview.xml4
-rw-r--r--indra/newview/skins/default/xui/da/floater_script_queue.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_script_search.xml6
-rw-r--r--indra/newview/skins/default/xui/da/floater_select_key.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_sell_land.xml26
-rw-r--r--indra/newview/skins/default/xui/da/floater_settings_debug.xml10
-rw-r--r--indra/newview/skins/default/xui/da/floater_snapshot.xml152
-rw-r--r--indra/newview/skins/default/xui/da/floater_sound_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_statistics.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_stats.xml71
-rw-r--r--indra/newview/skins/default/xui/da/floater_telehub.xml10
-rw-r--r--indra/newview/skins/default/xui/da/floater_texture_ctrl.xml6
-rw-r--r--indra/newview/skins/default/xui/da/floater_tools.xml623
-rw-r--r--indra/newview/skins/default/xui/da/floater_top_objects.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_tos.xml3
-rw-r--r--indra/newview/skins/default/xui/da/floater_water.xml42
-rw-r--r--indra/newview/skins/default/xui/da/floater_wearable_save_as.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_windlight_options.xml98
-rw-r--r--indra/newview/skins/default/xui/da/floater_world_map.xml90
-rw-r--r--indra/newview/skins/default/xui/da/language_settings.xml55
-rw-r--r--indra/newview/skins/default/xui/da/menu_inventory.xml139
-rw-r--r--indra/newview/skins/default/xui/da/menu_inventory_add.xml32
-rw-r--r--indra/newview/skins/default/xui/da/menu_login.xml4
-rw-r--r--indra/newview/skins/default/xui/da/menu_mini_map.xml8
-rw-r--r--indra/newview/skins/default/xui/da/menu_picks.xml8
-rw-r--r--indra/newview/skins/default/xui/da/menu_places_gear_landmark.xml18
-rw-r--r--indra/newview/skins/default/xui/da/menu_viewer.xml364
-rw-r--r--indra/newview/skins/default/xui/da/notifications.xml2541
-rw-r--r--indra/newview/skins/default/xui/da/panel_audio_device.xml10
-rw-r--r--indra/newview/skins/default/xui/da/panel_block_list_sidetray.xml10
-rw-r--r--indra/newview/skins/default/xui/da/panel_edit_profile.xml46
-rw-r--r--indra/newview/skins/default/xui/da/panel_group_general.xml53
-rw-r--r--indra/newview/skins/default/xui/da/panel_group_invite.xml9
-rw-r--r--indra/newview/skins/default/xui/da/panel_group_land_money.xml49
-rw-r--r--indra/newview/skins/default/xui/da/panel_group_notices.xml8
-rw-r--r--indra/newview/skins/default/xui/da/panel_group_roles.xml154
-rw-r--r--indra/newview/skins/default/xui/da/panel_groups.xml4
-rw-r--r--indra/newview/skins/default/xui/da/panel_login.xml73
-rw-r--r--indra/newview/skins/default/xui/da/panel_main_inventory.xml64
-rw-r--r--indra/newview/skins/default/xui/da/panel_preferences_advanced.xml48
-rw-r--r--indra/newview/skins/default/xui/da/panel_preferences_alerts.xml14
-rw-r--r--indra/newview/skins/default/xui/da/panel_preferences_chat.xml95
-rw-r--r--indra/newview/skins/default/xui/da/panel_preferences_general.xml145
-rw-r--r--indra/newview/skins/default/xui/da/panel_preferences_graphics1.xml134
-rw-r--r--indra/newview/skins/default/xui/da/panel_preferences_privacy.xml33
-rw-r--r--indra/newview/skins/default/xui/da/panel_preferences_setup.xml30
-rw-r--r--indra/newview/skins/default/xui/da/panel_preferences_sound.xml38
-rw-r--r--indra/newview/skins/default/xui/da/panel_region_covenant.xml71
-rw-r--r--indra/newview/skins/default/xui/da/panel_region_estate.xml4
-rw-r--r--indra/newview/skins/default/xui/da/panel_region_general.xml67
-rw-r--r--indra/newview/skins/default/xui/da/panel_region_terrain.xml4
-rw-r--r--indra/newview/skins/default/xui/da/panel_scrolling_param.xml4
-rw-r--r--indra/newview/skins/default/xui/da/panel_status_bar.xml12
-rw-r--r--indra/newview/skins/default/xui/da/panel_world_map.xml57
-rw-r--r--indra/newview/skins/default/xui/da/strings.xml2899
-rw-r--r--indra/newview/skins/default/xui/da/teleport_strings.xml29
-rw-r--r--indra/newview/skins/default/xui/de/floater_about.xml71
-rw-r--r--indra/newview/skins/default/xui/de/floater_about_land.xml376
-rw-r--r--indra/newview/skins/default/xui/de/floater_activeim.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_animation_preview.xml285
-rw-r--r--indra/newview/skins/default/xui/de/floater_auction.xml16
-rw-r--r--indra/newview/skins/default/xui/de/floater_avatar_picker.xml60
-rw-r--r--indra/newview/skins/default/xui/de/floater_avatar_textures.xml41
-rw-r--r--indra/newview/skins/default/xui/de/floater_beacons.xml24
-rw-r--r--indra/newview/skins/default/xui/de/floater_build_options.xml17
-rw-r--r--indra/newview/skins/default/xui/de/floater_bulk_perms.xml64
-rw-r--r--indra/newview/skins/default/xui/de/floater_bumps.xml31
-rw-r--r--indra/newview/skins/default/xui/de/floater_buy_contents.xml10
-rw-r--r--indra/newview/skins/default/xui/de/floater_buy_currency.xml80
-rw-r--r--indra/newview/skins/default/xui/de/floater_buy_land.xml41
-rw-r--r--indra/newview/skins/default/xui/de/floater_buy_object.xml10
-rw-r--r--indra/newview/skins/default/xui/de/floater_camera.xml35
-rw-r--r--indra/newview/skins/default/xui/de/floater_choose_group.xml8
-rw-r--r--indra/newview/skins/default/xui/de/floater_color_picker.xml15
-rw-r--r--indra/newview/skins/default/xui/de/floater_customize.xml270
-rw-r--r--indra/newview/skins/default/xui/de/floater_day_cycle_options.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_device_settings.xml4
-rw-r--r--indra/newview/skins/default/xui/de/floater_env_settings.xml16
-rw-r--r--indra/newview/skins/default/xui/de/floater_first_time_tip.xml4
-rw-r--r--indra/newview/skins/default/xui/de/floater_font_test.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_gesture.xml38
-rw-r--r--indra/newview/skins/default/xui/de/floater_god_tools.xml146
-rw-r--r--indra/newview/skins/default/xui/de/floater_hardware_settings.xml40
-rw-r--r--indra/newview/skins/default/xui/de/floater_help_browser.xml14
-rw-r--r--indra/newview/skins/default/xui/de/floater_hud.xml4
-rw-r--r--indra/newview/skins/default/xui/de/floater_im.xml4
-rw-r--r--indra/newview/skins/default/xui/de/floater_im_container.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_im_session.xml9
-rw-r--r--indra/newview/skins/default/xui/de/floater_image_preview.xml48
-rw-r--r--indra/newview/skins/default/xui/de/floater_incoming_call.xml21
-rw-r--r--indra/newview/skins/default/xui/de/floater_inspect.xml24
-rw-r--r--indra/newview/skins/default/xui/de/floater_inventory.xml61
-rw-r--r--indra/newview/skins/default/xui/de/floater_inventory_item_properties.xml96
-rw-r--r--indra/newview/skins/default/xui/de/floater_inventory_view_finder.xml42
-rw-r--r--indra/newview/skins/default/xui/de/floater_joystick.xml32
-rw-r--r--indra/newview/skins/default/xui/de/floater_lagmeter.xml215
-rw-r--r--indra/newview/skins/default/xui/de/floater_land_holdings.xml14
-rw-r--r--indra/newview/skins/default/xui/de/floater_live_lsleditor.xml23
-rw-r--r--indra/newview/skins/default/xui/de/floater_lsl_guide.xml12
-rw-r--r--indra/newview/skins/default/xui/de/floater_map.xml54
-rw-r--r--indra/newview/skins/default/xui/de/floater_media_browser.xml31
-rw-r--r--indra/newview/skins/default/xui/de/floater_media_settings.xml6
-rw-r--r--indra/newview/skins/default/xui/de/floater_mem_leaking.xml16
-rw-r--r--indra/newview/skins/default/xui/de/floater_moveview.xml47
-rw-r--r--indra/newview/skins/default/xui/de/floater_mute_object.xml14
-rw-r--r--indra/newview/skins/default/xui/de/floater_my_friends.xml8
-rw-r--r--indra/newview/skins/default/xui/de/floater_nearby_chat.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_notification.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_notifications_console.xml6
-rw-r--r--indra/newview/skins/default/xui/de/floater_openobject.xml12
-rw-r--r--indra/newview/skins/default/xui/de/floater_outgoing_call.xml28
-rw-r--r--indra/newview/skins/default/xui/de/floater_pay.xml34
-rw-r--r--indra/newview/skins/default/xui/de/floater_pay_object.xml41
-rw-r--r--indra/newview/skins/default/xui/de/floater_perm_prefs.xml4
-rw-r--r--indra/newview/skins/default/xui/de/floater_post_process.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_postcard.xml26
-rw-r--r--indra/newview/skins/default/xui/de/floater_preferences.xml21
-rw-r--r--indra/newview/skins/default/xui/de/floater_preview_animation.xml15
-rw-r--r--indra/newview/skins/default/xui/de/floater_preview_classified.xml8
-rw-r--r--indra/newview/skins/default/xui/de/floater_preview_event.xml8
-rw-r--r--indra/newview/skins/default/xui/de/floater_preview_gesture.xml54
-rw-r--r--indra/newview/skins/default/xui/de/floater_preview_gesture_info.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_preview_gesture_shortcut.xml15
-rw-r--r--indra/newview/skins/default/xui/de/floater_preview_gesture_steps.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_preview_notecard.xml28
-rw-r--r--indra/newview/skins/default/xui/de/floater_preview_sound.xml15
-rw-r--r--indra/newview/skins/default/xui/de/floater_preview_texture.xml45
-rw-r--r--indra/newview/skins/default/xui/de/floater_region_info.xml4
-rw-r--r--indra/newview/skins/default/xui/de/floater_report_abuse.xml184
-rw-r--r--indra/newview/skins/default/xui/de/floater_script_debug.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_script_debug_panel.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_script_preview.xml9
-rw-r--r--indra/newview/skins/default/xui/de/floater_script_queue.xml21
-rw-r--r--indra/newview/skins/default/xui/de/floater_script_search.xml16
-rw-r--r--indra/newview/skins/default/xui/de/floater_search.xml9
-rw-r--r--indra/newview/skins/default/xui/de/floater_sell_land.xml136
-rw-r--r--indra/newview/skins/default/xui/de/floater_settings_debug.xml24
-rw-r--r--indra/newview/skins/default/xui/de/floater_snapshot.xml120
-rw-r--r--indra/newview/skins/default/xui/de/floater_sound_preview.xml24
-rw-r--r--indra/newview/skins/default/xui/de/floater_statistics.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_stats.xml71
-rw-r--r--indra/newview/skins/default/xui/de/floater_sys_well.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_telehub.xml14
-rw-r--r--indra/newview/skins/default/xui/de/floater_texture_ctrl.xml30
-rw-r--r--indra/newview/skins/default/xui/de/floater_tools.xml735
-rw-r--r--indra/newview/skins/default/xui/de/floater_top_objects.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_tos.xml19
-rw-r--r--indra/newview/skins/default/xui/de/floater_voice_controls.xml13
-rw-r--r--indra/newview/skins/default/xui/de/floater_water.xml44
-rw-r--r--indra/newview/skins/default/xui/de/floater_wearable_save_as.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_whitelist_entry.xml9
-rw-r--r--indra/newview/skins/default/xui/de/floater_windlight_options.xml67
-rw-r--r--indra/newview/skins/default/xui/de/floater_world_map.xml26
-rw-r--r--indra/newview/skins/default/xui/de/inspect_avatar.xml28
-rw-r--r--indra/newview/skins/default/xui/de/inspect_group.xml34
-rw-r--r--indra/newview/skins/default/xui/de/inspect_object.xml48
-rw-r--r--indra/newview/skins/default/xui/de/inspect_remote_object.xml25
-rw-r--r--indra/newview/skins/default/xui/de/language_settings.xml55
-rw-r--r--indra/newview/skins/default/xui/de/menu_avatar_icon.xml7
-rw-r--r--indra/newview/skins/default/xui/de/menu_bottomtray.xml7
-rw-r--r--indra/newview/skins/default/xui/de/menu_favorites.xml10
-rw-r--r--indra/newview/skins/default/xui/de/menu_gesture_gear.xml10
-rw-r--r--indra/newview/skins/default/xui/de/menu_group_plus.xml5
-rw-r--r--indra/newview/skins/default/xui/de/menu_hide_navbar.xml5
-rw-r--r--indra/newview/skins/default/xui/de/menu_imchiclet_group.xml6
-rw-r--r--indra/newview/skins/default/xui/de/menu_imchiclet_p2p.xml7
-rw-r--r--indra/newview/skins/default/xui/de/menu_inspect_avatar_gear.xml17
-rw-r--r--indra/newview/skins/default/xui/de/menu_inspect_object_gear.xml17
-rw-r--r--indra/newview/skins/default/xui/de/menu_inspect_self_gear.xml8
-rw-r--r--indra/newview/skins/default/xui/de/menu_inventory.xml26
-rw-r--r--indra/newview/skins/default/xui/de/menu_inventory_add.xml32
-rw-r--r--indra/newview/skins/default/xui/de/menu_inventory_gear_default.xml12
-rw-r--r--indra/newview/skins/default/xui/de/menu_landmark.xml7
-rw-r--r--indra/newview/skins/default/xui/de/menu_login.xml37
-rw-r--r--indra/newview/skins/default/xui/de/menu_mini_map.xml3
-rw-r--r--indra/newview/skins/default/xui/de/menu_navbar.xml11
-rw-r--r--indra/newview/skins/default/xui/de/menu_nearby_chat.xml9
-rw-r--r--indra/newview/skins/default/xui/de/menu_object_icon.xml5
-rw-r--r--indra/newview/skins/default/xui/de/menu_participant_list.xml5
-rw-r--r--indra/newview/skins/default/xui/de/menu_people_friends_view_sort.xml7
-rw-r--r--indra/newview/skins/default/xui/de/menu_people_groups_view_sort.xml5
-rw-r--r--indra/newview/skins/default/xui/de/menu_people_nearby.xml10
-rw-r--r--indra/newview/skins/default/xui/de/menu_people_nearby_multiselect.xml8
-rw-r--r--indra/newview/skins/default/xui/de/menu_people_nearby_view_sort.xml8
-rw-r--r--indra/newview/skins/default/xui/de/menu_people_recent_view_sort.xml7
-rw-r--r--indra/newview/skins/default/xui/de/menu_picks.xml8
-rw-r--r--indra/newview/skins/default/xui/de/menu_picks_plus.xml5
-rw-r--r--indra/newview/skins/default/xui/de/menu_place.xml7
-rw-r--r--indra/newview/skins/default/xui/de/menu_place_add_button.xml5
-rw-r--r--indra/newview/skins/default/xui/de/menu_places_gear_folder.xml15
-rw-r--r--indra/newview/skins/default/xui/de/menu_places_gear_landmark.xml18
-rw-r--r--indra/newview/skins/default/xui/de/menu_profile_overflow.xml5
-rw-r--r--indra/newview/skins/default/xui/de/menu_slurl.xml8
-rw-r--r--indra/newview/skins/default/xui/de/menu_teleport_history_gear.xml6
-rw-r--r--indra/newview/skins/default/xui/de/menu_teleport_history_item.xml6
-rw-r--r--indra/newview/skins/default/xui/de/menu_teleport_history_tab.xml5
-rw-r--r--indra/newview/skins/default/xui/de/menu_text_editor.xml8
-rw-r--r--indra/newview/skins/default/xui/de/menu_url_agent.xml6
-rw-r--r--indra/newview/skins/default/xui/de/menu_url_group.xml6
-rw-r--r--indra/newview/skins/default/xui/de/menu_url_http.xml7
-rw-r--r--indra/newview/skins/default/xui/de/menu_url_inventory.xml6
-rw-r--r--indra/newview/skins/default/xui/de/menu_url_map.xml6
-rw-r--r--indra/newview/skins/default/xui/de/menu_url_objectim.xml8
-rw-r--r--indra/newview/skins/default/xui/de/menu_url_parcel.xml6
-rw-r--r--indra/newview/skins/default/xui/de/menu_url_slapp.xml5
-rw-r--r--indra/newview/skins/default/xui/de/menu_url_slurl.xml7
-rw-r--r--indra/newview/skins/default/xui/de/menu_url_teleport.xml6
-rw-r--r--indra/newview/skins/default/xui/de/menu_viewer.xml599
-rw-r--r--indra/newview/skins/default/xui/de/notifications.xml1207
-rw-r--r--indra/newview/skins/default/xui/de/panel_activeim_row.xml6
-rw-r--r--indra/newview/skins/default/xui/de/panel_adhoc_control_panel.xml8
-rw-r--r--indra/newview/skins/default/xui/de/panel_avatar_list_item.xml26
-rw-r--r--indra/newview/skins/default/xui/de/panel_avatar_tag.xml12
-rw-r--r--indra/newview/skins/default/xui/de/panel_block_list_sidetray.xml10
-rw-r--r--indra/newview/skins/default/xui/de/panel_bottomtray.xml23
-rw-r--r--indra/newview/skins/default/xui/de/panel_chat_header.xml5
-rw-r--r--indra/newview/skins/default/xui/de/panel_classified_info.xml28
-rw-r--r--indra/newview/skins/default/xui/de/panel_edit_alpha.xml10
-rw-r--r--indra/newview/skins/default/xui/de/panel_edit_classified.xml41
-rw-r--r--indra/newview/skins/default/xui/de/panel_edit_eyes.xml9
-rw-r--r--indra/newview/skins/default/xui/de/panel_edit_gloves.xml10
-rw-r--r--indra/newview/skins/default/xui/de/panel_edit_hair.xml12
-rw-r--r--indra/newview/skins/default/xui/de/panel_edit_jacket.xml11
-rw-r--r--indra/newview/skins/default/xui/de/panel_edit_pants.xml10
-rw-r--r--indra/newview/skins/default/xui/de/panel_edit_pick.xml28
-rw-r--r--indra/newview/skins/default/xui/de/panel_edit_profile.xml56
-rw-r--r--indra/newview/skins/default/xui/de/panel_edit_shape.xml23
-rw-r--r--indra/newview/skins/default/xui/de/panel_edit_shirt.xml10
-rw-r--r--indra/newview/skins/default/xui/de/panel_edit_shoes.xml10
-rw-r--r--indra/newview/skins/default/xui/de/panel_edit_skin.xml14
-rw-r--r--indra/newview/skins/default/xui/de/panel_edit_skirt.xml10
-rw-r--r--indra/newview/skins/default/xui/de/panel_edit_socks.xml10
-rw-r--r--indra/newview/skins/default/xui/de/panel_edit_tattoo.xml8
-rw-r--r--indra/newview/skins/default/xui/de/panel_edit_underpants.xml10
-rw-r--r--indra/newview/skins/default/xui/de/panel_edit_undershirt.xml10
-rw-r--r--indra/newview/skins/default/xui/de/panel_edit_wearable.xml101
-rw-r--r--indra/newview/skins/default/xui/de/panel_group_control_panel.xml9
-rw-r--r--indra/newview/skins/default/xui/de/panel_group_general.xml85
-rw-r--r--indra/newview/skins/default/xui/de/panel_group_info_sidetray.xml36
-rw-r--r--indra/newview/skins/default/xui/de/panel_group_invite.xml34
-rw-r--r--indra/newview/skins/default/xui/de/panel_group_land_money.xml88
-rw-r--r--indra/newview/skins/default/xui/de/panel_group_list_item.xml4
-rw-r--r--indra/newview/skins/default/xui/de/panel_group_notices.xml65
-rw-r--r--indra/newview/skins/default/xui/de/panel_group_notify.xml12
-rw-r--r--indra/newview/skins/default/xui/de/panel_group_roles.xml176
-rw-r--r--indra/newview/skins/default/xui/de/panel_im_control_panel.xml13
-rw-r--r--indra/newview/skins/default/xui/de/panel_instant_message.xml11
-rw-r--r--indra/newview/skins/default/xui/de/panel_landmark_info.xml43
-rw-r--r--indra/newview/skins/default/xui/de/panel_landmarks.xml14
-rw-r--r--indra/newview/skins/default/xui/de/panel_login.xml86
-rw-r--r--indra/newview/skins/default/xui/de/panel_main_inventory.xml64
-rw-r--r--indra/newview/skins/default/xui/de/panel_me.xml7
-rw-r--r--indra/newview/skins/default/xui/de/panel_media_settings_general.xml32
-rw-r--r--indra/newview/skins/default/xui/de/panel_media_settings_permissions.xml9
-rw-r--r--indra/newview/skins/default/xui/de/panel_media_settings_security.xml12
-rw-r--r--indra/newview/skins/default/xui/de/panel_my_profile.xml55
-rw-r--r--indra/newview/skins/default/xui/de/panel_navigation_bar.xml15
-rw-r--r--indra/newview/skins/default/xui/de/panel_nearby_chat.xml9
-rw-r--r--indra/newview/skins/default/xui/de/panel_nearby_chat_bar.xml11
-rw-r--r--indra/newview/skins/default/xui/de/panel_notes.xml23
-rw-r--r--indra/newview/skins/default/xui/de/panel_outfits_inventory.xml13
-rw-r--r--indra/newview/skins/default/xui/de/panel_outfits_inventory_gear_default.xml6
-rw-r--r--indra/newview/skins/default/xui/de/panel_people.xml53
-rw-r--r--indra/newview/skins/default/xui/de/panel_pick_info.xml16
-rw-r--r--indra/newview/skins/default/xui/de/panel_picks.xml21
-rw-r--r--indra/newview/skins/default/xui/de/panel_place_profile.xml129
-rw-r--r--indra/newview/skins/default/xui/de/panel_places.xml14
-rw-r--r--indra/newview/skins/default/xui/de/panel_preferences_advanced.xml48
-rw-r--r--indra/newview/skins/default/xui/de/panel_preferences_alerts.xml14
-rw-r--r--indra/newview/skins/default/xui/de/panel_preferences_chat.xml82
-rw-r--r--indra/newview/skins/default/xui/de/panel_preferences_general.xml183
-rw-r--r--indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml267
-rw-r--r--indra/newview/skins/default/xui/de/panel_preferences_privacy.xml27
-rw-r--r--indra/newview/skins/default/xui/de/panel_preferences_setup.xml46
-rw-r--r--indra/newview/skins/default/xui/de/panel_preferences_sound.xml38
-rw-r--r--indra/newview/skins/default/xui/de/panel_prim_media_controls.xml33
-rw-r--r--indra/newview/skins/default/xui/de/panel_profile.xml61
-rw-r--r--indra/newview/skins/default/xui/de/panel_profile_view.xml16
-rw-r--r--indra/newview/skins/default/xui/de/panel_region_covenant.xml9
-rw-r--r--indra/newview/skins/default/xui/de/panel_region_debug.xml8
-rw-r--r--indra/newview/skins/default/xui/de/panel_region_estate.xml70
-rw-r--r--indra/newview/skins/default/xui/de/panel_region_general.xml12
-rw-r--r--indra/newview/skins/default/xui/de/panel_region_texture.xml21
-rw-r--r--indra/newview/skins/default/xui/de/panel_script_ed.xml43
-rw-r--r--indra/newview/skins/default/xui/de/panel_scrolling_param.xml4
-rw-r--r--indra/newview/skins/default/xui/de/panel_side_tray.xml26
-rw-r--r--indra/newview/skins/default/xui/de/panel_side_tray_tab_caption.xml5
-rw-r--r--indra/newview/skins/default/xui/de/panel_sidetray_home_tab.xml38
-rw-r--r--indra/newview/skins/default/xui/de/panel_stand_stop_flying.xml6
-rw-r--r--indra/newview/skins/default/xui/de/panel_status_bar.xml55
-rw-r--r--indra/newview/skins/default/xui/de/panel_sys_well_item.xml7
-rw-r--r--indra/newview/skins/default/xui/de/panel_teleport_history.xml15
-rw-r--r--indra/newview/skins/default/xui/de/panel_teleport_history_item.xml4
-rw-r--r--indra/newview/skins/default/xui/de/panel_world_map.xml57
-rw-r--r--indra/newview/skins/default/xui/de/sidepanel_appearance.xml16
-rw-r--r--indra/newview/skins/default/xui/de/sidepanel_inventory.xml11
-rw-r--r--indra/newview/skins/default/xui/de/sidepanel_item_info.xml80
-rw-r--r--indra/newview/skins/default/xui/de/sidepanel_task_info.xml126
-rw-r--r--indra/newview/skins/default/xui/de/strings.xml2710
-rw-r--r--indra/newview/skins/default/xui/de/teleport_strings.xml10
-rw-r--r--indra/newview/skins/default/xui/en/accordion_drag.xml8
-rw-r--r--indra/newview/skins/default/xui/en/accordion_parent.xml7
-rw-r--r--indra/newview/skins/default/xui/en/alert_button.xml15
-rw-r--r--indra/newview/skins/default/xui/en/alert_check_box.xml7
-rw-r--r--indra/newview/skins/default/xui/en/alert_icon.xml8
-rw-r--r--indra/newview/skins/default/xui/en/alert_line_editor.xml11
-rw-r--r--indra/newview/skins/default/xui/en/favorites_bar_button.xml27
-rw-r--r--indra/newview/skins/default/xui/en/floater_aaa.xml56
-rw-r--r--indra/newview/skins/default/xui/en/floater_about.xml171
-rw-r--r--indra/newview/skins/default/xui/en/floater_about_land.xml2122
-rw-r--r--indra/newview/skins/default/xui/en/floater_activeim.xml33
-rw-r--r--indra/newview/skins/default/xui/en/floater_animation_preview.xml545
-rw-r--r--indra/newview/skins/default/xui/en/floater_auction.xml96
-rw-r--r--indra/newview/skins/default/xui/en/floater_avatar_picker.xml226
-rw-r--r--indra/newview/skins/default/xui/en/floater_avatar_textures.xml306
-rw-r--r--indra/newview/skins/default/xui/en/floater_beacons.xml137
-rw-r--r--indra/newview/skins/default/xui/en/floater_build_options.xml82
-rw-r--r--indra/newview/skins/default/xui/en/floater_bulk_perms.xml310
-rw-r--r--indra/newview/skins/default/xui/en/floater_bumps.xml49
-rw-r--r--indra/newview/skins/default/xui/en/floater_buy_contents.xml97
-rw-r--r--indra/newview/skins/default/xui/en/floater_buy_currency.xml324
-rw-r--r--indra/newview/skins/default/xui/en/floater_buy_land.xml707
-rw-r--r--indra/newview/skins/default/xui/en/floater_buy_object.xml116
-rw-r--r--indra/newview/skins/default/xui/en/floater_camera.xml245
-rw-r--r--indra/newview/skins/default/xui/en/floater_choose_group.xml51
-rw-r--r--indra/newview/skins/default/xui/en/floater_color_picker.xml230
-rw-r--r--indra/newview/skins/default/xui/en/floater_critical.xml58
-rw-r--r--indra/newview/skins/default/xui/en/floater_customize.xml3389
-rw-r--r--indra/newview/skins/default/xui/en/floater_day_cycle_options.xml557
-rw-r--r--indra/newview/skins/default/xui/en/floater_device_settings.xml18
-rw-r--r--indra/newview/skins/default/xui/en/floater_env_settings.xml163
-rw-r--r--indra/newview/skins/default/xui/en/floater_first_time_tip.xml22
-rw-r--r--indra/newview/skins/default/xui/en/floater_font_test.xml364
-rw-r--r--indra/newview/skins/default/xui/en/floater_gesture.xml144
-rw-r--r--indra/newview/skins/default/xui/en/floater_god_tools.xml789
-rw-r--r--indra/newview/skins/default/xui/en/floater_hardware_settings.xml164
-rw-r--r--indra/newview/skins/default/xui/en/floater_help_browser.xml49
-rw-r--r--indra/newview/skins/default/xui/en/floater_hud.xml24
-rw-r--r--indra/newview/skins/default/xui/en/floater_im.xml80
-rw-r--r--indra/newview/skins/default/xui/en/floater_im_container.xml37
-rw-r--r--indra/newview/skins/default/xui/en/floater_im_session.xml82
-rw-r--r--indra/newview/skins/default/xui/en/floater_image_preview.xml141
-rw-r--r--indra/newview/skins/default/xui/en/floater_incoming_call.xml101
-rw-r--r--indra/newview/skins/default/xui/en/floater_inspect.xml74
-rw-r--r--indra/newview/skins/default/xui/en/floater_inventory.xml44
-rw-r--r--indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml468
-rw-r--r--indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml283
-rw-r--r--indra/newview/skins/default/xui/en/floater_joystick.xml864
-rw-r--r--indra/newview/skins/default/xui/en/floater_lagmeter.xml336
-rw-r--r--indra/newview/skins/default/xui/en/floater_land_holdings.xml167
-rw-r--r--indra/newview/skins/default/xui/en/floater_live_lsleditor.xml73
-rw-r--r--indra/newview/skins/default/xui/en/floater_lsl_guide.xml64
-rw-r--r--indra/newview/skins/default/xui/en/floater_map.xml167
-rw-r--r--indra/newview/skins/default/xui/en/floater_media_browser.xml236
-rw-r--r--indra/newview/skins/default/xui/en/floater_media_settings.xml74
-rw-r--r--indra/newview/skins/default/xui/en/floater_mem_leaking.xml130
-rw-r--r--indra/newview/skins/default/xui/en/floater_moveview.xml193
-rw-r--r--indra/newview/skins/default/xui/en/floater_mute_object.xml64
-rw-r--r--indra/newview/skins/default/xui/en/floater_my_friends.xml45
-rw-r--r--indra/newview/skins/default/xui/en/floater_nearby_chat.xml45
-rw-r--r--indra/newview/skins/default/xui/en/floater_notification.xml37
-rw-r--r--indra/newview/skins/default/xui/en/floater_notifications_console.xml42
-rw-r--r--indra/newview/skins/default/xui/en/floater_openobject.xml65
-rw-r--r--indra/newview/skins/default/xui/en/floater_outfit_save_as.xml58
-rw-r--r--indra/newview/skins/default/xui/en/floater_outgoing_call.xml125
-rw-r--r--indra/newview/skins/default/xui/en/floater_pay.xml127
-rw-r--r--indra/newview/skins/default/xui/en/floater_pay_object.xml152
-rw-r--r--indra/newview/skins/default/xui/en/floater_perm_prefs.xml108
-rw-r--r--indra/newview/skins/default/xui/en/floater_post_process.xml426
-rw-r--r--indra/newview/skins/default/xui/en/floater_postcard.xml159
-rw-r--r--indra/newview/skins/default/xui/en/floater_preferences.xml109
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_animation.xml59
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_classified.xml24
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_event.xml24
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_gesture.xml381
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_gesture_info.xml57
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_gesture_shortcut.xml88
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_gesture_steps.xml242
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_notecard.xml96
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_sound.xml62
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_texture.xml136
-rw-r--r--indra/newview/skins/default/xui/en/floater_region_info.xml20
-rw-r--r--indra/newview/skins/default/xui/en/floater_report_abuse.xml514
-rw-r--r--indra/newview/skins/default/xui/en/floater_script.xml18
-rw-r--r--indra/newview/skins/default/xui/en/floater_script_debug.xml20
-rw-r--r--indra/newview/skins/default/xui/en/floater_script_debug_panel.xml23
-rw-r--r--indra/newview/skins/default/xui/en/floater_script_limits.xml20
-rw-r--r--indra/newview/skins/default/xui/en/floater_script_preview.xml64
-rw-r--r--indra/newview/skins/default/xui/en/floater_script_queue.xml51
-rw-r--r--indra/newview/skins/default/xui/en/floater_script_search.xml92
-rw-r--r--indra/newview/skins/default/xui/en/floater_search.xml69
-rw-r--r--indra/newview/skins/default/xui/en/floater_select_key.xml34
-rw-r--r--indra/newview/skins/default/xui/en/floater_sell_land.xml253
-rw-r--r--indra/newview/skins/default/xui/en/floater_settings_debug.xml141
-rw-r--r--indra/newview/skins/default/xui/en/floater_snapshot.xml394
-rw-r--r--indra/newview/skins/default/xui/en/floater_sound_preview.xml76
-rw-r--r--indra/newview/skins/default/xui/en/floater_statistics.xml12
-rw-r--r--indra/newview/skins/default/xui/en/floater_stats.xml694
-rw-r--r--indra/newview/skins/default/xui/en/floater_sys_well.xml42
-rw-r--r--indra/newview/skins/default/xui/en/floater_telehub.xml126
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_button.xml110
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_checkbox.xml153
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_combobox.xml157
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_inspectors.xml137
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_layout.xml90
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_line_editor.xml105
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_list_view.xml11
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_navigation_bar.xml19
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_radiogroup.xml83
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_slider.xml100
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_spinner.xml96
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_text_editor.xml30
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_textbox.xml253
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_widgets.xml450
-rw-r--r--indra/newview/skins/default/xui/en/floater_texture_ctrl.xml150
-rw-r--r--indra/newview/skins/default/xui/en/floater_tools.xml2933
-rw-r--r--indra/newview/skins/default/xui/en/floater_top_objects.xml256
-rw-r--r--indra/newview/skins/default/xui/en/floater_tos.xml65
-rw-r--r--indra/newview/skins/default/xui/en/floater_ui_preview.xml407
-rw-r--r--indra/newview/skins/default/xui/en/floater_url_entry.xml72
-rw-r--r--indra/newview/skins/default/xui/en/floater_voice_controls.xml132
-rw-r--r--indra/newview/skins/default/xui/en/floater_water.xml498
-rw-r--r--indra/newview/skins/default/xui/en/floater_wearable_save_as.xml57
-rw-r--r--indra/newview/skins/default/xui/en/floater_whitelist_entry.xml28
-rw-r--r--indra/newview/skins/default/xui/en/floater_windlight_options.xml1274
-rw-r--r--indra/newview/skins/default/xui/en/floater_window_size.xml64
-rw-r--r--indra/newview/skins/default/xui/en/floater_world_map.xml687
-rw-r--r--indra/newview/skins/default/xui/en/fonts.xml161
-rw-r--r--indra/newview/skins/default/xui/en/inspect_avatar.xml182
-rw-r--r--indra/newview/skins/default/xui/en/inspect_group.xml104
-rw-r--r--indra/newview/skins/default/xui/en/inspect_object.xml180
-rw-r--r--indra/newview/skins/default/xui/en/inspect_remote_object.xml95
-rw-r--r--indra/newview/skins/default/xui/en/inspect_toast.xml19
-rw-r--r--indra/newview/skins/default/xui/en/language_settings.xml61
-rw-r--r--indra/newview/skins/default/xui/en/main_view.xml182
-rw-r--r--indra/newview/skins/default/xui/en/menu_attachment_other.xml105
-rw-r--r--indra/newview/skins/default/xui/en/menu_attachment_self.xml103
-rw-r--r--indra/newview/skins/default/xui/en/menu_avatar_icon.xml43
-rw-r--r--indra/newview/skins/default/xui/en/menu_avatar_other.xml96
-rw-r--r--indra/newview/skins/default/xui/en/menu_avatar_self.xml218
-rw-r--r--indra/newview/skins/default/xui/en/menu_bottomtray.xml108
-rw-r--r--indra/newview/skins/default/xui/en/menu_favorites.xml74
-rw-r--r--indra/newview/skins/default/xui/en/menu_gesture_gear.xml75
-rw-r--r--indra/newview/skins/default/xui/en/menu_group_plus.xml11
-rw-r--r--indra/newview/skins/default/xui/en/menu_hide_navbar.xml33
-rw-r--r--indra/newview/skins/default/xui/en/menu_im_well_button.xml16
-rw-r--r--indra/newview/skins/default/xui/en/menu_imchiclet_adhoc.xml19
-rw-r--r--indra/newview/skins/default/xui/en/menu_imchiclet_group.xml35
-rw-r--r--indra/newview/skins/default/xui/en/menu_imchiclet_p2p.xml43
-rw-r--r--indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml117
-rw-r--r--indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml130
-rw-r--r--indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml48
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory.xml662
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory_add.xml229
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml114
-rw-r--r--indra/newview/skins/default/xui/en/menu_land.xml64
-rw-r--r--indra/newview/skins/default/xui/en/menu_landmark.xml43
-rw-r--r--indra/newview/skins/default/xui/en/menu_login.xml267
-rw-r--r--indra/newview/skins/default/xui/en/menu_mini_map.xml57
-rw-r--r--indra/newview/skins/default/xui/en/menu_navbar.xml93
-rw-r--r--indra/newview/skins/default/xui/en/menu_nearby_chat.xml39
-rw-r--r--indra/newview/skins/default/xui/en/menu_notification_well_button.xml16
-rw-r--r--indra/newview/skins/default/xui/en/menu_object.xml164
-rw-r--r--indra/newview/skins/default/xui/en/menu_object_icon.xml27
-rw-r--r--indra/newview/skins/default/xui/en/menu_participant_list.xml177
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml38
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_groups.xml57
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml25
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_nearby.xml72
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml50
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml48
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml38
-rw-r--r--indra/newview/skins/default/xui/en/menu_picks.xml46
-rw-r--r--indra/newview/skins/default/xui/en/menu_picks_plus.xml25
-rw-r--r--indra/newview/skins/default/xui/en/menu_place.xml49
-rw-r--r--indra/newview/skins/default/xui/en/menu_place_add_button.xml27
-rw-r--r--indra/newview/skins/default/xui/en/menu_places_gear_folder.xml133
-rw-r--r--indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml177
-rw-r--r--indra/newview/skins/default/xui/en/menu_profile_overflow.xml58
-rw-r--r--indra/newview/skins/default/xui/en/menu_slurl.xml37
-rw-r--r--indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml36
-rw-r--r--indra/newview/skins/default/xui/en/menu_teleport_history_item.xml26
-rw-r--r--indra/newview/skins/default/xui/en/menu_teleport_history_tab.xml19
-rw-r--r--indra/newview/skins/default/xui/en/menu_text_editor.xml54
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_agent.xml28
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_group.xml28
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_http.xml37
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_inventory.xml28
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_map.xml30
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_objectim.xml44
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_parcel.xml30
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_slapp.xml21
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_slurl.xml37
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_teleport.xml30
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml3652
-rw-r--r--indra/newview/skins/default/xui/en/mime_types.xml442
-rw-r--r--indra/newview/skins/default/xui/en/mime_types_linux.xml442
-rw-r--r--indra/newview/skins/default/xui/en/mime_types_mac.xml442
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml5951
-rw-r--r--indra/newview/skins/default/xui/en/panel_active_object_row.xml81
-rw-r--r--indra/newview/skins/default/xui/en/panel_activeim_row.xml95
-rw-r--r--indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml99
-rw-r--r--indra/newview/skins/default/xui/en/panel_audio_device.xml152
-rw-r--r--indra/newview/skins/default/xui/en/panel_avatar_list_item.xml106
-rw-r--r--indra/newview/skins/default/xui/en/panel_avatar_tag.xml66
-rw-r--r--indra/newview/skins/default/xui/en/panel_bars.xml18
-rw-r--r--indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml83
-rw-r--r--indra/newview/skins/default/xui/en/panel_bottomtray.xml439
-rw-r--r--indra/newview/skins/default/xui/en/panel_chat_header.xml50
-rw-r--r--indra/newview/skins/default/xui/en/panel_chat_item.xml27
-rw-r--r--indra/newview/skins/default/xui/en/panel_chat_separator.xml8
-rw-r--r--indra/newview/skins/default/xui/en/panel_classified.xml138
-rw-r--r--indra/newview/skins/default/xui/en/panel_classified_info.xml181
-rw-r--r--indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml80
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_alpha.xml126
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_classified.xml257
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_eyes.xml53
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_gloves.xml64
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_hair.xml89
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_jacket.xml76
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_pants.xml64
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_pick.xml198
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_profile.xml345
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_shape.xml171
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_shirt.xml64
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_shoes.xml64
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_skin.xml116
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_skirt.xml64
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_socks.xml64
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_tattoo.xml57
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_underpants.xml64
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_undershirt.xml64
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_wearable.xml364
-rw-r--r--indra/newview/skins/default/xui/en/panel_friends.xml124
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_control_panel.xml114
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_general.xml172
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml243
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_invite.xml102
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_land_money.xml366
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_list_item.xml71
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_notices.xml340
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_notify.xml101
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_roles.xml540
-rw-r--r--indra/newview/skins/default/xui/en/panel_groups.xml111
-rw-r--r--indra/newview/skins/default/xui/en/panel_hud.xml10
-rw-r--r--indra/newview/skins/default/xui/en/panel_im_control_panel.xml166
-rw-r--r--indra/newview/skins/default/xui/en/panel_instant_message.xml87
-rw-r--r--indra/newview/skins/default/xui/en/panel_landmark_info.xml294
-rw-r--r--indra/newview/skins/default/xui/en/panel_landmarks.xml132
-rw-r--r--indra/newview/skins/default/xui/en/panel_login.xml234
-rw-r--r--indra/newview/skins/default/xui/en/panel_main_inventory.xml473
-rw-r--r--indra/newview/skins/default/xui/en/panel_me.xml52
-rw-r--r--indra/newview/skins/default/xui/en/panel_media_settings_general.xml226
-rw-r--r--indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml164
-rw-r--r--indra/newview/skins/default/xui/en/panel_media_settings_security.xml89
-rw-r--r--indra/newview/skins/default/xui/en/panel_my_profile.xml395
-rw-r--r--indra/newview/skins/default/xui/en/panel_navigation_bar.xml157
-rw-r--r--indra/newview/skins/default/xui/en/panel_nearby_chat.xml27
-rw-r--r--indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml63
-rw-r--r--indra/newview/skins/default/xui/en/panel_notes.xml169
-rw-r--r--indra/newview/skins/default/xui/en/panel_notification.xml93
-rw-r--r--indra/newview/skins/default/xui/en/panel_notifications_channel.xml76
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfits_inventory.xml117
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfits_inventory_gear_default.xml67
-rw-r--r--indra/newview/skins/default/xui/en/panel_people.xml425
-rw-r--r--indra/newview/skins/default/xui/en/panel_pick_info.xml138
-rw-r--r--indra/newview/skins/default/xui/en/panel_pick_list_item.xml80
-rw-r--r--indra/newview/skins/default/xui/en/panel_picks.xml165
-rw-r--r--indra/newview/skins/default/xui/en/panel_place_profile.xml929
-rw-r--r--indra/newview/skins/default/xui/en/panel_places.xml141
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_advanced.xml333
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_alerts.xml119
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_chat.xml351
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_general.xml353
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml760
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_privacy.xml215
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_setup.xml346
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_sound.xml507
-rw-r--r--indra/newview/skins/default/xui/en/panel_prim_media_controls.xml612
-rw-r--r--indra/newview/skins/default/xui/en/panel_profile.xml384
-rw-r--r--indra/newview/skins/default/xui/en/panel_profile_view.xml87
-rw-r--r--indra/newview/skins/default/xui/en/panel_progress.xml134
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_covenant.xml278
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_debug.xml204
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_estate.xml396
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_general.xml243
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_general_layout.xml242
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_terrain.xml156
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_texture.xml319
-rw-r--r--indra/newview/skins/default/xui/en/panel_script_ed.xml190
-rw-r--r--indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml62
-rw-r--r--indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml122
-rw-r--r--indra/newview/skins/default/xui/en/panel_scrolling_param.xml90
-rw-r--r--indra/newview/skins/default/xui/en/panel_side_tray.xml166
-rw-r--r--indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml37
-rw-r--r--indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml40
-rw-r--r--indra/newview/skins/default/xui/en/panel_stand_stop_flying.xml30
-rw-r--r--indra/newview/skins/default/xui/en/panel_status_bar.xml112
-rw-r--r--indra/newview/skins/default/xui/en/panel_sys_well_item.xml44
-rw-r--r--indra/newview/skins/default/xui/en/panel_teleport_history.xml165
-rw-r--r--indra/newview/skins/default/xui/en/panel_teleport_history_item.xml62
-rw-r--r--indra/newview/skins/default/xui/en/panel_toast.xml64
-rw-r--r--indra/newview/skins/default/xui/en/panel_volume_pulldown.xml55
-rw-r--r--indra/newview/skins/default/xui/en/panel_world_map.xml120
-rw-r--r--indra/newview/skins/default/xui/en/role_actions.xml187
-rw-r--r--indra/newview/skins/default/xui/en/sidepanel_appearance.xml122
-rw-r--r--indra/newview/skins/default/xui/en/sidepanel_inventory.xml110
-rw-r--r--indra/newview/skins/default/xui/en/sidepanel_item_info.xml416
-rw-r--r--indra/newview/skins/default/xui/en/sidepanel_task_info.xml553
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml3013
-rw-r--r--indra/newview/skins/default/xui/en/teleport_strings.xml77
-rw-r--r--indra/newview/skins/default/xui/en/widgets/accordion_tab.xml14
-rw-r--r--indra/newview/skins/default/xui/en/widgets/avatar_icon.xml4
-rw-r--r--indra/newview/skins/default/xui/en/widgets/button.xml23
-rw-r--r--indra/newview/skins/default/xui/en/widgets/chat_history.xml24
-rw-r--r--indra/newview/skins/default/xui/en/widgets/check_box.xml19
-rw-r--r--indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml48
-rw-r--r--indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml49
-rw-r--r--indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml48
-rw-r--r--indra/newview/skins/default/xui/en/widgets/chiclet_offer.xml30
-rw-r--r--indra/newview/skins/default/xui/en/widgets/chiclet_panel.xml9
-rw-r--r--indra/newview/skins/default/xui/en/widgets/chiclet_script.xml30
-rw-r--r--indra/newview/skins/default/xui/en/widgets/color_swatch.xml8
-rw-r--r--indra/newview/skins/default/xui/en/widgets/combo_box.xml33
-rw-r--r--indra/newview/skins/default/xui/en/widgets/context_menu.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/drop_down.xml20
-rw-r--r--indra/newview/skins/default/xui/en/widgets/expandable_text.xml19
-rw-r--r--indra/newview/skins/default/xui/en/widgets/filter_editor.xml21
-rw-r--r--indra/newview/skins/default/xui/en/widgets/flat_list_view.xml8
-rw-r--r--indra/newview/skins/default/xui/en/widgets/floater.xml24
-rw-r--r--indra/newview/skins/default/xui/en/widgets/flyout_button.xml12
-rw-r--r--indra/newview/skins/default/xui/en/widgets/folder_view_item.xml8
-rw-r--r--indra/newview/skins/default/xui/en/widgets/gesture_combo_list.xml21
-rw-r--r--indra/newview/skins/default/xui/en/widgets/group_icon.xml5
-rw-r--r--indra/newview/skins/default/xui/en/widgets/icon.xml7
-rw-r--r--indra/newview/skins/default/xui/en/widgets/inspector.xml10
-rw-r--r--indra/newview/skins/default/xui/en/widgets/inventory_panel.xml6
-rw-r--r--indra/newview/skins/default/xui/en/widgets/line_editor.xml19
-rw-r--r--indra/newview/skins/default/xui/en/widgets/list_view.xml6
-rw-r--r--indra/newview/skins/default/xui/en/widgets/location_input.xml130
-rw-r--r--indra/newview/skins/default/xui/en/widgets/menu.xml7
-rw-r--r--indra/newview/skins/default/xui/en/widgets/menu_item.xml3
-rw-r--r--indra/newview/skins/default/xui/en/widgets/menu_item_call.xml6
-rw-r--r--indra/newview/skins/default/xui/en/widgets/menu_item_check.xml6
-rw-r--r--indra/newview/skins/default/xui/en/widgets/menu_item_separator.xml6
-rw-r--r--indra/newview/skins/default/xui/en/widgets/menu_item_tear_off.xml7
-rw-r--r--indra/newview/skins/default/xui/en/widgets/multi_slider.xml6
-rw-r--r--indra/newview/skins/default/xui/en/widgets/multi_slider_bar.xml10
-rw-r--r--indra/newview/skins/default/xui/en/widgets/name_editor.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/output_monitor.xml13
-rw-r--r--indra/newview/skins/default/xui/en/widgets/panel.xml11
-rw-r--r--indra/newview/skins/default/xui/en/widgets/progress_bar.xml12
-rw-r--r--indra/newview/skins/default/xui/en/widgets/radio_group.xml6
-rw-r--r--indra/newview/skins/default/xui/en/widgets/radio_item.xml12
-rw-r--r--indra/newview/skins/default/xui/en/widgets/scroll_bar.xml25
-rw-r--r--indra/newview/skins/default/xui/en/widgets/scroll_column_header.xml11
-rw-r--r--indra/newview/skins/default/xui/en/widgets/scroll_container.xml5
-rw-r--r--indra/newview/skins/default/xui/en/widgets/scroll_list.xml20
-rw-r--r--indra/newview/skins/default/xui/en/widgets/search_combo_box.xml34
-rw-r--r--indra/newview/skins/default/xui/en/widgets/search_editor.xml21
-rw-r--r--indra/newview/skins/default/xui/en/widgets/side_tray.xml7
-rw-r--r--indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml27
-rw-r--r--indra/newview/skins/default/xui/en/widgets/slider.xml16
-rw-r--r--indra/newview/skins/default/xui/en/widgets/slider_bar.xml12
-rw-r--r--indra/newview/skins/default/xui/en/widgets/spinner.xml17
-rw-r--r--indra/newview/skins/default/xui/en/widgets/split_button.xml25
-rw-r--r--indra/newview/skins/default/xui/en/widgets/tab_container.xml31
-rw-r--r--indra/newview/skins/default/xui/en/widgets/talk_button.xml43
-rw-r--r--indra/newview/skins/default/xui/en/widgets/teleport_history_menu_item.xml8
-rw-r--r--indra/newview/skins/default/xui/en/widgets/text.xml20
-rw-r--r--indra/newview/skins/default/xui/en/widgets/text_editor.xml4
-rw-r--r--indra/newview/skins/default/xui/en/widgets/textbase.xml3
-rw-r--r--indra/newview/skins/default/xui/en/widgets/texture_picker.xml9
-rw-r--r--indra/newview/skins/default/xui/en/widgets/toggleable_menu.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/tool_tip.xml12
-rw-r--r--indra/newview/skins/default/xui/en/widgets/ui_ctrl.xml5
-rw-r--r--indra/newview/skins/default/xui/en/widgets/view_border.xml8
-rw-r--r--indra/newview/skins/default/xui/en/widgets/web_browser.xml2
-rw-r--r--indra/newview/skins/default/xui/en/xui_version.xml4
-rw-r--r--indra/newview/skins/default/xui/es/floater_about.xml20
-rw-r--r--indra/newview/skins/default/xui/es/floater_about_land.xml382
-rw-r--r--indra/newview/skins/default/xui/es/floater_animation_preview.xml173
-rw-r--r--indra/newview/skins/default/xui/es/floater_auction.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_avatar_picker.xml10
-rw-r--r--indra/newview/skins/default/xui/es/floater_avatar_textures.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_beacons.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_build_options.xml8
-rw-r--r--indra/newview/skins/default/xui/es/floater_bulk_perms.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_bumps.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_buy_contents.xml4
-rw-r--r--indra/newview/skins/default/xui/es/floater_buy_currency.xml17
-rw-r--r--indra/newview/skins/default/xui/es/floater_buy_land.xml25
-rw-r--r--indra/newview/skins/default/xui/es/floater_buy_object.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_camera.xml20
-rw-r--r--indra/newview/skins/default/xui/es/floater_choose_group.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_color_picker.xml5
-rw-r--r--indra/newview/skins/default/xui/es/floater_customize.xml200
-rw-r--r--indra/newview/skins/default/xui/es/floater_day_cycle_options.xml14
-rw-r--r--indra/newview/skins/default/xui/es/floater_device_settings.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_env_settings.xml17
-rw-r--r--indra/newview/skins/default/xui/es/floater_font_test.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_gesture.xml7
-rw-r--r--indra/newview/skins/default/xui/es/floater_god_tools.xml28
-rw-r--r--indra/newview/skins/default/xui/es/floater_hardware_settings.xml26
-rw-r--r--indra/newview/skins/default/xui/es/floater_hud.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_image_preview.xml50
-rw-r--r--indra/newview/skins/default/xui/es/floater_inspect.xml10
-rw-r--r--indra/newview/skins/default/xui/es/floater_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_inventory_item_properties.xml18
-rw-r--r--indra/newview/skins/default/xui/es/floater_inventory_view_finder.xml14
-rw-r--r--indra/newview/skins/default/xui/es/floater_joystick.xml63
-rw-r--r--indra/newview/skins/default/xui/es/floater_lagmeter.xml15
-rw-r--r--indra/newview/skins/default/xui/es/floater_land_holdings.xml4
-rw-r--r--indra/newview/skins/default/xui/es/floater_live_lsleditor.xml6
-rw-r--r--indra/newview/skins/default/xui/es/floater_lsl_guide.xml6
-rw-r--r--indra/newview/skins/default/xui/es/floater_map.xml51
-rw-r--r--indra/newview/skins/default/xui/es/floater_media_browser.xml17
-rw-r--r--indra/newview/skins/default/xui/es/floater_mem_leaking.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_moveview.xml4
-rw-r--r--indra/newview/skins/default/xui/es/floater_mute_object.xml9
-rw-r--r--indra/newview/skins/default/xui/es/floater_my_friends.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_openobject.xml4
-rw-r--r--indra/newview/skins/default/xui/es/floater_pay.xml9
-rw-r--r--indra/newview/skins/default/xui/es/floater_pay_object.xml14
-rw-r--r--indra/newview/skins/default/xui/es/floater_perm_prefs.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_post_process.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_postcard.xml23
-rw-r--r--indra/newview/skins/default/xui/es/floater_preferences.xml5
-rw-r--r--indra/newview/skins/default/xui/es/floater_preview_animation.xml6
-rw-r--r--indra/newview/skins/default/xui/es/floater_preview_classified.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_preview_event.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_preview_gesture.xml24
-rw-r--r--indra/newview/skins/default/xui/es/floater_preview_notecard.xml6
-rw-r--r--indra/newview/skins/default/xui/es/floater_preview_sound.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_preview_texture.xml4
-rw-r--r--indra/newview/skins/default/xui/es/floater_region_info.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_report_abuse.xml162
-rw-r--r--indra/newview/skins/default/xui/es/floater_script_debug.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_script_preview.xml4
-rw-r--r--indra/newview/skins/default/xui/es/floater_script_queue.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_script_search.xml16
-rw-r--r--indra/newview/skins/default/xui/es/floater_select_key.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_sell_land.xml26
-rw-r--r--indra/newview/skins/default/xui/es/floater_settings_debug.xml12
-rw-r--r--indra/newview/skins/default/xui/es/floater_snapshot.xml130
-rw-r--r--indra/newview/skins/default/xui/es/floater_sound_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_statistics.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_telehub.xml18
-rw-r--r--indra/newview/skins/default/xui/es/floater_texture_ctrl.xml10
-rw-r--r--indra/newview/skins/default/xui/es/floater_tools.xml504
-rw-r--r--indra/newview/skins/default/xui/es/floater_top_objects.xml23
-rw-r--r--indra/newview/skins/default/xui/es/floater_tos.xml4
-rw-r--r--indra/newview/skins/default/xui/es/floater_url_entry.xml3
-rw-r--r--indra/newview/skins/default/xui/es/floater_water.xml24
-rw-r--r--indra/newview/skins/default/xui/es/floater_wearable_save_as.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_windlight_options.xml22
-rw-r--r--indra/newview/skins/default/xui/es/floater_world_map.xml10
-rw-r--r--indra/newview/skins/default/xui/es/language_settings.xml55
-rw-r--r--indra/newview/skins/default/xui/es/menu_inventory.xml4
-rw-r--r--indra/newview/skins/default/xui/es/menu_login.xml4
-rw-r--r--indra/newview/skins/default/xui/es/menu_viewer.xml22
-rw-r--r--indra/newview/skins/default/xui/es/notifications.xml244
-rw-r--r--indra/newview/skins/default/xui/es/panel_edit_profile.xml45
-rw-r--r--indra/newview/skins/default/xui/es/panel_group_general.xml28
-rw-r--r--indra/newview/skins/default/xui/es/panel_group_invite.xml17
-rw-r--r--indra/newview/skins/default/xui/es/panel_group_land_money.xml20
-rw-r--r--indra/newview/skins/default/xui/es/panel_group_notices.xml18
-rw-r--r--indra/newview/skins/default/xui/es/panel_group_roles.xml46
-rw-r--r--indra/newview/skins/default/xui/es/panel_groups.xml8
-rw-r--r--indra/newview/skins/default/xui/es/panel_login.xml26
-rw-r--r--indra/newview/skins/default/xui/es/panel_preferences_advanced.xml12
-rw-r--r--indra/newview/skins/default/xui/es/panel_preferences_alerts.xml18
-rw-r--r--indra/newview/skins/default/xui/es/panel_preferences_chat.xml73
-rw-r--r--indra/newview/skins/default/xui/es/panel_preferences_general.xml149
-rw-r--r--indra/newview/skins/default/xui/es/panel_preferences_graphics1.xml122
-rw-r--r--indra/newview/skins/default/xui/es/panel_preferences_privacy.xml34
-rw-r--r--indra/newview/skins/default/xui/es/panel_preferences_setup.xml32
-rw-r--r--indra/newview/skins/default/xui/es/panel_preferences_sound.xml38
-rw-r--r--indra/newview/skins/default/xui/es/panel_profile.xml14
-rw-r--r--indra/newview/skins/default/xui/es/panel_region_covenant.xml10
-rw-r--r--indra/newview/skins/default/xui/es/panel_region_debug.xml16
-rw-r--r--indra/newview/skins/default/xui/es/panel_region_estate.xml16
-rw-r--r--indra/newview/skins/default/xui/es/panel_region_general.xml22
-rw-r--r--indra/newview/skins/default/xui/es/panel_region_terrain.xml16
-rw-r--r--indra/newview/skins/default/xui/es/panel_region_texture.xml2
-rw-r--r--indra/newview/skins/default/xui/es/panel_scrolling_param.xml4
-rw-r--r--indra/newview/skins/default/xui/es/panel_status_bar.xml12
-rw-r--r--indra/newview/skins/default/xui/es/panel_world_map.xml51
-rw-r--r--indra/newview/skins/default/xui/es/role_actions.xml195
-rw-r--r--indra/newview/skins/default/xui/es/strings.xml181
-rw-r--r--indra/newview/skins/default/xui/fr/floater_about.xml69
-rw-r--r--indra/newview/skins/default/xui/fr/floater_about_land.xml488
-rw-r--r--indra/newview/skins/default/xui/fr/floater_activeim.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_animation_preview.xml304
-rw-r--r--indra/newview/skins/default/xui/fr/floater_auction.xml25
-rw-r--r--indra/newview/skins/default/xui/fr/floater_avatar_picker.xml55
-rw-r--r--indra/newview/skins/default/xui/fr/floater_avatar_textures.xml43
-rw-r--r--indra/newview/skins/default/xui/fr/floater_beacons.xml26
-rw-r--r--indra/newview/skins/default/xui/fr/floater_build_options.xml17
-rw-r--r--indra/newview/skins/default/xui/fr/floater_bulk_perms.xml64
-rw-r--r--indra/newview/skins/default/xui/fr/floater_bumps.xml31
-rw-r--r--indra/newview/skins/default/xui/fr/floater_buy_contents.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_buy_currency.xml83
-rw-r--r--indra/newview/skins/default/xui/fr/floater_buy_land.xml39
-rw-r--r--indra/newview/skins/default/xui/fr/floater_buy_object.xml4
-rw-r--r--indra/newview/skins/default/xui/fr/floater_camera.xml35
-rw-r--r--indra/newview/skins/default/xui/fr/floater_choose_group.xml8
-rw-r--r--indra/newview/skins/default/xui/fr/floater_color_picker.xml9
-rw-r--r--indra/newview/skins/default/xui/fr/floater_customize.xml316
-rw-r--r--indra/newview/skins/default/xui/fr/floater_day_cycle_options.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_device_settings.xml5
-rw-r--r--indra/newview/skins/default/xui/fr/floater_env_settings.xml12
-rw-r--r--indra/newview/skins/default/xui/fr/floater_first_time_tip.xml4
-rw-r--r--indra/newview/skins/default/xui/fr/floater_font_test.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_gesture.xml39
-rw-r--r--indra/newview/skins/default/xui/fr/floater_god_tools.xml83
-rw-r--r--indra/newview/skins/default/xui/fr/floater_hardware_settings.xml26
-rw-r--r--indra/newview/skins/default/xui/fr/floater_help_browser.xml14
-rw-r--r--indra/newview/skins/default/xui/fr/floater_hud.xml4
-rw-r--r--indra/newview/skins/default/xui/fr/floater_im.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_im_container.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_im_session.xml9
-rw-r--r--indra/newview/skins/default/xui/fr/floater_image_preview.xml42
-rw-r--r--indra/newview/skins/default/xui/fr/floater_incoming_call.xml21
-rw-r--r--indra/newview/skins/default/xui/fr/floater_inspect.xml24
-rw-r--r--indra/newview/skins/default/xui/fr/floater_inventory.xml67
-rw-r--r--indra/newview/skins/default/xui/fr/floater_inventory_item_properties.xml82
-rw-r--r--indra/newview/skins/default/xui/fr/floater_inventory_view_finder.xml12
-rw-r--r--indra/newview/skins/default/xui/fr/floater_joystick.xml32
-rw-r--r--indra/newview/skins/default/xui/fr/floater_lagmeter.xml215
-rw-r--r--indra/newview/skins/default/xui/fr/floater_land_holdings.xml6
-rw-r--r--indra/newview/skins/default/xui/fr/floater_live_lsleditor.xml23
-rw-r--r--indra/newview/skins/default/xui/fr/floater_lsl_guide.xml12
-rw-r--r--indra/newview/skins/default/xui/fr/floater_map.xml54
-rw-r--r--indra/newview/skins/default/xui/fr/floater_media_browser.xml13
-rw-r--r--indra/newview/skins/default/xui/fr/floater_media_settings.xml6
-rw-r--r--indra/newview/skins/default/xui/fr/floater_mem_leaking.xml16
-rw-r--r--indra/newview/skins/default/xui/fr/floater_moveview.xml43
-rw-r--r--indra/newview/skins/default/xui/fr/floater_mute_object.xml8
-rw-r--r--indra/newview/skins/default/xui/fr/floater_my_friends.xml8
-rw-r--r--indra/newview/skins/default/xui/fr/floater_nearby_chat.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_notification.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_notifications_console.xml4
-rw-r--r--indra/newview/skins/default/xui/fr/floater_openobject.xml10
-rw-r--r--indra/newview/skins/default/xui/fr/floater_outgoing_call.xml28
-rw-r--r--indra/newview/skins/default/xui/fr/floater_pay.xml30
-rw-r--r--indra/newview/skins/default/xui/fr/floater_pay_object.xml37
-rw-r--r--indra/newview/skins/default/xui/fr/floater_perm_prefs.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_post_process.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_postcard.xml30
-rw-r--r--indra/newview/skins/default/xui/fr/floater_preferences.xml22
-rw-r--r--indra/newview/skins/default/xui/fr/floater_preview_animation.xml13
-rw-r--r--indra/newview/skins/default/xui/fr/floater_preview_classified.xml8
-rw-r--r--indra/newview/skins/default/xui/fr/floater_preview_event.xml8
-rw-r--r--indra/newview/skins/default/xui/fr/floater_preview_gesture.xml83
-rw-r--r--indra/newview/skins/default/xui/fr/floater_preview_gesture_info.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_preview_gesture_shortcut.xml15
-rw-r--r--indra/newview/skins/default/xui/fr/floater_preview_gesture_steps.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_preview_notecard.xml26
-rw-r--r--indra/newview/skins/default/xui/fr/floater_preview_sound.xml15
-rw-r--r--indra/newview/skins/default/xui/fr/floater_preview_texture.xml45
-rw-r--r--indra/newview/skins/default/xui/fr/floater_region_info.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_report_abuse.xml184
-rw-r--r--indra/newview/skins/default/xui/fr/floater_script_debug.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_script_debug_panel.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_script_preview.xml9
-rw-r--r--indra/newview/skins/default/xui/fr/floater_script_queue.xml21
-rw-r--r--indra/newview/skins/default/xui/fr/floater_script_search.xml18
-rw-r--r--indra/newview/skins/default/xui/fr/floater_search.xml9
-rw-r--r--indra/newview/skins/default/xui/fr/floater_sell_land.xml133
-rw-r--r--indra/newview/skins/default/xui/fr/floater_settings_debug.xml24
-rw-r--r--indra/newview/skins/default/xui/fr/floater_snapshot.xml120
-rw-r--r--indra/newview/skins/default/xui/fr/floater_sound_preview.xml18
-rw-r--r--indra/newview/skins/default/xui/fr/floater_statistics.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_stats.xml71
-rw-r--r--indra/newview/skins/default/xui/fr/floater_sys_well.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_telehub.xml12
-rw-r--r--indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml24
-rw-r--r--indra/newview/skins/default/xui/fr/floater_tools.xml672
-rw-r--r--indra/newview/skins/default/xui/fr/floater_top_objects.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_tos.xml19
-rw-r--r--indra/newview/skins/default/xui/fr/floater_voice_controls.xml13
-rw-r--r--indra/newview/skins/default/xui/fr/floater_water.xml42
-rw-r--r--indra/newview/skins/default/xui/fr/floater_wearable_save_as.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_whitelist_entry.xml9
-rw-r--r--indra/newview/skins/default/xui/fr/floater_windlight_options.xml67
-rw-r--r--indra/newview/skins/default/xui/fr/floater_world_map.xml67
-rw-r--r--indra/newview/skins/default/xui/fr/inspect_avatar.xml28
-rw-r--r--indra/newview/skins/default/xui/fr/inspect_group.xml34
-rw-r--r--indra/newview/skins/default/xui/fr/inspect_object.xml48
-rw-r--r--indra/newview/skins/default/xui/fr/inspect_remote_object.xml25
-rw-r--r--indra/newview/skins/default/xui/fr/language_settings.xml55
-rw-r--r--indra/newview/skins/default/xui/fr/menu_avatar_icon.xml7
-rw-r--r--indra/newview/skins/default/xui/fr/menu_bottomtray.xml7
-rw-r--r--indra/newview/skins/default/xui/fr/menu_favorites.xml10
-rw-r--r--indra/newview/skins/default/xui/fr/menu_gesture_gear.xml10
-rw-r--r--indra/newview/skins/default/xui/fr/menu_group_plus.xml5
-rw-r--r--indra/newview/skins/default/xui/fr/menu_hide_navbar.xml5
-rw-r--r--indra/newview/skins/default/xui/fr/menu_imchiclet_group.xml6
-rw-r--r--indra/newview/skins/default/xui/fr/menu_imchiclet_p2p.xml7
-rw-r--r--indra/newview/skins/default/xui/fr/menu_inspect_avatar_gear.xml17
-rw-r--r--indra/newview/skins/default/xui/fr/menu_inspect_object_gear.xml17
-rw-r--r--indra/newview/skins/default/xui/fr/menu_inspect_self_gear.xml8
-rw-r--r--indra/newview/skins/default/xui/fr/menu_inventory.xml26
-rw-r--r--indra/newview/skins/default/xui/fr/menu_inventory_add.xml32
-rw-r--r--indra/newview/skins/default/xui/fr/menu_inventory_gear_default.xml12
-rw-r--r--indra/newview/skins/default/xui/fr/menu_landmark.xml7
-rw-r--r--indra/newview/skins/default/xui/fr/menu_login.xml37
-rw-r--r--indra/newview/skins/default/xui/fr/menu_mini_map.xml3
-rw-r--r--indra/newview/skins/default/xui/fr/menu_navbar.xml11
-rw-r--r--indra/newview/skins/default/xui/fr/menu_nearby_chat.xml9
-rw-r--r--indra/newview/skins/default/xui/fr/menu_object_icon.xml5
-rw-r--r--indra/newview/skins/default/xui/fr/menu_participant_list.xml5
-rw-r--r--indra/newview/skins/default/xui/fr/menu_people_friends_view_sort.xml7
-rw-r--r--indra/newview/skins/default/xui/fr/menu_people_groups_view_sort.xml5
-rw-r--r--indra/newview/skins/default/xui/fr/menu_people_nearby.xml10
-rw-r--r--indra/newview/skins/default/xui/fr/menu_people_nearby_multiselect.xml8
-rw-r--r--indra/newview/skins/default/xui/fr/menu_people_nearby_view_sort.xml8
-rw-r--r--indra/newview/skins/default/xui/fr/menu_people_recent_view_sort.xml7
-rw-r--r--indra/newview/skins/default/xui/fr/menu_picks.xml8
-rw-r--r--indra/newview/skins/default/xui/fr/menu_picks_plus.xml5
-rw-r--r--indra/newview/skins/default/xui/fr/menu_place.xml7
-rw-r--r--indra/newview/skins/default/xui/fr/menu_place_add_button.xml5
-rw-r--r--indra/newview/skins/default/xui/fr/menu_places_gear_folder.xml15
-rw-r--r--indra/newview/skins/default/xui/fr/menu_places_gear_landmark.xml18
-rw-r--r--indra/newview/skins/default/xui/fr/menu_profile_overflow.xml5
-rw-r--r--indra/newview/skins/default/xui/fr/menu_slurl.xml8
-rw-r--r--indra/newview/skins/default/xui/fr/menu_teleport_history_gear.xml6
-rw-r--r--indra/newview/skins/default/xui/fr/menu_teleport_history_item.xml6
-rw-r--r--indra/newview/skins/default/xui/fr/menu_teleport_history_tab.xml5
-rw-r--r--indra/newview/skins/default/xui/fr/menu_text_editor.xml8
-rw-r--r--indra/newview/skins/default/xui/fr/menu_url_agent.xml6
-rw-r--r--indra/newview/skins/default/xui/fr/menu_url_group.xml6
-rw-r--r--indra/newview/skins/default/xui/fr/menu_url_http.xml7
-rw-r--r--indra/newview/skins/default/xui/fr/menu_url_inventory.xml6
-rw-r--r--indra/newview/skins/default/xui/fr/menu_url_map.xml6
-rw-r--r--indra/newview/skins/default/xui/fr/menu_url_objectim.xml8
-rw-r--r--indra/newview/skins/default/xui/fr/menu_url_parcel.xml6
-rw-r--r--indra/newview/skins/default/xui/fr/menu_url_slapp.xml5
-rw-r--r--indra/newview/skins/default/xui/fr/menu_url_slurl.xml7
-rw-r--r--indra/newview/skins/default/xui/fr/menu_url_teleport.xml6
-rw-r--r--indra/newview/skins/default/xui/fr/menu_viewer.xml607
-rw-r--r--indra/newview/skins/default/xui/fr/notifications.xml1196
-rw-r--r--indra/newview/skins/default/xui/fr/panel_activeim_row.xml6
-rw-r--r--indra/newview/skins/default/xui/fr/panel_adhoc_control_panel.xml8
-rw-r--r--indra/newview/skins/default/xui/fr/panel_avatar_list_item.xml26
-rw-r--r--indra/newview/skins/default/xui/fr/panel_avatar_tag.xml12
-rw-r--r--indra/newview/skins/default/xui/fr/panel_block_list_sidetray.xml10
-rw-r--r--indra/newview/skins/default/xui/fr/panel_bottomtray.xml23
-rw-r--r--indra/newview/skins/default/xui/fr/panel_chat_header.xml5
-rw-r--r--indra/newview/skins/default/xui/fr/panel_classified_info.xml28
-rw-r--r--indra/newview/skins/default/xui/fr/panel_edit_alpha.xml10
-rw-r--r--indra/newview/skins/default/xui/fr/panel_edit_classified.xml41
-rw-r--r--indra/newview/skins/default/xui/fr/panel_edit_eyes.xml9
-rw-r--r--indra/newview/skins/default/xui/fr/panel_edit_gloves.xml10
-rw-r--r--indra/newview/skins/default/xui/fr/panel_edit_hair.xml12
-rw-r--r--indra/newview/skins/default/xui/fr/panel_edit_jacket.xml11
-rw-r--r--indra/newview/skins/default/xui/fr/panel_edit_pants.xml10
-rw-r--r--indra/newview/skins/default/xui/fr/panel_edit_pick.xml28
-rw-r--r--indra/newview/skins/default/xui/fr/panel_edit_profile.xml56
-rw-r--r--indra/newview/skins/default/xui/fr/panel_edit_shape.xml23
-rw-r--r--indra/newview/skins/default/xui/fr/panel_edit_shirt.xml10
-rw-r--r--indra/newview/skins/default/xui/fr/panel_edit_shoes.xml10
-rw-r--r--indra/newview/skins/default/xui/fr/panel_edit_skin.xml14
-rw-r--r--indra/newview/skins/default/xui/fr/panel_edit_skirt.xml10
-rw-r--r--indra/newview/skins/default/xui/fr/panel_edit_socks.xml10
-rw-r--r--indra/newview/skins/default/xui/fr/panel_edit_tattoo.xml8
-rw-r--r--indra/newview/skins/default/xui/fr/panel_edit_underpants.xml10
-rw-r--r--indra/newview/skins/default/xui/fr/panel_edit_undershirt.xml10
-rw-r--r--indra/newview/skins/default/xui/fr/panel_edit_wearable.xml101
-rw-r--r--indra/newview/skins/default/xui/fr/panel_group_control_panel.xml9
-rw-r--r--indra/newview/skins/default/xui/fr/panel_group_general.xml87
-rw-r--r--indra/newview/skins/default/xui/fr/panel_group_info_sidetray.xml36
-rw-r--r--indra/newview/skins/default/xui/fr/panel_group_invite.xml25
-rw-r--r--indra/newview/skins/default/xui/fr/panel_group_land_money.xml47
-rw-r--r--indra/newview/skins/default/xui/fr/panel_group_list_item.xml4
-rw-r--r--indra/newview/skins/default/xui/fr/panel_group_notices.xml67
-rw-r--r--indra/newview/skins/default/xui/fr/panel_group_notify.xml12
-rw-r--r--indra/newview/skins/default/xui/fr/panel_group_roles.xml177
-rw-r--r--indra/newview/skins/default/xui/fr/panel_im_control_panel.xml13
-rw-r--r--indra/newview/skins/default/xui/fr/panel_instant_message.xml11
-rw-r--r--indra/newview/skins/default/xui/fr/panel_landmark_info.xml43
-rw-r--r--indra/newview/skins/default/xui/fr/panel_landmarks.xml14
-rw-r--r--indra/newview/skins/default/xui/fr/panel_login.xml87
-rw-r--r--indra/newview/skins/default/xui/fr/panel_main_inventory.xml64
-rw-r--r--indra/newview/skins/default/xui/fr/panel_me.xml7
-rw-r--r--indra/newview/skins/default/xui/fr/panel_media_settings_general.xml40
-rw-r--r--indra/newview/skins/default/xui/fr/panel_media_settings_permissions.xml9
-rw-r--r--indra/newview/skins/default/xui/fr/panel_media_settings_security.xml6
-rw-r--r--indra/newview/skins/default/xui/fr/panel_my_profile.xml55
-rw-r--r--indra/newview/skins/default/xui/fr/panel_navigation_bar.xml12
-rw-r--r--indra/newview/skins/default/xui/fr/panel_nearby_chat.xml9
-rw-r--r--indra/newview/skins/default/xui/fr/panel_nearby_chat_bar.xml11
-rw-r--r--indra/newview/skins/default/xui/fr/panel_notes.xml23
-rw-r--r--indra/newview/skins/default/xui/fr/panel_outfits_inventory.xml13
-rw-r--r--indra/newview/skins/default/xui/fr/panel_outfits_inventory_gear_default.xml6
-rw-r--r--indra/newview/skins/default/xui/fr/panel_people.xml53
-rw-r--r--indra/newview/skins/default/xui/fr/panel_pick_info.xml16
-rw-r--r--indra/newview/skins/default/xui/fr/panel_picks.xml21
-rw-r--r--indra/newview/skins/default/xui/fr/panel_place_profile.xml129
-rw-r--r--indra/newview/skins/default/xui/fr/panel_places.xml14
-rw-r--r--indra/newview/skins/default/xui/fr/panel_preferences_advanced.xml48
-rw-r--r--indra/newview/skins/default/xui/fr/panel_preferences_alerts.xml14
-rw-r--r--indra/newview/skins/default/xui/fr/panel_preferences_chat.xml84
-rw-r--r--indra/newview/skins/default/xui/fr/panel_preferences_general.xml184
-rw-r--r--indra/newview/skins/default/xui/fr/panel_preferences_graphics1.xml259
-rw-r--r--indra/newview/skins/default/xui/fr/panel_preferences_privacy.xml28
-rw-r--r--indra/newview/skins/default/xui/fr/panel_preferences_setup.xml46
-rw-r--r--indra/newview/skins/default/xui/fr/panel_preferences_sound.xml38
-rw-r--r--indra/newview/skins/default/xui/fr/panel_prim_media_controls.xml33
-rw-r--r--indra/newview/skins/default/xui/fr/panel_profile.xml61
-rw-r--r--indra/newview/skins/default/xui/fr/panel_profile_view.xml16
-rw-r--r--indra/newview/skins/default/xui/fr/panel_region_covenant.xml6
-rw-r--r--indra/newview/skins/default/xui/fr/panel_region_debug.xml18
-rw-r--r--indra/newview/skins/default/xui/fr/panel_region_estate.xml10
-rw-r--r--indra/newview/skins/default/xui/fr/panel_region_general.xml12
-rw-r--r--indra/newview/skins/default/xui/fr/panel_region_texture.xml21
-rw-r--r--indra/newview/skins/default/xui/fr/panel_script_ed.xml43
-rw-r--r--indra/newview/skins/default/xui/fr/panel_scrolling_param.xml4
-rw-r--r--indra/newview/skins/default/xui/fr/panel_side_tray.xml26
-rw-r--r--indra/newview/skins/default/xui/fr/panel_side_tray_tab_caption.xml5
-rw-r--r--indra/newview/skins/default/xui/fr/panel_sidetray_home_tab.xml38
-rw-r--r--indra/newview/skins/default/xui/fr/panel_stand_stop_flying.xml6
-rw-r--r--indra/newview/skins/default/xui/fr/panel_status_bar.xml54
-rw-r--r--indra/newview/skins/default/xui/fr/panel_sys_well_item.xml7
-rw-r--r--indra/newview/skins/default/xui/fr/panel_teleport_history.xml15
-rw-r--r--indra/newview/skins/default/xui/fr/panel_teleport_history_item.xml4
-rw-r--r--indra/newview/skins/default/xui/fr/panel_world_map.xml57
-rw-r--r--indra/newview/skins/default/xui/fr/sidepanel_appearance.xml16
-rw-r--r--indra/newview/skins/default/xui/fr/sidepanel_inventory.xml11
-rw-r--r--indra/newview/skins/default/xui/fr/sidepanel_item_info.xml80
-rw-r--r--indra/newview/skins/default/xui/fr/sidepanel_task_info.xml126
-rw-r--r--indra/newview/skins/default/xui/fr/strings.xml2712
-rw-r--r--indra/newview/skins/default/xui/fr/teleport_strings.xml10
-rw-r--r--indra/newview/skins/default/xui/it/floater_about.xml20
-rw-r--r--indra/newview/skins/default/xui/it/floater_about_land.xml278
-rw-r--r--indra/newview/skins/default/xui/it/floater_animation_preview.xml167
-rw-r--r--indra/newview/skins/default/xui/it/floater_auction.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_avatar_picker.xml10
-rw-r--r--indra/newview/skins/default/xui/it/floater_avatar_textures.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_beacons.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_build_options.xml8
-rw-r--r--indra/newview/skins/default/xui/it/floater_bulk_perms.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_bumps.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_buy_contents.xml8
-rw-r--r--indra/newview/skins/default/xui/it/floater_buy_currency.xml17
-rw-r--r--indra/newview/skins/default/xui/it/floater_buy_land.xml25
-rw-r--r--indra/newview/skins/default/xui/it/floater_buy_object.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_camera.xml18
-rw-r--r--indra/newview/skins/default/xui/it/floater_choose_group.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_color_picker.xml4
-rw-r--r--indra/newview/skins/default/xui/it/floater_customize.xml12
-rw-r--r--indra/newview/skins/default/xui/it/floater_day_cycle_options.xml32
-rw-r--r--indra/newview/skins/default/xui/it/floater_device_settings.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_env_settings.xml16
-rw-r--r--indra/newview/skins/default/xui/it/floater_font_test.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_gesture.xml13
-rw-r--r--indra/newview/skins/default/xui/it/floater_hardware_settings.xml28
-rw-r--r--indra/newview/skins/default/xui/it/floater_hud.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_image_preview.xml45
-rw-r--r--indra/newview/skins/default/xui/it/floater_inspect.xml10
-rw-r--r--indra/newview/skins/default/xui/it/floater_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_inventory_item_properties.xml18
-rw-r--r--indra/newview/skins/default/xui/it/floater_inventory_view_finder.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_joystick.xml79
-rw-r--r--indra/newview/skins/default/xui/it/floater_lagmeter.xml19
-rw-r--r--indra/newview/skins/default/xui/it/floater_land_holdings.xml12
-rw-r--r--indra/newview/skins/default/xui/it/floater_live_lsleditor.xml6
-rw-r--r--indra/newview/skins/default/xui/it/floater_lsl_guide.xml6
-rw-r--r--indra/newview/skins/default/xui/it/floater_map.xml51
-rw-r--r--indra/newview/skins/default/xui/it/floater_media_browser.xml17
-rw-r--r--indra/newview/skins/default/xui/it/floater_mem_leaking.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_moveview.xml4
-rw-r--r--indra/newview/skins/default/xui/it/floater_mute_object.xml8
-rw-r--r--indra/newview/skins/default/xui/it/floater_my_friends.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_openobject.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_pay.xml21
-rw-r--r--indra/newview/skins/default/xui/it/floater_pay_object.xml23
-rw-r--r--indra/newview/skins/default/xui/it/floater_perm_prefs.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_post_process.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_postcard.xml14
-rw-r--r--indra/newview/skins/default/xui/it/floater_preferences.xml3
-rw-r--r--indra/newview/skins/default/xui/it/floater_preview_animation.xml4
-rw-r--r--indra/newview/skins/default/xui/it/floater_preview_classified.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_preview_event.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_preview_gesture.xml17
-rw-r--r--indra/newview/skins/default/xui/it/floater_preview_notecard.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_region_info.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_report_abuse.xml163
-rw-r--r--indra/newview/skins/default/xui/it/floater_script_debug.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_script_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_script_queue.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_script_search.xml16
-rw-r--r--indra/newview/skins/default/xui/it/floater_sell_land.xml26
-rw-r--r--indra/newview/skins/default/xui/it/floater_settings_debug.xml12
-rw-r--r--indra/newview/skins/default/xui/it/floater_snapshot.xml138
-rw-r--r--indra/newview/skins/default/xui/it/floater_sound_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_statistics.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_telehub.xml18
-rw-r--r--indra/newview/skins/default/xui/it/floater_texture_ctrl.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_tools.xml544
-rw-r--r--indra/newview/skins/default/xui/it/floater_top_objects.xml33
-rw-r--r--indra/newview/skins/default/xui/it/floater_tos.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_url_entry.xml4
-rw-r--r--indra/newview/skins/default/xui/it/floater_water.xml46
-rw-r--r--indra/newview/skins/default/xui/it/floater_windlight_options.xml34
-rw-r--r--indra/newview/skins/default/xui/it/floater_world_map.xml12
-rw-r--r--indra/newview/skins/default/xui/it/language_settings.xml55
-rw-r--r--indra/newview/skins/default/xui/it/menu_login.xml4
-rw-r--r--indra/newview/skins/default/xui/it/menu_viewer.xml14
-rw-r--r--indra/newview/skins/default/xui/it/notifications.xml323
-rw-r--r--indra/newview/skins/default/xui/it/panel_edit_profile.xml45
-rw-r--r--indra/newview/skins/default/xui/it/panel_friends.xml2
-rw-r--r--indra/newview/skins/default/xui/it/panel_group_general.xml26
-rw-r--r--indra/newview/skins/default/xui/it/panel_group_invite.xml4
-rw-r--r--indra/newview/skins/default/xui/it/panel_group_land_money.xml26
-rw-r--r--indra/newview/skins/default/xui/it/panel_group_notices.xml30
-rw-r--r--indra/newview/skins/default/xui/it/panel_group_roles.xml44
-rw-r--r--indra/newview/skins/default/xui/it/panel_groups.xml10
-rw-r--r--indra/newview/skins/default/xui/it/panel_login.xml26
-rw-r--r--indra/newview/skins/default/xui/it/panel_preferences_advanced.xml12
-rw-r--r--indra/newview/skins/default/xui/it/panel_preferences_alerts.xml18
-rw-r--r--indra/newview/skins/default/xui/it/panel_preferences_chat.xml68
-rw-r--r--indra/newview/skins/default/xui/it/panel_preferences_general.xml137
-rw-r--r--indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml106
-rw-r--r--indra/newview/skins/default/xui/it/panel_preferences_privacy.xml33
-rw-r--r--indra/newview/skins/default/xui/it/panel_preferences_setup.xml36
-rw-r--r--indra/newview/skins/default/xui/it/panel_preferences_sound.xml38
-rw-r--r--indra/newview/skins/default/xui/it/panel_profile.xml14
-rw-r--r--indra/newview/skins/default/xui/it/panel_region_covenant.xml30
-rw-r--r--indra/newview/skins/default/xui/it/panel_region_debug.xml12
-rw-r--r--indra/newview/skins/default/xui/it/panel_region_estate.xml16
-rw-r--r--indra/newview/skins/default/xui/it/panel_region_general.xml34
-rw-r--r--indra/newview/skins/default/xui/it/panel_region_terrain.xml8
-rw-r--r--indra/newview/skins/default/xui/it/panel_region_texture.xml6
-rw-r--r--indra/newview/skins/default/xui/it/panel_status_bar.xml4
-rw-r--r--indra/newview/skins/default/xui/it/panel_world_map.xml51
-rw-r--r--indra/newview/skins/default/xui/it/strings.xml168
-rw-r--r--indra/newview/skins/default/xui/it/teleport_strings.xml18
-rw-r--r--indra/newview/skins/default/xui/ja/floater_about.xml71
-rw-r--r--indra/newview/skins/default/xui/ja/floater_about_land.xml475
-rw-r--r--indra/newview/skins/default/xui/ja/floater_activeim.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/floater_animation_preview.xml316
-rw-r--r--indra/newview/skins/default/xui/ja/floater_auction.xml17
-rw-r--r--indra/newview/skins/default/xui/ja/floater_avatar_picker.xml48
-rw-r--r--indra/newview/skins/default/xui/ja/floater_avatar_textures.xml41
-rw-r--r--indra/newview/skins/default/xui/ja/floater_beacons.xml22
-rw-r--r--indra/newview/skins/default/xui/ja/floater_build_options.xml17
-rw-r--r--indra/newview/skins/default/xui/ja/floater_bulk_perms.xml64
-rw-r--r--indra/newview/skins/default/xui/ja/floater_bumps.xml31
-rw-r--r--indra/newview/skins/default/xui/ja/floater_buy_contents.xml15
-rw-r--r--indra/newview/skins/default/xui/ja/floater_buy_currency.xml82
-rw-r--r--indra/newview/skins/default/xui/ja/floater_buy_land.xml42
-rw-r--r--indra/newview/skins/default/xui/ja/floater_buy_object.xml8
-rw-r--r--indra/newview/skins/default/xui/ja/floater_camera.xml35
-rw-r--r--indra/newview/skins/default/xui/ja/floater_choose_group.xml6
-rw-r--r--indra/newview/skins/default/xui/ja/floater_color_picker.xml14
-rw-r--r--indra/newview/skins/default/xui/ja/floater_customize.xml286
-rw-r--r--indra/newview/skins/default/xui/ja/floater_device_settings.xml4
-rw-r--r--indra/newview/skins/default/xui/ja/floater_env_settings.xml17
-rw-r--r--indra/newview/skins/default/xui/ja/floater_first_time_tip.xml4
-rw-r--r--indra/newview/skins/default/xui/ja/floater_gesture.xml38
-rw-r--r--indra/newview/skins/default/xui/ja/floater_god_tools.xml143
-rw-r--r--indra/newview/skins/default/xui/ja/floater_hardware_settings.xml40
-rw-r--r--indra/newview/skins/default/xui/ja/floater_help_browser.xml14
-rw-r--r--indra/newview/skins/default/xui/ja/floater_hud.xml4
-rw-r--r--indra/newview/skins/default/xui/ja/floater_im.xml4
-rw-r--r--indra/newview/skins/default/xui/ja/floater_im_container.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/floater_im_session.xml9
-rw-r--r--indra/newview/skins/default/xui/ja/floater_image_preview.xml48
-rw-r--r--indra/newview/skins/default/xui/ja/floater_incoming_call.xml21
-rw-r--r--indra/newview/skins/default/xui/ja/floater_inspect.xml24
-rw-r--r--indra/newview/skins/default/xui/ja/floater_inventory.xml63
-rw-r--r--indra/newview/skins/default/xui/ja/floater_inventory_item_properties.xml94
-rw-r--r--indra/newview/skins/default/xui/ja/floater_inventory_view_finder.xml42
-rw-r--r--indra/newview/skins/default/xui/ja/floater_joystick.xml30
-rw-r--r--indra/newview/skins/default/xui/ja/floater_lagmeter.xml215
-rw-r--r--indra/newview/skins/default/xui/ja/floater_land_holdings.xml12
-rw-r--r--indra/newview/skins/default/xui/ja/floater_live_lsleditor.xml23
-rw-r--r--indra/newview/skins/default/xui/ja/floater_lsl_guide.xml12
-rw-r--r--indra/newview/skins/default/xui/ja/floater_map.xml54
-rw-r--r--indra/newview/skins/default/xui/ja/floater_media_browser.xml31
-rw-r--r--indra/newview/skins/default/xui/ja/floater_media_settings.xml6
-rw-r--r--indra/newview/skins/default/xui/ja/floater_mem_leaking.xml17
-rw-r--r--indra/newview/skins/default/xui/ja/floater_moveview.xml48
-rw-r--r--indra/newview/skins/default/xui/ja/floater_mute_object.xml14
-rw-r--r--indra/newview/skins/default/xui/ja/floater_my_friends.xml8
-rw-r--r--indra/newview/skins/default/xui/ja/floater_nearby_chat.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/floater_openobject.xml12
-rw-r--r--indra/newview/skins/default/xui/ja/floater_outgoing_call.xml28
-rw-r--r--indra/newview/skins/default/xui/ja/floater_pay.xml34
-rw-r--r--indra/newview/skins/default/xui/ja/floater_pay_object.xml41
-rw-r--r--indra/newview/skins/default/xui/ja/floater_postcard.xml27
-rw-r--r--indra/newview/skins/default/xui/ja/floater_preferences.xml19
-rw-r--r--indra/newview/skins/default/xui/ja/floater_preview_animation.xml13
-rw-r--r--indra/newview/skins/default/xui/ja/floater_preview_classified.xml8
-rw-r--r--indra/newview/skins/default/xui/ja/floater_preview_event.xml8
-rw-r--r--indra/newview/skins/default/xui/ja/floater_preview_gesture.xml60
-rw-r--r--indra/newview/skins/default/xui/ja/floater_preview_gesture_info.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/floater_preview_gesture_shortcut.xml15
-rw-r--r--indra/newview/skins/default/xui/ja/floater_preview_gesture_steps.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/floater_preview_notecard.xml26
-rw-r--r--indra/newview/skins/default/xui/ja/floater_preview_sound.xml14
-rw-r--r--indra/newview/skins/default/xui/ja/floater_preview_texture.xml45
-rw-r--r--indra/newview/skins/default/xui/ja/floater_region_info.xml4
-rw-r--r--indra/newview/skins/default/xui/ja/floater_report_abuse.xml181
-rw-r--r--indra/newview/skins/default/xui/ja/floater_script_debug.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/floater_script_debug_panel.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/floater_script_preview.xml9
-rw-r--r--indra/newview/skins/default/xui/ja/floater_script_queue.xml21
-rw-r--r--indra/newview/skins/default/xui/ja/floater_script_search.xml16
-rw-r--r--indra/newview/skins/default/xui/ja/floater_search.xml9
-rw-r--r--indra/newview/skins/default/xui/ja/floater_sell_land.xml135
-rw-r--r--indra/newview/skins/default/xui/ja/floater_settings_debug.xml22
-rw-r--r--indra/newview/skins/default/xui/ja/floater_snapshot.xml126
-rw-r--r--indra/newview/skins/default/xui/ja/floater_sound_preview.xml22
-rw-r--r--indra/newview/skins/default/xui/ja/floater_stats.xml71
-rw-r--r--indra/newview/skins/default/xui/ja/floater_sys_well.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/floater_telehub.xml10
-rw-r--r--indra/newview/skins/default/xui/ja/floater_texture_ctrl.xml30
-rw-r--r--indra/newview/skins/default/xui/ja/floater_tools.xml702
-rw-r--r--indra/newview/skins/default/xui/ja/floater_top_objects.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/floater_tos.xml19
-rw-r--r--indra/newview/skins/default/xui/ja/floater_voice_controls.xml13
-rw-r--r--indra/newview/skins/default/xui/ja/floater_water.xml41
-rw-r--r--indra/newview/skins/default/xui/ja/floater_wearable_save_as.xml4
-rw-r--r--indra/newview/skins/default/xui/ja/floater_whitelist_entry.xml9
-rw-r--r--indra/newview/skins/default/xui/ja/floater_windlight_options.xml65
-rw-r--r--indra/newview/skins/default/xui/ja/floater_world_map.xml26
-rw-r--r--indra/newview/skins/default/xui/ja/inspect_avatar.xml28
-rw-r--r--indra/newview/skins/default/xui/ja/inspect_group.xml34
-rw-r--r--indra/newview/skins/default/xui/ja/inspect_object.xml48
-rw-r--r--indra/newview/skins/default/xui/ja/inspect_remote_object.xml25
-rw-r--r--indra/newview/skins/default/xui/ja/language_settings.xml55
-rw-r--r--indra/newview/skins/default/xui/ja/menu_avatar_icon.xml7
-rw-r--r--indra/newview/skins/default/xui/ja/menu_bottomtray.xml7
-rw-r--r--indra/newview/skins/default/xui/ja/menu_favorites.xml10
-rw-r--r--indra/newview/skins/default/xui/ja/menu_gesture_gear.xml10
-rw-r--r--indra/newview/skins/default/xui/ja/menu_group_plus.xml5
-rw-r--r--indra/newview/skins/default/xui/ja/menu_hide_navbar.xml5
-rw-r--r--indra/newview/skins/default/xui/ja/menu_imchiclet_group.xml6
-rw-r--r--indra/newview/skins/default/xui/ja/menu_imchiclet_p2p.xml7
-rw-r--r--indra/newview/skins/default/xui/ja/menu_inspect_avatar_gear.xml17
-rw-r--r--indra/newview/skins/default/xui/ja/menu_inspect_object_gear.xml17
-rw-r--r--indra/newview/skins/default/xui/ja/menu_inspect_self_gear.xml8
-rw-r--r--indra/newview/skins/default/xui/ja/menu_inventory.xml26
-rw-r--r--indra/newview/skins/default/xui/ja/menu_inventory_add.xml32
-rw-r--r--indra/newview/skins/default/xui/ja/menu_inventory_gear_default.xml12
-rw-r--r--indra/newview/skins/default/xui/ja/menu_landmark.xml7
-rw-r--r--indra/newview/skins/default/xui/ja/menu_login.xml37
-rw-r--r--indra/newview/skins/default/xui/ja/menu_mini_map.xml3
-rw-r--r--indra/newview/skins/default/xui/ja/menu_navbar.xml11
-rw-r--r--indra/newview/skins/default/xui/ja/menu_nearby_chat.xml9
-rw-r--r--indra/newview/skins/default/xui/ja/menu_object_icon.xml5
-rw-r--r--indra/newview/skins/default/xui/ja/menu_participant_list.xml5
-rw-r--r--indra/newview/skins/default/xui/ja/menu_people_friends_view_sort.xml7
-rw-r--r--indra/newview/skins/default/xui/ja/menu_people_groups_view_sort.xml5
-rw-r--r--indra/newview/skins/default/xui/ja/menu_people_nearby.xml10
-rw-r--r--indra/newview/skins/default/xui/ja/menu_people_nearby_multiselect.xml8
-rw-r--r--indra/newview/skins/default/xui/ja/menu_people_nearby_view_sort.xml8
-rw-r--r--indra/newview/skins/default/xui/ja/menu_people_recent_view_sort.xml7
-rw-r--r--indra/newview/skins/default/xui/ja/menu_picks.xml8
-rw-r--r--indra/newview/skins/default/xui/ja/menu_picks_plus.xml5
-rw-r--r--indra/newview/skins/default/xui/ja/menu_place.xml7
-rw-r--r--indra/newview/skins/default/xui/ja/menu_place_add_button.xml5
-rw-r--r--indra/newview/skins/default/xui/ja/menu_places_gear_folder.xml15
-rw-r--r--indra/newview/skins/default/xui/ja/menu_places_gear_landmark.xml18
-rw-r--r--indra/newview/skins/default/xui/ja/menu_profile_overflow.xml5
-rw-r--r--indra/newview/skins/default/xui/ja/menu_slurl.xml8
-rw-r--r--indra/newview/skins/default/xui/ja/menu_teleport_history_gear.xml6
-rw-r--r--indra/newview/skins/default/xui/ja/menu_teleport_history_item.xml6
-rw-r--r--indra/newview/skins/default/xui/ja/menu_teleport_history_tab.xml5
-rw-r--r--indra/newview/skins/default/xui/ja/menu_text_editor.xml8
-rw-r--r--indra/newview/skins/default/xui/ja/menu_url_agent.xml6
-rw-r--r--indra/newview/skins/default/xui/ja/menu_url_group.xml6
-rw-r--r--indra/newview/skins/default/xui/ja/menu_url_http.xml7
-rw-r--r--indra/newview/skins/default/xui/ja/menu_url_inventory.xml6
-rw-r--r--indra/newview/skins/default/xui/ja/menu_url_map.xml6
-rw-r--r--indra/newview/skins/default/xui/ja/menu_url_objectim.xml8
-rw-r--r--indra/newview/skins/default/xui/ja/menu_url_parcel.xml6
-rw-r--r--indra/newview/skins/default/xui/ja/menu_url_slapp.xml5
-rw-r--r--indra/newview/skins/default/xui/ja/menu_url_slurl.xml7
-rw-r--r--indra/newview/skins/default/xui/ja/menu_url_teleport.xml6
-rw-r--r--indra/newview/skins/default/xui/ja/menu_viewer.xml607
-rw-r--r--indra/newview/skins/default/xui/ja/notifications.xml1514
-rw-r--r--indra/newview/skins/default/xui/ja/panel_activeim_row.xml6
-rw-r--r--indra/newview/skins/default/xui/ja/panel_adhoc_control_panel.xml8
-rw-r--r--indra/newview/skins/default/xui/ja/panel_avatar_list_item.xml26
-rw-r--r--indra/newview/skins/default/xui/ja/panel_avatar_tag.xml12
-rw-r--r--indra/newview/skins/default/xui/ja/panel_block_list_sidetray.xml10
-rw-r--r--indra/newview/skins/default/xui/ja/panel_bottomtray.xml23
-rw-r--r--indra/newview/skins/default/xui/ja/panel_chat_header.xml5
-rw-r--r--indra/newview/skins/default/xui/ja/panel_classified_info.xml28
-rw-r--r--indra/newview/skins/default/xui/ja/panel_edit_alpha.xml10
-rw-r--r--indra/newview/skins/default/xui/ja/panel_edit_classified.xml41
-rw-r--r--indra/newview/skins/default/xui/ja/panel_edit_eyes.xml9
-rw-r--r--indra/newview/skins/default/xui/ja/panel_edit_gloves.xml10
-rw-r--r--indra/newview/skins/default/xui/ja/panel_edit_hair.xml12
-rw-r--r--indra/newview/skins/default/xui/ja/panel_edit_jacket.xml11
-rw-r--r--indra/newview/skins/default/xui/ja/panel_edit_pants.xml10
-rw-r--r--indra/newview/skins/default/xui/ja/panel_edit_pick.xml28
-rw-r--r--indra/newview/skins/default/xui/ja/panel_edit_profile.xml56
-rw-r--r--indra/newview/skins/default/xui/ja/panel_edit_shape.xml23
-rw-r--r--indra/newview/skins/default/xui/ja/panel_edit_shirt.xml10
-rw-r--r--indra/newview/skins/default/xui/ja/panel_edit_shoes.xml10
-rw-r--r--indra/newview/skins/default/xui/ja/panel_edit_skin.xml14
-rw-r--r--indra/newview/skins/default/xui/ja/panel_edit_skirt.xml10
-rw-r--r--indra/newview/skins/default/xui/ja/panel_edit_socks.xml10
-rw-r--r--indra/newview/skins/default/xui/ja/panel_edit_tattoo.xml8
-rw-r--r--indra/newview/skins/default/xui/ja/panel_edit_underpants.xml10
-rw-r--r--indra/newview/skins/default/xui/ja/panel_edit_undershirt.xml10
-rw-r--r--indra/newview/skins/default/xui/ja/panel_edit_wearable.xml101
-rw-r--r--indra/newview/skins/default/xui/ja/panel_group_control_panel.xml9
-rw-r--r--indra/newview/skins/default/xui/ja/panel_group_general.xml91
-rw-r--r--indra/newview/skins/default/xui/ja/panel_group_info_sidetray.xml36
-rw-r--r--indra/newview/skins/default/xui/ja/panel_group_invite.xml36
-rw-r--r--indra/newview/skins/default/xui/ja/panel_group_land_money.xml45
-rw-r--r--indra/newview/skins/default/xui/ja/panel_group_list_item.xml4
-rw-r--r--indra/newview/skins/default/xui/ja/panel_group_notices.xml60
-rw-r--r--indra/newview/skins/default/xui/ja/panel_group_notify.xml12
-rw-r--r--indra/newview/skins/default/xui/ja/panel_group_roles.xml172
-rw-r--r--indra/newview/skins/default/xui/ja/panel_im_control_panel.xml13
-rw-r--r--indra/newview/skins/default/xui/ja/panel_instant_message.xml11
-rw-r--r--indra/newview/skins/default/xui/ja/panel_landmark_info.xml43
-rw-r--r--indra/newview/skins/default/xui/ja/panel_landmarks.xml14
-rw-r--r--indra/newview/skins/default/xui/ja/panel_login.xml88
-rw-r--r--indra/newview/skins/default/xui/ja/panel_main_inventory.xml64
-rw-r--r--indra/newview/skins/default/xui/ja/panel_me.xml7
-rw-r--r--indra/newview/skins/default/xui/ja/panel_media_settings_general.xml40
-rw-r--r--indra/newview/skins/default/xui/ja/panel_media_settings_permissions.xml9
-rw-r--r--indra/newview/skins/default/xui/ja/panel_media_settings_security.xml6
-rw-r--r--indra/newview/skins/default/xui/ja/panel_my_profile.xml55
-rw-r--r--indra/newview/skins/default/xui/ja/panel_navigation_bar.xml12
-rw-r--r--indra/newview/skins/default/xui/ja/panel_nearby_chat.xml9
-rw-r--r--indra/newview/skins/default/xui/ja/panel_nearby_chat_bar.xml11
-rw-r--r--indra/newview/skins/default/xui/ja/panel_notes.xml23
-rw-r--r--indra/newview/skins/default/xui/ja/panel_outfits_inventory.xml13
-rw-r--r--indra/newview/skins/default/xui/ja/panel_outfits_inventory_gear_default.xml6
-rw-r--r--indra/newview/skins/default/xui/ja/panel_people.xml53
-rw-r--r--indra/newview/skins/default/xui/ja/panel_pick_info.xml16
-rw-r--r--indra/newview/skins/default/xui/ja/panel_picks.xml21
-rw-r--r--indra/newview/skins/default/xui/ja/panel_place_profile.xml129
-rw-r--r--indra/newview/skins/default/xui/ja/panel_places.xml14
-rw-r--r--indra/newview/skins/default/xui/ja/panel_preferences_advanced.xml48
-rw-r--r--indra/newview/skins/default/xui/ja/panel_preferences_alerts.xml14
-rw-r--r--indra/newview/skins/default/xui/ja/panel_preferences_chat.xml85
-rw-r--r--indra/newview/skins/default/xui/ja/panel_preferences_general.xml180
-rw-r--r--indra/newview/skins/default/xui/ja/panel_preferences_graphics1.xml269
-rw-r--r--indra/newview/skins/default/xui/ja/panel_preferences_privacy.xml27
-rw-r--r--indra/newview/skins/default/xui/ja/panel_preferences_setup.xml46
-rw-r--r--indra/newview/skins/default/xui/ja/panel_preferences_sound.xml38
-rw-r--r--indra/newview/skins/default/xui/ja/panel_prim_media_controls.xml33
-rw-r--r--indra/newview/skins/default/xui/ja/panel_profile.xml61
-rw-r--r--indra/newview/skins/default/xui/ja/panel_profile_view.xml16
-rw-r--r--indra/newview/skins/default/xui/ja/panel_region_covenant.xml9
-rw-r--r--indra/newview/skins/default/xui/ja/panel_region_debug.xml10
-rw-r--r--indra/newview/skins/default/xui/ja/panel_region_estate.xml69
-rw-r--r--indra/newview/skins/default/xui/ja/panel_region_general.xml12
-rw-r--r--indra/newview/skins/default/xui/ja/panel_region_texture.xml25
-rw-r--r--indra/newview/skins/default/xui/ja/panel_script_ed.xml43
-rw-r--r--indra/newview/skins/default/xui/ja/panel_scrolling_param.xml4
-rw-r--r--indra/newview/skins/default/xui/ja/panel_side_tray.xml26
-rw-r--r--indra/newview/skins/default/xui/ja/panel_side_tray_tab_caption.xml5
-rw-r--r--indra/newview/skins/default/xui/ja/panel_sidetray_home_tab.xml38
-rw-r--r--indra/newview/skins/default/xui/ja/panel_stand_stop_flying.xml6
-rw-r--r--indra/newview/skins/default/xui/ja/panel_status_bar.xml55
-rw-r--r--indra/newview/skins/default/xui/ja/panel_sys_well_item.xml7
-rw-r--r--indra/newview/skins/default/xui/ja/panel_teleport_history.xml15
-rw-r--r--indra/newview/skins/default/xui/ja/panel_teleport_history_item.xml4
-rw-r--r--indra/newview/skins/default/xui/ja/panel_world_map.xml57
-rw-r--r--indra/newview/skins/default/xui/ja/sidepanel_appearance.xml16
-rw-r--r--indra/newview/skins/default/xui/ja/sidepanel_inventory.xml11
-rw-r--r--indra/newview/skins/default/xui/ja/sidepanel_item_info.xml80
-rw-r--r--indra/newview/skins/default/xui/ja/sidepanel_task_info.xml126
-rw-r--r--indra/newview/skins/default/xui/ja/strings.xml2744
-rw-r--r--indra/newview/skins/default/xui/ja/teleport_strings.xml10
-rw-r--r--indra/newview/skins/default/xui/nl/floater_about.xml19
-rw-r--r--indra/newview/skins/default/xui/nl/floater_about_land.xml284
-rw-r--r--indra/newview/skins/default/xui/nl/floater_auction.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_beacons.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_bulk_perms.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_bumps.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_buy_contents.xml4
-rw-r--r--indra/newview/skins/default/xui/nl/floater_buy_currency.xml6
-rw-r--r--indra/newview/skins/default/xui/nl/floater_buy_land.xml17
-rw-r--r--indra/newview/skins/default/xui/nl/floater_buy_object.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_camera.xml18
-rw-r--r--indra/newview/skins/default/xui/nl/floater_choose_group.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_color_picker.xml7
-rw-r--r--indra/newview/skins/default/xui/nl/floater_customize.xml34
-rw-r--r--indra/newview/skins/default/xui/nl/floater_env_settings.xml9
-rw-r--r--indra/newview/skins/default/xui/nl/floater_font_test.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_gesture.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_hud.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_inspect.xml10
-rw-r--r--indra/newview/skins/default/xui/nl/floater_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_joystick.xml39
-rw-r--r--indra/newview/skins/default/xui/nl/floater_lagmeter.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_lsl_guide.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_map.xml51
-rw-r--r--indra/newview/skins/default/xui/nl/floater_mem_leaking.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_moveview.xml4
-rw-r--r--indra/newview/skins/default/xui/nl/floater_mute_object.xml10
-rw-r--r--indra/newview/skins/default/xui/nl/floater_my_friends.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_openobject.xml6
-rw-r--r--indra/newview/skins/default/xui/nl/floater_pay.xml4
-rw-r--r--indra/newview/skins/default/xui/nl/floater_pay_object.xml12
-rw-r--r--indra/newview/skins/default/xui/nl/floater_perm_prefs.xml4
-rw-r--r--indra/newview/skins/default/xui/nl/floater_post_process.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_postcard.xml6
-rw-r--r--indra/newview/skins/default/xui/nl/floater_preferences.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_region_info.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_report_abuse.xml172
-rw-r--r--indra/newview/skins/default/xui/nl/floater_script_debug.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_script_queue.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_select_key.xml4
-rw-r--r--indra/newview/skins/default/xui/nl/floater_sell_land.xml26
-rw-r--r--indra/newview/skins/default/xui/nl/floater_snapshot.xml128
-rw-r--r--indra/newview/skins/default/xui/nl/floater_statistics.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_telehub.xml16
-rw-r--r--indra/newview/skins/default/xui/nl/floater_texture_ctrl.xml8
-rw-r--r--indra/newview/skins/default/xui/nl/floater_tools.xml506
-rw-r--r--indra/newview/skins/default/xui/nl/floater_top_objects.xml28
-rw-r--r--indra/newview/skins/default/xui/nl/floater_tos.xml3
-rw-r--r--indra/newview/skins/default/xui/nl/floater_url_entry.xml4
-rw-r--r--indra/newview/skins/default/xui/nl/floater_water.xml7
-rw-r--r--indra/newview/skins/default/xui/nl/floater_world_map.xml12
-rw-r--r--indra/newview/skins/default/xui/nl/language_settings.xml55
-rw-r--r--indra/newview/skins/default/xui/nl/menu_inventory.xml4
-rw-r--r--indra/newview/skins/default/xui/nl/menu_login.xml4
-rw-r--r--indra/newview/skins/default/xui/nl/menu_viewer.xml8
-rw-r--r--indra/newview/skins/default/xui/nl/notifications.xml194
-rw-r--r--indra/newview/skins/default/xui/nl/panel_edit_profile.xml45
-rw-r--r--indra/newview/skins/default/xui/nl/panel_friends.xml12
-rw-r--r--indra/newview/skins/default/xui/nl/panel_group_general.xml39
-rw-r--r--indra/newview/skins/default/xui/nl/panel_group_invite.xml9
-rw-r--r--indra/newview/skins/default/xui/nl/panel_group_notices.xml18
-rw-r--r--indra/newview/skins/default/xui/nl/panel_group_roles.xml34
-rw-r--r--indra/newview/skins/default/xui/nl/panel_groups.xml14
-rw-r--r--indra/newview/skins/default/xui/nl/panel_login.xml28
-rw-r--r--indra/newview/skins/default/xui/nl/panel_region_estate.xml16
-rw-r--r--indra/newview/skins/default/xui/nl/panel_region_general.xml16
-rw-r--r--indra/newview/skins/default/xui/nl/panel_status_bar.xml4
-rw-r--r--indra/newview/skins/default/xui/nl/panel_world_map.xml51
-rw-r--r--indra/newview/skins/default/xui/nl/role_actions.xml76
-rw-r--r--indra/newview/skins/default/xui/nl/strings.xml170
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_about.xml22
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_about_land.xml400
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_auction.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_avatar_picker.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_avatar_textures.xml2
-rw-r--r--indra/newview/skins/default/xui/pl/floater_beacons.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_build_options.xml2
-rw-r--r--indra/newview/skins/default/xui/pl/floater_bulk_perms.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_bumps.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_buy_contents.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_buy_currency.xml6
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_buy_land.xml14
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_buy_object.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_camera.xml18
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_choose_group.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_color_picker.xml4
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_customize.xml194
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_day_cycle_options.xml50
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_device_settings.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_env_settings.xml12
-rw-r--r--indra/newview/skins/default/xui/pl/floater_font_test.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_gesture.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_god_tools.xml34
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_hardware_settings.xml30
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_hud.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_image_preview.xml40
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_inspect.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_inventory.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_inventory_item_properties.xml10
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_inventory_view_finder.xml4
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_joystick.xml117
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_lagmeter.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_land_holdings.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_live_lsleditor.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_lsl_guide.xml2
-rw-r--r--indra/newview/skins/default/xui/pl/floater_map.xml51
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_media_browser.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_mem_leaking.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_moveview.xml4
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_mute_object.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_my_friends.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_openobject.xml4
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_pay.xml8
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_pay_object.xml14
-rw-r--r--indra/newview/skins/default/xui/pl/floater_perm_prefs.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_post_process.xml22
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_postcard.xml8
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_preferences.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_preview_animation.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_preview_classified.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_preview_event.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_preview_gesture.xml8
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_preview_notecard.xml6
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_preview_sound.xml4
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_preview_texture.xml4
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_region_info.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_report_abuse.xml158
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_script_debug.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_script_preview.xml4
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_script_queue.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_script_search.xml6
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_select_key.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_sell_land.xml26
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_settings_debug.xml10
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_snapshot.xml118
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_sound_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/pl/floater_statistics.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_telehub.xml6
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_texture_ctrl.xml6
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_tools.xml485
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_top_objects.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_tos.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_water.xml42
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_wearable_save_as.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_windlight_options.xml98
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_world_map.xml12
-rw-r--r--indra/newview/skins/default/xui/pl/language_settings.xml55
-rwxr-xr-xindra/newview/skins/default/xui/pl/menu_login.xml4
-rwxr-xr-xindra/newview/skins/default/xui/pl/menu_viewer.xml10
-rw-r--r--indra/newview/skins/default/xui/pl/notifications.xml195
-rwxr-xr-xindra/newview/skins/default/xui/pl/panel_audio_device.xml10
-rw-r--r--indra/newview/skins/default/xui/pl/panel_edit_profile.xml45
-rwxr-xr-xindra/newview/skins/default/xui/pl/panel_group_general.xml26
-rwxr-xr-xindra/newview/skins/default/xui/pl/panel_group_land_money.xml5
-rwxr-xr-xindra/newview/skins/default/xui/pl/panel_group_notices.xml7
-rwxr-xr-xindra/newview/skins/default/xui/pl/panel_groups.xml4
-rwxr-xr-xindra/newview/skins/default/xui/pl/panel_login.xml14
-rw-r--r--indra/newview/skins/default/xui/pl/panel_preferences_advanced.xml12
-rwxr-xr-xindra/newview/skins/default/xui/pl/panel_preferences_alerts.xml21
-rwxr-xr-xindra/newview/skins/default/xui/pl/panel_preferences_chat.xml76
-rwxr-xr-xindra/newview/skins/default/xui/pl/panel_preferences_general.xml147
-rwxr-xr-xindra/newview/skins/default/xui/pl/panel_preferences_graphics1.xml134
-rwxr-xr-xindra/newview/skins/default/xui/pl/panel_preferences_privacy.xml33
-rwxr-xr-xindra/newview/skins/default/xui/pl/panel_preferences_setup.xml31
-rwxr-xr-xindra/newview/skins/default/xui/pl/panel_preferences_sound.xml40
-rwxr-xr-xindra/newview/skins/default/xui/pl/panel_region_estate.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/panel_region_general.xml12
-rwxr-xr-xindra/newview/skins/default/xui/pl/panel_scrolling_param.xml4
-rwxr-xr-xindra/newview/skins/default/xui/pl/panel_status_bar.xml12
-rw-r--r--indra/newview/skins/default/xui/pl/panel_world_map.xml51
-rwxr-xr-xindra/newview/skins/default/xui/pl/strings.xml168
-rw-r--r--indra/newview/skins/default/xui/pt/floater_about.xml19
-rw-r--r--indra/newview/skins/default/xui/pt/floater_about_land.xml380
-rw-r--r--indra/newview/skins/default/xui/pt/floater_animation_preview.xml173
-rw-r--r--indra/newview/skins/default/xui/pt/floater_auction.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_avatar_picker.xml12
-rw-r--r--indra/newview/skins/default/xui/pt/floater_avatar_textures.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_beacons.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_build_options.xml8
-rw-r--r--indra/newview/skins/default/xui/pt/floater_bulk_perms.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_bumps.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_buy_contents.xml8
-rw-r--r--indra/newview/skins/default/xui/pt/floater_buy_currency.xml9
-rw-r--r--indra/newview/skins/default/xui/pt/floater_buy_land.xml33
-rw-r--r--indra/newview/skins/default/xui/pt/floater_buy_object.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_camera.xml20
-rw-r--r--indra/newview/skins/default/xui/pt/floater_choose_group.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_color_picker.xml8
-rw-r--r--indra/newview/skins/default/xui/pt/floater_customize.xml194
-rw-r--r--indra/newview/skins/default/xui/pt/floater_day_cycle_options.xml30
-rw-r--r--indra/newview/skins/default/xui/pt/floater_device_settings.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_env_settings.xml14
-rw-r--r--indra/newview/skins/default/xui/pt/floater_font_test.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_gesture.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_god_tools.xml28
-rw-r--r--indra/newview/skins/default/xui/pt/floater_hardware_settings.xml22
-rw-r--r--indra/newview/skins/default/xui/pt/floater_hud.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_image_preview.xml45
-rw-r--r--indra/newview/skins/default/xui/pt/floater_inspect.xml10
-rw-r--r--indra/newview/skins/default/xui/pt/floater_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_inventory_item_properties.xml12
-rw-r--r--indra/newview/skins/default/xui/pt/floater_inventory_view_finder.xml8
-rw-r--r--indra/newview/skins/default/xui/pt/floater_joystick.xml71
-rw-r--r--indra/newview/skins/default/xui/pt/floater_lagmeter.xml15
-rw-r--r--indra/newview/skins/default/xui/pt/floater_land_holdings.xml12
-rw-r--r--indra/newview/skins/default/xui/pt/floater_live_lsleditor.xml4
-rw-r--r--indra/newview/skins/default/xui/pt/floater_lsl_guide.xml6
-rw-r--r--indra/newview/skins/default/xui/pt/floater_map.xml51
-rw-r--r--indra/newview/skins/default/xui/pt/floater_media_browser.xml8
-rw-r--r--indra/newview/skins/default/xui/pt/floater_mem_leaking.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_moveview.xml4
-rw-r--r--indra/newview/skins/default/xui/pt/floater_mute_object.xml7
-rw-r--r--indra/newview/skins/default/xui/pt/floater_my_friends.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_openobject.xml4
-rw-r--r--indra/newview/skins/default/xui/pt/floater_pay.xml8
-rw-r--r--indra/newview/skins/default/xui/pt/floater_pay_object.xml14
-rw-r--r--indra/newview/skins/default/xui/pt/floater_perm_prefs.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_post_process.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_postcard.xml8
-rw-r--r--indra/newview/skins/default/xui/pt/floater_preferences.xml3
-rw-r--r--indra/newview/skins/default/xui/pt/floater_preview_animation.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_preview_classified.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_preview_event.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_preview_gesture.xml32
-rw-r--r--indra/newview/skins/default/xui/pt/floater_preview_notecard.xml6
-rw-r--r--indra/newview/skins/default/xui/pt/floater_preview_sound.xml6
-rw-r--r--indra/newview/skins/default/xui/pt/floater_preview_texture.xml4
-rw-r--r--indra/newview/skins/default/xui/pt/floater_region_info.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_report_abuse.xml162
-rw-r--r--indra/newview/skins/default/xui/pt/floater_script_debug.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_script_preview.xml4
-rw-r--r--indra/newview/skins/default/xui/pt/floater_script_queue.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_script_search.xml16
-rw-r--r--indra/newview/skins/default/xui/pt/floater_sell_land.xml26
-rw-r--r--indra/newview/skins/default/xui/pt/floater_settings_debug.xml10
-rw-r--r--indra/newview/skins/default/xui/pt/floater_snapshot.xml130
-rw-r--r--indra/newview/skins/default/xui/pt/floater_sound_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_statistics.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_telehub.xml18
-rw-r--r--indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml6
-rw-r--r--indra/newview/skins/default/xui/pt/floater_tools.xml503
-rw-r--r--indra/newview/skins/default/xui/pt/floater_top_objects.xml15
-rw-r--r--indra/newview/skins/default/xui/pt/floater_tos.xml3
-rw-r--r--indra/newview/skins/default/xui/pt/floater_url_entry.xml1
-rw-r--r--indra/newview/skins/default/xui/pt/floater_water.xml25
-rw-r--r--indra/newview/skins/default/xui/pt/floater_wearable_save_as.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_windlight_options.xml25
-rw-r--r--indra/newview/skins/default/xui/pt/floater_world_map.xml12
-rw-r--r--indra/newview/skins/default/xui/pt/language_settings.xml55
-rw-r--r--indra/newview/skins/default/xui/pt/menu_login.xml4
-rw-r--r--indra/newview/skins/default/xui/pt/menu_viewer.xml22
-rw-r--r--indra/newview/skins/default/xui/pt/notifications.xml212
-rw-r--r--indra/newview/skins/default/xui/pt/panel_edit_profile.xml45
-rw-r--r--indra/newview/skins/default/xui/pt/panel_friends.xml12
-rw-r--r--indra/newview/skins/default/xui/pt/panel_group_general.xml26
-rw-r--r--indra/newview/skins/default/xui/pt/panel_group_invite.xml10
-rw-r--r--indra/newview/skins/default/xui/pt/panel_group_land_money.xml16
-rw-r--r--indra/newview/skins/default/xui/pt/panel_group_notices.xml25
-rw-r--r--indra/newview/skins/default/xui/pt/panel_group_roles.xml45
-rw-r--r--indra/newview/skins/default/xui/pt/panel_groups.xml17
-rw-r--r--indra/newview/skins/default/xui/pt/panel_login.xml24
-rw-r--r--indra/newview/skins/default/xui/pt/panel_preferences_advanced.xml12
-rw-r--r--indra/newview/skins/default/xui/pt/panel_preferences_alerts.xml18
-rw-r--r--indra/newview/skins/default/xui/pt/panel_preferences_chat.xml62
-rw-r--r--indra/newview/skins/default/xui/pt/panel_preferences_general.xml147
-rw-r--r--indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml102
-rw-r--r--indra/newview/skins/default/xui/pt/panel_preferences_privacy.xml33
-rw-r--r--indra/newview/skins/default/xui/pt/panel_preferences_setup.xml33
-rw-r--r--indra/newview/skins/default/xui/pt/panel_preferences_sound.xml39
-rw-r--r--indra/newview/skins/default/xui/pt/panel_profile.xml14
-rw-r--r--indra/newview/skins/default/xui/pt/panel_region_covenant.xml20
-rw-r--r--indra/newview/skins/default/xui/pt/panel_region_debug.xml10
-rw-r--r--indra/newview/skins/default/xui/pt/panel_region_estate.xml4
-rw-r--r--indra/newview/skins/default/xui/pt/panel_region_general.xml12
-rw-r--r--indra/newview/skins/default/xui/pt/panel_region_terrain.xml10
-rw-r--r--indra/newview/skins/default/xui/pt/panel_region_texture.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/panel_scrolling_param.xml4
-rw-r--r--indra/newview/skins/default/xui/pt/panel_status_bar.xml12
-rw-r--r--indra/newview/skins/default/xui/pt/panel_world_map.xml51
-rw-r--r--indra/newview/skins/default/xui/pt/strings.xml165
-rw-r--r--indra/newview/skins/paths.xml2
-rw-r--r--indra/newview/tests/llagentaccess_test.cpp139
-rw-r--r--indra/newview/tests/llcapabilitylistener_test.cpp276
-rw-r--r--indra/newview/tests/lldateutil_test.cpp192
-rw-r--r--indra/newview/tests/lllogininstance_test.cpp424
-rw-r--r--indra/newview/tests/llmediadataclient_test.cpp938
-rw-r--r--indra/newview/tests/lltextureinfo_test.cpp284
-rw-r--r--indra/newview/tests/lltextureinfodetails_test.cpp98
-rw-r--r--indra/newview/tests/lltexturestatsuploader_test.cpp156
-rw-r--r--indra/newview/tests/llviewerhelputil_test.cpp173
-rw-r--r--indra/newview/tests/llworldmap_test.cpp523
-rw-r--r--indra/newview/tests/llworldmipmap_test.cpp176
-rw-r--r--indra/newview/tests/llxmlrpclistener_test.cpp230
-rw-r--r--indra/newview/tests/test_llxmlrpc_peer.py59
-rw-r--r--indra/newview/tr.lproj/language.txt1
-rw-r--r--indra/newview/uk.lproj/language.txt1
-rwxr-xr-xindra/newview/viewer_manifest.py614
-rw-r--r--indra/newview/zh-Hans.lproj/language.txt1
-rw-r--r--indra/test/CMakeLists.txt59
-rw-r--r--indra/test/debug.h68
-rwxr-xr-xindra/test/lldoubledispatch_tut.cpp245
-rw-r--r--indra/test/llevents_tut.cpp722
-rw-r--r--indra/test/llhttpclient_tut.cpp4
-rw-r--r--indra/test/llhttpdate_tut.cpp72
-rw-r--r--indra/test/llpermissions_tut.cpp11
-rw-r--r--indra/test/llsaleinfo_tut.cpp15
-rw-r--r--indra/test/llscriptresource_tut.cpp7
-rwxr-xr-xindra/test/llsdmessagebuilder_tut.cpp52
-rwxr-xr-xindra/test/llsdmessagereader_tut.cpp1
-rw-r--r--indra/test/llsdutil_tut.cpp235
-rw-r--r--indra/test/lltimestampcache_tut.cpp7
-rw-r--r--indra/test/lltranscode_tut.cpp7
-rw-r--r--indra/test/lltut.cpp12
-rw-r--r--indra/test/lltut.h5
-rw-r--r--indra/test/test.cpp43
-rw-r--r--indra/test/test.h5
-rw-r--r--indra/test_apps/llplugintest/CMakeLists.txt539
-rw-r--r--indra/test_apps/llplugintest/bookmarks.txt37
-rw-r--r--indra/test_apps/llplugintest/llmediaplugintest.cpp2207
-rw-r--r--indra/test_apps/llplugintest/llmediaplugintest.h201
-rw-r--r--indra/viewer_components/CMakeLists.txt5
-rw-r--r--indra/viewer_components/login/CMakeLists.txt56
-rw-r--r--indra/viewer_components/login/lllogin.cpp423
-rw-r--r--indra/viewer_components/login/lllogin.h133
-rw-r--r--indra/viewer_components/login/tests/lllogin_test.cpp481
-rw-r--r--indra/win_crash_logger/CMakeLists.txt4
-rw-r--r--indra/win_updater/CMakeLists.txt3
-rw-r--r--install.xml317
-rwxr-xr-xscripts/install.py19
-rw-r--r--scripts/messages/message_template.msg27
-rwxr-xr-xscripts/template_verifier.py9
-rwxr-xr-xscripts/update_version_files.py42
4138 files changed, 404520 insertions, 117912 deletions
diff --git a/.hgignore b/.hgignore
new file mode 100644
index 0000000000..53ddf71bb7
--- /dev/null
+++ b/.hgignore
@@ -0,0 +1,62 @@
+syntax: glob
+
+# WinMerge temp files
+*.bak
+# Compiled python bytecode
+*.pyc
+# Emacs temp files
+*~
+.*.swp
+#OSX image cache file
+*.DS_Store
+LICENSES
+indra/.distcc
+indra/build-darwin-*
+indra/build-vc[0-9]*
+indra/CMakeFiles
+indra/lib/mono/1.0/*.dll
+indra/lib/mono/indra/*.dll
+indra/lib/mono/indra/*.exe
+indra/lib/mono/indra/*.pdb
+indra/lib/python/eventlet/
+indra/llwindow/glh/glh_linear.h
+indra/newview/app_settings/mozilla
+indra/newview/app_settings/mozilla-runtime-*
+indra/newview/app_settings/mozilla_debug
+indra/newview/app_settings/static_*.db2
+indra/newview/browser_profile
+indra/newview/character
+indra/newview/fmod.dll
+indra/newview/mozilla-theme
+indra/newview/mozilla-universal-darwin.tgz
+indra/newview/res-sdl
+indra/newview/vivox-runtime
+indra/server-linux-*
+indra/temp
+indra/test/linden_file.dat
+indra/test_apps/llmediatest/dependencies/i686-win32
+indra/test_apps/terrain_mule/*.dll
+indra/viewer-linux-*
+indra/web/doc/asset-upload/plugins/lsl_compiler/lslc
+indra/web/doc/asset-upload/plugins/verify-notecard
+indra/web/doc/asset-upload/plugins/verify-texture
+installed.xml
+libraries
+tarfile_tmp
+^indra/lib/python/mulib.*
+^web/locale.*
+^web/secondlife.com.*
+^web/config.*
+^indra/web/dataservice/locale.*
+^indra/web/dataservice/lib/shared/vault.*
+^indra/web/dataservice/vendor.*
+glob:indra/newview/dbghelp.dll
+glob:*.cpp.orig
+glob:*.cpp.bak
+glob:*.h.bak
+glob:*.h.orig
+glob:indra/newview/typed_locations.txt
+glob:indra/newview/teleport_history.txt
+glob:indra/newview/search_history.txt
+glob:indra/newview/filters.xml
+glob:indra/newview/avatar_icons_cache.txt
diff --git a/doc/contributions.txt b/doc/contributions.txt
index 4b97e78b0f..a5b0a10e69 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -1,7 +1,7 @@
Linden Lab would like to acknowledge source code contributions from the
-following residents. The Second Life resident name is given below,
+following residents. The Second Life resident name is given below,
along with the issue identifier corresponding to the patches we've
-received from them. To see more about these contributions, visit the
+received from them. To see more about these contributions, visit the
browsable version: http://wiki.secondlife.com/wiki/Source_contributions
Able Whitman
@@ -25,27 +25,37 @@ Aimee Trescothick
VWR-6348
VWR-6358
VWR-6360
+ VWR-6432
VWR-6550
VWR-6583
VWR-6482
VWR-7109
VWR-7383
+ VWR-7800
+ VWR-8008
VWR-8341
VWR-8430
VWR-8482
VWR-9255
+ VWR-10717
VWR-10990
VWR-11100
VWR-11111
- VWR-11844
+ VWR-11844
+ VWR-14267
+ VWR-14278
+ VWR-14087
Alejandro Rosenthal
VWR-1184
Aleric Inglewood
VWR-10001
VWR-10759
VWR-10837
+ VWR-12691
+ VWR-13996
+ VWR-14426
Ales Beaumont
- VWR-9352
+ VWR-9352
Alissa Sabre
VWR-81
VWR-83
@@ -67,7 +77,7 @@ Alissa Sabre
VWR-1351
VWR-1353
VWR-1410
- VWR-1843
+ VWR-1843
VWR-2116
VWR-2826
VWR-3290
@@ -75,19 +85,25 @@ Alissa Sabre
VWR-3857
VWR-4010
VWR-5575
- VWR-5929
- VWR-6384
- VWR-6385
+ VWR-5717
+ VWR-5929
+ VWR-6384
+ VWR-6385
VWR-6386
- VWR-6430
+ VWR-6430
VWR-6858
- VWR-6668
- VWR-7086
- VWR-7087
- VWR-7153
- VWR-7168
+ VWR-6668
+ VWR-7086
+ VWR-7087
+ VWR-7153
+ VWR-7168
VWR-9190
VWR-10728
+ VWR-11172
+ VWR-12569
+ VWR-12617
+ VWR-12620
+ VWR-12789
Angus Boyd
VWR-592
Ann Congrejo
@@ -123,6 +139,7 @@ Blakar Ogre
blino Nakamura
VWR-17
Boroondas Gupte
+ SNOW-278
VWR-233
WEB-262
Bulli Schumann
@@ -145,6 +162,7 @@ Carjay McGinnis
VWR-4212
VWR-6154
VWR-9400
+ VWR-9620
Catherine Pfeffer
VWR-1282
VWR-8624
@@ -197,6 +215,7 @@ Feep Larsson
VWR-4444
Flemming Congrejo
CT-193
+ CT-318
Fluf Fredriksson
VWR-3450
Fremont Cunningham
@@ -274,7 +293,11 @@ Jacek Antonelli
VWR-597
VWR-2054
VWR-2448
+ VWR-2896
+ VWR-2947
+ VWR-2948
VWR-3605
+ VWR-8617
JB Kraft
VWR-5283
VWR-7802
@@ -288,6 +311,7 @@ Kerutsen Sellery
VWR-1350
Khyota Wulluf
VWR-2085
+ VWR-8885
VWR-9256
VWR-9966
Kunnis Basiat
@@ -330,6 +354,7 @@ McCabe Maxsted
VWR-7877
VWR-7893
VWR-8080
+ VWR-8454
VWR-8689
VWR-9007
Michelle2 Zenovka
@@ -344,12 +369,15 @@ Michelle2 Zenovka
VWR-5082
VWR-5659
VWR-7831
+ VWR-8885
VWR-8889
VWR-8310
VWR-9499
Mm Alder
+ VWR-197
VWR-3777
VWR-4794
+ VWR-13578
Mr Greggan
VWR-445
Nicholaz Beresford
@@ -457,7 +485,7 @@ Pf Shan
CT-321
princess niven
VWR-5733
- CT-85
+ CT-85
CT-320
CT-352
Renault Clio
@@ -472,9 +500,17 @@ Ringo Tuxing
CT-231
CT-321
Robin Cornelius
+ SNOW-108
+ SNOW-204
+ SNOW-287
+ SNOW-512
VWR-2488
VWR-9557
+ VWR-11128
+ VWR-12533
VWR-12587
+ VWR-12763
+ VWR-12995
VWR-20911
Ryozu Kojima
VWR-53
@@ -546,6 +582,8 @@ Strife Onizuka
VWR-183
VWR-2265
VWR-4111
+Tayra Dagostino
+ VWR-13947
TBBle Kurosawa
VWR-938
VWR-941
@@ -556,12 +594,18 @@ TBBle Kurosawa
VWR-1892
Teardrops Fall
VWR-5366
+Techwolf Lupindo
+ SNOW-92
+ VWR-12385
tenebrous pau
VWR-247
Tharax Ferraris
VWR-605
Thickbrick Sleaford
VWR-7109
+ VWR-9287
+ VWR-13483
+ VWR-13947
Thraxis Epsilon
SVC-371
VWR-383
diff --git a/etc/message.xml b/etc/message.xml
index 4af5bd5296..c17ae3656d 100644
--- a/etc/message.xml
+++ b/etc/message.xml
@@ -50,7 +50,7 @@
<key>OpenCircuit</key>
<map>
<key>flavor</key>
- <string>template</string>
+ <string>llsd</string>
<key>trusted-sender</key>
<boolean>false</boolean>
</map>
@@ -377,7 +377,23 @@
<key>trusted-sender</key>
<boolean>true</boolean>
</map>
+
+ <key>ParcelMediaURLFilter</key>
+ <map>
+ <key>flavor</key>
+ <string>llsd</string>
+ <key>trusted-sender</key>
+ <boolean>false</boolean>
+ </map>
+ <key>ParcelNavigateMedia</key>
+ <map>
+ <key>flavor</key>
+ <string>llsd</string>
+ <key>trusted-sender</key>
+ <boolean>false</boolean>
+ </map>
+
<key>ParcelObjectOwnersReply</key>
<map>
<key>flavor</key>
@@ -652,7 +668,17 @@
<key>FetchLib</key>
<boolean>true</boolean>
- </map>
+
+ <key>UploadBakedTexture</key>
+ <boolean>true</boolean>
+
+ <key>ObjectMedia</key>
+ <boolean>false</boolean>
+
+ <key>ObjectMediaNavigate</key>
+ <boolean>false</boolean>
+
+ </map>
<key>messageBans</key>
<map>
diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
index 7f4c2c33c1..261c0b17e2 100644
--- a/indra/CMakeLists.txt
+++ b/indra/CMakeLists.txt
@@ -1,3 +1,4 @@
+
# -*- cmake -*-
# cmake_minimum_required should appear before any
@@ -42,7 +43,6 @@ add_subdirectory(${LIBS_OPEN_PREFIX}llimage)
add_subdirectory(${LIBS_OPEN_PREFIX}llimagej2coj)
add_subdirectory(${LIBS_OPEN_PREFIX}llinventory)
add_subdirectory(${LIBS_OPEN_PREFIX}llmath)
-add_subdirectory(${LIBS_OPEN_PREFIX}llmedia)
add_subdirectory(${LIBS_OPEN_PREFIX}llmessage)
add_subdirectory(${LIBS_OPEN_PREFIX}llprimitive)
add_subdirectory(${LIBS_OPEN_PREFIX}llrender)
@@ -63,11 +63,23 @@ endif (WINDOWS AND EXISTS ${LIBS_CLOSED_DIR}copy_win_scripts)
add_custom_target(viewer)
if (VIEWER)
add_subdirectory(${LIBS_OPEN_PREFIX}llcrashlogger)
+ add_subdirectory(${LIBS_OPEN_PREFIX}llplugin)
add_subdirectory(${LIBS_OPEN_PREFIX}llui)
+ add_subdirectory(${LIBS_OPEN_PREFIX}llxuixml)
+ add_subdirectory(${LIBS_OPEN_PREFIX}viewer_components)
+
+ # viewer media plugins
+ add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins)
+
+ # llplugin testbed code (is this the right way to include it?)
+ if (NOT LINUX)
+ add_subdirectory(${VIEWER_PREFIX}test_apps/llplugintest)
+ endif (NOT LINUX)
if (LINUX)
add_subdirectory(${VIEWER_PREFIX}linux_crash_logger)
- add_dependencies(viewer linux-crash-logger-strip-target)
+ add_subdirectory(${VIEWER_PREFIX}linux_updater)
+ add_dependencies(viewer linux-crash-logger-strip-target linux-updater)
elseif (DARWIN)
add_subdirectory(${VIEWER_PREFIX}mac_crash_logger)
add_subdirectory(${VIEWER_PREFIX}mac_updater)
@@ -110,3 +122,7 @@ if (SERVER)
add_subdirectory(${SERVER_PREFIX}tools)
endif (WINDOWS)
endif (SERVER)
+
+# Define after the custom viewer and server targets are created so individual
+# apps can add themselves as dependencies
+add_subdirectory(${INTEGRATION_TESTS_PREFIX}integration_tests)
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index ad7529ea0a..1f578eec5f 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -35,13 +35,13 @@ if (WINDOWS)
# Don't build DLLs.
set(BUILD_SHARED_LIBS OFF)
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Od /Zi /MDd"
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Od /Zi /MDd /MP"
CACHE STRING "C++ compiler debug options" FORCE)
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO
- "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Od /Zi /MD"
+ "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Od /Zi /MD /MP"
CACHE STRING "C++ compiler release-with-debug options" FORCE)
set(CMAKE_CXX_FLAGS_RELEASE
- "${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /O2 /Zi /MD"
+ "${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /O2 /Zi /MD /MP"
CACHE STRING "C++ compiler release options" FORCE)
set(CMAKE_CXX_STANDARD_LIBRARIES "")
@@ -118,14 +118,15 @@ if (LINUX)
endif (NOT ${GXX_VERSION} MATCHES " 4.1.*Red Hat")
endif (${GXX_VERSION} STREQUAL ${CXX_VERSION})
- # GCC 4.3 introduces a pile of obnoxious new warnings, which we
- # treat as errors due to -Werror. Quiet the most offensive and
- # widespread of them.
+ # Let's actually get a numerical version of gxx's version
+ STRING(REGEX REPLACE ".* ([0-9])\\.([0-9])\\.([0-9]).*" "\\1\\2\\3" CXX_VERSION_NUMBER ${CXX_VERSION})
- if (${CXX_VERSION} MATCHES "4.3")
+ # gcc 4.3 and above don't like the LL boost and also
+ # cause warnings due to our use of deprecated headers
+ if(${CXX_VERSION_NUMBER} GREATER 429)
add_definitions(-Wno-parentheses)
set(CMAKE_CXX_FLAGS "-Wno-deprecated ${CMAKE_CXX_FLAGS}")
- endif (${CXX_VERSION} MATCHES "4.3")
+ endif (${CXX_VERSION_NUMBER} GREATER 429)
# End of hacks.
@@ -170,6 +171,8 @@ if (LINUX)
if (NOT STANDALONE)
# this stops us requiring a really recent glibc at runtime
add_definitions(-fno-stack-protector)
+ # linking can be so slow - give us a chance to figure out why
+ set(CMAKE_CXX_LINK_FLAGS "-Wl,--stats,--no-keep-memory")
endif (NOT STANDALONE)
endif (VIEWER)
@@ -179,11 +182,17 @@ endif (LINUX)
if (DARWIN)
- add_definitions(-DLL_DARWIN=1)
+ # NOTE (per http://lists.apple.com/archives/darwin-dev/2008/Jan/msg00232.html):
+ # > Why the bus error? What am I doing wrong?
+ # This is a known issue where getcontext(3) is writing past the end of the
+ # ucontext_t struct when _XOPEN_SOURCE is not defined (rdar://problem/5578699 ).
+ # As a workaround, define _XOPEN_SOURCE before including ucontext.h.
+ add_definitions(-DLL_DARWIN=1 -D_XOPEN_SOURCE)
set(CMAKE_CXX_LINK_FLAGS "-Wl,-headerpad_max_install_names,-search_paths_first")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mlong-branch")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mlong-branch")
+ set(DARWIN_extra_cstar_flags "-mlong-branch")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DARWIN_extra_cstar_flags}")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${DARWIN_extra_cstar_flags}")
# NOTE: it's critical that the optimization flag is put in front.
# NOTE: it's critical to have both CXX_FLAGS and C_FLAGS covered.
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O0 ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
@@ -192,13 +201,13 @@ endif (DARWIN)
if (LINUX OR DARWIN)
- set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs -Wno-non-virtual-dtor")
+ set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs")
if (NOT GCC_DISABLE_FATAL_WARNINGS)
set(GCC_WARNINGS "${GCC_WARNINGS} -Werror")
endif (NOT GCC_DISABLE_FATAL_WARNINGS)
- set(GCC_CXX_WARNINGS "${GCC_WARNINGS} -Wno-reorder")
+ set(GCC_CXX_WARNINGS "${GCC_WARNINGS} -Wno-reorder -Wno-non-virtual-dtor -Woverloaded-virtual")
set(CMAKE_C_FLAGS "${GCC_WARNINGS} ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${GCC_CXX_WARNINGS} ${CMAKE_CXX_FLAGS}")
@@ -227,7 +236,6 @@ else (STANDALONE)
glib-2.0
gstreamer-0.10
gtk-2.0
- llfreetype2
pango-1.0
)
endif (STANDALONE)
diff --git a/indra/cmake/APR.cmake b/indra/cmake/APR.cmake
index 0755aeee03..f4706dd4f2 100644
--- a/indra/cmake/APR.cmake
+++ b/indra/cmake/APR.cmake
@@ -13,26 +13,38 @@ if (STANDALONE)
else (STANDALONE)
use_prebuilt_binary(apr_suite)
if (WINDOWS)
+ if (LLCOMMON_LINK_SHARED)
+ set(APR_selector "lib")
+ else (LLCOMMON_LINK_SHARED)
+ set(APR_selector "")
+ endif (LLCOMMON_LINK_SHARED)
set(APR_LIBRARIES
- debug ${ARCH_PREBUILT_DIRS_DEBUG}/apr-1.lib
- optimized ${ARCH_PREBUILT_DIRS_RELEASE}/apr-1.lib
+ debug ${ARCH_PREBUILT_DIRS_DEBUG}/${APR_selector}apr-1.lib
+ optimized ${ARCH_PREBUILT_DIRS_RELEASE}/${APR_selector}apr-1.lib
)
set(APRICONV_LIBRARIES
- debug ${ARCH_PREBUILT_DIRS_DEBUG}/apriconv-1.lib
- optimized ${ARCH_PREBUILT_DIRS_RELEASE}/apriconv-1.lib
+ debug ${ARCH_PREBUILT_DIRS_DEBUG}/${APR_selector}apriconv-1.lib
+ optimized ${ARCH_PREBUILT_DIRS_RELEASE}/${APR_selector}apriconv-1.lib
)
set(APRUTIL_LIBRARIES
- debug ${ARCH_PREBUILT_DIRS_DEBUG}/aprutil-1.lib ${APRICONV_LIBRARIES}
- optimized ${ARCH_PREBUILT_DIRS_RELEASE}/aprutil-1.lib ${APRICONV_LIBRARIES}
+ debug ${ARCH_PREBUILT_DIRS_DEBUG}/${APR_selector}aprutil-1.lib ${APRICONV_LIBRARIES}
+ optimized ${ARCH_PREBUILT_DIRS_RELEASE}/${APR_selector}aprutil-1.lib ${APRICONV_LIBRARIES}
)
elseif (DARWIN)
+ if (LLCOMMON_LINK_SHARED)
+ set(APR_selector "0.3.7.dylib")
+ set(APRUTIL_selector "0.3.8.dylib")
+ else (LLCOMMON_LINK_SHARED)
+ set(APR_selector "a")
+ set(APRUTIL_selector "a")
+ endif (LLCOMMON_LINK_SHARED)
set(APR_LIBRARIES
- debug ${ARCH_PREBUILT_DIRS_DEBUG}/libapr-1.a
- optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libapr-1.a
+ debug ${ARCH_PREBUILT_DIRS_DEBUG}/libapr-1.${APR_selector}
+ optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libapr-1.${APR_selector}
)
set(APRUTIL_LIBRARIES
- debug ${ARCH_PREBUILT_DIRS_DEBUG}/libaprutil-1.a
- optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libaprutil-1.a
+ debug ${ARCH_PREBUILT_DIRS_DEBUG}/libaprutil-1.${APRUTIL_selector}
+ optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libaprutil-1.${APRUTIL_selector}
)
set(APRICONV_LIBRARIES iconv)
else (WINDOWS)
diff --git a/indra/cmake/Boost.cmake b/indra/cmake/Boost.cmake
index 0578ae95ff..efe9ad74d3 100644
--- a/indra/cmake/Boost.cmake
+++ b/indra/cmake/Boost.cmake
@@ -15,7 +15,7 @@ else (STANDALONE)
set(Boost_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
if (WINDOWS)
- set(BOOST_VERSION 1_34_1)
+ set(BOOST_VERSION 1_39)
if (MSVC71)
set(BOOST_PROGRAM_OPTIONS_LIBRARY
optimized libboost_program_options-vc71-mt-s-${BOOST_VERSION}
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index 658441dab1..4fc25dcc24 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -16,7 +16,7 @@ set(cmake_SOURCE_FILES
CARes.cmake
CURL.cmake
CMakeCopyIfDifferent.cmake
- CopyWinLibs.cmake
+ Copy3rdPartyLibs.cmake
CSharpMacros.cmake
DBusGlib.cmake
DirectX.cmake
@@ -34,7 +34,7 @@ set(cmake_SOURCE_FILES
FindXmlRpcEpi.cmake
FMOD.cmake
FreeType.cmake
- GStreamer.cmake
+ GStreamer010Plugin.cmake
GooglePerfTools.cmake
JPEG.cmake
LLAddBuildTest.cmake
@@ -48,11 +48,12 @@ set(cmake_SOURCE_FILES
LLInventory.cmake
LLKDU.cmake
LLMath.cmake
- LLMedia.cmake
LLMessage.cmake
+ LLPlugin.cmake
LLPrimitive.cmake
LLRender.cmake
LLScene.cmake
+ LLTestCommand.cmake
LLUI.cmake
LLVFS.cmake
LLWindow.cmake
@@ -60,7 +61,6 @@ set(cmake_SOURCE_FILES
LScript.cmake
Linking.cmake
MonoEmbed.cmake
- Mozlib.cmake
MySQL.cmake
NDOF.cmake
OPENAL.cmake
@@ -70,8 +70,6 @@ set(cmake_SOURCE_FILES
PNG.cmake
Python.cmake
Prebuilt.cmake
- QuickTime.cmake
- RunBuildTest.cmake
TemplateCheck.cmake
Tut.cmake
UI.cmake
diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
new file mode 100644
index 0000000000..faf9da8b14
--- /dev/null
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -0,0 +1,395 @@
+# -*- cmake -*-
+
+# The copy_win_libs folder contains file lists and a script used to
+# copy dlls, exes and such needed to run the SecondLife from within
+# VisualStudio.
+
+include(CMakeCopyIfDifferent)
+
+###################################################################
+# set up platform specific lists of files that need to be copied
+###################################################################
+if(WINDOWS)
+ set(SHARED_LIB_STAGING_DIR_DEBUG "${SHARED_LIB_STAGING_DIR}/Debug")
+ set(SHARED_LIB_STAGING_DIR_RELWITHDEBINFO "${SHARED_LIB_STAGING_DIR}/RelWithDebInfo")
+ set(SHARED_LIB_STAGING_DIR_RELEASE "${SHARED_LIB_STAGING_DIR}/Release")
+
+ #*******************************
+ # VIVOX - *NOTE: no debug version
+ set(vivox_src_dir "${CMAKE_SOURCE_DIR}/newview/vivox-runtime/i686-win32")
+ set(vivox_files
+ SLVoice.exe
+ libsndfile-1.dll
+ vivoxplatform.dll
+ vivoxsdk.dll
+ ortp.dll
+ zlib1.dll
+ vivoxoal.dll
+ )
+
+ #*******************************
+ # Misc shared libs
+
+ # *TODO - update this to use LIBS_PREBUILT_DIR and LL_ARCH_DIR variables
+ # or ARCH_PREBUILT_DIRS
+ set(debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug")
+ set(debug_files
+ openjpegd.dll
+ libapr-1.dll
+ libaprutil-1.dll
+ libapriconv-1.dll
+ )
+
+ # *TODO - update this to use LIBS_PREBUILT_DIR and LL_ARCH_DIR variables
+ # or ARCH_PREBUILT_DIRS
+ set(release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release")
+ set(release_files
+ openjpeg.dll
+ libapr-1.dll
+ libaprutil-1.dll
+ libapriconv-1.dll
+ )
+
+ if(USE_GOOGLE_PERFTOOLS)
+ set(debug_files ${debug_files} libtcmalloc_minimal-debug.dll)
+ set(release_files ${release_files} libtcmalloc_minimal.dll)
+ endif(USE_GOOGLE_PERFTOOLS)
+
+ if (FMOD_SDK_DIR)
+ set(fmod_files fmod.dll)
+ endif (FMOD_SDK_DIR)
+
+ #*******************************
+ # LLKDU
+ set(internal_llkdu_path "${CMAKE_SOURCE_DIR}/llkdu")
+ if(NOT EXISTS ${internal_llkdu_path})
+ if (EXISTS "${debug_src_dir}/llkdu.dll")
+ set(debug_llkdu_src "${debug_src_dir}/llkdu.dll")
+ set(debug_llkdu_dst "${SHARED_LIB_STAGING_DIR_DEBUG}/llkdu.dll")
+ endif (EXISTS "${debug_src_dir}/llkdu.dll")
+
+ if (EXISTS "${release_src_dir}/llkdu.dll")
+ set(release_llkdu_src "${release_src_dir}/llkdu.dll")
+ set(release_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELEASE}/llkdu.dll")
+ set(relwithdebinfo_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}/llkdu.dll")
+ endif (EXISTS "${release_src_dir}/llkdu.dll")
+ endif (NOT EXISTS ${internal_llkdu_path})
+
+#*******************************
+# Copy MS C runtime dlls, required for packaging.
+# *TODO - Adapt this to support VC9
+if (MSVC80)
+ FIND_PATH(debug_msvc8_redist_path msvcr80d.dll
+ PATHS
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0\\Setup\\VC;ProductDir]/redist/Debug_NonRedist/x86/Microsoft.VC80.DebugCRT
+ NO_DEFAULT_PATH
+ NO_DEFAULT_PATH
+ )
+
+ if(EXISTS ${debug_msvc8_redist_path})
+ set(debug_msvc8_files
+ msvcr80d.dll
+ msvcp80d.dll
+ Microsoft.VC80.DebugCRT.manifest
+ )
+
+ copy_if_different(
+ ${debug_msvc8_redist_path}
+ "${SHARED_LIB_STAGING_DIR_DEBUG}"
+ out_targets
+ ${debug_msvc8_files}
+ )
+ set(third_party_targets ${third_party_targets} ${out_targets})
+
+ endif (EXISTS ${debug_msvc8_redist_path})
+
+ FIND_PATH(release_msvc8_redist_path msvcr80.dll
+ PATHS
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0\\Setup\\VC;ProductDir]/redist/x86/Microsoft.VC80.CRT
+ NO_DEFAULT_PATH
+ NO_DEFAULT_PATH
+ )
+
+ if(EXISTS ${release_msvc8_redist_path})
+ set(release_msvc8_files
+ msvcr80.dll
+ msvcp80.dll
+ Microsoft.VC80.CRT.manifest
+ )
+
+ copy_if_different(
+ ${release_msvc8_redist_path}
+ "${SHARED_LIB_STAGING_DIR_RELEASE}"
+ out_targets
+ ${release_msvc8_files}
+ )
+ set(third_party_targets ${third_party_targets} ${out_targets})
+
+ copy_if_different(
+ ${release_msvc8_redist_path}
+ "${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}"
+ out_targets
+ ${release_msvc8_files}
+ )
+ set(third_party_targets ${third_party_targets} ${out_targets})
+
+ endif (EXISTS ${release_msvc8_redist_path})
+endif (MSVC80)
+
+elseif(DARWIN)
+ set(SHARED_LIB_STAGING_DIR_DEBUG "${SHARED_LIB_STAGING_DIR}/Debug/Resources")
+ set(SHARED_LIB_STAGING_DIR_RELWITHDEBINFO "${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/Resources")
+ set(SHARED_LIB_STAGING_DIR_RELEASE "${SHARED_LIB_STAGING_DIR}/Release/Resources")
+
+ set(vivox_src_dir "${CMAKE_SOURCE_DIR}/newview/vivox-runtime/universal-darwin")
+ set(vivox_files
+ SLVoice
+ libsndfile.dylib
+ libvivoxoal.dylib
+ libortp.dylib
+ libvivoxplatform.dylib
+ libvivoxsdk.dylib
+ )
+ # *TODO - update this to use LIBS_PREBUILT_DIR and LL_ARCH_DIR variables
+ # or ARCH_PREBUILT_DIRS
+ set(debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_debug")
+ set(debug_files
+ )
+ # *TODO - update this to use LIBS_PREBUILT_DIR and LL_ARCH_DIR variables
+ # or ARCH_PREBUILT_DIRS
+ set(release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release")
+ set(release_files
+ libapr-1.0.3.7.dylib
+ libapr-1.dylib
+ libaprutil-1.0.3.8.dylib
+ libaprutil-1.dylib
+ libexpat.0.5.0.dylib
+ libexpat.dylib
+ libllqtwebkit.dylib
+ libndofdev.dylib
+ )
+
+ # fmod is statically linked on darwin
+ set(fmod_files "")
+
+ #*******************************
+ # LLKDU
+ set(internal_llkdu_path "${CMAKE_SOURCE_DIR}/llkdu")
+ if(NOT EXISTS ${internal_llkdu_path})
+ if (EXISTS "${debug_src_dir}/libllkdu.dylib")
+ set(debug_llkdu_src "${debug_src_dir}/libllkdu.dylib")
+ set(debug_llkdu_dst "${SHARED_LIB_STAGING_DIR_DEBUG}/libllkdu.dylib")
+ endif (EXISTS "${debug_src_dir}/libllkdu.dylib")
+
+ if (EXISTS "${release_src_dir}/libllkdu.dylib")
+ set(release_llkdu_src "${release_src_dir}/libllkdu.dylib")
+ set(release_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELEASE}/libllkdu.dylib")
+ set(relwithdebinfo_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}/libllkdu.dylib")
+ endif (EXISTS "${release_src_dir}/libllkdu.dylib")
+ endif (NOT EXISTS ${internal_llkdu_path})
+elseif(LINUX)
+ # linux is weird, multiple side by side configurations aren't supported
+ # and we don't seem to have any debug shared libs built yet anyways...
+ set(SHARED_LIB_STAGING_DIR_DEBUG "${SHARED_LIB_STAGING_DIR}")
+ set(SHARED_LIB_STAGING_DIR_RELWITHDEBINFO "${SHARED_LIB_STAGING_DIR}")
+ set(SHARED_LIB_STAGING_DIR_RELEASE "${SHARED_LIB_STAGING_DIR}")
+
+ set(vivox_src_dir "${CMAKE_SOURCE_DIR}/newview/vivox-runtime/i686-linux")
+ set(vivox_files
+ libsndfile.so.1
+ libortp.so
+ libvivoxoal.so.1
+ libvivoxplatform.so
+ libvivoxsdk.so
+ SLVoice
+ )
+ # *TODO - update this to use LIBS_PREBUILT_DIR and LL_ARCH_DIR variables
+ # or ARCH_PREBUILT_DIRS
+ set(debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-linux/lib_debug")
+ set(debug_files
+ )
+ # *TODO - update this to use LIBS_PREBUILT_DIR and LL_ARCH_DIR variables
+ # or ARCH_PREBUILT_DIRS
+ set(release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-linux/lib_release_client")
+ # *FIX - figure out what to do with duplicate libalut.so here -brad
+ set(release_files
+ libapr-1.so.0
+ libaprutil-1.so.0
+ libatk-1.0.so
+ libcrypto.so.0.9.7
+ libdb-4.2.so
+ libexpat.so
+ libgmock_main.so
+ libgmock.so.0
+ libgmodule-2.0.so
+ libgobject-2.0.so
+ libgtest_main.so
+ libgtest.so.0
+ libopenal.so
+ libopenjpeg.so
+ libssl.so
+ libstacktrace.so
+ libtcmalloc.so
+ libuuid.so.1
+ libssl.so.0.9.7
+ )
+
+ if (FMOD_SDK_DIR)
+ set(fmod_files "libfmod-3.75.so")
+ endif (FMOD_SDK_DIR)
+
+ #*******************************
+ # LLKDU
+ set(internal_llkdu_path "${CMAKE_SOURCE_DIR}/llkdu")
+ if(NOT EXISTS ${internal_llkdu_path})
+ if (EXISTS "${debug_src_dir}/libllkdu.so")
+ set(debug_llkdu_src "${debug_src_dir}/libllkdu.so")
+ set(debug_llkdu_dst "${SHARED_LIB_STAGING_DIR_DEBUG}/libllkdu.so")
+ endif (EXISTS "${debug_src_dir}/libllkdu.so")
+
+ if (EXISTS "${release_src_dir}/libllkdu.so")
+ set(release_llkdu_src "${release_src_dir}/libllkdu.so")
+ set(release_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELEASE}/libllkdu.so")
+ set(relwithdebinfo_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}/libllkdu.so")
+ endif (EXISTS "${release_src_dir}/libllkdu.so")
+ endif(NOT EXISTS ${internal_llkdu_path})
+else(WINDOWS)
+ message(STATUS "WARNING: unrecognized platform for staging 3rd party libs, skipping...")
+ set(vivox_src_dir "${CMAKE_SOURCE_DIR}/newview/vivox-runtime/i686-linux")
+ set(vivox_files "")
+ # *TODO - update this to use LIBS_PREBUILT_DIR and LL_ARCH_DIR variables
+ # or ARCH_PREBUILT_DIRS
+ set(debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-linux/lib/debug")
+ set(debug_files "")
+ # *TODO - update this to use LIBS_PREBUILT_DIR and LL_ARCH_DIR variables
+ # or ARCH_PREBUILT_DIRS
+ set(release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-linux/lib/release")
+ set(release_files "")
+
+ set(fmod_files "")
+
+ set(debug_llkdu_src "")
+ set(debug_llkdu_dst "")
+ set(release_llkdu_src "")
+ set(release_llkdu_dst "")
+ set(relwithdebinfo_llkdu_dst "")
+endif(WINDOWS)
+
+
+################################################################
+# Done building the file lists, now set up the copy commands.
+################################################################
+
+copy_if_different(
+ ${vivox_src_dir}
+ "${SHARED_LIB_STAGING_DIR_DEBUG}"
+ out_targets
+ ${vivox_files}
+ )
+set(third_party_targets ${third_party_targets} ${out_targets})
+
+copy_if_different(
+ ${vivox_src_dir}
+ "${SHARED_LIB_STAGING_DIR_RELEASE}"
+ out_targets
+ ${vivox_files}
+ )
+set(third_party_targets ${third_party_targets} ${out_targets})
+
+copy_if_different(
+ ${vivox_src_dir}
+ "${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}"
+ out_targets
+ ${vivox_files}
+ )
+set(third_party_targets ${third_party_targets} ${out_targets})
+
+
+
+copy_if_different(
+ ${debug_src_dir}
+ "${SHARED_LIB_STAGING_DIR_DEBUG}"
+ out_targets
+ ${debug_files}
+ )
+set(third_party_targets ${third_party_targets} ${out_targets})
+
+copy_if_different(
+ ${release_src_dir}
+ "${SHARED_LIB_STAGING_DIR_RELEASE}"
+ out_targets
+ ${release_files}
+ )
+set(third_party_targets ${third_party_targets} ${out_targets})
+
+copy_if_different(
+ ${release_src_dir}
+ "${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}"
+ out_targets
+ ${release_files}
+ )
+set(third_party_targets ${third_party_targets} ${out_targets})
+
+if (FMOD_SDK_DIR)
+ copy_if_different(
+ ${FMOD_SDK_DIR}
+ "${CMAKE_CURRENT_BINARY_DIR}/Debug"
+ out_targets
+ ${fmod_files}
+ )
+ set(all_targets ${all_targets} ${out_targets})
+ copy_if_different(
+ ${FMOD_SDK_DIR}
+ "${CMAKE_CURRENT_BINARY_DIR}/Release"
+ out_targets
+ ${fmod_files}
+ )
+ set(all_targets ${all_targets} ${out_targets})
+ copy_if_different(
+ ${FMOD_SDK_DIR}
+ "${CMAKE_CURRENT_BINARY_DIR}/RelWithDbgInfo"
+ out_targets
+ ${fmod_files}
+ )
+ set(all_targets ${all_targets} ${out_targets})
+endif (FMOD_SDK_DIR)
+
+#*******************************
+# LLKDU
+set(internal_llkdu_path "${CMAKE_SOURCE_DIR}/llkdu")
+if(NOT EXISTS ${internal_llkdu_path})
+ if (EXISTS "${debug_llkdu_src}")
+ ADD_CUSTOM_COMMAND(
+ OUTPUT ${debug_llkdu_dst}
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${debug_llkdu_src} ${debug_llkdu_dst}
+ DEPENDS ${debug_llkdu_src}
+ COMMENT "Copying llkdu.dll ${SHARED_LIB_STAGING_DIR_DEBUG}"
+ )
+ set(third_party_targets ${third_party_targets} $} ${debug_llkdu_dst})
+ endif (EXISTS "${debug_llkdu_src}")
+
+ if (EXISTS "${release_llkdu_src}")
+ ADD_CUSTOM_COMMAND(
+ OUTPUT ${release_llkdu_dst}
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${release_llkdu_src} ${release_llkdu_dst}
+ DEPENDS ${release_llkdu_src}
+ COMMENT "Copying llkdu.dll ${SHARED_LIB_STAGING_DIR_RELEASE}"
+ )
+ set(third_party_targets ${third_party_targets} ${release_llkdu_dst})
+
+ ADD_CUSTOM_COMMAND(
+ OUTPUT ${relwithdebinfo_llkdu_dst}
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${release_llkdu_src} ${relwithdebinfo_llkdu_dst}
+ DEPENDS ${release_llkdu_src}
+ COMMENT "Copying llkdu.dll ${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}"
+ )
+ set(third_party_targets ${third_party_targets} ${relwithdebinfo_llkdu_dst})
+ endif (EXISTS "${release_llkdu_src}")
+
+endif (NOT EXISTS ${internal_llkdu_path})
+
+
+add_custom_target(stage_third_party_libs ALL
+ DEPENDS
+ ${third_party_targets}
+ )
diff --git a/indra/cmake/DeploySharedLibs.cmake b/indra/cmake/DeploySharedLibs.cmake
new file mode 100644
index 0000000000..663c272e50
--- /dev/null
+++ b/indra/cmake/DeploySharedLibs.cmake
@@ -0,0 +1,73 @@
+# DeploySharedLibs.cmake
+# This is a script to be run at build time! Its not part of the cmake configuration!
+# See indra/cmake/LLSharedLibs.cmake for a macro that simplifies adding a command to a target to run this script.
+
+# This script requires a few cmake variable to be set on the command line:
+# BIN_NAME= The full path the the binary to search for dependecies.
+# SEARCH_DIRS= The full paths to dirs to search for dependencies.
+# DST_PATH= The full path where the dependecies will be copied.
+
+# *FIX:Mani - I pulled in the CMake 2.8 GetPrerequisites.cmake script here, because it works on windows where 2.6 did not.
+# Once we have officially upgraded to 2.8 we can just use that version of GetPrerequisites.cmake.
+get_filename_component(current_dir ${CMAKE_CURRENT_LIST_FILE} PATH)
+include(${current_dir}/GetPrerequisites_2_8.cmake)
+
+message("Getting recursive dependencies for file: ${BIN_NAME}")
+
+set(EXCLUDE_SYSTEM 1)
+set(RECURSE 1)
+get_filename_component(EXE_PATH ${BIN_NAME} PATH)
+
+get_prerequisites( ${BIN_NAME} RESULTS ${EXCLUDE_SYSTEM} ${RECURSE} "${EXE_PATH}" "${SEARCH_DIRS}" )
+
+foreach(DEP ${RESULTS})
+ Message("Processing dependency: ${DEP}")
+ get_filename_component(DEP_FILE ${DEP} NAME)
+ set(DEP_FILES ${DEP_FILES} ${DEP_FILE})
+endforeach(DEP)
+
+if(DEP_FILES)
+ list(REMOVE_DUPLICATES DEP_FILES)
+endif(DEP_FILES)
+
+foreach(DEP_FILE ${DEP_FILES})
+ if(FOUND_FILES)
+ list(FIND FOUND_FILES ${DEP_FILE} FOUND)
+ else(FOUND_FILES)
+ set(FOUND -1)
+ endif(FOUND_FILES)
+
+ if(FOUND EQUAL -1)
+ find_path(DEP_PATH ${DEP_FILE} PATHS ${SEARCH_DIRS} NO_DEFAULT_PATH)
+ if(DEP_PATH)
+ set(FOUND_FILES ${FOUND_FILES} "${DEP_PATH}/${DEP_FILE}")
+ set(DEP_PATH NOTFOUND) #reset DEP_PATH for the next find_path call.
+ else(DEP_PATH)
+ set(MISSING_FILES ${MISSING_FILES} ${DEP_FILE})
+ endif(DEP_PATH)
+ endif(FOUND EQUAL -1)
+endforeach(DEP_FILE)
+
+if(MISSING_FILES)
+ message("Missing:")
+ foreach(FILE ${MISSING_FILES})
+ message(" ${FILE}")
+ endforeach(FILE)
+ message("Searched in:")
+ foreach(SEARCH_DIR ${SEARCH_DIRS})
+ message(" ${SEARCH_DIR}")
+ endforeach(SEARCH_DIR)
+ message(FATAL_ERROR "Failed")
+endif(MISSING_FILES)
+
+if(FOUND_FILES)
+ foreach(FILE ${FOUND_FILES})
+ get_filename_component(DST_FILE ${FILE} NAME)
+ set(DST_FILE "${DST_PATH}/${DST_FILE}")
+ message("Copying ${FILE} to ${DST_FILE}")
+ execute_process(
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${FILE} ${DST_FILE}
+ )
+ endforeach(FILE ${FOUND_FILES})
+endif(FOUND_FILES)
+message("Success!")
diff --git a/indra/cmake/ExamplePlugin.cmake b/indra/cmake/ExamplePlugin.cmake
new file mode 100644
index 0000000000..599787ad21
--- /dev/null
+++ b/indra/cmake/ExamplePlugin.cmake
@@ -0,0 +1,16 @@
+# -*- cmake -*-
+include(Linking)
+include(Prebuilt)
+
+if (STANDALONE)
+ set(EXAMPLEPLUGIN OFF CACHE BOOL
+ "EXAMPLEPLUGIN support for the llplugin/llmedia test apps.")
+else (STANDALONE)
+ set(EXAMPLEPLUGIN ON CACHE BOOL
+ "EXAMPLEPLUGIN support for the llplugin/llmedia test apps.")
+endif (STANDALONE)
+
+if (WINDOWS)
+elseif (DARWIN)
+elseif (LINUX)
+endif (WINDOWS)
diff --git a/indra/cmake/Externals.cmake b/indra/cmake/Externals.cmake
new file mode 100644
index 0000000000..26f3b56049
--- /dev/null
+++ b/indra/cmake/Externals.cmake
@@ -0,0 +1,34 @@
+# -*- cmake -*-
+
+include(Python)
+include(FindSVN)
+
+macro (use_svn_external _binary _path _url _rev)
+ if (NOT STANDALONE)
+ if(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed)
+ if(SVN_FOUND)
+ if(DEBUG_EXTERNALS)
+ message("cd ${_path} && ${SVN_EXECUTABLE} checkout -r ${_rev} ${_url} ${_binary}")
+ endif(DEBUG_EXTERNALS)
+ execute_process(COMMAND ${SVN_EXECUTABLE}
+ checkout
+ -r ${_rev}
+ ${_url}
+ ${_binary}
+ WORKING_DIRECTORY ${_path}
+ RESULT_VARIABLE ${_binary}_installed
+ )
+ else(SVN_FOUND)
+ message(FATAL_ERROR "Failed to find SVN_EXECUTABLE")
+ endif(SVN_FOUND)
+ file(WRITE ${CMAKE_BINARY_DIR}/temp/${_binary}_installed "${${_binary}_installed}")
+ else(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed)
+ set(${_binary}_installed 0)
+ endif(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed)
+ if(NOT ${_binary}_installed EQUAL 0)
+ message(FATAL_ERROR
+ "Failed to download or unpack prebuilt '${_binary}'."
+ " Process returned ${${_binary}_installed}.")
+ endif (NOT ${_binary}_installed EQUAL 0)
+ endif (NOT STANDALONE)
+endmacro (use_svn_external _binary _path _url _rev)
diff --git a/indra/cmake/FindMono.cmake b/indra/cmake/FindMono.cmake
index c36d7259e8..d956c48656 100644
--- a/indra/cmake/FindMono.cmake
+++ b/indra/cmake/FindMono.cmake
@@ -42,7 +42,7 @@ FIND_PROGRAM (GACUTIL_EXECUTABLE gacutil
/usr/local/bin
)
FIND_PROGRAM (ILASM_EXECUTABLE
- ilasm
+ NAMES ilasm.bat ilasm
NO_DEFAULT_PATH
PATHS "$ENV{PROGRAMFILES}/Mono-1.9.1/bin" "$ENV{PROGRAMFILES}/Mono-1.2.6/bin" /bin /usr/bin /usr/local/bin
)
diff --git a/indra/cmake/FindSVN.cmake b/indra/cmake/FindSVN.cmake
new file mode 100644
index 0000000000..3322be4ca9
--- /dev/null
+++ b/indra/cmake/FindSVN.cmake
@@ -0,0 +1,34 @@
+# -*- cmake -*-
+#
+# Find the svn executable for exporting old svn:externals.
+#
+# Input variables:
+# SVN_FIND_REQUIRED - set this if configuration should fail without scp
+#
+# Output variables:
+#
+# SVN_FOUND - set if svn was found
+# SVN_EXECUTABLE - path to svn executable
+# SVN_BATCH_FLAG - how to put svn into batch mode
+
+
+SET(SVN_EXECUTABLE)
+FIND_PROGRAM(SVN_EXECUTABLE NAMES svn svn.exe)
+
+IF (SVN_EXECUTABLE)
+ SET(SVN_FOUND ON)
+ELSE (SVN_EXECUTABLE)
+ SET(SVN_FOUND OFF)
+ENDIF (SVN_EXECUTABLE)
+
+IF (SVN_FOUND)
+ GET_FILENAME_COMPONENT(_svn_name ${SVN_EXECUTABLE} NAME_WE)
+ SET(SVN_BATCH_FLAG --non-interactive)
+ELSE (SVN_FOUND)
+ IF (SVN_FIND_REQUIRED)
+ MESSAGE(FATAL_ERROR "Could not find svn executable")
+ ENDIF (SVN_FIND_REQUIRED)
+ENDIF (SVN_FOUND)
+
+MARK_AS_ADVANCED(SVN_EXECUTABLE SVN_FOUND SVN_BATCH_FLAG)
+
diff --git a/indra/cmake/GStreamer010Plugin.cmake b/indra/cmake/GStreamer010Plugin.cmake
new file mode 100644
index 0000000000..0d334837d4
--- /dev/null
+++ b/indra/cmake/GStreamer010Plugin.cmake
@@ -0,0 +1,39 @@
+# -*- cmake -*-
+include(Prebuilt)
+
+if (STANDALONE)
+ include(FindPkgConfig)
+
+ pkg_check_modules(GSTREAMER010 REQUIRED gstreamer-0.10)
+ pkg_check_modules(GSTREAMER010_PLUGINS_BASE REQUIRED gstreamer-plugins-base-0.10)
+elseif (LINUX)
+ use_prebuilt_binary(gstreamer)
+ # possible libxml should have its own .cmake file instead
+ use_prebuilt_binary(libxml)
+ set(GSTREAMER010_FOUND ON FORCE BOOL)
+ set(GSTREAMER010_PLUGINS_BASE_FOUND ON FORCE BOOL)
+ set(GSTREAMER010_INCLUDE_DIRS
+ ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/gstreamer-0.10
+ ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/glib-2.0
+ ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/libxml2
+ )
+ # We don't need to explicitly link against gstreamer itself, because
+ # LLMediaImplGStreamer probes for the system's copy at runtime.
+ set(GSTREAMER010_LIBRARIES
+ gobject-2.0
+ gmodule-2.0
+ dl
+ gthread-2.0
+ rt
+ glib-2.0
+ )
+endif (STANDALONE)
+
+if (GSTREAMER010_FOUND AND GSTREAMER010_PLUGINS_BASE_FOUND)
+ set(GSTREAMER010 ON CACHE BOOL "Build with GStreamer-0.10 streaming media support.")
+endif (GSTREAMER010_FOUND AND GSTREAMER010_PLUGINS_BASE_FOUND)
+
+if (GSTREAMER010)
+ add_definitions(-DLL_GSTREAMER010_ENABLED=1)
+endif (GSTREAMER010)
+
diff --git a/indra/cmake/GetPrerequisites_2_8.cmake b/indra/cmake/GetPrerequisites_2_8.cmake
new file mode 100644
index 0000000000..5a24842c89
--- /dev/null
+++ b/indra/cmake/GetPrerequisites_2_8.cmake
@@ -0,0 +1,786 @@
+# GetPrerequisites.cmake
+#
+# This script provides functions to list the .dll, .dylib or .so files that an
+# executable or shared library file depends on. (Its prerequisites.)
+#
+# It uses various tools to obtain the list of required shared library files:
+# dumpbin (Windows)
+# ldd (Linux/Unix)
+# otool (Mac OSX)
+#
+# The following functions are provided by this script:
+# gp_append_unique
+# is_file_executable
+# gp_item_default_embedded_path
+# (projects can override with gp_item_default_embedded_path_override)
+# gp_resolve_item
+# (projects can override with gp_resolve_item_override)
+# gp_resolved_file_type
+# gp_file_type
+# get_prerequisites
+# list_prerequisites
+# list_prerequisites_by_glob
+#
+# Requires CMake 2.6 or greater because it uses function, break, return and
+# PARENT_SCOPE.
+
+#=============================================================================
+# Copyright 2008-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distributed this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+# gp_append_unique list_var value
+#
+# Append value to the list variable ${list_var} only if the value is not
+# already in the list.
+#
+function(gp_append_unique list_var value)
+ set(contains 0)
+
+ foreach(item ${${list_var}})
+ if("${item}" STREQUAL "${value}")
+ set(contains 1)
+ break()
+ endif("${item}" STREQUAL "${value}")
+ endforeach(item)
+
+ if(NOT contains)
+ set(${list_var} ${${list_var}} "${value}" PARENT_SCOPE)
+ endif(NOT contains)
+endfunction(gp_append_unique)
+
+
+# is_file_executable file result_var
+#
+# Return 1 in ${result_var} if ${file} is a binary executable.
+#
+# Return 0 in ${result_var} otherwise.
+#
+function(is_file_executable file result_var)
+ #
+ # A file is not executable until proven otherwise:
+ #
+ set(${result_var} 0 PARENT_SCOPE)
+
+ get_filename_component(file_full "${file}" ABSOLUTE)
+ string(TOLOWER "${file_full}" file_full_lower)
+
+ # If file name ends in .exe on Windows, *assume* executable:
+ #
+ if(WIN32)
+ if("${file_full_lower}" MATCHES "\\.exe$")
+ set(${result_var} 1 PARENT_SCOPE)
+ return()
+ endif("${file_full_lower}" MATCHES "\\.exe$")
+
+ # A clause could be added here that uses output or return value of dumpbin
+ # to determine ${result_var}. In 99%+? practical cases, the exe name
+ # match will be sufficient...
+ #
+ endif(WIN32)
+
+ # Use the information returned from the Unix shell command "file" to
+ # determine if ${file_full} should be considered an executable file...
+ #
+ # If the file command's output contains "executable" and does *not* contain
+ # "text" then it is likely an executable suitable for prerequisite analysis
+ # via the get_prerequisites macro.
+ #
+ if(UNIX)
+ if(NOT file_cmd)
+ find_program(file_cmd "file")
+ endif(NOT file_cmd)
+
+ if(file_cmd)
+ execute_process(COMMAND "${file_cmd}" "${file_full}"
+ OUTPUT_VARIABLE file_ov
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+
+ # Replace the name of the file in the output with a placeholder token
+ # (the string " _file_full_ ") so that just in case the path name of
+ # the file contains the word "text" or "executable" we are not fooled
+ # into thinking "the wrong thing" because the file name matches the
+ # other 'file' command output we are looking for...
+ #
+ string(REPLACE "${file_full}" " _file_full_ " file_ov "${file_ov}")
+ string(TOLOWER "${file_ov}" file_ov)
+
+ #message(STATUS "file_ov='${file_ov}'")
+ if("${file_ov}" MATCHES "executable")
+ #message(STATUS "executable!")
+ if("${file_ov}" MATCHES "text")
+ #message(STATUS "but text, so *not* a binary executable!")
+ else("${file_ov}" MATCHES "text")
+ set(${result_var} 1 PARENT_SCOPE)
+ return()
+ endif("${file_ov}" MATCHES "text")
+ endif("${file_ov}" MATCHES "executable")
+ else(file_cmd)
+ message(STATUS "warning: No 'file' command, skipping execute_process...")
+ endif(file_cmd)
+ endif(UNIX)
+endfunction(is_file_executable)
+
+
+# gp_item_default_embedded_path item default_embedded_path_var
+#
+# Return the path that others should refer to the item by when the item
+# is embedded inside a bundle.
+#
+# Override on a per-project basis by providing a project-specific
+# gp_item_default_embedded_path_override function.
+#
+function(gp_item_default_embedded_path item default_embedded_path_var)
+
+ # On Windows and Linux, "embed" prerequisites in the same directory
+ # as the executable by default:
+ #
+ set(path "@executable_path")
+ set(overridden 0)
+
+ # On the Mac, relative to the executable depending on the type
+ # of the thing we are embedding:
+ #
+ if(APPLE)
+ #
+ # The assumption here is that all executables in the bundle will be
+ # in same-level-directories inside the bundle. The parent directory
+ # of an executable inside the bundle should be MacOS or a sibling of
+ # MacOS and all embedded paths returned from here will begin with
+ # "@executable_path/../" and will work from all executables in all
+ # such same-level-directories inside the bundle.
+ #
+
+ # By default, embed things right next to the main bundle executable:
+ #
+ set(path "@executable_path/../../Contents/MacOS")
+
+ # Embed .dylibs right next to the main bundle executable:
+ #
+ if(item MATCHES "\\.dylib$")
+ set(path "@executable_path/../MacOS")
+ set(overridden 1)
+ endif(item MATCHES "\\.dylib$")
+
+ # Embed frameworks in the embedded "Frameworks" directory (sibling of MacOS):
+ #
+ if(NOT overridden)
+ if(item MATCHES "[^/]+\\.framework/")
+ set(path "@executable_path/../Frameworks")
+ set(overridden 1)
+ endif(item MATCHES "[^/]+\\.framework/")
+ endif(NOT overridden)
+ endif()
+
+ # Provide a hook so that projects can override the default embedded location
+ # of any given library by whatever logic they choose:
+ #
+ if(COMMAND gp_item_default_embedded_path_override)
+ gp_item_default_embedded_path_override("${item}" path)
+ endif(COMMAND gp_item_default_embedded_path_override)
+
+ set(${default_embedded_path_var} "${path}" PARENT_SCOPE)
+endfunction(gp_item_default_embedded_path)
+
+
+# gp_resolve_item context item exepath dirs resolved_item_var
+#
+# Resolve an item into an existing full path file.
+#
+# Override on a per-project basis by providing a project-specific
+# gp_resolve_item_override function.
+#
+function(gp_resolve_item context item exepath dirs resolved_item_var)
+ set(resolved 0)
+ set(resolved_item "${item}")
+
+ # Is it already resolved?
+ #
+ if(EXISTS "${resolved_item}")
+ set(resolved 1)
+ endif(EXISTS "${resolved_item}")
+
+ if(NOT resolved)
+ if(item MATCHES "@executable_path")
+ #
+ # @executable_path references are assumed relative to exepath
+ #
+ string(REPLACE "@executable_path" "${exepath}" ri "${item}")
+ get_filename_component(ri "${ri}" ABSOLUTE)
+
+ if(EXISTS "${ri}")
+ #message(STATUS "info: embedded item exists (${ri})")
+ set(resolved 1)
+ set(resolved_item "${ri}")
+ else(EXISTS "${ri}")
+ message(STATUS "warning: embedded item does not exist '${ri}'")
+ endif(EXISTS "${ri}")
+ endif(item MATCHES "@executable_path")
+ endif(NOT resolved)
+
+ if(NOT resolved)
+ if(item MATCHES "@loader_path")
+ #
+ # @loader_path references are assumed relative to the
+ # PATH of the given "context" (presumably another library)
+ #
+ get_filename_component(contextpath "${context}" PATH)
+ string(REPLACE "@loader_path" "${contextpath}" ri "${item}")
+ get_filename_component(ri "${ri}" ABSOLUTE)
+
+ if(EXISTS "${ri}")
+ #message(STATUS "info: embedded item exists (${ri})")
+ set(resolved 1)
+ set(resolved_item "${ri}")
+ else(EXISTS "${ri}")
+ message(STATUS "warning: embedded item does not exist '${ri}'")
+ endif(EXISTS "${ri}")
+ endif(item MATCHES "@loader_path")
+ endif(NOT resolved)
+
+ if(NOT resolved)
+ set(ri "ri-NOTFOUND")
+ find_file(ri "${item}" ${exepath} ${dirs} NO_DEFAULT_PATH)
+ find_file(ri "${item}" ${exepath} ${dirs} /usr/lib)
+ if(ri)
+ #message(STATUS "info: 'find_file' in exepath/dirs (${ri})")
+ set(resolved 1)
+ set(resolved_item "${ri}")
+ set(ri "ri-NOTFOUND")
+ endif(ri)
+ endif(NOT resolved)
+
+ if(NOT resolved)
+ if(item MATCHES "[^/]+\\.framework/")
+ set(fw "fw-NOTFOUND")
+ find_file(fw "${item}"
+ "~/Library/Frameworks"
+ "/Library/Frameworks"
+ "/System/Library/Frameworks"
+ )
+ if(fw)
+ #message(STATUS "info: 'find_file' found framework (${fw})")
+ set(resolved 1)
+ set(resolved_item "${fw}")
+ set(fw "fw-NOTFOUND")
+ endif(fw)
+ endif(item MATCHES "[^/]+\\.framework/")
+ endif(NOT resolved)
+
+ # Using find_program on Windows will find dll files that are in the PATH.
+ # (Converting simple file names into full path names if found.)
+ #
+ if(WIN32)
+ if(NOT resolved)
+ set(ri "ri-NOTFOUND")
+ find_program(ri "${item}" PATHS "${exepath};${dirs}" NO_DEFAULT_PATH)
+ find_program(ri "${item}" PATHS "${exepath};${dirs}")
+ if(ri)
+ #message(STATUS "info: 'find_program' in exepath/dirs (${ri})")
+ set(resolved 1)
+ set(resolved_item "${ri}")
+ set(ri "ri-NOTFOUND")
+ endif(ri)
+ endif(NOT resolved)
+ endif(WIN32)
+
+ # Provide a hook so that projects can override item resolution
+ # by whatever logic they choose:
+ #
+ if(COMMAND gp_resolve_item_override)
+ gp_resolve_item_override("${context}" "${item}" "${exepath}" "${dirs}" resolved_item resolved)
+ endif(COMMAND gp_resolve_item_override)
+
+ if(NOT resolved)
+ message(STATUS "
+warning: cannot resolve item '${item}'
+
+ possible problems:
+ need more directories?
+ need to use InstallRequiredSystemLibraries?
+ run in install tree instead of build tree?
+")
+# message(STATUS "
+#******************************************************************************
+#warning: cannot resolve item '${item}'
+#
+# possible problems:
+# need more directories?
+# need to use InstallRequiredSystemLibraries?
+# run in install tree instead of build tree?
+#
+# context='${context}'
+# item='${item}'
+# exepath='${exepath}'
+# dirs='${dirs}'
+# resolved_item_var='${resolved_item_var}'
+#******************************************************************************
+#")
+ endif(NOT resolved)
+
+ set(${resolved_item_var} "${resolved_item}" PARENT_SCOPE)
+endfunction(gp_resolve_item)
+
+
+# gp_resolved_file_type original_file file exepath dirs type_var
+#
+# Return the type of ${file} with respect to ${original_file}. String
+# describing type of prerequisite is returned in variable named ${type_var}.
+#
+# Use ${exepath} and ${dirs} if necessary to resolve non-absolute ${file}
+# values -- but only for non-embedded items.
+#
+# Possible types are:
+# system
+# local
+# embedded
+# other
+#
+function(gp_resolved_file_type original_file file exepath dirs type_var)
+ #message(STATUS "**")
+
+ if(NOT IS_ABSOLUTE "${original_file}")
+ message(STATUS "warning: gp_resolved_file_type expects absolute full path for first arg original_file")
+ endif()
+
+ set(is_embedded 0)
+ set(is_local 0)
+ set(is_system 0)
+
+ set(resolved_file "${file}")
+
+ if("${file}" MATCHES "^@(executable|loader)_path")
+ set(is_embedded 1)
+ endif()
+
+ if(NOT is_embedded)
+ if(NOT IS_ABSOLUTE "${file}")
+ gp_resolve_item("${original_file}" "${file}" "${exepath}" "${dirs}" resolved_file)
+ endif()
+
+ string(TOLOWER "${original_file}" original_lower)
+ string(TOLOWER "${resolved_file}" lower)
+
+ if(UNIX)
+ if(resolved_file MATCHES "^(/lib/|/lib32/|/lib64/|/usr/lib/|/usr/lib32/|/usr/lib64/|/usr/X11R6/)")
+ set(is_system 1)
+ endif()
+ endif()
+
+ if(APPLE)
+ if(resolved_file MATCHES "^(/System/Library/|/usr/lib/)")
+ set(is_system 1)
+ endif()
+ endif()
+
+ if(WIN32)
+ string(TOLOWER "$ENV{SystemRoot}" sysroot)
+ string(REGEX REPLACE "\\\\" "/" sysroot "${sysroot}")
+
+ string(TOLOWER "$ENV{windir}" windir)
+ string(REGEX REPLACE "\\\\" "/" windir "${windir}")
+
+ if(lower MATCHES "^(${sysroot}/system|${windir}/system|${sysroot}/syswow|${windir}/syswow|(.*/)*msvc[^/]+dll)")
+ set(is_system 1)
+ endif()
+ endif()
+
+ if(NOT is_system)
+ get_filename_component(original_path "${original_lower}" PATH)
+ get_filename_component(path "${lower}" PATH)
+ if("${original_path}" STREQUAL "${path}")
+ set(is_local 1)
+ endif()
+ endif()
+ endif()
+
+ # Return type string based on computed booleans:
+ #
+ set(type "other")
+
+ if(is_system)
+ set(type "system")
+ elseif(is_embedded)
+ set(type "embedded")
+ elseif(is_local)
+ set(type "local")
+ endif()
+
+ #message(STATUS "gp_resolved_file_type: '${file}' '${resolved_file}'")
+ #message(STATUS " type: '${type}'")
+
+ if(NOT is_embedded)
+ if(NOT IS_ABSOLUTE "${resolved_file}")
+ if(lower MATCHES "^msvc[^/]+dll" AND is_system)
+ message(STATUS "info: non-absolute msvc file '${file}' returning type '${type}'")
+ else()
+ message(STATUS "warning: gp_resolved_file_type non-absolute file '${file}' returning type '${type}' -- possibly incorrect")
+ endif()
+ endif()
+ endif()
+
+ set(${type_var} "${type}" PARENT_SCOPE)
+
+ #message(STATUS "**")
+endfunction()
+
+
+# gp_file_type original_file file type_var
+#
+# Return the type of ${file} with respect to ${original_file}. String
+# describing type of prerequisite is returned in variable named ${type_var}.
+#
+# Possible types are:
+# system
+# local
+# embedded
+# other
+#
+function(gp_file_type original_file file type_var)
+ if(NOT IS_ABSOLUTE "${original_file}")
+ message(STATUS "warning: gp_file_type expects absolute full path for first arg original_file")
+ endif()
+
+ get_filename_component(exepath "${original_file}" PATH)
+
+ set(type "")
+ gp_resolved_file_type("${original_file}" "${file}" "${exepath}" "" type)
+
+ set(${type_var} "${type}" PARENT_SCOPE)
+endfunction(gp_file_type)
+
+
+# get_prerequisites target prerequisites_var exclude_system recurse dirs
+#
+# Get the list of shared library files required by ${target}. The list in
+# the variable named ${prerequisites_var} should be empty on first entry to
+# this function. On exit, ${prerequisites_var} will contain the list of
+# required shared library files.
+#
+# target is the full path to an executable file
+#
+# prerequisites_var is the name of a CMake variable to contain the results
+#
+# exclude_system is 0 or 1: 0 to include "system" prerequisites , 1 to
+# exclude them
+#
+# recurse is 0 or 1: 0 for direct prerequisites only, 1 for all prerequisites
+# recursively
+#
+# exepath is the path to the top level executable used for @executable_path
+# replacment on the Mac
+#
+# dirs is a list of paths where libraries might be found: these paths are
+# searched first when a target without any path info is given. Then standard
+# system locations are also searched: PATH, Framework locations, /usr/lib...
+#
+function(get_prerequisites target prerequisites_var exclude_system recurse exepath dirs)
+ set(verbose 0)
+ set(eol_char "E")
+
+ if(NOT IS_ABSOLUTE "${target}")
+ message("warning: target '${target}' is not absolute...")
+ endif(NOT IS_ABSOLUTE "${target}")
+
+ if(NOT EXISTS "${target}")
+ message("warning: target '${target}' does not exist...")
+ endif(NOT EXISTS "${target}")
+
+ # <setup-gp_tool-vars>
+ #
+ # Try to choose the right tool by default. Caller can set gp_tool prior to
+ # calling this function to force using a different tool.
+ #
+ if("${gp_tool}" STREQUAL "")
+ set(gp_tool "ldd")
+ if(APPLE)
+ set(gp_tool "otool")
+ endif(APPLE)
+ if(WIN32)
+ set(gp_tool "dumpbin")
+ endif(WIN32)
+ endif("${gp_tool}" STREQUAL "")
+
+ set(gp_tool_known 0)
+
+ if("${gp_tool}" STREQUAL "ldd")
+ set(gp_cmd_args "")
+ set(gp_regex "^[\t ]*[^\t ]+ => ([^\t ]+).*${eol_char}$")
+ set(gp_regex_cmp_count 1)
+ set(gp_tool_known 1)
+ endif("${gp_tool}" STREQUAL "ldd")
+
+ if("${gp_tool}" STREQUAL "otool")
+ set(gp_cmd_args "-L")
+ set(gp_regex "^\t([^\t]+) \\(compatibility version ([0-9]+.[0-9]+.[0-9]+), current version ([0-9]+.[0-9]+.[0-9]+)\\)${eol_char}$")
+ set(gp_regex_cmp_count 3)
+ set(gp_tool_known 1)
+ endif("${gp_tool}" STREQUAL "otool")
+
+ if("${gp_tool}" STREQUAL "dumpbin")
+ set(gp_cmd_args "/dependents")
+ set(gp_regex "^ ([^ ].*[Dd][Ll][Ll])${eol_char}$")
+ set(gp_regex_cmp_count 1)
+ set(gp_tool_known 1)
+ set(ENV{VS_UNICODE_OUTPUT} "") # Block extra output from inside VS IDE.
+ endif("${gp_tool}" STREQUAL "dumpbin")
+
+ if(NOT gp_tool_known)
+ message(STATUS "warning: gp_tool='${gp_tool}' is an unknown tool...")
+ message(STATUS "CMake function get_prerequisites needs more code to handle '${gp_tool}'")
+ message(STATUS "Valid gp_tool values are dumpbin, ldd and otool.")
+ return()
+ endif(NOT gp_tool_known)
+
+ set(gp_cmd_paths ${gp_cmd_paths}
+ "C:/Program Files/Microsoft Visual Studio 9.0/VC/bin"
+ "C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/bin"
+ "C:/Program Files/Microsoft Visual Studio 8/VC/BIN"
+ "C:/Program Files (x86)/Microsoft Visual Studio 8/VC/BIN"
+ "C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/BIN"
+ "C:/Program Files (x86)/Microsoft Visual Studio .NET 2003/VC7/BIN"
+ "/usr/local/bin"
+ "/usr/bin"
+ )
+
+ find_program(gp_cmd ${gp_tool} PATHS ${gp_cmd_paths})
+
+ if(NOT gp_cmd)
+ message(STATUS "warning: could not find '${gp_tool}' - cannot analyze prerequisites...")
+ return()
+ endif(NOT gp_cmd)
+
+ if("${gp_tool}" STREQUAL "dumpbin")
+ # When running dumpbin, it also needs the "Common7/IDE" directory in the
+ # PATH. It will already be in the PATH if being run from a Visual Studio
+ # command prompt. Add it to the PATH here in case we are running from a
+ # different command prompt.
+ #
+ get_filename_component(gp_cmd_dir "${gp_cmd}" PATH)
+ get_filename_component(gp_cmd_dlls_dir "${gp_cmd_dir}/../../Common7/IDE" ABSOLUTE)
+ if(EXISTS "${gp_cmd_dlls_dir}")
+ # only add to the path if it is not already in the path
+ if(NOT "$ENV{PATH}" MATCHES "${gp_cmd_dlls_dir}")
+ set(ENV{PATH} "$ENV{PATH};${gp_cmd_dlls_dir}")
+ endif(NOT "$ENV{PATH}" MATCHES "${gp_cmd_dlls_dir}")
+ endif(EXISTS "${gp_cmd_dlls_dir}")
+ endif("${gp_tool}" STREQUAL "dumpbin")
+ #
+ # </setup-gp_tool-vars>
+
+ if("${gp_tool}" STREQUAL "ldd")
+ set(old_ld_env "$ENV{LD_LIBRARY_PATH}")
+ foreach(dir ${exepath} ${dirs})
+ set(ENV{LD_LIBRARY_PATH} "${dir}:$ENV{LD_LIBRARY_PATH}")
+ endforeach(dir)
+ endif("${gp_tool}" STREQUAL "ldd")
+
+
+ # Track new prerequisites at each new level of recursion. Start with an
+ # empty list at each level:
+ #
+ set(unseen_prereqs)
+
+ # Run gp_cmd on the target:
+ #
+ execute_process(
+ COMMAND ${gp_cmd} ${gp_cmd_args} ${target}
+ OUTPUT_VARIABLE gp_cmd_ov
+ )
+
+ if("${gp_tool}" STREQUAL "ldd")
+ set(ENV{LD_LIBRARY_PATH} "${old_ld_env}")
+ endif("${gp_tool}" STREQUAL "ldd")
+
+ if(verbose)
+ message(STATUS "<RawOutput cmd='${gp_cmd} ${gp_cmd_args} ${target}'>")
+ message(STATUS "gp_cmd_ov='${gp_cmd_ov}'")
+ message(STATUS "</RawOutput>")
+ endif(verbose)
+
+ get_filename_component(target_dir "${target}" PATH)
+
+ # Convert to a list of lines:
+ #
+ string(REGEX REPLACE ";" "\\\\;" candidates "${gp_cmd_ov}")
+ string(REGEX REPLACE "\n" "${eol_char};" candidates "${candidates}")
+
+ # Analyze each line for file names that match the regular expression:
+ #
+ foreach(candidate ${candidates})
+ if("${candidate}" MATCHES "${gp_regex}")
+ # Extract information from each candidate:
+ string(REGEX REPLACE "${gp_regex}" "\\1" raw_item "${candidate}")
+
+ if(gp_regex_cmp_count GREATER 1)
+ string(REGEX REPLACE "${gp_regex}" "\\2" raw_compat_version "${candidate}")
+ string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" compat_major_version "${raw_compat_version}")
+ string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" compat_minor_version "${raw_compat_version}")
+ string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" compat_patch_version "${raw_compat_version}")
+ endif(gp_regex_cmp_count GREATER 1)
+
+ if(gp_regex_cmp_count GREATER 2)
+ string(REGEX REPLACE "${gp_regex}" "\\3" raw_current_version "${candidate}")
+ string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" current_major_version "${raw_current_version}")
+ string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" current_minor_version "${raw_current_version}")
+ string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" current_patch_version "${raw_current_version}")
+ endif(gp_regex_cmp_count GREATER 2)
+
+ # Use the raw_item as the list entries returned by this function. Use the
+ # gp_resolve_item function to resolve it to an actual full path file if
+ # necessary.
+ #
+ set(item "${raw_item}")
+
+ # Add each item unless it is excluded:
+ #
+ set(add_item 1)
+
+ if(${exclude_system})
+ set(type "")
+ gp_resolved_file_type("${target}" "${item}" "${exepath}" "${dirs}" type)
+ if("${type}" STREQUAL "system")
+ set(add_item 0)
+ endif("${type}" STREQUAL "system")
+ endif(${exclude_system})
+
+ if(add_item)
+ list(LENGTH ${prerequisites_var} list_length_before_append)
+ gp_append_unique(${prerequisites_var} "${item}")
+ list(LENGTH ${prerequisites_var} list_length_after_append)
+
+ if(${recurse})
+ # If item was really added, this is the first time we have seen it.
+ # Add it to unseen_prereqs so that we can recursively add *its*
+ # prerequisites...
+ #
+ # But first: resolve its name to an absolute full path name such
+ # that the analysis tools can simply accept it as input.
+ #
+ if(NOT list_length_before_append EQUAL list_length_after_append)
+ gp_resolve_item("${target}" "${item}" "${exepath}" "${dirs}" resolved_item)
+ set(unseen_prereqs ${unseen_prereqs} "${resolved_item}")
+ endif(NOT list_length_before_append EQUAL list_length_after_append)
+ endif(${recurse})
+ endif(add_item)
+ else("${candidate}" MATCHES "${gp_regex}")
+ if(verbose)
+ message(STATUS "ignoring non-matching line: '${candidate}'")
+ endif(verbose)
+ endif("${candidate}" MATCHES "${gp_regex}")
+ endforeach(candidate)
+
+ list(LENGTH ${prerequisites_var} prerequisites_var_length)
+ if(prerequisites_var_length GREATER 0)
+ list(SORT ${prerequisites_var})
+ endif(prerequisites_var_length GREATER 0)
+ if(${recurse})
+ set(more_inputs ${unseen_prereqs})
+ foreach(input ${more_inputs})
+ get_prerequisites("${input}" ${prerequisites_var} ${exclude_system} ${recurse} "${exepath}" "${dirs}")
+ endforeach(input)
+ endif(${recurse})
+
+ set(${prerequisites_var} ${${prerequisites_var}} PARENT_SCOPE)
+endfunction(get_prerequisites)
+
+
+# list_prerequisites target all exclude_system verbose
+#
+# ARGV0 (target) is the full path to an executable file
+#
+# optional ARGV1 (all) is 0 or 1: 0 for direct prerequisites only,
+# 1 for all prerequisites recursively
+#
+# optional ARGV2 (exclude_system) is 0 or 1: 0 to include "system"
+# prerequisites , 1 to exclude them
+#
+# optional ARGV3 (verbose) is 0 or 1: 0 to print only full path
+# names of prerequisites, 1 to print extra information
+#
+function(list_prerequisites target)
+ if("${ARGV1}" STREQUAL "")
+ set(all 1)
+ else("${ARGV1}" STREQUAL "")
+ set(all "${ARGV1}")
+ endif("${ARGV1}" STREQUAL "")
+
+ if("${ARGV2}" STREQUAL "")
+ set(exclude_system 0)
+ else("${ARGV2}" STREQUAL "")
+ set(exclude_system "${ARGV2}")
+ endif("${ARGV2}" STREQUAL "")
+
+ if("${ARGV3}" STREQUAL "")
+ set(verbose 0)
+ else("${ARGV3}" STREQUAL "")
+ set(verbose "${ARGV3}")
+ endif("${ARGV3}" STREQUAL "")
+
+ set(count 0)
+ set(count_str "")
+ set(print_count "${verbose}")
+ set(print_prerequisite_type "${verbose}")
+ set(print_target "${verbose}")
+ set(type_str "")
+
+ get_filename_component(exepath "${target}" PATH)
+
+ set(prereqs "")
+ get_prerequisites("${target}" prereqs ${exclude_system} ${all} "${exepath}" "")
+
+ if(print_target)
+ message(STATUS "File '${target}' depends on:")
+ endif(print_target)
+
+ foreach(d ${prereqs})
+ math(EXPR count "${count} + 1")
+
+ if(print_count)
+ set(count_str "${count}. ")
+ endif(print_count)
+
+ if(print_prerequisite_type)
+ gp_file_type("${target}" "${d}" type)
+ set(type_str " (${type})")
+ endif(print_prerequisite_type)
+
+ message(STATUS "${count_str}${d}${type_str}")
+ endforeach(d)
+endfunction(list_prerequisites)
+
+
+# list_prerequisites_by_glob glob_arg glob_exp
+#
+# glob_arg is GLOB or GLOB_RECURSE
+#
+# glob_exp is a globbing expression used with "file(GLOB" to retrieve a list
+# of matching files. If a matching file is executable, its prerequisites are
+# listed.
+#
+# Any additional (optional) arguments provided are passed along as the
+# optional arguments to the list_prerequisites calls.
+#
+function(list_prerequisites_by_glob glob_arg glob_exp)
+ message(STATUS "=============================================================================")
+ message(STATUS "List prerequisites of executables matching ${glob_arg} '${glob_exp}'")
+ message(STATUS "")
+ file(${glob_arg} file_list ${glob_exp})
+ foreach(f ${file_list})
+ is_file_executable("${f}" is_f_executable)
+ if(is_f_executable)
+ message(STATUS "=============================================================================")
+ list_prerequisites("${f}" ${ARGN})
+ message(STATUS "")
+ endif(is_f_executable)
+ endforeach(f)
+endfunction(list_prerequisites_by_glob)
diff --git a/indra/cmake/Glui.cmake b/indra/cmake/Glui.cmake
new file mode 100644
index 0000000000..f62a56856c
--- /dev/null
+++ b/indra/cmake/Glui.cmake
@@ -0,0 +1,28 @@
+# -*- cmake -*-
+include(Linking)
+include(Prebuilt)
+
+if (STANDALONE)
+ set(GLUI OFF CACHE BOOL
+ "GLUI support for the llplugin/llmedia test apps.")
+else (STANDALONE)
+ use_prebuilt_binary(glui)
+ set(GLUI ON CACHE BOOL
+ "GLUI support for the llplugin/llmedia test apps.")
+endif (STANDALONE)
+
+if (LINUX)
+ set(GLUI ON CACHE BOOL
+ "llplugin media apps HACK for Linux.")
+endif (LINUX)
+
+if (DARWIN OR LINUX)
+ set(GLUI_LIBRARY
+ glui)
+endif (DARWIN OR LINUX)
+
+if (WINDOWS)
+ set(GLUI_LIBRARY
+ debug glui32.lib
+ optimized glui32.lib)
+endif (WINDOWS)
diff --git a/indra/cmake/Glut.cmake b/indra/cmake/Glut.cmake
new file mode 100644
index 0000000000..314da30652
--- /dev/null
+++ b/indra/cmake/Glut.cmake
@@ -0,0 +1,19 @@
+# -*- cmake -*-
+include(Linking)
+include(Prebuilt)
+
+if (WINDOWS)
+ use_prebuilt_binary(freeglut)
+ set(GLUT_LIBRARY
+ debug freeglut_static.lib
+ optimized freeglut_static.lib)
+endif (WINDOWS)
+
+if (LINUX)
+ FIND_LIBRARY(GLUT_LIBRARY glut)
+endif (LINUX)
+
+if (DARWIN)
+ include(CMakeFindFrameworks)
+ find_library(GLUT_LIBRARY GLUT)
+endif (DARWIN)
diff --git a/indra/cmake/GoogleMock.cmake b/indra/cmake/GoogleMock.cmake
new file mode 100644
index 0000000000..ca5a8034ba
--- /dev/null
+++ b/indra/cmake/GoogleMock.cmake
@@ -0,0 +1,27 @@
+# -*- cmake -*-
+include(Prebuilt)
+include(Linking)
+
+use_prebuilt_binary(googlemock)
+
+set(GOOGLEMOCK_INCLUDE_DIRS
+ ${LIBS_PREBUILT_DIR}/include)
+
+if (LINUX)
+ set(GOOGLEMOCK_LIBRARIES
+ gmock
+ gtest)
+elseif(WINDOWS)
+ set(GOOGLEMOCK_LIBRARIES
+ gmock)
+ set(GOOGLEMOCK_INCLUDE_DIRS
+ ${LIBS_PREBUILT_DIR}/include
+ ${LIBS_PREBUILT_DIR}/include/gmock
+ ${LIBS_PREBUILT_DIR}/include/gmock/boost/tr1/tr1)
+elseif(DARWIN)
+ set(GOOGLEMOCK_LIBRARIES
+ gmock
+ gtest)
+endif(LINUX)
+
+
diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake
index aff65cb53e..946fc6b375 100644
--- a/indra/cmake/GooglePerfTools.cmake
+++ b/indra/cmake/GooglePerfTools.cmake
@@ -6,9 +6,11 @@ if (STANDALONE)
else (STANDALONE)
use_prebuilt_binary(google)
if (WINDOWS)
+ use_prebuilt_binary(google-perftools)
set(TCMALLOC_LIBRARIES
debug libtcmalloc_minimal-debug
- optimized libtcmalloc_minimal-debug)
+ optimized libtcmalloc_minimal)
+ set(GOOGLE_PERFTOOLS_FOUND "YES")
endif (WINDOWS)
if (LINUX)
set(TCMALLOC_LIBRARIES tcmalloc)
@@ -21,12 +23,15 @@ else (STANDALONE)
endif (STANDALONE)
if (GOOGLE_PERFTOOLS_FOUND)
- set(USE_GOOGLE_PERFTOOLS ON CACHE BOOL "Build with Google PerfTools support.")
+ # XXX Disable temporarily, until we have compilation issues on 64-bit
+ # Etch sorted.
+ set(USE_GOOGLE_PERFTOOLS OFF CACHE BOOL "Build with Google PerfTools support.")
endif (GOOGLE_PERFTOOLS_FOUND)
-# XXX Disable temporarily, until we have compilation issues on 64-bit
-# Etch sorted.
-set(USE_GOOGLE_PERFTOOLS OFF)
+if (WINDOWS)
+ # *TODO -reenable this once we get server usage sorted out
+ #set(USE_GOOGLE_PERFTOOLS ON)
+endif (WINDOWS)
if (USE_GOOGLE_PERFTOOLS)
set(TCMALLOC_FLAG -DLL_USE_TCMALLOC=1)
diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index 08151bc732..bf4d9b72a9 100644
--- a/indra/cmake/LLAddBuildTest.cmake
+++ b/indra/cmake/LLAddBuildTest.cmake
@@ -1,154 +1,260 @@
# -*- cmake -*-
+include(LLTestCommand)
+include(GoogleMock)
+
+MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
+ # Given a project name and a list of sourcefiles (with optional properties on each),
+ # add targets to build and run the tests specified.
+ # ASSUMPTIONS:
+ # * this macro is being executed in the project file that is passed in
+ # * current working SOURCE dir is that project dir
+ # * there is a subfolder tests/ with test code corresponding to the filenames passed in
+ # * properties for each sourcefile passed in indicate what libs to link that file with (MAKE NO ASSUMPTIONS ASIDE FROM TUT)
+ #
+ # More info and examples at: https://wiki.secondlife.com/wiki/How_to_add_unit_tests_to_indra_code
+ #
+ # WARNING: do NOT modify this code without working with poppy -
+ # there is another branch that will conflict heavily with any changes here.
+INCLUDE(GoogleMock)
-INCLUDE(APR)
-INCLUDE(LLMath)
-
-MACRO(ADD_BUILD_TEST_NO_COMMON name parent)
-# MESSAGE("${CMAKE_CURRENT_SOURCE_DIR}/tests/${name}_test.cpp")
- IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/${name}_test.cpp")
- SET(no_common_libraries
- ${APRUTIL_LIBRARIES}
- ${APR_LIBRARIES}
- ${PTHREAD_LIBRARY}
- ${WINDOWS_LIBRARIES}
- )
- SET(no_common_source_files
- ${name}.cpp
- tests/${name}_test.cpp
- ${CMAKE_SOURCE_DIR}/test/test.cpp
- )
- ADD_BUILD_TEST_INTERNAL("${name}" "${parent}" "${no_common_libraries}" "${no_common_source_files}")
- ENDIF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/${name}_test.cpp")
-ENDMACRO(ADD_BUILD_TEST_NO_COMMON name parent)
-
-
-MACRO(ADD_BUILD_TEST name parent)
- # optional extra parameter: list of additional source files
- SET(more_source_files "${ARGN}")
-
-# MESSAGE("${CMAKE_CURRENT_SOURCE_DIR}/tests/${name}_test.cpp")
- IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/${name}_test.cpp")
-
- SET(basic_libraries
- ${LLCOMMON_LIBRARIES}
- ${APRUTIL_LIBRARIES}
- ${APR_LIBRARIES}
- ${PTHREAD_LIBRARY}
- ${WINDOWS_LIBRARIES}
- )
- SET(basic_source_files
- ${name}.cpp
- tests/${name}_test.cpp
- ${CMAKE_SOURCE_DIR}/test/test.cpp
- ${CMAKE_SOURCE_DIR}/test/lltut.cpp
- ${more_source_files}
- )
- ADD_BUILD_TEST_INTERNAL("${name}" "${parent}" "${basic_libraries}" "${basic_source_files}")
-
- ENDIF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/${name}_test.cpp")
-ENDMACRO(ADD_BUILD_TEST name parent)
-
-
-MACRO(ADD_VIEWER_BUILD_TEST name parent)
- # This is just like the generic ADD_BUILD_TEST, but we implicitly
- # add the necessary precompiled header .cpp file (anyone else find that
- # oxymoronic?) because the MSVC build errors will NOT point you there.
- ADD_BUILD_TEST("${name}" "${parent}" llviewerprecompiledheaders.cpp)
-ENDMACRO(ADD_VIEWER_BUILD_TEST name parent)
-
-
-MACRO(ADD_SIMULATOR_BUILD_TEST name parent)
- ADD_BUILD_TEST("${name}" "${parent}" llsimprecompiledheaders.cpp)
-
- if (WINDOWS)
- SET_SOURCE_FILES_PROPERTIES(
- "tests/${name}_test.cpp"
- PROPERTIES
- COMPILE_FLAGS "/Yullsimprecompiledheaders.h"
- )
- endif (WINDOWS)
-ENDMACRO(ADD_SIMULATOR_BUILD_TEST name parent)
-
-MACRO(ADD_BUILD_TEST_INTERNAL name parent libraries source_files)
- # Optional additional parameter: pathname of Python wrapper script
- SET(wrapper "${ARGN}")
- #MESSAGE(STATUS "ADD_BUILD_TEST_INTERNAL ${name} wrapper = ${wrapper}")
-
- SET(TEST_SOURCE_FILES ${source_files})
- SET(HEADER "${name}.h")
- set_source_files_properties(${HEADER}
- PROPERTIES HEADER_FILE_ONLY TRUE)
- LIST(APPEND TEST_SOURCE_FILES ${HEADER})
- INCLUDE_DIRECTORIES("${LIBS_OPEN_DIR}/test")
- ADD_EXECUTABLE(${name}_test ${TEST_SOURCE_FILES})
- TARGET_LINK_LIBRARIES(${name}_test
- ${libraries}
- )
- GET_TARGET_PROPERTY(TEST_EXE ${name}_test LOCATION)
- SET(TEST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}_test_ok.txt)
-
- IF ("${wrapper}" STREQUAL "")
- SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR})
- ELSE ("${wrapper}" STREQUAL "")
- SET(TEST_CMD ${PYTHON_EXECUTABLE} ${wrapper} ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR})
- ENDIF ("${wrapper}" STREQUAL "")
-
- #MESSAGE(STATUS "ADD_BUILD_TEST_INTERNAL ${name} test_cmd = ${TEST_CMD}")
- SET(TEST_SCRIPT_CMD
- ${CMAKE_COMMAND}
- -DLD_LIBRARY_PATH=${ARCH_PREBUILT_DIRS}:/usr/lib
- -DTEST_CMD:STRING="${TEST_CMD}"
- -P ${CMAKE_SOURCE_DIR}/cmake/RunBuildTest.cmake
+ IF(LL_TEST_VERBOSE)
+ MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} sources: ${sources}")
+ ENDIF(LL_TEST_VERBOSE)
+
+ # Start with the header and project-wide setup before making targets
+ #project(UNITTEST_PROJECT_${project})
+ # Setup includes, paths, etc
+ SET(alltest_SOURCE_FILES
+ ${CMAKE_SOURCE_DIR}/test/test.cpp
+ ${CMAKE_SOURCE_DIR}/test/lltut.cpp
+ )
+ SET(alltest_DEP_TARGETS
+ # needed by the test harness itself
+ ${APRUTIL_LIBRARIES}
+ ${APR_LIBRARIES}
+ llcommon
+ )
+ IF(NOT "${project}" STREQUAL "llmath")
+ # add llmath as a dep unless the tested module *is* llmath!
+ LIST(APPEND alltest_DEP_TARGETS
+ llmath
)
+ ENDIF(NOT "${project}" STREQUAL "llmath")
+ SET(alltest_INCLUDE_DIRS
+ ${LLMATH_INCLUDE_DIRS}
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LIBS_OPEN_DIR}/test
+ ${GOOGLEMOCK_INCLUDE_DIRS}
+ )
+ SET(alltest_LIBRARIES
+ ${GOOGLEMOCK_LIBRARIES}
+ ${PTHREAD_LIBRARY}
+ ${WINDOWS_LIBRARIES}
+ )
+ # Headers, for convenience in targets.
+ SET(alltest_HEADER_FILES
+ ${CMAKE_SOURCE_DIR}/test/test.h
+ )
+
+ # Use the default flags
+ if (LINUX)
+ SET(CMAKE_EXE_LINKER_FLAGS "")
+ endif (LINUX)
+
+ # start the source test executable definitions
+ SET(${project}_TEST_OUTPUT "")
+ FOREACH (source ${sources})
+ STRING( REGEX REPLACE "(.*)\\.[^.]+$" "\\1" name ${source} )
+ STRING( REGEX REPLACE ".*\\.([^.]+)$" "\\1" extension ${source} )
+ IF(LL_TEST_VERBOSE)
+ MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} individual source: ${source} (${name}.${extension})")
+ ENDIF(LL_TEST_VERBOSE)
+
+ #
+ # Per-codefile additional / external source, header, and include dir property extraction
+ #
+ # Source
+ GET_SOURCE_FILE_PROPERTY(${name}_test_additional_SOURCE_FILES ${source} LL_TEST_ADDITIONAL_SOURCE_FILES)
+ IF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND)
+ SET(${name}_test_additional_SOURCE_FILES "")
+ ENDIF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND)
+ SET(${name}_test_SOURCE_FILES ${source} tests/${name}_test.${extension} ${alltest_SOURCE_FILES} ${${name}_test_additional_SOURCE_FILES} )
+ IF(LL_TEST_VERBOSE)
+ MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_SOURCE_FILES ${${name}_test_SOURCE_FILES}")
+ ENDIF(LL_TEST_VERBOSE)
+ # Headers
+ GET_SOURCE_FILE_PROPERTY(${name}_test_additional_HEADER_FILES ${source} LL_TEST_ADDITIONAL_HEADER_FILES)
+ IF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND)
+ SET(${name}_test_additional_HEADER_FILES "")
+ ENDIF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND)
+ SET(${name}_test_HEADER_FILES ${name}.h ${${name}_test_additional_HEADER_FILES})
+ set_source_files_properties(${${name}_test_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE)
+ LIST(APPEND ${name}_test_SOURCE_FILES ${${name}_test_HEADER_FILES})
+ IF(LL_TEST_VERBOSE)
+ MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_HEADER_FILES ${${name}_test_HEADER_FILES}")
+ ENDIF(LL_TEST_VERBOSE)
+ # Include dirs
+ GET_SOURCE_FILE_PROPERTY(${name}_test_additional_INCLUDE_DIRS ${source} LL_TEST_ADDITIONAL_INCLUDE_DIRS)
+ IF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND)
+ SET(${name}_test_additional_INCLUDE_DIRS "")
+ ENDIF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND)
+ INCLUDE_DIRECTORIES(${alltest_INCLUDE_DIRS} ${name}_test_additional_INCLUDE_DIRS )
+ IF(LL_TEST_VERBOSE)
+ MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_INCLUDE_DIRS ${${name}_test_additional_INCLUDE_DIRS}")
+ ENDIF(LL_TEST_VERBOSE)
+
+
+ # Setup target
+ ADD_EXECUTABLE(PROJECT_${project}_TEST_${name} ${${name}_test_SOURCE_FILES})
+ SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${EXE_STAGING_DIR})
+
+ #
+ # Per-codefile additional / external project dep and lib dep property extraction
+ #
+ # WARNING: it's REALLY IMPORTANT to not mix these. I guarantee it will not work in the future. + poppy 2009-04-19
+ # Projects
+ GET_SOURCE_FILE_PROPERTY(${name}_test_additional_PROJECTS ${source} LL_TEST_ADDITIONAL_PROJECTS)
+ IF(${name}_test_additional_PROJECTS MATCHES NOTFOUND)
+ SET(${name}_test_additional_PROJECTS "")
+ ENDIF(${name}_test_additional_PROJECTS MATCHES NOTFOUND)
+ # Libraries
+ GET_SOURCE_FILE_PROPERTY(${name}_test_additional_LIBRARIES ${source} LL_TEST_ADDITIONAL_LIBRARIES)
+ IF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND)
+ SET(${name}_test_additional_LIBRARIES "")
+ ENDIF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND)
+ IF(LL_TEST_VERBOSE)
+ MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_PROJECTS ${${name}_test_additional_PROJECTS}")
+ MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_LIBRARIES ${${name}_test_additional_LIBRARIES}")
+ ENDIF(LL_TEST_VERBOSE)
+ # Add to project
+ TARGET_LINK_LIBRARIES(PROJECT_${project}_TEST_${name} ${alltest_LIBRARIES} ${alltest_DEP_TARGETS} ${${name}_test_additional_PROJECTS} ${${name}_test_additional_LIBRARIES} )
+
+ #
+ # Setup test targets
+ #
+ GET_TARGET_PROPERTY(TEST_EXE PROJECT_${project}_TEST_${name} LOCATION)
+ SET(TEST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/PROJECT_${project}_TEST_${name}_ok.txt)
+ SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR})
+
+ # daveh - what configuration does this use? Debug? it's cmake-time, not build time. + poppy 2009-04-19
+ IF(LL_TEST_VERBOSE)
+ MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_cmd = ${TEST_CMD}")
+ ENDIF(LL_TEST_VERBOSE)
+
+ IF(WINDOWS)
+ set(LD_LIBRARY_PATH ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR})
+ ELSEIF(DARWIN)
+ set(LD_LIBRARY_PATH ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/Resources:/usr/lib)
+ ELSE(WINDOWS)
+ set(LD_LIBRARY_PATH ${SHARED_LIB_STAGING_DIR}:/usr/lib)
+ ENDIF(WINDOWS)
- #MESSAGE(STATUS "ADD_BUILD_TEST_INTERNAL ${name} test_script = ${TEST_SCRIPT_CMD}")
+ LL_TEST_COMMAND("${LD_LIBRARY_PATH}" ${TEST_CMD})
+ SET(TEST_SCRIPT_CMD ${LL_TEST_COMMAND_value})
+ IF(LL_TEST_VERBOSE)
+ MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_script = ${TEST_SCRIPT_CMD}")
+ ENDIF(LL_TEST_VERBOSE)
+ # Add test
ADD_CUSTOM_COMMAND(
OUTPUT ${TEST_OUTPUT}
COMMAND ${TEST_SCRIPT_CMD}
- DEPENDS ${name}_test
+ DEPENDS PROJECT_${project}_TEST_${name}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
+ # Why not add custom target and add POST_BUILD command?
+ # Slightly less uncertain behavior
+ # (OUTPUT commands run non-deterministically AFAIK) + poppy 2009-04-19
+ # > I did not use a post build step as I could not make it notify of a
+ # > failure after the first time you build and fail a test. - daveh 2009-04-20
+ LIST(APPEND ${project}_TEST_OUTPUT ${TEST_OUTPUT})
+ ENDFOREACH (source)
- ADD_CUSTOM_TARGET(${name}_test_ok ALL DEPENDS ${TEST_OUTPUT})
- IF (${parent})
- ADD_DEPENDENCIES(${parent} ${name}_test_ok)
- ENDIF (${parent})
-
-ENDMACRO(ADD_BUILD_TEST_INTERNAL name parent libraries source_files)
-
-
-MACRO(ADD_COMM_BUILD_TEST name parent wrapper)
-## MESSAGE(STATUS "ADD_COMM_BUILD_TEST ${name} wrapper = ${wrapper}")
- # optional extra parameter: list of additional source files
- SET(more_source_files "${ARGN}")
-## MESSAGE(STATUS "ADD_COMM_BUILD_TEST ${name} more_source_files = ${more_source_files}")
-
- SET(libraries
- ${LLMESSAGE_LIBRARIES}
- ${LLMATH_LIBRARIES}
- ${LLVFS_LIBRARIES}
- ${LLCOMMON_LIBRARIES}
- ${APRUTIL_LIBRARIES}
- ${APR_LIBRARIES}
- ${PTHREAD_LIBRARY}
- ${WINDOWS_LIBRARIES}
- )
- SET(source_files
- ${name}.cpp
- tests/${name}_test.cpp
- ${CMAKE_SOURCE_DIR}/test/test.cpp
- ${CMAKE_SOURCE_DIR}/test/lltut.cpp
- ${more_source_files}
- )
+ # Add the test runner target per-project
+ # (replaces old _test_ok targets all over the place)
+ ADD_CUSTOM_TARGET(${project}_tests ALL DEPENDS ${${project}_TEST_OUTPUT})
+ ADD_DEPENDENCIES(${project} ${project}_tests)
+ENDMACRO(LL_ADD_PROJECT_UNIT_TESTS)
+
+FUNCTION(LL_ADD_INTEGRATION_TEST
+ testname
+ additional_source_files
+ library_dependencies
+# variable args
+ )
+ if(TEST_DEBUG)
+ message(STATUS "Adding INTEGRATION_TEST_${testname} - debug output is on")
+ endif(TEST_DEBUG)
+
+ SET(source_files
+ tests/${testname}_test.cpp
+ ${CMAKE_SOURCE_DIR}/test/test.cpp
+ ${CMAKE_SOURCE_DIR}/test/lltut.cpp
+ ${additional_source_files}
+ )
+
+ SET(libraries
+ ${library_dependencies}
+ ${GOOGLEMOCK_LIBRARIES}
+ ${PTHREAD_LIBRARY}
+ )
+
+ # Add test executable build target
+ if(TEST_DEBUG)
+ message(STATUS "ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})")
+ endif(TEST_DEBUG)
+ ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})
+ SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${EXE_STAGING_DIR})
+
+ # Add link deps to the executable
+ if(TEST_DEBUG)
+ message(STATUS "TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})")
+ endif(TEST_DEBUG)
+ TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})
+
+ # Create the test running command
+ SET(test_command ${ARGN})
+ GET_TARGET_PROPERTY(TEST_EXE INTEGRATION_TEST_${testname} LOCATION)
+ LIST(FIND test_command "{}" test_exe_pos)
+ IF(test_exe_pos LESS 0)
+ # The {} marker means "the full pathname of the test executable."
+ # test_exe_pos -1 means we didn't find it -- so append the test executable
+ # name to $ARGN, the variable part of the arg list. This is convenient
+ # shorthand for both straightforward execution of the test program (empty
+ # $ARGN) and for running a "wrapper" program of some kind accepting the
+ # pathname of the test program as the last of its args. You need specify
+ # {} only if the test program's pathname isn't the last argument in the
+ # desired command line.
+ LIST(APPEND test_command "${TEST_EXE}")
+ ELSE (test_exe_pos LESS 0)
+ # Found {} marker at test_exe_pos. Remove the {}...
+ LIST(REMOVE_AT test_command test_exe_pos)
+ # ...and replace it with the actual name of the test executable.
+ LIST(INSERT test_command test_exe_pos "${TEST_EXE}")
+ ENDIF (test_exe_pos LESS 0)
+
+ IF(WINDOWS)
+ set(LD_LIBRARY_PATH ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR})
+ ELSEIF(DARWIN)
+ set(LD_LIBRARY_PATH ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/Resources:/usr/lib)
+ ELSE(WINDOWS)
+ set(LD_LIBRARY_PATH ${SHARED_LIB_STAGING_DIR}:/usr/lib)
+ ENDIF(WINDOWS)
+
+ LL_TEST_COMMAND("${LD_LIBRARY_PATH}" ${test_command})
+ SET(TEST_SCRIPT_CMD ${LL_TEST_COMMAND_value})
+
+ if(TEST_DEBUG)
+ message(STATUS "TEST_SCRIPT_CMD: ${TEST_SCRIPT_CMD}")
+ endif(TEST_DEBUG)
+
+ ADD_CUSTOM_COMMAND(
+ TARGET INTEGRATION_TEST_${testname}
+ POST_BUILD
+ COMMAND ${TEST_SCRIPT_CMD}
+ )
- ADD_BUILD_TEST_INTERNAL("${name}" "${parent}" "${libraries}" "${source_files}" "${wrapper}")
-ENDMACRO(ADD_COMM_BUILD_TEST name parent wrapper)
+ # Use CTEST? Not sure how to yet...
+ # ADD_TEST(INTEGRATION_TEST_RUNNER_${testname} ${TEST_SCRIPT_CMD})
-MACRO(ADD_VIEWER_COMM_BUILD_TEST name parent wrapper)
- # This is just like the generic ADD_COMM_BUILD_TEST, but we implicitly
- # add the necessary precompiled header .cpp file (anyone else find that
- # oxymoronic?) because the MSVC build errors will NOT point you there.
-## MESSAGE(STATUS "ADD_VIEWER_COMM_BUILD_TEST ${name} wrapper = ${wrapper}")
- ADD_COMM_BUILD_TEST("${name}" "${parent}" "${wrapper}" llviewerprecompiledheaders.cpp)
-ENDMACRO(ADD_VIEWER_COMM_BUILD_TEST name parent wrapper)
+ENDFUNCTION(LL_ADD_INTEGRATION_TEST)
diff --git a/indra/cmake/LLAudio.cmake b/indra/cmake/LLAudio.cmake
index 89b790c6b0..7c248dfc72 100644
--- a/indra/cmake/LLAudio.cmake
+++ b/indra/cmake/LLAudio.cmake
@@ -6,4 +6,5 @@ set(LLAUDIO_INCLUDE_DIRS
${LIBS_OPEN_DIR}/llaudio
)
-set(LLAUDIO_LIBRARIES llaudio ${OPENAL_LIBRARIES})
+# be exhaustive here
+set(LLAUDIO_LIBRARIES llaudio ${VORBISFILE_LIBRARIES} ${VORBIS_LIBRARIES} ${VORBISENC_LIBRARIES} ${OGG_LIBRARIES} ${OPENAL_LIBRARIES})
diff --git a/indra/cmake/LLCommon.cmake b/indra/cmake/LLCommon.cmake
index 410766e4f9..d1ab264a41 100644
--- a/indra/cmake/LLCommon.cmake
+++ b/indra/cmake/LLCommon.cmake
@@ -4,6 +4,7 @@ include(APR)
include(Boost)
include(EXPAT)
include(ZLIB)
+include(GooglePerfTools)
set(LLCOMMON_INCLUDE_DIRS
${LIBS_OPEN_DIR}/llcommon
@@ -13,3 +14,10 @@ set(LLCOMMON_INCLUDE_DIRS
)
set(LLCOMMON_LIBRARIES llcommon)
+
+add_definitions(${TCMALLOC_FLAG})
+
+set(LLCOMMON_LINK_SHARED ON CACHE BOOL "Build the llcommon target as a shared library.")
+if(LLCOMMON_LINK_SHARED)
+ add_definitions(-DLL_COMMON_LINK_SHARED=1)
+endif(LLCOMMON_LINK_SHARED)
diff --git a/indra/cmake/LLKDU.cmake b/indra/cmake/LLKDU.cmake
index f103dcf664..6b69388896 100644
--- a/indra/cmake/LLKDU.cmake
+++ b/indra/cmake/LLKDU.cmake
@@ -1,7 +1,7 @@
# -*- cmake -*-
include(Prebuilt)
-if (NOT STANDALONE AND EXISTS ${LIBS_CLOSED_DIR}/llkdu)
+if (INSTALL_PROPRIETARY AND NOT STANDALONE AND EXISTS ${LIBS_CLOSED_DIR}/llkdu)
use_prebuilt_binary(kdu)
if (WINDOWS)
set(KDU_LIBRARY debug kdu_cored optimized kdu_core)
@@ -15,4 +15,4 @@ if (NOT STANDALONE AND EXISTS ${LIBS_CLOSED_DIR}/llkdu)
set(LLKDU_STATIC_LIBRARY llkdu_static)
set(LLKDU_LIBRARIES ${LLKDU_LIBRARY})
set(LLKDU_STATIC_LIBRARIES ${LLKDU_STATIC_LIBRARY})
-endif (NOT STANDALONE AND EXISTS ${LIBS_CLOSED_DIR}/llkdu)
+endif (INSTALL_PROPRIETARY AND NOT STANDALONE AND EXISTS ${LIBS_CLOSED_DIR}/llkdu)
diff --git a/indra/cmake/LLLogin.cmake b/indra/cmake/LLLogin.cmake
new file mode 100644
index 0000000000..47d171876a
--- /dev/null
+++ b/indra/cmake/LLLogin.cmake
@@ -0,0 +1,7 @@
+# -*- cmake -*-
+
+set(LLLOGIN_INCLUDE_DIRS
+ ${LIBS_OPEN_DIR}/viewer_components/login
+ )
+
+set(LLLOGIN_LIBRARIES lllogin)
diff --git a/indra/cmake/LLPlugin.cmake b/indra/cmake/LLPlugin.cmake
new file mode 100644
index 0000000000..9722f16c3c
--- /dev/null
+++ b/indra/cmake/LLPlugin.cmake
@@ -0,0 +1,8 @@
+# -*- cmake -*-
+
+
+set(LLPLUGIN_INCLUDE_DIRS
+ ${LIBS_OPEN_DIR}/llplugin
+ )
+
+set(LLPLUGIN_LIBRARIES llplugin)
diff --git a/indra/cmake/LLSharedLibs.cmake b/indra/cmake/LLSharedLibs.cmake
new file mode 100644
index 0000000000..6f602680f4
--- /dev/null
+++ b/indra/cmake/LLSharedLibs.cmake
@@ -0,0 +1,74 @@
+# ll_deploy_sharedlibs_command
+# target_exe: the cmake target of the executable for which the shared libs will be deployed.
+macro(ll_deploy_sharedlibs_command target_exe)
+ get_target_property(TARGET_LOCATION ${target_exe} LOCATION)
+ get_filename_component(OUTPUT_PATH ${TARGET_LOCATION} PATH)
+
+ if(DARWIN)
+ set(SEARCH_DIRS "${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/Resources")
+ get_target_property(IS_BUNDLE ${target_exe} MACOSX_BUNDLE)
+ if(IS_BUNDLE)
+ # If its a bundle the exe is not in the target location, this should find it.
+ get_filename_component(TARGET_FILE ${TARGET_LOCATION} NAME)
+ set(OUTPUT_PATH ${TARGET_LOCATION}.app/Contents/MacOS)
+ set(TARGET_LOCATION ${OUTPUT_PATH}/${TARGET_FILE})
+ set(OUTPUT_PATH ${OUTPUT_PATH}/../Resources)
+ endif(IS_BUNDLE)
+ elseif(WINDOWS)
+ set(SEARCH_DIRS "${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}" "$ENV{SystemRoot}/system32")
+ elseif(LINUX)
+ set(SEARCH_DIRS "${SHARED_LIB_STAGING_DIR}")
+ set(OUTPUT_PATH ${OUTPUT_PATH}/lib)
+ endif(DARWIN)
+
+ add_custom_command(
+ TARGET ${target_exe} POST_BUILD
+ COMMAND ${CMAKE_COMMAND}
+ ARGS
+ "-DBIN_NAME=\"${TARGET_LOCATION}\""
+ "-DSEARCH_DIRS=\"${SEARCH_DIRS}\""
+ "-DDST_PATH=\"${OUTPUT_PATH}\""
+ "-P"
+ "${CMAKE_SOURCE_DIR}/cmake/DeploySharedLibs.cmake"
+ )
+
+endmacro(ll_deploy_sharedlibs_command)
+
+# ll_stage_sharedlib
+# Performs config and adds a copy command for a sharedlib target.
+macro(ll_stage_sharedlib DSO_TARGET)
+ if(SHARED_LIB_STAGING_DIR)
+ # target gets written to the DLL staging directory.
+ # Also this directory is shared with RunBuildTest.cmake, y'know, for the tests.
+ set_target_properties(${DSO_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${SHARED_LIB_STAGING_DIR})
+ if(NOT WINDOWS)
+ get_target_property(DSO_PATH ${DSO_TARGET} LOCATION)
+ get_filename_component(DSO_FILE ${DSO_PATH} NAME)
+ if(DARWIN)
+ set(SHARED_LIB_STAGING_DIR_CONFIG ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/Resources)
+ else(DARWIN)
+ set(SHARED_LIB_STAGING_DIR_CONFIG ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR})
+ endif(DARWIN)
+
+ # *TODO - maybe make this a symbolic link? -brad
+ add_custom_command(
+ TARGET ${DSO_TARGET} POST_BUILD
+ COMMAND ${CMAKE_COMMAND}
+ ARGS
+ -E
+ copy_if_different
+ ${DSO_PATH}
+ ${SHARED_LIB_STAGING_DIR_CONFIG}/${DSO_FILE}
+ COMMENT "Copying llcommon to the staging folder."
+ )
+ endif(NOT WINDOWS)
+ endif(SHARED_LIB_STAGING_DIR)
+
+ if (DARWIN)
+ set_target_properties(${DSO_TARGET} PROPERTIES
+ BUILD_WITH_INSTALL_RPATH 1
+ INSTALL_NAME_DIR "@executable_path/../Resources"
+ )
+ endif(DARWIN)
+
+endmacro(ll_stage_sharedlib) \ No newline at end of file
diff --git a/indra/cmake/LLTestCommand.cmake b/indra/cmake/LLTestCommand.cmake
new file mode 100644
index 0000000000..fae5640493
--- /dev/null
+++ b/indra/cmake/LLTestCommand.cmake
@@ -0,0 +1,13 @@
+MACRO(LL_TEST_COMMAND LD_LIBRARY_PATH)
+ # nat wonders how Kitware can use the term 'function' for a construct that
+ # cannot return a value. And yet, variables you set inside a FUNCTION are
+ # local. Try a MACRO instead.
+ SET(LL_TEST_COMMAND_value
+ ${PYTHON_EXECUTABLE}
+ "${CMAKE_SOURCE_DIR}/cmake/run_build_test.py")
+ IF(LD_LIBRARY_PATH)
+ LIST(APPEND LL_TEST_COMMAND_value "-l${LD_LIBRARY_PATH}")
+ ENDIF(LD_LIBRARY_PATH)
+ LIST(APPEND LL_TEST_COMMAND_value ${ARGN})
+##MESSAGE(STATUS "Will run: ${LL_TEST_COMMAND_value}")
+ENDMACRO(LL_TEST_COMMAND)
diff --git a/indra/cmake/LLWindow.cmake b/indra/cmake/LLWindow.cmake
index c0efa27f6e..a5b9cf47a4 100644
--- a/indra/cmake/LLWindow.cmake
+++ b/indra/cmake/LLWindow.cmake
@@ -13,9 +13,9 @@ if (STANDALONE)
SDL_LIBRARY
)
else (STANDALONE)
- use_prebuilt_binary(SDL)
use_prebuilt_binary(mesa)
if (LINUX AND VIEWER)
+ use_prebuilt_binary(SDL)
set (SDL_FOUND TRUE)
set (SDL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/i686-linux)
set (SDL_LIBRARY SDL)
diff --git a/indra/cmake/LLXUIXML.cmake b/indra/cmake/LLXUIXML.cmake
new file mode 100644
index 0000000000..b8bfe48c77
--- /dev/null
+++ b/indra/cmake/LLXUIXML.cmake
@@ -0,0 +1,7 @@
+# -*- cmake -*-
+
+set(LLXUIXML_INCLUDE_DIRS
+ ${LIBS_OPEN_DIR}/llxuixml
+ )
+
+set(LLXUIXML_LIBRARIES llxuixml)
diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake
index 2bddb95178..bca99caf2a 100644
--- a/indra/cmake/Linking.cmake
+++ b/indra/cmake/Linking.cmake
@@ -5,6 +5,8 @@ if (NOT STANDALONE)
set(ARCH_PREBUILT_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib)
set(ARCH_PREBUILT_DIRS_RELEASE ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib/release)
set(ARCH_PREBUILT_DIRS_DEBUG ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib/debug)
+ set(SHARED_LIB_STAGING_DIR ${CMAKE_BINARY_DIR}/sharedlibs CACHE FILEPATH "Location of staged DLLs")
+ set(EXE_STAGING_DIR ${CMAKE_BINARY_DIR}/sharedlibs CACHE FILEPATH "Location of staged executables")
elseif (LINUX)
if (VIEWER)
set(ARCH_PREBUILT_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib_release_client)
@@ -13,10 +15,14 @@ if (NOT STANDALONE)
endif (VIEWER)
set(ARCH_PREBUILT_DIRS_RELEASE ${ARCH_PREBUILT_DIRS})
set(ARCH_PREBUILT_DIRS_DEBUG ${ARCH_PREBUILT_DIRS})
+ set(SHARED_LIB_STAGING_DIR ${CMAKE_BINARY_DIR}/sharedlibs/lib CACHE FILEPATH "Location of staged .sos")
+ set(EXE_STAGING_DIR ${CMAKE_BINARY_DIR}/sharedlibs/bin CACHE FILEPATH "Location of staged executables")
elseif (DARWIN)
set(ARCH_PREBUILT_DIRS_RELEASE ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib_release)
set(ARCH_PREBUILT_DIRS ${ARCH_PREBUILT_DIRS_RELEASE})
set(ARCH_PREBUILT_DIRS_DEBUG ${ARCH_PREBUILT_DIRS_RELEASE})
+ set(SHARED_LIB_STAGING_DIR ${CMAKE_BINARY_DIR}/sharedlibs CACHE FILEPATH "Location of staged DLLs")
+ set(EXE_STAGING_DIR "${CMAKE_BINARY_DIR}/sharedlibs/\$(CONFIGURATION)" CACHE FILEPATH "Location of staged executables")
endif (WINDOWS)
endif (NOT STANDALONE)
@@ -42,6 +48,7 @@ if (WINDOWS)
wldap32
gdi32
user32
+ dbghelp
)
else (WINDOWS)
set(WINDOWS_LIBRARIES "")
diff --git a/indra/cmake/MediaPluginBase.cmake b/indra/cmake/MediaPluginBase.cmake
new file mode 100644
index 0000000000..2be035b641
--- /dev/null
+++ b/indra/cmake/MediaPluginBase.cmake
@@ -0,0 +1,8 @@
+# -*- cmake -*-
+
+
+set(MEDIA_PLUGIN_BASE_INCLUDE_DIRS
+ ${LIBS_OPEN_DIR}/media_plugins/base/
+ )
+
+set(MEDIA_PLUGIN_BASE_LIBRARIES media_plugin_base)
diff --git a/indra/cmake/PluginAPI.cmake b/indra/cmake/PluginAPI.cmake
new file mode 100644
index 0000000000..d1649e8248
--- /dev/null
+++ b/indra/cmake/PluginAPI.cmake
@@ -0,0 +1,16 @@
+# -*- cmake -*-
+
+if (WINDOWS)
+ set(PLUGIN_API_WINDOWS_LIBRARIES
+ wsock32
+ ws2_32
+ psapi
+ netapi32
+ advapi32
+ user32
+ )
+else (WINDOWS)
+ set(PLUGIN_API_WINDOWS_LIBRARIES "")
+endif (WINDOWS)
+
+
diff --git a/indra/cmake/Pth.cmake b/indra/cmake/Pth.cmake
new file mode 100644
index 0000000000..a28f6ec696
--- /dev/null
+++ b/indra/cmake/Pth.cmake
@@ -0,0 +1,21 @@
+# -*- cmake -*-
+include(Prebuilt)
+
+set(PTH_FIND_QUIETLY ON)
+set(PTH_FIND_REQUIRED ON)
+
+if (STANDALONE)
+# ?? How would I construct FindPTH.cmake? This file was cloned from
+# CURL.cmake, which uses include(FindCURL), but there's no FindCURL.cmake?
+# include(FindPTH)
+else (STANDALONE)
+ # This library is only needed to support Boost.Coroutine, and only on Mac.
+ if (DARWIN)
+ use_prebuilt_binary(pth)
+ set(PTH_LIBRARIES pth)
+ set(PTH_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
+ else (DARWIN)
+ set(PTH_LIBRARIES)
+ set(PTH_INCLUDE_DIRS)
+ endif (DARWIN)
+endif (STANDALONE)
diff --git a/indra/cmake/Python.cmake b/indra/cmake/Python.cmake
index 4f86d3234e..0901c1b7a2 100644
--- a/indra/cmake/Python.cmake
+++ b/indra/cmake/Python.cmake
@@ -13,6 +13,10 @@ if (WINDOWS)
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath]
)
elseif (EXISTS /etc/debian_version)
# On Debian and Ubuntu, avoid Python 2.4 if possible.
diff --git a/indra/cmake/QuickTimePlugin.cmake b/indra/cmake/QuickTimePlugin.cmake
new file mode 100644
index 0000000000..02f432e3c1
--- /dev/null
+++ b/indra/cmake/QuickTimePlugin.cmake
@@ -0,0 +1,46 @@
+# -*- cmake -*-
+
+if(INSTALL_PROPRIETARY)
+ include(Prebuilt)
+ use_prebuilt_binary(quicktime)
+endif(INSTALL_PROPRIETARY)
+
+if (DARWIN)
+ include(CMakeFindFrameworks)
+ find_library(QUICKTIME_LIBRARY QuickTime)
+elseif (WINDOWS)
+ set(QUICKTIME_SDK_DIR "$ENV{PROGRAMFILES}/QuickTime SDK"
+ CACHE PATH "Location of the QuickTime SDK.")
+
+ find_library(DEBUG_QUICKTIME_LIBRARY qtmlclient.lib
+ PATHS
+ ${ARCH_PREBUILT_DIRS_DEBUG}
+ "${QUICKTIME_SDK_DIR}\\libraries"
+ )
+
+ find_library(RELEASE_QUICKTIME_LIBRARY qtmlclient.lib
+ PATHS
+ ${ARCH_PREBUILT_DIRS_RELEASE}
+ "${QUICKTIME_SDK_DIR}\\libraries"
+ )
+
+ if (DEBUG_QUICKTIME_LIBRARY AND RELEASE_QUICKTIME_LIBRARY)
+ set(QUICKTIME_LIBRARY
+ optimized ${RELEASE_QUICKTIME_LIBRARY}
+ debug ${DEBUG_QUICKTIME_LIBRARY}
+ )
+
+ endif (DEBUG_QUICKTIME_LIBRARY AND RELEASE_QUICKTIME_LIBRARY)
+
+ include_directories(
+ ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/quicktime
+ "${QUICKTIME_SDK_DIR}\\CIncludes"
+ )
+endif (DARWIN)
+
+mark_as_advanced(QUICKTIME_LIBRARY)
+
+if (QUICKTIME_LIBRARY)
+ set(QUICKTIME ON CACHE BOOL "Build with QuickTime streaming media support.")
+endif (QUICKTIME_LIBRARY)
+
diff --git a/indra/cmake/TemplateCheck.cmake b/indra/cmake/TemplateCheck.cmake
index 3b73dc82df..fa4e387dd5 100644
--- a/indra/cmake/TemplateCheck.cmake
+++ b/indra/cmake/TemplateCheck.cmake
@@ -5,7 +5,7 @@ include(Python)
macro (check_message_template _target)
add_custom_command(
TARGET ${_target}
- PRE_LINK
+ POST_BUILD
COMMAND ${PYTHON_EXECUTABLE}
ARGS ${SCRIPTS_DIR}/template_verifier.py
--mode=development --cache_master
diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake
index 0573aa85d1..6c2d9ec2a4 100644
--- a/indra/cmake/Variables.cmake
+++ b/indra/cmake/Variables.cmake
@@ -23,6 +23,8 @@ set(LIBS_SERVER_PREFIX)
set(SCRIPTS_PREFIX ../scripts)
set(SERVER_PREFIX)
set(VIEWER_PREFIX)
+set(INTEGRATION_TESTS_PREFIX)
+set(LL_TESTS ON CACHE BOOL "Build and run unit and integration tests (disable for build timing runs to reduce variation")
set(LIBS_CLOSED_DIR ${CMAKE_SOURCE_DIR}/${LIBS_CLOSED_PREFIX})
set(LIBS_OPEN_DIR ${CMAKE_SOURCE_DIR}/${LIBS_OPEN_PREFIX})
@@ -115,4 +117,7 @@ For more information, please see JIRA DEV-14943 - Cmake Linux cannot build both
")
endif (LINUX AND SERVER AND VIEWER)
+
+set(USE_PRECOMPILED_HEADERS ON CACHE BOOL "Enable use of precompiled header directives where supported.")
+
source_group("CMake Rules" FILES CMakeLists.txt)
diff --git a/indra/cmake/WebKitLibPlugin.cmake b/indra/cmake/WebKitLibPlugin.cmake
new file mode 100644
index 0000000000..1c572ab27f
--- /dev/null
+++ b/indra/cmake/WebKitLibPlugin.cmake
@@ -0,0 +1,64 @@
+# -*- cmake -*-
+include(Linking)
+include(Prebuilt)
+
+if (STANDALONE)
+ set(WEBKITLIBPLUGIN OFF CACHE BOOL
+ "WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.")
+else (STANDALONE)
+ use_prebuilt_binary(llqtwebkit)
+ set(WEBKITLIBPLUGIN ON CACHE BOOL
+ "WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.")
+endif (STANDALONE)
+
+if (WINDOWS)
+ set(WEBKIT_PLUGIN_LIBRARIES
+ debug llqtwebkitd
+ debug QtWebKitd4
+ debug QtOpenGLd4
+ debug QtNetworkd4
+ debug QtGuid4
+ debug QtCored4
+ debug qtmaind
+ optimized llqtwebkit
+ optimized QtWebKit4
+ optimized QtOpenGL4
+ optimized QtNetwork4
+ optimized QtGui4
+ optimized QtCore4
+ optimized qtmain
+ )
+elseif (DARWIN)
+ set(WEBKIT_PLUGIN_LIBRARIES
+ optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib
+ debug ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib
+ )
+elseif (LINUX)
+ set(WEBKIT_PLUGIN_LIBRARIES
+ llqtwebkit
+
+ qgif
+# qico
+ qjpeg
+# qpng
+# qtiff
+# qsvg
+
+# QtSvg
+ QtWebKit
+ QtOpenGL
+ QtNetwork
+ QtGui
+ QtCore
+
+ jpeg
+ fontconfig
+ X11
+ Xrender
+ GL
+
+# sqlite3
+# Xi
+# SM
+ )
+endif (WINDOWS)
diff --git a/indra/cmake/run_build_test.py b/indra/cmake/run_build_test.py
new file mode 100644
index 0000000000..0f6967e42a
--- /dev/null
+++ b/indra/cmake/run_build_test.py
@@ -0,0 +1,111 @@
+#!/usr/bin/python
+"""\
+@file run_build_test.py
+@author Nat Goodspeed
+@date 2009-09-03
+@brief Helper script to allow CMake to run some command after setting
+ environment variables.
+
+CMake has commands to run an external program. But remember that each CMake
+command must be backed by multiple build-system implementations. Unfortunately
+it seems CMake can't promise that every target build system can set specified
+environment variables before running the external program of interest.
+
+This helper script is a workaround. It simply sets the requested environment
+variables and then executes the program specified on the rest of its command
+line.
+
+Example:
+
+python run_build_test.py -DFOO=bar myprog somearg otherarg
+
+sets environment variable FOO=bar, then runs:
+myprog somearg otherarg
+
+$LicenseInfo:firstyear=2009&license=internal$
+Copyright (c) 2009, Linden Research, Inc.
+$/LicenseInfo$
+"""
+
+import os
+import sys
+import subprocess
+
+def main(command, libpath=[], vars={}):
+ """Pass:
+ command is a sequence (e.g. a list) of strings. The first item in the list
+ must be the command name, the rest are its arguments.
+
+ libpath is a sequence of directory pathnames. These will be appended to
+ the platform-specific dynamic library search path environment variable.
+
+ vars is a dict of arbitrary (var, value) pairs to be added to the
+ environment before running 'command'.
+
+ This function runs the specified command, waits for it to terminate and
+ returns its return code. This will be negative if the command terminated
+ with a signal, else it will be the process's specified exit code.
+ """
+ # Handle platform-dependent libpath first.
+ if sys.platform == "win32":
+ lpvars = ["PATH"]
+ elif sys.platform == "darwin":
+ lpvars = ["LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH"]
+ elif sys.platform.startswith("linux"):
+ lpvars = ["LD_LIBRARY_PATH"]
+ else:
+ # No idea what the right pathname might be! But only crump if this
+ # feature is requested.
+ if libpath:
+ raise NotImplemented("run_build_test: unknown platform %s" % sys.platform)
+ lpvars = []
+ for var in lpvars:
+ # Split the existing path. Bear in mind that the variable in question
+ # might not exist; instead of KeyError, just use an empty string.
+ dirs = os.environ.get(var, "").split(os.pathsep)
+ # Append the sequence in libpath
+ print "%s += %r" % (var, libpath)
+ dirs.extend(libpath)
+ # Now rebuild the path string. This way we use a minimum of separators
+ # -- and we avoid adding a pointless separator when libpath is empty.
+ os.environ[var] = os.pathsep.join(dirs)
+ # Now handle arbitrary environment variables. The tricky part is ensuring
+ # that all the keys and values we try to pass are actually strings.
+ if vars:
+ print "Setting:"
+ for key, value in vars.iteritems():
+ print "%s=%s" % (key, value)
+ os.environ.update(dict([(str(key), str(value)) for key, value in vars.iteritems()]))
+ # Run the child process.
+ print "Running: %s" % " ".join(command)
+ return subprocess.call(command)
+
+if __name__ == "__main__":
+ from optparse import OptionParser
+ parser = OptionParser(usage="usage: %prog [options] command args...")
+ # We want optparse support for the options we ourselves handle -- but we
+ # DO NOT want it looking at options for the executable we intend to run,
+ # rejecting them as invalid because we don't define them. So configure the
+ # parser to stop looking for options as soon as it sees the first
+ # positional argument (traditional Unix syntax).
+ parser.disable_interspersed_args()
+ parser.add_option("-D", "--define", dest="vars", default=[], action="append",
+ metavar="VAR=value",
+ help="Add VAR=value to the env variables defined")
+ parser.add_option("-l", "--libpath", dest="libpath", default=[], action="append",
+ metavar="DIR",
+ help="Add DIR to the platform-dependent DLL search path")
+ opts, args = parser.parse_args()
+ # What we have in opts.vars is a list of strings of the form "VAR=value"
+ # or possibly just "VAR". What we want is a dict. We can build that dict by
+ # constructing a list of ["VAR", "value"] pairs -- so split each
+ # "VAR=value" string on the '=' sign (but only once, in case we have
+ # "VAR=some=user=string"). To handle the case of just "VAR", append "" to
+ # the list returned by split(), then slice off anything after the pair we
+ # want.
+ rc = main(command=args, libpath=opts.libpath,
+ vars=dict([(pair.split('=', 1) + [""])[:2] for pair in opts.vars]))
+ if rc not in (None, 0):
+ print >>sys.stderr, "Failure running: %s" % " ".join(args)
+ print >>sys.stderr, "Error: %s" % rc
+ sys.exit((rc < 0) and 255 or rc)
diff --git a/indra/develop.py b/indra/develop.py
index 345dd1cb9b..eaecdd0ab6 100755
--- a/indra/develop.py
+++ b/indra/develop.py
@@ -76,6 +76,7 @@ class PlatformSetup(object):
build_type = build_types['relwithdebinfo']
standalone = 'OFF'
unattended = 'OFF'
+ universal = 'OFF'
project_name = 'SecondLife'
distcc = True
cmake_opts = []
@@ -238,6 +239,7 @@ class UnixSetup(PlatformSetup):
def run(self, command, name=None):
'''Run a program. If the program fails, raise an exception.'''
+ sys.stdout.flush()
ret = os.system(command)
if ret:
if name is None:
@@ -383,16 +385,20 @@ class LinuxSetup(UnixSetup):
if job_count is None:
hosts, job_count = count_distcc_hosts()
+ hostname = socket.gethostname()
if hosts == 1:
- hostname = socket.gethostname()
if hostname.startswith('station'):
hosts, job_count = mk_distcc_hosts('station', 36, 2)
os.environ['DISTCC_HOSTS'] = hosts
if hostname.startswith('eniac'):
hosts, job_count = mk_distcc_hosts('eniac', 71, 2)
os.environ['DISTCC_HOSTS'] = hosts
- if job_count > 12:
- job_count = 12;
+ if hostname.startswith('build'):
+ max_jobs = 6
+ else:
+ max_jobs = 12
+ if job_count > max_jobs:
+ job_count = max_jobs;
opts.extend(['-j', str(job_count)])
if targets:
@@ -415,7 +421,7 @@ class DarwinSetup(UnixSetup):
return 'darwin'
def arch(self):
- if self.unattended == 'ON':
+ if self.universal == 'ON':
return 'universal'
else:
return UnixSetup.arch(self)
@@ -429,10 +435,10 @@ class DarwinSetup(UnixSetup):
word_size=self.word_size,
unattended=self.unattended,
project_name=self.project_name,
- universal='',
+ universal=self.universal,
type=self.build_type.upper(),
)
- if self.unattended == 'ON':
+ if self.universal == 'ON':
args['universal'] = '-DCMAKE_OSX_ARCHITECTURES:STRING=\'i386;ppc\''
#if simple:
# return 'cmake %(opts)s %(dir)r' % args
@@ -451,8 +457,7 @@ class DarwinSetup(UnixSetup):
targets = ' '.join(['-target ' + repr(t) for t in targets])
else:
targets = ''
- cmd = ('xcodebuild -parallelizeTargets '
- '-configuration %s %s %s' %
+ cmd = ('xcodebuild -configuration %s %s %s | grep -v "^[[:space:]]*setenv" ; exit ${PIPESTATUS[0]}' %
(self.build_type, ' '.join(opts), targets))
for d in self.build_dirs():
try:
@@ -568,25 +573,33 @@ class WindowsSetup(PlatformSetup):
if self.gens[self.generator]['ver'] in [ r'8.0', r'9.0' ]:
config = '\"%s|Win32\"' % config
- return "buildconsole %s.sln /build %s" % (self.project_name, config)
+ return "buildconsole %(prj)s.sln /build /cfg=%(cfg)s" % {'prj': self.project_name, 'cfg': config}
# devenv.com is CLI friendly, devenv.exe... not so much.
return ('"%sdevenv.com" %s.sln /build %s' %
(self.find_visual_studio(), self.project_name, self.build_type))
+ #return ('devenv.com %s.sln /build %s' %
+ # (self.project_name, self.build_type))
- def run(self, command, name=None):
+ def run(self, command, name=None, retry_on=None, retries=1):
'''Run a program. If the program fails, raise an exception.'''
- ret = os.system(command)
- if ret:
- if name is None:
- name = command.split(None, 1)[0]
- path = self.find_in_path(name)
- if not path:
- ret = 'was not found'
- else:
- ret = 'exited with status %d' % ret
- raise CommandError('the command %r %s' %
- (name, ret))
+ while retries:
+ retries = retries - 1
+ print "develop.py tries to run:", command
+ ret = os.system(command)
+ print "got ret", ret, "from", command
+ if ret:
+ if name is None:
+ name = command.split(None, 1)[0]
+ path = self.find_in_path(name)
+ if not path:
+ error = 'was not found'
+ else:
+ error = 'exited with status %d' % ret
+ if retry_on is not None and retry_on == ret:
+ print "Retrying... the command %r %s" % (name, error)
+ else:
+ raise CommandError('the command %r %s' % (name, error))
def run_cmake(self, args=[]):
'''Override to add the vstool.exe call after running cmake.'''
@@ -624,11 +637,11 @@ class WindowsSetup(PlatformSetup):
for t in targets:
cmd = '%s /project %s %s' % (build_cmd, t, ' '.join(opts))
print 'Running %r in %r' % (cmd, d)
- self.run(cmd)
+ self.run(cmd, retry_on=4, retries=3)
else:
cmd = '%s %s' % (build_cmd, ' '.join(opts))
print 'Running %r in %r' % (cmd, d)
- self.run(cmd)
+ self.run(cmd, retry_on=4, retries=3)
finally:
os.chdir(cwd)
@@ -673,6 +686,7 @@ Options:
--standalone build standalone, without Linden prebuild libraries
--unattended build unattended, do not invoke any tools requiring
a human response
+ --universal build a universal binary on Mac OS X (unsupported)
-t | --type=NAME build type ("Debug", "Release", or "RelWithDebInfo")
-m32 | -m64 build architecture (32-bit or 64-bit)
-N | --no-distcc disable use of distcc
@@ -718,7 +732,7 @@ def main(arguments):
opts, args = getopt.getopt(
arguments,
'?hNt:p:G:m:',
- ['help', 'standalone', 'no-distcc', 'unattended', 'type=', 'incredibuild', 'generator=', 'project='])
+ ['help', 'standalone', 'no-distcc', 'unattended', 'universal', 'type=', 'incredibuild', 'generator=', 'project='])
except getopt.GetoptError, err:
print >> sys.stderr, 'Error:', err
print >> sys.stderr, """
@@ -735,6 +749,8 @@ For example: develop.py configure -DSERVER:BOOL=OFF"""
setup.standalone = 'ON'
elif o in ('--unattended',):
setup.unattended = 'ON'
+ elif o in ('--universal',):
+ setup.universal = 'ON'
elif o in ('-m',):
if a in ('32', '64'):
setup.word_size = int(a)
diff --git a/indra/integration_tests/CMakeLists.txt b/indra/integration_tests/CMakeLists.txt
new file mode 100644
index 0000000000..67e8fbf1f2
--- /dev/null
+++ b/indra/integration_tests/CMakeLists.txt
@@ -0,0 +1,3 @@
+# -*- cmake -*-
+
+add_subdirectory(llui_libtest)
diff --git a/indra/integration_tests/llui_libtest/CMakeLists.txt b/indra/integration_tests/llui_libtest/CMakeLists.txt
new file mode 100644
index 0000000000..452d37d3be
--- /dev/null
+++ b/indra/integration_tests/llui_libtest/CMakeLists.txt
@@ -0,0 +1,108 @@
+# -*- cmake -*-
+
+# Only set this up for viewer builds, because the llui library is most closely
+# related to the viewer
+if (VIEWER)
+
+project (llui_libtest)
+
+include(00-Common)
+include(LLCommon)
+include(LLImage)
+include(LLImageJ2COJ) # ugh, needed for images
+include(LLMath)
+include(LLMessage)
+include(LLRender)
+include(LLWindow)
+include(LLUI)
+include(LLVFS) # ugh, needed for LLDir
+include(LLXML)
+include(LLXUIXML)
+include(Linking)
+# include(Tut)
+
+include_directories(
+ ${FREETYPE_INCLUDE_DIRS}
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LLIMAGE_INCLUDE_DIRS}
+ ${LLMATH_INCLUDE_DIRS}
+ ${LLRENDER_INCLUDE_DIRS}
+ ${LLUI_INCLUDE_DIRS}
+ ${LLVFS_INCLUDE_DIRS}
+ ${LLWINDOW_INCLUDE_DIRS}
+ ${LLXML_INCLUDE_DIRS}
+ ${LLXUIXML_INCLUDE_DIRS}
+ )
+
+set(llui_libtest_SOURCE_FILES
+ llui_libtest.cpp
+ llwidgetreg.cpp
+ )
+
+set(llui_libtest_HEADER_FILES
+ CMakeLists.txt
+ llui_libtest.h
+ llwidgetreg.h
+ )
+
+set_source_files_properties(${llui_libtest_HEADER_FILES}
+ PROPERTIES HEADER_FILE_ONLY TRUE)
+
+list(APPEND llui_libtest_SOURCE_FILES ${llui_libtest_HEADER_FILES})
+
+add_executable(llui_libtest ${llui_libtest_SOURCE_FILES})
+
+# Link with OS-specific libraries for LLWindow dependency
+if (DARWIN)
+ find_library(COCOA_LIBRARY Cocoa)
+ set(OS_LIBRARIES ${COCOA_LIBRARY})
+elseif (WINDOWS)
+ #ll_stack_trace needs this now...
+ list(APPEND WINDOWS_LIBRARIES dbghelp)
+ set(OS_LIBRARIES ${WINDOWS_LIBRARIES})
+elseif (LINUX)
+ set(OS_LIBRARIES)
+else (DARWIN)
+ message(FATAL_ERROR "unknown platform")
+endif (DARWIN)
+
+# Libraries on which this library depends, needed for Linux builds
+# Sort by high-level to low-level
+target_link_libraries(llui_libtest
+ llui
+ llmessage
+ ${OS_LIBRARIES}
+ ${GOOGLE_PERFTOOLS_LIBRARIES}
+ )
+
+if (WINDOWS)
+ set_target_properties(llui_libtest
+ PROPERTIES
+ LINK_FLAGS "/NODEFAULTLIB:LIBCMT"
+ LINK_FLAGS_DEBUG "/NODEFAULTLIB:MSVCRT /NODEFAULTLIB:LIBCMTD"
+ )
+
+ # Copy over OpenJPEG.dll
+ # *NOTE: On Windows with VS2005, only the first comment prints
+ set(OPENJPEG_RELEASE
+ "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release/openjpeg.dll")
+ add_custom_command( TARGET llui_libtest POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ ${OPENJPEG_RELEASE} ${CMAKE_CURRENT_BINARY_DIR}
+ COMMENT "Copying OpenJPEG DLLs to binary directory"
+ )
+ set(OPENJPEG_DEBUG
+ "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug/openjpegd.dll")
+ add_custom_command( TARGET llui_libtest POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ ${OPENJPEG_DEBUG} ${CMAKE_CURRENT_BINARY_DIR}
+ )
+
+endif (WINDOWS)
+
+# Ensure people working on the viewer don't break this library
+# *NOTE: This could be removed, or only built by Parabuild, if the build
+# and link times become too long. JC
+add_dependencies(viewer llui_libtest)
+
+endif (VIEWER)
diff --git a/indra/integration_tests/llui_libtest/llui_libtest.cpp b/indra/integration_tests/llui_libtest/llui_libtest.cpp
new file mode 100644
index 0000000000..abd8f7dbde
--- /dev/null
+++ b/indra/integration_tests/llui_libtest/llui_libtest.cpp
@@ -0,0 +1,221 @@
+/**
+ * @file llui_libtest.cpp
+ * @brief Integration test for the LLUI library
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+
+#include "llui_libtest.h"
+
+// project includes
+#include "llwidgetreg.h"
+
+// linden library includes
+#include "llcontrol.h" // LLControlGroup
+#include "lldir.h"
+#include "llerrorcontrol.h"
+#include "llfloater.h"
+#include "llfontfreetype.h"
+#include "llfontgl.h"
+#include "lltransutil.h"
+#include "llui.h"
+#include "lluictrlfactory.h"
+
+#include <iostream>
+
+// *TODO: switch to using TUT
+// *TODO: teach Parabuild about this program, run automatically after full builds
+
+// I believe these must be globals, not stack variables. JC
+LLControlGroup gSavedSettings("Global"); // saved at end of session
+LLControlGroup gSavedPerAccountSettings("PerAccount"); // saved at end of session
+LLControlGroup gWarningSettings("Warnings"); // persists ignored dialogs/warnings
+
+// We can't create LLImageGL objects because we have no window or rendering
+// context. Provide enough of an LLUIImage to test the LLUI library without
+// an underlying image.
+class TestUIImage : public LLUIImage
+{
+public:
+ TestUIImage()
+ : LLUIImage( std::string(), NULL ) // NULL ImageGL, don't deref!
+ { }
+
+ /*virtual*/ S32 getWidth() const
+ {
+ return 16;
+ }
+
+ /*virtual*/ S32 getHeight() const
+ {
+ return 16;
+ }
+};
+
+
+class LLTexture ;
+// We need to supply dummy images
+class TestImageProvider : public LLImageProviderInterface
+{
+public:
+ /*virtual*/ LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority)
+ {
+ return makeImage();
+ }
+
+ /*virtual*/ LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority)
+ {
+ return makeImage();
+ }
+
+ /*virtual*/ void cleanUp()
+ {
+ }
+
+ LLPointer<LLUIImage> makeImage()
+ {
+ LLPointer<LLTexture> image_gl;
+ LLPointer<LLUIImage> image = new TestUIImage(); //LLUIImage( std::string(), image_gl);
+ mImageList.push_back(image);
+ return image;
+ }
+
+public:
+ // Unclear if we need this, hold on to one copy of each image we make
+ std::vector<LLPointer<LLUIImage> > mImageList;
+};
+TestImageProvider gTestImageProvider;
+
+static std::string get_xui_dir()
+{
+ std::string delim = gDirUtilp->getDirDelimiter();
+ return gDirUtilp->getSkinBaseDir() + delim + "default" + delim + "xui" + delim;
+}
+
+void init_llui()
+{
+ // Font lookup needs directory support
+#if LL_DARWIN
+ const char* newview_path = "../../../../newview";
+#else
+ const char* newview_path = "../../../newview";
+#endif
+ gDirUtilp->initAppDirs("SecondLife", newview_path);
+ gDirUtilp->setSkinFolder("default");
+
+ // colors are no longer stored in a LLControlGroup file
+ LLUIColorTable::instance().loadFromSettings();
+
+ std::string config_filename = gDirUtilp->getExpandedFilename(
+ LL_PATH_APP_SETTINGS, "settings.xml");
+ gSavedSettings.loadFromFile(config_filename);
+
+ // See LLAppViewer::init()
+ LLUI::settings_map_t settings;
+ settings["config"] = &gSavedSettings;
+ settings["ignores"] = &gWarningSettings;
+ settings["floater"] = &gSavedSettings;
+ settings["account"] = &gSavedPerAccountSettings;
+
+ // Don't use real images as we don't have a GL context
+ LLUI::initClass(settings, &gTestImageProvider);
+
+ const bool no_register_widgets = false;
+ LLWidgetReg::initClass( no_register_widgets );
+
+ // Unclear if this is needed
+ LLUI::setupPaths();
+ // Otherwise we get translation warnings when setting up floaters
+ // (tooltips for buttons)
+ std::set<std::string> default_args;
+ LLTransUtil::parseStrings("strings.xml", default_args);
+ LLTransUtil::parseLanguageStrings("language_settings.xml");
+ LLFontManager::initClass();
+
+ // Creating widgets apparently requires fonts to be initialized,
+ // otherwise it crashes.
+ LLFontGL::initClass(96.f, 1.f, 1.f,
+ gDirUtilp->getAppRODataDir(),
+ LLUI::getXUIPaths(),
+ false ); // don't create gl textures
+
+ LLFloaterView::Params fvparams;
+ fvparams.name("Floater View");
+ fvparams.rect( LLRect(0,480,640,0) );
+ fvparams.mouse_opaque(false);
+ fvparams.follows.flags(FOLLOWS_ALL);
+ fvparams.tab_stop(false);
+ gFloaterView = LLUICtrlFactory::create<LLFloaterView> (fvparams);
+}
+
+void export_test_floaters()
+{
+ // Convert all test floaters to new XML format
+ std::string delim = gDirUtilp->getDirDelimiter();
+ std::string xui_dir = get_xui_dir() + "en" + delim;
+ std::string filename;
+ while (gDirUtilp->getNextFileInDir(xui_dir, "floater_test_*.xml", filename, false))
+ {
+ if (filename.find("_new.xml") != std::string::npos)
+ {
+ // don't re-export other test floaters
+ continue;
+ }
+ llinfos << "Converting " << filename << llendl;
+ // Build a floater and output new attributes
+ LLXMLNodePtr output_node = new LLXMLNode();
+ LLFloater* floater = new LLFloater(LLSD());
+ LLUICtrlFactory::getInstance()->buildFloater(floater,
+ filename,
+ // FALSE, // don't open floater
+ output_node);
+ std::string out_filename = xui_dir + filename;
+ std::string::size_type extension_pos = out_filename.rfind(".xml");
+ out_filename.resize(extension_pos);
+ out_filename += "_new.xml";
+
+ llinfos << "Output: " << out_filename << llendl;
+ LLFILE* floater_file = LLFile::fopen(out_filename.c_str(), "w");
+ LLXMLNode::writeHeaderToFile(floater_file);
+ output_node->writeToFile(floater_file);
+ fclose(floater_file);
+ }
+}
+
+int main(int argc, char** argv)
+{
+ // Must init LLError for llerrs to actually cause errors.
+ LLError::initForApplication(".");
+
+ init_llui();
+
+ export_test_floaters();
+
+ return 0;
+}
diff --git a/indra/integration_tests/llui_libtest/llui_libtest.h b/indra/integration_tests/llui_libtest/llui_libtest.h
new file mode 100644
index 0000000000..a84d57dba9
--- /dev/null
+++ b/indra/integration_tests/llui_libtest/llui_libtest.h
@@ -0,0 +1,36 @@
+/**
+ * @file llui_libtest.h
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef LLUI_LIBTEST_H
+#define LLUI_LIBTEST_H
+
+// TODO
+
+#endif
diff --git a/indra/integration_tests/llui_libtest/llwidgetreg.cpp b/indra/integration_tests/llui_libtest/llwidgetreg.cpp
new file mode 100644
index 0000000000..c6e2e79a09
--- /dev/null
+++ b/indra/integration_tests/llui_libtest/llwidgetreg.cpp
@@ -0,0 +1,109 @@
+/**
+ * @file llwidgetreg.cpp
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+
+#include "llwidgetreg.h"
+
+#include "llbutton.h"
+#include "llcheckboxctrl.h"
+#include "llcombobox.h"
+#include "llcontainerview.h"
+#include "lliconctrl.h"
+#include "llmenubutton.h"
+#include "llmenugl.h"
+#include "llmultislider.h"
+#include "llmultisliderctrl.h"
+#include "llprogressbar.h"
+#include "llradiogroup.h"
+#include "llsearcheditor.h"
+#include "llscrollcontainer.h"
+#include "llscrollingpanellist.h"
+#include "llscrolllistctrl.h"
+#include "llslider.h"
+#include "llsliderctrl.h"
+#include "llspinctrl.h"
+#include "llstatview.h"
+#include "lltabcontainer.h"
+#include "lltextbox.h"
+#include "lltexteditor.h"
+#include "llflyoutbutton.h"
+#include "llfiltereditor.h"
+#include "lllayoutstack.h"
+
+void LLWidgetReg::initClass(bool register_widgets)
+{
+ // Only need to register if the Windows linker has optimized away the
+ // references to the object files.
+ if (register_widgets)
+ {
+ LLDefaultChildRegistry::Register<LLButton> button("button");
+ LLDefaultChildRegistry::Register<LLMenuButton> menu_button("menu_button");
+ LLDefaultChildRegistry::Register<LLCheckBoxCtrl> check_box("check_box");
+ LLDefaultChildRegistry::Register<LLComboBox> combo_box("combo_box");
+ LLDefaultChildRegistry::Register<LLFilterEditor> filter_editor("filter_editor");
+ LLDefaultChildRegistry::Register<LLFlyoutButton> flyout_button("flyout_button");
+ LLDefaultChildRegistry::Register<LLContainerView> container_view("container_view");
+ LLDefaultChildRegistry::Register<LLIconCtrl> icon("icon");
+ LLDefaultChildRegistry::Register<LLLineEditor> line_editor("line_editor");
+ LLDefaultChildRegistry::Register<LLMenuItemSeparatorGL> menu_item_separator("menu_item_separator");
+ LLDefaultChildRegistry::Register<LLMenuItemCallGL> menu_item_call_gl("menu_item_call");
+ LLDefaultChildRegistry::Register<LLMenuItemCheckGL> menu_item_check_gl("menu_item_check");
+ LLDefaultChildRegistry::Register<LLMenuGL> menu("menu");
+ LLDefaultChildRegistry::Register<LLMenuBarGL> menu_bar("menu_bar");
+ LLDefaultChildRegistry::Register<LLContextMenu> context_menu("context_menu");
+ LLDefaultChildRegistry::Register<LLMultiSlider> multi_slider_bar("multi_slider_bar");
+ LLDefaultChildRegistry::Register<LLMultiSliderCtrl> multi_slider("multi_slider");
+ LLDefaultChildRegistry::Register<LLPanel> panel("panel", &LLPanel::fromXML);
+ LLDefaultChildRegistry::Register<LLLayoutStack> layout_stack("layout_stack", &LLLayoutStack::fromXML);
+ LLDefaultChildRegistry::Register<LLProgressBar> progress_bar("progress_bar");
+ LLDefaultChildRegistry::Register<LLRadioGroup> radio_group("radio_group");
+ LLDefaultChildRegistry::Register<LLSearchEditor> search_editor("search_editor");
+ LLDefaultChildRegistry::Register<LLScrollContainer> scroll_container("scroll_container");
+ LLDefaultChildRegistry::Register<LLScrollingPanelList> scrolling_panel_list("scrolling_panel_list");
+ LLDefaultChildRegistry::Register<LLScrollListCtrl> scroll_list("scroll_list");
+ LLDefaultChildRegistry::Register<LLSlider> slider_bar("slider_bar");
+ LLDefaultChildRegistry::Register<LLSliderCtrl> slider("slider");
+ LLDefaultChildRegistry::Register<LLSpinCtrl> spinner("spinner");
+ LLDefaultChildRegistry::Register<LLStatBar> stat_bar("stat_bar");
+ //LLDefaultChildRegistry::Register<LLPlaceHolderPanel> placeholder("placeholder");
+ LLDefaultChildRegistry::Register<LLTabContainer> tab_container("tab_container");
+ LLDefaultChildRegistry::Register<LLTextBox> text("text");
+ LLDefaultChildRegistry::Register<LLTextEditor> simple_text_editor("simple_text_editor");
+ LLDefaultChildRegistry::Register<LLUICtrl> ui_ctrl("ui_ctrl");
+ LLDefaultChildRegistry::Register<LLStatView> stat_view("stat_view");
+ //LLDefaultChildRegistry::Register<LLUICtrlLocate> locate("locate");
+ //LLDefaultChildRegistry::Register<LLUICtrlLocate> pad("pad");
+ LLDefaultChildRegistry::Register<LLViewBorder> view_border("view_border");
+ }
+
+ // *HACK: Usually this is registered as a viewer text editor
+ LLDefaultChildRegistry::Register<LLTextEditor> text_editor("text_editor");
+}
diff --git a/indra/integration_tests/llui_libtest/llwidgetreg.h b/indra/integration_tests/llui_libtest/llwidgetreg.h
new file mode 100644
index 0000000000..4e0bc5377a
--- /dev/null
+++ b/indra/integration_tests/llui_libtest/llwidgetreg.h
@@ -0,0 +1,43 @@
+/**
+ * @file llwidgetreg.h
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef LLWIDGETREG_H
+#define LLWIDGETREG_H
+
+// Register all widgets with the builder registry.
+// Useful on Windows where linker discards all references to the
+// static LLDefaultChildRegistry::Register<> calls.
+class LLWidgetReg
+{
+public:
+ static void initClass(bool register_widgets);
+};
+
+#endif
diff --git a/indra/lib/python/indra/base/llsd.py b/indra/lib/python/indra/base/llsd.py
index 1190d88663..4527b115f9 100644
--- a/indra/lib/python/indra/base/llsd.py
+++ b/indra/lib/python/indra/base/llsd.py
@@ -238,7 +238,7 @@ class LLSDXMLFormatter(object):
def MAP(self, v):
return self.elt(
'map',
- ''.join(["%s%s" % (self.elt('key', key), self.generate(value))
+ ''.join(["%s%s" % (self.elt('key', self.xml_esc(str(key))), self.generate(value))
for key, value in v.items()]))
typeof = type
diff --git a/indra/lib/python/indra/base/lluuid.py b/indra/lib/python/indra/base/lluuid.py
index aceea29cd2..1cdd8e915b 100644
--- a/indra/lib/python/indra/base/lluuid.py
+++ b/indra/lib/python/indra/base/lluuid.py
@@ -26,8 +26,14 @@ THE SOFTWARE.
$/LicenseInfo$
"""
-import md5, random, socket, string, time, re
+import random, socket, string, time, re
import uuid
+try:
+ # Python 2.6
+ from hashlib import md5
+except ImportError:
+ # Python 2.5 and earlier
+ from md5 import new as md5
def _int2binstr(i,l):
s=''
@@ -196,7 +202,7 @@ class UUID(object):
from c++ implementation for portability reasons.
Returns self.
"""
- m = md5.new()
+ m = md5()
m.update(uuid.uuid1().bytes)
self._bits = m.digest()
return self
diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py
index 59c84e571b..7e5b86c53f 100644
--- a/indra/lib/python/indra/util/llmanifest.py
+++ b/indra/lib/python/indra/util/llmanifest.py
@@ -119,10 +119,10 @@ ARGUMENTS=[
On Linux this would try to use Linux_i686Manifest.""",
default=""),
dict(name='build', description='Build directory.', default=DEFAULT_SRCTREE),
+ dict(name='buildtype', description='Build type (i.e. Debug, Release, RelWithDebInfo).', default=None),
dict(name='configuration',
- description="""The build configuration used. Only used on OS X for
- now, but it could be used for other platforms as well.""",
- default="Universal"),
+ description="""The build configuration used.""",
+ default="Release"),
dict(name='dest', description='Destination directory.', default=DEFAULT_SRCTREE),
dict(name='grid',
description="""Which grid the client will try to connect to. Even
diff --git a/indra/lib/python/indra/util/llsubprocess.py b/indra/lib/python/indra/util/llsubprocess.py
index c4c40739ec..7e0e115d14 100644
--- a/indra/lib/python/indra/util/llsubprocess.py
+++ b/indra/lib/python/indra/util/llsubprocess.py
@@ -90,6 +90,17 @@ all the output, and get the result.
child.tochild.close()
result = child.poll()
if result != -1:
+ # At this point, the child process has exited and result
+ # is the return value from the process. Between the time
+ # we called select() and poll() the process may have
+ # exited so read all the data left on the child process
+ # stdout and stderr.
+ last = child.fromchild.read()
+ if last:
+ out.append(last)
+ last = child.childerr.read()
+ if last:
+ err.append(last)
child.tochild.close()
child.fromchild.close()
child.childerr.close()
diff --git a/indra/lib/python/indra/util/llversion.py b/indra/lib/python/indra/util/llversion.py
index 770b861ddc..2718a85f41 100644
--- a/indra/lib/python/indra/util/llversion.py
+++ b/indra/lib/python/indra/util/llversion.py
@@ -1,7 +1,7 @@
"""@file llversion.py
@brief Utility for parsing llcommon/llversion${server}.h
for the version string and channel string
- Utility that parses svn info for branch and revision
+ Utility that parses hg or svn info for branch and revision
$LicenseInfo:firstyear=2006&license=mit$
@@ -79,8 +79,8 @@ def get_svn_status_matching(regular_expression):
status, output = commands.getstatusoutput('svn info %s' % get_src_root())
m = regular_expression.search(output)
if not m:
- print "Failed to parse svn info output, resultfollows:"
- print output
+ print >> sys.stderr, "Failed to parse svn info output, result follows:"
+ print >> sys.stderr, output
raise Exception, "No matching svn status in "+src_root
return m.group(1)
@@ -92,4 +92,35 @@ def get_svn_revision():
last_rev_re = re.compile('Last Changed Rev: (\d+)')
return get_svn_status_matching(last_rev_re)
-
+def get_hg_repo():
+ status, output = commands.getstatusoutput('hg showconfig paths.default')
+ if status:
+ print >> sys.stderr, output
+ sys.exit(1)
+ if not output:
+ print >> sys.stderr, 'ERROR: cannot find repo we cloned from'
+ sys.exit(1)
+ return output
+
+def get_hg_changeset():
+ # The right thing to do:
+ # status, output = commands.getstatusoutput('hg id -i')
+ # if status:
+ # print >> sys.stderr, output
+ # sys.exit(1)
+
+ # The temporary hack:
+ status, output = commands.getstatusoutput('hg parents --template "{rev}"')
+ if status:
+ print >> sys.stderr, output
+ sys.exit(1)
+ lines = output.splitlines()
+ if len(lines) > 1:
+ print >> sys.stderr, 'ERROR: working directory has %d parents' % len(lines)
+ return lines[0]
+
+def using_svn():
+ return os.path.isdir(os.path.join(get_src_root(), '.svn'))
+
+def using_hg():
+ return os.path.isdir(os.path.join(get_src_root(), '.hg'))
diff --git a/indra/lib/python/indra/util/named_query.py b/indra/lib/python/indra/util/named_query.py
index 693b483f79..5c19368240 100644
--- a/indra/lib/python/indra/util/named_query.py
+++ b/indra/lib/python/indra/util/named_query.py
@@ -48,8 +48,8 @@ from indra.base import llsd
from indra.base import config
DEBUG = False
-NQ_FILE_SUFFIX = None
-NQ_FILE_SUFFIX_LEN = None
+NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq')
+NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX)
_g_named_manager = None
diff --git a/indra/lib/python/indra/util/test_win32_manifest.py b/indra/lib/python/indra/util/test_win32_manifest.py
new file mode 100644
index 0000000000..0149b9f43a
--- /dev/null
+++ b/indra/lib/python/indra/util/test_win32_manifest.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python
+# @file test_win32_manifest.py
+# @brief Test an assembly binding version and uniqueness in a windows dll or exe.
+#
+# $LicenseInfo:firstyear=2009&license=viewergpl$
+#
+# Copyright (c) 2009, Linden Research, Inc.
+#
+# Second Life Viewer Source Code
+# The source code in this file ("Source Code") is provided by Linden Lab
+# to you under the terms of the GNU General Public License, version 2.0
+# ("GPL"), unless you have obtained a separate licensing agreement
+# ("Other License"), formally executed by you and Linden Lab. Terms of
+# the GPL can be found in doc/GPL-license.txt in this distribution, or
+# online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+#
+# There are special exceptions to the terms and conditions of the GPL as
+# it is applied to this Source Code. View the full text of the exception
+# in the file doc/FLOSS-exception.txt in this software distribution, or
+# online at
+# http://secondlifegrid.net/programs/open_source/licensing/flossexception
+#
+# By copying, modifying or distributing this software, you acknowledge
+# that you have read and understood your obligations described above,
+# and agree to abide by those obligations.
+#
+# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+# COMPLETENESS OR PERFORMANCE.
+# $/LicenseInfo$
+
+import sys, os
+import tempfile
+from xml.dom.minidom import parse
+
+class AssemblyTestException(Exception):
+ pass
+
+class NoManifestException(AssemblyTestException):
+ pass
+
+class MultipleBindingsException(AssemblyTestException):
+ pass
+
+class UnexpectedVersionException(AssemblyTestException):
+ pass
+
+class NoMatchingAssemblyException(AssemblyTestException):
+ pass
+
+def get_HKLM_registry_value(key_str, value_str):
+ import _winreg
+ reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
+ key = _winreg.OpenKey(reg, key_str)
+ value = _winreg.QueryValueEx(key, value_str)[0]
+ #print 'Found: %s' % value
+ return value
+
+def find_vc_dir():
+ supported_versions = (r'8.0', r'9.0')
+ value_str = (r'ProductDir')
+
+ for version in supported_versions:
+ key_str = (r'SOFTWARE\Microsoft\VisualStudio\%s\Setup\VC' %
+ version)
+ try:
+ return get_HKLM_registry_value(key_str, value_str)
+ except WindowsError, err:
+ x64_key_str = (r'SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%s\Setup\VS' %
+ version)
+ try:
+ return get_HKLM_registry_value(x64_key_str, value_str)
+ except:
+ print >> sys.stderr, "Didn't find MS VC version %s " % version
+
+ raise
+
+def find_mt_path():
+ vc_dir = find_vc_dir()
+ mt_path = '\"%sbin\\mt.exe\"' % vc_dir
+ return mt_path
+
+def test_assembly_binding(src_filename, assembly_name, assembly_ver):
+ print "checking %s dependency %s..." % (src_filename, assembly_name)
+
+ (tmp_file_fd, tmp_file_name) = tempfile.mkstemp(suffix='.xml')
+ tmp_file = os.fdopen(tmp_file_fd)
+ tmp_file.close()
+
+ mt_path = find_mt_path()
+ resource_id = ""
+ if os.path.splitext(src_filename)[1].lower() == ".dll":
+ resource_id = ";#2"
+ system_call = '%s -nologo -inputresource:%s%s -out:%s > NUL' % (mt_path, src_filename, resource_id, tmp_file_name)
+ print "Executing: %s" % system_call
+ mt_result = os.system(system_call)
+ if mt_result == 31:
+ print "No manifest found in %s" % src_filename
+ raise NoManifestException()
+
+ manifest_dom = parse(tmp_file_name)
+ nodes = manifest_dom.getElementsByTagName('assemblyIdentity')
+
+ versions = list()
+ for node in nodes:
+ if node.getAttribute('name') == assembly_name:
+ versions.append(node.getAttribute('version'))
+
+ if len(versions) == 0:
+ print "No matching assemblies found in %s" % src_filename
+ raise NoMatchingAssemblyException()
+
+ elif len(versions) > 1:
+ print "Multiple bindings to %s found:" % assembly_name
+ print versions
+ print
+ raise MultipleBindingsException(versions)
+
+ elif versions[0] != assembly_ver:
+ print "Unexpected version found for %s:" % assembly_name
+ print "Wanted %s, found %s" % (assembly_ver, versions[0])
+ print
+ raise UnexpectedVersionException(assembly_ver, versions[0])
+
+ os.remove(tmp_file_name)
+
+ print "SUCCESS: %s OK!" % src_filename
+ print
+
+if __name__ == '__main__':
+
+ print
+ print "Running test_win32_manifest.py..."
+
+ usage = 'test_win32_manfest <srcFileName> <assemblyName> <assemblyVersion>'
+
+ try:
+ src_filename = sys.argv[1]
+ assembly_name = sys.argv[2]
+ assembly_ver = sys.argv[3]
+ except:
+ print "Usage:"
+ print usage
+ print
+ raise
+
+ test_assembly_binding(src_filename, assembly_name, assembly_ver)
+
+
diff --git a/indra/linux_crash_logger/CMakeLists.txt b/indra/linux_crash_logger/CMakeLists.txt
index 6f6754ed7a..4b19e28066 100644
--- a/indra/linux_crash_logger/CMakeLists.txt
+++ b/indra/linux_crash_logger/CMakeLists.txt
@@ -38,7 +38,7 @@ list(APPEND linux_crash_logger_SOURCE_FILES
${linux_crash_logger_HEADER_FILES}
)
-list(APPEND CMAKE_EXE_LINKER_FLAGS -Wl,--as-needed)
+set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed")
add_executable(linux-crash-logger ${linux_crash_logger_SOURCE_FILES})
diff --git a/indra/linux_updater/CMakeLists.txt b/indra/linux_updater/CMakeLists.txt
new file mode 100644
index 0000000000..9fe32ecb46
--- /dev/null
+++ b/indra/linux_updater/CMakeLists.txt
@@ -0,0 +1,58 @@
+# -*- cmake -*-
+
+project(linux_updater)
+
+include(00-Common)
+include(CURL)
+include(CARes)
+include(OpenSSL)
+include(UI)
+include(LLCommon)
+include(LLVFS)
+include(LLXML)
+include(LLXUIXML)
+include(Linking)
+
+include_directories(
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LLVFS_INCLUDE_DIRS}
+ ${LLXML_INCLUDE_DIRS}
+ ${LLXUIXML_INCLUDE_DIRS}
+ ${CURL_INCLUDE_DIRS}
+ ${CARES_INCLUDE_DIRS}
+ ${OPENSSL_INCLUDE_DIRS}
+ ${UI_INCLUDE_DIRS}
+ )
+
+set(linux_updater_SOURCE_FILES linux_updater.cpp)
+
+set(linux_updater_HEADER_FILES CMakeLists.txt)
+
+set_source_files_properties(${linux_updater_HEADER_FILES}
+ PROPERTIES HEADER_FILES_ONLY TRUE)
+
+list(APPEND linux_updater_SOURCE_FILES ${linux_updater_HEADER_FILES})
+
+add_executable(linux-updater ${linux_updater_SOURCE_FILES})
+
+target_link_libraries(linux-updater
+ ${CURL_LIBRARIES}
+ ${CARES_LIBRARIES}
+ ${OPENSSL_LIBRARIES}
+ ${CRYPTO_LIBRARIES}
+ ${UI_LIBRARIES}
+ ${LLXML_LIBRARIES}
+ ${LLXUIXML_LIBRARIES}
+ ${LLVFS_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+ )
+
+add_custom_command(
+ OUTPUT linux-updater-stripped
+ COMMAND strip
+ ARGS --strip-debug -o linux-updater-stripped linux-updater
+ DEPENDS linux-updater
+ )
+
+add_custom_target(linux-updater-strip-target ALL
+ DEPENDS linux-updater-stripped)
diff --git a/indra/linux_updater/linux_updater.cpp b/indra/linux_updater/linux_updater.cpp
new file mode 100644
index 0000000000..d5fee2828e
--- /dev/null
+++ b/indra/linux_updater/linux_updater.cpp
@@ -0,0 +1,818 @@
+/**
+ * @file linux_updater.cpp
+ * @author Kyle Ambroff <ambroff@lindenlab.com>, Tofu Linden
+ * @brief Viewer update program for unix platforms that support GTK+
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+
+#include "linden_common.h"
+#include "llerrorcontrol.h"
+#include "llfile.h"
+#include "lldir.h"
+#include "llxmlnode.h"
+#include "lltrans.h"
+
+#include <curl/curl.h>
+
+extern "C" {
+#include <gtk/gtk.h>
+}
+
+const guint UPDATE_PROGRESS_TIMEOUT = 100;
+const guint UPDATE_PROGRESS_TEXT_TIMEOUT = 1000;
+const guint ROTATE_IMAGE_TIMEOUT = 8000;
+
+typedef struct _updater_app_state {
+ std::string app_name;
+ std::string url;
+ std::string image_dir;
+ std::string dest_dir;
+ std::string strings_dirs;
+ std::string strings_file;
+
+ GtkWidget *window;
+ GtkWidget *progress_bar;
+ GtkWidget *image;
+
+ double progress_value;
+ bool activity_mode;
+
+ guint image_rotation_timeout_id;
+ guint progress_update_timeout_id;
+ guint update_progress_text_timeout_id;
+
+ bool failure;
+} UpdaterAppState;
+
+// List of entries from strings.xml to always replace
+static std::set<std::string> default_trans_args;
+void init_default_trans_args()
+{
+ default_trans_args.insert("SECOND_LIFE"); // World
+ default_trans_args.insert("APP_NAME");
+ default_trans_args.insert("SECOND_LIFE_GRID");
+ default_trans_args.insert("SUPPORT_SITE");
+}
+
+bool translate_init(std::string comma_delim_path_list,
+ std::string base_xml_name)
+{
+ init_default_trans_args();
+
+ // extract paths string vector from comma-delimited flat string
+ std::vector<std::string> paths;
+ LLStringUtil::getTokens(comma_delim_path_list, paths, ","); // split over ','
+
+ // suck the translation xml files into memory
+ LLXMLNodePtr root;
+ bool success = LLXMLNode::getLayeredXMLNode(base_xml_name, root, paths);
+ if (!success)
+ {
+ // couldn't load string table XML
+ return false;
+ }
+ else
+ {
+ // get those strings out of the XML
+ LLTrans::parseStrings(root, default_trans_args);
+ return true;
+ }
+}
+
+
+void updater_app_ui_init(void);
+void updater_app_quit(UpdaterAppState *app_state);
+void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state);
+std::string next_image_filename(std::string& image_path);
+void display_error(GtkWidget *parent, std::string title, std::string message);
+BOOL install_package(std::string package_file, std::string destination);
+BOOL spawn_viewer(UpdaterAppState *app_state);
+
+extern "C" {
+ void on_window_closed(GtkWidget *sender, gpointer state);
+ gpointer worker_thread_cb(gpointer *data);
+ int download_progress_cb(gpointer data, double t, double d, double utotal, double ulnow);
+ gboolean rotate_image_cb(gpointer data);
+ gboolean progress_update_timeout(gpointer data);
+ gboolean update_progress_text_timeout(gpointer data);
+}
+
+void updater_app_ui_init(UpdaterAppState *app_state)
+{
+ GtkWidget *vbox;
+ GtkWidget *summary_label;
+ GtkWidget *description_label;
+ GtkWidget *frame;
+
+ llassert(app_state != NULL);
+
+ // set up window and main container
+ std::string window_title = LLTrans::getString("UpdaterWindowTitle");
+ app_state->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(app_state->window),
+ window_title.c_str());
+ gtk_window_set_resizable(GTK_WINDOW(app_state->window), FALSE);
+ gtk_window_set_position(GTK_WINDOW(app_state->window),
+ GTK_WIN_POS_CENTER_ALWAYS);
+
+ gtk_container_set_border_width(GTK_CONTAINER(app_state->window), 12);
+ g_signal_connect(G_OBJECT(app_state->window), "delete-event",
+ G_CALLBACK(on_window_closed), app_state);
+
+ vbox = gtk_vbox_new(FALSE, 6);
+ gtk_container_add(GTK_CONTAINER(app_state->window), vbox);
+
+ // set top label
+ std::ostringstream label_ostr;
+ label_ostr << "<big><b>"
+ << LLTrans::getString("UpdaterNowUpdating")
+ << "</b></big>";
+
+ summary_label = gtk_label_new(NULL);
+ gtk_label_set_use_markup(GTK_LABEL(summary_label), TRUE);
+ gtk_label_set_markup(GTK_LABEL(summary_label),
+ label_ostr.str().c_str());
+ gtk_misc_set_alignment(GTK_MISC(summary_label), 0, 0.5);
+ gtk_box_pack_start(GTK_BOX(vbox), summary_label, FALSE, FALSE, 0);
+
+ // create the description label
+ description_label = gtk_label_new(LLTrans::getString("UpdaterUpdatingDescriptive").c_str());
+ gtk_label_set_line_wrap(GTK_LABEL(description_label), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(description_label), 0, 0.5);
+ gtk_box_pack_start(GTK_BOX(vbox), description_label, FALSE, FALSE, 0);
+
+ // If an image path has been set, load the background images
+ if (!app_state->image_dir.empty()) {
+ frame = gtk_frame_new(NULL);
+ gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
+ gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
+
+ // load the first image
+ app_state->image = gtk_image_new_from_file
+ (next_image_filename(app_state->image_dir).c_str());
+ gtk_widget_set_size_request(app_state->image, 340, 310);
+ gtk_container_add(GTK_CONTAINER(frame), app_state->image);
+
+ // rotate the images every 5 seconds
+ app_state->image_rotation_timeout_id = g_timeout_add
+ (ROTATE_IMAGE_TIMEOUT, rotate_image_cb, app_state);
+ }
+
+ // set up progress bar, and update it roughly every 1/10 of a second
+ app_state->progress_bar = gtk_progress_bar_new();
+ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(app_state->progress_bar),
+ LLTrans::getString("UpdaterProgressBarTextWithEllipses").c_str());
+ gtk_box_pack_start(GTK_BOX(vbox),
+ app_state->progress_bar, FALSE, TRUE, 0);
+ app_state->progress_update_timeout_id = g_timeout_add
+ (UPDATE_PROGRESS_TIMEOUT, progress_update_timeout, app_state);
+ app_state->update_progress_text_timeout_id = g_timeout_add
+ (UPDATE_PROGRESS_TEXT_TIMEOUT, update_progress_text_timeout, app_state);
+
+ gtk_widget_show_all(app_state->window);
+}
+
+gboolean rotate_image_cb(gpointer data)
+{
+ UpdaterAppState *app_state;
+ std::string filename;
+
+ llassert(data != NULL);
+ app_state = (UpdaterAppState *) data;
+
+ filename = next_image_filename(app_state->image_dir);
+
+ gdk_threads_enter();
+ gtk_image_set_from_file(GTK_IMAGE(app_state->image), filename.c_str());
+ gdk_threads_leave();
+
+ return TRUE;
+}
+
+std::string next_image_filename(std::string& image_path)
+{
+ std::string image_filename;
+ gDirUtilp->getNextFileInDir(image_path, "/*.jpg", image_filename, true);
+ return image_path + "/" + image_filename;
+}
+
+void on_window_closed(GtkWidget *sender, gpointer data)
+{
+ UpdaterAppState *app_state;
+
+ llassert(data != NULL);
+ app_state = (UpdaterAppState *) data;
+
+ updater_app_quit(app_state);
+}
+
+void updater_app_quit(UpdaterAppState *app_state)
+{
+ if (app_state != NULL)
+ {
+ g_source_remove(app_state->progress_update_timeout_id);
+
+ if (!app_state->image_dir.empty())
+ {
+ g_source_remove(app_state->image_rotation_timeout_id);
+ }
+ }
+
+ gtk_main_quit();
+}
+
+void display_error(GtkWidget *parent, std::string title, std::string message)
+{
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new(GTK_WINDOW(parent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ "%s", message.c_str());
+ gtk_window_set_title(GTK_WINDOW(dialog), title.c_str());
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+}
+
+gpointer worker_thread_cb(gpointer data)
+{
+ UpdaterAppState *app_state;
+ CURL *curl;
+ CURLcode result;
+ FILE *package_file;
+ GError *error = NULL;
+ char *tmp_filename = NULL;
+ int fd;
+
+ //g_return_val_if_fail (data != NULL, NULL);
+ app_state = (UpdaterAppState *) data;
+
+ try {
+ // create temporary file to store the package.
+ fd = g_file_open_tmp
+ ("secondlife-update-XXXXXX", &tmp_filename, &error);
+ if (error != NULL)
+ {
+ llerrs << "Unable to create temporary file: "
+ << error->message
+ << llendl;
+
+ g_error_free(error);
+ throw 0;
+ }
+
+ package_file = fdopen(fd, "wb");
+ if (package_file == NULL)
+ {
+ llerrs << "Failed to create temporary file: "
+ << tmp_filename
+ << llendl;
+
+ gdk_threads_enter();
+ display_error(app_state->window,
+ LLTrans::getString("UpdaterFailDownloadTitle"),
+ LLTrans::getString("UpdaterFailUpdateDescriptive"));
+ gdk_threads_leave();
+ throw 0;
+ }
+
+ // initialize curl and start downloading the package
+ llinfos << "Downloading package: " << app_state->url << llendl;
+
+ curl = curl_easy_init();
+ if (curl == NULL)
+ {
+ llerrs << "Failed to initialize libcurl" << llendl;
+
+ gdk_threads_enter();
+ display_error(app_state->window,
+ LLTrans::getString("UpdaterFailDownloadTitle"),
+ LLTrans::getString("UpdaterFailUpdateDescriptive"));
+ gdk_threads_leave();
+ throw 0;
+ }
+
+ curl_easy_setopt(curl, CURLOPT_URL, app_state->url.c_str());
+ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, TRUE);
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, TRUE);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, package_file);
+ curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
+ curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION,
+ &download_progress_cb);
+ curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, app_state);
+
+ result = curl_easy_perform(curl);
+ fclose(package_file);
+ curl_easy_cleanup(curl);
+
+ if (result)
+ {
+ llerrs << "Failed to download update: "
+ << app_state->url
+ << llendl;
+
+ gdk_threads_enter();
+ display_error(app_state->window,
+ LLTrans::getString("UpdaterFailDownloadTitle"),
+ LLTrans::getString("UpdaterFailUpdateDescriptive"));
+ gdk_threads_leave();
+
+ throw 0;
+ }
+
+ // now pulse the progres bar back and forth while the package is
+ // being unpacked
+ gdk_threads_enter();
+ std::string installing_msg = LLTrans::getString("UpdaterNowInstalling");
+ gtk_progress_bar_set_text(
+ GTK_PROGRESS_BAR(app_state->progress_bar),
+ installing_msg.c_str());
+ app_state->activity_mode = TRUE;
+ gdk_threads_leave();
+
+ // *TODO: if the destination is not writable, terminate this
+ // thread and show file chooser?
+ if (!install_package(tmp_filename, app_state->dest_dir))
+ {
+ llwarns << "Failed to install package to destination: "
+ << app_state->dest_dir
+ << llendl;
+
+ gdk_threads_enter();
+ display_error(app_state->window,
+ LLTrans::getString("UpdaterFailInstallTitle"),
+ LLTrans::getString("UpdaterFailUpdateDescriptive"));
+ //"Failed to update " + app_state->app_name,
+ gdk_threads_leave();
+ throw 0;
+ }
+
+ // try to spawn the new viewer
+ if (!spawn_viewer(app_state))
+ {
+ llwarns << "Viewer was not installed properly in : "
+ << app_state->dest_dir
+ << llendl;
+
+ gdk_threads_enter();
+ display_error(app_state->window,
+ LLTrans::getString("UpdaterFailStartTitle"),
+ LLTrans::getString("UpdaterFailUpdateDescriptive"));
+ gdk_threads_leave();
+ throw 0;
+ }
+ }
+ catch (...)
+ {
+ app_state->failure = TRUE;
+ }
+
+ // FIXME: delete package file also if delete-event is raised on window
+ if (tmp_filename != NULL)
+ {
+ if (gDirUtilp->fileExists(tmp_filename))
+ {
+ LLFile::remove(tmp_filename);
+ }
+ }
+
+ gdk_threads_enter();
+ updater_app_quit(app_state);
+ gdk_threads_leave();
+
+ return NULL;
+}
+
+
+gboolean less_anal_gspawnsync(gchar **argv,
+ gchar **stderr_output,
+ gint *child_exit_status,
+ GError **spawn_error)
+{
+ // store current SIGCHLD handler if there is one, replace with default
+ // handler to make glib happy
+ struct sigaction sigchld_backup;
+ struct sigaction sigchld_appease_glib;
+ sigchld_appease_glib.sa_handler = SIG_DFL;
+ sigemptyset(&sigchld_appease_glib.sa_mask);
+ sigchld_appease_glib.sa_flags = 0;
+ sigaction(SIGCHLD, &sigchld_appease_glib, &sigchld_backup);
+
+ gboolean rtn = g_spawn_sync(NULL,
+ argv,
+ NULL,
+ (GSpawnFlags) (G_SPAWN_STDOUT_TO_DEV_NULL),
+ NULL,
+ NULL,
+ NULL,
+ stderr_output,
+ child_exit_status,
+ spawn_error);
+
+ // restore SIGCHLD handler
+ sigaction(SIGCHLD, &sigchld_backup, NULL);
+
+ return rtn;
+}
+
+
+// perform a rename, or perform a (prompted) root rename if that fails
+int
+rename_with_sudo_fallback(const std::string& filename, const std::string& newname)
+{
+ int rtncode = ::rename(filename.c_str(), newname.c_str());
+ lldebugs << "rename result is: " << rtncode << " / " << errno << llendl;
+ if (rtncode && (EACCES == errno || EPERM == errno || EXDEV == errno))
+ {
+ llinfos << "Permission problem in rename, or moving between different mount points. Retrying as a mv under a sudo." << llendl;
+ // failed due to permissions, try again as a gksudo or kdesu mv wrapper hack
+ char *sudo_cmd = NULL;
+ sudo_cmd = g_find_program_in_path("gksudo");
+ if (!sudo_cmd)
+ {
+ sudo_cmd = g_find_program_in_path("kdesu");
+ }
+ if (sudo_cmd)
+ {
+ char *mv_cmd = NULL;
+ mv_cmd = g_find_program_in_path("mv");
+ if (mv_cmd)
+ {
+ char *src_string_copy = g_strdup(filename.c_str());
+ char *dst_string_copy = g_strdup(newname.c_str());
+ char* argv[] =
+ {
+ sudo_cmd,
+ mv_cmd,
+ src_string_copy,
+ dst_string_copy,
+ NULL
+ };
+
+ gchar *stderr_output = NULL;
+ gint child_exit_status = 0;
+ GError *spawn_error = NULL;
+ if (!less_anal_gspawnsync(argv, &stderr_output,
+ &child_exit_status, &spawn_error))
+ {
+ llwarns << "Failed to spawn child process: "
+ << spawn_error->message
+ << llendl;
+ }
+ else if (child_exit_status)
+ {
+ llwarns << "mv command failed: "
+ << (stderr_output ? stderr_output : "(no reason given)")
+ << llendl;
+ }
+ else
+ {
+ // everything looks good, clear the error code
+ rtncode = 0;
+ }
+
+ g_free(src_string_copy);
+ g_free(dst_string_copy);
+ if (spawn_error) g_error_free(spawn_error);
+ }
+ }
+ }
+ return rtncode;
+}
+
+gboolean install_package(std::string package_file, std::string destination)
+{
+ char *tar_cmd = NULL;
+ std::ostringstream command;
+
+ // Find the absolute path to the 'tar' command.
+ tar_cmd = g_find_program_in_path("tar");
+ if (!tar_cmd)
+ {
+ llerrs << "`tar' was not found in $PATH" << llendl;
+ return FALSE;
+ }
+ llinfos << "Found tar command: " << tar_cmd << llendl;
+
+ // Unpack the tarball in a temporary place first, then move it to
+ // its final destination
+ std::string tmp_dest_dir = gDirUtilp->getTempFilename();
+ if (LLFile::mkdir(tmp_dest_dir, 0744))
+ {
+ llerrs << "Failed to create directory: "
+ << destination
+ << llendl;
+
+ return FALSE;
+ }
+
+ char *package_file_string_copy = g_strdup(package_file.c_str());
+ char *tmp_dest_dir_string_copy = g_strdup(tmp_dest_dir.c_str());
+ gchar *argv[8] = {
+ tar_cmd,
+ const_cast<gchar*>("--strip"), const_cast<gchar*>("1"),
+ const_cast<gchar*>("-xjf"),
+ package_file_string_copy,
+ const_cast<gchar*>("-C"), tmp_dest_dir_string_copy,
+ NULL,
+ };
+
+ llinfos << "Untarring package: " << package_file << llendl;
+
+ // store current SIGCHLD handler if there is one, replace with default
+ // handler to make glib happy
+ struct sigaction sigchld_backup;
+ struct sigaction sigchld_appease_glib;
+ sigchld_appease_glib.sa_handler = SIG_DFL;
+ sigemptyset(&sigchld_appease_glib.sa_mask);
+ sigchld_appease_glib.sa_flags = 0;
+ sigaction(SIGCHLD, &sigchld_appease_glib, &sigchld_backup);
+
+ gchar *stderr_output = NULL;
+ gint child_exit_status = 0;
+ GError *untar_error = NULL;
+ if (!less_anal_gspawnsync(argv, &stderr_output,
+ &child_exit_status, &untar_error))
+ {
+ llwarns << "Failed to spawn child process: "
+ << untar_error->message
+ << llendl;
+ return FALSE;
+ }
+
+ if (child_exit_status)
+ {
+ llwarns << "Untar command failed: "
+ << (stderr_output ? stderr_output : "(no reason given)")
+ << llendl;
+ return FALSE;
+ }
+
+ g_free(tar_cmd);
+ g_free(package_file_string_copy);
+ g_free(tmp_dest_dir_string_copy);
+ g_free(stderr_output);
+ if (untar_error) g_error_free(untar_error);
+
+ // move the existing package out of the way if it exists
+ if (gDirUtilp->fileExists(destination))
+ {
+ std::string backup_dir = destination + ".backup";
+ int oldcounter = 1;
+ while (gDirUtilp->fileExists(backup_dir))
+ {
+ // find a foo.backup.N folder name that isn't taken yet
+ backup_dir = destination + ".backup." + llformat("%d", oldcounter);
+ ++oldcounter;
+ }
+
+ if (rename_with_sudo_fallback(destination, backup_dir))
+ {
+ llwarns << "Failed to move directory: '"
+ << destination << "' -> '" << backup_dir
+ << llendl;
+ return FALSE;
+ }
+ }
+
+ // The package has been unpacked in a staging directory, now we just
+ // need to move it to its destination.
+ if (rename_with_sudo_fallback(tmp_dest_dir, destination))
+ {
+ llwarns << "Failed to move installation to the destination: "
+ << destination
+ << llendl;
+ return FALSE;
+ }
+
+ // \0/ Success!
+ return TRUE;
+}
+
+gboolean progress_update_timeout(gpointer data)
+{
+ UpdaterAppState *app_state;
+
+ llassert(data != NULL);
+
+ app_state = (UpdaterAppState *) data;
+
+ gdk_threads_enter();
+ if (app_state->activity_mode)
+ {
+ gtk_progress_bar_pulse
+ (GTK_PROGRESS_BAR(app_state->progress_bar));
+ }
+ else
+ {
+ gtk_progress_set_value(GTK_PROGRESS(app_state->progress_bar),
+ app_state->progress_value);
+ }
+ gdk_threads_leave();
+
+ return TRUE;
+}
+
+gboolean update_progress_text_timeout(gpointer data)
+{
+ UpdaterAppState *app_state;
+
+ llassert(data != NULL);
+ app_state = (UpdaterAppState *) data;
+
+ if (app_state->activity_mode == TRUE)
+ {
+ // We no longer need this timeout, it will be removed.
+ return FALSE;
+ }
+
+ if (!app_state->progress_value)
+ {
+ return TRUE;
+ }
+
+ std::string progress_text = llformat((LLTrans::getString("UpdaterProgressBarText")+" (%.0f%%)").c_str(), app_state->progress_value);
+
+ gdk_threads_enter();
+ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(app_state->progress_bar),
+ progress_text.c_str());
+ gdk_threads_leave();
+
+ return TRUE;
+}
+
+int download_progress_cb(gpointer data,
+ double t,
+ double d,
+ double utotal,
+ double ulnow)
+{
+ UpdaterAppState *app_state;
+
+ llassert(data != NULL);
+ app_state = (UpdaterAppState *) data;
+
+ if (t <= 0.0)
+ {
+ app_state->progress_value = 0;
+ }
+ else
+ {
+ app_state->progress_value = d * 100.0 / t;
+ }
+ return 0;
+}
+
+BOOL spawn_viewer(UpdaterAppState *app_state)
+{
+ llassert(app_state != NULL);
+
+ std::string cmd = app_state->dest_dir + "/secondlife";
+ GError *error = NULL;
+
+ // We want to spawn the Viewer on the same display as the updater app
+ gboolean success = gdk_spawn_command_line_on_screen
+ (gtk_widget_get_screen(app_state->window), cmd.c_str(), &error);
+
+ if (!success)
+ {
+ llwarns << "Failed to launch viewer: " << error->message
+ << llendl;
+ }
+
+ if (error) g_error_free(error);
+
+ return success;
+}
+
+void show_usage_and_exit()
+{
+ std::cout << "Usage: linux-updater --url URL --name NAME --dest PATH --stringsdir PATH1,PATH2 --stringsfile FILE"
+ << "[--image-dir PATH]"
+ << std::endl;
+ exit(1);
+}
+
+void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state)
+{
+ int i;
+
+ for (i = 1; i < argc; i++)
+ {
+ if ((!strcmp(argv[i], "--url")) && (++i < argc))
+ {
+ app_state->url = argv[i];
+ }
+ else if ((!strcmp(argv[i], "--name")) && (++i < argc))
+ {
+ app_state->app_name = argv[i];
+ }
+ else if ((!strcmp(argv[i], "--image-dir")) && (++i < argc))
+ {
+ app_state->image_dir = argv[i];
+ }
+ else if ((!strcmp(argv[i], "--dest")) && (++i < argc))
+ {
+ app_state->dest_dir = argv[i];
+ }
+ else if ((!strcmp(argv[i], "--stringsdir")) && (++i < argc))
+ {
+ app_state->strings_dirs = argv[i];
+ }
+ else if ((!strcmp(argv[i], "--stringsfile")) && (++i < argc))
+ {
+ app_state->strings_file = argv[i];
+ }
+ else
+ {
+ // show usage, an invalid option was given.
+ show_usage_and_exit();
+ }
+ }
+
+ if (app_state->app_name.empty()
+ || app_state->url.empty()
+ || app_state->dest_dir.empty())
+ {
+ show_usage_and_exit();
+ }
+
+ app_state->progress_value = 0.0;
+ app_state->activity_mode = FALSE;
+ app_state->failure = FALSE;
+
+ translate_init(app_state->strings_dirs, app_state->strings_file);
+}
+
+int main(int argc, char **argv)
+{
+ UpdaterAppState app_state;
+ GThread *worker_thread;
+
+ parse_args_and_init(argc, argv, &app_state);
+
+ // Initialize logger, and rename old log file
+ gDirUtilp->initAppDirs("SecondLife");
+ LLError::initForApplication
+ (gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
+ std::string old_log_file = gDirUtilp->getExpandedFilename
+ (LL_PATH_LOGS, "updater.log.old");
+ std::string log_file =
+ gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log");
+ LLFile::rename(log_file, old_log_file);
+ LLError::logToFile(log_file);
+
+ // initialize gthreads and gtk+
+ if (!g_thread_supported())
+ {
+ g_thread_init(NULL);
+ gdk_threads_init();
+ }
+
+ gtk_init(&argc, &argv);
+
+ // create UI
+ updater_app_ui_init(&app_state);
+
+ //llinfos << "SAMPLE TRANSLATION IS: " << LLTrans::getString("LoginInProgress") << llendl;
+
+ // create download thread
+ worker_thread = g_thread_create
+ (GThreadFunc(worker_thread_cb), &app_state, FALSE, NULL);
+
+ gdk_threads_enter();
+ gtk_main();
+ gdk_threads_leave();
+
+ return (app_state.failure == FALSE) ? 0 : 1;
+}
diff --git a/indra/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt
index 235248ee73..bfa2c34c12 100644
--- a/indra/llaudio/CMakeLists.txt
+++ b/indra/llaudio/CMakeLists.txt
@@ -4,15 +4,16 @@ project(llaudio)
include(00-Common)
include(Audio)
+include(LLAudio)
include(FMOD)
include(OPENAL)
include(LLCommon)
include(LLMath)
include(LLMessage)
include(LLVFS)
-include(LLMedia)
include_directories(
+ ${LLAUDIO_INCLUDE_DIRS}
${FMOD_INCLUDE_DIR}
${LLCOMMON_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS}
@@ -24,56 +25,56 @@ include_directories(
${VORBIS_INCLUDE_DIRS}
${OPENAL_LIB_INCLUDE_DIRS}
${FREEAULT_LIB_INCLUDE_DIRS}
- ${LLMEDIA_INCLUDE_DIRS}
)
set(llaudio_SOURCE_FILES
- audioengine.cpp
- listener.cpp
+ llaudioengine.cpp
+ lllistener.cpp
llaudiodecodemgr.cpp
- vorbisdecode.cpp
- vorbisencode.cpp
+ llvorbisencode.cpp
)
set(llaudio_HEADER_FILES
CMakeLists.txt
- audioengine.h
- listener.h
+ llaudioengine.h
+ lllistener.h
llaudiodecodemgr.h
- vorbisdecode.h
- vorbisencode.h
- windgen.h
+ llvorbisencode.h
+ llwindgen.h
)
if (FMOD)
list(APPEND llaudio_SOURCE_FILES
- audioengine_fmod.cpp
- listener_fmod.cpp
+ llaudioengine_fmod.cpp
+ lllistener_fmod.cpp
+ llstreamingaudio_fmod.cpp
)
list(APPEND llaudio_HEADER_FILES
- audioengine_fmod.h
- listener_fmod.h
+ llaudioengine_fmod.h
+ lllistener_fmod.h
+ llstreamingaudio_fmod.h
)
if (LINUX)
- if (${CXX_VERSION} MATCHES "4.[23]")
- set_source_files_properties(audioengine_fmod.cpp
- COMPILE_FLAGS -Wno-error=write-strings)
- endif (${CXX_VERSION} MATCHES "4.[23]")
+ if (${CXX_VERSION_NUMBER} GREATER 419)
+ set_source_files_properties(llaudioengine_fmod.cpp
+ llstreamingaudio_fmod.cpp
+ COMPILE_FLAGS -Wno-write-strings)
+ endif (${CXX_VERSION_NUMBER} GREATER 419)
endif (LINUX)
endif (FMOD)
if (OPENAL)
list(APPEND llaudio_SOURCE_FILES
- audioengine_openal.cpp
- listener_openal.cpp
+ llaudioengine_openal.cpp
+ lllistener_openal.cpp
)
list(APPEND llaudio_HEADER_FILES
- audioengine_openal.h
- listener_openal.h
+ llaudioengine_openal.h
+ lllistener_openal.h
)
endif (OPENAL)
diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp
index 5b6db3bd87..6bbaad9cef 100644
--- a/indra/llaudio/llaudiodecodemgr.cpp
+++ b/indra/llaudio/llaudiodecodemgr.cpp
@@ -33,15 +33,16 @@
#include "llaudiodecodemgr.h"
-#include "vorbisdecode.h"
-#include "audioengine.h"
+#include "llaudioengine.h"
#include "lllfsthread.h"
#include "llvfile.h"
#include "llstring.h"
#include "lldir.h"
#include "llendianswizzle.h"
-#include "audioengine.h"
#include "llassetstorage.h"
+#include "llrefcount.h"
+
+#include "llvorbisencode.h"
#include "vorbis/codec.h"
#include "vorbis/vorbisfile.h"
@@ -218,11 +219,42 @@ BOOL LLVorbisDecodeState::initDecode()
return(FALSE);
}
- size_t size_guess = (size_t)ov_pcm_total(&mVF, -1);
+ S32 sample_count = ov_pcm_total(&mVF, -1);
+ size_t size_guess = (size_t)sample_count;
vorbis_info* vi = ov_info(&mVF, -1);
size_guess *= vi->channels;
size_guess *= 2;
size_guess += 2048;
+
+ bool abort_decode = false;
+
+ if( vi->channels < 1 || vi->channels > LLVORBIS_CLIP_MAX_CHANNELS )
+ {
+ abort_decode = true;
+ llwarns << "Bad channel count: " << vi->channels << llendl;
+ }
+
+ if( (size_t)sample_count > LLVORBIS_CLIP_REJECT_SAMPLES )
+ {
+ abort_decode = true;
+ llwarns << "Illegal sample count: " << sample_count << llendl;
+ }
+
+ if( size_guess > LLVORBIS_CLIP_REJECT_SIZE )
+ {
+ abort_decode = true;
+ llwarns << "Illegal sample size: " << size_guess << llendl;
+ }
+
+ if( abort_decode )
+ {
+ llwarns << "Canceling initDecode. Bad asset: " << mUUID << llendl;
+ llwarns << "Bad asset encoded by: " << ov_comment(&mVF,-1)->vendor << llendl;
+ delete mInFilep;
+ mInFilep = NULL;
+ return FALSE;
+ }
+
mWAVBuffer.reserve(size_guess);
mWAVBuffer.resize(WAV_HEADER_SIZE);
diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp
new file mode 100644
index 0000000000..a28c94d00d
--- /dev/null
+++ b/indra/llaudio/llaudioengine.cpp
@@ -0,0 +1,1751 @@
+ /**
+ * @file audioengine.cpp
+ * @brief implementation of LLAudioEngine class abstracting the Open
+ * AL audio support
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llaudioengine.h"
+#include "llstreamingaudio.h"
+
+#include "llerror.h"
+#include "llmath.h"
+
+#include "sound_ids.h" // temporary hack for min/max distances
+
+#include "llvfs.h"
+#include "lldir.h"
+#include "llaudiodecodemgr.h"
+#include "llassetstorage.h"
+
+
+// necessary for grabbing sounds from sim (implemented in viewer)
+extern void request_sound(const LLUUID &sound_guid);
+
+LLAudioEngine* gAudiop = NULL;
+
+
+//
+// LLAudioEngine implementation
+//
+
+
+LLAudioEngine::LLAudioEngine()
+{
+ setDefaults();
+}
+
+
+LLAudioEngine::~LLAudioEngine()
+{
+}
+
+LLStreamingAudioInterface* LLAudioEngine::getStreamingAudioImpl()
+{
+ return mStreamingAudioImpl;
+}
+
+void LLAudioEngine::setStreamingAudioImpl(LLStreamingAudioInterface *impl)
+{
+ mStreamingAudioImpl = impl;
+}
+
+void LLAudioEngine::setDefaults()
+{
+ mMaxWindGain = 1.f;
+
+ mListenerp = NULL;
+
+ mMuted = false;
+ mUserData = NULL;
+
+ mLastStatus = 0;
+
+ mNumChannels = 0;
+ mEnableWind = false;
+
+ S32 i;
+ for (i = 0; i < MAX_CHANNELS; i++)
+ {
+ mChannels[i] = NULL;
+ }
+ for (i = 0; i < MAX_BUFFERS; i++)
+ {
+ mBuffers[i] = NULL;
+ }
+
+ mMasterGain = 1.f;
+ mNextWindUpdate = 0.f;
+
+ mStreamingAudioImpl = NULL;
+
+ for (U32 i = 0; i < LLAudioEngine::AUDIO_TYPE_COUNT; i++)
+ mSecondaryGain[i] = 1.0f;
+}
+
+
+bool LLAudioEngine::init(const S32 num_channels, void* userdata)
+{
+ setDefaults();
+
+ mNumChannels = num_channels;
+ mUserData = userdata;
+
+ allocateListener();
+
+ // Initialize the decode manager
+ gAudioDecodeMgrp = new LLAudioDecodeMgr;
+
+ llinfos << "LLAudioEngine::init() AudioEngine successfully initialized" << llendl;
+
+ return true;
+}
+
+
+void LLAudioEngine::shutdown()
+{
+ // Clean up decode manager
+ delete gAudioDecodeMgrp;
+ gAudioDecodeMgrp = NULL;
+
+ // Clean up wind source
+ cleanupWind();
+
+ // Clean up audio sources
+ source_map::iterator iter_src;
+ for (iter_src = mAllSources.begin(); iter_src != mAllSources.end(); iter_src++)
+ {
+ delete iter_src->second;
+ }
+
+
+ // Clean up audio data
+ data_map::iterator iter_data;
+ for (iter_data = mAllData.begin(); iter_data != mAllData.end(); iter_data++)
+ {
+ delete iter_data->second;
+ }
+
+
+ // Clean up channels
+ S32 i;
+ for (i = 0; i < MAX_CHANNELS; i++)
+ {
+ delete mChannels[i];
+ mChannels[i] = NULL;
+ }
+
+ // Clean up buffers
+ for (i = 0; i < MAX_BUFFERS; i++)
+ {
+ delete mBuffers[i];
+ mBuffers[i] = NULL;
+ }
+}
+
+
+// virtual
+void LLAudioEngine::startInternetStream(const std::string& url)
+{
+ if (mStreamingAudioImpl)
+ mStreamingAudioImpl->start(url);
+}
+
+
+// virtual
+void LLAudioEngine::stopInternetStream()
+{
+ if (mStreamingAudioImpl)
+ mStreamingAudioImpl->stop();
+}
+
+// virtual
+void LLAudioEngine::pauseInternetStream(int pause)
+{
+ if (mStreamingAudioImpl)
+ mStreamingAudioImpl->pause(pause);
+}
+
+// virtual
+void LLAudioEngine::updateInternetStream()
+{
+ if (mStreamingAudioImpl)
+ mStreamingAudioImpl->update();
+}
+
+// virtual
+int LLAudioEngine::isInternetStreamPlaying()
+{
+ if (mStreamingAudioImpl)
+ return mStreamingAudioImpl->isPlaying();
+
+ return 0; // Stopped
+}
+
+
+// virtual
+void LLAudioEngine::setInternetStreamGain(F32 vol)
+{
+ if (mStreamingAudioImpl)
+ mStreamingAudioImpl->setGain(vol);
+}
+
+// virtual
+std::string LLAudioEngine::getInternetStreamURL()
+{
+ if (mStreamingAudioImpl)
+ return mStreamingAudioImpl->getURL();
+ else return std::string();
+}
+
+
+void LLAudioEngine::updateChannels()
+{
+ S32 i;
+ for (i = 0; i < MAX_CHANNELS; i++)
+ {
+ if (mChannels[i])
+ {
+ mChannels[i]->updateBuffer();
+ mChannels[i]->update3DPosition();
+ mChannels[i]->updateLoop();
+ }
+ }
+}
+
+static const F32 default_max_decode_time = .002f; // 2 ms
+void LLAudioEngine::idle(F32 max_decode_time)
+{
+ if (max_decode_time <= 0.f)
+ {
+ max_decode_time = default_max_decode_time;
+ }
+
+ // "Update" all of our audio sources, clean up dead ones.
+ // Primarily does position updating, cleanup of unused audio sources.
+ // Also does regeneration of the current priority of each audio source.
+
+ if (getMuted())
+ {
+ setInternalGain(0.f);
+ }
+ else
+ {
+ setInternalGain(getMasterGain());
+ }
+
+ S32 i;
+ for (i = 0; i < MAX_BUFFERS; i++)
+ {
+ if (mBuffers[i])
+ {
+ mBuffers[i]->mInUse = false;
+ }
+ }
+
+ F32 max_priority = -1.f;
+ LLAudioSource *max_sourcep = NULL; // Maximum priority source without a channel
+ source_map::iterator iter;
+ for (iter = mAllSources.begin(); iter != mAllSources.end();)
+ {
+ LLAudioSource *sourcep = iter->second;
+
+ // Update this source
+ sourcep->update();
+ sourcep->updatePriority();
+
+ if (sourcep->isDone())
+ {
+ // The source is done playing, clean it up.
+ delete sourcep;
+ mAllSources.erase(iter++);
+ continue;
+ }
+
+ if (!sourcep->getChannel() && sourcep->getCurrentBuffer())
+ {
+ // We could potentially play this sound if its priority is high enough.
+ if (sourcep->getPriority() > max_priority)
+ {
+ max_priority = sourcep->getPriority();
+ max_sourcep = sourcep;
+ }
+ }
+
+ // Move on to the next source
+ iter++;
+ }
+
+ // Now, do priority-based organization of audio sources.
+ // All channels used, check priorities.
+ // Find channel with lowest priority
+ if (max_sourcep)
+ {
+ LLAudioChannel *channelp = getFreeChannel(max_priority);
+ if (channelp)
+ {
+ //llinfos << "Replacing source in channel due to priority!" << llendl;
+ max_sourcep->setChannel(channelp);
+ channelp->setSource(max_sourcep);
+ if (max_sourcep->isSyncSlave())
+ {
+ // A sync slave, it doesn't start playing until it's synced up with the master.
+ // Flag this channel as waiting for sync, and return true.
+ channelp->setWaiting(true);
+ }
+ else
+ {
+ channelp->setWaiting(false);
+ channelp->play();
+ }
+ }
+ }
+
+
+ // Do this BEFORE we update the channels
+ // Update the channels to sync up with any changes that the source made,
+ // such as changing what sound was playing.
+ updateChannels();
+
+ // Update queued sounds (switch to next queued data if the current has finished playing)
+ for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter)
+ {
+ // This is lame, instead of this I could actually iterate through all the sources
+ // attached to each channel, since only those with active channels
+ // can have anything interesting happen with their queue? (Maybe not true)
+ LLAudioSource *sourcep = iter->second;
+ if (!sourcep->mQueuedDatap)
+ {
+ // Nothing queued, so we don't care.
+ continue;
+ }
+
+ LLAudioChannel *channelp = sourcep->getChannel();
+ if (!channelp)
+ {
+ // This sound isn't playing, so we just process move the queue
+ sourcep->mCurrentDatap = sourcep->mQueuedDatap;
+ sourcep->mQueuedDatap = NULL;
+
+ // Reset the timer so the source doesn't die.
+ sourcep->mAgeTimer.reset();
+ // Make sure we have the buffer set up if we just decoded the data
+ if (sourcep->mCurrentDatap)
+ {
+ updateBufferForData(sourcep->mCurrentDatap);
+ }
+
+ // Actually play the associated data.
+ sourcep->setupChannel();
+ channelp = sourcep->getChannel();
+ if (channelp)
+ {
+ channelp->updateBuffer();
+ sourcep->getChannel()->play();
+ }
+ continue;
+ }
+ else
+ {
+ // Check to see if the current sound is done playing, or looped.
+ if (!channelp->isPlaying())
+ {
+ sourcep->mCurrentDatap = sourcep->mQueuedDatap;
+ sourcep->mQueuedDatap = NULL;
+
+ // Reset the timer so the source doesn't die.
+ sourcep->mAgeTimer.reset();
+
+ // Make sure we have the buffer set up if we just decoded the data
+ if (sourcep->mCurrentDatap)
+ {
+ updateBufferForData(sourcep->mCurrentDatap);
+ }
+
+ // Actually play the associated data.
+ sourcep->setupChannel();
+ channelp->updateBuffer();
+ sourcep->getChannel()->play();
+ }
+ else if (sourcep->isLoop())
+ {
+ // It's a loop, we need to check and see if we're done with it.
+ if (channelp->mLoopedThisFrame)
+ {
+ sourcep->mCurrentDatap = sourcep->mQueuedDatap;
+ sourcep->mQueuedDatap = NULL;
+
+ // Actually, should do a time sync so if we're a loop master/slave
+ // we don't drift away.
+ sourcep->setupChannel();
+ sourcep->getChannel()->play();
+ }
+ }
+ }
+ }
+
+ // Lame, update the channels AGAIN.
+ // Update the channels to sync up with any changes that the source made,
+ // such as changing what sound was playing.
+ updateChannels();
+
+ // Hack! For now, just use a global sync master;
+ LLAudioSource *sync_masterp = NULL;
+ LLAudioChannel *master_channelp = NULL;
+ F32 max_sm_priority = -1.f;
+ for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter)
+ {
+ LLAudioSource *sourcep = iter->second;
+ if (sourcep->isSyncMaster())
+ {
+ if (sourcep->getPriority() > max_sm_priority)
+ {
+ sync_masterp = sourcep;
+ master_channelp = sync_masterp->getChannel();
+ max_sm_priority = sourcep->getPriority();
+ }
+ }
+ }
+
+ if (master_channelp && master_channelp->mLoopedThisFrame)
+ {
+ // Synchronize loop slaves with their masters
+ // Update queued sounds (switch to next queued data if the current has finished playing)
+ for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter)
+ {
+ LLAudioSource *sourcep = iter->second;
+
+ if (!sourcep->isSyncSlave())
+ {
+ // Not a loop slave, we don't need to do anything
+ continue;
+ }
+
+ LLAudioChannel *channelp = sourcep->getChannel();
+ if (!channelp)
+ {
+ // Not playing, don't need to bother.
+ continue;
+ }
+
+ if (!channelp->isPlaying())
+ {
+ // Now we need to check if our loop master has just looped, and
+ // start playback if that's the case.
+ if (sync_masterp->getChannel())
+ {
+ channelp->playSynced(master_channelp);
+ channelp->setWaiting(false);
+ }
+ }
+ }
+ }
+
+ // Sync up everything that the audio engine needs done.
+ commitDeferredChanges();
+
+ // Flush unused buffers that are stale enough
+ for (i = 0; i < MAX_BUFFERS; i++)
+ {
+ if (mBuffers[i])
+ {
+ if (!mBuffers[i]->mInUse && mBuffers[i]->mLastUseTimer.getElapsedTimeF32() > 30.f)
+ {
+ //llinfos << "Flushing unused buffer!" << llendl;
+ mBuffers[i]->mAudioDatap->mBufferp = NULL;
+ delete mBuffers[i];
+ mBuffers[i] = NULL;
+ }
+ }
+ }
+
+
+ // Clear all of the looped flags for the channels
+ for (i = 0; i < MAX_CHANNELS; i++)
+ {
+ if (mChannels[i])
+ {
+ mChannels[i]->mLoopedThisFrame = false;
+ }
+ }
+
+ // Decode audio files
+ gAudioDecodeMgrp->processQueue(max_decode_time);
+
+ // Call this every frame, just in case we somehow
+ // missed picking it up in all the places that can add
+ // or request new data.
+ startNextTransfer();
+
+ updateInternetStream();
+}
+
+
+
+bool LLAudioEngine::updateBufferForData(LLAudioData *adp, const LLUUID &audio_uuid)
+{
+ if (!adp)
+ {
+ return false;
+ }
+
+ // Update the audio buffer first - load a sound if we have it.
+ // Note that this could potentially cause us to waste time updating buffers
+ // for sounds that actually aren't playing, although this should be mitigated
+ // by the fact that we limit the number of buffers, and we flush buffers based
+ // on priority.
+ if (!adp->getBuffer())
+ {
+ if (adp->hasDecodedData())
+ {
+ adp->load();
+ }
+ else if (adp->hasLocalData())
+ {
+ if (audio_uuid.notNull())
+ {
+ gAudioDecodeMgrp->addDecodeRequest(audio_uuid);
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+void LLAudioEngine::enableWind(bool enable)
+{
+ if (enable && (!mEnableWind))
+ {
+ initWind();
+ mEnableWind = enable;
+ }
+ else if (mEnableWind && (!enable))
+ {
+ mEnableWind = enable;
+ cleanupWind();
+ }
+}
+
+
+LLAudioBuffer * LLAudioEngine::getFreeBuffer()
+{
+ S32 i;
+ for (i = 0; i < MAX_BUFFERS; i++)
+ {
+ if (!mBuffers[i])
+ {
+ mBuffers[i] = createBuffer();
+ return mBuffers[i];
+ }
+ }
+
+
+ // Grab the oldest unused buffer
+ F32 max_age = -1.f;
+ S32 buffer_id = -1;
+ for (i = 0; i < MAX_BUFFERS; i++)
+ {
+ if (mBuffers[i])
+ {
+ if (!mBuffers[i]->mInUse)
+ {
+ if (mBuffers[i]->mLastUseTimer.getElapsedTimeF32() > max_age)
+ {
+ max_age = mBuffers[i]->mLastUseTimer.getElapsedTimeF32();
+ buffer_id = i;
+ }
+ }
+ }
+ }
+
+ if (buffer_id >= 0)
+ {
+ llinfos << "Taking over unused buffer " << buffer_id << llendl;
+ //llinfos << "Flushing unused buffer!" << llendl;
+ mBuffers[buffer_id]->mAudioDatap->mBufferp = NULL;
+ delete mBuffers[buffer_id];
+ mBuffers[buffer_id] = createBuffer();
+ return mBuffers[buffer_id];
+ }
+ return NULL;
+}
+
+
+LLAudioChannel * LLAudioEngine::getFreeChannel(const F32 priority)
+{
+ S32 i;
+ for (i = 0; i < mNumChannels; i++)
+ {
+ if (!mChannels[i])
+ {
+ // No channel allocated here, use it.
+ mChannels[i] = createChannel();
+ return mChannels[i];
+ }
+ else
+ {
+ // Channel is allocated but not playing right now, use it.
+ if (!mChannels[i]->isPlaying() && !mChannels[i]->isWaiting())
+ {
+ mChannels[i]->cleanup();
+ if (mChannels[i]->getSource())
+ {
+ mChannels[i]->getSource()->setChannel(NULL);
+ }
+ return mChannels[i];
+ }
+ }
+ }
+
+ // All channels used, check priorities.
+ // Find channel with lowest priority and see if we want to replace it.
+ F32 min_priority = 10000.f;
+ LLAudioChannel *min_channelp = NULL;
+
+ for (i = 0; i < mNumChannels; i++)
+ {
+ LLAudioChannel *channelp = mChannels[i];
+ LLAudioSource *sourcep = channelp->getSource();
+ if (sourcep->getPriority() < min_priority)
+ {
+ min_channelp = channelp;
+ min_priority = sourcep->getPriority();
+ }
+ }
+
+ if (min_priority > priority || !min_channelp)
+ {
+ // All playing channels have higher priority, return.
+ return NULL;
+ }
+
+ // Flush the minimum priority channel, and return it.
+ min_channelp->cleanup();
+ min_channelp->getSource()->setChannel(NULL);
+ return min_channelp;
+}
+
+
+void LLAudioEngine::cleanupBuffer(LLAudioBuffer *bufferp)
+{
+ S32 i;
+ for (i = 0; i < MAX_BUFFERS; i++)
+ {
+ if (mBuffers[i] == bufferp)
+ {
+ delete mBuffers[i];
+ mBuffers[i] = NULL;
+ }
+ }
+}
+
+
+bool LLAudioEngine::preloadSound(const LLUUID &uuid)
+{
+ gAudiop->getAudioData(uuid); // We don't care about the return value, this is just to make sure
+ // that we have an entry, which will mean that the audio engine knows about this
+
+ if (gAudioDecodeMgrp->addDecodeRequest(uuid))
+ {
+ // This means that we do have a local copy, and we're working on decoding it.
+ return true;
+ }
+
+ // At some point we need to have the audio/asset system check the static VFS
+ // before it goes off and fetches stuff from the server.
+ //llwarns << "Used internal preload for non-local sound" << llendl;
+ return false;
+}
+
+
+bool LLAudioEngine::isWindEnabled()
+{
+ return mEnableWind;
+}
+
+
+void LLAudioEngine::setMuted(bool muted)
+{
+ mMuted = muted;
+ enableWind(!mMuted);
+}
+
+
+void LLAudioEngine::setMasterGain(const F32 gain)
+{
+ mMasterGain = gain;
+ setInternalGain(gain);
+}
+
+F32 LLAudioEngine::getMasterGain()
+{
+ return mMasterGain;
+}
+
+void LLAudioEngine::setSecondaryGain(S32 type, F32 gain)
+{
+ llassert(type < LLAudioEngine::AUDIO_TYPE_COUNT);
+
+ mSecondaryGain[type] = gain;
+}
+
+F32 LLAudioEngine::getSecondaryGain(S32 type)
+{
+ return mSecondaryGain[type];
+}
+
+F32 LLAudioEngine::getInternetStreamGain()
+{
+ if (mStreamingAudioImpl)
+ return mStreamingAudioImpl->getGain();
+ else
+ return 1.0f;
+}
+
+void LLAudioEngine::setMaxWindGain(F32 gain)
+{
+ mMaxWindGain = gain;
+}
+
+
+F64 LLAudioEngine::mapWindVecToGain(LLVector3 wind_vec)
+{
+ F64 gain = 0.0;
+
+ gain = wind_vec.magVec();
+
+ if (gain)
+ {
+ if (gain > 20)
+ {
+ gain = 20;
+ }
+ gain = gain/20.0;
+ }
+
+ return (gain);
+}
+
+
+F64 LLAudioEngine::mapWindVecToPitch(LLVector3 wind_vec)
+{
+ LLVector3 listen_right;
+ F64 theta;
+
+ // Wind frame is in listener-relative coordinates
+ LLVector3 norm_wind = wind_vec;
+ norm_wind.normVec();
+ listen_right.setVec(1.0,0.0,0.0);
+
+ // measure angle between wind vec and listener right axis (on 0,PI)
+ theta = acos(norm_wind * listen_right);
+
+ // put it on 0, 1
+ theta /= F_PI;
+
+ // put it on [0, 0.5, 0]
+ if (theta > 0.5) theta = 1.0-theta;
+ if (theta < 0) theta = 0;
+
+ return (theta);
+}
+
+
+F64 LLAudioEngine::mapWindVecToPan(LLVector3 wind_vec)
+{
+ LLVector3 listen_right;
+ F64 theta;
+
+ // Wind frame is in listener-relative coordinates
+ listen_right.setVec(1.0,0.0,0.0);
+
+ LLVector3 norm_wind = wind_vec;
+ norm_wind.normVec();
+
+ // measure angle between wind vec and listener right axis (on 0,PI)
+ theta = acos(norm_wind * listen_right);
+
+ // put it on 0, 1
+ theta /= F_PI;
+
+ return (theta);
+}
+
+
+void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain,
+ const S32 type, const LLVector3d &pos_global)
+{
+ // Create a new source (since this can't be associated with an existing source.
+ //llinfos << "Localized: " << audio_uuid << llendl;
+
+ if (mMuted)
+ {
+ return;
+ }
+
+ LLUUID source_id;
+ source_id.generate();
+
+ LLAudioSource *asp = new LLAudioSource(source_id, owner_id, gain, type);
+ gAudiop->addAudioSource(asp);
+ if (pos_global.isExactlyZero())
+ {
+ asp->setAmbient(true);
+ }
+ else
+ {
+ asp->setPositionGlobal(pos_global);
+ }
+ asp->updatePriority();
+ asp->play(audio_uuid);
+}
+
+
+void LLAudioEngine::setListenerPos(LLVector3 aVec)
+{
+ mListenerp->setPosition(aVec);
+}
+
+
+LLVector3 LLAudioEngine::getListenerPos()
+{
+ if (mListenerp)
+ {
+ return(mListenerp->getPosition());
+ }
+ else
+ {
+ return(LLVector3::zero);
+ }
+}
+
+
+void LLAudioEngine::setListenerVelocity(LLVector3 aVec)
+{
+ mListenerp->setVelocity(aVec);
+}
+
+
+void LLAudioEngine::translateListener(LLVector3 aVec)
+{
+ mListenerp->translate(aVec);
+}
+
+
+void LLAudioEngine::orientListener(LLVector3 up, LLVector3 at)
+{
+ mListenerp->orient(up, at);
+}
+
+
+void LLAudioEngine::setListener(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at)
+{
+ mListenerp->set(pos,vel,up,at);
+}
+
+
+void LLAudioEngine::setDopplerFactor(F32 factor)
+{
+ if (mListenerp)
+ {
+ mListenerp->setDopplerFactor(factor);
+ }
+}
+
+
+F32 LLAudioEngine::getDopplerFactor()
+{
+ if (mListenerp)
+ {
+ return mListenerp->getDopplerFactor();
+ }
+ else
+ {
+ return 0.f;
+ }
+}
+
+
+void LLAudioEngine::setRolloffFactor(F32 factor)
+{
+ if (mListenerp)
+ {
+ mListenerp->setRolloffFactor(factor);
+ }
+}
+
+
+F32 LLAudioEngine::getRolloffFactor()
+{
+ if (mListenerp)
+ {
+ return mListenerp->getRolloffFactor();
+ }
+ else
+ {
+ return 0.f;
+ }
+}
+
+
+void LLAudioEngine::commitDeferredChanges()
+{
+ mListenerp->commitDeferredChanges();
+}
+
+
+LLAudioSource * LLAudioEngine::findAudioSource(const LLUUID &source_id)
+{
+ source_map::iterator iter;
+ iter = mAllSources.find(source_id);
+
+ if (iter == mAllSources.end())
+ {
+ return NULL;
+ }
+ else
+ {
+ return iter->second;
+ }
+}
+
+
+LLAudioData * LLAudioEngine::getAudioData(const LLUUID &audio_uuid)
+{
+ data_map::iterator iter;
+ iter = mAllData.find(audio_uuid);
+ if (iter == mAllData.end())
+ {
+ // Create the new audio data
+ LLAudioData *adp = new LLAudioData(audio_uuid);
+ mAllData[audio_uuid] = adp;
+ return adp;
+ }
+ else
+ {
+ return iter->second;
+ }
+}
+
+void LLAudioEngine::addAudioSource(LLAudioSource *asp)
+{
+ mAllSources[asp->getID()] = asp;
+}
+
+
+void LLAudioEngine::cleanupAudioSource(LLAudioSource *asp)
+{
+ source_map::iterator iter;
+ iter = mAllSources.find(asp->getID());
+ if (iter == mAllSources.end())
+ {
+ llwarns << "Cleaning up unknown audio source!" << llendl;
+ return;
+ }
+ delete asp;
+ mAllSources.erase(iter);
+}
+
+
+bool LLAudioEngine::hasDecodedFile(const LLUUID &uuid)
+{
+ std::string uuid_str;
+ uuid.toString(uuid_str);
+
+ std::string wav_path;
+ wav_path = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str);
+ wav_path += ".dsf";
+
+ if (gDirUtilp->fileExists(wav_path))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+bool LLAudioEngine::hasLocalFile(const LLUUID &uuid)
+{
+ // See if it's in the VFS.
+ return gVFS->getExists(uuid, LLAssetType::AT_SOUND);
+}
+
+
+void LLAudioEngine::startNextTransfer()
+{
+ //llinfos << "LLAudioEngine::startNextTransfer()" << llendl;
+ if (mCurrentTransfer.notNull() || getMuted())
+ {
+ //llinfos << "Transfer in progress, aborting" << llendl;
+ return;
+ }
+
+ // Get the ID for the next asset that we want to transfer.
+ // Pick one in the following order:
+ LLUUID asset_id;
+ S32 i;
+ LLAudioSource *asp = NULL;
+ LLAudioData *adp = NULL;
+ data_map::iterator data_iter;
+
+ // Check all channels for currently playing sounds.
+ F32 max_pri = -1.f;
+ for (i = 0; i < MAX_CHANNELS; i++)
+ {
+ if (!mChannels[i])
+ {
+ continue;
+ }
+
+ asp = mChannels[i]->getSource();
+ if (!asp)
+ {
+ continue;
+ }
+ if (asp->getPriority() <= max_pri)
+ {
+ continue;
+ }
+
+ if (asp->getPriority() <= max_pri)
+ {
+ continue;
+ }
+
+ adp = asp->getCurrentData();
+ if (!adp)
+ {
+ continue;
+ }
+
+ if (!adp->hasLocalData() && adp->hasValidData())
+ {
+ asset_id = adp->getID();
+ max_pri = asp->getPriority();
+ }
+ }
+
+ // Check all channels for currently queued sounds.
+ if (asset_id.isNull())
+ {
+ max_pri = -1.f;
+ for (i = 0; i < MAX_CHANNELS; i++)
+ {
+ if (!mChannels[i])
+ {
+ continue;
+ }
+
+ LLAudioSource *asp;
+ asp = mChannels[i]->getSource();
+ if (!asp)
+ {
+ continue;
+ }
+
+ if (asp->getPriority() <= max_pri)
+ {
+ continue;
+ }
+
+ adp = asp->getQueuedData();
+ if (!adp)
+ {
+ continue;
+ }
+
+ if (!adp->hasLocalData() && adp->hasValidData())
+ {
+ asset_id = adp->getID();
+ max_pri = asp->getPriority();
+ }
+ }
+ }
+
+ // Check all live channels for other sounds (preloads).
+ if (asset_id.isNull())
+ {
+ max_pri = -1.f;
+ for (i = 0; i < MAX_CHANNELS; i++)
+ {
+ if (!mChannels[i])
+ {
+ continue;
+ }
+
+ LLAudioSource *asp;
+ asp = mChannels[i]->getSource();
+ if (!asp)
+ {
+ continue;
+ }
+
+ if (asp->getPriority() <= max_pri)
+ {
+ continue;
+ }
+
+
+ for (data_iter = asp->mPreloadMap.begin(); data_iter != asp->mPreloadMap.end(); data_iter++)
+ {
+ LLAudioData *adp = data_iter->second;
+ if (!adp)
+ {
+ continue;
+ }
+
+ if (!adp->hasLocalData() && adp->hasValidData())
+ {
+ asset_id = adp->getID();
+ max_pri = asp->getPriority();
+ }
+ }
+ }
+ }
+
+ // Check all sources
+ if (asset_id.isNull())
+ {
+ max_pri = -1.f;
+ source_map::iterator source_iter;
+ for (source_iter = mAllSources.begin(); source_iter != mAllSources.end(); source_iter++)
+ {
+ asp = source_iter->second;
+ if (!asp)
+ {
+ continue;
+ }
+
+ if (asp->getPriority() <= max_pri)
+ {
+ continue;
+ }
+
+ adp = asp->getCurrentData();
+ if (adp && !adp->hasLocalData() && adp->hasValidData())
+ {
+ asset_id = adp->getID();
+ max_pri = asp->getPriority();
+ continue;
+ }
+
+ adp = asp->getQueuedData();
+ if (adp && !adp->hasLocalData() && adp->hasValidData())
+ {
+ asset_id = adp->getID();
+ max_pri = asp->getPriority();
+ continue;
+ }
+
+ for (data_iter = asp->mPreloadMap.begin(); data_iter != asp->mPreloadMap.end(); data_iter++)
+ {
+ LLAudioData *adp = data_iter->second;
+ if (!adp)
+ {
+ continue;
+ }
+
+ if (!adp->hasLocalData() && adp->hasValidData())
+ {
+ asset_id = adp->getID();
+ max_pri = asp->getPriority();
+ break;
+ }
+ }
+ }
+ }
+
+ if (asset_id.notNull())
+ {
+ llinfos << "Getting asset data for: " << asset_id << llendl;
+ gAudiop->mCurrentTransfer = asset_id;
+ gAudiop->mCurrentTransferTimer.reset();
+ gAssetStorage->getAssetData(asset_id, LLAssetType::AT_SOUND,
+ assetCallback, NULL);
+ }
+ else
+ {
+ //llinfos << "No pending transfers?" << llendl;
+ }
+}
+
+
+// static
+void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code, LLExtStat ext_status)
+{
+ if (result_code)
+ {
+ llinfos << "Boom, error in audio file transfer: " << LLAssetStorage::getErrorString( result_code ) << " (" << result_code << ")" << llendl;
+ // Need to mark data as bad to avoid constant rerequests.
+ LLAudioData *adp = gAudiop->getAudioData(uuid);
+ if (adp)
+ {
+ adp->setHasValidData(false);
+ adp->setHasLocalData(false);
+ adp->setHasDecodedData(false);
+ }
+ }
+ else
+ {
+ LLAudioData *adp = gAudiop->getAudioData(uuid);
+ if (!adp)
+ {
+ // Should never happen
+ llwarns << "Got asset callback without audio data for " << uuid << llendl;
+ }
+ else
+ {
+ adp->setHasValidData(true);
+ adp->setHasLocalData(true);
+ gAudioDecodeMgrp->addDecodeRequest(uuid);
+ }
+ }
+ gAudiop->mCurrentTransfer = LLUUID::null;
+ gAudiop->startNextTransfer();
+}
+
+
+//
+// LLAudioSource implementation
+//
+
+
+LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32 gain, const S32 type)
+: mID(id),
+ mOwnerID(owner_id),
+ mPriority(0.f),
+ mGain(gain),
+ mType(type),
+ mAmbient(false),
+ mLoop(false),
+ mSyncMaster(false),
+ mSyncSlave(false),
+ mQueueSounds(false),
+ mPlayedOnce(false),
+ mChannelp(NULL),
+ mCurrentDatap(NULL),
+ mQueuedDatap(NULL)
+{
+}
+
+
+LLAudioSource::~LLAudioSource()
+{
+ if (mChannelp)
+ {
+ // Stop playback of this sound
+ mChannelp->setSource(NULL);
+ mChannelp = NULL;
+ }
+}
+
+
+void LLAudioSource::setChannel(LLAudioChannel *channelp)
+{
+ if (channelp == mChannelp)
+ {
+ return;
+ }
+
+ mChannelp = channelp;
+}
+
+
+void LLAudioSource::update()
+{
+ if (!getCurrentBuffer())
+ {
+ if (getCurrentData())
+ {
+ // Hack - try and load the sound. Will do this as a callback
+ // on decode later.
+ if (getCurrentData()->load())
+ {
+ play(getCurrentData()->getID());
+ }
+ }
+ }
+}
+
+void LLAudioSource::updatePriority()
+{
+ if (isAmbient())
+ {
+ mPriority = 1.f;
+ }
+ else
+ {
+ // Priority is based on distance
+ LLVector3 dist_vec;
+ dist_vec.setVec(getPositionGlobal());
+ dist_vec -= gAudiop->getListenerPos();
+ F32 dist_squared = llmax(1.f, dist_vec.magVecSquared());
+
+ mPriority = mGain / dist_squared;
+ }
+}
+
+bool LLAudioSource::setupChannel()
+{
+ LLAudioData *adp = getCurrentData();
+
+ if (!adp->getBuffer())
+ {
+ // We're not ready to play back the sound yet, so don't try and allocate a channel for it.
+ //llwarns << "Aborting, no buffer" << llendl;
+ return false;
+ }
+
+
+ if (!mChannelp)
+ {
+ // Update the priority, in case we need to push out another channel.
+ updatePriority();
+
+ setChannel(gAudiop->getFreeChannel(getPriority()));
+ }
+
+ if (!mChannelp)
+ {
+ // Ugh, we don't have any free channels.
+ // Now we have to reprioritize.
+ // For now, just don't play the sound.
+ //llwarns << "Aborting, no free channels" << llendl;
+ return false;
+ }
+
+ mChannelp->setSource(this);
+ return true;
+}
+
+
+bool LLAudioSource::play(const LLUUID &audio_uuid)
+{
+ if (audio_uuid.isNull())
+ {
+ if (getChannel())
+ {
+ getChannel()->setSource(NULL);
+ setChannel(NULL);
+ addAudioData(NULL, true);
+ }
+ }
+ // Reset our age timeout if someone attempts to play the source.
+ mAgeTimer.reset();
+
+ LLAudioData *adp = gAudiop->getAudioData(audio_uuid);
+
+ bool has_buffer = gAudiop->updateBufferForData(adp, audio_uuid);
+
+
+ addAudioData(adp);
+
+ if (!has_buffer)
+ {
+ // Don't bother trying to set up a channel or anything, we don't have an audio buffer.
+ return false;
+ }
+
+ if (!setupChannel())
+ {
+ return false;
+ }
+
+ if (isSyncSlave())
+ {
+ // A sync slave, it doesn't start playing until it's synced up with the master.
+ // Flag this channel as waiting for sync, and return true.
+ getChannel()->setWaiting(true);
+ return true;
+ }
+
+ getChannel()->play();
+ return true;
+}
+
+
+bool LLAudioSource::isDone()
+{
+ const F32 MAX_AGE = 60.f;
+ const F32 MAX_UNPLAYED_AGE = 15.f;
+
+ if (isLoop())
+ {
+ // Looped sources never die on their own.
+ return false;
+ }
+
+
+ if (hasPendingPreloads())
+ {
+ return false;
+ }
+
+ if (mQueuedDatap)
+ {
+ // Don't kill this sound if we've got something queued up to play.
+ return false;
+ }
+
+ F32 elapsed = mAgeTimer.getElapsedTimeF32();
+
+ // This is a single-play source
+ if (!mChannelp)
+ {
+ if ((elapsed > MAX_UNPLAYED_AGE) || mPlayedOnce)
+ {
+ // We don't have a channel assigned, and it's been
+ // over 5 seconds since we tried to play it. Don't bother.
+ //llinfos << "No channel assigned, source is done" << llendl;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ if (mChannelp->isPlaying())
+ {
+ if (elapsed > MAX_AGE)
+ {
+ // Arbitarily cut off non-looped sounds when they're old.
+ return true;
+ }
+ else
+ {
+ // Sound is still playing and we haven't timed out, don't kill it.
+ return false;
+ }
+ }
+
+ if ((elapsed > MAX_UNPLAYED_AGE) || mPlayedOnce)
+ {
+ // The sound isn't playing back after 5 seconds or we're already done playing it, kill it.
+ return true;
+ }
+
+ return false;
+}
+
+
+void LLAudioSource::addAudioData(LLAudioData *adp, const bool set_current)
+{
+ // Only handle a single piece of audio data associated with a source right now,
+ // until I implement prefetch.
+ if (set_current)
+ {
+ if (!mCurrentDatap)
+ {
+ mCurrentDatap = adp;
+ if (mChannelp)
+ {
+ mChannelp->updateBuffer();
+ mChannelp->play();
+ }
+
+ // Make sure the audio engine knows that we want to request this sound.
+ gAudiop->startNextTransfer();
+ return;
+ }
+ else if (mQueueSounds)
+ {
+ // If we have current data, and we're queuing, put
+ // the object onto the queue.
+ if (mQueuedDatap)
+ {
+ // We only queue one sound at a time, and it's a FIFO.
+ // Don't put it onto the queue.
+ return;
+ }
+
+ if (adp == mCurrentDatap && isLoop())
+ {
+ // No point in queueing the same sound if
+ // we're looping.
+ return;
+ }
+ mQueuedDatap = adp;
+
+ // Make sure the audio engine knows that we want to request this sound.
+ gAudiop->startNextTransfer();
+ }
+ else
+ {
+ if (mCurrentDatap != adp)
+ {
+ // Right now, if we're currently playing this sound in a channel, we
+ // update the buffer that the channel's associated with
+ // and play it. This may not be the correct behavior.
+ mCurrentDatap = adp;
+ if (mChannelp)
+ {
+ mChannelp->updateBuffer();
+ mChannelp->play();
+ }
+ // Make sure the audio engine knows that we want to request this sound.
+ gAudiop->startNextTransfer();
+ }
+ }
+ }
+ else
+ {
+ // Add it to the preload list.
+ mPreloadMap[adp->getID()] = adp;
+ gAudiop->startNextTransfer();
+ }
+}
+
+
+bool LLAudioSource::hasPendingPreloads() const
+{
+ // Check to see if we've got any preloads on deck for this source
+ data_map::const_iterator iter;
+ for (iter = mPreloadMap.begin(); iter != mPreloadMap.end(); iter++)
+ {
+ LLAudioData *adp = iter->second;
+ // note: a bad UUID will forever be !hasDecodedData()
+ // but also !hasValidData(), hence the check for hasValidData()
+ if (!adp->hasDecodedData() && adp->hasValidData())
+ {
+ // This source is still waiting for a preload
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+LLAudioData * LLAudioSource::getCurrentData()
+{
+ return mCurrentDatap;
+}
+
+LLAudioData * LLAudioSource::getQueuedData()
+{
+ return mQueuedDatap;
+}
+
+LLAudioBuffer * LLAudioSource::getCurrentBuffer()
+{
+ if (!mCurrentDatap)
+ {
+ return NULL;
+ }
+
+ return mCurrentDatap->getBuffer();
+}
+
+
+
+
+//
+// LLAudioChannel implementation
+//
+
+
+LLAudioChannel::LLAudioChannel() :
+ mCurrentSourcep(NULL),
+ mCurrentBufferp(NULL),
+ mLoopedThisFrame(false),
+ mWaiting(false),
+ mSecondaryGain(1.0f)
+{
+}
+
+
+LLAudioChannel::~LLAudioChannel()
+{
+ // Need to disconnect any sources which are using this channel.
+ //llinfos << "Cleaning up audio channel" << llendl;
+ if (mCurrentSourcep)
+ {
+ mCurrentSourcep->setChannel(NULL);
+ }
+ mCurrentBufferp = NULL;
+}
+
+
+void LLAudioChannel::setSource(LLAudioSource *sourcep)
+{
+ //llinfos << this << ": setSource(" << sourcep << ")" << llendl;
+
+ if (!sourcep)
+ {
+ // Clearing the source for this channel, don't need to do anything.
+ //llinfos << "Clearing source for channel" << llendl;
+ cleanup();
+ mCurrentSourcep = NULL;
+ mWaiting = false;
+ return;
+ }
+
+ if (sourcep == mCurrentSourcep)
+ {
+ // Don't reallocate the channel, this will make FMOD goofy.
+ //llinfos << "Calling setSource with same source!" << llendl;
+ }
+
+ mCurrentSourcep = sourcep;
+
+
+ updateBuffer();
+ update3DPosition();
+}
+
+
+bool LLAudioChannel::updateBuffer()
+{
+ if (!mCurrentSourcep)
+ {
+ // This channel isn't associated with any source, nothing
+ // to be updated
+ return false;
+ }
+
+ // Initialize the channel's gain setting for this sound.
+ if(gAudiop)
+ {
+ setSecondaryGain(gAudiop->getSecondaryGain(mCurrentSourcep->getType()));
+ }
+
+ LLAudioBuffer *bufferp = mCurrentSourcep->getCurrentBuffer();
+ if (bufferp == mCurrentBufferp)
+ {
+ if (bufferp)
+ {
+ // The source hasn't changed what buffer it's playing
+ bufferp->mLastUseTimer.reset();
+ bufferp->mInUse = true;
+ }
+ return false;
+ }
+
+ //
+ // The source changed what buffer it's playing. We need to clean up
+ // the existing channel
+ //
+ cleanup();
+
+ mCurrentBufferp = bufferp;
+ if (bufferp)
+ {
+ bufferp->mLastUseTimer.reset();
+ bufferp->mInUse = true;
+ }
+
+ if (!mCurrentBufferp)
+ {
+ // There's no new buffer to be played, so we just abort.
+ return false;
+ }
+
+ return true;
+}
+
+
+
+
+//
+// LLAudioData implementation
+//
+
+
+LLAudioData::LLAudioData(const LLUUID &uuid) :
+ mID(uuid),
+ mBufferp(NULL),
+ mHasLocalData(false),
+ mHasDecodedData(false),
+ mHasValidData(true)
+{
+ if (uuid.isNull())
+ {
+ // This is a null sound.
+ return;
+ }
+
+ if (gAudiop && gAudiop->hasDecodedFile(uuid))
+ {
+ // Already have a decoded version, don't need to decode it.
+ mHasLocalData = true;
+ mHasDecodedData = true;
+ }
+ else if (gAssetStorage && gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND))
+ {
+ mHasLocalData = true;
+ }
+}
+
+
+bool LLAudioData::load()
+{
+ // For now, just assume we're going to use one buffer per audiodata.
+ if (mBufferp)
+ {
+ // We already have this sound in a buffer, don't do anything.
+ llinfos << "Already have a buffer for this sound, don't bother loading!" << llendl;
+ return true;
+ }
+
+ mBufferp = gAudiop->getFreeBuffer();
+ if (!mBufferp)
+ {
+ // No free buffers, abort.
+ llinfos << "Not able to allocate a new audio buffer, aborting." << llendl;
+ return false;
+ }
+
+ std::string uuid_str;
+ std::string wav_path;
+ mID.toString(uuid_str);
+ wav_path= gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str) + ".dsf";
+
+ if (!mBufferp->loadWAV(wav_path))
+ {
+ // Hrm. Right now, let's unset the buffer, since it's empty.
+ gAudiop->cleanupBuffer(mBufferp);
+ mBufferp = NULL;
+
+ return false;
+ }
+ mBufferp->mAudioDatap = this;
+ return true;
+}
+
+
diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h
new file mode 100644
index 0000000000..457fd93abe
--- /dev/null
+++ b/indra/llaudio/llaudioengine.h
@@ -0,0 +1,452 @@
+/**
+ * @file audioengine.h
+ * @brief Definition of LLAudioEngine base class abstracting the audio support
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#ifndef LL_AUDIOENGINE_H
+#define LL_AUDIOENGINE_H
+
+#include <list>
+#include <map>
+
+#include "v3math.h"
+#include "v3dmath.h"
+#include "lltimer.h"
+#include "lluuid.h"
+#include "llframetimer.h"
+#include "llassettype.h"
+
+#include "lllistener.h"
+
+const F32 LL_WIND_UPDATE_INTERVAL = 0.1f;
+const F32 LL_ROLLOFF_MULTIPLIER_UNDER_WATER = 5.f; // How much sounds are weaker under water
+const F32 LL_WIND_UNDERWATER_CENTER_FREQ = 20.f;
+
+const F32 ATTACHED_OBJECT_TIMEOUT = 5.0f;
+const F32 DEFAULT_MIN_DISTANCE = 2.0f;
+
+#define MAX_CHANNELS 30
+#define MAX_BUFFERS 40 // Some extra for preloading, maybe?
+
+// This define is intended to allow us to switch from os based wav
+// file loading to vfs based wav file loading. The problem is that I
+// am unconvinced that the LLWaveFile works for loading sounds from
+// memory. So, until that is fixed up, changed, whatever, this remains
+// undefined.
+//#define USE_WAV_VFILE
+
+class LLVFS;
+
+class LLAudioSource;
+class LLAudioData;
+class LLAudioChannel;
+class LLAudioChannelOpenAL;
+class LLAudioBuffer;
+class LLStreamingAudioInterface;
+
+
+//
+// LLAudioEngine definition
+//
+
+class LLAudioEngine
+{
+ friend class LLAudioChannelOpenAL; // bleh. channel needs some listener methods.
+
+public:
+ enum LLAudioType
+ {
+ AUDIO_TYPE_NONE = 0,
+ AUDIO_TYPE_SFX = 1,
+ AUDIO_TYPE_UI = 2,
+ AUDIO_TYPE_AMBIENT = 3,
+ AUDIO_TYPE_COUNT = 4 // last
+ };
+
+ LLAudioEngine();
+ virtual ~LLAudioEngine();
+
+ // initialization/startup/shutdown
+ virtual bool init(const S32 num_channels, void *userdata);
+ virtual std::string getDriverName(bool verbose) = 0;
+ virtual void shutdown();
+
+ // Used by the mechanics of the engine
+ //virtual void processQueue(const LLUUID &sound_guid);
+ virtual void setListener(LLVector3 pos,LLVector3 vel,LLVector3 up,LLVector3 at);
+ virtual void updateWind(LLVector3 direction, F32 camera_height_above_water) = 0;
+ virtual void idle(F32 max_decode_time = 0.f);
+ virtual void updateChannels();
+
+ //
+ // "End user" functionality
+ //
+ virtual bool isWindEnabled();
+ virtual void enableWind(bool state_b);
+
+ // Use these for temporarily muting the audio system.
+ // Does not change buffers, initialization, etc. but
+ // stops playing new sounds.
+ virtual void setMuted(bool muted);
+ virtual bool getMuted() const { return mMuted; }
+#ifdef USE_PLUGIN_MEDIA
+ LLPluginClassMedia* initializeMedia(const std::string& media_type);
+#endif
+ F32 getMasterGain();
+ void setMasterGain(F32 gain);
+
+ F32 getSecondaryGain(S32 type);
+ void setSecondaryGain(S32 type, F32 gain);
+
+ F32 getInternetStreamGain();
+
+ virtual void setDopplerFactor(F32 factor);
+ virtual F32 getDopplerFactor();
+ virtual void setRolloffFactor(F32 factor);
+ virtual F32 getRolloffFactor();
+ virtual void setMaxWindGain(F32 gain);
+
+
+ // Methods actually related to setting up and removing sounds
+ // Owner ID is the owner of the object making the request
+ void triggerSound(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain,
+ const S32 type = LLAudioEngine::AUDIO_TYPE_NONE,
+ const LLVector3d &pos_global = LLVector3d::zero);
+ bool preloadSound(const LLUUID &id);
+
+ void addAudioSource(LLAudioSource *asp);
+ void cleanupAudioSource(LLAudioSource *asp);
+
+ LLAudioSource *findAudioSource(const LLUUID &source_id);
+ LLAudioData *getAudioData(const LLUUID &audio_uuid);
+
+ // Internet stream implementation manipulation
+ LLStreamingAudioInterface *getStreamingAudioImpl();
+ void setStreamingAudioImpl(LLStreamingAudioInterface *impl);
+ // Internet stream methods - these will call down into the *mStreamingAudioImpl if it exists
+ void startInternetStream(const std::string& url);
+ void stopInternetStream();
+ void pauseInternetStream(int pause);
+ void updateInternetStream(); // expected to be called often
+ int isInternetStreamPlaying();
+ // use a value from 0.0 to 1.0, inclusive
+ void setInternetStreamGain(F32 vol);
+ std::string getInternetStreamURL();
+
+ // For debugging usage
+ virtual LLVector3 getListenerPos();
+
+ LLAudioBuffer *getFreeBuffer(); // Get a free buffer, or flush an existing one if you have to.
+ LLAudioChannel *getFreeChannel(const F32 priority); // Get a free channel or flush an existing one if your priority is higher
+ void cleanupBuffer(LLAudioBuffer *bufferp);
+
+ bool hasDecodedFile(const LLUUID &uuid);
+ bool hasLocalFile(const LLUUID &uuid);
+
+ bool updateBufferForData(LLAudioData *adp, const LLUUID &audio_uuid = LLUUID::null);
+
+
+ // Asset callback when we're retrieved a sound from the asset server.
+ void startNextTransfer();
+ static void assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code, LLExtStat ext_status);
+
+ friend class LLPipeline; // For debugging
+public:
+ F32 mMaxWindGain; // Hack. Public to set before fade in?
+
+protected:
+ virtual LLAudioBuffer *createBuffer() = 0;
+ virtual LLAudioChannel *createChannel() = 0;
+
+ virtual void initWind() = 0;
+ virtual void cleanupWind() = 0;
+ virtual void setInternalGain(F32 gain) = 0;
+
+ void commitDeferredChanges();
+
+ virtual void allocateListener() = 0;
+
+
+ // listener methods
+ virtual void setListenerPos(LLVector3 vec);
+ virtual void setListenerVelocity(LLVector3 vec);
+ virtual void orientListener(LLVector3 up, LLVector3 at);
+ virtual void translateListener(LLVector3 vec);
+
+
+ F64 mapWindVecToGain(LLVector3 wind_vec);
+ F64 mapWindVecToPitch(LLVector3 wind_vec);
+ F64 mapWindVecToPan(LLVector3 wind_vec);
+
+protected:
+ LLListener *mListenerp;
+
+ bool mMuted;
+ void* mUserData;
+
+ S32 mLastStatus;
+
+ S32 mNumChannels;
+ bool mEnableWind;
+
+ LLUUID mCurrentTransfer; // Audio file currently being transferred by the system
+ LLFrameTimer mCurrentTransferTimer;
+
+ // A list of all audio sources that are known to the viewer at this time.
+ // This is most likely a superset of the ones that we actually have audio
+ // data for, or are playing back.
+ typedef std::map<LLUUID, LLAudioSource *> source_map;
+ typedef std::map<LLUUID, LLAudioData *> data_map;
+
+ source_map mAllSources;
+ data_map mAllData;
+
+ LLAudioChannel *mChannels[MAX_CHANNELS];
+
+ // Buffers needs to change into a different data structure, as the number of buffers
+ // that we have active should be limited by RAM usage, not count.
+ LLAudioBuffer *mBuffers[MAX_BUFFERS];
+
+ F32 mMasterGain;
+ F32 mSecondaryGain[AUDIO_TYPE_COUNT];
+
+ F32 mNextWindUpdate;
+
+ LLFrameTimer mWindUpdateTimer;
+
+private:
+ void setDefaults();
+ LLStreamingAudioInterface *mStreamingAudioImpl;
+};
+
+
+
+
+//
+// Standard audio source. Can be derived from for special sources, such as those attached to objects.
+//
+
+
+class LLAudioSource
+{
+public:
+ // owner_id is the id of the agent responsible for making this sound
+ // play, for example, the owner of the object currently playing it
+ LLAudioSource(const LLUUID &id, const LLUUID& owner_id, const F32 gain, const S32 type = LLAudioEngine::AUDIO_TYPE_NONE);
+ virtual ~LLAudioSource();
+
+ virtual void update(); // Update this audio source
+ void updatePriority();
+
+ void preload(const LLUUID &audio_id); // Only used for preloading UI sounds, now.
+
+ void addAudioData(LLAudioData *adp, bool set_current = TRUE);
+
+ void setAmbient(const bool ambient) { mAmbient = ambient; }
+ bool isAmbient() const { return mAmbient; }
+
+ void setLoop(const bool loop) { mLoop = loop; }
+ bool isLoop() const { return mLoop; }
+
+ void setSyncMaster(const bool master) { mSyncMaster = master; }
+ bool isSyncMaster() const { return mSyncMaster; }
+
+ void setSyncSlave(const bool slave) { mSyncSlave = slave; }
+ bool isSyncSlave() const { return mSyncSlave; }
+
+ void setQueueSounds(const bool queue) { mQueueSounds = queue; }
+ bool isQueueSounds() const { return mQueueSounds; }
+
+ void setPlayedOnce(const bool played_once) { mPlayedOnce = played_once; }
+
+ void setType(S32 type) { mType = type; }
+ S32 getType() { return mType; }
+
+ void setPositionGlobal(const LLVector3d &position_global) { mPositionGlobal = position_global; }
+ LLVector3d getPositionGlobal() const { return mPositionGlobal; }
+ LLVector3 getVelocity() const { return mVelocity; }
+ F32 getPriority() const { return mPriority; }
+
+ // Gain should always be clamped between 0 and 1.
+ F32 getGain() const { return mGain; }
+ virtual void setGain(const F32 gain) { mGain = llclamp(gain, 0.f, 1.f); }
+
+ const LLUUID &getID() const { return mID; }
+ bool isDone();
+
+ LLAudioData *getCurrentData();
+ LLAudioData *getQueuedData();
+ LLAudioBuffer *getCurrentBuffer();
+
+ bool setupChannel();
+ bool play(const LLUUID &audio_id); // Start the audio source playing
+
+ bool hasPendingPreloads() const; // Has preloads that haven't been done yet
+
+ friend class LLAudioEngine;
+ friend class LLAudioChannel;
+protected:
+ void setChannel(LLAudioChannel *channelp);
+ LLAudioChannel *getChannel() const { return mChannelp; }
+
+protected:
+ LLUUID mID; // The ID of the source is that of the object if it's attached to an object.
+ LLUUID mOwnerID; // owner of the object playing the sound
+ F32 mPriority;
+ F32 mGain;
+ bool mAmbient;
+ bool mLoop;
+ bool mSyncMaster;
+ bool mSyncSlave;
+ bool mQueueSounds;
+ bool mPlayedOnce;
+ S32 mType;
+ LLVector3d mPositionGlobal;
+ LLVector3 mVelocity;
+
+ //LLAudioSource *mSyncMasterp; // If we're a slave, the source that we're synced to.
+ LLAudioChannel *mChannelp; // If we're currently playing back, this is the channel that we're assigned to.
+ LLAudioData *mCurrentDatap;
+ LLAudioData *mQueuedDatap;
+
+ typedef std::map<LLUUID, LLAudioData *> data_map;
+ data_map mPreloadMap;
+
+ LLFrameTimer mAgeTimer;
+};
+
+
+
+
+//
+// Generic metadata about a particular piece of audio data.
+// The actual data is handled by the derived LLAudioBuffer classes which are
+// derived for each audio engine.
+//
+
+
+class LLAudioData
+{
+public:
+ LLAudioData(const LLUUID &uuid);
+ bool load();
+
+ LLUUID getID() const { return mID; }
+ LLAudioBuffer *getBuffer() const { return mBufferp; }
+
+ bool hasLocalData() const { return mHasLocalData; }
+ bool hasDecodedData() const { return mHasDecodedData; }
+ bool hasValidData() const { return mHasValidData; }
+
+ void setHasLocalData(const bool hld) { mHasLocalData = hld; }
+ void setHasDecodedData(const bool hdd) { mHasDecodedData = hdd; }
+ void setHasValidData(const bool hvd) { mHasValidData = hvd; }
+
+ friend class LLAudioEngine; // Severe laziness, bad.
+
+protected:
+ LLUUID mID;
+ LLAudioBuffer *mBufferp; // If this data is being used by the audio system, a pointer to the buffer will be set here.
+ bool mHasLocalData;
+ bool mHasDecodedData;
+ bool mHasValidData;
+};
+
+
+//
+// Base class for an audio channel, i.e. a channel which is capable of playing back a sound.
+// Management of channels is done generically, methods for actually manipulating the channel
+// are derived for each audio engine.
+//
+
+
+class LLAudioChannel
+{
+public:
+ LLAudioChannel();
+ virtual ~LLAudioChannel();
+
+ virtual void setSource(LLAudioSource *sourcep);
+ LLAudioSource *getSource() const { return mCurrentSourcep; }
+
+ void setSecondaryGain(F32 gain) { mSecondaryGain = gain; }
+ F32 getSecondaryGain() { return mSecondaryGain; }
+
+ friend class LLAudioEngine;
+ friend class LLAudioSource;
+protected:
+ virtual void play() = 0;
+ virtual void playSynced(LLAudioChannel *channelp) = 0;
+ virtual void cleanup() = 0;
+ virtual bool isPlaying() = 0;
+ void setWaiting(const bool waiting) { mWaiting = waiting; }
+ bool isWaiting() const { return mWaiting; }
+
+ virtual bool updateBuffer(); // Check to see if the buffer associated with the source changed, and update if necessary.
+ virtual void update3DPosition() = 0;
+ virtual void updateLoop() = 0; // Update your loop/completion status, for use by queueing/syncing.
+protected:
+ LLAudioSource *mCurrentSourcep;
+ LLAudioBuffer *mCurrentBufferp;
+ bool mLoopedThisFrame;
+ bool mWaiting; // Waiting for sync.
+ F32 mSecondaryGain;
+};
+
+
+
+
+// Basically an interface class to the engine-specific implementation
+// of audio data that's ready for playback.
+// Will likely get more complex as we decide to do stuff like real streaming audio.
+
+
+class LLAudioBuffer
+{
+public:
+ virtual ~LLAudioBuffer() {};
+ virtual bool loadWAV(const std::string& filename) = 0;
+ virtual U32 getLength() = 0;
+
+ friend class LLAudioEngine;
+ friend class LLAudioChannel;
+ friend class LLAudioData;
+protected:
+ bool mInUse;
+ LLAudioData *mAudioDatap;
+ LLFrameTimer mLastUseTimer;
+};
+
+
+
+extern LLAudioEngine* gAudiop;
+
+#endif
diff --git a/indra/llaudio/llaudioengine_fmod.cpp b/indra/llaudio/llaudioengine_fmod.cpp
new file mode 100644
index 0000000000..d7f58defca
--- /dev/null
+++ b/indra/llaudio/llaudioengine_fmod.cpp
@@ -0,0 +1,769 @@
+/**
+ * @file audioengine_fmod.cpp
+ * @brief Implementation of LLAudioEngine class abstracting the audio support as a FMOD 3D implementation
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llstreamingaudio.h"
+#include "llstreamingaudio_fmod.h"
+
+#include "llaudioengine_fmod.h"
+#include "lllistener_fmod.h"
+
+#include "llerror.h"
+#include "llmath.h"
+#include "llrand.h"
+
+#include "fmod.h"
+#include "fmod_errors.h"
+#include "lldir.h"
+#include "llapr.h"
+
+#include "sound_ids.h"
+
+
+extern "C" {
+ void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata);
+}
+
+FSOUND_DSPUNIT *gWindDSP = NULL;
+
+
+LLAudioEngine_FMOD::LLAudioEngine_FMOD()
+{
+ mInited = false;
+ mWindGen = NULL;
+}
+
+
+LLAudioEngine_FMOD::~LLAudioEngine_FMOD()
+{
+}
+
+
+bool LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata)
+{
+ LLAudioEngine::init(num_channels, userdata);
+
+ // Reserve one extra channel for the http stream.
+ if (!FSOUND_SetMinHardwareChannels(num_channels + 1))
+ {
+ LL_WARNS("AppInit") << "FMOD::init[0](), error: " << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
+ }
+
+ LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() initializing FMOD" << LL_ENDL;
+
+ F32 version = FSOUND_GetVersion();
+ if (version < FMOD_VERSION)
+ {
+ LL_WARNS("AppInit") << "Error : You are using the wrong FMOD version (" << version
+ << ")! You should be using FMOD " << FMOD_VERSION << LL_ENDL;
+ //return false;
+ }
+
+ U32 fmod_flags = 0x0;
+
+#if LL_WINDOWS
+ // Windows needs to know which window is frontmost.
+ // This must be called before FSOUND_Init() per the FMOD docs.
+ // This could be used to let FMOD handle muting when we lose focus,
+ // but we don't actually want to do that because we want to distinguish
+ // between minimized and not-focused states.
+ if (!FSOUND_SetHWND(userdata))
+ {
+ LL_WARNS("AppInit") << "Error setting FMOD window: "
+ << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
+ return false;
+ }
+ // Play audio when we don't have focus.
+ // (For example, IM client on top of us.)
+ // This means we also try to play audio when minimized,
+ // so we manually handle muting in that case. JC
+ fmod_flags |= FSOUND_INIT_GLOBALFOCUS;
+#endif
+
+#if LL_LINUX
+ // initialize the FMOD engine
+
+ // This is a hack to use only FMOD's basic FPU mixer
+ // when the LL_VALGRIND environmental variable is set,
+ // otherwise valgrind will fall over on FMOD's MMX detection
+ if (getenv("LL_VALGRIND")) /*Flawfinder: ignore*/
+ {
+ LL_INFOS("AppInit") << "Pacifying valgrind in FMOD init." << LL_ENDL;
+ FSOUND_SetMixer(FSOUND_MIXER_QUALITY_FPU);
+ }
+
+ // If we don't set an output method, Linux FMOD always
+ // decides on OSS and fails otherwise. So we'll manually
+ // try ESD, then OSS, then ALSA.
+ // Why this order? See SL-13250, but in short, OSS emulated
+ // on top of ALSA is ironically more reliable than raw ALSA.
+ // Ack, and ESD has more reliable failure modes - but has worse
+ // latency - than all of them, so wins for now.
+ bool audio_ok = false;
+
+ if (!audio_ok)
+ {
+ if (NULL == getenv("LL_BAD_FMOD_ESD")) /*Flawfinder: ignore*/
+ {
+ LL_DEBUGS("AppInit") << "Trying ESD audio output..." << LL_ENDL;
+ if(FSOUND_SetOutput(FSOUND_OUTPUT_ESD) &&
+ FSOUND_Init(44100, num_channels, fmod_flags))
+ {
+ LL_DEBUGS("AppInit") << "ESD audio output initialized OKAY"
+ << LL_ENDL;
+ audio_ok = true;
+ } else {
+ LL_WARNS("AppInit") << "ESD audio output FAILED to initialize: "
+ << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
+ }
+ } else {
+ LL_DEBUGS("AppInit") << "ESD audio output SKIPPED" << LL_ENDL;
+ }
+ }
+ if (!audio_ok)
+ {
+ if (NULL == getenv("LL_BAD_FMOD_OSS")) /*Flawfinder: ignore*/
+ {
+ LL_DEBUGS("AppInit") << "Trying OSS audio output..." << LL_ENDL;
+ if(FSOUND_SetOutput(FSOUND_OUTPUT_OSS) &&
+ FSOUND_Init(44100, num_channels, fmod_flags))
+ {
+ LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL;
+ audio_ok = true;
+ } else {
+ LL_WARNS("AppInit") << "OSS audio output FAILED to initialize: "
+ << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
+ }
+ } else {
+ LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL;
+ }
+ }
+ if (!audio_ok)
+ {
+ if (NULL == getenv("LL_BAD_FMOD_ALSA")) /*Flawfinder: ignore*/
+ {
+ LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL;
+ if(FSOUND_SetOutput(FSOUND_OUTPUT_ALSA) &&
+ FSOUND_Init(44100, num_channels, fmod_flags))
+ {
+ LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL;
+ audio_ok = true;
+ } else {
+ LL_WARNS("AppInit") << "ALSA audio output FAILED to initialize: "
+ << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
+ }
+ } else {
+ LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL;
+ }
+ }
+ if (!audio_ok)
+ {
+ LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL;
+ return false;
+ }
+
+ // On Linux, FMOD causes a SIGPIPE for some netstream error
+ // conditions (an FMOD bug); ignore SIGPIPE so it doesn't crash us.
+ // NOW FIXED in FMOD 3.x since 2006-10-01.
+ //signal(SIGPIPE, SIG_IGN);
+
+ // We're interested in logging which output method we
+ // ended up with, for QA purposes.
+ switch (FSOUND_GetOutput())
+ {
+ case FSOUND_OUTPUT_NOSOUND: LL_DEBUGS("AppInit") << "Audio output: NoSound" << LL_ENDL; break;
+ case FSOUND_OUTPUT_OSS: LL_DEBUGS("AppInit") << "Audio output: OSS" << LL_ENDL; break;
+ case FSOUND_OUTPUT_ESD: LL_DEBUGS("AppInit") << "Audio output: ESD" << LL_ENDL; break;
+ case FSOUND_OUTPUT_ALSA: LL_DEBUGS("AppInit") << "Audio output: ALSA" << LL_ENDL; break;
+ default: LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break;
+ };
+
+#else // LL_LINUX
+
+ // initialize the FMOD engine
+ if (!FSOUND_Init(44100, num_channels, fmod_flags))
+ {
+ LL_WARNS("AppInit") << "Error initializing FMOD: "
+ << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
+ return false;
+ }
+
+#endif
+
+ // set up our favourite FMOD-native streaming audio implementation if none has already been added
+ if (!getStreamingAudioImpl()) // no existing implementation added
+ setStreamingAudioImpl(new LLStreamingAudio_FMOD());
+
+ LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() FMOD initialized correctly" << LL_ENDL;
+
+ mInited = true;
+
+ return true;
+}
+
+
+std::string LLAudioEngine_FMOD::getDriverName(bool verbose)
+{
+ if (verbose)
+ {
+ F32 version = FSOUND_GetVersion();
+ return llformat("FMOD version %f", version);
+ }
+ else
+ {
+ return "FMOD";
+ }
+}
+
+
+void LLAudioEngine_FMOD::allocateListener(void)
+{
+ mListenerp = (LLListener *) new LLListener_FMOD();
+ if (!mListenerp)
+ {
+ llwarns << "Listener creation failed" << llendl;
+ }
+}
+
+
+void LLAudioEngine_FMOD::shutdown()
+{
+ if (gWindDSP)
+ {
+ FSOUND_DSP_SetActive(gWindDSP,false);
+ FSOUND_DSP_Free(gWindDSP);
+ }
+
+ stopInternetStream();
+
+ LLAudioEngine::shutdown();
+
+ llinfos << "LLAudioEngine_FMOD::shutdown() closing FMOD" << llendl;
+ FSOUND_Close();
+ llinfos << "LLAudioEngine_FMOD::shutdown() done closing FMOD" << llendl;
+
+ delete mListenerp;
+ mListenerp = NULL;
+}
+
+
+LLAudioBuffer * LLAudioEngine_FMOD::createBuffer()
+{
+ return new LLAudioBufferFMOD();
+}
+
+
+LLAudioChannel * LLAudioEngine_FMOD::createChannel()
+{
+ return new LLAudioChannelFMOD();
+}
+
+
+void LLAudioEngine_FMOD::initWind()
+{
+ mWindGen = new LLWindGen<MIXBUFFERFORMAT>;
+
+ if (!gWindDSP)
+ {
+ gWindDSP = FSOUND_DSP_Create(&windCallback, FSOUND_DSP_DEFAULTPRIORITY_CLEARUNIT + 20, mWindGen);
+ }
+ if (gWindDSP)
+ {
+ FSOUND_DSP_SetActive(gWindDSP, true);
+ }
+ mNextWindUpdate = 0.0;
+}
+
+
+void LLAudioEngine_FMOD::cleanupWind()
+{
+ if (gWindDSP)
+ {
+ FSOUND_DSP_SetActive(gWindDSP, false);
+ FSOUND_DSP_Free(gWindDSP);
+ gWindDSP = NULL;
+ }
+
+ delete mWindGen;
+ mWindGen = NULL;
+}
+
+
+//-----------------------------------------------------------------------
+void LLAudioEngine_FMOD::updateWind(LLVector3 wind_vec, F32 camera_height_above_water)
+{
+ LLVector3 wind_pos;
+ F64 pitch;
+ F64 center_freq;
+
+ if (!mEnableWind)
+ {
+ return;
+ }
+
+ if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL))
+ {
+
+ // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up)
+ // need to convert this to the conventional orientation DS3D and OpenAL use
+ // where +X = right, +Y = up, +Z = backwards
+
+ wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]);
+
+ // cerr << "Wind update" << endl;
+
+ pitch = 1.0 + mapWindVecToPitch(wind_vec);
+ center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0));
+
+ mWindGen->mTargetFreq = (F32)center_freq;
+ mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain;
+ mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec);
+ }
+}
+
+/*
+//-----------------------------------------------------------------------
+void LLAudioEngine_FMOD::setSourceMinDistance(U16 source_num, F64 distance)
+{
+ if (!mInited)
+ {
+ return;
+ }
+ if (mBuffer[source_num])
+ {
+ mMinDistance[source_num] = (F32) distance;
+ if (!FSOUND_Sample_SetMinMaxDistance(mBuffer[source_num],mMinDistance[source_num], mMaxDistance[source_num]))
+ {
+ llwarns << "FMOD::setSourceMinDistance(" << source_num << "), error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------
+void LLAudioEngine_FMOD::setSourceMaxDistance(U16 source_num, F64 distance)
+{
+ if (!mInited)
+ {
+ return;
+ }
+ if (mBuffer[source_num])
+ {
+ mMaxDistance[source_num] = (F32) distance;
+ if (!FSOUND_Sample_SetMinMaxDistance(mBuffer[source_num],mMinDistance[source_num], mMaxDistance[source_num]))
+ {
+ llwarns << "FMOD::setSourceMaxDistance(" << source_num << "), error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------
+void LLAudioEngine_FMOD::get3DParams(S32 source_num, S32 *volume, S32 *freq, S32 *inside, S32 *outside, LLVector3 *orient, S32 *out_volume, F32 *min_dist, F32 *max_dist)
+{
+ *volume = 0;
+ *freq = 0;
+ *inside = 0;
+ *outside = 0;
+ *orient = LLVector3::zero;
+ *out_volume = 0;
+ *min_dist = 0.f;
+ *max_dist = 0.f;
+}
+
+*/
+
+
+//-----------------------------------------------------------------------
+void LLAudioEngine_FMOD::setInternalGain(F32 gain)
+{
+ if (!mInited)
+ {
+ return;
+ }
+
+ gain = llclamp( gain, 0.0f, 1.0f );
+ FSOUND_SetSFXMasterVolume( llround( 255.0f * gain ) );
+
+ LLStreamingAudioInterface *saimpl = getStreamingAudioImpl();
+ if ( saimpl )
+ {
+ // fmod likes its streaming audio channel gain re-asserted after
+ // master volume change.
+ saimpl->setGain(saimpl->getGain());
+ }
+}
+
+//
+// LLAudioChannelFMOD implementation
+//
+
+LLAudioChannelFMOD::LLAudioChannelFMOD() : LLAudioChannel(), mChannelID(0), mLastSamplePos(0)
+{
+}
+
+
+LLAudioChannelFMOD::~LLAudioChannelFMOD()
+{
+ cleanup();
+}
+
+
+bool LLAudioChannelFMOD::updateBuffer()
+{
+ if (LLAudioChannel::updateBuffer())
+ {
+ // Base class update returned true, which means that we need to actually
+ // set up the channel for a different buffer.
+
+ LLAudioBufferFMOD *bufferp = (LLAudioBufferFMOD *)mCurrentSourcep->getCurrentBuffer();
+
+ // Grab the FMOD sample associated with the buffer
+ FSOUND_SAMPLE *samplep = bufferp->getSample();
+ if (!samplep)
+ {
+ // This is bad, there should ALWAYS be a sample associated with a legit
+ // buffer.
+ llerrs << "No FMOD sample!" << llendl;
+ return false;
+ }
+
+
+ // Actually play the sound. Start it off paused so we can do all the necessary
+ // setup.
+ mChannelID = FSOUND_PlaySoundEx(FSOUND_FREE, samplep, FSOUND_DSP_GetSFXUnit(), true);
+
+ //llinfos << "Setting up channel " << std::hex << mChannelID << std::dec << llendl;
+ }
+
+ // If we have a source for the channel, we need to update its gain.
+ if (mCurrentSourcep)
+ {
+ // SJB: warnings can spam and hurt framerate, disabling
+ if (!FSOUND_SetVolume(mChannelID, llround(getSecondaryGain() * mCurrentSourcep->getGain() * 255.0f)))
+ {
+// llwarns << "LLAudioChannelFMOD::updateBuffer error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
+ }
+
+ if (!FSOUND_SetLoopMode(mChannelID, mCurrentSourcep->isLoop() ? FSOUND_LOOP_NORMAL : FSOUND_LOOP_OFF))
+ {
+// llwarns << "Channel " << mChannelID << "Source ID: " << mCurrentSourcep->getID()
+// << " at " << mCurrentSourcep->getPositionGlobal() << llendl;
+// llwarns << "LLAudioChannelFMOD::updateBuffer error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
+ }
+ }
+
+ return true;
+}
+
+
+void LLAudioChannelFMOD::update3DPosition()
+{
+ if (!mChannelID)
+ {
+ // We're not actually a live channel (i.e., we're not playing back anything)
+ return;
+ }
+
+ LLAudioBufferFMOD *bufferp = (LLAudioBufferFMOD *)mCurrentBufferp;
+ if (!bufferp)
+ {
+ // We don't have a buffer associated with us (should really have been picked up
+ // by the above if.
+ return;
+ }
+
+ if (mCurrentSourcep->isAmbient())
+ {
+ // Ambient sound, don't need to do any positional updates.
+ bufferp->set3DMode(false);
+ }
+ else
+ {
+ // Localized sound. Update the position and velocity of the sound.
+ bufferp->set3DMode(true);
+
+ LLVector3 float_pos;
+ float_pos.setVec(mCurrentSourcep->getPositionGlobal());
+ if (!FSOUND_3D_SetAttributes(mChannelID, float_pos.mV, mCurrentSourcep->getVelocity().mV))
+ {
+ LL_DEBUGS("FMOD") << "LLAudioChannelFMOD::update3DPosition error: " << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
+ }
+ }
+}
+
+
+void LLAudioChannelFMOD::updateLoop()
+{
+ if (!mChannelID)
+ {
+ // May want to clear up the loop/sample counters.
+ return;
+ }
+
+ //
+ // Hack: We keep track of whether we looped or not by seeing when the
+ // sample position looks like it's going backwards. Not reliable; may
+ // yield false negatives.
+ //
+ U32 cur_pos = FSOUND_GetCurrentPosition(mChannelID);
+ if (cur_pos < (U32)mLastSamplePos)
+ {
+ mLoopedThisFrame = true;
+ }
+ mLastSamplePos = cur_pos;
+}
+
+
+void LLAudioChannelFMOD::cleanup()
+{
+ if (!mChannelID)
+ {
+ //llinfos << "Aborting cleanup with no channelID." << llendl;
+ return;
+ }
+
+ //llinfos << "Cleaning up channel: " << mChannelID << llendl;
+ if (!FSOUND_StopSound(mChannelID))
+ {
+ LL_DEBUGS("FMOD") << "LLAudioChannelFMOD::cleanup error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
+ }
+
+ mCurrentBufferp = NULL;
+ mChannelID = 0;
+}
+
+
+void LLAudioChannelFMOD::play()
+{
+ if (!mChannelID)
+ {
+ llwarns << "Playing without a channelID, aborting" << llendl;
+ return;
+ }
+
+ if (!FSOUND_SetPaused(mChannelID, false))
+ {
+ llwarns << "LLAudioChannelFMOD::play error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
+ }
+ getSource()->setPlayedOnce(true);
+}
+
+
+void LLAudioChannelFMOD::playSynced(LLAudioChannel *channelp)
+{
+ LLAudioChannelFMOD *fmod_channelp = (LLAudioChannelFMOD*)channelp;
+ if (!(fmod_channelp->mChannelID && mChannelID))
+ {
+ // Don't have channels allocated to both the master and the slave
+ return;
+ }
+
+ U32 position = FSOUND_GetCurrentPosition(fmod_channelp->mChannelID) % mCurrentBufferp->getLength();
+ // Try to match the position of our sync master
+ if (!FSOUND_SetCurrentPosition(mChannelID, position))
+ {
+ llwarns << "LLAudioChannelFMOD::playSynced unable to set current position" << llendl;
+ }
+
+ // Start us playing
+ play();
+}
+
+
+bool LLAudioChannelFMOD::isPlaying()
+{
+ if (!mChannelID)
+ {
+ return false;
+ }
+
+ return FSOUND_IsPlaying(mChannelID) && (!FSOUND_GetPaused(mChannelID));
+}
+
+
+
+//
+// LLAudioBufferFMOD implementation
+//
+
+
+LLAudioBufferFMOD::LLAudioBufferFMOD()
+{
+ mSamplep = NULL;
+}
+
+
+LLAudioBufferFMOD::~LLAudioBufferFMOD()
+{
+ if (mSamplep)
+ {
+ // Clean up the associated FMOD sample if it exists.
+ FSOUND_Sample_Free(mSamplep);
+ mSamplep = NULL;
+ }
+}
+
+
+bool LLAudioBufferFMOD::loadWAV(const std::string& filename)
+{
+ // Try to open a wav file from disk. This will eventually go away, as we don't
+ // really want to block doing this.
+ if (filename.empty())
+ {
+ // invalid filename, abort.
+ return false;
+ }
+
+ if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB))
+ {
+ // File not found, abort.
+ return false;
+ }
+
+ if (mSamplep)
+ {
+ // If there's already something loaded in this buffer, clean it up.
+ FSOUND_Sample_Free(mSamplep);
+ mSamplep = NULL;
+ }
+
+ // Load up the wav file into an fmod sample
+#if LL_WINDOWS
+ // MikeS. - Loading the sound file manually and then handing it over to FMOD,
+ // since FMOD uses posix IO internally,
+ // which doesn't work with unicode file paths.
+ LLFILE* sound_file = LLFile::fopen(filename,"rb"); /* Flawfinder: ignore */
+ if (sound_file)
+ {
+ fseek(sound_file,0,SEEK_END);
+ U32 file_length = ftell(sound_file); //Find the length of the file by seeking to the end and getting the offset
+ size_t read_count;
+ fseek(sound_file,0,SEEK_SET); //Seek back to the beginning
+ char* buffer = new char[file_length];
+ llassert(buffer);
+ read_count = fread((void*)buffer,file_length,1,sound_file);//Load it..
+ if(ferror(sound_file)==0 && (read_count == 1)){//No read error, and we got 1 chunk of our size...
+ unsigned int mode_flags = FSOUND_LOOP_NORMAL | FSOUND_LOADMEMORY;
+ //FSOUND_16BITS | FSOUND_MONO | FSOUND_LOADMEMORY | FSOUND_LOOP_NORMAL;
+ mSamplep = FSOUND_Sample_Load(FSOUND_UNMANAGED, buffer, mode_flags , 0, file_length);
+ }
+ delete[] buffer;
+ fclose(sound_file);
+ }
+#else
+ mSamplep = FSOUND_Sample_Load(FSOUND_UNMANAGED, filename.c_str(), FSOUND_LOOP_NORMAL, 0, 0);
+#endif
+
+ if (!mSamplep)
+ {
+ // We failed to load the file for some reason.
+ llwarns << "Could not load data '" << filename << "': "
+ << FMOD_ErrorString(FSOUND_GetError()) << llendl;
+
+ //
+ // If we EVER want to load wav files provided by end users, we need
+ // to rethink this!
+ //
+ // file is probably corrupt - remove it.
+ LLFile::remove(filename);
+ return false;
+ }
+
+ // Everything went well, return true
+ return true;
+}
+
+
+U32 LLAudioBufferFMOD::getLength()
+{
+ if (!mSamplep)
+ {
+ return 0;
+ }
+
+ return FSOUND_Sample_GetLength(mSamplep);
+}
+
+
+void LLAudioBufferFMOD::set3DMode(bool use3d)
+{
+ U16 current_mode = FSOUND_Sample_GetMode(mSamplep);
+
+ if (use3d)
+ {
+ if (!FSOUND_Sample_SetMode(mSamplep, (current_mode & (~FSOUND_2D))))
+ {
+ llwarns << "LLAudioBufferFMOD::set3DMode error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
+ }
+ }
+ else
+ {
+ if (!FSOUND_Sample_SetMode(mSamplep, current_mode | FSOUND_2D))
+ {
+ llwarns << "LLAudioBufferFMOD::set3DMode error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
+ }
+ }
+}
+
+
+void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata)
+{
+ // originalbuffer = fmod's original mixbuffer.
+ // newbuffer = the buffer passed from the previous DSP unit.
+ // length = length in samples at this mix time.
+ // param = user parameter passed through in FSOUND_DSP_Create.
+ //
+ // modify the buffer in some fashion
+
+ LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT> *windgen =
+ (LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT> *)userdata;
+ U8 stride;
+
+#if LL_DARWIN
+ stride = sizeof(LLAudioEngine_FMOD::MIXBUFFERFORMAT);
+#else
+ int mixertype = FSOUND_GetMixer();
+ if (mixertype == FSOUND_MIXER_BLENDMODE ||
+ mixertype == FSOUND_MIXER_QUALITY_FPU)
+ {
+ stride = 4;
+ }
+ else
+ {
+ stride = 2;
+ }
+#endif
+
+ newbuffer = windgen->windGenerate((LLAudioEngine_FMOD::MIXBUFFERFORMAT *)newbuffer, length, stride);
+
+ return newbuffer;
+}
diff --git a/indra/llaudio/llaudioengine_fmod.h b/indra/llaudio/llaudioengine_fmod.h
new file mode 100644
index 0000000000..3968657cba
--- /dev/null
+++ b/indra/llaudio/llaudioengine_fmod.h
@@ -0,0 +1,129 @@
+/**
+ * @file audioengine_fmod.h
+ * @brief Definition of LLAudioEngine class abstracting the audio
+ * support as a FMOD 3D implementation
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_AUDIOENGINE_FMOD_H
+#define LL_AUDIOENGINE_FMOD_H
+
+#include "llaudioengine.h"
+#include "lllistener_fmod.h"
+#include "llwindgen.h"
+
+#include "fmod.h"
+
+class LLAudioStreamManagerFMOD;
+
+class LLAudioEngine_FMOD : public LLAudioEngine
+{
+public:
+ LLAudioEngine_FMOD();
+ virtual ~LLAudioEngine_FMOD();
+
+ // initialization/startup/shutdown
+ virtual bool init(const S32 num_channels, void *user_data);
+ virtual std::string getDriverName(bool verbose);
+ virtual void allocateListener();
+
+ virtual void shutdown();
+
+ /*virtual*/ void initWind();
+ /*virtual*/ void cleanupWind();
+
+ /*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water);
+
+#if LL_DARWIN
+ typedef S32 MIXBUFFERFORMAT;
+#else
+ typedef S16 MIXBUFFERFORMAT;
+#endif
+
+protected:
+ /*virtual*/ LLAudioBuffer *createBuffer(); // Get a free buffer, or flush an existing one if you have to.
+ /*virtual*/ LLAudioChannel *createChannel(); // Create a new audio channel.
+
+ /*virtual*/ void setInternalGain(F32 gain);
+protected:
+ static signed char F_CALLBACKAPI callbackMetaData(char* name, char* value, void* userdata);
+
+ //F32 mMinDistance[MAX_BUFFERS];
+ //F32 mMaxDistance[MAX_BUFFERS];
+
+ bool mInited;
+
+ // On Windows, userdata is the HWND of the application window.
+ void* mUserData;
+
+ LLWindGen<MIXBUFFERFORMAT> *mWindGen;
+};
+
+
+class LLAudioChannelFMOD : public LLAudioChannel
+{
+public:
+ LLAudioChannelFMOD();
+ virtual ~LLAudioChannelFMOD();
+
+protected:
+ /*virtual*/ void play();
+ /*virtual*/ void playSynced(LLAudioChannel *channelp);
+ /*virtual*/ void cleanup();
+ /*virtual*/ bool isPlaying();
+
+ /*virtual*/ bool updateBuffer();
+ /*virtual*/ void update3DPosition();
+ /*virtual*/ void updateLoop();
+
+protected:
+ int mChannelID;
+ S32 mLastSamplePos;
+};
+
+
+class LLAudioBufferFMOD : public LLAudioBuffer
+{
+public:
+ LLAudioBufferFMOD();
+ virtual ~LLAudioBufferFMOD();
+
+ /*virtual*/ bool loadWAV(const std::string& filename);
+ /*virtual*/ U32 getLength();
+ friend class LLAudioChannelFMOD;
+
+ void set3DMode(bool use3d);
+protected:
+ FSOUND_SAMPLE *getSample() { return mSamplep; }
+protected:
+ FSOUND_SAMPLE *mSamplep;
+};
+
+
+#endif // LL_AUDIOENGINE_FMOD_H
diff --git a/indra/llaudio/llaudioengine_openal.cpp b/indra/llaudio/llaudioengine_openal.cpp
new file mode 100644
index 0000000000..a5982ccbd6
--- /dev/null
+++ b/indra/llaudio/llaudioengine_openal.cpp
@@ -0,0 +1,546 @@
+/**
+ * @file audioengine_openal.cpp
+ * @brief implementation of audio engine using OpenAL
+ * support as a OpenAL 3D implementation
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "lldir.h"
+
+#include "llaudioengine_openal.h"
+#include "lllistener_openal.h"
+
+
+LLAudioEngine_OpenAL::LLAudioEngine_OpenAL()
+ :
+ mWindGen(NULL),
+ mWindBuf(NULL),
+ mWindBufFreq(0),
+ mWindBufSamples(0),
+ mWindBufBytes(0),
+ mWindSource(AL_NONE),
+ mNumEmptyWindALBuffers(MAX_NUM_WIND_BUFFERS)
+{
+}
+
+// virtual
+LLAudioEngine_OpenAL::~LLAudioEngine_OpenAL()
+{
+}
+
+// virtual
+bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata)
+{
+ mWindGen = NULL;
+ LLAudioEngine::init(num_channels, userdata);
+
+ if(!alutInit(NULL, NULL))
+ {
+ llwarns << "LLAudioEngine_OpenAL::init() ALUT initialization failed: " << alutGetErrorString (alutGetError ()) << llendl;
+ return false;
+ }
+
+ llinfos << "LLAudioEngine_OpenAL::init() OpenAL successfully initialized" << llendl;
+
+ llinfos << "OpenAL version: "
+ << ll_safe_string(alGetString(AL_VERSION)) << llendl;
+ llinfos << "OpenAL vendor: "
+ << ll_safe_string(alGetString(AL_VENDOR)) << llendl;
+ llinfos << "OpenAL renderer: "
+ << ll_safe_string(alGetString(AL_RENDERER)) << llendl;
+
+ ALint major = alutGetMajorVersion ();
+ ALint minor = alutGetMinorVersion ();
+ llinfos << "ALUT version: " << major << "." << minor << llendl;
+
+ ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext());
+
+ alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major);
+ alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &minor);
+ llinfos << "ALC version: " << major << "." << minor << llendl;
+
+ llinfos << "ALC default device: "
+ << ll_safe_string(alcGetString(device,
+ ALC_DEFAULT_DEVICE_SPECIFIER))
+ << llendl;
+
+ return true;
+}
+
+// virtual
+std::string LLAudioEngine_OpenAL::getDriverName(bool verbose)
+{
+ ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext());
+ std::ostringstream version;
+
+ version <<
+ "OpenAL";
+
+ if (verbose)
+ {
+ version <<
+ ", version " <<
+ ll_safe_string(alGetString(AL_VERSION)) <<
+ " / " <<
+ ll_safe_string(alGetString(AL_VENDOR)) <<
+ " / " <<
+ ll_safe_string(alGetString(AL_RENDERER));
+
+ if (device)
+ version <<
+ ": " <<
+ ll_safe_string(alcGetString(device,
+ ALC_DEFAULT_DEVICE_SPECIFIER));
+ }
+
+ return version.str();
+}
+
+// virtual
+void LLAudioEngine_OpenAL::allocateListener()
+{
+ mListenerp = (LLListener *) new LLListener_OpenAL();
+ if(!mListenerp)
+ {
+ llwarns << "LLAudioEngine_OpenAL::allocateListener() Listener creation failed" << llendl;
+ }
+}
+
+// virtual
+void LLAudioEngine_OpenAL::shutdown()
+{
+ llinfos << "About to LLAudioEngine::shutdown()" << llendl;
+ LLAudioEngine::shutdown();
+
+ llinfos << "About to alutExit()" << llendl;
+ if(!alutExit())
+ {
+ llwarns << "Nuts." << llendl;
+ llwarns << "LLAudioEngine_OpenAL::shutdown() ALUT shutdown failed: " << alutGetErrorString (alutGetError ()) << llendl;
+ }
+
+ llinfos << "LLAudioEngine_OpenAL::shutdown() OpenAL successfully shut down" << llendl;
+
+ delete mListenerp;
+ mListenerp = NULL;
+}
+
+LLAudioBuffer *LLAudioEngine_OpenAL::createBuffer()
+{
+ return new LLAudioBufferOpenAL();
+}
+
+LLAudioChannel *LLAudioEngine_OpenAL::createChannel()
+{
+ return new LLAudioChannelOpenAL();
+}
+
+void LLAudioEngine_OpenAL::setInternalGain(F32 gain)
+{
+ //llinfos << "LLAudioEngine_OpenAL::setInternalGain() Gain: " << gain << llendl;
+ alListenerf(AL_GAIN, gain);
+}
+
+LLAudioChannelOpenAL::LLAudioChannelOpenAL()
+ :
+ mALSource(AL_NONE),
+ mLastSamplePos(0)
+{
+ alGenSources(1, &mALSource);
+}
+
+LLAudioChannelOpenAL::~LLAudioChannelOpenAL()
+{
+ cleanup();
+ alDeleteSources(1, &mALSource);
+}
+
+void LLAudioChannelOpenAL::cleanup()
+{
+ alSourceStop(mALSource);
+ mCurrentBufferp = NULL;
+}
+
+void LLAudioChannelOpenAL::play()
+{
+ if (mALSource == AL_NONE)
+ {
+ llwarns << "Playing without a mALSource, aborting" << llendl;
+ return;
+ }
+
+ if(!isPlaying())
+ {
+ alSourcePlay(mALSource);
+ getSource()->setPlayedOnce(true);
+ }
+}
+
+void LLAudioChannelOpenAL::playSynced(LLAudioChannel *channelp)
+{
+ if (channelp)
+ {
+ LLAudioChannelOpenAL *masterchannelp =
+ (LLAudioChannelOpenAL*)channelp;
+ if (mALSource != AL_NONE &&
+ masterchannelp->mALSource != AL_NONE)
+ {
+ // we have channels allocated to master and slave
+ ALfloat master_offset;
+ alGetSourcef(masterchannelp->mALSource, AL_SEC_OFFSET,
+ &master_offset);
+
+ llinfos << "Syncing with master at " << master_offset
+ << "sec" << llendl;
+ // *TODO: detect when this fails, maybe use AL_SAMPLE_
+ alSourcef(mALSource, AL_SEC_OFFSET, master_offset);
+ }
+ }
+ play();
+}
+
+bool LLAudioChannelOpenAL::isPlaying()
+{
+ if (mALSource != AL_NONE)
+ {
+ ALint state;
+ alGetSourcei(mALSource, AL_SOURCE_STATE, &state);
+ if(state == AL_PLAYING)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool LLAudioChannelOpenAL::updateBuffer()
+{
+ if (LLAudioChannel::updateBuffer())
+ {
+ // Base class update returned true, which means that we need to actually
+ // set up the source for a different buffer.
+ LLAudioBufferOpenAL *bufferp = (LLAudioBufferOpenAL *)mCurrentSourcep->getCurrentBuffer();
+ ALuint buffer = bufferp->getBuffer();
+ alSourcei(mALSource, AL_BUFFER, buffer);
+ mLastSamplePos = 0;
+ }
+
+ if (mCurrentSourcep)
+ {
+ alSourcef(mALSource, AL_GAIN,
+ mCurrentSourcep->getGain() * getSecondaryGain());
+ alSourcei(mALSource, AL_LOOPING,
+ mCurrentSourcep->isLoop() ? AL_TRUE : AL_FALSE);
+ alSourcef(mALSource, AL_ROLLOFF_FACTOR,
+ gAudiop->mListenerp->getRolloffFactor());
+ }
+
+ return true;
+}
+
+
+void LLAudioChannelOpenAL::updateLoop()
+{
+ if (mALSource == AL_NONE)
+ {
+ return;
+ }
+
+ // Hack: We keep track of whether we looped or not by seeing when the
+ // sample position looks like it's going backwards. Not reliable; may
+ // yield false negatives.
+ //
+ ALint cur_pos;
+ alGetSourcei(mALSource, AL_SAMPLE_OFFSET, &cur_pos);
+ if (cur_pos < mLastSamplePos)
+ {
+ mLoopedThisFrame = true;
+ }
+ mLastSamplePos = cur_pos;
+}
+
+
+void LLAudioChannelOpenAL::update3DPosition()
+{
+ if(!mCurrentSourcep)
+ {
+ return;
+ }
+ if (mCurrentSourcep->isAmbient())
+ {
+ alSource3f(mALSource, AL_POSITION, 0.0, 0.0, 0.0);
+ alSource3f(mALSource, AL_VELOCITY, 0.0, 0.0, 0.0);
+ alSourcei (mALSource, AL_SOURCE_RELATIVE, AL_TRUE);
+ } else {
+ LLVector3 float_pos;
+ float_pos.setVec(mCurrentSourcep->getPositionGlobal());
+ alSourcefv(mALSource, AL_POSITION, float_pos.mV);
+ alSourcefv(mALSource, AL_VELOCITY, mCurrentSourcep->getVelocity().mV);
+ alSourcei (mALSource, AL_SOURCE_RELATIVE, AL_FALSE);
+ }
+
+ alSourcef(mALSource, AL_GAIN, mCurrentSourcep->getGain() * getSecondaryGain());
+}
+
+LLAudioBufferOpenAL::LLAudioBufferOpenAL()
+{
+ mALBuffer = AL_NONE;
+}
+
+LLAudioBufferOpenAL::~LLAudioBufferOpenAL()
+{
+ cleanup();
+}
+
+void LLAudioBufferOpenAL::cleanup()
+{
+ if(mALBuffer != AL_NONE)
+ {
+ alDeleteBuffers(1, &mALBuffer);
+ mALBuffer = AL_NONE;
+ }
+}
+
+bool LLAudioBufferOpenAL::loadWAV(const std::string& filename)
+{
+ cleanup();
+ mALBuffer = alutCreateBufferFromFile(filename.c_str());
+ if(mALBuffer == AL_NONE)
+ {
+ ALenum error = alutGetError();
+ if (gDirUtilp->fileExists(filename))
+ {
+ llwarns <<
+ "LLAudioBufferOpenAL::loadWAV() Error loading "
+ << filename
+ << " " << alutGetErrorString(error) << llendl;
+ }
+ else
+ {
+ // It's common for the file to not actually exist.
+ lldebugs <<
+ "LLAudioBufferOpenAL::loadWAV() Error loading "
+ << filename
+ << " " << alutGetErrorString(error) << llendl;
+ }
+ return false;
+ }
+
+ return true;
+}
+
+U32 LLAudioBufferOpenAL::getLength()
+{
+ if(mALBuffer == AL_NONE)
+ {
+ return 0;
+ }
+ ALint length;
+ alGetBufferi(mALBuffer, AL_SIZE, &length);
+ return length / 2; // convert size in bytes to size in (16-bit) samples
+}
+
+// ------------
+
+void LLAudioEngine_OpenAL::initWind()
+{
+ ALenum error;
+ llinfos << "LLAudioEngine_OpenAL::initWind() start" << llendl;
+
+ mNumEmptyWindALBuffers = MAX_NUM_WIND_BUFFERS;
+
+ alGetError(); /* clear error */
+
+ alGenSources(1,&mWindSource);
+
+ if((error=alGetError()) != AL_NO_ERROR)
+ {
+ llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind sources: "<<error<<llendl;
+ }
+
+ mWindGen = new LLWindGen<WIND_SAMPLE_T>;
+
+ mWindBufFreq = mWindGen->getInputSamplingRate();
+ mWindBufSamples = llceil(mWindBufFreq * WIND_BUFFER_SIZE_SEC);
+ mWindBufBytes = mWindBufSamples * 2 /*stereo*/ * sizeof(WIND_SAMPLE_T);
+
+ mWindBuf = new WIND_SAMPLE_T [mWindBufSamples * 2 /*stereo*/];
+
+ if(mWindBuf==NULL)
+ {
+ llerrs << "LLAudioEngine_OpenAL::initWind() Error creating wind memory buffer" << llendl;
+ mEnableWind=false;
+ }
+
+ llinfos << "LLAudioEngine_OpenAL::initWind() done" << llendl;
+}
+
+void LLAudioEngine_OpenAL::cleanupWind()
+{
+ llinfos << "LLAudioEngine_OpenAL::cleanupWind()" << llendl;
+
+ if (mWindSource != AL_NONE)
+ {
+ // detach and delete all outstanding buffers on the wind source
+ alSourceStop(mWindSource);
+ ALint processed;
+ alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed);
+ while (processed--)
+ {
+ ALuint buffer = AL_NONE;
+ alSourceUnqueueBuffers(mWindSource, 1, &buffer);
+ alDeleteBuffers(1, &buffer);
+ }
+
+ // delete the wind source itself
+ alDeleteSources(1, &mWindSource);
+
+ mWindSource = AL_NONE;
+ }
+
+ delete[] mWindBuf;
+ mWindBuf = NULL;
+
+ delete mWindGen;
+ mWindGen = NULL;
+}
+
+void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude)
+{
+ LLVector3 wind_pos;
+ F64 pitch;
+ F64 center_freq;
+ ALenum error;
+
+ if (!mEnableWind)
+ return;
+
+ if(!mWindBuf)
+ return;
+
+ if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL))
+ {
+
+ // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up)
+ // need to convert this to the conventional orientation DS3D and OpenAL use
+ // where +X = right, +Y = up, +Z = backwards
+
+ wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]);
+
+ pitch = 1.0 + mapWindVecToPitch(wind_vec);
+ center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0));
+
+ mWindGen->mTargetFreq = (F32)center_freq;
+ mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain;
+ mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec);
+
+ alSourcei(mWindSource, AL_LOOPING, AL_FALSE);
+ alSource3f(mWindSource, AL_POSITION, 0.0, 0.0, 0.0);
+ alSource3f(mWindSource, AL_VELOCITY, 0.0, 0.0, 0.0);
+ alSourcef(mWindSource, AL_ROLLOFF_FACTOR, 0.0);
+ alSourcei(mWindSource, AL_SOURCE_RELATIVE, AL_TRUE);
+ }
+
+ // ok lets make a wind buffer now
+
+ ALint processed, queued, unprocessed;
+ alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed);
+ alGetSourcei(mWindSource, AL_BUFFERS_QUEUED, &queued);
+ unprocessed = queued - processed;
+
+ // ensure that there are always at least 3x as many filled buffers
+ // queued as we managed to empty since last time.
+ mNumEmptyWindALBuffers = llmin(mNumEmptyWindALBuffers + processed * 3 - unprocessed, MAX_NUM_WIND_BUFFERS-unprocessed);
+ mNumEmptyWindALBuffers = llmax(mNumEmptyWindALBuffers, 0);
+
+ //llinfos << "mNumEmptyWindALBuffers: " << mNumEmptyWindALBuffers <<" (" << unprocessed << ":" << processed << ")" << llendl;
+
+ while(processed--) // unqueue old buffers
+ {
+ ALuint buffer;
+ ALenum error;
+ alGetError(); /* clear error */
+ alSourceUnqueueBuffers(mWindSource, 1, &buffer);
+ error = alGetError();
+ if(error != AL_NO_ERROR)
+ {
+ llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (unqueuing) buffers" << llendl;
+ }
+ else
+ {
+ alDeleteBuffers(1, &buffer);
+ }
+ }
+
+ unprocessed += mNumEmptyWindALBuffers;
+ while (mNumEmptyWindALBuffers > 0) // fill+queue new buffers
+ {
+ ALuint buffer;
+ alGetError(); /* clear error */
+ alGenBuffers(1,&buffer);
+ if((error=alGetError()) != AL_NO_ERROR)
+ {
+ llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind buffer: " << error << llendl;
+ break;
+ }
+
+ alBufferData(buffer,
+ AL_FORMAT_STEREO16,
+ mWindGen->windGenerate(mWindBuf,
+ mWindBufSamples, 2),
+ mWindBufBytes,
+ mWindBufFreq);
+ error = alGetError();
+ if(error != AL_NO_ERROR)
+ {
+ llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (bufferdata) buffers" << llendl;
+ }
+
+ alSourceQueueBuffers(mWindSource, 1, &buffer);
+ error = alGetError();
+ if(error != AL_NO_ERROR)
+ {
+ llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (queuing) buffers" << llendl;
+ }
+
+ --mNumEmptyWindALBuffers;
+ }
+
+ ALint playing;
+ alGetSourcei(mWindSource, AL_SOURCE_STATE, &playing);
+ if(playing != AL_PLAYING)
+ {
+ alSourcePlay(mWindSource);
+
+ lldebugs << "Wind had stopped - probably ran out of buffers - restarting: " << (unprocessed+mNumEmptyWindALBuffers) << " now queued." << llendl;
+ }
+}
+
diff --git a/indra/llaudio/llaudioengine_openal.h b/indra/llaudio/llaudioengine_openal.h
new file mode 100644
index 0000000000..5aca03e195
--- /dev/null
+++ b/indra/llaudio/llaudioengine_openal.h
@@ -0,0 +1,114 @@
+/**
+ * @file audioengine_openal.cpp
+ * @brief implementation of audio engine using OpenAL
+ * support as a OpenAL 3D implementation
+ *
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#ifndef LL_AUDIOENGINE_OPENAL_H
+#define LL_AUDIOENGINE_OPENAL_H
+
+#include "llaudioengine.h"
+#include "lllistener_openal.h"
+#include "llwindgen.h"
+
+class LLAudioEngine_OpenAL : public LLAudioEngine
+{
+ public:
+ LLAudioEngine_OpenAL();
+ virtual ~LLAudioEngine_OpenAL();
+
+ virtual bool init(const S32 num_channels, void *user_data);
+ virtual std::string getDriverName(bool verbose);
+ virtual void allocateListener();
+
+ virtual void shutdown();
+
+ void setInternalGain(F32 gain);
+
+ LLAudioBuffer* createBuffer();
+ LLAudioChannel* createChannel();
+
+ /*virtual*/ void initWind();
+ /*virtual*/ void cleanupWind();
+ /*virtual*/ void updateWind(LLVector3 direction, F32 camera_altitude);
+
+ private:
+ void * windDSP(void *newbuffer, int length);
+ typedef S16 WIND_SAMPLE_T;
+ LLWindGen<WIND_SAMPLE_T> *mWindGen;
+ S16 *mWindBuf;
+ U32 mWindBufFreq;
+ U32 mWindBufSamples;
+ U32 mWindBufBytes;
+ ALuint mWindSource;
+ int mNumEmptyWindALBuffers;
+
+ static const int MAX_NUM_WIND_BUFFERS = 80;
+ static const float WIND_BUFFER_SIZE_SEC = 0.05f; // 1/20th sec
+};
+
+class LLAudioChannelOpenAL : public LLAudioChannel
+{
+ public:
+ LLAudioChannelOpenAL();
+ virtual ~LLAudioChannelOpenAL();
+ protected:
+ /*virtual*/ void play();
+ /*virtual*/ void playSynced(LLAudioChannel *channelp);
+ /*virtual*/ void cleanup();
+ /*virtual*/ bool isPlaying();
+
+ /*virtual*/ bool updateBuffer();
+ /*virtual*/ void update3DPosition();
+ /*virtual*/ void updateLoop();
+
+ ALuint mALSource;
+ ALint mLastSamplePos;
+};
+
+class LLAudioBufferOpenAL : public LLAudioBuffer{
+ public:
+ LLAudioBufferOpenAL();
+ virtual ~LLAudioBufferOpenAL();
+
+ bool loadWAV(const std::string& filename);
+ U32 getLength();
+
+ friend class LLAudioChannelOpenAL;
+ protected:
+ void cleanup();
+ ALuint getBuffer() {return mALBuffer;}
+
+ ALuint mALBuffer;
+};
+
+#endif
diff --git a/indra/llaudio/lllistener.cpp b/indra/llaudio/lllistener.cpp
new file mode 100644
index 0000000000..846c6bccb5
--- /dev/null
+++ b/indra/llaudio/lllistener.cpp
@@ -0,0 +1,142 @@
+/**
+ * @file listener.cpp
+ * @brief Implementation of LISTENER class abstracting the audio support
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lllistener.h"
+
+#define DEFAULT_AT 0.0f,0.0f,-1.0f
+#define DEFAULT_UP 0.0f,1.0f,0.0f
+
+//-----------------------------------------------------------------------
+// constructor
+//-----------------------------------------------------------------------
+LLListener::LLListener()
+{
+ init();
+}
+
+//-----------------------------------------------------------------------
+LLListener::~LLListener()
+{
+}
+
+//-----------------------------------------------------------------------
+void LLListener::init(void)
+{
+ mPosition.zeroVec();
+ mListenAt.setVec(DEFAULT_AT);
+ mListenUp.setVec(DEFAULT_UP);
+ mVelocity.zeroVec();
+}
+
+//-----------------------------------------------------------------------
+void LLListener::translate(LLVector3 offset)
+{
+ mPosition += offset;
+}
+
+//-----------------------------------------------------------------------
+void LLListener::setPosition(LLVector3 pos)
+{
+ mPosition = pos;
+}
+
+//-----------------------------------------------------------------------
+LLVector3 LLListener::getPosition(void)
+{
+ return(mPosition);
+}
+
+//-----------------------------------------------------------------------
+LLVector3 LLListener::getAt(void)
+{
+ return(mListenAt);
+}
+
+//-----------------------------------------------------------------------
+LLVector3 LLListener::getUp(void)
+{
+ return(mListenUp);
+}
+
+//-----------------------------------------------------------------------
+void LLListener::setVelocity(LLVector3 vel)
+{
+ mVelocity = vel;
+}
+
+//-----------------------------------------------------------------------
+void LLListener::orient(LLVector3 up, LLVector3 at)
+{
+ mListenUp = up;
+ mListenAt = at;
+}
+
+//-----------------------------------------------------------------------
+void LLListener::set(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at)
+{
+ mPosition = pos;
+ mVelocity = vel;
+
+ setPosition(pos);
+ setVelocity(vel);
+ orient(up,at);
+}
+
+//-----------------------------------------------------------------------
+void LLListener::setDopplerFactor(F32 factor)
+{
+}
+
+//-----------------------------------------------------------------------
+F32 LLListener::getDopplerFactor()
+{
+ return (1.f);
+}
+
+//-----------------------------------------------------------------------
+void LLListener::setRolloffFactor(F32 factor)
+{
+}
+
+//-----------------------------------------------------------------------
+F32 LLListener::getRolloffFactor()
+{
+ return (1.f);
+}
+
+//-----------------------------------------------------------------------
+void LLListener::commitDeferredChanges()
+{
+}
+
diff --git a/indra/llaudio/lllistener.h b/indra/llaudio/lllistener.h
new file mode 100644
index 0000000000..e94fbe853f
--- /dev/null
+++ b/indra/llaudio/lllistener.h
@@ -0,0 +1,78 @@
+/**
+ * @file listener.h
+ * @brief Description of LISTENER base class abstracting the audio support.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LISTENER_H
+#define LL_LISTENER_H
+
+#include "v3math.h"
+
+class LLListener
+{
+ private:
+ protected:
+ LLVector3 mPosition;
+ LLVector3 mVelocity;
+ LLVector3 mListenAt;
+ LLVector3 mListenUp;
+
+ public:
+
+ private:
+ protected:
+ public:
+ LLListener();
+ virtual ~LLListener();
+ virtual void init();
+
+ virtual void set(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at);
+
+ virtual void setPosition(LLVector3 pos);
+ virtual void setVelocity(LLVector3 vel);
+
+ virtual void orient(LLVector3 up, LLVector3 at);
+ virtual void translate(LLVector3 offset);
+
+ virtual void setDopplerFactor(F32 factor);
+ virtual void setRolloffFactor(F32 factor);
+
+ virtual LLVector3 getPosition();
+ virtual LLVector3 getAt();
+ virtual LLVector3 getUp();
+
+ virtual F32 getDopplerFactor();
+ virtual F32 getRolloffFactor();
+
+ virtual void commitDeferredChanges();
+};
+
+#endif
+
diff --git a/indra/llaudio/lllistener_ds3d.h b/indra/llaudio/lllistener_ds3d.h
new file mode 100644
index 0000000000..1ff9c170c4
--- /dev/null
+++ b/indra/llaudio/lllistener_ds3d.h
@@ -0,0 +1,74 @@
+/**
+ * @file listener_ds3d.h
+ * @brief Description of LISTENER class abstracting the audio support
+ * as a DirectSound 3D implementation (windows only)
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LISTENER_DS3D_H
+#define LL_LISTENER_DS3D_H
+
+#include "lllistener.h"
+
+#include <dmusici.h>
+#include <dsound.h>
+#include <ks.h>
+
+class LLListener_DS3D : public LLListener
+{
+ private:
+ protected:
+ IDirectSound3DListener8 *m3DListener;
+ public:
+
+ private:
+ protected:
+ public:
+ LLListener_DS3D();
+ virtual ~LLListener_DS3D();
+ virtual void init();
+
+ virtual void setDS3DLPtr (IDirectSound3DListener8 *listener_p);
+
+ virtual void translate(LLVector3 offset);
+ virtual void setPosition(LLVector3 pos);
+ virtual void setVelocity(LLVector3 vel);
+ virtual void orient(LLVector3 up, LLVector3 at);
+
+ virtual void setDopplerFactor(F32 factor);
+ virtual F32 getDopplerFactor();
+ virtual void setRolloffFactor(F32 factor);
+ virtual F32 getRolloffFactor();
+
+ virtual void commitDeferredChanges();
+};
+
+#endif
+
+
diff --git a/indra/llaudio/lllistener_fmod.cpp b/indra/llaudio/lllistener_fmod.cpp
new file mode 100644
index 0000000000..57ad461b02
--- /dev/null
+++ b/indra/llaudio/lllistener_fmod.cpp
@@ -0,0 +1,131 @@
+/**
+ * @file listener_fmod.cpp
+ * @brief implementation of LISTENER class abstracting the audio
+ * support as a FMOD 3D implementation (windows only)
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llaudioengine.h"
+#include "lllistener_fmod.h"
+#include "fmod.h"
+
+//-----------------------------------------------------------------------
+// constructor
+//-----------------------------------------------------------------------
+LLListener_FMOD::LLListener_FMOD()
+{
+ init();
+}
+
+//-----------------------------------------------------------------------
+LLListener_FMOD::~LLListener_FMOD()
+{
+}
+
+//-----------------------------------------------------------------------
+void LLListener_FMOD::init(void)
+{
+ // do inherited
+ LLListener::init();
+ mDopplerFactor = 1.0f;
+ mRolloffFactor = 1.0f;
+}
+
+//-----------------------------------------------------------------------
+void LLListener_FMOD::translate(LLVector3 offset)
+{
+ LLListener::translate(offset);
+
+ FSOUND_3D_Listener_SetAttributes(mPosition.mV, NULL, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]);
+}
+
+//-----------------------------------------------------------------------
+void LLListener_FMOD::setPosition(LLVector3 pos)
+{
+ LLListener::setPosition(pos);
+
+ FSOUND_3D_Listener_SetAttributes(pos.mV, NULL, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]);
+}
+
+//-----------------------------------------------------------------------
+void LLListener_FMOD::setVelocity(LLVector3 vel)
+{
+ LLListener::setVelocity(vel);
+
+ FSOUND_3D_Listener_SetAttributes(NULL, vel.mV, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]);
+}
+
+//-----------------------------------------------------------------------
+void LLListener_FMOD::orient(LLVector3 up, LLVector3 at)
+{
+ LLListener::orient(up, at);
+
+ // Welcome to the transition between right and left
+ // (coordinate systems, that is)
+ // Leaving the at vector alone results in a L/R reversal
+ // since DX is left-handed and we (LL, OpenGL, OpenAL) are right-handed
+ at = -at;
+
+ FSOUND_3D_Listener_SetAttributes(NULL, NULL, at.mV[0],at.mV[1],at.mV[2], up.mV[0],up.mV[1],up.mV[2]);
+}
+
+//-----------------------------------------------------------------------
+void LLListener_FMOD::commitDeferredChanges()
+{
+ FSOUND_Update();
+}
+
+
+void LLListener_FMOD::setRolloffFactor(F32 factor)
+{
+ mRolloffFactor = factor;
+ FSOUND_3D_SetRolloffFactor(factor);
+}
+
+
+F32 LLListener_FMOD::getRolloffFactor()
+{
+ return mRolloffFactor;
+}
+
+
+void LLListener_FMOD::setDopplerFactor(F32 factor)
+{
+ mDopplerFactor = factor;
+ FSOUND_3D_SetDopplerFactor(factor);
+}
+
+
+F32 LLListener_FMOD::getDopplerFactor()
+{
+ return mDopplerFactor;
+}
+
+
diff --git a/indra/llaudio/lllistener_fmod.h b/indra/llaudio/lllistener_fmod.h
new file mode 100644
index 0000000000..5a48ec8b68
--- /dev/null
+++ b/indra/llaudio/lllistener_fmod.h
@@ -0,0 +1,64 @@
+/**
+ * @file listener_fmod.h
+ * @brief Description of LISTENER class abstracting the audio support
+ * as an FMOD 3D implementation (windows and Linux)
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LISTENER_FMOD_H
+#define LL_LISTENER_FMOD_H
+
+#include "lllistener.h"
+
+class LLListener_FMOD : public LLListener
+{
+ public:
+ LLListener_FMOD();
+ virtual ~LLListener_FMOD();
+ virtual void init();
+
+ virtual void translate(LLVector3 offset);
+ virtual void setPosition(LLVector3 pos);
+ virtual void setVelocity(LLVector3 vel);
+ virtual void orient(LLVector3 up, LLVector3 at);
+ virtual void commitDeferredChanges();
+
+ virtual void setDopplerFactor(F32 factor);
+ virtual F32 getDopplerFactor();
+ virtual void setRolloffFactor(F32 factor);
+ virtual F32 getRolloffFactor();
+
+ protected:
+ F32 mDopplerFactor;
+ F32 mRolloffFactor;
+};
+
+#endif
+
+
diff --git a/indra/llaudio/lllistener_openal.cpp b/indra/llaudio/lllistener_openal.cpp
new file mode 100644
index 0000000000..a96ebd5dba
--- /dev/null
+++ b/indra/llaudio/lllistener_openal.cpp
@@ -0,0 +1,116 @@
+/**
+ * @file audioengine_openal.cpp
+ * @brief implementation of audio engine using OpenAL
+ * support as a OpenAL 3D implementation
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llaudioengine.h"
+
+#include "lllistener_openal.h"
+
+LLListener_OpenAL::LLListener_OpenAL()
+{
+ init();
+}
+
+LLListener_OpenAL::~LLListener_OpenAL()
+{
+}
+
+void LLListener_OpenAL::translate(LLVector3 offset)
+{
+ //llinfos << "LLListener_OpenAL::translate() : " << offset << llendl;
+ LLListener::translate(offset);
+}
+
+void LLListener_OpenAL::setPosition(LLVector3 pos)
+{
+ //llinfos << "LLListener_OpenAL::setPosition() : " << pos << llendl;
+ LLListener::setPosition(pos);
+}
+
+void LLListener_OpenAL::setVelocity(LLVector3 vel)
+{
+ LLListener::setVelocity(vel);
+}
+
+void LLListener_OpenAL::orient(LLVector3 up, LLVector3 at)
+{
+ //llinfos << "LLListener_OpenAL::orient() up: " << up << " at: " << at << llendl;
+ LLListener::orient(up, at);
+}
+
+void LLListener_OpenAL::commitDeferredChanges()
+{
+ ALfloat orientation[6];
+ orientation[0] = mListenAt.mV[0];
+ orientation[1] = mListenAt.mV[1];
+ orientation[2] = mListenAt.mV[2];
+ orientation[3] = mListenUp.mV[0];
+ orientation[4] = mListenUp.mV[1];
+ orientation[5] = mListenUp.mV[2];
+
+ ALfloat velocity[3];
+ velocity[0] = mVelocity.mV[0];
+ velocity[1] = mVelocity.mV[1];
+ velocity[2] = mVelocity.mV[2];
+
+ alListenerfv(AL_ORIENTATION, orientation);
+ alListenerfv(AL_POSITION, mPosition.mV);
+ alListenerfv(AL_VELOCITY, velocity);
+}
+
+void LLListener_OpenAL::setDopplerFactor(F32 factor)
+{
+ //llinfos << "LLListener_OpenAL::setDopplerFactor() : " << factor << llendl;
+ alDopplerFactor(factor);
+}
+
+F32 LLListener_OpenAL::getDopplerFactor()
+{
+ ALfloat factor;
+ factor = alGetFloat(AL_DOPPLER_FACTOR);
+ //llinfos << "LLListener_OpenAL::getDopplerFactor() : " << factor << llendl;
+ return factor;
+}
+
+
+void LLListener_OpenAL::setRolloffFactor(F32 factor)
+{
+ mRolloffFactor = factor;
+}
+
+F32 LLListener_OpenAL::getRolloffFactor()
+{
+ return mRolloffFactor;
+}
+
+
diff --git a/indra/llaudio/lllistener_openal.h b/indra/llaudio/lllistener_openal.h
new file mode 100644
index 0000000000..0dfeea5c90
--- /dev/null
+++ b/indra/llaudio/lllistener_openal.h
@@ -0,0 +1,64 @@
+/**
+ * @file listener_openal.h
+ * @brief Description of LISTENER class abstracting the audio support
+ * as an OpenAL implementation
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LISTENER_OPENAL_H
+#define LL_LISTENER_OPENAL_H
+
+#include "lllistener.h"
+
+#include "AL/al.h"
+#include "AL/alut.h"
+
+class LLListener_OpenAL : public LLListener
+{
+ public:
+ LLListener_OpenAL();
+ virtual ~LLListener_OpenAL();
+
+ virtual void translate(LLVector3 offset);
+ virtual void setPosition(LLVector3 pos);
+ virtual void setVelocity(LLVector3 vel);
+ virtual void orient(LLVector3 up, LLVector3 at);
+ virtual void commitDeferredChanges();
+
+ virtual void setDopplerFactor(F32 factor);
+ virtual F32 getDopplerFactor();
+ virtual void setRolloffFactor(F32 factor);
+ virtual F32 getRolloffFactor();
+
+ protected:
+ F32 mRolloffFactor;
+};
+
+#endif
+
diff --git a/indra/llaudio/llstreamingaudio.h b/indra/llaudio/llstreamingaudio.h
new file mode 100644
index 0000000000..aa89e6a177
--- /dev/null
+++ b/indra/llaudio/llstreamingaudio.h
@@ -0,0 +1,56 @@
+/**
+ * @file streamingaudio.h
+ * @author Tofu Linden
+ * @brief Definition of LLStreamingAudioInterface base class abstracting the streaming audio interface
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_STREAMINGAUDIO_H
+#define LL_STREAMINGAUDIO_H
+
+#include "stdtypes.h" // from llcommon
+
+// Entirely abstract. Based exactly on the historic API.
+class LLStreamingAudioInterface
+{
+ public:
+ virtual ~LLStreamingAudioInterface() {}
+
+ virtual void start(const std::string& url) = 0;
+ virtual void stop() = 0;
+ virtual void pause(int pause) = 0;
+ virtual void update() = 0;
+ virtual int isPlaying() = 0;
+ // use a value from 0.0 to 1.0, inclusive
+ virtual void setGain(F32 vol) = 0;
+ virtual F32 getGain() = 0;
+ virtual std::string getURL() = 0;
+};
+
+#endif // LL_STREAMINGAUDIO_H
diff --git a/indra/llaudio/llstreamingaudio_fmod.cpp b/indra/llaudio/llstreamingaudio_fmod.cpp
new file mode 100644
index 0000000000..a4620fa13c
--- /dev/null
+++ b/indra/llaudio/llstreamingaudio_fmod.cpp
@@ -0,0 +1,362 @@
+/**
+ * @file streamingaudio_fmod.cpp
+ * @brief LLStreamingAudio_FMOD implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llmath.h"
+
+#include "fmod.h"
+#include "fmod_errors.h"
+
+#include "llstreamingaudio_fmod.h"
+
+
+class LLAudioStreamManagerFMOD
+{
+public:
+ LLAudioStreamManagerFMOD(const std::string& url);
+ int startStream();
+ bool stopStream(); // Returns true if the stream was successfully stopped.
+ bool ready();
+
+ const std::string& getURL() { return mInternetStreamURL; }
+
+ int getOpenState();
+protected:
+ FSOUND_STREAM* mInternetStream;
+ bool mReady;
+
+ std::string mInternetStreamURL;
+};
+
+
+
+//---------------------------------------------------------------------------
+// Internet Streaming
+//---------------------------------------------------------------------------
+LLStreamingAudio_FMOD::LLStreamingAudio_FMOD() :
+ mCurrentInternetStreamp(NULL),
+ mFMODInternetStreamChannel(-1),
+ mGain(1.0f)
+{
+ // Number of milliseconds of audio to buffer for the audio card.
+ // Must be larger than the usual Second Life frame stutter time.
+ FSOUND_Stream_SetBufferSize(200);
+
+ // Here's where we set the size of the network buffer and some buffering
+ // parameters. In this case we want a network buffer of 16k, we want it
+ // to prebuffer 40% of that when we first connect, and we want it
+ // to rebuffer 80% of that whenever we encounter a buffer underrun.
+
+ // Leave the net buffer properties at the default.
+ //FSOUND_Stream_Net_SetBufferProperties(20000, 40, 80);
+}
+
+
+LLStreamingAudio_FMOD::~LLStreamingAudio_FMOD()
+{
+ // nothing interesting/safe to do.
+}
+
+
+void LLStreamingAudio_FMOD::start(const std::string& url)
+{
+ //if (!mInited)
+ //{
+ // llwarns << "startInternetStream before audio initialized" << llendl;
+ // return;
+ //}
+
+ // "stop" stream but don't clear url, etc. in case url == mInternetStreamURL
+ stop();
+
+ if (!url.empty())
+ {
+ llinfos << "Starting internet stream: " << url << llendl;
+ mCurrentInternetStreamp = new LLAudioStreamManagerFMOD(url);
+ mURL = url;
+ }
+ else
+ {
+ llinfos << "Set internet stream to null" << llendl;
+ mURL.clear();
+ }
+}
+
+
+void LLStreamingAudio_FMOD::update()
+{
+ // Kill dead internet streams, if possible
+ std::list<LLAudioStreamManagerFMOD *>::iterator iter;
+ for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
+ {
+ LLAudioStreamManagerFMOD *streamp = *iter;
+ if (streamp->stopStream())
+ {
+ llinfos << "Closed dead stream" << llendl;
+ delete streamp;
+ mDeadStreams.erase(iter++);
+ }
+ else
+ {
+ iter++;
+ }
+ }
+
+ // Don't do anything if there are no streams playing
+ if (!mCurrentInternetStreamp)
+ {
+ return;
+ }
+
+ int open_state = mCurrentInternetStreamp->getOpenState();
+
+ if (!open_state)
+ {
+ // Stream is live
+
+ // start the stream if it's ready
+ if (mFMODInternetStreamChannel < 0)
+ {
+ mFMODInternetStreamChannel = mCurrentInternetStreamp->startStream();
+
+ if (mFMODInternetStreamChannel != -1)
+ {
+ // Reset volume to previously set volume
+ setGain(getGain());
+ FSOUND_SetPaused(mFMODInternetStreamChannel, false);
+ }
+ }
+ }
+
+ switch(open_state)
+ {
+ default:
+ case 0:
+ // success
+ break;
+ case -1:
+ // stream handle is invalid
+ llwarns << "InternetStream - invalid handle" << llendl;
+ stop();
+ return;
+ case -2:
+ // opening
+ break;
+ case -3:
+ // failed to open, file not found, perhaps
+ llwarns << "InternetStream - failed to open" << llendl;
+ stop();
+ return;
+ case -4:
+ // connecting
+ break;
+ case -5:
+ // buffering
+ break;
+ }
+
+}
+
+void LLStreamingAudio_FMOD::stop()
+{
+ if (mFMODInternetStreamChannel != -1)
+ {
+ FSOUND_SetPaused(mFMODInternetStreamChannel, true);
+ FSOUND_SetPriority(mFMODInternetStreamChannel, 0);
+ mFMODInternetStreamChannel = -1;
+ }
+
+ if (mCurrentInternetStreamp)
+ {
+ llinfos << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << llendl;
+ if (mCurrentInternetStreamp->stopStream())
+ {
+ delete mCurrentInternetStreamp;
+ }
+ else
+ {
+ llwarns << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << llendl;
+ mDeadStreams.push_back(mCurrentInternetStreamp);
+ }
+ mCurrentInternetStreamp = NULL;
+ //mURL.clear();
+ }
+}
+
+void LLStreamingAudio_FMOD::pause(int pauseopt)
+{
+ if (pauseopt < 0)
+ {
+ pauseopt = mCurrentInternetStreamp ? 1 : 0;
+ }
+
+ if (pauseopt)
+ {
+ if (mCurrentInternetStreamp)
+ {
+ stop();
+ }
+ }
+ else
+ {
+ start(getURL());
+ }
+}
+
+
+// A stream is "playing" if it has been requested to start. That
+// doesn't necessarily mean audio is coming out of the speakers.
+int LLStreamingAudio_FMOD::isPlaying()
+{
+ if (mCurrentInternetStreamp)
+ {
+ return 1; // Active and playing
+ }
+ else if (!mURL.empty())
+ {
+ return 2; // "Paused"
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+F32 LLStreamingAudio_FMOD::getGain()
+{
+ return mGain;
+}
+
+
+std::string LLStreamingAudio_FMOD::getURL()
+{
+ return mURL;
+}
+
+
+void LLStreamingAudio_FMOD::setGain(F32 vol)
+{
+ mGain = vol;
+
+ if (mFMODInternetStreamChannel != -1)
+ {
+ vol = llclamp(vol, 0.f, 1.f);
+ int vol_int = llround(vol * 255.f);
+ FSOUND_SetVolumeAbsolute(mFMODInternetStreamChannel, vol_int);
+ }
+}
+
+
+///////////////////////////////////////////////////////
+// manager of possibly-multiple internet audio streams
+
+LLAudioStreamManagerFMOD::LLAudioStreamManagerFMOD(const std::string& url) :
+ mInternetStream(NULL),
+ mReady(false)
+{
+ mInternetStreamURL = url;
+ mInternetStream = FSOUND_Stream_Open(url.c_str(), FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0);
+ if (!mInternetStream)
+ {
+ llwarns << "Couldn't open fmod stream, error "
+ << FMOD_ErrorString(FSOUND_GetError())
+ << llendl;
+ mReady = false;
+ return;
+ }
+
+ mReady = true;
+}
+
+int LLAudioStreamManagerFMOD::startStream()
+{
+ // We need a live and opened stream before we try and play it.
+ if (!mInternetStream || getOpenState())
+ {
+ llwarns << "No internet stream to start playing!" << llendl;
+ return -1;
+ }
+
+ // Make sure the stream is set to 2D mode.
+ FSOUND_Stream_SetMode(mInternetStream, FSOUND_2D);
+
+ return FSOUND_Stream_PlayEx(FSOUND_FREE, mInternetStream, NULL, true);
+}
+
+bool LLAudioStreamManagerFMOD::stopStream()
+{
+ if (mInternetStream)
+ {
+ int read_percent = 0;
+ int status = 0;
+ int bitrate = 0;
+ unsigned int flags = 0x0;
+ FSOUND_Stream_Net_GetStatus(mInternetStream, &status, &read_percent, &bitrate, &flags);
+
+ bool close = true;
+ switch (status)
+ {
+ case FSOUND_STREAM_NET_CONNECTING:
+ close = false;
+ break;
+ case FSOUND_STREAM_NET_NOTCONNECTED:
+ case FSOUND_STREAM_NET_BUFFERING:
+ case FSOUND_STREAM_NET_READY:
+ case FSOUND_STREAM_NET_ERROR:
+ default:
+ close = true;
+ }
+
+ if (close)
+ {
+ FSOUND_Stream_Close(mInternetStream);
+ mInternetStream = NULL;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return true;
+ }
+}
+
+int LLAudioStreamManagerFMOD::getOpenState()
+{
+ int open_state = FSOUND_Stream_GetOpenState(mInternetStream);
+ return open_state;
+}
diff --git a/indra/llaudio/llstreamingaudio_fmod.h b/indra/llaudio/llstreamingaudio_fmod.h
new file mode 100644
index 0000000000..968ab53a0b
--- /dev/null
+++ b/indra/llaudio/llstreamingaudio_fmod.h
@@ -0,0 +1,68 @@
+/**
+ * @file streamingaudio_fmod.h
+ * @author Tofu Linden
+ * @brief Definition of LLStreamingAudio_FMOD implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_STREAMINGAUDIO_FMOD_H
+#define LL_STREAMINGAUDIO_FMOD_H
+
+#include "stdtypes.h" // from llcommon
+
+#include "llstreamingaudio.h"
+
+class LLAudioStreamManagerFMOD;
+
+class LLStreamingAudio_FMOD : public LLStreamingAudioInterface
+{
+ public:
+ LLStreamingAudio_FMOD();
+ /*virtual*/ ~LLStreamingAudio_FMOD();
+
+ /*virtual*/ void start(const std::string& url);
+ /*virtual*/ void stop();
+ /*virtual*/ void pause(int pause);
+ /*virtual*/ void update();
+ /*virtual*/ int isPlaying();
+ /*virtual*/ void setGain(F32 vol);
+ /*virtual*/ F32 getGain();
+ /*virtual*/ std::string getURL();
+
+private:
+ LLAudioStreamManagerFMOD *mCurrentInternetStreamp;
+ int mFMODInternetStreamChannel;
+ std::list<LLAudioStreamManagerFMOD *> mDeadStreams;
+
+ std::string mURL;
+ F32 mGain;
+};
+
+
+#endif // LL_STREAMINGAUDIO_FMOD_H
diff --git a/indra/llaudio/llvorbisencode.cpp b/indra/llaudio/llvorbisencode.cpp
new file mode 100644
index 0000000000..0c1ad8191c
--- /dev/null
+++ b/indra/llaudio/llvorbisencode.cpp
@@ -0,0 +1,505 @@
+/**
+ * @file vorbisencode.cpp
+ * @brief Vorbis encoding routine routine for Indra.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "vorbis/vorbisenc.h"
+
+#include "llvorbisencode.h"
+#include "llerror.h"
+#include "llrand.h"
+#include "llmath.h"
+#include "llapr.h"
+
+//#if LL_DARWIN
+// MBW -- XXX -- Getting rid of SecondLifeVorbis for now -- no fmod means no name collisions.
+#if 0
+#include "VorbisFramework.h"
+
+#define vorbis_analysis mac_vorbis_analysis
+#define vorbis_analysis_headerout mac_vorbis_analysis_headerout
+#define vorbis_analysis_init mac_vorbis_analysis_init
+#define vorbis_encode_ctl mac_vorbis_encode_ctl
+#define vorbis_encode_setup_init mac_vorbis_encode_setup_init
+#define vorbis_encode_setup_managed mac_vorbis_encode_setup_managed
+
+#define vorbis_info_init mac_vorbis_info_init
+#define vorbis_info_clear mac_vorbis_info_clear
+#define vorbis_comment_init mac_vorbis_comment_init
+#define vorbis_comment_clear mac_vorbis_comment_clear
+#define vorbis_block_init mac_vorbis_block_init
+#define vorbis_block_clear mac_vorbis_block_clear
+#define vorbis_dsp_clear mac_vorbis_dsp_clear
+#define vorbis_analysis_buffer mac_vorbis_analysis_buffer
+#define vorbis_analysis_wrote mac_vorbis_analysis_wrote
+#define vorbis_analysis_blockout mac_vorbis_analysis_blockout
+
+#define ogg_stream_packetin mac_ogg_stream_packetin
+#define ogg_stream_init mac_ogg_stream_init
+#define ogg_stream_flush mac_ogg_stream_flush
+#define ogg_stream_pageout mac_ogg_stream_pageout
+#define ogg_page_eos mac_ogg_page_eos
+#define ogg_stream_clear mac_ogg_stream_clear
+
+#endif
+
+S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& error_msg)
+{
+ U16 num_channels = 0;
+ U32 sample_rate = 0;
+ U32 bits_per_sample = 0;
+ U32 physical_file_size = 0;
+ U32 chunk_length = 0;
+ U32 raw_data_length = 0;
+ U32 bytes_per_sec = 0;
+ BOOL uncompressed_pcm = FALSE;
+
+ unsigned char wav_header[44]; /*Flawfinder: ignore*/
+
+ error_msg.clear();
+
+ //********************************
+ LLAPRFile infile ;
+ infile.open(in_fname,LL_APR_RB);
+ //********************************
+ if (!infile.getFileHandle())
+ {
+ error_msg = "CannotUploadSoundFile";
+ return(LLVORBISENC_SOURCE_OPEN_ERR);
+ }
+
+ infile.read(wav_header, 44);
+ physical_file_size = infile.seek(APR_END,0);
+
+ if (strncmp((char *)&(wav_header[0]),"RIFF",4))
+ {
+ error_msg = "SoundFileNotRIFF";
+ return(LLVORBISENC_WAV_FORMAT_ERR);
+ }
+
+ if (strncmp((char *)&(wav_header[8]),"WAVE",4))
+ {
+ error_msg = "SoundFileNotRIFF";
+ return(LLVORBISENC_WAV_FORMAT_ERR);
+ }
+
+ // parse the chunks
+
+ U32 file_pos = 12; // start at the first chunk (usually fmt but not always)
+
+ while ((file_pos + 8)< physical_file_size)
+ {
+ infile.seek(APR_SET,file_pos);
+ infile.read(wav_header, 44);
+
+ chunk_length = ((U32) wav_header[7] << 24)
+ + ((U32) wav_header[6] << 16)
+ + ((U32) wav_header[5] << 8)
+ + wav_header[4];
+
+// llinfos << "chunk found: '" << wav_header[0] << wav_header[1] << wav_header[2] << wav_header[3] << "'" << llendl;
+
+ if (!(strncmp((char *)&(wav_header[0]),"fmt ",4)))
+ {
+ if ((wav_header[8] == 0x01) && (wav_header[9] == 0x00))
+ {
+ uncompressed_pcm = TRUE;
+ }
+ num_channels = ((U16) wav_header[11] << 8) + wav_header[10];
+ sample_rate = ((U32) wav_header[15] << 24)
+ + ((U32) wav_header[14] << 16)
+ + ((U32) wav_header[13] << 8)
+ + wav_header[12];
+ bits_per_sample = ((U16) wav_header[23] << 8) + wav_header[22];
+ bytes_per_sec = ((U32) wav_header[19] << 24)
+ + ((U32) wav_header[18] << 16)
+ + ((U32) wav_header[17] << 8)
+ + wav_header[16];
+ }
+ else if (!(strncmp((char *)&(wav_header[0]),"data",4)))
+ {
+ raw_data_length = chunk_length;
+ }
+ file_pos += (chunk_length + 8);
+ chunk_length = 0;
+ }
+ //****************
+ infile.close();
+ //****************
+
+ if (!uncompressed_pcm)
+ {
+ error_msg = "SoundFileNotPCM";
+ return(LLVORBISENC_PCM_FORMAT_ERR);
+ }
+
+ if ((num_channels < 1) || (num_channels > LLVORBIS_CLIP_MAX_CHANNELS))
+ {
+ error_msg = "SoundFileInvalidChannelCount";
+ return(LLVORBISENC_MULTICHANNEL_ERR);
+ }
+
+ if (sample_rate != LLVORBIS_CLIP_SAMPLE_RATE)
+ {
+ error_msg = "SoundFileInvalidSampleRate";
+ return(LLVORBISENC_UNSUPPORTED_SAMPLE_RATE);
+ }
+
+ if ((bits_per_sample != 16) && (bits_per_sample != 8))
+ {
+ error_msg = "SoundFileInvalidWordSize";
+ return(LLVORBISENC_UNSUPPORTED_WORD_SIZE);
+ }
+
+ if (!raw_data_length)
+ {
+ error_msg = "SoundFileInvalidHeader";
+ return(LLVORBISENC_CLIP_TOO_LONG);
+ }
+
+ F32 clip_length = (F32)raw_data_length/(F32)bytes_per_sec;
+
+ if (clip_length > LLVORBIS_CLIP_MAX_TIME)
+ {
+ error_msg = "SoundFileInvalidTooLong";
+ return(LLVORBISENC_CLIP_TOO_LONG);
+ }
+
+ return(LLVORBISENC_NOERR);
+}
+
+S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname)
+{
+#define READ_BUFFER 1024
+ unsigned char readbuffer[READ_BUFFER*4+44]; /* out of the data segment, not the stack */ /*Flawfinder: ignore*/
+
+ ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */
+ ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */
+ ogg_packet op; /* one raw packet of data for decode */
+
+ vorbis_info vi; /* struct that stores all the static vorbis bitstream settings */
+ vorbis_comment vc; /* struct that stores all the user comments */
+
+ vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
+ vorbis_block vb; /* local working space for packet->PCM decode */
+
+ int eos=0;
+ int result;
+
+ U16 num_channels = 0;
+ U32 sample_rate = 0;
+ U32 bits_per_sample = 0;
+
+ S32 format_error = 0;
+ std::string error_msg;
+ if ((format_error = check_for_invalid_wav_formats(in_fname, error_msg)))
+ {
+ llwarns << error_msg << ": " << in_fname << llendl;
+ return(format_error);
+ }
+
+#if 1
+ unsigned char wav_header[44]; /*Flawfinder: ignore*/
+
+ S32 data_left = 0;
+
+ LLAPRFile infile ;
+ infile.open(in_fname,LL_APR_RB);
+ if (!infile.getFileHandle())
+ {
+ llwarns << "Couldn't open temporary ogg file for writing: " << in_fname
+ << llendl;
+ return(LLVORBISENC_SOURCE_OPEN_ERR);
+ }
+
+ LLAPRFile outfile ;
+ outfile.open(out_fname,LL_APR_WPB);
+ if (!outfile.getFileHandle())
+ {
+ llwarns << "Couldn't open upload sound file for reading: " << in_fname
+ << llendl;
+ return(LLVORBISENC_DEST_OPEN_ERR);
+ }
+
+ // parse the chunks
+ U32 chunk_length = 0;
+ U32 file_pos = 12; // start at the first chunk (usually fmt but not always)
+
+ while (infile.eof() != APR_EOF)
+ {
+ infile.seek(APR_SET,file_pos);
+ infile.read(wav_header, 44);
+
+ chunk_length = ((U32) wav_header[7] << 24)
+ + ((U32) wav_header[6] << 16)
+ + ((U32) wav_header[5] << 8)
+ + wav_header[4];
+
+// llinfos << "chunk found: '" << wav_header[0] << wav_header[1] << wav_header[2] << wav_header[3] << "'" << llendl;
+
+ if (!(strncmp((char *)&(wav_header[0]),"fmt ",4)))
+ {
+ num_channels = ((U16) wav_header[11] << 8) + wav_header[10];
+ sample_rate = ((U32) wav_header[15] << 24)
+ + ((U32) wav_header[14] << 16)
+ + ((U32) wav_header[13] << 8)
+ + wav_header[12];
+ bits_per_sample = ((U16) wav_header[23] << 8) + wav_header[22];
+ }
+ else if (!(strncmp((char *)&(wav_header[0]),"data",4)))
+ {
+ infile.seek(APR_SET,file_pos+8);
+ // leave the file pointer at the beginning of the data chunk data
+ data_left = chunk_length;
+ break;
+ }
+ file_pos += (chunk_length + 8);
+ chunk_length = 0;
+ }
+
+
+ /********** Encode setup ************/
+
+ /* choose an encoding mode */
+ /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
+ vorbis_info_init(&vi);
+
+ // always encode to mono
+
+ // SL-52913 & SL-53779 determined this quality level to be our 'good
+ // enough' general-purpose quality level with a nice low bitrate.
+ // Equivalent to oggenc -q0.5
+ F32 quality = 0.05f;
+// quality = (bitrate==128000 ? 0.4f : 0.1);
+
+// if (vorbis_encode_init(&vi, /* num_channels */ 1 ,sample_rate, -1, bitrate, -1))
+ if (vorbis_encode_init_vbr(&vi, /* num_channels */ 1 ,sample_rate, quality))
+// if (vorbis_encode_setup_managed(&vi,1,sample_rate,-1,bitrate,-1) ||
+// vorbis_encode_ctl(&vi,OV_ECTL_RATEMANAGE_AVG,NULL) ||
+// vorbis_encode_setup_init(&vi))
+ {
+ llwarns << "unable to initialize vorbis codec at quality " << quality << llendl;
+ // llwarns << "unable to initialize vorbis codec at bitrate " << bitrate << llendl;
+ return(LLVORBISENC_DEST_OPEN_ERR);
+ }
+
+ /* add a comment */
+ vorbis_comment_init(&vc);
+// vorbis_comment_add(&vc,"Linden");
+
+ /* set up the analysis state and auxiliary encoding storage */
+ vorbis_analysis_init(&vd,&vi);
+ vorbis_block_init(&vd,&vb);
+
+ /* set up our packet->stream encoder */
+ /* pick a random serial number; that way we can more likely build
+ chained streams just by concatenation */
+ ogg_stream_init(&os, ll_rand());
+
+ /* Vorbis streams begin with three headers; the initial header (with
+ most of the codec setup parameters) which is mandated by the Ogg
+ bitstream spec. The second header holds any comment fields. The
+ third header holds the bitstream codebook. We merely need to
+ make the headers, then pass them to libvorbis one at a time;
+ libvorbis handles the additional Ogg bitstream constraints */
+
+ {
+ ogg_packet header;
+ ogg_packet header_comm;
+ ogg_packet header_code;
+
+ vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code);
+ ogg_stream_packetin(&os,&header); /* automatically placed in its own
+ page */
+ ogg_stream_packetin(&os,&header_comm);
+ ogg_stream_packetin(&os,&header_code);
+
+ /* We don't have to write out here, but doing so makes streaming
+ * much easier, so we do, flushing ALL pages. This ensures the actual
+ * audio data will start on a new page
+ */
+ while(!eos){
+ int result=ogg_stream_flush(&os,&og);
+ if(result==0)break;
+ outfile.write(og.header, og.header_len);
+ outfile.write(og.body, og.body_len);
+ }
+
+ }
+
+
+ while(!eos)
+ {
+ long bytes_per_sample = bits_per_sample/8;
+
+ long bytes=(long)infile.read(readbuffer,llclamp((S32)(READ_BUFFER*num_channels*bytes_per_sample),0,data_left)); /* stereo hardwired here */
+
+ if (bytes==0)
+ {
+ /* end of file. this can be done implicitly in the mainline,
+ but it's easier to see here in non-clever fashion.
+ Tell the library we're at end of stream so that it can handle
+ the last frame and mark end of stream in the output properly */
+
+ vorbis_analysis_wrote(&vd,0);
+// eos = 1;
+
+ }
+ else
+ {
+ long i;
+ long samples;
+ int temp;
+
+ data_left -= bytes;
+ /* data to encode */
+
+ /* expose the buffer to submit data */
+ float **buffer=vorbis_analysis_buffer(&vd,READ_BUFFER);
+
+ i = 0;
+ samples = bytes / (num_channels * bytes_per_sample);
+
+ if (num_channels == 2)
+ {
+ if (bytes_per_sample == 2)
+ {
+ /* uninterleave samples */
+ for(i=0; i<samples ;i++)
+ {
+ temp = ((signed char *)readbuffer)[i*4+1]; /*Flawfinder: ignore*/
+ temp += ((signed char *)readbuffer)[i*4+3]; /*Flawfinder: ignore*/
+ temp <<= 8;
+ temp += readbuffer[i*4];
+ temp += readbuffer[i*4+2];
+
+ buffer[0][i] = ((float)temp) / 65536.f;
+ }
+ }
+ else // presume it's 1 byte per which is unsigned (F#@%ing wav "standard")
+ {
+ /* uninterleave samples */
+ for(i=0; i<samples ;i++)
+ {
+ temp = readbuffer[i*2+0];
+ temp += readbuffer[i*2+1];
+ temp -= 256;
+ buffer[0][i] = ((float)temp) / 256.f;
+ }
+ }
+ }
+ else if (num_channels == 1)
+ {
+ if (bytes_per_sample == 2)
+ {
+ for(i=0; i < samples ;i++)
+ {
+ temp = ((signed char*)readbuffer)[i*2+1];
+ temp <<= 8;
+ temp += readbuffer[i*2];
+ buffer[0][i] = ((float)temp) / 32768.f;
+ }
+ }
+ else // presume it's 1 byte per which is unsigned (F#@%ing wav "standard")
+ {
+ for(i=0; i < samples ;i++)
+ {
+ temp = readbuffer[i];
+ temp -= 128;
+ buffer[0][i] = ((float)temp) / 128.f;
+ }
+ }
+ }
+
+ /* tell the library how much we actually submitted */
+ vorbis_analysis_wrote(&vd,i);
+ }
+
+ /* vorbis does some data preanalysis, then divvies up blocks for
+ more involved (potentially parallel) processing. Get a single
+ block for encoding now */
+ while(vorbis_analysis_blockout(&vd,&vb)==1)
+ {
+
+ /* analysis */
+ /* Do the main analysis, creating a packet */
+ vorbis_analysis(&vb, NULL);
+ vorbis_bitrate_addblock(&vb);
+
+ while(vorbis_bitrate_flushpacket(&vd, &op))
+ {
+
+ /* weld the packet into the bitstream */
+ ogg_stream_packetin(&os,&op);
+
+ /* write out pages (if any) */
+ while(!eos)
+ {
+ result = ogg_stream_pageout(&os,&og);
+
+ if(result==0)
+ break;
+
+ outfile.write(og.header, og.header_len);
+ outfile.write(og.body, og.body_len);
+
+ /* this could be set above, but for illustrative purposes, I do
+ it here (to show that vorbis does know where the stream ends) */
+
+ if(ogg_page_eos(&og))
+ eos=1;
+
+ }
+ }
+ }
+ }
+
+
+
+ /* clean up and exit. vorbis_info_clear() must be called last */
+
+ ogg_stream_clear(&os);
+ vorbis_block_clear(&vb);
+ vorbis_dsp_clear(&vd);
+ vorbis_comment_clear(&vc);
+ vorbis_info_clear(&vi);
+
+ /* ogg_page and ogg_packet structs always point to storage in
+ libvorbis. They're never freed or manipulated directly */
+
+// fprintf(stderr,"Vorbis encoding: Done.\n");
+ llinfos << "Vorbis encoding: Done." << llendl;
+
+#endif
+ return(LLVORBISENC_NOERR);
+
+}
diff --git a/indra/llaudio/llvorbisencode.h b/indra/llaudio/llvorbisencode.h
new file mode 100644
index 0000000000..6531c1919e
--- /dev/null
+++ b/indra/llaudio/llvorbisencode.h
@@ -0,0 +1,64 @@
+/**
+ * @file vorbisencode.h
+ * @brief Vorbis encoding routine routine for Indra.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_VORBISENCODE_H
+#define LL_VORBISENCODE_H
+
+const S32 LLVORBISENC_NOERR = 0; // no error
+const S32 LLVORBISENC_SOURCE_OPEN_ERR = 1; // error opening source
+const S32 LLVORBISENC_DEST_OPEN_ERR = 2; // error opening destination
+const S32 LLVORBISENC_WAV_FORMAT_ERR = 3; // not a WAV
+const S32 LLVORBISENC_PCM_FORMAT_ERR = 4; // not a PCM
+const S32 LLVORBISENC_MONO_ERR = 5; // can't do mono
+const S32 LLVORBISENC_STEREO_ERR = 6; // can't do stereo
+const S32 LLVORBISENC_MULTICHANNEL_ERR = 7; // can't do stereo
+const S32 LLVORBISENC_UNSUPPORTED_SAMPLE_RATE = 8; // unsupported sample rate
+const S32 LLVORBISENC_UNSUPPORTED_WORD_SIZE = 9; // unsupported word size
+const S32 LLVORBISENC_CLIP_TOO_LONG = 10; // source file is too long
+
+const F32 LLVORBIS_CLIP_MAX_TIME = 10.0f;
+const U8 LLVORBIS_CLIP_MAX_CHANNELS = 2;
+const U32 LLVORBIS_CLIP_SAMPLE_RATE = 44100;
+const U32 LLVORBIS_CLIP_MAX_SAMPLES_PER_CHANNEL = (U32)(LLVORBIS_CLIP_MAX_TIME * LLVORBIS_CLIP_SAMPLE_RATE);
+const U32 LLVORBIS_CLIP_MAX_SAMPLES = LLVORBIS_CLIP_MAX_SAMPLES_PER_CHANNEL * LLVORBIS_CLIP_MAX_CHANNELS;
+const size_t LLVORBIS_CLIP_MAX_SAMPLE_DATA = LLVORBIS_CLIP_MAX_SAMPLES * 2; // 2 = 16-bit
+
+// Treat anything this long as a bad asset. A little fudge factor at the end:
+// Make that a lot of fudge factor. We're allowing 30 sec for now - 3x legal upload
+const size_t LLVORBIS_CLIP_REJECT_SAMPLES = LLVORBIS_CLIP_MAX_SAMPLES * 3;
+const size_t LLVORBIS_CLIP_REJECT_SIZE = LLVORBIS_CLIP_MAX_SAMPLE_DATA * 3;
+
+S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& error_msg);
+S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname);
+
+#endif
+
diff --git a/indra/llaudio/llwindgen.h b/indra/llaudio/llwindgen.h
new file mode 100644
index 0000000000..847bfa6e9d
--- /dev/null
+++ b/indra/llaudio/llwindgen.h
@@ -0,0 +1,136 @@
+/**
+ * @file windgen.h
+ * @brief Templated wind noise generation
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef WINDGEN_H
+#define WINDGEN_H
+
+#include "llcommon.h"
+#include "llrand.h"
+
+template <class MIXBUFFERFORMAT_T>
+class LLWindGen
+{
+public:
+ LLWindGen() :
+ mTargetGain(0.f),
+ mTargetFreq(100.f),
+ mTargetPanGainR(0.5f),
+ mbuf0(0.0),
+ mbuf1(0.0),
+ mbuf2(0.0),
+ mbuf3(0.0),
+ mbuf4(0.0),
+ mbuf5(0.0),
+ mY0(0.0),
+ mY1(0.0),
+ mCurrentGain(0.f),
+ mCurrentFreq(100.f),
+ mCurrentPanGainR(0.5f) {};
+
+ static const U32 getInputSamplingRate() {return mInputSamplingRate;}
+
+ // newbuffer = the buffer passed from the previous DSP unit.
+ // numsamples = length in samples-per-channel at this mix time.
+ // stride = number of bytes between start of each sample.
+ // NOTE: generates L/R interleaved stereo
+ MIXBUFFERFORMAT_T* windGenerate(MIXBUFFERFORMAT_T *newbuffer, int numsamples, int stride)
+ {
+ U8 *cursamplep = (U8*)newbuffer;
+
+ double bandwidth = 50.0F;
+ double a0,b1,b2;
+
+ // calculate resonant filter coeffs
+ b2 = exp(-(F_TWO_PI) * (bandwidth / mInputSamplingRate));
+
+ while (numsamples--)
+ {
+ mCurrentFreq = (float)((0.999 * mCurrentFreq) + (0.001 * mTargetFreq));
+ mCurrentGain = (float)((0.999 * mCurrentGain) + (0.001 * mTargetGain));
+ mCurrentPanGainR = (float)((0.999 * mCurrentPanGainR) + (0.001 * mTargetPanGainR));
+ b1 = (-4.0 * b2) / (1.0 + b2) * cos(F_TWO_PI * (mCurrentFreq / mInputSamplingRate));
+ a0 = (1.0 - b2) * sqrt(1.0 - (b1 * b1) / (4.0 * b2));
+ double nextSample;
+
+ // start with white noise
+ nextSample = ll_frand(2.0f) - 1.0f;
+
+ // apply pinking filter
+ mbuf0 = 0.997f * mbuf0 + 0.0126502f * nextSample;
+ mbuf1 = 0.985f * mbuf1 + 0.0139083f * nextSample;
+ mbuf2 = 0.950f * mbuf2 + 0.0205439f * nextSample;
+ mbuf3 = 0.850f * mbuf3 + 0.0387225f * nextSample;
+ mbuf4 = 0.620f * mbuf4 + 0.0465932f * nextSample;
+ mbuf5 = 0.250f * mbuf5 + 0.1093477f * nextSample;
+
+ nextSample = mbuf0 + mbuf1 + mbuf2 + mbuf3 + mbuf4 + mbuf5;
+
+ // do a resonant filter on the noise
+ nextSample = (double)( a0 * nextSample - b1 * mY0 - b2 * mY1 );
+ mY1 = mY0;
+ mY0 = nextSample;
+
+ nextSample *= mCurrentGain;
+
+ MIXBUFFERFORMAT_T sample;
+
+ sample = llfloor(((F32)nextSample*32768.f*(1.0f - mCurrentPanGainR))+0.5f);
+ *(MIXBUFFERFORMAT_T*)cursamplep = llclamp(sample, (MIXBUFFERFORMAT_T)-32768, (MIXBUFFERFORMAT_T)32767);
+ cursamplep += stride;
+
+ sample = llfloor(((F32)nextSample*32768.f*mCurrentPanGainR)+0.5f);
+ *(MIXBUFFERFORMAT_T*)cursamplep = llclamp(sample, (MIXBUFFERFORMAT_T)-32768, (MIXBUFFERFORMAT_T)32767);
+ cursamplep += stride;
+ }
+
+ return newbuffer;
+ }
+
+ F32 mTargetGain;
+ F32 mTargetFreq;
+ F32 mTargetPanGainR;
+
+private:
+ static const U32 mInputSamplingRate = 44100;
+ F64 mbuf0;
+ F64 mbuf1;
+ F64 mbuf2;
+ F64 mbuf3;
+ F64 mbuf4;
+ F64 mbuf5;
+ F64 mY0;
+ F64 mY1;
+ F32 mCurrentGain;
+ F32 mCurrentFreq;
+ F32 mCurrentPanGainR;
+};
+
+#endif
diff --git a/indra/llcharacter/CMakeLists.txt b/indra/llcharacter/CMakeLists.txt
index 612229d16b..85e3f97092 100644
--- a/indra/llcharacter/CMakeLists.txt
+++ b/indra/llcharacter/CMakeLists.txt
@@ -75,3 +75,13 @@ set_source_files_properties(${llcharacter_HEADER_FILES}
list(APPEND llcharacter_SOURCE_FILES ${llcharacter_HEADER_FILES})
add_library (llcharacter ${llcharacter_SOURCE_FILES})
+
+
+# Add tests
+include(LLAddBuildTest)
+# UNIT TESTS
+SET(llcharacter_TEST_SOURCE_FILES
+ lljoint.cpp
+ )
+LL_ADD_PROJECT_UNIT_TESTS(llcharacter "${llcharacter_TEST_SOURCE_FILES}")
+
diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp
index e1f8ce53fb..3dd54b4760 100644
--- a/indra/llcharacter/llbvhloader.cpp
+++ b/indra/llcharacter/llbvhloader.cpp
@@ -56,7 +56,7 @@ const F32 ROTATION_MOTION_THRESHOLD = 0.001f;
char gInFile[1024]; /* Flawfinder: ignore */
char gOutFile[1024]; /* Flawfinder: ignore */
-
+/*
//------------------------------------------------------------------------
// Status Codes
//------------------------------------------------------------------------
@@ -91,6 +91,8 @@ const char *LLBVHLoader::ST_NO_XLT_EASEIN = "Can't get easeIn values.";
const char *LLBVHLoader::ST_NO_XLT_EASEOUT = "Can't get easeOut values.";
const char *LLBVHLoader::ST_NO_XLT_HAND = "Can't get hand morph value.";
const char *LLBVHLoader::ST_NO_XLT_EMOTE = "Can't read emote name.";
+const char *LLBVHLoader::ST_BAD_ROOT = "Illegal ROOT joint.";
+*/
//------------------------------------------------------------------------
// find_next_whitespace()
@@ -124,7 +126,9 @@ LLQuaternion::Order bvhStringToOrder( char *str )
//-----------------------------------------------------------------------------
// LLBVHLoader()
//-----------------------------------------------------------------------------
-LLBVHLoader::LLBVHLoader(const char* buffer)
+
+/*
+ LLBVHLoader::LLBVHLoader(const char* buffer)
{
reset();
@@ -144,7 +148,7 @@ LLBVHLoader::LLBVHLoader(const char* buffer)
}
}
- char error_text[128]; /* Flawfinder: ignore */
+ char error_text[128]; // Flawfinder: ignore
S32 error_line;
mStatus = loadBVHFile(buffer, error_text, error_line);
if (mStatus != LLBVHLoader::ST_OK)
@@ -158,6 +162,49 @@ LLBVHLoader::LLBVHLoader(const char* buffer)
mInitialized = TRUE;
}
+*/
+LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine)
+{
+ reset();
+ errorLine = 0;
+ mStatus = loadTranslationTable("anim.ini");
+ loadStatus = mStatus;
+ llinfos<<"Load Status 00 : "<< loadStatus << llendl;
+ if (mStatus == E_ST_NO_XLT_FILE)
+ {
+ //llwarns << "NOTE: No translation table found." << llendl;
+ loadStatus = mStatus;
+ return;
+ }
+ else
+ {
+ if (mStatus != E_ST_OK)
+ {
+ //llwarns << "ERROR: [line: " << getLineNumber() << "] " << mStatus << llendl;
+ errorLine = getLineNumber();
+ loadStatus = mStatus;
+ return;
+ }
+ }
+
+ char error_text[128]; /* Flawfinder: ignore */
+ S32 error_line;
+ mStatus = loadBVHFile(buffer, error_text, error_line);
+
+ if (mStatus != E_ST_OK)
+ {
+ //llwarns << "ERROR: [line: " << getLineNumber() << "] " << mStatus << llendl;
+ loadStatus = mStatus;
+ errorLine = getLineNumber();
+ return;
+ }
+
+ applyTranslations();
+ optimize();
+
+ mInitialized = TRUE;
+}
+
LLBVHLoader::~LLBVHLoader()
{
@@ -167,7 +214,7 @@ LLBVHLoader::~LLBVHLoader()
//------------------------------------------------------------------------
// LLBVHLoader::loadTranslationTable()
//------------------------------------------------------------------------
-LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
+ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName)
{
mLineNumber = 0;
mTranslations.clear();
@@ -182,7 +229,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
infile.open(path, LL_APR_R);
apr_file_t *fp = infile.getFileHandle();
if (!fp)
- return ST_NO_XLT_FILE;
+ return E_ST_NO_XLT_FILE;
llinfos << "NOTE: Loading translation table: " << fileName << llendl;
@@ -194,9 +241,9 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
// load header
//--------------------------------------------------------------------
if ( ! getLine(fp) )
- return ST_EOF;
+ return E_ST_EOF;
if ( strncmp(mLine, "Translations 1.0", 16) )
- return ST_NO_XLT_HEADER;
+ return E_ST_NO_XLT_HEADER;
//--------------------------------------------------------------------
// load data one line at a time
@@ -222,7 +269,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
{
char name[128]; /* Flawfinder: ignore */
if ( sscanf(mLine, " [%127[^]]", name) != 1 )
- return ST_NO_XLT_NAME;
+ return E_ST_NO_XLT_NAME;
if (strcmp(name, "GLOBALS")==0)
{
@@ -245,7 +292,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
{
char emote_str[1024]; /* Flawfinder: ignore */
if ( sscanf(mLine, " %*s = %1023s", emote_str) != 1 ) /* Flawfinder: ignore */
- return ST_NO_XLT_EMOTE;
+ return E_ST_NO_XLT_EMOTE;
mEmoteName.assign( emote_str );
// llinfos << "NOTE: Emote: " << mEmoteName.c_str() << llendl;
@@ -260,7 +307,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
{
S32 priority;
if ( sscanf(mLine, " %*s = %d", &priority) != 1 )
- return ST_NO_XLT_PRIORITY;
+ return E_ST_NO_XLT_PRIORITY;
mPriority = priority;
// llinfos << "NOTE: Priority: " << mPriority << llendl;
@@ -288,7 +335,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
}
else
{
- return ST_NO_XLT_LOOP;
+ return E_ST_NO_XLT_LOOP;
}
mLoopInPoint = loop_in * mDuration;
@@ -305,7 +352,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
F32 duration;
char type[128]; /* Flawfinder: ignore */
if ( sscanf(mLine, " %*s = %f %127s", &duration, type) != 2 ) /* Flawfinder: ignore */
- return ST_NO_XLT_EASEIN;
+ return E_ST_NO_XLT_EASEIN;
mEaseIn = duration;
continue;
@@ -319,7 +366,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
F32 duration;
char type[128]; /* Flawfinder: ignore */
if ( sscanf(mLine, " %*s = %f %127s", &duration, type) != 2 ) /* Flawfinder: ignore */
- return ST_NO_XLT_EASEOUT;
+ return E_ST_NO_XLT_EASEOUT;
mEaseOut = duration;
continue;
@@ -332,7 +379,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
{
S32 handMorph;
if (sscanf(mLine, " %*s = %d", &handMorph) != 1)
- return ST_NO_XLT_HAND;
+ return E_ST_NO_XLT_HAND;
mHand = handMorph;
continue;
@@ -380,7 +427,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
&constraint.mTargetOffset.mV[VY],
&constraint.mTargetOffset.mV[VZ]) != 13)
{
- return ST_NO_CONSTRAINT;
+ return E_ST_NO_CONSTRAINT;
}
}
else
@@ -440,7 +487,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
&constraint.mTargetOffset.mV[VY],
&constraint.mTargetOffset.mV[VZ]) != 13)
{
- return ST_NO_CONSTRAINT;
+ return E_ST_NO_CONSTRAINT;
}
}
else
@@ -463,7 +510,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
// at this point there must be a valid trans pointer
//----------------------------------------------------------------
if ( ! trans )
- return ST_NO_XLT_NAME;
+ return E_ST_NO_XLT_NAME;
//----------------------------------------------------------------
// check for ignore flag
@@ -472,7 +519,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
{
char trueFalse[128]; /* Flawfinder: ignore */
if ( sscanf(mLine, " %*s = %127s", trueFalse) != 1 ) /* Flawfinder: ignore */
- return ST_NO_XLT_IGNORE;
+ return E_ST_NO_XLT_IGNORE;
trans->mIgnore = (LLStringUtil::compareInsensitive(trueFalse, "true")==0);
continue;
@@ -497,12 +544,12 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
}
else
{
- return ST_NO_XLT_RELATIVE;
+ return E_ST_NO_XLT_RELATIVE;
}
}
else
{
- return ST_NO_XLT_RELATIVE;
+ return E_ST_NO_XLT_RELATIVE;
}
continue;
@@ -523,12 +570,12 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
}
else
{
- return ST_NO_XLT_RELATIVE;
+ return E_ST_NO_XLT_RELATIVE;
}
}
else
{
- return ST_NO_XLT_RELATIVE;
+ return E_ST_NO_XLT_RELATIVE;
}
continue;
@@ -541,7 +588,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
{
char outName[128]; /* Flawfinder: ignore */
if ( sscanf(mLine, " %*s = %127s", outName) != 1 ) /* Flawfinder: ignore */
- return ST_NO_XLT_OUTNAME;
+ return E_ST_NO_XLT_OUTNAME;
trans->mOutName = outName;
continue;
@@ -557,7 +604,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
&fm.mMatrix[0][0], &fm.mMatrix[0][1], &fm.mMatrix[0][2],
&fm.mMatrix[1][0], &fm.mMatrix[1][1], &fm.mMatrix[1][2],
&fm.mMatrix[2][0], &fm.mMatrix[2][1], &fm.mMatrix[2][2] ) != 9 )
- return ST_NO_XLT_MATRIX;
+ return E_ST_NO_XLT_MATRIX;
trans->mFrameMatrix = fm;
continue;
@@ -573,7 +620,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
&om.mMatrix[0][0], &om.mMatrix[0][1], &om.mMatrix[0][2],
&om.mMatrix[1][0], &om.mMatrix[1][1], &om.mMatrix[1][2],
&om.mMatrix[2][0], &om.mMatrix[2][1], &om.mMatrix[2][2] ) != 9 )
- return ST_NO_XLT_MATRIX;
+ return E_ST_NO_XLT_MATRIX;
trans->mOffsetMatrix = om;
continue;
@@ -586,7 +633,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
{
char mergeParentName[128]; /* Flawfinder: ignore */
if ( sscanf(mLine, " %*s = %127s", mergeParentName) != 1 ) /* Flawfinder: ignore */
- return ST_NO_XLT_MERGEPARENT;
+ return E_ST_NO_XLT_MERGEPARENT;
trans->mMergeParentName = mergeParentName;
continue;
@@ -599,7 +646,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
{
char mergeChildName[128]; /* Flawfinder: ignore */
if ( sscanf(mLine, " %*s = %127s", mergeChildName) != 1 ) /* Flawfinder: ignore */
- return ST_NO_XLT_MERGECHILD;
+ return E_ST_NO_XLT_MERGECHILD;
trans->mMergeChildName = mergeChildName;
continue;
@@ -612,7 +659,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
{
S32 priority;
if ( sscanf(mLine, " %*s = %d", &priority) != 1 )
- return ST_NO_XLT_PRIORITY;
+ return E_ST_NO_XLT_PRIORITY;
trans->mPriorityModifier = priority;
continue;
@@ -621,14 +668,14 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
}
infile.close() ;
- return ST_OK;
+ return E_ST_OK;
}
//------------------------------------------------------------------------
// LLBVHLoader::loadBVHFile()
//------------------------------------------------------------------------
-LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 &err_line)
+ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 &err_line)
{
std::string line;
@@ -650,14 +697,14 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
// consume hierarchy
//--------------------------------------------------------------------
if (iter == tokens.end())
- return ST_EOF;
+ return E_ST_EOF;
line = (*(iter++));
err_line++;
if ( !strstr(line.c_str(), "HIERARCHY") )
{
// llinfos << line << llendl;
- return ST_NO_HIER;
+ return E_ST_NO_HIER;
}
//--------------------------------------------------------------------
@@ -669,7 +716,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
// get next line
//----------------------------------------------------------------
if (iter == tokens.end())
- return ST_EOF;
+ return E_ST_EOF;
line = (*(iter++));
err_line++;
@@ -719,7 +766,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
else
{
strncpy(error_text, line.c_str(), 127); /* Flawfinder: ignore */
- return ST_NO_JOINT;
+ return E_ST_NO_JOINT;
}
//----------------------------------------------------------------
@@ -729,9 +776,20 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
if ( sscanf(line.c_str(), "%*s %79s", jointName) != 1 ) /* Flawfinder: ignore */
{
strncpy(error_text, line.c_str(), 127); /* Flawfinder: ignore */
- return ST_NO_NAME;
+ return E_ST_NO_NAME;
+ }
+
+ //---------------------------------------------------------------
+ // we require the root joint be "hip" - DEV-26188
+ //---------------------------------------------------------------
+ const char* FORCED_ROOT_NAME = "hip";
+ if ( (mJoints.size() == 0 ) && ( !strstr(jointName, FORCED_ROOT_NAME) ) )
+ {
+ strncpy(error_text, line.c_str(), 127); /* Flawfinder: ignore */
+ return E_ST_BAD_ROOT;
}
+
//----------------------------------------------------------------
// add a set of keyframes for this joint
//----------------------------------------------------------------
@@ -754,7 +812,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
//----------------------------------------------------------------
if (iter == tokens.end())
{
- return ST_EOF;
+ return E_ST_EOF;
}
line = (*(iter++));
err_line++;
@@ -765,7 +823,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
if ( !strstr(line.c_str(), "{") )
{
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
- return ST_NO_OFFSET;
+ return E_ST_NO_OFFSET;
}
else
{
@@ -777,7 +835,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
//----------------------------------------------------------------
if (iter == tokens.end())
{
- return ST_EOF;
+ return E_ST_EOF;
}
line = (*(iter++));
err_line++;
@@ -788,7 +846,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
if ( !strstr(line.c_str(), "OFFSET") )
{
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
- return ST_NO_OFFSET;
+ return E_ST_NO_OFFSET;
}
//----------------------------------------------------------------
@@ -796,7 +854,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
//----------------------------------------------------------------
if (iter == tokens.end())
{
- return ST_EOF;
+ return E_ST_EOF;
}
line = (*(iter++));
err_line++;
@@ -807,7 +865,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
if ( !strstr(line.c_str(), "CHANNELS") )
{
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
- return ST_NO_CHANNELS;
+ return E_ST_NO_CHANNELS;
}
//----------------------------------------------------------------
@@ -820,14 +878,14 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
if (!p)
{
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
- return ST_NO_ROTATION;
+ return E_ST_NO_ROTATION;
}
const char axis = *(p - 1);
if ((axis != 'X') && (axis != 'Y') && (axis != 'Z'))
{
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
- return ST_NO_AXIS;
+ return E_ST_NO_AXIS;
}
joint->mOrder[i] = axis;
@@ -842,7 +900,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
if ( !strstr(line.c_str(), "MOTION") )
{
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
- return ST_NO_MOTION;
+ return E_ST_NO_MOTION;
}
//--------------------------------------------------------------------
@@ -850,7 +908,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
//--------------------------------------------------------------------
if (iter == tokens.end())
{
- return ST_EOF;
+ return E_ST_EOF;
}
line = (*(iter++));
err_line++;
@@ -858,13 +916,13 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
if ( !strstr(line.c_str(), "Frames:") )
{
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
- return ST_NO_FRAMES;
+ return E_ST_NO_FRAMES;
}
if ( sscanf(line.c_str(), "Frames: %d", &mNumFrames) != 1 )
{
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
- return ST_NO_FRAMES;
+ return E_ST_NO_FRAMES;
}
//--------------------------------------------------------------------
@@ -872,7 +930,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
//--------------------------------------------------------------------
if (iter == tokens.end())
{
- return ST_EOF;
+ return E_ST_EOF;
}
line = (*(iter++));
err_line++;
@@ -880,13 +938,13 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
if ( !strstr(line.c_str(), "Frame Time:") )
{
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
- return ST_NO_FRAME_TIME;
+ return E_ST_NO_FRAME_TIME;
}
if ( sscanf(line.c_str(), "Frame Time: %f", &mFrameTime) != 1 )
{
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
- return ST_NO_FRAME_TIME;
+ return E_ST_NO_FRAME_TIME;
}
mDuration = (F32)mNumFrames * mFrameTime;
@@ -903,7 +961,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
// get next line
if (iter == tokens.end())
{
- return ST_EOF;
+ return E_ST_EOF;
}
line = (*(iter++));
err_line++;
@@ -922,7 +980,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
if ( sscanf(p, "%f %f %f", key.mPos, key.mPos+1, key.mPos+2) != 3 )
{
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
- return ST_NO_POS;
+ return E_ST_NO_POS;
}
}
@@ -931,19 +989,19 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
if (!p)
{
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
- return ST_NO_ROT;
+ return E_ST_NO_ROT;
}
p = find_next_whitespace(++p);
if (!p)
{
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
- return ST_NO_ROT;
+ return E_ST_NO_ROT;
}
p = find_next_whitespace(++p);
if (!p)
{
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
- return ST_NO_ROT;
+ return E_ST_NO_ROT;
}
// get 3 rot values for joint
@@ -951,7 +1009,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
if ( sscanf(p, " %f %f %f", rot, rot+1, rot+2) != 3 )
{
strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/
- return ST_NO_ROT;
+ return E_ST_NO_ROT;
}
p++;
@@ -962,7 +1020,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex
}
}
- return ST_OK;
+ return E_ST_OK;
}
diff --git a/indra/llcharacter/llbvhloader.h b/indra/llcharacter/llbvhloader.h
index 6937b9d835..85ab035e61 100644
--- a/indra/llcharacter/llbvhloader.h
+++ b/indra/llcharacter/llbvhloader.h
@@ -184,6 +184,42 @@ public:
S32 mPriorityModifier;
};
+typedef enum e_load_status
+ {
+ E_ST_OK,
+ E_ST_EOF,
+ E_ST_NO_CONSTRAINT,
+ E_ST_NO_FILE,
+ E_ST_NO_HIER,
+ E_ST_NO_JOINT,
+ E_ST_NO_NAME,
+ E_ST_NO_OFFSET,
+ E_ST_NO_CHANNELS,
+ E_ST_NO_ROTATION,
+ E_ST_NO_AXIS,
+ E_ST_NO_MOTION,
+ E_ST_NO_FRAMES,
+ E_ST_NO_FRAME_TIME,
+ E_ST_NO_POS,
+ E_ST_NO_ROT,
+ E_ST_NO_XLT_FILE,
+ E_ST_NO_XLT_HEADER,
+ E_ST_NO_XLT_NAME,
+ E_ST_NO_XLT_IGNORE,
+ E_ST_NO_XLT_RELATIVE,
+ E_ST_NO_XLT_OUTNAME,
+ E_ST_NO_XLT_MATRIX,
+ E_ST_NO_XLT_MERGECHILD,
+ E_ST_NO_XLT_MERGEPARENT,
+ E_ST_NO_XLT_PRIORITY,
+ E_ST_NO_XLT_LOOP,
+ E_ST_NO_XLT_EASEIN,
+ E_ST_NO_XLT_EASEOUT,
+ E_ST_NO_XLT_HAND,
+ E_ST_NO_XLT_EMOTE,
+ E_ST_BAD_ROOT
+ } ELoadStatus;
+
//------------------------------------------------------------------------
// TranslationMap
//------------------------------------------------------------------------
@@ -194,11 +230,13 @@ class LLBVHLoader
friend class LLKeyframeMotion;
public:
// Constructor
- LLBVHLoader(const char* buffer);
+// LLBVHLoader(const char* buffer);
+ LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine);
~LLBVHLoader();
-
+
+/*
// Status Codes
- typedef const char *Status;
+ typedef const char *status_t;
static const char *ST_OK;
static const char *ST_EOF;
static const char *ST_NO_CONSTRAINT;
@@ -230,13 +268,14 @@ public:
static const char *ST_NO_XLT_EASEOUT;
static const char *ST_NO_XLT_HAND;
static const char *ST_NO_XLT_EMOTE;
-
+ static const char *ST_BAD_ROOT;
+*/
// Loads the specified translation table.
- Status loadTranslationTable(const char *fileName);
+ ELoadStatus loadTranslationTable(const char *fileName);
// Load the specified BVH file.
// Returns status code.
- Status loadBVHFile(const char *buffer, char *error_text, S32 &error_line);
+ ELoadStatus loadBVHFile(const char *buffer, char *error_text, S32 &error_line);
// Applies translations to BVH data loaded.
void applyTranslations();
@@ -260,7 +299,7 @@ public:
BOOL isInitialized() { return mInitialized; }
- Status getStatus() { return mStatus; }
+ ELoadStatus getStatus() { return mStatus; }
protected:
// Consumes one line of input from file.
@@ -287,7 +326,8 @@ protected:
std::string mEmoteName;
BOOL mInitialized;
- Status mStatus;
+ ELoadStatus mStatus;
+
// computed values
F32 mDuration;
};
diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp
index 6633c65317..528a7bb4a5 100644
--- a/indra/llcharacter/llcharacter.cpp
+++ b/indra/llcharacter/llcharacter.cpp
@@ -180,9 +180,11 @@ void LLCharacter::requestStopMotion( LLMotion* motion)
//-----------------------------------------------------------------------------
// updateMotions()
//-----------------------------------------------------------------------------
+static LLFastTimer::DeclareTimer FTM_UPDATE_ANIMATION("Update Animation");
+
void LLCharacter::updateMotions(e_update_t update_type)
{
- LLFastTimer t(LLFastTimer::FTM_UPDATE_ANIMATION);
+ LLFastTimer t(FTM_UPDATE_ANIMATION);
if (update_type == HIDDEN_UPDATE)
{
mMotionController.updateMotionsMinimal();
@@ -271,13 +273,13 @@ void LLCharacter::removeAnimationData(std::string name)
//-----------------------------------------------------------------------------
// setVisualParamWeight()
//-----------------------------------------------------------------------------
-BOOL LLCharacter::setVisualParamWeight(LLVisualParam* which_param, F32 weight, BOOL set_by_user)
+BOOL LLCharacter::setVisualParamWeight(LLVisualParam* which_param, F32 weight, BOOL upload_bake)
{
S32 index = which_param->getID();
- VisualParamIndexMap_t::iterator index_iter = mVisualParamIndexMap.find(index);
+ visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index);
if (index_iter != mVisualParamIndexMap.end())
{
- index_iter->second->setWeight(weight, set_by_user);
+ index_iter->second->setWeight(weight, upload_bake);
return TRUE;
}
return FALSE;
@@ -286,15 +288,15 @@ BOOL LLCharacter::setVisualParamWeight(LLVisualParam* which_param, F32 weight, B
//-----------------------------------------------------------------------------
// setVisualParamWeight()
//-----------------------------------------------------------------------------
-BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight, BOOL set_by_user)
+BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake)
{
std::string tname(param_name);
LLStringUtil::toLower(tname);
char *tableptr = sVisualParamNames.checkString(tname);
- VisualParamNameMap_t::iterator name_iter = mVisualParamNameMap.find(tableptr);
+ visual_param_name_map_t::iterator name_iter = mVisualParamNameMap.find(tableptr);
if (name_iter != mVisualParamNameMap.end())
{
- name_iter->second->setWeight(weight, set_by_user);
+ name_iter->second->setWeight(weight, upload_bake);
return TRUE;
}
llwarns << "LLCharacter::setVisualParamWeight() Invalid visual parameter: " << param_name << llendl;
@@ -304,12 +306,12 @@ BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight, BOOL
//-----------------------------------------------------------------------------
// setVisualParamWeight()
//-----------------------------------------------------------------------------
-BOOL LLCharacter::setVisualParamWeight(S32 index, F32 weight, BOOL set_by_user)
+BOOL LLCharacter::setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake)
{
- VisualParamIndexMap_t::iterator index_iter = mVisualParamIndexMap.find(index);
+ visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index);
if (index_iter != mVisualParamIndexMap.end())
{
- index_iter->second->setWeight(weight, set_by_user);
+ index_iter->second->setWeight(weight, upload_bake);
return TRUE;
}
llwarns << "LLCharacter::setVisualParamWeight() Invalid visual parameter index: " << index << llendl;
@@ -322,7 +324,7 @@ BOOL LLCharacter::setVisualParamWeight(S32 index, F32 weight, BOOL set_by_user)
F32 LLCharacter::getVisualParamWeight(LLVisualParam *which_param)
{
S32 index = which_param->getID();
- VisualParamIndexMap_t::iterator index_iter = mVisualParamIndexMap.find(index);
+ visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index);
if (index_iter != mVisualParamIndexMap.end())
{
return index_iter->second->getWeight();
@@ -342,7 +344,7 @@ F32 LLCharacter::getVisualParamWeight(const char* param_name)
std::string tname(param_name);
LLStringUtil::toLower(tname);
char *tableptr = sVisualParamNames.checkString(tname);
- VisualParamNameMap_t::iterator name_iter = mVisualParamNameMap.find(tableptr);
+ visual_param_name_map_t::iterator name_iter = mVisualParamNameMap.find(tableptr);
if (name_iter != mVisualParamNameMap.end())
{
return name_iter->second->getWeight();
@@ -356,7 +358,7 @@ F32 LLCharacter::getVisualParamWeight(const char* param_name)
//-----------------------------------------------------------------------------
F32 LLCharacter::getVisualParamWeight(S32 index)
{
- VisualParamIndexMap_t::iterator index_iter = mVisualParamIndexMap.find(index);
+ visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index);
if (index_iter != mVisualParamIndexMap.end())
{
return index_iter->second->getWeight();
@@ -413,7 +415,7 @@ LLVisualParam* LLCharacter::getVisualParam(const char *param_name)
std::string tname(param_name);
LLStringUtil::toLower(tname);
char *tableptr = sVisualParamNames.checkString(tname);
- VisualParamNameMap_t::iterator name_iter = mVisualParamNameMap.find(tableptr);
+ visual_param_name_map_t::iterator name_iter = mVisualParamNameMap.find(tableptr);
if (name_iter != mVisualParamNameMap.end())
{
return name_iter->second;
@@ -428,7 +430,7 @@ LLVisualParam* LLCharacter::getVisualParam(const char *param_name)
void LLCharacter::addSharedVisualParam(LLVisualParam *param)
{
S32 index = param->getID();
- VisualParamIndexMap_t::iterator index_iter = mVisualParamIndexMap.find(index);
+ visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index);
LLVisualParam* current_param = 0;
if (index_iter != mVisualParamIndexMap.end())
current_param = index_iter->second;
@@ -455,13 +457,13 @@ void LLCharacter::addVisualParam(LLVisualParam *param)
{
S32 index = param->getID();
// Add Index map
- std::pair<VisualParamIndexMap_t::iterator, bool> idxres;
- idxres = mVisualParamIndexMap.insert(VisualParamIndexMap_t::value_type(index, param));
+ std::pair<visual_param_index_map_t::iterator, bool> idxres;
+ idxres = mVisualParamIndexMap.insert(visual_param_index_map_t::value_type(index, param));
if (!idxres.second)
{
llwarns << "Visual parameter " << param->getName() << " already exists with same ID as " <<
param->getName() << llendl;
- VisualParamIndexMap_t::iterator index_iter = idxres.first;
+ visual_param_index_map_t::iterator index_iter = idxres.first;
index_iter->second = param;
}
@@ -471,12 +473,12 @@ void LLCharacter::addVisualParam(LLVisualParam *param)
std::string tname(param->getName());
LLStringUtil::toLower(tname);
char *tableptr = sVisualParamNames.addString(tname);
- std::pair<VisualParamNameMap_t::iterator, bool> nameres;
- nameres = mVisualParamNameMap.insert(VisualParamNameMap_t::value_type(tableptr, param));
+ std::pair<visual_param_name_map_t::iterator, bool> nameres;
+ nameres = mVisualParamNameMap.insert(visual_param_name_map_t::value_type(tableptr, param));
if (!nameres.second)
{
// Already exists, copy param
- VisualParamNameMap_t::iterator name_iter = nameres.first;
+ visual_param_name_map_t::iterator name_iter = nameres.first;
name_iter->second = param;
}
}
diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h
index 0112788884..27e2a51c62 100644
--- a/indra/llcharacter/llcharacter.h
+++ b/indra/llcharacter/llcharacter.h
@@ -42,7 +42,7 @@
#include "llmotioncontroller.h"
#include "llvisualparam.h"
#include "string_table.h"
-#include "llmemory.h"
+#include "llpointer.h"
#include "llthread.h"
class LLPolyMesh;
@@ -169,7 +169,7 @@ public:
void updateMotions(e_update_t update_type);
LLAnimPauseRequest requestPause();
- BOOL areAnimationsPaused() { return mMotionController.isPaused(); }
+ BOOL areAnimationsPaused() const { return mMotionController.isPaused(); }
void setAnimTimeFactor(F32 factor) { mMotionController.setTimeFactor(factor); }
void setTimeStep(F32 time_step) { mMotionController.setTimeStep(time_step); }
@@ -203,9 +203,9 @@ public:
void addVisualParam(LLVisualParam *param);
void addSharedVisualParam(LLVisualParam *param);
- BOOL setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL set_by_user = FALSE );
- BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL set_by_user = FALSE );
- BOOL setVisualParamWeight(S32 index, F32 weight, BOOL set_by_user = FALSE );
+ virtual BOOL setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL upload_bake = FALSE );
+ virtual BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake = FALSE );
+ virtual BOOL setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake = FALSE );
// get visual param weight by param or name
F32 getVisualParamWeight(LLVisualParam *distortion);
@@ -231,14 +231,14 @@ public:
return (mCurIterator++)->second;
}
- LLVisualParam* getVisualParam(S32 id)
+ LLVisualParam* getVisualParam(S32 id) const
{
- VisualParamIndexMap_t::iterator iter = mVisualParamIndexMap.find(id);
+ visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.find(id);
return (iter == mVisualParamIndexMap.end()) ? 0 : iter->second;
}
S32 getVisualParamID(LLVisualParam *id)
{
- VisualParamIndexMap_t::iterator iter;
+ visual_param_index_map_t::iterator iter;
for (iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); iter++)
{
if (iter->second == id)
@@ -246,11 +246,11 @@ public:
}
return 0;
}
- S32 getVisualParamCount() { return (S32)mVisualParamIndexMap.size(); }
+ S32 getVisualParamCount() const { return (S32)mVisualParamIndexMap.size(); }
LLVisualParam* getVisualParam(const char *name);
- ESex getSex() { return mSex; }
+ ESex getSex() const { return mSex; }
void setSex( ESex sex ) { mSex = sex; }
U32 getAppearanceSerialNum() const { return mAppearanceSerialNum; }
@@ -276,11 +276,12 @@ protected:
private:
// visual parameter stuff
- typedef std::map<S32, LLVisualParam *> VisualParamIndexMap_t;
- VisualParamIndexMap_t mVisualParamIndexMap;
- VisualParamIndexMap_t::iterator mCurIterator;
- typedef std::map<char *, LLVisualParam *> VisualParamNameMap_t;
- VisualParamNameMap_t mVisualParamNameMap;
+ typedef std::map<S32, LLVisualParam *> visual_param_index_map_t;
+ typedef std::map<char *, LLVisualParam *> visual_param_name_map_t;
+
+ visual_param_index_map_t::iterator mCurIterator;
+ visual_param_index_map_t mVisualParamIndexMap;
+ visual_param_name_map_t mVisualParamNameMap;
static LLStringTable sVisualParamNames;
};
diff --git a/indra/llcharacter/llgesture.cpp b/indra/llcharacter/llgesture.cpp
index 4ee29fe100..83e4e35b00 100644
--- a/indra/llcharacter/llgesture.cpp
+++ b/indra/llcharacter/llgesture.cpp
@@ -304,7 +304,7 @@ BOOL LLGestureList::trigger(KEY key, MASK mask)
}
else
{
- llwarns << "NULL gesture in gesture list (" << i << ")" << llendl
+ llwarns << "NULL gesture in gesture list (" << i << ")" << llendl;
}
}
return FALSE;
diff --git a/indra/llcharacter/llheadrotmotion.cpp b/indra/llcharacter/llheadrotmotion.cpp
index 88cd77f7af..0ee378f3b8 100644
--- a/indra/llcharacter/llheadrotmotion.cpp
+++ b/indra/llcharacter/llheadrotmotion.cpp
@@ -251,10 +251,13 @@ BOOL LLHeadRotMotion::onUpdate(F32 time, U8* joint_mask)
mLastHeadRot = head_rot_local;
// Set the head rotation.
- LLQuaternion torsoRotLocal = mNeckState->getJoint()->getParent()->getWorldRotation() * currentInvRootRotWorld;
- head_rot_local = head_rot_local * ~torsoRotLocal;
- mNeckState->setRotation( nlerp(NECK_LAG, LLQuaternion::DEFAULT, head_rot_local) );
- mHeadState->setRotation( nlerp(1.f - NECK_LAG, LLQuaternion::DEFAULT, head_rot_local));
+ if(mNeckState->getJoint() && mNeckState->getJoint()->getParent())
+ {
+ LLQuaternion torsoRotLocal = mNeckState->getJoint()->getParent()->getWorldRotation() * currentInvRootRotWorld;
+ head_rot_local = head_rot_local * ~torsoRotLocal;
+ mNeckState->setRotation( nlerp(NECK_LAG, LLQuaternion::DEFAULT, head_rot_local) );
+ mHeadState->setRotation( nlerp(1.f - NECK_LAG, LLQuaternion::DEFAULT, head_rot_local));
+ }
return TRUE;
}
diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h
index b1a0b74f85..0473d1599a 100644
--- a/indra/llcharacter/lljoint.h
+++ b/indra/llcharacter/lljoint.h
@@ -174,7 +174,7 @@ public:
void clampRotation(LLQuaternion old_rot, LLQuaternion new_rot);
- virtual BOOL isAnimatable() { return TRUE; }
+ virtual BOOL isAnimatable() const { return TRUE; }
S32 getJointNum() const { return mJointNum; }
void setJointNum(S32 joint_num) { mJointNum = joint_num; }
diff --git a/indra/llcharacter/lljointsolverrp3.cpp b/indra/llcharacter/lljointsolverrp3.cpp
index 0ea92a2d77..6599a76b16 100644
--- a/indra/llcharacter/lljointsolverrp3.cpp
+++ b/indra/llcharacter/lljointsolverrp3.cpp
@@ -211,7 +211,7 @@ void LLJointSolverRP3::solve()
//-------------------------------------------------------------------------
LLVector3 abacCompOrthoVec = abVec - acVec * ((abVec * acVec)/(acVec * acVec));
-// llinfos << "abacCompOrthoVec : " << abacCompOrthoVec << llendl
+// llinfos << "abacCompOrthoVec : " << abacCompOrthoVec << llendl;
//-------------------------------------------------------------------------
// compute the normal of the original ABC plane (and store for later)
diff --git a/indra/llcharacter/lljointstate.h b/indra/llcharacter/lljointstate.h
index 16ad0e1200..e40cf2673f 100644
--- a/indra/llcharacter/lljointstate.h
+++ b/indra/llcharacter/lljointstate.h
@@ -37,7 +37,7 @@
// Header Files
//-----------------------------------------------------------------------------
#include "lljoint.h"
-#include "llmemory.h"
+#include "llrefcount.h"
//-----------------------------------------------------------------------------
// class LLJointState
diff --git a/indra/llcharacter/llkeyframemotion.h b/indra/llcharacter/llkeyframemotion.h
index 7e8c84488c..50d9d05046 100644
--- a/indra/llcharacter/llkeyframemotion.h
+++ b/indra/llcharacter/llkeyframemotion.h
@@ -47,7 +47,6 @@
#include "llquaternion.h"
#include "v3dmath.h"
#include "v3math.h"
-#include "llapr.h"
#include "llbvhconsts.h"
class LLKeyframeDataCache;
diff --git a/indra/llcharacter/llkeyframemotionparam.cpp b/indra/llcharacter/llkeyframemotionparam.cpp
index 622405a5e1..c4333fc0fd 100644
--- a/indra/llcharacter/llkeyframemotionparam.cpp
+++ b/indra/llcharacter/llkeyframemotionparam.cpp
@@ -347,8 +347,11 @@ BOOL LLKeyframeMotionParam::loadMotions()
// Load named file by concatenating the character prefix with the motion name.
// Load data into a buffer to be parsed.
//-------------------------------------------------------------------------
- std::string path = gDirUtilp->getExpandedFilename(LL_PATH_MOTIONS,mCharacter->getAnimationPrefix())
- + "_" + getName() + ".llp";
+ //std::string path = gDirUtilp->getExpandedFilename(LL_PATH_MOTIONS,mCharacter->getAnimationPrefix())
+ // + "_" + getName() + ".llp";
+ //RN: deprecated unused reference to "motion" directory
+ std::string path;
+
//-------------------------------------------------------------------------
// open the file
diff --git a/indra/llcharacter/llkeyframestandmotion.cpp b/indra/llcharacter/llkeyframestandmotion.cpp
index 1d42298f4d..1ae0ddeea0 100644
--- a/indra/llcharacter/llkeyframestandmotion.cpp
+++ b/indra/llcharacter/llkeyframestandmotion.cpp
@@ -190,7 +190,7 @@ BOOL LLKeyframeStandMotion::onUpdate(F32 time, U8* joint_mask)
if (dot(mPelvisState->getJoint()->getWorldRotation(), mLastGoodPelvisRotation) < ROTATION_THRESHOLD)
{
mLastGoodPelvisRotation = mPelvisState->getJoint()->getWorldRotation();
- mLastGoodPelvisRotation.normQuat();
+ mLastGoodPelvisRotation.normalize();
mTrackAnkles = TRUE;
}
else if ((mCharacter->getCharacterPosition() - mLastGoodPosition).magVecSquared() > POSITION_THRESHOLD)
diff --git a/indra/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp
index 006d2b5f62..bb9625b2bd 100644
--- a/indra/llcharacter/llmotioncontroller.cpp
+++ b/indra/llcharacter/llmotioncontroller.cpp
@@ -1019,9 +1019,9 @@ bool LLMotionController::isMotionLoading(LLMotion* motion)
//-----------------------------------------------------------------------------
// findMotion()
//-----------------------------------------------------------------------------
-LLMotion* LLMotionController::findMotion(const LLUUID& id)
+LLMotion* LLMotionController::findMotion(const LLUUID& id) const
{
- motion_map_t::iterator iter = mAllMotions.find(id);
+ motion_map_t::const_iterator iter = mAllMotions.find(id);
if(iter == mAllMotions.end())
{
return NULL;
diff --git a/indra/llcharacter/llmotioncontroller.h b/indra/llcharacter/llmotioncontroller.h
index 9271483a25..5c3ec223cb 100644
--- a/indra/llcharacter/llmotioncontroller.h
+++ b/indra/llcharacter/llmotioncontroller.h
@@ -153,12 +153,12 @@ public:
// pause and continue all motions
void pauseAllMotions();
void unpauseAllMotions();
- BOOL isPaused() { return mPaused; }
+ BOOL isPaused() const { return mPaused; }
void setTimeStep(F32 step);
void setTimeFactor(F32 time_factor);
- F32 getTimeFactor() { return mTimeFactor; }
+ F32 getTimeFactor() const { return mTimeFactor; }
motion_list_t& getActiveMotions() { return mActiveMotions; }
@@ -167,7 +167,7 @@ public:
//protected:
bool isMotionActive( LLMotion *motion );
bool isMotionLoading( LLMotion *motion );
- LLMotion *findMotion( const LLUUID& id );
+ LLMotion *findMotion( const LLUUID& id ) const;
protected:
// internal operations act on motion instances directly
diff --git a/indra/llcharacter/llmultigesture.cpp b/indra/llcharacter/llmultigesture.cpp
index 7fe21dbc93..05d1bc0cd9 100644
--- a/indra/llcharacter/llmultigesture.cpp
+++ b/indra/llcharacter/llmultigesture.cpp
@@ -50,6 +50,7 @@ const S32 GESTURE_VERSION = 2;
LLMultiGesture::LLMultiGesture()
: mKey(),
mMask(),
+ mName(),
mTrigger(),
mReplaceText(),
mSteps(),
@@ -243,7 +244,7 @@ void LLMultiGesture::dump()
//---------------------------------------------------------------------------
LLGestureStepAnimation::LLGestureStepAnimation()
: LLGestureStep(),
- mAnimName("None"),
+ mAnimName("None"),
mAnimAssetID(),
mFlags(0x0)
{ }
@@ -292,20 +293,27 @@ BOOL LLGestureStepAnimation::deserialize(LLDataPacker& dp)
dp.unpackU32(mFlags, "flags");
return TRUE;
}
-
-std::string LLGestureStepAnimation::getLabel() const
+// *TODO: Translate
+std::vector<std::string> LLGestureStepAnimation::getLabel() const
{
- std::string label;
+ std::vector<std::string> strings;
+
+// std::string label;
if (mFlags & ANIM_FLAG_STOP)
{
- label = "Stop Animation: ";
+ strings.push_back( "AnimFlagStop");
+
+// label = "Stop Animation: ";
}
else
{
- label = "Start Animation: ";
+ strings.push_back( "AnimFlagStart");
+
+// label = "Start Animation: ";
}
- label += mAnimName;
- return label;
+ strings.push_back( mAnimName);
+// label += mAnimName;
+ return strings;
}
void LLGestureStepAnimation::dump()
@@ -359,12 +367,15 @@ BOOL LLGestureStepSound::deserialize(LLDataPacker& dp)
dp.unpackU32(mFlags, "flags");
return TRUE;
}
-
-std::string LLGestureStepSound::getLabel() const
+// *TODO: Translate
+std::vector<std::string> LLGestureStepSound::getLabel() const
{
- std::string label("Sound: ");
- label += mSoundName;
- return label;
+ std::vector<std::string> strings;
+ strings.push_back( "Sound");
+ strings.push_back( mSoundName);
+// std::string label("Sound: ");
+// label += mSoundName;
+ return strings;
}
void LLGestureStepSound::dump()
@@ -414,12 +425,13 @@ BOOL LLGestureStepChat::deserialize(LLDataPacker& dp)
dp.unpackU32(mFlags, "flags");
return TRUE;
}
-
-std::string LLGestureStepChat::getLabel() const
+// *TODO: Translate
+std::vector<std::string> LLGestureStepChat::getLabel() const
{
- std::string label("Chat: ");
- label += mChatText;
- return label;
+ std::vector<std::string> strings;
+ strings.push_back("Chat");
+ strings.push_back(mChatText);
+ return strings;
}
void LLGestureStepChat::dump()
@@ -467,22 +479,27 @@ BOOL LLGestureStepWait::deserialize(LLDataPacker& dp)
dp.unpackU32(mFlags, "flags");
return TRUE;
}
-
-std::string LLGestureStepWait::getLabel() const
+// *TODO: Translate
+std::vector<std::string> LLGestureStepWait::getLabel() const
{
- std::string label("--- Wait: ");
+ std::vector<std::string> strings;
+ strings.push_back( "Wait" );
+
+// std::string label("--- Wait: ");
if (mFlags & WAIT_FLAG_TIME)
{
char buffer[64]; /* Flawfinder: ignore */
snprintf(buffer, sizeof(buffer), "%.1f seconds", (double)mWaitSeconds); /* Flawfinder: ignore */
- label += buffer;
+ strings.push_back(buffer);
+// label += buffer;
}
else if (mFlags & WAIT_FLAG_ALL_ANIM)
{
- label += "until animations are done";
+ strings.push_back("until animations are done");
+ // label += "until animations are done";
}
- return label;
+ return strings;
}
diff --git a/indra/llcharacter/llmultigesture.h b/indra/llcharacter/llmultigesture.h
index eb15f600ca..fdcf32dc67 100644
--- a/indra/llcharacter/llmultigesture.h
+++ b/indra/llcharacter/llmultigesture.h
@@ -65,11 +65,13 @@ protected:
const LLMultiGesture& operator=(const LLMultiGesture& rhs);
public:
- // name is stored at asset level
- // desc is stored at asset level
KEY mKey;
MASK mMask;
+ // This name can be empty if the inventory item is not around and
+ // the gesture manager has not yet set the name
+ std::string mName;
+
// String, like "/foo" or "hello" that makes it play
std::string mTrigger;
@@ -130,7 +132,7 @@ public:
virtual EStepType getType() = 0;
// Return a user-readable label for this step
- virtual std::string getLabel() const = 0;
+ virtual std::vector<std::string> getLabel() const = 0;
virtual S32 getMaxSerialSize() const = 0;
virtual BOOL serialize(LLDataPacker& dp) const = 0;
@@ -152,7 +154,7 @@ public:
virtual EStepType getType() { return STEP_ANIMATION; }
- virtual std::string getLabel() const;
+ virtual std::vector<std::string> getLabel() const;
virtual S32 getMaxSerialSize() const;
virtual BOOL serialize(LLDataPacker& dp) const;
@@ -175,7 +177,7 @@ public:
virtual EStepType getType() { return STEP_SOUND; }
- virtual std::string getLabel() const;
+ virtual std::vector<std::string> getLabel() const;
virtual S32 getMaxSerialSize() const;
virtual BOOL serialize(LLDataPacker& dp) const;
@@ -198,7 +200,7 @@ public:
virtual EStepType getType() { return STEP_CHAT; }
- virtual std::string getLabel() const;
+ virtual std::vector<std::string> getLabel() const;
virtual S32 getMaxSerialSize() const;
virtual BOOL serialize(LLDataPacker& dp) const;
@@ -223,7 +225,7 @@ public:
virtual EStepType getType() { return STEP_WAIT; }
- virtual std::string getLabel() const;
+ virtual std::vector<std::string> getLabel() const;
virtual S32 getMaxSerialSize() const;
virtual BOOL serialize(LLDataPacker& dp) const;
diff --git a/indra/llcharacter/llpose.cpp b/indra/llcharacter/llpose.cpp
index 93255d702c..dd4880dbb9 100644
--- a/indra/llcharacter/llpose.cpp
+++ b/indra/llcharacter/llpose.cpp
@@ -516,9 +516,9 @@ BOOL LLPoseBlender::addMotion(LLMotion* motion)
void LLPoseBlender::blendAndApply()
{
for (blender_list_t::iterator iter = mActiveBlenders.begin();
- iter != mActiveBlenders.end(); ++iter)
+ iter != mActiveBlenders.end(); )
{
- LLJointStateBlender* jsbp = *iter;
+ LLJointStateBlender* jsbp = *iter++;
jsbp->blendJointStates();
}
diff --git a/indra/llcharacter/llpose.h b/indra/llcharacter/llpose.h
index 5698f21614..2b976b219d 100644
--- a/indra/llcharacter/llpose.h
+++ b/indra/llcharacter/llpose.h
@@ -36,12 +36,14 @@
//-----------------------------------------------------------------------------
// Header Files
//-----------------------------------------------------------------------------
-#include <string>
-#include "llmap.h"
#include "lljointstate.h"
#include "lljoint.h"
+#include "llmap.h"
+#include "llpointer.h"
+
#include <map>
+#include <string>
//-----------------------------------------------------------------------------
diff --git a/indra/llcharacter/llvisualparam.cpp b/indra/llcharacter/llvisualparam.cpp
index d7a144e00c..297322fe58 100644
--- a/indra/llcharacter/llvisualparam.cpp
+++ b/indra/llcharacter/llvisualparam.cpp
@@ -147,6 +147,21 @@ BOOL LLVisualParamInfo::parseXml(LLXmlTreeNode *node)
return TRUE;
}
+//virtual
+void LLVisualParamInfo::toStream(std::ostream &out)
+{
+ out << mID << "\t";
+ out << mName << "\t";
+ out << mDisplayName << "\t";
+ out << mMinName << "\t";
+ out << mMaxName << "\t";
+ out << mGroup << "\t";
+ out << mMinWeight << "\t";
+ out << mMaxWeight << "\t";
+ out << mDefaultWeight << "\t";
+ out << mSex << "\t";
+}
+
//-----------------------------------------------------------------------------
// LLVisualParam()
//-----------------------------------------------------------------------------
@@ -158,7 +173,8 @@ LLVisualParam::LLVisualParam()
mTargetWeight( 0.f ),
mIsAnimating( FALSE ),
mID( -1 ),
- mInfo( 0 )
+ mInfo( 0 ),
+ mIsDummy(FALSE)
{
}
@@ -209,7 +225,7 @@ BOOL LLVisualParam::parseData(LLXmlTreeNode *node)
//-----------------------------------------------------------------------------
// setWeight()
//-----------------------------------------------------------------------------
-void LLVisualParam::setWeight(F32 weight, BOOL set_by_user)
+void LLVisualParam::setWeight(F32 weight, BOOL upload_bake)
{
if (mIsAnimating)
{
@@ -227,15 +243,22 @@ void LLVisualParam::setWeight(F32 weight, BOOL set_by_user)
if (mNext)
{
- mNext->setWeight(weight, set_by_user);
+ mNext->setWeight(weight, upload_bake);
}
}
//-----------------------------------------------------------------------------
// setAnimationTarget()
//-----------------------------------------------------------------------------
-void LLVisualParam::setAnimationTarget(F32 target_value, BOOL set_by_user)
+void LLVisualParam::setAnimationTarget(F32 target_value, BOOL upload_bake)
{
+ // don't animate dummy parameters
+ if (mIsDummy)
+ {
+ setWeight(target_value, upload_bake);
+ return;
+ }
+
if (mInfo)
{
if (getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE)
@@ -251,7 +274,7 @@ void LLVisualParam::setAnimationTarget(F32 target_value, BOOL set_by_user)
if (mNext)
{
- mNext->setAnimationTarget(target_value, set_by_user);
+ mNext->setAnimationTarget(target_value, upload_bake);
}
}
@@ -268,23 +291,37 @@ void LLVisualParam::setNextParam( LLVisualParam *next )
//-----------------------------------------------------------------------------
// animate()
//-----------------------------------------------------------------------------
-void LLVisualParam::animate( F32 delta, BOOL set_by_user )
+void LLVisualParam::animate( F32 delta, BOOL upload_bake )
{
if (mIsAnimating)
{
F32 new_weight = ((mTargetWeight - mCurWeight) * delta) + mCurWeight;
- setWeight(new_weight, set_by_user);
+ setWeight(new_weight, upload_bake);
}
}
//-----------------------------------------------------------------------------
// stopAnimating()
//-----------------------------------------------------------------------------
-void LLVisualParam::stopAnimating(BOOL set_by_user)
+void LLVisualParam::stopAnimating(BOOL upload_bake)
{
if (mIsAnimating && getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE)
{
mIsAnimating = FALSE;
- setWeight(mTargetWeight, set_by_user);
+ setWeight(mTargetWeight, upload_bake);
}
}
+
+//virtual
+BOOL LLVisualParam::linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params)
+{
+ // nothing to do for non-driver parameters
+ return TRUE;
+}
+
+//virtual
+void LLVisualParam::resetDrivenParams()
+{
+ // nothing to do for non-driver parameters
+ return;
+}
diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h
index 3a0c1bbc77..12b45e6ebe 100644
--- a/indra/llcharacter/llvisualparam.h
+++ b/indra/llcharacter/llvisualparam.h
@@ -36,6 +36,7 @@
#include "v3math.h"
#include "llstring.h"
#include "llxmltree.h"
+#include <boost/function.hpp>
class LLPolyMesh;
class LLXmlTreeNode;
@@ -68,6 +69,10 @@ public:
virtual ~LLVisualParamInfo() {};
virtual BOOL parseXml(LLXmlTreeNode *node);
+
+ S32 getID() const { return mID; }
+
+ virtual void toStream(std::ostream &out);
protected:
S32 mID; // ID associated with VisualParam
@@ -92,6 +97,8 @@ protected:
class LLVisualParam
{
public:
+ typedef boost::function<LLVisualParam*(S32)> visual_param_mapper;
+
LLVisualParam();
virtual ~LLVisualParam();
@@ -106,13 +113,16 @@ public:
//virtual BOOL parseData( LLXmlTreeNode *node ) = 0;
virtual void apply( ESex avatar_sex ) = 0;
// Default functions
- virtual void setWeight(F32 weight, BOOL set_by_user);
- virtual void setAnimationTarget( F32 target_value, BOOL set_by_user );
- virtual void animate(F32 delta, BOOL set_by_user);
- virtual void stopAnimating(BOOL set_by_user);
+ virtual void setWeight(F32 weight, BOOL upload_bake);
+ virtual void setAnimationTarget( F32 target_value, BOOL upload_bake );
+ virtual void animate(F32 delta, BOOL upload_bake);
+ virtual void stopAnimating(BOOL upload_bake);
+
+ virtual BOOL linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params);
+ virtual void resetDrivenParams();
// Interface methods
- S32 getID() { return mID; }
+ S32 getID() const { return mID; }
void setID(S32 id) { llassert(!mInfo); mID = id; }
const std::string& getName() const { return mInfo->mName; }
@@ -124,22 +134,24 @@ public:
void setMaxDisplayName(const std::string& s) { mInfo->mMaxName = s; }
void setMinDisplayName(const std::string& s) { mInfo->mMinName = s; }
- EVisualParamGroup getGroup() { return mInfo->mGroup; }
- F32 getMinWeight() { return mInfo->mMinWeight; }
- F32 getMaxWeight() { return mInfo->mMaxWeight; }
- F32 getDefaultWeight() { return mInfo->mDefaultWeight; }
- ESex getSex() { return mInfo->mSex; }
+ EVisualParamGroup getGroup() const { return mInfo->mGroup; }
+ F32 getMinWeight() const { return mInfo->mMinWeight; }
+ F32 getMaxWeight() const { return mInfo->mMaxWeight; }
+ F32 getDefaultWeight() const { return mInfo->mDefaultWeight; }
+ ESex getSex() const { return mInfo->mSex; }
- F32 getWeight() { return mIsAnimating ? mTargetWeight : mCurWeight; }
- F32 getCurrentWeight() { return mCurWeight; }
- F32 getLastWeight() { return mLastWeight; }
- BOOL isAnimating() { return mIsAnimating; }
+ F32 getWeight() const { return mIsAnimating ? mTargetWeight : mCurWeight; }
+ F32 getCurrentWeight() const { return mCurWeight; }
+ F32 getLastWeight() const { return mLastWeight; }
+ BOOL isAnimating() const { return mIsAnimating; }
LLVisualParam* getNextParam() { return mNext; }
void setNextParam( LLVisualParam *next );
- virtual void setAnimating(BOOL is_animating) { mIsAnimating = is_animating; }
- BOOL getAnimating() { return mIsAnimating; }
+ virtual void setAnimating(BOOL is_animating) { mIsAnimating = is_animating && !mIsDummy; }
+ BOOL getAnimating() const { return mIsAnimating; }
+
+ void setIsDummy(BOOL is_dummy) { mIsDummy = is_dummy; }
protected:
F32 mCurWeight; // current weight
@@ -147,6 +159,8 @@ protected:
LLVisualParam* mNext; // next param in a shared chain
F32 mTargetWeight; // interpolation target
BOOL mIsAnimating; // this value has been given an interpolation target
+ BOOL mIsDummy; // this is used to prevent dummy visual params from animating
+
S32 mID; // id for storing weight/morphtarget compares compactly
LLVisualParamInfo *mInfo;
diff --git a/indra/llcharacter/tests/lljoint_test.cpp b/indra/llcharacter/tests/lljoint_test.cpp
new file mode 100644
index 0000000000..06e455883b
--- /dev/null
+++ b/indra/llcharacter/tests/lljoint_test.cpp
@@ -0,0 +1,246 @@
+/**
+ * @file lljoint_test.cpp
+ * @author Adroit
+ * @date 2007-03
+ * @brief lljoint test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "m4math.h"
+#include "v3math.h"
+
+#include "../lljoint.h"
+
+#include "../test/lltut.h"
+
+
+namespace tut
+{
+ struct lljoint_data
+ {
+ };
+ typedef test_group<lljoint_data> lljoint_test;
+ typedef lljoint_test::object lljoint_object;
+ tut::lljoint_test lljoint_testcase("lljoint");
+
+ template<> template<>
+ void lljoint_object::test<1>()
+ {
+ LLJoint lljoint;
+ LLJoint* jnt = lljoint.getParent();
+ ensure("getParent() failed ", (NULL == jnt));
+ ensure("getRoot() failed ", (&lljoint == lljoint.getRoot()));
+ }
+
+ template<> template<>
+ void lljoint_object::test<2>()
+ {
+ std::string str = "LLJoint";
+ LLJoint parent(str), child;
+ child.setup(str, &parent);
+ LLJoint* jnt = child.getParent();
+ ensure("setup() failed ", (&parent == jnt));
+ }
+
+ template<> template<>
+ void lljoint_object::test<3>()
+ {
+ LLJoint parent, child;
+ std::string str = "LLJoint";
+ child.setup(str, &parent);
+ LLJoint* jnt = parent.findJoint(str);
+ ensure("findJoint() failed ", (&child == jnt));
+ }
+
+ template<> template<>
+ void lljoint_object::test<4>()
+ {
+ LLJoint parent;
+ std::string str1 = "LLJoint", str2;
+ parent.setName(str1);
+ str2 = parent.getName();
+ ensure("setName() failed ", (str1 == str2));
+ }
+
+ template<> template<>
+ void lljoint_object::test<5>()
+ {
+ LLJoint lljoint;
+ LLVector3 vec3(2.3f,30.f,10.f);
+ lljoint.setPosition(vec3);
+ LLVector3 pos = lljoint.getPosition();
+ ensure("setPosition()/getPosition() failed ", (vec3 == pos));
+ }
+
+ template<> template<>
+ void lljoint_object::test<6>()
+ {
+ LLJoint lljoint;
+ LLVector3 vec3(2.3f,30.f,10.f);
+ lljoint.setWorldPosition(vec3);
+ LLVector3 pos = lljoint.getWorldPosition();
+ ensure("1:setWorldPosition()/getWorldPosition() failed ", (vec3 == pos));
+ LLVector3 lastPos = lljoint.getLastWorldPosition();
+ ensure("2:getLastWorldPosition failed ", (vec3 == lastPos));
+ }
+
+ template<> template<>
+ void lljoint_object::test<7>()
+ {
+ LLJoint lljoint("LLJoint");
+ LLQuaternion q(2.3f,30.f,10.f,1.f);
+ lljoint.setRotation(q);
+ LLQuaternion rot = lljoint.getRotation();
+ ensure("setRotation()/getRotation() failed ", (q == rot));
+ }
+ template<> template<>
+ void lljoint_object::test<8>()
+ {
+ LLJoint lljoint("LLJoint");
+ LLQuaternion q(2.3f,30.f,10.f,1.f);
+ lljoint.setWorldRotation(q);
+ LLQuaternion rot = lljoint.getWorldRotation();
+ ensure("1:setWorldRotation()/getWorldRotation() failed ", (q == rot));
+ LLQuaternion lastRot = lljoint.getLastWorldRotation();
+ ensure("2:getLastWorldRotation failed ", (q == lastRot));
+ }
+
+ template<> template<>
+ void lljoint_object::test<9>()
+ {
+ LLJoint lljoint;
+ LLVector3 vec3(2.3f,30.f,10.f);
+ lljoint.setScale(vec3);
+ LLVector3 scale = lljoint.getScale();
+ ensure("setScale()/getScale failed ", (vec3 == scale));
+ }
+
+ template<> template<>
+ void lljoint_object::test<10>()
+ {
+ LLJoint lljoint("LLJoint");
+ LLMatrix4 mat;
+ mat.setIdentity();
+ lljoint.setWorldMatrix(mat);//giving warning setWorldMatrix not correctly implemented;
+ LLMatrix4 mat4 = lljoint.getWorldMatrix();
+ ensure("setWorldMatrix()/getWorldMatrix failed ", (mat4 == mat));
+ }
+
+ template<> template<>
+ void lljoint_object::test<11>()
+ {
+ LLJoint lljoint("parent");
+ S32 joint_num = 12;
+ lljoint.setJointNum(joint_num);
+ S32 jointNum = lljoint.getJointNum();
+ ensure("setJointNum()/getJointNum failed ", (jointNum == joint_num));
+ }
+
+ template<> template<>
+ void lljoint_object::test<12>()
+ {
+ LLJoint lljoint;
+ LLVector3 vec3(2.3f,30.f,10.f);
+ lljoint.setSkinOffset(vec3);
+ LLVector3 offset = lljoint.getSkinOffset();
+ ensure("1:setSkinOffset()/getSkinOffset() failed ", (vec3 == offset));
+ }
+
+ template<> template<>
+ void lljoint_object::test<13>()
+ {
+ LLJoint lljointgp("gparent");
+ LLJoint lljoint("parent");
+ LLJoint lljoint1("child1");
+ lljoint.addChild(&lljoint1);
+ LLJoint lljoint2("child2");
+ lljoint.addChild(&lljoint2);
+ LLJoint lljoint3("child3");
+ lljoint.addChild(&lljoint3);
+
+ LLJoint* jnt = NULL;
+ jnt = lljoint2.getParent();
+ ensure("addChild() failed ", (&lljoint == jnt));
+ LLJoint* jnt1 = lljoint.findJoint("child3");
+ ensure("findJoint() failed ", (&lljoint3 == jnt1));
+ lljoint.removeChild(&lljoint3);
+ LLJoint* jnt2 = lljoint.findJoint("child3");
+ ensure("removeChild() failed ", (NULL == jnt2));
+
+ lljointgp.addChild(&lljoint);
+ ensure("GetParent() failed ", (&lljoint== lljoint2.getParent()));
+ ensure("getRoot() failed ", (&lljointgp == lljoint2.getRoot()));
+
+ ensure("getRoot() failed ", &lljoint1 == lljoint.findJoint("child1"));
+
+ lljointgp.removeAllChildren();
+ // parent removed from grandparent - so should not be able to locate child
+ ensure("removeAllChildren() failed ", (NULL == lljointgp.findJoint("child1")));
+ // it should still exist in parent though
+ ensure("removeAllChildren() failed ", (&lljoint1 == lljoint.findJoint("child1")));
+ }
+
+ template<> template<>
+ void lljoint_object::test<14>()
+ {
+ LLJoint lljointgp("gparent");
+
+ LLJoint llparent1("parent1");
+ LLJoint llparent2("parent2");
+
+ LLJoint llchild("child1");
+ LLJoint lladoptedchild("child2");
+ llparent1.addChild(&llchild);
+ llparent1.addChild(&lladoptedchild);
+
+ llparent2.addChild(&lladoptedchild);
+ ensure("1. addChild failed to remove prior parent", lladoptedchild.getParent() == &llparent2);
+ ensure("2. addChild failed to remove prior parent", llparent1.findJoint("child2") == NULL);
+ }
+
+
+ /*
+ Test cases for the following not added. They perform operations
+ on underlying LLXformMatrix and LLVector3 elements which have
+ been unit tested separately.
+ Unit Testing these functions will basically require re-implementing
+ logic of these function in the test case itself
+
+ 1) void WorldMatrixChildren();
+ 2) void updateWorldMatrixParent();
+ 3) void updateWorldPRSParent();
+ 4) void updateWorldMatrix();
+ 5) LLXformMatrix *getXform() { return &mXform; }
+ 6) void setConstraintSilhouette(LLDynamicArray<LLVector3>& silhouette);
+ 7) void clampRotation(LLQuaternion old_rot, LLQuaternion new_rot);
+
+ */
+}
+
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index d6a9e10707..f5acadf30c 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -1,34 +1,60 @@
+
# -*- cmake -*-
project(llcommon)
include(00-Common)
include(LLCommon)
+include(Linking)
+include(Boost)
+include(Pth)
+include(LLSharedLibs)
+include(GooglePerfTools)
+include(Copy3rdPartyLibs)
include_directories(
${EXPAT_INCLUDE_DIRS}
${LLCOMMON_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIRS}
+ ${PTH_INCLUDE_DIRS}
)
+# add_executable(lltreeiterators lltreeiterators.cpp)
+#
+# target_link_libraries(lltreeiterators
+# ${LLCOMMON_LIBRARIES})
+
set(llcommon_SOURCE_FILES
+ imageids.cpp
+ indra_constants.cpp
+ llallocator.cpp
+ llallocator_heap_profile.cpp
llapp.cpp
llapr.cpp
llassettype.cpp
llbase32.cpp
llbase64.cpp
llcommon.cpp
+ llcoros.cpp
llcrc.cpp
llcriticaldamp.cpp
llcursortypes.cpp
lldate.cpp
+ lldependencies.cpp
+ lldictionary.cpp
llerror.cpp
llerrorthread.cpp
llevent.cpp
- llfasttimer.cpp
+ lleventapi.cpp
+ lleventcoro.cpp
+ lleventdispatcher.cpp
+ lleventfilter.cpp
+ llevents.cpp
+ llfasttimer_class.cpp
llfile.cpp
llfindlocale.cpp
llfixedbuffer.cpp
+ llfoldertype.cpp
llformat.cpp
llframetimer.cpp
llheartbeat.cpp
@@ -38,18 +64,25 @@ set(llcommon_SOURCE_FILES
llmd5.cpp
llmemory.cpp
llmemorystream.cpp
+ llmemtype.cpp
llmetrics.cpp
llmortician.cpp
+ lloptioninterface.cpp
+ llptrto.cpp
+ llprocesslauncher.cpp
llprocessor.cpp
llqueuedthread.cpp
llrand.cpp
+ llrefcount.cpp
llrun.cpp
llsd.cpp
llsdserialize.cpp
llsdserialize_xml.cpp
llsdutil.cpp
llsecondlifeurls.cpp
+ llsingleton.cpp
llstat.cpp
+ llstacktrace.cpp
llstreamtools.cpp
llstring.cpp
llstringtable.cpp
@@ -76,6 +109,8 @@ set(llcommon_HEADER_FILES
indra_constants.h
linden_common.h
linked_lists.h
+ llallocator.h
+ llallocator_heap_profile.h
llagentconstants.h
llapp.h
llapr.h
@@ -88,6 +123,7 @@ set(llcommon_HEADER_FILES
llchat.h
llclickaction.h
llcommon.h
+ llcoros.h
llcrc.h
llcriticaldamp.h
llcursortypes.h
@@ -95,8 +131,12 @@ set(llcommon_HEADER_FILES
lldarrayptr.h
lldate.h
lldefs.h
+ lldependencies.h
+ lldeleteutils.h
lldepthstack.h
+ lldictionary.h
lldlinked.h
+ lldoubledispatch.h
lldqueueptr.h
llendianswizzle.h
llenum.h
@@ -105,19 +145,29 @@ set(llcommon_HEADER_FILES
llerrorlegacy.h
llerrorthread.h
llevent.h
+ lleventapi.h
+ lleventcoro.h
+ lleventdispatcher.h
+ lleventfilter.h
+ llevents.h
lleventemitter.h
llextendedstatus.h
llfasttimer.h
llfile.h
llfindlocale.h
llfixedbuffer.h
+ llfoldertype.h
llformat.h
llframetimer.h
llhash.h
llheartbeat.h
llhttpstatuscodes.h
llindexedqueue.h
+ llinstancetracker.h
+ llinstancetracker.h
llkeythrottle.h
+ lllazy.h
+ lllistenerwrapper.h
lllinkedqueue.h
llliveappconfig.h
lllivefile.h
@@ -132,23 +182,32 @@ set(llcommon_HEADER_FILES
llmetrics.h
llmortician.h
llnametable.h
+ lloptioninterface.h
+ llpointer.h
llpreprocessor.h
llpriqueuemap.h
+ llprocesslauncher.h
llprocessor.h
llptrskiplist.h
llptrskipmap.h
+ llptrto.h
llqueuedthread.h
llrand.h
+ llrefcount.h
llrun.h
+ llrefcount.h
+ llsafehandle.h
llsd.h
llsdserialize.h
llsdserialize_xml.h
llsdutil.h
llsecondlifeurls.h
llsimplehash.h
+ llsingleton.h
llskiplist.h
llskipmap.h
llstack.h
+ llstacktrace.h
llstat.h
llstatenums.h
llstl.h
@@ -159,12 +218,14 @@ set(llcommon_HEADER_FILES
llsys.h
llthread.h
lltimer.h
+ lltreeiterators.h
lluri.h
lluuid.h
lluuidhashmap.h
llversionserver.h
llversionviewer.h
llworkerthread.h
+ ll_template_cast.h
metaclass.h
metaclasst.h
metaproperty.h
@@ -176,6 +237,7 @@ set(llcommon_HEADER_FILES
stdenums.h
stdtypes.h
string_table.h
+ stringize.h
timer.h
timing.h
u64.h
@@ -186,11 +248,63 @@ set_source_files_properties(${llcommon_HEADER_FILES}
list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES})
-add_library (llcommon ${llcommon_SOURCE_FILES})
+if(LLCOMMON_LINK_SHARED)
+ add_library (llcommon SHARED ${llcommon_SOURCE_FILES})
+ if(NOT WORD_SIZE EQUAL 32)
+ if(WINDOWS)
+ add_definitions(/FIXED:NO)
+ else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
+ add_definitions(-fPIC)
+ endif(WINDOWS)
+ endif(NOT WORD_SIZE EQUAL 32)
+ ll_stage_sharedlib(llcommon)
+else(LLCOMMON_LINK_SHARED)
+ add_library (llcommon ${llcommon_SOURCE_FILES})
+endif(LLCOMMON_LINK_SHARED)
+
target_link_libraries(
llcommon
${APRUTIL_LIBRARIES}
${APR_LIBRARIES}
${EXPAT_LIBRARIES}
${ZLIB_LIBRARIES}
+ ${WINDOWS_LIBRARIES}
+ ${BOOST_PROGRAM_OPTIONS_LIBRARY}
+ ${BOOST_REGEX_LIBRARY}
+ ${PTH_LIBRARIES}
+ ${GOOGLE_PERFTOOLS_LIBRARIES}
+ )
+
+add_dependencies(llcommon stage_third_party_libs)
+
+if (LL_TESTS)
+ include(LLAddBuildTest)
+ SET(llcommon_TEST_SOURCE_FILES
+ # unit-testing llcommon is not possible right now as the test-harness *itself* depends upon llcommon, causing a circular dependency. Add your 'unit' tests as integration tests for now.
)
+ LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}")
+
+ #set(TEST_DEBUG on)
+ set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES} ${GOOGLEMOCK_LIBRARIES})
+ LL_ADD_INTEGRATION_TEST(commonmisc "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(bitpack "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(llbase64 "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(lldate "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(lldependencies "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(llerror "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(llframetimer "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(llinstancetracker "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(lluri "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(reflection "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}")
+
+ # *TODO - reenable these once tcmalloc libs no longer break the build.
+ #ADD_BUILD_TEST(llallocator llcommon)
+ #ADD_BUILD_TEST(llallocator_heap_profile llcommon)
+ #ADD_BUILD_TEST(llmemtype llcommon)
+endif (LL_TESTS)
diff --git a/indra/llcommon/bitpack.cpp b/indra/llcommon/bitpack.cpp
new file mode 100644
index 0000000000..8db403febf
--- /dev/null
+++ b/indra/llcommon/bitpack.cpp
@@ -0,0 +1,36 @@
+/**
+ * @file bitpack.cpp
+ * @brief LLBitPack class implementation
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+// implementation is all in the header, this include dep ensures the unit test is rerun if the implementation changes.
+#include "bitpack.h"
diff --git a/indra/llcommon/imageids.cpp b/indra/llcommon/imageids.cpp
new file mode 100644
index 0000000000..f48bb1374d
--- /dev/null
+++ b/indra/llcommon/imageids.cpp
@@ -0,0 +1,76 @@
+/**
+ * @file imageids.cpp
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "imageids.h"
+
+#include "lluuid.h"
+
+//
+// USE OF THIS FILE IS DEPRECATED
+//
+// Please use viewerart.ini and the standard
+// art import path. // indicates if file is only
+ // on dataserver, or also
+ // pre-cached on viewer
+
+// Grass Images
+const LLUUID IMG_SMOKE ("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d"); // VIEWER
+
+const LLUUID IMG_DEFAULT ("d2114404-dd59-4a4d-8e6c-49359e91bbf0"); // VIEWER
+
+const LLUUID IMG_SUN ("cce0f112-878f-4586-a2e2-a8f104bba271"); // dataserver
+const LLUUID IMG_MOON ("d07f6eed-b96a-47cd-b51d-400ad4a1c428"); // dataserver
+const LLUUID IMG_CLOUD_POOF ("fc4b9f0b-d008-45c6-96a4-01dd947ac621"); // dataserver
+const LLUUID IMG_SHOT ("35f217a3-f618-49cf-bbca-c86d486551a9"); // dataserver
+const LLUUID IMG_SPARK ("d2e75ac1-d0fb-4532-820e-a20034ac814d"); // dataserver
+const LLUUID IMG_FIRE ("aca40aa8-44cf-44ca-a0fa-93e1a2986f82"); // dataserver
+const LLUUID IMG_FACE_SELECT ("a85ac674-cb75-4af6-9499-df7c5aaf7a28"); // face selector
+const LLUUID IMG_DEFAULT_AVATAR ("c228d1cf-4b5d-4ba8-84f4-899a0796aa97"); // dataserver
+const LLUUID IMG_INVISIBLE ("3a367d1c-bef1-6d43-7595-e88c1e3aadb3"); // dataserver
+
+const LLUUID IMG_EXPLOSION ("68edcf47-ccd7-45b8-9f90-1649d7f12806"); // On dataserver
+const LLUUID IMG_EXPLOSION_2 ("21ce046c-83fe-430a-b629-c7660ac78d7c"); // On dataserver
+const LLUUID IMG_EXPLOSION_3 ("fedea30a-1be8-47a6-bc06-337a04a39c4b"); // On dataserver
+const LLUUID IMG_EXPLOSION_4 ("abf0d56b-82e5-47a2-a8ad-74741bb2c29e"); // On dataserver
+const LLUUID IMG_SMOKE_POOF ("1e63e323-5fe0-452e-92f8-b98bd0f764e3"); // On dataserver
+
+const LLUUID IMG_BIG_EXPLOSION_1 ("5e47a0dc-97bf-44e0-8b40-de06718cee9d"); // On dataserver
+const LLUUID IMG_BIG_EXPLOSION_2 ("9c8eca51-53d5-42a7-bb58-cef070395db8"); // On dataserver
+
+const LLUUID IMG_BLOOM1 ("3c59f7fe-9dc8-47f9-8aaf-a9dd1fbc3bef"); // VIEWER
+const LLUUID TERRAIN_DIRT_DETAIL ("0bc58228-74a0-7e83-89bc-5c23464bcec5"); // VIEWER
+const LLUUID TERRAIN_GRASS_DETAIL ("63338ede-0037-c4fd-855b-015d77112fc8"); // VIEWER
+const LLUUID TERRAIN_MOUNTAIN_DETAIL ("303cd381-8560-7579-23f1-f0a880799740"); // VIEWER
+const LLUUID TERRAIN_ROCK_DETAIL ("53a2f406-4895-1d13-d541-d2e3b86bc19c"); // VIEWER
+
+const LLUUID DEFAULT_WATER_NORMAL ("822ded49-9a6c-f61c-cb89-6df54f42cdf4"); // VIEWER
diff --git a/indra/llcommon/imageids.h b/indra/llcommon/imageids.h
index 832708c782..dc726dcf53 100644
--- a/indra/llcommon/imageids.h
+++ b/indra/llcommon/imageids.h
@@ -33,46 +33,43 @@
#ifndef LL_IMAGEIDS_H
#define LL_IMAGEIDS_H
-#include "lluuid.h"
-
//
// USE OF THIS FILE IS DEPRECATED
//
// Please use viewerart.ini and the standard
-// art import path. // indicates if file is only
- // on dataserver, or also
- // pre-cached on viewer
+// art import path.
+
+class LLUUID;
-// Grass Images
-const LLUUID IMG_SMOKE ("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d"); // VIEWER
+LL_COMMON_API extern const LLUUID IMG_SMOKE;
-const LLUUID IMG_DEFAULT ("d2114404-dd59-4a4d-8e6c-49359e91bbf0"); // VIEWER
+LL_COMMON_API extern const LLUUID IMG_DEFAULT;
-const LLUUID IMG_SUN ("cce0f112-878f-4586-a2e2-a8f104bba271"); // dataserver
-const LLUUID IMG_MOON ("d07f6eed-b96a-47cd-b51d-400ad4a1c428"); // dataserver
-const LLUUID IMG_CLOUD_POOF ("fc4b9f0b-d008-45c6-96a4-01dd947ac621"); // dataserver
-const LLUUID IMG_SHOT ("35f217a3-f618-49cf-bbca-c86d486551a9"); // dataserver
-const LLUUID IMG_SPARK ("d2e75ac1-d0fb-4532-820e-a20034ac814d"); // dataserver
-const LLUUID IMG_FIRE ("aca40aa8-44cf-44ca-a0fa-93e1a2986f82"); // dataserver
-const LLUUID IMG_FACE_SELECT ("a85ac674-cb75-4af6-9499-df7c5aaf7a28"); // face selector
-const LLUUID IMG_DEFAULT_AVATAR ("c228d1cf-4b5d-4ba8-84f4-899a0796aa97"); // dataserver
-const LLUUID IMG_INVISIBLE ("3a367d1c-bef1-6d43-7595-e88c1e3aadb3"); // dataserver
+LL_COMMON_API extern const LLUUID IMG_SUN;
+LL_COMMON_API extern const LLUUID IMG_MOON;
+LL_COMMON_API extern const LLUUID IMG_CLOUD_POOF;
+LL_COMMON_API extern const LLUUID IMG_SHOT;
+LL_COMMON_API extern const LLUUID IMG_SPARK;
+LL_COMMON_API extern const LLUUID IMG_FIRE;
+LL_COMMON_API extern const LLUUID IMG_FACE_SELECT;
+LL_COMMON_API extern const LLUUID IMG_DEFAULT_AVATAR;
+LL_COMMON_API extern const LLUUID IMG_INVISIBLE;
-const LLUUID IMG_EXPLOSION ("68edcf47-ccd7-45b8-9f90-1649d7f12806"); // On dataserver
-const LLUUID IMG_EXPLOSION_2 ("21ce046c-83fe-430a-b629-c7660ac78d7c"); // On dataserver
-const LLUUID IMG_EXPLOSION_3 ("fedea30a-1be8-47a6-bc06-337a04a39c4b"); // On dataserver
-const LLUUID IMG_EXPLOSION_4 ("abf0d56b-82e5-47a2-a8ad-74741bb2c29e"); // On dataserver
-const LLUUID IMG_SMOKE_POOF ("1e63e323-5fe0-452e-92f8-b98bd0f764e3"); // On dataserver
+LL_COMMON_API extern const LLUUID IMG_EXPLOSION;
+LL_COMMON_API extern const LLUUID IMG_EXPLOSION_2;
+LL_COMMON_API extern const LLUUID IMG_EXPLOSION_3;
+LL_COMMON_API extern const LLUUID IMG_EXPLOSION_4;
+LL_COMMON_API extern const LLUUID IMG_SMOKE_POOF;
-const LLUUID IMG_BIG_EXPLOSION_1 ("5e47a0dc-97bf-44e0-8b40-de06718cee9d"); // On dataserver
-const LLUUID IMG_BIG_EXPLOSION_2 ("9c8eca51-53d5-42a7-bb58-cef070395db8"); // On dataserver
+LL_COMMON_API extern const LLUUID IMG_BIG_EXPLOSION_1;
+LL_COMMON_API extern const LLUUID IMG_BIG_EXPLOSION_2;
-const LLUUID IMG_BLOOM1 ("3c59f7fe-9dc8-47f9-8aaf-a9dd1fbc3bef"); // VIEWER
-const LLUUID TERRAIN_DIRT_DETAIL ("0bc58228-74a0-7e83-89bc-5c23464bcec5"); // VIEWER
-const LLUUID TERRAIN_GRASS_DETAIL ("63338ede-0037-c4fd-855b-015d77112fc8"); // VIEWER
-const LLUUID TERRAIN_MOUNTAIN_DETAIL ("303cd381-8560-7579-23f1-f0a880799740"); // VIEWER
-const LLUUID TERRAIN_ROCK_DETAIL ("53a2f406-4895-1d13-d541-d2e3b86bc19c"); // VIEWER
+LL_COMMON_API extern const LLUUID IMG_BLOOM1;
+LL_COMMON_API extern const LLUUID TERRAIN_DIRT_DETAIL;
+LL_COMMON_API extern const LLUUID TERRAIN_GRASS_DETAIL;
+LL_COMMON_API extern const LLUUID TERRAIN_MOUNTAIN_DETAIL;
+LL_COMMON_API extern const LLUUID TERRAIN_ROCK_DETAIL;
-const LLUUID DEFAULT_WATER_NORMAL ("822ded49-9a6c-f61c-cb89-6df54f42cdf4"); // VIEWER
+LL_COMMON_API extern const LLUUID DEFAULT_WATER_NORMAL;
#endif
diff --git a/indra/llcommon/indra_constants.cpp b/indra/llcommon/indra_constants.cpp
new file mode 100644
index 0000000000..8a1290d4dc
--- /dev/null
+++ b/indra/llcommon/indra_constants.cpp
@@ -0,0 +1,46 @@
+/**
+ * @file indra_constants.cpp
+ * @brief some useful short term constants for Indra
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+
+#include "indra_constants.h"
+
+#include "lluuid.h"
+
+// "agent id" for things that should be done to ALL agents
+const LLUUID LL_UUID_ALL_AGENTS("44e87126-e794-4ded-05b3-7c42da3d5cdb");
+
+// Governor Linden's agent id.
+const LLUUID ALEXANDRIA_LINDEN_ID("ba2a564a-f0f1-4b82-9c61-b7520bfcd09f");
+const LLUUID GOVERNOR_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1");
+const LLUUID REALESTATE_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1");
+// Maintenance's group id.
+const LLUUID MAINTENANCE_GROUP_ID("dc7b21cd-3c89-fcaa-31c8-25f9ffd224cd");
diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h
index c0b0d72d9b..d4a07d77cc 100644
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -34,7 +34,8 @@
#define LL_INDRA_CONSTANTS_H
#include "stdtypes.h"
-#include "lluuid.h"
+
+class LLUUID;
// At 45 Hz collisions seem stable and objects seem
// to settle down at a reasonable rate.
@@ -46,7 +47,7 @@
#define PHYSICS_TIMESTEP (1.f / 45.f)
const F32 COLLISION_TOLERANCE = 0.1f;
-const F32 HALF_COLLISION_TOLERANCE = COLLISION_TOLERANCE * 0.5f;
+const F32 HALF_COLLISION_TOLERANCE = 0.05f;
// Time constants
const U32 HOURS_PER_LINDEN_DAY = 4;
@@ -97,9 +98,9 @@ const F32 MIN_AGENT_WIDTH = 0.40f;
const F32 DEFAULT_AGENT_WIDTH = 0.60f;
const F32 MAX_AGENT_WIDTH = 0.80f;
-const F32 MIN_AGENT_HEIGHT = 1.3f - 2.0f * COLLISION_TOLERANCE;
+const F32 MIN_AGENT_HEIGHT = 1.1f;
const F32 DEFAULT_AGENT_HEIGHT = 1.9f;
-const F32 MAX_AGENT_HEIGHT = 2.65f - 2.0f * COLLISION_TOLERANCE;
+const F32 MAX_AGENT_HEIGHT = 2.45f;
// For linked sets
const S32 MAX_CHILDREN_PER_TASK = 255;
@@ -253,6 +254,10 @@ const U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT;
// group constants
const S32 MAX_AGENT_GROUPS = 25;
+// attachment constants
+const S32 MAX_AGENT_ATTACHMENTS = 38;
+const U8 ATTACHMENT_ADD = 0x80;
+
// god levels
const U8 GOD_MAINTENANCE = 250;
const U8 GOD_FULL = 200;
@@ -262,14 +267,15 @@ const U8 GOD_LIKE = 1;
const U8 GOD_NOT = 0;
// "agent id" for things that should be done to ALL agents
-const LLUUID LL_UUID_ALL_AGENTS("44e87126-e794-4ded-05b3-7c42da3d5cdb");
+LL_COMMON_API extern const LLUUID LL_UUID_ALL_AGENTS;
+
+// inventory library owner
+LL_COMMON_API extern const LLUUID ALEXANDRIA_LINDEN_ID;
-// Governor Linden's agent id.
-const LLUUID ALEXANDRIA_LINDEN_ID("ba2a564a-f0f1-4b82-9c61-b7520bfcd09f");
-const LLUUID GOVERNOR_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1");
-const LLUUID REALESTATE_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1");
+LL_COMMON_API extern const LLUUID GOVERNOR_LINDEN_ID;
+LL_COMMON_API extern const LLUUID REALESTATE_LINDEN_ID;
// Maintenance's group id.
-const LLUUID MAINTENANCE_GROUP_ID("dc7b21cd-3c89-fcaa-31c8-25f9ffd224cd");
+LL_COMMON_API extern const LLUUID MAINTENANCE_GROUP_ID;
// Flags for kick message
const U32 KICK_FLAGS_DEFAULT = 0x0;
@@ -286,6 +292,7 @@ const U8 UPD_UNIFORM = 0x10; // used with UPD_SCALE
// Agent Update Flags (U8)
const U8 AU_FLAGS_NONE = 0x00;
const U8 AU_FLAGS_HIDETITLE = 0x01;
+const U8 AU_FLAGS_CLIENT_AUTOPILOT = 0x02;
// start location constants
const U32 START_LOCATION_ID_LAST = 0;
diff --git a/indra/llcommon/is_approx_equal_fraction.h b/indra/llcommon/is_approx_equal_fraction.h
index f95b148590..d369fbc5b3 100644
--- a/indra/llcommon/is_approx_equal_fraction.h
+++ b/indra/llcommon/is_approx_equal_fraction.h
@@ -7,7 +7,30 @@
* making llcommon depend on llmath.
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
* Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
diff --git a/indra/llcommon/linden_common.h b/indra/llcommon/linden_common.h
index f9d5877ab2..771af01279 100644
--- a/indra/llcommon/linden_common.h
+++ b/indra/llcommon/linden_common.h
@@ -33,6 +33,11 @@
#ifndef LL_LINDEN_COMMON_H
#define LL_LINDEN_COMMON_H
+// *NOTE: Please keep includes here to a minimum!
+//
+// Files included here are included in every library .cpp file and
+// are not precompiled.
+
#if defined(LL_WINDOWS) && defined(_DEBUG)
# if _MSC_VER >= 1400 // Visual C++ 2005 or later
# define _CRTDBG_MAP_ALLOC
@@ -51,42 +56,36 @@
#include <cstdio>
#include <cstdlib>
#include <ctime>
-#include <iostream>
-#include <fstream>
+#include <iosfwd>
-// Work Microsoft compiler warnings
+// Work around Microsoft compiler warnings in STL headers
#ifdef LL_WINDOWS
#pragma warning (disable : 4702) // unreachable code
#pragma warning (disable : 4244) // conversion from time_t to S32
#endif // LL_WINDOWS
-#include <algorithm>
+// *TODO: Eliminate these, most library .cpp files don't need them.
+// Add them to llviewerprecompiledheaders.h if necessary.
#include <list>
#include <map>
#include <vector>
#include <string>
#ifdef LL_WINDOWS
-#pragma warning (3 : 4702) // we like level 3, not 4
-// level 4 warnings that we need to disable:
-#pragma warning (disable : 4100) // unreferenced formal parameter
-#pragma warning (disable : 4127) // conditional expression is constant (e.g. while(1) )
-#pragma warning (disable : 4244) // possible loss of data on conversions
-#pragma warning (disable : 4396) // the inline specifier cannot be used when a friend declaration refers to a specialization of a function template
-#pragma warning (disable : 4512) // assignment operator could not be generated
-#pragma warning (disable : 4706) // assignment within conditional (even if((x = y)) )
+// Reenable warnings we disabled above
+#pragma warning (3 : 4702) // unreachable code, we like level 3, not 4
+// moved msvc warnings to llpreprocessor.h *TODO - delete this comment after merge conflicts are unlikely -brad
#endif // LL_WINDOWS
// Linden only libs in alpha-order other than stdtypes.h
+// *NOTE: Please keep includes here to a minimum, see above.
#include "stdtypes.h"
#include "lldefs.h"
#include "llerror.h"
#include "llextendedstatus.h"
-#include "llfasttimer.h"
+// Don't do this, adds 15K lines of header code to every library file.
+//#include "llfasttimer.h"
#include "llfile.h"
#include "llformat.h"
-#include "llstring.h"
-#include "llsys.h"
-#include "lltimer.h"
#endif
diff --git a/indra/llcommon/ll_template_cast.h b/indra/llcommon/ll_template_cast.h
new file mode 100644
index 0000000000..cff58ce00d
--- /dev/null
+++ b/indra/llcommon/ll_template_cast.h
@@ -0,0 +1,160 @@
+/**
+ * @file ll_template_cast.h
+ * @author Nat Goodspeed
+ * @date 2009-11-21
+ * @brief Define ll_template_cast function
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LL_TEMPLATE_CAST_H)
+#define LL_LL_TEMPLATE_CAST_H
+
+/**
+ * Implementation for ll_template_cast() (q.v.).
+ *
+ * Default implementation: trying to cast two completely unrelated types
+ * returns 0. Typically you'd specify T and U as pointer types, but in fact T
+ * can be any type that can be initialized with 0.
+ */
+template <typename T, typename U>
+struct ll_template_cast_impl
+{
+ T operator()(U)
+ {
+ return 0;
+ }
+};
+
+/**
+ * ll_template_cast<T>(some_value) is for use in a template function when
+ * some_value might be of arbitrary type, but you want to recognize type T
+ * specially.
+ *
+ * It's designed for use with pointer types. Example:
+ * @code
+ * struct SpecialClass
+ * {
+ * void someMethod(const std::string&) const;
+ * };
+ *
+ * template <class REALCLASS>
+ * void somefunc(const REALCLASS& instance)
+ * {
+ * const SpecialClass* ptr = ll_template_cast<const SpecialClass*>(&instance);
+ * if (ptr)
+ * {
+ * ptr->someMethod("Call method only available on SpecialClass");
+ * }
+ * }
+ * @endcode
+ *
+ * Why is this better than dynamic_cast<>? Because unless OtherClass is
+ * polymorphic, the following won't even compile (gcc 4.0.1):
+ * @code
+ * OtherClass other;
+ * SpecialClass* ptr = dynamic_cast<SpecialClass*>(&other);
+ * @endcode
+ * to say nothing of this:
+ * @code
+ * void function(int);
+ * SpecialClass* ptr = dynamic_cast<SpecialClass*>(&function);
+ * @endcode
+ * ll_template_cast handles these kinds of cases by returning 0.
+ */
+template <typename T, typename U>
+T ll_template_cast(U value)
+{
+ return ll_template_cast_impl<T, U>()(value);
+}
+
+/**
+ * Implementation for ll_template_cast() (q.v.).
+ *
+ * Implementation for identical types: return same value.
+ */
+template <typename T>
+struct ll_template_cast_impl<T, T>
+{
+ T operator()(T value)
+ {
+ return value;
+ }
+};
+
+/**
+ * LL_TEMPLATE_CONVERTIBLE(dest, source) asserts that, for a value @c s of
+ * type @c source, <tt>ll_template_cast<dest>(s)</tt> will return @c s --
+ * presuming that @c source can be converted to @c dest by the normal rules of
+ * C++.
+ *
+ * By default, <tt>ll_template_cast<dest>(s)</tt> will return 0 unless @c s's
+ * type is literally identical to @c dest. (This is because of the
+ * straightforward application of template specialization rules.) That can
+ * lead to surprising results, e.g.:
+ *
+ * @code
+ * Foo myFoo;
+ * const Foo* fooptr = ll_template_cast<const Foo*>(&myFoo);
+ * @endcode
+ *
+ * Here @c fooptr will be 0 because <tt>&myFoo</tt> is of type <tt>Foo*</tt>
+ * -- @em not <tt>const Foo*</tt>. (Declaring <tt>const Foo myFoo;</tt> would
+ * force the compiler to do the right thing.)
+ *
+ * More disappointingly:
+ * @code
+ * struct Base {};
+ * struct Subclass: public Base {};
+ * Subclass object;
+ * Base* ptr = ll_template_cast<Base*>(&object);
+ * @endcode
+ *
+ * Here @c ptr will be 0 because <tt>&object</tt> is of type
+ * <tt>Subclass*</tt> rather than <tt>Base*</tt>. We @em want this cast to
+ * succeed, but without our help ll_template_cast can't recognize it.
+ *
+ * The following would suffice:
+ * @code
+ * LL_TEMPLATE_CONVERTIBLE(Base*, Subclass*);
+ * ...
+ * Base* ptr = ll_template_cast<Base*>(&object);
+ * @endcode
+ *
+ * However, as noted earlier, this is easily fooled:
+ * @code
+ * const Base* ptr = ll_template_cast<const Base*>(&object);
+ * @endcode
+ * would still produce 0 because we haven't yet seen:
+ * @code
+ * LL_TEMPLATE_CONVERTIBLE(const Base*, Subclass*);
+ * @endcode
+ *
+ * @TODO
+ * This macro should use Boost type_traits facilities for stripping and
+ * re-adding @c const and @c volatile qualifiers so that invoking
+ * LL_TEMPLATE_CONVERTIBLE(dest, source) will automatically generate all
+ * permitted permutations. It's really not fair to the coder to require
+ * separate:
+ * @code
+ * LL_TEMPLATE_CONVERTIBLE(Base*, Subclass*);
+ * LL_TEMPLATE_CONVERTIBLE(const Base*, Subclass*);
+ * LL_TEMPLATE_CONVERTIBLE(const Base*, const Subclass*);
+ * @endcode
+ *
+ * (Naturally we omit <tt>LL_TEMPLATE_CONVERTIBLE(Base*, const Subclass*)</tt>
+ * because that's not permitted by normal C++ assignment anyway.)
+ */
+#define LL_TEMPLATE_CONVERTIBLE(DEST, SOURCE) \
+template <> \
+struct ll_template_cast_impl<DEST, SOURCE> \
+{ \
+ DEST operator()(SOURCE wrapper) \
+ { \
+ return wrapper; \
+ } \
+}
+
+#endif /* ! defined(LL_LL_TEMPLATE_CAST_H) */
diff --git a/indra/llcommon/llallocator.cpp b/indra/llcommon/llallocator.cpp
new file mode 100644
index 0000000000..eed9d1e7db
--- /dev/null
+++ b/indra/llcommon/llallocator.cpp
@@ -0,0 +1,140 @@
+/**
+ * @file llallocator.cpp
+ * @brief Implementation of the LLAllocator class.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llallocator.h"
+
+#if LL_USE_TCMALLOC
+
+#include "google/heap-profiler.h"
+#include "google/commandlineflags_public.h"
+
+DECLARE_bool(heap_profile_use_stack_trace);
+//DECLARE_double(tcmalloc_release_rate);
+
+// static
+void LLAllocator::pushMemType(S32 type)
+{
+ if(isProfiling())
+ {
+ PushMemType(type);
+ }
+}
+
+// static
+S32 LLAllocator::popMemType()
+{
+ if (isProfiling())
+ {
+ return PopMemType();
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+void LLAllocator::setProfilingEnabled(bool should_enable)
+{
+ // NULL disables dumping to disk
+ static char const * const PREFIX = NULL;
+ if(should_enable)
+ {
+ HeapProfilerSetUseStackTrace(false);
+ HeapProfilerStart(PREFIX);
+ }
+ else
+ {
+ HeapProfilerStop();
+ }
+}
+
+// static
+bool LLAllocator::isProfiling()
+{
+ return IsHeapProfilerRunning();
+}
+
+std::string LLAllocator::getRawProfile()
+{
+ // *TODO - fix google-perftools to accept an buffer to avoid this
+ // malloc-copy-free cycle.
+ char * buffer = GetHeapProfile();
+ std::string ret = buffer;
+ free(buffer);
+ return ret;
+}
+
+#else // LL_USE_TCMALLOC
+
+//
+// stub implementations for when tcmalloc is disabled
+//
+
+// static
+void LLAllocator::pushMemType(S32 type)
+{
+}
+
+// static
+S32 LLAllocator::popMemType()
+{
+ return -1;
+}
+
+void LLAllocator::setProfilingEnabled(bool should_enable)
+{
+}
+
+// static
+bool LLAllocator::isProfiling()
+{
+ return false;
+}
+
+std::string LLAllocator::getRawProfile()
+{
+ return std::string();
+}
+
+#endif // LL_USE_TCMALLOC
+
+LLAllocatorHeapProfile const & LLAllocator::getProfile()
+{
+ mProf.mLines.clear();
+
+ // *TODO - avoid making all these extra copies of things...
+ std::string prof_text = getRawProfile();
+ //std::cout << prof_text << std::endl;
+ mProf.parse(prof_text);
+ return mProf;
+}
diff --git a/indra/llcommon/llallocator.h b/indra/llcommon/llallocator.h
new file mode 100644
index 0000000000..50129b4526
--- /dev/null
+++ b/indra/llcommon/llallocator.h
@@ -0,0 +1,63 @@
+/**
+ * @file llallocator.h
+ * @brief Declaration of the LLAllocator class.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLALLOCATOR_H
+#define LL_LLALLOCATOR_H
+
+#include <string>
+
+#include "llmemtype.h"
+#include "llallocator_heap_profile.h"
+
+class LL_COMMON_API LLAllocator {
+ friend class LLMemoryView;
+ friend class LLMemType;
+
+private:
+ static void pushMemType(S32 type);
+ static S32 popMemType();
+
+public:
+ void setProfilingEnabled(bool should_enable);
+
+ static bool isProfiling();
+
+ LLAllocatorHeapProfile const & getProfile();
+
+private:
+ std::string getRawProfile();
+
+private:
+ LLAllocatorHeapProfile mProf;
+};
+
+#endif // LL_LLALLOCATOR_H
diff --git a/indra/llcommon/llallocator_heap_profile.cpp b/indra/llcommon/llallocator_heap_profile.cpp
new file mode 100644
index 0000000000..0a807702d0
--- /dev/null
+++ b/indra/llcommon/llallocator_heap_profile.cpp
@@ -0,0 +1,150 @@
+/**
+ * @file llallocator_heap_profile.cpp
+ * @brief Implementation of the parser for tcmalloc heap profile data.
+ * @author Brad Kittenbrink
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llallocator_heap_profile.h"
+
+#if LL_MSVC
+// disable warning about boost::lexical_cast returning uninitialized data
+// when it fails to parse the string
+#pragma warning (disable:4701)
+#pragma warning (disable:4702)
+#endif
+
+#include <boost/algorithm/string/split.hpp>
+#include <boost/bind.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/range/iterator_range.hpp>
+
+static const std::string HEAP_PROFILE_MAGIC_STR = "heap profile:";
+
+static bool is_separator(char c)
+{
+ return isspace(c) || c == '[' || c == ']' || c == ':';
+}
+
+void LLAllocatorHeapProfile::parse(std::string const & prof_text)
+{
+ // a typedef for handling a token in the string buffer
+ // it's a begin/end pair of string::const_iterators
+ typedef boost::iterator_range<std::string::const_iterator> range_t;
+
+ mLines.clear();
+
+ if(prof_text.compare(0, HEAP_PROFILE_MAGIC_STR.length(), HEAP_PROFILE_MAGIC_STR) != 0)
+ {
+ // *TODO - determine if there should be some better error state than
+ // mLines being empty. -brad
+ llwarns << "invalid heap profile data passed into parser." << llendl;
+ return;
+ }
+
+ std::vector< range_t > prof_lines;
+
+ std::string::const_iterator prof_begin = prof_text.begin() + HEAP_PROFILE_MAGIC_STR.length();
+
+ range_t prof_range(prof_begin, prof_text.end());
+ boost::algorithm::split(prof_lines,
+ prof_range,
+ boost::bind(std::equal_to<llwchar>(), '\n', _1));
+
+ std::vector< range_t >::const_iterator i;
+ for(i = prof_lines.begin(); i != prof_lines.end() && !i->empty(); ++i)
+ {
+ range_t const & line_text = *i;
+
+ std::vector<range_t> line_elems;
+
+ boost::algorithm::split(line_elems,
+ line_text,
+ is_separator);
+
+ std::vector< range_t >::iterator j;
+ j = line_elems.begin();
+
+ while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
+ llassert_always(j != line_elems.end());
+ U32 live_count = boost::lexical_cast<U32>(*j);
+ ++j;
+
+ while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
+ llassert_always(j != line_elems.end());
+ U64 live_size = boost::lexical_cast<U64>(*j);
+ ++j;
+
+ while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
+ llassert_always(j != line_elems.end());
+ U32 tot_count = boost::lexical_cast<U32>(*j);
+ ++j;
+
+ while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
+ llassert_always(j != line_elems.end());
+ U64 tot_size = boost::lexical_cast<U64>(*j);
+ ++j;
+
+ while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
+ llassert_always(j != line_elems.end());
+ ++j; // skip the '@'
+
+ mLines.push_back(line(live_count, live_size, tot_count, tot_size));
+ line & current_line = mLines.back();
+
+ for(; j != line_elems.end(); ++j)
+ {
+ if(!j->empty()) {
+ U32 marker = boost::lexical_cast<U32>(*j);
+ current_line.mTrace.push_back(marker);
+ }
+ }
+ }
+
+ // *TODO - parse MAPPED_LIBRARIES section here if we're ever interested in it
+}
+
+void LLAllocatorHeapProfile::dump(std::ostream & out) const
+{
+ lines_t::const_iterator i;
+ for(i = mLines.begin(); i != mLines.end(); ++i)
+ {
+ out << i->mLiveCount << ": " << i->mLiveSize << '[' << i->mTotalCount << ": " << i->mTotalSize << "] @";
+
+ stack_trace::const_iterator j;
+ for(j = i->mTrace.begin(); j != i->mTrace.end(); ++j)
+ {
+ out << ' ' << *j;
+ }
+ out << '\n';
+ }
+ out.flush();
+}
+
diff --git a/indra/llcommon/llallocator_heap_profile.h b/indra/llcommon/llallocator_heap_profile.h
new file mode 100644
index 0000000000..19758df544
--- /dev/null
+++ b/indra/llcommon/llallocator_heap_profile.h
@@ -0,0 +1,77 @@
+/**
+ * @file llallocator_heap_profile.h
+ * @brief Declaration of the parser for tcmalloc heap profile data.
+ * @author Brad Kittenbrink
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLALLOCATOR_HEAP_PROFILE_H
+#define LL_LLALLOCATOR_HEAP_PROFILE_H
+
+#include "stdtypes.h"
+
+#include <map>
+#include <vector>
+
+class LLAllocatorHeapProfile
+{
+public:
+ typedef int stack_marker;
+
+ typedef std::vector<stack_marker> stack_trace;
+
+ struct line {
+ line(U32 live_count, U64 live_size, U32 tot_count, U64 tot_size) :
+ mLiveSize(live_size),
+ mTotalSize(tot_size),
+ mLiveCount(live_count),
+ mTotalCount(tot_count)
+ {
+ }
+ U64 mLiveSize, mTotalSize;
+ U32 mLiveCount, mTotalCount;
+ stack_trace mTrace;
+ };
+
+ typedef std::vector<line> lines_t;
+
+ LLAllocatorHeapProfile()
+ {
+ }
+
+ void parse(std::string const & prof_text);
+
+ void dump(std::ostream & out) const;
+
+public:
+ lines_t mLines;
+};
+
+
+#endif // LL_LLALLOCATOR_HEAP_PROFILE_H
diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h
index cc60ba0b80..27a52cdd99 100644
--- a/indra/llcommon/llapp.h
+++ b/indra/llcommon/llapp.h
@@ -34,13 +34,18 @@
#define LL_LLAPP_H
#include <map>
-#include "llapr.h"
#include "llrun.h"
#include "llsd.h"
+#include "lloptioninterface.h"
// Forward declarations
+template <typename Type> class LLAtomic32;
+typedef LLAtomic32<U32> LLAtomicU32;
class LLErrorThread;
class LLLiveFile;
+#if LL_LINUX
+typedef struct siginfo siginfo_t;
+#endif
typedef void (*LLAppErrorHandler)();
typedef void (*LLAppChildCallback)(int pid, bool exited, int status);
@@ -61,7 +66,7 @@ public:
};
#endif
-class LLApp
+class LL_COMMON_API LLApp : public LLOptionInterface
{
friend class LLErrorThread;
public:
@@ -110,7 +115,7 @@ public:
* @param name The name of the option.
* @return Returns the option data.
*/
- LLSD getOption(const std::string& name) const;
+ virtual LLSD getOption(const std::string& name) const;
/**
* @brief Parse command line options and insert them into
@@ -201,8 +206,6 @@ public:
#if !LL_WINDOWS
static U32 getSigChildCount();
static void incSigChildCount();
-#else
-#define getpid GetCurrentProcessId
#endif
static int getPid();
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index 669afc5330..ed70b1d9f2 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -57,7 +57,7 @@ void ll_init_apr()
if(!LLAPRFile::sAPRFilePoolp)
{
- LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool() ;
+ LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ;
}
}
@@ -99,13 +99,12 @@ void ll_cleanup_apr()
//
//LLAPRPool
//
-LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag)
-{
- mParent = parent ;
- mReleasePoolFlag = releasePoolFlag ;
- mMaxSize = size ;
- mPool = NULL ;
-
+LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag)
+ : mParent(parent),
+ mReleasePoolFlag(releasePoolFlag),
+ mMaxSize(size),
+ mPool(NULL)
+{
createAPRPool() ;
}
@@ -148,31 +147,65 @@ void LLAPRPool::releaseAPRPool()
}
}
+//virtual
apr_pool_t* LLAPRPool::getAPRPool()
+{
+ return mPool ;
+}
+
+LLVolatileAPRPool::LLVolatileAPRPool(BOOL is_local, apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag)
+ : LLAPRPool(parent, size, releasePoolFlag),
+ mNumActiveRef(0),
+ mNumTotalRef(0),
+ mMutexPool(NULL),
+ mMutexp(NULL)
{
- if(!mPool)
+ //create mutex
+ if(!is_local) //not a local apr_pool, that is: shared by multiple threads.
{
- createAPRPool() ;
+ apr_pool_create(&mMutexPool, NULL); // Create a pool for mutex
+ apr_thread_mutex_create(&mMutexp, APR_THREAD_MUTEX_UNNESTED, mMutexPool);
}
-
- return mPool ;
}
-LLVolatileAPRPool::LLVolatileAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag)
- : LLAPRPool(parent, size, releasePoolFlag)
+
+LLVolatileAPRPool::~LLVolatileAPRPool()
{
- mNumActiveRef = 0 ;
- mNumTotalRef = 0 ;
+ //delete mutex
+ if(mMutexp)
+ {
+ apr_thread_mutex_destroy(mMutexp);
+ apr_pool_destroy(mMutexPool);
+ }
}
-apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool()
+//
+//define this virtual function to avoid any mistakenly calling LLAPRPool::getAPRPool().
+//
+//virtual
+apr_pool_t* LLVolatileAPRPool::getAPRPool()
{
+ return LLVolatileAPRPool::getVolatileAPRPool() ;
+}
+
+apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool()
+{
+ LLScopedLock lock(mMutexp) ;
+
mNumTotalRef++ ;
mNumActiveRef++ ;
- return getAPRPool() ;
+
+ if(!mPool)
+ {
+ createAPRPool() ;
+ }
+
+ return mPool ;
}
void LLVolatileAPRPool::clearVolatileAPRPool()
{
+ LLScopedLock lock(mMutexp) ;
+
if(mNumActiveRef > 0)
{
mNumActiveRef--;
@@ -251,10 +284,9 @@ void LLScopedLock::unlock()
bool ll_apr_warn_status(apr_status_t status)
{
if(APR_SUCCESS == status) return false;
-#ifndef LL_WINDOWS
char buf[MAX_STRING]; /* Flawfinder: ignore */
- LL_WARNS_ONCE("APR") << "APR: " << apr_strerror(status, buf, MAX_STRING) << LL_ENDL;
-#endif
+ apr_strerror(status, buf, MAX_STRING);
+ LL_WARNS("APR") << "APR: " << buf << LL_ENDL;
return true;
}
@@ -268,10 +300,18 @@ void ll_apr_assert_status(apr_status_t status)
// LLAPRFile functions
//
LLAPRFile::LLAPRFile()
+ : mFile(NULL),
+ mCurrentFilePoolp(NULL)
+{
+}
+
+LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool)
+ : mFile(NULL),
+ mCurrentFilePoolp(NULL)
{
- mFile = NULL ;
- mCurrentFilePoolp = NULL ;
+ open(filename, flags, pool);
}
+
LLAPRFile::~LLAPRFile()
{
close() ;
@@ -295,11 +335,40 @@ apr_status_t LLAPRFile::close()
return ret ;
}
-apr_status_t LLAPRFile::open(LLVolatileAPRPool* pool, const std::string& filename, apr_int32_t flags, S32* sizep)
+apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool, S32* sizep)
{
apr_status_t s ;
- s = open(filename, flags, pool ? pool->getVolatileAPRPool() : NULL, sizep) ;
+
+ //check if already open some file
+ llassert_always(!mFile) ;
+ llassert_always(!mCurrentFilePoolp) ;
+ apr_pool_t* apr_pool = pool ? pool->getVolatileAPRPool() : NULL ;
+ s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, getAPRFilePool(apr_pool));
+
+ if (s != APR_SUCCESS || !mFile)
+ {
+ mFile = NULL ;
+
+ if (sizep)
+ {
+ *sizep = 0;
+ }
+ }
+ else if (sizep)
+ {
+ S32 file_size = 0;
+ apr_off_t offset = 0;
+ if (apr_file_seek(mFile, APR_END, &offset) == APR_SUCCESS)
+ {
+ llassert_always(offset <= 0x7fffffff);
+ file_size = (S32)offset;
+ offset = 0;
+ apr_file_seek(mFile, APR_SET, &offset);
+ }
+ *sizep = file_size;
+ }
+
if(!mCurrentFilePoolp)
{
mCurrentFilePoolp = pool ;
@@ -312,40 +381,25 @@ apr_status_t LLAPRFile::open(LLVolatileAPRPool* pool, const std::string& filenam
return s ;
}
-apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, apr_pool_t* pool, S32* sizep)
+
+//use gAPRPoolp.
+apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool)
{
apr_status_t s;
//check if already open some file
llassert_always(!mFile) ;
llassert_always(!mCurrentFilePoolp) ;
+ llassert_always(use_global_pool) ; //be aware of using gAPRPoolp.
- s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, getAPRFilePool(pool));
+ s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, gAPRPoolp);
if (s != APR_SUCCESS || !mFile)
{
mFile = NULL ;
close() ;
- if (sizep)
- {
- *sizep = 0;
- }
return s;
}
- if (sizep)
- {
- S32 file_size = 0;
- apr_off_t offset = 0;
- if (apr_file_seek(mFile, APR_END, &offset) == APR_SUCCESS)
- {
- llassert_always(offset <= 0x7fffffff);
- file_size = (S32)offset;
- offset = 0;
- apr_file_seek(mFile, APR_SET, &offset);
- }
- *sizep = file_size;
- }
-
return s;
}
@@ -369,6 +423,7 @@ S32 LLAPRFile::read(void *buf, S32 nbytes)
apr_status_t s = apr_file_read(mFile, buf, &sz);
if (s != APR_SUCCESS)
{
+ ll_apr_warn_status(s);
return 0;
}
else
@@ -386,6 +441,7 @@ S32 LLAPRFile::write(const void *buf, S32 nbytes)
apr_status_t s = apr_file_write(mFile, buf, &sz);
if (s != APR_SUCCESS)
{
+ ll_apr_warn_status(s);
return 0;
}
else
@@ -434,6 +490,8 @@ apr_file_t* LLAPRFile::open(const std::string& filename, LLVolatileAPRPool* pool
s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool());
if (s != APR_SUCCESS || !file_handle)
{
+ ll_apr_warn_status(s);
+ LL_WARNS("APR") << " Attempting to open filename: " << filename << LL_ENDL;
file_handle = NULL ;
close(file_handle, pool) ;
return NULL;
@@ -464,6 +522,7 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
}
if (s != APR_SUCCESS)
{
+ ll_apr_warn_status(s);
return -1;
}
else
@@ -501,6 +560,8 @@ S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nb
apr_status_t s = apr_file_read(file_handle, buf, &bytes_read);
if (s != APR_SUCCESS)
{
+ LL_WARNS("APR") << " Attempting to read filename: " << filename << LL_ENDL;
+ ll_apr_warn_status(s);
bytes_read = 0;
}
else
@@ -549,6 +610,8 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n
apr_status_t s = apr_file_write(file_handle, buf, &bytes_written);
if (s != APR_SUCCESS)
{
+ LL_WARNS("APR") << " Attempting to write filename: " << filename << LL_ENDL;
+ ll_apr_warn_status(s);
bytes_written = 0;
}
else
@@ -575,8 +638,8 @@ bool LLAPRFile::remove(const std::string& filename, LLVolatileAPRPool* pool)
if (s != APR_SUCCESS)
{
- LL_DEBUGS("APR") << "LLAPRFile::remove failed on file: " << filename << LL_ENDL;
ll_apr_warn_status(s);
+ LL_WARNS("APR") << " Attempting to remove filename: " << filename << LL_ENDL;
return false;
}
return true;
@@ -593,8 +656,8 @@ bool LLAPRFile::rename(const std::string& filename, const std::string& newname,
if (s != APR_SUCCESS)
{
- LL_DEBUGS("APR") << "LLAPRFile::rename failed on file: " << filename << LL_ENDL;
ll_apr_warn_status(s);
+ LL_WARNS("APR") << " Attempting to rename filename: " << filename << LL_ENDL;
return false;
}
return true;
@@ -667,8 +730,8 @@ bool LLAPRFile::makeDir(const std::string& dirname, LLVolatileAPRPool* pool)
if (s != APR_SUCCESS)
{
- LL_DEBUGS("APR") << "LLAPRFile::makeDir failed on file: " << dirname << LL_ENDL;
ll_apr_warn_status(s);
+ LL_WARNS("APR") << " Attempting to make directory: " << dirname << LL_ENDL;
return false;
}
return true;
@@ -685,8 +748,8 @@ bool LLAPRFile::removeDir(const std::string& dirname, LLVolatileAPRPool* pool)
if (s != APR_SUCCESS)
{
- LL_DEBUGS("APR") << "LLAPRFile::removeDir failed on file: " << dirname << LL_ENDL;
ll_apr_warn_status(s);
+ LL_WARNS("APR") << " Attempting to remove directory: " << dirname << LL_ENDL;
return false;
}
return true;
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 63130a89fc..b05a222b33 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -38,6 +38,14 @@
#if LL_LINUX || LL_SOLARIS
#include <sys/param.h> // Need PATH_MAX in APR headers...
#endif
+#if LL_WINDOWS
+ // Limit Windows API to small and manageable set.
+ // If you get undefined symbols, find the appropriate
+ // Windows header file and include that in your .cpp file.
+ #define WIN32_LEAN_AND_MEAN
+ #include <winsock2.h>
+ #include <windows.h>
+#endif
#include <boost/noncopyable.hpp>
@@ -48,31 +56,31 @@
#include "apr_atomic.h"
#include "llstring.h"
-extern apr_thread_mutex_t* gLogMutexp;
+extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp;
extern apr_thread_mutex_t* gCallStacksLogMutexp;
/**
* @brief initialize the common apr constructs -- apr itself, the
* global pool, and a mutex.
*/
-void ll_init_apr();
+void LL_COMMON_API ll_init_apr();
/**
* @brief Cleanup those common apr constructs.
*/
-void ll_cleanup_apr();
+void LL_COMMON_API ll_cleanup_apr();
//
//LL apr_pool
//manage apr_pool_t, destroy allocated apr_pool in the destruction function.
//
-class LLAPRPool
+class LL_COMMON_API LLAPRPool
{
public:
LLAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE) ;
- ~LLAPRPool() ;
+ virtual ~LLAPRPool() ;
- apr_pool_t* getAPRPool() ;
+ virtual apr_pool_t* getAPRPool() ;
apr_status_t getStatus() {return mStatus ; }
protected:
@@ -92,21 +100,24 @@ protected:
//which clears memory automatically.
//so it can not hold static data or data after memory is cleared
//
-class LLVolatileAPRPool : public LLAPRPool
+class LL_COMMON_API LLVolatileAPRPool : public LLAPRPool
{
public:
- LLVolatileAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE);
- ~LLVolatileAPRPool(){}
+ LLVolatileAPRPool(BOOL is_local = TRUE, apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE);
+ virtual ~LLVolatileAPRPool();
- apr_pool_t* getVolatileAPRPool() ;
-
+ /*virtual*/ apr_pool_t* getAPRPool() ; //define this virtual function to avoid any mistakenly calling LLAPRPool::getAPRPool().
+ apr_pool_t* getVolatileAPRPool() ;
void clearVolatileAPRPool() ;
BOOL isFull() ;
- BOOL isEmpty() {return !mNumActiveRef ;}
+
private:
S32 mNumActiveRef ; //number of active pointers pointing to the apr_pool.
- S32 mNumTotalRef ; //number of total pointers pointing to the apr_pool since last creating.
+ S32 mNumTotalRef ; //number of total pointers pointing to the apr_pool since last creating.
+
+ apr_thread_mutex_t *mMutexp;
+ apr_pool_t *mMutexPool;
} ;
/**
@@ -118,7 +129,7 @@ private:
* destructor handles the unlock. Instances of this class are
* <b>not</b> thread safe.
*/
-class LLScopedLock : private boost::noncopyable
+class LL_COMMON_API LLScopedLock : private boost::noncopyable
{
public:
/**
@@ -192,18 +203,21 @@ typedef LLAtomic32<S32> LLAtomicS32;
// 1, a temperary pool passed to an APRFile function, which is used within this function and only once.
// 2, a global pool.
//
-class LLAPRFile
+
+class LL_COMMON_API LLAPRFile : boost::noncopyable
{
+ // make this non copyable since a copy closes the file
private:
apr_file_t* mFile ;
LLVolatileAPRPool *mCurrentFilePoolp ; //currently in use apr_pool, could be one of them: sAPRFilePoolp, or a temp pool.
public:
LLAPRFile() ;
+ LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL);
~LLAPRFile() ;
-
- apr_status_t open(LLVolatileAPRPool* pool, const std::string& filename, apr_int32_t flags, S32* sizep = NULL);
- apr_status_t open(const std::string& filename, apr_int32_t flags, apr_pool_t* pool = NULL, S32* sizep = NULL);
+
+ apr_status_t open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL, S32* sizep = NULL);
+ apr_status_t open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool); //use gAPRPoolp.
apr_status_t close() ;
// Returns actual offset, -1 if seek fails
@@ -217,8 +231,8 @@ public:
apr_file_t* getFileHandle() {return mFile;}
private:
- apr_pool_t* getAPRFilePool(apr_pool_t* pool) ;
-
+ apr_pool_t* getAPRFilePool(apr_pool_t* pool) ;
+
//
//*******************************************************************************************************************************
//static components
@@ -250,10 +264,10 @@ public:
* APR_SUCCESS.
* @return Returns <code>true</code> if status is an error condition.
*/
-bool ll_apr_warn_status(apr_status_t status);
+bool LL_COMMON_API ll_apr_warn_status(apr_status_t status);
-void ll_apr_assert_status(apr_status_t status);
+void LL_COMMON_API ll_apr_assert_status(apr_status_t status);
-extern "C" apr_pool_t* gAPRPoolp; // Global APR memory pool
+extern "C" LL_COMMON_API apr_pool_t* gAPRPoolp; // Global APR memory pool
#endif // LL_LLAPR_H
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp
index cf3bf89b4f..6d5b12d840 100644
--- a/indra/llcommon/llassettype.cpp
+++ b/indra/llcommon/llassettype.cpp
@@ -33,235 +33,195 @@
#include "linden_common.h"
#include "llassettype.h"
+#include "lldictionary.h"
+#include "llmemory.h"
+#include "llsingleton.h"
-#include "llstring.h"
-#include "lltimer.h"
+///----------------------------------------------------------------------------
+/// Class LLAssetType
+///----------------------------------------------------------------------------
+struct AssetEntry : public LLDictionaryEntry
+{
+ AssetEntry(const char *desc_name,
+ const char *type_name, // 8 character limit!
+ const char *human_name, // for decoding to human readable form; put any and as many printable characters you want in each one
+ bool can_link) // can you create a link to this type?
+ :
+ LLDictionaryEntry(desc_name),
+ mTypeName(type_name),
+ mHumanName(human_name),
+ mCanLink(can_link)
+ {
+ llassert(strlen(mTypeName) <= 8);
+ }
-// I added lookups for exact text of asset type enums in addition to the ones below, so shoot me. -Steve
+ const char *mTypeName;
+ const char *mHumanName;
+ bool mCanLink;
+};
-struct asset_info_t
+class LLAssetDictionary : public LLSingleton<LLAssetDictionary>,
+ public LLDictionary<LLAssetType::EType, AssetEntry>
{
- LLAssetType::EType type;
- const char* desc;
+public:
+ LLAssetDictionary();
};
-asset_info_t asset_types[] =
+LLAssetDictionary::LLAssetDictionary()
{
- { LLAssetType::AT_TEXTURE, "TEXTURE" },
- { LLAssetType::AT_SOUND, "SOUND" },
- { LLAssetType::AT_CALLINGCARD, "CALLINGCARD" },
- { LLAssetType::AT_LANDMARK, "LANDMARK" },
- { LLAssetType::AT_SCRIPT, "SCRIPT" },
- { LLAssetType::AT_CLOTHING, "CLOTHING" },
- { LLAssetType::AT_OBJECT, "OBJECT" },
- { LLAssetType::AT_NOTECARD, "NOTECARD" },
- { LLAssetType::AT_CATEGORY, "CATEGORY" },
- { LLAssetType::AT_ROOT_CATEGORY, "ROOT_CATEGORY" },
- { LLAssetType::AT_LSL_TEXT, "LSL_TEXT" },
- { LLAssetType::AT_LSL_BYTECODE, "LSL_BYTECODE" },
- { LLAssetType::AT_TEXTURE_TGA, "TEXTURE_TGA" },
- { LLAssetType::AT_BODYPART, "BODYPART" },
- { LLAssetType::AT_TRASH, "TRASH" },
- { LLAssetType::AT_SNAPSHOT_CATEGORY, "SNAPSHOT_CATEGORY" },
- { LLAssetType::AT_LOST_AND_FOUND, "LOST_AND_FOUND" },
- { LLAssetType::AT_SOUND_WAV, "SOUND_WAV" },
- { LLAssetType::AT_IMAGE_TGA, "IMAGE_TGA" },
- { LLAssetType::AT_IMAGE_JPEG, "IMAGE_JPEG" },
- { LLAssetType::AT_ANIMATION, "ANIMATION" },
- { LLAssetType::AT_GESTURE, "GESTURE" },
- { LLAssetType::AT_SIMSTATE, "SIMSTATE" },
- { LLAssetType::AT_NONE, "NONE" },
+ // DESCRIPTION TYPE NAME HUMAN NAME CAN LINK?
+ // |--------------------|-----------|-------------------|-----------|
+ addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", FALSE));
+ addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", FALSE));
+ addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", FALSE));
+ addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", FALSE));
+ addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", FALSE));
+ addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", TRUE));
+ addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", TRUE));
+ addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", FALSE));
+ addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", TRUE));
+ addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", FALSE));
+ addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", FALSE));
+ addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", FALSE));
+ addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", TRUE));
+ addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", FALSE));
+ addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", FALSE));
+ addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", FALSE));
+ addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", FALSE));
+ addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", TRUE));
+ addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", FALSE));
+
+ addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "symbolic link", FALSE));
+ addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "symbolic folder link", FALSE));
+
+ addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE));
};
-LLAssetType::EType LLAssetType::getType(const std::string& sin)
+// static
+LLAssetType::EType LLAssetType::getType(const std::string& desc_name)
{
- std::string s = sin;
+ std::string s = desc_name;
LLStringUtil::toUpper(s);
- for (S32 idx = 0; ;idx++)
- {
- asset_info_t* info = asset_types + idx;
- if (info->type == LLAssetType::AT_NONE)
- break;
- if (s == info->desc)
- return info->type;
- }
- return LLAssetType::AT_NONE;
+ return LLAssetDictionary::getInstance()->lookup(s);
}
-std::string LLAssetType::getDesc(LLAssetType::EType type)
+// static
+const std::string &LLAssetType::getDesc(LLAssetType::EType asset_type)
{
- for (S32 idx = 0; ;idx++)
+ const AssetEntry *entry = LLAssetDictionary::getInstance()->lookup(asset_type);
+ if (entry)
+ {
+ return entry->mName;
+ }
+ else
{
- asset_info_t* info = asset_types + idx;
- if (type == info->type)
- return info->desc;
- if (info->type == LLAssetType::AT_NONE)
- break;
+ return badLookup();
}
- return "BAD TYPE";
}
-//============================================================================
-
-// The asset type names are limited to 8 characters.
-// static
-const char* LLAssetType::mAssetTypeNames[LLAssetType::AT_COUNT] =
-{
- "texture",
- "sound",
- "callcard",
- "landmark",
- "script",
- "clothing",
- "object",
- "notecard",
- "category",
- "root",
- "lsltext",
- "lslbyte",
- "txtr_tga",// Intentionally spelled this way. Limited to eight characters.
- "bodypart",
- "trash",
- "snapshot",
- "lstndfnd",
- "snd_wav",
- "img_tga",
- "jpeg",
- "animatn",
- "gesture",
- "simstate"
-};
-
-// This table is meant for decoding to human readable form. Put any
-// and as many printable characters you want in each one.
-// See also llinventory.cpp INVENTORY_TYPE_HUMAN_NAMES
-const char* LLAssetType::mAssetTypeHumanNames[LLAssetType::AT_COUNT] =
-{
- "texture",
- "sound",
- "calling card",
- "landmark",
- "legacy script",
- "clothing",
- "object",
- "note card",
- "folder",
- "root",
- "lsl2 script",
- "lsl bytecode",
- "tga texture",
- "body part",
- "trash",
- "snapshot",
- "lost and found",
- "sound",
- "targa image",
- "jpeg image",
- "animation",
- "gesture",
- "simstate"
-};
-
-///----------------------------------------------------------------------------
-/// class LLAssetType
-///----------------------------------------------------------------------------
-
// static
-const char* LLAssetType::lookup( LLAssetType::EType type )
+const char *LLAssetType::lookup(LLAssetType::EType asset_type)
{
- if( (type >= 0) && (type < AT_COUNT ))
+ const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
+ const AssetEntry *entry = dict->lookup(asset_type);
+ if (entry)
{
- return mAssetTypeNames[ S32( type ) ];
+ return entry->mTypeName;
}
else
{
- return "-1";
+ return badLookup().c_str();
}
}
// static
-LLAssetType::EType LLAssetType::lookup( const char* name )
+LLAssetType::EType LLAssetType::lookup(const char* name)
{
return lookup(ll_safe_string(name));
}
-LLAssetType::EType LLAssetType::lookup( const std::string& name )
+// static
+LLAssetType::EType LLAssetType::lookup(const std::string& type_name)
{
- for( S32 i = 0; i < AT_COUNT; i++ )
+ const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
+ for (LLAssetDictionary::const_iterator iter = dict->begin();
+ iter != dict->end();
+ iter++)
{
- if( name == mAssetTypeNames[i] )
+ const AssetEntry *entry = iter->second;
+ if (type_name == entry->mTypeName)
{
- // match
- return (EType)i;
+ return iter->first;
}
}
return AT_NONE;
}
// static
-const char* LLAssetType::lookupHumanReadable(LLAssetType::EType type)
+const char *LLAssetType::lookupHumanReadable(LLAssetType::EType asset_type)
{
- if( (type >= 0) && (type < AT_COUNT ))
+ const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
+ const AssetEntry *entry = dict->lookup(asset_type);
+ if (entry)
{
- return mAssetTypeHumanNames[S32(type)];
+ return entry->mHumanName;
}
else
{
- return NULL;
+ return badLookup().c_str();
}
}
// static
-LLAssetType::EType LLAssetType::lookupHumanReadable( const char* name )
+LLAssetType::EType LLAssetType::lookupHumanReadable(const char* name)
{
return lookupHumanReadable(ll_safe_string(name));
}
-LLAssetType::EType LLAssetType::lookupHumanReadable( const std::string& name )
+// static
+LLAssetType::EType LLAssetType::lookupHumanReadable(const std::string& readable_name)
{
- for( S32 i = 0; i < AT_COUNT; i++ )
+ const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
+ for (LLAssetDictionary::const_iterator iter = dict->begin();
+ iter != dict->end();
+ iter++)
{
- if( name == mAssetTypeHumanNames[i] )
+ const AssetEntry *entry = iter->second;
+ if (entry->mHumanName && (readable_name == entry->mHumanName))
{
- // match
- return (EType)i;
+ return iter->first;
}
}
return AT_NONE;
}
-EDragAndDropType LLAssetType::lookupDragAndDropType( EType asset )
+// static
+bool LLAssetType::lookupCanLink(EType asset_type)
{
- switch( asset )
+ const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
+ const AssetEntry *entry = dict->lookup(asset_type);
+ if (entry)
{
- case AT_TEXTURE: return DAD_TEXTURE;
- case AT_SOUND: return DAD_SOUND;
- case AT_CALLINGCARD: return DAD_CALLINGCARD;
- case AT_LANDMARK: return DAD_LANDMARK;
- case AT_SCRIPT: return DAD_NONE;
- case AT_CLOTHING: return DAD_CLOTHING;
- case AT_OBJECT: return DAD_OBJECT;
- case AT_NOTECARD: return DAD_NOTECARD;
- case AT_CATEGORY: return DAD_CATEGORY;
- case AT_ROOT_CATEGORY: return DAD_ROOT_CATEGORY;
- case AT_LSL_TEXT: return DAD_SCRIPT;
- case AT_BODYPART: return DAD_BODYPART;
- case AT_ANIMATION: return DAD_ANIMATION;
- case AT_GESTURE: return DAD_GESTURE;
- default: return DAD_NONE;
- };
+ return entry->mCanLink;
+ }
+ return false;
}
-// static. Generate a good default description
-void LLAssetType::generateDescriptionFor(LLAssetType::EType type,
- std::string& desc)
+// static
+// Not adding this to dictionary since we probably will only have these two types
+bool LLAssetType::lookupIsLinkType(EType asset_type)
+{
+ if (asset_type == AT_LINK || asset_type == AT_LINK_FOLDER)
+ {
+ return true;
+ }
+ return false;
+}
+
+// static
+const std::string &LLAssetType::badLookup()
{
- const S32 BUF_SIZE = 30;
- char time_str[BUF_SIZE]; /* Flawfinder: ignore */
- time_t now;
- time(&now);
- memset(time_str, '\0', BUF_SIZE);
- strftime(time_str, BUF_SIZE - 1, "%Y-%m-%d %H:%M:%S ", localtime(&now));
- desc.assign(time_str);
- desc.append(LLAssetType::lookupHumanReadable(type));
+ static const std::string sBadLookup = "llassettype_bad_lookup";
+ return sBadLookup;
+
}
diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index 4077b8d2c1..c7bbc2e74a 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -30,149 +30,127 @@
* $/LicenseInfo$
*/
-#ifndef LL_LLASSETTYPE
-#define LL_LLASSETTYPE
+#ifndef LL_LLASSETTYPE_H
+#define LL_LLASSETTYPE_H
#include <string>
#include "stdenums.h" // for EDragAndDropType
-class LLAssetType
+class LL_COMMON_API LLAssetType
{
public:
enum EType
{
- // Used for painting the faces of geometry.
- // Stored in typical j2c stream format
AT_TEXTURE = 0,
+ // Used for painting the faces of geometry.
+ // Stored in typical j2c stream format.
- // Used to fill the aural spectrum.
AT_SOUND = 1,
+ // Used to fill the aural spectrum.
- // Links instant message access to the user on the card. eg, a
- // card for yourself, a card for linden support, a card for
- // the guy you were talking to in the coliseum.
AT_CALLINGCARD = 2,
+ // Links instant message access to the user on the card.
+ // : E.G. A card for yourself, for linden support, for
+ // : the guy you were talking to in the coliseum.
- // Links to places in the world with location and a screen
- // shot or image saved. eg, home, linden headquarters, the
- // coliseum, or destinations where we want to increase
- // traffic.
AT_LANDMARK = 3,
+ // Links to places in the world with location and a screen shot or image saved.
+ // : E.G. Home, linden headquarters, the coliseum, destinations where
+ // : we want to increase traffic.
- // Valid scripts that can be attached to an object. eg. open a
- // door, jump into the air.
AT_SCRIPT = 4,
+ // Valid scripts that can be attached to an object.
+ // : E.G. Open a door, jump into the air.
- // A collection of textures and parameters that can be worn
- // by an avatar.
AT_CLOTHING = 5,
+ // A collection of textures and parameters that can be worn by an avatar.
- // Any combination of textures, sounds, and scripts that are
- // associated with a fixed piece of geometry. eg, a hot tub, a
- // house with working door.
AT_OBJECT = 6,
+ // Any combination of textures, sounds, and scripts that are
+ // associated with a fixed piece of geometry.
+ // : E.G. A hot tub, a house with working door.
- // Just text
AT_NOTECARD = 7,
+ // Just text.
- // A category holds a collection of inventory items. It's
- // treated as an item in the inventory, and therefore needs a
- // type.
AT_CATEGORY = 8,
+ // Holds a collection of inventory items.
+ // It's treated as an item in the inventory and therefore needs a type.
- // A root category is a user's root inventory category. We
- // decided to expose it visually, so it seems logical to fold
- // it into the asset types.
- AT_ROOT_CATEGORY = 9,
-
- // The LSL is the brand spanking new scripting language. We've
- // split it into a text and bytecode representation.
AT_LSL_TEXT = 10,
AT_LSL_BYTECODE = 11,
+ // The LSL is the scripting language.
+ // We've split it into a text and bytecode representation.
- // uncompressed TGA texture
AT_TEXTURE_TGA = 12,
+ // Uncompressed TGA texture.
- // A collection of textures and parameters that can be worn
- // by an avatar.
AT_BODYPART = 13,
+ // A collection of textures and parameters that can be worn by an avatar.
- // This asset type is meant to only be used as a marker for a
- // category preferred type. Using this, we can throw things in
- // the trash before completely deleting.
- AT_TRASH = 14,
-
- // This is a marker for a folder meant for snapshots. No
- // actual assets will be snapshots, though if there were, you
- // could interpret them as textures.
- AT_SNAPSHOT_CATEGORY = 15,
-
- // This is used to stuff lost&found items into
- AT_LOST_AND_FOUND = 16,
-
- // uncompressed sound
AT_SOUND_WAV = 17,
+ // Uncompressed sound.
- // uncompressed image, non-square, and not appropriate for use
- // as a texture.
AT_IMAGE_TGA = 18,
+ // Uncompressed image, non-square.
+ // Not appropriate for use as a texture.
- // compressed image, non-square, and not appropriate for use
- // as a texture.
AT_IMAGE_JPEG = 19,
+ // Compressed image, non-square.
+ // Not appropriate for use as a texture.
- // animation
AT_ANIMATION = 20,
+ // Animation.
- // gesture, sequence of animations, sounds, chat, wait steps
AT_GESTURE = 21,
+ // Gesture, sequence of animations, sounds, chat, wait steps.
- // simstate file
AT_SIMSTATE = 22,
+ // Simstate file.
- // +*********************************************+
- // | TO ADD AN ELEMENT TO THIS ENUM: |
- // +*********************************************+
- // | 1. INSERT BEFORE AT_COUNT |
- // | 2. INCREMENT AT_COUNT BY 1 |
- // | 3. ADD TO LLAssetType::mAssetTypeNames |
- // | 4. ADD TO LLAssetType::mAssetTypeHumanNames |
- // +*********************************************+
+ AT_LINK = 24,
+ // Inventory symbolic link
- AT_COUNT = 23,
+ AT_LINK_FOLDER = 25,
+ // Inventory folder link
+
+ AT_COUNT = 26,
+
+ // +*********************************************************+
+ // | TO ADD AN ELEMENT TO THIS ENUM: |
+ // +*********************************************************+
+ // | 1. INSERT BEFORE AT_COUNT |
+ // | 2. INCREMENT AT_COUNT BY 1 |
+ // | 3. ADD TO LLAssetType.cpp |
+ // | 4. ADD TO LLViewerAssetType.cpp |
+ // | 5. ADD TO DEFAULT_ASSET_FOR_INV in LLInventoryType.cpp |
+ // +*********************************************************+
AT_NONE = -1
};
// machine transation between type and strings
- static EType lookup(const char* name); // safe conversion to std::string, *TODO: deprecate
- static EType lookup(const std::string& name);
- static const char* lookup(EType type);
+ static EType lookup(const char* name); // safe conversion to std::string, *TODO: deprecate
+ static EType lookup(const std::string& type_name);
+ static const char* lookup(EType asset_type);
// translation from a type to a human readable form.
- static EType lookupHumanReadable( const char* name ); // safe conversion to std::string, *TODO: deprecate
- static EType lookupHumanReadable( const std::string& name );
- static const char* lookupHumanReadable(EType type);
-
- static EDragAndDropType lookupDragAndDropType( EType );
-
- // Generate a good default description. You may want to add a verb
- // or agent name after this depending on your application.
- static void generateDescriptionFor(LLAssetType::EType type,
- std::string& desc);
-
- static EType getType(const std::string& sin);
- static std::string getDesc(EType type);
-
-private:
- // don't instantiate or derive one of these objects
- LLAssetType( void ) {}
- ~LLAssetType( void ) {}
-
-private:
- static const char* mAssetTypeNames[];
- static const char* mAssetTypeHumanNames[];
+ static EType lookupHumanReadable(const char* desc_name); // safe conversion to std::string, *TODO: deprecate
+ static EType lookupHumanReadable(const std::string& readable_name);
+ static const char* lookupHumanReadable(EType asset_type);
+
+ static EType getType(const std::string& desc_name);
+ static const std::string& getDesc(EType asset_type);
+
+ static bool lookupCanLink(EType asset_type);
+ static bool lookupIsLinkType(EType asset_type);
+
+ static const std::string& badLookup(); // error string when a lookup fails
+
+protected:
+ LLAssetType() {}
+ ~LLAssetType() {}
};
-#endif // LL_LLASSETTYPE
+#endif // LL_LLASSETTYPE_H
diff --git a/indra/llcommon/llbase32.h b/indra/llcommon/llbase32.h
index 63a93e11ab..0697f7b8e2 100644
--- a/indra/llcommon/llbase32.h
+++ b/indra/llcommon/llbase32.h
@@ -32,9 +32,9 @@
*/
#ifndef LLBASE32_H
-#define LLBASE32_h
+#define LLBASE32_H
-class LLBase32
+class LL_COMMON_API LLBase32
{
public:
static std::string encode(const U8* input, size_t input_size);
diff --git a/indra/llcommon/llbase64.h b/indra/llcommon/llbase64.h
index 58414bba8b..c48fea2478 100644
--- a/indra/llcommon/llbase64.h
+++ b/indra/llcommon/llbase64.h
@@ -32,9 +32,9 @@
*/
#ifndef LLBASE64_H
-#define LLBASE64_h
+#define LLBASE64_H
-class LLBase64
+class LL_COMMON_API LLBase64
{
public:
static std::string encode(const U8* input, size_t input_size);
diff --git a/indra/llcommon/llboost.h b/indra/llcommon/llboost.h
index 4df9dbf3bd..c2bde3a097 100644
--- a/indra/llcommon/llboost.h
+++ b/indra/llcommon/llboost.h
@@ -46,4 +46,19 @@
*/
typedef boost::tokenizer<boost::char_separator<char> > boost_tokenizer;
+// Useful combiner for boost signals that return a bool (e.g. validation)
+// returns false if any of the callbacks return false
+struct boost_boolean_combiner
+{
+ typedef bool result_type;
+ template<typename InputIterator>
+ bool operator()(InputIterator first, InputIterator last) const
+ {
+ bool res = true;
+ while (first != last)
+ res &= *first++;
+ return res;
+ }
+};
+
#endif // LL_LLBOOST_H
diff --git a/indra/llcommon/llchat.h b/indra/llcommon/llchat.h
index 7b010d6739..5af7991006 100644
--- a/indra/llcommon/llchat.h
+++ b/indra/llcommon/llchat.h
@@ -65,6 +65,12 @@ typedef enum e_chat_audible_level
CHAT_AUDIBLE_FULLY = 1
} EChatAudible;
+typedef enum e_chat_style
+{
+ CHAT_STYLE_NORMAL,
+ CHAT_STYLE_IRC
+}EChatStyle;
+
// A piece of chat
class LLChat
{
@@ -78,8 +84,10 @@ public:
mAudible(CHAT_AUDIBLE_FULLY),
mMuted(FALSE),
mTime(0.0),
+ mTimeStr(),
mPosAgent(),
- mURL()
+ mURL(),
+ mChatStyle(CHAT_STYLE_NORMAL)
{ }
std::string mText; // UTF-8 line of text
@@ -90,8 +98,10 @@ public:
EChatAudible mAudible;
BOOL mMuted; // pass muted chat to maintain list of chatters
F64 mTime; // viewer only, seconds from viewer start
+ std::string mTimeStr;
LLVector3 mPosAgent;
std::string mURL;
+ EChatStyle mChatStyle;
};
#endif
diff --git a/indra/llcommon/llclickaction.h b/indra/llcommon/llclickaction.h
index 8048724575..d4ffbf8634 100644
--- a/indra/llcommon/llclickaction.h
+++ b/indra/llcommon/llclickaction.h
@@ -33,7 +33,7 @@
#ifndef LL_LLCLICKACTION_H
#define LL_LLCLICKACTION_H
-
+// DO NOT CHANGE THE SEQUENCE OF THIS LIST!!
const U8 CLICK_ACTION_NONE = 0;
const U8 CLICK_ACTION_TOUCH = 0;
const U8 CLICK_ACTION_SIT = 1;
@@ -42,5 +42,6 @@ const U8 CLICK_ACTION_PAY = 3;
const U8 CLICK_ACTION_OPEN = 4;
const U8 CLICK_ACTION_PLAY = 5;
const U8 CLICK_ACTION_OPEN_MEDIA = 6;
-
+const U8 CLICK_ACTION_ZOOM = 7;
+// DO NOT CHANGE THE SEQUENCE OF THIS LIST!!
#endif
diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp
index 2cbb71855f..36a0018995 100644
--- a/indra/llcommon/llcommon.cpp
+++ b/indra/llcommon/llcommon.cpp
@@ -32,6 +32,8 @@
#include "linden_common.h"
#include "llcommon.h"
+
+#include "llmemory.h"
#include "llthread.h"
//static
diff --git a/indra/llcommon/llcommon.h b/indra/llcommon/llcommon.h
index 5f77988336..05eef25b21 100644
--- a/indra/llcommon/llcommon.h
+++ b/indra/llcommon/llcommon.h
@@ -32,13 +32,11 @@
#ifndef LL_COMMON_H
#define LL_COMMON_H
-#include "llmemory.h"
-#include "llapr.h"
-// #include "llframecallbackmanager.h"
+// *TODO: remove these?
#include "lltimer.h"
#include "llfile.h"
-class LLCommon
+class LL_COMMON_API LLCommon
{
public:
static void initClass();
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
new file mode 100644
index 0000000000..377bfaa247
--- /dev/null
+++ b/indra/llcommon/llcoros.cpp
@@ -0,0 +1,137 @@
+/**
+ * @file llcoros.cpp
+ * @author Nat Goodspeed
+ * @date 2009-06-03
+ * @brief Implementation for llcoros.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llcoros.h"
+// STL headers
+// std headers
+// external library headers
+#include <boost/bind.hpp>
+// other Linden headers
+#include "llevents.h"
+#include "llerror.h"
+#include "stringize.h"
+
+LLCoros::LLCoros()
+{
+ // Register our cleanup() method for "mainloop" ticks
+ LLEventPumps::instance().obtain("mainloop").listen(
+ "LLCoros", boost::bind(&LLCoros::cleanup, this, _1));
+}
+
+bool LLCoros::cleanup(const LLSD&)
+{
+ // Walk the mCoros map, checking and removing completed coroutines.
+ for (CoroMap::iterator mi(mCoros.begin()), mend(mCoros.end()); mi != mend; )
+ {
+ // Has this coroutine exited (normal return, exception, exit() call)
+ // since last tick?
+ if (mi->second->exited())
+ {
+ LL_INFOS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << LL_ENDL;
+ // The erase() call will invalidate its passed iterator value --
+ // so increment mi FIRST -- but pass its original value to
+ // erase(). This is what postincrement is all about.
+ mCoros.erase(mi++);
+ }
+ else
+ {
+ // Still live, just skip this entry as if incrementing at the top
+ // of the loop as usual.
+ ++mi;
+ }
+ }
+ return false;
+}
+
+std::string LLCoros::generateDistinctName(const std::string& prefix) const
+{
+ // Allowing empty name would make getName()'s not-found return ambiguous.
+ if (prefix.empty())
+ {
+ LL_ERRS("LLCoros") << "LLCoros::launch(): pass non-empty name string" << LL_ENDL;
+ }
+
+ // If the specified name isn't already in the map, just use that.
+ std::string name(prefix);
+
+ // Find the lowest numeric suffix that doesn't collide with an existing
+ // entry. Start with 2 just to make it more intuitive for any interested
+ // parties: e.g. "joe", "joe2", "joe3"...
+ for (int i = 2; ; name = STRINGIZE(prefix << i++))
+ {
+ if (mCoros.find(name) == mCoros.end())
+ {
+ LL_INFOS("LLCoros") << "LLCoros: launching coroutine " << name << LL_ENDL;
+ return name;
+ }
+ }
+}
+
+bool LLCoros::kill(const std::string& name)
+{
+ CoroMap::iterator found = mCoros.find(name);
+ if (found == mCoros.end())
+ {
+ return false;
+ }
+ // Because this is a boost::ptr_map, erasing the map entry also destroys
+ // the referenced heap object, in this case the boost::coroutine object,
+ // which will terminate the coroutine.
+ mCoros.erase(found);
+ return true;
+}
+
+std::string LLCoros::getNameByID(const void* self_id) const
+{
+ // Walk the existing coroutines, looking for one from which the 'self_id'
+ // passed to us comes.
+ for (CoroMap::const_iterator mi(mCoros.begin()), mend(mCoros.end()); mi != mend; ++mi)
+ {
+ namespace coro_private = boost::coroutines::detail;
+ if (static_cast<void*>(coro_private::coroutine_accessor::get_impl(const_cast<coro&>(*mi->second)).get())
+ == self_id)
+ {
+ return mi->first;
+ }
+ }
+ return "";
+}
+
+/*****************************************************************************
+* MUST BE LAST
+*****************************************************************************/
+// Turn off MSVC optimizations for just LLCoros::launchImpl() -- see
+// DEV-32777. But MSVC doesn't support push/pop for optimization flags as it
+// does for warning suppression, and we really don't want to force
+// optimization ON for other code even in Debug or RelWithDebInfo builds.
+
+#if LL_MSVC
+// work around broken optimizations
+#pragma warning(disable: 4748)
+#pragma optimize("", off)
+#endif // LL_MSVC
+
+std::string LLCoros::launchImpl(const std::string& prefix, coro* newCoro)
+{
+ std::string name(generateDistinctName(prefix));
+ mCoros.insert(name, newCoro);
+ /* Run the coroutine until its first wait, then return here */
+ (*newCoro)(std::nothrow);
+ return name;
+}
+
+#if LL_MSVC
+// reenable optimizations
+#pragma optimize("", on)
+#endif // LL_MSVC
diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h
new file mode 100644
index 0000000000..141b0df43c
--- /dev/null
+++ b/indra/llcommon/llcoros.h
@@ -0,0 +1,149 @@
+/**
+ * @file llcoros.h
+ * @author Nat Goodspeed
+ * @date 2009-06-02
+ * @brief Manage running boost::coroutine instances
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLCOROS_H)
+#define LL_LLCOROS_H
+
+#include <boost/coroutine/coroutine.hpp>
+#include "llsingleton.h"
+#include <boost/ptr_container/ptr_map.hpp>
+#include <string>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#include <boost/preprocessor/iteration/local.hpp>
+#include <stdexcept>
+
+/**
+ * Registry of named Boost.Coroutine instances
+ *
+ * The Boost.Coroutine library supports the general case of a coroutine
+ * accepting arbitrary parameters and yielding multiple (sets of) results. For
+ * such use cases, it's natural for the invoking code to retain the coroutine
+ * instance: the consumer repeatedly calls into the coroutine, perhaps passing
+ * new parameter values, prompting it to yield its next result.
+ *
+ * Our typical coroutine usage is different, though. For us, coroutines
+ * provide an alternative to the @c Responder pattern. Our typical coroutine
+ * has @c void return, invoked in fire-and-forget mode: the handler for some
+ * user gesture launches the coroutine and promptly returns to the main loop.
+ * The coroutine initiates some action that will take multiple frames (e.g. a
+ * capability request), waits for its result, processes it and silently steals
+ * away.
+ *
+ * This usage poses two (related) problems:
+ *
+ * # Who should own the coroutine instance? If it's simply local to the
+ * handler code that launches it, return from the handler will destroy the
+ * coroutine object, terminating the coroutine.
+ * # Once the coroutine terminates, in whatever way, who's responsible for
+ * cleaning up the coroutine object?
+ *
+ * LLCoros is a Singleton collection of currently-active coroutine instances.
+ * Each has a name. You ask LLCoros to launch a new coroutine with a suggested
+ * name prefix; from your prefix it generates a distinct name, registers the
+ * new coroutine and returns the actual name.
+ *
+ * The name can be used to kill off the coroutine prematurely, if needed. It
+ * can also provide diagnostic info: we can look up the name of the
+ * currently-running coroutine.
+ *
+ * Finally, the next frame ("mainloop" event) after the coroutine terminates,
+ * LLCoros will notice its demise and destroy it.
+ */
+class LL_COMMON_API LLCoros: public LLSingleton<LLCoros>
+{
+public:
+ /// Canonical boost::coroutines::coroutine signature we use
+ typedef boost::coroutines::coroutine<void()> coro;
+ /// Canonical 'self' type
+ typedef coro::self self;
+
+ /**
+ * Create and start running a new coroutine with specified name. The name
+ * string you pass is a suggestion; it will be tweaked for uniqueness. The
+ * actual name is returned to you.
+ *
+ * Usage looks like this, for (e.g.) two coroutine parameters:
+ * @code
+ * class MyClass
+ * {
+ * public:
+ * ...
+ * // Do NOT NOT NOT accept reference params other than 'self'!
+ * // Pass by value only!
+ * void myCoroutineMethod(LLCoros::self& self, std::string, LLSD);
+ * ...
+ * };
+ * ...
+ * std::string name = LLCoros::instance().launch(
+ * "mycoro", boost::bind(&MyClass::myCoroutineMethod, this, _1,
+ * "somestring", LLSD(17));
+ * @endcode
+ *
+ * Your function/method must accept LLCoros::self& as its first parameter.
+ * It can accept any other parameters you want -- but ONLY BY VALUE!
+ * Other reference parameters are a BAD IDEA! You Have Been Warned. See
+ * DEV-32777 comments for an explanation.
+ *
+ * Pass a callable that accepts the single LLCoros::self& parameter. It
+ * may work to pass a free function whose only parameter is 'self'; for
+ * all other cases use boost::bind(). Of course, for a non-static class
+ * method, the first parameter must be the class instance. Use the
+ * placeholder _1 for the 'self' parameter. Any other parameters should be
+ * passed via the bind() expression.
+ *
+ * launch() tweaks the suggested name so it won't collide with any
+ * existing coroutine instance, creates the coroutine instance, registers
+ * it with the tweaked name and runs it until its first wait. At that
+ * point it returns the tweaked name.
+ */
+ template <typename CALLABLE>
+ std::string launch(const std::string& prefix, const CALLABLE& callable)
+ {
+ return launchImpl(prefix, new coro(callable));
+ }
+
+ /**
+ * Abort a running coroutine by name. Normally, when a coroutine either
+ * runs to completion or terminates with an exception, LLCoros quietly
+ * cleans it up. This is for use only when you must explicitly interrupt
+ * one prematurely. Returns @c true if the specified name was found and
+ * still running at the time.
+ */
+ bool kill(const std::string& name);
+
+ /**
+ * From within a coroutine, pass its @c self object to look up the
+ * (tweaked) name string by which this coroutine is registered. Returns
+ * the empty string if not found (e.g. if the coroutine was launched by
+ * hand rather than using LLCoros::launch()).
+ */
+ template <typename COROUTINE_SELF>
+ std::string getName(const COROUTINE_SELF& self) const
+ {
+ return getNameByID(self.get_id());
+ }
+
+ /// getName() by self.get_id()
+ std::string getNameByID(const void* self_id) const;
+
+private:
+ friend class LLSingleton<LLCoros>;
+ LLCoros();
+ std::string launchImpl(const std::string& prefix, coro* newCoro);
+ std::string generateDistinctName(const std::string& prefix) const;
+ bool cleanup(const LLSD&);
+
+ typedef boost::ptr_map<std::string, coro> CoroMap;
+ CoroMap mCoros;
+};
+
+#endif /* ! defined(LL_LLCOROS_H) */
diff --git a/indra/llcommon/llcrc.h b/indra/llcommon/llcrc.h
index 27fae7d269..74369062cc 100644
--- a/indra/llcommon/llcrc.h
+++ b/indra/llcommon/llcrc.h
@@ -50,7 +50,7 @@
// llinfos << "File crc: " << crc.getCRC() << llendl;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLCRC
+class LL_COMMON_API LLCRC
{
protected:
U32 mCurrent;
diff --git a/indra/llcommon/llcriticaldamp.h b/indra/llcommon/llcriticaldamp.h
index ad98284a6c..1ea5914b5b 100644
--- a/indra/llcommon/llcriticaldamp.h
+++ b/indra/llcommon/llcriticaldamp.h
@@ -38,7 +38,7 @@
#include "llframetimer.h"
-class LLCriticalDamp
+class LL_COMMON_API LLCriticalDamp
{
public:
LLCriticalDamp();
diff --git a/indra/llcommon/llcursortypes.cpp b/indra/llcommon/llcursortypes.cpp
index 7444115aa1..23ede97af3 100644
--- a/indra/llcommon/llcursortypes.cpp
+++ b/indra/llcommon/llcursortypes.cpp
@@ -30,6 +30,8 @@
* $/LicenseInfo$
*/
+#include "linden_common.h"
+
#include "llcursortypes.h"
ECursorType getCursorFromString(const std::string& cursor_string)
@@ -66,10 +68,6 @@ ECursorType getCursorFromString(const std::string& cursor_string)
cursor_string_table["UI_CURSOR_TOOLPAN"] = UI_CURSOR_TOOLPAN;
cursor_string_table["UI_CURSOR_TOOLZOOMIN"] = UI_CURSOR_TOOLZOOMIN;
cursor_string_table["UI_CURSOR_TOOLPICKOBJECT3"] = UI_CURSOR_TOOLPICKOBJECT3;
- cursor_string_table["UI_CURSOR_TOOLSIT"] = UI_CURSOR_TOOLSIT;
- cursor_string_table["UI_CURSOR_TOOLBUY"] = UI_CURSOR_TOOLBUY;
- cursor_string_table["UI_CURSOR_TOOLPAY"] = UI_CURSOR_TOOLPAY;
- cursor_string_table["UI_CURSOR_TOOLOPEN"] = UI_CURSOR_TOOLOPEN;
cursor_string_table["UI_CURSOR_TOOLPLAY"] = UI_CURSOR_TOOLPLAY;
cursor_string_table["UI_CURSOR_TOOLPAUSE"] = UI_CURSOR_TOOLPAUSE;
cursor_string_table["UI_CURSOR_TOOLMEDIAOPEN"] = UI_CURSOR_TOOLMEDIAOPEN;
diff --git a/indra/llcommon/llcursortypes.h b/indra/llcommon/llcursortypes.h
index bea70351b7..a1b8178bfe 100644
--- a/indra/llcommon/llcursortypes.h
+++ b/indra/llcommon/llcursortypes.h
@@ -33,8 +33,6 @@
#ifndef LL_LLCURSORTYPES_H
#define LL_LLCURSORTYPES_H
-#include "linden_common.h"
-
// If you add types here, add them in LLCursor::getCursorFromString
enum ECursorType {
UI_CURSOR_ARROW,
@@ -66,10 +64,6 @@ enum ECursorType {
UI_CURSOR_TOOLPAN,
UI_CURSOR_TOOLZOOMIN,
UI_CURSOR_TOOLPICKOBJECT3,
- UI_CURSOR_TOOLSIT,
- UI_CURSOR_TOOLBUY,
- UI_CURSOR_TOOLPAY,
- UI_CURSOR_TOOLOPEN,
UI_CURSOR_TOOLPLAY,
UI_CURSOR_TOOLPAUSE,
UI_CURSOR_TOOLMEDIAOPEN,
@@ -77,6 +71,6 @@ enum ECursorType {
UI_CURSOR_COUNT // Number of elements in this enum (NOT a cursor)
};
-ECursorType getCursorFromString(const std::string& cursor_string);
+LL_COMMON_API ECursorType getCursorFromString(const std::string& cursor_string);
#endif // LL_LLCURSORTYPES_H
diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp
index 41a3af398f..ca7e471bf2 100644
--- a/indra/llcommon/lldate.cpp
+++ b/indra/llcommon/lldate.cpp
@@ -38,10 +38,13 @@
#include "apr_time.h"
#include <time.h>
+#include <locale.h>
+#include <string>
#include <iomanip>
#include <sstream>
#include "lltimer.h"
+#include "llstring.h"
static const F64 DATE_EPOCH = 0.0;
@@ -88,45 +91,37 @@ std::string LLDate::asString() const
// is one of the standards used and the prefered format
std::string LLDate::asRFC1123() const
{
- std::ostringstream stream;
- toHTTPDateStream(stream);
- return stream.str();
+ return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT"));
}
-void LLDate::toHTTPDateStream(std::ostream& s) const
-{
- // http://apr.apache.org/docs/apr/0.9/group__apr__time.html
- apr_time_t time = (apr_time_t)(mSecondsSinceEpoch * LL_APR_USEC_PER_SEC);
+LLFastTimer::DeclareTimer FT_DATE_FORMAT("Date Format");
- apr_time_exp_t exp_time ; //Apache time module
+std::string LLDate::toHTTPDateString (std::string fmt) const
+{
+ LLFastTimer ft1(FT_DATE_FORMAT);
+
+ time_t locSeconds = (time_t) mSecondsSinceEpoch;
+ struct tm * gmt = gmtime (&locSeconds);
+ return toHTTPDateString(gmt, fmt);
+}
- if (apr_time_exp_gmt(&exp_time, time) != APR_SUCCESS)
- {
- // Return Epoch UTC date
- s << "Thursday, 01 Jan 1970 00:00:00 GMT" ;
- return;
- }
+std::string LLDate::toHTTPDateString (tm * gmt, std::string fmt)
+{
+ LLFastTimer ft1(FT_DATE_FORMAT);
- s << std::dec << std::setfill('0');
-#if( LL_WINDOWS || __GNUC__ > 2)
- s << std::right ;
-#else
- s.setf(ios::right);
-#endif
- std::string day = weekdays[exp_time.tm_wday];
- std::string month = months[exp_time.tm_mon];
-
- s << std::setw(day.length()) << (day)
- << ", " << std::setw(2) << (exp_time.tm_mday)
- << ' ' << std::setw(month.length()) << (month)
- << ' ' << std::setw(4) << (exp_time.tm_year + 1900)
- << ' ' << std::setw(2) << (exp_time.tm_hour)
- << ':' << std::setw(2) << (exp_time.tm_min)
- << ':' << std::setw(2) << (exp_time.tm_sec)
- << " GMT";
+ // avoid calling setlocale() unnecessarily - it's expensive.
+ static std::string prev_locale = "";
+ std::string this_locale = LLStringUtil::getLocale();
+ if (this_locale != prev_locale)
+ {
+ setlocale(LC_TIME, this_locale.c_str());
+ prev_locale = this_locale;
+ }
- // RFC 1123 date does not use microseconds
- //llinfos << "Date in RFC 1123 format is " << s << llendl;
+ // use strftime() as it appears to be faster than std::time_put
+ char buffer[128];
+ strftime(buffer, 128, fmt.c_str(), gmt);
+ return std::string(buffer);
}
void LLDate::toStream(std::ostream& s) const
@@ -160,6 +155,37 @@ void LLDate::toStream(std::ostream& s) const
s << 'Z';
}
+bool LLDate::split(S32 *year, S32 *month, S32 *day, S32 *hour, S32 *min, S32 *sec) const
+{
+ apr_time_t time = (apr_time_t)(mSecondsSinceEpoch * LL_APR_USEC_PER_SEC);
+
+ apr_time_exp_t exp_time;
+ if (apr_time_exp_gmt(&exp_time, time) != APR_SUCCESS)
+ {
+ return false;
+ }
+
+ if (year)
+ *year = exp_time.tm_year + 1900;
+
+ if (month)
+ *month = exp_time.tm_mon + 1;
+
+ if (day)
+ *day = exp_time.tm_mday;
+
+ if (hour)
+ *hour = exp_time.tm_hour;
+
+ if (min)
+ *min = exp_time.tm_min;
+
+ if (sec)
+ *sec = exp_time.tm_sec;
+
+ return true;
+}
+
bool LLDate::fromString(const std::string& iso8601_date)
{
std::istringstream stream(iso8601_date);
@@ -228,6 +254,36 @@ bool LLDate::fromStream(std::istream& s)
return true;
}
+bool LLDate::fromYMDHMS(S32 year, S32 month, S32 day, S32 hour, S32 min, S32 sec)
+{
+ struct apr_time_exp_t exp_time;
+
+ exp_time.tm_year = year - 1900;
+ exp_time.tm_mon = month - 1;
+ exp_time.tm_mday = day;
+ exp_time.tm_hour = hour;
+ exp_time.tm_min = min;
+ exp_time.tm_sec = sec;
+
+ // zero out the unused fields
+ exp_time.tm_usec = 0;
+ exp_time.tm_wday = 0;
+ exp_time.tm_yday = 0;
+ exp_time.tm_isdst = 0;
+ exp_time.tm_gmtoff = 0;
+
+ // generate a time_t from that
+ apr_time_t time;
+ if (apr_time_exp_gmt_get(&time, &exp_time) != APR_SUCCESS)
+ {
+ return false;
+ }
+
+ mSecondsSinceEpoch = time / LL_APR_USEC_PER_SEC;
+
+ return true;
+}
+
F64 LLDate::secondsSinceEpoch() const
{
return mSecondsSinceEpoch;
diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h
index 7cc9c8aceb..f8b2f2f163 100644
--- a/indra/llcommon/lldate.h
+++ b/indra/llcommon/lldate.h
@@ -46,7 +46,7 @@
*
* The date class represents a point in time after epoch - 1970-01-01.
*/
-class LLDate
+class LL_COMMON_API LLDate
{
public:
/**
@@ -84,7 +84,9 @@ public:
std::string asString() const;
std::string asRFC1123() const;
void toStream(std::ostream&) const;
- void toHTTPDateStream(std::ostream&) const;
+ bool split(S32 *year, S32 *month = NULL, S32 *day = NULL, S32 *hour = NULL, S32 *min = NULL, S32 *sec = NULL) const;
+ std::string toHTTPDateString (std::string fmt) const;
+ static std::string toHTTPDateString (tm * gmt, std::string fmt);
/**
* @brief Set the date from an ISO-8601 string.
*
@@ -99,6 +101,7 @@ public:
*/
bool fromString(const std::string& iso8601_date);
bool fromStream(std::istream&);
+ bool fromYMDHMS(S32 year, S32 month = 1, S32 day = 0, S32 hour = 0, S32 min = 0, S32 sec = 0);
/**
* @brief Return the date in seconds since epoch.
@@ -153,14 +156,11 @@ private:
};
// Helper function to stream out a date
-std::ostream& operator<<(std::ostream& s, const LLDate& date);
+LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLDate& date);
// Helper function to stream in a date
-std::istream& operator>>(std::istream& s, LLDate& date);
+LL_COMMON_API std::istream& operator>>(std::istream& s, LLDate& date);
-const static std::string weekdays[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
-
-const static std::string months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
#endif // LL_LLDATE_H
diff --git a/indra/llcommon/lldeleteutils.h b/indra/llcommon/lldeleteutils.h
new file mode 100644
index 0000000000..d6a0945e46
--- /dev/null
+++ b/indra/llcommon/lldeleteutils.h
@@ -0,0 +1,53 @@
+/**
+ * @file lldeleteutils.h
+ * @brief Utility functions to simplify some common pointer-munging idioms.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef LL_DELETE_UTILS_H
+#define LL_DELETE_UTILS_H
+
+// Simple utility functions to eventually replace the common 2-line
+// idiom scattered throughout the viewer codebase. Note that where
+// possible we would rather be using smart pointers of some sort.
+
+template <class T>
+inline void deleteAndClear(T*& ptr)
+{
+ delete ptr;
+ ptr = NULL;
+}
+
+template <class T>
+inline void deleteAndClearArray(T*& array_ptr)
+{
+ delete[] array_ptr;
+ array_ptr = NULL;
+}
+
+#endif
diff --git a/indra/llcommon/lldependencies.cpp b/indra/llcommon/lldependencies.cpp
new file mode 100644
index 0000000000..ffb5cfbdaa
--- /dev/null
+++ b/indra/llcommon/lldependencies.cpp
@@ -0,0 +1,86 @@
+/**
+ * @file lldependencies.cpp
+ * @author Nat Goodspeed
+ * @date 2008-09-17
+ * @brief Implementation for lldependencies.
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * Copyright (c) 2008, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "lldependencies.h"
+// STL headers
+#include <map>
+#include <sstream>
+// std headers
+// external library headers
+#include <boost/graph/graph_traits.hpp> // for boost::graph_traits
+#include <boost/graph/adjacency_list.hpp>
+#include <boost/graph/topological_sort.hpp>
+#include <boost/graph/exception.hpp>
+// other Linden headers
+
+LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const EdgeList& edges) const
+{
+ // Construct a Boost Graph Library graph according to the constraints
+ // we've collected. It seems as though we ought to be able to capture
+ // the uniqueness of vertex keys using a setS of vertices with a
+ // string property -- but I don't yet understand adjacency_list well
+ // enough to get there. All the examples I've seen so far use integers
+ // for vertices.
+ // Define the Graph type. Use a vector for vertices so we can use the
+ // default topological_sort vertex lookup by int index. Use a set for
+ // edges because the same dependency may be stated twice: Node "a" may
+ // specify that it must precede "b", while "b" may also state that it
+ // must follow "a".
+ typedef boost::adjacency_list<boost::setS, boost::vecS, boost::directedS,
+ boost::no_property> Graph;
+ // Instantiate the graph. Without vertex properties, we need say no
+ // more about vertices than the total number.
+ Graph g(edges.begin(), edges.end(), vertices);
+ // topo sort
+ typedef boost::graph_traits<Graph>::vertex_descriptor VertexDesc;
+ typedef std::vector<VertexDesc> SortedList;
+ SortedList sorted;
+ // note that it throws not_a_dag if it finds a cycle
+ try
+ {
+ boost::topological_sort(g, std::back_inserter(sorted));
+ }
+ catch (const boost::not_a_dag& e)
+ {
+ // translate to the exception we define
+ std::ostringstream out;
+ out << "LLDependencies cycle: " << e.what() << '\n';
+ // Omit independent nodes: display only those that might contribute to
+ // the cycle.
+ describe(out, false);
+ throw Cycle(out.str());
+ }
+ // A peculiarity of boost::topological_sort() is that it emits results in
+ // REVERSE topological order: to get the result you want, you must
+ // traverse the SortedList using reverse iterators.
+ return VertexList(sorted.rbegin(), sorted.rend());
+}
+
+std::ostream& LLDependenciesBase::describe(std::ostream& out, bool full) const
+{
+ // Should never encounter this base-class implementation; may mean that
+ // the KEY type doesn't have a suitable ostream operator<<().
+ out << "<no description available>";
+ return out;
+}
+
+std::string LLDependenciesBase::describe(bool full) const
+{
+ // Just use the ostream-based describe() on a std::ostringstream. The
+ // implementation is here mostly so that we can avoid #include <sstream>
+ // in the header file.
+ std::ostringstream out;
+ describe(out, full);
+ return out.str();
+}
diff --git a/indra/llcommon/lldependencies.h b/indra/llcommon/lldependencies.h
new file mode 100644
index 0000000000..e6229db834
--- /dev/null
+++ b/indra/llcommon/lldependencies.h
@@ -0,0 +1,782 @@
+/**
+ * @file lldependencies.h
+ * @author Nat Goodspeed
+ * @date 2008-09-17
+ * @brief LLDependencies: a generic mechanism for expressing "b must follow a,
+ * but precede c"
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * Copyright (c) 2008, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLDEPENDENCIES_H)
+#define LL_LLDEPENDENCIES_H
+
+#include <string>
+#include <vector>
+#include <set>
+#include <map>
+#include <stdexcept>
+#include <iosfwd>
+#include <boost/iterator/transform_iterator.hpp>
+#include <boost/iterator/indirect_iterator.hpp>
+#include <boost/range/iterator_range.hpp>
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
+
+/*****************************************************************************
+* Utilities
+*****************************************************************************/
+/**
+ * generic range transformer: given a range acceptable to Boost.Range (e.g. a
+ * standard container, an iterator pair, ...) and a unary function to apply to
+ * each element of the range, make a corresponding range that lazily applies
+ * that function to each element on dereferencing.
+ */
+template<typename FUNCTION, typename RANGE>
+inline
+boost::iterator_range<boost::transform_iterator<FUNCTION,
+ typename boost::range_const_iterator<RANGE>::type> >
+make_transform_range(const RANGE& range, FUNCTION function)
+{
+ // shorthand for the iterator type embedded in our return type
+ typedef boost::transform_iterator<FUNCTION, typename boost::range_const_iterator<RANGE>::type>
+ transform_iterator;
+ return boost::make_iterator_range(transform_iterator(boost::begin(range), function),
+ transform_iterator(boost::end(range), function));
+}
+
+/// non-const version of make_transform_range()
+template<typename FUNCTION, typename RANGE>
+inline
+boost::iterator_range<boost::transform_iterator<FUNCTION,
+ typename boost::range_iterator<RANGE>::type> >
+make_transform_range(RANGE& range, FUNCTION function)
+{
+ // shorthand for the iterator type embedded in our return type
+ typedef boost::transform_iterator<FUNCTION, typename boost::range_iterator<RANGE>::type>
+ transform_iterator;
+ return boost::make_iterator_range(transform_iterator(boost::begin(range), function),
+ transform_iterator(boost::end(range), function));
+}
+
+/**
+ * From any range compatible with Boost.Range, instantiate any class capable
+ * of accepting an iterator pair.
+ */
+template<class TYPE>
+struct instance_from_range: public TYPE
+{
+ template<typename RANGE>
+ instance_from_range(RANGE range):
+ TYPE(boost::begin(range), boost::end(range))
+ {}
+};
+
+/*****************************************************************************
+* LLDependencies
+*****************************************************************************/
+/**
+ * LLDependencies components that should not be reinstantiated for each KEY,
+ * NODE specialization
+ */
+class LL_COMMON_API LLDependenciesBase
+{
+public:
+ virtual ~LLDependenciesBase() {}
+
+ /**
+ * Exception thrown by sort() if there's a cycle
+ */
+ struct Cycle: public std::runtime_error
+ {
+ Cycle(const std::string& what): std::runtime_error(what) {}
+ };
+
+ /**
+ * Provide a short description of this LLDependencies instance on the
+ * specified output stream, assuming that its KEY type has an operator<<()
+ * that works with std::ostream.
+ *
+ * Pass @a full as @c false to omit any keys without dependency constraints.
+ */
+ virtual std::ostream& describe(std::ostream& out, bool full=true) const;
+
+ /// describe() to a string
+ virtual std::string describe(bool full=true) const;
+
+protected:
+ typedef std::vector< std::pair<int, int> > EdgeList;
+ typedef std::vector<int> VertexList;
+ VertexList topo_sort(int vertices, const EdgeList& edges) const;
+
+ /**
+ * refpair is specifically intended to capture a pair of references. This
+ * is better than std::pair<T1&, T2&> because some implementations of
+ * std::pair's ctor accept const references to the two types. If the
+ * types are themselves references, this results in an illegal reference-
+ * to-reference.
+ */
+ template<typename T1, typename T2>
+ struct refpair
+ {
+ refpair(T1 value1, T2 value2):
+ first(value1),
+ second(value2)
+ {}
+ T1 first;
+ T2 second;
+ };
+};
+
+/// describe() helper: for most types, report the type as usual
+template<typename T>
+inline
+std::ostream& LLDependencies_describe(std::ostream& out, const T& key)
+{
+ out << key;
+ return out;
+}
+
+/// specialize LLDependencies_describe() for std::string
+template<>
+inline
+std::ostream& LLDependencies_describe(std::ostream& out, const std::string& key)
+{
+ out << '"' << key << '"';
+ return out;
+}
+
+/**
+ * It's reasonable to use LLDependencies in a keys-only way, more or less like
+ * std::set. For that case, the default NODE type is an empty struct.
+ */
+struct LLDependenciesEmpty
+{
+ LLDependenciesEmpty() {}
+ /**
+ * Give it a constructor accepting void* so caller can pass placeholder
+ * values such as NULL or 0 rather than having to write
+ * LLDependenciesEmpty().
+ */
+ LLDependenciesEmpty(void*) {}
+};
+
+/**
+ * This class manages abstract dependencies between node types of your
+ * choosing. As with a std::map, nodes are copied when add()ed, so the node
+ * type should be relatively lightweight; to manipulate dependencies between
+ * expensive objects, use a pointer type.
+ *
+ * For a given node, you may state the keys of nodes that must precede it
+ * and/or nodes that must follow it. The sort() method will produce an order
+ * that should work, or throw an exception if the constraints are impossible.
+ * We cache results to minimize the cost of repeated sort() calls.
+ */
+template<typename KEY = std::string,
+ typename NODE = LLDependenciesEmpty>
+class LLDependencies: public LLDependenciesBase
+{
+ typedef LLDependencies<KEY, NODE> self_type;
+
+ /**
+ * Internally, we bundle the client's NODE with its before/after keys.
+ */
+ struct DepNode
+ {
+ typedef std::set<KEY> dep_set;
+ DepNode(const NODE& node_, const dep_set& after_, const dep_set& before_):
+ node(node_),
+ after(after_),
+ before(before_)
+ {}
+ NODE node;
+ dep_set after, before;
+ };
+ typedef std::map<KEY, DepNode> DepNodeMap;
+ typedef typename DepNodeMap::value_type DepNodeMapEntry;
+
+ /// We have various ways to get the dependencies for a given DepNode.
+ /// Rather than having to restate each one for 'after' and 'before'
+ /// separately, pass a dep_selector so we can apply each to either.
+ typedef boost::function<const typename DepNode::dep_set&(const DepNode&)> dep_selector;
+
+public:
+ LLDependencies() {}
+
+ typedef KEY key_type;
+ typedef NODE node_type;
+
+ /// param type used to express lists of other node keys -- note that such
+ /// lists can be initialized with boost::assign::list_of()
+ typedef std::vector<KEY> KeyList;
+
+ /**
+ * Add a new node. State its dependencies on other nodes (which may not
+ * yet have been added) by listing the keys of nodes this new one must
+ * follow, and separately the keys of nodes this new one must precede.
+ *
+ * The node you pass is @em copied into an internal data structure. If you
+ * want to modify the node value after add()ing it, capture the returned
+ * NODE& reference.
+ *
+ * @note
+ * Actual dependency analysis is deferred to the sort() method, so
+ * you can add an arbitrary number of nodes without incurring analysis
+ * overhead for each. The flip side of this is that add()ing nodes that
+ * define a cycle leaves this object in a state in which sort() will
+ * always throw the Cycle exception.
+ *
+ * Two distinct use cases are anticipated:
+ * * The data used to load this object are completely known at compile
+ * time (e.g. LLEventPump listener names). A Cycle exception represents a
+ * bug which can be corrected by the coder. The program need neither catch
+ * Cycle nor attempt to salvage the state of this object.
+ * * The data are loaded at runtime, therefore the universe of
+ * dependencies cannot be known at compile time. The client code should
+ * catch Cycle.
+ * ** If a Cycle exception indicates fatally-flawed input data, this
+ * object can simply be discarded, possibly with the entire program run.
+ * ** If it is essential to restore this object to a working state, the
+ * simplest workaround is to remove() nodes in LIFO order.
+ * *** It may be useful to add functionality to this class to track the
+ * add() chronology, providing a pop() method to remove the most recently
+ * added node.
+ * *** It may further be useful to add a restore() method which would
+ * pop() until sort() no longer throws Cycle. This method would be
+ * expensive -- but it's not clear that client code could resolve the
+ * problem more cheaply.
+ */
+ NODE& add(const KEY& key, const NODE& node = NODE(),
+ const KeyList& after = KeyList(),
+ const KeyList& before = KeyList())
+ {
+ // Get the passed-in lists as sets for equality comparison
+ typename DepNode::dep_set
+ after_set(after.begin(), after.end()),
+ before_set(before.begin(), before.end());
+ // Try to insert the new node; if it already exists, find the old
+ // node instead.
+ std::pair<typename DepNodeMap::iterator, bool> inserted =
+ mNodes.insert(typename DepNodeMap::value_type(key,
+ DepNode(node, after_set, before_set)));
+ if (! inserted.second) // bool indicating success of insert()
+ {
+ // We already have a node by this name. Have its dependencies
+ // changed? If the existing node's dependencies are identical, the
+ // result will be unchanged, so we can leave the cache intact.
+ // Regardless of inserted.second, inserted.first is the iterator
+ // to the newly-inserted (or existing) map entry. Of course, that
+ // entry's second is the DepNode of interest.
+ if (inserted.first->second.after != after_set ||
+ inserted.first->second.before != before_set)
+ {
+ // Dependencies have changed: clear the cached result.
+ mCache.clear();
+ // save the new dependencies
+ inserted.first->second.after = after_set;
+ inserted.first->second.before = before_set;
+ }
+ }
+ else // this node is new
+ {
+ // This will change results.
+ mCache.clear();
+ }
+ return inserted.first->second.node;
+ }
+
+ /// the value of an iterator, showing both KEY and its NODE
+ typedef refpair<const KEY&, NODE&> value_type;
+ /// the value of a const_iterator
+ typedef refpair<const KEY&, const NODE&> const_value_type;
+
+private:
+ // Extract functors
+ static value_type value_extract(DepNodeMapEntry& entry)
+ {
+ return value_type(entry.first, entry.second.node);
+ }
+
+ static const_value_type const_value_extract(const DepNodeMapEntry& entry)
+ {
+ return const_value_type(entry.first, entry.second.node);
+ }
+
+ // All the iterator access methods return iterator ranges just to cut down
+ // on the friggin' boilerplate!!
+
+ /// generic mNodes range method
+ template<typename ITERATOR, typename FUNCTION>
+ boost::iterator_range<ITERATOR> generic_range(FUNCTION function)
+ {
+ return make_transform_range(mNodes, function);
+ }
+
+ /// generic mNodes const range method
+ template<typename ITERATOR, typename FUNCTION>
+ boost::iterator_range<ITERATOR> generic_range(FUNCTION function) const
+ {
+ return make_transform_range(mNodes, function);
+ }
+
+public:
+ /// iterator over value_type entries
+ typedef boost::transform_iterator<boost::function<value_type(DepNodeMapEntry&)>,
+ typename DepNodeMap::iterator> iterator;
+ /// range over value_type entries
+ typedef boost::iterator_range<iterator> range;
+
+ /// iterate over value_type <i>in @c KEY order</i> rather than dependency order
+ range get_range()
+ {
+ return generic_range<iterator>(value_extract);
+ }
+
+ /// iterator over const_value_type entries
+ typedef boost::transform_iterator<boost::function<const_value_type(const DepNodeMapEntry&)>,
+ typename DepNodeMap::const_iterator> const_iterator;
+ /// range over const_value_type entries
+ typedef boost::iterator_range<const_iterator> const_range;
+
+ /// iterate over const_value_type <i>in @c KEY order</i> rather than dependency order
+ const_range get_range() const
+ {
+ return generic_range<const_iterator>(const_value_extract);
+ }
+
+ /// iterator over stored NODEs
+ typedef boost::transform_iterator<boost::function<NODE&(DepNodeMapEntry&)>,
+ typename DepNodeMap::iterator> node_iterator;
+ /// range over stored NODEs
+ typedef boost::iterator_range<node_iterator> node_range;
+
+ /// iterate over NODE <i>in @c KEY order</i> rather than dependency order
+ node_range get_node_range()
+ {
+ // First take a DepNodeMapEntry and extract a reference to its
+ // DepNode, then from that extract a reference to its NODE.
+ return generic_range<node_iterator>(
+ boost::bind<NODE&>(&DepNode::node,
+ boost::bind<DepNode&>(&DepNodeMapEntry::second, _1)));
+ }
+
+ /// const iterator over stored NODEs
+ typedef boost::transform_iterator<boost::function<const NODE&(const DepNodeMapEntry&)>,
+ typename DepNodeMap::const_iterator> const_node_iterator;
+ /// const range over stored NODEs
+ typedef boost::iterator_range<const_node_iterator> const_node_range;
+
+ /// iterate over const NODE <i>in @c KEY order</i> rather than dependency order
+ const_node_range get_node_range() const
+ {
+ // First take a DepNodeMapEntry and extract a reference to its
+ // DepNode, then from that extract a reference to its NODE.
+ return generic_range<const_node_iterator>(
+ boost::bind<const NODE&>(&DepNode::node,
+ boost::bind<const DepNode&>(&DepNodeMapEntry::second, _1)));
+ }
+
+ /// const iterator over stored KEYs
+ typedef boost::transform_iterator<boost::function<const KEY&(const DepNodeMapEntry&)>,
+ typename DepNodeMap::const_iterator> const_key_iterator;
+ /// const range over stored KEYs
+ typedef boost::iterator_range<const_key_iterator> const_key_range;
+ // We don't provide a non-const iterator over KEYs because they should be
+ // immutable, and in fact our underlying std::map won't give us non-const
+ // references.
+
+ /// iterate over const KEY <i>in @c KEY order</i> rather than dependency order
+ const_key_range get_key_range() const
+ {
+ // From a DepNodeMapEntry, extract a reference to its KEY.
+ return generic_range<const_key_iterator>(
+ boost::bind<const KEY&>(&DepNodeMapEntry::first, _1));
+ }
+
+ /**
+ * Find an existing NODE, or return NULL. We decided to avoid providing a
+ * method analogous to std::map::find(), for a couple of reasons:
+ *
+ * * For a find-by-key, getting back an iterator to the (key, value) pair
+ * is less than useful, since you already have the key in hand.
+ * * For a failed request, comparing to end() is problematic. First, we
+ * provide range accessors, so it's more code to get end(). Second, we
+ * provide a number of different ranges -- quick, to which one's end()
+ * should we compare the iterator returned by find()?
+ *
+ * The returned pointer is solely to allow expressing the not-found
+ * condition. LLDependencies still owns the found NODE.
+ */
+ const NODE* get(const KEY& key) const
+ {
+ typename DepNodeMap::const_iterator found = mNodes.find(key);
+ if (found != mNodes.end())
+ {
+ return &found->second.node;
+ }
+ return NULL;
+ }
+
+ /**
+ * non-const get()
+ */
+ NODE* get(const KEY& key)
+ {
+ // Use const implementation, then cast away const-ness of return
+ return const_cast<NODE*>(const_cast<const self_type*>(this)->get(key));
+ }
+
+ /**
+ * Remove a node with specified key. This operation is the major reason
+ * we rebuild the graph on the fly instead of storing it.
+ */
+ bool remove(const KEY& key)
+ {
+ typename DepNodeMap::iterator found = mNodes.find(key);
+ if (found != mNodes.end())
+ {
+ mNodes.erase(found);
+ return true;
+ }
+ return false;
+ }
+
+private:
+ /// cached list of iterators
+ typedef std::vector<iterator> iterator_list;
+ typedef typename iterator_list::iterator iterator_list_iterator;
+
+public:
+ /**
+ * The return type of the sort() method needs some explanation. Provide a
+ * public typedef to facilitate storing the result.
+ *
+ * * We will prepare mCache by looking up DepNodeMap iterators.
+ * * We want to return a range containing iterators that will walk mCache.
+ * * If we simply stored DepNodeMap iterators and returned
+ * (mCache.begin(), mCache.end()), dereferencing each iterator would
+ * obtain a DepNodeMap iterator.
+ * * We want the caller to loop over @c value_type: pair<KEY, NODE>.
+ * * This requires two transformations:
+ * ** mCache must contain @c LLDependencies::iterator so that
+ * dereferencing each entry will obtain an @c LLDependencies::value_type
+ * rather than a DepNodeMapEntry.
+ * ** We must wrap mCache's iterators in boost::indirect_iterator so that
+ * dereferencing one of our returned iterators will also dereference the
+ * iterator contained in mCache.
+ */
+ typedef boost::iterator_range<boost::indirect_iterator<iterator_list_iterator> > sorted_range;
+ /// for convenience in looping over a sorted_range
+ typedef typename sorted_range::iterator sorted_iterator;
+
+ /**
+ * Once we've loaded in the dependencies of interest, arrange them into an
+ * order that works -- or throw Cycle exception.
+ *
+ * Return an iterator range over (key, node) pairs that traverses them in
+ * the desired order.
+ */
+ sorted_range sort() const
+ {
+ // Changes to mNodes cause us to clear our cache, so empty mCache
+ // means it's invalid and should be recomputed. However, if mNodes is
+ // also empty, then an empty mCache represents a valid order, so don't
+ // bother sorting.
+ if (mCache.empty() && ! mNodes.empty())
+ {
+ // Construct a map of node keys to distinct vertex numbers -- even for
+ // nodes mentioned only in before/after constraints, that haven't yet
+ // been explicitly added. Rely on std::map rejecting a second attempt
+ // to insert the same key. Use the map's size() as the vertex number
+ // to get a distinct value for each successful insertion.
+ typedef std::map<KEY, int> VertexMap;
+ VertexMap vmap;
+ // Nest each of these loops because !@#$%? MSVC warns us that its
+ // former broken behavior has finally been fixed -- and our builds
+ // treat warnings as errors.
+ {
+ for (typename DepNodeMap::const_iterator nmi = mNodes.begin(), nmend = mNodes.end();
+ nmi != nmend; ++nmi)
+ {
+ vmap.insert(typename VertexMap::value_type(nmi->first, vmap.size()));
+ for (typename DepNode::dep_set::const_iterator ai = nmi->second.after.begin(),
+ aend = nmi->second.after.end();
+ ai != aend; ++ai)
+ {
+ vmap.insert(typename VertexMap::value_type(*ai, vmap.size()));
+ }
+ for (typename DepNode::dep_set::const_iterator bi = nmi->second.before.begin(),
+ bend = nmi->second.before.end();
+ bi != bend; ++bi)
+ {
+ vmap.insert(typename VertexMap::value_type(*bi, vmap.size()));
+ }
+ }
+ }
+ // Define the edges. For this we must traverse mNodes again, mapping
+ // all the known key dependencies to integer pairs.
+ EdgeList edges;
+ {
+ for (typename DepNodeMap::const_iterator nmi = mNodes.begin(), nmend = mNodes.end();
+ nmi != nmend; ++nmi)
+ {
+ int thisnode = vmap[nmi->first];
+ // after dependencies: build edges from the named node to this one
+ for (typename DepNode::dep_set::const_iterator ai = nmi->second.after.begin(),
+ aend = nmi->second.after.end();
+ ai != aend; ++ai)
+ {
+ edges.push_back(EdgeList::value_type(vmap[*ai], thisnode));
+ }
+ // before dependencies: build edges from this node to the
+ // named one
+ for (typename DepNode::dep_set::const_iterator bi = nmi->second.before.begin(),
+ bend = nmi->second.before.end();
+ bi != bend; ++bi)
+ {
+ edges.push_back(EdgeList::value_type(thisnode, vmap[*bi]));
+ }
+ }
+ }
+ // Hide the gory details of our topological sort, since they shouldn't
+ // get reinstantiated for each distinct NODE type.
+ VertexList sorted(topo_sort(vmap.size(), edges));
+ // Build the reverse of vmap to look up the key for each vertex
+ // descriptor. vmap contains exactly one entry for each distinct key,
+ // and we're certain that the associated int values are distinct
+ // indexes. The fact that they're not in order is irrelevant.
+ KeyList vkeys(vmap.size());
+ for (typename VertexMap::const_iterator vmi = vmap.begin(), vmend = vmap.end();
+ vmi != vmend; ++vmi)
+ {
+ vkeys[vmi->second] = vmi->first;
+ }
+ // Walk the sorted output list, building the result into mCache so
+ // we'll have it next time someone asks.
+ mCache.clear();
+ for (VertexList::const_iterator svi = sorted.begin(), svend = sorted.end();
+ svi != svend; ++svi)
+ {
+ // We're certain that vkeys[*svi] exists. However, there might not
+ // yet be a corresponding entry in mNodes.
+ self_type* non_const_this(const_cast<self_type*>(this));
+ typename DepNodeMap::iterator found = non_const_this->mNodes.find(vkeys[*svi]);
+ if (found != non_const_this->mNodes.end())
+ {
+ // Make an iterator of appropriate type.
+ mCache.push_back(iterator(found, value_extract));
+ }
+ }
+ }
+ // Whether or not we've just recomputed mCache, it should now contain
+ // the results we want. Return a range of indirect_iterators over it
+ // so that dereferencing a returned iterator will dereference the
+ // iterator stored in mCache and directly reference the (key, node)
+ // pair.
+ boost::indirect_iterator<iterator_list_iterator>
+ begin(mCache.begin()),
+ end(mCache.end());
+ return sorted_range(begin, end);
+ }
+
+ using LLDependenciesBase::describe; // unhide virtual std::string describe(bool full=true) const;
+
+ /// Override base-class describe() with actual implementation
+ virtual std::ostream& describe(std::ostream& out, bool full=true) const
+ {
+ typename DepNodeMap::const_iterator dmi(mNodes.begin()), dmend(mNodes.end());
+ if (dmi != dmend)
+ {
+ std::string sep;
+ describe(out, sep, *dmi, full);
+ while (++dmi != dmend)
+ {
+ describe(out, sep, *dmi, full);
+ }
+ }
+ return out;
+ }
+
+
+ /// describe() helper: report a DepNodeEntry
+ static std::ostream& describe(std::ostream& out, std::string& sep,
+ const DepNodeMapEntry& entry, bool full)
+ {
+ // If we were asked for a full report, describe every node regardless
+ // of whether it has dependencies. If we were asked to suppress
+ // independent nodes, describe this one if either after or before is
+ // non-empty.
+ if (full || (! entry.second.after.empty()) || (! entry.second.before.empty()))
+ {
+ out << sep;
+ sep = "\n";
+ if (! entry.second.after.empty())
+ {
+ out << "after ";
+ describe(out, entry.second.after);
+ out << " -> ";
+ }
+ LLDependencies_describe(out, entry.first);
+ if (! entry.second.before.empty())
+ {
+ out << " -> before ";
+ describe(out, entry.second.before);
+ }
+ }
+ return out;
+ }
+
+ /// describe() helper: report a dep_set
+ static std::ostream& describe(std::ostream& out, const typename DepNode::dep_set& keys)
+ {
+ out << '(';
+ typename DepNode::dep_set::const_iterator ki(keys.begin()), kend(keys.end());
+ if (ki != kend)
+ {
+ LLDependencies_describe(out, *ki);
+ while (++ki != kend)
+ {
+ out << ", ";
+ LLDependencies_describe(out, *ki);
+ }
+ }
+ out << ')';
+ return out;
+ }
+
+ /// Iterator over the before/after KEYs on which a given NODE depends
+ typedef typename DepNode::dep_set::const_iterator dep_iterator;
+ /// range over the before/after KEYs on which a given NODE depends
+ typedef boost::iterator_range<dep_iterator> dep_range;
+
+ /// dependencies access from key
+ dep_range get_dep_range_from_key(const KEY& key, const dep_selector& selector) const
+ {
+ typename DepNodeMap::const_iterator found = mNodes.find(key);
+ if (found != mNodes.end())
+ {
+ return dep_range(selector(found->second));
+ }
+ // We want to return an empty range. On some platforms a default-
+ // constructed range (e.g. dep_range()) does NOT suffice! The client
+ // is likely to try to iterate from boost::begin(range) to
+ // boost::end(range); yet these iterators might not be valid. Instead
+ // return a range over a valid, empty container.
+ static const typename DepNode::dep_set empty_deps;
+ return dep_range(empty_deps.begin(), empty_deps.end());
+ }
+
+ /// dependencies access from any one of our key-order iterators
+ template<typename ITERATOR>
+ dep_range get_dep_range_from_xform(const ITERATOR& iterator, const dep_selector& selector) const
+ {
+ return dep_range(selector(iterator.base()->second));
+ }
+
+ /// dependencies access from sorted_iterator
+ dep_range get_dep_range_from_sorted(const sorted_iterator& sortiter,
+ const dep_selector& selector) const
+ {
+ // sorted_iterator is a boost::indirect_iterator wrapping an mCache
+ // iterator, which we can obtain by sortiter.base(). Deferencing that
+ // gets us an mCache entry, an 'iterator' -- one of our traversal
+ // iterators -- on which we can use get_dep_range_from_xform().
+ return get_dep_range_from_xform(*sortiter.base(), selector);
+ }
+
+ /**
+ * Get a range over the after KEYs stored for the passed KEY or iterator,
+ * in <i>arbitrary order.</i> If you pass a nonexistent KEY, returns empty
+ * range -- same as a KEY with no after KEYs. Detect existence of a KEY
+ * using get() instead.
+ */
+ template<typename KEY_OR_ITER>
+ dep_range get_after_range(const KEY_OR_ITER& key) const;
+
+ /**
+ * Get a range over the before KEYs stored for the passed KEY or iterator,
+ * in <i>arbitrary order.</i> If you pass a nonexistent KEY, returns empty
+ * range -- same as a KEY with no before KEYs. Detect existence of a KEY
+ * using get() instead.
+ */
+ template<typename KEY_OR_ITER>
+ dep_range get_before_range(const KEY_OR_ITER& key) const;
+
+private:
+ DepNodeMap mNodes;
+ mutable iterator_list mCache;
+};
+
+/**
+ * Functor to get a dep_range from a KEY or iterator -- generic case. If the
+ * passed value isn't one of our iterator specializations, assume it's
+ * convertible to the KEY type.
+ */
+template<typename KEY_ITER>
+struct LLDependencies_dep_range_from
+{
+ template<typename KEY, typename NODE, typename SELECTOR>
+ typename LLDependencies<KEY, NODE>::dep_range
+ operator()(const LLDependencies<KEY, NODE>& deps,
+ const KEY_ITER& key,
+ const SELECTOR& selector)
+ {
+ return deps.get_dep_range_from_key(key, selector);
+ }
+};
+
+/// Specialize LLDependencies_dep_range_from for our key-order iterators
+template<typename FUNCTION, typename ITERATOR>
+struct LLDependencies_dep_range_from< boost::transform_iterator<FUNCTION, ITERATOR> >
+{
+ template<typename KEY, typename NODE, typename SELECTOR>
+ typename LLDependencies<KEY, NODE>::dep_range
+ operator()(const LLDependencies<KEY, NODE>& deps,
+ const boost::transform_iterator<FUNCTION, ITERATOR>& iter,
+ const SELECTOR& selector)
+ {
+ return deps.get_dep_range_from_xform(iter, selector);
+ }
+};
+
+/// Specialize LLDependencies_dep_range_from for sorted_iterator
+template<typename BASEITER>
+struct LLDependencies_dep_range_from< boost::indirect_iterator<BASEITER> >
+{
+ template<typename KEY, typename NODE, typename SELECTOR>
+ typename LLDependencies<KEY, NODE>::dep_range
+ operator()(const LLDependencies<KEY, NODE>& deps,
+ const boost::indirect_iterator<BASEITER>& iter,
+ const SELECTOR& selector)
+ {
+ return deps.get_dep_range_from_sorted(iter, selector);
+ }
+};
+
+/// generic get_after_range() implementation
+template<typename KEY, typename NODE>
+template<typename KEY_OR_ITER>
+typename LLDependencies<KEY, NODE>::dep_range
+LLDependencies<KEY, NODE>::get_after_range(const KEY_OR_ITER& key_iter) const
+{
+ return LLDependencies_dep_range_from<KEY_OR_ITER>()(
+ *this,
+ key_iter,
+ boost::bind<const typename DepNode::dep_set&>(&DepNode::after, _1));
+}
+
+/// generic get_before_range() implementation
+template<typename KEY, typename NODE>
+template<typename KEY_OR_ITER>
+typename LLDependencies<KEY, NODE>::dep_range
+LLDependencies<KEY, NODE>::get_before_range(const KEY_OR_ITER& key_iter) const
+{
+ return LLDependencies_dep_range_from<KEY_OR_ITER>()(
+ *this,
+ key_iter,
+ boost::bind<const typename DepNode::dep_set&>(&DepNode::before, _1));
+}
+
+#endif /* ! defined(LL_LLDEPENDENCIES_H) */
diff --git a/indra/llcommon/lldictionary.cpp b/indra/llcommon/lldictionary.cpp
new file mode 100644
index 0000000000..8730238d92
--- /dev/null
+++ b/indra/llcommon/lldictionary.cpp
@@ -0,0 +1,52 @@
+/**
+ * @file lldictionary.cpp
+ * @brief Lldictionary class header file
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lldictionary.h"
+
+#include "llstring.h"
+
+// Define in .cpp file to prevent header include of llstring.h
+LLDictionaryEntry::LLDictionaryEntry(const std::string &name)
+: mName(name)
+{
+ mNameCapitalized = mName;
+ LLStringUtil::replaceChar(mNameCapitalized, '-', ' ');
+ LLStringUtil::replaceChar(mNameCapitalized, '_', ' ');
+ for (U32 i=0; i < mNameCapitalized.size(); i++)
+ {
+ if (i == 0 || mNameCapitalized[i-1] == ' ') // don't change ordering of this statement or crash
+ {
+ mNameCapitalized[i] = toupper(mNameCapitalized[i]);
+ }
+ }
+}
diff --git a/indra/llcommon/lldictionary.h b/indra/llcommon/lldictionary.h
new file mode 100644
index 0000000000..4a2bfb9f3f
--- /dev/null
+++ b/indra/llcommon/lldictionary.h
@@ -0,0 +1,99 @@
+/**
+ * @file lldictionary.h
+ * @brief Lldictionary class header file
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLDICTIONARY_H
+#define LL_LLDICTIONARY_H
+
+#include <map>
+#include <string>
+
+struct LL_COMMON_API LLDictionaryEntry
+{
+ LLDictionaryEntry(const std::string &name);
+ virtual ~LLDictionaryEntry() {}
+ const std::string mName;
+ std::string mNameCapitalized;
+};
+
+template <class Index, class Entry>
+class LLDictionary : public std::map<Index, Entry *>
+{
+public:
+ typedef std::map<Index, Entry *> map_t;
+ typedef typename map_t::iterator iterator_t;
+ typedef typename map_t::const_iterator const_iterator_t;
+
+ LLDictionary() {}
+ virtual ~LLDictionary()
+ {
+ for (iterator_t iter = map_t::begin(); iter != map_t::end(); ++iter)
+ delete (iter->second);
+ }
+
+ const Entry *lookup(Index index) const
+ {
+ const_iterator_t dictionary_iter = map_t::find(index);
+ if (dictionary_iter == map_t::end()) return NULL;
+ return dictionary_iter->second;
+ }
+ const Index lookup(const std::string &name) const
+ {
+ for (const_iterator_t dictionary_iter = map_t::begin();
+ dictionary_iter != map_t::end();
+ dictionary_iter++)
+ {
+ const Entry *entry = dictionary_iter->second;
+ if (entry->mName == name)
+ {
+ return dictionary_iter->first;
+ }
+ }
+ return notFound();
+ }
+
+protected:
+ virtual Index notFound() const
+ {
+ // default is to assert
+ llassert(false);
+ return Index(-1);
+ }
+ void addEntry(Index index, Entry *entry)
+ {
+ if (lookup(index))
+ {
+ llerrs << "Dictionary entry already added (attempted to add duplicate entry)" << llendl;
+ }
+ (*this)[index] = entry;
+ }
+};
+
+#endif // LL_LLDICTIONARY_H
diff --git a/indra/llcommon/lldoubledispatch.h b/indra/llcommon/lldoubledispatch.h
new file mode 100755
index 0000000000..60678d44fb
--- /dev/null
+++ b/indra/llcommon/lldoubledispatch.h
@@ -0,0 +1,332 @@
+/**
+ * @file lldoubledispatch.h
+ * @author Nat Goodspeed
+ * @date 2008-11-11
+ * @brief function calls virtual on more than one parameter
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLDOUBLEDISPATCH_H)
+#define LL_LLDOUBLEDISPATCH_H
+
+#include <list>
+#include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
+#include <boost/ref.hpp>
+
+/**
+ * This class supports function calls which are virtual on the dynamic type of
+ * more than one parameter. Specifically, we address a limited but useful
+ * subset of that problem: function calls which accept two parameters, and
+ * select which particular function to call depending on the dynamic type of
+ * both.
+ *
+ * Scott Meyers, in More Effective C++ (Item 31), talks about some of the perils
+ * and pitfalls lurking down this pathway. He discusses and dismisses the
+ * straightforward approaches of using single-dispatch virtual functions twice,
+ * and of using a family of single-dispatch virtual functions which each examine
+ * RTTI for their other parameter. He advocates using a registry in which you
+ * look up the actual types of both parameters (he uses the classes' string names,
+ * via typeid(param).name()) to obtain a pointer to a free (non-member) function
+ * that will accept this pair of parameters.
+ *
+ * He does point out that his approach doesn't handle inheritance. If you have a
+ * registry entry for SpaceShip, and you have in hand a MilitaryShip (subclass of
+ * SpaceShip) and an Asteroid, you'd like to call the function appropriate for
+ * SpaceShips and Asteroids -- but alas, his lookup fails because the class name
+ * for your MilitaryShip subclass isn't in the registry.
+ *
+ * This class extends his idea to build a registry whose entries can examine the
+ * dynamic type of the parameter in a more flexible way -- using dynamic_cast<>
+ * -- thereby supporting inheritance relationships.
+ *
+ * Of course we must allow for the ambiguity this permits. We choose to use a
+ * sequence container rather than a map, and require that the client code
+ * specify the order in which dispatch-table entries should be searched. The
+ * result resembles the semantics of the catch clauses for a try/catch block:
+ * you must code catch clauses in decreasing order of specificity, because if
+ * you catch ErrorBaseClass before you catch ErrorSubclass, then any
+ * ErrorSubclass exceptions thrown by the protected code will always match
+ * ErrorBaseClass, and you will never reach your catch(ErrorSubclass) clause.
+ *
+ * So, in a similar way, if you have a specific routine to process
+ * MilitaryShip and Asteroid, you'd better place that in the table @em before
+ * your more general routine that processes SpaceShip and Asteroid, or else
+ * the MilitaryShip variant will never be called.
+ *
+ * @todo This implementation doesn't attempt to deal with
+ * <tt>const</tt>-correctness of arguments. Our container stores templated
+ * objects into which the specific parameter types have been "frozen." But to
+ * store all these in the same container, they are all instances of a base
+ * class with a virtual invocation method. Naturally the base-class virtual
+ * method definition cannot know the <tt>const</tt>-ness of the particular
+ * types with which its template subclass is instantiated.
+ *
+ * One is tempted to suggest four different virtual methods, one for each
+ * combination of @c const and non-<tt>const</tt> arguments. Then the client
+ * will select the particular virtual method that best fits the
+ * <tt>const</tt>-ness of the arguments in hand. The trouble with that idea is
+ * that in order to instantiate the subclass instance, we must compile all
+ * four of its virtual method overrides, which means we must be prepared to
+ * pass all four combinations of @c const and non-<tt>const</tt> arguments to
+ * the registered callable. That only works when the registered callable
+ * accepts both parameters as @c const.
+ *
+ * Of course the virtual method overrides could use @c const_cast to force
+ * them to compile correctly regardless of the <tt>const</tt>-ness of the
+ * registered callable's parameter declarations. But if we're going to force
+ * the issue with @c const_cast anyway, why bother with the four different
+ * virtual methods? Why not just require canonical parameter
+ * <tt>const</tt>-ness for any callables used with this mechanism?
+ *
+ * We therefore require that your callable accept both params as
+ * non-<tt>const</tt>. (This is more general than @c const: you can perform @c
+ * const operations on a non-<tt>const</tt> parameter, but you can't perform
+ * non-<tt>const</tt> operations on a @c const parameter.)
+ *
+ * For ease of use, though, our invocation method accepts both params as @c
+ * const. Again, you can pass a non-<tt>const</tt> object to a @c const param,
+ * but not the other way around. We take care of the @c const_cast for you.
+ */
+// LLDoubleDispatch is a template because we have to assume that all parameter
+// types are subclasses of some common base class -- but we don't have to
+// impose that base class on client code. Instead, we let IT tell US the
+// common parameter base class.
+template<class ReturnType, class ParamBaseType>
+class LLDoubleDispatch
+{
+ typedef LLDoubleDispatch<ReturnType, ParamBaseType> self_type;
+
+public:
+ LLDoubleDispatch() {}
+
+ /**
+ * Call the first matching entry. If there's no registered Functor
+ * appropriate for this pair of parameter types, this call will do
+ * @em nothing! (If you want notification in this case, simply add a new
+ * Functor for (ParamBaseType&, ParamBaseType&) at the end of the table.
+ * The two base-class entries should match anything that isn't matched by
+ * any more specific entry.)
+ *
+ * See note in class documentation about <tt>const</tt>-correctness.
+ */
+ inline
+ ReturnType operator()(const ParamBaseType& param1, const ParamBaseType& param2) const;
+
+ // Borrow a trick from Alexandrescu: use a Type class to "wrap" a type
+ // for purposes of passing the type itself into a template method.
+ template<typename T>
+ struct Type {};
+
+ /**
+ * Add a new Entry for a given @a Functor. As mentioned above, the order
+ * in which you add these entries is very important.
+ *
+ * If you want symmetrical entries -- that is, if a B and an A can call
+ * the same Functor as an A and a B -- then pass @c true for the last
+ * parameter, and we'll add a (B, A) entry as well as an (A, B) entry. But
+ * your @a Functor can still be written to expect exactly the pair of types
+ * you've explicitly specified, because the Entry with the reversed params
+ * will call a special thunk that swaps params before calling your @a
+ * Functor.
+ */
+ template<typename Type1, typename Type2, class Functor>
+ void add(const Type<Type1>& t1, const Type<Type2>& t2, Functor func, bool symmetrical=false)
+ {
+ insert(t1, t2, func);
+ if (symmetrical)
+ {
+ // Use boost::bind() to construct a param-swapping thunk. Don't
+ // forget to reverse the parameters too.
+ insert(t2, t1, boost::bind(func, _2, _1));
+ }
+ }
+
+ /**
+ * Add a new Entry for a given @a Functor, explicitly passing instances of
+ * the Functor's leaf param types to help us figure out where to insert.
+ * Because it can use RTTI, this add() method isn't order-sensitive like
+ * the other one.
+ *
+ * If you want symmetrical entries -- that is, if a B and an A can call
+ * the same Functor as an A and a B -- then pass @c true for the last
+ * parameter, and we'll add a (B, A) entry as well as an (A, B) entry. But
+ * your @a Functor can still be written to expect exactly the pair of types
+ * you've explicitly specified, because the Entry with the reversed params
+ * will call a special thunk that swaps params before calling your @a
+ * Functor.
+ */
+ template <typename Type1, typename Type2, class Functor>
+ void add(const Type1& prototype1, const Type2& prototype2, Functor func, bool symmetrical=false)
+ {
+ // Because we expect our caller to pass leaf param types, we can just
+ // perform an ordinary search to find the first matching iterator. If
+ // we find an existing Entry that matches both params, either the
+ // param types are the same, or the existing Entry uses the base class
+ // for one or both params, and the new Entry must precede that. Assume
+ // our client won't register two callables with exactly the SAME set
+ // of types; in that case we'll insert the new one before any earlier
+ // ones, meaning the last one registered will "win." Note that if
+ // find() doesn't find any matching Entry, it will return end(),
+ // meaning the new Entry will be last, which is fine.
+ typename DispatchTable::iterator insertion = find(prototype1, prototype2);
+ insert(Type<Type1>(), Type<Type2>(), func, insertion);
+ if (symmetrical)
+ {
+ insert(Type<Type2>(), Type<Type1>(), boost::bind(func, _2, _1), insertion);
+ }
+ }
+
+ /**
+ * Add a new Entry for a given @a Functor, specifying the Functor's leaf
+ * param types as explicit template arguments. This will instantiate
+ * temporary objects of each of these types, which requires that they have
+ * a lightweight default constructor.
+ *
+ * If you want symmetrical entries -- that is, if a B and an A can call
+ * the same Functor as an A and a B -- then pass @c true for the last
+ * parameter, and we'll add a (B, A) entry as well as an (A, B) entry. But
+ * your @a Functor can still be written to expect exactly the pair of types
+ * you've explicitly specified, because the Entry with the reversed params
+ * will call a special thunk that swaps params before calling your @a
+ * Functor.
+ */
+ template <typename Type1, typename Type2, class Functor>
+ void add(Functor func, bool symmetrical=false)
+ {
+ // This is a convenience wrapper for the add() variant taking explicit
+ // instances.
+ add(Type1(), Type2(), func, symmetrical);
+ }
+
+private:
+ /// This is the base class for each entry in our dispatch table.
+ struct EntryBase
+ {
+ virtual ~EntryBase() {}
+ virtual bool matches(const ParamBaseType& param1, const ParamBaseType& param2) const = 0;
+ virtual ReturnType operator()(ParamBaseType& param1, ParamBaseType& param2) const = 0;
+ };
+
+ /// Here's the template subclass that actually creates each entry.
+ template<typename Type1, typename Type2, class Functor>
+ class Entry: public EntryBase
+ {
+ public:
+ Entry(Functor func): mFunc(func) {}
+ /// Is this entry appropriate for these arguments?
+ virtual bool matches(const ParamBaseType& param1, const ParamBaseType& param2) const
+ {
+ return (dynamic_cast<const Type1*>(&param1) &&
+ dynamic_cast<const Type2*>(&param2));
+ }
+ /// invocation
+ virtual ReturnType operator()(ParamBaseType& param1, ParamBaseType& param2) const
+ {
+ // We perform the downcast so callable can accept leaf param
+ // types, instead of accepting ParamBaseType and downcasting
+ // explicitly.
+ return mFunc(dynamic_cast<Type1&>(param1), dynamic_cast<Type2&>(param2));
+ }
+ private:
+ /// Bind whatever function or function object the instantiator passed.
+ Functor mFunc;
+ };
+
+ /// shared_ptr manages Entry lifespan for us
+ typedef boost::shared_ptr<EntryBase> EntryPtr;
+ /// use a @c list to make it easy to insert
+ typedef std::list<EntryPtr> DispatchTable;
+ DispatchTable mDispatch;
+
+ /// Look up the location of the first matching entry.
+ typename DispatchTable::const_iterator find(const ParamBaseType& param1, const ParamBaseType& param2) const
+ {
+ // We assert that it's safe to call the non-const find() method on a
+ // const LLDoubleDispatch instance. Cast away the const-ness of 'this'.
+ return const_cast<self_type*>(this)->find(param1, param2);
+ }
+
+ /// Look up the location of the first matching entry.
+ typename DispatchTable::iterator find(const ParamBaseType& param1, const ParamBaseType& param2)
+ {
+ return std::find_if(mDispatch.begin(), mDispatch.end(),
+ boost::bind(&EntryBase::matches, _1,
+ boost::ref(param1), boost::ref(param2)));
+ }
+
+ /// Look up the first matching entry.
+ EntryPtr lookup(const ParamBaseType& param1, const ParamBaseType& param2) const
+ {
+ typename DispatchTable::const_iterator found = find(param1, param2);
+ if (found != mDispatch.end())
+ {
+ // Dereferencing the list iterator gets us an EntryPtr
+ return *found;
+ }
+ // not found
+ return EntryPtr();
+ }
+
+ // Break out the actual insert operation so the public add() template
+ // function can avoid calling itself recursively. See add() comments.
+ template<typename Type1, typename Type2, class Functor>
+ void insert(const Type<Type1>& param1, const Type<Type2>& param2, Functor func)
+ {
+ insert(param1, param2, func, mDispatch.end());
+ }
+
+ // Break out the actual insert operation so the public add() template
+ // function can avoid calling itself recursively. See add() comments.
+ template<typename Type1, typename Type2, class Functor>
+ void insert(const Type<Type1>&, const Type<Type2>&, Functor func,
+ typename DispatchTable::iterator where)
+ {
+ mDispatch.insert(where, EntryPtr(new Entry<Type1, Type2, Functor>(func)));
+ }
+
+ /// Don't implement the copy ctor. Everyone will be happier if the
+ /// LLDoubleDispatch object isn't copied.
+ LLDoubleDispatch(const LLDoubleDispatch& src);
+};
+
+template <class ReturnType, class ParamBaseType>
+ReturnType LLDoubleDispatch<ReturnType, ParamBaseType>::operator()(const ParamBaseType& param1,
+ const ParamBaseType& param2) const
+{
+ EntryPtr found = lookup(param1, param2);
+ if (found.get() == 0)
+ return ReturnType(); // bogus return value
+
+ // otherwise, call the Functor we found
+ return (*found)(const_cast<ParamBaseType&>(param1), const_cast<ParamBaseType&>(param2));
+}
+
+#endif /* ! defined(LL_LLDOUBLEDISPATCH_H) */
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index b135dafb3c..bd334a6654 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -45,20 +45,16 @@
# include <syslog.h>
# include <unistd.h>
#endif // !LL_WINDOWS
-#if LL_WINDOWS
-# include <windows.h>
-#endif // LL_WINDOWS
#include <vector>
#include "llapp.h"
#include "llapr.h"
#include "llfile.h"
-#include "llfixedbuffer.h"
#include "lllivefile.h"
#include "llsd.h"
#include "llsdserialize.h"
#include "llstl.h"
-
+#include "lltimer.h"
namespace {
#if !LL_WINDOWS
@@ -192,16 +188,16 @@ namespace {
class RecordToFixedBuffer : public LLError::Recorder
{
public:
- RecordToFixedBuffer(LLFixedBuffer& buffer) : mBuffer(buffer) { }
+ RecordToFixedBuffer(LLLineBuffer* buffer) : mBuffer(buffer) { }
virtual void recordMessage(LLError::ELevel level,
- const std::string& message)
+ const std::string& message)
{
- mBuffer.addLine(message);
+ mBuffer->addLine(message);
}
private:
- LLFixedBuffer& mBuffer;
+ LLLineBuffer* mBuffer;
};
#if LL_WINDOWS
@@ -209,7 +205,7 @@ namespace {
{
public:
virtual void recordMessage(LLError::ELevel level,
- const std::string& message)
+ const std::string& message)
{
llutf16string utf16str =
wstring_to_utf16str(utf8str_to_wstring(message));
@@ -433,7 +429,7 @@ namespace LLError
Settings()
: printLocation(false),
defaultLevel(LLError::LEVEL_DEBUG),
- crashFunction(NULL),
+ crashFunction(),
timeFunction(NULL),
fileRecorder(NULL),
fixedBufferRecorder(NULL),
@@ -601,12 +597,18 @@ namespace LLError
s.printLocation = print;
}
- void setFatalFunction(FatalFunction f)
+ void setFatalFunction(const FatalFunction& f)
{
Settings& s = Settings::get();
s.crashFunction = f;
}
+ FatalFunction getFatalFunction()
+ {
+ Settings& s = Settings::get();
+ return s.crashFunction;
+ }
+
void setTimeFunction(TimeFunction f)
{
Settings& s = Settings::get();
@@ -786,7 +788,7 @@ namespace LLError
addRecorder(f);
}
- void logToFixedBuffer(LLFixedBuffer* fixedBuffer)
+ void logToFixedBuffer(LLLineBuffer* fixedBuffer)
{
LLError::Settings& s = LLError::Settings::get();
@@ -799,7 +801,7 @@ namespace LLError
return;
}
- s.fixedBufferRecorder = new RecordToFixedBuffer(*fixedBuffer);
+ s.fixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer);
addRecorder(s.fixedBufferRecorder);
}
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 6794be4904..5a4c644859 100644
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -131,7 +131,7 @@ namespace LLError
class CallSite;
- class Log
+ class LL_COMMON_API Log
{
public:
static bool shouldLog(CallSite&);
@@ -140,7 +140,7 @@ namespace LLError
static void flush(std::ostringstream*, const CallSite&);
};
- class CallSite
+ class LL_COMMON_API CallSite
{
// Represents a specific place in the code where a message is logged
// This is public because it is used by the macros below. It is not
@@ -189,7 +189,7 @@ namespace LLError
//LLCallStacks is designed not to be thread-safe.
//so try not to use it in multiple parallel threads at same time.
//Used in a single thread at a time is fine.
- class LLCallStacks
+ class LL_COMMON_API LLCallStacks
{
private:
static char** sBuffer ;
@@ -239,7 +239,7 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
*/
#define lllog(level, broadTag, narrowTag, once) \
- { \
+ do { \
static LLError::CallSite _site( \
level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, broadTag, narrowTag, once);\
if (_site.shouldLog()) \
@@ -252,7 +252,7 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
LLError::End(); \
LLError::Log::flush(_out, _site); \
} \
- }
+ } while(0)
// DEPRECATED: Use the new macros that allow tags and *look* like macros.
#define lldebugs lllog(LLError::LEVEL_DEBUG, NULL, NULL, false)
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index a55d706d2e..233e9d3389 100644
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -35,10 +35,9 @@
#define LL_LLERRORCONTROL_H
#include "llerror.h"
-
+#include "boost/function.hpp"
#include <string>
-class LLFixedBuffer;
class LLSD;
/*
@@ -49,15 +48,27 @@ class LLSD;
These implementations are in llerror.cpp.
*/
+// Line buffer interface
+class LLLineBuffer
+{
+public:
+ LLLineBuffer() {};
+ virtual ~LLLineBuffer() {};
+
+ virtual void clear() = 0; // Clear the buffer, and reset it.
+
+ virtual void addLine(const std::string& utf8line) = 0;
+};
+
namespace LLError
{
- void initForServer(const std::string& identity);
+ LL_COMMON_API void initForServer(const std::string& identity);
// resets all logging settings to defaults needed by server processes
// logs to stderr, syslog, and windows debug log
// the identity string is used for in the syslog
- void initForApplication(const std::string& dir);
+ LL_COMMON_API void initForApplication(const std::string& dir);
// resets all logging settings to defaults needed by applicaitons
// logs to stderr and windows debug log
// sets up log configuration from the file logcontrol.xml in dir
@@ -68,13 +79,14 @@ namespace LLError
Setting a level means log messages at that level or above.
*/
- void setPrintLocation(bool);
- void setDefaultLevel(LLError::ELevel);
- void setFunctionLevel(const std::string& function_name, LLError::ELevel);
- void setClassLevel(const std::string& class_name, LLError::ELevel);
- void setFileLevel(const std::string& file_name, LLError::ELevel);
+ LL_COMMON_API void setPrintLocation(bool);
+ LL_COMMON_API void setDefaultLevel(LLError::ELevel);
+ LL_COMMON_API void setFunctionLevel(const std::string& function_name, LLError::ELevel);
+ LL_COMMON_API void setClassLevel(const std::string& class_name, LLError::ELevel);
+ LL_COMMON_API void setFileLevel(const std::string& file_name, LLError::ELevel);
+ LL_COMMON_API void setTagLevel(const std::string& file_name, LLError::ELevel);
- void configure(const LLSD&);
+ LL_COMMON_API void configure(const LLSD&);
// the LLSD can configure all of the settings
// usually read automatically from the live errorlog.xml file
@@ -83,26 +95,48 @@ namespace LLError
Control functions.
*/
- typedef void(*FatalFunction)(const std::string& message);
- void crashAndLoop(const std::string& message);
- // Default fatal funtion: access null pointer and loops forever
+ typedef boost::function<void(const std::string&)> FatalFunction;
+ LL_COMMON_API void crashAndLoop(const std::string& message);
+ // Default fatal function: access null pointer and loops forever
- void setFatalFunction(FatalFunction);
+ LL_COMMON_API void setFatalFunction(const FatalFunction&);
// The fatal function will be called when an message of LEVEL_ERROR
// is logged. Note: supressing a LEVEL_ERROR message from being logged
// (by, for example, setting a class level to LEVEL_NONE), will keep
// the that message from causing the fatal funciton to be invoked.
-
+
+ LL_COMMON_API FatalFunction getFatalFunction();
+ // Retrieve the previously-set FatalFunction
+
+ /// temporarily override the FatalFunction for the duration of a
+ /// particular scope, e.g. for unit tests
+ class LL_COMMON_API OverrideFatalFunction
+ {
+ public:
+ OverrideFatalFunction(const FatalFunction& func):
+ mPrev(getFatalFunction())
+ {
+ setFatalFunction(func);
+ }
+ ~OverrideFatalFunction()
+ {
+ setFatalFunction(mPrev);
+ }
+
+ private:
+ FatalFunction mPrev;
+ };
+
typedef std::string (*TimeFunction)();
- std::string utcTime();
+ LL_COMMON_API std::string utcTime();
- void setTimeFunction(TimeFunction);
+ LL_COMMON_API void setTimeFunction(TimeFunction);
// The function is use to return the current time, formatted for
// display by those error recorders that want the time included.
- class Recorder
+ class LL_COMMON_API Recorder
{
// An object that handles the actual output or error messages.
public:
@@ -116,17 +150,17 @@ namespace LLError
// included in the text of the message
};
- void addRecorder(Recorder*);
- void removeRecorder(Recorder*);
+ LL_COMMON_API void addRecorder(Recorder*);
+ LL_COMMON_API void removeRecorder(Recorder*);
// each error message is passed to each recorder via recordMessage()
- void logToFile(const std::string& filename);
- void logToFixedBuffer(LLFixedBuffer*);
+ LL_COMMON_API void logToFile(const std::string& filename);
+ LL_COMMON_API void logToFixedBuffer(LLLineBuffer*);
// Utilities to add recorders for logging to a file or a fixed buffer
// A second call to the same function will remove the logger added
// with the first.
// Passing the empty string or NULL to just removes any prior.
- std::string logFileName();
+ LL_COMMON_API std::string logFileName();
// returns name of current logging file, empty string if none
@@ -135,11 +169,11 @@ namespace LLError
*/
class Settings;
- Settings* saveAndResetSettings();
- void restoreSettings(Settings *);
+ LL_COMMON_API Settings* saveAndResetSettings();
+ LL_COMMON_API void restoreSettings(Settings *);
- std::string abbreviateFile(const std::string& filePath);
- int shouldLogCallCount();
+ LL_COMMON_API std::string abbreviateFile(const std::string& filePath);
+ LL_COMMON_API int shouldLogCallCount();
};
diff --git a/indra/llcommon/llerrorlegacy.h b/indra/llcommon/llerrorlegacy.h
index 7a970b1466..9920921a58 100644
--- a/indra/llcommon/llerrorlegacy.h
+++ b/indra/llcommon/llerrorlegacy.h
@@ -75,6 +75,10 @@ const int LL_ERR_PRICE_MISMATCH = -23018;
#define SHOW_ASSERT
#else // _DEBUG
+#ifdef LL_RELEASE_WITH_DEBUG_INFO
+#define SHOW_ASSERT
+#endif // LL_RELEASE_WITH_DEBUG_INFO
+
#ifdef RELEASE_SHOW_DEBUG
#define SHOW_DEBUG
#endif
diff --git a/indra/llcommon/llerrorthread.cpp b/indra/llcommon/llerrorthread.cpp
index 4c779c58c8..f0e46ae78d 100644
--- a/indra/llcommon/llerrorthread.cpp
+++ b/indra/llcommon/llerrorthread.cpp
@@ -31,7 +31,9 @@
#include "linden_common.h"
#include "llerrorthread.h"
+
#include "llapp.h"
+#include "lltimer.h" // ms_sleep()
LLErrorThread::LLErrorThread()
: LLThread("Error"),
diff --git a/indra/llcommon/llerrorthread.h b/indra/llcommon/llerrorthread.h
index f1d6ffc34f..3121d29675 100644
--- a/indra/llcommon/llerrorthread.h
+++ b/indra/llcommon/llerrorthread.h
@@ -35,7 +35,7 @@
#include "llthread.h"
-class LLErrorThread : public LLThread
+class LL_COMMON_API LLErrorThread : public LLThread
{
public:
LLErrorThread();
diff --git a/indra/llcommon/llevent.cpp b/indra/llcommon/llevent.cpp
index 24be6e8b34..f669d0e13f 100644
--- a/indra/llcommon/llevent.cpp
+++ b/indra/llcommon/llevent.cpp
@@ -34,6 +34,8 @@
#include "llevent.h"
+using namespace LLOldEvents;
+
/************************************************
Events
************************************************/
diff --git a/indra/llcommon/llevent.h b/indra/llcommon/llevent.h
index 60887a060a..0ea7cf4ae8 100644
--- a/indra/llcommon/llevent.h
+++ b/indra/llcommon/llevent.h
@@ -35,16 +35,19 @@
#define LL_EVENT_H
#include "llsd.h"
-#include "llmemory.h"
+#include "llpointer.h"
#include "llthread.h"
+namespace LLOldEvents
+{
+
class LLEventListener;
class LLEvent;
class LLEventDispatcher;
class LLObservable;
// Abstract event. All events derive from LLEvent
-class LLEvent : public LLThreadSafeRefCount
+class LL_COMMON_API LLEvent : public LLThreadSafeRefCount
{
protected:
virtual ~LLEvent();
@@ -72,7 +75,7 @@ private:
};
// Abstract listener. All listeners derive from LLEventListener
-class LLEventListener : public LLThreadSafeRefCount
+class LL_COMMON_API LLEventListener : public LLThreadSafeRefCount
{
protected:
virtual ~LLEventListener();
@@ -89,7 +92,7 @@ public:
};
// A listener which tracks references to it and cleans up when it's deallocated
-class LLSimpleListener : public LLEventListener
+class LL_COMMON_API LLSimpleListener : public LLEventListener
{
public:
void clearDispatchers();
@@ -114,7 +117,7 @@ struct LLListenerEntry
// Base class for a dispatcher - an object which listens
// to events being fired and relays them to their
// appropriate destinations.
-class LLEventDispatcher : public LLThreadSafeRefCount
+class LL_COMMON_API LLEventDispatcher : public LLThreadSafeRefCount
{
protected:
virtual ~LLEventDispatcher();
@@ -157,7 +160,7 @@ private:
// In order for this class to work properly, it needs
// an instance of an LLEventDispatcher to route events to their
// listeners.
-class LLObservable
+class LL_COMMON_API LLObservable
{
public:
// Initialize with the default Dispatcher
@@ -194,4 +197,6 @@ public:
LLSD mValue;
};
+} // LLOldEvents
+
#endif // LL_EVENT_H
diff --git a/indra/llcommon/lleventapi.cpp b/indra/llcommon/lleventapi.cpp
new file mode 100644
index 0000000000..1dd104da8f
--- /dev/null
+++ b/indra/llcommon/lleventapi.cpp
@@ -0,0 +1,30 @@
+/**
+ * @file lleventapi.cpp
+ * @author Nat Goodspeed
+ * @date 2009-11-10
+ * @brief Implementation for lleventapi.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "lleventapi.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+
+LLEventAPI::LLEventAPI(const std::string& name, const std::string& desc, const std::string& field):
+ lbase(name, field),
+ ibase(name),
+ mDesc(desc)
+{
+}
+
+LLEventAPI::~LLEventAPI()
+{
+}
diff --git a/indra/llcommon/lleventapi.h b/indra/llcommon/lleventapi.h
new file mode 100644
index 0000000000..96d1b03be8
--- /dev/null
+++ b/indra/llcommon/lleventapi.h
@@ -0,0 +1,66 @@
+/**
+ * @file lleventapi.h
+ * @author Nat Goodspeed
+ * @date 2009-10-28
+ * @brief LLEventAPI is the base class for every class that wraps a C++ API
+ * in an event API
+ * (see https://wiki.lindenlab.com/wiki/Incremental_Viewer_Automation/Event_API).
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLEVENTAPI_H)
+#define LL_LLEVENTAPI_H
+
+#include "lleventdispatcher.h"
+#include "llinstancetracker.h"
+#include <string>
+
+/**
+ * LLEventAPI not only provides operation dispatch functionality, inherited
+ * from LLDispatchListener -- it also gives us event API introspection.
+ * Deriving from LLInstanceTracker lets us enumerate instances.
+ */
+class LL_COMMON_API LLEventAPI: public LLDispatchListener,
+ public LLInstanceTracker<LLEventAPI, std::string>
+{
+ typedef LLDispatchListener lbase;
+ typedef LLInstanceTracker<LLEventAPI, std::string> ibase;
+
+public:
+ /**
+ * @param name LLEventPump name on which this LLEventAPI will listen. This
+ * also serves as the LLInstanceTracker instance key.
+ * @param desc Documentation string shown to a client trying to discover
+ * available event APIs.
+ * @param field LLSD::Map key used by LLDispatchListener to look up the
+ * subclass method to invoke [default "op"].
+ */
+ LLEventAPI(const std::string& name, const std::string& desc, const std::string& field="op");
+ virtual ~LLEventAPI();
+
+ /// Get the string name of this LLEventAPI
+ std::string getName() const { return ibase::getKey(); }
+ /// Get the documentation string
+ std::string getDesc() const { return mDesc; }
+
+ /**
+ * Publish only selected add() methods from LLEventDispatcher.
+ * Every LLEventAPI add() @em must have a description string.
+ */
+ template <typename CALLABLE>
+ void add(const std::string& name,
+ const std::string& desc,
+ CALLABLE callable,
+ const LLSD& required=LLSD())
+ {
+ LLEventDispatcher::add(name, desc, callable, required);
+ }
+
+private:
+ std::string mDesc;
+};
+
+#endif /* ! defined(LL_LLEVENTAPI_H) */
diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp
new file mode 100644
index 0000000000..d598f1cc4a
--- /dev/null
+++ b/indra/llcommon/lleventcoro.cpp
@@ -0,0 +1,129 @@
+/**
+ * @file lleventcoro.cpp
+ * @author Nat Goodspeed
+ * @date 2009-04-29
+ * @brief Implementation for lleventcoro.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "lleventcoro.h"
+// STL headers
+#include <map>
+// std headers
+// external library headers
+// other Linden headers
+#include "llsdserialize.h"
+#include "llerror.h"
+#include "llcoros.h"
+
+std::string LLEventDetail::listenerNameForCoroImpl(const void* self_id)
+{
+ // First, if this coroutine was launched by LLCoros::launch(), find that name.
+ std::string name(LLCoros::instance().getNameByID(self_id));
+ if (! name.empty())
+ {
+ return name;
+ }
+ // Apparently this coroutine wasn't launched by LLCoros::launch(). Check
+ // whether we have a memo for this self_id.
+ typedef std::map<const void*, std::string> MapType;
+ static MapType memo;
+ MapType::const_iterator found = memo.find(self_id);
+ if (found != memo.end())
+ {
+ // this coroutine instance has called us before, reuse same name
+ return found->second;
+ }
+ // this is the first time we've been called for this coroutine instance
+ name = LLEventPump::inventName("coro");
+ memo[self_id] = name;
+ LL_INFOS("LLEventCoro") << "listenerNameForCoroImpl(" << self_id << "): inventing coro name '"
+ << name << "'" << LL_ENDL;
+ return name;
+}
+
+void LLEventDetail::storeToLLSDPath(LLSD& dest, const LLSD& rawPath, const LLSD& value)
+{
+ if (rawPath.isUndefined())
+ {
+ // no-op case
+ return;
+ }
+
+ // Arrange to treat rawPath uniformly as an array. If it's not already an
+ // array, store it as the only entry in one.
+ LLSD path;
+ if (rawPath.isArray())
+ {
+ path = rawPath;
+ }
+ else
+ {
+ path.append(rawPath);
+ }
+
+ // Need to indicate a current destination -- but that current destination
+ // needs to change as we step through the path array. Where normally we'd
+ // use an LLSD& to capture a subscripted LLSD lvalue, this time we must
+ // instead use a pointer -- since it must be reassigned.
+ LLSD* pdest = &dest;
+
+ // Now loop through that array
+ for (LLSD::Integer i = 0; i < path.size(); ++i)
+ {
+ if (path[i].isString())
+ {
+ // *pdest is an LLSD map
+ pdest = &((*pdest)[path[i].asString()]);
+ }
+ else if (path[i].isInteger())
+ {
+ // *pdest is an LLSD array
+ pdest = &((*pdest)[path[i].asInteger()]);
+ }
+ else
+ {
+ // What do we do with Real or Array or Map or ...?
+ // As it's a coder error -- not a user error -- rub the coder's
+ // face in it so it gets fixed.
+ LL_ERRS("lleventcoro") << "storeToLLSDPath(" << dest << ", " << rawPath << ", " << value
+ << "): path[" << i << "] bad type " << path[i].type() << LL_ENDL;
+ }
+ }
+
+ // Here *pdest is where we should store value.
+ *pdest = value;
+}
+
+LLSD errorException(const LLEventWithID& result, const std::string& desc)
+{
+ // If the result arrived on the error pump (pump 1), instead of
+ // returning it, deliver it via exception.
+ if (result.second)
+ {
+ throw LLErrorEvent(desc, result.first);
+ }
+ // That way, our caller knows a simple return must be from the reply
+ // pump (pump 0).
+ return result.first;
+}
+
+LLSD errorLog(const LLEventWithID& result, const std::string& desc)
+{
+ // If the result arrived on the error pump (pump 1), log it as a fatal
+ // error.
+ if (result.second)
+ {
+ LL_ERRS("errorLog") << desc << ":" << std::endl;
+ LLSDSerialize::toPrettyXML(result.first, LL_CONT);
+ LL_CONT << LL_ENDL;
+ }
+ // A simple return must therefore be from the reply pump (pump 0).
+ return result.first;
+}
diff --git a/indra/llcommon/lleventcoro.h b/indra/llcommon/lleventcoro.h
new file mode 100644
index 0000000000..1981ae7482
--- /dev/null
+++ b/indra/llcommon/lleventcoro.h
@@ -0,0 +1,552 @@
+/**
+ * @file lleventcoro.h
+ * @author Nat Goodspeed
+ * @date 2009-04-29
+ * @brief Utilities to interface between coroutines and events.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLEVENTCORO_H)
+#define LL_LLEVENTCORO_H
+
+#include <boost/coroutine/coroutine.hpp>
+#include <boost/coroutine/future.hpp>
+#include <boost/optional.hpp>
+#include <string>
+#include <stdexcept>
+#include "llevents.h"
+#include "llerror.h"
+
+/**
+ * Like LLListenerOrPumpName, this is a class intended for parameter lists:
+ * accept a <tt>const LLEventPumpOrPumpName&</tt> and you can accept either an
+ * <tt>LLEventPump&</tt> or its string name. For a single parameter that could
+ * be either, it's not hard to overload the function -- but as soon as you
+ * want to accept two such parameters, this is cheaper than four overloads.
+ */
+class LLEventPumpOrPumpName
+{
+public:
+ /// Pass an actual LLEventPump&
+ LLEventPumpOrPumpName(LLEventPump& pump):
+ mPump(pump)
+ {}
+ /// Pass the string name of an LLEventPump
+ LLEventPumpOrPumpName(const std::string& pumpname):
+ mPump(LLEventPumps::instance().obtain(pumpname))
+ {}
+ /// Pass string constant name of an LLEventPump. This override must be
+ /// explicit, since otherwise passing <tt>const char*</tt> to a function
+ /// accepting <tt>const LLEventPumpOrPumpName&</tt> would require two
+ /// different implicit conversions: <tt>const char*</tt> -> <tt>const
+ /// std::string&</tt> -> <tt>const LLEventPumpOrPumpName&</tt>.
+ LLEventPumpOrPumpName(const char* pumpname):
+ mPump(LLEventPumps::instance().obtain(pumpname))
+ {}
+ /// Unspecified: "I choose not to identify an LLEventPump."
+ LLEventPumpOrPumpName() {}
+ operator LLEventPump& () const { return *mPump; }
+ LLEventPump& getPump() const { return *mPump; }
+ operator bool() const { return mPump; }
+ bool operator!() const { return ! mPump; }
+
+private:
+ boost::optional<LLEventPump&> mPump;
+};
+
+/// This is an adapter for a signature like void LISTENER(const LLSD&), which
+/// isn't a valid LLEventPump listener: such listeners should return bool.
+template <typename LISTENER>
+class LLVoidListener
+{
+public:
+ LLVoidListener(const LISTENER& listener):
+ mListener(listener)
+ {}
+ bool operator()(const LLSD& event)
+ {
+ mListener(event);
+ // don't swallow the event, let other listeners see it
+ return false;
+ }
+private:
+ LISTENER mListener;
+};
+
+/// LLVoidListener helper function to infer the type of the LISTENER
+template <typename LISTENER>
+LLVoidListener<LISTENER> voidlistener(const LISTENER& listener)
+{
+ return LLVoidListener<LISTENER>(listener);
+}
+
+namespace LLEventDetail
+{
+ /**
+ * waitForEventOn() permits a coroutine to temporarily listen on an
+ * LLEventPump any number of times. We don't really want to have to ask
+ * the caller to label each such call with a distinct string; the whole
+ * point of waitForEventOn() is to present a nice sequential interface to
+ * the underlying LLEventPump-with-named-listeners machinery. So we'll use
+ * LLEventPump::inventName() to generate a distinct name for each
+ * temporary listener. On the other hand, because a given coroutine might
+ * call waitForEventOn() any number of times, we don't really want to
+ * consume an arbitrary number of generated inventName()s: that namespace,
+ * though large, is nonetheless finite. So we memoize an invented name for
+ * each distinct coroutine instance (each different 'self' object). We
+ * can't know the type of 'self', because it depends on the coroutine
+ * body's signature. So we cast its address to void*, looking for distinct
+ * pointer values. Yes, that means that an early coroutine could cache a
+ * value here, then be destroyed, only to be supplanted by a later
+ * coroutine (of the same or different type), and we'll end up
+ * "recognizing" the second one and reusing the listener name -- but
+ * that's okay, since it won't collide with any listener name used by the
+ * earlier coroutine since that earlier coroutine no longer exists.
+ */
+ template <typename COROUTINE_SELF>
+ std::string listenerNameForCoro(COROUTINE_SELF& self)
+ {
+ return listenerNameForCoroImpl(self.get_id());
+ }
+
+ /// Implementation for listenerNameForCoro()
+ LL_COMMON_API std::string listenerNameForCoroImpl(const void* self_id);
+
+ /**
+ * Implement behavior described for postAndWait()'s @a replyPumpNamePath
+ * parameter:
+ *
+ * * If <tt>path.isUndefined()</tt>, do nothing.
+ * * If <tt>path.isString()</tt>, @a dest is an LLSD map: store @a value
+ * into <tt>dest[path.asString()]</tt>.
+ * * If <tt>path.isInteger()</tt>, @a dest is an LLSD array: store @a
+ * value into <tt>dest[path.asInteger()]</tt>.
+ * * If <tt>path.isArray()</tt>, iteratively apply the rules above to step
+ * down through the structure of @a dest. The last array entry in @a
+ * path specifies the entry in the lowest-level structure in @a dest
+ * into which to store @a value.
+ *
+ * @note
+ * In the degenerate case in which @a path is an empty array, @a dest will
+ * @em become @a value rather than @em containing it.
+ */
+ LL_COMMON_API void storeToLLSDPath(LLSD& dest, const LLSD& path, const LLSD& value);
+} // namespace LLEventDetail
+
+/**
+ * Post specified LLSD event on the specified LLEventPump, then wait for a
+ * response on specified other LLEventPump. This is more than mere
+ * convenience: the difference between this function and the sequence
+ * @code
+ * requestPump.post(myEvent);
+ * LLSD reply = waitForEventOn(self, replyPump);
+ * @endcode
+ * is that the sequence above fails if the reply is posted immediately on
+ * @a replyPump, that is, before <tt>requestPump.post()</tt> returns. In the
+ * sequence above, the running coroutine isn't even listening on @a replyPump
+ * until <tt>requestPump.post()</tt> returns and @c waitForEventOn() is
+ * entered. Therefore, the coroutine completely misses an immediate reply
+ * event, making it wait indefinitely.
+ *
+ * By contrast, postAndWait() listens on the @a replyPump @em before posting
+ * the specified LLSD event on the specified @a requestPump.
+ *
+ * @param self The @c self object passed into a coroutine
+ * @param event LLSD data to be posted on @a requestPump
+ * @param requestPump an LLEventPump on which to post @a event. Pass either
+ * the LLEventPump& or its string name. However, if you pass a
+ * default-constructed @c LLEventPumpOrPumpName, we skip the post() call.
+ * @param replyPump an LLEventPump on which postAndWait() will listen for a
+ * reply. Pass either the LLEventPump& or its string name. The calling
+ * coroutine will wait until that reply arrives. (If you're concerned about a
+ * reply that might not arrive, please see also LLEventTimeout.)
+ * @param replyPumpNamePath specifies the location within @a event in which to
+ * store <tt>replyPump.getName()</tt>. This is a strictly optional convenience
+ * feature; obviously you can store the name in @a event "by hand" if desired.
+ * @a replyPumpNamePath can be specified in any of four forms:
+ * * @c isUndefined() (default-constructed LLSD object): do nothing. This is
+ * the default behavior if you omit @a replyPumpNamePath.
+ * * @c isInteger(): @a event is an array. Store <tt>replyPump.getName()</tt>
+ * in <tt>event[replyPumpNamePath.asInteger()]</tt>.
+ * * @c isString(): @a event is a map. Store <tt>replyPump.getName()</tt> in
+ * <tt>event[replyPumpNamePath.asString()]</tt>.
+ * * @c isArray(): @a event has several levels of structure, e.g. map of
+ * maps, array of arrays, array of maps, map of arrays, ... Store
+ * <tt>replyPump.getName()</tt> in
+ * <tt>event[replyPumpNamePath[0]][replyPumpNamePath[1]]...</tt> In other
+ * words, examine each array entry in @a replyPumpNamePath in turn. If it's an
+ * <tt>LLSD::String</tt>, the current level of @a event is a map; step down to
+ * that map entry. If it's an <tt>LLSD::Integer</tt>, the current level of @a
+ * event is an array; step down to that array entry. The last array entry in
+ * @a replyPumpNamePath specifies the entry in the lowest-level structure in
+ * @a event into which to store <tt>replyPump.getName()</tt>.
+ */
+template <typename SELF>
+LLSD postAndWait(SELF& self, const LLSD& event, const LLEventPumpOrPumpName& requestPump,
+ const LLEventPumpOrPumpName& replyPump, const LLSD& replyPumpNamePath=LLSD())
+{
+ // declare the future
+ boost::coroutines::future<LLSD> future(self);
+ // make a callback that will assign a value to the future, and listen on
+ // the specified LLEventPump with that callback
+ std::string listenerName(LLEventDetail::listenerNameForCoro(self));
+ LLTempBoundListener connection(
+ replyPump.getPump().listen(listenerName,
+ voidlistener(boost::coroutines::make_callback(future))));
+ // skip the "post" part if requestPump is default-constructed
+ if (requestPump)
+ {
+ // If replyPumpNamePath is non-empty, store the replyPump name in the
+ // request event.
+ LLSD modevent(event);
+ LLEventDetail::storeToLLSDPath(modevent, replyPumpNamePath, replyPump.getPump().getName());
+ LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << listenerName
+ << " posting to " << requestPump.getPump().getName()
+ << LL_ENDL;
+
+ // *NOTE:Mani - Removed because modevent could contain user's hashed passwd.
+ // << ": " << modevent << LL_ENDL;
+ requestPump.getPump().post(modevent);
+ }
+ LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << listenerName
+ << " about to wait on LLEventPump " << replyPump.getPump().getName()
+ << LL_ENDL;
+ // trying to dereference ("resolve") the future makes us wait for it
+ LLSD value(*future);
+ LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << listenerName
+ << " resuming with " << value << LL_ENDL;
+ // returning should disconnect the connection
+ return value;
+}
+
+/// Wait for the next event on the specified LLEventPump. Pass either the
+/// LLEventPump& or its string name.
+template <typename SELF>
+LLSD waitForEventOn(SELF& self, const LLEventPumpOrPumpName& pump)
+{
+ // This is now a convenience wrapper for postAndWait().
+ return postAndWait(self, LLSD(), LLEventPumpOrPumpName(), pump);
+}
+
+/// return type for two-pump variant of waitForEventOn()
+typedef std::pair<LLSD, int> LLEventWithID;
+
+namespace LLEventDetail
+{
+ /**
+ * This helper is specifically for the two-pump version of waitForEventOn().
+ * We use a single future object, but we want to listen on two pumps with it.
+ * Since we must still adapt from (the callable constructed by)
+ * boost::coroutines::make_callback() (void return) to provide an event
+ * listener (bool return), we've adapted LLVoidListener for the purpose. The
+ * basic idea is that we construct a distinct instance of WaitForEventOnHelper
+ * -- binding different instance data -- for each of the pumps. Then, when a
+ * pump delivers an LLSD value to either WaitForEventOnHelper, it can combine
+ * that LLSD with its discriminator to feed the future object.
+ */
+ template <typename LISTENER>
+ class WaitForEventOnHelper
+ {
+ public:
+ WaitForEventOnHelper(const LISTENER& listener, int discriminator):
+ mListener(listener),
+ mDiscrim(discriminator)
+ {}
+ // this signature is required for an LLEventPump listener
+ bool operator()(const LLSD& event)
+ {
+ // our future object is defined to accept LLEventWithID
+ mListener(LLEventWithID(event, mDiscrim));
+ // don't swallow the event, let other listeners see it
+ return false;
+ }
+ private:
+ LISTENER mListener;
+ const int mDiscrim;
+ };
+
+ /// WaitForEventOnHelper type-inference helper
+ template <typename LISTENER>
+ WaitForEventOnHelper<LISTENER> wfeoh(const LISTENER& listener, int discriminator)
+ {
+ return WaitForEventOnHelper<LISTENER>(listener, discriminator);
+ }
+} // namespace LLEventDetail
+
+/**
+ * This function waits for a reply on either of two specified LLEventPumps.
+ * Otherwise, it closely resembles postAndWait(); please see the documentation
+ * for that function for detailed parameter info.
+ *
+ * While we could have implemented the single-pump variant in terms of this
+ * one, there's enough added complexity here to make it worthwhile to give the
+ * single-pump variant its own straightforward implementation. Conversely,
+ * though we could use preprocessor logic to generate n-pump overloads up to
+ * BOOST_COROUTINE_WAIT_MAX, we don't foresee a use case. This two-pump
+ * overload exists because certain event APIs are defined in terms of a reply
+ * LLEventPump and an error LLEventPump.
+ *
+ * The LLEventWithID return value provides not only the received event, but
+ * the index of the pump on which it arrived (0 or 1).
+ *
+ * @note
+ * I'd have preferred to overload the name postAndWait() for both signatures.
+ * But consider the following ambiguous call:
+ * @code
+ * postAndWait(self, LLSD(), requestPump, replyPump, "someString");
+ * @endcode
+ * "someString" could be converted to either LLSD (@a replyPumpNamePath for
+ * the single-pump function) or LLEventOrPumpName (@a replyPump1 for two-pump
+ * function).
+ *
+ * It seems less burdensome to write postAndWait2() than to write either
+ * LLSD("someString") or LLEventOrPumpName("someString").
+ */
+template <typename SELF>
+LLEventWithID postAndWait2(SELF& self, const LLSD& event,
+ const LLEventPumpOrPumpName& requestPump,
+ const LLEventPumpOrPumpName& replyPump0,
+ const LLEventPumpOrPumpName& replyPump1,
+ const LLSD& replyPump0NamePath=LLSD(),
+ const LLSD& replyPump1NamePath=LLSD())
+{
+ // declare the future
+ boost::coroutines::future<LLEventWithID> future(self);
+ // either callback will assign a value to this future; listen on
+ // each specified LLEventPump with a callback
+ std::string name(LLEventDetail::listenerNameForCoro(self));
+ LLTempBoundListener connection0(
+ replyPump0.getPump().listen(name + "a",
+ LLEventDetail::wfeoh(boost::coroutines::make_callback(future), 0)));
+ LLTempBoundListener connection1(
+ replyPump1.getPump().listen(name + "b",
+ LLEventDetail::wfeoh(boost::coroutines::make_callback(future), 1)));
+ // skip the "post" part if requestPump is default-constructed
+ if (requestPump)
+ {
+ // If either replyPumpNamePath is non-empty, store the corresponding
+ // replyPump name in the request event.
+ LLSD modevent(event);
+ LLEventDetail::storeToLLSDPath(modevent, replyPump0NamePath,
+ replyPump0.getPump().getName());
+ LLEventDetail::storeToLLSDPath(modevent, replyPump1NamePath,
+ replyPump1.getPump().getName());
+ LL_DEBUGS("lleventcoro") << "postAndWait2(): coroutine " << name
+ << " posting to " << requestPump.getPump().getName()
+ << ": " << modevent << LL_ENDL;
+ requestPump.getPump().post(modevent);
+ }
+ LL_DEBUGS("lleventcoro") << "postAndWait2(): coroutine " << name
+ << " about to wait on LLEventPumps " << replyPump0.getPump().getName()
+ << ", " << replyPump1.getPump().getName() << LL_ENDL;
+ // trying to dereference ("resolve") the future makes us wait for it
+ LLEventWithID value(*future);
+ LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << name
+ << " resuming with (" << value.first << ", " << value.second << ")"
+ << LL_ENDL;
+ // returning should disconnect both connections
+ return value;
+}
+
+/**
+ * Wait for the next event on either of two specified LLEventPumps.
+ */
+template <typename SELF>
+LLEventWithID
+waitForEventOn(SELF& self,
+ const LLEventPumpOrPumpName& pump0, const LLEventPumpOrPumpName& pump1)
+{
+ // This is now a convenience wrapper for postAndWait2().
+ return postAndWait2(self, LLSD(), LLEventPumpOrPumpName(), pump0, pump1);
+}
+
+/**
+ * Helper for the two-pump variant of waitForEventOn(), e.g.:
+ *
+ * @code
+ * LLSD reply = errorException(waitForEventOn(self, replyPump, errorPump),
+ * "error response from login.cgi");
+ * @endcode
+ *
+ * Examines an LLEventWithID, assuming that the second pump (pump 1) is
+ * listening for an error indication. If the incoming data arrived on pump 1,
+ * throw an LLErrorEvent exception. If the incoming data arrived on pump 0,
+ * just return it. Since a normal return can only be from pump 0, we no longer
+ * need the LLEventWithID's discriminator int; we can just return the LLSD.
+ *
+ * @note I'm not worried about introducing the (fairly generic) name
+ * errorException() into global namespace, because how many other overloads of
+ * the same name are going to accept an LLEventWithID parameter?
+ */
+LLSD errorException(const LLEventWithID& result, const std::string& desc);
+
+/**
+ * Exception thrown by errorException(). We don't call this LLEventError
+ * because it's not an error in event processing: rather, this exception
+ * announces an event that bears error information (for some other API).
+ */
+class LL_COMMON_API LLErrorEvent: public std::runtime_error
+{
+public:
+ LLErrorEvent(const std::string& what, const LLSD& data):
+ std::runtime_error(what),
+ mData(data)
+ {}
+ virtual ~LLErrorEvent() throw() {}
+
+ LLSD getData() const { return mData; }
+
+private:
+ LLSD mData;
+};
+
+/**
+ * Like errorException(), save that this trips a fatal error using LL_ERRS
+ * rather than throwing an exception.
+ */
+LL_COMMON_API LLSD errorLog(const LLEventWithID& result, const std::string& desc);
+
+/**
+ * Certain event APIs require the name of an LLEventPump on which they should
+ * post results. While it works to invent a distinct name and let
+ * LLEventPumps::obtain() instantiate the LLEventPump as a "named singleton,"
+ * in a certain sense it's more robust to instantiate a local LLEventPump and
+ * provide its name instead. This class packages the following idiom:
+ *
+ * 1. Instantiate a local LLCoroEventPump, with an optional name prefix.
+ * 2. Provide its actual name to the event API in question as the name of the
+ * reply LLEventPump.
+ * 3. Initiate the request to the event API.
+ * 4. Call your LLEventTempStream's wait() method to wait for the reply.
+ * 5. Let the LLCoroEventPump go out of scope.
+ */
+class LL_COMMON_API LLCoroEventPump
+{
+public:
+ LLCoroEventPump(const std::string& name="coro"):
+ mPump(name, true) // allow tweaking the pump instance name
+ {}
+ /// It's typical to request the LLEventPump name to direct an event API to
+ /// send its response to this pump.
+ std::string getName() const { return mPump.getName(); }
+ /// Less typically, we'd request the pump itself for some reason.
+ LLEventPump& getPump() { return mPump; }
+
+ /**
+ * Wait for an event on this LLEventPump.
+ *
+ * @note
+ * The other major usage pattern we considered was to bind @c self at
+ * LLCoroEventPump construction time, which would avoid passing the
+ * parameter to each wait() call. But if we were going to bind @c self as
+ * a class member, we'd need to specify a class template parameter
+ * indicating its type. The big advantage of passing it to the wait() call
+ * is that the type can be implicit.
+ */
+ template <typename SELF>
+ LLSD wait(SELF& self)
+ {
+ return waitForEventOn(self, mPump);
+ }
+
+ template <typename SELF>
+ LLSD postAndWait(SELF& self, const LLSD& event, const LLEventPumpOrPumpName& requestPump,
+ const LLSD& replyPumpNamePath=LLSD())
+ {
+ return ::postAndWait(self, event, requestPump, mPump, replyPumpNamePath);
+ }
+
+private:
+ LLEventStream mPump;
+};
+
+/**
+ * Other event APIs require the names of two different LLEventPumps: one for
+ * success response, the other for error response. Extend LLCoroEventPump
+ * for the two-pump use case.
+ */
+class LL_COMMON_API LLCoroEventPumps
+{
+public:
+ LLCoroEventPumps(const std::string& name="coro",
+ const std::string& suff0="Reply",
+ const std::string& suff1="Error"):
+ mPump0(name + suff0, true), // allow tweaking the pump instance name
+ mPump1(name + suff1, true)
+ {}
+ /// request pump 0's name
+ std::string getName0() const { return mPump0.getName(); }
+ /// request pump 1's name
+ std::string getName1() const { return mPump1.getName(); }
+ /// request both names
+ std::pair<std::string, std::string> getNames() const
+ {
+ return std::pair<std::string, std::string>(mPump0.getName(), mPump1.getName());
+ }
+
+ /// request pump 0
+ LLEventPump& getPump0() { return mPump0; }
+ /// request pump 1
+ LLEventPump& getPump1() { return mPump1; }
+
+ /// waitForEventOn(self, either of our two LLEventPumps)
+ template <typename SELF>
+ LLEventWithID wait(SELF& self)
+ {
+ return waitForEventOn(self, mPump0, mPump1);
+ }
+
+ /// errorException(wait(self))
+ template <typename SELF>
+ LLSD waitWithException(SELF& self)
+ {
+ return errorException(wait(self), std::string("Error event on ") + getName1());
+ }
+
+ /// errorLog(wait(self))
+ template <typename SELF>
+ LLSD waitWithLog(SELF& self)
+ {
+ return errorLog(wait(self), std::string("Error event on ") + getName1());
+ }
+
+ template <typename SELF>
+ LLEventWithID postAndWait(SELF& self, const LLSD& event,
+ const LLEventPumpOrPumpName& requestPump,
+ const LLSD& replyPump0NamePath=LLSD(),
+ const LLSD& replyPump1NamePath=LLSD())
+ {
+ return postAndWait2(self, event, requestPump, mPump0, mPump1,
+ replyPump0NamePath, replyPump1NamePath);
+ }
+
+ template <typename SELF>
+ LLSD postAndWaitWithException(SELF& self, const LLSD& event,
+ const LLEventPumpOrPumpName& requestPump,
+ const LLSD& replyPump0NamePath=LLSD(),
+ const LLSD& replyPump1NamePath=LLSD())
+ {
+ return errorException(postAndWait(self, event, requestPump,
+ replyPump0NamePath, replyPump1NamePath),
+ std::string("Error event on ") + getName1());
+ }
+
+ template <typename SELF>
+ LLSD postAndWaitWithLog(SELF& self, const LLSD& event,
+ const LLEventPumpOrPumpName& requestPump,
+ const LLSD& replyPump0NamePath=LLSD(),
+ const LLSD& replyPump1NamePath=LLSD())
+ {
+ return errorLog(postAndWait(self, event, requestPump,
+ replyPump0NamePath, replyPump1NamePath),
+ std::string("Error event on ") + getName1());
+ }
+
+private:
+ LLEventStream mPump0, mPump1;
+};
+
+#endif /* ! defined(LL_LLEVENTCORO_H) */
diff --git a/indra/llcommon/lleventdispatcher.cpp b/indra/llcommon/lleventdispatcher.cpp
new file mode 100644
index 0000000000..5fa6059718
--- /dev/null
+++ b/indra/llcommon/lleventdispatcher.cpp
@@ -0,0 +1,149 @@
+/**
+ * @file lleventdispatcher.cpp
+ * @author Nat Goodspeed
+ * @date 2009-06-18
+ * @brief Implementation for lleventdispatcher.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if LL_WINDOWS
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
+#endif
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "lleventdispatcher.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llevents.h"
+#include "llerror.h"
+#include "llsdutil.h"
+
+LLEventDispatcher::LLEventDispatcher(const std::string& desc, const std::string& key):
+ mDesc(desc),
+ mKey(key)
+{
+}
+
+LLEventDispatcher::~LLEventDispatcher()
+{
+}
+
+/// Register a callable by name
+void LLEventDispatcher::add(const std::string& name, const std::string& desc,
+ const Callable& callable, const LLSD& required)
+{
+ mDispatch.insert(DispatchMap::value_type(name,
+ DispatchMap::mapped_type(callable, desc, required)));
+}
+
+void LLEventDispatcher::addFail(const std::string& name, const std::string& classname) const
+{
+ LL_ERRS("LLEventDispatcher") << "LLEventDispatcher(" << mDesc << ")::add(" << name
+ << "): " << classname << " is not a subclass "
+ << "of LLEventDispatcher" << LL_ENDL;
+}
+
+/// Unregister a callable
+bool LLEventDispatcher::remove(const std::string& name)
+{
+ DispatchMap::iterator found = mDispatch.find(name);
+ if (found == mDispatch.end())
+ {
+ return false;
+ }
+ mDispatch.erase(found);
+ return true;
+}
+
+/// Call a registered callable with an explicitly-specified name. If no
+/// such callable exists, die with LL_ERRS.
+void LLEventDispatcher::operator()(const std::string& name, const LLSD& event) const
+{
+ if (! attemptCall(name, event))
+ {
+ LL_ERRS("LLEventDispatcher") << "LLEventDispatcher(" << mDesc << "): '" << name
+ << "' not found" << LL_ENDL;
+ }
+}
+
+/// Extract the @a key value from the incoming @a event, and call the
+/// callable whose name is specified by that map @a key. If no such
+/// callable exists, die with LL_ERRS.
+void LLEventDispatcher::operator()(const LLSD& event) const
+{
+ // This could/should be implemented in terms of the two-arg overload.
+ // However -- we can produce a more informative error message.
+ std::string name(event[mKey]);
+ if (! attemptCall(name, event))
+ {
+ LL_ERRS("LLEventDispatcher") << "LLEventDispatcher(" << mDesc << "): bad " << mKey
+ << " value '" << name << "'" << LL_ENDL;
+ }
+}
+
+bool LLEventDispatcher::attemptCall(const std::string& name, const LLSD& event) const
+{
+ DispatchMap::const_iterator found = mDispatch.find(name);
+ if (found == mDispatch.end())
+ {
+ // The reason we only return false, leaving it up to our caller to die
+ // with LL_ERRS, is that different callers have different amounts of
+ // available information.
+ return false;
+ }
+ // Found the name, so it's plausible to even attempt the call. But first,
+ // validate the syntax of the event itself.
+ std::string mismatch(llsd_matches(found->second.mRequired, event));
+ if (! mismatch.empty())
+ {
+ LL_ERRS("LLEventDispatcher") << "LLEventDispatcher(" << mDesc << ") calling '" << name
+ << "': bad request: " << mismatch << LL_ENDL;
+ }
+ // Event syntax looks good, go for it!
+ (found->second.mFunc)(event);
+ return true; // tell caller we were able to call
+}
+
+LLEventDispatcher::Callable LLEventDispatcher::get(const std::string& name) const
+{
+ DispatchMap::const_iterator found = mDispatch.find(name);
+ if (found == mDispatch.end())
+ {
+ return Callable();
+ }
+ return found->second.mFunc;
+}
+
+LLSD LLEventDispatcher::getMetadata(const std::string& name) const
+{
+ DispatchMap::const_iterator found = mDispatch.find(name);
+ if (found == mDispatch.end())
+ {
+ return LLSD();
+ }
+ LLSD meta;
+ meta["name"] = name;
+ meta["desc"] = found->second.mDesc;
+ meta["required"] = found->second.mRequired;
+ return meta;
+}
+
+LLDispatchListener::LLDispatchListener(const std::string& pumpname, const std::string& key):
+ LLEventDispatcher(pumpname, key),
+ mPump(pumpname, true), // allow tweaking for uniqueness
+ mBoundListener(mPump.listen("self", boost::bind(&LLDispatchListener::process, this, _1)))
+{
+}
+
+bool LLDispatchListener::process(const LLSD& event)
+{
+ (*this)(event);
+ return false;
+}
diff --git a/indra/llcommon/lleventdispatcher.h b/indra/llcommon/lleventdispatcher.h
new file mode 100644
index 0000000000..1e625bcee8
--- /dev/null
+++ b/indra/llcommon/lleventdispatcher.h
@@ -0,0 +1,193 @@
+/**
+ * @file lleventdispatcher.h
+ * @author Nat Goodspeed
+ * @date 2009-06-18
+ * @brief Central mechanism for dispatching events by string name. This is
+ * useful when you have a single LLEventPump listener on which you can
+ * request different operations, vs. instantiating a different
+ * LLEventPump for each such operation.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLEVENTDISPATCHER_H)
+#define LL_LLEVENTDISPATCHER_H
+
+#include <string>
+#include <map>
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
+#include <boost/iterator/transform_iterator.hpp>
+#include <typeinfo>
+#include "llevents.h"
+
+class LLSD;
+
+/**
+ * Given an LLSD map, examine a string-valued key and call a corresponding
+ * callable. This class is designed to be contained by an LLEventPump
+ * listener class that will register some of its own methods, though any
+ * callable can be used.
+ */
+class LL_COMMON_API LLEventDispatcher
+{
+public:
+ LLEventDispatcher(const std::string& desc, const std::string& key);
+ virtual ~LLEventDispatcher();
+
+ /// Accept any C++ callable, typically a boost::bind() expression
+ typedef boost::function<void(const LLSD&)> Callable;
+
+ /**
+ * Register a @a callable by @a name. The optional @a required parameter
+ * is used to validate the structure of each incoming event (see
+ * llsd_matches()).
+ */
+ void add(const std::string& name,
+ const std::string& desc,
+ const Callable& callable,
+ const LLSD& required=LLSD());
+
+ /**
+ * Special case: a subclass of this class can pass an unbound member
+ * function pointer without explicitly specifying the
+ * <tt>boost::bind()</tt> expression.
+ */
+ template <class CLASS>
+ void add(const std::string& name,
+ const std::string& desc,
+ void (CLASS::*method)(const LLSD&),
+ const LLSD& required=LLSD())
+ {
+ addMethod<CLASS>(name, desc, method, required);
+ }
+
+ /// Overload for both const and non-const methods
+ template <class CLASS>
+ void add(const std::string& name,
+ const std::string& desc,
+ void (CLASS::*method)(const LLSD&) const,
+ const LLSD& required=LLSD())
+ {
+ addMethod<CLASS>(name, desc, method, required);
+ }
+
+ /// Convenience: for LLEventDispatcher, not every callable needs a
+ /// documentation string.
+ template <typename CALLABLE>
+ void add(const std::string& name,
+ CALLABLE callable,
+ const LLSD& required=LLSD())
+ {
+ add(name, "", callable, required);
+ }
+
+ /// Unregister a callable
+ bool remove(const std::string& name);
+
+ /// Call a registered callable with an explicitly-specified name. If no
+ /// such callable exists, die with LL_ERRS. If the @a event fails to match
+ /// the @a required prototype specified at add() time, die with LL_ERRS.
+ void operator()(const std::string& name, const LLSD& event) const;
+
+ /// Extract the @a key value from the incoming @a event, and call the
+ /// callable whose name is specified by that map @a key. If no such
+ /// callable exists, die with LL_ERRS. If the @a event fails to match the
+ /// @a required prototype specified at add() time, die with LL_ERRS.
+ void operator()(const LLSD& event) const;
+
+ /// @name Iterate over defined names
+ //@{
+ typedef std::pair<std::string, std::string> NameDesc;
+
+private:
+ struct DispatchEntry
+ {
+ DispatchEntry(const Callable& func, const std::string& desc, const LLSD& required):
+ mFunc(func),
+ mDesc(desc),
+ mRequired(required)
+ {}
+ Callable mFunc;
+ std::string mDesc;
+ LLSD mRequired;
+ };
+ typedef std::map<std::string, DispatchEntry> DispatchMap;
+
+public:
+ /// We want the flexibility to redefine what data we store per name,
+ /// therefore our public interface doesn't expose DispatchMap iterators,
+ /// or DispatchMap itself, or DispatchEntry. Instead we explicitly
+ /// transform each DispatchMap item to NameDesc on dereferencing.
+ typedef boost::transform_iterator<NameDesc(*)(const DispatchMap::value_type&), DispatchMap::const_iterator> const_iterator;
+ const_iterator begin() const
+ {
+ return boost::make_transform_iterator(mDispatch.begin(), makeNameDesc);
+ }
+ const_iterator end() const
+ {
+ return boost::make_transform_iterator(mDispatch.end(), makeNameDesc);
+ }
+ //@}
+
+ /// Fetch the Callable for the specified name. If no such name was
+ /// registered, return an empty() Callable.
+ Callable get(const std::string& name) const;
+
+ /// Get information about a specific Callable
+ LLSD getMetadata(const std::string& name) const;
+
+ /// Retrieve the LLSD key we use for one-arg <tt>operator()</tt> method
+ std::string getDispatchKey() const { return mKey; }
+
+private:
+ template <class CLASS, typename METHOD>
+ void addMethod(const std::string& name, const std::string& desc,
+ const METHOD& method, const LLSD& required)
+ {
+ CLASS* downcast = dynamic_cast<CLASS*>(this);
+ if (! downcast)
+ {
+ addFail(name, typeid(CLASS).name());
+ }
+ else
+ {
+ add(name, desc, boost::bind(method, downcast, _1), required);
+ }
+ }
+ void addFail(const std::string& name, const std::string& classname) const;
+ /// try to dispatch, return @c true if success
+ bool attemptCall(const std::string& name, const LLSD& event) const;
+
+ std::string mDesc, mKey;
+ DispatchMap mDispatch;
+
+ static NameDesc makeNameDesc(const DispatchMap::value_type& item)
+ {
+ return NameDesc(item.first, item.second.mDesc);
+ }
+};
+
+/**
+ * Bundle an LLEventPump and a listener with an LLEventDispatcher. A class
+ * that contains (or derives from) LLDispatchListener need only specify the
+ * LLEventPump name and dispatch key, and add() its methods. Incoming events
+ * will automatically be dispatched.
+ */
+class LL_COMMON_API LLDispatchListener: public LLEventDispatcher
+{
+public:
+ LLDispatchListener(const std::string& pumpname, const std::string& key);
+
+ std::string getPumpName() const { return mPump.getName(); }
+
+private:
+ bool process(const LLSD& event);
+
+ LLEventStream mPump;
+ LLTempBoundListener mBoundListener;
+};
+
+#endif /* ! defined(LL_LLEVENTDISPATCHER_H) */
diff --git a/indra/llcommon/lleventfilter.cpp b/indra/llcommon/lleventfilter.cpp
new file mode 100644
index 0000000000..74133781be
--- /dev/null
+++ b/indra/llcommon/lleventfilter.cpp
@@ -0,0 +1,149 @@
+/**
+ * @file lleventfilter.cpp
+ * @author Nat Goodspeed
+ * @date 2009-03-05
+ * @brief Implementation for lleventfilter.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "lleventfilter.h"
+// STL headers
+// std headers
+// external library headers
+#include <boost/bind.hpp>
+// other Linden headers
+#include "llerror.h" // LL_ERRS
+#include "llsdutil.h" // llsd_matches()
+
+LLEventFilter::LLEventFilter(LLEventPump& source, const std::string& name, bool tweak):
+ LLEventStream(name, tweak)
+{
+ source.listen(getName(), boost::bind(&LLEventFilter::post, this, _1));
+}
+
+LLEventMatching::LLEventMatching(const LLSD& pattern):
+ LLEventFilter("matching"),
+ mPattern(pattern)
+{
+}
+
+LLEventMatching::LLEventMatching(LLEventPump& source, const LLSD& pattern):
+ LLEventFilter(source, "matching"),
+ mPattern(pattern)
+{
+}
+
+bool LLEventMatching::post(const LLSD& event)
+{
+ if (! llsd_matches(mPattern, event).empty())
+ return false;
+
+ return LLEventStream::post(event);
+}
+
+LLEventTimeoutBase::LLEventTimeoutBase():
+ LLEventFilter("timeout")
+{
+}
+
+LLEventTimeoutBase::LLEventTimeoutBase(LLEventPump& source):
+ LLEventFilter(source, "timeout")
+{
+}
+
+void LLEventTimeoutBase::actionAfter(F32 seconds, const Action& action)
+{
+ setCountdown(seconds);
+ mAction = action;
+ if (! mMainloop.connected())
+ {
+ LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
+ mMainloop = mainloop.listen(getName(), boost::bind(&LLEventTimeoutBase::tick, this, _1));
+ }
+}
+
+class ErrorAfter
+{
+public:
+ ErrorAfter(const std::string& message): mMessage(message) {}
+
+ void operator()()
+ {
+ LL_ERRS("LLEventTimeout") << mMessage << LL_ENDL;
+ }
+
+private:
+ std::string mMessage;
+};
+
+void LLEventTimeoutBase::errorAfter(F32 seconds, const std::string& message)
+{
+ actionAfter(seconds, ErrorAfter(message));
+}
+
+class EventAfter
+{
+public:
+ EventAfter(LLEventPump& pump, const LLSD& event):
+ mPump(pump),
+ mEvent(event)
+ {}
+
+ void operator()()
+ {
+ mPump.post(mEvent);
+ }
+
+private:
+ LLEventPump& mPump;
+ LLSD mEvent;
+};
+
+void LLEventTimeoutBase::eventAfter(F32 seconds, const LLSD& event)
+{
+ actionAfter(seconds, EventAfter(*this, event));
+}
+
+bool LLEventTimeoutBase::post(const LLSD& event)
+{
+ cancel();
+ return LLEventStream::post(event);
+}
+
+void LLEventTimeoutBase::cancel()
+{
+ mMainloop.disconnect();
+}
+
+bool LLEventTimeoutBase::tick(const LLSD&)
+{
+ if (countdownElapsed())
+ {
+ cancel();
+ mAction();
+ }
+ return false; // show event to other listeners
+}
+
+LLEventTimeout::LLEventTimeout() {}
+
+LLEventTimeout::LLEventTimeout(LLEventPump& source):
+ LLEventTimeoutBase(source)
+{
+}
+
+void LLEventTimeout::setCountdown(F32 seconds)
+{
+ mTimer.setTimerExpirySec(seconds);
+}
+
+bool LLEventTimeout::countdownElapsed() const
+{
+ return mTimer.hasExpired();
+}
diff --git a/indra/llcommon/lleventfilter.h b/indra/llcommon/lleventfilter.h
new file mode 100644
index 0000000000..89f0c7ea43
--- /dev/null
+++ b/indra/llcommon/lleventfilter.h
@@ -0,0 +1,186 @@
+/**
+ * @file lleventfilter.h
+ * @author Nat Goodspeed
+ * @date 2009-03-05
+ * @brief Define LLEventFilter: LLEventStream subclass with conditions
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLEVENTFILTER_H)
+#define LL_LLEVENTFILTER_H
+
+#include "llevents.h"
+#include "stdtypes.h"
+#include "lltimer.h"
+#include <boost/function.hpp>
+
+/**
+ * Generic base class
+ */
+class LL_COMMON_API LLEventFilter: public LLEventStream
+{
+public:
+ /// construct a standalone LLEventFilter
+ LLEventFilter(const std::string& name="filter", bool tweak=true):
+ LLEventStream(name, tweak)
+ {}
+ /// construct LLEventFilter and connect it to the specified LLEventPump
+ LLEventFilter(LLEventPump& source, const std::string& name="filter", bool tweak=true);
+
+ /// Post an event to all listeners
+ virtual bool post(const LLSD& event) = 0;
+};
+
+/**
+ * Pass through only events matching a specified pattern
+ */
+class LLEventMatching: public LLEventFilter
+{
+public:
+ /// Pass an LLSD map with keys and values the incoming event must match
+ LLEventMatching(const LLSD& pattern);
+ /// instantiate and connect
+ LLEventMatching(LLEventPump& source, const LLSD& pattern);
+
+ /// Only pass through events matching the pattern
+ virtual bool post(const LLSD& event);
+
+private:
+ LLSD mPattern;
+};
+
+/**
+ * Wait for an event to be posted. If no such event arrives within a specified
+ * time, take a specified action. See LLEventTimeout for production
+ * implementation.
+ *
+ * @NOTE This is an abstract base class so that, for testing, we can use an
+ * alternate "timer" that doesn't actually consume real time.
+ */
+class LL_COMMON_API LLEventTimeoutBase: public LLEventFilter
+{
+public:
+ /// construct standalone
+ LLEventTimeoutBase();
+ /// construct and connect
+ LLEventTimeoutBase(LLEventPump& source);
+
+ /// Callable, can be constructed with boost::bind()
+ typedef boost::function<void()> Action;
+
+ /**
+ * Start countdown timer for the specified number of @a seconds. Forward
+ * all events. If any event arrives before timer expires, cancel timer. If
+ * no event arrives before timer expires, take specified @a action.
+ *
+ * This is a one-shot timer. Once it has either expired or been canceled,
+ * it is inert until another call to actionAfter().
+ *
+ * Calling actionAfter() while an existing timer is running cheaply
+ * replaces that original timer. Thus, a valid use case is to detect
+ * idleness of some event source by calling actionAfter() on each new
+ * event. A rapid sequence of events will keep the timer from expiring;
+ * the first gap in events longer than the specified timer will fire the
+ * specified Action.
+ *
+ * Any post() call cancels the timer. To be satisfied with only a
+ * particular event, chain on an LLEventMatching that only passes such
+ * events:
+ *
+ * @code
+ * event ultimate
+ * source ---> LLEventMatching ---> LLEventTimeout ---> listener
+ * @endcode
+ *
+ * @NOTE
+ * The implementation relies on frequent events on the LLEventPump named
+ * "mainloop".
+ */
+ void actionAfter(F32 seconds, const Action& action);
+
+ /**
+ * Like actionAfter(), but where the desired Action is LL_ERRS
+ * termination. Pass the timeout time and the desired LL_ERRS @a message.
+ *
+ * This method is useful when, for instance, some async API guarantees an
+ * event, whether success or failure, within a stated time window.
+ * Instantiate an LLEventTimeout listening to that API and call
+ * errorAfter() on each async request with a timeout comfortably longer
+ * than the API's time guarantee (much longer than the anticipated
+ * "mainloop" granularity).
+ *
+ * Then if the async API breaks its promise, the program terminates with
+ * the specified LL_ERRS @a message. The client of the async API can
+ * therefore assume the guarantee is upheld.
+ *
+ * @NOTE
+ * errorAfter() is implemented in terms of actionAfter(), so all remarks
+ * about calling actionAfter() also apply to errorAfter().
+ */
+ void errorAfter(F32 seconds, const std::string& message);
+
+ /**
+ * Like actionAfter(), but where the desired Action is a particular event
+ * for all listeners. Pass the timeout time and the desired @a event data.
+ *
+ * Suppose the timeout should only be satisfied by a particular event, but
+ * the ultimate listener must see all other incoming events as well, plus
+ * the timeout @a event if any:
+ *
+ * @code
+ * some LLEventMatching LLEventMatching
+ * event ---> for particular ---> LLEventTimeout ---> for timeout
+ * source event event \
+ * \ \ ultimate
+ * `-----------------------------------------------------> listener
+ * @endcode
+ *
+ * Since a given listener can listen on more than one LLEventPump, we can
+ * set things up so it sees the set union of events from LLEventTimeout
+ * and the original event source. However, as LLEventTimeout passes
+ * through all incoming events, the "particular event" that satisfies the
+ * left LLEventMatching would reach the ultimate listener twice. So we add
+ * an LLEventMatching that only passes timeout events.
+ *
+ * @NOTE
+ * eventAfter() is implemented in terms of actionAfter(), so all remarks
+ * about calling actionAfter() also apply to eventAfter().
+ */
+ void eventAfter(F32 seconds, const LLSD& event);
+
+ /// Pass event through, canceling the countdown timer
+ virtual bool post(const LLSD& event);
+
+ /// Cancel timer without event
+ void cancel();
+
+protected:
+ virtual void setCountdown(F32 seconds) = 0;
+ virtual bool countdownElapsed() const = 0;
+
+private:
+ bool tick(const LLSD&);
+
+ LLBoundListener mMainloop;
+ Action mAction;
+};
+
+/// Production implementation of LLEventTimoutBase
+class LL_COMMON_API LLEventTimeout: public LLEventTimeoutBase
+{
+public:
+ LLEventTimeout();
+ LLEventTimeout(LLEventPump& source);
+
+protected:
+ virtual void setCountdown(F32 seconds);
+ virtual bool countdownElapsed() const;
+
+private:
+ LLTimer mTimer;
+};
+
+#endif /* ! defined(LL_LLEVENTFILTER_H) */
diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp
new file mode 100644
index 0000000000..31fdd9e60a
--- /dev/null
+++ b/indra/llcommon/llevents.cpp
@@ -0,0 +1,571 @@
+/**
+ * @file llevents.cpp
+ * @author Nat Goodspeed
+ * @date 2008-09-12
+ * @brief Implementation for llevents.
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * Copyright (c) 2008, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+
+#if LL_WINDOWS
+#pragma warning (disable : 4675) // "resolved by ADL" -- just as I want!
+#endif
+
+// associated header
+#include "llevents.h"
+// STL headers
+#include <set>
+#include <sstream>
+#include <algorithm>
+// std headers
+#include <typeinfo>
+#include <cassert>
+#include <cmath>
+#include <cctype>
+// external library headers
+#include <boost/range/iterator_range.hpp>
+#if LL_WINDOWS
+#pragma warning (push)
+#pragma warning (disable : 4701) // compiler thinks might use uninitialized var, but no
+#endif
+#include <boost/lexical_cast.hpp>
+#if LL_WINDOWS
+#pragma warning (pop)
+#endif
+// other Linden headers
+#include "stringize.h"
+#include "llerror.h"
+#include "llsdutil.h"
+#if LL_MSVC
+#pragma warning (disable : 4702)
+#endif
+
+/*****************************************************************************
+* queue_names: specify LLEventPump names that should be instantiated as
+* LLEventQueue
+*****************************************************************************/
+/**
+ * At present, we recognize particular requested LLEventPump names as needing
+ * LLEventQueues. Later on we'll migrate this information to an external
+ * configuration file.
+ */
+const char* queue_names[] =
+{
+ "placeholder - replace with first real name string"
+};
+
+/*****************************************************************************
+* If there's a "mainloop" pump, listen on that to flush all LLEventQueues
+*****************************************************************************/
+struct RegisterFlush : public LLEventTrackable
+{
+ RegisterFlush():
+ pumps(LLEventPumps::instance())
+ {
+ pumps.obtain("mainloop").listen("flushLLEventQueues", boost::bind(&RegisterFlush::flush, this, _1));
+ }
+ bool flush(const LLSD&)
+ {
+ pumps.flush();
+ return false;
+ }
+ ~RegisterFlush()
+ {
+ // LLEventTrackable handles stopListening for us.
+ }
+ LLEventPumps& pumps;
+};
+static RegisterFlush registerFlush;
+
+/*****************************************************************************
+* LLEventPumps
+*****************************************************************************/
+LLEventPumps::LLEventPumps():
+ // Until we migrate this information to an external config file,
+ // initialize mQueueNames from the static queue_names array.
+ mQueueNames(boost::begin(queue_names), boost::end(queue_names))
+{
+}
+
+LLEventPump& LLEventPumps::obtain(const std::string& name)
+{
+ PumpMap::iterator found = mPumpMap.find(name);
+ if (found != mPumpMap.end())
+ {
+ // Here we already have an LLEventPump instance with the requested
+ // name.
+ return *found->second;
+ }
+ // Here we must instantiate an LLEventPump subclass.
+ LLEventPump* newInstance;
+ // Should this name be an LLEventQueue?
+ PumpNames::const_iterator nfound = mQueueNames.find(name);
+ if (nfound != mQueueNames.end())
+ newInstance = new LLEventQueue(name);
+ else
+ newInstance = new LLEventStream(name);
+ // LLEventPump's constructor implicitly registers each new instance in
+ // mPumpMap. But remember that we instantiated it (in mOurPumps) so we'll
+ // delete it later.
+ mOurPumps.insert(newInstance);
+ return *newInstance;
+}
+
+void LLEventPumps::flush()
+{
+ // Flush every known LLEventPump instance. Leave it up to each instance to
+ // decide what to do with the flush() call.
+ for (PumpMap::iterator pmi = mPumpMap.begin(), pmend = mPumpMap.end(); pmi != pmend; ++pmi)
+ {
+ pmi->second->flush();
+ }
+}
+
+void LLEventPumps::reset()
+{
+ // Reset every known LLEventPump instance. Leave it up to each instance to
+ // decide what to do with the reset() call.
+ for (PumpMap::iterator pmi = mPumpMap.begin(), pmend = mPumpMap.end(); pmi != pmend; ++pmi)
+ {
+ pmi->second->reset();
+ }
+}
+
+std::string LLEventPumps::registerNew(const LLEventPump& pump, const std::string& name, bool tweak)
+{
+ std::pair<PumpMap::iterator, bool> inserted =
+ mPumpMap.insert(PumpMap::value_type(name, const_cast<LLEventPump*>(&pump)));
+ // If the insert worked, then the name is unique; return that.
+ if (inserted.second)
+ return name;
+ // Here the new entry was NOT inserted, and therefore name isn't unique.
+ // Unless we're permitted to tweak it, that's Bad.
+ if (! tweak)
+ {
+ throw LLEventPump::DupPumpName(std::string("Duplicate LLEventPump name '") + name + "'");
+ }
+ // The passed name isn't unique, but we're permitted to tweak it. Find the
+ // first decimal-integer suffix not already taken. The insert() attempt
+ // above will have set inserted.first to the iterator of the existing
+ // entry by that name. Starting there, walk forward until we reach an
+ // entry that doesn't start with 'name'. For each entry consisting of name
+ // + integer suffix, capture the integer suffix in a set. Use a set
+ // because we're going to encounter string suffixes in the order: name1,
+ // name10, name11, name2, ... Walking those possibilities in that order
+ // isn't convenient to detect the first available "hole."
+ std::set<int> suffixes;
+ PumpMap::iterator pmi(inserted.first), pmend(mPumpMap.end());
+ // We already know inserted.first references the existing entry with
+ // 'name' as the key; skip that one and start with the next.
+ while (++pmi != pmend)
+ {
+ if (pmi->first.substr(0, name.length()) != name)
+ {
+ // Found the first entry beyond the entries starting with 'name':
+ // stop looping.
+ break;
+ }
+ // Here we're looking at an entry that starts with 'name'. Is the rest
+ // of it an integer?
+ // Dubious (?) assumption: in the local character set, decimal digits
+ // are in increasing order such that '9' is the last of them. This
+ // test deals with 'name' values such as 'a', where there might be a
+ // very large number of entries starting with 'a' whose suffixes
+ // aren't integers. A secondary assumption is that digit characters
+ // precede most common name characters (true in ASCII, false in
+ // EBCDIC). The test below is correct either way, but it's worth more
+ // if the assumption holds.
+ if (pmi->first[name.length()] > '9')
+ break;
+ // It should be cheaper to detect that we're not looking at a digit
+ // character -- and therefore the suffix can't possibly be an integer
+ // -- than to attempt the lexical_cast and catch the exception.
+ if (! std::isdigit(pmi->first[name.length()]))
+ continue;
+ // Okay, the first character of the suffix is a digit, it's worth at
+ // least attempting to convert to int.
+ try
+ {
+ suffixes.insert(boost::lexical_cast<int>(pmi->first.substr(name.length())));
+ }
+ catch (const boost::bad_lexical_cast&)
+ {
+ // If the rest of pmi->first isn't an int, just ignore it.
+ }
+ }
+ // Here we've accumulated in 'suffixes' all existing int suffixes of the
+ // entries starting with 'name'. Find the first unused one.
+ int suffix = 1;
+ for ( ; suffixes.find(suffix) != suffixes.end(); ++suffix)
+ ;
+ // Here 'suffix' is not in 'suffixes'. Construct a new name based on that
+ // suffix, insert it and return it.
+ std::ostringstream out;
+ out << name << suffix;
+ return registerNew(pump, out.str(), tweak);
+}
+
+void LLEventPumps::unregister(const LLEventPump& pump)
+{
+ // Remove this instance from mPumpMap
+ PumpMap::iterator found = mPumpMap.find(pump.getName());
+ if (found != mPumpMap.end())
+ {
+ mPumpMap.erase(found);
+ }
+ // If this instance is one we created, also remove it from mOurPumps so we
+ // won't try again to delete it later!
+ PumpSet::iterator psfound = mOurPumps.find(const_cast<LLEventPump*>(&pump));
+ if (psfound != mOurPumps.end())
+ {
+ mOurPumps.erase(psfound);
+ }
+}
+
+LLEventPumps::~LLEventPumps()
+{
+ // On destruction, delete every LLEventPump we instantiated (via
+ // obtain()). CAREFUL: deleting an LLEventPump calls its destructor, which
+ // calls unregister(), which removes that LLEventPump instance from
+ // mOurPumps. So an iterator loop over mOurPumps to delete contained
+ // LLEventPump instances is dangerous! Instead, delete them one at a time
+ // until mOurPumps is empty.
+ while (! mOurPumps.empty())
+ {
+ delete *mOurPumps.begin();
+ }
+}
+
+/*****************************************************************************
+* LLEventPump
+*****************************************************************************/
+#if LL_WINDOWS
+#pragma warning (push)
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
+#endif
+
+LLEventPump::LLEventPump(const std::string& name, bool tweak):
+ // Register every new instance with LLEventPumps
+ mName(LLEventPumps::instance().registerNew(*this, name, tweak)),
+ mSignal(new LLStandardSignal()),
+ mEnabled(true)
+{}
+
+#if LL_WINDOWS
+#pragma warning (pop)
+#endif
+
+LLEventPump::~LLEventPump()
+{
+ // Unregister this doomed instance from LLEventPumps
+ LLEventPumps::instance().unregister(*this);
+}
+
+// static data member
+const LLEventPump::NameList LLEventPump::empty;
+
+std::string LLEventPump::inventName(const std::string& pfx)
+{
+ static long suffix = 0;
+ return STRINGIZE(pfx << suffix++);
+}
+
+void LLEventPump::reset()
+{
+ mSignal.reset();
+ mConnections.clear();
+ //mDeps.clear();
+}
+
+LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventListener& listener,
+ const NameList& after,
+ const NameList& before)
+{
+ // Check for duplicate name before connecting listener to mSignal
+ ConnectionMap::const_iterator found = mConnections.find(name);
+ // In some cases the user might disconnect a connection explicitly -- or
+ // might use LLEventTrackable to disconnect implicitly. Either way, we can
+ // end up retaining in mConnections a zombie connection object that's
+ // already been disconnected. Such a connection object can't be
+ // reconnected -- nor, in the case of LLEventTrackable, would we want to
+ // try, since disconnection happens with the destruction of the listener
+ // object. That means it's safe to overwrite a disconnected connection
+ // object with the new one we're attempting. The case we want to prevent
+ // is only when the existing connection object is still connected.
+ if (found != mConnections.end() && found->second.connected())
+ {
+ throw DupListenerName(std::string("Attempt to register duplicate listener name '") + name +
+ "' on " + typeid(*this).name() + " '" + getName() + "'");
+ }
+ // Okay, name is unique, try to reconcile its dependencies. Specify a new
+ // "node" value that we never use for an mSignal placement; we'll fix it
+ // later.
+ DependencyMap::node_type& newNode = mDeps.add(name, -1.0, after, before);
+ // What if this listener has been added, removed and re-added? In that
+ // case newNode already has a non-negative value because we never remove a
+ // listener from mDeps. But keep processing uniformly anyway in case the
+ // listener was added back with different dependencies. Then mDeps.sort()
+ // would put it in a different position, and the old newNode placement
+ // value would be wrong, so we'd have to reassign it anyway. Trust that
+ // re-adding a listener with the same dependencies is the trivial case for
+ // mDeps.sort(): it can just replay its cache.
+ DependencyMap::sorted_range sorted_range;
+ try
+ {
+ // Can we pick an order that works including this new entry?
+ sorted_range = mDeps.sort();
+ }
+ catch (const DependencyMap::Cycle& e)
+ {
+ // No: the new node's after/before dependencies have made mDeps
+ // unsortable. If we leave the new node in mDeps, it will continue
+ // to screw up all future attempts to sort()! Pull it out.
+ mDeps.remove(name);
+ throw Cycle(std::string("New listener '") + name + "' on " + typeid(*this).name() +
+ " '" + getName() + "' would cause cycle: " + e.what());
+ }
+ // Walk the list to verify that we haven't changed the order.
+ float previous = 0.0, myprev = 0.0;
+ DependencyMap::sorted_iterator mydmi = sorted_range.end(); // need this visible after loop
+ for (DependencyMap::sorted_iterator dmi = sorted_range.begin();
+ dmi != sorted_range.end(); ++dmi)
+ {
+ // Since we've added the new entry with an invalid placement,
+ // recognize it and skip it.
+ if (dmi->first == name)
+ {
+ // Remember the iterator belonging to our new node, and which
+ // placement value was 'previous' at that point.
+ mydmi = dmi;
+ myprev = previous;
+ continue;
+ }
+ // If the new node has rearranged the existing nodes, we'll find
+ // that their placement values are no longer in increasing order.
+ if (dmi->second < previous)
+ {
+ // This is another scenario in which we'd better back out the
+ // newly-added node from mDeps -- but don't do it yet, we want to
+ // traverse the existing mDeps to report on it!
+ // Describe the change to the order of our listeners. Copy
+ // everything but the newest listener to a vector we can sort to
+ // obtain the old order.
+ typedef std::vector< std::pair<float, std::string> > SortNameList;
+ SortNameList sortnames;
+ for (DependencyMap::sorted_iterator cdmi(sorted_range.begin()), cdmend(sorted_range.end());
+ cdmi != cdmend; ++cdmi)
+ {
+ if (cdmi->first != name)
+ {
+ sortnames.push_back(SortNameList::value_type(cdmi->second, cdmi->first));
+ }
+ }
+ std::sort(sortnames.begin(), sortnames.end());
+ std::ostringstream out;
+ out << "New listener '" << name << "' on " << typeid(*this).name() << " '" << getName()
+ << "' would move previous listener '" << dmi->first << "'\nwas: ";
+ SortNameList::const_iterator sni(sortnames.begin()), snend(sortnames.end());
+ if (sni != snend)
+ {
+ out << sni->second;
+ while (++sni != snend)
+ {
+ out << ", " << sni->second;
+ }
+ }
+ out << "\nnow: ";
+ DependencyMap::sorted_iterator ddmi(sorted_range.begin()), ddmend(sorted_range.end());
+ if (ddmi != ddmend)
+ {
+ out << ddmi->first;
+ while (++ddmi != ddmend)
+ {
+ out << ", " << ddmi->first;
+ }
+ }
+ // NOW remove the offending listener node.
+ mDeps.remove(name);
+ // Having constructed a description of the order change, inform caller.
+ throw OrderChange(out.str());
+ }
+ // This node becomes the previous one.
+ previous = dmi->second;
+ }
+ // We just got done with a successful mDeps.add(name, ...) call. We'd
+ // better have found 'name' somewhere in that sorted list!
+ assert(mydmi != sorted_range.end());
+ // Four cases:
+ // 0. name is the only entry: placement 1.0
+ // 1. name is the first of several entries: placement (next placement)/2
+ // 2. name is between two other entries: placement (myprev + (next placement))/2
+ // 3. name is the last entry: placement ceil(myprev) + 1.0
+ // Since we've cleverly arranged for myprev to be 0.0 if name is the
+ // first entry, this folds down to two cases. Case 1 is subsumed by
+ // case 2, and case 0 is subsumed by case 3. So we need only handle
+ // cases 2 and 3, which means we need only detect whether name is the
+ // last entry. Increment mydmi to see if there's anything beyond.
+ if (++mydmi != sorted_range.end())
+ {
+ // The new node isn't last. Place it between the previous node and
+ // the successor.
+ newNode = (myprev + mydmi->second)/2.0;
+ }
+ else
+ {
+ // The new node is last. Bump myprev up to the next integer, add
+ // 1.0 and use that.
+ newNode = std::ceil(myprev) + 1.0;
+ }
+ // Now that newNode has a value that places it appropriately in mSignal,
+ // connect it.
+ LLBoundListener bound = mSignal->connect(newNode, listener);
+ mConnections[name] = bound;
+ return bound;
+}
+
+LLBoundListener LLEventPump::getListener(const std::string& name) const
+{
+ ConnectionMap::const_iterator found = mConnections.find(name);
+ if (found != mConnections.end())
+ {
+ return found->second;
+ }
+ // not found, return dummy LLBoundListener
+ return LLBoundListener();
+}
+
+void LLEventPump::stopListening(const std::string& name)
+{
+ ConnectionMap::iterator found = mConnections.find(name);
+ if (found != mConnections.end())
+ {
+ found->second.disconnect();
+ mConnections.erase(found);
+ }
+ // We intentionally do NOT remove this name from mDeps. It may happen that
+ // the same listener with the same name and dependencies will jump on and
+ // off this LLEventPump repeatedly. Keeping a cache of dependencies will
+ // avoid a new dependency sort in such cases.
+}
+
+/*****************************************************************************
+* LLEventStream
+*****************************************************************************/
+bool LLEventStream::post(const LLSD& event)
+{
+ if (! mEnabled)
+ {
+ return false;
+ }
+ // NOTE NOTE NOTE: Any new access to member data beyond this point should
+ // cause us to move our LLStandardSignal object to a pimpl class along
+ // with said member data. Then the local shared_ptr will preserve both.
+
+ // DEV-43463: capture a local copy of mSignal. We've turned up a
+ // cross-coroutine scenario (described in the Jira) in which this post()
+ // call could end up destroying 'this', the LLEventPump subclass instance
+ // containing mSignal, during the call through *mSignal. So -- capture a
+ // *stack* instance of the shared_ptr, ensuring that our heap
+ // LLStandardSignal object will live at least until post() returns, even
+ // if 'this' gets destroyed during the call.
+ boost::shared_ptr<LLStandardSignal> signal(mSignal);
+ // Let caller know if any one listener handled the event. This is mostly
+ // useful when using LLEventStream as a listener for an upstream
+ // LLEventPump.
+ return (*signal)(event);
+}
+
+/*****************************************************************************
+* LLEventQueue
+*****************************************************************************/
+bool LLEventQueue::post(const LLSD& event)
+{
+ if (mEnabled)
+ {
+ // Defer sending this event by queueing it until flush()
+ mEventQueue.push_back(event);
+ }
+ // Unconditionally return false. We won't know until flush() whether a
+ // listener claims to have handled the event -- meanwhile, don't block
+ // other listeners.
+ return false;
+}
+
+void LLEventQueue::flush()
+{
+ // Consider the case when a given listener on this LLEventQueue posts yet
+ // another event on the same queue. If we loop over mEventQueue directly,
+ // we'll end up processing all those events during the same flush() call
+ // -- rather like an EventStream. Instead, copy mEventQueue and clear it,
+ // so that any new events posted to this LLEventQueue during flush() will
+ // be processed in the *next* flush() call.
+ EventQueue queue(mEventQueue);
+ mEventQueue.clear();
+ // NOTE NOTE NOTE: Any new access to member data beyond this point should
+ // cause us to move our LLStandardSignal object to a pimpl class along
+ // with said member data. Then the local shared_ptr will preserve both.
+
+ // DEV-43463: capture a local copy of mSignal. See LLEventStream::post()
+ // for detailed comments.
+ boost::shared_ptr<LLStandardSignal> signal(mSignal);
+ for ( ; ! queue.empty(); queue.pop_front())
+ {
+ (*signal)(queue.front());
+ }
+}
+
+/*****************************************************************************
+* LLListenerOrPumpName
+*****************************************************************************/
+LLListenerOrPumpName::LLListenerOrPumpName(const std::string& pumpname):
+ // Look up the specified pumpname, and bind its post() method as our listener
+ mListener(boost::bind(&LLEventPump::post,
+ boost::ref(LLEventPumps::instance().obtain(pumpname)),
+ _1))
+{
+}
+
+LLListenerOrPumpName::LLListenerOrPumpName(const char* pumpname):
+ // Look up the specified pumpname, and bind its post() method as our listener
+ mListener(boost::bind(&LLEventPump::post,
+ boost::ref(LLEventPumps::instance().obtain(pumpname)),
+ _1))
+{
+}
+
+bool LLListenerOrPumpName::operator()(const LLSD& event) const
+{
+ if (! mListener)
+ {
+ throw Empty("attempting to call uninitialized");
+ }
+ return (*mListener)(event);
+}
+
+void LLReqID::stamp(LLSD& response) const
+{
+ if (! (response.isUndefined() || response.isMap()))
+ {
+ // If 'response' was previously completely empty, it's okay to
+ // turn it into a map. If it was already a map, then it should be
+ // okay to add a key. But if it was anything else (e.g. a scalar),
+ // assigning a ["reqid"] key will DISCARD the previous value,
+ // replacing it with a map. That would be Bad.
+ LL_INFOS("LLReqID") << "stamp(" << mReqid << ") leaving non-map response unmodified: "
+ << response << LL_ENDL;
+ return;
+ }
+ LLSD oldReqid(response["reqid"]);
+ if (! (oldReqid.isUndefined() || llsd_equals(oldReqid, mReqid)))
+ {
+ LL_INFOS("LLReqID") << "stamp(" << mReqid << ") preserving existing [\"reqid\"] value "
+ << oldReqid << " in response: " << response << LL_ENDL;
+ return;
+ }
+ response["reqid"] = mReqid;
+}
diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h
new file mode 100644
index 0000000000..a73ada2931
--- /dev/null
+++ b/indra/llcommon/llevents.h
@@ -0,0 +1,1018 @@
+/**
+ * @file llevents.h
+ * @author Kent Quirk, Nat Goodspeed
+ * @date 2008-09-11
+ * @brief This is an implementation of the event system described at
+ * https://wiki.lindenlab.com/wiki/Viewer:Messaging/Event_System,
+ * originally introduced in llnotifications.h. It has nothing
+ * whatsoever to do with the older system in llevent.h.
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * Copyright (c) 2008, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLEVENTS_H)
+#define LL_LLEVENTS_H
+
+#include <string>
+#include <map>
+#include <set>
+#include <vector>
+#include <deque>
+#include <stdexcept>
+#if LL_WINDOWS
+ #pragma warning (push)
+ #pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
+ #pragma warning (disable : 4264)
+#endif
+#include <boost/signals2.hpp>
+#if LL_WINDOWS
+ #pragma warning (pop)
+#endif
+
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/utility.hpp> // noncopyable
+#include <boost/optional/optional.hpp>
+#include <boost/visit_each.hpp>
+#include <boost/ref.hpp> // reference_wrapper
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/function.hpp>
+#include <boost/static_assert.hpp>
+#include "llsd.h"
+#include "llsingleton.h"
+#include "lldependencies.h"
+#include "ll_template_cast.h"
+
+/*==========================================================================*|
+// override this to allow binding free functions with more parameters
+#ifndef LLEVENTS_LISTENER_ARITY
+#define LLEVENTS_LISTENER_ARITY 10
+#endif
+|*==========================================================================*/
+
+// hack for testing
+#ifndef testable
+#define testable private
+#endif
+
+/*****************************************************************************
+* Signal and handler declarations
+* Using a single handler signature means that we can have a common handler
+* type, rather than needing a distinct one for each different handler.
+*****************************************************************************/
+
+/**
+ * A boost::signals Combiner that stops the first time a handler returns true
+ * We need this because we want to have our handlers return bool, so that
+ * we have the option to cause a handler to stop further processing. The
+ * default handler fails when the signal returns a value but has no slots.
+ */
+struct LLStopWhenHandled
+{
+ typedef bool result_type;
+
+ template<typename InputIterator>
+ result_type operator()(InputIterator first, InputIterator last) const
+ {
+ for (InputIterator si = first; si != last; ++si)
+ {
+ if (*si)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+};
+
+/**
+ * We want to have a standard signature for all signals; this way,
+ * we can easily document a protocol for communicating across
+ * dlls and into scripting languages someday.
+ *
+ * We want to return a bool to indicate whether the signal has been
+ * handled and should NOT be passed on to other listeners.
+ * Return true to stop further handling of the signal, and false
+ * to continue.
+ *
+ * We take an LLSD because this way the contents of the signal
+ * are independent of the API used to communicate it.
+ * It is const ref because then there's low cost to pass it;
+ * if you only need to inspect it, it's very cheap.
+ *
+ * @internal
+ * The @c float template parameter indicates that we will internally use @c
+ * float to indicate relative listener order on a given LLStandardSignal.
+ * Don't worry, the @c float values are strictly internal! They are not part
+ * of the interface, for the excellent reason that requiring the caller to
+ * specify a numeric key to establish order means that the caller must know
+ * the universe of possible values. We use LLDependencies for that instead.
+ */
+typedef boost::signals2::signal<bool(const LLSD&), LLStopWhenHandled, float> LLStandardSignal;
+/// Methods that forward listeners (e.g. constructed with
+/// <tt>boost::bind()</tt>) should accept (const LLEventListener&)
+typedef LLStandardSignal::slot_type LLEventListener;
+/// Result of registering a listener, supports <tt>connected()</tt>,
+/// <tt>disconnect()</tt> and <tt>blocked()</tt>
+typedef boost::signals2::connection LLBoundListener;
+/// Storing an LLBoundListener in LLTempBoundListener will disconnect the
+/// referenced listener when the LLTempBoundListener instance is destroyed.
+typedef boost::signals2::scoped_connection LLTempBoundListener;
+
+/**
+ * A common idiom for event-based code is to accept either a callable --
+ * directly called on completion -- or the string name of an LLEventPump on
+ * which to post the completion event. Specifying a parameter as <tt>const
+ * LLListenerOrPumpName&</tt> allows either.
+ *
+ * Calling a validly-constructed LLListenerOrPumpName, passing the LLSD
+ * 'event' object, either calls the callable or posts the event to the named
+ * LLEventPump.
+ *
+ * A default-constructed LLListenerOrPumpName is 'empty'. (This is useful as
+ * the default value of an optional method parameter.) Calling it throws
+ * LLListenerOrPumpName::Empty. Test for this condition beforehand using
+ * either <tt>if (param)</tt> or <tt>if (! param)</tt>.
+ */
+class LL_COMMON_API LLListenerOrPumpName
+{
+public:
+ /// passing string name of LLEventPump
+ LLListenerOrPumpName(const std::string& pumpname);
+ /// passing string literal (overload so compiler isn't forced to infer
+ /// double conversion)
+ LLListenerOrPumpName(const char* pumpname);
+ /// passing listener -- the "anything else" catch-all case. The type of an
+ /// object constructed by boost::bind() isn't intended to be written out.
+ /// Normally we'd just accept 'const LLEventListener&', but that would
+ /// require double implicit conversion: boost::bind() object to
+ /// LLEventListener, LLEventListener to LLListenerOrPumpName. So use a
+ /// template to forward anything.
+ template<typename T>
+ LLListenerOrPumpName(const T& listener): mListener(listener) {}
+
+ /// for omitted method parameter: uninitialized mListener
+ LLListenerOrPumpName() {}
+
+ /// test for validity
+ operator bool() const { return bool(mListener); }
+ bool operator! () const { return ! mListener; }
+
+ /// explicit accessor
+ const LLEventListener& getListener() const { return *mListener; }
+
+ /// implicit conversion to LLEventListener
+ operator LLEventListener() const { return *mListener; }
+
+ /// allow calling directly
+ bool operator()(const LLSD& event) const;
+
+ /// exception if you try to call when empty
+ struct Empty: public std::runtime_error
+ {
+ Empty(const std::string& what):
+ std::runtime_error(std::string("LLListenerOrPumpName::Empty: ") + what) {}
+ };
+
+private:
+ boost::optional<LLEventListener> mListener;
+};
+
+/*****************************************************************************
+* LLEventPumps
+*****************************************************************************/
+class LLEventPump;
+
+/**
+ * LLEventPumps is a Singleton manager through which one typically accesses
+ * this subsystem.
+ */
+class LL_COMMON_API LLEventPumps: public LLSingleton<LLEventPumps>
+{
+ friend class LLSingleton<LLEventPumps>;
+public:
+ /**
+ * Find or create an LLEventPump instance with a specific name. We return
+ * a reference so there's no question about ownership. obtain() @em finds
+ * an instance without conferring @em ownership.
+ */
+ LLEventPump& obtain(const std::string& name);
+ /**
+ * Flush all known LLEventPump instances
+ */
+ void flush();
+
+ /**
+ * Reset all known LLEventPump instances
+ * workaround for DEV-35406 crash on shutdown
+ */
+ void reset();
+
+private:
+ friend class LLEventPump;
+ /**
+ * Register a new LLEventPump instance (internal)
+ */
+ std::string registerNew(const LLEventPump&, const std::string& name, bool tweak);
+ /**
+ * Unregister a doomed LLEventPump instance (internal)
+ */
+ void unregister(const LLEventPump&);
+
+private:
+ LLEventPumps();
+ ~LLEventPumps();
+
+testable:
+ // Map of all known LLEventPump instances, whether or not we instantiated
+ // them. We store a plain old LLEventPump* because this map doesn't claim
+ // ownership of the instances. Though the common usage pattern is to
+ // request an instance using obtain(), it's fair to instantiate an
+ // LLEventPump subclass statically, as a class member, on the stack or on
+ // the heap. In such cases, the instantiating party is responsible for its
+ // lifespan.
+ typedef std::map<std::string, LLEventPump*> PumpMap;
+ PumpMap mPumpMap;
+ // Set of all LLEventPumps we instantiated. Membership in this set means
+ // we claim ownership, and will delete them when this LLEventPumps is
+ // destroyed.
+ typedef std::set<LLEventPump*> PumpSet;
+ PumpSet mOurPumps;
+ // LLEventPump names that should be instantiated as LLEventQueue rather
+ // than as LLEventStream
+ typedef std::set<std::string> PumpNames;
+ PumpNames mQueueNames;
+};
+
+/*****************************************************************************
+* details
+*****************************************************************************/
+namespace LLEventDetail
+{
+ /// Any callable capable of connecting an LLEventListener to an
+ /// LLStandardSignal to produce an LLBoundListener can be mapped to this
+ /// signature.
+ typedef boost::function<LLBoundListener(const LLEventListener&)> ConnectFunc;
+
+ /// overload of visit_and_connect() when we have a string identifier available
+ template <typename LISTENER>
+ LLBoundListener visit_and_connect(const std::string& name,
+ const LISTENER& listener,
+ const ConnectFunc& connect_func);
+ /**
+ * Utility template function to use Visitor appropriately
+ *
+ * @param listener Callable to connect, typically a boost::bind()
+ * expression. This will be visited by Visitor using boost::visit_each().
+ * @param connect_func Callable that will connect() @a listener to an
+ * LLStandardSignal, returning LLBoundListener.
+ */
+ template <typename LISTENER>
+ LLBoundListener visit_and_connect(const LISTENER& listener,
+ const ConnectFunc& connect_func)
+ {
+ return visit_and_connect("", listener, connect_func);
+ }
+} // namespace LLEventDetail
+
+/*****************************************************************************
+* LLEventTrackable
+*****************************************************************************/
+/**
+ * LLEventTrackable wraps boost::signals2::trackable, which resembles
+ * boost::trackable. Derive your listener class from LLEventTrackable instead,
+ * and use something like
+ * <tt>LLEventPump::listen(boost::bind(&YourTrackableSubclass::method,
+ * instance, _1))</tt>. This will implicitly disconnect when the object
+ * referenced by @c instance is destroyed.
+ *
+ * @note
+ * LLEventTrackable doesn't address a couple of cases:
+ * * Object destroyed during call
+ * - You enter a slot call in thread A.
+ * - Thread B destroys the object, which of course disconnects it from any
+ * future slot calls.
+ * - Thread A's call uses 'this', which now refers to a defunct object.
+ * Undefined behavior results.
+ * * Call during destruction
+ * - @c MySubclass is derived from LLEventTrackable.
+ * - @c MySubclass registers one of its own methods using
+ * <tt>LLEventPump::listen()</tt>.
+ * - The @c MySubclass object begins destruction. <tt>~MySubclass()</tt>
+ * runs, destroying state specific to the subclass. (For instance, a
+ * <tt>Foo*</tt> data member is <tt>delete</tt>d but not zeroed.)
+ * - The listening method will not be disconnected until
+ * <tt>~LLEventTrackable()</tt> runs.
+ * - Before we get there, another thread posts data to the @c LLEventPump
+ * instance, calling the @c MySubclass method.
+ * - The method in question relies on valid @c MySubclass state. (For
+ * instance, it attempts to dereference the <tt>Foo*</tt> pointer that was
+ * <tt>delete</tt>d but not zeroed.)
+ * - Undefined behavior results.
+ * If you suspect you may encounter any such scenario, you're better off
+ * managing the lifespan of your object with <tt>boost::shared_ptr</tt>.
+ * Passing <tt>LLEventPump::listen()</tt> a <tt>boost::bind()</tt> expression
+ * involving a <tt>boost::weak_ptr<Foo></tt> is recognized specially, engaging
+ * thread-safe Boost.Signals2 machinery.
+ */
+typedef boost::signals2::trackable LLEventTrackable;
+
+/*****************************************************************************
+* LLEventPump
+*****************************************************************************/
+/**
+ * LLEventPump is the base class interface through which we access the
+ * concrete subclasses LLEventStream and LLEventQueue.
+ *
+ * @NOTE
+ * LLEventPump derives from LLEventTrackable so that when you "chain"
+ * LLEventPump instances together, they will automatically disconnect on
+ * destruction. Please see LLEventTrackable documentation for situations in
+ * which this may be perilous across threads.
+ */
+class LL_COMMON_API LLEventPump: public LLEventTrackable
+{
+public:
+ /**
+ * Exception thrown by LLEventPump(). You are trying to instantiate an
+ * LLEventPump (subclass) using the same name as some other instance, and
+ * you didn't pass <tt>tweak=true</tt> to permit it to generate a unique
+ * variant.
+ */
+ struct DupPumpName: public std::runtime_error
+ {
+ DupPumpName(const std::string& what):
+ std::runtime_error(std::string("DupPumpName: ") + what) {}
+ };
+
+ /**
+ * Instantiate an LLEventPump (subclass) with the string name by which it
+ * can be found using LLEventPumps::obtain().
+ *
+ * If you pass (or default) @a tweak to @c false, then a duplicate name
+ * will throw DupPumpName. This won't happen if LLEventPumps::obtain()
+ * instantiates the LLEventPump, because obtain() uses find-or-create
+ * logic. It can only happen if you instantiate an LLEventPump in your own
+ * code -- and a collision with the name of some other LLEventPump is
+ * likely to cause much more subtle problems!
+ *
+ * When you hand-instantiate an LLEventPump, consider passing @a tweak as
+ * @c true. This directs LLEventPump() to append a suffix to the passed @a
+ * name to make it unique. You can retrieve the adjusted name by calling
+ * getName() on your new instance.
+ */
+ LLEventPump(const std::string& name, bool tweak=false);
+ virtual ~LLEventPump();
+
+ /// group exceptions thrown by listen(). We use exceptions because these
+ /// particular errors are likely to be coding errors, found and fixed by
+ /// the developer even before preliminary checkin.
+ struct ListenError: public std::runtime_error
+ {
+ ListenError(const std::string& what): std::runtime_error(what) {}
+ };
+ /**
+ * exception thrown by listen(). You are attempting to register a
+ * listener on this LLEventPump using the same listener name as an
+ * already-registered listener.
+ */
+ struct DupListenerName: public ListenError
+ {
+ DupListenerName(const std::string& what):
+ ListenError(std::string("DupListenerName: ") + what)
+ {}
+ };
+ /**
+ * exception thrown by listen(). The order dependencies specified for your
+ * listener are incompatible with existing listeners.
+ *
+ * Consider listener "a" which specifies before "b" and "b" which
+ * specifies before "c". You are now attempting to register "c" before
+ * "a". There is no order that can satisfy all constraints.
+ */
+ struct Cycle: public ListenError
+ {
+ Cycle(const std::string& what): ListenError(std::string("Cycle: ") + what) {}
+ };
+ /**
+ * exception thrown by listen(). This one means that your new listener
+ * would force a change to the order of previously-registered listeners,
+ * and we don't have a good way to implement that.
+ *
+ * Consider listeners "some", "other" and "third". "some" and "other" are
+ * registered earlier without specifying relative order, so "other"
+ * happens to be first. Now you attempt to register "third" after "some"
+ * and before "other". Whoops, that would require swapping "some" and
+ * "other", which we can't do. Instead we throw this exception.
+ *
+ * It may not be possible to change the registration order so we already
+ * know "third"s order requirement by the time we register the second of
+ * "some" and "other". A solution would be to specify that "some" must
+ * come before "other", or equivalently that "other" must come after
+ * "some".
+ */
+ struct OrderChange: public ListenError
+ {
+ OrderChange(const std::string& what): ListenError(std::string("OrderChange: ") + what) {}
+ };
+
+ /// used by listen()
+ typedef std::vector<std::string> NameList;
+ /// convenience placeholder for when you explicitly want to pass an empty
+ /// NameList
+ const static NameList empty;
+
+ /// Get this LLEventPump's name
+ std::string getName() const { return mName; }
+
+ /**
+ * Register a new listener with a unique name. Specify an optional list
+ * of other listener names after which this one must be called, likewise
+ * an optional list of other listener names before which this one must be
+ * called. The other listeners mentioned need not yet be registered
+ * themselves. listen() can throw any ListenError; see ListenError
+ * subclasses.
+ *
+ * The listener name must be unique among active listeners for this
+ * LLEventPump, else you get DupListenerName. If you don't care to invent
+ * a name yourself, use inventName(). (I was tempted to recognize e.g. ""
+ * and internally generate a distinct name for that case. But that would
+ * handle badly the scenario in which you want to add, remove, re-add,
+ * etc. the same listener: each new listen() call would necessarily
+ * perform a new dependency sort. Assuming you specify the same
+ * after/before lists each time, using inventName() when you first
+ * instantiate your listener, then passing the same name on each listen()
+ * call, allows us to optimize away the second and subsequent dependency
+ * sorts.
+ *
+ * If (as is typical) you pass a <tt>boost::bind()</tt> expression as @a
+ * listener, listen() will inspect the components of that expression. If a
+ * bound object matches any of several cases, the connection will
+ * automatically be disconnected when that object is destroyed.
+ *
+ * * You bind a <tt>boost::weak_ptr</tt>.
+ * * Binding a <tt>boost::shared_ptr</tt> that way would ensure that the
+ * referenced object would @em never be destroyed, since the @c
+ * shared_ptr stored in the LLEventPump would remain an outstanding
+ * reference. Use the weaken() function to convert your @c shared_ptr to
+ * @c weak_ptr. Because this is easy to forget, binding a @c shared_ptr
+ * will produce a compile error (@c BOOST_STATIC_ASSERT failure).
+ * * You bind a simple pointer or reference to an object derived from
+ * <tt>boost::enable_shared_from_this</tt>. (UNDER CONSTRUCTION)
+ * * You bind a simple pointer or reference to an object derived from
+ * LLEventTrackable. Unlike the cases described above, though, this is
+ * vulnerable to a couple of cross-thread race conditions, as described
+ * in the LLEventTrackable documentation.
+ */
+ template <typename LISTENER>
+ LLBoundListener listen(const std::string& name, const LISTENER& listener,
+ const NameList& after=NameList(),
+ const NameList& before=NameList())
+ {
+ // Examine listener, using our listen_impl() method to make the
+ // actual connection.
+ // This is why listen() is a template. Conversion from boost::bind()
+ // to LLEventListener performs type erasure, so it's important to look
+ // at the boost::bind object itself before that happens.
+ return LLEventDetail::visit_and_connect(name,
+ listener,
+ boost::bind(&LLEventPump::listen_impl,
+ this,
+ name,
+ _1,
+ after,
+ before));
+ }
+
+ /// Get the LLBoundListener associated with the passed name (dummy
+ /// LLBoundListener if not found)
+ virtual LLBoundListener getListener(const std::string& name) const;
+ /**
+ * Instantiate one of these to block an existing connection:
+ * @code
+ * { // in some local scope
+ * LLEventPump::Blocker block(someLLBoundListener);
+ * // code that needs the connection blocked
+ * } // unblock the connection again
+ * @endcode
+ */
+ typedef boost::signals2::shared_connection_block Blocker;
+ /// Unregister a listener by name. Prefer this to
+ /// <tt>getListener(name).disconnect()</tt> because stopListening() also
+ /// forgets this name.
+ virtual void stopListening(const std::string& name);
+ /// Post an event to all listeners. The @c bool return is only meaningful
+ /// if the underlying leaf class is LLEventStream -- beware of relying on
+ /// it too much! Truthfully, we return @c bool mostly to permit chaining
+ /// one LLEventPump as a listener on another.
+ virtual bool post(const LLSD&) = 0;
+ /// Enable/disable: while disabled, silently ignore all post() calls
+ virtual void enable(bool enabled=true) { mEnabled = enabled; }
+ /// query
+ virtual bool enabled() const { return mEnabled; }
+
+ /// Generate a distinct name for a listener -- see listen()
+ static std::string inventName(const std::string& pfx="listener");
+
+private:
+ friend class LLEventPumps;
+ /// flush queued events
+ virtual void flush() {}
+
+ virtual void reset();
+
+private:
+ virtual LLBoundListener listen_impl(const std::string& name, const LLEventListener&,
+ const NameList& after,
+ const NameList& before);
+ std::string mName;
+
+protected:
+ /// implement the dispatching
+ boost::shared_ptr<LLStandardSignal> mSignal;
+
+ /// valve open?
+ bool mEnabled;
+ /// Map of named listeners. This tracks the listeners that actually exist
+ /// at this moment. When we stopListening(), we discard the entry from
+ /// this map.
+ typedef std::map<std::string, boost::signals2::connection> ConnectionMap;
+ ConnectionMap mConnections;
+ typedef LLDependencies<std::string, float> DependencyMap;
+ /// Dependencies between listeners. For each listener, track the float
+ /// used to establish its place in mSignal's order. This caches all the
+ /// listeners that have ever registered; stopListening() does not discard
+ /// the entry from this map. This is to avoid a new dependency sort if the
+ /// same listener with the same dependencies keeps hopping on and off this
+ /// LLEventPump.
+ DependencyMap mDeps;
+};
+
+/*****************************************************************************
+* LLEventStream
+*****************************************************************************/
+/**
+ * LLEventStream is a thin wrapper around LLStandardSignal. Posting an
+ * event immediately calls all registered listeners.
+ */
+class LL_COMMON_API LLEventStream: public LLEventPump
+{
+public:
+ LLEventStream(const std::string& name, bool tweak=false): LLEventPump(name, tweak) {}
+ virtual ~LLEventStream() {}
+
+ /// Post an event to all listeners
+ virtual bool post(const LLSD& event);
+};
+
+/*****************************************************************************
+* LLEventQueue
+*****************************************************************************/
+/**
+ * LLEventQueue isa LLEventPump whose post() method defers calling registered
+ * listeners until flush() is called.
+ */
+class LL_COMMON_API LLEventQueue: public LLEventPump
+{
+public:
+ LLEventQueue(const std::string& name, bool tweak=false): LLEventPump(name, tweak) {}
+ virtual ~LLEventQueue() {}
+
+ /// Post an event to all listeners
+ virtual bool post(const LLSD& event);
+
+private:
+ /// flush queued events
+ virtual void flush();
+
+private:
+ typedef std::deque<LLSD> EventQueue;
+ EventQueue mEventQueue;
+};
+
+/*****************************************************************************
+* LLReqID
+*****************************************************************************/
+/**
+ * This class helps the implementer of a given event API to honor the
+ * ["reqid"] convention. By this convention, each event API stamps into its
+ * response LLSD a ["reqid"] key whose value echoes the ["reqid"] value, if
+ * any, from the corresponding request.
+ *
+ * This supports an (atypical, but occasionally necessary) use case in which
+ * two or more asynchronous requests are multiplexed onto the same ["reply"]
+ * LLEventPump. Since the response events could arrive in arbitrary order, the
+ * caller must be able to demux them. It does so by matching the ["reqid"]
+ * value in each response with the ["reqid"] value in the corresponding
+ * request.
+ *
+ * It is the caller's responsibility to ensure distinct ["reqid"] values for
+ * that case. Though LLSD::UUID is guaranteed to work, it might be overkill:
+ * the "namespace" of unique ["reqid"] values is simply the set of requests
+ * specifying the same ["reply"] LLEventPump name.
+ *
+ * Making a given event API echo the request's ["reqid"] into the response is
+ * nearly trivial. This helper is mostly for mnemonic purposes, to serve as a
+ * place to put these comments. We hope that each time a coder implements a
+ * new event API based on some existing one, s/he will say, "Huh, what's an
+ * LLReqID?" and look up this material.
+ *
+ * The hardest part about the convention is deciding where to store the
+ * ["reqid"] value. Ironically, LLReqID can't help with that: you must store
+ * an LLReqID instance in whatever storage will persist until the reply is
+ * sent. For example, if the request ultimately ends up using a Responder
+ * subclass, storing an LLReqID instance in the Responder works.
+ *
+ * @note
+ * The @em implementer of an event API must honor the ["reqid"] convention.
+ * However, the @em caller of an event API need only use it if s/he is sharing
+ * the same ["reply"] LLEventPump for two or more asynchronous event API
+ * requests.
+ *
+ * In most cases, it's far easier for the caller to instantiate a local
+ * LLEventStream and pass its name to the event API in question. Then it's
+ * perfectly reasonable not to set a ["reqid"] key in the request, ignoring
+ * the @c isUndefined() ["reqid"] value in the response.
+ */
+class LL_COMMON_API LLReqID
+{
+public:
+ /**
+ * If you have the request in hand at the time you instantiate the
+ * LLReqID, pass that request to extract its ["reqid"].
+ */
+ LLReqID(const LLSD& request):
+ mReqid(request["reqid"])
+ {}
+ /// If you don't yet have the request, use setFrom() later.
+ LLReqID() {}
+
+ /// Extract and store the ["reqid"] value from an incoming request.
+ void setFrom(const LLSD& request)
+ {
+ mReqid = request["reqid"];
+ }
+
+ /// Set ["reqid"] key into a pending response LLSD object.
+ void stamp(LLSD& response) const;
+
+ /// Make a whole new response LLSD object with our ["reqid"].
+ LLSD makeResponse() const
+ {
+ LLSD response;
+ stamp(response);
+ return response;
+ }
+
+ /// Not really sure of a use case for this accessor...
+ LLSD getReqID() const { return mReqid; }
+
+private:
+ LLSD mReqid;
+};
+
+/**
+ * Base class for LLListenerWrapper. See visit_and_connect() and llwrap(). We
+ * provide virtual @c accept_xxx() methods, customization points allowing a
+ * subclass access to certain data visible at LLEventPump::listen() time.
+ * Example subclass usage:
+ *
+ * @code
+ * myEventPump.listen("somename",
+ * llwrap<MyListenerWrapper>(boost::bind(&MyClass::method, instance, _1)));
+ * @endcode
+ *
+ * Because of the anticipated usage (note the anonymous temporary
+ * MyListenerWrapper instance in the example above), the @c accept_xxx()
+ * methods must be @c const.
+ */
+class LL_COMMON_API LLListenerWrapperBase
+{
+public:
+ /// New instance. The accept_xxx() machinery makes it important to use
+ /// shared_ptrs for our data. Many copies of this object are made before
+ /// the instance that actually ends up in the signal, yet accept_xxx()
+ /// will later be called on the @em original instance. All copies of the
+ /// same original instance must share the same data.
+ LLListenerWrapperBase():
+ mName(new std::string),
+ mConnection(new LLBoundListener)
+ {
+ }
+
+ /// Copy constructor. Copy shared_ptrs to original instance data.
+ LLListenerWrapperBase(const LLListenerWrapperBase& that):
+ mName(that.mName),
+ mConnection(that.mConnection)
+ {
+ }
+ virtual ~LLListenerWrapperBase() {}
+
+ /// Ask LLEventPump::listen() for the listener name
+ virtual void accept_name(const std::string& name) const
+ {
+ *mName = name;
+ }
+
+ /// Ask LLEventPump::listen() for the new connection
+ virtual void accept_connection(const LLBoundListener& connection) const
+ {
+ *mConnection = connection;
+ }
+
+protected:
+ /// Listener name.
+ boost::shared_ptr<std::string> mName;
+ /// Connection.
+ boost::shared_ptr<LLBoundListener> mConnection;
+};
+
+/*****************************************************************************
+* Underpinnings
+*****************************************************************************/
+/**
+ * We originally provided a suite of overloaded
+ * LLEventTrackable::listenTo(LLEventPump&, ...) methods that would call
+ * LLEventPump::listen(...) and then pass the returned LLBoundListener to
+ * LLEventTrackable::track(). This was workable but error-prone: the coder
+ * must remember to call listenTo() rather than the more straightforward
+ * listen() method.
+ *
+ * Now we publish only the single canonical listen() method, so there's a
+ * uniform mechanism. Having a single way to do this is good, in that there's
+ * no question in the coder's mind which of several alternatives to choose.
+ *
+ * To support automatic connection management, we use boost::visit_each
+ * (http://www.boost.org/doc/libs/1_37_0/doc/html/boost/visit_each.html) to
+ * inspect each argument of a boost::bind expression. (Although the visit_each
+ * mechanism was first introduced with the original Boost.Signals library, it
+ * was only later documented.)
+ *
+ * Cases:
+ * * At least one of the function's arguments is a boost::weak_ptr<T>. Pass
+ * the corresponding shared_ptr to slot_type::track(). Ideally that would be
+ * the object whose method we want to call, but in fact we do the same for
+ * any weak_ptr we might find among the bound arguments. If we're passing
+ * our bound method a weak_ptr to some object, wouldn't the destruction of
+ * that object invalidate the call? So we disconnect automatically when any
+ * such object is destroyed. This is the mechanism preferred by boost::
+ * signals2.
+ * * One of the functions's arguments is a boost::shared_ptr<T>. This produces
+ * a compile error: the bound copy of the shared_ptr stored in the
+ * boost_bind object stored in the signal object would make the referenced
+ * T object immortal. We provide a weaken() function. Pass
+ * weaken(your_shared_ptr) instead. (We can inspect, but not modify, the
+ * boost::bind object. Otherwise we'd replace the shared_ptr with weak_ptr
+ * implicitly and just proceed.)
+ * * One of the function's arguments is a plain pointer/reference to an object
+ * derived from boost::enable_shared_from_this. We assume that this object
+ * is managed using boost::shared_ptr, so we implicitly extract a shared_ptr
+ * and track that. (UNDER CONSTRUCTION)
+ * * One of the function's arguments is derived from LLEventTrackable. Pass
+ * the LLBoundListener to its LLEventTrackable::track(). This is vulnerable
+ * to a couple different race conditions, as described in LLEventTrackable
+ * documentation. (NOTE: Now that LLEventTrackable is a typedef for
+ * boost::signals2::trackable, the Signals2 library handles this itself, so
+ * our visitor needs no special logic for this case.)
+ * * Any other argument type is irrelevant to automatic connection management.
+ */
+
+namespace LLEventDetail
+{
+ template <typename F>
+ const F& unwrap(const F& f) { return f; }
+
+ template <typename F>
+ const F& unwrap(const boost::reference_wrapper<F>& f) { return f.get(); }
+
+ // Most of the following is lifted from the Boost.Signals use of
+ // visit_each.
+ template<bool Cond> struct truth {};
+
+ /**
+ * boost::visit_each() Visitor, used on a template argument <tt>const F&
+ * f</tt> as follows (see visit_and_connect()):
+ * @code
+ * LLEventListener listener(f);
+ * Visitor visitor(listener); // bind listener so it can track() shared_ptrs
+ * using boost::visit_each; // allow unqualified visit_each() call for ADL
+ * visit_each(visitor, unwrap(f));
+ * @endcode
+ */
+ class Visitor
+ {
+ public:
+ /**
+ * Visitor binds a reference to LLEventListener so we can track() any
+ * shared_ptrs we find in the argument list.
+ */
+ Visitor(LLEventListener& listener):
+ mListener(listener)
+ {
+ }
+
+ /**
+ * boost::visit_each() calls this method for each component of a
+ * boost::bind() expression.
+ */
+ template <typename T>
+ void operator()(const T& t) const
+ {
+ decode(t, 0);
+ }
+
+ private:
+ // decode() decides between a reference wrapper and anything else
+ // boost::ref() variant
+ template<typename T>
+ void decode(const boost::reference_wrapper<T>& t, int) const
+ {
+// add_if_trackable(t.get_pointer());
+ }
+
+ // decode() anything else
+ template<typename T>
+ void decode(const T& t, long) const
+ {
+ typedef truth<(boost::is_pointer<T>::value)> is_a_pointer;
+ maybe_get_pointer(t, is_a_pointer());
+ }
+
+ // maybe_get_pointer() decides between a pointer and a non-pointer
+ // plain pointer variant
+ template<typename T>
+ void maybe_get_pointer(const T& t, truth<true>) const
+ {
+// add_if_trackable(t);
+ }
+
+ // shared_ptr variant
+ template<typename T>
+ void maybe_get_pointer(const boost::shared_ptr<T>& t, truth<false>) const
+ {
+ // If we have a shared_ptr to this object, it doesn't matter
+ // whether the object is derived from LLEventTrackable, so no
+ // further analysis of T is needed.
+// mListener.track(t);
+
+ // Make this case illegal. Passing a bound shared_ptr to
+ // slot_type::track() is useless, since the bound shared_ptr will
+ // keep the object alive anyway! Force the coder to cast to weak_ptr.
+
+ // Trivial as it is, make the BOOST_STATIC_ASSERT() condition
+ // dependent on template param so the macro is only evaluated if
+ // this method is in fact instantiated, as described here:
+ // http://www.boost.org/doc/libs/1_34_1/doc/html/boost_staticassert.html
+
+ // ATTENTION: Don't bind a shared_ptr<anything> using
+ // LLEventPump::listen(boost::bind()). Doing so captures a copy of
+ // the shared_ptr, making the referenced object effectively
+ // immortal. Use the weaken() function, e.g.:
+ // somepump.listen(boost::bind(...weaken(my_shared_ptr)...));
+ // This lets us automatically disconnect when the referenced
+ // object is destroyed.
+ BOOST_STATIC_ASSERT(sizeof(T) == 0);
+ }
+
+ // weak_ptr variant
+ template<typename T>
+ void maybe_get_pointer(const boost::weak_ptr<T>& t, truth<false>) const
+ {
+ // If we have a weak_ptr to this object, it doesn't matter
+ // whether the object is derived from LLEventTrackable, so no
+ // further analysis of T is needed.
+ mListener.track(t);
+// std::cout << "Found weak_ptr<" << typeid(T).name() << ">!\n";
+ }
+
+#if 0
+ // reference to anything derived from boost::enable_shared_from_this
+ template <typename T>
+ inline void maybe_get_pointer(const boost::enable_shared_from_this<T>& ct,
+ truth<false>) const
+ {
+ // Use the slot_type::track(shared_ptr) mechanism. Cast away
+ // const-ness because (in our code base anyway) it's unusual
+ // to find shared_ptr<const T>.
+ boost::enable_shared_from_this<T>&
+ t(const_cast<boost::enable_shared_from_this<T>&>(ct));
+ std::cout << "Capturing shared_from_this()" << std::endl;
+ boost::shared_ptr<T> sp(t.shared_from_this());
+/*==========================================================================*|
+ std::cout << "Capturing weak_ptr" << std::endl;
+ boost::weak_ptr<T> wp(sp);
+|*==========================================================================*/
+ std::cout << "Tracking shared__ptr" << std::endl;
+ mListener.track(sp);
+ }
+#endif
+
+ // non-pointer variant
+ template<typename T>
+ void maybe_get_pointer(const T& t, truth<false>) const
+ {
+ // Take the address of this object, because the object itself may be
+ // trackable
+// add_if_trackable(boost::addressof(t));
+ }
+
+/*==========================================================================*|
+ // add_if_trackable() adds LLEventTrackable objects to mTrackables
+ inline void add_if_trackable(const LLEventTrackable* t) const
+ {
+ if (t)
+ {
+ }
+ }
+
+ // pointer to anything not an LLEventTrackable subclass
+ inline void add_if_trackable(const void*) const
+ {
+ }
+
+ // pointer to free function
+ // The following construct uses the preprocessor to generate
+ // add_if_trackable() overloads accepting pointer-to-function taking
+ // 0, 1, ..., LLEVENTS_LISTENER_ARITY parameters of arbitrary type.
+#define BOOST_PP_LOCAL_MACRO(n) \
+ template <typename R \
+ BOOST_PP_COMMA_IF(n) \
+ BOOST_PP_ENUM_PARAMS(n, typename T)> \
+ inline void \
+ add_if_trackable(R (*)(BOOST_PP_ENUM_PARAMS(n, T))) const \
+ { \
+ }
+#define BOOST_PP_LOCAL_LIMITS (0, LLEVENTS_LISTENER_ARITY)
+#include BOOST_PP_LOCAL_ITERATE()
+#undef BOOST_PP_LOCAL_MACRO
+#undef BOOST_PP_LOCAL_LIMITS
+|*==========================================================================*/
+
+ /// Bind a reference to the LLEventListener to call its track() method.
+ LLEventListener& mListener;
+ };
+
+ /**
+ * Utility template function to use Visitor appropriately
+ *
+ * @param raw_listener Callable to connect, typically a boost::bind()
+ * expression. This will be visited by Visitor using boost::visit_each().
+ * @param connect_funct Callable that will connect() @a raw_listener to an
+ * LLStandardSignal, returning LLBoundListener.
+ */
+ template <typename LISTENER>
+ LLBoundListener visit_and_connect(const std::string& name,
+ const LISTENER& raw_listener,
+ const ConnectFunc& connect_func)
+ {
+ // Capture the listener
+ LLEventListener listener(raw_listener);
+ // Define our Visitor, binding the listener so we can call
+ // listener.track() if we discover any shared_ptr<Foo>.
+ LLEventDetail::Visitor visitor(listener);
+ // Allow unqualified visit_each() call for ADL
+ using boost::visit_each;
+ // Visit each component of a boost::bind() expression. Pass
+ // 'raw_listener', our template argument, rather than 'listener' from
+ // which type details have been erased. unwrap() comes from
+ // Boost.Signals, in case we were passed a boost::ref().
+ visit_each(visitor, LLEventDetail::unwrap(raw_listener));
+ // Make the connection using passed function.
+ LLBoundListener connection(connect_func(listener));
+ // If the LISTENER is an LLListenerWrapperBase subclass, pass it the
+ // desired information. It's important that we pass the raw_listener
+ // so the compiler can make decisions based on its original type.
+ const LLListenerWrapperBase* lwb =
+ ll_template_cast<const LLListenerWrapperBase*>(&raw_listener);
+ if (lwb)
+ {
+ lwb->accept_name(name);
+ lwb->accept_connection(connection);
+ }
+ // In any case, show new connection to caller.
+ return connection;
+ }
+} // namespace LLEventDetail
+
+// Somewhat to my surprise, passing boost::bind(...boost::weak_ptr<T>...) to
+// listen() fails in Boost code trying to instantiate LLEventListener (i.e.
+// LLStandardSignal::slot_type) because the boost::get_pointer() utility function isn't
+// specialized for boost::weak_ptr. This remedies that omission.
+namespace boost
+{
+ template <typename T>
+ T* get_pointer(const weak_ptr<T>& ptr) { return shared_ptr<T>(ptr).get(); }
+}
+
+/// Since we forbid use of listen(boost::bind(...shared_ptr<T>...)), provide an
+/// easy way to cast to the corresponding weak_ptr.
+template <typename T>
+boost::weak_ptr<T> weaken(const boost::shared_ptr<T>& ptr)
+{
+ return boost::weak_ptr<T>(ptr);
+}
+
+#endif /* ! defined(LL_LLEVENTS_H) */
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 94b51119e4..9f9e2ea945 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -1,11 +1,11 @@
-/**
+/**
* @file llfasttimer.h
- * @brief Declaration of a fast timer.
+ * @brief Inline implementations of fast timers.
*
* $LicenseInfo:firstyear=2004&license=viewergpl$
- *
+ *
* Copyright (c) 2004-2009, Linden Research, Inc.
- *
+ *
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
@@ -13,246 +13,154 @@
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
+ *
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
+ *
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
- *
+ *
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
-#ifndef LL_LLFASTTIMER_H
-#define LL_LLFASTTIMER_H
+#ifndef LL_FASTTIMER_H
+#define LL_FASTTIMER_H
+
+// pull in the actual class definition
+#include "llfasttimer_class.h"
+
+#if LL_WINDOWS
+//
+// Windows implementation of CPU clock
+//
-#define FAST_TIMER_ON 1
+//
+// NOTE: put back in when we aren't using platform sdk anymore
+//
+// because MS has different signatures for these functions in winnt.h
+// need to rename them to avoid conflicts
+//#define _interlockedbittestandset _renamed_interlockedbittestandset
+//#define _interlockedbittestandreset _renamed_interlockedbittestandreset
+//#include <intrin.h>
+//#undef _interlockedbittestandset
+//#undef _interlockedbittestandreset
-U64 get_cpu_clock_count();
+//inline U32 LLFastTimer::getCPUClockCount32()
+//{
+// U64 time_stamp = __rdtsc();
+// return (U32)(time_stamp >> 8);
+//}
+//
+//// return full timer value, *not* shifted by 8 bits
+//inline U64 LLFastTimer::getCPUClockCount64()
+//{
+// return __rdtsc();
+//}
-class LLFastTimer
+// shift off lower 8 bits for lower resolution but longer term timing
+// on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing
+inline U32 LLFastTimer::getCPUClockCount32()
{
-public:
- enum EFastTimerType
+ U32 ret_val;
+ __asm
{
- // high level
- FTM_FRAME,
- FTM_UPDATE,
- FTM_RENDER,
- FTM_SWAP,
- FTM_CLIENT_COPY,
- FTM_IDLE,
- FTM_SLEEP,
-
- // common messaging components
- FTM_PUMP,
- FTM_CURL,
-
- // common simulation components
- FTM_UPDATE_ANIMATION,
- FTM_UPDATE_TERRAIN,
- FTM_UPDATE_PRIMITIVES,
- FTM_UPDATE_PARTICLES,
- FTM_SIMULATE_PARTICLES,
- FTM_UPDATE_SKY,
- FTM_UPDATE_TEXTURES,
- FTM_UPDATE_WLPARAM,
- FTM_UPDATE_WATER,
- FTM_UPDATE_CLOUDS,
- FTM_UPDATE_GRASS,
- FTM_UPDATE_TREE,
- FTM_UPDATE_AVATAR,
-
- // common render components
- FTM_SHADOW_GEOMETRY,
- FTM_SHADOW_RENDER,
- FTM_SHADOW_TERRAIN,
- FTM_SHADOW_AVATAR,
- FTM_SHADOW_SIMPLE,
- FTM_SHADOW_ALPHA,
- FTM_SHADOW_TREE,
-
- FTM_RENDER_GEOMETRY,
- FTM_RENDER_TERRAIN,
- FTM_RENDER_SIMPLE,
- FTM_RENDER_FULLBRIGHT,
- FTM_RENDER_GLOW,
- FTM_RENDER_GRASS,
- FTM_RENDER_INVISIBLE,
- FTM_RENDER_SHINY,
- FTM_RENDER_BUMP,
- FTM_RENDER_TREES,
- FTM_RENDER_CHARACTERS,
- FTM_RENDER_OCCLUSION,
- FTM_RENDER_ALPHA,
- FTM_RENDER_CLOUDS,
- FTM_RENDER_HUD,
- FTM_RENDER_PARTICLES,
- FTM_RENDER_WATER,
- FTM_RENDER_WL_SKY,
- FTM_RENDER_FAKE_VBO_UPDATE,
- FTM_RENDER_TIMER,
- FTM_RENDER_UI,
- FTM_RENDER_BLOOM,
- FTM_RENDER_BLOOM_FBO,
- FTM_RENDER_FONTS,
-
- // newview specific
- FTM_MESSAGES,
- FTM_MOUSEHANDLER,
- FTM_KEYHANDLER,
- FTM_REBUILD,
- FTM_STATESORT,
- FTM_STATESORT_DRAWABLE,
- FTM_STATESORT_POSTSORT,
- FTM_REBUILD_VBO,
- FTM_REBUILD_VOLUME_VB,
- FTM_REBUILD_BRIDGE_VB,
- FTM_REBUILD_HUD_VB,
- FTM_REBUILD_TERRAIN_VB,
- FTM_REBUILD_WATER_VB,
- FTM_REBUILD_TREE_VB,
- FTM_REBUILD_PARTICLE_VB,
- FTM_REBUILD_CLOUD_VB,
- FTM_REBUILD_GRASS_VB,
- FTM_REBUILD_NONE_VB,
- FTM_REBUILD_OCCLUSION_VB,
- FTM_POOLS,
- FTM_POOLRENDER,
- FTM_IDLE_CB,
- FTM_WORLD_UPDATE,
- FTM_UPDATE_MOVE,
- FTM_OCTREE_BALANCE,
- FTM_UPDATE_LIGHTS,
- FTM_CULL,
- FTM_CULL_REBOUND,
- FTM_FRUSTUM_CULL,
- FTM_GEO_UPDATE,
- FTM_GEO_RESERVE,
- FTM_GEO_LIGHT,
- FTM_GEO_SHADOW,
- FTM_GEO_SKY,
- FTM_GEN_VOLUME,
- FTM_GEN_TRIANGLES,
- FTM_GEN_FLEX,
- FTM_AUDIO_UPDATE,
- FTM_RESET_DRAWORDER,
- FTM_OBJECTLIST_UPDATE,
- FTM_AVATAR_UPDATE,
- FTM_JOINT_UPDATE,
- FTM_ATTACHMENT_UPDATE,
- FTM_LOD_UPDATE,
- FTM_REGION_UPDATE,
- FTM_CLEANUP,
- FTM_NETWORK,
- FTM_IDLE_NETWORK,
- FTM_CREATE_OBJECT,
- FTM_LOAD_AVATAR,
- FTM_PROCESS_MESSAGES,
- FTM_PROCESS_OBJECTS,
- FTM_PROCESS_IMAGES,
- FTM_IMAGE_UPDATE,
- FTM_IMAGE_CREATE,
- FTM_IMAGE_DECODE,
- FTM_IMAGE_MARK_DIRTY,
- FTM_PIPELINE,
- FTM_VFILE_WAIT,
- FTM_FLEXIBLE_UPDATE,
- FTM_OCCLUSION_READBACK,
- FTM_HUD_EFFECTS,
- FTM_HUD_UPDATE,
- FTM_INVENTORY,
- FTM_AUTO_SELECT,
- FTM_ARRANGE,
- FTM_FILTER,
- FTM_REFRESH,
- FTM_SORT,
- FTM_PICK,
-
- // Temp
- FTM_TEMP1,
- FTM_TEMP2,
- FTM_TEMP3,
- FTM_TEMP4,
- FTM_TEMP5,
- FTM_TEMP6,
- FTM_TEMP7,
- FTM_TEMP8,
-
- FTM_OTHER, // Special, used by display code
-
- FTM_NUM_TYPES
- };
- enum { FTM_HISTORY_NUM = 60 };
- enum { FTM_MAX_DEPTH = 64 };
-
-public:
- static LLFastTimer::EFastTimerType sCurType;
+ _emit 0x0f
+ _emit 0x31
+ shr eax,8
+ shl edx,24
+ or eax, edx
+ mov dword ptr [ret_val], eax
+ }
+ return ret_val;
+}
- LLFastTimer(EFastTimerType type)
+// return full timer value, *not* shifted by 8 bits
+inline U64 LLFastTimer::getCPUClockCount64()
+{
+ U64 ret_val;
+ __asm
{
-#if FAST_TIMER_ON
- mType = type;
- sCurType = type;
- // These don't get counted, because they use CPU clockticks
- //gTimerBins[gCurTimerBin]++;
- //LLTimer::sNumTimerCalls++;
+ _emit 0x0f
+ _emit 0x31
+ mov eax,eax
+ mov edx,edx
+ mov dword ptr [ret_val+4], edx
+ mov dword ptr [ret_val], eax
+ }
+ return ret_val;
+}
+#endif
- U64 cpu_clocks = get_cpu_clock_count();
- sStart[sCurDepth] = cpu_clocks;
- sCurDepth++;
+#if LL_LINUX || LL_SOLARIS
+//
+// Linux and Solaris implementation of CPU clock - all architectures.
+//
+// Try to use the MONOTONIC clock if available, this is a constant time counter
+// with nanosecond resolution (but not necessarily accuracy) and attempts are made
+// to synchronize this value between cores at kernel start. It should not be affected
+// by CPU frequency. If not available use the REALTIME clock, but this may be affected by
+// NTP adjustments or other user activity affecting the system time.
+inline U64 LLFastTimer::getCPUClockCount64()
+{
+ struct timespec tp;
+
+#ifdef CLOCK_MONOTONIC // MONOTONIC supported at build-time?
+ if (-1 == clock_gettime(CLOCK_MONOTONIC,&tp)) // if MONOTONIC isn't supported at runtime, try REALTIME
#endif
- };
- ~LLFastTimer()
- {
-#if FAST_TIMER_ON
- U64 end,delta;
- int i;
+ clock_gettime(CLOCK_REALTIME,&tp);
- // These don't get counted, because they use CPU clockticks
- //gTimerBins[gCurTimerBin]++;
- //LLTimer::sNumTimerCalls++;
- end = get_cpu_clock_count();
+ return (tp.tv_sec*LLFastTimer::sClockResolution)+tp.tv_nsec;
+}
+
+inline U32 LLFastTimer::getCPUClockCount32()
+{
+ return (U32)LLFastTimer::getCPUClockCount64();
+}
+#endif // (LL_LINUX || LL_SOLARIS))
+
+
+#if (LL_DARWIN) && (defined(__i386__) || defined(__amd64__))
+//
+// Mac x86 implementation of CPU clock
+inline U32 LLFastTimer::getCPUClockCount32()
+{
+ U64 x;
+ __asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
+ return (U32)x >> 8;
+}
- sCurDepth--;
- delta = end - sStart[sCurDepth];
- sCounter[mType] += delta;
- sCalls[mType]++;
- // Subtract delta from parents
- for (i=0; i<sCurDepth; i++)
- sStart[i] += delta;
+inline U32 LLFastTimer::getCPUClockCount64()
+{
+ U64 x;
+ __asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
+ return x >> 8;
+}
#endif
- }
- static void reset();
- static U64 countsPerSecond();
-public:
- static int sCurDepth;
- static U64 sStart[FTM_MAX_DEPTH];
- static U64 sCounter[FTM_NUM_TYPES];
- static U64 sCalls[FTM_NUM_TYPES];
- static U64 sCountAverage[FTM_NUM_TYPES];
- static U64 sCallAverage[FTM_NUM_TYPES];
- static U64 sCountHistory[FTM_HISTORY_NUM][FTM_NUM_TYPES];
- static U64 sCallHistory[FTM_HISTORY_NUM][FTM_NUM_TYPES];
- static S32 sCurFrameIndex;
- static S32 sLastFrameIndex;
- static int sPauseHistory;
- static int sResetHistory;
- static F64 sCPUClockFrequency;
-
-private:
- EFastTimerType mType;
-};
+#if ( LL_DARWIN && !(defined(__i386__) || defined(__amd64__)))
+//
+// Mac PPC (deprecated) implementation of CPU clock
+//
+// Just use gettimeofday implementation for now
+inline U32 LLFastTimer::getCPUClockCount32()
+{
+ return (U32)get_clock_count();
+}
+
+inline U32 LLFastTimer::getCPUClockCount64()
+{
+ return get_clock_count();
+}
+#endif
#endif // LL_LLFASTTIMER_H
diff --git a/indra/llcommon/llfasttimer_class.cpp b/indra/llcommon/llfasttimer_class.cpp
new file mode 100644
index 0000000000..abcaee673e
--- /dev/null
+++ b/indra/llcommon/llfasttimer_class.cpp
@@ -0,0 +1,751 @@
+/**
+ * @file llfasttimer_class.cpp
+ * @brief Implementation of the fast timer.
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS."LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+
+#include "llfasttimer.h"
+
+#include "llmemory.h"
+#include "llprocessor.h"
+#include "llsingleton.h"
+#include "lltreeiterators.h"
+#include "llsdserialize.h"
+
+#include <boost/bind.hpp>
+
+#if LL_WINDOWS
+#elif LL_LINUX || LL_SOLARIS
+#include <sys/time.h>
+#include <sched.h>
+#elif LL_DARWIN
+#include <sys/time.h>
+#include "lltimer.h" // get_clock_count()
+#else
+#error "architecture not supported"
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// statics
+
+S32 LLFastTimer::sCurFrameIndex = -1;
+S32 LLFastTimer::sLastFrameIndex = -1;
+U64 LLFastTimer::sLastFrameTime = LLFastTimer::getCPUClockCount64();
+bool LLFastTimer::sPauseHistory = 0;
+bool LLFastTimer::sResetHistory = 0;
+LLFastTimer::CurTimerData LLFastTimer::sCurTimerData;
+BOOL LLFastTimer::sLog = FALSE;
+BOOL LLFastTimer::sMetricLog = FALSE;
+LLMutex* LLFastTimer::sLogLock = NULL;
+std::queue<LLSD> LLFastTimer::sLogQueue;
+
+#if LL_LINUX || LL_SOLARIS
+U64 LLFastTimer::sClockResolution = 1000000000; // Nanosecond resolution
+#else
+U64 LLFastTimer::sClockResolution = 1000000; // Microsecond resolution
+#endif
+
+std::vector<LLFastTimer::FrameState>* LLFastTimer::sTimerInfos = NULL;
+U64 LLFastTimer::sTimerCycles = 0;
+U32 LLFastTimer::sTimerCalls = 0;
+
+
+// FIXME: move these declarations to the relevant modules
+
+// helper functions
+typedef LLTreeDFSPostIter<LLFastTimer::NamedTimer, LLFastTimer::NamedTimer::child_const_iter> timer_tree_bottom_up_iterator_t;
+
+static timer_tree_bottom_up_iterator_t begin_timer_tree_bottom_up(LLFastTimer::NamedTimer& id)
+{
+ return timer_tree_bottom_up_iterator_t(&id,
+ boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::beginChildren), _1),
+ boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::endChildren), _1));
+}
+
+static timer_tree_bottom_up_iterator_t end_timer_tree_bottom_up()
+{
+ return timer_tree_bottom_up_iterator_t();
+}
+
+typedef LLTreeDFSIter<LLFastTimer::NamedTimer, LLFastTimer::NamedTimer::child_const_iter> timer_tree_dfs_iterator_t;
+
+
+static timer_tree_dfs_iterator_t begin_timer_tree(LLFastTimer::NamedTimer& id)
+{
+ return timer_tree_dfs_iterator_t(&id,
+ boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::beginChildren), _1),
+ boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::endChildren), _1));
+}
+
+static timer_tree_dfs_iterator_t end_timer_tree()
+{
+ return timer_tree_dfs_iterator_t();
+}
+
+
+
+// factory class that creates NamedTimers via static DeclareTimer objects
+class NamedTimerFactory : public LLSingleton<NamedTimerFactory>
+{
+public:
+ NamedTimerFactory()
+ {}
+
+ /*virtual */ void initSingleton()
+ {
+ mTimerRoot = new LLFastTimer::NamedTimer("root");
+
+ mActiveTimerRoot = new LLFastTimer::NamedTimer("Frame");
+ mActiveTimerRoot->setCollapsed(false);
+
+ mRootFrameState = new LLFastTimer::FrameState(mActiveTimerRoot);
+ mRootFrameState->mParent = &mTimerRoot->getFrameState();
+ mActiveTimerRoot->setParent(mTimerRoot);
+
+ mAppTimer = new LLFastTimer(mRootFrameState);
+ }
+
+ ~NamedTimerFactory()
+ {
+ std::for_each(mTimers.begin(), mTimers.end(), DeletePairedPointer());
+
+ delete mAppTimer;
+ delete mActiveTimerRoot;
+ delete mTimerRoot;
+ delete mRootFrameState;
+ }
+
+ LLFastTimer::NamedTimer& createNamedTimer(const std::string& name)
+ {
+ timer_map_t::iterator found_it = mTimers.find(name);
+ if (found_it != mTimers.end())
+ {
+ return *found_it->second;
+ }
+
+ LLFastTimer::NamedTimer* timer = new LLFastTimer::NamedTimer(name);
+ timer->setParent(mTimerRoot);
+ mTimers.insert(std::make_pair(name, timer));
+
+ return *timer;
+ }
+
+ LLFastTimer::NamedTimer* getTimerByName(const std::string& name)
+ {
+ timer_map_t::iterator found_it = mTimers.find(name);
+ if (found_it != mTimers.end())
+ {
+ return found_it->second;
+ }
+ return NULL;
+ }
+
+ LLFastTimer::NamedTimer* getActiveRootTimer() { return mActiveTimerRoot; }
+ LLFastTimer::NamedTimer* getRootTimer() { return mTimerRoot; }
+ const LLFastTimer* getAppTimer() { return mAppTimer; }
+ LLFastTimer::FrameState& getRootFrameState() { return *mRootFrameState; }
+
+ typedef std::map<std::string, LLFastTimer::NamedTimer*> timer_map_t;
+ timer_map_t::iterator beginTimers() { return mTimers.begin(); }
+ timer_map_t::iterator endTimers() { return mTimers.end(); }
+ S32 timerCount() { return mTimers.size(); }
+
+private:
+ timer_map_t mTimers;
+
+ LLFastTimer::NamedTimer* mActiveTimerRoot;
+ LLFastTimer::NamedTimer* mTimerRoot;
+ LLFastTimer* mAppTimer;
+ LLFastTimer::FrameState* mRootFrameState;
+};
+
+void update_cached_pointers_if_changed()
+{
+ // detect when elements have moved and update cached pointers
+ static LLFastTimer::FrameState* sFirstTimerAddress = NULL;
+ if (&*(LLFastTimer::getFrameStateList().begin()) != sFirstTimerAddress)
+ {
+ LLFastTimer::DeclareTimer::updateCachedPointers();
+ }
+ sFirstTimerAddress = &*(LLFastTimer::getFrameStateList().begin());
+}
+
+LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name, bool open )
+: mTimer(NamedTimerFactory::instance().createNamedTimer(name))
+{
+ mTimer.setCollapsed(!open);
+ mFrameState = &mTimer.getFrameState();
+ update_cached_pointers_if_changed();
+}
+
+LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name)
+: mTimer(NamedTimerFactory::instance().createNamedTimer(name))
+{
+ mFrameState = &mTimer.getFrameState();
+ update_cached_pointers_if_changed();
+}
+
+// static
+void LLFastTimer::DeclareTimer::updateCachedPointers()
+{
+ // propagate frame state pointers to timer declarations
+ for (DeclareTimer::instance_iter it = DeclareTimer::beginInstances();
+ it != DeclareTimer::endInstances();
+ ++it)
+ {
+ // update cached pointer
+ it->mFrameState = &it->mTimer.getFrameState();
+ }
+}
+
+//static
+#if LL_LINUX || LL_SOLARIS || ( LL_DARWIN && !(defined(__i386__) || defined(__amd64__)) )
+U64 LLFastTimer::countsPerSecond()
+{
+ return sClockResolution;
+}
+#else // windows or x86-mac
+U64 LLFastTimer::countsPerSecond()
+{
+ static U64 sCPUClockFrequency = U64(CProcessor().GetCPUFrequency(50));
+
+ // we drop the low-order byte in out timers, so report a lower frequency
+ return sCPUClockFrequency >> 8;
+}
+#endif
+
+LLFastTimer::FrameState::FrameState(LLFastTimer::NamedTimer* timerp)
+: mActiveCount(0),
+ mCalls(0),
+ mSelfTimeCounter(0),
+ mParent(NULL),
+ mLastCaller(NULL),
+ mMoveUpTree(false),
+ mTimer(timerp)
+{}
+
+
+LLFastTimer::NamedTimer::NamedTimer(const std::string& name)
+: mName(name),
+ mCollapsed(true),
+ mParent(NULL),
+ mTotalTimeCounter(0),
+ mCountAverage(0),
+ mCallAverage(0),
+ mNeedsSorting(false)
+{
+ info_list_t& frame_state_list = getFrameStateList();
+ mFrameStateIndex = frame_state_list.size();
+ getFrameStateList().push_back(FrameState(this));
+
+ mCountHistory = new U32[HISTORY_NUM];
+ memset(mCountHistory, 0, sizeof(U32) * HISTORY_NUM);
+ mCallHistory = new U32[HISTORY_NUM];
+ memset(mCallHistory, 0, sizeof(U32) * HISTORY_NUM);
+}
+
+LLFastTimer::NamedTimer::~NamedTimer()
+{
+ delete[] mCountHistory;
+ delete[] mCallHistory;
+}
+
+std::string LLFastTimer::NamedTimer::getToolTip(S32 history_idx)
+{
+ if (history_idx < 0)
+ {
+ // by default, show average number of calls
+ return llformat("%s (%d calls)", getName().c_str(), (S32)getCallAverage());
+ }
+ else
+ {
+ return llformat("%s (%d calls)", getName().c_str(), (S32)getHistoricalCalls(history_idx));
+ }
+}
+
+void LLFastTimer::NamedTimer::setParent(NamedTimer* parent)
+{
+ llassert_always(parent != this);
+ llassert_always(parent != NULL);
+
+ if (mParent)
+ {
+ // subtract our accumulated from previous parent
+ for (S32 i = 0; i < HISTORY_NUM; i++)
+ {
+ mParent->mCountHistory[i] -= mCountHistory[i];
+ }
+
+ // subtract average timing from previous parent
+ mParent->mCountAverage -= mCountAverage;
+
+ std::vector<NamedTimer*>& children = mParent->getChildren();
+ std::vector<NamedTimer*>::iterator found_it = std::find(children.begin(), children.end(), this);
+ if (found_it != children.end())
+ {
+ children.erase(found_it);
+ }
+ }
+
+ mParent = parent;
+ if (parent)
+ {
+ getFrameState().mParent = &parent->getFrameState();
+ parent->getChildren().push_back(this);
+ parent->mNeedsSorting = true;
+ }
+}
+
+S32 LLFastTimer::NamedTimer::getDepth()
+{
+ S32 depth = 0;
+ NamedTimer* timerp = mParent;
+ while(timerp)
+ {
+ depth++;
+ timerp = timerp->mParent;
+ }
+ return depth;
+}
+
+// static
+void LLFastTimer::NamedTimer::processTimes()
+{
+ if (sCurFrameIndex < 0) return;
+
+ buildHierarchy();
+ accumulateTimings();
+}
+
+// sort timer info structs by depth first traversal order
+struct SortTimersDFS
+{
+ bool operator()(const LLFastTimer::FrameState& i1, const LLFastTimer::FrameState& i2)
+ {
+ return i1.mTimer->getFrameStateIndex() < i2.mTimer->getFrameStateIndex();
+ }
+};
+
+// sort child timers by name
+struct SortTimerByName
+{
+ bool operator()(const LLFastTimer::NamedTimer* i1, const LLFastTimer::NamedTimer* i2)
+ {
+ return i1->getName() < i2->getName();
+ }
+};
+
+//static
+void LLFastTimer::NamedTimer::buildHierarchy()
+{
+ if (sCurFrameIndex < 0 ) return;
+
+ // set up initial tree
+ for (instance_iter it = NamedTimer::beginInstances();
+ it != endInstances();
+ ++it)
+ {
+ NamedTimer& timer = *it;
+ if (&timer == NamedTimerFactory::instance().getRootTimer()) continue;
+
+ // bootstrap tree construction by attaching to last timer to be on stack
+ // when this timer was called
+ if (timer.getFrameState().mLastCaller && timer.mParent == NamedTimerFactory::instance().getRootTimer())
+ {
+ timer.setParent(timer.getFrameState().mLastCaller->mTimer);
+ // no need to push up tree on first use, flag can be set spuriously
+ timer.getFrameState().mMoveUpTree = false;
+ }
+ }
+
+ // bump timers up tree if they've been flagged as being in the wrong place
+ // do this in a bottom up order to promote descendants first before promoting ancestors
+ // this preserves partial order derived from current frame's observations
+ for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(*NamedTimerFactory::instance().getRootTimer());
+ it != end_timer_tree_bottom_up();
+ ++it)
+ {
+ NamedTimer* timerp = *it;
+ // skip root timer
+ if (timerp == NamedTimerFactory::instance().getRootTimer()) continue;
+
+ if (timerp->getFrameState().mMoveUpTree)
+ {
+ // since ancestors have already been visited, reparenting won't affect tree traversal
+ //step up tree, bringing our descendants with us
+ //llinfos << "Moving " << timerp->getName() << " from child of " << timerp->getParent()->getName() <<
+ // " to child of " << timerp->getParent()->getParent()->getName() << llendl;
+ timerp->setParent(timerp->getParent()->getParent());
+ timerp->getFrameState().mMoveUpTree = false;
+
+ // don't bubble up any ancestors until descendants are done bubbling up
+ it.skipAncestors();
+ }
+ }
+
+ // sort timers by time last called, so call graph makes sense
+ for(timer_tree_dfs_iterator_t it = begin_timer_tree(*NamedTimerFactory::instance().getRootTimer());
+ it != end_timer_tree();
+ ++it)
+ {
+ NamedTimer* timerp = (*it);
+ if (timerp->mNeedsSorting)
+ {
+ std::sort(timerp->getChildren().begin(), timerp->getChildren().end(), SortTimerByName());
+ }
+ timerp->mNeedsSorting = false;
+ }
+}
+
+//static
+void LLFastTimer::NamedTimer::accumulateTimings()
+{
+ U32 cur_time = getCPUClockCount32();
+
+ // walk up stack of active timers and accumulate current time while leaving timing structures active
+ LLFastTimer* cur_timer = sCurTimerData.mCurTimer;
+ // root defined by parent pointing to self
+ CurTimerData* cur_data = &sCurTimerData;
+ while(cur_timer->mLastTimerData.mCurTimer != cur_timer)
+ {
+ U32 cumulative_time_delta = cur_time - cur_timer->mStartTime;
+ U32 self_time_delta = cumulative_time_delta - cur_data->mChildTime;
+ cur_data->mChildTime = 0;
+ cur_timer->mFrameState->mSelfTimeCounter += self_time_delta;
+ cur_timer->mStartTime = cur_time;
+
+ cur_data = &cur_timer->mLastTimerData;
+ cur_data->mChildTime += cumulative_time_delta;
+
+ cur_timer = cur_timer->mLastTimerData.mCurTimer;
+ }
+
+ // traverse tree in DFS post order, or bottom up
+ for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(*NamedTimerFactory::instance().getActiveRootTimer());
+ it != end_timer_tree_bottom_up();
+ ++it)
+ {
+ NamedTimer* timerp = (*it);
+ timerp->mTotalTimeCounter = timerp->getFrameState().mSelfTimeCounter;
+ for (child_const_iter child_it = timerp->beginChildren(); child_it != timerp->endChildren(); ++child_it)
+ {
+ timerp->mTotalTimeCounter += (*child_it)->mTotalTimeCounter;
+ }
+
+ S32 cur_frame = sCurFrameIndex;
+ if (cur_frame >= 0)
+ {
+ // update timer history
+ int hidx = cur_frame % HISTORY_NUM;
+
+ timerp->mCountHistory[hidx] = timerp->mTotalTimeCounter;
+ timerp->mCountAverage = (timerp->mCountAverage * cur_frame + timerp->mTotalTimeCounter) / (cur_frame+1);
+ timerp->mCallHistory[hidx] = timerp->getFrameState().mCalls;
+ timerp->mCallAverage = (timerp->mCallAverage * cur_frame + timerp->getFrameState().mCalls) / (cur_frame+1);
+ }
+ }
+}
+
+// static
+void LLFastTimer::NamedTimer::resetFrame()
+{
+ if (sLog)
+ { //output current frame counts to performance log
+ F64 iclock_freq = 1000.0 / countsPerSecond(); // good place to calculate clock frequency
+
+ F64 total_time = 0;
+ LLSD sd;
+
+ for (NamedTimer::instance_iter it = NamedTimer::beginInstances();
+ it != NamedTimer::endInstances();
+ ++it)
+ {
+ NamedTimer& timer = *it;
+ FrameState& info = timer.getFrameState();
+ sd[timer.getName()]["Time"] = (LLSD::Real) (info.mSelfTimeCounter*iclock_freq);
+ sd[timer.getName()]["Calls"] = (LLSD::Integer) info.mCalls;
+
+ // computing total time here because getting the root timer's getCountHistory
+ // doesn't work correctly on the first frame
+ total_time = total_time + info.mSelfTimeCounter * iclock_freq;
+ }
+
+ sd["Total"]["Time"] = (LLSD::Real) total_time;
+ sd["Total"]["Calls"] = (LLSD::Integer) 1;
+
+ {
+ LLMutexLock lock(sLogLock);
+ sLogQueue.push(sd);
+ }
+ }
+
+
+ // tag timers by position in depth first traversal of tree
+ S32 index = 0;
+ for(timer_tree_dfs_iterator_t it = begin_timer_tree(*NamedTimerFactory::instance().getRootTimer());
+ it != end_timer_tree();
+ ++it)
+ {
+ NamedTimer* timerp = (*it);
+
+ timerp->mFrameStateIndex = index;
+ index++;
+
+ llassert_always(timerp->mFrameStateIndex < (S32)getFrameStateList().size());
+ }
+
+ // sort timers by dfs traversal order to improve cache coherency
+ std::sort(getFrameStateList().begin(), getFrameStateList().end(), SortTimersDFS());
+
+ // update pointers into framestatelist now that we've sorted it
+ DeclareTimer::updateCachedPointers();
+
+ // reset for next frame
+ for (NamedTimer::instance_iter it = NamedTimer::beginInstances();
+ it != NamedTimer::endInstances();
+ ++it)
+ {
+ NamedTimer& timer = *it;
+
+ FrameState& info = timer.getFrameState();
+ info.mSelfTimeCounter = 0;
+ info.mCalls = 0;
+ info.mLastCaller = NULL;
+ info.mMoveUpTree = false;
+ // update parent pointer in timer state struct
+ if (timer.mParent)
+ {
+ info.mParent = &timer.mParent->getFrameState();
+ }
+ }
+
+ //sTimerCycles = 0;
+ //sTimerCalls = 0;
+}
+
+//static
+void LLFastTimer::NamedTimer::reset()
+{
+ resetFrame(); // reset frame data
+
+ // walk up stack of active timers and reset start times to current time
+ // effectively zeroing out any accumulated time
+ U32 cur_time = getCPUClockCount32();
+
+ // root defined by parent pointing to self
+ CurTimerData* cur_data = &sCurTimerData;
+ LLFastTimer* cur_timer = cur_data->mCurTimer;
+ while(cur_timer->mLastTimerData.mCurTimer != cur_timer)
+ {
+ cur_timer->mStartTime = cur_time;
+ cur_data->mChildTime = 0;
+
+ cur_data = &cur_timer->mLastTimerData;
+ cur_timer = cur_data->mCurTimer;
+ }
+
+ // reset all history
+ for (NamedTimer::instance_iter it = NamedTimer::beginInstances();
+ it != NamedTimer::endInstances();
+ ++it)
+ {
+ NamedTimer& timer = *it;
+ if (&timer != NamedTimerFactory::instance().getRootTimer())
+ {
+ timer.setParent(NamedTimerFactory::instance().getRootTimer());
+ }
+
+ timer.mCountAverage = 0;
+ timer.mCallAverage = 0;
+ memset(timer.mCountHistory, 0, sizeof(U32) * HISTORY_NUM);
+ memset(timer.mCallHistory, 0, sizeof(U32) * HISTORY_NUM);
+ }
+
+ sLastFrameIndex = 0;
+ sCurFrameIndex = 0;
+}
+
+//static
+LLFastTimer::info_list_t& LLFastTimer::getFrameStateList()
+{
+ if (!sTimerInfos)
+ {
+ sTimerInfos = new info_list_t();
+ }
+ return *sTimerInfos;
+}
+
+
+U32 LLFastTimer::NamedTimer::getHistoricalCount(S32 history_index) const
+{
+ S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::NamedTimer::HISTORY_NUM;
+ return mCountHistory[history_idx];
+}
+
+U32 LLFastTimer::NamedTimer::getHistoricalCalls(S32 history_index ) const
+{
+ S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::NamedTimer::HISTORY_NUM;
+ return mCallHistory[history_idx];
+}
+
+LLFastTimer::FrameState& LLFastTimer::NamedTimer::getFrameState() const
+{
+ llassert_always(mFrameStateIndex >= 0);
+ if (this == NamedTimerFactory::instance().getActiveRootTimer())
+ {
+ return NamedTimerFactory::instance().getRootFrameState();
+ }
+ return getFrameStateList()[mFrameStateIndex];
+}
+
+// static
+LLFastTimer::NamedTimer& LLFastTimer::NamedTimer::getRootNamedTimer()
+{
+ return *NamedTimerFactory::instance().getActiveRootTimer();
+}
+
+std::vector<LLFastTimer::NamedTimer*>::const_iterator LLFastTimer::NamedTimer::beginChildren()
+{
+ return mChildren.begin();
+}
+
+std::vector<LLFastTimer::NamedTimer*>::const_iterator LLFastTimer::NamedTimer::endChildren()
+{
+ return mChildren.end();
+}
+
+std::vector<LLFastTimer::NamedTimer*>& LLFastTimer::NamedTimer::getChildren()
+{
+ return mChildren;
+}
+
+//static
+void LLFastTimer::nextFrame()
+{
+ countsPerSecond(); // good place to calculate clock frequency
+ U64 frame_time = getCPUClockCount64();
+ if ((frame_time - sLastFrameTime) >> 8 > 0xffffffff)
+ {
+ llinfos << "Slow frame, fast timers inaccurate" << llendl;
+ }
+
+ if (sPauseHistory)
+ {
+ sResetHistory = true;
+ }
+ else if (sResetHistory)
+ {
+ sLastFrameIndex = 0;
+ sCurFrameIndex = 0;
+ sResetHistory = false;
+ }
+ else // not paused
+ {
+ NamedTimer::processTimes();
+ sLastFrameIndex = sCurFrameIndex++;
+ }
+
+ // get ready for next frame
+ NamedTimer::resetFrame();
+ sLastFrameTime = frame_time;
+}
+
+//static
+void LLFastTimer::dumpCurTimes()
+{
+ // accumulate timings, etc.
+ NamedTimer::processTimes();
+
+ F64 clock_freq = (F64)countsPerSecond();
+ F64 iclock_freq = 1000.0 / clock_freq; // clock_ticks -> milliseconds
+
+ // walk over timers in depth order and output timings
+ for(timer_tree_dfs_iterator_t it = begin_timer_tree(*NamedTimerFactory::instance().getRootTimer());
+ it != end_timer_tree();
+ ++it)
+ {
+ NamedTimer* timerp = (*it);
+ F64 total_time_ms = ((F64)timerp->getHistoricalCount(0) * iclock_freq);
+ // Don't bother with really brief times, keep output concise
+ if (total_time_ms < 0.1) continue;
+
+ std::ostringstream out_str;
+ for (S32 i = 0; i < timerp->getDepth(); i++)
+ {
+ out_str << "\t";
+ }
+
+
+ out_str << timerp->getName() << " "
+ << std::setprecision(3) << total_time_ms << " ms, "
+ << timerp->getHistoricalCalls(0) << " calls";
+
+ llinfos << out_str.str() << llendl;
+ }
+}
+
+//static
+void LLFastTimer::reset()
+{
+ NamedTimer::reset();
+}
+
+
+//static
+void LLFastTimer::writeLog(std::ostream& os)
+{
+ while (!sLogQueue.empty())
+ {
+ LLSD& sd = sLogQueue.front();
+ LLSDSerialize::toXML(sd, os);
+ LLMutexLock lock(sLogLock);
+ sLogQueue.pop();
+ }
+}
+
+//static
+const LLFastTimer::NamedTimer* LLFastTimer::getTimerByName(const std::string& name)
+{
+ return NamedTimerFactory::instance().getTimerByName(name);
+}
+
+LLFastTimer::LLFastTimer(LLFastTimer::FrameState* state)
+: mFrameState(state)
+{
+ U32 start_time = getCPUClockCount32();
+ mStartTime = start_time;
+ mFrameState->mActiveCount++;
+ LLFastTimer::sCurTimerData.mCurTimer = this;
+ LLFastTimer::sCurTimerData.mFrameState = mFrameState;
+ LLFastTimer::sCurTimerData.mChildTime = 0;
+ mLastTimerData = LLFastTimer::sCurTimerData;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
diff --git a/indra/llcommon/llfasttimer_class.h b/indra/llcommon/llfasttimer_class.h
new file mode 100644
index 0000000000..4cb0c2d04e
--- /dev/null
+++ b/indra/llcommon/llfasttimer_class.h
@@ -0,0 +1,279 @@
+/**
+ * @file llfasttimer_class.h
+ * @brief Declaration of a fast timer.
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_FASTTIMER_CLASS_H
+#define LL_FASTTIMER_CLASS_H
+
+#include "llinstancetracker.h"
+
+#define FAST_TIMER_ON 1
+#define TIME_FAST_TIMERS 0
+
+
+#if LL_WINDOWS
+#define LL_INLINE __forceinline
+#else
+#define LL_INLINE
+#endif // LL_WINDOWS
+
+class LLMutex;
+
+#include <queue>
+#include "llsd.h"
+
+class LL_COMMON_API LLFastTimer
+{
+public:
+ class NamedTimer;
+
+ struct LL_COMMON_API FrameState
+ {
+ FrameState(NamedTimer* timerp);
+
+ U32 mSelfTimeCounter;
+ U32 mCalls;
+ FrameState* mParent; // info for caller timer
+ FrameState* mLastCaller; // used to bootstrap tree construction
+ NamedTimer* mTimer;
+ U16 mActiveCount; // number of timers with this ID active on stack
+ bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame
+ };
+
+ // stores a "named" timer instance to be reused via multiple LLFastTimer stack instances
+ class LL_COMMON_API NamedTimer
+ : public LLInstanceTracker<NamedTimer>
+ {
+ friend class DeclareTimer;
+ public:
+ ~NamedTimer();
+
+ enum { HISTORY_NUM = 60 };
+
+ const std::string& getName() const { return mName; }
+ NamedTimer* getParent() const { return mParent; }
+ void setParent(NamedTimer* parent);
+ S32 getDepth();
+ std::string getToolTip(S32 history_index = -1);
+
+ typedef std::vector<NamedTimer*>::const_iterator child_const_iter;
+ child_const_iter beginChildren();
+ child_const_iter endChildren();
+ std::vector<NamedTimer*>& getChildren();
+
+ void setCollapsed(bool collapsed) { mCollapsed = collapsed; }
+ bool getCollapsed() const { return mCollapsed; }
+
+ U32 getCountAverage() const { return mCountAverage; }
+ U32 getCallAverage() const { return mCallAverage; }
+
+ U32 getHistoricalCount(S32 history_index = 0) const;
+ U32 getHistoricalCalls(S32 history_index = 0) const;
+
+ static NamedTimer& getRootNamedTimer();
+
+ S32 getFrameStateIndex() const { return mFrameStateIndex; }
+
+ FrameState& getFrameState() const;
+
+ private:
+ friend class LLFastTimer;
+ friend class NamedTimerFactory;
+
+ //
+ // methods
+ //
+ NamedTimer(const std::string& name);
+ // recursive call to gather total time from children
+ static void accumulateTimings();
+
+ // updates cumulative times and hierarchy,
+ // can be called multiple times in a frame, at any point
+ static void processTimes();
+
+ static void buildHierarchy();
+ static void resetFrame();
+ static void reset();
+
+ //
+ // members
+ //
+ S32 mFrameStateIndex;
+
+ std::string mName;
+
+ U32 mTotalTimeCounter;
+
+ U32 mCountAverage;
+ U32 mCallAverage;
+
+ U32* mCountHistory;
+ U32* mCallHistory;
+
+ // tree structure
+ NamedTimer* mParent; // NamedTimer of caller(parent)
+ std::vector<NamedTimer*> mChildren;
+ bool mCollapsed; // don't show children
+ bool mNeedsSorting; // sort children whenever child added
+ };
+
+ // used to statically declare a new named timer
+ class LL_COMMON_API DeclareTimer
+ : public LLInstanceTracker<DeclareTimer>
+ {
+ friend class LLFastTimer;
+ public:
+ DeclareTimer(const std::string& name, bool open);
+ DeclareTimer(const std::string& name);
+
+ static void updateCachedPointers();
+
+ private:
+ NamedTimer& mTimer;
+ FrameState* mFrameState;
+ };
+
+public:
+ LLFastTimer(LLFastTimer::FrameState* state);
+
+ LL_INLINE LLFastTimer(LLFastTimer::DeclareTimer& timer)
+ : mFrameState(timer.mFrameState)
+ {
+#if TIME_FAST_TIMERS
+ U64 timer_start = getCPUClockCount64();
+#endif
+#if FAST_TIMER_ON
+ LLFastTimer::FrameState* frame_state = mFrameState;
+ mStartTime = getCPUClockCount32();
+
+ frame_state->mActiveCount++;
+ frame_state->mCalls++;
+ // keep current parent as long as it is active when we are
+ frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0);
+
+ LLFastTimer::CurTimerData* cur_timer_data = &LLFastTimer::sCurTimerData;
+ mLastTimerData = *cur_timer_data;
+ cur_timer_data->mCurTimer = this;
+ cur_timer_data->mFrameState = frame_state;
+ cur_timer_data->mChildTime = 0;
+#endif
+#if TIME_FAST_TIMERS
+ U64 timer_end = getCPUClockCount64();
+ sTimerCycles += timer_end - timer_start;
+#endif
+ }
+
+ LL_INLINE ~LLFastTimer()
+ {
+#if TIME_FAST_TIMERS
+ U64 timer_start = getCPUClockCount64();
+#endif
+#if FAST_TIMER_ON
+ LLFastTimer::FrameState* frame_state = mFrameState;
+ U32 total_time = getCPUClockCount32() - mStartTime;
+
+ frame_state->mSelfTimeCounter += total_time - LLFastTimer::sCurTimerData.mChildTime;
+ frame_state->mActiveCount--;
+
+ // store last caller to bootstrap tree creation
+ // do this in the destructor in case of recursion to get topmost caller
+ frame_state->mLastCaller = mLastTimerData.mFrameState;
+
+ // we are only tracking self time, so subtract our total time delta from parents
+ mLastTimerData.mChildTime += total_time;
+
+ LLFastTimer::sCurTimerData = mLastTimerData;
+#endif
+#if TIME_FAST_TIMERS
+ U64 timer_end = getCPUClockCount64();
+ sTimerCycles += timer_end - timer_start;
+ sTimerCalls++;
+#endif
+ }
+
+public:
+ static LLMutex* sLogLock;
+ static std::queue<LLSD> sLogQueue;
+ static BOOL sLog;
+ static BOOL sMetricLog;
+ static bool sPauseHistory;
+ static bool sResetHistory;
+ static U64 sTimerCycles;
+ static U32 sTimerCalls;
+
+ typedef std::vector<FrameState> info_list_t;
+ static info_list_t& getFrameStateList();
+
+
+ // call this once a frame to reset timers
+ static void nextFrame();
+
+ // dumps current cumulative frame stats to log
+ // call nextFrame() to reset timers
+ static void dumpCurTimes();
+
+ // call this to reset timer hierarchy, averages, etc.
+ static void reset();
+
+ static U64 countsPerSecond();
+ static S32 getLastFrameIndex() { return sLastFrameIndex; }
+ static S32 getCurFrameIndex() { return sCurFrameIndex; }
+
+ static void writeLog(std::ostream& os);
+ static const NamedTimer* getTimerByName(const std::string& name);
+
+ struct CurTimerData
+ {
+ LLFastTimer* mCurTimer;
+ FrameState* mFrameState;
+ U32 mChildTime;
+ };
+ static CurTimerData sCurTimerData;
+
+private:
+ static U32 getCPUClockCount32();
+ static U64 getCPUClockCount64();
+ static U64 sClockResolution;
+
+ static S32 sCurFrameIndex;
+ static S32 sLastFrameIndex;
+ static U64 sLastFrameTime;
+ static info_list_t* sTimerInfos;
+
+ U32 mStartTime;
+ LLFastTimer::FrameState* mFrameState;
+ LLFastTimer::CurTimerData mLastTimerData;
+
+};
+
+typedef class LLFastTimer LLFastTimer;
+
+#endif // LL_LLFASTTIMER_CLASS_H
diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h
index c6092f7b9c..fea5d3ed2b 100644
--- a/indra/llcommon/llfile.h
+++ b/indra/llcommon/llfile.h
@@ -70,7 +70,7 @@ typedef struct stat llstat;
#include "llstring.h" // safe char* -> std::string conversion
-class LLFile
+class LL_COMMON_API LLFile
{
public:
// All these functions take UTF8 path/filenames.
@@ -95,7 +95,7 @@ public:
#if USE_LLFILESTREAMS
-class llifstream : public std::basic_istream < char , std::char_traits < char > >
+class LL_COMMON_API llifstream : public std::basic_istream < char , std::char_traits < char > >
{
// input stream associated with a C stream
public:
@@ -136,7 +136,7 @@ private:
};
-class llofstream : public std::basic_ostream< char , std::char_traits < char > >
+class LL_COMMON_API llofstream : public std::basic_ostream< char , std::char_traits < char > >
{
public:
typedef std::basic_ostream< char , std::char_traits < char > > _Myt;
@@ -185,7 +185,7 @@ private:
//#define llifstream std::ifstream
//#define llofstream std::ofstream
-class llifstream : public std::ifstream
+class LL_COMMON_API llifstream : public std::ifstream
{
public:
llifstream() : std::ifstream()
@@ -203,7 +203,7 @@ public:
};
-class llofstream : public std::ofstream
+class LL_COMMON_API llofstream : public std::ofstream
{
public:
llofstream() : std::ofstream()
@@ -231,7 +231,7 @@ public:
* and should only be used for config files and the like -- not in a
* loop.
*/
-std::streamsize llifstream_size(llifstream& fstr);
-std::streamsize llofstream_size(llofstream& fstr);
+std::streamsize LL_COMMON_API llifstream_size(llifstream& fstr);
+std::streamsize LL_COMMON_API llofstream_size(llofstream& fstr);
#endif // not LL_LLFILE_H
diff --git a/indra/llcommon/llfindlocale.h b/indra/llcommon/llfindlocale.h
index f17c7740f3..b812a065db 100644
--- a/indra/llcommon/llfindlocale.h
+++ b/indra/llcommon/llfindlocale.h
@@ -59,8 +59,8 @@ typedef enum {
/* This allocates/fills in a FL_Locale structure with pointers to
strings (which should be treated as static), or NULL for inappropriate /
undetected fields. */
-FL_Success FL_FindLocale(FL_Locale **locale, FL_Domain domain);
+LL_COMMON_API FL_Success FL_FindLocale(FL_Locale **locale, FL_Domain domain);
/* This should be used to free the struct written by FL_FindLocale */
-void FL_FreeLocale(FL_Locale **locale);
+LL_COMMON_API void FL_FreeLocale(FL_Locale **locale);
#endif /*__findlocale_h_*/
diff --git a/indra/llcommon/llfixedbuffer.cpp b/indra/llcommon/llfixedbuffer.cpp
index e9d6029378..1f6a06c247 100644
--- a/indra/llcommon/llfixedbuffer.cpp
+++ b/indra/llcommon/llfixedbuffer.cpp
@@ -32,20 +32,21 @@
#include "llfixedbuffer.h"
+////////////////////////////////////////////////////////////////////////////
+
LLFixedBuffer::LLFixedBuffer(const U32 max_lines)
- : mMutex(NULL)
+ : LLLineBuffer(),
+ mMaxLines(max_lines),
+ mMutex(NULL)
{
- mMaxLines = max_lines;
mTimer.reset();
}
-
LLFixedBuffer::~LLFixedBuffer()
{
clear();
}
-
void LLFixedBuffer::clear()
{
mMutex.lock() ;
@@ -61,10 +62,10 @@ void LLFixedBuffer::clear()
void LLFixedBuffer::addLine(const std::string& utf8line)
{
LLWString wstring = utf8str_to_wstring(utf8line);
- LLFixedBuffer::addLine(wstring);
+ addWLine(wstring);
}
-void LLFixedBuffer::addLine(const LLWString& line)
+void LLFixedBuffer::addWLine(const LLWString& line)
{
if (line.empty())
{
diff --git a/indra/llcommon/llfixedbuffer.h b/indra/llcommon/llfixedbuffer.h
index 992a024df1..17fdef27d7 100644
--- a/indra/llcommon/llfixedbuffer.h
+++ b/indra/llcommon/llfixedbuffer.h
@@ -38,14 +38,14 @@
#include <string>
#include "llstring.h"
#include "llthread.h"
+#include "llerrorcontrol.h"
-// Fixed size buffer for console output and other things.
-
-class LLFixedBuffer
+// fixed buffer implementation
+class LL_COMMON_API LLFixedBuffer : public LLLineBuffer
{
public:
LLFixedBuffer(const U32 max_lines = 20);
- virtual ~LLFixedBuffer();
+ ~LLFixedBuffer();
LLTimer mTimer;
U32 mMaxLines;
@@ -53,22 +53,18 @@ public:
std::deque<F32> mAddTimes;
std::deque<S32> mLineLengths;
- void clear(); // Clear the buffer, and reset it.
+ /*virtual*/ void clear(); // Clear the buffer, and reset it.
- //do not make these two "virtual"
- void addLine(const std::string& utf8line);
- void addLine(const LLWString& line);
+ /*virtual*/ void addLine(const std::string& utf8line);
- // Get lines currently in the buffer, up to max_size chars, max_length lines
- char *getLines(U32 max_size = 0, U32 max_length = 0);
void setMaxLines(S32 max_lines);
+
protected:
- virtual void removeExtraLines();
+ void removeExtraLines();
+ void addWLine(const LLWString& line);
protected:
LLMutex mMutex ;
};
-const U32 FIXED_BUF_MAX_LINE_LEN = 255; // Not including termnating 0
-
#endif //LL_FIXED_BUFFER_H
diff --git a/indra/llcommon/llfoldertype.cpp b/indra/llcommon/llfoldertype.cpp
new file mode 100644
index 0000000000..2610fe9e6a
--- /dev/null
+++ b/indra/llcommon/llfoldertype.cpp
@@ -0,0 +1,169 @@
+/**
+ * @file llfoldertype.cpp
+ * @brief Implementatino of LLFolderType functionality.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llfoldertype.h"
+#include "lldictionary.h"
+#include "llmemory.h"
+#include "llsingleton.h"
+
+///----------------------------------------------------------------------------
+/// Class LLFolderType
+///----------------------------------------------------------------------------
+struct FolderEntry : public LLDictionaryEntry
+{
+ FolderEntry(const std::string &type_name, // 8 character limit!
+ bool is_protected) // can the viewer change categories of this type?
+ :
+ LLDictionaryEntry(type_name),
+ mIsProtected(is_protected)
+ {
+ llassert(type_name.length() <= 8);
+ }
+
+ const bool mIsProtected;
+};
+
+class LLFolderDictionary : public LLSingleton<LLFolderDictionary>,
+ public LLDictionary<LLFolderType::EType, FolderEntry>
+{
+public:
+ LLFolderDictionary();
+protected:
+ virtual LLFolderType::EType notFound() const
+ {
+ return LLFolderType::FT_NONE;
+ }
+};
+
+LLFolderDictionary::LLFolderDictionary()
+{
+ // TYPE NAME PROTECTED
+ // |-----------|---------|
+ addEntry(LLFolderType::FT_TEXTURE, new FolderEntry("texture", TRUE));
+ addEntry(LLFolderType::FT_SOUND, new FolderEntry("sound", TRUE));
+ addEntry(LLFolderType::FT_CALLINGCARD, new FolderEntry("callcard", TRUE));
+ addEntry(LLFolderType::FT_LANDMARK, new FolderEntry("landmark", TRUE));
+ addEntry(LLFolderType::FT_CLOTHING, new FolderEntry("clothing", TRUE));
+ addEntry(LLFolderType::FT_OBJECT, new FolderEntry("object", TRUE));
+ addEntry(LLFolderType::FT_NOTECARD, new FolderEntry("notecard", TRUE));
+ addEntry(LLFolderType::FT_ROOT_INVENTORY, new FolderEntry("root_inv", TRUE));
+ addEntry(LLFolderType::FT_LSL_TEXT, new FolderEntry("lsltext", TRUE));
+ addEntry(LLFolderType::FT_BODYPART, new FolderEntry("bodypart", TRUE));
+ addEntry(LLFolderType::FT_TRASH, new FolderEntry("trash", TRUE));
+ addEntry(LLFolderType::FT_SNAPSHOT_CATEGORY, new FolderEntry("snapshot", TRUE));
+ addEntry(LLFolderType::FT_LOST_AND_FOUND, new FolderEntry("lstndfnd", TRUE));
+ addEntry(LLFolderType::FT_ANIMATION, new FolderEntry("animatn", TRUE));
+ addEntry(LLFolderType::FT_GESTURE, new FolderEntry("gesture", TRUE));
+ addEntry(LLFolderType::FT_FAVORITE, new FolderEntry("favorite", TRUE));
+
+ for (S32 ensemble_num = S32(LLFolderType::FT_ENSEMBLE_START); ensemble_num <= S32(LLFolderType::FT_ENSEMBLE_END); ensemble_num++)
+ {
+ addEntry(LLFolderType::EType(ensemble_num), new FolderEntry("ensemble", FALSE));
+ }
+
+ addEntry(LLFolderType::FT_CURRENT_OUTFIT, new FolderEntry("current", TRUE));
+ addEntry(LLFolderType::FT_OUTFIT, new FolderEntry("outfit", FALSE));
+ addEntry(LLFolderType::FT_MY_OUTFITS, new FolderEntry("my_otfts", TRUE));
+ addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", TRUE));
+
+ addEntry(LLFolderType::FT_NONE, new FolderEntry("-1", FALSE));
+};
+
+// static
+LLFolderType::EType LLFolderType::lookup(const std::string& name)
+{
+ return LLFolderDictionary::getInstance()->lookup(name);
+}
+
+// static
+const std::string &LLFolderType::lookup(LLFolderType::EType folder_type)
+{
+ const FolderEntry *entry = LLFolderDictionary::getInstance()->lookup(folder_type);
+ if (entry)
+ {
+ return entry->mName;
+ }
+ else
+ {
+ return badLookup();
+ }
+}
+
+// static
+// Only ensembles and plain folders aren't protected. "Protected" means
+// you can't change certain properties such as their type.
+bool LLFolderType::lookupIsProtectedType(EType folder_type)
+{
+ const LLFolderDictionary *dict = LLFolderDictionary::getInstance();
+ const FolderEntry *entry = dict->lookup(folder_type);
+ if (entry)
+ {
+ return entry->mIsProtected;
+ }
+ return true;
+}
+
+// static
+bool LLFolderType::lookupIsEnsembleType(EType folder_type)
+{
+ return (folder_type >= FT_ENSEMBLE_START &&
+ folder_type <= FT_ENSEMBLE_END);
+}
+
+// static
+LLAssetType::EType LLFolderType::folderTypeToAssetType(LLFolderType::EType folder_type)
+{
+ if (LLAssetType::lookup(LLAssetType::EType(folder_type)) == LLAssetType::badLookup())
+ {
+ llwarns << "Converting to unknown asset type " << folder_type << llendl;
+ }
+ return (LLAssetType::EType)folder_type;
+}
+
+// static
+LLFolderType::EType LLFolderType::assetTypeToFolderType(LLAssetType::EType asset_type)
+{
+ if (LLFolderType::lookup(LLFolderType::EType(asset_type)) == LLFolderType::badLookup())
+ {
+ llwarns << "Converting to unknown folder type " << asset_type << llendl;
+ }
+ return (LLFolderType::EType)asset_type;
+}
+
+// static
+const std::string &LLFolderType::badLookup()
+{
+ static const std::string sBadLookup = "llfoldertype_bad_lookup";
+ return sBadLookup;
+}
diff --git a/indra/llcommon/llfoldertype.h b/indra/llcommon/llfoldertype.h
new file mode 100644
index 0000000000..7aa77f7f7e
--- /dev/null
+++ b/indra/llcommon/llfoldertype.h
@@ -0,0 +1,112 @@
+/**
+ * @file llfoldertype.h
+ * @brief Declaration of LLFolderType.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFOLDERTYPE_H
+#define LL_LLFOLDERTYPE_H
+
+#include <string>
+#include "llassettype.h"
+
+// This class handles folder types (similar to assettype, except for folders)
+// and operations on those.
+class LL_COMMON_API LLFolderType
+{
+public:
+ // ! BACKWARDS COMPATIBILITY ! Folder type enums must match asset type enums.
+ enum EType
+ {
+ FT_TEXTURE = 0,
+
+ FT_SOUND = 1,
+
+ FT_CALLINGCARD = 2,
+
+ FT_LANDMARK = 3,
+
+ FT_CLOTHING = 5,
+
+ FT_OBJECT = 6,
+
+ FT_NOTECARD = 7,
+
+ FT_ROOT_INVENTORY = 8,
+ // We'd really like to change this to 9 since AT_CATEGORY is 8,
+ // but "My Inventory" has been type 8 for a long time.
+
+ FT_LSL_TEXT = 10,
+
+ FT_BODYPART = 13,
+
+ FT_TRASH = 14,
+
+ FT_SNAPSHOT_CATEGORY = 15,
+
+ FT_LOST_AND_FOUND = 16,
+
+ FT_ANIMATION = 20,
+
+ FT_GESTURE = 21,
+
+ FT_FAVORITE = 23,
+
+ FT_ENSEMBLE_START = 26,
+ FT_ENSEMBLE_END = 45,
+ // This range is reserved for special clothing folder types.
+
+ FT_CURRENT_OUTFIT = 46,
+ FT_OUTFIT = 47,
+ FT_MY_OUTFITS = 48,
+
+ FT_INBOX = 49,
+
+ FT_COUNT = 50,
+
+ FT_NONE = -1
+ };
+
+ static EType lookup(const std::string& type_name);
+ static const std::string& lookup(EType folder_type);
+
+ static bool lookupIsProtectedType(EType folder_type);
+ static bool lookupIsEnsembleType(EType folder_type);
+
+ static LLAssetType::EType folderTypeToAssetType(LLFolderType::EType folder_type);
+ static LLFolderType::EType assetTypeToFolderType(LLAssetType::EType asset_type);
+
+ static const std::string& badLookup(); // error string when a lookup fails
+
+protected:
+ LLFolderType() {}
+ ~LLFolderType() {}
+};
+
+#endif // LL_LLFOLDERTYPE_H
diff --git a/indra/llcommon/llformat.h b/indra/llcommon/llformat.h
index 44c62d9710..dc64edb26d 100644
--- a/indra/llcommon/llformat.h
+++ b/indra/llcommon/llformat.h
@@ -40,6 +40,6 @@
// *NOTE: buffer limited to 1024, (but vsnprintf prevents overrun)
// should perhaps be replaced with boost::format.
-std::string llformat(const char *fmt, ...);
+std::string LL_COMMON_API llformat(const char *fmt, ...);
#endif // LL_LLFORMAT_H
diff --git a/indra/llcommon/llframetimer.h b/indra/llcommon/llframetimer.h
index 8f51272af2..be2d9b0703 100644
--- a/indra/llcommon/llframetimer.h
+++ b/indra/llcommon/llframetimer.h
@@ -43,7 +43,7 @@
#include "lltimer.h"
#include "timing.h"
-class LLFrameTimer
+class LL_COMMON_API LLFrameTimer
{
public:
LLFrameTimer() : mStartTime( sFrameTime ), mExpiry(0), mStarted(TRUE) {}
diff --git a/indra/llcommon/llheartbeat.h b/indra/llcommon/llheartbeat.h
index fecb5b1e54..6f7026970f 100644
--- a/indra/llcommon/llheartbeat.h
+++ b/indra/llcommon/llheartbeat.h
@@ -40,7 +40,7 @@
// Note: Win32 does not support the heartbeat/smackdown system;
// heartbeat-delivery turns into a no-op there.
-class LLHeartbeat
+class LL_COMMON_API LLHeartbeat
{
public:
// secs_between_heartbeat: after a heartbeat is successfully delivered,
diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
new file mode 100644
index 0000000000..11fe523651
--- /dev/null
+++ b/indra/llcommon/llinstancetracker.h
@@ -0,0 +1,159 @@
+/**
+ * @file llinstancetracker.h
+ * @brief LLInstanceTracker is a mixin class that automatically tracks object
+ * instances with or without an associated key
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLINSTANCETRACKER_H
+#define LL_LLINSTANCETRACKER_H
+
+#include <map>
+
+#include "string_table.h"
+#include <boost/utility.hpp>
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
+#include <boost/iterator/transform_iterator.hpp>
+#include <boost/iterator/indirect_iterator.hpp>
+
+/// This mix-in class adds support for tracking all instances of the specified class parameter T
+/// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup
+/// If KEY is not provided, then instances are stored in a simple set
+/// @NOTE: see explicit specialization below for default KEY==T* case
+template<typename T, typename KEY = T*>
+class LLInstanceTracker : boost::noncopyable
+{
+ typedef typename std::map<KEY, T*> InstanceMap;
+ typedef boost::function<const KEY&(typename InstanceMap::value_type&)> KeyGetter;
+ typedef boost::function<T*(typename InstanceMap::value_type&)> InstancePtrGetter;
+public:
+ /// Dereferencing key_iter gives you a const KEY&
+ typedef boost::transform_iterator<KeyGetter, typename InstanceMap::iterator> key_iter;
+ /// Dereferencing instance_iter gives you a T&
+ typedef boost::indirect_iterator< boost::transform_iterator<InstancePtrGetter, typename InstanceMap::iterator> > instance_iter;
+
+ static T* getInstance(const KEY& k)
+ {
+ typename InstanceMap::const_iterator found = getMap_().find(k);
+ return (found == getMap_().end()) ? NULL : found->second;
+ }
+
+ static key_iter beginKeys()
+ {
+ return boost::make_transform_iterator(getMap_().begin(),
+ boost::bind(&InstanceMap::value_type::first, _1));
+ }
+ static key_iter endKeys()
+ {
+ return boost::make_transform_iterator(getMap_().end(),
+ boost::bind(&InstanceMap::value_type::first, _1));
+ }
+ static instance_iter beginInstances()
+ {
+ return instance_iter(boost::make_transform_iterator(getMap_().begin(),
+ boost::bind(&InstanceMap::value_type::second, _1)));
+ }
+ static instance_iter endInstances()
+ {
+ return instance_iter(boost::make_transform_iterator(getMap_().end(),
+ boost::bind(&InstanceMap::value_type::second, _1)));
+ }
+ static S32 instanceCount() { return getMap_().size(); }
+protected:
+ LLInstanceTracker(KEY key) { add_(key); }
+ virtual ~LLInstanceTracker() { remove_(); }
+ virtual void setKey(KEY key) { remove_(); add_(key); }
+ virtual const KEY& getKey() const { return mKey; }
+
+private:
+ void add_(KEY key)
+ {
+ mKey = key;
+ getMap_()[key] = static_cast<T*>(this);
+ }
+ void remove_() { getMap_().erase(mKey); }
+
+ static InstanceMap& getMap_()
+ {
+ if (! sInstances)
+ {
+ sInstances = new InstanceMap;
+ }
+ return *sInstances;
+ }
+
+private:
+
+ KEY mKey;
+ static InstanceMap* sInstances;
+};
+
+/// explicit specialization for default case where KEY is T*
+/// use a simple std::set<T*>
+template<typename T>
+class LLInstanceTracker<T, T*>
+{
+ typedef typename std::set<T*> InstanceSet;
+public:
+ /// Dereferencing key_iter gives you a T* (since T* is the key)
+ typedef typename InstanceSet::iterator key_iter;
+ /// Dereferencing instance_iter gives you a T&
+ typedef boost::indirect_iterator<key_iter> instance_iter;
+
+ /// for completeness of analogy with the generic implementation
+ static T* getInstance(T* k) { return k; }
+ static key_iter beginKeys() { return getSet_().begin(); }
+ static key_iter endKeys() { return getSet_().end(); }
+ static instance_iter beginInstances() { return instance_iter(getSet_().begin()); }
+ static instance_iter endInstances() { return instance_iter(getSet_().end()); }
+ static S32 instanceCount() { return getSet_().size(); }
+
+protected:
+ LLInstanceTracker() { getSet_().insert(static_cast<T*>(this)); }
+ virtual ~LLInstanceTracker() { getSet_().erase(static_cast<T*>(this)); }
+
+ LLInstanceTracker(const LLInstanceTracker& other) { getSet_().insert(static_cast<T*>(this)); }
+
+ static InstanceSet& getSet_() // called after getReady() but before go()
+ {
+ if (! sInstances)
+ {
+ sInstances = new InstanceSet;
+ }
+ return *sInstances;
+ }
+
+ static InstanceSet* sInstances;
+};
+
+template <typename T, typename KEY> typename LLInstanceTracker<T, KEY>::InstanceMap* LLInstanceTracker<T, KEY>::sInstances = NULL;
+template <typename T> typename LLInstanceTracker<T, T*>::InstanceSet* LLInstanceTracker<T, T*>::sInstances = NULL;
+
+#endif
diff --git a/indra/llcommon/llkeythrottle.h b/indra/llcommon/llkeythrottle.h
index 873f50a65e..7544ab1d11 100644
--- a/indra/llcommon/llkeythrottle.h
+++ b/indra/llcommon/llkeythrottle.h
@@ -118,6 +118,63 @@ public:
THROTTLE_BLOCKED, // rate exceed, block key
};
+ F64 getActionCount(const T& id)
+ {
+ U64 now = 0;
+ if ( mIsRealtime )
+ {
+ now = LLKeyThrottleImpl<T>::getTime();
+ }
+ else
+ {
+ now = LLKeyThrottleImpl<T>::getFrame();
+ }
+
+ if (now >= (m.startTime + m.intervalLength))
+ {
+ if (now < (m.startTime + 2 * m.intervalLength))
+ {
+ // prune old data
+ delete m.prevMap;
+ m.prevMap = m.currMap;
+ m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+
+ m.startTime += m.intervalLength;
+ }
+ else
+ {
+ // lots of time has passed, all data is stale
+ delete m.prevMap;
+ delete m.currMap;
+ m.prevMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+ m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+
+ m.startTime = now;
+ }
+ }
+
+ U32 prevCount = 0;
+
+ typename LLKeyThrottleImpl<T>::EntryMap::const_iterator prev = m.prevMap->find(id);
+ if (prev != m.prevMap->end())
+ {
+ prevCount = prev->second.count;
+ }
+
+ typename LLKeyThrottleImpl<T>::Entry& curr = (*m.currMap)[id];
+
+ // curr.count is the number of keys in
+ // this current 'time slice' from the beginning of it until now
+ // prevCount is the number of keys in the previous
+ // time slice scaled to be one full time slice back from the current
+ // (now) time.
+
+ // compute current, windowed rate
+ F64 timeInCurrent = ((F64)(now - m.startTime) / m.intervalLength);
+ F64 averageCount = curr.count + prevCount * (1.0 - timeInCurrent);
+ return averageCount;
+ }
+
// call each time the key wants use
State noteAction(const T& id, S32 weight = 1)
{
diff --git a/indra/llcommon/lllazy.cpp b/indra/llcommon/lllazy.cpp
new file mode 100644
index 0000000000..215095bc27
--- /dev/null
+++ b/indra/llcommon/lllazy.cpp
@@ -0,0 +1,23 @@
+/**
+ * @file lllazy.cpp
+ * @author Nat Goodspeed
+ * @date 2009-01-28
+ * @brief Implementation for lllazy.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "lllazy.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+
+// lllazy.h is presently header-only. This file exists only because our CMake
+// test macro ADD_BUILD_TEST requires it.
+int dummy = 0;
diff --git a/indra/llcommon/lllazy.h b/indra/llcommon/lllazy.h
new file mode 100644
index 0000000000..2240954d98
--- /dev/null
+++ b/indra/llcommon/lllazy.h
@@ -0,0 +1,382 @@
+/**
+ * @file lllazy.h
+ * @author Nat Goodspeed
+ * @date 2009-01-22
+ * @brief Lazy instantiation of specified type. Useful in conjunction with
+ * Michael Feathers's "Extract and Override Getter" ("Working
+ * Effectively with Legacy Code", p. 352).
+ *
+ * Quoting his synopsis of steps on p.355:
+ *
+ * 1. Identify the object you need a getter for.
+ * 2. Extract all of the logic needed to create the object into a getter.
+ * 3. Replace all uses of the object with calls to the getter, and initialize
+ * the reference that holds the object to null in all constructors.
+ * 4. Add the first-time logic to the getter so that the object is constructed
+ * and assigned to the reference whenever the reference is null.
+ * 5. Subclass the class and override the getter to provide an alternative
+ * object for testing.
+ *
+ * It's the second half of bullet 3 (3b, as it were) that bothers me. I find
+ * it all too easy to imagine adding pointer initializers to all but one
+ * constructor... the one not exercised by my tests. That suggested using
+ * (e.g.) boost::scoped_ptr<MyObject> so you don't have to worry about
+ * destroying it either.
+ *
+ * However, introducing additional machinery allows us to encapsulate bullet 4
+ * as well.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLLAZY_H)
+#define LL_LLLAZY_H
+
+#include <boost/function.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/lambda/construct.hpp>
+#include <stdexcept>
+
+/// LLLazyCommon simply factors out of LLLazy<T> things that don't depend on
+/// its template parameter.
+class LLLazyCommon
+{
+public:
+ /**
+ * This exception is thrown if you try to replace an LLLazy<T>'s factory
+ * (or T* instance) after it already has an instance in hand. Since T
+ * might well be stateful, we can't know the effect of silently discarding
+ * and replacing an existing instance, so we disallow it. This facility is
+ * intended for testing, and in a test scenario we can definitely control
+ * that.
+ */
+ struct InstanceChange: public std::runtime_error
+ {
+ InstanceChange(const std::string& what): std::runtime_error(what) {}
+ };
+
+protected:
+ /**
+ * InstanceChange might be appropriate in a couple of different LLLazy<T>
+ * methods. Factor out the common logic.
+ */
+ template <typename PTR>
+ static void ensureNoInstance(const PTR& ptr)
+ {
+ if (ptr)
+ {
+ // Too late: we've already instantiated the lazy object. We don't
+ // know whether it's stateful or not, so it's not safe to discard
+ // the existing instance in favor of a replacement.
+ throw InstanceChange("Too late to replace LLLazy instance");
+ }
+ }
+};
+
+/**
+ * LLLazy<T> is useful when you have an outer class Outer that you're trying
+ * to bring under unit test, that contains a data member difficult to
+ * instantiate in a test harness. Typically the data member's class Inner has
+ * many thorny dependencies. Feathers generally advocates "Extract and
+ * Override Factory Method" (p. 350). But in C++, you can't call a derived
+ * class override of a virtual method from the derived class constructor,
+ * which limits applicability of "Extract and Override Factory Method." For
+ * such cases Feathers presents "Extract and Override Getter" (p. 352).
+ *
+ * So we'll assume that your class Outer contains a member like this:
+ * @code
+ * Inner mInner;
+ * @endcode
+ *
+ * LLLazy<Inner> can be used to replace this member. You can directly declare:
+ * @code
+ * LLLazy<Inner> mInner;
+ * @endcode
+ * and change references to mInner accordingly.
+ *
+ * (Alternatively, you can add a base class of the form
+ * <tt>LLLazyBase<Inner></tt>. This is discussed further in the LLLazyBase<T>
+ * documentation.)
+ *
+ * LLLazy<T> binds a <tt>boost::scoped_ptr<T></tt> and a factory functor
+ * returning T*. You can either bind that functor explicitly or let it default
+ * to the expression <tt>new T()</tt>.
+ *
+ * As long as LLLazy<T> remains unreferenced, its T remains uninstantiated.
+ * The first time you use get(), <tt>operator*()</tt> or <tt>operator->()</tt>
+ * it will instantiate its T and thereafter behave like a pointer to it.
+ *
+ * Thus, any existing reference to <tt>mInner.member</tt> should be replaced
+ * with <tt>mInner->member</tt>. Any simple reference to @c mInner should be
+ * replaced by <tt>*mInner</tt>.
+ *
+ * (If the original declaration was a pointer initialized in Outer's
+ * constructor, e.g. <tt>Inner* mInner</tt>, so much the better. In that case
+ * you should be able to drop in <tt>LLLazy<Inner></tt> without much change.)
+ *
+ * The support for "Extract and Override Getter" lies in the fact that you can
+ * replace the factory functor -- or provide an explicit T*. Presumably this
+ * is most useful from a test subclass -- which suggests that your @c mInner
+ * member should be @c protected.
+ *
+ * Note that <tt>boost::lambda::new_ptr<T>()</tt> makes a dandy factory
+ * functor, for either the set() method or LLLazy<T>'s constructor. If your T
+ * requires constructor arguments, use an expression more like
+ * <tt>boost::lambda::bind(boost::lambda::new_ptr<T>(), arg1, arg2, ...)</tt>.
+ *
+ * Of course the point of replacing the functor is to substitute a class that,
+ * though referenced as Inner*, is not an Inner; presumably this is a testing
+ * subclass of Inner (e.g. TestInner). Thus your test subclass TestOuter for
+ * the containing class Outer will contain something like this:
+ * @code
+ * class TestOuter: public Outer
+ * {
+ * public:
+ * TestOuter()
+ * {
+ * // mInner must be 'protected' rather than 'private'
+ * mInner.set(boost::lambda::new_ptr<TestInner>());
+ * }
+ * ...
+ * };
+ * @endcode
+ */
+template <typename T>
+class LLLazy: public LLLazyCommon
+{
+public:
+ /// Any nullary functor returning T* will work as a Factory
+ typedef boost::function<T* ()> Factory;
+
+ /// The default LLLazy constructor uses <tt>new T()</tt> as its Factory
+ LLLazy():
+ mFactory(boost::lambda::new_ptr<T>())
+ {}
+
+ /// Bind an explicit Factory functor
+ LLLazy(const Factory& factory):
+ mFactory(factory)
+ {}
+
+ /// Reference T, instantiating it if this is the first access
+ const T& get() const
+ {
+ if (! mInstance)
+ {
+ // use the bound Factory functor
+ mInstance.reset(mFactory());
+ }
+ return *mInstance;
+ }
+
+ /// non-const get()
+ T& get()
+ {
+ return const_cast<T&>(const_cast<const LLLazy<T>*>(this)->get());
+ }
+
+ /// operator*() is equivalent to get()
+ const T& operator*() const { return get(); }
+ /// operator*() is equivalent to get()
+ T& operator*() { return get(); }
+
+ /**
+ * operator->() must return (something resembling) T*. It's tempting to
+ * return the underlying boost::scoped_ptr<T>, but that would require
+ * breaking out the lazy-instantiation logic from get() into a common
+ * private method. Assume the pointer used for operator->() access is very
+ * short-lived.
+ */
+ const T* operator->() const { return &get(); }
+ /// non-const operator->()
+ T* operator->() { return &get(); }
+
+ /// set(Factory). This will throw InstanceChange if mInstance has already
+ /// been set.
+ void set(const Factory& factory)
+ {
+ ensureNoInstance(mInstance);
+ mFactory = factory;
+ }
+
+ /// set(T*). This will throw InstanceChange if mInstance has already been
+ /// set.
+ void set(T* instance)
+ {
+ ensureNoInstance(mInstance);
+ mInstance.reset(instance);
+ }
+
+private:
+ Factory mFactory;
+ // Consider an LLLazy<T> member of a class we're accessing by const
+ // reference. We want to allow even const methods to touch the LLLazy<T>
+ // member. Hence the actual pointer must be mutable because such access
+ // might assign it.
+ mutable boost::scoped_ptr<T> mInstance;
+};
+
+#if (! defined(__GNUC__)) || (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)
+// Not gcc at all, or a gcc more recent than gcc 3.3
+#define GCC33 0
+#else
+#define GCC33 1
+#endif
+
+/**
+ * LLLazyBase<T> wraps LLLazy<T>, giving you an alternative way to replace
+ * <tt>Inner mInner;</tt>. Instead of coding <tt>LLLazy<Inner> mInner</tt>,
+ * you can add LLLazyBase<Inner> to your Outer class's bases, e.g.:
+ * @code
+ * class Outer: public LLLazyBase<Inner>
+ * {
+ * ...
+ * };
+ * @endcode
+ *
+ * This gives you @c public get() and @c protected set() methods without
+ * having to make your LLLazy<Inner> member @c protected. The tradeoff is that
+ * you must access the wrapped LLLazy<Inner> using get() and set() rather than
+ * with <tt>operator*()</tt> or <tt>operator->()</tt>.
+ *
+ * This mechanism can be used for more than one member, but only if they're of
+ * different types. That is, you can replace:
+ * @code
+ * DifficultClass mDifficult;
+ * AwkwardType mAwkward;
+ * @endcode
+ * with:
+ * @code
+ * class Outer: public LLLazyBase<DifficultClass>, public LLLazyBase<AwkwardType>
+ * {
+ * ...
+ * };
+ * @endcode
+ * but for a situation like this:
+ * @code
+ * DifficultClass mMainDifficult, mAuxDifficult;
+ * @endcode
+ * you should directly embed LLLazy<DifficultClass> (q.v.).
+ *
+ * For multiple LLLazyBase bases, e.g. the <tt>LLLazyBase<DifficultClass>,
+ * LLLazyBase<AwkwardType></tt> example above, access the relevant get()/set()
+ * as (e.g.) <tt>LLLazyBase<DifficultClass>::get()</tt>. (This is why you
+ * can't have multiple LLLazyBase<T> of the same T.) For a bit of syntactic
+ * sugar, please see getLazy()/setLazy().
+ */
+template <typename T>
+class LLLazyBase
+{
+public:
+ /// invoke default LLLazy constructor
+ LLLazyBase() {}
+ /// make wrapped LLLazy bind an explicit Factory
+ LLLazyBase(const typename LLLazy<T>::Factory& factory):
+ mInstance(factory)
+ {}
+
+ /// access to LLLazy::get()
+ T& get() { return *mInstance; }
+ /// access to LLLazy::get()
+ const T& get() const { return *mInstance; }
+
+protected:
+ // see getLazy()/setLazy()
+ #if (! GCC33)
+ template <typename T2, class MYCLASS> friend T2& getLazy(MYCLASS* this_);
+ template <typename T2, class MYCLASS> friend const T2& getLazy(const MYCLASS* this_);
+ #else // gcc 3.3
+ template <typename T2, class MYCLASS> friend T2& getLazy(const MYCLASS* this_);
+ #endif // gcc 3.3
+ template <typename T2, class MYCLASS> friend void setLazy(MYCLASS* this_, T2* instance);
+ template <typename T2, class MYCLASS>
+ friend void setLazy(MYCLASS* this_, const typename LLLazy<T2>::Factory& factory);
+
+ /// access to LLLazy::set(Factory)
+ void set(const typename LLLazy<T>::Factory& factory)
+ {
+ mInstance.set(factory);
+ }
+
+ /// access to LLLazy::set(T*)
+ void set(T* instance)
+ {
+ mInstance.set(instance);
+ }
+
+private:
+ LLLazy<T> mInstance;
+};
+
+/**
+ * @name getLazy()/setLazy()
+ * Suppose you have something like the following:
+ * @code
+ * class Outer: public LLLazyBase<DifficultClass>, public LLLazyBase<AwkwardType>
+ * {
+ * ...
+ * };
+ * @endcode
+ *
+ * Your methods can reference the @c DifficultClass instance using
+ * <tt>LLLazyBase<DifficultClass>::get()</tt>, which is admittedly a bit ugly.
+ * Alternatively, you can write <tt>getLazy<DifficultClass>(this)</tt>, which
+ * is somewhat more straightforward to read.
+ *
+ * Similarly,
+ * @code
+ * LLLazyBase<DifficultClass>::set(new TestDifficultClass());
+ * @endcode
+ * could instead be written:
+ * @code
+ * setLazy<DifficultClass>(this, new TestDifficultClass());
+ * @endcode
+ *
+ * @note
+ * I wanted to provide getLazy() and setLazy() without explicitly passing @c
+ * this. That would imply making them methods on a base class rather than free
+ * functions. But if <tt>LLLazyBase<T></tt> derives normally from (say) @c
+ * LLLazyGrandBase providing those methods, then unqualified getLazy() would
+ * be ambiguous: you'd have to write <tt>LLLazyBase<T>::getLazy<T>()</tt>,
+ * which is even uglier than <tt>LLLazyBase<T>::get()</tt>, and therefore
+ * pointless. You can make the compiler not care which @c LLLazyGrandBase
+ * instance you're talking about by making @c LLLazyGrandBase a @c virtual
+ * base class of @c LLLazyBase. But in that case,
+ * <tt>LLLazyGrandBase::getLazy<T>()</tt> can't access
+ * <tt>LLLazyBase<T>::get()</tt>!
+ *
+ * We want <tt>getLazy<T>()</tt> to access <tt>LLLazyBase<T>::get()</tt> as if
+ * in the lexical context of some subclass method. Ironically, free functions
+ * let us do that better than methods on a @c virtual base class -- but that
+ * implies passing @c this explicitly. So be it.
+ */
+//@{
+#if (! GCC33)
+template <typename T, class MYCLASS>
+T& getLazy(MYCLASS* this_) { return this_->LLLazyBase<T>::get(); }
+template <typename T, class MYCLASS>
+const T& getLazy(const MYCLASS* this_) { return this_->LLLazyBase<T>::get(); }
+#else // gcc 3.3
+// For const-correctness, we really should have two getLazy() variants: one
+// accepting const MYCLASS* and returning const T&, the other accepting
+// non-const MYCLASS* and returning non-const T&. This works fine on the Mac
+// (gcc 4.0.1) and Windows (MSVC 8.0), but fails on our Linux 32-bit Debian
+// Sarge stations (gcc 3.3.5). Since I really don't know how to beat that aging
+// compiler over the head to make it do the right thing, I'm going to have to
+// move forward with the wrong thing: a single getLazy() function that accepts
+// const MYCLASS* and returns non-const T&.
+template <typename T, class MYCLASS>
+T& getLazy(const MYCLASS* this_) { return const_cast<MYCLASS*>(this_)->LLLazyBase<T>::get(); }
+#endif // gcc 3.3
+template <typename T, class MYCLASS>
+void setLazy(MYCLASS* this_, T* instance) { this_->LLLazyBase<T>::set(instance); }
+template <typename T, class MYCLASS>
+void setLazy(MYCLASS* this_, const typename LLLazy<T>::Factory& factory)
+{
+ this_->LLLazyBase<T>::set(factory);
+}
+//@}
+
+#endif /* ! defined(LL_LLLAZY_H) */
diff --git a/indra/llcommon/lllistenerwrapper.h b/indra/llcommon/lllistenerwrapper.h
new file mode 100644
index 0000000000..2f747fb182
--- /dev/null
+++ b/indra/llcommon/lllistenerwrapper.h
@@ -0,0 +1,181 @@
+/**
+ * @file lllistenerwrapper.h
+ * @author Nat Goodspeed
+ * @date 2009-11-30
+ * @brief Introduce LLListenerWrapper template
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLLISTENERWRAPPER_H)
+#define LL_LLLISTENERWRAPPER_H
+
+#include "llevents.h" // LLListenerWrapperBase
+#include <boost/visit_each.hpp>
+
+/**
+ * Template base class for coding wrappers for LLEventPump listeners.
+ *
+ * Derive your listener wrapper from LLListenerWrapper. You must use
+ * LLLISTENER_WRAPPER_SUBCLASS() so your subclass will play nicely with
+ * boost::visit_each (q.v.). That way boost::signals2 can still detect
+ * derivation from LLEventTrackable, and so forth.
+ */
+template <typename LISTENER>
+class LLListenerWrapper: public LLListenerWrapperBase
+{
+public:
+ /// Wrap an arbitrary listener object
+ LLListenerWrapper(const LISTENER& listener):
+ mListener(listener)
+ {}
+
+ /// call
+ virtual bool operator()(const LLSD& event)
+ {
+ return mListener(event);
+ }
+
+ /// Allow boost::visit_each() to peek at our mListener.
+ template <class V>
+ void accept_visitor(V& visitor) const
+ {
+ using boost::visit_each;
+ visit_each(visitor, mListener, 0);
+ }
+
+private:
+ LISTENER mListener;
+};
+
+/**
+ * Specialize boost::visit_each() (leveraging ADL) to peek inside an
+ * LLListenerWrapper<T> to traverse its LISTENER. We borrow the
+ * accept_visitor() pattern from boost::bind(), avoiding the need to make
+ * mListener public.
+ */
+template <class V, typename T>
+void visit_each(V& visitor, const LLListenerWrapper<T>& wrapper, int)
+{
+ wrapper.accept_visitor(visitor);
+}
+
+/// use this (sigh!) for each subclass of LLListenerWrapper<T> you write
+#define LLLISTENER_WRAPPER_SUBCLASS(CLASS) \
+template <class V, typename T> \
+void visit_each(V& visitor, const CLASS<T>& wrapper, int) \
+{ \
+ visit_each(visitor, static_cast<const LLListenerWrapper<T>&>(wrapper), 0); \
+} \
+ \
+/* Have to state this explicitly, rather than using LL_TEMPLATE_CONVERTIBLE, */ \
+/* because the source type is itself a template. */ \
+template <typename T> \
+struct ll_template_cast_impl<const LLListenerWrapperBase*, const CLASS<T>*> \
+{ \
+ const LLListenerWrapperBase* operator()(const CLASS<T>* wrapper) \
+ { \
+ return wrapper; \
+ } \
+}
+
+/**
+ * Make an instance of a listener wrapper. Every wrapper class must be a
+ * template accepting a listener object of arbitrary type. In particular, the
+ * type of a boost::bind() expression is deliberately undocumented. So we
+ * can't just write Wrapper<CorrectType>(boost::bind(...)). Instead we must
+ * write llwrap<Wrapper>(boost::bind(...)).
+ */
+template <template<typename> class WRAPPER, typename T>
+WRAPPER<T> llwrap(const T& listener)
+{
+ return WRAPPER<T>(listener);
+}
+
+/**
+ * This LLListenerWrapper template subclass is used to report entry/exit to an
+ * event listener, by changing this:
+ * @code
+ * someEventPump.listen("MyClass",
+ * boost::bind(&MyClass::method, ptr, _1));
+ * @endcode
+ * to this:
+ * @code
+ * someEventPump.listen("MyClass",
+ * llwrap<LLCoutListener>(
+ * boost::bind(&MyClass::method, ptr, _1)));
+ * @endcode
+ */
+template <class LISTENER>
+class LLCoutListener: public LLListenerWrapper<LISTENER>
+{
+ typedef LLListenerWrapper<LISTENER> super;
+
+public:
+ /// Wrap an arbitrary listener object
+ LLCoutListener(const LISTENER& listener):
+ super(listener)
+ {}
+
+ /// call
+ virtual bool operator()(const LLSD& event)
+ {
+ std::cout << "Entering listener " << *super::mName << " with " << event << std::endl;
+ bool handled = super::operator()(event);
+ std::cout << "Leaving listener " << *super::mName;
+ if (handled)
+ {
+ std::cout << " (handled)";
+ }
+ std::cout << std::endl;
+ return handled;
+ }
+};
+
+LLLISTENER_WRAPPER_SUBCLASS(LLCoutListener);
+
+/**
+ * This LLListenerWrapper template subclass is used to log entry/exit to an
+ * event listener, by changing this:
+ * @code
+ * someEventPump.listen("MyClass",
+ * boost::bind(&MyClass::method, ptr, _1));
+ * @endcode
+ * to this:
+ * @code
+ * someEventPump.listen("MyClass",
+ * llwrap<LLLogListener>(
+ * boost::bind(&MyClass::method, ptr, _1)));
+ * @endcode
+ */
+template <class LISTENER>
+class LLLogListener: public LLListenerWrapper<LISTENER>
+{
+ typedef LLListenerWrapper<LISTENER> super;
+
+public:
+ /// Wrap an arbitrary listener object
+ LLLogListener(const LISTENER& listener):
+ super(listener)
+ {}
+
+ /// call
+ virtual bool operator()(const LLSD& event)
+ {
+ LL_DEBUGS("LLLogListener") << "Entering listener " << *super::mName << " with " << event << LL_ENDL;
+ bool handled = super::operator()(event);
+ LL_DEBUGS("LLLogListener") << "Leaving listener " << *super::mName;
+ if (handled)
+ {
+ LL_CONT << " (handled)";
+ }
+ LL_CONT << LL_ENDL;
+ return handled;
+ }
+};
+
+LLLISTENER_WRAPPER_SUBCLASS(LLLogListener);
+
+#endif /* ! defined(LL_LLLISTENERWRAPPER_H) */
diff --git a/indra/llcommon/llliveappconfig.h b/indra/llcommon/llliveappconfig.h
index a6ece6e8b3..73b3a23352 100644
--- a/indra/llcommon/llliveappconfig.h
+++ b/indra/llcommon/llliveappconfig.h
@@ -45,7 +45,7 @@
* loop. The traditional name for it is live_config. Be sure to call
* <code>live_config.checkAndReload()</code> periodically.
*/
-class LLLiveAppConfig : public LLLiveFile
+class LL_COMMON_API LLLiveAppConfig : public LLLiveFile
{
public:
diff --git a/indra/llcommon/lllivefile.h b/indra/llcommon/lllivefile.h
index 89b5d95e44..2453d7a125 100644
--- a/indra/llcommon/lllivefile.h
+++ b/indra/llcommon/lllivefile.h
@@ -36,7 +36,7 @@
extern const F32 DEFAULT_CONFIG_FILE_REFRESH;
-class LLLiveFile
+class LL_COMMON_API LLLiveFile
{
public:
LLLiveFile(const std::string& filename, const F32 refresh_period = 5.f);
diff --git a/indra/llcommon/lllog.h b/indra/llcommon/lllog.h
index 7ac6c8aa42..4b6777bb9c 100644
--- a/indra/llcommon/lllog.h
+++ b/indra/llcommon/lllog.h
@@ -41,7 +41,7 @@ class LLLogImpl;
class LLApp;
class LLSD;
-class LLLog
+class LL_COMMON_API LLLog
{
public:
LLLog(LLApp* app);
diff --git a/indra/llcommon/lllslconstants.h b/indra/llcommon/lllslconstants.h
index 7cd854febd..78f4435ed7 100644
--- a/indra/llcommon/lllslconstants.h
+++ b/indra/llcommon/lllslconstants.h
@@ -48,6 +48,7 @@ const U32 AGENT_TYPING = 0x0200;
const U32 AGENT_CROUCHING = 0x0400;
const U32 AGENT_BUSY = 0x0800;
const U32 AGENT_ALWAYS_RUN = 0x1000;
+const U32 AGENT_AUTOPILOT = 0x2000;
const S32 LSL_REMOTE_DATA_CHANNEL = 1;
const S32 LSL_REMOTE_DATA_REQUEST = 2;
@@ -201,5 +202,18 @@ const U32 CHANGED_OWNER = 0x80;
const U32 CHANGED_REGION = 0x100;
const U32 CHANGED_TELEPORT = 0x200;
const U32 CHANGED_REGION_START = 0x400;
+const U32 CHANGED_MEDIA = 0x800;
+
+// Possible error results
+const U32 LSL_STATUS_OK = 0;
+const U32 LSL_STATUS_MALFORMED_PARAMS = 1000;
+const U32 LSL_STATUS_TYPE_MISMATCH = 1001;
+const U32 LSL_STATUS_BOUNDS_ERROR = 1002;
+const U32 LSL_STATUS_NOT_FOUND = 1003;
+const U32 LSL_STATUS_NOT_SUPPORTED = 1004;
+const U32 LSL_STATUS_INTERNAL_ERROR = 1999;
+
+// Start per-function errors below, starting at 2000:
+const U32 LSL_STATUS_WHITELIST_FAILED = 2001;
#endif
diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp
index 14b4f9f4b0..da9cb94e13 100644
--- a/indra/llcommon/llmd5.cpp
+++ b/indra/llcommon/llmd5.cpp
@@ -83,6 +83,7 @@ documentation and/or software.
#include "llmd5.h"
#include <cassert>
+#include <iostream> // cerr
// how many bytes to grab at a time when checking files
const int LLMD5::BLOCK_LEN = 4096;
diff --git a/indra/llcommon/llmd5.h b/indra/llcommon/llmd5.h
index d8bca03e4e..df9d7324ab 100644
--- a/indra/llcommon/llmd5.h
+++ b/indra/llcommon/llmd5.h
@@ -80,7 +80,7 @@ const int MD5RAW_BYTES = 16;
const int MD5HEX_STR_SIZE = 33; // char hex[MD5HEX_STR_SIZE]; with null
const int MD5HEX_STR_BYTES = 32; // message system fixed size
-class LLMD5 {
+class LL_COMMON_API LLMD5 {
// first, some types:
typedef unsigned int uint4; // assumes integer is 4 words long
typedef unsigned short int uint2; // assumes short integer is 2 words long
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index a6de3d2d69..2a8015e26d 100644
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -44,7 +44,6 @@
#endif
#include "llmemory.h"
-#include "llmemtype.h"
//----------------------------------------------------------------------------
@@ -74,162 +73,6 @@ void LLMemory::freeReserve()
reserveMem = NULL;
}
-
-//----------------------------------------------------------------------------
-
-//static
-#if MEM_TRACK_TYPE
-S32 LLMemType::sCurDepth = 0;
-S32 LLMemType::sCurType = LLMemType::MTYPE_INIT;
-S32 LLMemType::sType[LLMemType::MTYPE_MAX_DEPTH];
-S32 LLMemType::sMemCount[LLMemType::MTYPE_NUM_TYPES] = { 0 };
-S32 LLMemType::sMaxMemCount[LLMemType::MTYPE_NUM_TYPES] = { 0 };
-S32 LLMemType::sNewCount[LLMemType::MTYPE_NUM_TYPES] = { 0 };
-S32 LLMemType::sOverheadMem = 0;
-
-const char* LLMemType::sTypeDesc[LLMemType::MTYPE_NUM_TYPES] =
-{
- "INIT",
- "STARTUP",
- "MAIN",
-
- "IMAGEBASE",
- "IMAGERAW",
- "IMAGEFORMATTED",
-
- "APPFMTIMAGE",
- "APPRAWIMAGE",
- "APPAUXRAWIMAGE",
-
- "DRAWABLE",
- "OBJECT",
- "PIPELINE",
- "AVATAR",
- "PARTICLES",
- "REGIONS",
- "INVENTORY",
- "ANIMATION",
- "NETWORK",
- "PHYSICS",
- "INTERESTLIST",
-
- "SCRIPT",
- "SCRIPT_RUN",
- "SCRIPT_BYTECODE",
-
- "IO_PUMP",
- "IO_TCP",
- "IO_BUFFER",
- "IO_HTTP_SERVER"
- "IO_SD_SERVER",
- "IO_SD_CLIENT",
- "IO_URL_REQUEST",
-
- "TEMP1",
- "TEMP2",
- "TEMP3",
- "TEMP4",
- "TEMP5",
- "TEMP6",
- "TEMP7",
- "TEMP8",
- "TEMP9"
-};
-
-#endif
-S32 LLMemType::sTotalMem = 0;
-S32 LLMemType::sMaxTotalMem = 0;
-
-//static
-void LLMemType::printMem()
-{
- S32 misc_mem = sTotalMem;
-#if MEM_TRACK_TYPE
- for (S32 i=0; i<MTYPE_NUM_TYPES; i++)
- {
- if (sMemCount[i])
- {
- llinfos << llformat("MEM: % 20s %03d MB (%03d MB) in %06d News",sTypeDesc[i],sMemCount[i]>>20,sMaxMemCount[i]>>20, sNewCount[i]) << llendl;
- }
- misc_mem -= sMemCount[i];
- }
-#endif
- llinfos << llformat("MEM: % 20s %03d MB","MISC",misc_mem>>20) << llendl;
- llinfos << llformat("MEM: % 20s %03d MB (Max=%d MB)","TOTAL",sTotalMem>>20,sMaxTotalMem>>20) << llendl;
-}
-
-#if MEM_TRACK_MEM
-
-void* ll_allocate (size_t size)
-{
- if (size == 0)
- {
- llwarns << "Null allocation" << llendl;
- }
-
- size = (size+3)&~3;
- S32 alloc_size = size + 4;
-#if MEM_TRACK_TYPE
- alloc_size += 4;
-#endif
- char* p = (char*)malloc(alloc_size);
- if (p == NULL)
- {
- LLMemory::freeReserve();
- llerrs << "Out of memory Error" << llendl;
- }
- LLMemType::sTotalMem += size;
- LLMemType::sMaxTotalMem = llmax(LLMemType::sTotalMem, LLMemType::sMaxTotalMem);
- LLMemType::sOverheadMem += 4;
- *(size_t*)p = size;
- p += 4;
-#if MEM_TRACK_TYPE
- if (LLMemType::sCurType < 0 || LLMemType::sCurType >= LLMemType::MTYPE_NUM_TYPES)
- {
- llerrs << "Memory Type Error: new" << llendl;
- }
- LLMemType::sOverheadMem += 4;
- *(S32*)p = LLMemType::sCurType;
- p += 4;
- LLMemType::sMemCount[LLMemType::sCurType] += size;
- if (LLMemType::sMemCount[LLMemType::sCurType] > LLMemType::sMaxMemCount[LLMemType::sCurType])
- {
- LLMemType::sMaxMemCount[LLMemType::sCurType] = LLMemType::sMemCount[LLMemType::sCurType];
- }
- LLMemType::sNewCount[LLMemType::sCurType]++;
-#endif
- return (void*)p;
-}
-
-void ll_release (void *pin)
-{
- if (!pin)
- {
- return;
- }
- char* p = (char*)pin;
-#if MEM_TRACK_TYPE
- p -= 4;
- S32 type = *(S32*)p;
- if (type < 0 || type >= LLMemType::MTYPE_NUM_TYPES)
- {
- llerrs << "Memory Type Error: delete" << llendl;
- }
-#endif
- p -= 4;
- S32 size = *(size_t*)p;
- LLMemType::sOverheadMem -= 4;
-#if MEM_TRACK_TYPE
- LLMemType::sMemCount[type] -= size;
- LLMemType::sOverheadMem -= 4;
- LLMemType::sNewCount[type]--;
-#endif
- LLMemType::sTotalMem -= size;
- free(p);
-}
-
-#else
-
void* ll_allocate (size_t size)
{
if (size == 0)
@@ -250,52 +93,11 @@ void ll_release (void *p)
free(p);
}
-#endif
-
-#if MEM_TRACK_MEM
-
-void* operator new (size_t size)
-{
- return ll_allocate(size);
-}
-
-void* operator new[] (size_t size)
-{
- return ll_allocate(size);
-}
-
-void operator delete (void *p)
-{
- ll_release(p);
-}
-
-void operator delete[] (void *p)
-{
- ll_release(p);
-}
-
-#endif
-
-//----------------------------------------------------------------------------
-
-LLRefCount::LLRefCount() :
- mRef(0)
-{
-}
-
-LLRefCount::~LLRefCount()
-{
- if (mRef != 0)
- {
- llerrs << "deleting non-zero reference" << llendl;
- }
-}
-
//----------------------------------------------------------------------------
#if defined(LL_WINDOWS)
-U64 getCurrentRSS()
+U64 LLMemory::getCurrentRSS()
{
HANDLE self = GetCurrentProcess();
PROCESS_MEMORY_COUNTERS counters;
@@ -333,7 +135,7 @@ U64 getCurrentRSS()
// }
// }
-U64 getCurrentRSS()
+U64 LLMemory::getCurrentRSS()
{
U64 residentSize = 0;
task_basic_info_data_t basicInfo;
@@ -357,7 +159,7 @@ U64 getCurrentRSS()
#elif defined(LL_LINUX)
-U64 getCurrentRSS()
+U64 LLMemory::getCurrentRSS()
{
static const char statPath[] = "/proc/self/stat";
LLFILE *fp = LLFile::fopen(statPath, "r");
@@ -396,7 +198,7 @@ bail:
#define _STRUCTURED_PROC 1
#include <sys/procfs.h>
-U64 getCurrentRSS()
+U64 LLMemory::getCurrentRSS()
{
char path [LL_MAX_PATH]; /* Flawfinder: ignore */
@@ -419,7 +221,7 @@ U64 getCurrentRSS()
}
#else
-U64 getCurrentRSS()
+U64 LLMemory::getCurrentRSS()
{
return 0;
}
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index b5c0711484..1c6f64dd8b 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -29,444 +29,37 @@
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
-#ifndef LL_MEMORY_H
-#define LL_MEMORY_H
+#ifndef LLMEMORY_H
+#define LLMEMORY_H
-#include <new>
-#include <cstdlib>
-#include "llerror.h"
extern S32 gTotalDAlloc;
extern S32 gTotalDAUse;
extern S32 gDACount;
-const U32 LLREFCOUNT_SENTINEL_VALUE = 0xAAAAAAAA;
+extern void* ll_allocate (size_t size);
+extern void ll_release (void *p);
-//----------------------------------------------------------------------------
-
-class LLMemory
+class LL_COMMON_API LLMemory
{
public:
static void initClass();
static void cleanupClass();
static void freeReserve();
+ // Return the resident set size of the current process, in bytes.
+ // Return value is zero if not known.
+ static U64 getCurrentRSS();
private:
static char* reserveMem;
};
-//----------------------------------------------------------------------------
-// RefCount objects should generally only be accessed by way of LLPointer<>'s
-// NOTE: LLPointer<LLFoo> x = new LLFoo(); MAY NOT BE THREAD SAFE
-// if LLFoo::LLFoo() does anything like put itself in an update queue.
-// The queue may get accessed before it gets assigned to x.
-// The correct implementation is:
-// LLPointer<LLFoo> x = new LLFoo; // constructor does not do anything interesting
-// x->instantiate(); // does stuff like place x into an update queue
-
-// see llthread.h for LLThreadSafeRefCount
-
-//----------------------------------------------------------------------------
-
-class LLRefCount
-{
-protected:
- LLRefCount(const LLRefCount&); // not implemented
-private:
- LLRefCount&operator=(const LLRefCount&); // not implemented
-
-protected:
- virtual ~LLRefCount(); // use unref()
-
-public:
- LLRefCount();
-
- void ref()
- {
- mRef++;
- }
-
- S32 unref()
- {
- llassert(mRef >= 1);
- if (0 == --mRef)
- {
- delete this;
- return 0;
- }
- return mRef;
- }
-
- S32 getNumRefs() const
- {
- return mRef;
- }
-
-private:
- S32 mRef;
-};
-
-//----------------------------------------------------------------------------
-
-// Note: relies on Type having ref() and unref() methods
-template <class Type> class LLPointer
-{
-public:
-
- LLPointer() :
- mPointer(NULL)
- {
- }
-
- LLPointer(Type* ptr) :
- mPointer(ptr)
- {
- ref();
- }
-
- LLPointer(const LLPointer<Type>& ptr) :
- mPointer(ptr.mPointer)
- {
- ref();
- }
-
- // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
- template<typename Subclass>
- LLPointer(const LLPointer<Subclass>& ptr) :
- mPointer(ptr.get())
- {
- ref();
- }
-
- ~LLPointer()
- {
- unref();
- }
-
- Type* get() const { return mPointer; }
- const Type* operator->() const { return mPointer; }
- Type* operator->() { return mPointer; }
- const Type& operator*() const { return *mPointer; }
- Type& operator*() { return *mPointer; }
-
- operator BOOL() const { return (mPointer != NULL); }
- operator bool() const { return (mPointer != NULL); }
- bool operator!() const { return (mPointer == NULL); }
- bool isNull() const { return (mPointer == NULL); }
- bool notNull() const { return (mPointer != NULL); }
-
- operator Type*() const { return mPointer; }
- operator const Type*() const { return mPointer; }
- bool operator !=(Type* ptr) const { return (mPointer != ptr); }
- bool operator ==(Type* ptr) const { return (mPointer == ptr); }
- bool operator ==(const LLPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); }
- bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
- bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }
-
- LLPointer<Type>& operator =(Type* ptr)
- {
- if( mPointer != ptr )
- {
- unref();
- mPointer = ptr;
- ref();
- }
-
- return *this;
- }
-
- LLPointer<Type>& operator =(const LLPointer<Type>& ptr)
- {
- if( mPointer != ptr.mPointer )
- {
- unref();
- mPointer = ptr.mPointer;
- ref();
- }
- return *this;
- }
-
- // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
- template<typename Subclass>
- LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr)
- {
- if( mPointer != ptr.get() )
- {
- unref();
- mPointer = ptr.get();
- ref();
- }
- return *this;
- }
-
- // Just exchange the pointers, which will not change the reference counts.
- static void swap(LLPointer<Type>& a, LLPointer<Type>& b)
- {
- Type* temp = a.mPointer;
- a.mPointer = b.mPointer;
- b.mPointer = temp;
- }
-
-protected:
- void ref()
- {
- if (mPointer)
- {
- mPointer->ref();
- }
- }
-
- void unref()
- {
- if (mPointer)
- {
- Type *tempp = mPointer;
- mPointer = NULL;
- tempp->unref();
- if (mPointer != NULL)
- {
- llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
- unref();
- }
- }
- }
-
-protected:
- Type* mPointer;
-};
-
-//template <class Type>
-//class LLPointerTraits
-//{
-// static Type* null();
-//};
-//
-// Expands LLPointer to return a pointer to a special instance of class Type instead of NULL.
-// This is useful in instances where operations on NULL pointers are semantically safe and/or
-// when error checking occurs at a different granularity or in a different part of the code
-// than when referencing an object via a LLSafeHandle.
-//
-
-template <class Type>
-class LLSafeHandle
-{
-public:
- LLSafeHandle() :
- mPointer(NULL)
- {
- }
-
- LLSafeHandle(Type* ptr) :
- mPointer(NULL)
- {
- assign(ptr);
- }
-
- LLSafeHandle(const LLSafeHandle<Type>& ptr) :
- mPointer(NULL)
- {
- assign(ptr.mPointer);
- }
-
- // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
- template<typename Subclass>
- LLSafeHandle(const LLSafeHandle<Subclass>& ptr) :
- mPointer(NULL)
- {
- assign(ptr.get());
- }
-
- ~LLSafeHandle()
- {
- unref();
- }
-
- const Type* operator->() const { return nonNull(mPointer); }
- Type* operator->() { return nonNull(mPointer); }
-
- Type* get() const { return mPointer; }
- // we disallow these operations as they expose our null objects to direct manipulation
- // and bypass the reference counting semantics
- //const Type& operator*() const { return *nonNull(mPointer); }
- //Type& operator*() { return *nonNull(mPointer); }
-
- operator BOOL() const { return mPointer != NULL; }
- operator bool() const { return mPointer != NULL; }
- bool operator!() const { return mPointer == NULL; }
- bool isNull() const { return mPointer == NULL; }
- bool notNull() const { return mPointer != NULL; }
-
-
- operator Type*() const { return mPointer; }
- operator const Type*() const { return mPointer; }
- bool operator !=(Type* ptr) const { return (mPointer != ptr); }
- bool operator ==(Type* ptr) const { return (mPointer == ptr); }
- bool operator ==(const LLSafeHandle<Type>& ptr) const { return (mPointer == ptr.mPointer); }
- bool operator < (const LLSafeHandle<Type>& ptr) const { return (mPointer < ptr.mPointer); }
- bool operator > (const LLSafeHandle<Type>& ptr) const { return (mPointer > ptr.mPointer); }
-
- LLSafeHandle<Type>& operator =(Type* ptr)
- {
- assign(ptr);
- return *this;
- }
-
- LLSafeHandle<Type>& operator =(const LLSafeHandle<Type>& ptr)
- {
- assign(ptr.mPointer);
- return *this;
- }
-
- // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
- template<typename Subclass>
- LLSafeHandle<Type>& operator =(const LLSafeHandle<Subclass>& ptr)
- {
- assign(ptr.get());
- return *this;
- }
-
-public:
- typedef Type* (*NullFunc)();
- static const NullFunc sNullFunc;
-
-protected:
- void ref()
- {
- if (mPointer)
- {
- mPointer->ref();
- }
- }
-
- void unref()
- {
- if (mPointer)
- {
- Type *tempp = mPointer;
- mPointer = NULL;
- tempp->unref();
- if (mPointer != NULL)
- {
- llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
- unref();
- }
- }
- }
-
- void assign(Type* ptr)
- {
- if( mPointer != ptr )
- {
- unref();
- mPointer = ptr;
- ref();
- }
- }
-
- static Type* nonNull(Type* ptr)
- {
- return ptr == NULL ? sNullFunc() : ptr;
- }
-
-protected:
- Type* mPointer;
-};
-
-// LLInitializedPointer is just a pointer with a default constructor that initializes it to NULL
-// NOT a smart pointer like LLPointer<>
-// Useful for example in std::map<int,LLInitializedPointer<LLFoo> >
-// (std::map uses the default constructor for creating new entries)
-template <typename T> class LLInitializedPointer
-{
-public:
- LLInitializedPointer() : mPointer(NULL) {}
- ~LLInitializedPointer() { delete mPointer; }
-
- const T* operator->() const { return mPointer; }
- T* operator->() { return mPointer; }
- const T& operator*() const { return *mPointer; }
- T& operator*() { return *mPointer; }
- operator const T*() const { return mPointer; }
- operator T*() { return mPointer; }
- T* operator=(T* x) { return (mPointer = x); }
- operator bool() const { return mPointer != NULL; }
- bool operator!() const { return mPointer == NULL; }
- bool operator==(T* rhs) { return mPointer == rhs; }
- bool operator==(const LLInitializedPointer<T>* rhs) { return mPointer == rhs.mPointer; }
-
-protected:
- T* mPointer;
-};
-
-//----------------------------------------------------------------------------
+// LLRefCount moved to llrefcount.h
-// LLSingleton implements the getInstance() method part of the Singleton
-// pattern. It can't make the derived class constructors protected, though, so
-// you have to do that yourself.
-//
-// There are two ways to use LLSingleton. The first way is to inherit from it
-// while using the typename that you'd like to be static as the template
-// parameter, like so:
-//
-// class Foo: public LLSingleton<Foo>{};
-//
-// Foo& instance = Foo::instance();
-//
-// The second way is to use the singleton class directly, without inheritance:
-//
-// typedef LLSingleton<Foo> FooSingleton;
-//
-// Foo& instance = FooSingleton::instance();
-//
-// In this case, the class being managed as a singleton needs to provide an
-// initSingleton() method since the LLSingleton virtual method won't be
-// available
-//
-// As currently written, it is not thread-safe.
-template <typename T>
-class LLSingleton
-{
-public:
- virtual ~LLSingleton() {}
-#ifdef LL_MSVC7
-// workaround for VC7 compiler bug
-// adapted from http://www.codeproject.com/KB/tips/VC2003MeyersSingletonBug.aspx
-// our version doesn't introduce a nested struct so that you can still declare LLSingleton<MyClass>
-// a friend and hide your constructor
- static T* getInstance()
- {
- LLSingleton<T> singleton;
- return singleton.vsHack();
- }
-
- T* vsHack()
-#else
- static T* getInstance()
-#endif
- {
- static T instance;
- static bool needs_init = true;
- if (needs_init)
- {
- needs_init = false;
- instance.initSingleton();
- }
- return &instance;
- }
-
- static T& instance()
- {
- return *getInstance();
- }
-
-private:
- virtual void initSingleton() {}
-};
+// LLPointer moved to llpointer.h
-//----------------------------------------------------------------------------
+// LLSafeHandle moved to llsafehandle.h
-// Return the resident set size of the current process, in bytes.
-// Return value is zero if not known.
-U64 getCurrentRSS();
+// LLSingleton moved to llsingleton.h
#endif
diff --git a/indra/llcommon/llmemorystream.h b/indra/llcommon/llmemorystream.h
index f3486324c5..fa0f5d22f2 100644
--- a/indra/llcommon/llmemorystream.h
+++ b/indra/llcommon/llmemorystream.h
@@ -52,7 +52,7 @@
* be careful to always pass in a valid memory location that exists
* for at least as long as this streambuf.
*/
-class LLMemoryStreamBuf : public std::streambuf
+class LL_COMMON_API LLMemoryStreamBuf : public std::streambuf
{
public:
LLMemoryStreamBuf(const U8* start, S32 length);
@@ -74,7 +74,7 @@ protected:
* be careful to always pass in a valid memory location that exists
* for at least as long as this streambuf.
*/
-class LLMemoryStream : public std::istream
+class LL_COMMON_API LLMemoryStream : public std::istream
{
public:
LLMemoryStream(const U8* start, S32 length);
diff --git a/indra/llcommon/llmemtype.cpp b/indra/llcommon/llmemtype.cpp
new file mode 100644
index 0000000000..4e33439711
--- /dev/null
+++ b/indra/llcommon/llmemtype.cpp
@@ -0,0 +1,237 @@
+/**
+ * @file llmemtype.cpp
+ * @brief Simple memory allocation/deallocation tracking stuff here
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llmemtype.h"
+#include "llallocator.h"
+
+std::vector<char const *> LLMemType::DeclareMemType::mNameList;
+
+LLMemType::DeclareMemType LLMemType::MTYPE_INIT("Init");
+LLMemType::DeclareMemType LLMemType::MTYPE_STARTUP("Startup");
+LLMemType::DeclareMemType LLMemType::MTYPE_MAIN("Main");
+LLMemType::DeclareMemType LLMemType::MTYPE_FRAME("Frame");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_GATHER_INPUT("GatherInput");
+LLMemType::DeclareMemType LLMemType::MTYPE_JOY_KEY("JoyKey");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_IDLE("Idle");
+LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_PUMP("IdlePump");
+LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_NETWORK("IdleNetwork");
+LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_UPDATE_REGIONS("IdleUpdateRegions");
+LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_UPDATE_VIEWER_REGION("IdleUpdateViewerRegion");
+LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_UPDATE_SURFACE("IdleUpdateSurface");
+LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_UPDATE_PARCEL_OVERLAY("IdleUpdateParcelOverlay");
+LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_AUDIO("IdleAudio");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_CACHE_PROCESS_PENDING("CacheProcessPending");
+LLMemType::DeclareMemType LLMemType::MTYPE_CACHE_PROCESS_PENDING_ASKS("CacheProcessPendingAsks");
+LLMemType::DeclareMemType LLMemType::MTYPE_CACHE_PROCESS_PENDING_REPLIES("CacheProcessPendingReplies");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_MESSAGE_CHECK_ALL("MessageCheckAll");
+LLMemType::DeclareMemType LLMemType::MTYPE_MESSAGE_PROCESS_ACKS("MessageProcessAcks");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_RENDER("Render");
+LLMemType::DeclareMemType LLMemType::MTYPE_SLEEP("Sleep");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_NETWORK("Network");
+LLMemType::DeclareMemType LLMemType::MTYPE_PHYSICS("Physics");
+LLMemType::DeclareMemType LLMemType::MTYPE_INTERESTLIST("InterestList");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_IMAGEBASE("ImageBase");
+LLMemType::DeclareMemType LLMemType::MTYPE_IMAGERAW("ImageRaw");
+LLMemType::DeclareMemType LLMemType::MTYPE_IMAGEFORMATTED("ImageFormatted");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_APPFMTIMAGE("AppFmtImage");
+LLMemType::DeclareMemType LLMemType::MTYPE_APPRAWIMAGE("AppRawImage");
+LLMemType::DeclareMemType LLMemType::MTYPE_APPAUXRAWIMAGE("AppAuxRawImage");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_DRAWABLE("Drawable");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_OBJECT("Object");
+LLMemType::DeclareMemType LLMemType::MTYPE_OBJECT_PROCESS_UPDATE("ObjectProcessUpdate");
+LLMemType::DeclareMemType LLMemType::MTYPE_OBJECT_PROCESS_UPDATE_CORE("ObjectProcessUpdateCore");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY("Display");
+LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_UPDATE("DisplayUpdate");
+LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_UPDATE_CAMERA("DisplayUpdateCam");
+LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_UPDATE_GEOM("DisplayUpdateGeom");
+LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_SWAP("DisplaySwap");
+LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_UPDATE_HUD("DisplayUpdateHud");
+LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_GEN_REFLECTION("DisplayGenRefl");
+LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_IMAGE_UPDATE("DisplayImageUpdate");
+LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_STATE_SORT("DisplayStateSort");
+LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_SKY("DisplaySky");
+LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_RENDER_GEOM("DisplayRenderGeom");
+LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_RENDER_FLUSH("DisplayRenderFlush");
+LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_RENDER_UI("DisplayRenderUI");
+LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_RENDER_ATTACHMENTS("DisplayRenderAttach");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_DATA("VertexData");
+LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_CONSTRUCTOR("VertexConstr");
+LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_DESTRUCTOR("VertexDestr");
+LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_CREATE_VERTICES("VertexCreateVerts");
+LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_CREATE_INDICES("VertexCreateIndices");
+LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_DESTROY_BUFFER("VertexDestroyBuff");
+LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_DESTROY_INDICES("VertexDestroyIndices");
+LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_UPDATE_VERTS("VertexUpdateVerts");
+LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_UPDATE_INDICES("VertexUpdateIndices");
+LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_ALLOCATE_BUFFER("VertexAllocateBuffer");
+LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_RESIZE_BUFFER("VertexResizeBuffer");
+LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_MAP_BUFFER("VertexMapBuffer");
+LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES("VertexMapBufferVerts");
+LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES("VertexMapBufferIndices");
+LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_UNMAP_BUFFER("VertexUnmapBuffer");
+LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_SET_STRIDE("VertexSetStride");
+LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_SET_BUFFER("VertexSetBuffer");
+LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_SETUP_VERTEX_BUFFER("VertexSetupVertBuff");
+LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_CLEANUP_CLASS("VertexCleanupClass");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_SPACE_PARTITION("SpacePartition");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE("Pipeline");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_INIT("PipelineInit");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_CREATE_BUFFERS("PipelineCreateBuffs");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RESTORE_GL("PipelineRestroGL");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_UNLOAD_SHADERS("PipelineUnloadShaders");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_LIGHTING_DETAIL("PipelineLightingDetail");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_GET_POOL_TYPE("PipelineGetPoolType");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_ADD_POOL("PipelineAddPool");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_ALLOCATE_DRAWABLE("PipelineAllocDrawable");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_ADD_OBJECT("PipelineAddObj");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_CREATE_OBJECTS("PipelineCreateObjs");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_UPDATE_MOVE("PipelineUpdateMove");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_UPDATE_GEOM("PipelineUpdateGeom");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_VISIBLE("PipelineMarkVisible");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_MOVED("PipelineMarkMoved");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_SHIFT("PipelineMarkShift");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_SHIFT_OBJECTS("PipelineShiftObjs");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_TEXTURED("PipelineMarkTextured");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_REBUILD("PipelineMarkRebuild");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_UPDATE_CULL("PipelineUpdateCull");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_STATE_SORT("PipelineStateSort");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_POST_SORT("PipelinePostSort");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_HUD_ELS("PipelineHudEls");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_HL("PipelineRenderHL");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_GEOM("PipelineRenderGeom");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED("PipelineRenderGeomDef");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_GEOM_POST_DEF("PipelineRenderGeomPostDef");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_GEOM_SHADOW("PipelineRenderGeomShadow");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_SELECT("PipelineRenderSelect");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_REBUILD_POOLS("PipelineRebuildPools");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_QUICK_LOOKUP("PipelineQuickLookup");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_OBJECTS("PipelineRenderObjs");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_GENERATE_IMPOSTOR("PipelineGenImpostors");
+LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_BLOOM("PipelineRenderBloom");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_UPKEEP_POOLS("UpkeepPools");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_AVATAR("Avatar");
+LLMemType::DeclareMemType LLMemType::MTYPE_AVATAR_MESH("AvatarMesh");
+LLMemType::DeclareMemType LLMemType::MTYPE_PARTICLES("Particles");
+LLMemType::DeclareMemType LLMemType::MTYPE_REGIONS("Regions");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY("Inventory");
+LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_DRAW("InventoryDraw");
+LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_BUILD_NEW_VIEWS("InventoryBuildNewViews");
+LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_DO_FOLDER("InventoryDoFolder");
+LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_POST_BUILD("InventoryPostBuild");
+LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_FROM_XML("InventoryFromXML");
+LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_CREATE_NEW_ITEM("InventoryCreateNewItem");
+LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_VIEW_INIT("InventoryViewInit");
+LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_VIEW_SHOW("InventoryViewShow");
+LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_VIEW_TOGGLE("InventoryViewToggle");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_ANIMATION("Animation");
+LLMemType::DeclareMemType LLMemType::MTYPE_VOLUME("Volume");
+LLMemType::DeclareMemType LLMemType::MTYPE_PRIMITIVE("Primitive");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_SCRIPT("Script");
+LLMemType::DeclareMemType LLMemType::MTYPE_SCRIPT_RUN("ScriptRun");
+LLMemType::DeclareMemType LLMemType::MTYPE_SCRIPT_BYTECODE("ScriptByteCode");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_IO_PUMP("IoPump");
+LLMemType::DeclareMemType LLMemType::MTYPE_IO_TCP("IoTCP");
+LLMemType::DeclareMemType LLMemType::MTYPE_IO_BUFFER("IoBuffer");
+LLMemType::DeclareMemType LLMemType::MTYPE_IO_HTTP_SERVER("IoHttpServer");
+LLMemType::DeclareMemType LLMemType::MTYPE_IO_SD_SERVER("IoSDServer");
+LLMemType::DeclareMemType LLMemType::MTYPE_IO_SD_CLIENT("IoSDClient");
+LLMemType::DeclareMemType LLMemType::MTYPE_IO_URL_REQUEST("IOUrlRequest");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_DIRECTX_INIT("DirectXInit");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_TEMP1("Temp1");
+LLMemType::DeclareMemType LLMemType::MTYPE_TEMP2("Temp2");
+LLMemType::DeclareMemType LLMemType::MTYPE_TEMP3("Temp3");
+LLMemType::DeclareMemType LLMemType::MTYPE_TEMP4("Temp4");
+LLMemType::DeclareMemType LLMemType::MTYPE_TEMP5("Temp5");
+LLMemType::DeclareMemType LLMemType::MTYPE_TEMP6("Temp6");
+LLMemType::DeclareMemType LLMemType::MTYPE_TEMP7("Temp7");
+LLMemType::DeclareMemType LLMemType::MTYPE_TEMP8("Temp8");
+LLMemType::DeclareMemType LLMemType::MTYPE_TEMP9("Temp9");
+
+LLMemType::DeclareMemType LLMemType::MTYPE_OTHER("Other");
+
+
+LLMemType::DeclareMemType::DeclareMemType(char const * st)
+{
+ mID = (S32)mNameList.size();
+ mName = st;
+
+ mNameList.push_back(mName);
+}
+
+LLMemType::DeclareMemType::~DeclareMemType()
+{
+}
+
+LLMemType::LLMemType(LLMemType::DeclareMemType& dt)
+{
+ mTypeIndex = dt.mID;
+ LLAllocator::pushMemType(dt.mID);
+}
+
+LLMemType::~LLMemType()
+{
+ LLAllocator::popMemType();
+}
+
+char const * LLMemType::getNameFromID(S32 id)
+{
+ if (id < 0 || id >= (S32)DeclareMemType::mNameList.size())
+ {
+ return "INVALID";
+ }
+
+ return DeclareMemType::mNameList[id];
+}
+
diff --git a/indra/llcommon/llmemtype.h b/indra/llcommon/llmemtype.h
index a9ebc2062f..677fad3034 100644
--- a/indra/llcommon/llmemtype.h
+++ b/indra/llcommon/llmemtype.h
@@ -36,128 +36,210 @@
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
-class LLMemType;
-
-extern void* ll_allocate (size_t size);
-extern void ll_release (void *p);
+//----------------------------------------------------------------------------
-#define MEM_TRACK_MEM 0
-#define MEM_TRACK_TYPE (1 && MEM_TRACK_MEM)
+#include "linden_common.h"
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// WARNING: Never commit with MEM_TRACK_MEM == 1
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+#define MEM_TRACK_MEM (0 && LL_WINDOWS)
-#if MEM_TRACK_TYPE
-#define MEM_DUMP_DATA 1
-#define MEM_TYPE_NEW(T) \
-static void* operator new(size_t s) { LLMemType mt(T); return ll_allocate(s); } \
-static void operator delete(void* p) { ll_release(p); }
+#include <vector>
-#else
#define MEM_TYPE_NEW(T)
-#endif // MEM_TRACK_TYPE
-
-
-//----------------------------------------------------------------------------
-class LLMemType
+class LL_COMMON_API LLMemType
{
public:
- // Also update sTypeDesc in llmemory.cpp
- enum EMemType
- {
- MTYPE_INIT,
- MTYPE_STARTUP,
- MTYPE_MAIN,
- MTYPE_IMAGEBASE,
- MTYPE_IMAGERAW,
- MTYPE_IMAGEFORMATTED,
-
- MTYPE_APPFMTIMAGE,
- MTYPE_APPRAWIMAGE,
- MTYPE_APPAUXRAWIMAGE,
-
- MTYPE_DRAWABLE,
- MTYPE_OBJECT,
- MTYPE_VERTEX_DATA,
- MTYPE_SPACE_PARTITION,
- MTYPE_PIPELINE,
- MTYPE_AVATAR,
- MTYPE_AVATAR_MESH,
- MTYPE_PARTICLES,
- MTYPE_REGIONS,
- MTYPE_INVENTORY,
- MTYPE_ANIMATION,
- MTYPE_VOLUME,
- MTYPE_PRIMITIVE,
-
- MTYPE_NETWORK,
- MTYPE_PHYSICS,
- MTYPE_INTERESTLIST,
-
- MTYPE_SCRIPT,
- MTYPE_SCRIPT_RUN,
- MTYPE_SCRIPT_BYTECODE,
-
- MTYPE_IO_PUMP,
- MTYPE_IO_TCP,
- MTYPE_IO_BUFFER,
- MTYPE_IO_HTTP_SERVER,
- MTYPE_IO_SD_SERVER,
- MTYPE_IO_SD_CLIENT,
- MTYPE_IO_URL_REQUEST,
-
- MTYPE_TEMP1,
- MTYPE_TEMP2,
- MTYPE_TEMP3,
- MTYPE_TEMP4,
- MTYPE_TEMP5,
- MTYPE_TEMP6,
- MTYPE_TEMP7,
- MTYPE_TEMP8,
- MTYPE_TEMP9,
-
- MTYPE_OTHER, // Special, used by display code
+ // class we'll initialize all instances of as
+ // static members of MemType. Then use
+ // to construct any new mem type.
+ class LL_COMMON_API DeclareMemType
+ {
+ public:
+ DeclareMemType(char const * st);
+ ~DeclareMemType();
+
+ S32 mID;
+ char const * mName;
- MTYPE_NUM_TYPES
+ // array so we can map an index ID to Name
+ static std::vector<char const *> mNameList;
};
- enum { MTYPE_MAX_DEPTH = 64 };
-
-public:
- LLMemType(EMemType type)
- {
-#if MEM_TRACK_TYPE
- if (type < 0 || type >= MTYPE_NUM_TYPES)
- llerrs << "LLMemType error" << llendl;
- if (sCurDepth < 0 || sCurDepth >= MTYPE_MAX_DEPTH)
- llerrs << "LLMemType error" << llendl;
- sType[sCurDepth] = sCurType;
- sCurDepth++;
- sCurType = type;
-#endif
- }
- ~LLMemType()
- {
-#if MEM_TRACK_TYPE
- sCurDepth--;
- sCurType = sType[sCurDepth];
-#endif
- }
- static void reset();
- static void printMem();
+ LLMemType(DeclareMemType& dt);
+ ~LLMemType();
+
+ static char const * getNameFromID(S32 id);
+
+ static DeclareMemType MTYPE_INIT;
+ static DeclareMemType MTYPE_STARTUP;
+ static DeclareMemType MTYPE_MAIN;
+ static DeclareMemType MTYPE_FRAME;
+
+ static DeclareMemType MTYPE_GATHER_INPUT;
+ static DeclareMemType MTYPE_JOY_KEY;
+
+ static DeclareMemType MTYPE_IDLE;
+ static DeclareMemType MTYPE_IDLE_PUMP;
+ static DeclareMemType MTYPE_IDLE_NETWORK;
+ static DeclareMemType MTYPE_IDLE_UPDATE_REGIONS;
+ static DeclareMemType MTYPE_IDLE_UPDATE_VIEWER_REGION;
+ static DeclareMemType MTYPE_IDLE_UPDATE_SURFACE;
+ static DeclareMemType MTYPE_IDLE_UPDATE_PARCEL_OVERLAY;
+ static DeclareMemType MTYPE_IDLE_AUDIO;
+
+ static DeclareMemType MTYPE_CACHE_PROCESS_PENDING;
+ static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_ASKS;
+ static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_REPLIES;
+
+ static DeclareMemType MTYPE_MESSAGE_CHECK_ALL;
+ static DeclareMemType MTYPE_MESSAGE_PROCESS_ACKS;
+
+ static DeclareMemType MTYPE_RENDER;
+ static DeclareMemType MTYPE_SLEEP;
+
+ static DeclareMemType MTYPE_NETWORK;
+ static DeclareMemType MTYPE_PHYSICS;
+ static DeclareMemType MTYPE_INTERESTLIST;
+
+ static DeclareMemType MTYPE_IMAGEBASE;
+ static DeclareMemType MTYPE_IMAGERAW;
+ static DeclareMemType MTYPE_IMAGEFORMATTED;
-public:
-#if MEM_TRACK_TYPE
- static S32 sCurDepth;
- static S32 sCurType;
- static S32 sType[MTYPE_MAX_DEPTH];
- static S32 sMemCount[MTYPE_NUM_TYPES];
- static S32 sMaxMemCount[MTYPE_NUM_TYPES];
- static S32 sNewCount[MTYPE_NUM_TYPES];
- static S32 sOverheadMem;
- static const char* sTypeDesc[MTYPE_NUM_TYPES];
-#endif
- static S32 sTotalMem;
- static S32 sMaxTotalMem;
+ static DeclareMemType MTYPE_APPFMTIMAGE;
+ static DeclareMemType MTYPE_APPRAWIMAGE;
+ static DeclareMemType MTYPE_APPAUXRAWIMAGE;
+
+ static DeclareMemType MTYPE_DRAWABLE;
+
+ static DeclareMemType MTYPE_OBJECT;
+ static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE;
+ static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE_CORE;
+
+ static DeclareMemType MTYPE_DISPLAY;
+ static DeclareMemType MTYPE_DISPLAY_UPDATE;
+ static DeclareMemType MTYPE_DISPLAY_UPDATE_CAMERA;
+ static DeclareMemType MTYPE_DISPLAY_UPDATE_GEOM;
+ static DeclareMemType MTYPE_DISPLAY_SWAP;
+ static DeclareMemType MTYPE_DISPLAY_UPDATE_HUD;
+ static DeclareMemType MTYPE_DISPLAY_GEN_REFLECTION;
+ static DeclareMemType MTYPE_DISPLAY_IMAGE_UPDATE;
+ static DeclareMemType MTYPE_DISPLAY_STATE_SORT;
+ static DeclareMemType MTYPE_DISPLAY_SKY;
+ static DeclareMemType MTYPE_DISPLAY_RENDER_GEOM;
+ static DeclareMemType MTYPE_DISPLAY_RENDER_FLUSH;
+ static DeclareMemType MTYPE_DISPLAY_RENDER_UI;
+ static DeclareMemType MTYPE_DISPLAY_RENDER_ATTACHMENTS;
+
+ static DeclareMemType MTYPE_VERTEX_DATA;
+ static DeclareMemType MTYPE_VERTEX_CONSTRUCTOR;
+ static DeclareMemType MTYPE_VERTEX_DESTRUCTOR;
+ static DeclareMemType MTYPE_VERTEX_CREATE_VERTICES;
+ static DeclareMemType MTYPE_VERTEX_CREATE_INDICES;
+ static DeclareMemType MTYPE_VERTEX_DESTROY_BUFFER;
+ static DeclareMemType MTYPE_VERTEX_DESTROY_INDICES;
+ static DeclareMemType MTYPE_VERTEX_UPDATE_VERTS;
+ static DeclareMemType MTYPE_VERTEX_UPDATE_INDICES;
+ static DeclareMemType MTYPE_VERTEX_ALLOCATE_BUFFER;
+ static DeclareMemType MTYPE_VERTEX_RESIZE_BUFFER;
+ static DeclareMemType MTYPE_VERTEX_MAP_BUFFER;
+ static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_VERTICES;
+ static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_INDICES;
+ static DeclareMemType MTYPE_VERTEX_UNMAP_BUFFER;
+ static DeclareMemType MTYPE_VERTEX_SET_STRIDE;
+ static DeclareMemType MTYPE_VERTEX_SET_BUFFER;
+ static DeclareMemType MTYPE_VERTEX_SETUP_VERTEX_BUFFER;
+ static DeclareMemType MTYPE_VERTEX_CLEANUP_CLASS;
+
+ static DeclareMemType MTYPE_SPACE_PARTITION;
+
+ static DeclareMemType MTYPE_PIPELINE;
+ static DeclareMemType MTYPE_PIPELINE_INIT;
+ static DeclareMemType MTYPE_PIPELINE_CREATE_BUFFERS;
+ static DeclareMemType MTYPE_PIPELINE_RESTORE_GL;
+ static DeclareMemType MTYPE_PIPELINE_UNLOAD_SHADERS;
+ static DeclareMemType MTYPE_PIPELINE_LIGHTING_DETAIL;
+ static DeclareMemType MTYPE_PIPELINE_GET_POOL_TYPE;
+ static DeclareMemType MTYPE_PIPELINE_ADD_POOL;
+ static DeclareMemType MTYPE_PIPELINE_ALLOCATE_DRAWABLE;
+ static DeclareMemType MTYPE_PIPELINE_ADD_OBJECT;
+ static DeclareMemType MTYPE_PIPELINE_CREATE_OBJECTS;
+ static DeclareMemType MTYPE_PIPELINE_UPDATE_MOVE;
+ static DeclareMemType MTYPE_PIPELINE_UPDATE_GEOM;
+ static DeclareMemType MTYPE_PIPELINE_MARK_VISIBLE;
+ static DeclareMemType MTYPE_PIPELINE_MARK_MOVED;
+ static DeclareMemType MTYPE_PIPELINE_MARK_SHIFT;
+ static DeclareMemType MTYPE_PIPELINE_SHIFT_OBJECTS;
+ static DeclareMemType MTYPE_PIPELINE_MARK_TEXTURED;
+ static DeclareMemType MTYPE_PIPELINE_MARK_REBUILD;
+ static DeclareMemType MTYPE_PIPELINE_UPDATE_CULL;
+ static DeclareMemType MTYPE_PIPELINE_STATE_SORT;
+ static DeclareMemType MTYPE_PIPELINE_POST_SORT;
+
+ static DeclareMemType MTYPE_PIPELINE_RENDER_HUD_ELS;
+ static DeclareMemType MTYPE_PIPELINE_RENDER_HL;
+ static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM;
+ static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED;
+ static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_POST_DEF;
+ static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_SHADOW;
+ static DeclareMemType MTYPE_PIPELINE_RENDER_SELECT;
+ static DeclareMemType MTYPE_PIPELINE_REBUILD_POOLS;
+ static DeclareMemType MTYPE_PIPELINE_QUICK_LOOKUP;
+ static DeclareMemType MTYPE_PIPELINE_RENDER_OBJECTS;
+ static DeclareMemType MTYPE_PIPELINE_GENERATE_IMPOSTOR;
+ static DeclareMemType MTYPE_PIPELINE_RENDER_BLOOM;
+
+ static DeclareMemType MTYPE_UPKEEP_POOLS;
+
+ static DeclareMemType MTYPE_AVATAR;
+ static DeclareMemType MTYPE_AVATAR_MESH;
+ static DeclareMemType MTYPE_PARTICLES;
+ static DeclareMemType MTYPE_REGIONS;
+
+ static DeclareMemType MTYPE_INVENTORY;
+ static DeclareMemType MTYPE_INVENTORY_DRAW;
+ static DeclareMemType MTYPE_INVENTORY_BUILD_NEW_VIEWS;
+ static DeclareMemType MTYPE_INVENTORY_DO_FOLDER;
+ static DeclareMemType MTYPE_INVENTORY_POST_BUILD;
+ static DeclareMemType MTYPE_INVENTORY_FROM_XML;
+ static DeclareMemType MTYPE_INVENTORY_CREATE_NEW_ITEM;
+ static DeclareMemType MTYPE_INVENTORY_VIEW_INIT;
+ static DeclareMemType MTYPE_INVENTORY_VIEW_SHOW;
+ static DeclareMemType MTYPE_INVENTORY_VIEW_TOGGLE;
+
+ static DeclareMemType MTYPE_ANIMATION;
+ static DeclareMemType MTYPE_VOLUME;
+ static DeclareMemType MTYPE_PRIMITIVE;
+
+ static DeclareMemType MTYPE_SCRIPT;
+ static DeclareMemType MTYPE_SCRIPT_RUN;
+ static DeclareMemType MTYPE_SCRIPT_BYTECODE;
+
+ static DeclareMemType MTYPE_IO_PUMP;
+ static DeclareMemType MTYPE_IO_TCP;
+ static DeclareMemType MTYPE_IO_BUFFER;
+ static DeclareMemType MTYPE_IO_HTTP_SERVER;
+ static DeclareMemType MTYPE_IO_SD_SERVER;
+ static DeclareMemType MTYPE_IO_SD_CLIENT;
+ static DeclareMemType MTYPE_IO_URL_REQUEST;
+
+ static DeclareMemType MTYPE_DIRECTX_INIT;
+
+ static DeclareMemType MTYPE_TEMP1;
+ static DeclareMemType MTYPE_TEMP2;
+ static DeclareMemType MTYPE_TEMP3;
+ static DeclareMemType MTYPE_TEMP4;
+ static DeclareMemType MTYPE_TEMP5;
+ static DeclareMemType MTYPE_TEMP6;
+ static DeclareMemType MTYPE_TEMP7;
+ static DeclareMemType MTYPE_TEMP8;
+ static DeclareMemType MTYPE_TEMP9;
+
+ static DeclareMemType MTYPE_OTHER; // Special; used by display code
+
+ S32 mTypeIndex;
};
//----------------------------------------------------------------------------
diff --git a/indra/llcommon/llmetrics.cpp b/indra/llcommon/llmetrics.cpp
index 8db3284c42..30e5d435ae 100644
--- a/indra/llcommon/llmetrics.cpp
+++ b/indra/llcommon/llmetrics.cpp
@@ -71,7 +71,7 @@ void LLMetricsImpl::recordEventDetails(const std::string& location,
metrics["location"] = location;
metrics["stats"] = stats;
- llinfos << "LLMETRICS: " << LLSDNotationStreamer(metrics) << llendl;
+ llinfos << "LLMETRICS: " << (LLSDNotationStreamer(metrics)) << llendl;
}
// Store this:
diff --git a/indra/llcommon/llmetrics.h b/indra/llcommon/llmetrics.h
index 1d91e8c8a2..f6f49eb456 100644
--- a/indra/llcommon/llmetrics.h
+++ b/indra/llcommon/llmetrics.h
@@ -38,7 +38,7 @@
class LLMetricsImpl;
class LLSD;
-class LLMetrics
+class LL_COMMON_API LLMetrics
{
public:
LLMetrics();
diff --git a/indra/llcommon/llmortician.h b/indra/llcommon/llmortician.h
index fcda3df58e..27bd8cd9b5 100644
--- a/indra/llcommon/llmortician.h
+++ b/indra/llcommon/llmortician.h
@@ -35,7 +35,7 @@
#include "stdtypes.h"
-class LLMortician
+class LL_COMMON_API LLMortician
{
public:
LLMortician() { mIsDead = FALSE; }
diff --git a/indra/llcommon/lloptioninterface.cpp b/indra/llcommon/lloptioninterface.cpp
new file mode 100644
index 0000000000..68c1ff1c41
--- /dev/null
+++ b/indra/llcommon/lloptioninterface.cpp
@@ -0,0 +1,39 @@
+/**
+ * @file lloptioninterface.cpp
+ * @brief
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "lloptioninterface.h"
+
+
+LLOptionInterface::~LLOptionInterface()
+{
+
+}
diff --git a/indra/llcommon/lloptioninterface.h b/indra/llcommon/lloptioninterface.h
new file mode 100644
index 0000000000..4faf95f5e1
--- /dev/null
+++ b/indra/llcommon/lloptioninterface.h
@@ -0,0 +1,46 @@
+/**
+ * @file lloptioninterface.h
+ * @brief
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLOPTIONINTERFACE_H
+#define LL_LLOPTIONINTERFACE_H
+
+#include "linden_common.h"
+
+class LLSD;
+class LLOptionInterface
+{
+public:
+ virtual ~LLOptionInterface() = 0;
+ virtual LLSD getOption(const std::string& name) const = 0;
+};
+
+#endif
diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
new file mode 100644
index 0000000000..2c37eadcc6
--- /dev/null
+++ b/indra/llcommon/llpointer.h
@@ -0,0 +1,177 @@
+/**
+ * @file llpointer.h
+ * @brief A reference-counted pointer for objects derived from LLRefCount
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef LLPOINTER_H
+#define LLPOINTER_H
+
+#include "llerror.h" // *TODO: consider eliminating this
+
+//----------------------------------------------------------------------------
+// RefCount objects should generally only be accessed by way of LLPointer<>'s
+// NOTE: LLPointer<LLFoo> x = new LLFoo(); MAY NOT BE THREAD SAFE
+// if LLFoo::LLFoo() does anything like put itself in an update queue.
+// The queue may get accessed before it gets assigned to x.
+// The correct implementation is:
+// LLPointer<LLFoo> x = new LLFoo; // constructor does not do anything interesting
+// x->instantiate(); // does stuff like place x into an update queue
+
+// see llthread.h for LLThreadSafeRefCount
+
+//----------------------------------------------------------------------------
+
+// Note: relies on Type having ref() and unref() methods
+template <class Type> class LLPointer
+{
+public:
+
+ LLPointer() :
+ mPointer(NULL)
+ {
+ }
+
+ LLPointer(Type* ptr) :
+ mPointer(ptr)
+ {
+ ref();
+ }
+
+ LLPointer(const LLPointer<Type>& ptr) :
+ mPointer(ptr.mPointer)
+ {
+ ref();
+ }
+
+ // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
+ template<typename Subclass>
+ LLPointer(const LLPointer<Subclass>& ptr) :
+ mPointer(ptr.get())
+ {
+ ref();
+ }
+
+ ~LLPointer()
+ {
+ unref();
+ }
+
+ Type* get() const { return mPointer; }
+ const Type* operator->() const { return mPointer; }
+ Type* operator->() { return mPointer; }
+ const Type& operator*() const { return *mPointer; }
+ Type& operator*() { return *mPointer; }
+
+ operator BOOL() const { return (mPointer != NULL); }
+ operator bool() const { return (mPointer != NULL); }
+ bool operator!() const { return (mPointer == NULL); }
+ bool isNull() const { return (mPointer == NULL); }
+ bool notNull() const { return (mPointer != NULL); }
+
+ operator Type*() const { return mPointer; }
+ operator const Type*() const { return mPointer; }
+ bool operator !=(Type* ptr) const { return (mPointer != ptr); }
+ bool operator ==(Type* ptr) const { return (mPointer == ptr); }
+ bool operator ==(const LLPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); }
+ bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
+ bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }
+
+ LLPointer<Type>& operator =(Type* ptr)
+ {
+ if( mPointer != ptr )
+ {
+ unref();
+ mPointer = ptr;
+ ref();
+ }
+
+ return *this;
+ }
+
+ LLPointer<Type>& operator =(const LLPointer<Type>& ptr)
+ {
+ if( mPointer != ptr.mPointer )
+ {
+ unref();
+ mPointer = ptr.mPointer;
+ ref();
+ }
+ return *this;
+ }
+
+ // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
+ template<typename Subclass>
+ LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr)
+ {
+ if( mPointer != ptr.get() )
+ {
+ unref();
+ mPointer = ptr.get();
+ ref();
+ }
+ return *this;
+ }
+
+ // Just exchange the pointers, which will not change the reference counts.
+ static void swap(LLPointer<Type>& a, LLPointer<Type>& b)
+ {
+ Type* temp = a.mPointer;
+ a.mPointer = b.mPointer;
+ b.mPointer = temp;
+ }
+
+protected:
+ void ref()
+ {
+ if (mPointer)
+ {
+ mPointer->ref();
+ }
+ }
+
+ void unref()
+ {
+ if (mPointer)
+ {
+ Type *tempp = mPointer;
+ mPointer = NULL;
+ tempp->unref();
+ if (mPointer != NULL)
+ {
+ llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
+ unref();
+ }
+ }
+ }
+
+protected:
+ Type* mPointer;
+};
+
+#endif
diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h
index 2e4fd4787a..5eefa6a16b 100644
--- a/indra/llcommon/llpreprocessor.h
+++ b/indra/llcommon/llpreprocessor.h
@@ -93,19 +93,8 @@
#endif
-// Deal with the differeneces on Windows
-#if LL_MSVC
-namespace snprintf_hack
-{
- int snprintf(char *str, size_t size, const char *format, ...);
-}
-
-// #define snprintf safe_snprintf /* Flawfinder: ignore */
-using snprintf_hack::snprintf;
-#endif // LL_MSVC
-
// Static linking with apr on windows needs to be declared.
-#ifdef LL_WINDOWS
+#if LL_WINDOWS && !LL_COMMON_LINK_SHARED
#ifndef APR_DECLARE_STATIC
#define APR_DECLARE_STATIC // For APR on Windows
#endif
@@ -117,7 +106,9 @@ using snprintf_hack::snprintf;
#if defined(LL_WINDOWS)
#define BOOST_REGEX_NO_LIB 1
#define CURL_STATICLIB 1
+#ifndef XML_STATIC
#define XML_STATIC
+#endif
#endif // LL_WINDOWS
@@ -127,12 +118,56 @@ using snprintf_hack::snprintf;
#pragma warning( 3 : 4702 ) // "unreachable code" Treat this as level 3, not level 4.
#pragma warning( 3 : 4189 ) // "local variable initialized but not referenced" Treat this as level 3, not level 4.
//#pragma warning( 3 : 4018 ) // "signed/unsigned mismatch" Treat this as level 3, not level 4.
+#pragma warning( 3 : 4263 ) // 'function' : member function does not override any base class virtual member function
+#pragma warning( 3 : 4264 ) // "'virtual_function' : no override available for virtual member function from base 'class'; function is hidden"
#pragma warning( 3 : 4265 ) // "class has virtual functions, but destructor is not virtual"
-#pragma warning( disable : 4786 ) // silly MS warning deep inside their <map> include file
+#pragma warning( 3 : 4266 ) // 'function' : no override available for virtual member function from base 'type'; function is hidden
+#pragma warning (disable : 4180) // qualifier applied to function type has no meaning; ignored
#pragma warning( disable : 4284 ) // silly MS warning deep inside their <map> include file
#pragma warning( disable : 4503 ) // 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation.
#pragma warning( disable : 4800 ) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)
#pragma warning( disable : 4996 ) // warning: deprecated
+
+// Linker optimization with "extern template" generates these warnings
+#pragma warning( disable : 4231 ) // nonstandard extension used : 'extern' before template explicit instantiation
+#pragma warning( disable : 4506 ) // no definition for inline function
+
+// level 4 warnings that we need to disable:
+#pragma warning (disable : 4100) // unreferenced formal parameter
+#pragma warning (disable : 4127) // conditional expression is constant (e.g. while(1) )
+#pragma warning (disable : 4244) // possible loss of data on conversions
+#pragma warning (disable : 4396) // the inline specifier cannot be used when a friend declaration refers to a specialization of a function template
+#pragma warning (disable : 4512) // assignment operator could not be generated
+#pragma warning (disable : 4706) // assignment within conditional (even if((x = y)) )
+
+#pragma warning (disable : 4251) // member needs to have dll-interface to be used by clients of class
+#pragma warning (disable : 4275) // non dll-interface class used as base for dll-interface class
#endif // LL_MSVC
+#if LL_WINDOWS
+#define LL_DLLEXPORT __declspec(dllexport)
+#define LL_DLLIMPORT __declspec(dllimport)
+#elif LL_LINUX
+#define LL_DLLEXPORT __attribute__ ((visibility("default")))
+#define LL_DLLIMPORT
+#else
+#define LL_DLLEXPORT
+#define LL_DLLIMPORT
+#endif // LL_WINDOWS
+
+#if LL_COMMON_LINK_SHARED
+// CMake automagically defines llcommon_EXPORTS only when building llcommon
+// sources, and only when llcommon is a shared library (i.e. when
+// LL_COMMON_LINK_SHARED). We must still test LL_COMMON_LINK_SHARED because
+// otherwise we can't distinguish between (non-llcommon source) and (llcommon
+// not shared).
+# if defined(llcommon_EXPORTS)
+# define LL_COMMON_API LL_DLLEXPORT
+# else //llcommon_EXPORTS
+# define LL_COMMON_API LL_DLLIMPORT
+# endif //llcommon_EXPORTS
+#else // LL_COMMON_LINK_SHARED
+# define LL_COMMON_API
+#endif // LL_COMMON_LINK_SHARED
+
#endif // not LL_LINDEN_PREPROCESSOR_H
diff --git a/indra/llcommon/llprocesslauncher.cpp b/indra/llcommon/llprocesslauncher.cpp
new file mode 100644
index 0000000000..f0315e92eb
--- /dev/null
+++ b/indra/llcommon/llprocesslauncher.cpp
@@ -0,0 +1,344 @@
+/**
+ * @file llprocesslauncher.cpp
+ * @brief Utility class for launching, terminating, and tracking the state of processes.
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llprocesslauncher.h"
+
+#include <iostream>
+#if LL_DARWIN || LL_LINUX
+// not required or present on Win32
+#include <sys/wait.h>
+#endif
+
+LLProcessLauncher::LLProcessLauncher()
+{
+#if LL_WINDOWS
+ mProcessHandle = 0;
+#else
+ mProcessID = 0;
+#endif
+}
+
+LLProcessLauncher::~LLProcessLauncher()
+{
+ kill();
+}
+
+void LLProcessLauncher::setExecutable(const std::string &executable)
+{
+ mExecutable = executable;
+}
+
+void LLProcessLauncher::setWorkingDirectory(const std::string &dir)
+{
+ mWorkingDir = dir;
+}
+
+void LLProcessLauncher::clearArguments()
+{
+ mLaunchArguments.clear();
+}
+
+void LLProcessLauncher::addArgument(const std::string &arg)
+{
+ mLaunchArguments.push_back(arg);
+}
+
+void LLProcessLauncher::addArgument(const char *arg)
+{
+ mLaunchArguments.push_back(std::string(arg));
+}
+
+#if LL_WINDOWS
+
+int LLProcessLauncher::launch(void)
+{
+ // If there was already a process associated with this object, kill it.
+ kill();
+ orphan();
+
+ int result = 0;
+
+ PROCESS_INFORMATION pinfo;
+ STARTUPINFOA sinfo;
+ memset(&sinfo, 0, sizeof(sinfo));
+
+ std::string args = mExecutable;
+ for(int i = 0; i < (int)mLaunchArguments.size(); i++)
+ {
+ args += " ";
+ args += mLaunchArguments[i];
+ }
+
+ // So retarded. Windows requires that the second parameter to CreateProcessA be a writable (non-const) string...
+ char *args2 = new char[args.size() + 1];
+ strcpy(args2, args.c_str());
+
+ if( ! CreateProcessA( NULL, args2, NULL, NULL, FALSE, 0, NULL, NULL, &sinfo, &pinfo ) )
+ {
+ // TODO: do better than returning the OS-specific error code on failure...
+ result = GetLastError();
+ if(result == 0)
+ {
+ // Make absolutely certain we return a non-zero value on failure.
+ result = -1;
+ }
+ }
+ else
+ {
+ // foo = pinfo.dwProcessId; // get your pid here if you want to use it later on
+ // CloseHandle(pinfo.hProcess); // stops leaks - nothing else
+ mProcessHandle = pinfo.hProcess;
+ CloseHandle(pinfo.hThread); // stops leaks - nothing else
+ }
+
+ delete[] args2;
+
+ return result;
+}
+
+bool LLProcessLauncher::isRunning(void)
+{
+ if(mProcessHandle != 0)
+ {
+ DWORD waitresult = WaitForSingleObject(mProcessHandle, 0);
+ if(waitresult == WAIT_OBJECT_0)
+ {
+ // the process has completed.
+ mProcessHandle = 0;
+ }
+ }
+
+ return (mProcessHandle != 0);
+}
+bool LLProcessLauncher::kill(void)
+{
+ bool result = true;
+
+ if(mProcessHandle != 0)
+ {
+ TerminateProcess(mProcessHandle,0);
+
+ if(isRunning())
+ {
+ result = false;
+ }
+ }
+
+ return result;
+}
+
+void LLProcessLauncher::orphan(void)
+{
+ // Forget about the process
+ mProcessHandle = 0;
+}
+
+// static
+void LLProcessLauncher::reap(void)
+{
+ // No actions necessary on Windows.
+}
+
+#else // Mac and linux
+
+#include <signal.h>
+#include <fcntl.h>
+#include <errno.h>
+
+static std::list<pid_t> sZombies;
+
+// Attempt to reap a process ID -- returns true if the process has exited and been reaped, false otherwise.
+static bool reap_pid(pid_t pid)
+{
+ bool result = false;
+
+ pid_t wait_result = ::waitpid(pid, NULL, WNOHANG);
+ if(wait_result == pid)
+ {
+ result = true;
+ }
+ else if(wait_result == -1)
+ {
+ if(errno == ECHILD)
+ {
+ // No such process -- this may mean we're ignoring SIGCHILD.
+ result = true;
+ }
+ }
+
+ return result;
+}
+
+int LLProcessLauncher::launch(void)
+{
+ // If there was already a process associated with this object, kill it.
+ kill();
+ orphan();
+
+ int result = 0;
+ int current_wd = -1;
+
+ // create an argv vector for the child process
+ const char ** fake_argv = new const char *[mLaunchArguments.size() + 2]; // 1 for the executable path, 1 for the NULL terminator
+
+ int i = 0;
+
+ // add the executable path
+ fake_argv[i++] = mExecutable.c_str();
+
+ // and any arguments
+ for(int j=0; j < mLaunchArguments.size(); j++)
+ fake_argv[i++] = mLaunchArguments[j].c_str();
+
+ // terminate with a null pointer
+ fake_argv[i] = NULL;
+
+ if(!mWorkingDir.empty())
+ {
+ // save the current working directory
+ current_wd = ::open(".", O_RDONLY);
+
+ // and change to the one the child will be executed in
+ if (::chdir(mWorkingDir.c_str()))
+ {
+ // chdir failed
+ }
+ }
+
+ // flush all buffers before the child inherits them
+ ::fflush(NULL);
+
+ pid_t id = vfork();
+ if(id == 0)
+ {
+ // child process
+
+ ::execv(mExecutable.c_str(), (char * const *)fake_argv);
+
+ // If we reach this point, the exec failed.
+ // Use _exit() instead of exit() per the vfork man page.
+ _exit(0);
+ }
+
+ // parent process
+
+ if(current_wd >= 0)
+ {
+ // restore the previous working directory
+ if (::fchdir(current_wd))
+ {
+ // chdir failed
+ }
+ ::close(current_wd);
+ }
+
+ delete[] fake_argv;
+
+ mProcessID = id;
+
+ // At this point, the child process will have been created (since that's how vfork works -- the child borrowed our execution context until it forked)
+ // If the process doesn't exist at this point, the exec failed.
+ if(!isRunning())
+ {
+ result = -1;
+ }
+
+ return result;
+}
+
+bool LLProcessLauncher::isRunning(void)
+{
+ if(mProcessID != 0)
+ {
+ // Check whether the process has exited, and reap it if it has.
+ if(reap_pid(mProcessID))
+ {
+ // the process has exited.
+ mProcessID = 0;
+ }
+ }
+
+ return (mProcessID != 0);
+}
+
+bool LLProcessLauncher::kill(void)
+{
+ bool result = true;
+
+ if(mProcessID != 0)
+ {
+ // Try to kill the process. We'll do approximately the same thing whether the kill returns an error or not, so we ignore the result.
+ (void)::kill(mProcessID, SIGTERM);
+
+ // This will have the side-effect of reaping the zombie if the process has exited.
+ if(isRunning())
+ {
+ result = false;
+ }
+ }
+
+ return result;
+}
+
+void LLProcessLauncher::orphan(void)
+{
+ // Disassociate the process from this object
+ if(mProcessID != 0)
+ {
+ // We may still need to reap the process's zombie eventually
+ sZombies.push_back(mProcessID);
+
+ mProcessID = 0;
+ }
+}
+
+// static
+void LLProcessLauncher::reap(void)
+{
+ // Attempt to real all saved process ID's.
+
+ std::list<pid_t>::iterator iter = sZombies.begin();
+ while(iter != sZombies.end())
+ {
+ if(reap_pid(*iter))
+ {
+ iter = sZombies.erase(iter);
+ }
+ else
+ {
+ iter++;
+ }
+ }
+}
+
+#endif
diff --git a/indra/llcommon/llprocesslauncher.h b/indra/llcommon/llprocesslauncher.h
new file mode 100644
index 0000000000..929d547f6e
--- /dev/null
+++ b/indra/llcommon/llprocesslauncher.h
@@ -0,0 +1,93 @@
+/**
+ * @file llprocesslauncher.h
+ * @brief Utility class for launching, terminating, and tracking the state of processes.
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPROCESSLAUNCHER_H
+#define LL_LLPROCESSLAUNCHER_H
+
+#if LL_WINDOWS
+#include <windows.h>
+#endif
+
+
+/*
+ LLProcessLauncher handles launching external processes with specified command line arguments.
+ It also keeps track of whether the process is still running, and can kill it if required.
+*/
+
+class LL_COMMON_API LLProcessLauncher
+{
+ LOG_CLASS(LLProcessLauncher);
+public:
+ LLProcessLauncher();
+ virtual ~LLProcessLauncher();
+
+ void setExecutable(const std::string &executable);
+ void setWorkingDirectory(const std::string &dir);
+
+ void clearArguments();
+ void addArgument(const std::string &arg);
+ void addArgument(const char *arg);
+
+ int launch(void);
+ bool isRunning(void);
+
+ // Attempt to kill the process -- returns true if the process is no longer running when it returns.
+ // Note that even if this returns false, the process may exit some time after it's called.
+ bool kill(void);
+
+ // Use this if you want the external process to continue execution after the LLProcessLauncher instance controlling it is deleted.
+ // Normally, the destructor will attempt to kill the process and wait for termination.
+ // This should only be used if the viewer is about to exit -- otherwise, the child process will become a zombie after it exits.
+ void orphan(void);
+
+ // This needs to be called periodically on Mac/Linux to clean up zombie processes.
+ static void reap(void);
+
+ // Accessors for platform-specific process ID
+#if LL_WINDOWS
+ HANDLE getProcessHandle() { return mProcessHandle; };
+#else
+ pid_t getProcessID() { return mProcessID; };
+#endif
+
+private:
+ std::string mExecutable;
+ std::string mWorkingDir;
+ std::vector<std::string> mLaunchArguments;
+
+#if LL_WINDOWS
+ HANDLE mProcessHandle;
+#else
+ pid_t mProcessID;
+#endif
+};
+
+#endif // LL_LLPROCESSLAUNCHER_H
diff --git a/indra/llcommon/llptrto.cpp b/indra/llcommon/llptrto.cpp
new file mode 100644
index 0000000000..ce93f09489
--- /dev/null
+++ b/indra/llcommon/llptrto.cpp
@@ -0,0 +1,108 @@
+/**
+ * @file llptrto.cpp
+ * @author Nat Goodspeed
+ * @date 2008-08-20
+ * @brief Test for llptrto.h
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llptrto.h"
+// STL headers
+// std headers
+// external library headers
+#include <boost/type_traits/is_same.hpp>
+#include <boost/static_assert.hpp>
+// other Linden headers
+#include "llmemory.h"
+
+// a refcounted class
+class RCFoo: public LLRefCount
+{
+public:
+ RCFoo() {}
+};
+
+// a refcounted subclass
+class RCSubFoo: public RCFoo
+{
+public:
+ RCSubFoo() {}
+};
+
+// a refcounted class using the other refcount base class
+class TSRCFoo: public LLThreadSafeRefCount
+{
+public:
+ TSRCFoo() {}
+};
+
+// a non-refcounted class
+class Bar
+{
+public:
+ Bar() {}
+};
+
+// a non-refcounted subclass
+class SubBar: public Bar
+{
+public:
+ SubBar() {}
+};
+
+int main(int argc, char *argv[])
+{
+ // test LLPtrTo<>
+ BOOST_STATIC_ASSERT((boost::is_same<LLPtrTo<RCFoo>::type, LLPointer<RCFoo> >::value));
+ BOOST_STATIC_ASSERT((boost::is_same<LLPtrTo<RCSubFoo>::type, LLPointer<RCSubFoo> >::value));
+ BOOST_STATIC_ASSERT((boost::is_same<LLPtrTo<TSRCFoo>::type, LLPointer<TSRCFoo> >::value));
+ BOOST_STATIC_ASSERT((boost::is_same<LLPtrTo<Bar>::type, Bar*>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<LLPtrTo<SubBar>::type, SubBar*>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<LLPtrTo<int>::type, int*>::value));
+
+ // Test LLRemovePointer<>. Note that we remove both pointer variants from
+ // each kind of type, regardless of whether the variant makes sense.
+ BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer<RCFoo*>::type, RCFoo>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer< LLPointer<RCFoo> >::type, RCFoo>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer<RCSubFoo*>::type, RCSubFoo>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer< LLPointer<RCSubFoo> >::type, RCSubFoo>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer<TSRCFoo*>::type, TSRCFoo>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer< LLPointer<TSRCFoo> >::type, TSRCFoo>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer<Bar*>::type, Bar>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer< LLPointer<Bar> >::type, Bar>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer<SubBar*>::type, SubBar>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer< LLPointer<SubBar> >::type, SubBar>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer<int*>::type, int>::value));
+ BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer< LLPointer<int> >::type, int>::value));
+
+ return 0;
+}
diff --git a/indra/llcommon/llptrto.h b/indra/llcommon/llptrto.h
new file mode 100644
index 0000000000..74c117a7f6
--- /dev/null
+++ b/indra/llcommon/llptrto.h
@@ -0,0 +1,93 @@
+/**
+ * @file llptrto.h
+ * @author Nat Goodspeed
+ * @date 2008-08-19
+ * @brief LLPtrTo<TARGET> is a template helper to pick either TARGET* or -- when
+ * TARGET is a subclass of LLRefCount or LLThreadSafeRefCount --
+ * LLPointer<TARGET>. LLPtrTo<> chooses whichever pointer type is best.
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLPTRTO_H)
+#define LL_LLPTRTO_H
+
+#include "llpointer.h"
+#include "llrefcount.h" // LLRefCount
+#include "llthread.h" // LLThreadSafeRefCount
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/type_traits/remove_pointer.hpp>
+#include <boost/utility/enable_if.hpp>
+
+/**
+ * LLPtrTo<TARGET>::type is either of two things:
+ *
+ * * When TARGET is a subclass of either LLRefCount or LLThreadSafeRefCount,
+ * LLPtrTo<TARGET>::type is LLPointer<TARGET>.
+ * * Otherwise, LLPtrTo<TARGET>::type is TARGET*.
+ *
+ * This way, a class template can use LLPtrTo<TARGET>::type to select an
+ * appropriate pointer type to store.
+ */
+template <class T, class ENABLE=void>
+struct LLPtrTo
+{
+ typedef T* type;
+};
+
+/// specialize for subclasses of LLRefCount
+template <class T>
+struct LLPtrTo<T, typename boost::enable_if< boost::is_base_of<LLRefCount, T> >::type>
+{
+ typedef LLPointer<T> type;
+};
+
+/// specialize for subclasses of LLThreadSafeRefCount
+template <class T>
+struct LLPtrTo<T, typename boost::enable_if< boost::is_base_of<LLThreadSafeRefCount, T> >::type>
+{
+ typedef LLPointer<T> type;
+};
+
+/**
+ * LLRemovePointer<PTRTYPE>::type gets you the underlying (pointee) type.
+ */
+template <typename PTRTYPE>
+struct LLRemovePointer
+{
+ typedef typename boost::remove_pointer<PTRTYPE>::type type;
+};
+
+/// specialize for LLPointer<SOMECLASS>
+template <typename SOMECLASS>
+struct LLRemovePointer< LLPointer<SOMECLASS> >
+{
+ typedef SOMECLASS type;
+};
+
+#endif /* ! defined(LL_LLPTRTO_H) */
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index cd53e701d2..06ceeb2bc3 100644
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -31,7 +31,9 @@
#include "linden_common.h"
#include "llqueuedthread.h"
+
#include "llstl.h"
+#include "lltimer.h" // ms_sleep()
//============================================================================
@@ -40,7 +42,8 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) :
LLThread(name),
mThreaded(threaded),
mIdleThread(TRUE),
- mNextHandle(0)
+ mNextHandle(0),
+ mStarted(FALSE)
{
if (mThreaded)
{
@@ -51,6 +54,10 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) :
// MAIN THREAD
LLQueuedThread::~LLQueuedThread()
{
+ if (!mThreaded)
+ {
+ endThread();
+ }
shutdown();
// ~LLThread() will be called here
}
@@ -89,6 +96,7 @@ void LLQueuedThread::shutdown()
if (req->getStatus() == STATUS_QUEUED || req->getStatus() == STATUS_INPROGRESS)
{
++active_count;
+ req->setStatus(STATUS_ABORTED); // avoid assert in deleteRequest
}
req->deleteRequest();
}
@@ -104,6 +112,14 @@ void LLQueuedThread::shutdown()
// virtual
S32 LLQueuedThread::update(U32 max_time_ms)
{
+ if (!mStarted)
+ {
+ if (!mThreaded)
+ {
+ startThread();
+ mStarted = TRUE;
+ }
+ }
return updateQueue(max_time_ms);
}
@@ -421,6 +437,7 @@ S32 LLQueuedThread::processNextRequest()
if (req)
{
// process request
+ U32 start_priority = req->getPriority();
bool complete = req->processRequest();
if (complete)
@@ -441,35 +458,20 @@ S32 LLQueuedThread::processNextRequest()
lockData();
req->setStatus(STATUS_QUEUED);
mRequestQueue.insert(req);
- U32 priority = req->getPriority();
unlockData();
- if (priority < PRIORITY_NORMAL)
+ if (mThreaded && start_priority <= PRIORITY_LOW)
{
ms_sleep(1); // sleep the thread a little
}
}
}
- S32 res;
S32 pending = getPending();
- if (pending == 0)
- {
- if (isQuitting())
- {
- res = -1; // exit thread
- }
- else
- {
- res = 0;
- }
- }
- else
- {
- res = pending;
- }
- return res;
+
+ return pending;
}
+// virtual
bool LLQueuedThread::runCondition()
{
// mRunCondition must be locked here
@@ -479,35 +481,53 @@ bool LLQueuedThread::runCondition()
return true;
}
+// virtual
void LLQueuedThread::run()
{
+ // call checPause() immediately so we don't try to do anything before the class is fully constructed
+ checkPause();
+ startThread();
+ mStarted = TRUE;
+
while (1)
{
// this will block on the condition until runCondition() returns true, the thread is unpaused, or the thread leaves the RUNNING state.
checkPause();
- if(isQuitting())
+ if (isQuitting())
+ {
+ endThread();
break;
-
- //llinfos << "QUEUED THREAD RUNNING, queue size = " << mRequestQueue.size() << llendl;
+ }
mIdleThread = FALSE;
+
+ threadedUpdate();
int res = processNextRequest();
if (res == 0)
{
mIdleThread = TRUE;
+ ms_sleep(1);
}
-
- if (res < 0) // finished working and want to exit
- {
- break;
- }
-
//LLThread::yield(); // thread should yield after each request
}
+ llinfos << "LLQueuedThread " << mName << " EXITING." << llendl;
+}
+
+// virtual
+void LLQueuedThread::startThread()
+{
+}
- llinfos << "QUEUED THREAD " << mName << " EXITING." << llendl;
+// virtual
+void LLQueuedThread::endThread()
+{
+}
+
+// virtual
+void LLQueuedThread::threadedUpdate()
+{
}
//============================================================================
diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h
index 3ba43e1e07..9a9dbb18cc 100644
--- a/indra/llcommon/llqueuedthread.h
+++ b/indra/llcommon/llqueuedthread.h
@@ -47,7 +47,7 @@
// Note: ~LLQueuedThread is O(N) N=# of queued threads, assumed to be small
// It is assumed that LLQueuedThreads are rarely created/destroyed.
-class LLQueuedThread : public LLThread
+class LL_COMMON_API LLQueuedThread : public LLThread
{
//------------------------------------------------------------------------
public:
@@ -80,7 +80,7 @@ public:
//------------------------------------------------------------------------
public:
- class QueuedRequest : public LLSimpleHashEntry<handle_t>
+ class LL_COMMON_API QueuedRequest : public LLSimpleHashEntry<handle_t>
{
friend class LLQueuedThread;
@@ -148,6 +148,7 @@ protected:
}
};
+
//------------------------------------------------------------------------
public:
@@ -165,6 +166,9 @@ private:
virtual bool runCondition(void);
virtual void run(void);
+ virtual void startThread(void);
+ virtual void endThread(void);
+ virtual void threadedUpdate(void);
protected:
handle_t generateHandle();
@@ -199,6 +203,7 @@ public:
protected:
BOOL mThreaded; // if false, run on main thread and do updates during update()
+ BOOL mStarted; // required when mThreaded is false to call startThread() from update()
LLAtomic32<BOOL> mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
typedef std::set<QueuedRequest*, queued_request_less> request_queue_t;
diff --git a/indra/llcommon/llrand.h b/indra/llcommon/llrand.h
index d12597bb53..30fec9b982 100644
--- a/indra/llcommon/llrand.h
+++ b/indra/llcommon/llrand.h
@@ -65,32 +65,32 @@
/**
*@brief Generate a float from [0, RAND_MAX).
*/
-S32 ll_rand();
+S32 LL_COMMON_API ll_rand();
/**
*@brief Generate a float from [0, val) or (val, 0].
*/
-S32 ll_rand(S32 val);
+S32 LL_COMMON_API ll_rand(S32 val);
/**
*@brief Generate a float from [0, 1.0).
*/
-F32 ll_frand();
+F32 LL_COMMON_API ll_frand();
/**
*@brief Generate a float from [0, val) or (val, 0].
*/
-F32 ll_frand(F32 val);
+F32 LL_COMMON_API ll_frand(F32 val);
/**
*@brief Generate a double from [0, 1.0).
*/
-F64 ll_drand();
+F64 LL_COMMON_API ll_drand();
/**
*@brief Generate a double from [0, val) or (val, 0].
*/
-F64 ll_drand(F64 val);
+F64 LL_COMMON_API ll_drand(F64 val);
/**
* @brief typedefs for good boost lagged fibonacci.
diff --git a/indra/llcommon/llrefcount.cpp b/indra/llcommon/llrefcount.cpp
new file mode 100644
index 0000000000..33b6875fb0
--- /dev/null
+++ b/indra/llcommon/llrefcount.cpp
@@ -0,0 +1,49 @@
+/**
+ * @file llrefcount.cpp
+ * @brief Base class for reference counted objects for use with LLPointer
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+
+#include "llrefcount.h"
+
+#include "llerror.h"
+
+LLRefCount::LLRefCount() :
+ mRef(0)
+{
+}
+
+LLRefCount::~LLRefCount()
+{
+ if (mRef != 0)
+ {
+ llerrs << "deleting non-zero reference" << llendl;
+ }
+}
diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h
new file mode 100644
index 0000000000..9ab844eb22
--- /dev/null
+++ b/indra/llcommon/llrefcount.h
@@ -0,0 +1,79 @@
+/**
+ * @file llrefcount.h
+ * @brief Base class for reference counted objects for use with LLPointer
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef LLREFCOUNT_H
+#define LLREFCOUNT_H
+
+#include <boost/noncopyable.hpp>
+
+//----------------------------------------------------------------------------
+// RefCount objects should generally only be accessed by way of LLPointer<>'s
+// see llthread.h for LLThreadSafeRefCount
+//----------------------------------------------------------------------------
+
+class LL_COMMON_API LLRefCount
+{
+private:
+ LLRefCount(const LLRefCount& other); // no implementation
+private:
+ LLRefCount& operator=(const LLRefCount&); // no implementation
+protected:
+ virtual ~LLRefCount(); // use unref()
+
+public:
+ LLRefCount();
+
+ void ref()
+ {
+ mRef++;
+ }
+
+ S32 unref()
+ {
+ llassert(mRef >= 1);
+ if (0 == --mRef)
+ {
+ delete this;
+ return 0;
+ }
+ return mRef;
+ }
+
+ S32 getNumRefs() const
+ {
+ return mRef;
+ }
+
+private:
+ S32 mRef;
+};
+
+#endif
diff --git a/indra/llcommon/llrun.h b/indra/llcommon/llrun.h
index 77b23d9051..1fc9925df9 100644
--- a/indra/llcommon/llrun.h
+++ b/indra/llcommon/llrun.h
@@ -48,7 +48,7 @@ class LLRunnable;
* which are scheduled to run on a repeating or one time basis.
* @see LLRunnable
*/
-class LLRunner
+class LL_COMMON_API LLRunner
{
public:
/**
@@ -149,7 +149,7 @@ protected:
* something useful.
* @see LLRunner
*/
-class LLRunnable
+class LL_COMMON_API LLRunnable
{
public:
LLRunnable();
diff --git a/indra/llcommon/llsafehandle.h b/indra/llcommon/llsafehandle.h
new file mode 100644
index 0000000000..5862f1a341
--- /dev/null
+++ b/indra/llcommon/llsafehandle.h
@@ -0,0 +1,168 @@
+/**
+ * @file llsafehandle.h
+ * @brief Reference-counted object where Object() is valid, not NULL.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef LLSAFEHANDLE_H
+#define LLSAFEHANDLE_H
+
+#include "llerror.h" // *TODO: consider eliminating this
+
+// Expands LLPointer to return a pointer to a special instance of class Type instead of NULL.
+// This is useful in instances where operations on NULL pointers are semantically safe and/or
+// when error checking occurs at a different granularity or in a different part of the code
+// than when referencing an object via a LLSafeHandle.
+
+template <class Type>
+class LLSafeHandle
+{
+public:
+ LLSafeHandle() :
+ mPointer(NULL)
+ {
+ }
+
+ LLSafeHandle(Type* ptr) :
+ mPointer(NULL)
+ {
+ assign(ptr);
+ }
+
+ LLSafeHandle(const LLSafeHandle<Type>& ptr) :
+ mPointer(NULL)
+ {
+ assign(ptr.mPointer);
+ }
+
+ // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
+ template<typename Subclass>
+ LLSafeHandle(const LLSafeHandle<Subclass>& ptr) :
+ mPointer(NULL)
+ {
+ assign(ptr.get());
+ }
+
+ ~LLSafeHandle()
+ {
+ unref();
+ }
+
+ const Type* operator->() const { return nonNull(mPointer); }
+ Type* operator->() { return nonNull(mPointer); }
+
+ Type* get() const { return mPointer; }
+ void clear() { assign(NULL); }
+ // we disallow these operations as they expose our null objects to direct manipulation
+ // and bypass the reference counting semantics
+ //const Type& operator*() const { return *nonNull(mPointer); }
+ //Type& operator*() { return *nonNull(mPointer); }
+
+ operator BOOL() const { return mPointer != NULL; }
+ operator bool() const { return mPointer != NULL; }
+ bool operator!() const { return mPointer == NULL; }
+ bool isNull() const { return mPointer == NULL; }
+ bool notNull() const { return mPointer != NULL; }
+
+
+ operator Type*() const { return mPointer; }
+ operator const Type*() const { return mPointer; }
+ bool operator !=(Type* ptr) const { return (mPointer != ptr); }
+ bool operator ==(Type* ptr) const { return (mPointer == ptr); }
+ bool operator ==(const LLSafeHandle<Type>& ptr) const { return (mPointer == ptr.mPointer); }
+ bool operator < (const LLSafeHandle<Type>& ptr) const { return (mPointer < ptr.mPointer); }
+ bool operator > (const LLSafeHandle<Type>& ptr) const { return (mPointer > ptr.mPointer); }
+
+ LLSafeHandle<Type>& operator =(Type* ptr)
+ {
+ assign(ptr);
+ return *this;
+ }
+
+ LLSafeHandle<Type>& operator =(const LLSafeHandle<Type>& ptr)
+ {
+ assign(ptr.mPointer);
+ return *this;
+ }
+
+ // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
+ template<typename Subclass>
+ LLSafeHandle<Type>& operator =(const LLSafeHandle<Subclass>& ptr)
+ {
+ assign(ptr.get());
+ return *this;
+ }
+
+public:
+ typedef Type* (*NullFunc)();
+ static const NullFunc sNullFunc;
+
+protected:
+ void ref()
+ {
+ if (mPointer)
+ {
+ mPointer->ref();
+ }
+ }
+
+ void unref()
+ {
+ if (mPointer)
+ {
+ Type *tempp = mPointer;
+ mPointer = NULL;
+ tempp->unref();
+ if (mPointer != NULL)
+ {
+ llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
+ unref();
+ }
+ }
+ }
+
+ void assign(Type* ptr)
+ {
+ if( mPointer != ptr )
+ {
+ unref();
+ mPointer = ptr;
+ ref();
+ }
+ }
+
+ static Type* nonNull(Type* ptr)
+ {
+ return ptr == NULL ? sNullFunc() : ptr;
+ }
+
+protected:
+ Type* mPointer;
+};
+
+#endif
diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp
index 2cc94c2914..c863d4e266 100644
--- a/indra/llcommon/llsd.cpp
+++ b/indra/llcommon/llsd.cpp
@@ -162,6 +162,7 @@ namespace
virtual LLSD::Type type() const { return T; }
+ using LLSD::Impl::assign; // Unhiding base class virtuals...
virtual void assign(LLSD::Impl*& var, DataRef value) {
if (shared())
{
@@ -349,8 +350,12 @@ namespace
virtual LLSD::Boolean asBoolean() const { return !mData.empty(); }
virtual bool has(const LLSD::String&) const;
+
+ using LLSD::Impl::get; // Unhiding get(LLSD::Integer)
+ using LLSD::Impl::erase; // Unhiding erase(LLSD::Integer)
+ using LLSD::Impl::ref; // Unhiding ref(LLSD::Integer)
virtual LLSD get(const LLSD::String&) const;
- LLSD& insert(const LLSD::String& k, const LLSD& v);
+ void insert(const LLSD::String& k, const LLSD& v);
virtual void erase(const LLSD::String&);
LLSD& ref(const LLSD::String&);
virtual const LLSD& ref(const LLSD::String&) const;
@@ -389,14 +394,9 @@ namespace
return (i != mData.end()) ? i->second : LLSD();
}
- LLSD& ImplMap::insert(const LLSD::String& k, const LLSD& v)
+ void ImplMap::insert(const LLSD::String& k, const LLSD& v)
{
mData.insert(DataMap::value_type(k, v));
- #ifdef LL_MSVC7
- return *((LLSD*)this);
- #else
- return *dynamic_cast<LLSD*>(this);
- #endif
}
void ImplMap::erase(const LLSD::String& k)
@@ -439,10 +439,13 @@ namespace
virtual LLSD::Boolean asBoolean() const { return !mData.empty(); }
+ using LLSD::Impl::get; // Unhiding get(LLSD::String)
+ using LLSD::Impl::erase; // Unhiding erase(LLSD::String)
+ using LLSD::Impl::ref; // Unhiding ref(LLSD::String)
virtual int size() const;
virtual LLSD get(LLSD::Integer) const;
void set(LLSD::Integer, const LLSD&);
- LLSD& insert(LLSD::Integer, const LLSD&);
+ void insert(LLSD::Integer, const LLSD&);
void append(const LLSD&);
virtual void erase(LLSD::Integer);
LLSD& ref(LLSD::Integer);
@@ -491,14 +494,10 @@ namespace
mData[index] = v;
}
- LLSD& ImplArray::insert(LLSD::Integer i, const LLSD& v)
+ void ImplArray::insert(LLSD::Integer i, const LLSD& v)
{
if (i < 0) {
- #ifdef LL_MSVC7
- return *((LLSD*)this);
- #else
- return *dynamic_cast<LLSD*>(this);
- #endif
+ return;
}
DataVector::size_type index = i;
@@ -508,11 +507,6 @@ namespace
}
mData.insert(mData.begin() + index, v);
- #ifdef LL_MSVC7
- return *((LLSD*)this);
- #else
- return *dynamic_cast<LLSD*>(this);
- #endif
}
void ImplArray::append(const LLSD& v)
@@ -755,11 +749,12 @@ LLSD LLSD::emptyMap()
bool LLSD::has(const String& k) const { return safe(impl).has(k); }
LLSD LLSD::get(const String& k) const { return safe(impl).get(k); }
+void LLSD::insert(const String& k, const LLSD& v) { makeMap(impl).insert(k, v); }
-LLSD& LLSD::insert(const String& k, const LLSD& v)
+LLSD& LLSD::with(const String& k, const LLSD& v)
{
makeMap(impl).insert(k, v);
- return *dynamic_cast<LLSD*>(this);
+ return *this;
}
void LLSD::erase(const String& k) { makeMap(impl).erase(k); }
@@ -780,8 +775,9 @@ int LLSD::size() const { return safe(impl).size(); }
LLSD LLSD::get(Integer i) const { return safe(impl).get(i); }
void LLSD::set(Integer i, const LLSD& v){ makeArray(impl).set(i, v); }
+void LLSD::insert(Integer i, const LLSD& v) { makeArray(impl).insert(i, v); }
-LLSD& LLSD::insert(Integer i, const LLSD& v)
+LLSD& LLSD::with(Integer i, const LLSD& v)
{
makeArray(impl).insert(i, v);
return *this;
@@ -811,9 +807,15 @@ static const char *llsd_dump(const LLSD &llsd, bool useXMLFormat)
{
std::ostringstream out;
if (useXMLFormat)
- out << LLSDXMLStreamer(llsd);
+ {
+ LLSDXMLStreamer xml_streamer(llsd);
+ out << xml_streamer;
+ }
else
- out << LLSDNotationStreamer(llsd);
+ {
+ LLSDNotationStreamer notation_streamer(llsd);
+ out << notation_streamer;
+ }
out_string = out.str();
}
int len = out_string.length();
diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h
index d2845a3757..135133c19c 100644
--- a/indra/llcommon/llsd.h
+++ b/indra/llcommon/llsd.h
@@ -89,7 +89,7 @@
@nosubgrouping
*/
-class LLSD
+class LL_COMMON_API LLSD
{
public:
LLSD(); ///< initially Undefined
@@ -223,8 +223,9 @@ public:
bool has(const String&) const;
LLSD get(const String&) const;
- LLSD& insert(const String&, const LLSD&);
+ void insert(const String&, const LLSD&);
void erase(const String&);
+ LLSD& with(const String&, const LLSD&);
LLSD& operator[](const String&);
LLSD& operator[](const char* c) { return (*this)[String(c)]; }
@@ -238,9 +239,10 @@ public:
LLSD get(Integer) const;
void set(Integer, const LLSD&);
- LLSD& insert(Integer, const LLSD&);
+ void insert(Integer, const LLSD&);
void append(const LLSD&);
void erase(Integer);
+ LLSD& with(Integer, const LLSD&);
const LLSD& operator[](Integer) const;
LLSD& operator[](Integer);
@@ -387,7 +389,7 @@ struct llsd_select_string : public std::unary_function<LLSD, LLSD::String>
}
};
-std::ostream& operator<<(std::ostream& s, const LLSD& llsd);
+LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLSD& llsd);
/** QUESTIONS & TO DOS
- Would Binary be more convenient as usigned char* buffer semantics?
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 7a66d70d3f..cf337be161 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -34,7 +34,7 @@
#include "linden_common.h"
#include "llsdserialize.h"
-#include "llmemory.h"
+#include "llpointer.h"
#include "llstreamtools.h" // for fullread
#include <iostream>
diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h
index bb38b75d8f..2f2b292189 100644
--- a/indra/llcommon/llsdserialize.h
+++ b/indra/llcommon/llsdserialize.h
@@ -36,14 +36,15 @@
#define LL_LLSDSERIALIZE_H
#include <iosfwd>
+#include "llpointer.h"
+#include "llrefcount.h"
#include "llsd.h"
-#include "llmemory.h"
/**
* @class LLSDParser
* @brief Abstract base class for LLSD parsers.
*/
-class LLSDParser : public LLRefCount
+class LL_COMMON_API LLSDParser : public LLRefCount
{
protected:
/**
@@ -220,7 +221,7 @@ protected:
* @class LLSDNotationParser
* @brief Parser which handles the original notation format for LLSD.
*/
-class LLSDNotationParser : public LLSDParser
+class LL_COMMON_API LLSDNotationParser : public LLSDParser
{
protected:
/**
@@ -293,7 +294,7 @@ private:
* @class LLSDXMLParser
* @brief Parser which handles XML format LLSD.
*/
-class LLSDXMLParser : public LLSDParser
+class LL_COMMON_API LLSDXMLParser : public LLSDParser
{
protected:
/**
@@ -341,7 +342,7 @@ private:
* @class LLSDBinaryParser
* @brief Parser which handles binary formatted LLSD.
*/
-class LLSDBinaryParser : public LLSDParser
+class LL_COMMON_API LLSDBinaryParser : public LLSDParser
{
protected:
/**
@@ -406,7 +407,7 @@ private:
* @class LLSDFormatter
* @brief Abstract base class for formatting LLSD.
*/
-class LLSDFormatter : public LLRefCount
+class LL_COMMON_API LLSDFormatter : public LLRefCount
{
protected:
/**
@@ -478,7 +479,7 @@ protected:
* @class LLSDNotationFormatter
* @brief Formatter which outputs the original notation format for LLSD.
*/
-class LLSDNotationFormatter : public LLSDFormatter
+class LL_COMMON_API LLSDNotationFormatter : public LLSDFormatter
{
protected:
/**
@@ -519,7 +520,7 @@ public:
* @class LLSDXMLFormatter
* @brief Formatter which outputs the LLSD as XML.
*/
-class LLSDXMLFormatter : public LLSDFormatter
+class LL_COMMON_API LLSDXMLFormatter : public LLSDFormatter
{
protected:
/**
@@ -587,7 +588,7 @@ protected:
* Map: '{' + 4 byte integer size every(key + value) + '}'<br>
* map keys are serialized as 'k' + 4 byte integer size + string
*/
-class LLSDBinaryFormatter : public LLSDFormatter
+class LL_COMMON_API LLSDBinaryFormatter : public LLSDFormatter
{
protected:
/**
@@ -637,9 +638,14 @@ protected:
* params << "[{'version':i1}," << LLSDOStreamer<LLSDNotationFormatter>(sd)
* << "]";
* </code>
+ *
+ * *NOTE - formerly this class inherited from its template parameter Formatter,
+ * but all insnatiations passed in LLRefCount subclasses. This conflicted with
+ * the auto allocation intended for this class template (demonstrated in the
+ * example above). -brad
*/
template <class Formatter>
-class LLSDOStreamer : public Formatter
+class LLSDOStreamer
{
public:
/**
@@ -660,7 +666,8 @@ public:
std::ostream& str,
const LLSDOStreamer<Formatter>& formatter)
{
- formatter.format(formatter.mSD, str, formatter.mOptions);
+ LLPointer<Formatter> f = new Formatter;
+ f->format(formatter.mSD, str, formatter.mOptions);
return str;
}
@@ -676,7 +683,7 @@ typedef LLSDOStreamer<LLSDXMLFormatter> LLSDXMLStreamer;
* @class LLSDSerialize
* @brief Serializer / deserializer for the various LLSD formats
*/
-class LLSDSerialize
+class LL_COMMON_API LLSDSerialize
{
public:
enum ELLSD_Serialize
diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp
index c12ca350de..7e1c2e35e0 100644
--- a/indra/llcommon/llsdserialize_xml.cpp
+++ b/indra/llcommon/llsdserialize_xml.cpp
@@ -37,6 +37,7 @@
#include <deque>
#include "apr_base64.h"
+#include <boost/regex.hpp>
extern "C"
{
@@ -777,10 +778,17 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name)
case ELEMENT_BINARY:
{
- S32 len = apr_base64_decode_len(mCurrentContent.c_str());
+ // Regex is expensive, but only fix for whitespace in base64,
+ // created by python and other non-linden systems - DEV-39358
+ // Fortunately we have very little binary passing now,
+ // so performance impact shold be negligible. + poppy 2009-09-04
+ boost::regex r;
+ r.assign("\\s");
+ std::string stripped = boost::regex_replace(mCurrentContent, r, "");
+ S32 len = apr_base64_decode_len(stripped.c_str());
std::vector<U8> data;
data.resize(len);
- len = apr_base64_decode_binary(&data[0], mCurrentContent.c_str());
+ len = apr_base64_decode_binary(&data[0], stripped.c_str());
data.resize(len);
value = data;
break;
diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp
index aa0e0f3696..c8d8030e87 100644
--- a/indra/llcommon/llsdutil.cpp
+++ b/indra/llcommon/llsdutil.cpp
@@ -46,6 +46,11 @@
#endif
#include "llsdserialize.h"
+#include "stringize.h"
+
+#include <map>
+#include <set>
+#include <boost/range.hpp>
// U32
LLSD ll_sd_from_U32(const U32 val)
@@ -171,6 +176,15 @@ char* ll_print_sd(const LLSD& sd)
return buffer;
}
+char* ll_pretty_print_sd_ptr(const LLSD* sd)
+{
+ if (sd)
+ {
+ return ll_pretty_print_sd(*sd);
+ }
+ return NULL;
+}
+
char* ll_pretty_print_sd(const LLSD& sd)
{
const U32 bufferSize = 10 * 1024;
@@ -304,3 +318,353 @@ BOOL compare_llsd_with_template(
return TRUE;
}
+
+/*****************************************************************************
+* Helpers for llsd_matches()
+*****************************************************************************/
+// raw data used for LLSD::Type lookup
+struct Data
+{
+ LLSD::Type type;
+ const char* name;
+} typedata[] =
+{
+#define def(type) { LLSD::type, #type + 4 }
+ def(TypeUndefined),
+ def(TypeBoolean),
+ def(TypeInteger),
+ def(TypeReal),
+ def(TypeString),
+ def(TypeUUID),
+ def(TypeDate),
+ def(TypeURI),
+ def(TypeBinary),
+ def(TypeMap),
+ def(TypeArray)
+#undef def
+};
+
+// LLSD::Type lookup class into which we load the above static data
+class TypeLookup
+{
+ typedef std::map<LLSD::Type, std::string> MapType;
+
+public:
+ TypeLookup()
+ {
+ for (const Data *di(boost::begin(typedata)), *dend(boost::end(typedata)); di != dend; ++di)
+ {
+ mMap[di->type] = di->name;
+ }
+ }
+
+ std::string lookup(LLSD::Type type) const
+ {
+ MapType::const_iterator found = mMap.find(type);
+ if (found != mMap.end())
+ {
+ return found->second;
+ }
+ return STRINGIZE("<unknown LLSD type " << type << ">");
+ }
+
+private:
+ MapType mMap;
+};
+
+// static instance of the lookup class
+static const TypeLookup sTypes;
+
+// describe a mismatch; phrasing may want tweaking
+const std::string op(" required instead of ");
+
+// llsd_matches() wants to identify specifically where in a complex prototype
+// structure the mismatch occurred. This entails passing a prefix string,
+// empty for the top-level call. If the prototype contains an array of maps,
+// and the mismatch occurs in the second map in a key 'foo', we want to
+// decorate the returned string with: "[1]['foo']: etc." On the other hand, we
+// want to omit the entire prefix -- including colon -- if the mismatch is at
+// top level. This helper accepts the (possibly empty) recursively-accumulated
+// prefix string, returning either empty or the original string with colon
+// appended.
+static std::string colon(const std::string& pfx)
+{
+ if (pfx.empty())
+ return pfx;
+ return pfx + ": ";
+}
+
+// param type for match_types
+typedef std::vector<LLSD::Type> TypeVector;
+
+// The scalar cases in llsd_matches() use this helper. In most cases, we can
+// accept not only the exact type specified in the prototype, but also other
+// types convertible to the expected type. That implies looping over an array
+// of such types. If the actual type doesn't match any of them, we want to
+// provide a list of acceptable conversions as well as the exact type, e.g.:
+// "Integer (or Boolean, Real, String) required instead of UUID". Both the
+// implementation and the calling logic are simplified by separating out the
+// expected type from the convertible types.
+static std::string match_types(LLSD::Type expect, // prototype.type()
+ const TypeVector& accept, // types convertible to that type
+ LLSD::Type actual, // type we're checking
+ const std::string& pfx) // as for llsd_matches
+{
+ // Trivial case: if the actual type is exactly what we expect, we're good.
+ if (actual == expect)
+ return "";
+
+ // For the rest of the logic, build up a suitable error string as we go so
+ // we only have to make a single pass over the list of acceptable types.
+ // If we detect success along the way, we'll simply discard the partial
+ // error string.
+ std::ostringstream out;
+ out << colon(pfx) << sTypes.lookup(expect);
+
+ // If there are any convertible types, append that list.
+ if (! accept.empty())
+ {
+ out << " (";
+ const char* sep = "or ";
+ for (TypeVector::const_iterator ai(accept.begin()), aend(accept.end());
+ ai != aend; ++ai, sep = ", ")
+ {
+ // Don't forget to return success if we match any of those types...
+ if (actual == *ai)
+ return "";
+ out << sep << sTypes.lookup(*ai);
+ }
+ out << ')';
+ }
+ // If we got this far, it's because 'actual' was not one of the acceptable
+ // types, so we must return an error. 'out' already contains colon(pfx)
+ // and the formatted list of acceptable types, so just append the mismatch
+ // phrase and the actual type.
+ out << op << sTypes.lookup(actual);
+ return out.str();
+}
+
+// see docstring in .h file
+std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::string& pfx)
+{
+ // An undefined prototype means that any data is valid.
+ // An undefined slot in an array or map prototype means that any data
+ // may fill that slot.
+ if (prototype.isUndefined())
+ return "";
+ // A prototype array must match a data array with at least as many
+ // entries. Moreover, every prototype entry must match the
+ // corresponding data entry.
+ if (prototype.isArray())
+ {
+ if (! data.isArray())
+ {
+ return STRINGIZE(colon(pfx) << "Array" << op << sTypes.lookup(data.type()));
+ }
+ if (data.size() < prototype.size())
+ {
+ return STRINGIZE(colon(pfx) << "Array size " << prototype.size() << op
+ << "Array size " << data.size());
+ }
+ for (LLSD::Integer i = 0; i < prototype.size(); ++i)
+ {
+ std::string match(llsd_matches(prototype[i], data[i], STRINGIZE('[' << i << ']')));
+ if (! match.empty())
+ {
+ return match;
+ }
+ }
+ return "";
+ }
+ // A prototype map must match a data map. Every key in the prototype
+ // must have a corresponding key in the data map; every value in the
+ // prototype must match the corresponding key's value in the data.
+ if (prototype.isMap())
+ {
+ if (! data.isMap())
+ {
+ return STRINGIZE(colon(pfx) << "Map" << op << sTypes.lookup(data.type()));
+ }
+ // If there are a number of keys missing from the data, it would be
+ // frustrating to a coder to discover them one at a time, with a big
+ // build each time. Enumerate all missing keys.
+ std::ostringstream out;
+ out << colon(pfx);
+ const char* init = "Map missing keys: ";
+ const char* sep = init;
+ for (LLSD::map_const_iterator mi = prototype.beginMap(); mi != prototype.endMap(); ++mi)
+ {
+ if (! data.has(mi->first))
+ {
+ out << sep << mi->first;
+ sep = ", ";
+ }
+ }
+ // So... are we missing any keys?
+ if (sep != init)
+ {
+ return out.str();
+ }
+ // Good, the data block contains all the keys required by the
+ // prototype. Now match the prototype entries.
+ for (LLSD::map_const_iterator mi2 = prototype.beginMap(); mi2 != prototype.endMap(); ++mi2)
+ {
+ std::string match(llsd_matches(mi2->second, data[mi2->first],
+ STRINGIZE("['" << mi2->first << "']")));
+ if (! match.empty())
+ {
+ return match;
+ }
+ }
+ return "";
+ }
+ // A String prototype can match String, Boolean, Integer, Real, UUID,
+ // Date and URI, because any of these can be converted to String.
+ if (prototype.isString())
+ {
+ static LLSD::Type accept[] =
+ {
+ LLSD::TypeBoolean,
+ LLSD::TypeInteger,
+ LLSD::TypeReal,
+ LLSD::TypeUUID,
+ LLSD::TypeDate,
+ LLSD::TypeURI
+ };
+ return match_types(prototype.type(),
+ TypeVector(boost::begin(accept), boost::end(accept)),
+ data.type(),
+ pfx);
+ }
+ // Boolean, Integer, Real match each other or String. TBD: ensure that
+ // a String value is numeric.
+ if (prototype.isBoolean() || prototype.isInteger() || prototype.isReal())
+ {
+ static LLSD::Type all[] =
+ {
+ LLSD::TypeBoolean,
+ LLSD::TypeInteger,
+ LLSD::TypeReal,
+ LLSD::TypeString
+ };
+ // Funny business: shuffle the set of acceptable types to include all
+ // but the prototype's type. Get the acceptable types in a set.
+ std::set<LLSD::Type> rest(boost::begin(all), boost::end(all));
+ // Remove the prototype's type because we pass that separately.
+ rest.erase(prototype.type());
+ return match_types(prototype.type(),
+ TypeVector(rest.begin(), rest.end()),
+ data.type(),
+ pfx);
+ }
+ // UUID, Date and URI match themselves or String.
+ if (prototype.isUUID() || prototype.isDate() || prototype.isURI())
+ {
+ static LLSD::Type accept[] =
+ {
+ LLSD::TypeString
+ };
+ return match_types(prototype.type(),
+ TypeVector(boost::begin(accept), boost::end(accept)),
+ data.type(),
+ pfx);
+ }
+ // We don't yet know the conversion semantics associated with any new LLSD
+ // data type that might be added, so until we've been extended to handle
+ // them, assume it's strict: the new type matches only itself. (This is
+ // true of Binary, which is why we don't handle that case separately.) Too
+ // bad LLSD doesn't define isConvertible(Type to, Type from).
+ return match_types(prototype.type(), TypeVector(), data.type(), pfx);
+}
+
+bool llsd_equals(const LLSD& lhs, const LLSD& rhs)
+{
+ // We're comparing strict equality of LLSD representation rather than
+ // performing any conversions. So if the types aren't equal, the LLSD
+ // values aren't equal.
+ if (lhs.type() != rhs.type())
+ {
+ return false;
+ }
+
+ // Here we know both types are equal. Now compare values.
+ switch (lhs.type())
+ {
+ case LLSD::TypeUndefined:
+ // Both are TypeUndefined. There's nothing more to know.
+ return true;
+
+#define COMPARE_SCALAR(type) \
+ case LLSD::Type##type: \
+ /* LLSD::URI has operator!=() but not operator==() */ \
+ /* rely on the optimizer for all others */ \
+ return (! (lhs.as##type() != rhs.as##type()))
+
+ COMPARE_SCALAR(Boolean);
+ COMPARE_SCALAR(Integer);
+ // The usual caveats about comparing floating-point numbers apply. This is
+ // only useful when we expect identical bit representation for a given
+ // Real value, e.g. for integer-valued Reals.
+ COMPARE_SCALAR(Real);
+ COMPARE_SCALAR(String);
+ COMPARE_SCALAR(UUID);
+ COMPARE_SCALAR(Date);
+ COMPARE_SCALAR(URI);
+ COMPARE_SCALAR(Binary);
+
+#undef COMPARE_SCALAR
+
+ case LLSD::TypeArray:
+ {
+ LLSD::array_const_iterator
+ lai(lhs.beginArray()), laend(lhs.endArray()),
+ rai(rhs.beginArray()), raend(rhs.endArray());
+ // Compare array elements, walking the two arrays in parallel.
+ for ( ; lai != laend && rai != raend; ++lai, ++rai)
+ {
+ // If any one array element is unequal, the arrays are unequal.
+ if (! llsd_equals(*lai, *rai))
+ return false;
+ }
+ // Here we've reached the end of one or the other array. They're equal
+ // only if they're BOTH at end: that is, if they have equal length too.
+ return (lai == laend && rai == raend);
+ }
+
+ case LLSD::TypeMap:
+ {
+ // Build a set of all rhs keys.
+ std::set<LLSD::String> rhskeys;
+ for (LLSD::map_const_iterator rmi(rhs.beginMap()), rmend(rhs.endMap());
+ rmi != rmend; ++rmi)
+ {
+ rhskeys.insert(rmi->first);
+ }
+ // Now walk all the lhs keys.
+ for (LLSD::map_const_iterator lmi(lhs.beginMap()), lmend(lhs.endMap());
+ lmi != lmend; ++lmi)
+ {
+ // Try to erase this lhs key from the set of rhs keys. If rhs has
+ // no such key, the maps are unequal. erase(key) returns count of
+ // items erased.
+ if (rhskeys.erase(lmi->first) != 1)
+ return false;
+ // Both maps have the current key. Compare values.
+ if (! llsd_equals(lmi->second, rhs[lmi->first]))
+ return false;
+ }
+ // We've now established that all the lhs keys have equal values in
+ // both maps. The maps are equal unless rhs contains a superset of
+ // those keys.
+ return rhskeys.empty();
+ }
+
+ default:
+ // We expect that every possible type() value is specifically handled
+ // above. Failing to extend this switch to support a new LLSD type is
+ // an error that must be brought to the coder's attention.
+ LL_ERRS("llsd_equals") << "llsd_equals(" << lhs << ", " << rhs << "): "
+ "unknown type " << lhs.type() << LL_ENDL;
+ return false; // pacify the compiler
+ }
+}
diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h
index b67ad521ea..6a6c396687 100644
--- a/indra/llcommon/llsdutil.h
+++ b/indra/llcommon/llsdutil.h
@@ -35,61 +35,32 @@
#ifndef LL_LLSDUTIL_H
#define LL_LLSDUTIL_H
-#include "llsd.h"
-
-// vector3
-class LLVector3;
-LLSD ll_sd_from_vector3(const LLVector3& vec);
-LLVector3 ll_vector3_from_sd(const LLSD& sd, S32 start_index = 0);
-
-// vector4
-class LLVector4;
-LLSD ll_sd_from_vector4(const LLVector4& vec);
-LLVector4 ll_vector4_from_sd(const LLSD& sd, S32 start_index = 0);
-
-// vector3d (double)
-class LLVector3d;
-LLSD ll_sd_from_vector3d(const LLVector3d& vec);
-LLVector3d ll_vector3d_from_sd(const LLSD& sd, S32 start_index = 0);
-
-// vector2
-class LLVector2;
-LLSD ll_sd_from_vector2(const LLVector2& vec);
-LLVector2 ll_vector2_from_sd(const LLSD& sd);
-
-// Quaternion
-class LLQuaternion;
-LLSD ll_sd_from_quaternion(const LLQuaternion& quat);
-LLQuaternion ll_quaternion_from_sd(const LLSD& sd);
-
-// color4
-class LLColor4;
-LLSD ll_sd_from_color4(const LLColor4& c);
-LLColor4 ll_color4_from_sd(const LLSD& sd);
+class LLSD;
// U32
-LLSD ll_sd_from_U32(const U32);
-U32 ll_U32_from_sd(const LLSD& sd);
+LL_COMMON_API LLSD ll_sd_from_U32(const U32);
+LL_COMMON_API U32 ll_U32_from_sd(const LLSD& sd);
// U64
-LLSD ll_sd_from_U64(const U64);
-U64 ll_U64_from_sd(const LLSD& sd);
+LL_COMMON_API LLSD ll_sd_from_U64(const U64);
+LL_COMMON_API U64 ll_U64_from_sd(const LLSD& sd);
// IP Address
-LLSD ll_sd_from_ipaddr(const U32);
-U32 ll_ipaddr_from_sd(const LLSD& sd);
+LL_COMMON_API LLSD ll_sd_from_ipaddr(const U32);
+LL_COMMON_API U32 ll_ipaddr_from_sd(const LLSD& sd);
// Binary to string
-LLSD ll_string_from_binary(const LLSD& sd);
+LL_COMMON_API LLSD ll_string_from_binary(const LLSD& sd);
//String to binary
-LLSD ll_binary_from_string(const LLSD& sd);
+LL_COMMON_API LLSD ll_binary_from_string(const LLSD& sd);
// Serializes sd to static buffer and returns pointer, useful for gdb debugging.
-char* ll_print_sd(const LLSD& sd);
+LL_COMMON_API char* ll_print_sd(const LLSD& sd);
// Serializes sd to static buffer and returns pointer, using "pretty printing" mode.
-char* ll_pretty_print_sd(const LLSD& sd);
+LL_COMMON_API char* ll_pretty_print_sd_ptr(const LLSD* sd);
+LL_COMMON_API char* ll_pretty_print_sd(const LLSD& sd);
//compares the structure of an LLSD to a template LLSD and stores the
//"valid" values in a 3rd LLSD. Default values
@@ -98,11 +69,69 @@ char* ll_pretty_print_sd(const LLSD& sd);
//Returns false if the test is of same type but values differ in type
//Otherwise, returns true
-BOOL compare_llsd_with_template(
+LL_COMMON_API BOOL compare_llsd_with_template(
const LLSD& llsd_to_test,
const LLSD& template_llsd,
LLSD& resultant_llsd);
+/**
+ * Recursively determine whether a given LLSD data block "matches" another
+ * LLSD prototype. The returned string is empty() on success, non-empty() on
+ * mismatch.
+ *
+ * This function tests structure (types) rather than data values. It is
+ * intended for when a consumer expects an LLSD block with a particular
+ * structure, and must succinctly detect whether the arriving block is
+ * well-formed. For instance, a test of the form:
+ * @code
+ * if (! (data.has("request") && data.has("target") && data.has("modifier") ...))
+ * @endcode
+ * could instead be expressed by initializing a prototype LLSD map with the
+ * required keys and writing:
+ * @code
+ * if (! llsd_matches(prototype, data).empty())
+ * @endcode
+ *
+ * A non-empty return value is an error-message fragment intended to indicate
+ * to (English-speaking) developers where in the prototype structure the
+ * mismatch occurred.
+ *
+ * * If a slot in the prototype isUndefined(), then anything is valid at that
+ * place in the real object. (Passing prototype == LLSD() matches anything
+ * at all.)
+ * * An array in the prototype must match a data array at least that large.
+ * (Additional entries in the data array are ignored.) Every isDefined()
+ * entry in the prototype array must match the corresponding entry in the
+ * data array.
+ * * A map in the prototype must match a map in the data. Every key in the
+ * prototype map must match a corresponding key in the data map. (Additional
+ * keys in the data map are ignored.) Every isDefined() value in the
+ * prototype map must match the corresponding key's value in the data map.
+ * * Scalar values in the prototype are tested for @em type rather than value.
+ * For instance, a String in the prototype matches any String at all. In
+ * effect, storing an Integer at a particular place in the prototype asserts
+ * that the caller intends to apply asInteger() to the corresponding slot in
+ * the data.
+ * * A String in the prototype matches String, Boolean, Integer, Real, UUID,
+ * Date and URI, because asString() applied to any of these produces a
+ * meaningful result.
+ * * Similarly, a Boolean, Integer or Real in the prototype can match any of
+ * Boolean, Integer or Real in the data -- or even String.
+ * * UUID matches UUID or String.
+ * * Date matches Date or String.
+ * * URI matches URI or String.
+ * * Binary in the prototype matches only Binary in the data.
+ *
+ * @TODO: when a Boolean, Integer or Real in the prototype matches a String in
+ * the data, we should examine the String @em value to ensure it can be
+ * meaningfully converted to the requested type. The same goes for UUID, Date
+ * and URI.
+ */
+LL_COMMON_API std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::string& pfx="");
+
+/// Deep equality
+LL_COMMON_API bool llsd_equals(const LLSD& lhs, const LLSD& rhs);
+
// Simple function to copy data out of input & output iterators if
// there is no need for casting.
template<typename Input> LLSD llsd_copy_array(Input iter, Input end)
diff --git a/indra/llcommon/llsecondlifeurls.cpp b/indra/llcommon/llsecondlifeurls.cpp
index 36d8e8870f..9e67872ffd 100644
--- a/indra/llcommon/llsecondlifeurls.cpp
+++ b/indra/llcommon/llsecondlifeurls.cpp
@@ -32,57 +32,59 @@
#include "linden_common.h"
#include "llsecondlifeurls.h"
-
+/*
const std::string CREATE_ACCOUNT_URL (
- "http://secondlife.com/registration/");
+ "http://join.secondlife.com/");
const std::string MANAGE_ACCOUNT (
- "http://secondlife.com/account/");
+ "http://secondlife.com/account/"); // *TODO: NOT USED
const std::string AUCTION_URL (
"http://secondlife.com/auctions/auction-detail.php?id=");
const std::string EVENTS_URL (
"http://secondlife.com/events/");
-
+*/
const std::string TIER_UP_URL (
- "http://secondlife.com/app/landtier");
+ "http://secondlife.com/app/landtier"); // *TODO: Translate (simulator)
+const std::string DIRECTX_9_URL (
+ "http://secondlife.com/support/"); // *TODO: NOT USED
+/*
const std::string LAND_URL (
- "http://secondlife.com/app/landtier");
+ "http://secondlife.com/app/landtier"); // *TODO: NOT USED
const std::string UPGRADE_TO_PREMIUM_URL (
- "http://secondlife.com/app/upgrade/");
-
-const std::string DIRECTX_9_URL (
- "http://secondlife.com/support/");
+ "http://secondlife.com/app/upgrade/"); // *TODO: NOT USED
const std::string AMD_AGP_URL (
- "http://secondlife.com/support/");
+ "http://secondlife.com/support/"); // *TODO: NOT USED
const std::string VIA_URL (
- "http://secondlife.com/support/");
+ "http://secondlife.com/support/"); // *TODO: NOT USED
const std::string SUPPORT_URL (
"http://secondlife.com/support/");
const std::string INTEL_CHIPSET_URL (
- "http://secondlife.com/support/");
+ "http://secondlife.com/support/"); // *TODO: NOT USED
const std::string SIS_CHIPSET_URL (
- "http://secondlife.com/support/");
+ "http://secondlife.com/support/"); // *TODO: NOT USED
const std::string BLOGS_URL (
- "http://blog.secondlife.com/");
+ "http://blog.secondlife.com/"); // *TODO: NOT USED
const std::string BUY_CURRENCY_URL (
"http://secondlife.com/app/currency/");
const std::string LSL_DOC_URL (
- "http://secondlife.com/app/lsldoc/");
+ "http://secondlife.com/app/lsldoc/"); // *TODO: NOT USED
const std::string SL_KB_URL (
- "http://secondlife.com/knowledgebase/");
+ "http://secondlife.com/knowledgebase/"); // *TODO: NOT USED
const std::string RELEASE_NOTES_BASE_URL (
"http://secondlife.com/app/releasenotes/");
+*/
+
diff --git a/indra/llcommon/llsecondlifeurls.h b/indra/llcommon/llsecondlifeurls.h
index 9fd75c363b..bd2f9f7604 100644
--- a/indra/llcommon/llsecondlifeurls.h
+++ b/indra/llcommon/llsecondlifeurls.h
@@ -32,48 +32,51 @@
#ifndef LL_LLSECONDLIFEURLS_H
#define LL_LLSECONDLIFEURLS_H
-
+/*
// Account registration web page
-extern const std::string CREATE_ACCOUNT_URL;
+LL_COMMON_API extern const std::string CREATE_ACCOUNT_URL;
// Manage Account
-extern const std::string MANAGE_ACCOUNT;
-
-extern const std::string AUCTION_URL;
+LL_COMMON_API extern const std::string MANAGE_ACCOUNT;
-extern const std::string EVENTS_URL;
+LL_COMMON_API extern const std::string AUCTION_URL;
+LL_COMMON_API extern const std::string EVENTS_URL;
+*/
// Tier up to a new land level.
-extern const std::string TIER_UP_URL;
+LL_COMMON_API extern const std::string TIER_UP_URL;
+
// Tier up to a new land level.
-extern const std::string LAND_URL;
+LL_COMMON_API extern const std::string LAND_URL;
+// How to get DirectX 9
+LL_COMMON_API extern const std::string DIRECTX_9_URL;
+
+/*
// Upgrade from basic membership to premium membership
-extern const std::string UPGRADE_TO_PREMIUM_URL;
+LL_COMMON_API extern const std::string UPGRADE_TO_PREMIUM_URL;
-// How to get DirectX 9
-extern const std::string DIRECTX_9_URL;
// Out of date VIA chipset
-extern const std::string VIA_URL;
+LL_COMMON_API extern const std::string VIA_URL;
// Support URL
-extern const std::string SUPPORT_URL;
+LL_COMMON_API extern const std::string SUPPORT_URL;
// Linden Blogs page
-extern const std::string BLOGS_URL;
+LL_COMMON_API extern const std::string BLOGS_URL;
// Currency page
-extern const std::string BUY_CURRENCY_URL;
+LL_COMMON_API extern const std::string BUY_CURRENCY_URL;
// LSL script wiki
-extern const std::string LSL_DOC_URL;
+LL_COMMON_API extern const std::string LSL_DOC_URL;
// SL KnowledgeBase page
-extern const std::string SL_KB_URL;
+LL_COMMON_API extern const std::string SL_KB_URL;
// Release Notes Redirect URL for Server and Viewer
-extern const std::string RELEASE_NOTES_BASE_URL;
-
+LL_COMMON_API extern const std::string RELEASE_NOTES_BASE_URL;
+*/
#endif
diff --git a/indra/llcommon/llsimplehash.h b/indra/llcommon/llsimplehash.h
index 0ba2a3014c..5df93b646e 100644
--- a/indra/llcommon/llsimplehash.h
+++ b/indra/llcommon/llsimplehash.h
@@ -64,7 +64,7 @@ public:
};
template <typename HASH_KEY_TYPE, int TABLE_SIZE>
-class LLSimpleHash
+class LL_COMMON_API LLSimpleHash
{
public:
LLSimpleHash()
diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp
new file mode 100644
index 0000000000..6b5feaf1c4
--- /dev/null
+++ b/indra/llcommon/llsingleton.cpp
@@ -0,0 +1,38 @@
+/**
+ * @file llsingleton.cpp
+ * @author Brad Kittenbrink
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llsingleton.h"
+
+std::map<std::string, void *> * LLSingletonRegistry::sSingletonMap = NULL;
+
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
new file mode 100644
index 0000000000..ddeb4d1489
--- /dev/null
+++ b/indra/llcommon/llsingleton.h
@@ -0,0 +1,207 @@
+/**
+ * @file llsingleton.h
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef LLSINGLETON_H
+#define LLSINGLETON_H
+
+#include "llerror.h" // *TODO: eliminate this
+
+#include <typeinfo>
+#include <boost/noncopyable.hpp>
+
+/// @brief A global registry of all singletons to prevent duplicate allocations
+/// across shared library boundaries
+class LL_COMMON_API LLSingletonRegistry {
+ private:
+ typedef std::map<std::string, void *> TypeMap;
+ static TypeMap * sSingletonMap;
+
+ static void checkInit()
+ {
+ if(sSingletonMap == NULL)
+ {
+ sSingletonMap = new TypeMap();
+ }
+ }
+
+ public:
+ template<typename T> static void * & get()
+ {
+ std::string name(typeid(T).name());
+
+ checkInit();
+
+ // the first entry of the pair returned by insert will be either the existing
+ // iterator matching our key, or the newly inserted NULL initialized entry
+ // see "Insert element" in http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
+ TypeMap::iterator result =
+ sSingletonMap->insert(std::make_pair(name, (void*)NULL)).first;
+
+ return result->second;
+ }
+};
+
+// LLSingleton implements the getInstance() method part of the Singleton
+// pattern. It can't make the derived class constructors protected, though, so
+// you have to do that yourself.
+//
+// There are two ways to use LLSingleton. The first way is to inherit from it
+// while using the typename that you'd like to be static as the template
+// parameter, like so:
+//
+// class Foo: public LLSingleton<Foo>{};
+//
+// Foo& instance = Foo::instance();
+//
+// The second way is to use the singleton class directly, without inheritance:
+//
+// typedef LLSingleton<Foo> FooSingleton;
+//
+// Foo& instance = FooSingleton::instance();
+//
+// In this case, the class being managed as a singleton needs to provide an
+// initSingleton() method since the LLSingleton virtual method won't be
+// available
+//
+// As currently written, it is not thread-safe.
+
+template <typename DERIVED_TYPE>
+class LLSingleton : private boost::noncopyable
+{
+
+private:
+ typedef enum e_init_state
+ {
+ UNINITIALIZED,
+ CONSTRUCTING,
+ INITIALIZING,
+ INITIALIZED,
+ DELETED
+ } EInitState;
+
+ static void deleteSingleton()
+ {
+ delete getData().mSingletonInstance;
+ getData().mSingletonInstance = NULL;
+ }
+
+ // stores pointer to singleton instance
+ // and tracks initialization state of singleton
+ struct SingletonInstanceData
+ {
+ EInitState mInitState;
+ DERIVED_TYPE* mSingletonInstance;
+
+ SingletonInstanceData()
+ : mSingletonInstance(NULL),
+ mInitState(UNINITIALIZED)
+ {}
+
+ ~SingletonInstanceData()
+ {
+ deleteSingleton();
+ }
+ };
+
+public:
+ virtual ~LLSingleton()
+ {
+ SingletonInstanceData& data = getData();
+ data.mSingletonInstance = NULL;
+ data.mInitState = DELETED;
+ }
+
+ static SingletonInstanceData& getData()
+ {
+ // this is static to cache the lookup results
+ static void * & registry = LLSingletonRegistry::get<DERIVED_TYPE>();
+
+ // *TODO - look into making this threadsafe
+ if(NULL == registry)
+ {
+ static SingletonInstanceData data;
+ registry = &data;
+ }
+
+ return *static_cast<SingletonInstanceData *>(registry);
+ }
+
+ static DERIVED_TYPE* getInstance()
+ {
+ SingletonInstanceData& data = getData();
+
+ if (data.mInitState == CONSTRUCTING)
+ {
+ llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl;
+ }
+
+ if (data.mInitState == DELETED)
+ {
+ llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
+ }
+
+ if (!data.mSingletonInstance)
+ {
+ data.mInitState = CONSTRUCTING;
+ data.mSingletonInstance = new DERIVED_TYPE();
+ data.mInitState = INITIALIZING;
+ data.mSingletonInstance->initSingleton();
+ data.mInitState = INITIALIZED;
+ }
+
+ return data.mSingletonInstance;
+ }
+
+ // Reference version of getInstance()
+ // Preferred over getInstance() as it disallows checking for NULL
+ static DERIVED_TYPE& instance()
+ {
+ return *getInstance();
+ }
+
+ // Has this singleton been created uet?
+ // Use this to avoid accessing singletons before the can safely be constructed
+ static bool instanceExists()
+ {
+ return getData().mInitState == INITIALIZED;
+ }
+
+ // Has this singleton already been deleted?
+ // Use this to avoid accessing singletons from a static object's destructor
+ static bool destroyed()
+ {
+ return getData().mInitState == DELETED;
+ }
+
+private:
+ virtual void initSingleton() {}
+};
+
+#endif
diff --git a/indra/llcommon/llstacktrace.cpp b/indra/llcommon/llstacktrace.cpp
new file mode 100644
index 0000000000..6558df70a4
--- /dev/null
+++ b/indra/llcommon/llstacktrace.cpp
@@ -0,0 +1,142 @@
+/**
+ * @file llstacktrace.cpp
+ * @brief stack tracing functionality
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llstacktrace.h"
+
+#ifdef LL_WINDOWS
+
+#include <iostream>
+#include <sstream>
+
+#include "windows.h"
+#include "Dbghelp.h"
+
+typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(
+ IN ULONG frames_to_skip,
+ IN ULONG frames_to_capture,
+ OUT PVOID *backtrace,
+ OUT PULONG backtrace_hash);
+
+static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn =
+ (RtlCaptureStackBackTrace_Function*)
+ GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace");
+
+bool ll_get_stack_trace(std::vector<std::string>& lines)
+{
+ const S32 MAX_STACK_DEPTH = 32;
+ const S32 STRING_NAME_LENGTH = 200;
+ const S32 FRAME_SKIP = 2;
+ static BOOL symbolsLoaded = false;
+ static BOOL firstCall = true;
+
+ HANDLE hProc = GetCurrentProcess();
+
+ // load the symbols if they're not loaded
+ if(!symbolsLoaded && firstCall)
+ {
+ symbolsLoaded = SymInitialize(hProc, NULL, true);
+ firstCall = false;
+ }
+
+ // if loaded, get the call stack
+ if(symbolsLoaded)
+ {
+ // create the frames to hold the addresses
+ void* frames[MAX_STACK_DEPTH];
+ memset(frames, 0, sizeof(void*)*MAX_STACK_DEPTH);
+ S32 depth = 0;
+
+ // get the addresses
+ depth = RtlCaptureStackBackTrace_fn(FRAME_SKIP, MAX_STACK_DEPTH, frames, NULL);
+
+ IMAGEHLP_LINE64 line;
+ memset(&line, 0, sizeof(IMAGEHLP_LINE64));
+ line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+
+ // create something to hold address info
+ PIMAGEHLP_SYMBOL64 pSym;
+ pSym = (PIMAGEHLP_SYMBOL64)malloc(sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
+ memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
+ pSym->MaxNameLength = STRING_NAME_LENGTH;
+ pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
+
+ // get address info for each address frame
+ // and store
+ for(S32 i=0; i < depth; i++)
+ {
+ std::stringstream stack_line;
+ BOOL ret;
+
+ DWORD64 addr = (DWORD64)frames[i];
+ ret = SymGetSymFromAddr64(hProc, addr, 0, pSym);
+ if(ret)
+ {
+ stack_line << pSym->Name << " ";
+ }
+
+ DWORD dummy;
+ ret = SymGetLineFromAddr64(hProc, addr, &dummy, &line);
+ if(ret)
+ {
+ std::string file_name = line.FileName;
+ std::string::size_type index = file_name.rfind("\\");
+ stack_line << file_name.substr(index + 1, file_name.size()) << ":" << line.LineNumber;
+ }
+
+ lines.push_back(stack_line.str());
+ }
+
+ free(pSym);
+
+ // TODO: figure out a way to cleanup symbol loading
+ // Not hugely necessary, however.
+ //SymCleanup(hProc);
+ return true;
+ }
+ else
+ {
+ lines.push_back("Stack Trace Failed. PDB symbol info not loaded");
+ }
+
+ return false;
+}
+
+#else
+
+bool ll_get_stack_trace(std::vector<std::string>& lines)
+{
+ return false;
+}
+
+#endif
+
diff --git a/indra/llcommon/llstacktrace.h b/indra/llcommon/llstacktrace.h
new file mode 100644
index 0000000000..9f857f0fd3
--- /dev/null
+++ b/indra/llcommon/llstacktrace.h
@@ -0,0 +1,44 @@
+/**
+ * @file llstacktrace.h
+ * @brief stack trace functions
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#ifndef LL_LLSTACKTRACE_H
+#define LL_LLSTACKTRACE_H
+
+#include "stdtypes.h"
+#include <vector>
+#include <string>
+
+LL_COMMON_API bool ll_get_stack_trace(std::vector<std::string>& lines);
+
+#endif
+
diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp
index 291b019616..0bd2609f4a 100644
--- a/indra/llcommon/llstat.cpp
+++ b/indra/llcommon/llstat.cpp
@@ -43,9 +43,10 @@
// statics
-BOOL LLPerfBlock::sStatsEnabled = FALSE; // Flag for detailed information
+S32 LLPerfBlock::sStatsFlags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS; // Control what is being recorded
LLPerfBlock::stat_map_t LLPerfBlock::sStatMap; // Map full path string to LLStatTime objects, tracks all active objects
std::string LLPerfBlock::sCurrentStatPath = ""; // Something like "/total_time/physics/physics step"
+LLStat::stat_map_t LLStat::sStatList;
//------------------------------------------------------------------------
// Live config file to trigger stats logging
@@ -129,6 +130,7 @@ bool LLStatsConfigFile::loadFile()
F32 duration = 0.f;
F32 interval = 0.f;
+ S32 flags = LLPerfBlock::LLSTATS_BASIC_STATS;
const char * w = "duration";
if (stats_config.has(w))
@@ -140,8 +142,18 @@ bool LLStatsConfigFile::loadFile()
{
interval = (F32)stats_config[w].asReal();
}
+ w = "flags";
+ if (stats_config.has(w))
+ {
+ flags = (S32)stats_config[w].asInteger();
+ if (flags == LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS &&
+ duration > 0)
+ { // No flags passed in, but have a duration, so reset to basic stats
+ flags = LLPerfBlock::LLSTATS_BASIC_STATS;
+ }
+ }
- mStatsp->setReportPerformanceDuration( duration );
+ mStatsp->setReportPerformanceDuration( duration, flags );
mStatsp->setReportPerformanceInterval( interval );
if ( duration > 0 )
@@ -253,13 +265,14 @@ void LLPerfStats::dumpIntervalPerformanceStats()
}
}
-// Set length of performance stat recording
-void LLPerfStats::setReportPerformanceDuration( F32 seconds )
+// Set length of performance stat recording.
+// If turning stats on, caller must provide flags
+void LLPerfStats::setReportPerformanceDuration( F32 seconds, S32 flags /* = LLSTATS_NO_OPTIONAL_STATS */ )
{
if ( seconds <= 0.f )
{
mReportPerformanceStatEnd = 0.0;
- LLPerfBlock::setStatsEnabled( FALSE );
+ LLPerfBlock::setStatsFlags(LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS); // Make sure all recording is off
mFrameStatsFile.close();
LLPerfBlock::clearDynamicStats();
}
@@ -268,8 +281,8 @@ void LLPerfStats::setReportPerformanceDuration( F32 seconds )
mReportPerformanceStatEnd = LLFrameTimer::getElapsedSeconds() + ((F64) seconds);
// Clear failure flag to try and create the log file once
mFrameStatsFileFailure = FALSE;
- LLPerfBlock::setStatsEnabled( TRUE );
mSkipFirstFrameStats = TRUE; // Skip the first report (at the end of this frame)
+ LLPerfBlock::setStatsFlags(flags);
}
}
@@ -611,11 +624,26 @@ LLPerfBlock::LLPerfBlock(LLStatTime* stat ) : mPredefinedStat(stat), mDynamicSta
}
}
-// Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key.
-// These are also turned on or off via the switch passed in
-LLPerfBlock::LLPerfBlock( const char* key1, const char* key2 ) : mPredefinedStat(NULL), mDynamicStat(NULL)
+// Use this constructor for normal, optional LLPerfBlock time slices
+LLPerfBlock::LLPerfBlock( const char* key ) : mPredefinedStat(NULL), mDynamicStat(NULL)
+{
+ if ((sStatsFlags & LLSTATS_BASIC_STATS) == 0)
+ { // These are off unless the base set is enabled
+ return;
+ }
+
+ initDynamicStat(key);
+}
+
+
+// Use this constructor for dynamically created LLPerfBlock time slices
+// that are only enabled by specific control flags
+LLPerfBlock::LLPerfBlock( const char* key1, const char* key2, S32 flags ) : mPredefinedStat(NULL), mDynamicStat(NULL)
{
- if (!sStatsEnabled) return;
+ if ((sStatsFlags & flags) == 0)
+ {
+ return;
+ }
if (NULL == key2 || strlen(key2) == 0)
{
@@ -629,10 +657,12 @@ LLPerfBlock::LLPerfBlock( const char* key1, const char* key2 ) : mPredefinedStat
}
}
+// Set up the result data map if dynamic stats are enabled
void LLPerfBlock::initDynamicStat(const std::string& key)
{
// Early exit if dynamic stats aren't enabled.
- if (!sStatsEnabled) return;
+ if (sStatsFlags == LLSTATS_NO_OPTIONAL_STATS)
+ return;
mLastPath = sCurrentStatPath; // Save and restore current path
sCurrentStatPath += "/" + key; // Add key to current path
@@ -725,28 +755,48 @@ void LLPerfBlock::addStatsToLLSDandReset( LLSD & stats,
LLTimer LLStat::sTimer;
LLFrameTimer LLStat::sFrameTimer;
-LLStat::LLStat(const U32 num_bins, const BOOL use_frame_timer)
+void LLStat::init()
{
- llassert(num_bins > 0);
- U32 i;
- mUseFrameTimer = use_frame_timer;
+ llassert(mNumBins > 0);
mNumValues = 0;
mLastValue = 0.f;
mLastTime = 0.f;
- mNumBins = num_bins;
mCurBin = (mNumBins-1);
mNextBin = 0;
mBins = new F32[mNumBins];
mBeginTime = new F64[mNumBins];
mTime = new F64[mNumBins];
mDT = new F32[mNumBins];
- for (i = 0; i < mNumBins; i++)
+ for (U32 i = 0; i < mNumBins; i++)
{
mBins[i] = 0.f;
mBeginTime[i] = 0.0;
mTime[i] = 0.0;
mDT[i] = 0.f;
}
+
+ if (!mName.empty())
+ {
+ stat_map_t::iterator iter = sStatList.find(mName);
+ if (iter != sStatList.end())
+ llwarns << "LLStat with duplicate name: " << mName << llendl;
+ sStatList.insert(std::make_pair(mName, this));
+ }
+}
+
+LLStat::LLStat(const U32 num_bins, const BOOL use_frame_timer)
+ : mUseFrameTimer(use_frame_timer),
+ mNumBins(num_bins)
+{
+ init();
+}
+
+LLStat::LLStat(std::string name, U32 num_bins, BOOL use_frame_timer)
+ : mUseFrameTimer(use_frame_timer),
+ mNumBins(num_bins),
+ mName(name)
+{
+ init();
}
LLStat::~LLStat()
@@ -755,6 +805,15 @@ LLStat::~LLStat()
delete[] mBeginTime;
delete[] mTime;
delete[] mDT;
+
+ if (!mName.empty())
+ {
+ // handle multiple entries with the same name
+ stat_map_t::iterator iter = sStatList.find(mName);
+ while (iter != sStatList.end() && iter->second != this)
+ ++iter;
+ sStatList.erase(iter);
+ }
}
void LLStat::reset()
diff --git a/indra/llcommon/llstat.h b/indra/llcommon/llstat.h
index 61aaac45bf..bd73c9a6bb 100644
--- a/indra/llcommon/llstat.h
+++ b/indra/llcommon/llstat.h
@@ -52,7 +52,7 @@ class LLSD;
// amounts of time with very low memory cost.
//
-class LLStatAccum
+class LL_COMMON_API LLStatAccum
{
protected:
LLStatAccum(bool use_frame_timer);
@@ -116,7 +116,7 @@ public:
F64 mLastSampleValue;
};
-class LLStatMeasure : public LLStatAccum
+class LL_COMMON_API LLStatMeasure : public LLStatAccum
// gathers statistics about things that are measured
// ex.: tempature, time dilation
{
@@ -131,7 +131,7 @@ public:
};
-class LLStatRate : public LLStatAccum
+class LL_COMMON_API LLStatRate : public LLStatAccum
// gathers statistics about things that can be counted over time
// ex.: LSL instructions executed, messages sent, simulator frames completed
// renders it in terms of rate of thing per second
@@ -147,7 +147,7 @@ public:
};
-class LLStatTime : public LLStatAccum
+class LL_COMMON_API LLStatTime : public LLStatAccum
// gathers statistics about time spent in a block of code
// measure average duration per second in the block
{
@@ -178,7 +178,7 @@ private:
// Use this class on the stack to record statistics about an area of code
-class LLPerfBlock
+class LL_COMMON_API LLPerfBlock
{
public:
struct StatEntry
@@ -192,14 +192,23 @@ public:
// Use this constructor for pre-defined LLStatTime objects
LLPerfBlock(LLStatTime* stat);
- // Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key
- LLPerfBlock( const char* key1, const char* key2 = NULL);
+ // Use this constructor for normal, optional LLPerfBlock time slices
+ LLPerfBlock( const char* key );
+ // Use this constructor for dynamically created LLPerfBlock time slices
+ // that are only enabled by specific control flags
+ LLPerfBlock( const char* key1, const char* key2, S32 flags = LLSTATS_BASIC_STATS );
~LLPerfBlock();
- static void setStatsEnabled( BOOL enable ) { sStatsEnabled = enable; };
- static S32 getStatsEnabled() { return sStatsEnabled; };
+ enum
+ { // Stats bitfield flags
+ LLSTATS_NO_OPTIONAL_STATS = 0x00, // No optional stats gathering, just pre-defined LLStatTime objects
+ LLSTATS_BASIC_STATS = 0x01, // Gather basic optional runtime stats
+ LLSTATS_SCRIPT_FUNCTIONS = 0x02, // Include LSL function calls
+ };
+ static void setStatsFlags( S32 flags ) { sStatsFlags = flags; };
+ static S32 getStatsFlags() { return sStatsFlags; };
static void clearDynamicStats(); // Reset maps to clear out dynamic objects
static void addStatsToLLSDandReset( LLSD & stats, // Get current information and clear time bin
@@ -213,14 +222,14 @@ private:
LLStatTime * mPredefinedStat; // LLStatTime object to get data
StatEntry * mDynamicStat; // StatEntryobject to get data
- static BOOL sStatsEnabled; // Normally FALSE
+ static S32 sStatsFlags; // Control what is being recorded
static stat_map_t sStatMap; // Map full path string to LLStatTime objects
static std::string sCurrentStatPath; // Something like "frame/physics/physics step"
};
// ----------------------------------------------------------------------------
-class LLPerfStats
+class LL_COMMON_API LLPerfStats
{
public:
LLPerfStats(const std::string& process_name = "unknown", S32 process_pid = 0);
@@ -236,7 +245,7 @@ public:
BOOL frameStatsIsRunning() { return (mReportPerformanceStatEnd > 0.); };
F32 getReportPerformanceInterval() const { return mReportPerformanceStatInterval; };
void setReportPerformanceInterval( F32 interval ) { mReportPerformanceStatInterval = interval; };
- void setReportPerformanceDuration( F32 seconds );
+ void setReportPerformanceDuration( F32 seconds, S32 flags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS );
void setProcessName(const std::string& process_name) { mProcessName = process_name; }
void setProcessPID(S32 process_pid) { mProcessPID = process_pid; }
@@ -256,10 +265,17 @@ private:
};
// ----------------------------------------------------------------------------
-class LLStat
+class LL_COMMON_API LLStat
{
+private:
+ typedef std::multimap<std::string, LLStat*> stat_map_t;
+ static stat_map_t sStatList;
+
+ void init();
+
public:
- LLStat(const U32 num_bins = 32, BOOL use_frame_timer = FALSE);
+ LLStat(U32 num_bins = 32, BOOL use_frame_timer = FALSE);
+ LLStat(std::string name, U32 num_bins = 32, BOOL use_frame_timer = FALSE);
~LLStat();
void reset();
@@ -322,8 +338,22 @@ private:
F32 *mDT;
S32 mCurBin;
S32 mNextBin;
+
+ std::string mName;
+
static LLTimer sTimer;
static LLFrameTimer sFrameTimer;
+
+public:
+ static LLStat* getStat(const std::string& name)
+ {
+ // return the first stat that matches 'name'
+ stat_map_t::iterator iter = sStatList.find(name);
+ if (iter != sStatList.end())
+ return iter->second;
+ else
+ return NULL;
+ }
};
-
+
#endif // LL_STAT_
diff --git a/indra/llcommon/llstreamtools.h b/indra/llcommon/llstreamtools.h
index a6dc4d51e2..f64e761409 100644
--- a/indra/llcommon/llstreamtools.h
+++ b/indra/llcommon/llstreamtools.h
@@ -39,23 +39,23 @@
// unless specifed otherwise these all return input_stream.good()
// skips spaces and tabs
-bool skip_whitespace(std::istream& input_stream);
+LL_COMMON_API bool skip_whitespace(std::istream& input_stream);
// skips whitespace and newlines
-bool skip_emptyspace(std::istream& input_stream);
+LL_COMMON_API bool skip_emptyspace(std::istream& input_stream);
// skips emptyspace and lines that start with a #
-bool skip_comments_and_emptyspace(std::istream& input_stream);
+LL_COMMON_API bool skip_comments_and_emptyspace(std::istream& input_stream);
// skips to character after next newline
-bool skip_line(std::istream& input_stream);
+LL_COMMON_API bool skip_line(std::istream& input_stream);
// skips to beginning of next non-emptyspace
-bool skip_to_next_word(std::istream& input_stream);
+LL_COMMON_API bool skip_to_next_word(std::istream& input_stream);
// skips to character after the end of next keyword
// a 'keyword' is defined as the first word on a line
-bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream);
+LL_COMMON_API bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream);
// skip_to_start_of_next_keyword() is disabled -- might tickle corruption bug
// in windows iostream
@@ -65,14 +65,14 @@ bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream
// characters are pulled out of input_stream and appended to output_string
// returns result of input_stream.good() after characters are pulled
-bool get_word(std::string& output_string, std::istream& input_stream);
-bool get_line(std::string& output_string, std::istream& input_stream);
+LL_COMMON_API bool get_word(std::string& output_string, std::istream& input_stream);
+LL_COMMON_API bool get_line(std::string& output_string, std::istream& input_stream);
// characters are pulled out of input_stream (up to a max of 'n')
// and appended to output_string
// returns result of input_stream.good() after characters are pulled
-bool get_word(std::string& output_string, std::istream& input_stream, int n);
-bool get_line(std::string& output_string, std::istream& input_stream, int n);
+LL_COMMON_API bool get_word(std::string& output_string, std::istream& input_stream, int n);
+LL_COMMON_API bool get_line(std::string& output_string, std::istream& input_stream, int n);
// unget_line() is disabled -- might tickle corruption bug in windows iostream
//// backs up the input_stream by line_size + 1 characters
@@ -82,28 +82,28 @@ bool get_line(std::string& output_string, std::istream& input_stream, int n);
// removes the last char in 'line' if it matches 'c'
// returns true if removed last char
-bool remove_last_char(char c, std::string& line);
+LL_COMMON_API bool remove_last_char(char c, std::string& line);
// replaces escaped characters with the correct characters from left to right
// "\\" ---> '\\'
// "\n" ---> '\n'
-void unescape_string(std::string& line);
+LL_COMMON_API void unescape_string(std::string& line);
// replaces unescaped characters with expanded equivalents from left to right
// '\\' ---> "\\"
// '\n' ---> "\n"
-void escape_string(std::string& line);
+LL_COMMON_API void escape_string(std::string& line);
// replaces each '\n' character with ' '
-void replace_newlines_with_whitespace(std::string& line);
+LL_COMMON_API void replace_newlines_with_whitespace(std::string& line);
// erases any double-quote characters in line
-void remove_double_quotes(std::string& line);
+LL_COMMON_API void remove_double_quotes(std::string& line);
// the 'keyword' is defined as the first word on a line
// the 'value' is everything after the keyword on the same line
// starting at the first non-whitespace and ending right before the newline
-void get_keyword_and_value(std::string& keyword,
+LL_COMMON_API void get_keyword_and_value(std::string& keyword,
std::string& value,
const std::string& line);
@@ -111,13 +111,13 @@ void get_keyword_and_value(std::string& keyword,
// read anymore or until we hit the count. Some istream
// implimentations have a max that they will read.
// Returns the number of bytes read.
-std::streamsize fullread(
+LL_COMMON_API std::streamsize fullread(
std::istream& istr,
char* buf,
std::streamsize requested);
-std::istream& operator>>(std::istream& str, const char *tocheck);
+LL_COMMON_API std::istream& operator>>(std::istream& str, const char *tocheck);
#endif
diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index 1f653c159c..5f3d9d6582 100644
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -42,6 +42,9 @@
#include <winnls.h> // for WideCharToMultiByte
#endif
+LLFastTimer::DeclareTimer FT_STRING_FORMAT("String Format");
+
+
std::string ll_safe_string(const char* in)
{
if(in) return std::string(in);
@@ -71,6 +74,24 @@ U8 hex_as_nybble(char hex)
return 0; // uh - oh, not hex any more...
}
+bool iswindividual(llwchar elem)
+{
+ U32 cur_char = (U32)elem;
+ bool result = false;
+ if (0x2E80<= cur_char && cur_char <= 0x9FFF)
+ {
+ result = true;
+ }
+ else if (0xAC00<= cur_char && cur_char <= 0xD7A0 )
+ {
+ result = true;
+ }
+ else if (0xF900<= cur_char && cur_char <= 0xFA60 )
+ {
+ result = true;
+ }
+ return result;
+}
bool _read_file_into_string(std::string& str, const std::string& filename)
{
@@ -134,7 +155,7 @@ S32 wchar_to_utf8chars(llwchar in_char, char* outchars)
*outchars++ = 0xF0 | (cur_char >> 18);
*outchars++ = 0x80 | ((cur_char >> 12) & 0x3F);
*outchars++ = 0x80 | ((cur_char >> 6) & 0x3F);
- *outchars++ = 0x80 | cur_char & 0x3F;
+ *outchars++ = 0x80 | (cur_char & 0x3F);
}
else if (cur_char < 0x4000000)
{
@@ -142,7 +163,7 @@ S32 wchar_to_utf8chars(llwchar in_char, char* outchars)
*outchars++ = 0x80 | ((cur_char >> 18) & 0x3F);
*outchars++ = 0x80 | ((cur_char >> 12) & 0x3F);
*outchars++ = 0x80 | ((cur_char >> 6) & 0x3F);
- *outchars++ = 0x80 | cur_char & 0x3F;
+ *outchars++ = 0x80 | (cur_char & 0x3F);
}
else if (cur_char < 0x80000000)
{
@@ -151,7 +172,7 @@ S32 wchar_to_utf8chars(llwchar in_char, char* outchars)
*outchars++ = 0x80 | ((cur_char >> 18) & 0x3F);
*outchars++ = 0x80 | ((cur_char >> 12) & 0x3F);
*outchars++ = 0x80 | ((cur_char >> 6) & 0x3F);
- *outchars++ = 0x80 | cur_char & 0x3F;
+ *outchars++ = 0x80 | (cur_char & 0x3F);
}
else
{
@@ -650,6 +671,11 @@ std::string ll_convert_wide_to_string(const wchar_t* in)
}
#endif // LL_WINDOWS
+long LLStringOps::sPacificTimeOffset = 0;
+long LLStringOps::sLocalTimeOffset = 0;
+bool LLStringOps::sPacificDaylightTime = 0;
+std::map<std::string, std::string> LLStringOps::datetimeToCodes;
+
S32 LLStringOps::collate(const llwchar* a, const llwchar* b)
{
#if LL_WINDOWS
@@ -661,6 +687,59 @@ S32 LLStringOps::collate(const llwchar* a, const llwchar* b)
#endif
}
+void LLStringOps::setupDatetimeInfo (bool daylight)
+{
+ time_t nowT, localT, gmtT;
+ struct tm * tmpT;
+
+ nowT = time (NULL);
+
+ tmpT = localtime (&nowT);
+ localT = mktime (tmpT);
+
+ tmpT = gmtime (&nowT);
+ gmtT = mktime (tmpT);
+
+ sLocalTimeOffset = (long) (gmtT - localT);
+
+
+ sPacificDaylightTime = daylight;
+ sPacificTimeOffset = (sPacificDaylightTime? 7 : 8 ) * 60 * 60;
+
+ datetimeToCodes["wkday"] = "%a"; // Thu
+ datetimeToCodes["weekday"] = "%A"; // Thursday
+ datetimeToCodes["year4"] = "%Y"; // 2009
+ datetimeToCodes["year"] = "%Y"; // 2009
+ datetimeToCodes["year2"] = "%y"; // 09
+ datetimeToCodes["mth"] = "%b"; // Aug
+ datetimeToCodes["month"] = "%B"; // August
+ datetimeToCodes["mthnum"] = "%m"; // 08
+ datetimeToCodes["day"] = "%d"; // 31
+ datetimeToCodes["hour24"] = "%H"; // 14
+ datetimeToCodes["hour"] = "%H"; // 14
+ datetimeToCodes["hour12"] = "%I"; // 02
+ datetimeToCodes["min"] = "%M"; // 59
+ datetimeToCodes["ampm"] = "%p"; // AM
+ datetimeToCodes["second"] = "%S"; // 59
+ datetimeToCodes["timezone"] = "%Z"; // PST
+}
+
+std::string LLStringOps::getDatetimeCode (std::string key)
+{
+ std::map<std::string, std::string>::iterator iter;
+
+ iter = datetimeToCodes.find (key);
+ if (iter != datetimeToCodes.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ return std::string("");
+ }
+}
+
+
namespace LLStringFn
{
// NOTE - this restricts output to ascii
@@ -697,12 +776,12 @@ namespace LLStringFn
// https://wiki.lindenlab.com/wiki/Unicode_Guidelines has details on
// allowable code points for XML. Specifically, they are:
// 0x09, 0x0a, 0x0d, and 0x20 on up. JC
- std::string strip_invalid_xml(const std::string& input)
+ std::string strip_invalid_xml(const std::string& instr)
{
std::string output;
- output.reserve( input.size() );
- std::string::const_iterator it = input.begin();
- while (it != input.end())
+ output.reserve( instr.size() );
+ std::string::const_iterator it = instr.begin();
+ while (it != instr.end())
{
// Must compare as unsigned for >=
// Test most likely match first
@@ -738,6 +817,336 @@ namespace LLStringFn
}
}
+////////////////////////////////////////////////////////////
+
+//static
+template<>
+void LLStringUtil::getTokens(const std::string& instr, std::vector<std::string >& tokens, const std::string& delims)
+{
+ std::string currToken;
+ std::string::size_type begIdx, endIdx;
+
+ begIdx = instr.find_first_not_of (delims);
+ while (begIdx != std::string::npos)
+ {
+ endIdx = instr.find_first_of (delims, begIdx);
+ if (endIdx == std::string::npos)
+ {
+ endIdx = instr.length();
+ }
+
+ currToken = instr.substr(begIdx, endIdx - begIdx);
+ LLStringUtil::trim (currToken);
+ tokens.push_back(currToken);
+ begIdx = instr.find_first_not_of (delims, endIdx);
+ }
+}
+
+template<>
+LLStringUtil::size_type LLStringUtil::getSubstitution(const std::string& instr, size_type& start, std::vector<std::string>& tokens)
+{
+ const std::string delims (",");
+
+ // Find the first ]
+ size_type pos2 = instr.find(']', start);
+ if (pos2 == std::string::npos)
+ return std::string::npos;
+
+ // Find the last [ before ]
+ size_type pos1 = instr.find_last_of('[', pos2-1);
+ if (pos1 == std::string::npos || pos1 < start)
+ return std::string::npos;
+
+ getTokens(std::string(instr,pos1+1,pos2-pos1-1), tokens, delims);
+ start = pos2+1;
+
+ return pos1;
+}
+
+// static
+template<>
+bool LLStringUtil::simpleReplacement(std::string &replacement, std::string token, const format_map_t& substitutions)
+{
+ // see if we have a replacement for the bracketed string (without the brackets)
+ // test first using has() because if we just look up with operator[] we get back an
+ // empty string even if the value is missing. We want to distinguish between
+ // missing replacements and deliberately empty replacement strings.
+ format_map_t::const_iterator iter = substitutions.find(token);
+ if (iter != substitutions.end())
+ {
+ replacement = iter->second;
+ return true;
+ }
+ // if not, see if there's one WITH brackets
+ iter = substitutions.find(std::string("[" + token + "]"));
+ if (iter != substitutions.end())
+ {
+ replacement = iter->second;
+ return true;
+ }
+
+ return false;
+}
+
+// static
+template<>
+bool LLStringUtil::simpleReplacement(std::string &replacement, std::string token, const LLSD& substitutions)
+{
+ // see if we have a replacement for the bracketed string (without the brackets)
+ // test first using has() because if we just look up with operator[] we get back an
+ // empty string even if the value is missing. We want to distinguish between
+ // missing replacements and deliberately empty replacement strings.
+ if (substitutions.has(token))
+ {
+ replacement = substitutions[token].asString();
+ return true;
+ }
+ // if not, see if there's one WITH brackets
+ else if (substitutions.has(std::string("[" + token + "]")))
+ {
+ replacement = substitutions[std::string("[" + token + "]")].asString();
+ return true;
+ }
+
+ return false;
+}
+
+// static
+template<>
+void LLStringUtil::formatNumber(std::string& numStr, std::string decimals)
+{
+ std::stringstream strStream;
+ S32 intDecimals = 0;
+
+ convertToS32 (decimals, intDecimals);
+ if (!sLocale.empty())
+ {
+ strStream.imbue (std::locale(sLocale.c_str()));
+ }
+
+ if (!intDecimals)
+ {
+ S32 intStr;
+
+ if (convertToS32(numStr, intStr))
+ {
+ strStream << intStr;
+ numStr = strStream.str();
+ }
+ }
+ else
+ {
+ F32 floatStr;
+
+ if (convertToF32(numStr, floatStr))
+ {
+ strStream << std::fixed << std::showpoint << std::setprecision(intDecimals) << floatStr;
+ numStr = strStream.str();
+ }
+ }
+}
+
+// static
+template<>
+bool LLStringUtil::formatDatetime(std::string& replacement, std::string token,
+ std::string param, S32 secFromEpoch)
+{
+ if (param == "local") // local
+ {
+ secFromEpoch -= LLStringOps::getLocalTimeOffset();
+ }
+ else if (param != "utc") // slt
+ {
+ secFromEpoch -= LLStringOps::getPacificTimeOffset();
+ }
+
+ // if never fell into those two ifs above, param must be utc
+ if (secFromEpoch < 0) secFromEpoch = 0;
+
+ LLDate datetime((F64)secFromEpoch);
+ std::string code = LLStringOps::getDatetimeCode (token);
+
+ // special case to handle timezone
+ if (code == "%Z") {
+ if (param == "utc")
+ {
+ replacement = "GMT";
+ }
+ else if (param == "local")
+ {
+ replacement = ""; // user knows their own timezone
+ }
+ else
+ {
+ // "slt" = Second Life Time, which is deprecated.
+ // If not utc or user local time, fallback to Pacific time
+ replacement = LLStringOps::getPacificDaylightTime() ? "PDT" : "PST";
+ }
+ return true;
+ }
+ replacement = datetime.toHTTPDateString(code);
+
+ // *HACK: delete leading zero from hour string in case 'hour12' (code = %I) time format
+ // to show time without leading zero, e.g. 08:16 -> 8:16 (EXT-2738).
+ // We could have used '%l' format instead, but it's not supported by Windows.
+ if(code == "%I" && token == "hour12" && replacement.at(0) == '0')
+ {
+ replacement = replacement.at(1);
+ }
+
+ return !code.empty();
+}
+
+// LLStringUtil::format recogizes the following patterns.
+// All substitutions *must* be encased in []'s in the input string.
+// The []'s are optional in the substitution map.
+// [FOO_123]
+// [FOO,number,precision]
+// [FOO,datetime,format]
+
+
+// static
+template<>
+S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions)
+{
+ LLFastTimer ft(FT_STRING_FORMAT);
+ S32 res = 0;
+
+ std::string output;
+ std::vector<std::string> tokens;
+
+ std::string::size_type start = 0;
+ std::string::size_type prev_start = 0;
+ std::string::size_type key_start = 0;
+ while ((key_start = getSubstitution(s, start, tokens)) != std::string::npos)
+ {
+ output += std::string(s, prev_start, key_start-prev_start);
+ prev_start = start;
+
+ bool found_replacement = false;
+ std::string replacement;
+
+ if (tokens.size() == 0)
+ {
+ found_replacement = false;
+ }
+ else if (tokens.size() == 1)
+ {
+ found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
+ }
+ else if (tokens[1] == "number")
+ {
+ std::string param = "0";
+
+ if (tokens.size() > 2) param = tokens[2];
+ found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
+ if (found_replacement) formatNumber (replacement, param);
+ }
+ else if (tokens[1] == "datetime")
+ {
+ std::string param;
+ if (tokens.size() > 2) param = tokens[2];
+
+ format_map_t::const_iterator iter = substitutions.find("datetime");
+ if (iter != substitutions.end())
+ {
+ S32 secFromEpoch = 0;
+ BOOL r = LLStringUtil::convertToS32(iter->second, secFromEpoch);
+ if (r)
+ {
+ found_replacement = formatDatetime(replacement, tokens[0], param, secFromEpoch);
+ }
+ }
+ }
+
+ if (found_replacement)
+ {
+ output += replacement;
+ res++;
+ }
+ else
+ {
+ // we had no replacement, use the string as is
+ // e.g. "hello [MISSING_REPLACEMENT]" or "-=[Stylized Name]=-"
+ output += std::string(s, key_start, start-key_start);
+ }
+ tokens.clear();
+ }
+ // send the remainder of the string (with no further matches for bracketed names)
+ output += std::string(s, start);
+ s = output;
+ return res;
+}
+
+//static
+template<>
+S32 LLStringUtil::format(std::string& s, const LLSD& substitutions)
+{
+ LLFastTimer ft(FT_STRING_FORMAT);
+ S32 res = 0;
+
+ if (!substitutions.isMap())
+ {
+ return res;
+ }
+
+ std::string output;
+ std::vector<std::string> tokens;
+
+ std::string::size_type start = 0;
+ std::string::size_type prev_start = 0;
+ std::string::size_type key_start = 0;
+ while ((key_start = getSubstitution(s, start, tokens)) != std::string::npos)
+ {
+ output += std::string(s, prev_start, key_start-prev_start);
+ prev_start = start;
+
+ bool found_replacement = false;
+ std::string replacement;
+
+ if (tokens.size() == 0)
+ {
+ found_replacement = false;
+ }
+ else if (tokens.size() == 1)
+ {
+ found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
+ }
+ else if (tokens[1] == "number")
+ {
+ std::string param = "0";
+
+ if (tokens.size() > 2) param = tokens[2];
+ found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
+ if (found_replacement) formatNumber (replacement, param);
+ }
+ else if (tokens[1] == "datetime")
+ {
+ std::string param;
+ if (tokens.size() > 2) param = tokens[2];
+
+ S32 secFromEpoch = (S32) substitutions["datetime"].asInteger();
+ found_replacement = formatDatetime (replacement, tokens[0], param, secFromEpoch);
+ }
+
+ if (found_replacement)
+ {
+ output += replacement;
+ res++;
+ }
+ else
+ {
+ // we had no replacement, use the string as is
+ // e.g. "hello [MISSING_REPLACEMENT]" or "-=[Stylized Name]=-"
+ output += std::string(s, key_start, start-key_start);
+ }
+ tokens.clear();
+ }
+ // send the remainder of the string (with no further matches for bracketed names)
+ output += std::string(s, start);
+ s = output;
+ return res;
+}
////////////////////////////////////////////////////////////
// Testing
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index 6ba665b8d2..31e70e0fe4 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -34,6 +34,11 @@
#define LL_LLSTRING_H
#include <string>
+#include <cstdio>
+#include <locale>
+#include <iomanip>
+#include "llsd.h"
+#include "llfasttimer.h"
#if LL_LINUX || LL_SOLARIS
#include <wctype.h>
@@ -143,8 +148,14 @@ struct char_traits<U16>
};
#endif
-class LLStringOps
+class LL_COMMON_API LLStringOps
{
+private:
+ static long sPacificTimeOffset;
+ static long sLocalTimeOffset;
+ static bool sPacificDaylightTime;
+ static std::map<std::string, std::string> datetimeToCodes;
+
public:
static char toUpper(char elem) { return toupper((unsigned char)elem); }
static llwchar toUpper(llwchar elem) { return towupper(elem); }
@@ -172,14 +183,23 @@ public:
static S32 collate(const char* a, const char* b) { return strcoll(a, b); }
static S32 collate(const llwchar* a, const llwchar* b);
+
+ static void setupDatetimeInfo(bool pacific_daylight_time);
+ static long getPacificTimeOffset(void) { return sPacificTimeOffset;}
+ static long getLocalTimeOffset(void) { return sLocalTimeOffset;}
+ // Is the Pacific time zone (aka server time zone)
+ // currently in daylight savings time?
+ static bool getPacificDaylightTime(void) { return sPacificDaylightTime;}
+
+ static std::string getDatetimeCode (std::string key);
};
/**
* @brief Return a string constructed from in without crashing if the
* pointer is NULL.
*/
-std::string ll_safe_string(const char* in);
-std::string ll_safe_string(const char* in, S32 maxlen);
+LL_COMMON_API std::string ll_safe_string(const char* in);
+LL_COMMON_API std::string ll_safe_string(const char* in, S32 maxlen);
// Allowing assignments from non-strings into format_map_t is apparently
@@ -201,6 +221,9 @@ private:
template <class T>
class LLStringUtilBase
{
+private:
+ static std::string sLocale;
+
public:
typedef typename std::basic_string<T>::size_type size_type;
@@ -211,7 +234,15 @@ public:
static std::basic_string<T> null;
typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
- static S32 format(std::basic_string<T>& s, const format_map_t& fmt_map);
+ LL_COMMON_API static void getTokens(const std::basic_string<T>& instr, std::vector<std::basic_string<T> >& tokens, const std::basic_string<T>& delims);
+ LL_COMMON_API static void formatNumber(std::basic_string<T>& numStr, std::basic_string<T> decimals);
+ LL_COMMON_API static bool formatDatetime(std::basic_string<T>& replacement, std::basic_string<T> token, std::basic_string<T> param, S32 secFromEpoch);
+ LL_COMMON_API static S32 format(std::basic_string<T>& s, const format_map_t& substitutions);
+ LL_COMMON_API static S32 format(std::basic_string<T>& s, const LLSD& substitutions);
+ LL_COMMON_API static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const format_map_t& substitutions);
+ LL_COMMON_API static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const LLSD& substitutions);
+ static void setLocale (std::string inLocale) {sLocale = inLocale;};
+ static std::string getLocale (void) {return sLocale;};
static bool isValidIndex(const std::basic_string<T>& string, size_type i)
{
@@ -253,7 +284,8 @@ public:
static void replaceTabsWithSpaces( std::basic_string<T>& string, size_type spaces_per_tab );
static void replaceNonstandardASCII( std::basic_string<T>& string, T replacement );
static void replaceChar( std::basic_string<T>& string, T target, T replacement );
-
+ static void replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement );
+
static BOOL containsNonprintable(const std::basic_string<T>& string);
static void stripNonprintable(std::basic_string<T>& string);
@@ -310,13 +342,19 @@ public:
// Copies src into dst at a given offset.
static void copyInto(std::basic_string<T>& dst, const std::basic_string<T>& src, size_type offset);
+ static bool isPartOfWord(T c) { return (c == (T)'_') || LLStringOps::isAlnum(c); }
+
+
#ifdef _DEBUG
- static void testHarness();
+ LL_COMMON_API static void testHarness();
#endif
+private:
+ LL_COMMON_API static size_type getSubstitution(const std::basic_string<T>& instr, size_type& start, std::vector<std::basic_string<T> >& tokens);
};
template<class T> std::basic_string<T> LLStringUtilBase<T>::null;
+template<class T> std::string LLStringUtilBase<T>::sLocale;
typedef LLStringUtilBase<char> LLStringUtil;
typedef LLStringUtilBase<llwchar> LLWStringUtil;
@@ -366,7 +404,7 @@ inline std::string chop_tail_copy(
* @brief This translates a nybble stored as a hex value from 0-f back
* to a nybble in the low order bits of the return byte.
*/
-U8 hex_as_nybble(char hex);
+LL_COMMON_API U8 hex_as_nybble(char hex);
/**
* @brief read the contents of a file into a string.
@@ -377,7 +415,8 @@ U8 hex_as_nybble(char hex);
* @param filename The full name of the file to read.
* @return Returns true on success. If false, str is unmodified.
*/
-bool _read_file_into_string(std::string& str, const std::string& filename);
+LL_COMMON_API bool _read_file_into_string(std::string& str, const std::string& filename);
+LL_COMMON_API bool iswindividual(llwchar elem);
/**
* Unicode support
@@ -386,52 +425,52 @@ bool _read_file_into_string(std::string& str, const std::string& filename);
// Make the incoming string a utf8 string. Replaces any unknown glyph
// with the UNKOWN_CHARACTER. Once any unknown glph is found, the rest
// of the data may not be recovered.
-std::string rawstr_to_utf8(const std::string& raw);
+LL_COMMON_API std::string rawstr_to_utf8(const std::string& raw);
//
// We should never use UTF16 except when communicating with Win32!
//
typedef std::basic_string<U16> llutf16string;
-LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len);
-LLWString utf16str_to_wstring(const llutf16string &utf16str);
+LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len);
+LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str);
-llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len);
-llutf16string wstring_to_utf16str(const LLWString &utf32str);
+LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len);
+LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str);
-llutf16string utf8str_to_utf16str ( const std::string& utf8str, S32 len);
-llutf16string utf8str_to_utf16str ( const std::string& utf8str );
+LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str, S32 len);
+LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str );
-LLWString utf8str_to_wstring(const std::string &utf8str, S32 len);
-LLWString utf8str_to_wstring(const std::string &utf8str);
+LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str, S32 len);
+LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str);
// Same function, better name. JC
inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); }
//
-S32 wchar_to_utf8chars(llwchar inchar, char* outchars);
+LL_COMMON_API S32 wchar_to_utf8chars(llwchar inchar, char* outchars);
-std::string wstring_to_utf8str(const LLWString &utf32str, S32 len);
-std::string wstring_to_utf8str(const LLWString &utf32str);
+LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str, S32 len);
+LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str);
-std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len);
-std::string utf16str_to_utf8str(const llutf16string &utf16str);
+LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len);
+LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str);
// Length of this UTF32 string in bytes when transformed to UTF8
-S32 wstring_utf8_length(const LLWString& wstr);
+LL_COMMON_API S32 wstring_utf8_length(const LLWString& wstr);
// Length in bytes of this wide char in a UTF8 string
-S32 wchar_utf8_length(const llwchar wc);
+LL_COMMON_API S32 wchar_utf8_length(const llwchar wc);
-std::string utf8str_tolower(const std::string& utf8str);
+LL_COMMON_API std::string utf8str_tolower(const std::string& utf8str);
// Length in llwchar (UTF-32) of the first len units (16 bits) of the given UTF-16 string.
-S32 utf16str_wstring_length(const llutf16string &utf16str, S32 len);
+LL_COMMON_API S32 utf16str_wstring_length(const llutf16string &utf16str, S32 len);
// Length in utf16string (UTF-16) of wlen wchars beginning at woffset.
-S32 wstring_utf16_length(const LLWString & wstr, S32 woffset, S32 wlen);
+LL_COMMON_API S32 wstring_utf16_length(const LLWString & wstr, S32 woffset, S32 wlen);
// Length in wstring (i.e., llwchar count) of a part of a wstring specified by utf16 length (i.e., utf16 units.)
-S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset, S32 utf16_length, BOOL *unaligned = NULL);
+LL_COMMON_API S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset, S32 utf16_length, BOOL *unaligned = NULL);
/**
* @brief Properly truncate a utf8 string to a maximum byte count.
@@ -443,11 +482,11 @@ S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset
* @param max_len The maximum number of bytes in the return value.
* @return Returns a valid utf8 string with byte count <= max_len.
*/
-std::string utf8str_truncate(const std::string& utf8str, const S32 max_len);
+LL_COMMON_API std::string utf8str_truncate(const std::string& utf8str, const S32 max_len);
-std::string utf8str_trim(const std::string& utf8str);
+LL_COMMON_API std::string utf8str_trim(const std::string& utf8str);
-S32 utf8str_compare_insensitive(
+LL_COMMON_API S32 utf8str_compare_insensitive(
const std::string& lhs,
const std::string& rhs);
@@ -458,17 +497,17 @@ S32 utf8str_compare_insensitive(
* @param target_char The wchar to be replaced
* @param replace_char The wchar which is written on replace
*/
-std::string utf8str_substChar(
+LL_COMMON_API std::string utf8str_substChar(
const std::string& utf8str,
const llwchar target_char,
const llwchar replace_char);
-std::string utf8str_makeASCII(const std::string& utf8str);
+LL_COMMON_API std::string utf8str_makeASCII(const std::string& utf8str);
// Hack - used for evil notecards.
-std::string mbcsstring_makeASCII(const std::string& str);
+LL_COMMON_API std::string mbcsstring_makeASCII(const std::string& str);
-std::string utf8str_removeCRLF(const std::string& utf8str);
+LL_COMMON_API std::string utf8str_removeCRLF(const std::string& utf8str);
#if LL_WINDOWS
@@ -493,14 +532,21 @@ std::string utf8str_removeCRLF(const std::string& utf8str);
* formatted string.
*
*/
-int safe_snprintf(char* str, size_t size, const char* format, ...);
+
+// Deal with the differeneces on Windows
+namespace snprintf_hack
+{
+ LL_COMMON_API int snprintf(char *str, size_t size, const char *format, ...);
+}
+
+using snprintf_hack::snprintf;
/**
* @brief Convert a wide string to std::string
*
* This replaces the unsafe W2A macro from ATL.
*/
-std::string ll_convert_wide_to_string(const wchar_t* in);
+LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in);
//@}
#endif // LL_WINDOWS
@@ -523,7 +569,7 @@ namespace LLStringFn
* with zero non-printable characters.
* @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
*/
- void replace_nonprintable_in_ascii(
+ LL_COMMON_API void replace_nonprintable_in_ascii(
std::basic_string<char>& string,
char replacement);
@@ -537,7 +583,7 @@ namespace LLStringFn
* with zero non-printable characters and zero pipe characters.
* @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
*/
- void replace_nonprintable_and_pipe_in_ascii(std::basic_string<char>& str,
+ LL_COMMON_API void replace_nonprintable_and_pipe_in_ascii(std::basic_string<char>& str,
char replacement);
@@ -546,7 +592,7 @@ namespace LLStringFn
* Returns a copy of the string with those characters removed.
* Works with US ASCII and UTF-8 encoded strings. JC
*/
- std::string strip_invalid_xml(const std::string& input);
+ LL_COMMON_API std::string strip_invalid_xml(const std::string& input);
/**
@@ -557,69 +603,18 @@ namespace LLStringFn
* with zero non-printable characters.
* @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
*/
- void replace_ascii_controlchars(
+ LL_COMMON_API void replace_ascii_controlchars(
std::basic_string<char>& string,
char replacement);
}
////////////////////////////////////////////////////////////
+// NOTE: LLStringUtil::format, getTokens, and support functions moved to llstring.cpp.
+// There is no LLWStringUtil::format implementation currently.
+// Calling thse for anything other than LLStringUtil will produce link errors.
-// LLStringBase::format()
-//
-// This function takes a string 's' and a map 'fmt_map' of strings-to-strings.
-// All occurances of strings in 's' from the left-hand side of 'fmt_map' are
-// then replaced with the corresponding right-hand side of 'fmt_map', non-
-// recursively. The function returns the number of substitutions made.
-
-// static
-template<class T>
-S32 LLStringUtilBase<T>::format(std::basic_string<T>& s, const format_map_t& fmt_map)
-{
- typedef typename std::basic_string<T>::size_type string_size_type_t;
- string_size_type_t scanstart = 0;
- S32 res = 0;
-
- // Look for the first match of any keyword, replace that keyword,
- // repeat from the end of the replacement string. This avoids
- // accidentally performing substitution on a substituted string.
- while (1)
- {
- string_size_type_t first_match_pos = scanstart;
- string_size_type_t first_match_str_length = 0;
- std::basic_string<T> first_match_str_replacement;
-
- for (format_map_t::const_iterator iter = fmt_map.begin();
- iter != fmt_map.end();
- ++iter)
- {
- string_size_type_t n = s.find(iter->first, scanstart);
- if (n != std::basic_string<T>::npos &&
- (n < first_match_pos ||
- 0 == first_match_str_length))
- {
- first_match_pos = n;
- first_match_str_length = iter->first.length();
- first_match_str_replacement = iter->second;
- }
- }
+////////////////////////////////////////////////////////////
- if (0 == first_match_str_length)
- {
- // no more keys found to substitute from this point
- // in the string forward.
- break;
- }
- else
- {
- s.erase(first_match_pos, first_match_str_length);
- s.insert(first_match_pos, first_match_str_replacement);
- scanstart = first_match_pos +
- first_match_str_replacement.length();
- ++res;
- }
- }
- return res;
-}
// static
template<class T>
@@ -917,11 +912,22 @@ template<class T>
void LLStringUtilBase<T>::replaceChar( std::basic_string<T>& string, T target, T replacement )
{
size_type found_pos = 0;
- for (found_pos = string.find(target, found_pos);
- found_pos != std::basic_string<T>::npos;
- found_pos = string.find(target, found_pos))
+ while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos )
{
string[found_pos] = replacement;
+ found_pos++; // avoid infinite defeat if target == replacement
+ }
+}
+
+//static
+template<class T>
+void LLStringUtilBase<T>::replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement )
+{
+ size_type found_pos = 0;
+ while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos )
+ {
+ string.replace( found_pos, target.length(), replacement );
+ found_pos += replacement.length(); // avoid infinite defeat if replacement contains target
}
}
@@ -996,14 +1002,15 @@ void LLStringUtilBase<T>::stripNonprintable(std::basic_string<T>& string)
{
return;
}
- char* c_string = new char[string.size() + 1];
+ size_t src_size = string.size();
+ char* c_string = new char[src_size + 1];
if(c_string == NULL)
{
return;
}
- strcpy(c_string, string.c_str()); /*Flawfinder: ignore*/
+ copy(c_string, string.c_str(), src_size+1);
char* write_head = &c_string[0];
- for (size_type i = 0; i < string.size(); i++)
+ for (size_type i = 0; i < src_size; i++)
{
char* read_head = &string[i];
write_head = &c_string[j];
diff --git a/indra/llcommon/llstringtable.cpp b/indra/llcommon/llstringtable.cpp
index 27f9036b8b..2f3a994d8f 100644
--- a/indra/llcommon/llstringtable.cpp
+++ b/indra/llcommon/llstringtable.cpp
@@ -38,6 +38,23 @@
LLStringTable gStringTable(32768);
+LLStringTableEntry::LLStringTableEntry(const char *str)
+: mString(NULL), mCount(1)
+{
+ // Copy string
+ U32 length = (U32)strlen(str) + 1; /*Flawfinder: ignore*/
+ length = llmin(length, MAX_STRINGS_LENGTH);
+ mString = new char[length];
+ strncpy(mString, str, length); /*Flawfinder: ignore*/
+ mString[length - 1] = 0;
+}
+
+LLStringTableEntry::~LLStringTableEntry()
+{
+ delete [] mString;
+ mCount = 0;
+}
+
LLStringTable::LLStringTable(int tablesize)
: mUniqueEntries(0)
{
diff --git a/indra/llcommon/llstringtable.h b/indra/llcommon/llstringtable.h
index 4492063275..d40c9d8dfd 100644
--- a/indra/llcommon/llstringtable.h
+++ b/indra/llcommon/llstringtable.h
@@ -48,32 +48,22 @@
//# define STRING_TABLE_HASH_MAP 1
#endif
-#if LL_WINDOWS
-#include <hash_map>
-#else
-#include <ext/hash_map>
+#if STRING_TABLE_HASH_MAP
+# if LL_WINDOWS
+# include <hash_map>
+# else
+# include <ext/hash_map>
+# endif
#endif
const U32 MAX_STRINGS_LENGTH = 256;
-class LLStringTableEntry
+class LL_COMMON_API LLStringTableEntry
{
public:
- LLStringTableEntry(const char *str)
- : mString(NULL), mCount(1)
- {
- // Copy string
- U32 length = (U32)strlen(str) + 1; /*Flawfinder: ignore*/
- length = llmin(length, MAX_STRINGS_LENGTH);
- mString = new char[length];
- strncpy(mString, str, length); /*Flawfinder: ignore*/
- mString[length - 1] = 0;
- }
- ~LLStringTableEntry()
- {
- delete [] mString;
- mCount = 0;
- }
+ LLStringTableEntry(const char *str);
+ ~LLStringTableEntry();
+
void incCount() { mCount++; }
BOOL decCount() { return --mCount; }
@@ -81,7 +71,7 @@ public:
S32 mCount;
};
-class LLStringTable
+class LL_COMMON_API LLStringTable
{
public:
LLStringTable(int tablesize);
@@ -115,7 +105,7 @@ public:
#endif
};
-extern LLStringTable gStringTable;
+extern LL_COMMON_API LLStringTable gStringTable;
//============================================================================
@@ -125,7 +115,7 @@ extern LLStringTable gStringTable;
typedef const std::string* LLStdStringHandle;
-class LLStdStringTable
+class LL_COMMON_API LLStdStringTable
{
public:
LLStdStringTable(S32 tablesize = 0)
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 4d03c4d40d..0272c55db2 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -76,6 +76,75 @@ extern int errno;
static const S32 CPUINFO_BUFFER_SIZE = 16383;
LLCPUInfo gSysCPU;
+#if LL_WINDOWS
+#ifndef DLLVERSIONINFO
+typedef struct _DllVersionInfo
+{
+ DWORD cbSize;
+ DWORD dwMajorVersion;
+ DWORD dwMinorVersion;
+ DWORD dwBuildNumber;
+ DWORD dwPlatformID;
+}DLLVERSIONINFO;
+#endif
+
+#ifndef DLLGETVERSIONPROC
+typedef int (FAR WINAPI *DLLGETVERSIONPROC) (DLLVERSIONINFO *);
+#endif
+
+bool get_shell32_dll_version(DWORD& major, DWORD& minor, DWORD& build_number)
+{
+ bool result = false;
+ const U32 BUFF_SIZE = 32767;
+ WCHAR tempBuf[BUFF_SIZE];
+ if(GetSystemDirectory((LPWSTR)&tempBuf, BUFF_SIZE))
+ {
+
+ std::basic_string<WCHAR> shell32_path(tempBuf);
+
+ // Shell32.dll contains the DLLGetVersion function.
+ // according to msdn its not part of the API
+ // so you have to go in and get it.
+ // http://msdn.microsoft.com/en-us/library/bb776404(VS.85).aspx
+ shell32_path += TEXT("\\shell32.dll");
+
+ HMODULE hDllInst = LoadLibrary(shell32_path.c_str()); //load the DLL
+ if(hDllInst)
+ { // Could successfully load the DLL
+ DLLGETVERSIONPROC pDllGetVersion;
+ /*
+ You must get this function explicitly because earlier versions of the DLL
+ don't implement this function. That makes the lack of implementation of the
+ function a version marker in itself.
+ */
+ pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hDllInst,
+ "DllGetVersion");
+
+ if(pDllGetVersion)
+ {
+ // DLL supports version retrieval function
+ DLLVERSIONINFO dvi;
+
+ ZeroMemory(&dvi, sizeof(dvi));
+ dvi.cbSize = sizeof(dvi);
+ HRESULT hr = (*pDllGetVersion)(&dvi);
+
+ if(SUCCEEDED(hr))
+ { // Finally, the version is at our hands
+ major = dvi.dwMajorVersion;
+ minor = dvi.dwMinorVersion;
+ build_number = dvi.dwBuildNumber;
+ result = true;
+ }
+ }
+
+ FreeLibrary(hDllInst); // Release DLL
+ }
+ }
+ return result;
+}
+#endif // LL_WINDOWS
+
LLOSInfo::LLOSInfo() :
mMajorVer(0), mMinorVer(0), mBuild(0)
{
@@ -98,6 +167,11 @@ LLOSInfo::LLOSInfo() :
mMinorVer = osvi.dwMinorVersion;
mBuild = osvi.dwBuildNumber;
+ DWORD shell32_major, shell32_minor, shell32_build;
+ bool got_shell32_version = get_shell32_dll_version(shell32_major,
+ shell32_minor,
+ shell32_build);
+
switch(osvi.dwPlatformId)
{
case VER_PLATFORM_WIN32_NT:
@@ -122,14 +196,50 @@ LLOSInfo::LLOSInfo() :
else
mOSStringSimple = "Microsoft Windows Server 2003 ";
}
- else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0)
+ else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion <= 1)
{
- if(osvi.wProductType == VER_NT_WORKSTATION)
+ if(osvi.dwMinorVersion == 0)
+ {
mOSStringSimple = "Microsoft Windows Vista ";
- else mOSStringSimple = "Microsoft Windows Vista Server ";
+ }
+ else if(osvi.dwMinorVersion == 1)
+ {
+ mOSStringSimple = "Microsoft Windows 7 ";
+ }
+
+ if(osvi.wProductType != VER_NT_WORKSTATION)
+ {
+ mOSStringSimple += "Server ";
+ }
+
+ ///get native system info if available..
+ typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); ///function pointer for loading GetNativeSystemInfo
+ SYSTEM_INFO si; //System Info object file contains architecture info
+ PGNSI pGNSI; //pointer object
+ ZeroMemory(&si, sizeof(SYSTEM_INFO)); //zero out the memory in information
+ pGNSI = (PGNSI) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo"); //load kernel32 get function
+ if(NULL != pGNSI) //check if it has failed
+ pGNSI(&si); //success
+ else
+ GetSystemInfo(&si); //if it fails get regular system info
+ //(Warning: If GetSystemInfo it may result in incorrect information in a WOW64 machine, if the kernel fails to load)
+
+ //msdn microsoft finds 32 bit and 64 bit flavors this way..
+ //http://msdn.microsoft.com/en-us/library/ms724429(VS.85).aspx (example code that contains quite a few more flavors
+ //of windows than this code does (in case it is needed for the future)
+ if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 ) //check for 64 bit
+ {
+ mOSStringSimple += "64-bit ";
+ }
+ else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL )
+ {
+ mOSStringSimple += "32-bit ";
+ }
}
else // Use the registry on early versions of Windows NT.
{
+ mOSStringSimple = "Microsoft Windows (unrecognized) ";
+
HKEY hKey;
WCHAR szProductType[80];
DWORD dwBufLen;
@@ -170,6 +280,7 @@ LLOSInfo::LLOSInfo() :
csdversion.c_str(),
(osvi.dwBuildNumber & 0xffff));
}
+
mOSString = mOSStringSimple + tmpstr;
}
break;
@@ -199,6 +310,21 @@ LLOSInfo::LLOSInfo() :
mOSString = mOSStringSimple;
break;
}
+
+ std::string compatibility_mode;
+ if(got_shell32_version)
+ {
+ if(osvi.dwMajorVersion != shell32_major
+ || osvi.dwMinorVersion != shell32_minor)
+ {
+ compatibility_mode = llformat(" compatibility mode. real ver: %d.%d (Build %d)",
+ shell32_major,
+ shell32_minor,
+ shell32_build);
+ }
+ }
+ mOSString += compatibility_mode;
+
#else
struct utsname un;
if(uname(&un) != -1)
diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h
index 03f48ca018..c2c45bec9a 100644
--- a/indra/llcommon/llsys.h
+++ b/indra/llcommon/llsys.h
@@ -45,7 +45,7 @@
#include <iosfwd>
#include <string>
-class LLOSInfo
+class LL_COMMON_API LLOSInfo
{
public:
LLOSInfo();
@@ -70,7 +70,7 @@ private:
};
-class LLCPUInfo
+class LL_COMMON_API LLCPUInfo
{
public:
LLCPUInfo();
@@ -99,7 +99,7 @@ private:
//
// CLASS LLMemoryInfo
-class LLMemoryInfo
+class LL_COMMON_API LLMemoryInfo
/*! @brief Class to query the memory subsystem
@@ -123,15 +123,15 @@ public:
};
-std::ostream& operator<<(std::ostream& s, const LLOSInfo& info);
-std::ostream& operator<<(std::ostream& s, const LLCPUInfo& info);
-std::ostream& operator<<(std::ostream& s, const LLMemoryInfo& info);
+LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLOSInfo& info);
+LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLCPUInfo& info);
+LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLMemoryInfo& info);
// gunzip srcfile into dstfile. Returns FALSE on error.
-BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile);
+BOOL LL_COMMON_API gunzip_file(const std::string& srcfile, const std::string& dstfile);
// gzip srcfile into dstfile. Returns FALSE on error.
-BOOL gzip_file(const std::string& srcfile, const std::string& dstfile);
+BOOL LL_COMMON_API gzip_file(const std::string& srcfile, const std::string& dstfile);
-extern LLCPUInfo gSysCPU;
+extern LL_COMMON_API LLCPUInfo gSysCPU;
#endif // LL_LLSYS_H
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 920d8c0977..37370e44e7 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -291,8 +291,8 @@ LLMutex::LLMutex(apr_pool_t *poolp) :
LLMutex::~LLMutex()
{
-#if _DEBUG
- llassert(!isLocked()); // better not be locked!
+#if MUTEX_DEBUG
+ llassert_always(!isLocked()); // better not be locked!
#endif
apr_thread_mutex_destroy(mAPRMutexp);
mAPRMutexp = NULL;
@@ -306,10 +306,24 @@ LLMutex::~LLMutex()
void LLMutex::lock()
{
apr_thread_mutex_lock(mAPRMutexp);
+#if MUTEX_DEBUG
+ // Have to have the lock before we can access the debug info
+ U32 id = LLThread::currentID();
+ if (mIsLocked[id] != FALSE)
+ llerrs << "Already locked in Thread: " << id << llendl;
+ mIsLocked[id] = TRUE;
+#endif
}
void LLMutex::unlock()
{
+#if MUTEX_DEBUG
+ // Access the debug info while we have the lock
+ U32 id = LLThread::currentID();
+ if (mIsLocked[id] != TRUE)
+ llerrs << "Not locked in Thread: " << id << llendl;
+ mIsLocked[id] = FALSE;
+#endif
apr_thread_mutex_unlock(mAPRMutexp);
}
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index c8c9fd4eec..adef1a9192 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -33,17 +33,15 @@
#ifndef LL_LLTHREAD_H
#define LL_LLTHREAD_H
-#include "llapr.h"
#include "llapp.h"
-#include "llmemory.h"
-
+#include "llapr.h"
#include "apr_thread_cond.h"
class LLThread;
class LLMutex;
class LLCondition;
-class LLThread
+class LL_COMMON_API LLThread
{
public:
typedef enum e_thread_status
@@ -131,7 +129,9 @@ protected:
//============================================================================
-class LLMutex
+#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
+
+class LL_COMMON_API LLMutex
{
public:
LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex
@@ -145,10 +145,13 @@ protected:
apr_thread_mutex_t *mAPRMutexp;
apr_pool_t *mAPRPoolp;
BOOL mIsLocalPool;
+#if MUTEX_DEBUG
+ std::map<U32, BOOL> mIsLocked;
+#endif
};
// Actually a condition/mutex pair (since each condition needs to be associated with a mutex).
-class LLCondition : public LLMutex
+class LL_COMMON_API LLCondition : public LLMutex
{
public:
LLCondition(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well.
@@ -195,7 +198,7 @@ void LLThread::unlockData()
// see llmemory.h for LLPointer<> definition
-class LLThreadSafeRefCount
+class LL_COMMON_API LLThreadSafeRefCount
{
public:
static void initThreadSafeRefCount(); // creates sMutex
@@ -247,7 +250,7 @@ private:
// Simple responder for self destructing callbacks
// Pure virtual class
-class LLResponder : public LLThreadSafeRefCount
+class LL_COMMON_API LLResponder : public LLThreadSafeRefCount
{
protected:
virtual ~LLResponder();
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index fa6efaf38e..ef3e8dbc94 100644
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -561,40 +561,35 @@ void secondsToTimecodeString(F32 current_time, std::string& tcstring)
//
//////////////////////////////////////////////////////////////////////////////
-std::list<LLEventTimer*> LLEventTimer::sActiveList;
-
LLEventTimer::LLEventTimer(F32 period)
: mEventTimer()
{
mPeriod = period;
- sActiveList.push_back(this);
}
LLEventTimer::LLEventTimer(const LLDate& time)
: mEventTimer()
{
mPeriod = (F32)(time.secondsSinceEpoch() - LLDate::now().secondsSinceEpoch());
- sActiveList.push_back(this);
}
-LLEventTimer::~LLEventTimer()
+LLEventTimer::~LLEventTimer()
{
- sActiveList.remove(this);
}
void LLEventTimer::updateClass()
{
std::list<LLEventTimer*> completed_timers;
- for (std::list<LLEventTimer*>::iterator iter = sActiveList.begin(); iter != sActiveList.end(); )
+ for (instance_iter iter = beginInstances(); iter != endInstances(); )
{
- LLEventTimer* timer = *iter++;
- F32 et = timer->mEventTimer.getElapsedTimeF32();
- if (timer->mEventTimer.getStarted() && et > timer->mPeriod) {
- timer->mEventTimer.reset();
- if ( timer->tick() )
+ LLEventTimer& timer = *iter++;
+ F32 et = timer.mEventTimer.getElapsedTimeF32();
+ if (timer.mEventTimer.getStarted() && et > timer.mPeriod) {
+ timer.mEventTimer.reset();
+ if ( timer.tick() )
{
- completed_timers.push_back( timer );
+ completed_timers.push_back( &timer );
}
}
}
diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h
index e2cf1c7689..d009c0f5f7 100644
--- a/indra/llcommon/lltimer.h
+++ b/indra/llcommon/lltimer.h
@@ -40,6 +40,7 @@
#include "stdtypes.h"
#include "lldate.h"
+#include "llinstancetracker.h"
#include <string>
#include <list>
@@ -54,7 +55,7 @@ const U32 USEC_PER_HOUR = USEC_PER_MIN * MIN_PER_HOUR;
const U32 SEC_PER_HOUR = SEC_PER_MIN * MIN_PER_HOUR;
const F64 SEC_PER_USEC = 1.0 / (F64) USEC_PER_SEC;
-class LLTimer
+class LL_COMMON_API LLTimer
{
public:
static LLTimer *sTimer; // global timer
@@ -113,17 +114,17 @@ public:
//
// Various functions for initializing/accessing clock and timing stuff. Don't use these without REALLY knowing how they work.
//
-U64 get_clock_count();
-F64 calc_clock_frequency(U32 msecs);
-void update_clock_frequencies();
+LL_COMMON_API U64 get_clock_count();
+LL_COMMON_API F64 calc_clock_frequency(U32 msecs);
+LL_COMMON_API void update_clock_frequencies();
// Sleep for milliseconds
-void ms_sleep(U32 ms);
-U32 micro_sleep(U64 us, U32 max_yields = 0xFFFFFFFF);
+LL_COMMON_API void ms_sleep(U32 ms);
+LL_COMMON_API U32 micro_sleep(U64 us, U32 max_yields = 0xFFFFFFFF);
// Returns the correct UTC time in seconds, like time(NULL).
// Useful on the viewer, which may have its local clock set wrong.
-time_t time_corrected();
+LL_COMMON_API time_t time_corrected();
static inline time_t time_min()
{
@@ -154,30 +155,30 @@ static inline time_t time_max()
}
// Correction factor used by time_corrected() above.
-extern S32 gUTCOffset;
+extern LL_COMMON_API S32 gUTCOffset;
// Is the current computer (in its current time zone)
// observing daylight savings time?
-BOOL is_daylight_savings();
+LL_COMMON_API BOOL is_daylight_savings();
// Converts internal "struct tm" time buffer to Pacific Standard/Daylight Time
// Usage:
// S32 utc_time;
// utc_time = time_corrected();
// struct tm* internal_time = utc_to_pacific_time(utc_time, gDaylight);
-struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time);
+LL_COMMON_API struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time);
-void microsecondsToTimecodeString(U64 current_time, std::string& tcstring);
-void secondsToTimecodeString(F32 current_time, std::string& tcstring);
+LL_COMMON_API void microsecondsToTimecodeString(U64 current_time, std::string& tcstring);
+LL_COMMON_API void secondsToTimecodeString(F32 current_time, std::string& tcstring);
// class for scheduling a function to be called at a given frequency (approximate, inprecise)
-class LLEventTimer
+class LL_COMMON_API LLEventTimer : protected LLInstanceTracker<LLEventTimer>
{
public:
LLEventTimer(F32 period); // period is the amount of time between each call to tick() in seconds
LLEventTimer(const LLDate& time);
virtual ~LLEventTimer();
-
+
//function to be called at the supplied frequency
// Normally return FALSE; TRUE will delete the timer after the function returns.
virtual BOOL tick() = 0;
@@ -187,10 +188,8 @@ public:
protected:
LLTimer mEventTimer;
F32 mPeriod;
-
-private:
- //list of active timers
- static std::list<LLEventTimer*> sActiveList; // TODO should this be a vector
};
+U64 LL_COMMON_API totalTime(); // Returns current system time in microseconds
+
#endif
diff --git a/indra/llcommon/lltreeiterators.h b/indra/llcommon/lltreeiterators.h
new file mode 100644
index 0000000000..c946566e84
--- /dev/null
+++ b/indra/llcommon/lltreeiterators.h
@@ -0,0 +1,711 @@
+/**
+ * @file lltreeiterators.h
+ * @author Nat Goodspeed
+ * @date 2008-08-19
+ * @brief This file defines iterators useful for traversing arbitrary node
+ * classes, potentially polymorphic, linked into strict tree
+ * structures.
+ *
+ * Dereferencing any one of these iterators actually yields a @em
+ * pointer to the node in question. For example, given an
+ * LLLinkedIter<MyNode> <tt>li</tt>, <tt>*li</tt> gets you a pointer
+ * to MyNode, and <tt>**li</tt> gets you the MyNode instance itself.
+ * More commonly, instead of writing <tt>li->member</tt>, you write
+ * <tt>(*li)->member</tt> -- as you would if you were traversing an
+ * STL container of MyNode pointers.
+ *
+ * It would certainly be possible to build these iterators so that
+ * <tt>*iterator</tt> would return a reference to the node itself
+ * rather than a pointer to the node, and for many purposes it would
+ * even be more convenient. However, that would be insufficiently
+ * flexible. If you want to use an iterator range to (e.g.) initialize
+ * a std::vector collecting results -- you rarely want to actually @em
+ * copy the nodes in question. You're much more likely to want to copy
+ * <i>pointers to</i> the traversed nodes. Hence these iterators
+ * produce pointers.
+ *
+ * Though you specify the actual NODE class as the template parameter,
+ * these iterators internally use LLPtrTo<> to discover whether to
+ * store and return an LLPointer<NODE> or a simple NODE*.
+ *
+ * By strict tree structures, we mean that each child must have
+ * exactly one parent. This forbids a child claiming any ancestor as a
+ * child of its own. Child nodes with multiple parents will be visited
+ * once for each parent. Cycles in the graph will result in either an
+ * infinite loop or an out-of-memory crash. You Have Been Warned.
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLTREEITERATORS_H)
+#define LL_LLTREEITERATORS_H
+
+#include "llptrto.h"
+#include <vector>
+#include <deque>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/function.hpp>
+#include <boost/static_assert.hpp>
+
+namespace LLTreeIter
+{
+ /// Discriminator between LLTreeUpIter and LLTreeDownIter
+ enum RootIter { UP, DOWN };
+ /// Discriminator between LLTreeDFSIter, LLTreeDFSPostIter and LLTreeBFSIter
+ enum WalkIter { DFS_PRE, DFS_POST, BFS };
+}
+
+/**
+ * LLBaseIter defines some machinery common to all these iterators. We use
+ * boost::iterator_facade to define the iterator boilerplate: the conventional
+ * operators and methods necessary to implement a standards-conforming
+ * iterator. That allows us to specify the actual iterator semantics in terms
+ * of equal(), dereference() and increment() methods.
+ */
+template <class SELFTYPE, class NODE>
+class LLBaseIter: public boost::iterator_facade<SELFTYPE,
+ // use pointer type as the
+ // reference type
+ typename LLPtrTo<NODE>::type,
+ boost::forward_traversal_tag>
+{
+protected:
+ /// LLPtrTo<NODE>::type is either NODE* or LLPointer<NODE>, as appropriate
+ typedef typename LLPtrTo<NODE>::type ptr_type;
+ /// function that advances from this node to next accepts a node pointer
+ /// and returns another
+ typedef boost::function<ptr_type(const ptr_type&)> func_type;
+ typedef SELFTYPE self_type;
+};
+
+/// Functor returning NULL, suitable for an end-iterator's 'next' functor
+template <class NODE>
+typename LLPtrTo<NODE>::type LLNullNextFunctor(const typename LLPtrTo<NODE>::type&)
+{
+ return typename LLPtrTo<NODE>::type();
+}
+
+/**
+ * LLLinkedIter is an iterator over an intrusive singly-linked list. The
+ * beginning of the list is represented by LLLinkedIter(list head); the end is
+ * represented by LLLinkedIter().
+ *
+ * The begin LLLinkedIter must be instantiated with a functor to extract the
+ * 'next' pointer from the current node. Supposing that the link pointer is @c
+ * public, something like:
+ *
+ * @code
+ * NODE* mNext;
+ * @endcode
+ *
+ * you can use (e.g.) <tt>boost::bind(&NODE::mNext, _1)</tt> for the purpose.
+ * Alternatively, you can bind whatever accessor method is normally used to
+ * advance to the next node, e.g. for:
+ *
+ * @code
+ * NODE* next() const;
+ * @endcode
+ *
+ * you can use <tt>boost::bind(&NODE::next, _1)</tt>.
+ */
+template <class NODE>
+class LLLinkedIter: public LLBaseIter<LLLinkedIter<NODE>, NODE>
+{
+ typedef LLBaseIter<LLLinkedIter<NODE>, NODE> super;
+protected:
+ /// some methods need to return a reference to self
+ typedef typename super::self_type self_type;
+ typedef typename super::ptr_type ptr_type;
+ typedef typename super::func_type func_type;
+public:
+ /// Instantiate an LLLinkedIter to start a range, or to end a range before
+ /// a particular list entry. Pass a functor to extract the 'next' pointer
+ /// from the current node.
+ LLLinkedIter(const ptr_type& entry, const func_type& nextfunc):
+ mCurrent(entry),
+ mNextFunc(nextfunc)
+ {}
+ /// Instantiate an LLLinkedIter to end a range at the end of the list
+ LLLinkedIter():
+ mCurrent(),
+ mNextFunc(LLNullNextFunctor<NODE>)
+ {}
+
+private:
+ /// leverage boost::iterator_facade
+ friend class boost::iterator_core_access;
+
+ /// advance
+ void increment()
+ {
+ mCurrent = mNextFunc(mCurrent);
+ }
+ /// equality
+ bool equal(const self_type& that) const { return this->mCurrent == that.mCurrent; }
+ /// dereference
+ ptr_type& dereference() const { return const_cast<ptr_type&>(mCurrent); }
+
+ ptr_type mCurrent;
+ func_type mNextFunc;
+};
+
+/**
+ * LLTreeUpIter walks from the node in hand to the root of the tree. The term
+ * "up" is applied to a tree visualized with the root at the top.
+ *
+ * LLTreeUpIter is an alias for LLLinkedIter, since any linked tree that you
+ * can navigate that way at all contains parent pointers.
+ */
+template <class NODE>
+class LLTreeUpIter: public LLLinkedIter<NODE>
+{
+ typedef LLLinkedIter<NODE> super;
+public:
+ /// Instantiate an LLTreeUpIter to start from a particular tree node, or
+ /// to end a parent traversal before reaching a particular ancestor. Pass
+ /// a functor to extract the 'parent' pointer from the current node.
+ LLTreeUpIter(const typename super::ptr_type& node,
+ const typename super::func_type& parentfunc):
+ super(node, parentfunc)
+ {}
+ /// Instantiate an LLTreeUpIter to end a range at the root of the tree
+ LLTreeUpIter():
+ super()
+ {}
+};
+
+/**
+ * LLTreeDownIter walks from the root of the tree to the node in hand. The
+ * term "down" is applied to a tree visualized with the root at the top.
+ *
+ * Though you instantiate the begin() LLTreeDownIter with a pointer to some
+ * node at an arbitrary location in the tree, the root will be the first node
+ * you dereference and the passed node will be the last node you dereference.
+ *
+ * On construction, LLTreeDownIter walks from the current node to the root,
+ * capturing the path. Then in use, it replays that walk in reverse. As with
+ * all traversals of interesting data structures, it is actively dangerous to
+ * modify the tree during an LLTreeDownIter walk.
+ */
+template <class NODE>
+class LLTreeDownIter: public LLBaseIter<LLTreeDownIter<NODE>, NODE>
+{
+ typedef LLBaseIter<LLTreeDownIter<NODE>, NODE> super;
+ typedef typename super::self_type self_type;
+protected:
+ typedef typename super::ptr_type ptr_type;
+ typedef typename super::func_type func_type;
+private:
+ typedef std::vector<ptr_type> list_type;
+public:
+ /// Instantiate an LLTreeDownIter to end at a particular tree node. Pass a
+ /// functor to extract the 'parent' pointer from the current node.
+ LLTreeDownIter(const ptr_type& node,
+ const func_type& parentfunc)
+ {
+ for (ptr_type n = node; n; n = parentfunc(n))
+ mParents.push_back(n);
+ }
+ /// Instantiate an LLTreeDownIter representing "here", the end of the loop
+ LLTreeDownIter() {}
+
+private:
+ /// leverage boost::iterator_facade
+ friend class boost::iterator_core_access;
+
+ /// advance
+ void increment()
+ {
+ mParents.pop_back();
+ }
+ /// equality
+ bool equal(const self_type& that) const { return this->mParents == that.mParents; }
+ /// implement dereference/indirection operators
+ ptr_type& dereference() const { return const_cast<ptr_type&>(mParents.back()); }
+
+ list_type mParents;
+};
+
+/**
+ * When you want to select between LLTreeUpIter and LLTreeDownIter with a
+ * compile-time discriminator, use LLTreeRootIter with an LLTreeIter::RootIter
+ * template arg.
+ */
+template <LLTreeIter::RootIter DISCRIM, class NODE>
+class LLTreeRootIter
+{
+ enum { use_a_valid_LLTreeIter_RootIter_value = false };
+public:
+ /// Bogus constructors for default (unrecognized discriminator) case
+ template <typename TYPE1, typename TYPE2>
+ LLTreeRootIter(TYPE1, TYPE2)
+ {
+ BOOST_STATIC_ASSERT(use_a_valid_LLTreeIter_RootIter_value);
+ }
+ LLTreeRootIter()
+ {
+ BOOST_STATIC_ASSERT(use_a_valid_LLTreeIter_RootIter_value);
+ }
+};
+
+/// Specialize for LLTreeIter::UP
+template <class NODE>
+class LLTreeRootIter<LLTreeIter::UP, NODE>: public LLTreeUpIter<NODE>
+{
+ typedef LLTreeUpIter<NODE> super;
+public:
+ /// forward begin ctor
+ LLTreeRootIter(const typename super::ptr_type& node,
+ const typename super::func_type& parentfunc):
+ super(node, parentfunc)
+ {}
+ /// forward end ctor
+ LLTreeRootIter():
+ super()
+ {}
+};
+
+/// Specialize for LLTreeIter::DOWN
+template <class NODE>
+class LLTreeRootIter<LLTreeIter::DOWN, NODE>: public LLTreeDownIter<NODE>
+{
+ typedef LLTreeDownIter<NODE> super;
+public:
+ /// forward begin ctor
+ LLTreeRootIter(const typename super::ptr_type& node,
+ const typename super::func_type& parentfunc):
+ super(node, parentfunc)
+ {}
+ /// forward end ctor
+ LLTreeRootIter():
+ super()
+ {}
+};
+
+/**
+ * Instantiated with a tree node, typically the root, LLTreeDFSIter "flattens"
+ * a depth-first tree walk through that node and all its descendants.
+ *
+ * The begin() LLTreeDFSIter must be instantiated with functors to obtain from
+ * a given node begin() and end() iterators for that node's children. For this
+ * reason, you must specify the type of the node's child iterator as an
+ * additional template parameter.
+ *
+ * Specifically, the begin functor must return an iterator whose dereferenced
+ * value is a @em pointer to a child tree node. For instance, if each node
+ * tracks its children in an STL container of node* pointers, you can simply
+ * return that container's begin() iterator.
+ *
+ * Alternatively, if a node tracks its children with a classic linked list,
+ * write a functor returning LLLinkedIter<NODE>.
+ *
+ * The end() LLTreeDFSIter must, of course, match the begin() iterator's
+ * template parameters, but is constructed without runtime parameters.
+ */
+template <class NODE, typename CHILDITER>
+class LLTreeDFSIter: public LLBaseIter<LLTreeDFSIter<NODE, CHILDITER>, NODE>
+{
+ typedef LLBaseIter<LLTreeDFSIter<NODE, CHILDITER>, NODE> super;
+ typedef typename super::self_type self_type;
+protected:
+ typedef typename super::ptr_type ptr_type;
+ // The func_type is different for this: from a NODE pointer, we must
+ // obtain a CHILDITER.
+ typedef boost::function<CHILDITER(const ptr_type&)> func_type;
+private:
+ typedef std::vector<ptr_type> list_type;
+public:
+ /// Instantiate an LLTreeDFSIter to start a depth-first walk. Pass
+ /// functors to extract the 'child begin' and 'child end' iterators from
+ /// each node.
+ LLTreeDFSIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc):
+ mBeginFunc(beginfunc),
+ mEndFunc(endfunc),
+ mSkipChildren(false)
+ {
+ // Only push back this node if it's non-NULL!
+ if (node)
+ mPending.push_back(node);
+ }
+ /// Instantiate an LLTreeDFSIter to mark the end of the walk
+ LLTreeDFSIter() {}
+
+ /// flags iterator logic to skip traversing children of current node on next increment
+ void skipDescendants(bool skip = true) { mSkipChildren = skip; }
+
+private:
+ /// leverage boost::iterator_facade
+ friend class boost::iterator_core_access;
+
+ /// advance
+ /// This implementation is due to http://en.wikipedia.org/wiki/Depth-first_search
+ void increment()
+ {
+ // Capture the node we were just looking at
+ ptr_type current = mPending.back();
+ // Remove it from mPending so we don't process it again later
+ mPending.pop_back();
+ if (!mSkipChildren)
+ {
+ // Add all its children to mPending
+ addChildren(current);
+ }
+ // reset flag after each step
+ mSkipChildren = false;
+ }
+ /// equality
+ bool equal(const self_type& that) const { return this->mPending == that.mPending; }
+ /// implement dereference/indirection operators
+ ptr_type& dereference() const { return const_cast<ptr_type&>(mPending.back()); }
+
+ /// Add the direct children of the specified node to mPending
+ void addChildren(const ptr_type& node)
+ {
+ // If we just use push_back() for each child in turn, we'll end up
+ // processing children in reverse order. We don't want to assume
+ // CHILDITER is reversible: some of the linked trees we'll be
+ // processing manage their children using singly-linked lists. So
+ // figure out how many children there are, grow mPending by that size
+ // and reverse-copy the children into the new space.
+ CHILDITER chi = mBeginFunc(node), chend = mEndFunc(node);
+ // grow mPending by the number of children
+ mPending.resize(mPending.size() + std::distance(chi, chend));
+ // reverse-copy the children into the newly-expanded space
+ std::copy(chi, chend, mPending.rbegin());
+ }
+
+ /// list of the nodes yet to be processed
+ list_type mPending;
+ /// functor to extract begin() child iterator
+ func_type mBeginFunc;
+ /// functor to extract end() child iterator
+ func_type mEndFunc;
+ /// flag which controls traversal of children (skip children of current node if true)
+ bool mSkipChildren;
+};
+
+/**
+ * Instantiated with a tree node, typically the root, LLTreeDFSPostIter
+ * "flattens" a depth-first tree walk through that node and all its
+ * descendants. Whereas LLTreeDFSIter visits each node before visiting any of
+ * its children, LLTreeDFSPostIter visits all of a node's children before
+ * visiting the node itself.
+ *
+ * The begin() LLTreeDFSPostIter must be instantiated with functors to obtain
+ * from a given node begin() and end() iterators for that node's children. For
+ * this reason, you must specify the type of the node's child iterator as an
+ * additional template parameter.
+ *
+ * Specifically, the begin functor must return an iterator whose dereferenced
+ * value is a @em pointer to a child tree node. For instance, if each node
+ * tracks its children in an STL container of node* pointers, you can simply
+ * return that container's begin() iterator.
+ *
+ * Alternatively, if a node tracks its children with a classic linked list,
+ * write a functor returning LLLinkedIter<NODE>.
+ *
+ * The end() LLTreeDFSPostIter must, of course, match the begin() iterator's
+ * template parameters, but is constructed without runtime parameters.
+ */
+template <class NODE, typename CHILDITER>
+class LLTreeDFSPostIter: public LLBaseIter<LLTreeDFSPostIter<NODE, CHILDITER>, NODE>
+{
+ typedef LLBaseIter<LLTreeDFSPostIter<NODE, CHILDITER>, NODE> super;
+ typedef typename super::self_type self_type;
+protected:
+ typedef typename super::ptr_type ptr_type;
+ // The func_type is different for this: from a NODE pointer, we must
+ // obtain a CHILDITER.
+ typedef boost::function<CHILDITER(const ptr_type&)> func_type;
+private:
+ // Upon reaching a given node in our pending list, we need to know whether
+ // we've already pushed that node's children, so we must associate a bool
+ // with each node pointer.
+ typedef std::vector< std::pair<ptr_type, bool> > list_type;
+public:
+ /// Instantiate an LLTreeDFSPostIter to start a depth-first walk. Pass
+ /// functors to extract the 'child begin' and 'child end' iterators from
+ /// each node.
+ LLTreeDFSPostIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc):
+ mBeginFunc(beginfunc),
+ mEndFunc(endfunc),
+ mSkipAncestors(false)
+ {
+ if (! node)
+ return;
+ mPending.push_back(typename list_type::value_type(node, false));
+ makeCurrent();
+ }
+ /// Instantiate an LLTreeDFSPostIter to mark the end of the walk
+ LLTreeDFSPostIter() {}
+
+ /// flags iterator logic to skip traversing ancestors of current node on next increment
+ void skipAncestors(bool skip = true) { mSkipAncestors = skip; }
+
+private:
+ /// leverage boost::iterator_facade
+ friend class boost::iterator_core_access;
+
+ /// advance
+ /// This implementation is due to http://en.wikipedia.org/wiki/Depth-first_search
+ void increment()
+ {
+ // Pop the previous current node
+ mPending.pop_back();
+ makeCurrent();
+ }
+ /// equality
+ bool equal(const self_type& that) const { return this->mPending == that.mPending; }
+ /// implement dereference/indirection operators
+ ptr_type& dereference() const { return const_cast<ptr_type&>(mPending.back().first); }
+
+ struct isOpen
+ {
+ bool operator()(const typename list_type::value_type& item)
+ {
+ return item.second;
+ }
+ };
+
+ /// Call this each time we change mPending.back() -- that is, every time
+ /// we're about to change the value returned by dereference(). If we
+ /// haven't yet pushed the new node's children, do so now.
+ void makeCurrent()
+ {
+ if (mSkipAncestors)
+ {
+ mPending.erase(std::remove_if(mPending.begin(), mPending.end(), isOpen()), mPending.end());
+ mSkipAncestors = false;
+ }
+
+ // Once we've popped the last node, this becomes a no-op.
+ if (mPending.empty())
+ return;
+ // Here mPending.back() holds the node pointer we're proposing to
+ // dereference next. Have we pushed that node's children yet?
+ if (mPending.back().second)
+ return; // if so, it's okay to visit this node now
+ // We haven't yet pushed this node's children. Do so now. Remember
+ // that we did -- while the node in question is still back().
+ mPending.back().second = true;
+ addChildren(mPending.back().first);
+ // Now, because we've just changed mPending.back(), make that new node
+ // current.
+ makeCurrent();
+ }
+
+ /// Add the direct children of the specified node to mPending
+ void addChildren(const ptr_type& node)
+ {
+ // If we just use push_back() for each child in turn, we'll end up
+ // processing children in reverse order. We don't want to assume
+ // CHILDITER is reversible: some of the linked trees we'll be
+ // processing manage their children using singly-linked lists. So
+ // figure out how many children there are, grow mPending by that size
+ // and reverse-copy the children into the new space.
+ CHILDITER chi = mBeginFunc(node), chend = mEndFunc(node);
+ // grow mPending by the number of children
+ mPending.resize(mPending.size() + std::distance(chi, chend));
+ // Reverse-copy the children into the newly-expanded space. We can't
+ // just use std::copy() because the source is a ptr_type, whereas the
+ // dest is a pair of (ptr_type, bool).
+ for (typename list_type::reverse_iterator pi = mPending.rbegin(); chi != chend; ++chi, ++pi)
+ {
+ pi->first = *chi; // copy the child pointer
+ pi->second = false; // we haven't yet pushed this child's chldren
+ }
+ }
+
+ /// list of the nodes yet to be processed
+ list_type mPending;
+ /// functor to extract begin() child iterator
+ func_type mBeginFunc;
+ /// functor to extract end() child iterator
+ func_type mEndFunc;
+ /// flags logic to skip traversal of ancestors of current node
+ bool mSkipAncestors;
+};
+
+/**
+ * Instantiated with a tree node, typically the root, LLTreeBFSIter "flattens"
+ * a breadth-first tree walk through that node and all its descendants.
+ *
+ * The begin() LLTreeBFSIter must be instantiated with functors to obtain from
+ * a given node the begin() and end() iterators of that node's children. For
+ * this reason, you must specify the type of the node's child iterator as an
+ * additional template parameter.
+ *
+ * Specifically, the begin functor must return an iterator whose dereferenced
+ * value is a @em pointer to a child tree node. For instance, if each node
+ * tracks its children in an STL container of node* pointers, you can simply
+ * return that container's begin() iterator.
+ *
+ * Alternatively, if a node tracks its children with a classic linked list,
+ * write a functor returning LLLinkedIter<NODE>.
+ *
+ * The end() LLTreeBFSIter must, of course, match the begin() iterator's
+ * template parameters, but is constructed without runtime parameters.
+ */
+template <class NODE, typename CHILDITER>
+class LLTreeBFSIter: public LLBaseIter<LLTreeBFSIter<NODE, CHILDITER>, NODE>
+{
+ typedef LLBaseIter<LLTreeBFSIter<NODE, CHILDITER>, NODE> super;
+ typedef typename super::self_type self_type;
+protected:
+ typedef typename super::ptr_type ptr_type;
+ // The func_type is different for this: from a NODE pointer, we must
+ // obtain a CHILDITER.
+ typedef boost::function<CHILDITER(const ptr_type&)> func_type;
+private:
+ // We need a FIFO queue rather than a LIFO stack. Use a deque rather than
+ // a vector, since vector can't implement pop_front() efficiently.
+ typedef std::deque<ptr_type> list_type;
+public:
+ /// Instantiate an LLTreeBFSIter to start a depth-first walk. Pass
+ /// functors to extract the 'child begin' and 'child end' iterators from
+ /// each node.
+ LLTreeBFSIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc):
+ mBeginFunc(beginfunc),
+ mEndFunc(endfunc)
+ {
+ if (node)
+ mPending.push_back(node);
+ }
+ /// Instantiate an LLTreeBFSIter to mark the end of the walk
+ LLTreeBFSIter() {}
+
+private:
+ /// leverage boost::iterator_facade
+ friend class boost::iterator_core_access;
+
+ /// advance
+ /// This implementation is due to http://en.wikipedia.org/wiki/Breadth-first_search
+ void increment()
+ {
+ // Capture the node we were just looking at
+ ptr_type current = mPending.front();
+ // Remove it from mPending so we don't process it again later
+ mPending.pop_front();
+ // Add all its children to mPending
+ CHILDITER chend = mEndFunc(current);
+ for (CHILDITER chi = mBeginFunc(current); chi != chend; ++chi)
+ mPending.push_back(*chi);
+ }
+ /// equality
+ bool equal(const self_type& that) const { return this->mPending == that.mPending; }
+ /// implement dereference/indirection operators
+ ptr_type& dereference() const { return const_cast<ptr_type&>(mPending.front()); }
+
+ /// list of the nodes yet to be processed
+ list_type mPending;
+ /// functor to extract begin() child iterator
+ func_type mBeginFunc;
+ /// functor to extract end() child iterator
+ func_type mEndFunc;
+};
+
+/**
+ * When you want to select between LLTreeDFSIter, LLTreeDFSPostIter and
+ * LLTreeBFSIter with a compile-time discriminator, use LLTreeWalkIter with an
+ * LLTreeIter::WalkIter template arg.
+ */
+template <LLTreeIter::WalkIter DISCRIM, class NODE, typename CHILDITER>
+class LLTreeWalkIter
+{
+ enum { use_a_valid_LLTreeIter_WalkIter_value = false };
+public:
+ /// Bogus constructors for default (unrecognized discriminator) case
+ template <typename TYPE1, typename TYPE2>
+ LLTreeWalkIter(TYPE1, TYPE2)
+ {
+ BOOST_STATIC_ASSERT(use_a_valid_LLTreeIter_WalkIter_value);
+ }
+ LLTreeWalkIter()
+ {
+ BOOST_STATIC_ASSERT(use_a_valid_LLTreeIter_WalkIter_value);
+ }
+};
+
+/// Specialize for LLTreeIter::DFS_PRE
+template <class NODE, typename CHILDITER>
+class LLTreeWalkIter<LLTreeIter::DFS_PRE, NODE, CHILDITER>:
+ public LLTreeDFSIter<NODE, CHILDITER>
+{
+ typedef LLTreeDFSIter<NODE, CHILDITER> super;
+public:
+ /// forward begin ctor
+ LLTreeWalkIter(const typename super::ptr_type& node,
+ const typename super::func_type& beginfunc,
+ const typename super::func_type& endfunc):
+ super(node, beginfunc, endfunc)
+ {}
+ /// forward end ctor
+ LLTreeWalkIter():
+ super()
+ {}
+};
+
+/// Specialize for LLTreeIter::DFS_POST
+template <class NODE, typename CHILDITER>
+class LLTreeWalkIter<LLTreeIter::DFS_POST, NODE, CHILDITER>:
+ public LLTreeDFSPostIter<NODE, CHILDITER>
+{
+ typedef LLTreeDFSPostIter<NODE, CHILDITER> super;
+public:
+ /// forward begin ctor
+ LLTreeWalkIter(const typename super::ptr_type& node,
+ const typename super::func_type& beginfunc,
+ const typename super::func_type& endfunc):
+ super(node, beginfunc, endfunc)
+ {}
+ /// forward end ctor
+ LLTreeWalkIter():
+ super()
+ {}
+};
+
+/// Specialize for LLTreeIter::BFS
+template <class NODE, typename CHILDITER>
+class LLTreeWalkIter<LLTreeIter::BFS, NODE, CHILDITER>:
+ public LLTreeBFSIter<NODE, CHILDITER>
+{
+ typedef LLTreeBFSIter<NODE, CHILDITER> super;
+public:
+ /// forward begin ctor
+ LLTreeWalkIter(const typename super::ptr_type& node,
+ const typename super::func_type& beginfunc,
+ const typename super::func_type& endfunc):
+ super(node, beginfunc, endfunc)
+ {}
+ /// forward end ctor
+ LLTreeWalkIter():
+ super()
+ {}
+};
+
+#endif /* ! defined(LL_LLTREEITERATORS_H) */
diff --git a/indra/llcommon/lluri.h b/indra/llcommon/lluri.h
index 8e46e2e89e..8e69e8558a 100644
--- a/indra/llcommon/lluri.h
+++ b/indra/llcommon/lluri.h
@@ -47,7 +47,7 @@ class LLApp;
* See: http://www.ietf.org/rfc/rfc3986.txt
*
*/
-class LLURI
+class LL_COMMON_API LLURI
{
public:
LLURI();
@@ -178,6 +178,6 @@ private:
};
// this operator required for tut
-bool operator!=(const LLURI& first, const LLURI& second);
+LL_COMMON_API bool operator!=(const LLURI& first, const LLURI& second);
#endif // LL_LLURI_H
diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h
index 4b32138a06..c78fb12018 100644
--- a/indra/llcommon/lluuid.h
+++ b/indra/llcommon/lluuid.h
@@ -35,6 +35,7 @@
#include <iostream>
#include <set>
#include "stdtypes.h"
+#include "llpreprocessor.h"
const S32 UUID_BYTES = 16;
const S32 UUID_WORDS = 4;
@@ -47,7 +48,7 @@ struct uuid_time_t {
U32 low;
};
-class LLUUID
+class LL_COMMON_API LLUUID
{
public:
//
@@ -106,8 +107,8 @@ public:
LLUUID combine(const LLUUID& other) const;
void combine(const LLUUID& other, LLUUID& result) const;
- friend std::ostream& operator<<(std::ostream& s, const LLUUID &uuid);
- friend std::istream& operator>>(std::istream& s, LLUUID &uuid);
+ friend LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLUUID &uuid);
+ friend LL_COMMON_API std::istream& operator>>(std::istream& s, LLUUID &uuid);
void toString(char *out) const; // Does not allocate memory, needs 36 characters (including \0)
void toString(std::string& out) const;
@@ -323,7 +324,7 @@ typedef std::set<LLUUID, lluuid_less> uuid_list_t;
*/
typedef LLUUID LLAssetID;
-class LLTransactionID : public LLUUID
+class LL_COMMON_API LLTransactionID : public LLUUID
{
public:
LLTransactionID() : LLUUID() { }
diff --git a/indra/llcommon/llversionserver.h b/indra/llcommon/llversionserver.h
index c0fc06ee6e..0f1e59a18c 100644
--- a/indra/llcommon/llversionserver.h
+++ b/indra/llcommon/llversionserver.h
@@ -34,9 +34,9 @@
#define LL_LLVERSIONSERVER_H
const S32 LL_VERSION_MAJOR = 1;
-const S32 LL_VERSION_MINOR = 29;
+const S32 LL_VERSION_MINOR = 31;
const S32 LL_VERSION_PATCH = 0;
-const S32 LL_VERSION_BUILD = 120909;
+const S32 LL_VERSION_BUILD = 200030;
const char * const LL_CHANNEL = "Second Life Server";
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index a28d0f7268..540aea4252 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -33,11 +33,11 @@
#ifndef LL_LLVERSIONVIEWER_H
#define LL_LLVERSIONVIEWER_H
-const S32 LL_VERSION_MAJOR = 1;
-const S32 LL_VERSION_MINOR = 24;
-const S32 LL_VERSION_PATCH = 2;
-const S32 LL_VERSION_BUILD = 0;
+const S32 LL_VERSION_MAJOR = 2;
+const S32 LL_VERSION_MINOR = 0;
+const S32 LL_VERSION_PATCH = 0;
+const S32 LL_VERSION_BUILD = 200030;
-const char * const LL_CHANNEL = "Second Life Release";
+const char * const LL_CHANNEL = "Second Life Developer";
#endif
diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp
index 5dda600755..82c736266d 100644
--- a/indra/llcommon/llworkerthread.cpp
+++ b/indra/llcommon/llworkerthread.cpp
@@ -201,6 +201,7 @@ LLWorkerClass::~LLWorkerClass()
{
llassert_always(!(mWorkFlags & WCF_WORKING));
llassert_always(mWorkFlags & WCF_DELETE_REQUESTED);
+ llassert_always(!mMutex.isLocked());
if (mRequestHandle != LLWorkerThread::nullHandle())
{
LLWorkerThread::WorkRequest* workreq = (LLWorkerThread::WorkRequest*)mWorkerThread->getRequest(mRequestHandle);
diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h
index 19407f4463..a1e85d2ecc 100644
--- a/indra/llcommon/llworkerthread.h
+++ b/indra/llcommon/llworkerthread.h
@@ -50,8 +50,9 @@ class LLWorkerClass;
// Note: ~LLWorkerThread is O(N) N=# of worker threads, assumed to be small
// It is assumed that LLWorkerThreads are rarely created/destroyed.
-class LLWorkerThread : public LLQueuedThread
+class LL_COMMON_API LLWorkerThread : public LLQueuedThread
{
+ friend class LLWorkerClass;
public:
class WorkRequest : public LLQueuedThread::QueuedRequest
{
@@ -92,8 +93,11 @@ public:
handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority = PRIORITY_NORMAL);
- void deleteWorker(LLWorkerClass* workerclass); // schedule for deletion
S32 getNumDeletes() { return (S32)mDeleteList.size(); } // debug
+
+private:
+ void deleteWorker(LLWorkerClass* workerclass); // schedule for deletion
+
};
//============================================================================
@@ -113,7 +117,7 @@ public:
// Only one background task can be active at a time (per instance).
// i.e. don't call addWork() if haveWork() returns true
-class LLWorkerClass
+class LL_COMMON_API LLWorkerClass
{
friend class LLWorkerThread;
friend class LLWorkerThread::WorkRequest;
diff --git a/indra/llcommon/metaclass.h b/indra/llcommon/metaclass.h
index cc10f1675f..f38bcd2d57 100644
--- a/indra/llcommon/metaclass.h
+++ b/indra/llcommon/metaclass.h
@@ -43,7 +43,7 @@
class LLReflective;
class LLMetaProperty;
class LLMetaMethod;
-class LLMetaClass
+class LL_COMMON_API LLMetaClass
{
public:
diff --git a/indra/llcommon/metaproperty.h b/indra/llcommon/metaproperty.h
index e5ac35907c..6c016c56dd 100644
--- a/indra/llcommon/metaproperty.h
+++ b/indra/llcommon/metaproperty.h
@@ -41,7 +41,7 @@
class LLMetaClass;
class LLReflective;
-class LLMetaProperty
+class LL_COMMON_API LLMetaProperty
{
public:
LLMetaProperty(const std::string& name, const LLMetaClass& object_class);
diff --git a/indra/llcommon/metapropertyt.h b/indra/llcommon/metapropertyt.h
index 79a536a224..5ad230d1d5 100644
--- a/indra/llcommon/metapropertyt.h
+++ b/indra/llcommon/metapropertyt.h
@@ -94,6 +94,13 @@ inline const LLReflective* LLMetaPropertyT<LLUUID>::get(const LLReflective* obje
}
template <>
+inline const LLReflective* LLMetaPropertyT<bool>::get(const LLReflective* object) const
+{
+ checkObjectClass(object);
+ return NULL;
+}
+
+template <>
inline LLSD LLMetaPropertyT<S32>::getLLSD(const LLReflective* object) const
{
return *(getProperty(object));
@@ -111,6 +118,12 @@ inline LLSD LLMetaPropertyT<LLUUID>::getLLSD(const LLReflective* object) const
return *(getProperty(object));
}
+template <>
+inline LLSD LLMetaPropertyT<bool>::getLLSD(const LLReflective* object) const
+{
+ return *(getProperty(object));
+}
+
template<class TObject, class TProperty>
class LLMetaPropertyTT : public LLMetaPropertyT<TProperty>
{
diff --git a/indra/llcommon/reflective.h b/indra/llcommon/reflective.h
index e2c18ebc6d..a13537681d 100644
--- a/indra/llcommon/reflective.h
+++ b/indra/llcommon/reflective.h
@@ -36,7 +36,7 @@
#define LL_REFLECTIVE_H
class LLMetaClass;
-class LLReflective
+class LL_COMMON_API LLReflective
{
public:
LLReflective();
diff --git a/indra/llcommon/stdenums.h b/indra/llcommon/stdenums.h
index 41da51fce3..1a5678dde1 100644
--- a/indra/llcommon/stdenums.h
+++ b/indra/llcommon/stdenums.h
@@ -54,7 +54,8 @@ enum EDragAndDropType
DAD_BODYPART = 11,
DAD_ANIMATION = 12,
DAD_GESTURE = 13,
- DAD_COUNT = 14, // number of types in this enum
+ DAD_LINK = 14,
+ DAD_COUNT = 15, // number of types in this enum
};
// Reasons for drags to be denied.
diff --git a/indra/llcommon/stringize.h b/indra/llcommon/stringize.h
new file mode 100644
index 0000000000..6399547f5e
--- /dev/null
+++ b/indra/llcommon/stringize.h
@@ -0,0 +1,90 @@
+/**
+ * @file stringize.h
+ * @author Nat Goodspeed
+ * @date 2008-12-17
+ * @brief stringize(item) template function and STRINGIZE(expression) macro
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * Copyright (c) 2008, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_STRINGIZE_H)
+#define LL_STRINGIZE_H
+
+#include <sstream>
+#include <boost/lambda/lambda.hpp>
+
+/**
+ * stringize(item) encapsulates an idiom we use constantly, using
+ * operator<<(std::ostringstream&, TYPE) followed by std::ostringstream::str()
+ * to render a string expressing some item.
+ */
+template <typename T>
+std::string stringize(const T& item)
+{
+ std::ostringstream out;
+ out << item;
+ return out.str();
+}
+
+/**
+ * stringize_f(functor)
+ */
+template <typename Functor>
+std::string stringize_f(Functor const & f)
+{
+ std::ostringstream out;
+ f(out);
+ return out.str();
+}
+
+/**
+ * STRINGIZE(item1 << item2 << item3 ...) effectively expands to the
+ * following:
+ * @code
+ * std::ostringstream out;
+ * out << item1 << item2 << item3 ... ;
+ * return out.str();
+ * @endcode
+ */
+#define STRINGIZE(EXPRESSION) (stringize_f(boost::lambda::_1 << EXPRESSION))
+
+
+/**
+ * destringize(str)
+ * defined for symmetry with stringize
+ * *NOTE - this has distinct behavior from boost::lexical_cast<T> regarding
+ * leading/trailing whitespace and handling of bad_lexical_cast exceptions
+ */
+template <typename T>
+T destringize(std::string const & str)
+{
+ T val;
+ std::istringstream in(str);
+ in >> val;
+ return val;
+}
+
+/**
+ * destringize_f(str, functor)
+ */
+template <typename Functor>
+void destringize_f(std::string const & str, Functor const & f)
+{
+ std::istringstream in(str);
+ f(in);
+}
+
+/**
+ * DESTRINGIZE(str, item1 >> item2 >> item3 ...) effectively expands to the
+ * following:
+ * @code
+ * std::istringstream in(str);
+ * in >> item1 >> item2 >> item3 ... ;
+ * @endcode
+ */
+#define DESTRINGIZE(STR, EXPRESSION) (destringize_f((STR), (boost::lambda::_1 >> EXPRESSION)))
+
+
+#endif /* ! defined(LL_STRINGIZE_H) */
diff --git a/indra/llcommon/tests/bitpack_test.cpp b/indra/llcommon/tests/bitpack_test.cpp
new file mode 100644
index 0000000000..09fd037f02
--- /dev/null
+++ b/indra/llcommon/tests/bitpack_test.cpp
@@ -0,0 +1,125 @@
+/**
+ * @file bitpack_test.cpp
+ * @author Adroit
+ * @date 2007-02
+ * @brief llstreamtools test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../bitpack.h"
+
+#include "../test/lltut.h"
+
+
+namespace tut
+{
+ struct bit_pack
+ {
+ };
+ typedef test_group<bit_pack> bit_pack_t;
+ typedef bit_pack_t::object bit_pack_object_t;
+ tut::bit_pack_t tut_bit_pack("bitpack");
+
+ // pack -> unpack
+ template<> template<>
+ void bit_pack_object_t::test<1>()
+ {
+ U8 packbuffer[255];
+ U8 unpackbuffer[255];
+ int pack_bufsize = 0;
+ int unpack_bufsize = 0;
+
+ LLBitPack bitpack(packbuffer, 255);
+
+ char str[] = "SecondLife is a 3D virtual world";
+ int len = sizeof(str);
+ pack_bufsize = bitpack.bitPack((U8*) str, len*8);
+ pack_bufsize = bitpack.flushBitPack();
+
+ LLBitPack bitunpack(packbuffer, pack_bufsize*8);
+ unpack_bufsize = bitunpack.bitUnpack(unpackbuffer, len*8);
+ ensure("bitPack: unpack size should be same as string size prior to pack", len == unpack_bufsize);
+ ensure_memory_matches("str->bitPack->bitUnpack should be equal to string", str, len, unpackbuffer, unpack_bufsize);
+ }
+
+ // pack large, unpack in individual bytes
+ template<> template<>
+ void bit_pack_object_t::test<2>()
+ {
+ U8 packbuffer[255];
+ U8 unpackbuffer[255];
+ int pack_bufsize = 0;
+ int unpack_bufsize = 0;
+
+ LLBitPack bitpack(packbuffer, 255);
+
+ char str[] = "SecondLife";
+ int len = sizeof(str);
+ pack_bufsize = bitpack.bitPack((U8*) str, len*8);
+ pack_bufsize = bitpack.flushBitPack();
+
+ LLBitPack bitunpack(packbuffer, pack_bufsize*8);
+ unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8);
+ ensure("bitPack: individual unpack: 0", unpackbuffer[0] == (U8) str[0]);
+ unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8);
+ ensure("bitPack: individual unpack: 1", unpackbuffer[0] == (U8) str[1]);
+ unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8);
+ ensure("bitPack: individual unpack: 2", unpackbuffer[0] == (U8) str[2]);
+ unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8);
+ ensure("bitPack: individual unpack: 3", unpackbuffer[0] == (U8) str[3]);
+ unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8);
+ ensure("bitPack: individual unpack: 4", unpackbuffer[0] == (U8) str[4]);
+ unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8);
+ ensure("bitPack: individual unpack: 5", unpackbuffer[0] == (U8) str[5]);
+ unpack_bufsize = bitunpack.bitUnpack(unpackbuffer, 8*4); // Life
+ ensure_memory_matches("bitPack: 4 bytes unpack:", unpackbuffer, 4, str+6, 4);
+ }
+
+ // U32 packing
+ template<> template<>
+ void bit_pack_object_t::test<3>()
+ {
+ U8 packbuffer[255];
+ int pack_bufsize = 0;
+
+ LLBitPack bitpack(packbuffer, 255);
+ U32 num = 0x41fab67a;
+ pack_bufsize = bitpack.bitPack((U8*)&num, 8*sizeof(U32));
+ pack_bufsize = bitpack.flushBitPack();
+
+ LLBitPack bitunpack(packbuffer, pack_bufsize*8);
+ U32 res = 0;
+ // since packing and unpacking is done on same machine in the unit test run,
+ // endianness should not matter
+ bitunpack.bitUnpack((U8*) &res, sizeof(res)*8);
+ ensure("U32->bitPack->bitUnpack->U32 should be equal", num == res);
+ }
+}
diff --git a/indra/llcommon/tests/commonmisc_test.cpp b/indra/llcommon/tests/commonmisc_test.cpp
new file mode 100644
index 0000000000..ca27fe9b23
--- /dev/null
+++ b/indra/llcommon/tests/commonmisc_test.cpp
@@ -0,0 +1,677 @@
+/**
+ * @file common.cpp
+ * @author Phoenix
+ * @date 2005-10-12
+ * @brief Common templates for test framework
+ *
+ * $LicenseInfo:firstyear=2005&license=viewergpl$
+ *
+ * Copyright (c) 2005-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+/**
+ *
+ * THOROUGH_DESCRIPTION of common.cpp
+ *
+ */
+
+#include <algorithm>
+#include <iomanip>
+#include <iterator>
+
+#include "linden_common.h"
+
+#include "../llmemorystream.h"
+#include "../llsd.h"
+#include "../llsdserialize.h"
+#include "../u64.h"
+#include "../llhash.h"
+
+#include "../test/lltut.h"
+
+
+#if LL_WINDOWS
+// disable overflow warnings
+#pragma warning(disable: 4307)
+#endif
+
+namespace tut
+{
+ struct sd_data
+ {
+ };
+ typedef test_group<sd_data> sd_test;
+ typedef sd_test::object sd_object;
+ tut::sd_test sd("llsd");
+
+ template<> template<>
+ void sd_object::test<1>()
+ {
+ std::ostringstream resp;
+ resp << "{'connect':true, 'position':[r128,r128,r128], 'look_at':[r0,r1,r0], 'agent_access':'M', 'region_x':i8192, 'region_y':i8192}";
+ std::string str = resp.str();
+ LLMemoryStream mstr((U8*)str.c_str(), str.size());
+ LLSD response;
+ S32 count = LLSDSerialize::fromNotation(response, mstr, str.size());
+ ensure("stream parsed", response.isDefined());
+ ensure_equals("stream parse count", count, 13);
+ ensure_equals("sd type", response.type(), LLSD::TypeMap);
+ ensure_equals("map element count", response.size(), 6);
+ ensure_equals("value connect", response["connect"].asBoolean(), true);
+ ensure_equals("value region_x", response["region_x"].asInteger(),8192);
+ ensure_equals("value region_y", response["region_y"].asInteger(),8192);
+ }
+
+ template<> template<>
+ void sd_object::test<2>()
+ {
+ const std::string decoded("random");
+ //const std::string encoded("cmFuZG9t\n");
+ const std::string streamed("b(6)\"random\"");
+ typedef std::vector<U8> buf_t;
+ buf_t buf;
+ std::copy(
+ decoded.begin(),
+ decoded.end(),
+ std::back_insert_iterator<buf_t>(buf));
+ LLSD sd;
+ sd = buf;
+ std::stringstream str;
+ S32 count = LLSDSerialize::toNotation(sd, str);
+ ensure_equals("output count", count, 1);
+ std::string actual(str.str());
+ ensure_equals("formatted binary encoding", actual, streamed);
+ sd.clear();
+ LLSDSerialize::fromNotation(sd, str, str.str().size());
+ std::vector<U8> after;
+ after = sd.asBinary();
+ ensure_equals("binary decoded size", after.size(), decoded.size());
+ ensure("binary decoding", (0 == memcmp(
+ &after[0],
+ decoded.c_str(),
+ decoded.size())));
+ }
+
+ template<> template<>
+ void sd_object::test<3>()
+ {
+ for(S32 i = 0; i < 100; ++i)
+ {
+ // gen up a starting point
+ typedef std::vector<U8> buf_t;
+ buf_t source;
+ srand(i); /* Flawfinder: ignore */
+ S32 size = rand() % 1000 + 10;
+ std::generate_n(
+ std::back_insert_iterator<buf_t>(source),
+ size,
+ rand);
+ LLSD sd(source);
+ std::stringstream str;
+ S32 count = LLSDSerialize::toNotation(sd, str);
+ sd.clear();
+ ensure_equals("format count", count, 1);
+ LLSD sd2;
+ count = LLSDSerialize::fromNotation(sd2, str, str.str().size());
+ ensure_equals("parse count", count, 1);
+ buf_t dest = sd2.asBinary();
+ str.str("");
+ str << "binary encoding size " << i;
+ ensure_equals(str.str().c_str(), dest.size(), source.size());
+ str.str("");
+ str << "binary encoding " << i;
+ ensure(str.str().c_str(), (source == dest));
+ }
+ }
+
+ template<> template<>
+ void sd_object::test<4>()
+ {
+ std::ostringstream ostr;
+ ostr << "{'task_id':u1fd77b79-a8e7-25a5-9454-02a4d948ba1c}\n"
+ << "{\n\tname\tObject|\n}\n";
+ std::string expected = ostr.str();
+ std::stringstream serialized;
+ serialized << "'" << LLSDNotationFormatter::escapeString(expected)
+ << "'";
+ LLSD sd;
+ S32 count = LLSDSerialize::fromNotation(
+ sd,
+ serialized,
+ serialized.str().size());
+ ensure_equals("parse count", count, 1);
+ ensure_equals("String streaming", sd.asString(), expected);
+ }
+
+ template<> template<>
+ void sd_object::test<5>()
+ {
+ for(S32 i = 0; i < 100; ++i)
+ {
+ // gen up a starting point
+ typedef std::vector<U8> buf_t;
+ buf_t source;
+ srand(666 + i); /* Flawfinder: ignore */
+ S32 size = rand() % 1000 + 10;
+ std::generate_n(
+ std::back_insert_iterator<buf_t>(source),
+ size,
+ rand);
+ std::stringstream str;
+ str << "b(" << size << ")\"";
+ str.write((const char*)&source[0], size);
+ str << "\"";
+ LLSD sd;
+ S32 count = LLSDSerialize::fromNotation(sd, str, str.str().size());
+ ensure_equals("binary parse", count, 1);
+ buf_t actual = sd.asBinary();
+ ensure_equals("binary size", actual.size(), (size_t)size);
+ ensure("binary data", (0 == memcmp(&source[0], &actual[0], size)));
+ }
+ }
+
+ template<> template<>
+ void sd_object::test<6>()
+ {
+ std::string expected("'{\"task_id\":u1fd77b79-a8e7-25a5-9454-02a4d948ba1c}'\t\n\t\t");
+ std::stringstream str;
+ str << "s(" << expected.size() << ")'";
+ str.write(expected.c_str(), expected.size());
+ str << "'";
+ LLSD sd;
+ S32 count = LLSDSerialize::fromNotation(sd, str, str.str().size());
+ ensure_equals("parse count", count, 1);
+ std::string actual = sd.asString();
+ ensure_equals("string sizes", actual.size(), expected.size());
+ ensure_equals("string content", actual, expected);
+ }
+
+ template<> template<>
+ void sd_object::test<7>()
+ {
+ std::string msg("come on in");
+ std::stringstream stream;
+ stream << "{'connect':1, 'message':'" << msg << "',"
+ << " 'position':[r45.65,r100.1,r25.5],"
+ << " 'look_at':[r0,r1,r0],"
+ << " 'agent_access':'PG'}";
+ LLSD sd;
+ S32 count = LLSDSerialize::fromNotation(
+ sd,
+ stream,
+ stream.str().size());
+ ensure_equals("parse count", count, 12);
+ ensure_equals("bool value", sd["connect"].asBoolean(), true);
+ ensure_equals("message value", sd["message"].asString(), msg);
+ ensure_equals("pos x", sd["position"][0].asReal(), 45.65);
+ ensure_equals("pos y", sd["position"][1].asReal(), 100.1);
+ ensure_equals("pos z", sd["position"][2].asReal(), 25.5);
+ ensure_equals("look x", sd["look_at"][0].asReal(), 0.0);
+ ensure_equals("look y", sd["look_at"][1].asReal(), 1.0);
+ ensure_equals("look z", sd["look_at"][2].asReal(), 0.0);
+ }
+
+ template<> template<>
+ void sd_object::test<8>()
+ {
+ std::stringstream resp;
+ resp << "{'label':'short string test', 'singlechar':'a', 'empty':'', 'endoftest':'end' }";
+ LLSD response;
+ S32 count = LLSDSerialize::fromNotation(
+ response,
+ resp,
+ resp.str().size());
+ ensure_equals("parse count", count, 5);
+ ensure_equals("sd type", response.type(), LLSD::TypeMap);
+ ensure_equals("map element count", response.size(), 4);
+ ensure_equals("singlechar", response["singlechar"].asString(), "a");
+ ensure_equals("empty", response["empty"].asString(), "");
+ }
+
+ template<> template<>
+ void sd_object::test<9>()
+ {
+ std::ostringstream resp;
+ resp << "{'label':'short binary test', 'singlebinary':b(1)\"A\", 'singlerawstring':s(1)\"A\", 'endoftest':'end' }";
+ std::string str = resp.str();
+ LLSD sd;
+ LLMemoryStream mstr((U8*)str.c_str(), str.size());
+ S32 count = LLSDSerialize::fromNotation(sd, mstr, str.size());
+ ensure_equals("parse count", count, 5);
+ ensure("sd created", sd.isDefined());
+ ensure_equals("sd type", sd.type(), LLSD::TypeMap);
+ ensure_equals("map element count", sd.size(), 4);
+ ensure_equals(
+ "label",
+ sd["label"].asString(),
+ "short binary test");
+ std::vector<U8> bin = sd["singlebinary"].asBinary();
+ std::vector<U8> expected;
+ expected.resize(1);
+ expected[0] = 'A';
+ ensure("single binary", (0 == memcmp(&bin[0], &expected[0], 1)));
+ ensure_equals(
+ "single string",
+ sd["singlerawstring"].asString(),
+ std::string("A"));
+ ensure_equals("end", sd["endoftest"].asString(), "end");
+ }
+
+ template<> template<>
+ void sd_object::test<10>()
+ {
+
+ std::string message("parcel '' is naughty.");
+ std::stringstream str;
+ str << "{'message':'" << LLSDNotationFormatter::escapeString(message)
+ << "'}";
+ std::string expected_str("{'message':'parcel \\'\\' is naughty.'}");
+ std::string actual_str = str.str();
+ ensure_equals("stream contents", actual_str, expected_str);
+ LLSD sd;
+ S32 count = LLSDSerialize::fromNotation(sd, str, actual_str.size());
+ ensure_equals("parse count", count, 2);
+ ensure("valid parse", sd.isDefined());
+ std::string actual = sd["message"].asString();
+ ensure_equals("message contents", actual, message);
+ }
+
+ template<> template<>
+ void sd_object::test<11>()
+ {
+ std::string expected("\"\"\"\"''''''\"");
+ std::stringstream str;
+ str << "'" << LLSDNotationFormatter::escapeString(expected) << "'";
+ LLSD sd;
+ S32 count = LLSDSerialize::fromNotation(sd, str, str.str().size());
+ ensure_equals("parse count", count, 1);
+ ensure_equals("string value", sd.asString(), expected);
+ }
+
+ template<> template<>
+ void sd_object::test<12>()
+ {
+ std::string expected("mytest\\");
+ std::stringstream str;
+ str << "'" << LLSDNotationFormatter::escapeString(expected) << "'";
+ LLSD sd;
+ S32 count = LLSDSerialize::fromNotation(sd, str, str.str().size());
+ ensure_equals("parse count", count, 1);
+ ensure_equals("string value", sd.asString(), expected);
+ }
+
+ template<> template<>
+ void sd_object::test<13>()
+ {
+ for(S32 i = 0; i < 1000; ++i)
+ {
+ // gen up a starting point
+ std::string expected;
+ srand(1337 + i); /* Flawfinder: ignore */
+ S32 size = rand() % 30 + 5;
+ std::generate_n(
+ std::back_insert_iterator<std::string>(expected),
+ size,
+ rand);
+ std::stringstream str;
+ str << "'" << LLSDNotationFormatter::escapeString(expected) << "'";
+ LLSD sd;
+ S32 count = LLSDSerialize::fromNotation(sd, str, expected.size());
+ ensure_equals("parse count", count, 1);
+ std::string actual = sd.asString();
+/*
+ if(actual != expected)
+ {
+ llwarns << "iteration " << i << llendl;
+ std::ostringstream e_str;
+ std::string::iterator iter = expected.begin();
+ std::string::iterator end = expected.end();
+ for(; iter != end; ++iter)
+ {
+ e_str << (S32)((U8)(*iter)) << " ";
+ }
+ e_str << std::endl;
+ llsd_serialize_string(e_str, expected);
+ llwarns << "expected size: " << expected.size() << llendl;
+ llwarns << "expected: " << e_str.str() << llendl;
+
+ std::ostringstream a_str;
+ iter = actual.begin();
+ end = actual.end();
+ for(; iter != end; ++iter)
+ {
+ a_str << (S32)((U8)(*iter)) << " ";
+ }
+ a_str << std::endl;
+ llsd_serialize_string(a_str, actual);
+ llwarns << "actual size: " << actual.size() << llendl;
+ llwarns << "actual: " << a_str.str() << llendl;
+ }
+*/
+ ensure_equals("string value", actual, expected);
+ }
+ }
+
+ template<> template<>
+ void sd_object::test<14>()
+ {
+//#if LL_WINDOWS && _MSC_VER >= 1400
+// skip_fail("Fails on VS2005 due to broken LLSDSerialize::fromNotation() parser.");
+//#endif
+ std::string param = "[{'version':i1},{'data':{'binary_bucket':b(0)\"\"},'from_id':u3c115e51-04f4-523c-9fa6-98aff1034730,'from_name':'Phoenix Linden','id':u004e45e5-5576-277a-fba7-859d6a4cb5c8,'message':'hey','offline':i0,'timestamp':i0,'to_id':u3c5f1bb4-5182-7546-6401-1d329b4ff2f8,'type':i0},{'agent_id':u3c115e51-04f4-523c-9fa6-98aff1034730,'god_level':i0,'limited_to_estate':i1}]";
+ std::istringstream istr;
+ istr.str(param);
+ LLSD param_sd;
+ LLSDSerialize::fromNotation(param_sd, istr, param.size());
+ ensure_equals("parsed type", param_sd.type(), LLSD::TypeArray);
+ LLSD version_sd = param_sd[0];
+ ensure_equals("version type", version_sd.type(), LLSD::TypeMap);
+ ensure("has version", version_sd.has("version"));
+ ensure_equals("version number", version_sd["version"].asInteger(), 1);
+ LLSD src_sd = param_sd[1];
+ ensure_equals("src type", src_sd.type(), LLSD::TypeMap);
+ LLSD dst_sd = param_sd[2];
+ ensure_equals("dst type", dst_sd.type(), LLSD::TypeMap);
+ }
+
+ template<> template<>
+ void sd_object::test<15>()
+ {
+ std::string val = "[{'failures':!,'successfuls':[u3c115e51-04f4-523c-9fa6-98aff1034730]}]";
+ std::istringstream istr;
+ istr.str(val);
+ LLSD sd;
+ LLSDSerialize::fromNotation(sd, istr, val.size());
+ ensure_equals("parsed type", sd.type(), LLSD::TypeArray);
+ ensure_equals("parsed size", sd.size(), 1);
+ LLSD failures = sd[0]["failures"];
+ ensure("no failures.", failures.isUndefined());
+ LLSD success = sd[0]["successfuls"];
+ ensure_equals("success type", success.type(), LLSD::TypeArray);
+ ensure_equals("success size", success.size(), 1);
+ ensure_equals("success instance type", success[0].type(), LLSD::TypeUUID);
+ }
+
+ template<> template<>
+ void sd_object::test<16>()
+ {
+ std::string val = "[f,t,0,1,{'foo':t,'bar':f}]";
+ std::istringstream istr;
+ istr.str(val);
+ LLSD sd;
+ LLSDSerialize::fromNotation(sd, istr, val.size());
+ ensure_equals("parsed type", sd.type(), LLSD::TypeArray);
+ ensure_equals("parsed size", sd.size(), 5);
+ ensure_equals("element 0 false", sd[0].asBoolean(), false);
+ ensure_equals("element 1 true", sd[1].asBoolean(), true);
+ ensure_equals("element 2 false", sd[2].asBoolean(), false);
+ ensure_equals("element 3 true", sd[3].asBoolean(), true);
+ LLSD map = sd[4];
+ ensure_equals("element 4 type", map.type(), LLSD::TypeMap);
+ ensure_equals("map foo type", map["foo"].type(), LLSD::TypeBoolean);
+ ensure_equals("map foo value", map["foo"].asBoolean(), true);
+ ensure_equals("map bar type", map["bar"].type(), LLSD::TypeBoolean);
+ ensure_equals("map bar value", map["bar"].asBoolean(), false);
+ }
+
+/*
+ template<> template<>
+ void sd_object::test<16>()
+ {
+ }
+*/
+}
+
+#if 0
+'{\'task_id\':u1fd77b79-a8e7-25a5-9454-02a4d948ba1c}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t00082000\n\t\tcreator_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t00000000-0000-0000-0000-000000000000\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t10284\n\ttotal_crc\t35\n\ttype\t1\n\ttask_valid\t2\n\ttravel_access\t21\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t0\t0\t0\n\toldpos\t0\t0\t0\n\trotation\t4.371139183945160766597837e-08\t1\t4.371139183945160766597837e-08\t0\n\tvelocity\t0\t0\t0\n\tangvel\t0\t0\t0\n\tscale\t0.2816932\t0.2816932\t0.2816932\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t80\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t16\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\tscale_x\t1\n\t\t\tscale_y\t1\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t1\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t6\n\t{\n\t\timageid\t89556747-24cb-43ed-920b-47caed15465f\n\t\tcolors\t1 1 1 1\n\t\tscales\t0.56\n\t\tscalet\t0.56\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\t89556747-24cb-43ed-920b-47caed15465f\n\t\tcolors\t1 1 1 1\n\t\tscales\t0.56\n\t\tscalet\t0.56\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\t89556747-24cb-43ed-920b-47caed15465f\n\t\tcolors\t1 1 1 1\n\t\tscales\t0.56\n\t\tscalet\t0.56\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\t89556747-24cb-43ed-920b-47caed15465f\n\t\tcolors\t1 1 1 1\n\t\tscales\t0.56\n\t\tscalet\t0.56\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\t89556747-24cb-43ed-920b-47caed15465f\n\t\tcolors\t1 1 1 1\n\t\tscales\t0.56\n\t\tscalet\t0.56\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\t89556747-24cb-43ed-920b-47caed15465f\n\t\tcolors\t1 1 1 1\n\t\tscales\t0.56\n\t\tscalet\t0.56\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t1132625972249870\n\tbirthtime\t1132625953120694\n\treztime\t1132625953120694\n\tparceltime\t1132625953120694\n\ttax_rate\t1.01615\n\tnamevalue\tAttachmentOrientation VEC3 RW DS -3.141593, 0.000000, -3.141593\n\tnamevalue\tAttachmentOffset VEC3 RW DS 0.000000, 0.000000, 0.000000\n\tnamevalue\tAttachPt U32 RW S 5\n\tnamevalue\tAttachItemID STRING RW SV 1f9975c0-2951-1b93-dd83-46e2b932fcc8\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\torig_asset_id\t52019cdd-b464-ba19-e66d-3da751fef9da\n\torig_item_id\t1f9975c0-2951-1b93-dd83-46e2b932fcc8\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n'
+#endif
+
+namespace tut
+{
+ struct mem_data
+ {
+ };
+ typedef test_group<mem_data> mem_test;
+ typedef mem_test::object mem_object;
+ tut::mem_test mem_stream("memory_stream");
+
+ template<> template<>
+ void mem_object::test<1>()
+ {
+ const char HELLO_WORLD[] = "hello world";
+ LLMemoryStream mem((U8*)&HELLO_WORLD[0], strlen(HELLO_WORLD)); /* Flawfinder: ignore */
+ std::string hello;
+ std::string world;
+ mem >> hello >> world;
+ ensure_equals("first word", hello, std::string("hello"));
+ ensure_equals("second word", world, std::string("world"));
+ }
+}
+
+namespace tut
+{
+ struct U64_data
+ {
+ };
+ typedef test_group<U64_data> U64_test;
+ typedef U64_test::object U64_object;
+ tut::U64_test U64_testcase("U64_conversion");
+
+ // U64_to_str
+ template<> template<>
+ void U64_object::test<1>()
+ {
+ U64 val;
+ std::string val_str;
+ char result[256];
+ std::string result_str;
+
+ val = U64L(18446744073709551610); // slightly less than MAX_U64
+ val_str = "18446744073709551610";
+
+ U64_to_str(val, result, sizeof(result));
+ result_str = (const char*) result;
+ ensure_equals("U64_to_str converted 1.1", val_str, result_str);
+
+ val = 0;
+ val_str = "0";
+ U64_to_str(val, result, sizeof(result));
+ result_str = (const char*) result;
+ ensure_equals("U64_to_str converted 1.2", val_str, result_str);
+
+ val = U64L(18446744073709551615); // 0xFFFFFFFFFFFFFFFF
+ val_str = "18446744073709551615";
+ U64_to_str(val, result, sizeof(result));
+ result_str = (const char*) result;
+ ensure_equals("U64_to_str converted 1.3", val_str, result_str);
+
+ // overflow - will result in warning at compile time
+ val = U64L(18446744073709551615) + 1; // overflow 0xFFFFFFFFFFFFFFFF + 1 == 0
+ val_str = "0";
+ U64_to_str(val, result, sizeof(result));
+ result_str = (const char*) result;
+ ensure_equals("U64_to_str converted 1.4", val_str, result_str);
+
+ val = U64L(-1); // 0xFFFFFFFFFFFFFFFF == 18446744073709551615
+ val_str = "18446744073709551615";
+ U64_to_str(val, result, sizeof(result));
+ result_str = (const char*) result;
+ ensure_equals("U64_to_str converted 1.5", val_str, result_str);
+
+ val = U64L(10000000000000000000); // testing preserving of 0s
+ val_str = "10000000000000000000";
+ U64_to_str(val, result, sizeof(result));
+ result_str = (const char*) result;
+ ensure_equals("U64_to_str converted 1.6", val_str, result_str);
+
+ val = 1; // testing no leading 0s
+ val_str = "1";
+ U64_to_str(val, result, sizeof(result));
+ result_str = (const char*) result;
+ ensure_equals("U64_to_str converted 1.7", val_str, result_str);
+
+ val = U64L(18446744073709551615); // testing exact sized buffer for result
+ val_str = "18446744073709551615";
+ memset(result, 'A', sizeof(result)); // initialize buffer with all 'A'
+ U64_to_str(val, result, sizeof("18446744073709551615")); //pass in the exact size
+ result_str = (const char*) result;
+ ensure_equals("U64_to_str converted 1.8", val_str, result_str);
+
+ val = U64L(18446744073709551615); // testing smaller sized buffer for result
+ val_str = "1844";
+ memset(result, 'A', sizeof(result)); // initialize buffer with all 'A'
+ U64_to_str(val, result, 5); //pass in a size of 5. should only copy first 4 integers and add a null terminator
+ result_str = (const char*) result;
+ ensure_equals("U64_to_str converted 1.9", val_str, result_str);
+ }
+
+ // str_to_U64
+ template<> template<>
+ void U64_object::test<2>()
+ {
+ U64 val;
+ U64 result;
+
+ val = U64L(18446744073709551610); // slightly less than MAX_U64
+ result = str_to_U64("18446744073709551610");
+ ensure_equals("str_to_U64 converted 2.1", val, result);
+
+ val = U64L(0); // empty string
+ result = str_to_U64(LLStringUtil::null);
+ ensure_equals("str_to_U64 converted 2.2", val, result);
+
+ val = U64L(0); // 0
+ result = str_to_U64("0");
+ ensure_equals("str_to_U64 converted 2.3", val, result);
+
+ val = U64L(18446744073709551615); // 0xFFFFFFFFFFFFFFFF
+ result = str_to_U64("18446744073709551615");
+ ensure_equals("str_to_U64 converted 2.4", val, result);
+
+ // overflow - will result in warning at compile time
+ val = U64L(18446744073709551615) + 1; // overflow 0xFFFFFFFFFFFFFFFF + 1 == 0
+ result = str_to_U64("18446744073709551616");
+ ensure_equals("str_to_U64 converted 2.5", val, result);
+
+ val = U64L(1234); // process till first non-integral character
+ result = str_to_U64("1234A5678");
+ ensure_equals("str_to_U64 converted 2.6", val, result);
+
+ val = U64L(5678); // skip all non-integral characters
+ result = str_to_U64("ABCD5678");
+ ensure_equals("str_to_U64 converted 2.7", val, result);
+
+ // should it skip negative sign and process
+ // rest of string or return 0
+ val = U64L(1234); // skip initial negative sign
+ result = str_to_U64("-1234");
+ ensure_equals("str_to_U64 converted 2.8", val, result);
+
+ val = U64L(5678); // stop at negative sign in the middle
+ result = str_to_U64("5678-1234");
+ ensure_equals("str_to_U64 converted 2.9", val, result);
+
+ val = U64L(0); // no integers
+ result = str_to_U64("AaCD");
+ ensure_equals("str_to_U64 converted 2.10", val, result);
+ }
+
+ // U64_to_F64
+ template<> template<>
+ void U64_object::test<3>()
+ {
+ F64 val;
+ F64 result;
+
+ result = 18446744073709551610.0;
+ val = U64_to_F64(U64L(18446744073709551610));
+ ensure_equals("U64_to_F64 converted 3.1", val, result);
+
+ result = 18446744073709551615.0; // 0xFFFFFFFFFFFFFFFF
+ val = U64_to_F64(U64L(18446744073709551615));
+ ensure_equals("U64_to_F64 converted 3.2", val, result);
+
+ result = 0.0; // overflow 0xFFFFFFFFFFFFFFFF + 1 == 0
+ // overflow - will result in warning at compile time
+ val = U64_to_F64(U64L(18446744073709551615)+1);
+ ensure_equals("U64_to_F64 converted 3.3", val, result);
+
+ result = 0.0; // 0
+ val = U64_to_F64(U64L(0));
+ ensure_equals("U64_to_F64 converted 3.4", val, result);
+
+ result = 1.0; // odd
+ val = U64_to_F64(U64L(1));
+ ensure_equals("U64_to_F64 converted 3.5", val, result);
+
+ result = 2.0; // even
+ val = U64_to_F64(U64L(2));
+ ensure_equals("U64_to_F64 converted 3.6", val, result);
+
+ result = U64L(0x7FFFFFFFFFFFFFFF) * 1.0L; // 0x7FFFFFFFFFFFFFFF
+ val = U64_to_F64(U64L(0x7FFFFFFFFFFFFFFF));
+ ensure_equals("U64_to_F64 converted 3.7", val, result);
+ }
+
+ // llstrtou64
+ // seems to be deprecated - could not find it being used
+ // anywhere in the tarball - skipping unit tests for now
+}
+
+
+namespace tut
+{
+ struct hash_data
+ {
+ };
+ typedef test_group<hash_data> hash_test;
+ typedef hash_test::object hash_object;
+ tut::hash_test hash_tester("hash_test");
+
+ template<> template<>
+ void hash_object::test<1>()
+ {
+ const char * str1 = "test string one";
+ const char * same_as_str1 = "test string one";
+
+ size_t hash1 = llhash(str1);
+ size_t same_as_hash1 = llhash(same_as_str1);
+
+
+ ensure("Hashes from identical strings should be equal", hash1 == same_as_hash1);
+
+ char str[100];
+ strcpy( str, "Another test" );
+
+ size_t hash2 = llhash(str);
+
+ strcpy( str, "Different string, same pointer" );
+
+ size_t hash3 = llhash(str);
+
+ ensure("Hashes from same pointer but different string should not be equal", hash2 != hash3);
+ }
+}
diff --git a/indra/llcommon/tests/listener.h b/indra/llcommon/tests/listener.h
new file mode 100644
index 0000000000..fa12f944ef
--- /dev/null
+++ b/indra/llcommon/tests/listener.h
@@ -0,0 +1,139 @@
+/**
+ * @file listener.h
+ * @author Nat Goodspeed
+ * @date 2009-03-06
+ * @brief Useful for tests of the LLEventPump family of classes
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LISTENER_H)
+#define LL_LISTENER_H
+
+#include "llsd.h"
+#include <iostream>
+
+/*****************************************************************************
+* test listener class
+*****************************************************************************/
+class Listener;
+std::ostream& operator<<(std::ostream&, const Listener&);
+
+/// Bear in mind that this is strictly for testing
+class Listener
+{
+public:
+ /// Every Listener is instantiated with a name
+ Listener(const std::string& name):
+ mName(name)
+ {
+// std::cout << *this << ": ctor\n";
+ }
+/*==========================================================================*|
+ // These methods are only useful when trying to track Listener instance
+ // lifespan
+ Listener(const Listener& that):
+ mName(that.mName),
+ mLastEvent(that.mLastEvent)
+ {
+ std::cout << *this << ": copy\n";
+ }
+ virtual ~Listener()
+ {
+ std::cout << *this << ": dtor\n";
+ }
+|*==========================================================================*/
+ /// You can request the name
+ std::string getName() const { return mName; }
+ /// This is a typical listener method that returns 'false' when done,
+ /// allowing subsequent listeners on the LLEventPump to process the
+ /// incoming event.
+ bool call(const LLSD& event)
+ {
+// std::cout << *this << "::call(" << event << ")\n";
+ mLastEvent = event;
+ return false;
+ }
+ /// This is an alternate listener that returns 'true' when done, which
+ /// stops processing of the incoming event.
+ bool callstop(const LLSD& event)
+ {
+// std::cout << *this << "::callstop(" << event << ")\n";
+ mLastEvent = event;
+ return true;
+ }
+ /// ListenMethod can represent either call() or callstop().
+ typedef bool (Listener::*ListenMethod)(const LLSD&);
+ /**
+ * This helper method is only because our test code makes so many
+ * repetitive listen() calls to ListenerMethods. In real code, you should
+ * call LLEventPump::listen() directly so it can examine the specific
+ * object you pass to boost::bind().
+ */
+ LLBoundListener listenTo(LLEventPump& pump,
+ ListenMethod method=&Listener::call,
+ const LLEventPump::NameList& after=LLEventPump::empty,
+ const LLEventPump::NameList& before=LLEventPump::empty)
+ {
+ return pump.listen(getName(), boost::bind(method, this, _1), after, before);
+ }
+ /// Both call() and callstop() set mLastEvent. Retrieve it.
+ LLSD getLastEvent() const
+ {
+// std::cout << *this << "::getLastEvent() -> " << mLastEvent << "\n";
+ return mLastEvent;
+ }
+ /// Reset mLastEvent to a known state.
+ void reset(const LLSD& to = LLSD())
+ {
+// std::cout << *this << "::reset(" << to << ")\n";
+ mLastEvent = to;
+ }
+
+private:
+ std::string mName;
+ LLSD mLastEvent;
+};
+
+std::ostream& operator<<(std::ostream& out, const Listener& listener)
+{
+ out << "Listener(" << listener.getName() /* << "@" << &listener */ << ')';
+ return out;
+}
+
+/**
+ * This class tests the relative order in which various listeners on a given
+ * LLEventPump are called. Each listen() call binds a particular string, which
+ * we collect for later examination. The actual event is ignored.
+ */
+struct Collect
+{
+ bool add(const std::string& bound, const LLSD& event)
+ {
+ result.push_back(bound);
+ return false;
+ }
+ void clear() { result.clear(); }
+ typedef std::vector<std::string> StringList;
+ StringList result;
+};
+
+std::ostream& operator<<(std::ostream& out, const Collect::StringList& strings)
+{
+ out << '(';
+ Collect::StringList::const_iterator begin(strings.begin()), end(strings.end());
+ if (begin != end)
+ {
+ out << '"' << *begin << '"';
+ while (++begin != end)
+ {
+ out << ", \"" << *begin << '"';
+ }
+ }
+ out << ')';
+ return out;
+}
+
+#endif /* ! defined(LL_LISTENER_H) */
diff --git a/indra/llcommon/tests/llallocator_heap_profile_test.cpp b/indra/llcommon/tests/llallocator_heap_profile_test.cpp
new file mode 100644
index 0000000000..7369fdc8bc
--- /dev/null
+++ b/indra/llcommon/tests/llallocator_heap_profile_test.cpp
@@ -0,0 +1,150 @@
+/**
+ * @file llallocator_heap_profile_test.cpp
+ * @author Brad Kittenbrink
+ * @date 2008-02-
+ * @brief Test for llallocator_heap_profile.cpp.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "../llallocator_heap_profile.h"
+#include "../test/lltut.h"
+
+namespace tut
+{
+ struct llallocator_heap_profile_data
+ {
+ LLAllocatorHeapProfile prof;
+
+ static char const * const sample_win_profile;
+ // *TODO - get test output from mac/linux tcmalloc
+ static char const * const sample_mac_profile;
+ static char const * const sample_lin_profile;
+
+ static char const * const crash_testcase;
+ };
+ typedef test_group<llallocator_heap_profile_data> factory;
+ typedef factory::object object;
+}
+namespace
+{
+ tut::factory llallocator_heap_profile_test_factory("LLAllocatorHeapProfile");
+}
+
+namespace tut
+{
+ template<> template<>
+ void object::test<1>()
+ {
+ prof.parse(sample_win_profile);
+
+ ensure_equals("count lines", prof.mLines.size() , 5);
+ ensure_equals("alloc counts", prof.mLines[0].mLiveCount, 2131854U);
+ ensure_equals("alloc counts", prof.mLines[0].mLiveSize, 2245710106ULL);
+ ensure_equals("alloc counts", prof.mLines[0].mTotalCount, 14069198U);
+ ensure_equals("alloc counts", prof.mLines[0].mTotalSize, 4295177308ULL);
+ ensure_equals("count markers", prof.mLines[0].mTrace.size(), 0);
+ ensure_equals("count markers", prof.mLines[1].mTrace.size(), 0);
+ ensure_equals("count markers", prof.mLines[2].mTrace.size(), 4);
+ ensure_equals("count markers", prof.mLines[3].mTrace.size(), 6);
+ ensure_equals("count markers", prof.mLines[4].mTrace.size(), 7);
+
+ //prof.dump(std::cout);
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ prof.parse(crash_testcase);
+
+ ensure_equals("count lines", prof.mLines.size(), 2);
+ ensure_equals("alloc counts", prof.mLines[0].mLiveCount, 3U);
+ ensure_equals("alloc counts", prof.mLines[0].mLiveSize, 1049652ULL);
+ ensure_equals("alloc counts", prof.mLines[0].mTotalCount, 8U);
+ ensure_equals("alloc counts", prof.mLines[0].mTotalSize, 1049748ULL);
+ ensure_equals("count markers", prof.mLines[0].mTrace.size(), 0);
+ ensure_equals("count markers", prof.mLines[1].mTrace.size(), 0);
+
+ //prof.dump(std::cout);
+ }
+
+ template<> template<>
+ void object::test<3>()
+ {
+ // test that we don't crash on edge case data
+ prof.parse("");
+ ensure("emtpy on error", prof.mLines.empty());
+
+ prof.parse("heap profile:");
+ ensure("emtpy on error", prof.mLines.empty());
+ }
+
+char const * const llallocator_heap_profile_data::sample_win_profile =
+"heap profile: 2131854: 2245710106 [14069198: 4295177308] @\n"
+"308592: 1073398388 [966564: 1280998739] @\n"
+"462651: 375969538 [1177377: 753561247] @ 2 3 6 1\n"
+"314744: 206611283 [2008722: 570934755] @ 2 3 3 7 21 32\n"
+"277152: 82862770 [621961: 168503640] @ 2 3 3 7 21 32 87\n"
+"\n"
+"MAPPED_LIBRARIES:\n"
+"00400000-02681000 r-xp 00000000 00:00 0 c:\\proj\\tcmalloc-eval-9\\indra\\build-vc80\\newview\\RelWithDebInfo\\secondlife-bin.exe\n"
+"77280000-773a7000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\ntdll.dll\n"
+"76df0000-76ecb000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\kernel32.dll\n"
+"76000000-76073000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\comdlg32.dll\n"
+"75ee0000-75f8a000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\msvcrt.dll\n"
+"76c30000-76c88000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\SHLWAPI.dll\n"
+"75f90000-75fdb000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\GDI32.dll\n"
+"77420000-774bd000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\USER32.dll\n"
+"75e10000-75ed6000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\ADVAPI32.dll\n"
+"75b00000-75bc2000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\RPCRT4.dll\n"
+"72ca0000-72d25000 r-xp 00000000 00:00 0 C:\\Windows\\WinSxS\\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.6001.18000_none_886786f450a74a05\\COMCTL32.dll\n"
+"76120000-76c30000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\SHELL32.dll\n"
+"71ce0000-71d13000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\DINPUT8.dll\n";
+
+
+char const * const llallocator_heap_profile_data::crash_testcase =
+"heap profile: 3: 1049652 [ 8: 1049748] @\n"
+" 3: 1049652 [ 8: 1049748] @\n"
+"\n"
+"MAPPED_LIBRARIES:\n"
+"00400000-004d5000 r-xp 00000000 00:00 0 c:\\code\\linden\\tcmalloc\\indra\\build-vc80\\llcommon\\RelWithDebInfo\\llallocator_test.exe\n"
+"7c900000-7c9af000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\ntdll.dll\n"
+"7c800000-7c8f6000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\kernel32.dll\n"
+"77dd0000-77e6b000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\ADVAPI32.dll\n"
+"77e70000-77f02000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\RPCRT4.dll\n"
+"77fe0000-77ff1000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\Secur32.dll\n"
+"71ab0000-71ac7000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\WS2_32.dll\n"
+"77c10000-77c68000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\msvcrt.dll\n"
+"71aa0000-71aa8000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\WS2HELP.dll\n"
+"76bf0000-76bfb000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\PSAPI.DLL\n"
+"5b860000-5b8b5000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\NETAPI32.dll\n"
+"10000000-10041000 r-xp 00000000 00:00 0 c:\\code\\linden\\tcmalloc\\indra\\build-vc80\\llcommon\\RelWithDebInfo\\libtcmalloc_minimal.dll\n"
+"7c420000-7c4a7000 r-xp 00000000 00:00 0 C:\\WINDOWS\\WinSxS\\x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.1433_x-ww_5cf844d2\\MSVCP80.dll\n"
+"78130000-781cb000 r-xp 00000000 00:00 0 C:\\WINDOWS\\WinSxS\\x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.1433_x-ww_5cf844d2\\MSVCR80.dll\n";
+
+}
diff --git a/indra/llcommon/tests/llallocator_test.cpp b/indra/llcommon/tests/llallocator_test.cpp
new file mode 100644
index 0000000000..9db95f4273
--- /dev/null
+++ b/indra/llcommon/tests/llallocator_test.cpp
@@ -0,0 +1,86 @@
+/**
+ * @file llallocator_test.cpp
+ * @author Brad Kittenbrink
+ * @date 2008-02-
+ * @brief Test for llallocator.cpp.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "../llallocator.h"
+#include "../test/lltut.h"
+
+namespace tut
+{
+ struct llallocator_data
+ {
+ LLAllocator llallocator;
+ };
+ typedef test_group<llallocator_data> factory;
+ typedef factory::object object;
+}
+namespace
+{
+ tut::factory llallocator_test_factory("LLAllocator");
+}
+
+namespace tut
+{
+ template<> template<>
+ void object::test<1>()
+ {
+ llallocator.setProfilingEnabled(false);
+ ensure("Profiler disable", !llallocator.isProfiling());
+ }
+
+#if LL_USE_TCMALLOC
+ template<> template<>
+ void object::test<2>()
+ {
+ llallocator.setProfilingEnabled(true);
+ ensure("Profiler enable", llallocator.isProfiling());
+ }
+
+ template <> template <>
+ void object::test<3>()
+ {
+ llallocator.setProfilingEnabled(true);
+
+ char * test_alloc = new char[1024];
+
+ llallocator.getProfile();
+
+ delete [] test_alloc;
+
+ llallocator.getProfile();
+
+ // *NOTE - this test isn't ensuring anything right now other than no
+ // exceptions are thrown.
+ }
+#endif // LL_USE_TCMALLOC
+};
diff --git a/indra/llcommon/tests/llbase64_test.cpp b/indra/llcommon/tests/llbase64_test.cpp
new file mode 100644
index 0000000000..6009788b22
--- /dev/null
+++ b/indra/llcommon/tests/llbase64_test.cpp
@@ -0,0 +1,83 @@
+/**
+ * @file llbase64_test.cpp
+ * @author James Cook
+ * @date 2007-02-04
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include <string>
+
+#include "linden_common.h"
+
+#include "../llbase64.h"
+#include "../lluuid.h"
+
+#include "../test/lltut.h"
+
+namespace tut
+{
+ struct base64_data
+ {
+ };
+ typedef test_group<base64_data> base64_test;
+ typedef base64_test::object base64_object;
+ tut::base64_test base64("base64");
+
+ template<> template<>
+ void base64_object::test<1>()
+ {
+ std::string result;
+
+ result = LLBase64::encode(NULL, 0);
+ ensure("encode nothing", (result == "") );
+
+ LLUUID nothing;
+ result = LLBase64::encode(&nothing.mData[0], UUID_BYTES);
+ ensure("encode blank uuid",
+ (result == "AAAAAAAAAAAAAAAAAAAAAA==") );
+
+ LLUUID id("526a1e07-a19d-baed-84c4-ff08a488d15e");
+ result = LLBase64::encode(&id.mData[0], UUID_BYTES);
+ ensure("encode random uuid",
+ (result == "UmoeB6Gduu2ExP8IpIjRXg==") );
+
+ }
+
+ template<> template<>
+ void base64_object::test<2>()
+ {
+ std::string result;
+
+ U8 blob[40] = { 115, 223, 172, 255, 140, 70, 49, 125, 236, 155, 45, 199, 101, 17, 164, 131, 230, 19, 80, 64, 112, 53, 135, 98, 237, 12, 26, 72, 126, 14, 145, 143, 118, 196, 11, 177, 132, 169, 195, 134 };
+ result = LLBase64::encode(&blob[0], 40);
+ ensure("encode 40 bytes",
+ (result == "c9+s/4xGMX3smy3HZRGkg+YTUEBwNYdi7QwaSH4OkY92xAuxhKnDhg==") );
+ }
+
+}
diff --git a/indra/llcommon/tests/lldate_test.cpp b/indra/llcommon/tests/lldate_test.cpp
new file mode 100644
index 0000000000..c31259227a
--- /dev/null
+++ b/indra/llcommon/tests/lldate_test.cpp
@@ -0,0 +1,219 @@
+/**
+ * @file lldate_test.cpp
+ * @author Adroit
+ * @date 2007-02
+ * @brief LLDate test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../llstring.h"
+#include "../lldate.h"
+
+#include "../test/lltut.h"
+
+
+#define VALID_DATE "2003-04-30T04:00:00Z"
+#define VALID_DATE_LEAP "2004-02-29T04:00:00Z"
+#define VALID_DATE_HOUR_BOUNDARY "2003-04-30T23:59:59Z"
+#define VALID_DATE_FRACTIONAL_SECS "2007-09-26T20:31:33.70Z"
+
+// invalid format
+#define INVALID_DATE_MISSING_YEAR "-04-30T22:59:59Z"
+#define INVALID_DATE_MISSING_MONTH "1900-0430T22:59:59Z"
+#define INVALID_DATE_MISSING_DATE "1900-0430-T22:59:59Z"
+#define INVALID_DATE_MISSING_T "1900-04-30-22:59:59Z"
+#define INVALID_DATE_MISSING_HOUR "1900-04-30T:59:59Z"
+#define INVALID_DATE_MISSING_MIN "1900-04-30T01::59Z"
+#define INVALID_DATE_MISSING_SEC "1900-04-30T01:59Z"
+#define INVALID_DATE_MISSING_Z "1900-04-30T01:59:23"
+#define INVALID_DATE_EMPTY ""
+
+// invalid values
+// apr 1.1.1 seems to not care about constraining the date to valid
+// dates. Put these back when the parser checks.
+#define LL_DATE_PARSER_CHECKS_BOUNDARY 0
+//#define INVALID_DATE_24HOUR_BOUNDARY "2003-04-30T24:00:00Z"
+//#define INVALID_DATE_LEAP "2003-04-29T04:00:00Z"
+//#define INVALID_DATE_HOUR "2003-04-30T24:59:59Z"
+//#define INVALID_DATE_MIN "2003-04-30T22:69:59Z"
+//#define INVALID_DATE_SEC "2003-04-30T22:59:69Z"
+//#define INVALID_DATE_YEAR "0-04-30T22:59:59Z"
+//#define INVALID_DATE_MONTH "2003-13-30T22:59:59Z"
+//#define INVALID_DATE_DAY "2003-04-35T22:59:59Z"
+
+namespace tut
+{
+ struct date_test
+ {
+
+ };
+ typedef test_group<date_test> date_test_t;
+ typedef date_test_t::object date_test_object_t;
+ tut::date_test_t tut_date_test("date_test");
+
+ /* format validation */
+ template<> template<>
+ void date_test_object_t::test<1>()
+ {
+ LLDate date(VALID_DATE);
+ std::string expected_string;
+ bool result;
+ expected_string = VALID_DATE;
+ ensure_equals("Valid Date failed" , expected_string, date.asString());
+
+ result = date.fromString(VALID_DATE_LEAP);
+ expected_string = VALID_DATE_LEAP;
+ ensure_equals("VALID_DATE_LEAP failed" , expected_string, date.asString());
+
+ result = date.fromString(VALID_DATE_HOUR_BOUNDARY);
+ expected_string = VALID_DATE_HOUR_BOUNDARY;
+ ensure_equals("VALID_DATE_HOUR_BOUNDARY failed" , expected_string, date.asString());
+
+ result = date.fromString(VALID_DATE_FRACTIONAL_SECS);
+ expected_string = VALID_DATE_FRACTIONAL_SECS;
+ ensure_equals("VALID_DATE_FRACTIONAL_SECS failed" , expected_string, date.asString());
+
+ result = date.fromString(INVALID_DATE_MISSING_YEAR);
+ ensure_equals("INVALID_DATE_MISSING_YEAR should have failed" , result, false);
+
+ result = date.fromString(INVALID_DATE_MISSING_MONTH);
+ ensure_equals("INVALID_DATE_MISSING_MONTH should have failed" , result, false);
+
+ result = date.fromString(INVALID_DATE_MISSING_DATE);
+ ensure_equals("INVALID_DATE_MISSING_DATE should have failed" , result, false);
+
+ result = date.fromString(INVALID_DATE_MISSING_T);
+ ensure_equals("INVALID_DATE_MISSING_T should have failed" , result, false);
+
+ result = date.fromString(INVALID_DATE_MISSING_HOUR);
+ ensure_equals("INVALID_DATE_MISSING_HOUR should have failed" , result, false);
+
+ result = date.fromString(INVALID_DATE_MISSING_MIN);
+ ensure_equals("INVALID_DATE_MISSING_MIN should have failed" , result, false);
+
+ result = date.fromString(INVALID_DATE_MISSING_SEC);
+ ensure_equals("INVALID_DATE_MISSING_SEC should have failed" , result, false);
+
+ result = date.fromString(INVALID_DATE_MISSING_Z);
+ ensure_equals("INVALID_DATE_MISSING_Z should have failed" , result, false);
+
+ result = date.fromString(INVALID_DATE_EMPTY);
+ ensure_equals("INVALID_DATE_EMPTY should have failed" , result, false);
+ }
+
+ /* Invalid Value Handling */
+ template<> template<>
+ void date_test_object_t::test<2>()
+ {
+#if LL_DATE_PARSER_CHECKS_BOUNDARY
+ LLDate date;
+ std::string expected_string;
+ bool result;
+
+ result = date.fromString(INVALID_DATE_24HOUR_BOUNDARY);
+ ensure_equals("INVALID_DATE_24HOUR_BOUNDARY should have failed" , result, false);
+ ensure_equals("INVALID_DATE_24HOUR_BOUNDARY date still set to old value on failure!" , date.secondsSinceEpoch(), 0);
+
+ result = date.fromString(INVALID_DATE_LEAP);
+ ensure_equals("INVALID_DATE_LEAP should have failed" , result, false);
+
+ result = date.fromString(INVALID_DATE_HOUR);
+ ensure_equals("INVALID_DATE_HOUR should have failed" , result, false);
+
+ result = date.fromString(INVALID_DATE_MIN);
+ ensure_equals("INVALID_DATE_MIN should have failed" , result, false);
+
+ result = date.fromString(INVALID_DATE_SEC);
+ ensure_equals("INVALID_DATE_SEC should have failed" , result, false);
+
+ result = date.fromString(INVALID_DATE_YEAR);
+ ensure_equals("INVALID_DATE_YEAR should have failed" , result, false);
+
+ result = date.fromString(INVALID_DATE_MONTH);
+ ensure_equals("INVALID_DATE_MONTH should have failed" , result, false);
+
+ result = date.fromString(INVALID_DATE_DAY);
+ ensure_equals("INVALID_DATE_DAY should have failed" , result, false);
+#endif
+ }
+
+ /* API checks */
+ template<> template<>
+ void date_test_object_t::test<3>()
+ {
+ LLDate date;
+ std::istringstream stream(VALID_DATE);
+ std::string expected_string = VALID_DATE;
+ date.fromStream(stream);
+ ensure_equals("fromStream failed", date.asString(), expected_string);
+ }
+
+ template<> template<>
+ void date_test_object_t::test<4>()
+ {
+ LLDate date1(VALID_DATE);
+ LLDate date2(date1);
+ ensure_equals("LLDate(const LLDate& date) constructor failed", date1.asString(), date2.asString());
+ }
+
+ template<> template<>
+ void date_test_object_t::test<5>()
+ {
+ LLDate date1(VALID_DATE);
+ LLDate date2(date1.secondsSinceEpoch());
+ ensure_equals("secondsSinceEpoch not equal",date1.secondsSinceEpoch(), date2.secondsSinceEpoch());
+ ensure_equals("LLDate created using secondsSinceEpoch not equal", date1.asString(), date2.asString());
+ }
+
+ template<> template<>
+ void date_test_object_t::test<6>()
+ {
+ LLDate date(VALID_DATE);
+ std::ostringstream stream;
+ stream << date;
+ std::string expected_str = VALID_DATE;
+ ensure_equals("ostringstream failed", expected_str, stream.str());
+ }
+
+ template<> template<>
+ void date_test_object_t::test<7>()
+ {
+ LLDate date;
+ std::istringstream stream(VALID_DATE);
+ stream >> date;
+ std::string expected_str = VALID_DATE;
+ std::ostringstream out_stream;
+ out_stream << date;
+
+ ensure_equals("<< failed", date.asString(),expected_str);
+ ensure_equals("<< to >> failed", stream.str(),out_stream.str());
+ }
+}
diff --git a/indra/llcommon/tests/lldependencies_test.cpp b/indra/llcommon/tests/lldependencies_test.cpp
new file mode 100644
index 0000000000..f3c25de8b5
--- /dev/null
+++ b/indra/llcommon/tests/lldependencies_test.cpp
@@ -0,0 +1,275 @@
+/**
+ * @file lldependencies_tut.cpp
+ * @author Nat Goodspeed
+ * @date 2008-09-17
+ * @brief Test of lldependencies.h
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * Copyright (c) 2008, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// STL headers
+#include <iostream>
+#include <string>
+// std headers
+// external library headers
+#include <boost/assign/list_of.hpp>
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "../lldependencies.h"
+// other Linden headers
+#include "../test/lltut.h"
+
+using boost::assign::list_of;
+
+#if LL_WINDOWS
+#pragma warning (disable : 4675) // "resolved by ADL" -- just as I want!
+#endif
+
+typedef LLDependencies<> StringDeps;
+typedef StringDeps::KeyList StringList;
+
+// We use the very cool boost::assign::list_of() construct to specify vectors
+// of strings inline. For reasons on which I'm not entirely clear, though, it
+// needs a helper function. You can use list_of() to construct an implicit
+// StringList (std::vector<std::string>) by conversion, e.g. for a function
+// parameter -- but if you simply write StringList(list_of("etc.")), you get
+// ambiguity errors. Shrug!
+template<typename CONTAINER>
+CONTAINER make(const CONTAINER& data)
+{
+ return data;
+}
+
+// Display an arbitary value as itself...
+template<typename T>
+std::ostream& display(std::ostream& out, const T& value)
+{
+ out << value;
+ return out;
+}
+
+// ...but display std::string enclosed in double quotes.
+template<>
+std::ostream& display(std::ostream& out, const std::string& value)
+{
+ out << '"' << value << '"';
+ return out;
+}
+
+// display any sequence compatible with Boost.Range
+template<typename SEQUENCE>
+std::ostream& display_seq(std::ostream& out,
+ const std::string& open, const SEQUENCE& seq, const std::string& close)
+{
+ out << open;
+ typename boost::range_const_iterator<SEQUENCE>::type
+ sli = boost::begin(seq),
+ slend = boost::end(seq);
+ if (sli != slend)
+ {
+ display(out, *sli);
+ while (++sli != slend)
+ {
+ out << ", ";
+ display(out, *sli);
+ }
+ }
+ out << close;
+ return out;
+}
+
+// helper to dump a StringList to std::cout if needed
+template<typename ENTRY>
+std::ostream& operator<<(std::ostream& out, const std::vector<ENTRY>& list)
+{
+ display_seq(out, "(", list, ")");
+ return out;
+}
+
+template<typename ENTRY>
+std::ostream& operator<<(std::ostream& out, const std::set<ENTRY>& set)
+{
+ display_seq(out, "{", set, "}");
+ return out;
+}
+
+const std::string& extract_key(const LLDependencies<>::value_type& entry)
+{
+ return entry.first;
+}
+
+// helper to return a StringList of keys from LLDependencies::sort()
+StringList sorted_keys(LLDependencies<>& deps)
+{
+ // 1. Call deps.sort(), returning a value_type range of (key, node) pairs.
+ // 2. Use make_transform_range() to obtain a range of just keys.
+ // 3. Use instance_from_range to instantiate a StringList from that range.
+ // 4. Return by value "slices" instance_from_range<StringList> (a subclass
+ // of StringList) to its base class StringList.
+ return instance_from_range<StringList>(make_transform_range(deps.sort(), extract_key));
+}
+
+template<typename RANGE>
+bool is_empty(const RANGE& range)
+{
+ return boost::begin(range) == boost::end(range);
+}
+
+/*****************************************************************************
+* tut test group
+*****************************************************************************/
+namespace tut
+{
+ struct deps_data
+ {
+ };
+ typedef test_group<deps_data> deps_group;
+ typedef deps_group::object deps_object;
+ tut::deps_group depsgr("lldependencies");
+
+ template<> template<>
+ void deps_object::test<1>()
+ {
+ StringDeps deps;
+ StringList empty;
+ // The quick brown fox jumps over the lazy yellow dog.
+ // (note, "The" and "the" are distinct, else this test wouldn't work)
+ deps.add("lazy");
+ ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")));
+ deps.add("jumps");
+ ensure("found lazy", deps.get("lazy"));
+ ensure("not found dog.", ! deps.get("dog."));
+ // NOTE: Maybe it's overkill to test each of these intermediate
+ // results before all the interdependencies have been specified. My
+ // thought is simply that if the order changes, I'd like to know why.
+ // A change to the implementation of boost::topological_sort() would
+ // be an acceptable reason, and you can simply update the expected
+ // test output.
+ ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("jumps")));
+ deps.add("The", 0, empty, list_of("fox")("dog."));
+ // Test key accessors
+ ensure("empty before deps for missing key", is_empty(deps.get_before_range("bogus")));
+ ensure("empty before deps for jumps", is_empty(deps.get_before_range("jumps")));
+ ensure_equals(instance_from_range< std::set<std::string> >(deps.get_before_range("The")),
+ make< std::set<std::string> >(list_of("dog.")("fox")));
+ // resume building dependencies
+ ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("jumps")("The")));
+ deps.add("the", 0, list_of("The"));
+ ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("jumps")("The")("the")));
+ deps.add("fox", 0, list_of("The"), list_of("jumps"));
+ ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("The")("the")("fox")("jumps")));
+ deps.add("the", 0, list_of("The")); // same, see if cache works
+ ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("The")("the")("fox")("jumps")));
+ deps.add("jumps", 0, empty, list_of("over")); // update jumps deps
+ ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("The")("the")("fox")("jumps")));
+/*==========================================================================*|
+ // It drives me nuts that this test doesn't work in the test
+ // framework, because -- for reasons unknown -- running the test
+ // framework on Mac OS X 10.5 Leopard and Windows XP Pro, the catch
+ // clause below doesn't catch the exception. Something about the TUT
+ // test framework?!? The identical code works fine in a standalone
+ // test program. Commenting out the test for now, in hopes that our
+ // real builds will be able to catch Cycle exceptions...
+ try
+ {
+ // We've already specified fox -> jumps and jumps -> over. Try an
+ // impossible constraint.
+ deps.add("over", 0, empty, list_of("fox"));
+ }
+ catch (const StringDeps::Cycle& e)
+ {
+ std::cout << "Cycle detected: " << e.what() << '\n';
+ // It's legal to add() an impossible constraint because we don't
+ // detect the cycle until sort(). So sort() can't know the minimum set
+ // of nodes to remove to make the StringDeps object valid again.
+ // Therefore we must break the cycle by hand.
+ deps.remove("over");
+ }
+|*==========================================================================*/
+ deps.add("dog.", 0, list_of("yellow")("lazy"));
+ ensure_equals(instance_from_range< std::set<std::string> >(deps.get_after_range("dog.")),
+ make< std::set<std::string> >(list_of("lazy")("yellow")));
+ ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("The")("the")("fox")("jumps")("dog.")));
+ deps.add("quick", 0, list_of("The"), list_of("fox")("brown"));
+ ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("The")("the")("quick")("fox")("jumps")("dog.")));
+ deps.add("over", 0, list_of("jumps"), list_of("yellow")("the"));
+ ensure_equals(sorted_keys(deps), make<StringList>(list_of("lazy")("The")("quick")("fox")("jumps")("over")("the")("dog.")));
+ deps.add("yellow", 0, list_of("the"), list_of("lazy"));
+ ensure_equals(sorted_keys(deps), make<StringList>(list_of("The")("quick")("fox")("jumps")("over")("the")("yellow")("lazy")("dog.")));
+ deps.add("brown");
+ // By now the dependencies are pretty well in place. A change to THIS
+ // order should be viewed with suspicion.
+ ensure_equals(sorted_keys(deps), make<StringList>(list_of("The")("quick")("brown")("fox")("jumps")("over")("the")("yellow")("lazy")("dog.")));
+
+ StringList keys(make<StringList>(list_of("The")("brown")("dog.")("fox")("jumps")("lazy")("over")("quick")("the")("yellow")));
+ ensure_equals(instance_from_range<StringList>(deps.get_key_range()), keys);
+#if (! defined(__GNUC__)) || (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)
+ // This is the succinct way, works on modern compilers
+ ensure_equals(instance_from_range<StringList>(make_transform_range(deps.get_range(), extract_key)), keys);
+#else // gcc 3.3
+ StringDeps::range got_range(deps.get_range());
+ StringDeps::iterator kni = got_range.begin(), knend = got_range.end();
+ StringList::iterator ki = keys.begin(), kend = keys.end();
+ for ( ; kni != knend && ki != kend; ++kni, ++ki)
+ {
+ ensure_equals(kni->first, *ki);
+ }
+ ensure("get_range() returns proper length", kni == knend && ki == kend);
+#endif // gcc 3.3
+ // blow off get_node_range() because they're all LLDependenciesEmpty instances
+ }
+
+ template<> template<>
+ void deps_object::test<2>()
+ {
+ typedef LLDependencies<std::string, int> NameIndexDeps;
+ NameIndexDeps nideps;
+ const NameIndexDeps& const_nideps(nideps);
+ nideps.add("def", 2, list_of("ghi"));
+ nideps.add("ghi", 3);
+ nideps.add("abc", 1, list_of("def"));
+ NameIndexDeps::range range(nideps.get_range());
+ ensure_equals(range.begin()->first, "abc");
+ ensure_equals(range.begin()->second, 1);
+ range.begin()->second = 0;
+ range.begin()->second = 1;
+ NameIndexDeps::const_range const_range(const_nideps.get_range());
+ NameIndexDeps::const_iterator const_iterator(const_range.begin());
+ ++const_iterator;
+ ensure_equals(const_iterator->first, "def");
+ ensure_equals(const_iterator->second, 2);
+ NameIndexDeps::node_range node_range(nideps.get_node_range());
+ ensure_equals(instance_from_range<std::vector<int> >(node_range), make< std::vector<int> >(list_of(1)(2)(3)));
+ *node_range.begin() = 0;
+ *node_range.begin() = 1;
+ NameIndexDeps::const_node_range const_node_range(const_nideps.get_node_range());
+ ensure_equals(instance_from_range<std::vector<int> >(const_node_range), make< std::vector<int> >(list_of(1)(2)(3)));
+ NameIndexDeps::const_key_range const_key_range(const_nideps.get_key_range());
+ ensure_equals(instance_from_range<StringList>(const_key_range), make<StringList>(list_of("abc")("def")("ghi")));
+ NameIndexDeps::sorted_range sorted(const_nideps.sort());
+ NameIndexDeps::sorted_iterator sortiter(sorted.begin());
+ ensure_equals(sortiter->first, "ghi");
+ ensure_equals(sortiter->second, 3);
+
+ // test all iterator-flavored versions of get_after_range()
+ StringList def(make<StringList>(list_of("def")));
+ ensure("empty abc before list", is_empty(nideps.get_before_range(nideps.get_range().begin())));
+ ensure_equals(instance_from_range<StringList>(nideps.get_after_range(nideps.get_range().begin())),
+ def);
+ ensure_equals(instance_from_range<StringList>(const_nideps.get_after_range(const_nideps.get_range().begin())),
+ def);
+ ensure_equals(instance_from_range<StringList>(nideps.get_after_range(nideps.get_node_range().begin())),
+ def);
+ ensure_equals(instance_from_range<StringList>(const_nideps.get_after_range(const_nideps.get_node_range().begin())),
+ def);
+ ensure_equals(instance_from_range<StringList>(nideps.get_after_range(nideps.get_key_range().begin())),
+ def);
+ // advance from "ghi" to "def", which must come after "ghi"
+ ++sortiter;
+ ensure_equals(instance_from_range<StringList>(const_nideps.get_after_range(sortiter)),
+ make<StringList>(list_of("ghi")));
+ }
+} // namespace tut
diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp
new file mode 100644
index 0000000000..6785d0cf17
--- /dev/null
+++ b/indra/llcommon/tests/llerror_test.cpp
@@ -0,0 +1,777 @@
+/**
+ * @file llerror_test.cpp
+ * @date December 2006
+ * @brief error unit tests
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ *
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include <vector>
+
+#include "linden_common.h"
+
+#include "../llerror.h"
+
+#include "../llerrorcontrol.h"
+#include "../llsd.h"
+
+#include "../test/lltut.h"
+
+namespace
+{
+ void test_that_error_h_includes_enough_things_to_compile_a_message()
+ {
+ llinfos << "!" << llendl;
+ }
+}
+
+namespace
+{
+ static bool fatalWasCalled;
+ void fatalCall(const std::string&) { fatalWasCalled = true; }
+
+ class TestRecorder : public LLError::Recorder
+ {
+ public:
+ TestRecorder() : mWantsTime(false) { }
+ ~TestRecorder() { LLError::removeRecorder(this); }
+
+ void recordMessage(LLError::ELevel level,
+ const std::string& message)
+ {
+ mMessages.push_back(message);
+ }
+
+ int countMessages() { return (int) mMessages.size(); }
+ void clearMessages() { mMessages.clear(); }
+
+ void setWantsTime(bool t) { mWantsTime = t; }
+ bool wantsTime() { return mWantsTime; }
+
+ std::string message(int n)
+ {
+ std::ostringstream test_name;
+ test_name << "testing message " << n << ", not enough messages";
+
+ tut::ensure(test_name.str(), n < countMessages());
+ return mMessages[n];
+ }
+
+ private:
+ typedef std::vector<std::string> MessageVector;
+ MessageVector mMessages;
+
+ bool mWantsTime;
+ };
+}
+
+namespace tut
+{
+ struct ErrorTestData
+ {
+ TestRecorder mRecorder;
+ LLError::Settings* mPriorErrorSettings;
+
+ ErrorTestData()
+ {
+ fatalWasCalled = false;
+
+ mPriorErrorSettings = LLError::saveAndResetSettings();
+ LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
+ LLError::setFatalFunction(fatalCall);
+ LLError::addRecorder(&mRecorder);
+ }
+
+ ~ErrorTestData()
+ {
+ LLError::removeRecorder(&mRecorder);
+ LLError::restoreSettings(mPriorErrorSettings);
+ }
+
+ void ensure_message_count(int expectedCount)
+ {
+ ensure_equals("message count", mRecorder.countMessages(), expectedCount);
+ }
+
+ void ensure_message_contains(int n, const std::string& expectedText)
+ {
+ std::ostringstream test_name;
+ test_name << "testing message " << n;
+
+ ensure_contains(test_name.str(), mRecorder.message(n), expectedText);
+ }
+
+ void ensure_message_does_not_contain(int n, const std::string& expectedText)
+ {
+ std::ostringstream test_name;
+ test_name << "testing message " << n;
+
+ ensure_does_not_contain(test_name.str(), mRecorder.message(n), expectedText);
+ }
+ };
+
+ typedef test_group<ErrorTestData> ErrorTestGroup;
+ typedef ErrorTestGroup::object ErrorTestObject;
+
+ ErrorTestGroup errorTestGroup("error");
+
+ template<> template<>
+ void ErrorTestObject::test<1>()
+ // basic test of output
+ {
+ llinfos << "test" << llendl;
+ llinfos << "bob" << llendl;
+
+ ensure_message_contains(0, "test");
+ ensure_message_contains(1, "bob");
+ }
+}
+
+namespace
+{
+ void writeSome()
+ {
+ lldebugs << "one" << llendl;
+ llinfos << "two" << llendl;
+ llwarns << "three" << llendl;
+ llerrs << "four" << llendl;
+ // fatal messages write out and addtional "error" message
+ }
+};
+
+namespace tut
+{
+ template<> template<>
+ void ErrorTestObject::test<2>()
+ // messages are filtered based on default level
+ {
+ LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
+ writeSome();
+ ensure_message_contains(0, "one");
+ ensure_message_contains(1, "two");
+ ensure_message_contains(2, "three");
+ ensure_message_contains(3, "error");
+ ensure_message_contains(4, "four");
+ ensure_message_count(5);
+
+ LLError::setDefaultLevel(LLError::LEVEL_INFO);
+ writeSome();
+ ensure_message_contains(5, "two");
+ ensure_message_contains(6, "three");
+ ensure_message_contains(7, "error");
+ ensure_message_contains(8, "four");
+ ensure_message_count(9);
+
+ LLError::setDefaultLevel(LLError::LEVEL_WARN);
+ writeSome();
+ ensure_message_contains(9, "three");
+ ensure_message_contains(10, "error");
+ ensure_message_contains(11, "four");
+ ensure_message_count(12);
+
+ LLError::setDefaultLevel(LLError::LEVEL_ERROR);
+ writeSome();
+ ensure_message_contains(12, "error");
+ ensure_message_contains(13, "four");
+ ensure_message_count(14);
+
+ LLError::setDefaultLevel(LLError::LEVEL_NONE);
+ writeSome();
+ ensure_message_count(14);
+ }
+
+ template<> template<>
+ void ErrorTestObject::test<3>()
+ // error type string in output
+ {
+ writeSome();
+ ensure_message_contains(0, "DEBUG: ");
+ ensure_message_contains(1, "INFO: ");
+ ensure_message_contains(2, "WARNING: ");
+ ensure_message_does_not_contain(3, "ERROR");
+ ensure_message_contains(4, "ERROR: ");
+ ensure_message_count(5);
+ }
+
+ template<> template<>
+ void ErrorTestObject::test<4>()
+ // file abbreviation
+ {
+ std::string thisFile = __FILE__;
+ std::string abbreviateFile = LLError::abbreviateFile(thisFile);
+
+ ensure_ends_with("file name abbreviation",
+ abbreviateFile,
+ "llcommon/tests/llerror_test.cpp"
+ );
+ ensure_does_not_contain("file name abbreviation",
+ abbreviateFile, "indra");
+
+ std::string someFile =
+#if LL_WINDOWS
+ "C:/amy/bob/cam.cpp"
+#else
+ "/amy/bob/cam.cpp"
+#endif
+ ;
+ std::string someAbbreviation = LLError::abbreviateFile(someFile);
+
+ ensure_equals("non-indra file abbreviation",
+ someAbbreviation, someFile);
+ }
+}
+
+namespace
+{
+ std::string locationString(int line)
+ {
+ std::ostringstream location;
+ location << LLError::abbreviateFile(__FILE__)
+ << "(" << line << ") : ";
+
+ return location.str();
+ }
+
+ std::string writeReturningLocation()
+ {
+ llinfos << "apple" << llendl; int this_line = __LINE__;
+ return locationString(this_line);
+ }
+
+ std::string writeReturningLocationAndFunction()
+ {
+ llinfos << "apple" << llendl; int this_line = __LINE__;
+ return locationString(this_line) + __FUNCTION__;
+ }
+
+ std::string errorReturningLocation()
+ {
+ llerrs << "die" << llendl; int this_line = __LINE__;
+ return locationString(this_line);
+ }
+}
+
+namespace tut
+{
+ template<> template<>
+ void ErrorTestObject::test<5>()
+ // file and line information in log messages
+ {
+ std::string location = writeReturningLocation();
+ // expecting default to not print location information
+
+ LLError::setPrintLocation(true);
+ writeReturningLocation();
+
+ LLError::setPrintLocation(false);
+ writeReturningLocation();
+
+ ensure_message_does_not_contain(0, location);
+ ensure_message_contains(1, location);
+ ensure_message_does_not_contain(2, location);
+ }
+}
+
+/* The following helper functions and class members all log a simple message
+ from some particular function scope. Each function takes a bool argument
+ that indicates if it should log its own name or not (in the manner that
+ existing log messages often do.) The functions all return their C++
+ name so that test can be substantial mechanized.
+ */
+
+std::string logFromGlobal(bool id)
+{
+ llinfos << (id ? "logFromGlobal: " : "") << "hi" << llendl;
+ return "logFromGlobal";
+}
+
+static std::string logFromStatic(bool id)
+{
+ llinfos << (id ? "logFromStatic: " : "") << "hi" << llendl;
+ return "logFromStatic";
+}
+
+namespace
+{
+ std::string logFromAnon(bool id)
+ {
+ llinfos << (id ? "logFromAnon: " : "") << "hi" << llendl;
+ return "logFromAnon";
+ }
+}
+
+namespace Foo {
+ std::string logFromNamespace(bool id)
+ {
+ llinfos << (id ? "Foo::logFromNamespace: " : "") << "hi" << llendl;
+ //return "Foo::logFromNamespace";
+ // there is no standard way to get the namespace name, hence
+ // we won't be testing for it
+ return "logFromNamespace";
+ }
+}
+
+namespace
+{
+ class ClassWithNoLogType {
+ public:
+ std::string logFromMember(bool id)
+ {
+ llinfos << (id ? "ClassWithNoLogType::logFromMember: " : "") << "hi" << llendl;
+ return "ClassWithNoLogType::logFromMember";
+ }
+ static std::string logFromStatic(bool id)
+ {
+ llinfos << (id ? "ClassWithNoLogType::logFromStatic: " : "") << "hi" << llendl;
+ return "ClassWithNoLogType::logFromStatic";
+ }
+ };
+
+ class ClassWithLogType {
+ LOG_CLASS(ClassWithLogType);
+ public:
+ std::string logFromMember(bool id)
+ {
+ llinfos << (id ? "ClassWithLogType::logFromMember: " : "") << "hi" << llendl;
+ return "ClassWithLogType::logFromMember";
+ }
+ static std::string logFromStatic(bool id)
+ {
+ llinfos << (id ? "ClassWithLogType::logFromStatic: " : "") << "hi" << llendl;
+ return "ClassWithLogType::logFromStatic";
+ }
+ };
+
+ std::string logFromNamespace(bool id) { return Foo::logFromNamespace(id); }
+ std::string logFromClassWithNoLogTypeMember(bool id) { ClassWithNoLogType c; return c.logFromMember(id); }
+ std::string logFromClassWithNoLogTypeStatic(bool id) { return ClassWithNoLogType::logFromStatic(id); }
+ std::string logFromClassWithLogTypeMember(bool id) { ClassWithLogType c; return c.logFromMember(id); }
+ std::string logFromClassWithLogTypeStatic(bool id) { return ClassWithLogType::logFromStatic(id); }
+
+ void ensure_has(const std::string& message,
+ const std::string& actual, const std::string& expected)
+ {
+ std::string::size_type n1 = actual.find(expected);
+ if (n1 == std::string::npos)
+ {
+ std::stringstream ss;
+ ss << message << ": " << "expected to find a copy of " << expected
+ << " in actual " << actual;
+ throw tut::failure(ss.str().c_str());
+ }
+ }
+
+ typedef std::string (*LogFromFunction)(bool);
+ void testLogName(TestRecorder& recorder, LogFromFunction f,
+ const std::string& class_name = "")
+ {
+ recorder.clearMessages();
+ std::string name = f(false);
+ f(true);
+
+ std::string messageWithoutName = recorder.message(0);
+ std::string messageWithName = recorder.message(1);
+
+ ensure_has(name + " logged without name",
+ messageWithoutName, name);
+ ensure_has(name + " logged with name",
+ messageWithName, name);
+
+ if (!class_name.empty())
+ {
+ ensure_has(name + "logged without name",
+ messageWithoutName, class_name);
+ ensure_has(name + "logged with name",
+ messageWithName, class_name);
+ }
+ }
+}
+
+namespace tut
+{
+ template<> template<>
+ // class/function information in output
+ void ErrorTestObject::test<6>()
+ {
+ testLogName(mRecorder, logFromGlobal);
+ testLogName(mRecorder, logFromStatic);
+ testLogName(mRecorder, logFromAnon);
+ testLogName(mRecorder, logFromNamespace);
+ //testLogName(mRecorder, logFromClassWithNoLogTypeMember, "ClassWithNoLogType");
+ //testLogName(mRecorder, logFromClassWithNoLogTypeStatic, "ClassWithNoLogType");
+ // XXX: figure out what the exepcted response is for these
+ testLogName(mRecorder, logFromClassWithLogTypeMember, "ClassWithLogType");
+ testLogName(mRecorder, logFromClassWithLogTypeStatic, "ClassWithLogType");
+ }
+}
+
+namespace
+{
+ std::string innerLogger()
+ {
+ llinfos << "inside" << llendl;
+ return "moo";
+ }
+
+ std::string outerLogger()
+ {
+ llinfos << "outside(" << innerLogger() << ")" << llendl;
+ return "bar";
+ }
+
+ void uberLogger()
+ {
+ llinfos << "uber(" << outerLogger() << "," << innerLogger() << ")" << llendl;
+ }
+
+ class LogWhileLogging
+ {
+ public:
+ void print(std::ostream& out) const
+ {
+ llinfos << "logging" << llendl;
+ out << "baz";
+ }
+ };
+
+ std::ostream& operator<<(std::ostream& out, const LogWhileLogging& l)
+ { l.print(out); return out; }
+
+ void metaLogger()
+ {
+ LogWhileLogging l;
+ llinfos << "meta(" << l << ")" << llendl;
+ }
+
+}
+
+namespace tut
+{
+ template<> template<>
+ // handle nested logging
+ void ErrorTestObject::test<7>()
+ {
+ outerLogger();
+ ensure_message_contains(0, "inside");
+ ensure_message_contains(1, "outside(moo)");
+ ensure_message_count(2);
+
+ uberLogger();
+ ensure_message_contains(2, "inside");
+ ensure_message_contains(3, "inside");
+ ensure_message_contains(4, "outside(moo)");
+ ensure_message_contains(5, "uber(bar,moo)");
+ ensure_message_count(6);
+
+ metaLogger();
+ ensure_message_contains(6, "logging");
+ ensure_message_contains(7, "meta(baz)");
+ ensure_message_count(8);
+ }
+
+ template<> template<>
+ // special handling of llerrs calls
+ void ErrorTestObject::test<8>()
+ {
+ LLError::setPrintLocation(false);
+ std::string location = errorReturningLocation();
+
+ ensure_message_contains(0, location + "error");
+ ensure_message_contains(1, "die");
+ ensure_message_count(2);
+
+ ensure("fatal callback called", fatalWasCalled);
+ }
+}
+
+namespace
+{
+ std::string roswell()
+ {
+ return "1947-07-08T03:04:05Z";
+ }
+
+ void ufoSighting()
+ {
+ llinfos << "ufo" << llendl;
+ }
+}
+
+namespace tut
+{
+ template<> template<>
+ // time in output (for recorders that need it)
+ void ErrorTestObject::test<9>()
+ {
+ LLError::setTimeFunction(roswell);
+
+ mRecorder.setWantsTime(false);
+ ufoSighting();
+ ensure_message_contains(0, "ufo");
+ ensure_message_does_not_contain(0, roswell());
+
+ mRecorder.setWantsTime(true);
+ ufoSighting();
+ ensure_message_contains(1, "ufo");
+ ensure_message_contains(1, roswell());
+ }
+
+ template<> template<>
+ // output order
+ void ErrorTestObject::test<10>()
+ {
+#if LL_LINUX
+ skip("Fails on Linux, see comments");
+// on Linux:
+// [error, 10] fail: 'order is time type location function message: expected
+// '1947-07-08T03:04:05Z INFO: llcommon/tests/llerror_test.cpp(268) :
+// writeReturningLocationAndFunction: apple' actual
+// '1947-07-08T03:04:05Z INFO: llcommon/tests/llerror_test.cpp(268) :
+// LLError::NoClassInfo::writeReturningLocationAndFunction: apple''
+#endif
+ LLError::setPrintLocation(true);
+ LLError::setTimeFunction(roswell);
+ mRecorder.setWantsTime(true);
+ std::string locationAndFunction = writeReturningLocationAndFunction();
+
+ ensure_equals("order is time type location function message",
+ mRecorder.message(0),
+ roswell() + " INFO: " + locationAndFunction + ": apple");
+ }
+
+ template<> template<>
+ // multiple recorders
+ void ErrorTestObject::test<11>()
+ {
+ TestRecorder altRecorder;
+ LLError::addRecorder(&altRecorder);
+
+ llinfos << "boo" << llendl;
+
+ ensure_message_contains(0, "boo");
+ ensure_equals("alt recorder count", altRecorder.countMessages(), 1);
+ ensure_contains("alt recorder message 0", altRecorder.message(0), "boo");
+
+ LLError::setTimeFunction(roswell);
+
+ TestRecorder anotherRecorder;
+ anotherRecorder.setWantsTime(true);
+ LLError::addRecorder(&anotherRecorder);
+
+ llinfos << "baz" << llendl;
+
+ std::string when = roswell();
+
+ ensure_message_does_not_contain(1, when);
+ ensure_equals("alt recorder count", altRecorder.countMessages(), 2);
+ ensure_does_not_contain("alt recorder message 1", altRecorder.message(1), when);
+ ensure_equals("another recorder count", anotherRecorder.countMessages(), 1);
+ ensure_contains("another recorder message 0", anotherRecorder.message(0), when);
+ }
+}
+
+class TestAlpha
+{
+ LOG_CLASS(TestAlpha);
+public:
+ static void doDebug() { lldebugs << "add dice" << llendl; }
+ static void doInfo() { llinfos << "any idea" << llendl; }
+ static void doWarn() { llwarns << "aim west" << llendl; }
+ static void doError() { llerrs << "ate eels" << llendl; }
+ static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }
+};
+
+class TestBeta
+{
+ LOG_CLASS(TestBeta);
+public:
+ static void doDebug() { lldebugs << "bed down" << llendl; }
+ static void doInfo() { llinfos << "buy iron" << llendl; }
+ static void doWarn() { llwarns << "bad word" << llendl; }
+ static void doError() { llerrs << "big easy" << llendl; }
+ static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }
+};
+
+namespace tut
+{
+ template<> template<>
+ // filtering by class
+ void ErrorTestObject::test<12>()
+ {
+ LLError::setDefaultLevel(LLError::LEVEL_WARN);
+ LLError::setClassLevel("TestBeta", LLError::LEVEL_INFO);
+
+ TestAlpha::doAll();
+ TestBeta::doAll();
+
+ ensure_message_contains(0, "aim west");
+ ensure_message_contains(1, "error");
+ ensure_message_contains(2, "ate eels");
+ ensure_message_contains(3, "buy iron");
+ ensure_message_contains(4, "bad word");
+ ensure_message_contains(5, "error");
+ ensure_message_contains(6, "big easy");
+ ensure_message_count(7);
+ }
+
+ template<> template<>
+ // filtering by function, and that it will override class filtering
+ void ErrorTestObject::test<13>()
+ {
+ LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
+ LLError::setClassLevel("TestBeta", LLError::LEVEL_WARN);
+ LLError::setFunctionLevel("TestBeta::doInfo", LLError::LEVEL_DEBUG);
+ LLError::setFunctionLevel("TestBeta::doError", LLError::LEVEL_NONE);
+
+ TestBeta::doAll();
+ ensure_message_contains(0, "buy iron");
+ ensure_message_contains(1, "bad word");
+ ensure_message_count(2);
+ }
+
+ template<> template<>
+ // filtering by file
+ // and that it is overridden by both class and function filtering
+ void ErrorTestObject::test<14>()
+ {
+ LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
+ LLError::setFileLevel(LLError::abbreviateFile(__FILE__),
+ LLError::LEVEL_WARN);
+ LLError::setClassLevel("TestAlpha", LLError::LEVEL_INFO);
+ LLError::setFunctionLevel("TestAlpha::doError",
+ LLError::LEVEL_NONE);
+ LLError::setFunctionLevel("TestBeta::doError",
+ LLError::LEVEL_NONE);
+
+ TestAlpha::doAll();
+ TestBeta::doAll();
+ ensure_message_contains(0, "any idea");
+ ensure_message_contains(1, "aim west");
+ ensure_message_contains(2, "bad word");
+ ensure_message_count(3);
+ }
+
+ template<> template<>
+ // proper cached, efficient lookup of filtering
+ void ErrorTestObject::test<15>()
+ {
+ LLError::setDefaultLevel(LLError::LEVEL_NONE);
+
+ TestAlpha::doInfo();
+ ensure_message_count(0);
+ ensure_equals("first check", LLError::shouldLogCallCount(), 1);
+ TestAlpha::doInfo();
+ ensure_message_count(0);
+ ensure_equals("second check", LLError::shouldLogCallCount(), 1);
+
+ LLError::setClassLevel("TestAlpha", LLError::LEVEL_DEBUG);
+ TestAlpha::doInfo();
+ ensure_message_count(1);
+ ensure_equals("third check", LLError::shouldLogCallCount(), 2);
+ TestAlpha::doInfo();
+ ensure_message_count(2);
+ ensure_equals("fourth check", LLError::shouldLogCallCount(), 2);
+
+ LLError::setClassLevel("TestAlpha", LLError::LEVEL_WARN);
+ TestAlpha::doInfo();
+ ensure_message_count(2);
+ ensure_equals("fifth check", LLError::shouldLogCallCount(), 3);
+ TestAlpha::doInfo();
+ ensure_message_count(2);
+ ensure_equals("sixth check", LLError::shouldLogCallCount(), 3);
+ }
+
+ template<> template<>
+ // configuration from LLSD
+ void ErrorTestObject::test<16>()
+ {
+ std::string this_file = LLError::abbreviateFile(__FILE__);
+ LLSD config;
+ config["print-location"] = true;
+ config["default-level"] = "DEBUG";
+
+ LLSD set1;
+ set1["level"] = "WARN";
+ set1["files"][0] = this_file;
+
+ LLSD set2;
+ set2["level"] = "INFO";
+ set2["classes"][0] = "TestAlpha";
+
+ LLSD set3;
+ set3["level"] = "NONE";
+ set3["functions"][0] = "TestAlpha::doError";
+ set3["functions"][1] = "TestBeta::doError";
+
+ config["settings"][0] = set1;
+ config["settings"][1] = set2;
+ config["settings"][2] = set3;
+
+ LLError::configure(config);
+
+ TestAlpha::doAll();
+ TestBeta::doAll();
+ ensure_message_contains(0, "any idea");
+ ensure_message_contains(0, this_file);
+ ensure_message_contains(1, "aim west");
+ ensure_message_contains(2, "bad word");
+ ensure_message_count(3);
+
+ // make sure reconfiguring works
+ LLSD config2;
+ config2["default-level"] = "WARN";
+
+ LLError::configure(config2);
+
+ TestAlpha::doAll();
+ TestBeta::doAll();
+ ensure_message_contains(3, "aim west");
+ ensure_message_does_not_contain(3, this_file);
+ ensure_message_contains(4, "error");
+ ensure_message_contains(5, "ate eels");
+ ensure_message_contains(6, "bad word");
+ ensure_message_contains(7, "error");
+ ensure_message_contains(8, "big easy");
+ ensure_message_count(9);
+ }
+}
+
+/* Tests left:
+ handling of classes without LOG_CLASS
+
+ live update of filtering from file
+
+ syslog recorder
+ file recorder
+ cerr/stderr recorder
+ fixed buffer recorder
+ windows recorder
+
+ mutex use when logging (?)
+ strange careful about to crash handling (?)
+*/
diff --git a/indra/llcommon/tests/lleventcoro_test.cpp b/indra/llcommon/tests/lleventcoro_test.cpp
new file mode 100644
index 0000000000..3a2cda7735
--- /dev/null
+++ b/indra/llcommon/tests/lleventcoro_test.cpp
@@ -0,0 +1,782 @@
+/**
+ * @file coroutine_test.cpp
+ * @author Nat Goodspeed
+ * @date 2009-04-22
+ * @brief Test for coroutine.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+/*****************************************************************************/
+// test<1>() is cloned from a Boost.Coroutine example program whose copyright
+// info is reproduced here:
+/*---------------------------------------------------------------------------*/
+// Copyright (c) 2006, Giovanni P. Deretta
+//
+// This code may be used under either of the following two licences:
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE. OF SUCH DAMAGE.
+//
+// Or:
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+/*****************************************************************************/
+
+// On some platforms, Boost.Coroutine must #define magic symbols before
+// #including platform-API headers. Naturally, that's ineffective unless the
+// Boost.Coroutine #include is the *first* #include of the platform header.
+// That means that client code must generally #include Boost.Coroutine headers
+// before anything else.
+#include <boost/coroutine/coroutine.hpp>
+// Normally, lleventcoro.h obviates future.hpp. We only include this because
+// we implement a "by hand" test of future functionality.
+#include <boost/coroutine/future.hpp>
+#include <boost/bind.hpp>
+#include <boost/range.hpp>
+
+#include "linden_common.h"
+
+#include <iostream>
+#include <string>
+
+#include "../test/lltut.h"
+#include "llsd.h"
+#include "llevents.h"
+#include "tests/wrapllerrs.h"
+#include "stringize.h"
+#include "lleventcoro.h"
+#include "../test/debug.h"
+
+/*****************************************************************************
+* from the banana.cpp example program borrowed for test<1>()
+*****************************************************************************/
+namespace coroutines = boost::coroutines;
+using coroutines::coroutine;
+
+template<typename Iter>
+bool match(Iter first, Iter last, std::string match) {
+ std::string::iterator i = match.begin();
+ i != match.end();
+ for(; (first != last) && (i != match.end()); ++i) {
+ if (*first != *i)
+ return false;
+ ++first;
+ }
+ return i == match.end();
+}
+
+template<typename BidirectionalIterator>
+BidirectionalIterator
+match_substring(BidirectionalIterator begin,
+ BidirectionalIterator end,
+ std::string xmatch,
+ BOOST_DEDUCED_TYPENAME coroutine<BidirectionalIterator(void)>::self& self) {
+ BidirectionalIterator begin_ = begin;
+ for(; begin != end; ++begin)
+ if(match(begin, end, xmatch)) {
+ self.yield(begin);
+ }
+ return end;
+}
+
+typedef coroutine<std::string::iterator(void)> match_coroutine_type;
+
+/*****************************************************************************
+* Test helpers
+*****************************************************************************/
+// I suspect this will be typical of coroutines used in Linden software
+typedef boost::coroutines::coroutine<void()> coroutine_type;
+
+/// Simulate an event API whose response is immediate: sent on receipt of the
+/// initial request, rather than after some delay. This is the case that
+/// distinguishes postAndWait() from calling post(), then calling
+/// waitForEventOn().
+class ImmediateAPI
+{
+public:
+ ImmediateAPI():
+ mPump("immediate", true)
+ {
+ mPump.listen("API", boost::bind(&ImmediateAPI::operator(), this, _1));
+ }
+
+ LLEventPump& getPump() { return mPump; }
+
+ // Invoke this with an LLSD map containing:
+ // ["value"]: Integer value. We will reply with ["value"] + 1.
+ // ["reply"]: Name of LLEventPump on which to send success response.
+ // ["error"]: Name of LLEventPump on which to send error response.
+ // ["fail"]: Presence of this key selects ["error"], else ["success"] as
+ // the name of the pump on which to send the response.
+ bool operator()(const LLSD& event) const
+ {
+ LLSD::Integer value(event["value"]);
+ LLSD::String replyPumpName(event.has("fail")? "error" : "reply");
+ LLEventPumps::instance().obtain(event[replyPumpName]).post(value + 1);
+ return false;
+ }
+
+private:
+ LLEventStream mPump;
+};
+
+/*****************************************************************************
+* TUT
+*****************************************************************************/
+namespace tut
+{
+ struct coroutine_data
+ {
+ // Define coroutine bodies as methods here so they can use ensure*()
+
+ void explicit_wait(coroutine_type::self& self)
+ {
+ BEGIN
+ {
+ // ... do whatever preliminary stuff must happen ...
+
+ // declare the future
+ boost::coroutines::future<LLSD> future(self);
+ // tell the future what to wait for
+ LLTempBoundListener connection(
+ LLEventPumps::instance().obtain("source").listen("coro", voidlistener(boost::coroutines::make_callback(future))));
+ ensure("Not yet", ! future);
+ // attempting to dereference ("resolve") the future causes the calling
+ // coroutine to wait for it
+ debug("about to wait");
+ result = *future;
+ ensure("Got it", future);
+ }
+ END
+ }
+
+ void waitForEventOn1(coroutine_type::self& self)
+ {
+ BEGIN
+ {
+ result = waitForEventOn(self, "source");
+ }
+ END
+ }
+
+ void waitForEventOn2(coroutine_type::self& self)
+ {
+ BEGIN
+ {
+ LLEventWithID pair = waitForEventOn(self, "reply", "error");
+ result = pair.first;
+ which = pair.second;
+ debug(STRINGIZE("result = " << result << ", which = " << which));
+ }
+ END
+ }
+
+ void postAndWait1(coroutine_type::self& self)
+ {
+ BEGIN
+ {
+ result = postAndWait(self,
+ LLSD().insert("value", 17), // request event
+ immediateAPI.getPump(), // requestPump
+ "reply1", // replyPump
+ "reply"); // request["reply"] = name
+ }
+ END
+ }
+
+ void postAndWait2(coroutine_type::self& self)
+ {
+ BEGIN
+ {
+ LLEventWithID pair = ::postAndWait2(self,
+ LLSD().insert("value", 18),
+ immediateAPI.getPump(),
+ "reply2",
+ "error2",
+ "reply",
+ "error");
+ result = pair.first;
+ which = pair.second;
+ debug(STRINGIZE("result = " << result << ", which = " << which));
+ }
+ END
+ }
+
+ void postAndWait2_1(coroutine_type::self& self)
+ {
+ BEGIN
+ {
+ LLEventWithID pair = ::postAndWait2(self,
+ LLSD().insert("value", 18).insert("fail", LLSD()),
+ immediateAPI.getPump(),
+ "reply2",
+ "error2",
+ "reply",
+ "error");
+ result = pair.first;
+ which = pair.second;
+ debug(STRINGIZE("result = " << result << ", which = " << which));
+ }
+ END
+ }
+
+ void coroPump(coroutine_type::self& self)
+ {
+ BEGIN
+ {
+ LLCoroEventPump waiter;
+ replyName = waiter.getName();
+ result = waiter.wait(self);
+ }
+ END
+ }
+
+ void coroPumpPost(coroutine_type::self& self)
+ {
+ BEGIN
+ {
+ LLCoroEventPump waiter;
+ result = waiter.postAndWait(self, LLSD().insert("value", 17),
+ immediateAPI.getPump(), "reply");
+ }
+ END
+ }
+
+ void coroPumps(coroutine_type::self& self)
+ {
+ BEGIN
+ {
+ LLCoroEventPumps waiter;
+ replyName = waiter.getName0();
+ errorName = waiter.getName1();
+ LLEventWithID pair(waiter.wait(self));
+ result = pair.first;
+ which = pair.second;
+ }
+ END
+ }
+
+ void coroPumpsNoEx(coroutine_type::self& self)
+ {
+ BEGIN
+ {
+ LLCoroEventPumps waiter;
+ replyName = waiter.getName0();
+ errorName = waiter.getName1();
+ result = waiter.waitWithException(self);
+ }
+ END
+ }
+
+ void coroPumpsEx(coroutine_type::self& self)
+ {
+ BEGIN
+ {
+ LLCoroEventPumps waiter;
+ replyName = waiter.getName0();
+ errorName = waiter.getName1();
+ try
+ {
+ result = waiter.waitWithException(self);
+ debug("no exception");
+ }
+ catch (const LLErrorEvent& e)
+ {
+ debug(STRINGIZE("exception " << e.what()));
+ errordata = e.getData();
+ }
+ }
+ END
+ }
+
+ void coroPumpsNoLog(coroutine_type::self& self)
+ {
+ BEGIN
+ {
+ LLCoroEventPumps waiter;
+ replyName = waiter.getName0();
+ errorName = waiter.getName1();
+ result = waiter.waitWithLog(self);
+ }
+ END
+ }
+
+ void coroPumpsLog(coroutine_type::self& self)
+ {
+ BEGIN
+ {
+ LLCoroEventPumps waiter;
+ replyName = waiter.getName0();
+ errorName = waiter.getName1();
+ WrapLL_ERRS capture;
+ try
+ {
+ result = waiter.waitWithLog(self);
+ debug("no exception");
+ }
+ catch (const WrapLL_ERRS::FatalException& e)
+ {
+ debug(STRINGIZE("exception " << e.what()));
+ threw = e.what();
+ }
+ }
+ END
+ }
+
+ void coroPumpsPost(coroutine_type::self& self)
+ {
+ BEGIN
+ {
+ LLCoroEventPumps waiter;
+ LLEventWithID pair(waiter.postAndWait(self, LLSD().insert("value", 23),
+ immediateAPI.getPump(), "reply", "error"));
+ result = pair.first;
+ which = pair.second;
+ }
+ END
+ }
+
+ void coroPumpsPost_1(coroutine_type::self& self)
+ {
+ BEGIN
+ {
+ LLCoroEventPumps waiter;
+ LLEventWithID pair(
+ waiter.postAndWait(self, LLSD().insert("value", 23).insert("fail", LLSD()),
+ immediateAPI.getPump(), "reply", "error"));
+ result = pair.first;
+ which = pair.second;
+ }
+ END
+ }
+
+ void coroPumpsPostNoEx(coroutine_type::self& self)
+ {
+ BEGIN
+ {
+ LLCoroEventPumps waiter;
+ result = waiter.postAndWaitWithException(self, LLSD().insert("value", 8),
+ immediateAPI.getPump(), "reply", "error");
+ }
+ END
+ }
+
+ void coroPumpsPostEx(coroutine_type::self& self)
+ {
+ BEGIN
+ {
+ LLCoroEventPumps waiter;
+ try
+ {
+ result = waiter.postAndWaitWithException(self,
+ LLSD().insert("value", 9).insert("fail", LLSD()),
+ immediateAPI.getPump(), "reply", "error");
+ debug("no exception");
+ }
+ catch (const LLErrorEvent& e)
+ {
+ debug(STRINGIZE("exception " << e.what()));
+ errordata = e.getData();
+ }
+ }
+ END
+ }
+
+ void coroPumpsPostNoLog(coroutine_type::self& self)
+ {
+ BEGIN
+ {
+ LLCoroEventPumps waiter;
+ result = waiter.postAndWaitWithLog(self, LLSD().insert("value", 30),
+ immediateAPI.getPump(), "reply", "error");
+ }
+ END
+ }
+
+ void coroPumpsPostLog(coroutine_type::self& self)
+ {
+ BEGIN
+ {
+ LLCoroEventPumps waiter;
+ WrapLL_ERRS capture;
+ try
+ {
+ result = waiter.postAndWaitWithLog(self,
+ LLSD().insert("value", 31).insert("fail", LLSD()),
+ immediateAPI.getPump(), "reply", "error");
+ debug("no exception");
+ }
+ catch (const WrapLL_ERRS::FatalException& e)
+ {
+ debug(STRINGIZE("exception " << e.what()));
+ threw = e.what();
+ }
+ }
+ END
+ }
+
+ void ensure_done(coroutine_type& coro)
+ {
+ ensure("coroutine complete", ! coro);
+ }
+
+ ImmediateAPI immediateAPI;
+ std::string replyName, errorName, threw;
+ LLSD result, errordata;
+ int which;
+ };
+ typedef test_group<coroutine_data> coroutine_group;
+ typedef coroutine_group::object object;
+ coroutine_group coroutinegrp("coroutine");
+
+ template<> template<>
+ void object::test<1>()
+ {
+ set_test_name("From banana.cpp example program in Boost.Coroutine distro");
+ std::string buffer = "banananana";
+ std::string match = "nana";
+ std::string::iterator begin = buffer.begin();
+ std::string::iterator end = buffer.end();
+
+#if defined(BOOST_CORO_POSIX_IMPL)
+// std::cout << "Using Boost.Coroutine " << BOOST_CORO_POSIX_IMPL << '\n';
+#else
+// std::cout << "Using non-Posix Boost.Coroutine implementation" << std::endl;
+#endif
+
+ typedef std::string::iterator signature(std::string::iterator,
+ std::string::iterator,
+ std::string,
+ match_coroutine_type::self&);
+
+ coroutine<std::string::iterator(void)> matcher
+ (boost::bind(static_cast<signature*>(match_substring),
+ begin,
+ end,
+ match,
+ _1));
+
+ std::string::iterator i = matcher();
+/*==========================================================================*|
+ while(matcher && i != buffer.end()) {
+ std::cout <<"Match at: "<< std::distance(buffer.begin(), i)<<'\n';
+ i = matcher();
+ }
+|*==========================================================================*/
+ size_t matches[] = { 2, 4, 6 };
+ for (size_t *mi(boost::begin(matches)), *mend(boost::end(matches));
+ mi != mend; ++mi, i = matcher())
+ {
+ ensure("more", matcher);
+ ensure("found", i != buffer.end());
+ ensure_equals("value", std::distance(buffer.begin(), i), *mi);
+ }
+ ensure("done", ! matcher);
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ set_test_name("explicit_wait");
+ DEBUG;
+
+ // Construct the coroutine instance that will run explicit_wait.
+ // Pass the ctor a callable that accepts the coroutine_type::self
+ // param passed by the library.
+ coroutine_type coro(boost::bind(&coroutine_data::explicit_wait, this, _1));
+ // Start the coroutine
+ coro(std::nothrow);
+ // When the coroutine waits for the event pump, it returns here.
+ debug("about to send");
+ // Satisfy the wait.
+ LLEventPumps::instance().obtain("source").post("received");
+ // Now wait for the coroutine to complete.
+ ensure_done(coro);
+ // ensure the coroutine ran and woke up again with the intended result
+ ensure_equals(result.asString(), "received");
+ }
+
+ template<> template<>
+ void object::test<3>()
+ {
+ set_test_name("waitForEventOn1");
+ DEBUG;
+ coroutine_type coro(boost::bind(&coroutine_data::waitForEventOn1, this, _1));
+ coro(std::nothrow);
+ debug("about to send");
+ LLEventPumps::instance().obtain("source").post("received");
+ debug("back from send");
+ ensure_done(coro);
+ ensure_equals(result.asString(), "received");
+ }
+
+ template<> template<>
+ void object::test<4>()
+ {
+ set_test_name("waitForEventOn2 reply");
+ {
+ DEBUG;
+ coroutine_type coro(boost::bind(&coroutine_data::waitForEventOn2, this, _1));
+ coro(std::nothrow);
+ debug("about to send");
+ LLEventPumps::instance().obtain("reply").post("received");
+ debug("back from send");
+ ensure_done(coro);
+ }
+ ensure_equals(result.asString(), "received");
+ ensure_equals("which pump", which, 0);
+ }
+
+ template<> template<>
+ void object::test<5>()
+ {
+ set_test_name("waitForEventOn2 error");
+ DEBUG;
+ coroutine_type coro(boost::bind(&coroutine_data::waitForEventOn2, this, _1));
+ coro(std::nothrow);
+ debug("about to send");
+ LLEventPumps::instance().obtain("error").post("badness");
+ debug("back from send");
+ ensure_done(coro);
+ ensure_equals(result.asString(), "badness");
+ ensure_equals("which pump", which, 1);
+ }
+
+ template<> template<>
+ void object::test<6>()
+ {
+ set_test_name("coroPump");
+ DEBUG;
+ coroutine_type coro(boost::bind(&coroutine_data::coroPump, this, _1));
+ coro(std::nothrow);
+ debug("about to send");
+ LLEventPumps::instance().obtain(replyName).post("received");
+ debug("back from send");
+ ensure_done(coro);
+ ensure_equals(result.asString(), "received");
+ }
+
+ template<> template<>
+ void object::test<7>()
+ {
+ set_test_name("coroPumps reply");
+ DEBUG;
+ coroutine_type coro(boost::bind(&coroutine_data::coroPumps, this, _1));
+ coro(std::nothrow);
+ debug("about to send");
+ LLEventPumps::instance().obtain(replyName).post("received");
+ debug("back from send");
+ ensure_done(coro);
+ ensure_equals(result.asString(), "received");
+ ensure_equals("which pump", which, 0);
+ }
+
+ template<> template<>
+ void object::test<8>()
+ {
+ set_test_name("coroPumps error");
+ DEBUG;
+ coroutine_type coro(boost::bind(&coroutine_data::coroPumps, this, _1));
+ coro(std::nothrow);
+ debug("about to send");
+ LLEventPumps::instance().obtain(errorName).post("badness");
+ debug("back from send");
+ ensure_done(coro);
+ ensure_equals(result.asString(), "badness");
+ ensure_equals("which pump", which, 1);
+ }
+
+ template<> template<>
+ void object::test<9>()
+ {
+ set_test_name("coroPumpsNoEx");
+ DEBUG;
+ coroutine_type coro(boost::bind(&coroutine_data::coroPumpsNoEx, this, _1));
+ coro(std::nothrow);
+ debug("about to send");
+ LLEventPumps::instance().obtain(replyName).post("received");
+ debug("back from send");
+ ensure_done(coro);
+ ensure_equals(result.asString(), "received");
+ }
+
+ template<> template<>
+ void object::test<10>()
+ {
+ set_test_name("coroPumpsEx");
+ DEBUG;
+ coroutine_type coro(boost::bind(&coroutine_data::coroPumpsEx, this, _1));
+ coro(std::nothrow);
+ debug("about to send");
+ LLEventPumps::instance().obtain(errorName).post("badness");
+ debug("back from send");
+ ensure_done(coro);
+ ensure("no result", result.isUndefined());
+ ensure_equals("got error", errordata.asString(), "badness");
+ }
+
+ template<> template<>
+ void object::test<11>()
+ {
+ set_test_name("coroPumpsNoLog");
+ DEBUG;
+ coroutine_type coro(boost::bind(&coroutine_data::coroPumpsNoLog, this, _1));
+ coro(std::nothrow);
+ debug("about to send");
+ LLEventPumps::instance().obtain(replyName).post("received");
+ debug("back from send");
+ ensure_done(coro);
+ ensure_equals(result.asString(), "received");
+ }
+
+ template<> template<>
+ void object::test<12>()
+ {
+ set_test_name("coroPumpsLog");
+ DEBUG;
+ coroutine_type coro(boost::bind(&coroutine_data::coroPumpsLog, this, _1));
+ coro(std::nothrow);
+ debug("about to send");
+ LLEventPumps::instance().obtain(errorName).post("badness");
+ debug("back from send");
+ ensure_done(coro);
+ ensure("no result", result.isUndefined());
+ ensure_contains("got error", threw, "badness");
+ }
+
+ template<> template<>
+ void object::test<13>()
+ {
+ set_test_name("postAndWait1");
+ DEBUG;
+ coroutine_type coro(boost::bind(&coroutine_data::postAndWait1, this, _1));
+ coro(std::nothrow);
+ ensure_done(coro);
+ ensure_equals(result.asInteger(), 18);
+ }
+
+ template<> template<>
+ void object::test<14>()
+ {
+ set_test_name("postAndWait2");
+ DEBUG;
+ coroutine_type coro(boost::bind(&coroutine_data::postAndWait2, this, _1));
+ coro(std::nothrow);
+ ensure_done(coro);
+ ensure_equals(result.asInteger(), 19);
+ ensure_equals(which, 0);
+ }
+
+ template<> template<>
+ void object::test<15>()
+ {
+ set_test_name("postAndWait2_1");
+ DEBUG;
+ coroutine_type coro(boost::bind(&coroutine_data::postAndWait2_1, this, _1));
+ coro(std::nothrow);
+ ensure_done(coro);
+ ensure_equals(result.asInteger(), 19);
+ ensure_equals(which, 1);
+ }
+
+ template<> template<>
+ void object::test<16>()
+ {
+ set_test_name("coroPumpPost");
+ DEBUG;
+ coroutine_type coro(boost::bind(&coroutine_data::coroPumpPost, this, _1));
+ coro(std::nothrow);
+ ensure_done(coro);
+ ensure_equals(result.asInteger(), 18);
+ }
+
+ template<> template<>
+ void object::test<17>()
+ {
+ set_test_name("coroPumpsPost reply");
+ DEBUG;
+ coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPost, this, _1));
+ coro(std::nothrow);
+ ensure_done(coro);
+ ensure_equals(result.asInteger(), 24);
+ ensure_equals("which pump", which, 0);
+ }
+
+ template<> template<>
+ void object::test<18>()
+ {
+ set_test_name("coroPumpsPost error");
+ DEBUG;
+ coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPost_1, this, _1));
+ coro(std::nothrow);
+ ensure_done(coro);
+ ensure_equals(result.asInteger(), 24);
+ ensure_equals("which pump", which, 1);
+ }
+
+ template<> template<>
+ void object::test<19>()
+ {
+ set_test_name("coroPumpsPostNoEx");
+ DEBUG;
+ coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPostNoEx, this, _1));
+ coro(std::nothrow);
+ ensure_done(coro);
+ ensure_equals(result.asInteger(), 9);
+ }
+
+ template<> template<>
+ void object::test<20>()
+ {
+ set_test_name("coroPumpsPostEx");
+ DEBUG;
+ coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPostEx, this, _1));
+ coro(std::nothrow);
+ ensure_done(coro);
+ ensure("no result", result.isUndefined());
+ ensure_equals("got error", errordata.asInteger(), 10);
+ }
+
+ template<> template<>
+ void object::test<21>()
+ {
+ set_test_name("coroPumpsPostNoLog");
+ DEBUG;
+ coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPostNoLog, this, _1));
+ coro(std::nothrow);
+ ensure_done(coro);
+ ensure_equals(result.asInteger(), 31);
+ }
+
+ template<> template<>
+ void object::test<22>()
+ {
+ set_test_name("coroPumpsPostLog");
+ DEBUG;
+ coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPostLog, this, _1));
+ coro(std::nothrow);
+ ensure_done(coro);
+ ensure("no result", result.isUndefined());
+ ensure_contains("got error", threw, "32");
+ }
+} // namespace tut
diff --git a/indra/llcommon/tests/lleventfilter_test.cpp b/indra/llcommon/tests/lleventfilter_test.cpp
new file mode 100644
index 0000000000..28b909298e
--- /dev/null
+++ b/indra/llcommon/tests/lleventfilter_test.cpp
@@ -0,0 +1,276 @@
+/**
+ * @file lleventfilter_test.cpp
+ * @author Nat Goodspeed
+ * @date 2009-03-06
+ * @brief Test for lleventfilter.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "lleventfilter.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "../test/lltut.h"
+#include "stringize.h"
+#include "listener.h"
+#include "tests/wrapllerrs.h"
+
+/*****************************************************************************
+* Test classes
+*****************************************************************************/
+// Strictly speaking, we're testing LLEventTimeoutBase rather than the
+// production LLEventTimeout (using LLTimer) because we don't want every test
+// run to pause for some number of seconds until we reach a real timeout. But
+// as we've carefully put all functionality except actual LLTimer calls into
+// LLEventTimeoutBase, that should suffice. We're not not not trying to test
+// LLTimer here.
+class TestEventTimeout: public LLEventTimeoutBase
+{
+public:
+ TestEventTimeout():
+ mElapsed(true)
+ {}
+ TestEventTimeout(LLEventPump& source):
+ LLEventTimeoutBase(source),
+ mElapsed(true)
+ {}
+
+ // test hook
+ void forceTimeout(bool timeout=true) { mElapsed = timeout; }
+
+protected:
+ virtual void setCountdown(F32 seconds) { mElapsed = false; }
+ virtual bool countdownElapsed() const { return mElapsed; }
+
+private:
+ bool mElapsed;
+};
+
+/*****************************************************************************
+* TUT
+*****************************************************************************/
+namespace tut
+{
+ struct filter_data
+ {
+ // The resemblance between this test data and that in llevents_tut.cpp
+ // is not coincidental.
+ filter_data():
+ pumps(LLEventPumps::instance()),
+ mainloop(pumps.obtain("mainloop")),
+ listener0("first"),
+ listener1("second")
+ {}
+ LLEventPumps& pumps;
+ LLEventPump& mainloop;
+ Listener listener0;
+ Listener listener1;
+
+ void check_listener(const std::string& desc, const Listener& listener, const LLSD& got)
+ {
+ ensure_equals(STRINGIZE(listener << ' ' << desc),
+ listener.getLastEvent(), got);
+ }
+ };
+ typedef test_group<filter_data> filter_group;
+ typedef filter_group::object filter_object;
+ filter_group filtergrp("lleventfilter");
+
+ template<> template<>
+ void filter_object::test<1>()
+ {
+ set_test_name("LLEventMatching");
+ LLEventPump& driver(pumps.obtain("driver"));
+ listener0.reset(0);
+ // Listener isn't derived from LLEventTrackable specifically to test
+ // various connection-management mechanisms. But that means we have a
+ // couple of transient Listener objects, one of which is listening to
+ // a persistent LLEventPump. Capture those connections in local
+ // LLTempBoundListener instances so they'll disconnect
+ // on destruction.
+ LLTempBoundListener temp1(
+ listener0.listenTo(driver));
+ // Construct a pattern LLSD: desired Event must have a key "foo"
+ // containing string "bar"
+ LLEventMatching filter(driver, LLSD().insert("foo", "bar"));
+ listener1.reset(0);
+ LLTempBoundListener temp2(
+ listener1.listenTo(filter));
+ driver.post(1);
+ check_listener("direct", listener0, LLSD(1));
+ check_listener("filtered", listener1, LLSD(0));
+ // Okay, construct an LLSD map matching the pattern
+ LLSD data;
+ data["foo"] = "bar";
+ data["random"] = 17;
+ driver.post(data);
+ check_listener("direct", listener0, data);
+ check_listener("filtered", listener1, data);
+ }
+
+ template<> template<>
+ void filter_object::test<2>()
+ {
+ set_test_name("LLEventTimeout::actionAfter()");
+ LLEventPump& driver(pumps.obtain("driver"));
+ TestEventTimeout filter(driver);
+ listener0.reset(0);
+ LLTempBoundListener temp1(
+ listener0.listenTo(filter));
+ // Use listener1.call() as the Action for actionAfter(), since it
+ // already provides a way to sense the call
+ listener1.reset(0);
+ // driver --> filter --> listener0
+ filter.actionAfter(20,
+ boost::bind(&Listener::call, boost::ref(listener1), LLSD("timeout")));
+ // Okay, (fake) timer is ticking. 'filter' can only sense the timer
+ // when we pump mainloop. Do that right now to take the logic path
+ // before either the anticipated event arrives or the timer expires.
+ mainloop.post(17);
+ check_listener("no timeout 1", listener1, LLSD(0));
+ // Expected event arrives...
+ driver.post(1);
+ check_listener("event passed thru", listener0, LLSD(1));
+ // Should have canceled the timer. Verify that by asserting that the
+ // time has expired, then pumping mainloop again.
+ filter.forceTimeout();
+ mainloop.post(17);
+ check_listener("no timeout 2", listener1, LLSD(0));
+ // Verify chained actionAfter() calls, that is, that a second
+ // actionAfter() resets the timer established by the first
+ // actionAfter().
+ filter.actionAfter(20,
+ boost::bind(&Listener::call, boost::ref(listener1), LLSD("timeout")));
+ // Since our TestEventTimeout class isn't actually manipulating time
+ // (quantities of seconds), only a bool "elapsed" flag, sense that by
+ // forcing the flag between actionAfter() calls.
+ filter.forceTimeout();
+ // Pumping mainloop here would result in a timeout (as we'll verify
+ // below). This state simulates a ticking timer that has not yet timed
+ // out. But now, before a mainloop event lets 'filter' recognize
+ // timeout on the previous actionAfter() call, pretend we're pushing
+ // that timeout farther into the future.
+ filter.actionAfter(20,
+ boost::bind(&Listener::call, boost::ref(listener1), LLSD("timeout")));
+ // Look ma, no timeout!
+ mainloop.post(17);
+ check_listener("no timeout 3", listener1, LLSD(0));
+ // Now let the updated actionAfter() timer expire.
+ filter.forceTimeout();
+ // Notice the timeout.
+ mainloop.post(17);
+ check_listener("timeout", listener1, LLSD("timeout"));
+ // Timing out cancels the timer. Verify that.
+ listener1.reset(0);
+ filter.forceTimeout();
+ mainloop.post(17);
+ check_listener("no timeout 4", listener1, LLSD(0));
+ // Reset the timer and then cancel() it.
+ filter.actionAfter(20,
+ boost::bind(&Listener::call, boost::ref(listener1), LLSD("timeout")));
+ // neither expired nor satisified
+ mainloop.post(17);
+ check_listener("no timeout 5", listener1, LLSD(0));
+ // cancel
+ filter.cancel();
+ // timeout!
+ filter.forceTimeout();
+ mainloop.post(17);
+ check_listener("no timeout 6", listener1, LLSD(0));
+ }
+
+ template<> template<>
+ void filter_object::test<3>()
+ {
+ set_test_name("LLEventTimeout::eventAfter()");
+ LLEventPump& driver(pumps.obtain("driver"));
+ TestEventTimeout filter(driver);
+ listener0.reset(0);
+ LLTempBoundListener temp1(
+ listener0.listenTo(filter));
+ filter.eventAfter(20, LLSD("timeout"));
+ // Okay, (fake) timer is ticking. 'filter' can only sense the timer
+ // when we pump mainloop. Do that right now to take the logic path
+ // before either the anticipated event arrives or the timer expires.
+ mainloop.post(17);
+ check_listener("no timeout 1", listener0, LLSD(0));
+ // Expected event arrives...
+ driver.post(1);
+ check_listener("event passed thru", listener0, LLSD(1));
+ // Should have canceled the timer. Verify that by asserting that the
+ // time has expired, then pumping mainloop again.
+ filter.forceTimeout();
+ mainloop.post(17);
+ check_listener("no timeout 2", listener0, LLSD(1));
+ // Set timer again.
+ filter.eventAfter(20, LLSD("timeout"));
+ // Now let the timer expire.
+ filter.forceTimeout();
+ // Notice the timeout.
+ mainloop.post(17);
+ check_listener("timeout", listener0, LLSD("timeout"));
+ // Timing out cancels the timer. Verify that.
+ listener0.reset(0);
+ filter.forceTimeout();
+ mainloop.post(17);
+ check_listener("no timeout 3", listener0, LLSD(0));
+ }
+
+ template<> template<>
+ void filter_object::test<4>()
+ {
+ set_test_name("LLEventTimeout::errorAfter()");
+ WrapLL_ERRS capture;
+ LLEventPump& driver(pumps.obtain("driver"));
+ TestEventTimeout filter(driver);
+ listener0.reset(0);
+ LLTempBoundListener temp1(
+ listener0.listenTo(filter));
+ filter.errorAfter(20, "timeout");
+ // Okay, (fake) timer is ticking. 'filter' can only sense the timer
+ // when we pump mainloop. Do that right now to take the logic path
+ // before either the anticipated event arrives or the timer expires.
+ mainloop.post(17);
+ check_listener("no timeout 1", listener0, LLSD(0));
+ // Expected event arrives...
+ driver.post(1);
+ check_listener("event passed thru", listener0, LLSD(1));
+ // Should have canceled the timer. Verify that by asserting that the
+ // time has expired, then pumping mainloop again.
+ filter.forceTimeout();
+ mainloop.post(17);
+ check_listener("no timeout 2", listener0, LLSD(1));
+ // Set timer again.
+ filter.errorAfter(20, "timeout");
+ // Now let the timer expire.
+ filter.forceTimeout();
+ // Notice the timeout.
+ std::string threw;
+ try
+ {
+ mainloop.post(17);
+ }
+ catch (const WrapLL_ERRS::FatalException& e)
+ {
+ threw = e.what();
+ }
+ ensure_contains("errorAfter() timeout exception", threw, "timeout");
+ // Timing out cancels the timer. Verify that.
+ listener0.reset(0);
+ filter.forceTimeout();
+ mainloop.post(17);
+ check_listener("no timeout 3", listener0, LLSD(0));
+ }
+} // namespace tut
+
+/*****************************************************************************
+* Link dependencies
+*****************************************************************************/
+#include "llsdutil.cpp"
diff --git a/indra/llcommon/tests/llframetimer_test.cpp b/indra/llcommon/tests/llframetimer_test.cpp
new file mode 100644
index 0000000000..1d047e41f8
--- /dev/null
+++ b/indra/llcommon/tests/llframetimer_test.cpp
@@ -0,0 +1,118 @@
+/**
+ * @file lltiming_test.cpp
+ * @date 2006-07-23
+ * @brief Tests the timers.
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ *
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../llframetimer.h"
+#include "../llsd.h"
+
+#include "../test/lltut.h"
+
+namespace tut
+{
+ struct frametimer_test
+ {
+ frametimer_test()
+ {
+ LLFrameTimer::updateFrameTime();
+ }
+ };
+ typedef test_group<frametimer_test> frametimer_group_t;
+ typedef frametimer_group_t::object frametimer_object_t;
+ tut::frametimer_group_t frametimer_instance("frametimer");
+
+ template<> template<>
+ void frametimer_object_t::test<1>()
+ {
+ F64 seconds_since_epoch = LLFrameTimer::getTotalSeconds();
+ LLFrameTimer timer;
+ timer.setExpiryAt(seconds_since_epoch);
+ F64 expires_at = timer.expiresAt();
+ ensure_distance(
+ "set expiry matches get expiry",
+ expires_at,
+ seconds_since_epoch,
+ 0.001);
+ }
+
+ template<> template<>
+ void frametimer_object_t::test<2>()
+ {
+ F64 seconds_since_epoch = LLFrameTimer::getTotalSeconds();
+ seconds_since_epoch += 10.0;
+ LLFrameTimer timer;
+ timer.setExpiryAt(seconds_since_epoch);
+ F64 expires_at = timer.expiresAt();
+ ensure_distance(
+ "set expiry matches get expiry 1",
+ expires_at,
+ seconds_since_epoch,
+ 0.001);
+ seconds_since_epoch += 10.0;
+ timer.setExpiryAt(seconds_since_epoch);
+ expires_at = timer.expiresAt();
+ ensure_distance(
+ "set expiry matches get expiry 2",
+ expires_at,
+ seconds_since_epoch,
+ 0.001);
+ }
+ template<> template<>
+ void frametimer_object_t::test<3>()
+ {
+ F64 seconds_since_epoch = LLFrameTimer::getTotalSeconds();
+ seconds_since_epoch += 2.0;
+ LLFrameTimer timer;
+ timer.setExpiryAt(seconds_since_epoch);
+ ensure("timer not expired on create", !timer.hasExpired());
+ int ii;
+ for(ii = 0; ii < 10; ++ii)
+ {
+ ms_sleep(150);
+ LLFrameTimer::updateFrameTime();
+ }
+ ensure("timer not expired after a bit", !timer.hasExpired());
+ for(ii = 0; ii < 10; ++ii)
+ {
+ ms_sleep(100);
+ LLFrameTimer::updateFrameTime();
+ }
+ ensure("timer expired", timer.hasExpired());
+ }
+/*
+ template<> template<>
+ void frametimer_object_t::test<4>()
+ {
+ }
+*/
+}
diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp
new file mode 100644
index 0000000000..7415f2d33b
--- /dev/null
+++ b/indra/llcommon/tests/llinstancetracker_test.cpp
@@ -0,0 +1,160 @@
+/**
+ * @file llinstancetracker_test.cpp
+ * @author Nat Goodspeed
+ * @date 2009-11-10
+ * @brief Test for llinstancetracker.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llinstancetracker.h"
+// STL headers
+#include <string>
+#include <vector>
+#include <set>
+#include <algorithm> // std::sort()
+// std headers
+// external library headers
+#include <boost/scoped_ptr.hpp>
+// other Linden headers
+#include "../test/lltut.h"
+
+struct Keyed: public LLInstanceTracker<Keyed, std::string>
+{
+ Keyed(const std::string& name):
+ LLInstanceTracker<Keyed, std::string>(name),
+ mName(name)
+ {}
+ std::string mName;
+};
+
+struct Unkeyed: public LLInstanceTracker<Unkeyed>
+{
+};
+
+/*****************************************************************************
+* TUT
+*****************************************************************************/
+namespace tut
+{
+ struct llinstancetracker_data
+ {
+ };
+ typedef test_group<llinstancetracker_data> llinstancetracker_group;
+ typedef llinstancetracker_group::object object;
+ llinstancetracker_group llinstancetrackergrp("llinstancetracker");
+
+ template<> template<>
+ void object::test<1>()
+ {
+ ensure_equals(Keyed::instanceCount(), 0);
+ {
+ Keyed one("one");
+ ensure_equals(Keyed::instanceCount(), 1);
+ Keyed* found = Keyed::getInstance("one");
+ ensure("couldn't find stack Keyed", found);
+ ensure_equals("found wrong Keyed instance", found, &one);
+ {
+ boost::scoped_ptr<Keyed> two(new Keyed("two"));
+ ensure_equals(Keyed::instanceCount(), 2);
+ Keyed* found = Keyed::getInstance("two");
+ ensure("couldn't find heap Keyed", found);
+ ensure_equals("found wrong Keyed instance", found, two.get());
+ }
+ ensure_equals(Keyed::instanceCount(), 1);
+ }
+ Keyed* found = Keyed::getInstance("one");
+ ensure("Keyed key lives too long", ! found);
+ ensure_equals(Keyed::instanceCount(), 0);
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ ensure_equals(Unkeyed::instanceCount(), 0);
+ {
+ Unkeyed one;
+ ensure_equals(Unkeyed::instanceCount(), 1);
+ Unkeyed* found = Unkeyed::getInstance(&one);
+ ensure_equals(found, &one);
+ {
+ boost::scoped_ptr<Unkeyed> two(new Unkeyed);
+ ensure_equals(Unkeyed::instanceCount(), 2);
+ Unkeyed* found = Unkeyed::getInstance(two.get());
+ ensure_equals(found, two.get());
+ }
+ ensure_equals(Unkeyed::instanceCount(), 1);
+ }
+ ensure_equals(Unkeyed::instanceCount(), 0);
+ }
+
+ template<> template<>
+ void object::test<3>()
+ {
+ Keyed one("one"), two("two"), three("three");
+ // We don't want to rely on the underlying container delivering keys
+ // in any particular order. That allows us the flexibility to
+ // reimplement LLInstanceTracker using, say, a hash map instead of a
+ // std::map. We DO insist that every key appear exactly once.
+ typedef std::vector<std::string> StringVector;
+ StringVector keys(Keyed::beginKeys(), Keyed::endKeys());
+ std::sort(keys.begin(), keys.end());
+ StringVector::const_iterator ki(keys.begin());
+ ensure_equals(*ki++, "one");
+ ensure_equals(*ki++, "three");
+ ensure_equals(*ki++, "two");
+ // Use ensure() here because ensure_equals would want to display
+ // mismatched values, and frankly that wouldn't help much.
+ ensure("didn't reach end", ki == keys.end());
+
+ // Use a somewhat different approach to order independence with
+ // beginInstances(): explicitly capture the instances we know in a
+ // set, and delete them as we iterate through.
+ typedef std::set<Keyed*> InstanceSet;
+ InstanceSet instances;
+ instances.insert(&one);
+ instances.insert(&two);
+ instances.insert(&three);
+ for (Keyed::instance_iter ii(Keyed::beginInstances()), iend(Keyed::endInstances());
+ ii != iend; ++ii)
+ {
+ Keyed& ref = *ii;
+ ensure_equals("spurious instance", instances.erase(&ref), 1);
+ }
+ ensure_equals("unreported instance", instances.size(), 0);
+ }
+
+ template<> template<>
+ void object::test<4>()
+ {
+ Unkeyed one, two, three;
+ typedef std::set<Unkeyed*> KeySet;
+ KeySet keys;
+ keys.insert(&one);
+ keys.insert(&two);
+ keys.insert(&three);
+ for (Unkeyed::key_iter ki(Unkeyed::beginKeys()), kend(Unkeyed::endKeys());
+ ki != kend; ++ki)
+ {
+ ensure_equals("spurious key", keys.erase(*ki), 1);
+ }
+ ensure_equals("unreported key", keys.size(), 0);
+
+ KeySet instances;
+ instances.insert(&one);
+ instances.insert(&two);
+ instances.insert(&three);
+ for (Unkeyed::instance_iter ii(Unkeyed::beginInstances()), iend(Unkeyed::endInstances());
+ ii != iend; ++ii)
+ {
+ Unkeyed& ref = *ii;
+ ensure_equals("spurious instance", instances.erase(&ref), 1);
+ }
+ ensure_equals("unreported instance", instances.size(), 0);
+ }
+} // namespace tut
diff --git a/indra/llcommon/tests/lllazy_test.cpp b/indra/llcommon/tests/lllazy_test.cpp
new file mode 100644
index 0000000000..db581d650f
--- /dev/null
+++ b/indra/llcommon/tests/lllazy_test.cpp
@@ -0,0 +1,227 @@
+/**
+ * @file lllazy_test.cpp
+ * @author Nat Goodspeed
+ * @date 2009-01-28
+ * @brief Tests of lllazy.h.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "lllazy.h"
+// STL headers
+#include <iostream>
+// std headers
+// external library headers
+#include <boost/lambda/construct.hpp>
+#include <boost/lambda/bind.hpp>
+// other Linden headers
+#include "../test/lltut.h"
+
+namespace bll = boost::lambda;
+
+/*****************************************************************************
+* Test classes
+*****************************************************************************/
+
+// Let's say that because of its many external dependencies, YuckyFoo is very
+// hard to instantiate in a test harness.
+class YuckyFoo
+{
+public:
+ virtual ~YuckyFoo() {}
+ virtual std::string whoami() const { return "YuckyFoo"; }
+};
+
+// Let's further suppose that YuckyBar is another hard-to-instantiate class.
+class YuckyBar
+{
+public:
+ YuckyBar(const std::string& which):
+ mWhich(which)
+ {}
+ virtual ~YuckyBar() {}
+
+ virtual std::string identity() const { return std::string("YuckyBar(") + mWhich + ")"; }
+
+private:
+ const std::string mWhich;
+};
+
+// Pretend that this class would be tough to test because, up until we started
+// trying to test it, it contained instances of both YuckyFoo and YuckyBar.
+// Now we've refactored so it contains LLLazy<YuckyFoo> and LLLazy<YuckyBar>.
+// More than that, it contains them by virtue of deriving from
+// LLLazyBase<YuckyFoo> and LLLazyBase<YuckyBar>.
+// We postulate two different LLLazyBases because, with only one, you need not
+// specify *which* get()/set() method you're talking about. That's a simpler
+// case.
+class NeedsTesting: public LLLazyBase<YuckyFoo>, public LLLazyBase<YuckyBar>
+{
+public:
+ NeedsTesting():
+ // mYuckyBar("RealYuckyBar")
+ LLLazyBase<YuckyBar>(bll::bind(bll::new_ptr<YuckyBar>(), "RealYuckyBar"))
+ {}
+ virtual ~NeedsTesting() {}
+
+ virtual std::string describe() const
+ {
+ return std::string("NeedsTesting(") + getLazy<YuckyFoo>(this).whoami() + ", " +
+ getLazy<YuckyBar>(this).identity() + ")";
+ }
+
+private:
+ // These instance members were moved to LLLazyBases:
+ // YuckyFoo mYuckyFoo;
+ // YuckyBar mYuckyBar;
+};
+
+// Fake up a test YuckyFoo class
+class TestFoo: public YuckyFoo
+{
+public:
+ virtual std::string whoami() const { return "TestFoo"; }
+};
+
+// and a test YuckyBar
+class TestBar: public YuckyBar
+{
+public:
+ TestBar(const std::string& which): YuckyBar(which) {}
+ virtual std::string identity() const
+ {
+ return std::string("TestBar(") + YuckyBar::identity() + ")";
+ }
+};
+
+// So here's a test subclass of NeedsTesting that uses TestFoo and TestBar
+// instead of YuckyFoo and YuckyBar.
+class TestNeedsTesting: public NeedsTesting
+{
+public:
+ TestNeedsTesting()
+ {
+ // Exercise setLazy(T*)
+ setLazy<YuckyFoo>(this, new TestFoo());
+ // Exercise setLazy(Factory)
+ setLazy<YuckyBar>(this, bll::bind(bll::new_ptr<TestBar>(), "TestYuckyBar"));
+ }
+
+ virtual std::string describe() const
+ {
+ return std::string("TestNeedsTesting(") + NeedsTesting::describe() + ")";
+ }
+
+ void toolate()
+ {
+ setLazy<YuckyFoo>(this, new TestFoo());
+ }
+};
+
+// This class tests having an explicit LLLazy<T> instance as a named member,
+// rather than deriving from LLLazyBase<T>.
+class LazyMember
+{
+public:
+ YuckyFoo& getYuckyFoo() { return *mYuckyFoo; }
+ std::string whoisit() const { return mYuckyFoo->whoami(); }
+
+protected:
+ LLLazy<YuckyFoo> mYuckyFoo;
+};
+
+// This is a test subclass of the above, dynamically replacing the
+// LLLazy<YuckyFoo> member.
+class TestLazyMember: public LazyMember
+{
+public:
+ // use factory setter
+ TestLazyMember()
+ {
+ mYuckyFoo.set(bll::new_ptr<TestFoo>());
+ }
+
+ // use instance setter
+ TestLazyMember(YuckyFoo* instance)
+ {
+ mYuckyFoo.set(instance);
+ }
+};
+
+/*****************************************************************************
+* TUT
+*****************************************************************************/
+namespace tut
+{
+ struct lllazy_data
+ {
+ };
+ typedef test_group<lllazy_data> lllazy_group;
+ typedef lllazy_group::object lllazy_object;
+ lllazy_group lllazygrp("lllazy");
+
+ template<> template<>
+ void lllazy_object::test<1>()
+ {
+ // Instantiate an official one, just because we can
+ NeedsTesting nt;
+ // and a test one
+ TestNeedsTesting tnt;
+// std::cout << nt.describe() << '\n';
+ ensure_equals(nt.describe(), "NeedsTesting(YuckyFoo, YuckyBar(RealYuckyBar))");
+// std::cout << tnt.describe() << '\n';
+ ensure_equals(tnt.describe(),
+ "TestNeedsTesting(NeedsTesting(TestFoo, TestBar(YuckyBar(TestYuckyBar))))");
+ }
+
+ template<> template<>
+ void lllazy_object::test<2>()
+ {
+ TestNeedsTesting tnt;
+ std::string threw;
+ try
+ {
+ tnt.toolate();
+ }
+ catch (const LLLazyCommon::InstanceChange& e)
+ {
+ threw = e.what();
+ }
+ ensure_contains("InstanceChange exception", threw, "replace LLLazy instance");
+ }
+
+ template<> template<>
+ void lllazy_object::test<3>()
+ {
+ {
+ LazyMember lm;
+ // operator*() on-demand instantiation
+ ensure_equals(lm.getYuckyFoo().whoami(), "YuckyFoo");
+ }
+ {
+ LazyMember lm;
+ // operator->() on-demand instantiation
+ ensure_equals(lm.whoisit(), "YuckyFoo");
+ }
+ }
+
+ template<> template<>
+ void lllazy_object::test<4>()
+ {
+ {
+ // factory setter
+ TestLazyMember tlm;
+ ensure_equals(tlm.whoisit(), "TestFoo");
+ }
+ {
+ // instance setter
+ TestLazyMember tlm(new TestFoo());
+ ensure_equals(tlm.whoisit(), "TestFoo");
+ }
+ }
+} // namespace tut
diff --git a/indra/llcommon/tests/llmemtype_test.cpp b/indra/llcommon/tests/llmemtype_test.cpp
new file mode 100644
index 0000000000..6cc5ce01ce
--- /dev/null
+++ b/indra/llcommon/tests/llmemtype_test.cpp
@@ -0,0 +1,123 @@
+/**
+ * @file llmemtype_test.cpp
+ * @author Palmer Truelson
+ * @date 2008-03-
+ * @brief Test for llmemtype.cpp.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "../llmemtype.h"
+#include "../test/lltut.h"
+#include "../llallocator.h"
+
+
+#include <stack>
+
+std::stack<S32> memTypeStack;
+
+void LLAllocator::pushMemType(S32 i)
+{
+ memTypeStack.push(i);
+}
+
+S32 LLAllocator::popMemType(void)
+{
+ S32 ret = memTypeStack.top();
+ memTypeStack.pop();
+ return ret;
+}
+
+namespace tut
+{
+ struct llmemtype_data
+ {
+ };
+
+ typedef test_group<llmemtype_data> factory;
+ typedef factory::object object;
+}
+namespace
+{
+ tut::factory llmemtype_test_factory("LLMemType");
+}
+
+namespace tut
+{
+ template<> template<>
+ void object::test<1>()
+ {
+ ensure("Simplest test ever", true);
+ }
+
+ // test with no scripts
+ template<> template<>
+ void object::test<2>()
+ {
+ {
+ LLMemType m1(LLMemType::MTYPE_INIT);
+ }
+ ensure("Test that you can construct and destruct the mem type");
+ }
+
+ // test creation and stack testing
+ template<> template<>
+ void object::test<3>()
+ {
+ {
+ ensure("Test that creation and destruction properly inc/dec the stack");
+ ensure_equals(memTypeStack.size(), 0);
+ {
+ LLMemType m1(LLMemType::MTYPE_INIT);
+ ensure_equals(memTypeStack.size(), 1);
+ LLMemType m2(LLMemType::MTYPE_STARTUP);
+ ensure_equals(memTypeStack.size(), 2);
+ }
+ ensure_equals(memTypeStack.size(), 0);
+ }
+ }
+
+ // test with no scripts
+ template<> template<>
+ void object::test<4>()
+ {
+ // catch the begining and end
+ std::string test_name = LLMemType::getNameFromID(LLMemType::MTYPE_INIT.mID);
+ ensure_equals("Init name", test_name, "Init");
+
+ std::string test_name2 = LLMemType::getNameFromID(LLMemType::MTYPE_VOLUME.mID);
+ ensure_equals("Volume name", test_name2, "Volume");
+
+ std::string test_name3 = LLMemType::getNameFromID(LLMemType::MTYPE_OTHER.mID);
+ ensure_equals("Other name", test_name3, "Other");
+
+ std::string test_name4 = LLMemType::getNameFromID(-1);
+ ensure_equals("Invalid name", test_name4, "INVALID");
+ }
+
+};
diff --git a/indra/llcommon/tests/llrand_test.cpp b/indra/llcommon/tests/llrand_test.cpp
new file mode 100644
index 0000000000..1f178d6fc9
--- /dev/null
+++ b/indra/llcommon/tests/llrand_test.cpp
@@ -0,0 +1,133 @@
+/**
+ * @file llrandom_test.cpp
+ * @author Phoenix
+ * @date 2007-01-25
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+
+#include "../llrand.h"
+
+
+namespace tut
+{
+ struct random
+ {
+ };
+
+ typedef test_group<random> random_t;
+ typedef random_t::object random_object_t;
+ tut::random_t tut_random("random");
+
+ template<> template<>
+ void random_object_t::test<1>()
+ {
+ F32 number = 0.0f;
+ for(S32 ii = 0; ii < 100000; ++ii)
+ {
+ number = ll_frand();
+ ensure("frand >= 0", (number >= 0.0f));
+ ensure("frand < 1", (number < 1.0f));
+ }
+ }
+
+ template<> template<>
+ void random_object_t::test<2>()
+ {
+ F64 number = 0.0f;
+ for(S32 ii = 0; ii < 100000; ++ii)
+ {
+ number = ll_drand();
+ ensure("drand >= 0", (number >= 0.0));
+ ensure("drand < 1", (number < 1.0));
+ }
+ }
+
+ template<> template<>
+ void random_object_t::test<3>()
+ {
+ F32 number = 0.0f;
+ for(S32 ii = 0; ii < 100000; ++ii)
+ {
+ number = ll_frand(2.0f) - 1.0f;
+ ensure("frand >= 0", (number >= -1.0f));
+ ensure("frand < 1", (number <= 1.0f));
+ }
+ }
+
+ template<> template<>
+ void random_object_t::test<4>()
+ {
+ F32 number = 0.0f;
+ for(S32 ii = 0; ii < 100000; ++ii)
+ {
+ number = ll_frand(-7.0);
+ ensure("drand <= 0", (number <= 0.0));
+ ensure("drand > -7", (number > -7.0));
+ }
+ }
+
+ template<> template<>
+ void random_object_t::test<5>()
+ {
+ F64 number = 0.0f;
+ for(S32 ii = 0; ii < 100000; ++ii)
+ {
+ number = ll_drand(-2.0);
+ ensure("drand <= 0", (number <= 0.0));
+ ensure("drand > -2", (number > -2.0));
+ }
+ }
+
+ template<> template<>
+ void random_object_t::test<6>()
+ {
+ S32 number = 0;
+ for(S32 ii = 0; ii < 100000; ++ii)
+ {
+ number = ll_rand(100);
+ ensure("rand >= 0", (number >= 0));
+ ensure("rand < 100", (number < 100));
+ }
+ }
+
+ template<> template<>
+ void random_object_t::test<7>()
+ {
+ S32 number = 0;
+ for(S32 ii = 0; ii < 100000; ++ii)
+ {
+ number = ll_rand(-127);
+ ensure("rand <= 0", (number <= 0));
+ ensure("rand > -127", (number > -127));
+ }
+ }
+}
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
new file mode 100644
index 0000000000..6ab48ec34a
--- /dev/null
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -0,0 +1,1504 @@
+/**
+ * @file llsdserialize_test.cpp
+ * @date 2006-04
+ * @brief LLSDSerialize unit tests
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ *
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#if !LL_WINDOWS
+#include <netinet/in.h>
+#endif
+
+#include "linden_common.h"
+#include "../llsd.h"
+#include "../llsdserialize.h"
+#include "../llformat.h"
+
+#include "../test/lltut.h"
+
+
+#if LL_WINDOWS
+#include <winsock2.h>
+typedef U32 uint32_t;
+#endif
+
+std::vector<U8> string_to_vector(std::string str)
+{
+ // bc LLSD can't...
+ size_t len = (size_t)str.length();
+ std::vector<U8> v(len);
+ for (size_t i = 0; i < len ; i++)
+ {
+ v[i] = str[i];
+ }
+ return v;
+}
+
+namespace tut
+{
+ struct sd_xml_data
+ {
+ sd_xml_data()
+ {
+ mFormatter = new LLSDXMLFormatter;
+ }
+ LLSD mSD;
+ LLPointer<LLSDXMLFormatter> mFormatter;
+ void xml_test(const char* name, const std::string& expected)
+ {
+ std::ostringstream ostr;
+ mFormatter->format(mSD, ostr);
+ ensure_equals(name, ostr.str(), expected);
+ }
+ };
+
+ typedef test_group<sd_xml_data> sd_xml_test;
+ typedef sd_xml_test::object sd_xml_object;
+ tut::sd_xml_test sd_xml_stream("sd_xml_serialization");
+
+ template<> template<>
+ void sd_xml_object::test<1>()
+ {
+ // random atomic tests
+ std::string expected;
+
+ expected = "<llsd><undef /></llsd>\n";
+ xml_test("undef", expected);
+
+ mSD = 3463;
+ expected = "<llsd><integer>3463</integer></llsd>\n";
+ xml_test("integer", expected);
+
+ mSD = "";
+ expected = "<llsd><string /></llsd>\n";
+ xml_test("empty string", expected);
+
+ mSD = "foobar";
+ expected = "<llsd><string>foobar</string></llsd>\n";
+ xml_test("string", expected);
+
+ mSD = LLUUID::null;
+ expected = "<llsd><uuid /></llsd>\n";
+ xml_test("null uuid", expected);
+
+ mSD = LLUUID("c96f9b1e-f589-4100-9774-d98643ce0bed");
+ expected = "<llsd><uuid>c96f9b1e-f589-4100-9774-d98643ce0bed</uuid></llsd>\n";
+ xml_test("uuid", expected);
+
+ mSD = LLURI("https://secondlife.com/login");
+ expected = "<llsd><uri>https://secondlife.com/login</uri></llsd>\n";
+ xml_test("uri", expected);
+
+ mSD = LLDate("2006-04-24T16:11:33Z");
+ expected = "<llsd><date>2006-04-24T16:11:33Z</date></llsd>\n";
+ xml_test("date", expected);
+
+ // Generated by: echo -n 'hello' | openssl enc -e -base64
+ std::vector<U8> hello;
+ hello.push_back('h');
+ hello.push_back('e');
+ hello.push_back('l');
+ hello.push_back('l');
+ hello.push_back('o');
+ mSD = hello;
+ expected = "<llsd><binary encoding=\"base64\">aGVsbG8=</binary></llsd>\n";
+ xml_test("binary", expected);
+ }
+
+ template<> template<>
+ void sd_xml_object::test<2>()
+ {
+ // tests with boolean values.
+ std::string expected;
+
+ mFormatter->boolalpha(true);
+ mSD = true;
+ expected = "<llsd><boolean>true</boolean></llsd>\n";
+ xml_test("bool alpha true", expected);
+ mSD = false;
+ expected = "<llsd><boolean>false</boolean></llsd>\n";
+ xml_test("bool alpha false", expected);
+
+ mFormatter->boolalpha(false);
+ mSD = true;
+ expected = "<llsd><boolean>1</boolean></llsd>\n";
+ xml_test("bool true", expected);
+ mSD = false;
+ expected = "<llsd><boolean>0</boolean></llsd>\n";
+ xml_test("bool false", expected);
+ }
+
+
+ template<> template<>
+ void sd_xml_object::test<3>()
+ {
+ // tests with real values.
+ std::string expected;
+
+ mFormatter->realFormat("%.2f");
+ mSD = 1.0;
+ expected = "<llsd><real>1.00</real></llsd>\n";
+ xml_test("real 1", expected);
+
+ mSD = -34379.0438;
+ expected = "<llsd><real>-34379.04</real></llsd>\n";
+ xml_test("real reduced precision", expected);
+ mFormatter->realFormat("%.4f");
+ expected = "<llsd><real>-34379.0438</real></llsd>\n";
+ xml_test("higher precision", expected);
+
+ mFormatter->realFormat("%.0f");
+ mSD = 0.0;
+ expected = "<llsd><real>0</real></llsd>\n";
+ xml_test("no decimal 0", expected);
+ mSD = 3287.4387;
+ expected = "<llsd><real>3287</real></llsd>\n";
+ xml_test("no decimal real number", expected);
+ }
+
+ template<> template<>
+ void sd_xml_object::test<4>()
+ {
+ // tests with arrays
+ std::string expected;
+
+ mSD = LLSD::emptyArray();
+ expected = "<llsd><array /></llsd>\n";
+ xml_test("empty array", expected);
+
+ mSD.append(LLSD());
+ expected = "<llsd><array><undef /></array></llsd>\n";
+ xml_test("1 element array", expected);
+
+ mSD.append(1);
+ expected = "<llsd><array><undef /><integer>1</integer></array></llsd>\n";
+ xml_test("2 element array", expected);
+ }
+
+ template<> template<>
+ void sd_xml_object::test<5>()
+ {
+ // tests with arrays
+ std::string expected;
+
+ mSD = LLSD::emptyMap();
+ expected = "<llsd><map /></llsd>\n";
+ xml_test("empty map", expected);
+
+ mSD["foo"] = "bar";
+ expected = "<llsd><map><key>foo</key><string>bar</string></map></llsd>\n";
+ xml_test("1 element map", expected);
+
+ mSD["baz"] = LLSD();
+ expected = "<llsd><map><key>baz</key><undef /><key>foo</key><string>bar</string></map></llsd>\n";
+ xml_test("2 element map", expected);
+ }
+
+ template<> template<>
+ void sd_xml_object::test<6>()
+ {
+ // tests with binary
+ std::string expected;
+
+ // Generated by: echo -n 'hello' | openssl enc -e -base64
+ mSD = string_to_vector("hello");
+ expected = "<llsd><binary encoding=\"base64\">aGVsbG8=</binary></llsd>\n";
+ xml_test("binary", expected);
+
+ mSD = string_to_vector("6|6|asdfhappybox|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|82000|450fe394-2904-c9ad-214c-a07eb7feec29|(No Description)|0|10|0");
+ expected = "<llsd><binary encoding=\"base64\">Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBlNDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZmZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMyOXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==</binary></llsd>\n";
+ xml_test("binary", expected);
+ }
+
+ class TestLLSDSerializeData
+ {
+ public:
+ TestLLSDSerializeData();
+ ~TestLLSDSerializeData();
+
+ void doRoundTripTests(const std::string&);
+ void checkRoundTrip(const std::string&, const LLSD& v);
+
+ LLPointer<LLSDFormatter> mFormatter;
+ LLPointer<LLSDParser> mParser;
+ };
+
+ TestLLSDSerializeData::TestLLSDSerializeData()
+ {
+ }
+
+ TestLLSDSerializeData::~TestLLSDSerializeData()
+ {
+ }
+
+ void TestLLSDSerializeData::checkRoundTrip(const std::string& msg, const LLSD& v)
+ {
+ std::stringstream stream;
+ mFormatter->format(v, stream);
+ //llinfos << "checkRoundTrip: length " << stream.str().length() << llendl;
+ LLSD w;
+ mParser->reset(); // reset() call is needed since test code re-uses mParser
+ mParser->parse(stream, w, stream.str().size());
+
+ try
+ {
+ ensure_equals(msg.c_str(), w, v);
+ }
+ catch (...)
+ {
+ std::cerr << "the serialized string was:" << std::endl;
+ std::cerr << stream.str() << std::endl;
+ throw;
+ }
+ }
+
+ static void fillmap(LLSD& root, U32 width, U32 depth)
+ {
+ if(depth == 0)
+ {
+ root["foo"] = "bar";
+ return;
+ }
+
+ for(U32 i = 0; i < width; ++i)
+ {
+ std::string key = llformat("child %d", i);
+ root[key] = LLSD::emptyMap();
+ fillmap(root[key], width, depth - 1);
+ }
+ }
+
+ void TestLLSDSerializeData::doRoundTripTests(const std::string& msg)
+ {
+ LLSD v;
+ checkRoundTrip(msg + " undefined", v);
+
+ v = true;
+ checkRoundTrip(msg + " true bool", v);
+
+ v = false;
+ checkRoundTrip(msg + " false bool", v);
+
+ v = 1;
+ checkRoundTrip(msg + " positive int", v);
+
+ v = 0;
+ checkRoundTrip(msg + " zero int", v);
+
+ v = -1;
+ checkRoundTrip(msg + " negative int", v);
+
+ v = 1234.5f;
+ checkRoundTrip(msg + " positive float", v);
+
+ v = 0.0f;
+ checkRoundTrip(msg + " zero float", v);
+
+ v = -1234.5f;
+ checkRoundTrip(msg + " negative float", v);
+
+ // FIXME: need a NaN test
+
+ v = LLUUID::null;
+ checkRoundTrip(msg + " null uuid", v);
+
+ LLUUID newUUID;
+ newUUID.generate();
+ v = newUUID;
+ checkRoundTrip(msg + " new uuid", v);
+
+ v = "";
+ checkRoundTrip(msg + " empty string", v);
+
+ v = "some string";
+ checkRoundTrip(msg + " non-empty string", v);
+
+ v =
+"Second Life is a 3-D virtual world entirely built and owned by its residents. "
+"Since opening to the public in 2003, it has grown explosively and today is "
+"inhabited by nearly 100,000 people from around the globe.\n"
+"\n"
+"From the moment you enter the World you'll discover a vast digital continent, "
+"teeming with people, entertainment, experiences and opportunity. Once you've "
+"explored a bit, perhaps you'll find a perfect parcel of land to build your "
+"house or business.\n"
+"\n"
+"You'll also be surrounded by the Creations of your fellow residents. Because "
+"residents retain the rights to their digital creations, they can buy, sell "
+"and trade with other residents.\n"
+"\n"
+"The Marketplace currently supports millions of US dollars in monthly "
+"transactions. This commerce is handled with the in-world currency, the Linden "
+"dollar, which can be converted to US dollars at several thriving online "
+"currency exchanges.\n"
+"\n"
+"Welcome to Second Life. We look forward to seeing you in-world!\n"
+ ;
+ checkRoundTrip(msg + " long string", v);
+
+ static const U32 block_size = 0x000020;
+ for (U32 block = 0x000000; block <= 0x10ffff; block += block_size)
+ {
+ std::ostringstream out;
+
+ for (U32 c = block; c < block + block_size; ++c)
+ {
+ if (c <= 0x000001f
+ && c != 0x000009
+ && c != 0x00000a)
+ {
+ // see XML standard, sections 2.2 and 4.1
+ continue;
+ }
+ if (0x00d800 <= c && c <= 0x00dfff) { continue; }
+ if (0x00fdd0 <= c && c <= 0x00fdef) { continue; }
+ if ((c & 0x00fffe) == 0x00fffe) { continue; }
+ // see Unicode standard, section 15.8
+
+ if (c <= 0x00007f)
+ {
+ out << (char)(c & 0x7f);
+ }
+ else if (c <= 0x0007ff)
+ {
+ out << (char)(0xc0 | ((c >> 6) & 0x1f));
+ out << (char)(0x80 | ((c >> 0) & 0x3f));
+ }
+ else if (c <= 0x00ffff)
+ {
+ out << (char)(0xe0 | ((c >> 12) & 0x0f));
+ out << (char)(0x80 | ((c >> 6) & 0x3f));
+ out << (char)(0x80 | ((c >> 0) & 0x3f));
+ }
+ else
+ {
+ out << (char)(0xf0 | ((c >> 18) & 0x07));
+ out << (char)(0x80 | ((c >> 12) & 0x3f));
+ out << (char)(0x80 | ((c >> 6) & 0x3f));
+ out << (char)(0x80 | ((c >> 0) & 0x3f));
+ }
+ }
+
+ v = out.str();
+
+ std::ostringstream blockmsg;
+ blockmsg << msg << " unicode string block 0x" << std::hex << block;
+ checkRoundTrip(blockmsg.str(), v);
+ }
+
+ LLDate epoch;
+ v = epoch;
+ checkRoundTrip(msg + " epoch date", v);
+
+ LLDate aDay("2002-12-07T05:07:15.00Z");
+ v = aDay;
+ checkRoundTrip(msg + " date", v);
+
+ LLURI path("http://slurl.com/secondlife/Ambleside/57/104/26/");
+ v = path;
+ checkRoundTrip(msg + " url", v);
+
+ const char source[] = "it must be a blue moon again";
+ std::vector<U8> data;
+ copy(&source[0], &source[sizeof(source)], back_inserter(data));
+
+ v = data;
+ checkRoundTrip(msg + " binary", v);
+
+ v = LLSD::emptyMap();
+ checkRoundTrip(msg + " empty map", v);
+
+ v = LLSD::emptyMap();
+ v["name"] = "luke"; //v.insert("name", "luke");
+ v["age"] = 3; //v.insert("age", 3);
+ checkRoundTrip(msg + " map", v);
+
+ v.clear();
+ v["a"]["1"] = true;
+ v["b"]["0"] = false;
+ checkRoundTrip(msg + " nested maps", v);
+
+ v = LLSD::emptyArray();
+ checkRoundTrip(msg + " empty array", v);
+
+ v = LLSD::emptyArray();
+ v.append("ali");
+ v.append(28);
+ checkRoundTrip(msg + " array", v);
+
+ v.clear();
+ v[0][0] = true;
+ v[1][0] = false;
+ checkRoundTrip(msg + " nested arrays", v);
+
+ v = LLSD::emptyMap();
+ fillmap(v, 10, 6); // 10^6 maps
+ checkRoundTrip(msg + " many nested maps", v);
+ }
+
+ typedef tut::test_group<TestLLSDSerializeData> TestLLSDSerialzeGroup;
+ typedef TestLLSDSerialzeGroup::object TestLLSDSerializeObject;
+ TestLLSDSerialzeGroup gTestLLSDSerializeGroup("llsd serialization");
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<1>()
+ {
+ mFormatter = new LLSDNotationFormatter();
+ mParser = new LLSDNotationParser();
+ doRoundTripTests("notation serialization");
+ }
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<2>()
+ {
+ mFormatter = new LLSDXMLFormatter();
+ mParser = new LLSDXMLParser();
+ doRoundTripTests("xml serialization");
+ }
+
+ template<> template<>
+ void TestLLSDSerializeObject::test<3>()
+ {
+ mFormatter = new LLSDBinaryFormatter();
+ mParser = new LLSDBinaryParser();
+ doRoundTripTests("binary serialization");
+ }
+
+
+ /**
+ * @class TestLLSDParsing
+ * @brief Base class for of a parse tester.
+ */
+ template <class parser_t>
+ class TestLLSDParsing
+ {
+ public:
+ TestLLSDParsing()
+ {
+ mParser = new parser_t;
+ }
+
+ void ensureParse(
+ const std::string& msg,
+ const std::string& in,
+ const LLSD& expected_value,
+ S32 expected_count)
+ {
+ std::stringstream input;
+ input.str(in);
+
+ LLSD parsed_result;
+ mParser->reset(); // reset() call is needed since test code re-uses mParser
+ S32 parsed_count = mParser->parse(input, parsed_result, in.size());
+ ensure_equals(msg.c_str(), parsed_result, expected_value);
+
+ // This count check is really only useful for expected
+ // parse failures, since the ensures equal will already
+ // require eqality.
+ std::string count_msg(msg);
+ count_msg += " (count)";
+ ensure_equals(count_msg, parsed_count, expected_count);
+ }
+
+ LLPointer<parser_t> mParser;
+ };
+
+
+ /**
+ * @class TestLLSDXMLParsing
+ * @brief Concrete instance of a parse tester.
+ */
+ class TestLLSDXMLParsing : public TestLLSDParsing<LLSDXMLParser>
+ {
+ public:
+ TestLLSDXMLParsing() {}
+ };
+
+ typedef tut::test_group<TestLLSDXMLParsing> TestLLSDXMLParsingGroup;
+ typedef TestLLSDXMLParsingGroup::object TestLLSDXMLParsingObject;
+ TestLLSDXMLParsingGroup gTestLLSDXMLParsingGroup("llsd XML parsing");
+
+ template<> template<>
+ void TestLLSDXMLParsingObject::test<1>()
+ {
+ // test handling of xml not recognized as llsd results in an
+ // LLSD Undefined
+ ensureParse(
+ "malformed xml",
+ "<llsd><string>ha ha</string>",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "not llsd",
+ "<html><body><p>ha ha</p></body></html>",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "value without llsd",
+ "<string>ha ha</string>",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "key without llsd",
+ "<key>ha ha</key>",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+
+ template<> template<>
+ void TestLLSDXMLParsingObject::test<2>()
+ {
+ // test handling of unrecognized or unparseable llsd values
+ LLSD v;
+ v["amy"] = 23;
+ v["bob"] = LLSD();
+ v["cam"] = 1.23;
+
+ ensureParse(
+ "unknown data type",
+ "<llsd><map>"
+ "<key>amy</key><integer>23</integer>"
+ "<key>bob</key><bigint>99999999999999999</bigint>"
+ "<key>cam</key><real>1.23</real>"
+ "</map></llsd>",
+ v,
+ v.size() + 1);
+ }
+
+ template<> template<>
+ void TestLLSDXMLParsingObject::test<3>()
+ {
+ // test handling of nested bad data
+
+ LLSD v;
+ v["amy"] = 23;
+ v["cam"] = 1.23;
+
+ ensureParse(
+ "map with html",
+ "<llsd><map>"
+ "<key>amy</key><integer>23</integer>"
+ "<html><body>ha ha</body></html>"
+ "<key>cam</key><real>1.23</real>"
+ "</map></llsd>",
+ v,
+ v.size() + 1);
+
+ v.clear();
+ v["amy"] = 23;
+ v["cam"] = 1.23;
+ ensureParse(
+ "map with value for key",
+ "<llsd><map>"
+ "<key>amy</key><integer>23</integer>"
+ "<string>ha ha</string>"
+ "<key>cam</key><real>1.23</real>"
+ "</map></llsd>",
+ v,
+ v.size() + 1);
+
+ v.clear();
+ v["amy"] = 23;
+ v["bob"] = LLSD::emptyMap();
+ v["cam"] = 1.23;
+ ensureParse(
+ "map with map of html",
+ "<llsd><map>"
+ "<key>amy</key><integer>23</integer>"
+ "<key>bob</key>"
+ "<map>"
+ "<html><body>ha ha</body></html>"
+ "</map>"
+ "<key>cam</key><real>1.23</real>"
+ "</map></llsd>",
+ v,
+ v.size() + 1);
+
+ v.clear();
+ v[0] = 23;
+ v[1] = LLSD();
+ v[2] = 1.23;
+
+ ensureParse(
+ "array value of html",
+ "<llsd><array>"
+ "<integer>23</integer>"
+ "<html><body>ha ha</body></html>"
+ "<real>1.23</real>"
+ "</array></llsd>",
+ v,
+ v.size() + 1);
+
+ v.clear();
+ v[0] = 23;
+ v[1] = LLSD::emptyMap();
+ v[2] = 1.23;
+ ensureParse(
+ "array with map of html",
+ "<llsd><array>"
+ "<integer>23</integer>"
+ "<map>"
+ "<html><body>ha ha</body></html>"
+ "</map>"
+ "<real>1.23</real>"
+ "</array></llsd>",
+ v,
+ v.size() + 1);
+ }
+
+ template<> template<>
+ void TestLLSDXMLParsingObject::test<4>()
+ {
+ // test handling of binary object in XML
+ std::string xml;
+ LLSD expected;
+
+ // Generated by: echo -n 'hello' | openssl enc -e -base64
+ expected = string_to_vector("hello");
+ xml = "<llsd><binary encoding=\"base64\">aGVsbG8=</binary></llsd>\n";
+ ensureParse(
+ "the word 'hello' packed in binary encoded base64",
+ xml,
+ expected,
+ 1);
+
+ expected = string_to_vector("6|6|asdfhappybox|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|82000|450fe394-2904-c9ad-214c-a07eb7feec29|(No Description)|0|10|0");
+ xml = "<llsd><binary encoding=\"base64\">Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBlNDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZmZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMyOXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==</binary></llsd>\n";
+ ensureParse(
+ "a common binary blob for object -> agent offline inv transfer",
+ xml,
+ expected,
+ 1);
+
+ expected = string_to_vector("6|6|asdfhappybox|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|60e44ec5-305c-43c2-9a19-b4b89b1ae2a6|00000000-0000-0000-0000-000000000000|7fffffff|7fffffff|0|0|82000|450fe394-2904-c9ad-214c-a07eb7feec29|(No Description)|0|10|0");
+ xml = "<llsd><binary encoding=\"base64\">Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBl\n";
+ xml += "NDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5\n";
+ xml += "LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZm\n";
+ xml += "ZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMy\n";
+ xml += "OXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==</binary></llsd>\n";
+ ensureParse(
+ "a common binary blob for object -> agent offline inv transfer",
+ xml,
+ expected,
+ 1);
+ }
+ /*
+ TODO:
+ test XML parsing
+ binary with unrecognized encoding
+ nested LLSD tags
+ multiple values inside an LLSD
+ */
+
+
+ /**
+ * @class TestLLSDNotationParsing
+ * @brief Concrete instance of a parse tester.
+ */
+ class TestLLSDNotationParsing : public TestLLSDParsing<LLSDNotationParser>
+ {
+ public:
+ TestLLSDNotationParsing() {}
+ };
+
+ typedef tut::test_group<TestLLSDNotationParsing> TestLLSDNotationParsingGroup;
+ typedef TestLLSDNotationParsingGroup::object TestLLSDNotationParsingObject;
+ TestLLSDNotationParsingGroup gTestLLSDNotationParsingGroup(
+ "llsd notation parsing");
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<1>()
+ {
+ // test handling of xml not recognized as llsd results in an
+ // LLSD Undefined
+ ensureParse(
+ "malformed notation map",
+ "{'ha ha'",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "malformed notation array",
+ "['ha ha'",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "malformed notation string",
+ "'ha ha",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "bad notation noise",
+ "g48ejlnfr",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<2>()
+ {
+ ensureParse("valid undef", "!", LLSD(), 1);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<3>()
+ {
+ LLSD val = false;
+ ensureParse("valid boolean false 0", "false", val, 1);
+ ensureParse("valid boolean false 1", "f", val, 1);
+ ensureParse("valid boolean false 2", "0", val, 1);
+ ensureParse("valid boolean false 3", "F", val, 1);
+ ensureParse("valid boolean false 4", "FALSE", val, 1);
+ val = true;
+ ensureParse("valid boolean true 0", "true", val, 1);
+ ensureParse("valid boolean true 1", "t", val, 1);
+ ensureParse("valid boolean true 2", "1", val, 1);
+ ensureParse("valid boolean true 3", "T", val, 1);
+ ensureParse("valid boolean true 4", "TRUE", val, 1);
+
+ val.clear();
+ ensureParse("invalid true", "TR", val, LLSDParser::PARSE_FAILURE);
+ ensureParse("invalid false", "FAL", val, LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<4>()
+ {
+ LLSD val = 123;
+ ensureParse("valid integer", "i123", val, 1);
+ val.clear();
+ ensureParse("invalid integer", "421", val, LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<5>()
+ {
+ LLSD val = 456.7;
+ ensureParse("valid real", "r456.7", val, 1);
+ val.clear();
+ ensureParse("invalid real", "456.7", val, LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<6>()
+ {
+ LLUUID id;
+ LLSD val = id;
+ ensureParse(
+ "unparseable uuid",
+ "u123",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ id.generate();
+ val = id;
+ std::string uuid_str("u");
+ uuid_str += id.asString();
+ ensureParse("valid uuid", uuid_str.c_str(), val, 1);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<7>()
+ {
+ LLSD val = std::string("foolish");
+ ensureParse("valid string 1", "\"foolish\"", val, 1);
+ val = std::string("g'day");
+ ensureParse("valid string 2", "\"g'day\"", val, 1);
+ val = std::string("have a \"nice\" day");
+ ensureParse("valid string 3", "'have a \"nice\" day'", val, 1);
+ val = std::string("whatever");
+ ensureParse("valid string 4", "s(8)\"whatever\"", val, 1);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<8>()
+ {
+ ensureParse(
+ "invalid string 1",
+ "s(7)\"whatever\"",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "invalid string 2",
+ "s(9)\"whatever\"",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<9>()
+ {
+ LLSD val = LLURI("http://www.google.com");
+ ensureParse("valid uri", "l\"http://www.google.com\"", val, 1);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<10>()
+ {
+ LLSD val = LLDate("2007-12-28T09:22:53.10Z");
+ ensureParse("valid date", "d\"2007-12-28T09:22:53.10Z\"", val, 1);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<11>()
+ {
+ std::vector<U8> vec;
+ vec.push_back((U8)'a'); vec.push_back((U8)'b'); vec.push_back((U8)'c');
+ vec.push_back((U8)'3'); vec.push_back((U8)'2'); vec.push_back((U8)'1');
+ LLSD val = vec;
+ ensureParse("valid binary b64", "b64\"YWJjMzIx\"", val, 1);
+ ensureParse("valid bainry b16", "b16\"616263333231\"", val, 1);
+ ensureParse("valid bainry raw", "b(6)\"abc321\"", val, 1);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<12>()
+ {
+ ensureParse(
+ "invalid -- binary length specified too long",
+ "b(7)\"abc321\"",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "invalid -- binary length specified way too long",
+ "b(1000000)\"abc321\"",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<13>()
+ {
+ LLSD val;
+ val["amy"] = 23;
+ val["bob"] = LLSD();
+ val["cam"] = 1.23;
+ ensureParse("simple map", "{'amy':i23,'bob':!,'cam':r1.23}", val, 4);
+
+ val["bob"] = LLSD::emptyMap();
+ val["bob"]["vehicle"] = std::string("bicycle");
+ ensureParse(
+ "nested map",
+ "{'amy':i23,'bob':{'vehicle':'bicycle'},'cam':r1.23}",
+ val,
+ 5);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<14>()
+ {
+ LLSD val;
+ val.append(23);
+ val.append(LLSD());
+ val.append(1.23);
+ ensureParse("simple array", "[i23,!,r1.23]", val, 4);
+ val[1] = LLSD::emptyArray();
+ val[1].append("bicycle");
+ ensureParse("nested array", "[i23,['bicycle'],r1.23]", val, 5);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<15>()
+ {
+ LLSD val;
+ val["amy"] = 23;
+ val["bob"]["dogs"] = LLSD::emptyArray();
+ val["bob"]["dogs"].append(LLSD::emptyMap());
+ val["bob"]["dogs"][0]["name"] = std::string("groove");
+ val["bob"]["dogs"][0]["breed"] = std::string("samoyed");
+ val["bob"]["dogs"].append(LLSD::emptyMap());
+ val["bob"]["dogs"][1]["name"] = std::string("greyley");
+ val["bob"]["dogs"][1]["breed"] = std::string("chow/husky");
+ val["cam"] = 1.23;
+ ensureParse(
+ "nested notation",
+ "{'amy':i23,"
+ " 'bob':{'dogs':["
+ "{'name':'groove', 'breed':'samoyed'},"
+ "{'name':'greyley', 'breed':'chow/husky'}]},"
+ " 'cam':r1.23}",
+ val,
+ 11);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<16>()
+ {
+ // text to make sure that incorrect sizes bail because
+ std::string bad_str("s(5)\"hi\"");
+ ensureParse(
+ "size longer than bytes left",
+ bad_str,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDNotationParsingObject::test<17>()
+ {
+ // text to make sure that incorrect sizes bail because
+ std::string bad_bin("b(5)\"hi\"");
+ ensureParse(
+ "size longer than bytes left",
+ bad_bin,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ /**
+ * @class TestLLSDBinaryParsing
+ * @brief Concrete instance of a parse tester.
+ */
+ class TestLLSDBinaryParsing : public TestLLSDParsing<LLSDBinaryParser>
+ {
+ public:
+ TestLLSDBinaryParsing() {}
+ };
+
+ typedef tut::test_group<TestLLSDBinaryParsing> TestLLSDBinaryParsingGroup;
+ typedef TestLLSDBinaryParsingGroup::object TestLLSDBinaryParsingObject;
+ TestLLSDBinaryParsingGroup gTestLLSDBinaryParsingGroup(
+ "llsd binary parsing");
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<1>()
+ {
+ std::vector<U8> vec;
+ vec.resize(6);
+ vec[0] = 'a'; vec[1] = 'b'; vec[2] = 'c';
+ vec[3] = '3'; vec[4] = '2'; vec[5] = '1';
+ std::string string_expected((char*)&vec[0], vec.size());
+ LLSD value = string_expected;
+
+ vec.resize(11);
+ vec[0] = 's'; // for string
+ vec[5] = 'a'; vec[6] = 'b'; vec[7] = 'c';
+ vec[8] = '3'; vec[9] = '2'; vec[10] = '1';
+
+ uint32_t size = htonl(6);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_good((char*)&vec[0], vec.size());
+ ensureParse("correct string parse", str_good, value, 1);
+
+ size = htonl(7);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_1((char*)&vec[0], vec.size());
+ ensureParse(
+ "incorrect size string parse",
+ str_bad_1,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ size = htonl(100000);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_2((char*)&vec[0], vec.size());
+ ensureParse(
+ "incorrect size string parse",
+ str_bad_2,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<2>()
+ {
+ std::vector<U8> vec;
+ vec.resize(6);
+ vec[0] = 'a'; vec[1] = 'b'; vec[2] = 'c';
+ vec[3] = '3'; vec[4] = '2'; vec[5] = '1';
+ LLSD value = vec;
+
+ vec.resize(11);
+ vec[0] = 'b'; // for binary
+ vec[5] = 'a'; vec[6] = 'b'; vec[7] = 'c';
+ vec[8] = '3'; vec[9] = '2'; vec[10] = '1';
+
+ uint32_t size = htonl(6);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_good((char*)&vec[0], vec.size());
+ ensureParse("correct binary parse", str_good, value, 1);
+
+ size = htonl(7);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_1((char*)&vec[0], vec.size());
+ ensureParse(
+ "incorrect size binary parse 1",
+ str_bad_1,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ size = htonl(100000);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_2((char*)&vec[0], vec.size());
+ ensureParse(
+ "incorrect size binary parse 2",
+ str_bad_2,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<3>()
+ {
+ // test handling of xml not recognized as llsd results in an
+ // LLSD Undefined
+ ensureParse(
+ "malformed binary map",
+ "{'ha ha'",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "malformed binary array",
+ "['ha ha'",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "malformed binary string",
+ "'ha ha",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ ensureParse(
+ "bad noise",
+ "g48ejlnfr",
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<4>()
+ {
+ ensureParse("valid undef", "!", LLSD(), 1);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<5>()
+ {
+ LLSD val = false;
+ ensureParse("valid boolean false 2", "0", val, 1);
+ val = true;
+ ensureParse("valid boolean true 2", "1", val, 1);
+
+ val.clear();
+ ensureParse("invalid true", "t", val, LLSDParser::PARSE_FAILURE);
+ ensureParse("invalid false", "f", val, LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<6>()
+ {
+ std::vector<U8> vec;
+ vec.push_back('{');
+ vec.resize(vec.size() + 4);
+ uint32_t size = htonl(1);
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ vec.push_back('k');
+ int key_size_loc = vec.size();
+ size = htonl(1); // 1 too short
+ vec.resize(vec.size() + 4);
+ memcpy(&vec[key_size_loc], &size, sizeof(uint32_t));
+ vec.push_back('a'); vec.push_back('m'); vec.push_back('y');
+ vec.push_back('i');
+ int integer_loc = vec.size();
+ vec.resize(vec.size() + 4);
+ uint32_t val_int = htonl(23);
+ memcpy(&vec[integer_loc], &val_int, sizeof(uint32_t));
+ std::string str_bad_1((char*)&vec[0], vec.size());
+ ensureParse(
+ "invalid key size",
+ str_bad_1,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ // check with correct size, but unterminated map (missing '}')
+ size = htonl(3); // correct size
+ memcpy(&vec[key_size_loc], &size, sizeof(uint32_t));
+ std::string str_bad_2((char*)&vec[0], vec.size());
+ ensureParse(
+ "valid key size, unterminated map",
+ str_bad_2,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ // check w/ correct size and correct map termination
+ LLSD val;
+ val["amy"] = 23;
+ vec.push_back('}');
+ std::string str_good((char*)&vec[0], vec.size());
+ ensureParse(
+ "valid map",
+ str_good,
+ val,
+ 2);
+
+ // check w/ incorrect sizes and correct map termination
+ size = htonl(0); // 1 too few (for the map entry)
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_3((char*)&vec[0], vec.size());
+ ensureParse(
+ "invalid map too long",
+ str_bad_3,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ size = htonl(2); // 1 too many
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_4((char*)&vec[0], vec.size());
+ ensureParse(
+ "invalid map too short",
+ str_bad_4,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<7>()
+ {
+ std::vector<U8> vec;
+ vec.push_back('[');
+ vec.resize(vec.size() + 4);
+ uint32_t size = htonl(1); // 1 too short
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ vec.push_back('"'); vec.push_back('a'); vec.push_back('m');
+ vec.push_back('y'); vec.push_back('"'); vec.push_back('i');
+ int integer_loc = vec.size();
+ vec.resize(vec.size() + 4);
+ uint32_t val_int = htonl(23);
+ memcpy(&vec[integer_loc], &val_int, sizeof(uint32_t));
+
+ std::string str_bad_1((char*)&vec[0], vec.size());
+ ensureParse(
+ "invalid array size",
+ str_bad_1,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ // check with correct size, but unterminated map (missing ']')
+ size = htonl(2); // correct size
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_2((char*)&vec[0], vec.size());
+ ensureParse(
+ "unterminated array",
+ str_bad_2,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ // check w/ correct size and correct map termination
+ LLSD val;
+ val.append("amy");
+ val.append(23);
+ vec.push_back(']');
+ std::string str_good((char*)&vec[0], vec.size());
+ ensureParse(
+ "valid array",
+ str_good,
+ val,
+ 3);
+
+ // check with too many elements
+ size = htonl(3); // 1 too long
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_bad_3((char*)&vec[0], vec.size());
+ ensureParse(
+ "array too short",
+ str_bad_3,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<8>()
+ {
+ std::vector<U8> vec;
+ vec.push_back('{');
+ vec.resize(vec.size() + 4);
+ memset(&vec[1], 0, 4);
+ vec.push_back('}');
+ std::string str_good((char*)&vec[0], vec.size());
+ LLSD val = LLSD::emptyMap();
+ ensureParse(
+ "empty map",
+ str_good,
+ val,
+ 1);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<9>()
+ {
+ std::vector<U8> vec;
+ vec.push_back('[');
+ vec.resize(vec.size() + 4);
+ memset(&vec[1], 0, 4);
+ vec.push_back(']');
+ std::string str_good((char*)&vec[0], vec.size());
+ LLSD val = LLSD::emptyArray();
+ ensureParse(
+ "empty array",
+ str_good,
+ val,
+ 1);
+ }
+
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<10>()
+ {
+ std::vector<U8> vec;
+ vec.push_back('l');
+ vec.resize(vec.size() + 4);
+ uint32_t size = htonl(14); // 1 too long
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ vec.push_back('h'); vec.push_back('t'); vec.push_back('t');
+ vec.push_back('p'); vec.push_back(':'); vec.push_back('/');
+ vec.push_back('/'); vec.push_back('s'); vec.push_back('l');
+ vec.push_back('.'); vec.push_back('c'); vec.push_back('o');
+ vec.push_back('m');
+ std::string str_bad((char*)&vec[0], vec.size());
+ ensureParse(
+ "invalid uri length size",
+ str_bad,
+ LLSD(),
+ LLSDParser::PARSE_FAILURE);
+
+ LLSD val;
+ val = LLURI("http://sl.com");
+ size = htonl(13); // correct length
+ memcpy(&vec[1], &size, sizeof(uint32_t));
+ std::string str_good((char*)&vec[0], vec.size());
+ ensureParse(
+ "valid key size",
+ str_good,
+ val,
+ 1);
+ }
+
+/*
+ template<> template<>
+ void TestLLSDBinaryParsingObject::test<11>()
+ {
+ }
+*/
+
+ /**
+ * @class TestLLSDCrossCompatible
+ * @brief Miscellaneous serialization and parsing tests
+ */
+ class TestLLSDCrossCompatible
+ {
+ public:
+ TestLLSDCrossCompatible() {}
+
+ void ensureBinaryAndNotation(
+ const std::string& msg,
+ const LLSD& input)
+ {
+ // to binary, and back again
+ std::stringstream str1;
+ S32 count1 = LLSDSerialize::toBinary(input, str1);
+ LLSD actual_value_bin;
+ S32 count2 = LLSDSerialize::fromBinary(
+ actual_value_bin,
+ str1,
+ LLSDSerialize::SIZE_UNLIMITED);
+ ensure_equals(
+ "ensureBinaryAndNotation binary count",
+ count2,
+ count1);
+
+ // to notation and back again
+ std::stringstream str2;
+ S32 count3 = LLSDSerialize::toNotation(actual_value_bin, str2);
+ ensure_equals(
+ "ensureBinaryAndNotation notation count1",
+ count3,
+ count2);
+ LLSD actual_value_notation;
+ S32 count4 = LLSDSerialize::fromNotation(
+ actual_value_notation,
+ str2,
+ LLSDSerialize::SIZE_UNLIMITED);
+ ensure_equals(
+ "ensureBinaryAndNotation notation count2",
+ count4,
+ count3);
+ ensure_equals(
+ (msg + " (binaryandnotation)").c_str(),
+ actual_value_notation,
+ input);
+ }
+
+ void ensureBinaryAndXML(
+ const std::string& msg,
+ const LLSD& input)
+ {
+ // to binary, and back again
+ std::stringstream str1;
+ S32 count1 = LLSDSerialize::toBinary(input, str1);
+ LLSD actual_value_bin;
+ S32 count2 = LLSDSerialize::fromBinary(
+ actual_value_bin,
+ str1,
+ LLSDSerialize::SIZE_UNLIMITED);
+ ensure_equals(
+ "ensureBinaryAndXML binary count",
+ count2,
+ count1);
+
+ // to xml and back again
+ std::stringstream str2;
+ S32 count3 = LLSDSerialize::toXML(actual_value_bin, str2);
+ ensure_equals(
+ "ensureBinaryAndXML xml count1",
+ count3,
+ count2);
+ LLSD actual_value_xml;
+ S32 count4 = LLSDSerialize::fromXML(actual_value_xml, str2);
+ ensure_equals(
+ "ensureBinaryAndXML xml count2",
+ count4,
+ count3);
+ ensure_equals((msg + " (binaryandxml)").c_str(), actual_value_xml, input);
+ }
+ };
+
+ typedef tut::test_group<TestLLSDCrossCompatible> TestLLSDCompatibleGroup;
+ typedef TestLLSDCompatibleGroup::object TestLLSDCompatibleObject;
+ TestLLSDCompatibleGroup gTestLLSDCompatibleGroup(
+ "llsd serialize compatible");
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<1>()
+ {
+ LLSD test;
+ ensureBinaryAndNotation("undef", test);
+ ensureBinaryAndXML("undef", test);
+ test = true;
+ ensureBinaryAndNotation("boolean true", test);
+ ensureBinaryAndXML("boolean true", test);
+ test = false;
+ ensureBinaryAndNotation("boolean false", test);
+ ensureBinaryAndXML("boolean false", test);
+ test = 0;
+ ensureBinaryAndNotation("integer zero", test);
+ ensureBinaryAndXML("integer zero", test);
+ test = 1;
+ ensureBinaryAndNotation("integer positive", test);
+ ensureBinaryAndXML("integer positive", test);
+ test = -234567;
+ ensureBinaryAndNotation("integer negative", test);
+ ensureBinaryAndXML("integer negative", test);
+ test = 0.0;
+ ensureBinaryAndNotation("real zero", test);
+ ensureBinaryAndXML("real zero", test);
+ test = 1.0;
+ ensureBinaryAndNotation("real positive", test);
+ ensureBinaryAndXML("real positive", test);
+ test = -1.0;
+ ensureBinaryAndNotation("real negative", test);
+ ensureBinaryAndXML("real negative", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<2>()
+ {
+ LLSD test;
+ test = "foobar";
+ ensureBinaryAndNotation("string", test);
+ ensureBinaryAndXML("string", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<3>()
+ {
+ LLSD test;
+ LLUUID id;
+ id.generate();
+ test = id;
+ ensureBinaryAndNotation("uuid", test);
+ ensureBinaryAndXML("uuid", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<4>()
+ {
+ LLSD test;
+ test = LLDate(12345.0);
+ ensureBinaryAndNotation("date", test);
+ ensureBinaryAndXML("date", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<5>()
+ {
+ LLSD test;
+ test = LLURI("http://www.secondlife.com/");
+ ensureBinaryAndNotation("uri", test);
+ ensureBinaryAndXML("uri", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<6>()
+ {
+ LLSD test;
+ typedef std::vector<U8> buf_t;
+ buf_t val;
+ for(int ii = 0; ii < 100; ++ii)
+ {
+ srand(ii); /* Flawfinder: ignore */
+ S32 size = rand() % 100 + 10;
+ std::generate_n(
+ std::back_insert_iterator<buf_t>(val),
+ size,
+ rand);
+ }
+ test = val;
+ ensureBinaryAndNotation("binary", test);
+ ensureBinaryAndXML("binary", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<7>()
+ {
+ LLSD test;
+ test = LLSD::emptyArray();
+ test.append(1);
+ test.append("hello");
+ ensureBinaryAndNotation("array", test);
+ ensureBinaryAndXML("array", test);
+ }
+
+ template<> template<>
+ void TestLLSDCompatibleObject::test<8>()
+ {
+ LLSD test;
+ test = LLSD::emptyArray();
+ test["foo"] = "bar";
+ test["baz"] = 100;
+ ensureBinaryAndNotation("map", test);
+ ensureBinaryAndXML("map", test);
+ }
+}
+
diff --git a/indra/llcommon/tests/llstring_test.cpp b/indra/llcommon/tests/llstring_test.cpp
new file mode 100644
index 0000000000..beba55416a
--- /dev/null
+++ b/indra/llcommon/tests/llstring_test.cpp
@@ -0,0 +1,751 @@
+/**
+ * @file llstring_test.cpp
+ * @author Adroit, Steve Linden, Tofu Linden
+ * @date 2006-12-24
+ * @brief Test cases of llstring.cpp
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+
+#include "../llstring.h"
+
+namespace tut
+{
+ struct string_index
+ {
+ };
+ typedef test_group<string_index> string_index_t;
+ typedef string_index_t::object string_index_object_t;
+ tut::string_index_t tut_string_index("string_test");
+
+ template<> template<>
+ void string_index_object_t::test<1>()
+ {
+ std::string llstr1;
+ ensure("Empty std::string", (llstr1.size() == 0) && llstr1.empty());
+
+ std::string llstr2("Hello");
+ ensure("std::string = Hello", (!strcmp(llstr2.c_str(), "Hello")) && (llstr2.size() == 5) && !llstr2.empty());
+
+ std::string llstr3(llstr2);
+ ensure("std::string = std::string(std::string)", (!strcmp(llstr3.c_str(), "Hello")) && (llstr3.size() == 5) && !llstr3.empty());
+
+ std::string str("Hello World");
+ std::string llstr4(str, 6);
+ ensure("std::string = std::string(s, size_type pos, size_type n = npos)", (!strcmp(llstr4.c_str(), "World")) && (llstr4.size() == 5) && !llstr4.empty());
+
+ std::string llstr5(str, str.size());
+ ensure("std::string = std::string(s, size_type pos, size_type n = npos)", (llstr5.size() == 0) && llstr5.empty());
+
+ std::string llstr6(5, 'A');
+ ensure("std::string = std::string(count, c)", (!strcmp(llstr6.c_str(), "AAAAA")) && (llstr6.size() == 5) && !llstr6.empty());
+
+ std::string llstr7("Hello World", 5);
+ ensure("std::string(s, n)", (!strcmp(llstr7.c_str(), "Hello")) && (llstr7.size() == 5) && !llstr7.empty());
+
+ std::string llstr8("Hello World", 6, 5);
+ ensure("std::string(s, n, count)", (!strcmp(llstr8.c_str(), "World")) && (llstr8.size() == 5) && !llstr8.empty());
+
+ std::string llstr9("Hello World", sizeof("Hello World")-1, 5); // go past end
+ ensure("std::string(s, n, count) goes past end", (llstr9.size() == 0) && llstr9.empty());
+ }
+
+ template<> template<>
+ void string_index_object_t::test<3>()
+ {
+ std::string str("Len=5");
+ ensure("isValidIndex failed", LLStringUtil::isValidIndex(str, 0) == TRUE &&
+ LLStringUtil::isValidIndex(str, 5) == TRUE &&
+ LLStringUtil::isValidIndex(str, 6) == FALSE);
+
+ std::string str1;
+ ensure("isValidIndex failed fo rempty string", LLStringUtil::isValidIndex(str1, 0) == FALSE);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<4>()
+ {
+ std::string str_val(" Testing the extra whitespaces ");
+ LLStringUtil::trimHead(str_val);
+ ensure_equals("1: trimHead failed", str_val, "Testing the extra whitespaces ");
+
+ std::string str_val1("\n\t\r\n Testing the extra whitespaces ");
+ LLStringUtil::trimHead(str_val1);
+ ensure_equals("2: trimHead failed", str_val1, "Testing the extra whitespaces ");
+ }
+
+ template<> template<>
+ void string_index_object_t::test<5>()
+ {
+ std::string str_val(" Testing the extra whitespaces ");
+ LLStringUtil::trimTail(str_val);
+ ensure_equals("1: trimTail failed", str_val, " Testing the extra whitespaces");
+
+ std::string str_val1("\n Testing the extra whitespaces \n\t\r\n ");
+ LLStringUtil::trimTail(str_val1);
+ ensure_equals("2: trimTail failed", str_val1, "\n Testing the extra whitespaces");
+ }
+
+
+ template<> template<>
+ void string_index_object_t::test<6>()
+ {
+ std::string str_val(" \t \r Testing the extra \r\n whitespaces \n \t ");
+ LLStringUtil::trim(str_val);
+ ensure_equals("1: trim failed", str_val, "Testing the extra \r\n whitespaces");
+ }
+
+ template<> template<>
+ void string_index_object_t::test<7>()
+ {
+ std::string str("Second LindenLabs");
+ LLStringUtil::truncate(str, 6);
+ ensure_equals("1: truncate", str, "Second");
+
+ // further truncate more than the length
+ LLStringUtil::truncate(str, 0);
+ ensure_equals("2: truncate", str, "");
+ }
+
+ template<> template<>
+ void string_index_object_t::test<8>()
+ {
+ std::string str_val("SecondLife Source");
+ LLStringUtil::toUpper(str_val);
+ ensure_equals("toUpper failed", str_val, "SECONDLIFE SOURCE");
+ }
+
+ template<> template<>
+ void string_index_object_t::test<9>()
+ {
+ std::string str_val("SecondLife Source");
+ LLStringUtil::toLower(str_val);
+ ensure_equals("toLower failed", str_val, "secondlife source");
+ }
+
+ template<> template<>
+ void string_index_object_t::test<10>()
+ {
+ std::string str_val("Second");
+ ensure("1. isHead failed", LLStringUtil::isHead(str_val, "SecondLife Source") == TRUE);
+ ensure("2. isHead failed", LLStringUtil::isHead(str_val, " SecondLife Source") == FALSE);
+ std::string str_val2("");
+ ensure("3. isHead failed", LLStringUtil::isHead(str_val2, "") == FALSE);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<11>()
+ {
+ std::string str_val("Hello.\n\n Lindenlabs. \n This is \na simple test.\n");
+ std::string orig_str_val(str_val);
+ LLStringUtil::addCRLF(str_val);
+ ensure_equals("addCRLF failed", str_val, "Hello.\r\n\r\n Lindenlabs. \r\n This is \r\na simple test.\r\n");
+ LLStringUtil::removeCRLF(str_val);
+ ensure_equals("removeCRLF failed", str_val, orig_str_val);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<12>()
+ {
+ std::string str_val("Hello.\n\n\t \t Lindenlabs. \t\t");
+ std::string orig_str_val(str_val);
+ LLStringUtil::replaceTabsWithSpaces(str_val, 1);
+ ensure_equals("replaceTabsWithSpaces failed", str_val, "Hello.\n\n Lindenlabs. ");
+ LLStringUtil::replaceTabsWithSpaces(orig_str_val, 0);
+ ensure_equals("replaceTabsWithSpaces failed for 0", orig_str_val, "Hello.\n\n Lindenlabs. ");
+
+ str_val = "\t\t\t\t";
+ LLStringUtil::replaceTabsWithSpaces(str_val, 0);
+ ensure_equals("replaceTabsWithSpaces failed for all tabs", str_val, "");
+ }
+
+ template<> template<>
+ void string_index_object_t::test<13>()
+ {
+ std::string str_val("Hello.\n\n\t\t\r\nLindenlabsX.");
+ LLStringUtil::replaceNonstandardASCII(str_val, 'X');
+ ensure_equals("replaceNonstandardASCII failed", str_val, "Hello.\n\nXXX\nLindenlabsX.");
+ }
+
+ template<> template<>
+ void string_index_object_t::test<14>()
+ {
+ std::string str_val("Hello.\n\t\r\nABCDEFGHIABABAB");
+ LLStringUtil::replaceChar(str_val, 'A', 'X');
+ ensure_equals("1: replaceChar failed", str_val, "Hello.\n\t\r\nXBCDEFGHIXBXBXB");
+ std::string str_val1("Hello.\n\t\r\nABCDEFGHIABABAB");
+ }
+
+ template<> template<>
+ void string_index_object_t::test<15>()
+ {
+ std::string str_val("Hello.\n\r\t");
+ ensure("containsNonprintable failed", LLStringUtil::containsNonprintable(str_val) == TRUE);
+
+ str_val = "ABC ";
+ ensure("containsNonprintable failed", LLStringUtil::containsNonprintable(str_val) == FALSE);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<16>()
+ {
+ std::string str_val("Hello.\n\r\t Again!");
+ LLStringUtil::stripNonprintable(str_val);
+ ensure_equals("stripNonprintable failed", str_val, "Hello. Again!");
+
+ str_val = "\r\n\t\t";
+ LLStringUtil::stripNonprintable(str_val);
+ ensure_equals("stripNonprintable resulting in empty string failed", str_val, "");
+
+ str_val = "";
+ LLStringUtil::stripNonprintable(str_val);
+ ensure_equals("stripNonprintable of empty string resulting in empty string failed", str_val, "");
+ }
+
+ template<> template<>
+ void string_index_object_t::test<17>()
+ {
+ BOOL value;
+ std::string str_val("1");
+ ensure("convertToBOOL 1 failed", LLStringUtil::convertToBOOL(str_val, value) && value);
+ str_val = "T";
+ ensure("convertToBOOL T failed", LLStringUtil::convertToBOOL(str_val, value) && value);
+ str_val = "t";
+ ensure("convertToBOOL t failed", LLStringUtil::convertToBOOL(str_val, value) && value);
+ str_val = "TRUE";
+ ensure("convertToBOOL TRUE failed", LLStringUtil::convertToBOOL(str_val, value) && value);
+ str_val = "True";
+ ensure("convertToBOOL True failed", LLStringUtil::convertToBOOL(str_val, value) && value);
+ str_val = "true";
+ ensure("convertToBOOL true failed", LLStringUtil::convertToBOOL(str_val, value) && value);
+
+ str_val = "0";
+ ensure("convertToBOOL 0 failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
+ str_val = "F";
+ ensure("convertToBOOL F failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
+ str_val = "f";
+ ensure("convertToBOOL f failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
+ str_val = "FALSE";
+ ensure("convertToBOOL FASLE failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
+ str_val = "False";
+ ensure("convertToBOOL False failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
+ str_val = "false";
+ ensure("convertToBOOL false failed", LLStringUtil::convertToBOOL(str_val, value) && !value);
+
+ str_val = "Tblah";
+ ensure("convertToBOOL false failed", !LLStringUtil::convertToBOOL(str_val, value));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<18>()
+ {
+ U8 value;
+ std::string str_val("255");
+ ensure("1: convertToU8 failed", LLStringUtil::convertToU8(str_val, value) && value == 255);
+
+ str_val = "0";
+ ensure("2: convertToU8 failed", LLStringUtil::convertToU8(str_val, value) && value == 0);
+
+ str_val = "-1";
+ ensure("3: convertToU8 failed", !LLStringUtil::convertToU8(str_val, value));
+
+ str_val = "256"; // bigger than MAX_U8
+ ensure("4: convertToU8 failed", !LLStringUtil::convertToU8(str_val, value));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<19>()
+ {
+ S8 value;
+ std::string str_val("127");
+ ensure("1: convertToS8 failed", LLStringUtil::convertToS8(str_val, value) && value == 127);
+
+ str_val = "0";
+ ensure("2: convertToS8 failed", LLStringUtil::convertToS8(str_val, value) && value == 0);
+
+ str_val = "-128";
+ ensure("3: convertToS8 failed", LLStringUtil::convertToS8(str_val, value) && value == -128);
+
+ str_val = "128"; // bigger than MAX_S8
+ ensure("4: convertToS8 failed", !LLStringUtil::convertToS8(str_val, value));
+
+ str_val = "-129";
+ ensure("5: convertToS8 failed", !LLStringUtil::convertToS8(str_val, value));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<20>()
+ {
+ S16 value;
+ std::string str_val("32767");
+ ensure("1: convertToS16 failed", LLStringUtil::convertToS16(str_val, value) && value == 32767);
+
+ str_val = "0";
+ ensure("2: convertToS16 failed", LLStringUtil::convertToS16(str_val, value) && value == 0);
+
+ str_val = "-32768";
+ ensure("3: convertToS16 failed", LLStringUtil::convertToS16(str_val, value) && value == -32768);
+
+ str_val = "32768";
+ ensure("4: convertToS16 failed", !LLStringUtil::convertToS16(str_val, value));
+
+ str_val = "-32769";
+ ensure("5: convertToS16 failed", !LLStringUtil::convertToS16(str_val, value));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<21>()
+ {
+ U16 value;
+ std::string str_val("65535"); //0xFFFF
+ ensure("1: convertToU16 failed", LLStringUtil::convertToU16(str_val, value) && value == 65535);
+
+ str_val = "0";
+ ensure("2: convertToU16 failed", LLStringUtil::convertToU16(str_val, value) && value == 0);
+
+ str_val = "-1";
+ ensure("3: convertToU16 failed", !LLStringUtil::convertToU16(str_val, value));
+
+ str_val = "65536";
+ ensure("4: convertToU16 failed", !LLStringUtil::convertToU16(str_val, value));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<22>()
+ {
+ U32 value;
+ std::string str_val("4294967295"); //0xFFFFFFFF
+ ensure("1: convertToU32 failed", LLStringUtil::convertToU32(str_val, value) && value == 4294967295UL);
+
+ str_val = "0";
+ ensure("2: convertToU32 failed", LLStringUtil::convertToU32(str_val, value) && value == 0);
+
+ str_val = "4294967296";
+ ensure("3: convertToU32 failed", !LLStringUtil::convertToU32(str_val, value));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<23>()
+ {
+ S32 value;
+ std::string str_val("2147483647"); //0x7FFFFFFF
+ ensure("1: convertToS32 failed", LLStringUtil::convertToS32(str_val, value) && value == 2147483647);
+
+ str_val = "0";
+ ensure("2: convertToS32 failed", LLStringUtil::convertToS32(str_val, value) && value == 0);
+
+ // Avoid "unary minus operator applied to unsigned type" warning on VC++. JC
+ S32 min_val = -2147483647 - 1;
+ str_val = "-2147483648";
+ ensure("3: convertToS32 failed", LLStringUtil::convertToS32(str_val, value) && value == min_val);
+
+ str_val = "2147483648";
+ ensure("4: convertToS32 failed", !LLStringUtil::convertToS32(str_val, value));
+
+ str_val = "-2147483649";
+ ensure("5: convertToS32 failed", !LLStringUtil::convertToS32(str_val, value));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<24>()
+ {
+ F32 value;
+ std::string str_val("2147483647"); //0x7FFFFFFF
+ ensure("1: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == 2147483647);
+
+ str_val = "0";
+ ensure("2: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == 0);
+
+ /* Need to find max/min F32 values
+ str_val = "-2147483648";
+ ensure("3: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == -2147483648);
+
+ str_val = "2147483648";
+ ensure("4: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value));
+
+ str_val = "-2147483649";
+ ensure("5: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value));
+ */
+ }
+
+ template<> template<>
+ void string_index_object_t::test<25>()
+ {
+ F64 value;
+ std::string str_val("9223372036854775807"); //0x7FFFFFFFFFFFFFFF
+ ensure("1: convertToF64 failed", LLStringUtil::convertToF64(str_val, value) && value == 9223372036854775807LL);
+
+ str_val = "0";
+ ensure("2: convertToF64 failed", LLStringUtil::convertToF64(str_val, value) && value == 0.0F);
+
+ /* Need to find max/min F64 values
+ str_val = "-2147483648";
+ ensure("3: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == -2147483648);
+
+ str_val = "2147483648";
+ ensure("4: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value));
+
+ str_val = "-2147483649";
+ ensure("5: convertToF32 failed", !LLStringUtil::convertToF32(str_val, value));
+ */
+ }
+
+ template<> template<>
+ void string_index_object_t::test<26>()
+ {
+ const char* str1 = NULL;
+ const char* str2 = NULL;
+
+ ensure("1: compareStrings failed", LLStringUtil::compareStrings(str1, str2) == 0);
+ str2 = "A";
+ ensure("2: compareStrings failed", LLStringUtil::compareStrings(str1, str2) > 0);
+ ensure("3: compareStrings failed", LLStringUtil::compareStrings(str2, str1) < 0);
+
+ str1 = "A is smaller than B";
+ str2 = "B is greater than A";
+ ensure("4: compareStrings failed", LLStringUtil::compareStrings(str1, str2) < 0);
+
+ str2 = "A is smaller than B";
+ ensure("5: compareStrings failed", LLStringUtil::compareStrings(str1, str2) == 0);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<27>()
+ {
+ const char* str1 = NULL;
+ const char* str2 = NULL;
+
+ ensure("1: compareInsensitive failed", LLStringUtil::compareInsensitive(str1, str2) == 0);
+ str2 = "A";
+ ensure("2: compareInsensitive failed", LLStringUtil::compareInsensitive(str1, str2) > 0);
+ ensure("3: compareInsensitive failed", LLStringUtil::compareInsensitive(str2, str1) < 0);
+
+ str1 = "A is equal to a";
+ str2 = "a is EQUAL to A";
+ ensure("4: compareInsensitive failed", LLStringUtil::compareInsensitive(str1, str2) == 0);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<28>()
+ {
+ std::string lhs_str("PROgraM12files");
+ std::string rhs_str("PROgram12Files");
+ ensure("compareDict 1 failed", LLStringUtil::compareDict(lhs_str, rhs_str) < 0);
+ ensure("precedesDict 1 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == TRUE);
+
+ lhs_str = "PROgram12Files";
+ rhs_str = "PROgram12Files";
+ ensure("compareDict 2 failed", LLStringUtil::compareDict(lhs_str, rhs_str) == 0);
+ ensure("precedesDict 2 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == FALSE);
+
+ lhs_str = "PROgram12Files";
+ rhs_str = "PROgRAM12FILES";
+ ensure("compareDict 3 failed", LLStringUtil::compareDict(lhs_str, rhs_str) > 0);
+ ensure("precedesDict 3 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == FALSE);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<29>()
+ {
+ char str1[] = "First String...";
+ char str2[100];
+
+ LLStringUtil::copy(str2, str1, 100);
+ ensure("LLStringUtil::copy with enough dest length failed", strcmp(str2, str1) == 0);
+ LLStringUtil::copy(str2, str1, sizeof("First"));
+ ensure("LLStringUtil::copy with less dest length failed", strcmp(str2, "First") == 0);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<30>()
+ {
+ std::string str1 = "This is the sentence...";
+ std::string str2 = "This is the ";
+ std::string str3 = "first ";
+ std::string str4 = "This is the first sentence...";
+ std::string str5 = "This is the sentence...first ";
+ std::string dest;
+
+ dest = str1;
+ LLStringUtil::copyInto(dest, str3, str2.length());
+ ensure("LLStringUtil::copyInto insert failed", dest == str4);
+
+ dest = str1;
+ LLStringUtil::copyInto(dest, str3, dest.length());
+ ensure("LLStringUtil::copyInto append failed", dest == str5);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<31>()
+ {
+ std::string stripped;
+
+ // Plain US ASCII text, including spaces and punctuation,
+ // should not be altered.
+ std::string simple_text = "Hello, world!";
+ stripped = LLStringFn::strip_invalid_xml(simple_text);
+ ensure("Simple text passed unchanged", stripped == simple_text);
+
+ // Control characters should be removed
+ // except for 0x09, 0x0a, 0x0d
+ std::string control_chars;
+ for (char c = 0x01; c < 0x20; c++)
+ {
+ control_chars.push_back(c);
+ }
+ std::string allowed_control_chars;
+ allowed_control_chars.push_back( (char)0x09 );
+ allowed_control_chars.push_back( (char)0x0a );
+ allowed_control_chars.push_back( (char)0x0d );
+
+ stripped = LLStringFn::strip_invalid_xml(control_chars);
+ ensure("Only tab, LF, CR control characters allowed",
+ stripped == allowed_control_chars);
+
+ // UTF-8 should be passed intact, including high byte
+ // characters. Try Francais (with C squiggle cedilla)
+ std::string french = "Fran";
+ french.push_back( (char)0xC3 );
+ french.push_back( (char)0xA7 );
+ french += "ais";
+ stripped = LLStringFn::strip_invalid_xml( french );
+ ensure("UTF-8 high byte text is allowed", french == stripped );
+ }
+
+ template<> template<>
+ void string_index_object_t::test<32>()
+ {
+ // Test LLStringUtil::format() string interpolation
+ LLStringUtil::format_map_t fmt_map;
+ std::string s;
+ int subcount;
+
+ fmt_map["[TRICK1]"] = "[A]";
+ fmt_map["[A]"] = "a";
+ fmt_map["[B]"] = "b";
+ fmt_map["[AAA]"] = "aaa";
+ fmt_map["[BBB]"] = "bbb";
+ fmt_map["[TRICK2]"] = "[A]";
+ fmt_map["[EXPLOIT]"] = "!!!!!!!!!!!![EXPLOIT]!!!!!!!!!!!!";
+ fmt_map["[KEYLONGER]"] = "short";
+ fmt_map["[KEYSHORTER]"] = "Am I not a long string?";
+ fmt_map["?"] = "?";
+ fmt_map["[DELETE]"] = "";
+ fmt_map["[]"] = "[]"; // doesn't do a substitution, but shouldn't crash either
+
+ for (LLStringUtil::format_map_t::const_iterator iter = fmt_map.begin(); iter != fmt_map.end(); ++iter)
+ {
+ // Test when source string is entirely one key
+ std::string s1 = (std::string)iter->first;
+ std::string s2 = (std::string)iter->second;
+ subcount = LLStringUtil::format(s1, fmt_map);
+ ensure_equals("LLStringUtil::format: Raw interpolation result", s1, s2);
+ if (s1 == "?" || s1 == "[]") // no interp expected
+ {
+ ensure_equals("LLStringUtil::format: Raw interpolation result count", 0, subcount);
+ }
+ else
+ {
+ ensure_equals("LLStringUtil::format: Raw interpolation result count", 1, subcount);
+ }
+ }
+
+ for (LLStringUtil::format_map_t::const_iterator iter = fmt_map.begin(); iter != fmt_map.end(); ++iter)
+ {
+ // Test when source string is one key, duplicated
+ std::string s1 = (std::string)iter->first;
+ std::string s2 = (std::string)iter->second;
+ s = s1 + s1 + s1 + s1;
+ subcount = LLStringUtil::format(s, fmt_map);
+ ensure_equals("LLStringUtil::format: Rawx4 interpolation result", s, s2 + s2 + s2 + s2);
+ if (s1 == "?" || s1 == "[]") // no interp expected
+ {
+ ensure_equals("LLStringUtil::format: Rawx4 interpolation result count", 0, subcount);
+ }
+ else
+ {
+ ensure_equals("LLStringUtil::format: Rawx4 interpolation result count", 4, subcount);
+ }
+ }
+
+ // Test when source string has no keys
+ std::string srcs = "!!!!!!!!!!!!!!!!";
+ s = srcs;
+ subcount = LLStringUtil::format(s, fmt_map);
+ ensure_equals("LLStringUtil::format: No key test result", s, srcs);
+ ensure_equals("LLStringUtil::format: No key test result count", 0, subcount);
+
+ // Test when source string has no keys and is empty
+ std::string srcs3;
+ s = srcs3;
+ subcount = LLStringUtil::format(s, fmt_map);
+ ensure("LLStringUtil::format: No key test3 result", s.empty());
+ ensure_equals("LLStringUtil::format: No key test3 result count", 0, subcount);
+
+ // Test a substitution where a key is substituted with blankness
+ std::string srcs2 = "[DELETE]";
+ s = srcs2;
+ subcount = LLStringUtil::format(s, fmt_map);
+ ensure("LLStringUtil::format: Delete key test2 result", s.empty());
+ ensure_equals("LLStringUtil::format: Delete key test2 result count", 1, subcount);
+
+ // Test an assorted substitution
+ std::string srcs4 = "[TRICK1][A][B][AAA][BBB][TRICK2][KEYLONGER][KEYSHORTER]?[DELETE]";
+ s = srcs4;
+ subcount = LLStringUtil::format(s, fmt_map);
+ ensure_equals("LLStringUtil::format: Assorted Test1 result", s, "[A]abaaabbb[A]shortAm I not a long string??");
+ ensure_equals("LLStringUtil::format: Assorted Test1 result count", 9, subcount);
+
+ // Test an assorted substitution
+ std::string srcs5 = "[DELETE]?[KEYSHORTER][KEYLONGER][TRICK2][BBB][AAA][B][A][TRICK1]";
+ s = srcs5;
+ subcount = LLStringUtil::format(s, fmt_map);
+ ensure_equals("LLStringUtil::format: Assorted Test2 result", s, "?Am I not a long string?short[A]bbbaaaba[A]");
+ ensure_equals("LLStringUtil::format: Assorted Test2 result count", 9, subcount);
+
+ // Test an assorted substitution
+ std::string srcs8 = "foo[DELETE]bar?";
+ s = srcs8;
+ subcount = LLStringUtil::format(s, fmt_map);
+ ensure_equals("LLStringUtil::format: Assorted Test3 result", s, "foobar?");
+ ensure_equals("LLStringUtil::format: Assorted Test3 result count", 1, subcount);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<33>()
+ {
+ // Test LLStringUtil::format() string interpolation
+ LLStringUtil::format_map_t blank_fmt_map;
+ std::string s;
+ int subcount;
+
+ // Test substituting out of a blank format_map
+ std::string srcs6 = "12345";
+ s = srcs6;
+ subcount = LLStringUtil::format(s, blank_fmt_map);
+ ensure_equals("LLStringUtil::format: Blankfmt Test1 result", s, "12345");
+ ensure_equals("LLStringUtil::format: Blankfmt Test1 result count", 0, subcount);
+
+ // Test substituting a blank string out of a blank format_map
+ std::string srcs7;
+ s = srcs7;
+ subcount = LLStringUtil::format(s, blank_fmt_map);
+ ensure("LLStringUtil::format: Blankfmt Test2 result", s.empty());
+ ensure_equals("LLStringUtil::format: Blankfmt Test2 result count", 0, subcount);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<34>()
+ {
+ // Test that incorrect LLStringUtil::format() use does not explode.
+ LLStringUtil::format_map_t nasty_fmt_map;
+ std::string s;
+ int subcount;
+
+ nasty_fmt_map[""] = "never used"; // see, this is nasty.
+
+ // Test substituting out of a nasty format_map
+ std::string srcs6 = "12345";
+ s = srcs6;
+ subcount = LLStringUtil::format(s, nasty_fmt_map);
+ ensure_equals("LLStringUtil::format: Nastyfmt Test1 result", s, "12345");
+ ensure_equals("LLStringUtil::format: Nastyfmt Test1 result count", 0, subcount);
+
+ // Test substituting a blank string out of a nasty format_map
+ std::string srcs7;
+ s = srcs7;
+ subcount = LLStringUtil::format(s, nasty_fmt_map);
+ ensure("LLStringUtil::format: Nastyfmt Test2 result", s.empty());
+ ensure_equals("LLStringUtil::format: Nastyfmt Test2 result count", 0, subcount);
+ }
+
+ template<> template<>
+ void string_index_object_t::test<35>()
+ {
+ // Make sure startsWith works
+ std::string string("anybody in there?");
+ std::string substr("anybody");
+ ensure("startsWith works.", LLStringUtil::startsWith(string, substr));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<36>()
+ {
+ // Make sure startsWith correctly fails
+ std::string string("anybody in there?");
+ std::string substr("there");
+ ensure("startsWith fails.", !LLStringUtil::startsWith(string, substr));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<37>()
+ {
+ // startsWith fails on empty strings
+ std::string value("anybody in there?");
+ std::string empty;
+ ensure("empty string.", !LLStringUtil::startsWith(value, empty));
+ ensure("empty substr.", !LLStringUtil::startsWith(empty, value));
+ ensure("empty everything.", !LLStringUtil::startsWith(empty, empty));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<38>()
+ {
+ // Make sure endsWith works correctly
+ std::string string("anybody in there?");
+ std::string substr("there?");
+ ensure("endsWith works.", LLStringUtil::endsWith(string, substr));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<39>()
+ {
+ // Make sure endsWith correctly fails
+ std::string string("anybody in there?");
+ std::string substr("anybody");
+ ensure("endsWith fails.", !LLStringUtil::endsWith(string, substr));
+ substr = "there";
+ ensure("endsWith fails.", !LLStringUtil::endsWith(string, substr));
+ substr = "ther?";
+ ensure("endsWith fails.", !LLStringUtil::endsWith(string, substr));
+ }
+
+ template<> template<>
+ void string_index_object_t::test<40>()
+ {
+ // endsWith fails on empty strings
+ std::string value("anybody in there?");
+ std::string empty;
+ ensure("empty string.", !LLStringUtil::endsWith(value, empty));
+ ensure("empty substr.", !LLStringUtil::endsWith(empty, value));
+ ensure("empty everything.", !LLStringUtil::endsWith(empty, empty));
+ }
+}
diff --git a/indra/llcommon/tests/lltreeiterators_test.cpp b/indra/llcommon/tests/lltreeiterators_test.cpp
new file mode 100644
index 0000000000..31c70b4daa
--- /dev/null
+++ b/indra/llcommon/tests/lltreeiterators_test.cpp
@@ -0,0 +1,1219 @@
+/**
+ * @file lltreeiterators.cpp
+ * @author Nat Goodspeed
+ * @date 2008-08-20
+ * @brief Test of lltreeiterators.h
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+
+
+// STL headers
+// std headers
+#include <iostream>
+#include <sstream>
+#include <string>
+// external library headers
+#include <boost/bind.hpp>
+#include <boost/range/iterator_range.hpp>
+#include <boost/foreach.hpp>
+
+// associated header
+#include "../lltreeiterators.h"
+#include "../llpointer.h"
+
+#include "../test/lltut.h"
+
+/*****************************************************************************
+* tut test group
+*****************************************************************************/
+namespace tut
+{
+ struct iter_data
+ {
+ };
+ typedef test_group<iter_data> iter_group;
+ typedef iter_group::object iter_object;
+ tut::iter_group ig("lltreeiterators");
+} // namespace tut
+
+/*****************************************************************************
+* boost::get_pointer() specialization for LLPointer<>
+*****************************************************************************/
+// This specialization of boost::get_pointer() undoubtedly belongs in
+// llmemory.h. It's used by boost::bind() so that you can pass an
+// LLPointer<Foo> as well as a Foo* to a functor such as
+// boost::bind(&Foo::method, _1).
+//namespace boost
+//{
+ template <class NODE>
+ NODE* get_pointer(const LLPointer<NODE>& ptr) { return ptr.get(); }
+//};
+
+/*****************************************************************************
+* ScopeLabel
+*****************************************************************************/
+class ScopeLabel
+{
+public:
+ ScopeLabel(const std::string& label): mLabel(label)
+ {
+ std::cout << "Entering " << mLabel << '\n';
+ }
+ ~ScopeLabel()
+ {
+ std::cout << "Leaving " << mLabel << '\n';
+ }
+private:
+ std::string mLabel;
+};
+
+/*****************************************************************************
+* Cleanup
+*****************************************************************************/
+// Yes, we realize this is redundant with auto_ptr and LLPointer and all
+// kinds of better mechanisms. But in this particular source file, we need to
+// test nodes managed with plain old dumb pointers as well as nodes managed
+// with LLPointer, so we introduce this mechanism.
+//
+// In the general case, when we declare a Cleanup for some pointer, delete the
+// pointer when the Cleanup goes out of scope.
+template <typename PTRTYPE>
+struct Cleanup
+{
+ Cleanup(const PTRTYPE& ptr): mPtr(ptr) {}
+ ~Cleanup()
+ {
+ delete mPtr;
+ }
+ PTRTYPE mPtr;
+};
+
+// But when the pointer is an LLPointer<something>, Cleanup is a no-op:
+// LLPointer will handle the cleanup automagically.
+template <typename NODE>
+struct Cleanup< LLPointer<NODE> >
+{
+ Cleanup(const LLPointer<NODE>& ptr) {}
+ ~Cleanup() {}
+};
+
+/*****************************************************************************
+* Expected
+*****************************************************************************/
+// Expected is a base class used to capture the expected results -- a sequence
+// of string node names -- from one of our traversals of this example data.
+// Its subclasses initialize it with a pair of string iterators. It's not
+// strictly necessary to customize Expected to model Boost.Range, it's just
+// convenient.
+struct Expected
+{
+ template <typename ITER>
+ Expected(ITER begin, ITER end):
+ strings(begin, end)
+ {}
+ /*------ The following are to make Expected work with Boost.Range ------*/
+ typedef std::vector<std::string> container_type;
+ typedef container_type::iterator iterator;
+ typedef container_type::const_iterator const_iterator;
+ typedef container_type::size_type size_type;
+ container_type strings;
+ iterator begin() { return strings.begin(); }
+ iterator end() { return strings.end(); }
+ size_type size() { return strings.size(); }
+ const_iterator begin() const { return strings.begin(); }
+ const_iterator end() const { return strings.end(); }
+};
+
+// We have a couple of generic Expected template subclasses. This list of
+// strings is used for the "else" case when all specializations fail.
+const char* bad_strings[] = { "FAIL" };
+
+/*****************************************************************************
+* verify()
+*****************************************************************************/
+// test function: given (an object modeling) a Boost.Range of tree nodes,
+// compare the sequence of visited node names with a range of expected name
+// strings. Report success both with std::cout output and a bool return. The
+// string desc parameter is to identify the different tests.
+template <typename NODERANGE, typename STRINGRANGE>
+bool verify(const std::string& desc, NODERANGE noderange, STRINGRANGE expected)
+{
+ typename boost::range_iterator<NODERANGE>::type
+ nri = boost::begin(noderange),
+ nrend = boost::end(noderange);
+ typename boost::range_iterator<STRINGRANGE>::type
+ sri = boost::begin(expected),
+ srend = boost::end(expected);
+ // We choose to loop over both sequences explicitly rather than using
+ // std::equal() or std::lexicographical_compare(). The latter tells you
+ // whether one sequence is *less* than the other -- it doesn't tell you
+ // equality. std::equal() needs you to verify the sequence lengths ahead
+ // of time. Anyway, comparing explicitly allows us to report much more
+ // information about any sequence mismatch.
+ for ( ; nri != nrend && sri != srend; ++nri, ++sri)
+ {
+ if ((*nri)->name() != *sri)
+ {
+ std::cout << desc << " mismatch: "
+ << "expected " << *sri << ", got " << (*nri)->name() << "\n";
+ return false;
+ }
+ }
+ if (nri != nrend)
+ {
+ std::cout << desc << " produced too many items:\n";
+ for ( ; nri != nrend; ++nri)
+ {
+ std::cout << " " << (*nri)->name() << '\n';
+ }
+ return false;
+ }
+ if (sri != srend)
+ {
+ std::cout << desc << " produced too few items, omitting:\n";
+ for ( ; sri != srend; ++sri)
+ {
+ std::cout << " " << *sri << '\n';
+ }
+ return false;
+ }
+// std::cout << desc << " test passed\n";
+ return true;
+}
+
+/*****************************************************************************
+* PlainNode: LLLinkIter, non-refcounted
+*****************************************************************************/
+class PlainNode
+{
+public:
+ PlainNode(const std::string& name, PlainNode* next=NULL):
+ mName(name),
+ mNext(next)
+ {}
+ ~PlainNode()
+ {
+ delete mNext;
+ }
+ std::string name() const { return mName; }
+ PlainNode* next() const { return mNext; }
+public: // if this were 'private', couldn't bind mNext
+ PlainNode* mNext;
+private:
+ std::string mName;
+};
+
+namespace tut
+{
+ template<> template<>
+ void iter_object::test<1>()
+ {
+// set_test_name("LLLinkedIter -- non-refcounted class");
+ PlainNode* last(new PlainNode("c"));
+ PlainNode* second(new PlainNode("b", last));
+ PlainNode* first(new PlainNode("a", second));
+ Cleanup<PlainNode*> cleanup(first);
+ static const char* cseq[] = { "a", "b", "c" };
+ Expected seq(boost::begin(cseq), boost::end(cseq));
+ std::string desc1("Iterate by public link member");
+// std::cout << desc1 << ":\n";
+ // Try instantiating an iterator with NULL. This test is less about
+ // "did we iterate once?" than "did we avoid blowing up?"
+ for (LLLinkedIter<PlainNode> pni(NULL, boost::bind(&PlainNode::mNext, _1)), end;
+ pni != end; ++pni)
+ {
+// std::cout << (*pni)->name() << '\n';
+ ensure("LLLinkedIter<PlainNode>(NULL)", false);
+ }
+ ensure(desc1,
+ verify(desc1,
+ boost::make_iterator_range(LLLinkedIter<PlainNode>(first,
+ boost::bind(&PlainNode::mNext, _1)),
+ LLLinkedIter<PlainNode>()),
+ seq));
+ std::string desc2("Iterate by next() method");
+// std::cout << desc2 << ":\n";
+// for (LLLinkedIter<PlainNode> pni(first, boost::bind(&PlainNode::next, _1)); ! (pni == end); ++pni)
+// std::cout << (**pni).name() << '\n';
+ ensure(desc2,
+ verify(desc2,
+ boost::make_iterator_range(LLLinkedIter<PlainNode>(first,
+ boost::bind(&PlainNode::next, _1)),
+ LLLinkedIter<PlainNode>()),
+ seq));
+ {
+// LLLinkedIter<PlainNode> pni(first, boost::bind(&PlainNode::next, _1));
+// std::cout << "First is " << (*pni++)->name() << '\n';
+// std::cout << "Second is " << (*pni )->name() << '\n';
+ }
+ {
+ LLLinkedIter<PlainNode> pni(first, boost::bind(&PlainNode::next, _1));
+ ensure_equals("first", (*pni++)->name(), "a");
+ ensure_equals("second", (*pni )->name(), "b");
+ }
+ }
+} // tut
+
+/*****************************************************************************
+* RCNode: LLLinkIter, refcounted
+*****************************************************************************/
+class RCNode;
+typedef LLPointer<RCNode> RCNodePtr;
+
+class RCNode: public LLRefCount
+{
+public:
+ RCNode(const std::string& name, const RCNodePtr& next=RCNodePtr()):
+ mName(name),
+ mNext(next)
+ {
+// std::cout << "New RCNode(" << mName << ")\n";
+ }
+ RCNode(const RCNode& that):
+ mName(that.mName),
+ mNext(that.mNext)
+ {
+// std::cout << "Copy RCNode(" << mName << ")\n";
+ }
+ virtual ~RCNode();
+ std::string name() const { return mName; }
+ RCNodePtr next() const { return mNext; }
+public: // if this were 'private', couldn't bind mNext
+ RCNodePtr mNext;
+private:
+ std::string mName;
+};
+
+std::ostream& operator<<(std::ostream& out, const RCNode& node)
+{
+ out << "RCNode(" << node.name() << ')';
+ return out;
+}
+
+// This string contains the node name of the last RCNode destroyed. We use it
+// to validate that LLLinkedIter<RCNode> in fact contains LLPointer<RCNode>,
+// and that therefore an outstanding LLLinkedIter to an instance of a
+// refcounted class suffices to keep that instance alive.
+std::string last_RCNode_destroyed;
+
+RCNode::~RCNode()
+{
+// std::cout << "Kill " << *this << "\n";
+ last_RCNode_destroyed = mName;
+}
+
+namespace tut
+{
+ template<> template<>
+ void iter_object::test<2>()
+ {
+// set_test_name("LLLinkedIter -- refcounted class");
+ LLLinkedIter<RCNode> rcni, end2;
+ {
+// ScopeLabel label("inner scope");
+ RCNodePtr head(new RCNode("x", new RCNode("y", new RCNode("z"))));
+// for (rcni = LLLinkedIter<RCNode>(head, boost::bind(&RCNode::mNext, _1)); rcni != end2; ++rcni)
+// std::cout << **rcni << '\n';
+ rcni = LLLinkedIter<RCNode>(head, boost::bind(&RCNode::next, _1));
+ }
+// std::cout << "Now the LLLinkedIter<RCNode> is the only remaining reference to RCNode chain\n";
+ ensure_equals(last_RCNode_destroyed, "");
+ ensure(rcni != end2);
+ ensure_equals((*rcni)->name(), "x");
+ ++rcni;
+ ensure_equals(last_RCNode_destroyed, "x");
+ ensure(rcni != end2);
+ ensure_equals((*rcni)->name(), "y");
+ ++rcni;
+ ensure_equals(last_RCNode_destroyed, "y");
+ ensure(rcni != end2);
+ ensure_equals((*rcni)->name(), "z");
+ ++rcni;
+ ensure_equals(last_RCNode_destroyed, "z");
+ ensure(rcni == end2);
+ }
+}
+
+/*****************************************************************************
+* TreeNode
+*****************************************************************************/
+class TreeNode;
+typedef LLPointer<TreeNode> TreeNodePtr;
+
+/**
+ * TreeNode represents a refcounted tree-node class that hasn't (yet) been
+ * modified to incorporate LLTreeIter methods. This illustrates how you can
+ * use tree iterators either standalone, or with free functions.
+ */
+class TreeNode: public LLRefCount
+{
+public:
+ typedef std::vector<TreeNodePtr> list_type;
+ typedef list_type::const_iterator child_iterator;
+
+ // To avoid cycles, use a "weak" raw pointer for the parent link
+ TreeNode(const std::string& name, TreeNode* parent=0):
+ mParent(parent),
+ mName(name)
+ {}
+ TreeNodePtr newChild(const std::string& name)
+ {
+ TreeNodePtr child(new TreeNode(name, this));
+ mChildren.push_back(child);
+ return child;
+ }
+ std::string name() const { return mName; }
+ TreeNodePtr getParent() const { return mParent; }
+ child_iterator child_begin() const { return mChildren.begin(); }
+ child_iterator child_end() const { return mChildren.end(); }
+private:
+ std::string mName;
+ // To avoid cycles, use a "weak" raw pointer for the parent link
+ TreeNode* mParent;
+ list_type mChildren;
+};
+
+/**
+ * This is an example of a helper function to facilitate iterating from a
+ * TreeNode up to the root or down from the root (see LLTreeIter::RootIter).
+ *
+ * Example:
+ * @code
+ * BOOST_FOREACH(TreeNodePtr node, getRootRange<LLTreeIter::UP>(somenode))
+ * {
+ * std::cout << node->name() << '\n';
+ * }
+ * @endcode
+ */
+template <LLTreeIter::RootIter DISCRIM>
+boost::iterator_range< LLTreeRootIter<DISCRIM, TreeNode> >
+getRootRange(const TreeNodePtr& node)
+{
+ typedef LLTreeRootIter<DISCRIM, TreeNode> iter_type;
+ typedef boost::iterator_range<iter_type> range_type;
+ return range_type(iter_type(node, boost::bind(&TreeNode::getParent, _1)),
+ iter_type());
+}
+
+/**
+ * This is an example of a helper function to facilitate walking a given
+ * TreeNode's subtree in any supported order (see LLTreeIter::WalkIter).
+ *
+ * Example:
+ * @code
+ * BOOST_FOREACH(TreeNodePtr node, getWalkRange<LLTreeIter::DFS_PRE>(root))
+ * {
+ * std::cout << node->name() << '\n';
+ * }
+ * @endcode
+ */
+template <LLTreeIter::WalkIter DISCRIM>
+boost::iterator_range< LLTreeWalkIter<DISCRIM, TreeNode, TreeNode::child_iterator> >
+getWalkRange(const TreeNodePtr& node)
+{
+ typedef LLTreeWalkIter<DISCRIM, TreeNode, TreeNode::child_iterator> iter_type;
+ typedef boost::iterator_range<iter_type> range_type;
+ return range_type(iter_type(node,
+ boost::bind(&TreeNode::child_begin, _1),
+ boost::bind(&TreeNode::child_end, _1)),
+ iter_type());
+}
+
+/*****************************************************************************
+* EnhancedTreeNode
+*****************************************************************************/
+class EnhancedTreeNode;
+typedef LLPointer<EnhancedTreeNode> EnhancedTreeNodePtr;
+
+/**
+ * More typically, you enhance the tree-node class itself with template
+ * methods like the above. This EnhancedTreeNode class illustrates the
+ * technique. Normally, of course, you'd simply add these methods to TreeNode;
+ * we put them in a separate class to preserve the undecorated TreeNode class
+ * to illustrate (and test) the use of plain tree iterators and standalone
+ * helper functions.
+ *
+ * We originally implemented EnhancedTreeNode as a subclass of TreeNode -- but
+ * because TreeNode stores and manipulates TreeNodePtrs and TreeNode*s,
+ * reusing its methods required so much ugly downcast logic that we gave up
+ * and restated the whole class. Bear in mind that logically these aren't two
+ * separate classes; logically they're two snapshots of the @em same class at
+ * different moments in time.
+ */
+class EnhancedTreeNode: public LLRefCount
+{
+public:
+ /*-------------- The following is restated from TreeNode ---------------*/
+ typedef std::vector<EnhancedTreeNodePtr> list_type;
+ typedef list_type::const_iterator child_iterator;
+
+ // To avoid cycles, use a "weak" raw pointer for the parent link
+ EnhancedTreeNode(const std::string& name, EnhancedTreeNode* parent=0):
+ mParent(parent),
+ mName(name)
+ {}
+ EnhancedTreeNodePtr newChild(const std::string& name)
+ {
+ EnhancedTreeNodePtr child(new EnhancedTreeNode(name, this));
+ mChildren.push_back(child);
+ return child;
+ }
+ std::string name() const { return mName; }
+ EnhancedTreeNodePtr getParent() const { return mParent; }
+ child_iterator child_begin() const { return mChildren.begin(); }
+ child_iterator child_end() const { return mChildren.end(); }
+
+private:
+ std::string mName;
+ // To avoid cycles, use a "weak" raw pointer for the parent link
+ EnhancedTreeNode* mParent;
+ list_type mChildren;
+public:
+ /*----- End of TreeNode; what follows is new with EnhancedTreeNode -----*/
+
+ /**
+ * Because the type of the iterator range returned by getRootRange()
+ * depends on the discriminator enum value, instead of a simple typedef we
+ * use a templated struct. Example usage:
+ *
+ * @code
+ * for (EnhancedTreeNode::root_range<LLTreeIter::UP>::type range =
+ * somenode->getRootRange<LLTreeIter::UP>();
+ * range.first != range.second; ++range.first)
+ * {
+ * std::cout << (*range.first)->name() << '\n';
+ * }
+ * @endcode
+ */
+ template <LLTreeIter::RootIter DISCRIM>
+ struct root_range
+ {
+ typedef boost::iterator_range< LLTreeRootIter<DISCRIM, EnhancedTreeNode> > type;
+ };
+
+ /**
+ * Helper method for walking up to (or down from) the tree root. See
+ * LLTreeIter::RootIter.
+ *
+ * Example usage:
+ * @code
+ * BOOST_FOREACH(EnhancedTreeNodePtr node, somenode->getRootRange<LLTreeIter::UP>())
+ * {
+ * std::cout << node->name() << '\n';
+ * }
+ * @endcode
+ */
+ template <LLTreeIter::RootIter DISCRIM>
+ typename root_range<DISCRIM>::type getRootRange() const
+ {
+ typedef typename root_range<DISCRIM>::type range_type;
+ typedef typename range_type::iterator iter_type;
+ return range_type(iter_type(const_cast<EnhancedTreeNode*>(this),
+ boost::bind(&EnhancedTreeNode::getParent, _1)),
+ iter_type());
+ }
+
+ /**
+ * Because the type of the iterator range returned by getWalkRange()
+ * depends on the discriminator enum value, instead of a simple typedef we
+ * use a templated stuct. Example usage:
+ *
+ * @code
+ * for (EnhancedTreeNode::walk_range<LLTreeIter::DFS_PRE>::type range =
+ * somenode->getWalkRange<LLTreeIter::DFS_PRE>();
+ * range.first != range.second; ++range.first)
+ * {
+ * std::cout << (*range.first)->name() << '\n';
+ * }
+ * @endcode
+ */
+ template <LLTreeIter::WalkIter DISCRIM>
+ struct walk_range
+ {
+ typedef boost::iterator_range< LLTreeWalkIter<DISCRIM,
+ EnhancedTreeNode,
+ EnhancedTreeNode::child_iterator> > type;
+ };
+
+ /**
+ * Helper method for walking a given node's subtree in any supported
+ * order (see LLTreeIter::WalkIter).
+ *
+ * Example usage:
+ * @code
+ * BOOST_FOREACH(EnhancedTreeNodePtr node, somenode->getWalkRange<LLTreeIter::DFS_PRE>())
+ * {
+ * std::cout << node->name() << '\n';
+ * }
+ * @endcode
+ */
+ template <LLTreeIter::WalkIter DISCRIM>
+ typename walk_range<DISCRIM>::type getWalkRange() const
+ {
+ typedef typename walk_range<DISCRIM>::type range_type;
+ typedef typename range_type::iterator iter_type;
+ return range_type(iter_type(const_cast<EnhancedTreeNode*>(this),
+ boost::bind(&EnhancedTreeNode::child_begin, _1),
+ boost::bind(&EnhancedTreeNode::child_end, _1)),
+ iter_type());
+ }
+};
+
+/*****************************************************************************
+* PlainTree
+*****************************************************************************/
+struct PlainTree
+{
+ PlainTree(const std::string& name, PlainTree* parent=0):
+ mName(name),
+ mParent(parent),
+ mNextSibling(0),
+ mFirstChild(0)
+ {
+ mLastChildLink = &mFirstChild;
+ }
+ ~PlainTree()
+ {
+ delete mNextSibling;
+ delete mFirstChild;
+ }
+ PlainTree* newChild(const std::string& name)
+ {
+ PlainTree* child(new PlainTree(name, this));
+ *mLastChildLink = child;
+ mLastChildLink = &child->mNextSibling;
+ return child;
+ }
+ std::string name() const { return mName; }
+
+ std::string mName;
+ PlainTree* mParent;
+ PlainTree* mNextSibling;
+ PlainTree* mFirstChild;
+ PlainTree** mLastChildLink;
+};
+
+// This "classic" tree tracks each node's children with a linked list anchored
+// at the parent's mFirstChild and linked through each child's mNextSibling.
+// LLTreeDFSIter<> and LLTreeBFSIter<> need functors to return begin()/end()
+// iterators over a given node's children. But because this tree's children
+// aren't stored in an STL container, we can't just export that container's
+// begin()/end(). Instead we'll use LLLinkedIter<> to view the hand-maintained
+// linked list as an iterator range. The straightforward way to do that would
+// be to add child_begin() and child_end() methods. But let's say (for the
+// sake of argument) that this struct is so venerable we don't dare modify it
+// even to add new methods. Well, we can use free functions (or functors) too.
+LLLinkedIter<PlainTree> PlainTree_child_begin(PlainTree* node)
+{
+ return LLLinkedIter<PlainTree>(node->mFirstChild, boost::bind(&PlainTree::mNextSibling, _1));
+}
+
+LLLinkedIter<PlainTree> PlainTree_child_end(PlainTree* node)
+{
+ return LLLinkedIter<PlainTree>();
+}
+
+/**
+ * This is an example of a helper function to facilitate iterating from a
+ * PlainTree up to the root or down from the root (see LLTreeIter::RootIter).
+ * Note that we're simply overloading the same getRootRange() helper function
+ * name we used for TreeNode.
+ *
+ * Example:
+ * @code
+ * BOOST_FOREACH(PlainTree* node, getRootRange<LLTreeIter::UP>(somenode))
+ * {
+ * std::cout << node->name() << '\n';
+ * }
+ * @endcode
+ */
+template <LLTreeIter::RootIter DISCRIM>
+boost::iterator_range< LLTreeRootIter<DISCRIM, PlainTree> >
+getRootRange(PlainTree* node)
+{
+ typedef LLTreeRootIter<DISCRIM, PlainTree> iter_type;
+ typedef boost::iterator_range<iter_type> range_type;
+ return range_type(iter_type(node, boost::bind(&PlainTree::mParent, _1)),
+ iter_type());
+}
+
+/**
+ * This is an example of a helper function to facilitate walking a given
+ * PlainTree's subtree in any supported order (see LLTreeIter::WalkIter). Note
+ * that we're simply overloading the same getWalkRange() helper function name
+ * we used for TreeNode.
+ *
+ * Example:
+ * @code
+ * BOOST_FOREACH(PlainTree* node, getWalkRange<LLTreeIter::DFS_PRE>(root))
+ * {
+ * std::cout << node->name() << '\n';
+ * }
+ * @endcode
+ */
+template <LLTreeIter::WalkIter DISCRIM>
+boost::iterator_range< LLTreeWalkIter<DISCRIM, PlainTree, LLLinkedIter<PlainTree> > >
+getWalkRange(PlainTree* node)
+{
+ typedef LLTreeWalkIter<DISCRIM, PlainTree, LLLinkedIter<PlainTree> > iter_type;
+ typedef boost::iterator_range<iter_type> range_type;
+ return range_type(iter_type(node,
+ PlainTree_child_begin,
+ PlainTree_child_end),
+ iter_type());
+}
+
+// We could go through the exercise of writing EnhancedPlainTree containing
+// root_range, getRootRange(), walk_range and getWalkRange() members -- but we
+// won't. See EnhancedTreeNode for examples.
+
+/*****************************************************************************
+* Generic tree test data
+*****************************************************************************/
+template <class NODE>
+typename LLPtrTo<NODE>::type example_tree()
+{
+ typedef typename LLPtrTo<NODE>::type NodePtr;
+ NodePtr root(new NODE("root"));
+ NodePtr A(root->newChild("A"));
+ NodePtr A1(A->newChild("A1"));
+/* NodePtr A1a*/(A1->newChild("A1a"));
+/* NodePtr A1b*/(A1->newChild("A1b"));
+/* NodePtr A1c*/(A1->newChild("A1c"));
+ NodePtr A2(A->newChild("A2"));
+/* NodePtr A2a*/(A2->newChild("A2a"));
+/* NodePtr A2b*/(A2->newChild("A2b"));
+/* NodePtr A2c*/(A2->newChild("A2c"));
+ NodePtr A3(A->newChild("A3"));
+/* NodePtr A3a*/(A3->newChild("A3a"));
+/* NodePtr A3b*/(A3->newChild("A3b"));
+/* NodePtr A3c*/(A3->newChild("A3c"));
+ NodePtr B(root->newChild("B"));
+ NodePtr B1(B->newChild("B1"));
+/* NodePtr B1a*/(B1->newChild("B1a"));
+/* NodePtr B1b*/(B1->newChild("B1b"));
+/* NodePtr B1c*/(B1->newChild("B1c"));
+ NodePtr B2(B->newChild("B2"));
+/* NodePtr B2a*/(B2->newChild("B2a"));
+/* NodePtr B2b*/(B2->newChild("B2b"));
+/* NodePtr B2c*/(B2->newChild("B2c"));
+ NodePtr B3(B->newChild("B3"));
+/* NodePtr B3a*/(B3->newChild("B3a"));
+/* NodePtr B3b*/(B3->newChild("B3b"));
+/* NodePtr B3c*/(B3->newChild("B3c"));
+ NodePtr C(root->newChild("C"));
+ NodePtr C1(C->newChild("C1"));
+/* NodePtr C1a*/(C1->newChild("C1a"));
+/* NodePtr C1b*/(C1->newChild("C1b"));
+/* NodePtr C1c*/(C1->newChild("C1c"));
+ NodePtr C2(C->newChild("C2"));
+/* NodePtr C2a*/(C2->newChild("C2a"));
+/* NodePtr C2b*/(C2->newChild("C2b"));
+/* NodePtr C2c*/(C2->newChild("C2c"));
+ NodePtr C3(C->newChild("C3"));
+/* NodePtr C3a*/(C3->newChild("C3a"));
+/* NodePtr C3b*/(C3->newChild("C3b"));
+/* NodePtr C3c*/(C3->newChild("C3c"));
+ return root;
+}
+
+// WalkExpected<WalkIter> is the list of string node names we expect from a
+// WalkIter traversal of our example_tree() data.
+template <LLTreeIter::WalkIter DISCRIM>
+struct WalkExpected: public Expected
+{
+ // Initialize with bad_strings: we don't expect to use this generic case,
+ // only the specializations. Note that for a classic C-style array we must
+ // pass a pair of iterators rather than extracting boost::begin() and
+ // boost::end() within the target constructor: a template ctor accepts
+ // these classic C-style arrays as char** rather than char*[length]. Oh well.
+ WalkExpected(): Expected(boost::begin(bad_strings), boost::end(bad_strings)) {}
+};
+
+// list of string node names we expect from traversing example_tree() in
+// DFS_PRE order
+const char* dfs_pre_strings[] =
+{
+ "root",
+ "A",
+ "A1",
+ "A1a",
+ "A1b",
+ "A1c",
+ "A2",
+ "A2a",
+ "A2b",
+ "A2c",
+ "A3",
+ "A3a",
+ "A3b",
+ "A3c",
+ "B",
+ "B1",
+ "B1a",
+ "B1b",
+ "B1c",
+ "B2",
+ "B2a",
+ "B2b",
+ "B2c",
+ "B3",
+ "B3a",
+ "B3b",
+ "B3c",
+ "C",
+ "C1",
+ "C1a",
+ "C1b",
+ "C1c",
+ "C2",
+ "C2a",
+ "C2b",
+ "C2c",
+ "C3",
+ "C3a",
+ "C3b",
+ "C3c"
+};
+
+// specialize WalkExpected<DFS_PRE> with the expected strings
+template <>
+struct WalkExpected<LLTreeIter::DFS_PRE>: public Expected
+{
+ WalkExpected(): Expected(boost::begin(dfs_pre_strings), boost::end(dfs_pre_strings)) {}
+};
+
+// list of string node names we expect from traversing example_tree() in
+// DFS_POST order
+const char* dfs_post_strings[] =
+{
+ "A1a",
+ "A1b",
+ "A1c",
+ "A1",
+ "A2a",
+ "A2b",
+ "A2c",
+ "A2",
+ "A3a",
+ "A3b",
+ "A3c",
+ "A3",
+ "A",
+ "B1a",
+ "B1b",
+ "B1c",
+ "B1",
+ "B2a",
+ "B2b",
+ "B2c",
+ "B2",
+ "B3a",
+ "B3b",
+ "B3c",
+ "B3",
+ "B",
+ "C1a",
+ "C1b",
+ "C1c",
+ "C1",
+ "C2a",
+ "C2b",
+ "C2c",
+ "C2",
+ "C3a",
+ "C3b",
+ "C3c",
+ "C3",
+ "C",
+ "root"
+};
+
+// specialize WalkExpected<DFS_POST> with the expected strings
+template <>
+struct WalkExpected<LLTreeIter::DFS_POST>: public Expected
+{
+ WalkExpected(): Expected(boost::begin(dfs_post_strings), boost::end(dfs_post_strings)) {}
+};
+
+// list of string node names we expect from traversing example_tree() in BFS order
+const char* bfs_strings[] =
+{
+ "root",
+ "A",
+ "B",
+ "C",
+ "A1",
+ "A2",
+ "A3",
+ "B1",
+ "B2",
+ "B3",
+ "C1",
+ "C2",
+ "C3",
+ "A1a",
+ "A1b",
+ "A1c",
+ "A2a",
+ "A2b",
+ "A2c",
+ "A3a",
+ "A3b",
+ "A3c",
+ "B1a",
+ "B1b",
+ "B1c",
+ "B2a",
+ "B2b",
+ "B2c",
+ "B3a",
+ "B3b",
+ "B3c",
+ "C1a",
+ "C1b",
+ "C1c",
+ "C2a",
+ "C2b",
+ "C2c",
+ "C3a",
+ "C3b",
+ "C3c"
+};
+
+// specialize WalkExpected<BFS> with the expected strings
+template <>
+struct WalkExpected<LLTreeIter::BFS>: public Expected
+{
+ WalkExpected(): Expected(boost::begin(bfs_strings), boost::end(bfs_strings)) {}
+};
+
+// extract a particular "arbitrary" node from the example_tree() data: the
+// second (middle) node at each child level
+template <class NODE, typename CHILDITER>
+typename LLPtrTo<NODE>::type
+get_B2b(const typename LLPtrTo<NODE>::type& root,
+ const boost::function<CHILDITER(const typename LLPtrTo<NODE>::type&)>& child_begin)
+{
+ typedef typename LLPtrTo<NODE>::type NodePtr;
+ CHILDITER Bi(child_begin(root));
+ ++Bi;
+ NodePtr B(*Bi);
+ CHILDITER B2i(child_begin(B));
+ ++B2i;
+ NodePtr B2(*B2i);
+ CHILDITER B2bi(child_begin(B2));
+ ++B2bi;
+ NodePtr B2b(*B2bi);
+ return B2b;
+}
+
+// RootExpected<RootIter> is the list of string node names we expect from a
+// RootIter traversal of our example_tree() data.
+template <LLTreeIter::RootIter DISCRIM>
+struct RootExpected: public Expected
+{
+ // Initialize with bad_strings: we don't expect to use this generic case,
+ // only the specializations.
+ RootExpected(): Expected(boost::begin(bad_strings), boost::end(bad_strings)) {}
+};
+
+// list of string node names we expect from traversing UP from
+// example_tree()'s B2b node
+const char* up_from_B2b[] =
+{
+ "B2b",
+ "B2",
+ "B",
+ "root"
+};
+
+// specialize RootExpected<UP> with the expected strings
+template <>
+struct RootExpected<LLTreeIter::UP>: public Expected
+{
+ RootExpected(): Expected(boost::begin(up_from_B2b), boost::end(up_from_B2b)) {}
+};
+
+// list of string node names we expect from traversing DOWN to
+// example_tree()'s B2b node
+const char* down_to_B2b[] =
+{
+ "root",
+ "B",
+ "B2",
+ "B2b"
+};
+
+// specialize RootExpected<DOWN> with the expected strings
+template <>
+struct RootExpected<LLTreeIter::DOWN>: public Expected
+{
+ RootExpected(): Expected(boost::begin(down_to_B2b), boost::end(down_to_B2b)) {}
+};
+
+/*****************************************************************************
+* Generic tree test functions
+*****************************************************************************/
+template<LLTreeIter::RootIter DISCRIM, class NODE, typename PARENTFUNC>
+bool LLTreeRootIter_test(const std::string& itername, const std::string& nodename,
+ const typename LLPtrTo<NODE>::type& node,
+ PARENTFUNC parentfunc)
+{
+ std::ostringstream desc;
+ desc << itername << '<' << nodename << "> from " << node->name();
+ if (! verify(desc.str(),
+ boost::make_iterator_range(LLTreeRootIter<DISCRIM, NODE>(node, parentfunc),
+ LLTreeRootIter<DISCRIM, NODE>()),
+ RootExpected<DISCRIM>()))
+ return false;
+// std::cout << desc.str() << '\n';
+ // Try instantiating an iterator with NULL (that is, a default-constructed
+ // node pointer). This test is less about "did we iterate once?" than "did
+ // we avoid blowing up?"
+ for (LLTreeRootIter<DISCRIM, NODE> hri = LLTreeRootIter<DISCRIM, NODE>(typename LLPtrTo<NODE>::type(), parentfunc), hrend;
+ hri != hrend; /* ++hri */) // incrementing is moot, and MSVC complains
+ {
+// std::cout << nodename << '(' << (*hri)->name() << ")\n";
+ std::cout << itername << '<' << nodename << ">(NULL)\n";
+ return false;
+ }
+ return true;
+}
+
+template<class NODE, typename CHILDITER, typename PARENTFUNC, typename CHILDFUNC>
+bool LLTreeUpIter_test(const std::string& nodename, PARENTFUNC parentfunc, CHILDFUNC childfunc)
+{
+ bool success = true;
+ typedef typename LLPtrTo<NODE>::type ptr_type;
+ ptr_type root(example_tree<NODE>());
+ Cleanup<ptr_type> cleanup(root);
+ ptr_type B2b(get_B2b<NODE, CHILDITER>(root, childfunc));
+ if (! LLTreeRootIter_test<LLTreeIter::UP, NODE>("LLTreeUpIter", nodename, B2b, parentfunc))
+ success = false;
+ if (! LLTreeRootIter_test<LLTreeIter::DOWN, NODE>("LLTreeDownIter", nodename, B2b, parentfunc))
+ success = false;
+ return success;
+}
+
+template <LLTreeIter::WalkIter DISCRIM, class NODE, typename CHILDITER,
+ typename CHILDBEGINFUNC, typename CHILDENDFUNC>
+bool LLTreeWalkIter_test(const std::string& itername, const std::string& nodename,
+ CHILDBEGINFUNC childbegin, CHILDENDFUNC childend)
+{
+ typename LLPtrTo<NODE>::type root(example_tree<NODE>());
+ Cleanup<typename LLPtrTo<NODE>::type> cleanup(root);
+ std::ostringstream desc;
+ desc << itername << '<' << nodename << "> from " << root->name();
+ if (! verify(desc.str(),
+ boost::make_iterator_range(LLTreeWalkIter<DISCRIM, NODE, CHILDITER>(root,
+ childbegin,
+ childend),
+ LLTreeWalkIter<DISCRIM, NODE, CHILDITER>()),
+ WalkExpected<DISCRIM>()))
+ return false;
+ // Try instantiating an iterator with NULL (that is, a default-constructed
+ // node pointer). This test is less about "did we iterate once?" than "did
+ // we avoid blowing up?"
+ for (LLTreeWalkIter<DISCRIM, NODE, CHILDITER> twi = LLTreeWalkIter<DISCRIM, NODE, CHILDITER>(typename LLPtrTo<NODE>::type(),
+ childbegin,
+ childend),
+ twend;
+ twi != twend; /* ++twi */) // incrementing is moot, and MSVC complains
+ {
+ std::cout << itername << '<' << nodename << ">(NULL)\n";
+ return false;
+ }
+ return true;
+}
+
+template <class NODE, typename CHILDITER,
+ typename PARENTFUNC, typename CHILDBEGINFUNC, typename CHILDENDFUNC>
+bool LLTreeIter_tests(const std::string& nodename,
+ PARENTFUNC parentfunc, CHILDBEGINFUNC childbegin, CHILDENDFUNC childend)
+{
+ bool success = true;
+ if (! LLTreeUpIter_test<NODE, CHILDITER>(nodename, parentfunc, childbegin))
+ success = false;
+/*==========================================================================*|
+ LLTreeIter_test<NODE, LLTreeDFSIter<NODE, CHILDITER> >("LLTreeDFSIter", nodename,
+ childbegin, childend);
+ LLTreeIter_test<NODE, LLTreeDFSPostIter<NODE, CHILDITER> >("LLTreeDFSPostIter", nodename,
+ childbegin, childend);
+ LLTreeIter_test<NODE, LLTreeBFSIter<NODE, CHILDITER> >("LLTreeBFSIter", nodename,
+ childbegin, childend);
+|*==========================================================================*/
+ if (! LLTreeWalkIter_test<LLTreeIter::DFS_PRE, NODE, CHILDITER>("LLTreeDFSIter", nodename,
+ childbegin, childend))
+ success = false;
+ if (! LLTreeWalkIter_test<LLTreeIter::DFS_POST, NODE, CHILDITER>("LLTreeDFSPostIter", nodename,
+ childbegin, childend))
+ success = false;
+ if (! LLTreeWalkIter_test<LLTreeIter::BFS, NODE, CHILDITER>("LLTreeBFSIter", nodename,
+ childbegin, childend))
+ success = false;
+ return success;
+}
+
+namespace tut
+{
+ template<> template<>
+ void iter_object::test<3>()
+ {
+// set_test_name("LLTreeIter tests");
+ ensure(LLTreeIter_tests<TreeNode, TreeNode::child_iterator>
+ ("TreeNode",
+ boost::bind(&TreeNode::getParent, _1),
+ boost::bind(&TreeNode::child_begin, _1),
+ boost::bind(&TreeNode::child_end, _1)));
+ ensure(LLTreeIter_tests<PlainTree, LLLinkedIter<PlainTree> >
+ ("PlainTree",
+ boost::bind(&PlainTree::mParent, _1),
+ PlainTree_child_begin,
+ PlainTree_child_end));
+ }
+
+ template<> template<>
+ void iter_object::test<4>()
+ {
+// set_test_name("getRootRange() tests");
+ // This test function illustrates the looping techniques described in the
+ // comments for the getRootRange() free function, the
+ // EnhancedTreeNode::root_range template and the
+ // EnhancedTreeNode::getRootRange() method. Obviously the BOOST_FOREACH()
+ // forms are more succinct.
+ TreeNodePtr tnroot(example_tree<TreeNode>());
+ TreeNodePtr tnB2b(get_B2b<TreeNode, TreeNode::child_iterator>
+ (tnroot, boost::bind(&TreeNode::child_begin, _1)));
+
+ std::string desc1("BOOST_FOREACH(TreeNodePr, getRootRange<LLTreeIter::UP>(tnB2b))");
+// std::cout << desc1 << "\n";
+ // Although we've commented out the output statement, ensure that the
+ // loop construct is still valid, as promised by the getRootRange()
+ // documentation.
+ BOOST_FOREACH(TreeNodePtr node, getRootRange<LLTreeIter::UP>(tnB2b))
+ {
+// std::cout << node->name() << '\n';
+ }
+ ensure(desc1,
+ verify(desc1, getRootRange<LLTreeIter::UP>(tnB2b), RootExpected<LLTreeIter::UP>()));
+
+ EnhancedTreeNodePtr etnroot(example_tree<EnhancedTreeNode>());
+ EnhancedTreeNodePtr etnB2b(get_B2b<EnhancedTreeNode, EnhancedTreeNode::child_iterator>
+ (etnroot, boost::bind(&EnhancedTreeNode::child_begin, _1)));
+
+// std::cout << "EnhancedTreeNode::root_range<LLTreeIter::DOWN>::type range =\n"
+// << " etnB2b->getRootRange<LLTreeIter::DOWN>();\n"
+// << "for (EnhancedTreeNode::root_range<LLTreeIter::DOWN>::type::iterator ri = range.begin();\n"
+// << " ri != range.end(); ++ri)\n";
+ EnhancedTreeNode::root_range<LLTreeIter::DOWN>::type range =
+ etnB2b->getRootRange<LLTreeIter::DOWN>();
+ for (EnhancedTreeNode::root_range<LLTreeIter::DOWN>::type::iterator ri = range.begin();
+ ri != range.end(); ++ri)
+ {
+// std::cout << (*ri)->name() << '\n';
+ }
+
+ std::string desc2("BOOST_FOREACH(EnhancedTreeNodePtr node, etnB2b->getRootRange<LLTreeIter::UP>())");
+// std::cout << desc2 << '\n';
+ BOOST_FOREACH(EnhancedTreeNodePtr node, etnB2b->getRootRange<LLTreeIter::UP>())
+ {
+// std::cout << node->name() << '\n';
+ }
+ ensure(desc2,
+ verify(desc2, etnB2b->getRootRange<LLTreeIter::UP>(), RootExpected<LLTreeIter::UP>()));
+ }
+
+ template<> template<>
+ void iter_object::test<5>()
+ {
+// set_test_name("getWalkRange() tests");
+ // This test function doesn't illustrate the looping permutations for
+ // getWalkRange(); see getRootRange_tests() for such examples. This
+ // function simply verifies that they all work.
+
+ // TreeNode, using helper function
+ TreeNodePtr tnroot(example_tree<TreeNode>());
+ std::string desc_tnpre("getWalkRange<LLTreeIter::DFS_PRE>(tnroot)");
+ ensure(desc_tnpre,
+ verify(desc_tnpre,
+ getWalkRange<LLTreeIter::DFS_PRE>(tnroot),
+ WalkExpected<LLTreeIter::DFS_PRE>()));
+ std::string desc_tnpost("getWalkRange<LLTreeIter::DFS_POST>(tnroot)");
+ ensure(desc_tnpost,
+ verify(desc_tnpost,
+ getWalkRange<LLTreeIter::DFS_POST>(tnroot),
+ WalkExpected<LLTreeIter::DFS_POST>()));
+ std::string desc_tnb("getWalkRange<LLTreeIter::BFS>(tnroot)");
+ ensure(desc_tnb,
+ verify(desc_tnb,
+ getWalkRange<LLTreeIter::BFS>(tnroot),
+ WalkExpected<LLTreeIter::BFS>()));
+
+ // EnhancedTreeNode, using method
+ EnhancedTreeNodePtr etnroot(example_tree<EnhancedTreeNode>());
+ std::string desc_etnpre("etnroot->getWalkRange<LLTreeIter::DFS_PRE>()");
+ ensure(desc_etnpre,
+ verify(desc_etnpre,
+ etnroot->getWalkRange<LLTreeIter::DFS_PRE>(),
+ WalkExpected<LLTreeIter::DFS_PRE>()));
+ std::string desc_etnpost("etnroot->getWalkRange<LLTreeIter::DFS_POST>()");
+ ensure(desc_etnpost,
+ verify(desc_etnpost,
+ etnroot->getWalkRange<LLTreeIter::DFS_POST>(),
+ WalkExpected<LLTreeIter::DFS_POST>()));
+ std::string desc_etnb("etnroot->getWalkRange<LLTreeIter::BFS>()");
+ ensure(desc_etnb,
+ verify(desc_etnb,
+ etnroot->getWalkRange<LLTreeIter::BFS>(),
+ WalkExpected<LLTreeIter::BFS>()));
+
+ // PlainTree, using helper function
+ PlainTree* ptroot(example_tree<PlainTree>());
+ Cleanup<PlainTree*> cleanup(ptroot);
+ std::string desc_ptpre("getWalkRange<LLTreeIter::DFS_PRE>(ptroot)");
+ ensure(desc_ptpre,
+ verify(desc_ptpre,
+ getWalkRange<LLTreeIter::DFS_PRE>(ptroot),
+ WalkExpected<LLTreeIter::DFS_PRE>()));
+ std::string desc_ptpost("getWalkRange<LLTreeIter::DFS_POST>(ptroot)");
+ ensure(desc_ptpost,
+ verify(desc_ptpost,
+ getWalkRange<LLTreeIter::DFS_POST>(ptroot),
+ WalkExpected<LLTreeIter::DFS_POST>()));
+ std::string desc_ptb("getWalkRange<LLTreeIter::BFS>(ptroot)");
+ ensure(desc_ptb,
+ verify(desc_ptb,
+ getWalkRange<LLTreeIter::BFS>(ptroot),
+ WalkExpected<LLTreeIter::BFS>()));
+ }
+} // tut
diff --git a/indra/llcommon/tests/lluri_test.cpp b/indra/llcommon/tests/lluri_test.cpp
new file mode 100644
index 0000000000..0a7c37d4b9
--- /dev/null
+++ b/indra/llcommon/tests/lluri_test.cpp
@@ -0,0 +1,370 @@
+/**
+ * @file lluri_test.cpp
+ * @brief LLURI unit tests
+ * @date September 2006
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ *
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../llsd.h"
+#include "../lluri.h"
+
+#include "../test/lltut.h"
+
+namespace tut
+{
+ struct URITestData {
+ void checkParts(const LLURI& u,
+ const char* expectedScheme,
+ const char* expectedOpaque,
+ const char* expectedAuthority,
+ const char* expectedPath,
+ const char* expectedQuery = "")
+ {
+ ensure_equals("scheme", u.scheme(), expectedScheme);
+ ensure_equals("opaque", u.opaque(), expectedOpaque);
+ ensure_equals("authority", u.authority(), expectedAuthority);
+ ensure_equals("path", u.path(), expectedPath);
+ ensure_equals("query", u.query(), expectedQuery);
+ }
+
+ void escapeRoundTrip(const std::string& uri_raw_1)
+ {
+ std::string uri_esc_1(LLURI::escape(uri_raw_1));
+ std::string uri_raw_2(LLURI::unescape(uri_esc_1));
+ ensure_equals("escape/unescape raw", uri_raw_2, uri_raw_1);
+ std::string uri_esc_2(LLURI::escape(uri_raw_2));
+ ensure_equals("escape/unescape escaped", uri_esc_2, uri_esc_1);
+ }
+ };
+
+ typedef test_group<URITestData> URITestGroup;
+ typedef URITestGroup::object URITestObject;
+
+ URITestGroup uriTestGroup("LLURI");
+
+ template<> template<>
+ void URITestObject::test<1>()
+ {
+ LLURI u("http://abc.com/def/ghi?x=37&y=hello");
+
+ ensure_equals("scheme", u.scheme(), "http");
+ ensure_equals("authority", u.authority(), "abc.com");
+ ensure_equals("path", u.path(), "/def/ghi");
+ ensure_equals("query", u.query(), "x=37&y=hello");
+
+ ensure_equals("host name", u.hostName(), "abc.com");
+ ensure_equals("host port", u.hostPort(), 80);
+
+ LLSD query = u.queryMap();
+ ensure_equals("query x", query["x"].asInteger(), 37);
+ ensure_equals("query y", query["y"].asString(), "hello");
+
+ query = LLURI::queryMap("x=22.23&y=https://lindenlab.com/");
+ ensure_equals("query x", query["x"].asReal(), 22.23);
+ ensure_equals("query y", query["y"].asURI().asString(), "https://lindenlab.com/");
+ }
+
+ template<> template<>
+ void URITestObject::test<2>()
+ {
+ // empty string
+ checkParts(LLURI(""), "", "", "", "");
+ }
+
+ template<> template<>
+ void URITestObject::test<3>()
+ {
+ // no scheme
+ checkParts(LLURI("foo"), "", "foo", "", "");
+ checkParts(LLURI("foo%3A"), "", "foo:", "", "");
+ }
+
+ template<> template<>
+ void URITestObject::test<4>()
+ {
+ // scheme w/o paths
+ checkParts(LLURI("mailto:zero@ll.com"),
+ "mailto", "zero@ll.com", "", "");
+ checkParts(LLURI("silly://abc/def?foo"),
+ "silly", "//abc/def?foo", "", "");
+ }
+
+ template<> template<>
+ void URITestObject::test<5>()
+ {
+ // authority section
+ checkParts(LLURI("http:///"),
+ "http", "///", "", "/");
+
+ checkParts(LLURI("http://abc"),
+ "http", "//abc", "abc", "");
+
+ checkParts(LLURI("http://a%2Fb/cd"),
+ "http", "//a/b/cd", "a/b", "/cd");
+
+ checkParts(LLURI("http://host?"),
+ "http", "//host?", "host", "");
+ }
+
+ template<> template<>
+ void URITestObject::test<6>()
+ {
+ // path section
+ checkParts(LLURI("http://host/a/b/"),
+ "http", "//host/a/b/", "host", "/a/b/");
+
+ checkParts(LLURI("http://host/a%3Fb/"),
+ "http", "//host/a?b/", "host", "/a?b/");
+
+ checkParts(LLURI("http://host/a:b/"),
+ "http", "//host/a:b/", "host", "/a:b/");
+ }
+
+ template<> template<>
+ void URITestObject::test<7>()
+ {
+ // query string
+ checkParts(LLURI("http://host/?"),
+ "http", "//host/?", "host", "/", "");
+
+ checkParts(LLURI("http://host/?x"),
+ "http", "//host/?x", "host", "/", "x");
+
+ checkParts(LLURI("http://host/??"),
+ "http", "//host/??", "host", "/", "?");
+
+ checkParts(LLURI("http://host/?%3F"),
+ "http", "//host/??", "host", "/", "?");
+ }
+
+ template<> template<>
+ void URITestObject::test<8>()
+ {
+ LLSD path;
+ path.append("x");
+ path.append("123");
+ checkParts(LLURI::buildHTTP("host", path),
+ "http", "//host/x/123", "host", "/x/123");
+
+ LLSD query;
+ query["123"] = "12";
+ query["abcd"] = "abc";
+ checkParts(LLURI::buildHTTP("host", path, query),
+ "http", "//host/x/123?123=12&abcd=abc",
+ "host", "/x/123", "123=12&abcd=abc");
+ }
+
+ template<> template<>
+ void URITestObject::test<9>()
+ {
+ // test unescaped path components
+ LLSD path;
+ path.append("x@*//*$&^");
+ path.append("123");
+ checkParts(LLURI::buildHTTP("host", path),
+ "http", "//host/x@*//*$&^/123", "host", "/x@*//*$&^/123");
+ }
+
+ template<> template<>
+ void URITestObject::test<10>()
+ {
+ // test unescaped query components
+ LLSD path;
+ path.append("x");
+ path.append("123");
+ LLSD query;
+ query["123"] = "?&*#//";
+ query["**@&?//"] = "abc";
+ checkParts(LLURI::buildHTTP("host", path, query),
+ "http", "//host/x/123?**@&?//=abc&123=?&*#//",
+ "host", "/x/123", "**@&?//=abc&123=?&*#//");
+ }
+
+ template<> template<>
+ void URITestObject::test<11>()
+ {
+ // test unescaped host components
+ LLSD path;
+ path.append("x");
+ path.append("123");
+ LLSD query;
+ query["123"] = "12";
+ query["abcd"] = "abc";
+ checkParts(LLURI::buildHTTP("hi123*33--}{:portstuffs", path, query),
+ "http", "//hi123*33--}{:portstuffs/x/123?123=12&abcd=abc",
+ "hi123*33--}{:portstuffs", "/x/123", "123=12&abcd=abc");
+ }
+
+ template<> template<>
+ void URITestObject::test<12>()
+ {
+ // test funky host_port values that are actually prefixes
+
+ checkParts(LLURI::buildHTTP("http://example.com:8080", LLSD()),
+ "http", "//example.com:8080",
+ "example.com:8080", "");
+
+ checkParts(LLURI::buildHTTP("http://example.com:8080/", LLSD()),
+ "http", "//example.com:8080/",
+ "example.com:8080", "/");
+
+ checkParts(LLURI::buildHTTP("http://example.com:8080/a/b", LLSD()),
+ "http", "//example.com:8080/a/b",
+ "example.com:8080", "/a/b");
+ }
+
+ template<> template<>
+ void URITestObject::test<13>()
+ {
+ const std::string unreserved =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "-._~";
+ // test escape
+ ensure_equals("escaping", LLURI::escape("abcdefg", "abcdef"), "abcdef%67");
+ ensure_equals("escaping", LLURI::escape("|/&\\+-_!@", ""), "%7C%2F%26%5C%2B%2D%5F%21%40");
+ ensure_equals("escaping as query variable",
+ LLURI::escape("http://10.0.1.4:12032/agent/god/agent-id/map/layer/?resume=http://station3.ll.com:12032/agent/203ad6df-b522-491d-ba48-4e24eb57aeff/send-postcard", unreserved + ":@!$'()*+,="),
+ "http:%2F%2F10.0.1.4:12032%2Fagent%2Fgod%2Fagent-id%2Fmap%2Flayer%2F%3Fresume=http:%2F%2Fstation3.ll.com:12032%2Fagent%2F203ad6df-b522-491d-ba48-4e24eb57aeff%2Fsend-postcard");
+ // French cedilla (C with squiggle, like in the word Francais) is UTF-8 C3 A7
+
+#if LL_WINDOWS
+#pragma warning(disable: 4309)
+#endif
+
+ std::string cedilla;
+ cedilla.push_back( (char)0xC3 );
+ cedilla.push_back( (char)0xA7 );
+ ensure_equals("escape UTF8", LLURI::escape( cedilla, unreserved), "%C3%A7");
+ }
+
+
+ template<> template<>
+ void URITestObject::test<14>()
+ {
+ // make sure escape and unescape of empty strings return empty
+ // strings.
+ std::string uri_esc(LLURI::escape(""));
+ ensure("escape string empty", uri_esc.empty());
+ std::string uri_raw(LLURI::unescape(""));
+ ensure("unescape string empty", uri_raw.empty());
+ }
+
+ template<> template<>
+ void URITestObject::test<15>()
+ {
+ // do some round-trip tests
+ escapeRoundTrip("http://secondlife.com");
+ escapeRoundTrip("http://secondlife.com/url with spaces");
+ escapeRoundTrip("http://bad[domain]name.com/");
+ escapeRoundTrip("ftp://bill.gates@ms/micro$oft.com/c:\\autoexec.bat");
+ escapeRoundTrip("");
+ }
+
+ template<> template<>
+ void URITestObject::test<16>()
+ {
+ // Test the default escaping
+ // yes -- this mangles the url. This is expected behavior
+ std::string simple("http://secondlife.com");
+ ensure_equals(
+ "simple http",
+ LLURI::escape(simple),
+ "http%3A%2F%2Fsecondlife.com");
+ ensure_equals(
+ "needs escape",
+ LLURI::escape("http://get.secondlife.com/windows viewer"),
+ "http%3A%2F%2Fget.secondlife.com%2Fwindows%20viewer");
+ }
+
+ template<> template<>
+ void URITestObject::test<17>()
+ {
+ // do some round-trip tests with very long strings.
+ escapeRoundTrip("Welcome to Second Life.We hope you'll have a richly rewarding experience, filled with creativity, self expression and fun.The goals of the Community Standards are simple: treat each other with respect and without harassment, adhere to local standards as indicated by simulator ratings, and refrain from any hate activity which slurs a real-world individual or real-world community. Behavioral Guidelines - The Big Six");
+ escapeRoundTrip(
+ "'asset_data':b(12100){'task_id':ucc706f2d-0b68-68f8-11a4-f1043ff35ca0}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444921\n\ttotal_crc\t323\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.368634403\t0.00781063363\t-0.569040775\n\toldpos\t150.117996\t25.8658009\t8.19664001\n\trotation\t-0.06293071806430816650390625\t-0.6995697021484375\t-0.7002241611480712890625\t0.1277817934751510620117188\n\tchildpos\t-0.00499999989\t-0.0359999985\t0.307999998\n\tchildrot\t-0.515492737293243408203125\t-0.46601200103759765625\t0.529055416584014892578125\t0.4870323240756988525390625\n\tscale"
+ "\t0.074629\t0.289956\t0.01\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t16\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\tscale_x\t1\n\t\t\tscale_y\t1\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t1\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tf"
+ "aces\t6\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204"
+ "\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t-1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061088050622956\n\treztime\t1094866329019785\n\tparceltime\t1133568981980596\n\ttax_rate\t1.00084\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':u61fa7364-e151-0597-774c-523312dae31b}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffff"
+ "ff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444922\n\ttotal_crc\t324\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.367110789\t0.00780026987\t-0.566269755\n\toldpos\t150.115005\t25.8479004\t8.18669987\n\trotation\t0.47332942485809326171875\t-0.380102097988128662109375\t-0.5734078884124755859375\t0.550168216228485107421875\n\tchildpos\t-0.00499999989\t-0.0370000005\t0.305000007\n\tchildrot\t-0.736649334430694580078125\t-0.03042060509324073791503906\t-0.02784589119255542755126953\t0.67501628398895263671875\n\tscale\t0.074629\t0.289956\t0.01\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t"
+ "0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t16\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\tscale_x\t1\n\t\t\tscale_y\t1\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t1\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t6\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t"
+ "\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t"
+ "\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t-1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087839248891\n\treztime\t1094866329020800\n\tparceltime\t1133568981981983\n\ttax_rate\t1.00084\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':ub8d68643-7dd8-57af-0d24-8790032aed0c}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreat"
+ "or_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444923\n\ttotal_crc\t235\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.120029509\t-0.00284469454\t-0.0302077383\n\toldpos\t150.710999\t25.8584995\t8.19172001\n\trotation\t0.145459949970245361328125\t-0.1646589934825897216796875\t0.659558117389678955078125\t-0.718826770782470703125\n\tchildpos\t0\t-0.182999998\t-0.26699999\n\tchildrot\t0.991444766521453857421875\t3.271923924330621957778931e-05\t-0.0002416197530692443251609802\t0.1305266767740249633789062\n\tscale\t0.0382982\t0.205957\t0.368276\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundra"
+ "dius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t32\n\t\t\tbegin\t0.3\n\t\t\tend\t0.65\n\t\t\tscale_x\t1\n\t\t\tscale_y\t0.05\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t0\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t3\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0"
+ "\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087534454174\n\treztime\t1094866329021741\n\tparceltime\t1133568981982889\n\ttax_rate\t1.00326\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':ue4b19200-9d33-962f-c8c5-6f"
+ "25be3a3fd0}\n{\n\tname\tApotheosis_Immolaine_tail|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444924\n\ttotal_crc\t675\n\ttype\t1\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.34780401\t-0.00968400016\t-0.260098994\n\toldpos\t0\t0\t0\n\trotation\t0.73164522647857666015625\t-0.67541944980621337890625\t-0.07733880728483200073242188\t0.05022468417882919311523438\n\tvelocity\t0\t0\t0\n\tangvel\t0\t0\t0\n\tscale\t0.0382982\t0.32228\t0.383834\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000"
+ "000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t32\n\t\t\tbegin\t0.3\n\t\t\tend\t0.65\n\t\t\tscale_x\t1\n\t\t\tscale_y\t0.05\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t0\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t3\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1"
+ ".57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087463950186\n\treztime\t1094866329022555\n\tparceltime\t1133568981984359\n\tdescription\t(No Description)|\n\ttax_rate\t1.01736\n\tnamevalue\tAttachPt U32 RW S 10\n\tnamevalue\tAttachmentOrientation VEC3 RW DS -3.110088, -0.182018, 1.493795\n\tnamevalue\tAttachmentOffset VEC3 RW DS -0.347804, -0.009684, -0.260099\n\tnamevalue\tAttachItemI"
+ "D STRING RW SV 20f36c3a-b44b-9bc7-87f3-018bfdfc8cda\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\torig_asset_id\t8747acbc-d391-1e59-69f1-41d06830e6c0\n\torig_item_id\t20f36c3a-b44b-9bc7-87f3-018bfdfc8cda\n\tfrom_task_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tlinked\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n");
+ }
+
+
+ template<> template<>
+ void URITestObject::test<18>()
+ {
+ LLURI u("secondlife:///app/login?first_name=Testert4&last_name=Tester&web_login_key=test");
+ // if secondlife is the scheme, LLURI should parse /app/login as path, with no authority
+ ensure_equals("scheme", u.scheme(), "secondlife");
+ ensure_equals("authority", u.authority(), "");
+ ensure_equals("path", u.path(), "/app/login");
+ ensure_equals("pathmap", u.pathArray()[0].asString(), "app");
+ ensure_equals("pathmap", u.pathArray()[1].asString(), "login");
+ ensure_equals("query", u.query(), "first_name=Testert4&last_name=Tester&web_login_key=test");
+ ensure_equals("query map element", u.queryMap()["last_name"].asString(), "Tester");
+
+ u = LLURI("secondlife://Da Boom/128/128/128");
+ // if secondlife is the scheme, LLURI should parse /128/128/128 as path, with Da Boom as authority
+ ensure_equals("scheme", u.scheme(), "secondlife");
+ ensure_equals("authority", u.authority(), "Da Boom");
+ ensure_equals("path", u.path(), "/128/128/128");
+ ensure_equals("pathmap", u.pathArray()[0].asString(), "128");
+ ensure_equals("pathmap", u.pathArray()[1].asString(), "128");
+ ensure_equals("pathmap", u.pathArray()[2].asString(), "128");
+ ensure_equals("query", u.query(), "");
+ }
+
+ template<> template<>
+ void URITestObject::test<19>()
+ {
+ // Parse about: schemes
+ LLURI u("about:blank?redirect-http-hack=secondlife%3A%2F%2F%2Fapp%2Flogin%3Ffirst_name%3DCallum%26last_name%3DLinden%26location%3Dspecify%26grid%3Dvaak%26region%3D%2FMorris%2F128%2F128%26web_login_key%3Defaa4795-c2aa-4c58-8966-763c27931e78");
+ ensure_equals("scheme", u.scheme(), "about");
+ ensure_equals("authority", u.authority(), "");
+ ensure_equals("path", u.path(), "blank");
+ ensure_equals("pathmap", u.pathArray()[0].asString(), "blank");
+ ensure_equals("query", u.query(), "redirect-http-hack=secondlife:///app/login?first_name=Callum&last_name=Linden&location=specify&grid=vaak&region=/Morris/128/128&web_login_key=efaa4795-c2aa-4c58-8966-763c27931e78");
+ ensure_equals("query map element", u.queryMap()["redirect-http-hack"].asString(), "secondlife:///app/login?first_name=Callum&last_name=Linden&location=specify&grid=vaak&region=/Morris/128/128&web_login_key=efaa4795-c2aa-4c58-8966-763c27931e78");
+ }
+}
+
+
diff --git a/indra/llcommon/tests/reflection_test.cpp b/indra/llcommon/tests/reflection_test.cpp
new file mode 100644
index 0000000000..5263e7fa64
--- /dev/null
+++ b/indra/llcommon/tests/reflection_test.cpp
@@ -0,0 +1,226 @@
+/**
+ * @file reflection_test.cpp
+ * @date May 2006
+ * @brief Reflection unit tests.
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ *
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "../linden_common.h"
+#include "../reflective.h"
+#include "../metaclasst.h"
+#include "../metapropertyt.h"
+#include "../stdtypes.h"
+
+#include "../test/lltut.h"
+
+namespace tut
+{
+ class TestAggregatedData : public LLReflective
+ {
+ public:
+ TestAggregatedData() {;}
+ virtual const LLMetaClass& getMetaClass() const;
+
+ private:
+ };
+
+ class TestReflectionData : public LLReflective
+ {
+ public:
+ TestReflectionData() : mInt(42), mString("foo"), mNullPtr(NULL), mPtr(new TestAggregatedData()), mRef(*(new TestAggregatedData)) {;}
+ virtual ~TestReflectionData() {delete mPtr;}
+ virtual const LLMetaClass& getMetaClass() const;
+
+ static U32 getPropertyCount() {return 5;}
+
+ private:
+
+ friend class LLMetaClassT<TestReflectionData>;
+ S32 mInt;
+ std::string mString;
+ TestAggregatedData* mNullPtr;
+ TestAggregatedData* mPtr;
+ TestAggregatedData mObj;
+ TestAggregatedData& mRef;
+ };
+}
+
+template <>
+void LLMetaClassT<tut::TestReflectionData>::reflectProperties(LLMetaClass& meta_class)
+{
+ reflectProperty(meta_class, "mInt", &tut::TestReflectionData::mInt);
+ reflectProperty(meta_class, "mString", &tut::TestReflectionData::mString);
+ reflectPtrProperty(meta_class, "mNullPtr", &tut::TestReflectionData::mNullPtr);
+ reflectPtrProperty(meta_class, "mPtr", &tut::TestReflectionData::mPtr);
+ reflectProperty(meta_class, "mObj", &tut::TestReflectionData::mObj);
+ //reflectProperty(meta_class, "mRef", &tut::TestReflectionData::mRef); // AARGH!
+}
+
+namespace tut
+{
+ // virtual
+ const LLMetaClass& TestReflectionData::getMetaClass() const
+ {
+ return LLMetaClassT<TestReflectionData>::instance();
+ }
+
+ const LLMetaClass& TestAggregatedData::getMetaClass() const
+ {
+ return LLMetaClassT<TestAggregatedData>::instance();
+ }
+}
+
+namespace tut
+{
+ typedef tut::test_group<TestReflectionData> TestReflectionGroup;
+ typedef TestReflectionGroup::object TestReflectionObject;
+ TestReflectionGroup gTestReflectionGroup("reflection");
+
+ template<> template<>
+ void TestReflectionObject::test<1>()
+ {
+ // Check properties can be found.
+ const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
+ const LLMetaProperty* null = NULL;
+ ensure_not_equals(meta_class.findProperty("mInt"), null);
+ ensure_not_equals(meta_class.findProperty("mString"), null);
+ }
+
+ template<> template<>
+ void TestReflectionObject::test<2>()
+ {
+ // Check non-existent property cannot be found.
+ const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
+ const LLMetaProperty* null = NULL;
+ ensure_equals(meta_class.findProperty("foo"), null);
+ }
+
+ template<> template<>
+ void TestReflectionObject::test<3>()
+ {
+ // Check integer property has correct value.
+ const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
+ ensure_equals(meta_class.findProperty("mInt")->getLLSD(this).asInteger(), 42);
+ }
+
+ template<> template<>
+ void TestReflectionObject::test<4>()
+ {
+ // Check string property has correct value.
+ const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
+ ensure_equals(meta_class.findProperty("mString")->getLLSD(this).asString(), std::string("foo"));
+ }
+
+ template<> template<>
+ void TestReflectionObject::test<5>()
+ {
+ // Check NULL reference property has correct value.
+ const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
+ const LLReflective* null = NULL;
+ ensure_equals(meta_class.findProperty("mNullPtr")->get(this), null);
+ }
+
+ template<> template<>
+ void TestReflectionObject::test<6>()
+ {
+ // Check reference property has correct value.
+ const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
+ const LLReflective* null = NULL;
+ const LLReflective* ref = meta_class.findProperty("mPtr")->get(this);
+ ensure_not_equals(ref, null);
+ }
+
+ template<> template<>
+ void TestReflectionObject::test<7>()
+ {
+ // Check reflective property has correct value.
+ const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
+ const LLReflective* null = NULL;
+ const LLReflective* ref = meta_class.findProperty("mObj")->get(this);
+ ensure_not_equals(ref, null);
+ }
+
+ template<> template<>
+ void TestReflectionObject::test<8>()
+ {
+ // Check property count.
+ const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
+ ensure_equals(meta_class.getPropertyCount(), TestReflectionData::getPropertyCount());
+ }
+
+ template<> template<>
+ void TestReflectionObject::test<9>()
+ {
+ // Check property iteration.
+ const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
+ U32 count = 0;
+ LLMetaClass::PropertyIterator iter;
+ for(iter = meta_class.beginProperties(); iter != meta_class.endProperties(); ++iter)
+ {
+ ++count;
+ }
+ ensure_equals(count, TestReflectionData::getPropertyCount());
+ }
+
+ template<> template<>
+ void TestReflectionObject::test<10>()
+ {
+ // Check meta classes of different types do not compare equal.
+ const LLMetaClass* reflection_data_meta_class = &(LLMetaClassT<TestReflectionData>::instance());
+ const LLMetaClass* aggregated_data_meta_class = &(LLMetaClassT<TestAggregatedData>::instance());
+ ensure_not_equals(reflection_data_meta_class, aggregated_data_meta_class);
+ }
+
+ template<> template<>
+ void TestReflectionObject::test<11>()
+ {
+ // Check class cast checks.
+ const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
+ TestAggregatedData* aggregated_data = new TestAggregatedData();
+ LLMetaClass::PropertyIterator iter;
+ U32 exception_count = 0;
+ for(iter = meta_class.beginProperties(); iter != meta_class.endProperties(); ++iter)
+ {
+ try
+ {
+ const LLMetaProperty* property = (*iter).second;
+ const LLReflective* reflective = property->get(aggregated_data); // Wrong reflective type, should throw exception.
+
+ // useless op to get rid of compiler warning.
+ reflective = NULL;
+ }
+ catch(...)
+ {
+ ++exception_count;
+ }
+ }
+ ensure_equals(exception_count, getPropertyCount());
+
+ }
+}
diff --git a/indra/llcommon/tests/stringize_test.cpp b/indra/llcommon/tests/stringize_test.cpp
new file mode 100644
index 0000000000..dd69787a1c
--- /dev/null
+++ b/indra/llcommon/tests/stringize_test.cpp
@@ -0,0 +1,110 @@
+/**
+ * @file stringize_test.cpp
+ * @author Nat Goodspeed
+ * @date 2008-09-12
+ * @brief Test of stringize.h
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+/*==========================================================================*|
+#if LL_WINDOWS
+#pragma warning (disable : 4675) // "resolved by ADL" -- just as I want!
+#endif
+|*==========================================================================*/
+
+// STL headers
+#include <iomanip>
+
+// Precompiled header
+#include "linden_common.h"
+
+// associated header
+#include "../stringize.h"
+
+// std headers
+// external library headers
+// other Linden headers
+#include "../llsd.h"
+
+#include "../test/lltut.h"
+
+namespace tut
+{
+ struct stringize_data
+ {
+ stringize_data():
+ c('c'),
+ s(17),
+ i(34),
+ l(68),
+ f(3.14159265358979f),
+ d(3.14159265358979),
+ // Including a space differentiates this from
+ // boost::lexical_cast<std::string>, which doesn't handle embedded
+ // spaces so well.
+ abc("abc def")
+ {
+ llsd["i"] = i;
+ llsd["d"] = d;
+ llsd["abc"] = abc;
+ }
+
+ char c;
+ short s;
+ int i;
+ long l;
+ float f;
+ double d;
+ std::string abc;
+ LLSD llsd;
+ };
+ typedef test_group<stringize_data> stringize_group;
+ typedef stringize_group::object stringize_object;
+ tut::stringize_group strzgrp("stringize");
+
+ template<> template<>
+ void stringize_object::test<1>()
+ {
+ ensure_equals(stringize(c), "c");
+ ensure_equals(stringize(s), "17");
+ ensure_equals(stringize(i), "34");
+ ensure_equals(stringize(l), "68");
+ ensure_equals(stringize(f), "3.14159");
+ ensure_equals(stringize(d), "3.14159");
+ ensure_equals(stringize(abc), "abc def");
+ ensure_equals(stringize(llsd), "{'abc':'abc def','d':r3.14159,'i':i34}");
+ }
+
+ template<> template<>
+ void stringize_object::test<2>()
+ {
+ ensure_equals(STRINGIZE("c is " << c), "c is c");
+ ensure_equals(STRINGIZE(std::setprecision(4) << d), "3.142");
+ }
+} // namespace tut
diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h
new file mode 100644
index 0000000000..1001ebc466
--- /dev/null
+++ b/indra/llcommon/tests/wrapllerrs.h
@@ -0,0 +1,56 @@
+/**
+ * @file wrapllerrs.h
+ * @author Nat Goodspeed
+ * @date 2009-03-11
+ * @brief Define a class useful for unit tests that engage llerrs (LL_ERRS) functionality
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_WRAPLLERRS_H)
+#define LL_WRAPLLERRS_H
+
+#include "llerrorcontrol.h"
+
+struct WrapLL_ERRS
+{
+ WrapLL_ERRS():
+ // Resetting Settings discards the default Recorder that writes to
+ // stderr. Otherwise, expected llerrs (LL_ERRS) messages clutter the
+ // console output of successful tests, potentially confusing things.
+ mPriorErrorSettings(LLError::saveAndResetSettings()),
+ // Save shutdown function called by LL_ERRS
+ mPriorFatal(LLError::getFatalFunction())
+ {
+ // Make LL_ERRS call our own operator() method
+ LLError::setFatalFunction(boost::bind(&WrapLL_ERRS::operator(), this, _1));
+ }
+
+ ~WrapLL_ERRS()
+ {
+ LLError::setFatalFunction(mPriorFatal);
+ LLError::restoreSettings(mPriorErrorSettings);
+ }
+
+ struct FatalException: public std::runtime_error
+ {
+ FatalException(const std::string& what): std::runtime_error(what) {}
+ };
+
+ void operator()(const std::string& message)
+ {
+ // Save message for later in case consumer wants to sense the result directly
+ error = message;
+ // Also throw an appropriate exception since calling code is likely to
+ // assume that control won't continue beyond LL_ERRS.
+ throw FatalException(message);
+ }
+
+ std::string error;
+ LLError::Settings* mPriorErrorSettings;
+ LLError::FatalFunction mPriorFatal;
+};
+
+#endif /* ! defined(LL_WRAPLLERRS_H) */
diff --git a/indra/llcommon/timing.h b/indra/llcommon/timing.h
index 2b9f60adad..140ce1fcaa 100644
--- a/indra/llcommon/timing.h
+++ b/indra/llcommon/timing.h
@@ -43,7 +43,6 @@ const F32 SEC_TO_MICROSEC = 1000000.f;
const U64 SEC_TO_MICROSEC_U64 = 1000000;
const U32 SEC_PER_DAY = 86400;
-// This is just a stub, implementation in lltimer.cpp. This file will be deprecated in the future.
-U64 totalTime(); // Returns current system time in microseconds
+// functionality has been moved lltimer.{cpp,h}. This file will be deprecated in the future.
#endif
diff --git a/indra/llcommon/u64.h b/indra/llcommon/u64.h
index 09a6b3e18d..eb51131e94 100644
--- a/indra/llcommon/u64.h
+++ b/indra/llcommon/u64.h
@@ -39,14 +39,14 @@
* @param str The string to parse.
* @return Returns the first U64 value found in the string or 0 on failure.
*/
-U64 str_to_U64(const std::string& str);
+LL_COMMON_API U64 str_to_U64(const std::string& str);
/**
* @brief Given a U64 value, return a printable representation.
* @param value The U64 to turn into a printable character array.
* @return Returns the result string.
*/
-std::string U64_to_str(U64 value);
+LL_COMMON_API std::string U64_to_str(U64 value);
/**
* @brief Given a U64 value, return a printable representation.
@@ -65,16 +65,16 @@ std::string U64_to_str(U64 value);
* @param result_size The size of the buffer allocated. Use U64_BUF.
* @return Returns the result pointer.
*/
-char* U64_to_str(U64 value, char* result, S32 result_size);
+LL_COMMON_API char* U64_to_str(U64 value, char* result, S32 result_size);
/**
* @brief Convert a U64 to the closest F64 value.
*/
-F64 U64_to_F64(const U64 value);
+LL_COMMON_API F64 U64_to_F64(const U64 value);
/**
* @brief Helper function to wrap strtoull() which is not available on windows.
*/
-U64 llstrtou64(const char* str, char** end, S32 base);
+LL_COMMON_API U64 llstrtou64(const char* str, char** end, S32 base);
#endif
diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp
index 2fd37e848e..c1022c1195 100755
--- a/indra/llcrashlogger/llcrashlogger.cpp
+++ b/indra/llcrashlogger/llcrashlogger.cpp
@@ -86,6 +86,7 @@ void LLCrashLoggerText::updateApplication(const std::string& message)
LLCrashLogger::LLCrashLogger() :
mCrashBehavior(CRASH_BEHAVIOR_ASK),
mCrashInPreviousExec(false),
+ mCrashSettings("CrashSettings"),
mSentCrashLogs(false),
mCrashHost("")
{
@@ -208,7 +209,10 @@ void LLCrashLogger::gatherFiles()
mFileMap["SettingsXml"] = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"settings.xml");
}
+#if !LL_DARWIN
if(mCrashInPreviousExec)
+#else
+#endif
{
// Replace the log file ext with .old, since the
// instance that launched this process has overwritten
diff --git a/indra/llimage/CMakeLists.txt b/indra/llimage/CMakeLists.txt
index 0635ddd5f5..22be4078a1 100644
--- a/indra/llimage/CMakeLists.txt
+++ b/indra/llimage/CMakeLists.txt
@@ -3,6 +3,7 @@
project(llimage)
include(00-Common)
+include(LLAddBuildTest)
include(LLCommon)
include(LLImage)
include(LLMath)
@@ -59,3 +60,6 @@ target_link_libraries(llimage
${PNG_LIBRARIES}
${ZLIB_LIBRARIES}
)
+
+# Add tests
+#ADD_BUILD_TEST(llimageworker llimage)
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 93ddc65f32..e02be6c8c1 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -55,13 +55,9 @@ std::string LLImage::sLastErrorMessage;
LLMutex* LLImage::sMutex = NULL;
//static
-void LLImage::initClass(LLWorkerThread* workerthread)
+void LLImage::initClass()
{
sMutex = new LLMutex(NULL);
- if (workerthread)
- {
- LLImageWorker::initImageWorker(workerthread);
- }
LLImageJ2C::openDSO();
}
@@ -69,7 +65,6 @@ void LLImage::initClass(LLWorkerThread* workerthread)
void LLImage::cleanupClass()
{
LLImageJ2C::closeDSO();
- LLImageWorker::cleanupImageWorker();
delete sMutex;
sMutex = NULL;
}
@@ -152,14 +147,14 @@ void LLImageBase::deleteData()
// virtual
U8* LLImageBase::allocateData(S32 size)
{
- LLMemType mt1((LLMemType::EMemType)mMemType);
+ LLMemType mt1(mMemType);
if (size < 0)
{
size = mWidth * mHeight * mComponents;
if (size <= 0)
{
- llerrs << llformat("LLImageBase::allocateData called with bad dimentions: %dx%dx%d",mWidth,mHeight,mComponents) << llendl;
+ llerrs << llformat("LLImageBase::allocateData called with bad dimensions: %dx%dx%d",mWidth,mHeight,mComponents) << llendl;
}
}
else if (size <= 0 || (size > 4096*4096*16 && sSizeOverride == FALSE))
@@ -188,7 +183,7 @@ U8* LLImageBase::allocateData(S32 size)
// virtual
U8* LLImageBase::reallocateData(S32 size)
{
- LLMemType mt1((LLMemType::EMemType)mMemType);
+ LLMemType mt1(mMemType);
U8 *new_datap = new U8[size];
if (!new_datap)
{
@@ -316,6 +311,21 @@ void LLImageRaw::deleteData()
LLImageBase::deleteData();
}
+void LLImageRaw::setDataAndSize(U8 *data, S32 width, S32 height, S8 components)
+{
+ if(data == getData())
+ {
+ return ;
+ }
+
+ deleteData();
+
+ LLImageBase::setSize(width, height, components) ;
+ LLImageBase::setDataAndSize(data, width * height * components) ;
+
+ sGlobalRawMemory += getDataSize();
+}
+
BOOL LLImageRaw::resize(U16 width, U16 height, S8 components)
{
if ((getWidth() == width) && (getHeight() == height) && (getComponents() == components))
@@ -332,7 +342,7 @@ BOOL LLImageRaw::resize(U16 width, U16 height, S8 components)
U8 * LLImageRaw::getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const
{
- LLMemType mt1((LLMemType::EMemType)mMemType);
+ LLMemType mt1(mMemType);
U8 *data = new U8[width*height*getComponents()];
// Should do some simple bounds checking
@@ -415,7 +425,7 @@ void LLImageRaw::clear(U8 r, U8 g, U8 b, U8 a)
// Reverses the order of the rows in the image
void LLImageRaw::verticalFlip()
{
- LLMemType mt1((LLMemType::EMemType)mMemType);
+ LLMemType mt1(mMemType);
S32 row_bytes = getWidth() * getComponents();
llassert(row_bytes > 0);
std::vector<U8> line_buffer(row_bytes);
@@ -548,7 +558,7 @@ void LLImageRaw::composite( LLImageRaw* src )
// Src and dst can be any size. Src has 4 components. Dst has 3 components.
void LLImageRaw::compositeScaled4onto3(LLImageRaw* src)
{
- LLMemType mt1((LLMemType::EMemType)mMemType);
+ LLMemType mt1(mMemType);
llinfos << "compositeScaled4onto3" << llendl;
LLImageRaw* dst = this; // Just for clarity.
@@ -658,6 +668,12 @@ void LLImageRaw::fill( const LLColor4U& color )
// Src and dst can be any size. Src and dst can each have 3 or 4 components.
void LLImageRaw::copy(LLImageRaw* src)
{
+ if (!src)
+ {
+ llwarns << "LLImageRaw::copy called with a null src pointer" << llendl;
+ return;
+ }
+
LLImageRaw* dst = this; // Just for clarity.
llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
@@ -787,7 +803,7 @@ void LLImageRaw::copyUnscaled3onto4( LLImageRaw* src )
// Src and dst can be any size. Src and dst have same number of components.
void LLImageRaw::copyScaled( LLImageRaw* src )
{
- LLMemType mt1((LLMemType::EMemType)mMemType);
+ LLMemType mt1(mMemType);
LLImageRaw* dst = this; // Just for clarity.
llassert_always( (1 == src->getComponents()) || (3 == src->getComponents()) || (4 == src->getComponents()) );
@@ -816,10 +832,55 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
}
}
+//scale down image by not blending a pixel with its neighbors.
+BOOL LLImageRaw::scaleDownWithoutBlending( S32 new_width, S32 new_height)
+{
+ LLMemType mt1(mMemType);
+
+ S8 c = getComponents() ;
+ llassert((1 == c) || (3 == c) || (4 == c) );
+
+ S32 old_width = getWidth();
+ S32 old_height = getHeight();
+
+ S32 new_data_size = old_width * new_height * c ;
+ llassert_always(new_data_size > 0);
+
+ F32 ratio_x = (F32)old_width / new_width ;
+ F32 ratio_y = (F32)old_height / new_height ;
+ if( ratio_x < 1.0f || ratio_y < 1.0f )
+ {
+ return TRUE; // Nothing to do.
+ }
+ ratio_x -= 1.0f ;
+ ratio_y -= 1.0f ;
+
+ U8* new_data = new U8[new_data_size] ;
+ llassert_always(new_data != NULL) ;
+
+ U8* old_data = getData() ;
+ S32 i, j, k, s, t;
+ for(i = 0, s = 0, t = 0 ; i < new_height ; i++)
+ {
+ for(j = 0 ; j < new_width ; j++)
+ {
+ for(k = 0 ; k < c ; k++)
+ {
+ new_data[s++] = old_data[t++] ;
+ }
+ t += (S32)(ratio_x * c + 0.1f) ;
+ }
+ t += (S32)(ratio_y * old_width * c + 0.1f) ;
+ }
+
+ setDataAndSize(new_data, new_width, new_height, c) ;
+
+ return TRUE ;
+}
BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
{
- LLMemType mt1((LLMemType::EMemType)mMemType);
+ LLMemType mt1(mMemType);
llassert((1 == getComponents()) || (3 == getComponents()) || (4 == getComponents()) );
S32 old_width = getWidth();
@@ -1223,25 +1284,28 @@ bool LLImageRaw::createFromFile(const std::string &filename, bool j2c_lowest_mip
ifs.read ((char*)buffer, length);
ifs.close();
- image->updateData();
-
- if (j2c_lowest_mip_only && codec == IMG_CODEC_J2C)
+ BOOL success;
+
+ success = image->updateData();
+ if (success)
{
- S32 width = image->getWidth();
- S32 height = image->getHeight();
- S32 discard_level = 0;
- while (width > 1 && height > 1 && discard_level < MAX_DISCARD_LEVEL)
+ if (j2c_lowest_mip_only && codec == IMG_CODEC_J2C)
{
- width >>= 1;
- height >>= 1;
- discard_level++;
+ S32 width = image->getWidth();
+ S32 height = image->getHeight();
+ S32 discard_level = 0;
+ while (width > 1 && height > 1 && discard_level < MAX_DISCARD_LEVEL)
+ {
+ width >>= 1;
+ height >>= 1;
+ discard_level++;
+ }
+ ((LLImageJ2C *)((LLImageFormatted*)image))->setDiscardLevel(discard_level);
}
- ((LLImageJ2C *)((LLImageFormatted*)image))->setDiscardLevel(discard_level);
+ success = image->decode(this, 100000.0f);
}
-
- BOOL success = image->decode(this, 100000.0f);
- image = NULL; // deletes image
+ image = NULL; // deletes image
if (!success)
{
deleteData();
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index bd609b638c..686f583886 100644
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -35,8 +35,9 @@
#include "lluuid.h"
#include "llstring.h"
-#include "llmemory.h"
+//#include "llmemory.h"
#include "llthread.h"
+#include "llmemtype.h"
const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2
const S32 MAX_IMAGE_MIP = 11; // 2048x2048
@@ -49,7 +50,8 @@ const S32 MAX_IMAGE_AREA = MAX_IMAGE_SIZE * MAX_IMAGE_SIZE;
const S32 MAX_IMAGE_COMPONENTS = 8;
const S32 MAX_IMAGE_DATA_SIZE = MAX_IMAGE_AREA * MAX_IMAGE_COMPONENTS;
-// Note! These CANNOT be changed without invalidating the viewer VFS files, I think?
+// Note! These CANNOT be changed without modifying simulator code
+// *TODO: change both to 1024 when SIM texture fetching is deprecated
const S32 FIRST_PACKET_SIZE = 600;
const S32 MAX_IMG_PACKET_SIZE = 1000;
@@ -60,7 +62,6 @@ const S32 MAX_IMG_PACKET_SIZE = 1000;
class LLImageFormatted;
class LLImageRaw;
class LLColor4U;
-class LLWorkerThread;
typedef enum e_image_codec
{
@@ -81,7 +82,7 @@ typedef enum e_image_codec
class LLImage
{
public:
- static void initClass(LLWorkerThread* workerthread);
+ static void initClass();
static void cleanupClass();
static const std::string& getLastError();
@@ -130,7 +131,7 @@ public:
protected:
// special accessor to allow direct setting of mData and mDataSize by LLImageFormatted
- void setDataAndSize(U8 *data, S32 size) { mData = data; mDataSize = size; };
+ void setDataAndSize(U8 *data, S32 size) { mData = data; mDataSize = size; }
public:
static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels);
@@ -155,7 +156,7 @@ private:
BOOL mBadBufferAllocation ;
public:
- S16 mMemType; // debug
+ LLMemType::DeclareMemType& mMemType; // debug
static BOOL sSizeOverride;
};
@@ -191,6 +192,7 @@ public:
void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE);
BOOL scale( S32 new_width, S32 new_height, BOOL scale_image = TRUE );
+ BOOL scaleDownWithoutBlending( S32 new_width, S32 new_height) ;
// Fill the buffer with a constant color
void fill( const LLColor4U& color );
@@ -239,6 +241,8 @@ protected:
U8 fastFractionalMult(U8 a,U8 b);
+ void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ;
+
public:
static S32 sGlobalRawMemory;
static S32 sRawImageCount;
@@ -309,7 +313,7 @@ protected:
protected:
S8 mCodec;
S8 mDecoding;
- S8 mDecoded;
+ S8 mDecoded; // unused, but changing LLImage layout requires recompiling static Mac/Linux libs. 2009-01-30 JC
S8 mDiscardLevel;
public:
diff --git a/indra/llimage/llimagedxt.cpp b/indra/llimage/llimagedxt.cpp
index 1ce4517a0d..0aa6840ff6 100644
--- a/indra/llimage/llimagedxt.cpp
+++ b/indra/llimage/llimagedxt.cpp
@@ -264,6 +264,8 @@ void LLImageDXT::setFormat()
// virtual
BOOL LLImageDXT::decode(LLImageRaw* raw_image, F32 time)
{
+ // *TODO: Test! This has been tweaked since its intial inception,
+ // but we don't use it any more!
llassert_always(raw_image);
if (mFileFormat >= FORMAT_DXT1 && mFileFormat <= FORMAT_DXR5)
@@ -274,8 +276,17 @@ BOOL LLImageDXT::decode(LLImageRaw* raw_image, F32 time)
S32 width = getWidth(), height = getHeight();
S32 ncomponents = getComponents();
+ U8* data = NULL;
+ if (mDiscardLevel >= 0)
+ {
+ data = getData() + getMipOffset(mDiscardLevel);
+ calcDiscardWidthHeight(mDiscardLevel, mFileFormat, width, height);
+ }
+ else
+ {
+ data = getData() + getMipOffset(0);
+ }
S32 image_size = formatBytes(mFileFormat, width, height);
- U8* data = getData() + getMipOffset(0);
if ((!getData()) || (data + image_size > getData() + getDataSize()))
{
@@ -300,10 +311,8 @@ BOOL LLImageDXT::getMipData(LLPointer<LLImageRaw>& raw, S32 discard)
llerrs << "Request for invalid discard level" << llendl;
}
U8* data = getData() + getMipOffset(discard);
- // I'm not sure these are the correct initial values for height and width,
- // but previously they were being used uninitialized. JC
- S32 width = raw->getWidth();
- S32 height = raw->getHeight();
+ S32 width = 0;
+ S32 height = 0;
calcDiscardWidthHeight(discard, mFileFormat, width, height);
raw = new LLImageRaw(data, width, height, getComponents());
return TRUE;
diff --git a/indra/llimage/llimagedxt.h b/indra/llimage/llimagedxt.h
index bc2d6522d2..1a297536b4 100644
--- a/indra/llimage/llimagedxt.h
+++ b/indra/llimage/llimagedxt.h
@@ -33,6 +33,7 @@
#define LL_LLIMAGEDXT_H
#include "llimage.h"
+#include "llpointer.h"
// This class decodes and encodes LL DXT files (which may unclude uncompressed RGB or RGBA mipped data)
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index 1b93c21982..74f08b2d0b 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -178,8 +178,8 @@ LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C),
mMaxBytes(0),
mRawDiscardLevel(-1),
mRate(0.0f),
- mReversible(FALSE)
-
+ mReversible(FALSE),
+ mAreaUsedForDataSizeCalcs(0)
{
//We assume here that if we wanted to create via
//a dynamic library that the approriate open calls were made
@@ -195,6 +195,12 @@ LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C),
}
mImpl = j2cimpl_create_func();
+
+ // Clear data size table
+ for( S32 i = 0; i <= MAX_DISCARD_LEVEL; i++)
+ { // Array size is MAX_DISCARD_LEVEL+1
+ mDataSizes[i] = 0;
+ }
}
// virtual
@@ -277,9 +283,10 @@ BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time)
}
+// Returns TRUE to mean done, whether successful or not.
BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count )
{
- LLMemType mt1((LLMemType::EMemType)mMemType);
+ LLMemType mt1(mMemType);
BOOL res = TRUE;
@@ -289,7 +296,7 @@ BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir
if (!getData() || (getDataSize() < 16))
{
setLastError("LLImageJ2C uninitialized");
- res = FALSE;
+ res = TRUE; // done
}
else
{
@@ -329,7 +336,7 @@ BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, F32 encode_time)
BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time)
{
- LLMemType mt1((LLMemType::EMemType)mMemType);
+ LLMemType mt1(mMemType);
resetLastError();
BOOL res = mImpl->encodeImpl(*this, *raw_imagep, comment_text, encode_time, mReversible);
if (!mLastError.empty())
@@ -342,7 +349,7 @@ BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text,
//static
S32 LLImageJ2C::calcHeaderSizeJ2C()
{
- return 600; //2048; // ??? hack... just needs to be >= actual header size...
+ return FIRST_PACKET_SIZE; // Hack. just needs to be >= actual header size...
}
//static
@@ -367,9 +374,45 @@ S32 LLImageJ2C::calcHeaderSize()
return calcHeaderSizeJ2C();
}
+
+// calcDataSize() returns how many bytes to read
+// to load discard_level (including header and higher discard levels)
S32 LLImageJ2C::calcDataSize(S32 discard_level)
{
- return calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), discard_level, mRate);
+ discard_level = llclamp(discard_level, 0, MAX_DISCARD_LEVEL);
+
+ if ( mAreaUsedForDataSizeCalcs != (getHeight() * getWidth())
+ || mDataSizes[0] == 0)
+ {
+ mAreaUsedForDataSizeCalcs = getHeight() * getWidth();
+
+ S32 level = MAX_DISCARD_LEVEL; // Start at the highest discard
+ while ( level >= 0 )
+ {
+ mDataSizes[level] = calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), level, mRate);
+ level--;
+ }
+
+ /* This is technically a more correct way to calculate the size required
+ for each discard level, since they should include the size needed for
+ lower levels. Unfortunately, this doesn't work well and will lead to
+ download stalls. The true correct way is to parse the header. This will
+ all go away with http textures at some point.
+
+ // Calculate the size for each discard level. Lower levels (higher quality)
+ // contain the cumulative size of higher levels
+ S32 total_size = calcHeaderSizeJ2C();
+
+ S32 level = MAX_DISCARD_LEVEL; // Start at the highest discard
+ while ( level >= 0 )
+ { // Add in this discard level and all before it
+ total_size += calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), level, mRate);
+ mDataSizes[level] = total_size;
+ level--;
+ }
+ */
+ }
+ return mDataSizes[discard_level];
}
S32 LLImageJ2C::calcDiscardLevelBytes(S32 bytes)
@@ -462,7 +505,7 @@ BOOL LLImageJ2C::loadAndValidate(const std::string &filename)
BOOL LLImageJ2C::validate(U8 *data, U32 file_size)
{
- LLMemType mt1((LLMemType::EMemType)mMemType);
+ LLMemType mt1(mMemType);
resetLastError();
diff --git a/indra/llimage/llimagej2c.h b/indra/llimage/llimagej2c.h
index 23f6ef5fd1..55df7f4429 100644
--- a/indra/llimage/llimagej2c.h
+++ b/indra/llimage/llimagej2c.h
@@ -87,6 +87,10 @@ protected:
void updateRawDiscardLevel();
S32 mMaxBytes; // Maximum number of bytes of data to use...
+
+ S32 mDataSizes[MAX_DISCARD_LEVEL+1]; // Size of data required to reach a given level
+ U32 mAreaUsedForDataSizeCalcs; // Height * width used to calculate mDataSizes
+
S8 mRawDiscardLevel;
F32 mRate;
BOOL mReversible;
diff --git a/indra/llimage/llimagejpeg.cpp b/indra/llimage/llimagejpeg.cpp
index fa0dd3ff05..79ea79cc07 100644
--- a/indra/llimage/llimagejpeg.cpp
+++ b/indra/llimage/llimagejpeg.cpp
@@ -188,6 +188,7 @@ void LLImageJPEG::decodeTermSource (j_decompress_ptr cinfo)
}
+// Returns true when done, whether or not decode was successful.
BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
{
llassert_always(raw_image);
@@ -198,7 +199,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
if (!getData() || (0 == getDataSize()))
{
setLastError("LLImageJPEG trying to decode an image with no data!");
- return FALSE;
+ return TRUE; // done
}
S32 row_stride = 0;
@@ -226,7 +227,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
if(setjmp(sSetjmpBuffer))
{
jpeg_destroy_decompress(&cinfo);
- return FALSE;
+ return TRUE; // done
}
try
{
@@ -320,7 +321,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
catch (int)
{
jpeg_destroy_decompress(&cinfo);
- return FALSE;
+ return TRUE; // done
}
// Check to see whether any corrupt-data warnings occurred
@@ -328,7 +329,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
{
// TODO: extract the warning to find out what went wrong.
setLastError( "Unable to decode JPEG image.");
- return FALSE;
+ return TRUE; // done
}
return TRUE;
diff --git a/indra/llimage/llimagetga.cpp b/indra/llimage/llimagetga.cpp
index a6721bfa0f..d8f8003593 100644
--- a/indra/llimage/llimagetga.cpp
+++ b/indra/llimage/llimagetga.cpp
@@ -31,10 +31,12 @@
#include "linden_common.h"
-#include "lldir.h"
#include "llimagetga.h"
+
+#include "lldir.h"
#include "llerror.h"
#include "llmath.h"
+#include "llpointer.h"
// For expanding 5-bit pixel values to 8-bit with best rounding
// static
diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp
index 532e996188..86d41515e7 100644
--- a/indra/llimage/llimageworker.cpp
+++ b/indra/llimage/llimageworker.cpp
@@ -37,152 +37,138 @@
//----------------------------------------------------------------------------
-//static
-LLWorkerThread* LLImageWorker::sWorkerThread = NULL;
-S32 LLImageWorker::sCount = 0;
+// MAIN THREAD
+LLImageDecodeThread::LLImageDecodeThread(bool threaded)
+ : LLQueuedThread("imagedecode", threaded)
+{
+ mCreationMutex = new LLMutex(getAPRPool());
+}
-//static
-void LLImageWorker::initImageWorker(LLWorkerThread* workerthread)
+// MAIN THREAD
+// virtual
+S32 LLImageDecodeThread::update(U32 max_time_ms)
{
- sWorkerThread = workerthread;
+ LLMutexLock lock(mCreationMutex);
+ for (creation_list_t::iterator iter = mCreationList.begin();
+ iter != mCreationList.end(); ++iter)
+ {
+ creation_info& info = *iter;
+ ImageRequest* req = new ImageRequest(info.handle, info.image,
+ info.priority, info.discard, info.needs_aux,
+ info.responder);
+ addRequest(req);
+ }
+ mCreationList.clear();
+ S32 res = LLQueuedThread::update(max_time_ms);
+ return res;
}
-//static
-void LLImageWorker::cleanupImageWorker()
+LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* image,
+ U32 priority, S32 discard, BOOL needs_aux, Responder* responder)
+{
+ LLMutexLock lock(mCreationMutex);
+ handle_t handle = generateHandle();
+ mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder));
+ return handle;
+}
+
+// Used by unit test only
+// Returns the size of the mutex guarded list as an indication of sanity
+S32 LLImageDecodeThread::tut_size()
+{
+ LLMutexLock lock(mCreationMutex);
+ S32 res = mCreationList.size();
+ return res;
+}
+
+LLImageDecodeThread::Responder::~Responder()
{
}
//----------------------------------------------------------------------------
-LLImageWorker::LLImageWorker(LLImageFormatted* image, U32 priority,
- S32 discard,
- LLPointer<LLResponder> responder)
- : LLWorkerClass(sWorkerThread, "Image"),
+LLImageDecodeThread::ImageRequest::ImageRequest(handle_t handle, LLImageFormatted* image,
+ U32 priority, S32 discard, BOOL needs_aux,
+ LLImageDecodeThread::Responder* responder)
+ : LLQueuedThread::QueuedRequest(handle, priority, FLAG_AUTO_COMPLETE),
mFormattedImage(image),
- mDecodedType(-1),
mDiscardLevel(discard),
- mPriority(priority),
+ mNeedsAux(needs_aux),
+ mDecodedRaw(FALSE),
+ mDecodedAux(FALSE),
mResponder(responder)
{
- ++sCount;
}
-LLImageWorker::~LLImageWorker()
+LLImageDecodeThread::ImageRequest::~ImageRequest()
{
- mDecodedImage = NULL;
+ mDecodedImageRaw = NULL;
+ mDecodedImageAux = NULL;
mFormattedImage = NULL;
- --sCount;
}
//----------------------------------------------------------------------------
-//virtual, main thread
-void LLImageWorker::startWork(S32 param)
-{
- llassert_always(mDecodedImage.isNull());
- mDecodedType = -1;
-}
-bool LLImageWorker::doWork(S32 param)
+// Returns true when done, whether or not decode was successful.
+bool LLImageDecodeThread::ImageRequest::processRequest()
{
- bool decoded = false;
- if(mDecodedImage.isNull())
+ const F32 decode_time_slice = .1f;
+ bool done = true;
+ if (!mDecodedRaw && mFormattedImage.notNull())
{
- if (!mFormattedImage->updateData())
- {
- mDecodedType = -2; // failed
- return true;
- }
- if (mDiscardLevel >= 0)
+ // Decode primary channels
+ if (mDecodedImageRaw.isNull())
{
- mFormattedImage->setDiscardLevel(mDiscardLevel);
- }
- if (!(mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents()))
- {
- decoded = true; // failed
- }
- else
- {
- mDecodedImage = new LLImageRaw(); // allow possibly smaller size set during decoding
+ // parse formatted header
+ if (!mFormattedImage->updateData())
+ {
+ return true; // done (failed)
+ }
+ if (!(mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents()))
+ {
+ return true; // done (failed)
+ }
+ if (mDiscardLevel >= 0)
+ {
+ mFormattedImage->setDiscardLevel(mDiscardLevel);
+ }
+ mDecodedImageRaw = new LLImageRaw(mFormattedImage->getWidth(),
+ mFormattedImage->getHeight(),
+ mFormattedImage->getComponents());
}
+ done = mFormattedImage->decode(mDecodedImageRaw, decode_time_slice); // 1ms
+ mDecodedRaw = done;
}
- if (!decoded)
+ if (done && mNeedsAux && !mDecodedAux && mFormattedImage.notNull())
{
- if (param == 0)
- {
- // Decode primary channels
- decoded = mFormattedImage->decode(mDecodedImage, .1f); // 1ms
- }
- else
+ // Decode aux channel
+ if (!mDecodedImageAux)
{
- // Decode aux channel
- decoded = mFormattedImage->decodeChannels(mDecodedImage, .1f, param, param); // 1ms
+ mDecodedImageAux = new LLImageRaw(mFormattedImage->getWidth(),
+ mFormattedImage->getHeight(),
+ 1);
}
+ done = mFormattedImage->decodeChannels(mDecodedImageAux, decode_time_slice, 4, 4); // 1ms
+ mDecodedAux = done;
}
- if (decoded)
- {
- // Call the callback immediately; endWork doesn't get called until ckeckWork
- if (mResponder.notNull())
- {
- bool success = (!wasAborted() && mDecodedImage.notNull() && mDecodedImage->getDataSize() != 0);
- mResponder->completed(success);
- }
- }
- return decoded;
-}
-void LLImageWorker::endWork(S32 param, bool aborted)
-{
- if (mDecodedType != -2)
- {
- mDecodedType = aborted ? -2 : param;
- }
+ return done;
}
-//----------------------------------------------------------------------------
-
-
-BOOL LLImageWorker::requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel, S32 discard)
+void LLImageDecodeThread::ImageRequest::finishRequest(bool completed)
{
- // For most codecs, only mDiscardLevel data is available.
- // (see LLImageDXT for exception)
- if (discard >= 0 && discard != mFormattedImage->getDiscardLevel())
- {
- llerrs << "Request for invalid discard level" << llendl;
- }
- checkWork();
- if (mDecodedType == -2)
+ if (mResponder.notNull())
{
- return TRUE; // aborted, done
- }
- if (mDecodedType != channel)
- {
- if (!haveWork())
- {
- addWork(channel, mPriority);
- }
- return FALSE;
- }
- else
- {
- llassert_always(!haveWork());
- llassert_always(mDecodedType == channel);
- raw = mDecodedImage; // smart pointer acquires ownership of data
- mDecodedImage = NULL;
- return TRUE;
+ bool success = completed && mDecodedRaw && (!mNeedsAux || mDecodedAux);
+ mResponder->completed(success, mDecodedImageRaw, mDecodedImageAux);
}
+ // Will automatically be deleted
}
-BOOL LLImageWorker::requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard)
+// Used by unit test only
+// Checks that a responder exists for this instance so that something can happen when completion is reached
+bool LLImageDecodeThread::ImageRequest::tut_isOK()
{
- if (mFormattedImage->getCodec() == IMG_CODEC_DXT)
- {
- // special case
- LLImageDXT* imagedxt = (LLImageDXT*)((LLImageFormatted*)mFormattedImage);
- return imagedxt->getMipData(raw, discard);
- }
- else
- {
- return requestDecodedAuxData(raw, 0, discard);
- }
+ return mResponder.notNull();
}
diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h
index 879fcf5565..6a5b86a277 100644
--- a/indra/llimage/llimageworker.h
+++ b/indra/llimage/llimageworker.h
@@ -34,51 +34,75 @@
#define LL_LLIMAGEWORKER_H
#include "llimage.h"
+#include "llpointer.h"
#include "llworkerthread.h"
-class LLImageWorker : public LLWorkerClass
+class LLImageDecodeThread : public LLQueuedThread
{
public:
- static void initImageWorker(LLWorkerThread* workerthread);
- static void cleanupImageWorker();
-
-public:
- static LLWorkerThread* getWorkerThread() { return sWorkerThread; }
-
- // LLWorkerThread
-public:
- LLImageWorker(LLImageFormatted* image, U32 priority, S32 discard,
- LLPointer<LLResponder> responder);
- ~LLImageWorker();
-
- // called from WORKER THREAD, returns TRUE if done
- /*virtual*/ bool doWork(S32 param);
-
- BOOL requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard = -1);
- BOOL requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel, S32 discard = -1);
- void releaseDecodedData();
- void cancelDecode();
+ class Responder : public LLThreadSafeRefCount
+ {
+ protected:
+ virtual ~Responder();
+ public:
+ virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) = 0;
+ };
-private:
- // called from MAIN THREAD
- /*virtual*/ void startWork(S32 param); // called from addWork()
- /*virtual*/ void endWork(S32 param, bool aborted); // called from doWork()
+ class ImageRequest : public LLQueuedThread::QueuedRequest
+ {
+ protected:
+ virtual ~ImageRequest(); // use deleteRequest()
+
+ public:
+ ImageRequest(handle_t handle, LLImageFormatted* image,
+ U32 priority, S32 discard, BOOL needs_aux,
+ LLImageDecodeThread::Responder* responder);
-protected:
- LLPointer<LLImageFormatted> mFormattedImage;
- LLPointer<LLImageRaw> mDecodedImage;
- S32 mDecodedType;
- S32 mDiscardLevel;
+ /*virtual*/ bool processRequest();
+ /*virtual*/ void finishRequest(bool completed);
-private:
- U32 mPriority;
- LLPointer<LLResponder> mResponder;
+ // Used by unit tests to check the consitency of the request instance
+ bool tut_isOK();
+
+ private:
+ // input
+ LLPointer<LLImageFormatted> mFormattedImage;
+ S32 mDiscardLevel;
+ BOOL mNeedsAux;
+ // output
+ LLPointer<LLImageRaw> mDecodedImageRaw;
+ LLPointer<LLImageRaw> mDecodedImageAux;
+ BOOL mDecodedRaw;
+ BOOL mDecodedAux;
+ LLPointer<LLImageDecodeThread::Responder> mResponder;
+ };
-protected:
- static LLWorkerThread* sWorkerThread;
-
public:
- static S32 sCount;
+ LLImageDecodeThread(bool threaded = true);
+ handle_t decodeImage(LLImageFormatted* image,
+ U32 priority, S32 discard, BOOL needs_aux,
+ Responder* responder);
+ S32 update(U32 max_time_ms);
+
+ // Used by unit tests to check the consistency of the thread instance
+ S32 tut_size();
+
+private:
+ struct creation_info
+ {
+ handle_t handle;
+ LLPointer<LLImageFormatted> image;
+ U32 priority;
+ S32 discard;
+ BOOL needs_aux;
+ LLPointer<Responder> responder;
+ creation_info(handle_t h, LLImageFormatted* i, U32 p, S32 d, BOOL aux, Responder* r)
+ : handle(h), image(i), priority(p), discard(d), needs_aux(aux), responder(r)
+ {}
+ };
+ typedef std::list<creation_info> creation_list_t;
+ creation_list_t mCreationList;
+ LLMutex* mCreationMutex;
};
#endif
diff --git a/indra/llimage/tests/llimageworker_test.cpp b/indra/llimage/tests/llimageworker_test.cpp
new file mode 100644
index 0000000000..cc44696a45
--- /dev/null
+++ b/indra/llimage/tests/llimageworker_test.cpp
@@ -0,0 +1,260 @@
+/**
+ * @file llimageworker_test.cpp
+ * @author Merov Linden
+ * @date 2009-04-28
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ *
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header: almost always required for newview cpp files
+#include <list>
+#include <map>
+#include <algorithm>
+// Class to test
+#include "../llimageworker.h"
+// For timer class
+#include "../llcommon/lltimer.h"
+// Tut header
+#include "../test/lltut.h"
+
+// -------------------------------------------------------------------------------------------
+// Stubbing: Declarations required to link and run the class being tested
+// Notes:
+// * Add here stubbed implementation of the few classes and methods used in the class to be tested
+// * Add as little as possible (let the link errors guide you)
+// * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code)
+// * A simulator for a class can be implemented here. Please comment and document thoroughly.
+
+LLImageBase::LLImageBase() {}
+LLImageBase::~LLImageBase() {}
+void LLImageBase::dump() { }
+void LLImageBase::sanityCheck() { }
+void LLImageBase::deleteData() { }
+U8* LLImageBase::allocateData(S32 size) { return NULL; }
+U8* LLImageBase::reallocateData(S32 size) { return NULL; }
+
+LLImageRaw::LLImageRaw(U16 width, U16 height, S8 components) { }
+LLImageRaw::~LLImageRaw() { }
+void LLImageRaw::deleteData() { }
+U8* LLImageRaw::allocateData(S32 size) { return NULL; }
+U8* LLImageRaw::reallocateData(S32 size) { return NULL; }
+
+// End Stubbing
+// -------------------------------------------------------------------------------------------
+
+// -------------------------------------------------------------------------------------------
+// TUT
+// -------------------------------------------------------------------------------------------
+
+namespace tut
+{
+ // Test wrapper declarations
+
+ // Note: We derive the responder class for 2 reasons:
+ // 1. It's a pure virtual class and we can't compile without completed() being implemented
+ // 2. We actually need a responder to test that the thread work test completed
+ // We implement this making no assumption on what's done in the thread or worker
+ // though, just that the responder's completed() method is called in the end.
+ // Note on responders: responders are ref counted and *will* be deleted by the request they are
+ // attached to when the queued request is deleted. The recommended way of using them is to
+ // create them when creating a request, put a callback method in completed() and not rely on
+ // anything to survive in the responder object once completed() has been called. Let the request
+ // do the deletion and clean up itself.
+ class responder_test : public LLImageDecodeThread::Responder
+ {
+ public:
+ responder_test(bool* res)
+ {
+ done = res;
+ *done = false;
+ }
+ virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux)
+ {
+ *done = true;
+ }
+ private:
+ // This is what can be thought of as the minimal implementation of a responder
+ // Done will be switched to true when completed() is called and can be tested
+ // outside the responder. A better way of doing this is to store a callback here.
+ bool* done;
+ };
+
+ // Test wrapper declaration : decode thread
+ struct imagedecodethread_test
+ {
+ // Instance to be tested
+ LLImageDecodeThread* mThread;
+
+ // Constructor and destructor of the test wrapper
+ imagedecodethread_test()
+ {
+ mThread = NULL;
+ }
+ ~imagedecodethread_test()
+ {
+ delete mThread;
+ }
+ };
+
+ // Test wrapper declaration : image worker
+ // Note: this class is not meant to be instantiated outside an LLImageDecodeThread instance
+ // but it's not a bad idea to get its public API a good shake as part of a thorough unit test set.
+ // Some gotcha with the destructor though (see below).
+ struct imagerequest_test
+ {
+ // Instance to be tested
+ LLImageDecodeThread::ImageRequest* mRequest;
+ bool done;
+
+ // Constructor and destructor of the test wrapper
+ imagerequest_test()
+ {
+ done = false;
+ mRequest = new LLImageDecodeThread::ImageRequest(0, 0,
+ LLQueuedThread::PRIORITY_NORMAL, 0, FALSE,
+ new responder_test(&done));
+ }
+ ~imagerequest_test()
+ {
+ // We should delete the object *but*, because its destructor is protected, that cannot be
+ // done from outside an LLImageDecodeThread instance... So we leak memory here... It's fine...
+ //delete mRequest;
+ }
+ };
+
+ // Tut templating thingamagic: test group, object and test instance
+ typedef test_group<imagedecodethread_test> imagedecodethread_t;
+ typedef imagedecodethread_t::object imagedecodethread_object_t;
+ tut::imagedecodethread_t tut_imagedecodethread("imagedecodethread");
+
+ typedef test_group<imagerequest_test> imagerequest_t;
+ typedef imagerequest_t::object imagerequest_object_t;
+ tut::imagerequest_t tut_imagerequest("imagerequest");
+
+ // ---------------------------------------------------------------------------------------
+ // Test functions
+ // Notes:
+ // * Test as many as you possibly can without requiring a full blown simulation of everything
+ // * The tests are executed in sequence so the test instance state may change between calls
+ // * Remember that you cannot test private methods with tut
+ // ---------------------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------------------
+ // Test the LLImageDecodeThread interface
+ // ---------------------------------------------------------------------------------------
+ //
+ // Note on Unit Testing Queued Thread Classes
+ //
+ // Since methods on such a class are called on a separate loop and that we can't insert tut
+ // ensure() calls in there, we exercise the class with 2 sets of tests:
+ // - 1: Test as a single threaded instance: We declare the class but ask for no thread
+ // to be spawned (easy with LLThreads since there's a boolean argument on the constructor
+ // just for that). We can then unit test each public method like we do on a normal class.
+ // - 2: Test as a threaded instance: We let the thread launch and check that its external
+ // behavior is as expected (i.e. it runs, can accept a work order and processes
+ // it). Typically though there's no guarantee that this exercises all the methods of the
+ // class which is why we also need the previous "non threaded" set of unit tests for
+ // complete coverage.
+ //
+ // ---------------------------------------------------------------------------------------
+
+ template<> template<>
+ void imagedecodethread_object_t::test<1>()
+ {
+ // Test a *non threaded* instance of the class
+ mThread = new LLImageDecodeThread(false);
+ ensure("LLImageDecodeThread: non threaded constructor failed", mThread != NULL);
+ // Test that we start with an empty list right at creation
+ ensure("LLImageDecodeThread: non threaded init state incorrect", mThread->tut_size() == 0);
+ // Insert something in the queue
+ bool done = false;
+ LLImageDecodeThread::handle_t decodeHandle = mThread->decodeImage(NULL, LLQueuedThread::PRIORITY_NORMAL, 0, FALSE, new responder_test(&done));
+ // Verifies we got a valid handle
+ ensure("LLImageDecodeThread: non threaded decodeImage(), returned handle is null", decodeHandle != 0);
+ // Verifies that we do now have something in the queued list
+ ensure("LLImageDecodeThread: non threaded decodeImage() insertion in threaded list failed", mThread->tut_size() == 1);
+ // Trigger queue handling "manually" (on a threaded instance, this is done on the thread loop)
+ S32 res = mThread->update(0);
+ // Verifies that we successfully handled the list
+ ensure("LLImageDecodeThread: non threaded update() list handling test failed", res == 0);
+ // Verifies that the list is now empty
+ ensure("LLImageDecodeThread: non threaded update() list emptying test failed", mThread->tut_size() == 0);
+ }
+
+ template<> template<>
+ void imagedecodethread_object_t::test<2>()
+ {
+ // Test a *threaded* instance of the class
+ mThread = new LLImageDecodeThread(true);
+ ensure("LLImageDecodeThread: threaded constructor failed", mThread != NULL);
+ // Test that we start with an empty list right at creation
+ ensure("LLImageDecodeThread: threaded init state incorrect", mThread->tut_size() == 0);
+ // Insert something in the queue
+ bool done = false;
+ LLImageDecodeThread::handle_t decodeHandle = mThread->decodeImage(NULL, LLQueuedThread::PRIORITY_NORMAL, 0, FALSE, new responder_test(&done));
+ // Verifies we get back a valid handle
+ ensure("LLImageDecodeThread: threaded decodeImage(), returned handle is null", decodeHandle != 0);
+ // Wait a little so to simulate the main thread doing something on its main loop...
+ ms_sleep(500); // 500 milliseconds
+ // Verifies that the responder has *not* been called yet in the meantime
+ ensure("LLImageDecodeThread: responder creation failed", done == false);
+ // Ask the thread to update: that means tells the queue to check itself and creates work requests
+ mThread->update(1);
+ // Wait till the thread has time to handle the work order (though it doesn't do much per work order...)
+ const U32 INCREMENT_TIME = 500; // 500 milliseconds
+ const U32 MAX_TIME = 20 * INCREMENT_TIME; // Do the loop 20 times max, i.e. wait 10 seconds but no more
+ U32 total_time = 0;
+ while ((done == false) && (total_time < MAX_TIME))
+ {
+ ms_sleep(INCREMENT_TIME);
+ total_time += INCREMENT_TIME;
+ }
+ // Verifies that the responder has now been called
+ ensure("LLImageDecodeThread: threaded work unit not processed", done == true);
+ }
+
+ // ---------------------------------------------------------------------------------------
+ // Test the LLImageDecodeThread::ImageRequest interface
+ // ---------------------------------------------------------------------------------------
+
+ template<> template<>
+ void imagerequest_object_t::test<1>()
+ {
+ // Test that we start with a correct request at creation
+ ensure("LLImageDecodeThread::ImageRequest::ImageRequest() constructor test failed", mRequest->tut_isOK());
+ bool res = mRequest->processRequest();
+ // Verifies that we processed the request successfully
+ ensure("LLImageDecodeThread::ImageRequest::processRequest() processing request test failed", res == true);
+ // Check that we can call the finishing call safely
+ try {
+ mRequest->finishRequest(false);
+ } catch (...) {
+ fail("LLImageDecodeThread::ImageRequest::finishRequest() test failed");
+ }
+ }
+}
diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp
index be6b6c817b..e71429b18d 100644
--- a/indra/llimagej2coj/llimagej2coj.cpp
+++ b/indra/llimagej2coj/llimagej2coj.cpp
@@ -37,7 +37,7 @@
#include "openjpeg.h"
#include "lltimer.h"
-#include "llmemory.h"
+//#include "llmemory.h"
const char* fallbackEngineInfoLLImageJ2CImpl()
{
@@ -168,7 +168,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
// dereference the array.
if(!image || !image->numcomps)
{
- llwarns << "ERROR -> decodeImpl: failed to decode image!" << llendl;
+ LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image!" << LL_ENDL;
if (image)
{
opj_image_destroy(image);
@@ -241,7 +241,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
}
else // Some rare OpenJPEG versions have this bug.
{
- llwarns << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << llendl;
+ LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << LL_ENDL;
opj_image_destroy(image);
return TRUE; // done
@@ -375,7 +375,7 @@ BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, con
if (!bSuccess)
{
opj_cio_close(cio);
- llinfos << "Failed to encode image." << llendl;
+ LL_DEBUGS("Texture") << "Failed to encode image." << LL_ENDL;
return FALSE;
}
codestream_length = cio_tell(cio);
diff --git a/indra/llinventory/CMakeLists.txt b/indra/llinventory/CMakeLists.txt
index b70548a9ba..b358f0a013 100644
--- a/indra/llinventory/CMakeLists.txt
+++ b/indra/llinventory/CMakeLists.txt
@@ -6,6 +6,7 @@ include(00-Common)
include(LLCommon)
include(LLMath)
include(LLMessage)
+include(LLVFS)
include(LLXML)
include_directories(
@@ -54,3 +55,18 @@ set_source_files_properties(${llinventory_HEADER_FILES}
list(APPEND llinventory_SOURCE_FILES ${llinventory_HEADER_FILES})
add_library (llinventory ${llinventory_SOURCE_FILES})
+
+
+
+#add unit tests
+INCLUDE(LLAddBuildTest)
+SET(llinventory_TEST_SOURCE_FILES
+ # no real unit tests yet!
+ )
+LL_ADD_PROJECT_UNIT_TESTS(llinventory "${llinventory_TEST_SOURCE_FILES}")
+
+#set(TEST_DEBUG on)
+set(test_libs llinventory ${LLMESSAGE_LIBRARIES} ${LLVFS_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
+LL_ADD_INTEGRATION_TEST(inventorymisc "" "${test_libs}")
+LL_ADD_INTEGRATION_TEST(llparcel "" "${test_libs}")
+
diff --git a/indra/llinventory/lleconomy.h b/indra/llinventory/lleconomy.h
index 2e2adc4d45..e480085453 100644
--- a/indra/llinventory/lleconomy.h
+++ b/indra/llinventory/lleconomy.h
@@ -32,7 +32,7 @@
#ifndef LL_LLECONOMY_H
#define LL_LLECONOMY_H
-#include "llmemory.h"
+#include "llsingleton.h"
class LLMessageSystem;
class LLVector3;
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index 2823cf7be9..d665deb605 100644
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -126,6 +126,25 @@ const std::string& LLInventoryObject::getName() const
return mName;
}
+// To bypass linked items, since llviewerinventory's getType
+// will return the linked-to item's type instead of this object's type.
+LLAssetType::EType LLInventoryObject::getActualType() const
+{
+ return mType;
+}
+
+BOOL LLInventoryObject::getIsLinkType() const
+{
+ return LLAssetType::lookupIsLinkType(mType);
+}
+
+// See LLInventoryItem override.
+// virtual
+const LLUUID& LLInventoryObject::getLinkedUUID() const
+{
+ return mUUID;
+}
+
LLAssetType::EType LLInventoryObject::getType() const
{
return mType;
@@ -296,6 +315,7 @@ LLInventoryItem::LLInventoryItem(
{
LLStringUtil::replaceNonstandardASCII(mDescription, ' ');
LLStringUtil::replaceChar(mDescription, '|', ' ');
+ mPermissions.initMasks(inv_type);
}
LLInventoryItem::LLInventoryItem() :
@@ -333,6 +353,19 @@ void LLInventoryItem::copyItem(const LLInventoryItem* other)
mCreationDate = other->mCreationDate;
}
+// If this is a linked item, then the UUID of the base object is
+// this item's assetID.
+// virtual
+const LLUUID& LLInventoryItem::getLinkedUUID() const
+{
+ if (LLAssetType::lookupIsLinkType(getActualType()))
+ {
+ return mAssetUUID;
+ }
+
+ return LLInventoryObject::getLinkedUUID();
+}
+
const LLPermissions& LLInventoryItem::getPermissions() const
{
return mPermissions;
@@ -405,6 +438,9 @@ void LLInventoryItem::setDescription(const std::string& d)
void LLInventoryItem::setPermissions(const LLPermissions& perm)
{
mPermissions = perm;
+
+ // Override permissions to unrestricted if this is a landmark
+ mPermissions.initMasks(mInventoryType);
}
void LLInventoryItem::setInventoryType(LLInventoryType::EType inv_type)
@@ -422,6 +458,39 @@ void LLInventoryItem::setCreationDate(time_t creation_date_utc)
mCreationDate = creation_date_utc;
}
+void LLInventoryItem::accumulatePermissionSlamBits(const LLInventoryItem& old_item)
+{
+ // Remove any pre-existing II_FLAGS_PERM_OVERWRITE_MASK flags
+ // because we now detect when they should be set.
+ setFlags( old_item.getFlags() | (getFlags() & ~(LLInventoryItem::II_FLAGS_PERM_OVERWRITE_MASK)) );
+
+ // Enforce the PERM_OVERWRITE flags for any masks that are different
+ // but only for AT_OBJECT's since that is the only asset type that can
+ // exist in-world (instead of only in-inventory or in-object-contents).
+ if (LLAssetType::AT_OBJECT == getType())
+ {
+ LLPermissions old_permissions = old_item.getPermissions();
+ U32 flags_to_be_set = 0;
+ if(old_permissions.getMaskNextOwner() != getPermissions().getMaskNextOwner())
+ {
+ flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_PERM;
+ }
+ if(old_permissions.getMaskEveryone() != getPermissions().getMaskEveryone())
+ {
+ flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE;
+ }
+ if(old_permissions.getMaskGroup() != getPermissions().getMaskGroup())
+ {
+ flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
+ }
+ LLSaleInfo old_sale_info = old_item.getSaleInfo();
+ if(old_sale_info != getSaleInfo())
+ {
+ flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_SALE;
+ }
+ setFlags(getFlags() | flags_to_be_set);
+ }
+}
const LLSaleInfo& LLInventoryItem::getSaleInfo() const
{
@@ -476,6 +545,7 @@ BOOL LLInventoryItem::unpackMessage(LLMessageSystem* msg, const char* block, S32
mType = static_cast<LLAssetType::EType>(type);
msg->getS8(block, "InvType", type, block_num);
mInventoryType = static_cast<LLInventoryType::EType>(type);
+ mPermissions.initMasks(mInventoryType);
msg->getU32Fast(block, _PREHASH_Flags, mFlags, block_num);
@@ -666,6 +736,9 @@ BOOL LLInventoryItem::importFile(LLFILE* fp)
lldebugs << "Resetting inventory type for " << mUUID << llendl;
mInventoryType = LLInventoryType::defaultForAssetType(mType);
}
+
+ mPermissions.initMasks(mInventoryType);
+
return success;
}
@@ -705,8 +778,8 @@ BOOL LLInventoryItem::exportFile(LLFILE* fp, BOOL include_asset_key) const
fprintf(fp, "\t\tasset_id\t%s\n", uuid_str.c_str());
}
fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
- const char* inv_type_str = LLInventoryType::lookup(mInventoryType);
- if(inv_type_str) fprintf(fp, "\t\tinv_type\t%s\n", inv_type_str);
+ const std::string inv_type_str = LLInventoryType::lookup(mInventoryType);
+ if(!inv_type_str.empty()) fprintf(fp, "\t\tinv_type\t%s\n", inv_type_str.c_str());
fprintf(fp, "\t\tflags\t%08x\n", mFlags);
mSaleInfo.exportFile(fp);
fprintf(fp, "\t\tname\t%s|\n", mName.c_str());
@@ -869,6 +942,9 @@ BOOL LLInventoryItem::importLegacyStream(std::istream& input_stream)
lldebugs << "Resetting inventory type for " << mUUID << llendl;
mInventoryType = LLInventoryType::defaultForAssetType(mType);
}
+
+ mPermissions.initMasks(mInventoryType);
+
return success;
}
@@ -908,8 +984,8 @@ BOOL LLInventoryItem::exportLegacyStream(std::ostream& output_stream, BOOL inclu
output_stream << "\t\tasset_id\t" << uuid_str << "\n";
}
output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n";
- const char* inv_type_str = LLInventoryType::lookup(mInventoryType);
- if(inv_type_str)
+ const std::string inv_type_str = LLInventoryType::lookup(mInventoryType);
+ if(!inv_type_str.empty())
output_stream << "\t\tinv_type\t" << inv_type_str << "\n";
std::string buffer;
buffer = llformat( "\t\tflags\t%08x\n", mFlags);
@@ -951,8 +1027,8 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const
}
sd[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(mType);
sd[INV_INVENTORY_TYPE_LABEL] = mInventoryType;
- const char* inv_type_str = LLInventoryType::lookup(mInventoryType);
- if(inv_type_str)
+ const std::string inv_type_str = LLInventoryType::lookup(mInventoryType);
+ if(!inv_type_str.empty())
{
sd[INV_INVENTORY_TYPE_LABEL] = inv_type_str;
}
@@ -1091,115 +1167,16 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd)
mInventoryType = LLInventoryType::defaultForAssetType(mType);
}
+ mPermissions.initMasks(mInventoryType);
+
return true;
fail:
return false;
}
-LLXMLNode *LLInventoryItem::exportFileXML(BOOL include_asset_key) const
-{
- LLMemType m1(LLMemType::MTYPE_INVENTORY);
- LLXMLNode *ret = new LLXMLNode("item", FALSE);
-
- ret->createChild("uuid", TRUE)->setUUIDValue(1, &mUUID);
- ret->createChild("parent_uuid", TRUE)->setUUIDValue(1, &mParentUUID);
-
- mPermissions.exportFileXML()->setParent(ret);
-
- // Check for permissions to see the asset id, and if so write it
- // out as an asset id. Otherwise, apply our cheesy encryption.
- if(include_asset_key)
- {
- U32 mask = mPermissions.getMaskBase();
- if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
- || (mAssetUUID.isNull()))
- {
- ret->createChild("asset_id", FALSE)->setUUIDValue(1, &mAssetUUID);
- }
- else
- {
- LLUUID shadow_id(mAssetUUID);
- LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
- cipher.encrypt(shadow_id.mData, UUID_BYTES);
-
- ret->createChild("shadow_id", FALSE)->setUUIDValue(1, &shadow_id);
- }
- }
-
- std::string type_str = LLAssetType::lookup(mType);
- std::string inv_type_str = LLInventoryType::lookup(mInventoryType);
-
- ret->createChild("asset_type", FALSE)->setStringValue(type_str);
- ret->createChild("inventory_type", FALSE)->setStringValue(inv_type_str);
- S32 tmp_flags = (S32) mFlags;
- ret->createChild("flags", FALSE)->setByteValue(4, (U8*)(&tmp_flags), LLXMLNode::ENCODING_HEX);
-
- mSaleInfo.exportFileXML()->setParent(ret);
-
- std::string temp;
- temp.assign(mName);
- ret->createChild("name", FALSE)->setStringValue(temp);
- temp.assign(mDescription);
- ret->createChild("description", FALSE)->setStringValue(temp);
- S32 date = mCreationDate;
- ret->createChild("creation_date", FALSE)->setIntValue(1, &date);
-
- return ret;
-}
-
-BOOL LLInventoryItem::importXML(LLXMLNode* node)
-{
- BOOL success = FALSE;
- if (node)
- {
- success = TRUE;
- LLXMLNodePtr sub_node;
- if (node->getChild("uuid", sub_node))
- success = (1 == sub_node->getUUIDValue(1, &mUUID));
- if (node->getChild("parent_uuid", sub_node))
- success = success && (1 == sub_node->getUUIDValue(1, &mParentUUID));
- if (node->getChild("permissions", sub_node))
- success = success && mPermissions.importXML(sub_node);
- if (node->getChild("asset_id", sub_node))
- success = success && (1 == sub_node->getUUIDValue(1, &mAssetUUID));
- if (node->getChild("shadow_id", sub_node))
- {
- success = success && (1 == sub_node->getUUIDValue(1, &mAssetUUID));
- LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
- cipher.decrypt(mAssetUUID.mData, UUID_BYTES);
- }
- if (node->getChild("asset_type", sub_node))
- mType = LLAssetType::lookup(sub_node->getValue());
- if (node->getChild("inventory_type", sub_node))
- mInventoryType = LLInventoryType::lookup(sub_node->getValue());
- if (node->getChild("flags", sub_node))
- {
- S32 tmp_flags = 0;
- success = success && (1 == sub_node->getIntValue(1, &tmp_flags));
- mFlags = (U32) tmp_flags;
- }
- if (node->getChild("sale_info", sub_node))
- success = success && mSaleInfo.importXML(sub_node);
- if (node->getChild("name", sub_node))
- mName = sub_node->getValue();
- if (node->getChild("description", sub_node))
- mDescription = sub_node->getValue();
- if (node->getChild("creation_date", sub_node))
- {
- S32 date = 0;
- success = success && (1 == sub_node->getIntValue(1, &date));
- mCreationDate = date;
- }
-
- if (!success)
- {
- lldebugs << "LLInventory::importXML() failed for node named '"
- << node->getName() << "'" << llendl;
- }
- }
- return success;
-}
+// Deleted LLInventoryItem::exportFileXML() and LLInventoryItem::importXML()
+// because I can't find any non-test code references to it. 2009-05-04 JC
S32 LLInventoryItem::packBinaryBucket(U8* bin_bucket, LLPermissions* perm_override) const
{
@@ -1347,7 +1324,7 @@ BOOL item_date_sort( LLInventoryItem* a, LLInventoryItem* b )
LLInventoryCategory::LLInventoryCategory(
const LLUUID& uuid,
const LLUUID& parent_uuid,
- LLAssetType::EType preferred_type,
+ LLFolderType::EType preferred_type,
const std::string& name) :
LLInventoryObject(uuid, parent_uuid, LLAssetType::AT_CATEGORY, name),
mPreferredType(preferred_type)
@@ -1355,7 +1332,7 @@ LLInventoryCategory::LLInventoryCategory(
}
LLInventoryCategory::LLInventoryCategory() :
- mPreferredType(LLAssetType::AT_NONE)
+ mPreferredType(LLFolderType::FT_NONE)
{
mType = LLAssetType::AT_CATEGORY;
}
@@ -1377,12 +1354,12 @@ void LLInventoryCategory::copyCategory(const LLInventoryCategory* other)
mPreferredType = other->mPreferredType;
}
-LLAssetType::EType LLInventoryCategory::getPreferredType() const
+LLFolderType::EType LLInventoryCategory::getPreferredType() const
{
return mPreferredType;
}
-void LLInventoryCategory::setPreferredType(LLAssetType::EType type)
+void LLInventoryCategory::setPreferredType(LLFolderType::EType type)
{
mPreferredType = type;
}
@@ -1428,13 +1405,13 @@ bool LLInventoryCategory::fromLLSD(const LLSD& sd)
if (sd.has(w))
{
S8 type = (U8)sd[w].asInteger();
- mPreferredType = static_cast<LLAssetType::EType>(type);
+ mPreferredType = static_cast<LLFolderType::EType>(type);
}
w = INV_ASSET_TYPE_LABEL_WS;
if (sd.has(w))
{
S8 type = (U8)sd[w].asInteger();
- mPreferredType = static_cast<LLAssetType::EType>(type);
+ mPreferredType = static_cast<LLFolderType::EType>(type);
}
w = INV_NAME_LABEL;
@@ -1456,7 +1433,7 @@ void LLInventoryCategory::unpackMessage(LLMessageSystem* msg,
msg->getUUIDFast(block, _PREHASH_ParentID, mParentUUID, block_num);
S8 type;
msg->getS8Fast(block, _PREHASH_Type, type, block_num);
- mPreferredType = static_cast<LLAssetType::EType>(type);
+ mPreferredType = static_cast<LLFolderType::EType>(type);
msg->getStringFast(block, _PREHASH_Name, mName, block_num);
LLStringUtil::replaceNonstandardASCII(mName, ' ');
}
@@ -1505,7 +1482,7 @@ BOOL LLInventoryCategory::importFile(LLFILE* fp)
}
else if(0 == strcmp("pref_type", keyword))
{
- mPreferredType = LLAssetType::lookup(valuestr);
+ mPreferredType = LLFolderType::lookup(valuestr);
}
else if(0 == strcmp("name", keyword))
{
@@ -1537,7 +1514,7 @@ BOOL LLInventoryCategory::exportFile(LLFILE* fp, BOOL) const
mParentUUID.toString(uuid_str);
fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str());
fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
- fprintf(fp, "\t\tpref_type\t%s\n", LLAssetType::lookup(mPreferredType));
+ fprintf(fp, "\t\tpref_type\t%s\n", LLFolderType::lookup(mPreferredType).c_str());
fprintf(fp, "\t\tname\t%s|\n", mName.c_str());
fprintf(fp,"\t}\n");
return TRUE;
@@ -1584,7 +1561,7 @@ BOOL LLInventoryCategory::importLegacyStream(std::istream& input_stream)
}
else if(0 == strcmp("pref_type", keyword))
{
- mPreferredType = LLAssetType::lookup(valuestr);
+ mPreferredType = LLFolderType::lookup(valuestr);
}
else if(0 == strcmp("name", keyword))
{
@@ -1616,7 +1593,7 @@ BOOL LLInventoryCategory::exportLegacyStream(std::ostream& output_stream, BOOL)
mParentUUID.toString(uuid_str);
output_stream << "\t\tparent_id\t" << uuid_str << "\n";
output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n";
- output_stream << "\t\tpref_type\t" << LLAssetType::lookup(mPreferredType) << "\n";
+ output_stream << "\t\tpref_type\t" << LLFolderType::lookup(mPreferredType) << "\n";
output_stream << "\t\tname\t" << mName.c_str() << "|\n";
output_stream << "\t}\n";
return TRUE;
@@ -1652,38 +1629,6 @@ LLSD ll_create_sd_from_inventory_item(LLPointer<LLInventoryItem> item)
return rv;
}
-/* deprecated, use LLInventoryItem::fromLLSD() instead
-LLPointer<LLInventoryItem> ll_create_item_from_sd(const LLSD& sd_item)
-{
- LLPointer<LLInventoryItem> rv = new LLInventoryItem;
- rv->setUUID(sd_item[INV_ITEM_ID_LABEL].asUUID());
- rv->setParent(sd_item[INV_PARENT_ID_LABEL].asUUID());
- rv->rename(sd_item[INV_NAME_LABEL].asString());
- rv->setType(
- LLAssetType::lookup(sd_item[INV_ASSET_TYPE_LABEL].asString()));
- if (sd_item.has("shadow_id"))
- {
- LLUUID asset_id = sd_item["shadow_id"];
- LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
- cipher.decrypt(asset_id.mData, UUID_BYTES);
- rv->setAssetUUID(asset_id);
- }
- if (sd_item.has(INV_ASSET_ID_LABEL))
- {
- rv->setAssetUUID(sd_item[INV_ASSET_ID_LABEL].asUUID());
- }
- rv->setDescription(sd_item[INV_DESC_LABEL].asString());
- rv->setSaleInfo(ll_sale_info_from_sd(sd_item[INV_SALE_INFO_LABEL]));
- rv->setPermissions(ll_permissions_from_sd(sd_item[INV_PERMISSIONS_LABEL]));
- rv->setInventoryType(
- LLInventoryType::lookup(
- sd_item[INV_INVENTORY_TYPE_LABEL].asString()));
- rv->setFlags((U32)(sd_item[INV_FLAGS_LABEL].asInteger()));
- rv->setCreationDate(sd_item[INV_CREATION_DATE_LABEL].asInteger());
- return rv;
-}
-*/
-
LLSD ll_create_sd_from_inventory_category(LLPointer<LLInventoryCategory> cat)
{
LLSD rv;
@@ -1698,10 +1643,10 @@ LLSD ll_create_sd_from_inventory_category(LLPointer<LLInventoryCategory> cat)
rv[INV_PARENT_ID_LABEL] = cat->getParentUUID();
rv[INV_NAME_LABEL] = cat->getName();
rv[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(cat->getType());
- if(LLAssetType::AT_NONE != cat->getPreferredType())
+ if(LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
{
rv[INV_PREFERRED_TYPE_LABEL] =
- LLAssetType::lookup(cat->getPreferredType());
+ LLFolderType::lookup(cat->getPreferredType()).c_str();
}
return rv;
}
@@ -1715,7 +1660,7 @@ LLPointer<LLInventoryCategory> ll_create_category_from_sd(const LLSD& sd_cat)
rv->setType(
LLAssetType::lookup(sd_cat[INV_ASSET_TYPE_LABEL].asString()));
rv->setPreferredType(
- LLAssetType::lookup(
- sd_cat[INV_PREFERRED_TYPE_LABEL].asString()));
+ LLFolderType::lookup(
+ sd_cat[INV_PREFERRED_TYPE_LABEL].asString()));
return rv;
}
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index d34046c310..9faecbea85 100644
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -35,15 +35,15 @@
#include <functional>
-#include "llassetstorage.h"
#include "lldarray.h"
+#include "llfoldertype.h"
#include "llinventorytype.h"
#include "llmemtype.h"
#include "llpermissions.h"
+#include "llrefcount.h"
#include "llsaleinfo.h"
#include "llsd.h"
#include "lluuid.h"
-#include "llxmlnode.h"
// consts for Key field in the task inventory update message
extern const U8 TASK_INVENTORY_ITEM_KEY;
@@ -91,12 +91,14 @@ public:
// accessors
virtual const LLUUID& getUUID() const;
const LLUUID& getParentUUID() const;
- const std::string& getName() const;
- LLAssetType::EType getType() const;
-
+ virtual const LLUUID& getLinkedUUID() const; // get the inventoryID that this item points to, else this item's inventoryID
+ virtual const std::string& getName() const;
+ virtual LLAssetType::EType getType() const;
+ LLAssetType::EType getActualType() const; // bypasses indirection for linked items
+ BOOL getIsLinkType() const;
// mutators - will not call updateServer();
void setUUID(const LLUUID& new_uuid);
- void rename(const std::string& new_name);
+ virtual void rename(const std::string& new_name);
void setParent(const LLUUID& new_parent);
void setType(LLAssetType::EType type);
@@ -216,6 +218,7 @@ protected:
~LLInventoryItem(); // ref counted
public:
+
MEM_TYPE_NEW(LLMemType::MTYPE_INVENTORY);
LLInventoryItem(const LLUUID& uuid,
const LLUUID& parent_uuid,
@@ -238,15 +241,16 @@ public:
void generateUUID() { mUUID.generate(); }
// accessors
- const LLPermissions& getPermissions() const;
- const LLUUID& getCreatorUUID() const;
- const LLUUID& getAssetUUID() const;
- const std::string& getDescription() const;
- const LLSaleInfo& getSaleInfo() const;
- LLInventoryType::EType getInventoryType() const;
- U32 getFlags() const;
- time_t getCreationDate() const;
- U32 getCRC32() const; // really more of a checksum.
+ virtual const LLUUID& getLinkedUUID() const;
+ virtual const LLPermissions& getPermissions() const;
+ virtual const LLUUID& getCreatorUUID() const;
+ virtual const LLUUID& getAssetUUID() const;
+ virtual const std::string& getDescription() const;
+ virtual const LLSaleInfo& getSaleInfo() const;
+ virtual LLInventoryType::EType getInventoryType() const;
+ virtual U32 getFlags() const;
+ virtual time_t getCreationDate() const;
+ virtual U32 getCRC32() const; // really more of a checksum.
// mutators - will not call updateServer(), and will never fail
// (though it may correct to sane values)
@@ -258,6 +262,14 @@ public:
void setFlags(U32 flags);
void setCreationDate(time_t creation_date_utc);
+ // Check for changes in permissions masks and sale info
+ // and set the corresponding bits in mFlags
+ void accumulatePermissionSlamBits(const LLInventoryItem& old_item);
+
+ // This is currently only used in the Viewer to handle calling cards
+ // where the creator is actually used to store the target.
+ void setCreator(const LLUUID& creator) { mPermissions.setCreator(creator); }
+
// Put this inventory item onto the current outgoing mesage. It
// assumes you have already called nextBlock().
virtual void packMessage(LLMessageSystem* msg) const;
@@ -273,9 +285,6 @@ public:
virtual BOOL importLegacyStream(std::istream& input_stream);
virtual BOOL exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key = TRUE) const;
- virtual LLXMLNode *exportFileXML(BOOL include_asset_key = TRUE) const;
- BOOL importXML(LLXMLNode* node);
-
// helper functions
// pack all information needed to reconstruct this item into the given binary bucket.
@@ -311,15 +320,15 @@ protected:
public:
MEM_TYPE_NEW(LLMemType::MTYPE_INVENTORY);
LLInventoryCategory(const LLUUID& uuid, const LLUUID& parent_uuid,
- LLAssetType::EType preferred_type,
+ LLFolderType::EType preferred_type,
const std::string& name);
LLInventoryCategory();
LLInventoryCategory(const LLInventoryCategory* other);
void copyCategory(const LLInventoryCategory* other); // LLRefCount requires custom copy
// accessors and mutators
- LLAssetType::EType getPreferredType() const;
- void setPreferredType(LLAssetType::EType type);
+ LLFolderType::EType getPreferredType() const;
+ void setPreferredType(LLFolderType::EType type);
// For messaging system support
virtual void packMessage(LLMessageSystem* msg) const;
virtual void unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0);
@@ -335,10 +344,8 @@ public:
virtual BOOL exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key = TRUE) const;
protected:
- // The type of asset that this category was "meant" to hold
- // (although it may in fact hold any type).
- LLAssetType::EType mPreferredType;
-
+ // May be the type that this category was "meant" to hold (although it may hold any type).
+ LLFolderType::EType mPreferredType;
};
@@ -348,7 +355,7 @@ protected:
typedef std::list<LLPointer<LLInventoryObject> > InventoryObjectList;
-// These functions convert between structured data and an inventroy
+// These functions convert between structured data and an inventory
// item, appropriate for serialization.
LLSD ll_create_sd_from_inventory_item(LLPointer<LLInventoryItem> item);
//LLPointer<LLInventoryItem> ll_create_item_from_sd(const LLSD& sd_item);
diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp
index a161a0ee00..4ef5df0b28 100644
--- a/indra/llinventory/llinventorytype.cpp
+++ b/indra/llinventory/llinventorytype.cpp
@@ -33,66 +33,65 @@
#include "linden_common.h"
#include "llinventorytype.h"
+#include "lldictionary.h"
+#include "llmemory.h"
+#include "llsingleton.h"
+
+static const std::string empty_string;
///----------------------------------------------------------------------------
/// Class LLInventoryType
///----------------------------------------------------------------------------
-
-// Unlike asset type names, not limited to 8 characters.
-// Need not match asset type names.
-static const char* INVENTORY_TYPE_NAMES[LLInventoryType::IT_COUNT] =
-{
- "texture", // 0
- "sound",
- "callcard",
- "landmark",
- NULL,
- NULL, // 5
- "object",
- "notecard",
- "category",
- "root",
- "script", // 10
- NULL,
- NULL,
- NULL,
- NULL,
- "snapshot", // 15
- NULL,
- "attach",
- "wearable",
- "animation",
- "gesture", // 20
+struct InventoryEntry : public LLDictionaryEntry
+{
+ InventoryEntry(const std::string &name, // unlike asset type names, not limited to 8 characters; need not match asset type names
+ const std::string &human_name, // for decoding to human readable form; put any and as many printable characters you want in each one.
+ int num_asset_types = 0, ...)
+ :
+ LLDictionaryEntry(name),
+ mHumanName(human_name)
+ {
+ va_list argp;
+ va_start(argp, num_asset_types);
+ // Read in local textures
+ for (U8 i=0; i < num_asset_types; i++)
+ {
+ LLAssetType::EType t = (LLAssetType::EType)va_arg(argp,int);
+ mAssetTypes.push_back(t);
+ }
+ }
+
+ const std::string mHumanName;
+ typedef std::vector<LLAssetType::EType> asset_vec_t;
+ asset_vec_t mAssetTypes;
};
-// This table is meant for decoding to human readable form. Put any
-// and as many printable characters you want in each one.
-// See also LLAssetType::mAssetTypeHumanNames
-static const char* INVENTORY_TYPE_HUMAN_NAMES[LLInventoryType::IT_COUNT] =
-{
- "texture", // 0
- "sound",
- "calling card",
- "landmark",
- NULL,
- NULL, // 5
- "object",
- "note card",
- "folder",
- "root",
- "script", // 10
- NULL,
- NULL,
- NULL,
- NULL,
- "snapshot", // 15
- NULL,
- "attachment",
- "wearable",
- "animation",
- "gesture", // 20
+class LLInventoryDictionary : public LLSingleton<LLInventoryDictionary>,
+ public LLDictionary<LLInventoryType::EType, InventoryEntry>
+{
+public:
+ LLInventoryDictionary();
};
+LLInventoryDictionary::LLInventoryDictionary()
+{
+ addEntry(LLInventoryType::IT_TEXTURE, new InventoryEntry("texture", "texture", 1, LLAssetType::AT_TEXTURE));
+ addEntry(LLInventoryType::IT_SOUND, new InventoryEntry("sound", "sound", 1, LLAssetType::AT_SOUND));
+ addEntry(LLInventoryType::IT_CALLINGCARD, new InventoryEntry("callcard", "calling card", 1, LLAssetType::AT_CALLINGCARD));
+ addEntry(LLInventoryType::IT_LANDMARK, new InventoryEntry("landmark", "landmark", 1, LLAssetType::AT_LANDMARK));
+ addEntry(LLInventoryType::IT_OBJECT, new InventoryEntry("object", "object", 1, LLAssetType::AT_OBJECT));
+ addEntry(LLInventoryType::IT_NOTECARD, new InventoryEntry("notecard", "note card", 1, LLAssetType::AT_NOTECARD));
+ addEntry(LLInventoryType::IT_CATEGORY, new InventoryEntry("category", "folder" ));
+ addEntry(LLInventoryType::IT_ROOT_CATEGORY, new InventoryEntry("root", "root" ));
+ addEntry(LLInventoryType::IT_LSL, new InventoryEntry("script", "script", 2, LLAssetType::AT_LSL_TEXT, LLAssetType::AT_LSL_BYTECODE));
+ addEntry(LLInventoryType::IT_SNAPSHOT, new InventoryEntry("snapshot", "snapshot", 1, LLAssetType::AT_TEXTURE));
+ addEntry(LLInventoryType::IT_ATTACHMENT, new InventoryEntry("attach", "attachment", 1, LLAssetType::AT_OBJECT));
+ addEntry(LLInventoryType::IT_WEARABLE, new InventoryEntry("wearable", "wearable", 2, LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART));
+ addEntry(LLInventoryType::IT_ANIMATION, new InventoryEntry("animation", "animation", 1, LLAssetType::AT_ANIMATION));
+ addEntry(LLInventoryType::IT_GESTURE, new InventoryEntry("gesture", "gesture", 1, LLAssetType::AT_GESTURE));
+}
+
+
// Maps asset types to the default inventory type for that kind of asset.
// Thus, "Lost and Found" is a "Category"
static const LLInventoryType::EType
@@ -107,7 +106,7 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] =
LLInventoryType::IT_OBJECT, // AT_OBJECT
LLInventoryType::IT_NOTECARD, // AT_NOTECARD
LLInventoryType::IT_CATEGORY, // AT_CATEGORY
- LLInventoryType::IT_ROOT_CATEGORY, // AT_ROOT_CATEGORY
+ LLInventoryType::IT_NONE, // (null entry)
LLInventoryType::IT_LSL, // AT_LSL_TEXT
LLInventoryType::IT_LSL, // AT_LSL_BYTECODE
LLInventoryType::IT_TEXTURE, // AT_TEXTURE_TGA
@@ -120,76 +119,34 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] =
LLInventoryType::IT_NONE, // AT_IMAGE_JPEG
LLInventoryType::IT_ANIMATION, // AT_ANIMATION
LLInventoryType::IT_GESTURE, // AT_GESTURE
-};
+ LLInventoryType::IT_NONE, // AT_SIMSTATE
-static const int MAX_POSSIBLE_ASSET_TYPES = 2;
-static const LLAssetType::EType
-INVENTORY_TO_ASSET_TYPE[LLInventoryType::IT_COUNT][MAX_POSSIBLE_ASSET_TYPES] =
-{
- { LLAssetType::AT_TEXTURE, LLAssetType::AT_NONE }, // IT_TEXTURE
- { LLAssetType::AT_SOUND, LLAssetType::AT_NONE }, // IT_SOUND
- { LLAssetType::AT_CALLINGCARD, LLAssetType::AT_NONE }, // IT_CALLINGCARD
- { LLAssetType::AT_LANDMARK, LLAssetType::AT_NONE }, // IT_LANDMARK
- { LLAssetType::AT_NONE, LLAssetType::AT_NONE },
- { LLAssetType::AT_NONE, LLAssetType::AT_NONE },
- { LLAssetType::AT_OBJECT, LLAssetType::AT_NONE }, // IT_OBJECT
- { LLAssetType::AT_NOTECARD, LLAssetType::AT_NONE }, // IT_NOTECARD
- { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, // IT_CATEGORY
- { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, // IT_ROOT_CATEGORY
- { LLAssetType::AT_LSL_TEXT, LLAssetType::AT_LSL_BYTECODE }, // IT_LSL
- { LLAssetType::AT_NONE, LLAssetType::AT_NONE },
- { LLAssetType::AT_NONE, LLAssetType::AT_NONE },
- { LLAssetType::AT_NONE, LLAssetType::AT_NONE },
- { LLAssetType::AT_NONE, LLAssetType::AT_NONE },
- { LLAssetType::AT_TEXTURE, LLAssetType::AT_NONE }, // IT_SNAPSHOT
- { LLAssetType::AT_NONE, LLAssetType::AT_NONE },
- { LLAssetType::AT_OBJECT, LLAssetType::AT_NONE }, // IT_ATTACHMENT
- { LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART }, // IT_WEARABLE
- { LLAssetType::AT_ANIMATION, LLAssetType::AT_NONE }, // IT_ANIMATION
- { LLAssetType::AT_GESTURE, LLAssetType::AT_NONE }, // IT_GESTURE
+ LLInventoryType::IT_NONE, // AT_LINK
+ LLInventoryType::IT_NONE, // AT_LINK_FOLDER
};
// static
-const char* LLInventoryType::lookup(EType type)
+const std::string &LLInventoryType::lookup(EType type)
{
- if((type >= 0) && (type < IT_COUNT))
- {
- return INVENTORY_TYPE_NAMES[S32(type)];
- }
- else
- {
- return NULL;
- }
+ const InventoryEntry *entry = LLInventoryDictionary::getInstance()->lookup(type);
+ if (!entry) return empty_string;
+ return entry->mName;
}
// static
LLInventoryType::EType LLInventoryType::lookup(const std::string& name)
{
- for(S32 i = 0; i < IT_COUNT; ++i)
- {
- if((INVENTORY_TYPE_NAMES[i])
- && (name == INVENTORY_TYPE_NAMES[i]))
- {
- // match
- return (EType)i;
- }
- }
- return IT_NONE;
+ return LLInventoryDictionary::getInstance()->lookup(name);
}
// XUI:translate
// translation from a type to a human readable form.
// static
-const char* LLInventoryType::lookupHumanReadable(EType type)
+const std::string &LLInventoryType::lookupHumanReadable(EType type)
{
- if((type >= 0) && (type < IT_COUNT))
- {
- return INVENTORY_TYPE_HUMAN_NAMES[S32(type)];
- }
- else
- {
- return NULL;
- }
+ const InventoryEntry *entry = LLInventoryDictionary::getInstance()->lookup(type);
+ if (!entry) return empty_string;
+ return entry->mHumanName;
}
// return the default inventory for the given asset type.
@@ -206,21 +163,36 @@ LLInventoryType::EType LLInventoryType::defaultForAssetType(LLAssetType::EType a
}
}
-bool inventory_and_asset_types_match(
- LLInventoryType::EType inventory_type,
- LLAssetType::EType asset_type)
+
+// add any types that we don't want the user to be able to change permissions on.
+// static
+bool LLInventoryType::cannotRestrictPermissions(LLInventoryType::EType type)
{
- bool rv = false;
- if((inventory_type >= 0) && (inventory_type < LLInventoryType::IT_COUNT))
+ switch(type)
+ {
+ case IT_CALLINGCARD:
+ case IT_LANDMARK:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool inventory_and_asset_types_match(LLInventoryType::EType inventory_type,
+ LLAssetType::EType asset_type)
+{
+ const InventoryEntry *entry = LLInventoryDictionary::getInstance()->lookup(inventory_type);
+ if (!entry) return false;
+
+ for (InventoryEntry::asset_vec_t::const_iterator iter = entry->mAssetTypes.begin();
+ iter != entry->mAssetTypes.end();
+ iter++)
{
- for(S32 i = 0; i < MAX_POSSIBLE_ASSET_TYPES; ++i)
+ const LLAssetType::EType type = (*iter);
+ if(type == asset_type)
{
- if(INVENTORY_TO_ASSET_TYPE[inventory_type][i] == asset_type)
- {
- rv = true;
- break;
- }
+ return true;
}
}
- return rv;
+ return false;
}
diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h
index d3effc0e6d..e515b8a304 100644
--- a/indra/llinventory/llinventorytype.h
+++ b/indra/llinventory/llinventorytype.h
@@ -74,25 +74,27 @@ public:
// machine transation between type and strings
static EType lookup(const std::string& name);
- static const char* lookup(EType type);
+ static const std::string &lookup(EType type);
// translation from a type to a human readable form.
- static const char* lookupHumanReadable(EType type);
+ static const std::string &lookupHumanReadable(EType type);
// return the default inventory for the given asset type.
static EType defaultForAssetType(LLAssetType::EType asset_type);
+ // true if this type cannot have restricted permissions.
+ static bool cannotRestrictPermissions(EType type);
+
private:
// don't instantiate or derive one of these objects
LLInventoryType( void );
~LLInventoryType( void );
};
-// helper function which returns true if inventory type and asset type
+// helper function that returns true if inventory type and asset type
// are potentially compatible. For example, an attachment must be an
// object, but a wearable can be a bodypart or clothing asset.
-bool inventory_and_asset_types_match(
- LLInventoryType::EType inventory_type,
- LLAssetType::EType asset_type);
+bool inventory_and_asset_types_match(LLInventoryType::EType inventory_type,
+ LLAssetType::EType asset_type);
#endif
diff --git a/indra/llinventory/lllandmark.cpp b/indra/llinventory/lllandmark.cpp
index 13a63bc7d6..83b6392ca8 100644
--- a/indra/llinventory/lllandmark.cpp
+++ b/indra/llinventory/lllandmark.cpp
@@ -40,7 +40,7 @@
std::pair<LLUUID, U64> LLLandmark::mLocalRegion;
LLLandmark::region_map_t LLLandmark::mRegions;
-LLLandmark::region_callback_t LLLandmark::mRegionCallback;
+LLLandmark::region_callback_map_t LLLandmark::sRegionCallbackMap;
LLLandmark::LLLandmark() :
mGlobalPositionKnown(false)
@@ -177,7 +177,7 @@ void LLLandmark::requestRegionHandle(
LLMessageSystem* msg,
const LLHost& upstream_host,
const LLUUID& region_id,
- LLRegionHandleCallback* callback)
+ region_handle_callback_t callback)
{
if(region_id.isNull())
{
@@ -186,7 +186,7 @@ void LLLandmark::requestRegionHandle(
if(callback)
{
const U64 U64_ZERO = 0;
- callback->dataReady(region_id, U64_ZERO);
+ callback(region_id, U64_ZERO);
}
}
else
@@ -196,7 +196,7 @@ void LLLandmark::requestRegionHandle(
lldebugs << "requestRegionHandle: local" << llendl;
if(callback)
{
- callback->dataReady(region_id, mLocalRegion.second);
+ callback(region_id, mLocalRegion.second);
}
}
else
@@ -207,8 +207,8 @@ void LLLandmark::requestRegionHandle(
lldebugs << "requestRegionHandle: upstream" << llendl;
if(callback)
{
- region_callback_t::value_type vt(region_id, callback);
- mRegionCallback.insert(vt);
+ region_callback_map_t::value_type vt(region_id, callback);
+ sRegionCallbackMap.insert(vt);
}
lldebugs << "Landmark requesting information about: "
<< region_id << llendl;
@@ -221,7 +221,7 @@ void LLLandmark::requestRegionHandle(
{
// we have the answer locally - just call the callack.
lldebugs << "requestRegionHandle: ready" << llendl;
- callback->dataReady(region_id, (*it).second.mRegionHandle);
+ callback(region_id, (*it).second.mRegionHandle);
}
}
}
@@ -259,11 +259,11 @@ void LLLandmark::processRegionIDAndHandle(LLMessageSystem* msg, void**)
#endif
// make all the callbacks here.
- region_callback_t::iterator it;
- while((it = mRegionCallback.find(region_id)) != mRegionCallback.end())
+ region_callback_map_t::iterator it;
+ while((it = sRegionCallbackMap.find(region_id)) != sRegionCallbackMap.end())
{
- (*it).second->dataReady(region_id, info.mRegionHandle);
- mRegionCallback.erase(it);
+ (*it).second(region_id, info.mRegionHandle);
+ sRegionCallbackMap.erase(it);
}
}
diff --git a/indra/llinventory/lllandmark.h b/indra/llinventory/lllandmark.h
index cb0c11ab87..feaf1a0e9c 100644
--- a/indra/llinventory/lllandmark.h
+++ b/indra/llinventory/lllandmark.h
@@ -35,6 +35,7 @@
#define LL_LLLANDMARK_H
#include <map>
+#include <boost/function.hpp>
#include "llframetimer.h"
#include "lluuid.h"
#include "v3dmath.h"
@@ -42,24 +43,12 @@
class LLMessageSystem;
class LLHost;
-// virutal base class used for calling back interested parties when a
-// region handle comes back.
-class LLRegionHandleCallback
-{
-public:
- LLRegionHandleCallback() {}
- virtual ~LLRegionHandleCallback() {}
- virtual bool dataReady(
- const LLUUID& region_id,
- const U64& region_handle)
- {
- return true;
- }
-};
-
class LLLandmark
{
public:
+ // for calling back interested parties when a region handle comes back.
+ typedef boost::function<void(const LLUUID& region_id, const U64& region_handle)> region_handle_callback_t;
+
~LLLandmark() {}
// returns true if the position is known.
@@ -90,7 +79,7 @@ public:
LLMessageSystem* msg,
const LLHost& upstream_host,
const LLUUID& region_id,
- LLRegionHandleCallback* callback);
+ region_handle_callback_t callback);
// Call this method to create a lookup for this region. This
// simplifies a lot of the code.
@@ -118,8 +107,8 @@ private:
static std::pair<LLUUID, U64> mLocalRegion;
typedef std::map<LLUUID, CacheInfo> region_map_t;
static region_map_t mRegions;
- typedef std::multimap<LLUUID, LLRegionHandleCallback*> region_callback_t;
- static region_callback_t mRegionCallback;
+ typedef std::multimap<LLUUID, region_handle_callback_t> region_callback_map_t;
+ static region_callback_map_t sRegionCallbackMap;
};
#endif
diff --git a/indra/llinventory/llnotecard.h b/indra/llinventory/llnotecard.h
index b903f1fdb0..092ab2ce35 100644
--- a/indra/llinventory/llnotecard.h
+++ b/indra/llinventory/llnotecard.h
@@ -33,7 +33,7 @@
#ifndef LL_NOTECARD_H
#define LL_NOTECARD_H
-#include "llmemory.h"
+#include "llpointer.h"
#include "llinventory.h"
class LLNotecard
diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp
index a0b27c788f..ec21ae40e7 100644
--- a/indra/llinventory/llparcel.cpp
+++ b/indra/llinventory/llparcel.cpp
@@ -43,7 +43,7 @@
#include "llsdutil.h"
#include "lltransactiontypes.h"
#include "lltransactionflags.h"
-#include "llsdutil.h"
+#include "llsdutil_math.h"
#include "message.h"
#include "u64.h"
@@ -85,13 +85,13 @@ static const std::string PARCEL_CATEGORY_UI_STRING[LLParcel::C_COUNT + 1] =
"None",
"Linden Location",
"Adult",
- "Arts & Culture",
+ "Arts and Culture",
"Business",
"Educational",
"Gaming",
"Hangout",
"Newcomer Friendly",
- "Parks & Nature",
+ "Parks and Nature",
"Residential",
"Shopping",
"Stage",
@@ -199,6 +199,12 @@ void LLParcel::init(const LLUUID &owner_id,
mObscureMusic = 1;
mMediaWidth = 0;
mMediaHeight = 0;
+ setMediaCurrentURL(LLStringUtil::null);
+ mMediaURLFilterEnable = FALSE;
+ mMediaURLFilterList = LLSD::emptyArray();
+ mMediaAllowNavigate = TRUE;
+ mMediaURLTimeout = 0.0f;
+ mMediaPreventCameraZoom = FALSE;
mGroupID.setNull();
@@ -314,6 +320,56 @@ void LLParcel::setMediaHeight(S32 height)
{
mMediaHeight = height;
}
+
+void LLParcel::setMediaCurrentURL(const std::string& url)
+{
+ mMediaCurrentURL = url;
+ // The escaping here must match the escaping in the database
+ // abstraction layer if it's ever added.
+ // This should really filter the url in some way. Other than
+ // simply requiring non-printable.
+ LLStringFn::replace_nonprintable_in_ascii(mMediaCurrentURL, LL_UNKNOWN_CHAR);
+
+}
+
+void LLParcel::setMediaURLResetTimer(F32 time)
+{
+ mMediaResetTimer.start();
+ mMediaResetTimer.setTimerExpirySec(time);
+}
+
+void LLParcel::setMediaURLFilterList(LLSD list)
+{
+ // sanity check LLSD
+ // must be array of strings
+ if (!list.isArray())
+ {
+ return;
+ }
+
+ for (S32 i = 0; i < list.size(); i++)
+ {
+ if (!list[i].isString())
+ return;
+ }
+
+ // can't be too big
+ const S32 MAX_SIZE = 50;
+ if (list.size() > MAX_SIZE)
+ {
+ LLSD new_list = LLSD::emptyArray();
+
+ for (S32 i = 0; i < llmin(list.size(), MAX_SIZE); i++)
+ {
+ new_list.append(list[i]);
+ }
+
+ list = new_list;
+ }
+
+ mMediaURLFilterList = list;
+}
+
// virtual
void LLParcel::setLocalID(S32 local_id)
{
@@ -568,6 +624,34 @@ BOOL LLParcel::importAccessEntry(std::istream& input_stream, LLAccessEntry* entr
return input_stream.good();
}
+BOOL LLParcel::importMediaURLFilter(std::istream& input_stream, std::string& url)
+{
+ skip_to_end_of_next_keyword("{", input_stream);
+
+ while(input_stream.good())
+ {
+ skip_comments_and_emptyspace(input_stream);
+ std::string line, keyword, value;
+ get_line(line, input_stream, MAX_STRING);
+ get_keyword_and_value(keyword, value, line);
+
+ if ("}" == keyword)
+ {
+ break;
+ }
+ else if ("url" == keyword)
+ {
+ url = value;
+ }
+ else
+ {
+ llwarns << "Unknown keyword in parcel media url filter section: <"
+ << keyword << ">" << llendl;
+ }
+ }
+ return input_stream.good();
+}
+
// Assumes we are in a block "ParcelData"
void LLParcel::packMessage(LLMessageSystem* msg)
{
@@ -593,6 +677,7 @@ void LLParcel::packMessage(LLMessageSystem* msg)
// Assumes we are in a block "ParcelData"
void LLParcel::packMessage(LLSD& msg)
{
+ // used in the viewer, the sim uses it's own packer
msg["local_id"] = getLocalID();
msg["parcel_flags"] = ll_sd_from_U32(getParcelFlags());
msg["sale_price"] = getSalePrice();
@@ -606,16 +691,21 @@ void LLParcel::packMessage(LLSD& msg)
msg["media_height"] = getMediaHeight();
msg["auto_scale"] = getMediaAutoScale();
msg["media_loop"] = getMediaLoop();
+ msg["media_current_url"] = getMediaCurrentURL();
msg["obscure_media"] = getObscureMedia();
msg["obscure_music"] = getObscureMusic();
msg["media_id"] = getMediaID();
+ msg["media_allow_navigate"] = getMediaAllowNavigate();
+ msg["media_prevent_camera_zoom"] = getMediaPreventCameraZoom();
+ msg["media_url_timeout"] = getMediaURLTimeout();
+ msg["media_url_filter_enable"] = getMediaURLFilterEnable();
+ msg["media_url_filter_list"] = getMediaURLFilterList();
msg["group_id"] = getGroupID();
msg["pass_price"] = mPassPrice;
msg["pass_hours"] = mPassHours;
msg["category"] = (U8)mCategory;
msg["auth_buyer_id"] = mAuthBuyerID;
msg["snapshot_id"] = mSnapshotID;
- msg["snapshot_id"] = mSnapshotID;
msg["user_location"] = ll_sd_from_vector3(mUserLocation);
msg["user_look_at"] = ll_sd_from_vector3(mUserLookAt);
msg["landing_type"] = (U8)mLandingType;
@@ -678,6 +768,21 @@ void LLParcel::unpackMessage(LLMessageSystem* msg)
mObscureMedia = true;
mObscureMusic = true;
}
+
+ if(msg->getNumberOfBlocks("MediaLinkSharing") > 0)
+ {
+ msg->getString("MediaLinkSharing", "MediaCurrentURL", buffer);
+ setMediaCurrentURL(buffer);
+ msg->getU8 ( "MediaLinkSharing", "MediaAllowNavigate", mMediaAllowNavigate );
+ msg->getU8 ( "MediaLinkSharing", "MediaURLFilterEnable", mMediaURLFilterEnable );
+ msg->getU8 ( "MediaLinkSharing", "MediaPreventCameraZoom", mMediaPreventCameraZoom );
+ msg->getF32( "MediaLinkSharing", "MediaURLTimeout", mMediaURLTimeout);
+ }
+ else
+ {
+ setMediaCurrentURL(LLStringUtil::null);
+ }
+
}
void LLParcel::packAccessEntries(LLMessageSystem* msg,
@@ -994,6 +1099,20 @@ BOOL LLParcel::isSaleTimerExpired(const U64& time)
return expired;
}
+BOOL LLParcel::isMediaResetTimerExpired(const U64& time)
+{
+ if (mMediaResetTimer.getStarted() == FALSE)
+ {
+ return FALSE;
+ }
+ BOOL expired = mMediaResetTimer.checkExpirationAndReset(0.0);
+ if (expired)
+ {
+ mMediaResetTimer.stop();
+ }
+ return expired;
+}
+
void LLParcel::startSale(const LLUUID& buyer_id, BOOL is_buyer_group)
{
@@ -1117,6 +1236,12 @@ void LLParcel::clearParcel()
mObscureMusic = 1;
mMediaWidth = 0;
mMediaHeight = 0;
+ setMediaCurrentURL(LLStringUtil::null);
+ setMediaURLFilterList(LLSD::emptyArray());
+ setMediaURLFilterEnable(FALSE);
+ setMediaAllowNavigate(TRUE);
+ setMediaPreventCameraZoom(FALSE);
+ setMediaURLTimeout(0.0f);
setMusicURL(LLStringUtil::null);
setInEscrow(FALSE);
setAuthorizedBuyerID(LLUUID::null);
diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h
index 40bbb7b2e0..2a9a596912 100644
--- a/indra/llinventory/llparcel.h
+++ b/indra/llinventory/llparcel.h
@@ -38,6 +38,7 @@
#include "lluuid.h"
#include "llparcelflags.h"
#include "llpermissions.h"
+#include "lltimer.h"
#include "v3math.h"
@@ -135,9 +136,9 @@ class LLSD;
class LLAccessEntry
{
public:
- LLUUID mID;
- S32 mTime;
- U32 mFlags;
+ LLUUID mID; // Agent ID
+ S32 mTime; // Time (unix seconds) when entry expires
+ U32 mFlags; // Not used - currently should always be zero
};
typedef std::map<LLUUID,LLAccessEntry>::iterator access_map_iterator;
@@ -247,6 +248,14 @@ public:
void setObscureMusic( U8 flagIn ) { mObscureMusic = flagIn; }
void setMediaWidth(S32 width);
void setMediaHeight(S32 height);
+ void setMediaCurrentURL(const std::string& url);
+ void setMediaURLFilterEnable(U8 enable) { mMediaURLFilterEnable = enable; }
+ void setMediaURLFilterList(LLSD list);
+ void setMediaAllowNavigate(U8 enable) { mMediaAllowNavigate = enable; }
+ void setMediaURLTimeout(F32 timeout) { mMediaURLTimeout = timeout; }
+ void setMediaPreventCameraZoom(U8 enable) { mMediaPreventCameraZoom = enable; }
+
+ void setMediaURLResetTimer(F32 time);
virtual void setLocalID(S32 local_id);
// blow away all the extra crap lurking in parcels, including urls, access lists, etc
@@ -299,7 +308,8 @@ public:
// BOOL importStream(std::istream& input_stream);
BOOL importAccessEntry(std::istream& input_stream, LLAccessEntry* entry);
-// BOOL exportStream(std::ostream& output_stream);
+ BOOL importMediaURLFilter(std::istream& input_stream, std::string& url);
+ // BOOL exportStream(std::ostream& output_stream);
void packMessage(LLMessageSystem* msg);
void packMessage(LLSD& msg);
@@ -341,8 +351,15 @@ public:
S32 getMediaHeight() const { return mMediaHeight; }
U8 getMediaAutoScale() const { return mMediaAutoScale; }
U8 getMediaLoop() const { return mMediaLoop; }
+ const std::string& getMediaCurrentURL() const { return mMediaCurrentURL; }
U8 getObscureMedia() const { return mObscureMedia; }
U8 getObscureMusic() const { return mObscureMusic; }
+ U8 getMediaURLFilterEnable() const { return mMediaURLFilterEnable; }
+ LLSD getMediaURLFilterList() const { return mMediaURLFilterList; }
+ U8 getMediaAllowNavigate() const { return mMediaAllowNavigate; }
+ F32 getMediaURLTimeout() const { return mMediaURLTimeout; }
+ U8 getMediaPreventCameraZoom() const { return mMediaPreventCameraZoom; }
+
S32 getLocalID() const { return mLocalID; }
const LLUUID& getOwnerID() const { return mOwnerID; }
const LLUUID& getGroupID() const { return mGroupID; }
@@ -413,6 +430,10 @@ public:
void completeSale(U32& type, U8& flags, LLUUID& to_id);
void clearSale();
+
+ BOOL isMediaResetTimerExpired(const U64& time);
+
+
// more accessors
U32 getParcelFlags() const { return mParcelFlags; }
@@ -446,8 +467,10 @@ public:
BOOL getAllowFly() const
{ return (mParcelFlags & PF_ALLOW_FLY) ? TRUE : FALSE; }
+ // Remove permission restrictions for creating landmarks.
+ // We should eventually remove this flag completely.
BOOL getAllowLandmark() const
- { return (mParcelFlags & PF_ALLOW_LANDMARK) ? TRUE : FALSE; }
+ { return TRUE; }
BOOL getAllowGroupScripts() const
{ return (mParcelFlags & PF_ALLOW_GROUP_SCRIPTS) ? TRUE : FALSE; }
@@ -589,6 +612,8 @@ protected:
LLVector3 mUserLookAt;
ELandingType mLandingType;
LLTimer mSaleTimerExpires;
+ LLTimer mMediaResetTimer;
+
S32 mGraceExtension;
// This value is non-zero if there is an auction associated with
@@ -616,9 +641,15 @@ protected:
S32 mMediaHeight;
U8 mMediaAutoScale;
U8 mMediaLoop;
+ std::string mMediaCurrentURL;
U8 mObscureMedia;
U8 mObscureMusic;
LLUUID mMediaID;
+ U8 mMediaURLFilterEnable;
+ LLSD mMediaURLFilterList;
+ U8 mMediaAllowNavigate;
+ U8 mMediaPreventCameraZoom;
+ F32 mMediaURLTimeout;
S32 mPassPrice;
F32 mPassHours;
LLVector3 mAABBMin;
@@ -648,6 +679,7 @@ public:
std::map<LLUUID,LLAccessEntry> mBanList;
std::map<LLUUID,LLAccessEntry> mTempBanList;
std::map<LLUUID,LLAccessEntry> mTempAccessList;
+
};
diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp
index 328ed4588b..d2e5034734 100644
--- a/indra/llinventory/llpermissions.cpp
+++ b/indra/llinventory/llpermissions.cpp
@@ -83,6 +83,17 @@ void LLPermissions::initMasks(PermissionMask base, PermissionMask owner,
fix();
}
+// ! BACKWARDS COMPATIBILITY ! Override masks for inventory types that
+// no longer can have restricted permissions. This takes care of previous
+// version landmarks that could have had no copy/mod/transfer bits set.
+void LLPermissions::initMasks(LLInventoryType::EType type)
+{
+ if (LLInventoryType::cannotRestrictPermissions(type))
+ {
+ initMasks(PERM_ALL, PERM_ALL, PERM_ALL, PERM_ALL, PERM_ALL);
+ }
+}
+
BOOL LLPermissions::getOwnership(LLUUID& owner_id, BOOL& is_group_owned) const
{
if(mOwner.notNull())
@@ -277,6 +288,17 @@ BOOL LLPermissions::setOwnerAndGroup(
return allowed;
}
+//Fix for DEV-33917, last owner isn't used much and has little impact on
+//permissions so it's reasonably safe to do this, however, for now,
+//limiting the functionality of this routine to objects which are
+//group owned.
+void LLPermissions::setLastOwner(const LLUUID& last_owner)
+{
+ if (isGroupOwned())
+ mLastOwner = last_owner;
+}
+
+
// only call this if you know what you're doing
// there are usually perm-bit consequences when the
// ownerhsip changes
@@ -831,67 +853,8 @@ BOOL LLPermissions::exportLegacyStream(std::ostream& output_stream) const
return TRUE;
}
-
-LLXMLNode *LLPermissions::exportFileXML() const
-{
- LLXMLNode *ret = new LLXMLNode("permissions", FALSE);
-
- ret->createChild("group_owned", TRUE)->setBoolValue(mIsGroupOwned);
-
- ret->createChild("base_mask", FALSE)->setByteValue(4, (U8*)&mMaskBase, LLXMLNode::ENCODING_HEX);
- ret->createChild("owner_mask", FALSE)->setByteValue(4, (U8*)&mMaskOwner, LLXMLNode::ENCODING_HEX);
- ret->createChild("group_mask", FALSE)->setByteValue(4, (U8*)&mMaskGroup, LLXMLNode::ENCODING_HEX);
- ret->createChild("everyone_mask", FALSE)->setByteValue(4, (U8*)&mMaskEveryone, LLXMLNode::ENCODING_HEX);
- ret->createChild("next_owner_mask", FALSE)->setByteValue(4, (U8*)&mMaskNextOwner, LLXMLNode::ENCODING_HEX);
-
- ret->createChild("creator_id", FALSE)->setUUIDValue(1, &mCreator);
- ret->createChild("owner_id", FALSE)->setUUIDValue(1, &mOwner);
- ret->createChild("last_owner_id", FALSE)->setUUIDValue(1, &mLastOwner);
- ret->createChild("group_id", FALSE)->setUUIDValue(1, &mGroup);
-
- return ret;
-}
-
-bool LLPermissions::importXML(LLXMLNode* node)
-{
- bool success = false;
- if (node)
- {
- success = true;
- LLXMLNodePtr sub_node;
- if (node->getChild("base_mask", sub_node))
- success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskBase));
- if (node->getChild("owner_mask", sub_node))
- success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskOwner));
- if (node->getChild("group_mask", sub_node))
- success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskGroup));
- if (node->getChild("everyone_mask", sub_node))
- success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskEveryone));
- if (node->getChild("next_owner_mask", sub_node))
- success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskNextOwner));
-
- if (node->getChild("creator_id", sub_node))
- success = success && (1 == sub_node->getUUIDValue(1, &mCreator));
- if (node->getChild("owner_id", sub_node))
- success = success && (1 == sub_node->getUUIDValue(1, &mOwner));
- if (node->getChild("last_owner_id", sub_node))
- success = success && (1 == sub_node->getUUIDValue(1, &mLastOwner));
- if (node->getChild("group_id", sub_node))
- success = success && (1 == sub_node->getUUIDValue(1, &mGroup));
- if (node->getChild("group_owned", sub_node))
- {
- BOOL tmpbool = FALSE;
- success = success && (1 == sub_node->getBoolValue(1, &tmpbool));
- mIsGroupOwned = (bool)tmpbool;
- }
- if (!success)
- {
- lldebugs << "LLPermissions::importXML() failed for node named '"
- << node->getName() << "'" << llendl;
- }
- }
- return success;
-}
+// Deleted LLPermissions::exportFileXML() and LLPermissions::importXML()
+// because I can't find any non-test code references to it. 2009-05-04 JC
bool LLPermissions::operator==(const LLPermissions &rhs) const
{
@@ -943,6 +906,8 @@ void LLMetaClassT<LLPermissions>::reflectProperties(LLMetaClass& meta_class)
{
reflectProperty(meta_class, "mCreator", &LLPermissions::mCreator);
reflectProperty(meta_class, "mOwner", &LLPermissions::mOwner);
+ reflectProperty(meta_class, "mGroup", &LLPermissions::mGroup);
+ reflectProperty(meta_class, "mIsGroupOwned", &LLPermissions::mIsGroupOwned);
}
// virtual
diff --git a/indra/llinventory/llpermissions.h b/indra/llinventory/llpermissions.h
index 5587f8c3c8..d5a0881c8f 100644
--- a/indra/llinventory/llpermissions.h
+++ b/indra/llinventory/llpermissions.h
@@ -38,6 +38,7 @@
#include "lluuid.h"
#include "llxmlnode.h"
#include "reflective.h"
+#include "llinventorytype.h"
// prototypes
class LLMessageSystem;
@@ -129,6 +130,8 @@ public:
void initMasks(PermissionMask base, PermissionMask owner,
PermissionMask everyone, PermissionMask group,
PermissionMask next);
+ // adjust permissions based on inventory type.
+ void initMasks(LLInventoryType::EType type);
//
// ACCESSORS
@@ -229,6 +232,10 @@ public:
// ownerhsip changes
void yesReallySetOwner(const LLUUID& owner, bool group_owned);
+ // Last owner doesn't have much in the way of permissions so it's
+ //not too dangerous to do this.
+ void setLastOwner(const LLUUID& last_owner);
+
// saves last owner, sets owner to uuid null, sets group
// owned. group_id must be the group of the object (that's who it
// is being deeded to) and the object must be group
@@ -249,7 +256,11 @@ public:
BOOL setGroupBits( const LLUUID& agent, const LLUUID& group, BOOL set, PermissionMask bits);
BOOL setEveryoneBits(const LLUUID& agent, const LLUUID& group, BOOL set, PermissionMask bits);
BOOL setNextOwnerBits(const LLUUID& agent, const LLUUID& group, BOOL set, PermissionMask bits);
-
+
+ // This is currently only used in the Viewer to handle calling cards
+ // where the creator is actually used to store the target. Use with care.
+ void setCreator(const LLUUID& creator) { mCreator = creator; }
+
//
// METHODS
//
@@ -314,9 +325,6 @@ public:
BOOL importLegacyStream(std::istream& input_stream);
BOOL exportLegacyStream(std::ostream& output_stream) const;
- LLXMLNode *exportFileXML() const;
- bool importXML(LLXMLNode* node);
-
bool operator==(const LLPermissions &rhs) const;
bool operator!=(const LLPermissions &rhs) const;
diff --git a/indra/llinventory/llpermissionsflags.h b/indra/llinventory/llpermissionsflags.h
index afa2adbd90..f810929d68 100644
--- a/indra/llinventory/llpermissionsflags.h
+++ b/indra/llinventory/llpermissionsflags.h
@@ -32,9 +32,6 @@
#ifndef LL_LLPERMISSIONSFLAGS_H
#define LL_LLPERMISSIONSFLAGS_H
-// llpermissionsflags.h
-// Copyright 2002, Linden Research, Inc.
-//
// Flags for various permissions bits.
// Shared between viewer and simulator.
diff --git a/indra/llinventory/llsaleinfo.cpp b/indra/llinventory/llsaleinfo.cpp
index b7afb28adf..930901f309 100644
--- a/indra/llinventory/llsaleinfo.cpp
+++ b/indra/llinventory/llsaleinfo.cpp
@@ -135,38 +135,8 @@ bool LLSaleInfo::fromLLSD(const LLSD& sd, BOOL& has_perm_mask, U32& perm_mask)
return true;
}
-LLXMLNode *LLSaleInfo::exportFileXML() const
-{
- LLXMLNode *ret = new LLXMLNode("sale_info", FALSE);
- std::string type_str = ll_safe_string( lookup(mSaleType));
- ret->createChild("type", TRUE)->setStringValue(1, &type_str);
- ret->createChild("price", TRUE)->setIntValue(1, &mSalePrice);
- return ret;
-}
-
-BOOL LLSaleInfo::importXML(LLXMLNode* node)
-{
- BOOL success = FALSE;
- if (node)
- {
- success = TRUE;
- LLXMLNodePtr sub_node;
- if (node->getChild("type", sub_node))
- {
- mSaleType = lookup(sub_node->getValue().c_str());
- }
- if (node->getChild("price", sub_node))
- {
- success &= (1 == sub_node->getIntValue(1, &mSalePrice));
- }
- if (!success)
- {
- lldebugs << "LLSaleInfo::importXML() failed for node named '"
- << node->getName() << "'" << llendl;
- }
- }
- return success;
-}
+// Deleted LLSaleInfo::exportFileXML() and LLSaleInfo::importXML()
+// because I can't find any non-test code references to it. 2009-05-04 JC
BOOL LLSaleInfo::importFile(LLFILE* fp, BOOL& has_perm_mask, U32& perm_mask)
{
diff --git a/indra/llinventory/llsaleinfo.h b/indra/llinventory/llsaleinfo.h
index d546c49fd7..3461a128be 100644
--- a/indra/llinventory/llsaleinfo.h
+++ b/indra/llinventory/llsaleinfo.h
@@ -101,9 +101,6 @@ public:
bool fromLLSD(const LLSD& sd, BOOL& has_perm_mask, U32& perm_mask);
BOOL importLegacyStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask);
- LLXMLNode *exportFileXML() const;
- BOOL importXML(LLXMLNode* node);
-
LLSD packMessage() const;
void unpackMessage(LLSD sales);
diff --git a/indra/llinventory/lltransactiontypes.h b/indra/llinventory/lltransactiontypes.h
index 1cb7308bd4..2c699bcb87 100644
--- a/indra/llinventory/lltransactiontypes.h
+++ b/indra/llinventory/lltransactiontypes.h
@@ -69,6 +69,12 @@ const S32 TRANS_PARCEL_DIR_FEE = 2003;
const S32 TRANS_GROUP_TAX = 2004; // Taxes incurred as part of group membership
const S32 TRANS_CLASSIFIED_RENEW = 2005;
+// Codes 2100-2999 reserved for recurring billing services
+// New codes can be created through an admin interface so may not
+// automatically end up in the list below :-(
+// So make sure you check the transaction_description table
+const S32 TRANS_RECURRING_GENERIC = 2100;
+
// Codes 3000-3999 reserved for inventory transactions
const S32 TRANS_GIVE_INVENTORY = 3000;
@@ -84,6 +90,12 @@ const S32 TRANS_DWELL_BONUS = 5007;
const S32 TRANS_PAY_OBJECT = 5008;
const S32 TRANS_OBJECT_PAYS = 5009;
+// Codes 5100-5999 reserved for recurring billing transfers between users
+// New codes can be created through an admin interface so may not
+// automatically end up in the list below :-(
+// So make sure you check the transaction_description table
+const S32 TRANS_RECURRING_GENERIC_USER = 5100;
+
// Codes 6000-6999 reserved for group transactions
//const S32 TRANS_GROUP_JOIN = 6000; //reserved for future use
const S32 TRANS_GROUP_LAND_DEED = 6001;
diff --git a/indra/llinventory/tests/inventorymisc_test.cpp b/indra/llinventory/tests/inventorymisc_test.cpp
new file mode 100644
index 0000000000..c797a70c50
--- /dev/null
+++ b/indra/llinventory/tests/inventorymisc_test.cpp
@@ -0,0 +1,514 @@
+/**
+ * @file inventory.cpp
+ * @author Phoenix
+ * @date 2005-11-15
+ * @brief Functions for inventory test framework
+ *
+ * $LicenseInfo:firstyear=2005&license=viewergpl$
+ *
+ * Copyright (c) 2005-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llsd.h"
+
+#include "../llinventory.h"
+
+#include "../test/lltut.h"
+
+
+#if LL_WINDOWS
+// disable unreachable code warnings
+#pragma warning(disable: 4702)
+#endif
+
+LLPointer<LLInventoryItem> create_random_inventory_item()
+{
+ LLUUID item_id;
+ item_id.generate();
+ LLUUID parent_id;
+ parent_id.generate();
+ LLPermissions perm;
+ LLUUID creator_id;
+ creator_id.generate();
+ LLUUID owner_id;
+ owner_id.generate();
+ LLUUID last_owner_id;
+ last_owner_id.generate();
+ LLUUID group_id;
+ group_id.generate();
+ perm.init(creator_id, owner_id, last_owner_id, group_id);
+ perm.initMasks(PERM_ALL, PERM_ALL, PERM_COPY, PERM_COPY, PERM_MODIFY | PERM_COPY);
+ LLUUID asset_id;
+ asset_id.generate();
+ S32 price = rand();
+ LLSaleInfo sale_info(LLSaleInfo::FS_COPY, price);
+ U32 flags = rand();
+ S32 creation = time(NULL);
+
+ LLPointer<LLInventoryItem> item = new LLInventoryItem(
+ item_id,
+ parent_id,
+ perm,
+ asset_id,
+ LLAssetType::AT_OBJECT,
+ LLInventoryType::IT_ATTACHMENT,
+ std::string("Sample Object"),
+ std::string("Used for Testing"),
+ sale_info,
+ flags,
+ creation);
+ return item;
+}
+
+LLPointer<LLInventoryCategory> create_random_inventory_cat()
+{
+ LLUUID item_id;
+ item_id.generate();
+ LLUUID parent_id;
+ parent_id.generate();
+
+ LLPointer<LLInventoryCategory> cat = new LLInventoryCategory(
+ item_id,
+ parent_id,
+ LLFolderType::FT_NONE,
+ std::string("Sample category"));
+ return cat;
+}
+
+namespace tut
+{
+ struct inventory_data
+ {
+ };
+ typedef test_group<inventory_data> inventory_test;
+ typedef inventory_test::object inventory_object;
+ tut::inventory_test inv("llinventory");
+
+//***class LLInventoryType***//
+
+
+ template<> template<>
+ void inventory_object::test<1>()
+ {
+ LLInventoryType::EType retType = LLInventoryType::lookup(std::string("sound"));
+ ensure("1.LLInventoryType::lookup(char*) failed", retType == LLInventoryType::IT_SOUND);
+
+ retType = LLInventoryType::lookup(std::string("snapshot"));
+ ensure("2.LLInventoryType::lookup(char*) failed", retType == LLInventoryType::IT_SNAPSHOT);
+ }
+
+ template<> template<>
+ void inventory_object::test<2>()
+ {
+ static std::string retType = LLInventoryType::lookup(LLInventoryType::IT_CALLINGCARD);
+ ensure("1.LLInventoryType::lookup(EType) failed", (retType == "callcard"));
+
+ retType = LLInventoryType::lookup(LLInventoryType::IT_LANDMARK);
+ ensure("2.LLInventoryType::lookup(EType) failed", (retType == "landmark"));
+
+ }
+
+ template<> template<>
+ void inventory_object::test<3>()
+ {
+ static std::string retType = LLInventoryType::lookupHumanReadable(LLInventoryType::IT_CALLINGCARD);
+ ensure("1.LLInventoryType::lookupHumanReadable(EType) failed", (retType == "calling card"));
+
+ retType = LLInventoryType::lookupHumanReadable(LLInventoryType::IT_LANDMARK);
+ ensure("2.LLInventoryType::lookupHumanReadable(EType) failed", (retType == "landmark"));
+ }
+
+ template<> template<>
+ void inventory_object::test<4>()
+ {
+ static LLInventoryType::EType retType = LLInventoryType::defaultForAssetType(LLAssetType::AT_TEXTURE);
+ ensure("1.LLInventoryType::defaultForAssetType(LLAssetType EType) failed", retType == LLInventoryType::IT_TEXTURE);
+
+ retType = LLInventoryType::defaultForAssetType(LLAssetType::AT_LANDMARK);
+ ensure("2.LLInventoryType::defaultForAssetType(LLAssetType EType) failed", retType == LLInventoryType::IT_LANDMARK);
+ }
+
+//*****class LLInventoryItem*****//
+
+ template<> template<>
+ void inventory_object::test<5>()
+ {
+ LLPointer<LLInventoryItem> src = create_random_inventory_item();
+ LLSD sd = ll_create_sd_from_inventory_item(src);
+ //llinfos << "sd: " << *sd << llendl;
+ LLPointer<LLInventoryItem> dst = new LLInventoryItem;
+ bool successful_parse = dst->fromLLSD(sd);
+ ensure_equals("0.LLInventoryItem::fromLLSD()", successful_parse, true);
+ ensure_equals("1.item id::getUUID() failed", dst->getUUID(), src->getUUID());
+ ensure_equals("2.parent::getParentUUID() failed", dst->getParentUUID(), src->getParentUUID());
+ ensure_equals("3.name::getName() failed", dst->getName(), src->getName());
+ ensure_equals("4.type::getType() failed", dst->getType(), src->getType());
+
+ ensure_equals("5.permissions::getPermissions() failed", dst->getPermissions(), src->getPermissions());
+ ensure_equals("6.description::getDescription() failed", dst->getDescription(), src->getDescription());
+ ensure_equals("7.sale type::getSaleType() failed", dst->getSaleInfo().getSaleType(), src->getSaleInfo().getSaleType());
+ ensure_equals("8.sale price::getSalePrice() failed", dst->getSaleInfo().getSalePrice(), src->getSaleInfo().getSalePrice());
+ ensure_equals("9.asset id::getAssetUUID() failed", dst->getAssetUUID(), src->getAssetUUID());
+ ensure_equals("10.inventory type::getInventoryType() failed", dst->getInventoryType(), src->getInventoryType());
+ ensure_equals("11.flags::getFlags() failed", dst->getFlags(), src->getFlags());
+ ensure_equals("12.creation::getCreationDate() failed", dst->getCreationDate(), src->getCreationDate());
+
+ LLUUID new_item_id, new_parent_id;
+ new_item_id.generate();
+ src->setUUID(new_item_id);
+
+ new_parent_id.generate();
+ src->setParent(new_parent_id);
+
+ std::string new_name = "LindenLab";
+ src->rename(new_name);
+
+ src->setType(LLAssetType::AT_SOUND);
+
+ LLUUID new_asset_id;
+ new_asset_id.generate();
+
+ src->setAssetUUID(new_asset_id);
+ std::string new_desc = "SecondLife Testing";
+ src->setDescription(new_desc);
+
+ S32 new_price = rand();
+ LLSaleInfo new_sale_info(LLSaleInfo::FS_COPY, new_price);
+ src->setSaleInfo(new_sale_info);
+
+ U32 new_flags = rand();
+ S32 new_creation = time(NULL);
+
+ LLPermissions new_perm;
+
+ LLUUID new_creator_id;
+ new_creator_id.generate();
+
+ LLUUID new_owner_id;
+ new_owner_id.generate();
+
+ LLUUID last_owner_id;
+ last_owner_id.generate();
+
+ LLUUID new_group_id;
+ new_group_id.generate();
+ new_perm.init(new_creator_id, new_owner_id, last_owner_id, new_group_id);
+ new_perm.initMasks(PERM_ALL, PERM_ALL, PERM_COPY, PERM_COPY, PERM_MODIFY | PERM_COPY);
+ src->setPermissions(new_perm);
+
+ src->setInventoryType(LLInventoryType::IT_SOUND);
+ src->setFlags(new_flags);
+ src->setCreationDate(new_creation);
+
+ sd = ll_create_sd_from_inventory_item(src);
+ //llinfos << "sd: " << *sd << llendl;
+ successful_parse = dst->fromLLSD(sd);
+ ensure_equals("13.item id::getUUID() failed", dst->getUUID(), src->getUUID());
+ ensure_equals("14.parent::getParentUUID() failed", dst->getParentUUID(), src->getParentUUID());
+ ensure_equals("15.name::getName() failed", dst->getName(), src->getName());
+ ensure_equals("16.type::getType() failed", dst->getType(), src->getType());
+
+ ensure_equals("17.permissions::getPermissions() failed", dst->getPermissions(), src->getPermissions());
+ ensure_equals("18.description::getDescription() failed", dst->getDescription(), src->getDescription());
+ ensure_equals("19.sale type::getSaleType() failed type", dst->getSaleInfo().getSaleType(), src->getSaleInfo().getSaleType());
+ ensure_equals("20.sale price::getSalePrice() failed price", dst->getSaleInfo().getSalePrice(), src->getSaleInfo().getSalePrice());
+ ensure_equals("21.asset id::getAssetUUID() failed id", dst->getAssetUUID(), src->getAssetUUID());
+ ensure_equals("22.inventory type::getInventoryType() failed type", dst->getInventoryType(), src->getInventoryType());
+ ensure_equals("23.flags::getFlags() failed", dst->getFlags(), src->getFlags());
+ ensure_equals("24.creation::getCreationDate() failed", dst->getCreationDate(), src->getCreationDate());
+
+ }
+
+ template<> template<>
+ void inventory_object::test<6>()
+ {
+ LLPointer<LLInventoryItem> src = create_random_inventory_item();
+
+ LLUUID new_item_id, new_parent_id;
+ new_item_id.generate();
+ src->setUUID(new_item_id);
+
+ new_parent_id.generate();
+ src->setParent(new_parent_id);
+
+ std::string new_name = "LindenLab";
+ src->rename(new_name);
+
+ src->setType(LLAssetType::AT_SOUND);
+
+ LLUUID new_asset_id;
+ new_asset_id.generate();
+
+ src->setAssetUUID(new_asset_id);
+ std::string new_desc = "SecondLife Testing";
+ src->setDescription(new_desc);
+
+ S32 new_price = rand();
+ LLSaleInfo new_sale_info(LLSaleInfo::FS_COPY, new_price);
+ src->setSaleInfo(new_sale_info);
+
+ U32 new_flags = rand();
+ S32 new_creation = time(NULL);
+
+ LLPermissions new_perm;
+
+ LLUUID new_creator_id;
+ new_creator_id.generate();
+
+ LLUUID new_owner_id;
+ new_owner_id.generate();
+
+ LLUUID last_owner_id;
+ last_owner_id.generate();
+
+ LLUUID new_group_id;
+ new_group_id.generate();
+ new_perm.init(new_creator_id, new_owner_id, last_owner_id, new_group_id);
+ new_perm.initMasks(PERM_ALL, PERM_ALL, PERM_COPY, PERM_COPY, PERM_MODIFY | PERM_COPY);
+ src->setPermissions(new_perm);
+
+ src->setInventoryType(LLInventoryType::IT_SOUND);
+ src->setFlags(new_flags);
+ src->setCreationDate(new_creation);
+
+ // test a save/load cycle to LLSD and back again
+ LLSD sd = ll_create_sd_from_inventory_item(src);
+ LLPointer<LLInventoryItem> dst = new LLInventoryItem;
+ bool successful_parse = dst->fromLLSD(sd);
+ ensure_equals("0.LLInventoryItem::fromLLSD()", successful_parse, true);
+
+ LLPointer<LLInventoryItem> src1 = create_random_inventory_item();
+ src1->copyItem(src);
+
+ ensure_equals("1.item id::getUUID() failed", dst->getUUID(), src1->getUUID());
+ ensure_equals("2.parent::getParentUUID() failed", dst->getParentUUID(), src1->getParentUUID());
+ ensure_equals("3.name::getName() failed", dst->getName(), src1->getName());
+ ensure_equals("4.type::getType() failed", dst->getType(), src1->getType());
+
+ ensure_equals("5.permissions::getPermissions() failed", dst->getPermissions(), src1->getPermissions());
+ ensure_equals("6.description::getDescription() failed", dst->getDescription(), src1->getDescription());
+ ensure_equals("7.sale type::getSaleType() failed type", dst->getSaleInfo().getSaleType(), src1->getSaleInfo().getSaleType());
+ ensure_equals("8.sale price::getSalePrice() failed price", dst->getSaleInfo().getSalePrice(), src1->getSaleInfo().getSalePrice());
+ ensure_equals("9.asset id::getAssetUUID() failed id", dst->getAssetUUID(), src1->getAssetUUID());
+ ensure_equals("10.inventory type::getInventoryType() failed type", dst->getInventoryType(), src1->getInventoryType());
+ ensure_equals("11.flags::getFlags() failed", dst->getFlags(), src1->getFlags());
+ ensure_equals("12.creation::getCreationDate() failed", dst->getCreationDate(), src1->getCreationDate());
+
+ // quick test to make sure generateUUID() really works
+ src1->generateUUID();
+ ensure_not_equals("13.item id::generateUUID() failed", src->getUUID(), src1->getUUID());
+ }
+
+ template<> template<>
+ void inventory_object::test<7>()
+ {
+ LLFILE* fp = LLFile::fopen("linden_file.dat","w+");
+ if(!fp)
+ {
+ llerrs << "file could not be opened\n" << llendl;
+ return;
+ }
+
+ LLPointer<LLInventoryItem> src1 = create_random_inventory_item();
+ src1->exportFile(fp, TRUE);
+ fclose(fp);
+
+ LLPointer<LLInventoryItem> src2 = new LLInventoryItem();
+ fp = LLFile::fopen("linden_file.dat","r+");
+ if(!fp)
+ {
+ llerrs << "file could not be opened\n" << llendl;
+ return;
+ }
+
+ src2->importFile(fp);
+ fclose(fp);
+
+ ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID());
+ ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID());
+ ensure_equals("3.permissions::getPermissions() failed", src1->getPermissions(), src2->getPermissions());
+ ensure_equals("4.sale price::getSalePrice() failed price", src1->getSaleInfo().getSalePrice(), src2->getSaleInfo().getSalePrice());
+ ensure_equals("5.asset id::getAssetUUID() failed id", src1->getAssetUUID(), src2->getAssetUUID());
+ ensure_equals("6.type::getType() failed", src1->getType(), src2->getType());
+ ensure_equals("7.inventory type::getInventoryType() failed type", src1->getInventoryType(), src2->getInventoryType());
+ ensure_equals("8.name::getName() failed", src1->getName(), src2->getName());
+ ensure_equals("9.description::getDescription() failed", src1->getDescription(), src2->getDescription());
+ ensure_equals("10.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate());
+
+ }
+
+ template<> template<>
+ void inventory_object::test<8>()
+ {
+
+ LLPointer<LLInventoryItem> src1 = create_random_inventory_item();
+
+ std::ostringstream ostream;
+ src1->exportLegacyStream(ostream, TRUE);
+
+ std::istringstream istream(ostream.str());
+ LLPointer<LLInventoryItem> src2 = new LLInventoryItem();
+ src2->importLegacyStream(istream);
+
+ ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID());
+ ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID());
+ ensure_equals("3.permissions::getPermissions() failed", src1->getPermissions(), src2->getPermissions());
+ ensure_equals("4.sale price::getSalePrice() failed price", src1->getSaleInfo().getSalePrice(), src2->getSaleInfo().getSalePrice());
+ ensure_equals("5.asset id::getAssetUUID() failed id", src1->getAssetUUID(), src2->getAssetUUID());
+ ensure_equals("6.type::getType() failed", src1->getType(), src2->getType());
+ ensure_equals("7.inventory type::getInventoryType() failed type", src1->getInventoryType(), src2->getInventoryType());
+ ensure_equals("8.name::getName() failed", src1->getName(), src2->getName());
+ ensure_equals("9.description::getDescription() failed", src1->getDescription(), src2->getDescription());
+ ensure_equals("10.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate());
+
+
+ }
+
+ template<> template<>
+ void inventory_object::test<9>()
+ {
+ // Deleted LLInventoryItem::exportFileXML() and LLInventoryItem::importXML()
+ // because I can't find any non-test code references to it. 2009-05-04 JC
+ }
+
+ template<> template<>
+ void inventory_object::test<10>()
+ {
+ LLPointer<LLInventoryItem> src1 = create_random_inventory_item();
+ U8* bin_bucket = new U8[300];
+ S32 bin_bucket_size = src1->packBinaryBucket(bin_bucket, NULL);
+
+ LLPointer<LLInventoryItem> src2 = new LLInventoryItem();
+ src2->unpackBinaryBucket(bin_bucket, bin_bucket_size);
+
+ ensure_equals("1.sale price::getSalePrice() failed price", src1->getSaleInfo().getSalePrice(), src2->getSaleInfo().getSalePrice());
+ ensure_equals("2.sale type::getSaleType() failed type", src1->getSaleInfo().getSaleType(), src2->getSaleInfo().getSaleType());
+ ensure_equals("3.type::getType() failed", src1->getType(), src2->getType());
+ ensure_equals("4.inventory type::getInventoryType() failed type", src1->getInventoryType(), src2->getInventoryType());
+ ensure_equals("5.name::getName() failed", src1->getName(), src2->getName());
+ ensure_equals("6.description::getDescription() failed", src1->getDescription(), src2->getDescription());
+ ensure_equals("7.flags::getFlags() failed", src1->getFlags(), src2->getFlags());
+
+ }
+
+ template<> template<>
+ void inventory_object::test<11>()
+ {
+ LLPointer<LLInventoryItem> src1 = create_random_inventory_item();
+ LLSD retSd = src1->asLLSD();
+ LLPointer<LLInventoryItem> src2 = new LLInventoryItem();
+ src2->fromLLSD(retSd);
+
+ ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID());
+ ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID());
+ ensure_equals("3.permissions::getPermissions() failed", src1->getPermissions(), src2->getPermissions());
+ ensure_equals("4.asset id::getAssetUUID() failed id", src1->getAssetUUID(), src2->getAssetUUID());
+ ensure_equals("5.type::getType() failed", src1->getType(), src2->getType());
+ ensure_equals("6.inventory type::getInventoryType() failed type", src1->getInventoryType(), src2->getInventoryType());
+ ensure_equals("7.flags::getFlags() failed", src1->getFlags(), src2->getFlags());
+ ensure_equals("8.sale type::getSaleType() failed type", src1->getSaleInfo().getSaleType(), src2->getSaleInfo().getSaleType());
+ ensure_equals("9.sale price::getSalePrice() failed price", src1->getSaleInfo().getSalePrice(), src2->getSaleInfo().getSalePrice());
+ ensure_equals("10.name::getName() failed", src1->getName(), src2->getName());
+ ensure_equals("11.description::getDescription() failed", src1->getDescription(), src2->getDescription());
+ ensure_equals("12.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate());
+ }
+
+//******class LLInventoryCategory*******//
+
+ template<> template<>
+ void inventory_object::test<12>()
+ {
+ LLPointer<LLInventoryCategory> src = create_random_inventory_cat();
+ LLSD sd = ll_create_sd_from_inventory_category(src);
+ LLPointer<LLInventoryCategory> dst = ll_create_category_from_sd(sd);
+
+ ensure_equals("1.item id::getUUID() failed", dst->getUUID(), src->getUUID());
+ ensure_equals("2.parent::getParentUUID() failed", dst->getParentUUID(), src->getParentUUID());
+ ensure_equals("3.name::getName() failed", dst->getName(), src->getName());
+ ensure_equals("4.type::getType() failed", dst->getType(), src->getType());
+ ensure_equals("5.preferred type::getPreferredType() failed", dst->getPreferredType(), src->getPreferredType());
+
+ src->setPreferredType( LLFolderType::FT_TEXTURE);
+ sd = ll_create_sd_from_inventory_category(src);
+ dst = ll_create_category_from_sd(sd);
+ ensure_equals("6.preferred type::getPreferredType() failed", dst->getPreferredType(), src->getPreferredType());
+
+
+ }
+
+ template<> template<>
+ void inventory_object::test<13>()
+ {
+ LLFILE* fp = LLFile::fopen("linden_file.dat","w");
+ if(!fp)
+ {
+ llerrs << "file coudnt be opened\n" << llendl;
+ return;
+ }
+
+ LLPointer<LLInventoryCategory> src1 = create_random_inventory_cat();
+ src1->exportFile(fp, TRUE);
+ fclose(fp);
+
+ LLPointer<LLInventoryCategory> src2 = new LLInventoryCategory();
+ fp = LLFile::fopen("linden_file.dat","r");
+ if(!fp)
+ {
+ llerrs << "file coudnt be opened\n" << llendl;
+ return;
+ }
+
+ src2->importFile(fp);
+ fclose(fp);
+
+ ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID());
+ ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID());
+ ensure_equals("3.type::getType() failed", src1->getType(), src2->getType());
+ ensure_equals("4.preferred type::getPreferredType() failed", src1->getPreferredType(), src2->getPreferredType());
+ ensure_equals("5.name::getName() failed", src1->getName(), src2->getName());
+ }
+
+ template<> template<>
+ void inventory_object::test<14>()
+ {
+ LLPointer<LLInventoryCategory> src1 = create_random_inventory_cat();
+
+ std::ostringstream ostream;
+ src1->exportLegacyStream(ostream, TRUE);
+
+ std::istringstream istream(ostream.str());
+ LLPointer<LLInventoryCategory> src2 = new LLInventoryCategory();
+ src2->importLegacyStream(istream);
+
+ ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID());
+ ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID());
+ ensure_equals("3.type::getType() failed", src1->getType(), src2->getType());
+ ensure_equals("4.preferred type::getPreferredType() failed", src1->getPreferredType(), src2->getPreferredType());
+ ensure_equals("5.name::getName() failed", src1->getName(), src2->getName());
+
+ }
+}
diff --git a/indra/llinventory/tests/llparcel_test.cpp b/indra/llinventory/tests/llparcel_test.cpp
new file mode 100644
index 0000000000..cb762eec3c
--- /dev/null
+++ b/indra/llinventory/tests/llparcel_test.cpp
@@ -0,0 +1,75 @@
+/**
+ * @file llinventoryparcel_tut.cpp
+ * @author Moss
+ * @date 2007-04-17
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include <string>
+
+#include "linden_common.h"
+
+#include "../llparcel.h"
+
+#include "../test/lltut.h"
+
+namespace tut
+{
+ struct llinventoryparcel_data
+ {
+ };
+ typedef test_group<llinventoryparcel_data> llinventoryparcel_test;
+ typedef llinventoryparcel_test::object llinventoryparcel_object;
+ tut::llinventoryparcel_test llinventoryparcel("llinventoryparcel");
+
+ template<> template<>
+ void llinventoryparcel_object::test<1>()
+ {
+ for (S32 i=0; i<LLParcel::C_COUNT; ++i)
+ {
+ const std::string& catstring = LLParcel::getCategoryString(LLParcel::ECategory(i));
+ ensure("LLParcel::getCategoryString(i)",
+ !catstring.empty());
+
+ const std::string& catuistring = LLParcel::getCategoryUIString(LLParcel::ECategory(i));
+ ensure("LLParcel::getCategoryUIString(i)",
+ !catuistring.empty());
+
+ ensure_equals("LLParcel::ECategory mapping of string back to enum", LLParcel::getCategoryFromString(catstring), i);
+ ensure_equals("LLParcel::ECategory mapping of uistring back to enum", LLParcel::getCategoryFromUIString(catuistring), i);
+ }
+
+ // test the C_ANY case, which has to work for UI strings
+ const std::string& catuistring = LLParcel::getCategoryUIString(LLParcel::C_ANY);
+ ensure("LLParcel::getCategoryUIString(C_ANY)",
+ !catuistring.empty());
+
+ ensure_equals("LLParcel::ECategory mapping of uistring back to enum", LLParcel::getCategoryFromUIString(catuistring), LLParcel::C_ANY);
+ }
+}
diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt
index 6a329fabb6..e93fe90650 100644
--- a/indra/llmath/CMakeLists.txt
+++ b/indra/llmath/CMakeLists.txt
@@ -10,10 +10,12 @@ include_directories(
)
set(llmath_SOURCE_FILES
+ llbbox.cpp
llbboxlocal.cpp
llcamera.cpp
llcoordframe.cpp
llline.cpp
+ llmodularmath.cpp
llperlin.cpp
llquaternion.cpp
llrect.cpp
@@ -39,6 +41,7 @@ set(llmath_HEADER_FILES
camera.h
coordframe.h
+ llbbox.h
llbboxlocal.h
llcamera.h
llcoord.h
@@ -46,6 +49,7 @@ set(llmath_HEADER_FILES
llinterp.h
llline.h
llmath.h
+ llmodularmath.h
lloctree.h
llperlin.h
llplane.h
@@ -60,6 +64,7 @@ set(llmath_HEADER_FILES
llv4vector3.h
llvolume.h
llvolumemgr.h
+ llsdutil_math.h
m3math.h
m4math.h
raytrace.h
@@ -79,3 +84,31 @@ set_source_files_properties(${llmath_HEADER_FILES}
list(APPEND llmath_SOURCE_FILES ${llmath_HEADER_FILES})
add_library (llmath ${llmath_SOURCE_FILES})
+
+# Add tests
+if (LL_TESTS)
+ include(LLAddBuildTest)
+ # UNIT TESTS
+ SET(llmath_TEST_SOURCE_FILES
+ llbboxlocal.cpp
+ llmodularmath.cpp
+ llrect.cpp
+ v2math.cpp
+ v3color.cpp
+ v4color.cpp
+ v4coloru.cpp
+ )
+ LL_ADD_PROJECT_UNIT_TESTS(llmath "${llmath_TEST_SOURCE_FILES}")
+
+ # INTEGRATION TESTS
+ set(test_libs llmath llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
+ # TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests.
+ LL_ADD_INTEGRATION_TEST(llbbox llbbox.cpp "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(llquaternion llquaternion.cpp "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(mathmisc "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(m3math "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(v3dmath v3dmath.cpp "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(v3math v3math.cpp "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(v4math v4math.cpp "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(xform xform.cpp "${test_libs}")
+endif (LL_TESTS)
diff --git a/indra/llmath/llbbox.cpp b/indra/llmath/llbbox.cpp
new file mode 100644
index 0000000000..914cbfdc12
--- /dev/null
+++ b/indra/llmath/llbbox.cpp
@@ -0,0 +1,162 @@
+/**
+ * @file llbbox.cpp
+ * @brief General purpose bounding box class (Not axis aligned)
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+// self include
+#include "llbbox.h"
+
+// library includes
+#include "m4math.h"
+
+void LLBBox::addPointLocal(const LLVector3& p)
+{
+ if (mEmpty)
+ {
+ mMinLocal = p;
+ mMaxLocal = p;
+ mEmpty = FALSE;
+ }
+ else
+ {
+ mMinLocal.mV[VX] = llmin( p.mV[VX], mMinLocal.mV[VX] );
+ mMinLocal.mV[VY] = llmin( p.mV[VY], mMinLocal.mV[VY] );
+ mMinLocal.mV[VZ] = llmin( p.mV[VZ], mMinLocal.mV[VZ] );
+ mMaxLocal.mV[VX] = llmax( p.mV[VX], mMaxLocal.mV[VX] );
+ mMaxLocal.mV[VY] = llmax( p.mV[VY], mMaxLocal.mV[VY] );
+ mMaxLocal.mV[VZ] = llmax( p.mV[VZ], mMaxLocal.mV[VZ] );
+ }
+}
+
+void LLBBox::addPointAgent( LLVector3 p)
+{
+ p -= mPosAgent;
+ p.rotVec( ~mRotation );
+ addPointLocal( p );
+}
+
+
+void LLBBox::addBBoxAgent(const LLBBox& b)
+{
+ if (mEmpty)
+ {
+ mPosAgent = b.mPosAgent;
+ mRotation = b.mRotation;
+ mMinLocal.clearVec();
+ mMaxLocal.clearVec();
+ }
+ LLVector3 vertex[8];
+ vertex[0].setVec( b.mMinLocal.mV[VX], b.mMinLocal.mV[VY], b.mMinLocal.mV[VZ] );
+ vertex[1].setVec( b.mMinLocal.mV[VX], b.mMinLocal.mV[VY], b.mMaxLocal.mV[VZ] );
+ vertex[2].setVec( b.mMinLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMinLocal.mV[VZ] );
+ vertex[3].setVec( b.mMinLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMaxLocal.mV[VZ] );
+ vertex[4].setVec( b.mMaxLocal.mV[VX], b.mMinLocal.mV[VY], b.mMinLocal.mV[VZ] );
+ vertex[5].setVec( b.mMaxLocal.mV[VX], b.mMinLocal.mV[VY], b.mMaxLocal.mV[VZ] );
+ vertex[6].setVec( b.mMaxLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMinLocal.mV[VZ] );
+ vertex[7].setVec( b.mMaxLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMaxLocal.mV[VZ] );
+
+ LLMatrix4 m( b.mRotation );
+ m.translate( b.mPosAgent );
+ m.translate( -mPosAgent );
+ m.rotate( ~mRotation );
+
+ for( S32 i=0; i<8; i++ )
+ {
+ addPointLocal( vertex[i] * m );
+ }
+}
+
+
+void LLBBox::expand( F32 delta )
+{
+ mMinLocal.mV[VX] -= delta;
+ mMinLocal.mV[VY] -= delta;
+ mMinLocal.mV[VZ] -= delta;
+ mMaxLocal.mV[VX] += delta;
+ mMaxLocal.mV[VY] += delta;
+ mMaxLocal.mV[VZ] += delta;
+}
+
+LLVector3 LLBBox::localToAgent(const LLVector3& v) const
+{
+ LLMatrix4 m( mRotation );
+ m.translate( mPosAgent );
+ return v * m;
+}
+
+LLVector3 LLBBox::agentToLocal(const LLVector3& v) const
+{
+ LLMatrix4 m;
+ m.translate( -mPosAgent );
+ m.rotate( ~mRotation ); // inverse rotation
+ return v * m;
+}
+
+LLVector3 LLBBox::localToAgentBasis(const LLVector3& v) const
+{
+ LLMatrix4 m( mRotation );
+ return v * m;
+}
+
+LLVector3 LLBBox::agentToLocalBasis(const LLVector3& v) const
+{
+ LLMatrix4 m( ~mRotation ); // inverse rotation
+ return v * m;
+}
+
+BOOL LLBBox::containsPointLocal(const LLVector3& p) const
+{
+ if ( (p.mV[VX] < mMinLocal.mV[VX])
+ ||(p.mV[VX] > mMaxLocal.mV[VX])
+ ||(p.mV[VY] < mMinLocal.mV[VY])
+ ||(p.mV[VY] > mMaxLocal.mV[VY])
+ ||(p.mV[VZ] < mMinLocal.mV[VZ])
+ ||(p.mV[VZ] > mMaxLocal.mV[VZ]))
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL LLBBox::containsPointAgent(const LLVector3& p) const
+{
+ LLVector3 point_local = agentToLocal(p);
+ return containsPointLocal(point_local);
+}
+
+
+/*
+LLBBox operator*(const LLBBox &a, const LLMatrix4 &b)
+{
+ return LLBBox( a.mMin * b, a.mMax * b );
+}
+*/
diff --git a/indra/llmath/llbbox.h b/indra/llmath/llbbox.h
new file mode 100644
index 0000000000..cd29551b01
--- /dev/null
+++ b/indra/llmath/llbbox.h
@@ -0,0 +1,103 @@
+/**
+ * @file llbbox.h
+ * @brief General purpose bounding box class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_BBOX_H
+#define LL_BBOX_H
+
+#include "v3math.h"
+#include "llquaternion.h"
+
+// Note: "local space" for an LLBBox is defined relative to agent space in terms of
+// a translation followed by a rotation. There is no scale term since the LLBBox's min and
+// max are not necessarily symetrical and define their own extents.
+
+class LLBBox
+{
+public:
+ LLBBox() {mEmpty = TRUE;}
+ LLBBox( const LLVector3& pos_agent,
+ const LLQuaternion& rot,
+ const LLVector3& min_local,
+ const LLVector3& max_local )
+ :
+ mMinLocal( min_local ), mMaxLocal( max_local ), mPosAgent(pos_agent), mRotation( rot), mEmpty( TRUE )
+ {}
+
+ // Default copy constructor is OK.
+
+ const LLVector3& getPositionAgent() const { return mPosAgent; }
+ const LLQuaternion& getRotation() const { return mRotation; }
+
+ const LLVector3& getMinLocal() const { return mMinLocal; }
+ void setMinLocal( const LLVector3& min ) { mMinLocal = min; }
+
+ const LLVector3& getMaxLocal() const { return mMaxLocal; }
+ void setMaxLocal( const LLVector3& max ) { mMaxLocal = max; }
+
+ LLVector3 getCenterLocal() const { return (mMaxLocal - mMinLocal) * 0.5f + mMinLocal; }
+ LLVector3 getCenterAgent() const { return localToAgent( getCenterLocal() ); }
+
+ LLVector3 getExtentLocal() const { return mMaxLocal - mMinLocal; }
+
+ BOOL containsPointLocal(const LLVector3& p) const;
+ BOOL containsPointAgent(const LLVector3& p) const;
+
+ void addPointAgent(LLVector3 p);
+ void addBBoxAgent(const LLBBox& b);
+
+ void addPointLocal(const LLVector3& p);
+ void addBBoxLocal(const LLBBox& b) { addPointLocal( b.mMinLocal ); addPointLocal( b.mMaxLocal ); }
+
+ void expand( F32 delta );
+
+ LLVector3 localToAgent( const LLVector3& v ) const;
+ LLVector3 agentToLocal( const LLVector3& v ) const;
+
+ // Changes rotation but not position
+ LLVector3 localToAgentBasis(const LLVector3& v) const;
+ LLVector3 agentToLocalBasis(const LLVector3& v) const;
+
+
+// friend LLBBox operator*(const LLBBox& a, const LLMatrix4& b);
+
+private:
+ LLVector3 mMinLocal;
+ LLVector3 mMaxLocal;
+ LLVector3 mPosAgent; // Position relative to Agent's Region
+ LLQuaternion mRotation;
+ BOOL mEmpty; // Nothing has been added to this bbox yet
+};
+
+//LLBBox operator*(const LLBBox &a, const LLMatrix4 &b);
+
+
+#endif // LL_BBOX_H
diff --git a/indra/llmath/llbboxlocal.h b/indra/llmath/llbboxlocal.h
index d69028e3aa..0d1e5a3ae5 100644
--- a/indra/llmath/llbboxlocal.h
+++ b/indra/llmath/llbboxlocal.h
@@ -53,9 +53,6 @@ public:
LLVector3 getCenter() const { return (mMax - mMin) * 0.5f + mMin; }
LLVector3 getExtent() const { return mMax - mMin; }
- BOOL containsPoint(const LLVector3& p) const;
- BOOL intersects(const LLBBoxLocal& b) const;
-
void addPoint(const LLVector3& p);
void addBBox(const LLBBoxLocal& b) { addPoint( b.mMin ); addPoint( b.mMax ); }
diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp
index 0f343bcefe..21ea4b2e7c 100644
--- a/indra/llmath/llcamera.cpp
+++ b/indra/llmath/llcamera.cpp
@@ -178,7 +178,7 @@ S32 LLCamera::AABBInFrustum(const LLVector3 &center, const LLVector3& radius)
U8 mask = 0;
S32 result = 2;
- if (radius.magVecSquared() > mFrustumCornerDist * mFrustumCornerDist)
+ /*if (mFrustumCornerDist > 0.f && radius.magVecSquared() > mFrustumCornerDist * mFrustumCornerDist)
{ //box is larger than frustum, check frustum quads against box planes
static const LLVector3 dir[] =
@@ -241,11 +241,15 @@ S32 LLCamera::AABBInFrustum(const LLVector3 &center, const LLVector3& radius)
result = 1;
}
}
- else
+ else*/
{
for (U32 i = 0; i < mPlaneCount; i++)
{
mask = mAgentPlanes[i].mask;
+ if (mask == 0xff)
+ {
+ continue;
+ }
LLPlane p = mAgentPlanes[i].p;
LLVector3 n = LLVector3(p);
float d = p.mV[3];
@@ -294,6 +298,10 @@ S32 LLCamera::AABBInFrustumNoFarClip(const LLVector3 &center, const LLVector3& r
}
mask = mAgentPlanes[i].mask;
+ if (mask == 0xff)
+ {
+ continue;
+ }
LLPlane p = mAgentPlanes[i].p;
LLVector3 n = LLVector3(p);
float d = p.mV[3];
@@ -437,6 +445,11 @@ int LLCamera::sphereInFrustum(const LLVector3 &sphere_center, const F32 radius)
int res = 2;
for (int i = 0; i < 6; i++)
{
+ if (mAgentPlanes[i].mask == 0xff)
+ {
+ continue;
+ }
+
float d = mAgentPlanes[i].p.dist(sphere_center);
if (d > radius)
@@ -622,6 +635,17 @@ U8 LLCamera::calcPlaneMask(const LLPlane& plane)
return mask;
}
+void LLCamera::ignoreAgentFrustumPlane(S32 idx)
+{
+ if (idx < 0 || idx > (S32) mPlaneCount)
+ {
+ return;
+ }
+
+ mAgentPlanes[idx].mask = 0xff;
+ mAgentPlanes[idx].p.clearVec();
+}
+
void LLCamera::calcAgentFrustumPlanes(LLVector3* frust)
{
diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h
index 23ee1157f9..0c81067919 100644
--- a/indra/llmath/llcamera.h
+++ b/indra/llmath/llcamera.h
@@ -93,6 +93,17 @@ public:
PLANE_TOP_MASK = (1<<PLANE_TOP),
PLANE_ALL_MASK = 0xf
};
+
+ enum
+ {
+ AGENT_PLANE_LEFT = 0,
+ AGENT_PLANE_RIGHT,
+ AGENT_PLANE_NEAR,
+ AGENT_PLANE_BOTTOM,
+ AGENT_PLANE_TOP,
+ AGENT_PLANE_FAR,
+ };
+
enum {
HORIZ_PLANE_LEFT = 0,
HORIZ_PLANE_RIGHT = 1,
@@ -132,7 +143,8 @@ private:
public:
LLVector3 mAgentFrustum[8]; //8 corners of 6-plane frustum
F32 mFrustumCornerDist; //distance to corner of frustum against far clip plane
-
+ LLPlane getAgentPlane(U32 idx) { return mAgentPlanes[idx].p; }
+
public:
LLCamera();
LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane);
@@ -179,6 +191,8 @@ public:
// Return number of bytes copied.
size_t readFrustumFromBuffer(const char *buffer);
void calcAgentFrustumPlanes(LLVector3* frust);
+ void ignoreAgentFrustumPlane(S32 idx);
+
// Returns 1 if partly in, 2 if fully in.
// NOTE: 'center' is in absolute frame.
S32 sphereInFrustumOld(const LLVector3 &center, const F32 radius) const;
diff --git a/indra/llmath/llcoord.h b/indra/llmath/llcoord.h
index 9d46a8b454..9e38fddbd7 100644
--- a/indra/llmath/llcoord.h
+++ b/indra/llmath/llcoord.h
@@ -59,8 +59,11 @@ public:
{}
LLCoordGL(S32 x, S32 y) : LLCoord(x, y)
{}
+ bool operator==(const LLCoordGL& other) const { return mX == other.mX && mY == other.mY; }
+ bool operator!=(const LLCoordGL& other) const { return !(*this == other); }
};
+//bool operator ==(const LLCoordGL& a, const LLCoordGL& b);
// Window coords include things like window borders,
// menu regions, etc.
@@ -71,6 +74,8 @@ public:
{}
LLCoordWindow(S32 x, S32 y) : LLCoord(x, y)
{}
+ bool operator==(const LLCoordWindow& other) const { return mX == other.mX && mY == other.mY; }
+ bool operator!=(const LLCoordWindow& other) const { return !(*this == other); }
};
@@ -82,6 +87,8 @@ public:
{}
LLCoordScreen(S32 x, S32 y) : LLCoord(x, y)
{}
+ bool operator==(const LLCoordScreen& other) const { return mX == other.mX && mY == other.mY; }
+ bool operator!=(const LLCoordScreen& other) const { return !(*this == other); }
};
class LLCoordFont : public LLCoord
@@ -96,6 +103,8 @@ public:
void set(S32 x, S32 y) { LLCoord::set(x,y); mZ = 0.f; }
void set(S32 x, S32 y, F32 z) { mX = x; mY = y; mZ = z; }
+ bool operator==(const LLCoordFont& other) const { return mX == other.mX && mY == other.mY; }
+ bool operator!=(const LLCoordFont& other) const { return !(*this == other); }
};
diff --git a/indra/llmath/llinterp.h b/indra/llmath/llinterp.h
index 8beeef480b..36ca2e9865 100644
--- a/indra/llmath/llinterp.h
+++ b/indra/llmath/llinterp.h
@@ -32,6 +32,13 @@
#ifndef LL_LLINTERP_H
#define LL_LLINTERP_H
+#if defined(LL_WINDOWS)
+// macro definitions for common math constants (e.g. M_PI) are declared under the _USE_MATH_DEFINES
+// on Windows system.
+// So, let's define _USE_MATH_DEFINES before including math.h
+ #define _USE_MATH_DEFINES
+#endif
+
#include "math.h"
// Class from which different types of interpolators can be derived
diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h
index 66451b1a27..7a5d51ff76 100644
--- a/indra/llmath/llmath.h
+++ b/indra/llmath/llmath.h
@@ -35,9 +35,10 @@
#include <cmath>
#include <cstdlib>
+#include <complex>
#include "lldefs.h"
-#include "llstl.h" // *TODO: Remove when LLString is gone
-#include "llstring.h" // *TODO: Remove when LLString is gone
+//#include "llstl.h" // *TODO: Remove when LLString is gone
+//#include "llstring.h" // *TODO: Remove when LLString is gone
// lltut.h uses is_approx_equal_fraction(). This was moved to its own header
// file in llcommon so we can use lltut.h for llcommon tests without making
// llcommon depend on llmath.
diff --git a/indra/llmath/llmodularmath.cpp b/indra/llmath/llmodularmath.cpp
new file mode 100644
index 0000000000..4a6553ae7c
--- /dev/null
+++ b/indra/llmath/llmodularmath.cpp
@@ -0,0 +1,36 @@
+/**
+ * @file llmodularmath.cpp
+ * @brief LLModularMath class implementation
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+// implementation is all in the header, this include dep ensures the unit test is rerun if the implementation changes.
+#include "llmodularmath.h"
diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h
index bced84cb1c..ba8776690a 100644
--- a/indra/llmath/lloctree.h
+++ b/indra/llmath/lloctree.h
@@ -65,11 +65,10 @@ public:
};
template <class T>
-class LLOctreeTraveler : public LLTreeTraveler<T>
+class LLOctreeTraveler
{
public:
- virtual void traverse(const LLTreeNode<T>* node);
- virtual void visit(const LLTreeNode<T>* state) { }
+ virtual void traverse(const LLOctreeNode<T>* node);
virtual void visit(const LLOctreeNode<T>* branch) = 0;
};
@@ -700,19 +699,16 @@ public:
}
};
-
//========================
// LLOctreeTraveler
//========================
template <class T>
-void LLOctreeTraveler<T>::traverse(const LLTreeNode<T>* tree_node)
+void LLOctreeTraveler<T>::traverse(const LLOctreeNode<T>* node)
{
- const LLOctreeNode<T>* node = (const LLOctreeNode<T>*) tree_node;
node->accept(this);
for (U32 i = 0; i < node->getChildCount(); i++)
{
traverse(node->getChild(i));
}
}
-
#endif
diff --git a/indra/llmath/llquaternion.cpp b/indra/llmath/llquaternion.cpp
index cfd6183ec4..fdcc19d657 100644
--- a/indra/llmath/llquaternion.cpp
+++ b/indra/llmath/llquaternion.cpp
@@ -121,7 +121,7 @@ void LLQuaternion::quantize16(F32 lower, F32 upper)
mQ[VZ] = z;
mQ[VS] = s;
- normQuat();
+ normalize();
}
void LLQuaternion::quantize8(F32 lower, F32 upper)
@@ -131,7 +131,7 @@ void LLQuaternion::quantize8(F32 lower, F32 upper)
mQ[VZ] = U8_to_F32(F32_to_U8_ROUND(mQ[VZ], lower, upper), lower, upper);
mQ[VS] = U8_to_F32(F32_to_U8_ROUND(mQ[VS], lower, upper), lower, upper);
- normQuat();
+ normalize();
}
// LLVector3 Magnitude and Normalization Functions
@@ -346,7 +346,7 @@ const LLQuaternion& LLQuaternion::setQuat(const LLMatrix4 &mat)
// mQ[VZ] = (F32)(cosX*cosY*sinZ - sinX*sinY*cosZ);
//#endif
//
-// normQuat();
+// normalize();
// return (*this);
}
diff --git a/indra/llmath/llquaternion.h b/indra/llmath/llquaternion.h
index 5db9c5be2e..0769f29f23 100644
--- a/indra/llmath/llquaternion.h
+++ b/indra/llmath/llquaternion.h
@@ -469,20 +469,30 @@ inline const LLQuaternion& operator*=(LLQuaternion &a, const LLQuaternion &b)
return a;
}
+const F32 ONE_PART_IN_A_MILLION = 0.000001f;
+
inline F32 LLQuaternion::normalize()
{
F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]);
if (mag > FP_MAG_THRESHOLD)
{
- F32 oomag = 1.f/mag;
- mQ[VX] *= oomag;
- mQ[VY] *= oomag;
- mQ[VZ] *= oomag;
- mQ[VS] *= oomag;
+ // Floating point error can prevent some quaternions from achieving
+ // exact unity length. When trying to renormalize such quaternions we
+ // can oscillate between multiple quantized states. To prevent such
+ // drifts we only renomalize if the length is far enough from unity.
+ if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION)
+ {
+ F32 oomag = 1.f/mag;
+ mQ[VX] *= oomag;
+ mQ[VY] *= oomag;
+ mQ[VZ] *= oomag;
+ mQ[VS] *= oomag;
+ }
}
else
{
+ // we were given a very bad quaternion so we set it to identity
mQ[VX] = 0.f;
mQ[VY] = 0.f;
mQ[VZ] = 0.f;
@@ -499,11 +509,15 @@ inline F32 LLQuaternion::normQuat()
if (mag > FP_MAG_THRESHOLD)
{
- F32 oomag = 1.f/mag;
- mQ[VX] *= oomag;
- mQ[VY] *= oomag;
- mQ[VZ] *= oomag;
- mQ[VS] *= oomag;
+ if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION)
+ {
+ // only renormalize if length not close enough to 1.0 already
+ F32 oomag = 1.f/mag;
+ mQ[VX] *= oomag;
+ mQ[VY] *= oomag;
+ mQ[VZ] *= oomag;
+ mQ[VS] *= oomag;
+ }
}
else
{
diff --git a/indra/llmath/llrect.cpp b/indra/llmath/llrect.cpp
index cba76dd211..14e094792d 100644
--- a/indra/llmath/llrect.cpp
+++ b/indra/llmath/llrect.cpp
@@ -1,5 +1,6 @@
/**
* @file llrect.cpp
+ * @brief LLRect class implementation
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
@@ -31,4 +32,5 @@
#include "linden_common.h"
+// implementation is all in the header, this include dep ensures the unit test is rerun if the implementation changes.
#include "llrect.h"
diff --git a/indra/llmath/llrect.h b/indra/llmath/llrect.h
index 9eb58dbbe9..2fa8cb3f16 100644
--- a/indra/llmath/llrect.h
+++ b/indra/llmath/llrect.h
@@ -42,6 +42,7 @@
template <class Type> class LLRectBase
{
public:
+ typedef Type tCoordType;
Type mLeft;
Type mTop;
Type mRight;
@@ -64,23 +65,17 @@ public:
mLeft(left), mTop(top), mRight(right), mBottom(bottom)
{}
- LLRectBase(const LLSD& sd)
+ explicit LLRectBase(const LLSD& sd)
{
setValue(sd);
}
- const LLRectBase& operator=(const LLSD& sd)
- {
- setValue(sd);
- return *this;
- }
-
void setValue(const LLSD& sd)
{
- mLeft = sd[0].asInteger();
- mTop = sd[1].asInteger();
- mRight = sd[2].asInteger();
- mBottom = sd[3].asInteger();
+ mLeft = (Type)sd[0].asInteger();
+ mTop = (Type)sd[1].asInteger();
+ mRight = (Type)sd[2].asInteger();
+ mBottom = (Type)sd[3].asInteger();
}
LLSD getValue() const
@@ -147,10 +142,20 @@ public:
// Note: Does NOT follow GL_QUAD conventions: the top and right edges ARE considered part of the rect
// returns TRUE if any part of rect is is inside this LLRect
- BOOL rectInRect(const LLRectBase* rect) const
+ BOOL overlaps(const LLRectBase& rect) const
+ {
+ return !(mLeft > rect.mRight
+ || mRight < rect.mLeft
+ || mBottom > rect.mTop
+ || mTop < rect.mBottom);
+ }
+
+ BOOL contains(const LLRectBase& rect) const
{
- return mLeft <= rect->mRight && rect->mLeft <= mRight &&
- mBottom <= rect->mTop && rect->mBottom <= mTop ;
+ return mLeft <= rect.mLeft
+ && mRight >= rect.mRight
+ && mBottom <= rect.mBottom
+ && mTop >= rect.mTop;
}
LLRectBase& set(Type left, Type top, Type right, Type bottom)
@@ -229,26 +234,25 @@ public:
return mLeft <= mRight && mBottom <= mTop;
}
- bool isNull() const
+ bool isEmpty() const
{
return mLeft == mRight || mBottom == mTop;
}
- bool notNull() const
+ bool notEmpty() const
{
- return !isNull();
+ return !isEmpty();
}
- LLRectBase& unionWith(const LLRectBase &other)
+ void unionWith(const LLRectBase &other)
{
mLeft = llmin(mLeft, other.mLeft);
mRight = llmax(mRight, other.mRight);
mBottom = llmin(mBottom, other.mBottom);
mTop = llmax(mTop, other.mTop);
- return *this;
}
- LLRectBase& intersectWith(const LLRectBase &other)
+ void intersectWith(const LLRectBase &other)
{
mLeft = llmax(mLeft, other.mLeft);
mRight = llmin(mRight, other.mRight);
@@ -262,7 +266,6 @@ public:
{
mBottom = mTop;
}
- return *this;
}
friend std::ostream &operator<<(std::ostream &s, const LLRectBase &rect)
@@ -271,8 +274,8 @@ public:
<< " W " << rect.getWidth() << " H " << rect.getHeight() << " }";
return s;
}
-
- bool operator==(const LLRectBase &b)
+
+ bool operator==(const LLRectBase &b) const
{
return ((mLeft == b.mLeft) &&
(mTop == b.mTop) &&
@@ -280,7 +283,7 @@ public:
(mBottom == b.mBottom));
}
- bool operator!=(const LLRectBase &b)
+ bool operator!=(const LLRectBase &b) const
{
return ((mLeft != b.mLeft) ||
(mTop != b.mTop) ||
diff --git a/indra/llmath/llsdutil_math.cpp b/indra/llmath/llsdutil_math.cpp
index 073cb2e3bd..1bd12ae513 100644
--- a/indra/llmath/llsdutil_math.cpp
+++ b/indra/llmath/llsdutil_math.cpp
@@ -34,7 +34,7 @@
#include "linden_common.h"
-#include "llsdutil.h"
+#include "llsdutil_math.h"
#include "v3math.h"
#include "v4math.h"
@@ -165,9 +165,6 @@ LLSD ll_sd_from_color4(const LLColor4& c)
LLColor4 ll_color4_from_sd(const LLSD& sd)
{
LLColor4 c;
- c.mV[0] = (F32)sd[0].asReal();
- c.mV[1] = (F32)sd[1].asReal();
- c.mV[2] = (F32)sd[2].asReal();
- c.mV[3] = (F32)sd[3].asReal();
+ c.setValue(sd);
return c;
}
diff --git a/indra/llmath/llsdutil_math.h b/indra/llmath/llsdutil_math.h
new file mode 100644
index 0000000000..121f4b746a
--- /dev/null
+++ b/indra/llmath/llsdutil_math.h
@@ -0,0 +1,70 @@
+/**
+ * @file llsdutil_math.h
+ * @author Brad
+ * @date 2009-05-19
+ * @brief Utility classes, functions, etc, for using structured data with math classes.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSDUTIL_MATH_H
+#define LL_LLSDUTIL_MATH_H
+
+class LL_COMMON_API LLSD;
+
+// vector3
+class LLVector3;
+LLSD ll_sd_from_vector3(const LLVector3& vec);
+LLVector3 ll_vector3_from_sd(const LLSD& sd, S32 start_index = 0);
+
+// vector4
+class LLVector4;
+LLSD ll_sd_from_vector4(const LLVector4& vec);
+LLVector4 ll_vector4_from_sd(const LLSD& sd, S32 start_index = 0);
+
+// vector3d (double)
+class LLVector3d;
+LLSD ll_sd_from_vector3d(const LLVector3d& vec);
+LLVector3d ll_vector3d_from_sd(const LLSD& sd, S32 start_index = 0);
+
+// vector2
+class LLVector2;
+LLSD ll_sd_from_vector2(const LLVector2& vec);
+LLVector2 ll_vector2_from_sd(const LLSD& sd);
+
+// Quaternion
+class LLQuaternion;
+LLSD ll_sd_from_quaternion(const LLQuaternion& quat);
+LLQuaternion ll_quaternion_from_sd(const LLSD& sd);
+
+// color4
+class LLColor4;
+LLSD ll_sd_from_color4(const LLColor4& c);
+LLColor4 ll_color4_from_sd(const LLSD& sd);
+
+#endif // LL_LLSDUTIL_MATH_H
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 1250f539f5..df4c618ac1 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -84,6 +84,7 @@ const F32 SKEW_MIN = -0.95f;
const F32 SKEW_MAX = 0.95f;
const F32 SCULPT_MIN_AREA = 0.002f;
+const S32 SCULPT_MIN_AREA_DETAIL = 1;
BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, const LLVector3& norm)
{
@@ -2230,10 +2231,14 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
if (!data_is_empty)
{
sculptGenerateMapVertices(sculpt_width, sculpt_height, sculpt_components, sculpt_data, sculpt_type);
-
- if (sculptGetSurfaceArea() < SCULPT_MIN_AREA)
+
+ // don't test lowest LOD to support legacy content DEV-33670
+ if (mDetail > SCULPT_MIN_AREA_DETAIL)
{
- data_is_empty = TRUE;
+ if (sculptGetSurfaceArea() < SCULPT_MIN_AREA)
+ {
+ data_is_empty = TRUE;
+ }
}
}
@@ -3370,7 +3375,8 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
std::vector<S32> &segments,
const LLVector3& obj_cam_vec,
const LLMatrix4& mat,
- const LLMatrix3& norm_mat)
+ const LLMatrix3& norm_mat,
+ S32 face_mask)
{
LLMemType m1(LLMemType::MTYPE_VOLUME);
@@ -3378,12 +3384,17 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
normals.clear();
segments.clear();
+ S32 cur_index = 0;
//for each face
for (face_list_t::iterator iter = mVolumeFaces.begin();
iter != mVolumeFaces.end(); ++iter)
{
const LLVolumeFace& face = *iter;
+ if (!(face_mask & (0x1 << cur_index++)))
+ {
+ continue;
+ }
if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) {
}
@@ -3571,7 +3582,7 @@ S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
if (face == -1) // ALL_SIDES
{
start_face = 0;
- end_face = getNumFaces() - 1;
+ end_face = getNumVolumeFaces() - 1;
}
else
{
@@ -4262,7 +4273,7 @@ LLFaceID LLVolume::generateFaceMask()
}
break;
default:
- llerrs << "Unknown profile!" << llendl
+ llerrs << "Unknown profile!" << llendl;
break;
}
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index e55fe52c91..871b334452 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -52,7 +52,7 @@ class LLVolume;
#include "llquaternion.h"
#include "llstrider.h"
#include "v4coloru.h"
-#include "llmemory.h"
+#include "llrefcount.h"
#include "llfile.h"
//============================================================================
@@ -902,9 +902,13 @@ public:
// returns number of triangle indeces required for path/profile mesh
S32 getNumTriangleIndices() const;
- void generateSilhouetteVertices(std::vector<LLVector3> &vertices, std::vector<LLVector3> &normals, std::vector<S32> &segments, const LLVector3& view_vec,
- const LLMatrix4& mat,
- const LLMatrix3& norm_mat);
+ void generateSilhouetteVertices(std::vector<LLVector3> &vertices,
+ std::vector<LLVector3> &normals,
+ std::vector<S32> &segments,
+ const LLVector3& view_vec,
+ const LLMatrix4& mat,
+ const LLMatrix3& norm_mat,
+ S32 face_index);
//get the face index of the face that intersects with the given line segment at the point
//closest to start. Moves end to the point of intersection. Returns -1 if no intersection.
diff --git a/indra/llmath/llvolumemgr.h b/indra/llmath/llvolumemgr.h
index e10ad94dba..a78ea76a1a 100644
--- a/indra/llmath/llvolumemgr.h
+++ b/indra/llmath/llvolumemgr.h
@@ -36,7 +36,7 @@
#include <map>
#include "llvolume.h"
-#include "llmemory.h"
+#include "llpointer.h"
#include "llthread.h"
class LLVolumeParams;
@@ -92,8 +92,8 @@ public:
// whatever calls getVolume() never owns the LLVolume* and
// cannot keep references for long since it may be deleted
// later. For best results hold it in an LLPointer<LLVolume>.
- LLVolume *refVolume(const LLVolumeParams &volume_params, const S32 detail);
- void unrefVolume(LLVolume *volumep);
+ virtual LLVolume *refVolume(const LLVolumeParams &volume_params, const S32 detail);
+ virtual void unrefVolume(LLVolume *volumep);
void dump();
diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp
index 59a0bc2335..d8e7b4aaf9 100644
--- a/indra/llmath/m4math.cpp
+++ b/indra/llmath/m4math.cpp
@@ -678,32 +678,6 @@ LLVector4 operator*(const LLMatrix4 &a, const LLVector4 &b)
}
*/
-// Operates "to the left" on row-vector a
-//
-// This used to be in the header file but was not actually inlined in practice.
-// When avatar vertex programs are off, this function is a hot spot in profiles
-// due to software skinning in LLViewerJointMesh::updateGeometry(). JC
-LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b)
-{
- // This is better than making a temporary LLVector3. This eliminates an
- // unnecessary LLVector3() constructor and also helps the compiler to
- // realize that the output floats do not alias the input floats, hence
- // eliminating redundant loads of a.mV[0], etc. JC
- return LLVector3(a.mV[VX] * b.mMatrix[VX][VX] +
- a.mV[VY] * b.mMatrix[VY][VX] +
- a.mV[VZ] * b.mMatrix[VZ][VX] +
- b.mMatrix[VW][VX],
-
- a.mV[VX] * b.mMatrix[VX][VY] +
- a.mV[VY] * b.mMatrix[VY][VY] +
- a.mV[VZ] * b.mMatrix[VZ][VY] +
- b.mMatrix[VW][VY],
-
- a.mV[VX] * b.mMatrix[VX][VZ] +
- a.mV[VY] * b.mMatrix[VY][VZ] +
- a.mV[VZ] * b.mMatrix[VZ][VZ] +
- b.mMatrix[VW][VZ]);
-}
LLVector4 operator*(const LLVector4 &a, const LLMatrix4 &b)
{
diff --git a/indra/llmath/m4math.h b/indra/llmath/m4math.h
index 58c9c09d7f..e74b7afe9b 100644
--- a/indra/llmath/m4math.h
+++ b/indra/llmath/m4math.h
@@ -230,7 +230,7 @@ public:
// friend inline LLMatrix4 operator*(const LLMatrix4 &a, const LLMatrix4 &b); // Return a * b
friend LLVector4 operator*(const LLVector4 &a, const LLMatrix4 &b); // Return transform of vector a by matrix b
- friend LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b); // Return full transform of a by matrix b
+ friend const LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b); // Return full transform of a by matrix b
friend LLVector4 rotate_vector(const LLVector4 &a, const LLMatrix4 &b); // Rotates a but does not translate
friend LLVector3 rotate_vector(const LLVector3 &a, const LLMatrix4 &b); // Rotates a but does not translate
@@ -353,7 +353,31 @@ inline const LLMatrix4& operator-=(LLMatrix4 &a, const LLMatrix4 &b)
return a;
}
-#endif
-
+// Operates "to the left" on row-vector a
+//
+// When avatar vertex programs are off, this function is a hot spot in profiles
+// due to software skinning in LLViewerJointMesh::updateGeometry(). JC
+inline const LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b)
+{
+ // This is better than making a temporary LLVector3. This eliminates an
+ // unnecessary LLVector3() constructor and also helps the compiler to
+ // realize that the output floats do not alias the input floats, hence
+ // eliminating redundant loads of a.mV[0], etc. JC
+ return LLVector3(a.mV[VX] * b.mMatrix[VX][VX] +
+ a.mV[VY] * b.mMatrix[VY][VX] +
+ a.mV[VZ] * b.mMatrix[VZ][VX] +
+ b.mMatrix[VW][VX],
+
+ a.mV[VX] * b.mMatrix[VX][VY] +
+ a.mV[VY] * b.mMatrix[VY][VY] +
+ a.mV[VZ] * b.mMatrix[VZ][VY] +
+ b.mMatrix[VW][VY],
+
+ a.mV[VX] * b.mMatrix[VX][VZ] +
+ a.mV[VY] * b.mMatrix[VY][VZ] +
+ a.mV[VZ] * b.mMatrix[VZ][VZ] +
+ b.mMatrix[VW][VZ]);
+}
+#endif
diff --git a/indra/llmath/tests/llbbox_test.cpp b/indra/llmath/tests/llbbox_test.cpp
new file mode 100644
index 0000000000..3031310a5d
--- /dev/null
+++ b/indra/llmath/tests/llbbox_test.cpp
@@ -0,0 +1,373 @@
+/**
+ * @file llbbox_test.cpp
+ * @author Martin Reddy
+ * @date 2009-06-25
+ * @brief Test for llbbox.cpp.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../test/lltut.h"
+
+#include "../llbbox.h"
+
+
+#define ANGLE (3.14159265f / 2.0f)
+#define APPROX_EQUAL(a, b) dist_vec((a),(b)) < 1e-5
+
+namespace tut
+{
+ struct LLBBoxData
+ {
+ };
+
+ typedef test_group<LLBBoxData> factory;
+ typedef factory::object object;
+}
+
+namespace
+{
+ tut::factory llbbox_test_factory("LLBBox");
+}
+
+namespace tut
+{
+ template<> template<>
+ void object::test<1>()
+ {
+ //
+ // test the default constructor
+ //
+
+ LLBBox bbox1;
+
+ ensure_equals("Default bbox min", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f));
+ ensure_equals("Default bbox max", bbox1.getMaxLocal(), LLVector3(0.0f, 0.0f, 0.0f));
+ ensure_equals("Default bbox pos agent", bbox1.getPositionAgent(), LLVector3(0.0f, 0.0f, 0.0f));
+ ensure_equals("Default bbox rotation", bbox1.getRotation(), LLQuaternion(0.0f, 0.0f, 0.0f, 1.0f));
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ //
+ // test the non-default constructor
+ //
+
+ LLBBox bbox2(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(),
+ LLVector3(2.0f, 3.0f, 4.0f), LLVector3(4.0f, 5.0f, 6.0f));
+
+ ensure_equals("Custom bbox min", bbox2.getMinLocal(), LLVector3(2.0f, 3.0f, 4.0f));
+ ensure_equals("Custom bbox max", bbox2.getMaxLocal(), LLVector3(4.0f, 5.0f, 6.0f));
+ ensure_equals("Custom bbox pos agent", bbox2.getPositionAgent(), LLVector3(1.0f, 2.0f, 3.0f));
+ ensure_equals("Custom bbox rotation", bbox2.getRotation(), LLQuaternion(0.0f, 0.0f, 0.0f, 1.0f));
+ }
+
+ template<> template<>
+ void object::test<3>()
+ {
+ //
+ // test the setMinLocal() method
+ //
+ LLBBox bbox2;
+ bbox2.setMinLocal(LLVector3(3.0f, 3.0f, 3.0f));
+ ensure_equals("Custom bbox min (2)", bbox2.getMinLocal(), LLVector3(3.0f, 3.0f, 3.0f));
+ }
+
+ template<> template<>
+ void object::test<4>()
+ {
+ //
+ // test the setMaxLocal() method
+ //
+ LLBBox bbox2;
+ bbox2.setMaxLocal(LLVector3(5.0f, 5.0f, 5.0f));
+ ensure_equals("Custom bbox max (2)", bbox2.getMaxLocal(), LLVector3(5.0f, 5.0f, 5.0f));
+ }
+
+ template<> template<>
+ void object::test<5>()
+ {
+ //
+ // test the getCenterLocal() method
+ //
+
+ ensure_equals("Default bbox local center", LLBBox().getCenterLocal(), LLVector3(0.0f, 0.0f, 0.0f));
+
+ LLBBox bbox1(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(),
+ LLVector3(2.0f, 4.0f, 6.0f), LLVector3(4.0f, 6.0f, 8.0f));
+
+ ensure_equals("Custom bbox center local", bbox1.getCenterLocal(), LLVector3(3.0f, 5.0f, 7.0f));
+
+ LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(0.0f, 0.0f, 1.0f)),
+ LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f));
+
+ ensure_equals("Custom bbox center local with rot", bbox2.getCenterLocal(), LLVector3(3.0f, 3.0f, 3.0f));
+ }
+
+ template<> template<>
+ void object::test<6>()
+ {
+ //
+ // test the getCenterAgent()
+ //
+
+ ensure_equals("Default bbox agent center", LLBBox().getCenterAgent(), LLVector3(0.0f, 0.0f, 0.0f));
+
+ LLBBox bbox1(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(),
+ LLVector3(2.0f, 4.0f, 6.0f), LLVector3(4.0f, 6.0f, 8.0f));
+
+ ensure_equals("Custom bbox center agent", bbox1.getCenterAgent(), LLVector3(4.0f, 7.0f, 10.0f));
+
+ LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(0.0f, 0.0f, 1.0f)),
+ LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f));
+
+ ensure("Custom bbox center agent with rot", APPROX_EQUAL(bbox2.getCenterAgent(), LLVector3(-2.0f, 4.0f, 4.0f)));
+ }
+
+ template<> template<>
+ void object::test<7>()
+ {
+ //
+ // test the getExtentLocal() method
+ //
+
+ ensure_equals("Default bbox local extent", LLBBox().getExtentLocal(), LLVector3(0.0f, 0.0f, 0.0f));
+
+ LLBBox bbox1(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(),
+ LLVector3(2.0f, 4.0f, 6.0f), LLVector3(4.0f, 6.0f, 8.0f));
+
+ ensure_equals("Custom bbox extent local", bbox1.getExtentLocal(), LLVector3(2.0f, 2.0f, 2.0f));
+
+ LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(0.0f, 0.0f, 1.0f)),
+ LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f));
+
+ ensure_equals("Custom bbox extent local with rot", bbox1.getExtentLocal(), LLVector3(2.0f, 2.0f, 2.0f));
+ }
+
+ template<> template<>
+ void object::test<8>()
+ {
+ //
+ // test the addPointLocal() method
+ //
+
+ LLBBox bbox1;
+ bbox1.addPointLocal(LLVector3(1.0f, 1.0f, 1.0f));
+ bbox1.addPointLocal(LLVector3(3.0f, 3.0f, 3.0f));
+
+ ensure_equals("addPointLocal center local (1)", bbox1.getCenterLocal(), LLVector3(2.0f, 2.0f, 2.0f));
+ ensure_equals("addPointLocal center agent (1)", bbox1.getCenterAgent(), LLVector3(2.0f, 2.0f, 2.0f));
+ ensure_equals("addPointLocal min (1)", bbox1.getMinLocal(), LLVector3(1.0f, 1.0f, 1.0f));
+ ensure_equals("addPointLocal max (1)", bbox1.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f));
+
+ bbox1.addPointLocal(LLVector3(0.0f, 0.0f, 0.0f));
+ bbox1.addPointLocal(LLVector3(1.0f, 1.0f, 1.0f));
+ bbox1.addPointLocal(LLVector3(2.0f, 2.0f, 2.0f));
+
+ ensure_equals("addPointLocal center local (2)", bbox1.getCenterLocal(), LLVector3(1.5f, 1.5f, 1.5f));
+ ensure_equals("addPointLocal min (2)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f));
+ ensure_equals("addPointLocal max (2)", bbox1.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f));
+ }
+
+ template<> template<>
+ void object::test<9>()
+ {
+ //
+ // test the addBBoxLocal() method
+ //
+
+ LLBBox bbox1;
+ bbox1.addBBoxLocal(LLBBox(LLVector3(), LLQuaternion(),
+ LLVector3(0.0f, 0.0f, 0.0f), LLVector3(3.0f, 3.0f, 3.0f)));
+
+ ensure_equals("addPointLocal center local (3)", bbox1.getCenterLocal(), LLVector3(1.5f, 1.5f, 1.5f));
+ ensure_equals("addPointLocal min (3)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f));
+ ensure_equals("addPointLocal max (3)", bbox1.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f));
+
+ bbox1.addBBoxLocal(LLBBox(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
+ LLVector3(5.0f, 5.0f, 5.0f), LLVector3(10.0f, 10.0f, 10.0f)));
+
+ ensure_equals("addPointLocal center local (4)", bbox1.getCenterLocal(), LLVector3(5.0f, 5.0f, 5.0f));
+ ensure_equals("addPointLocal center agent (4)", bbox1.getCenterAgent(), LLVector3(5.0f, 5.0f, 5.0f));
+ ensure_equals("addPointLocal min (4)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f));
+ ensure_equals("addPointLocal max (4)", bbox1.getMaxLocal(), LLVector3(10.0f, 10.0f, 10.0f));
+ }
+
+ template<> template<>
+ void object::test<10>()
+ {
+ //
+ // test the addPointAgent() method
+ //
+
+ LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(1.0, 0.0, 0.0, 1.0),
+ LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f));
+
+ bbox1.addPointAgent(LLVector3(1.0f, 1.0f, 1.0f));
+ bbox1.addPointAgent(LLVector3(3.0f, 3.0f, 3.0f));
+
+ ensure_equals("addPointAgent center local (1)", bbox1.getCenterLocal(), LLVector3(2.0f, 2.0f, -2.0f));
+ ensure_equals("addPointAgent center agent (1)", bbox1.getCenterAgent(), LLVector3(3.0f, 3.0f, 7.0f));
+ ensure_equals("addPointAgent min (1)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, -4.0f));
+ ensure_equals("addPointAgent max (1)", bbox1.getMaxLocal(), LLVector3(4.0f, 4.0f, 0.0f));
+ }
+
+ template<> template<>
+ void object::test<11>()
+ {
+ //
+ // test the addBBoxAgent() method
+ //
+
+ LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(1.0, 0.0, 0.0, 1.0),
+ LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f));
+
+ bbox1.addPointAgent(LLVector3(1.0f, 1.0f, 1.0f));
+ bbox1.addPointAgent(LLVector3(3.0f, 3.0f, 3.0f));
+
+ bbox1.addBBoxLocal(LLBBox(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
+ LLVector3(5.0f, 5.0f, 5.0f), LLVector3(10.0f, 10.0f, 10.0f)));
+
+ ensure_equals("addPointAgent center local (2)", bbox1.getCenterLocal(), LLVector3(5.0f, 5.0f, 3.0f));
+ ensure_equals("addPointAgent center agent (2)", bbox1.getCenterAgent(), LLVector3(6.0f, -10.0f, 8.0f));
+ ensure_equals("addPointAgent min (2)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, -4.0f));
+ ensure_equals("addPointAgent max (2)", bbox1.getMaxLocal(), LLVector3(10.0f, 10.0f, 10.0f));
+ }
+
+ template<> template<>
+ void object::test<12>()
+ {
+ //
+ // test the expand() method
+ //
+
+ LLBBox bbox1;
+ bbox1.expand(0.0);
+
+ ensure_equals("Zero-expanded Default BBox center", bbox1.getCenterLocal(), LLVector3(0.0f, 0.0f, 0.0f));
+
+ LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
+ LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f));
+ bbox2.expand(0.0);
+
+ ensure_equals("Zero-expanded center local", bbox2.getCenterLocal(), LLVector3(2.0f, 2.0f, 2.0f));
+ ensure_equals("Zero-expanded center agent", bbox2.getCenterAgent(), LLVector3(3.0f, 3.0f, 3.0f));
+ ensure_equals("Zero-expanded min", bbox2.getMinLocal(), LLVector3(1.0f, 1.0f, 1.0f));
+ ensure_equals("Zero-expanded max", bbox2.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f));
+
+ bbox2.expand(0.5);
+
+ ensure_equals("Positive-expanded center", bbox2.getCenterLocal(), LLVector3(2.0f, 2.0f, 2.0f));
+ ensure_equals("Positive-expanded min", bbox2.getMinLocal(), LLVector3(0.5f, 0.5f, 0.5f));
+ ensure_equals("Positive-expanded max", bbox2.getMaxLocal(), LLVector3(3.5f, 3.5f, 3.5f));
+
+ bbox2.expand(-1.0);
+
+ ensure_equals("Negative-expanded center", bbox2.getCenterLocal(), LLVector3(2.0f, 2.0f, 2.0f));
+ ensure_equals("Negative-expanded min", bbox2.getMinLocal(), LLVector3(1.5f, 1.5f, 1.5f));
+ ensure_equals("Negative-expanded max", bbox2.getMaxLocal(), LLVector3(2.5f, 2.5f, 2.5f));
+ }
+
+ template<> template<>
+ void object::test<13>()
+ {
+ //
+ // test the localToAgent() method
+ //
+
+ LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
+ LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f));
+
+ ensure_equals("localToAgent(1,2,3)", bbox1.localToAgent(LLVector3(1.0f, 2.0f, 3.0f)), LLVector3(2.0f, 3.0f, 4.0f));
+
+ LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(1.0f, 0.0f, 0.0f)),
+ LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f));
+
+ ensure("localToAgent(1,2,3) rot", APPROX_EQUAL(bbox2.localToAgent(LLVector3(1.0f, 2.0f, 3.0f)), LLVector3(2.0f, -2.0f, 3.0f)));
+ }
+
+ template<> template<>
+ void object::test<14>()
+ {
+ //
+ // test the agentToLocal() method
+ //
+
+ LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
+ LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f));
+
+ ensure_equals("agentToLocal(1,2,3)", bbox1.agentToLocal(LLVector3(1.0f, 2.0f, 3.0f)), LLVector3(0.0f, 1.0f, 2.0f));
+ ensure_equals("agentToLocal(localToAgent)", bbox1.agentToLocal(bbox1.localToAgent(LLVector3(1.0f, 2.0f, 3.0f))),
+ LLVector3(1.0f, 2.0f, 3.0f));
+
+ LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(1.0f, 0.0f, 0.0f)),
+ LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f));
+
+ ensure("agentToLocal(1,2,3) rot", APPROX_EQUAL(bbox2.agentToLocal(LLVector3(1.0f, 2.0f, 3.0f)), LLVector3(0.0f, 2.0f, -1.0f)));
+ ensure("agentToLocal(localToAgent) rot", APPROX_EQUAL(bbox2.agentToLocal(bbox2.localToAgent(LLVector3(1.0f, 2.0f, 3.0f))),
+ LLVector3(1.0f, 2.0f, 3.0f)));
+ }
+
+ template<> template<>
+ void object::test<15>()
+ {
+ //
+ // test the containsPointLocal() method
+ //
+
+ LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
+ LLVector3(1.0f, 2.0f, 3.0f), LLVector3(3.0f, 4.0f, 5.0f));
+
+ ensure("containsPointLocal(0,0,0)", bbox1.containsPointLocal(LLVector3(0.0f, 0.0f, 0.0f)) == FALSE);
+ ensure("containsPointLocal(1,2,3)", bbox1.containsPointLocal(LLVector3(1.0f, 2.0f, 3.0f)) == TRUE);
+ ensure("containsPointLocal(0.999,2,3)", bbox1.containsPointLocal(LLVector3(0.999f, 2.0f, 3.0f)) == FALSE);
+ ensure("containsPointLocal(3,4,5)", bbox1.containsPointLocal(LLVector3(3.0f, 4.0f, 5.0f)) == TRUE);
+ ensure("containsPointLocal(3,4,5.001)", bbox1.containsPointLocal(LLVector3(3.0f, 4.0f, 5.001f)) == FALSE);
+ }
+
+ template<> template<>
+ void object::test<16>()
+ {
+ //
+ // test the containsPointAgent() method
+ //
+
+ LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
+ LLVector3(1.0f, 2.0f, 3.0f), LLVector3(3.0f, 4.0f, 5.0f));
+
+ ensure("containsPointAgent(0,0,0)", bbox1.containsPointAgent(LLVector3(0.0f, 0.0f, 0.0f)) == FALSE);
+ ensure("containsPointAgent(2,3,4)", bbox1.containsPointAgent(LLVector3(2.0f, 3.0f, 4.0f)) == TRUE);
+ ensure("containsPointAgent(2,2.999,4)", bbox1.containsPointAgent(LLVector3(2.0f, 2.999f, 4.0f)) == FALSE);
+ ensure("containsPointAgent(4,5,6)", bbox1.containsPointAgent(LLVector3(4.0f, 5.0f, 6.0f)) == TRUE);
+ ensure("containsPointAgent(4,5.001,6)", bbox1.containsPointAgent(LLVector3(4.0f, 5.001f, 6.0f)) == FALSE);
+ }
+}
+
diff --git a/indra/llmath/tests/llbboxlocal_test.cpp b/indra/llmath/tests/llbboxlocal_test.cpp
new file mode 100644
index 0000000000..fb51deab4a
--- /dev/null
+++ b/indra/llmath/tests/llbboxlocal_test.cpp
@@ -0,0 +1,238 @@
+/**
+ * @file llbboxlocal_test.cpp
+ * @author Martin Reddy
+ * @date 2009-06-25
+ * @brief Test for llbboxlocal.cpp.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+#include "../llbboxlocal.h"
+
+namespace tut
+{
+ struct LLBBoxLocalData
+ {
+ };
+
+ typedef test_group<LLBBoxLocalData> factory;
+ typedef factory::object object;
+}
+
+namespace
+{
+ tut::factory llbboxlocal_test_factory("LLBBoxLocal");
+}
+
+namespace tut
+{
+ template<> template<>
+ void object::test<1>()
+ {
+ //
+ // test the default constructor
+ //
+
+ LLBBoxLocal bbox1;
+
+ ensure_equals("Default bbox min", bbox1.getMin(), LLVector3(0.0f, 0.0f, 0.0f));
+ ensure_equals("Default bbox max", bbox1.getMax(), LLVector3(0.0f, 0.0f, 0.0f));
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ //
+ // test the non-default constructor
+ //
+
+ LLBBoxLocal bbox2(LLVector3(-1.0f, -2.0f, 0.0f), LLVector3(1.0f, 2.0f, 3.0f));
+
+ ensure_equals("Custom bbox min", bbox2.getMin(), LLVector3(-1.0f, -2.0f, 0.0f));
+ ensure_equals("Custom bbox max", bbox2.getMax(), LLVector3(1.0f, 2.0f, 3.0f));
+ }
+
+ template<> template<>
+ void object::test<3>()
+ {
+ //
+ // test the setMin()
+ //
+ // N.B. no validation is currently performed to ensure that the min
+ // and max vectors are actually the min/max values.
+ //
+
+ LLBBoxLocal bbox2;
+ bbox2.setMin(LLVector3(1.0f, 2.0f, 3.0f));
+
+ ensure_equals("Custom bbox min (2)", bbox2.getMin(), LLVector3(1.0f, 2.0f, 3.0f));
+ }
+
+ template<> template<>
+ void object::test<4>()
+ {
+ //
+ // test the setMax()
+ //
+ // N.B. no validation is currently performed to ensure that the min
+ // and max vectors are actually the min/max values.
+ //
+
+ LLBBoxLocal bbox2;
+ bbox2.setMax(LLVector3(10.0f, 20.0f, 30.0f));
+
+ ensure_equals("Custom bbox max (2)", bbox2.getMax(), LLVector3(10.0f, 20.0f, 30.0f));
+ }
+
+ template<> template<>
+ void object::test<5>()
+ {
+ //
+ // test the getCenter() method
+ //
+
+ ensure_equals("Default bbox center", LLBBoxLocal().getCenter(), LLVector3(0.0f, 0.0f, 0.0f));
+
+ LLBBoxLocal bbox1(LLVector3(-1.0f, -1.0f, -1.0f), LLVector3(0.0f, 0.0f, 0.0f));
+
+ ensure_equals("Custom bbox center", bbox1.getCenter(), LLVector3(-0.5f, -0.5f, -0.5f));
+
+ LLBBoxLocal bbox2(LLVector3(0.0f, 0.0f, 0.0f), LLVector3(-1.0f, -1.0f, -1.0f));
+
+ ensure_equals("Invalid bbox center", bbox2.getCenter(), LLVector3(-0.5f, -0.5f, -0.5f));
+ }
+
+ template<> template<>
+ void object::test<6>()
+ {
+ //
+ // test the getExtent() method
+ //
+
+ LLBBoxLocal bbox2(LLVector3(0.0f, 0.0f, 0.0f), LLVector3(-1.0f, -1.0f, -1.0f));
+
+ ensure_equals("Default bbox extent", LLBBoxLocal().getExtent(), LLVector3(0.0f, 0.0f, 0.0f));
+
+ LLBBoxLocal bbox3(LLVector3(-1.0f, -1.0f, -1.0f), LLVector3(1.0f, 2.0f, 0.0f));
+
+ ensure_equals("Custom bbox extent", bbox3.getExtent(), LLVector3(2.0f, 3.0f, 1.0f));
+ }
+
+ template<> template<>
+ void object::test<7>()
+ {
+ //
+ // test the addPoint() method
+ //
+ // N.B. if you create an empty bbox and then add points,
+ // the vector (0, 0, 0) will always be part of the bbox.
+ // (Fixing this would require adding a bool to the class size).
+ //
+
+ LLBBoxLocal bbox1;
+ bbox1.addPoint(LLVector3(-1.0f, -2.0f, -3.0f));
+ bbox1.addPoint(LLVector3(3.0f, 4.0f, 5.0f));
+
+ ensure_equals("Custom BBox center (1)", bbox1.getCenter(), LLVector3(1.0f, 1.0f, 1.0f));
+ ensure_equals("Custom BBox min (1)", bbox1.getMin(), LLVector3(-1.0f, -2.0f, -3.0f));
+ ensure_equals("Custom BBox max (1)", bbox1.getMax(), LLVector3(3.0f, 4.0f, 5.0f));
+
+ bbox1.addPoint(LLVector3(0.0f, 0.0f, 0.0f));
+ bbox1.addPoint(LLVector3(1.0f, 2.0f, 3.0f));
+ bbox1.addPoint(LLVector3(2.0f, 2.0f, 2.0f));
+
+ ensure_equals("Custom BBox center (2)", bbox1.getCenter(), LLVector3(1.0f, 1.0f, 1.0f));
+ ensure_equals("Custom BBox min (2)", bbox1.getMin(), LLVector3(-1.0f, -2.0f, -3.0f));
+ ensure_equals("Custom BBox max (2)", bbox1.getMax(), LLVector3(3.0f, 4.0f, 5.0f));
+
+ bbox1.addPoint(LLVector3(5.0f, 5.0f, 5.0f));
+
+ ensure_equals("Custom BBox center (3)", bbox1.getCenter(), LLVector3(2.0f, 1.5f, 1.0f));
+ ensure_equals("Custom BBox min (3)", bbox1.getMin(), LLVector3(-1.0f, -2.0f, -3.0f));
+ ensure_equals("Custom BBox max (3)", bbox1.getMax(), LLVector3(5.0f, 5.0f, 5.0f));
+ }
+
+ template<> template<>
+ void object::test<8>()
+ {
+ //
+ // test the addBBox() methods
+ //
+ // N.B. if you create an empty bbox and then add points,
+ // the vector (0, 0, 0) will always be part of the bbox.
+ // (Fixing this would require adding a bool to the class size).
+ //
+
+ LLBBoxLocal bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLVector3(2.0f, 2.0f, 2.0f));
+ bbox2.addBBox(LLBBoxLocal(LLVector3(1.5f, 1.5f, 1.5f), LLVector3(3.0f, 3.0f, 3.0f)));
+
+ ensure_equals("Custom BBox center (4)", bbox2.getCenter(), LLVector3(2.0f, 2.0f, 2.0f));
+ ensure_equals("Custom BBox min (4)", bbox2.getMin(), LLVector3(1.0f, 1.0f, 1.0f));
+ ensure_equals("Custom BBox max (4)", bbox2.getMax(), LLVector3(3.0f, 3.0f, 3.0f));
+
+ bbox2.addBBox(LLBBoxLocal(LLVector3(-1.0f, -1.0f, -1.0f), LLVector3(0.0f, 0.0f, 0.0f)));
+
+ ensure_equals("Custom BBox center (5)", bbox2.getCenter(), LLVector3(1.0f, 1.0f, 1.0f));
+ ensure_equals("Custom BBox min (5)", bbox2.getMin(), LLVector3(-1.0f, -1.0f, -1.0f));
+ ensure_equals("Custom BBox max (5)", bbox2.getMax(), LLVector3(3.0f, 3.0f, 3.0f));
+ }
+
+ template<> template<>
+ void object::test<9>()
+ {
+ //
+ // test the expand() method
+ //
+
+ LLBBoxLocal bbox1;
+ bbox1.expand(0.0f);
+
+ ensure_equals("Zero-expanded Default BBox center", bbox1.getCenter(), LLVector3(0.0f, 0.0f, 0.0f));
+
+ LLBBoxLocal bbox2(LLVector3(1.0f, 2.0f, 3.0f), LLVector3(3.0f, 4.0f, 5.0f));
+ bbox2.expand(0.0f);
+
+ ensure_equals("Zero-expanded BBox center", bbox2.getCenter(), LLVector3(2.0f, 3.0f, 4.0f));
+ ensure_equals("Zero-expanded BBox min", bbox2.getMin(), LLVector3(1.0f, 2.0f, 3.0f));
+ ensure_equals("Zero-expanded BBox max", bbox2.getMax(), LLVector3(3.0f, 4.0f, 5.0f));
+
+ bbox2.expand(0.5f);
+
+ ensure_equals("Positive-expanded BBox center", bbox2.getCenter(), LLVector3(2.0f, 3.0f, 4.0f));
+ ensure_equals("Positive-expanded BBox min", bbox2.getMin(), LLVector3(0.5f, 1.5f, 2.5f));
+ ensure_equals("Positive-expanded BBox max", bbox2.getMax(), LLVector3(3.5f, 4.5f, 5.5f));
+
+ bbox2.expand(-1.0f);
+
+ ensure_equals("Negative-expanded BBox center", bbox2.getCenter(), LLVector3(2.0f, 3.0f, 4.0f));
+ ensure_equals("Negative-expanded BBox min", bbox2.getMin(), LLVector3(1.5f, 2.5f, 3.5f));
+ ensure_equals("Negative-expanded BBox max", bbox2.getMax(), LLVector3(2.5f, 3.5f, 4.5f));
+ }
+}
diff --git a/indra/llmath/tests/llmodularmath_test.cpp b/indra/llmath/tests/llmodularmath_test.cpp
new file mode 100644
index 0000000000..dc61c85859
--- /dev/null
+++ b/indra/llmath/tests/llmodularmath_test.cpp
@@ -0,0 +1,82 @@
+/**
+ * @file modularmath_test.cpp
+ * @author babbage
+ * @date 2008-09
+ * @brief llmodularmath tests
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../llmodularmath.h"
+
+#include "../test/lltut.h"
+
+namespace tut
+{
+ struct modularmath_data
+ {
+ };
+ typedef test_group<modularmath_data> modularmath_test;
+ typedef modularmath_test::object modularmath_object;
+ tut::modularmath_test modularmath_testcase("modularmath");
+
+ template<> template<>
+ void modularmath_object::test<1>()
+ {
+ // lhs < rhs
+ const U32 lhs = 0x000001;
+ const U32 rhs = 0xFFFFFF;
+ const U32 width = 24;
+ U32 result = LLModularMath::subtract<width>(lhs, rhs);
+ ensure_equals("diff(0x000001, 0xFFFFFF, 24)", result, 2);
+ }
+
+ template<> template<>
+ void modularmath_object::test<2>()
+ {
+ // lhs > rhs
+ const U32 lhs = 0x000002;
+ const U32 rhs = 0x000001;
+ const U32 width = 24;
+ U32 result = LLModularMath::subtract<width>(lhs, rhs);
+ ensure_equals("diff(0x000002, 0x000001, 24)", result, 1);
+ }
+
+ template<> template<>
+ void modularmath_object::test<3>()
+ {
+ // lhs == rhs
+ const U32 lhs = 0xABCDEF;
+ const U32 rhs = 0xABCDEF;
+ const U32 width = 24;
+ U32 result = LLModularMath::subtract<width>(lhs, rhs);
+ ensure_equals("diff(0xABCDEF, 0xABCDEF, 24)", result, 0);
+ }
+}
diff --git a/indra/llmath/tests/llquaternion_test.cpp b/indra/llmath/tests/llquaternion_test.cpp
new file mode 100644
index 0000000000..2d27d1eb32
--- /dev/null
+++ b/indra/llmath/tests/llquaternion_test.cpp
@@ -0,0 +1,666 @@
+/**
+ * @file llquaternion_test.cpp
+ * @author Adroit
+ * @date 2007-03
+ * @brief Test cases of llquaternion.h
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+
+#include "../llquaternion.h"
+#include "../v4math.h"
+#include "../v3math.h"
+#include "../v3dmath.h"
+#include "../m4math.h"
+#include "../m3math.h"
+
+namespace tut
+{
+ struct llquat_test
+ {
+ };
+ typedef test_group<llquat_test> llquat_test_t;
+ typedef llquat_test_t::object llquat_test_object_t;
+ tut::llquat_test_t tut_llquat_test("llquat");
+
+ //test case for LLQuaternion::LLQuaternion(void) fn.
+ template<> template<>
+ void llquat_test_object_t::test<1>()
+ {
+ LLQuaternion llquat;
+ ensure("LLQuaternion::LLQuaternion() failed", 0.f == llquat.mQ[0] &&
+ 0.f == llquat.mQ[1] &&
+ 0.f == llquat.mQ[2] &&
+ 1.f == llquat.mQ[3]);
+ }
+
+ //test case for explicit LLQuaternion(const LLMatrix4 &mat) fn.
+ template<> template<>
+ void llquat_test_object_t::test<2>()
+ {
+ LLMatrix4 llmat;
+ LLVector4 vector1(2.0f, 1.0f, 3.0f, 6.0f);
+ LLVector4 vector2(5.0f, 6.0f, 0.0f, 1.0f);
+ LLVector4 vector3(2.0f, 1.0f, 2.0f, 9.0f);
+ LLVector4 vector4(3.0f, 8.0f, 1.0f, 5.0f);
+
+ llmat.initRows(vector1, vector2, vector3, vector4);
+ ensure("explicit LLQuaternion(const LLMatrix4 &mat) failed", 2.0f == llmat.mMatrix[0][0] &&
+ 1.0f == llmat.mMatrix[0][1] &&
+ 3.0f == llmat.mMatrix[0][2] &&
+ 6.0f == llmat.mMatrix[0][3] &&
+ 5.0f == llmat.mMatrix[1][0] &&
+ 6.0f == llmat.mMatrix[1][1] &&
+ 0.0f == llmat.mMatrix[1][2] &&
+ 1.0f == llmat.mMatrix[1][3] &&
+ 2.0f == llmat.mMatrix[2][0] &&
+ 1.0f == llmat.mMatrix[2][1] &&
+ 2.0f == llmat.mMatrix[2][2] &&
+ 9.0f == llmat.mMatrix[2][3] &&
+ 3.0f == llmat.mMatrix[3][0] &&
+ 8.0f == llmat.mMatrix[3][1] &&
+ 1.0f == llmat.mMatrix[3][2] &&
+ 5.0f == llmat.mMatrix[3][3]);
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<3>()
+ {
+ LLMatrix3 llmat;
+
+ LLVector3 vect1(3.4028234660000000f , 234.56f, 4234.442234f);
+ LLVector3 vect2(741.434f, 23.00034f, 6567.223423f);
+ LLVector3 vect3(566.003034f, 12.98705f, 234.764423f);
+ llmat.setRows(vect1, vect2, vect3);
+
+ ensure("LLMatrix3::setRows fn failed.", 3.4028234660000000f == llmat.mMatrix[0][0] &&
+ 234.56f == llmat.mMatrix[0][1] &&
+ 4234.442234f == llmat.mMatrix[0][2] &&
+ 741.434f == llmat.mMatrix[1][0] &&
+ 23.00034f == llmat.mMatrix[1][1] &&
+ 6567.223423f == llmat.mMatrix[1][2] &&
+ 566.003034f == llmat.mMatrix[2][0] &&
+ 12.98705f == llmat.mMatrix[2][1] &&
+ 234.764423f == llmat.mMatrix[2][2]);
+ }
+
+ //test case for LLQuaternion(F32 x, F32 y, F32 z, F32 w), setQuatInit() and normQuat() fns.
+ template<> template<>
+ void llquat_test_object_t::test<4>()
+ {
+ F32 x_val = 3.0f;
+ F32 y_val = 2.0f;
+ F32 z_val = 6.0f;
+ F32 w_val = 1.0f;
+
+ LLQuaternion res_quat;
+ res_quat.setQuatInit(x_val, y_val, z_val, w_val);
+ res_quat.normQuat();
+
+ ensure("LLQuaternion::normQuat() fn failed",
+ is_approx_equal(0.42426407f, res_quat.mQ[0]) &&
+ is_approx_equal(0.28284273f, res_quat.mQ[1]) &&
+ is_approx_equal(0.84852815f, res_quat.mQ[2]) &&
+ is_approx_equal(0.14142136f, res_quat.mQ[3]));
+
+ x_val = 0.0f;
+ y_val = 0.0f;
+ z_val = 0.0f;
+ w_val = 0.0f;
+
+ res_quat.setQuatInit(x_val, y_val, z_val, w_val);
+ res_quat.normQuat();
+
+ ensure("LLQuaternion::normQuat() fn. failed.",
+ is_approx_equal(0.0f, res_quat.mQ[0]) &&
+ is_approx_equal(0.0f, res_quat.mQ[1]) &&
+ is_approx_equal(0.0f, res_quat.mQ[2]) &&
+ is_approx_equal(1.0f, res_quat.mQ[3]));
+
+
+ ensure("LLQuaternion::normQuat() fn. failed.",
+ is_approx_equal(0.0f, res_quat.mQ[0]) &&
+ is_approx_equal(0.0f, res_quat.mQ[1]) &&
+ is_approx_equal(0.0f, res_quat.mQ[2]) &&
+ is_approx_equal(1.0f, res_quat.mQ[3]));
+ }
+
+ //test case for conjQuat() and transQuat() fns.
+ template<> template<>
+ void llquat_test_object_t::test<5>()
+ {
+ F32 x_val = 3.0f;
+ F32 y_val = 2.0f;
+ F32 z_val = 6.0f;
+ F32 w_val = 1.0f;
+
+ LLQuaternion res_quat;
+ LLQuaternion result, result1;
+ result1 = result = res_quat.setQuatInit(x_val, y_val, z_val, w_val);
+
+ result.conjQuat();
+ result1.transQuat();
+
+ ensure("LLQuaternion::conjQuat and LLQuaternion::transQuat failed ",
+ is_approx_equal(result1.mQ[0], result.mQ[0]) &&
+ is_approx_equal(result1.mQ[1], result.mQ[1]) &&
+ is_approx_equal(result1.mQ[2], result.mQ[2]));
+
+ }
+
+ //test case for dot(const LLQuaternion &a, const LLQuaternion &b) fn.
+ template<> template<>
+ void llquat_test_object_t::test<6>()
+ {
+ LLQuaternion quat1(3.0f, 2.0f, 6.0f, 0.0f), quat2(1.0f, 1.0f, 1.0f, 1.0f);
+ ensure("1. The two values are different", llround(12.000000f, 2) == llround(dot(quat1, quat2), 2));
+
+ LLQuaternion quat0(3.0f, 9.334f, 34.5f, 23.0f), quat(34.5f, 23.23f, 2.0f, 45.5f);
+ ensure("2. The two values are different", llround(1435.828807f, 2) == llround(dot(quat0, quat), 2));
+ }
+
+ //test case for LLQuaternion &LLQuaternion::constrain(F32 radians) fn.
+ template<> template<>
+ void llquat_test_object_t::test<7>()
+ {
+ F32 radian = 60.0f;
+ LLQuaternion quat(3.0f, 2.0f, 6.0f, 0.0f);
+ LLQuaternion quat1;
+ quat1 = quat.constrain(radian);
+ ensure("1. LLQuaternion::constrain(F32 radians) failed",
+ is_approx_equal_fraction(-0.423442f, quat1.mQ[0], 8) &&
+ is_approx_equal_fraction(-0.282295f, quat1.mQ[1], 8) &&
+ is_approx_equal_fraction(-0.846884f, quat1.mQ[2], 8) &&
+ is_approx_equal_fraction(0.154251f, quat1.mQ[3], 8));
+
+
+ radian = 30.0f;
+ LLQuaternion quat0(37.50f, 12.0f, 86.023f, 40.32f);
+ quat1 = quat0.constrain(radian);
+
+ ensure("2. LLQuaternion::constrain(F32 radians) failed",
+ is_approx_equal_fraction(37.500000f, quat1.mQ[0], 8) &&
+ is_approx_equal_fraction(12.0000f, quat1.mQ[1], 8) &&
+ is_approx_equal_fraction(86.0230f, quat1.mQ[2], 8) &&
+ is_approx_equal_fraction(40.320000f, quat1.mQ[3], 8));
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<8>()
+ {
+ F32 value1 = 15.0f;
+ LLQuaternion quat1(1.0f, 2.0f, 4.0f, 1.0f);
+ LLQuaternion quat2(4.0f, 3.0f, 6.5f, 9.7f);
+ LLQuaternion res_lerp, res_slerp, res_nlerp;
+
+ //test case for lerp(F32 t, const LLQuaternion &q) fn.
+ res_lerp = lerp(value1, quat1);
+ ensure("1. LLQuaternion lerp(F32 t, const LLQuaternion &q) failed",
+ is_approx_equal_fraction(0.181355f, res_lerp.mQ[0], 16) &&
+ is_approx_equal_fraction(0.362711f, res_lerp.mQ[1], 16) &&
+ is_approx_equal_fraction(0.725423f, res_lerp.mQ[2], 16) &&
+ is_approx_equal_fraction(0.556158f, res_lerp.mQ[3], 16));
+
+ //test case for lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) fn.
+ res_lerp = lerp(value1, quat1, quat2);
+ ensure("2. LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) failed",
+ is_approx_equal_fraction(0.314306f, res_lerp.mQ[0], 16) &&
+ is_approx_equal_fraction(0.116156f, res_lerp.mQ[1], 16) &&
+ is_approx_equal_fraction(0.283559f, res_lerp.mQ[2], 16) &&
+ is_approx_equal_fraction(0.898506f, res_lerp.mQ[3], 16));
+
+ //test case for slerp( F32 u, const LLQuaternion &a, const LLQuaternion &b ) fn.
+ res_slerp = slerp(value1, quat1, quat2);
+ ensure("3. LLQuaternion slerp( F32 u, const LLQuaternion &a, const LLQuaternion &b) failed",
+ is_approx_equal_fraction(46.000f, res_slerp.mQ[0], 16) &&
+ is_approx_equal_fraction(17.00f, res_slerp.mQ[1], 16) &&
+ is_approx_equal_fraction(41.5f, res_slerp.mQ[2], 16) &&
+ is_approx_equal_fraction(131.5f, res_slerp.mQ[3], 16));
+
+ //test case for nlerp(F32 t, const LLQuaternion &a, const LLQuaternion &b) fn.
+ res_nlerp = nlerp(value1, quat1, quat2);
+ ensure("4. LLQuaternion nlerp(F32 t, const LLQuaternion &a, const LLQuaternion &b) failed",
+ is_approx_equal_fraction(0.314306f, res_nlerp.mQ[0], 16) &&
+ is_approx_equal_fraction(0.116157f, res_nlerp.mQ[1], 16) &&
+ is_approx_equal_fraction(0.283559f, res_nlerp.mQ[2], 16) &&
+ is_approx_equal_fraction(0.898506f, res_nlerp.mQ[3], 16));
+
+ //test case for nlerp(F32 t, const LLQuaternion &q) fn.
+ res_slerp = slerp(value1, quat1);
+ ensure("5. LLQuaternion slerp(F32 t, const LLQuaternion &q) failed",
+ is_approx_equal_fraction(1.0f, res_slerp.mQ[0], 16) &&
+ is_approx_equal_fraction(2.0f, res_slerp.mQ[1], 16) &&
+ is_approx_equal_fraction(4.0000f, res_slerp.mQ[2], 16) &&
+ is_approx_equal_fraction(1.000f, res_slerp.mQ[3], 16));
+
+ LLQuaternion quat3(2.0f, 1.0f, 5.5f, 10.5f);
+ LLQuaternion res_nlerp1;
+ value1 = 100.0f;
+ res_nlerp1 = nlerp(value1, quat3);
+ ensure("6. LLQuaternion nlerp(F32 t, const LLQuaternion &q) failed",
+ is_approx_equal_fraction(0.268245f, res_nlerp1.mQ[0], 16) && is_approx_equal_fraction(0.134122f, res_nlerp1.mQ[1], 2) &&
+ is_approx_equal_fraction(0.737673f, res_nlerp1.mQ[2], 16) &&
+ is_approx_equal_fraction(0.604892f, res_nlerp1.mQ[3], 16));
+
+ //test case for lerp(F32 t, const LLQuaternion &q) fn.
+ res_lerp = lerp(value1, quat2);
+ ensure("7. LLQuaternion lerp(F32 t, const LLQuaternion &q) failed",
+ is_approx_equal_fraction(0.404867f, res_lerp.mQ[0], 16) &&
+ is_approx_equal_fraction(0.303650f, res_lerp.mQ[1], 16) &&
+ is_approx_equal_fraction(0.657909f, res_lerp.mQ[2], 16) &&
+ is_approx_equal_fraction(0.557704f, res_lerp.mQ[3], 16));
+
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<9>()
+ {
+ //test case for LLQuaternion operator*(const LLQuaternion &a, const LLQuaternion &b) fn
+ LLQuaternion quat1(1.0f, 2.5f, 3.5f, 5.5f);
+ LLQuaternion quat2(4.0f, 3.0f, 5.0f, 1.0f);
+ LLQuaternion result = quat1 * quat2;
+ ensure("1. LLQuaternion Operator* failed", (21.0f == result.mQ[0]) &&
+ (10.0f == result.mQ[1]) &&
+ (38.0f == result.mQ[2]) &&
+ (-23.5f == result.mQ[3]));
+
+ LLQuaternion quat3(2341.340f, 2352.345f, 233.25f, 7645.5f);
+ LLQuaternion quat4(674.067f, 893.0897f, 578.0f, 231.0f);
+ result = quat3 * quat4;
+ ensure("2. LLQuaternion Operator* failed", (4543086.5f == result.mQ[0]) &&
+ (8567578.0f == result.mQ[1]) &&
+ (3967591.25f == result.mQ[2]) &&
+ is_approx_equal(-2047783.25f, result.mQ[3]));
+
+ //inline LLQuaternion operator+(const LLQuaternion &a, const LLQuaternion &b)fn.
+ result = quat1 + quat2;
+ ensure("3. LLQuaternion operator+ failed", (5.0f == result.mQ[0]) &&
+ (5.5f == result.mQ[1]) &&
+ (8.5f == result.mQ[2]) &&
+ (6.5f == result.mQ[3]));
+
+ result = quat3 + quat4;
+ ensure(
+ "4. LLQuaternion operator+ failed",
+ is_approx_equal(3015.407227f, result.mQ[0]) &&
+ is_approx_equal(3245.434570f, result.mQ[1]) &&
+ (811.25f == result.mQ[2]) &&
+ (7876.5f == result.mQ[3]));
+
+ //inline LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b) fn
+ result = quat1 - quat2;
+ ensure(
+ "5. LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b) failed",
+ (-3.0f == result.mQ[0]) &&
+ (-0.5f == result.mQ[1]) &&
+ (-1.5f == result.mQ[2]) &&
+ (4.5f == result.mQ[3]));
+
+ result = quat3 - quat4;
+ ensure(
+ "6. LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b) failed",
+ is_approx_equal(1667.273071f, result.mQ[0]) &&
+ is_approx_equal(1459.255249f, result.mQ[1]) &&
+ (-344.75f == result.mQ[2]) &&
+ (7414.50f == result.mQ[3]));
+ }
+
+ //test case for LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) fn.
+ template<> template<>
+ void llquat_test_object_t::test<10>()
+ {
+ LLVector4 vect(12.0f, 5.0f, 60.0f, 75.1f);
+ LLQuaternion quat(2323.034f, 23.5f, 673.23f, 57667.5f);
+ LLVector4 result = vect * quat;
+ ensure(
+ "1. LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) failed",
+ is_approx_equal(39928406016.0f, result.mV[0]) &&
+ // gcc on x86 actually gives us more precision than we were expecting, verified with -ffloat-store - we forgive this
+ (1457802240.0f >= result.mV[1]) && // gcc+x86+linux
+ (1457800960.0f <= result.mV[1]) && // elsewhere
+ is_approx_equal(200580612096.0f, result.mV[2]) &&
+ (75.099998f == result.mV[3]));
+
+ LLVector4 vect1(22.0f, 45.0f, 40.0f, 78.1f);
+ LLQuaternion quat1(2.034f, 45.5f, 37.23f, 7.5f);
+ result = vect1 * quat1;
+ ensure(
+ "2. LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) failed",
+ is_approx_equal(-58153.5390f, result.mV[0]) &&
+ (183787.8125f == result.mV[1]) &&
+ (116864.164063f == result.mV[2]) &&
+ (78.099998f == result.mV[3]));
+ }
+
+ //test case for LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) fn.
+ template<> template<>
+ void llquat_test_object_t::test<11>()
+ {
+ LLVector3 vect(12.0f, 5.0f, 60.0f);
+ LLQuaternion quat(23.5f, 6.5f, 3.23f, 56.5f);
+ LLVector3 result = vect * quat;
+ ensure(
+ "1. LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) failed",
+ is_approx_equal(97182.953125f,result.mV[0]) &&
+ is_approx_equal(-135405.640625f, result.mV[1]) &&
+ is_approx_equal(162986.140f, result.mV[2]));
+
+ LLVector3 vect1(5.0f, 40.0f, 78.1f);
+ LLQuaternion quat1(2.034f, 45.5f, 37.23f, 7.5f);
+ result = vect1 * quat1;
+ ensure(
+ "2. LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) failed",
+ is_approx_equal(33217.703f, result.mV[0]) &&
+ is_approx_equal(295383.8125f, result.mV[1]) &&
+ is_approx_equal(84718.140f, result.mV[2]));
+ }
+
+ //test case for LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) fn.
+ template<> template<>
+ void llquat_test_object_t::test<12>()
+ {
+ LLVector3d vect(-2.0f, 5.0f, -6.0f);
+ LLQuaternion quat(-3.5f, 4.5f, 3.5f, 6.5f);
+ LLVector3d result = vect * quat;
+ ensure(
+ "1. LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) failed ",
+ (-633.0f == result.mdV[0]) &&
+ (-300.0f == result.mdV[1]) &&
+ (-36.0f == result.mdV[2]));
+
+ LLVector3d vect1(5.0f, -4.5f, 8.21f);
+ LLQuaternion quat1(2.0f, 4.5f, -7.2f, 9.5f);
+ result = vect1 * quat1;
+ ensure(
+ "2. LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) failed",
+ is_approx_equal_fraction(-120.29f, (F32) result.mdV[0], 8) &&
+ is_approx_equal_fraction(-1683.958f, (F32) result.mdV[1], 8) &&
+ is_approx_equal_fraction(516.56f, (F32) result.mdV[2], 8));
+
+ LLVector3d vect2(2.0f, 3.5f, 1.1f);
+ LLQuaternion quat2(1.0f, 4.0f, 2.0f, 5.0f);
+ result = vect2 * quat2;
+ ensure(
+ "3. LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) failed",
+ is_approx_equal_fraction(18.400001f, (F32) result.mdV[0], 8) &&
+ is_approx_equal_fraction(188.6f, (F32) result.mdV[1], 8) &&
+ is_approx_equal_fraction(32.20f, (F32) result.mdV[2], 8));
+ }
+
+ //test case for inline LLQuaternion operator-(const LLQuaternion &a) fn.
+ template<> template<>
+ void llquat_test_object_t::test<13>()
+ {
+ LLQuaternion quat(23.5f, 34.5f, 16723.4f, 324.7f);
+ LLQuaternion result = -quat;
+ ensure(
+ "1. LLQuaternion operator-(const LLQuaternion &a) failed",
+ (-23.5f == result.mQ[0]) &&
+ (-34.5f == result.mQ[1]) &&
+ (-16723.4f == result.mQ[2]) &&
+ (-324.7f == result.mQ[3]));
+
+ LLQuaternion quat1(-3.5f, -34.5f, -16.4f, -154.7f);
+ result = -quat1;
+ ensure(
+ "2. LLQuaternion operator-(const LLQuaternion &a) failed.",
+ (3.5f == result.mQ[0]) &&
+ (34.5f == result.mQ[1]) &&
+ (16.4f == result.mQ[2]) &&
+ (154.7f == result.mQ[3]));
+ }
+
+ //test case for inline LLQuaternion operator*(F32 a, const LLQuaternion &q) and
+ //inline LLQuaternion operator*(F32 a, const LLQuaternion &q) fns.
+ template<> template<>
+ void llquat_test_object_t::test<14>()
+ {
+ LLQuaternion quat_value(9.0f, 8.0f, 7.0f, 6.0f);
+ F32 a =3.5f;
+ LLQuaternion result = a * quat_value;
+ LLQuaternion result1 = quat_value * a;
+
+ ensure(
+ "1. LLQuaternion operator* failed",
+ (result.mQ[0] == result1.mQ[0]) &&
+ (result.mQ[1] == result1.mQ[1]) &&
+ (result.mQ[2] == result1.mQ[2]) &&
+ (result.mQ[3] == result1.mQ[3]));
+
+
+ LLQuaternion quat_val(9454.0f, 43568.3450f, 456343247.0343f, 2346.03434f);
+ a =-3324.3445f;
+ result = a * quat_val;
+ result1 = quat_val * a;
+
+ ensure(
+ "2. LLQuaternion operator* failed",
+ (result.mQ[0] == result1.mQ[0]) &&
+ (result.mQ[1] == result1.mQ[1]) &&
+ (result.mQ[2] == result1.mQ[2]) &&
+ (result.mQ[3] == result1.mQ[3]));
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<15>()
+ {
+ // test cases for inline LLQuaternion operator~(const LLQuaternion &a)
+ LLQuaternion quat_val(2323.634f, -43535.4f, 3455.88f, -32232.45f);
+ LLQuaternion result = ~quat_val;
+ ensure(
+ "1. LLQuaternion operator~(const LLQuaternion &a) failed ",
+ (-2323.634f == result.mQ[0]) &&
+ (43535.4f == result.mQ[1]) &&
+ (-3455.88f == result.mQ[2]) &&
+ (-32232.45f == result.mQ[3]));
+
+ //test case for inline bool LLQuaternion::operator==(const LLQuaternion &b) const
+ LLQuaternion quat_val1(2323.634f, -43535.4f, 3455.88f, -32232.45f);
+ LLQuaternion quat_val2(2323.634f, -43535.4f, 3455.88f, -32232.45f);
+ ensure(
+ "2. LLQuaternion::operator==(const LLQuaternion &b) failed",
+ quat_val1 == quat_val2);
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<16>()
+ {
+ //test case for inline bool LLQuaternion::operator!=(const LLQuaternion &b) const
+ LLQuaternion quat_val1(2323.634f, -43535.4f, 3455.88f, -32232.45f);
+ LLQuaternion quat_val2(0, -43535.4f, 3455.88f, -32232.45f);
+ ensure("LLQuaternion::operator!=(const LLQuaternion &b) failed", quat_val1 != quat_val2);
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<17>()
+ {
+ //test case for LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order)
+ F32 x = 2.0f;
+ F32 y = 1.0f;
+ F32 z = 3.0f;
+
+ LLQuaternion result = mayaQ(x, y, z, LLQuaternion::XYZ);
+ ensure(
+ "1. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for XYZ",
+ is_approx_equal_fraction(0.0172174f, result.mQ[0], 16) &&
+ is_approx_equal_fraction(0.009179f, result.mQ[1], 16) &&
+ is_approx_equal_fraction(0.026020f, result.mQ[2], 16) &&
+ is_approx_equal_fraction(0.999471f, result.mQ[3], 16));
+
+ LLQuaternion result1 = mayaQ(x, y, z, LLQuaternion::YZX);
+ ensure(
+ "2. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for XYZ",
+ is_approx_equal_fraction(0.017217f, result1.mQ[0], 16) &&
+ is_approx_equal_fraction(0.008265f, result1.mQ[1], 16) &&
+ is_approx_equal_fraction(0.026324f, result1.mQ[2], 16) &&
+ is_approx_equal_fraction(0.999471f, result1.mQ[3], 16));
+
+ LLQuaternion result2 = mayaQ(x, y, z, LLQuaternion::ZXY);
+ ensure(
+ "3. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for ZXY",
+ is_approx_equal_fraction(0.017674f, result2.mQ[0], 16) &&
+ is_approx_equal_fraction(0.008265f, result2.mQ[1], 16) &&
+ is_approx_equal_fraction(0.026020f, result2.mQ[2], 16) &&
+ is_approx_equal_fraction(0.999471f, result2.mQ[3], 16));
+
+ LLQuaternion result3 = mayaQ(x, y, z, LLQuaternion::XZY);
+ ensure(
+ "4. TLLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for XZY",
+ is_approx_equal_fraction(0.017674f, result3.mQ[0], 16) &&
+ is_approx_equal_fraction(0.009179f, result3.mQ[1], 16) &&
+ is_approx_equal_fraction(0.026020f, result3.mQ[2], 16) &&
+ is_approx_equal_fraction(0.999463f, result3.mQ[3], 16));
+
+ LLQuaternion result4 = mayaQ(x, y, z, LLQuaternion::YXZ);
+ ensure(
+ "5. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for YXZ",
+ is_approx_equal_fraction(0.017217f, result4.mQ[0], 16) &&
+ is_approx_equal_fraction(0.009179f, result4.mQ[1], 16) &&
+ is_approx_equal_fraction(0.026324f, result4.mQ[2], 16) &&
+ is_approx_equal_fraction(0.999463f, result4.mQ[3], 16));
+
+ LLQuaternion result5 = mayaQ(x, y, z, LLQuaternion::ZYX);
+ ensure(
+ "6. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for ZYX",
+ is_approx_equal_fraction(0.017674f, result5.mQ[0], 16) &&
+ is_approx_equal_fraction(0.008265f, result5.mQ[1], 16) &&
+ is_approx_equal_fraction(0.026324f, result5.mQ[2], 16) &&
+ is_approx_equal_fraction(0.999463f, result5.mQ[3], 16));
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<18>()
+ {
+ // test case for friend std::ostream& operator<<(std::ostream &s, const LLQuaternion &a) fn
+ LLQuaternion a(1.0f, 1.0f, 1.0f, 1.0f);
+ std::ostringstream result_value;
+ result_value << a;
+ ensure_equals("1. Operator << failed", result_value.str(), "{ 1, 1, 1, 1 }");
+
+ LLQuaternion b(-31.034f, 231.2340f, 3451.344320f, -341.0f);
+ std::ostringstream result_value1;
+ result_value1 << b;
+ ensure_equals("2. Operator << failed", result_value1.str(), "{ -31.034, 231.234, 3451.34, -341 }");
+
+ LLQuaternion c(1.0f, 2.2f, 3.3f, 4.4f);
+ result_value << c;
+ ensure_equals("3. Operator << failed", result_value.str(), "{ 1, 1, 1, 1 }{ 1, 2.2, 3.3, 4.4 }");
+
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<19>()
+ {
+ //test case for const char *OrderToString( const LLQuaternion::Order order ) fn
+ const char* result = OrderToString(LLQuaternion::XYZ);
+ ensure("1. OrderToString failed for XYZ", (0 == strcmp("XYZ", result)));
+
+ result = OrderToString(LLQuaternion::YZX);
+ ensure("2. OrderToString failed for YZX", (0 == strcmp("YZX", result)));
+
+ result = OrderToString(LLQuaternion::ZXY);
+ ensure(
+ "3. OrderToString failed for ZXY",
+ (0 == strcmp("ZXY", result)) &&
+ (0 != strcmp("XYZ", result)) &&
+ (0 != strcmp("YXZ", result)) &&
+ (0 != strcmp("ZYX", result)) &&
+ (0 != strcmp("XYZ", result)));
+
+ result = OrderToString(LLQuaternion::XZY);
+ ensure("4. OrderToString failed for XZY", (0 == strcmp("XZY", result)));
+
+ result = OrderToString(LLQuaternion::ZYX);
+ ensure("5. OrderToString failed for ZYX", (0 == strcmp("ZYX", result)));
+
+ result = OrderToString(LLQuaternion::YXZ);
+ ensure("6.OrderToString failed for YXZ", (0 == strcmp("YXZ", result)));
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<20>()
+ {
+ //test case for LLQuaternion::Order StringToOrder( const char *str ) fn
+ int result = StringToOrder("XYZ");
+ ensure("1. LLQuaternion::Order StringToOrder(const char *str ) failed for XYZ", 0 == result);
+
+ result = StringToOrder("YZX");
+ ensure("2. LLQuaternion::Order StringToOrder(const char *str) failed for YZX", 1 == result);
+
+ result = StringToOrder("ZXY");
+ ensure("3. LLQuaternion::Order StringToOrder(const char *str) failed for ZXY", 2 == result);
+
+ result = StringToOrder("XZY");
+ ensure("4. LLQuaternion::Order StringToOrder(const char *str) failed for XZY", 3 == result);
+
+ result = StringToOrder("YXZ");
+ ensure("5. LLQuaternion::Order StringToOrder(const char *str) failed for YXZ", 4 == result);
+
+ result = StringToOrder("ZYX");
+ ensure("6. LLQuaternion::Order StringToOrder(const char *str) failed for ZYX", 5 == result);
+
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<21>()
+ {
+ //void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const fn
+ F32 angle_value = 90.0f;
+ LLVector3 vect(12.0f, 4.0f, 1.0f);
+ LLQuaternion llquat(angle_value, vect);
+ llquat.getAngleAxis(&angle_value, vect);
+ ensure(
+ "LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) failed",
+ is_approx_equal_fraction(2.035406f, angle_value, 16) &&
+ is_approx_equal_fraction(0.315244f, vect.mV[1], 16) &&
+ is_approx_equal_fraction(0.078811f, vect.mV[2], 16) &&
+ is_approx_equal_fraction(0.945733f, vect.mV[0], 16));
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<22>()
+ {
+ //test case for void LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const fn
+ F32 roll = -12.0f;
+ F32 pitch = -22.43f;
+ F32 yaw = 11.0f;
+
+ LLQuaternion llquat;
+ llquat.getEulerAngles(&roll, &pitch, &yaw);
+ ensure(
+ "LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) failed",
+ is_approx_equal(0.000f, llquat.mQ[0]) &&
+ is_approx_equal(0.000f, llquat.mQ[1]) &&
+ is_approx_equal(0.000f, llquat.mQ[2]) &&
+ is_approx_equal(1.000f, llquat.mQ[3]));
+ }
+
+}
diff --git a/indra/llmath/tests/llrect_test.cpp b/indra/llmath/tests/llrect_test.cpp
new file mode 100644
index 0000000000..c5e9e425bb
--- /dev/null
+++ b/indra/llmath/tests/llrect_test.cpp
@@ -0,0 +1,532 @@
+/**
+ * @file llrect_test.cpp
+ * @author Martin Reddy
+ * @date 2009-06-25
+ * @brief Test for llrect.cpp.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+#include "../llrect.h"
+
+namespace tut
+{
+ struct LLRectData
+ {
+ };
+
+ typedef test_group<LLRectData> factory;
+ typedef factory::object object;
+}
+
+namespace
+{
+ tut::factory llrect_test_factory("LLRect");
+}
+
+namespace tut
+{
+ template<> template<>
+ void object::test<1>()
+ {
+ //
+ // test the LLRect default constructor
+ //
+
+ LLSD zero;
+ zero.append(0); zero.append(0); zero.append(0); zero.append(0);
+
+ // default constructor
+ LLRect rect1;
+ ensure_equals("Empty rect", rect1.getValue(), zero);
+ ensure_equals("Empty rect left", rect1.mLeft, 0);
+ ensure_equals("Empty rect top", rect1.mTop, 0);
+ ensure_equals("Empty rect right", rect1.mRight, 0);
+ ensure_equals("Empty rect bottom", rect1.mBottom, 0);
+ ensure_equals("Empty rect width", rect1.getWidth(), 0);
+ ensure_equals("Empty rect height", rect1.getHeight(), 0);
+ ensure_equals("Empty rect centerx", rect1.getCenterX(), 0);
+ ensure_equals("Empty rect centery", rect1.getCenterY(), 0);
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ //
+ // test the LLRectf default constructor
+ //
+
+ LLSD zerof;
+ zerof.append(0.0f); zerof.append(0.0f); zerof.append(0.0f); zerof.append(0.0f);
+
+ LLRectf rect2;
+ ensure_equals("Empty rectf", rect2.getValue(), zerof);
+ ensure_equals("Empty rectf left", rect2.mLeft, 0.0f);
+ ensure_equals("Empty rectf top", rect2.mTop, 0.0f);
+ ensure_equals("Empty rectf right", rect2.mRight, 0.0f);
+ ensure_equals("Empty rectf bottom", rect2.mBottom, 0.0f);
+ ensure_equals("Empty rectf width", rect2.getWidth(), 0.0f);
+ ensure_equals("Empty rectf height", rect2.getHeight(), 0.0f);
+ ensure_equals("Empty rectf centerx", rect2.getCenterX(), 0.0f);
+ ensure_equals("Empty rectf centery", rect2.getCenterY(), 0.0f);
+ }
+
+ template<> template<>
+ void object::test<3>()
+ {
+ //
+ // test the LLRect constructor from another LLRect
+ //
+
+ LLRect rect3(LLRect(1, 6, 7, 2));
+ ensure_equals("Default rect left", rect3.mLeft, 1);
+ ensure_equals("Default rect top", rect3.mTop, 6);
+ ensure_equals("Default rect right", rect3.mRight, 7);
+ ensure_equals("Default rect bottom", rect3.mBottom, 2);
+ ensure_equals("Default rect width", rect3.getWidth(), 6);
+ ensure_equals("Default rect height", rect3.getHeight(), 4);
+ ensure_equals("Default rect centerx", rect3.getCenterX(), 4);
+ ensure_equals("Default rect centery", rect3.getCenterY(), 4);
+ }
+
+ template<> template<>
+ void object::test<4>()
+ {
+ //
+ // test the LLRectf four-float constructor
+ //
+
+ LLRectf rect4(1.0f, 5.0f, 6.0f, 2.0f);
+ ensure_equals("Default rectf left", rect4.mLeft, 1.0f);
+ ensure_equals("Default rectf top", rect4.mTop, 5.0f);
+ ensure_equals("Default rectf right", rect4.mRight, 6.0f);
+ ensure_equals("Default rectf bottom", rect4.mBottom, 2.0f);
+ ensure_equals("Default rectf width", rect4.getWidth(), 5.0f);
+ ensure_equals("Default rectf height", rect4.getHeight(), 3.0f);
+ ensure_equals("Default rectf centerx", rect4.getCenterX(), 3.5f);
+ ensure_equals("Default rectf centery", rect4.getCenterY(), 3.5f);
+ }
+
+ template<> template<>
+ void object::test<5>()
+ {
+ //
+ // test the LLRectf LLSD constructor
+ //
+
+ LLSD array;
+ array.append(-1.0f); array.append(0.0f); array.append(0.0f); array.append(-1.0f);
+ LLRectf rect5(array);
+ ensure_equals("LLSD rectf left", rect5.mLeft, -1.0f);
+ ensure_equals("LLSD rectf top", rect5.mTop, 0.0f);
+ ensure_equals("LLSD rectf right", rect5.mRight, 0.0f);
+ ensure_equals("LLSD rectf bottom", rect5.mBottom, -1.0f);
+ ensure_equals("LLSD rectf width", rect5.getWidth(), 1.0f);
+ ensure_equals("LLSD rectf height", rect5.getHeight(), 1.0f);
+ ensure_equals("LLSD rectf centerx", rect5.getCenterX(), -0.5f);
+ ensure_equals("LLSD rectf centery", rect5.getCenterY(), -0.5f);
+ }
+
+ template<> template<>
+ void object::test<6>()
+ {
+ //
+ // test directly setting the member variables for dimensions
+ //
+
+ LLRectf rectf;
+
+ rectf.mLeft = -1.0f;
+ rectf.mTop = 1.0f;
+ rectf.mRight = 1.0f;
+ rectf.mBottom = -1.0f;
+ ensure_equals("Member-set rectf left", rectf.mLeft, -1.0f);
+ ensure_equals("Member-set rectf top", rectf.mTop, 1.0f);
+ ensure_equals("Member-set rectf right", rectf.mRight, 1.0f);
+ ensure_equals("Member-set rectf bottom", rectf.mBottom, -1.0f);
+ ensure_equals("Member-set rectf width", rectf.getWidth(), 2.0f);
+ ensure_equals("Member-set rectf height", rectf.getHeight(), 2.0f);
+ ensure_equals("Member-set rectf centerx", rectf.getCenterX(), 0.0f);
+ ensure_equals("Member-set rectf centery", rectf.getCenterY(), 0.0f);
+ }
+
+ template<> template<>
+ void object::test<7>()
+ {
+ //
+ // test the setValue() method
+ //
+
+ LLRectf rectf;
+
+ LLSD array;
+ array.append(-1.0f); array.append(0.0f); array.append(0.0f); array.append(-1.0f);
+ rectf.setValue(array);
+ ensure_equals("setValue() rectf left", rectf.mLeft, -1.0f);
+ ensure_equals("setValue() rectf top", rectf.mTop, 0.0f);
+ ensure_equals("setValue() rectf right", rectf.mRight, 0.0f);
+ ensure_equals("setValue() rectf bottom", rectf.mBottom, -1.0f);
+ ensure_equals("setValue() rectf width", rectf.getWidth(), 1.0f);
+ ensure_equals("setValue() rectf height", rectf.getHeight(), 1.0f);
+ ensure_equals("setValue() rectf centerx", rectf.getCenterX(), -0.5f);
+ ensure_equals("setValue() rectf centery", rectf.getCenterY(), -0.5f);
+ }
+
+ template<> template<>
+ void object::test<8>()
+ {
+ //
+ // test the set() method
+ //
+
+ LLRect rect;
+
+ rect.set(10, 90, 70, 10);
+ ensure_equals("set() rectf left", rect.mLeft, 10);
+ ensure_equals("set() rectf top", rect.mTop, 90);
+ ensure_equals("set() rectf right", rect.mRight, 70);
+ ensure_equals("set() rectf bottom", rect.mBottom, 10);
+ ensure_equals("set() rectf width", rect.getWidth(), 60);
+ ensure_equals("set() rectf height", rect.getHeight(), 80);
+ ensure_equals("set() rectf centerx", rect.getCenterX(), 40);
+ ensure_equals("set() rectf centery", rect.getCenterY(), 50);
+ }
+
+ template<> template<>
+ void object::test<9>()
+ {
+ //
+ // test the setOriginAndSize() method
+ //
+
+ LLRectf rectf;
+
+ rectf.setOriginAndSize(0.0f, 0.0f, 2.0f, 1.0f);
+ ensure_equals("setOriginAndSize() rectf left", rectf.mLeft, 0.0f);
+ ensure_equals("setOriginAndSize() rectf top", rectf.mTop, 1.0f);
+ ensure_equals("setOriginAndSize() rectf right", rectf.mRight, 2.0f);
+ ensure_equals("setOriginAndSize() rectf bottom", rectf.mBottom, 0.0f);
+ ensure_equals("setOriginAndSize() rectf width", rectf.getWidth(), 2.0f);
+ ensure_equals("setOriginAndSize() rectf height", rectf.getHeight(), 1.0f);
+ ensure_equals("setOriginAndSize() rectf centerx", rectf.getCenterX(), 1.0f);
+ ensure_equals("setOriginAndSize() rectf centery", rectf.getCenterY(), 0.5f);
+ }
+
+ template<> template<>
+ void object::test<10>()
+ {
+ //
+ // test the setLeftTopAndSize() method
+ //
+
+ LLRectf rectf;
+
+ rectf.setLeftTopAndSize(0.0f, 0.0f, 2.0f, 1.0f);
+ ensure_equals("setLeftTopAndSize() rectf left", rectf.mLeft, 0.0f);
+ ensure_equals("setLeftTopAndSize() rectf top", rectf.mTop, 0.0f);
+ ensure_equals("setLeftTopAndSize() rectf right", rectf.mRight, 2.0f);
+ ensure_equals("setLeftTopAndSize() rectf bottom", rectf.mBottom, -1.0f);
+ ensure_equals("setLeftTopAndSize() rectf width", rectf.getWidth(), 2.0f);
+ ensure_equals("setLeftTopAndSize() rectf height", rectf.getHeight(), 1.0f);
+ ensure_equals("setLeftTopAndSize() rectf centerx", rectf.getCenterX(), 1.0f);
+ ensure_equals("setLeftTopAndSize() rectf centery", rectf.getCenterY(), -0.5f);
+ }
+
+ template<> template<>
+ void object::test<11>()
+ {
+ //
+ // test the setCenterAndSize() method
+ //
+
+ LLRectf rectf;
+
+ rectf.setCenterAndSize(0.0f, 0.0f, 2.0f, 1.0f);
+ ensure_equals("setCenterAndSize() rectf left", rectf.mLeft, -1.0f);
+ ensure_equals("setCenterAndSize() rectf top", rectf.mTop, 0.5f);
+ ensure_equals("setCenterAndSize() rectf right", rectf.mRight, 1.0f);
+ ensure_equals("setCenterAndSize() rectf bottom", rectf.mBottom, -0.5f);
+ ensure_equals("setCenterAndSize() rectf width", rectf.getWidth(), 2.0f);
+ ensure_equals("setCenterAndSize() rectf height", rectf.getHeight(), 1.0f);
+ ensure_equals("setCenterAndSize() rectf centerx", rectf.getCenterX(), 0.0f);
+ ensure_equals("setCenterAndSize() rectf centery", rectf.getCenterY(), 0.0f);
+ }
+
+ template<> template<>
+ void object::test<12>()
+ {
+ //
+ // test the validity checking method
+ //
+
+ LLRectf rectf;
+
+ rectf.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ ensure("BBox is valid", rectf.isValid());
+
+ rectf.mLeft = 2.0f;
+ ensure("BBox is not valid", ! rectf.isValid());
+
+ rectf.makeValid();
+ ensure("BBox forced valid", rectf.isValid());
+
+ rectf.set(-1.0f, -1.0f, -1.0f, -1.0f);
+ ensure("BBox(0,0,0,0) is valid", rectf.isValid());
+ }
+
+ template<> template<>
+ void object::test<13>()
+ {
+ //
+ // test the null checking methods
+ //
+
+ LLRectf rectf;
+
+ rectf.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ ensure("BBox is not Null", ! rectf.isEmpty());
+ ensure("BBox notNull", rectf.notEmpty());
+
+ rectf.mLeft = 2.0f;
+ rectf.makeValid();
+ ensure("BBox is now Null", rectf.isEmpty());
+
+ rectf.set(-1.0f, -1.0f, -1.0f, -1.0f);
+ ensure("BBox(0,0,0,0) is Null", rectf.isEmpty());
+ }
+
+ template<> template<>
+ void object::test<14>()
+ {
+ //
+ // test the (in)equality operators
+ //
+
+ LLRectf rect1, rect2;
+
+ rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ rect2.set(-1.0f, 0.9f, 1.0f, -1.0f);
+
+ ensure("rect1 == rect2 (false)", ! (rect1 == rect2));
+ ensure("rect1 != rect2 (true)", rect1 != rect2);
+
+ ensure("rect1 == rect1 (true)", rect1 == rect1);
+ ensure("rect1 != rect1 (false)", ! (rect1 != rect1));
+ }
+
+ template<> template<>
+ void object::test<15>()
+ {
+ //
+ // test the copy constructor
+ //
+
+ LLRectf rect1, rect2(rect1);
+
+ ensure("rect1 == rect2 (true)", rect1 == rect2);
+ ensure("rect1 != rect2 (false)", ! (rect1 != rect2));
+ }
+
+ template<> template<>
+ void object::test<16>()
+ {
+ //
+ // test the translate() method
+ //
+
+ LLRectf rect1(-1.0f, 1.0f, 1.0f, -1.0f);
+ LLRectf rect2(rect1);
+
+ rect1.translate(0.0f, 0.0f);
+
+ ensure("translate(0, 0)", rect1 == rect2);
+
+ rect1.translate(100.0f, 100.0f);
+ rect1.translate(-100.0f, -100.0f);
+
+ ensure("translate(100, 100) + translate(-100, -100)", rect1 == rect2);
+
+ rect1.translate(10.0f, 0.0f);
+ rect2.set(9.0f, 1.0f, 11.0f, -1.0f);
+ ensure("translate(10, 0)", rect1 == rect2);
+
+ rect1.translate(0.0f, 10.0f);
+ rect2.set(9.0f, 11.0f, 11.0f, 9.0f);
+ ensure("translate(0, 10)", rect1 == rect2);
+
+ rect1.translate(-10.0f, -10.0f);
+ rect2.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ ensure("translate(-10, -10)", rect1 == rect2);
+ }
+
+ template<> template<>
+ void object::test<17>()
+ {
+ //
+ // test the stretch() method
+ //
+
+ LLRectf rect1(-1.0f, 1.0f, 1.0f, -1.0f);
+ LLRectf rect2(rect1);
+
+ rect1.stretch(0.0f);
+ ensure("stretch(0)", rect1 == rect2);
+
+ rect1.stretch(0.0f, 0.0f);
+ ensure("stretch(0, 0)", rect1 == rect2);
+
+ rect1.stretch(10.0f);
+ rect1.stretch(-10.0f);
+ ensure("stretch(10) + stretch(-10)", rect1 == rect2);
+
+ rect1.stretch(2.0f, 1.0f);
+ rect2.set(-3.0f, 2.0f, 3.0f, -2.0f);
+ ensure("stretch(2, 1)", rect1 == rect2);
+ }
+
+
+ template<> template<>
+ void object::test<18>()
+ {
+ //
+ // test the unionWith() method
+ //
+
+ LLRectf rect1, rect2, rect3;
+
+ rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ rect2.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ rect3 = rect1;
+ rect3.unionWith(rect2);
+ ensure_equals("union with self", rect3, rect1);
+
+ rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ rect2.set(-2.0f, 2.0f, 0.0f, 0.0f);
+ rect3 = rect1;
+ rect3.unionWith(rect2);
+ ensure_equals("union - overlap", rect3, LLRectf(-2.0f, 2.0f, 1.0f, -1.0f));
+
+ rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ rect2.set(5.0f, 10.0f, 10.0f, 5.0f);
+ rect3 = rect1;
+ rect3.unionWith(rect2);
+ ensure_equals("union - no overlap", rect3, LLRectf(-1.0f, 10.0f, 10.0f, -1.0f));
+ }
+
+ template<> template<>
+ void object::test<19>()
+ {
+ //
+ // test the intersectWith() methods
+ //
+
+ LLRectf rect1, rect2, rect3;
+
+ rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ rect2.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ rect3 = rect1;
+ rect3.intersectWith(rect2);
+ ensure_equals("intersect with self", rect3, rect1);
+
+ rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ rect2.set(-2.0f, 2.0f, 0.0f, 0.0f);
+ rect3 = rect1;
+ rect3.intersectWith(rect2);
+ ensure_equals("intersect - overlap", rect3, LLRectf(-1.0f, 1.0f, 0.0f, 0.0f));
+
+ rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ rect2.set(5.0f, 10.0f, 10.0f, 5.0f);
+ rect3 = rect1;
+ rect3.intersectWith(rect2);
+ ensure("intersect - no overlap", rect3.isEmpty());
+ }
+
+ template<> template<>
+ void object::test<20>()
+ {
+ //
+ // test the pointInRect() method
+ //
+
+ LLRectf rect(1.0f, 3.0f, 3.0f, 1.0f);
+
+ ensure("(0,0) not in rect", rect.pointInRect(0.0f, 0.0f) == FALSE);
+ ensure("(2,2) in rect", rect.pointInRect(2.0f, 2.0f) == TRUE);
+ ensure("(1,1) in rect", rect.pointInRect(1.0f, 1.0f) == TRUE);
+ ensure("(3,3) not in rect", rect.pointInRect(3.0f, 3.0f) == FALSE);
+ ensure("(2.999,2.999) in rect", rect.pointInRect(2.999f, 2.999f) == TRUE);
+ ensure("(2.999,3.0) not in rect", rect.pointInRect(2.999f, 3.0f) == FALSE);
+ ensure("(3.0,2.999) not in rect", rect.pointInRect(3.0f, 2.999f) == FALSE);
+ }
+
+ template<> template<>
+ void object::test<21>()
+ {
+ //
+ // test the localPointInRect() method
+ //
+
+ LLRectf rect(1.0f, 3.0f, 3.0f, 1.0f);
+
+ ensure("(0,0) in local rect", rect.localPointInRect(0.0f, 0.0f) == TRUE);
+ ensure("(-0.0001,-0.0001) not in local rect", rect.localPointInRect(-0.0001f, -0.001f) == FALSE);
+ ensure("(1,1) in local rect", rect.localPointInRect(1.0f, 1.0f) == TRUE);
+ ensure("(2,2) not in local rect", rect.localPointInRect(2.0f, 2.0f) == FALSE);
+ ensure("(1.999,1.999) in local rect", rect.localPointInRect(1.999f, 1.999f) == TRUE);
+ ensure("(1.999,2.0) not in local rect", rect.localPointInRect(1.999f, 2.0f) == FALSE);
+ ensure("(2.0,1.999) not in local rect", rect.localPointInRect(2.0f, 1.999f) == FALSE);
+ }
+
+ template<> template<>
+ void object::test<22>()
+ {
+ //
+ // test the clampPointToRect() method
+ //
+
+ LLRectf rect(1.0f, 3.0f, 3.0f, 1.0f);
+ F32 x, y;
+
+ x = 2.0f; y = 2.0f;
+ rect.clampPointToRect(x, y);
+ ensure_equals("clamp x-coord within rect", x, 2.0f);
+ ensure_equals("clamp y-coord within rect", y, 2.0f);
+
+ x = -100.0f; y = 100.0f;
+ rect.clampPointToRect(x, y);
+ ensure_equals("clamp x-coord outside rect", x, 1.0f);
+ ensure_equals("clamp y-coord outside rect", y, 3.0f);
+
+ x = 3.0f; y = 1.0f;
+ rect.clampPointToRect(x, y);
+ ensure_equals("clamp x-coord edge rect", x, 3.0f);
+ ensure_equals("clamp y-coord edge rect", y, 1.0f);
+ }
+}
diff --git a/indra/llmath/tests/m3math_test.cpp b/indra/llmath/tests/m3math_test.cpp
new file mode 100644
index 0000000000..83ca5768df
--- /dev/null
+++ b/indra/llmath/tests/m3math_test.cpp
@@ -0,0 +1,327 @@
+/**
+ * @file m3math_test.cpp
+ * @author Adroit
+ * @date 2007-03
+ * @brief Test cases of m3math.h
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../m3math.h"
+#include "../v3math.h"
+#include "../v4math.h"
+#include "../m4math.h"
+#include "../llquaternion.h"
+#include "../v3dmath.h"
+
+#include "../test/lltut.h"
+
+namespace tut
+{
+ struct m3math_test
+ {
+ };
+ typedef test_group<m3math_test> m3math_test_t;
+ typedef m3math_test_t::object m3math_test_object_t;
+ tut::m3math_test_t tut_m3math_test("m3math_test");
+
+ //test case for setIdentity() fn.
+ template<> template<>
+ void m3math_test_object_t::test<1>()
+ {
+ LLMatrix3 llmat3_obj;
+ llmat3_obj.setIdentity();
+ ensure("LLMatrix3::setIdentity failed", 1.f == llmat3_obj.mMatrix[0][0] &&
+ 0.f == llmat3_obj.mMatrix[0][1] &&
+ 0.f == llmat3_obj.mMatrix[0][2] &&
+ 0.f == llmat3_obj.mMatrix[1][0] &&
+ 1.f == llmat3_obj.mMatrix[1][1] &&
+ 0.f == llmat3_obj.mMatrix[1][2] &&
+ 0.f == llmat3_obj.mMatrix[2][0] &&
+ 0.f == llmat3_obj.mMatrix[2][1] &&
+ 1.f == llmat3_obj.mMatrix[2][2]);
+ }
+
+ //test case for LLMatrix3& setZero() fn.
+ template<> template<>
+ void m3math_test_object_t::test<2>()
+ {
+ LLMatrix3 llmat3_obj(30, 1, 2, 3);
+ llmat3_obj.setZero();
+
+ ensure("LLMatrix3::setZero failed", 0.f == llmat3_obj.setZero().mMatrix[0][0] &&
+ 0.f == llmat3_obj.setZero().mMatrix[0][1] &&
+ 0.f == llmat3_obj.setZero().mMatrix[0][2] &&
+ 0.f == llmat3_obj.setZero().mMatrix[1][0] &&
+ 0.f == llmat3_obj.setZero().mMatrix[1][1] &&
+ 0.f == llmat3_obj.setZero().mMatrix[1][2] &&
+ 0.f == llmat3_obj.setZero().mMatrix[2][0] &&
+ 0.f == llmat3_obj.setZero().mMatrix[2][1] &&
+ 0.f == llmat3_obj.setZero().mMatrix[2][2]);
+ }
+
+ //test case for setRows(const LLVector3 &x_axis, const LLVector3 &y_axis, const LLVector3 &z_axis) fns.
+ template<> template<>
+ void m3math_test_object_t::test<3>()
+ {
+ LLMatrix3 llmat3_obj;
+ LLVector3 vect1(2, 1, 4);
+ LLVector3 vect2(3, 5, 7);
+ LLVector3 vect3(6, 9, 7);
+ llmat3_obj.setRows(vect1, vect2, vect3);
+ ensure("LLVector3::setRows failed ", 2 == llmat3_obj.mMatrix[0][0] &&
+ 1 == llmat3_obj.mMatrix[0][1] &&
+ 4 == llmat3_obj.mMatrix[0][2] &&
+ 3 == llmat3_obj.mMatrix[1][0] &&
+ 5 == llmat3_obj.mMatrix[1][1] &&
+ 7 == llmat3_obj.mMatrix[1][2] &&
+ 6 == llmat3_obj.mMatrix[2][0] &&
+ 9 == llmat3_obj.mMatrix[2][1] &&
+ 7 == llmat3_obj.mMatrix[2][2]);
+ }
+
+ //test case for getFwdRow(), getLeftRow(), getUpRow() fns.
+ template<> template<>
+ void m3math_test_object_t::test<4>()
+ {
+ LLMatrix3 llmat3_obj;
+ LLVector3 vect1(2, 1, 4);
+ LLVector3 vect2(3, 5, 7);
+ LLVector3 vect3(6, 9, 7);
+ llmat3_obj.setRows(vect1, vect2, vect3);
+
+ ensure("LLVector3::getFwdRow failed ", vect1 == llmat3_obj.getFwdRow());
+ ensure("LLVector3::getLeftRow failed ", vect2 == llmat3_obj.getLeftRow());
+ ensure("LLVector3::getUpRow failed ", vect3 == llmat3_obj.getUpRow());
+ }
+
+ //test case for operator*(const LLMatrix3 &a, const LLMatrix3 &b)
+ template<> template<>
+ void m3math_test_object_t::test<5>()
+ {
+ LLMatrix3 llmat_obj1;
+ LLMatrix3 llmat_obj2;
+ LLMatrix3 llmat_obj3;
+
+ LLVector3 llvec1(1, 3, 5);
+ LLVector3 llvec2(3, 6, 1);
+ LLVector3 llvec3(4, 6, 9);
+
+ LLVector3 llvec4(1, 1, 5);
+ LLVector3 llvec5(3, 6, 8);
+ LLVector3 llvec6(8, 6, 2);
+
+ LLVector3 llvec7(0, 0, 0);
+ LLVector3 llvec8(0, 0, 0);
+ LLVector3 llvec9(0, 0, 0);
+
+ llmat_obj1.setRows(llvec1, llvec2, llvec3);
+ llmat_obj2.setRows(llvec4, llvec5, llvec6);
+ llmat_obj3.setRows(llvec7, llvec8, llvec9);
+ llmat_obj3 = llmat_obj1 * llmat_obj2;
+ ensure("LLMatrix3::operator*(const LLMatrix3 &a, const LLMatrix3 &b) failed",
+ 50 == llmat_obj3.mMatrix[0][0] &&
+ 49 == llmat_obj3.mMatrix[0][1] &&
+ 39 == llmat_obj3.mMatrix[0][2] &&
+ 29 == llmat_obj3.mMatrix[1][0] &&
+ 45 == llmat_obj3.mMatrix[1][1] &&
+ 65 == llmat_obj3.mMatrix[1][2] &&
+ 94 == llmat_obj3.mMatrix[2][0] &&
+ 94 == llmat_obj3.mMatrix[2][1] &&
+ 86 == llmat_obj3.mMatrix[2][2]);
+ }
+
+
+ //test case for operator*(const LLVector3 &a, const LLMatrix3 &b)
+ template<> template<>
+ void m3math_test_object_t::test<6>()
+ {
+
+ LLMatrix3 llmat_obj1;
+
+ LLVector3 llvec(1, 3, 5);
+ LLVector3 res_vec(0, 0, 0);
+ LLVector3 llvec1(1, 3, 5);
+ LLVector3 llvec2(3, 6, 1);
+ LLVector3 llvec3(4, 6, 9);
+
+ llmat_obj1.setRows(llvec1, llvec2, llvec3);
+ res_vec = llvec * llmat_obj1;
+
+ LLVector3 expected_result(30, 51, 53);
+
+ ensure("LLMatrix3::operator*(const LLVector3 &a, const LLMatrix3 &b) failed", res_vec == expected_result);
+ }
+
+ //test case for operator*(const LLVector3d &a, const LLMatrix3 &b)
+ template<> template<>
+ void m3math_test_object_t::test<7>()
+ {
+ LLMatrix3 llmat_obj1;
+ LLVector3d llvec3d1;
+ LLVector3d llvec3d2(0, 3, 4);
+
+ LLVector3 llvec1(1, 3, 5);
+ LLVector3 llvec2(3, 2, 1);
+ LLVector3 llvec3(4, 6, 0);
+
+ llmat_obj1.setRows(llvec1, llvec2, llvec3);
+ llvec3d1 = llvec3d2 * llmat_obj1;
+
+ LLVector3d expected_result(25, 30, 3);
+
+ ensure("LLMatrix3::operator*(const LLVector3 &a, const LLMatrix3 &b) failed", llvec3d1 == expected_result);
+ }
+
+ // test case for operator==(const LLMatrix3 &a, const LLMatrix3 &b)
+ template<> template<>
+ void m3math_test_object_t::test<8>()
+ {
+ LLMatrix3 llmat_obj1;
+ LLMatrix3 llmat_obj2;
+
+ LLVector3 llvec1(1, 3, 5);
+ LLVector3 llvec2(3, 6, 1);
+ LLVector3 llvec3(4, 6, 9);
+
+ llmat_obj1.setRows(llvec1, llvec2, llvec3);
+ llmat_obj2.setRows(llvec1, llvec2, llvec3);
+ ensure("LLMatrix3::operator==(const LLMatrix3 &a, const LLMatrix3 &b) failed", llmat_obj1 == llmat_obj2);
+
+ llmat_obj2.setRows(llvec2, llvec2, llvec3);
+ ensure("LLMatrix3::operator!=(const LLMatrix3 &a, const LLMatrix3 &b) failed", llmat_obj1 != llmat_obj2);
+ }
+
+ //test case for quaternion() fn.
+ template<> template<>
+ void m3math_test_object_t::test<9>()
+ {
+ LLMatrix3 llmat_obj1;
+ LLQuaternion llmat_quat;
+
+ LLVector3 llmat1(2.0f, 1.0f, 6.0f);
+ LLVector3 llmat2(1.0f, 1.0f, 3.0f);
+ LLVector3 llmat3(1.0f, 7.0f, 5.0f);
+
+ llmat_obj1.setRows(llmat1, llmat2, llmat3);
+ llmat_quat = llmat_obj1.quaternion();
+ ensure("LLMatrix3::quaternion failed ", is_approx_equal(-0.66666669f, llmat_quat.mQ[0]) &&
+ is_approx_equal(-0.83333337f, llmat_quat.mQ[1]) &&
+ is_approx_equal(0.0f, llmat_quat.mQ[2]) &&
+ is_approx_equal(1.5f, llmat_quat.mQ[3]));
+ }
+
+ //test case for transpose() fn.
+ template<> template<>
+ void m3math_test_object_t::test<10>()
+ {
+ LLMatrix3 llmat_obj;
+
+ LLVector3 llvec1(1, 2, 3);
+ LLVector3 llvec2(3, 2, 1);
+ LLVector3 llvec3(2, 2, 2);
+
+ llmat_obj.setRows(llvec1, llvec2, llvec3);
+ llmat_obj.transpose();
+
+ LLVector3 resllvec1(1, 3, 2);
+ LLVector3 resllvec2(2, 2, 2);
+ LLVector3 resllvec3(3, 1, 2);
+ LLMatrix3 expectedllmat_obj;
+ expectedllmat_obj.setRows(resllvec1, resllvec2, resllvec3);
+
+ ensure("LLMatrix3::transpose failed ", llmat_obj == expectedllmat_obj);
+ }
+
+ //test case for determinant() fn.
+ template<> template<>
+ void m3math_test_object_t::test<11>()
+ {
+ LLMatrix3 llmat_obj1;
+
+ LLVector3 llvec1(1, 2, 3);
+ LLVector3 llvec2(3, 2, 1);
+ LLVector3 llvec3(2, 2, 2);
+ llmat_obj1.setRows(llvec1, llvec2, llvec3);
+ ensure("LLMatrix3::determinant failed ", 0.0f == llmat_obj1.determinant());
+ }
+
+ //test case for orthogonalize() fn.
+ template<> template<>
+ void m3math_test_object_t::test<12>()
+ {
+ LLMatrix3 llmat_obj;
+
+ LLVector3 llvec1(1, 4, 3);
+ LLVector3 llvec2(1, 2, 0);
+ LLVector3 llvec3(2, 4, 2);
+
+ llmat_obj.setRows(llvec1, llvec2, llvec3);
+ llmat_obj.orthogonalize();
+
+ skip("Grr, LLMatrix3::orthogonalize test is failing. Has it ever worked?");
+ ensure("LLMatrix3::orthogonalize failed ",
+ is_approx_equal(0.19611613f, llmat_obj.mMatrix[0][0]) &&
+ is_approx_equal(0.78446454f, llmat_obj.mMatrix[0][1]) &&
+ is_approx_equal(0.58834839f, llmat_obj.mMatrix[0][2]) &&
+ is_approx_equal(0.47628206f, llmat_obj.mMatrix[1][0]) &&
+ is_approx_equal(0.44826555f, llmat_obj.mMatrix[1][1]) &&
+ is_approx_equal(-0.75644791f, llmat_obj.mMatrix[1][2]) &&
+ is_approx_equal(-0.85714287f, llmat_obj.mMatrix[2][0]) &&
+ is_approx_equal(0.42857143f, llmat_obj.mMatrix[2][1]) &&
+ is_approx_equal(-0.28571427f, llmat_obj.mMatrix[2][2]));
+ }
+
+ //test case for adjointTranspose() fn.
+ template<> template<>
+ void m3math_test_object_t::test<13>()
+ {
+ LLMatrix3 llmat_obj;
+
+ LLVector3 llvec1(3, 2, 1);
+ LLVector3 llvec2(6, 2, 1);
+ LLVector3 llvec3(3, 6, 8);
+
+ llmat_obj.setRows(llvec1, llvec2, llvec3);
+ llmat_obj.adjointTranspose();
+
+ ensure("LLMatrix3::adjointTranspose failed ", 10 == llmat_obj.mMatrix[0][0] &&
+ -45 == llmat_obj.mMatrix[1][0] &&
+ 30 == llmat_obj.mMatrix[2][0] &&
+ -10 == llmat_obj.mMatrix[0][1] &&
+ 21 == llmat_obj.mMatrix[1][1] &&
+ -12 == llmat_obj.mMatrix[2][1] &&
+ 0 == llmat_obj.mMatrix[0][2] &&
+ 3 == llmat_obj.mMatrix[1][2] &&
+ -6 == llmat_obj.mMatrix[2][2]);
+ }
+
+ /* TBD: Need to add test cases for getEulerAngles() and setRot() functions */
+}
diff --git a/indra/llmath/tests/mathmisc_test.cpp b/indra/llmath/tests/mathmisc_test.cpp
new file mode 100644
index 0000000000..ea42f6e001
--- /dev/null
+++ b/indra/llmath/tests/mathmisc_test.cpp
@@ -0,0 +1,727 @@
+/**
+ * @file math.cpp
+ * @author Phoenix
+ * @date 2005-09-26
+ * @brief Tests for the llmath library.
+ *
+ * $LicenseInfo:firstyear=2005&license=viewergpl$
+ *
+ * Copyright (c) 2005-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+
+#include "llcrc.h"
+#include "llrand.h"
+#include "lluuid.h"
+
+#include "../llline.h"
+#include "../llmath.h"
+#include "../llsphere.h"
+#include "../v3math.h"
+
+namespace tut
+{
+ struct math_data
+ {
+ };
+ typedef test_group<math_data> math_test;
+ typedef math_test::object math_object;
+ tut::math_test tm("basic_linden_math");
+
+ template<> template<>
+ void math_object::test<1>()
+ {
+ S32 val = 89543;
+ val = llabs(val);
+ ensure("integer absolute value 1", (89543 == val));
+ val = -500;
+ val = llabs(val);
+ ensure("integer absolute value 2", (500 == val));
+ }
+
+ template<> template<>
+ void math_object::test<2>()
+ {
+ F32 val = -2583.4f;
+ val = llabs(val);
+ ensure("float absolute value 1", (2583.4f == val));
+ val = 430903.f;
+ val = llabs(val);
+ ensure("float absolute value 2", (430903.f == val));
+ }
+
+ template<> template<>
+ void math_object::test<3>()
+ {
+ F64 val = 387439393.987329839;
+ val = llabs(val);
+ ensure("double absolute value 1", (387439393.987329839 == val));
+ val = -8937843.9394878;
+ val = llabs(val);
+ ensure("double absolute value 2", (8937843.9394878 == val));
+ }
+
+ template<> template<>
+ void math_object::test<4>()
+ {
+ F32 val = 430903.9f;
+ S32 val1 = lltrunc(val);
+ ensure("float truncate value 1", (430903 == val1));
+ val = -2303.9f;
+ val1 = lltrunc(val);
+ ensure("float truncate value 2", (-2303 == val1));
+ }
+
+ template<> template<>
+ void math_object::test<5>()
+ {
+ F64 val = 387439393.987329839 ;
+ S32 val1 = lltrunc(val);
+ ensure("float truncate value 1", (387439393 == val1));
+ val = -387439393.987329839;
+ val1 = lltrunc(val);
+ ensure("float truncate value 2", (-387439393 == val1));
+ }
+
+ template<> template<>
+ void math_object::test<6>()
+ {
+ F32 val = 430903.2f;
+ S32 val1 = llfloor(val);
+ ensure("float llfloor value 1", (430903 == val1));
+ val = -430903.9f;
+ val1 = llfloor(val);
+ ensure("float llfloor value 2", (-430904 == val1));
+ }
+
+ template<> template<>
+ void math_object::test<7>()
+ {
+ F32 val = 430903.2f;
+ S32 val1 = llceil(val);
+ ensure("float llceil value 1", (430904 == val1));
+ val = -430903.9f;
+ val1 = llceil(val);
+ ensure("float llceil value 2", (-430903 == val1));
+ }
+
+ template<> template<>
+ void math_object::test<8>()
+ {
+ F32 val = 430903.2f;
+ S32 val1 = llround(val);
+ ensure("float llround value 1", (430903 == val1));
+ val = -430903.9f;
+ val1 = llround(val);
+ ensure("float llround value 2", (-430904 == val1));
+ }
+
+ template<> template<>
+ void math_object::test<9>()
+ {
+ F32 val = 430905.2654f, nearest = 100.f;
+ val = llround(val, nearest);
+ ensure("float llround value 1", (430900 == val));
+ val = -430905.2654f, nearest = 10.f;
+ val = llround(val, nearest);
+ ensure("float llround value 1", (-430910 == val));
+ }
+
+ template<> template<>
+ void math_object::test<10>()
+ {
+ F64 val = 430905.2654, nearest = 100.0;
+ val = llround(val, nearest);
+ ensure("double llround value 1", (430900 == val));
+ val = -430905.2654, nearest = 10.0;
+ val = llround(val, nearest);
+ ensure("double llround value 1", (-430910.00000 == val));
+ }
+
+ template<> template<>
+ void math_object::test<11>()
+ {
+ const F32 F_PI = 3.1415926535897932384626433832795f;
+ F32 angle = 3506.f;
+ angle = llsimple_angle(angle);
+ ensure("llsimple_angle value 1", (angle <=F_PI && angle >= -F_PI));
+ angle = -431.f;
+ angle = llsimple_angle(angle);
+ ensure("llsimple_angle value 1", (angle <=F_PI && angle >= -F_PI));
+ }
+}
+
+namespace tut
+{
+ struct uuid_data
+ {
+ LLUUID id;
+ };
+ typedef test_group<uuid_data> uuid_test;
+ typedef uuid_test::object uuid_object;
+ tut::uuid_test tu("uuid");
+
+ template<> template<>
+ void uuid_object::test<1>()
+ {
+ ensure("uuid null", id.isNull());
+ id.generate();
+ ensure("generate not null", id.notNull());
+ id.setNull();
+ ensure("set null", id.isNull());
+ }
+
+ template<> template<>
+ void uuid_object::test<2>()
+ {
+ id.generate();
+ LLUUID a(id);
+ ensure_equals("copy equal", id, a);
+ a.generate();
+ ensure_not_equals("generate not equal", id, a);
+ a = id;
+ ensure_equals("assignment equal", id, a);
+ }
+
+ template<> template<>
+ void uuid_object::test<3>()
+ {
+ id.generate();
+ LLUUID copy(id);
+ LLUUID mask;
+ mask.generate();
+ copy ^= mask;
+ ensure_not_equals("mask not equal", id, copy);
+ copy ^= mask;
+ ensure_equals("mask back", id, copy);
+ }
+
+ template<> template<>
+ void uuid_object::test<4>()
+ {
+ id.generate();
+ std::string id_str = id.asString();
+ LLUUID copy(id_str.c_str());
+ ensure_equals("string serialization", id, copy);
+ }
+
+}
+
+namespace tut
+{
+ struct crc_data
+ {
+ };
+ typedef test_group<crc_data> crc_test;
+ typedef crc_test::object crc_object;
+ tut::crc_test tc("crc");
+
+ template<> template<>
+ void crc_object::test<1>()
+ {
+ /* Test buffer update and individual char update */
+ const char TEST_BUFFER[] = "hello &#$)$&Nd0";
+ LLCRC c1, c2;
+ c1.update((U8*)TEST_BUFFER, sizeof(TEST_BUFFER) - 1);
+ char* rh = (char*)TEST_BUFFER;
+ while(*rh != '\0')
+ {
+ c2.update(*rh);
+ ++rh;
+ }
+ ensure_equals("crc update 1", c1.getCRC(), c2.getCRC());
+ }
+
+ template<> template<>
+ void crc_object::test<2>()
+ {
+ /* Test mixing of buffer and individual char update */
+ const char TEST_BUFFER1[] = "Split Buffer one $^%$%#@$";
+ const char TEST_BUFFER2[] = "Split Buffer two )(8723#5dsds";
+ LLCRC c1, c2;
+ c1.update((U8*)TEST_BUFFER1, sizeof(TEST_BUFFER1) - 1);
+ char* rh = (char*)TEST_BUFFER2;
+ while(*rh != '\0')
+ {
+ c1.update(*rh);
+ ++rh;
+ }
+
+ rh = (char*)TEST_BUFFER1;
+ while(*rh != '\0')
+ {
+ c2.update(*rh);
+ ++rh;
+ }
+ c2.update((U8*)TEST_BUFFER2, sizeof(TEST_BUFFER2) - 1);
+
+ ensure_equals("crc update 2", c1.getCRC(), c2.getCRC());
+ }
+}
+
+namespace tut
+{
+ struct sphere_data
+ {
+ };
+ typedef test_group<sphere_data> sphere_test;
+ typedef sphere_test::object sphere_object;
+ tut::sphere_test tsphere("LLSphere");
+
+ template<> template<>
+ void sphere_object::test<1>()
+ {
+ // test LLSphere::contains() and ::overlaps()
+ S32 number_of_tests = 10;
+ for (S32 test = 0; test < number_of_tests; ++test)
+ {
+ LLVector3 first_center(1.f, 1.f, 1.f);
+ F32 first_radius = 3.f;
+ LLSphere first_sphere( first_center, first_radius );
+
+ F32 half_millimeter = 0.0005f;
+ LLVector3 direction( ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f);
+ direction.normalize();
+
+ F32 distance = ll_frand(first_radius - 2.f * half_millimeter);
+ LLVector3 second_center = first_center + distance * direction;
+ F32 second_radius = first_radius - distance - half_millimeter;
+ LLSphere second_sphere( second_center, second_radius );
+ ensure("first sphere should contain the second", first_sphere.contains(second_sphere));
+ ensure("first sphere should overlap the second", first_sphere.overlaps(second_sphere));
+
+ distance = first_radius + ll_frand(first_radius);
+ second_center = first_center + distance * direction;
+ second_radius = distance - first_radius + half_millimeter;
+ second_sphere.set( second_center, second_radius );
+ ensure("first sphere should NOT contain the second", !first_sphere.contains(second_sphere));
+ ensure("first sphere should overlap the second", first_sphere.overlaps(second_sphere));
+
+ distance = first_radius + ll_frand(first_radius) + half_millimeter;
+ second_center = first_center + distance * direction;
+ second_radius = distance - first_radius - half_millimeter;
+ second_sphere.set( second_center, second_radius );
+ ensure("first sphere should NOT contain the second", !first_sphere.contains(second_sphere));
+ ensure("first sphere should NOT overlap the second", !first_sphere.overlaps(second_sphere));
+ }
+ }
+
+ template<> template<>
+ void sphere_object::test<2>()
+ {
+ // test LLSphere::getBoundingSphere()
+ S32 number_of_tests = 100;
+ S32 number_of_spheres = 10;
+ F32 sphere_center_range = 32.f;
+ F32 sphere_radius_range = 5.f;
+
+ for (S32 test = 0; test < number_of_tests; ++test)
+ {
+ // gegnerate a bunch of random sphere
+ std::vector< LLSphere > sphere_list;
+ for (S32 sphere_count=0; sphere_count < number_of_spheres; ++sphere_count)
+ {
+ LLVector3 direction( ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f);
+ direction.normalize();
+ F32 distance = ll_frand(sphere_center_range);
+ LLVector3 center = distance * direction;
+ F32 radius = ll_frand(sphere_radius_range);
+ LLSphere sphere( center, radius );
+ sphere_list.push_back(sphere);
+ }
+
+ // compute the bounding sphere
+ LLSphere bounding_sphere = LLSphere::getBoundingSphere(sphere_list);
+
+ // make sure all spheres are inside the bounding sphere
+ {
+ std::vector< LLSphere >::const_iterator sphere_itr;
+ for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr)
+ {
+ ensure("sphere should be contained by the bounding sphere", bounding_sphere.contains(*sphere_itr));
+ }
+ }
+
+ // TODO -- improve LLSphere::getBoundingSphere() to the point where
+ // we can reduce the 'expansion' in the two tests below to about
+ // 2 mm or less
+
+ F32 expansion = 0.005f;
+ // move all spheres out a little bit
+ // and count how many are NOT contained
+ {
+ std::vector< LLVector3 > uncontained_directions;
+ std::vector< LLSphere >::iterator sphere_itr;
+ for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr)
+ {
+ LLVector3 direction = sphere_itr->getCenter() - bounding_sphere.getCenter();
+ direction.normalize();
+
+ sphere_itr->setCenter( sphere_itr->getCenter() + expansion * direction );
+ if (! bounding_sphere.contains( *sphere_itr ) )
+ {
+ uncontained_directions.push_back(direction);
+ }
+ }
+ ensure("when moving spheres out there should be at least two uncontained spheres",
+ uncontained_directions.size() > 1);
+
+ /* TODO -- when the bounding sphere algorithm is improved we can open up this test
+ * at the moment it occasionally fails when the sphere collection is tight and small
+ * (2 meters or less)
+ if (2 == uncontained_directions.size() )
+ {
+ // if there were only two uncontained spheres then
+ // the two directions should be nearly opposite
+ F32 dir_dot = uncontained_directions[0] * uncontained_directions[1];
+ ensure("two uncontained spheres should lie opposite the bounding center", dir_dot < -0.95f);
+ }
+ */
+ }
+
+ // compute the new bounding sphere
+ bounding_sphere = LLSphere::getBoundingSphere(sphere_list);
+
+ // increase the size of all spheres a little bit
+ // and count how many are NOT contained
+ {
+ std::vector< LLVector3 > uncontained_directions;
+ std::vector< LLSphere >::iterator sphere_itr;
+ for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr)
+ {
+ LLVector3 direction = sphere_itr->getCenter() - bounding_sphere.getCenter();
+ direction.normalize();
+
+ sphere_itr->setRadius( sphere_itr->getRadius() + expansion );
+ if (! bounding_sphere.contains( *sphere_itr ) )
+ {
+ uncontained_directions.push_back(direction);
+ }
+ }
+ ensure("when boosting sphere radii there should be at least two uncontained spheres",
+ uncontained_directions.size() > 1);
+
+ /* TODO -- when the bounding sphere algorithm is improved we can open up this test
+ * at the moment it occasionally fails when the sphere collection is tight and small
+ * (2 meters or less)
+ if (2 == uncontained_directions.size() )
+ {
+ // if there were only two uncontained spheres then
+ // the two directions should be nearly opposite
+ F32 dir_dot = uncontained_directions[0] * uncontained_directions[1];
+ ensure("two uncontained spheres should lie opposite the bounding center", dir_dot < -0.95f);
+ }
+ */
+ }
+ }
+ }
+}
+
+namespace tut
+{
+ F32 SMALL_RADIUS = 1.0f;
+ F32 MEDIUM_RADIUS = 5.0f;
+ F32 LARGE_RADIUS = 10.0f;
+
+ struct line_data
+ {
+ };
+ typedef test_group<line_data> line_test;
+ typedef line_test::object line_object;
+ tut::line_test tline("LLLine");
+
+ template<> template<>
+ void line_object::test<1>()
+ {
+ // this is a test for LLLine::intersects(point) which returns TRUE
+ // if the line passes within some tolerance of point
+
+ // these tests will have some floating point error,
+ // so we need to specify how much error is ok
+ F32 allowable_relative_error = 0.00001f;
+ S32 number_of_tests = 100;
+ for (S32 test = 0; test < number_of_tests; ++test)
+ {
+ // generate some random point to be on the line
+ LLVector3 point_on_line( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ point_on_line.normalize();
+ point_on_line *= ll_frand(LARGE_RADIUS);
+
+ // generate some random point to "intersect"
+ LLVector3 random_direction ( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ random_direction.normalize();
+
+ LLVector3 random_offset( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ random_offset.normalize();
+ random_offset *= ll_frand(SMALL_RADIUS);
+
+ LLVector3 point = point_on_line + MEDIUM_RADIUS * random_direction
+ + random_offset;
+
+ // compute the axis of approach (a unit vector between the points)
+ LLVector3 axis_of_approach = point - point_on_line;
+ axis_of_approach.normalize();
+
+ // compute the direction of the the first line (perp to axis_of_approach)
+ LLVector3 first_dir( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ first_dir.normalize();
+ F32 dot = first_dir * axis_of_approach;
+ first_dir -= dot * axis_of_approach; // subtract component parallel to axis
+ first_dir.normalize();
+
+ // construct the line
+ LLVector3 another_point_on_line = point_on_line + ll_frand(LARGE_RADIUS) * first_dir;
+ LLLine line(another_point_on_line, point_on_line);
+
+ // test that the intersection point is within MEDIUM_RADIUS + SMALL_RADIUS
+ F32 test_radius = MEDIUM_RADIUS + SMALL_RADIUS;
+ test_radius += (LARGE_RADIUS * allowable_relative_error);
+ ensure("line should pass near intersection point", line.intersects(point, test_radius));
+
+ test_radius = allowable_relative_error * (point - point_on_line).length();
+ ensure("line should intersect point used to define it", line.intersects(point_on_line, test_radius));
+ }
+ }
+
+ template<> template<>
+ void line_object::test<2>()
+ {
+ /*
+ These tests fail intermittently on all platforms - see DEV-16600
+ Commenting this out until dev has time to investigate.
+
+ // this is a test for LLLine::nearestApproach(LLLIne) method
+ // which computes the point on a line nearest another line
+
+ // these tests will have some floating point error,
+ // so we need to specify how much error is ok
+ // TODO -- make nearestApproach() algorithm more accurate so
+ // we can tighten the allowable_error. Most tests are tighter
+ // than one milimeter, however when doing randomized testing
+ // you can walk into inaccurate cases.
+ F32 allowable_relative_error = 0.001f;
+ S32 number_of_tests = 100;
+ for (S32 test = 0; test < number_of_tests; ++test)
+ {
+ // generate two points to be our known nearest approaches
+ LLVector3 some_point( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ some_point.normalize();
+ some_point *= ll_frand(LARGE_RADIUS);
+
+ LLVector3 another_point( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ another_point.normalize();
+ another_point *= ll_frand(LARGE_RADIUS);
+
+ // compute the axis of approach (a unit vector between the points)
+ LLVector3 axis_of_approach = another_point - some_point;
+ axis_of_approach.normalize();
+
+ // compute the direction of the the first line (perp to axis_of_approach)
+ LLVector3 first_dir( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ F32 dot = first_dir * axis_of_approach;
+ first_dir -= dot * axis_of_approach; // subtract component parallel to axis
+ first_dir.normalize(); // normalize
+
+ // compute the direction of the the second line
+ LLVector3 second_dir( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ dot = second_dir * axis_of_approach;
+ second_dir -= dot * axis_of_approach;
+ second_dir.normalize();
+
+ // make sure the lines aren't too parallel,
+ dot = fabsf(first_dir * second_dir);
+ if (dot > 0.99f)
+ {
+ // skip this test, we're not interested in testing
+ // the intractible cases
+ continue;
+ }
+
+ // construct the lines
+ LLVector3 first_point = some_point + ll_frand(LARGE_RADIUS) * first_dir;
+ LLLine first_line(first_point, some_point);
+
+ LLVector3 second_point = another_point + ll_frand(LARGE_RADIUS) * second_dir;
+ LLLine second_line(second_point, another_point);
+
+ // compute the points of nearest approach
+ LLVector3 some_computed_point = first_line.nearestApproach(second_line);
+ LLVector3 another_computed_point = second_line.nearestApproach(first_line);
+
+ // compute the error
+ F32 first_error = (some_point - some_computed_point).length();
+ F32 scale = llmax((some_point - another_point).length(), some_point.length());
+ scale = llmax(scale, another_point.length());
+ scale = llmax(scale, 1.f);
+ F32 first_relative_error = first_error / scale;
+
+ F32 second_error = (another_point - another_computed_point).length();
+ F32 second_relative_error = second_error / scale;
+
+ //if (first_relative_error > allowable_relative_error)
+ //{
+ // std::cout << "first_error = " << first_error
+ // << " first_relative_error = " << first_relative_error
+ // << " scale = " << scale
+ // << " dir_dot = " << (first_dir * second_dir)
+ // << std::endl;
+ //}
+ //if (second_relative_error > allowable_relative_error)
+ //{
+ // std::cout << "second_error = " << second_error
+ // << " second_relative_error = " << second_relative_error
+ // << " scale = " << scale
+ // << " dist = " << (some_point - another_point).length()
+ // << " dir_dot = " << (first_dir * second_dir)
+ // << std::endl;
+ //}
+
+ // test that the errors are small
+
+ ensure("first line should accurately compute its closest approach",
+ first_relative_error <= allowable_relative_error);
+ ensure("second line should accurately compute its closest approach",
+ second_relative_error <= allowable_relative_error);
+ }
+ */
+ }
+
+ F32 ALMOST_PARALLEL = 0.99f;
+ template<> template<>
+ void line_object::test<3>()
+ {
+ // this is a test for LLLine::getIntersectionBetweenTwoPlanes() method
+
+ // first some known tests
+ LLLine xy_plane(LLVector3(0.f, 0.f, 2.f), LLVector3(0.f, 0.f, 3.f));
+ LLLine yz_plane(LLVector3(2.f, 0.f, 0.f), LLVector3(3.f, 0.f, 0.f));
+ LLLine zx_plane(LLVector3(0.f, 2.f, 0.f), LLVector3(0.f, 3.f, 0.f));
+
+ LLLine x_line;
+ LLLine y_line;
+ LLLine z_line;
+
+ bool x_success = LLLine::getIntersectionBetweenTwoPlanes(x_line, xy_plane, zx_plane);
+ bool y_success = LLLine::getIntersectionBetweenTwoPlanes(y_line, yz_plane, xy_plane);
+ bool z_success = LLLine::getIntersectionBetweenTwoPlanes(z_line, zx_plane, yz_plane);
+
+ ensure("xy and zx planes should intersect", x_success);
+ ensure("yz and xy planes should intersect", y_success);
+ ensure("zx and yz planes should intersect", z_success);
+
+ LLVector3 direction = x_line.getDirection();
+ ensure("x_line should be parallel to x_axis", fabs(direction.mV[VX]) == 1.f
+ && 0.f == direction.mV[VY]
+ && 0.f == direction.mV[VZ] );
+ direction = y_line.getDirection();
+ ensure("y_line should be parallel to y_axis", 0.f == direction.mV[VX]
+ && fabs(direction.mV[VY]) == 1.f
+ && 0.f == direction.mV[VZ] );
+ direction = z_line.getDirection();
+ ensure("z_line should be parallel to z_axis", 0.f == direction.mV[VX]
+ && 0.f == direction.mV[VY]
+ && fabs(direction.mV[VZ]) == 1.f );
+
+ // next some random tests
+ F32 allowable_relative_error = 0.0001f;
+ S32 number_of_tests = 20;
+ for (S32 test = 0; test < number_of_tests; ++test)
+ {
+ // generate the known line
+ LLVector3 some_point( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ some_point.normalize();
+ some_point *= ll_frand(LARGE_RADIUS);
+ LLVector3 another_point( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ another_point.normalize();
+ another_point *= ll_frand(LARGE_RADIUS);
+ LLLine known_intersection(some_point, another_point);
+
+ // compute a plane that intersect the line
+ LLVector3 point_on_plane( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ point_on_plane.normalize();
+ point_on_plane *= ll_frand(LARGE_RADIUS);
+ LLVector3 plane_normal = (point_on_plane - some_point) % known_intersection.getDirection();
+ plane_normal.normalize();
+ LLLine first_plane(point_on_plane, point_on_plane + plane_normal);
+
+ // compute a different plane that intersect the line
+ LLVector3 point_on_different_plane( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ point_on_different_plane.normalize();
+ point_on_different_plane *= ll_frand(LARGE_RADIUS);
+ LLVector3 different_plane_normal = (point_on_different_plane - another_point) % known_intersection.getDirection();
+ different_plane_normal.normalize();
+ LLLine second_plane(point_on_different_plane, point_on_different_plane + different_plane_normal);
+
+ if (fabs(plane_normal * different_plane_normal) > ALMOST_PARALLEL)
+ {
+ // the two planes are approximately parallel, so we won't test this case
+ continue;
+ }
+
+ LLLine measured_intersection;
+ bool success = LLLine::getIntersectionBetweenTwoPlanes(
+ measured_intersection,
+ first_plane,
+ second_plane);
+
+ ensure("plane intersection should succeed", success);
+
+ F32 dot = fabs(known_intersection.getDirection() * measured_intersection.getDirection());
+ ensure("measured intersection should be parallel to known intersection",
+ dot > ALMOST_PARALLEL);
+
+ ensure("measured intersection should pass near known point",
+ measured_intersection.intersects(some_point, LARGE_RADIUS * allowable_relative_error));
+ }
+ }
+}
+
diff --git a/indra/llmath/tests/v2math_test.cpp b/indra/llmath/tests/v2math_test.cpp
new file mode 100644
index 0000000000..4660fcb955
--- /dev/null
+++ b/indra/llmath/tests/v2math_test.cpp
@@ -0,0 +1,454 @@
+/**
+ * @file v2math_test.cpp
+ * @author Adroit
+ * @date 2007-02
+ * @brief v2math test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+
+#include "../v2math.h"
+
+
+namespace tut
+{
+ struct v2math_data
+ {
+ };
+ typedef test_group<v2math_data> v2math_test;
+ typedef v2math_test::object v2math_object;
+ tut::v2math_test v2math_testcase("v2math");
+
+ template<> template<>
+ void v2math_object::test<1>()
+ {
+ LLVector2 vec2;
+ ensure("LLVector2:Fail to initialize ", (0.f == vec2.mV[VX] && 0.f == vec2.mV[VY]));
+
+ F32 x =2.0f, y = 3.2f ;
+ LLVector2 vec3(x,y);
+ ensure("LLVector2(F32 x, F32 y):Fail to initialize ", (x == vec3.mV[VX]) && (y == vec3.mV[VY]));
+
+ const F32 vec[2] = {3.2f, 4.5f};
+ LLVector2 vec4(vec);
+ ensure("LLVector2(const F32 *vec):Fail to initialize ", (vec[0] == vec4.mV[VX]) && (vec[1] == vec4.mV[VY]));
+
+ vec4.clearVec();
+ ensure("clearVec():Fail to clean the values ", (0.f == vec4.mV[VX] && 0.f == vec4.mV[VY]));
+
+ vec3.zeroVec();
+ ensure("zeroVec():Fail to fill the zero ", (0.f == vec3.mV[VX] && 0.f == vec3.mV[VY]));
+ }
+
+ template<> template<>
+ void v2math_object::test<2>()
+ {
+ F32 x = 123.356f, y = 2387.453f;
+ LLVector2 vec2,vec3;
+ vec2.setVec(x, y);
+ ensure("1:setVec: Fail ", (x == vec2.mV[VX]) && (y == vec2.mV[VY]));
+
+ vec3.setVec(vec2);
+ ensure("2:setVec: Fail " ,(vec2 == vec3));
+
+ vec3.zeroVec();
+ const F32 vec[2] = {3.24653f, 457653.4f};
+ vec3.setVec(vec);
+ ensure("3:setVec: Fail ", (vec[0] == vec3.mV[VX]) && (vec[1] == vec3.mV[VY]));
+ }
+
+ template<> template<>
+ void v2math_object::test<3>()
+ {
+ F32 x = 2.2345f, y = 3.5678f ;
+ LLVector2 vec2(x,y);
+ ensure("magVecSquared:Fail ", is_approx_equal(vec2.magVecSquared(), (x*x + y*y)));
+ ensure("magVec:Fail ", is_approx_equal(vec2.magVec(), fsqrtf(x*x + y*y)));
+ }
+
+ template<> template<>
+ void v2math_object::test<4>()
+ {
+ F32 x =-2.0f, y = -3.0f ;
+ LLVector2 vec2(x,y);
+ ensure_equals("abs():Fail", vec2.abs(), TRUE);
+ ensure("abs() x", is_approx_equal(vec2.mV[VX], 2.f));
+ ensure("abs() y", is_approx_equal(vec2.mV[VY], 3.f));
+
+ ensure("isNull():Fail ", FALSE == vec2.isNull()); //Returns TRUE if vector has a _very_small_ length
+
+ x =.00000001f, y = .000001001f;
+ vec2.setVec(x, y);
+ ensure("isNull(): Fail ", TRUE == vec2.isNull());
+ }
+
+ template<> template<>
+ void v2math_object::test<5>()
+ {
+ F32 x =1.f, y = 2.f;
+ LLVector2 vec2(x, y), vec3;
+ vec3 = vec3.scaleVec(vec2);
+ ensure("scaleVec: Fail ", vec3.mV[VX] == 0. && vec3.mV[VY] == 0.);
+ ensure("isExactlyZero(): Fail", TRUE == vec3.isExactlyZero());
+
+ vec3.setVec(2.f, 1.f);
+ vec3 = vec3.scaleVec(vec2);
+ ensure("scaleVec: Fail ", (2.f == vec3.mV[VX]) && (2.f == vec3.mV[VY]));
+ ensure("isExactlyZero():Fail", FALSE == vec3.isExactlyZero());
+ }
+
+ template<> template<>
+ void v2math_object::test<6>()
+ {
+ F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f;
+ F32 val1, val2;
+ LLVector2 vec2(x1, y1), vec3(x2, y2), vec4;
+ vec4 = vec2 + vec3 ;
+ val1 = x1+x2;
+ val2 = y1+y2;
+ ensure("1:operator+ failed",(val1 == vec4.mV[VX]) && ((val2 == vec4.mV[VY])));
+
+ vec2.clearVec();
+ vec3.clearVec();
+ x1 = -.235f, y1 = -24.32f, x2 = -2.3f, y2 = 1.f;
+ vec2.setVec(x1, y1);
+ vec3.setVec(x2, y2);
+ vec4 = vec2 + vec3;
+ val1 = x1+x2;
+ val2 = y1+y2;
+ ensure("2:operator+ failed",(val1 == vec4.mV[VX]) && ((val2 == vec4.mV[VY])));
+ }
+
+ template<> template<>
+ void v2math_object::test<7>()
+ {
+ F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f;
+ F32 val1, val2;
+ LLVector2 vec2(x1, y1), vec3(x2, y2), vec4;
+ vec4 = vec2 - vec3 ;
+ val1 = x1-x2;
+ val2 = y1-y2;
+ ensure("1:operator- failed",(val1 == vec4.mV[VX]) && ((val2 == vec4.mV[VY])));
+
+ vec2.clearVec();
+ vec3.clearVec();
+ vec4.clearVec();
+ x1 = -.235f, y1 = -24.32f, x2 = -2.3f, y2 = 1.f;
+ vec2.setVec(x1, y1);
+ vec3.setVec(x2, y2);
+ vec4 = vec2 - vec3;
+ val1 = x1-x2;
+ val2 = y1-y2;
+ ensure("2:operator- failed",(val1 == vec4.mV[VX]) && ((val2 == vec4.mV[VY])));
+ }
+
+ template<> template<>
+ void v2math_object::test<8>()
+ {
+ F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f;
+ F32 val1, val2;
+ LLVector2 vec2(x1, y1), vec3(x2, y2);
+ val1 = vec2 * vec3;
+ val2 = x1*x2 + y1*y2;
+ ensure("1:operator* failed",(val1 == val2));
+
+ vec3.clearVec();
+ F32 mulVal = 4.332f;
+ vec3 = vec2 * mulVal;
+ val1 = x1*mulVal;
+ val2 = y1*mulVal;
+ ensure("2:operator* failed",(val1 == vec3.mV[VX]) && (val2 == vec3.mV[VY]));
+
+ vec3.clearVec();
+ vec3 = mulVal * vec2;
+ ensure("3:operator* failed",(val1 == vec3.mV[VX]) && (val2 == vec3.mV[VY]));
+ }
+
+ template<> template<>
+ void v2math_object::test<9>()
+ {
+ F32 x1 =1.f, y1 = 2.f, div = 3.2f;
+ F32 val1, val2;
+ LLVector2 vec2(x1, y1), vec3;
+ vec3 = vec2 / div;
+ val1 = x1 / div;
+ val2 = y1 / div;
+ ensure("1:operator/ failed", is_approx_equal(val1, vec3.mV[VX]) && is_approx_equal(val2, vec3.mV[VY]));
+
+ vec3.clearVec();
+ x1 = -.235f, y1 = -24.32f, div = -2.2f;
+ vec2.setVec(x1, y1);
+ vec3 = vec2 / div;
+ val1 = x1 / div;
+ val2 = y1 / div;
+ ensure("2:operator/ failed", is_approx_equal(val1, vec3.mV[VX]) && is_approx_equal(val2, vec3.mV[VY]));
+ }
+
+ template<> template<>
+ void v2math_object::test<10>()
+ {
+ F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f;
+ F32 val1, val2;
+ LLVector2 vec2(x1, y1), vec3(x2, y2), vec4;
+ vec4 = vec2 % vec3;
+ val1 = x1*y2 - x2*y1;
+ val2 = y1*x2 - y2*x1;
+ ensure("1:operator% failed",(val1 == vec4.mV[VX]) && (val2 == vec4.mV[VY]));
+
+ vec2.clearVec();
+ vec3.clearVec();
+ vec4.clearVec();
+ x1 = -.235f, y1 = -24.32f, x2 = -2.3f, y2 = 1.f;
+ vec2.setVec(x1, y1);
+ vec3.setVec(x2, y2);
+ vec4 = vec2 % vec3;
+ val1 = x1*y2 - x2*y1;
+ val2 = y1*x2 - y2*x1;
+ ensure("2:operator% failed",(val1 == vec4.mV[VX]) && (val2 == vec4.mV[VY]));
+ }
+ template<> template<>
+ void v2math_object::test<11>()
+ {
+ F32 x1 =1.f, y1 = 2.f;
+ LLVector2 vec2(x1, y1), vec3(x1, y1);
+ ensure("1:operator== failed",(vec2 == vec3));
+
+ vec2.clearVec();
+ vec3.clearVec();
+ x1 = -.235f, y1 = -24.32f;
+ vec2.setVec(x1, y1);
+ vec3.setVec(vec2);
+ ensure("2:operator== failed",(vec2 == vec3));
+ }
+
+ template<> template<>
+ void v2math_object::test<12>()
+ {
+ F32 x1 = 1.f, y1 = 2.f,x2 = 2.332f, y2 = -1.23f;
+ LLVector2 vec2(x1, y1), vec3(x2, y2);
+ ensure("1:operator!= failed",(vec2 != vec3));
+
+ vec2.clearVec();
+ vec3.clearVec();
+ vec2.setVec(x1, y1);
+ vec3.setVec(vec2);
+ ensure("2:operator!= failed", (FALSE == (vec2 != vec3)));
+ }
+ template<> template<>
+ void v2math_object::test<13>()
+ {
+ F32 x1 = 1.f, y1 = 2.f,x2 = 2.332f, y2 = -1.23f;
+ F32 val1, val2;
+ LLVector2 vec2(x1, y1), vec3(x2, y2);
+ vec2 +=vec3;
+ val1 = x1+x2;
+ val2 = y1+y2;
+ ensure("1:operator+= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY]));
+
+ vec2.setVec(x1, y1);
+ vec2 -=vec3;
+ val1 = x1-x2;
+ val2 = y1-y2;
+ ensure("2:operator-= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY]));
+
+ vec2.clearVec();
+ vec3.clearVec();
+ x1 = -21.000466f, y1 = 2.98382f,x2 = 0.332f, y2 = -01.23f;
+ vec2.setVec(x1, y1);
+ vec3.setVec(x2, y2);
+ vec2 +=vec3;
+ val1 = x1+x2;
+ val2 = y1+y2;
+ ensure("3:operator+= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY]));
+
+ vec2.setVec(x1, y1);
+ vec2 -=vec3;
+ val1 = x1-x2;
+ val2 = y1-y2;
+ ensure("4:operator-= failed", is_approx_equal(val1, vec2.mV[VX]) && is_approx_equal(val2, vec2.mV[VY]));
+ }
+
+ template<> template<>
+ void v2math_object::test<14>()
+ {
+ F32 x1 =1.f, y1 = 2.f;
+ F32 val1, val2, mulVal = 4.332f;
+ LLVector2 vec2(x1, y1);
+ vec2 /=mulVal;
+ val1 = x1 / mulVal;
+ val2 = y1 / mulVal;
+ ensure("1:operator/= failed", is_approx_equal(val1, vec2.mV[VX]) && is_approx_equal(val2, vec2.mV[VY]));
+
+ vec2.clearVec();
+ x1 = .213f, y1 = -2.34f, mulVal = -.23f;
+ vec2.setVec(x1, y1);
+ vec2 /=mulVal;
+ val1 = x1 / mulVal;
+ val2 = y1 / mulVal;
+ ensure("2:operator/= failed", is_approx_equal(val1, vec2.mV[VX]) && is_approx_equal(val2, vec2.mV[VY]));
+ }
+
+ template<> template<>
+ void v2math_object::test<15>()
+ {
+ F32 x1 =1.f, y1 = 2.f;
+ F32 val1, val2, mulVal = 4.332f;
+ LLVector2 vec2(x1, y1);
+ vec2 *=mulVal;
+ val1 = x1*mulVal;
+ val2 = y1*mulVal;
+ ensure("1:operator*= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY]));
+
+ vec2.clearVec();
+ x1 = .213f, y1 = -2.34f, mulVal = -.23f;
+ vec2.setVec(x1, y1);
+ vec2 *=mulVal;
+ val1 = x1*mulVal;
+ val2 = y1*mulVal;
+ ensure("2:operator*= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY]));
+ }
+
+ template<> template<>
+ void v2math_object::test<16>()
+ {
+ F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f;
+ F32 val1, val2;
+ LLVector2 vec2(x1, y1), vec3(x2, y2);
+ vec2 %= vec3;
+ val1 = x1*y2 - x2*y1;
+ val2 = y1*x2 - y2*x1;
+ ensure("1:operator%= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY]));
+ }
+
+ template<> template<>
+ void v2math_object::test<17>()
+ {
+ F32 x1 =1.f, y1 = 2.f;
+ LLVector2 vec2(x1, y1),vec3;
+ vec3 = -vec2;
+ ensure("1:operator- failed",(-vec3 == vec2));
+ }
+
+ template<> template<>
+ void v2math_object::test<18>()
+ {
+ F32 x1 =1.f, y1 = 2.f;
+ std::ostringstream stream1, stream2;
+ LLVector2 vec2(x1, y1),vec3;
+ stream1 << vec2;
+ vec3.setVec(x1, y1);
+ stream2 << vec3;
+ ensure("1:operator << failed",(stream1.str() == stream2.str()));
+ }
+
+ template<> template<>
+ void v2math_object::test<19>()
+ {
+ F32 x1 =1.0f, y1 = 2.0f, x2 = -.32f, y2 = .2234f;
+ LLVector2 vec2(x1, y1),vec3(x2, y2);
+ ensure("1:operator < failed",(vec3 < vec2));
+
+ x1 = 1.0f, y1 = 2.0f, x2 = 1.0f, y2 = 3.2234f;
+ vec2.setVec(x1, y1);
+ vec3.setVec(x2, y2);
+ ensure("2:operator < failed", (FALSE == (vec3 < vec2)));
+ }
+
+ template<> template<>
+ void v2math_object::test<20>()
+ {
+ F32 x1 =1.0f, y1 = 2.0f;
+ LLVector2 vec2(x1, y1);
+ ensure("1:operator [] failed",( x1 == vec2[0]));
+ ensure("2:operator [] failed",( y1 == vec2[1]));
+
+ vec2.clearVec();
+ x1 = 23.0f, y1 = -.2361f;
+ vec2.setVec(x1, y1);
+ F32 ref1 = vec2[0];
+ ensure("3:operator [] failed", ( ref1 == x1));
+ F32 ref2 = vec2[1];
+ ensure("4:operator [] failed", ( ref2 == y1));
+ }
+
+ template<> template<>
+ void v2math_object::test<21>()
+ {
+ F32 x1 =1.f, y1 = 2.f, x2 = -.32f, y2 = .2234f;
+ F32 val1, val2;
+ LLVector2 vec2(x1, y1),vec3(x2, y2);
+ val1 = dist_vec_squared2D(vec2, vec3);
+ val2 = (x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2);
+ ensure_equals("dist_vec_squared2D values are not equal",val2, val1);
+
+ val1 = dist_vec_squared(vec2, vec3);
+ ensure_equals("dist_vec_squared values are not equal",val2, val1);
+
+ val1 = dist_vec(vec2, vec3);
+ val2 = fsqrtf((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2));
+ ensure_equals("dist_vec values are not equal",val2, val1);
+ }
+
+ template<> template<>
+ void v2math_object::test<22>()
+ {
+ F32 x1 =1.f, y1 = 2.f, x2 = -.32f, y2 = .2234f,fVal = .0121f;
+ F32 val1, val2;
+ LLVector2 vec2(x1, y1),vec3(x2, y2);
+ LLVector2 vec4 = lerp(vec2, vec3, fVal);
+ val1 = x1 + (x2 - x1) * fVal;
+ val2 = y1 + (y2 - y1) * fVal;
+ ensure("lerp values are not equal", ((val1 == vec4.mV[VX]) && (val2 == vec4.mV[VY])));
+ }
+
+ template<> template<>
+ void v2math_object::test<23>()
+ {
+ F32 x1 =1.f, y1 = 2.f;
+ F32 val1, val2;
+ LLVector2 vec2(x1, y1);
+
+ F32 vecMag = vec2.normVec();
+ F32 mag = fsqrtf(x1*x1 + y1*y1);
+
+ F32 oomag = 1.f / mag;
+ val1 = x1 * oomag;
+ val2 = y1 * oomag;
+
+ ensure("normVec failed", is_approx_equal(val1, vec2.mV[VX]) && is_approx_equal(val2, vec2.mV[VY]) && is_approx_equal(vecMag, mag));
+
+ x1 =.00000001f, y1 = 0.f;
+
+ vec2.setVec(x1, y1);
+ vecMag = vec2.normVec();
+ ensure("normVec failed should be 0.", 0. == vec2.mV[VX] && 0. == vec2.mV[VY] && vecMag == 0.);
+ }
+}
diff --git a/indra/llmath/tests/v3color_test.cpp b/indra/llmath/tests/v3color_test.cpp
new file mode 100644
index 0000000000..316b6e392f
--- /dev/null
+++ b/indra/llmath/tests/v3color_test.cpp
@@ -0,0 +1,315 @@
+/**
+ * @file v3color_test.cpp
+ * @author Adroit
+ * @date 2007-03
+ * @brief v3color test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+
+#include "../v3color.h"
+
+
+namespace tut
+{
+ struct v3color_data
+ {
+ };
+ typedef test_group<v3color_data> v3color_test;
+ typedef v3color_test::object v3color_object;
+ tut::v3color_test v3color_testcase("v3color");
+
+ template<> template<>
+ void v3color_object::test<1>()
+ {
+ LLColor3 llcolor3;
+ ensure("1:LLColor3:Fail to default-initialize ", (0.0f == llcolor3.mV[0]) && (0.0f == llcolor3.mV[1]) && (0.0f == llcolor3.mV[2]));
+ F32 r = 2.0f, g = 3.2f, b = 1.f;
+ F32 v1,v2,v3;
+ LLColor3 llcolor3a(r,g,b);
+ ensure("2:LLColor3:Fail to initialize " ,(2.0f == llcolor3a.mV[0]) && (3.2f == llcolor3a.mV[1]) && (1.f == llcolor3a.mV[2]));
+
+ const F32 vec[3] = {2.0f, 3.2f,1.f};
+ LLColor3 llcolor3b(vec);
+ ensure("3:LLColor3:Fail to initialize " ,(2.0f == llcolor3b.mV[0]) && (3.2f == llcolor3b.mV[1]) && (1.f == llcolor3b.mV[2]));
+ const char* str = "561122";
+ LLColor3 llcolor3c(str);
+ v1 = (F32)86.0f/255.0f; // 0x56 = 86
+ v2 = (F32)17.0f/255.0f; // 0x11 = 17
+ v3 = (F32)34.0f/255.f; // 0x22 = 34
+ ensure("4:LLColor3:Fail to initialize " , is_approx_equal(v1, llcolor3c.mV[0]) && is_approx_equal(v2, llcolor3c.mV[1]) && is_approx_equal(v3, llcolor3c.mV[2]));
+ }
+
+ template<> template<>
+ void v3color_object::test<2>()
+ {
+ LLColor3 llcolor3;
+ llcolor3.setToBlack();
+ ensure("setToBlack:Fail to set black ", ((llcolor3.mV[0] == 0.f) && (llcolor3.mV[1] == 0.f) && (llcolor3.mV[2] == 0.f)));
+ llcolor3.setToWhite();
+ ensure("setToWhite:Fail to set white ", ((llcolor3.mV[0] == 1.f) && (llcolor3.mV[1] == 1.f) && (llcolor3.mV[2] == 1.f)));
+ }
+
+ template<> template<>
+ void v3color_object::test<3>()
+ {
+ F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f;
+ LLColor3 llcolor3, llcolor3a;
+ llcolor3.setVec(r,g,b);
+ ensure("1:setVec(r,g,b) Fail ",((r == llcolor3.mV[0]) && (g == llcolor3.mV[1]) && (b == llcolor3.mV[2])));
+ llcolor3a.setVec(llcolor3);
+ ensure_equals("2:setVec(LLColor3) Fail ", llcolor3,llcolor3a);
+ F32 vec[3] = {1.2324f, 2.45634f, .234563f};
+ llcolor3.setToBlack();
+ llcolor3.setVec(vec);
+ ensure("3:setVec(F32*) Fail ",((vec[0] == llcolor3.mV[0]) && (vec[1] == llcolor3.mV[1]) && (vec[2] == llcolor3.mV[2])));
+ }
+
+ template<> template<>
+ void v3color_object::test<4>()
+ {
+ F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f;
+ LLColor3 llcolor3(r,g,b);
+ ensure("magVecSquared:Fail ", is_approx_equal(llcolor3.magVecSquared(), (r*r + g*g + b*b)));
+ ensure("magVec:Fail ", is_approx_equal(llcolor3.magVec(), fsqrtf(r*r + g*g + b*b)));
+ }
+
+ template<> template<>
+ void v3color_object::test<5>()
+ {
+ F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f;
+ F32 val1, val2,val3;
+ LLColor3 llcolor3(r,g,b);
+ F32 vecMag = llcolor3.normVec();
+ F32 mag = fsqrtf(r*r + g*g + b*b);
+ F32 oomag = 1.f / mag;
+ val1 = r * oomag;
+ val2 = g * oomag;
+ val3 = b * oomag;
+ ensure("1:normVec failed ", (is_approx_equal(val1, llcolor3.mV[0]) && is_approx_equal(val2, llcolor3.mV[1]) && is_approx_equal(val3, llcolor3.mV[2]) && is_approx_equal(vecMag, mag)));
+ r = .000000000f, g = 0.f, b = 0.0f;
+ llcolor3.setVec(r,g,b);
+ vecMag = llcolor3.normVec();
+ ensure("2:normVec failed should be 0. ", (0. == llcolor3.mV[0] && 0. == llcolor3.mV[1] && 0. == llcolor3.mV[2] && vecMag == 0.));
+ }
+
+ template<> template<>
+ void v3color_object::test<6>()
+ {
+ F32 r = 2.3436212f, g = -1231.f, b = .7849321232f;
+ std::ostringstream stream1, stream2;
+ LLColor3 llcolor3(r,g,b),llcolor3a;
+ stream1 << llcolor3;
+ llcolor3a.setVec(r,g,b);
+ stream2 << llcolor3a;
+ ensure("operator << failed ", (stream1.str() == stream2.str()));
+ }
+
+ template<> template<>
+ void v3color_object::test<7>()
+ {
+ F32 r = 2.3436212f, g = -1231.f, b = .7849321232f;
+ LLColor3 llcolor3(r,g,b),llcolor3a;
+ llcolor3a = llcolor3;
+ ensure("operator == failed ", (llcolor3a == llcolor3));
+ }
+
+ template<> template<>
+ void v3color_object::test<8>()
+ {
+ F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
+ LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2),llcolor3b;
+ llcolor3b = llcolor3 + llcolor3a ;
+ ensure("1:operator+ failed",is_approx_equal(r1+r2 ,llcolor3b.mV[0]) && is_approx_equal(g1+g2,llcolor3b.mV[1])&& is_approx_equal(b1+b2,llcolor3b.mV[2]));
+ r1 = -.235f, g1 = -24.32f, b1 = 2.13f, r2 = -2.3f, g2 = 1.f, b2 = 34.21f;
+ llcolor3.setVec(r1,g1,b1);
+ llcolor3a.setVec(r2,g2,b2);
+ llcolor3b = llcolor3 + llcolor3a;
+ ensure("2:operator+ failed",is_approx_equal(r1+r2 ,llcolor3b.mV[0]) && is_approx_equal(g1+g2,llcolor3b.mV[1])&& is_approx_equal(b1+b2,llcolor3b.mV[2]));
+ }
+
+ template<> template<>
+ void v3color_object::test<9>()
+ {
+ F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
+ LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2),llcolor3b;
+ llcolor3b = llcolor3 - llcolor3a ;
+ ensure("1:operator- failed",is_approx_equal(r1-r2 ,llcolor3b.mV[0]) && is_approx_equal(g1-g2,llcolor3b.mV[1])&& is_approx_equal(b1-b2,llcolor3b.mV[2]));
+ r1 = -.235f, g1 = -24.32f, b1 = 2.13f, r2 = -2.3f, g2 = 1.f, b2 = 34.21f;
+ llcolor3.setVec(r1,g1,b1);
+ llcolor3a.setVec(r2,g2,b2);
+ llcolor3b = llcolor3 - llcolor3a;
+ ensure("2:operator- failed",is_approx_equal(r1-r2 ,llcolor3b.mV[0]) && is_approx_equal(g1-g2,llcolor3b.mV[1])&& is_approx_equal(b1-b2,llcolor3b.mV[2]));
+ }
+
+ template<> template<>
+ void v3color_object::test<10>()
+ {
+ F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
+ LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2),llcolor3b;
+ llcolor3b = llcolor3 * llcolor3a;
+ ensure("1:operator* failed",is_approx_equal(r1*r2 ,llcolor3b.mV[0]) && is_approx_equal(g1*g2,llcolor3b.mV[1])&& is_approx_equal(b1*b2,llcolor3b.mV[2]));
+ llcolor3a.setToBlack();
+ F32 mulVal = 4.332f;
+ llcolor3a = llcolor3 * mulVal;
+ ensure("2:operator* failed",is_approx_equal(r1*mulVal ,llcolor3a.mV[0]) && is_approx_equal(g1*mulVal,llcolor3a.mV[1])&& is_approx_equal(b1*mulVal,llcolor3a.mV[2]));
+ llcolor3a.setToBlack();
+ llcolor3a = mulVal * llcolor3;
+ ensure("3:operator* failed",is_approx_equal(r1*mulVal ,llcolor3a.mV[0]) && is_approx_equal(g1*mulVal,llcolor3a.mV[1])&& is_approx_equal(b1*mulVal,llcolor3a.mV[2]));
+ }
+
+ template<> template<>
+ void v3color_object::test<11>()
+ {
+ F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f;
+ LLColor3 llcolor3(r,g,b),llcolor3a;
+ llcolor3a = -llcolor3;
+ ensure("operator- failed ", (-llcolor3a == llcolor3));
+ }
+
+ template<> template<>
+ void v3color_object::test<12>()
+ {
+ F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f;
+ LLColor3 llcolor3(r,g,b),llcolor3a(r,g,b);
+ ensure_equals("1:operator== failed",llcolor3a,llcolor3);
+ r = 13.3436212f, g = -11.f, b = .7849321232f;
+ llcolor3.setVec(r,g,b);
+ llcolor3a.setVec(r,g,b);
+ ensure_equals("2:operator== failed",llcolor3a,llcolor3);
+ }
+
+ template<> template<>
+ void v3color_object::test<13>()
+ {
+ F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
+ LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2);
+ ensure("1:operator!= failed",(llcolor3 != llcolor3a));
+ llcolor3.setToBlack();
+ llcolor3a.setVec(llcolor3);
+ ensure("2:operator!= failed", ( FALSE == (llcolor3a != llcolor3)));
+ }
+
+ template<> template<>
+ void v3color_object::test<14>()
+ {
+ F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
+ LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2);
+ llcolor3a += llcolor3;
+ ensure("1:operator+= failed",is_approx_equal(r1+r2 ,llcolor3a.mV[0]) && is_approx_equal(g1+g2,llcolor3a.mV[1])&& is_approx_equal(b1+b2,llcolor3a.mV[2]));
+ llcolor3.setVec(r1,g1,b1);
+ llcolor3a.setVec(r2,g2,b2);
+ llcolor3a += llcolor3;
+ ensure("2:operator+= failed",is_approx_equal(r1+r2 ,llcolor3a.mV[0]) && is_approx_equal(g1+g2,llcolor3a.mV[1])&& is_approx_equal(b1+b2,llcolor3a.mV[2]));
+ }
+
+ template<> template<>
+ void v3color_object::test<15>()
+ {
+ F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
+ LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2);
+ llcolor3a -= llcolor3;
+ ensure("1:operator-= failed", is_approx_equal(r2-r1, llcolor3a.mV[0]));
+ ensure("2:operator-= failed", is_approx_equal(g2-g1, llcolor3a.mV[1]));
+ ensure("3:operator-= failed", is_approx_equal(b2-b1, llcolor3a.mV[2]));
+ llcolor3.setVec(r1,g1,b1);
+ llcolor3a.setVec(r2,g2,b2);
+ llcolor3a -= llcolor3;
+ ensure("4:operator-= failed", is_approx_equal(r2-r1, llcolor3a.mV[0]));
+ ensure("5:operator-= failed", is_approx_equal(g2-g1, llcolor3a.mV[1]));
+ ensure("6:operator-= failed", is_approx_equal(b2-b1, llcolor3a.mV[2]));
+ }
+
+ template<> template<>
+ void v3color_object::test<16>()
+ {
+ F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
+ LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2);
+ llcolor3a *= llcolor3;
+ ensure("1:operator*= failed",is_approx_equal(r1*r2 ,llcolor3a.mV[0]) && is_approx_equal(g1*g2,llcolor3a.mV[1])&& is_approx_equal(b1*b2,llcolor3a.mV[2]));
+ F32 mulVal = 4.332f;
+ llcolor3 *=mulVal;
+ ensure("2:operator*= failed",is_approx_equal(r1*mulVal ,llcolor3.mV[0]) && is_approx_equal(g1*mulVal,llcolor3.mV[1])&& is_approx_equal(b1*mulVal,llcolor3.mV[2]));
+ }
+
+ template<> template<>
+ void v3color_object::test<17>()
+ {
+ F32 r = 2.3436212f, g = -1231.f, b = .7849321232f;
+ LLColor3 llcolor3(r,g,b);
+ llcolor3.clamp();
+ ensure("1:clamp:Fail to clamp " ,(1.0f == llcolor3.mV[0]) && (0.f == llcolor3.mV[1]) && (b == llcolor3.mV[2]));
+ r = -2.3436212f, g = -1231.f, b = 67.7849321232f;
+ llcolor3.setVec(r,g,b);
+ llcolor3.clamp();
+ ensure("2:clamp:Fail to clamp " ,(0.f == llcolor3.mV[0]) && (0.f == llcolor3.mV[1]) && (1.f == llcolor3.mV[2]));
+ }
+
+ template<> template<>
+ void v3color_object::test<18>()
+ {
+ F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
+ F32 val = 2.3f,val1,val2,val3;
+ LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2);
+ val1 = r1 + (r2 - r1)* val;
+ val2 = g1 + (g2 - g1)* val;
+ val3 = b1 + (b2 - b1)* val;
+ LLColor3 llcolor3b = lerp(llcolor3,llcolor3a,val);
+ ensure("lerp failed ", ((val1 ==llcolor3b.mV[0])&& (val2 ==llcolor3b.mV[1]) && (val3 ==llcolor3b.mV[2])));
+ }
+
+ template<> template<>
+ void v3color_object::test<19>()
+ {
+ F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
+ LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2);
+ F32 val = distVec(llcolor3,llcolor3a);
+ ensure("distVec failed ", is_approx_equal(fsqrtf((r1-r2)*(r1-r2) + (g1-g2)*(g1-g2) + (b1-b2)*(b1-b2)) ,val));
+
+ F32 val1 = distVec_squared(llcolor3,llcolor3a);
+ ensure("distVec_squared failed ", is_approx_equal(((r1-r2)*(r1-r2) + (g1-g2)*(g1-g2) + (b1-b2)*(b1-b2)) ,val1));
+ }
+
+ template<> template<>
+ void v3color_object::test<20>()
+ {
+ F32 r1 = 1.02223f, g1 = 22222.212f, b1 = 122222.00002f;
+ LLColor3 llcolor31(r1,g1,b1);
+
+ LLSD sd = llcolor31.getValue();
+ LLColor3 llcolor32;
+ llcolor32.setValue(sd);
+ ensure_equals("LLColor3::setValue/getValue failed", llcolor31, llcolor32);
+
+ LLColor3 llcolor33(sd);
+ ensure_equals("LLColor3(LLSD) failed", llcolor31, llcolor33);
+ }
+}
diff --git a/indra/llmath/tests/v3dmath_test.cpp b/indra/llmath/tests/v3dmath_test.cpp
new file mode 100644
index 0000000000..e7c949186c
--- /dev/null
+++ b/indra/llmath/tests/v3dmath_test.cpp
@@ -0,0 +1,532 @@
+/**
+ * @file v3dmath_test.cpp
+ * @author Adroit
+ * @date 2007-03
+ * @brief v3dmath test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llsd.h"
+#include "../test/lltut.h"
+
+#include "../llquaternion.h"
+#include "../m3math.h"
+#include "../v4math.h"
+#include "../v3dmath.h"
+#include "../v3dmath.h"
+
+namespace tut
+{
+ struct v3dmath_data
+ {
+ };
+ typedef test_group<v3dmath_data> v3dmath_test;
+ typedef v3dmath_test::object v3dmath_object;
+ tut::v3dmath_test v3dmath_testcase("v3dmath");
+
+ template<> template<>
+ void v3dmath_object::test<1>()
+ {
+ LLVector3d vec3D;
+ ensure("1:LLVector3d:Fail to initialize ", ((0 == vec3D.mdV[VX]) && (0 == vec3D.mdV[VY]) && (0 == vec3D.mdV[VZ])));
+ F64 x = 2.32f, y = 1.212f, z = -.12f;
+ LLVector3d vec3Da(x,y,z);
+ ensure("2:LLVector3d:Fail to initialize ", ((2.32f == vec3Da.mdV[VX]) && (1.212f == vec3Da.mdV[VY]) && (-.12f == vec3Da.mdV[VZ])));
+ const F64 vec[3] = {1.2f ,3.2f, -4.2f};
+ LLVector3d vec3Db(vec);
+ ensure("3:LLVector3d:Fail to initialize ", ((1.2f == vec3Db.mdV[VX]) && (3.2f == vec3Db.mdV[VY]) && (-4.2f == vec3Db.mdV[VZ])));
+ LLVector3 vec3((F32)x,(F32)y,(F32)z);
+ LLVector3d vec3Dc(vec3);
+ ensure_equals("4:LLVector3d Fail to initialize",vec3Da,vec3Dc);
+ }
+
+ template<> template<>
+ void v3dmath_object::test<2>()
+ {
+ S32 a = -235;
+ LLSD llsd(a);
+ LLVector3d vec3d(llsd);
+ LLSD sd = vec3d.getValue();
+ LLVector3d vec3da(sd);
+ ensure("1:getValue:Fail ", (vec3d == vec3da));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<3>()
+ {
+ F64 a = 232345521.411132;
+ LLSD llsd(a);
+ LLVector3d vec3d;
+ vec3d.setValue(llsd);
+ LLSD sd = vec3d.getValue();
+ LLVector3d vec3da(sd);
+ ensure("1:setValue:Fail to initialize ", (vec3d == vec3da));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<4>()
+ {
+ F64 a[3] = {222231.43222, 12345.2343, -434343.33222};
+ LLSD llsd;
+ llsd[0] = a[0];
+ llsd[1] = a[1];
+ llsd[2] = a[2];
+ LLVector3d vec3D;
+ vec3D = (LLVector3d)llsd;
+ ensure("1:operator=:Fail to initialize ", ((llsd[0].asReal()== vec3D.mdV[VX]) && (llsd[1].asReal() == vec3D.mdV[VY]) && (llsd[2].asReal() == vec3D.mdV[VZ])));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<5>()
+ {
+ F64 x = 2.32f, y = 1.212f, z = -.12f;
+ LLVector3d vec3D(x,y,z);
+ vec3D.clearVec();
+ ensure("1:clearVec:Fail to initialize ", ((0 == vec3D.mdV[VX]) && (0 == vec3D.mdV[VY]) && (0 == vec3D.mdV[VZ])));
+ vec3D.setVec(x,y,z);
+ ensure("2:setVec:Fail to initialize ", ((x == vec3D.mdV[VX]) && (y == vec3D.mdV[VY]) && (z == vec3D.mdV[VZ])));
+ vec3D.zeroVec();
+ ensure("3:zeroVec:Fail to initialize ", ((0 == vec3D.mdV[VX]) && (0 == vec3D.mdV[VY]) && (0 == vec3D.mdV[VZ])));
+ vec3D.clearVec();
+ LLVector3 vec3((F32)x,(F32)y,(F32)z);
+ vec3D.setVec(vec3);
+ ensure("4:setVec:Fail to initialize ", ((x == vec3D.mdV[VX]) && (y == vec3D.mdV[VY]) && (z == vec3D.mdV[VZ])));
+ vec3D.clearVec();
+ const F64 vec[3] = {x,y,z};
+ vec3D.setVec(vec);
+ ensure("5:setVec:Fail to initialize ", ((x == vec3D.mdV[VX]) && (y == vec3D.mdV[VY]) && (z == vec3D.mdV[VZ])));
+ LLVector3d vec3Da;
+ vec3Da.setVec(vec3D);
+ ensure_equals("6:setVec: Fail to initialize", vec3D, vec3Da);
+ }
+
+ template<> template<>
+ void v3dmath_object::test<6>()
+ {
+ F64 x = -2.32, y = 1.212, z = -.12;
+ LLVector3d vec3D(x,y,z);
+ vec3D.abs();
+ ensure("1:abs:Fail ", ((-x == vec3D.mdV[VX]) && (y == vec3D.mdV[VY]) && (-z == vec3D.mdV[VZ])));
+ ensure("2:isNull():Fail ", (FALSE == vec3D.isNull()));
+ vec3D.clearVec();
+ x =.00000001, y = .000001001, z = .000001001;
+ vec3D.setVec(x,y,z);
+ ensure("3:isNull():Fail ", (TRUE == vec3D.isNull()));
+ ensure("4:isExactlyZero():Fail ", (FALSE == vec3D.isExactlyZero()));
+ x =.0000000, y = .00000000, z = .00000000;
+ vec3D.setVec(x,y,z);
+ ensure("5:isExactlyZero():Fail ", (TRUE == vec3D.isExactlyZero()));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<7>()
+ {
+ F64 x = -2.32, y = 1.212, z = -.12;
+ LLVector3d vec3D(x,y,z);
+
+ ensure("1:operator [] failed",( x == vec3D[0]));
+ ensure("2:operator [] failed",( y == vec3D[1]));
+ ensure("3:operator [] failed",( z == vec3D[2]));
+ vec3D.clearVec();
+ x = 23.23, y = -.2361, z = 3.25;
+ vec3D.setVec(x,y,z);
+ F64 &ref1 = vec3D[0];
+ ensure("4:operator [] failed",( ref1 == vec3D[0]));
+ F64 &ref2 = vec3D[1];
+ ensure("5:operator [] failed",( ref2 == vec3D[1]));
+ F64 &ref3 = vec3D[2];
+ ensure("6:operator [] failed",( ref3 == vec3D[2]));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<8>()
+ {
+ F32 x = 1.f, y = 2.f, z = -1.f;
+ LLVector4 vec4(x,y,z);
+ LLVector3d vec3D;
+ vec3D = vec4;
+ ensure("1:operator=:Fail to initialize ", ((vec4.mV[VX] == vec3D.mdV[VX]) && (vec4.mV[VY] == vec3D.mdV[VY]) && (vec4.mV[VZ] == vec3D.mdV[VZ])));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<9>()
+ {
+ F64 x1 = 1.78787878, y1 = 232322.2121, z1 = -12121.121212;
+ F64 x2 = 1.2, y2 = 2.5, z2 = 1.;
+ LLVector3d vec3D(x1,y1,z1),vec3Da(x2,y2,z2),vec3Db;
+ vec3Db = vec3Da+ vec3D;
+ ensure("1:operator+:Fail to initialize ", ((x1+x2 == vec3Db.mdV[VX]) && (y1+y2 == vec3Db.mdV[VY]) && (z1+z2 == vec3Db.mdV[VZ])));
+ x1 = -2.45, y1 = 2.1, z1 = 3.0;
+ vec3D.clearVec();
+ vec3Da.clearVec();
+ vec3D.setVec(x1,y1,z1);
+ vec3Da += vec3D;
+ ensure_equals("2:operator+=: Fail to initialize", vec3Da,vec3D);
+ vec3Da += vec3D;
+ ensure("3:operator+=:Fail to initialize ", ((2*x1 == vec3Da.mdV[VX]) && (2*y1 == vec3Da.mdV[VY]) && (2*z1 == vec3Da.mdV[VZ])));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<10>()
+ {
+ F64 x1 = 1., y1 = 2., z1 = -1.1;
+ F64 x2 = 1.2, y2 = 2.5, z2 = 1.;
+ LLVector3d vec3D(x1,y1,z1),vec3Da(x2,y2,z2),vec3Db;
+ vec3Db = vec3Da - vec3D;
+ ensure("1:operator-:Fail to initialize ", ((x2-x1 == vec3Db.mdV[VX]) && (y2-y1 == vec3Db.mdV[VY]) && (z2-z1 == vec3Db.mdV[VZ])));
+ x1 = -2.45, y1 = 2.1, z1 = 3.0;
+ vec3D.clearVec();
+ vec3Da.clearVec();
+ vec3D.setVec(x1,y1,z1);
+ vec3Da -=vec3D;
+ ensure("2:operator-=:Fail to initialize ", ((2.45 == vec3Da.mdV[VX]) && (-2.1 == vec3Da.mdV[VY]) && (-3.0 == vec3Da.mdV[VZ])));
+ vec3Da -= vec3D;
+ ensure("3:operator-=:Fail to initialize ", ((-2*x1 == vec3Da.mdV[VX]) && (-2*y1 == vec3Da.mdV[VY]) && (-2*z1 == vec3Da.mdV[VZ])));
+ }
+ template<> template<>
+ void v3dmath_object::test<11>()
+ {
+ F64 x1 = 1., y1 = 2., z1 = -1.1;
+ F64 x2 = 1.2, y2 = 2.5, z2 = 1.;
+ LLVector3d vec3D(x1,y1,z1),vec3Da(x2,y2,z2);
+ F64 res = vec3D * vec3Da;
+ ensure_approximately_equals(
+ "1:operator* failed",
+ res,
+ (x1*x2 + y1*y2 + z1*z2),
+ 8);
+ vec3Da.clearVec();
+ F64 mulVal = 4.2;
+ vec3Da = vec3D * mulVal;
+ ensure_approximately_equals(
+ "2a:operator* failed",
+ vec3Da.mdV[VX],
+ x1*mulVal,
+ 8);
+ ensure_approximately_equals(
+ "2b:operator* failed",
+ vec3Da.mdV[VY],
+ y1*mulVal,
+ 8);
+ ensure_approximately_equals(
+ "2c:operator* failed",
+ vec3Da.mdV[VZ],
+ z1*mulVal,
+ 8);
+ vec3Da.clearVec();
+ vec3Da = mulVal * vec3D;
+ ensure_approximately_equals(
+ "3a:operator* failed",
+ vec3Da.mdV[VX],
+ x1*mulVal,
+ 8);
+ ensure_approximately_equals(
+ "3b:operator* failed",
+ vec3Da.mdV[VY],
+ y1*mulVal,
+ 8);
+ ensure_approximately_equals(
+ "3c:operator* failed",
+ vec3Da.mdV[VZ],
+ z1*mulVal,
+ 8);
+ vec3D *= mulVal;
+ ensure_approximately_equals(
+ "4a:operator*= failed",
+ vec3D.mdV[VX],
+ x1*mulVal,
+ 8);
+ ensure_approximately_equals(
+ "4b:operator*= failed",
+ vec3D.mdV[VY],
+ y1*mulVal,
+ 8);
+ ensure_approximately_equals(
+ "4c:operator*= failed",
+ vec3D.mdV[VZ],
+ z1*mulVal,
+ 8);
+ }
+
+ template<> template<>
+ void v3dmath_object::test<12>()
+ {
+ F64 x1 = 1., y1 = 2., z1 = -1.1;
+ F64 x2 = 1.2, y2 = 2.5, z2 = 1.;
+ F64 val1, val2, val3;
+ LLVector3d vec3D(x1,y1,z1),vec3Da(x2,y2,z2), vec3Db;
+ vec3Db = vec3D % vec3Da;
+ val1 = y1*z2 - y2*z1;
+ val2 = z1*x2 -z2*x1;
+ val3 = x1*y2-x2*y1;
+ ensure("1:operator% failed",(val1 == vec3Db.mdV[VX]) && (val2 == vec3Db.mdV[VY]) && (val3 == vec3Db.mdV[VZ]));
+ vec3D %= vec3Da;
+ ensure("2:operator%= failed",
+ is_approx_equal(vec3D.mdV[VX],vec3Db.mdV[VX]) &&
+ is_approx_equal(vec3D.mdV[VY],vec3Db.mdV[VY]) &&
+ is_approx_equal(vec3D.mdV[VZ],vec3Db.mdV[VZ]) );
+ }
+
+ template<> template<>
+ void v3dmath_object::test<13>()
+ {
+ F64 x1 = 1., y1 = 2., z1 = -1.1,div = 4.2;
+ F64 t = 1.f / div;
+ LLVector3d vec3D(x1,y1,z1), vec3Da;
+ vec3Da = vec3D/div;
+ ensure_approximately_equals(
+ "1a:operator/ failed",
+ vec3Da.mdV[VX],
+ x1*t,
+ 8);
+ ensure_approximately_equals(
+ "1b:operator/ failed",
+ vec3Da.mdV[VY],
+ y1*t,
+ 8);
+ ensure_approximately_equals(
+ "1c:operator/ failed",
+ vec3Da.mdV[VZ],
+ z1*t,
+ 8);
+ x1 = 1.23, y1 = 4., z1 = -2.32;
+ vec3D.clearVec();
+ vec3Da.clearVec();
+ vec3D.setVec(x1,y1,z1);
+ vec3Da = vec3D/div;
+ ensure_approximately_equals(
+ "2a:operator/ failed",
+ vec3Da.mdV[VX],
+ x1*t,
+ 8);
+ ensure_approximately_equals(
+ "2b:operator/ failed",
+ vec3Da.mdV[VY],
+ y1*t,
+ 8);
+ ensure_approximately_equals(
+ "2c:operator/ failed",
+ vec3Da.mdV[VZ],
+ z1*t,
+ 8);
+ vec3D /= div;
+ ensure_approximately_equals(
+ "3a:operator/= failed",
+ vec3D.mdV[VX],
+ x1*t,
+ 8);
+ ensure_approximately_equals(
+ "3b:operator/= failed",
+ vec3D.mdV[VY],
+ y1*t,
+ 8);
+ ensure_approximately_equals(
+ "3c:operator/= failed",
+ vec3D.mdV[VZ],
+ z1*t,
+ 8);
+ }
+
+ template<> template<>
+ void v3dmath_object::test<14>()
+ {
+ F64 x1 = 1., y1 = 2., z1 = -1.1;
+ LLVector3d vec3D(x1,y1,z1), vec3Da;
+ ensure("1:operator!= failed",(TRUE == (vec3D !=vec3Da)));
+ vec3Da = vec3D;
+ ensure("2:operator== failed",(vec3D ==vec3Da));
+ vec3D.clearVec();
+ vec3Da.clearVec();
+ x1 = .211, y1 = 21.111, z1 = 23.22;
+ vec3D.setVec(x1,y1,z1);
+ vec3Da.setVec(x1,y1,z1);
+ ensure("3:operator== failed",(vec3D ==vec3Da));
+ ensure("4:operator!= failed",(FALSE == (vec3D !=vec3Da)));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<15>()
+ {
+ F64 x1 = 1., y1 = 2., z1 = -1.1;
+ LLVector3d vec3D(x1,y1,z1), vec3Da;
+ std::ostringstream stream1, stream2;
+ stream1 << vec3D;
+ vec3Da.setVec(x1,y1,z1);
+ stream2 << vec3Da;
+ ensure("1:operator << failed",(stream1.str() == stream2.str()));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<16>()
+ {
+ F64 x1 = 1.23, y1 = 2.0, z1 = 4.;
+ std::string buf("1.23 2. 4");
+ LLVector3d vec3D, vec3Da(x1,y1,z1);
+ LLVector3d::parseVector3d(buf, &vec3D);
+ ensure_equals("1:parseVector3d: failed " , vec3D, vec3Da);
+ }
+
+ template<> template<>
+ void v3dmath_object::test<17>()
+ {
+ F64 x1 = 1., y1 = 2., z1 = -1.1;
+ LLVector3d vec3D(x1,y1,z1), vec3Da;
+ vec3Da = -vec3D;
+ ensure("1:operator- failed", (vec3D == - vec3Da));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<18>()
+ {
+ F64 x = 1., y = 2., z = -1.1;
+ LLVector3d vec3D(x,y,z);
+ F64 res = (x*x + y*y + z*z) - vec3D.magVecSquared();
+ ensure("1:magVecSquared:Fail ", ((-F_APPROXIMATELY_ZERO <= res)&& (res <=F_APPROXIMATELY_ZERO)));
+ res = fsqrtf(x*x + y*y + z*z) - vec3D.magVec();
+ ensure("2:magVec: Fail ", ((-F_APPROXIMATELY_ZERO <= res)&& (res <=F_APPROXIMATELY_ZERO)));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<19>()
+ {
+ F64 x = 1., y = 2., z = -1.1;
+ LLVector3d vec3D(x,y,z);
+ F64 mag = vec3D.normVec();
+ mag = 1.f/ mag;
+ ensure_approximately_equals(
+ "1a:normVec: Fail ",
+ vec3D.mdV[VX],
+ x * mag,
+ 8);
+ ensure_approximately_equals(
+ "1b:normVec: Fail ",
+ vec3D.mdV[VY],
+ y * mag,
+ 8);
+ ensure_approximately_equals(
+ "1c:normVec: Fail ",
+ vec3D.mdV[VZ],
+ z * mag,
+ 8);
+ x = 0.000000001, y = 0.000000001, z = 0.000000001;
+ vec3D.clearVec();
+ vec3D.setVec(x,y,z);
+ mag = vec3D.normVec();
+ ensure_approximately_equals(
+ "2a:normVec: Fail ",
+ vec3D.mdV[VX],
+ x * mag,
+ 8);
+ ensure_approximately_equals(
+ "2b:normVec: Fail ",
+ vec3D.mdV[VY],
+ y * mag,
+ 8);
+ ensure_approximately_equals(
+ "2c:normVec: Fail ",
+ vec3D.mdV[VZ],
+ z * mag,
+ 8);
+ }
+
+ template<> template<>
+ void v3dmath_object::test<20>()
+ {
+ F64 x1 = 1111.232222;
+ F64 y1 = 2222222222.22;
+ F64 z1 = 422222222222.0;
+ std::string buf("1111.232222 2222222222.22 422222222222");
+ LLVector3d vec3Da, vec3Db(x1,y1,z1);
+ LLVector3d::parseVector3d(buf, &vec3Da);
+ ensure_equals("1:parseVector3 failed", vec3Da, vec3Db);
+ }
+
+ template<> template<>
+ void v3dmath_object::test<21>()
+ {
+ F64 x1 = 1., y1 = 2., z1 = -1.1;
+ F64 x2 = 1.2, y2 = 2.5, z2 = 1.;
+ F64 val = 2.3f,val1,val2,val3;
+ val1 = x1 + (x2 - x1)* val;
+ val2 = y1 + (y2 - y1)* val;
+ val3 = z1 + (z2 - z1)* val;
+ LLVector3d vec3Da(x1,y1,z1),vec3Db(x2,y2,z2);
+ LLVector3d vec3d = lerp(vec3Da,vec3Db,val);
+ ensure("1:lerp failed", ((val1 ==vec3d.mdV[VX])&& (val2 ==vec3d.mdV[VY]) && (val3 ==vec3d.mdV[VZ])));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<22>()
+ {
+ F64 x = 2.32, y = 1.212, z = -.12;
+ F64 min = 0.0001, max = 3.0;
+ LLVector3d vec3d(x,y,z);
+ ensure("1:clamp:Fail ", (TRUE == (vec3d.clamp(min, max))));
+ x = 0.000001f, z = 5.3f;
+ vec3d.setVec(x,y,z);
+ ensure("2:clamp:Fail ", (TRUE == (vec3d.clamp(min, max))));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<23>()
+ {
+ F64 x = 10., y = 20., z = -15.;
+ F64 epsilon = .23425;
+ LLVector3d vec3Da(x,y,z), vec3Db(x,y,z);
+ ensure("1:are_parallel: Fail ", (TRUE == are_parallel(vec3Da,vec3Db,epsilon)));
+ F64 x1 = -12., y1 = -20., z1 = -100.;
+ vec3Db.clearVec();
+ vec3Db.setVec(x1,y1,z1);
+ ensure("2:are_parallel: Fail ", (FALSE == are_parallel(vec3Da,vec3Db,epsilon)));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<24>()
+ {
+#if LL_WINDOWS && _MSC_VER < 1400
+ skip("This fails on VS2003!");
+#else
+ F64 x = 10., y = 20., z = -15.;
+ F64 angle1, angle2;
+ LLVector3d vec3Da(x,y,z), vec3Db(x,y,z);
+ angle1 = angle_between(vec3Da, vec3Db);
+ ensure("1:angle_between: Fail ", (0 == angle1));
+ F64 x1 = -1., y1 = -20., z1 = -1.;
+ vec3Da.clearVec();
+ vec3Da.setVec(x1,y1,z1);
+ angle2 = angle_between(vec3Da, vec3Db);
+ vec3Db.normVec();
+ vec3Da.normVec();
+ F64 angle = vec3Db*vec3Da;
+ angle = acos(angle);
+ ensure("2:angle_between: Fail ", (angle == angle2));
+#endif
+ }
+}
diff --git a/indra/llmath/tests/v3math_test.cpp b/indra/llmath/tests/v3math_test.cpp
new file mode 100644
index 0000000000..7faf076243
--- /dev/null
+++ b/indra/llmath/tests/v3math_test.cpp
@@ -0,0 +1,573 @@
+/**
+ * @file v3math_test.cpp
+ * @author Adroit
+ * @date 2007-02
+ * @brief v3math test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+#include "llsd.h"
+
+#include "../llquaternion.h"
+#include "../llquantize.h"
+#include "../v3dmath.h"
+#include "../m3math.h"
+#include "../v4math.h"
+#include "../v3math.h"
+
+
+namespace tut
+{
+ struct v3math_data
+ {
+ };
+ typedef test_group<v3math_data> v3math_test;
+ typedef v3math_test::object v3math_object;
+ tut::v3math_test v3math_testcase("v3math");
+
+ template<> template<>
+ void v3math_object::test<1>()
+ {
+ LLVector3 vec3;
+ ensure("1:LLVector3:Fail to initialize ", ((0.f == vec3.mV[VX]) && (0.f == vec3.mV[VY]) && (0.f == vec3.mV[VZ])));
+ F32 x = 2.32f, y = 1.212f, z = -.12f;
+ LLVector3 vec3a(x,y,z);
+ ensure("2:LLVector3:Fail to initialize ", ((2.32f == vec3a.mV[VX]) && (1.212f == vec3a.mV[VY]) && (-.12f == vec3a.mV[VZ])));
+ const F32 vec[3] = {1.2f ,3.2f, -4.2f};
+ LLVector3 vec3b(vec);
+ ensure("3:LLVector3:Fail to initialize ", ((1.2f == vec3b.mV[VX]) && (3.2f == vec3b.mV[VY]) && (-4.2f == vec3b.mV[VZ])));
+ }
+
+ template<> template<>
+ void v3math_object::test<2>()
+ {
+ F32 x = 2.32f, y = 1.212f, z = -.12f;
+ LLVector3 vec3(x,y,z);
+ LLVector3d vector3d(vec3);
+ LLVector3 vec3a(vector3d);
+ ensure("1:LLVector3:Fail to initialize ", vec3 == vec3a);
+ LLVector4 vector4(vec3);
+ LLVector3 vec3b(vector4);
+ ensure("2:LLVector3:Fail to initialize ", vec3 == vec3b);
+ }
+
+ template<> template<>
+ void v3math_object::test<3>()
+ {
+ S32 a = 231;
+ LLSD llsd(a);
+ LLVector3 vec3(llsd);
+ LLSD sd = vec3.getValue();
+ LLVector3 vec3a(sd);
+ ensure("1:LLVector3:Fail to initialize ", (vec3 == vec3a));
+ }
+
+ template<> template<>
+ void v3math_object::test<4>()
+ {
+ S32 a = 231;
+ LLSD llsd(a);
+ LLVector3 vec3(llsd),vec3a;
+ vec3a = vec3;
+ ensure("1:Operator= Fail to initialize " ,(vec3 == vec3a));
+ }
+
+ template<> template<>
+ void v3math_object::test<5>()
+ {
+ F32 x = 2.32f, y = 1.212f, z = -.12f;
+ LLVector3 vec3(x,y,z);
+ ensure("1:isFinite= Fail to initialize ", (TRUE == vec3.isFinite()));//need more test cases:
+ vec3.clearVec();
+ ensure("2:clearVec:Fail to set values ", ((0.f == vec3.mV[VX]) && (0.f == vec3.mV[VY]) && (0.f == vec3.mV[VZ])));
+ vec3.setVec(x,y,z);
+ ensure("3:setVec:Fail to set values ", ((2.32f == vec3.mV[VX]) && (1.212f == vec3.mV[VY]) && (-.12f == vec3.mV[VZ])));
+ vec3.zeroVec();
+ ensure("4:zeroVec:Fail to set values ", ((0.f == vec3.mV[VX]) && (0.f == vec3.mV[VY]) && (0.f == vec3.mV[VZ])));
+ }
+
+ template<> template<>
+ void v3math_object::test<6>()
+ {
+ F32 x = 2.32f, y = 1.212f, z = -.12f;
+ LLVector3 vec3(x,y,z),vec3a;
+ vec3.abs();
+ ensure("1:abs:Fail ", ((x == vec3.mV[VX]) && (y == vec3.mV[VY]) && (-z == vec3.mV[VZ])));
+ vec3a.setVec(vec3);
+ ensure("2:setVec:Fail to initialize ", (vec3a == vec3));
+ const F32 vec[3] = {1.2f ,3.2f, -4.2f};
+ vec3.clearVec();
+ vec3.setVec(vec);
+ ensure("3:setVec:Fail to initialize ", ((1.2f == vec3.mV[VX]) && (3.2f == vec3.mV[VY]) && (-4.2f == vec3.mV[VZ])));
+ vec3a.clearVec();
+ LLVector3d vector3d(vec3);
+ vec3a.setVec(vector3d);
+ ensure("4:setVec:Fail to initialize ", (vec3 == vec3a));
+ LLVector4 vector4(vec3);
+ vec3a.clearVec();
+ vec3a.setVec(vector4);
+ ensure("5:setVec:Fail to initialize ", (vec3 == vec3a));
+ }
+
+ template<> template<>
+ void v3math_object::test<7>()
+ {
+ F32 x = 2.32f, y = 3.212f, z = -.12f;
+ F32 min = 0.0001f, max = 3.0f;
+ LLVector3 vec3(x,y,z);
+ ensure("1:clamp:Fail ", TRUE == vec3.clamp(min, max) && x == vec3.mV[VX] && max == vec3.mV[VY] && min == vec3.mV[VZ]);
+ x = 1.f, y = 2.2f, z = 2.8f;
+ vec3.setVec(x,y,z);
+ ensure("2:clamp:Fail ", FALSE == vec3.clamp(min, max));
+ }
+
+ template<> template<>
+ void v3math_object::test<8>()
+ {
+ F32 x = 2.32f, y = 1.212f, z = -.12f;
+ LLVector3 vec3(x,y,z);
+ ensure("1:magVecSquared:Fail ", is_approx_equal(vec3.magVecSquared(), (x*x + y*y + z*z)));
+ ensure("2:magVec:Fail ", is_approx_equal(vec3.magVec(), fsqrtf(x*x + y*y + z*z)));
+ }
+
+ template<> template<>
+ void v3math_object::test<9>()
+ {
+ F32 x =-2.0f, y = -3.0f, z = 1.23f ;
+ LLVector3 vec3(x,y,z);
+ ensure("1:abs():Fail ", (TRUE == vec3.abs()));
+ ensure("2:isNull():Fail", (FALSE == vec3.isNull())); //Returns TRUE if vector has a _very_small_ length
+ x =.00000001f, y = .000001001f, z = .000001001f;
+ vec3.setVec(x,y,z);
+ ensure("3:isNull(): Fail ", (TRUE == vec3.isNull()));
+ }
+
+ template<> template<>
+ void v3math_object::test<10>()
+ {
+ F32 x =-2.0f, y = -3.0f, z = 1.f ;
+ LLVector3 vec3(x,y,z),vec3a;
+ ensure("1:isExactlyZero():Fail ", (TRUE == vec3a.isExactlyZero()));
+ vec3a = vec3a.scaleVec(vec3);
+ ensure("2:scaleVec: Fail ", vec3a.mV[VX] == 0.f && vec3a.mV[VY] == 0.f && vec3a.mV[VZ] == 0.f);
+ vec3a.setVec(x,y,z);
+ vec3a = vec3a.scaleVec(vec3);
+ ensure("3:scaleVec: Fail ", ((4 == vec3a.mV[VX]) && (9 == vec3a.mV[VY]) &&(1 == vec3a.mV[VZ])));
+ ensure("4:isExactlyZero():Fail ", (FALSE == vec3.isExactlyZero()));
+ }
+
+ template<> template<>
+ void v3math_object::test<11>()
+ {
+ F32 x =20.0f, y = 30.0f, z = 15.f ;
+ F32 angle = 100.f;
+ LLVector3 vec3(x,y,z),vec3a(1.f,2.f,3.f);
+ vec3a = vec3a.rotVec(angle, vec3);
+ LLVector3 vec3b(1.f,2.f,3.f);
+ vec3b = vec3b.rotVec(angle, vec3);
+ ensure_equals("rotVec():Fail" ,vec3b,vec3a);
+ }
+
+ template<> template<>
+ void v3math_object::test<12>()
+ {
+ F32 x =-2.0f, y = -3.0f, z = 1.f ;
+ LLVector3 vec3(x,y,z);
+ ensure("1:operator [] failed",( x == vec3[0]));
+ ensure("2:operator [] failed",( y == vec3[1]));
+ ensure("3:operator [] failed",( z == vec3[2]));
+
+ vec3.clearVec();
+ x = 23.f, y = -.2361f, z = 3.25;
+ vec3.setVec(x,y,z);
+ F32 &ref1 = vec3[0];
+ ensure("4:operator [] failed",( ref1 == vec3[0]));
+ F32 &ref2 = vec3[1];
+ ensure("5:operator [] failed",( ref2 == vec3[1]));
+ F32 &ref3 = vec3[2];
+ ensure("6:operator [] failed",( ref3 == vec3[2]));
+ }
+
+ template<> template<>
+ void v3math_object::test<13>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f;
+ F32 val1, val2, val3;
+ LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2), vec3b;
+ vec3b = vec3 + vec3a ;
+ val1 = x1+x2;
+ val2 = y1+y2;
+ val3 = z1+z2;
+ ensure("1:operator+ failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ]));
+
+ vec3.clearVec();
+ vec3a.clearVec();
+ vec3b.clearVec();
+ x1 = -.235f, y1 = -24.32f,z1 = 2.13f, x2 = -2.3f, y2 = 1.f, z2 = 34.21f;
+ vec3.setVec(x1,y1,z1);
+ vec3a.setVec(x2,y2,z2);
+ vec3b = vec3 + vec3a;
+ val1 = x1+x2;
+ val2 = y1+y2;
+ val3 = z1+z2;
+ ensure("2:operator+ failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<14>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f;
+ F32 val1, val2, val3;
+ LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2), vec3b;
+ vec3b = vec3 - vec3a ;
+ val1 = x1-x2;
+ val2 = y1-y2;
+ val3 = z1-z2;
+ ensure("1:operator- failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ]));
+
+ vec3.clearVec();
+ vec3a.clearVec();
+ vec3b.clearVec();
+ x1 = -.235f, y1 = -24.32f,z1 = 2.13f, x2 = -2.3f, y2 = 1.f, z2 = 34.21f;
+ vec3.setVec(x1,y1,z1);
+ vec3a.setVec(x2,y2,z2);
+ vec3b = vec3 - vec3a;
+ val1 = x1-x2;
+ val2 = y1-y2;
+ val3 = z1-z2;
+ ensure("2:operator- failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<15>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f;
+ F32 val1, val2, val3;
+ LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2);
+ val1 = vec3 * vec3a;
+ val2 = x1*x2 + y1*y2 + z1*z2;
+ ensure_equals("1:operator* failed",val1,val2);
+
+ vec3a.clearVec();
+ F32 mulVal = 4.332f;
+ vec3a = vec3 * mulVal;
+ val1 = x1*mulVal;
+ val2 = y1*mulVal;
+ val3 = z1*mulVal;
+ ensure("2:operator* failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ]));
+ vec3a.clearVec();
+ vec3a = mulVal * vec3;
+ ensure("3:operator* failed ", (val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<16>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f;
+ F32 val1, val2, val3;
+ LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2), vec3b;
+ vec3b = vec3 % vec3a ;
+ val1 = y1*z2 - y2*z1;
+ val2 = z1*x2 -z2*x1;
+ val3 = x1*y2-x2*y1;
+ ensure("1:operator% failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ]));
+
+ vec3.clearVec();
+ vec3a.clearVec();
+ vec3b.clearVec();
+ x1 =112.f, y1 = 22.3f,z1 = 1.2f, x2 = -2.3f, y2 = 341.11f, z2 = 1234.234f;
+ vec3.setVec(x1,y1,z1);
+ vec3a.setVec(x2,y2,z2);
+ vec3b = vec3 % vec3a ;
+ val1 = y1*z2 - y2*z1;
+ val2 = z1*x2 -z2*x1;
+ val3 = x1*y2-x2*y1;
+ ensure("2:operator% failed ", (val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<17>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, div = 3.2f;
+ F32 t = 1.f / div, val1, val2, val3;
+ LLVector3 vec3(x1,y1,z1), vec3a;
+ vec3a = vec3 / div;
+ val1 = x1 * t;
+ val2 = y1 * t;
+ val3 = z1 *t;
+ ensure("1:operator/ failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY]) && (val3 == vec3a.mV[VZ]));
+
+ vec3a.clearVec();
+ x1 = -.235f, y1 = -24.32f, z1 = .342f, div = -2.2f;
+ t = 1.f / div;
+ vec3.setVec(x1,y1,z1);
+ vec3a = vec3 / div;
+ val1 = x1 * t;
+ val2 = y1 * t;
+ val3 = z1 *t;
+ ensure("2:operator/ failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY]) && (val3 == vec3a.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<18>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f;
+ LLVector3 vec3(x1,y1,z1), vec3a(x1,y1,z1);
+ ensure("1:operator== failed",(vec3 == vec3a));
+
+ vec3a.clearVec();
+ x1 = -.235f, y1 = -24.32f, z1 = .342f;
+ vec3.clearVec();
+ vec3a.clearVec();
+ vec3.setVec(x1,y1,z1);
+ vec3a.setVec(x1,y1,z1);
+ ensure("2:operator== failed ", (vec3 == vec3a));
+ }
+
+ template<> template<>
+ void v3math_object::test<19>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 =112.f, y2 = 2.234f,z2 = 11.2f;;
+ LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2);
+ ensure("1:operator!= failed",(vec3a != vec3));
+
+ vec3.clearVec();
+ vec3.clearVec();
+ vec3a.setVec(vec3);
+ ensure("2:operator!= failed", ( FALSE == (vec3a != vec3)));
+ }
+
+ template<> template<>
+ void v3math_object::test<20>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 =112.f, y2 = 2.2f,z2 = 11.2f;;
+ LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2);
+ vec3a += vec3;
+ F32 val1, val2, val3;
+ val1 = x1+x2;
+ val2 = y1+y2;
+ val3 = z1+z2;
+ ensure("1:operator+= failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<21>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 =112.f, y2 = 2.2f,z2 = 11.2f;;
+ LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2);
+ vec3a -= vec3;
+ F32 val1, val2, val3;
+ val1 = x2-x1;
+ val2 = y2-y1;
+ val3 = z2-z1;
+ ensure("1:operator-= failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<22>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f;
+ F32 val1,val2,val3;
+ LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2);
+ vec3a *= vec3;
+ val1 = x1*x2;
+ val2 = y1*y2;
+ val3 = z1*z2;
+ ensure("1:operator*= failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ]));
+
+ F32 mulVal = 4.332f;
+ vec3 *=mulVal;
+ val1 = x1*mulVal;
+ val2 = y1*mulVal;
+ val3 = z1*mulVal;
+ ensure("2:operator*= failed ", is_approx_equal(val1, vec3.mV[VX]) && is_approx_equal(val2, vec3.mV[VY]) && is_approx_equal(val3, vec3.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<23>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f;
+ LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2),vec3b;
+ vec3b = vec3a % vec3;
+ vec3a %= vec3;
+ ensure_equals("1:operator%= failed",vec3a,vec3b);
+ }
+
+ template<> template<>
+ void v3math_object::test<24>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, div = 3.2f;
+ F32 t = 1.f / div, val1, val2, val3;
+ LLVector3 vec3a(x1,y1,z1);
+ vec3a /= div;
+ val1 = x1 * t;
+ val2 = y1 * t;
+ val3 = z1 *t;
+ ensure("1:operator/= failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY]) && (val3 == vec3a.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<25>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f;
+ LLVector3 vec3(x1,y1,z1), vec3a;
+ vec3a = -vec3;
+ ensure("1:operator- failed",(-vec3a == vec3));
+ }
+
+ template<> template<>
+ void v3math_object::test<26>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f;
+ std::ostringstream stream1, stream2;
+ LLVector3 vec3(x1,y1,z1), vec3a;
+ stream1 << vec3;
+ vec3a.setVec(x1,y1,z1);
+ stream2 << vec3a;
+ ensure("1:operator << failed",(stream1.str() == stream2.str()));
+ }
+
+ template<> template<>
+ void v3math_object::test<27>()
+ {
+ F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.11f, z2 = 1234.234f;
+ LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2);
+ ensure("1:operator< failed", (TRUE == (vec3 < vec3a)));
+ x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 2.f, z2 = 1234.234f;
+ vec3.setVec(x1,y1,z1);
+ vec3a.setVec(x2,y2,z2);
+ ensure("2:operator< failed ", (TRUE == (vec3 < vec3a)));
+ x1 =2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f,
+ vec3.setVec(x1,y1,z1);
+ vec3a.setVec(x2,y2,z2);
+ ensure("3:operator< failed ", (FALSE == (vec3 < vec3a)));
+ }
+
+ template<> template<>
+ void v3math_object::test<28>()
+ {
+ F32 x1 =1.23f, y1 = 2.f,z1 = 4.f;
+ std::string buf("1.23 2. 4");
+ LLVector3 vec3, vec3a(x1,y1,z1);
+ LLVector3::parseVector3(buf, &vec3);
+ ensure_equals("1:parseVector3 failed", vec3, vec3a);
+ }
+
+ template<> template<>
+ void v3math_object::test<29>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 4.f;
+ LLVector3 vec3(x1,y1,z1),vec3a,vec3b;
+ vec3a.setVec(1,1,1);
+ vec3a.scaleVec(vec3);
+ ensure_equals("1:scaleVec failed", vec3, vec3a);
+ vec3a.clearVec();
+ vec3a.setVec(x1,y1,z1);
+ vec3a.scaleVec(vec3);
+ ensure("2:scaleVec failed", ((1.f ==vec3a.mV[VX])&& (4.f ==vec3a.mV[VY]) && (16.f ==vec3a.mV[VZ])));
+ }
+
+ template<> template<>
+ void v3math_object::test<30>()
+ {
+ F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.11f, z2 = 1234.234f;
+ F32 val = 2.3f,val1,val2,val3;
+ val1 = x1 + (x2 - x1)* val;
+ val2 = y1 + (y2 - y1)* val;
+ val3 = z1 + (z2 - z1)* val;
+ LLVector3 vec3(x1,y1,z1),vec3a(x2,y2,z2);
+ LLVector3 vec3b = lerp(vec3,vec3a,val);
+ ensure("1:lerp failed", ((val1 ==vec3b.mV[VX])&& (val2 ==vec3b.mV[VY]) && (val3 ==vec3b.mV[VZ])));
+ }
+
+ template<> template<>
+ void v3math_object::test<31>()
+ {
+ F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.f, z2 = 1.f;
+ F32 val1,val2;
+ LLVector3 vec3(x1,y1,z1),vec3a(x2,y2,z2);
+ val1 = dist_vec(vec3,vec3a);
+ val2 = fsqrtf((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2));
+ ensure_equals("1:dist_vec: Fail ",val2, val1);
+ val1 = dist_vec_squared(vec3,vec3a);
+ val2 =((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2));
+ ensure_equals("2:dist_vec_squared: Fail ",val2, val1);
+ val1 = dist_vec_squared2D(vec3, vec3a);
+ val2 =(x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2);
+ ensure_equals("3:dist_vec_squared2D: Fail ",val2, val1);
+ }
+
+ template<> template<>
+ void v3math_object::test<32>()
+ {
+ F32 x =12.3524f, y = -342.f,z = 4.126341f;
+ LLVector3 vec3(x,y,z);
+ F32 mag = vec3.normVec();
+ mag = 1.f/ mag;
+ F32 val1 = x* mag, val2 = y* mag, val3 = z* mag;
+ ensure("1:normVec: Fail ", is_approx_equal(val1, vec3.mV[VX]) && is_approx_equal(val2, vec3.mV[VY]) && is_approx_equal(val3, vec3.mV[VZ]));
+ x = 0.000000001f, y = 0.f, z = 0.f;
+ vec3.clearVec();
+ vec3.setVec(x,y,z);
+ mag = vec3.normVec();
+ val1 = x* mag, val2 = y* mag, val3 = z* mag;
+ ensure("2:normVec: Fail ", (mag == 0.) && (0. == vec3.mV[VX]) && (0. == vec3.mV[VY])&& (0. == vec3.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<33>()
+ {
+ F32 x = -202.23412f, y = 123.2312f, z = -89.f;
+ LLVector3 vec(x,y,z);
+ vec.snap(2);
+ ensure("1:snap: Fail ", is_approx_equal(-202.23f, vec.mV[VX]) && is_approx_equal(123.23f, vec.mV[VY]) && is_approx_equal(-89.f, vec.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<34>()
+ {
+ F32 x = 10.f, y = 20.f, z = -15.f;
+ F32 x1, y1, z1;
+ F32 lowerxy = 0.f, upperxy = 1.0f, lowerz = -1.0f, upperz = 1.f;
+ LLVector3 vec3(x,y,z);
+ vec3.quantize16(lowerxy,upperxy,lowerz,upperz);
+ x1 = U16_to_F32(F32_to_U16(x, lowerxy, upperxy), lowerxy, upperxy);
+ y1 = U16_to_F32(F32_to_U16(y, lowerxy, upperxy), lowerxy, upperxy);
+ z1 = U16_to_F32(F32_to_U16(z, lowerz, upperz), lowerz, upperz);
+ ensure("1:quantize16: Fail ", is_approx_equal(x1, vec3.mV[VX]) && is_approx_equal(y1, vec3.mV[VY]) && is_approx_equal(z1, vec3.mV[VZ]));
+ LLVector3 vec3a(x,y,z);
+ vec3a.quantize8(lowerxy,upperxy,lowerz,upperz);
+ x1 = U8_to_F32(F32_to_U8(x, lowerxy, upperxy), lowerxy, upperxy);
+ y1 = U8_to_F32(F32_to_U8(y, lowerxy, upperxy), lowerxy, upperxy);
+ z1 = U8_to_F32(F32_to_U8(z, lowerz, upperz), lowerz, upperz);
+ ensure("2:quantize8: Fail ", is_approx_equal(x1, vec3a.mV[VX]) && is_approx_equal(y1, vec3a.mV[VY]) && is_approx_equal(z1, vec3a.mV[VZ]));
+ }
+}
diff --git a/indra/llmath/tests/v4color_test.cpp b/indra/llmath/tests/v4color_test.cpp
new file mode 100644
index 0000000000..33921e0f0f
--- /dev/null
+++ b/indra/llmath/tests/v4color_test.cpp
@@ -0,0 +1,365 @@
+/**
+ * @file v4color_test.cpp
+ * @author Adroit
+ * @date 2007-03
+ * @brief v4color test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+
+#include "../v4coloru.h"
+#include "llsd.h"
+#include "../v3color.h"
+#include "../v4color.h"
+
+
+namespace tut
+{
+ struct v4color_data
+ {
+ };
+ typedef test_group<v4color_data> v4color_test;
+ typedef v4color_test::object v4color_object;
+ tut::v4color_test v4color_testcase("v4color");
+
+ template<> template<>
+ void v4color_object::test<1>()
+ {
+ LLColor4 llcolor4;
+ ensure("1:LLColor4:Fail to initialize ", ((0 == llcolor4.mV[VX]) && (0 == llcolor4.mV[VY]) && (0 == llcolor4.mV[VZ])&& (1.0f == llcolor4.mV[VW])));
+
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF, a = 0xAF;
+ LLColor4 llcolor4a(r,g,b);
+ ensure("2:LLColor4:Fail to initialize ", ((r == llcolor4a.mV[VX]) && (g == llcolor4a.mV[VY]) && (b == llcolor4a.mV[VZ])&& (1.0f == llcolor4a.mV[VW])));
+
+ LLColor4 llcolor4b(r,g,b,a);
+ ensure("3:LLColor4:Fail to initialize ", ((r == llcolor4b.mV[VX]) && (g == llcolor4b.mV[VY]) && (b == llcolor4b.mV[VZ])&& (a == llcolor4b.mV[VW])));
+
+ const F32 vec[4] = {.112f ,23.2f, -4.2f, -.0001f};
+ LLColor4 llcolor4c(vec);
+ ensure("4:LLColor4:Fail to initialize ", ((vec[0] == llcolor4c.mV[VX]) && (vec[1] == llcolor4c.mV[VY]) && (vec[2] == llcolor4c.mV[VZ])&& (vec[3] == llcolor4c.mV[VW])));
+
+ LLColor3 llcolor3(-2.23f,1.01f,42.3f);
+ F32 val = -.1f;
+ LLColor4 llcolor4d(llcolor3,val);
+ ensure("5:LLColor4:Fail to initialize ", ((llcolor3.mV[VX] == llcolor4d.mV[VX]) && (llcolor3.mV[VY] == llcolor4d.mV[VY]) && (llcolor3.mV[VZ] == llcolor4d.mV[VZ])&& (val == llcolor4d.mV[VW])));
+
+ LLSD sd = llcolor4d.getValue();
+ LLColor4 llcolor4e(sd);
+ ensure_equals("6:LLColor4:(LLSD) failed ", llcolor4d, llcolor4e);
+
+ U8 r1 = 0xF2, g1 = 0xFA, b1 = 0xBF;
+ LLColor4U color4u(r1,g1,b1);
+ LLColor4 llcolor4g(color4u);
+ const F32 SCALE = 1.f/255.f;
+ F32 r2 = r1*SCALE, g2 = g1* SCALE, b2 = b1* SCALE;
+ ensure("7:LLColor4:Fail to initialize ", ((r2 == llcolor4g.mV[VX]) && (g2 == llcolor4g.mV[VY]) && (b2 == llcolor4g.mV[VZ])));
+ }
+
+ template<> template<>
+ void v4color_object::test<2>()
+ {
+ LLColor4 llcolor(1.0, 2.0, 3.0, 4.0);
+ LLSD llsd = llcolor.getValue();
+ LLColor4 llcolor4(llsd), llcolor4a;
+ llcolor4a.setValue(llsd);
+ ensure("setValue: failed", (llcolor4 == llcolor4a));
+ LLSD sd = llcolor4a.getValue();
+ LLColor4 llcolor4b(sd);
+ ensure("getValue: Failed ", (llcolor4b == llcolor4a));
+ }
+
+ template<> template<>
+ void v4color_object::test<3>()
+ {
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF,a = 0xAF;
+ LLColor4 llcolor4(r,g,b,a);
+ llcolor4.setToBlack();
+ ensure("setToBlack:Fail to set the black ", ((0 == llcolor4.mV[VX]) && (0 == llcolor4.mV[VY]) && (0 == llcolor4.mV[VZ])&& (1.0f == llcolor4.mV[VW])));
+
+ llcolor4.setToWhite();
+ ensure("setToWhite:Fail to set the white ", ((1.f == llcolor4.mV[VX]) && (1.f == llcolor4.mV[VY]) && (1.f == llcolor4.mV[VZ])&& (1.0f == llcolor4.mV[VW])));
+ }
+
+ template<> template<>
+ void v4color_object::test<4>()
+ {
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF, a = 0xAF;
+ LLColor4 llcolor4;
+ llcolor4.setVec(r,g,b);
+ ensure("1:setVec:Fail to set the values ", ((r == llcolor4.mV[VX]) && (g == llcolor4.mV[VY]) && (b == llcolor4.mV[VZ])&& (1.f == llcolor4.mV[VW])));
+
+ llcolor4.setVec(r,g,b,a);
+ ensure("2:setVec:Fail to set the values ", ((r == llcolor4.mV[VX]) && (g == llcolor4.mV[VY]) && (b == llcolor4.mV[VZ])&& (a == llcolor4.mV[VW])));
+
+ LLColor4 llcolor4a;
+ llcolor4a.setVec(llcolor4);
+ ensure_equals("3:setVec:Fail to set the values ", llcolor4a,llcolor4);
+
+ LLColor3 llcolor3(-2.23f,1.01f,42.3f);
+ llcolor4a.setVec(llcolor3);
+ ensure("4:setVec:Fail to set the values ", ((llcolor3.mV[VX] == llcolor4a.mV[VX]) && (llcolor3.mV[VY] == llcolor4a.mV[VY]) && (llcolor3.mV[VZ] == llcolor4a.mV[VZ])));
+
+ F32 val = -.33f;
+ llcolor4a.setVec(llcolor3,val);
+ ensure("4:setVec:Fail to set the values ", ((llcolor3.mV[VX] == llcolor4a.mV[VX]) && (llcolor3.mV[VY] == llcolor4a.mV[VY]) && (llcolor3.mV[VZ] == llcolor4a.mV[VZ]) && (val == llcolor4a.mV[VW])));
+
+ const F32 vec[4] = {.112f ,23.2f, -4.2f, -.0001f};
+ LLColor4 llcolor4c;
+ llcolor4c.setVec(vec);
+ ensure("5:setVec:Fail to initialize ", ((vec[0] == llcolor4c.mV[VX]) && (vec[1] == llcolor4c.mV[VY]) && (vec[2] == llcolor4c.mV[VZ])&& (vec[3] == llcolor4c.mV[VW])));
+
+ U8 r1 = 0xF2, g1 = 0xFA, b1= 0xBF;
+ LLColor4U color4u(r1,g1,b1);
+ llcolor4.setVec(color4u);
+ const F32 SCALE = 1.f/255.f;
+ F32 r2 = r1*SCALE, g2 = g1* SCALE, b2 = b1* SCALE;
+ ensure("6:setVec:Fail to initialize ", ((r2 == llcolor4.mV[VX]) && (g2 == llcolor4.mV[VY]) && (b2 == llcolor4.mV[VZ])));
+ }
+
+ template<> template<>
+ void v4color_object::test<5>()
+ {
+ F32 alpha = 0xAF;
+ LLColor4 llcolor4;
+ llcolor4.setAlpha(alpha);
+ ensure("setAlpha:Fail to initialize ", (alpha == llcolor4.mV[VW]));
+ }
+
+ template<> template<>
+ void v4color_object::test<6>()
+ {
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF;
+ LLColor4 llcolor4(r,g,b);
+ ensure("magVecSquared:Fail ", is_approx_equal(llcolor4.magVecSquared(), (r*r + g*g + b*b)));
+ ensure("magVec:Fail ", is_approx_equal(llcolor4.magVec(), fsqrtf(r*r + g*g + b*b)));
+ }
+
+ template<> template<>
+ void v4color_object::test<7>()
+ {
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF;
+ LLColor4 llcolor4(r,g,b);
+ F32 vecMag = llcolor4.normVec();
+ F32 mag = fsqrtf(r*r + g*g + b*b);
+ F32 oomag = 1.f / mag;
+ F32 val1 = r * oomag, val2 = g * oomag, val3 = b * oomag;
+ ensure("1:normVec failed ", (is_approx_equal(val1, llcolor4.mV[0]) && is_approx_equal(val2, llcolor4.mV[1]) && is_approx_equal(val3, llcolor4.mV[2]) && is_approx_equal(vecMag, mag)));
+ }
+
+ template<> template<>
+ void v4color_object::test<8>()
+ {
+ LLColor4 llcolor4;
+ ensure("1:isOpaque failed ",(1 == llcolor4.isOpaque()));
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF,a = 1.f;
+ llcolor4.setVec(r,g,b,a);
+ ensure("2:isOpaque failed ",(1 == llcolor4.isOpaque()));
+ a = 2.f;
+ llcolor4.setVec(r,g,b,a);
+ ensure("3:isOpaque failed ",(0 == llcolor4.isOpaque()));
+ }
+
+ template<> template<>
+ void v4color_object::test<9>()
+ {
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF;
+ LLColor4 llcolor4(r,g,b);
+ ensure("1:operator [] failed",( r == llcolor4[0]));
+ ensure("2:operator [] failed",( g == llcolor4[1]));
+ ensure("3:operator [] failed",( b == llcolor4[2]));
+
+ r = 0xA20, g = 0xFBFF, b = 0xFFF;
+ llcolor4.setVec(r,g,b);
+ F32 &ref1 = llcolor4[0];
+ ensure("4:operator [] failed",( ref1 == llcolor4[0]));
+ F32 &ref2 = llcolor4[1];
+ ensure("5:operator [] failed",( ref2 == llcolor4[1]));
+ F32 &ref3 = llcolor4[2];
+ ensure("6:operator [] failed",( ref3 == llcolor4[2]));
+ }
+
+ template<> template<>
+ void v4color_object::test<10>()
+ {
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF;
+ LLColor3 llcolor3(r,g,b);
+ LLColor4 llcolor4a,llcolor4b;
+ llcolor4a = llcolor3;
+ ensure("Operator=:Fail to initialize ", ((llcolor3.mV[0] == llcolor4a.mV[VX]) && (llcolor3.mV[1] == llcolor4a.mV[VY]) && (llcolor3.mV[2] == llcolor4a.mV[VZ])));
+ LLSD sd = llcolor4a.getValue();
+ llcolor4b = LLColor4(sd);
+ ensure_equals("Operator= LLSD:Fail ", llcolor4a, llcolor4b);
+ }
+
+ template<> template<>
+ void v4color_object::test<11>()
+ {
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF;
+ std::ostringstream stream1, stream2;
+ LLColor4 llcolor4a(r,g,b),llcolor4b;
+ stream1 << llcolor4a;
+ llcolor4b.setVec(r,g,b);
+ stream2 << llcolor4b;
+ ensure("operator << failed ", (stream1.str() == stream2.str()));
+ }
+
+ template<> template<>
+ void v4color_object::test<12>()
+ {
+ F32 r1 = 0x20, g1 = 0xFFFF, b1 = 0xFF;
+ F32 r2 = 0xABF, g2 = 0xFB, b2 = 0xFFF;
+ LLColor4 llcolor4a(r1,g1,b1),llcolor4b(r2,g2,b2),llcolor4c;
+ llcolor4c = llcolor4b + llcolor4a;
+ ensure("operator+:Fail to Add the values ", (is_approx_equal(r1+r2,llcolor4c.mV[VX]) && is_approx_equal(g1+g2,llcolor4c.mV[VY]) && is_approx_equal(b1+b2,llcolor4c.mV[VZ])));
+
+ llcolor4b += llcolor4a;
+ ensure("operator+=:Fail to Add the values ", (is_approx_equal(r1+r2,llcolor4b.mV[VX]) && is_approx_equal(g1+g2,llcolor4b.mV[VY]) && is_approx_equal(b1+b2,llcolor4b.mV[VZ])));
+ }
+
+ template<> template<>
+ void v4color_object::test<13>()
+ {
+ F32 r1 = 0x20, g1 = 0xFFFF, b1 = 0xFF;
+ F32 r2 = 0xABF, g2 = 0xFB, b2 = 0xFFF;
+ LLColor4 llcolor4a(r1,g1,b1),llcolor4b(r2,g2,b2),llcolor4c;
+ llcolor4c = llcolor4a - llcolor4b;
+ ensure("operator-:Fail to subtract the values ", (is_approx_equal(r1-r2,llcolor4c.mV[VX]) && is_approx_equal(g1-g2,llcolor4c.mV[VY]) && is_approx_equal(b1-b2,llcolor4c.mV[VZ])));
+
+ llcolor4a -= llcolor4b;
+ ensure("operator-=:Fail to subtract the values ", (is_approx_equal(r1-r2,llcolor4a.mV[VX]) && is_approx_equal(g1-g2,llcolor4a.mV[VY]) && is_approx_equal(b1-b2,llcolor4a.mV[VZ])));
+ }
+
+ template<> template<>
+ void v4color_object::test<14>()
+ {
+ F32 r1 = 0x20, g1 = 0xFFFF, b1 = 0xFF;
+ F32 r2 = 0xABF, g2 = 0xFB, b2 = 0xFFF;
+ LLColor4 llcolor4a(r1,g1,b1),llcolor4b(r2,g2,b2),llcolor4c;
+ llcolor4c = llcolor4a * llcolor4b;
+ ensure("1:operator*:Fail to multiply the values", (is_approx_equal(r1*r2,llcolor4c.mV[VX]) && is_approx_equal(g1*g2,llcolor4c.mV[VY]) && is_approx_equal(b1*b2,llcolor4c.mV[VZ])));
+
+ F32 mulVal = 3.33f;
+ llcolor4c = llcolor4a * mulVal;
+ ensure("2:operator*:Fail ", (is_approx_equal(r1*mulVal,llcolor4c.mV[VX]) && is_approx_equal(g1*mulVal,llcolor4c.mV[VY]) && is_approx_equal(b1*mulVal,llcolor4c.mV[VZ])));
+ llcolor4c = mulVal * llcolor4a;
+ ensure("3:operator*:Fail to multiply the values", (is_approx_equal(r1*mulVal,llcolor4c.mV[VX]) && is_approx_equal(g1*mulVal,llcolor4c.mV[VY]) && is_approx_equal(b1*mulVal,llcolor4c.mV[VZ])));
+
+ llcolor4a *= mulVal;
+ ensure("4:operator*=:Fail to multiply the values ", (is_approx_equal(r1*mulVal,llcolor4a.mV[VX]) && is_approx_equal(g1*mulVal,llcolor4a.mV[VY]) && is_approx_equal(b1*mulVal,llcolor4a.mV[VZ])));
+
+ LLColor4 llcolor4d(r1,g1,b1),llcolor4e(r2,g2,b2);
+ llcolor4e *= llcolor4d;
+ ensure("5:operator*=:Fail to multiply the values ", (is_approx_equal(r1*r2,llcolor4e.mV[VX]) && is_approx_equal(g1*g2,llcolor4e.mV[VY]) && is_approx_equal(b1*b2,llcolor4e.mV[VZ])));
+ }
+
+ template<> template<>
+ void v4color_object::test<15>()
+ {
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF,a = 0x30;
+ F32 div = 12.345f;
+ LLColor4 llcolor4a(r,g,b,a),llcolor4b;
+ llcolor4b = llcolor4a % div;//chnage only alpha value nor r,g,b;
+ ensure("1operator%:Fail ", (is_approx_equal(r,llcolor4b.mV[VX]) && is_approx_equal(g,llcolor4b.mV[VY]) && is_approx_equal(b,llcolor4b.mV[VZ])&& is_approx_equal(div*a,llcolor4b.mV[VW])));
+
+ llcolor4b = div % llcolor4a;
+ ensure("2operator%:Fail ", (is_approx_equal(r,llcolor4b.mV[VX]) && is_approx_equal(g,llcolor4b.mV[VY]) && is_approx_equal(b,llcolor4b.mV[VZ])&& is_approx_equal(div*a,llcolor4b.mV[VW])));
+
+ llcolor4a %= div;
+ ensure("operator%=:Fail ", (is_approx_equal(a*div,llcolor4a.mV[VW])));
+ }
+
+ template<> template<>
+ void v4color_object::test<16>()
+ {
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF,a = 0x30;
+ LLColor4 llcolor4a(r,g,b,a),llcolor4b;
+ llcolor4b = llcolor4a;
+ ensure("1:operator== failed to ensure the equality ", (llcolor4b == llcolor4a));
+ F32 r1 = 0x2, g1 = 0xFF, b1 = 0xFA;
+ LLColor3 llcolor3(r1,g1,b1);
+ llcolor4b = llcolor3;
+ ensure("2:operator== failed to ensure the equality ", (llcolor4b == llcolor3));
+ ensure("2:operator!= failed to ensure the equality ", (llcolor4a != llcolor3));
+ }
+
+ template<> template<>
+ void v4color_object::test<17>()
+ {
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF;
+ LLColor4 llcolor4a(r,g,b),llcolor4b;
+ LLColor3 llcolor3 = vec4to3(llcolor4a);
+ ensure("vec4to3:Fail to convert vec4 to vec3 ", (is_approx_equal(llcolor3.mV[VX],llcolor4a.mV[VX]) && is_approx_equal(llcolor3.mV[VY],llcolor4a.mV[VY]) && is_approx_equal(llcolor3.mV[VZ],llcolor4a.mV[VZ])));
+ llcolor4b = vec3to4(llcolor3);
+ ensure_equals("vec3to4:Fail to convert vec3 to vec4 ", llcolor4b, llcolor4a);
+ }
+
+ template<> template<>
+ void v4color_object::test<18>()
+ {
+ F32 r1 = 0x20, g1 = 0xFFFF, b1 = 0xFF, val = 0x20;
+ F32 r2 = 0xABF, g2 = 0xFB, b2 = 0xFFF;
+ LLColor4 llcolor4a(r1,g1,b1),llcolor4b(r2,g2,b2),llcolor4c;
+ llcolor4c = lerp(llcolor4a,llcolor4b,val);
+ ensure("lerp:Fail ", (is_approx_equal(r1 + (r2 - r1)* val,llcolor4c.mV[VX]) && is_approx_equal(g1 + (g2 - g1)* val,llcolor4c.mV[VY]) && is_approx_equal(b1 + (b2 - b1)* val,llcolor4c.mV[VZ])));
+ }
+
+ template<> template<>
+ void v4color_object::test<19>()
+ {
+ F32 r = 12.0f, g = -2.3f, b = 1.32f, a = 5.0f;
+ LLColor4 llcolor4a(r,g,b,a),llcolor4b;
+ std::string color("red");
+ LLColor4::parseColor(color, &llcolor4b);
+ ensure_equals("1:parseColor() failed to parse the color value ", llcolor4b, LLColor4::red);
+
+ color = "12.0, -2.3, 1.32, 5.0";
+ LLColor4::parseColor(color, &llcolor4b);
+ llcolor4a = llcolor4a * (1.f / 255.f);
+ ensure_equals("2:parseColor() failed to parse the color value ", llcolor4a,llcolor4b);
+
+ color = "yellow5";
+ llcolor4a.setVec(r,g,b);
+ LLColor4::parseColor(color, &llcolor4a);
+ ensure_equals("3:parseColor() failed to parse the color value ", llcolor4a, LLColor4::yellow5);
+ }
+
+ template<> template<>
+ void v4color_object::test<20>()
+ {
+ F32 r = 12.0f, g = -2.3f, b = 1.32f, a = 5.0f;
+ LLColor4 llcolor4a(r,g,b,a),llcolor4b;
+ std::string color("12.0, -2.3, 1.32, 5.0");
+ LLColor4::parseColor4(color, &llcolor4b);
+ ensure_equals("parseColor4() failed to parse the color value ", llcolor4a, llcolor4b);
+ }
+}
diff --git a/indra/llmath/tests/v4coloru_test.cpp b/indra/llmath/tests/v4coloru_test.cpp
new file mode 100644
index 0000000000..9f71cfc8cc
--- /dev/null
+++ b/indra/llmath/tests/v4coloru_test.cpp
@@ -0,0 +1,342 @@
+/**
+ * @file v4coloru_test.cpp
+ * @author Adroit
+ * @date 2007-03
+ * @brief v4coloru test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+
+#include "llsd.h"
+
+#include "../v4coloru.h"
+
+
+namespace tut
+{
+ struct v4coloru_data
+ {
+ };
+ typedef test_group<v4coloru_data> v4coloru_test;
+ typedef v4coloru_test::object v4coloru_object;
+ tut::v4coloru_test v4coloru_testcase("v4coloru");
+
+ template<> template<>
+ void v4coloru_object::test<1>()
+ {
+ LLColor4U llcolor4u;
+ ensure("1:LLColor4u:Fail to initialize ", ((0 == llcolor4u.mV[VX]) && (0 == llcolor4u.mV[VY]) && (0 == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW])));
+
+ U8 r = 0x12, g = 0xFF, b = 0xAF, a = 0x23;
+ LLColor4U llcolor4u1(r,g,b);
+ ensure("2:LLColor4u:Fail to initialize ", ((r == llcolor4u1.mV[VX]) && (g == llcolor4u1.mV[VY]) && (b == llcolor4u1.mV[VZ])&& (255 == llcolor4u1.mV[VW])));
+
+ LLColor4U llcolor4u2(r,g,b,a);
+ ensure("3:LLColor4u:Fail to initialize ", ((r == llcolor4u2.mV[VX]) && (g == llcolor4u2.mV[VY]) && (b == llcolor4u2.mV[VZ])&& (a == llcolor4u2.mV[VW])));
+
+ const U8 vec[4] = {0x12,0xFF,0xAF,0x23};
+ LLColor4U llcolor4u3(vec);
+ ensure("4:LLColor4u:Fail to initialize ", ((vec[0] == llcolor4u3.mV[VX]) && (vec[1] == llcolor4u3.mV[VY]) && (vec[2] == llcolor4u3.mV[VZ])&& (vec[3] == llcolor4u3.mV[VW])));
+
+ LLSD sd = llcolor4u3.getValue();
+ LLColor4U llcolor4u4(sd);
+ ensure_equals("5:LLColor4u (LLSD) Failed ", llcolor4u4, llcolor4u3);
+ }
+
+ template<> template<>
+ void v4coloru_object::test<2>()
+ {
+ LLColor4U llcolor4ua(1, 2, 3, 4);
+ LLSD sd = llcolor4ua.getValue();
+ LLColor4U llcolor4u;
+ llcolor4u.setValue(sd);
+ ensure_equals("setValue(LLSD)/getValue Failed ", llcolor4u, llcolor4ua);
+ }
+
+ template<> template<>
+ void v4coloru_object::test<3>()
+ {
+ U8 r = 0x12, g = 0xFF, b = 0xAF, a = 0x23;
+ LLColor4U llcolor4u(r,g,b,a);
+ llcolor4u.setToBlack();
+ ensure("setToBlack:Fail to set black ", ((0 == llcolor4u.mV[VX]) && (0 == llcolor4u.mV[VY]) && (0 == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW])));
+
+ llcolor4u.setToWhite();
+ ensure("setToWhite:Fail to white ", ((255 == llcolor4u.mV[VX]) && (255 == llcolor4u.mV[VY]) && (255 == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW])));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<4>()
+ {
+ U8 r = 0x12, g = 0xFF, b = 0xAF, a = 0x23;
+ LLColor4U llcolor4ua(r,g,b,a);
+ LLSD sd = llcolor4ua.getValue();
+ LLColor4U llcolor4u = (LLColor4U)sd;
+ ensure_equals("Operator=(LLSD) Failed ", llcolor4u, llcolor4ua);
+ }
+
+ template<> template<>
+ void v4coloru_object::test<5>()
+ {
+ U8 r = 0x12, g = 0xFF, b = 0xAF, a = 0x23;
+ LLColor4U llcolor4u;
+ llcolor4u.setVec(r,g,b,a);
+ ensure("1:setVec:Fail to set the values ", ((r == llcolor4u.mV[VX]) && (g == llcolor4u.mV[VY]) && (b == llcolor4u.mV[VZ])&& (a == llcolor4u.mV[VW])));
+
+ llcolor4u.setToBlack();
+ llcolor4u.setVec(r,g,b);
+ ensure("2:setVec:Fail to set the values ", ((r == llcolor4u.mV[VX]) && (g == llcolor4u.mV[VY]) && (b == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW])));
+
+ LLColor4U llcolor4u1;
+ llcolor4u1.setVec(llcolor4u);
+ ensure_equals("3:setVec:Fail to set the values ", llcolor4u1,llcolor4u);
+
+ const U8 vec[4] = {0x12,0xFF,0xAF,0x23};
+ LLColor4U llcolor4u2;
+ llcolor4u2.setVec(vec);
+ ensure("4:setVec:Fail to set the values ", ((vec[0] == llcolor4u2.mV[VX]) && (vec[1] == llcolor4u2.mV[VY]) && (vec[2] == llcolor4u2.mV[VZ])&& (vec[3] == llcolor4u2.mV[VW])));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<6>()
+ {
+ U8 alpha = 0x12;
+ LLColor4U llcolor4u;
+ llcolor4u.setAlpha(alpha);
+ ensure("setAlpha:Fail to set alpha value ", (alpha == llcolor4u.mV[VW]));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<7>()
+ {
+ U8 r = 0x12, g = 0xFF, b = 0xAF;
+ LLColor4U llcolor4u(r,g,b);
+ ensure("magVecSquared:Fail ", is_approx_equal(llcolor4u.magVecSquared(), (F32)(r*r + g*g + b*b)));
+ ensure("magVec:Fail ", is_approx_equal(llcolor4u.magVec(), fsqrtf(r*r + g*g + b*b)));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<8>()
+ {
+ U8 r = 0x12, g = 0xFF, b = 0xAF;
+ std::ostringstream stream1, stream2;
+ LLColor4U llcolor4u1(r,g,b),llcolor4u2;
+ stream1 << llcolor4u1;
+ llcolor4u2.setVec(r,g,b);
+ stream2 << llcolor4u2;
+ ensure("operator << failed ", (stream1.str() == stream2.str()));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<9>()
+ {
+ U8 r1 = 0x12, g1 = 0xFF, b1 = 0xAF;
+ U8 r2 = 0x1C, g2 = 0x9A, b2 = 0x1B;
+ LLColor4U llcolor4u1(r1,g1,b1), llcolor4u2(r2,g2,b2),llcolor4u3;
+ llcolor4u3 = llcolor4u1 + llcolor4u2;
+ ensure_equals(
+ "1a.operator+:Fail to Add the values ",
+ llcolor4u3.mV[VX],
+ (U8)(r1+r2));
+ ensure_equals(
+ "1b.operator+:Fail to Add the values ",
+ llcolor4u3.mV[VY],
+ (U8)(g1+g2));
+ ensure_equals(
+ "1c.operator+:Fail to Add the values ",
+ llcolor4u3.mV[VZ],
+ (U8)(b1+b2));
+
+ llcolor4u2 += llcolor4u1;
+ ensure_equals(
+ "2a.operator+=:Fail to Add the values ",
+ llcolor4u2.mV[VX],
+ (U8)(r1+r2));
+ ensure_equals(
+ "2b.operator+=:Fail to Add the values ",
+ llcolor4u2.mV[VY],
+ (U8)(g1+g2));
+ ensure_equals(
+ "2c.operator+=:Fail to Add the values ",
+ llcolor4u2.mV[VZ],
+ (U8)(b1+b2));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<10>()
+ {
+ U8 r1 = 0x12, g1 = 0xFF, b1 = 0xAF;
+ U8 r2 = 0x1C, g2 = 0x9A, b2 = 0x1B;
+ LLColor4U llcolor4u1(r1,g1,b1), llcolor4u2(r2,g2,b2),llcolor4u3;
+ llcolor4u3 = llcolor4u1 - llcolor4u2;
+ ensure_equals(
+ "1a. operator-:Fail to Add the values ",
+ llcolor4u3.mV[VX],
+ (U8)(r1-r2));
+ ensure_equals(
+ "1b. operator-:Fail to Add the values ",
+ llcolor4u3.mV[VY],
+ (U8)(g1-g2));
+ ensure_equals(
+ "1c. operator-:Fail to Add the values ",
+ llcolor4u3.mV[VZ],
+ (U8)(b1-b2));
+
+ llcolor4u1 -= llcolor4u2;
+ ensure_equals(
+ "2a. operator-=:Fail to Add the values ",
+ llcolor4u1.mV[VX],
+ (U8)(r1-r2));
+ ensure_equals(
+ "2b. operator-=:Fail to Add the values ",
+ llcolor4u1.mV[VY],
+ (U8)(g1-g2));
+ ensure_equals(
+ "2c. operator-=:Fail to Add the values ",
+ llcolor4u1.mV[VZ],
+ (U8)(b1-b2));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<11>()
+ {
+ U8 r1 = 0x12, g1 = 0xFF, b1 = 0xAF;
+ U8 r2 = 0x1C, g2 = 0x9A, b2 = 0x1B;
+ LLColor4U llcolor4u1(r1,g1,b1), llcolor4u2(r2,g2,b2),llcolor4u3;
+ llcolor4u3 = llcolor4u1 * llcolor4u2;
+ ensure_equals(
+ "1a. operator*:Fail to multiply the values",
+ llcolor4u3.mV[VX],
+ (U8)(r1*r2));
+ ensure_equals(
+ "1b. operator*:Fail to multiply the values",
+ llcolor4u3.mV[VY],
+ (U8)(g1*g2));
+ ensure_equals(
+ "1c. operator*:Fail to multiply the values",
+ llcolor4u3.mV[VZ],
+ (U8)(b1*b2));
+
+ U8 mulVal = 123;
+ llcolor4u1 *= mulVal;
+ ensure_equals(
+ "2a. operator*=:Fail to multiply the values",
+ llcolor4u1.mV[VX],
+ (U8)(r1*mulVal));
+ ensure_equals(
+ "2b. operator*=:Fail to multiply the values",
+ llcolor4u1.mV[VY],
+ (U8)(g1*mulVal));
+ ensure_equals(
+ "2c. operator*=:Fail to multiply the values",
+ llcolor4u1.mV[VZ],
+ (U8)(b1*mulVal));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<12>()
+ {
+ U8 r = 0x12, g = 0xFF, b = 0xAF;
+ LLColor4U llcolor4u(r,g,b),llcolor4u1;
+ llcolor4u1 = llcolor4u;
+ ensure("operator== failed to ensure the equality ", (llcolor4u1 == llcolor4u));
+ llcolor4u1.setToBlack();
+ ensure("operator!= failed to ensure the equality ", (llcolor4u1 != llcolor4u));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<13>()
+ {
+ U8 r = 0x12, g = 0xFF, b = 0xAF, a = 12;
+ LLColor4U llcolor4u(r,g,b,a);
+ U8 modVal = 45;
+ llcolor4u %= modVal;
+ ensure_equals("operator%=:Fail ", llcolor4u.mV[VW], (U8)(a * modVal));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<14>()
+ {
+ U8 r = 0x12, g = 0xFF, b = 0xAF, a = 12;
+ LLColor4U llcolor4u1(r,g,b,a);
+ std::string color("12, 23, 132, 50");
+ LLColor4U::parseColor4U(color, &llcolor4u1);
+ ensure("parseColor4U() failed to parse the color value ", ((12 == llcolor4u1.mV[VX]) && (23 == llcolor4u1.mV[VY]) && (132 == llcolor4u1.mV[VZ])&& (50 == llcolor4u1.mV[VW])));
+
+ color = "12, 23, 132";
+ ensure("2:parseColor4U() failed to parse the color value ", (FALSE == LLColor4U::parseColor4U(color, &llcolor4u1)));
+
+ color = "12";
+ ensure("2:parseColor4U() failed to parse the color value ", (FALSE == LLColor4U::parseColor4U(color, &llcolor4u1)));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<15>()
+ {
+ U8 r = 12, g = 123, b = 3, a = 2;
+ LLColor4U llcolor4u(r,g,b,a),llcolor4u1;
+ const F32 fVal = 3.f;
+ llcolor4u1 = llcolor4u.multAll(fVal);
+ ensure("multAll:Fail to multiply ", (((U8)llround(r * fVal) == llcolor4u1.mV[VX]) && (U8)llround(g * fVal) == llcolor4u1.mV[VY]
+ && ((U8)llround(b * fVal) == llcolor4u1.mV[VZ])&& ((U8)llround(a * fVal) == llcolor4u1.mV[VW])));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<16>()
+ {
+ U8 r1 = 12, g1 = 123, b1 = 3, a1 = 2;
+ U8 r2 = 23, g2 = 230, b2 = 124, a2 = 255;
+ LLColor4U llcolor4u(r1,g1,b1,a1),llcolor4u1(r2,g2,b2,a2);
+ llcolor4u1 = llcolor4u1.addClampMax(llcolor4u);
+ ensure("1:addClampMax():Fail to add the value ", ((r1+r2 == llcolor4u1.mV[VX]) && (255 == llcolor4u1.mV[VY]) && (b1+b2 == llcolor4u1.mV[VZ])&& (255 == llcolor4u1.mV[VW])));
+
+ r1 = 132, g1 = 3, b1 = 3, a1 = 2;
+ r2 = 123, g2 = 230, b2 = 154, a2 = 25;
+ LLColor4U llcolor4u2(r1,g1,b1,a1),llcolor4u3(r2,g2,b2,a2);
+ llcolor4u3 = llcolor4u3.addClampMax(llcolor4u2);
+ ensure("2:addClampMax():Fail to add the value ", ((255 == llcolor4u3.mV[VX]) && (g1+g2 == llcolor4u3.mV[VY]) && (b1+b2 == llcolor4u3.mV[VZ])&& (a1+a2 == llcolor4u3.mV[VW])));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<17>()
+ {
+ F32 r = 23.f, g = 12.32f, b = -12.3f;
+ LLColor3 color3(r,g,b);
+ LLColor4U llcolor4u;
+ llcolor4u.setVecScaleClamp(color3);
+ const S32 MAX_COLOR = 255;
+ F32 color_scale_factor = MAX_COLOR/r;
+ S32 r2 = llround(r * color_scale_factor);
+ S32 g2 = llround(g * color_scale_factor);
+ ensure("setVecScaleClamp():Fail to add the value ", ((r2 == llcolor4u.mV[VX]) && (g2 == llcolor4u.mV[VY]) && (0 == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW])));
+ }
+}
diff --git a/indra/llmath/tests/v4math_test.cpp b/indra/llmath/tests/v4math_test.cpp
new file mode 100644
index 0000000000..fe051c27e9
--- /dev/null
+++ b/indra/llmath/tests/v4math_test.cpp
@@ -0,0 +1,388 @@
+/**
+ * @file v4math_test.cpp
+ * @author Adroit
+ * @date 2007-03
+ * @brief v4math test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+#include "llsd.h"
+
+#include "../llquaternion.h"
+#include "../m4math.h"
+#include "../v4math.h"
+
+namespace tut
+{
+ struct v4math_data
+ {
+ };
+ typedef test_group<v4math_data> v4math_test;
+ typedef v4math_test::object v4math_object;
+ tut::v4math_test v4math_testcase("v4math");
+
+ template<> template<>
+ void v4math_object::test<1>()
+ {
+ LLVector4 vec4;
+ ensure("1:LLVector4:Fail to initialize " ,((0 == vec4.mV[VX]) && (0 == vec4.mV[VY]) && (0 == vec4.mV[VZ])&& (1.0f == vec4.mV[VW])));
+ F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
+ LLVector4 vec4a(x,y,z);
+ ensure("2:LLVector4:Fail to initialize " ,((x == vec4a.mV[VX]) && (y == vec4a.mV[VY]) && (z == vec4a.mV[VZ])&& (1.0f == vec4a.mV[VW])));
+ LLVector4 vec4b(x,y,z,w);
+ ensure("3:LLVector4:Fail to initialize " ,((x == vec4b.mV[VX]) && (y == vec4b.mV[VY]) && (z == vec4b.mV[VZ])&& (w == vec4b.mV[VW])));
+ const F32 vec[4] = {.112f ,23.2f, -4.2f, -.0001f};
+ LLVector4 vec4c(vec);
+ ensure("4:LLVector4:Fail to initialize " ,((vec[0] == vec4c.mV[VX]) && (vec[1] == vec4c.mV[VY]) && (vec[2] == vec4c.mV[VZ])&& (vec[3] == vec4c.mV[VW])));
+ LLVector3 vec3(-2.23f,1.01f,42.3f);
+ LLVector4 vec4d(vec3);
+ ensure("5:LLVector4:Fail to initialize " ,((vec3.mV[VX] == vec4d.mV[VX]) && (vec3.mV[VY] == vec4d.mV[VY]) && (vec3.mV[VZ] == vec4d.mV[VZ])&& (1.f == vec4d.mV[VW])));
+ F32 w1 = -.234f;
+ LLVector4 vec4e(vec3,w1);
+ ensure("6:LLVector4:Fail to initialize " ,((vec3.mV[VX] == vec4e.mV[VX]) && (vec3.mV[VY] == vec4e.mV[VY]) && (vec3.mV[VZ] == vec4e.mV[VZ])&& (w1 == vec4e.mV[VW])));
+ }
+
+ template<> template<>
+ void v4math_object::test<2>()
+ {
+ F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
+ LLVector4 vec4;
+ vec4.setVec(x,y,z);
+ ensure("1:setVec:Fail to initialize " ,((x == vec4.mV[VX]) && (y == vec4.mV[VY]) && (z == vec4.mV[VZ])&& (1.0f == vec4.mV[VW])));
+ vec4.clearVec();
+ ensure("2:clearVec:Fail " ,((0 == vec4.mV[VX]) && (0 == vec4.mV[VY]) && (0 == vec4.mV[VZ])&& (1.0f == vec4.mV[VW])));
+ vec4.setVec(x,y,z,w);
+ ensure("3:setVec:Fail to initialize " ,((x == vec4.mV[VX]) && (y == vec4.mV[VY]) && (z == vec4.mV[VZ])&& (w == vec4.mV[VW])));
+ vec4.zeroVec();
+ ensure("4:zeroVec:Fail " ,((0 == vec4.mV[VX]) && (0 == vec4.mV[VY]) && (0 == vec4.mV[VZ])&& (0 == vec4.mV[VW])));
+ LLVector3 vec3(-2.23f,1.01f,42.3f);
+ vec4.clearVec();
+ vec4.setVec(vec3);
+ ensure("5:setVec:Fail to initialize " ,((vec3.mV[VX] == vec4.mV[VX]) && (vec3.mV[VY] == vec4.mV[VY]) && (vec3.mV[VZ] == vec4.mV[VZ])&& (1.f == vec4.mV[VW])));
+ F32 w1 = -.234f;
+ vec4.zeroVec();
+ vec4.setVec(vec3,w1);
+ ensure("6:setVec:Fail to initialize " ,((vec3.mV[VX] == vec4.mV[VX]) && (vec3.mV[VY] == vec4.mV[VY]) && (vec3.mV[VZ] == vec4.mV[VZ])&& (w1 == vec4.mV[VW])));
+ const F32 vec[4] = {.112f ,23.2f, -4.2f, -.0001f};
+ LLVector4 vec4a;
+ vec4a.setVec(vec);
+ ensure("7:setVec:Fail to initialize " ,((vec[0] == vec4a.mV[VX]) && (vec[1] == vec4a.mV[VY]) && (vec[2] == vec4a.mV[VZ])&& (vec[3] == vec4a.mV[VW])));
+ }
+
+ template<> template<>
+ void v4math_object::test<3>()
+ {
+ F32 x = 10.f, y = -2.3f, z = -.023f;
+ LLVector4 vec4(x,y,z);
+ ensure("magVec:Fail ", is_approx_equal(vec4.magVec(), fsqrtf(x*x + y*y + z*z)));
+ ensure("magVecSquared:Fail ", is_approx_equal(vec4.magVecSquared(), (x*x + y*y + z*z)));
+ }
+
+ template<> template<>
+ void v4math_object::test<4>()
+ {
+ F32 x = 10.f, y = -2.3f, z = -.023f;
+ LLVector4 vec4(x,y,z);
+ F32 mag = vec4.normVec();
+ mag = 1.f/ mag;
+ ensure("1:normVec: Fail " ,is_approx_equal(mag*x,vec4.mV[VX]) && is_approx_equal(mag*y, vec4.mV[VY])&& is_approx_equal(mag*z, vec4.mV[VZ]));
+ x = 0.000000001f, y = 0.000000001f, z = 0.000000001f;
+ vec4.clearVec();
+ vec4.setVec(x,y,z);
+ mag = vec4.normVec();
+ ensure("2:normVec: Fail " ,is_approx_equal(mag*x,vec4.mV[VX]) && is_approx_equal(mag*y, vec4.mV[VY])&& is_approx_equal(mag*z, vec4.mV[VZ]));
+ }
+
+ template<> template<>
+ void v4math_object::test<5>()
+ {
+ F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
+ LLVector4 vec4(x,y,z,w);
+ vec4.abs();
+ ensure("abs:Fail " ,((x == vec4.mV[VX]) && (-y == vec4.mV[VY]) && (-z == vec4.mV[VZ])&& (-w == vec4.mV[VW])));
+ vec4.clearVec();
+ ensure("isExactlyClear:Fail " ,(TRUE == vec4.isExactlyClear()));
+ vec4.zeroVec();
+ ensure("isExactlyZero:Fail " ,(TRUE == vec4.isExactlyZero()));
+ }
+
+ template<> template<>
+ void v4math_object::test<6>()
+ {
+ F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
+ LLVector4 vec4(x,y,z,w),vec4a;
+ vec4a = vec4.scaleVec(vec4);
+ ensure("scaleVec:Fail " ,(is_approx_equal(x*x, vec4a.mV[VX]) && is_approx_equal(y*y, vec4a.mV[VY]) && is_approx_equal(z*z, vec4a.mV[VZ])&& is_approx_equal(w*w, vec4a.mV[VW])));
+ }
+
+ template<> template<>
+ void v4math_object::test<7>()
+ {
+ F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
+ LLVector4 vec4(x,y,z,w);
+ ensure("1:operator [] failed " ,( x == vec4[0]));
+ ensure("2:operator [] failed " ,( y == vec4[1]));
+ ensure("3:operator [] failed " ,( z == vec4[2]));
+ ensure("4:operator [] failed " ,( w == vec4[3]));
+ x = 23.f, y = -.2361f, z = 3.25;
+ vec4.setVec(x,y,z);
+ F32 &ref1 = vec4[0];
+ ensure("5:operator [] failed " ,( ref1 == vec4[0]));
+ F32 &ref2 = vec4[1];
+ ensure("6:operator [] failed " ,( ref2 == vec4[1]));
+ F32 &ref3 = vec4[2];
+ ensure("7:operator [] failed " ,( ref3 == vec4[2]));
+ F32 &ref4 = vec4[3];
+ ensure("8:operator [] failed " ,( ref4 == vec4[3]));
+ }
+
+ template<> template<>
+ void v4math_object::test<8>()
+ {
+ F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
+ const F32 val[16] = {
+ 1.f, 2.f, 3.f, 0.f,
+ .34f, .1f, -.5f, 0.f,
+ 2.f, 1.23f, 1.234f, 0.f,
+ .89f, 0.f, 0.f, 0.f
+ };
+ LLMatrix4 mat(val);
+ LLVector4 vec4(x,y,z,w),vec4a;
+ vec4.rotVec(mat);
+ vec4a.setVec(x,y,z,w);
+ vec4a.rotVec(mat);
+ ensure_equals("1:rotVec: Fail " ,vec4a, vec4);
+ F32 a = 2.32f, b = -23.2f, c = -34.1112f, d = 1.010112f;
+ LLQuaternion q(a,b,c,d);
+ LLVector4 vec4b(a,b,c,d),vec4c;
+ vec4b.rotVec(q);
+ vec4c.setVec(a, b, c, d);
+ vec4c.rotVec(q);
+ ensure_equals("2:rotVec: Fail " ,vec4b, vec4c);
+ }
+
+ template<> template<>
+ void v4math_object::test<9>()
+ {
+ F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
+ LLVector4 vec4(x,y,z,w),vec4a;;
+ std::ostringstream stream1, stream2;
+ stream1 << vec4;
+ vec4a.setVec(x,y,z,w);
+ stream2 << vec4a;
+ ensure("operator << failed",(stream1.str() == stream2.str()));
+ }
+
+ template<> template<>
+ void v4math_object::test<10>()
+ {
+ F32 x1 = 1.f, y1 = 2.f, z1 = -1.1f, w1 = .23f;
+ F32 x2 = 1.2f, y2 = 2.5f, z2 = 1.f, w2 = 1.3f;
+ LLVector4 vec4(x1,y1,z1,w1),vec4a(x2,y2,z2,w2),vec4b;
+ vec4b = vec4a + vec4;
+ ensure("1:operator+:Fail to initialize " ,(is_approx_equal(x1+x2,vec4b.mV[VX]) && is_approx_equal(y1+y2,vec4b.mV[VY]) && is_approx_equal(z1+z2,vec4b.mV[VZ])));
+ x1 = -2.45f, y1 = 2.1f, z1 = 3.0f;
+ vec4.clearVec();
+ vec4a.clearVec();
+ vec4.setVec(x1,y1,z1);
+ vec4a +=vec4;
+ ensure_equals("2:operator+=: Fail to initialize", vec4a,vec4);
+ vec4a += vec4;
+ ensure("3:operator+=:Fail to initialize " ,(is_approx_equal(2*x1,vec4a.mV[VX]) && is_approx_equal(2*y1,vec4a.mV[VY]) && is_approx_equal(2*z1,vec4a.mV[VZ])));
+ }
+ template<> template<>
+ void v4math_object::test<11>()
+ {
+ F32 x1 = 1.f, y1 = 2.f, z1 = -1.1f, w1 = .23f;
+ F32 x2 = 1.2f, y2 = 2.5f, z2 = 1.f, w2 = 1.3f;
+ LLVector4 vec4(x1,y1,z1,w1),vec4a(x2,y2,z2,w2),vec4b;
+ vec4b = vec4a - vec4;
+ ensure("1:operator-:Fail to initialize " ,(is_approx_equal(x2-x1,vec4b.mV[VX]) && is_approx_equal(y2-y1,vec4b.mV[VY]) && is_approx_equal(z2-z1,vec4b.mV[VZ])));
+ x1 = -2.45f, y1 = 2.1f, z1 = 3.0f;
+ vec4.clearVec();
+ vec4a.clearVec();
+ vec4.setVec(x1,y1,z1);
+ vec4a -=vec4;
+ ensure_equals("2:operator-=: Fail to initialize" , vec4a,-vec4);
+ vec4a -=vec4;
+ ensure("3:operator-=:Fail to initialize " ,(is_approx_equal(-2*x1,vec4a.mV[VX]) && is_approx_equal(-2*y1,vec4a.mV[VY]) && is_approx_equal(-2*z1,vec4a.mV[VZ])));
+ }
+
+ template<> template<>
+ void v4math_object::test<12>()
+ {
+ F32 x1 = 1.f, y1 = 2.f, z1 = -1.1f;
+ F32 x2 = 1.2f, y2 = 2.5f, z2 = 1.f;
+ LLVector4 vec4(x1,y1,z1),vec4a(x2,y2,z2);
+ F32 res = vec4 * vec4a;
+ ensure("1:operator* failed " ,is_approx_equal(res, x1*x2 + y1*y2 + z1*z2));
+ vec4a.clearVec();
+ F32 mulVal = 4.2f;
+ vec4a = vec4 * mulVal;
+ ensure("2:operator* failed " ,is_approx_equal(x1*mulVal,vec4a.mV[VX]) && is_approx_equal(y1*mulVal, vec4a.mV[VY])&& is_approx_equal(z1*mulVal, vec4a.mV[VZ]));
+ vec4a.clearVec();
+ vec4a = mulVal * vec4 ;
+ ensure("3:operator* failed " ,is_approx_equal(x1*mulVal, vec4a.mV[VX]) && is_approx_equal(y1*mulVal, vec4a.mV[VY])&& is_approx_equal(z1*mulVal, vec4a.mV[VZ]));
+ vec4 *= mulVal;
+ ensure("4:operator*= failed " ,is_approx_equal(x1*mulVal, vec4.mV[VX]) && is_approx_equal(y1*mulVal, vec4.mV[VY])&& is_approx_equal(z1*mulVal, vec4.mV[VZ]));
+ }
+
+ template<> template<>
+ void v4math_object::test<13>()
+ {
+ F32 x1 = 1.f, y1 = 2.f, z1 = -1.1f;
+ F32 x2 = 1.2f, y2 = 2.5f, z2 = 1.f;
+ LLVector4 vec4(x1,y1,z1),vec4a(x2,y2,z2),vec4b;
+ vec4b = vec4 % vec4a;
+ ensure("1:operator% failed " ,is_approx_equal(y1*z2 - y2*z1, vec4b.mV[VX]) && is_approx_equal(z1*x2 -z2*x1, vec4b.mV[VY]) && is_approx_equal(x1*y2-x2*y1, vec4b.mV[VZ]));
+ vec4 %= vec4a;
+ ensure_equals("operator%= failed " ,vec4,vec4b);
+ }
+
+ template<> template<>
+ void v4math_object::test<14>()
+ {
+ F32 x = 1.f, y = 2.f, z = -1.1f,div = 4.2f;
+ F32 t = 1.f / div;
+ LLVector4 vec4(x,y,z), vec4a;
+ vec4a = vec4/div;
+ ensure("1:operator/ failed " ,is_approx_equal(x*t, vec4a.mV[VX]) && is_approx_equal(y*t, vec4a.mV[VY])&& is_approx_equal(z*t, vec4a.mV[VZ]));
+ x = 1.23f, y = 4.f, z = -2.32f;
+ vec4.clearVec();
+ vec4a.clearVec();
+ vec4.setVec(x,y,z);
+ vec4a = vec4/div;
+ ensure("2:operator/ failed " ,is_approx_equal(x*t, vec4a.mV[VX]) && is_approx_equal(y*t, vec4a.mV[VY])&& is_approx_equal(z*t, vec4a.mV[VZ]));
+ vec4 /= div;
+ ensure("3:operator/ failed " ,is_approx_equal(x*t, vec4.mV[VX]) && is_approx_equal(y*t, vec4.mV[VY])&& is_approx_equal(z*t, vec4.mV[VZ]));
+ }
+
+ template<> template<>
+ void v4math_object::test<15>()
+ {
+ F32 x = 1.f, y = 2.f, z = -1.1f;
+ LLVector4 vec4(x,y,z), vec4a;
+ ensure("operator!= failed " ,(vec4 != vec4a));
+ vec4a = vec4;
+ ensure("operator== failed " ,(vec4 ==vec4a));
+ }
+
+ template<> template<>
+ void v4math_object::test<16>()
+ {
+ F32 x = 1.f, y = 2.f, z = -1.1f;
+ LLVector4 vec4(x,y,z), vec4a;
+ vec4a = - vec4;
+ ensure("operator- failed " , (vec4 == - vec4a));
+ }
+
+ template<> template<>
+ void v4math_object::test<17>()
+ {
+ F32 x = 1.f, y = 2.f, z = -1.1f,epsilon = .23425f;
+ LLVector4 vec4(x,y,z), vec4a(x,y,z);
+ ensure("1:are_parallel: Fail " ,(TRUE == are_parallel(vec4a,vec4,epsilon)));
+ x = 21.f, y = 12.f, z = -123.1f;
+ vec4a.clearVec();
+ vec4a.setVec(x,y,z);
+ ensure("2:are_parallel: Fail " ,(FALSE == are_parallel(vec4a,vec4,epsilon)));
+ }
+
+ template<> template<>
+ void v4math_object::test<18>()
+ {
+ F32 x = 1.f, y = 2.f, z = -1.1f;
+ F32 angle1, angle2;
+ LLVector4 vec4(x,y,z), vec4a(x,y,z);
+ angle1 = angle_between(vec4, vec4a);
+ vec4.normVec();
+ vec4a.normVec();
+ angle2 = acos(vec4 * vec4a);
+ ensure_approximately_equals("1:angle_between: Fail " ,angle1,angle2,8);
+ F32 x1 = 21.f, y1 = 2.23f, z1 = -1.1f;
+ LLVector4 vec4b(x,y,z), vec4c(x1,y1,z1);
+ angle1 = angle_between(vec4b, vec4c);
+ vec4b.normVec();
+ vec4c.normVec();
+ angle2 = acos(vec4b * vec4c);
+ ensure_approximately_equals("2:angle_between: Fail " ,angle1,angle2,8);
+ }
+
+ template<> template<>
+ void v4math_object::test<19>()
+ {
+ F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.f, z2 = 1.f;
+ F32 val1,val2;
+ LLVector4 vec4(x1,y1,z1),vec4a(x2,y2,z2);
+ val1 = dist_vec(vec4,vec4a);
+ val2 = fsqrtf((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2));
+ ensure_equals("dist_vec: Fail ",val2, val1);
+ val1 = dist_vec_squared(vec4,vec4a);
+ val2 =((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2));
+ ensure_equals("dist_vec_squared: Fail ",val2, val1);
+ }
+
+ template<> template<>
+ void v4math_object::test<20>()
+ {
+ F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, w1 = -.23f, x2 = 1.3f, y2 = 1.f, z2 = 1.f,w2 = .12f;
+ F32 val = 2.3f,val1,val2,val3,val4;
+ LLVector4 vec4(x1,y1,z1,w1),vec4a(x2,y2,z2,w2);
+ val1 = x1 + (x2 - x1)* val;
+ val2 = y1 + (y2 - y1)* val;
+ val3 = z1 + (z2 - z1)* val;
+ val4 = w1 + (w2 - w1)* val;
+ LLVector4 vec4b = lerp(vec4,vec4a,val);
+ ensure("lerp failed", ((val1 ==vec4b.mV[VX])&& (val2 ==vec4b.mV[VY]) && (val3 ==vec4b.mV[VZ])&& (val4 ==vec4b.mV[VW])));
+ }
+
+ template<> template<>
+ void v4math_object::test<21>()
+ {
+ F32 x = 1.f, y = 2.f, z = -1.1f;
+ LLVector4 vec4(x,y,z);
+ LLVector3 vec3 = vec4to3(vec4);
+ ensure("vec4to3 failed", ((x == vec3.mV[VX])&& (y == vec3.mV[VY]) && (z == vec3.mV[VZ])));
+ LLVector4 vec4a = vec3to4(vec3);
+ ensure_equals("vec3to4 failed",vec4a,vec4);
+ }
+
+ template<> template<>
+ void v4math_object::test<22>()
+ {
+ F32 x = 1.f, y = 2.f, z = -1.1f;
+ LLVector4 vec4(x,y,z);
+ LLSD llsd = vec4.getValue();
+ LLVector3 vec3(llsd);
+ LLVector4 vec4a = vec3to4(vec3);
+ ensure_equals("getValue failed",vec4a,vec4);
+ }
+}
diff --git a/indra/llmath/tests/xform_test.cpp b/indra/llmath/tests/xform_test.cpp
new file mode 100644
index 0000000000..e697a0b7a1
--- /dev/null
+++ b/indra/llmath/tests/xform_test.cpp
@@ -0,0 +1,251 @@
+/**
+ * @file xform_test.cpp
+ * @author Adroit
+ * @date March 2007
+ * @brief Test cases for LLXform
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+
+#include "../xform.h"
+
+namespace tut
+{
+ struct xform_test
+ {
+ };
+ typedef test_group<xform_test> xform_test_t;
+ typedef xform_test_t::object xform_test_object_t;
+ tut::xform_test_t tut_xform_test("xform_test");
+
+ //test case for init(), getParent(), getRotation(), getPositionW(), getWorldRotation() fns.
+ template<> template<>
+ void xform_test_object_t::test<1>()
+ {
+ LLXform xform_obj;
+ LLVector3 emptyVec(0.f,0.f,0.f);
+ LLVector3 initialScaleVec(1.f,1.f,1.f);
+
+ ensure("LLXform empty constructor failed: ", !xform_obj.getParent() && !xform_obj.isChanged() &&
+ xform_obj.getPosition() == emptyVec &&
+ (xform_obj.getRotation()).isIdentity() &&
+ xform_obj.getScale() == initialScaleVec &&
+ xform_obj.getPositionW() == emptyVec &&
+ (xform_obj.getWorldRotation()).isIdentity() &&
+ !xform_obj.getScaleChildOffset());
+ }
+
+ // test cases for
+ // setScale(const LLVector3& scale)
+ // setScale(const F32 x, const F32 y, const F32 z)
+ // setRotation(const F32 x, const F32 y, const F32 z)
+ // setPosition(const F32 x, const F32 y, const F32 z)
+ // getLocalMat4(LLMatrix4 &mat)
+ template<> template<>
+ void xform_test_object_t::test<2>()
+ {
+ LLMatrix4 llmat4;
+ LLXform xform_obj;
+
+ F32 x = 3.6f;
+ F32 y = 5.5f;
+ F32 z = 4.2f;
+ F32 w = 0.f;
+ F32 posz = z + 2.122f;
+ LLVector3 vec(x, y, z);
+ xform_obj.setScale(x, y, z);
+ xform_obj.setPosition(x, y, posz);
+ ensure("setScale failed: ", xform_obj.getScale() == vec);
+
+ vec.setVec(x, y, posz);
+ ensure("getPosition failed: ", xform_obj.getPosition() == vec);
+
+ x = x * 2.f;
+ y = y + 2.3f;
+ z = posz * 4.f;
+ vec.setVec(x, y, z);
+ xform_obj.setPositionX(x);
+ xform_obj.setPositionY(y);
+ xform_obj.setPositionZ(z);
+ ensure("setPositionX/Y/Z failed: ", xform_obj.getPosition() == vec);
+
+ xform_obj.setScaleChildOffset(TRUE);
+ ensure("setScaleChildOffset failed: ", xform_obj.getScaleChildOffset());
+
+ vec.setVec(x, y, z);
+
+ xform_obj.addPosition(vec);
+ vec += vec;
+ ensure("addPosition failed: ", xform_obj.getPosition() == vec);
+
+ xform_obj.setScale(vec);
+ ensure("setScale vector failed: ", xform_obj.getScale() == vec);
+
+ LLQuaternion quat(x, y, z, w);
+ xform_obj.setRotation(quat);
+ ensure("setRotation quat failed: ", xform_obj.getRotation() == quat);
+
+ xform_obj.setRotation(x, y, z, w);
+ ensure("getRotation 2 failed: ", xform_obj.getRotation() == quat);
+
+ xform_obj.setRotation(x, y, z);
+ quat.setQuat(x,y,z);
+ ensure("setRotation xyz failed: ", xform_obj.getRotation() == quat);
+
+ // LLXform::setRotation(const F32 x, const F32 y, const F32 z)
+ // Does normalization
+ // LLXform::setRotation(const F32 x, const F32 y, const F32 z, const F32 s)
+ // Simply copies the individual values - does not do any normalization.
+ // Is that the expected behavior?
+ }
+
+ // test cases for inline BOOL setParent(LLXform *parent) and getParent() fn.
+ template<> template<>
+ void xform_test_object_t::test<3>()
+ {
+ LLXform xform_obj;
+ LLXform par;
+ LLXform grandpar;
+ xform_obj.setParent(&par);
+ par.setParent(&grandpar);
+ ensure("setParent/getParent failed: ", &par == xform_obj.getParent());
+ ensure("getRoot failed: ", &grandpar == xform_obj.getRoot());
+ ensure("isRoot failed: ", grandpar.isRoot() && !par.isRoot() && !xform_obj.isRoot());
+ ensure("isRootEdit failed: ", grandpar.isRootEdit() && !par.isRootEdit() && !xform_obj.isRootEdit());
+ }
+
+ template<> template<>
+ void xform_test_object_t::test<4>()
+ {
+ LLXform xform_obj;
+ xform_obj.setChanged(LLXform::TRANSLATED | LLXform::ROTATED | LLXform::SCALED);
+ ensure("setChanged/isChanged failed: ", xform_obj.isChanged());
+
+ xform_obj.clearChanged(LLXform::TRANSLATED | LLXform::ROTATED | LLXform::SCALED);
+ ensure("clearChanged failed: ", !xform_obj.isChanged());
+
+ LLVector3 llvect3(12.4f, -5.6f, 0.34f);
+ xform_obj.setScale(llvect3);
+ ensure("setScale did not set SCALED flag: ", xform_obj.isChanged(LLXform::SCALED));
+ xform_obj.setPosition(1.2f, 2.3f, 3.4f);
+ ensure("setScale did not set TRANSLATED flag: ", xform_obj.isChanged(LLXform::TRANSLATED));
+ ensure("TRANSLATED reset SCALED flag: ", xform_obj.isChanged(LLXform::TRANSLATED | LLXform::SCALED));
+ xform_obj.clearChanged(LLXform::SCALED);
+ ensure("reset SCALED failed: ", !xform_obj.isChanged(LLXform::SCALED));
+ xform_obj.setRotation(1, 2, 3, 4);
+ ensure("ROTATION flag not set ", xform_obj.isChanged(LLXform::TRANSLATED | LLXform::ROTATED));
+ xform_obj.setScale(llvect3);
+ ensure("ROTATION flag not set ", xform_obj.isChanged(LLXform::MOVED));
+ }
+
+ //to test init() and getWorldMatrix() fns.
+ template<> template<>
+ void xform_test_object_t::test<5>()
+ {
+ LLXformMatrix formMatrix_obj;
+ formMatrix_obj.init();
+ LLMatrix4 mat4_obj;
+
+ ensure("1. The value is not NULL", 1.f == formMatrix_obj.getWorldMatrix().mMatrix[0][0]);
+ ensure("2. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[0][1]);
+ ensure("3. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[0][2]);
+ ensure("4. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[0][3]);
+ ensure("5. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[1][0]);
+ ensure("6. The value is not NULL", 1.f == formMatrix_obj.getWorldMatrix().mMatrix[1][1]);
+ ensure("7. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[1][2]);
+ ensure("8. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[1][3]);
+ ensure("9. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[2][0]);
+ ensure("10. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[2][1]);
+ ensure("11. The value is not NULL", 1.f == formMatrix_obj.getWorldMatrix().mMatrix[2][2]);
+ ensure("12. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[2][3]);
+ ensure("13. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[3][0]);
+ ensure("14. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[3][1]);
+ ensure("15. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[3][2]);
+ ensure("16. The value is not NULL", 1.f == formMatrix_obj.getWorldMatrix().mMatrix[3][3]);
+ }
+
+ //to test mMin.clearVec() and mMax.clearVec() fns
+ template<> template<>
+ void xform_test_object_t::test<6>()
+ {
+ LLXformMatrix formMatrix_obj;
+ formMatrix_obj.init();
+ LLVector3 llmin_vec3;
+ LLVector3 llmax_vec3;
+ formMatrix_obj.getMinMax(llmin_vec3, llmax_vec3);
+ ensure("1. The value is not NULL", 0.f == llmin_vec3.mV[0]);
+ ensure("2. The value is not NULL", 0.f == llmin_vec3.mV[1]);
+ ensure("3. The value is not NULL", 0.f == llmin_vec3.mV[2]);
+ ensure("4. The value is not NULL", 0.f == llmin_vec3.mV[0]);
+ ensure("5. The value is not NULL", 0.f == llmin_vec3.mV[1]);
+ ensure("6. The value is not NULL", 0.f == llmin_vec3.mV[2]);
+ }
+
+ //test case of update() fn.
+ template<> template<>
+ void xform_test_object_t::test<7>()
+ {
+ LLXformMatrix formMatrix_obj;
+
+ LLXformMatrix parent;
+ LLVector3 llvecpos(1.0, 2.0, 3.0);
+ LLVector3 llvecpospar(10.0, 20.0, 30.0);
+ formMatrix_obj.setPosition(llvecpos);
+ parent.setPosition(llvecpospar);
+
+ LLVector3 llvecparentscale(1.0, 2.0, 0);
+ parent.setScaleChildOffset(TRUE);
+ parent.setScale(llvecparentscale);
+
+ LLQuaternion quat(1, 2, 3, 4);
+ LLQuaternion quatparent(5, 6, 7, 8);
+ formMatrix_obj.setRotation(quat);
+ parent.setRotation(quatparent);
+ formMatrix_obj.setParent(&parent);
+
+ parent.update();
+ formMatrix_obj.update();
+
+ LLVector3 worldPos = llvecpos;
+ worldPos.scaleVec(llvecparentscale);
+ worldPos *= quatparent;
+ worldPos += llvecpospar;
+
+ LLQuaternion worldRot = quat * quatparent;
+
+ ensure("getWorldPosition failed: ", formMatrix_obj.getWorldPosition() == worldPos);
+ ensure("getWorldRotation failed: ", formMatrix_obj.getWorldRotation() == worldRot);
+
+ ensure("getWorldPosition for parent failed: ", parent.getWorldPosition() == llvecpospar);
+ ensure("getWorldRotation for parent failed: ", parent.getWorldRotation() == quatparent);
+ }
+}
+
diff --git a/indra/llmath/v3color.cpp b/indra/llmath/v3color.cpp
index fa7b61cd75..b4cd410076 100644
--- a/indra/llmath/v3color.cpp
+++ b/indra/llmath/v3color.cpp
@@ -56,9 +56,7 @@ LLColor3::LLColor3(const LLVector4 &a)
LLColor3::LLColor3(const LLSD &sd)
{
- mV[0] = (F32) sd[0].asReal();
- mV[1] = (F32) sd[1].asReal();
- mV[2] = (F32) sd[2].asReal();
+ setValue(sd);
}
const LLColor3& LLColor3::operator=(const LLColor4 &a)
@@ -75,6 +73,42 @@ std::ostream& operator<<(std::ostream& s, const LLColor3 &a)
return s;
}
+static F32 hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn )
+{
+ if ( valHUeIn < 0.0f ) valHUeIn += 1.0f;
+ if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f;
+ if ( ( 6.0f * valHUeIn ) < 1.0f ) return ( val1In + ( val2In - val1In ) * 6.0f * valHUeIn );
+ if ( ( 2.0f * valHUeIn ) < 1.0f ) return ( val2In );
+ if ( ( 3.0f * valHUeIn ) < 2.0f ) return ( val1In + ( val2In - val1In ) * ( ( 2.0f / 3.0f ) - valHUeIn ) * 6.0f );
+ return ( val1In );
+}
+
+void LLColor3::setHSL ( F32 hValIn, F32 sValIn, F32 lValIn)
+{
+ if ( sValIn < 0.00001f )
+ {
+ mV[VRED] = lValIn;
+ mV[VGREEN] = lValIn;
+ mV[VBLUE] = lValIn;
+ }
+ else
+ {
+ F32 interVal1;
+ F32 interVal2;
+
+ if ( lValIn < 0.5f )
+ interVal2 = lValIn * ( 1.0f + sValIn );
+ else
+ interVal2 = ( lValIn + sValIn ) - ( sValIn * lValIn );
+
+ interVal1 = 2.0f * lValIn - interVal2;
+
+ mV[VRED] = hueToRgb ( interVal1, interVal2, hValIn + ( 1.f / 3.f ) );
+ mV[VGREEN] = hueToRgb ( interVal1, interVal2, hValIn );
+ mV[VBLUE] = hueToRgb ( interVal1, interVal2, hValIn - ( 1.f / 3.f ) );
+ }
+}
+
void LLColor3::calcHSL(F32* hue, F32* saturation, F32* luminance) const
{
F32 var_R = mV[VRED];
diff --git a/indra/llmath/v3color.h b/indra/llmath/v3color.h
index 179687a32e..1915d80502 100644
--- a/indra/llmath/v3color.h
+++ b/indra/llmath/v3color.h
@@ -79,6 +79,7 @@ public:
mV[2] = (F32) sd[2].asReal();;
}
+ void setHSL(F32 hue, F32 saturation, F32 luminance);
void calcHSL(F32* hue, F32* saturation, F32* luminance) const;
const LLColor3& setToBlack(); // Clears LLColor3 to (0, 0, 0)
diff --git a/indra/llmath/v3dmath.h b/indra/llmath/v3dmath.h
index a99bf5b4a6..6ab31e8a41 100644
--- a/indra/llmath/v3dmath.h
+++ b/indra/llmath/v3dmath.h
@@ -53,7 +53,7 @@ class LLVector3d
inline LLVector3d(const F64 x, const F64 y, const F64 z); // Initializes LLVector3d to (x. y, z)
inline explicit LLVector3d(const F64 *vec); // Initializes LLVector3d to (vec[0]. vec[1], vec[2])
inline explicit LLVector3d(const LLVector3 &vec);
- LLVector3d(const LLSD& sd)
+ explicit LLVector3d(const LLSD& sd)
{
setValue(sd);
}
@@ -65,12 +65,6 @@ class LLVector3d
mdV[2] = sd[2].asReal();
}
- const LLVector3d& operator=(const LLSD& sd)
- {
- setValue(sd);
- return *this;
- }
-
LLSD getValue() const
{
LLSD ret;
diff --git a/indra/llmath/v3math.cpp b/indra/llmath/v3math.cpp
index 101e9d075a..63683ed496 100644
--- a/indra/llmath/v3math.cpp
+++ b/indra/llmath/v3math.cpp
@@ -185,14 +185,6 @@ void LLVector3::snap(S32 sig_digits)
mV[VZ] = snap_to_sig_figs(mV[VZ], sig_digits);
}
-
-std::ostream& operator<<(std::ostream& s, const LLVector3 &a)
-{
- s << "{ " << a.mV[VX] << ", " << a.mV[VY] << ", " << a.mV[VZ] << " }";
- return s;
-}
-
-
const LLVector3& LLVector3::rotVec(const LLMatrix3 &mat)
{
*this = *this * mat;
@@ -314,12 +306,6 @@ void LLVector3::setValue(const LLSD& sd)
mV[2] = (F32) sd[2].asReal();
}
-const LLVector3& LLVector3::operator=(const LLSD& sd)
-{
- setValue(sd);
- return *this;
-}
-
const LLVector3& operator*=(LLVector3 &a, const LLQuaternion &rot)
{
const F32 rw = - rot.mQ[VX] * a.mV[VX] - rot.mQ[VY] * a.mV[VY] - rot.mQ[VZ] * a.mV[VZ];
diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h
index 7f96800e21..73738cffd2 100644
--- a/indra/llmath/v3math.h
+++ b/indra/llmath/v3math.h
@@ -67,14 +67,12 @@ class LLVector3
explicit LLVector3(const LLVector2 &vec); // Initializes LLVector3 to (vec[0]. vec[1], 0)
explicit LLVector3(const LLVector3d &vec); // Initializes LLVector3 to (vec[0]. vec[1], vec[2])
explicit LLVector3(const LLVector4 &vec); // Initializes LLVector4 to (vec[0]. vec[1], vec[2])
- LLVector3(const LLSD& sd);
+ explicit LLVector3(const LLSD& sd);
LLSD getValue() const;
void setValue(const LLSD& sd);
- const LLVector3& operator=(const LLSD& sd);
-
inline BOOL isFinite() const; // checks to see if all values of LLVector3 are finite
BOOL clamp(F32 min, F32 max); // Clamps all values to (min,max), returns TRUE if data changed
BOOL clampLength( F32 length_limit ); // Scales vector to limit length to a value
@@ -411,8 +409,8 @@ inline bool operator<(const LLVector3 &a, const LLVector3 &b)
return (a.mV[0] < b.mV[0]
|| (a.mV[0] == b.mV[0]
&& (a.mV[1] < b.mV[1]
- || (a.mV[1] == b.mV[1])
- && a.mV[2] < b.mV[2])));
+ || ((a.mV[1] == b.mV[1])
+ && a.mV[2] < b.mV[2]))));
}
inline const LLVector3& operator+=(LLVector3 &a, const LLVector3 &b)
@@ -558,4 +556,10 @@ inline BOOL are_parallel(const LLVector3 &a, const LLVector3 &b, F32 epsilon)
return FALSE;
}
+inline std::ostream& operator<<(std::ostream& s, const LLVector3 &a)
+{
+ s << "{ " << a.mV[VX] << ", " << a.mV[VY] << ", " << a.mV[VZ] << " }";
+ return s;
+}
+
#endif
diff --git a/indra/llmath/v4color.cpp b/indra/llmath/v4color.cpp
index 0cbfce07c9..219b06ec74 100644
--- a/indra/llmath/v4color.cpp
+++ b/indra/llmath/v4color.cpp
@@ -227,6 +227,40 @@ const LLColor4& LLColor4::setVec(const LLColor3 &vec, F32 a)
return (*this);
}
+void LLColor4::setValue(const LLSD& sd)
+{
+#if 0
+ // Clamping on setValue from LLSD is inconsistent with other set behavior
+ F32 val;
+ bool out_of_range = false;
+ val = sd[0].asReal();
+ mV[0] = llclamp(val, 0.f, 1.f);
+ out_of_range = mV[0] != val;
+
+ val = sd[1].asReal();
+ mV[1] = llclamp(val, 0.f, 1.f);
+ out_of_range |= mV[1] != val;
+
+ val = sd[2].asReal();
+ mV[2] = llclamp(val, 0.f, 1.f);
+ out_of_range |= mV[2] != val;
+
+ val = sd[3].asReal();
+ mV[3] = llclamp(val, 0.f, 1.f);
+ out_of_range |= mV[3] != val;
+
+ if (out_of_range)
+ {
+ llwarns << "LLSD color value out of range!" << llendl;
+ }
+#else
+ mV[0] = (F32) sd[0].asReal();
+ mV[1] = (F32) sd[1].asReal();
+ mV[2] = (F32) sd[2].asReal();
+ mV[3] = (F32) sd[3].asReal();
+#endif
+}
+
const LLColor4& LLColor4::operator=(const LLColor3 &a)
{
mV[VX] = a.mV[VX];
@@ -271,6 +305,42 @@ LLColor4 vec3to4(const LLColor3 &vec)
return temp;
}
+static F32 hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn )
+{
+ if ( valHUeIn < 0.0f ) valHUeIn += 1.0f;
+ if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f;
+ if ( ( 6.0f * valHUeIn ) < 1.0f ) return ( val1In + ( val2In - val1In ) * 6.0f * valHUeIn );
+ if ( ( 2.0f * valHUeIn ) < 1.0f ) return ( val2In );
+ if ( ( 3.0f * valHUeIn ) < 2.0f ) return ( val1In + ( val2In - val1In ) * ( ( 2.0f / 3.0f ) - valHUeIn ) * 6.0f );
+ return ( val1In );
+}
+
+void LLColor4::setHSL ( F32 hValIn, F32 sValIn, F32 lValIn)
+{
+ if ( sValIn < 0.00001f )
+ {
+ mV[VRED] = lValIn;
+ mV[VGREEN] = lValIn;
+ mV[VBLUE] = lValIn;
+ }
+ else
+ {
+ F32 interVal1;
+ F32 interVal2;
+
+ if ( lValIn < 0.5f )
+ interVal2 = lValIn * ( 1.0f + sValIn );
+ else
+ interVal2 = ( lValIn + sValIn ) - ( sValIn * lValIn );
+
+ interVal1 = 2.0f * lValIn - interVal2;
+
+ mV[VRED] = hueToRgb ( interVal1, interVal2, hValIn + ( 1.f / 3.f ) );
+ mV[VGREEN] = hueToRgb ( interVal1, interVal2, hValIn );
+ mV[VBLUE] = hueToRgb ( interVal1, interVal2, hValIn - ( 1.f / 3.f ) );
+ }
+}
+
void LLColor4::calcHSL(F32* hue, F32* saturation, F32* luminance) const
{
F32 var_R = mV[VRED];
diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h
index 785b47dd37..d6fbdec61e 100644
--- a/indra/llmath/v4color.h
+++ b/indra/llmath/v4color.h
@@ -58,7 +58,7 @@ class LLColor4
LLColor4(U32 clr); // Initializes LLColor4 to (r=clr>>24, etc))
LLColor4(const F32 *vec); // Initializes LLColor4 to (vec[0]. vec[1], vec[2], 1)
LLColor4(const LLColor3 &vec, F32 a = 1.f); // Initializes LLColor4 to (vec, a)
- LLColor4(const LLSD& sd);
+ explicit LLColor4(const LLSD& sd);
explicit LLColor4(const LLColor4U& color4u); // "explicit" to avoid automatic conversion
explicit LLColor4(const LLVector4& vector4); // "explicit" to avoid automatic conversion
@@ -72,14 +72,9 @@ class LLColor4
return ret;
}
- void setValue(const LLSD& sd)
- {
- mV[0] = (F32) sd[0].asReal();
- mV[1] = (F32) sd[1].asReal();
- mV[2] = (F32) sd[2].asReal();
- mV[3] = (F32) sd[3].asReal();
- }
+ void setValue(const LLSD& sd);
+ void setHSL(F32 hue, F32 saturation, F32 luminance);
void calcHSL(F32* hue, F32* saturation, F32* luminance) const;
const LLColor4& setToBlack(); // zero LLColor4 to (0, 0, 0, 1)
@@ -118,7 +113,6 @@ class LLColor4
F32 &operator[](int idx) { return mV[idx]; }
const LLColor4& operator=(const LLColor3 &a); // Assigns vec3 to vec4 and returns vec4
- const LLColor4& operator=(const LLSD& sd);
friend std::ostream& operator<<(std::ostream& s, const LLColor4 &a); // Print a
friend LLColor4 operator+(const LLColor4 &a, const LLColor4 &b); // Return vector a + b
@@ -249,7 +243,7 @@ inline LLColor4::LLColor4(void)
inline LLColor4::LLColor4(const LLSD& sd)
{
- *this = sd;
+ this->setValue(sd);
}
inline LLColor4::LLColor4(F32 r, F32 g, F32 b)
@@ -639,15 +633,5 @@ void LLColor4::clamp()
}
}
-inline const LLColor4& LLColor4::operator=(const LLSD& sd)
-{
- mV[0] = (F32) sd[0].asReal();
- mV[1] = (F32) sd[1].asReal();
- mV[2] = (F32) sd[2].asReal();
- mV[3] = (F32) sd[3].asReal();
-
- return *this;
-}
-
#endif
diff --git a/indra/llmath/v4coloru.h b/indra/llmath/v4coloru.h
index 082d0efbb1..4ec5a345eb 100644
--- a/indra/llmath/v4coloru.h
+++ b/indra/llmath/v4coloru.h
@@ -66,7 +66,7 @@ public:
LLColor4U(U8 r, U8 g, U8 b); // Initializes LLColor4U to (r, g, b, 1)
LLColor4U(U8 r, U8 g, U8 b, U8 a); // Initializes LLColor4U to (r. g, b, a)
LLColor4U(const U8 *vec); // Initializes LLColor4U to (vec[0]. vec[1], vec[2], 1)
- LLColor4U(const LLSD& sd)
+ explicit LLColor4U(const LLSD& sd)
{
setValue(sd);
}
@@ -79,12 +79,6 @@ public:
mV[3] = sd[3].asInteger();
}
- const LLColor4U& operator=(const LLSD& sd)
- {
- setValue(sd);
- return *this;
- }
-
LLSD getValue() const
{
LLSD ret;
@@ -138,6 +132,12 @@ public:
static BOOL parseColor4U(const std::string& buf, LLColor4U* value);
+ // conversion
+ operator const LLColor4() const
+ {
+ return LLColor4(*this);
+ }
+
static LLColor4U white;
static LLColor4U black;
static LLColor4U red;
diff --git a/indra/llmath/xform.cpp b/indra/llmath/xform.cpp
index ce6f756ab9..7a8b0cf6a3 100644
--- a/indra/llmath/xform.cpp
+++ b/indra/llmath/xform.cpp
@@ -42,6 +42,11 @@ LLXform::~LLXform()
{
}
+// Link optimization - don't inline these llwarns
+void LLXform::warn(const char* const msg)
+{
+ llwarns << msg << llendl;
+}
LLXform* LLXform::getRoot() const
{
diff --git a/indra/llmath/xform.h b/indra/llmath/xform.h
index d3be28f41d..c4edd46279 100644
--- a/indra/llmath/xform.h
+++ b/indra/llmath/xform.h
@@ -107,6 +107,12 @@ public:
inline void setRotation(const LLQuaternion& rot);
inline void setRotation(const F32 x, const F32 y, const F32 z);
inline void setRotation(const F32 x, const F32 y, const F32 z, const F32 s);
+
+ // Above functions must be inline for speed, but also
+ // need to emit warnings. llwarns causes inline LLError::CallSite
+ // static objects that make more work for the linker.
+ // Avoid inline llwarns by calling this function.
+ void warn(const char* const msg);
void setChanged(const U32 bits) { mChanged |= bits; }
BOOL isChanged() const { return mChanged; }
@@ -173,7 +179,7 @@ BOOL LLXform::setParent(LLXform* parent)
{
if (cur_par == this)
{
- llwarns << "LLXform::setParent Creating loop when setting parent!" << llendl;
+ //warn("LLXform::setParent Creating loop when setting parent!");
return FALSE;
}
cur_par = cur_par->mParent;
@@ -191,7 +197,7 @@ void LLXform::setPosition(const LLVector3& pos)
else
{
mPosition.clearVec();
- llwarns << "Non Finite in LLXform::setPosition(LLVector3)" << llendl;
+ warn("Non Finite in LLXform::setPosition(LLVector3)");
}
}
@@ -203,7 +209,7 @@ void LLXform::setPosition(const F32 x, const F32 y, const F32 z)
else
{
mPosition.clearVec();
- llwarns << "Non Finite in LLXform::setPosition(F32,F32,F32)" << llendl;
+ warn("Non Finite in LLXform::setPosition(F32,F32,F32)");
}
}
@@ -215,7 +221,7 @@ void LLXform::setPositionX(const F32 x)
else
{
mPosition.mV[VX] = 0.f;
- llwarns << "Non Finite in LLXform::setPositionX" << llendl;
+ warn("Non Finite in LLXform::setPositionX");
}
}
@@ -227,7 +233,7 @@ void LLXform::setPositionY(const F32 y)
else
{
mPosition.mV[VY] = 0.f;
- llwarns << "Non Finite in LLXform::setPositionY" << llendl;
+ warn("Non Finite in LLXform::setPositionY");
}
}
@@ -239,7 +245,7 @@ void LLXform::setPositionZ(const F32 z)
else
{
mPosition.mV[VZ] = 0.f;
- llwarns << "Non Finite in LLXform::setPositionZ" << llendl;
+ warn("Non Finite in LLXform::setPositionZ");
}
}
@@ -249,7 +255,7 @@ void LLXform::addPosition(const LLVector3& pos)
if (pos.isFinite())
mPosition += pos;
else
- llwarns << "Non Finite in LLXform::addPosition" << llendl;
+ warn("Non Finite in LLXform::addPosition");
}
void LLXform::setScale(const LLVector3& scale)
@@ -260,7 +266,7 @@ void LLXform::setScale(const LLVector3& scale)
else
{
mScale.setVec(1.f, 1.f, 1.f);
- llwarns << "Non Finite in LLXform::setScale" << llendl;
+ warn("Non Finite in LLXform::setScale");
}
}
void LLXform::setScale(const F32 x, const F32 y, const F32 z)
@@ -271,7 +277,7 @@ void LLXform::setScale(const F32 x, const F32 y, const F32 z)
else
{
mScale.setVec(1.f, 1.f, 1.f);
- llwarns << "Non Finite in LLXform::setScale" << llendl;
+ warn("Non Finite in LLXform::setScale");
}
}
void LLXform::setRotation(const LLQuaternion& rot)
@@ -282,7 +288,7 @@ void LLXform::setRotation(const LLQuaternion& rot)
else
{
mRotation.loadIdentity();
- llwarns << "Non Finite in LLXform::setRotation" << llendl;
+ warn("Non Finite in LLXform::setRotation");
}
}
void LLXform::setRotation(const F32 x, const F32 y, const F32 z)
@@ -295,7 +301,7 @@ void LLXform::setRotation(const F32 x, const F32 y, const F32 z)
else
{
mRotation.loadIdentity();
- llwarns << "Non Finite in LLXform::setRotation" << llendl;
+ warn("Non Finite in LLXform::setRotation");
}
}
void LLXform::setRotation(const F32 x, const F32 y, const F32 z, const F32 s)
@@ -308,7 +314,7 @@ void LLXform::setRotation(const F32 x, const F32 y, const F32 z, const F32 s)
else
{
mRotation.loadIdentity();
- llwarns << "Non Finite in LLXform::setRotation" << llendl;
+ warn("Non Finite in LLXform::setRotation");
}
}
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index 0f3e159802..1f8ee26716 100644
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -3,6 +3,8 @@
project(llmessage)
include(00-Common)
+include(GoogleMock)
+include(LLAddBuildTest)
include(LLCommon)
include(LLMath)
include(LLMessage)
@@ -21,6 +23,7 @@ include_directories(
set(llmessage_SOURCE_FILES
llares.cpp
+ llareslistener.cpp
llassetstorage.cpp
llblowfishcipher.cpp
llbuffer.cpp
@@ -63,6 +66,7 @@ set(llmessage_SOURCE_FILES
llregionpresenceverifier.cpp
llsdappservices.cpp
llsdhttpserver.cpp
+ llsdmessage.cpp
llsdmessagebuilder.cpp
llsdmessagereader.cpp
llsdrpcclient.cpp
@@ -88,6 +92,7 @@ set(llmessage_SOURCE_FILES
llxfer_mem.cpp
llxfer_vfile.cpp
llxorcipher.cpp
+ machine.cpp
message.cpp
message_prehash.cpp
message_string_table.cpp
@@ -96,12 +101,14 @@ set(llmessage_SOURCE_FILES
patch_code.cpp
patch_dct.cpp
patch_idct.cpp
+ sound_ids.cpp
)
set(llmessage_HEADER_FILES
CMakeLists.txt
llares.h
+ llareslistener.h
llassetstorage.h
llblowfishcipher.h
llbuffer.h
@@ -156,6 +163,7 @@ set(llmessage_HEADER_FILES
llregionpresenceverifier.h
llsdappservices.h
llsdhttpserver.h
+ llsdmessage.h
llsdmessagebuilder.h
llsdmessagereader.h
llsdrpcclient.h
@@ -202,20 +210,46 @@ list(APPEND llmessage_SOURCE_FILES ${llmessage_HEADER_FILES})
add_library (llmessage ${llmessage_SOURCE_FILES})
target_link_libraries(
- llmessage
- ${CURL_LIBRARIES}
- ${CARES_LIBRARIES}
- ${OPENSSL_LIBRARIES}
- ${CRYPTO_LIBRARIES}
- ${XMLRPCEPI_LIBRARIES}
+ llmessage
+ ${CURL_LIBRARIES}
+ ${CARES_LIBRARIES}
+ ${OPENSSL_LIBRARIES}
+ ${CRYPTO_LIBRARIES}
+ ${XMLRPCEPI_LIBRARIES}
+ )
+
+# tests
+if (LL_TESTS)
+ SET(llmessage_TEST_SOURCE_FILES
+ # llhttpclientadapter.cpp
+ llmime.cpp
+ llnamevalue.cpp
+ lltrustedmessageservice.cpp
+ lltemplatemessagedispatcher.cpp
+ llregionpresenceverifier.cpp
+ )
+ LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}")
+
+ # set(TEST_DEBUG on)
+ set(test_libs
+ ${LLMESSAGE_LIBRARIES}
+ ${WINDOWS_LIBRARIES}
+ ${LLVFS_LIBRARIES}
+ ${LLMATH_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+ ${GOOGLEMOCK_LIBRARIES}
+ )
+
+ LL_ADD_INTEGRATION_TEST(
+ llsdmessage
+ "llsdmessage.cpp"
+ "${test_libs}"
+ ${PYTHON_EXECUTABLE}
+ "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py"
)
-IF (NOT LINUX AND VIEWER)
- # When building the viewer the tests links against the shared objects.
- # These can not be found when we try to run the tests, so we had to disable them, for the viewer build.
- # TODO: Can someone with viewer knowledge figure out how to make these find the correct so.
- #ADD_BUILD_TEST(llhttpclientadapter llmessage)
- ADD_BUILD_TEST(lltrustedmessageservice llmessage)
- ADD_BUILD_TEST(lltemplatemessagedispatcher llmessage)
-ENDIF (NOT LINUX AND VIEWER)
+ LL_ADD_INTEGRATION_TEST(llhost "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(llpartdata "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(llxfer_file "" "${test_libs}")
+endif (LL_TESTS)
diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp
index fe37fe8142..104629c157 100644
--- a/indra/llmessage/llares.cpp
+++ b/indra/llmessage/llares.cpp
@@ -33,6 +33,7 @@
*/
#include "linden_common.h"
+#include "llares.h"
#include <ares_dns.h>
#include <ares_version.h>
@@ -42,9 +43,10 @@
#include "apr_poll.h"
#include "llapr.h"
-#include "llares.h"
+#include "llareslistener.h"
#if defined(LL_WINDOWS)
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
# define ns_c_in 1
# define NS_HFIXEDSZ 12 /* #/bytes of fixed data in header */
# define NS_QFIXEDSZ 4 /* #/bytes of fixed data in query */
@@ -102,7 +104,9 @@ void LLAres::QueryResponder::queryError(int code)
}
LLAres::LLAres() :
-chan_(NULL), mInitSuccess(false)
+ chan_(NULL),
+ mInitSuccess(false),
+ mListener(new LLAresListener(this))
{
if (ares_init(&chan_) != ARES_SUCCESS)
{
diff --git a/indra/llmessage/llares.h b/indra/llmessage/llares.h
index 96d7f6dd31..78febcd560 100644
--- a/indra/llmessage/llares.h
+++ b/indra/llmessage/llares.h
@@ -36,7 +36,13 @@
#define LL_LLARES_H
#ifdef LL_WINDOWS
+// ares.h is broken on windows in that it depends on types defined in ws2tcpip.h
+// we need to include them first to work around it, but the headers issue warnings
+# pragma warning(push)
+# pragma warning(disable:4996)
+# include <winsock2.h>
# include <ws2tcpip.h>
+# pragma warning(pop)
#endif
#ifdef LL_STANDALONE
@@ -45,10 +51,14 @@
# include <ares/ares.h>
#endif
-#include "llmemory.h"
+#include "llpointer.h"
+#include "llrefcount.h"
#include "lluri.h"
+#include <boost/shared_ptr.hpp>
+
class LLQueryResponder;
+class LLAresListener;
/**
* @brief Supported DNS RR types.
@@ -443,6 +453,9 @@ public:
protected:
ares_channel chan_;
bool mInitSuccess;
+ // boost::scoped_ptr would actually fit the requirement better, but it
+ // can't handle incomplete types as boost::shared_ptr can.
+ boost::shared_ptr<LLAresListener> mListener;
};
/**
diff --git a/indra/llmessage/llareslistener.cpp b/indra/llmessage/llareslistener.cpp
new file mode 100644
index 0000000000..97efa96d53
--- /dev/null
+++ b/indra/llmessage/llareslistener.cpp
@@ -0,0 +1,80 @@
+/**
+ * @file llareslistener.cpp
+ * @author Nat Goodspeed
+ * @date 2009-03-18
+ * @brief Implementation for llareslistener.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llareslistener.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llares.h"
+#include "llerror.h"
+#include "llevents.h"
+#include "llsdutil.h"
+
+LLAresListener::LLAresListener(LLAres* llares):
+ LLEventAPI("LLAres",
+ "LLAres listener to request DNS operations"),
+ mAres(llares)
+{
+ // add() every method we want to be able to invoke via this event API.
+ // Optional last parameter validates expected LLSD request structure.
+ add("rewriteURI",
+ "Given [\"uri\"], return on [\"reply\"] an array of alternative URIs.\n"
+ "On failure, returns an array containing only the original URI, so\n"
+ "failure case can be processed like success case.",
+ &LLAresListener::rewriteURI,
+ LLSD().with("uri", LLSD()).with("reply", LLSD()));
+}
+
+/// This UriRewriteResponder subclass packages returned URIs as an LLSD
+/// array to send back to the requester.
+class UriRewriteResponder: public LLAres::UriRewriteResponder
+{
+public:
+ /**
+ * Specify the request, containing the event pump name on which to send
+ * the reply.
+ */
+ UriRewriteResponder(const LLSD& request):
+ mReqID(request),
+ mPumpName(request["reply"])
+ {}
+
+ /// Called by base class with results. This is called in both the
+ /// success and error cases. On error, the calling logic passes the
+ /// original URI.
+ virtual void rewriteResult(const std::vector<std::string>& uris)
+ {
+ LLSD result;
+ for (std::vector<std::string>::const_iterator ui(uris.begin()), uend(uris.end());
+ ui != uend; ++ui)
+ {
+ result.append(*ui);
+ }
+ // This call knows enough to avoid trying to insert a map key into an
+ // LLSD array. It's there so that if, for any reason, we ever decide
+ // to change the response from array to map, it will Just Start Working.
+ mReqID.stamp(result);
+ LLEventPumps::instance().obtain(mPumpName).post(result);
+ }
+
+private:
+ LLReqID mReqID;
+ const std::string mPumpName;
+};
+
+void LLAresListener::rewriteURI(const LLSD& data)
+{
+ mAres->rewriteURI(data["uri"], new UriRewriteResponder(data));
+}
diff --git a/indra/llmessage/llareslistener.h b/indra/llmessage/llareslistener.h
new file mode 100644
index 0000000000..33cef79c09
--- /dev/null
+++ b/indra/llmessage/llareslistener.h
@@ -0,0 +1,36 @@
+/**
+ * @file llareslistener.h
+ * @author Nat Goodspeed
+ * @date 2009-03-18
+ * @brief LLEventPump API for LLAres. This header doesn't actually define the
+ * API; the API is defined by the pump name on which this class
+ * listens, and by the expected content of LLSD it receives.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLARESLISTENER_H)
+#define LL_LLARESLISTENER_H
+
+#include "lleventapi.h"
+
+class LLAres;
+class LLSD;
+
+/// Listen on an LLEventPump with specified name for LLAres request events.
+class LLAresListener: public LLEventAPI
+{
+public:
+ /// Bind the LLAres instance to use (e.g. gAres)
+ LLAresListener(LLAres* llares);
+
+private:
+ /// command["op"] == "rewriteURI"
+ void rewriteURI(const LLSD& data);
+
+ LLAres* mAres;
+};
+
+#endif /* ! defined(LL_LLARESLISTENER_H) */
diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp
index 2966b602d7..0ab1081200 100644
--- a/indra/llmessage/llassetstorage.cpp
+++ b/indra/llmessage/llassetstorage.cpp
@@ -64,6 +64,9 @@ const LLUUID CATEGORIZE_LOST_AND_FOUND_ID(std::string("00000000-0000-0000-0000-0
const U64 TOXIC_ASSET_LIFETIME = (120 * 1000000); // microseconds
+LLTempAssetStorage::~LLTempAssetStorage()
+{
+}
///----------------------------------------------------------------------------
/// LLAssetInfo
@@ -1025,12 +1028,12 @@ LLSD LLAssetStorage::getPendingDetails(LLAssetStorage::ERequestType rt,
{
const request_list_t* requests = getRequestList(rt);
LLSD sd;
- sd["requests"] = getPendingDetails(requests, asset_type, detail_prefix);
+ sd["requests"] = getPendingDetailsImpl(requests, asset_type, detail_prefix);
return sd;
}
// virtual
-LLSD LLAssetStorage::getPendingDetails(const LLAssetStorage::request_list_t* requests,
+LLSD LLAssetStorage::getPendingDetailsImpl(const LLAssetStorage::request_list_t* requests,
LLAssetType::EType asset_type,
const std::string& detail_prefix) const
{
@@ -1113,11 +1116,11 @@ LLSD LLAssetStorage::getPendingRequest(LLAssetStorage::ERequestType rt,
const LLUUID& asset_id) const
{
const request_list_t* requests = getRequestList(rt);
- return getPendingRequest(requests, asset_type, asset_id);
+ return getPendingRequestImpl(requests, asset_type, asset_id);
}
// virtual
-LLSD LLAssetStorage::getPendingRequest(const LLAssetStorage::request_list_t* requests,
+LLSD LLAssetStorage::getPendingRequestImpl(const LLAssetStorage::request_list_t* requests,
LLAssetType::EType asset_type,
const LLUUID& asset_id) const
{
@@ -1136,7 +1139,7 @@ bool LLAssetStorage::deletePendingRequest(LLAssetStorage::ERequestType rt,
const LLUUID& asset_id)
{
request_list_t* requests = getRequestList(rt);
- if (deletePendingRequest(requests, asset_type, asset_id))
+ if (deletePendingRequestImpl(requests, asset_type, asset_id))
{
llinfos << "Asset " << getRequestName(rt) << " request for "
<< asset_id << "." << LLAssetType::lookup(asset_type)
@@ -1147,7 +1150,7 @@ bool LLAssetStorage::deletePendingRequest(LLAssetStorage::ERequestType rt,
}
// virtual
-bool LLAssetStorage::deletePendingRequest(LLAssetStorage::request_list_t* requests,
+bool LLAssetStorage::deletePendingRequestImpl(LLAssetStorage::request_list_t* requests,
LLAssetType::EType asset_type,
const LLUUID& asset_id)
{
diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h
index f01ee6a8e8..83cfdf6110 100644
--- a/indra/llmessage/llassetstorage.h
+++ b/indra/llmessage/llassetstorage.h
@@ -204,7 +204,16 @@ typedef std::map<LLUUID,U64,lluuid_less> toxic_asset_map_t;
typedef void (*LLGetAssetCallback)(LLVFS *vfs, const LLUUID &asset_id,
LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status);
-class LLAssetStorage
+class LLTempAssetStorage
+{
+public:
+ virtual ~LLTempAssetStorage() =0;
+ virtual void addTempAssetData(const LLUUID& asset_id,
+ const LLUUID& agent_id,
+ const std::string& host_name) = 0;
+};
+
+class LLAssetStorage : public LLTempAssetStorage
{
public:
// VFS member is public because static child methods need it :(
@@ -306,15 +315,15 @@ public:
void markAssetToxic( const LLUUID& uuid );
protected:
- virtual LLSD getPendingDetails(const request_list_t* requests,
+ virtual LLSD getPendingDetailsImpl(const request_list_t* requests,
LLAssetType::EType asset_type,
const std::string& detail_prefix) const;
- virtual LLSD getPendingRequest(const request_list_t* requests,
+ virtual LLSD getPendingRequestImpl(const request_list_t* requests,
LLAssetType::EType asset_type,
const LLUUID& asset_id) const;
- virtual bool deletePendingRequest(request_list_t* requests,
+ virtual bool deletePendingRequestImpl(request_list_t* requests,
LLAssetType::EType asset_type,
const LLUUID& asset_id);
diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp
index 799bc83e20..3078d80552 100644
--- a/indra/llmessage/llcachename.cpp
+++ b/indra/llmessage/llcachename.cpp
@@ -42,11 +42,7 @@
#include "llsdserialize.h"
#include "lluuid.h"
#include "message.h"
-
-// Constants
-static const std::string CN_WAITING("(Loading...)"); // *TODO: translate
-static const std::string CN_NOBODY("(nobody)"); // *TODO: translate
-static const std::string CN_NONE("(none)"); // *TODO: translate
+#include "llmemtype.h"
// llsd serialization constants
static const std::string AGENTS("agents");
@@ -65,6 +61,7 @@ const S32 CN_FILE_VERSION = 2;
// Globals
LLCacheName* gCacheName = NULL;
+std::map<std::string, std::string> LLCacheName::sCacheName;
/// ---------------------------------------------------------------------------
/// class LLCacheNameEntry
@@ -92,17 +89,19 @@ class PendingReply
{
public:
LLUUID mID;
- LLCacheNameCallback mCallback;
+ LLCacheNameSignal mSignal;
LLHost mHost;
- void* mData;
- PendingReply(const LLUUID& id, LLCacheNameCallback callback, void* data = NULL)
- : mID(id), mCallback(callback), mData(data)
- { }
-
+
PendingReply(const LLUUID& id, const LLHost& host)
- : mID(id), mCallback(0), mHost(host)
- { }
-
+ : mID(id), mHost(host)
+ {
+ }
+
+ boost::signals2::connection setCallback(const LLCacheNameCallback& cb)
+ {
+ return mSignal.connect(cb);
+ }
+
void done() { mID.setNull(); }
bool isDone() const { return mID.isNull() != FALSE; }
};
@@ -187,10 +186,10 @@ void ReplySender::flush()
typedef std::set<LLUUID> AskQueue;
-typedef std::vector<PendingReply> ReplyQueue;
+typedef std::list<PendingReply*> ReplyQueue;
typedef std::map<LLUUID,U32> PendingQueue;
typedef std::map<LLUUID, LLCacheNameEntry*> Cache;
-typedef std::vector<LLCacheNameCallback> Observers;
+typedef std::map<std::string, LLUUID> ReverseCache;
class LLCacheName::Impl
{
@@ -200,7 +199,9 @@ public:
Cache mCache;
// the map of UUIDs to names
-
+ ReverseCache mReverseCache;
+ // map of names to UUIDs
+
AskQueue mAskNameQueue;
AskQueue mAskGroupQueue;
// UUIDs to ask our upstream host about
@@ -211,13 +212,16 @@ public:
ReplyQueue mReplyQueue;
// requests awaiting replies from us
- Observers mObservers;
+ LLCacheNameSignal mSignal;
LLFrameTimer mProcessTimer;
Impl(LLMessageSystem* msg);
~Impl();
-
+
+ boost::signals2::connection addPending(const LLUUID& id, const LLCacheNameCallback& callback);
+ void addPending(const LLUUID& id, const LLHost& host);
+
void processPendingAsks();
void processPendingReplies();
void sendRequest(const char* msg_name, const AskQueue& queue);
@@ -231,8 +235,6 @@ public:
static void handleUUIDNameReply(LLMessageSystem* msg, void** userdata);
static void handleUUIDGroupNameRequest(LLMessageSystem* msg, void** userdata);
static void handleUUIDGroupNameReply(LLMessageSystem* msg, void** userdata);
-
- void notifyObservers(const LLUUID& id, const std::string& first, const std::string& last, BOOL group);
};
@@ -247,6 +249,9 @@ LLCacheName::LLCacheName(LLMessageSystem* msg)
LLCacheName::LLCacheName(LLMessageSystem* msg, const LLHost& upstream_host)
: impl(* new Impl(msg))
{
+ sCacheName["waiting"] = "(Loading...)";
+ sCacheName["nobody"] = "(nobody)";
+ sCacheName["none"] = "(none)";
setUpstream(upstream_host);
}
@@ -272,52 +277,31 @@ LLCacheName::Impl::Impl(LLMessageSystem* msg)
LLCacheName::Impl::~Impl()
{
for_each(mCache.begin(), mCache.end(), DeletePairedPointer());
+ for_each(mReplyQueue.begin(), mReplyQueue.end(), DeletePointer());
}
-
-void LLCacheName::setUpstream(const LLHost& upstream_host)
+boost::signals2::connection LLCacheName::Impl::addPending(const LLUUID& id, const LLCacheNameCallback& callback)
{
- impl.mUpstreamHost = upstream_host;
+ PendingReply* reply = new PendingReply(id, LLHost());
+ boost::signals2::connection res = reply->setCallback(callback);
+ mReplyQueue.push_back(reply);
+ return res;
}
-void LLCacheName::addObserver(LLCacheNameCallback callback)
+void LLCacheName::Impl::addPending(const LLUUID& id, const LLHost& host)
{
- impl.mObservers.push_back(callback);
+ PendingReply* reply = new PendingReply(id, host);
+ mReplyQueue.push_back(reply);
}
-void LLCacheName::removeObserver(LLCacheNameCallback callback)
+void LLCacheName::setUpstream(const LLHost& upstream_host)
{
- Observers::iterator it = impl.mObservers.begin();
- Observers::iterator end = impl.mObservers.end();
-
- for ( ; it != end; ++it)
- {
- const LLCacheNameCallback& cb = (*it);
- if (cb == callback)
- {
- impl.mObservers.erase(it);
- return;
- }
- }
+ impl.mUpstreamHost = upstream_host;
}
-void LLCacheName::cancelCallback(const LLUUID& id, LLCacheNameCallback callback, void* user_data)
+boost::signals2::connection LLCacheName::addObserver(const LLCacheNameCallback& callback)
{
- ReplyQueue::iterator it = impl.mReplyQueue.begin();
- ReplyQueue::iterator end = impl.mReplyQueue.end();
-
- for(; it != end; ++it)
- {
- const PendingReply& reply = (*it);
-
- if ((callback == reply.mCallback)
- && (id == reply.mID)
- && (user_data == reply.mData) )
- {
- impl.mReplyQueue.erase(it);
- return;
- }
- }
+ return impl.mSignal.connect(callback);
}
void LLCacheName::importFile(LLFILE* fp)
@@ -390,7 +374,9 @@ void LLCacheName::importFile(LLFILE* fp)
entry->mFirstName = firstname;
entry->mLastName = lastname;
impl.mCache[id] = entry;
-
+ std::string fullname = entry->mFirstName + " " + entry->mLastName;
+ impl.mReverseCache[fullname] = id;
+
count++;
}
@@ -426,6 +412,8 @@ bool LLCacheName::importFile(std::istream& istr)
entry->mFirstName = agent[FIRST].asString();
entry->mLastName = agent[LAST].asString();
impl.mCache[id] = entry;
+ std::string fullname = entry->mFirstName + " " + entry->mLastName;
+ impl.mReverseCache[fullname] = id;
++count;
}
@@ -447,6 +435,7 @@ bool LLCacheName::importFile(std::istream& istr)
entry->mCreateTime = ctime;
entry->mGroupName = group[NAME].asString();
impl.mCache[id] = entry;
+ impl.mReverseCache[entry->mGroupName] = id;
++count;
}
llinfos << "LLCacheName loaded " << count << " group names" << llendl;
@@ -493,7 +482,7 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las
{
if(id.isNull())
{
- first = CN_NOBODY;
+ first = sCacheName["nobody"];
last.clear();
return FALSE;
}
@@ -507,7 +496,7 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las
}
else
{
- first = CN_WAITING;
+ first = sCacheName["waiting"];
last.clear();
if (!impl.isRequestPending(id))
{
@@ -517,6 +506,14 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las
}
}
+// static
+void LLCacheName::LocalizeCacheName(std::string key, std::string value)
+{
+ if (key!="" && value!= "" )
+ sCacheName[key]=value;
+ else
+ llwarns<< " Error localizing cache key " << key << " To "<< value<<llendl;
+}
BOOL LLCacheName::getFullName(const LLUUID& id, std::string& fullname)
{
@@ -530,7 +527,7 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
{
if(id.isNull())
{
- group = CN_NONE;
+ group = sCacheName["none"];
return FALSE;
}
@@ -551,7 +548,7 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
}
else
{
- group = CN_WAITING;
+ group = sCacheName["waiting"];
if (!impl.isRequestPending(id))
{
impl.mAskGroupQueue.insert(id);
@@ -560,27 +557,58 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
}
}
-// TODO: Make the cache name callback take a SINGLE std::string,
-// not a separate first and last name.
-void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data)
+BOOL LLCacheName::getUUID(const std::string& first, const std::string& last, LLUUID& id)
+{
+ std::string fullname = first + " " + last;
+ return getUUID(fullname, id);
+}
+
+BOOL LLCacheName::getUUID(const std::string& fullname, LLUUID& id)
+{
+ ReverseCache::iterator iter = impl.mReverseCache.find(fullname);
+ if (iter != impl.mReverseCache.end())
+ {
+ id = iter->second;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+// This is a little bit kludgy. LLCacheNameCallback is a slot instead of a function pointer.
+// The reason it is a slot is so that the legacy get() function below can bind an old callback
+// and pass it as a slot. The reason it isn't a boost::function is so that trackable behavior
+// doesn't get lost. As a result, we have to bind the slot to a signal to call it, even when
+// we call it immediately. -Steve
+// NOTE: Even though passing first and last name is a bit of extra overhead, it eliminates the
+// potential need for any parsing should any code need to handle first and last name independently.
+boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, const LLCacheNameCallback& callback)
{
+ boost::signals2::connection res;
+
if(id.isNull())
{
- callback(id, CN_NOBODY, "", is_group, user_data);
- return;
+ LLCacheNameSignal signal;
+ signal.connect(callback);
+ signal(id, sCacheName["nobody"], "", is_group);
+ return res;
}
LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache, id );
if (entry)
{
+ LLCacheNameSignal signal;
+ signal.connect(callback);
// id found in map therefore we can call the callback immediately.
if (entry->mIsGroup)
{
- callback(id, entry->mGroupName, "", entry->mIsGroup, user_data);
+ signal(id, entry->mGroupName, "", entry->mIsGroup);
}
else
{
- callback(id, entry->mFirstName, entry->mLastName, entry->mIsGroup, user_data);
+ signal(id, entry->mFirstName, entry->mLastName, entry->mIsGroup);
}
}
else
@@ -597,12 +625,19 @@ void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callb
impl.mAskNameQueue.insert(id);
}
}
- impl.mReplyQueue.push_back(PendingReply(id, callback, user_data));
+ res = impl.addPending(id, callback);
}
+ return res;
+}
+
+boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, old_callback_t callback, void* user_data)
+{
+ return get(id, is_group, boost::bind(callback, _1, _2, _3, _4, user_data));
}
void LLCacheName::processPending()
{
+ LLMemType mt_pp(LLMemType::MTYPE_CACHE_PROCESS_PENDING);
const F32 SECS_BETWEEN_PROCESS = 0.1f;
if(!impl.mProcessTimer.checkExpirationAndReset(SECS_BETWEEN_PROCESS))
{
@@ -684,18 +719,19 @@ void LLCacheName::dumpStats()
<< " AskGroup=" << impl.mAskGroupQueue.size()
<< " Pending=" << impl.mPendingQueue.size()
<< " Reply=" << impl.mReplyQueue.size()
- << " Observers=" << impl.mObservers.size()
+// << " Observers=" << impl.mSignal.size()
<< llendl;
}
//static
std::string LLCacheName::getDefaultName()
{
- return CN_WAITING;
+ return sCacheName["waiting"];
}
void LLCacheName::Impl::processPendingAsks()
{
+ LLMemType mt_ppa(LLMemType::MTYPE_CACHE_PROCESS_PENDING_ASKS);
sendRequest(_PREHASH_UUIDNameRequest, mAskNameQueue);
sendRequest(_PREHASH_UUIDGroupNameRequest, mAskGroupQueue);
mAskNameQueue.clear();
@@ -704,50 +740,50 @@ void LLCacheName::Impl::processPendingAsks()
void LLCacheName::Impl::processPendingReplies()
{
- ReplyQueue::iterator it = mReplyQueue.begin();
- ReplyQueue::iterator end = mReplyQueue.end();
-
+ LLMemType mt_ppr(LLMemType::MTYPE_CACHE_PROCESS_PENDING_REPLIES);
// First call all the callbacks, because they might send messages.
- for(; it != end; ++it)
+ for(ReplyQueue::iterator it = mReplyQueue.begin(); it != mReplyQueue.end(); ++it)
{
- LLCacheNameEntry* entry = get_ptr_in_map(mCache, it->mID);
+ PendingReply* reply = *it;
+ LLCacheNameEntry* entry = get_ptr_in_map(mCache, reply->mID);
if(!entry) continue;
- if (it->mCallback)
+ if (!entry->mIsGroup)
{
- if (!entry->mIsGroup)
- {
- (it->mCallback)(it->mID,
- entry->mFirstName, entry->mLastName,
- FALSE, it->mData);
- }
- else {
- (it->mCallback)(it->mID,
- entry->mGroupName, "",
- TRUE, it->mData);
- }
+ (reply->mSignal)(reply->mID, entry->mFirstName, entry->mLastName, FALSE);
+ }
+ else
+ {
+ (reply->mSignal)(reply->mID, entry->mGroupName, "", TRUE);
}
}
// Forward on all replies, if needed.
ReplySender sender(mMsg);
- for (it = mReplyQueue.begin(); it != end; ++it)
+ for(ReplyQueue::iterator it = mReplyQueue.begin(); it != mReplyQueue.end(); ++it)
{
- LLCacheNameEntry* entry = get_ptr_in_map(mCache, it->mID);
+ PendingReply* reply = *it;
+ LLCacheNameEntry* entry = get_ptr_in_map(mCache, reply->mID);
if(!entry) continue;
- if (it->mHost.isOk())
+ if (reply->mHost.isOk())
{
- sender.send(it->mID, *entry, it->mHost);
+ sender.send(reply->mID, *entry, reply->mHost);
}
- it->done();
+ reply->done();
+ }
+
+ for(ReplyQueue::iterator it = mReplyQueue.begin(); it != mReplyQueue.end(); )
+ {
+ ReplyQueue::iterator curit = it++;
+ PendingReply* reply = *curit;
+ if (reply->isDone())
+ {
+ delete reply;
+ mReplyQueue.erase(curit);
+ }
}
-
- mReplyQueue.erase(
- remove_if(mReplyQueue.begin(), mReplyQueue.end(),
- std::mem_fun_ref(&PendingReply::isDone)),
- mReplyQueue.end());
}
@@ -785,18 +821,6 @@ void LLCacheName::Impl::sendRequest(
}
}
-void LLCacheName::Impl::notifyObservers(const LLUUID& id,
- const std::string& first, const std::string& last, BOOL is_group)
-{
- for (Observers::const_iterator i = mObservers.begin(),
- end = mObservers.end();
- i != end;
- ++i)
- {
- (**i)(id, first, last, is_group, NULL);
- }
-}
-
bool LLCacheName::Impl::isRequestPending(const LLUUID& id)
{
U32 now = (U32)time(NULL);
@@ -863,7 +887,7 @@ void LLCacheName::Impl::processUUIDRequest(LLMessageSystem* msg, bool isGroup)
}
}
- mReplyQueue.push_back(PendingReply(id, fromHost));
+ addPending(id, fromHost);
}
}
}
@@ -901,11 +925,14 @@ void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup)
if (!isGroup)
{
- notifyObservers(id, entry->mFirstName, entry->mLastName, FALSE);
+ mSignal(id, entry->mFirstName, entry->mLastName, FALSE);
+ std::string fullname = entry->mFirstName + " " + entry->mLastName;
+ mReverseCache[fullname] = id;
}
else
{
- notifyObservers(id, entry->mGroupName, "", TRUE);
+ mSignal(id, entry->mGroupName, "", TRUE);
+ mReverseCache[entry->mGroupName] = id;
}
}
}
diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h
index 2757b86a7c..111cc8b650 100644
--- a/indra/llmessage/llcachename.h
+++ b/indra/llmessage/llcachename.h
@@ -33,12 +33,22 @@
#ifndef LL_LLCACHENAME_H
#define LL_LLCACHENAME_H
+#include <boost/bind.hpp>
+#include <boost/signals2.hpp>
+
class LLMessageSystem;
class LLHost;
class LLUUID;
-// agent_id/group_id, first_name, last_name, is_group, user_data
-typedef void (*LLCacheNameCallback)(const LLUUID&, const std::string&, const std::string&, BOOL, void*);
+
+typedef boost::signals2::signal<void (const LLUUID& id,
+ const std::string& first_name,
+ const std::string& last_name,
+ BOOL is_group)> LLCacheNameSignal;
+typedef LLCacheNameSignal::slot_type LLCacheNameCallback;
+
+// Old callback with user data for compatability
+typedef void (*old_callback_t)(const LLUUID&, const std::string&, const std::string&, BOOL, void*);
// Here's the theory:
// If you request a name that isn't in the cache, it returns "waiting"
@@ -59,10 +69,7 @@ public:
// for simulators, this is the data server
void setUpstream(const LLHost& upstream_host);
- void addObserver(LLCacheNameCallback callback);
- void removeObserver(LLCacheNameCallback callback);
-
- void cancelCallback(const LLUUID& id, LLCacheNameCallback callback, void* user_data = NULL);
+ boost::signals2::connection addObserver(const LLCacheNameCallback& callback);
// janky old format. Remove after a while. Phoenix. 2008-01-30
void importFile(LLFILE* fp);
@@ -79,6 +86,10 @@ public:
BOOL getName(const LLUUID& id, std::string& first, std::string& last);
BOOL getFullName(const LLUUID& id, std::string& fullname);
+ // Reverse lookup of UUID from name
+ BOOL getUUID(const std::string& first, const std::string& last, LLUUID& id);
+ BOOL getUUID(const std::string& fullname, LLUUID& id);
+
// If available, this method copies the group name into the string
// provided. The caller must allocate at least
// DB_GROUP_NAME_BUF_SIZE characters. If not available, this
@@ -89,12 +100,10 @@ public:
// If the data is currently available, may call the callback immediatly
// otherwise, will request the data, and will call the callback when
// available. There is no garuntee the callback will ever be called.
- void get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data = NULL);
+ boost::signals2::connection get(const LLUUID& id, BOOL is_group, const LLCacheNameCallback& callback);
// LEGACY
- void getName(const LLUUID& id, LLCacheNameCallback callback, void* user_data = NULL)
- { get(id, FALSE, callback, user_data); }
-
+ boost::signals2::connection get(const LLUUID& id, BOOL is_group, old_callback_t callback, void* user_data);
// This method needs to be called from time to time to send out
// requests.
void processPending();
@@ -107,7 +116,8 @@ public:
void dumpStats(); // Dumps the sizes of the cache and associated queues.
static std::string getDefaultName();
-
+ static void LocalizeCacheName(std::string key, std::string value);
+ static std::map<std::string, std::string> sCacheName;
private:
class Impl;
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 1a432cd7df..024e17a777 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -89,6 +89,10 @@ S32 gCurlMultiCount = 0;
std::vector<LLMutex*> LLCurl::sSSLMutex;
std::string LLCurl::sCAPath;
std::string LLCurl::sCAFile;
+// Verify SSL certificates by default (matches libcurl default). The ability
+// to alter this flag is only to allow us to suppress verification if it's
+// broken for some reason.
+bool LLCurl::sSSLVerify = true;
//static
void LLCurl::setCAPath(const std::string& path)
@@ -103,6 +107,18 @@ void LLCurl::setCAFile(const std::string& file)
}
//static
+void LLCurl::setSSLVerify(bool verify)
+{
+ sSSLVerify = verify;
+}
+
+//static
+bool LLCurl::getSSLVerify()
+{
+ return sSSLVerify;
+}
+
+//static
std::string LLCurl::getVersionString()
{
return std::string(curl_version());
@@ -120,7 +136,7 @@ LLCurl::Responder::~Responder()
}
// virtual
-void LLCurl::Responder::error(
+void LLCurl::Responder::errorWithContent(
U32 status,
const std::string& reason,
const LLSD&)
@@ -131,7 +147,7 @@ void LLCurl::Responder::error(
// virtual
void LLCurl::Responder::error(U32 status, const std::string& reason)
{
- llinfos << status << ": " << reason << llendl;
+ llinfos << mURL << " [" << status << "]: " << reason << llendl;
}
// virtual
@@ -139,6 +155,11 @@ void LLCurl::Responder::result(const LLSD& content)
{
}
+void LLCurl::Responder::setURL(const std::string& url)
+{
+ mURL = url;
+}
+
// virtual
void LLCurl::Responder::completedRaw(
U32 status,
@@ -148,7 +169,11 @@ void LLCurl::Responder::completedRaw(
{
LLSD content;
LLBufferStream istr(channels, buffer.get());
- LLSDSerialize::fromXML(content, istr);
+ if (!LLSDSerialize::fromXML(content, istr))
+ {
+ llinfos << "Failed to deserialize LLSD. " << mURL << " [" << status << "]: " << reason << llendl;
+ }
+
completed(status, reason, content);
}
@@ -161,7 +186,7 @@ void LLCurl::Responder::completed(U32 status, const std::string& reason, const L
}
else
{
- error(status, reason, content);
+ errorWithContent(status, reason, content);
}
}
@@ -220,7 +245,7 @@ public:
U32 report(CURLcode);
void getTransferInfo(LLCurl::TransferInfo* info);
- void prepRequest(const std::string& url, ResponderPtr, bool post = false);
+ void prepRequest(const std::string& url, const std::vector<std::string>& headers, ResponderPtr, bool post = false);
const char* getErrorBuffer();
@@ -432,7 +457,9 @@ size_t curlHeaderCallback(void* data, size_t size, size_t nmemb, void* user_data
return n;
}
-void LLCurl::Easy::prepRequest(const std::string& url, ResponderPtr responder, bool post)
+void LLCurl::Easy::prepRequest(const std::string& url,
+ const std::vector<std::string>& headers,
+ ResponderPtr responder, bool post)
{
resetState();
@@ -454,7 +481,8 @@ void LLCurl::Easy::prepRequest(const std::string& url, ResponderPtr responder, b
setErrorBuffer();
setCA();
- setopt(CURLOPT_SSL_VERIFYPEER, true);
+ setopt(CURLOPT_SSL_VERIFYPEER, LLCurl::getSSLVerify());
+ setopt(CURLOPT_SSL_VERIFYHOST, LLCurl::getSSLVerify()? 2 : 0);
setopt(CURLOPT_TIMEOUT, CURL_REQUEST_TIMEOUT);
setoptString(CURLOPT_URL, url);
@@ -465,8 +493,13 @@ void LLCurl::Easy::prepRequest(const std::string& url, ResponderPtr responder, b
{
slist_append("Connection: keep-alive");
slist_append("Keep-alive: 300");
+ // Accept and other headers
+ for (std::vector<std::string>::const_iterator iter = headers.begin();
+ iter != headers.end(); ++iter)
+ {
+ slist_append((*iter).c_str());
+ }
}
- // *FIX: should have ACCEPT headers
}
////////////////////////////////////////////////////////////////////////////
@@ -676,15 +709,18 @@ LLCurlRequest::LLCurlRequest() :
mActiveMulti(NULL),
mActiveRequestCount(0)
{
+ mThreadID = LLThread::currentID();
}
LLCurlRequest::~LLCurlRequest()
{
+ llassert_always(mThreadID == LLThread::currentID());
for_each(mMultiSet.begin(), mMultiSet.end(), DeletePointer());
}
void LLCurlRequest::addMulti()
{
+ llassert_always(mThreadID == LLThread::currentID());
LLCurl::Multi* multi = new LLCurl::Multi();
mMultiSet.insert(multi);
mActiveMulti = multi;
@@ -714,17 +750,20 @@ bool LLCurlRequest::addEasy(LLCurl::Easy* easy)
void LLCurlRequest::get(const std::string& url, LLCurl::ResponderPtr responder)
{
- getByteRange(url, 0, -1, responder);
+ getByteRange(url, headers_t(), 0, -1, responder);
}
-bool LLCurlRequest::getByteRange(const std::string& url, S32 offset, S32 length, LLCurl::ResponderPtr responder)
+bool LLCurlRequest::getByteRange(const std::string& url,
+ const headers_t& headers,
+ S32 offset, S32 length,
+ LLCurl::ResponderPtr responder)
{
LLCurl::Easy* easy = allocEasy();
if (!easy)
{
return false;
}
- easy->prepRequest(url, responder);
+ easy->prepRequest(url, headers, responder);
easy->setopt(CURLOPT_HTTPGET, 1);
if (length > 0)
{
@@ -736,14 +775,17 @@ bool LLCurlRequest::getByteRange(const std::string& url, S32 offset, S32 length,
return res;
}
-bool LLCurlRequest::post(const std::string& url, const LLSD& data, LLCurl::ResponderPtr responder)
+bool LLCurlRequest::post(const std::string& url,
+ const headers_t& headers,
+ const LLSD& data,
+ LLCurl::ResponderPtr responder)
{
LLCurl::Easy* easy = allocEasy();
if (!easy)
{
return false;
}
- easy->prepRequest(url, responder);
+ easy->prepRequest(url, headers, responder);
LLSDSerialize::toXML(data, easy->getInput());
S32 bytes = easy->getInput().str().length();
@@ -763,6 +805,7 @@ bool LLCurlRequest::post(const std::string& url, const LLSD& data, LLCurl::Respo
// Note: call once per frame
S32 LLCurlRequest::process()
{
+ llassert_always(mThreadID == LLThread::currentID());
S32 res = 0;
for (curlmulti_set_t::iterator iter = mMultiSet.begin();
iter != mMultiSet.end(); )
@@ -782,6 +825,7 @@ S32 LLCurlRequest::process()
S32 LLCurlRequest::getQueued()
{
+ llassert_always(mThreadID == LLThread::currentID());
S32 queued = 0;
for (curlmulti_set_t::iterator iter = mMultiSet.begin();
iter != mMultiSet.end(); )
@@ -1002,7 +1046,7 @@ void LLCurl::initClass()
S32 mutex_count = CRYPTO_num_locks();
for (S32 i=0; i<mutex_count; i++)
{
- sSSLMutex.push_back(new LLMutex(gAPRPoolp));
+ sSSLMutex.push_back(new LLMutex(NULL));
}
CRYPTO_set_id_callback(&LLCurl::ssl_thread_id);
CRYPTO_set_locking_callback(&LLCurl::ssl_locking_callback);
@@ -1017,4 +1061,3 @@ void LLCurl::cleanupClass()
#endif
curl_global_cleanup();
}
-
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index ff63904c91..caf02cccd9 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -85,7 +85,7 @@ public:
return((200 <= status) && (status < 300));
}
- virtual void error(
+ virtual void errorWithContent(
U32 status,
const std::string& reason,
const LLSD& content);
@@ -120,8 +120,14 @@ public:
// of the header can be parsed. In the ::completed call above only the body is contained in the LLSD.
virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content);
+ // Used internally to set the url for debugging later.
+ void setURL(const std::string& url);
+
public: /* but not really -- don't touch this */
U32 mReferenceCount;
+
+ private:
+ std::string mURL;
};
typedef boost::intrusive_ptr<Responder> ResponderPtr;
@@ -152,6 +158,16 @@ public:
static const std::string& getCAPath() { return sCAPath; }
/**
+ * @ brief Set flag controlling whether to verify HTTPS certs.
+ */
+ static void setSSLVerify(bool verify);
+
+ /**
+ * @ brief Get flag controlling whether to verify HTTPS certs.
+ */
+ static bool getSSLVerify();
+
+ /**
* @ brief Initialize LLCurl class
*/
static void initClass();
@@ -176,6 +192,7 @@ public:
private:
static std::string sCAPath;
static std::string sCAFile;
+ static bool sSSLVerify;
};
namespace boost
@@ -188,12 +205,14 @@ namespace boost
class LLCurlRequest
{
public:
+ typedef std::vector<std::string> headers_t;
+
LLCurlRequest();
~LLCurlRequest();
void get(const std::string& url, LLCurl::ResponderPtr responder);
- bool getByteRange(const std::string& url, S32 offset, S32 length, LLCurl::ResponderPtr responder);
- bool post(const std::string& url, const LLSD& data, LLCurl::ResponderPtr responder);
+ bool getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, LLCurl::ResponderPtr responder);
+ bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder);
S32 process();
S32 getQueued();
@@ -207,6 +226,7 @@ private:
curlmulti_set_t mMultiSet;
LLCurl::Multi* mActiveMulti;
S32 mActiveRequestCount;
+ U32 mThreadID; // debug
};
class LLCurlEasyRequest
diff --git a/indra/llmessage/lldatapacker.cpp b/indra/llmessage/lldatapacker.cpp
index 1f52bf3a23..a1b5c7908d 100644
--- a/indra/llmessage/lldatapacker.cpp
+++ b/indra/llmessage/lldatapacker.cpp
@@ -55,6 +55,18 @@ LLDataPacker::LLDataPacker() : mPassFlags(0), mWriteEnabled(FALSE)
{
}
+//virtual
+void LLDataPacker::reset()
+{
+ llerrs << "Using unimplemented datapacker reset!" << llendl;
+}
+
+//virtual
+void LLDataPacker::dumpBufferToLog()
+{
+ llerrs << "dumpBufferToLog not implemented for this type!" << llendl;
+}
+
BOOL LLDataPacker::packFixed(const F32 value, const char *name,
const BOOL is_signed, const U32 int_bits, const U32 frac_bits)
{
diff --git a/indra/llmessage/lldatapacker.h b/indra/llmessage/lldatapacker.h
index 92bfec698b..b8d9fcbdd4 100644
--- a/indra/llmessage/lldatapacker.h
+++ b/indra/llmessage/lldatapacker.h
@@ -45,8 +45,9 @@ class LLDataPacker
public:
virtual ~LLDataPacker() {}
- virtual void reset() { llerrs << "Using unimplemented datapacker reset!" << llendl; };
- virtual void dumpBufferToLog() { llerrs << "dumpBufferToLog not implemented for this type!" << llendl; }
+ // Not required to override, but error to call?
+ virtual void reset();
+ virtual void dumpBufferToLog();
virtual BOOL hasNext() const = 0;
diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp
index dfdad59e2a..49dbdbd56d 100644
--- a/indra/llmessage/llhttpassetstorage.cpp
+++ b/indra/llmessage/llhttpassetstorage.cpp
@@ -626,7 +626,7 @@ LLSD LLHTTPAssetStorage::getPendingRequest(LLAssetStorage::ERequestType rt,
const request_list_t* running = getRunningList(rt);
if (running)
{
- LLSD sd = LLAssetStorage::getPendingRequest(running, asset_type, asset_id);
+ LLSD sd = LLAssetStorage::getPendingRequestImpl(running, asset_type, asset_id);
if (sd)
{
sd["is_running"] = true;
diff --git a/indra/llmessage/llhttpassetstorage.h b/indra/llmessage/llhttpassetstorage.h
index 5786c5df32..231437dad4 100644
--- a/indra/llmessage/llhttpassetstorage.h
+++ b/indra/llmessage/llhttpassetstorage.h
@@ -62,6 +62,8 @@ public:
virtual ~LLHTTPAssetStorage();
+ using LLAssetStorage::storeAssetData; // Unhiding virtuals...
+
virtual void storeAssetData(
const LLUUID& uuid,
LLAssetType::EType atype,
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index 8b90a4c5ca..dd56e18caf 100644
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -222,7 +222,7 @@ static void request(
LLPumpIO::chain_t chain;
LLURLRequest* req = new LLURLRequest(method, url);
- req->checkRootCertificate(true);
+ req->checkRootCertificate(LLCurl::getSSLVerify());
lldebugs << LLURLRequest::actionAsVerb(method) << " " << url << " "
@@ -265,6 +265,11 @@ static void request(
}
}
+ if (responder)
+ {
+ responder->setURL(url);
+ }
+
req->setCallback(new LLHTTPClientURLAdaptor(responder));
if (method == LLURLRequest::HTTP_POST && gMessageSystem)
diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp
index bbb56960df..9d3c83f828 100644
--- a/indra/llmessage/llhttpclientadapter.cpp
+++ b/indra/llmessage/llhttpclientadapter.cpp
@@ -1,10 +1,10 @@
/**
- * @file
+ * @file llhttpclientadapter.cpp
* @brief
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
- * Copyright (c) 2001-2009, Linden Research, Inc.
+ * Copyright (c) 2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -12,12 +12,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
diff --git a/indra/llmessage/llhttpclientadapter.h b/indra/llmessage/llhttpclientadapter.h
index d5f3aeaf2c..a205a2f260 100644
--- a/indra/llmessage/llhttpclientadapter.h
+++ b/indra/llmessage/llhttpclientadapter.h
@@ -1,10 +1,10 @@
/**
- * @file
+ * @file llhttpclientadepter.h
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2001-2008, Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -12,12 +12,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
@@ -33,7 +34,7 @@
#define LL_HTTPCLIENTADAPTER_H
#include "llhttpclientinterface.h"
-#include "llmemory.h" // LLSingleton<>
+#include "llsingleton.h" // LLSingleton<>
class LLHTTPClientAdapter : public LLHTTPClientInterface, public LLSingleton<LLHTTPClientAdapter>
{
diff --git a/indra/llmessage/llhttpclientinterface.h b/indra/llmessage/llhttpclientinterface.h
index 1f13d46447..085a59cf27 100644
--- a/indra/llmessage/llhttpclientinterface.h
+++ b/indra/llmessage/llhttpclientinterface.h
@@ -1,10 +1,10 @@
/**
- * @file
+ * @file llhttpclientinterface.h
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2001-2008, Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -12,12 +12,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
diff --git a/indra/llmessage/llhttpnode.cpp b/indra/llmessage/llhttpnode.cpp
index 2ba900a533..440b91fcfa 100644
--- a/indra/llmessage/llhttpnode.cpp
+++ b/indra/llmessage/llhttpnode.cpp
@@ -98,19 +98,19 @@ namespace {
}
// virtual
-LLSD LLHTTPNode::get() const
+LLSD LLHTTPNode::simpleGet() const
{
throw NotImplemented();
}
// virtual
-LLSD LLHTTPNode::put(const LLSD& input) const
+LLSD LLHTTPNode::simplePut(const LLSD& input) const
{
throw NotImplemented();
}
// virtual
-LLSD LLHTTPNode::post(const LLSD& input) const
+LLSD LLHTTPNode::simplePost(const LLSD& input) const
{
throw NotImplemented();
}
@@ -121,7 +121,7 @@ void LLHTTPNode::get(LLHTTPNode::ResponsePtr response, const LLSD& context) cons
{
try
{
- response->result(get());
+ response->result(simpleGet());
}
catch (NotImplemented)
{
@@ -134,7 +134,7 @@ void LLHTTPNode::put(LLHTTPNode::ResponsePtr response, const LLSD& context, cons
{
try
{
- response->result(put(input));
+ response->result(simplePut(input));
}
catch (NotImplemented)
{
@@ -147,7 +147,7 @@ void LLHTTPNode::post(LLHTTPNode::ResponsePtr response, const LLSD& context, con
{
try
{
- response->result(post(input));
+ response->result(simplePost(input));
}
catch (NotImplemented)
{
@@ -160,7 +160,7 @@ void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) cons
{
try
{
- response->result(del(context));
+ response->result(simpleDel(context));
}
catch (NotImplemented)
{
@@ -170,7 +170,7 @@ void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) cons
}
// virtual
-LLSD LLHTTPNode::del(const LLSD&) const
+LLSD LLHTTPNode::simpleDel(const LLSD&) const
{
throw NotImplemented();
}
@@ -388,7 +388,7 @@ LLHTTPNode::Response::~Response()
{
}
-void LLHTTPNode::Response::status(S32 code)
+void LLHTTPNode::Response::statusUnknownError(S32 code)
{
status(code, "Unknown Error");
}
diff --git a/indra/llmessage/llhttpnode.h b/indra/llmessage/llhttpnode.h
index 17ffd66e8f..915aacb7cc 100644
--- a/indra/llmessage/llhttpnode.h
+++ b/indra/llmessage/llhttpnode.h
@@ -33,7 +33,8 @@
#ifndef LL_LLHTTPNODE_H
#define LL_LLHTTPNODE_H
-#include "llmemory.h"
+#include "llpointer.h"
+#include "llrefcount.h"
#include "llsd.h"
class LLChainIOFactory;
@@ -83,10 +84,10 @@ public:
//@{
public:
- virtual LLSD get() const;
- virtual LLSD put(const LLSD& input) const;
- virtual LLSD post(const LLSD& input) const;
- virtual LLSD del(const LLSD& context) const;
+ virtual LLSD simpleGet() const;
+ virtual LLSD simplePut(const LLSD& input) const;
+ virtual LLSD simplePost(const LLSD& input) const;
+ virtual LLSD simpleDel(const LLSD& context) const;
/**
* @brief Abstract Base Class declaring Response interface.
@@ -116,7 +117,7 @@ public:
/**
* @brief Return no body, just status code and 'UNKNOWN ERROR'.
*/
- virtual void status(S32 code);
+ virtual void statusUnknownError(S32 code);
virtual void notFound(const std::string& message);
virtual void notFound();
@@ -292,6 +293,7 @@ public:
void result(const LLSD& result);
void extendedResult(S32 code, const std::string& body, const LLSD& headers);
+
void status(S32 code, const std::string& message);
void print(std::ostream& out) const;
diff --git a/indra/llmessage/llhttpnodeadapter.h b/indra/llmessage/llhttpnodeadapter.h
index 08b5664162..7c3e9d81d1 100644
--- a/indra/llmessage/llhttpnodeadapter.h
+++ b/indra/llmessage/llhttpnodeadapter.h
@@ -3,26 +3,27 @@
* @brief Declaration of llhttpnode adapter classes
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
- *
+ *
* Copyright (c) 2009, Linden Research, Inc.
- *
+ *
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
- *
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
- *
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
- *
+ *
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
diff --git a/indra/llmessage/llinstantmessage.cpp b/indra/llmessage/llinstantmessage.cpp
index 3205ddfaeb..3da41939fa 100644
--- a/indra/llmessage/llinstantmessage.cpp
+++ b/indra/llmessage/llinstantmessage.cpp
@@ -40,8 +40,8 @@
#include "lluuid.h"
#include "llsd.h"
#include "llsdserialize.h"
-#include "llsdutil.h"
-#include "llmemory.h"
+#include "llsdutil_math.h"
+#include "llpointer.h"
#include "message.h"
#include "message.h"
diff --git a/indra/llmessage/llinstantmessage.h b/indra/llmessage/llinstantmessage.h
index 9ce6a10c80..272e753f3c 100644
--- a/indra/llmessage/llinstantmessage.h
+++ b/indra/llmessage/llinstantmessage.h
@@ -36,7 +36,8 @@
#include "llhost.h"
#include "lluuid.h"
#include "llsd.h"
-#include "llmemory.h"
+#include "llrefcount.h"
+#include "llpointer.h"
#include "v3math.h"
class LLMessageSystem;
diff --git a/indra/llmessage/lliobuffer.cpp b/indra/llmessage/lliobuffer.cpp
index 71c1df8f99..223a23949b 100644
--- a/indra/llmessage/lliobuffer.cpp
+++ b/indra/llmessage/lliobuffer.cpp
@@ -87,7 +87,7 @@ LLIOPipe::EStatus LLIOBuffer::seek(LLIOBuffer::EHead head, S64 delta)
{
case READ:
if(((delta >= 0) && ((mReadHead + delta) <= mWriteHead))
- || (delta < 0) && ((mReadHead + delta) >= mBuffer))
+ || ((delta < 0) && ((mReadHead + delta) >= mBuffer)))
{
mReadHead += delta;
status = STATUS_OK;
@@ -95,7 +95,7 @@ LLIOPipe::EStatus LLIOBuffer::seek(LLIOBuffer::EHead head, S64 delta)
break;
case WRITE:
if(((delta >= 0) && ((mWriteHead + delta) < (mBuffer + mBufferSize)))
- || (delta < 0) && ((mWriteHead + delta) > mReadHead))
+ || ((delta < 0) && ((mWriteHead + delta) > mReadHead)))
{
mWriteHead += delta;
status = STATUS_OK;
diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp
index 83dfa94f00..97134bd336 100644
--- a/indra/llmessage/lliohttpserver.cpp
+++ b/indra/llmessage/lliohttpserver.cpp
@@ -105,6 +105,7 @@ private:
// from LLHTTPNode::Response
virtual void result(const LLSD&);
virtual void extendedResult(S32 code, const std::string& body, const LLSD& headers);
+
virtual void status(S32 code, const std::string& message);
void nullPipe();
@@ -520,7 +521,7 @@ protected:
* seek orfor string assignment.
* @returns Returns true if a line was found.
*/
- bool readLine(
+ bool readHeaderLine(
const LLChannelDescriptors& channels,
buffer_ptr_t buffer,
U8* dest,
@@ -591,7 +592,7 @@ LLHTTPResponder::~LLHTTPResponder()
//lldebugs << "destroying LLHTTPResponder" << llendl;
}
-bool LLHTTPResponder::readLine(
+bool LLHTTPResponder::readHeaderLine(
const LLChannelDescriptors& channels,
buffer_ptr_t buffer,
U8* dest,
@@ -669,7 +670,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
#endif
PUMP_DEBUG;
- if(readLine(channels, buffer, (U8*)buf, len))
+ if(readHeaderLine(channels, buffer, (U8*)buf, len))
{
bool read_next_line = false;
bool parse_all = true;
@@ -733,7 +734,13 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
if(read_next_line)
{
len = HEADER_BUFFER_SIZE;
- readLine(channels, buffer, (U8*)buf, len);
+ if (!readHeaderLine(channels, buffer, (U8*)buf, len))
+ {
+ // Failed to read the header line, probably too long.
+ // readHeaderLine already marked the channel/buffer as bad.
+ keep_parsing = false;
+ break;
+ }
}
if(0 == len)
{
diff --git a/indra/llmessage/lliohttpserver.h b/indra/llmessage/lliohttpserver.h
index d1c9bdde85..e8e390f296 100644
--- a/indra/llmessage/lliohttpserver.h
+++ b/indra/llmessage/lliohttpserver.h
@@ -34,7 +34,6 @@
#ifndef LL_LLIOHTTPSERVER_H
#define LL_LLIOHTTPSERVER_H
-#include "llapr.h"
#include "llchainio.h"
#include "llhttpnode.h"
diff --git a/indra/llmessage/llmail.cpp b/indra/llmessage/llmail.cpp
index d52ff6c7e8..ce206d8d7d 100644
--- a/indra/llmessage/llmail.cpp
+++ b/indra/llmessage/llmail.cpp
@@ -265,7 +265,7 @@ std::string LLMail::buildSMTPTransaction(
// static
bool LLMail::send(
const std::string& header,
- const std::string& message,
+ const std::string& raw_message,
const char* from_address,
const char* to_address)
{
@@ -276,8 +276,20 @@ bool LLMail::send(
return false;
}
- // *FIX: this translation doesn't deal with a single period on a
- // line by itself.
+ // remove any "." SMTP commands to prevent injection (DEV-35777)
+ // we don't need to worry about "\r\n.\r\n" because of the
+ // "\n" --> "\n\n" conversion going into rfc2822_msg below
+ std::string message = raw_message;
+ std::string bad_string = "\n.\n";
+ std::string good_string = "\n..\n";
+ while (1)
+ {
+ int index = message.find(bad_string);
+ if (index == std::string::npos) break;
+ message.replace(index, bad_string.size(), good_string);
+ }
+
+ // convert all "\n" into "\r\n"
std::ostringstream rfc2822_msg;
for(U32 i = 0; i < message.size(); ++i)
{
diff --git a/indra/llmessage/llmessagesenderinterface.h b/indra/llmessage/llmessagesenderinterface.h
index 4082666339..af6733fa05 100644
--- a/indra/llmessage/llmessagesenderinterface.h
+++ b/indra/llmessage/llmessagesenderinterface.h
@@ -1,10 +1,10 @@
/**
- * @file
+ * @file llmessagesenderinterface.h
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2001-2008, Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -12,12 +12,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
diff --git a/indra/llmessage/llpartdata.cpp b/indra/llmessage/llpartdata.cpp
index 485bc6aa44..9376cde7b5 100644
--- a/indra/llmessage/llpartdata.cpp
+++ b/indra/llmessage/llpartdata.cpp
@@ -39,6 +39,8 @@
#include "v4coloru.h"
#include "llsdutil.h"
+#include "llsdutil_math.h"
+
const S32 PS_PART_DATA_BLOCK_SIZE = 4 + 2 + 4 + 4 + 2 + 2; // 18
diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp
index 3e3f0b37a7..5e9dfd81fa 100644
--- a/indra/llmessage/llpumpio.cpp
+++ b/indra/llmessage/llpumpio.cpp
@@ -444,11 +444,13 @@ void LLPumpIO::pump()
pump(DEFAULT_POLL_TIMEOUT);
}
+static LLFastTimer::DeclareTimer FTM_PUMP("Pump");
+
//timeout is in microseconds
void LLPumpIO::pump(const S32& poll_timeout)
{
LLMemType m1(LLMemType::MTYPE_IO_PUMP);
- LLFastTimer t1(LLFastTimer::FTM_PUMP);
+ LLFastTimer t1(FTM_PUMP);
//llinfos << "LLPumpIO::pump()" << llendl;
// Run any pending runners.
diff --git a/indra/llmessage/llregionflags.h b/indra/llmessage/llregionflags.h
index 232478577c..40e4a4268d 100644
--- a/indra/llmessage/llregionflags.h
+++ b/indra/llmessage/llregionflags.h
@@ -92,7 +92,7 @@ const U32 REGION_FLAGS_DENY_ANONYMOUS = (1 << 23);
const U32 REGION_FLAGS_ALLOW_PARCEL_CHANGES = (1 << 26);
-const U32 REGION_FLAGS_ABUSE_EMAIL_TO_ESTATE_OWNER = (1 << 27);
+// const U32 REGION_FLAGS_ABUSE_EMAIL_TO_ESTATE_OWNER = (1 << 27); // We no longer support ELAR
const U32 REGION_FLAGS_ALLOW_VOICE = (1 << 28);
diff --git a/indra/llmessage/llregionpresenceverifier.cpp b/indra/llmessage/llregionpresenceverifier.cpp
index 552cf4cbdb..b1868e6a00 100644
--- a/indra/llmessage/llregionpresenceverifier.cpp
+++ b/indra/llmessage/llregionpresenceverifier.cpp
@@ -1,17 +1,28 @@
/**
- * @file
+ * @file llregionpresenceverifier.cpp
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2008, Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
- * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
- * this source code is governed by the Linden Lab Source Code Disclosure
- * Agreement ("Agreement") previously entered between you and Linden
- * Lab. By accessing, using, copying, modifying or distributing this
- * software, you acknowledge that you have been informed of your
- * obligations under the Agreement and agree to abide by those obligations.
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
@@ -19,17 +30,48 @@
* $/LicenseInfo$
*/
+#include "linden_common.h"
+
#include "llregionpresenceverifier.h"
#include "llhttpclientinterface.h"
#include <sstream>
#include "net.h"
#include "message.h"
+namespace boost
+{
+ void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p)
+ {
+ ++p->mReferenceCount;
+ }
+
+ void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p)
+ {
+ if(p && 0 == --p->mReferenceCount)
+ {
+ delete p;
+ }
+ }
+};
+
+LLRegionPresenceVerifier::Response::~Response()
+{
+}
-LLRegionPresenceVerifier::RegionResponder::RegionResponder(ResponsePtr data) : mSharedData(data)
+LLRegionPresenceVerifier::RegionResponder::RegionResponder(const std::string&
+ uri,
+ ResponsePtr data,
+ S32 retry_count) :
+ mUri(uri),
+ mSharedData(data),
+ mRetryCount(retry_count)
{
}
+//virtual
+LLRegionPresenceVerifier::RegionResponder::~RegionResponder()
+{
+}
void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content)
{
@@ -38,30 +80,36 @@ void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content)
LLHost destination(host, port);
LLUUID id = content["region_id"];
- llinfos << "Verifying " << destination.getString() << " is region " << id << llendl;
+ lldebugs << "Verifying " << destination.getString() << " is region " << id << llendl;
std::stringstream uri;
uri << "http://" << destination.getString() << "/state/basic/";
- mSharedData->getHttpClient().get(uri.str(), new VerifiedDestinationResponder(mSharedData, content));
+ mSharedData->getHttpClient().get(
+ uri.str(),
+ new VerifiedDestinationResponder(mUri, mSharedData, content, mRetryCount));
}
-void LLRegionPresenceVerifier::RegionResponder::completed(
- U32 status,
- const std::string& reason,
- const LLSD& content)
+void LLRegionPresenceVerifier::RegionResponder::error(U32 status,
+ const std::string& reason)
{
- LLHTTPClient::Responder::completed(status, reason, content);
-
- mSharedData->onCompletedRegionRequest();
+ // TODO: babbage: distinguish between region presence service and
+ // region verification errors?
+ mSharedData->onRegionVerificationFailed();
}
-
-LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(ResponsePtr data, const LLSD& content) : mSharedData(data), mContent(content)
+LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(const std::string& uri, ResponsePtr data, const LLSD& content,
+ S32 retry_count):
+ mUri(uri),
+ mSharedData(data),
+ mContent(content),
+ mRetryCount(retry_count)
{
}
-
-
+//virtual
+LLRegionPresenceVerifier::VerifiedDestinationResponder::~VerifiedDestinationResponder()
+{
+}
void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD& content)
{
@@ -76,13 +124,14 @@ void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD&
{
mSharedData->onRegionVerified(mContent);
}
- else if (mSharedData->shouldRetry())
+ else if (mRetryCount > 0)
{
retry();
}
else
{
- llwarns << "Could not correctly look up region from region presence service. Region: " << mSharedData->getRegionUri() << llendl;
+ llwarns << "Simulator verification failed. Region: " << mUri << llendl;
+ mSharedData->onRegionVerificationFailed();
}
}
@@ -90,13 +139,21 @@ void LLRegionPresenceVerifier::VerifiedDestinationResponder::retry()
{
LLSD headers;
headers["Cache-Control"] = "no-cache, max-age=0";
- llinfos << "Requesting region information, get uncached for region " << mSharedData->getRegionUri() << llendl;
- mSharedData->decrementRetries();
- mSharedData->getHttpClient().get(mSharedData->getRegionUri(), new RegionResponder(mSharedData), headers);
+ llinfos << "Requesting region information, get uncached for region "
+ << mUri << llendl;
+ --mRetryCount;
+ mSharedData->getHttpClient().get(mUri, new RegionResponder(mUri, mSharedData, mRetryCount), headers);
}
void LLRegionPresenceVerifier::VerifiedDestinationResponder::error(U32 status, const std::string& reason)
{
- retry();
+ if(mRetryCount > 0)
+ {
+ retry();
+ }
+ else
+ {
+ llwarns << "Failed to contact simulator for verification. Region: " << mUri << llendl;
+ mSharedData->onRegionVerificationFailed();
+ }
}
-
diff --git a/indra/llmessage/llregionpresenceverifier.h b/indra/llmessage/llregionpresenceverifier.h
index d1de608ec6..f57a62a731 100644
--- a/indra/llmessage/llregionpresenceverifier.h
+++ b/indra/llmessage/llregionpresenceverifier.h
@@ -1,17 +1,28 @@
/**
- * @file
+ * @file llregionpresenceverifier.cpp
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2008, Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
- * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
- * this source code is governed by the Linden Lab Source Code Disclosure
- * Agreement ("Agreement") previously entered between you and Linden
- * Lab. By accessing, using, copying, modifying or distributing this
- * software, you acknowledge that you have been informed of your
- * obligations under the Agreement and agree to abide by those obligations.
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
@@ -26,7 +37,7 @@
#include "llhttpclient.h"
#include <string>
#include "llsd.h"
-#include <boost/shared_ptr.hpp>
+#include <boost/intrusive_ptr.hpp>
class LLHTTPClientInterface;
@@ -36,48 +47,58 @@ public:
class Response
{
public:
- virtual ~Response() {}
+ virtual ~Response() = 0;
virtual bool checkValidity(const LLSD& content) const = 0;
virtual void onRegionVerified(const LLSD& region_details) = 0;
-
- virtual void decrementRetries() = 0;
+ virtual void onRegionVerificationFailed() = 0;
virtual LLHTTPClientInterface& getHttpClient() = 0;
- virtual std::string getRegionUri() const = 0;
- virtual bool shouldRetry() const = 0;
- virtual void onCompletedRegionRequest() {}
+ public: /* but not really -- don't touch this */
+ U32 mReferenceCount;
};
- typedef boost::shared_ptr<Response> ResponsePtr;
+ typedef boost::intrusive_ptr<Response> ResponsePtr;
class RegionResponder : public LLHTTPClient::Responder
{
public:
- RegionResponder(ResponsePtr data);
+ RegionResponder(const std::string& uri, ResponsePtr data,
+ S32 retry_count);
+ virtual ~RegionResponder();
virtual void result(const LLSD& content);
- virtual void completed(
- U32 status,
- const std::string& reason,
- const LLSD& content);
+ virtual void error(U32 status, const std::string& reason);
private:
ResponsePtr mSharedData;
+ std::string mUri;
+ S32 mRetryCount;
};
class VerifiedDestinationResponder : public LLHTTPClient::Responder
{
public:
- VerifiedDestinationResponder(ResponsePtr data, const LLSD& content);
+ VerifiedDestinationResponder(const std::string& uri, ResponsePtr data,
+ const LLSD& content, S32 retry_count);
+ virtual ~VerifiedDestinationResponder();
virtual void result(const LLSD& content);
+
virtual void error(U32 status, const std::string& reason);
+
private:
void retry();
ResponsePtr mSharedData;
LLSD mContent;
+ std::string mUri;
+ S32 mRetryCount;
};
};
+namespace boost
+{
+ void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p);
+ void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p);
+};
#endif //LL_LLREGIONPRESENCEVERIFIER_H
diff --git a/indra/llmessage/llsdappservices.cpp b/indra/llmessage/llsdappservices.cpp
index dc135c51b2..b87c0cd6b7 100644
--- a/indra/llmessage/llsdappservices.cpp
+++ b/indra/llmessage/llsdappservices.cpp
@@ -56,7 +56,7 @@ public:
desc.source(__FILE__, __LINE__);
}
- virtual LLSD get() const
+ virtual LLSD simpleGet() const
{
LLSD result;
LLApp* app = LLApp::instance();
@@ -82,7 +82,7 @@ public:
desc.source(__FILE__, __LINE__);
}
- virtual LLSD get() const
+ virtual LLSD simpleGet() const
{
return LLApp::instance()->getOptionData(
LLApp::PRIORITY_RUNTIME_OVERRIDE);
diff --git a/indra/llmessage/llsdhttpserver.cpp b/indra/llmessage/llsdhttpserver.cpp
index 00fc170c59..704c375ffc 100644
--- a/indra/llmessage/llsdhttpserver.cpp
+++ b/indra/llmessage/llsdhttpserver.cpp
@@ -62,7 +62,7 @@ public:
desc.source(__FILE__, __LINE__);
}
- virtual LLSD get() const
+ virtual LLSD simpleGet() const
{
LLSD result = "hello";
return result;
@@ -86,7 +86,7 @@ public:
desc.source(__FILE__, __LINE__);
}
- virtual LLSD post(const LLSD& params) const
+ virtual LLSD simplePost(const LLSD& params) const
{
return params;
}
diff --git a/indra/llmessage/llsdmessage.cpp b/indra/llmessage/llsdmessage.cpp
new file mode 100644
index 0000000000..2cb742e261
--- /dev/null
+++ b/indra/llmessage/llsdmessage.cpp
@@ -0,0 +1,153 @@
+/**
+ * @file llsdmessage.cpp
+ * @author Nat Goodspeed
+ * @date 2008-10-31
+ * @brief Implementation for llsdmessage.
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * Copyright (c) 2008, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if LL_WINDOWS
+#pragma warning (disable : 4675) // "resolved by ADL" -- just as I want!
+#endif
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llsdmessage.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llevents.h"
+#include "llsdserialize.h"
+#include "llhttpclient.h"
+#include "llmessageconfig.h"
+#include "llhost.h"
+#include "message.h"
+#include "llsdutil.h"
+
+// Declare a static LLSDMessage instance to ensure that we have a listener as
+// soon as someone tries to post on our canonical LLEventPump name.
+static LLSDMessage httpListener;
+
+LLSDMessage::LLSDMessage():
+ // Instantiating our own local LLEventPump with a string name the
+ // constructor is NOT allowed to tweak is a way of ensuring Singleton
+ // semantics: attempting to instantiate a second LLSDMessage object would
+ // throw LLEventPump::DupPumpName.
+ mEventPump("LLHTTPClient")
+{
+ mEventPump.listen("self", boost::bind(&LLSDMessage::httpListener, this, _1));
+}
+
+bool LLSDMessage::httpListener(const LLSD& request)
+{
+ // Extract what we want from the request object. We do it all up front
+ // partly to document what we expect.
+ LLSD::String url(request["url"]);
+ LLSD payload(request["payload"]);
+ LLSD::String reply(request["reply"]);
+ LLSD::String error(request["error"]);
+ LLSD::Real timeout(request["timeout"]);
+ // If the LLSD doesn't even have a "url" key, we doubt it was intended for
+ // this listener.
+ if (url.empty())
+ {
+ std::ostringstream out;
+ out << "request event without 'url' key to '" << mEventPump.getName() << "'";
+ throw ArgError(out.str());
+ }
+ // Establish default timeout. This test relies on LLSD::asReal() returning
+ // exactly 0.0 for an undef value.
+ if (! timeout)
+ {
+ timeout = HTTP_REQUEST_EXPIRY_SECS;
+ }
+ LLHTTPClient::post(url, payload,
+ new LLSDMessage::EventResponder(LLEventPumps::instance(),
+ request,
+ url, "POST", reply, error),
+ LLSD(), // headers
+ timeout);
+ return false;
+}
+
+void LLSDMessage::EventResponder::result(const LLSD& data)
+{
+ // If our caller passed an empty replyPump name, they're not
+ // listening: this is a fire-and-forget message. Don't bother posting
+ // to the pump whose name is "".
+ if (! mReplyPump.empty())
+ {
+ LLSD response(data);
+ mReqID.stamp(response);
+ mPumps.obtain(mReplyPump).post(response);
+ }
+ else // default success handling
+ {
+ LL_INFOS("LLSDMessage::EventResponder")
+ << "'" << mMessage << "' to '" << mTarget << "' succeeded"
+ << LL_ENDL;
+ }
+}
+
+void LLSDMessage::EventResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content)
+{
+ // If our caller passed an empty errorPump name, they're not
+ // listening: "default error handling is acceptable." Only post to an
+ // explicit pump name.
+ if (! mErrorPump.empty())
+ {
+ LLSD info(mReqID.makeResponse());
+ info["target"] = mTarget;
+ info["message"] = mMessage;
+ info["status"] = LLSD::Integer(status);
+ info["reason"] = reason;
+ info["content"] = content;
+ mPumps.obtain(mErrorPump).post(info);
+ }
+ else // default error handling
+ {
+ // convention seems to be to use llinfos, but that seems a bit casual?
+ LL_WARNS("LLSDMessage::EventResponder")
+ << "'" << mMessage << "' to '" << mTarget
+ << "' failed with code " << status << ": " << reason << '\n'
+ << ll_pretty_print_sd(content)
+ << LL_ENDL;
+ }
+}
+
+LLSDMessage::ResponderAdapter::ResponderAdapter(LLHTTPClient::ResponderPtr responder,
+ const std::string& name):
+ mResponder(responder),
+ mReplyPump(name + ".reply", true), // tweak name for uniqueness
+ mErrorPump(name + ".error", true)
+{
+ mReplyPump.listen("self", boost::bind(&ResponderAdapter::listener, this, _1, true));
+ mErrorPump.listen("self", boost::bind(&ResponderAdapter::listener, this, _1, false));
+}
+
+bool LLSDMessage::ResponderAdapter::listener(const LLSD& payload, bool success)
+{
+ if (success)
+ {
+ mResponder->result(payload);
+ }
+ else
+ {
+ mResponder->errorWithContent(payload["status"].asInteger(), payload["reason"], payload["content"]);
+ }
+
+ /*---------------- MUST BE LAST STATEMENT BEFORE RETURN ----------------*/
+ delete this;
+ // Destruction of mResponder will usually implicitly free its referent as well
+ /*------------------------- NOTHING AFTER THIS -------------------------*/
+ return false;
+}
+
+void LLSDMessage::link()
+{
+}
diff --git a/indra/llmessage/llsdmessage.h b/indra/llmessage/llsdmessage.h
new file mode 100644
index 0000000000..6ee00fd41d
--- /dev/null
+++ b/indra/llmessage/llsdmessage.h
@@ -0,0 +1,149 @@
+/**
+ * @file llsdmessage.h
+ * @author Nat Goodspeed
+ * @date 2008-10-30
+ * @brief API intended to unify sending capability, UDP and TCP messages:
+ * https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * Copyright (c) 2008, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLSDMESSAGE_H)
+#define LL_LLSDMESSAGE_H
+
+#include "llerror.h" // LOG_CLASS()
+#include "llevents.h" // LLEventPumps
+#include "llhttpclient.h"
+#include <string>
+#include <stdexcept>
+
+class LLSD;
+
+/**
+ * Class managing the messaging API described in
+ * https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes
+ */
+class LLSDMessage
+{
+ LOG_CLASS(LLSDMessage);
+
+public:
+ LLSDMessage();
+
+ /// Exception if you specify arguments badly
+ struct ArgError: public std::runtime_error
+ {
+ ArgError(const std::string& what):
+ std::runtime_error(std::string("ArgError: ") + what) {}
+ };
+
+ /**
+ * The response idiom used by LLSDMessage -- LLEventPump names on which to
+ * post reply or error -- is designed for the case in which your
+ * reply/error handlers are methods on the same class as the method
+ * sending the message. Any state available to the sending method that
+ * must be visible to the reply/error methods can conveniently be stored
+ * on that class itself, if it's not already.
+ *
+ * The LLHTTPClient::Responder idiom requires a separate instance of a
+ * separate class so that it can dispatch to the code of interest by
+ * calling canonical virtual methods. Interesting state must be copied
+ * into that new object.
+ *
+ * With some trepidation, because existing response code is packaged in
+ * LLHTTPClient::Responder subclasses, we provide this adapter class
+ * <i>for transitional purposes only.</i> Instantiate a new heap
+ * ResponderAdapter with your new LLHTTPClient::ResponderPtr. Pass
+ * ResponderAdapter::getReplyName() and/or getErrorName() in your
+ * LLSDMessage (or LLViewerRegion::getCapAPI()) request event. The
+ * ResponderAdapter will call the appropriate Responder method, then
+ * @c delete itself.
+ */
+ class ResponderAdapter
+ {
+ public:
+ /**
+ * Bind the new LLHTTPClient::Responder subclass instance.
+ *
+ * Passing the constructor a name other than the default is only
+ * interesting if you suspect some usage will lead to an exception or
+ * log message.
+ */
+ ResponderAdapter(LLHTTPClient::ResponderPtr responder,
+ const std::string& name="ResponderAdapter");
+
+ /// EventPump name on which LLSDMessage should post reply event
+ std::string getReplyName() const { return mReplyPump.getName(); }
+ /// EventPump name on which LLSDMessage should post error event
+ std::string getErrorName() const { return mErrorPump.getName(); }
+
+ private:
+ // We have two different LLEventStreams, though we route them both to
+ // the same listener, so that we can bind an extra flag identifying
+ // which case (reply or error) reached that listener.
+ bool listener(const LLSD&, bool success);
+
+ LLHTTPClient::ResponderPtr mResponder;
+ LLEventStream mReplyPump, mErrorPump;
+ };
+
+ /**
+ * Force our implementation file to be linked with caller. The .cpp file
+ * contains a static instance of this class, which must be linked into the
+ * executable to support the canonical listener. But since the primary
+ * interface to that static instance is via a named LLEventPump rather
+ * than by direct reference, the linker doesn't necessarily perceive the
+ * necessity to bring in the translation unit. Referencing this dummy
+ * method forces the issue.
+ */
+ static void link();
+
+private:
+ friend class LLCapabilityListener;
+ /// Responder used for internal purposes by LLSDMessage and
+ /// LLCapabilityListener. Others should use higher-level APIs.
+ class EventResponder: public LLHTTPClient::Responder
+ {
+ public:
+ /**
+ * LLHTTPClient::Responder that dispatches via named LLEventPump instances.
+ * We bind LLEventPumps, even though it's an LLSingleton, for testability.
+ * We bind the string names of the desired LLEventPump instances rather
+ * than actually obtain()ing them so we only obtain() the one we're going
+ * to use. If the caller doesn't bother to listen() on it, the other pump
+ * may never materialize at all.
+ * @a target and @a message are only to clarify error processing.
+ * For a capability message, @a target should be the region description,
+ * @a message should be the capability name.
+ * For a service with a visible URL, pass the URL as @a target and the HTTP verb
+ * (e.g. "POST") as @a message.
+ */
+ EventResponder(LLEventPumps& pumps,
+ const LLSD& request,
+ const std::string& target, const std::string& message,
+ const std::string& replyPump, const std::string& errorPump):
+ mPumps(pumps),
+ mReqID(request),
+ mTarget(target),
+ mMessage(message),
+ mReplyPump(replyPump),
+ mErrorPump(errorPump)
+ {}
+
+ virtual void result(const LLSD& data);
+ virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content);
+
+ private:
+ LLEventPumps& mPumps;
+ LLReqID mReqID;
+ const std::string mTarget, mMessage, mReplyPump, mErrorPump;
+ };
+
+private:
+ bool httpListener(const LLSD&);
+ LLEventStream mEventPump;
+};
+
+#endif /* ! defined(LL_LLSDMESSAGE_H) */
diff --git a/indra/llmessage/llsdmessagebuilder.cpp b/indra/llmessage/llsdmessagebuilder.cpp
index 21937f022f..6e41b03895 100755
--- a/indra/llmessage/llsdmessagebuilder.cpp
+++ b/indra/llmessage/llsdmessagebuilder.cpp
@@ -37,6 +37,7 @@
#include "llmessagetemplate.h"
#include "llquaternion.h"
#include "llsdutil.h"
+#include "llsdutil_math.h"
#include "llsdserialize.h"
#include "u64.h"
#include "v3dmath.h"
diff --git a/indra/llmessage/llsdmessagereader.cpp b/indra/llmessage/llsdmessagereader.cpp
index e699ec9e28..845a12d23b 100755
--- a/indra/llmessage/llsdmessagereader.cpp
+++ b/indra/llmessage/llsdmessagereader.cpp
@@ -38,6 +38,7 @@
#include "llsdmessagebuilder.h"
#include "llsdutil.h"
+#include "llsdutil_math.h"
#include "v3math.h"
#include "v4math.h"
#include "v3dmath.h"
diff --git a/indra/llmessage/llstoredmessage.cpp b/indra/llmessage/llstoredmessage.cpp
index 615eff405d..d6b2f45d04 100644
--- a/indra/llmessage/llstoredmessage.cpp
+++ b/indra/llmessage/llstoredmessage.cpp
@@ -1,10 +1,10 @@
/**
- * @file
+ * @file llstoredmessage.cpp
* @brief
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
- * Copyright (c) 2001-2009, Linden Research, Inc.
+ * Copyright (c) 2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
diff --git a/indra/llmessage/llstoredmessage.h b/indra/llmessage/llstoredmessage.h
index e817f19bd2..359e4c5aea 100644
--- a/indra/llmessage/llstoredmessage.h
+++ b/indra/llmessage/llstoredmessage.h
@@ -1,10 +1,10 @@
/**
- * @file
+ * @file llstoredmessage.h
* @brief
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
- * Copyright (c) 2001-2009, Linden Research, Inc.
+ * Copyright (c) 2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
diff --git a/indra/llmessage/lltemplatemessagebuilder.cpp b/indra/llmessage/lltemplatemessagebuilder.cpp
index e6419807ff..6400310c46 100644
--- a/indra/llmessage/lltemplatemessagebuilder.cpp
+++ b/indra/llmessage/lltemplatemessagebuilder.cpp
@@ -728,9 +728,9 @@ static S32 buildBlock(U8* buffer, S32 buffer_size, const LLMessageBlock* templat
// out gracefully from this function. XXXTBD
llerrs << "buildBlock failed. "
<< "Attempted to pack "
- << result + mvci.getSize()
+ << (result + mvci.getSize())
<< " bytes into a buffer with size "
- << buffer_size << "." << llendl
+ << buffer_size << "." << llendl;
}
}
}
diff --git a/indra/llmessage/lltemplatemessagedispatcher.cpp b/indra/llmessage/lltemplatemessagedispatcher.cpp
index 3bbf3a058d..ab1beb362b 100644
--- a/indra/llmessage/lltemplatemessagedispatcher.cpp
+++ b/indra/llmessage/lltemplatemessagedispatcher.cpp
@@ -3,26 +3,27 @@
* @brief LLTemplateMessageDispatcher class
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
- *
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
- *
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
- *
+ *
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
diff --git a/indra/llmessage/lltemplatemessagedispatcher.h b/indra/llmessage/lltemplatemessagedispatcher.h
index b1e74f47bb..fa861e4e42 100644
--- a/indra/llmessage/lltemplatemessagedispatcher.h
+++ b/indra/llmessage/lltemplatemessagedispatcher.h
@@ -3,26 +3,27 @@
* @brief LLTemplateMessageDispatcher class
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
- *
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
- *
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
- *
+ *
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp
index 80ea6ce96b..6682575ca5 100644
--- a/indra/llmessage/lltemplatemessagereader.cpp
+++ b/indra/llmessage/lltemplatemessagereader.cpp
@@ -531,6 +531,8 @@ void LLTemplateMessageReader::logRanOffEndOfPacket( const LLHost& host, const S3
gMessageSystem->callExceptionFunc(MX_RAN_OFF_END_OF_PACKET);
}
+static LLFastTimer::DeclareTimer FTM_PROCESS_MESSAGES("Process Messages");
+
// decode a given message
BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender )
{
@@ -676,12 +678,7 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender
// default to 0s.
U32 size = mvci.getSize();
- std::vector<U8> data(size);
- if(size)
- {
- // Nonsense test to get past GCC 4.3.1 bug with -O3
- memset(&(data[0]), 0, size);
- }
+ std::vector<U8> data(size, 0);
cur_data_block->addData(mvci.getName(), &(data[0]),
size, mvci.getType());
}
@@ -714,7 +711,7 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender
}
{
- LLFastTimer t(LLFastTimer::FTM_PROCESS_MESSAGES);
+ LLFastTimer t(FTM_PROCESS_MESSAGES);
if( !mCurrentRMessageTemplate->callHandlerFunc(gMessageSystem) )
{
llwarns << "Message from " << sender << " with no handler function received: " << mCurrentRMessageTemplate->mName << llendl;
diff --git a/indra/llmessage/llthrottle.cpp b/indra/llmessage/llthrottle.cpp
index 70279a3c62..0872efba50 100644
--- a/indra/llmessage/llthrottle.cpp
+++ b/indra/llmessage/llthrottle.cpp
@@ -265,6 +265,31 @@ BOOL LLThrottleGroup::setNominalBPS(F32* throttle_vec)
return changed;
}
+// Return bits available in the channel
+S32 LLThrottleGroup::getAvailable(S32 throttle_cat)
+{
+ S32 retval = 0;
+
+ F32 category_bps = mCurrentBPS[throttle_cat];
+ F32 lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME;
+
+ // use a temporary bits_available
+ // since we don't want to change mBitsAvailable every time
+ F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat]);
+ F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time);
+
+ if (bits_available >= lookahead_bits)
+ {
+ retval = (S32) gThrottleMaximumBPS[throttle_cat];
+ }
+ else
+ {
+ retval = (S32) bits_available;
+ }
+
+ return retval;
+}
+
BOOL LLThrottleGroup::checkOverflow(S32 throttle_cat, F32 bits)
{
diff --git a/indra/llmessage/llthrottle.h b/indra/llmessage/llthrottle.h
index 7d1679beb2..47a7c653b2 100644
--- a/indra/llmessage/llthrottle.h
+++ b/indra/llmessage/llthrottle.h
@@ -84,6 +84,8 @@ public:
BOOL dynamicAdjust(); // Shift bandwidth from idle channels to busy channels, TRUE if adjustment occurred
BOOL setNominalBPS(F32* throttle_vec); // TRUE if any value was different, resets adjustment system if was different
+ S32 getAvailable(S32 throttle_cat); // Return bits available in the channel
+
void packThrottle(LLDataPacker &dp) const;
void unpackThrottle(LLDataPacker &dp);
public:
diff --git a/indra/llmessage/lltransfersourceasset.cpp b/indra/llmessage/lltransfersourceasset.cpp
index a4d59275b9..7332f5c954 100644
--- a/indra/llmessage/lltransfersourceasset.cpp
+++ b/indra/llmessage/lltransfersourceasset.cpp
@@ -264,16 +264,16 @@ bool is_asset_fetch_by_id_allowed(LLAssetType::EType type)
bool rv = false;
switch(type)
{
- case LLAssetType::AT_SOUND:
- case LLAssetType::AT_LANDMARK:
- case LLAssetType::AT_CLOTHING:
- case LLAssetType::AT_BODYPART:
- case LLAssetType::AT_ANIMATION:
- case LLAssetType::AT_GESTURE:
- rv = true;
- break;
- default:
- break;
+ case LLAssetType::AT_SOUND:
+ case LLAssetType::AT_LANDMARK:
+ case LLAssetType::AT_CLOTHING:
+ case LLAssetType::AT_BODYPART:
+ case LLAssetType::AT_ANIMATION:
+ case LLAssetType::AT_GESTURE:
+ rv = true;
+ break;
+ default:
+ break;
}
return rv;
}
@@ -284,18 +284,20 @@ bool is_asset_id_knowable(LLAssetType::EType type)
bool rv = false;
switch(type)
{
- case LLAssetType::AT_TEXTURE:
- case LLAssetType::AT_SOUND:
- case LLAssetType::AT_LANDMARK:
- case LLAssetType::AT_CLOTHING:
- case LLAssetType::AT_NOTECARD:
- case LLAssetType::AT_BODYPART:
- case LLAssetType::AT_ANIMATION:
- case LLAssetType::AT_GESTURE:
- rv = true;
- break;
- default:
- break;
+ case LLAssetType::AT_TEXTURE:
+ case LLAssetType::AT_SOUND:
+ case LLAssetType::AT_LANDMARK:
+ case LLAssetType::AT_CLOTHING:
+ case LLAssetType::AT_NOTECARD:
+ case LLAssetType::AT_BODYPART:
+ case LLAssetType::AT_ANIMATION:
+ case LLAssetType::AT_GESTURE:
+ case LLAssetType::AT_LINK:
+ case LLAssetType::AT_LINK_FOLDER:
+ rv = true;
+ break;
+ default:
+ break;
}
return rv;
}
diff --git a/indra/llmessage/lltrustedmessageservice.cpp b/indra/llmessage/lltrustedmessageservice.cpp
index c1a6c437a7..505ece57b0 100644
--- a/indra/llmessage/lltrustedmessageservice.cpp
+++ b/indra/llmessage/lltrustedmessageservice.cpp
@@ -3,26 +3,27 @@
* @brief LLTrustedMessageService implementation
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
- *
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
- *
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
- *
+ *
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
diff --git a/indra/llmessage/lltrustedmessageservice.h b/indra/llmessage/lltrustedmessageservice.h
index bc824565f1..dc37702471 100644
--- a/indra/llmessage/lltrustedmessageservice.h
+++ b/indra/llmessage/lltrustedmessageservice.h
@@ -3,26 +3,27 @@
* @brief LLTrustedMessageService class
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
- *
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
- *
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
- *
+ *
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index 3ab8057abb..4e7ceff984 100644
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -51,6 +51,7 @@ static const U32 HTTP_STATUS_PIPE_ERROR = 499;
* String constants
*/
const std::string CONTEXT_DEST_URI_SD_LABEL("dest_uri");
+const std::string CONTEXT_TRANSFERED_BYTES("transfered_bytes");
static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user);
@@ -162,6 +163,7 @@ void LLURLRequest::setBodyLimit(U32 size)
void LLURLRequest::checkRootCertificate(bool check)
{
mDetail->mCurlRequest->setopt(CURLOPT_SSL_VERIFYPEER, (check? TRUE : FALSE));
+ mDetail->mCurlRequest->setopt(CURLOPT_SSL_VERIFYHOST, (check? 2 : 0));
mDetail->mCurlRequest->setoptString(CURLOPT_ENCODING, "");
}
@@ -247,7 +249,29 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
PUMP_DEBUG;
LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
//llinfos << "LLURLRequest::process_impl()" << llendl;
- if(!buffer) return STATUS_ERROR;
+ if (!buffer) return STATUS_ERROR;
+
+ // we're still waiting or prcessing, check how many
+ // bytes we have accumulated.
+ const S32 MIN_ACCUMULATION = 100000;
+ if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION))
+ {
+ // This is a pretty sloppy calculation, but this
+ // tries to make the gross assumption that if data
+ // is coming in at 56kb/s, then this transfer will
+ // probably succeed. So, if we're accumlated
+ // 100,000 bytes (MIN_ACCUMULATION) then let's
+ // give this client another 2s to complete.
+ const F32 TIMEOUT_ADJUSTMENT = 2.0f;
+ mDetail->mByteAccumulator = 0;
+ pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT);
+ lldebugs << "LLURLRequest adjustTimeoutSeconds for request: " << mDetail->mURL << llendl;
+ if (mState == STATE_INITIALIZED)
+ {
+ llinfos << "LLURLRequest adjustTimeoutSeconds called during upload" << llendl;
+ }
+ }
+
switch(mState)
{
case STATE_INITIALIZED:
@@ -286,27 +310,14 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
bool newmsg = mDetail->mCurlRequest->getResult(&result);
if(!newmsg)
{
- // we're still waiting or prcessing, check how many
- // bytes we have accumulated.
- const S32 MIN_ACCUMULATION = 100000;
- if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION))
- {
- // This is a pretty sloppy calculation, but this
- // tries to make the gross assumption that if data
- // is coming in at 56kb/s, then this transfer will
- // probably succeed. So, if we're accumlated
- // 100,000 bytes (MIN_ACCUMULATION) then let's
- // give this client another 2s to complete.
- const F32 TIMEOUT_ADJUSTMENT = 2.0f;
- mDetail->mByteAccumulator = 0;
- pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT);
- }
-
// keep processing
break;
}
mState = STATE_HAVE_RESPONSE;
+ context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+ context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+ lldebugs << this << "Setting context to " << context << llendl;
switch(result)
{
case CURLE_OK:
@@ -353,10 +364,16 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
// we already stuffed everything into channel in in the curl
// callback, so we are done.
eos = true;
+ context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+ context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+ lldebugs << this << "Setting context to " << context << llendl;
return STATUS_DONE;
default:
PUMP_DEBUG;
+ context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+ context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+ lldebugs << this << "Setting context to " << context << llendl;
return STATUS_ERROR;
}
}
@@ -369,6 +386,8 @@ void LLURLRequest::initialize()
mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);
mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this);
mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this);
+ mRequestTransferedBytes = 0;
+ mResponseTransferedBytes = 0;
}
bool LLURLRequest::configure()
@@ -471,6 +490,7 @@ size_t LLURLRequest::downCallback(
req->mDetail->mChannels.out(),
(U8*)data,
bytes);
+ req->mResponseTransferedBytes += bytes;
req->mDetail->mByteAccumulator += bytes;
return bytes;
}
@@ -494,6 +514,7 @@ size_t LLURLRequest::upCallback(
req->mDetail->mLastRead,
(U8*)data,
bytes);
+ req->mRequestTransferedBytes += bytes;
return bytes;
}
diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h
index 86ef71f085..cb3c466440 100644
--- a/indra/llmessage/llurlrequest.h
+++ b/indra/llmessage/llurlrequest.h
@@ -45,6 +45,12 @@
#include "llchainio.h"
#include "llerror.h"
+
+extern const std::string CONTEXT_REQUEST;
+extern const std::string CONTEXT_DEST_URI_SD_LABEL;
+extern const std::string CONTEXT_RESPONSE;
+extern const std::string CONTEXT_TRANSFERED_BYTES;
+
class LLURLRequestDetail;
class LLURLRequestComplete;
@@ -208,6 +214,8 @@ protected:
ERequestAction mAction;
LLURLRequestDetail* mDetail;
LLIOPipe::ptr_t mCompletionCallback;
+ S32 mRequestTransferedBytes;
+ S32 mResponseTransferedBytes;
private:
/**
diff --git a/indra/llmessage/llxfermanager.cpp b/indra/llmessage/llxfermanager.cpp
index 08c9192c9f..209bdb2249 100644
--- a/indra/llmessage/llxfermanager.cpp
+++ b/indra/llmessage/llxfermanager.cpp
@@ -760,30 +760,36 @@ static bool remove_prefix(std::string& filename, const std::string& prefix)
static bool verify_cache_filename(const std::string& filename)
{
//NOTE: This routine is only used to check file names that our own
- // code places in the cache directory. As such, it can be limited
- // to this very restrictive file name pattern. It does not need to
- // handle other characters.
-
+ // code places in the cache directory. As such, it can be limited
+ // to this very restrictive file name pattern. It does not need to
+ // handle other characters. The only known uses of this are (with examples):
+ // sim to sim object pass: fc0b72d8-9456-63d9-a802-a557ef847313.tmp
+ // sim to viewer mute list: mute_b78eacd0-1244-448e-93ca-28ede242f647.tmp
+ // sim to viewer task inventory: inventory_d8ab59d2-baf0-0e79-c4c2-a3f99b9fcf45.tmp
+
+ //IMPORTANT: Do not broaden the filenames accepted by this routine
+ // without careful analysis. Anything allowed by this function can
+ // be downloaded by the viewer.
+
size_t len = filename.size();
- //const boost::regex expr("[a-zA-Z0-9][-_.a-zA-Z0-9]<0,49>");
- if (len < 1 || len > 50)
- {
+ //const boost::regex expr("[0-9a-zA-Z_-]<1,46>\.tmp");
+ if (len < 5 || len > 50)
+ {
return false;
}
- for(unsigned i=0; i<len; ++i)
- {
+ for(size_t i=0; i<(len-4); ++i)
+ {
char c = filename[i];
- bool ok = isalnum(c);
- if (!ok && i > 0)
- {
- ok = '_'==c || '-'==c || '.'==c;
- }
+ bool ok = isalnum(c) || '_'==c || '-'==c;
if (!ok)
{
return false;
}
}
- return true;
+ return filename[len-4] == '.'
+ && filename[len-3] == 't'
+ && filename[len-2] == 'm'
+ && filename[len-1] == 'p';
}
void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user_data*/)
diff --git a/indra/llmessage/machine.cpp b/indra/llmessage/machine.cpp
new file mode 100644
index 0000000000..afaaeb8ea2
--- /dev/null
+++ b/indra/llmessage/machine.cpp
@@ -0,0 +1,62 @@
+/**
+ * @file machine.cpp
+ * @brief LLMachine class header file
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+
+#include "machine.h"
+
+#include "llerror.h"
+
+void LLMachine::setMachinePort(S32 port)
+{
+ if (port < 0)
+ {
+ llinfos << "Can't assign a negative number to LLMachine::mPort" << llendl;
+ mHost.setPort(0);
+ }
+ else
+ {
+ mHost.setPort(port);
+ }
+}
+
+void LLMachine::setControlPort( S32 port )
+{
+ if (port < 0)
+ {
+ llinfos << "Can't assign a negative number to LLMachine::mControlPort" << llendl;
+ mControlPort = 0;
+ }
+ else
+ {
+ mControlPort = port;
+ }
+}
diff --git a/indra/llmessage/machine.h b/indra/llmessage/machine.h
index 63a038159e..6da8e5e04e 100644
--- a/indra/llmessage/machine.h
+++ b/indra/llmessage/machine.h
@@ -33,7 +33,6 @@
#ifndef LL_MACHINE_H
#define LL_MACHINE_H
-#include "llerror.h"
#include "net.h"
#include "llhost.h"
@@ -79,31 +78,8 @@ public:
void setMachineIP(U32 ip) { mHost.setAddress(ip); }
void setMachineHost(const LLHost &host) { mHost = host; }
- void setMachinePort(S32 port)
- {
- if (port < 0)
- {
- llinfos << "Can't assign a negative number to LLMachine::mPort" << llendl;
- mHost.setPort(0);
- }
- else
- {
- mHost.setPort(port);
- }
- }
-
- void setControlPort( S32 port )
- {
- if (port < 0)
- {
- llinfos << "Can't assign a negative number to LLMachine::mControlPort" << llendl;
- mControlPort = 0;
- }
- else
- {
- mControlPort = port;
- }
- }
+ void setMachinePort(S32 port);
+ void setControlPort( S32 port );
// member variables
diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp
index 78af35bf65..e56d818d65 100644
--- a/indra/llmessage/message.cpp
+++ b/indra/llmessage/message.cpp
@@ -86,6 +86,7 @@
#include "v3math.h"
#include "v4math.h"
#include "lltransfertargetvfile.h"
+#include "llmemtype.h"
// Constants
//const char* MESSAGE_LOG_FILENAME = "message.log";
@@ -794,6 +795,7 @@ S32 LLMessageSystem::getReceiveBytes() const
void LLMessageSystem::processAcks()
{
+ LLMemType mt_pa(LLMemType::MTYPE_MESSAGE_PROCESS_ACKS);
F64 mt_sec = getMessageTimeSeconds();
{
gTransferManager.updateTransfers();
@@ -4020,6 +4022,7 @@ void LLMessageSystem::setTimeDecodesSpamThreshold( F32 seconds )
// TODO: babbage: move gServicePump in to LLMessageSystem?
bool LLMessageSystem::checkAllMessages(S64 frame_count, LLPumpIO* http_pump)
{
+ LLMemType mt_cam(LLMemType::MTYPE_MESSAGE_CHECK_ALL);
if(checkMessages(frame_count))
{
return true;
diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h
index 0f3576732d..27482ca1af 100644
--- a/indra/llmessage/message.h
+++ b/indra/llmessage/message.h
@@ -59,10 +59,10 @@
#include "llhttpclient.h"
#include "llhttpnode.h"
#include "llpacketack.h"
+#include "llsingleton.h"
#include "message_prehash.h"
#include "llstl.h"
#include "llmsgvariabletype.h"
-#include "llmsgvariabletype.h"
#include "llmessagesenderinterface.h"
#include "llstoredmessage.h"
diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp
index 43b5f8e224..9e3986f257 100644
--- a/indra/llmessage/message_prehash.cpp
+++ b/indra/llmessage/message_prehash.cpp
@@ -174,6 +174,7 @@ char* _PREHASH_UpdateInventoryItem = LLMessageStringTable::getInstance()->getStr
char* _PREHASH_UpdateCreateInventoryItem = LLMessageStringTable::getInstance()->getString("UpdateCreateInventoryItem");
char* _PREHASH_MoveInventoryItem = LLMessageStringTable::getInstance()->getString("MoveInventoryItem");
char* _PREHASH_CopyInventoryItem = LLMessageStringTable::getInstance()->getString("CopyInventoryItem");
+char* _PREHASH_LinkInventoryItem = LLMessageStringTable::getInstance()->getString("LinkInventoryItem");
char* _PREHASH_RemoveInventoryItem = LLMessageStringTable::getInstance()->getString("RemoveInventoryItem");
char* _PREHASH_CreateInventoryItem = LLMessageStringTable::getInstance()->getString("CreateInventoryItem");
char* _PREHASH_PathTwistBegin = LLMessageStringTable::getInstance()->getString("PathTwistBegin");
@@ -405,7 +406,7 @@ char* _PREHASH_GlobalX = LLMessageStringTable::getInstance()->getString("GlobalX
char* _PREHASH_GlobalY = LLMessageStringTable::getInstance()->getString("GlobalY");
char* _PREHASH_CopyRotates = LLMessageStringTable::getInstance()->getString("CopyRotates");
char* _PREHASH_KickUserAck = LLMessageStringTable::getInstance()->getString("KickUserAck");
-char* _PREHASH_TopPick = LLMessageStringTable::getInstance()->getString("TopPick");
+char* _PREHASH_TopPick = LLMessageStringTable::getInstance()->getString("TopPick"); //legacy var need to be deleted -angela
char* _PREHASH_SessionID = LLMessageStringTable::getInstance()->getString("SessionID");
char* _PREHASH_GlobalZ = LLMessageStringTable::getInstance()->getString("GlobalZ");
char* _PREHASH_DeclineFriendship = LLMessageStringTable::getInstance()->getString("DeclineFriendship");
diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h
index f8ef610408..e73ec3e5e1 100644
--- a/indra/llmessage/message_prehash.h
+++ b/indra/llmessage/message_prehash.h
@@ -174,6 +174,7 @@ extern char * _PREHASH_UpdateInventoryItem;
extern char * _PREHASH_UpdateCreateInventoryItem;
extern char * _PREHASH_MoveInventoryItem;
extern char * _PREHASH_CopyInventoryItem;
+extern char * _PREHASH_LinkInventoryItem;
extern char * _PREHASH_RemoveInventoryItem;
extern char * _PREHASH_CreateInventoryItem;
extern char * _PREHASH_PathTwistBegin;
diff --git a/indra/llmessage/sound_ids.cpp b/indra/llmessage/sound_ids.cpp
new file mode 100644
index 0000000000..edd9a36c5f
--- /dev/null
+++ b/indra/llmessage/sound_ids.cpp
@@ -0,0 +1,314 @@
+/**
+ * @file sound_ids.cpp
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+
+#include "sound_ids.h"
+
+#include "lluuid.h"
+
+const LLUUID SND_NULL = LLUUID::null;
+const LLUUID SND_RIDE ("00000000-0000-0000-0000-000000000100");
+const LLUUID SND_SHOT ("00000000-0000-0000-0000-000000000101");
+const LLUUID SND_MORTAR ("00000000-0000-0000-0000-000000000102");
+const LLUUID SND_HIT ("00000000-0000-0000-0000-000000000103");
+const LLUUID SND_EXPLOSION ("00000000-0000-0000-0000-000000000104");
+const LLUUID SND_BOING ("00000000-0000-0000-0000-000000000105");
+const LLUUID SND_OBJECT_CREATE ("9f1bc096-3592-411e-9b0b-c447a9ff054c");
+
+//
+// Different bird sounds for different states
+//
+
+const LLUUID SND_CHIRP ("00000000-0000-0000-0000-000000000106"); // Flying random chirp
+const LLUUID SND_CHIRP2 ("828a9526-175b-455d-8af0-0e3c0fb602b2"); // Spooked by user
+const LLUUID SND_CHIRP3 ("f99772d6-1ce6-4a39-a28b-06d26c94c9e3"); // Spooked by object
+const LLUUID SND_CHIRP4 ("54472ca4-7fc9-42cb-b7d5-99ad5b12bd50"); // Chasing other bird
+const LLUUID SND_CHIRP5 ("2929964f-fac5-40d7-9179-2864a8fa9ace"); // Hopping random chirp
+const LLUUID SND_CHIRPDEAD ("9abff1d3-863a-4e04-bd83-3834fd7fcff4"); // Hit by grenade - dead!
+
+
+const LLUUID SND_MUNCH ("00000000-0000-0000-0000-000000000107");
+const LLUUID SND_PUNCH ("00000000-0000-0000-0000-000000000108");
+const LLUUID SND_SPLASH ("00000000-0000-0000-0000-000000000109");
+const LLUUID SND_CLICK ("00000000-0000-0000-0000-000000000110");
+const LLUUID SND_WHISTLE ("ab858f9a-1f44-4d39-9b33-351543d03ccb");
+const LLUUID SND_TYPING ("5e191c7b-8996-9ced-a177-b2ac32bfea06");
+
+const LLUUID SND_ARROW_SHOT ("00000000-0000-0000-0000-000000000111");
+const LLUUID SND_ARROW_THUD ("00000000-0000-0000-0000-000000000112");
+const LLUUID SND_LASER_SHOT ("00000000-0000-0000-0000-000000000113");
+const LLUUID SND_JET_THRUST ("67f5e4f0-0534-4d97-bc01-f297648d20e0");
+
+const LLUUID SND_SILENCE ("00000000-0000-0000-0000-000000000114");
+const LLUUID SND_BUBBLES ("00000000-0000-0000-0000-000000000115");
+const LLUUID SND_WELCOME ("00000000-0000-0000-0000-000000000116");
+const LLUUID SND_SQUISH ("00000000-0000-0000-0000-000000000117");
+const LLUUID SND_SUBPOD ("00000000-0000-0000-0000-000000000118");
+const LLUUID SND_FOOTSTEPS ("00000000-0000-0000-0000-000000000119");
+const LLUUID SND_STEP_LEFT ("00000000-0000-0000-0000-000000000124");
+const LLUUID SND_STEP_RIGHT ("00000000-0000-0000-0000-000000000125");
+
+const LLUUID SND_BALL_COLLISION ("00000000-0000-0000-0000-000000000120");
+
+const LLUUID SND_OOOH_SCARE_ME ("00000000-0000-0000-0000-000000000121");
+const LLUUID SND_PAYBACK_TIME ("00000000-0000-0000-0000-000000000122");
+const LLUUID SND_READY_FOR_BATTLE ("00000000-0000-0000-0000-000000000123");
+
+const LLUUID SND_FLESH_FLESH ("dce5fdd4-afe4-4ea1-822f-dd52cac46b08");
+const LLUUID SND_FLESH_PLASTIC ("51011582-fbca-4580-ae9e-1a5593f094ec");
+const LLUUID SND_FLESH_RUBBER ("68d62208-e257-4d0c-bbe2-20c9ea9760bb");
+const LLUUID SND_GLASS_FLESH ("75872e8c-bc39-451b-9b0b-042d7ba36cba");
+const LLUUID SND_GLASS_GLASS ("6a45ba0b-5775-4ea8-8513-26008a17f873");
+const LLUUID SND_GLASS_PLASTIC ("992a6d1b-8c77-40e0-9495-4098ce539694");
+const LLUUID SND_GLASS_RUBBER ("2de4da5a-faf8-46be-bac6-c4d74f1e5767");
+const LLUUID SND_GLASS_WOOD ("6e3fb0f7-6d9c-42ca-b86b-1122ff562d7d");
+const LLUUID SND_METAL_FLESH ("14209133-4961-4acc-9649-53fc38ee1667");
+const LLUUID SND_METAL_GLASS ("bc4a4348-cfcc-4e5e-908e-8a52a8915fe6");
+const LLUUID SND_METAL_METAL ("9e5c1297-6eed-40c0-825a-d9bcd86e3193");
+const LLUUID SND_METAL_PLASTIC ("e534761c-1894-4b61-b20c-658a6fb68157");
+const LLUUID SND_METAL_RUBBER ("8761f73f-6cf9-4186-8aaa-0948ed002db1");
+const LLUUID SND_METAL_WOOD ("874a26fd-142f-4173-8c5b-890cd846c74d");
+const LLUUID SND_PLASTIC_PLASTIC ("0e24a717-b97e-4b77-9c94-b59a5a88b2da");
+const LLUUID SND_RUBBER_PLASTIC ("75cf3ade-9a5b-4c4d-bb35-f9799bda7fb2");
+const LLUUID SND_RUBBER_RUBBER ("153c8bf7-fb89-4d89-b263-47e58b1b4774");
+const LLUUID SND_STONE_FLESH ("55c3e0ce-275a-46fa-82ff-e0465f5e8703");
+const LLUUID SND_STONE_GLASS ("24babf58-7156-4841-9a3f-761bdbb8e237");
+const LLUUID SND_STONE_METAL ("aca261d8-e145-4610-9e20-9eff990f2c12");
+const LLUUID SND_STONE_PLASTIC ("0642fba6-5dcf-4d62-8e7b-94dbb529d117");
+const LLUUID SND_STONE_RUBBER ("25a863e8-dc42-4e8a-a357-e76422ace9b5");
+const LLUUID SND_STONE_STONE ("9538f37c-456e-4047-81be-6435045608d4");
+const LLUUID SND_STONE_WOOD ("8c0f84c3-9afd-4396-b5f5-9bca2c911c20");
+const LLUUID SND_WOOD_FLESH ("be582e5d-b123-41a2-a150-454c39e961c8");
+const LLUUID SND_WOOD_PLASTIC ("c70141d4-ba06-41ea-bcbc-35ea81cb8335");
+const LLUUID SND_WOOD_RUBBER ("7d1826f4-24c4-4aac-8c2e-eff45df37783");
+const LLUUID SND_WOOD_WOOD ("063c97d3-033a-4e9b-98d8-05c8074922cb");
+
+
+const LLUUID SND_SLIDE_FLESH_FLESH ("614eec22-f73d-4fdc-8691-a37dc5c58333");
+const LLUUID SND_SLIDE_FLESH_PLASTIC (SND_NULL);
+const LLUUID SND_SLIDE_FLESH_RUBBER (SND_NULL);
+const LLUUID SND_SLIDE_FLESH_FABRIC ("3678b9b9-2a0c-42b5-9c83-80b64ad6e898");
+const LLUUID SND_SLIDE_FLESH_GRAVEL ("02eaa42a-ce1a-4b6b-9c38-cd7ad0e8f4a6");
+const LLUUID SND_SLIDE_FLESH_GRAVEL_02 ("e7d3b501-79f8-4419-b842-ab6843e0f840");
+const LLUUID SND_SLIDE_FLESH_GRAVEL_03 ("4c3e8b52-6244-4e44-85a6-f4ab994418ed");
+const LLUUID SND_SLIDE_GLASS_GRAVEL ("ca491e77-5c47-4ea1-8021-b3ebbf636cab");
+const LLUUID SND_SLIDE_GLASS_GRAVEL_02 ("30794d49-91ce-48e3-a527-c06f67bd6cbe");
+const LLUUID SND_SLIDE_GLASS_GRAVEL_03 ("04c78e54-fd8d-46b6-8ab9-7678b5d6e5cb");
+const LLUUID SND_SLIDE_GLASS_FLESH (SND_NULL);
+const LLUUID SND_SLIDE_GLASS_GLASS (SND_NULL);
+const LLUUID SND_SLIDE_GLASS_PLASTIC (SND_NULL);
+const LLUUID SND_SLIDE_GLASS_RUBBER (SND_NULL);
+const LLUUID SND_SLIDE_GLASS_WOOD (SND_NULL);
+const LLUUID SND_SLIDE_METAL_FABRIC ("18b66e81-2958-42d4-a373-7a5054919adc");
+const LLUUID SND_SLIDE_METAL_FLESH ("dde65837-633c-4841-af2f-62ec471bf61e");
+const LLUUID SND_SLIDE_METAL_FLESH_02 ("f3cc2cbe-1a1a-4db7-a8d2-e9c8f8fa1f4f");
+const LLUUID SND_SLIDE_METAL_GLASS ("4188be39-7b1f-4495-bf2b-83ddd82eea05");
+const LLUUID SND_SLIDE_METAL_GLASS_02 ("336faa2b-9d96-4e14-93ad-b63b60074379");
+const LLUUID SND_SLIDE_METAL_GLASS_03 ("34d912aa-cf73-4462-b7d0-dcba2c66caba");
+const LLUUID SND_SLIDE_METAL_GLASS_04 ("97ffc063-e872-4469-8e95-1450ac6bad2b");
+const LLUUID SND_SLIDE_METAL_GRAVEL ("2bbff37d-009a-4cfc-9a0d-817652c08fbe");
+const LLUUID SND_SLIDE_METAL_GRAVEL_02 ("a906a228-783b-49e7-9f0a-e20a41d0e39f");
+const LLUUID SND_SLIDE_METAL_METAL ("09461277-c691-45de-b2c5-89dfd3712f79");
+const LLUUID SND_SLIDE_METAL_METAL_02 ("e00a5d97-8fdc-46c1-bd53-7e312727466c");
+const LLUUID SND_SLIDE_METAL_METAL_03 ("8ebfa780-c440-4b52-ab65-5edf3bc15bf1");
+const LLUUID SND_SLIDE_METAL_METAL_04 ("d6d03cb2-5b16-4e31-b7d4-2a81d2a0909b");
+const LLUUID SND_SLIDE_METAL_METAL_05 ("3a46f447-916e-47de-a1e5-95d1af46bd0f");
+const LLUUID SND_SLIDE_METAL_METAL_06 ("cd423231-e70d-4fd2-ad26-f1c6cf5f0610");
+const LLUUID SND_SLIDE_METAL_PLASTIC (SND_NULL);
+const LLUUID SND_SLIDE_METAL_RUBBER ("12d97bc0-3c15-4744-b6bd-77d1316eb4f0");
+const LLUUID SND_SLIDE_METAL_WOOD ("4afb6926-a73f-4cb7-85d5-0f9a40107434");
+const LLUUID SND_SLIDE_METAL_WOOD_02 ("349970bf-187d-4bcb-b2cf-e7bb6581590f");
+const LLUUID SND_SLIDE_METAL_WOOD_03 ("64bf6e87-73d4-4cb4-84f7-55cecfd97cd3");
+const LLUUID SND_SLIDE_METAL_WOOD_04 ("0dc670a9-dbe8-41bc-b8ee-4d96d99219d5");
+const LLUUID SND_SLIDE_METAL_WOOD_05 ("6e3cc57b-c9aa-4829-86a1-8e82aeaccb47");
+const LLUUID SND_SLIDE_METAL_WOOD_06 ("c1237f4c-8c88-4da1-bfbc-2af26a8d9e5a");
+const LLUUID SND_SLIDE_METAL_WOOD_07 ("0e1ec243-063b-4dcb-a903-52b8dffed3d2");
+const LLUUID SND_SLIDE_METAL_WOOD_08 ("66736d0f-533d-4007-a8ee-0f27c2034126");
+const LLUUID SND_SLIDE_PLASTIC_GRAVEL ("35092c21-5c48-4b4d-a818-3cf240af2348");
+const LLUUID SND_SLIDE_PLASTIC_GRAVEL_02("c37f5776-0020-47e8-89a0-c74cc6f5742d");
+const LLUUID SND_SLIDE_PLASTIC_GRAVEL_03("d2fc8db6-2e66-464a-8ccb-f99b61ee4987");
+const LLUUID SND_SLIDE_PLASTIC_GRAVEL_04("93cbdb10-6e82-4c0b-a547-7b3b79ac25f6");
+const LLUUID SND_SLIDE_PLASTIC_GRAVEL_05("2f6d0542-fcd1-4264-a17b-f57bf5ebf402");
+const LLUUID SND_SLIDE_PLASTIC_GRAVEL_06("5b8887d4-3be2-45a0-b25d-85af3b1e6392");
+const LLUUID SND_SLIDE_PLASTIC_PLASTIC (SND_NULL);
+const LLUUID SND_SLIDE_PLASTIC_PLASTIC_02 (SND_NULL);
+const LLUUID SND_SLIDE_PLASTIC_PLASTIC_03 (SND_NULL);
+const LLUUID SND_SLIDE_PLASTIC_FABRIC ("7294d9ad-3e41-4373-992c-a9f21d5d66ad");
+const LLUUID SND_SLIDE_PLASTIC_FABRIC_02("58608ce1-f524-472f-b447-bbe6ce4a46e0");
+const LLUUID SND_SLIDE_PLASTIC_FABRIC_03("06ae285e-0b34-4ea6-84ab-9c6c31b414fc");
+const LLUUID SND_SLIDE_PLASTIC_FABRIC_04("211613db-0461-49bd-9554-5c14ad8b31f6");
+const LLUUID SND_SLIDE_RUBBER_PLASTIC ("a98ffa5a-e48e-4f9d-9242-b9a3210ad84a");
+const LLUUID SND_SLIDE_RUBBER_PLASTIC_02 ("d4136c40-eeaa-49c6-a982-8e5a16f5d93a");
+const LLUUID SND_SLIDE_RUBBER_PLASTIC_03 ("29ec0fb2-0b23-47b2-835b-c83cc7cf9fb0");
+const LLUUID SND_SLIDE_RUBBER_RUBBER (SND_NULL);
+const LLUUID SND_SLIDE_STONE_FLESH (SND_NULL);
+const LLUUID SND_SLIDE_STONE_GLASS (SND_NULL);
+const LLUUID SND_SLIDE_STONE_METAL (SND_NULL);
+const LLUUID SND_SLIDE_STONE_PLASTIC ("afd0bcc3-d41a-4572-9e7f-08a29eeb0b8a");
+const LLUUID SND_SLIDE_STONE_PLASTIC_02 ("881b720a-96cf-4128-bb98-5d87e03e93c7");
+const LLUUID SND_SLIDE_STONE_PLASTIC_03 ("293dac42-658a-4c5a-a7a2-6d4c5e5658b0");
+const LLUUID SND_SLIDE_STONE_RUBBER ("0724b946-6a3f-4eeb-bb50-0a3b33120974");
+const LLUUID SND_SLIDE_STONE_RUBBER_02 ("ada93d00-76e2-4bf1-9ad9-493727630717");
+const LLUUID SND_SLIDE_STONE_STONE ("ade766dc-2e75-4699-9b41-7c8e53d2b3f2");
+const LLUUID SND_SLIDE_STONE_STONE_02 ("66698375-6594-47b0-8046-c3973de1291d");
+const LLUUID SND_SLIDE_STONE_WOOD ("174ef324-ed50-4f65-9479-b4da580aeb3c");
+const LLUUID SND_SLIDE_STONE_WOOD_02 ("33d517fd-ff11-4d01-a7b5-0e3abf818dcf");
+const LLUUID SND_SLIDE_STONE_WOOD_03 ("1bac4b63-e6fd-4659-9761-991284cf4582");
+const LLUUID SND_SLIDE_STONE_WOOD_04 ("a7d28564-6821-4c01-a378-cde98fba7ba9");
+const LLUUID SND_SLIDE_WOOD_FABRIC ("22c58e74-22cd-4960-9ab7-5bf08ab824e5");
+const LLUUID SND_SLIDE_WOOD_FABRIC_02 ("0b0ed22e-4a0f-4617-a4cf-20d0f2b78ccc");
+const LLUUID SND_SLIDE_WOOD_FABRIC_03 ("42b80abb-9823-4b74-a210-326ccf23636a");
+const LLUUID SND_SLIDE_WOOD_FABRIC_04 ("8538298a-1e6b-4b69-a9ee-5e01e4a02b35");
+const LLUUID SND_SLIDE_WOOD_FLESH ("84b026f3-a11c-4366-aa7c-07edcd89b2bb");
+const LLUUID SND_SLIDE_WOOD_FLESH_02 ("2644191f-4848-47ba-8ba7-bddc0bfcb3da");
+const LLUUID SND_SLIDE_WOOD_FLESH_03 ("edb978e4-9be9-456f-b2fc-e8502bfe25be");
+const LLUUID SND_SLIDE_WOOD_FLESH_04 ("bf2b972e-f42a-46d7-b53e-5fca38f5bc61");
+const LLUUID SND_SLIDE_WOOD_GRAVEL ("d063bb4d-0eff-4403-a6cc-c6c6c073e624");
+const LLUUID SND_SLIDE_WOOD_GRAVEL_02 ("511eb679-6d93-47fa-9141-c3ef9261c919");
+const LLUUID SND_SLIDE_WOOD_GRAVEL_03 ("4ed1fd43-4707-4e5c-b7b7-21ec4e72c1ac");
+const LLUUID SND_SLIDE_WOOD_GRAVEL_04 ("99ea89b3-aa76-4b87-99c8-670365c6d8c3");
+const LLUUID SND_SLIDE_WOOD_PLASTIC ("505ca3c4-94a0-4e28-8fc1-ea72a428396b");
+const LLUUID SND_SLIDE_WOOD_PLASTIC_02 ("fc404011-df71-4ed0-8f22-b72bdd18f63c");
+const LLUUID SND_SLIDE_WOOD_PLASTIC_03 ("67dbe225-26df-4efa-8c8b-f1ef669fec45");
+const LLUUID SND_SLIDE_WOOD_RUBBER (SND_NULL);
+const LLUUID SND_SLIDE_WOOD_WOOD ("3079d569-b3e8-4df4-9e09-f0d4611213ef");
+const LLUUID SND_SLIDE_WOOD_WOOD_02 ("276b093d-dbcb-4279-a89e-a54b0b416af6");
+const LLUUID SND_SLIDE_WOOD_WOOD_03 ("c3f3ca5e-2768-4081-847f-247139310fdb");
+const LLUUID SND_SLIDE_WOOD_WOOD_04 ("f08d44b8-ff87-4a98-9561-c72f1f2fec81");
+const LLUUID SND_SLIDE_WOOD_WOOD_05 ("2d8a58cf-f139-4238-8503-27d334d05c85");
+const LLUUID SND_SLIDE_WOOD_WOOD_06 ("e157ebbd-b12d-4225-aa7c-d47b026a7687");
+const LLUUID SND_SLIDE_WOOD_WOOD_07 ("35e17956-e7b4-478c-b274-e37db8a166b2");
+const LLUUID SND_SLIDE_WOOD_WOOD_08 ("e606fc65-0643-4964-9979-ff964fa6a62c");
+
+
+const LLUUID SND_ROLL_FLESH_FLESH (SND_NULL);
+const LLUUID SND_ROLL_FLESH_PLASTIC ("89a0be4c-848d-4a6e-8886-298f56c2cff4");
+const LLUUID SND_ROLL_FLESH_PLASTIC_02 ("beb06343-1aa1-4af2-b320-5d2ec31c53b1");
+const LLUUID SND_ROLL_FLESH_RUBBER (SND_NULL);
+const LLUUID SND_ROLL_GLASS_GRAVEL ("ba795c74-7e09-4572-b495-e09886a46b86");
+const LLUUID SND_ROLL_GLASS_GRAVEL_02 ("4c93c3b7-14cb-4d9b-a7df-628ad935f1f2");
+const LLUUID SND_ROLL_GLASS_FLESH (SND_NULL);
+const LLUUID SND_ROLL_GLASS_GLASS (SND_NULL);
+const LLUUID SND_ROLL_GLASS_PLASTIC (SND_NULL);
+const LLUUID SND_ROLL_GLASS_RUBBER (SND_NULL);
+const LLUUID SND_ROLL_GLASS_WOOD ("d40b1f48-a061-4f6e-b18f-4326a3dd5c29");
+const LLUUID SND_ROLL_GLASS_WOOD_02 ("78cd407a-bb36-4163-ba09-20f2e6d9d44b");
+const LLUUID SND_ROLL_GRAVEL_GRAVEL ("c7354cc3-6df5-4738-8dbb-b28a6ac46a05");
+const LLUUID SND_ROLL_GRAVEL_GRAVEL_02 ("01d194c4-72a6-47df-81a5-8db430faff87");
+const LLUUID SND_ROLL_METAL_FABRIC ("ce6e6564-20fd-48e4-81e2-cd3f81c00a3e");
+const LLUUID SND_ROLL_METAL_FABRIC_02 ("fc4d0065-32f6-4bb0-9f3f-f4737eb27163");
+const LLUUID SND_ROLL_METAL_FLESH (SND_NULL);
+const LLUUID SND_ROLL_METAL_GLASS ("63d530bb-a41f-402b-aa1f-be6b11959809");
+const LLUUID SND_ROLL_METAL_GLASS_02 ("f62642c2-6db5-4faa-8b77-939067d837c3");
+const LLUUID SND_ROLL_METAL_GLASS_03 ("db5b5a15-2817-4cd7-9f0b-9ad49b5e52c8");
+const LLUUID SND_ROLL_METAL_GRAVEL ("447164e3-9646-4c1a-a16d-606892891466");
+const LLUUID SND_ROLL_METAL_METAL ("c3c22cf3-5d1f-4cc3-b4b5-708b9f65979c");
+const LLUUID SND_ROLL_METAL_METAL_02 ("d8386277-a1ea-460e-b6fd-bb285c323bf1");
+const LLUUID SND_ROLL_METAL_METAL_03 ("69ee1f02-f9cd-4c8b-aedd-39a2d6705680");
+const LLUUID SND_ROLL_METAL_METAL_04 ("5cc6b5fd-26ce-47ad-b21d-3a7c190dd375");
+const LLUUID SND_ROLL_METAL_PLASTIC ("c6a9bbf6-df15-4713-9f84-7237fce4051e");
+const LLUUID SND_ROLL_METAL_PLASTIC_01 ("0fedb59b-2dbb-4cec-b6cc-8559ec027749");
+const LLUUID SND_ROLL_METAL_RUBBER (SND_NULL);
+const LLUUID SND_ROLL_METAL_WOOD ("1d76af57-01b1-4c73-9a1d-69523bfa50ea");
+const LLUUID SND_ROLL_METAL_WOOD_02 ("78aa4e71-8e7c-4b90-a561-3ebdc639f99b");
+const LLUUID SND_ROLL_METAL_WOOD_03 ("777d95bf-962f-48fa-93bf-8c1806557d72");
+const LLUUID SND_ROLL_METAL_WOOD_04 ("1833da76-45e2-4a8b-97da-d17413e056c9");
+const LLUUID SND_ROLL_METAL_WOOD_05 ("b13e1232-3d8d-42e9-92ec-b30f9f823962");
+const LLUUID SND_ROLL_PLASTIC_FABRIC ("616a1f03-209f-4c55-b264-83a000b6ef0a");
+const LLUUID SND_ROLL_PLASTIC_PLASTIC ("873f3d82-00b2-4082-9c69-7aef3461dba1");
+const LLUUID SND_ROLL_PLASTIC_PLASTIC_02 ("cc39879f-ebc8-4405-a4fc-8342f5bed31e");
+const LLUUID SND_ROLL_RUBBER_PLASTIC (SND_NULL);
+const LLUUID SND_ROLL_RUBBER_RUBBER (SND_NULL);
+const LLUUID SND_ROLL_STONE_FLESH (SND_NULL);
+const LLUUID SND_ROLL_STONE_GLASS (SND_NULL);
+const LLUUID SND_ROLL_STONE_METAL (SND_NULL);
+const LLUUID SND_ROLL_STONE_PLASTIC ("155f65a8-cae7-476e-a58b-fd362be7fd0e");
+const LLUUID SND_ROLL_STONE_RUBBER (SND_NULL);
+const LLUUID SND_ROLL_STONE_STONE ("67d56e3f-6ed5-4658-9418-14f020c38b11");
+const LLUUID SND_ROLL_STONE_STONE_02 ("43d99d10-d75b-4246-accf-4ceb2c909aa7");
+const LLUUID SND_ROLL_STONE_STONE_03 ("f04e83ff-eed7-4e99-8f45-eb97e4e1d3b7");
+const LLUUID SND_ROLL_STONE_STONE_04 ("10fcc5ad-fa89-48d6-b774-986b580c1efc");
+const LLUUID SND_ROLL_STONE_STONE_05 ("3d86f5a3-1a91-49d9-b99f-8521a7422497");
+const LLUUID SND_ROLL_STONE_WOOD ("53e46fb7-6c21-4fe1-bffe-0567475d48fa");
+const LLUUID SND_ROLL_STONE_WOOD_02 ("5eba8c9a-a014-4299-87f1-315c45ec795b");
+const LLUUID SND_ROLL_STONE_WOOD_03 ("ea6c05fc-6e9c-4526-8a20-bc47810bb549");
+const LLUUID SND_ROLL_STONE_WOOD_04 ("64618cbf-3f42-4728-8094-e77807545efb");
+const LLUUID SND_ROLL_WOOD_FLESH ("26ee185d-6fc3-49f8-89ba-51cab04cfc42");
+const LLUUID SND_ROLL_WOOD_FLESH_02 ("334faa25-1e80-4c99-b29f-4c9c2a3d079d");
+const LLUUID SND_ROLL_WOOD_FLESH_03 ("2f876626-4dce-4f71-a91e-a25302edfab7");
+const LLUUID SND_ROLL_WOOD_FLESH_04 ("d6877aac-07fc-4931-bcde-585f223802ad");
+const LLUUID SND_ROLL_WOOD_GRAVEL ("2a23ebb5-a4a2-4f1f-8d75-7384239354aa");
+const LLUUID SND_ROLL_WOOD_GRAVEL_02 ("208bf26d-f097-450c-95c4-9d26317c613c");
+const LLUUID SND_ROLL_WOOD_GRAVEL_03 ("a26ecaf4-92c6-4e32-9864-56b7c70cab8e");
+const LLUUID SND_ROLL_WOOD_PLASTIC ("71c1000a-9f16-4cc3-8ede-ec4aa3bf5723");
+const LLUUID SND_ROLL_WOOD_PLASTIC_02 ("7bc20ba6-1e6d-4eea-83ad-c5cc3ae0e409");
+const LLUUID SND_ROLL_WOOD_RUBBER (SND_NULL);
+const LLUUID SND_ROLL_WOOD_WOOD ("2cc8eec4-bb4a-4ba8-b783-71526ec708e8");
+const LLUUID SND_ROLL_WOOD_WOOD_02 ("0a1f8070-a11a-4b4c-b260-5ffb6acb0a5d");
+const LLUUID SND_ROLL_WOOD_WOOD_03 ("160bef64-da9c-4be8-b07b-a5060b501700");
+const LLUUID SND_ROLL_WOOD_WOOD_04 ("1c62ea16-cc60-48ed-829a-68b8f4cf0c1c");
+const LLUUID SND_ROLL_WOOD_WOOD_05 ("be9cc8fe-b920-4bf5-8924-453088cbc03f");
+const LLUUID SND_ROLL_WOOD_WOOD_06 ("a76cfe60-56b0-43b1-8f31-93e56947d78b");
+const LLUUID SND_ROLL_WOOD_WOOD_07 ("0c6aa481-b5bc-4573-ae83-8e16ff27e750");
+const LLUUID SND_ROLL_WOOD_WOOD_08 ("214ab2c7-871a-451b-b0db-4c5677199011");
+const LLUUID SND_ROLL_WOOD_WOOD_09 ("0086e4db-3ac6-4545-b414-6f359bedd9a5");
+
+const LLUUID SND_SLIDE_STONE_STONE_01 ("2a7dcbd1-d3e6-4767-8432-8322648e7b9d");
+
+const LLUUID SND_STONE_DIRT_01 ("97727335-392c-4338-ac4b-23a7883279c2");
+const LLUUID SND_STONE_DIRT_02 ("cbe75eb2-3375-41d8-9e3f-2ae46b4164ed");
+const LLUUID SND_STONE_DIRT_03 ("31e236ee-001b-4c8e-ad6c-c2074cb64357");
+const LLUUID SND_STONE_DIRT_04 ("c8091652-e04b-4a11-84ba-15dba06e7a1b");
+
+const LLUUID SND_STONE_STONE_02 ("ba4ef5ac-7435-4240-b826-c24ba8fa5a78");
+const LLUUID SND_STONE_STONE_04 ("ea296329-0f09-4993-af1b-e6784bab1dc9");
+
+
+
+// extra guids
+#if 0
+const LLUUID SND_ ("a839b8ac-b0af-4ba9-9fde-188754744e02");
+const LLUUID SND_ ("20165fa8-836f-4993-85dc-1529172dcd14");
+const LLUUID SND_ ("fba8e17b-a4b3-4693-9fce-c14800f8a349");
+const LLUUID SND_ ("2d48db8b-7260-4b02-ad2a-b2c6bee60e94");
+const LLUUID SND_ ("956d344b-1808-4d8b-88b1-cbc82b7a96a1");
+const LLUUID SND_ ("b8303cc6-f0b4-4c6f-a199-81f87aba342e");
+const LLUUID SND_ ("fbf7cd0c-bc8f-4cba-9c19-11f4dd03a06b");
+const LLUUID SND_ ("85047f7d-933a-4ce5-a7b5-34670243e1ab");
+const LLUUID SND_ ("0f81acf7-6a2e-4490-957f-c7b0eda00559");
+const LLUUID SND_ ("5631a6a1-79b4-4de8-bccf-1880b6882da1");
+const LLUUID SND_ ("43c87a6b-ffb2-437b-89a0-9deba890a4fc");
+const LLUUID SND_ ("58878d1d-3156-4d01-ac3c-0c4fb99f4d53");
+const LLUUID SND_ ("9a83f321-44bf-40f6-b006-46c085515345");
+const LLUUID SND_ ("ff144533-33ab-40f2-bac8-39c34699ecc4");
+const LLUUID SND_ ("09018e87-d52c-4cd5-9805-015f413319e7");
+const LLUUID SND_ ("17d4c057-7edd-401e-9589-d5b9fe981bf2");
+#endif
diff --git a/indra/llmessage/sound_ids.h b/indra/llmessage/sound_ids.h
index e7a919056e..f67fdd2aaf 100644
--- a/indra/llmessage/sound_ids.h
+++ b/indra/llmessage/sound_ids.h
@@ -33,285 +33,263 @@
#ifndef LL_SOUND_IDS_H
#define LL_SOUND_IDS_H
-#include "lluuid.h"
+// *NOTE: Do not put the actual IDs in this file - otherwise the symbols
+// and values will be copied into every .o/.obj file and increase link time.
-const LLUUID SND_NULL = LLUUID::null;
-const LLUUID SND_RIDE ("00000000-0000-0000-0000-000000000100");
-const LLUUID SND_SHOT ("00000000-0000-0000-0000-000000000101");
-const LLUUID SND_MORTAR ("00000000-0000-0000-0000-000000000102");
-const LLUUID SND_HIT ("00000000-0000-0000-0000-000000000103");
-const LLUUID SND_EXPLOSION ("00000000-0000-0000-0000-000000000104");
-const LLUUID SND_BOING ("00000000-0000-0000-0000-000000000105");
-const LLUUID SND_OBJECT_CREATE ("9f1bc096-3592-411e-9b0b-c447a9ff054c");
+class LLUUID;
-//
-// Different bird sounds for different states
-//
-
-const LLUUID SND_CHIRP ("00000000-0000-0000-0000-000000000106"); // Flying random chirp
-const LLUUID SND_CHIRP2 ("828a9526-175b-455d-8af0-0e3c0fb602b2"); // Spooked by user
-const LLUUID SND_CHIRP3 ("f99772d6-1ce6-4a39-a28b-06d26c94c9e3"); // Spooked by object
-const LLUUID SND_CHIRP4 ("54472ca4-7fc9-42cb-b7d5-99ad5b12bd50"); // Chasing other bird
-const LLUUID SND_CHIRP5 ("2929964f-fac5-40d7-9179-2864a8fa9ace"); // Hopping random chirp
-const LLUUID SND_CHIRPDEAD ("9abff1d3-863a-4e04-bd83-3834fd7fcff4"); // Hit by grenade - dead!
-
-
-const LLUUID SND_MUNCH ("00000000-0000-0000-0000-000000000107");
-const LLUUID SND_PUNCH ("00000000-0000-0000-0000-000000000108");
-const LLUUID SND_SPLASH ("00000000-0000-0000-0000-000000000109");
-const LLUUID SND_CLICK ("00000000-0000-0000-0000-000000000110");
-const LLUUID SND_WHISTLE ("ab858f9a-1f44-4d39-9b33-351543d03ccb");
-const LLUUID SND_TYPING ("5e191c7b-8996-9ced-a177-b2ac32bfea06");
+extern const LLUUID SND_NULL;
+extern const LLUUID SND_RIDE;
+extern const LLUUID SND_SHOT;
+extern const LLUUID SND_MORTAR;
+extern const LLUUID SND_HIT;
+extern const LLUUID SND_EXPLOSION;
+extern const LLUUID SND_BOING;
+extern const LLUUID SND_OBJECT_CREATE;
-const LLUUID SND_ARROW_SHOT ("00000000-0000-0000-0000-000000000111");
-const LLUUID SND_ARROW_THUD ("00000000-0000-0000-0000-000000000112");
-const LLUUID SND_LASER_SHOT ("00000000-0000-0000-0000-000000000113");
-const LLUUID SND_JET_THRUST ("67f5e4f0-0534-4d97-bc01-f297648d20e0");
+// Different bird sounds for different states
+extern const LLUUID SND_CHIRP; // Flying random chirp
+extern const LLUUID SND_CHIRP2; // Spooked by user
+extern const LLUUID SND_CHIRP3; // Spooked by object
+extern const LLUUID SND_CHIRP4; // Chasing other bird
+extern const LLUUID SND_CHIRP5; // Hopping random chirp
+extern const LLUUID SND_CHIRPDEAD; // Hit by grenade - dead!
-const LLUUID SND_SILENCE ("00000000-0000-0000-0000-000000000114");
-const LLUUID SND_BUBBLES ("00000000-0000-0000-0000-000000000115");
-const LLUUID SND_WELCOME ("00000000-0000-0000-0000-000000000116");
-const LLUUID SND_SQUISH ("00000000-0000-0000-0000-000000000117");
-const LLUUID SND_SUBPOD ("00000000-0000-0000-0000-000000000118");
-const LLUUID SND_FOOTSTEPS ("00000000-0000-0000-0000-000000000119");
-const LLUUID SND_STEP_LEFT ("00000000-0000-0000-0000-000000000124");
-const LLUUID SND_STEP_RIGHT ("00000000-0000-0000-0000-000000000125");
-const LLUUID SND_BALL_COLLISION ("00000000-0000-0000-0000-000000000120");
+extern const LLUUID SND_MUNCH;
+extern const LLUUID SND_PUNCH;
+extern const LLUUID SND_SPLASH;
+extern const LLUUID SND_CLICK;
+extern const LLUUID SND_WHISTLE;
+extern const LLUUID SND_TYPING;
-const LLUUID SND_OOOH_SCARE_ME ("00000000-0000-0000-0000-000000000121");
-const LLUUID SND_PAYBACK_TIME ("00000000-0000-0000-0000-000000000122");
-const LLUUID SND_READY_FOR_BATTLE ("00000000-0000-0000-0000-000000000123");
+extern const LLUUID SND_ARROW_SHOT;
+extern const LLUUID SND_ARROW_THUD;
+extern const LLUUID SND_LASER_SHOT;
+extern const LLUUID SND_JET_THRUST;
-const LLUUID SND_FLESH_FLESH ("dce5fdd4-afe4-4ea1-822f-dd52cac46b08");
-const LLUUID SND_FLESH_PLASTIC ("51011582-fbca-4580-ae9e-1a5593f094ec");
-const LLUUID SND_FLESH_RUBBER ("68d62208-e257-4d0c-bbe2-20c9ea9760bb");
-const LLUUID SND_GLASS_FLESH ("75872e8c-bc39-451b-9b0b-042d7ba36cba");
-const LLUUID SND_GLASS_GLASS ("6a45ba0b-5775-4ea8-8513-26008a17f873");
-const LLUUID SND_GLASS_PLASTIC ("992a6d1b-8c77-40e0-9495-4098ce539694");
-const LLUUID SND_GLASS_RUBBER ("2de4da5a-faf8-46be-bac6-c4d74f1e5767");
-const LLUUID SND_GLASS_WOOD ("6e3fb0f7-6d9c-42ca-b86b-1122ff562d7d");
-const LLUUID SND_METAL_FLESH ("14209133-4961-4acc-9649-53fc38ee1667");
-const LLUUID SND_METAL_GLASS ("bc4a4348-cfcc-4e5e-908e-8a52a8915fe6");
-const LLUUID SND_METAL_METAL ("9e5c1297-6eed-40c0-825a-d9bcd86e3193");
-const LLUUID SND_METAL_PLASTIC ("e534761c-1894-4b61-b20c-658a6fb68157");
-const LLUUID SND_METAL_RUBBER ("8761f73f-6cf9-4186-8aaa-0948ed002db1");
-const LLUUID SND_METAL_WOOD ("874a26fd-142f-4173-8c5b-890cd846c74d");
-const LLUUID SND_PLASTIC_PLASTIC ("0e24a717-b97e-4b77-9c94-b59a5a88b2da");
-const LLUUID SND_RUBBER_PLASTIC ("75cf3ade-9a5b-4c4d-bb35-f9799bda7fb2");
-const LLUUID SND_RUBBER_RUBBER ("153c8bf7-fb89-4d89-b263-47e58b1b4774");
-const LLUUID SND_STONE_FLESH ("55c3e0ce-275a-46fa-82ff-e0465f5e8703");
-const LLUUID SND_STONE_GLASS ("24babf58-7156-4841-9a3f-761bdbb8e237");
-const LLUUID SND_STONE_METAL ("aca261d8-e145-4610-9e20-9eff990f2c12");
-const LLUUID SND_STONE_PLASTIC ("0642fba6-5dcf-4d62-8e7b-94dbb529d117");
-const LLUUID SND_STONE_RUBBER ("25a863e8-dc42-4e8a-a357-e76422ace9b5");
-const LLUUID SND_STONE_STONE ("9538f37c-456e-4047-81be-6435045608d4");
-const LLUUID SND_STONE_WOOD ("8c0f84c3-9afd-4396-b5f5-9bca2c911c20");
-const LLUUID SND_WOOD_FLESH ("be582e5d-b123-41a2-a150-454c39e961c8");
-const LLUUID SND_WOOD_PLASTIC ("c70141d4-ba06-41ea-bcbc-35ea81cb8335");
-const LLUUID SND_WOOD_RUBBER ("7d1826f4-24c4-4aac-8c2e-eff45df37783");
-const LLUUID SND_WOOD_WOOD ("063c97d3-033a-4e9b-98d8-05c8074922cb");
+extern const LLUUID SND_SILENCE;
+extern const LLUUID SND_BUBBLES;
+extern const LLUUID SND_WELCOME;
+extern const LLUUID SND_SQUISH;
+extern const LLUUID SND_SUBPOD;
+extern const LLUUID SND_FOOTSTEPS;
+extern const LLUUID SND_STEP_LEFT;
+extern const LLUUID SND_STEP_RIGHT;
+extern const LLUUID SND_BALL_COLLISION;
-const LLUUID SND_SLIDE_FLESH_FLESH ("614eec22-f73d-4fdc-8691-a37dc5c58333");
-const LLUUID SND_SLIDE_FLESH_PLASTIC (SND_NULL);
-const LLUUID SND_SLIDE_FLESH_RUBBER (SND_NULL);
-const LLUUID SND_SLIDE_FLESH_FABRIC ("3678b9b9-2a0c-42b5-9c83-80b64ad6e898");
-const LLUUID SND_SLIDE_FLESH_GRAVEL ("02eaa42a-ce1a-4b6b-9c38-cd7ad0e8f4a6");
-const LLUUID SND_SLIDE_FLESH_GRAVEL_02 ("e7d3b501-79f8-4419-b842-ab6843e0f840");
-const LLUUID SND_SLIDE_FLESH_GRAVEL_03 ("4c3e8b52-6244-4e44-85a6-f4ab994418ed");
-const LLUUID SND_SLIDE_GLASS_GRAVEL ("ca491e77-5c47-4ea1-8021-b3ebbf636cab");
-const LLUUID SND_SLIDE_GLASS_GRAVEL_02 ("30794d49-91ce-48e3-a527-c06f67bd6cbe");
-const LLUUID SND_SLIDE_GLASS_GRAVEL_03 ("04c78e54-fd8d-46b6-8ab9-7678b5d6e5cb");
-const LLUUID SND_SLIDE_GLASS_FLESH (SND_NULL);
-const LLUUID SND_SLIDE_GLASS_GLASS (SND_NULL);
-const LLUUID SND_SLIDE_GLASS_PLASTIC (SND_NULL);
-const LLUUID SND_SLIDE_GLASS_RUBBER (SND_NULL);
-const LLUUID SND_SLIDE_GLASS_WOOD (SND_NULL);
-const LLUUID SND_SLIDE_METAL_FABRIC ("18b66e81-2958-42d4-a373-7a5054919adc");
-const LLUUID SND_SLIDE_METAL_FLESH ("dde65837-633c-4841-af2f-62ec471bf61e");
-const LLUUID SND_SLIDE_METAL_FLESH_02 ("f3cc2cbe-1a1a-4db7-a8d2-e9c8f8fa1f4f");
-const LLUUID SND_SLIDE_METAL_GLASS ("4188be39-7b1f-4495-bf2b-83ddd82eea05");
-const LLUUID SND_SLIDE_METAL_GLASS_02 ("336faa2b-9d96-4e14-93ad-b63b60074379");
-const LLUUID SND_SLIDE_METAL_GLASS_03 ("34d912aa-cf73-4462-b7d0-dcba2c66caba");
-const LLUUID SND_SLIDE_METAL_GLASS_04 ("97ffc063-e872-4469-8e95-1450ac6bad2b");
-const LLUUID SND_SLIDE_METAL_GRAVEL ("2bbff37d-009a-4cfc-9a0d-817652c08fbe");
-const LLUUID SND_SLIDE_METAL_GRAVEL_02 ("a906a228-783b-49e7-9f0a-e20a41d0e39f");
-const LLUUID SND_SLIDE_METAL_METAL ("09461277-c691-45de-b2c5-89dfd3712f79");
-const LLUUID SND_SLIDE_METAL_METAL_02 ("e00a5d97-8fdc-46c1-bd53-7e312727466c");
-const LLUUID SND_SLIDE_METAL_METAL_03 ("8ebfa780-c440-4b52-ab65-5edf3bc15bf1");
-const LLUUID SND_SLIDE_METAL_METAL_04 ("d6d03cb2-5b16-4e31-b7d4-2a81d2a0909b");
-const LLUUID SND_SLIDE_METAL_METAL_05 ("3a46f447-916e-47de-a1e5-95d1af46bd0f");
-const LLUUID SND_SLIDE_METAL_METAL_06 ("cd423231-e70d-4fd2-ad26-f1c6cf5f0610");
-const LLUUID SND_SLIDE_METAL_PLASTIC (SND_NULL);
-const LLUUID SND_SLIDE_METAL_RUBBER ("12d97bc0-3c15-4744-b6bd-77d1316eb4f0");
-const LLUUID SND_SLIDE_METAL_WOOD ("4afb6926-a73f-4cb7-85d5-0f9a40107434");
-const LLUUID SND_SLIDE_METAL_WOOD_02 ("349970bf-187d-4bcb-b2cf-e7bb6581590f");
-const LLUUID SND_SLIDE_METAL_WOOD_03 ("64bf6e87-73d4-4cb4-84f7-55cecfd97cd3");
-const LLUUID SND_SLIDE_METAL_WOOD_04 ("0dc670a9-dbe8-41bc-b8ee-4d96d99219d5");
-const LLUUID SND_SLIDE_METAL_WOOD_05 ("6e3cc57b-c9aa-4829-86a1-8e82aeaccb47");
-const LLUUID SND_SLIDE_METAL_WOOD_06 ("c1237f4c-8c88-4da1-bfbc-2af26a8d9e5a");
-const LLUUID SND_SLIDE_METAL_WOOD_07 ("0e1ec243-063b-4dcb-a903-52b8dffed3d2");
-const LLUUID SND_SLIDE_METAL_WOOD_08 ("66736d0f-533d-4007-a8ee-0f27c2034126");
-const LLUUID SND_SLIDE_PLASTIC_GRAVEL ("35092c21-5c48-4b4d-a818-3cf240af2348");
-const LLUUID SND_SLIDE_PLASTIC_GRAVEL_02("c37f5776-0020-47e8-89a0-c74cc6f5742d");
-const LLUUID SND_SLIDE_PLASTIC_GRAVEL_03("d2fc8db6-2e66-464a-8ccb-f99b61ee4987");
-const LLUUID SND_SLIDE_PLASTIC_GRAVEL_04("93cbdb10-6e82-4c0b-a547-7b3b79ac25f6");
-const LLUUID SND_SLIDE_PLASTIC_GRAVEL_05("2f6d0542-fcd1-4264-a17b-f57bf5ebf402");
-const LLUUID SND_SLIDE_PLASTIC_GRAVEL_06("5b8887d4-3be2-45a0-b25d-85af3b1e6392");
-const LLUUID SND_SLIDE_PLASTIC_PLASTIC (SND_NULL);
-const LLUUID SND_SLIDE_PLASTIC_PLASTIC_02 (SND_NULL);
-const LLUUID SND_SLIDE_PLASTIC_PLASTIC_03 (SND_NULL);
-const LLUUID SND_SLIDE_PLASTIC_FABRIC ("7294d9ad-3e41-4373-992c-a9f21d5d66ad");
-const LLUUID SND_SLIDE_PLASTIC_FABRIC_02("58608ce1-f524-472f-b447-bbe6ce4a46e0");
-const LLUUID SND_SLIDE_PLASTIC_FABRIC_03("06ae285e-0b34-4ea6-84ab-9c6c31b414fc");
-const LLUUID SND_SLIDE_PLASTIC_FABRIC_04("211613db-0461-49bd-9554-5c14ad8b31f6");
-const LLUUID SND_SLIDE_RUBBER_PLASTIC ("a98ffa5a-e48e-4f9d-9242-b9a3210ad84a");
-const LLUUID SND_SLIDE_RUBBER_PLASTIC_02 ("d4136c40-eeaa-49c6-a982-8e5a16f5d93a");
-const LLUUID SND_SLIDE_RUBBER_PLASTIC_03 ("29ec0fb2-0b23-47b2-835b-c83cc7cf9fb0");
-const LLUUID SND_SLIDE_RUBBER_RUBBER (SND_NULL);
-const LLUUID SND_SLIDE_STONE_FLESH (SND_NULL);
-const LLUUID SND_SLIDE_STONE_GLASS (SND_NULL);
-const LLUUID SND_SLIDE_STONE_METAL (SND_NULL);
-const LLUUID SND_SLIDE_STONE_PLASTIC ("afd0bcc3-d41a-4572-9e7f-08a29eeb0b8a");
-const LLUUID SND_SLIDE_STONE_PLASTIC_02 ("881b720a-96cf-4128-bb98-5d87e03e93c7");
-const LLUUID SND_SLIDE_STONE_PLASTIC_03 ("293dac42-658a-4c5a-a7a2-6d4c5e5658b0");
-const LLUUID SND_SLIDE_STONE_RUBBER ("0724b946-6a3f-4eeb-bb50-0a3b33120974");
-const LLUUID SND_SLIDE_STONE_RUBBER_02 ("ada93d00-76e2-4bf1-9ad9-493727630717");
-const LLUUID SND_SLIDE_STONE_STONE ("ade766dc-2e75-4699-9b41-7c8e53d2b3f2");
-const LLUUID SND_SLIDE_STONE_STONE_02 ("66698375-6594-47b0-8046-c3973de1291d");
-const LLUUID SND_SLIDE_STONE_WOOD ("174ef324-ed50-4f65-9479-b4da580aeb3c");
-const LLUUID SND_SLIDE_STONE_WOOD_02 ("33d517fd-ff11-4d01-a7b5-0e3abf818dcf");
-const LLUUID SND_SLIDE_STONE_WOOD_03 ("1bac4b63-e6fd-4659-9761-991284cf4582");
-const LLUUID SND_SLIDE_STONE_WOOD_04 ("a7d28564-6821-4c01-a378-cde98fba7ba9");
-const LLUUID SND_SLIDE_WOOD_FABRIC ("22c58e74-22cd-4960-9ab7-5bf08ab824e5");
-const LLUUID SND_SLIDE_WOOD_FABRIC_02 ("0b0ed22e-4a0f-4617-a4cf-20d0f2b78ccc");
-const LLUUID SND_SLIDE_WOOD_FABRIC_03 ("42b80abb-9823-4b74-a210-326ccf23636a");
-const LLUUID SND_SLIDE_WOOD_FABRIC_04 ("8538298a-1e6b-4b69-a9ee-5e01e4a02b35");
-const LLUUID SND_SLIDE_WOOD_FLESH ("84b026f3-a11c-4366-aa7c-07edcd89b2bb");
-const LLUUID SND_SLIDE_WOOD_FLESH_02 ("2644191f-4848-47ba-8ba7-bddc0bfcb3da");
-const LLUUID SND_SLIDE_WOOD_FLESH_03 ("edb978e4-9be9-456f-b2fc-e8502bfe25be");
-const LLUUID SND_SLIDE_WOOD_FLESH_04 ("bf2b972e-f42a-46d7-b53e-5fca38f5bc61");
-const LLUUID SND_SLIDE_WOOD_GRAVEL ("d063bb4d-0eff-4403-a6cc-c6c6c073e624");
-const LLUUID SND_SLIDE_WOOD_GRAVEL_02 ("511eb679-6d93-47fa-9141-c3ef9261c919");
-const LLUUID SND_SLIDE_WOOD_GRAVEL_03 ("4ed1fd43-4707-4e5c-b7b7-21ec4e72c1ac");
-const LLUUID SND_SLIDE_WOOD_GRAVEL_04 ("99ea89b3-aa76-4b87-99c8-670365c6d8c3");
-const LLUUID SND_SLIDE_WOOD_PLASTIC ("505ca3c4-94a0-4e28-8fc1-ea72a428396b");
-const LLUUID SND_SLIDE_WOOD_PLASTIC_02 ("fc404011-df71-4ed0-8f22-b72bdd18f63c");
-const LLUUID SND_SLIDE_WOOD_PLASTIC_03 ("67dbe225-26df-4efa-8c8b-f1ef669fec45");
-const LLUUID SND_SLIDE_WOOD_RUBBER (SND_NULL);
-const LLUUID SND_SLIDE_WOOD_WOOD ("3079d569-b3e8-4df4-9e09-f0d4611213ef");
-const LLUUID SND_SLIDE_WOOD_WOOD_02 ("276b093d-dbcb-4279-a89e-a54b0b416af6");
-const LLUUID SND_SLIDE_WOOD_WOOD_03 ("c3f3ca5e-2768-4081-847f-247139310fdb");
-const LLUUID SND_SLIDE_WOOD_WOOD_04 ("f08d44b8-ff87-4a98-9561-c72f1f2fec81");
-const LLUUID SND_SLIDE_WOOD_WOOD_05 ("2d8a58cf-f139-4238-8503-27d334d05c85");
-const LLUUID SND_SLIDE_WOOD_WOOD_06 ("e157ebbd-b12d-4225-aa7c-d47b026a7687");
-const LLUUID SND_SLIDE_WOOD_WOOD_07 ("35e17956-e7b4-478c-b274-e37db8a166b2");
-const LLUUID SND_SLIDE_WOOD_WOOD_08 ("e606fc65-0643-4964-9979-ff964fa6a62c");
+extern const LLUUID SND_OOOH_SCARE_ME;
+extern const LLUUID SND_PAYBACK_TIME;
+extern const LLUUID SND_READY_FOR_BATTLE;
+extern const LLUUID SND_FLESH_FLESH;
+extern const LLUUID SND_FLESH_PLASTIC;
+extern const LLUUID SND_FLESH_RUBBER;
+extern const LLUUID SND_GLASS_FLESH;
+extern const LLUUID SND_GLASS_GLASS;
+extern const LLUUID SND_GLASS_PLASTIC;
+extern const LLUUID SND_GLASS_RUBBER;
+extern const LLUUID SND_GLASS_WOOD;
+extern const LLUUID SND_METAL_FLESH;
+extern const LLUUID SND_METAL_GLASS;
+extern const LLUUID SND_METAL_METAL;
+extern const LLUUID SND_METAL_PLASTIC;
+extern const LLUUID SND_METAL_RUBBER;
+extern const LLUUID SND_METAL_WOOD;
+extern const LLUUID SND_PLASTIC_PLASTIC;
+extern const LLUUID SND_RUBBER_PLASTIC;
+extern const LLUUID SND_RUBBER_RUBBER;
+extern const LLUUID SND_STONE_FLESH;
+extern const LLUUID SND_STONE_GLASS;
+extern const LLUUID SND_STONE_METAL;
+extern const LLUUID SND_STONE_PLASTIC;
+extern const LLUUID SND_STONE_RUBBER;
+extern const LLUUID SND_STONE_STONE;
+extern const LLUUID SND_STONE_WOOD;
+extern const LLUUID SND_WOOD_FLESH;
+extern const LLUUID SND_WOOD_PLASTIC;
+extern const LLUUID SND_WOOD_RUBBER;
+extern const LLUUID SND_WOOD_WOOD;
-const LLUUID SND_ROLL_FLESH_FLESH (SND_NULL);
-const LLUUID SND_ROLL_FLESH_PLASTIC ("89a0be4c-848d-4a6e-8886-298f56c2cff4");
-const LLUUID SND_ROLL_FLESH_PLASTIC_02 ("beb06343-1aa1-4af2-b320-5d2ec31c53b1");
-const LLUUID SND_ROLL_FLESH_RUBBER (SND_NULL);
-const LLUUID SND_ROLL_GLASS_GRAVEL ("ba795c74-7e09-4572-b495-e09886a46b86");
-const LLUUID SND_ROLL_GLASS_GRAVEL_02 ("4c93c3b7-14cb-4d9b-a7df-628ad935f1f2");
-const LLUUID SND_ROLL_GLASS_FLESH (SND_NULL);
-const LLUUID SND_ROLL_GLASS_GLASS (SND_NULL);
-const LLUUID SND_ROLL_GLASS_PLASTIC (SND_NULL);
-const LLUUID SND_ROLL_GLASS_RUBBER (SND_NULL);
-const LLUUID SND_ROLL_GLASS_WOOD ("d40b1f48-a061-4f6e-b18f-4326a3dd5c29");
-const LLUUID SND_ROLL_GLASS_WOOD_02 ("78cd407a-bb36-4163-ba09-20f2e6d9d44b");
-const LLUUID SND_ROLL_GRAVEL_GRAVEL ("c7354cc3-6df5-4738-8dbb-b28a6ac46a05");
-const LLUUID SND_ROLL_GRAVEL_GRAVEL_02 ("01d194c4-72a6-47df-81a5-8db430faff87");
-const LLUUID SND_ROLL_METAL_FABRIC ("ce6e6564-20fd-48e4-81e2-cd3f81c00a3e");
-const LLUUID SND_ROLL_METAL_FABRIC_02 ("fc4d0065-32f6-4bb0-9f3f-f4737eb27163");
-const LLUUID SND_ROLL_METAL_FLESH (SND_NULL);
-const LLUUID SND_ROLL_METAL_GLASS ("63d530bb-a41f-402b-aa1f-be6b11959809");
-const LLUUID SND_ROLL_METAL_GLASS_02 ("f62642c2-6db5-4faa-8b77-939067d837c3");
-const LLUUID SND_ROLL_METAL_GLASS_03 ("db5b5a15-2817-4cd7-9f0b-9ad49b5e52c8");
-const LLUUID SND_ROLL_METAL_GRAVEL ("447164e3-9646-4c1a-a16d-606892891466");
-const LLUUID SND_ROLL_METAL_METAL ("c3c22cf3-5d1f-4cc3-b4b5-708b9f65979c");
-const LLUUID SND_ROLL_METAL_METAL_02 ("d8386277-a1ea-460e-b6fd-bb285c323bf1");
-const LLUUID SND_ROLL_METAL_METAL_03 ("69ee1f02-f9cd-4c8b-aedd-39a2d6705680");
-const LLUUID SND_ROLL_METAL_METAL_04 ("5cc6b5fd-26ce-47ad-b21d-3a7c190dd375");
-const LLUUID SND_ROLL_METAL_PLASTIC ("c6a9bbf6-df15-4713-9f84-7237fce4051e");
-const LLUUID SND_ROLL_METAL_PLASTIC_01 ("0fedb59b-2dbb-4cec-b6cc-8559ec027749");
-const LLUUID SND_ROLL_METAL_RUBBER (SND_NULL);
-const LLUUID SND_ROLL_METAL_WOOD ("1d76af57-01b1-4c73-9a1d-69523bfa50ea");
-const LLUUID SND_ROLL_METAL_WOOD_02 ("78aa4e71-8e7c-4b90-a561-3ebdc639f99b");
-const LLUUID SND_ROLL_METAL_WOOD_03 ("777d95bf-962f-48fa-93bf-8c1806557d72");
-const LLUUID SND_ROLL_METAL_WOOD_04 ("1833da76-45e2-4a8b-97da-d17413e056c9");
-const LLUUID SND_ROLL_METAL_WOOD_05 ("b13e1232-3d8d-42e9-92ec-b30f9f823962");
-const LLUUID SND_ROLL_PLASTIC_FABRIC ("616a1f03-209f-4c55-b264-83a000b6ef0a");
-const LLUUID SND_ROLL_PLASTIC_PLASTIC ("873f3d82-00b2-4082-9c69-7aef3461dba1");
-const LLUUID SND_ROLL_PLASTIC_PLASTIC_02 ("cc39879f-ebc8-4405-a4fc-8342f5bed31e");
-const LLUUID SND_ROLL_RUBBER_PLASTIC (SND_NULL);
-const LLUUID SND_ROLL_RUBBER_RUBBER (SND_NULL);
-const LLUUID SND_ROLL_STONE_FLESH (SND_NULL);
-const LLUUID SND_ROLL_STONE_GLASS (SND_NULL);
-const LLUUID SND_ROLL_STONE_METAL (SND_NULL);
-const LLUUID SND_ROLL_STONE_PLASTIC ("155f65a8-cae7-476e-a58b-fd362be7fd0e");
-const LLUUID SND_ROLL_STONE_RUBBER (SND_NULL);
-const LLUUID SND_ROLL_STONE_STONE ("67d56e3f-6ed5-4658-9418-14f020c38b11");
-const LLUUID SND_ROLL_STONE_STONE_02 ("43d99d10-d75b-4246-accf-4ceb2c909aa7");
-const LLUUID SND_ROLL_STONE_STONE_03 ("f04e83ff-eed7-4e99-8f45-eb97e4e1d3b7");
-const LLUUID SND_ROLL_STONE_STONE_04 ("10fcc5ad-fa89-48d6-b774-986b580c1efc");
-const LLUUID SND_ROLL_STONE_STONE_05 ("3d86f5a3-1a91-49d9-b99f-8521a7422497");
-const LLUUID SND_ROLL_STONE_WOOD ("53e46fb7-6c21-4fe1-bffe-0567475d48fa");
-const LLUUID SND_ROLL_STONE_WOOD_02 ("5eba8c9a-a014-4299-87f1-315c45ec795b");
-const LLUUID SND_ROLL_STONE_WOOD_03 ("ea6c05fc-6e9c-4526-8a20-bc47810bb549");
-const LLUUID SND_ROLL_STONE_WOOD_04 ("64618cbf-3f42-4728-8094-e77807545efb");
-const LLUUID SND_ROLL_WOOD_FLESH ("26ee185d-6fc3-49f8-89ba-51cab04cfc42");
-const LLUUID SND_ROLL_WOOD_FLESH_02 ("334faa25-1e80-4c99-b29f-4c9c2a3d079d");
-const LLUUID SND_ROLL_WOOD_FLESH_03 ("2f876626-4dce-4f71-a91e-a25302edfab7");
-const LLUUID SND_ROLL_WOOD_FLESH_04 ("d6877aac-07fc-4931-bcde-585f223802ad");
-const LLUUID SND_ROLL_WOOD_GRAVEL ("2a23ebb5-a4a2-4f1f-8d75-7384239354aa");
-const LLUUID SND_ROLL_WOOD_GRAVEL_02 ("208bf26d-f097-450c-95c4-9d26317c613c");
-const LLUUID SND_ROLL_WOOD_GRAVEL_03 ("a26ecaf4-92c6-4e32-9864-56b7c70cab8e");
-const LLUUID SND_ROLL_WOOD_PLASTIC ("71c1000a-9f16-4cc3-8ede-ec4aa3bf5723");
-const LLUUID SND_ROLL_WOOD_PLASTIC_02 ("7bc20ba6-1e6d-4eea-83ad-c5cc3ae0e409");
-const LLUUID SND_ROLL_WOOD_RUBBER (SND_NULL);
-const LLUUID SND_ROLL_WOOD_WOOD ("2cc8eec4-bb4a-4ba8-b783-71526ec708e8");
-const LLUUID SND_ROLL_WOOD_WOOD_02 ("0a1f8070-a11a-4b4c-b260-5ffb6acb0a5d");
-const LLUUID SND_ROLL_WOOD_WOOD_03 ("160bef64-da9c-4be8-b07b-a5060b501700");
-const LLUUID SND_ROLL_WOOD_WOOD_04 ("1c62ea16-cc60-48ed-829a-68b8f4cf0c1c");
-const LLUUID SND_ROLL_WOOD_WOOD_05 ("be9cc8fe-b920-4bf5-8924-453088cbc03f");
-const LLUUID SND_ROLL_WOOD_WOOD_06 ("a76cfe60-56b0-43b1-8f31-93e56947d78b");
-const LLUUID SND_ROLL_WOOD_WOOD_07 ("0c6aa481-b5bc-4573-ae83-8e16ff27e750");
-const LLUUID SND_ROLL_WOOD_WOOD_08 ("214ab2c7-871a-451b-b0db-4c5677199011");
-const LLUUID SND_ROLL_WOOD_WOOD_09 ("0086e4db-3ac6-4545-b414-6f359bedd9a5");
-const LLUUID SND_SLIDE_STONE_STONE_01 ("2a7dcbd1-d3e6-4767-8432-8322648e7b9d");
+extern const LLUUID SND_SLIDE_FLESH_FLESH;
+extern const LLUUID SND_SLIDE_FLESH_PLASTIC;
+extern const LLUUID SND_SLIDE_FLESH_RUBBER;
+extern const LLUUID SND_SLIDE_FLESH_FABRIC;
+extern const LLUUID SND_SLIDE_FLESH_GRAVEL;
+extern const LLUUID SND_SLIDE_FLESH_GRAVEL_02;
+extern const LLUUID SND_SLIDE_FLESH_GRAVEL_03;
+extern const LLUUID SND_SLIDE_GLASS_GRAVEL;
+extern const LLUUID SND_SLIDE_GLASS_GRAVEL_02;
+extern const LLUUID SND_SLIDE_GLASS_GRAVEL_03;
+extern const LLUUID SND_SLIDE_GLASS_FLESH;
+extern const LLUUID SND_SLIDE_GLASS_GLASS;
+extern const LLUUID SND_SLIDE_GLASS_PLASTIC;
+extern const LLUUID SND_SLIDE_GLASS_RUBBER;
+extern const LLUUID SND_SLIDE_GLASS_WOOD;
+extern const LLUUID SND_SLIDE_METAL_FABRIC;
+extern const LLUUID SND_SLIDE_METAL_FLESH;
+extern const LLUUID SND_SLIDE_METAL_FLESH_02;
+extern const LLUUID SND_SLIDE_METAL_GLASS;
+extern const LLUUID SND_SLIDE_METAL_GLASS_02;
+extern const LLUUID SND_SLIDE_METAL_GLASS_03;
+extern const LLUUID SND_SLIDE_METAL_GLASS_04;
+extern const LLUUID SND_SLIDE_METAL_GRAVEL;
+extern const LLUUID SND_SLIDE_METAL_GRAVEL_02;
+extern const LLUUID SND_SLIDE_METAL_METAL;
+extern const LLUUID SND_SLIDE_METAL_METAL_02;
+extern const LLUUID SND_SLIDE_METAL_METAL_03;
+extern const LLUUID SND_SLIDE_METAL_METAL_04;
+extern const LLUUID SND_SLIDE_METAL_METAL_05;
+extern const LLUUID SND_SLIDE_METAL_METAL_06;
+extern const LLUUID SND_SLIDE_METAL_PLASTIC;
+extern const LLUUID SND_SLIDE_METAL_RUBBER;
+extern const LLUUID SND_SLIDE_METAL_WOOD;
+extern const LLUUID SND_SLIDE_METAL_WOOD_02;
+extern const LLUUID SND_SLIDE_METAL_WOOD_03;
+extern const LLUUID SND_SLIDE_METAL_WOOD_04;
+extern const LLUUID SND_SLIDE_METAL_WOOD_05;
+extern const LLUUID SND_SLIDE_METAL_WOOD_06;
+extern const LLUUID SND_SLIDE_METAL_WOOD_07;
+extern const LLUUID SND_SLIDE_METAL_WOOD_08;
+extern const LLUUID SND_SLIDE_PLASTIC_GRAVEL;
+extern const LLUUID SND_SLIDE_PLASTIC_GRAVEL_02;
+extern const LLUUID SND_SLIDE_PLASTIC_GRAVEL_03;
+extern const LLUUID SND_SLIDE_PLASTIC_GRAVEL_04;
+extern const LLUUID SND_SLIDE_PLASTIC_GRAVEL_05;
+extern const LLUUID SND_SLIDE_PLASTIC_GRAVEL_06;
+extern const LLUUID SND_SLIDE_PLASTIC_PLASTIC;
+extern const LLUUID SND_SLIDE_PLASTIC_PLASTIC_02;
+extern const LLUUID SND_SLIDE_PLASTIC_PLASTIC_03;
+extern const LLUUID SND_SLIDE_PLASTIC_FABRIC;
+extern const LLUUID SND_SLIDE_PLASTIC_FABRIC_02;
+extern const LLUUID SND_SLIDE_PLASTIC_FABRIC_03;
+extern const LLUUID SND_SLIDE_PLASTIC_FABRIC_04;
+extern const LLUUID SND_SLIDE_RUBBER_PLASTIC;
+extern const LLUUID SND_SLIDE_RUBBER_PLASTIC_02;
+extern const LLUUID SND_SLIDE_RUBBER_PLASTIC_03;
+extern const LLUUID SND_SLIDE_RUBBER_RUBBER;
+extern const LLUUID SND_SLIDE_STONE_FLESH;
+extern const LLUUID SND_SLIDE_STONE_GLASS;
+extern const LLUUID SND_SLIDE_STONE_METAL;
+extern const LLUUID SND_SLIDE_STONE_PLASTIC;
+extern const LLUUID SND_SLIDE_STONE_PLASTIC_02;
+extern const LLUUID SND_SLIDE_STONE_PLASTIC_03;
+extern const LLUUID SND_SLIDE_STONE_RUBBER;
+extern const LLUUID SND_SLIDE_STONE_RUBBER_02;
+extern const LLUUID SND_SLIDE_STONE_STONE;
+extern const LLUUID SND_SLIDE_STONE_STONE_02;
+extern const LLUUID SND_SLIDE_STONE_WOOD;
+extern const LLUUID SND_SLIDE_STONE_WOOD_02;
+extern const LLUUID SND_SLIDE_STONE_WOOD_03;
+extern const LLUUID SND_SLIDE_STONE_WOOD_04;
+extern const LLUUID SND_SLIDE_WOOD_FABRIC;
+extern const LLUUID SND_SLIDE_WOOD_FABRIC_02;
+extern const LLUUID SND_SLIDE_WOOD_FABRIC_03;
+extern const LLUUID SND_SLIDE_WOOD_FABRIC_04;
+extern const LLUUID SND_SLIDE_WOOD_FLESH;
+extern const LLUUID SND_SLIDE_WOOD_FLESH_02;
+extern const LLUUID SND_SLIDE_WOOD_FLESH_03;
+extern const LLUUID SND_SLIDE_WOOD_FLESH_04;
+extern const LLUUID SND_SLIDE_WOOD_GRAVEL;
+extern const LLUUID SND_SLIDE_WOOD_GRAVEL_02;
+extern const LLUUID SND_SLIDE_WOOD_GRAVEL_03;
+extern const LLUUID SND_SLIDE_WOOD_GRAVEL_04;
+extern const LLUUID SND_SLIDE_WOOD_PLASTIC;
+extern const LLUUID SND_SLIDE_WOOD_PLASTIC_02;
+extern const LLUUID SND_SLIDE_WOOD_PLASTIC_03;
+extern const LLUUID SND_SLIDE_WOOD_RUBBER;
+extern const LLUUID SND_SLIDE_WOOD_WOOD;
+extern const LLUUID SND_SLIDE_WOOD_WOOD_02;
+extern const LLUUID SND_SLIDE_WOOD_WOOD_03;
+extern const LLUUID SND_SLIDE_WOOD_WOOD_04;
+extern const LLUUID SND_SLIDE_WOOD_WOOD_05;
+extern const LLUUID SND_SLIDE_WOOD_WOOD_06;
+extern const LLUUID SND_SLIDE_WOOD_WOOD_07;
+extern const LLUUID SND_SLIDE_WOOD_WOOD_08;
-const LLUUID SND_STONE_DIRT_01 ("97727335-392c-4338-ac4b-23a7883279c2");
-const LLUUID SND_STONE_DIRT_02 ("cbe75eb2-3375-41d8-9e3f-2ae46b4164ed");
-const LLUUID SND_STONE_DIRT_03 ("31e236ee-001b-4c8e-ad6c-c2074cb64357");
-const LLUUID SND_STONE_DIRT_04 ("c8091652-e04b-4a11-84ba-15dba06e7a1b");
-const LLUUID SND_STONE_STONE_02 ("ba4ef5ac-7435-4240-b826-c24ba8fa5a78");
-const LLUUID SND_STONE_STONE_04 ("ea296329-0f09-4993-af1b-e6784bab1dc9");
+extern const LLUUID SND_ROLL_FLESH_FLESH;
+extern const LLUUID SND_ROLL_FLESH_PLASTIC;
+extern const LLUUID SND_ROLL_FLESH_PLASTIC_02;
+extern const LLUUID SND_ROLL_FLESH_RUBBER;
+extern const LLUUID SND_ROLL_GLASS_GRAVEL;
+extern const LLUUID SND_ROLL_GLASS_GRAVEL_02;
+extern const LLUUID SND_ROLL_GLASS_FLESH;
+extern const LLUUID SND_ROLL_GLASS_GLASS;
+extern const LLUUID SND_ROLL_GLASS_PLASTIC;
+extern const LLUUID SND_ROLL_GLASS_RUBBER;
+extern const LLUUID SND_ROLL_GLASS_WOOD;
+extern const LLUUID SND_ROLL_GLASS_WOOD_02;
+extern const LLUUID SND_ROLL_GRAVEL_GRAVEL;
+extern const LLUUID SND_ROLL_GRAVEL_GRAVEL_02;
+extern const LLUUID SND_ROLL_METAL_FABRIC;
+extern const LLUUID SND_ROLL_METAL_FABRIC_02;
+extern const LLUUID SND_ROLL_METAL_FLESH;
+extern const LLUUID SND_ROLL_METAL_GLASS;
+extern const LLUUID SND_ROLL_METAL_GLASS_02;
+extern const LLUUID SND_ROLL_METAL_GLASS_03;
+extern const LLUUID SND_ROLL_METAL_GRAVEL;
+extern const LLUUID SND_ROLL_METAL_METAL;
+extern const LLUUID SND_ROLL_METAL_METAL_02;
+extern const LLUUID SND_ROLL_METAL_METAL_03;
+extern const LLUUID SND_ROLL_METAL_METAL_04;
+extern const LLUUID SND_ROLL_METAL_PLASTIC;
+extern const LLUUID SND_ROLL_METAL_PLASTIC_01;
+extern const LLUUID SND_ROLL_METAL_RUBBER;
+extern const LLUUID SND_ROLL_METAL_WOOD;
+extern const LLUUID SND_ROLL_METAL_WOOD_02;
+extern const LLUUID SND_ROLL_METAL_WOOD_03;
+extern const LLUUID SND_ROLL_METAL_WOOD_04;
+extern const LLUUID SND_ROLL_METAL_WOOD_05;
+extern const LLUUID SND_ROLL_PLASTIC_FABRIC;
+extern const LLUUID SND_ROLL_PLASTIC_PLASTIC;
+extern const LLUUID SND_ROLL_PLASTIC_PLASTIC_02;
+extern const LLUUID SND_ROLL_RUBBER_PLASTIC;
+extern const LLUUID SND_ROLL_RUBBER_RUBBER;
+extern const LLUUID SND_ROLL_STONE_FLESH;
+extern const LLUUID SND_ROLL_STONE_GLASS;
+extern const LLUUID SND_ROLL_STONE_METAL;
+extern const LLUUID SND_ROLL_STONE_PLASTIC;
+extern const LLUUID SND_ROLL_STONE_RUBBER;
+extern const LLUUID SND_ROLL_STONE_STONE;
+extern const LLUUID SND_ROLL_STONE_STONE_02;
+extern const LLUUID SND_ROLL_STONE_STONE_03;
+extern const LLUUID SND_ROLL_STONE_STONE_04;
+extern const LLUUID SND_ROLL_STONE_STONE_05;
+extern const LLUUID SND_ROLL_STONE_WOOD;
+extern const LLUUID SND_ROLL_STONE_WOOD_02;
+extern const LLUUID SND_ROLL_STONE_WOOD_03;
+extern const LLUUID SND_ROLL_STONE_WOOD_04;
+extern const LLUUID SND_ROLL_WOOD_FLESH;
+extern const LLUUID SND_ROLL_WOOD_FLESH_02;
+extern const LLUUID SND_ROLL_WOOD_FLESH_03;
+extern const LLUUID SND_ROLL_WOOD_FLESH_04;
+extern const LLUUID SND_ROLL_WOOD_GRAVEL;
+extern const LLUUID SND_ROLL_WOOD_GRAVEL_02;
+extern const LLUUID SND_ROLL_WOOD_GRAVEL_03;
+extern const LLUUID SND_ROLL_WOOD_PLASTIC;
+extern const LLUUID SND_ROLL_WOOD_PLASTIC_02;
+extern const LLUUID SND_ROLL_WOOD_RUBBER;
+extern const LLUUID SND_ROLL_WOOD_WOOD;
+extern const LLUUID SND_ROLL_WOOD_WOOD_02;
+extern const LLUUID SND_ROLL_WOOD_WOOD_03;
+extern const LLUUID SND_ROLL_WOOD_WOOD_04;
+extern const LLUUID SND_ROLL_WOOD_WOOD_05;
+extern const LLUUID SND_ROLL_WOOD_WOOD_06;
+extern const LLUUID SND_ROLL_WOOD_WOOD_07;
+extern const LLUUID SND_ROLL_WOOD_WOOD_08;
+extern const LLUUID SND_ROLL_WOOD_WOOD_09;
+extern const LLUUID SND_SLIDE_STONE_STONE_01;
+extern const LLUUID SND_STONE_DIRT_01;
+extern const LLUUID SND_STONE_DIRT_02;
+extern const LLUUID SND_STONE_DIRT_03;
+extern const LLUUID SND_STONE_DIRT_04;
-// extra guids
-#if 0
-const LLUUID SND_ ("a839b8ac-b0af-4ba9-9fde-188754744e02");
-const LLUUID SND_ ("20165fa8-836f-4993-85dc-1529172dcd14");
-const LLUUID SND_ ("fba8e17b-a4b3-4693-9fce-c14800f8a349");
-const LLUUID SND_ ("2d48db8b-7260-4b02-ad2a-b2c6bee60e94");
-const LLUUID SND_ ("956d344b-1808-4d8b-88b1-cbc82b7a96a1");
-const LLUUID SND_ ("b8303cc6-f0b4-4c6f-a199-81f87aba342e");
-const LLUUID SND_ ("fbf7cd0c-bc8f-4cba-9c19-11f4dd03a06b");
-const LLUUID SND_ ("85047f7d-933a-4ce5-a7b5-34670243e1ab");
-const LLUUID SND_ ("0f81acf7-6a2e-4490-957f-c7b0eda00559");
-const LLUUID SND_ ("5631a6a1-79b4-4de8-bccf-1880b6882da1");
-const LLUUID SND_ ("43c87a6b-ffb2-437b-89a0-9deba890a4fc");
-const LLUUID SND_ ("58878d1d-3156-4d01-ac3c-0c4fb99f4d53");
-const LLUUID SND_ ("9a83f321-44bf-40f6-b006-46c085515345");
-const LLUUID SND_ ("ff144533-33ab-40f2-bac8-39c34699ecc4");
-const LLUUID SND_ ("09018e87-d52c-4cd5-9805-015f413319e7");
-const LLUUID SND_ ("17d4c057-7edd-401e-9589-d5b9fe981bf2");
-#endif
+extern const LLUUID SND_STONE_STONE_02;
+extern const LLUUID SND_STONE_STONE_04;
#endif
diff --git a/indra/llmessage/tests/commtest.h b/indra/llmessage/tests/commtest.h
index 7360230451..cf1461ed2b 100644
--- a/indra/llmessage/tests/commtest.h
+++ b/indra/llmessage/tests/commtest.h
@@ -5,7 +5,30 @@
* @brief
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
* Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
diff --git a/indra/llmessage/tests/llareslistener_test.cpp b/indra/llmessage/tests/llareslistener_test.cpp
new file mode 100644
index 0000000000..ac4886ccf4
--- /dev/null
+++ b/indra/llmessage/tests/llareslistener_test.cpp
@@ -0,0 +1,200 @@
+/**
+ * @file llareslistener_test.cpp
+ * @author Mark Palange
+ * @date 2009-02-26
+ * @brief Tests of llareslistener.h.
+ *
+ * $LicenseInfo:firstyear=2009&license=internal$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if LL_WINDOWS
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
+#endif
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "../llareslistener.h"
+// STL headers
+#include <iostream>
+// std headers
+// external library headers
+#include <boost/bind.hpp>
+
+// other Linden headers
+#include "llsd.h"
+#include "llares.h"
+#include "../test/lltut.h"
+#include "llevents.h"
+#include "tests/wrapllerrs.h"
+
+/*****************************************************************************
+* Dummy stuff
+*****************************************************************************/
+LLAres::LLAres():
+ // Simulate this much of the real LLAres constructor: we need an
+ // LLAresListener instance.
+ mListener(new LLAresListener("LLAres", this))
+{}
+LLAres::~LLAres() {}
+void LLAres::rewriteURI(const std::string &uri,
+ LLAres::UriRewriteResponder *resp)
+{
+ // This is the only LLAres method I chose to implement.
+ // The effect is that LLAres returns immediately with
+ // a result that is equal to the input uri.
+ std::vector<std::string> result;
+ result.push_back(uri);
+ resp->rewriteResult(result);
+}
+
+LLAres::QueryResponder::~QueryResponder() {}
+void LLAres::QueryResponder::queryError(int) {}
+void LLAres::QueryResponder::queryResult(char const*, size_t) {}
+LLQueryResponder::LLQueryResponder() {}
+void LLQueryResponder::queryResult(char const*, size_t) {}
+void LLQueryResponder::querySuccess() {}
+void LLAres::UriRewriteResponder::queryError(int) {}
+void LLAres::UriRewriteResponder::querySuccess() {}
+void LLAres::UriRewriteResponder::rewriteResult(const std::vector<std::string>& uris) {}
+
+/*****************************************************************************
+* TUT
+*****************************************************************************/
+namespace tut
+{
+ struct data
+ {
+ LLAres dummyAres;
+ };
+ typedef test_group<data> llareslistener_group;
+ typedef llareslistener_group::object object;
+ llareslistener_group llareslistenergrp("llareslistener");
+
+ struct ResponseCallback
+ {
+ std::vector<std::string> mURIs;
+ bool operator()(const LLSD& response)
+ {
+ mURIs.clear();
+ for (LLSD::array_const_iterator ri(response.beginArray()), rend(response.endArray());
+ ri != rend; ++ri)
+ {
+ mURIs.push_back(*ri);
+ }
+ return false;
+ }
+ };
+
+ template<> template<>
+ void object::test<1>()
+ {
+ set_test_name("test event");
+ // Tests the success and failure cases, since they both use
+ // the same code paths in the LLAres responder.
+ ResponseCallback response;
+ std::string pumpname("trigger");
+ // Since we're asking LLEventPumps to obtain() the pump by the desired
+ // name, it will persist beyond the current scope, so ensure we
+ // disconnect from it when 'response' goes away.
+ LLTempBoundListener temp(
+ LLEventPumps::instance().obtain(pumpname).listen("rewriteURIresponse",
+ boost::bind(&ResponseCallback::operator(), &response, _1)));
+ // Now build an LLSD request that will direct its response events to
+ // that pump.
+ const std::string testURI("login.bar.com");
+ LLSD request;
+ request["op"] = "rewriteURI";
+ request["uri"] = testURI;
+ request["reply"] = pumpname;
+ LLEventPumps::instance().obtain("LLAres").post(request);
+ ensure_equals(response.mURIs.size(), 1);
+ ensure_equals(response.mURIs.front(), testURI);
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ set_test_name("bad op");
+ WrapLL_ERRS capture;
+ LLSD request;
+ request["op"] = "foo";
+ std::string threw;
+ try
+ {
+ LLEventPumps::instance().obtain("LLAres").post(request);
+ }
+ catch (const WrapLL_ERRS::FatalException& e)
+ {
+ threw = e.what();
+ }
+ ensure_contains("LLAresListener bad op", threw, "bad");
+ }
+
+ template<> template<>
+ void object::test<3>()
+ {
+ set_test_name("bad rewriteURI request");
+ WrapLL_ERRS capture;
+ LLSD request;
+ request["op"] = "rewriteURI";
+ std::string threw;
+ try
+ {
+ LLEventPumps::instance().obtain("LLAres").post(request);
+ }
+ catch (const WrapLL_ERRS::FatalException& e)
+ {
+ threw = e.what();
+ }
+ ensure_contains("LLAresListener bad req", threw, "missing");
+ ensure_contains("LLAresListener bad req", threw, "reply");
+ ensure_contains("LLAresListener bad req", threw, "uri");
+ }
+
+ template<> template<>
+ void object::test<4>()
+ {
+ set_test_name("bad rewriteURI request");
+ WrapLL_ERRS capture;
+ LLSD request;
+ request["op"] = "rewriteURI";
+ request["reply"] = "nonexistent";
+ std::string threw;
+ try
+ {
+ LLEventPumps::instance().obtain("LLAres").post(request);
+ }
+ catch (const WrapLL_ERRS::FatalException& e)
+ {
+ threw = e.what();
+ }
+ ensure_contains("LLAresListener bad req", threw, "missing");
+ ensure_contains("LLAresListener bad req", threw, "uri");
+ ensure_does_not_contain("LLAresListener bad req", threw, "reply");
+ }
+
+ template<> template<>
+ void object::test<5>()
+ {
+ set_test_name("bad rewriteURI request");
+ WrapLL_ERRS capture;
+ LLSD request;
+ request["op"] = "rewriteURI";
+ request["uri"] = "foo.bar.com";
+ std::string threw;
+ try
+ {
+ LLEventPumps::instance().obtain("LLAres").post(request);
+ }
+ catch (const WrapLL_ERRS::FatalException& e)
+ {
+ threw = e.what();
+ }
+ ensure_contains("LLAresListener bad req", threw, "missing");
+ ensure_contains("LLAresListener bad req", threw, "reply");
+ ensure_does_not_contain("LLAresListener bad req", threw, "uri");
+ }
+}
diff --git a/indra/llmessage/tests/llcurl_stub.cpp b/indra/llmessage/tests/llcurl_stub.cpp
index 9d1d3fa221..ffbe7bd202 100644
--- a/indra/llmessage/tests/llcurl_stub.cpp
+++ b/indra/llmessage/tests/llcurl_stub.cpp
@@ -2,17 +2,17 @@
* @file llcurl_stub.cpp
* @brief stub class to allow unit testing
*
- * $LicenseInfo:firstyear=2008&license=internal$
- *
- * Copyright (c) 2008, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
* The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
* this source code is governed by the Linden Lab Source Code Disclosure
- * Agreement ("Agreement") { }
+ * Agreement ("Agreement") previously entered between you and Linden
* Lab. By accessing, using, copying, modifying or distributing this
* software, you acknowledge that you have been informed of your
* obligations under the Agreement and agree to abide by those obligations.
- *
+ *
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
@@ -20,8 +20,10 @@
*/
#include "linden_common.h"
+#include "llcurl.h"
LLCurl::Responder::Responder()
+ : mReferenceCount(0)
{
}
@@ -34,7 +36,7 @@ void LLCurl::Responder::completed(U32 status, std::basic_string<char, std::char_
}
else
{
- error(status, reason, mContent);
+ errorWithContent(status, reason, mContent);
}
}
@@ -51,7 +53,7 @@ void LLCurl::Responder::completedRaw(unsigned,
{
}
-void LLCurl::Responder::error(unsigned,
+void LLCurl::Responder::errorWithContent(unsigned,
std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&,
LLSD const&)
{
diff --git a/indra/llmessage/tests/llhost_test.cpp b/indra/llmessage/tests/llhost_test.cpp
new file mode 100644
index 0000000000..7e5c3a117b
--- /dev/null
+++ b/indra/llmessage/tests/llhost_test.cpp
@@ -0,0 +1,256 @@
+/**
+ * @file llhost_test.cpp
+ * @author Adroit
+ * @date 2007-02
+ * @brief llhost test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../llhost.h"
+
+#include "../test/lltut.h"
+
+namespace tut
+{
+ struct host_data
+ {
+ };
+ typedef test_group<host_data> host_test;
+ typedef host_test::object host_object;
+ tut::host_test host_testcase("llhost");
+
+
+ template<> template<>
+ void host_object::test<1>()
+ {
+ LLHost host;
+ ensure("IP address is not NULL", (0 == host.getAddress()) && (0 == host.getPort()) && !host.isOk());
+ }
+ template<> template<>
+ void host_object::test<2>()
+ {
+ U32 ip_addr = 0xc098017d;
+ U32 port = 8080;
+ LLHost host(ip_addr, port);
+ ensure("IP address is invalid", ip_addr == host.getAddress());
+ ensure("Port Number is invalid", port == host.getPort());
+ ensure("IP address and port number both should be ok", host.isOk());
+ }
+
+ template<> template<>
+ void host_object::test<3>()
+ {
+ const char* str = "192.168.1.1";
+ U32 port = 8080;
+ LLHost host(str, port);
+ ensure("IP address could not be processed", (host.getAddress() == ip_string_to_u32(str)));
+ ensure("Port Number is invalid", (port == host.getPort()));
+ }
+
+ template<> template<>
+ void host_object::test<4>()
+ {
+ U32 ip = ip_string_to_u32("192.168.1.1");
+ U32 port = 22;
+ U64 ip_port = (((U64) ip) << 32) | port;
+ LLHost host(ip_port);
+ ensure("IP address is invalid", ip == host.getAddress());
+ ensure("Port Number is invalid", port == host.getPort());
+ }
+
+ template<> template<>
+ void host_object::test<5>()
+ {
+ std::string ip_port_string = "192.168.1.1:8080";
+ U32 ip = ip_string_to_u32("192.168.1.1");
+ U32 port = 8080;
+
+ LLHost host(ip_port_string);
+ ensure("IP address from IP:port is invalid", ip == host.getAddress());
+ ensure("Port Number from from IP:port is invalid", port == host.getPort());
+ }
+
+ template<> template<>
+ void host_object::test<6>()
+ {
+ U32 ip = 0xc098017d, port = 8080;
+ LLHost host;
+ host.set(ip,port);
+ ensure("IP address is invalid", (ip == host.getAddress()));
+ ensure("Port Number is invalid", (port == host.getPort()));
+ }
+
+ template<> template<>
+ void host_object::test<7>()
+ {
+ const char* str = "192.168.1.1";
+ U32 port = 8080, ip;
+ LLHost host;
+ host.set(str,port);
+ ip = ip_string_to_u32(str);
+ ensure("IP address is invalid", (ip == host.getAddress()));
+ ensure("Port Number is invalid", (port == host.getPort()));
+
+ str = "64.233.187.99";
+ ip = ip_string_to_u32(str);
+ host.setAddress(str);
+ ensure("IP address is invalid", (ip == host.getAddress()));
+
+ ip = 0xc098017b;
+ host.setAddress(ip);
+ ensure("IP address is invalid", (ip == host.getAddress()));
+ // should still use the old port
+ ensure("Port Number is invalid", (port == host.getPort()));
+
+ port = 8084;
+ host.setPort(port);
+ ensure("Port Number is invalid", (port == host.getPort()));
+ // should still use the old address
+ ensure("IP address is invalid", (ip == host.getAddress()));
+ }
+
+ template<> template<>
+ void host_object::test<8>()
+ {
+ const std::string str("192.168.1.1");
+ U32 port = 8080;
+ LLHost host;
+ host.set(str,port);
+
+ std::string ip_string = host.getIPString();
+ ensure("Function Failed", (ip_string == str));
+
+ std::string ip_string_port = host.getIPandPort();
+ ensure("Function Failed", (ip_string_port == "192.168.1.1:8080"));
+ }
+
+
+// getHostName() and setHostByName
+ template<> template<>
+ void host_object::test<9>()
+ {
+// skip("setHostByName(\"google.com\"); getHostName() -> (e.g.) \"yx-in-f100.1e100.net\"");
+ std::string hostStr = "linux.org";
+ LLHost host;
+ host.setHostByName(hostStr);
+
+ // reverse DNS will likely result in appending of some
+ // sub-domain to the main hostname. so look for
+ // the main domain name and not do the exact compare
+
+ std::string hostname = host.getHostName();
+ try
+ {
+ ensure("getHostName failed", hostname.find(hostStr) != std::string::npos);
+ }
+ catch (const std::exception&)
+ {
+ std::cerr << "set '" << hostStr << "'; reported '" << hostname << "'" << std::endl;
+ throw;
+ }
+ }
+
+// setHostByName for dotted IP
+ template<> template<>
+ void host_object::test<10>()
+ {
+ std::string hostStr = "64.233.167.99";
+ LLHost host;
+ host.setHostByName(hostStr);
+ ensure("SetHostByName for dotted IP Address failed", host.getAddress() == ip_string_to_u32(hostStr.c_str()));
+ }
+
+ template<> template<>
+ void host_object::test<11>()
+ {
+ LLHost host1(0xc098017d, 8080);
+ LLHost host2 = host1;
+ ensure("Both IP addresses are not same", (host1.getAddress() == host2.getAddress()));
+ ensure("Both port numbers are not same", (host1.getPort() == host2.getPort()));
+ }
+
+ template<> template<>
+ void host_object::test<12>()
+ {
+ LLHost host1("192.168.1.1", 8080);
+ std::string str1 = "192.168.1.1:8080";
+ std::ostringstream stream;
+ stream << host1;
+ ensure("Operator << failed", ( stream.str()== str1));
+
+ // There is no istream >> llhost operator.
+ //std::istringstream is(stream.str());
+ //LLHost host2;
+ //is >> host2;
+ //ensure("Operator >> failed. Not compatible with <<", host1 == host2);
+ }
+
+ // operators ==, !=, <
+ template<> template<>
+ void host_object::test<13>()
+ {
+ U32 ip_addr = 0xc098017d;
+ U32 port = 8080;
+ LLHost host1(ip_addr, port);
+ LLHost host2(ip_addr, port);
+ ensure("operator== failed", host1 == host2);
+
+ // change port
+ host2.setPort(7070);
+ ensure("operator!= failed", host1 != host2);
+
+ // set port back to 8080 and change IP address now
+ host2.setPort(8080);
+ host2.setAddress(ip_addr+10);
+ ensure("operator!= failed", host1 != host2);
+
+ ensure("operator< failed", host1 < host2);
+
+ // set IP address back to same value and change port
+ host2.setAddress(ip_addr);
+ host2.setPort(host1.getPort() + 10);
+ ensure("operator< failed", host1 < host2);
+ }
+
+ // invalid ip address string
+ template<> template<>
+ void host_object::test<14>()
+ {
+ LLHost host1("10.0.1.2", 6143);
+ ensure("10.0.1.2 should be a valid address", host1.isOk());
+
+ LLHost host2("booger-brains", 6143);
+ ensure("booger-brains should be an invalid ip addess", !host2.isOk());
+
+ LLHost host3("255.255.255.255", 6143);
+ ensure("255.255.255.255 should be valid broadcast address", host3.isOk());
+ }
+}
diff --git a/indra/llmessage/tests/llhttpclientadapter_test.cpp b/indra/llmessage/tests/llhttpclientadapter_test.cpp
index bde76db08b..7065c9d7e4 100644
--- a/indra/llmessage/tests/llhttpclientadapter_test.cpp
+++ b/indra/llmessage/tests/llhttpclientadapter_test.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2001-2008, Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -12,12 +12,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
@@ -49,7 +50,7 @@ std::vector<std::string> put_urls;
std::vector<LLSD> put_body;
std::vector<boost::intrusive_ptr<LLCurl::Responder> > put_responders;
-void LLHTTPClient::put(std::string const &url, LLSD const &body, boost::intrusive_ptr<LLCurl::Responder> responder,float)
+void LLHTTPClient::put(const std::string& url, const LLSD& body, boost::intrusive_ptr<LLCurl::Responder> responder, const LLSD& headers, const F32 timeout)
{
put_urls.push_back(url);
put_responders.push_back(responder);
diff --git a/indra/llmessage/tests/llmime_test.cpp b/indra/llmessage/tests/llmime_test.cpp
new file mode 100644
index 0000000000..ad96286731
--- /dev/null
+++ b/indra/llmessage/tests/llmime_test.cpp
@@ -0,0 +1,451 @@
+/**
+ * @file llmime_test.cpp
+ * @author Phoenix
+ * @date 2006-12-24
+ * @brief BRIEF_DESC of llmime_test.cpp
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ *
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llsdserialize.h"
+
+#include "../llmime.h"
+
+#include "../test/lltut.h"
+
+namespace tut
+{
+ struct mime_index
+ {
+ };
+ typedef test_group<mime_index> mime_index_t;
+ typedef mime_index_t::object mime_index_object_t;
+ tut::mime_index_t tut_mime_index("mime_index");
+
+ template<> template<>
+ void mime_index_object_t::test<1>()
+ {
+ LLMimeIndex mime;
+ ensure("no headers", mime.headers().isUndefined());
+ ensure_equals("invalid offset", mime.offset(), -1);
+ ensure_equals("invalid content length", mime.contentLength(), -1);
+ ensure("no content type", mime.contentType().empty());
+ ensure("not multipart", !mime.isMultipart());
+ ensure_equals("no attachments", mime.subPartCount(), 0);
+ }
+
+ template<> template<>
+ void mime_index_object_t::test<2>()
+ {
+ const S32 CONTENT_LENGTH = 6000;
+ const S32 CONTENT_OFFSET = 100;
+ const std::string CONTENT_TYPE = std::string("image/j2c");
+ LLSD headers;
+ headers["Content-Length"] = CONTENT_LENGTH;
+ headers["Content-Type"] = CONTENT_TYPE;
+ LLMimeIndex mime(headers, CONTENT_OFFSET);
+ ensure("headers are map", mime.headers().isMap());
+ ensure_equals("offset", mime.offset(), CONTENT_OFFSET);
+ ensure_equals("content length", mime.contentLength(), CONTENT_LENGTH);
+ ensure_equals("type is image/j2c", mime.contentType(), CONTENT_TYPE);
+ ensure("not multipart", !mime.isMultipart());
+ ensure_equals("no attachments", mime.subPartCount(), 0);
+ }
+
+ template<> template<>
+ void mime_index_object_t::test<3>()
+ {
+ const S32 MULTI_CONTENT_LENGTH = 8000;
+ const S32 MULTI_CONTENT_OFFSET = 100;
+ const std::string MULTI_CONTENT_TYPE = std::string("multipart/mixed");
+ LLSD headers;
+ headers["Content-Length"] = MULTI_CONTENT_LENGTH;
+ headers["Content-Type"] = MULTI_CONTENT_TYPE;
+ LLMimeIndex mime(headers, MULTI_CONTENT_OFFSET);
+ llinfos << "headers: " << LLSDOStreamer<LLSDNotationFormatter>(headers)
+ << llendl;
+
+
+ const S32 META_CONTENT_LENGTH = 700;
+ const S32 META_CONTENT_OFFSET = 69;
+ const std::string META_CONTENT_TYPE = std::string(
+ "text/llsd+xml");
+ headers = LLSD::emptyMap();
+ headers["Content-Length"] = META_CONTENT_LENGTH;
+ headers["Content-Type"] = META_CONTENT_TYPE;
+ LLMimeIndex meta(headers, META_CONTENT_OFFSET);
+ mime.attachSubPart(meta);
+
+ const S32 IMAGE_CONTENT_LENGTH = 6000;
+ const S32 IMAGE_CONTENT_OFFSET = 200;
+ const std::string IMAGE_CONTENT_TYPE = std::string("image/j2c");
+ headers = LLSD::emptyMap();
+ headers["Content-Length"] = IMAGE_CONTENT_LENGTH;
+ headers["Content-Type"] = IMAGE_CONTENT_TYPE;
+ LLMimeIndex image(headers, IMAGE_CONTENT_OFFSET);
+ mime.attachSubPart(image);
+
+ // make sure we have a valid multi-part
+ ensure("is multipart", mime.isMultipart());
+ ensure_equals("multi offset", mime.offset(), MULTI_CONTENT_OFFSET);
+ ensure_equals(
+ "multi content length",
+ mime.contentLength(),
+ MULTI_CONTENT_LENGTH);
+ ensure_equals("two attachments", mime.subPartCount(), 2);
+
+ // make sure ranged gets do the right thing with out of bounds
+ // sub-parts.
+ LLMimeIndex invalid_child(mime.subPart(-1));
+ ensure("no headers", invalid_child.headers().isUndefined());
+ ensure_equals("invalid offset", invalid_child.offset(), -1);
+ ensure_equals(
+ "invalid content length", invalid_child.contentLength(), -1);
+ ensure("no content type", invalid_child.contentType().empty());
+ ensure("not multipart", !invalid_child.isMultipart());
+ ensure_equals("no attachments", invalid_child.subPartCount(), 0);
+
+ invalid_child = mime.subPart(2);
+ ensure("no headers", invalid_child.headers().isUndefined());
+ ensure_equals("invalid offset", invalid_child.offset(), -1);
+ ensure_equals(
+ "invalid content length", invalid_child.contentLength(), -1);
+ ensure("no content type", invalid_child.contentType().empty());
+ ensure("not multipart", !invalid_child.isMultipart());
+ ensure_equals("no attachments", invalid_child.subPartCount(), 0);
+ }
+
+ template<> template<>
+ void mime_index_object_t::test<4>()
+ {
+ const S32 MULTI_CONTENT_LENGTH = 8000;
+ const S32 MULTI_CONTENT_OFFSET = 100;
+ const std::string MULTI_CONTENT_TYPE = std::string("multipart/mixed");
+ LLSD headers;
+ headers["Content-Length"] = MULTI_CONTENT_LENGTH;
+ headers["Content-Type"] = MULTI_CONTENT_TYPE;
+ LLMimeIndex mime(headers, MULTI_CONTENT_OFFSET);
+
+ const S32 META_CONTENT_LENGTH = 700;
+ const S32 META_CONTENT_OFFSET = 69;
+ const std::string META_CONTENT_TYPE = std::string(
+ "application/llsd+xml");
+ headers = LLSD::emptyMap();
+ headers["Content-Length"] = META_CONTENT_LENGTH;
+ headers["Content-Type"] = META_CONTENT_TYPE;
+ LLMimeIndex meta(headers, META_CONTENT_OFFSET);
+ mime.attachSubPart(meta);
+
+ const S32 IMAGE_CONTENT_LENGTH = 6000;
+ const S32 IMAGE_CONTENT_OFFSET = 200;
+ const std::string IMAGE_CONTENT_TYPE = std::string("image/j2c");
+ headers = LLSD::emptyMap();
+ headers["Content-Length"] = IMAGE_CONTENT_LENGTH;
+ headers["Content-Type"] = IMAGE_CONTENT_TYPE;
+ LLMimeIndex image(headers, IMAGE_CONTENT_OFFSET);
+ mime.attachSubPart(image);
+
+ // check what we have
+ ensure("is multipart", mime.isMultipart());
+ ensure_equals("multi offset", mime.offset(), MULTI_CONTENT_OFFSET);
+ ensure_equals(
+ "multi content length",
+ mime.contentLength(),
+ MULTI_CONTENT_LENGTH);
+ ensure_equals("two attachments", mime.subPartCount(), 2);
+
+ LLMimeIndex actual_meta = mime.subPart(0);
+ ensure_equals(
+ "meta type", actual_meta.contentType(), META_CONTENT_TYPE);
+ ensure_equals(
+ "meta offset", actual_meta.offset(), META_CONTENT_OFFSET);
+ ensure_equals(
+ "meta content length",
+ actual_meta.contentLength(),
+ META_CONTENT_LENGTH);
+
+ LLMimeIndex actual_image = mime.subPart(1);
+ ensure_equals(
+ "image type", actual_image.contentType(), IMAGE_CONTENT_TYPE);
+ ensure_equals(
+ "image offset", actual_image.offset(), IMAGE_CONTENT_OFFSET);
+ ensure_equals(
+ "image content length",
+ actual_image.contentLength(),
+ IMAGE_CONTENT_LENGTH);
+ }
+
+/*
+ template<> template<>
+ void mime_index_object_t::test<5>()
+ {
+ }
+ template<> template<>
+ void mime_index_object_t::test<6>()
+ {
+ }
+ template<> template<>
+ void mime_index_object_t::test<7>()
+ {
+ }
+ template<> template<>
+ void mime_index_object_t::test<8>()
+ {
+ }
+ template<> template<>
+ void mime_index_object_t::test<>()
+ {
+ }
+*/
+}
+
+
+namespace tut
+{
+ struct mime_parse
+ {
+ };
+ typedef test_group<mime_parse> mime_parse_t;
+ typedef mime_parse_t::object mime_parse_object_t;
+ tut::mime_parse_t tut_mime_parse("mime_parse");
+
+ template<> template<>
+ void mime_parse_object_t::test<1>()
+ {
+ // parse one mime object
+ const std::string SERIALIZED_MIME("Content-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n");
+ std::stringstream istr;
+ istr.str(SERIALIZED_MIME);
+ LLMimeIndex mime;
+ LLMimeParser parser;
+ bool ok = parser.parseIndex(istr, mime);
+ ensure("Parse successful.", ok);
+ ensure_equals("content type", mime.contentType(), "text/plain");
+ ensure_equals("content length", mime.contentLength(), 200);
+ ensure_equals("offset", mime.offset(), 49);
+ }
+
+ template<> template<>
+ void mime_parse_object_t::test<2>()
+ {
+ // make sure we only parse one.
+ const std::string SERIALIZED_MIME("Content-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n\r\nContent-Length: 200\r\nContent-Type: text/plain\r\n\r\naaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccc\r\n\r\n");
+ std::stringstream istr;
+ istr.str(SERIALIZED_MIME);
+ LLMimeIndex mime;
+ LLMimeParser parser;
+ bool ok = parser.parseIndex(istr, mime);
+ ensure("Parse successful.", ok);
+ ensure("not multipart.", !mime.isMultipart());
+ ensure_equals("content type", mime.contentType(), "text/plain");
+ ensure_equals("content length", mime.contentLength(), 200);
+ ensure_equals("offset", mime.offset(), 49);
+ }
+
+ template<> template<>
+ void mime_parse_object_t::test<3>()
+ {
+ // test multi-part and lack of content length for some of it.
+ /*
+Content-Type: multipart/mixed; boundary="segment"rnContent-Length: 148rnrn--segmentrnContent-Type: text/plainrnrnsome datarnrn--segmentrnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn
+ */
+ const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=\"segment\"\r\nContent-Length: 150\r\n\r\n--segment\r\nContent-Type: text/plain\r\n\r\nsome data\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
+ std::stringstream istr;
+ istr.str(SERIALIZED_MIME);
+ LLMimeIndex mime;
+ LLMimeParser parser;
+ bool ok = parser.parseIndex(istr, mime);
+ ensure("Parse successful.", ok);
+ ensure("is multipart.", mime.isMultipart());
+ ensure_equals("sub-part count", mime.subPartCount(), 2);
+ ensure_equals("content length", mime.contentLength(), 150);
+ ensure_equals("data offset for multipart", mime.offset(), 74);
+
+ LLMimeIndex mime_plain(mime.subPart(0));
+ ensure_equals(
+ "first part type",
+ mime_plain.contentType(),
+ "text/plain");
+ ensure_equals(
+ "first part content length not known.",
+ mime_plain.contentLength(),
+ -1);
+ ensure_equals("first part offset", mime_plain.offset(), 113);
+
+ LLMimeIndex mime_xml(mime.subPart(1));
+ ensure_equals(
+ "second part type",
+ mime_xml.contentType(),
+ "text/xml; charset=UTF-8");
+ ensure_equals(
+ "second part content length",
+ mime_xml.contentLength(),
+ 22);
+ ensure_equals("second part offset", mime_xml.offset(), 198);
+ }
+
+ template<> template<>
+ void mime_parse_object_t::test<4>()
+ {
+ // test multi-part, unquoted separator, and premature eof conditions
+ /*
+Content-Type: multipart/mixed; boundary=segmentrnContent-Length: 220rnrn--segmentrnContent-Type: text/plainrnContent-Length: 55rnrnhow are you today?rnI do not know. I guess I am:n'fine'rnrn--segmentrnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn */
+ const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=segment\r\nContent-Length: 220\r\n\r\n--segment\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
+ std::stringstream istr;
+ istr.str(SERIALIZED_MIME);
+ LLMimeIndex mime;
+ LLMimeParser parser;
+ bool ok = parser.parseIndex(istr, mime);
+ ensure("Parse successful.", ok);
+ ensure("is multipart.", mime.isMultipart());
+ ensure_equals("sub-part count", mime.subPartCount(), 2);
+ ensure_equals("content length", mime.contentLength(), 220);
+ ensure_equals("data offset for multipart", mime.offset(), 72);
+
+ LLMimeIndex mime_plain(mime.subPart(0));
+ ensure_equals(
+ "first part type",
+ mime_plain.contentType(),
+ "text/plain");
+ ensure_equals(
+ "first part content length",
+ mime_plain.contentLength(),
+ 55);
+ ensure_equals("first part offset", mime_plain.offset(), 131);
+
+ LLMimeIndex mime_xml(mime.subPart(1));
+ ensure_equals(
+ "second part type",
+ mime_xml.contentType(),
+ "text/xml; charset=UTF-8");
+ ensure_equals(
+ "second part content length",
+ mime_xml.contentLength(),
+ 22);
+ ensure_equals("second part offset", mime_xml.offset(), 262);
+ }
+
+ template<> template<>
+ void mime_parse_object_t::test<5>()
+ {
+ // test multi-part with multiple params
+ const std::string SERIALIZED_MIME("Content-Type: multipart/mixed; boundary=segment; comment=\"testing multiple params.\"\r\nContent-Length: 220\r\n\r\n--segment\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--segment\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
+ std::stringstream istr;
+ istr.str(SERIALIZED_MIME);
+ LLMimeIndex mime;
+ LLMimeParser parser;
+ bool ok = parser.parseIndex(istr, mime);
+ ensure("Parse successful.", ok);
+ ensure("is multipart.", mime.isMultipart());
+ ensure_equals("sub-part count", mime.subPartCount(), 2);
+ ensure_equals("content length", mime.contentLength(), 220);
+
+ LLMimeIndex mime_plain(mime.subPart(0));
+ ensure_equals(
+ "first part type",
+ mime_plain.contentType(),
+ "text/plain");
+ ensure_equals(
+ "first part content length",
+ mime_plain.contentLength(),
+ 55);
+
+ LLMimeIndex mime_xml(mime.subPart(1));
+ ensure_equals(
+ "second part type",
+ mime_xml.contentType(),
+ "text/xml; charset=UTF-8");
+ ensure_equals(
+ "second part content length",
+ mime_xml.contentLength(),
+ 22);
+ }
+
+ template<> template<>
+ void mime_parse_object_t::test<6>()
+ {
+ // test multi-part with no specified boundary and eof
+/*
+Content-Type: multipart/relatedrnContent-Length: 220rnrn--rnContent-Type: text/plainrnContent-Length: 55rnrnhow are you today?rnI do not know. I guess I am:n'fine'rnrn--rnContent-Type: text/xml; charset=UTF-8rnContent-Length: 22rnrn<llsd><undef /></llsd>rnrn
+*/
+ const std::string SERIALIZED_MIME("Content-Type: multipart/related\r\nContent-Length: 500\r\n\r\n--\r\nContent-Type: text/plain\r\nContent-Length: 55\r\n\r\nhow are you today?\r\nI do not know. I guess I am:\n'fine'\r\n\r\n--\r\nContent-Type: text/xml; charset=UTF-8\r\nContent-Length: 22\r\n\r\n<llsd><undef /></llsd>\r\n\r\n");
+ std::stringstream istr;
+ istr.str(SERIALIZED_MIME);
+ LLMimeIndex mime;
+ LLMimeParser parser;
+ bool ok = parser.parseIndex(istr, mime);
+ ensure("Parse successful.", ok);
+ ensure("is multipart.", mime.isMultipart());
+ ensure_equals("sub-part count", mime.subPartCount(), 2);
+ ensure_equals("content length", mime.contentLength(), 500);
+ ensure_equals("data offset for multipart", mime.offset(), 56);
+
+ LLMimeIndex mime_plain(mime.subPart(0));
+ ensure_equals(
+ "first part type",
+ mime_plain.contentType(),
+ "text/plain");
+ ensure_equals(
+ "first part content length",
+ mime_plain.contentLength(),
+ 55);
+ ensure_equals("first part offset", mime_plain.offset(), 108);
+
+ LLMimeIndex mime_xml(mime.subPart(1));
+ ensure_equals(
+ "second part type",
+ mime_xml.contentType(),
+ "text/xml; charset=UTF-8");
+ ensure_equals(
+ "second part content length",
+ mime_xml.contentLength(),
+ 22);
+ ensure_equals("second part offset", mime_xml.offset(), 232);
+ }
+
+/*
+ template<> template<>
+ void mime_parse_object_t::test<>()
+ {
+ }
+ template<> template<>
+ void mime_parse_object_t::test<>()
+ {
+ }
+ template<> template<>
+ void mime_parse_object_t::test<>()
+ {
+ }
+ template<> template<>
+ void mime_parse_object_t::test<>()
+ {
+ }
+*/
+}
diff --git a/indra/llmessage/tests/llmockhttpclient.h b/indra/llmessage/tests/llmockhttpclient.h
new file mode 100644
index 0000000000..2f55e97fcc
--- /dev/null
+++ b/indra/llmessage/tests/llmockhttpclient.h
@@ -0,0 +1,61 @@
+/**
+ * @file
+ * @brief
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+ * this source code is governed by the Linden Lab Source Code Disclosure
+ * Agreement ("Agreement") previously entered between you and Linden
+ * Lab. By accessing, using, copying, modifying or distributing this
+ * software, you acknowledge that you have been informed of your
+ * obligations under the Agreement and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+/* Macro Definitions */
+#ifndef LL_LLMOCKHTTPCLIENT_H
+#define LL_LLMOCKHTTPCLIENT_H
+
+#include "linden_common.h"
+#include "llhttpclientinterface.h"
+
+#include <gmock/gmock.h>
+
+class LLMockHTTPClient : public LLHTTPClientInterface
+{
+public:
+ MOCK_METHOD2(get, void(const std::string& url, LLCurl::ResponderPtr responder));
+ MOCK_METHOD3(get, void(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers));
+ MOCK_METHOD3(put, void(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder));
+};
+
+// A helper to match responder types
+template<typename T>
+struct ResponderType
+{
+ bool operator()(LLCurl::ResponderPtr ptr) const
+ {
+ T* p = dynamic_cast<T*>(ptr.get());
+ return p != NULL;
+ }
+};
+
+inline bool operator==(const LLSD& l, const LLSD& r)
+{
+ std::ostringstream ls, rs;
+ ls << l;
+ rs << r;
+ return ls.str() == rs.str();
+
+}
+
+
+#endif //LL_LLMOCKHTTPCLIENT_H
+
diff --git a/indra/llmessage/tests/llnamevalue_test.cpp b/indra/llmessage/tests/llnamevalue_test.cpp
new file mode 100644
index 0000000000..bef4c06334
--- /dev/null
+++ b/indra/llmessage/tests/llnamevalue_test.cpp
@@ -0,0 +1,412 @@
+/**
+ * @file llnamevalue_test.cpp
+ * @author Adroit
+ * @date 2007-02
+ * @brief LLNameValue unit test
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llsdserialize.h"
+
+#include "../llnamevalue.h"
+
+#include "../test/lltut.h"
+
+
+#if LL_WINDOWS
+// disable unreachable code warnings
+#pragma warning(disable: 4702)
+#endif
+
+namespace tut
+{
+ struct namevalue_test
+ {
+ namevalue_test()
+ {
+ }
+ };
+ typedef test_group<namevalue_test> namevalue_t;
+ typedef namevalue_t::object namevalue_object_t;
+ tut::namevalue_t tut_namevalue("namevalue_test");
+
+
+ template<> template<>
+ void namevalue_object_t::test<1>()
+ {
+ // LLNameValue()
+ LLNameValue nValue;
+ ensure("mName should have been NULL", nValue.mName == NULL);
+ ensure("getTypeEnum failed",nValue.getTypeEnum() == NVT_NULL);
+ ensure("getClassEnum failed",nValue.getClassEnum() == NVC_NULL);
+ ensure("getSendtoEnum failed",nValue.getSendtoEnum() == NVS_NULL);
+
+ LLNameValue nValue1(" SecondLife ASSET RW SIM 232324343");
+
+ }
+
+ // LLNameValue(const char* data);
+ // LLNameValue(const char* name, const char* data, const char* type, const char* nvclass, const char* nvsendto,
+ // TNameValueCallback nvcb = NULL, void** user_data = NULL);
+ template<> template<>
+ void namevalue_object_t::test<2>()
+ {
+ LLNameValue nValue(" SecondLife ASSET RW S 232324343");
+ ensure("mName not set correctly", (0 == strcmp(nValue.mName,"SecondLife")));
+ ensure("getTypeEnum failed", nValue.getTypeEnum() == NVT_ASSET);
+ ensure("getClassEnum failed", nValue.getClassEnum() == NVC_READ_WRITE);
+ ensure("getSendtoEnum failed", nValue.getSendtoEnum() == NVS_SIM);
+ ensure("getString failed", (0==strcmp(nValue.getAsset(),"232324343")));
+ ensure("sendToData or sendToViewer failed", !nValue.sendToData() && !nValue.sendToViewer());
+
+ LLNameValue nValue1("\n\r SecondLife_1 STRING READ_WRITE SIM 232324343");
+ ensure("1. mName not set correctly", (0 == strcmp(nValue1.mName,"SecondLife_1")));
+ ensure("1. getTypeEnum failed", nValue1.getTypeEnum() == NVT_STRING);
+ ensure("1. getClassEnum failed", nValue1.getClassEnum() == NVC_READ_WRITE);
+ ensure("1. getSendtoEnum failed", nValue1.getSendtoEnum() == NVS_SIM);
+ ensure("1. getString failed", (0==strcmp(nValue1.getString(),"232324343")));
+ ensure("1. sendToData or sendToViewer failed", !nValue1.sendToData() && !nValue1.sendToViewer());
+
+ LLNameValue nValue2("SecondLife", "23.5", "F32", "R", "DS");
+ ensure("2. getTypeEnum failed", nValue2.getTypeEnum() == NVT_F32);
+ ensure("2. getClassEnum failed", nValue2.getClassEnum() == NVC_READ_ONLY);
+ ensure("2. getSendtoEnum failed", nValue2.getSendtoEnum() == NVS_DATA_SIM);
+ ensure("2. getF32 failed", *nValue2.getF32() == 23.5f);
+ ensure("2. sendToData or sendToViewer failed", nValue2.sendToData() && !nValue2.sendToViewer());
+
+ LLNameValue nValue3("SecondLife", "-43456787", "S32", "READ_ONLY", "SIM_SPACE");
+ ensure("3. getTypeEnum failed", nValue3.getTypeEnum() == NVT_S32);
+ ensure("3. getClassEnum failed", nValue3.getClassEnum() == NVC_READ_ONLY);
+ ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_DATA_SIM);
+ ensure("3. getS32 failed", *nValue3.getS32() == -43456787);
+ ensure("sendToData or sendToViewer failed", nValue3.sendToData() && !nValue3.sendToViewer());
+
+ LLNameValue nValue4("SecondLife", "<1.0, 2.0, 3.0>", "VEC3", "RW", "SV");
+ LLVector3 llvec4(1.0, 2.0, 3.0);
+ ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3);
+ ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE);
+ ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM_VIEWER);
+ ensure("4. getVec3 failed", *nValue4.getVec3() == llvec4);
+ ensure("4. sendToData or sendToViewer failed", !nValue4.sendToData() && nValue4.sendToViewer());
+
+ LLNameValue nValue5("SecondLife", "-1.0, 2.4, 3", "VEC3", "RW", "SIM_VIEWER");
+ LLVector3 llvec5(-1.0f, 2.4f, 3);
+ ensure("5. getTypeEnum failed", nValue5.getTypeEnum() == NVT_VEC3);
+ ensure("5. getClassEnum failed", nValue5.getClassEnum() == NVC_READ_WRITE);
+ ensure("5. getSendtoEnum failed", nValue5.getSendtoEnum() == NVS_SIM_VIEWER);
+ ensure("5. getVec3 failed", *nValue5.getVec3() == llvec5);
+ ensure("5. sendToData or sendToViewer failed", !nValue5.sendToData() && nValue5.sendToViewer());
+
+ LLNameValue nValue6("SecondLife", "89764323", "U32", "RW", "DSV");
+ ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32);
+ ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE);
+ ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_DATA_SIM_VIEWER);
+ ensure("6. getU32 failed", *nValue6.getU32() == 89764323);
+ ensure("6. sendToData or sendToViewer failed", nValue6.sendToData() && nValue6.sendToViewer());
+
+ LLNameValue nValue7("SecondLife", "89764323323232", "U64", "RW", "SIM_SPACE_VIEWER");
+ U64 u64_7 = U64L(89764323323232);
+ ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64);
+ ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE);
+ ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_DATA_SIM_VIEWER);
+ ensure("7. getU32 failed", *nValue7.getU64() == u64_7);
+ ensure("7. sendToData or sendToViewer failed", nValue7.sendToData() && nValue7.sendToViewer());
+ }
+
+ // LLNameValue(const char* name, const char* data, const char* type, const char* nvclass,
+ // TNameValueCallback nvcb = NULL, void** user_data = NULL);
+ template<> template<>
+ void namevalue_object_t::test<3>()
+ {
+ LLNameValue nValue("SecondLife", "232324343", "ASSET", "READ_WRITE");
+ ensure("mName not set correctly", (0 == strcmp(nValue.mName,"SecondLife")));
+ ensure("getTypeEnum failed", nValue.getTypeEnum() == NVT_ASSET);
+ ensure("getClassEnum failed", nValue.getClassEnum() == NVC_READ_WRITE);
+ ensure("getSendtoEnum failed", nValue.getSendtoEnum() == NVS_SIM);
+ ensure("getString failed", (0==strcmp(nValue.getAsset(),"232324343")));
+
+ LLNameValue nValue1("SecondLife", "232324343", "STRING", "READ_WRITE");
+ ensure("1. mName not set correctly", (0 == strcmp(nValue1.mName,"SecondLife")));
+ ensure("1. getTypeEnum failed", nValue1.getTypeEnum() == NVT_STRING);
+ ensure("1. getClassEnum failed", nValue1.getClassEnum() == NVC_READ_WRITE);
+ ensure("1. getSendtoEnum failed", nValue1.getSendtoEnum() == NVS_SIM);
+ ensure("1. getString failed", (0==strcmp(nValue1.getString(),"232324343")));
+
+ LLNameValue nValue2("SecondLife", "23.5", "F32", "R");
+ ensure("2. getTypeEnum failed", nValue2.getTypeEnum() == NVT_F32);
+ ensure("2. getClassEnum failed", nValue2.getClassEnum() == NVC_READ_ONLY);
+ ensure("2. getSendtoEnum failed", nValue2.getSendtoEnum() == NVS_SIM);
+ ensure("2. getF32 failed", *nValue2.getF32() == 23.5f);
+
+ LLNameValue nValue3("SecondLife", "-43456787", "S32", "READ_ONLY");
+ ensure("3. getTypeEnum failed", nValue3.getTypeEnum() == NVT_S32);
+ ensure("3. getClassEnum failed", nValue3.getClassEnum() == NVC_READ_ONLY);
+ ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_SIM);
+ ensure("3. getS32 failed", *nValue3.getS32() == -43456787);
+
+ LLNameValue nValue4("SecondLife", "<1.0, 2.0, 3.0>", "VEC3", "RW");
+ LLVector3 llvec4(1.0, 2.0, 3.0);
+ ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3);
+ ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE);
+ ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM);
+ ensure("4. getVec3 failed", *nValue4.getVec3() == llvec4);
+
+ LLNameValue nValue5("SecondLife", "-1.0, 2.4, 3", "VEC3", "RW");
+ LLVector3 llvec5(-1.0f, 2.4f, 3);
+ ensure("5. getTypeEnum failed", nValue5.getTypeEnum() == NVT_VEC3);
+ ensure("5. getClassEnum failed", nValue5.getClassEnum() == NVC_READ_WRITE);
+ ensure("5. getSendtoEnum failed", nValue5.getSendtoEnum() == NVS_SIM);
+ ensure("5. getVec3 failed", *nValue5.getVec3() == llvec5);
+
+ LLNameValue nValue6("SecondLife", "89764323", "U32", "RW");
+ ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32);
+ ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE);
+ ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_SIM);
+ ensure("6. getU32 failed", *nValue6.getU32() == 89764323);
+
+ LLNameValue nValue7("SecondLife", "89764323323232", "U64", "RW");
+ U64 u64_7 = U64L(89764323323232);
+ ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64);
+ ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE);
+ ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_SIM);
+ ensure("7. getU32 failed", *nValue7.getU64() == u64_7);
+ }
+
+ // LLNameValue(const char* name, const char* type, const char* nvclass,
+ // TNameValueCallback nvcb = NULL, void** user_data = NULL);
+ template<> template<>
+ void namevalue_object_t::test<4>()
+ {
+ LLNameValue nValue("SecondLife", "STRING", "READ_WRITE");
+ ensure("mName not set correctly", (0 == strcmp(nValue.mName,"SecondLife")));
+ ensure("getTypeEnum failed", nValue.getTypeEnum() == NVT_STRING);
+ ensure("getClassEnum failed", nValue.getClassEnum() == NVC_READ_WRITE);
+ ensure("getSendtoEnum failed", nValue.getSendtoEnum() == NVS_SIM);
+
+ LLNameValue nValue1("SecondLife", "ASSET", "READ_WRITE");
+ ensure("1. mName not set correctly", (0 == strcmp(nValue1.mName,"SecondLife")));
+ ensure("1. getTypeEnum for RW failed", nValue1.getTypeEnum() == NVT_ASSET);
+ ensure("1. getClassEnum for RW failed", nValue1.getClassEnum() == NVC_READ_WRITE);
+ ensure("1. getSendtoEnum for RW failed", nValue1.getSendtoEnum() == NVS_SIM);
+
+ LLNameValue nValue2("SecondLife", "F32", "READ_ONLY");
+ ensure("2. getTypeEnum failed", nValue2.getTypeEnum() == NVT_F32);
+ ensure("2. getClassEnum failed", nValue2.getClassEnum() == NVC_READ_ONLY);
+ ensure("2. getSendtoEnum failed", nValue2.getSendtoEnum() == NVS_SIM);
+
+ LLNameValue nValue3("SecondLife", "S32", "READ_ONLY");
+ ensure("3. getTypeEnum failed", nValue3.getTypeEnum() == NVT_S32);
+ ensure("3. getClassEnum failed", nValue3.getClassEnum() == NVC_READ_ONLY);
+ ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_SIM);
+
+ LLNameValue nValue4("SecondLife", "VEC3", "READ_WRITE");
+ ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3);
+ ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE);
+ ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM);
+
+ LLNameValue nValue6("SecondLife", "U32", "READ_WRITE");
+ ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32);
+ ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE);
+ ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_SIM);
+
+ LLNameValue nValue7("SecondLife", "U64", "READ_WRITE");
+ ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64);
+ ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE);
+ ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_SIM);
+ }
+
+ template<> template<>
+ void namevalue_object_t::test<5>()
+ {
+ LLNameValue nValue("SecondLife", "This is a test", "STRING", "RW", "SIM");
+
+ ensure("getString failed", (0 == strcmp(nValue.getString(),"This is a test")));
+ }
+
+ template<> template<>
+ void namevalue_object_t::test<6>()
+ {
+ LLNameValue nValue("SecondLife", "This is a test", "ASSET", "RW", "S");
+ ensure("getAsset failed", (0 == strcmp(nValue.getAsset(),"This is a test")));
+ }
+
+ template<> template<>
+ void namevalue_object_t::test<7>()
+ {
+ LLNameValue nValue("SecondLife", "555555", "F32", "RW", "SIM");
+
+ ensure("getF32 failed",*nValue.getF32() == 555555.f);
+ }
+
+ template<> template<>
+ void namevalue_object_t::test<8>()
+ {
+ LLNameValue nValue("SecondLife", "-5555", "S32", "RW", "SIM");
+
+ ensure("getS32 failed", *nValue.getS32() == -5555);
+
+ S32 sVal = 0x7FFFFFFF;
+ nValue.setS32(sVal);
+ ensure("getS32 failed", *nValue.getS32() == sVal);
+
+ sVal = -0x7FFFFFFF;
+ nValue.setS32(sVal);
+ ensure("getS32 failed", *nValue.getS32() == sVal);
+
+ sVal = 0;
+ nValue.setS32(sVal);
+ ensure("getS32 failed", *nValue.getS32() == sVal);
+ }
+
+ template<> template<>
+ void namevalue_object_t::test<9>()
+ {
+ LLNameValue nValue("SecondLife", "<-3, 2, 1>", "VEC3", "RW", "SIM");
+ LLVector3 vecExpected(-3, 2, 1);
+ LLVector3 vec;
+ nValue.getVec3(vec);
+ ensure("getVec3 failed", vec == vecExpected);
+ }
+
+ template<> template<>
+ void namevalue_object_t::test<10>()
+ {
+ LLNameValue nValue("SecondLife", "12345678", "U32", "RW", "SIM");
+
+ ensure("getU32 failed",*nValue.getU32() == 12345678);
+
+ U32 val = 0xFFFFFFFF;
+ nValue.setU32(val);
+ ensure("U32 max", *nValue.getU32() == val);
+
+ val = 0;
+ nValue.setU32(val);
+ ensure("U32 min", *nValue.getU32() == val);
+ }
+
+ template<> template<>
+ void namevalue_object_t::test<11>()
+ {
+ //skip_fail("incomplete support for U64.");
+ LLNameValue nValue("SecondLife", "44444444444", "U64", "RW", "SIM");
+
+ ensure("getU64 failed",*nValue.getU64() == U64L(44444444444));
+
+ // there is no LLNameValue::setU64()
+ }
+
+
+ template<> template<>
+ void namevalue_object_t::test<12>()
+ {
+ //skip_fail("incomplete support for U64.");
+ LLNameValue nValue("SecondLife U64 RW DSV 44444444444");
+ std::string ret_str = nValue.printNameValue();
+
+ ensure_equals("1:printNameValue failed",ret_str,"SecondLife U64 RW DSV 44444444444");
+
+ LLNameValue nValue1(ret_str.c_str());
+ ensure_equals("Serialization of printNameValue failed", *nValue.getU64(), *nValue1.getU64());
+ }
+
+ template<> template<>
+ void namevalue_object_t::test<13>()
+ {
+ LLNameValue nValue("SecondLife STRING RW DSV 44444444444");
+ std::string ret_str = nValue.printData();
+ ensure_equals("1:printData failed",ret_str,"44444444444");
+
+ LLNameValue nValue1("SecondLife S32 RW DSV 44444");
+ ret_str = nValue1.printData();
+ ensure_equals("2:printData failed",ret_str,"44444");
+ }
+
+ template<> template<>
+ void namevalue_object_t::test<14>()
+ {
+ LLNameValue nValue("SecodLife STRING RW SIM 22222");
+ std::ostringstream stream1,stream2,stream3, stream4, stream5;
+ stream1 << nValue;
+ ensure_equals("STRING << failed",stream1.str(),"22222");
+
+ LLNameValue nValue1("SecodLife F32 RW SIM 22222");
+ stream2 << nValue1;
+ ensure_equals("F32 << failed",stream2.str(),"22222");
+
+ LLNameValue nValue2("SecodLife S32 RW SIM 22222");
+ stream3<< nValue2;
+ ensure_equals("S32 << failed",stream3.str(),"22222");
+
+ LLNameValue nValue3("SecodLife U32 RW SIM 122222");
+ stream4<< nValue3;
+ ensure_equals("U32 << failed",stream4.str(),"122222");
+
+ // I don't think we use U64 name value pairs. JC
+ //skip_fail("incomplete support for U64.");
+ //LLNameValue nValue4("SecodLife U64 RW SIM 22222");
+ //stream5<< nValue4;
+ //ensure("U64 << failed",0 == strcmp((stream5.str()).c_str(),"22222"));
+ }
+
+ template<> template<>
+ void namevalue_object_t::test<15>()
+ {
+ LLNameValue nValue("SecondLife", "This is a test", "ASSET", "R", "S");
+
+ ensure("getAsset failed", (0 == strcmp(nValue.getAsset(),"This is a test")));
+ // this should not have updated as it is read only.
+ nValue.setAsset("New Value should not be updated");
+ ensure("setAsset on ReadOnly failed", (0 == strcmp(nValue.getAsset(),"This is a test")));
+
+ LLNameValue nValue1("SecondLife", "1234", "U32", "R", "S");
+ // this should not have updated as it is read only.
+ nValue1.setU32(4567);
+ ensure("setU32 on ReadOnly failed", *nValue1.getU32() == 1234);
+
+ LLNameValue nValue2("SecondLife", "1234", "S32", "R", "S");
+ // this should not have updated as it is read only.
+ nValue2.setS32(4567);
+ ensure("setS32 on ReadOnly failed", *nValue2.getS32() == 1234);
+
+ LLNameValue nValue3("SecondLife", "1234", "F32", "R", "S");
+ // this should not have updated as it is read only.
+ nValue3.setF32(4567);
+ ensure("setF32 on ReadOnly failed", *nValue3.getF32() == 1234);
+
+ LLNameValue nValue4("SecondLife", "<1,2,3>", "VEC3", "R", "S");
+ // this should not have updated as it is read only.
+ LLVector3 vec(4,5,6);
+ nValue3.setVec3(vec);
+ LLVector3 vec1(1,2,3);
+ ensure("setVec3 on ReadOnly failed", *nValue4.getVec3() == vec1);
+
+ // cant test for U64 as no set64 exists nor any operators support U64 type
+ }
+}
diff --git a/indra/llmessage/tests/llpartdata_test.cpp b/indra/llmessage/tests/llpartdata_test.cpp
new file mode 100644
index 0000000000..5b691781b8
--- /dev/null
+++ b/indra/llmessage/tests/llpartdata_test.cpp
@@ -0,0 +1,222 @@
+/**
+ * @file llpartdata_tut.cpp
+ * @author Adroit
+ * @date March 2007
+ * @brief LLPartData and LLPartSysData test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "lldatapacker.h"
+#include "v3math.h"
+#include "llsdserialize.h"
+#include "message.h"
+
+#include "../llpartdata.h"
+
+#include "../test/lltut.h"
+
+namespace tut
+{
+
+ struct partdata_test
+ {
+ };
+ typedef test_group<partdata_test> partdata_test_t;
+ typedef partdata_test_t::object partdata_test_object_t;
+ tut::partdata_test_t tut_partdata_test("partdata_test");
+
+ template<> template<>
+ void partdata_test_object_t::test<1>()
+ {
+ LLPartData llpdata,llpdata1;
+ U8 pkbuf[128];
+
+ llpdata.setFlags(LLPartData::LL_PART_INTERP_COLOR_MASK | LLPartData::LL_PART_INTERP_SCALE_MASK |
+ LLPartData::LL_PART_BOUNCE_MASK | LLPartData::LL_PART_WIND_MASK | LLPartData::LL_PART_FOLLOW_SRC_MASK |
+ LLPartData::LL_PART_FOLLOW_VELOCITY_MASK | LLPartData::LL_PART_TARGET_POS_MASK | LLPartData::LL_PART_TARGET_LINEAR_MASK |
+ LLPartData::LL_PART_EMISSIVE_MASK | LLPartData::LL_PART_BEAM_MASK | LLPartData::LL_PART_DEAD_MASK);
+
+ llpdata.setMaxAge(29.3f);
+
+ LLVector3 llvec1(1.0f, .5f, .25f);
+ llpdata.setStartColor(llvec1);
+ llpdata.setStartAlpha(.7f);
+
+ LLVector3 llvec2(.2f, .3f, 1.0f);
+ llpdata.setEndColor(llvec2);
+ llpdata.setEndAlpha(1.0f);
+
+ llpdata.setStartScale(3.23f, 4.0f);
+ llpdata.setEndScale(2.4678f, 1.0f);
+
+ LLDataPackerBinaryBuffer dp((U8*)pkbuf, 128);
+ llpdata.pack(dp);
+
+ S32 cur_size = dp.getCurrentSize();
+
+ LLDataPackerBinaryBuffer dp1((U8*)pkbuf, cur_size);
+ llpdata1.unpack(dp1);
+
+ ensure("1.mFlags values are different after unpacking", llpdata1.mFlags == llpdata.mFlags);
+ ensure_approximately_equals("2.mMaxAge values are different after unpacking", llpdata1.mMaxAge, llpdata.mMaxAge, 8);
+
+ ensure_approximately_equals("3.mStartColor[0] values are different after unpacking", llpdata1.mStartColor.mV[0], llpdata.mStartColor.mV[0], 8);
+ ensure_approximately_equals("4.mStartColor[1] values are different after unpacking", llpdata1.mStartColor.mV[1], llpdata.mStartColor.mV[1], 8);
+ ensure_approximately_equals("5.mStartColor[2] values are different after unpacking", llpdata1.mStartColor.mV[2], llpdata.mStartColor.mV[2], 8);
+ ensure_approximately_equals("6.mStartColor[3] values are different after unpacking", llpdata1.mStartColor.mV[3], llpdata.mStartColor.mV[3], 8);
+
+ ensure_approximately_equals("7.mEndColor[0] values are different after unpacking", llpdata1.mEndColor.mV[0], llpdata.mEndColor.mV[0], 8);
+ ensure_approximately_equals("8.mEndColor[1] values are different after unpacking", llpdata1.mEndColor.mV[1], llpdata.mEndColor.mV[1], 8);
+ ensure_approximately_equals("9.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[2], llpdata.mEndColor.mV[2], 8);
+ ensure_approximately_equals("10.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[3], llpdata.mEndColor.mV[3], 8);
+
+ ensure_approximately_equals("11.mStartScale[0] values are different after unpacking", llpdata1.mStartScale.mV[0], llpdata.mStartScale.mV[0], 5);
+ ensure_approximately_equals("12.mStartScale[1] values are different after unpacking", llpdata1.mStartScale.mV[1], llpdata.mStartScale.mV[1], 5);
+
+ ensure_approximately_equals("13.mEndScale[0] values are different after unpacking", llpdata1.mEndScale.mV[0], llpdata.mEndScale.mV[0], 5);
+ ensure_approximately_equals("14.mEndScale[1] values are different after unpacking", llpdata1.mEndScale.mV[1], llpdata.mEndScale.mV[1], 5);
+ }
+
+
+ template<> template<>
+ void partdata_test_object_t::test<2>()
+ {
+ LLPartData llpdata,llpdata1;
+
+ llpdata.setFlags(LLPartData::LL_PART_INTERP_COLOR_MASK | LLPartData::LL_PART_INTERP_SCALE_MASK |
+ LLPartData::LL_PART_BOUNCE_MASK | LLPartData::LL_PART_WIND_MASK | LLPartData::LL_PART_FOLLOW_SRC_MASK |
+ LLPartData::LL_PART_FOLLOW_VELOCITY_MASK | LLPartData::LL_PART_TARGET_POS_MASK | LLPartData::LL_PART_TARGET_LINEAR_MASK |
+ LLPartData::LL_PART_EMISSIVE_MASK | LLPartData::LL_PART_BEAM_MASK | LLPartData::LL_PART_DEAD_MASK);
+
+ llpdata.setMaxAge(29.3f);
+
+ LLVector3 llvec1(1.0f, .5f, .25f);
+ llpdata.setStartColor(llvec1);
+ llpdata.setStartAlpha(.7f);
+
+ LLVector3 llvec2(.2f, .3f, 1.0f);
+ llpdata.setEndColor(llvec2);
+ llpdata.setEndAlpha(1.0f);
+
+ llpdata.setStartScale(3.23f, 4.0f);
+ llpdata.setEndScale(2.4678f, 1.0f);
+
+ LLSD llsd = llpdata.asLLSD();
+
+ llpdata1.fromLLSD(llsd);
+
+ ensure("1.mFlags values are different after unpacking", llpdata1.mFlags == llpdata.mFlags);
+ ensure_approximately_equals("2.mMaxAge values are different after unpacking", llpdata1.mMaxAge, llpdata.mMaxAge, 8);
+
+ ensure_approximately_equals("3.mStartColor[0] values are different after unpacking", llpdata1.mStartColor.mV[0], llpdata.mStartColor.mV[0], 8);
+ ensure_approximately_equals("4.mStartColor[1] values are different after unpacking", llpdata1.mStartColor.mV[1], llpdata.mStartColor.mV[1], 8);
+ ensure_approximately_equals("5.mStartColor[2] values are different after unpacking", llpdata1.mStartColor.mV[2], llpdata.mStartColor.mV[2], 8);
+ ensure_approximately_equals("6.mStartColor[3] values are different after unpacking", llpdata1.mStartColor.mV[3], llpdata.mStartColor.mV[3], 8);
+
+ ensure_approximately_equals("7.mEndColor[0] values are different after unpacking", llpdata1.mEndColor.mV[0], llpdata.mEndColor.mV[0], 8);
+ ensure_approximately_equals("8.mEndColor[1] values are different after unpacking", llpdata1.mEndColor.mV[1], llpdata.mEndColor.mV[1], 8);
+ ensure_approximately_equals("9.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[2], llpdata.mEndColor.mV[2], 8);
+ ensure_approximately_equals("10.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[3], llpdata.mEndColor.mV[3], 8);
+
+ ensure_approximately_equals("11.mStartScale[0] values are different after unpacking", llpdata1.mStartScale.mV[0], llpdata.mStartScale.mV[0], 5);
+ ensure_approximately_equals("12.mStartScale[1] values are different after unpacking", llpdata1.mStartScale.mV[1], llpdata.mStartScale.mV[1], 5);
+
+ ensure_approximately_equals("13.mEndScale[0] values are different after unpacking", llpdata1.mEndScale.mV[0], llpdata.mEndScale.mV[0], 5);
+ ensure_approximately_equals("14.mEndScale[1] values are different after unpacking", llpdata1.mEndScale.mV[1], llpdata.mEndScale.mV[1], 5);
+ }
+
+
+//*********llpartsysdata***********
+
+ template<> template<>
+ void partdata_test_object_t::test<3>()
+ {
+ LLPartSysData llpsysdata, llpsysdata1;
+ U8 pkbuf[256];
+ llpsysdata.setBurstSpeedMin(33.33f);
+ ensure("1.mBurstSpeedMin coudnt be set", 33.33f == llpsysdata.mBurstSpeedMin);
+
+ llpsysdata.setBurstSpeedMax(44.44f);
+ ensure("2.mBurstSpeedMax coudnt be set", 44.44f == llpsysdata.mBurstSpeedMax);
+
+ llpsysdata.setBurstRadius(45.55f);
+ ensure("3.mBurstRadius coudnt be set", 45.55f == llpsysdata.mBurstRadius);
+
+ LLVector3 llvec(44.44f, 111.11f, -40.4f);
+ llpsysdata.setPartAccel(llvec);
+
+ llpsysdata.mCRC = 0xFFFFFFFF;
+ llpsysdata.mFlags = 0x20;
+
+ llpsysdata.mPattern = LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE_EMPTY;
+
+ llpsysdata.mMaxAge = 99.99f;
+ llpsysdata.mStartAge = 18.5f;
+ llpsysdata.mInnerAngle = 4.234f;
+ llpsysdata.mOuterAngle = 7.123f;
+ llpsysdata.mBurstRate = 245.53f;
+ llpsysdata.mBurstPartCount = 0xFF;
+ llpsysdata.mAngularVelocity = llvec;
+
+ llpsysdata.mPartImageID.generate();
+ llpsysdata.mTargetUUID.generate();
+
+ LLDataPackerBinaryBuffer dp((U8*)pkbuf, 256);
+ llpsysdata.pack(dp);
+ S32 cur_size = dp.getCurrentSize();
+ LLDataPackerBinaryBuffer dp1((U8*)pkbuf, cur_size);
+ llpsysdata1.unpack(dp1);
+
+ ensure("1.mCRC's not equal", llpsysdata.mCRC == llpsysdata1.mCRC);
+ ensure("2.mFlags's not equal", llpsysdata.mFlags == llpsysdata1.mFlags);
+ ensure("3.mPattern's not equal", llpsysdata.mPattern == llpsysdata1.mPattern);
+ ensure_approximately_equals("4.mMaxAge's not equal", llpsysdata.mMaxAge , llpsysdata1.mMaxAge, 8);
+ ensure_approximately_equals("5.mStartAge's not equal", llpsysdata.mStartAge, llpsysdata1.mStartAge, 8);
+ ensure_approximately_equals("6.mOuterAngle's not equal", llpsysdata.mOuterAngle, llpsysdata1.mOuterAngle, 5);
+ ensure_approximately_equals("7.mInnerAngles's not equal", llpsysdata.mInnerAngle, llpsysdata1.mInnerAngle, 5);
+ ensure_approximately_equals("8.mBurstRate's not equal", llpsysdata.mBurstRate, llpsysdata1.mBurstRate, 8);
+ ensure("9.mBurstPartCount's not equal", llpsysdata.mBurstPartCount == llpsysdata1.mBurstPartCount);
+
+ ensure_approximately_equals("10.mBurstSpeedMin's not equal", llpsysdata.mBurstSpeedMin, llpsysdata1.mBurstSpeedMin, 8);
+ ensure_approximately_equals("11.mBurstSpeedMax's not equal", llpsysdata.mBurstSpeedMax, llpsysdata1.mBurstSpeedMax, 8);
+
+ ensure_approximately_equals("12.mAngularVelocity's not equal", llpsysdata.mAngularVelocity.mV[0], llpsysdata1.mAngularVelocity.mV[0], 7);
+ ensure_approximately_equals("13.mAngularVelocity's not equal", llpsysdata.mAngularVelocity.mV[1], llpsysdata1.mAngularVelocity.mV[1], 7);
+ ensure_approximately_equals("14.mAngularVelocity's not equal", llpsysdata.mAngularVelocity.mV[2], llpsysdata1.mAngularVelocity.mV[2], 7);
+
+ ensure_approximately_equals("15.mPartAccel's not equal", llpsysdata.mPartAccel.mV[0], llpsysdata1.mPartAccel.mV[0], 7);
+ ensure_approximately_equals("16.mPartAccel's not equal", llpsysdata.mPartAccel.mV[1], llpsysdata1.mPartAccel.mV[1], 7);
+ ensure_approximately_equals("17.mPartAccel's not equal", llpsysdata.mPartAccel.mV[2], llpsysdata1.mPartAccel.mV[2], 7);
+
+ ensure("18.mPartImageID's not equal", llpsysdata.mPartImageID == llpsysdata1.mPartImageID);
+ ensure("19.mTargetUUID's not equal", llpsysdata.mTargetUUID == llpsysdata1.mTargetUUID);
+ ensure_approximately_equals("20.mBurstRadius's not equal", llpsysdata.mBurstRadius, llpsysdata1.mBurstRadius, 8);
+ }
+}
diff --git a/indra/llmessage/tests/llregionpresenceverifier_test.cpp b/indra/llmessage/tests/llregionpresenceverifier_test.cpp
new file mode 100644
index 0000000000..c86126406e
--- /dev/null
+++ b/indra/llmessage/tests/llregionpresenceverifier_test.cpp
@@ -0,0 +1,113 @@
+/**
+ * @file
+ * @brief
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2001-2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../test/lltut.h"
+#include "llregionpresenceverifier.h"
+#include "llcurl_stub.cpp"
+#include "llhost.cpp"
+#include "net.cpp"
+#include "lltesthttpclientadapter.cpp"
+
+class LLTestResponse : public LLRegionPresenceVerifier::Response
+{
+public:
+
+ virtual bool checkValidity(const LLSD& content) const
+ {
+ return true;
+ }
+
+ virtual void onRegionVerified(const LLSD& region_details)
+ {
+ }
+
+ virtual void onRegionVerificationFailed()
+ {
+ }
+
+ virtual LLHTTPClientInterface& getHttpClient()
+ {
+ return mHttpInterface;
+ }
+
+ LLTestHTTPClientAdapter mHttpInterface;
+};
+
+namespace tut
+{
+ struct LLRegionPresenceVerifierData
+ {
+ LLRegionPresenceVerifierData() :
+ mResponse(new LLTestResponse()),
+ mResponder("", LLRegionPresenceVerifier::ResponsePtr(mResponse),
+ LLSD(), 3)
+ {
+ }
+
+ LLTestResponse* mResponse;
+ LLRegionPresenceVerifier::VerifiedDestinationResponder mResponder;
+ };
+
+ typedef test_group<LLRegionPresenceVerifierData> factory;
+ typedef factory::object object;
+}
+
+namespace
+{
+ tut::factory tf("LLRegionPresenceVerifier test");
+}
+
+namespace tut
+{
+ // Test that VerifiedDestinationResponder does retry
+ // on error when shouldRetry returns true.
+ template<> template<>
+ void object::test<1>()
+ {
+ mResponder.error(500, "Internal server error");
+ ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 1);
+ }
+
+ // Test that VerifiedDestinationResponder only retries
+ // on error until shouldRetry returns false.
+ template<> template<>
+ void object::test<2>()
+ {
+ mResponder.error(500, "Internal server error");
+ mResponder.error(500, "Internal server error");
+ mResponder.error(500, "Internal server error");
+ mResponder.error(500, "Internal server error");
+ ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 3);
+ }
+}
+
diff --git a/indra/llmessage/tests/llsdmessage_test.cpp b/indra/llmessage/tests/llsdmessage_test.cpp
new file mode 100644
index 0000000000..de2c7e00c8
--- /dev/null
+++ b/indra/llmessage/tests/llsdmessage_test.cpp
@@ -0,0 +1,140 @@
+/**
+ * @file llsdmessage_test.cpp
+ * @author Nat Goodspeed
+ * @date 2008-12-22
+ * @brief Test of llsdmessage.h
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * Copyright (c) 2008, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if LL_WINDOWS
+#pragma warning (disable : 4675) // "resolved by ADL" -- just as I want!
+#endif
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llsdmessage.h"
+// STL headers
+#include <iostream>
+// std headers
+#include <stdexcept>
+#include <typeinfo>
+// external library headers
+// other Linden headers
+#include "../test/lltut.h"
+#include "llsdserialize.h"
+#include "llevents.h"
+#include "stringize.h"
+#include "llhost.h"
+#include "tests/networkio.h"
+#include "tests/commtest.h"
+
+/*****************************************************************************
+* TUT
+*****************************************************************************/
+namespace tut
+{
+ struct llsdmessage_data: public commtest_data
+ {
+ LLEventPump& httpPump;
+
+ llsdmessage_data():
+ httpPump(pumps.obtain("LLHTTPClient"))
+ {
+ LLSDMessage::link();
+ }
+ };
+ typedef test_group<llsdmessage_data> llsdmessage_group;
+ typedef llsdmessage_group::object llsdmessage_object;
+ llsdmessage_group llsdmgr("llsdmessage");
+
+ template<> template<>
+ void llsdmessage_object::test<1>()
+ {
+ bool threw = false;
+ // This should fail...
+ try
+ {
+ LLSDMessage localListener;
+ }
+ catch (const LLEventPump::DupPumpName&)
+ {
+ threw = true;
+ }
+ catch (const std::runtime_error& ex)
+ {
+ // This clause is because on Linux, on the viewer side, for this
+ // one test program (though not others!), the
+ // LLEventPump::DupPumpName exception isn't caught by the clause
+ // above. Warn the user...
+ std::cerr << "Failed to catch " << typeid(ex).name() << std::endl;
+ // But if the expected exception was thrown, allow the test to
+ // succeed anyway. Not sure how else to handle this odd case.
+ if (std::string(typeid(ex).name()) == typeid(LLEventPump::DupPumpName).name())
+ {
+ threw = true;
+ }
+ else
+ {
+ // We don't even recognize this exception. Let it propagate
+ // out to TUT to fail the test.
+ throw;
+ }
+ }
+ catch (...)
+ {
+ std::cerr << "Utterly failed to catch expected exception!" << std::endl;
+ // This case is full of fail. We HAVE to address it.
+ throw;
+ }
+ ensure("second LLSDMessage should throw", threw);
+ }
+
+ template<> template<>
+ void llsdmessage_object::test<2>()
+ {
+ LLSD request, body;
+ body["data"] = "yes";
+ request["payload"] = body;
+ request["reply"] = replyPump.getName();
+ request["error"] = errorPump.getName();
+ bool threw = false;
+ try
+ {
+ httpPump.post(request);
+ }
+ catch (const LLSDMessage::ArgError&)
+ {
+ threw = true;
+ }
+ ensure("missing URL", threw);
+ }
+
+ template<> template<>
+ void llsdmessage_object::test<3>()
+ {
+ LLSD request, body;
+ body["data"] = "yes";
+ request["url"] = server + "got-message";
+ request["payload"] = body;
+ request["reply"] = replyPump.getName();
+ request["error"] = errorPump.getName();
+ httpPump.post(request);
+ ensure("got response", netio.pump());
+ ensure("success response", success);
+ ensure_equals(result.asString(), "success");
+
+ body["status"] = 499;
+ body["reason"] = "custom error message";
+ request["url"] = server + "fail";
+ request["payload"] = body;
+ httpPump.post(request);
+ ensure("got response", netio.pump());
+ ensure("failure response", ! success);
+ ensure_equals(result["status"].asInteger(), body["status"].asInteger());
+ ensure_equals(result["reason"].asString(), body["reason"].asString());
+ }
+} // namespace tut
diff --git a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp
index a6f5659352..d57f17f270 100644
--- a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp
+++ b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp
@@ -3,26 +3,27 @@
* @brief LLTrustedMessageService unit tests
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
- *
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
- *
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
- *
+ *
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
diff --git a/indra/llmessage/tests/lltesthttpclientadapter.cpp b/indra/llmessage/tests/lltesthttpclientadapter.cpp
index 1140458918..0cea4b57c2 100644
--- a/indra/llmessage/tests/lltesthttpclientadapter.cpp
+++ b/indra/llmessage/tests/lltesthttpclientadapter.cpp
@@ -2,9 +2,9 @@
* @file
* @brief
*
- * $LicenseInfo:firstyear=2008&license=internal$
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2008, Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
* The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
* this source code is governed by the Linden Lab Source Code Disclosure
diff --git a/indra/llmessage/tests/lltesthttpclientadapter.h b/indra/llmessage/tests/lltesthttpclientadapter.h
index d032503685..6f252e8510 100644
--- a/indra/llmessage/tests/lltesthttpclientadapter.h
+++ b/indra/llmessage/tests/lltesthttpclientadapter.h
@@ -2,9 +2,9 @@
* @file
* @brief
*
- * $LicenseInfo:firstyear=2008&license=internal$
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2008, Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
* The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
* this source code is governed by the Linden Lab Source Code Disclosure
diff --git a/indra/llmessage/tests/lltestmessagesender.cpp b/indra/llmessage/tests/lltestmessagesender.cpp
index a37aa4c566..3d1876ec36 100644
--- a/indra/llmessage/tests/lltestmessagesender.cpp
+++ b/indra/llmessage/tests/lltestmessagesender.cpp
@@ -2,9 +2,9 @@
* @file
* @brief
*
- * $LicenseInfo:firstyear=2008&license=internal$
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2008, Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
* The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
* this source code is governed by the Linden Lab Source Code Disclosure
diff --git a/indra/llmessage/tests/lltestmessagesender.h b/indra/llmessage/tests/lltestmessagesender.h
index 83c0eff4d3..d3aaee8f69 100644
--- a/indra/llmessage/tests/lltestmessagesender.h
+++ b/indra/llmessage/tests/lltestmessagesender.h
@@ -2,9 +2,9 @@
* @file
* @brief
*
- * $LicenseInfo:firstyear=2008&license=internal$
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2008, Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
* The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
* this source code is governed by the Linden Lab Source Code Disclosure
diff --git a/indra/llmessage/tests/lltrustedmessageservice_test.cpp b/indra/llmessage/tests/lltrustedmessageservice_test.cpp
index 44595391df..0a3da4b467 100644
--- a/indra/llmessage/tests/lltrustedmessageservice_test.cpp
+++ b/indra/llmessage/tests/lltrustedmessageservice_test.cpp
@@ -3,26 +3,27 @@
* @brief LLTrustedMessageService unit tests
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
- *
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
- *
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
- *
+ *
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
diff --git a/indra/llmessage/tests/llxfer_file_test.cpp b/indra/llmessage/tests/llxfer_file_test.cpp
new file mode 100644
index 0000000000..59bf1a01bb
--- /dev/null
+++ b/indra/llmessage/tests/llxfer_file_test.cpp
@@ -0,0 +1,64 @@
+/**
+ * @file llxfer_test.cpp
+ * @author Moss
+ * @date 2007-04-17
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../llxfer_file.h"
+
+#include "../test/lltut.h"
+
+namespace tut
+{
+ struct llxfer_data
+ {
+ };
+ typedef test_group<llxfer_data> llxfer_test;
+ typedef llxfer_test::object llxfer_object;
+ tut::llxfer_test llxfer("llxfer");
+
+ template<> template<>
+ void llxfer_object::test<1>()
+ {
+ // test that we handle an oversized filename correctly.
+ std::string oversized_filename;
+ U32 i;
+ for (i=0; i<LL_MAX_PATH*2; ++i) // create oversized filename
+ {
+ oversized_filename += 'X';
+ }
+
+ LLXfer_File xff(oversized_filename, FALSE, 1);
+ ensure("oversized local_filename nul-terminated",
+ xff.getFileName().length() < LL_MAX_PATH);
+ }
+}
diff --git a/indra/llmessage/tests/networkio.h b/indra/llmessage/tests/networkio.h
index 11c5cc07fc..0ebe369ea2 100644
--- a/indra/llmessage/tests/networkio.h
+++ b/indra/llmessage/tests/networkio.h
@@ -5,7 +5,30 @@
* @brief
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
* Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
diff --git a/indra/llmessage/tests/test_llsdmessage_peer.py b/indra/llmessage/tests/test_llsdmessage_peer.py
index e62f20912b..86d5761b1b 100644
--- a/indra/llmessage/tests/test_llsdmessage_peer.py
+++ b/indra/llmessage/tests/test_llsdmessage_peer.py
@@ -16,16 +16,12 @@ import os
import sys
from threading import Thread
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
+
mydir = os.path.dirname(__file__) # expected to be .../indra/llmessage/tests/
sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python"))
from indra.util.fastest_elementtree import parse as xml_parse
from indra.base import llsd
-
-def debug(*args):
- sys.stdout.writelines(args)
- sys.stdout.flush()
-# comment out the line below to enable debug output
-debug = lambda *args: None
+from testrunner import run, debug
class TestHTTPRequestHandler(BaseHTTPRequestHandler):
"""This subclass of BaseHTTPRequestHandler is to receive and echo
@@ -106,25 +102,5 @@ class TestHTTPServer(Thread):
debug("Starting HTTP server...\n")
httpd.serve_forever()
-def main(*args):
- # Start HTTP server thread. Note that this and all other comm server
- # threads should be daemon threads: we'll let them run "forever,"
- # confident that the whole process will terminate when the main thread
- # terminates, which will be when the test executable child process
- # terminates.
- httpThread = TestHTTPServer(name="httpd")
- httpThread.setDaemon(True)
- httpThread.start()
- # choice of os.spawnv():
- # - [v vs. l] pass a list of args vs. individual arguments,
- # - [no p] don't use the PATH because we specifically want to invoke the
- # executable passed as our first arg,
- # - [no e] child should inherit this process's environment.
- debug("Running %s...\n" % (" ".join(args)))
- sys.stdout.flush()
- rc = os.spawnv(os.P_WAIT, args[0], args)
- debug("%s returned %s\n" % (args[0], rc))
- return rc
-
if __name__ == "__main__":
- sys.exit(main(*sys.argv[1:]))
+ sys.exit(run(server=TestHTTPServer(name="httpd"), *sys.argv[1:]))
diff --git a/indra/llmessage/tests/testrunner.py b/indra/llmessage/tests/testrunner.py
new file mode 100644
index 0000000000..3b9c3a7a19
--- /dev/null
+++ b/indra/llmessage/tests/testrunner.py
@@ -0,0 +1,53 @@
+#!/usr/bin/python
+"""\
+@file testrunner.py
+@author Nat Goodspeed
+@date 2009-03-20
+@brief Utilities for writing wrapper scripts for ADD_COMM_BUILD_TEST unit tests
+
+$LicenseInfo:firstyear=2009&license=viewergpl$
+Copyright (c) 2009, Linden Research, Inc.
+$/LicenseInfo$
+"""
+
+import os
+import sys
+
+def debug(*args):
+ sys.stdout.writelines(args)
+ sys.stdout.flush()
+# comment out the line below to enable debug output
+debug = lambda *args: None
+
+def run(*args, **kwds):
+ """All positional arguments collectively form a command line, executed as
+ a synchronous child process.
+ In addition, pass server=new_thread_instance as an explicit keyword (to
+ differentiate it from an additional command-line argument).
+ new_thread_instance should be an instantiated but not yet started Thread
+ subclass instance, e.g.:
+ run("python", "-c", 'print "Hello, world!"', server=TestHTTPServer(name="httpd"))
+ """
+ # If there's no server= keyword arg, don't start a server thread: simply
+ # run a child process.
+ try:
+ thread = kwds.pop("server")
+ except KeyError:
+ pass
+ else:
+ # Start server thread. Note that this and all other comm server
+ # threads should be daemon threads: we'll let them run "forever,"
+ # confident that the whole process will terminate when the main thread
+ # terminates, which will be when the child process terminates.
+ thread.setDaemon(True)
+ thread.start()
+ # choice of os.spawnv():
+ # - [v vs. l] pass a list of args vs. individual arguments,
+ # - [no p] don't use the PATH because we specifically want to invoke the
+ # executable passed as our first arg,
+ # - [no e] child should inherit this process's environment.
+ debug("Running %s...\n" % (" ".join(args)))
+ sys.stdout.flush()
+ rc = os.spawnv(os.P_WAIT, args[0], args)
+ debug("%s returned %s\n" % (args[0], rc))
+ return rc
diff --git a/indra/llplugin/CMakeLists.txt b/indra/llplugin/CMakeLists.txt
new file mode 100644
index 0000000000..51cb0d78b4
--- /dev/null
+++ b/indra/llplugin/CMakeLists.txt
@@ -0,0 +1,63 @@
+# -*- cmake -*-
+
+project(llplugin)
+
+include(00-Common)
+include(LLCommon)
+include(LLImage)
+include(LLMath)
+include(LLMessage)
+include(LLRender)
+include(LLXML)
+include(LLWindow)
+
+include_directories(
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LLIMAGE_INCLUDE_DIRS}
+ ${LLMATH_INCLUDE_DIRS}
+ ${LLMESSAGE_INCLUDE_DIRS}
+ ${LLRENDER_INCLUDE_DIRS}
+ ${LLXML_INCLUDE_DIRS}
+ ${LLWINDOW_INCLUDE_DIRS}
+ )
+
+set(llplugin_SOURCE_FILES
+ llpluginclassmedia.cpp
+ llplugininstance.cpp
+ llpluginmessage.cpp
+ llpluginmessagepipe.cpp
+ llpluginprocesschild.cpp
+ llpluginprocessparent.cpp
+ llpluginsharedmemory.cpp
+ )
+
+set(llplugin_HEADER_FILES
+ CMakeLists.txt
+
+ llpluginclassmedia.h
+ llpluginclassmediaowner.h
+ llplugininstance.h
+ llpluginmessage.h
+ llpluginmessageclasses.h
+ llpluginmessagepipe.h
+ llpluginprocesschild.h
+ llpluginprocessparent.h
+ llpluginsharedmemory.h
+ )
+
+set_source_files_properties(${llplugin_HEADER_FILES}
+ PROPERTIES HEADER_FILE_ONLY TRUE)
+
+if(NOT WORD_SIZE EQUAL 32)
+ if(WINDOWS)
+ add_definitions(/FIXED:NO)
+ else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
+ add_definitions(-fPIC)
+ endif(WINDOWS)
+endif(NOT WORD_SIZE EQUAL 32)
+
+list(APPEND llplugin_SOURCE_FILES ${llplugin_HEADER_FILES})
+
+add_library (llplugin ${llplugin_SOURCE_FILES})
+
+add_subdirectory(slplugin)
diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
new file mode 100644
index 0000000000..3d2eaed5c5
--- /dev/null
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -0,0 +1,1196 @@
+/**
+ * @file llpluginclassmedia.cpp
+ * @brief LLPluginClassMedia handles a plugin which knows about the "media" message class.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "linden_common.h"
+#include "indra_constants.h"
+
+#include "llpluginclassmedia.h"
+#include "llpluginmessageclasses.h"
+
+#include "llqtwebkit.h"
+
+static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256;
+
+static int nextPowerOf2( int value )
+{
+ int next_power_of_2 = 1;
+ while ( next_power_of_2 < value )
+ {
+ next_power_of_2 <<= 1;
+ }
+
+ return next_power_of_2;
+}
+
+LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner)
+{
+ mOwner = owner;
+ mPlugin = NULL;
+ reset();
+}
+
+
+LLPluginClassMedia::~LLPluginClassMedia()
+{
+ reset();
+}
+
+bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug, const std::string &user_data_path)
+{
+ LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL;
+ LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL;
+ LL_DEBUGS("Plugin") << "user_data_path: " << user_data_path << LL_ENDL;
+
+ mPlugin = new LLPluginProcessParent(this);
+ mPlugin->setSleepTime(mSleepTime);
+ mPlugin->init(launcher_filename, plugin_filename, debug, user_data_path);
+
+ return true;
+}
+
+
+void LLPluginClassMedia::reset()
+{
+ if(mPlugin != NULL)
+ {
+ delete mPlugin;
+ mPlugin = NULL;
+ }
+
+ mTextureParamsReceived = false;
+ mRequestedTextureDepth = 0;
+ mRequestedTextureInternalFormat = 0;
+ mRequestedTextureFormat = 0;
+ mRequestedTextureType = 0;
+ mRequestedTextureSwapBytes = false;
+ mRequestedTextureCoordsOpenGL = false;
+ mTextureSharedMemorySize = 0;
+ mTextureSharedMemoryName.clear();
+ mDefaultMediaWidth = 0;
+ mDefaultMediaHeight = 0;
+ mNaturalMediaWidth = 0;
+ mNaturalMediaHeight = 0;
+ mSetMediaWidth = -1;
+ mSetMediaHeight = -1;
+ mRequestedMediaWidth = 0;
+ mRequestedMediaHeight = 0;
+ mFullMediaWidth = 0;
+ mFullMediaHeight = 0;
+ mTextureWidth = 0;
+ mTextureHeight = 0;
+ mMediaWidth = 0;
+ mMediaHeight = 0;
+ mDirtyRect = LLRect::null;
+ mAutoScaleMedia = false;
+ mRequestedVolume = 1.0f;
+ mPriority = PRIORITY_NORMAL;
+ mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT;
+ mAllowDownsample = false;
+ mPadding = 0;
+ mLastMouseX = 0;
+ mLastMouseY = 0;
+ mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
+ mSleepTime = 1.0f / 100.0f;
+ mCanCut = false;
+ mCanCopy = false;
+ mCanPaste = false;
+ mMediaName.clear();
+ mMediaDescription.clear();
+ mBackgroundColor = LLColor4(1.0f, 1.0f, 1.0f, 1.0f);
+
+ // media_browser class
+ mNavigateURI.clear();
+ mNavigateResultCode = -1;
+ mNavigateResultString.clear();
+ mHistoryBackAvailable = false;
+ mHistoryForwardAvailable = false;
+ mStatusText.clear();
+ mProgressPercent = 0;
+ mClickURL.clear();
+ mClickTarget.clear();
+ mClickTargetType = TARGET_NONE;
+
+ // media_time class
+ mCurrentTime = 0.0f;
+ mDuration = 0.0f;
+ mCurrentRate = 0.0f;
+ mLoadedDuration = 0.0f;
+}
+
+void LLPluginClassMedia::idle(void)
+{
+ if(mPlugin)
+ {
+ mPlugin->idle();
+ }
+
+ if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL))
+ {
+ // Can't process a size change at this time
+ }
+ else if((mRequestedMediaWidth != mMediaWidth) || (mRequestedMediaHeight != mMediaHeight))
+ {
+ // Calculate the correct size for the media texture
+ mRequestedTextureHeight = mRequestedMediaHeight;
+ if(mPadding < 0)
+ {
+ // negative values indicate the plugin wants a power of 2
+ mRequestedTextureWidth = nextPowerOf2(mRequestedMediaWidth);
+ }
+ else
+ {
+ mRequestedTextureWidth = mRequestedMediaWidth;
+
+ if(mPadding > 1)
+ {
+ // Pad up to a multiple of the specified number of bytes per row
+ int rowbytes = mRequestedTextureWidth * mRequestedTextureDepth;
+ int pad = rowbytes % mPadding;
+ if(pad != 0)
+ {
+ rowbytes += mPadding - pad;
+ }
+
+ if(rowbytes % mRequestedTextureDepth == 0)
+ {
+ mRequestedTextureWidth = rowbytes / mRequestedTextureDepth;
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unable to pad texture width, padding size " << mPadding << "is not a multiple of pixel size " << mRequestedTextureDepth << LL_ENDL;
+ }
+ }
+ }
+
+
+ // Size change has been requested but not initiated yet.
+ size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight * mRequestedTextureDepth;
+
+ // Add an extra line for padding, just in case.
+ newsize += mRequestedTextureWidth * mRequestedTextureDepth;
+
+ if(newsize != mTextureSharedMemorySize)
+ {
+ if(!mTextureSharedMemoryName.empty())
+ {
+ // Tell the plugin to remove the old memory segment
+ mPlugin->removeSharedMemory(mTextureSharedMemoryName);
+ mTextureSharedMemoryName.clear();
+ }
+
+ mTextureSharedMemorySize = newsize;
+ mTextureSharedMemoryName = mPlugin->addSharedMemory(mTextureSharedMemorySize);
+ if(!mTextureSharedMemoryName.empty())
+ {
+ void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
+
+ // clear texture memory to avoid random screen visual fuzz from uninitialized texture data
+ memset( addr, 0x00, newsize );
+
+ // We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin,
+ // so it may not be worthwhile.
+ // mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth, mRequestedMediaHeight);
+ }
+ }
+
+ // This is our local indicator that a change is in progress.
+ mTextureWidth = -1;
+ mTextureHeight = -1;
+ mMediaWidth = -1;
+ mMediaHeight = -1;
+
+ // This invalidates any existing dirty rect.
+ resetDirty();
+
+ // Send a size change message to the plugin
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change");
+ message.setValue("name", mTextureSharedMemoryName);
+ message.setValueS32("width", mRequestedMediaWidth);
+ message.setValueS32("height", mRequestedMediaHeight);
+ message.setValueS32("texture_width", mRequestedTextureWidth);
+ message.setValueS32("texture_height", mRequestedTextureHeight);
+ message.setValueReal("background_r", mBackgroundColor.mV[VX]);
+ message.setValueReal("background_g", mBackgroundColor.mV[VY]);
+ message.setValueReal("background_b", mBackgroundColor.mV[VZ]);
+ message.setValueReal("background_a", mBackgroundColor.mV[VW]);
+ mPlugin->sendMessage(message); // DO NOT just use sendMessage() here -- we want this to jump ahead of the queue.
+
+ LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL;
+ }
+ }
+
+ if(mPlugin && mPlugin->isRunning())
+ {
+ // Send queued messages
+ while(!mSendQueue.empty())
+ {
+ LLPluginMessage message = mSendQueue.front();
+ mSendQueue.pop();
+ mPlugin->sendMessage(message);
+ }
+ }
+}
+
+int LLPluginClassMedia::getTextureWidth() const
+{
+ return nextPowerOf2(mTextureWidth);
+}
+
+int LLPluginClassMedia::getTextureHeight() const
+{
+ return nextPowerOf2(mTextureHeight);
+}
+
+unsigned char* LLPluginClassMedia::getBitsData()
+{
+ unsigned char *result = NULL;
+ if((mPlugin != NULL) && !mTextureSharedMemoryName.empty())
+ {
+ result = (unsigned char*)mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
+ }
+ return result;
+}
+
+void LLPluginClassMedia::setSize(int width, int height)
+{
+ if((width > 0) && (height > 0))
+ {
+ mSetMediaWidth = width;
+ mSetMediaHeight = height;
+ }
+ else
+ {
+ mSetMediaWidth = -1;
+ mSetMediaHeight = -1;
+ }
+
+ setSizeInternal();
+}
+
+void LLPluginClassMedia::setSizeInternal(void)
+{
+ if((mSetMediaWidth > 0) && (mSetMediaHeight > 0))
+ {
+ mRequestedMediaWidth = mSetMediaWidth;
+ mRequestedMediaHeight = mSetMediaHeight;
+ }
+ else if((mNaturalMediaWidth > 0) && (mNaturalMediaHeight > 0))
+ {
+ mRequestedMediaWidth = mNaturalMediaWidth;
+ mRequestedMediaHeight = mNaturalMediaHeight;
+ }
+ else
+ {
+ mRequestedMediaWidth = mDefaultMediaWidth;
+ mRequestedMediaHeight = mDefaultMediaHeight;
+ }
+
+ // Save these for size/interest calculations
+ mFullMediaWidth = mRequestedMediaWidth;
+ mFullMediaHeight = mRequestedMediaHeight;
+
+ if(mAllowDownsample)
+ {
+ switch(mPriority)
+ {
+ case PRIORITY_SLIDESHOW:
+ case PRIORITY_LOW:
+ // Reduce maximum texture dimension to (or below) mLowPrioritySizeLimit
+ while((mRequestedMediaWidth > mLowPrioritySizeLimit) || (mRequestedMediaHeight > mLowPrioritySizeLimit))
+ {
+ mRequestedMediaWidth /= 2;
+ mRequestedMediaHeight /= 2;
+ }
+ break;
+
+ default:
+ // Don't adjust texture size
+ break;
+ }
+ }
+
+ if(mAutoScaleMedia)
+ {
+ mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth);
+ mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight);
+ }
+
+ if(mRequestedMediaWidth > 2048)
+ mRequestedMediaWidth = 2048;
+
+ if(mRequestedMediaHeight > 2048)
+ mRequestedMediaHeight = 2048;
+}
+
+void LLPluginClassMedia::setAutoScale(bool auto_scale)
+{
+ if(auto_scale != mAutoScaleMedia)
+ {
+ mAutoScaleMedia = auto_scale;
+ setSizeInternal();
+ }
+}
+
+bool LLPluginClassMedia::textureValid(void)
+{
+ if(
+ !mTextureParamsReceived ||
+ mTextureWidth <= 0 ||
+ mTextureHeight <= 0 ||
+ mMediaWidth <= 0 ||
+ mMediaHeight <= 0 ||
+ mRequestedMediaWidth != mMediaWidth ||
+ mRequestedMediaHeight != mMediaHeight ||
+ getBitsData() == NULL
+ )
+ return false;
+
+ return true;
+}
+
+bool LLPluginClassMedia::getDirty(LLRect *dirty_rect)
+{
+ bool result = !mDirtyRect.isEmpty();
+
+ if(dirty_rect != NULL)
+ {
+ *dirty_rect = mDirtyRect;
+ }
+
+ return result;
+}
+
+void LLPluginClassMedia::resetDirty(void)
+{
+ mDirtyRect = LLRect::null;
+}
+
+std::string LLPluginClassMedia::translateModifiers(MASK modifiers)
+{
+ std::string result;
+
+
+ if(modifiers & MASK_CONTROL)
+ {
+ result += "control|";
+ }
+
+ if(modifiers & MASK_ALT)
+ {
+ result += "alt|";
+ }
+
+ if(modifiers & MASK_SHIFT)
+ {
+ result += "shift|";
+ }
+
+ // TODO: should I deal with platform differences here or in callers?
+ // TODO: how do we deal with the Mac "command" key?
+/*
+ if(modifiers & MASK_SOMETHING)
+ {
+ result += "meta|";
+ }
+*/
+ return result;
+}
+
+void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers)
+{
+ if(type == MOUSE_EVENT_MOVE)
+ {
+ if((x == mLastMouseX) && (y == mLastMouseY))
+ {
+ // Don't spam unnecessary mouse move events.
+ return;
+ }
+
+ mLastMouseX = x;
+ mLastMouseY = y;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event");
+ std::string temp;
+ switch(type)
+ {
+ case MOUSE_EVENT_DOWN: temp = "down"; break;
+ case MOUSE_EVENT_UP: temp = "up"; break;
+ case MOUSE_EVENT_MOVE: temp = "move"; break;
+ case MOUSE_EVENT_DOUBLE_CLICK: temp = "double_click"; break;
+ }
+ message.setValue("event", temp);
+
+ message.setValueS32("button", button);
+
+ message.setValueS32("x", x);
+
+ // Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip them here if the plugin has requested it.
+ if(!mRequestedTextureCoordsOpenGL)
+ {
+ // TODO: Should I use mMediaHeight or mRequestedMediaHeight here?
+ y = mMediaHeight - y;
+ }
+ message.setValueS32("y", y);
+
+ message.setValue("modifiers", translateModifiers(modifiers));
+
+ sendMessage(message);
+}
+
+bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers)
+{
+ bool result = true;
+
+ // FIXME:
+ // HACK: we don't have an easy way to tell if the plugin is going to handle a particular keycode.
+ // For now, return false for the ones the webkit plugin won't handle properly.
+
+ switch(key_code)
+ {
+ case KEY_BACKSPACE:
+ case KEY_TAB:
+ case KEY_RETURN:
+ case KEY_PAD_RETURN:
+ case KEY_SHIFT:
+ case KEY_CONTROL:
+ case KEY_ALT:
+ case KEY_CAPSLOCK:
+ case KEY_ESCAPE:
+ case KEY_PAGE_UP:
+ case KEY_PAGE_DOWN:
+ case KEY_END:
+ case KEY_HOME:
+ case KEY_LEFT:
+ case KEY_UP:
+ case KEY_RIGHT:
+ case KEY_DOWN:
+ case KEY_INSERT:
+ case KEY_DELETE:
+ // These will be handled
+ break;
+
+ default:
+ // regular ASCII characters will also be handled
+ if(key_code >= KEY_SPECIAL)
+ {
+ // Other "special" codes will not work properly.
+ result = false;
+ }
+ break;
+ }
+
+ if(result)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event");
+ std::string temp;
+ switch(type)
+ {
+ case KEY_EVENT_DOWN: temp = "down"; break;
+ case KEY_EVENT_UP: temp = "up"; break;
+ case KEY_EVENT_REPEAT: temp = "repeat"; break;
+ }
+ message.setValue("event", temp);
+
+ message.setValueS32("key", key_code);
+
+ message.setValue("modifiers", translateModifiers(modifiers));
+
+ sendMessage(message);
+ }
+
+ return result;
+}
+
+void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "scroll_event");
+
+ message.setValueS32("x", x);
+ message.setValueS32("y", y);
+ message.setValue("modifiers", translateModifiers(modifiers));
+
+ sendMessage(message);
+}
+
+bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event");
+
+ message.setValue("text", text);
+ message.setValue("modifiers", translateModifiers(modifiers));
+
+ sendMessage(message);
+
+ return true;
+}
+
+void LLPluginClassMedia::loadURI(const std::string &uri)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri");
+
+ message.setValue("uri", uri);
+
+ sendMessage(message);
+}
+
+const char* LLPluginClassMedia::priorityToString(EPriority priority)
+{
+ const char* result = "UNKNOWN";
+ switch(priority)
+ {
+ case PRIORITY_UNLOADED: result = "unloaded"; break;
+ case PRIORITY_STOPPED: result = "stopped"; break;
+ case PRIORITY_HIDDEN: result = "hidden"; break;
+ case PRIORITY_SLIDESHOW: result = "slideshow"; break;
+ case PRIORITY_LOW: result = "low"; break;
+ case PRIORITY_NORMAL: result = "normal"; break;
+ case PRIORITY_HIGH: result = "high"; break;
+ }
+
+ return result;
+}
+
+void LLPluginClassMedia::setPriority(EPriority priority)
+{
+ if(mPriority != priority)
+ {
+ mPriority = priority;
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority");
+
+ std::string priority_string = priorityToString(priority);
+ switch(priority)
+ {
+ case PRIORITY_UNLOADED:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_STOPPED:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_HIDDEN:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_SLIDESHOW:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_LOW:
+ mSleepTime = 1.0f / 25.0f;
+ break;
+ case PRIORITY_NORMAL:
+ mSleepTime = 1.0f / 50.0f;
+ break;
+ case PRIORITY_HIGH:
+ mSleepTime = 1.0f / 100.0f;
+ break;
+ }
+
+ message.setValue("priority", priority_string);
+
+ sendMessage(message);
+
+ if(mPlugin)
+ {
+ mPlugin->setSleepTime(mSleepTime);
+ }
+
+ LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL;
+
+ // This may affect the calculated size, so recalculate it here.
+ setSizeInternal();
+ }
+}
+
+void LLPluginClassMedia::setLowPrioritySizeLimit(int size)
+{
+ int power = nextPowerOf2(size);
+ if(mLowPrioritySizeLimit != power)
+ {
+ mLowPrioritySizeLimit = power;
+
+ // This may affect the calculated size, so recalculate it here.
+ setSizeInternal();
+ }
+}
+
+F64 LLPluginClassMedia::getCPUUsage()
+{
+ F64 result = 0.0f;
+
+ if(mPlugin)
+ {
+ result = mPlugin->getCPUUsage();
+ }
+
+ return result;
+}
+
+void LLPluginClassMedia::cut()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::copy()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_copy");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::paste()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_paste");
+ sendMessage(message);
+}
+
+LLPluginClassMedia::ETargetType getTargetTypeFromLLQtWebkit(int target_type)
+{
+ // convert a LinkTargetType value from llqtwebkit to an ETargetType
+ // so that we don't expose the llqtwebkit header in viewer code
+ switch (target_type)
+ {
+ case LinkTargetType::LTT_TARGET_NONE:
+ return LLPluginClassMedia::TARGET_NONE;
+
+ case LinkTargetType::LTT_TARGET_BLANK:
+ return LLPluginClassMedia::TARGET_BLANK;
+
+ case LinkTargetType::LTT_TARGET_EXTERNAL:
+ return LLPluginClassMedia::TARGET_EXTERNAL;
+
+ default:
+ return LLPluginClassMedia::TARGET_OTHER;
+ }
+}
+
+/* virtual */
+void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
+{
+ std::string message_class = message.getClass();
+
+ if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
+ {
+ std::string message_name = message.getName();
+ if(message_name == "texture_params")
+ {
+ mRequestedTextureDepth = message.getValueS32("depth");
+ mRequestedTextureInternalFormat = message.getValueU32("internalformat");
+ mRequestedTextureFormat = message.getValueU32("format");
+ mRequestedTextureType = message.getValueU32("type");
+ mRequestedTextureSwapBytes = message.getValueBoolean("swap_bytes");
+ mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl");
+
+ // These two are optional, and will default to 0 if they're not specified.
+ mDefaultMediaWidth = message.getValueS32("default_width");
+ mDefaultMediaHeight = message.getValueS32("default_height");
+
+ mAllowDownsample = message.getValueBoolean("allow_downsample");
+ mPadding = message.getValueS32("padding");
+
+ setSizeInternal();
+
+ mTextureParamsReceived = true;
+ }
+ else if(message_name == "updated")
+ {
+ if(message.hasValue("left"))
+ {
+ LLRect newDirtyRect;
+ newDirtyRect.mLeft = message.getValueS32("left");
+ newDirtyRect.mTop = message.getValueS32("top");
+ newDirtyRect.mRight = message.getValueS32("right");
+ newDirtyRect.mBottom = message.getValueS32("bottom");
+
+ // The plugin is likely to have top and bottom switched, due to vertical flip and OpenGL coordinate confusion.
+ // If they're backwards, swap them.
+ if(newDirtyRect.mTop < newDirtyRect.mBottom)
+ {
+ S32 temp = newDirtyRect.mTop;
+ newDirtyRect.mTop = newDirtyRect.mBottom;
+ newDirtyRect.mBottom = temp;
+ }
+
+ if(mDirtyRect.isEmpty())
+ {
+ mDirtyRect = newDirtyRect;
+ }
+ else
+ {
+ mDirtyRect.unionWith(newDirtyRect);
+ }
+
+ LL_DEBUGS("Plugin") << "adjusted incoming rect is: ("
+ << newDirtyRect.mLeft << ", "
+ << newDirtyRect.mTop << ", "
+ << newDirtyRect.mRight << ", "
+ << newDirtyRect.mBottom << "), new dirty rect is: ("
+ << mDirtyRect.mLeft << ", "
+ << mDirtyRect.mTop << ", "
+ << mDirtyRect.mRight << ", "
+ << mDirtyRect.mBottom << ")"
+ << LL_ENDL;
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CONTENT_UPDATED);
+ }
+
+
+ bool time_duration_updated = false;
+ int previous_percent = mProgressPercent;
+
+ if(message.hasValue("current_time"))
+ {
+ mCurrentTime = message.getValueReal("current_time");
+ time_duration_updated = true;
+ }
+ if(message.hasValue("duration"))
+ {
+ mDuration = message.getValueReal("duration");
+ time_duration_updated = true;
+ }
+
+ if(message.hasValue("current_rate"))
+ {
+ mCurrentRate = message.getValueReal("current_rate");
+ }
+
+ if(message.hasValue("loaded_duration"))
+ {
+ mLoadedDuration = message.getValueReal("loaded_duration");
+ time_duration_updated = true;
+ }
+ else
+ {
+ // If the message doesn't contain a loaded_duration param, assume it's equal to duration
+ mLoadedDuration = mDuration;
+ }
+
+ // Calculate a percentage based on the loaded duration and total duration.
+ if(mDuration != 0.0f) // Don't divide by zero.
+ {
+ mProgressPercent = (int)((mLoadedDuration * 100.0f)/mDuration);
+ }
+
+ if(time_duration_updated)
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED);
+ }
+
+ if(previous_percent != mProgressPercent)
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
+ }
+ }
+ else if(message_name == "media_status")
+ {
+ std::string status = message.getValue("status");
+
+ LL_DEBUGS("Plugin") << "Status changed to: " << status << LL_ENDL;
+
+ if(status == "loading")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_LOADING;
+ }
+ else if(status == "loaded")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_LOADED;
+ }
+ else if(status == "error")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_ERROR;
+ }
+ else if(status == "playing")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_PLAYING;
+ }
+ else if(status == "paused")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED;
+ }
+ else if(status == "done")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_DONE;
+ }
+ else
+ {
+ // empty string or any unknown string
+ mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
+ }
+ }
+ else if(message_name == "size_change_request")
+ {
+ S32 width = message.getValueS32("width");
+ S32 height = message.getValueS32("height");
+ std::string name = message.getValue("name");
+
+ // TODO: check that name matches?
+ mNaturalMediaWidth = width;
+ mNaturalMediaHeight = height;
+
+ setSizeInternal();
+ }
+ else if(message_name == "size_change_response")
+ {
+ std::string name = message.getValue("name");
+
+ // TODO: check that name matches?
+
+ mTextureWidth = message.getValueS32("texture_width");
+ mTextureHeight = message.getValueS32("texture_height");
+ mMediaWidth = message.getValueS32("width");
+ mMediaHeight = message.getValueS32("height");
+
+ // This invalidates any existing dirty rect.
+ resetDirty();
+
+ // TODO: should we verify that the plugin sent back the right values?
+ // Two size changes in a row may cause them to not match, due to queueing, etc.
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_SIZE_CHANGED);
+ }
+ else if(message_name == "cursor_changed")
+ {
+ mCursorName = message.getValue("name");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CURSOR_CHANGED);
+ }
+ else if(message_name == "edit_state")
+ {
+ if(message.hasValue("cut"))
+ {
+ mCanCut = message.getValueBoolean("cut");
+ }
+ if(message.hasValue("copy"))
+ {
+ mCanCopy = message.getValueBoolean("copy");
+ }
+ if(message.hasValue("paste"))
+ {
+ mCanPaste = message.getValueBoolean("paste");
+ }
+ }
+ else if(message_name == "name_text")
+ {
+ mMediaName = message.getValue("name");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+ }
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
+ {
+ std::string message_name = message.getName();
+ if(message_name == "navigate_begin")
+ {
+ mNavigateURI = message.getValue("uri");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_BEGIN);
+ }
+ else if(message_name == "navigate_complete")
+ {
+ mNavigateURI = message.getValue("uri");
+ mNavigateResultCode = message.getValueS32("result_code");
+ mNavigateResultString = message.getValue("result_string");
+ mHistoryBackAvailable = message.getValueBoolean("history_back_available");
+ mHistoryForwardAvailable = message.getValueBoolean("history_forward_available");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE);
+ }
+ else if(message_name == "progress")
+ {
+ mProgressPercent = message.getValueS32("percent");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
+ }
+ else if(message_name == "status_text")
+ {
+ mStatusText = message.getValue("status");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_STATUS_TEXT_CHANGED);
+ }
+ else if(message_name == "location_changed")
+ {
+ mLocation = message.getValue("uri");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LOCATION_CHANGED);
+ }
+ else if(message_name == "click_href")
+ {
+ mClickURL = message.getValue("uri");
+ mClickTarget = message.getValue("target");
+ U32 target_type = message.getValueU32("target_type");
+ mClickTargetType = ::getTargetTypeFromLLQtWebkit(target_type);
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF);
+ }
+ else if(message_name == "click_nofollow")
+ {
+ mClickURL = message.getValue("uri");
+ mClickTarget.clear();
+ mClickTargetType = TARGET_NONE;
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+ }
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
+ {
+ std::string message_name = message.getName();
+
+ // This class hasn't defined any incoming messages yet.
+// if(message_name == "message_name")
+// {
+// }
+// else
+ {
+ LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+ }
+ }
+
+}
+
+/* virtual */
+void LLPluginClassMedia::pluginLaunchFailed()
+{
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
+}
+
+/* virtual */
+void LLPluginClassMedia::pluginDied()
+{
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED);
+}
+
+void LLPluginClassMedia::mediaEvent(LLPluginClassMediaOwner::EMediaEvent event)
+{
+ if(mOwner)
+ {
+ mOwner->handleMediaEvent(this, event);
+ }
+}
+
+void LLPluginClassMedia::sendMessage(const LLPluginMessage &message)
+{
+ if(mPlugin && mPlugin->isRunning())
+ {
+ mPlugin->sendMessage(message);
+ }
+ else
+ {
+ // The plugin isn't set up yet -- queue this message to be sent after initialization.
+ mSendQueue.push(message);
+ }
+}
+
+////////////////////////////////////////////////////////////
+// MARK: media_browser class functions
+bool LLPluginClassMedia::pluginSupportsMediaBrowser(void)
+{
+ std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER);
+ return !version.empty();
+}
+
+void LLPluginClassMedia::focus(bool focused)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "focus");
+
+ message.setValueBoolean("focused", focused);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::clear_cache()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cache");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::clear_cookies()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cookies");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::enable_cookies(bool enable)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "enable_cookies");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::proxy_setup(bool enable, const std::string &host, int port)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_setup");
+
+ message.setValueBoolean("enable", enable);
+ message.setValue("host", host);
+ message.setValueS32("port", port);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_stop()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_stop");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_reload(bool ignore_cache)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_reload");
+
+ message.setValueBoolean("ignore_cache", ignore_cache);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_forward()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_forward");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_back()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_back");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::set_status_redirect(int code, const std::string &url)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_status_redirect");
+
+ message.setValueS32("code", code);
+ message.setValue("url", url);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_user_agent");
+
+ message.setValue("user_agent", user_agent);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::crashPlugin()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash");
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::hangPlugin()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hang");
+
+ sendMessage(message);
+}
+
+
+////////////////////////////////////////////////////////////
+// MARK: media_time class functions
+bool LLPluginClassMedia::pluginSupportsMediaTime(void)
+{
+ std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME);
+ return !version.empty();
+}
+
+void LLPluginClassMedia::stop()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "stop");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::start(float rate)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "start");
+
+ message.setValueReal("rate", rate);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::pause()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "pause");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::seek(float time)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "seek");
+
+ message.setValueReal("time", time);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setLoop(bool loop)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_loop");
+
+ message.setValueBoolean("loop", loop);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setVolume(float volume)
+{
+ if(volume != mRequestedVolume)
+ {
+ mRequestedVolume = volume;
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_volume");
+
+ message.setValueReal("volume", volume);
+
+ sendMessage(message);
+ }
+}
+
+float LLPluginClassMedia::getVolume()
+{
+ return mRequestedVolume;
+}
+
+void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history)
+{
+ // Send URL history to plugin
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "init_history");
+ message.setValueLLSD("history", url_history);
+ sendMessage(message);
+
+ LL_DEBUGS("Plugin") << "Sending history" << LL_ENDL;
+}
+
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
new file mode 100644
index 0000000000..ebb9099576
--- /dev/null
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -0,0 +1,369 @@
+/**
+ * @file llpluginclassmedia.h
+ * @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#ifndef LL_LLPLUGINCLASSMEDIA_H
+#define LL_LLPLUGINCLASSMEDIA_H
+
+#include "llgltypes.h"
+#include "llpluginprocessparent.h"
+#include "llrect.h"
+#include "llpluginclassmediaowner.h"
+#include <queue>
+#include "v4color.h"
+
+class LLPluginClassMedia : public LLPluginProcessParentOwner
+{
+ LOG_CLASS(LLPluginClassMedia);
+public:
+ LLPluginClassMedia(LLPluginClassMediaOwner *owner);
+ virtual ~LLPluginClassMedia();
+
+ // local initialization, called by the media manager when creating a source
+ virtual bool init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug, const std::string &user_data_path);
+
+ // undoes everything init() didm called by the media manager when destroying a source
+ virtual void reset();
+
+ void idle(void);
+
+ // All of these may return 0 or an actual valid value.
+ // Callers need to check the return for 0, and not use the values in that case.
+ int getWidth() const { return (mMediaWidth > 0) ? mMediaWidth : 0; };
+ int getHeight() const { return (mMediaHeight > 0) ? mMediaHeight : 0; };
+ int getNaturalWidth() const { return mNaturalMediaWidth; };
+ int getNaturalHeight() const { return mNaturalMediaHeight; };
+ int getSetWidth() const { return mSetMediaWidth; };
+ int getSetHeight() const { return mSetMediaHeight; };
+ int getBitsWidth() const { return (mTextureWidth > 0) ? mTextureWidth : 0; };
+ int getBitsHeight() const { return (mTextureHeight > 0) ? mTextureHeight : 0; };
+ int getTextureWidth() const;
+ int getTextureHeight() const;
+ int getFullWidth() const { return mFullMediaWidth; };
+ int getFullHeight() const { return mFullMediaHeight; };
+
+ // This may return NULL. Callers need to check for and handle this case.
+ unsigned char* getBitsData();
+
+ // gets the format details of the texture data
+ // These may return 0 if they haven't been set up yet. The caller needs to detect this case.
+ int getTextureDepth() const { return mRequestedTextureDepth; };
+ int getTextureFormatInternal() const { return mRequestedTextureInternalFormat; };
+ int getTextureFormatPrimary() const { return mRequestedTextureFormat; };
+ int getTextureFormatType() const { return mRequestedTextureType; };
+ bool getTextureFormatSwapBytes() const { return mRequestedTextureSwapBytes; };
+ bool getTextureCoordsOpenGL() const { return mRequestedTextureCoordsOpenGL; };
+
+ void setSize(int width, int height);
+ void setAutoScale(bool auto_scale);
+
+ void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; };
+
+ // Returns true if all of the texture parameters (depth, format, size, and texture size) are set up and consistent.
+ // This will initially be false, and will also be false for some time after setSize while the resize is processed.
+ // Note that if this returns true, it is safe to use all the get() functions above without checking for invalid return values
+ // until you call idle() again.
+ bool textureValid(void);
+
+ bool getDirty(LLRect *dirty_rect = NULL);
+ void resetDirty(void);
+
+ typedef enum
+ {
+ MOUSE_EVENT_DOWN,
+ MOUSE_EVENT_UP,
+ MOUSE_EVENT_MOVE,
+ MOUSE_EVENT_DOUBLE_CLICK
+ }EMouseEventType;
+
+ void mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers);
+
+ typedef enum
+ {
+ KEY_EVENT_DOWN,
+ KEY_EVENT_UP,
+ KEY_EVENT_REPEAT
+ }EKeyEventType;
+
+ bool keyEvent(EKeyEventType type, int key_code, MASK modifiers);
+
+ void scrollEvent(int x, int y, MASK modifiers);
+
+ // Text may be unicode (utf8 encoded)
+ bool textInput(const std::string &text, MASK modifiers);
+
+ void loadURI(const std::string &uri);
+
+ // "Loading" means uninitialized or any state prior to fully running (processing commands)
+ bool isPluginLoading(void) { return mPlugin?mPlugin->isLoading():false; };
+
+ // "Running" means the steady state -- i.e. processing messages
+ bool isPluginRunning(void) { return mPlugin?mPlugin->isRunning():false; };
+
+ // "Exited" means any regular or error state after "Running" (plugin may have crashed or exited normally)
+ bool isPluginExited(void) { return mPlugin?mPlugin->isDone():false; };
+
+ std::string getPluginVersion() { return mPlugin?mPlugin->getPluginVersion():std::string(""); };
+
+ bool getDisableTimeout() { return mPlugin?mPlugin->getDisableTimeout():false; };
+ void setDisableTimeout(bool disable) { if(mPlugin) mPlugin->setDisableTimeout(disable); };
+
+ // Inherited from LLPluginProcessParentOwner
+ /* virtual */ void receivePluginMessage(const LLPluginMessage &message);
+ /* virtual */ void pluginLaunchFailed();
+ /* virtual */ void pluginDied();
+
+
+ typedef enum
+ {
+ PRIORITY_UNLOADED, // media plugin isn't even loaded.
+ PRIORITY_STOPPED, // media is not playing, shouldn't need to update at all.
+ PRIORITY_HIDDEN, // media is not being displayed or is out of view, don't need to do graphic updates, but may still update audio, playhead, etc.
+ PRIORITY_SLIDESHOW, // media is in the far distance, updates very infrequently
+ PRIORITY_LOW, // media is in the distance, may be rendered at reduced size
+ PRIORITY_NORMAL, // normal (default) priority
+ PRIORITY_HIGH // media has user focus and/or is taking up most of the screen
+ }EPriority;
+
+ static const char* priorityToString(EPriority priority);
+ void setPriority(EPriority priority);
+ void setLowPrioritySizeLimit(int size);
+
+ F64 getCPUUsage();
+
+ // Valid after a MEDIA_EVENT_CURSOR_CHANGED event
+ std::string getCursorName() const { return mCursorName; };
+
+ LLPluginClassMediaOwner::EMediaStatus getStatus() const { return mStatus; }
+
+ void cut();
+ bool canCut() const { return mCanCut; };
+
+ void copy();
+ bool canCopy() const { return mCanCopy; };
+
+ void paste();
+ bool canPaste() const { return mCanPaste; };
+
+ ///////////////////////////////////
+ // media browser class functions
+ bool pluginSupportsMediaBrowser(void);
+
+ void focus(bool focused);
+ void clear_cache();
+ void clear_cookies();
+ void enable_cookies(bool enable);
+ void proxy_setup(bool enable, const std::string &host = LLStringUtil::null, int port = 0);
+ void browse_stop();
+ void browse_reload(bool ignore_cache = false);
+ void browse_forward();
+ void browse_back();
+ void set_status_redirect(int code, const std::string &url);
+ void setBrowserUserAgent(const std::string& user_agent);
+
+ // This is valid after MEDIA_EVENT_NAVIGATE_BEGIN or MEDIA_EVENT_NAVIGATE_COMPLETE
+ std::string getNavigateURI() const { return mNavigateURI; };
+
+ // These are valid after MEDIA_EVENT_NAVIGATE_COMPLETE
+ S32 getNavigateResultCode() const { return mNavigateResultCode; };
+ std::string getNavigateResultString() const { return mNavigateResultString; };
+ bool getHistoryBackAvailable() const { return mHistoryBackAvailable; };
+ bool getHistoryForwardAvailable() const { return mHistoryForwardAvailable; };
+
+ // This is valid after MEDIA_EVENT_PROGRESS_UPDATED
+ int getProgressPercent() const { return mProgressPercent; };
+
+ // This is valid after MEDIA_EVENT_STATUS_TEXT_CHANGED
+ std::string getStatusText() const { return mStatusText; };
+
+ // This is valid after MEDIA_EVENT_LOCATION_CHANGED
+ std::string getLocation() const { return mLocation; };
+
+ // This is valid after MEDIA_EVENT_CLICK_LINK_HREF or MEDIA_EVENT_CLICK_LINK_NOFOLLOW
+ std::string getClickURL() const { return mClickURL; };
+
+ // This is valid after MEDIA_EVENT_CLICK_LINK_HREF
+ std::string getClickTarget() const { return mClickTarget; };
+
+ typedef enum
+ {
+ TARGET_NONE, // empty href target string
+ TARGET_BLANK, // target to open link in user's preferred browser
+ TARGET_EXTERNAL, // target to open link in external browser
+ TARGET_OTHER // nonempty and unsupported target type
+ }ETargetType;
+
+ // This is valid after MEDIA_EVENT_CLICK_LINK_HREF
+ ETargetType getClickTargetType() const { return mClickTargetType; };
+
+ std::string getMediaName() const { return mMediaName; };
+ std::string getMediaDescription() const { return mMediaDescription; };
+
+ // Crash the plugin. If you use this outside of a testbed, you will be punished.
+ void crashPlugin();
+
+ // Hang the plugin. If you use this outside of a testbed, you will be punished.
+ void hangPlugin();
+
+ ///////////////////////////////////
+ // media time class functions
+ bool pluginSupportsMediaTime(void);
+ void stop();
+ void start(float rate = 0.0f);
+ void pause();
+ void seek(float time);
+ void setLoop(bool loop);
+ void setVolume(float volume);
+ float getVolume();
+
+ F64 getCurrentTime(void) const { return mCurrentTime; };
+ F64 getDuration(void) const { return mDuration; };
+ F64 getCurrentPlayRate(void) { return mCurrentRate; };
+ F64 getLoadedDuration(void) const { return mLoadedDuration; };
+
+ // Initialize the URL history of the plugin by sending
+ // "init_history" message
+ void initializeUrlHistory(const LLSD& url_history);
+
+protected:
+
+ LLPluginClassMediaOwner *mOwner;
+
+ // Notify this object's owner that an event has occurred.
+ void mediaEvent(LLPluginClassMediaOwner::EMediaEvent event);
+
+ void sendMessage(const LLPluginMessage &message); // Send message internally, either queueing or sending directly.
+ std::queue<LLPluginMessage> mSendQueue; // Used to queue messages while the plugin initializes.
+
+ void setSizeInternal(void);
+
+ bool mTextureParamsReceived; // the mRequestedTexture* fields are only valid when this is true
+ S32 mRequestedTextureDepth;
+ LLGLenum mRequestedTextureInternalFormat;
+ LLGLenum mRequestedTextureFormat;
+ LLGLenum mRequestedTextureType;
+ bool mRequestedTextureSwapBytes;
+ bool mRequestedTextureCoordsOpenGL;
+
+ std::string mTextureSharedMemoryName;
+ size_t mTextureSharedMemorySize;
+
+ // True to scale requested media up to the full size of the texture (i.e. next power of two)
+ bool mAutoScaleMedia;
+
+ // default media size for the plugin, from the texture_params message.
+ int mDefaultMediaWidth;
+ int mDefaultMediaHeight;
+
+ // Size that has been requested by the plugin itself
+ int mNaturalMediaWidth;
+ int mNaturalMediaHeight;
+
+ // Size that has been requested with setSize()
+ int mSetMediaWidth;
+ int mSetMediaHeight;
+
+ // Full calculated media size (before auto-scale and downsample calculations)
+ int mFullMediaWidth;
+ int mFullMediaHeight;
+
+ // Actual media size being set (after auto-scale)
+ int mRequestedMediaWidth;
+ int mRequestedMediaHeight;
+
+ // Texture size calculated from actual media size
+ int mRequestedTextureWidth;
+ int mRequestedTextureHeight;
+
+ // Size that the plugin has acknowledged
+ int mTextureWidth;
+ int mTextureHeight;
+ int mMediaWidth;
+ int mMediaHeight;
+
+ float mRequestedVolume;
+
+ // Priority of this media stream
+ EPriority mPriority;
+ int mLowPrioritySizeLimit;
+
+ bool mAllowDownsample;
+ int mPadding;
+
+
+ LLPluginProcessParent *mPlugin;
+
+ LLRect mDirtyRect;
+
+ std::string translateModifiers(MASK modifiers);
+
+ std::string mCursorName;
+ int mLastMouseX;
+ int mLastMouseY;
+
+ LLPluginClassMediaOwner::EMediaStatus mStatus;
+
+ F64 mSleepTime;
+
+ bool mCanCut;
+ bool mCanCopy;
+ bool mCanPaste;
+
+ std::string mMediaName;
+ std::string mMediaDescription;
+
+ LLColor4 mBackgroundColor;
+
+ /////////////////////////////////////////
+ // media_browser class
+ std::string mNavigateURI;
+ S32 mNavigateResultCode;
+ std::string mNavigateResultString;
+ bool mHistoryBackAvailable;
+ bool mHistoryForwardAvailable;
+ std::string mStatusText;
+ int mProgressPercent;
+ std::string mLocation;
+ std::string mClickURL;
+ std::string mClickTarget;
+ ETargetType mClickTargetType;
+
+ /////////////////////////////////////////
+ // media_time class
+ F64 mCurrentTime;
+ F64 mDuration;
+ F64 mCurrentRate;
+ F64 mLoadedDuration;
+
+};
+
+#endif // LL_LLPLUGINCLASSMEDIA_H
diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h
new file mode 100644
index 0000000000..6d369cd51a
--- /dev/null
+++ b/indra/llplugin/llpluginclassmediaowner.h
@@ -0,0 +1,83 @@
+/**
+ * @file llpluginclassmediaowner.h
+ * @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#ifndef LL_LLPLUGINCLASSMEDIAOWNER_H
+#define LL_LLPLUGINCLASSMEDIAOWNER_H
+
+#include "llpluginprocessparent.h"
+#include "llrect.h"
+#include <queue>
+
+class LLPluginClassMedia;
+
+class LLPluginClassMediaOwner
+{
+public:
+ typedef enum
+ {
+ MEDIA_EVENT_CONTENT_UPDATED, // contents/dirty rect have updated
+ MEDIA_EVENT_TIME_DURATION_UPDATED, // current time and/or duration have updated
+ MEDIA_EVENT_SIZE_CHANGED, // media size has changed
+ MEDIA_EVENT_CURSOR_CHANGED, // plugin has requested a cursor change
+
+ MEDIA_EVENT_NAVIGATE_BEGIN, // browser has begun navigation
+ MEDIA_EVENT_NAVIGATE_COMPLETE, // browser has finished navigation
+ MEDIA_EVENT_PROGRESS_UPDATED, // browser has updated loading progress
+ MEDIA_EVENT_STATUS_TEXT_CHANGED, // browser has updated the status text
+ MEDIA_EVENT_NAME_CHANGED, // browser has updated the name of the media (typically <title> tag)
+ MEDIA_EVENT_LOCATION_CHANGED, // browser location (URL) has changed (maybe due to internal navagation/frames/etc)
+ MEDIA_EVENT_CLICK_LINK_HREF, // I'm not entirely sure what the semantics of these two are
+ MEDIA_EVENT_CLICK_LINK_NOFOLLOW,
+
+ MEDIA_EVENT_PLUGIN_FAILED_LAUNCH, // The plugin failed to launch
+ MEDIA_EVENT_PLUGIN_FAILED // The plugin died unexpectedly
+
+ } EMediaEvent;
+
+ typedef enum
+ {
+ MEDIA_NONE, // Uninitialized -- no useful state
+ MEDIA_LOADING, // loading or navigating
+ MEDIA_LOADED, // navigation/preroll complete
+ MEDIA_ERROR, // navigation/preroll failed
+ MEDIA_PLAYING, // playing (only for time-based media)
+ MEDIA_PAUSED, // paused (only for time-based media)
+ MEDIA_DONE // finished playing (only for time-based media)
+
+ } EMediaStatus;
+
+ virtual ~LLPluginClassMediaOwner() {};
+ virtual void handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent /*event*/) {};
+};
+
+#endif // LL_LLPLUGINCLASSMEDIAOWNER_H
diff --git a/indra/llplugin/llplugininstance.cpp b/indra/llplugin/llplugininstance.cpp
new file mode 100644
index 0000000000..44e3b4950f
--- /dev/null
+++ b/indra/llplugin/llplugininstance.cpp
@@ -0,0 +1,173 @@
+/**
+ * @file llplugininstance.cpp
+ * @brief LLPluginInstance handles loading the dynamic library of a plugin and setting up its entry points for message passing.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "linden_common.h"
+
+#include "llplugininstance.h"
+
+#include "llapr.h"
+
+/** Virtual destructor. */
+LLPluginInstanceMessageListener::~LLPluginInstanceMessageListener()
+{
+}
+
+/**
+ * TODO:DOC describe how it's used
+ */
+const char *LLPluginInstance::PLUGIN_INIT_FUNCTION_NAME = "LLPluginInitEntryPoint";
+
+/**
+ * Constructor.
+ *
+ * @param[in] owner Plugin instance. TODO:DOC is this a good description of what "owner" is?
+ */
+LLPluginInstance::LLPluginInstance(LLPluginInstanceMessageListener *owner) :
+ mDSOHandle(NULL),
+ mPluginUserData(NULL),
+ mPluginSendMessageFunction(NULL)
+{
+ mOwner = owner;
+}
+
+/**
+ * Destructor.
+ */
+LLPluginInstance::~LLPluginInstance()
+{
+ if(mDSOHandle != NULL)
+ {
+ apr_dso_unload(mDSOHandle);
+ mDSOHandle = NULL;
+ }
+}
+
+/**
+ * Dynamically loads the plugin and runs the plugin's init function.
+ *
+ * @param[in] plugin_file Name of plugin dll/dylib/so. TODO:DOC is this correct? see .h
+ * @return 0 if successful, APR error code or error code from the plugin's init function on failure.
+ */
+int LLPluginInstance::load(std::string &plugin_file)
+{
+ pluginInitFunction init_function = NULL;
+
+ int result = apr_dso_load(&mDSOHandle,
+ plugin_file.c_str(),
+ gAPRPoolp);
+ if(result != APR_SUCCESS)
+ {
+ char buf[1024];
+ apr_dso_error(mDSOHandle, buf, sizeof(buf));
+
+ LL_WARNS("Plugin") << "apr_dso_load of " << plugin_file << " failed with error " << result << " , additional info string: " << buf << LL_ENDL;
+
+ }
+
+ if(result == APR_SUCCESS)
+ {
+ result = apr_dso_sym((apr_dso_handle_sym_t*)&init_function,
+ mDSOHandle,
+ PLUGIN_INIT_FUNCTION_NAME);
+
+ if(result != APR_SUCCESS)
+ {
+ LL_WARNS("Plugin") << "apr_dso_sym failed with error " << result << LL_ENDL;
+ }
+ }
+
+ if(result == APR_SUCCESS)
+ {
+ result = init_function(staticReceiveMessage, (void*)this, &mPluginSendMessageFunction, &mPluginUserData);
+
+ if(result != APR_SUCCESS)
+ {
+ LL_WARNS("Plugin") << "call to init function failed with error " << result << LL_ENDL;
+ }
+ }
+
+ return (int)result;
+}
+
+/**
+ * Sends a message to the plugin.
+ *
+ * @param[in] message Message
+ */
+void LLPluginInstance::sendMessage(const std::string &message)
+{
+ if(mPluginSendMessageFunction)
+ {
+ LL_DEBUGS("Plugin") << "sending message to plugin: \"" << message << "\"" << LL_ENDL;
+ mPluginSendMessageFunction(message.c_str(), &mPluginUserData);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "dropping message: \"" << message << "\"" << LL_ENDL;
+ }
+}
+
+/**
+ * Idle. TODO:DOC what's the purpose of this?
+ *
+ */
+void LLPluginInstance::idle(void)
+{
+}
+
+// static
+void LLPluginInstance::staticReceiveMessage(const char *message_string, void **user_data)
+{
+ // TODO: validate that the user_data argument is still a valid LLPluginInstance pointer
+ // we could also use a key that's looked up in a map (instead of a direct pointer) for safety, but that's probably overkill
+ LLPluginInstance *self = (LLPluginInstance*)*user_data;
+ self->receiveMessage(message_string);
+}
+
+/**
+ * Plugin receives message from plugin loader shell.
+ *
+ * @param[in] message_string Message
+ */
+void LLPluginInstance::receiveMessage(const char *message_string)
+{
+ if(mOwner)
+ {
+ LL_DEBUGS("Plugin") << "processing incoming message: \"" << message_string << "\"" << LL_ENDL;
+ mOwner->receivePluginMessage(message_string);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "dropping incoming message: \"" << message_string << "\"" << LL_ENDL;
+ }
+}
diff --git a/indra/llplugin/llplugininstance.h b/indra/llplugin/llplugininstance.h
new file mode 100644
index 0000000000..c11d5ab5d4
--- /dev/null
+++ b/indra/llplugin/llplugininstance.h
@@ -0,0 +1,104 @@
+/**
+ * @file llplugininstance.h
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#ifndef LL_LLPLUGININSTANCE_H
+#define LL_LLPLUGININSTANCE_H
+
+#include "llstring.h"
+#include "llapr.h"
+
+#include "apr_dso.h"
+
+/**
+ * @brief LLPluginInstanceMessageListener receives messages sent from the plugin loader shell to the plugin.
+ */
+class LLPluginInstanceMessageListener
+{
+public:
+ virtual ~LLPluginInstanceMessageListener();
+ /** Plugin receives message from plugin loader shell. */
+ virtual void receivePluginMessage(const std::string &message) = 0;
+};
+
+/**
+ * @brief LLPluginInstance handles loading the dynamic library of a plugin and setting up its entry points for message passing.
+ */
+class LLPluginInstance
+{
+ LOG_CLASS(LLPluginInstance);
+public:
+ LLPluginInstance(LLPluginInstanceMessageListener *owner);
+ virtual ~LLPluginInstance();
+
+ // Load a plugin dll/dylib/so
+ // Returns 0 if successful, APR error code or error code returned from the plugin's init function on failure.
+ int load(std::string &plugin_file);
+
+ // Sends a message to the plugin.
+ void sendMessage(const std::string &message);
+
+ // TODO:DOC is this comment obsolete? can't find "send_count" anywhere in indra tree.
+ // send_count is the maximum number of message to process from the send queue. If negative, it will drain the queue completely.
+ // The receive queue is always drained completely.
+ // Returns the total number of messages processed from both queues.
+ void idle(void);
+
+ /** The signature of the function for sending a message from plugin to plugin loader shell.
+ *
+ * @param[in] message_string Null-terminated C string
+ * @param[in] user_data The opaque reference that the callee supplied during setup.
+ */
+ typedef void (*sendMessageFunction) (const char *message_string, void **user_data);
+
+ /** The signature of the plugin init function. TODO:DOC check direction (pluging loader shell to plugin?)
+ *
+ * @param[in] host_user_data Data from plugin loader shell.
+ * @param[in] plugin_send_function Function for sending from the plugin loader shell to plugin.
+ */
+ typedef int (*pluginInitFunction) (sendMessageFunction host_send_func, void *host_user_data, sendMessageFunction *plugin_send_func, void **plugin_user_data);
+
+ /** Name of plugin init function */
+ static const char *PLUGIN_INIT_FUNCTION_NAME;
+
+private:
+ static void staticReceiveMessage(const char *message_string, void **user_data);
+ void receiveMessage(const char *message_string);
+
+ apr_dso_handle_t *mDSOHandle;
+
+ void *mPluginUserData;
+ sendMessageFunction mPluginSendMessageFunction;
+
+ LLPluginInstanceMessageListener *mOwner;
+};
+
+#endif // LL_LLPLUGININSTANCE_H
diff --git a/indra/llplugin/llpluginmessage.cpp b/indra/llplugin/llpluginmessage.cpp
new file mode 100644
index 0000000000..f76d848a70
--- /dev/null
+++ b/indra/llplugin/llpluginmessage.cpp
@@ -0,0 +1,443 @@
+/**
+ * @file llpluginmessage.cpp
+ * @brief LLPluginMessage encapsulates the serialization/deserialization of messages passed to and from plugins.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "linden_common.h"
+
+#include "llpluginmessage.h"
+#include "llsdserialize.h"
+#include "u64.h"
+
+/**
+ * Constructor.
+ */
+LLPluginMessage::LLPluginMessage()
+{
+}
+
+/**
+ * Constructor.
+ *
+ * @param[in] p Existing message
+ */
+LLPluginMessage::LLPluginMessage(const LLPluginMessage &p)
+{
+ mMessage = p.mMessage;
+}
+
+/**
+ * Constructor.
+ *
+ * @param[in] message_class Message class
+ * @param[in] message_name Message name
+ */
+LLPluginMessage::LLPluginMessage(const std::string &message_class, const std::string &message_name)
+{
+ setMessage(message_class, message_name);
+}
+
+
+/**
+ * Destructor.
+ */
+LLPluginMessage::~LLPluginMessage()
+{
+}
+
+/**
+ * Reset all internal state.
+ */
+void LLPluginMessage::clear()
+{
+ mMessage = LLSD::emptyMap();
+ mMessage["params"] = LLSD::emptyMap();
+}
+
+/**
+ * Sets the message class and name. Also has the side-effect of clearing any key-value pairs in the message.
+ *
+ * @param[in] message_class Message class
+ * @param[in] message_name Message name
+ */
+void LLPluginMessage::setMessage(const std::string &message_class, const std::string &message_name)
+{
+ clear();
+ mMessage["class"] = message_class;
+ mMessage["name"] = message_name;
+}
+
+/**
+ * Sets a key/value pair in the message, where the value is a string.
+ *
+ * @param[in] key Key
+ * @param[in] value String value
+ */
+void LLPluginMessage::setValue(const std::string &key, const std::string &value)
+{
+ mMessage["params"][key] = value;
+}
+
+/**
+ * Sets a key/value pair in the message, where the value is LLSD.
+ *
+ * @param[in] key Key
+ * @param[in] value LLSD value
+ */
+void LLPluginMessage::setValueLLSD(const std::string &key, const LLSD &value)
+{
+ mMessage["params"][key] = value;
+}
+
+/**
+ * Sets a key/value pair in the message, where the value is signed 32-bit.
+ *
+ * @param[in] key Key
+ * @param[in] value 32-bit signed value
+ */
+void LLPluginMessage::setValueS32(const std::string &key, S32 value)
+{
+ mMessage["params"][key] = value;
+}
+
+/**
+ * Sets a key/value pair in the message, where the value is unsigned 32-bit. The value is stored as a string beginning with "0x".
+ *
+ * @param[in] key Key
+ * @param[in] value 32-bit unsigned value
+ */
+void LLPluginMessage::setValueU32(const std::string &key, U32 value)
+{
+ std::stringstream temp;
+ temp << "0x" << std::hex << value;
+ setValue(key, temp.str());
+}
+
+/**
+ * Sets a key/value pair in the message, where the value is a bool.
+ *
+ * @param[in] key Key
+ * @param[in] value Boolean value
+ */
+void LLPluginMessage::setValueBoolean(const std::string &key, bool value)
+{
+ mMessage["params"][key] = value;
+}
+
+/**
+ * Sets a key/value pair in the message, where the value is a double.
+ *
+ * @param[in] key Key
+ * @param[in] value Boolean value
+ */
+void LLPluginMessage::setValueReal(const std::string &key, F64 value)
+{
+ mMessage["params"][key] = value;
+}
+
+/**
+ * Sets a key/value pair in the message, where the value is a pointer. The pointer is stored as a string.
+ *
+ * @param[in] key Key
+ * @param[in] value Pointer value
+ */
+void LLPluginMessage::setValuePointer(const std::string &key, void* value)
+{
+ std::stringstream temp;
+ // iostreams should output pointer values in hex with an initial 0x by default.
+ temp << value;
+ setValue(key, temp.str());
+}
+
+/**
+ * Gets the message class.
+ *
+ * @return Message class
+ */
+std::string LLPluginMessage::getClass(void) const
+{
+ return mMessage["class"];
+}
+
+/**
+ * Gets the message name.
+ *
+ * @return Message name
+ */
+std::string LLPluginMessage::getName(void) const
+{
+ return mMessage["name"];
+}
+
+/**
+ * Returns true if the specified key exists in this message (useful for optional parameters).
+ *
+ * @param[in] key Key
+ *
+ * @return True if key exists, false otherwise.
+ */
+bool LLPluginMessage::hasValue(const std::string &key) const
+{
+ bool result = false;
+
+ if(mMessage["params"].has(key))
+ {
+ result = true;
+ }
+
+ return result;
+}
+
+/**
+ * Gets the value of a key as a string. If the key does not exist, an empty string will be returned.
+ *
+ * @param[in] key Key
+ *
+ * @return String value of key if key exists, empty string if key does not exist.
+ */
+std::string LLPluginMessage::getValue(const std::string &key) const
+{
+ std::string result;
+
+ if(mMessage["params"].has(key))
+ {
+ result = mMessage["params"][key].asString();
+ }
+
+ return result;
+}
+
+/**
+ * Gets the value of a key as LLSD. If the key does not exist, a null LLSD will be returned.
+ *
+ * @param[in] key Key
+ *
+ * @return LLSD value of key if key exists, null LLSD if key does not exist.
+ */
+LLSD LLPluginMessage::getValueLLSD(const std::string &key) const
+{
+ LLSD result;
+
+ if(mMessage["params"].has(key))
+ {
+ result = mMessage["params"][key];
+ }
+
+ return result;
+}
+
+/**
+ * Gets the value of a key as signed 32-bit int. If the key does not exist, 0 will be returned.
+ *
+ * @param[in] key Key
+ *
+ * @return Signed 32-bit int value of key if key exists, 0 if key does not exist.
+ */
+S32 LLPluginMessage::getValueS32(const std::string &key) const
+{
+ S32 result = 0;
+
+ if(mMessage["params"].has(key))
+ {
+ result = mMessage["params"][key].asInteger();
+ }
+
+ return result;
+}
+
+/**
+ * Gets the value of a key as unsigned 32-bit int. If the key does not exist, 0 will be returned.
+ *
+ * @param[in] key Key
+ *
+ * @return Unsigned 32-bit int value of key if key exists, 0 if key does not exist.
+ */
+U32 LLPluginMessage::getValueU32(const std::string &key) const
+{
+ U32 result = 0;
+
+ if(mMessage["params"].has(key))
+ {
+ std::string value = mMessage["params"][key].asString();
+
+ result = (U32)strtoul(value.c_str(), NULL, 16);
+ }
+
+ return result;
+}
+
+/**
+ * Gets the value of a key as a bool. If the key does not exist, false will be returned.
+ *
+ * @param[in] key Key
+ *
+ * @return Boolean value of key if it exists, false otherwise.
+ */
+bool LLPluginMessage::getValueBoolean(const std::string &key) const
+{
+ bool result = false;
+
+ if(mMessage["params"].has(key))
+ {
+ result = mMessage["params"][key].asBoolean();
+ }
+
+ return result;
+}
+
+/**
+ * Gets the value of a key as a double. If the key does not exist, 0 will be returned.
+ *
+ * @param[in] key Key
+ *
+ * @return Value as a double if key exists, 0 otherwise.
+ */
+F64 LLPluginMessage::getValueReal(const std::string &key) const
+{
+ F64 result = 0.0f;
+
+ if(mMessage["params"].has(key))
+ {
+ result = mMessage["params"][key].asReal();
+ }
+
+ return result;
+}
+
+/**
+ * Gets the value of a key as a pointer. If the key does not exist, NULL will be returned.
+ *
+ * @param[in] key Key
+ *
+ * @return Pointer value if key exists, NULL otherwise.
+ */
+void* LLPluginMessage::getValuePointer(const std::string &key) const
+{
+ void* result = NULL;
+
+ if(mMessage["params"].has(key))
+ {
+ std::string value = mMessage["params"][key].asString();
+
+ result = (void*)llstrtou64(value.c_str(), NULL, 16);
+ }
+
+ return result;
+}
+
+/**
+ * Flatten the message into a string.
+ *
+ * @return Message as a string.
+ */
+std::string LLPluginMessage::generate(void) const
+{
+ std::ostringstream result;
+
+ // Pretty XML may be slightly easier to deal with while debugging...
+// LLSDSerialize::toXML(mMessage, result);
+ LLSDSerialize::toPrettyXML(mMessage, result);
+
+ return result.str();
+}
+
+/**
+ * Parse an incoming message into component parts. Clears all existing state before starting the parse.
+ *
+ * @return Returns -1 on failure, otherwise returns the number of key/value pairs in the incoming message.
+ */
+int LLPluginMessage::parse(const std::string &message)
+{
+ // clear any previous state
+ clear();
+
+ std::istringstream input(message);
+
+ S32 parse_result = LLSDSerialize::fromXML(mMessage, input);
+
+ return (int)parse_result;
+}
+
+
+/**
+ * Destructor
+ */
+LLPluginMessageListener::~LLPluginMessageListener()
+{
+ // TODO: should listeners have a way to ensure they're removed from dispatcher lists when deleted?
+}
+
+
+/**
+ * Destructor
+ */
+LLPluginMessageDispatcher::~LLPluginMessageDispatcher()
+{
+
+}
+
+/**
+ * Add a message listener. TODO:DOC need more info on what uses this. when are multiple listeners needed?
+ *
+ * @param[in] listener Message listener
+ */
+void LLPluginMessageDispatcher::addPluginMessageListener(LLPluginMessageListener *listener)
+{
+ mListeners.insert(listener);
+}
+
+/**
+ * Remove a message listener.
+ *
+ * @param[in] listener Message listener
+ */
+void LLPluginMessageDispatcher::removePluginMessageListener(LLPluginMessageListener *listener)
+{
+ mListeners.erase(listener);
+}
+
+/**
+ * Distribute a message to all message listeners.
+ *
+ * @param[in] message Message
+ */
+void LLPluginMessageDispatcher::dispatchPluginMessage(const LLPluginMessage &message)
+{
+ for (listener_set_t::iterator it = mListeners.begin();
+ it != mListeners.end();
+ )
+ {
+ LLPluginMessageListener* listener = *it;
+ listener->receivePluginMessage(message);
+ // In case something deleted an entry.
+ it = mListeners.upper_bound(listener);
+ }
+}
diff --git a/indra/llplugin/llpluginmessage.h b/indra/llplugin/llpluginmessage.h
new file mode 100644
index 0000000000..cbd31e0964
--- /dev/null
+++ b/indra/llplugin/llpluginmessage.h
@@ -0,0 +1,142 @@
+/**
+ * @file llpluginmessage.h
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#ifndef LL_LLPLUGINMESSAGE_H
+#define LL_LLPLUGINMESSAGE_H
+
+#include "llsd.h"
+
+/**
+ * @brief LLPluginMessage encapsulates the serialization/deserialization of messages passed to and from plugins.
+ */
+class LLPluginMessage
+{
+ LOG_CLASS(LLPluginMessage);
+public:
+ LLPluginMessage();
+ LLPluginMessage(const LLPluginMessage &p);
+ LLPluginMessage(const std::string &message_class, const std::string &message_name);
+ ~LLPluginMessage();
+
+ // reset all internal state
+ void clear(void);
+
+ // Sets the message class and name
+ // Also has the side-effect of clearing any key/value pairs in the message.
+ void setMessage(const std::string &message_class, const std::string &message_name);
+
+ // Sets a key/value pair in the message
+ void setValue(const std::string &key, const std::string &value);
+ void setValueLLSD(const std::string &key, const LLSD &value);
+ void setValueS32(const std::string &key, S32 value);
+ void setValueU32(const std::string &key, U32 value);
+ void setValueBoolean(const std::string &key, bool value);
+ void setValueReal(const std::string &key, F64 value);
+ void setValuePointer(const std::string &key, void *value);
+
+ std::string getClass(void) const;
+ std::string getName(void) const;
+
+ // Returns true if the specified key exists in this message (useful for optional parameters)
+ bool hasValue(const std::string &key) const;
+
+ // get the value of a particular key as a string. If the key doesn't exist in the message, an empty string will be returned.
+ std::string getValue(const std::string &key) const;
+
+ // get the value of a particular key as LLSD. If the key doesn't exist in the message, a null LLSD will be returned.
+ LLSD getValueLLSD(const std::string &key) const;
+
+ // get the value of a key as a S32. If the value wasn't set as a S32, behavior is undefined.
+ S32 getValueS32(const std::string &key) const;
+
+ // get the value of a key as a U32. Since there isn't an LLSD type for this, we use a hexadecimal string instead.
+ U32 getValueU32(const std::string &key) const;
+
+ // get the value of a key as a Boolean.
+ bool getValueBoolean(const std::string &key) const;
+
+ // get the value of a key as a float.
+ F64 getValueReal(const std::string &key) const;
+
+ // get the value of a key as a pointer.
+ void* getValuePointer(const std::string &key) const;
+
+ // Flatten the message into a string
+ std::string generate(void) const;
+
+ // Parse an incoming message into component parts
+ // (this clears out all existing state before starting the parse)
+ // Returns -1 on failure, otherwise returns the number of key/value pairs in the message.
+ int parse(const std::string &message);
+
+
+private:
+
+ LLSD mMessage;
+
+};
+
+/**
+ * @brief Listener for plugin messages.
+ */
+class LLPluginMessageListener
+{
+public:
+ virtual ~LLPluginMessageListener();
+ /** Plugin receives message from plugin loader shell. */
+ virtual void receivePluginMessage(const LLPluginMessage &message) = 0;
+
+};
+
+/**
+ * @brief Dispatcher for plugin messages.
+ *
+ * Manages the set of plugin message listeners and distributes messages to plugin message listeners.
+ */
+class LLPluginMessageDispatcher
+{
+public:
+ virtual ~LLPluginMessageDispatcher();
+
+ void addPluginMessageListener(LLPluginMessageListener *);
+ void removePluginMessageListener(LLPluginMessageListener *);
+protected:
+ void dispatchPluginMessage(const LLPluginMessage &message);
+
+ /** A set of message listeners. */
+ typedef std::set<LLPluginMessageListener*> listener_set_t;
+ /** The set of message listeners. */
+ listener_set_t mListeners;
+};
+
+
+#endif // LL_LLPLUGINMESSAGE_H
diff --git a/indra/llplugin/llpluginmessageclasses.h b/indra/llplugin/llpluginmessageclasses.h
new file mode 100644
index 0000000000..01fddb92c5
--- /dev/null
+++ b/indra/llplugin/llpluginmessageclasses.h
@@ -0,0 +1,58 @@
+/**
+ * @file llpluginmessageclasses.h
+ * @brief This file defines the versions of existing message classes for LLPluginMessage.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#ifndef LL_LLPLUGINMESSAGECLASSES_H
+#define LL_LLPLUGINMESSAGECLASSES_H
+
+// Version strings for each plugin message class.
+// Backwards-compatible changes (i.e. changes which only add new messges) should increment the minor version (i.e. "1.0" -> "1.1").
+// Non-backwards-compatible changes (which delete messages or change their semantics) should increment the major version (i.e. "1.1" -> "2.0").
+// Plugins will supply the set of message classes they understand, with version numbers, as part of their init_response message.
+// The contents and semantics of the base:init message must NEVER change in a non-backwards-compatible way, as a special case.
+
+#define LLPLUGIN_MESSAGE_CLASS_INTERNAL "internal"
+#define LLPLUGIN_MESSAGE_CLASS_INTERNAL_VERSION "1.0"
+
+#define LLPLUGIN_MESSAGE_CLASS_BASE "base"
+#define LLPLUGIN_MESSAGE_CLASS_BASE_VERSION "1.0"
+
+#define LLPLUGIN_MESSAGE_CLASS_MEDIA "media"
+#define LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION "1.0"
+
+#define LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER "media_browser"
+#define LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION "1.0"
+
+#define LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME "media_time"
+#define LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION "1.0"
+
+#endif // LL_LLPLUGINMESSAGECLASSES_H
diff --git a/indra/llplugin/llpluginmessagepipe.cpp b/indra/llplugin/llpluginmessagepipe.cpp
new file mode 100644
index 0000000000..cc193fca42
--- /dev/null
+++ b/indra/llplugin/llpluginmessagepipe.cpp
@@ -0,0 +1,317 @@
+/**
+ * @file llpluginmessagepipe.cpp
+ * @brief Classes that implement connections from the plugin system to pipes/pumps.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "linden_common.h"
+
+#include "llpluginmessagepipe.h"
+#include "llbufferstream.h"
+
+#include "llapr.h"
+
+static const char MESSAGE_DELIMITER = '\0';
+
+LLPluginMessagePipeOwner::LLPluginMessagePipeOwner() :
+ mMessagePipe(NULL),
+ mSocketError(APR_SUCCESS)
+{
+}
+
+// virtual
+LLPluginMessagePipeOwner::~LLPluginMessagePipeOwner()
+{
+ killMessagePipe();
+}
+
+// virtual
+apr_status_t LLPluginMessagePipeOwner::socketError(apr_status_t error)
+{
+ mSocketError = error;
+ return error;
+};
+
+//virtual
+void LLPluginMessagePipeOwner::setMessagePipe(LLPluginMessagePipe *read_pipe)
+{
+ // Save a reference to this pipe
+ mMessagePipe = read_pipe;
+}
+
+bool LLPluginMessagePipeOwner::canSendMessage(void)
+{
+ return (mMessagePipe != NULL);
+}
+
+bool LLPluginMessagePipeOwner::writeMessageRaw(const std::string &message)
+{
+ bool result = true;
+ if(mMessagePipe != NULL)
+ {
+ result = mMessagePipe->addMessage(message);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "dropping message: " << message << LL_ENDL;
+ result = false;
+ }
+
+ return result;
+}
+
+void LLPluginMessagePipeOwner::killMessagePipe(void)
+{
+ if(mMessagePipe != NULL)
+ {
+ delete mMessagePipe;
+ mMessagePipe = NULL;
+ }
+}
+
+LLPluginMessagePipe::LLPluginMessagePipe(LLPluginMessagePipeOwner *owner, LLSocket::ptr_t socket)
+{
+ mOwner = owner;
+ mOwner->setMessagePipe(this);
+ mSocket = socket;
+}
+
+LLPluginMessagePipe::~LLPluginMessagePipe()
+{
+ if(mOwner != NULL)
+ {
+ mOwner->setMessagePipe(NULL);
+ }
+}
+
+bool LLPluginMessagePipe::addMessage(const std::string &message)
+{
+ // queue the message for later output
+ mOutput += message;
+ mOutput += MESSAGE_DELIMITER; // message separator
+
+ return true;
+}
+
+void LLPluginMessagePipe::clearOwner(void)
+{
+ // The owner is done with this pipe. The next call to process_impl should send any remaining data and exit.
+ mOwner = NULL;
+}
+
+void LLPluginMessagePipe::setSocketTimeout(apr_interval_time_t timeout_usec)
+{
+ // We never want to sleep forever, so force negative timeouts to become non-blocking.
+
+ // according to this page: http://dev.ariel-networks.com/apr/apr-tutorial/html/apr-tutorial-13.html
+ // blocking/non-blocking with apr sockets is somewhat non-portable.
+
+ if(timeout_usec <= 0)
+ {
+ // Make the socket non-blocking
+ apr_socket_opt_set(mSocket->getSocket(), APR_SO_NONBLOCK, 1);
+ apr_socket_timeout_set(mSocket->getSocket(), 0);
+ }
+ else
+ {
+ // Make the socket blocking-with-timeout
+ apr_socket_opt_set(mSocket->getSocket(), APR_SO_NONBLOCK, 1);
+ apr_socket_timeout_set(mSocket->getSocket(), timeout_usec);
+ }
+}
+
+bool LLPluginMessagePipe::pump(F64 timeout)
+{
+ bool result = true;
+
+ if(mSocket)
+ {
+ apr_status_t status;
+ apr_size_t size;
+
+ if(!mOutput.empty())
+ {
+ // write any outgoing messages
+ size = (apr_size_t)mOutput.size();
+
+ setSocketTimeout(0);
+
+// LL_INFOS("Plugin") << "before apr_socket_send, size = " << size << LL_ENDL;
+
+ status = apr_socket_send(
+ mSocket->getSocket(),
+ (const char*)mOutput.data(),
+ &size);
+
+// LL_INFOS("Plugin") << "after apr_socket_send, size = " << size << LL_ENDL;
+
+ if(status == APR_SUCCESS)
+ {
+ // success
+ mOutput = mOutput.substr(size);
+ }
+ else if(APR_STATUS_IS_EAGAIN(status))
+ {
+ // Socket buffer is full...
+ // remove the written part from the buffer and try again later.
+ mOutput = mOutput.substr(size);
+ }
+ else
+ {
+ // some other error
+ // Treat this as fatal.
+ ll_apr_warn_status(status);
+
+ if(mOwner)
+ {
+ mOwner->socketError(status);
+ }
+ result = false;
+ }
+ }
+
+ // FIXME: For some reason, the apr timeout stuff isn't working properly on windows.
+ // Until such time as we figure out why, don't try to use the socket timeout -- just sleep here instead.
+#if LL_WINDOWS
+ if(result)
+ {
+ if(timeout != 0.0f)
+ {
+ ms_sleep((int)(timeout * 1000.0f));
+ timeout = 0.0f;
+ }
+ }
+#endif
+
+ // Check for incoming messages
+ if(result)
+ {
+ char input_buf[1024];
+ apr_size_t request_size;
+
+ // Start out by reading one byte, so that any data received will wake us up.
+ request_size = 1;
+
+ // and use the timeout so we'll sleep if no data is available.
+ setSocketTimeout((apr_interval_time_t)(timeout * 1000000));
+
+ while(1)
+ {
+ size = request_size;
+
+// LL_INFOS("Plugin") << "before apr_socket_recv, size = " << size << LL_ENDL;
+
+ status = apr_socket_recv(
+ mSocket->getSocket(),
+ input_buf,
+ &size);
+
+// LL_INFOS("Plugin") << "after apr_socket_recv, size = " << size << LL_ENDL;
+
+ if(size > 0)
+ mInput.append(input_buf, size);
+
+ if(status == APR_SUCCESS)
+ {
+// llinfos << "success, read " << size << llendl;
+
+ if(size != request_size)
+ {
+ // This was a short read, so we're done.
+ break;
+ }
+ }
+ else if(APR_STATUS_IS_TIMEUP(status))
+ {
+// llinfos << "TIMEUP, read " << size << llendl;
+
+ // Timeout was hit. Since the initial read is 1 byte, this should never be a partial read.
+ break;
+ }
+ else if(APR_STATUS_IS_EAGAIN(status))
+ {
+// llinfos << "EAGAIN, read " << size << llendl;
+
+ // We've been doing partial reads, and we're done now.
+ break;
+ }
+ else
+ {
+ // some other error
+ // Treat this as fatal.
+ ll_apr_warn_status(status);
+
+ if(mOwner)
+ {
+ mOwner->socketError(status);
+ }
+ result = false;
+ break;
+ }
+
+ // Second and subsequent reads should not use the timeout
+ setSocketTimeout(0);
+ // and should try to fill the input buffer
+ request_size = sizeof(input_buf);
+ }
+
+ processInput();
+ }
+ }
+
+ if(!result)
+ {
+ // If we got an error, we're done.
+ LL_INFOS("Plugin") << "Error from socket, cleaning up." << LL_ENDL;
+ delete this;
+ }
+
+ return result;
+}
+
+void LLPluginMessagePipe::processInput(void)
+{
+ // Look for input delimiter(s) in the input buffer.
+ int start = 0;
+ int delim;
+ while((delim = mInput.find(MESSAGE_DELIMITER, start)) != std::string::npos)
+ {
+ // Let the owner process this message
+ mOwner->receiveMessageRaw(mInput.substr(start, delim - start));
+
+ start = delim + 1;
+ }
+
+ // Remove delivered messages from the input buffer.
+ if(start != 0)
+ mInput = mInput.substr(start);
+
+}
+
diff --git a/indra/llplugin/llpluginmessagepipe.h b/indra/llplugin/llpluginmessagepipe.h
new file mode 100644
index 0000000000..1ddb38de68
--- /dev/null
+++ b/indra/llplugin/llpluginmessagepipe.h
@@ -0,0 +1,93 @@
+/**
+ * @file llpluginmessagepipe.h
+ * @brief Classes that implement connections from the plugin system to pipes/pumps.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#ifndef LL_LLPLUGINMESSAGEPIPE_H
+#define LL_LLPLUGINMESSAGEPIPE_H
+
+#include "lliosocket.h"
+
+class LLPluginMessagePipe;
+
+// Inherit from this to be able to receive messages from the LLPluginMessagePipe
+class LLPluginMessagePipeOwner
+{
+ LOG_CLASS(LLPluginMessagePipeOwner);
+public:
+ LLPluginMessagePipeOwner();
+ virtual ~LLPluginMessagePipeOwner();
+ // called with incoming messages
+ virtual void receiveMessageRaw(const std::string &message) = 0;
+ // called when the socket has an error
+ virtual apr_status_t socketError(apr_status_t error);
+
+ // called from LLPluginMessagePipe to manage the connection with LLPluginMessagePipeOwner -- do not use!
+ virtual void setMessagePipe(LLPluginMessagePipe *message_pipe) ;
+
+protected:
+ // returns false if writeMessageRaw() would drop the message
+ bool canSendMessage(void);
+ // call this to send a message over the pipe
+ bool writeMessageRaw(const std::string &message);
+ // call this to close the pipe
+ void killMessagePipe(void);
+
+ LLPluginMessagePipe *mMessagePipe;
+ apr_status_t mSocketError;
+};
+
+class LLPluginMessagePipe
+{
+ LOG_CLASS(LLPluginMessagePipe);
+public:
+ LLPluginMessagePipe(LLPluginMessagePipeOwner *owner, LLSocket::ptr_t socket);
+ virtual ~LLPluginMessagePipe();
+
+ bool addMessage(const std::string &message);
+ void clearOwner(void);
+
+ bool pump(F64 timeout = 0.0f);
+
+protected:
+ void processInput(void);
+
+ // used internally by pump()
+ void setSocketTimeout(apr_interval_time_t timeout_usec);
+
+ std::string mInput;
+ std::string mOutput;
+
+ LLPluginMessagePipeOwner *mOwner;
+ LLSocket::ptr_t mSocket;
+};
+
+#endif // LL_LLPLUGINMESSAGE_H
diff --git a/indra/llplugin/llpluginprocesschild.cpp b/indra/llplugin/llpluginprocesschild.cpp
new file mode 100644
index 0000000000..07fc82c770
--- /dev/null
+++ b/indra/llplugin/llpluginprocesschild.cpp
@@ -0,0 +1,497 @@
+/**
+ * @file llpluginprocesschild.cpp
+ * @brief LLPluginProcessChild handles the child side of the external-process plugin API.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "linden_common.h"
+
+#include "llpluginprocesschild.h"
+#include "llplugininstance.h"
+#include "llpluginmessagepipe.h"
+#include "llpluginmessageclasses.h"
+
+static const F32 HEARTBEAT_SECONDS = 1.0f;
+static const F32 PLUGIN_IDLE_SECONDS = 1.0f / 100.0f; // Each call to idle will give the plugin this much time.
+
+LLPluginProcessChild::LLPluginProcessChild()
+{
+ mInstance = NULL;
+ mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);
+ mSleepTime = PLUGIN_IDLE_SECONDS; // default: send idle messages at 100Hz
+ mCPUElapsed = 0.0f;
+}
+
+LLPluginProcessChild::~LLPluginProcessChild()
+{
+ if(mInstance != NULL)
+ {
+ sendMessageToPlugin(LLPluginMessage("base", "cleanup"));
+
+ // IMPORTANT: under some (unknown) circumstances the apr_dso_unload() triggered when mInstance is deleted
+ // appears to fail and lock up which means that a given instance of the slplugin process never exits.
+ // This is bad, especially when users try to update their version of SL - it fails because the slplugin
+ // process as well as a bunch of plugin specific files are locked and cannot be overwritten.
+ exit( 0 );
+ //delete mInstance;
+ //mInstance = NULL;
+ }
+}
+
+void LLPluginProcessChild::killSockets(void)
+{
+ killMessagePipe();
+ mSocket.reset();
+}
+
+void LLPluginProcessChild::init(U32 launcher_port)
+{
+ mLauncherHost = LLHost("127.0.0.1", launcher_port);
+ setState(STATE_INITIALIZED);
+}
+
+void LLPluginProcessChild::idle(void)
+{
+ bool idle_again;
+ do
+ {
+ if(mSocketError != APR_SUCCESS)
+ {
+ LL_INFOS("Plugin") << "message pipe is in error state, moving to STATE_ERROR"<< LL_ENDL;
+ setState(STATE_ERROR);
+ }
+
+ if((mState > STATE_INITIALIZED) && (mMessagePipe == NULL))
+ {
+ // The pipe has been closed -- we're done.
+ // TODO: This could be slightly more subtle, but I'm not sure it needs to be.
+ LL_INFOS("Plugin") << "message pipe went away, moving to STATE_ERROR"<< LL_ENDL;
+ setState(STATE_ERROR);
+ }
+
+ // If a state needs to go directly to another state (as a performance enhancement), it can set idle_again to true after calling setState().
+ // USE THIS CAREFULLY, since it can starve other code. Specifically make sure there's no way to get into a closed cycle and never return.
+ // When in doubt, don't do it.
+ idle_again = false;
+
+ if(mInstance != NULL)
+ {
+ // Provide some time to the plugin
+ mInstance->idle();
+ }
+
+ switch(mState)
+ {
+ case STATE_UNINITIALIZED:
+ break;
+
+ case STATE_INITIALIZED:
+ if(mSocket->blockingConnect(mLauncherHost))
+ {
+ // This automatically sets mMessagePipe
+ new LLPluginMessagePipe(this, mSocket);
+
+ setState(STATE_CONNECTED);
+ }
+ else
+ {
+ // connect failed
+ setState(STATE_ERROR);
+ }
+ break;
+
+ case STATE_CONNECTED:
+ sendMessageToParent(LLPluginMessage(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hello"));
+ setState(STATE_PLUGIN_LOADING);
+ break;
+
+ case STATE_PLUGIN_LOADING:
+ if(!mPluginFile.empty())
+ {
+ mInstance = new LLPluginInstance(this);
+ if(mInstance->load(mPluginFile) == 0)
+ {
+ mHeartbeat.start();
+ mHeartbeat.setTimerExpirySec(HEARTBEAT_SECONDS);
+ mCPUElapsed = 0.0f;
+ setState(STATE_PLUGIN_LOADED);
+ }
+ else
+ {
+ setState(STATE_ERROR);
+ }
+ }
+ break;
+
+ case STATE_PLUGIN_LOADED:
+ {
+ setState(STATE_PLUGIN_INITIALIZING);
+ LLPluginMessage message("base", "init");
+ message.setValue("user_data_path", mUserDataPath);
+ sendMessageToPlugin(message);
+ }
+ break;
+
+ case STATE_PLUGIN_INITIALIZING:
+ // waiting for init_response...
+ break;
+
+ case STATE_RUNNING:
+ if(mInstance != NULL)
+ {
+ // Provide some time to the plugin
+ LLPluginMessage message("base", "idle");
+ message.setValueReal("time", PLUGIN_IDLE_SECONDS);
+ sendMessageToPlugin(message);
+
+ mInstance->idle();
+
+ if(mHeartbeat.hasExpired())
+ {
+
+ // This just proves that we're not stuck down inside the plugin code.
+ LLPluginMessage heartbeat(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "heartbeat");
+
+ // Calculate the approximage CPU usage fraction (floating point value between 0 and 1) used by the plugin this heartbeat cycle.
+ // Note that this will not take into account any threads or additional processes the plugin spawns, but it's a first approximation.
+ // If we could write OS-specific functions to query the actual CPU usage of this process, that would be a better approximation.
+ heartbeat.setValueReal("cpu_usage", mCPUElapsed / mHeartbeat.getElapsedTimeF64());
+
+ sendMessageToParent(heartbeat);
+
+ mHeartbeat.reset();
+ mHeartbeat.setTimerExpirySec(HEARTBEAT_SECONDS);
+ mCPUElapsed = 0.0f;
+ }
+ }
+ // receivePluginMessage will transition to STATE_UNLOADING
+ break;
+
+ case STATE_UNLOADING:
+ if(mInstance != NULL)
+ {
+ sendMessageToPlugin(LLPluginMessage("base", "cleanup"));
+ delete mInstance;
+ mInstance = NULL;
+ }
+ setState(STATE_UNLOADED);
+ break;
+
+ case STATE_UNLOADED:
+ killSockets();
+ setState(STATE_DONE);
+ break;
+
+ case STATE_ERROR:
+ // Close the socket to the launcher
+ killSockets();
+ // TODO: Where do we go from here? Just exit()?
+ setState(STATE_DONE);
+ break;
+
+ case STATE_DONE:
+ // just sit here.
+ break;
+ }
+
+ } while (idle_again);
+}
+
+void LLPluginProcessChild::sleep(F64 seconds)
+{
+ if(mMessagePipe)
+ {
+ mMessagePipe->pump(seconds);
+ }
+ else
+ {
+ ms_sleep((int)(seconds * 1000.0f));
+ }
+}
+
+void LLPluginProcessChild::pump(void)
+{
+ if(mMessagePipe)
+ {
+ mMessagePipe->pump(0.0f);
+ }
+ else
+ {
+ // Should we warn here?
+ }
+}
+
+
+bool LLPluginProcessChild::isRunning(void)
+{
+ bool result = false;
+
+ if(mState == STATE_RUNNING)
+ result = true;
+
+ return result;
+}
+
+bool LLPluginProcessChild::isDone(void)
+{
+ bool result = false;
+
+ switch(mState)
+ {
+ case STATE_DONE:
+ result = true;
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+void LLPluginProcessChild::sendMessageToPlugin(const LLPluginMessage &message)
+{
+ std::string buffer = message.generate();
+
+ LL_DEBUGS("Plugin") << "Sending to plugin: " << buffer << LL_ENDL;
+ LLTimer elapsed;
+
+ mInstance->sendMessage(buffer);
+
+ mCPUElapsed += elapsed.getElapsedTimeF64();
+}
+
+void LLPluginProcessChild::sendMessageToParent(const LLPluginMessage &message)
+{
+ std::string buffer = message.generate();
+
+ LL_DEBUGS("Plugin") << "Sending to parent: " << buffer << LL_ENDL;
+
+ writeMessageRaw(buffer);
+}
+
+void LLPluginProcessChild::receiveMessageRaw(const std::string &message)
+{
+ // Incoming message from the TCP Socket
+
+ LL_DEBUGS("Plugin") << "Received from parent: " << message << LL_ENDL;
+
+ bool passMessage = true;
+
+ // FIXME: how should we handle queueing here?
+
+ {
+ // Decode this message
+ LLPluginMessage parsed;
+ parsed.parse(message);
+
+ std::string message_class = parsed.getClass();
+ if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL)
+ {
+ passMessage = false;
+
+ std::string message_name = parsed.getName();
+ if(message_name == "load_plugin")
+ {
+ mPluginFile = parsed.getValue("file");
+ mUserDataPath = parsed.getValue("user_data_path");
+ }
+ else if(message_name == "shm_add")
+ {
+ std::string name = parsed.getValue("name");
+ size_t size = (size_t)parsed.getValueS32("size");
+
+ sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
+ if(iter != mSharedMemoryRegions.end())
+ {
+ // Need to remove the old region first
+ LL_WARNS("Plugin") << "Adding a duplicate shared memory segment!" << LL_ENDL;
+ }
+ else
+ {
+ // This is a new region
+ LLPluginSharedMemory *region = new LLPluginSharedMemory;
+ if(region->attach(name, size))
+ {
+ mSharedMemoryRegions.insert(sharedMemoryRegionsType::value_type(name, region));
+
+ std::stringstream addr;
+ addr << region->getMappedAddress();
+
+ // Send the add notification to the plugin
+ LLPluginMessage message("base", "shm_added");
+ message.setValue("name", name);
+ message.setValueS32("size", (S32)size);
+ message.setValuePointer("address", region->getMappedAddress());
+ sendMessageToPlugin(message);
+
+ // and send the response to the parent
+ message.setMessage(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_add_response");
+ message.setValue("name", name);
+ sendMessageToParent(message);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Couldn't create a shared memory segment!" << LL_ENDL;
+ }
+ }
+
+ }
+ else if(message_name == "shm_remove")
+ {
+ std::string name = parsed.getValue("name");
+ sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
+ if(iter != mSharedMemoryRegions.end())
+ {
+ // forward the remove request to the plugin -- its response will trigger us to detach the segment.
+ LLPluginMessage message("base", "shm_remove");
+ message.setValue("name", name);
+ sendMessageToPlugin(message);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "shm_remove for unknown memory segment!" << LL_ENDL;
+ }
+ }
+ else if(message_name == "sleep_time")
+ {
+ mSleepTime = parsed.getValueReal("time");
+ }
+ else if(message_name == "crash")
+ {
+ // Crash the plugin
+ LL_ERRS("Plugin") << "Plugin crash requested." << LL_ENDL;
+ }
+ else if(message_name == "hang")
+ {
+ // Hang the plugin
+ LL_WARNS("Plugin") << "Plugin hang requested." << LL_ENDL;
+ while(1)
+ {
+ // wheeeeeeeee......
+ }
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unknown internal message from parent: " << message_name << LL_ENDL;
+ }
+ }
+ }
+
+ if(passMessage && mInstance != NULL)
+ {
+ LLTimer elapsed;
+
+ mInstance->sendMessage(message);
+
+ mCPUElapsed += elapsed.getElapsedTimeF64();
+ }
+}
+
+/* virtual */
+void LLPluginProcessChild::receivePluginMessage(const std::string &message)
+{
+ LL_DEBUGS("Plugin") << "Received from plugin: " << message << LL_ENDL;
+
+ // Incoming message from the plugin instance
+ bool passMessage = true;
+
+ // FIXME: how should we handle queueing here?
+
+ // Intercept certain base messages (responses to ones sent by this class)
+ {
+ // Decode this message
+ LLPluginMessage parsed;
+ parsed.parse(message);
+ std::string message_class = parsed.getClass();
+ if(message_class == "base")
+ {
+ std::string message_name = parsed.getName();
+ if(message_name == "init_response")
+ {
+ // The plugin has finished initializing.
+ setState(STATE_RUNNING);
+
+ // Don't pass this message up to the parent
+ passMessage = false;
+
+ LLPluginMessage new_message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin_response");
+ LLSD versions = parsed.getValueLLSD("versions");
+ new_message.setValueLLSD("versions", versions);
+
+ if(parsed.hasValue("plugin_version"))
+ {
+ std::string plugin_version = parsed.getValue("plugin_version");
+ new_message.setValueLLSD("plugin_version", plugin_version);
+ }
+
+ // Let the parent know it's loaded and initialized.
+ sendMessageToParent(new_message);
+ }
+ else if(message_name == "shm_remove_response")
+ {
+ // Don't pass this message up to the parent
+ passMessage = false;
+
+ std::string name = parsed.getValue("name");
+ sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
+ if(iter != mSharedMemoryRegions.end())
+ {
+ // detach the shared memory region
+ iter->second->detach();
+
+ // and remove it from our map
+ mSharedMemoryRegions.erase(iter);
+
+ // Finally, send the response to the parent.
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_remove_response");
+ message.setValue("name", name);
+ sendMessageToParent(message);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "shm_remove_response for unknown memory segment!" << LL_ENDL;
+ }
+ }
+ }
+ }
+
+ if(passMessage)
+ {
+ LL_DEBUGS("Plugin") << "Passing through to parent: " << message << LL_ENDL;
+ writeMessageRaw(message);
+ }
+}
+
+
+void LLPluginProcessChild::setState(EState state)
+{
+ LL_DEBUGS("Plugin") << "setting state to " << state << LL_ENDL;
+ mState = state;
+};
diff --git a/indra/llplugin/llpluginprocesschild.h b/indra/llplugin/llpluginprocesschild.h
new file mode 100644
index 0000000000..1cfd9dcaf9
--- /dev/null
+++ b/indra/llplugin/llpluginprocesschild.h
@@ -0,0 +1,113 @@
+/**
+ * @file llpluginprocesschild.h
+ * @brief LLPluginProcessChild handles the child side of the external-process plugin API.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#ifndef LL_LLPLUGINPROCESSCHILD_H
+#define LL_LLPLUGINPROCESSCHILD_H
+
+#include "llpluginmessage.h"
+#include "llpluginmessagepipe.h"
+#include "llplugininstance.h"
+#include "llhost.h"
+#include "llpluginsharedmemory.h"
+
+class LLPluginInstance;
+
+class LLPluginProcessChild: public LLPluginMessagePipeOwner, public LLPluginInstanceMessageListener
+{
+ LOG_CLASS(LLPluginProcessChild);
+public:
+ LLPluginProcessChild();
+ ~LLPluginProcessChild();
+
+ void init(U32 launcher_port);
+ void idle(void);
+ void sleep(F64 seconds);
+ void pump();
+
+ // returns true if the plugin is in the steady state (processing messages)
+ bool isRunning(void);
+
+ // returns true if the plugin is unloaded or we're in an unrecoverable error state.
+ bool isDone(void);
+
+ void killSockets(void);
+
+ F64 getSleepTime(void) const { return mSleepTime; };
+
+ void sendMessageToPlugin(const LLPluginMessage &message);
+ void sendMessageToParent(const LLPluginMessage &message);
+
+ // Inherited from LLPluginMessagePipeOwner
+ /* virtual */ void receiveMessageRaw(const std::string &message);
+
+ // Inherited from LLPluginInstanceMessageListener
+ /* virtual */ void receivePluginMessage(const std::string &message);
+
+private:
+
+ enum EState
+ {
+ STATE_UNINITIALIZED,
+ STATE_INITIALIZED, // init() has been called
+ STATE_CONNECTED, // connected back to launcher
+ STATE_PLUGIN_LOADING, // plugin library needs to be loaded
+ STATE_PLUGIN_LOADED, // plugin library has been loaded
+ STATE_PLUGIN_INITIALIZING, // plugin is processing init message
+ STATE_RUNNING, // steady state (processing messages)
+ STATE_UNLOADING, // plugin has sent shutdown_response and needs to be unloaded
+ STATE_UNLOADED, // plugin has been unloaded
+ STATE_ERROR, // generic bailout state
+ STATE_DONE // state machine will sit in this state after either error or normal termination.
+ };
+ EState mState;
+ void setState(EState state);
+
+ LLHost mLauncherHost;
+ LLSocket::ptr_t mSocket;
+
+ std::string mPluginFile;
+
+ std::string mUserDataPath;
+
+ LLPluginInstance *mInstance;
+
+ typedef std::map<std::string, LLPluginSharedMemory*> sharedMemoryRegionsType;
+ sharedMemoryRegionsType mSharedMemoryRegions;
+
+ LLTimer mHeartbeat;
+ F64 mSleepTime;
+ F64 mCPUElapsed;
+
+};
+
+#endif // LL_LLPLUGINPROCESSCHILD_H
diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp
new file mode 100644
index 0000000000..49f9783824
--- /dev/null
+++ b/indra/llplugin/llpluginprocessparent.cpp
@@ -0,0 +1,715 @@
+/**
+ * @file llpluginprocessparent.cpp
+ * @brief LLPluginProcessParent handles the parent side of the external-process plugin API.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "linden_common.h"
+
+#include "llpluginprocessparent.h"
+#include "llpluginmessagepipe.h"
+#include "llpluginmessageclasses.h"
+
+#include "llapr.h"
+
+//virtual
+LLPluginProcessParentOwner::~LLPluginProcessParentOwner()
+{
+
+}
+
+LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner)
+{
+ mOwner = owner;
+ mBoundPort = 0;
+ mState = STATE_UNINITIALIZED;
+ mDisableTimeout = false;
+ mDebug = false;
+
+ mPluginLaunchTimeout = 60.0f;
+ mPluginLockupTimeout = 15.0f;
+
+ // Don't start the timer here -- start it when we actually launch the plugin process.
+ mHeartbeat.stop();
+}
+
+LLPluginProcessParent::~LLPluginProcessParent()
+{
+ LL_DEBUGS("Plugin") << "destructor" << LL_ENDL;
+
+ // Destroy any remaining shared memory regions
+ sharedMemoryRegionsType::iterator iter;
+ while((iter = mSharedMemoryRegions.begin()) != mSharedMemoryRegions.end())
+ {
+ // destroy the shared memory region
+ iter->second->destroy();
+
+ // and remove it from our map
+ mSharedMemoryRegions.erase(iter);
+ }
+
+ // orphaning the process means it won't be killed when the LLProcessLauncher is destructed.
+ // This is what we want -- it should exit cleanly once it notices the sockets have been closed.
+ mProcess.orphan();
+ killSockets();
+}
+
+void LLPluginProcessParent::killSockets(void)
+{
+ killMessagePipe();
+ mListenSocket.reset();
+ mSocket.reset();
+}
+
+void LLPluginProcessParent::errorState(void)
+{
+ if(mState < STATE_RUNNING)
+ setState(STATE_LAUNCH_FAILURE);
+ else
+ setState(STATE_ERROR);
+}
+
+void LLPluginProcessParent::init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug, const std::string &user_data_path)
+{
+ mProcess.setExecutable(launcher_filename);
+ mPluginFile = plugin_filename;
+ mCPUUsage = 0.0f;
+ mDebug = debug;
+ mUserDataPath = user_data_path;
+
+ setState(STATE_INITIALIZED);
+}
+
+bool LLPluginProcessParent::accept()
+{
+ bool result = false;
+
+ apr_status_t status = APR_EGENERAL;
+ apr_socket_t *new_socket = NULL;
+
+ status = apr_socket_accept(
+ &new_socket,
+ mListenSocket->getSocket(),
+ gAPRPoolp);
+
+
+ if(status == APR_SUCCESS)
+ {
+// llinfos << "SUCCESS" << llendl;
+ // Success. Create a message pipe on the new socket
+
+ // we MUST create a new pool for the LLSocket, since it will take ownership of it and delete it in its destructor!
+ apr_pool_t* new_pool = NULL;
+ status = apr_pool_create(&new_pool, gAPRPoolp);
+
+ mSocket = LLSocket::create(new_socket, new_pool);
+ new LLPluginMessagePipe(this, mSocket);
+
+ result = true;
+ }
+ else if(APR_STATUS_IS_EAGAIN(status))
+ {
+// llinfos << "EAGAIN" << llendl;
+
+ // No incoming connections. This is not an error.
+ status = APR_SUCCESS;
+ }
+ else
+ {
+// llinfos << "Error:" << llendl;
+ ll_apr_warn_status(status);
+
+ // Some other error.
+ errorState();
+ }
+
+ return result;
+}
+
+void LLPluginProcessParent::idle(void)
+{
+ bool idle_again;
+
+ do
+ {
+ // Give time to network processing
+ if(mMessagePipe)
+ {
+ if(!mMessagePipe->pump())
+ {
+// LL_WARNS("Plugin") << "Message pipe hit an error state" << LL_ENDL;
+ errorState();
+ }
+ }
+
+ if((mSocketError != APR_SUCCESS) && (mState <= STATE_RUNNING))
+ {
+ // The socket is in an error state -- the plugin is gone.
+ LL_WARNS("Plugin") << "Socket hit an error state (" << mSocketError << ")" << LL_ENDL;
+ errorState();
+ }
+
+ // If a state needs to go directly to another state (as a performance enhancement), it can set idle_again to true after calling setState().
+ // USE THIS CAREFULLY, since it can starve other code. Specifically make sure there's no way to get into a closed cycle and never return.
+ // When in doubt, don't do it.
+ idle_again = false;
+ switch(mState)
+ {
+ case STATE_UNINITIALIZED:
+ break;
+
+ case STATE_INITIALIZED:
+ {
+
+ apr_status_t status = APR_SUCCESS;
+ apr_sockaddr_t* addr = NULL;
+ mListenSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);
+ mBoundPort = 0;
+
+ // This code is based on parts of LLSocket::create() in lliosocket.cpp.
+
+ status = apr_sockaddr_info_get(
+ &addr,
+ "127.0.0.1",
+ APR_INET,
+ 0, // port 0 = ephemeral ("find me a port")
+ 0,
+ gAPRPoolp);
+
+ if(ll_apr_warn_status(status))
+ {
+ killSockets();
+ errorState();
+ break;
+ }
+
+ // This allows us to reuse the address on quick down/up. This is unlikely to create problems.
+ ll_apr_warn_status(apr_socket_opt_set(mListenSocket->getSocket(), APR_SO_REUSEADDR, 1));
+
+ status = apr_socket_bind(mListenSocket->getSocket(), addr);
+ if(ll_apr_warn_status(status))
+ {
+ killSockets();
+ errorState();
+ break;
+ }
+
+ // Get the actual port the socket was bound to
+ {
+ apr_sockaddr_t* bound_addr = NULL;
+ if(ll_apr_warn_status(apr_socket_addr_get(&bound_addr, APR_LOCAL, mListenSocket->getSocket())))
+ {
+ killSockets();
+ errorState();
+ break;
+ }
+ mBoundPort = bound_addr->port;
+
+ if(mBoundPort == 0)
+ {
+ LL_WARNS("Plugin") << "Bound port number unknown, bailing out." << LL_ENDL;
+
+ killSockets();
+ errorState();
+ break;
+ }
+ }
+
+ LL_DEBUGS("Plugin") << "Bound tcp socket to port: " << addr->port << LL_ENDL;
+
+ // Make the listen socket non-blocking
+ status = apr_socket_opt_set(mListenSocket->getSocket(), APR_SO_NONBLOCK, 1);
+ if(ll_apr_warn_status(status))
+ {
+ killSockets();
+ errorState();
+ break;
+ }
+
+ apr_socket_timeout_set(mListenSocket->getSocket(), 0);
+ if(ll_apr_warn_status(status))
+ {
+ killSockets();
+ errorState();
+ break;
+ }
+
+ // If it's a stream based socket, we need to tell the OS
+ // to keep a queue of incoming connections for ACCEPT.
+ status = apr_socket_listen(
+ mListenSocket->getSocket(),
+ 10); // FIXME: Magic number for queue size
+
+ if(ll_apr_warn_status(status))
+ {
+ killSockets();
+ errorState();
+ break;
+ }
+
+ // If we got here, we're listening.
+ setState(STATE_LISTENING);
+ }
+ break;
+
+ case STATE_LISTENING:
+ {
+ // Launch the plugin process.
+
+ // Only argument to the launcher is the port number we're listening on
+ std::stringstream stream;
+ stream << mBoundPort;
+ mProcess.addArgument(stream.str());
+ if(mProcess.launch() != 0)
+ {
+ errorState();
+ }
+ else
+ {
+ if(mDebug)
+ {
+ #if LL_DARWIN
+ // If we're set to debug, start up a gdb instance in a new terminal window and have it attach to the plugin process and continue.
+
+ // The command we're constructing would look like this on the command line:
+ // osascript -e 'tell application "Terminal"' -e 'set win to do script "gdb -pid 12345"' -e 'do script "continue" in win' -e 'end tell'
+
+ std::stringstream cmd;
+
+ mDebugger.setExecutable("/usr/bin/osascript");
+ mDebugger.addArgument("-e");
+ mDebugger.addArgument("tell application \"Terminal\"");
+ mDebugger.addArgument("-e");
+ cmd << "set win to do script \"gdb -pid " << mProcess.getProcessID() << "\"";
+ mDebugger.addArgument(cmd.str());
+ mDebugger.addArgument("-e");
+ mDebugger.addArgument("do script \"continue\" in win");
+ mDebugger.addArgument("-e");
+ mDebugger.addArgument("end tell");
+ mDebugger.launch();
+
+ #endif
+ }
+
+ // This will allow us to time out if the process never starts.
+ mHeartbeat.start();
+ mHeartbeat.setTimerExpirySec(mPluginLaunchTimeout);
+ setState(STATE_LAUNCHED);
+ }
+ }
+ break;
+
+ case STATE_LAUNCHED:
+ // waiting for the plugin to connect
+ if(pluginLockedUpOrQuit())
+ {
+ errorState();
+ }
+ else
+ {
+ // Check for the incoming connection.
+ if(accept())
+ {
+ // Stop listening on the server port
+ mListenSocket.reset();
+ setState(STATE_CONNECTED);
+ }
+ }
+ break;
+
+ case STATE_CONNECTED:
+ // waiting for hello message from the plugin
+
+ if(pluginLockedUpOrQuit())
+ {
+ errorState();
+ }
+ break;
+
+ case STATE_HELLO:
+ LL_DEBUGS("Plugin") << "received hello message" << llendl;
+
+ // Send the message to load the plugin
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin");
+ message.setValue("file", mPluginFile);
+ message.setValue("user_data_path", mUserDataPath);
+ sendMessage(message);
+ }
+
+ setState(STATE_LOADING);
+ break;
+
+ case STATE_LOADING:
+ // The load_plugin_response message will kick us from here into STATE_RUNNING
+ if(pluginLockedUpOrQuit())
+ {
+ errorState();
+ }
+ break;
+
+ case STATE_RUNNING:
+ if(pluginLockedUpOrQuit())
+ {
+ errorState();
+ }
+ break;
+
+ case STATE_EXITING:
+ if(!mProcess.isRunning())
+ {
+ setState(STATE_CLEANUP);
+ }
+ else if(pluginLockedUp())
+ {
+ LL_WARNS("Plugin") << "timeout in exiting state, bailing out" << llendl;
+ errorState();
+ }
+ break;
+
+ case STATE_LAUNCH_FAILURE:
+ if(mOwner != NULL)
+ {
+ mOwner->pluginLaunchFailed();
+ }
+ setState(STATE_CLEANUP);
+ break;
+
+ case STATE_ERROR:
+ if(mOwner != NULL)
+ {
+ mOwner->pluginDied();
+ }
+ setState(STATE_CLEANUP);
+ break;
+
+ case STATE_CLEANUP:
+ // Don't do a kill here anymore -- closing the sockets is the new 'kill'.
+ mProcess.orphan();
+ killSockets();
+ setState(STATE_DONE);
+ break;
+
+
+ case STATE_DONE:
+ // just sit here.
+ break;
+
+ }
+
+ } while (idle_again);
+}
+
+bool LLPluginProcessParent::isLoading(void)
+{
+ bool result = false;
+
+ if(mState <= STATE_LOADING)
+ result = true;
+
+ return result;
+}
+
+bool LLPluginProcessParent::isRunning(void)
+{
+ bool result = false;
+
+ if(mState == STATE_RUNNING)
+ result = true;
+
+ return result;
+}
+
+bool LLPluginProcessParent::isDone(void)
+{
+ bool result = false;
+
+ if(mState == STATE_DONE)
+ result = true;
+
+ return result;
+}
+
+void LLPluginProcessParent::setSleepTime(F64 sleep_time, bool force_send)
+{
+ if(force_send || (sleep_time != mSleepTime))
+ {
+ // Cache the time locally
+ mSleepTime = sleep_time;
+
+ if(canSendMessage())
+ {
+ // and send to the plugin.
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "sleep_time");
+ message.setValueReal("time", mSleepTime);
+ sendMessage(message);
+ }
+ else
+ {
+ // Too early to send -- the load_plugin_response message will trigger us to send mSleepTime later.
+ }
+ }
+}
+
+void LLPluginProcessParent::sendMessage(const LLPluginMessage &message)
+{
+
+ std::string buffer = message.generate();
+ LL_DEBUGS("Plugin") << "Sending: " << buffer << LL_ENDL;
+ writeMessageRaw(buffer);
+}
+
+
+void LLPluginProcessParent::receiveMessageRaw(const std::string &message)
+{
+ LL_DEBUGS("Plugin") << "Received: " << message << LL_ENDL;
+
+ // FIXME: should this go into a queue instead?
+
+ LLPluginMessage parsed;
+ if(parsed.parse(message) != -1)
+ {
+ receiveMessage(parsed);
+ }
+}
+
+void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
+{
+ std::string message_class = message.getClass();
+ if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL)
+ {
+ // internal messages should be handled here
+ std::string message_name = message.getName();
+ if(message_name == "hello")
+ {
+ if(mState == STATE_CONNECTED)
+ {
+ // Plugin host has launched. Tell it which plugin to load.
+ setState(STATE_HELLO);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "received hello message in wrong state -- bailing out" << LL_ENDL;
+ errorState();
+ }
+
+ }
+ else if(message_name == "load_plugin_response")
+ {
+ if(mState == STATE_LOADING)
+ {
+ // Plugin has been loaded.
+
+ mPluginVersionString = message.getValue("plugin_version");
+ LL_INFOS("Plugin") << "plugin version string: " << mPluginVersionString << LL_ENDL;
+
+ // Check which message classes/versions the plugin supports.
+ // TODO: check against current versions
+ // TODO: kill plugin on major mismatches?
+ mMessageClassVersions = message.getValueLLSD("versions");
+ LLSD::map_iterator iter;
+ for(iter = mMessageClassVersions.beginMap(); iter != mMessageClassVersions.endMap(); iter++)
+ {
+ LL_INFOS("Plugin") << "message class: " << iter->first << " -> version: " << iter->second.asString() << LL_ENDL;
+ }
+
+ // Send initial sleep time
+ setSleepTime(mSleepTime, true);
+
+ setState(STATE_RUNNING);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "received load_plugin_response message in wrong state -- bailing out" << LL_ENDL;
+ errorState();
+ }
+ }
+ else if(message_name == "heartbeat")
+ {
+ // this resets our timer.
+ mHeartbeat.setTimerExpirySec(mPluginLockupTimeout);
+
+ mCPUUsage = message.getValueReal("cpu_usage");
+
+ LL_DEBUGS("Plugin") << "cpu usage reported as " << mCPUUsage << LL_ENDL;
+
+ }
+ else if(message_name == "shm_add_response")
+ {
+ // Nothing to do here.
+ }
+ else if(message_name == "shm_remove_response")
+ {
+ std::string name = message.getValue("name");
+ sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
+
+ if(iter != mSharedMemoryRegions.end())
+ {
+ // destroy the shared memory region
+ iter->second->destroy();
+
+ // and remove it from our map
+ mSharedMemoryRegions.erase(iter);
+ }
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unknown internal message from child: " << message_name << LL_ENDL;
+ }
+ }
+ else
+ {
+ if(mOwner != NULL)
+ {
+ mOwner->receivePluginMessage(message);
+ }
+ }
+}
+
+std::string LLPluginProcessParent::addSharedMemory(size_t size)
+{
+ std::string name;
+
+ LLPluginSharedMemory *region = new LLPluginSharedMemory;
+
+ // This is a new region
+ if(region->create(size))
+ {
+ name = region->getName();
+
+ mSharedMemoryRegions.insert(sharedMemoryRegionsType::value_type(name, region));
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_add");
+ message.setValue("name", name);
+ message.setValueS32("size", (S32)size);
+ sendMessage(message);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Couldn't create a shared memory segment!" << LL_ENDL;
+
+ // Don't leak
+ delete region;
+ }
+
+ return name;
+}
+
+void LLPluginProcessParent::removeSharedMemory(const std::string &name)
+{
+ sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
+
+ if(iter != mSharedMemoryRegions.end())
+ {
+ // This segment exists. Send the message to the child to unmap it. The response will cause the parent to unmap our end.
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_remove");
+ message.setValue("name", name);
+ sendMessage(message);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Request to remove an unknown shared memory segment." << LL_ENDL;
+ }
+}
+size_t LLPluginProcessParent::getSharedMemorySize(const std::string &name)
+{
+ size_t result = 0;
+
+ sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
+ if(iter != mSharedMemoryRegions.end())
+ {
+ result = iter->second->getSize();
+ }
+
+ return result;
+}
+void *LLPluginProcessParent::getSharedMemoryAddress(const std::string &name)
+{
+ void *result = NULL;
+
+ sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
+ if(iter != mSharedMemoryRegions.end())
+ {
+ result = iter->second->getMappedAddress();
+ }
+
+ return result;
+}
+
+std::string LLPluginProcessParent::getMessageClassVersion(const std::string &message_class)
+{
+ std::string result;
+
+ if(mMessageClassVersions.has(message_class))
+ {
+ result = mMessageClassVersions[message_class].asString();
+ }
+
+ return result;
+}
+
+std::string LLPluginProcessParent::getPluginVersion(void)
+{
+ return mPluginVersionString;
+}
+
+void LLPluginProcessParent::setState(EState state)
+{
+ LL_DEBUGS("Plugin") << "setting state to " << state << LL_ENDL;
+ mState = state;
+};
+
+bool LLPluginProcessParent::pluginLockedUpOrQuit()
+{
+ bool result = false;
+
+ if(!mDisableTimeout && !mDebug)
+ {
+ if(!mProcess.isRunning())
+ {
+ LL_WARNS("Plugin") << "child exited" << llendl;
+ result = true;
+ }
+ else if(pluginLockedUp())
+ {
+ LL_WARNS("Plugin") << "timeout" << llendl;
+ result = true;
+ }
+ }
+
+ return result;
+}
+
+bool LLPluginProcessParent::pluginLockedUp()
+{
+ // If the timer is running and has expired, the plugin has locked up.
+ return (mHeartbeat.getStarted() && mHeartbeat.hasExpired());
+}
+
diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h
new file mode 100644
index 0000000000..524cd9923f
--- /dev/null
+++ b/indra/llplugin/llpluginprocessparent.h
@@ -0,0 +1,170 @@
+/**
+ * @file llpluginprocessparent.h
+ * @brief LLPluginProcessParent handles the parent side of the external-process plugin API.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#ifndef LL_LLPLUGINPROCESSPARENT_H
+#define LL_LLPLUGINPROCESSPARENT_H
+
+#include "llapr.h"
+#include "llprocesslauncher.h"
+#include "llpluginmessage.h"
+#include "llpluginmessagepipe.h"
+#include "llpluginsharedmemory.h"
+
+#include "lliosocket.h"
+
+class LLPluginProcessParentOwner
+{
+public:
+ virtual ~LLPluginProcessParentOwner();
+ virtual void receivePluginMessage(const LLPluginMessage &message) = 0;
+ // This will only be called when the plugin has died unexpectedly
+ virtual void pluginLaunchFailed() {};
+ virtual void pluginDied() {};
+};
+
+class LLPluginProcessParent : public LLPluginMessagePipeOwner
+{
+ LOG_CLASS(LLPluginProcessParent);
+public:
+ LLPluginProcessParent(LLPluginProcessParentOwner *owner);
+ ~LLPluginProcessParent();
+
+ void init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug, const std::string &user_data_path);
+ void idle(void);
+
+ // returns true if the plugin is on its way to steady state
+ bool isLoading(void);
+
+ // returns true if the plugin is in the steady state (processing messages)
+ bool isRunning(void);
+
+ // returns true if the process has exited or we've had a fatal error
+ bool isDone(void);
+
+ void killSockets(void);
+
+ // Go to the proper error state
+ void errorState(void);
+
+ void setSleepTime(F64 sleep_time, bool force_send = false);
+ F64 getSleepTime(void) const { return mSleepTime; };
+
+ void sendMessage(const LLPluginMessage &message);
+
+ void receiveMessage(const LLPluginMessage &message);
+
+ // Inherited from LLPluginMessagePipeOwner
+ void receiveMessageRaw(const std::string &message);
+
+ // This adds a memory segment shared with the client, generating a name for the segment. The name generated is guaranteed to be unique on the host.
+ // The caller must call removeSharedMemory first (and wait until getSharedMemorySize returns 0 for the indicated name) before re-adding a segment with the same name.
+ std::string addSharedMemory(size_t size);
+ // Negotiates for the removal of a shared memory segment. It is the caller's responsibility to ensure that nothing touches the memory
+ // after this has been called, since the segment will be unmapped shortly thereafter.
+ void removeSharedMemory(const std::string &name);
+ size_t getSharedMemorySize(const std::string &name);
+ void *getSharedMemoryAddress(const std::string &name);
+
+ // Returns the version string the plugin indicated for the message class, or an empty string if that class wasn't in the list.
+ std::string getMessageClassVersion(const std::string &message_class);
+
+ std::string getPluginVersion(void);
+
+ bool getDisableTimeout() { return mDisableTimeout; };
+ void setDisableTimeout(bool disable) { mDisableTimeout = disable; };
+
+ void setLaunchTimeout(F32 timeout) { mPluginLaunchTimeout = timeout; };
+ void setLockupTimeout(F32 timeout) { mPluginLockupTimeout = timeout; };
+
+ F64 getCPUUsage() { return mCPUUsage; };
+
+private:
+
+ enum EState
+ {
+ STATE_UNINITIALIZED,
+ STATE_INITIALIZED, // init() has been called
+ STATE_LISTENING, // listening for incoming connection
+ STATE_LAUNCHED, // process has been launched
+ STATE_CONNECTED, // process has connected
+ STATE_HELLO, // first message from the plugin process has been received
+ STATE_LOADING, // process has been asked to load the plugin
+ STATE_RUNNING, //
+ STATE_LAUNCH_FAILURE, // Failure before plugin loaded
+ STATE_ERROR, // generic bailout state
+ STATE_CLEANUP, // clean everything up
+ STATE_EXITING, // Tried to kill process, waiting for it to exit
+ STATE_DONE //
+
+ };
+ EState mState;
+ void setState(EState state);
+
+ bool pluginLockedUp();
+ bool pluginLockedUpOrQuit();
+
+ bool accept();
+
+ LLSocket::ptr_t mListenSocket;
+ LLSocket::ptr_t mSocket;
+ U32 mBoundPort;
+
+ LLProcessLauncher mProcess;
+
+ std::string mPluginFile;
+
+ std::string mUserDataPath;
+
+ LLPluginProcessParentOwner *mOwner;
+
+ typedef std::map<std::string, LLPluginSharedMemory*> sharedMemoryRegionsType;
+ sharedMemoryRegionsType mSharedMemoryRegions;
+
+ LLSD mMessageClassVersions;
+ std::string mPluginVersionString;
+
+ LLTimer mHeartbeat;
+ F64 mSleepTime;
+ F64 mCPUUsage;
+
+ bool mDisableTimeout;
+ bool mDebug;
+
+ LLProcessLauncher mDebugger;
+
+ F32 mPluginLaunchTimeout; // Somewhat longer timeout for initial launch.
+ F32 mPluginLockupTimeout; // If we don't receive a heartbeat in this many seconds, we declare the plugin locked up.
+
+};
+
+#endif // LL_LLPLUGINPROCESSPARENT_H
diff --git a/indra/llplugin/llpluginsharedmemory.cpp b/indra/llplugin/llpluginsharedmemory.cpp
new file mode 100644
index 0000000000..9c18b410c7
--- /dev/null
+++ b/indra/llplugin/llpluginsharedmemory.cpp
@@ -0,0 +1,507 @@
+/**
+ * @file llpluginsharedmemory.cpp
+ * LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "linden_common.h"
+
+#include "llpluginsharedmemory.h"
+
+// on Mac and Linux, we use the native shm_open/mmap interface by using
+// #define USE_SHM_OPEN_SHARED_MEMORY 1
+// in the appropriate sections below.
+
+// For Windows, use:
+// #define USE_WIN32_SHARED_MEMORY 1
+
+// If we ever want to fall back to the apr implementation for a platform, use:
+// #define USE_APR_SHARED_MEMORY 1
+
+#if LL_WINDOWS
+// #define USE_APR_SHARED_MEMORY 1
+ #define USE_WIN32_SHARED_MEMORY 1
+#elif LL_DARWIN
+ #define USE_SHM_OPEN_SHARED_MEMORY 1
+#elif LL_LINUX
+ #define USE_SHM_OPEN_SHARED_MEMORY 1
+#endif
+
+
+// FIXME: This path thing is evil and unacceptable.
+#if LL_WINDOWS
+ #define APR_SHARED_MEMORY_PREFIX_STRING "C:\\LLPlugin_"
+ // Apparnently using the "Global\\" prefix here only works from administrative accounts under Vista.
+ // Other options I've seen referenced are "Local\\" and "Session\\".
+ #define WIN32_SHARED_MEMORY_PREFIX_STRING "Local\\LL_"
+#else
+ // mac and linux
+ #define APR_SHARED_MEMORY_PREFIX_STRING "/tmp/LLPlugin_"
+ #define SHM_OPEN_SHARED_MEMORY_PREFIX_STRING "/LL"
+#endif
+
+#if USE_APR_SHARED_MEMORY
+ #include "llapr.h"
+ #include "apr_shm.h"
+#elif USE_SHM_OPEN_SHARED_MEMORY
+ #include <sys/fcntl.h>
+ #include <sys/mman.h>
+ #include <errno.h>
+#elif USE_WIN32_SHARED_MEMORY
+#include <windows.h>
+#endif // USE_APR_SHARED_MEMORY
+
+
+int LLPluginSharedMemory::sSegmentNumber = 0;
+
+std::string LLPluginSharedMemory::createName(void)
+{
+ std::stringstream newname;
+
+#if LL_WINDOWS
+ newname << GetCurrentProcessId();
+#else // LL_WINDOWS
+ newname << getpid();
+#endif // LL_WINDOWS
+
+ newname << "_" << sSegmentNumber++;
+
+ return newname.str();
+}
+
+/**
+ * @brief LLPluginSharedMemoryImpl is the platform-dependent implementation of LLPluginSharedMemory. TODO:DOC is this necessary/sufficient? kinda obvious.
+ *
+ */
+class LLPluginSharedMemoryPlatformImpl
+{
+public:
+ LLPluginSharedMemoryPlatformImpl();
+ ~LLPluginSharedMemoryPlatformImpl();
+
+#if USE_APR_SHARED_MEMORY
+ apr_shm_t* mAprSharedMemory;
+#elif USE_SHM_OPEN_SHARED_MEMORY
+ int mSharedMemoryFD;
+#elif USE_WIN32_SHARED_MEMORY
+ HANDLE mMapFile;
+#endif
+
+};
+
+/**
+ * Constructor. Creates a shared memory segment.
+ */
+LLPluginSharedMemory::LLPluginSharedMemory()
+{
+ mSize = 0;
+ mMappedAddress = NULL;
+ mNeedsDestroy = false;
+
+ mImpl = new LLPluginSharedMemoryPlatformImpl;
+}
+
+/**
+ * Destructor. Uses destroy() and detach() to ensure shared memory segment is cleaned up.
+ */
+LLPluginSharedMemory::~LLPluginSharedMemory()
+{
+ if(mNeedsDestroy)
+ destroy();
+ else
+ detach();
+
+ unlink();
+
+ delete mImpl;
+}
+
+#if USE_APR_SHARED_MEMORY
+// MARK: apr implementation
+
+LLPluginSharedMemoryPlatformImpl::LLPluginSharedMemoryPlatformImpl()
+{
+ mAprSharedMemory = NULL;
+}
+
+LLPluginSharedMemoryPlatformImpl::~LLPluginSharedMemoryPlatformImpl()
+{
+
+}
+
+bool LLPluginSharedMemory::map(void)
+{
+ mMappedAddress = apr_shm_baseaddr_get(mImpl->mAprSharedMemory);
+ if(mMappedAddress == NULL)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool LLPluginSharedMemory::unmap(void)
+{
+ // This is a no-op under apr.
+ return true;
+}
+
+bool LLPluginSharedMemory::close(void)
+{
+ // This is a no-op under apr.
+ return true;
+}
+
+bool LLPluginSharedMemory::unlink(void)
+{
+ // This is a no-op under apr.
+ return true;
+}
+
+
+bool LLPluginSharedMemory::create(size_t size)
+{
+ mName = APR_SHARED_MEMORY_PREFIX_STRING;
+ mName += createName();
+ mSize = size;
+
+ apr_status_t status = apr_shm_create( &(mImpl->mAprSharedMemory), mSize, mName.c_str(), gAPRPoolp );
+
+ if(ll_apr_warn_status(status))
+ {
+ return false;
+ }
+
+ mNeedsDestroy = true;
+
+ return map();
+}
+
+bool LLPluginSharedMemory::destroy(void)
+{
+ if(mImpl->mAprSharedMemory)
+ {
+ apr_status_t status = apr_shm_destroy(mImpl->mAprSharedMemory);
+ if(ll_apr_warn_status(status))
+ {
+ // TODO: Is this a fatal error? I think not...
+ }
+ mImpl->mAprSharedMemory = NULL;
+ }
+
+ return true;
+}
+
+bool LLPluginSharedMemory::attach(const std::string &name, size_t size)
+{
+ mName = name;
+ mSize = size;
+
+ apr_status_t status = apr_shm_attach( &(mImpl->mAprSharedMemory), mName.c_str(), gAPRPoolp );
+
+ if(ll_apr_warn_status(status))
+ {
+ return false;
+ }
+
+ return map();
+}
+
+
+bool LLPluginSharedMemory::detach(void)
+{
+ if(mImpl->mAprSharedMemory)
+ {
+ apr_status_t status = apr_shm_detach(mImpl->mAprSharedMemory);
+ if(ll_apr_warn_status(status))
+ {
+ // TODO: Is this a fatal error? I think not...
+ }
+ mImpl->mAprSharedMemory = NULL;
+ }
+
+ return true;
+}
+
+
+#elif USE_SHM_OPEN_SHARED_MEMORY
+// MARK: shm_open/mmap implementation
+
+LLPluginSharedMemoryPlatformImpl::LLPluginSharedMemoryPlatformImpl()
+{
+ mSharedMemoryFD = -1;
+}
+
+LLPluginSharedMemoryPlatformImpl::~LLPluginSharedMemoryPlatformImpl()
+{
+}
+
+bool LLPluginSharedMemory::map(void)
+{
+ mMappedAddress = ::mmap(NULL, mSize, PROT_READ | PROT_WRITE, MAP_SHARED, mImpl->mSharedMemoryFD, 0);
+ if(mMappedAddress == NULL)
+ {
+ return false;
+ }
+
+ LL_DEBUGS("Plugin") << "memory mapped at " << mMappedAddress << LL_ENDL;
+
+ return true;
+}
+
+bool LLPluginSharedMemory::unmap(void)
+{
+ if(mMappedAddress != NULL)
+ {
+ LL_DEBUGS("Plugin") << "calling munmap(" << mMappedAddress << ", " << mSize << ")" << LL_ENDL;
+ if(::munmap(mMappedAddress, mSize) == -1)
+ {
+ // TODO: Is this a fatal error? I think not...
+ }
+
+ mMappedAddress = NULL;
+ }
+
+ return true;
+}
+
+bool LLPluginSharedMemory::close(void)
+{
+ if(mImpl->mSharedMemoryFD != -1)
+ {
+ LL_DEBUGS("Plugin") << "calling close(" << mImpl->mSharedMemoryFD << ")" << LL_ENDL;
+ if(::close(mImpl->mSharedMemoryFD) == -1)
+ {
+ // TODO: Is this a fatal error? I think not...
+ }
+
+ mImpl->mSharedMemoryFD = -1;
+ }
+ return true;
+}
+
+bool LLPluginSharedMemory::unlink(void)
+{
+ if(!mName.empty())
+ {
+ if(::shm_unlink(mName.c_str()) == -1)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+bool LLPluginSharedMemory::create(size_t size)
+{
+ mName = SHM_OPEN_SHARED_MEMORY_PREFIX_STRING;
+ mName += createName();
+ mSize = size;
+
+ // Preemptive unlink, just in case something didn't get cleaned up.
+ unlink();
+
+ mImpl->mSharedMemoryFD = ::shm_open(mName.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
+ if(mImpl->mSharedMemoryFD == -1)
+ {
+ return false;
+ }
+
+ mNeedsDestroy = true;
+
+ if(::ftruncate(mImpl->mSharedMemoryFD, mSize) == -1)
+ {
+ return false;
+ }
+
+
+ return map();
+}
+
+bool LLPluginSharedMemory::destroy(void)
+{
+ unmap();
+ close();
+
+ return true;
+}
+
+
+bool LLPluginSharedMemory::attach(const std::string &name, size_t size)
+{
+ mName = name;
+ mSize = size;
+
+ mImpl->mSharedMemoryFD = ::shm_open(mName.c_str(), O_RDWR, S_IRUSR | S_IWUSR);
+ if(mImpl->mSharedMemoryFD == -1)
+ {
+ return false;
+ }
+
+ // unlink here so the segment will be cleaned up automatically after the last close.
+ unlink();
+
+ return map();
+}
+
+bool LLPluginSharedMemory::detach(void)
+{
+ unmap();
+ close();
+ return true;
+}
+
+#elif USE_WIN32_SHARED_MEMORY
+// MARK: Win32 CreateFileMapping-based implementation
+
+// Reference: http://msdn.microsoft.com/en-us/library/aa366551(VS.85).aspx
+
+LLPluginSharedMemoryPlatformImpl::LLPluginSharedMemoryPlatformImpl()
+{
+ mMapFile = NULL;
+}
+
+LLPluginSharedMemoryPlatformImpl::~LLPluginSharedMemoryPlatformImpl()
+{
+
+}
+
+bool LLPluginSharedMemory::map(void)
+{
+ mMappedAddress = MapViewOfFile(
+ mImpl->mMapFile, // handle to map object
+ FILE_MAP_ALL_ACCESS, // read/write permission
+ 0,
+ 0,
+ mSize);
+
+ if(mMappedAddress == NULL)
+ {
+ LL_WARNS("Plugin") << "MapViewOfFile failed: " << GetLastError() << LL_ENDL;
+ return false;
+ }
+
+ LL_DEBUGS("Plugin") << "memory mapped at " << mMappedAddress << LL_ENDL;
+
+ return true;
+}
+
+bool LLPluginSharedMemory::unmap(void)
+{
+ if(mMappedAddress != NULL)
+ {
+ UnmapViewOfFile(mMappedAddress);
+ mMappedAddress = NULL;
+ }
+
+ return true;
+}
+
+bool LLPluginSharedMemory::close(void)
+{
+ if(mImpl->mMapFile != NULL)
+ {
+ CloseHandle(mImpl->mMapFile);
+ mImpl->mMapFile = NULL;
+ }
+
+ return true;
+}
+
+bool LLPluginSharedMemory::unlink(void)
+{
+ // This is a no-op on Windows.
+ return true;
+}
+
+
+bool LLPluginSharedMemory::create(size_t size)
+{
+ mName = WIN32_SHARED_MEMORY_PREFIX_STRING;
+ mName += createName();
+ mSize = size;
+
+ mImpl->mMapFile = CreateFileMappingA(
+ INVALID_HANDLE_VALUE, // use paging file
+ NULL, // default security
+ PAGE_READWRITE, // read/write access
+ 0, // max. object size
+ mSize, // buffer size
+ mName.c_str()); // name of mapping object
+
+ if(mImpl->mMapFile == NULL)
+ {
+ LL_WARNS("Plugin") << "CreateFileMapping failed: " << GetLastError() << LL_ENDL;
+ return false;
+ }
+
+ mNeedsDestroy = true;
+
+ return map();
+}
+
+bool LLPluginSharedMemory::destroy(void)
+{
+ unmap();
+ close();
+ return true;
+}
+
+bool LLPluginSharedMemory::attach(const std::string &name, size_t size)
+{
+ mName = name;
+ mSize = size;
+
+ mImpl->mMapFile = OpenFileMappingA(
+ FILE_MAP_ALL_ACCESS, // read/write access
+ FALSE, // do not inherit the name
+ mName.c_str()); // name of mapping object
+
+ if(mImpl->mMapFile == NULL)
+ {
+ LL_WARNS("Plugin") << "OpenFileMapping failed: " << GetLastError() << LL_ENDL;
+ return false;
+ }
+
+ return map();
+}
+
+bool LLPluginSharedMemory::detach(void)
+{
+ unmap();
+ close();
+ return true;
+}
+
+
+
+#endif
diff --git a/indra/llplugin/llpluginsharedmemory.h b/indra/llplugin/llpluginsharedmemory.h
new file mode 100644
index 0000000000..00c54ef08c
--- /dev/null
+++ b/indra/llplugin/llpluginsharedmemory.h
@@ -0,0 +1,130 @@
+/**
+ * @file llpluginsharedmemory.h
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#ifndef LL_LLPLUGINSHAREDMEMORY_H
+#define LL_LLPLUGINSHAREDMEMORY_H
+
+class LLPluginSharedMemoryPlatformImpl;
+
+/**
+ * @brief LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API.
+ *
+ */
+class LLPluginSharedMemory
+{
+ LOG_CLASS(LLPluginSharedMemory);
+public:
+ LLPluginSharedMemory();
+ ~LLPluginSharedMemory();
+
+ // Parent will use create/destroy, child will use attach/detach.
+ // Message transactions will ensure child attaches after parent creates and detaches before parent destroys.
+
+ /**
+ * Creates a shared memory segment, with a name which is guaranteed to be unique on the host at the current time. Used by parent.
+ * Message transactions will (? TODO:DOC - should? must?) ensure child attaches after parent creates and detaches before parent destroys.
+ *
+ * @param[in] size Shared memory size in TODO:DOC units = bytes?.
+ *
+ * @return False for failure, true for success.
+ */
+ bool create(size_t size);
+ /**
+ * Destroys a shared memory segment. Used by parent.
+ * Message transactions will (? TODO:DOC - should? must?) ensure child attaches after parent creates and detaches before parent destroys.
+ *
+ * @return True. TODO:DOC - always returns true. Is this the intended behavior?
+ */
+ bool destroy(void);
+
+ /**
+ * Creates and attaches a name to a shared memory segment. TODO:DOC what's the difference between attach() and create()?
+ *
+ * @param[in] name Name to attach to memory segment
+ * @param[in] size Size of memory segment TODO:DOC in bytes?
+ *
+ * @return False on failure, true otherwise.
+ */
+ bool attach(const std::string &name, size_t size);
+ /**
+ * Detaches shared memory segment.
+ *
+ * @return False on failure, true otherwise.
+ */
+ bool detach(void);
+
+ /**
+ * Checks if shared memory is mapped to a non-null address.
+ *
+ * @return True if memory address is non-null, false otherwise.
+ */
+ bool isMapped(void) const { return (mMappedAddress != NULL); };
+ /**
+ * Get pointer to shared memory.
+ *
+ * @return Pointer to shared memory.
+ */
+ void *getMappedAddress(void) const { return mMappedAddress; };
+ /**
+ * Get size of shared memory.
+ *
+ * @return Size of shared memory in bytes. TODO:DOC are bytes the correct unit?
+ */
+ size_t getSize(void) const { return mSize; };
+ /**
+ * Get name of shared memory.
+ *
+ * @return Name of shared memory.
+ */
+ std::string getName() const { return mName; };
+
+private:
+ bool map(void);
+ bool unmap(void);
+ bool close(void);
+ bool unlink(void);
+
+ std::string mName;
+ size_t mSize;
+ void *mMappedAddress;
+ bool mNeedsDestroy;
+
+ LLPluginSharedMemoryPlatformImpl *mImpl;
+
+ static int sSegmentNumber;
+ static std::string createName();
+
+};
+
+
+
+#endif // LL_LLPLUGINSHAREDMEMORY_H
diff --git a/indra/llplugin/slplugin/CMakeLists.txt b/indra/llplugin/slplugin/CMakeLists.txt
new file mode 100644
index 0000000000..4a7d670c23
--- /dev/null
+++ b/indra/llplugin/slplugin/CMakeLists.txt
@@ -0,0 +1,55 @@
+project(SLPlugin)
+
+include(00-Common)
+include(LLCommon)
+include(LLPlugin)
+include(Linking)
+include(PluginAPI)
+include(LLMessage)
+
+include_directories(
+ ${LLPLUGIN_INCLUDE_DIRS}
+ ${LLMESSAGE_INCLUDE_DIRS}
+ ${LLCOMMON_INCLUDE_DIRS}
+)
+
+if (DARWIN)
+ include(CMakeFindFrameworks)
+ find_library(CARBON_LIBRARY Carbon)
+endif (DARWIN)
+
+
+### SLPlugin
+
+set(SLPlugin_SOURCE_FILES
+ slplugin.cpp
+ )
+
+add_executable(SLPlugin
+ WIN32
+ ${SLPlugin_SOURCE_FILES}
+)
+
+target_link_libraries(SLPlugin
+ ${LLPLUGIN_LIBRARIES}
+ ${LLMESSAGE_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+ ${PLUGIN_API_WINDOWS_LIBRARIES}
+)
+
+add_dependencies(SLPlugin
+ ${LLPLUGIN_LIBRARIES}
+ ${LLMESSAGE_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+)
+
+if (DARWIN)
+ # Mac version needs to link against carbon, and also needs an embedded plist (to set LSBackgroundOnly)
+ target_link_libraries(SLPlugin ${CARBON_LIBRARY})
+ set_target_properties(
+ SLPlugin
+ PROPERTIES
+ LINK_FLAGS "-Wl,-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_SOURCE_DIR}/slplugin_info.plist"
+ )
+endif (DARWIN)
+
diff --git a/indra/llplugin/slplugin/slplugin.cpp b/indra/llplugin/slplugin/slplugin.cpp
new file mode 100644
index 0000000000..23dc532ba5
--- /dev/null
+++ b/indra/llplugin/slplugin/slplugin.cpp
@@ -0,0 +1,291 @@
+/**
+ * @file slplugin.cpp
+ * @brief Loader shell for plugins, intended to be launched by the plugin host application, which directly loads a plugin dynamic library.
+ *
+ * @cond
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ *
+ * @endcond
+ */
+
+
+#include "linden_common.h"
+
+#include "llpluginprocesschild.h"
+#include "llpluginmessage.h"
+#include "llerrorcontrol.h"
+#include "llapr.h"
+#include "llstring.h"
+
+#if LL_DARWIN
+ #include <Carbon/Carbon.h>
+#endif
+
+#if LL_DARWIN || LL_LINUX
+ #include <signal.h>
+#endif
+
+/*
+ On Mac OS, since we call WaitNextEvent, this process will show up in the dock unless we set the LSBackgroundOnly flag in the Info.plist.
+
+ Normally non-bundled binaries don't have an info.plist file, but it's possible to embed one in the binary by adding this to the linker flags:
+
+ -sectcreate __TEXT __info_plist /path/to/slplugin_info.plist
+
+ which means adding this to the gcc flags:
+
+ -Wl,-sectcreate,__TEXT,__info_plist,/path/to/slplugin_info.plist
+
+*/
+
+#if LL_DARWIN || LL_LINUX
+// Signal handlers to make crashes not show an OS dialog...
+static void crash_handler(int sig)
+{
+ // Just exit cleanly.
+ // TODO: add our own crash reporting
+ _exit(1);
+}
+#endif
+
+#if LL_WINDOWS
+#include <windows.h>
+////////////////////////////////////////////////////////////////////////////////
+// Our exception handler - will probably just exit and the host application
+// will miss the heartbeat and log the error in the usual fashion.
+LONG WINAPI myWin32ExceptionHandler( struct _EXCEPTION_POINTERS* exception_infop )
+{
+ //std::cerr << "This plugin (" << __FILE__ << ") - ";
+ //std::cerr << "intercepted an unhandled exception and will exit immediately." << std::endl;
+
+ // TODO: replace exception handler before we exit?
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+// Taken from : http://blog.kalmbachnet.de/?postid=75
+// The MSVC 2005 CRT forces the call of the default-debugger (normally Dr.Watson)
+// even with the other exception handling code. This (terrifying) piece of code
+// patches things so that doesn't happen.
+LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter(
+ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter )
+{
+ return NULL;
+}
+
+BOOL PreventSetUnhandledExceptionFilter()
+{
+// WARNING: This won't work on 64-bit Windows systems so we turn it off it.
+// It should work for any flavor of 32-bit Windows we care about.
+// If it's off, sometimes you will see an OS message when a plugin crashes
+#ifndef _WIN64
+ HMODULE hKernel32 = LoadLibraryA( "kernel32.dll" );
+ if ( NULL == hKernel32 )
+ return FALSE;
+
+ void *pOrgEntry = GetProcAddress( hKernel32, "SetUnhandledExceptionFilter" );
+ if( NULL == pOrgEntry )
+ return FALSE;
+
+ unsigned char newJump[ 100 ];
+ DWORD dwOrgEntryAddr = (DWORD)pOrgEntry;
+ dwOrgEntryAddr += 5; // add 5 for 5 op-codes for jmp far
+ void *pNewFunc = &MyDummySetUnhandledExceptionFilter;
+ DWORD dwNewEntryAddr = (DWORD) pNewFunc;
+ DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr;
+
+ newJump[ 0 ] = 0xE9; // JMP absolute
+ memcpy( &newJump[ 1 ], &dwRelativeAddr, sizeof( pNewFunc ) );
+ SIZE_T bytesWritten;
+ BOOL bRet = WriteProcessMemory( GetCurrentProcess(), pOrgEntry, newJump, sizeof( pNewFunc ) + 1, &bytesWritten );
+ return bRet;
+#else
+ return FALSE;
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Hook our exception handler and replace the system one
+void initExceptionHandler()
+{
+ LPTOP_LEVEL_EXCEPTION_FILTER prev_filter;
+
+ // save old exception handler in case we need to restore it at the end
+ prev_filter = SetUnhandledExceptionFilter( myWin32ExceptionHandler );
+ PreventSetUnhandledExceptionFilter();
+}
+
+bool checkExceptionHandler()
+{
+ bool ok = true;
+ LPTOP_LEVEL_EXCEPTION_FILTER prev_filter;
+ prev_filter = SetUnhandledExceptionFilter(myWin32ExceptionHandler);
+
+ PreventSetUnhandledExceptionFilter();
+
+ if (prev_filter != myWin32ExceptionHandler)
+ {
+ LL_WARNS("AppInit") << "Our exception handler (" << (void *)myWin32ExceptionHandler << ") replaced with " << prev_filter << "!" << LL_ENDL;
+ ok = false;
+ }
+
+ if (prev_filter == NULL)
+ {
+ ok = FALSE;
+ if (myWin32ExceptionHandler == NULL)
+ {
+ LL_WARNS("AppInit") << "Exception handler uninitialized." << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("AppInit") << "Our exception handler (" << (void *)myWin32ExceptionHandler << ") replaced with NULL!" << LL_ENDL;
+ }
+ }
+
+ return ok;
+}
+#endif
+
+// If this application on Windows platform is a console application, a console is always
+// created which is bad. Making it a Windows "application" via CMake settings but not
+// adding any code to explicitly create windows does the right thing.
+#if LL_WINDOWS
+int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
+#else
+int main(int argc, char **argv)
+#endif
+{
+ ll_init_apr();
+
+ // Set up llerror logging
+ {
+ LLError::initForApplication(".");
+ LLError::setDefaultLevel(LLError::LEVEL_INFO);
+// LLError::setTagLevel("Plugin", LLError::LEVEL_DEBUG);
+// LLError::logToFile("slplugin.log");
+ }
+
+#if LL_WINDOWS
+ if( strlen( lpCmdLine ) == 0 )
+ {
+ LL_ERRS("slplugin") << "usage: " << "SLPlugin" << " launcher_port" << LL_ENDL;
+ };
+
+ U32 port = 0;
+ if(!LLStringUtil::convertToU32(lpCmdLine, port))
+ {
+ LL_ERRS("slplugin") << "port number must be numeric" << LL_ENDL;
+ };
+
+ // Insert our exception handler into the system so this plugin doesn't
+ // display a crash message if something bad happens. The host app will
+ // see the missing heartbeat and log appropriately.
+ initExceptionHandler();
+#elif LL_DARWIN || LL_LINUX
+ if(argc < 2)
+ {
+ LL_ERRS("slplugin") << "usage: " << argv[0] << " launcher_port" << LL_ENDL;
+ }
+
+ U32 port = 0;
+ if(!LLStringUtil::convertToU32(argv[1], port))
+ {
+ LL_ERRS("slplugin") << "port number must be numeric" << LL_ENDL;
+ }
+
+ // Catch signals that most kinds of crashes will generate, and exit cleanly so the system crash dialog isn't shown.
+ signal(SIGILL, &crash_handler); // illegal instruction
+# if LL_DARWIN
+ signal(SIGEMT, &crash_handler); // emulate instruction executed
+# endif // LL_DARWIN
+ signal(SIGFPE, &crash_handler); // floating-point exception
+ signal(SIGBUS, &crash_handler); // bus error
+ signal(SIGSEGV, &crash_handler); // segmentation violation
+ signal(SIGSYS, &crash_handler); // non-existent system call invoked
+#endif
+
+ LLPluginProcessChild *plugin = new LLPluginProcessChild();
+
+ plugin->init(port);
+
+ LLTimer timer;
+ timer.start();
+
+#if LL_WINDOWS
+ checkExceptionHandler();
+#endif
+
+ while(!plugin->isDone())
+ {
+ timer.reset();
+ plugin->idle();
+#if LL_DARWIN
+ {
+ // Some plugins (webkit at least) will want an event loop. This qualifies.
+ EventRecord evt;
+ WaitNextEvent(0, &evt, 0, NULL);
+ }
+#endif
+ F64 elapsed = timer.getElapsedTimeF64();
+ F64 remaining = plugin->getSleepTime() - elapsed;
+
+ if(remaining <= 0.0f)
+ {
+ // We've already used our full allotment.
+// LL_INFOS("slplugin") << "elapsed = " << elapsed * 1000.0f << " ms, remaining = " << remaining * 1000.0f << " ms, not sleeping" << LL_ENDL;
+
+ // Still need to service the network...
+ plugin->pump();
+ }
+ else
+ {
+
+// LL_INFOS("slplugin") << "elapsed = " << elapsed * 1000.0f << " ms, remaining = " << remaining * 1000.0f << " ms, sleeping for " << remaining * 1000.0f << " ms" << LL_ENDL;
+// timer.reset();
+
+ // This also services the network as needed.
+ plugin->sleep(remaining);
+
+// LL_INFOS("slplugin") << "slept for "<< timer.getElapsedTimeF64() * 1000.0f << " ms" << LL_ENDL;
+ }
+
+#if LL_WINDOWS
+ // More agressive checking of interfering exception handlers.
+ // Doesn't appear to be required so far - even for plugins
+ // that do crash with a single call to the intercept
+ // exception handler such as QuickTime.
+ //checkExceptionHandler();
+#endif
+ }
+
+ delete plugin;
+
+ ll_cleanup_apr();
+
+ return 0;
+}
+
diff --git a/indra/llplugin/slplugin/slplugin_info.plist b/indra/llplugin/slplugin/slplugin_info.plist
new file mode 100644
index 0000000000..b1daf87424
--- /dev/null
+++ b/indra/llplugin/slplugin/slplugin_info.plist
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>LSBackgroundOnly</key>
+ <true/>
+</dict>
+</plist>
diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt
index 478dd398ff..68a3d54597 100644
--- a/indra/llprimitive/CMakeLists.txt
+++ b/indra/llprimitive/CMakeLists.txt
@@ -17,6 +17,7 @@ include_directories(
set(llprimitive_SOURCE_FILES
llmaterialtable.cpp
+ llmediaentry.cpp
llprimitive.cpp
llprimtexturelist.cpp
lltextureanim.cpp
@@ -24,6 +25,7 @@ set(llprimitive_SOURCE_FILES
lltreeparams.cpp
llvolumemessage.cpp
llvolumexml.cpp
+ material_codes.cpp
)
set(llprimitive_HEADER_FILES
@@ -31,6 +33,7 @@ set(llprimitive_HEADER_FILES
legacy_object_types.h
llmaterialtable.h
+ llmediaentry.h
llprimitive.h
llprimtexturelist.h
lltextureanim.h
@@ -49,3 +52,10 @@ set_source_files_properties(${llprimitive_HEADER_FILES}
list(APPEND llprimitive_SOURCE_FILES ${llprimitive_HEADER_FILES})
add_library (llprimitive ${llprimitive_SOURCE_FILES})
+
+#add unit tests
+INCLUDE(LLAddBuildTest)
+SET(llprimitive_TEST_SOURCE_FILES
+ llmediaentry.cpp
+ )
+LL_ADD_PROJECT_UNIT_TESTS(llprimitive "${llprimitive_TEST_SOURCE_FILES}")
diff --git a/indra/llprimitive/llmaterialtable.cpp b/indra/llprimitive/llmaterialtable.cpp
index 4c22203eb9..18787c47c5 100644
--- a/indra/llprimitive/llmaterialtable.cpp
+++ b/indra/llprimitive/llmaterialtable.cpp
@@ -124,6 +124,17 @@ LLMaterialTable::~LLMaterialTable()
mMaterialInfoList.clear();
}
+void LLMaterialTable::initTableTransNames(std::map<std::string, std::string> namemap)
+{
+ for (info_list_t::iterator iter = mMaterialInfoList.begin();
+ iter != mMaterialInfoList.end(); ++iter)
+ {
+ LLMaterialInfo *infop = *iter;
+ std::string name = infop->mName;
+ infop->mName = namemap[name];
+ }
+}
+
void LLMaterialTable::initBasicTable()
{
// *TODO: Translate
diff --git a/indra/llprimitive/llmaterialtable.h b/indra/llprimitive/llmaterialtable.h
index ca9017abd0..2c0b046fa7 100644
--- a/indra/llprimitive/llmaterialtable.h
+++ b/indra/llprimitive/llmaterialtable.h
@@ -147,6 +147,8 @@ public:
void initBasicTable();
+ void initTableTransNames(std::map<std::string, std::string> namemap);
+
BOOL add(U8 mcode, const std::string& name, const LLUUID &uuid);
BOOL addCollisionSound(U8 mcode, U8 mcode2, const LLUUID &uuid);
BOOL addSlidingSound(U8 mcode, U8 mcode2, const LLUUID &uuid);
diff --git a/indra/llprimitive/llmediaentry.cpp b/indra/llprimitive/llmediaentry.cpp
new file mode 100644
index 0000000000..2fc1e5e60c
--- /dev/null
+++ b/indra/llprimitive/llmediaentry.cpp
@@ -0,0 +1,602 @@
+/**
+ * @file llmediaentry.cpp
+ * @brief This is a single instance of media data related to the face of a prim
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llmediaentry.h"
+#include "lllslconstants.h"
+
+#include <boost/regex.hpp>
+
+// LLSD key defines
+// DO NOT REORDER OR REMOVE THESE!
+
+// Some LLSD keys. Do not change!
+#define MEDIA_ALT_IMAGE_ENABLE_KEY_STR "alt_image_enable"
+#define MEDIA_CONTROLS_KEY_STR "controls"
+#define MEDIA_CURRENT_URL_KEY_STR "current_url"
+#define MEDIA_HOME_URL_KEY_STR "home_url"
+#define MEDIA_AUTO_LOOP_KEY_STR "auto_loop"
+#define MEDIA_AUTO_PLAY_KEY_STR "auto_play"
+#define MEDIA_AUTO_SCALE_KEY_STR "auto_scale"
+#define MEDIA_AUTO_ZOOM_KEY_STR "auto_zoom"
+#define MEDIA_FIRST_CLICK_INTERACT_KEY_STR "first_click_interact"
+#define MEDIA_WIDTH_PIXELS_KEY_STR "width_pixels"
+#define MEDIA_HEIGHT_PIXELS_KEY_STR "height_pixels"
+
+// "security" fields
+#define MEDIA_WHITELIST_ENABLE_KEY_STR "whitelist_enable"
+#define MEDIA_WHITELIST_KEY_STR "whitelist"
+
+// "permissions" fields
+#define MEDIA_PERMS_INTERACT_KEY_STR "perms_interact"
+#define MEDIA_PERMS_CONTROL_KEY_STR "perms_control"
+
+// "general" fields
+const char* LLMediaEntry::ALT_IMAGE_ENABLE_KEY = MEDIA_ALT_IMAGE_ENABLE_KEY_STR;
+const char* LLMediaEntry::CONTROLS_KEY = MEDIA_CONTROLS_KEY_STR;
+const char* LLMediaEntry::CURRENT_URL_KEY = MEDIA_CURRENT_URL_KEY_STR;
+const char* LLMediaEntry::HOME_URL_KEY = MEDIA_HOME_URL_KEY_STR;
+const char* LLMediaEntry::AUTO_LOOP_KEY = MEDIA_AUTO_LOOP_KEY_STR;
+const char* LLMediaEntry::AUTO_PLAY_KEY = MEDIA_AUTO_PLAY_KEY_STR;
+const char* LLMediaEntry::AUTO_SCALE_KEY = MEDIA_AUTO_SCALE_KEY_STR;
+const char* LLMediaEntry::AUTO_ZOOM_KEY = MEDIA_AUTO_ZOOM_KEY_STR;
+const char* LLMediaEntry::FIRST_CLICK_INTERACT_KEY = MEDIA_FIRST_CLICK_INTERACT_KEY_STR;
+const char* LLMediaEntry::WIDTH_PIXELS_KEY = MEDIA_WIDTH_PIXELS_KEY_STR;
+const char* LLMediaEntry::HEIGHT_PIXELS_KEY = MEDIA_HEIGHT_PIXELS_KEY_STR;
+
+// "security" fields
+const char* LLMediaEntry::WHITELIST_ENABLE_KEY = MEDIA_WHITELIST_ENABLE_KEY_STR;
+const char* LLMediaEntry::WHITELIST_KEY = MEDIA_WHITELIST_KEY_STR;
+
+// "permissions" fields
+const char* LLMediaEntry::PERMS_INTERACT_KEY = MEDIA_PERMS_INTERACT_KEY_STR;
+const char* LLMediaEntry::PERMS_CONTROL_KEY = MEDIA_PERMS_CONTROL_KEY_STR;
+
+#define DEFAULT_URL_PREFIX "http://"
+
+// Constructor(s)
+LLMediaEntry::LLMediaEntry() :
+ mAltImageEnable(false),
+ mControls(STANDARD),
+ mCurrentURL(""),
+ mHomeURL(""),
+ mAutoLoop(false),
+ mAutoPlay(false),
+ mAutoScale(false),
+ mAutoZoom(false),
+ mFirstClickInteract(false),
+ mWidthPixels(0),
+ mHeightPixels(0),
+ mWhiteListEnable(false),
+ // mWhiteList
+ mPermsInteract(PERM_ALL),
+ mPermsControl(PERM_ALL),
+ mMediaIDp(NULL)
+{
+}
+
+LLMediaEntry::LLMediaEntry(const LLMediaEntry &rhs) :
+ mMediaIDp(NULL)
+{
+ // "general" fields
+ mAltImageEnable = rhs.mAltImageEnable;
+ mControls = rhs.mControls;
+ mCurrentURL = rhs.mCurrentURL;
+ mHomeURL = rhs.mHomeURL;
+ mAutoLoop = rhs.mAutoLoop;
+ mAutoPlay = rhs.mAutoPlay;
+ mAutoScale = rhs.mAutoScale;
+ mAutoZoom = rhs.mAutoZoom;
+ mFirstClickInteract = rhs.mFirstClickInteract;
+ mWidthPixels = rhs.mWidthPixels;
+ mHeightPixels = rhs.mHeightPixels;
+
+ // "security" fields
+ mWhiteListEnable = rhs.mWhiteListEnable;
+ mWhiteList = rhs.mWhiteList;
+
+ // "permissions" fields
+ mPermsInteract = rhs.mPermsInteract;
+ mPermsControl = rhs.mPermsControl;
+}
+
+LLMediaEntry::~LLMediaEntry()
+{
+ if (NULL != mMediaIDp)
+ {
+ delete mMediaIDp;
+ }
+}
+
+LLSD LLMediaEntry::asLLSD() const
+{
+ LLSD sd;
+ asLLSD(sd);
+ return sd;
+}
+
+//
+// LLSD functions
+//
+void LLMediaEntry::asLLSD(LLSD& sd) const
+{
+ // "general" fields
+ sd[ALT_IMAGE_ENABLE_KEY] = mAltImageEnable;
+ sd[CONTROLS_KEY] = (LLSD::Integer)mControls;
+ sd[CURRENT_URL_KEY] = mCurrentURL;
+ sd[HOME_URL_KEY] = mHomeURL;
+ sd[AUTO_LOOP_KEY] = mAutoLoop;
+ sd[AUTO_PLAY_KEY] = mAutoPlay;
+ sd[AUTO_SCALE_KEY] = mAutoScale;
+ sd[AUTO_ZOOM_KEY] = mAutoZoom;
+ sd[FIRST_CLICK_INTERACT_KEY] = mFirstClickInteract;
+ sd[WIDTH_PIXELS_KEY] = mWidthPixels;
+ sd[HEIGHT_PIXELS_KEY] = mHeightPixels;
+
+ // "security" fields
+ sd[WHITELIST_ENABLE_KEY] = mWhiteListEnable;
+ sd.erase(WHITELIST_KEY);
+ for (U32 i=0; i<mWhiteList.size(); i++)
+ {
+ sd[WHITELIST_KEY].append(mWhiteList[i]);
+ }
+
+ // "permissions" fields
+ sd[PERMS_INTERACT_KEY] = mPermsInteract;
+ sd[PERMS_CONTROL_KEY] = mPermsControl;
+}
+
+// static
+bool LLMediaEntry::checkLLSD(const LLSD& sd)
+{
+ if (sd.isUndefined()) return true;
+ LLMediaEntry temp;
+ return temp.fromLLSDInternal(sd, true);
+}
+
+void LLMediaEntry::fromLLSD(const LLSD& sd)
+{
+ (void)fromLLSDInternal(sd, true);
+}
+
+void LLMediaEntry::mergeFromLLSD(const LLSD& sd)
+{
+ (void)fromLLSDInternal(sd, false);
+}
+
+// *NOTE: returns true if NO failures to set occurred, false otherwise.
+// However, be aware that if a failure to set does occur, it does
+// not stop setting fields from the LLSD!
+bool LLMediaEntry::fromLLSDInternal(const LLSD& sd, bool overwrite)
+{
+ // *HACK: we sort of cheat here and assume that status is a
+ // bit field. We "or" into status and instead of returning
+ // it, we return whether it finishes off as LSL_STATUS_OK or not.
+ U32 status = LSL_STATUS_OK;
+
+ // "general" fields
+ if ( overwrite || sd.has(ALT_IMAGE_ENABLE_KEY) )
+ {
+ status |= setAltImageEnable( sd[ALT_IMAGE_ENABLE_KEY] );
+ }
+ if ( overwrite || sd.has(CONTROLS_KEY) )
+ {
+ status |= setControls( (MediaControls)(LLSD::Integer)sd[CONTROLS_KEY] );
+ }
+ if ( overwrite || sd.has(CURRENT_URL_KEY) )
+ {
+ // Don't check whitelist
+ status |= setCurrentURLInternal( sd[CURRENT_URL_KEY], false );
+ }
+ if ( overwrite || sd.has(HOME_URL_KEY) )
+ {
+ status |= setHomeURL( sd[HOME_URL_KEY] );
+ }
+ if ( overwrite || sd.has(AUTO_LOOP_KEY) )
+ {
+ status |= setAutoLoop( sd[AUTO_LOOP_KEY] );
+ }
+ if ( overwrite || sd.has(AUTO_PLAY_KEY) )
+ {
+ status |= setAutoPlay( sd[AUTO_PLAY_KEY] );
+ }
+ if ( overwrite || sd.has(AUTO_SCALE_KEY) )
+ {
+ status |= setAutoScale( sd[AUTO_SCALE_KEY] );
+ }
+ if ( overwrite || sd.has(AUTO_ZOOM_KEY) )
+ {
+ status |= setAutoZoom( sd[AUTO_ZOOM_KEY] );
+ }
+ if ( overwrite || sd.has(FIRST_CLICK_INTERACT_KEY) )
+ {
+ status |= setFirstClickInteract( sd[FIRST_CLICK_INTERACT_KEY] );
+ }
+ if ( overwrite || sd.has(WIDTH_PIXELS_KEY) )
+ {
+ status |= setWidthPixels( (LLSD::Integer)sd[WIDTH_PIXELS_KEY] );
+ }
+ if ( overwrite || sd.has(HEIGHT_PIXELS_KEY) )
+ {
+ status |= setHeightPixels( (LLSD::Integer)sd[HEIGHT_PIXELS_KEY] );
+ }
+
+ // "security" fields
+ if ( overwrite || sd.has(WHITELIST_ENABLE_KEY) )
+ {
+ status |= setWhiteListEnable( sd[WHITELIST_ENABLE_KEY] );
+ }
+ if ( overwrite || sd.has(WHITELIST_KEY) )
+ {
+ status |= setWhiteList( sd[WHITELIST_KEY] );
+ }
+
+ // "permissions" fields
+ if ( overwrite || sd.has(PERMS_INTERACT_KEY) )
+ {
+ status |= setPermsInteract( 0xff & (LLSD::Integer)sd[PERMS_INTERACT_KEY] );
+ }
+ if ( overwrite || sd.has(PERMS_CONTROL_KEY) )
+ {
+ status |= setPermsControl( 0xff & (LLSD::Integer)sd[PERMS_CONTROL_KEY] );
+ }
+
+ return LSL_STATUS_OK == status;
+}
+
+LLMediaEntry& LLMediaEntry::operator=(const LLMediaEntry &rhs)
+{
+ if (this != &rhs)
+ {
+ // "general" fields
+ mAltImageEnable = rhs.mAltImageEnable;
+ mControls = rhs.mControls;
+ mCurrentURL = rhs.mCurrentURL;
+ mHomeURL = rhs.mHomeURL;
+ mAutoLoop = rhs.mAutoLoop;
+ mAutoPlay = rhs.mAutoPlay;
+ mAutoScale = rhs.mAutoScale;
+ mAutoZoom = rhs.mAutoZoom;
+ mFirstClickInteract = rhs.mFirstClickInteract;
+ mWidthPixels = rhs.mWidthPixels;
+ mHeightPixels = rhs.mHeightPixels;
+
+ // "security" fields
+ mWhiteListEnable = rhs.mWhiteListEnable;
+ mWhiteList = rhs.mWhiteList;
+
+ // "permissions" fields
+ mPermsInteract = rhs.mPermsInteract;
+ mPermsControl = rhs.mPermsControl;
+ }
+
+ return *this;
+}
+
+bool LLMediaEntry::operator==(const LLMediaEntry &rhs) const
+{
+ return (
+ // "general" fields
+ mAltImageEnable == rhs.mAltImageEnable &&
+ mControls == rhs.mControls &&
+ mCurrentURL == rhs.mCurrentURL &&
+ mHomeURL == rhs.mHomeURL &&
+ mAutoLoop == rhs.mAutoLoop &&
+ mAutoPlay == rhs.mAutoPlay &&
+ mAutoScale == rhs.mAutoScale &&
+ mAutoZoom == rhs.mAutoZoom &&
+ mFirstClickInteract == rhs.mFirstClickInteract &&
+ mWidthPixels == rhs.mWidthPixels &&
+ mHeightPixels == rhs.mHeightPixels &&
+
+ // "security" fields
+ mWhiteListEnable == rhs.mWhiteListEnable &&
+ mWhiteList == rhs.mWhiteList &&
+
+ // "permissions" fields
+ mPermsInteract == rhs.mPermsInteract &&
+ mPermsControl == rhs.mPermsControl
+
+ );
+}
+
+bool LLMediaEntry::operator!=(const LLMediaEntry &rhs) const
+{
+ return (
+ // "general" fields
+ mAltImageEnable != rhs.mAltImageEnable ||
+ mControls != rhs.mControls ||
+ mCurrentURL != rhs.mCurrentURL ||
+ mHomeURL != rhs.mHomeURL ||
+ mAutoLoop != rhs.mAutoLoop ||
+ mAutoPlay != rhs.mAutoPlay ||
+ mAutoScale != rhs.mAutoScale ||
+ mAutoZoom != rhs.mAutoZoom ||
+ mFirstClickInteract != rhs.mFirstClickInteract ||
+ mWidthPixels != rhs.mWidthPixels ||
+ mHeightPixels != rhs.mHeightPixels ||
+
+ // "security" fields
+ mWhiteListEnable != rhs.mWhiteListEnable ||
+ mWhiteList != rhs.mWhiteList ||
+
+ // "permissions" fields
+ mPermsInteract != rhs.mPermsInteract ||
+ mPermsControl != rhs.mPermsControl
+
+ );
+}
+
+U32 LLMediaEntry::setWhiteList( const std::vector<std::string> &whitelist )
+{
+ // *NOTE: This code is VERY similar to the setWhitelist below.
+ // IF YOU CHANGE THIS IMPLEMENTATION, BE SURE TO CHANGE THE OTHER!
+ U32 size = 0;
+ U32 count = 0;
+ // First count to make sure the size constraint is not violated
+ std::vector<std::string>::const_iterator iter = whitelist.begin();
+ std::vector<std::string>::const_iterator end = whitelist.end();
+ for ( ; iter < end; ++iter)
+ {
+ const std::string &entry = (*iter);
+ size += entry.length() + 1; // Include one for \0
+ count ++;
+ if (size > MAX_WHITELIST_SIZE || count > MAX_WHITELIST_COUNT)
+ {
+ return LSL_STATUS_BOUNDS_ERROR;
+ }
+ }
+ // Next clear the vector
+ mWhiteList.clear();
+ // Then re-iterate and copy entries
+ iter = whitelist.begin();
+ for ( ; iter < end; ++iter)
+ {
+ const std::string &entry = (*iter);
+ mWhiteList.push_back(entry);
+ }
+ return LSL_STATUS_OK;
+}
+
+U32 LLMediaEntry::setWhiteList( const LLSD &whitelist )
+{
+ // If whitelist is undef, the whitelist is cleared
+ if (whitelist.isUndefined())
+ {
+ mWhiteList.clear();
+ return LSL_STATUS_OK;
+ }
+
+ // However, if the whitelist is an empty array, erase it.
+ if (whitelist.isArray())
+ {
+ // *NOTE: This code is VERY similar to the setWhitelist above.
+ // IF YOU CHANGE THIS IMPLEMENTATION, BE SURE TO CHANGE THE OTHER!
+ U32 size = 0;
+ U32 count = 0;
+ // First check to make sure the size and count constraints are not violated
+ LLSD::array_const_iterator iter = whitelist.beginArray();
+ LLSD::array_const_iterator end = whitelist.endArray();
+ for ( ; iter < end; ++iter)
+ {
+ const std::string &entry = (*iter).asString();
+ size += entry.length() + 1; // Include one for \0
+ count ++;
+ if (size > MAX_WHITELIST_SIZE || count > MAX_WHITELIST_COUNT)
+ {
+ return LSL_STATUS_BOUNDS_ERROR;
+ }
+ }
+ // Next clear the vector
+ mWhiteList.clear();
+ // Then re-iterate and copy entries
+ iter = whitelist.beginArray();
+ for ( ; iter < end; ++iter)
+ {
+ const std::string &entry = (*iter).asString();
+ mWhiteList.push_back(entry);
+ }
+ return LSL_STATUS_OK;
+ }
+ else
+ {
+ return LSL_STATUS_MALFORMED_PARAMS;
+ }
+}
+
+
+static void prefix_with(std::string &str, const char *chars, const char *prefix)
+{
+ // Given string 'str', prefix all instances of any character in 'chars'
+ // with 'prefix'
+ size_t found = str.find_first_of(chars);
+ size_t prefix_len = strlen(prefix);
+ while (found != std::string::npos)
+ {
+ str.insert(found, prefix, prefix_len);
+ found = str.find_first_of(chars, found+prefix_len+1);
+ }
+}
+
+static bool pattern_match(const std::string &candidate_str, const std::string &pattern)
+{
+ // If the pattern is empty, it matches
+ if (pattern.empty()) return true;
+
+ // 'pattern' is a glob pattern, we only accept '*' chars
+ // copy it
+ std::string expression = pattern;
+
+ // Escape perl's regexp chars with a backslash, except all "*" chars
+ prefix_with(expression, ".[{()\\+?|^$", "\\");
+ prefix_with(expression, "*", ".");
+
+ // case-insensitive matching:
+ boost::regex regexp(expression, boost::regex::perl|boost::regex::icase);
+ return boost::regex_match(candidate_str, regexp);
+}
+
+bool LLMediaEntry::checkCandidateUrl(const std::string& url) const
+{
+ if (getWhiteListEnable())
+ {
+ return checkUrlAgainstWhitelist(url, getWhiteList());
+ }
+ else
+ {
+ return true;
+ }
+}
+
+// static
+bool LLMediaEntry::checkUrlAgainstWhitelist(const std::string& url,
+ const std::vector<std::string> &whitelist)
+{
+ bool passes = true;
+ // *NOTE: no entries? Don't check
+ if (whitelist.size() > 0)
+ {
+ passes = false;
+
+ // Case insensitive: the reason why we toUpper both this and the
+ // filter
+ std::string candidate_url = url;
+ // Use lluri to see if there is a path part in the candidate URL. No path? Assume "/"
+ LLURI candidate_uri(candidate_url);
+ std::vector<std::string>::const_iterator iter = whitelist.begin();
+ std::vector<std::string>::const_iterator end = whitelist.end();
+ for ( ; iter < end; ++iter )
+ {
+ std::string filter = *iter;
+
+ LLURI filter_uri(filter);
+ bool scheme_passes = pattern_match( candidate_uri.scheme(), filter_uri.scheme() );
+ if (filter_uri.scheme().empty())
+ {
+ filter_uri = LLURI(DEFAULT_URL_PREFIX + filter);
+ }
+ bool authority_passes = pattern_match( candidate_uri.authority(), filter_uri.authority() );
+ bool path_passes = pattern_match( candidate_uri.escapedPath(), filter_uri.escapedPath() );
+
+ if (scheme_passes && authority_passes && path_passes)
+ {
+ passes = true;
+ break;
+ }
+ }
+ }
+ return passes;
+}
+
+U32 LLMediaEntry::setStringFieldWithLimit( std::string &field, const std::string &value, U32 limit )
+{
+ if ( value.length() > limit )
+ {
+ return LSL_STATUS_BOUNDS_ERROR;
+ }
+ else
+ {
+ field = value;
+ return LSL_STATUS_OK;
+ }
+}
+
+U32 LLMediaEntry::setControls(LLMediaEntry::MediaControls controls)
+{
+ if (controls == STANDARD ||
+ controls == MINI)
+ {
+ mControls = controls;
+ return LSL_STATUS_OK;
+ }
+ return LSL_STATUS_BOUNDS_ERROR;
+}
+
+U32 LLMediaEntry::setPermsInteract( U8 val )
+{
+ mPermsInteract = val & PERM_MASK;
+ return LSL_STATUS_OK;
+}
+
+U32 LLMediaEntry::setPermsControl( U8 val )
+{
+ mPermsControl = val & PERM_MASK;
+ return LSL_STATUS_OK;
+}
+
+U32 LLMediaEntry::setCurrentURL(const std::string& current_url)
+{
+ return setCurrentURLInternal( current_url, true );
+}
+
+U32 LLMediaEntry::setCurrentURLInternal(const std::string& current_url, bool check_whitelist)
+{
+ if ( ! check_whitelist || checkCandidateUrl(current_url))
+ {
+ return setStringFieldWithLimit( mCurrentURL, current_url, MAX_URL_LENGTH );
+ }
+ else
+ {
+ return LSL_STATUS_WHITELIST_FAILED;
+ }
+}
+
+U32 LLMediaEntry::setHomeURL(const std::string& home_url)
+{
+ return setStringFieldWithLimit( mHomeURL, home_url, MAX_URL_LENGTH );
+}
+
+U32 LLMediaEntry::setWidthPixels(U16 width)
+{
+ if (width > MAX_WIDTH_PIXELS) return LSL_STATUS_BOUNDS_ERROR;
+ mWidthPixels = width;
+ return LSL_STATUS_OK;
+}
+
+U32 LLMediaEntry::setHeightPixels(U16 height)
+{
+ if (height > MAX_HEIGHT_PIXELS) return LSL_STATUS_BOUNDS_ERROR;
+ mHeightPixels = height;
+ return LSL_STATUS_OK;
+}
+
+const LLUUID &LLMediaEntry::getMediaID() const
+{
+ // Lazily generate media ID
+ if (NULL == mMediaIDp)
+ {
+ mMediaIDp = new LLUUID();
+ mMediaIDp->generate();
+ }
+ return *mMediaIDp;
+}
+
diff --git a/indra/llprimitive/llmediaentry.h b/indra/llprimitive/llmediaentry.h
new file mode 100644
index 0000000000..2a5486666a
--- /dev/null
+++ b/indra/llprimitive/llmediaentry.h
@@ -0,0 +1,228 @@
+/**
+ * @file llmediaentry.h
+ * @brief This is a single instance of media data related to the face of a prim
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLMEDIAENTRY_H
+#define LL_LLMEDIAENTRY_H
+
+#include "llsd.h"
+#include "llstring.h"
+
+// For return values of set*
+#include "lllslconstants.h"
+
+class LLMediaEntry
+{
+public:
+ enum MediaControls {
+ STANDARD = 0,
+ MINI
+ };
+
+ // Constructors
+ LLMediaEntry();
+ LLMediaEntry(const LLMediaEntry &rhs);
+
+ LLMediaEntry &operator=(const LLMediaEntry &rhs);
+ virtual ~LLMediaEntry();
+
+ bool operator==(const LLMediaEntry &rhs) const;
+ bool operator!=(const LLMediaEntry &rhs) const;
+
+ // Render as LLSD
+ LLSD asLLSD() const;
+ void asLLSD(LLSD& sd) const;
+ operator LLSD() const { return asLLSD(); }
+ // Returns false iff the given LLSD contains fields that violate any bounds
+ // limits.
+ static bool checkLLSD(const LLSD& sd);
+ // This doesn't merge, it overwrites the data, so will use
+ // LLSD defaults if need be. Note: does not check limits!
+ // Use checkLLSD() above first to ensure the LLSD is valid.
+ void fromLLSD(const LLSD& sd);
+ // This merges data from the incoming LLSD into our fields.
+ // Note that it also does NOT check limits! Use checkLLSD() above first.
+ void mergeFromLLSD(const LLSD& sd);
+
+ // "general" fields
+ bool getAltImageEnable() const { return mAltImageEnable; }
+ MediaControls getControls() const { return mControls; }
+ std::string getCurrentURL() const { return mCurrentURL; }
+ std::string getHomeURL() const { return mHomeURL; }
+ bool getAutoLoop() const { return mAutoLoop; }
+ bool getAutoPlay() const { return mAutoPlay; }
+ bool getAutoScale() const { return mAutoScale; }
+ bool getAutoZoom() const { return mAutoZoom; }
+ bool getFirstClickInteract() const { return mFirstClickInteract; }
+ U16 getWidthPixels() const { return mWidthPixels; }
+ U16 getHeightPixels() const { return mHeightPixels; }
+
+ // "security" fields
+ bool getWhiteListEnable() const { return mWhiteListEnable; }
+ const std::vector<std::string> &getWhiteList() const { return mWhiteList; }
+
+ // "permissions" fields
+ U8 getPermsInteract() const { return mPermsInteract; }
+ U8 getPermsControl() const { return mPermsControl; }
+
+ // Setters. Those that return a U32 return a status error code
+ // See lllslconstants.h
+
+ // "general" fields
+ U32 setAltImageEnable(bool alt_image_enable) { mAltImageEnable = alt_image_enable; return LSL_STATUS_OK; }
+ U32 setControls(MediaControls controls);
+ U32 setCurrentURL(const std::string& current_url);
+ U32 setHomeURL(const std::string& home_url);
+ U32 setAutoLoop(bool auto_loop) { mAutoLoop = auto_loop; return LSL_STATUS_OK; }
+ U32 setAutoPlay(bool auto_play) { mAutoPlay = auto_play; return LSL_STATUS_OK; }
+ U32 setAutoScale(bool auto_scale) { mAutoScale = auto_scale; return LSL_STATUS_OK; }
+ U32 setAutoZoom(bool auto_zoom) { mAutoZoom = auto_zoom; return LSL_STATUS_OK; }
+ U32 setFirstClickInteract(bool first_click) { mFirstClickInteract = first_click; return LSL_STATUS_OK; }
+ U32 setWidthPixels(U16 width);
+ U32 setHeightPixels(U16 height);
+
+ // "security" fields
+ U32 setWhiteListEnable( bool whitelist_enable ) { mWhiteListEnable = whitelist_enable; return LSL_STATUS_OK; }
+ U32 setWhiteList( const std::vector<std::string> &whitelist );
+ U32 setWhiteList( const LLSD &whitelist ); // takes an LLSD array
+
+ // "permissions" fields
+ U32 setPermsInteract( U8 val );
+ U32 setPermsControl( U8 val );
+
+ const LLUUID& getMediaID() const;
+
+ // Helper function to check a candidate URL against the whitelist
+ // Returns true iff candidate URL passes (or if there is no whitelist), false otherwise
+ bool checkCandidateUrl(const std::string& url) const;
+
+public:
+ // Static function to check a URL against a whitelist
+ // Returns true iff url passes the given whitelist
+ static bool checkUrlAgainstWhitelist(const std::string &url,
+ const std::vector<std::string> &whitelist);
+
+public:
+ // LLSD key defines
+ // "general" fields
+ static const char* ALT_IMAGE_ENABLE_KEY;
+ static const char* CONTROLS_KEY;
+ static const char* CURRENT_URL_KEY;
+ static const char* HOME_URL_KEY;
+ static const char* AUTO_LOOP_KEY;
+ static const char* AUTO_PLAY_KEY;
+ static const char* AUTO_SCALE_KEY;
+ static const char* AUTO_ZOOM_KEY;
+ static const char* FIRST_CLICK_INTERACT_KEY;
+ static const char* WIDTH_PIXELS_KEY;
+ static const char* HEIGHT_PIXELS_KEY;
+
+ // "security" fields
+ static const char* WHITELIST_ENABLE_KEY;
+ static const char* WHITELIST_KEY;
+
+ // "permissions" fields
+ static const char* PERMS_INTERACT_KEY;
+ static const char* PERMS_CONTROL_KEY;
+
+ // Field enumerations & constants
+
+ // *NOTE: DO NOT change the order of these, and do not insert values
+ // in the middle!
+ // Add values to the end, and make sure to change PARAM_MAX_ID!
+ enum Fields {
+ ALT_IMAGE_ENABLE_ID = 0,
+ CONTROLS_ID = 1,
+ CURRENT_URL_ID = 2,
+ HOME_URL_ID = 3,
+ AUTO_LOOP_ID = 4,
+ AUTO_PLAY_ID = 5,
+ AUTO_SCALE_ID = 6,
+ AUTO_ZOOM_ID = 7,
+ FIRST_CLICK_INTERACT_ID = 8,
+ WIDTH_PIXELS_ID = 9,
+ HEIGHT_PIXELS_ID = 10,
+ WHITELIST_ENABLE_ID = 11,
+ WHITELIST_ID = 12,
+ PERMS_INTERACT_ID = 13,
+ PERMS_CONTROL_ID = 14,
+ PARAM_MAX_ID = PERMS_CONTROL_ID
+ };
+
+ // "permissions" values
+ // (e.g. (PERM_OWNER | PERM_GROUP) sets permissions on for OWNER and GROUP
+ static const U8 PERM_NONE = 0x0;
+ static const U8 PERM_OWNER = 0x1;
+ static const U8 PERM_GROUP = 0x2;
+ static const U8 PERM_ANYONE = 0x4;
+ static const U8 PERM_ALL = PERM_OWNER|PERM_GROUP|PERM_ANYONE;
+ static const U8 PERM_MASK = PERM_OWNER|PERM_GROUP|PERM_ANYONE;
+
+ // Limits (in bytes)
+ static const U32 MAX_URL_LENGTH = 1024;
+ static const U32 MAX_WHITELIST_SIZE = 1024;
+ static const U32 MAX_WHITELIST_COUNT = 64;
+ static const U16 MAX_WIDTH_PIXELS = 2048;
+ static const U16 MAX_HEIGHT_PIXELS = 2048;
+
+private:
+
+ U32 setStringFieldWithLimit( std::string &field, const std::string &value, U32 limit );
+ U32 setCurrentURLInternal( const std::string &url, bool check_whitelist);
+ bool fromLLSDInternal(const LLSD &sd, bool overwrite);
+
+private:
+ // "general" fields
+ bool mAltImageEnable;
+ MediaControls mControls;
+ std::string mCurrentURL;
+ std::string mHomeURL;
+ bool mAutoLoop;
+ bool mAutoPlay;
+ bool mAutoScale;
+ bool mAutoZoom;
+ bool mFirstClickInteract;
+ U16 mWidthPixels;
+ U16 mHeightPixels;
+
+ // "security" fields
+ bool mWhiteListEnable;
+ std::vector<std::string> mWhiteList;
+
+ // "permissions" fields
+ U8 mPermsInteract;
+ U8 mPermsControl;
+
+ mutable LLUUID *mMediaIDp; // temporary id assigned to media on the viewer
+};
+
+#endif
+
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index 13facc0d58..5ad758072c 100644
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -43,7 +43,7 @@
#include "llvolumemgr.h"
#include "llstring.h"
#include "lldatapacker.h"
-#include "llsdutil.h"
+#include "llsdutil_math.h"
#include "llprimtexturelist.h"
/**
@@ -132,7 +132,7 @@ void LLPrimitive::setVolumeManager( LLVolumeMgr* volume_manager )
{
if ( !volume_manager || sVolumeManager )
{
- llerrs << "Unable to set LLPrimitive::sVolumeManager to NULL" << llendl;
+ llerrs << "LLPrimitive::sVolumeManager attempting to be set to NULL or it already has been set." << llendl;
}
sVolumeManager = volume_manager;
}
@@ -746,16 +746,201 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai
U32 old_face_mask = mVolumep->mFaceMask;
+ S32 face_bit = 0;
+ S32 cur_mask = 0;
+
+ // Grab copies of the old faces from the original shape, ordered by type.
+ // We will use these to figure out what old texture info gets mapped to new
+ // faces in the new shape.
+ std::vector<LLProfile::Face> old_faces;
+ for (S32 face = 0; face < mVolumep->getNumFaces(); face++)
+ {
+ old_faces.push_back(mVolumep->getProfile().mFaces[face]);
+ }
+
+ // Copy the old texture info off to the side, but not in the order in which
+ // they live in the mTextureList, rather in order of ther "face id" which
+ // is the corresponding value of LLVolueParams::LLProfile::mFaces::mIndex.
+ //
+ // Hence, some elements of old_tes::mEntryList will be invalid. It is
+ // initialized to a size of 9 (max number of possible faces on a volume?)
+ // and only the ones with valid types are filled in.
+ LLPrimTextureList old_tes;
+ old_tes.setSize(9);
+ for (face_bit = 0; face_bit < 9; face_bit++)
+ {
+ cur_mask = 0x1 << face_bit;
+ if (old_face_mask & cur_mask)
+ {
+ S32 te_index = face_index_from_id(cur_mask, old_faces);
+ old_tes.copyTexture(face_bit, *(getTE(te_index)));
+ //llinfos << face_bit << ":" << te_index << ":" << old_tes[face_bit].getID() << llendl;
+ }
+ }
+
+
// build the new object
sVolumeManager->unrefVolume(mVolumep);
mVolumep = volumep;
U32 new_face_mask = mVolumep->mFaceMask;
- if (old_face_mask != new_face_mask)
+ S32 i;
+
+ if (old_face_mask == new_face_mask)
+ {
+ // nothing to do
+ return TRUE;
+ }
+
+ if (mVolumep->getNumFaces() == 0 && new_face_mask != 0)
{
+ llwarns << "Object with 0 faces found...INCORRECT!" << llendl;
setNumTEs(mVolumep->getNumFaces());
+ return TRUE;
+ }
+
+ // initialize face_mapping
+ S32 face_mapping[9];
+ for (face_bit = 0; face_bit < 9; face_bit++)
+ {
+ face_mapping[face_bit] = face_bit;
}
+ // The new shape may have more faces than the original, but we can't just
+ // add them to the end -- the ordering matters and it may be that we must
+ // insert the new faces in the middle of the list. When we add a face it
+ // will pick up the texture/color info of one of the old faces an so we
+ // now figure out which old face info gets mapped to each new face, and
+ // store in the face_mapping lookup table.
+ for (face_bit = 0; face_bit < 9; face_bit++)
+ {
+ cur_mask = 0x1 << face_bit;
+ if (!(new_face_mask & cur_mask))
+ {
+ // Face doesn't exist in new map.
+ face_mapping[face_bit] = -1;
+ continue;
+ }
+ else if (old_face_mask & cur_mask)
+ {
+ // Face exists in new and old map.
+ face_mapping[face_bit] = face_bit;
+ continue;
+ }
+
+ // OK, how we've got a mismatch, where we have to fill a new face with one from
+ // the old face.
+ if (cur_mask & (LL_FACE_PATH_BEGIN | LL_FACE_PATH_END | LL_FACE_INNER_SIDE))
+ {
+ // It's a top/bottom/hollow interior face.
+ if (old_face_mask & LL_FACE_PATH_END)
+ {
+ face_mapping[face_bit] = 1;
+ continue;
+ }
+ else
+ {
+ S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0;
+ for (i = 0; i < 4; i++)
+ {
+ if (old_face_mask & cur_outer_mask)
+ {
+ face_mapping[face_bit] = 5 + i;
+ break;
+ }
+ cur_outer_mask <<= 1;
+ }
+ if (i == 4)
+ {
+ llwarns << "No path end or outer face in volume!" << llendl;
+ }
+ continue;
+ }
+ }
+
+ if (cur_mask & (LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END))
+ {
+ // A cut slice. Use the hollow interior if we have it.
+ if (old_face_mask & LL_FACE_INNER_SIDE)
+ {
+ face_mapping[face_bit] = 2;
+ continue;
+ }
+
+ // No interior, use the bottom face.
+ // Could figure out which of the outer faces was nearest, but that would be harder.
+ if (old_face_mask & LL_FACE_PATH_END)
+ {
+ face_mapping[face_bit] = 1;
+ continue;
+ }
+ else
+ {
+ S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0;
+ for (i = 0; i < 4; i++)
+ {
+ if (old_face_mask & cur_outer_mask)
+ {
+ face_mapping[face_bit] = 5 + i;
+ break;
+ }
+ cur_outer_mask <<= 1;
+ }
+ if (i == 4)
+ {
+ llwarns << "No path end or outer face in volume!" << llendl;
+ }
+ continue;
+ }
+ }
+
+ // OK, the face that's missing is an outer face...
+ // Pull from the nearest adjacent outer face (there's always guaranteed to be one...
+ S32 cur_outer = face_bit - 5;
+ S32 min_dist = 5;
+ S32 min_outer_bit = -1;
+ S32 i;
+ for (i = 0; i < 4; i++)
+ {
+ if (old_face_mask & (LL_FACE_OUTER_SIDE_0 << i))
+ {
+ S32 dist = abs(i - cur_outer);
+ if (dist < min_dist)
+ {
+ min_dist = dist;
+ min_outer_bit = i + 5;
+ }
+ }
+ }
+ if (-1 == min_outer_bit)
+ {
+ llinfos << (LLVolume *)mVolumep << llendl;
+ llwarns << "Bad! No outer faces, impossible!" << llendl;
+ }
+ face_mapping[face_bit] = min_outer_bit;
+ }
+
+
+ setNumTEs(mVolumep->getNumFaces());
+ for (face_bit = 0; face_bit < 9; face_bit++)
+ {
+ // For each possible face type on the new shape we check to see if that
+ // face exists and if it does we create a texture entry that is a copy
+ // of one of the originals. Since the originals might not have a
+ // matching face, we use the face_mapping lookup table to figure out
+ // which face information to copy.
+ cur_mask = 0x1 << face_bit;
+ if (new_face_mask & cur_mask)
+ {
+ if (-1 == face_mapping[face_bit])
+ {
+ llwarns << "No mapping from old face to new face!" << llendl;
+ }
+
+ S32 te_num = face_index_from_id(cur_mask, mVolumep->getProfile().mFaces);
+ setTE(te_num, *(old_tes.getTexture(face_mapping[face_bit])));
+ }
+ }
return TRUE;
}
@@ -1134,6 +1319,7 @@ S32 LLPrimitive::unpackTEMessage(LLMessageSystem *mesgsys, char *block_name, con
color.mV[VALPHA] = F32(255 - coloru.mV[VALPHA]) / 255.f;
retval |= setTEColor(i, color);
+
}
return retval;
@@ -1314,6 +1500,8 @@ BOOL LLNetworkData::isValid(U16 param_type, U32 size)
return (size == 16);
case PARAMS_SCULPT:
return (size == 17);
+ case PARAMS_LIGHT_IMAGE:
+ return (size == 28);
}
return FALSE;
@@ -1646,3 +1834,78 @@ bool LLSculptParams::fromLLSD(LLSD& sd)
return false;
}
+//============================================================================
+
+LLLightImageParams::LLLightImageParams()
+{
+ mType = PARAMS_LIGHT_IMAGE;
+ mParams.setVec(F_PI*0.5f, 0.f, 0.f);
+}
+
+BOOL LLLightImageParams::pack(LLDataPacker &dp) const
+{
+ dp.packUUID(mLightTexture, "texture");
+ dp.packVector3(mParams, "params");
+
+ return TRUE;
+}
+
+BOOL LLLightImageParams::unpack(LLDataPacker &dp)
+{
+ dp.unpackUUID(mLightTexture, "texture");
+ dp.unpackVector3(mParams, "params");
+
+ return TRUE;
+}
+
+bool LLLightImageParams::operator==(const LLNetworkData& data) const
+{
+ if (data.mType != PARAMS_LIGHT_IMAGE)
+ {
+ return false;
+ }
+
+ const LLLightImageParams *param = (const LLLightImageParams*)&data;
+ if ( (param->mLightTexture != mLightTexture) )
+ {
+ return false;
+ }
+
+ if ( (param->mParams != mParams ) )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void LLLightImageParams::copy(const LLNetworkData& data)
+{
+ const LLLightImageParams *param = (LLLightImageParams*)&data;
+ mLightTexture = param->mLightTexture;
+ mParams = param->mParams;
+}
+
+
+
+LLSD LLLightImageParams::asLLSD() const
+{
+ LLSD sd;
+
+ sd["texture"] = mLightTexture;
+ sd["params"] = mParams.getValue();
+
+ return sd;
+}
+
+bool LLLightImageParams::fromLLSD(LLSD& sd)
+{
+ if (sd.has("texture"))
+ {
+ setLightTexture( sd["texture"] );
+ setParams( LLVector3( sd["params"] ) );
+ return true;
+ }
+
+ return false;
+}
diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h
index c25df0a40f..4f828186cb 100644
--- a/indra/llprimitive/llprimitive.h
+++ b/indra/llprimitive/llprimitive.h
@@ -37,7 +37,7 @@
#include "v3math.h"
#include "xform.h"
#include "message.h"
-#include "llmemory.h"
+#include "llpointer.h"
#include "llvolume.h"
#include "lltextureentry.h"
#include "llprimtexturelist.h"
@@ -107,7 +107,8 @@ public:
{
PARAMS_FLEXIBLE = 0x10,
PARAMS_LIGHT = 0x20,
- PARAMS_SCULPT = 0x30
+ PARAMS_SCULPT = 0x30,
+ PARAMS_LIGHT_IMAGE = 0x40,
};
public:
@@ -262,11 +263,33 @@ public:
bool fromLLSD(LLSD& sd);
void setSculptTexture(const LLUUID& id) { mSculptTexture = id; }
- LLUUID getSculptTexture() { return mSculptTexture; }
+ LLUUID getSculptTexture() const { return mSculptTexture; }
void setSculptType(U8 type) { mSculptType = type; }
- U8 getSculptType() { return mSculptType; }
+ U8 getSculptType() const { return mSculptType; }
};
+class LLLightImageParams : public LLNetworkData
+{
+protected:
+ LLUUID mLightTexture;
+ LLVector3 mParams;
+
+public:
+ LLLightImageParams();
+ /*virtual*/ BOOL pack(LLDataPacker &dp) const;
+ /*virtual*/ BOOL unpack(LLDataPacker &dp);
+ /*virtual*/ bool operator==(const LLNetworkData& data) const;
+ /*virtual*/ void copy(const LLNetworkData& data);
+ LLSD asLLSD() const;
+ operator LLSD() const { return asLLSD(); }
+ bool fromLLSD(LLSD& sd);
+
+ void setLightTexture(const LLUUID& id) { mLightTexture = id; }
+ LLUUID getLightTexture() const { return mLightTexture; }
+ void setParams(const LLVector3& params) { mParams = params; }
+ LLVector3 getParams() const { return mParams; }
+
+};
class LLPrimitive : public LLXform
diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp
index c9632ebdad..1c7de95975 100644
--- a/indra/llprimitive/llprimtexturelist.cpp
+++ b/indra/llprimitive/llprimtexturelist.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2008-2007, Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -12,12 +12,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
@@ -134,13 +135,12 @@ S32 LLPrimTextureList::copyTexture(const U8 index, const LLTextureEntry& te)
{
if (S32(index) >= mEntryList.size())
{
- // TODO -- assert here
S32 current_size = mEntryList.size();
- llerrs << "index = " << S32(index) << " current_size = " << current_size << llendl;
+ llwarns << "ignore copy of index = " << S32(index) << " into texture entry list of size = " << current_size << llendl;
return TEM_CHANGE_NONE;
}
- // we're changing an existing entry
+ // we're changing an existing entry
llassert(mEntryList[index]);
delete (mEntryList[index]);
if (&te)
@@ -386,8 +386,18 @@ void LLPrimTextureList::setSize(S32 new_size)
mEntryList.resize(new_size);
for (S32 index = current_size; index < new_size; ++index)
{
- LLTextureEntry* new_entry = LLPrimTextureList::newTextureEntry();
- mEntryList[index] = new_entry;
+ if (current_size > 0
+ && mEntryList[current_size - 1])
+ {
+ // copy the last valid entry for the new one
+ mEntryList[index] = mEntryList[current_size - 1]->newCopy();
+ }
+ else
+ {
+ // no valid enries to copy, so we new one up
+ LLTextureEntry* new_entry = LLPrimTextureList::newTextureEntry();
+ mEntryList[index] = new_entry;
+ }
}
}
else if (new_size < current_size)
diff --git a/indra/llprimitive/llprimtexturelist.h b/indra/llprimitive/llprimtexturelist.h
index 61285bd1bf..6254878b99 100644
--- a/indra/llprimitive/llprimtexturelist.h
+++ b/indra/llprimitive/llprimtexturelist.h
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2008-2007, Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -12,12 +12,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp
index 3bcd831142..f75f1d9b8c 100644
--- a/indra/llprimitive/lltextureentry.cpp
+++ b/indra/llprimitive/lltextureentry.cpp
@@ -32,13 +32,31 @@
#include "linden_common.h"
+#include "lluuid.h"
+#include "llmediaentry.h"
#include "lltextureentry.h"
-#include "llsdutil.h"
+#include "llsdutil_math.h"
+#include "v4color.h"
const U8 DEFAULT_BUMP_CODE = 0; // no bump or shininess
const LLTextureEntry LLTextureEntry::null;
+// Some LLSD keys. Do not change these!
+#define OBJECT_ID_KEY_STR "object_id"
+#define TEXTURE_INDEX_KEY_STR "texture_index"
+#define OBJECT_MEDIA_VERSION_KEY_STR "object_media_version"
+#define OBJECT_MEDIA_DATA_KEY_STR "object_media_data"
+#define TEXTURE_MEDIA_DATA_KEY_STR "media_data"
+
+/*static*/ const char* LLTextureEntry::OBJECT_ID_KEY = OBJECT_ID_KEY_STR;
+/*static*/ const char* LLTextureEntry::OBJECT_MEDIA_DATA_KEY = OBJECT_MEDIA_DATA_KEY_STR;
+/*static*/ const char* LLTextureEntry::MEDIA_VERSION_KEY = OBJECT_MEDIA_VERSION_KEY_STR;
+/*static*/ const char* LLTextureEntry::TEXTURE_INDEX_KEY = TEXTURE_INDEX_KEY_STR;
+/*static*/ const char* LLTextureEntry::TEXTURE_MEDIA_DATA_KEY = TEXTURE_MEDIA_DATA_KEY_STR;
+
+static const std::string MEDIA_VERSION_STRING_PREFIX = "x-mv:";
+
// static
LLTextureEntry* LLTextureEntry::newTextureEntry()
{
@@ -47,16 +65,19 @@ LLTextureEntry* LLTextureEntry::newTextureEntry()
//===============================================================
LLTextureEntry::LLTextureEntry()
+ : mMediaEntry(NULL)
{
init(LLUUID::null,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE);
}
LLTextureEntry::LLTextureEntry(const LLUUID& tex_id)
+ : mMediaEntry(NULL)
{
init(tex_id,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE);
}
LLTextureEntry::LLTextureEntry(const LLTextureEntry &rhs)
+ : mMediaEntry(NULL)
{
mID = rhs.mID;
mScaleS = rhs.mScaleS;
@@ -68,6 +89,10 @@ LLTextureEntry::LLTextureEntry(const LLTextureEntry &rhs)
mBump = rhs.mBump;
mMediaFlags = rhs.mMediaFlags;
mGlow = rhs.mGlow;
+ if (rhs.mMediaEntry != NULL) {
+ // Make a copy
+ mMediaEntry = new LLMediaEntry(*rhs.mMediaEntry);
+ }
}
LLTextureEntry &LLTextureEntry::operator=(const LLTextureEntry &rhs)
@@ -84,6 +109,16 @@ LLTextureEntry &LLTextureEntry::operator=(const LLTextureEntry &rhs)
mBump = rhs.mBump;
mMediaFlags = rhs.mMediaFlags;
mGlow = rhs.mGlow;
+ if (mMediaEntry != NULL) {
+ delete mMediaEntry;
+ }
+ if (rhs.mMediaEntry != NULL) {
+ // Make a copy
+ mMediaEntry = new LLMediaEntry(*rhs.mMediaEntry);
+ }
+ else {
+ mMediaEntry = NULL;
+ }
}
return *this;
@@ -103,10 +138,19 @@ void LLTextureEntry::init(const LLUUID& tex_id, F32 scale_s, F32 scale_t, F32 of
mGlow = 0;
setColor(LLColor4(1.f, 1.f, 1.f, 1.f));
+ if (mMediaEntry != NULL) {
+ delete mMediaEntry;
+ }
+ mMediaEntry = NULL;
}
LLTextureEntry::~LLTextureEntry()
{
+ if(mMediaEntry)
+ {
+ delete mMediaEntry;
+ mMediaEntry = NULL;
+ }
}
bool LLTextureEntry::operator!=(const LLTextureEntry &rhs) const
@@ -158,10 +202,17 @@ void LLTextureEntry::asLLSD(LLSD& sd) const
sd["bump"] = getBumpShiny();
sd["fullbright"] = getFullbright();
sd["media_flags"] = mMediaFlags;
+ if (hasMedia()) {
+ LLSD mediaData;
+ if (NULL != getMediaData()) {
+ getMediaData()->asLLSD(mediaData);
+ }
+ sd[TEXTURE_MEDIA_DATA_KEY] = mediaData;
+ }
sd["glow"] = mGlow;
}
-bool LLTextureEntry::fromLLSD(LLSD& sd)
+bool LLTextureEntry::fromLLSD(const LLSD& sd)
{
const char *w, *x;
w = "imageid";
@@ -206,6 +257,17 @@ bool LLTextureEntry::fromLLSD(LLSD& sd)
{
setMediaTexGen( sd[w].asInteger() );
} else goto fail;
+ // If the "has media" flag doesn't match the fact that
+ // media data exists, updateMediaData will "fix" it
+ // by either clearing or setting the flag
+ w = TEXTURE_MEDIA_DATA_KEY;
+ if (hasMedia() != sd.has(w))
+ {
+ llwarns << "LLTextureEntry::fromLLSD: media_flags (" << hasMedia() <<
+ ") does not match presence of media_data (" << sd.has(w) << "). Fixing." << llendl;
+ }
+ updateMediaData(sd[w]);
+
w = "glow";
if (sd.has(w))
{
@@ -370,7 +432,19 @@ S32 LLTextureEntry::setMediaTexGen(U8 media)
if (mMediaFlags != media)
{
mMediaFlags = media;
- return TEM_CHANGE_TEXTURE;
+
+ // Special code for media handling
+ if( hasMedia() && mMediaEntry == NULL)
+ {
+ mMediaEntry = new LLMediaEntry;
+ }
+ else if ( ! hasMedia() && mMediaEntry != NULL)
+ {
+ delete mMediaEntry;
+ mMediaEntry = NULL;
+ }
+
+ return TEM_CHANGE_MEDIA;
}
return TEM_CHANGE_NONE;
}
@@ -430,7 +504,19 @@ S32 LLTextureEntry::setMediaFlags(U8 media_flags)
{
mMediaFlags &= ~TEM_MEDIA_MASK;
mMediaFlags |= media_flags;
- return TEM_CHANGE_TEXTURE;
+
+ // Special code for media handling
+ if( hasMedia() && mMediaEntry == NULL)
+ {
+ mMediaEntry = new LLMediaEntry;
+ }
+ else if ( ! hasMedia() && mMediaEntry != NULL)
+ {
+ delete mMediaEntry;
+ mMediaEntry = NULL;
+ }
+
+ return TEM_CHANGE_MEDIA;
}
return TEM_CHANGE_NONE;
}
@@ -456,3 +542,113 @@ S32 LLTextureEntry::setGlow(F32 glow)
}
return TEM_CHANGE_NONE;
}
+
+void LLTextureEntry::setMediaData(const LLMediaEntry &media_entry)
+{
+ mMediaFlags |= MF_HAS_MEDIA;
+ if (NULL != mMediaEntry)
+ {
+ delete mMediaEntry;
+ }
+ mMediaEntry = new LLMediaEntry(media_entry);
+}
+
+bool LLTextureEntry::updateMediaData(const LLSD& media_data)
+{
+ if (media_data.isUndefined())
+ {
+ // clear the media data
+ clearMediaData();
+ return false;
+ }
+ else {
+ mMediaFlags |= MF_HAS_MEDIA;
+ if (mMediaEntry == NULL)
+ {
+ mMediaEntry = new LLMediaEntry;
+ }
+ // *NOTE: this will *clobber* all of the fields in mMediaEntry
+ // with whatever fields are present (or not present) in media_data!
+ mMediaEntry->fromLLSD(media_data);
+ return true;
+ }
+}
+
+void LLTextureEntry::clearMediaData()
+{
+ mMediaFlags &= ~MF_HAS_MEDIA;
+ if (mMediaEntry != NULL) {
+ delete mMediaEntry;
+ }
+ mMediaEntry = NULL;
+}
+
+void LLTextureEntry::mergeIntoMediaData(const LLSD& media_fields)
+{
+ mMediaFlags |= MF_HAS_MEDIA;
+ if (mMediaEntry == NULL)
+ {
+ mMediaEntry = new LLMediaEntry;
+ }
+ // *NOTE: this will *merge* the data in media_fields
+ // with the data in our media entry
+ mMediaEntry->mergeFromLLSD(media_fields);
+}
+
+//static
+std::string LLTextureEntry::touchMediaVersionString(const std::string &in_version, const LLUUID &agent_id)
+{
+ // XXX TODO: make media version string binary (base64-encoded?)
+ // Media "URL" is a representation of a version and the last-touched agent
+ // x-mv:nnnnn/agent-id
+ // where "nnnnn" is version number
+ // *NOTE: not the most efficient code in the world...
+ U32 current_version = getVersionFromMediaVersionString(in_version) + 1;
+ const size_t MAX_VERSION_LEN = 10; // 2^32 fits in 10 decimal digits
+ char buf[MAX_VERSION_LEN+1];
+ snprintf(buf, (int)MAX_VERSION_LEN+1, "%0*u", (int)MAX_VERSION_LEN, current_version); // added int cast to fix warning/breakage on mac.
+ return MEDIA_VERSION_STRING_PREFIX + buf + "/" + agent_id.asString();
+}
+
+//static
+U32 LLTextureEntry::getVersionFromMediaVersionString(const std::string &version_string)
+{
+ U32 version = 0;
+ if (!version_string.empty())
+ {
+ size_t found = version_string.find(MEDIA_VERSION_STRING_PREFIX);
+ if (found != std::string::npos)
+ {
+ found = version_string.find_first_of("/", found);
+ std::string v = version_string.substr(MEDIA_VERSION_STRING_PREFIX.length(), found);
+ version = strtoul(v.c_str(),NULL,10);
+ }
+ }
+ return version;
+}
+
+//static
+LLUUID LLTextureEntry::getAgentIDFromMediaVersionString(const std::string &version_string)
+{
+ LLUUID id;
+ if (!version_string.empty())
+ {
+ size_t found = version_string.find(MEDIA_VERSION_STRING_PREFIX);
+ if (found != std::string::npos)
+ {
+ found = version_string.find_first_of("/", found);
+ if (found != std::string::npos)
+ {
+ std::string v = version_string.substr(found + 1);
+ id.set(v);
+ }
+ }
+ }
+ return id;
+}
+
+//static
+bool LLTextureEntry::isMediaVersionString(const std::string &version_string)
+{
+ return std::string::npos != version_string.find(MEDIA_VERSION_STRING_PREFIX);
+}
diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h
index 84870e93e6..d6366b9bb2 100644
--- a/indra/llprimitive/lltextureentry.h
+++ b/indra/llprimitive/lltextureentry.h
@@ -37,10 +37,13 @@
#include "v4color.h"
#include "llsd.h"
+// These bits are used while unpacking TEM messages to tell which aspects of
+// the texture entry changed.
const S32 TEM_CHANGE_NONE = 0x0;
const S32 TEM_CHANGE_COLOR = 0x1;
const S32 TEM_CHANGE_TEXTURE = 0x2;
-const S32 TEM_INVALID = 0x4;
+const S32 TEM_CHANGE_MEDIA = 0x4;
+const S32 TEM_INVALID = 0x8;
const S32 TEM_BUMPMAP_COUNT = 32;
@@ -65,6 +68,8 @@ const S32 TEM_MEDIA_MASK = 0x01;
const S32 TEM_TEX_GEN_MASK = 0x06;
const S32 TEM_TEX_GEN_SHIFT = 1;
+// forward declarations
+class LLMediaEntry;
class LLTextureEntry
{
@@ -92,7 +97,7 @@ public:
LLSD asLLSD() const;
void asLLSD(LLSD& sd) const;
operator LLSD() const { return asLLSD(); }
- bool fromLLSD(LLSD& sd);
+ bool fromLLSD(const LLSD& sd);
virtual LLTextureEntry* newBlank() const;
virtual LLTextureEntry* newCopy() const;
@@ -140,9 +145,37 @@ public:
U8 getTexGen() const { return mMediaFlags & TEM_TEX_GEN_MASK; }
U8 getMediaTexGen() const { return mMediaFlags; }
F32 getGlow() const { return mGlow; }
+
+ // *NOTE: it is possible for hasMedia() to return true, but getMediaData() to return NULL.
+ // CONVERSELY, it is also possible for hasMedia() to return false, but getMediaData()
+ // to NOT return NULL.
+ bool hasMedia() const { return (bool)(mMediaFlags & MF_HAS_MEDIA); }
+ LLMediaEntry* getMediaData() const { return mMediaEntry; }
+
+ // Completely change the media data on this texture entry.
+ void setMediaData(const LLMediaEntry &media_entry);
+ // Returns true if media data was updated, false if it was cleared
+ bool updateMediaData(const LLSD& media_data);
+ // Clears media data, and sets the media flags bit to 0
+ void clearMediaData();
+ // Merges the given LLSD of media fields with this media entry.
+ // Only those fields that are set that match the keys in
+ // LLMediaEntry will be affected. If no fields are set or if
+ // the LLSD is undefined, this is a no-op.
+ void mergeIntoMediaData(const LLSD& media_fields);
+
+ // Takes a media version string (an empty string or a previously-returned string)
+ // and returns a "touched" string, touched by agent_id
+ static std::string touchMediaVersionString(const std::string &in_version, const LLUUID &agent_id);
+ // Given a media version string, return the version
+ static U32 getVersionFromMediaVersionString(const std::string &version_string);
+ // Given a media version string, return the UUID of the agent
+ static LLUUID getAgentIDFromMediaVersionString(const std::string &version_string);
+ // Return whether or not the given string is actually a media version
+ static bool isMediaVersionString(const std::string &version_string);
// Media flags
- enum { MF_NONE = 0x0, MF_WEB_PAGE = 0x1 };
+ enum { MF_NONE = 0x0, MF_HAS_MEDIA = 0x1 };
public:
F32 mScaleS; // S, T offset
@@ -152,6 +185,14 @@ public:
F32 mRotation; // anti-clockwise rotation in rad about the bottom left corner
static const LLTextureEntry null;
+
+ // LLSD key defines
+ static const char* OBJECT_ID_KEY;
+ static const char* OBJECT_MEDIA_DATA_KEY;
+ static const char* MEDIA_VERSION_KEY;
+ static const char* TEXTURE_INDEX_KEY;
+ static const char* TEXTURE_MEDIA_DATA_KEY;
+
protected:
LLUUID mID; // Texture GUID
LLColor4 mColor;
@@ -159,6 +200,9 @@ protected:
U8 mMediaFlags; // replace with web page, movie, etc.
F32 mGlow;
+ // Note the media data is not sent via the same message structure as the rest of the TE
+ LLMediaEntry* mMediaEntry; // The media data for the face
+
// NOTE: when adding new data to this class, in addition to adding it to the serializers asLLSD/fromLLSD and the
// message packers (e.g. LLPrimitive::packTEMessage) you must also implement its copy in LLPrimitive::copyTEs()
diff --git a/indra/llprimitive/material_codes.cpp b/indra/llprimitive/material_codes.cpp
new file mode 100644
index 0000000000..ce146dad8a
--- /dev/null
+++ b/indra/llprimitive/material_codes.cpp
@@ -0,0 +1,46 @@
+/**
+ * @file material_codes.cpp
+ * @brief Material_codes definitions
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "material_codes.h"
+
+#include "lluuid.h"
+
+const LLUUID LL_DEFAULT_STONE_UUID("87c5765b-aa26-43eb-b8c6-c09a1ca6208e");
+const LLUUID LL_DEFAULT_METAL_UUID("6f3c53e9-ba60-4010-8f3e-30f51a762476");
+const LLUUID LL_DEFAULT_GLASS_UUID("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d");
+const LLUUID LL_DEFAULT_WOOD_UUID("89556747-24cb-43ed-920b-47caed15465f");
+const LLUUID LL_DEFAULT_FLESH_UUID("80736669-e4b9-450e-8890-d5169f988a50");
+const LLUUID LL_DEFAULT_PLASTIC_UUID("304fcb4e-7d33-4339-ba80-76d3d22dc11a");
+const LLUUID LL_DEFAULT_RUBBER_UUID("9fae0bc5-666d-477e-9f70-84e8556ec867");
+const LLUUID LL_DEFAULT_LIGHT_UUID("00000000-0000-0000-0000-000000000000");
diff --git a/indra/llprimitive/material_codes.h b/indra/llprimitive/material_codes.h
index e5a59a2789..ba3faba39f 100644
--- a/indra/llprimitive/material_codes.h
+++ b/indra/llprimitive/material_codes.h
@@ -33,7 +33,7 @@
#ifndef LL_MATERIAL_CODES_H
#define LL_MATERIAL_CODES_H
-#include "lluuid.h"
+class LLUUID;
// material types
const U8 LL_MCODE_STONE = 0;
@@ -47,13 +47,14 @@ const U8 LL_MCODE_LIGHT = 7;
const U8 LL_MCODE_END = 8;
const U8 LL_MCODE_MASK = 0x0F;
-const LLUUID LL_DEFAULT_STONE_UUID("87c5765b-aa26-43eb-b8c6-c09a1ca6208e");
-const LLUUID LL_DEFAULT_METAL_UUID("6f3c53e9-ba60-4010-8f3e-30f51a762476");
-const LLUUID LL_DEFAULT_GLASS_UUID("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d");
-const LLUUID LL_DEFAULT_WOOD_UUID("89556747-24cb-43ed-920b-47caed15465f");
-const LLUUID LL_DEFAULT_FLESH_UUID("80736669-e4b9-450e-8890-d5169f988a50");
-const LLUUID LL_DEFAULT_PLASTIC_UUID("304fcb4e-7d33-4339-ba80-76d3d22dc11a");
-const LLUUID LL_DEFAULT_RUBBER_UUID("9fae0bc5-666d-477e-9f70-84e8556ec867");
-const LLUUID LL_DEFAULT_LIGHT_UUID("00000000-0000-0000-0000-000000000000");
+// *NOTE: Define these in .cpp file to reduce duplicate instances
+extern const LLUUID LL_DEFAULT_STONE_UUID;
+extern const LLUUID LL_DEFAULT_METAL_UUID;
+extern const LLUUID LL_DEFAULT_GLASS_UUID;
+extern const LLUUID LL_DEFAULT_WOOD_UUID;
+extern const LLUUID LL_DEFAULT_FLESH_UUID;
+extern const LLUUID LL_DEFAULT_PLASTIC_UUID;
+extern const LLUUID LL_DEFAULT_RUBBER_UUID;
+extern const LLUUID LL_DEFAULT_LIGHT_UUID;
#endif
diff --git a/indra/llprimitive/tests/llmediaentry_test.cpp b/indra/llprimitive/tests/llmediaentry_test.cpp
new file mode 100644
index 0000000000..277e370ca4
--- /dev/null
+++ b/indra/llprimitive/tests/llmediaentry_test.cpp
@@ -0,0 +1,490 @@
+/**
+ * @file llmediaentry_test.cpp
+ * @brief llmediaentry unit tests
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "lltut.h"
+#if LL_WINDOWS
+#pragma warning (push)
+#pragma warning (disable : 4702) // boost::lexical_cast generates this warning
+#endif
+#include <boost/lexical_cast.hpp>
+#if LL_WINDOWS
+#pragma warning (pop)
+#endif
+#include "llstring.h"
+#include "llsdutil.h"
+#include "llsdserialize.h"
+
+#include "../llmediaentry.h"
+#include "lllslconstants.h"
+
+#define DEFAULT_MEDIA_ENTRY "<llsd>\n\
+ <map>\n\
+ <key>alt_image_enable</key>\n\
+ <boolean>0</boolean>\n\
+ <key>auto_loop</key>\n\
+ <boolean>0</boolean>\n\
+ <key>auto_play</key>\n\
+ <boolean>0</boolean>\n\
+ <key>auto_scale</key>\n\
+ <boolean>0</boolean>\n\
+ <key>auto_zoom</key>\n\
+ <boolean>0</boolean>\n\
+ <key>controls</key>\n\
+ <integer>0</integer>\n\
+ <key>current_url</key>\n\
+ <string />\n\
+ <key>first_click_interact</key>\n\
+ <boolean>0</boolean>\n\
+ <key>height_pixels</key>\n\
+ <integer>0</integer>\n\
+ <key>home_url</key>\n\
+ <string />\n\
+ <key>perms_control</key>\n\
+ <integer>7</integer>\n\
+ <key>perms_interact</key>\n\
+ <integer>7</integer>\n\
+ <key>whitelist_enable</key>\n\
+ <boolean>0</boolean>\n\
+ <key>width_pixels</key>\n\
+ <integer>0</integer>\n\
+ </map>\n\
+ </llsd>"
+
+#define EMPTY_MEDIA_ENTRY "<llsd>\n\
+ <map>\n\
+ <key>alt_image_enable</key>\n\
+ <boolean>0</boolean>\n\
+ <key>auto_loop</key>\n\
+ <boolean>0</boolean>\n\
+ <key>auto_play</key>\n\
+ <boolean>0</boolean>\n\
+ <key>auto_scale</key>\n\
+ <boolean>0</boolean>\n\
+ <key>auto_zoom</key>\n\
+ <boolean>0</boolean>\n\
+ <key>controls</key>\n\
+ <integer>0</integer>\n\
+ <key>current_url</key>\n\
+ <string />\n\
+ <key>first_click_interact</key>\n\
+ <boolean>0</boolean>\n\
+ <key>height_pixels</key>\n\
+ <integer>0</integer>\n\
+ <key>home_url</key>\n\
+ <string />\n\
+ <key>perms_control</key>\n\
+ <integer>0</integer>\n\
+ <key>perms_interact</key>\n\
+ <integer>0</integer>\n\
+ <key>whitelist_enable</key>\n\
+ <boolean>0</boolean>\n\
+ <key>width_pixels</key>\n\
+ <integer>0</integer>\n\
+ </map>\n\
+ </llsd>"
+
+#define PARTIAL_MEDIA_ENTRY(CURRENT_URL) "<llsd>\n\
+ <map>\n\
+ <key>alt_image_enable</key>\n\
+ <boolean>0</boolean>\n\
+ <key>auto_loop</key>\n\
+ <boolean>0</boolean>\n\
+ <key>auto_play</key>\n\
+ <boolean>0</boolean>\n\
+ <key>auto_scale</key>\n\
+ <boolean>0</boolean>\n\
+ <key>auto_zoom</key>\n\
+ <boolean>0</boolean>\n\
+ <key>controls</key>\n\
+ <integer>0</integer>\n\
+ <key>current_url</key>\n\
+ <string>" CURRENT_URL "</string>\n\
+ <key>first_click_interact</key>\n\
+ <boolean>0</boolean>\n\
+ <key>height_pixels</key>\n\
+ <integer>0</integer>\n\
+ <key>home_url</key>\n\
+ <string />\n\
+ <key>perms_control</key>\n\
+ <integer>0</integer>\n\
+ <key>perms_interact</key>\n\
+ <integer>0</integer>\n\
+ <key>whitelist_enable</key>\n\
+ <boolean>0</boolean>\n\
+ <key>width_pixels</key>\n\
+ <integer>0</integer>\n\
+ </map>\n\
+ </llsd>"
+
+namespace tut
+{
+ // this is fixture data that gets created before each test and destroyed
+ // after each test. this is where we put all of the setup/takedown code
+ // and data needed for each test.
+ struct MediaEntry_test
+ {
+ MediaEntry_test() {
+ emptyMediaEntryStr = EMPTY_MEDIA_ENTRY;
+ std::istringstream e(EMPTY_MEDIA_ENTRY);
+ LLSDSerialize::fromXML(emptyMediaEntryLLSD, e);
+ defaultMediaEntryStr = DEFAULT_MEDIA_ENTRY;
+ std::istringstream d(DEFAULT_MEDIA_ENTRY);
+ LLSDSerialize::fromXML(defaultMediaEntryLLSD, d);
+ }
+ std::string emptyMediaEntryStr;
+ LLSD emptyMediaEntryLLSD;
+ std::string defaultMediaEntryStr;
+ LLSD defaultMediaEntryLLSD;
+ };
+
+ typedef test_group<MediaEntry_test, 55> factory;
+ typedef factory::object object;
+}
+
+
+namespace
+{
+ // this is for naming our tests to make pretty output
+ tut::factory tf("MediaEntry Test");
+}
+
+namespace tut
+{
+ bool llsd_equals(const LLSD& a, const LLSD& b) {
+ // cheesy, brute force, but it works
+ return std::string(ll_pretty_print_sd(a)) == std::string(ll_pretty_print_sd(b));
+ }
+
+ void ensure_llsd_equals(const std::string& msg, const LLSD& expected, const LLSD& actual)
+ {
+ if (!tut::llsd_equals(expected, actual))
+ {
+ std::string message = msg;
+ message += ": actual: ";
+ message += ll_pretty_print_sd(actual);
+ message += "\n expected: ";
+ message += ll_pretty_print_sd(expected);
+ message += "\n";
+ ensure(message, false);
+ }
+ }
+
+ void ensure_string_equals(const std::string& msg, const std::string& expected, const std::string& actual)
+ {
+ if ( expected != actual )
+ {
+ std::string message = msg;
+ message += ": actual: ";
+ message += actual;
+ message += "\n expected: ";
+ message += expected;
+ message += "\n";
+ ensure(message, false);
+ }
+ }
+
+ void set_whitelist(LLMediaEntry &entry, const char *str)
+ {
+ std::vector<std::string> tokens;
+ LLStringUtil::getTokens(std::string(str), tokens, ",");
+ entry.setWhiteList(tokens);
+ }
+
+ void whitelist_test(int num, bool enable, const char *whitelist, const char *candidate_url, bool expected_pass)
+ {
+ std::string message = "Whitelist test " + boost::lexical_cast<std::string>(num);
+ LLMediaEntry entry;
+ entry.setWhiteListEnable(enable);
+ set_whitelist(entry, whitelist);
+ bool passed_whitelist = entry.checkCandidateUrl(candidate_url);
+ if (passed_whitelist != expected_pass)
+ {
+ message += " failed: expected ";
+ message += (expected_pass) ? "" : "NOT ";
+ message += "to match\nwhitelist = ";
+ message += whitelist;
+ message += "\ncandidate_url = ";
+ message += candidate_url;
+ }
+ ensure(message, expected_pass == passed_whitelist);
+ }
+
+ void whitelist_test(int num, const char *whitelist, const char *candidate_url, bool expected_pass)
+ {
+ whitelist_test(num, true, whitelist, candidate_url, expected_pass);
+ }
+ void whitelist_test(int num, const char *whitelist, const char *candidate_url)
+ {
+ whitelist_test(num, true, whitelist, candidate_url, true);
+ }
+
+ template<> template<>
+ void object::test<1>()
+ {
+ set_test_name("Test LLMediaEntry Instantiation");
+ LLMediaEntry entry;
+ ensure_llsd_equals(get_test_name() + " failed", defaultMediaEntryLLSD, entry.asLLSD());
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ set_test_name("Test LLMediaEntry Instantiation from LLSD");
+ LLMediaEntry entry;
+ LLSD sd;
+ entry.fromLLSD(sd);
+ ensure_llsd_equals(get_test_name() + " failed", emptyMediaEntryLLSD, entry.asLLSD());
+ }
+
+ template<> template<>
+ void object::test<3>()
+ {
+ set_test_name("Test LLMediaEntry Partial Instantiation from LLSD");
+ LLMediaEntry entry;
+ LLSD sd;
+ sd[LLMediaEntry::CURRENT_URL_KEY] = "http://www.example.com";
+ entry.fromLLSD(sd);
+ LLSD golden;
+ std::istringstream p(PARTIAL_MEDIA_ENTRY("http://www.example.com"));
+ LLSDSerialize::fromXML(golden,p);
+ ensure_llsd_equals(get_test_name() + " failed", golden, entry.asLLSD());
+ }
+
+ template<> template<>
+ void object::test<4>()
+ {
+ set_test_name("Test LLMediaEntry::asLLSD()");
+ LLMediaEntry entry;
+ LLSD sd;
+ // Put some cruft in the LLSD
+ sd[LLMediaEntry::CURRENT_URL_KEY] = "http://www.example.com";
+ LLSD whitelist;
+ whitelist.append("*.example.com");
+ sd[LLMediaEntry::WHITELIST_KEY] = whitelist;
+ entry.asLLSD(sd);
+ ensure_llsd_equals(get_test_name() + " failed", defaultMediaEntryLLSD, sd);
+ }
+
+
+ template<> template<>
+ void object::test<5>()
+ {
+ set_test_name("Test LLMediaEntry::asLLSD() -> LLMediaEntry::fromLLSD()");
+ LLMediaEntry entry1, entry2;
+ // Add a whitelist to entry2
+ std::vector<std::string> whitelist;
+ whitelist.push_back("*.example.com");
+ entry2.setWhiteList(whitelist);
+ // Render entry1 (which has no whitelist) as an LLSD
+ LLSD sd;
+ entry1.asLLSD(sd);
+ // "read" that LLSD into entry 2
+ entry2.fromLLSD(sd);
+ ensure_llsd_equals(get_test_name() + " failed", defaultMediaEntryLLSD, entry2.asLLSD());
+ }
+
+ // limit tests
+ const char *URL_OK = "http://www.example.com";
+ const char *URL_TOO_BIG = "http://www.example.com.qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq";
+
+ template<> template<>
+ void object::test<6>()
+ {
+ set_test_name("Test Limits on setting current URL");
+ LLMediaEntry entry;
+ U32 status = entry.setCurrentURL(URL_OK);
+ ensure(get_test_name() + " ok failed", status == LSL_STATUS_OK);
+ status = entry.setCurrentURL(URL_TOO_BIG);
+ ensure(get_test_name() + " ok failed", status == LSL_STATUS_BOUNDS_ERROR);
+ }
+
+ template<> template<>
+ void object::test<7>()
+ {
+ set_test_name("Test Limits on setting home URL");
+ LLMediaEntry entry;
+ U32 status = entry.setHomeURL(URL_OK);
+ ensure(get_test_name() + " ok failed", status == LSL_STATUS_OK);
+ status = entry.setHomeURL(URL_TOO_BIG);
+ ensure(get_test_name() + " ok failed", status == LSL_STATUS_BOUNDS_ERROR);
+ }
+
+ template<> template<>
+ void object::test<8>()
+ {
+ set_test_name("Test Limits on setting whitelist");
+
+ // Test a valid list
+ LLMediaEntry entry;
+ std::vector<std::string> whitelist;
+ whitelist.push_back(std::string(URL_OK));
+ S32 status = entry.setWhiteList(whitelist);
+ ensure(get_test_name() + " invalid result", status == LSL_STATUS_OK);
+ ensure(get_test_name() + " failed", whitelist == entry.getWhiteList());
+ }
+
+ template<> template<>
+ void object::test<9>()
+ {
+ set_test_name("Test Limits on setting whitelist too big");
+
+ // Test an invalid list
+ LLMediaEntry entry;
+ std::vector<std::string> whitelist, empty;
+ whitelist.push_back(std::string(URL_OK));
+ whitelist.push_back(std::string(URL_TOO_BIG));
+ S32 status = entry.setWhiteList(whitelist);
+ ensure(get_test_name() + " invalid result", status == LSL_STATUS_BOUNDS_ERROR);
+ ensure(get_test_name() + " failed", empty == entry.getWhiteList());
+ }
+
+ template<> template<>
+ void object::test<10>()
+ {
+ set_test_name("Test Limits on setting whitelist too many");
+
+ // Test an invalid list
+ LLMediaEntry entry;
+ std::vector<std::string> whitelist, empty;
+ for (int i=0; i < LLMediaEntry::MAX_WHITELIST_SIZE+1; i++) {
+ whitelist.push_back("Q");
+ }
+ S32 status = entry.setWhiteList(whitelist);
+ ensure(get_test_name() + " invalid result", status == LSL_STATUS_BOUNDS_ERROR);
+ ensure(get_test_name() + " failed", empty == entry.getWhiteList());
+ }
+
+ template<> template<>
+ void object::test<11>()
+ {
+ set_test_name("Test to make sure both setWhiteList() functions behave the same");
+
+ // Test a valid list
+ std::vector<std::string> whitelist, empty;
+ LLSD whitelist_llsd;
+ whitelist.push_back(std::string(URL_OK));
+ whitelist_llsd.append(std::string(URL_OK));
+ LLMediaEntry entry1, entry2;
+ ensure(get_test_name() + " setWhiteList(s) don't match",
+ entry1.setWhiteList(whitelist) == LSL_STATUS_OK &&
+ entry2.setWhiteList(whitelist_llsd)== LSL_STATUS_OK );
+ ensure(get_test_name() + " failed",
+ entry1.getWhiteList() == entry2.getWhiteList());
+ }
+
+ template<> template<>
+ void object::test<12>()
+ {
+ set_test_name("Test to make sure both setWhiteList() functions behave the same");
+
+ // Test an invalid list
+ std::vector<std::string> whitelist, empty;
+ LLSD whitelist_llsd;
+ whitelist.push_back(std::string(URL_OK));
+ whitelist.push_back(std::string(URL_TOO_BIG));
+ whitelist_llsd.append(std::string(URL_OK));
+ whitelist_llsd.append(std::string(URL_TOO_BIG));
+ LLMediaEntry entry1, entry2;
+ ensure(get_test_name() + " setWhiteList(s) don't match",
+ entry1.setWhiteList(whitelist) == LSL_STATUS_BOUNDS_ERROR &&
+ entry2.setWhiteList(whitelist_llsd) == LSL_STATUS_BOUNDS_ERROR);
+ ensure(get_test_name() + " failed",
+ empty == entry1.getWhiteList() &&
+ empty == entry2.getWhiteList());
+ }
+
+ template<> template<>
+ void object::test<13>()
+ {
+ set_test_name("Test to make sure both setWhiteList() functions behave the same");
+
+ // Test an invalid list, too many
+ std::vector<std::string> whitelist, empty;
+ LLSD whitelist_llsd;
+ for (int i=0; i < LLMediaEntry::MAX_WHITELIST_SIZE+1; i++) {
+ whitelist.push_back("Q");
+ whitelist_llsd.append("Q");
+ }
+ LLMediaEntry entry1, entry2;
+ ensure(get_test_name() + " invalid result",
+ entry1.setWhiteList(whitelist) == LSL_STATUS_BOUNDS_ERROR &&
+ entry2.setWhiteList(whitelist_llsd) == LSL_STATUS_BOUNDS_ERROR);
+ ensure(get_test_name() + " failed",
+ empty == entry1.getWhiteList() &&
+ empty == entry2.getWhiteList());
+ }
+
+ template<> template<>
+ void object::test<14>()
+ {
+ // Whitelist check tests
+ int n=0;
+
+ // Check the "empty whitelist" case
+ whitelist_test(++n, "", "http://www.example.com", true);
+
+ // Check the "missing scheme" case
+ whitelist_test(++n, "www.example.com", "http://www.example.com", true);
+
+ // Check the "exactly the same" case
+ whitelist_test(++n, "http://example.com", "http://example.com", true);
+
+ // Check the enable flag
+ whitelist_test(++n, false, "www.example.com", "http://www.secondlife.com", true);
+ whitelist_test(++n, true, "www.example.com", "http://www.secondlife.com", false);
+
+ // Check permutations of trailing slash:
+ whitelist_test(++n, "http://www.example.com", "http://www.example.com/", true);
+ whitelist_test(++n, "http://www.example.com/", "http://www.example.com/", true);
+ whitelist_test(++n, "http://www.example.com/", "http://www.example.com", false);
+ whitelist_test(++n, "http://www.example.com", "http://www.example.com/foobar", true);
+ whitelist_test(++n, "http://www.example.com/", "http://www.example.com/foobar", false);
+
+
+ // More cases...
+ whitelist_test(++n, "http://example.com", "http://example.com/wiki", true);
+ whitelist_test(++n, "www.example.com", "http://www.example.com/help", true);
+ whitelist_test(++n, "http://www.example.com", "http://wwwexample.com", false);
+ whitelist_test(++n, "http://www.example.com", "http://www.example.com/wiki", true);
+ whitelist_test(++n, "example.com", "http://wwwexample.com", false);
+ whitelist_test(++n, "http://www.example.com/", "http://www.amazon.com/wiki", false);
+ whitelist_test(++n, "www.example.com", "http://www.amazon.com", false);
+
+ // regexp cases
+ whitelist_test(++n, "*.example.com", "http://www.example.com", true);
+ whitelist_test(++n, "*.example.com", "http://www.amazon.com", false);
+ whitelist_test(++n, "*.example.com", "http://www.example.com/foo/bar", true);
+ whitelist_test(++n, "*.example.com", "http:/example.com/foo/bar", false);
+ whitelist_test(++n, "*example.com", "http://example.com/foo/bar", true);
+ whitelist_test(++n, "*example.com", "http://my.virus.com/foo/bar?example.com", false);
+ whitelist_test(++n, "example.com", "http://my.virus.com/foo/bar?example.com", false);
+ whitelist_test(++n, "*example.com", "http://my.virus.com/foo/bar?*example.com", false);
+ whitelist_test(++n, "http://*example.com", "http://www.example.com", true);
+ whitelist_test(++n, "http://*.example.com", "http://www.example.com", true);
+ whitelist_test(++n, "http://*.e$?^.com", "http://www.e$?^.com", true);
+ whitelist_test(++n, "*.example.com/foo/bar", "http://www.example.com/", false);
+ whitelist_test(++n, "*.example.com/foo/bar", "http://example.com/foo/bar", false);
+ whitelist_test(++n, "http://*.example.com/foo/bar", "http://www.example.com", false);
+ whitelist_test(++n, "http://*.example.com", "https://www.example.com", false);
+ whitelist_test(++n, "http*://*.example.com", "rtsp://www.example.com", false);
+ whitelist_test(++n, "http*://*.example.com", "https://www.example.com", true);
+ whitelist_test(++n, "example.com", "http://www.example.com", false);
+ whitelist_test(++n, "www.example.com", "http://www.example.com:80", false);
+ whitelist_test(++n, "www.example.com", "http://www.example.com", true);
+ whitelist_test(++n, "www.example.com/", "http://www.example.com", false);
+ whitelist_test(++n, "www.example.com/foo/bar/*", "http://www.example.com/foo/bar/baz", true);
+
+ // Path only
+ whitelist_test(++n, "/foo/*/baz", "http://www.example.com/foo/bar/baz", true);
+ whitelist_test(++n, "/foo/*/baz", "http://www.example.com/foo/bar/", false);
+ }
+
+}
+
diff --git a/indra/llprimitive/tests/llmessagesystem_stub.cpp b/indra/llprimitive/tests/llmessagesystem_stub.cpp
new file mode 100644
index 0000000000..8ca3c56022
--- /dev/null
+++ b/indra/llprimitive/tests/llmessagesystem_stub.cpp
@@ -0,0 +1,30 @@
+/**
+ * @file llmessagesystem_stub.cpp
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+char * _PREHASH_TextureEntry;
+
+S32 LLMessageSystem::getSizeFast(char const*, char const*) const
+{
+ return 0;
+}
+
+S32 LLMessageSystem::getSizeFast(char const*, int, char const*) const
+{
+ return 0;
+}
+
+void LLMessageSystem::getBinaryDataFast(char const*, char const*, void*, int, int, int)
+{
+}
+
+void LLMessageSystem::addBinaryDataFast(char const*, void const*, int)
+{
+}
+
diff --git a/indra/llprimitive/tests/llprimitive_test.cpp b/indra/llprimitive/tests/llprimitive_test.cpp
new file mode 100644
index 0000000000..1805a9e968
--- /dev/null
+++ b/indra/llprimitive/tests/llprimitive_test.cpp
@@ -0,0 +1,214 @@
+/**
+ * @file llprimitive_test.cpp
+ * @brief llprimitive tests
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../test/lltut.h"
+
+#include "../llprimitive.h"
+
+#include "../../llmath/llvolumemgr.h"
+
+class DummyVolumeMgr : public LLVolumeMgr
+{
+public:
+ DummyVolumeMgr() : LLVolumeMgr(), mVolumeTest(NULL), mCurrDetailTest(0) {}
+ ~DummyVolumeMgr()
+ {
+ }
+
+
+ virtual LLVolume *refVolume(const LLVolumeParams &volume_params, const S32 detail)
+ {
+ if (mVolumeTest.isNull() || volume_params != mCurrParamsTest || detail != mCurrDetailTest)
+ {
+ F32 volume_detail = LLVolumeLODGroup::getVolumeScaleFromDetail(detail);
+ mVolumeTest = new LLVolume(volume_params, volume_detail, FALSE, FALSE);
+ mCurrParamsTest = volume_params;
+ mCurrDetailTest = detail;
+ return mVolumeTest;
+ }
+ else
+ {
+ return mVolumeTest;
+ }
+ }
+
+ virtual void unrefVolume(LLVolume *volumep)
+ {
+ if (mVolumeTest == volumep)
+ {
+ mVolumeTest = NULL;
+ }
+ }
+
+private:
+ LLPointer<LLVolume> mVolumeTest;
+ LLVolumeParams mCurrParamsTest;
+ S32 mCurrDetailTest;
+};
+
+class PRIMITIVE_TEST_SETUP
+{
+public:
+ PRIMITIVE_TEST_SETUP()
+ {
+ volume_manager_test = new DummyVolumeMgr();
+ LLPrimitive::setVolumeManager(volume_manager_test);
+ }
+
+ ~PRIMITIVE_TEST_SETUP()
+ {
+ LLPrimitive::cleanupVolumeManager();
+ }
+ DummyVolumeMgr * volume_manager_test;
+};
+
+namespace tut
+{
+ struct llprimitive
+ {
+ PRIMITIVE_TEST_SETUP setup_class;
+ };
+
+ typedef test_group<llprimitive> llprimitive_t;
+ typedef llprimitive_t::object llprimitive_object_t;
+ tut::llprimitive_t tut_llprimitive("llprimitive");
+
+ template<> template<>
+ void llprimitive_object_t::test<1>()
+ {
+ set_test_name("Test LLPrimitive Instantiation");
+ LLPrimitive test;
+ }
+
+ template<> template<>
+ void llprimitive_object_t::test<2>()
+ {
+ set_test_name("Test LLPrimitive PCode setter and getter.");
+ LLPrimitive test;
+ ensure_equals(test.getPCode(), 0);
+ LLPCode code = 1;
+ test.setPCode(code);
+ ensure_equals(test.getPCode(), code);
+ }
+
+ template<> template<>
+ void llprimitive_object_t::test<3>()
+ {
+ set_test_name("Test llprimitive constructor and initer.");
+ LLPCode code = 1;
+ LLPrimitive primitive;
+ primitive.init_primitive(code);
+ ensure_equals(primitive.getPCode(), code);
+ }
+
+ template<> template<>
+ void llprimitive_object_t::test<4>()
+ {
+ set_test_name("Test Static llprimitive constructor and initer.");
+ LLPCode code = 1;
+ LLPrimitive * primitive = LLPrimitive::createPrimitive(code);
+ ensure(primitive != NULL);
+ ensure_equals(primitive->getPCode(), code);
+ }
+
+ template<> template<>
+ void llprimitive_object_t::test<5>()
+ {
+ set_test_name("Test setVolume creation of new unique volume.");
+ LLPrimitive primitive;
+ LLVolumeParams params;
+
+ // Make sure volume starts off null
+ ensure(primitive.getVolume() == NULL);
+
+ // Make sure we have no texture entries before setting the volume
+ ensure_equals(primitive.getNumTEs(), 0);
+
+ // Test that GEOMETRY has not been flagged as changed.
+ ensure(!primitive.isChanged(LLXform::GEOMETRY));
+
+ // Make sure setVolume returns true
+ ensure(primitive.setVolume(params, 0, true) == TRUE);
+ LLVolume* new_volume = primitive.getVolume();
+
+ // make sure new volume was actually created
+ ensure(new_volume != NULL);
+
+ // Make sure that now that we've set the volume we have texture entries
+ ensure_not_equals(primitive.getNumTEs(), 0);
+
+ // Make sure that the number of texture entries equals the number of faces in the volume (should be 6)
+ ensure_equals(new_volume->getNumFaces(), 6);
+ ensure_equals(primitive.getNumTEs(), new_volume->getNumFaces());
+
+ // Test that GEOMETRY has been flagged as changed.
+ ensure(primitive.isChanged(LLXform::GEOMETRY));
+
+ // Run it twice to make sure it doesn't create a different one if params are the same
+ ensure(primitive.setVolume(params, 0, true) == FALSE);
+ ensure(new_volume == primitive.getVolume());
+
+ // Change the param definition and try setting it again.
+ params.setRevolutions(4);
+ ensure(primitive.setVolume(params, 0, true) == TRUE);
+
+ // Ensure that we now have a different volume
+ ensure(new_volume != primitive.getVolume());
+ }
+
+ template<> template<>
+ void llprimitive_object_t::test<6>()
+ {
+ set_test_name("Test setVolume creation of new NOT-unique volume.");
+ LLPrimitive primitive;
+ LLVolumeParams params;
+
+ // Make sure volume starts off null
+ ensure(primitive.getVolume() == NULL);
+
+ // Make sure we have no texture entries before setting the volume
+ ensure_equals(primitive.getNumTEs(), 0);
+
+ // Test that GEOMETRY has not been flagged as changed.
+ ensure(!primitive.isChanged(LLXform::GEOMETRY));
+
+ // Make sure setVolume returns true
+ ensure(primitive.setVolume(params, 0, false) == TRUE);
+
+ LLVolume* new_volume = primitive.getVolume();
+
+ // make sure new volume was actually created
+ ensure(new_volume != NULL);
+
+ // Make sure that now that we've set the volume we have texture entries
+ ensure_not_equals(primitive.getNumTEs(), 0);
+
+ // Make sure that the number of texture entries equals the number of faces in the volume (should be 6)
+ ensure_equals(new_volume->getNumFaces(), 6);
+ ensure_equals(primitive.getNumTEs(), new_volume->getNumFaces());
+
+ // Test that GEOMETRY has been flagged as changed.
+ ensure(primitive.isChanged(LLXform::GEOMETRY));
+
+ // Run it twice to make sure it doesn't create a different one if params are the same
+ ensure(primitive.setVolume(params, 0, false) == FALSE);
+ ensure(new_volume == primitive.getVolume());
+
+ // Change the param definition and try setting it again.
+ params.setRevolutions(4);
+ ensure(primitive.setVolume(params, 0, false) == TRUE);
+
+ // Ensure that we now have a different volume
+ ensure(new_volume != primitive.getVolume());
+ }
+}
+
+#include "llmessagesystem_stub.cpp"
diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt
index 0bb835970f..5c13df9f81 100644
--- a/indra/llrender/CMakeLists.txt
+++ b/indra/llrender/CMakeLists.txt
@@ -9,6 +9,7 @@ include(LLCommon)
include(LLImage)
include(LLMath)
include(LLRender)
+include(LLVFS)
include(LLWindow)
include(LLXML)
include(LLVFS)
@@ -19,6 +20,7 @@ include_directories(
${LLIMAGE_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS}
${LLRENDER_INCLUDE_DIRS}
+ ${LLVFS_INCLUDE_DIRS}
${LLWINDOW_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS}
@@ -26,7 +28,7 @@ include_directories(
set(llrender_SOURCE_FILES
llcubemap.cpp
- llfont.cpp
+ llfontfreetype.cpp
llfontgl.cpp
llfontbitmapcache.cpp
llfontregistry.cpp
@@ -36,6 +38,7 @@ set(llrender_SOURCE_FILES
llpostprocess.cpp
llrendersphere.cpp
llshadermgr.cpp
+ lltexture.cpp
llvertexbuffer.cpp
)
@@ -44,7 +47,7 @@ set(llrender_HEADER_FILES
llcubemap.h
llfontgl.h
- llfont.h
+ llfontfreetype.h
llfontbitmapcache.h
llfontregistry.h
llgl.h
@@ -58,6 +61,7 @@ set(llrender_HEADER_FILES
llrender.h
llrendersphere.h
llshadermgr.h
+ lltexture.h
llvertexbuffer.h
)
diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp
index 754d90c854..08a96b4e31 100644
--- a/indra/llrender/llcubemap.cpp
+++ b/indra/llrender/llcubemap.cpp
@@ -106,7 +106,7 @@ void LLCubeMap::initGL()
}
else
{
- llwarns << "Using cube map without extension!" << llendl
+ llwarns << "Using cube map without extension!" << llendl;
}
}
diff --git a/indra/llrender/llfontbitmapcache.cpp b/indra/llrender/llfontbitmapcache.cpp
index f6321b0534..f01878642a 100644
--- a/indra/llrender/llfontbitmapcache.cpp
+++ b/indra/llrender/llfontbitmapcache.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2008, Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -12,12 +12,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
@@ -36,13 +37,13 @@
LLFontBitmapCache::LLFontBitmapCache():
mNumComponents(0),
- mMaxCharWidth(0),
- mMaxCharHeight(0),
mBitmapWidth(0),
mBitmapHeight(0),
+ mBitmapNum(-1),
+ mMaxCharWidth(0),
+ mMaxCharHeight(0),
mCurrentOffsetX(1),
- mCurrentOffsetY(1),
- mCurrentBitmapNum(-1)
+ mCurrentOffsetY(1)
{
}
@@ -159,10 +160,10 @@ void LLFontBitmapCache::reset()
mImageRawVec.clear();
mImageGLVec.clear();
- mBitmapWidth = 0,
- mBitmapHeight = 0,
- mCurrentOffsetX = 0,
- mCurrentOffsetY = 0,
- mCurrentBitmapNum = -1;
+ mBitmapWidth = 0;
+ mBitmapHeight = 0;
+ mBitmapNum = -1;
+ mCurrentOffsetX = 1;
+ mCurrentOffsetY = 1;
}
diff --git a/indra/llrender/llfontbitmapcache.h b/indra/llrender/llfontbitmapcache.h
index e5c09f8826..b044ba2b16 100644
--- a/indra/llrender/llfontbitmapcache.h
+++ b/indra/llrender/llfontbitmapcache.h
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2008, Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -12,12 +12,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
@@ -35,7 +36,7 @@
#include <vector>
// Maintain a collection of bitmaps containing rendered glyphs.
-// Generalizes the single-bitmap logic from LLFont and LLFontGL.
+// Generalizes the single-bitmap logic from LLFontFreetype and LLFontGL.
class LLFontBitmapCache: public LLRefCount
{
public:
@@ -70,7 +71,6 @@ private:
S32 mMaxCharHeight;
S32 mCurrentOffsetX;
S32 mCurrentOffsetY;
- S32 mCurrentBitmapNum;
std::vector<LLPointer<LLImageRaw> > mImageRawVec;
std::vector<LLPointer<LLImageGL> > mImageGLVec;
};
diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp
new file mode 100644
index 0000000000..786dc64452
--- /dev/null
+++ b/indra/llrender/llfontfreetype.cpp
@@ -0,0 +1,568 @@
+/**
+ * @file llfontfreetype.cpp
+ * @brief Freetype font library wrapper
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llfontfreetype.h"
+#include "llfontgl.h"
+
+// Freetype stuff
+#include <ft2build.h>
+
+// For some reason, this won't work if it's not wrapped in the ifdef
+#ifdef FT_FREETYPE_H
+#include FT_FREETYPE_H
+#endif
+
+#include "llerror.h"
+#include "llimage.h"
+//#include "llimagej2c.h"
+#include "llmath.h" // Linden math
+#include "llstring.h"
+//#include "imdebug.h"
+#include "llfontbitmapcache.h"
+#include "llgl.h"
+
+FT_Render_Mode gFontRenderMode = FT_RENDER_MODE_NORMAL;
+
+LLFontManager *gFontManagerp = NULL;
+
+FT_Library gFTLibrary = NULL;
+
+//static
+void LLFontManager::initClass()
+{
+ gFontManagerp = new LLFontManager;
+}
+
+//static
+void LLFontManager::cleanupClass()
+{
+ delete gFontManagerp;
+ gFontManagerp = NULL;
+}
+
+LLFontManager::LLFontManager()
+{
+ int error;
+ error = FT_Init_FreeType(&gFTLibrary);
+ if (error)
+ {
+ // Clean up freetype libs.
+ llerrs << "Freetype initialization failure!" << llendl;
+ FT_Done_FreeType(gFTLibrary);
+ }
+}
+
+LLFontManager::~LLFontManager()
+{
+ FT_Done_FreeType(gFTLibrary);
+}
+
+
+LLFontGlyphInfo::LLFontGlyphInfo(U32 index)
+: mGlyphIndex(index),
+ mXBitmapOffset(0), // Offset to the origin in the bitmap
+ mYBitmapOffset(0), // Offset to the origin in the bitmap
+ mXBearing(0), // Distance from baseline to left in pixels
+ mYBearing(0), // Distance from baseline to top in pixels
+ mWidth(0), // In pixels
+ mHeight(0), // In pixels
+ mXAdvance(0.f), // In pixels
+ mYAdvance(0.f) // In pixels
+{
+}
+
+LLFontFreetype::LLFontFreetype()
+: mFontBitmapCachep(new LLFontBitmapCache),
+ mValid(FALSE),
+ mAscender(0.f),
+ mDescender(0.f),
+ mLineHeight(0.f),
+ mIsFallback(FALSE),
+ mFTFace(NULL),
+ mRenderGlyphCount(0),
+ mAddGlyphCount(0),
+ mPointSize(0)
+{
+}
+
+
+LLFontFreetype::~LLFontFreetype()
+{
+ // Clean up freetype libs.
+ if (mFTFace)
+ FT_Done_Face(mFTFace);
+ mFTFace = NULL;
+
+ // Delete glyph info
+ std::for_each(mCharGlyphInfoMap.begin(), mCharGlyphInfoMap.end(), DeletePairedPointer());
+
+ // mFontBitmapCachep will be cleaned up by LLPointer destructor.
+ // mFallbackFonts cleaned up by LLPointer destructor
+}
+
+BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback)
+{
+ // Don't leak face objects. This is also needed to deal with
+ // changed font file names.
+ if (mFTFace)
+ {
+ FT_Done_Face(mFTFace);
+ mFTFace = NULL;
+ }
+
+ int error;
+
+ error = FT_New_Face( gFTLibrary,
+ filename.c_str(),
+ 0,
+ &mFTFace );
+
+ if (error)
+ {
+ return FALSE;
+ }
+
+ mIsFallback = is_fallback;
+ F32 pixels_per_em = (point_size / 72.f)*vert_dpi; // Size in inches * dpi
+
+ error = FT_Set_Char_Size(mFTFace, /* handle to face object */
+ 0, /* char_width in 1/64th of points */
+ (S32)(point_size*64), /* char_height in 1/64th of points */
+ (U32)horz_dpi, /* horizontal device resolution */
+ (U32)vert_dpi); /* vertical device resolution */
+
+ if (error)
+ {
+ // Clean up freetype libs.
+ FT_Done_Face(mFTFace);
+ mFTFace = NULL;
+ return FALSE;
+ }
+
+ F32 y_max, y_min, x_max, x_min;
+ F32 ems_per_unit = 1.f/ mFTFace->units_per_EM;
+ F32 pixels_per_unit = pixels_per_em * ems_per_unit;
+
+ // Get size of bbox in pixels
+ y_max = mFTFace->bbox.yMax * pixels_per_unit;
+ y_min = mFTFace->bbox.yMin * pixels_per_unit;
+ x_max = mFTFace->bbox.xMax * pixels_per_unit;
+ x_min = mFTFace->bbox.xMin * pixels_per_unit;
+ mAscender = mFTFace->ascender * pixels_per_unit;
+ mDescender = -mFTFace->descender * pixels_per_unit;
+ mLineHeight = mFTFace->height * pixels_per_unit;
+
+ S32 max_char_width = llround(0.5f + (x_max - x_min));
+ S32 max_char_height = llround(0.5f + (y_max - y_min));
+
+ mFontBitmapCachep->init(components, max_char_width, max_char_height);
+
+ if (!mFTFace->charmap)
+ {
+ //llinfos << " no unicode encoding, set whatever encoding there is..." << llendl;
+ FT_Set_Charmap(mFTFace, mFTFace->charmaps[0]);
+ }
+
+ if (!mIsFallback)
+ {
+ // Add the default glyph
+ addGlyphFromFont(this, 0, 0);
+ }
+
+ mName = filename;
+ mPointSize = point_size;
+
+ mStyle = LLFontGL::NORMAL;
+ if(mFTFace->style_flags & FT_STYLE_FLAG_BOLD)
+ {
+ mStyle |= LLFontGL::BOLD;
+ mStyle &= ~LLFontGL::NORMAL;
+ }
+
+ if(mFTFace->style_flags & FT_STYLE_FLAG_ITALIC)
+ {
+ mStyle |= LLFontGL::ITALIC;
+ mStyle &= ~LLFontGL::NORMAL;
+ }
+
+ return TRUE;
+}
+
+void LLFontFreetype::setFallbackFonts(const font_vector_t &font)
+{
+ mFallbackFonts = font;
+}
+
+const LLFontFreetype::font_vector_t &LLFontFreetype::getFallbackFonts() const
+{
+ return mFallbackFonts;
+}
+
+F32 LLFontFreetype::getLineHeight() const
+{
+ return mLineHeight;
+}
+
+F32 LLFontFreetype::getAscenderHeight() const
+{
+ return mAscender;
+}
+
+F32 LLFontFreetype::getDescenderHeight() const
+{
+ return mDescender;
+}
+
+F32 LLFontFreetype::getXAdvance(llwchar wch) const
+{
+ if (mFTFace == NULL)
+ return 0.0;
+
+ // Return existing info only if it is current
+ LLFontGlyphInfo* gi = getGlyphInfo(wch);
+ if (gi)
+ {
+ return gi->mXAdvance;
+ }
+ else
+ {
+ gi = get_if_there(mCharGlyphInfoMap, (llwchar)0, (LLFontGlyphInfo*)NULL);
+ if (gi)
+ {
+ return gi->mXAdvance;
+ }
+ }
+
+ // Last ditch fallback - no glyphs defined at all.
+ return (F32)mFontBitmapCachep->getMaxCharWidth();
+}
+
+F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
+{
+ if (mFTFace == NULL)
+ return 0.0;
+
+ //llassert(!mIsFallback);
+ LLFontGlyphInfo* left_glyph_info = getGlyphInfo(char_left);;
+ U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0;
+ // Kern this puppy.
+ LLFontGlyphInfo* right_glyph_info = getGlyphInfo(char_right);
+ U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0;
+
+ FT_Vector delta;
+
+ llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta));
+
+ return delta.x*(1.f/64.f);
+}
+
+BOOL LLFontFreetype::hasGlyph(llwchar wch) const
+{
+ llassert(!mIsFallback);
+ return(mCharGlyphInfoMap.find(wch) != mCharGlyphInfoMap.end());
+}
+
+LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch) const
+{
+ if (mFTFace == NULL)
+ return FALSE;
+
+ llassert(!mIsFallback);
+ //lldebugs << "Adding new glyph for " << wch << " to font" << llendl;
+
+ FT_UInt glyph_index;
+
+ // Initialize char to glyph map
+ glyph_index = FT_Get_Char_Index(mFTFace, wch);
+ if (glyph_index == 0)
+ {
+ //llinfos << "Trying to add glyph from fallback font!" << llendl;
+ font_vector_t::const_iterator iter;
+ for(iter = mFallbackFonts.begin(); iter != mFallbackFonts.end(); iter++)
+ {
+ glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch);
+ if (glyph_index)
+ {
+ return addGlyphFromFont(*iter, wch, glyph_index);
+ }
+ }
+ }
+
+ char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch);
+ if (iter == mCharGlyphInfoMap.end())
+ {
+ return addGlyphFromFont(this, wch, glyph_index);
+ }
+ return NULL;
+}
+
+LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const
+{
+ if (mFTFace == NULL)
+ return NULL;
+
+ llassert(!mIsFallback);
+ fontp->renderGlyph(glyph_index);
+ S32 width = fontp->mFTFace->glyph->bitmap.width;
+ S32 height = fontp->mFTFace->glyph->bitmap.rows;
+
+ S32 pos_x, pos_y;
+ S32 bitmap_num;
+ mFontBitmapCachep->nextOpenPos(width, pos_x, pos_y, bitmap_num);
+ mAddGlyphCount++;
+
+ LLFontGlyphInfo* gi = new LLFontGlyphInfo(glyph_index);
+ gi->mXBitmapOffset = pos_x;
+ gi->mYBitmapOffset = pos_y;
+ gi->mBitmapNum = bitmap_num;
+ gi->mWidth = width;
+ gi->mHeight = height;
+ gi->mXBearing = fontp->mFTFace->glyph->bitmap_left;
+ gi->mYBearing = fontp->mFTFace->glyph->bitmap_top;
+ // Convert these from 26.6 units to float pixels.
+ gi->mXAdvance = fontp->mFTFace->glyph->advance.x / 64.f;
+ gi->mYAdvance = fontp->mFTFace->glyph->advance.y / 64.f;
+
+ insertGlyphInfo(wch, gi);
+
+ llassert(fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO
+ || fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY);
+
+ if (fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO
+ || fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY)
+ {
+ U8 *buffer_data = fontp->mFTFace->glyph->bitmap.buffer;
+ S32 buffer_row_stride = fontp->mFTFace->glyph->bitmap.pitch;
+ U8 *tmp_graydata = NULL;
+
+ if (fontp->mFTFace->glyph->bitmap.pixel_mode
+ == FT_PIXEL_MODE_MONO)
+ {
+ // need to expand 1-bit bitmap to 8-bit graymap.
+ tmp_graydata = new U8[width * height];
+ S32 xpos, ypos;
+ for (ypos = 0; ypos < height; ++ypos)
+ {
+ S32 bm_row_offset = buffer_row_stride * ypos;
+ for (xpos = 0; xpos < width; ++xpos)
+ {
+ U32 bm_col_offsetbyte = xpos / 8;
+ U32 bm_col_offsetbit = 7 - (xpos % 8);
+ U32 bit =
+ !!(buffer_data[bm_row_offset
+ + bm_col_offsetbyte
+ ] & (1 << bm_col_offsetbit) );
+ tmp_graydata[width*ypos + xpos] =
+ 255 * bit;
+ }
+ }
+ // use newly-built graymap.
+ buffer_data = tmp_graydata;
+ buffer_row_stride = width;
+ }
+
+ switch (mFontBitmapCachep->getNumComponents())
+ {
+ case 1:
+ mFontBitmapCachep->getImageRaw(bitmap_num)->setSubImage(pos_x,
+ pos_y,
+ width,
+ height,
+ buffer_data,
+ buffer_row_stride,
+ TRUE);
+ break;
+ case 2:
+ setSubImageLuminanceAlpha(pos_x,
+ pos_y,
+ bitmap_num,
+ width,
+ height,
+ buffer_data,
+ buffer_row_stride);
+ break;
+ default:
+ break;
+ }
+
+ if (tmp_graydata)
+ delete[] tmp_graydata;
+ } else {
+ // we don't know how to handle this pixel format from FreeType;
+ // omit it from the font-image.
+ }
+
+ LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_num);
+ LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num);
+ image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight());
+
+ return gi;
+}
+
+LLFontGlyphInfo* LLFontFreetype::getGlyphInfo(llwchar wch) const
+{
+ char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch);
+ if (iter != mCharGlyphInfoMap.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ // this glyph doesn't yet exist, so render it and return the result
+ return addGlyph(wch);
+ }
+}
+
+void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const
+{
+ char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch);
+ if (iter != mCharGlyphInfoMap.end())
+ {
+ delete iter->second;
+ iter->second = gi;
+ }
+ else
+ {
+ mCharGlyphInfoMap[wch] = gi;
+ }
+}
+
+void LLFontFreetype::renderGlyph(U32 glyph_index) const
+{
+ if (mFTFace == NULL)
+ return;
+
+ int error = FT_Load_Glyph(mFTFace, glyph_index, FT_LOAD_DEFAULT );
+ llassert(!error);
+
+ error = FT_Render_Glyph(mFTFace->glyph, gFontRenderMode);
+
+ mRenderGlyphCount++;
+
+ llassert(!error);
+}
+
+void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi)
+{
+ resetBitmapCache();
+ loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mFontBitmapCachep->getNumComponents(), mIsFallback);
+ if (!mIsFallback)
+ {
+ // This is the head of the list - need to rebuild ourself and all fallbacks.
+ if (mFallbackFonts.empty())
+ {
+ llwarns << "LLFontGL::reset(), no fallback fonts present" << llendl;
+ }
+ else
+ {
+ for(font_vector_t::iterator it = mFallbackFonts.begin();
+ it != mFallbackFonts.end();
+ ++it)
+ {
+ (*it)->reset(vert_dpi, horz_dpi);
+ }
+ }
+ }
+}
+
+void LLFontFreetype::resetBitmapCache()
+{
+ for_each(mCharGlyphInfoMap.begin(), mCharGlyphInfoMap.end(), DeletePairedPointer());
+ mCharGlyphInfoMap.clear();
+ mFontBitmapCachep->reset();
+
+ // Add the empty glyph
+ addGlyphFromFont(this, 0, 0);
+}
+
+void LLFontFreetype::destroyGL()
+{
+ mFontBitmapCachep->destroyGL();
+}
+
+const std::string &LLFontFreetype::getName() const
+{
+ return mName;
+}
+
+const LLPointer<LLFontBitmapCache> LLFontFreetype::getFontBitmapCache() const
+{
+ return mFontBitmapCachep;
+}
+
+void LLFontFreetype::setStyle(U8 style)
+{
+ mStyle = style;
+}
+
+U8 LLFontFreetype::getStyle() const
+{
+ return mStyle;
+}
+
+void LLFontFreetype::setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride) const
+{
+ LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num);
+
+ llassert(!mIsFallback);
+ llassert(image_raw && (image_raw->getComponents() == 2));
+
+
+ U8 *target = image_raw->getData();
+
+ if (!data)
+ {
+ return;
+ }
+
+ if (0 == stride)
+ stride = width;
+
+ U32 i, j;
+ U32 to_offset;
+ U32 from_offset;
+ U32 target_width = image_raw->getWidth();
+ for (i = 0; i < height; i++)
+ {
+ to_offset = (y + i)*target_width + x;
+ from_offset = (height - 1 - i)*stride;
+ for (j = 0; j < width; j++)
+ {
+ *(target + to_offset*2 + 1) = *(data + from_offset);
+ to_offset++;
+ from_offset++;
+ }
+ }
+}
+
diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h
new file mode 100644
index 0000000000..7a5d029038
--- /dev/null
+++ b/indra/llrender/llfontfreetype.h
@@ -0,0 +1,180 @@
+/**
+ * @file llfontfreetype.h
+ * @brief Font library wrapper
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFONTFREETYPE_H
+#define LL_LLFONTFREETYPE_H
+
+#include <map>
+#include "llpointer.h"
+#include "llstl.h"
+
+#include "llimagegl.h"
+#include "llfontbitmapcache.h"
+
+// Hack. FT_Face is just a typedef for a pointer to a struct,
+// but there's no simple forward declarations file for FreeType,
+// and the main include file is 200K.
+// We'll forward declare the struct here. JC
+struct FT_FaceRec_;
+typedef struct FT_FaceRec_* LLFT_Face;
+
+class LLFontManager
+{
+public:
+ static void initClass();
+ static void cleanupClass();
+
+private:
+ LLFontManager();
+ ~LLFontManager();
+};
+
+struct LLFontGlyphInfo
+{
+ LLFontGlyphInfo(U32 index);
+
+ U32 mGlyphIndex;
+
+ // Metrics
+ S32 mWidth; // In pixels
+ S32 mHeight; // In pixels
+ F32 mXAdvance; // In pixels
+ F32 mYAdvance; // In pixels
+
+ // Information for actually rendering
+ S32 mXBitmapOffset; // Offset to the origin in the bitmap
+ S32 mYBitmapOffset; // Offset to the origin in the bitmap
+ S32 mXBearing; // Distance from baseline to left in pixels
+ S32 mYBearing; // Distance from baseline to top in pixels
+ S32 mBitmapNum; // Which bitmap in the bitmap cache contains this glyph
+};
+
+extern LLFontManager *gFontManagerp;
+
+class LLFontFreetype : public LLRefCount
+{
+public:
+ LLFontFreetype();
+ ~LLFontFreetype();
+
+ // is_fallback should be true for fallback fonts that aren't used
+ // to render directly (Unicode backup, primarily)
+ BOOL loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback);
+
+ typedef std::vector<LLPointer<LLFontFreetype> > font_vector_t;
+
+ void setFallbackFonts(const font_vector_t &font);
+ const font_vector_t &getFallbackFonts() const;
+
+ // Global font metrics - in units of pixels
+ F32 getLineHeight() const;
+ F32 getAscenderHeight() const;
+ F32 getDescenderHeight() const;
+
+
+// For a lowercase "g":
+//
+// ------------------------------
+// ^ ^
+// | |
+// xxx x |Ascender
+// x x v |
+// --------- xxxx-------------- Baseline
+// ^ x |
+// | Descender x |
+// v xxxx |LineHeight
+// ----------------------- |
+// v
+// ------------------------------
+
+ enum
+ {
+ FIRST_CHAR = 32,
+ NUM_CHARS = 127 - 32,
+ LAST_CHAR_BASIC = 127,
+
+ // Need full 8-bit ascii range for spanish
+ NUM_CHARS_FULL = 255 - 32,
+ LAST_CHAR_FULL = 255
+ };
+
+ F32 getXAdvance(llwchar wc) const;
+ F32 getXKerning(llwchar char_left, llwchar char_right) const; // Get the kerning between the two characters
+
+ LLFontGlyphInfo* getGlyphInfo(llwchar wch) const;
+
+ void reset(F32 vert_dpi, F32 horz_dpi);
+
+ void destroyGL();
+
+ const std::string& getName() const;
+
+ const LLPointer<LLFontBitmapCache> getFontBitmapCache() const;
+
+ void setStyle(U8 style);
+ U8 getStyle() const;
+
+private:
+ void resetBitmapCache();
+ void setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride = 0) const;
+ BOOL hasGlyph(llwchar wch) const; // Has a glyph for this character
+ LLFontGlyphInfo* addGlyph(llwchar wch) const; // Add a new character to the font if necessary
+ LLFontGlyphInfo* addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const; // Add a glyph from this font to the other (returns the glyph_index, 0 if not found)
+ void renderGlyph(U32 glyph_index) const;
+ void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const;
+
+ std::string mName;
+
+ U8 mStyle;
+
+ F32 mPointSize;
+ F32 mAscender;
+ F32 mDescender;
+ F32 mLineHeight;
+
+ LLFT_Face mFTFace;
+
+ BOOL mIsFallback;
+ font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars)
+
+ BOOL mValid;
+
+ typedef std::map<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t;
+ mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap
+
+ mutable LLPointer<LLFontBitmapCache> mFontBitmapCachep;
+
+ mutable S32 mRenderGlyphCount;
+ mutable S32 mAddGlyphCount;
+};
+
+#endif // LL_FONTFREETYPE_H
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index beecb6b7c1..1de1d6ded4 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -32,16 +32,22 @@
#include "linden_common.h"
-#include <boost/tokenizer.hpp>
-
-#include "llfont.h"
#include "llfontgl.h"
+
+// Linden library includes
+#include "llfontfreetype.h"
#include "llfontbitmapcache.h"
#include "llfontregistry.h"
#include "llgl.h"
+#include "llimagegl.h"
#include "llrender.h"
-#include "v4color.h"
#include "llstl.h"
+#include "v4color.h"
+#include "lltexture.h"
+#include "lldir.h"
+
+// Third party library includes
+#include <boost/tokenizer.hpp>
const S32 BOLD_OFFSET = 1;
@@ -68,320 +74,52 @@ const F32 PIXEL_CORRECTION_DISTANCE = 0.01f;
const F32 PAD_UVY = 0.5f; // half of vertical padding between glyphs in the glyph texture
const F32 DROP_SHADOW_SOFT_STRENGTH = 0.3f;
-F32 llfont_round_x(F32 x)
+static F32 llfont_round_x(F32 x)
{
//return llfloor((x-LLFontGL::sCurOrigin.mX)/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleX+LLFontGL::sCurOrigin.mX;
//return llfloor(x/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleY;
return x;
}
-F32 llfont_round_y(F32 y)
+static F32 llfont_round_y(F32 y)
{
//return llfloor((y-LLFontGL::sCurOrigin.mY)/LLFontGL::sScaleY+0.5f)*LLFontGL::sScaleY+LLFontGL::sCurOrigin.mY;
//return llfloor(y+0.5f);
return y;
}
-// static
-U8 LLFontGL::getStyleFromString(const std::string &style)
-{
- S32 ret = 0;
- if (style.find("NORMAL") != style.npos)
- {
- ret |= NORMAL;
- }
- if (style.find("BOLD") != style.npos)
- {
- ret |= BOLD;
- }
- if (style.find("ITALIC") != style.npos)
- {
- ret |= ITALIC;
- }
- if (style.find("UNDERLINE") != style.npos)
- {
- ret |= UNDERLINE;
- }
- if (style.find("SHADOW") != style.npos)
- {
- ret |= DROP_SHADOW;
- }
- if (style.find("SOFT_SHADOW") != style.npos)
- {
- ret |= DROP_SHADOW_SOFT;
- }
- return ret;
-}
-
LLFontGL::LLFontGL()
- : LLFont()
{
- clearEmbeddedChars();
-}
-
-LLFontGL::LLFontGL(const LLFontGL &source)
-{
- llerrs << "Not implemented!" << llendl;
}
LLFontGL::~LLFontGL()
{
- clearEmbeddedChars();
}
void LLFontGL::reset()
{
- if (!mIsFallback)
- {
- // This is the head of the list - need to rebuild ourself and all fallbacks.
- loadFace(mName,mPointSize,sVertDPI,sHorizDPI,mFontBitmapCachep->getNumComponents(),mIsFallback);
- if (mFallbackFontp==NULL)
- {
- llwarns << "LLFontGL::reset(), no fallback fonts present" << llendl;
- }
- else
- {
- for (LLFontList::iterator it = mFallbackFontp->begin();
- it != mFallbackFontp->end();
- ++it)
- {
- (*it)->reset();
- }
- }
- }
- resetBitmapCache();
-}
-
-// static
-std::string LLFontGL::getFontPathSystem()
-{
- std::string system_path;
-
- // Try to figure out where the system's font files are stored.
- char *system_root = NULL;
-#if LL_WINDOWS
- system_root = getenv("SystemRoot"); /* Flawfinder: ignore */
- if (!system_root)
- {
- llwarns << "SystemRoot not found, attempting to load fonts from default path." << llendl;
- }
-#endif
-
- if (system_root)
- {
- system_path = llformat("%s/fonts/", system_root);
- }
- else
- {
-#if LL_WINDOWS
- // HACK for windows 98/Me
- system_path = "/WINDOWS/FONTS/";
-#elif LL_DARWIN
- // HACK for Mac OS X
- system_path = "/System/Library/Fonts/";
-#endif
- }
- return system_path;
-}
-
-
-// static
-std::string LLFontGL::getFontPathLocal()
-{
- std::string local_path;
-
- // Backup files if we can't load from system fonts directory.
- // We could store this in an end-user writable directory to allow
- // end users to switch fonts.
- if (LLFontGL::sAppDir.length())
- {
- // use specified application dir to look for fonts
- local_path = LLFontGL::sAppDir + "/fonts/";
- }
- else
- {
- // assume working directory is executable directory
- local_path = "./fonts/";
- }
- return local_path;
-}
-
-bool findOrCreateFont(LLFontGL*& fontp, const LLFontDescriptor& desc)
-{
- // Don't delete existing fonts, if any, here, because they've
- // already been deleted by LLFontRegistry::clear()
- fontp = LLFontGL::getFont(desc);
- return (fontp != NULL);
-}
-
-// static
-BOOL LLFontGL::initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale,
- const std::string& app_dir,
- const std::vector<std::string>& xui_paths)
-{
- bool succ = true;
- sVertDPI = (F32)llfloor(screen_dpi * y_scale);
- sHorizDPI = (F32)llfloor(screen_dpi * x_scale);
- sScaleX = x_scale;
- sScaleY = y_scale;
- sAppDir = app_dir;
-
- // Font registry init
- if (!sFontRegistry)
- {
- sFontRegistry = new LLFontRegistry(xui_paths);
- sFontRegistry->parseFontInfo("fonts.xml");
- }
- else
- {
- sFontRegistry->reset();
- }
-
- // Force standard fonts to get generated up front.
- // This is primarily for error detection purposes.
- succ &= (NULL != getFontSansSerifSmall());
- succ &= (NULL != getFontSansSerif());
- succ &= (NULL != getFontSansSerifBig());
- succ &= (NULL != getFontSansSerifHuge());
- succ &= (NULL != getFontSansSerifBold());
- succ &= (NULL != getFontMonospace());
- succ &= (NULL != getFontExtChar());
-
- return succ;
-}
-
-
-
-// static
-void LLFontGL::destroyDefaultFonts()
-{
- // Remove the actual fonts.
- delete sFontRegistry;
- sFontRegistry = NULL;
-}
-
-//static
-void LLFontGL::destroyAllGL()
-{
- if (sFontRegistry)
- {
- sFontRegistry->destroyGL();
- }
+ mFontFreetype->reset(sVertDPI, sHorizDPI);
}
void LLFontGL::destroyGL()
{
- mFontBitmapCachep->destroyGL();
-}
-
-
-
-LLFontGL &LLFontGL::operator=(const LLFontGL &source)
-{
- llerrs << "Not implemented" << llendl;
- return *this;
-}
-
-BOOL LLFontGL::loadFace(const std::string& filename,
- const F32 point_size, const F32 vert_dpi, const F32 horz_dpi,
- const S32 components, BOOL is_fallback)
-{
- if (!LLFont::loadFace(filename, point_size, vert_dpi, horz_dpi, components, is_fallback))
- {
- return FALSE;
- }
- return TRUE;
-}
-
-//static
-LLFontGL* LLFontGL::getFontMonospace()
-{
- return getFont(LLFontDescriptor("Monospace","Monospace",0));
-}
-
-//static
-LLFontGL* LLFontGL::getFontSansSerifSmall()
-{
- return getFont(LLFontDescriptor("SansSerif","Small",0));
-}
-
-//static
-LLFontGL* LLFontGL::getFontSansSerif()
-{
- return getFont(LLFontDescriptor("SansSerif","Medium",0));
-}
-
-//static
-LLFontGL* LLFontGL::getFontSansSerifBig()
-{
- return getFont(LLFontDescriptor("SansSerif","Large",0));
+ mFontFreetype->destroyGL();
}
-//static
-LLFontGL* LLFontGL::getFontSansSerifHuge()
+BOOL LLFontGL::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback)
{
- return getFont(LLFontDescriptor("SansSerif","Huge",0));
-}
-
-//static
-LLFontGL* LLFontGL::getFontSansSerifBold()
-{
- return getFont(LLFontDescriptor("SansSerif","Medium",BOLD));
-}
-
-//static
-LLFontGL* LLFontGL::getFontExtChar()
-{
- return getFontSansSerif();
-}
-
-//static
-LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc)
-{
- return sFontRegistry->getFont(desc);
-}
-
-BOOL LLFontGL::addChar(const llwchar wch) const
-{
- if (!LLFont::addChar(wch))
+ if(mFontFreetype == reinterpret_cast<LLFontFreetype*>(NULL))
{
- return FALSE;
+ mFontFreetype = new LLFontFreetype;
}
- stop_glerror();
-
- LLFontGlyphInfo *glyph_info = getGlyphInfo(wch);
- U32 bitmap_num = glyph_info->mBitmapNum;
- LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_num);
- LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num);
- image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight());
- return TRUE;
+ return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, components, is_fallback);
}
+static LLFastTimer::DeclareTimer FTM_RENDER_FONTS("Fonts");
-S32 LLFontGL::renderUTF8(const std::string &text, const S32 offset,
- const F32 x, const F32 y,
- const LLColor4 &color,
- const HAlign halign, const VAlign valign,
- U8 style,
- const S32 max_chars, const S32 max_pixels,
- F32* right_x,
- BOOL use_ellipses) const
-{
- LLWString wstr = utf8str_to_wstring(text);
- return render(wstr, offset, x, y, color, halign, valign, style, max_chars, max_pixels, right_x, FALSE, use_ellipses);
-}
-
-S32 LLFontGL::render(const LLWString &wstr,
- const S32 begin_offset,
- const F32 x, const F32 y,
- const LLColor4 &color,
- const HAlign halign, const VAlign valign,
- U8 style,
- const S32 max_chars, S32 max_pixels,
- F32* right_x,
- BOOL use_embedded,
- BOOL use_ellipses) const
+S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
+ ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const
{
if(!sDisplayFont) //do not display texts
{
@@ -397,18 +135,19 @@ S32 LLFontGL::render(const LLWString &wstr,
S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX);
- // Strip off any style bits that are already accounted for by the font.
- style = style & (~getFontDesc().getStyle());
+ // determine which style flags need to be added programmatically by stripping off the
+ // style bits that are drawn by the underlying Freetype font
+ U8 style_to_add = (style | mFontDescriptor.getStyle()) & ~mFontFreetype->getStyle();
F32 drop_shadow_strength = 0.f;
- if (style & (DROP_SHADOW | DROP_SHADOW_SOFT))
+ if (shadow != NO_SHADOW)
{
F32 luminance;
color.calcHSL(NULL, NULL, &luminance);
drop_shadow_strength = clamp_rescale(luminance, 0.35f, 0.6f, 0.f, 1.f);
if (luminance < 0.35f)
{
- style = style & ~(DROP_SHADOW | DROP_SHADOW_SOFT);
+ shadow = NO_SHADOW;
}
}
@@ -421,7 +160,7 @@ S32 LLFontGL::render(const LLWString &wstr,
F32 pixel_offset_y = llround((F32)sCurOrigin.mY) - (sCurOrigin.mY);
gGL.translatef(-pixel_offset_x, -pixel_offset_y, 0.f);
- LLFastTimer t(LLFastTimer::FTM_RENDER_FONTS);
+ LLFastTimer t(FTM_RENDER_FONTS);
gGL.color4fv( color.mV );
@@ -450,13 +189,13 @@ S32 LLFontGL::render(const LLWString &wstr,
switch (valign)
{
case TOP:
- cur_y -= mAscender;
+ cur_y -= mFontFreetype->getAscenderHeight();
break;
case BOTTOM:
- cur_y += mDescender;
+ cur_y += mFontFreetype->getDescenderHeight();
break;
case VCENTER:
- cur_y -= ((mAscender - mDescender)/2.f);
+ cur_y -= (mFontFreetype->getAscenderHeight() - mFontFreetype->getDescenderHeight()) / 2.f;
break;
case BASELINE:
// Baseline, do nothing.
@@ -470,10 +209,10 @@ S32 LLFontGL::render(const LLWString &wstr,
case LEFT:
break;
case RIGHT:
- cur_x -= llmin(scaled_max_pixels, llround(getWidthF32(wstr.c_str(), 0, length) * sScaleX));
+ cur_x -= llmin(scaled_max_pixels, llround(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX));
break;
case HCENTER:
- cur_x -= llmin(scaled_max_pixels, llround(getWidthF32(wstr.c_str(), 0, length) * sScaleX)) / 2;
+ cur_x -= llmin(scaled_max_pixels, llround(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX)) / 2;
break;
default:
break;
@@ -482,19 +221,22 @@ S32 LLFontGL::render(const LLWString &wstr,
cur_render_y = cur_y;
cur_render_x = cur_x;
- F32 start_x = cur_x;
+ F32 start_x = llround(cur_x);
- F32 inv_width = 1.f / mFontBitmapCachep->getBitmapWidth();
- F32 inv_height = 1.f / mFontBitmapCachep->getBitmapHeight();
+ const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache();
- const S32 LAST_CHARACTER = LLFont::LAST_CHAR_FULL;
+ F32 inv_width = 1.f / font_bitmap_cache->getBitmapWidth();
+ F32 inv_height = 1.f / font_bitmap_cache->getBitmapHeight();
+
+ const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL;
BOOL draw_ellipses = FALSE;
- if (use_ellipses && halign == LEFT)
+ if (use_ellipses)
{
// check for too long of a string
- if (getWidthF32(wstr.c_str(), 0, max_chars) * sScaleX > scaled_max_pixels)
+ S32 string_width = llround(getWidthF32(wstr.c_str(), begin_offset, max_chars) * sScaleX);
+ if (string_width > scaled_max_pixels)
{
// use four dots for ellipsis width to generate padding
const LLWString dots(utf8str_to_wstring(std::string("....")));
@@ -511,135 +253,60 @@ S32 LLFontGL::render(const LLWString &wstr,
{
llwchar wch = wstr[i];
- // Handle embedded characters first, if they're enabled.
- // Embedded characters are a hack for notecards
- const embedded_data_t* ext_data = use_embedded ? getEmbeddedCharData(wch) : NULL;
- if (ext_data)
+ const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
+ if (!fgi)
{
- LLImageGL* ext_image = ext_data->mImage;
- const LLWString& label = ext_data->mLabel;
-
- F32 ext_height = (F32)ext_image->getHeight() * sScaleY;
-
- F32 ext_width = (F32)ext_image->getWidth() * sScaleX;
- F32 ext_advance = (EXT_X_BEARING * sScaleX) + ext_width;
-
- if (!label.empty())
- {
- ext_advance += (EXT_X_BEARING + getFontExtChar()->getWidthF32( label.c_str() )) * sScaleX;
- }
-
- if (start_x + scaled_max_pixels < cur_x + ext_advance)
- {
- // Not enough room for this character.
- break;
- }
-
- if (last_bound_texture != ext_image)
- {
- gGL.getTexUnit(0)->bind(ext_image);
- last_bound_texture = ext_image;
- }
-
- // snap origin to whole screen pixel
- const F32 ext_x = (F32)llround(cur_render_x + (EXT_X_BEARING * sScaleX));
- const F32 ext_y = (F32)llround(cur_render_y + (EXT_Y_BEARING * sScaleY + mAscender - mLineHeight));
-
- LLRectf uv_rect(0.f, 1.f, 1.f, 0.f);
- LLRectf screen_rect(ext_x, ext_y + ext_height, ext_x + ext_width, ext_y);
- drawGlyph(screen_rect, uv_rect, LLColor4::white, style, drop_shadow_strength);
-
- if (!label.empty())
- {
- gGL.pushMatrix();
- //glLoadIdentity();
- //gGL.translatef(sCurOrigin.mX, sCurOrigin.mY, 0.0f);
- //glScalef(sScaleX, sScaleY, 1.f);
- getFontExtChar()->render(label, 0,
- /*llfloor*/((ext_x + (F32)ext_image->getWidth() + EXT_X_BEARING) / sScaleX),
- /*llfloor*/(cur_y / sScaleY),
- color,
- halign, BASELINE, NORMAL, S32_MAX, S32_MAX, NULL,
- TRUE );
- gGL.popMatrix();
- }
-
- gGL.color4fv(color.mV);
-
- chars_drawn++;
- cur_x += ext_advance;
- if (((i + 1) < length) && wstr[i+1])
- {
- cur_x += EXT_KERNING * sScaleX;
- }
- cur_render_x = cur_x;
+ llerrs << "Missing Glyph Info" << llendl;
+ break;
}
- else
+ // Per-glyph bitmap texture.
+ LLImageGL *image_gl = mFontFreetype->getFontBitmapCache()->getImageGL(fgi->mBitmapNum);
+ if (last_bound_texture != image_gl)
{
- if (!hasGlyph(wch))
- {
- addChar(wch);
- }
-
- const LLFontGlyphInfo* fgi= getGlyphInfo(wch);
- if (!fgi)
- {
- llerrs << "Missing Glyph Info" << llendl;
- break;
- }
- // Per-glyph bitmap texture.
- LLImageGL *image_gl = mFontBitmapCachep->getImageGL(fgi->mBitmapNum);
- if (last_bound_texture != image_gl)
- {
- gGL.getTexUnit(0)->bind(image_gl);
- last_bound_texture = image_gl;
- }
-
- if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth))
- {
- // Not enough room for this character.
- break;
- }
-
- // Draw the text at the appropriate location
- //Specify vertices and texture coordinates
- LLRectf uv_rect((fgi->mXBitmapOffset) * inv_width,
- (fgi->mYBitmapOffset + fgi->mHeight + PAD_UVY) * inv_height,
- (fgi->mXBitmapOffset + fgi->mWidth) * inv_width,
- (fgi->mYBitmapOffset - PAD_UVY) * inv_height);
- // snap glyph origin to whole screen pixel
- LLRectf screen_rect(llround(cur_render_x + (F32)fgi->mXBearing),
- llround(cur_render_y + (F32)fgi->mYBearing),
- llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth,
- llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight);
-
- drawGlyph(screen_rect, uv_rect, color, style, drop_shadow_strength);
-
- chars_drawn++;
- cur_x += fgi->mXAdvance;
- cur_y += fgi->mYAdvance;
-
- llwchar next_char = wstr[i+1];
- if (next_char && (next_char < LAST_CHARACTER))
- {
- // Kern this puppy.
- if (!hasGlyph(next_char))
- {
- addChar(next_char);
- }
- cur_x += getXKerning(wch, next_char);
- }
+ gGL.getTexUnit(0)->bind(image_gl);
+ last_bound_texture = image_gl;
+ }
- // Round after kerning.
- // Must do this to cur_x, not just to cur_render_x, otherwise you
- // will squish sub-pixel kerned characters too close together.
- // For example, "CCCCC" looks bad.
- cur_x = (F32)llfloor(cur_x + 0.5f);
- //cur_y = (F32)llfloor(cur_y + 0.5f);
+ if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth))
+ {
+ // Not enough room for this character.
+ break;
+ }
- cur_render_x = cur_x;
- cur_render_y = cur_y;
+ // Draw the text at the appropriate location
+ //Specify vertices and texture coordinates
+ LLRectf uv_rect((fgi->mXBitmapOffset) * inv_width,
+ (fgi->mYBitmapOffset + fgi->mHeight + PAD_UVY) * inv_height,
+ (fgi->mXBitmapOffset + fgi->mWidth) * inv_width,
+ (fgi->mYBitmapOffset - PAD_UVY) * inv_height);
+ // snap glyph origin to whole screen pixel
+ LLRectf screen_rect(llround(cur_render_x + (F32)fgi->mXBearing),
+ llround(cur_render_y + (F32)fgi->mYBearing),
+ llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth,
+ llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight);
+
+ drawGlyph(screen_rect, uv_rect, color, style_to_add, shadow, drop_shadow_strength);
+
+ chars_drawn++;
+ cur_x += fgi->mXAdvance;
+ cur_y += fgi->mYAdvance;
+
+ llwchar next_char = wstr[i+1];
+ if (next_char && (next_char < LAST_CHARACTER))
+ {
+ // Kern this puppy.
+ cur_x += mFontFreetype->getXKerning(wch, next_char);
}
+
+ // Round after kerning.
+ // Must do this to cur_x, not just to cur_render_x, otherwise you
+ // will squish sub-pixel kerned characters too close together.
+ // For example, "CCCCC" looks bad.
+ cur_x = (F32)llround(cur_x);
+ //cur_y = (F32)llround(cur_y);
+
+ cur_render_x = cur_x;
+ cur_render_y = cur_y;
}
if (right_x)
@@ -647,18 +314,20 @@ S32 LLFontGL::render(const LLWString &wstr,
*right_x = cur_x / sScaleX;
}
- if (style & UNDERLINE)
+ if (style_to_add & UNDERLINE)
{
+ F32 descender = mFontFreetype->getDescenderHeight();
+
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.begin(LLRender::LINES);
- gGL.vertex2f(start_x, cur_y - (mDescender));
- gGL.vertex2f(cur_x, cur_y - (mDescender));
+ gGL.vertex2f(start_x, cur_y - (descender));
+ gGL.vertex2f(cur_x, cur_y - (descender));
gGL.end();
}
- // *FIX: get this working in all alignment cases, etc.
if (draw_ellipses)
{
+
// recursively render ellipses at end of string
// we've already reserved enough room
gGL.pushMatrix();
@@ -670,7 +339,8 @@ S32 LLFontGL::render(const LLWString &wstr,
cur_x / sScaleX, (F32)y,
color,
LEFT, valign,
- style,
+ style_to_add,
+ shadow,
S32_MAX, max_pixels,
right_x,
FALSE);
@@ -682,6 +352,41 @@ S32 LLFontGL::render(const LLWString &wstr,
return chars_drawn;
}
+S32 LLFontGL::render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const
+{
+ return render(text, begin_offset, x, y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
+}
+
+S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const
+{
+ return render(utf8str_to_wstring(text), begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses);
+}
+
+S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color) const
+{
+ return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
+}
+
+S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow) const
+{
+ return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, halign, valign, style, shadow, S32_MAX, S32_MAX, NULL, FALSE);
+}
+
+// font metrics - override for LLFontFreetype that returns units of virtual pixels
+F32 LLFontGL::getLineHeight() const
+{
+ return (F32)llround(mFontFreetype->getLineHeight() / sScaleY);
+}
+
+F32 LLFontGL::getAscenderHeight() const
+{
+ return (F32)llround(mFontFreetype->getAscenderHeight() / sScaleY);
+}
+
+F32 LLFontGL::getDescenderHeight() const
+{
+ return (F32)llround(mFontFreetype->getDescenderHeight() / sScaleY);
+}
S32 LLFontGL::getWidth(const std::string& utf8text) const
{
@@ -694,15 +399,15 @@ S32 LLFontGL::getWidth(const llwchar* wchars) const
return getWidth(wchars, 0, S32_MAX);
}
-S32 LLFontGL::getWidth(const std::string& utf8text, const S32 begin_offset, const S32 max_chars) const
+S32 LLFontGL::getWidth(const std::string& utf8text, S32 begin_offset, S32 max_chars) const
{
LLWString wtext = utf8str_to_wstring(utf8text);
return getWidth(wtext.c_str(), begin_offset, max_chars);
}
-S32 LLFontGL::getWidth(const llwchar* wchars, const S32 begin_offset, const S32 max_chars, BOOL use_embedded) const
+S32 LLFontGL::getWidth(const llwchar* wchars, S32 begin_offset, S32 max_chars) const
{
- F32 width = getWidthF32(wchars, begin_offset, max_chars, use_embedded);
+ F32 width = getWidthF32(wchars, begin_offset, max_chars);
return llround(width);
}
@@ -717,62 +422,57 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars) const
return getWidthF32(wchars, 0, S32_MAX);
}
-F32 LLFontGL::getWidthF32(const std::string& utf8text, const S32 begin_offset, const S32 max_chars ) const
+F32 LLFontGL::getWidthF32(const std::string& utf8text, S32 begin_offset, S32 max_chars ) const
{
LLWString wtext = utf8str_to_wstring(utf8text);
return getWidthF32(wtext.c_str(), begin_offset, max_chars);
}
-F32 LLFontGL::getWidthF32(const llwchar* wchars, const S32 begin_offset, const S32 max_chars, BOOL use_embedded) const
+F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars) const
{
- const S32 LAST_CHARACTER = LLFont::LAST_CHAR_FULL;
+ const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL;
F32 cur_x = 0;
const S32 max_index = begin_offset + max_chars;
- for (S32 i = begin_offset; i < max_index; i++)
+
+ F32 width_padding = 0.f;
+ for (S32 i = begin_offset; i < max_index && wchars[i] != 0; i++)
{
- const llwchar wch = wchars[i];
- if (wch == 0)
- {
- break; // done
- }
- const embedded_data_t* ext_data = use_embedded ? getEmbeddedCharData(wch) : NULL;
- if (ext_data)
- {
- // Handle crappy embedded hack
- cur_x += getEmbeddedCharAdvance(ext_data);
+ llwchar wch = wchars[i];
- if( ((i+1) < max_chars) && (i+1 < max_index))
- {
- cur_x += EXT_KERNING * sScaleX;
- }
- }
- else
- {
- cur_x += getXAdvance(wch);
- llwchar next_char = wchars[i+1];
+ const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
- if (((i + 1) < max_chars)
- && next_char
- && (next_char < LAST_CHARACTER))
- {
- // Kern this puppy.
- cur_x += getXKerning(wch, next_char);
- }
+ F32 advance = mFontFreetype->getXAdvance(wch);
+
+ // for the last character we want to measure the greater of its width and xadvance values
+ // so keep track of the difference between these values for the each character we measure
+ // so we can fix things up at the end
+ width_padding = llmax( 0.f, // always use positive padding amount
+ width_padding - advance, // previous padding left over after advance of current character
+ (F32)(fgi->mWidth + fgi->mXBearing) - advance); // difference between width of this character and advance to next character
+
+ cur_x += advance;
+ llwchar next_char = wchars[i+1];
+
+ if (((i + 1) < begin_offset + max_chars)
+ && next_char
+ && (next_char < LAST_CHARACTER))
+ {
+ // Kern this puppy.
+ cur_x += mFontFreetype->getXKerning(wch, next_char);
}
// Round after kerning.
- cur_x = (F32)llfloor(cur_x + 0.5f);
+ cur_x = (F32)llround(cur_x);
}
+ // add in extra pixels for last character's width past its xadvance
+ cur_x += width_padding;
+
return cur_x / sScaleX;
}
-
-
// Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels
-S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars,
- BOOL end_on_word_boundary, const BOOL use_embedded,
- F32* drawn_pixels) const
+S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars, EWordWrapStyle end_on_word_boundary) const
{
if (!wchars || !wchars[0] || max_chars == 0)
{
@@ -789,7 +489,9 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
S32 start_of_last_word = 0;
BOOL in_word = FALSE;
- F32 scaled_max_pixels = (F32)llceil(max_pixels * sScaleX);
+ // avoid S32 overflow when max_pixels == S32_MAX by staying in floating point
+ F32 scaled_max_pixels = ceil(max_pixels * sScaleX);
+ F32 width_padding = 0.f;
S32 i;
for (i=0; (i < max_chars); i++)
@@ -802,85 +504,86 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
break;
}
- const embedded_data_t* ext_data = use_embedded ? getEmbeddedCharData(wch) : NULL;
- if (ext_data)
+ if (in_word)
{
- if (in_word)
- {
- in_word = FALSE;
- }
- else
- {
- start_of_last_word = i;
- }
- cur_x += getEmbeddedCharAdvance(ext_data);
-
- if (scaled_max_pixels < cur_x)
+ if (iswspace(wch))
{
- clip = TRUE;
- break;
- }
-
- if (((i+1) < max_chars) && wchars[i+1])
- {
- cur_x += EXT_KERNING * sScaleX;
- }
-
- if( scaled_max_pixels < cur_x )
- {
- clip = TRUE;
- break;
- }
- }
- else
- {
- if (in_word)
- {
- if (iswspace(wch))
+ if(wch !=(0x00A0))
{
in_word = FALSE;
}
}
- else
+ if (iswindividual(wch))
{
- start_of_last_word = i;
- if (!iswspace(wch))
+ if (iswpunct(wchars[i+1]))
{
- in_word = TRUE;
+ in_word=TRUE;
+ }
+ else
+ {
+ in_word=FALSE;
+ start_of_last_word = i;
}
}
-
- cur_x += getXAdvance(wch);
-
- if (scaled_max_pixels < cur_x)
+ }
+ else
+ {
+ start_of_last_word = i;
+ if (!iswspace(wch)||!iswindividual(wch))
{
- clip = TRUE;
- break;
+ in_word = TRUE;
}
+ }
- if (((i+1) < max_chars) && wchars[i+1])
- {
- // Kern this puppy.
- cur_x += getXKerning(wch, wchars[i+1]);
- }
+ LLFontGlyphInfo* fgi = mFontFreetype->getGlyphInfo(wch);
+
+ // account for glyphs that run beyond the starting point for the next glyphs
+ width_padding = llmax( 0.f, // always use positive padding amount
+ width_padding - fgi->mXAdvance, // previous padding left over after advance of current character
+ (F32)(fgi->mWidth + fgi->mXBearing) - fgi->mXAdvance); // difference between width of this character and advance to next character
+
+ cur_x += fgi->mXAdvance;
+
+ // clip if current character runs past scaled_max_pixels (using width_padding)
+ if (scaled_max_pixels < cur_x + width_padding)
+ {
+ clip = TRUE;
+ break;
+ }
+
+ if (((i+1) < max_chars) && wchars[i+1])
+ {
+ // Kern this puppy.
+ cur_x += mFontFreetype->getXKerning(wch, wchars[i+1]);
}
+
// Round after kerning.
- cur_x = (F32)llfloor(cur_x + 0.5f);
+ cur_x = llround(cur_x);
drawn_x = cur_x;
}
- if( clip && end_on_word_boundary && (start_of_last_word != 0) )
+ if( clip )
{
- i = start_of_last_word;
- }
- if (drawn_pixels)
- {
- *drawn_pixels = drawn_x;
+ switch (end_on_word_boundary)
+ {
+ case ONLY_WORD_BOUNDARIES:
+ i = start_of_last_word;
+ break;
+ case WORD_BOUNDARY_IF_POSSIBLE:
+ if (start_of_last_word != 0)
+ {
+ i = start_of_last_word;
+ }
+ break;
+ default:
+ case ANYWHERE:
+ // do nothing
+ break;
+ }
}
return i;
}
-
S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos, S32 max_chars) const
{
if (!wchars || !wchars[0] || max_chars == 0)
@@ -898,8 +601,7 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_
{
llwchar wch = wchars[i];
- const embedded_data_t* ext_data = getEmbeddedCharData(wch);
- F32 char_width = ext_data ? getEmbeddedCharAdvance(ext_data) : getXAdvance(wch);
+ F32 char_width = mFontFreetype->getXAdvance(wch);
if( scaled_max_pixels < (total_width + char_width) )
{
@@ -917,7 +619,7 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_
if ( i > 0 )
{
// kerning
- total_width += ext_data ? (EXT_KERNING * sScaleX) : getXKerning(wchars[i-1], wch);
+ total_width += mFontFreetype->getXKerning(wchars[i-1], wch);
}
// Round after kerning.
@@ -927,8 +629,7 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_
return start_pos - drawable_chars;
}
-
-S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset, F32 target_x, F32 max_pixels, S32 max_chars, BOOL round, BOOL use_embedded) const
+S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 target_x, F32 max_pixels, S32 max_chars, BOOL round) const
{
if (!wchars || !wchars[0] || max_chars == 0)
{
@@ -936,7 +637,6 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset,
}
F32 cur_x = 0;
- S32 pos = 0;
target_x *= sScaleX;
@@ -945,149 +645,382 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset,
F32 scaled_max_pixels = max_pixels * sScaleX;
- for (S32 i = begin_offset; (i < max_index); i++)
+ S32 pos;
+ for (pos = begin_offset; pos < max_index; pos++)
{
- llwchar wch = wchars[i];
+ llwchar wch = wchars[pos];
if (!wch)
{
break; // done
}
- const embedded_data_t* ext_data = use_embedded ? getEmbeddedCharData(wch) : NULL;
- if (ext_data)
- {
- F32 ext_advance = getEmbeddedCharAdvance(ext_data);
+ F32 char_width = mFontFreetype->getXAdvance(wch);
- if (round)
- {
- // Note: if the mouse is on the left half of the character, the pick is to the character's left
- // If it's on the right half, the pick is to the right.
- if (target_x < cur_x + ext_advance/2)
- {
- break;
- }
- }
- else
- {
- if (target_x < cur_x + ext_advance)
- {
- break;
- }
- }
-
- if (scaled_max_pixels < cur_x + ext_advance)
+ if (round)
+ {
+ // Note: if the mouse is on the left half of the character, the pick is to the character's left
+ // If it's on the right half, the pick is to the right.
+ if (target_x < cur_x + char_width*0.5f)
{
break;
}
+ }
+ else if (target_x < cur_x + char_width)
+ {
+ break;
+ }
- pos++;
- cur_x += ext_advance;
-
- if (((i + 1) < max_index)
- && (wchars[(i + 1)]))
- {
- cur_x += EXT_KERNING * sScaleX;
- }
- // Round after kerning.
- cur_x = (F32)llfloor(cur_x + 0.5f);
+ if (scaled_max_pixels < cur_x + char_width)
+ {
+ break;
}
- else
+
+ cur_x += char_width;
+
+ if (((pos + 1) < max_index)
+ && (wchars[(pos + 1)]))
{
- F32 char_width = getXAdvance(wch);
+ llwchar next_char = wchars[pos + 1];
+ // Kern this puppy.
+ cur_x += mFontFreetype->getXKerning(wch, next_char);
+ }
- if (round)
- {
- // Note: if the mouse is on the left half of the character, the pick is to the character's left
- // If it's on the right half, the pick is to the right.
- if (target_x < cur_x + char_width*0.5f)
- {
- break;
- }
- }
- else if (target_x < cur_x + char_width)
- {
- break;
- }
+ // Round after kerning.
+ cur_x = llround(cur_x);
+ }
- if (scaled_max_pixels < cur_x + char_width)
- {
- break;
- }
+ return llmin(max_chars, pos - begin_offset);
+}
- pos++;
- cur_x += char_width;
+const LLFontDescriptor& LLFontGL::getFontDesc() const
+{
+ return mFontDescriptor;
+}
- if (((i + 1) < max_index)
- && (wchars[(i + 1)]))
- {
- llwchar next_char = wchars[i + 1];
- // Kern this puppy.
- cur_x += getXKerning(wch, next_char);
- }
+// static
+void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::vector<std::string>& xui_paths, bool create_gl_textures)
+{
+ sVertDPI = (F32)llfloor(screen_dpi * y_scale);
+ sHorizDPI = (F32)llfloor(screen_dpi * x_scale);
+ sScaleX = x_scale;
+ sScaleY = y_scale;
+ sAppDir = app_dir;
- // Round after kerning.
- cur_x = (F32)llfloor(cur_x + 0.5f);
- }
+ // Font registry init
+ if (!sFontRegistry)
+ {
+ sFontRegistry = new LLFontRegistry(xui_paths, create_gl_textures);
+ sFontRegistry->parseFontInfo("fonts.xml");
}
+ else
+ {
+ sFontRegistry->reset();
+ }
+}
- return pos;
+// Force standard fonts to get generated up front.
+// This is primarily for error detection purposes.
+// Don't do this during initClass because it can be slow and we want to get
+// the viewer window on screen first. JC
+// static
+bool LLFontGL::loadDefaultFonts()
+{
+ bool succ = true;
+ succ &= (NULL != getFontSansSerifSmall());
+ succ &= (NULL != getFontSansSerif());
+ succ &= (NULL != getFontSansSerifBig());
+ succ &= (NULL != getFontSansSerifHuge());
+ succ &= (NULL != getFontSansSerifBold());
+ succ &= (NULL != getFontMonospace());
+ succ &= (NULL != getFontExtChar());
+ return succ;
}
+// static
+void LLFontGL::destroyDefaultFonts()
+{
+ // Remove the actual fonts.
+ delete sFontRegistry;
+ sFontRegistry = NULL;
+}
-const LLFontGL::embedded_data_t* LLFontGL::getEmbeddedCharData(const llwchar wch) const
+//static
+void LLFontGL::destroyAllGL()
{
- // Handle crappy embedded hack
- embedded_map_t::const_iterator iter = mEmbeddedChars.find(wch);
- if (iter != mEmbeddedChars.end())
+ if (sFontRegistry)
{
- return iter->second;
+ sFontRegistry->destroyGL();
}
- return NULL;
}
+// static
+U8 LLFontGL::getStyleFromString(const std::string &style)
+{
+ S32 ret = 0;
+ if (style.find("NORMAL") != style.npos)
+ {
+ ret |= NORMAL;
+ }
+ if (style.find("BOLD") != style.npos)
+ {
+ ret |= BOLD;
+ }
+ if (style.find("ITALIC") != style.npos)
+ {
+ ret |= ITALIC;
+ }
+ if (style.find("UNDERLINE") != style.npos)
+ {
+ ret |= UNDERLINE;
+ }
+ return ret;
+}
-F32 LLFontGL::getEmbeddedCharAdvance(const embedded_data_t* ext_data) const
+// static
+std::string LLFontGL::getStringFromStyle(U8 style)
{
- const LLWString& label = ext_data->mLabel;
- LLImageGL* ext_image = ext_data->mImage;
+ std::string style_string;
+ if (style & NORMAL)
+ {
+ style_string += "|NORMAL";
+ }
+ if (style & BOLD)
+ {
+ style_string += "|BOLD";
+ }
+ if (style & ITALIC)
+ {
+ style_string += "|ITALIC";
+ }
+ if (style & UNDERLINE)
+ {
+ style_string += "|UNDERLINE";
+ }
+ return style_string;
+}
- F32 ext_width = (F32)ext_image->getWidth();
- if( !label.empty() )
+// static
+std::string LLFontGL::nameFromFont(const LLFontGL* fontp)
+{
+ return fontp->mFontDescriptor.getName();
+}
+
+
+// static
+std::string LLFontGL::sizeFromFont(const LLFontGL* fontp)
+{
+ return fontp->mFontDescriptor.getSize();
+}
+
+// static
+std::string LLFontGL::nameFromHAlign(LLFontGL::HAlign align)
+{
+ if (align == LEFT) return std::string("left");
+ else if (align == RIGHT) return std::string("right");
+ else if (align == HCENTER) return std::string("center");
+ else return std::string();
+}
+
+// static
+LLFontGL::HAlign LLFontGL::hAlignFromName(const std::string& name)
+{
+ LLFontGL::HAlign gl_hfont_align = LLFontGL::LEFT;
+ if (name == "left")
{
- ext_width += (EXT_X_BEARING + getFontExtChar()->getWidthF32(label.c_str())) * sScaleX;
+ gl_hfont_align = LLFontGL::LEFT;
}
+ else if (name == "right")
+ {
+ gl_hfont_align = LLFontGL::RIGHT;
+ }
+ else if (name == "center")
+ {
+ gl_hfont_align = LLFontGL::HCENTER;
+ }
+ //else leave left
+ return gl_hfont_align;
+}
- return (EXT_X_BEARING * sScaleX) + ext_width;
+// static
+std::string LLFontGL::nameFromVAlign(LLFontGL::VAlign align)
+{
+ if (align == TOP) return std::string("top");
+ else if (align == VCENTER) return std::string("center");
+ else if (align == BASELINE) return std::string("baseline");
+ else if (align == BOTTOM) return std::string("bottom");
+ else return std::string();
}
+// static
+LLFontGL::VAlign LLFontGL::vAlignFromName(const std::string& name)
+{
+ LLFontGL::VAlign gl_vfont_align = LLFontGL::BASELINE;
+ if (name == "top")
+ {
+ gl_vfont_align = LLFontGL::TOP;
+ }
+ else if (name == "center")
+ {
+ gl_vfont_align = LLFontGL::VCENTER;
+ }
+ else if (name == "baseline")
+ {
+ gl_vfont_align = LLFontGL::BASELINE;
+ }
+ else if (name == "bottom")
+ {
+ gl_vfont_align = LLFontGL::BOTTOM;
+ }
+ //else leave baseline
+ return gl_vfont_align;
+}
-void LLFontGL::clearEmbeddedChars()
+//static
+LLFontGL* LLFontGL::getFontMonospace()
{
- for_each(mEmbeddedChars.begin(), mEmbeddedChars.end(), DeletePairedPointer());
- mEmbeddedChars.clear();
+ return getFont(LLFontDescriptor("Monospace","Monospace",0));
}
-void LLFontGL::addEmbeddedChar( llwchar wc, LLImageGL* image, const std::string& label ) const
+//static
+LLFontGL* LLFontGL::getFontSansSerifSmall()
{
- LLWString wlabel = utf8str_to_wstring(label);
- addEmbeddedChar(wc, image, wlabel);
+ return getFont(LLFontDescriptor("SansSerif","Small",0));
}
-void LLFontGL::addEmbeddedChar( llwchar wc, LLImageGL* image, const LLWString& wlabel ) const
+//static
+LLFontGL* LLFontGL::getFontSansSerif()
+{
+ return getFont(LLFontDescriptor("SansSerif","Medium",0));
+}
+
+//static
+LLFontGL* LLFontGL::getFontSansSerifBig()
{
- embedded_data_t* ext_data = new embedded_data_t(image, wlabel);
- mEmbeddedChars[wc] = ext_data;
+ return getFont(LLFontDescriptor("SansSerif","Large",0));
}
-void LLFontGL::removeEmbeddedChar( llwchar wc ) const
+//static
+LLFontGL* LLFontGL::getFontSansSerifHuge()
{
- embedded_map_t::iterator iter = mEmbeddedChars.find(wc);
- if (iter != mEmbeddedChars.end())
+ return getFont(LLFontDescriptor("SansSerif","Huge",0));
+}
+
+//static
+LLFontGL* LLFontGL::getFontSansSerifBold()
+{
+ return getFont(LLFontDescriptor("SansSerif","Medium",BOLD));
+}
+
+//static
+LLFontGL* LLFontGL::getFontExtChar()
+{
+ return getFontSansSerif();
+}
+
+//static
+LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc)
+{
+ return sFontRegistry->getFont(desc);
+}
+
+//static
+LLFontGL* LLFontGL::getFontByName(const std::string& name)
+{
+ // check for most common fonts first
+ if (name == "SANSSERIF")
+ {
+ return getFontSansSerif();
+ }
+ else if (name == "SANSSERIF_SMALL")
+ {
+ return getFontSansSerifSmall();
+ }
+ else if (name == "SANSSERIF_BIG")
+ {
+ return getFontSansSerifBig();
+ }
+ else if (name == "SMALL" || name == "OCRA")
+ {
+ // *BUG: Should this be "MONOSPACE"? Do we use "OCRA" anymore?
+ // Does "SMALL" mean "SERIF"?
+ return getFontMonospace();
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+//static
+LLFontGL* LLFontGL::getFontDefault()
+{
+ return getFontSansSerif(); // Fallback to sans serif as default font
+}
+
+
+// static
+std::string LLFontGL::getFontPathSystem()
+{
+ std::string system_path;
+
+ // Try to figure out where the system's font files are stored.
+ char *system_root = NULL;
+#if LL_WINDOWS
+ system_root = getenv("SystemRoot"); /* Flawfinder: ignore */
+ if (!system_root)
+ {
+ llwarns << "SystemRoot not found, attempting to load fonts from default path." << llendl;
+ }
+#endif
+
+ if (system_root)
+ {
+ system_path = llformat("%s/fonts/", system_root);
+ }
+ else
+ {
+#if LL_WINDOWS
+ // HACK for windows 98/Me
+ system_path = "/WINDOWS/FONTS/";
+#elif LL_DARWIN
+ // HACK for Mac OS X
+ system_path = "/System/Library/Fonts/";
+#endif
+ }
+ return system_path;
+}
+
+
+// static
+std::string LLFontGL::getFontPathLocal()
+{
+ std::string local_path;
+
+ // Backup files if we can't load from system fonts directory.
+ // We could store this in an end-user writable directory to allow
+ // end users to switch fonts.
+ if (LLFontGL::sAppDir.length())
+ {
+ // use specified application dir to look for fonts
+ local_path = LLFontGL::sAppDir + "/fonts/";
+ }
+ else
{
- delete iter->second;
- mEmbeddedChars.erase(wc);
+ // assume working directory is executable directory
+ local_path = "./fonts/";
}
+ return local_path;
}
+LLFontGL::LLFontGL(const LLFontGL &source)
+{
+ llerrs << "Not implemented!" << llendl;
+}
+
+LLFontGL &LLFontGL::operator=(const LLFontGL &source)
+{
+ llerrs << "Not implemented" << llendl;
+ return *this;
+}
void LLFontGL::renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const
{
@@ -1108,10 +1041,10 @@ void LLFontGL::renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F3
llfont_round_y(screen_rect.mBottom));
}
-void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, F32 drop_shadow_strength) const
+void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_strength) const
{
F32 slant_offset;
- slant_offset = ((style & ITALIC) ? ( -mAscender * 0.2f) : 0.f);
+ slant_offset = ((style & ITALIC) ? ( -mFontFreetype->getAscenderHeight() * 0.2f) : 0.f);
gGL.begin(LLRender::QUADS);
{
@@ -1128,7 +1061,7 @@ void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, con
renderQuad(screen_rect_offset, uv_rect, slant_offset);
}
}
- else if (style & DROP_SHADOW_SOFT)
+ else if (shadow == DROP_SHADOW_SOFT)
{
LLColor4 shadow_color = LLFontGL::sShadowColor;
shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength * DROP_SHADOW_SOFT_STRENGTH;
@@ -1161,7 +1094,7 @@ void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, con
gGL.color4fv(color.mV);
renderQuad(screen_rect, uv_rect, slant_offset);
}
- else if (style & DROP_SHADOW)
+ else if (shadow == DROP_SHADOW)
{
LLColor4 shadow_color = LLFontGL::sShadowColor;
shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength;
@@ -1181,71 +1114,3 @@ void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, con
}
gGL.end();
}
-
-std::string LLFontGL::nameFromFont(const LLFontGL* fontp)
-{
- return fontp->getFontDesc().getName();
-}
-
-// static
-std::string LLFontGL::nameFromHAlign(LLFontGL::HAlign align)
-{
- if (align == LEFT) return std::string("left");
- else if (align == RIGHT) return std::string("right");
- else if (align == HCENTER) return std::string("center");
- else return std::string();
-}
-
-// static
-LLFontGL::HAlign LLFontGL::hAlignFromName(const std::string& name)
-{
- LLFontGL::HAlign gl_hfont_align = LLFontGL::LEFT;
- if (name == "left")
- {
- gl_hfont_align = LLFontGL::LEFT;
- }
- else if (name == "right")
- {
- gl_hfont_align = LLFontGL::RIGHT;
- }
- else if (name == "center")
- {
- gl_hfont_align = LLFontGL::HCENTER;
- }
- //else leave left
- return gl_hfont_align;
-}
-
-// static
-std::string LLFontGL::nameFromVAlign(LLFontGL::VAlign align)
-{
- if (align == TOP) return std::string("top");
- else if (align == VCENTER) return std::string("center");
- else if (align == BASELINE) return std::string("baseline");
- else if (align == BOTTOM) return std::string("bottom");
- else return std::string();
-}
-
-// static
-LLFontGL::VAlign LLFontGL::vAlignFromName(const std::string& name)
-{
- LLFontGL::VAlign gl_vfont_align = LLFontGL::BASELINE;
- if (name == "top")
- {
- gl_vfont_align = LLFontGL::TOP;
- }
- else if (name == "center")
- {
- gl_vfont_align = LLFontGL::VCENTER;
- }
- else if (name == "baseline")
- {
- gl_vfont_align = LLFontGL::BASELINE;
- }
- else if (name == "bottom")
- {
- gl_vfont_align = LLFontGL::BOTTOM;
- }
- //else leave baseline
- return gl_vfont_align;
-}
diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h
index 6cb1727ff4..dfa4cf8ce5 100644
--- a/indra/llrender/llfontgl.h
+++ b/indra/llrender/llfontgl.h
@@ -34,23 +34,22 @@
#ifndef LL_LLFONTGL_H
#define LL_LLFONTGL_H
-#include "llfont.h"
-#include "llimagegl.h"
-#include "v2math.h"
#include "llcoord.h"
-#include "llrect.h"
-
#include "llfontregistry.h"
+#include "llimagegl.h"
+#include "llpointer.h"
+#include "llrect.h"
+#include "v2math.h"
class LLColor4;
-
// Key used to request a font.
class LLFontDescriptor;
+class LLFontFreetype;
// Structure used to store previously requested fonts.
class LLFontRegistry;
-class LLFontGL : public LLFont
+class LLFontGL
{
public:
enum HAlign
@@ -73,133 +72,88 @@ public:
enum StyleFlags
{
// text style to render. May be combined (these are bit flags)
- NORMAL = 0,
- BOLD = 1,
- ITALIC = 2,
- UNDERLINE = 4,
- DROP_SHADOW = 8,
- DROP_SHADOW_SOFT = 16
+ NORMAL = 0x00,
+ BOLD = 0x01,
+ ITALIC = 0x02,
+ UNDERLINE = 0x04
+ };
+
+ enum ShadowType
+ {
+ NO_SHADOW,
+ DROP_SHADOW,
+ DROP_SHADOW_SOFT
};
-
- // Takes a string with potentially several flags, i.e. "NORMAL|BOLD|ITALIC"
- static U8 getStyleFromString(const std::string &style);
LLFontGL();
- LLFontGL(const LLFontGL &source);
~LLFontGL();
- void init(); // Internal init, or reinitialization
- void reset(); // Reset a font after GL cleanup. ONLY works on an already loaded font.
-
- LLFontGL &operator=(const LLFontGL &source);
- static BOOL initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale,
- const std::string& app_dir,
- const std::vector<std::string>& xui_paths);
+ void reset(); // Reset a font after GL cleanup. ONLY works on an already loaded font.
- static void destroyDefaultFonts();
- static void destroyAllGL();
void destroyGL();
- /* virtual*/ BOOL loadFace(const std::string& filename,
- const F32 point_size, const F32 vert_dpi, const F32 horz_dpi,
- const S32 components, BOOL is_fallback);
+ BOOL loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, const S32 components, BOOL is_fallback);
+ S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign = LEFT, VAlign valign = BASELINE, U8 style = NORMAL,
+ ShadowType shadow = NO_SHADOW, S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX, F32* right_x=NULL, BOOL use_ellipses = FALSE) const;
+ S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const;
- S32 renderUTF8(const std::string &text, const S32 begin_offset,
- S32 x, S32 y,
- const LLColor4 &color) const
- {
- return renderUTF8(text, begin_offset, (F32)x, (F32)y, color,
- LEFT, BASELINE, NORMAL,
- S32_MAX, S32_MAX, NULL, FALSE);
- }
-
- S32 renderUTF8(const std::string &text, const S32 begin_offset,
- S32 x, S32 y,
- const LLColor4 &color,
- HAlign halign, VAlign valign, U8 style = NORMAL) const
- {
- return renderUTF8(text, begin_offset, (F32)x, (F32)y, color,
- halign, valign, style,
- S32_MAX, S32_MAX, NULL, FALSE);
- }
-
// renderUTF8 does a conversion, so is slower!
- S32 renderUTF8(const std::string &text,
- S32 begin_offset,
- F32 x, F32 y,
- const LLColor4 &color,
- HAlign halign,
- VAlign valign,
- U8 style,
- S32 max_chars,
- S32 max_pixels,
- F32* right_x,
- BOOL use_ellipses) const;
-
- S32 render(const LLWString &text, const S32 begin_offset,
- F32 x, F32 y,
- const LLColor4 &color) const
- {
- return render(text, begin_offset, x, y, color,
- LEFT, BASELINE, NORMAL,
- S32_MAX, S32_MAX, NULL, FALSE, FALSE);
- }
-
+ S32 renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const;
+ S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color) const;
+ S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style = NORMAL, ShadowType shadow = NO_SHADOW) const;
- S32 render(const LLWString &text,
- S32 begin_offset,
- F32 x, F32 y,
- const LLColor4 &color,
- HAlign halign = LEFT,
- VAlign valign = BASELINE,
- U8 style = NORMAL,
- S32 max_chars = S32_MAX,
- S32 max_pixels = S32_MAX,
- F32* right_x=NULL,
- BOOL use_embedded = FALSE,
- BOOL use_ellipses = FALSE) const;
-
- // font metrics - override for LLFont that returns units of virtual pixels
- /*virtual*/ F32 getLineHeight() const { return (F32)llround(mLineHeight / sScaleY); }
- /*virtual*/ F32 getAscenderHeight() const { return (F32)llround(mAscender / sScaleY); }
- /*virtual*/ F32 getDescenderHeight() const { return (F32)llround(mDescender / sScaleY); }
-
- virtual S32 getWidth(const std::string& utf8text) const;
- virtual S32 getWidth(const llwchar* wchars) const;
- virtual S32 getWidth(const std::string& utf8text, const S32 offset, const S32 max_chars ) const;
- virtual S32 getWidth(const llwchar* wchars, const S32 offset, const S32 max_chars, BOOL use_embedded = FALSE) const;
+ // font metrics - override for LLFontFreetype that returns units of virtual pixels
+ F32 getLineHeight() const;
+ F32 getAscenderHeight() const;
+ F32 getDescenderHeight() const;
+
+ S32 getWidth(const std::string& utf8text) const;
+ S32 getWidth(const llwchar* wchars) const;
+ S32 getWidth(const std::string& utf8text, S32 offset, S32 max_chars ) const;
+ S32 getWidth(const llwchar* wchars, S32 offset, S32 max_chars) const;
- virtual F32 getWidthF32(const std::string& utf8text) const;
- virtual F32 getWidthF32(const llwchar* wchars) const;
- virtual F32 getWidthF32(const std::string& text, const S32 offset, const S32 max_chars ) const;
- virtual F32 getWidthF32(const llwchar* wchars, const S32 offset, const S32 max_chars, BOOL use_embedded = FALSE ) const;
+ F32 getWidthF32(const std::string& utf8text) const;
+ F32 getWidthF32(const llwchar* wchars) const;
+ F32 getWidthF32(const std::string& text, S32 offset, S32 max_chars ) const;
+ F32 getWidthF32(const llwchar* wchars, S32 offset, S32 max_chars) const;
// The following are called often, frequently with large buffers, so do not use a string interface
// Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels
- virtual S32 maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars = S32_MAX,
- BOOL end_on_word_boundary = FALSE, const BOOL use_embedded = FALSE,
- F32* drawn_pixels = NULL) const;
+ typedef enum e_word_wrap_style
+ {
+ ONLY_WORD_BOUNDARIES,
+ WORD_BOUNDARY_IF_POSSIBLE,
+ ANYWHERE
+ } EWordWrapStyle ;
+ S32 maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars = S32_MAX, EWordWrapStyle end_on_word_boundary = ANYWHERE) const;
// Returns the index of the first complete characters from text that can be drawn in max_pixels
// given that the character at start_pos should be the last character (or as close to last as possible).
- virtual S32 firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos=S32_MAX, S32 max_chars = S32_MAX) const;
+ S32 firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos=S32_MAX, S32 max_chars = S32_MAX) const;
// Returns the index of the character closest to pixel position x (ignoring text to the right of max_pixels and max_chars)
- virtual S32 charFromPixelOffset(const llwchar* wchars, const S32 char_offset,
- F32 x, F32 max_pixels=F32_MAX, S32 max_chars = S32_MAX,
- BOOL round = TRUE, BOOL use_embedded = FALSE) const;
+ S32 charFromPixelOffset(const llwchar* wchars, S32 char_offset, F32 x, F32 max_pixels=F32_MAX, S32 max_chars = S32_MAX, BOOL round = TRUE) const;
+ const LLFontDescriptor& getFontDesc() const;
- LLImageGL *getImageGL() const;
- void addEmbeddedChar( llwchar wc, LLImageGL* image, const std::string& label) const;
- void addEmbeddedChar( llwchar wc, LLImageGL* image, const LLWString& label) const;
- void removeEmbeddedChar( llwchar wc ) const;
+ static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::vector<std::string>& xui_paths, bool create_gl_textures = true);
+
+ // Load sans-serif, sans-serif-small, etc.
+ // Slow, requires multiple seconds to load fonts.
+ static bool loadDefaultFonts();
+ static void destroyDefaultFonts();
+ static void destroyAllGL();
+
+ // Takes a string with potentially several flags, i.e. "NORMAL|BOLD|ITALIC"
+ static U8 getStyleFromString(const std::string &style);
+ static std::string getStringFromStyle(U8 style);
static std::string nameFromFont(const LLFontGL* fontp);
+ static std::string sizeFromFont(const LLFontGL* fontp);
static std::string nameFromHAlign(LLFontGL::HAlign align);
static LLFontGL::HAlign hAlignFromName(const std::string& name);
@@ -207,28 +161,7 @@ public:
static std::string nameFromVAlign(LLFontGL::VAlign align);
static LLFontGL::VAlign vAlignFromName(const std::string& name);
- static void setFontDisplay(BOOL flag) { sDisplayFont = flag ; }
-
-protected:
- struct embedded_data_t
- {
- embedded_data_t(LLImageGL* image, const LLWString& label) : mImage(image), mLabel(label) {}
- LLPointer<LLImageGL> mImage;
- LLWString mLabel;
- };
- const embedded_data_t* getEmbeddedCharData(const llwchar wch) const;
- F32 getEmbeddedCharAdvance(const embedded_data_t* ext_data) const;
- void clearEmbeddedChars();
- void renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const;
- void drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, F32 drop_shadow_fade) const;
-
-public:
- static F32 sVertDPI;
- static F32 sHorizDPI;
- static F32 sScaleX;
- static F32 sScaleY;
- static BOOL sDisplayFont ;
- static std::string sAppDir; // For loading fonts
+ static void setFontDisplay(BOOL flag) { sDisplayFont = flag; }
static LLFontGL* getFontMonospace();
static LLFontGL* getFontSansSerifSmall();
@@ -238,33 +171,41 @@ public:
static LLFontGL* getFontSansSerifBold();
static LLFontGL* getFontExtChar();
static LLFontGL* getFont(const LLFontDescriptor& desc);
+ // Use with legacy names like "SANSSERIF_SMALL" or "OCRA"
+ static LLFontGL* getFontByName(const std::string& name);
+ static LLFontGL* getFontDefault(); // default fallback font
+
+ static std::string getFontPathLocal();
+ static std::string getFontPathSystem();
+
+ static LLCoordFont sCurOrigin;
+ static std::vector<LLCoordFont> sOriginStack;
static LLColor4 sShadowColor;
+ static F32 sVertDPI;
+ static F32 sHorizDPI;
+ static F32 sScaleX;
+ static F32 sScaleY;
+ static BOOL sDisplayFont ;
+ static std::string sAppDir; // For loading fonts
+
+private:
+ friend class LLFontRegistry;
friend class LLTextBillboard;
friend class LLHUDText;
-protected:
- /*virtual*/ BOOL addChar(const llwchar wch) const;
+ LLFontGL(const LLFontGL &source);
+ LLFontGL &operator=(const LLFontGL &source);
-protected:
- typedef std::map<llwchar,embedded_data_t*> embedded_map_t;
- mutable embedded_map_t mEmbeddedChars;
-
- LLFontDescriptor mFontDesc;
+ LLFontDescriptor mFontDescriptor;
+ LLPointer<LLFontFreetype> mFontFreetype;
+
+ void renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const;
+ void drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const;
// Registry holds all instantiated fonts.
static LLFontRegistry* sFontRegistry;
-
-public:
- static std::string getFontPathLocal();
- static std::string getFontPathSystem();
-
- static LLCoordFont sCurOrigin;
- static std::vector<LLCoordFont> sOriginStack;
-
- const LLFontDescriptor &getFontDesc() const { return mFontDesc; }
- void setFontDesc(const LLFontDescriptor& font_desc) { mFontDesc = font_desc; }
};
#endif
diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp
index 9b5bc5d0af..7a3d6ec4f2 100644
--- a/indra/llrender/llfontregistry.cpp
+++ b/indra/llrender/llfontregistry.cpp
@@ -5,7 +5,7 @@
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2008, Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -13,12 +13,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
@@ -32,8 +33,9 @@
#include "linden_common.h"
#include "llgl.h"
-#include "llfontregistry.h"
+#include "llfontfreetype.h"
#include "llfontgl.h"
+#include "llfontregistry.h"
#include <boost/tokenizer.hpp>
#include "llcontrol.h"
#include "lldir.h"
@@ -103,7 +105,7 @@ bool removeSubString(std::string& str, const std::string& substr)
size_t pos = str.find(substr);
if (pos != string::npos)
{
- str.replace(pos,substr.length(),(const char *)NULL, 0);
+ str.erase(pos, substr.size());
return true;
}
return false;
@@ -167,7 +169,9 @@ LLFontDescriptor LLFontDescriptor::normalize() const
return LLFontDescriptor(new_name,new_size,new_style,getFileNames());
}
-LLFontRegistry::LLFontRegistry(const string_vec_t& xui_paths)
+LLFontRegistry::LLFontRegistry(const string_vec_t& xui_paths,
+ bool create_gl_textures)
+: mCreateGLTextures(create_gl_textures)
{
// Propagate this down from LLUICtrlFactory so LLRender doesn't
// need an upstream dependency on LLUI.
@@ -215,8 +219,8 @@ bool LLFontRegistry::parseFontInfo(const std::string& xml_filename)
success = success || init_succ;
}
}
- if (success)
- dump();
+ //if (success)
+ // dump();
return success;
}
@@ -376,10 +380,20 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
LLFontDescriptor nearest_exact_desc = *match_desc;
nearest_exact_desc.setSize(norm_desc.getSize());
font_reg_map_t::iterator it = mFontMap.find(nearest_exact_desc);
- if (it != mFontMap.end())
+ // If we fail to find a font in the fonts directory, it->second might be NULL.
+ // We shouldn't construcnt a font with a NULL mFontFreetype.
+ // This may not be the best solution, but it at least prevents a crash.
+ if (it != mFontMap.end() && it->second != NULL)
{
llinfos << "-- matching font exists: " << nearest_exact_desc.getName() << " size " << nearest_exact_desc.getSize() << " style " << ((S32) nearest_exact_desc.getStyle()) << llendl;
- return it->second;
+
+ // copying underlying Freetype font, and storing in LLFontGL with requested font descriptor
+ LLFontGL *font = new LLFontGL;
+ font->mFontDescriptor = desc;
+ font->mFontFreetype = it->second->mFontFreetype;
+ mFontMap[desc] = font;
+
+ return font;
}
// Build list of font names to look for.
@@ -407,10 +421,11 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
llwarns << "createFont failed, no file names specified" << llendl;
return NULL;
}
- LLFontList *fontlistp = new LLFontList;
+
+ LLFontFreetype::font_vector_t fontlist;
LLFontGL *result = NULL;
- // Snarf all fonts we can into fontlistp. First will get pulled
+ // Snarf all fonts we can into fontlist. First will get pulled
// off the list and become the "head" font, set to non-fallback.
// Rest will consitute the fallback list.
BOOL is_first_found = TRUE;
@@ -426,7 +441,9 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
{
LLFontGL *fontp = new LLFontGL;
std::string font_path = local_path + *file_name_it;
- BOOL is_fallback = !is_first_found;
+ // *HACK: Fallback fonts don't render, so we can use that to suppress
+ // creation of OpenGL textures for test apps. JC
+ BOOL is_fallback = !is_first_found || !mCreateGLTextures;
F32 extra_scale = (is_fallback)?fallback_scale:1.0;
if (!fontp->loadFace(font_path, extra_scale * point_size,
LLFontGL::sVertDPI, LLFontGL::sHorizDPI, 2, is_fallback))
@@ -450,23 +467,27 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
is_first_found = false;
}
else
- fontlistp->addAtEnd(fontp);
+ {
+ fontlist.push_back(fontp->mFontFreetype);
+ }
}
}
- if (result && !fontlistp->empty())
+
+ if (result && !fontlist.empty())
{
- result->setFallbackFont(fontlistp);
+ result->mFontFreetype->setFallbackFonts(fontlist);
}
- norm_desc.setStyle(match_desc->getStyle());
if (result)
- result->setFontDesc(norm_desc);
-
- if (!result)
+ {
+ result->mFontDescriptor = desc;
+ }
+ else
{
llwarns << "createFont failed in some way" << llendl;
}
- mFontMap[norm_desc] = result;
+
+ mFontMap[desc] = result;
return result;
}
@@ -506,21 +527,19 @@ void LLFontRegistry::destroyGL()
}
}
-LLFontGL *LLFontRegistry::getFont(const LLFontDescriptor& orig_desc)
+LLFontGL *LLFontRegistry::getFont(const LLFontDescriptor& desc)
{
- LLFontDescriptor norm_desc = orig_desc.normalize();
-
- font_reg_map_t::iterator it = mFontMap.find(norm_desc);
+ font_reg_map_t::iterator it = mFontMap.find(desc);
if (it != mFontMap.end())
return it->second;
else
{
- LLFontGL *fontp = createFont(orig_desc);
+ LLFontGL *fontp = createFont(desc);
if (!fontp)
{
- llwarns << "getFont failed, name " << orig_desc.getName()
- <<" style=[" << ((S32) orig_desc.getStyle()) << "]"
- << " size=[" << orig_desc.getSize() << "]" << llendl;
+ llwarns << "getFont failed, name " << desc.getName()
+ <<" style=[" << ((S32) desc.getStyle()) << "]"
+ << " size=[" << desc.getSize() << "]" << llendl;
}
return fontp;
}
@@ -648,3 +667,8 @@ void LLFontRegistry::dump()
}
}
}
+
+const string_vec_t& LLFontRegistry::getUltimateFallbackList() const
+{
+ return mUltimateFallbackList;
+}
diff --git a/indra/llrender/llfontregistry.h b/indra/llrender/llfontregistry.h
index ed775eeed0..4da4ca48bb 100644
--- a/indra/llrender/llfontregistry.h
+++ b/indra/llrender/llfontregistry.h
@@ -5,7 +5,7 @@
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2008, Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -13,12 +13,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
@@ -70,7 +71,10 @@ private:
class LLFontRegistry
{
public:
- LLFontRegistry(const string_vec_t& xui_paths);
+ // create_gl_textures - set to false for test apps with no OpenGL window,
+ // such as llui_libtest
+ LLFontRegistry(const string_vec_t& xui_paths,
+ bool create_gl_textures);
~LLFontRegistry();
// Load standard font info from XML file(s).
@@ -94,7 +98,7 @@ public:
void dump();
- const string_vec_t& getUltimateFallbackList() const { return mUltimateFallbackList; }
+ const string_vec_t& getUltimateFallbackList() const;
private:
LLFontGL *createFont(const LLFontDescriptor& desc);
@@ -108,6 +112,7 @@ private:
string_vec_t mUltimateFallbackList;
string_vec_t mXUIPaths;
+ bool mCreateGLTextures;
};
#endif // LL_LLFONTREGISTRY_H
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 61194c4ecf..187a9a984e 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -45,10 +45,13 @@
#include "llrender.h"
#include "llerror.h"
+#include "llerrorcontrol.h"
#include "llquaternion.h"
#include "llmath.h"
#include "m4math.h"
#include "llstring.h"
+#include "llmemtype.h"
+#include "llstacktrace.h"
#include "llglheaders.h"
@@ -56,14 +59,57 @@
//#define GL_STATE_VERIFY
#endif
+
+BOOL gDebugSession = FALSE;
BOOL gDebugGL = FALSE;
BOOL gClothRipple = FALSE;
BOOL gNoRender = FALSE;
+BOOL gGLActive = FALSE;
+
+
+std::ofstream gFailLog;
+
+void ll_init_fail_log(std::string filename)
+{
+ gFailLog.open(filename.c_str());
+}
+
+
+void ll_fail(std::string msg)
+{
+
+ if (gDebugSession)
+ {
+ std::vector<std::string> lines;
+
+ gFailLog << LLError::utcTime() << " " << msg << std::endl;
+
+ gFailLog << "Stack Trace:" << std::endl;
+
+ ll_get_stack_trace(lines);
+
+ for(size_t i = 0; i < lines.size(); ++i)
+ {
+ gFailLog << lines[i] << std::endl;
+ }
+
+ gFailLog << "End of Stack Trace." << std::endl << std::endl;
+
+ gFailLog.flush();
+ }
+};
+
+void ll_close_fail_log()
+{
+ gFailLog.close();
+}
+
LLMatrix4 gGLObliqueProjectionInverse;
#define LL_GL_NAME_POOLING 0
LLGLNamePool::pool_list_t LLGLNamePool::sInstances;
+std::list<LLGLUpdate*> LLGLUpdate::sGLQ;
#if (LL_WINDOWS || LL_LINUX || LL_SOLARIS) && !LL_MESA_HEADLESS
// ATI prototypes
@@ -547,8 +593,6 @@ void LLGLManager::shutdownGL()
// these are used to turn software blending on. They appear in the Debug/Avatar menu
// presence of vertex skinning/blending or vertex programs will set these to FALSE by default.
-extern LLCPUInfo gSysCPU;
-
void LLGLManager::initExtensions()
{
#if LL_MESA_HEADLESS
@@ -596,6 +640,7 @@ void LLGLManager::initExtensions()
mHasShaderObjects = FALSE;
mHasVertexShader = FALSE;
mHasFragmentShader = FALSE;
+ mHasTextureRectangle = FALSE;
#else // LL_MESA_HEADLESS
mHasMultitexture = glh_init_extensions("GL_ARB_multitexture");
mHasMipMapGeneration = glh_init_extensions("GL_SGIS_generate_mipmap");
@@ -612,6 +657,7 @@ void LLGLManager::initExtensions()
&& ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts);
mHasFramebufferMultisample = mHasFramebufferObject && ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts);
mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts);
+ mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts);
#if !LL_DARWIN
mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts);
#endif
@@ -685,6 +731,7 @@ void LLGLManager::initExtensions()
if (strchr(blacklist,'q')) mHasFramebufferObject = FALSE;//S
if (strchr(blacklist,'r')) mHasDrawBuffers = FALSE;//S
if (strchr(blacklist,'s')) mHasFramebufferMultisample = FALSE;
+ if (strchr(blacklist,'t')) mHasTextureRectangle = FALSE;
}
#endif // LL_LINUX || LL_SOLARIS
@@ -967,10 +1014,21 @@ void flush_glerror()
void assert_glerror()
{
+ if (!gGLActive)
+ {
+ //llwarns << "GL used while not active!" << llendl;
+
+ if (gDebugSession)
+ {
+ //ll_fail("GL used while not active");
+ }
+ }
+
if (gNoRender || !gDebugGL)
{
return;
}
+
if (!gGLManager.mInited)
{
LL_ERRS("RenderInit") << "GL not initialized" << LL_ENDL;
@@ -988,12 +1046,22 @@ void assert_glerror()
{
LL_WARNS("RenderState") << "GL Error:" << error<< LL_ENDL;
LL_WARNS("RenderState") << "GL Error String:" << gl_error_msg << LL_ENDL;
+
+ if (gDebugSession)
+ {
+ gFailLog << "GL Error:" << gl_error_msg << std::endl;
+ }
}
else
{
// gluErrorString returns NULL for some extensions' error codes.
// you'll probably have to grep for the number in glext.h.
LL_WARNS("RenderState") << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << LL_ENDL;
+
+ if (gDebugSession)
+ {
+ gFailLog << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << std::endl;
+ }
}
error = glGetError();
#endif
@@ -1001,7 +1069,14 @@ void assert_glerror()
if (quit)
{
- llerrs << "One or more unhandled GL errors." << llendl;
+ if (gDebugSession)
+ {
+ ll_fail("assert_glerror failed");
+ }
+ else
+ {
+ llerrs << "One or more unhandled GL errors." << llendl;
+ }
}
}
@@ -1087,9 +1162,19 @@ void LLGLState::checkStates(const std::string& msg)
glGetIntegerv(GL_BLEND_SRC, &src);
glGetIntegerv(GL_BLEND_DST, &dst);
+ BOOL error = FALSE;
+
if (src != GL_SRC_ALPHA || dst != GL_ONE_MINUS_SRC_ALPHA)
{
- LL_GL_ERRS << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << std::endl;
+ error = TRUE;
+ }
+ else
+ {
+ LL_GL_ERRS << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << LL_ENDL;
+ }
}
for (std::map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
@@ -1101,10 +1186,22 @@ void LLGLState::checkStates(const std::string& msg)
if(cur_state != gl_state)
{
dumpStates();
- LL_GL_ERRS << llformat("LLGLState error. State: 0x%04x",state) << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << llformat("LLGLState error. State: 0x%04x",state) << std::endl;
+ error = TRUE;
+ }
+ else
+ {
+ LL_GL_ERRS << llformat("LLGLState error. State: 0x%04x",state) << LL_ENDL;
+ }
}
}
+ if (error)
+ {
+ ll_fail("LLGLState::checkStates failed.");
+ }
stop_glerror();
}
@@ -1115,9 +1212,12 @@ void LLGLState::checkTextureChannels(const std::string& msg)
return;
}
+ stop_glerror();
+
GLint activeTexture;
glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &activeTexture);
-
+ stop_glerror();
+
BOOL error = FALSE;
if (activeTexture == GL_TEXTURE0_ARB)
@@ -1125,15 +1225,22 @@ void LLGLState::checkTextureChannels(const std::string& msg)
GLint tex_env_mode = 0;
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env_mode);
+ stop_glerror();
+
if (tex_env_mode != GL_MODULATE)
{
error = TRUE;
LL_WARNS("RenderState") << "GL_TEXTURE_ENV_MODE invalid: " << std::hex << tex_env_mode << std::dec << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "GL_TEXTURE_ENV_MODE invalid: " << std::hex << tex_env_mode << std::dec << std::endl;
+ }
}
}
- GLint maxTextureUnits;
+ GLint maxTextureUnits = 0;
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextureUnits);
+ stop_glerror();
static const char* label[] =
{
@@ -1162,58 +1269,87 @@ void LLGLState::checkTextureChannels(const std::string& msg)
};
GLint stackDepth = 0;
- LLMatrix4 identity;
- LLMatrix4 matrix;
+
+ glh::matrix4f mat;
+ glh::matrix4f identity;
+ identity.identity();
for (GLint i = 1; i < maxTextureUnits; i++)
{
gGL.getTexUnit(i)->activate();
glClientActiveTextureARB(GL_TEXTURE0_ARB+i);
-
+ stop_glerror();
glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &stackDepth);
+ stop_glerror();
if (stackDepth != 1)
{
error = TRUE;
LL_WARNS("RenderState") << "Texture matrix stack corrupted." << LL_ENDL;
+
+ if (gDebugSession)
+ {
+ gFailLog << "Texture matrix stack corrupted." << std::endl;
+ }
}
- glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) matrix.mMatrix);
+ glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) mat.m);
+ stop_glerror();
- if (matrix != identity)
+ if (mat != identity)
{
error = TRUE;
LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "Texture matrix in channel " << i << " corrupt." << std::endl;
+ }
}
- for (S32 j = (i == 0 ? 1 : 0); j < 9; j++)
+
+ for (S32 j = (i == 0 ? 1 : 0);
+ j < (gGLManager.mHasTextureRectangle ? 9 : 8); j++)
{
if (glIsEnabled(value[j]))
{
error = TRUE;
LL_WARNS("RenderState") << "Texture channel " << i << " still has " << label[j] << " enabled." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "Texture channel " << i << " still has " << label[j] << " enabled." << std::endl;
+ }
}
+ stop_glerror();
}
- glh::matrix4f mat;
- glh::matrix4f identity;
- identity.identity();
-
glGetFloatv(GL_TEXTURE_MATRIX, mat.m);
+ stop_glerror();
if (mat != identity)
{
error = TRUE;
LL_WARNS("RenderState") << "Texture matrix " << i << " is not identity." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "Texture matrix " << i << " is not identity." << std::endl;
+ }
}
}
gGL.getTexUnit(0)->activate();
glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ stop_glerror();
if (error)
{
- LL_GL_ERRS << "GL texture state corruption detected. " << msg << LL_ENDL;
+ if (gDebugSession)
+ {
+ ll_fail("LLGLState::checkTextureChannels failed.");
+ }
+ else
+ {
+ LL_GL_ERRS << "GL texture state corruption detected. " << msg << LL_ENDL;
+ }
}
}
@@ -1233,6 +1369,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
if (active_texture != GL_TEXTURE0_ARB)
{
llwarns << "Client active texture corrupted: " << active_texture << llendl;
+ if (gDebugSession)
+ {
+ gFailLog << "Client active texture corrupted: " << active_texture << std::endl;
+ }
error = TRUE;
}
@@ -1240,6 +1380,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
if (active_texture != GL_TEXTURE0_ARB)
{
llwarns << "Active texture corrupted: " << active_texture << llendl;
+ if (gDebugSession)
+ {
+ gFailLog << "Active texture corrupted: " << active_texture << std::endl;
+ }
error = TRUE;
}
@@ -1276,6 +1420,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
{
error = TRUE;
LL_WARNS("RenderState") << "GL still has " << label[j] << " enabled." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "GL still has " << label[j] << " enabled." << std::endl;
+ }
}
}
else
@@ -1284,6 +1432,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
{
error = TRUE;
LL_WARNS("RenderState") << "GL does not have " << label[j] << " enabled." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "GL does not have " << label[j] << " enabled." << std::endl;
+ }
}
}
}
@@ -1296,6 +1448,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
{
error = TRUE;
LL_WARNS("RenderState") << "GL still has GL_TEXTURE_COORD_ARRAY enabled on channel 1." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "GL still has GL_TEXTURE_COORD_ARRAY enabled on channel 1." << std::endl;
+ }
}
}
else
@@ -1304,6 +1460,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
{
error = TRUE;
LL_WARNS("RenderState") << "GL does not have GL_TEXTURE_COORD_ARRAY enabled on channel 1." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "GL does not have GL_TEXTURE_COORD_ARRAY enabled on channel 1." << std::endl;
+ }
}
}
@@ -1313,6 +1473,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
{
error = TRUE;
LL_WARNS("RenderState") << "GL still has GL_TEXTURE_2D enabled on channel 1." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "GL still has GL_TEXTURE_2D enabled on channel 1." << std::endl;
+ }
}
}
else
@@ -1321,6 +1485,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
{
error = TRUE;
LL_WARNS("RenderState") << "GL does not have GL_TEXTURE_2D enabled on channel 1." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "GL does not have GL_TEXTURE_2D enabled on channel 1." << std::endl;
+ }
}
}
@@ -1339,13 +1507,24 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
{
error = TRUE;
LL_WARNS("RenderState") << "GL still has vertex attrib array " << i << " enabled." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "GL still has vertex attrib array " << i << " enabled." << std::endl;
+ }
}
}
}
if (error)
{
- LL_GL_ERRS << "GL client array corruption detected. " << msg << LL_ENDL;
+ if (gDebugSession)
+ {
+ ll_fail("LLGLState::checkClientArrays failed.");
+ }
+ else
+ {
+ LL_GL_ERRS << "GL client array corruption detected. " << msg << LL_ENDL;
+ }
}
}
@@ -1396,7 +1575,17 @@ LLGLState::~LLGLState()
{
if (gDebugGL)
{
- llassert_always(sStateMap[mState] == glIsEnabled(mState));
+ if (!gDebugSession)
+ {
+ llassert_always(sStateMap[mState] == glIsEnabled(mState));
+ }
+ else
+ {
+ if (sStateMap[mState] != glIsEnabled(mState))
+ {
+ ll_fail("GL enabled state does not match expected");
+ }
+ }
}
if (mIsEnabled != mWasEnabled)
@@ -1708,6 +1897,7 @@ void LLGLNamePool::release(GLuint name)
//static
void LLGLNamePool::upkeepPools()
{
+ LLMemType mt(LLMemType::MTYPE_UPKEEP_POOLS);
for (pool_list_t::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter)
{
LLGLNamePool* pool = *iter;
@@ -1729,6 +1919,16 @@ LLGLDepthTest::LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled, G
: mPrevDepthEnabled(sDepthEnabled), mPrevDepthFunc(sDepthFunc), mPrevWriteEnabled(sWriteEnabled)
{
stop_glerror();
+
+ checkState();
+
+ if (!depth_enabled)
+ { // always disable depth writes if depth testing is disabled
+ // GL spec defines this as a requirement, but some implementations allow depth writes with testing disabled
+ // The proper way to write to depth buffer with testing disabled is to enable testing and use a depth_func of GL_ALWAYS
+ write_enabled = FALSE;
+ }
+
if (depth_enabled != sDepthEnabled)
{
gGL.flush();
@@ -1752,6 +1952,7 @@ LLGLDepthTest::LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled, G
LLGLDepthTest::~LLGLDepthTest()
{
+ checkState();
if (sDepthEnabled != mPrevDepthEnabled )
{
gGL.flush();
@@ -1773,6 +1974,32 @@ LLGLDepthTest::~LLGLDepthTest()
}
}
+void LLGLDepthTest::checkState()
+{
+ if (gDebugGL)
+ {
+ GLint func = 0;
+ GLboolean mask = FALSE;
+
+ glGetIntegerv(GL_DEPTH_FUNC, &func);
+ glGetBooleanv(GL_DEPTH_WRITEMASK, &mask);
+
+ if (glIsEnabled(GL_DEPTH_TEST) != sDepthEnabled ||
+ sWriteEnabled != mask ||
+ sDepthFunc != func)
+ {
+ if (gDebugSession)
+ {
+ gFailLog << "Unexpected depth testing state." << std::endl;
+ }
+ else
+ {
+ LL_GL_ERRS << "Unexpected depth testing state." << LL_ENDL;
+ }
+ }
+ }
+}
+
LLGLClampToFarClip::LLGLClampToFarClip(glh::matrix4f P)
{
for (U32 i = 0; i < 4; i++)
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 00ff1e2f53..91421f3c95 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -37,6 +37,7 @@
#include <string>
#include <map>
+#include <list>
#include "llerror.h"
#include "v4color.h"
@@ -50,9 +51,17 @@
#include "glh/glh_linear.h"
extern BOOL gDebugGL;
+extern BOOL gDebugSession;
+extern std::ofstream gFailLog;
#define LL_GL_ERRS LL_ERRS("RenderState")
+void ll_init_fail_log(std::string filename);
+
+void ll_fail(std::string msg);
+
+void ll_close_fail_log();
+
class LLSD;
// Manage GL extensions...
@@ -88,6 +97,7 @@ public:
BOOL mHasOcclusionQuery;
BOOL mHasPointParameters;
BOOL mHasDrawBuffers;
+ BOOL mHasTextureRectangle;
// Other extensions.
BOOL mHasAnisotropic;
@@ -358,6 +368,35 @@ protected:
virtual void releaseName(GLuint name) = 0;
};
+/*
+ Interface for objects that need periodic GL updates applied to them.
+ Used to synchronize GL updates with GL thread.
+*/
+class LLGLUpdate
+{
+public:
+
+ static std::list<LLGLUpdate*> sGLQ;
+
+ BOOL mInQ;
+ LLGLUpdate()
+ : mInQ(FALSE)
+ {
+ }
+ virtual ~LLGLUpdate()
+ {
+ if (mInQ)
+ {
+ std::list<LLGLUpdate*>::iterator iter = std::find(sGLQ.begin(), sGLQ.end(), this);
+ if (iter != sGLQ.end())
+ {
+ sGLQ.erase(iter);
+ }
+ }
+ }
+ virtual void updateGL() = 0;
+};
+
extern LLMatrix4 gGLObliqueProjectionInverse;
#include "llglstates.h"
@@ -376,4 +415,6 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor
extern BOOL gClothRipple;
extern BOOL gNoRender;
+extern BOOL gGLActive;
+
#endif // LL_LLGL_H
diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
index c7178a5552..f33ae7d8f0 100644
--- a/indra/llrender/llglheaders.h
+++ b/indra/llrender/llglheaders.h
@@ -53,8 +53,6 @@
# include "GL/glxext.h"
//# define GLH_EXT_GET_PROC_ADDRESS(p) glXGetProcAddressARB((const GLubyte*)(p))
# define GLH_EXT_GET_PROC_ADDRESS(p) glXGetProcAddress((const GLubyte*)(p))
-// the X headers define 'Status'. Undefine to avoid confusion.
-#undef Status
// The __APPLE__ kludge is to make glh_extensions.h not symbol-clash horribly
// This header is distributed with SL. You'll find it in linden/libraries/include/GL/
@@ -277,8 +275,6 @@ extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT;
// Use glXGetProcAddressARB instead of glXGetProcAddress - the ARB symbol
// is considered 'legacy' but works on more machines.
# define GLH_EXT_GET_PROC_ADDRESS(p) glXGetProcAddressARB((const GLubyte*)(p))
-// Whee, the X headers define 'Status'. Undefine to avoid confusion.
-#undef Status
#endif // LL_LINUX && !LL_MESA_HEADLESS
#if LL_LINUX && defined(WINGDIAPI)
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 9e34144658..830617063b 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -408,7 +408,15 @@ S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode)
{
if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode)
{
- llerrs << "Texture channel " << index << " texture type corrupted." << llendl;
+ if (gDebugSession)
+ {
+ gFailLog << "Texture channel " << index << " texture type corrupted." << std::endl;
+ ll_fail("LLGLSLShader::disableTexture failed");
+ }
+ else
+ {
+ llerrs << "Texture channel " << index << " texture type corrupted." << llendl;
+ }
}
gGL.getTexUnit(index)->disable();
}
diff --git a/indra/llrender/llglstates.h b/indra/llrender/llglstates.h
index 4a51cac438..968a37cab0 100644
--- a/indra/llrender/llglstates.h
+++ b/indra/llrender/llglstates.h
@@ -46,6 +46,8 @@ public:
~LLGLDepthTest();
+ void checkState();
+
GLboolean mPrevDepthEnabled;
GLenum mPrevDepthFunc;
GLboolean mPrevWriteEnabled;
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index cdf626e16f..cd493481d5 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -43,10 +43,7 @@
#include "llmath.h"
#include "llgl.h"
#include "llrender.h"
-
-
//----------------------------------------------------------------------------
-
const F32 MIN_TEXTURE_LIFETIME = 10.f;
//statics
@@ -54,15 +51,42 @@ LLGLuint LLImageGL::sCurrentBoundTextures[MAX_GL_TEXTURE_UNITS] = { 0 };
U32 LLImageGL::sUniqueCount = 0;
U32 LLImageGL::sBindCount = 0;
-S32 LLImageGL::sGlobalTextureMemory = 0;
-S32 LLImageGL::sBoundTextureMemory = 0;
+S32 LLImageGL::sGlobalTextureMemoryInBytes = 0;
+S32 LLImageGL::sBoundTextureMemoryInBytes = 0;
S32 LLImageGL::sCurBoundTextureMemory = 0;
S32 LLImageGL::sCount = 0;
+std::list<U32> LLImageGL::sDeadTextureList;
BOOL LLImageGL::sGlobalUseAnisotropic = FALSE;
F32 LLImageGL::sLastFrameTime = 0.f;
+BOOL LLImageGL::sAllowReadBackRaw = FALSE ;
+LLImageGL* LLImageGL::sDefaultGLTexture = NULL ;
std::set<LLImageGL*> LLImageGL::sImageList;
+
+//****************************************************************************************************
+//The below for texture auditing use only
+//****************************************************************************************************
+//-----------------------
+//debug use
+BOOL gAuditTexture = FALSE ;
+#define MAX_TEXTURE_LOG_SIZE 22 //2048 * 2048
+std::vector<S32> LLImageGL::sTextureLoadedCounter(MAX_TEXTURE_LOG_SIZE + 1) ;
+std::vector<S32> LLImageGL::sTextureBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ;
+std::vector<S32> LLImageGL::sTextureCurBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ;
+S32 LLImageGL::sCurTexSizeBar = -1 ;
+S32 LLImageGL::sCurTexPickSize = -1 ;
+LLPointer<LLImageGL> LLImageGL::sHighlightTexturep = NULL;
+S32 LLImageGL::sMaxCatagories = 1 ;
+
+std::vector<S32> LLImageGL::sTextureMemByCategory;
+std::vector<S32> LLImageGL::sTextureMemByCategoryBound ;
+std::vector<S32> LLImageGL::sTextureCurMemByCategoryBound ;
+//------------------------
+//****************************************************************************************************
+//End for texture auditing use only
+//****************************************************************************************************
+
//**************************************************************************************
//below are functions for debug use
//do not delete them even though they are not currently being used.
@@ -87,9 +111,18 @@ void LLImageGL::checkTexSize() const
{
GLint texname;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &texname);
+ BOOL error = FALSE;
if (texname != mTexName)
{
- llerrs << "Invalid texture bound!" << llendl;
+ error = TRUE;
+ if (gDebugSession)
+ {
+ gFailLog << "Invalid texture bound!" << std::endl;
+ }
+ else
+ {
+ llerrs << "Invalid texture bound!" << llendl;
+ }
}
stop_glerror() ;
LLGLint x = 0, y = 0 ;
@@ -102,7 +135,20 @@ void LLImageGL::checkTexSize() const
}
if(x != (mWidth >> mCurrentDiscardLevel) || y != (mHeight >> mCurrentDiscardLevel))
{
- llerrs << "wrong texture size and discard level!" << llendl ;
+ error = TRUE;
+ if (gDebugSession)
+ {
+ gFailLog << "wrong texture size and discard level!" << std::endl;
+ }
+ else
+ {
+ llerrs << "wrong texture size and discard level!" << llendl ;
+ }
+ }
+
+ if (error)
+ {
+ ll_fail("LLImageGL::checkTexSize failed.");
}
}
}
@@ -110,6 +156,60 @@ void LLImageGL::checkTexSize() const
//**************************************************************************************
//----------------------------------------------------------------------------
+BOOL is_little_endian()
+{
+ S32 a = 0x12345678;
+ U8 *c = (U8*)(&a);
+
+ return (*c == 0x78) ;
+}
+//static
+void LLImageGL::initClass(S32 num_catagories)
+{
+ sMaxCatagories = num_catagories ;
+
+ sTextureMemByCategory.resize(sMaxCatagories);
+ sTextureMemByCategoryBound.resize(sMaxCatagories) ;
+ sTextureCurMemByCategoryBound.resize(sMaxCatagories) ;
+}
+
+//static
+void LLImageGL::cleanupClass()
+{
+ sTextureMemByCategory.clear() ;
+ sTextureMemByCategoryBound.clear() ;
+ sTextureCurMemByCategoryBound.clear() ;
+}
+
+//static
+void LLImageGL::setHighlightTexture(S32 category)
+{
+ const S32 dim = 128;
+ sHighlightTexturep = new LLImageGL() ;
+ LLPointer<LLImageRaw> image_raw = new LLImageRaw(dim,dim,3);
+ U8* data = image_raw->getData();
+ for (S32 i = 0; i<dim; i++)
+ {
+ for (S32 j = 0; j<dim; j++)
+ {
+ const S32 border = 2;
+ if (i<border || j<border || i>=(dim-border) || j>=(dim-border))
+ {
+ *data++ = 0xff;
+ *data++ = 0xff;
+ *data++ = 0xff;
+ }
+ else
+ {
+ *data++ = 0xff;
+ *data++ = 0xff;
+ *data++ = 0x00;
+ }
+ }
+ }
+ sHighlightTexturep->createGLTexture(0, image_raw, 0, TRUE, category);
+ image_raw = NULL;
+}
//static
S32 LLImageGL::dataFormatBits(S32 dataformat)
@@ -174,14 +274,34 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat)
void LLImageGL::updateStats(F32 current_time)
{
sLastFrameTime = current_time;
- sBoundTextureMemory = sCurBoundTextureMemory;
+ sBoundTextureMemoryInBytes = sCurBoundTextureMemory;
sCurBoundTextureMemory = 0;
+
+ if(gAuditTexture)
+ {
+ for(U32 i = 0 ; i < sTextureCurBoundCounter.size() ; i++)
+ {
+ sTextureBoundCounter[i] = sTextureCurBoundCounter[i] ;
+ sTextureCurBoundCounter[i] = 0 ;
+ }
+ for(U32 i = 0 ; i < sTextureCurMemByCategoryBound.size() ; i++)
+ {
+ sTextureMemByCategoryBound[i] = sTextureCurMemByCategoryBound[i] ;
+ sTextureCurMemByCategoryBound[i] = 0 ;
+ }
+ }
}
//static
-S32 LLImageGL::updateBoundTexMem(const S32 delta)
+S32 LLImageGL::updateBoundTexMem(const S32 mem, const S32 ncomponents, S32 category)
{
- LLImageGL::sCurBoundTextureMemory += delta;
+ if(gAuditTexture && ncomponents > 0 && category > -1)
+ {
+ sTextureCurBoundCounter[getTextureCounterIndex(mem / ncomponents)]++ ;
+ sTextureCurMemByCategoryBound[category] += mem ;
+ }
+
+ LLImageGL::sCurBoundTextureMemory += mem ;
return LLImageGL::sCurBoundTextureMemory;
}
@@ -195,6 +315,7 @@ void LLImageGL::destroyGL(BOOL save_state)
gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE);
}
+ sAllowReadBackRaw = true ;
for (std::set<LLImageGL*>::iterator iter = sImageList.begin();
iter != sImageList.end(); iter++)
{
@@ -204,7 +325,7 @@ void LLImageGL::destroyGL(BOOL save_state)
if (save_state && glimage->isGLTextureCreated() && glimage->mComponents)
{
glimage->mSaveData = new LLImageRaw;
- if(!glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false))
+ if(!glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false)) //necessary, keep it.
{
glimage->mSaveData = NULL ;
}
@@ -214,6 +335,7 @@ void LLImageGL::destroyGL(BOOL save_state)
stop_glerror();
}
}
+ sAllowReadBackRaw = false ;
}
//static
@@ -231,7 +353,7 @@ void LLImageGL::restoreGL()
{
if (glimage->getComponents() && glimage->mSaveData->getComponents())
{
- glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData);
+ glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData, 0, TRUE, glimage->getCategory());
stop_glerror();
}
glimage->mSaveData = NULL; // deletes data
@@ -241,6 +363,7 @@ void LLImageGL::restoreGL()
//----------------------------------------------------------------------------
+//for server side use only.
//static
BOOL LLImageGL::create(LLPointer<LLImageGL>& dest, BOOL usemipmaps)
{
@@ -248,12 +371,14 @@ BOOL LLImageGL::create(LLPointer<LLImageGL>& dest, BOOL usemipmaps)
return TRUE;
}
+//for server side use only.
BOOL LLImageGL::create(LLPointer<LLImageGL>& dest, U32 width, U32 height, U8 components, BOOL usemipmaps)
{
dest = new LLImageGL(width, height, components, usemipmaps);
return TRUE;
}
+//for server side use only.
BOOL LLImageGL::create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, BOOL usemipmaps)
{
dest = new LLImageGL(imageraw, usemipmaps);
@@ -303,42 +428,56 @@ LLImageGL::~LLImageGL()
void LLImageGL::init(BOOL usemipmaps)
{
-#ifdef DEBUG_MISS
- mMissed = FALSE;
-#endif
+ // keep these members in the same order as declared in llimagehl.h
+ // so that it is obvious by visual inspection if we forgot to
+ // init a field.
+
+ mTextureMemory = 0;
+ mLastBindTime = 0.f;
+
+ mPickMask = NULL;
+ mUseMipMaps = usemipmaps;
+ mHasExplicitFormat = FALSE;
+ mAutoGenMips = FALSE;
+
+ mIsMask = FALSE;
+ mNeedsAlphaAndPickMask = TRUE ;
+ mAlphaStride = 0 ;
+ mAlphaOffset = 0 ;
- mPickMask = NULL;
- mTextureState = NO_DELETE ;
- mTextureMemory = 0;
- mLastBindTime = 0.f;
+ mGLTextureCreated = FALSE ;
+ mTexName = 0;
+ mWidth = 0;
+ mHeight = 0;
+ mCurrentDiscardLevel = -1;
+
+ mDiscardLevelInAtlas = -1 ;
+ mTexelsInAtlas = 0 ;
+ mTexelsInGLTexture = 0 ;
+
+ mTarget = GL_TEXTURE_2D;
+ mBindTarget = LLTexUnit::TT_TEXTURE;
+ mHasMipMaps = false;
- mTarget = GL_TEXTURE_2D;
- mBindTarget = LLTexUnit::TT_TEXTURE;
- mUseMipMaps = usemipmaps;
- mHasMipMaps = false;
- mAutoGenMips = FALSE;
- mTexName = 0;
- mIsResident = 0;
+ mIsResident = 0;
+
+ mComponents = 0;
+ mMaxDiscardLevel = MAX_DISCARD_LEVEL;
mTexOptionsDirty = true;
mAddressMode = LLTexUnit::TAM_WRAP;
mFilterOption = LLTexUnit::TFO_ANISOTROPIC;
- mWidth = 0;
- mHeight = 0;
- mComponents = 0;
-
- mMaxDiscardLevel = MAX_DISCARD_LEVEL;
- mCurrentDiscardLevel = -1;
- mDontDiscard = FALSE;
mFormatInternal = -1;
mFormatPrimary = (LLGLenum) 0;
mFormatType = GL_UNSIGNED_BYTE;
mFormatSwapBytes = FALSE;
- mHasExplicitFormat = FALSE;
- mGLTextureCreated = FALSE ;
- mIsMask = FALSE;
+#ifdef DEBUG_MISS
+ mMissed = FALSE;
+#endif
+
+ mCategory = -1;
}
void LLImageGL::cleanup()
@@ -380,7 +519,7 @@ void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents)
// Check if dimensions are a power of two!
if (!checkSize(width,height))
{
- llerrs << llformat("Texture has non power of two dimention: %dx%d",width,height) << llendl;
+ llerrs << llformat("Texture has non power of two dimension: %dx%d",width,height) << llendl;
}
if (mTexName)
@@ -438,8 +577,12 @@ void LLImageGL::dump()
}
//----------------------------------------------------------------------------
+void LLImageGL::forceUpdateBindStats(void) const
+{
+ mLastBindTime = sLastFrameTime;
+}
-void LLImageGL::updateBindStats(void) const
+BOOL LLImageGL::updateBindStats(S32 tex_mem) const
{
if (mTexName != 0)
{
@@ -451,28 +594,18 @@ void LLImageGL::updateBindStats(void) const
{
// we haven't accounted for this texture yet this frame
sUniqueCount++;
- updateBoundTexMem(mTextureMemory);
+ updateBoundTexMem(tex_mem, mComponents, mCategory);
mLastBindTime = sLastFrameTime;
+
+ return TRUE ;
}
}
+ return FALSE ;
}
-//virtual
-bool LLImageGL::bindError(const S32 stage) const
-{
- return false;
-}
-
-//virtual
-bool LLImageGL::bindDefaultImage(const S32 stage) const
-{
- return false;
-}
-
-//virtual
-void LLImageGL::forceImmediateUpdate()
+F32 LLImageGL::getTimePassedSinceLastBound()
{
- return ;
+ return sLastFrameTime - mLastBindTime ;
}
void LLImageGL::setExplicitFormat( LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes )
@@ -487,6 +620,8 @@ void LLImageGL::setExplicitFormat( LLGLint internal_format, LLGLenum primary_for
else
mFormatType = type_format;
mFormatSwapBytes = swap_bytes;
+
+ calcAlphaChannelOffsetAndStride() ;
}
//----------------------------------------------------------------------------
@@ -502,20 +637,16 @@ void LLImageGL::setImage(const LLImageRaw* imageraw)
void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
{
-// LLFastTimer t1(LLFastTimer::FTM_TEMP1);
- llpushcallstacks ;
bool is_compressed = false;
if (mFormatPrimary >= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && mFormatPrimary <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
{
is_compressed = true;
}
-// LLFastTimer t2(LLFastTimer::FTM_TEMP2);
- gGL.getTexUnit(0)->bind(this);
+ llverify(gGL.getTexUnit(0)->bind(this));
if (mUseMipMaps)
{
-// LLFastTimer t2(LLFastTimer::FTM_TEMP3);
if (data_hasmips)
{
// NOTE: data_in points to largest image; smaller images
@@ -532,14 +663,13 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
}
if (is_compressed)
{
-// LLFastTimer t2(LLFastTimer::FTM_TEMP4);
S32 tex_size = dataFormatBytes(mFormatPrimary, w, h);
glCompressedTexImage2DARB(mTarget, gl_level, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in);
stop_glerror();
}
else
{
-// LLFastTimer t2(LLFastTimer::FTM_TEMP4);
+// LLFastTimer t2(FTM_TEMP4);
if(mFormatSwapBytes)
{
@@ -572,7 +702,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_GENERATE_MIPMAP_SGIS, TRUE);
stop_glerror();
{
-// LLFastTimer t2(LLFastTimer::FTM_TEMP4);
+// LLFastTimer t2(FTM_TEMP4);
if(mFormatSwapBytes)
{
@@ -632,7 +762,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
}
llassert(w > 0 && h > 0 && cur_mip_data);
{
-// LLFastTimer t1(LLFastTimer::FTM_TEMP4);
+// LLFastTimer t1(FTM_TEMP4);
if(mFormatSwapBytes)
{
glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
@@ -680,7 +810,6 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
}
else
{
-// LLFastTimer t2(LLFastTimer::FTM_TEMP5);
S32 w = getWidth();
S32 h = getHeight();
if (is_compressed)
@@ -716,12 +845,96 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
}
stop_glerror();
mGLTextureCreated = true;
- llpushcallstacks ;
}
-BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height)
+BOOL LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image)
+{
+ if (gGLManager.mIsDisabled)
+ {
+ llwarns << "Trying to create a texture while GL is disabled!" << llendl;
+ return FALSE;
+ }
+ llassert(gGLManager.mInited);
+ stop_glerror();
+
+ if (discard_level < 0)
+ {
+ llassert(mCurrentDiscardLevel >= 0);
+ discard_level = mCurrentDiscardLevel;
+ }
+ discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel);
+
+ // Actual image width/height = raw image width/height * 2^discard_level
+ S32 w = raw_image->getWidth() << discard_level;
+ S32 h = raw_image->getHeight() << discard_level;
+
+ // setSize may call destroyGLTexture if the size does not match
+ setSize(w, h, raw_image->getComponents());
+
+ if( !mHasExplicitFormat )
+ {
+ switch (mComponents)
+ {
+ case 1:
+ // Use luminance alpha (for fonts)
+ mFormatInternal = GL_LUMINANCE8;
+ mFormatPrimary = GL_LUMINANCE;
+ mFormatType = GL_UNSIGNED_BYTE;
+ break;
+ case 2:
+ // Use luminance alpha (for fonts)
+ mFormatInternal = GL_LUMINANCE8_ALPHA8;
+ mFormatPrimary = GL_LUMINANCE_ALPHA;
+ mFormatType = GL_UNSIGNED_BYTE;
+ break;
+ case 3:
+ mFormatInternal = GL_RGB8;
+ mFormatPrimary = GL_RGB;
+ mFormatType = GL_UNSIGNED_BYTE;
+ break;
+ case 4:
+ mFormatInternal = GL_RGBA8;
+ mFormatPrimary = GL_RGBA;
+ mFormatType = GL_UNSIGNED_BYTE;
+ break;
+ default:
+ llerrs << "Bad number of components for texture: " << (U32)getComponents() << llendl;
+ }
+ }
+
+ mCurrentDiscardLevel = discard_level;
+ mDiscardLevelInAtlas = discard_level;
+ mTexelsInAtlas = raw_image->getWidth() * raw_image->getHeight() ;
+ mLastBindTime = sLastFrameTime;
+ mGLTextureCreated = false ;
+
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, raw_image->getWidth());
+ stop_glerror();
+
+ if(mFormatSwapBytes)
+ {
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
+ stop_glerror();
+ }
+
+ return TRUE ;
+}
+
+void LLImageGL::postAddToAtlas()
+{
+ if(mFormatSwapBytes)
+ {
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
+ stop_glerror();
+ }
+
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption);
+ stop_glerror();
+}
+
+BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update)
{
- llpushcallstacks ;
if (!width || !height)
{
return TRUE;
@@ -737,7 +950,8 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
return FALSE;
}
- if (x_pos == 0 && y_pos == 0 && width == getWidth() && height == getHeight() && data_width == width && data_height == height)
+ // HACK: allow the caller to explicitly force the fast path (i.e. using glTexSubImage2D here instead of calling setImage) even when updating the full texture.
+ if (!force_fast_update && x_pos == 0 && y_pos == 0 && width == getWidth() && height == getHeight() && data_width == width && data_height == height)
{
setImage(datap, FALSE);
}
@@ -810,20 +1024,20 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
stop_glerror();
mGLTextureCreated = true;
}
- llpushcallstacks ;
return TRUE;
}
-BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height)
+BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update)
{
- return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height);
+ return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height, force_fast_update);
}
// Copy sub image from frame buffer
BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height)
{
- if (gGL.getTexUnit(0)->bind(this, true))
+ if (gGL.getTexUnit(0)->bind(this, false, true))
{
+ //checkTexSize() ;
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height);
mGLTextureCreated = true;
stop_glerror();
@@ -844,13 +1058,17 @@ void LLImageGL::generateTextures(S32 numTextures, U32 *textures)
// static
void LLImageGL::deleteTextures(S32 numTextures, U32 *textures)
{
- glDeleteTextures(numTextures, (GLuint*)textures);
+ for (S32 i = 0; i < numTextures; i++)
+ {
+ sDeadTextureList.push_back(textures[i]);
+ }
}
// static
void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels)
{
glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, pixels);
+ stop_glerror();
}
//create an empty GL texture: just create a texture name
@@ -883,14 +1101,14 @@ BOOL LLImageGL::createGLTexture()
return TRUE ;
}
-BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/)
+BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category)
{
- llpushcallstacks ;
if (gGLManager.mIsDisabled)
{
llwarns << "Trying to create a texture while GL is disabled!" << llendl;
return FALSE;
}
+
mGLTextureCreated = false ;
llassert(gGLManager.mInited);
stop_glerror();
@@ -903,8 +1121,10 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel);
// Actual image width/height = raw image width/height * 2^discard_level
- S32 w = imageraw->getWidth() << discard_level;
- S32 h = imageraw->getHeight() << discard_level;
+ S32 raw_w = imageraw->getWidth() ;
+ S32 raw_h = imageraw->getHeight() ;
+ S32 w = raw_w << discard_level;
+ S32 h = raw_h << discard_level;
// setSize may call destroyGLTexture if the size does not match
setSize(w, h, imageraw->getComponents());
@@ -938,15 +1158,25 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
default:
llerrs << "Bad number of components for texture: " << (U32)getComponents() << llendl;
}
+
+ calcAlphaChannelOffsetAndStride() ;
}
+ if(!to_create) //not create a gl texture
+ {
+ destroyGLTexture();
+ mCurrentDiscardLevel = discard_level;
+ mLastBindTime = sLastFrameTime;
+ return TRUE ;
+ }
+
+ setCategory(category) ;
const U8* rawdata = imageraw->getData();
return createGLTexture(discard_level, rawdata, FALSE, usename);
}
BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename)
{
- llpushcallstacks ;
llassert(data_in);
if (discard_level < 0)
@@ -975,7 +1205,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
LLImageGL::generateTextures(1, &mTexName);
stop_glerror();
{
-// LLFastTimer t1(LLFastTimer::FTM_TEMP6);
llverify(gGL.getTexUnit(0)->bind(this));
glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel-discard_level);
@@ -1013,92 +1242,36 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
if (old_name != 0)
{
- sGlobalTextureMemory -= mTextureMemory;
+ sGlobalTextureMemoryInBytes -= mTextureMemory;
+
+ if(gAuditTexture)
+ {
+ decTextureCounter(mTextureMemory, mComponents, mCategory) ;
+ }
+
LLImageGL::deleteTextures(1, &old_name);
+
stop_glerror();
}
mTextureMemory = getMipBytes(discard_level);
- sGlobalTextureMemory += mTextureMemory;
- setActive() ;
+ sGlobalTextureMemoryInBytes += mTextureMemory;
+ mTexelsInGLTexture = getWidth() * getHeight() ;
+ if(gAuditTexture)
+ {
+ incTextureCounter(mTextureMemory, mComponents, mCategory) ;
+ }
// mark this as bound at this point, so we don't throw it out immediately
mLastBindTime = sLastFrameTime;
-
- llpushcallstacks ;
return TRUE;
}
-BOOL LLImageGL::setDiscardLevel(S32 discard_level)
-{
- llassert(discard_level >= 0);
- llassert(mCurrentDiscardLevel >= 0);
-
- discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel);
-
- if (mDontDiscard)
- {
- // don't discard!
- return FALSE;
- }
- else if (discard_level == mCurrentDiscardLevel)
- {
- // nothing to do
- return FALSE;
- }
- else if (discard_level < mCurrentDiscardLevel)
- {
- // larger image
- dump();
- llerrs << "LLImageGL::setDiscardLevel() called with larger discard level; use createGLTexture()" << llendl;
- return FALSE;
- }
- else if (mUseMipMaps)
- {
- LLPointer<LLImageRaw> imageraw = new LLImageRaw;
- while(discard_level > mCurrentDiscardLevel)
- {
- if (readBackRaw(discard_level, imageraw, false))
- {
- break;
- }
- discard_level--;
- }
- if (discard_level == mCurrentDiscardLevel)
- {
- // unable to increase the discard level
- return FALSE;
- }
- return createGLTexture(discard_level, imageraw);
- }
- else
- {
-#if !LL_LINUX && !LL_SOLARIS
- // *FIX: This should not be skipped for the linux client.
- llerrs << "LLImageGL::setDiscardLevel() called on image without mipmaps" << llendl;
-#endif
- return FALSE;
- }
-}
-
-BOOL LLImageGL::isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents)
-{
- assert_glerror();
- S32 gl_discard = discard_level - mCurrentDiscardLevel;
- LLGLint glwidth = 0;
- glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_WIDTH, (GLint*)&glwidth);
- LLGLint glheight = 0;
- glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_HEIGHT, (GLint*)&glheight);
- LLGLint glcomponents = 0 ;
- glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_INTERNAL_FORMAT, (GLint*)&glcomponents);
- assert_glerror();
-
- return glwidth >= image_width && glheight >= image_height && (GL_RGB8 == glcomponents || GL_RGBA8 == glcomponents) ;
-}
-
-BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok)
+BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const
{
- llpushcallstacks ;
+ llassert_always(sAllowReadBackRaw) ;
+ //llerrs << "should not call this function!" << llendl ;
+
if (discard_level < 0)
{
discard_level = mCurrentDiscardLevel;
@@ -1201,37 +1374,53 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
return FALSE ;
}
//-----------------------------------------------------------------------------------------------
- llpushcallstacks ;
+
return TRUE ;
}
-void LLImageGL::destroyGLTexture()
+void LLImageGL::deleteDeadTextures()
{
- if (mTexName != 0)
+ while (!sDeadTextureList.empty())
{
- stop_glerror();
-
+ GLuint tex = sDeadTextureList.front();
+ sDeadTextureList.pop_front();
for (int i = 0; i < gGLManager.mNumTextureUnits; i++)
{
- if (sCurrentBoundTextures[i] == mTexName)
+ if (sCurrentBoundTextures[i] == tex)
{
gGL.getTexUnit(i)->unbind(LLTexUnit::TT_TEXTURE);
stop_glerror();
}
}
-
- sGlobalTextureMemory -= mTextureMemory;
- mTextureMemory = 0;
-
- LLImageGL::deleteTextures(1, &mTexName);
- mTextureState = DELETED ;
+
+ glDeleteTextures(1, &tex);
+ stop_glerror();
+ }
+}
+
+void LLImageGL::destroyGLTexture()
+{
+ if (mTexName != 0)
+ {
+ if(mTextureMemory)
+ {
+ if(gAuditTexture)
+ {
+ decTextureCounter(mTextureMemory, mComponents, mCategory) ;
+ }
+ sGlobalTextureMemoryInBytes -= mTextureMemory;
+ mTextureMemory = 0;
+ }
+
+ LLImageGL::deleteTextures(1, &mTexName);
mTexName = 0;
mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel.
mGLTextureCreated = FALSE ;
- stop_glerror();
}
}
+
+
//----------------------------------------------------------------------------
void LLImageGL::setAddressMode(LLTexUnit::eTextureAddressMode mode)
@@ -1257,12 +1446,12 @@ void LLImageGL::setFilteringOption(LLTexUnit::eTextureFilterOptions option)
mFilterOption = option;
}
- if (gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName)
+ if (mTexName != 0 && gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName)
{
gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->setTextureFilteringOption(option);
mTexOptionsDirty = false;
+ stop_glerror();
}
- stop_glerror();
}
BOOL LLImageGL::getIsResident(BOOL test_now)
@@ -1338,6 +1527,11 @@ S32 LLImageGL::getMipBytes(S32 discard_level) const
return res;
}
+BOOL LLImageGL::isJustBound() const
+{
+ return (BOOL)(sLastFrameTime - mLastBindTime < 0.5f);
+}
+
BOOL LLImageGL::getBoundRecently() const
{
return (BOOL)(sLastFrameTime - mLastBindTime < MIN_TEXTURE_LIFETIME);
@@ -1349,40 +1543,104 @@ void LLImageGL::setTarget(const LLGLenum target, const LLTexUnit::eTextureType b
mBindTarget = bind_target;
}
-void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h)
+const S8 INVALID_OFFSET = -99 ;
+void LLImageGL::setNeedsAlphaAndPickMask(BOOL need_mask)
{
- if (mFormatType != GL_UNSIGNED_BYTE)
+ if(mNeedsAlphaAndPickMask != need_mask)
{
- llwarns << "Cannot analyze alpha for image with format type " << std::hex << mFormatType << std::dec << llendl;
+ mNeedsAlphaAndPickMask = need_mask;
+
+ if(mNeedsAlphaAndPickMask)
+ {
+ mAlphaOffset = 0 ;
+ }
+ else //do not need alpha mask
+ {
+ mAlphaOffset = INVALID_OFFSET ;
+ mIsMask = FALSE;
+ }
+ }
+}
+
+void LLImageGL::calcAlphaChannelOffsetAndStride()
+{
+ if(mAlphaOffset == INVALID_OFFSET)//do not need alpha mask
+ {
+ return ;
}
- U32 stride = 0;
+ mAlphaStride = -1 ;
switch (mFormatPrimary)
{
case GL_LUMINANCE:
case GL_ALPHA:
- stride = 1;
+ mAlphaStride = 1;
break;
case GL_LUMINANCE_ALPHA:
- stride = 2;
+ mAlphaStride = 2;
break;
case GL_RGB:
- //no alpha
+ mNeedsAlphaAndPickMask = FALSE ;
mIsMask = FALSE;
- return;
+ return ; //no alpha channel.
case GL_RGBA:
- stride = 4;
+ mAlphaStride = 4;
break;
case GL_BGRA_EXT:
- stride = 4;
+ mAlphaStride = 4;
break;
default:
- llwarns << "Cannot analyze alpha of image with primary format " << std::hex << mFormatPrimary << std::dec << llendl;
- return;
+ break;
+ }
+
+ mAlphaOffset = -1 ;
+ if (mFormatType == GL_UNSIGNED_BYTE)
+ {
+ mAlphaOffset = mAlphaStride - 1 ;
+ }
+ else if(is_little_endian())
+ {
+ if (mFormatType == GL_UNSIGNED_INT_8_8_8_8)
+ {
+ mAlphaOffset = 0 ;
+ }
+ else if (mFormatType == GL_UNSIGNED_INT_8_8_8_8_REV)
+ {
+ mAlphaOffset = 3 ;
+ }
+ }
+ else //big endian
+ {
+ if (mFormatType == GL_UNSIGNED_INT_8_8_8_8)
+ {
+ mAlphaOffset = 3 ;
+ }
+ else if (mFormatType == GL_UNSIGNED_INT_8_8_8_8_REV)
+ {
+ mAlphaOffset = 0 ;
+ }
+ }
+
+ if( mAlphaStride < 1 || //unsupported format
+ mAlphaOffset < 0 || //unsupported type
+ (mFormatPrimary == GL_BGRA_EXT && mFormatType != GL_UNSIGNED_BYTE)) //unknown situation
+ {
+ llwarns << "Cannot analyze alpha for image with format type " << std::hex << mFormatType << std::dec << llendl;
+
+ mNeedsAlphaAndPickMask = FALSE ;
+ mIsMask = FALSE;
+ }
+}
+
+void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h)
+{
+ if(!mNeedsAlphaAndPickMask)
+ {
+ return ;
}
U32 length = w * h;
- const GLubyte* current = ((const GLubyte*) data_in)+stride-1;
+ const GLubyte* current = ((const GLubyte*) data_in) + mAlphaOffset ;
S32 sample[16];
memset(sample, 0, sizeof(S32)*16);
@@ -1390,7 +1648,7 @@ void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h)
for (U32 i = 0; i < length; i++)
{
++sample[*current/16];
- current += stride;
+ current += mAlphaStride ;
}
U32 total = 0;
@@ -1409,62 +1667,16 @@ void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h)
}
}
-BOOL LLImageGL::isDeleted()
-{
- return mTextureState == DELETED ;
-}
-
-BOOL LLImageGL::isInactive()
-{
- return mTextureState == INACTIVE ;
-}
-
-BOOL LLImageGL::isDeletionCandidate()
-{
- return mTextureState == DELETION_CANDIDATE ;
-}
-
-void LLImageGL::setDeletionCandidate()
-{
- if(mTexName && (mTextureState == INACTIVE))
- {
- mTextureState = DELETION_CANDIDATE ;
- }
-}
-
-void LLImageGL::forceActive()
-{
- mTextureState = ACTIVE ;
-}
-
-void LLImageGL::setActive()
-{
- if(mTextureState != NO_DELETE)
- {
- mTextureState = ACTIVE ;
- }
-}
-
-//set the texture inactive
-void LLImageGL::setInactive()
+//----------------------------------------------------------------------------
+void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
{
- if(mTexName && (mTextureState == ACTIVE) && !getBoundRecently())
+ if(!mNeedsAlphaAndPickMask)
{
- mTextureState = INACTIVE ;
+ return ;
}
-}
-//set the texture to stay in memory
-void LLImageGL::setNoDelete()
-{
- mTextureState = NO_DELETE ;
-}
-
-//----------------------------------------------------------------------------
-void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
-{
if (mFormatType != GL_UNSIGNED_BYTE ||
- mFormatPrimary != GL_RGBA)
+ mFormatPrimary != GL_RGBA)
{
//cannot generate a pick mask for this texture
delete [] mPickMask;
@@ -1524,12 +1736,25 @@ BOOL LLImageGL::getMask(const LLVector2 &tc)
if (u < 0.f || u > 1.f ||
v < 0.f || v > 1.f)
{
- llerrs << "WTF?" << llendl;
+ LL_WARNS_ONCE("render") << "Ugh, u/v out of range in image mask pick" << LL_ENDL;
+ u = v = 0.f;
+ llassert(false);
}
S32 x = (S32)(u * width);
S32 y = (S32)(v * height);
+ if (x >= width)
+ {
+ LL_WARNS_ONCE("render") << "Ooh, width overrun on pick mask read, that coulda been bad." << LL_ENDL;
+ x = llmax(0, width-1);
+ }
+ if (y >= height)
+ {
+ LL_WARNS_ONCE("render") << "Ooh, height overrun on pick mask read, that woulda been bad." << LL_ENDL;
+ y = llmax(0, height-1);
+ }
+
S32 idx = y*width+x;
S32 offset = idx%8;
@@ -1539,6 +1764,88 @@ BOOL LLImageGL::getMask(const LLVector2 &tc)
return res;
}
+void LLImageGL::setCategory(S32 category)
+{
+ if(!gAuditTexture)
+ {
+ return ;
+ }
+ if(mCategory != category)
+ {
+ if(mCategory > -1)
+ {
+ sTextureMemByCategory[mCategory] -= mTextureMemory ;
+ }
+ if(category > -1 && category < sMaxCatagories)
+ {
+ sTextureMemByCategory[category] += mTextureMemory ;
+ mCategory = category;
+ }
+ else
+ {
+ mCategory = -1 ;
+ }
+ }
+}
+
+//for debug use
+//val is a "power of two" number
+S32 LLImageGL::getTextureCounterIndex(U32 val)
+{
+ //index range is [0, MAX_TEXTURE_LOG_SIZE].
+ if(val < 2)
+ {
+ return 0 ;
+ }
+ else if(val >= (1 << MAX_TEXTURE_LOG_SIZE))
+ {
+ return MAX_TEXTURE_LOG_SIZE ;
+ }
+ else
+ {
+ S32 ret = 0 ;
+ while(val >>= 1)
+ {
+ ++ret;
+ }
+ return ret ;
+ }
+}
+
+//static
+void LLImageGL::incTextureCounter(U32 val, S32 ncomponents, S32 category)
+{
+ sTextureLoadedCounter[getTextureCounterIndex(val)]++ ;
+ sTextureMemByCategory[category] += (S32)val * ncomponents ;
+}
+
+//static
+void LLImageGL::decTextureCounter(U32 val, S32 ncomponents, S32 category)
+{
+ sTextureLoadedCounter[getTextureCounterIndex(val)]-- ;
+ sTextureMemByCategory[category] += (S32)val * ncomponents ;
+}
+
+void LLImageGL::setCurTexSizebar(S32 index, BOOL set_pick_size)
+{
+ sCurTexSizeBar = index ;
+
+ if(set_pick_size)
+ {
+ sCurTexPickSize = (1 << index) ;
+ }
+ else
+ {
+ sCurTexPickSize = -1 ;
+ }
+}
+void LLImageGL::resetCurTexSizebar()
+{
+ sCurTexSizeBar = -1 ;
+ sCurTexPickSize = -1 ;
+}
+//----------------------------------------------------------------------------
+
//----------------------------------------------------------------------------
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 4f737bcaae..facfb7bd62 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -37,23 +37,32 @@
#include "llimage.h"
#include "llgltypes.h"
-#include "llmemory.h"
+#include "llpointer.h"
+#include "llrefcount.h"
#include "v2math.h"
#include "llrender.h"
+class LLTextureAtlas ;
+#define BYTES_TO_MEGA_BYTES(x) ((x) >> 20)
+#define MEGA_BYTES_TO_BYTES(x) ((x) << 20)
//============================================================================
-
class LLImageGL : public LLRefCount
{
friend class LLTexUnit;
public:
+ static std::list<U32> sDeadTextureList;
+
+ static void deleteDeadTextures();
+
// Size calculation
static S32 dataFormatBits(S32 dataformat);
static S32 dataFormatBytes(S32 dataformat, S32 width, S32 height);
static S32 dataFormatComponents(S32 dataformat);
- void updateBindStats(void) const;
+ BOOL updateBindStats(S32 tex_mem) const ;
+ F32 getTimePassedSinceLastBound();
+ void forceUpdateBindStats(void) const;
// needs to be called every frame
static void updateStats(F32 current_time);
@@ -62,17 +71,18 @@ public:
static void destroyGL(BOOL save_state = TRUE);
static void restoreGL();
- // Sometimes called externally for textures not using LLImageGL (should go away...)
- static S32 updateBoundTexMem(const S32 delta);
-
- static bool checkSize(S32 width, S32 height);
+ // Sometimes called externally for textures not using LLImageGL (should go away...)
+ static S32 updateBoundTexMem(const S32 mem, const S32 ncomponents, S32 category) ;
+ static bool checkSize(S32 width, S32 height);
+
+ //for server side use only.
// Not currently necessary for LLImageGL, but required in some derived classes,
// so include for compatability
static BOOL create(LLPointer<LLImageGL>& dest, BOOL usemipmaps = TRUE);
static BOOL create(LLPointer<LLImageGL>& dest, U32 width, U32 height, U8 components, BOOL usemipmaps = TRUE);
static BOOL create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, BOOL usemipmaps = TRUE);
-
+
public:
LLImageGL(BOOL usemipmaps = TRUE);
LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps = TRUE);
@@ -82,14 +92,13 @@ protected:
virtual ~LLImageGL();
void analyzeAlpha(const void* data_in, S32 w, S32 h);
+ void calcAlphaChannelOffsetAndStride();
public:
virtual void dump(); // debugging info to llinfos
- virtual bool bindError(const S32 stage = 0) const;
- virtual bool bindDefaultImage(const S32 stage = 0) const;
- virtual void forceImmediateUpdate() ;
-
+
void setSize(S32 width, S32 height, S32 ncomponents);
+ void setComponents(S32 ncomponents) { mComponents = (S8)ncomponents ;}
// These 3 functions currently wrap glGenTextures(), glDeleteTextures(), and glTexImage2D()
// for tracking purposes and will be deprecated in the future
@@ -98,20 +107,21 @@ public:
static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels);
BOOL createGLTexture() ;
- BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0);
+ BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE,
+ S32 category = sMaxCatagories - 1);
BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0);
void setImage(const LLImageRaw* imageraw);
void setImage(const U8* data_in, BOOL data_hasmips = FALSE);
- BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height);
- BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height);
+ BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE);
+ BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE);
BOOL setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height);
- BOOL setDiscardLevel(S32 discard_level);
+
// Read back a raw image for this discard level, if it exists
- BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok);
+ BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const;
void destroyGLTexture();
void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE);
- void dontDiscard() { mDontDiscard = 1; mTextureState = NO_DELETE; }
+ void setComponents(S8 ncomponents) { mComponents = ncomponents; }
S32 getDiscardLevel() const { return mCurrentDiscardLevel; }
S32 getMaxDiscardLevel() const { return mMaxDiscardLevel; }
@@ -124,7 +134,9 @@ public:
S32 getBytes(S32 discard_level = -1) const;
S32 getMipBytes(S32 discard_level = -1) const;
BOOL getBoundRecently() const;
+ BOOL isJustBound() const;
LLGLenum getPrimaryFormat() const { return mFormatPrimary; }
+ LLGLenum getFormatType() const { return mFormatType; }
BOOL getHasGLTexture() const { return mTexName != 0; }
LLGLuint getTexName() const { return mTexName; }
@@ -140,11 +152,7 @@ public:
void setGLTextureCreated (bool initialized) { mGLTextureCreated = initialized; }
BOOL getUseMipMaps() const { return mUseMipMaps; }
- void setUseMipMaps(BOOL usemips) { mUseMipMaps = usemips; }
- BOOL getUseDiscard() const { return mUseMipMaps && !mDontDiscard; }
- BOOL getDontDiscard() const { return mDontDiscard; }
-
- BOOL isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents) ;
+ void setUseMipMaps(BOOL usemips) { mUseMipMaps = usemips; }
void updatePickMask(S32 width, S32 height, const U8* data_in);
BOOL getMask(const LLVector2 &tc);
@@ -163,24 +171,25 @@ public:
void setFilteringOption(LLTexUnit::eTextureFilterOptions option);
LLTexUnit::eTextureFilterOptions getFilteringOption(void) const { return mFilterOption; }
- BOOL isDeleted() ;
- BOOL isInactive() ;
- BOOL isDeletionCandidate();
- void setDeletionCandidate() ;
- void setInactive() ;
- void setActive() ;
- void forceActive() ;
- void setNoDelete() ;
+ LLGLenum getTexTarget()const { return mTarget ;}
+ S8 getDiscardLevelInAtlas()const {return mDiscardLevelInAtlas;}
+ U32 getTexelsInAtlas()const { return mTexelsInAtlas ;}
+ U32 getTexelsInGLTexture()const {return mTexelsInGLTexture;}
-protected:
+
void init(BOOL usemipmaps);
virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized. Be careful when using this in derived class destructors
+ void setNeedsAlphaAndPickMask(BOOL need_mask);
+
+ BOOL preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image);
+ void postAddToAtlas() ;
+
public:
// Various GL/Rendering options
S32 mTextureMemory;
mutable F32 mLastBindTime; // last time this was bound, by discard level
-
+
private:
LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL
U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel
@@ -189,12 +198,19 @@ private:
S8 mAutoGenMips;
BOOL mIsMask;
-
+ BOOL mNeedsAlphaAndPickMask;
+ S8 mAlphaStride ;
+ S8 mAlphaOffset ;
+
bool mGLTextureCreated ;
LLGLuint mTexName;
U16 mWidth;
U16 mHeight;
S8 mCurrentDiscardLevel;
+
+ S8 mDiscardLevelInAtlas;
+ U32 mTexelsInAtlas ;
+ U32 mTexelsInGLTexture;
protected:
LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps)
@@ -205,28 +221,15 @@ protected:
S8 mComponents;
S8 mMaxDiscardLevel;
- S8 mDontDiscard; // Keep full res version of this image (for UI, etc)
-
+
bool mTexOptionsDirty;
LLTexUnit::eTextureAddressMode mAddressMode; // Defaults to TAM_WRAP
- LLTexUnit::eTextureFilterOptions mFilterOption; // Defaults to TFO_TRILINEAR
-
+ LLTexUnit::eTextureFilterOptions mFilterOption; // Defaults to TFO_ANISOTROPIC
LLGLint mFormatInternal; // = GL internalformat
LLGLenum mFormatPrimary; // = GL format (pixel data format)
LLGLenum mFormatType;
BOOL mFormatSwapBytes;// if true, use glPixelStorei(GL_UNPACK_SWAP_BYTES, 1)
-
-protected:
- typedef enum
- {
- DELETED = 0, //removed from memory
- DELETION_CANDIDATE, //ready to be removed from memory
- INACTIVE, //not be used for the last certain period (i.e., 30 seconds).
- ACTIVE, //just being used, can become inactive if not being used for a certain time (10 seconds).
- NO_DELETE = 99 //stay in memory, can not be removed.
- } LLGLTexureState;
- LLGLTexureState mTextureState ;
// STATICS
public:
@@ -234,22 +237,74 @@ public:
static S32 sCount;
static F32 sLastFrameTime;
-
+
static LLGLuint sCurrentBoundTextures[MAX_GL_TEXTURE_UNITS]; // Currently bound texture ID
// Global memory statistics
- static S32 sGlobalTextureMemory; // Tracks main memory texmem
- static S32 sBoundTextureMemory; // Tracks bound texmem for last completed frame
+ static S32 sGlobalTextureMemoryInBytes; // Tracks main memory texmem
+ static S32 sBoundTextureMemoryInBytes; // Tracks bound texmem for last completed frame
static S32 sCurBoundTextureMemory; // Tracks bound texmem for current frame
static U32 sBindCount; // Tracks number of texture binds for current frame
static U32 sUniqueCount; // Tracks number of unique texture binds for current frame
static BOOL sGlobalUseAnisotropic;
+ static LLImageGL* sDefaultGLTexture ;
+ static BOOL sAutomatedTest;
+
#if DEBUG_MISS
BOOL mMissed; // Missed on last bind?
BOOL getMissed() const { return mMissed; };
#else
BOOL getMissed() const { return FALSE; };
#endif
+
+public:
+ static void initClass(S32 num_catagories) ;
+ static void cleanupClass() ;
+private:
+ static S32 sMaxCatagories ;
+
+ //the flag to allow to call readBackRaw(...).
+ //can be removed if we do not use that function at all.
+ static BOOL sAllowReadBackRaw ;
+//
+//****************************************************************************************************
+//The below for texture auditing use only
+//****************************************************************************************************
+private:
+ S32 mCategory ;
+public:
+ void setCategory(S32 category) ;
+ S32 getCategory()const {return mCategory ;}
+
+ //for debug use: show texture size distribution
+ //----------------------------------------
+ static LLPointer<LLImageGL> sHighlightTexturep; //default texture to replace normal textures
+ static std::vector<S32> sTextureLoadedCounter ;
+ static std::vector<S32> sTextureBoundCounter ;
+ static std::vector<S32> sTextureCurBoundCounter ;
+ static S32 sCurTexSizeBar ;
+ static S32 sCurTexPickSize ;
+
+ static void setHighlightTexture(S32 category) ;
+ static S32 getTextureCounterIndex(U32 val) ;
+ static void incTextureCounter(U32 val, S32 ncomponents, S32 category) ;
+ static void decTextureCounter(U32 val, S32 ncomponents, S32 category) ;
+ static void setCurTexSizebar(S32 index, BOOL set_pick_size = TRUE) ;
+ static void resetCurTexSizebar();
+ //----------------------------------------
+
+ //for debug use: show texture category distribution
+ //----------------------------------------
+
+ static std::vector<S32> sTextureMemByCategory;
+ static std::vector<S32> sTextureMemByCategoryBound ;
+ static std::vector<S32> sTextureCurMemByCategoryBound ;
+ //----------------------------------------
+//****************************************************************************************************
+//End of definitions for texture auditing use only
+//****************************************************************************************************
+
};
+extern BOOL gAuditTexture;
#endif // LL_LLIMAGEGL_H
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 6bb217a9c2..f97d81126e 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -38,16 +38,18 @@
#include "llcubemap.h"
#include "llimagegl.h"
#include "llrendertarget.h"
+#include "lltexture.h"
LLRender gGL;
// Handy copies of last good GL matrices
F64 gGLModelView[16];
F64 gGLLastModelView[16];
+F64 gGLLastProjection[16];
F64 gGLProjection[16];
S32 gGLViewport[4];
-static const U32 LL_NUM_TEXTURE_LAYERS = 8;
+static const U32 LL_NUM_TEXTURE_LAYERS = 16;
static GLenum sGLTextureType[] =
{
@@ -160,6 +162,8 @@ void LLTexUnit::enable(eTextureType type)
disable(); // Force a disable of a previous texture type if it's enabled.
}
mCurrTexType = type;
+
+ gGL.flush();
glEnable(sGLTextureType[type]);
}
}
@@ -177,35 +181,89 @@ void LLTexUnit::disable(void)
}
}
-bool LLTexUnit::bind(LLImageGL* texture, bool forceBind)
+bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
{
stop_glerror();
if (mIndex < 0) return false;
gGL.flush();
- if (texture == NULL)
+ LLImageGL* gl_tex = NULL ;
+ if (texture == NULL || !(gl_tex = texture->getGLTexture()))
{
llwarns << "NULL LLTexUnit::bind texture" << llendl;
return false;
}
-
- if (!texture->getTexName()) //if texture does not exist
+
+ if (!gl_tex->getTexName()) //if texture does not exist
{
//if deleted, will re-generate it immediately
texture->forceImmediateUpdate() ;
+ gl_tex->forceUpdateBindStats() ;
return texture->bindDefaultImage(mIndex);
}
+ //in audit, replace the selected texture by the default one.
+ if(gAuditTexture && for_rendering && LLImageGL::sCurTexPickSize > 0)
+ {
+ if(texture->getWidth() * texture->getHeight() == LLImageGL::sCurTexPickSize)
+ {
+ gl_tex->updateBindStats(gl_tex->mTextureMemory);
+ return bind(LLImageGL::sHighlightTexturep.get());
+ }
+ }
+ if ((mCurrTexture != gl_tex->getTexName()) || forceBind)
+ {
+ activate();
+ enable(gl_tex->getTarget());
+ mCurrTexture = gl_tex->getTexName();
+ glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture);
+ if(gl_tex->updateBindStats(gl_tex->mTextureMemory))
+ {
+ texture->setActive() ;
+ texture->updateBindStatsForTester() ;
+ }
+ mHasMipMaps = gl_tex->mHasMipMaps;
+ if (gl_tex->mTexOptionsDirty)
+ {
+ gl_tex->mTexOptionsDirty = false;
+ setTextureAddressMode(gl_tex->mAddressMode);
+ setTextureFilteringOption(gl_tex->mFilterOption);
+ }
+ }
+ return true;
+}
+
+bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind)
+{
+ stop_glerror();
+ if (mIndex < 0) return false;
+
+ if(!texture)
+ {
+ llwarns << "NULL LLTexUnit::bind texture" << llendl;
+ return false;
+ }
+
+ if(!texture->getTexName())
+ {
+ if(LLImageGL::sDefaultGLTexture && LLImageGL::sDefaultGLTexture->getTexName())
+ {
+ return bind(LLImageGL::sDefaultGLTexture) ;
+ }
+ return false ;
+ }
+
+ gGL.flush();
+
if ((mCurrTexture != texture->getTexName()) || forceBind)
{
activate();
enable(texture->getTarget());
mCurrTexture = texture->getTexName();
glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture);
- texture->updateBindStats();
- texture->setActive() ;
+ texture->updateBindStats(texture->mTextureMemory);
mHasMipMaps = texture->mHasMipMaps;
if (texture->mTexOptionsDirty)
{
@@ -214,6 +272,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool forceBind)
setTextureFilteringOption(texture->mFilterOption);
}
}
+
return true;
}
@@ -238,7 +297,7 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap)
mCurrTexture = cubeMap->mImages[0]->getTexName();
glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mCurrTexture);
mHasMipMaps = cubeMap->mImages[0]->mHasMipMaps;
- cubeMap->mImages[0]->updateBindStats();
+ cubeMap->mImages[0]->updateBindStats(cubeMap->mImages[0]->mTextureMemory);
if (cubeMap->mImages[0]->mTexOptionsDirty)
{
cubeMap->mImages[0]->mTexOptionsDirty = false;
@@ -266,6 +325,11 @@ bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth)
if (bindDepth)
{
+ if (renderTarget->hasStencil())
+ {
+ llerrs << "Cannot bind a render buffer for sampling. Allocate render target without a stencil buffer if sampling of depth buffer is required." << llendl;
+ }
+
bindManual(renderTarget->getUsage(), renderTarget->getDepth());
}
else
@@ -279,15 +343,21 @@ bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth)
bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips)
{
- if (mIndex < 0 || mCurrTexture == texture) return false;
-
- gGL.flush();
+ if (mIndex < 0)
+ {
+ return false;
+ }
- activate();
- enable(type);
- mCurrTexture = texture;
- glBindTexture(sGLTextureType[type], texture);
- mHasMipMaps = hasMips;
+ if(mCurrTexture != texture)
+ {
+ gGL.flush();
+
+ activate();
+ enable(type);
+ mCurrTexture = texture;
+ glBindTexture(sGLTextureType[type], texture);
+ mHasMipMaps = hasMips;
+ }
return true;
}
@@ -785,6 +855,9 @@ void LLRender::setSceneBlendType(eBlendType type)
case BT_MULT:
glBlendFunc(GL_DST_COLOR, GL_ZERO);
break;
+ case BT_MULT_ALPHA:
+ glBlendFunc(GL_DST_ALPHA, GL_ZERO);
+ break;
case BT_MULT_X2:
glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
break;
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 437c715c2f..0121a190ee 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -44,13 +44,14 @@
#include "v3math.h"
#include "v4coloru.h"
#include "llstrider.h"
-#include "llmemory.h"
+#include "llpointer.h"
#include "llglheaders.h"
class LLVertexBuffer;
class LLCubeMap;
class LLImageGL;
class LLRenderTarget;
+class LLTexture ;
class LLTexUnit
{
@@ -148,7 +149,8 @@ public:
// Binds the LLImageGL to this texture unit
// (automatically enables the unit for the LLImageGL's texture type)
- bool bind(LLImageGL* texture, bool forceBind = false);
+ bool bind(LLImageGL* texture, bool for_rendering = false, bool forceBind = false);
+ bool bind(LLTexture* texture, bool for_rendering = false, bool forceBind = false);
// Binds a cubemap to this texture unit
// (automatically enables the texture unit for cubemaps)
@@ -252,6 +254,7 @@ public:
BT_ADD,
BT_ADD_WITH_ALPHA, // Additive blend modulated by the fragment's alpha.
BT_MULT,
+ BT_MULT_ALPHA,
BT_MULT_X2,
BT_REPLACE
} eBlendType;
@@ -352,6 +355,7 @@ private:
extern F64 gGLModelView[16];
extern F64 gGLLastModelView[16];
+extern F64 gGLLastProjection[16];
extern F64 gGLProjection[16];
extern S32 gGLViewport[4];
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index b7f31779ca..d9520b3bf6 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -36,6 +36,9 @@
#include "llrender.h"
#include "llgl.h"
+LLRenderTarget* LLRenderTarget::sBoundTarget = NULL;
+
+
void check_framebuffer_status()
{
@@ -46,11 +49,9 @@ void check_framebuffer_status()
{
case GL_FRAMEBUFFER_COMPLETE_EXT:
break;
- case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
- llerrs << "WTF?" << llendl;
- break;
default:
- llerrs << "WTF?" << llendl;
+ ll_fail("check_framebuffer_status failed");
+ break;
}
}
}
@@ -139,7 +140,7 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt)
U32 offset = mTex.size();
if (offset >= 4 ||
- offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers))
+ (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)))
{
llerrs << "Too many color attachments!" << llendl;
}
@@ -203,7 +204,7 @@ void LLRenderTarget::allocateDepth()
gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
U32 internal_type = LLTexUnit::getInternalType(mUsage);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
- LLImageGL::setManualImage(internal_type, 0, GL_DEPTH24_STENCIL8_EXT, mResX, mResY, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL);
+ LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32_ARB, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
}
}
@@ -273,6 +274,7 @@ void LLRenderTarget::release()
}
mSampleBuffer = NULL;
+ sBoundTarget = NULL;
}
void LLRenderTarget::bindTarget()
@@ -311,6 +313,7 @@ void LLRenderTarget::bindTarget()
}
glViewport(0, 0, mResX, mResY);
+ sBoundTarget = this;
}
// static
@@ -320,6 +323,7 @@ void LLRenderTarget::unbindTarget()
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
+ sBoundTarget = NULL;
}
void LLRenderTarget::clear(U32 mask_in)
@@ -378,7 +382,7 @@ void LLRenderTarget::flush(BOOL fetch_depth)
allocateDepth();
}
- gGL.getTexUnit(0)->bind(this, true);
+ gGL.getTexUnit(0)->bind(this);
glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8_EXT, 0, 0, mResX, mResY, 0);
}
@@ -388,7 +392,11 @@ void LLRenderTarget::flush(BOOL fetch_depth)
{
#if !LL_DARWIN
+ stop_glerror();
+
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+ stop_glerror();
if (mSampleBuffer)
{
@@ -430,7 +438,6 @@ void LLRenderTarget::flush(BOOL fetch_depth)
#endif
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- glFlush();
}
}
@@ -438,6 +445,7 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0,
S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter)
{
#if !LL_DARWIN
+ gGL.flush();
if (!source.mFBO || !mFBO)
{
llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
@@ -449,12 +457,55 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0,
}
else
{
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO);
- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFBO);
+ if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil)
+ {
+ stop_glerror();
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, source.mFBO);
+ gGL.getTexUnit(0)->bind(this, true);
+ stop_glerror();
+ glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1);
+ stop_glerror();
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ stop_glerror();
+ }
+ else
+ {
+ glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO);
+ stop_glerror();
+ glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFBO);
+ stop_glerror();
+ check_framebuffer_status();
+ stop_glerror();
+ glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+ stop_glerror();
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ stop_glerror();
+ }
+ }
+#endif
+}
+//static
+void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
+ S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter)
+{
+#if !LL_DARWIN
+ if (!source.mFBO)
+ {
+ llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
+ }
+ {
+ glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO);
+ stop_glerror();
+ glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
+ stop_glerror();
+ check_framebuffer_status();
+ stop_glerror();
glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
-
+ stop_glerror();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ stop_glerror();
}
#endif
}
@@ -532,6 +583,7 @@ void LLMultisampleBuffer::bindTarget(LLRenderTarget* ref)
glViewport(0, 0, mResX, mResY);
+ sBoundTarget = this;
}
void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo )
@@ -608,7 +660,7 @@ void LLMultisampleBuffer::addColorAttachment(U32 color_fmt)
U32 offset = mTex.size();
if (offset >= 4 ||
- offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers))
+ (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)))
{
llerrs << "Too many color attachments!" << llendl;
}
diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h
index d5d809b791..b7ebfc8f7f 100644
--- a/indra/llrender/llrendertarget.h
+++ b/indra/llrender/llrendertarget.h
@@ -121,6 +121,7 @@ public:
U32 getTexture(U32 attachment = 0) const;
U32 getDepth(void) const { return mDepth; }
+ BOOL hasStencil() const { return mStencil; }
void bindTexture(U32 index, S32 channel);
@@ -135,11 +136,16 @@ public:
void copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter);
+ static void copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
+ S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter);
+
//Returns TRUE if target is ready to be rendered into.
//That is, if the target has been allocated with at least
//one renderable attachment (i.e. color buffer, depth buffer).
BOOL isComplete() const;
+ static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; }
+
protected:
friend class LLMultisampleBuffer;
U32 mResX;
@@ -153,6 +159,8 @@ protected:
LLTexUnit::eTextureType mUsage;
U32 mSamples;
LLMultisampleBuffer* mSampleBuffer;
+
+ static LLRenderTarget* sBoundTarget;
};
diff --git a/indra/llrender/lltexture.cpp b/indra/llrender/lltexture.cpp
new file mode 100644
index 0000000000..156ffb953c
--- /dev/null
+++ b/indra/llrender/lltexture.cpp
@@ -0,0 +1,37 @@
+/**
+ * @file lltexture.cpp
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+#include "lltexture.h"
+
+//virtual
+LLTexture::~LLTexture()
+{
+}
diff --git a/indra/llrender/lltexture.h b/indra/llrender/lltexture.h
new file mode 100644
index 0000000000..7034e9199d
--- /dev/null
+++ b/indra/llrender/lltexture.h
@@ -0,0 +1,79 @@
+/**
+ * @file lltexture.h
+ * @brief LLTexture definition
+ *
+ * This class acts as a wrapper for OpenGL calls.
+ * The goal of this class is to minimize the number of api calls due to legacy rendering
+ * code, to define an interface for a multiple rendering API abstraction of the UI
+ * rendering, and to abstract out direct rendering calls in a way that is cleaner and easier to maintain.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_TEXTURE_H
+#define LL_TEXTURE_H
+
+#include "llrefcount.h"
+class LLImageGL ;
+class LLTexUnit ;
+class LLFontGL ;
+
+//
+//this is an abstract class as the parent for the class LLViewerTexture
+//through the following virtual functions, the class LLViewerTexture can be reached from /llrender.
+//
+class LLTexture : public LLRefCount
+{
+ friend class LLTexUnit ;
+ friend class LLFontGL ;
+
+protected:
+ virtual ~LLTexture();
+
+public:
+ LLTexture(){}
+
+ //
+ //interfaces to access LLViewerTexture
+ //
+ virtual S8 getType() const = 0 ;
+ virtual void setKnownDrawSize(S32 width, S32 height) = 0 ;
+ virtual bool bindDefaultImage(const S32 stage = 0) = 0 ;
+ virtual void forceImmediateUpdate() = 0 ;
+ virtual void setActive() = 0 ;
+ virtual S32 getWidth(S32 discard_level = -1) const = 0 ;
+ virtual S32 getHeight(S32 discard_level = -1) const = 0 ;
+
+private:
+ //note: do not make this function public.
+ virtual LLImageGL* getGLTexture() const = 0 ;
+
+ virtual void updateBindStatsForTester() = 0 ;
+};
+#endif
+
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 5d88ea464d..572ae13909 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -37,7 +37,6 @@
#include "llvertexbuffer.h"
// #include "llrender.h"
#include "llglheaders.h"
-#include "llmemory.h"
#include "llmemtype.h"
#include "llrender.h"
@@ -117,6 +116,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
GL_COLOR_ARRAY,
};
+ BOOL error = FALSE;
for (U32 i = 0; i < 4; ++i)
{
if (sLastMask & mask[i])
@@ -129,7 +129,15 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
{ //needs to be enabled, make sure it was (DEBUG TEMPORARY)
if (i > 0 && !glIsEnabled(array[i]))
{
- llerrs << "Bad client state! " << array[i] << " disabled." << llendl;
+ if (gDebugSession)
+ {
+ error = TRUE;
+ gFailLog << "Bad client state! " << array[i] << " disabled." << std::endl;
+ }
+ else
+ {
+ llerrs << "Bad client state! " << array[i] << " disabled." << llendl;
+ }
}
}
}
@@ -141,11 +149,24 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
}
else if (gDebugGL && glIsEnabled(array[i]))
{ //needs to be disabled, make sure it was (DEBUG TEMPORARY)
- llerrs << "Bad client state! " << array[i] << " enabled." << llendl;
+ if (gDebugSession)
+ {
+ error = TRUE;
+ gFailLog << "Bad client state! " << array[i] << " enabled." << std::endl;
+ }
+ else
+ {
+ llerrs << "Bad client state! " << array[i] << " enabled." << llendl;
+ }
}
}
}
+ if (error)
+ {
+ ll_fail("LLVertexBuffer::setupClientArrays failed");
+ }
+
U32 map_tc[] =
{
MAP_TEXCOORD1,
@@ -315,7 +336,7 @@ void LLVertexBuffer::unbind()
//static
void LLVertexBuffer::cleanupClass()
{
- LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ LLMemType mt2(LLMemType::MTYPE_VERTEX_CLEANUP_CLASS);
unbind();
clientCopy(); // deletes GL buffers
}
@@ -342,7 +363,7 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
mResized(FALSE),
mDynamicSize(FALSE)
{
- LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ LLMemType mt2(LLMemType::MTYPE_VERTEX_CONSTRUCTOR);
if (!sEnableVBOs)
{
mUsage = 0 ;
@@ -379,7 +400,7 @@ S32 LLVertexBuffer::calcStride(const U32& typemask, S32* offsets)
//virtual
LLVertexBuffer::~LLVertexBuffer()
{
- LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTRUCTOR);
destroyGLBuffer();
destroyGLIndices();
sCount--;
@@ -459,8 +480,8 @@ void LLVertexBuffer::releaseIndices()
void LLVertexBuffer::createGLBuffer()
{
- LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
-
+ LLMemType mt2(LLMemType::MTYPE_VERTEX_CREATE_VERTICES);
+
U32 size = getSize();
if (mGLBuffer)
{
@@ -491,7 +512,7 @@ void LLVertexBuffer::createGLBuffer()
void LLVertexBuffer::createGLIndices()
{
- LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ LLMemType mt2(LLMemType::MTYPE_VERTEX_CREATE_INDICES);
U32 size = getIndicesSize();
if (mGLIndices)
@@ -523,7 +544,7 @@ void LLVertexBuffer::createGLIndices()
void LLVertexBuffer::destroyGLBuffer()
{
- LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTROY_BUFFER);
if (mGLBuffer)
{
if (useVBOs())
@@ -550,7 +571,7 @@ void LLVertexBuffer::destroyGLBuffer()
void LLVertexBuffer::destroyGLIndices()
{
- LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTROY_INDICES);
if (mGLIndices)
{
if (useVBOs())
@@ -577,7 +598,7 @@ void LLVertexBuffer::destroyGLIndices()
void LLVertexBuffer::updateNumVerts(S32 nverts)
{
- LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ LLMemType mt2(LLMemType::MTYPE_VERTEX_UPDATE_VERTS);
if (nverts >= 65535)
{
@@ -606,7 +627,7 @@ void LLVertexBuffer::updateNumVerts(S32 nverts)
void LLVertexBuffer::updateNumIndices(S32 nindices)
{
- LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ LLMemType mt2(LLMemType::MTYPE_VERTEX_UPDATE_INDICES);
mRequestedNumIndices = nindices;
if (!mDynamicSize)
{
@@ -627,7 +648,7 @@ void LLVertexBuffer::updateNumIndices(S32 nindices)
void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
{
- LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ LLMemType mt2(LLMemType::MTYPE_VERTEX_ALLOCATE_BUFFER);
updateNumVerts(nverts);
updateNumIndices(nindices);
@@ -650,7 +671,7 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
mRequestedNumVerts = newnverts;
mRequestedNumIndices = newnindices;
- LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ LLMemType mt2(LLMemType::MTYPE_VERTEX_RESIZE_BUFFER);
mDynamicSize = TRUE;
if (mUsage == GL_STATIC_DRAW_ARB)
{ //always delete/allocate static buffers on resize
@@ -779,7 +800,7 @@ BOOL LLVertexBuffer::useVBOs() const
// Map for data access
U8* LLVertexBuffer::mapBuffer(S32 access)
{
- LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER);
if (mFinal)
{
llerrs << "LLVertexBuffer::mapBuffer() called on a finalized buffer." << llendl;
@@ -791,13 +812,19 @@ U8* LLVertexBuffer::mapBuffer(S32 access)
if (!mLocked && useVBOs())
{
- setBuffer(0);
- mLocked = TRUE;
- stop_glerror();
- mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
- stop_glerror();
- mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
- stop_glerror();
+ {
+ LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES);
+ setBuffer(0);
+ mLocked = TRUE;
+ stop_glerror();
+ mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ stop_glerror();
+ }
+ {
+ LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES);
+ mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ stop_glerror();
+ }
if (!mMappedData)
{
@@ -840,7 +867,7 @@ U8* LLVertexBuffer::mapBuffer(S32 access)
void LLVertexBuffer::unmapBuffer()
{
- LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ LLMemType mt2(LLMemType::MTYPE_VERTEX_UNMAP_BUFFER);
if (mMappedData || mMappedIndexData)
{
if (useVBOs() && mLocked)
@@ -962,7 +989,7 @@ bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 in
void LLVertexBuffer::setStride(S32 type, S32 new_stride)
{
- LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ LLMemType mt2(LLMemType::MTYPE_VERTEX_SET_STRIDE);
if (mNumVerts)
{
llerrs << "LLVertexBuffer::setOffset called with mNumVerts = " << mNumVerts << llendl;
@@ -984,7 +1011,7 @@ void LLVertexBuffer::setStride(S32 type, S32 new_stride)
// Set for rendering
void LLVertexBuffer::setBuffer(U32 data_mask)
{
- LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ LLMemType mt2(LLMemType::MTYPE_VERTEX_SET_BUFFER);
//set up pointers if the data mask is different ...
BOOL setup = (sLastMask != data_mask);
@@ -1016,19 +1043,39 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
sIBOActive = TRUE;
}
+ BOOL error = FALSE;
if (gDebugGL)
{
GLint buff;
glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
if ((GLuint)buff != mGLBuffer)
{
- llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
+ if (gDebugSession)
+ {
+ error = TRUE;
+ gFailLog << "Invalid GL vertex buffer bound: " << buff << std::endl;
+ }
+ else
+ {
+ llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
+ }
}
- glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
- if ((GLuint)buff != mGLIndices)
+ if (mGLIndices)
{
- llerrs << "Invalid GL index buffer bound: " << buff << llendl;
+ glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
+ if ((GLuint)buff != mGLIndices)
+ {
+ if (gDebugSession)
+ {
+ error = TRUE;
+ gFailLog << "Invalid GL index buffer bound: " << buff << std::endl;
+ }
+ else
+ {
+ llerrs << "Invalid GL index buffer bound: " << buff << llendl;
+ }
+ }
}
}
@@ -1040,13 +1087,32 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
if ((GLuint)buff != mGLBuffer)
{
- llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
+ if (gDebugSession)
+ {
+ error = TRUE;
+ gFailLog << "Invalid GL vertex buffer bound: " << std::endl;
+ }
+ else
+ {
+ llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
+ }
}
- glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
- if ((GLuint)buff != mGLIndices)
+ if (mGLIndices != 0)
{
- llerrs << "Invalid GL index buffer bound: " << buff << llendl;
+ glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
+ if ((GLuint)buff != mGLIndices)
+ {
+ if (gDebugSession)
+ {
+ error = TRUE;
+ gFailLog << "Invalid GL index buffer bound: "<< std::endl;
+ }
+ else
+ {
+ llerrs << "Invalid GL index buffer bound: " << buff << llendl;
+ }
+ }
}
}
@@ -1068,10 +1134,22 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
if (data_mask != 0)
{
- llerrs << "Buffer set for rendering before being filled after resize." << llendl;
+ if (gDebugSession)
+ {
+ error = TRUE;
+ gFailLog << "Buffer set for rendering before being filled after resize." << std::endl;
+ }
+ else
+ {
+ llerrs << "Buffer set for rendering before being filled after resize." << llendl;
+ }
}
}
+ if (error)
+ {
+ ll_fail("LLVertexBuffer::mapBuffer failed");
+ }
unmapBuffer();
}
else
@@ -1122,7 +1200,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
// virtual (default)
void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const
{
- LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
+ LLMemType mt2(LLMemType::MTYPE_VERTEX_SETUP_VERTEX_BUFFER);
stop_glerror();
U8* base = useVBOs() ? NULL : mMappedData;
S32 stride = mStride;
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index aad948e17f..b785a22976 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -39,7 +39,6 @@
#include "v4math.h"
#include "v4coloru.h"
#include "llstrider.h"
-#include "llmemory.h"
#include "llrender.h"
#include <set>
#include <vector>
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 5de8dc76af..ce068618e2 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -3,7 +3,6 @@
project(llui)
include(00-Common)
-include(LLAudio)
include(LLCommon)
include(LLImage)
include(LLMath)
@@ -12,9 +11,9 @@ include(LLRender)
include(LLWindow)
include(LLVFS)
include(LLXML)
+include(LLXUIXML)
include_directories(
- ${LLAUDIO_INCLUDE_DIRS}
${LLCOMMON_INCLUDE_DIRS}
${LLIMAGE_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS}
@@ -23,55 +22,90 @@ include_directories(
${LLWINDOW_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS}
+ ${LLXUIXML_INCLUDE_DIRS}
)
set(llui_SOURCE_FILES
- llalertdialog.cpp
+ llaccordionctrl.cpp
+ llaccordionctrltab.cpp
llbutton.cpp
llcheckboxctrl.cpp
llclipboard.cpp
llcombobox.cpp
+ llconsole.cpp
+ llcontainerview.cpp
llctrlselectioninterface.cpp
+ lldockablefloater.cpp
+ lldockcontrol.cpp
lldraghandle.cpp
lleditmenuhandler.cpp
+ llf32uictrl.cpp
+ llfiltereditor.cpp
+ llflatlistview.cpp
llfloater.cpp
+ llfloaterreg.cpp
+ llfloaterreglistener.cpp
+ llflyoutbutton.cpp
llfocusmgr.cpp
llfunctorregistry.cpp
lliconctrl.cpp
llkeywords.cpp
+ lllayoutstack.cpp
lllineeditor.cpp
+ lllocalcliprect.cpp
+ llmenubutton.cpp
llmenugl.cpp
llmodaldialog.cpp
+ llmultifloater.cpp
llmultislider.cpp
llmultisliderctrl.cpp
llnotifications.cpp
+ llnotificationslistener.cpp
+ llnotificationsutil.cpp
llpanel.cpp
llprogressbar.cpp
llradiogroup.cpp
llresizebar.cpp
llresizehandle.cpp
llresmgr.cpp
- llrootview.cpp
+ llrngwriter.cpp
llscrollbar.cpp
llscrollcontainer.cpp
llscrollingpanellist.cpp
+ llscrolllistcell.cpp
+ llscrolllistcolumn.cpp
llscrolllistctrl.cpp
+ llscrolllistitem.cpp
+ llsdparam.cpp
+ llsearcheditor.cpp
llslider.cpp
llsliderctrl.cpp
llspinctrl.cpp
+ llstatbar.cpp
+ llstatgraph.cpp
+ llstatview.cpp
llstyle.cpp
lltabcontainer.cpp
- lltabcontainervertical.cpp
+ lltextbase.cpp
lltextbox.cpp
lltexteditor.cpp
lltextparser.cpp
+ lltransutil.cpp
+ lltoggleablemenu.cpp
+ lltooltip.cpp
llui.cpp
+ lluicolortable.cpp
lluictrl.cpp
lluictrlfactory.cpp
+ lluiimage.cpp
lluistring.cpp
- lluitrans.cpp
llundo.cpp
+ llurlaction.cpp
+ llurlentry.cpp
+ llurlmatch.cpp
+ llurlregistry.cpp
llviewborder.cpp
+ llviewmodel.cpp
llview.cpp
llviewquery.cpp
)
@@ -79,58 +113,93 @@ set(llui_SOURCE_FILES
set(llui_HEADER_FILES
CMakeLists.txt
- llalertdialog.h
+ llaccordionctrl.h
+ llaccordionctrltab.h
llbutton.h
llcallbackmap.h
llcheckboxctrl.h
llclipboard.h
llcombobox.h
+ llconsole.h
+ llcontainerview.h
llctrlselectioninterface.h
lldraghandle.h
+ lldockablefloater.h
+ lldockcontrol.h
lleditmenuhandler.h
+ llf32uictrl.h
+ llfiltereditor.h
+ llflatlistview.h
llfloater.h
+ llfloaterreg.h
+ llfloaterreglistener.h
+ llflyoutbutton.h
llfocusmgr.h
llfunctorregistry.h
- llhtmlhelp.h
+ llhandle.h
+ llhelp.h
lliconctrl.h
llkeywords.h
+ lllayoutstack.h
+ lllazyvalue.h
lllineeditor.h
- llmemberlistener.h
+ lllocalcliprect.h
+ llmenubutton.h
llmenugl.h
llmodaldialog.h
+ llmultifloater.h
llmultisliderctrl.h
llmultislider.h
+ llnotificationptr.h
llnotifications.h
+ llnotificationslistener.h
+ llnotificationsutil.h
llpanel.h
llprogressbar.h
llradiogroup.h
llresizebar.h
llresizehandle.h
llresmgr.h
- llrootview.h
+ llrngwriter.h
+ llsearcheditor.h
llscrollbar.h
llscrollcontainer.h
llscrollingpanellist.h
+ llscrolllistcell.h
+ llscrolllistcolumn.h
llscrolllistctrl.h
+ llscrolllistitem.h
+ llsdparam.h
llsliderctrl.h
llslider.h
llspinctrl.h
+ llstatbar.h
+ llstatgraph.h
+ llstatview.h
llstyle.h
lltabcontainer.h
- lltabcontainervertical.h
+ lltextbase.h
lltextbox.h
lltexteditor.h
lltextparser.h
+ lltoggleablemenu.h
+ lltooltip.h
+ lltransutil.h
+ lluicolortable.h
lluiconstants.h
lluictrlfactory.h
lluictrl.h
lluifwd.h
llui.h
+ lluiimage.h
lluistring.h
- lluitrans.h
- lluixmltags.h
llundo.h
+ llurlaction.h
+ llurlentry.h
+ llurlmatch.h
+ llurlregistry.h
llviewborder.h
+ llviewmodel.h
llview.h
llviewquery.h
)
@@ -144,11 +213,21 @@ add_library (llui ${llui_SOURCE_FILES})
# Libraries on which this library depends, needed for Linux builds
# Sort by high-level to low-level
target_link_libraries(llui
- llrender
- llwindow
- llimage
- llvfs # ugh, just for LLDir
- llxml
- llcommon # must be after llimage, llwindow, llrender
- llmath
+ ${LLMESSAGE_LIBRARIES}
+ ${LLRENDER_LIBRARIES}
+ ${LLWINDOW_LIBRARIES}
+ ${LLIMAGE_LIBRARIES}
+ ${LLVFS_LIBRARIES} # ugh, just for LLDir
+ ${LLXUIXML_LIBRARIES}
+ ${LLXML_LIBRARIES}
+ ${LLMATH_LIBRARIES}
+ ${LLCOMMON_LIBRARIES} # must be after llimage, llwindow, llrender
)
+
+# Add tests
+include(LLAddBuildTest)
+SET(llui_TEST_SOURCE_FILES
+ llurlmatch.cpp
+ llurlentry.cpp
+ )
+LL_ADD_PROJECT_UNIT_TESTS(llui "${llui_TEST_SOURCE_FILES}")
diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp
new file mode 100644
index 0000000000..b5e870228a
--- /dev/null
+++ b/indra/llui/llaccordionctrl.cpp
@@ -0,0 +1,578 @@
+/**
+ * @file llaccordionctrl.cpp
+ * @brief Accordion panel implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+
+#include "llaccordionctrl.h"
+#include "llaccordionctrltab.h"
+
+#include "lluictrlfactory.h" // builds floaters from XML
+
+#include "llwindow.h"
+#include "llfocusmgr.h"
+#include "lllocalcliprect.h"
+
+#include "boost/bind.hpp"
+
+static const S32 DRAGGER_BAR_MARGIN = 4;
+static const S32 DRAGGER_BAR_HEIGHT = 5;
+static const S32 BORDER_MARGIN = 2;
+static const S32 PARENT_BORDER_MARGIN = 5;
+
+static const S32 panel_delta = DRAGGER_BAR_MARGIN; // Distanse between two panels
+
+static const S32 HORIZONTAL_MULTIPLE = 8;
+static const S32 VERTICAL_MULTIPLE = 16;
+static const F32 MIN_AUTO_SCROLL_RATE = 120.f;
+static const F32 MAX_AUTO_SCROLL_RATE = 500.f;
+static const F32 AUTO_SCROLL_RATE_ACCEL = 120.f;
+
+
+// LLAccordionCtrl =================================================================|
+
+static LLDefaultChildRegistry::Register<LLAccordionCtrl> t2("accordion");
+
+
+LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params)
+ , mFitParent(params.fit_parent)
+{
+ mSingleExpansion = params.single_expansion;
+ if(mFitParent && !mSingleExpansion)
+ {
+ llinfos << "fit_parent works best when combined with single_expansion" << llendl;
+ }
+}
+
+LLAccordionCtrl::LLAccordionCtrl() : LLPanel()
+{
+ mSingleExpansion = false;
+ mFitParent = false;
+ LLUICtrlFactory::getInstance()->buildPanel(this, "accordion_parent.xml");
+}
+
+//---------------------------------------------------------------------------------
+void LLAccordionCtrl::draw()
+{
+ LLRect local_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
+
+ LLLocalClipRect clip(local_rect);
+
+ LLPanel::draw();
+}
+
+
+//---------------------------------------------------------------------------------
+BOOL LLAccordionCtrl::postBuild()
+{
+ static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+
+ LLRect scroll_rect;
+ scroll_rect.setOriginAndSize(
+ getRect().getWidth() - scrollbar_size,
+ 1,
+ scrollbar_size,
+ getRect().getHeight() - 1);
+
+
+ LLScrollbar::Params sbparams;
+ sbparams.name("scrollable vertical");
+ sbparams.rect(scroll_rect);
+ sbparams.orientation(LLScrollbar::VERTICAL);
+ sbparams.doc_size(mInnerRect.getHeight());
+ sbparams.doc_pos(0);
+ sbparams.page_size(mInnerRect.getHeight());
+ sbparams.step_size(VERTICAL_MULTIPLE);
+ sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
+ sbparams.change_callback(boost::bind(&LLAccordionCtrl::onScrollPosChangeCallback, this, _1, _2));
+
+ mScrollbar = LLUICtrlFactory::create<LLScrollbar> (sbparams);
+ LLView::addChild( mScrollbar );
+ mScrollbar->setVisible( false );
+ mScrollbar->setFollowsRight();
+ mScrollbar->setFollowsTop();
+ mScrollbar->setFollowsBottom();
+
+ //if it was created from xml...
+ std::vector<LLUICtrl*> accordion_tabs;
+ for(child_list_const_iter_t it = getChildList()->begin();
+ getChildList()->end() != it; ++it)
+ {
+ LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(*it);
+ if(accordion_tab == NULL)
+ continue;
+ if(std::find(mAccordionTabs.begin(),mAccordionTabs.end(),accordion_tab) == mAccordionTabs.end())
+ {
+ accordion_tabs.push_back(accordion_tab);
+ }
+ }
+
+ for(std::vector<LLUICtrl*>::reverse_iterator it = accordion_tabs.rbegin();it!=accordion_tabs.rend();++it)
+ addCollapsibleCtrl(*it);
+
+ arrange ();
+
+ if(mSingleExpansion)
+ {
+ if(!mAccordionTabs[0]->getDisplayChildren())
+ mAccordionTabs[0]->setDisplayChildren(true);
+ for(size_t i=1;i<mAccordionTabs.size();++i)
+ {
+ if(mAccordionTabs[i]->getDisplayChildren())
+ mAccordionTabs[i]->setDisplayChildren(false);
+ }
+ }
+
+ return TRUE;
+}
+
+
+//---------------------------------------------------------------------------------
+LLAccordionCtrl::~LLAccordionCtrl()
+{
+ mAccordionTabs.clear();
+}
+
+//---------------------------------------------------------------------------------
+
+void LLAccordionCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ // adjust our rectangle
+ LLRect rcLocal = getRect();
+ rcLocal.mRight = rcLocal.mLeft + width;
+ rcLocal.mTop = rcLocal.mBottom + height;
+
+ setRect(rcLocal);
+
+ arrange();
+}
+
+//---------------------------------------------------------------------------------
+BOOL LLAccordionCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ return LLPanel::handleRightMouseDown(x, y, mask);
+}
+
+//---------------------------------------------------------------------------------
+void LLAccordionCtrl::shiftAccordionTabs(S16 panel_num, S32 delta)
+{
+ for(size_t i = panel_num; i < mAccordionTabs.size(); i++ )
+ {
+ ctrlShiftVertical(mAccordionTabs[i],delta);
+ }
+}
+
+
+//---------------------------------------------------------------------------------
+void LLAccordionCtrl::onCollapseCtrlCloseOpen(S16 panel_num)
+{
+ if(mSingleExpansion)
+ {
+ for(size_t i=0;i<mAccordionTabs.size();++i)
+ {
+ if(i==panel_num)
+ continue;
+ if(mAccordionTabs[i]->getDisplayChildren())
+ mAccordionTabs[i]->setDisplayChildren(false);
+ }
+
+ }
+ arrange();
+}
+
+void LLAccordionCtrl::show_hide_scrollbar(S32 width, S32 height)
+{
+ calcRecuiredHeight();
+ if(getRecuiredHeight() > height )
+ showScrollbar(width,height);
+ else
+ hideScrollbar(width,height);
+}
+
+void LLAccordionCtrl::showScrollbar(S32 width, S32 height)
+{
+ bool was_visible = mScrollbar->getVisible();
+
+ mScrollbar->setVisible(true);
+
+ static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+
+ ctrlSetLeftTopAndSize(mScrollbar
+ ,width-scrollbar_size - PARENT_BORDER_MARGIN/2
+ ,height-PARENT_BORDER_MARGIN
+ ,scrollbar_size
+ ,height-2*PARENT_BORDER_MARGIN);
+
+ mScrollbar->setPageSize(height);
+ mScrollbar->setDocParams(mInnerRect.getHeight(),mScrollbar->getDocPos());
+
+ if(was_visible)
+ {
+ S32 scroll_pos = llmin(mScrollbar->getDocPos(), getRecuiredHeight() - height - 1);
+ mScrollbar->setDocPos(scroll_pos);
+ }
+}
+
+void LLAccordionCtrl::hideScrollbar( S32 width, S32 height )
+{
+ if(mScrollbar->getVisible() == false)
+ return;
+ mScrollbar->setVisible(false);
+
+ static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+
+ S32 panel_width = width - 2*BORDER_MARGIN;
+
+ //reshape all accordeons and shift all draggers
+ for(size_t i=0;i<mAccordionTabs.size();++i)
+ {
+ LLRect panel_rect = mAccordionTabs[i]->getRect();
+ ctrlSetLeftTopAndSize(mAccordionTabs[i],panel_rect.mLeft,panel_rect.mTop,panel_width,panel_rect.getHeight());
+ }
+
+ mScrollbar->setDocPos(0);
+
+ if(mAccordionTabs.size()>0)
+ {
+ S32 panel_top = height - BORDER_MARGIN; // Top coordinate of the first panel
+ S32 diff = panel_top - mAccordionTabs[0]->getRect().mTop;
+ shiftAccordionTabs(0,diff);
+ }
+}
+
+
+//---------------------------------------------------------------------------------
+S32 LLAccordionCtrl::calcRecuiredHeight()
+{
+ S32 rec_height = 0;
+
+ std::vector<LLAccordionCtrlTab*>::iterator panel;
+ for(panel=mAccordionTabs.begin(); panel!=mAccordionTabs.end(); ++panel)
+ {
+ LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(*panel);
+ if(accordion_tab && accordion_tab->getVisible())
+ {
+ rec_height += accordion_tab->getRect().getHeight();
+ }
+ }
+
+ mInnerRect.setLeftTopAndSize(0,rec_height + BORDER_MARGIN*2,getRect().getWidth(),rec_height + BORDER_MARGIN);
+
+ return mInnerRect.getHeight();
+}
+
+//---------------------------------------------------------------------------------
+void LLAccordionCtrl::ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height)
+{
+ if(!panel)
+ return;
+ LLRect panel_rect = panel->getRect();
+ panel_rect.setLeftTopAndSize( left, top, width, height);
+ panel->reshape( width, height, 1);
+ panel->setRect(panel_rect);
+}
+
+void LLAccordionCtrl::ctrlShiftVertical(LLView* panel,S32 delta)
+{
+ if(!panel)
+ return;
+ panel->translate(0,delta);
+}
+
+//---------------------------------------------------------------------------------
+
+void LLAccordionCtrl::addCollapsibleCtrl(LLView* view)
+{
+ LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(view);
+ if(!accordion_tab)
+ return;
+ if(std::find(getChildList()->begin(),getChildList()->end(),accordion_tab) == getChildList()->end())
+ addChild(accordion_tab);
+ mAccordionTabs.push_back(accordion_tab);
+
+ accordion_tab->setDropDownStateChangedCallback( boost::bind(&LLAccordionCtrl::onCollapseCtrlCloseOpen, this, mAccordionTabs.size() - 1) );
+
+}
+
+
+void LLAccordionCtrl::arrange()
+{
+ if( mAccordionTabs.size() == 0)
+ {
+ //We do not arrange if we do not have what should be arranged
+ return;
+ }
+
+ //Calculate params
+ S32 panel_left = BORDER_MARGIN; // Margin from left side of Splitter
+ S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel
+ S32 panel_width = getRect().getWidth() - 4; // Top coordinate of the first panel
+
+
+ if(mAccordionTabs.size() == 1)
+ {
+ LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[0]);
+
+ LLRect panel_rect = accordion_tab->getRect();
+
+ S32 panel_height = getRect().getHeight() - 2*BORDER_MARGIN;
+
+ ctrlSetLeftTopAndSize(accordion_tab,panel_rect.mLeft,panel_top,panel_width,panel_height);
+
+ show_hide_scrollbar(getRect().getWidth(),getRect().getHeight());
+ return;
+
+ }
+
+ for(size_t i = 0; i < mAccordionTabs.size(); i++ )
+ {
+ LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
+
+ if(accordion_tab->getVisible() == false) //skip hidden accordion tabs
+ continue;
+
+ if(!accordion_tab->isExpanded() )
+ {
+ ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, accordion_tab->getRect().getHeight());
+ panel_top-=mAccordionTabs[i]->getRect().getHeight();
+ }
+ else
+ {
+ S32 panel_height = accordion_tab->getRect().getHeight();
+
+ if(mFitParent)
+ {
+ // all expanded tabs will have equal height
+ panel_height = calcExpandedTabHeight(i, panel_top);
+ ctrlSetLeftTopAndSize(accordion_tab, panel_left, panel_top, panel_width, panel_height);
+
+ // try to make accordion tab fit accordion view height.
+ // Accordion View should implement getRequiredRect() and provide valid height
+ S32 optimal_height = accordion_tab->getAccordionView()->getRequiredRect().getHeight();
+ optimal_height += accordion_tab->getHeaderHeight() + 2 * BORDER_MARGIN;
+ if(optimal_height < panel_height)
+ {
+ panel_height = optimal_height;
+ }
+
+ // minimum tab height is equal to header height
+ if(mAccordionTabs[i]->getHeaderHeight() > panel_height)
+ {
+ panel_height = mAccordionTabs[i]->getHeaderHeight();
+ }
+ }
+
+ ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, panel_height);
+ panel_top-=panel_height;
+
+ }
+ }
+
+ show_hide_scrollbar(getRect().getWidth(),getRect().getHeight());
+
+ updateLayout(getRect().getWidth(),getRect().getHeight());
+
+}
+
+//---------------------------------------------------------------------------------
+
+BOOL LLAccordionCtrl::handleScrollWheel ( S32 x, S32 y, S32 clicks )
+{
+ if(LLPanel::handleScrollWheel(x,y,clicks))
+ return TRUE;
+ if( mScrollbar->getVisible() && mScrollbar->handleScrollWheel( 0, 0, clicks ) )
+ return TRUE;
+ return false;
+
+}
+
+BOOL LLAccordionCtrl::handleKeyHere (KEY key, MASK mask)
+{
+ if( mScrollbar->getVisible() && mScrollbar->handleKeyHere( key,mask ) )
+ return TRUE;
+ return LLPanel::handleKeyHere(key,mask);
+}
+
+void LLAccordionCtrl::updateLayout (S32 width, S32 height)
+{
+ S32 panel_top = height - BORDER_MARGIN ;
+ if(mScrollbar->getVisible())
+ panel_top+=mScrollbar->getDocPos();
+
+ S32 panel_width = width - 2*BORDER_MARGIN;
+
+ static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+ if(mScrollbar->getVisible())
+ panel_width-=scrollbar_size;
+
+ //set sizes for first panels and dragbars
+ for(size_t i=0;i<mAccordionTabs.size();++i)
+ {
+ if(!mAccordionTabs[i]->getVisible())
+ continue;
+ LLRect panel_rect = mAccordionTabs[i]->getRect();
+ ctrlSetLeftTopAndSize(mAccordionTabs[i],panel_rect.mLeft,panel_top,panel_width,panel_rect.getHeight());
+ panel_top-=panel_rect.getHeight();
+ }
+}
+
+void LLAccordionCtrl::onScrollPosChangeCallback(S32, LLScrollbar*)
+{
+ updateLayout(getRect().getWidth(),getRect().getHeight());
+}
+void LLAccordionCtrl::onOpen (const LLSD& key)
+{
+ for(size_t i=0;i<mAccordionTabs.size();++i)
+ {
+ LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
+ LLPanel* panel = dynamic_cast<LLPanel*>(accordion_tab->getAccordionView());
+ if(panel!=NULL)
+ {
+ panel->onOpen(key);
+ }
+ }
+}
+S32 LLAccordionCtrl::notifyParent(const LLSD& info)
+{
+ if(info.has("action"))
+ {
+ std::string str_action = info["action"];
+ if(str_action == "size_changes")
+ {
+ //
+ arrange();
+ return 1;
+ }
+ else if(str_action == "select_next")
+ {
+ for(size_t i=0;i<mAccordionTabs.size();++i)
+ {
+ LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
+ if(accordion_tab->hasFocus())
+ {
+ while(++i<mAccordionTabs.size())
+ {
+ if(mAccordionTabs[i]->getVisible())
+ break;
+ }
+ if(i<mAccordionTabs.size())
+ {
+ accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
+ accordion_tab->notify(LLSD().with("action","select_first"));
+ return 1;
+ }
+ break;
+ }
+ }
+ return 0;
+ }
+ else if(str_action == "select_prev")
+ {
+ for(size_t i=0;i<mAccordionTabs.size();++i)
+ {
+ LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
+ if(accordion_tab->hasFocus() && i>0)
+ {
+ while(i>0)
+ {
+ if(mAccordionTabs[--i]->getVisible())
+ break;
+ }
+
+ accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
+ accordion_tab->notify(LLSD().with("action","select_last"));
+ return 1;
+ }
+ }
+ return 0;
+ }
+ }
+ else if (info.has("scrollToShowRect"))
+ {
+ LLRect screen_rc, local_rc;
+ screen_rc.setValue(info["scrollToShowRect"]);
+ screenRectToLocal(screen_rc, &local_rc);
+
+ // Translate to parent coordinatess to check if we are in visible rectangle
+ local_rc.translate( getRect().mLeft, getRect().mBottom );
+
+ if ( !getRect().contains (local_rc) )
+ {
+ // Back to local coords and calculate position for scroller
+ S32 bottom = mScrollbar->getDocPos() - local_rc.mBottom + getRect().mBottom;
+ S32 top = mScrollbar->getDocPos() - local_rc.mTop + getRect().mTop;
+
+ S32 scroll_pos = llclamp(mScrollbar->getDocPos(),
+ bottom, // min vertical scroll
+ top); // max vertical scroll
+
+ mScrollbar->setDocPos( scroll_pos );
+ }
+ return 1;
+ }
+ return LLPanel::notifyParent(info);
+}
+void LLAccordionCtrl::reset ()
+{
+ if(mScrollbar)
+ mScrollbar->setDocPos(0);
+}
+
+S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 available_height /* = 0 */)
+{
+ if(tab_index < 0)
+ {
+ return available_height;
+ }
+
+ S32 collapsed_tabs_height = 0;
+ S32 num_expanded = 0;
+
+ for(size_t n = tab_index; n < mAccordionTabs.size(); ++n)
+ {
+ if(!mAccordionTabs[n]->isExpanded())
+ {
+ collapsed_tabs_height += mAccordionTabs[n]->getHeaderHeight();
+ }
+ else
+ {
+ ++num_expanded;
+ }
+ }
+
+ if(0 == num_expanded)
+ {
+ return available_height;
+ }
+
+ S32 expanded_tab_height = available_height - collapsed_tabs_height - BORDER_MARGIN; // top BORDER_MARGIN is added in arrange(), here we add bottom BORDER_MARGIN
+ expanded_tab_height /= num_expanded;
+ return expanded_tab_height;
+}
diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h
new file mode 100644
index 0000000000..4cb0f38281
--- /dev/null
+++ b/indra/llui/llaccordionctrl.h
@@ -0,0 +1,123 @@
+/**
+ * @file LLAccordionCtrl.h
+ * @brief Accordion Panel implementation
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_ACCORDIONCTRL_H
+#define LL_ACCORDIONCTRL_H
+
+#include "llpanel.h"
+#include "llscrollbar.h"
+
+#include <vector>
+#include <algorithm>
+#include <string>
+
+class LLAccordionCtrlTab;
+
+class LLAccordionCtrl: public LLPanel
+{
+private:
+
+ std::vector<LLAccordionCtrlTab*> mAccordionTabs;
+
+ void ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height);
+ void ctrlShiftVertical(LLView* panel,S32 delta);
+
+ void onCollapseCtrlCloseOpen(S16 panel_num);
+ void shiftAccordionTabs(S16 panel_num, S32 delta);
+
+
+public:
+ struct Params
+ : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ Optional<bool> single_expansion,
+ fit_parent; /* Accordion will fit its parent size, controls that are placed into
+ accordion tabs are responsible for scrolling their content.
+ *NOTE fit_parent works best when combined with single_expansion.
+ Accordion view should implement getRequiredRect() and provide valid height*/
+
+ Params()
+ : single_expansion("single_expansion",false)
+ , fit_parent("fit_parent", false)
+ {};
+ };
+
+ LLAccordionCtrl(const Params& params);
+
+ LLAccordionCtrl();
+ virtual ~LLAccordionCtrl();
+
+ virtual BOOL postBuild();
+
+ virtual BOOL handleRightMouseDown ( S32 x, S32 y, MASK mask);
+ virtual BOOL handleScrollWheel ( S32 x, S32 y, S32 clicks );
+ virtual BOOL handleKeyHere (KEY key, MASK mask);
+ //
+
+ // Call reshape after changing splitter's size
+ virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+ void addCollapsibleCtrl(LLView* view);
+ void arrange();
+
+
+ void draw();
+
+ void onScrollPosChangeCallback(S32, LLScrollbar*);
+
+ void onOpen (const LLSD& key);
+ S32 notifyParent(const LLSD& info);
+
+ void reset ();
+
+private:
+ // Calc Splitter's height that is necessary to display all child content
+ S32 calcRecuiredHeight();
+ S32 getRecuiredHeight() const { return mInnerRect.getHeight(); }
+ S32 calcExpandedTabHeight(S32 tab_index = 0, S32 available_height = 0);
+
+ void updateLayout (S32 width, S32 height);
+
+ void show_hide_scrollbar (S32 width, S32 height);
+
+ void showScrollbar (S32 width, S32 height);
+ void hideScrollbar (S32 width, S32 height);
+
+private:
+ LLRect mInnerRect;
+ LLScrollbar* mScrollbar;
+ bool mSingleExpansion;
+ bool mFitParent;
+};
+
+
+#endif // LL_LLSPLITTER_H
diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp
new file mode 100644
index 0000000000..4bfe44135a
--- /dev/null
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -0,0 +1,600 @@
+/**
+ * @file LLAccordionCtrlTab.cpp
+ * @brief Collapsible control implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lluictrl.h"
+
+#include "llaccordionctrltab.h"
+
+#include "lltextbox.h"
+
+static const std::string DD_BUTTON_NAME = "dd_button";
+static const std::string DD_TEXTBOX_NAME = "dd_textbox";
+static const std::string DD_HEADER_NAME = "dd_header";
+
+static const S32 HEADER_HEIGHT = 20;
+static const S32 HEADER_IMAGE_LEFT_OFFSET = 5;
+static const S32 HEADER_TEXT_LEFT_OFFSET = 30;
+
+static LLDefaultChildRegistry::Register<LLAccordionCtrlTab> t1("accordion_tab");
+
+class LLAccordionCtrlTab::LLAccordionCtrlTabHeader : public LLUICtrl
+{
+public:
+ friend class LLUICtrlFactory;
+
+ struct Params : public LLInitParam::Block<Params, LLAccordionCtrlTab::Params>
+ {
+ Params();
+ };
+
+ LLAccordionCtrlTabHeader(const LLAccordionCtrlTabHeader::Params& p);
+
+ virtual ~LLAccordionCtrlTabHeader();
+
+ virtual void draw();
+
+ virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+ virtual BOOL postBuild();
+
+ void setTitle(const std::string& title);
+
+ virtual void onMouseEnter(S32 x, S32 y, MASK mask);
+ virtual void onMouseLeave(S32 x, S32 y, MASK mask);
+ virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
+private:
+
+ LLTextBox* mHeaderTextbox;
+
+ // Overlay images (arrows)
+ LLPointer<LLUIImage> mImageCollapsed;
+ LLPointer<LLUIImage> mImageExpanded;
+ LLPointer<LLUIImage> mImageCollapsedPressed;
+ LLPointer<LLUIImage> mImageExpandedPressed;
+
+ // Background images
+ LLPointer<LLUIImage> mImageHeader;
+ LLPointer<LLUIImage> mImageHeaderOver;
+ LLPointer<LLUIImage> mImageHeaderPressed;
+ LLPointer<LLUIImage> mImageHeaderFocused;
+
+ LLUIColor mHeaderBGColor;
+
+ bool mNeedsHighlight;
+};
+
+LLAccordionCtrlTab::LLAccordionCtrlTabHeader::Params::Params()
+{
+}
+
+LLAccordionCtrlTab::LLAccordionCtrlTabHeader::LLAccordionCtrlTabHeader(
+ const LLAccordionCtrlTabHeader::Params& p)
+: LLUICtrl(p)
+, mHeaderBGColor(p.header_bg_color())
+,mNeedsHighlight(false),
+ mImageCollapsed(p.header_collapse_img),
+ mImageCollapsedPressed(p.header_collapse_img_pressed),
+ mImageExpanded(p.header_expand_img),
+ mImageExpandedPressed(p.header_expand_img_pressed),
+ mImageHeader(p.header_image),
+ mImageHeaderOver(p.header_image_over),
+ mImageHeaderPressed(p.header_image_pressed),
+ mImageHeaderFocused(p.header_image_focused)
+{
+ LLTextBox::Params textboxParams;
+ textboxParams.name(DD_TEXTBOX_NAME);
+ textboxParams.initial_value(p.title());
+ textboxParams.text_color(p.header_text_color());
+ textboxParams.follows.flags(FOLLOWS_NONE);
+ textboxParams.font( p.font() );
+ textboxParams.font_shadow(LLFontGL::NO_SHADOW);
+ textboxParams.use_ellipses = true;
+ textboxParams.bg_visible = false;
+ textboxParams.mouse_opaque = false;
+ mHeaderTextbox = LLUICtrlFactory::create<LLTextBox>(textboxParams);
+ addChild(mHeaderTextbox);
+}
+
+LLAccordionCtrlTab::LLAccordionCtrlTabHeader::~LLAccordionCtrlTabHeader()
+{
+}
+
+BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::postBuild()
+{
+ return TRUE;
+}
+
+void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitle(const std::string& title)
+{
+ if(mHeaderTextbox)
+ mHeaderTextbox->setText(title);
+}
+
+void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::draw()
+{
+ S32 width = getRect().getWidth();
+ S32 height = getRect().getHeight();
+
+ gl_rect_2d(0,0,width - 1 ,height - 1,mHeaderBGColor.get(),true);
+
+ LLAccordionCtrlTab* parent = dynamic_cast<LLAccordionCtrlTab*>(getParent());
+ bool collapsible = (parent && parent->getCollapsible());
+ bool expanded = (parent && parent->getDisplayChildren());
+
+ // Handle overlay images, if needed
+ // Only show green "focus" background image if the accordion is open,
+ // because the user's mental model of focus is that it goes away after
+ // the accordion is closed.
+ if (getParent()->hasFocus()
+ /*&& !(collapsible && !expanded)*/ // WHY??
+ )
+ {
+ mImageHeaderFocused->draw(0,0,width,height);
+ }
+ else
+ {
+ mImageHeader->draw(0,0,width,height);
+ }
+
+ if(mNeedsHighlight)
+ {
+ mImageHeaderOver->draw(0,0,width,height);
+ }
+
+
+ if(collapsible)
+ {
+ LLPointer<LLUIImage> overlay_image;
+ if(expanded)
+ {
+ overlay_image = mImageExpanded;
+ }
+ else
+ {
+ overlay_image = mImageCollapsed;
+ }
+ overlay_image->draw(HEADER_IMAGE_LEFT_OFFSET,
+ (height - overlay_image->getHeight()) / 2);
+ }
+
+ LLUICtrl::draw();
+}
+
+void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */)
+{
+ S32 header_height = mHeaderTextbox->getTextPixelHeight();
+
+ LLRect textboxRect(HEADER_TEXT_LEFT_OFFSET,(height+header_height)/2 ,width,(height-header_height)/2);
+ mHeaderTextbox->reshape(textboxRect.getWidth(), textboxRect.getHeight());
+ mHeaderTextbox->setRect(textboxRect);
+}
+
+void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+ LLUICtrl::onMouseEnter(x, y, mask);
+ mNeedsHighlight = true;
+}
+void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ LLUICtrl::onMouseLeave(x, y, mask);
+ mNeedsHighlight = false;
+}
+BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleKey(KEY key, MASK mask, BOOL called_from_parent)
+{
+ if ( ( key == KEY_LEFT || key == KEY_RIGHT) && mask == MASK_NONE)
+ {
+ return getParent()->handleKey(key, mask, called_from_parent);
+ }
+ return LLUICtrl::handleKey(key, mask, called_from_parent);
+}
+
+
+LLAccordionCtrlTab::Params::Params()
+ : title("title")
+ ,display_children("expanded", true)
+ ,header_height("header_height", HEADER_HEIGHT),
+ min_width("min_width", 0),
+ min_height("min_height", 0)
+ ,collapsible("collapsible", true)
+ ,header_bg_color("header_bg_color")
+ ,dropdown_bg_color("dropdown_bg_color")
+ ,header_visible("header_visible",true)
+ ,padding_left("padding_left",2)
+ ,padding_right("padding_right",2)
+ ,padding_top("padding_top",2)
+ ,padding_bottom("padding_bottom",2)
+ ,header_expand_img("header_expand_img")
+ ,header_expand_img_pressed("header_expand_img_pressed")
+ ,header_collapse_img("header_collapse_img")
+ ,header_collapse_img_pressed("header_collapse_img_pressed")
+ ,header_image("header_image")
+ ,header_image_over("header_image_over")
+ ,header_image_pressed("header_image_pressed")
+ ,header_image_focused("header_image_focused")
+ ,header_text_color("header_text_color")
+{
+ mouse_opaque(false);
+}
+
+LLAccordionCtrlTab::LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&p)
+ : LLUICtrl(p)
+ ,mDisplayChildren(p.display_children)
+ ,mCollapsible(p.collapsible)
+ ,mExpandedHeight(0)
+ ,mDropdownBGColor(p.dropdown_bg_color())
+ ,mHeaderVisible(p.header_visible)
+ ,mPaddingLeft(p.padding_left)
+ ,mPaddingRight(p.padding_right)
+ ,mPaddingTop(p.padding_top)
+ ,mPaddingBottom(p.padding_bottom)
+ ,mCanOpenClose(true)
+{
+ mStoredOpenCloseState = false;
+ mWasStateStored = false;
+
+ mDropdownBGColor = LLColor4::white;
+ LLAccordionCtrlTabHeader::Params headerParams;
+ headerParams.name(DD_HEADER_NAME);
+ headerParams.title(p.title);
+ mHeader = LLUICtrlFactory::create<LLAccordionCtrlTabHeader>(headerParams);
+ addChild(mHeader, 1);
+
+ reshape(100, 200,FALSE);
+}
+
+LLAccordionCtrlTab::~LLAccordionCtrlTab()
+{
+}
+
+
+void LLAccordionCtrlTab::setDisplayChildren(bool display)
+{
+ mDisplayChildren = display;
+ LLRect rect = getRect();
+
+ rect.mBottom = rect.mTop - (getDisplayChildren() ?
+ mExpandedHeight : HEADER_HEIGHT);
+ setRect(rect);
+
+ for(child_list_const_iter_t it = getChildList()->begin();
+ getChildList()->end() != it; ++it)
+ {
+ LLView* child = *it;
+ if(DD_HEADER_NAME == child->getName())
+ continue;
+
+ child->setVisible(getDisplayChildren());
+ }
+}
+
+void LLAccordionCtrlTab::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */)
+{
+ LLRect headerRect;
+
+ LLUICtrl::reshape(width, height, TRUE);
+
+ headerRect.setLeftTopAndSize(
+ 0,height,width,HEADER_HEIGHT);
+ mHeader->setRect(headerRect);
+ mHeader->reshape(headerRect.getWidth(), headerRect.getHeight());
+
+ for(child_list_const_iter_t it = getChildList()->begin();
+ getChildList()->end() != it; ++it)
+ {
+ LLView* child = *it;
+ if(DD_HEADER_NAME == child->getName())
+ continue;
+ if(!child->getVisible())
+ continue;
+
+ LLRect childRect = child->getRect();
+ S32 childWidth = width - getPaddingLeft() - getPaddingRight();
+ S32 childHeight = height - getHeaderHeight() - getPaddingTop() - getPaddingBottom();
+
+ child->reshape(childWidth,childHeight);
+
+ childRect.setLeftTopAndSize(
+ getPaddingLeft(),
+ childHeight + getPaddingBottom(),
+ childWidth,
+ childHeight);
+
+ child->setRect(childRect);
+
+ break;//suppose that there is only one panel
+ }
+
+}
+
+void LLAccordionCtrlTab::changeOpenClose(bool is_open)
+{
+ if(is_open)
+ mExpandedHeight = getRect().getHeight();
+
+ setDisplayChildren(!is_open);
+ reshape(getRect().getWidth(), getRect().getHeight(), FALSE);
+ if (mCommitSignal)
+ {
+ (*mCommitSignal)(this, getDisplayChildren());
+ }
+}
+
+BOOL LLAccordionCtrlTab::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ if(mCollapsible && mHeaderVisible && mCanOpenClose)
+ {
+ if(y >= (getRect().getHeight() - HEADER_HEIGHT) )
+ {
+ LLAccordionCtrlTabHeader* header = getChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
+ header->setFocus(true);
+ changeOpenClose(getDisplayChildren());
+
+ //reset stored state
+ mWasStateStored = false;
+ return TRUE;
+ }
+ }
+ return LLUICtrl::handleMouseDown(x,y,mask);
+}
+
+BOOL LLAccordionCtrlTab::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+ return LLUICtrl::handleMouseUp(x,y,mask);
+}
+
+boost::signals2::connection LLAccordionCtrlTab::setDropDownStateChangedCallback(commit_callback_t cb)
+{
+ return setCommitCallback(cb);
+}
+
+bool LLAccordionCtrlTab::addChild(LLView* child, S32 tab_group)
+{
+ if(DD_HEADER_NAME != child->getName())
+ {
+ reshape(child->getRect().getWidth() , child->getRect().getHeight() + HEADER_HEIGHT );
+ mExpandedHeight = getRect().getHeight();
+ }
+
+ bool res = LLUICtrl::addChild(child, tab_group);
+
+ if(DD_HEADER_NAME != child->getName())
+ {
+ if(!mCollapsible)
+ setDisplayChildren(true);
+ else
+ setDisplayChildren(getDisplayChildren());
+ }
+
+ return res;
+}
+
+void LLAccordionCtrlTab::setAccordionView(LLView* panel)
+{
+ addChild(panel,0);
+}
+
+
+LLView* LLAccordionCtrlTab::getAccordionView()
+{
+ for(child_list_const_iter_t it = getChildList()->begin();
+ getChildList()->end() != it; ++it)
+ {
+ LLView* child = *it;
+ if(DD_HEADER_NAME == child->getName())
+ continue;
+ if(!child->getVisible())
+ continue;
+ return child;
+ }
+ return NULL;
+}
+
+
+S32 LLAccordionCtrlTab::getHeaderHeight()
+{
+ return mHeaderVisible?HEADER_HEIGHT:0;
+}
+
+void LLAccordionCtrlTab::setHeaderVisible(bool value)
+{
+ if(mHeaderVisible == value)
+ return;
+ mHeaderVisible = value;
+ if(mHeader)
+ mHeader->setVisible(value);
+ reshape(getRect().getWidth(), getRect().getHeight(), FALSE);
+};
+
+//vurtual
+BOOL LLAccordionCtrlTab::postBuild()
+{
+ mHeader->setVisible(mHeaderVisible);
+ return LLUICtrl::postBuild();
+}
+bool LLAccordionCtrlTab::notifyChildren (const LLSD& info)
+{
+ if(info.has("action"))
+ {
+ std::string str_action = info["action"];
+ if(str_action == "store_state")
+ {
+ storeOpenCloseState();
+ return true;
+ }
+ if(str_action == "restore_state")
+ {
+ restoreOpenCloseState();
+ return true;
+ }
+ }
+ return LLUICtrl::notifyChildren(info);
+}
+
+S32 LLAccordionCtrlTab::notifyParent(const LLSD& info)
+{
+ if(info.has("action"))
+ {
+ std::string str_action = info["action"];
+ if(str_action == "size_changes")
+ {
+ //
+ S32 height = info["height"];
+ height = llmax(height,10) + HEADER_HEIGHT + getPaddingTop() + getPaddingBottom();
+
+ mExpandedHeight = height;
+
+ if(isExpanded())
+ {
+ LLRect panel_rect = getRect();
+ panel_rect.setLeftTopAndSize( panel_rect.mLeft, panel_rect.mTop, panel_rect.getWidth(), height);
+ reshape(getRect().getWidth(),height);
+ setRect(panel_rect);
+ }
+
+ //LLAccordionCtrl should rearrange accodion tab if one of accordion change its size
+ getParent()->notifyParent(info);
+ return 1;
+ }
+ else if(str_action == "select_prev")
+ {
+ showAndFocusHeader();
+ return 1;
+ }
+ }
+ return LLUICtrl::notifyParent(info);
+}
+
+S32 LLAccordionCtrlTab::notify(const LLSD& info)
+{
+ if(info.has("action"))
+ {
+ std::string str_action = info["action"];
+ if(str_action == "select_first")
+ {
+ showAndFocusHeader();
+ return 1;
+ }
+ else if( str_action == "select_last" )
+ {
+ if(getDisplayChildren() == false)
+ {
+ showAndFocusHeader();
+ }
+ else
+ {
+ LLView* view = getAccordionView();
+ if(view)
+ view->notify(LLSD().with("action","select_last"));
+ }
+ }
+ }
+ return 0;
+}
+
+BOOL LLAccordionCtrlTab::handleKey(KEY key, MASK mask, BOOL called_from_parent)
+{
+ LLAccordionCtrlTabHeader* header = getChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
+ if( !header->hasFocus() )
+ return LLUICtrl::handleKey(key, mask, called_from_parent);
+
+ if ( (key == KEY_ADD || key == KEY_RIGHT)&& mask == MASK_NONE)
+ {
+ if(getDisplayChildren() == false)
+ {
+ changeOpenClose(getDisplayChildren());
+ return TRUE;
+ }
+ }
+ if ( (key == KEY_SUBTRACT || key == KEY_LEFT)&& mask == MASK_NONE)
+ {
+ if(getDisplayChildren() == true)
+ {
+ changeOpenClose(getDisplayChildren());
+ return TRUE;
+ }
+ }
+
+ if ( key == KEY_DOWN && mask == MASK_NONE)
+ {
+ //if collapsed go to the next accordion
+ if(getDisplayChildren() == false)
+ //we processing notifyParent so let call parent directly
+ getParent()->notifyParent(LLSD().with("action","select_next"));
+ else
+ {
+ getAccordionView()->notify(LLSD().with("action","select_first"));
+ }
+ return TRUE;
+ }
+
+ if ( key == KEY_UP && mask == MASK_NONE)
+ {
+ //go to the previous accordion
+
+ //we processing notifyParent so let call parent directly
+ getParent()->notifyParent(LLSD().with("action","select_prev"));
+ return TRUE;
+ }
+
+ return LLUICtrl::handleKey(key, mask, called_from_parent);
+}
+
+void LLAccordionCtrlTab::showAndFocusHeader()
+{
+ LLAccordionCtrlTabHeader* header = getChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
+ header->setFocus(true);
+
+ LLRect screen_rc;
+ LLRect selected_rc = header->getRect();
+ localRectToScreen(selected_rc, &screen_rc);
+ notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue()));
+
+}
+void LLAccordionCtrlTab::storeOpenCloseState()
+{
+ if(mWasStateStored)
+ return;
+ mStoredOpenCloseState = getDisplayChildren();
+ mWasStateStored = true;
+}
+void LLAccordionCtrlTab::restoreOpenCloseState()
+{
+ if(!mWasStateStored)
+ return;
+ if(getDisplayChildren() != mStoredOpenCloseState)
+ {
+ changeOpenClose(getDisplayChildren());
+ }
+ mWasStateStored = false;
+}
diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h
new file mode 100644
index 0000000000..b200d43438
--- /dev/null
+++ b/indra/llui/llaccordionctrltab.h
@@ -0,0 +1,191 @@
+/**
+ * @file LLAccordionCtrlTab.h
+ * @brief Collapsible box control implementation
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_ACCORDIONCTRLTAB_H_
+#define LL_ACCORDIONCTRLTAB_H_
+
+#include <string>
+#include "llrect.h"
+
+class LLUICtrl;
+class LLUICtrlFactory;
+class LLUIImage;
+class LLButton;
+class LLTextBox;
+
+
+
+// LLAccordionCtrlTab is a container for other controls.
+// It has a Header, by clicking on which hosted controls are shown or hidden.
+// When hosted controls are show - LLAccordionCtrlTab is expanded.
+// When hosted controls are hidden - LLAccordionCtrlTab is collapsed.
+
+class LLAccordionCtrlTab : public LLUICtrl
+{
+// Interface
+public:
+
+ struct Params
+ : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<bool> display_children, //expanded or collapsed after initialization
+ collapsible;
+
+ Optional<std::string> title;
+
+ Optional<S32> header_height,
+ min_width,
+ min_height;
+
+ // Overlay images (arrows on the left)
+ Mandatory<LLUIImage*> header_expand_img,
+ header_expand_img_pressed,
+ header_collapse_img,
+ header_collapse_img_pressed;
+
+ // Background images for the accordion tabs
+ Mandatory<LLUIImage*> header_image,
+ header_image_over,
+ header_image_pressed,
+ header_image_focused;
+
+ Optional<LLUIColor> header_bg_color,
+ header_text_color,
+ dropdown_bg_color;
+
+ Optional<bool> header_visible;
+
+ Optional<S32> padding_left;
+ Optional<S32> padding_right;
+ Optional<S32> padding_top;
+ Optional<S32> padding_bottom;
+
+ Params();
+ };
+
+ typedef LLDefaultChildRegistry child_registry_t;
+
+ virtual ~LLAccordionCtrlTab();
+
+ // Registers callback for expand/collapse events.
+ boost::signals2::connection setDropDownStateChangedCallback(commit_callback_t cb);
+
+ // Changes expand/collapse state
+ virtual void setDisplayChildren(bool display);
+
+ // Returns expand/collapse state
+ virtual bool getDisplayChildren() const {return mDisplayChildren;};
+
+ //set LLAccordionCtrlTab panel
+ void setAccordionView(LLView* panel);
+ LLView* getAccordionView();
+
+ bool getCollapsible() {return mCollapsible;};
+
+ void setCollapsible(bool collapsible) {mCollapsible = collapsible;};
+ void changeOpenClose(bool is_open);
+
+ void canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close;};
+
+ virtual BOOL postBuild();
+
+ S32 notifyParent(const LLSD& info);
+ S32 notify(const LLSD& info);
+ bool notifyChildren(const LLSD& info);
+
+ void storeOpenCloseState ();
+ void restoreOpenCloseState ();
+
+protected:
+ LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&);
+ friend class LLUICtrlFactory;
+
+// Overrides
+public:
+
+ // Call reshape after changing size
+ virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+ // Changes expand/collapse state and triggers expand/collapse callbacks
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+
+ virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
+
+ virtual bool addChild(LLView* child, S32 tab_group);
+
+ bool isExpanded() { return mDisplayChildren; }
+
+ S32 getHeaderHeight();
+
+ // Min size functions
+
+ void setHeaderVisible(bool value);
+
+ bool getHeaderVisible() { return mHeaderVisible;}
+
+ S32 mExpandedHeight; // Height of expanded ctrl.
+ // Used to restore height after expand.
+
+ S32 getPaddingLeft() const { return mPaddingLeft;}
+ S32 getPaddingRight() const { return mPaddingRight;}
+ S32 getPaddingTop() const { return mPaddingTop;}
+ S32 getPaddingBottom() const { return mPaddingBottom;}
+
+ void showAndFocusHeader();
+
+private:
+
+
+
+ class LLAccordionCtrlTabHeader;
+ LLAccordionCtrlTabHeader* mHeader; //Header
+
+ bool mDisplayChildren; //Expanded/collapsed
+ bool mCollapsible;
+ bool mHeaderVisible;
+
+ bool mCanOpenClose;
+
+ S32 mPaddingLeft;
+ S32 mPaddingRight;
+ S32 mPaddingTop;
+ S32 mPaddingBottom;
+
+ bool mStoredOpenCloseState;
+ bool mWasStateStored;
+
+
+ LLUIColor mDropdownBGColor;
+};
+
+#endif
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 2c2c1c25d8..9ce8ce8d55 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -32,6 +32,7 @@
#include "linden_common.h"
+#define LLBUTTON_CPP
#include "llbutton.h"
// Linden library includes
@@ -39,189 +40,213 @@
#include "llstring.h"
// Project includes
-#include "llhtmlhelp.h"
#include "llkeyboard.h"
#include "llui.h"
#include "lluiconstants.h"
#include "llresmgr.h"
#include "llcriticaldamp.h"
+#include "llfloater.h"
+#include "llfloaterreg.h"
#include "llfocusmgr.h"
#include "llwindow.h"
+#include "llnotificationsutil.h"
#include "llrender.h"
+#include "lluictrlfactory.h"
+#include "llhelp.h"
+#include "lldockablefloater.h"
-static LLRegisterWidget<LLButton> r("button");
+static LLDefaultChildRegistry::Register<LLButton> r("button");
+
+// Compiler optimization, generate extern template
+template class LLButton* LLView::getChild<class LLButton>(
+ const std::string& name, BOOL recurse) const;
// globals loaded from settings.xml
-S32 LLBUTTON_ORIG_H_PAD = 6; // Pre-zoomable UI
S32 LLBUTTON_H_PAD = 0;
-S32 LLBUTTON_V_PAD = 0;
S32 BTN_HEIGHT_SMALL= 0;
S32 BTN_HEIGHT = 0;
-S32 BTN_GRID = 12;
-S32 BORDER_SIZE = 1;
-
-LLButton::LLButton( const std::string& name, const LLRect& rect, const std::string& control_name, void (*click_callback)(void*), void *callback_data)
-: LLUICtrl(name, rect, TRUE, NULL, NULL),
- mClickedCallback( click_callback ),
- mMouseDownCallback( NULL ),
- mMouseUpCallback( NULL ),
- mHeldDownCallback( NULL ),
- mGLFont( NULL ),
- mMouseDownFrame( 0 ),
- mHeldDownDelay( 0.5f ), // seconds until held-down callback is called
- mHeldDownFrameDelay( 0 ),
- mImageUnselected( NULL ),
- mImageSelected( NULL ),
- mImageHoverSelected( NULL ),
- mImageHoverUnselected( NULL ),
- mImageDisabled( NULL ),
- mImageDisabledSelected( NULL ),
- mToggleState( FALSE ),
- mIsToggle( FALSE ),
- mScaleImage( TRUE ),
- mDropShadowedText( TRUE ),
- mBorderEnabled( FALSE ),
- mFlashing( FALSE ),
- mHAlign( LLFontGL::HCENTER ),
- mLeftHPad( LLBUTTON_H_PAD ),
- mRightHPad( LLBUTTON_H_PAD ),
- mHoverGlowStrength(0.15f),
- mCurGlowStrength(0.f),
- mNeedsHighlight(FALSE),
- mCommitOnReturn(TRUE),
- mImagep( NULL )
+LLButton::Params::Params()
+: label_selected("label_selected"), // requires is_toggle true
+ label_shadow("label_shadow", true),
+ auto_resize("auto_resize", false),
+ use_ellipses("use_ellipses", false),
+ image_unselected("image_unselected"),
+ image_selected("image_selected"),
+ image_hover_selected("image_hover_selected"),
+ image_hover_unselected("image_hover_unselected"),
+ image_disabled_selected("image_disabled_selected"),
+ image_disabled("image_disabled"),
+ image_pressed("image_pressed"),
+ image_pressed_selected("image_pressed_selected"),
+ image_overlay("image_overlay"),
+ image_overlay_alignment("image_overlay_alignment", std::string("center")),
+ label_color("label_color"),
+ label_color_selected("label_color_selected"), // requires is_toggle true
+ label_color_disabled("label_color_disabled"),
+ label_color_disabled_selected("label_color_disabled_selected"),
+ highlight_color("highlight_color"),
+ image_color("image_color"),
+ image_color_disabled("image_color_disabled"),
+ image_overlay_color("image_overlay_color", LLColor4::white),
+ flash_color("flash_color"),
+ pad_right("pad_right", LLUI::sSettingGroups["config"]->getS32("ButtonHPad")),
+ pad_left("pad_left", LLUI::sSettingGroups["config"]->getS32("ButtonHPad")),
+ pad_bottom("pad_bottom"),
+ click_callback("click_callback"),
+ mouse_down_callback("mouse_down_callback"),
+ mouse_up_callback("mouse_up_callback"),
+ mouse_held_callback("mouse_held_callback"),
+ is_toggle("is_toggle", false),
+ scale_image("scale_image", true),
+ hover_glow_amount("hover_glow_amount"),
+ commit_on_return("commit_on_return", true)
{
- mUnselectedLabel = name;
- mSelectedLabel = name;
-
- setImageUnselected(std::string("button_enabled_32x128.tga"));
- setImageSelected(std::string("button_enabled_selected_32x128.tga"));
- setImageDisabled(std::string("button_disabled_32x128.tga"));
- setImageDisabledSelected(std::string("button_disabled_32x128.tga"));
-
- mImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" );
- mDisabledImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" );
-
- init(click_callback, callback_data, NULL, control_name);
+ addSynonym(is_toggle, "toggle");
+ held_down_delay.seconds = 0.5f;
+ initial_value.set(LLSD(false), false);
}
-LLButton::LLButton(const std::string& name, const LLRect& rect,
- const std::string &unselected_image_name,
- const std::string &selected_image_name,
- const std::string& control_name,
- void (*click_callback)(void*),
- void *callback_data,
- const LLFontGL *font,
- const std::string& unselected_label,
- const std::string& selected_label )
-: LLUICtrl(name, rect, TRUE, NULL, NULL),
- mClickedCallback( click_callback ),
- mMouseDownCallback( NULL ),
- mMouseUpCallback( NULL ),
- mHeldDownCallback( NULL ),
- mGLFont( NULL ),
- mMouseDownFrame( 0 ),
- mHeldDownDelay( 0.5f ), // seconds until held-down callback is called
- mHeldDownFrameDelay( 0 ),
- mImageUnselected( NULL ),
- mImageSelected( NULL ),
- mImageHoverSelected( NULL ),
- mImageHoverUnselected( NULL ),
- mImageDisabled( NULL ),
- mImageDisabledSelected( NULL ),
- mToggleState( FALSE ),
- mIsToggle( FALSE ),
- mScaleImage( TRUE ),
- mDropShadowedText( TRUE ),
+LLButton::LLButton(const LLButton::Params& p)
+: LLUICtrl(p),
+ mMouseDownFrame(0),
+ mMouseHeldDownCount(0),
mBorderEnabled( FALSE ),
mFlashing( FALSE ),
- mHAlign( LLFontGL::HCENTER ),
- mLeftHPad( LLBUTTON_H_PAD ),
- mRightHPad( LLBUTTON_H_PAD ),
- mHoverGlowStrength(0.25f),
mCurGlowStrength(0.f),
mNeedsHighlight(FALSE),
- mCommitOnReturn(TRUE),
- mImagep( NULL )
-{
- mUnselectedLabel = unselected_label;
- mSelectedLabel = selected_label;
+ mUnselectedLabel(p.label()),
+ mSelectedLabel(p.label_selected()),
+ mGLFont(p.font),
+ mHeldDownDelay(p.held_down_delay.seconds), // seconds until held-down callback is called
+ mHeldDownFrameDelay(p.held_down_delay.frames),
+ mImageUnselected(p.image_unselected),
+ mImageSelected(p.image_selected),
+ mImageDisabled(p.image_disabled),
+ mImageDisabledSelected(p.image_disabled_selected),
+ mImagePressed(p.image_pressed),
+ mImagePressedSelected(p.image_pressed_selected),
+ mImageHoverSelected(p.image_hover_selected),
+ mImageHoverUnselected(p.image_hover_unselected),
+ mUnselectedLabelColor(p.label_color()),
+ mSelectedLabelColor(p.label_color_selected()),
+ mDisabledLabelColor(p.label_color_disabled()),
+ mDisabledSelectedLabelColor(p.label_color_disabled_selected()),
+ mHighlightColor(p.highlight_color()),
+ mImageColor(p.image_color()),
+ mFlashBgColor(p.flash_color()),
+ mDisabledImageColor(p.image_color_disabled()),
+ mImageOverlay(p.image_overlay()),
+ mImageOverlayColor(p.image_overlay_color()),
+ mImageOverlayAlignment(LLFontGL::hAlignFromName(p.image_overlay_alignment)),
+ mIsToggle(p.is_toggle),
+ mScaleImage(p.scale_image),
+ mDropShadowedText(p.label_shadow),
+ mAutoResize(p.auto_resize),
+ mUseEllipses( p.use_ellipses ),
+ mHAlign(p.font_halign),
+ mLeftHPad(p.pad_left),
+ mRightHPad(p.pad_right),
+ mBottomVPad(p.pad_bottom),
+ mHoverGlowStrength(p.hover_glow_amount),
+ mCommitOnReturn(p.commit_on_return),
+ mFadeWhenDisabled(FALSE),
+ mForcePressedState(false),
+ mLastDrawCharsCount(0),
+ mMouseDownSignal(NULL),
+ mMouseUpSignal(NULL),
+ mHeldDownSignal(NULL)
- // by default, disabled color is same as enabled
- mImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" );
- mDisabledImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" );
+{
+ static LLUICachedControl<S32> llbutton_orig_h_pad ("UIButtonOrigHPad", 0);
+ static Params default_params(LLUICtrlFactory::getDefaultParams<LLButton>());
- if( unselected_image_name != "" )
+ if (!p.label_selected.isProvided())
{
- // user-specified image - don't use fixed borders unless requested
- setImageUnselected(unselected_image_name);
- setImageDisabled(unselected_image_name);
-
- mDisabledImageColor.mV[VALPHA] = 0.5f;
- mScaleImage = FALSE;
+ mSelectedLabel = mUnselectedLabel;
}
- else
+
+ // Hack to make sure there is space for at least one character
+ if (getRect().getWidth() - (mRightHPad + mLeftHPad) < mGLFont->getWidth(std::string(" ")))
{
- setImageUnselected(std::string("button_enabled_32x128.tga"));
- setImageDisabled(std::string("button_disabled_32x128.tga"));
+ // Use old defaults
+ mLeftHPad = llbutton_orig_h_pad;
+ mRightHPad = llbutton_orig_h_pad;
}
+
+ mMouseDownTimer.stop();
- if( selected_image_name != "" )
+ // if custom unselected button image provided...
+ if (p.image_unselected != default_params.image_unselected)
{
- // user-specified image - don't use fixed borders unless requested
- setImageSelected(selected_image_name);
- setImageDisabledSelected(selected_image_name);
+ //...fade it out for disabled image by default...
+ if (p.image_disabled() == default_params.image_disabled() )
+ {
+ mImageDisabled = p.image_unselected;
+ mFadeWhenDisabled = TRUE;
+ }
- mDisabledImageColor.mV[VALPHA] = 0.5f;
- mScaleImage = FALSE;
+ if (p.image_pressed_selected == default_params.image_pressed_selected)
+ {
+ mImagePressedSelected = mImageUnselected;
+ }
}
- else
+
+ // if custom selected button image provided...
+ if (p.image_selected != default_params.image_selected)
{
- setImageSelected(std::string("button_enabled_selected_32x128.tga"));
- setImageDisabledSelected(std::string("button_disabled_32x128.tga"));
- }
+ //...fade it out for disabled image by default...
+ if (p.image_disabled_selected() == default_params.image_disabled_selected())
+ {
+ mImageDisabledSelected = p.image_selected;
+ mFadeWhenDisabled = TRUE;
+ }
- init(click_callback, callback_data, font, control_name);
-}
+ if (p.image_pressed == default_params.image_pressed)
+ {
+ mImagePressed = mImageSelected;
+ }
+ }
-void LLButton::init(void (*click_callback)(void*), void *callback_data, const LLFontGL* font, const std::string& control_name)
-{
- mGLFont = ( font ? font : LLFontGL::getFontSansSerif());
+ if (!p.image_pressed.isProvided())
+ {
+ mImagePressed = mImageSelected;
+ }
- // Hack to make sure there is space for at least one character
- if (getRect().getWidth() - (mRightHPad + mLeftHPad) < mGLFont->getWidth(std::string(" ")))
+ if (!p.image_pressed_selected.isProvided())
{
- // Use old defaults
- mLeftHPad = LLBUTTON_ORIG_H_PAD;
- mRightHPad = LLBUTTON_ORIG_H_PAD;
+ mImagePressedSelected = mImageUnselected;
}
- mCallbackUserData = callback_data;
- mMouseDownTimer.stop();
-
- setControlName(control_name, NULL);
-
- mUnselectedLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelColor" ) );
- mSelectedLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelSelectedColor" ) );
- mDisabledLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelDisabledColor" ) );
- mDisabledSelectedLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelSelectedDisabledColor" ) );
- mHighlightColor = ( LLUI::sColorsGroup->getColor( "ButtonUnselectedFgColor" ) );
- mUnselectedBgColor = ( LLUI::sColorsGroup->getColor( "ButtonUnselectedBgColor" ) );
- mSelectedBgColor = ( LLUI::sColorsGroup->getColor( "ButtonSelectedBgColor" ) );
- mFlashBgColor = ( LLUI::sColorsGroup->getColor( "ButtonFlashBgColor" ) );
-
- mImageOverlayAlignment = LLFontGL::HCENTER;
- mImageOverlayColor = LLColor4::white;
+ if (mImageUnselected.isNull())
+ {
+ llwarns << "Button: " << getName() << " with no image!" << llendl;
+ }
+
+ if (p.click_callback.isProvided())
+ {
+ setCommitCallback(initCommitCallback(p.click_callback)); // alias -> commit_callback
+ }
+ if (p.mouse_down_callback.isProvided())
+ {
+ setMouseDownCallback(initCommitCallback(p.mouse_down_callback));
+ }
+ if (p.mouse_up_callback.isProvided())
+ {
+ setMouseUpCallback(initCommitCallback(p.mouse_up_callback));
+ }
+ if (p.mouse_held_callback.isProvided())
+ {
+ setHeldDownCallback(initCommitCallback(p.mouse_held_callback));
+ }
}
LLButton::~LLButton()
{
- if( hasMouseCapture() )
- {
- gFocusMgr.setMouseCapture( NULL );
- }
+ delete mMouseDownSignal;
+ delete mMouseUpSignal;
+ delete mHeldDownSignal;
}
// HACK: Committing a button is the same as instantly clicking it.
@@ -229,19 +254,12 @@ LLButton::~LLButton()
void LLButton::onCommit()
{
// WARNING: Sometimes clicking a button destroys the floater or
- // panel containing it. Therefore we need to call mClickedCallback
+ // panel containing it. Therefore we need to call LLUICtrl::onCommit()
// LAST, otherwise this becomes deleted memory.
- LLUICtrl::onCommit();
- if (mMouseDownCallback)
- {
- (*mMouseDownCallback)(mCallbackUserData);
- }
+ if (mMouseDownSignal) (*mMouseDownSignal)(this, LLSD());
- if (mMouseUpCallback)
- {
- (*mMouseUpCallback)(mCallbackUserData);
- }
+ if (mMouseUpSignal) (*mMouseUpSignal)(this, LLSD());
if (getSoundFlags() & MOUSE_DOWN)
{
@@ -259,14 +277,54 @@ void LLButton::onCommit()
}
// do this last, as it can result in destroying this button
- if (mClickedCallback)
- {
- (*mClickedCallback)( mCallbackUserData );
- }
+ LLUICtrl::onCommit();
}
+boost::signals2::connection LLButton::setClickedCallback( const commit_signal_t::slot_type& cb )
+{
+ if (!mCommitSignal) mCommitSignal = new commit_signal_t();
+ return mCommitSignal->connect(cb);
+}
+boost::signals2::connection LLButton::setMouseDownCallback( const commit_signal_t::slot_type& cb )
+{
+ if (!mMouseDownSignal) mMouseDownSignal = new commit_signal_t();
+ return mMouseDownSignal->connect(cb);
+}
+boost::signals2::connection LLButton::setMouseUpCallback( const commit_signal_t::slot_type& cb )
+{
+ if (!mMouseUpSignal) mMouseUpSignal = new commit_signal_t();
+ return mMouseUpSignal->connect(cb);
+}
+boost::signals2::connection LLButton::setHeldDownCallback( const commit_signal_t::slot_type& cb )
+{
+ if (!mHeldDownSignal) mHeldDownSignal = new commit_signal_t();
+ return mHeldDownSignal->connect(cb);
+}
+// *TODO: Deprecate (for backwards compatability only)
+boost::signals2::connection LLButton::setClickedCallback( button_callback_t cb, void* data )
+{
+ return setClickedCallback(boost::bind(cb, data));
+}
+boost::signals2::connection LLButton::setMouseDownCallback( button_callback_t cb, void* data )
+{
+ return setMouseDownCallback(boost::bind(cb, data));
+}
+boost::signals2::connection LLButton::setMouseUpCallback( button_callback_t cb, void* data )
+{
+ return setMouseUpCallback(boost::bind(cb, data));
+}
+boost::signals2::connection LLButton::setHeldDownCallback( button_callback_t cb, void* data )
+{
+ return setHeldDownCallback(boost::bind(cb, data));
+}
+
+BOOL LLButton::postBuild()
+{
+ autoResize();
+ return TRUE;
+}
BOOL LLButton::handleUnicodeCharHere(llwchar uni_char)
{
BOOL handled = FALSE;
@@ -278,10 +336,8 @@ BOOL LLButton::handleUnicodeCharHere(llwchar uni_char)
toggleState();
}
- if (mClickedCallback)
- {
- (*mClickedCallback)( mCallbackUserData );
- }
+ LLUICtrl::onCommit();
+
handled = TRUE;
}
return handled;
@@ -299,10 +355,7 @@ BOOL LLButton::handleKeyHere(KEY key, MASK mask )
handled = TRUE;
- if (mClickedCallback)
- {
- (*mClickedCallback)( mCallbackUserData );
- }
+ LLUICtrl::onCommit();
}
return handled;
}
@@ -310,27 +363,35 @@ BOOL LLButton::handleKeyHere(KEY key, MASK mask )
BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask)
{
- // Route future Mouse messages here preemptively. (Release on mouse up.)
- gFocusMgr.setMouseCapture( this );
-
- if (hasTabStop() && !getIsChrome())
+ if (!childrenHandleMouseDown(x, y, mask))
{
- setFocus(TRUE);
- }
+ // Route future Mouse messages here preemptively. (Release on mouse up.)
+ gFocusMgr.setMouseCapture( this );
- if (mMouseDownCallback)
- {
- (*mMouseDownCallback)(mCallbackUserData);
- }
+ if (hasTabStop() && !getIsChrome())
+ {
+ setFocus(TRUE);
+ }
- mMouseDownTimer.start();
- mMouseDownFrame = (S32) LLFrameTimer::getFrameCount();
-
- if (getSoundFlags() & MOUSE_DOWN)
- {
- make_ui_sound("UISndClick");
- }
+ /*
+ * ATTENTION! This call fires another mouse down callback.
+ * If you wish to remove this call emit that signal directly
+ * by calling LLUICtrl::mMouseDownSignal(x, y, mask);
+ */
+ LLUICtrl::handleMouseDown(x, y, mask);
+
+ if(mMouseDownSignal) (*mMouseDownSignal)(this, LLSD());
+
+ mMouseDownTimer.start();
+ mMouseDownFrame = (S32) LLFrameTimer::getFrameCount();
+ mMouseHeldDownCount = 0;
+
+ if (getSoundFlags() & MOUSE_DOWN)
+ {
+ make_ui_sound("UISndClick");
+ }
+ }
return TRUE;
}
@@ -343,14 +404,17 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
// Always release the mouse
gFocusMgr.setMouseCapture( NULL );
+ /*
+ * ATTENTION! This call fires another mouse up callback.
+ * If you wish to remove this call emit that signal directly
+ * by calling LLUICtrl::mMouseUpSignal(x, y, mask);
+ */
+ LLUICtrl::handleMouseUp(x, y, mask);
+
// Regardless of where mouseup occurs, handle callback
- if (mMouseUpCallback)
- {
- (*mMouseUpCallback)(mCallbackUserData);
- }
+ if(mMouseUpSignal) (*mMouseUpSignal)(this, LLSD());
- mMouseDownTimer.stop();
- mMouseDownTimer.reset();
+ resetMouseDownTimer();
// DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked.
// If mouseup in the widget, it's been clicked
@@ -366,38 +430,106 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
toggleState();
}
- if (mClickedCallback)
- {
- (*mClickedCallback)( mCallbackUserData );
- }
+ LLUICtrl::onCommit();
}
}
+ else
+ {
+ childrenHandleMouseUp(x, y, mask);
+ }
return TRUE;
}
-
-BOOL LLButton::handleHover(S32 x, S32 y, MASK mask)
+BOOL LLButton::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
- LLMouseHandler* other_captor = gFocusMgr.getMouseCapture();
- mNeedsHighlight = other_captor == NULL ||
- other_captor == this ||
- // this following bit is to support modal dialogs
- (other_captor->isView() && hasAncestor((LLView*)other_captor));
-
- if (mMouseDownTimer.getStarted() && NULL != mHeldDownCallback)
+ if (!childrenHandleRightMouseDown(x, y, mask))
{
- F32 elapsed = getHeldDownTime();
- if( mHeldDownDelay <= elapsed && mHeldDownFrameDelay <= (S32)LLFrameTimer::getFrameCount() - mMouseDownFrame)
+ // Route future Mouse messages here preemptively. (Release on mouse up.)
+ gFocusMgr.setMouseCapture( this );
+
+ if (hasTabStop() && !getIsChrome())
{
- mHeldDownCallback( mCallbackUserData );
+ setFocus(TRUE);
}
+
+// if (pointInView(x, y))
+// {
+// }
}
+ // send the mouse down signal
+ LLUICtrl::handleRightMouseDown(x,y,mask);
+ // *TODO: Return result of LLUICtrl call above? Should defer to base class
+ // but this might change the mouse handling of existing buttons in a bad way
+ // if they are not mouse opaque.
+ return TRUE;
+}
+BOOL LLButton::handleRightMouseUp(S32 x, S32 y, MASK mask)
+{
// We only handle the click if the click both started and ended within us
- getWindow()->setCursor(UI_CURSOR_ARROW);
- lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;
+ if( hasMouseCapture() )
+ {
+ // Always release the mouse
+ gFocusMgr.setMouseCapture( NULL );
+
+// if (pointInView(x, y))
+// {
+// mRightMouseUpSignal(this, x,y,mask);
+// }
+ }
+ else
+ {
+ childrenHandleRightMouseUp(x, y, mask);
+ }
+ // send the mouse up signal
+ LLUICtrl::handleRightMouseUp(x,y,mask);
+ // *TODO: Return result of LLUICtrl call above? Should defer to base class
+ // but this might change the mouse handling of existing buttons in a bad way.
+ // if they are not mouse opaque.
+ return TRUE;
+}
+
+
+void LLButton::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+ LLUICtrl::onMouseEnter(x, y, mask);
+
+ if (isInEnabledChain())
+ mNeedsHighlight = TRUE;
+}
+
+void LLButton::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ LLUICtrl::onMouseLeave(x, y, mask);
+
+ mNeedsHighlight = FALSE;
+}
+void LLButton::setHighlight(bool b)
+{
+ mNeedsHighlight = b;
+}
+
+BOOL LLButton::handleHover(S32 x, S32 y, MASK mask)
+{
+ if (!childrenHandleHover(x, y, mask))
+ {
+ if (mMouseDownTimer.getStarted())
+ {
+ F32 elapsed = getHeldDownTime();
+ if( mHeldDownDelay <= elapsed && mHeldDownFrameDelay <= (S32)LLFrameTimer::getFrameCount() - mMouseDownFrame)
+ {
+ LLSD param;
+ param["count"] = mMouseHeldDownCount++;
+ if (mHeldDownSignal) (*mHeldDownSignal)(this, param);
+ }
+ }
+
+ // We only handle the click if the click both started and ended within us
+ getWindow()->setCursor(UI_CURSOR_ARROW);
+ lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;
+ }
return TRUE;
}
@@ -405,16 +537,20 @@ BOOL LLButton::handleHover(S32 x, S32 y, MASK mask)
// virtual
void LLButton::draw()
{
- BOOL flash = FALSE;
+ F32 alpha = getDrawContext().mAlpha;
+ bool flash = FALSE;
+ static LLUICachedControl<F32> button_flash_rate("ButtonFlashRate", 0);
+ static LLUICachedControl<S32> button_flash_count("ButtonFlashCount", 0);
+
if( mFlashing )
{
F32 elapsed = mFlashingTimer.getElapsedTimeF32();
- S32 flash_count = S32(elapsed * LLUI::sConfigGroup->getF32("ButtonFlashRate") * 2.f);
+ S32 flash_count = S32(elapsed * button_flash_rate * 2.f);
// flash on or off?
- flash = (flash_count % 2 == 0) || flash_count > S32((F32)LLUI::sConfigGroup->getS32("ButtonFlashCount") * 2.f);
+ flash = (flash_count % 2 == 0) || flash_count > S32((F32)button_flash_count * 2.f);
}
- BOOL pressed_by_keyboard = FALSE;
+ bool pressed_by_keyboard = FALSE;
if (hasFocus())
{
pressed_by_keyboard = gKeyboard->getKeyDown(' ') || (mCommitOnReturn && gKeyboard->getKeyDown(KEY_RETURN));
@@ -423,26 +559,34 @@ void LLButton::draw()
// Unselected image assignments
S32 local_mouse_x;
S32 local_mouse_y;
- LLUI::getCursorPositionLocal(this, &local_mouse_x, &local_mouse_y);
+ LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y);
- BOOL pressed = pressed_by_keyboard
- || (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y))
- || mToggleState;
+ bool enabled = isInEnabledChain();
+
+ bool pressed = pressed_by_keyboard
+ || (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y))
+ || mForcePressedState;
+ bool selected = getToggleState();
- BOOL use_glow_effect = FALSE;
+ bool use_glow_effect = FALSE;
LLColor4 glow_color = LLColor4::white;
LLRender::eBlendType glow_type = LLRender::BT_ADD_WITH_ALPHA;
- if ( mNeedsHighlight )
+ LLUIImage* imagep = NULL;
+ if (pressed)
{
- if (pressed)
+ imagep = selected ? mImagePressedSelected : mImagePressed;
+ }
+ else if ( mNeedsHighlight )
+ {
+ if (selected)
{
if (mImageHoverSelected)
{
- mImagep = mImageHoverSelected;
+ imagep = mImageHoverSelected;
}
else
{
- mImagep = mImageSelected;
+ imagep = mImageSelected;
use_glow_effect = TRUE;
}
}
@@ -450,32 +594,18 @@ void LLButton::draw()
{
if (mImageHoverUnselected)
{
- mImagep = mImageHoverUnselected;
+ imagep = mImageHoverUnselected;
}
else
{
- mImagep = mImageUnselected;
+ imagep = mImageUnselected;
use_glow_effect = TRUE;
}
}
}
- else if ( pressed )
- {
- mImagep = mImageSelected;
- }
- else
- {
- mImagep = mImageUnselected;
- }
-
- if (mFlashing)
+ else
{
- use_glow_effect = TRUE;
- glow_type = LLRender::BT_ALPHA; // blend the glow
- if (mNeedsHighlight) // highlighted AND flashing
- glow_color = (glow_color*0.5f + mFlashBgColor*0.5f) % 2.0f; // average between flash and highlight colour, with sum of the opacity
- else
- glow_color = mFlashBgColor;
+ imagep = selected ? mImageSelected : mImageUnselected;
}
// Override if more data is available
@@ -485,19 +615,31 @@ void LLButton::draw()
// disabled but checked
if (!mImageDisabledSelected.isNull()
&&
- ( (getEnabled() && getTentative())
- || (!getEnabled() && pressed ) ) )
+ ( (enabled && getTentative())
+ || (!enabled && selected ) ) )
{
- mImagep = mImageDisabledSelected;
+ imagep = mImageDisabledSelected;
}
else if (!mImageDisabled.isNull()
- && !getEnabled()
- && !pressed)
+ && !enabled
+ && !selected)
{
- mImagep = mImageDisabled;
+ imagep = mImageDisabled;
}
- if (mNeedsHighlight && !mImagep)
+ if (mFlashing)
+ {
+ LLColor4 flash_color = mFlashBgColor.get();
+ use_glow_effect = TRUE;
+ glow_type = LLRender::BT_ALPHA; // blend the glow
+
+ if (mNeedsHighlight) // highlighted AND flashing
+ glow_color = (glow_color*0.5f + flash_color*0.5f) % 2.0f; // average between flash and highlight colour, with sum of the opacity
+ else
+ glow_color = flash_color;
+ }
+
+ if (mNeedsHighlight && !imagep)
{
use_glow_effect = TRUE;
}
@@ -506,60 +648,46 @@ void LLButton::draw()
LLColor4 label_color;
// label changes when button state changes, not when pressed
- if ( getEnabled() )
+ if ( enabled )
{
- if ( mToggleState )
+ if ( getToggleState() )
{
- label_color = mSelectedLabelColor;
+ label_color = mSelectedLabelColor.get();
}
else
{
- label_color = mUnselectedLabelColor;
+ label_color = mUnselectedLabelColor.get();
}
}
else
{
- if ( mToggleState )
+ if ( getToggleState() )
{
- label_color = mDisabledSelectedLabelColor;
+ label_color = mDisabledSelectedLabelColor.get();
}
else
{
- label_color = mDisabledLabelColor;
+ label_color = mDisabledLabelColor.get();
}
}
// Unselected label assignments
LLWString label;
- if( mToggleState )
+ if( getToggleState() )
{
- if( getEnabled() || mDisabledSelectedLabel.empty() )
- {
- label = mSelectedLabel;
- }
- else
- {
- label = mDisabledSelectedLabel;
- }
+ label = mSelectedLabel;
}
else
{
- if( getEnabled() || mDisabledLabel.empty() )
- {
- label = mUnselectedLabel;
- }
- else
- {
- label = mDisabledLabel;
- }
+ label = mUnselectedLabel;
}
// overlay with keyboard focus border
if (hasFocus())
{
F32 lerp_amt = gFocusMgr.getFocusFlashAmt();
- drawBorder(gFocusMgr.getFocusColor(), llround(lerp(1.f, 3.f, lerp_amt)));
+ drawBorder(imagep, gFocusMgr.getFocusColor() % alpha, llround(lerp(1.f, 3.f, lerp_amt)));
}
if (use_glow_effect)
@@ -576,25 +704,27 @@ void LLButton::draw()
// Draw button image, if available.
// Otherwise draw basic rectangular button.
- if (mImagep.notNull())
+ if (imagep != NULL)
{
+ // apply automatic 50% alpha fade to disabled image
+ LLColor4 disabled_color = mFadeWhenDisabled ? mDisabledImageColor.get() % 0.5f : mDisabledImageColor.get();
if ( mScaleImage)
{
- mImagep->draw(getLocalRect(), getEnabled() ? mImageColor : mDisabledImageColor );
+ imagep->draw(getLocalRect(), (enabled ? mImageColor.get() : disabled_color) % alpha );
if (mCurGlowStrength > 0.01f)
{
gGL.setSceneBlendType(glow_type);
- mImagep->drawSolid(0, 0, getRect().getWidth(), getRect().getHeight(), glow_color % mCurGlowStrength);
+ imagep->drawSolid(0, 0, getRect().getWidth(), getRect().getHeight(), glow_color % (mCurGlowStrength * alpha));
gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
}
else
{
- mImagep->draw(0, 0, getEnabled() ? mImageColor : mDisabledImageColor );
+ imagep->draw(0, 0, (enabled ? mImageColor.get() : disabled_color) % alpha );
if (mCurGlowStrength > 0.01f)
{
gGL.setSceneBlendType(glow_type);
- mImagep->drawSolid(0, 0, glow_color % mCurGlowStrength);
+ imagep->drawSolid(0, 0, glow_color % (mCurGlowStrength * alpha));
gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
}
@@ -602,9 +732,9 @@ void LLButton::draw()
else
{
// no image
- llwarns << "No image for button " << getName() << llendl;
+ lldebugs << "No image for button " << getName() << llendl;
// draw it in pink so we can find it
- gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4::pink1, FALSE);
+ gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4::pink1 % alpha, FALSE);
}
// let overlay image and text play well together
@@ -634,11 +764,12 @@ void LLButton::draw()
}
// fade out overlay images on disabled buttons
- LLColor4 overlay_color = mImageOverlayColor;
- if (!getEnabled())
+ LLColor4 overlay_color = mImageOverlayColor.get();
+ if (!enabled)
{
overlay_color.mV[VALPHA] = 0.5f;
}
+ overlay_color.mV[VALPHA] *= alpha;
switch(mImageOverlayAlignment)
{
@@ -704,52 +835,51 @@ void LLButton::draw()
x++;
}
- mGLFont->render(label, 0, (F32)x, (F32)(LLBUTTON_V_PAD + y_offset),
- label_color,
+ // *NOTE: mantipov: before mUseEllipses is implemented in EXT-279 U32_MAX has been passed as
+ // max_chars.
+ // LLFontGL::render expects S32 max_chars variable but process in a separate way -1 value.
+ // Due to U32_MAX is equal to S32 -1 value I have rest this value for non-ellipses mode.
+ // Not sure if it is really needed. Probably S32_MAX should be always passed as max_chars.
+ mLastDrawCharsCount = mGLFont->render(label, 0,
+ (F32)x,
+ (F32)(mBottomVPad + y_offset),
+ label_color % alpha,
mHAlign, LLFontGL::BOTTOM,
- mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NORMAL,
- U32_MAX, text_width,
- NULL, FALSE, FALSE);
+ LLFontGL::NORMAL,
+ mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NO_SHADOW,
+ S32_MAX, text_width,
+ NULL, mUseEllipses);
}
- if (sDebugRects
- || (LLView::sEditingUI && this == LLView::sEditingUIView))
- {
- drawDebugRect();
- }
-
- // reset hover status for next frame
- mNeedsHighlight = FALSE;
+ LLUICtrl::draw();
}
-void LLButton::drawBorder(const LLColor4& color, S32 size)
+void LLButton::drawBorder(LLUIImage* imagep, const LLColor4& color, S32 size)
{
+ if (imagep == NULL) return;
if (mScaleImage)
{
- mImagep->drawBorder(getLocalRect(), color, size);
+ imagep->drawBorder(getLocalRect(), color, size);
}
else
{
- mImagep->drawBorder(0, 0, color, size);
+ imagep->drawBorder(0, 0, color, size);
}
}
-void LLButton::setClickedCallback(void (*cb)(void*), void* userdata)
+BOOL LLButton::getToggleState() const
{
- mClickedCallback = cb;
- if (userdata)
- {
- mCallbackUserData = userdata;
- }
+ return getValue().asBoolean();
}
-
void LLButton::setToggleState(BOOL b)
{
- if( b != mToggleState )
+ if( b != getToggleState() )
{
setControlValue(b); // will fire LLControlVariable callbacks (if any)
- mToggleState = b; // may or may not be redundant
+ setValue(b); // may or may not be redundant
+ // Unselected label assignments
+ autoResize();
}
}
@@ -764,19 +894,11 @@ void LLButton::setFlashing( BOOL b )
BOOL LLButton::toggleState()
-{
- setToggleState( !mToggleState );
- return mToggleState;
-}
-
-void LLButton::setValue(const LLSD& value )
{
- mToggleState = value.asBoolean();
-}
+ bool flipped = ! getToggleState();
+ setToggleState(flipped);
-LLSD LLButton::getValue() const
-{
- return mToggleState == TRUE;
+ return flipped;
}
void LLButton::setLabel( const LLStringExplicit& label )
@@ -803,26 +925,48 @@ void LLButton::setLabelSelected( const LLStringExplicit& label )
mSelectedLabel = label;
}
-void LLButton::setDisabledLabel( const LLStringExplicit& label )
+void LLButton::setImageUnselected(LLPointer<LLUIImage> image)
{
- mDisabledLabel = label;
+ mImageUnselected = image;
+ if (mImageUnselected.isNull())
+ {
+ llwarns << "Setting default button image for: " << getName() << " to NULL" << llendl;
+ }
}
-void LLButton::setDisabledSelectedLabel( const LLStringExplicit& label )
+void LLButton::autoResize()
{
- mDisabledSelectedLabel = label;
+ LLUIString label;
+ if(getToggleState())
+ {
+ label = mSelectedLabel;
+ }
+ else
+ {
+ label = mUnselectedLabel;
+ }
+ resize(label);
}
-void LLButton::setImageUnselected(LLPointer<LLUIImage> image)
+void LLButton::resize(LLUIString label)
{
- mImageUnselected = image;
+ // get label length
+ S32 label_width = mGLFont->getWidth(label.getString());
+ // get current btn length
+ S32 btn_width =getRect().getWidth();
+ // check if it need resize
+ if (mAutoResize == TRUE)
+ {
+ if (btn_width - (mRightHPad + mLeftHPad) < label_width)
+ {
+ setRect(LLRect( getRect().mLeft, getRect().mTop, getRect().mLeft + label_width + mLeftHPad + mRightHPad , getRect().mBottom));
+ }
+ }
}
-
void LLButton::setImages( const std::string &image_name, const std::string &selected_name )
{
- setImageUnselected(image_name);
- setImageSelected(selected_name);
-
+ setImageUnselected(LLUI::getUIImage(image_name));
+ setImageSelected(LLUI::getUIImage(selected_name));
}
void LLButton::setImageSelected(LLPointer<LLUIImage> image)
@@ -840,26 +984,18 @@ void LLButton::setColor(const LLColor4& color)
setImageColor(color);
}
-
void LLButton::setImageDisabled(LLPointer<LLUIImage> image)
{
mImageDisabled = image;
mDisabledImageColor = mImageColor;
- mDisabledImageColor.mV[VALPHA] *= 0.5f;
+ mFadeWhenDisabled = TRUE;
}
void LLButton::setImageDisabledSelected(LLPointer<LLUIImage> image)
{
mImageDisabledSelected = image;
mDisabledImageColor = mImageColor;
- mDisabledImageColor.mV[VALPHA] *= 0.5f;
-}
-
-void LLButton::setDisabledImages( const std::string &image_name, const std::string &selected_name, const LLColor4& c )
-{
- setImageDisabled(image_name);
- setImageDisabledSelected(selected_name);
- mDisabledImageColor = c;
+ mFadeWhenDisabled = TRUE;
}
void LLButton::setImageHoverSelected(LLPointer<LLUIImage> image)
@@ -867,24 +1003,11 @@ void LLButton::setImageHoverSelected(LLPointer<LLUIImage> image)
mImageHoverSelected = image;
}
-void LLButton::setDisabledImages( const std::string &image_name, const std::string &selected_name)
-{
- LLColor4 clr = mImageColor;
- clr.mV[VALPHA] *= .5f;
- setDisabledImages( image_name, selected_name, clr );
-}
-
void LLButton::setImageHoverUnselected(LLPointer<LLUIImage> image)
{
mImageHoverUnselected = image;
}
-void LLButton::setHoverImages( const std::string& image_name, const std::string& selected_name )
-{
- setImageHoverUnselected(image_name);
- setImageHoverSelected(selected_name);
-}
-
void LLButton::setImageOverlay(const std::string& image_name, LLFontGL::HAlign alignment, const LLColor4& color)
{
if (image_name.empty())
@@ -899,11 +1022,23 @@ void LLButton::setImageOverlay(const std::string& image_name, LLFontGL::HAlign a
}
}
+void LLButton::setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignment, const LLColor4& color)
+{
+ if (image_id.isNull())
+ {
+ mImageOverlay = NULL;
+ }
+ else
+ {
+ mImageOverlay = LLUI::getUIImageByID(image_id);
+ mImageOverlayAlignment = alignment;
+ mImageOverlayColor = color;
+ }
+}
void LLButton::onMouseCaptureLost()
{
- mMouseDownTimer.stop();
- mMouseDownTimer.reset();
+ resetMouseDownTimer();
}
//-------------------------------------------------------------------------
@@ -924,42 +1059,6 @@ S32 round_up(S32 grid, S32 value)
}
}
-void LLButton::setImageUnselected(const std::string &image_name)
-{
- setImageUnselected(LLUI::getUIImage(image_name));
- mImageUnselectedName = image_name;
-}
-
-void LLButton::setImageSelected(const std::string &image_name)
-{
- setImageSelected(LLUI::getUIImage(image_name));
- mImageSelectedName = image_name;
-}
-
-void LLButton::setImageHoverSelected(const std::string &image_name)
-{
- setImageHoverSelected(LLUI::getUIImage(image_name));
- mImageHoverSelectedName = image_name;
-}
-
-void LLButton::setImageHoverUnselected(const std::string &image_name)
-{
- setImageHoverUnselected(LLUI::getUIImage(image_name));
- mImageHoverUnselectedName = image_name;
-}
-
-void LLButton::setImageDisabled(const std::string &image_name)
-{
- setImageDisabled(LLUI::getUIImage(image_name));
- mImageDisabledName = image_name;
-}
-
-void LLButton::setImageDisabledSelected(const std::string &image_name)
-{
- setImageDisabledSelected(LLUI::getUIImage(image_name));
- mImageDisabledSelectedName = image_name;
-}
-
void LLButton::addImageAttributeToXML(LLXMLNodePtr node,
const std::string& image_name,
const LLUUID& image_id,
@@ -975,149 +1074,65 @@ void LLButton::addImageAttributeToXML(LLXMLNodePtr node,
}
}
-// virtual
-LLXMLNodePtr LLButton::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLUICtrl::getXML();
-
- node->createChild("label", TRUE)->setStringValue(getLabelUnselected());
- node->createChild("label_selected", TRUE)->setStringValue(getLabelSelected());
- node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mGLFont));
- node->createChild("halign", TRUE)->setStringValue(LLFontGL::nameFromHAlign(mHAlign));
-
- addImageAttributeToXML(node,mImageUnselectedName,mImageUnselectedID,std::string("image_unselected"));
- addImageAttributeToXML(node,mImageSelectedName,mImageSelectedID,std::string("image_selected"));
- addImageAttributeToXML(node,mImageHoverSelectedName,mImageHoverSelectedID,std::string("image_hover_selected"));
- addImageAttributeToXML(node,mImageHoverUnselectedName,mImageHoverUnselectedID,std::string("image_hover_unselected"));
- addImageAttributeToXML(node,mImageDisabledName,mImageDisabledID,std::string("image_disabled"));
- addImageAttributeToXML(node,mImageDisabledSelectedName,mImageDisabledSelectedID,std::string("image_disabled_selected"));
-
- node->createChild("scale_image", TRUE)->setBoolValue(mScaleImage);
- return node;
+// static
+void LLButton::toggleFloaterAndSetToggleState(LLUICtrl* ctrl, const LLSD& sdname)
+{
+ bool floater_vis = LLFloaterReg::toggleInstance(sdname.asString());
+ LLButton* button = dynamic_cast<LLButton*>(ctrl);
+ if (button)
+ button->setToggleState(floater_vis);
}
-void clicked_help(void* data)
+// static
+// Gets called once
+void LLButton::setFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname)
{
- LLButton* self = (LLButton*)data;
- if (!self) return;
-
- if (!LLUI::sHtmlHelp)
- {
+ LLButton* button = dynamic_cast<LLButton*>(ctrl);
+ if (!button)
return;
- }
-
- LLUI::sHtmlHelp->show(self->getHelpURL());
+ // Get the visibility control name for the floater
+ std::string vis_control_name = LLFloaterReg::declareVisibilityControl(sdname.asString());
+ // Set the button control value (toggle state) to the floater visibility control (Sets the value as well)
+ button->setControlVariable(LLUI::sSettingGroups["floater"]->getControl(vis_control_name));
+ // Set the clicked callback to toggle the floater
+ button->setClickedCallback(boost::bind(&LLFloaterReg::toggleFloaterInstance, sdname));
}
// static
-LLView* LLButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
+void LLButton::setDockableFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname)
{
- std::string name("button");
- node->getAttributeString("name", name);
-
- std::string label = name;
- node->getAttributeString("label", label);
-
- std::string label_selected = label;
- node->getAttributeString("label_selected", label_selected);
-
- LLFontGL* font = selectFont(node);
-
- std::string image_unselected;
- if (node->hasAttribute("image_unselected")) node->getAttributeString("image_unselected",image_unselected);
-
- std::string image_selected;
- if (node->hasAttribute("image_selected")) node->getAttributeString("image_selected",image_selected);
-
- std::string image_hover_selected;
- if (node->hasAttribute("image_hover_selected")) node->getAttributeString("image_hover_selected",image_hover_selected);
-
- std::string image_hover_unselected;
- if (node->hasAttribute("image_hover_unselected")) node->getAttributeString("image_hover_unselected",image_hover_unselected);
-
- std::string image_disabled_selected;
- if (node->hasAttribute("image_disabled_selected")) node->getAttributeString("image_disabled_selected",image_disabled_selected);
-
- std::string image_disabled;
- if (node->hasAttribute("image_disabled")) node->getAttributeString("image_disabled",image_disabled);
-
- std::string image_overlay;
- node->getAttributeString("image_overlay", image_overlay);
-
- LLFontGL::HAlign image_overlay_alignment = LLFontGL::HCENTER;
- std::string image_overlay_alignment_string;
- if (node->hasAttribute("image_overlay_alignment"))
- {
- node->getAttributeString("image_overlay_alignment", image_overlay_alignment_string);
- image_overlay_alignment = LLFontGL::hAlignFromName(image_overlay_alignment_string);
- }
-
-
- LLButton *button = new LLButton(name,
- LLRect(),
- image_unselected,
- image_selected,
- LLStringUtil::null,
- NULL,
- parent,
- font,
- label,
- label_selected);
-
- node->getAttributeS32("pad_right", button->mRightHPad);
- node->getAttributeS32("pad_left", button->mLeftHPad);
-
- BOOL is_toggle = button->getIsToggle();
- node->getAttributeBOOL("toggle", is_toggle);
- button->setIsToggle(is_toggle);
-
- if(image_hover_selected != LLStringUtil::null) button->setImageHoverSelected(image_hover_selected);
-
- if(image_hover_unselected != LLStringUtil::null) button->setImageHoverUnselected(image_hover_unselected);
-
- if(image_disabled_selected != LLStringUtil::null) button->setImageDisabledSelected(image_disabled_selected );
-
- if(image_disabled != LLStringUtil::null) button->setImageDisabled(image_disabled);
-
- if(image_overlay != LLStringUtil::null) button->setImageOverlay(image_overlay, image_overlay_alignment);
-
- if (node->hasAttribute("halign"))
- {
- LLFontGL::HAlign halign = selectFontHAlign(node);
- button->setHAlign(halign);
- }
-
- if (node->hasAttribute("scale_image"))
- {
- BOOL needsScale = FALSE;
- node->getAttributeBOOL("scale_image",needsScale);
- button->setScaleImage( needsScale );
- }
+ LLButton* button = dynamic_cast<LLButton*>(ctrl);
+ if (!button)
+ return;
+ // Get the visibility control name for the floater
+ std::string vis_control_name = LLFloaterReg::declareVisibilityControl(sdname.asString());
+ // Set the button control value (toggle state) to the floater visibility control (Sets the value as well)
+ button->setControlVariable(LLUI::sSettingGroups["floater"]->getControl(vis_control_name));
+ // Set the clicked callback to toggle the floater
+ button->setClickedCallback(boost::bind(&LLDockableFloater::toggleInstance, sdname));
+}
- if(label.empty())
- {
- button->setLabelUnselected(node->getTextContents());
- }
- if (label_selected.empty())
- {
- button->setLabelSelected(node->getTextContents());
- }
-
- if (node->hasAttribute("help_url"))
+// static
+void LLButton::showHelp(LLUICtrl* ctrl, const LLSD& sdname)
+{
+ // search back through the button's parents for a panel
+ // with a help_topic string defined
+ std::string help_topic;
+ if (LLUI::sHelpImpl &&
+ ctrl->findHelpTopic(help_topic))
{
- std::string help_url;
- node->getAttributeString("help_url",help_url);
- button->setHelpURLCallback(help_url);
+ LLUI::sHelpImpl->showTopic(help_topic);
+ return; // success
}
- button->initFromXML(node, parent);
-
- return button;
+ // display an error if we can't find a help_topic string.
+ // fix this by adding a help_topic attribute to the xui file
+ LLNotificationsUtil::add("UnableToFindHelpTopic");
}
-void LLButton::setHelpURLCallback(const std::string &help_url)
+void LLButton::resetMouseDownTimer()
{
- mHelpURL = help_url;
- setClickedCallback(clicked_help,this);
+ mMouseDownTimer.stop();
+ mMouseDownTimer.reset();
}
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index 724b77541a..cd149e3113 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -39,7 +39,7 @@
#include "v4color.h"
#include "llframetimer.h"
#include "llfontgl.h"
-#include "llimage.h"
+#include "lluiimage.h"
#include "lluistring.h"
//
@@ -49,13 +49,9 @@
// PLEASE please use these "constants" when building your own buttons.
// They are loaded from settings.xml at run time.
extern S32 LLBUTTON_H_PAD;
-extern S32 LLBUTTON_V_PAD;
extern S32 BTN_HEIGHT_SMALL;
extern S32 BTN_HEIGHT;
-// All button widths should be rounded up to this size
-extern S32 BTN_GRID;
-
//
// Helpful functions
//
@@ -72,57 +68,116 @@ class LLButton
: public LLUICtrl
{
public:
- // simple button with text label
- LLButton(const std::string& name, const LLRect &rect, const std::string& control_name = std::string(),
- void (*on_click)(void*) = NULL, void *data = NULL);
-
- LLButton(const std::string& name, const LLRect& rect,
- const std::string &unselected_image,
- const std::string &selected_image,
- const std::string& control_name,
- void (*click_callback)(void*),
- void *callback_data = NULL,
- const LLFontGL* mGLFont = NULL,
- const std::string& unselected_label = LLStringUtil::null,
- const std::string& selected_label = LLStringUtil::null );
-
- virtual ~LLButton();
- void init(void (*click_callback)(void*), void *callback_data, const LLFontGL* font, const std::string& control_name);
-
+ struct Params
+ : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ // text label
+ Optional<std::string> label_selected;
+ Optional<bool> label_shadow;
+ Optional<bool> auto_resize;
+ Optional<bool> use_ellipses;
+
+ // images
+ Optional<LLUIImage*> image_unselected,
+ image_selected,
+ image_hover_selected,
+ image_hover_unselected,
+ image_disabled_selected,
+ image_disabled,
+ image_pressed,
+ image_pressed_selected,
+ image_overlay;
+
+ Optional<std::string> image_overlay_alignment;
+
+ // colors
+ Optional<LLUIColor> label_color,
+ label_color_selected,
+ label_color_disabled,
+ label_color_disabled_selected,
+ highlight_color,
+ image_color,
+ image_color_disabled,
+ image_overlay_color,
+ flash_color;
+
+ // layout
+ Optional<S32> pad_right;
+ Optional<S32> pad_left;
+ Optional<S32> pad_bottom; // under text label
+
+ // callbacks
+ Optional<CommitCallbackParam> click_callback, // alias -> commit_callback
+ mouse_down_callback,
+ mouse_up_callback,
+ mouse_held_callback;
+
+ // misc
+ Optional<bool> is_toggle,
+ scale_image,
+ commit_on_return;
+
+ Optional<F32> hover_glow_amount;
+ Optional<TimeIntervalParam> held_down_delay;
+
+ Params();
+ };
+protected:
+ friend class LLUICtrlFactory;
+ LLButton(const Params&);
+
+public:
+
+ ~LLButton();
+ // For backward compatability only
+ typedef boost::function<void(void*)> button_callback_t;
+
void addImageAttributeToXML(LLXMLNodePtr node, const std::string& imageName,
const LLUUID& imageID,const std::string& xmlTagName) const;
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
-
virtual BOOL handleUnicodeCharHere(llwchar uni_char);
virtual BOOL handleKeyHere(KEY key, MASK mask);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
+ virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
virtual void draw();
+ /*virtual*/ BOOL postBuild();
+ virtual void onMouseEnter(S32 x, S32 y, MASK mask);
+ virtual void onMouseLeave(S32 x, S32 y, MASK mask);
virtual void onMouseCaptureLost();
virtual void onCommit();
void setUnselectedLabelColor( const LLColor4& c ) { mUnselectedLabelColor = c; }
void setSelectedLabelColor( const LLColor4& c ) { mSelectedLabelColor = c; }
+ void setUseEllipses( BOOL use_ellipses ) { mUseEllipses = use_ellipses; }
- void setClickedCallback( void (*cb)(void *data), void* data = NULL ); // mouse down and up within button
- void setMouseDownCallback( void (*cb)(void *data) ) { mMouseDownCallback = cb; } // mouse down within button
- void setMouseUpCallback( void (*cb)(void *data) ) { mMouseUpCallback = cb; } // mouse up, EVEN IF NOT IN BUTTON
- void setHeldDownCallback( void (*cb)(void *data) ) { mHeldDownCallback = cb; } // Mouse button held down and in button
- void setHeldDownDelay( F32 seconds, S32 frames = 0) { mHeldDownDelay = seconds; mHeldDownFrameDelay = frames; }
+ boost::signals2::connection setClickedCallback( const commit_signal_t::slot_type& cb ); // mouse down and up within button
+ boost::signals2::connection setMouseDownCallback( const commit_signal_t::slot_type& cb );
+ boost::signals2::connection setMouseUpCallback( const commit_signal_t::slot_type& cb ); // mouse up, EVEN IF NOT IN BUTTON
+ // Passes a 'count' parameter in the commit param payload, i.e. param["count"])
+ boost::signals2::connection setHeldDownCallback( const commit_signal_t::slot_type& cb ); // Mouse button held down and in button
+
+
+ // *TODO: Deprecate (for backwards compatability only)
+ boost::signals2::connection setClickedCallback( button_callback_t cb, void* data );
+ boost::signals2::connection setMouseDownCallback( button_callback_t cb, void* data );
+ boost::signals2::connection setMouseUpCallback( button_callback_t cb, void* data );
+ boost::signals2::connection setHeldDownCallback( button_callback_t cb, void* data );
+
+ void setHeldDownDelay( F32 seconds, S32 frames = 0) { mHeldDownDelay = seconds; mHeldDownFrameDelay = frames; }
+
F32 getHeldDownTime() const { return mMouseDownTimer.getElapsedTimeF32(); }
- BOOL getIsToggle() const { return mIsToggle; }
- void setIsToggle(BOOL is_toggle) { mIsToggle = is_toggle; }
BOOL toggleState();
- BOOL getToggleState() const { return mToggleState; }
+ BOOL getToggleState() const;
void setToggleState(BOOL b);
+ void setHighlight(bool b);
void setFlashing( BOOL b );
BOOL getFlashing() const { return mFlashing; }
@@ -136,35 +191,31 @@ public:
void setImageColor(const std::string& color_control);
void setImageColor(const LLColor4& c);
- virtual void setColor(const LLColor4& c);
+ /*virtual*/ void setColor(const LLColor4& c);
void setImages(const std::string &image_name, const std::string &selected_name);
- void setDisabledImages(const std::string &image_name, const std::string &selected_name);
- void setDisabledImages(const std::string &image_name, const std::string &selected_name, const LLColor4& c);
- void setHoverImages(const std::string &image_name, const std::string &selected_name);
-
void setDisabledImageColor(const LLColor4& c) { mDisabledImageColor = c; }
void setDisabledSelectedLabelColor( const LLColor4& c ) { mDisabledSelectedLabelColor = c; }
void setImageOverlay(const std::string& image_name, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white);
+ void setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white);
LLPointer<LLUIImage> getImageOverlay() { return mImageOverlay; }
-
-
- virtual void setValue(const LLSD& value );
- virtual LLSD getValue() const;
+ void autoResize(); // resize with label of current btn state
+ void resize(LLUIString label); // resize with label input
void setLabel( const LLStringExplicit& label);
virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
void setLabelUnselected(const LLStringExplicit& label);
void setLabelSelected(const LLStringExplicit& label);
- void setDisabledLabel(const LLStringExplicit& disabled_label);
- void setDisabledSelectedLabel(const LLStringExplicit& disabled_label);
void setDisabledLabelColor( const LLColor4& c ) { mDisabledLabelColor = c; }
void setFont(const LLFontGL *font)
{ mGLFont = ( font ? font : LLFontGL::getFontSansSerif()); }
+
+ S32 getLastDrawCharsCount() const { return mLastDrawCharsCount; }
+
void setScaleImage(BOOL scale) { mScaleImage = scale; }
BOOL getScaleImage() const { return mScaleImage; }
@@ -172,19 +223,8 @@ public:
void setBorderEnabled(BOOL b) { mBorderEnabled = b; }
- static void onHeldDown(void *userdata); // to be called by gIdleCallbacks
-
void setHoverGlowStrength(F32 strength) { mHoverGlowStrength = strength; }
- void setImageUnselected(const std::string &image_name);
- const std::string& getImageUnselectedName() const { return mImageUnselectedName; }
- void setImageSelected(const std::string &image_name);
- const std::string& getImageSelectedName() const { return mImageSelectedName; }
- void setImageHoverSelected(const std::string &image_name);
- void setImageHoverUnselected(const std::string &image_name);
- void setImageDisabled(const std::string &image_name);
- void setImageDisabledSelected(const std::string &image_name);
-
void setImageUnselected(LLPointer<LLUIImage> image);
void setImageSelected(LLPointer<LLUIImage> image);
void setImageHoverSelected(LLPointer<LLUIImage> image);
@@ -195,109 +235,99 @@ public:
void setCommitOnReturn(BOOL commit) { mCommitOnReturn = commit; }
BOOL getCommitOnReturn() const { return mCommitOnReturn; }
- void setHelpURLCallback(const std::string &help_url);
- const std::string& getHelpURL() const { return mHelpURL; }
+ static void onHeldDown(void *userdata); // to be called by gIdleCallbacks
+ static void toggleFloaterAndSetToggleState(LLUICtrl* ctrl, const LLSD& sdname);
+ static void setFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname);
+ static void setDockableFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname);
+ static void showHelp(LLUICtrl* ctrl, const LLSD& sdname);
+ void setForcePressedState(bool b) { mForcePressedState = b; }
+
protected:
-
- virtual void drawBorder(const LLColor4& color, S32 size);
-
- void setImageUnselectedID(const LLUUID &image_id);
- const LLUUID& getImageUnselectedID() const { return mImageUnselectedID; }
- void setImageSelectedID(const LLUUID &image_id);
- const LLUUID& getImageSelectedID() const { return mImageSelectedID; }
- void setImageHoverSelectedID(const LLUUID &image_id);
- void setImageHoverUnselectedID(const LLUUID &image_id);
- void setImageDisabledID(const LLUUID &image_id);
- void setImageDisabledSelectedID(const LLUUID &image_id);
- const LLPointer<LLUIImage>& getImageUnselected() const { return mImageUnselected; }
- const LLPointer<LLUIImage>& getImageSelected() const { return mImageSelected; }
+ LLPointer<LLUIImage> getImageUnselected() const { return mImageUnselected; }
+ LLPointer<LLUIImage> getImageSelected() const { return mImageSelected; }
LLFrameTimer mMouseDownTimer;
private:
+ void drawBorder(LLUIImage* imagep, const LLColor4& color, S32 size);
+ void resetMouseDownTimer();
- void (*mClickedCallback)(void* data );
- void (*mMouseDownCallback)(void *data);
- void (*mMouseUpCallback)(void *data);
- void (*mHeldDownCallback)(void *data);
-
- const LLFontGL *mGLFont;
+private:
+ commit_signal_t* mMouseDownSignal;
+ commit_signal_t* mMouseUpSignal;
+ commit_signal_t* mHeldDownSignal;
- S32 mMouseDownFrame;
- F32 mHeldDownDelay; // seconds, after which held-down callbacks get called
- S32 mHeldDownFrameDelay; // frames, after which held-down callbacks get called
-
- LLPointer<LLUIImage> mImageOverlay;
- LLFontGL::HAlign mImageOverlayAlignment;
- LLColor4 mImageOverlayColor;
-
- LLPointer<LLUIImage> mImageUnselected;
- LLUIString mUnselectedLabel;
- LLColor4 mUnselectedLabelColor;
-
- LLPointer<LLUIImage> mImageSelected;
- LLUIString mSelectedLabel;
- LLColor4 mSelectedLabelColor;
+ const LLFontGL* mGLFont;
+
+ S32 mMouseDownFrame;
+ S32 mMouseHeldDownCount; // Counter for parameter passed to held-down callback
+ F32 mHeldDownDelay; // seconds, after which held-down callbacks get called
+ S32 mHeldDownFrameDelay; // frames, after which held-down callbacks get called
+ S32 mLastDrawCharsCount;
- LLPointer<LLUIImage> mImageHoverSelected;
+ LLPointer<LLUIImage> mImageOverlay;
+ LLFontGL::HAlign mImageOverlayAlignment;
+ LLUIColor mImageOverlayColor;
- LLPointer<LLUIImage> mImageHoverUnselected;
+ LLPointer<LLUIImage> mImageUnselected;
+ LLUIString mUnselectedLabel;
+ LLUIColor mUnselectedLabelColor;
- LLPointer<LLUIImage> mImageDisabled;
- LLUIString mDisabledLabel;
- LLColor4 mDisabledLabelColor;
+ LLPointer<LLUIImage> mImageSelected;
+ LLUIString mSelectedLabel;
+ LLUIColor mSelectedLabelColor;
- LLPointer<LLUIImage> mImageDisabledSelected;
- LLUIString mDisabledSelectedLabel;
- LLColor4 mDisabledSelectedLabelColor;
+ LLPointer<LLUIImage> mImageHoverSelected;
- LLUUID mImageUnselectedID;
- LLUUID mImageSelectedID;
- LLUUID mImageHoverSelectedID;
- LLUUID mImageHoverUnselectedID;
- LLUUID mImageDisabledID;
- LLUUID mImageDisabledSelectedID;
- std::string mImageUnselectedName;
- std::string mImageSelectedName;
- std::string mImageHoverSelectedName;
- std::string mImageHoverUnselectedName;
- std::string mImageDisabledName;
- std::string mImageDisabledSelectedName;
+ LLPointer<LLUIImage> mImageHoverUnselected;
- LLColor4 mHighlightColor;
- LLColor4 mUnselectedBgColor;
- LLColor4 mSelectedBgColor;
- LLColor4 mFlashBgColor;
+ LLPointer<LLUIImage> mImageDisabled;
+ LLUIColor mDisabledLabelColor;
- LLColor4 mImageColor;
- LLColor4 mDisabledImageColor;
+ LLPointer<LLUIImage> mImageDisabledSelected;
+ LLUIString mDisabledSelectedLabel;
+ LLUIColor mDisabledSelectedLabelColor;
- BOOL mIsToggle;
- BOOL mToggleState;
- BOOL mScaleImage;
+ LLPointer<LLUIImage> mImagePressed;
+ LLPointer<LLUIImage> mImagePressedSelected;
- BOOL mDropShadowedText;
+ LLUIColor mHighlightColor;
+ LLUIColor mFlashBgColor;
- BOOL mBorderEnabled;
+ LLUIColor mImageColor;
+ LLUIColor mDisabledImageColor;
- BOOL mFlashing;
+ BOOL mIsToggle;
+ BOOL mScaleImage;
- LLFontGL::HAlign mHAlign;
- S32 mLeftHPad;
- S32 mRightHPad;
+ BOOL mDropShadowedText;
+ BOOL mAutoResize;
+ BOOL mUseEllipses;
+ BOOL mBorderEnabled;
- F32 mHoverGlowStrength;
- F32 mCurGlowStrength;
+ BOOL mFlashing;
- BOOL mNeedsHighlight;
- BOOL mCommitOnReturn;
+ LLFontGL::HAlign mHAlign;
+ S32 mLeftHPad;
+ S32 mRightHPad;
+ S32 mBottomVPad; // under text label
- std::string mHelpURL;
+ F32 mHoverGlowStrength;
+ F32 mCurGlowStrength;
- LLPointer<LLUIImage> mImagep;
+ BOOL mNeedsHighlight;
+ BOOL mCommitOnReturn;
+ BOOL mFadeWhenDisabled;
+ bool mForcePressedState;
- LLFrameTimer mFlashingTimer;
+ LLFrameTimer mFlashingTimer;
};
+// Build time optimization, generate once in .cpp file
+#ifndef LLBUTTON_CPP
+extern template class LLButton* LLView::getChild<class LLButton>(
+ const std::string& name, BOOL recurse) const;
+#endif
+
#endif // LL_LLBUTTON_H
diff --git a/indra/llui/llcallbackmap.h b/indra/llui/llcallbackmap.h
index eadb9c98f3..97b1e2fc50 100644
--- a/indra/llui/llcallbackmap.h
+++ b/indra/llui/llcallbackmap.h
@@ -30,11 +30,11 @@
* $/LicenseInfo$
*/
-#ifndef LL_CALLBACK_MAP_H
-#define LL_CALLBACK_MAP_H
+#ifndef LLCALLBACKMAP_H
+#define LLCALLBACKMAP_H
#include <map>
-#include "llstring.h"
+#include <string>
class LLCallbackMap
{
@@ -45,12 +45,19 @@ public:
typedef std::map<std::string, LLCallbackMap> map_t;
typedef map_t::iterator map_iter_t;
typedef map_t::const_iterator map_const_iter_t;
-
+
+ template <class T>
+ static void* buildPanel(void* data)
+ {
+ T* panel = new T();
+ return (void*)panel;
+ }
+
LLCallbackMap() : mCallback(NULL), mData(NULL) { }
- LLCallbackMap(callback_t callback, void* data) : mCallback(callback), mData(data) { }
+ LLCallbackMap(callback_t callback, void* data = NULL) : mCallback(callback), mData(data) { }
callback_t mCallback;
void* mData;
};
-#endif // LL_CALLBACK_MAP_H
+#endif // LLCALLBACKMAP_H
diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp
index eda9467d87..3d32157406 100644
--- a/indra/llui/llcheckboxctrl.cpp
+++ b/indra/llui/llcheckboxctrl.cpp
@@ -31,9 +31,9 @@
*/
// The mutants are coming!
-
#include "linden_common.h"
+#define LLCHECKBOXCTRL_CPP
#include "llcheckboxctrl.h"
#include "llgl.h"
@@ -49,101 +49,90 @@
const U32 MAX_STRING_LENGTH = 10;
-static LLRegisterWidget<LLCheckBoxCtrl> r("check_box");
-
-
-LLCheckBoxCtrl::LLCheckBoxCtrl(const std::string& name, const LLRect& rect,
- const std::string& label,
- const LLFontGL* font,
- void (*commit_callback)(LLUICtrl* ctrl, void* userdata),
- void* callback_user_data,
- BOOL initial_value,
- BOOL use_radio_style,
- const std::string& control_which)
-: LLUICtrl(name, rect, TRUE, commit_callback, callback_user_data, FOLLOWS_LEFT | FOLLOWS_TOP),
- mTextEnabledColor( LLUI::sColorsGroup->getColor( "LabelTextColor" ) ),
- mTextDisabledColor( LLUI::sColorsGroup->getColor( "LabelDisabledColor" ) ),
- mRadioStyle( use_radio_style ),
- mInitialValue( initial_value ),
- mSetValue( initial_value )
+static LLDefaultChildRegistry::Register<LLCheckBoxCtrl> r("check_box");
+
+// Compiler optimization, generate extern template
+template class LLCheckBoxCtrl* LLView::getChild<class LLCheckBoxCtrl>(
+ const std::string& name, BOOL recurse) const;
+
+LLCheckBoxCtrl::Params::Params()
+: text_enabled_color("text_enabled_color"),
+ text_disabled_color("text_disabled_color"),
+ initial_value("initial_value", false),
+ label_text("label_text"),
+ check_button("check_button"),
+ radio_style("radio_style")
+{}
+
+
+LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p)
+: LLUICtrl(p),
+ mTextEnabledColor(p.text_enabled_color()),
+ mTextDisabledColor(p.text_disabled_color()),
+ mFont(p.font())
{
- if (font)
- {
- mFont = font;
- }
- else
- {
- mFont = LLFontGL::getFontSansSerifSmall();
- }
+ mViewModel->setValue(LLSD(p.initial_value));
+ mViewModel->resetDirty();
+ static LLUICachedControl<S32> llcheckboxctrl_spacing ("UICheckboxctrlSpacing", 0);
+ static LLUICachedControl<S32> llcheckboxctrl_hpad ("UICheckboxctrlHPad", 0);
+ static LLUICachedControl<S32> llcheckboxctrl_vpad ("UICheckboxctrlVPad", 0);
+ static LLUICachedControl<S32> llcheckboxctrl_btn_size ("UICheckboxctrlBtnSize", 0);
// must be big enough to hold all children
setUseBoundingRect(TRUE);
- mKeyboardFocusOnClick = TRUE;
-
// Label (add a little space to make sure text actually renders)
const S32 FUDGE = 10;
- S32 text_width = mFont->getWidth( label ) + FUDGE;
+ S32 text_width = mFont->getWidth( p.label ) + FUDGE;
S32 text_height = llround(mFont->getLineHeight());
LLRect label_rect;
label_rect.setOriginAndSize(
- LLCHECKBOXCTRL_HPAD + LLCHECKBOXCTRL_BTN_SIZE + LLCHECKBOXCTRL_SPACING,
- LLCHECKBOXCTRL_VPAD + 1, // padding to get better alignment
- text_width + LLCHECKBOXCTRL_HPAD,
+ llcheckboxctrl_hpad + llcheckboxctrl_btn_size + llcheckboxctrl_spacing,
+ llcheckboxctrl_vpad + 1, // padding to get better alignment
+ text_width + llcheckboxctrl_hpad,
text_height );
// *HACK Get rid of this with SL-55508...
// this allows blank check boxes and radio boxes for now
- std::string local_label = label;
+ std::string local_label = p.label;
if(local_label.empty())
{
local_label = " ";
}
- mLabel = new LLTextBox( std::string("CheckboxCtrl Label"), label_rect, local_label, mFont );
- mLabel->setFollowsLeft();
- mLabel->setFollowsBottom();
+ LLTextBox::Params tbparams = p.label_text;
+ tbparams.rect(label_rect);
+ tbparams.initial_value(local_label);
+ if (p.font.isProvided())
+ {
+ tbparams.font(p.font);
+ }
+ tbparams.text_color( p.enabled() ? p.text_enabled_color() : p.text_disabled_color() );
+ mLabel = LLUICtrlFactory::create<LLTextBox> (tbparams);
addChild(mLabel);
// Button
// Note: button cover the label by extending all the way to the right.
LLRect btn_rect;
btn_rect.setOriginAndSize(
- LLCHECKBOXCTRL_HPAD,
- LLCHECKBOXCTRL_VPAD,
- LLCHECKBOXCTRL_BTN_SIZE + LLCHECKBOXCTRL_SPACING + text_width + LLCHECKBOXCTRL_HPAD,
- llmax( text_height, LLCHECKBOXCTRL_BTN_SIZE ) + LLCHECKBOXCTRL_VPAD);
+ llcheckboxctrl_hpad,
+ llcheckboxctrl_vpad,
+ llcheckboxctrl_btn_size + llcheckboxctrl_spacing + text_width + llcheckboxctrl_hpad,
+ llmax( text_height, llcheckboxctrl_btn_size() ) + llcheckboxctrl_vpad);
std::string active_true_id, active_false_id;
std::string inactive_true_id, inactive_false_id;
- if (mRadioStyle)
- {
- active_true_id = "UIImgRadioActiveSelectedUUID";
- active_false_id = "UIImgRadioActiveUUID";
- inactive_true_id = "UIImgRadioInactiveSelectedUUID";
- inactive_false_id = "UIImgRadioInactiveUUID";
- mButton = new LLButton(std::string("Radio control button"), btn_rect,
- active_false_id, active_true_id, control_which,
- &LLCheckBoxCtrl::onButtonPress, this, LLFontGL::getFontSansSerif() );
- mButton->setDisabledImages( inactive_false_id, inactive_true_id );
- mButton->setHoverGlowStrength(0.35f);
- }
- else
- {
- active_false_id = "UIImgCheckboxActiveUUID";
- active_true_id = "UIImgCheckboxActiveSelectedUUID";
- inactive_true_id = "UIImgCheckboxInactiveSelectedUUID";
- inactive_false_id = "UIImgCheckboxInactiveUUID";
- mButton = new LLButton(std::string("Checkbox control button"), btn_rect,
- active_false_id, active_true_id, control_which,
- &LLCheckBoxCtrl::onButtonPress, this, LLFontGL::getFontSansSerif() );
- mButton->setDisabledImages( inactive_false_id, inactive_true_id );
- mButton->setHoverGlowStrength(0.35f);
- }
- mButton->setIsToggle(TRUE);
- mButton->setToggleState( initial_value );
- mButton->setFollowsLeft();
- mButton->setFollowsBottom();
- mButton->setCommitOnReturn(FALSE);
+
+ LLButton::Params params = p.check_button;
+ params.rect(btn_rect);
+ //params.control_name(p.control_name);
+ params.click_callback.function(boost::bind(&LLCheckBoxCtrl::onButtonPress, this, _2));
+ params.commit_on_return(false);
+ // Checkboxes only allow boolean initial values, but buttons can
+ // take any LLSD.
+ params.initial_value(LLSD(p.initial_value));
+ params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
+
+ mButton = LLUICtrlFactory::create<LLButton>(params);
addChild(mButton);
}
@@ -154,24 +143,14 @@ LLCheckBoxCtrl::~LLCheckBoxCtrl()
// static
-void LLCheckBoxCtrl::onButtonPress( void *userdata )
+void LLCheckBoxCtrl::onButtonPress( const LLSD& data )
{
- LLCheckBoxCtrl* self = (LLCheckBoxCtrl*) userdata;
-
- if (self->mRadioStyle)
- {
- self->setValue(TRUE);
- }
-
- self->setControlValue(self->getValue());
- // HACK: because buttons don't normally commit
- self->onCommit();
+ //if (mRadioStyle)
+ //{
+ // setValue(TRUE);
+ //}
- if (self->mKeyboardFocusOnClick)
- {
- self->setFocus( TRUE );
- self->onFocusReceived();
- }
+ onCommit();
}
void LLCheckBoxCtrl::onCommit()
@@ -179,6 +158,7 @@ void LLCheckBoxCtrl::onCommit()
if( getEnabled() )
{
setTentative(FALSE);
+ setControlValue(getValue());
LLUICtrl::onCommit();
}
}
@@ -186,7 +166,15 @@ void LLCheckBoxCtrl::onCommit()
void LLCheckBoxCtrl::setEnabled(BOOL b)
{
LLView::setEnabled(b);
- mButton->setEnabled(b);
+
+ if (b)
+ {
+ mLabel->setColor( mTextEnabledColor.get() );
+ }
+ else
+ {
+ mLabel->setColor( mTextDisabledColor.get() );
+ }
}
void LLCheckBoxCtrl::clear()
@@ -197,43 +185,33 @@ void LLCheckBoxCtrl::clear()
void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
{
//stretch or shrink bounding rectangle of label when rebuilding UI at new scale
+ static LLUICachedControl<S32> llcheckboxctrl_spacing ("UICheckboxctrlSpacing", 0);
+ static LLUICachedControl<S32> llcheckboxctrl_hpad ("UICheckboxctrlHPad", 0);
+ static LLUICachedControl<S32> llcheckboxctrl_vpad ("UICheckboxctrlVPad", 0);
+ static LLUICachedControl<S32> llcheckboxctrl_btn_size ("UICheckboxctrlBtnSize", 0);
+
const S32 FUDGE = 10;
S32 text_width = mFont->getWidth( mLabel->getText() ) + FUDGE;
S32 text_height = llround(mFont->getLineHeight());
LLRect label_rect;
label_rect.setOriginAndSize(
- LLCHECKBOXCTRL_HPAD + LLCHECKBOXCTRL_BTN_SIZE + LLCHECKBOXCTRL_SPACING,
- LLCHECKBOXCTRL_VPAD,
+ llcheckboxctrl_hpad + llcheckboxctrl_btn_size + llcheckboxctrl_spacing,
+ llcheckboxctrl_vpad,
text_width,
text_height );
mLabel->setRect(label_rect);
LLRect btn_rect;
btn_rect.setOriginAndSize(
- LLCHECKBOXCTRL_HPAD,
- LLCHECKBOXCTRL_VPAD,
- LLCHECKBOXCTRL_BTN_SIZE + LLCHECKBOXCTRL_SPACING + text_width,
- llmax( text_height, LLCHECKBOXCTRL_BTN_SIZE ) );
+ llcheckboxctrl_hpad,
+ llcheckboxctrl_vpad,
+ llcheckboxctrl_btn_size + llcheckboxctrl_spacing + text_width,
+ llmax( text_height, llcheckboxctrl_btn_size() ) );
mButton->setRect( btn_rect );
LLUICtrl::reshape(width, height, called_from_parent);
}
-void LLCheckBoxCtrl::draw()
-{
- if (getEnabled())
- {
- mLabel->setColor( mTextEnabledColor );
- }
- else
- {
- mLabel->setColor( mTextDisabledColor );
- }
-
- // Draw children
- LLUICtrl::draw();
-}
-
//virtual
void LLCheckBoxCtrl::setValue(const LLSD& value )
{
@@ -246,6 +224,18 @@ LLSD LLCheckBoxCtrl::getValue() const
return mButton->getValue();
}
+//virtual
+void LLCheckBoxCtrl::setTentative(BOOL b)
+{
+ mButton->setTentative(b);
+}
+
+//virtual
+BOOL LLCheckBoxCtrl::getTentative() const
+{
+ return mButton->getTentative();
+}
+
void LLCheckBoxCtrl::setLabel( const LLStringExplicit& label )
{
mLabel->setText( label );
@@ -264,12 +254,6 @@ BOOL LLCheckBoxCtrl::setLabelArg( const std::string& key, const LLStringExplicit
return res;
}
-//virtual
-std::string LLCheckBoxCtrl::getControlName() const
-{
- return mButton->getControlName();
-}
-
// virtual
void LLCheckBoxCtrl::setControlName(const std::string& control_name, LLView* context)
{
@@ -282,7 +266,7 @@ BOOL LLCheckBoxCtrl::isDirty() const
{
if ( mButton )
{
- return (mSetValue != mButton->getToggleState());
+ return mButton->isDirty();
}
return FALSE; // Shouldn't get here
}
@@ -293,78 +277,6 @@ void LLCheckBoxCtrl::resetDirty()
{
if ( mButton )
{
- mSetValue = mButton->getToggleState();
- }
-}
-
-
-
-// virtual
-LLXMLNodePtr LLCheckBoxCtrl::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLUICtrl::getXML();
-
- node->createChild("label", TRUE)->setStringValue(mLabel->getText());
-
- std::string control_name = mButton->getControlName();
-
- node->createChild("initial_value", TRUE)->setBoolValue(mInitialValue);
-
- node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mFont));
-
- node->createChild("radio_style", TRUE)->setBoolValue(mRadioStyle);
-
- return node;
-}
-
-// static
-LLView* LLCheckBoxCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("checkbox");
- node->getAttributeString("name", name);
-
- std::string label("");
- node->getAttributeString("label", label);
-
- LLFontGL* font = LLView::selectFont(node);
-
- BOOL radio_style = FALSE;
- node->getAttributeBOOL("radio_style", radio_style);
-
- LLUICtrlCallback callback = NULL;
-
- if (label.empty())
- {
- label.assign(node->getTextContents());
+ mButton->resetDirty();
}
-
- LLRect rect;
- createRect(node, rect, parent, LLRect());
-
- LLCheckBoxCtrl* checkbox = new LLCheckboxCtrl(name,
- rect,
- label,
- font,
- callback,
- NULL,
- FALSE,
- radio_style); // if true, draw radio button style icons
-
- BOOL initial_value = checkbox->getValue().asBoolean();
- node->getAttributeBOOL("initial_value", initial_value);
-
- LLColor4 color;
- color = LLUI::sColorsGroup->getColor( "LabelTextColor" );
- LLUICtrlFactory::getAttributeColor(node,"text_enabled_color", color);
- checkbox->setEnabledColor(color);
-
- color = LLUI::sColorsGroup->getColor( "LabelDisabledColor" );
- LLUICtrlFactory::getAttributeColor(node,"text_disabled_color", color);
- checkbox->setDisabledColor(color);
-
- checkbox->setValue(initial_value);
-
- checkbox->initFromXML(node, parent);
-
- return checkbox;
}
diff --git a/indra/llui/llcheckboxctrl.h b/indra/llui/llcheckboxctrl.h
index ff867f5193..28d50f957d 100644
--- a/indra/llui/llcheckboxctrl.h
+++ b/indra/llui/llcheckboxctrl.h
@@ -33,24 +33,14 @@
#ifndef LL_LLCHECKBOXCTRL_H
#define LL_LLCHECKBOXCTRL_H
-
-#include "stdtypes.h"
#include "lluictrl.h"
#include "llbutton.h"
+#include "lltextbox.h"
#include "v4color.h"
-#include "llrect.h"
//
// Constants
//
-const S32 LLCHECKBOXCTRL_BTN_SIZE = 13;
-const S32 LLCHECKBOXCTRL_VPAD = 2;
-const S32 LLCHECKBOXCTRL_HPAD = 2;
-const S32 LLCHECKBOXCTRL_SPACING = 5;
-const S32 LLCHECKBOXCTRL_HEIGHT = 16;
-
-// Deprecated, don't use.
-#define CHECKBOXCTRL_HEIGHT LLCHECKBOXCTRL_HEIGHT
const BOOL RADIO_STYLE = TRUE;
const BOOL CHECK_STYLE = FALSE;
@@ -59,30 +49,38 @@ const BOOL CHECK_STYLE = FALSE;
// Classes
//
class LLFontGL;
-class LLTextBox;
class LLViewBorder;
class LLCheckBoxCtrl
: public LLUICtrl
{
public:
- LLCheckBoxCtrl(const std::string& name, const LLRect& rect, const std::string& label,
- const LLFontGL* font = NULL,
- void (*commit_callback)(LLUICtrl*, void*) = NULL,
- void* callback_userdata = NULL,
- BOOL initial_value = FALSE,
- BOOL use_radio_style = FALSE, // if true, draw radio button style icons
- const std::string& control_which = LLStringUtil::null);
+ struct Params
+ : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<LLUIColor> text_enabled_color;
+ Optional<LLUIColor> text_disabled_color;
+ Optional<bool> initial_value; // override LLUICtrl initial_value
+
+ Optional<LLTextBox::Params> label_text;
+ Optional<LLButton::Params> check_button;
+
+ Ignored radio_style;
+
+ Params();
+ };
+
virtual ~LLCheckBoxCtrl();
- // LLView interface
+protected:
+ LLCheckBoxCtrl(const Params&);
+ friend class LLUICtrlFactory;
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
+public:
+ // LLView interface
virtual void setEnabled( BOOL b );
- virtual void draw();
virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
// LLUICtrl interface
@@ -91,8 +89,8 @@ public:
BOOL get() { return (BOOL)getValue().asBoolean(); }
void set(BOOL value) { setValue(value); }
- virtual void setTentative(BOOL b) { mButton->setTentative(b); }
- virtual BOOL getTentative() const { return mButton->getTentative(); }
+ virtual void setTentative(BOOL b);
+ virtual BOOL getTentative() const;
virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
@@ -108,10 +106,12 @@ public:
void setLabel( const LLStringExplicit& label );
std::string getLabel() const;
+ void setFont( const LLFontGL* font ) { mFont = font; }
+ const LLFontGL* getFont() { return mFont; }
+
virtual void setControlName(const std::string& control_name, LLView* context);
- virtual std::string getControlName() const;
- static void onButtonPress(void *userdata);
+ void onButtonPress(const LLSD& data);
virtual BOOL isDirty() const; // Returns TRUE if the user has modified this control.
virtual void resetDirty(); // Clear dirty state
@@ -121,19 +121,15 @@ protected:
LLButton* mButton;
LLTextBox* mLabel;
const LLFontGL* mFont;
- LLColor4 mTextEnabledColor;
- LLColor4 mTextDisabledColor;
- BOOL mRadioStyle;
- BOOL mInitialValue; // Value set in constructor
- BOOL mSetValue; // Value set programmatically
- BOOL mKeyboardFocusOnClick;
- LLViewBorder* mBorder;
-};
-
-// HACK: fix old capitalization problem
-//typedef LLCheckBoxCtrl LLCheckboxCtrl;
-#define LLCheckboxCtrl LLCheckBoxCtrl
+ LLUIColor mTextEnabledColor;
+ LLUIColor mTextDisabledColor;
+};
+// Build time optimization, generate once in .cpp file
+#ifndef LLCHECKBOXCTRL_CPP
+extern template class LLCheckBoxCtrl* LLView::getChild<class LLCheckBoxCtrl>(
+ const std::string& name, BOOL recurse) const;
+#endif
#endif // LL_LLCHECKBOXCTRL_H
diff --git a/indra/llui/llclipboard.cpp b/indra/llui/llclipboard.cpp
index 2cb8197a67..cbd4cb380f 100644
--- a/indra/llui/llclipboard.cpp
+++ b/indra/llui/llclipboard.cpp
@@ -61,6 +61,12 @@ void LLClipboard::copyFromSubstring(const LLWString &src, S32 pos, S32 len, cons
LLView::getWindow()->copyTextToClipboard( mString );
}
+void LLClipboard::copyFromString(const LLWString &src, const LLUUID& source_id )
+{
+ mSourceID = source_id;
+ mString = src;
+ LLView::getWindow()->copyTextToClipboard( mString );
+}
const LLWString& LLClipboard::getPasteWString( LLUUID* source_id )
{
diff --git a/indra/llui/llclipboard.h b/indra/llui/llclipboard.h
index 034a7a6aeb..d7ffeb33e0 100644
--- a/indra/llui/llclipboard.h
+++ b/indra/llui/llclipboard.h
@@ -50,6 +50,7 @@ public:
(i.e. X11/Linux). */
void copyFromSubstring(const LLWString &copy_from, S32 pos, S32 len, const LLUUID& source_id = LLUUID::null );
+ void copyFromString(const LLWString &copy_from, const LLUUID& source_id = LLUUID::null );
BOOL canPasteString() const;
const LLWString& getPasteWString(LLUUID* source_id = NULL);
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index 28a05c13f5..f29e8785eb 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -48,173 +48,147 @@
#include "llwindow.h"
#include "llfloater.h"
#include "llscrollbar.h"
+#include "llscrolllistcell.h"
+#include "llscrolllistitem.h"
#include "llcontrol.h"
#include "llfocusmgr.h"
#include "lllineeditor.h"
#include "v2math.h"
+#include "lluictrlfactory.h"
+#include "lltooltip.h"
// Globals
S32 LLCOMBOBOX_HEIGHT = 0;
S32 LLCOMBOBOX_WIDTH = 0;
S32 MAX_COMBO_WIDTH = 500;
-static LLRegisterWidget<LLComboBox> r1("combo_box");
+static LLDefaultChildRegistry::Register<LLComboBox> register_combo_box("combo_box");
-LLComboBox::LLComboBox( const std::string& name, const LLRect &rect, const std::string& label,
- void (*commit_callback)(LLUICtrl*,void*),
- void *callback_userdata
- )
-: LLUICtrl(name, rect, TRUE, commit_callback, callback_userdata,
- FOLLOWS_LEFT | FOLLOWS_TOP),
- mTextEntry(NULL),
- mArrowImage(NULL),
- mAllowTextEntry(FALSE),
- mMaxChars(20),
- mTextEntryTentative(TRUE),
- mListPosition(BELOW),
- mPrearrangeCallback( NULL ),
- mTextEntryCallback( NULL ),
- mLabel(label)
+void LLComboBox::PreferredPositionValues::declareValues()
{
- // Always use text box
- // Text label button
- mButton = new LLButton(mLabel,
- LLRect(),
- LLStringUtil::null,
- NULL, this);
- mButton->setImageUnselected(std::string("square_btn_32x128.tga"));
- mButton->setImageSelected(std::string("square_btn_selected_32x128.tga"));
- mButton->setImageDisabled(std::string("square_btn_32x128.tga"));
- mButton->setImageDisabledSelected(std::string("square_btn_selected_32x128.tga"));
- mButton->setScaleImage(TRUE);
-
- mButton->setMouseDownCallback(onButtonDown);
- mButton->setFont(LLFontGL::getFontSansSerifSmall());
- mButton->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM | FOLLOWS_RIGHT);
- mButton->setHAlign( LLFontGL::LEFT );
- mButton->setRightHPad(2);
- addChild(mButton);
-
- // disallow multiple selection
- mList = new LLScrollListCtrl(std::string("ComboBox"), LLRect(),
- &LLComboBox::onItemSelected, this, FALSE);
- mList->setVisible(FALSE);
- mList->setBgWriteableColor( LLColor4(1,1,1,1) );
- mList->setCommitOnKeyboardMovement(FALSE);
- addChild(mList);
-
- mArrowImage = LLUI::sImageProvider->getUIImage("combobox_arrow.tga");
- mButton->setImageOverlay("combobox_arrow.tga", LLFontGL::RIGHT);
+ declare("above", ABOVE);
+ declare("below", BELOW);
+}
- updateLayout();
+LLComboBox::ItemParams::ItemParams()
+: label("label")
+{
}
-LLComboBox::~LLComboBox()
+LLComboBox::Params::Params()
+: allow_text_entry("allow_text_entry", false),
+ allow_new_values("allow_new_values", false),
+ show_text_as_tentative("show_text_as_tentative", true),
+ max_chars("max_chars", 20),
+ list_position("list_position", BELOW),
+ items("item"),
+ combo_button("combo_button"),
+ combo_list("combo_list"),
+ combo_editor("combo_editor"),
+ drop_down_button("drop_down_button")
{
- // children automatically deleted, including mMenu, mButton
+ addSynonym(items, "combo_item");
}
-// virtual
-LLXMLNodePtr LLComboBox::getXML(bool save_children) const
+
+LLComboBox::LLComboBox(const LLComboBox::Params& p)
+: LLUICtrl(p),
+ mTextEntry(NULL),
+ mTextEntryTentative(p.show_text_as_tentative),
+ mHasAutocompletedText(false),
+ mAllowTextEntry(p.allow_text_entry),
+ mAllowNewValues(p.allow_new_values),
+ mMaxChars(p.max_chars),
+ mPrearrangeCallback(p.prearrange_callback()),
+ mTextEntryCallback(p.text_entry_callback()),
+ mListPosition(p.list_position),
+ mLastSelectedIndex(-1)
{
- LLXMLNodePtr node = LLUICtrl::getXML();
+ // Text label button
- // Attributes
+ LLButton::Params button_params = (mAllowTextEntry ? p.combo_button : p.drop_down_button);
+ button_params.mouse_down_callback.function(
+ boost::bind(&LLComboBox::onButtonMouseDown, this));
+ button_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_BOTTOM|FOLLOWS_RIGHT);
+ button_params.rect(p.rect);
- node->createChild("allow_text_entry", TRUE)->setBoolValue(mAllowTextEntry);
+ if(mAllowTextEntry)
+ {
+ button_params.pad_right(2);
+ }
- node->createChild("max_chars", TRUE)->setIntValue(mMaxChars);
+ mArrowImage = button_params.image_unselected;
- // Contents
+ mButton = LLUICtrlFactory::create<LLButton>(button_params);
- std::vector<LLScrollListItem*> data_list = mList->getAllData();
- std::vector<LLScrollListItem*>::iterator data_itor;
- for (data_itor = data_list.begin(); data_itor != data_list.end(); ++data_itor)
+
+ if(mAllowTextEntry)
{
- LLScrollListItem* item = *data_itor;
- LLScrollListCell* cell = item->getColumn(0);
- if (cell)
- {
- LLXMLNodePtr item_node = node->createChild("combo_item", FALSE);
- LLSD value = item->getValue();
- item_node->createChild("value", TRUE)->setStringValue(value.asString());
- item_node->createChild("enabled", TRUE)->setBoolValue(item->getEnabled());
- item_node->setStringValue(cell->getValue().asString());
- }
+ //redo to compensate for button hack that leaves space for a character
+ //unless it is a "minimal combobox"(drop down)
+ mButton->setRightHPad(2);
}
+ addChild(mButton);
- return node;
-}
-
-// static
-LLView* LLComboBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("combo_box");
- node->getAttributeString("name", name);
-
- std::string label("");
- node->getAttributeString("label", label);
+ LLScrollListCtrl::Params params = p.combo_list;
+ params.name("ComboBox");
+ params.commit_callback.function(boost::bind(&LLComboBox::onItemSelected, this, _2));
+ params.visible(false);
+ params.commit_on_keyboard_movement(false);
- LLRect rect;
- createRect(node, rect, parent, LLRect());
+ mList = LLUICtrlFactory::create<LLScrollListCtrl>(params);
+ addChild(mList);
- BOOL allow_text_entry = FALSE;
- node->getAttributeBOOL("allow_text_entry", allow_text_entry);
+ // Mouse-down on button will transfer mouse focus to the list
+ // Grab the mouse-up event and make sure the button state is correct
+ mList->setMouseUpCallback(boost::bind(&LLComboBox::onListMouseUp, this));
- S32 max_chars = 20;
- node->getAttributeS32("max_chars", max_chars);
+ for (LLInitParam::ParamIterator<ItemParams>::const_iterator it = p.items().begin();
+ it != p.items().end();
+ ++it)
+ {
+ LLScrollListItem::Params item_params = *it;
+ if (it->label.isProvided())
+ {
+ item_params.columns.add().value(it->label());
+ }
- LLUICtrlCallback callback = NULL;
+ mList->addRow(item_params);
+ }
- LLComboBox* combo_box = new LLComboBox(name,
- rect,
- label,
- callback,
- NULL);
- combo_box->setAllowTextEntry(allow_text_entry, max_chars);
+ createLineEditor(p);
- combo_box->initFromXML(node, parent);
+ setTopLostCallback(boost::bind(&LLComboBox::hideList, this));
+}
- const std::string& contents = node->getValue();
+void LLComboBox::initFromParams(const LLComboBox::Params& p)
+{
+ LLUICtrl::initFromParams(p);
- if (contents.find_first_not_of(" \n\t") != contents.npos)
- {
- llerrs << "Legacy combo box item format used! Please convert to <combo_item> tags!" << llendl;
- }
- else
+ if (!acceptsTextInput() && mLabel.empty())
{
- LLXMLNodePtr child;
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
- {
- if (child->hasName("combo_item"))
- {
- std::string label = child->getTextContents();
-
- std::string value = label;
- child->getAttributeString("value", value);
-
- combo_box->add(label, LLSD(value) );
- }
- }
+ selectFirstItem();
}
+}
- // if providing user text entry or descriptive label
- // don't select an item under the hood
- if (!combo_box->acceptsTextInput() && combo_box->mLabel.empty())
+// virtual
+BOOL LLComboBox::postBuild()
+{
+ if (mControlVariable)
{
- combo_box->selectFirstItem();
+ setValue(mControlVariable->getValue()); // selects the appropriate item
}
-
- return combo_box;
+ return TRUE;
}
-void LLComboBox::setEnabled(BOOL enabled)
+
+LLComboBox::~LLComboBox()
{
- LLView::setEnabled(enabled);
- mButton->setEnabled(enabled);
+ // children automatically deleted, including mMenu, mButton
}
+
void LLComboBox::clear()
{
if (mTextEntry)
@@ -223,9 +197,8 @@ void LLComboBox::clear()
}
mButton->setLabelSelected(LLStringUtil::null);
mButton->setLabelUnselected(LLStringUtil::null);
- mButton->setDisabledLabel(LLStringUtil::null);
- mButton->setDisabledSelectedLabel(LLStringUtil::null);
mList->deselectAllItems();
+ mLastSelectedIndex = -1;
}
void LLComboBox::onCommit()
@@ -237,6 +210,7 @@ void LLComboBox::onCommit()
mTextEntry->setValue(getSimple());
mTextEntry->setTentative(FALSE);
}
+ setControlValue(getValue());
LLUICtrl::onCommit();
}
@@ -330,6 +304,7 @@ BOOL LLComboBox::setSimple(const LLStringExplicit& name)
if (found)
{
setLabel(name);
+ mLastSelectedIndex = mList->getFirstSelectedIndex();
}
return found;
@@ -346,6 +321,7 @@ void LLComboBox::setValue(const LLSD& value)
{
setLabel( mList->getSelectedItemLabel() );
}
+ mLastSelectedIndex = mList->getFirstSelectedIndex();
}
}
@@ -393,6 +369,7 @@ void LLComboBox::setLabel(const LLStringExplicit& name)
if (mList->selectItemByLabel(name, FALSE))
{
mTextEntry->setTentative(FALSE);
+ mLastSelectedIndex = mList->getFirstSelectedIndex();
}
else
{
@@ -402,10 +379,7 @@ void LLComboBox::setLabel(const LLStringExplicit& name)
if (!mAllowTextEntry)
{
- mButton->setLabelUnselected(name);
- mButton->setLabelSelected(name);
- mButton->setDisabledLabel(name);
- mButton->setDisabledSelectedLabel(name);
+ mButton->setLabel(name);
}
}
@@ -421,6 +395,7 @@ BOOL LLComboBox::remove(const std::string& name)
{
mList->deleteSingleItem(mList->getItemIndex(item));
}
+ mLastSelectedIndex = mList->getFirstSelectedIndex();
}
return found;
@@ -431,6 +406,7 @@ BOOL LLComboBox::remove(S32 index)
if (index < mList->getItemCount())
{
mList->deleteSingleItem(index);
+ setLabel(mList->getSelectedItemLabel());
return TRUE;
}
return FALSE;
@@ -448,41 +424,31 @@ void LLComboBox::onFocusLost()
LLUICtrl::onFocusLost();
}
-void LLComboBox::onLostTop()
-{
- hideList();
-}
-
-
void LLComboBox::setButtonVisible(BOOL visible)
{
+ static LLUICachedControl<S32> drop_shadow_button ("DropShadowButton", 0);
+
mButton->setVisible(visible);
if (mTextEntry)
{
LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
if (visible)
{
- text_entry_rect.mRight -= llmax(8,mArrowImage->getWidth()) + 2 * LLUI::sConfigGroup->getS32("DropShadowButton");
+ S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0;
+ text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button;
}
//mTextEntry->setRect(text_entry_rect);
mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE);
}
}
-void LLComboBox::draw()
-{
- mButton->setEnabled(getEnabled() /*&& !mList->isEmpty()*/);
-
- // Draw children normally
- LLUICtrl::draw();
-}
-
BOOL LLComboBox::setCurrentByIndex( S32 index )
{
BOOL found = mList->selectNthItem( index );
if (found)
{
setLabel(mList->getSelectedItemLabel());
+ mLastSelectedIndex = index;
}
return found;
}
@@ -498,54 +464,47 @@ S32 LLComboBox::getCurrentIndex() const
}
-void LLComboBox::updateLayout()
+void LLComboBox::createLineEditor(const LLComboBox::Params& p)
{
+ static LLUICachedControl<S32> drop_shadow_button ("DropShadowButton", 0);
LLRect rect = getLocalRect();
if (mAllowTextEntry)
{
- S32 shadow_size = LLUI::sConfigGroup->getS32("DropShadowButton");
- mButton->setRect(LLRect( getRect().getWidth() - llmax(8,mArrowImage->getWidth()) - 2 * shadow_size,
+ S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0;
+ S32 shadow_size = drop_shadow_button;
+ mButton->setRect(LLRect( getRect().getWidth() - llmax(8,arrow_width) - 2 * shadow_size,
rect.mTop, rect.mRight, rect.mBottom));
mButton->setTabStop(FALSE);
+ mButton->setHAlign(LLFontGL::HCENTER);
- if (!mTextEntry)
- {
- LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
- text_entry_rect.mRight -= llmax(8,mArrowImage->getWidth()) + 2 * LLUI::sConfigGroup->getS32("DropShadowButton");
- // clear label on button
- std::string cur_label = mButton->getLabelSelected();
- mTextEntry = new LLLineEditor(std::string("combo_text_entry"),
- text_entry_rect,
- LLStringUtil::null,
- LLFontGL::getFontSansSerifSmall(),
- mMaxChars,
- onTextCommit,
- onTextEntry,
- NULL,
- this);
- mTextEntry->setSelectAllonFocusReceived(TRUE);
- mTextEntry->setHandleEditKeysDirectly(TRUE);
- mTextEntry->setCommitOnFocusLost(FALSE);
- mTextEntry->setText(cur_label);
- mTextEntry->setIgnoreTab(TRUE);
- mTextEntry->setFollowsAll();
- addChild(mTextEntry);
- }
- else
- {
- mTextEntry->setVisible(TRUE);
- mTextEntry->setMaxTextLength(mMaxChars);
- }
+ LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
+ text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button;
+ // clear label on button
+ std::string cur_label = mButton->getLabelSelected();
+ LLLineEditor::Params params = p.combo_editor;
+ params.rect(text_entry_rect);
+ params.default_text(LLStringUtil::null);
+ params.max_length_bytes(mMaxChars);
+ params.commit_callback.function(boost::bind(&LLComboBox::onTextCommit, this, _2));
+ params.keystroke_callback(boost::bind(&LLComboBox::onTextEntry, this, _1));
+ params.handle_edit_keys_directly(true);
+ params.commit_on_focus_lost(false);
+ params.follows.flags(FOLLOWS_ALL);
+ mTextEntry = LLUICtrlFactory::create<LLLineEditor> (params);
+ mTextEntry->setText(cur_label);
+ mTextEntry->setIgnoreTab(TRUE);
+ addChild(mTextEntry);
// clear label on button
setLabel(LLStringUtil::null);
mButton->setFollows(FOLLOWS_BOTTOM | FOLLOWS_TOP | FOLLOWS_RIGHT);
}
- else if (!mAllowTextEntry)
+ else
{
mButton->setRect(rect);
mButton->setTabStop(TRUE);
+ mButton->setHAlign(LLFontGL::LEFT);
if (mTextEntry)
{
@@ -664,126 +623,125 @@ void LLComboBox::showList()
void LLComboBox::hideList()
{
- //*HACK: store the original value explicitly somewhere, not just in label
- std::string orig_selection = mAllowTextEntry ? mTextEntry->getText() : mButton->getLabelSelected();
-
- // assert selection in list
- mList->selectItemByLabel(orig_selection, FALSE);
+ if (mList->getVisible())
+ {
+ // assert selection in list
+ if(mAllowNewValues)
+ {
+ // mLastSelectedIndex = -1 means that we entered a new value, don't select
+ // any of existing items in this case.
+ if(mLastSelectedIndex >= 0)
+ mList->selectNthItem(mLastSelectedIndex);
+ }
+ else
+ mList->selectNthItem(mLastSelectedIndex);
- mButton->setToggleState(FALSE);
- mList->setVisible(FALSE);
- mList->highlightNthItem(-1);
+ mButton->setToggleState(FALSE);
+ mList->setVisible(FALSE);
+ mList->mouseOverHighlightNthItem(-1);
- setUseBoundingRect(FALSE);
- if( gFocusMgr.getTopCtrl() == this )
- {
- gFocusMgr.setTopCtrl(NULL);
+ setUseBoundingRect(FALSE);
+ if( gFocusMgr.getTopCtrl() == this )
+ {
+ gFocusMgr.setTopCtrl(NULL);
+ }
}
}
-//------------------------------------------------------------------
-// static functions
-//------------------------------------------------------------------
-
-// static
-void LLComboBox::onButtonDown(void *userdata)
+void LLComboBox::onButtonMouseDown()
{
- LLComboBox *self = (LLComboBox *)userdata;
-
- if (!self->mList->getVisible())
+ if (!mList->getVisible())
{
- LLScrollListItem* last_selected_item = self->mList->getLastSelectedItem();
- if (last_selected_item)
- {
- // highlight the original selection before potentially selecting a new item
- self->mList->highlightNthItem(self->mList->getItemIndex(last_selected_item));
- }
+ // this might change selection, so do it first
+ prearrangeList();
- if( self->mPrearrangeCallback )
+ // highlight the last selected item from the original selection before potentially selecting a new item
+ // as visual cue to original value of combo box
+ LLScrollListItem* last_selected_item = mList->getLastSelectedItem();
+ if (last_selected_item)
{
- self->mPrearrangeCallback( self, self->mCallbackUserData );
+ mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item));
}
- if (self->mList->getItemCount() != 0)
+ if (mList->getItemCount() != 0)
{
- self->showList();
+ showList();
}
- self->setFocus( TRUE );
+ setFocus( TRUE );
// pass mouse capture on to list if button is depressed
- if (self->mButton->hasMouseCapture())
+ if (mButton->hasMouseCapture())
{
- gFocusMgr.setMouseCapture(self->mList);
+ gFocusMgr.setMouseCapture(mList);
+
+ // But keep the "pressed" look, which buttons normally lose when they
+ // lose focus
+ mButton->setForcePressedState(true);
}
}
else
{
- self->hideList();
+ hideList();
}
}
-// static
-void LLComboBox::onItemSelected(LLUICtrl* item, void *userdata)
+void LLComboBox::onListMouseUp()
{
- // Note: item is the LLScrollListCtrl
- LLComboBox *self = (LLComboBox *) userdata;
+ // In some cases this is the termination of a mouse click that started on
+ // the button, so clear its pressed state
+ mButton->setForcePressedState(false);
+}
- const std::string name = self->mList->getSelectedItemLabel();
+//------------------------------------------------------------------
+// static functions
+//------------------------------------------------------------------
- S32 cur_id = self->getCurrentIndex();
+void LLComboBox::onItemSelected(const LLSD& data)
+{
+ const std::string name = mList->getSelectedItemLabel();
+
+ S32 cur_id = getCurrentIndex();
+ mLastSelectedIndex = cur_id;
if (cur_id != -1)
{
- self->setLabel(name);
+ setLabel(name);
- if (self->mAllowTextEntry)
+ if (mAllowTextEntry)
{
- gFocusMgr.setKeyboardFocus(self->mTextEntry);
- self->mTextEntry->selectAll();
+ gFocusMgr.setKeyboardFocus(mTextEntry);
+ mTextEntry->selectAll();
}
}
// hiding the list reasserts the old value stored in the text editor/dropdown button
- self->hideList();
+ hideList();
// commit does the reverse, asserting the value in the list
- self->onCommit();
+ onCommit();
}
-BOOL LLComboBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
+BOOL LLComboBox::handleToolTip(S32 x, S32 y, MASK mask)
{
std::string tool_tip;
- if(LLUICtrl::handleToolTip(x, y, msg, sticky_rect_screen))
+ if(LLUICtrl::handleToolTip(x, y, mask))
{
return TRUE;
}
- if (LLUI::sShowXUINames)
- {
- tool_tip = getShowNamesToolTip();
- }
- else
+ tool_tip = getToolTip();
+ if (tool_tip.empty())
{
- tool_tip = getToolTip();
- if (tool_tip.empty())
- {
- tool_tip = getSelectedItemLabel();
- }
+ tool_tip = getSelectedItemLabel();
}
if( !tool_tip.empty() )
{
- msg = tool_tip;
-
- // Convert rect local to screen coordinates
- localPointToScreen(
- 0, 0,
- &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
- localPointToScreen(
- getRect().getWidth(), getRect().getHeight(),
- &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) );
+ LLToolTipMgr::instance().show(LLToolTip::Params()
+ .message(tool_tip)
+ .sticky_rect(calcScreenRect()));
}
return TRUE;
}
@@ -804,7 +762,7 @@ BOOL LLComboBox::handleKeyHere(KEY key, MASK mask)
if (last_selected_item)
{
// highlight the original selection before potentially selecting a new item
- mList->highlightNthItem(mList->getItemIndex(last_selected_item));
+ mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item));
}
result = mList->handleKeyHere(key, mask);
@@ -838,7 +796,7 @@ BOOL LLComboBox::handleUnicodeCharHere(llwchar uni_char)
if (last_selected_item)
{
// highlight the original selection before potentially selecting a new item
- mList->highlightNthItem(mList->getItemIndex(last_selected_item));
+ mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item));
}
result = mList->handleUnicodeCharHere(uni_char);
if (mList->getLastSelectedItem() != last_selected_item)
@@ -850,46 +808,37 @@ BOOL LLComboBox::handleUnicodeCharHere(llwchar uni_char)
return result;
}
-void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative)
-{
- mAllowTextEntry = allow;
- mTextEntryTentative = set_tentative;
- mMaxChars = max_chars;
-
- updateLayout();
-}
-
void LLComboBox::setTextEntry(const LLStringExplicit& text)
{
if (mTextEntry)
{
mTextEntry->setText(text);
+ mHasAutocompletedText = FALSE;
updateSelection();
}
}
-//static
-void LLComboBox::onTextEntry(LLLineEditor* line_editor, void* user_data)
+void LLComboBox::onTextEntry(LLLineEditor* line_editor)
{
- LLComboBox* self = (LLComboBox*)user_data;
-
- if (self->mTextEntryCallback)
+ if (mTextEntryCallback != NULL)
{
- (*self->mTextEntryCallback)(line_editor, self->mCallbackUserData);
+ (mTextEntryCallback)(line_editor, LLSD());
}
KEY key = gKeyboard->currentKey();
if (key == KEY_BACKSPACE ||
key == KEY_DELETE)
{
- if (self->mList->selectItemByLabel(line_editor->getText(), FALSE))
+ if (mList->selectItemByLabel(line_editor->getText(), FALSE))
{
line_editor->setTentative(FALSE);
+ mLastSelectedIndex = mList->getFirstSelectedIndex();
}
else
{
- line_editor->setTentative(self->mTextEntryTentative);
- self->mList->deselectAllItems();
+ line_editor->setTentative(mTextEntryTentative);
+ mList->deselectAllItems();
+ mLastSelectedIndex = -1;
}
return;
}
@@ -902,17 +851,14 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor, void* user_data)
if (key == KEY_DOWN)
{
- self->setCurrentByIndex(llmin(self->getItemCount() - 1, self->getCurrentIndex() + 1));
- if (!self->mList->getVisible())
+ setCurrentByIndex(llmin(getItemCount() - 1, getCurrentIndex() + 1));
+ if (!mList->getVisible())
{
- if( self->mPrearrangeCallback )
- {
- self->mPrearrangeCallback( self, self->mCallbackUserData );
- }
+ prearrangeList();
- if (self->mList->getItemCount() != 0)
+ if (mList->getItemCount() != 0)
{
- self->showList();
+ showList();
}
}
line_editor->selectAll();
@@ -920,17 +866,14 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor, void* user_data)
}
else if (key == KEY_UP)
{
- self->setCurrentByIndex(llmax(0, self->getCurrentIndex() - 1));
- if (!self->mList->getVisible())
+ setCurrentByIndex(llmax(0, getCurrentIndex() - 1));
+ if (!mList->getVisible())
{
- if( self->mPrearrangeCallback )
- {
- self->mPrearrangeCallback( self, self->mCallbackUserData );
- }
+ prearrangeList();
- if (self->mList->getItemCount() != 0)
+ if (mList->getItemCount() != 0)
{
- self->showList();
+ showList();
}
}
line_editor->selectAll();
@@ -939,7 +882,7 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor, void* user_data)
else
{
// RN: presumably text entry
- self->updateSelection();
+ updateSelection();
}
}
@@ -948,7 +891,7 @@ void LLComboBox::updateSelection()
LLWString left_wstring = mTextEntry->getWText().substr(0, mTextEntry->getCursor());
// user-entered portion of string, based on assumption that any selected
// text was a result of auto-completion
- LLWString user_wstring = mTextEntry->hasSelection() ? left_wstring : mTextEntry->getWText();
+ LLWString user_wstring = mHasAutocompletedText ? left_wstring : mTextEntry->getWText();
std::string full_string = mTextEntry->getText();
// go ahead and arrange drop down list on first typed character, even
@@ -956,23 +899,15 @@ void LLComboBox::updateSelection()
// callback to populate content
if( mTextEntry->getWText().size() == 1 )
{
- if (mPrearrangeCallback)
- {
- mPrearrangeCallback( this, mCallbackUserData );
- }
+ prearrangeList(mTextEntry->getText());
}
if (mList->selectItemByLabel(full_string, FALSE))
{
mTextEntry->setTentative(FALSE);
+ mLastSelectedIndex = mList->getFirstSelectedIndex();
}
- else if (!mList->selectItemByPrefix(left_wstring, FALSE))
- {
- mList->deselectAllItems();
- mTextEntry->setText(wstring_to_utf8str(user_wstring));
- mTextEntry->setTentative(mTextEntryTentative);
- }
- else
+ else if (mList->selectItemByPrefix(left_wstring, FALSE))
{
LLWString selected_item = utf8str_to_wstring(mList->getSelectedItemLabel());
LLWString wtext = left_wstring + selected_item.substr(left_wstring.size(), selected_item.size());
@@ -980,17 +915,25 @@ void LLComboBox::updateSelection()
mTextEntry->setSelection(left_wstring.size(), mTextEntry->getWText().size());
mTextEntry->endSelection();
mTextEntry->setTentative(FALSE);
+ mHasAutocompletedText = TRUE;
+ mLastSelectedIndex = mList->getFirstSelectedIndex();
+ }
+ else // no matching items found
+ {
+ mList->deselectAllItems();
+ mTextEntry->setText(wstring_to_utf8str(user_wstring)); // removes text added by autocompletion
+ mTextEntry->setTentative(mTextEntryTentative);
+ mHasAutocompletedText = FALSE;
+ mLastSelectedIndex = -1;
}
}
-//static
-void LLComboBox::onTextCommit(LLUICtrl* caller, void* user_data)
+void LLComboBox::onTextCommit(const LLSD& data)
{
- LLComboBox* self = (LLComboBox*)user_data;
- std::string text = self->mTextEntry->getText();
- self->setSimple(text);
- self->onCommit();
- self->mTextEntry->selectAll();
+ std::string text = mTextEntry->getText();
+ setSimple(text);
+ onCommit();
+ mTextEntry->selectAll();
}
void LLComboBox::setFocus(BOOL b)
@@ -1007,6 +950,14 @@ void LLComboBox::setFocus(BOOL b)
}
}
+void LLComboBox::prearrangeList(std::string filter)
+{
+ if (mPrearrangeCallback)
+ {
+ mPrearrangeCallback(this, LLSD(filter));
+ }
+}
+
//============================================================================
// LLCtrlListInterface functions
@@ -1061,6 +1012,7 @@ BOOL LLComboBox::setCurrentByID(const LLUUID& id)
if (found)
{
setLabel(mList->getSelectedItemLabel());
+ mLastSelectedIndex = mList->getFirstSelectedIndex();
}
return found;
@@ -1114,155 +1066,3 @@ BOOL LLComboBox::selectItemRange( S32 first, S32 last )
{
return mList->selectItemRange(first, last);
}
-
-
-//
-// LLFlyoutButton
-//
-
-static LLRegisterWidget<LLFlyoutButton> r2("flyout_button");
-
-const S32 FLYOUT_BUTTON_ARROW_WIDTH = 24;
-
-LLFlyoutButton::LLFlyoutButton(
- const std::string& name,
- const LLRect &rect,
- const std::string& label,
- void (*commit_callback)(LLUICtrl*, void*) ,
- void *callback_userdata)
-: LLComboBox(name, rect, LLStringUtil::null, commit_callback, callback_userdata),
- mToggleState(FALSE),
- mActionButton(NULL)
-{
- // Always use text box
- // Text label button
- mActionButton = new LLButton(label,
- LLRect(), LLStringUtil::null, NULL, this);
- mActionButton->setScaleImage(TRUE);
-
- mActionButton->setClickedCallback(onActionButtonClick);
- mActionButton->setFollowsAll();
- mActionButton->setHAlign( LLFontGL::HCENTER );
- mActionButton->setLabel(label);
- addChild(mActionButton);
-
- mActionButtonImage = LLUI::getUIImage("flyout_btn_left.tga");
- mExpanderButtonImage = LLUI::getUIImage("flyout_btn_right.tga");
- mActionButtonImageSelected = LLUI::getUIImage("flyout_btn_left_selected.tga");
- mExpanderButtonImageSelected = LLUI::getUIImage("flyout_btn_right_selected.tga");
- mActionButtonImageDisabled = LLUI::getUIImage("flyout_btn_left_disabled.tga");
- mExpanderButtonImageDisabled = LLUI::getUIImage("flyout_btn_right_disabled.tga");
-
- mActionButton->setImageSelected(mActionButtonImageSelected);
- mActionButton->setImageUnselected(mActionButtonImage);
- mActionButton->setImageDisabled(mActionButtonImageDisabled);
- mActionButton->setImageDisabledSelected(LLPointer<LLUIImage>(NULL));
-
- mButton->setImageSelected(mExpanderButtonImageSelected);
- mButton->setImageUnselected(mExpanderButtonImage);
- mButton->setImageDisabled(mExpanderButtonImageDisabled);
- mButton->setImageDisabledSelected(LLPointer<LLUIImage>(NULL));
- mButton->setRightHPad(6);
-
- updateLayout();
-}
-
-//static
-LLView* LLFlyoutButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name = "flyout_button";
- node->getAttributeString("name", name);
-
- std::string label("");
- node->getAttributeString("label", label);
-
- LLRect rect;
- createRect(node, rect, parent, LLRect());
-
- LLUICtrlCallback callback = NULL;
-
- LLFlyoutButton* flyout_button = new LLFlyoutButton(name,
- rect,
- label,
- callback,
- NULL);
-
- std::string list_position;
- node->getAttributeString("list_position", list_position);
- if (list_position == "below")
- {
- flyout_button->mListPosition = BELOW;
- }
- else if (list_position == "above")
- {
- flyout_button->mListPosition = ABOVE;
- }
-
-
- flyout_button->initFromXML(node, parent);
-
- LLXMLNodePtr child;
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
- {
- if (child->hasName("flyout_button_item"))
- {
- std::string label = child->getTextContents();
-
- std::string value = label;
- child->getAttributeString("value", value);
-
- flyout_button->add(label, LLSD(value) );
- }
- }
-
- flyout_button->updateLayout();
-
- return flyout_button;
-}
-
-void LLFlyoutButton::updateLayout()
-{
- LLComboBox::updateLayout();
-
- mButton->setOrigin(getRect().getWidth() - FLYOUT_BUTTON_ARROW_WIDTH, 0);
- mButton->reshape(FLYOUT_BUTTON_ARROW_WIDTH, getRect().getHeight());
- mButton->setFollows(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
- mButton->setTabStop(FALSE);
- mButton->setImageOverlay(mListPosition == BELOW ? "down_arrow.tga" : "up_arrow.tga", LLFontGL::RIGHT);
-
- mActionButton->setOrigin(0, 0);
- mActionButton->reshape(getRect().getWidth() - FLYOUT_BUTTON_ARROW_WIDTH, getRect().getHeight());
-}
-
-//static
-void LLFlyoutButton::onActionButtonClick(void *user_data)
-{
- LLFlyoutButton* buttonp = (LLFlyoutButton*)user_data;
- // remember last list selection?
- buttonp->mList->deselect();
- buttonp->onCommit();
-}
-
-void LLFlyoutButton::draw()
-{
- mActionButton->setToggleState(mToggleState);
- mButton->setToggleState(mToggleState);
-
- //FIXME: this should be an attribute of comboboxes, whether they have a distinct label or
- // the label reflects the last selected item, for now we have to manually remove the label
- mButton->setLabel(LLStringUtil::null);
- LLComboBox::draw();
-}
-
-void LLFlyoutButton::setEnabled(BOOL enabled)
-{
- mActionButton->setEnabled(enabled);
- LLComboBox::setEnabled(enabled);
-}
-
-
-void LLFlyoutButton::setToggleState(BOOL state)
-{
- mToggleState = state;
-}
-
diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h
index 33e1baa748..4f27588467 100644
--- a/indra/llui/llcombobox.h
+++ b/indra/llui/llcombobox.h
@@ -39,16 +39,14 @@
#include "llbutton.h"
#include "lluictrl.h"
#include "llctrlselectioninterface.h"
-#include "llimagegl.h"
#include "llrect.h"
+#include "llscrolllistctrl.h"
+#include "lllineeditor.h"
+#include <boost/function.hpp>
// Classes
class LLFontGL;
-class LLButton;
-class LLSquareButton;
-class LLScrollListCtrl;
-class LLLineEditor;
class LLViewBorder;
extern S32 LLCOMBOBOX_HEIGHT;
@@ -57,34 +55,64 @@ extern S32 LLCOMBOBOX_WIDTH;
class LLComboBox
: public LLUICtrl, public LLCtrlListInterface
{
-public:
+public:
typedef enum e_preferred_position
{
ABOVE,
BELOW
} EPreferredPosition;
- LLComboBox(
- const std::string& name,
- const LLRect &rect,
- const std::string& label,
- void (*commit_callback)(LLUICtrl*, void*) = NULL,
- void *callback_userdata = NULL
- );
- virtual ~LLComboBox();
+ struct PreferredPositionValues : public LLInitParam::TypeValuesHelper<EPreferredPosition, PreferredPositionValues>
+ {
+ static void declareValues();
+ };
- // LLView interface
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
+ struct ItemParams : public LLInitParam::Block<ItemParams, LLScrollListItem::Params>
+ {
+ Optional<std::string> label;
+ ItemParams();
+ };
- virtual void draw();
- virtual void onFocusLost();
- virtual void onLostTop();
+ struct Params
+ : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<bool> allow_text_entry,
+ show_text_as_tentative,
+ allow_new_values;
+ Optional<S32> max_chars;
+ Optional<commit_callback_t> prearrange_callback,
+ text_entry_callback;
+
+ Optional<EPreferredPosition, PreferredPositionValues> list_position;
+
+ // components
+ Optional<LLButton::Params> combo_button;
+ Optional<LLScrollListCtrl::Params> combo_list;
+ Optional<LLLineEditor::Params> combo_editor;
+
+ Optional<LLButton::Params> drop_down_button;
- virtual void setEnabled(BOOL enabled);
+ Multiple<ItemParams> items;
+
+ Params();
+ };
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect);
+
+ virtual ~LLComboBox();
+ /*virtual*/ BOOL postBuild();
+
+protected:
+ friend class LLUICtrlFactory;
+ LLComboBox(const Params&);
+ void initFromParams(const Params&);
+ void prearrangeList(std::string filter = "");
+
+public:
+ // LLView interface
+ virtual void onFocusLost();
+
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
virtual BOOL handleKeyHere(KEY key, MASK mask);
virtual BOOL handleUnicodeCharHere(llwchar uni_char);
@@ -105,7 +133,6 @@ public:
// items, this is just the label.
virtual LLSD getValue() const;
- void setAllowTextEntry(BOOL allow, S32 max_chars = 50, BOOL make_tentative = TRUE);
void setTextEntry(const LLStringExplicit& text);
LLScrollListItem* add(const std::string& name, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE); // add item "name" to menu
@@ -134,7 +161,7 @@ public:
BOOL setCurrentByIndex( S32 index );
S32 getCurrentIndex() const;
- virtual void updateLayout();
+ void createLineEditor(const Params&);
//========================================================================
LLCtrlSelectionInterface* getSelectionInterface() { return (LLCtrlSelectionInterface*)this; };
@@ -170,66 +197,39 @@ public:
void* getCurrentUserdata();
- void setPrearrangeCallback( void (*cb)(LLUICtrl*,void*) ) { mPrearrangeCallback = cb; }
- void setTextEntryCallback( void (*cb)(LLLineEditor*, void*) ) { mTextEntryCallback = cb; }
+ void setPrearrangeCallback( commit_callback_t cb ) { mPrearrangeCallback = cb; }
+ void setTextEntryCallback( commit_callback_t cb ) { mTextEntryCallback = cb; }
void setButtonVisible(BOOL visible);
- static void onButtonDown(void *userdata);
- static void onItemSelected(LLUICtrl* item, void *userdata);
- static void onTextEntry(LLLineEditor* line_editor, void* user_data);
- static void onTextCommit(LLUICtrl* caller, void* user_data);
+ void onButtonMouseDown();
+ void onListMouseUp();
+ void onItemSelected(const LLSD& data);
+ void onTextCommit(const LLSD& data);
void updateSelection();
virtual void showList();
virtual void hideList();
-
+
+ virtual void onTextEntry(LLLineEditor* line_editor);
+
protected:
LLButton* mButton;
+ LLLineEditor* mTextEntry;
LLScrollListCtrl* mList;
EPreferredPosition mListPosition;
LLPointer<LLUIImage> mArrowImage;
- std::string mLabel;
+ LLUIString mLabel;
+ BOOL mHasAutocompletedText;
private:
- S32 mButtonPadding;
- LLLineEditor* mTextEntry;
BOOL mAllowTextEntry;
+ BOOL mAllowNewValues;
S32 mMaxChars;
BOOL mTextEntryTentative;
- void (*mPrearrangeCallback)(LLUICtrl*,void*);
- void (*mTextEntryCallback)(LLLineEditor*, void*);
-};
-
-class LLFlyoutButton : public LLComboBox
-{
-public:
- LLFlyoutButton(
- const std::string& name,
- const LLRect &rect,
- const std::string& label,
- void (*commit_callback)(LLUICtrl*, void*) = NULL,
- void *callback_userdata = NULL);
-
- virtual void updateLayout();
- virtual void draw();
- virtual void setEnabled(BOOL enabled);
-
- void setToggleState(BOOL state);
-
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
- static void onActionButtonClick(void *userdata);
- static void onSelectAction(LLUICtrl* ctrl, void *userdata);
-
-protected:
- LLButton* mActionButton;
- LLPointer<LLUIImage> mActionButtonImage;
- LLPointer<LLUIImage> mExpanderButtonImage;
- LLPointer<LLUIImage> mActionButtonImageSelected;
- LLPointer<LLUIImage> mExpanderButtonImageSelected;
- LLPointer<LLUIImage> mActionButtonImageDisabled;
- LLPointer<LLUIImage> mExpanderButtonImageDisabled;
- BOOL mToggleState;
+ commit_callback_t mPrearrangeCallback;
+ commit_callback_t mTextEntryCallback;
+ commit_callback_t mSelectionCallback;
+ S32 mLastSelectedIndex;
};
-
#endif
diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp
new file mode 100644
index 0000000000..59499f987b
--- /dev/null
+++ b/indra/llui/llconsole.cpp
@@ -0,0 +1,401 @@
+/**
+ * @file llconsole.cpp
+ * @brief a scrolling console output device
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+//#include "llviewerprecompiledheaders.h"
+#include "linden_common.h"
+
+#include "llconsole.h"
+
+// linden library includes
+#include "llmath.h"
+//#include "llviewercontrol.h"
+#include "llcriticaldamp.h"
+#include "llfontgl.h"
+#include "llgl.h"
+#include "llui.h"
+#include "lluiimage.h"
+//#include "llviewerimage.h"
+//#include "llviewerimagelist.h"
+//#include "llviewerwindow.h"
+#include "llsd.h"
+#include "llfontgl.h"
+#include "llmath.h"
+
+//#include "llstartup.h"
+
+// Used for LCD display
+extern void AddNewDebugConsoleToLCD(const LLWString &newLine);
+
+LLConsole* gConsole = NULL; // Created and destroyed in LLViewerWindow.
+
+const F32 FADE_DURATION = 2.f;
+const S32 MIN_CONSOLE_WIDTH = 200;
+
+static LLDefaultChildRegistry::Register<LLConsole> r("console");
+
+LLConsole::LLConsole(const LLConsole::Params& p)
+: LLUICtrl(p),
+ LLFixedBuffer(p.max_lines),
+ mLinePersistTime(p.persist_time), // seconds
+ mFont(p.font)
+{
+ if (p.font_size_index.isProvided())
+ {
+ setFontSize(p.font_size_index);
+ }
+ mFadeTime = mLinePersistTime - FADE_DURATION;
+ setMaxLines(LLUI::sSettingGroups["config"]->getS32("ConsoleMaxLines"));
+}
+
+void LLConsole::setLinePersistTime(F32 seconds)
+{
+ mLinePersistTime = seconds;
+ mFadeTime = mLinePersistTime - FADE_DURATION;
+}
+
+void LLConsole::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ S32 new_width = llmax(50, llmin(getRect().getWidth(), width));
+ S32 new_height = llmax(llfloor(mFont->getLineHeight()) + 15, llmin(getRect().getHeight(), height));
+
+ if ( mConsoleWidth == new_width
+ && mConsoleHeight == new_height )
+ {
+ return;
+ }
+
+ mConsoleWidth = new_width;
+ mConsoleHeight= new_height;
+
+ LLUICtrl::reshape(new_width, new_height, called_from_parent);
+
+ for(paragraph_t::iterator paragraph_it = mParagraphs.begin(); paragraph_it != mParagraphs.end(); paragraph_it++)
+ {
+ (*paragraph_it).updateLines((F32)getRect().getWidth(), mFont, true);
+ }
+}
+
+void LLConsole::setFontSize(S32 size_index)
+{
+ if (-1 == size_index)
+ {
+ mFont = LLFontGL::getFontMonospace();
+ }
+ else if (0 == size_index)
+ {
+ mFont = LLFontGL::getFontSansSerif();
+ }
+ else if (1 == size_index)
+ {
+ mFont = LLFontGL::getFontSansSerifBig();
+ }
+ else
+ {
+ mFont = LLFontGL::getFontSansSerifHuge();
+ }
+ // Make sure the font exists
+ if (mFont == NULL)
+ {
+ mFont = LLFontGL::getFontDefault();
+ }
+
+ for(paragraph_t::iterator paragraph_it = mParagraphs.begin(); paragraph_it != mParagraphs.end(); paragraph_it++)
+ {
+ (*paragraph_it).updateLines((F32)getRect().getWidth(), mFont, true);
+ }
+}
+
+void LLConsole::draw()
+{
+ LLGLSUIDefault gls_ui;
+
+ // skip lines added more than mLinePersistTime ago
+ F32 cur_time = mTimer.getElapsedTimeF32();
+
+ F32 skip_time = cur_time - mLinePersistTime;
+ F32 fade_time = cur_time - mFadeTime;
+
+ if (mParagraphs.empty()) //No text to draw.
+ {
+ return;
+ }
+
+ U32 num_lines=0;
+
+ paragraph_t::reverse_iterator paragraph_it;
+ paragraph_it = mParagraphs.rbegin();
+ U32 paragraph_num=mParagraphs.size();
+
+ while (!mParagraphs.empty() && paragraph_it != mParagraphs.rend())
+ {
+ num_lines += (*paragraph_it).mLines.size();
+ if(num_lines > mMaxLines
+ || ( (mLinePersistTime > (F32)0.f) && ((*paragraph_it).mAddTime - skip_time)/(mLinePersistTime - mFadeTime) <= (F32)0.f))
+ { //All lines above here are done. Lose them.
+ for (U32 i=0;i<paragraph_num;i++)
+ {
+ if (!mParagraphs.empty())
+ mParagraphs.pop_front();
+ }
+ break;
+ }
+ paragraph_num--;
+ paragraph_it++;
+ }
+
+ if (mParagraphs.empty())
+ {
+ return;
+ }
+
+ // draw remaining lines
+ F32 y_pos = 0.f;
+
+ LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square");
+
+// F32 console_opacity = llclamp(gSavedSettings.getF32("ConsoleBackgroundOpacity"), 0.f, 1.f);
+ F32 console_opacity = llclamp(LLUI::sSettingGroups["config"]->getF32("ConsoleBackgroundOpacity"), 0.f, 1.f);
+// LLColor4 color = LLUIColorTable::instance().getColor("ConsoleBackground");
+ LLColor4 color = LLUIColorTable::instance().getColor("ConsoleBackground");
+ color.mV[VALPHA] *= console_opacity;
+
+ F32 line_height = mFont->getLineHeight();
+
+ for(paragraph_it = mParagraphs.rbegin(); paragraph_it != mParagraphs.rend(); paragraph_it++)
+ {
+ S32 target_height = llfloor( (*paragraph_it).mLines.size() * line_height + 8);
+ S32 target_width = llfloor( (*paragraph_it).mMaxWidth +15);
+
+ y_pos += ((*paragraph_it).mLines.size()) * line_height;
+ imagep->drawSolid(-14, (S32)(y_pos + line_height - target_height), target_width, target_height, color);
+
+ F32 y_off=0;
+
+ F32 alpha;
+
+ if ((mLinePersistTime > 0.f) && ((*paragraph_it).mAddTime < fade_time))
+ {
+ alpha = ((*paragraph_it).mAddTime - skip_time)/(mLinePersistTime - mFadeTime);
+ }
+ else
+ {
+ alpha = 1.0f;
+ }
+
+ if( alpha > 0.f )
+ {
+ for (lines_t::iterator line_it=(*paragraph_it).mLines.begin();
+ line_it != (*paragraph_it).mLines.end();
+ line_it ++)
+ {
+ for (line_color_segments_t::iterator seg_it = (*line_it).mLineColorSegments.begin();
+ seg_it != (*line_it).mLineColorSegments.end();
+ seg_it++)
+ {
+ mFont->render((*seg_it).mText, 0, (*seg_it).mXPosition - 8, y_pos - y_off,
+ LLColor4(
+ (*seg_it).mColor.mV[VRED],
+ (*seg_it).mColor.mV[VGREEN],
+ (*seg_it).mColor.mV[VBLUE],
+ (*seg_it).mColor.mV[VALPHA]*alpha),
+ LLFontGL::LEFT,
+ LLFontGL::BASELINE,
+ LLFontGL::NORMAL,
+ LLFontGL::DROP_SHADOW,
+ S32_MAX,
+ target_width
+ );
+ }
+ y_off += line_height;
+ }
+ }
+ y_pos += 8;
+ }
+}
+
+void LLConsole::addLine(const std::string& utf8line)
+{
+ LLWString wline = utf8str_to_wstring(utf8line);
+ addLine(wline, 0.f, LLColor4(1.f, 1.f, 1.f, 1.f));
+}
+
+void LLConsole::addLine(const LLWString& wline)
+{
+ addLine(wline, 0.f, LLColor4(1.f, 1.f, 1.f, 1.f));
+}
+
+void LLConsole::addLine(const std::string& utf8line, F32 size, const LLColor4 &color)
+{
+ LLWString wline = utf8str_to_wstring(utf8line);
+ addLine(wline, size, color);
+}
+
+//Generate highlight color segments for this paragraph. Pass in default color of paragraph.
+void LLConsole::Paragraph::makeParagraphColorSegments (const LLColor4 &color)
+{
+ LLSD paragraph_color_segments;
+ LLColor4 lcolor=color;
+
+ paragraph_color_segments[0]["text"] =wstring_to_utf8str(mParagraphText);
+ LLSD color_sd = color.getValue();
+ paragraph_color_segments[0]["color"]=color_sd;
+
+ for(LLSD::array_const_iterator color_segment_it = paragraph_color_segments.beginArray();
+ color_segment_it != paragraph_color_segments.endArray();
+ ++color_segment_it)
+ {
+ LLSD color_llsd = (*color_segment_it)["color"];
+ std::string color_str = (*color_segment_it)["text"].asString();
+
+ ParagraphColorSegment color_segment;
+
+ color_segment.mColor.setValue(color_llsd);
+ color_segment.mNumChars = color_str.length();
+
+ mParagraphColorSegments.push_back(color_segment);
+ }
+}
+
+//Called when a paragraph is added to the console or window is resized.
+void LLConsole::Paragraph::updateLines(F32 screen_width, const LLFontGL* font, bool force_resize)
+{
+ if ( !force_resize )
+ {
+ if ( mMaxWidth >= 0.0f
+ && mMaxWidth < screen_width )
+ {
+ return; //No resize required.
+ }
+ }
+
+ screen_width = screen_width - 30; //Margin for small windows.
+
+ if ( mParagraphText.empty()
+ || mParagraphColorSegments.empty()
+ || font == NULL)
+ {
+ return; //Not enough info to complete.
+ }
+
+ mLines.clear(); //Chuck everything.
+ mMaxWidth = 0.0f;
+
+ paragraph_color_segments_t::iterator current_color = mParagraphColorSegments.begin();
+ U32 current_color_length = (*current_color).mNumChars;
+
+ S32 paragraph_offset = 0; //Offset into the paragraph text.
+
+ // Wrap lines that are longer than the view is wide.
+ while( paragraph_offset < (S32)mParagraphText.length() )
+ {
+ S32 skip_chars; // skip '\n'
+ // Figure out if a word-wrapped line fits here.
+ LLWString::size_type line_end = mParagraphText.find_first_of(llwchar('\n'), paragraph_offset);
+ if (line_end != LLWString::npos)
+ {
+ skip_chars = 1; // skip '\n'
+ }
+ else
+ {
+ line_end = mParagraphText.size();
+ skip_chars = 0;
+ }
+
+ U32 drawable = font->maxDrawableChars(mParagraphText.c_str()+paragraph_offset, screen_width, line_end - paragraph_offset, LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
+
+ if (drawable != 0)
+ {
+ F32 x_position = 0; //Screen X position of text.
+
+ mMaxWidth = llmax( mMaxWidth, (F32)font->getWidth( mParagraphText.substr( paragraph_offset, drawable ).c_str() ) );
+ Line line;
+
+ U32 left_to_draw = drawable;
+ U32 drawn = 0;
+
+ while (left_to_draw >= current_color_length
+ && current_color != mParagraphColorSegments.end() )
+ {
+ LLWString color_text = mParagraphText.substr( paragraph_offset + drawn, current_color_length );
+ line.mLineColorSegments.push_back( LineColorSegment( color_text, //Append segment to line.
+ (*current_color).mColor,
+ x_position ) );
+
+ x_position += font->getWidth( color_text.c_str() ); //Set up next screen position.
+
+ drawn += current_color_length;
+ left_to_draw -= current_color_length;
+
+ current_color++; //Goto next paragraph color record.
+
+ if (current_color != mParagraphColorSegments.end())
+ {
+ current_color_length = (*current_color).mNumChars;
+ }
+ }
+
+ if (left_to_draw > 0 && current_color != mParagraphColorSegments.end() )
+ {
+ LLWString color_text = mParagraphText.substr( paragraph_offset + drawn, left_to_draw );
+
+ line.mLineColorSegments.push_back( LineColorSegment( color_text, //Append segment to line.
+ (*current_color).mColor,
+ x_position ) );
+
+ current_color_length -= left_to_draw;
+ }
+ mLines.push_back(line); //Append line to paragraph line list.
+ }
+ paragraph_offset += (drawable + skip_chars);
+ }
+}
+
+//Pass in the string and the default color for this block of text.
+LLConsole::Paragraph::Paragraph (LLWString str, const LLColor4 &color, F32 add_time, const LLFontGL* font, F32 screen_width)
+ : mParagraphText(str), mAddTime(add_time), mMaxWidth(-1)
+{
+ makeParagraphColorSegments(color);
+ updateLines( screen_width, font );
+}
+
+void LLConsole::addLine(const LLWString& wline, F32 size, const LLColor4 &color)
+{
+ Paragraph paragraph(wline, color, mTimer.getElapsedTimeF32(), mFont, (F32)getRect().getWidth() );
+
+ mParagraphs.push_back ( paragraph );
+
+ // remove old paragraphs which can't possibly be visible any more. ::draw() will do something similar but more conservative - we do this here because ::draw() isn't guaranteed to ever be called! (i.e. the console isn't visible)
+ while ((S32)mParagraphs.size() > llmax((S32)0, (S32)(mMaxLines)))
+ {
+ mParagraphs.pop_front();
+ }
+}
diff --git a/indra/llui/llconsole.h b/indra/llui/llconsole.h
new file mode 100644
index 0000000000..5800a82922
--- /dev/null
+++ b/indra/llui/llconsole.h
@@ -0,0 +1,162 @@
+/**
+ * @file llconsole.h
+ * @brief a simple console-style output device
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLCONSOLE_H
+#define LL_LLCONSOLE_H
+
+#include "llfixedbuffer.h"
+#include "lluictrl.h"
+#include "v4color.h"
+#include <deque>
+
+class LLSD;
+
+class LLConsole : public LLFixedBuffer, public LLUICtrl
+{
+public:
+ typedef enum e_font_size
+ {
+ MONOSPACE = -1,
+ SMALL = 0,
+ BIG = 1
+ } EFontSize;
+
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<U32> max_lines;
+ Optional<F32> persist_time;
+ Optional<S32> font_size_index;
+ Params()
+ : max_lines("max_lines", LLUI::sSettingGroups["config"]->getS32("ConsoleMaxLines")),
+ persist_time("persist_time", 0.f), // forever
+ font_size_index("font_size_index")
+ {
+ mouse_opaque(false);
+ }
+ };
+protected:
+ LLConsole(const Params&);
+ friend class LLUICtrlFactory;
+
+public:
+ //A paragraph color segment defines the color of text in a line
+ //of text that was received for console display. It has no
+ //notion of line wraps, screen position, or the text it contains.
+ //It is only the number of characters that are a color and the
+ //color.
+ struct ParagraphColorSegment
+ {
+ S32 mNumChars;
+ LLColor4 mColor;
+ };
+
+ //A line color segment is a chunk of text, the color associated
+ //with it, and the X Position it was calculated to begin at
+ //on the screen. X Positions are re-calculated if the
+ //screen changes size.
+ class LineColorSegment
+ {
+ public:
+ LineColorSegment(LLWString text, LLColor4 color, F32 xpos) : mText(text), mColor(color), mXPosition(xpos) {}
+ public:
+ LLWString mText;
+ LLColor4 mColor;
+ F32 mXPosition;
+ };
+
+ typedef std::list<LineColorSegment> line_color_segments_t;
+
+ //A line is composed of one or more color segments.
+ class Line
+ {
+ public:
+ line_color_segments_t mLineColorSegments;
+ };
+
+ typedef std::list<Line> lines_t;
+ typedef std::list<ParagraphColorSegment> paragraph_color_segments_t;
+
+ //A paragraph is a processed element containing the entire text of the
+ //message (used for recalculating positions on screen resize)
+ //The time this message was added to the console output
+ //The visual screen width of the longest line in this block
+ //And a list of one or more lines which are used to display this message.
+ class Paragraph
+ {
+ public:
+ Paragraph (LLWString str, const LLColor4 &color, F32 add_time, const LLFontGL* font, F32 screen_width);
+ void makeParagraphColorSegments ( const LLColor4 &color);
+ void updateLines ( F32 screen_width, const LLFontGL* font, bool force_resize=false );
+ public:
+ LLWString mParagraphText; //The entire text of the paragraph
+ paragraph_color_segments_t mParagraphColorSegments;
+ F32 mAddTime; //Time this paragraph was added to the display.
+ F32 mMaxWidth; //Width of the widest line of text in this paragraph.
+ lines_t mLines;
+
+ };
+
+ //The console contains a deque of paragraphs which represent the individual messages.
+ typedef std::deque<Paragraph> paragraph_t;
+ paragraph_t mParagraphs;
+
+ ~LLConsole(){};
+
+ // each line lasts this long after being added
+ void setLinePersistTime(F32 seconds);
+
+ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+ // -1 = monospace, 0 means small, font size = 1 means big
+ void setFontSize(S32 size_index);
+
+ void addLine(const std::string& utf8line, F32 size, const LLColor4 &color);
+ void addLine(const LLWString& wline, F32 size, const LLColor4 &color);
+
+ // Overrides
+ /*virtual*/ void draw();
+ /*virtual*/ void addLine(const std::string& utf8line);
+ /*virtual*/ void addLine(const LLWString& line);
+private:
+ F32 mLinePersistTime; // Age at which to stop drawing.
+ F32 mFadeTime; // Age at which to start fading
+ const LLFontGL* mFont;
+ S32 mLastBoxHeight;
+ S32 mLastBoxWidth;
+ S32 mConsoleWidth;
+ S32 mConsoleHeight;
+
+};
+
+extern LLConsole* gConsole;
+
+#endif
diff --git a/indra/llui/llcontainerview.cpp b/indra/llui/llcontainerview.cpp
new file mode 100644
index 0000000000..51ef80f4b9
--- /dev/null
+++ b/indra/llui/llcontainerview.cpp
@@ -0,0 +1,302 @@
+/**
+ * @file llcontainerview.cpp
+ * @brief Container for all statistics info
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llcontainerview.h"
+
+#include "llerror.h"
+#include "llfontgl.h"
+#include "llgl.h"
+#include "llui.h"
+#include "llstring.h"
+#include "llscrollcontainer.h"
+#include "lluictrlfactory.h"
+
+static LLDefaultChildRegistry::Register<LLContainerView> r1("container_view");
+
+#include "llpanel.h"
+#include "llstatview.h"
+static ContainerViewRegistry::Register<LLStatView> r2("stat_view");
+static ContainerViewRegistry::Register<LLPanel> r3("panel", &LLPanel::fromXML);
+
+LLContainerView::LLContainerView(const LLContainerView::Params& p)
+: LLView(p),
+ mShowLabel(p.show_label),
+ mLabel(p.label),
+ mDisplayChildren(p.display_children)
+{
+ mCollapsible = TRUE;
+ mScrollContainer = NULL;
+}
+
+LLContainerView::~LLContainerView()
+{
+ // Children all cleaned up by default view destructor.
+}
+
+BOOL LLContainerView::postBuild()
+{
+ setDisplayChildren(mDisplayChildren);
+ reshape(getRect().getWidth(), getRect().getHeight(), FALSE);
+ return TRUE;
+}
+
+bool LLContainerView::addChild(LLView* child, S32 tab_group)
+{
+ bool res = LLView::addChild(child, tab_group);
+ if (res)
+ {
+ sendChildToBack(child);
+ }
+ return res;
+}
+
+BOOL LLContainerView::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = FALSE;
+ if (mDisplayChildren)
+ {
+ handled = (LLView::childrenHandleMouseDown(x, y, mask) != NULL);
+ }
+ if (!handled)
+ {
+ if( mCollapsible && mShowLabel && (y >= getRect().getHeight() - 10) )
+ {
+ setDisplayChildren(!mDisplayChildren);
+ reshape(getRect().getWidth(), getRect().getHeight(), FALSE);
+ handled = TRUE;
+ }
+ }
+ return handled;
+}
+
+BOOL LLContainerView::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = FALSE;
+ if (mDisplayChildren)
+ {
+ handled = (LLView::childrenHandleMouseUp(x, y, mask) != NULL);
+ }
+ return handled;
+}
+
+
+void LLContainerView::draw()
+{
+ {
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f));
+ }
+
+ // Draw the label
+ if (mShowLabel)
+ {
+ LLFontGL::getFontMonospace()->renderUTF8(
+ mLabel, 0, 2, getRect().getHeight() - 2, LLColor4(1,1,1,1), LLFontGL::LEFT, LLFontGL::TOP);
+ }
+
+ LLView::draw();
+}
+
+
+void LLContainerView::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ LLRect scroller_rect;
+ scroller_rect.setOriginAndSize(0, 0, width, height);
+
+ if (mScrollContainer)
+ {
+ scroller_rect = mScrollContainer->getContentWindowRect();
+ }
+ else
+ {
+ // if we're uncontained - make height as small as possible
+ scroller_rect.mTop = 0;
+ }
+
+ arrange(scroller_rect.getWidth(), scroller_rect.getHeight(), called_from_parent);
+
+ // sometimes, after layout, our container will change size (scrollbars popping in and out)
+ // if so, attempt another layout
+ if (mScrollContainer)
+ {
+ LLRect new_container_rect = mScrollContainer->getContentWindowRect();
+
+ if ((new_container_rect.getWidth() != scroller_rect.getWidth()) ||
+ (new_container_rect.getHeight() != scroller_rect.getHeight())) // the container size has changed, attempt to arrange again
+ {
+ arrange(new_container_rect.getWidth(), new_container_rect.getHeight(), called_from_parent);
+ }
+ }
+}
+
+void LLContainerView::arrange(S32 width, S32 height, BOOL called_from_parent)
+{
+ // Determine the sizes and locations of all contained views
+ S32 total_height = 0;
+ S32 top, left, right, bottom;
+ //LLView *childp;
+
+ // These will be used for the children
+ left = 4;
+ top = getRect().getHeight() - 4;
+ right = width - 2;
+ bottom = top;
+
+ // Leave some space for the top label/grab handle
+ if (mShowLabel)
+ {
+ total_height += 20;
+ }
+
+ if (mDisplayChildren)
+ {
+ // Determine total height
+ U32 child_height = 0;
+ for (child_list_const_iter_t child_iter = getChildList()->begin();
+ child_iter != getChildList()->end(); ++child_iter)
+ {
+ LLView *childp = *child_iter;
+ if (!childp->getVisible())
+ {
+ llwarns << "Incorrect visibility!" << llendl;
+ }
+ LLRect child_rect = childp->getRequiredRect();
+ child_height += child_rect.getHeight();
+ child_height += 2;
+ }
+ total_height += child_height;
+ }
+
+ if (total_height < height)
+ total_height = height;
+
+ if (followsTop())
+ {
+ // HACK: casting away const. Should use setRect or some helper function instead.
+ const_cast<LLRect&>(getRect()).mBottom = getRect().mTop - total_height;
+ }
+ else
+ {
+ // HACK: casting away const. Should use setRect or some helper function instead.
+ const_cast<LLRect&>(getRect()).mTop = getRect().mBottom + total_height;
+ }
+ // HACK: casting away const. Should use setRect or some helper function instead.
+ const_cast<LLRect&>(getRect()).mRight = getRect().mLeft + width;
+
+ top = total_height;
+ if (mShowLabel)
+ {
+ top -= 20;
+ }
+
+ bottom = top;
+
+ if (mDisplayChildren)
+ {
+ // Iterate through all children, and put in container from top down.
+ for (child_list_const_iter_t child_iter = getChildList()->begin();
+ child_iter != getChildList()->end(); ++child_iter)
+ {
+ LLView *childp = *child_iter;
+ LLRect child_rect = childp->getRequiredRect();
+ bottom -= child_rect.getHeight();
+ LLRect r(left, bottom + child_rect.getHeight(), right, bottom);
+ childp->setRect(r);
+ childp->reshape(right - left, top - bottom);
+ top = bottom - 2;
+ bottom = top;
+ }
+ }
+
+ if (!called_from_parent)
+ {
+ if (getParent())
+ {
+ getParent()->reshape(getParent()->getRect().getWidth(), getParent()->getRect().getHeight(), FALSE);
+ }
+ }
+
+}
+
+LLRect LLContainerView::getRequiredRect()
+{
+ LLRect req_rect;
+ //LLView *childp;
+ U32 total_height = 0;
+
+ // Determine the sizes and locations of all contained views
+
+ // Leave some space for the top label/grab handle
+
+ if (mShowLabel)
+ {
+ total_height = 20;
+ }
+
+
+ if (mDisplayChildren)
+ {
+ // Determine total height
+ U32 child_height = 0;
+ for (child_list_const_iter_t child_iter = getChildList()->begin();
+ child_iter != getChildList()->end(); ++child_iter)
+ {
+ LLView *childp = *child_iter;
+ LLRect child_rect = childp->getRequiredRect();
+ child_height += child_rect.getHeight();
+ child_height += 2;
+ }
+
+ total_height += child_height;
+ }
+ req_rect.mTop = total_height;
+ return req_rect;
+}
+
+void LLContainerView::setLabel(const std::string& label)
+{
+ mLabel = label;
+}
+
+void LLContainerView::setDisplayChildren(const BOOL displayChildren)
+{
+ mDisplayChildren = displayChildren;
+ for (child_list_const_iter_t child_iter = getChildList()->begin();
+ child_iter != getChildList()->end(); ++child_iter)
+ {
+ LLView *childp = *child_iter;
+ childp->setVisible(mDisplayChildren);
+ }
+}
diff --git a/indra/llui/llcontainerview.h b/indra/llui/llcontainerview.h
new file mode 100644
index 0000000000..74e38e18bc
--- /dev/null
+++ b/indra/llui/llcontainerview.h
@@ -0,0 +1,100 @@
+/**
+ * @file llcontainerview.h
+ * @brief Container for all statistics info.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLCONTAINERVIEW_H
+#define LL_LLCONTAINERVIEW_H
+
+#include "stdtypes.h"
+#include "lltextbox.h"
+#include "llstatbar.h"
+#include "llview.h"
+
+class LLScrollContainer;
+
+struct ContainerViewRegistry : public LLChildRegistry<ContainerViewRegistry>
+{};
+
+class LLContainerView : public LLView
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
+ {
+ Optional<std::string> label;
+ Optional<bool> show_label;
+ Optional<bool> display_children;
+ Params()
+ : label("label"),
+ show_label("show_label", FALSE),
+ display_children("display_children", TRUE)
+ {
+ mouse_opaque(false);
+ }
+ };
+
+ // my valid children are stored in this registry
+ typedef ContainerViewRegistry child_registry_t;
+
+protected:
+ LLContainerView(const Params& p);
+ friend class LLUICtrlFactory;
+public:
+ ~LLContainerView();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0);
+
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+
+ /*virtual*/ void draw();
+ /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+ /*virtual*/ LLRect getRequiredRect(); // Return the height of this object, given the set options.
+
+ void setLabel(const std::string& label);
+ void showLabel(BOOL show) { mShowLabel = show; }
+ void setDisplayChildren(const BOOL displayChildren);
+ BOOL getDisplayChildren() { return mDisplayChildren; }
+ void setScrollContainer(LLScrollContainer* scroll) {mScrollContainer = scroll;}
+
+ private:
+ LLScrollContainer* mScrollContainer;
+ void arrange(S32 width, S32 height, BOOL called_from_parent = TRUE);
+ BOOL mShowLabel;
+
+protected:
+ BOOL mDisplayChildren;
+ std::string mLabel;
+public:
+ BOOL mCollapsible;
+
+};
+#endif // LL_CONTAINERVIEW_
diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp
new file mode 100644
index 0000000000..74438b184a
--- /dev/null
+++ b/indra/llui/lldockablefloater.cpp
@@ -0,0 +1,240 @@
+/**
+ * @file lldockablefloater.cpp
+ * @brief Creates a panel of a specific kind for a toast
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lldockablefloater.h"
+#include "llfloaterreg.h"
+
+//static
+LLHandle<LLFloater> LLDockableFloater::sInstanceHandle;
+
+//static
+void LLDockableFloater::init(LLDockableFloater* thiz)
+{
+ thiz->setDocked(thiz->mDockControl.get() != NULL
+ && thiz->mDockControl.get()->isDockVisible());
+ thiz->resetInstance();
+
+ // all dockable floaters should have close, dock and minimize buttons
+ thiz->setCanClose(TRUE);
+ thiz->setCanDock(true);
+ thiz->setCanMinimize(TRUE);
+}
+
+LLDockableFloater::LLDockableFloater(LLDockControl* dockControl,
+ const LLSD& key, const Params& params) :
+ LLFloater(key, params), mDockControl(dockControl), mUniqueDocking(true)
+ , mOverlapsScreenChannel(false)
+{
+ init(this);
+ mUseTongue = true;
+}
+
+LLDockableFloater::LLDockableFloater(LLDockControl* dockControl, bool uniqueDocking,
+ const LLSD& key, const Params& params) :
+ LLFloater(key, params), mDockControl(dockControl), mUniqueDocking(uniqueDocking)
+{
+ init(this);
+ mUseTongue = true;
+}
+
+LLDockableFloater::LLDockableFloater(LLDockControl* dockControl, bool uniqueDocking,
+ bool useTongue, const LLSD& key, const Params& params) :
+ LLFloater(key, params), mDockControl(dockControl), mUseTongue(useTongue), mUniqueDocking(uniqueDocking)
+{
+ init(this);
+}
+
+LLDockableFloater::~LLDockableFloater()
+{
+}
+
+BOOL LLDockableFloater::postBuild()
+{
+ mDockTongue = LLUI::getUIImage("windows/Flyout_Pointer.png");
+ LLFloater::setDocked(true);
+ return LLView::postBuild();
+}
+
+//static
+void LLDockableFloater::toggleInstance(const LLSD& sdname)
+{
+ LLSD key;
+ std::string name = sdname.asString();
+
+ LLDockableFloater* instance =
+ dynamic_cast<LLDockableFloater*> (LLFloaterReg::findInstance(name));
+ // if floater closed or docked
+ if (instance == NULL || instance != NULL && instance->isDocked())
+ {
+ LLFloaterReg::toggleInstance(name, key);
+ // restore button toggle state
+ if (instance != NULL)
+ {
+ instance->storeVisibilityControl();
+ }
+ }
+ // if floater undocked
+ else if (instance != NULL)
+ {
+ instance->setMinimized(FALSE);
+ if (instance->getVisible())
+ {
+ instance->setVisible(FALSE);
+ }
+ else
+ {
+ instance->setVisible(TRUE);
+ gFloaterView->bringToFront(instance);
+ }
+ }
+}
+
+void LLDockableFloater::resetInstance()
+{
+ if (mUniqueDocking && sInstanceHandle.get() != this)
+ {
+ if (sInstanceHandle.get() != NULL && sInstanceHandle.get()->isDocked())
+ {
+ sInstanceHandle.get()->setVisible(FALSE);
+ }
+ sInstanceHandle = getHandle();
+ }
+}
+
+void LLDockableFloater::setVisible(BOOL visible)
+{
+ if(visible && isDocked())
+ {
+ resetInstance();
+ }
+
+ if (visible && mDockControl.get() != NULL)
+ {
+ mDockControl.get()->repositionDockable();
+ }
+
+ if (visible)
+ {
+ LLFloater::setFrontmost(TRUE);
+ }
+ LLFloater::setVisible(visible);
+}
+
+void LLDockableFloater::setMinimized(BOOL minimize)
+{
+ if(minimize)
+ {
+ setVisible(FALSE);
+ }
+}
+
+LLView * LLDockableFloater::getDockWidget()
+{
+ LLView * res = NULL;
+ if (getDockControl() != NULL) {
+ res = getDockControl()->getDock();
+ }
+
+ return res;
+}
+
+void LLDockableFloater::onDockHidden()
+{
+ setCanDock(FALSE);
+}
+
+void LLDockableFloater::onDockShown()
+{
+ if (!isMinimized())
+ {
+ setCanDock(TRUE);
+ }
+}
+
+void LLDockableFloater::setDocked(bool docked, bool pop_on_undock)
+{
+ if (mDockControl.get() != NULL && mDockControl.get()->isDockVisible())
+ {
+ if (docked)
+ {
+ resetInstance();
+ mDockControl.get()->on();
+ }
+ else
+ {
+ mDockControl.get()->off();
+ }
+
+ if (!docked && pop_on_undock)
+ {
+ // visually pop up a little bit to emphasize the undocking
+ translate(0, UNDOCK_LEAP_HEIGHT);
+ }
+ }
+ else
+ {
+ docked = false;
+ }
+
+ LLFloater::setDocked(docked, pop_on_undock);
+}
+
+void LLDockableFloater::draw()
+{
+ if (mDockControl.get() != NULL)
+ {
+ mDockControl.get()->repositionDockable();
+ if (isDocked())
+ {
+ mDockControl.get()->drawToungue();
+ }
+ }
+ LLFloater::draw();
+}
+
+void LLDockableFloater::setDockControl(LLDockControl* dockControl)
+{
+ mDockControl.reset(dockControl);
+ setDocked(mDockControl.get() != NULL && mDockControl.get()->isDockVisible());
+}
+
+const LLUIImagePtr& LLDockableFloater::getDockTongue()
+{
+ return mDockTongue;
+}
+
+LLDockControl* LLDockableFloater::getDockControl()
+{
+ return mDockControl.get();
+}
diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h
new file mode 100644
index 0000000000..2b1ce99ae2
--- /dev/null
+++ b/indra/llui/lldockablefloater.h
@@ -0,0 +1,148 @@
+/**
+ * @file lldockablefloater.h
+ * @brief Creates a panel of a specific kind for a toast.
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_DOCKABLEFLOATER_H
+#define LL_DOCKABLEFLOATER_H
+
+#include "llerror.h"
+#include "llfloater.h"
+#include "lldockcontrol.h"
+
+/**
+ * Represents floater that can dock.
+ * In case impossibility deriving from LLDockableFloater use LLDockControl.
+ */
+class LLDockableFloater : public LLFloater
+{
+ static const U32 UNDOCK_LEAP_HEIGHT = 12;
+
+ static void init(LLDockableFloater* thiz);
+public:
+ LOG_CLASS(LLDockableFloater);
+ LLDockableFloater(LLDockControl* dockControl, const LLSD& key,
+ const Params& params = getDefaultParams());
+
+ /**
+ * Constructor.
+ * @param dockControl a pointer to the doc control instance
+ * @param uniqueDocking - a flag defines is docking should work as tab(at one
+ * moment only one docked floater can be shown), also this flag defines is dock
+ * tongue should be used.
+ * @params key a floater key.
+ * @params params a floater parameters
+ */
+ LLDockableFloater(LLDockControl* dockControl, bool uniqueDocking,
+ const LLSD& key, const Params& params = getDefaultParams());
+
+ /**
+ * Constructor.
+ * @param dockControl a pointer to the doc control instance
+ * @param uniqueDocking - a flag defines is docking should work as tab(at one
+ * moment only one docked floater can be shown).
+ * @praram useTongue - a flag defines is dock tongue should be used.
+ * @params key a floater key.
+ * @params params a floater parameters
+ */
+ LLDockableFloater(LLDockControl* dockControl, bool uniqueDocking,
+ bool useTongue, const LLSD& key,
+ const Params& params = getDefaultParams());
+
+ virtual ~LLDockableFloater();
+
+ static LLHandle<LLFloater> getInstanceHandle() { return sInstanceHandle; }
+
+ static void toggleInstance(const LLSD& sdname);
+
+ /**
+ * If descendant class overrides postBuild() in order to perform specific
+ * construction then it must still invoke its superclass' implementation.
+ */
+ /* virtula */BOOL postBuild();
+ /* virtual */void setDocked(bool docked, bool pop_on_undock = true);
+ /* virtual */void draw();
+
+ /**
+ * If descendant class overrides setVisible() then it must still invoke its
+ * superclass' implementation.
+ */
+ /*virtual*/ void setVisible(BOOL visible);
+
+ /**
+ * If descendant class overrides setMinimized() then it must still invoke its
+ * superclass' implementation.
+ */
+ /*virtual*/ void setMinimized(BOOL minimize);
+
+ LLView * getDockWidget();
+
+ virtual void onDockHidden();
+ virtual void onDockShown();
+
+ LLDockControl* getDockControl();
+
+ /**
+ * Returns true if screen channel should consider floater's size when drawing toasts.
+ *
+ * By default returns false.
+ */
+ virtual bool overlapsScreenChannel() { return mOverlapsScreenChannel && getVisible() && isDocked(); }
+ virtual void setOverlapsScreenChannel(bool overlaps) { mOverlapsScreenChannel = overlaps; }
+
+ bool getUniqueDocking() { return mUniqueDocking; }
+ bool getUseTongue() { return mUseTongue; }
+private:
+ /**
+ * Provides unique of dockable floater.
+ * If dockable floater already exists it should be closed.
+ */
+ void resetInstance();
+
+protected:
+ void setDockControl(LLDockControl* dockControl);
+ const LLUIImagePtr& getDockTongue();
+
+private:
+ std::auto_ptr<LLDockControl> mDockControl;
+ LLUIImagePtr mDockTongue;
+ static LLHandle<LLFloater> sInstanceHandle;
+ /**
+ * Provides possibility to define that dockable floaters can be docked
+ * non exclusively.
+ */
+ bool mUniqueDocking;
+
+ bool mUseTongue;
+
+ bool mOverlapsScreenChannel;
+};
+
+#endif /* LL_DOCKABLEFLOATER_H */
diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp
new file mode 100644
index 0000000000..0d8e54aa48
--- /dev/null
+++ b/indra/llui/lldockcontrol.cpp
@@ -0,0 +1,303 @@
+/**
+ * @file lldockcontrol.cpp
+ * @brief Creates a panel of a specific kind for a toast
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lldockcontrol.h"
+#include "lldockablefloater.h"
+
+LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
+ const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_allowed_rect_callback) :
+ mDockWidget(dockWidget), mDockableFloater(dockableFloater), mDockTongue(dockTongue)
+{
+ mDockAt = dockAt;
+
+ if (dockableFloater->isDocked())
+ {
+ on();
+ }
+ else
+ {
+ off();
+ }
+
+ if (!(get_allowed_rect_callback))
+ {
+ mGetAllowedRectCallback = boost::bind(&LLDockControl::getAllowedRect, this, _1);
+ }
+ else
+ {
+ mGetAllowedRectCallback = get_allowed_rect_callback;
+ }
+
+ if (dockWidget != NULL)
+ {
+ repositionDockable();
+ }
+
+ if (mDockWidget != NULL)
+ {
+ mDockWidgetVisible = isDockVisible();
+ }
+ else
+ {
+ mDockWidgetVisible = false;
+ }
+}
+
+LLDockControl::~LLDockControl()
+{
+}
+
+void LLDockControl::setDock(LLView* dockWidget)
+{
+ mDockWidget = dockWidget;
+ if (mDockWidget != NULL)
+ {
+ repositionDockable();
+ mDockWidgetVisible = isDockVisible();
+ }
+ else
+ {
+ mDockWidgetVisible = false;
+ }
+}
+
+void LLDockControl::getAllowedRect(LLRect& rect)
+{
+ rect = mDockableFloater->getRootView()->getRect();
+}
+
+void LLDockControl::repositionDockable()
+{
+ LLRect dockRect = mDockWidget->calcScreenRect();
+ LLRect rootRect;
+ mGetAllowedRectCallback(rootRect);
+
+ // recalculate dockable position if dock position changed, dock visibility changed,
+ // root view rect changed or recalculation is forced
+ if (mPrevDockRect != dockRect || mDockWidgetVisible != isDockVisible()
+ || mRootRect != rootRect || mRecalculateDocablePosition)
+ {
+ // undock dockable and off() if dock not visible
+ if (!isDockVisible())
+ {
+ mDockableFloater->setDocked(false);
+ // force off() since dockable may not have dockControll at this time
+ off();
+ LLDockableFloater* dockable_floater =
+ dynamic_cast<LLDockableFloater*> (mDockableFloater);
+ if(dockable_floater != NULL)
+ {
+ dockable_floater->onDockHidden();
+ }
+ }
+ else
+ {
+ if(mEnabled)
+ {
+ moveDockable();
+ }
+ LLDockableFloater* dockable_floater =
+ dynamic_cast<LLDockableFloater*> (mDockableFloater);
+ if(dockable_floater != NULL)
+ {
+ dockable_floater->onDockShown();
+ }
+ }
+
+ mPrevDockRect = dockRect;
+ mRootRect = rootRect;
+ mRecalculateDocablePosition = false;
+ mDockWidgetVisible = isDockVisible();
+ }
+}
+
+bool LLDockControl::isDockVisible()
+{
+ bool res = true;
+
+ if (mDockWidget != NULL)
+ {
+ //we should check all hierarchy
+ res = mDockWidget->isInVisibleChain();
+ if (res)
+ {
+ LLRect dockRect = mDockWidget->calcScreenRect();
+
+ switch (mDockAt)
+ {
+ case LEFT: // to keep compiler happy
+ break;
+ case TOP:
+ // check is dock inside parent rect
+ LLRect dockParentRect =
+ mDockWidget->getParent()->calcScreenRect();
+ if (dockRect.mRight <= dockParentRect.mLeft
+ || dockRect.mLeft >= dockParentRect.mRight)
+ {
+ res = false;
+ }
+ break;
+ }
+ }
+ }
+
+ return res;
+}
+
+void LLDockControl::moveDockable()
+{
+ // calculate new dockable position
+ LLRect dockRect = mDockWidget->calcScreenRect();
+ LLRect rootRect;
+ mGetAllowedRectCallback(rootRect);
+
+ bool use_tongue = false;
+ LLDockableFloater* dockable_floater =
+ dynamic_cast<LLDockableFloater*> (mDockableFloater);
+ if (dockable_floater != NULL)
+ {
+ use_tongue = dockable_floater->getUseTongue();
+ }
+
+ LLRect dockableRect = mDockableFloater->calcScreenRect();
+ S32 x = 0;
+ S32 y = 0;
+ LLRect dockParentRect;
+ switch (mDockAt)
+ {
+ case LEFT:
+ x = dockRect.mLeft;
+ y = dockRect.mTop + mDockTongue->getHeight() + dockableRect.getHeight();
+ // check is dockable inside root view rect
+ if (x < rootRect.mLeft)
+ {
+ x = rootRect.mLeft;
+ }
+ if (x + dockableRect.getWidth() > rootRect.mRight)
+ {
+ x = rootRect.mRight - dockableRect.getWidth();
+ }
+
+ mDockTongueX = x + dockableRect.getWidth()/2 - mDockTongue->getWidth() / 2;
+
+ mDockTongueY = dockRect.mTop;
+ break;
+
+ case TOP:
+ x = dockRect.getCenterX() - dockableRect.getWidth() / 2;
+ y = dockRect.mTop + dockableRect.getHeight();
+ // unique docking used with dock tongue, so add tongue height o the Y coordinate
+ if (use_tongue)
+ {
+ y += mDockTongue->getHeight();
+ }
+
+ // check is dockable inside root view rect
+ if (x < rootRect.mLeft)
+ {
+ x = rootRect.mLeft;
+ }
+ if (x + dockableRect.getWidth() > rootRect.mRight)
+ {
+ x = rootRect.mRight - dockableRect.getWidth();
+ }
+
+
+ // calculate dock tongue position
+ dockParentRect = mDockWidget->getParent()->calcScreenRect();
+ if (dockRect.getCenterX() < dockParentRect.mLeft)
+ {
+ mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2;
+ }
+ else if (dockRect.getCenterX() > dockParentRect.mRight)
+ {
+ mDockTongueX = dockParentRect.mRight - mDockTongue->getWidth() / 2;;
+ }
+ else
+ {
+ mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2;
+ }
+ mDockTongueY = dockRect.mTop;
+
+ break;
+ }
+
+ // move dockable
+ dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(),
+ dockableRect.getHeight());
+ LLRect localDocableParentRect;
+ mDockableFloater->getParent()->screenRectToLocal(dockableRect,
+ &localDocableParentRect);
+ mDockableFloater->setRect(localDocableParentRect);
+
+ mDockableFloater->screenPointToLocal(mDockTongueX, mDockTongueY,
+ &mDockTongueX, &mDockTongueY);
+
+}
+
+void LLDockControl::on()
+{
+ if (isDockVisible())
+ {
+ mEnabled = true;
+ mRecalculateDocablePosition = true;
+ }
+}
+
+void LLDockControl::off()
+{
+ mEnabled = false;
+}
+
+void LLDockControl::forceRecalculatePosition()
+{
+ mRecalculateDocablePosition = true;
+}
+
+void LLDockControl::drawToungue()
+{
+ bool use_tongue = false;
+ LLDockableFloater* dockable_floater =
+ dynamic_cast<LLDockableFloater*> (mDockableFloater);
+ if (dockable_floater != NULL)
+ {
+ use_tongue = dockable_floater->getUseTongue();
+ }
+
+ if (mEnabled && use_tongue)
+ {
+ mDockTongue->draw(mDockTongueX, mDockTongueY);
+ }
+}
+
diff --git a/indra/llui/lldockcontrol.h b/indra/llui/lldockcontrol.h
new file mode 100644
index 0000000000..550955c4c5
--- /dev/null
+++ b/indra/llui/lldockcontrol.h
@@ -0,0 +1,99 @@
+/**
+ * @file lldockcontrol.h
+ * @brief Creates a panel of a specific kind for a toast.
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_DOCKCONTROL_H
+#define LL_DOCKCONTROL_H
+
+#include "llerror.h"
+#include "llview.h"
+#include "llfloater.h"
+#include "lluiimage.h"
+
+/**
+ * Provides services for docking of specified floater.
+ * This class should be used in case impossibility deriving from LLDockableFloater.
+ */
+class LLDockControl
+{
+public:
+ enum DocAt
+ {
+ TOP
+ ,LEFT
+ };
+
+public:
+ // callback for a function getting a rect valid for control's position
+ typedef boost::function<void (LLRect& )> get_allowed_rect_callback_t;
+
+ LOG_CLASS(LLDockControl);
+ LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
+ const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_rect_callback = NULL);
+ virtual ~LLDockControl();
+
+public:
+ void on();
+ void off();
+ void forceRecalculatePosition();
+ void setDock(LLView* dockWidget);
+ LLView* getDock()
+ {
+ return mDockWidget;
+ }
+ void repositionDockable();
+ void drawToungue();
+ bool isDockVisible();
+
+ // gets a rect that bounds possible positions for a dockable control (EXT-1111)
+ void getAllowedRect(LLRect& rect);
+
+ S32 getTongueWidth() { return mDockTongue->getWidth(); }
+ S32 getTongueHeight() { return mDockTongue->getHeight(); }
+
+private:
+ virtual void moveDockable();
+private:
+ get_allowed_rect_callback_t mGetAllowedRectCallback;
+ bool mEnabled;
+ bool mRecalculateDocablePosition;
+ bool mDockWidgetVisible;
+ DocAt mDockAt;
+ LLView* mDockWidget;
+ LLRect mPrevDockRect;
+ LLRect mRootRect;
+ LLFloater* mDockableFloater;
+ LLUIImagePtr mDockTongue;
+ S32 mDockTongueX;
+ S32 mDockTongueY;
+};
+
+#endif /* LL_DOCKCONTROL_H */
diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp
index 6c92ea1ff7..a93c666648 100644
--- a/indra/llui/lldraghandle.cpp
+++ b/indra/llui/lldraghandle.cpp
@@ -43,34 +43,46 @@
#include "llmenugl.h"
#include "lltextbox.h"
#include "llcontrol.h"
-#include "llresmgr.h"
#include "llfontgl.h"
#include "llwindow.h"
#include "llfocusmgr.h"
+#include "lluictrlfactory.h"
const S32 LEADING_PAD = 5;
-const S32 TITLE_PAD = 8;
+const S32 TITLE_HPAD = 8;
const S32 BORDER_PAD = 1;
-const S32 LEFT_PAD = BORDER_PAD + TITLE_PAD + LEADING_PAD;
+const S32 LEFT_PAD = BORDER_PAD + TITLE_HPAD + LEADING_PAD;
const S32 RIGHT_PAD = BORDER_PAD + 32; // HACK: space for close btn and minimize btn
S32 LLDragHandle::sSnapMargin = 5;
-LLDragHandle::LLDragHandle( const std::string& name, const LLRect& rect, const std::string& title )
-: LLView( name, rect, TRUE ),
+LLDragHandle::LLDragHandle(const LLDragHandle::Params& p)
+: LLView(p),
mDragLastScreenX( 0 ),
mDragLastScreenY( 0 ),
mLastMouseScreenX( 0 ),
mLastMouseScreenY( 0 ),
- mDragHighlightColor( LLUI::sColorsGroup->getColor( "DefaultHighlightLight" ) ),
- mDragShadowColor( LLUI::sColorsGroup->getColor( "DefaultShadowDark" ) ),
mTitleBox( NULL ),
mMaxTitleWidth( 0 ),
- mForeground( TRUE )
+ mForeground( TRUE ),
+ mDragHighlightColor(p.drag_highlight_color()),
+ mDragShadowColor(p.drag_shadow_color())
+
+{
+ static LLUICachedControl<S32> snap_margin ("SnapMargin", 0);
+ sSnapMargin = snap_margin;
+}
+
+LLDragHandle::~LLDragHandle()
{
- sSnapMargin = LLUI::sConfigGroup->getS32("SnapMargin");
+ removeChild(mTitleBox);
+ delete mTitleBox;
+}
- setSaveToXML(false);
+void LLDragHandle::initFromParams(const LLDragHandle::Params& p)
+{
+ LLView::initFromParams(p);
+ setTitle( p.label );
}
void LLDragHandle::setTitleVisible(BOOL visible)
@@ -81,63 +93,53 @@ void LLDragHandle::setTitleVisible(BOOL visible)
}
}
-void LLDragHandle::setTitleBox(LLTextBox* titlebox)
-{
+void LLDragHandleTop::setTitle(const std::string& title)
+{
+ std::string trimmed_title = title;
+ LLStringUtil::trim(trimmed_title);
+
if( mTitleBox )
{
- removeChild(mTitleBox);
- delete mTitleBox;
+ mTitleBox->setText(trimmed_title);
}
- mTitleBox = titlebox;
- if(mTitleBox)
+ else
{
+ const LLFontGL* font = LLFontGL::getFontSansSerif();
+ LLTextBox::Params params;
+ params.name("Drag Handle Title");
+ params.rect(getRect());
+ params.initial_value(trimmed_title);
+ params.font(font);
+ params.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT | FOLLOWS_RIGHT);
+ params.font_shadow(LLFontGL::DROP_SHADOW_SOFT);
+ params.use_ellipses = true;
+ mTitleBox = LLUICtrlFactory::create<LLTextBox> (params);
addChild( mTitleBox );
}
-}
-
-LLDragHandleTop::LLDragHandleTop(const std::string& name, const LLRect &rect, const std::string& title)
-: LLDragHandle(name, rect, title)
-{
- setFollowsAll();
- setTitle( title );
-}
-
-LLDragHandleLeft::LLDragHandleLeft(const std::string& name, const LLRect &rect, const std::string& title)
-: LLDragHandle(name, rect, title)
-{
- setFollowsAll();
- setTitle( title );
-}
-
-void LLDragHandleTop::setTitle(const std::string& title)
-{
- std::string trimmed_title = title;
- LLStringUtil::trim(trimmed_title);
-
- const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF );
- LLTextBox* titlebox = new LLTextBox( std::string("Drag Handle Title"), getRect(), trimmed_title, font );
- titlebox->setFollows(FOLLOWS_TOP | FOLLOWS_LEFT | FOLLOWS_RIGHT);
- titlebox->setFontStyle(LLFontGL::DROP_SHADOW_SOFT);
- setTitleBox(titlebox);
reshapeTitleBox();
}
-const std::string& LLDragHandleTop::getTitle() const
+std::string LLDragHandleTop::getTitle() const
{
- return getTitleBox() == NULL ? LLStringUtil::null : getTitleBox()->getText();
+ return mTitleBox == NULL ? LLStringUtil::null : mTitleBox->getText();
}
void LLDragHandleLeft::setTitle(const std::string& )
{
- setTitleBox(NULL);
+ if( mTitleBox )
+ {
+ removeChild(mTitleBox);
+ delete mTitleBox;
+ mTitleBox = NULL;
+ }
/* no title on left edge */
}
-const std::string& LLDragHandleLeft::getTitle() const
+std::string LLDragHandleLeft::getTitle() const
{
return LLStringUtil::null;
}
@@ -184,9 +186,9 @@ void LLDragHandleTop::draw()
*/
// Colorize the text to match the frontmost state
- if (getTitleBox())
+ if (mTitleBox)
{
- getTitleBox()->setEnabled(getForeground());
+ mTitleBox->setEnabled(getForeground());
}
LLView::draw();
@@ -229,9 +231,9 @@ void LLDragHandleLeft::draw()
*/
// Colorize the text to match the frontmost state
- if (getTitleBox())
+ if (mTitleBox)
{
- getTitleBox()->setEnabled(getForeground());
+ mTitleBox->setEnabled(getForeground());
}
LLView::draw();
@@ -239,23 +241,25 @@ void LLDragHandleLeft::draw()
void LLDragHandleTop::reshapeTitleBox()
{
- if( ! getTitleBox())
+ static LLUICachedControl<S32> title_vpad("UIFloaterTitleVPad", 0);
+ if( ! mTitleBox)
{
return;
}
- const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF );
- S32 title_width = font->getWidth( getTitleBox()->getText() ) + TITLE_PAD;
+ const LLFontGL* font = LLFontGL::getFontSansSerif();
+ S32 title_width = font->getWidth( mTitleBox->getText() ) + TITLE_HPAD;
if (getMaxTitleWidth() > 0)
title_width = llmin(title_width, getMaxTitleWidth());
S32 title_height = llround(font->getLineHeight());
LLRect title_rect;
title_rect.setLeftTopAndSize(
LEFT_PAD,
- getRect().getHeight() - BORDER_PAD,
+ getRect().getHeight() - title_vpad,
getRect().getWidth() - LEFT_PAD - RIGHT_PAD,
title_height);
- getTitleBox()->setRect( title_rect );
+ // calls reshape on mTitleBox
+ mTitleBox->setShape( title_rect );
}
void LLDragHandleTop::reshape(S32 width, S32 height, BOOL called_from_parent)
@@ -316,6 +320,23 @@ BOOL LLDragHandle::handleHover(S32 x, S32 y, MASK mask)
S32 delta_x = screen_x - mDragLastScreenX;
S32 delta_y = screen_y - mDragLastScreenY;
+ // if dragging a docked floater we want to undock
+ if (((LLFloater*)getParent())->isDocked())
+ {
+ const S32 SLOP = 12;
+
+ if (delta_y <= -SLOP ||
+ delta_y >= SLOP)
+ {
+ ((LLFloater*)getParent())->setDocked(false, false);
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+
LLRect original_rect = getParent()->getRect();
LLRect translated_rect = getParent()->getRect();
translated_rect.translate(delta_x, delta_y);
@@ -337,14 +358,14 @@ BOOL LLDragHandle::handleHover(S32 x, S32 y, MASK mask)
LLView* snap_view = getParent()->findSnapRect(new_rect, mouse_dir, SNAP_PARENT_AND_SIBLINGS, sSnapMargin);
- getParent()->snappedTo(snap_view);
+ getParent()->setSnappedTo(snap_view);
delta_x = new_rect.mLeft - pre_snap_x;
delta_y = new_rect.mBottom - pre_snap_y;
translated_rect.translate(delta_x, delta_y);
// restore original rect so delta are detected, then call user reshape method to handle snapped floaters, etc
getParent()->setRect(original_rect);
- getParent()->userSetShape(translated_rect);
+ getParent()->setShape(translated_rect, true);
mDragLastScreenX += delta_x;
mDragLastScreenY += delta_y;
diff --git a/indra/llui/lldraghandle.h b/indra/llui/lldraghandle.h
index 9eb3e55a6c..dc5410787b 100644
--- a/indra/llui/lldraghandle.h
+++ b/indra/llui/lldraghandle.h
@@ -45,8 +45,25 @@ class LLTextBox;
class LLDragHandle : public LLView
{
public:
- LLDragHandle(const std::string& name, const LLRect& rect, const std::string& title );
- virtual ~LLDragHandle() { setTitleBox(NULL); }
+ struct Params
+ : public LLInitParam::Block<Params, LLView::Params>
+ {
+ Optional<std::string> label;
+ Optional<LLUIColor> drag_highlight_color;
+ Optional<LLUIColor> drag_shadow_color;
+
+ Params()
+ : label("label"),
+ drag_highlight_color("drag_highlight_color", LLUIColorTable::instance().getColor("DefaultHighlightLight")),
+ drag_shadow_color("drag_shadow_color", LLUIColorTable::instance().getColor("DefaultShadowDark"))
+ {
+ mouse_opaque(true);
+ follows.flags(FOLLOWS_ALL);
+ }
+ };
+ void initFromParams(const Params&);
+
+ virtual ~LLDragHandle();
virtual void setValue(const LLSD& value);
@@ -57,25 +74,27 @@ public:
void setTitleVisible(BOOL visible);
virtual void setTitle( const std::string& title ) = 0;
- virtual const std::string& getTitle() const = 0;
+ virtual std::string getTitle() const = 0;
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
protected:
- LLTextBox* getTitleBox() const { return mTitleBox; }
- void setTitleBox(LLTextBox*);
-
+ LLDragHandle(const Params&);
+ friend class LLUICtrlFactory;
+
+protected:
+ LLTextBox* mTitleBox;
+
private:
S32 mDragLastScreenX;
S32 mDragLastScreenY;
S32 mLastMouseScreenX;
S32 mLastMouseScreenY;
LLCoordGL mLastMouseDir;
- LLColor4 mDragHighlightColor;
- LLColor4 mDragShadowColor;
- LLTextBox* mTitleBox;
+ LLUIColor mDragHighlightColor;
+ LLUIColor mDragShadowColor;
S32 mMaxTitleWidth;
BOOL mForeground;
@@ -88,11 +107,12 @@ private:
class LLDragHandleTop
: public LLDragHandle
{
+protected:
+ LLDragHandleTop(const Params& p) : LLDragHandle(p) {}
+ friend class LLUICtrlFactory;
public:
- LLDragHandleTop(const std::string& name, const LLRect& rect, const std::string& title );
-
virtual void setTitle( const std::string& title );
- virtual const std::string& getTitle() const;
+ virtual std::string getTitle() const;
virtual void draw();
virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
@@ -105,11 +125,12 @@ private:
class LLDragHandleLeft
: public LLDragHandle
{
+protected:
+ LLDragHandleLeft(const Params& p) : LLDragHandle(p) {}
+ friend class LLUICtrlFactory;
public:
- LLDragHandleLeft(const std::string& name, const LLRect& rect, const std::string& title );
-
virtual void setTitle( const std::string& title );
- virtual const std::string& getTitle() const;
+ virtual std::string getTitle() const;
virtual void draw();
virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
diff --git a/indra/llui/llf32uictrl.cpp b/indra/llui/llf32uictrl.cpp
new file mode 100644
index 0000000000..0978005b78
--- /dev/null
+++ b/indra/llui/llf32uictrl.cpp
@@ -0,0 +1,57 @@
+/**
+ * @file llf32uictrl.cpp
+ * @author Nat Goodspeed
+ * @date 2008-09-08
+ * @brief Implementation for llf32uictrl.
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llf32uictrl.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+
+LLF32UICtrl::LLF32UICtrl(const Params& p)
+: LLUICtrl(p),
+ mInitialValue(p.initial_value().asReal()),
+ mMinValue(p.min_value),
+ mMaxValue(p.max_value),
+ mIncrement(p.increment)
+{
+ mViewModel->setValue(p.initial_value);
+}
+
+F32 LLF32UICtrl::getValueF32() const
+{
+ return mViewModel->getValue().asReal();
+}
diff --git a/indra/llui/llf32uictrl.h b/indra/llui/llf32uictrl.h
new file mode 100644
index 0000000000..0a54fe761b
--- /dev/null
+++ b/indra/llui/llf32uictrl.h
@@ -0,0 +1,83 @@
+/**
+ * @file llf32uictrl.h
+ * @author Nat Goodspeed
+ * @date 2008-09-08
+ * @brief Base class for float-valued LLUICtrl widgets
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLF32UICTRL_H)
+#define LL_LLF32UICTRL_H
+
+#include "lluictrl.h"
+
+class LLF32UICtrl: public LLUICtrl
+{
+public:
+ struct Params: public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<F32> min_value,
+ max_value,
+ increment;
+
+ Params()
+ : min_value("min_val", 0.f),
+ max_value("max_val", 1.f),
+ increment("increment", 0.1f)
+ {}
+ };
+
+protected:
+ LLF32UICtrl(const Params& p);
+
+public:
+ virtual F32 getValueF32() const;
+
+ virtual void setValue(const LLSD& value ) { mViewModel->setValue(value); }
+ virtual LLSD getValue() const { return LLSD(getValueF32()); }
+
+ virtual void setMinValue(const LLSD& min_value) { setMinValue((F32)min_value.asReal()); }
+ virtual void setMaxValue(const LLSD& max_value) { setMaxValue((F32)max_value.asReal()); }
+
+ virtual F32 getInitialValue() const { return mInitialValue; }
+ virtual F32 getMinValue() const { return mMinValue; }
+ virtual F32 getMaxValue() const { return mMaxValue; }
+ virtual F32 getIncrement() const { return mIncrement; }
+ virtual void setMinValue(F32 min_value) { mMinValue = min_value; }
+ virtual void setMaxValue(F32 max_value) { mMaxValue = max_value; }
+ virtual void setIncrement(F32 increment) { mIncrement = increment;}
+
+protected:
+ F32 mInitialValue;
+ F32 mMinValue;
+ F32 mMaxValue;
+ F32 mIncrement;
+};
+
+#endif /* ! defined(LL_LLF32UICTRL_H) */
diff --git a/indra/llui/llfiltereditor.cpp b/indra/llui/llfiltereditor.cpp
new file mode 100644
index 0000000000..390504234d
--- /dev/null
+++ b/indra/llui/llfiltereditor.cpp
@@ -0,0 +1,51 @@
+/**
+ * @file llfiltereditor.cpp
+ * @brief LLFilterEditor implementation
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Text editor widget to let users enter a single line.
+
+#include "linden_common.h"
+
+#include "llfiltereditor.h"
+
+LLFilterEditor::LLFilterEditor(const LLFilterEditor::Params& p)
+: LLSearchEditor(p)
+{
+}
+
+
+void LLFilterEditor::handleKeystroke()
+{
+ this->LLSearchEditor::handleKeystroke();
+
+ // Commit on every keystroke.
+ onCommit();
+}
diff --git a/indra/llui/llfiltereditor.h b/indra/llui/llfiltereditor.h
new file mode 100644
index 0000000000..c43a76b130
--- /dev/null
+++ b/indra/llui/llfiltereditor.h
@@ -0,0 +1,65 @@
+/**
+ * @file llfiltereditor.h
+ * @brief Text editor widget that represents a filter operation
+ *
+ * Features:
+ * Text entry of a single line (text, delete, left and right arrow, insert, return).
+ * Callbacks either on every keystroke or just on the return key.
+ * Focus (allow multiple text entry widgets)
+ * Clipboard (cut, copy, and paste)
+ * Horizontal scrolling to allow strings longer than widget size allows
+ * Pre-validation (limit which keys can be used)
+ * Optional line history so previous entries can be recalled by CTRL UP/DOWN
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_FILTEREDITOR_H
+#define LL_FILTEREDITOR_H
+
+#include "llsearcheditor.h"
+
+class LLFilterEditor : public LLSearchEditor
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLSearchEditor::Params>
+ {
+ Params()
+ {
+ name = "filter_editor";
+ }
+ };
+
+protected:
+ LLFilterEditor(const Params&);
+ friend class LLUICtrlFactory;
+
+ /*virtual*/ void handleKeystroke();
+};
+
+#endif // LL_FILTEREDITOR_H
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp
new file mode 100644
index 0000000000..3694ecd4f4
--- /dev/null
+++ b/indra/llui/llflatlistview.cpp
@@ -0,0 +1,1062 @@
+/**
+ * @file llflatlistview.cpp
+ * @brief LLFlatListView base class
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llpanel.h"
+#include "lltextbox.h"
+
+#include "llflatlistview.h"
+
+static const LLDefaultChildRegistry::Register<LLFlatListView> flat_list_view("flat_list_view");
+
+const LLSD SELECTED_EVENT = LLSD().with("selected", true);
+const LLSD UNSELECTED_EVENT = LLSD().with("selected", false);
+
+static const std::string COMMENT_TEXTBOX = "comment_text";
+
+//forward declaration
+bool llsds_are_equal(const LLSD& llsd_1, const LLSD& llsd_2);
+
+LLFlatListView::Params::Params()
+: item_pad("item_pad"),
+ allow_select("allow_select"),
+ multi_select("multi_select"),
+ keep_one_selected("keep_one_selected")
+{};
+
+void LLFlatListView::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */)
+{
+ LLScrollContainer::reshape(width, height, called_from_parent);
+ setItemsNoScrollWidth(width);
+ rearrangeItems();
+}
+
+const LLRect& LLFlatListView::getItemsRect() const
+{
+ return mItemsPanel->getRect();
+}
+
+bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null*/, EAddPosition pos /*= ADD_BOTTOM*/,bool rearrange /*= true*/)
+{
+ if (!item) return false;
+ if (value.isUndefined()) return false;
+
+ //force uniqueness of items, easiest check but unreliable
+ if (item->getParent() == mItemsPanel) return false;
+
+ item_pair_t* new_pair = new item_pair_t(item, value);
+ switch (pos)
+ {
+ case ADD_TOP:
+ mItemPairs.push_front(new_pair);
+ //in LLView::draw() children are iterated in backorder
+ mItemsPanel->addChildInBack(item);
+ break;
+ case ADD_BOTTOM:
+ mItemPairs.push_back(new_pair);
+ mItemsPanel->addChild(item);
+ break;
+ default:
+ break;
+ }
+
+ //_4 is for MASK
+ item->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4));
+ item->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, new_pair, _4));
+
+ // Children don't accept the focus
+ item->setTabStop(false);
+
+ if (rearrange)
+ {
+ rearrangeItems();
+ notifyParentItemsRectChanged();
+ }
+ return true;
+}
+
+
+bool LLFlatListView::insertItemAfter(LLPanel* after_item, LLPanel* item_to_add, const LLSD& value /*= LLUUID::null*/)
+{
+ if (!after_item) return false;
+ if (!item_to_add) return false;
+ if (value.isUndefined()) return false;
+
+ if (mItemPairs.empty()) return false;
+
+ //force uniqueness of items, easiest check but unreliable
+ if (item_to_add->getParent() == mItemsPanel) return false;
+
+ item_pair_t* after_pair = getItemPair(after_item);
+ if (!after_pair) return false;
+
+ item_pair_t* new_pair = new item_pair_t(item_to_add, value);
+ if (after_pair == mItemPairs.back())
+ {
+ mItemPairs.push_back(new_pair);
+ mItemsPanel->addChild(item_to_add);
+ }
+ else
+ {
+ pairs_iterator_t it = mItemPairs.begin();
+ for (; it != mItemPairs.end(); ++it)
+ {
+ if (*it == after_pair)
+ {
+ // insert new elements before the element at position of passed iterator.
+ mItemPairs.insert(++it, new_pair);
+ mItemsPanel->addChild(item_to_add);
+ break;
+ }
+ }
+ }
+
+ //_4 is for MASK
+ item_to_add->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4));
+ item_to_add->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, new_pair, _4));
+
+ rearrangeItems();
+ notifyParentItemsRectChanged();
+ return true;
+}
+
+
+bool LLFlatListView::removeItem(LLPanel* item)
+{
+ if (!item) return false;
+ if (item->getParent() != mItemsPanel) return false;
+
+ item_pair_t* item_pair = getItemPair(item);
+ if (!item_pair) return false;
+
+ return removeItemPair(item_pair);
+}
+
+bool LLFlatListView::removeItemByValue(const LLSD& value)
+{
+ if (value.isUndefined()) return false;
+
+ item_pair_t* item_pair = getItemPair(value);
+ if (!item_pair) return false;
+
+ return removeItemPair(item_pair);
+}
+
+bool LLFlatListView::removeItemByUUID(const LLUUID& uuid)
+{
+ return removeItemByValue(LLSD(uuid));
+}
+
+LLPanel* LLFlatListView::getItemByValue(const LLSD& value) const
+{
+ if (value.isUndefined()) return NULL;
+
+ item_pair_t* pair = getItemPair(value);
+ if (pair) return pair->first;
+ return NULL;
+}
+
+bool LLFlatListView::selectItem(LLPanel* item, bool select /*= true*/)
+{
+ if (!item) return false;
+ if (item->getParent() != mItemsPanel) return false;
+
+ item_pair_t* item_pair = getItemPair(item);
+ if (!item_pair) return false;
+
+ return selectItemPair(item_pair, select);
+}
+
+bool LLFlatListView::selectItemByValue(const LLSD& value, bool select /*= true*/)
+{
+ if (value.isUndefined()) return false;
+
+ item_pair_t* item_pair = getItemPair(value);
+ if (!item_pair) return false;
+
+ return selectItemPair(item_pair, select);
+}
+
+bool LLFlatListView::selectItemByUUID(const LLUUID& uuid, bool select /* = true*/)
+{
+ return selectItemByValue(LLSD(uuid), select);
+}
+
+
+LLSD LLFlatListView::getSelectedValue() const
+{
+ if (mSelectedItemPairs.empty()) return LLSD();
+
+ item_pair_t* first_selected_pair = mSelectedItemPairs.front();
+ return first_selected_pair->second;
+}
+
+void LLFlatListView::getSelectedValues(std::vector<LLSD>& selected_values) const
+{
+ if (mSelectedItemPairs.empty()) return;
+
+ for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it)
+ {
+ selected_values.push_back((*it)->second);
+ }
+}
+
+LLUUID LLFlatListView::getSelectedUUID() const
+{
+ const LLSD& value = getSelectedValue();
+ if (value.isDefined() && value.isUUID())
+ {
+ return value.asUUID();
+ }
+ else
+ {
+ return LLUUID::null;
+ }
+}
+
+void LLFlatListView::getSelectedUUIDs(std::vector<LLUUID>& selected_uuids) const
+{
+ if (mSelectedItemPairs.empty()) return;
+
+ for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it)
+ {
+ selected_uuids.push_back((*it)->second.asUUID());
+ }
+}
+
+LLPanel* LLFlatListView::getSelectedItem() const
+{
+ if (mSelectedItemPairs.empty()) return NULL;
+
+ return mSelectedItemPairs.front()->first;
+}
+
+void LLFlatListView::getSelectedItems(std::vector<LLPanel*>& selected_items) const
+{
+ if (mSelectedItemPairs.empty()) return;
+
+ for (pairs_const_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it)
+ {
+ selected_items.push_back((*it)->first);
+ }
+}
+
+void LLFlatListView::resetSelection(bool no_commit_on_deselection /*= false*/)
+{
+ if (mSelectedItemPairs.empty()) return;
+
+ for (pairs_iterator_t it= mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it)
+ {
+ item_pair_t* pair_to_deselect = *it;
+ LLPanel* item = pair_to_deselect->first;
+ item->setValue(UNSELECTED_EVENT);
+ }
+
+ mSelectedItemPairs.clear();
+
+ if (mCommitOnSelectionChange && !no_commit_on_deselection)
+ {
+ onCommit();
+ }
+
+ // Stretch selected items rect to ensure it won't be clipped
+ mSelectedItemsBorder->setRect(getSelectedItemsRect().stretch(-1));
+}
+
+void LLFlatListView::setNoItemsCommentText(const std::string& comment_text)
+{
+ if (NULL == mNoItemsCommentTextbox)
+ {
+ LLRect comment_rect = getRect();
+ comment_rect.setOriginAndSize(0, 0, comment_rect.getWidth(), comment_rect.getHeight());
+ comment_rect.stretch(-getBorderWidth());
+ LLTextBox::Params text_p;
+ text_p.name(COMMENT_TEXTBOX);
+ text_p.border_visible(false);
+ text_p.rect(comment_rect);
+ text_p.follows.flags(FOLLOWS_ALL);
+ mNoItemsCommentTextbox = LLUICtrlFactory::create<LLTextBox>(text_p, this);
+ }
+
+ mNoItemsCommentTextbox->setValue(comment_text);
+}
+
+void LLFlatListView::clear()
+{
+ // do not use LLView::deleteAllChildren to avoid removing nonvisible items. drag-n-drop for ex.
+ for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it)
+ {
+ mItemsPanel->removeChild((*it)->first);
+ (*it)->first->die();
+ delete *it;
+ }
+ mItemPairs.clear();
+ mSelectedItemPairs.clear();
+
+ // also set items panel height to zero. Reshape it to allow reshaping of non-item children
+ LLRect rc = mItemsPanel->getRect();
+ rc.mBottom = rc.mTop;
+ mItemsPanel->reshape(rc.getWidth(), rc.getHeight());
+ mItemsPanel->setRect(rc);
+
+ setNoItemsCommentVisible(true);
+ notifyParentItemsRectChanged();
+}
+
+void LLFlatListView::sort()
+{
+ if (!mItemComparator)
+ {
+ llwarns << "No comparator specified for sorting FlatListView items." << llendl;
+ return;
+ }
+
+ mItemPairs.sort(ComparatorAdaptor(*mItemComparator));
+ rearrangeItems();
+}
+
+bool LLFlatListView::updateValue(const LLSD& old_value, const LLSD& new_value)
+{
+ if (old_value.isUndefined() || new_value.isUndefined()) return false;
+ if (llsds_are_equal(old_value, new_value)) return false;
+
+ item_pair_t* item_pair = getItemPair(old_value);
+ if (!item_pair) return false;
+
+ item_pair->second = new_value;
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// PROTECTED STUFF
+//////////////////////////////////////////////////////////////////////////
+
+
+LLFlatListView::LLFlatListView(const LLFlatListView::Params& p)
+: LLScrollContainer(p)
+ , mItemComparator(NULL)
+ , mItemsPanel(NULL)
+ , mItemPad(p.item_pad)
+ , mAllowSelection(p.allow_select)
+ , mMultipleSelection(p.multi_select)
+ , mKeepOneItemSelected(p.keep_one_selected)
+ , mCommitOnSelectionChange(false)
+ , mPrevNotifyParentRect(LLRect())
+ , mNoItemsCommentTextbox(NULL)
+{
+ mBorderThickness = getBorderWidth();
+
+ LLRect scroll_rect = getRect();
+ LLRect items_rect;
+
+ setItemsNoScrollWidth(scroll_rect.getWidth());
+ items_rect.setLeftTopAndSize(mBorderThickness, scroll_rect.getHeight() - mBorderThickness, mItemsNoScrollWidth, 0);
+
+ LLPanel::Params pp;
+ pp.rect(items_rect);
+ mItemsPanel = LLUICtrlFactory::create<LLPanel> (pp);
+ addChild(mItemsPanel);
+
+ //we don't need to stretch in vertical direction on reshaping by a parent
+ //no bottom following!
+ mItemsPanel->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP);
+
+ LLViewBorder::Params params;
+ params.name("scroll border");
+ params.rect(getSelectedItemsRect());
+ params.visible(false);
+ params.bevel_style(LLViewBorder::BEVEL_IN);
+ mSelectedItemsBorder = LLUICtrlFactory::create<LLViewBorder> (params);
+ mItemsPanel->addChild( mSelectedItemsBorder );
+};
+
+// virtual
+void LLFlatListView::draw()
+{
+ // Highlight border if a child of this container has keyboard focus
+ if( mSelectedItemsBorder->getVisible() )
+ {
+ mSelectedItemsBorder->setKeyboardFocusHighlight( hasFocus() );
+ }
+ LLScrollContainer::draw();
+}
+
+// virtual
+BOOL LLFlatListView::postBuild()
+{
+ setTabStop(true);
+ return LLScrollContainer::postBuild();
+}
+
+void LLFlatListView::rearrangeItems()
+{
+ static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+
+ setNoItemsCommentVisible(mItemPairs.empty());
+
+ if (mItemPairs.empty()) return;
+
+ //calculating required height - assuming items can be of different height
+ //list should accommodate all its items
+ S32 height = 0;
+
+ S32 invisible_children_count = 0;
+ pairs_iterator_t it = mItemPairs.begin();
+ for (; it != mItemPairs.end(); ++it)
+ {
+ LLPanel* item = (*it)->first;
+
+ // skip invisible child
+ if (!item->getVisible())
+ {
+ ++invisible_children_count;
+ continue;
+ }
+
+ height += item->getRect().getHeight();
+ }
+
+ // add paddings between items, excluding invisible ones
+ height += mItemPad * (mItemPairs.size() - invisible_children_count - 1);
+
+ LLRect rc = mItemsPanel->getRect();
+ S32 width = mItemsNoScrollWidth;
+
+ // update width to avoid horizontal scrollbar
+ if (height > getRect().getHeight() - 2 * mBorderThickness)
+ width -= scrollbar_size;
+
+ //changes the bottom, end of the list goes down in the scroll container
+ rc.setLeftTopAndSize(rc.mLeft, rc.mTop, width, height);
+ mItemsPanel->setRect(rc);
+
+ //reshaping items
+ S32 item_new_top = height;
+ pairs_iterator_t it2, first_it = mItemPairs.begin();
+ for (it2 = first_it; it2 != mItemPairs.end(); ++it2)
+ {
+ LLPanel* item = (*it2)->first;
+
+ // skip invisible child
+ if (!item->getVisible())
+ continue;
+
+ LLRect rc = item->getRect();
+ rc.setLeftTopAndSize(rc.mLeft, item_new_top, width, rc.getHeight());
+ item->reshape(rc.getWidth(), rc.getHeight());
+ item->setRect(rc);
+
+ // move top for next item in list
+ item_new_top -= (rc.getHeight() + mItemPad);
+ }
+
+ // Stretch selected items rect to ensure it won't be clipped
+ mSelectedItemsBorder->setRect(getSelectedItemsRect().stretch(-1));
+}
+
+void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask)
+{
+ if (!item_pair) return;
+
+ setFocus(TRUE);
+
+ bool select_item = !isSelected(item_pair);
+
+ //*TODO find a better place for that enforcing stuff
+ if (mKeepOneItemSelected && numSelected() == 1 && !select_item) return;
+
+ if (!(mask & MASK_CONTROL) || !mMultipleSelection) resetSelection();
+ selectItemPair(item_pair, select_item);
+}
+
+void LLFlatListView::onItemRightMouseClick(item_pair_t* item_pair, MASK mask)
+{
+ if (!item_pair)
+ return;
+
+ // Forbid deselecting of items on right mouse button click if mMultipleSelection flag is set on,
+ // because some of derived classes may have context menu and selected items must be kept.
+ if ( !(mask & MASK_CONTROL) && mMultipleSelection && isSelected(item_pair) )
+ return;
+
+ // else got same behavior as at onItemMouseClick
+ onItemMouseClick(item_pair, mask);
+}
+
+BOOL LLFlatListView::handleKeyHere(KEY key, MASK mask)
+{
+ BOOL reset_selection = (mask != MASK_SHIFT);
+ BOOL handled = FALSE;
+ switch (key)
+ {
+ case KEY_RETURN:
+ {
+ if (mSelectedItemPairs.size() && mask == MASK_NONE)
+ {
+ mOnReturnSignal(this, getValue());
+ handled = TRUE;
+ }
+ break;
+ }
+ case KEY_UP:
+ {
+ if ( !selectNextItemPair(true, reset_selection) && reset_selection)
+ {
+ // If case we are in accordion tab notify parent to go to the previous accordion
+ if(notifyParent(LLSD().with("action","select_prev")) > 0 )//message was processed
+ resetSelection();
+ }
+ break;
+ }
+ case KEY_DOWN:
+ {
+ if ( !selectNextItemPair(false, reset_selection) && reset_selection)
+ {
+ // If case we are in accordion tab notify parent to go to the next accordion
+ if( notifyParent(LLSD().with("action","select_next")) > 0 ) //message was processed
+ resetSelection();
+ }
+ break;
+ }
+ case 'A':
+ {
+ if(MASK_CONTROL & mask)
+ {
+ selectAll();
+ handled = TRUE;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ if ( ( key == KEY_UP || key == KEY_DOWN ) && mSelectedItemPairs.size() )
+ {
+ ensureSelectedVisible();
+ /*
+ LLRect visible_rc = getVisibleContentRect();
+ LLRect selected_rc = getLastSelectedItemRect();
+
+ if ( !visible_rc.contains (selected_rc) )
+ {
+ // But scroll in Items panel coordinates
+ scrollToShowRect(selected_rc);
+ }
+
+ // In case we are in accordion tab notify parent to show selected rectangle
+ LLRect screen_rc;
+ localRectToScreen(selected_rc, &screen_rc);
+ notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue()));*/
+
+ handled = TRUE;
+ }
+
+ return handled ? handled : LLScrollContainer::handleKeyHere(key, mask);
+}
+
+LLFlatListView::item_pair_t* LLFlatListView::getItemPair(LLPanel* item) const
+{
+ llassert(item);
+
+ for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it)
+ {
+ item_pair_t* item_pair = *it;
+ if (item_pair->first == item) return item_pair;
+ }
+ return NULL;
+}
+
+//compares two LLSD's
+bool llsds_are_equal(const LLSD& llsd_1, const LLSD& llsd_2)
+{
+ llassert(llsd_1.isDefined());
+ llassert(llsd_2.isDefined());
+
+ if (llsd_1.type() != llsd_2.type()) return false;
+
+ if (!llsd_1.isMap())
+ {
+ if (llsd_1.isUUID()) return llsd_1.asUUID() == llsd_2.asUUID();
+
+ //assumptions that string representaion is enough for other types
+ return llsd_1.asString() == llsd_2.asString();
+ }
+
+ if (llsd_1.size() != llsd_2.size()) return false;
+
+ LLSD::map_const_iterator llsd_1_it = llsd_1.beginMap();
+ LLSD::map_const_iterator llsd_2_it = llsd_2.beginMap();
+ for (S32 i = 0; i < llsd_1.size(); ++i)
+ {
+ if ((*llsd_1_it).first != (*llsd_2_it).first) return false;
+ if (!llsds_are_equal((*llsd_1_it).second, (*llsd_2_it).second)) return false;
+ ++llsd_1_it;
+ ++llsd_2_it;
+ }
+ return true;
+}
+
+LLFlatListView::item_pair_t* LLFlatListView::getItemPair(const LLSD& value) const
+{
+ llassert(value.isDefined());
+
+ for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it)
+ {
+ item_pair_t* item_pair = *it;
+ if (llsds_are_equal(item_pair->second, value)) return item_pair;
+ }
+ return NULL;
+}
+
+bool LLFlatListView::selectItemPair(item_pair_t* item_pair, bool select)
+{
+ llassert(item_pair);
+
+ if (!mAllowSelection && select) return false;
+
+ if (isSelected(item_pair) == select) return true; //already in specified selection state
+ if (select)
+ {
+ mSelectedItemPairs.push_back(item_pair);
+ }
+ else
+ {
+ mSelectedItemPairs.remove(item_pair);
+ }
+
+ //a way of notifying panel of selection state changes
+ LLPanel* item = item_pair->first;
+ item->setValue(select ? SELECTED_EVENT : UNSELECTED_EVENT);
+
+ if (mCommitOnSelectionChange)
+ {
+ onCommit();
+ }
+
+ // Stretch selected items rect to ensure it won't be clipped
+ mSelectedItemsBorder->setRect(getSelectedItemsRect().stretch(-1));
+
+ return true;
+}
+
+LLRect LLFlatListView::getLastSelectedItemRect()
+{
+ if (!mSelectedItemPairs.size())
+ {
+ return LLRect::null;
+ }
+
+ return mSelectedItemPairs.back()->first->getRect();
+}
+
+LLRect LLFlatListView::getSelectedItemsRect()
+{
+ if (!mSelectedItemPairs.size())
+ {
+ return LLRect::null;
+ }
+ LLRect rc = getLastSelectedItemRect();
+ for ( pairs_const_iterator_t
+ it = mSelectedItemPairs.begin(),
+ it_end = mSelectedItemPairs.end();
+ it != it_end; ++it )
+ {
+ rc.unionWith((*it)->first->getRect());
+ }
+ return rc;
+}
+
+void LLFlatListView::selectFirstItem ()
+{
+ selectItemPair(mItemPairs.front(), true);
+ ensureSelectedVisible();
+}
+
+void LLFlatListView::selectLastItem ()
+{
+ selectItemPair(mItemPairs.back(), true);
+ ensureSelectedVisible();
+}
+
+void LLFlatListView::ensureSelectedVisible()
+{
+ LLRect selected_rc = getLastSelectedItemRect();
+
+ if ( selected_rc.isValid() )
+ {
+ scrollToShowRect(selected_rc);
+ }
+}
+
+
+// virtual
+bool LLFlatListView::selectNextItemPair(bool is_up_direction, bool reset_selection)
+{
+ // No items - no actions!
+ if ( !mItemPairs.size() )
+ return false;
+
+
+ item_pair_t* to_sel_pair = NULL;
+ item_pair_t* cur_sel_pair = NULL;
+ if ( mSelectedItemPairs.size() )
+ {
+ // Take the last selected pair
+ cur_sel_pair = mSelectedItemPairs.back();
+ // Bases on given direction choose next item to select
+ if ( is_up_direction )
+ {
+ // Find current selected item position in mItemPairs list
+ pairs_list_t::reverse_iterator sel_it = std::find(mItemPairs.rbegin(), mItemPairs.rend(), cur_sel_pair);
+
+ for (;++sel_it != mItemPairs.rend();)
+ {
+ // skip invisible items
+ if ( (*sel_it)->first->getVisible() )
+ {
+ to_sel_pair = *sel_it;
+ break;
+ }
+ }
+ }
+ else
+ {
+ // Find current selected item position in mItemPairs list
+ pairs_list_t::iterator sel_it = std::find(mItemPairs.begin(), mItemPairs.end(), cur_sel_pair);
+
+ for (;++sel_it != mItemPairs.end();)
+ {
+ // skip invisible items
+ if ( (*sel_it)->first->getVisible() )
+ {
+ to_sel_pair = *sel_it;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ // If there weren't selected items then choose the first one bases on given direction
+ cur_sel_pair = (is_up_direction) ? mItemPairs.back() : mItemPairs.front();
+ // Force selection to first item
+ to_sel_pair = cur_sel_pair;
+ }
+
+
+ if ( to_sel_pair )
+ {
+ bool select = true;
+
+ if ( reset_selection )
+ {
+ // Reset current selection if we were asked about it
+ resetSelection();
+ }
+ else
+ {
+ // If item already selected and no reset request than we should deselect last selected item.
+ select = (mSelectedItemPairs.end() == std::find(mSelectedItemPairs.begin(), mSelectedItemPairs.end(), to_sel_pair));
+ }
+
+ // Select/Deselect next item
+ selectItemPair(select ? to_sel_pair : cur_sel_pair, select);
+
+ return true;
+ }
+ return false;
+}
+
+bool LLFlatListView::selectAll()
+{
+ if (!mAllowSelection)
+ return false;
+
+ mSelectedItemPairs.clear();
+
+ for (pairs_const_iterator_t it= mItemPairs.begin(); it != mItemPairs.end(); ++it)
+ {
+ item_pair_t* item_pair = *it;
+ mSelectedItemPairs.push_back(item_pair);
+ //a way of notifying panel of selection state changes
+ LLPanel* item = item_pair->first;
+ item->setValue(SELECTED_EVENT);
+ }
+
+ if (mCommitOnSelectionChange)
+ {
+ onCommit();
+ }
+
+ // Stretch selected items rect to ensure it won't be clipped
+ mSelectedItemsBorder->setRect(getSelectedItemsRect().stretch(-1));
+
+ return true;
+}
+
+bool LLFlatListView::isSelected(item_pair_t* item_pair) const
+{
+ llassert(item_pair);
+
+ pairs_const_iterator_t it_end = mSelectedItemPairs.end();
+ return std::find(mSelectedItemPairs.begin(), it_end, item_pair) != it_end;
+}
+
+bool LLFlatListView::removeItemPair(item_pair_t* item_pair)
+{
+ llassert(item_pair);
+
+ bool deleted = false;
+ for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it)
+ {
+ item_pair_t* _item_pair = *it;
+ if (_item_pair == item_pair)
+ {
+ mItemPairs.erase(it);
+ deleted = true;
+ break;
+ }
+ }
+
+ if (!deleted) return false;
+
+ for (pairs_iterator_t it = mSelectedItemPairs.begin(); it != mSelectedItemPairs.end(); ++it)
+ {
+ item_pair_t* selected_item_pair = *it;
+ if (selected_item_pair == item_pair)
+ {
+ it = mSelectedItemPairs.erase(it);
+ break;
+ }
+ }
+
+ mItemsPanel->removeChild(item_pair->first);
+ item_pair->first->die();
+ delete item_pair;
+
+ rearrangeItems();
+ notifyParentItemsRectChanged();
+
+ return true;
+}
+
+void LLFlatListView::notifyParentItemsRectChanged()
+{
+ S32 comment_height = 0;
+
+ // take into account comment text height if exists
+ if (mNoItemsCommentTextbox && mNoItemsCommentTextbox->getVisible())
+ {
+ comment_height = mNoItemsCommentTextbox->getTextPixelHeight();
+ }
+
+ LLRect req_rect = getItemsRect();
+
+ // get maximum of items total height and comment text height
+ req_rect.setOriginAndSize(req_rect.mLeft, req_rect.mBottom, req_rect.getWidth(), llmax(req_rect.getHeight(), comment_height));
+
+ // take into account border size.
+ req_rect.stretch(getBorderWidth());
+
+ if (req_rect == mPrevNotifyParentRect)
+ return;
+
+ mPrevNotifyParentRect = req_rect;
+
+ LLSD params;
+ params["action"] = "size_changes";
+ params["width"] = req_rect.getWidth();
+ params["height"] = req_rect.getHeight();
+
+ if (getParent()) // dummy widgets don't have a parent
+ getParent()->notifyParent(params);
+}
+
+void LLFlatListView::setNoItemsCommentVisible(bool visible) const
+{
+ if (mNoItemsCommentTextbox)
+ {
+ if (visible)
+ {
+ // We have to update child rect here because of issues with rect after reshaping while creating LLTextbox
+ // It is possible to have invalid LLRect if Flat List is in LLAccordionTab
+ LLRect comment_rect = getLocalRect();
+
+ // To see comment correctly (EXT - 3244) in mNoItemsCommentTextbox we must get border width
+ // of LLFlatListView (@see getBorderWidth()) and stretch mNoItemsCommentTextbox to this width
+ // But getBorderWidth() returns 0 if LLFlatListView not visible. So we have to get border width
+ // from 'scroll_border'
+ LLViewBorder* scroll_border = getChild<LLViewBorder>("scroll border");
+ comment_rect.stretch(-scroll_border->getBorderWidth());
+ mNoItemsCommentTextbox->setRect(comment_rect);
+ }
+ mNoItemsCommentTextbox->setVisible(visible);
+ }
+}
+
+void LLFlatListView::getItems(std::vector<LLPanel*>& items) const
+{
+ if (mItemPairs.empty()) return;
+
+ items.clear();
+ for (pairs_const_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it)
+ {
+ items.push_back((*it)->first);
+ }
+}
+
+void LLFlatListView::getValues(std::vector<LLSD>& values) const
+{
+ if (mItemPairs.empty()) return;
+
+ values.clear();
+ for (pairs_const_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it)
+ {
+ values.push_back((*it)->second);
+ }
+}
+
+// virtual
+void LLFlatListView::onFocusReceived()
+{
+ mSelectedItemsBorder->setVisible(TRUE);
+}
+// virtual
+void LLFlatListView::onFocusLost()
+{
+ mSelectedItemsBorder->setVisible(FALSE);
+}
+
+//virtual
+S32 LLFlatListView::notify(const LLSD& info)
+{
+ if(info.has("action"))
+ {
+ std::string str_action = info["action"];
+ if(str_action == "select_first")
+ {
+ setFocus(true);
+ selectFirstItem();
+ return 1;
+ }
+ else if(str_action == "select_last")
+ {
+ setFocus(true);
+ selectLastItem();
+ return 1;
+ }
+ }
+ else if (info.has("rearrange"))
+ {
+ rearrangeItems();
+ notifyParentItemsRectChanged();
+ return 1;
+ }
+ return 0;
+}
+
+void LLFlatListView::detachItems(std::vector<LLPanel*>& detached_items)
+{
+ LLSD action;
+ action.with("detach", LLSD());
+ // Clear detached_items list
+ detached_items.clear();
+ // Go through items and detach valid items, remove them from items panel
+ // and add to detached_items.
+ for (pairs_iterator_t
+ iter = mItemPairs.begin(),
+ iter_end = mItemPairs.end();
+ iter != iter_end; ++iter)
+ {
+ LLPanel* pItem = (*iter)->first;
+ if (1 == pItem->notify(action))
+ {
+ selectItemPair((*iter), false);
+ mItemsPanel->removeChild(pItem);
+ detached_items.push_back(pItem);
+ }
+ }
+ if (!detached_items.empty())
+ {
+ // Some items were detached, clean ourself from unusable memory
+ if (detached_items.size() == mItemPairs.size())
+ {
+ // This way will be faster if all items were disconnected
+ for (pairs_iterator_t
+ iter = mItemPairs.begin(),
+ iter_end = mItemPairs.end();
+ iter != iter_end; ++iter)
+ {
+ (*iter)->first = NULL;
+ delete *iter;
+ }
+ mItemPairs.clear();
+ // Also set items panel height to zero.
+ // Reshape it to allow reshaping of non-item children.
+ LLRect rc = mItemsPanel->getRect();
+ rc.mBottom = rc.mTop;
+ mItemsPanel->reshape(rc.getWidth(), rc.getHeight());
+ mItemsPanel->setRect(rc);
+ setNoItemsCommentVisible(true);
+ }
+ else
+ {
+ for (std::vector<LLPanel*>::const_iterator
+ detached_iter = detached_items.begin(),
+ detached_iter_end = detached_items.end();
+ detached_iter != detached_iter_end; ++detached_iter)
+ {
+ LLPanel* pDetachedItem = *detached_iter;
+ for (pairs_iterator_t
+ iter = mItemPairs.begin(),
+ iter_end = mItemPairs.end();
+ iter != iter_end; ++iter)
+ {
+ item_pair_t* item_pair = *iter;
+ if (item_pair->first == pDetachedItem)
+ {
+ mItemPairs.erase(iter);
+ item_pair->first = NULL;
+ delete item_pair;
+ break;
+ }
+ }
+ }
+ rearrangeItems();
+ }
+ notifyParentItemsRectChanged();
+ }
+}
+
+//EOF
diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h
new file mode 100644
index 0000000000..5999e79f61
--- /dev/null
+++ b/indra/llui/llflatlistview.h
@@ -0,0 +1,430 @@
+/**
+ * @file llflatlistview.h
+ * @brief LLFlatListView base class
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLATLISTVIEW_H
+#define LL_LLFLATLISTVIEW_H
+
+#include "llpanel.h"
+#include "llscrollcontainer.h"
+
+class LLTextBox;
+
+/**
+ * LLFlatListView represents a flat list ui control that operates on items in a form of LLPanel's.
+ * LLSD can be associated with each added item, it can keep data from an item in digested form.
+ * Associated LLSD's can be of any type (singular, a map etc.).
+ * Items (LLPanel's subclasses) can be of different height.
+ * The list is LLPanel created in itself and grows in height while new items are added.
+ *
+ * The control can manage selection of its items when the flag "allow_select" is set. Also ability to select
+ * multiple items (by using CTRL) is enabled through setting the flag "multi_select" - if selection is not allowed that flag
+ * is ignored. The option "keep_one_selected" forces at least one item to be selected at any time (only for mouse events on items)
+ * since any item of the list was selected.
+ *
+ * Examples of using this control are presented in Picks panel (My Profile and Profile View), where this control is used to
+ * manage the list of pick items.
+ *
+ * ASSUMPTIONS AND STUFF
+ * - NULL pointers and undefined LLSD's are not accepted by any method of this class unless specified otherwise
+ * - Order of returned selected items are not guaranteed
+ * - The control assumes that all items being added are unique.
+ */
+class LLFlatListView : public LLScrollContainer
+{
+public:
+
+ /**
+ * Abstract comparator for comparing flat list items in a form of LLPanel
+ */
+ class ItemComparator
+ {
+ public:
+ ItemComparator() {};
+ virtual ~ItemComparator() {};
+
+ /** Returns true if item1 < item2, false otherwise */
+ virtual bool compare(const LLPanel* item1, const LLPanel* item2) const = 0;
+ };
+
+ /**
+ * Represents reverse comparator which acts as a decorator for a comparator that need to be reversed
+ */
+ class ItemReverseComparator : public ItemComparator
+ {
+ public:
+ ItemReverseComparator(const ItemComparator& comparator) : mComparator(comparator) {};
+ virtual ~ItemReverseComparator() {};
+
+ virtual bool compare(const LLPanel* item1, const LLPanel* item2) const
+ {
+ return mComparator.compare(item2, item1);
+ }
+
+ private:
+ const ItemComparator& mComparator;
+ };
+
+
+ struct Params : public LLInitParam::Block<Params, LLScrollContainer::Params>
+ {
+ /** turning on/off selection support */
+ Optional<bool> allow_select;
+
+ /** turning on/off multiple selection (works while clicking and holding CTRL)*/
+ Optional<bool> multi_select;
+
+ /** don't allow to deselect all selected items (for mouse events on items only) */
+ Optional<bool> keep_one_selected;
+
+ /** padding between items */
+ Optional<U32> item_pad;
+
+ Params();
+ };
+
+ virtual ~LLFlatListView() { clear(); };
+
+ /**
+ * Connects callback to signal called when Return key is pressed.
+ */
+ boost::signals2::connection setReturnCallback( const commit_signal_t::slot_type& cb ) { return mOnReturnSignal.connect(cb); }
+
+ /** Overridden LLPanel's reshape, height is ignored, the list sets its height to accommodate all items */
+ virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+ /** Returns full rect of child panel */
+ const LLRect& getItemsRect() const;
+
+ LLRect getRequiredRect() { return getItemsRect(); }
+
+ /** Returns distance between items */
+ const S32 getItemsPad() { return mItemPad; }
+
+ /**
+ * Adds and item and LLSD value associated with it to the list at specified position
+ * @return true if the item was added, false otherwise
+ */
+ virtual bool addItem(LLPanel * item, const LLSD& value = LLUUID::null, EAddPosition pos = ADD_BOTTOM, bool rearrange = true);
+
+ /**
+ * Insert item_to_add along with associated value to the list right after the after_item.
+ * @return true if the item was successfully added, false otherwise
+ */
+ virtual bool insertItemAfter(LLPanel* after_item, LLPanel* item_to_add, const LLSD& value = LLUUID::null);
+
+ /**
+ * Remove specified item
+ * @return true if the item was removed, false otherwise
+ */
+ virtual bool removeItem(LLPanel* item);
+
+ /**
+ * Remove an item specified by value
+ * @return true if the item was removed, false otherwise
+ */
+ virtual bool removeItemByValue(const LLSD& value);
+
+ /**
+ * Remove an item specified by uuid
+ * @return true if the item was removed, false otherwise
+ */
+ virtual bool removeItemByUUID(const LLUUID& uuid);
+
+ /**
+ * Get an item by value
+ * @return the item as LLPanel if associated with value, NULL otherwise
+ */
+ virtual LLPanel* getItemByValue(const LLSD& value) const;
+
+ template<class T>
+ T* getTypedItemByValue(const LLSD& value) const
+ {
+ return dynamic_cast<T*>(getItemByValue(value));
+ }
+
+ /**
+ * Select or deselect specified item based on select
+ * @return true if succeed, false otherwise
+ */
+ virtual bool selectItem(LLPanel* item, bool select = true);
+
+ /**
+ * Select or deselect an item by associated value based on select
+ * @return true if succeed, false otherwise
+ */
+ virtual bool selectItemByValue(const LLSD& value, bool select = true);
+
+ /**
+ * Select or deselect an item by associated uuid based on select
+ * @return true if succeed, false otherwise
+ */
+ virtual bool selectItemByUUID(const LLUUID& uuid, bool select = true);
+
+ /**
+ * Get all panels stored in the list.
+ */
+ virtual void getItems(std::vector<LLPanel*>& items) const;
+
+ /**
+ * Get all items values.
+ */
+ virtual void getValues(std::vector<LLSD>& values) const;
+
+ /**
+ * Get LLSD associated with the first selected item
+ */
+ virtual LLSD getSelectedValue() const;
+
+ /**
+ * Get LLSD's associated with selected items.
+ * @param selected_values std::vector being populated with LLSD associated with selected items
+ */
+ virtual void getSelectedValues(std::vector<LLSD>& selected_values) const;
+
+
+ /**
+ * Get LLUUID associated with selected item
+ * @return LLUUID if such was associated with selected item
+ */
+ virtual LLUUID getSelectedUUID() const;
+
+ /**
+ * Get LLUUIDs associated with selected items
+ * @param selected_uuids An std::vector being populated with LLUUIDs associated with selected items
+ */
+ virtual void getSelectedUUIDs(std::vector<LLUUID>& selected_uuids) const;
+
+ /** Get the top selected item */
+ virtual LLPanel* getSelectedItem() const;
+
+ /**
+ * Get selected items
+ * @param selected_items An std::vector being populated with pointers to selected items
+ */
+ virtual void getSelectedItems(std::vector<LLPanel*>& selected_items) const;
+
+
+ /**
+ * Resets selection of items.
+ *
+ * It calls onCommit callback if setCommitOnSelectionChange(bool b) was called with "true"
+ * argument for current Flat List.
+ * @param no_commit_on_deselection - if true onCommit callback will not be called
+ */
+ virtual void resetSelection(bool no_commit_on_deselection = false);
+
+ /**
+ * Sets comment text which will be shown in the list is it is empty.
+ *
+ * Textbox to hold passed text is created while this method is called at the first time.
+ *
+ * @param comment_text - string to be shown as a comment.
+ */
+ void setNoItemsCommentText( const std::string& comment_text);
+
+ /** Turn on/off multiple selection support */
+ void setAllowMultipleSelection(bool allow) { mMultipleSelection = allow; }
+
+ /** Turn on/off selection support */
+ void setAllowSelection(bool can_select) { mAllowSelection = can_select; }
+
+ /** Sets flag whether onCommit should be fired if selection was changed */
+ void setCommitOnSelectionChange(bool b) { mCommitOnSelectionChange = b; }
+
+ /** Get number of selected items in the list */
+ U32 numSelected() const {return mSelectedItemPairs.size(); }
+
+ /** Get number of items in the list */
+ U32 size() const { return mItemPairs.size(); }
+
+
+ /** Removes all items from the list */
+ virtual void clear();
+
+ /**
+ * Removes all items that can be detached from the list but doesn't destroy
+ * them, caller responsible to manage items after they are detached.
+ * Detachable item should accept "detach" action via notify() method,
+ * where it disconnect all callbacks, does other valuable routines and
+ * return 1.
+ */
+ void detachItems(std::vector<LLPanel*>& detached_items);
+
+ /**
+ * Set comparator to use for future sorts.
+ *
+ * This class does NOT manage lifetime of the comparator
+ * but assumes that the comparator is always alive.
+ */
+ void setComparator(const ItemComparator* comp) { mItemComparator = comp; }
+ void sort();
+
+ bool updateValue(const LLSD& old_value, const LLSD& new_value);
+
+
+ void selectFirstItem ();
+ void selectLastItem ();
+
+ virtual S32 notify(const LLSD& info) ;
+
+protected:
+
+ /** Pairs LLpanel representing a single item LLPanel and LLSD associated with it */
+ typedef std::pair<LLPanel*, LLSD> item_pair_t;
+
+ typedef std::list<item_pair_t*> pairs_list_t;
+ typedef pairs_list_t::iterator pairs_iterator_t;
+ typedef pairs_list_t::const_iterator pairs_const_iterator_t;
+
+ /** An adapter for a ItemComparator */
+ struct ComparatorAdaptor
+ {
+ ComparatorAdaptor(const ItemComparator& comparator) : mComparator(comparator) {};
+
+ bool operator()(const item_pair_t* item_pair1, const item_pair_t* item_pair2)
+ {
+ return mComparator.compare(item_pair1->first, item_pair2->first);
+ }
+
+ const ItemComparator& mComparator;
+ };
+
+
+ friend class LLUICtrlFactory;
+ LLFlatListView(const LLFlatListView::Params& p);
+
+ /** Manage selection on mouse events */
+ void onItemMouseClick(item_pair_t* item_pair, MASK mask);
+
+ void onItemRightMouseClick(item_pair_t* item_pair, MASK mask);
+
+ /**
+ * Updates position of items.
+ * It does not take into account invisible items.
+ */
+ virtual void rearrangeItems();
+
+ virtual item_pair_t* getItemPair(LLPanel* item) const;
+
+ virtual item_pair_t* getItemPair(const LLSD& value) const;
+
+ virtual bool selectItemPair(item_pair_t* item_pair, bool select);
+
+ virtual bool selectNextItemPair(bool is_up_direction, bool reset_selection);
+
+ virtual bool selectAll();
+
+ virtual bool isSelected(item_pair_t* item_pair) const;
+
+ virtual bool removeItemPair(item_pair_t* item_pair);
+
+ /**
+ * Notify parent about changed size of internal controls with "size_changes" action
+ *
+ * Size includes Items Rect width and either Items Rect height or comment text height.
+ * Comment text height is included if comment text is set and visible.
+ * List border size is also included into notified size.
+ */
+ void notifyParentItemsRectChanged();
+
+ virtual BOOL handleKeyHere(KEY key, MASK mask);
+
+ virtual BOOL postBuild();
+
+ virtual void onFocusReceived();
+
+ virtual void onFocusLost();
+
+ virtual void draw();
+
+ LLRect getLastSelectedItemRect();
+
+ LLRect getSelectedItemsRect();
+
+ void ensureSelectedVisible();
+
+private:
+
+ void setItemsNoScrollWidth(S32 new_width) {mItemsNoScrollWidth = new_width - 2 * mBorderThickness;}
+
+ void setNoItemsCommentVisible(bool visible) const;
+
+private:
+
+ /** Comparator to use when sorting the list. */
+ const ItemComparator* mItemComparator;
+
+ LLPanel* mItemsPanel;
+
+ S32 mItemsNoScrollWidth;
+
+ S32 mBorderThickness;
+
+ /** Items padding */
+ S32 mItemPad;
+
+ /** Selection support flag */
+ bool mAllowSelection;
+
+ /** Multiselection support flag, ignored if selection is not supported */
+ bool mMultipleSelection;
+
+ /**
+ * Flag specified whether onCommit be called if selection is changed in the list.
+ *
+ * Can be ignored in the resetSelection() method.
+ * @see resetSelection()
+ */
+ bool mCommitOnSelectionChange;
+
+ bool mKeepOneItemSelected;
+
+ /** All pairs of the list */
+ pairs_list_t mItemPairs;
+
+ /** Selected pairs for faster access */
+ pairs_list_t mSelectedItemPairs;
+
+ /**
+ * Rectangle contained previous size of items parent notified last time.
+ * Is used to reduce amount of parentNotify() calls if size was not changed.
+ */
+ LLRect mPrevNotifyParentRect;
+
+ LLTextBox* mNoItemsCommentTextbox;
+
+ LLViewBorder* mSelectedItemsBorder;
+
+ commit_signal_t mOnReturnSignal;
+};
+
+#endif
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 21f8f6e5f7..79d8f90fec 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -43,11 +43,13 @@
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "lldraghandle.h"
+#include "llfloaterreg.h"
#include "llfocusmgr.h"
#include "llresizebar.h"
#include "llresizehandle.h"
#include "llkeyboard.h"
#include "llmenugl.h" // MENU_BAR_HEIGHT
+#include "llmodaldialog.h"
#include "lltextbox.h"
#include "llresmgr.h"
#include "llui.h"
@@ -56,59 +58,39 @@
#include "llcontrol.h"
#include "lltabcontainer.h"
#include "v2math.h"
+#include "lltrans.h"
+#include "llhelp.h"
+#include "llmultifloater.h"
+#include "llsdutil.h"
-const S32 MINIMIZED_WIDTH = 160;
-const S32 CLOSE_BOX_FROM_TOP = 1;
// use this to control "jumping" behavior when Ctrl-Tabbing
const S32 TABBED_FLOATER_OFFSET = 0;
-std::string LLFloater::sButtonActiveImageNames[BUTTON_COUNT] =
-{
- "UIImgBtnCloseActiveUUID", //BUTTON_CLOSE
- "UIImgBtnRestoreActiveUUID", //BUTTON_RESTORE
- "UIImgBtnMinimizeActiveUUID", //BUTTON_MINIMIZE
- "UIImgBtnTearOffActiveUUID", //BUTTON_TEAR_OFF
- "UIImgBtnCloseActiveUUID", //BUTTON_EDIT
-};
-
-std::string LLFloater::sButtonInactiveImageNames[BUTTON_COUNT] =
-{
- "UIImgBtnCloseInactiveUUID", //BUTTON_CLOSE
- "UIImgBtnRestoreInactiveUUID", //BUTTON_RESTORE
- "UIImgBtnMinimizeInactiveUUID", //BUTTON_MINIMIZE
- "UIImgBtnTearOffInactiveUUID", //BUTTON_TEAR_OFF
- "UIImgBtnCloseInactiveUUID", //BUTTON_EDIT
-};
-
-std::string LLFloater::sButtonPressedImageNames[BUTTON_COUNT] =
-{
- "UIImgBtnClosePressedUUID", //BUTTON_CLOSE
- "UIImgBtnRestorePressedUUID", //BUTTON_RESTORE
- "UIImgBtnMinimizePressedUUID", //BUTTON_MINIMIZE
- "UIImgBtnTearOffPressedUUID", //BUTTON_TEAR_OFF
- "UIImgBtnClosePressedUUID", //BUTTON_EDIT
-};
std::string LLFloater::sButtonNames[BUTTON_COUNT] =
{
- "llfloater_close_btn", //BUTTON_CLOSE
+ "llfloater_close_btn", //BUTTON_CLOSE
"llfloater_restore_btn", //BUTTON_RESTORE
"llfloater_minimize_btn", //BUTTON_MINIMIZE
"llfloater_tear_off_btn", //BUTTON_TEAR_OFF
- "llfloater_edit_btn", //BUTTON_EDIT
+ "llfloater_dock_btn", //BUTTON_DOCK
+ "llfloater_help_btn" //BUTTON_HELP
};
-std::string LLFloater::sButtonToolTips[BUTTON_COUNT] =
+std::string LLFloater::sButtonToolTips[BUTTON_COUNT];
+
+std::string LLFloater::sButtonToolTipsIndex[BUTTON_COUNT]=
{
#ifdef LL_DARWIN
- "Close (Cmd-W)", //BUTTON_CLOSE
+ "BUTTON_CLOSE_DARWIN", //"Close (Cmd-W)", //BUTTON_CLOSE
#else
- "Close (Ctrl-W)", //BUTTON_CLOSE
+ "BUTTON_CLOSE_WIN", //"Close (Ctrl-W)", //BUTTON_CLOSE
#endif
- "Restore", //BUTTON_RESTORE
- "Minimize", //BUTTON_MINIMIZE
- "Tear Off", //BUTTON_TEAR_OFF
- "Edit", //BUTTON_EDIT
+ "BUTTON_RESTORE", //"Restore", //BUTTON_RESTORE
+ "BUTTON_MINIMIZE", //"Minimize", //BUTTON_MINIMIZE
+ "BUTTON_TEAR_OFF", //"Tear Off", //BUTTON_TEAR_OFF
+ "BUTTON_DOCK",
+ "BUTTON_HELP"
};
LLFloater::click_callback LLFloater::sButtonCallbacks[BUTTON_COUNT] =
@@ -117,330 +99,364 @@ LLFloater::click_callback LLFloater::sButtonCallbacks[BUTTON_COUNT] =
LLFloater::onClickMinimize, //BUTTON_RESTORE
LLFloater::onClickMinimize, //BUTTON_MINIMIZE
LLFloater::onClickTearOff, //BUTTON_TEAR_OFF
- LLFloater::onClickEdit, //BUTTON_EDIT
+ LLFloater::onClickDock, //BUTTON_DOCK
+ LLFloater::onClickHelp //BUTTON_HELP
};
LLMultiFloater* LLFloater::sHostp = NULL;
-BOOL LLFloater::sEditModeEnabled;
+BOOL LLFloater::sQuitting = FALSE; // Flag to prevent storing visibility controls while quitting
LLFloater::handle_map_t LLFloater::sFloaterMap;
LLFloaterView* gFloaterView = NULL;
-LLFloater::LLFloater() :
- //FIXME: we should initialize *all* member variables here
- LLPanel(), mAutoFocus(TRUE),
- mResizable(FALSE),
- mDragOnLeft(FALSE),
- mMinWidth(0),
- mMinHeight(0)
+/*==========================================================================*|
+// DEV-38598: The fundamental problem with this operation is that it can only
+// support a subset of LLSD values. While it's plausible to compare two arrays
+// lexicographically, what strict ordering can you impose on maps?
+// (LLFloaterTOS's current key is an LLSD map.)
+
+// Of course something like this is necessary if you want to build a std::set
+// or std::map with LLSD keys. Fortunately we're getting by with other
+// container types for now.
+
+//static
+bool LLFloater::KeyCompare::compare(const LLSD& a, const LLSD& b)
+{
+ if (a.type() != b.type())
+ {
+ //llerrs << "Mismatched LLSD types: (" << a << ") mismatches (" << b << ")" << llendl;
+ return false;
+ }
+ else if (a.isUndefined())
+ return false;
+ else if (a.isInteger())
+ return a.asInteger() < b.asInteger();
+ else if (a.isReal())
+ return a.asReal() < b.asReal();
+ else if (a.isString())
+ return a.asString() < b.asString();
+ else if (a.isUUID())
+ return a.asUUID() < b.asUUID();
+ else if (a.isDate())
+ return a.asDate() < b.asDate();
+ else if (a.isURI())
+ return a.asString() < b.asString(); // compare URIs as strings
+ else if (a.isBoolean())
+ return a.asBoolean() < b.asBoolean();
+ else
+ return false; // no valid operation for Binary
+}
+|*==========================================================================*/
+
+bool LLFloater::KeyCompare::equate(const LLSD& a, const LLSD& b)
{
- // automatically take focus when opened
- mAutoFocus = TRUE;
- for (S32 i = 0; i < BUTTON_COUNT; i++)
- {
- mButtonsEnabled[i] = FALSE;
- mButtons[i] = NULL;
- }
- for (S32 i = 0; i < 4; i++)
- {
- mResizeBar[i] = NULL;
- mResizeHandle[i] = NULL;
- }
- mDragHandle = NULL;
- mHandle.bind(this);
- mNotificationContext = new LLFloaterNotificationContext(getHandle());
+ return llsd_equals(a, b);
}
-LLFloater::LLFloater(const std::string& name)
-: LLPanel(name), mAutoFocus(TRUE) // automatically take focus when opened
+//************************************
+
+LLFloater::Params::Params()
+: title("title"),
+ short_title("short_title"),
+ single_instance("single_instance", false),
+ auto_tile("auto_tile", false),
+ can_resize("can_resize", false),
+ can_minimize("can_minimize", true),
+ can_close("can_close", true),
+ can_drag_on_left("can_drag_on_left", false),
+ can_tear_off("can_tear_off", true),
+ save_dock_state("save_dock_state", false),
+ save_rect("save_rect", false),
+ save_visibility("save_visibility", false),
+ can_dock("can_dock", false),
+ header_height("header_height", 0),
+ legacy_header_height("legacy_header_height", 0),
+ close_image("close_image"),
+ restore_image("restore_image"),
+ minimize_image("minimize_image"),
+ tear_off_image("tear_off_image"),
+ dock_image("dock_image"),
+ help_image("help_image"),
+ close_pressed_image("close_pressed_image"),
+ restore_pressed_image("restore_pressed_image"),
+ minimize_pressed_image("minimize_pressed_image"),
+ tear_off_pressed_image("tear_off_pressed_image"),
+ dock_pressed_image("dock_pressed_image"),
+ help_pressed_image("help_pressed_image"),
+ open_callback("open_callback"),
+ close_callback("close_callback")
{
- for (S32 i = 0; i < BUTTON_COUNT; i++)
- {
- mButtonsEnabled[i] = FALSE;
- mButtons[i] = NULL;
- }
- for (S32 i = 0; i < 4; i++)
- {
- mResizeBar[i] = NULL;
- mResizeHandle[i] = NULL;
- }
- std::string title; // null string
- initFloater(title, FALSE, DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT, FALSE, TRUE, TRUE); // defaults
+ visible = false;
}
-LLFloater::LLFloater(const std::string& name, const LLRect& rect, const std::string& title,
- BOOL resizable,
- S32 min_width,
- S32 min_height,
- BOOL drag_on_left,
- BOOL minimizable,
- BOOL close_btn,
- BOOL bordered)
-: LLPanel(name, rect, bordered), mAutoFocus(TRUE) // automatically take focus when opened
+//static
+const LLFloater::Params& LLFloater::getDefaultParams()
{
- for (S32 i = 0; i < BUTTON_COUNT; i++)
- {
- mButtonsEnabled[i] = FALSE;
- mButtons[i] = NULL;
- }
- for (S32 i = 0; i < 4; i++)
- {
- mResizeBar[i] = NULL;
- mResizeHandle[i] = NULL;
- }
- initFloater( title, resizable, min_width, min_height, drag_on_left, minimizable, close_btn);
+ return LLUICtrlFactory::getDefaultParams<LLFloater>();
}
-LLFloater::LLFloater(const std::string& name, const std::string& rect_control, const std::string& title,
- BOOL resizable,
- S32 min_width,
- S32 min_height,
- BOOL drag_on_left,
- BOOL minimizable,
- BOOL close_btn,
- BOOL bordered)
-: LLPanel(name, rect_control, bordered), mAutoFocus(TRUE) // automatically take focus when opened
+//static
+void LLFloater::initClass()
{
+ // translate tooltips for floater buttons
for (S32 i = 0; i < BUTTON_COUNT; i++)
{
- mButtonsEnabled[i] = FALSE;
- mButtons[i] = NULL;
- }
- for (S32 i = 0; i < 4; i++)
- {
- mResizeBar[i] = NULL;
- mResizeHandle[i] = NULL;
- }
- initFloater( title, resizable, min_width, min_height, drag_on_left, minimizable, close_btn);
-}
+ sButtonToolTips[i] = LLTrans::getString( sButtonToolTipsIndex[i] );
+ }
+}
+
+// defaults for floater param block pulled from widgets/floater.xml
+static LLWidgetNameRegistry::StaticRegistrar sRegisterFloaterParams(&typeid(LLFloater::Params), "floater");
+
+LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
+: LLPanel(), // intentionally do not pass params here, see initFromParams
+ mDragHandle(NULL),
+ mTitle(p.title),
+ mShortTitle(p.short_title),
+ mSingleInstance(p.single_instance),
+ mKey(key),
+ mAutoTile(p.auto_tile),
+ mCanTearOff(p.can_tear_off),
+ mCanMinimize(p.can_minimize),
+ mCanClose(p.can_close),
+ mDragOnLeft(p.can_drag_on_left),
+ mResizable(p.can_resize),
+ mMinWidth(p.min_width),
+ mMinHeight(p.min_height),
+ mHeaderHeight(p.header_height),
+ mLegacyHeaderHeight(p.legacy_header_height),
+ mMinimized(FALSE),
+ mForeground(FALSE),
+ mFirstLook(TRUE),
+ mButtonScale(1.0f),
+ mAutoFocus(TRUE), // automatically take focus when opened
+ mCanDock(false),
+ mDocked(false),
+ mTornOff(false),
+ mHasBeenDraggedWhileMinimized(FALSE),
+ mPreviousMinimizedBottom(0),
+ mPreviousMinimizedLeft(0)
+// mNotificationContext(NULL)
+{
+ mHandle.bind(this);
+// mNotificationContext = new LLFloaterNotificationContext(getHandle());
+
+ // Clicks stop here.
+ setMouseOpaque(TRUE);
+
+ // Floaters always draw their background, unlike every other panel.
+ setBackgroundVisible(TRUE);
+ // Floaters start not minimized. When minimized, they save their
+ // prior rectangle to be used on restore.
+ mExpandedRect.set(0,0,0,0);
+
+ memset(mButtonsEnabled, 0, BUTTON_COUNT * sizeof(bool));
+ memset(mButtons, 0, BUTTON_COUNT * sizeof(LLButton*));
+
+ addDragHandle();
+ addResizeCtrls();
+
+ initFromParams(p);
+
+ // chrome floaters don't take focus at all
+ setFocusRoot(!getIsChrome());
+
+ initFloater(p);
+}
// Note: Floaters constructed from XML call init() twice!
-void LLFloater::initFloater(const std::string& title,
- BOOL resizable, S32 min_width, S32 min_height,
- BOOL drag_on_left, BOOL minimizable, BOOL close_btn)
+void LLFloater::initFloater(const Params& p)
{
- mHandle.bind(this);
- mNotificationContext = new LLFloaterNotificationContext(getHandle());
-
- // Init function can be called more than once, so clear out old data.
- for (S32 i = 0; i < BUTTON_COUNT; i++)
+ // Close button.
+ if (mCanClose)
{
- mButtonsEnabled[i] = FALSE;
- if (mButtons[i] != NULL)
- {
- removeChild(mButtons[i]);
- delete mButtons[i];
- mButtons[i] = NULL;
- }
+ mButtonsEnabled[BUTTON_CLOSE] = TRUE;
}
- mButtonScale = 1.f;
- //sjb: Thia is a bit of a hack:
- BOOL need_border = hasBorder();
- // remove the border since deleteAllChildren() will also delete the border (but not clear mBorder)
- removeBorder();
- // this will delete mBorder too
- deleteAllChildren();
- // add the border back if we want it
- if (need_border)
+ // Help button: '?'
+ if ( !mHelpTopic.empty() )
{
- addBorder();
+ mButtonsEnabled[BUTTON_HELP] = TRUE;
}
- // chrome floaters don't take focus at all
- setFocusRoot(!getIsChrome());
+ // Minimize button only for top draggers
+ if ( !mDragOnLeft && mCanMinimize )
+ {
+ mButtonsEnabled[BUTTON_MINIMIZE] = TRUE;
+ }
- // Reset cached pointers
- mDragHandle = NULL;
- for (S32 i = 0; i < 4; i++)
+ if(mCanDock)
{
- mResizeBar[i] = NULL;
- mResizeHandle[i] = NULL;
+ mButtonsEnabled[BUTTON_DOCK] = TRUE;
}
- mCanTearOff = TRUE;
- mEditing = FALSE;
- // Clicks stop here.
- setMouseOpaque(TRUE);
+ buildButtons(p);
- mFirstLook = TRUE;
- mForeground = FALSE;
- mDragOnLeft = drag_on_left == TRUE;
+ // Floaters are created in the invisible state
+ setVisible(FALSE);
- // Floaters always draw their background, unlike every other panel.
- setBackgroundVisible(TRUE);
+ // add self to handle->floater map
+ sFloaterMap[mHandle] = this;
- // Floaters start not minimized. When minimized, they save their
- // prior rectangle to be used on restore.
- mMinimized = FALSE;
- mExpandedRect.set(0,0,0,0);
-
- S32 close_pad; // space to the right of close box
- S32 close_box_size; // For layout purposes, how big is the close box?
- if (close_btn)
- {
- close_box_size = LLFLOATER_CLOSE_BOX_SIZE;
- close_pad = 0;
- }
- else
+ if (!getParent())
{
- close_box_size = 0;
- close_pad = 0;
+ gFloaterView->addChild(this);
}
+}
- S32 minimize_box_size;
- S32 minimize_pad;
- if (minimizable && !drag_on_left)
- {
- minimize_box_size = LLFLOATER_CLOSE_BOX_SIZE;
- minimize_pad = 0;
- }
- else
+void LLFloater::addDragHandle()
+{
+ if (!mDragHandle)
{
- minimize_box_size = 0;
- minimize_pad = 0;
+ if (mDragOnLeft)
+ {
+ LLDragHandleLeft::Params p;
+ p.name("drag");
+ p.follows.flags(FOLLOWS_ALL);
+ p.label(mTitle);
+ mDragHandle = LLUICtrlFactory::create<LLDragHandleLeft>(p);
+ }
+ else // drag on top
+ {
+ LLDragHandleTop::Params p;
+ p.name("Drag Handle");
+ p.follows.flags(FOLLOWS_ALL);
+ p.label(mTitle);
+ mDragHandle = LLUICtrlFactory::create<LLDragHandleTop>(p);
+ }
+ addChild(mDragHandle);
}
+ layoutDragHandle();
+}
- // Drag Handle
- // Add first so it's in the background.
-// const S32 drag_pad = 2;
- if (drag_on_left)
+void LLFloater::layoutDragHandle()
+{
+ static LLUICachedControl<S32> floater_close_box_size ("UIFloaterCloseBoxSize", 0);
+ S32 close_box_size = mCanClose ? floater_close_box_size : 0;
+
+ LLRect rect;
+ if (mDragOnLeft)
{
- LLRect drag_handle_rect;
- drag_handle_rect.setOriginAndSize(
- 0, 0,
- DRAG_HANDLE_WIDTH,
- getRect().getHeight() - LLPANEL_BORDER_WIDTH - close_box_size);
- mDragHandle = new LLDragHandleLeft(std::string("drag"), drag_handle_rect, title );
+ rect.setLeftTopAndSize(0, 0, DRAG_HANDLE_WIDTH, getRect().getHeight() - LLPANEL_BORDER_WIDTH - close_box_size);
}
else // drag on top
{
- LLRect drag_handle_rect( 0, getRect().getHeight(), getRect().getWidth(), 0 );
- mDragHandle = new LLDragHandleTop( std::string("Drag Handle"), drag_handle_rect, title );
+ rect = getLocalRect();
}
- addChild(mDragHandle);
+ mDragHandle->setRect(rect);
+ updateButtons();
+ applyTitle();
+}
- // Resize Handle
- mResizable = resizable;
- mMinWidth = min_width;
- mMinHeight = min_height;
+void LLFloater::addResizeCtrls()
+{
+ // Resize bars (sides)
+ LLResizeBar::Params p;
+ p.name("resizebar_left");
+ p.resizing_view(this);
+ p.min_size(mMinWidth);
+ p.side(LLResizeBar::LEFT);
+ mResizeBar[LLResizeBar::LEFT] = LLUICtrlFactory::create<LLResizeBar>(p);
+ addChild( mResizeBar[LLResizeBar::LEFT] );
+
+ p.name("resizebar_top");
+ p.min_size(mMinHeight);
+ p.side(LLResizeBar::TOP);
+
+ mResizeBar[LLResizeBar::TOP] = LLUICtrlFactory::create<LLResizeBar>(p);
+ addChild( mResizeBar[LLResizeBar::TOP] );
+
+ p.name("resizebar_right");
+ p.min_size(mMinWidth);
+ p.side(LLResizeBar::RIGHT);
+ mResizeBar[LLResizeBar::RIGHT] = LLUICtrlFactory::create<LLResizeBar>(p);
+ addChild( mResizeBar[LLResizeBar::RIGHT] );
+
+ p.name("resizebar_bottom");
+ p.min_size(mMinHeight);
+ p.side(LLResizeBar::BOTTOM);
+ mResizeBar[LLResizeBar::BOTTOM] = LLUICtrlFactory::create<LLResizeBar>(p);
+ addChild( mResizeBar[LLResizeBar::BOTTOM] );
+
+ // Resize handles (corners)
+ LLResizeHandle::Params handle_p;
+ // handles must not be mouse-opaque, otherwise they block hover events
+ // to other buttons like the close box. JC
+ handle_p.mouse_opaque(false);
+ handle_p.min_width(mMinWidth);
+ handle_p.min_height(mMinHeight);
+ handle_p.corner(LLResizeHandle::RIGHT_BOTTOM);
+ mResizeHandle[0] = LLUICtrlFactory::create<LLResizeHandle>(handle_p);
+ addChild(mResizeHandle[0]);
+
+ handle_p.corner(LLResizeHandle::RIGHT_TOP);
+ mResizeHandle[1] = LLUICtrlFactory::create<LLResizeHandle>(handle_p);
+ addChild(mResizeHandle[1]);
+
+ handle_p.corner(LLResizeHandle::LEFT_BOTTOM);
+ mResizeHandle[2] = LLUICtrlFactory::create<LLResizeHandle>(handle_p);
+ addChild(mResizeHandle[2]);
- if( mResizable )
- {
- // Resize bars (sides)
- const S32 RESIZE_BAR_THICKNESS = 3;
- mResizeBar[LLResizeBar::LEFT] = new LLResizeBar(
- std::string("resizebar_left"),
- this,
- LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0),
- min_width, S32_MAX, LLResizeBar::LEFT );
- addChild( mResizeBar[0] );
-
- mResizeBar[LLResizeBar::TOP] = new LLResizeBar(
- std::string("resizebar_top"),
- this,
- LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS),
- min_height, S32_MAX, LLResizeBar::TOP );
- addChild( mResizeBar[1] );
-
- mResizeBar[LLResizeBar::RIGHT] = new LLResizeBar(
- std::string("resizebar_right"),
- this,
- LLRect( getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0),
- min_width, S32_MAX, LLResizeBar::RIGHT );
- addChild( mResizeBar[2] );
-
- mResizeBar[LLResizeBar::BOTTOM] = new LLResizeBar(
- std::string("resizebar_bottom"),
- this,
- LLRect( 0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0),
- min_height, S32_MAX, LLResizeBar::BOTTOM );
- addChild( mResizeBar[3] );
-
-
- // Resize handles (corners)
- mResizeHandle[0] = new LLResizeHandle(
- std::string("Resize Handle"),
- LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0),
- min_width,
- min_height,
- LLResizeHandle::RIGHT_BOTTOM);
- addChild(mResizeHandle[0]);
-
- mResizeHandle[1] = new LLResizeHandle(
- std::string("resize"),
- LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_HANDLE_HEIGHT),
- min_width,
- min_height,
- LLResizeHandle::RIGHT_TOP );
- addChild(mResizeHandle[1]);
-
- mResizeHandle[2] = new LLResizeHandle( std::string("resize"),
- LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 ),
- min_width,
- min_height,
- LLResizeHandle::LEFT_BOTTOM );
- addChild(mResizeHandle[2]);
+ handle_p.corner(LLResizeHandle::LEFT_TOP);
+ mResizeHandle[3] = LLUICtrlFactory::create<LLResizeHandle>(handle_p);
+ addChild(mResizeHandle[3]);
- mResizeHandle[3] = new LLResizeHandle( std::string("resize"),
- LLRect( 0, getRect().getHeight(), RESIZE_HANDLE_WIDTH, getRect().getHeight() - RESIZE_HANDLE_HEIGHT ),
- min_width,
- min_height,
- LLResizeHandle::LEFT_TOP );
- addChild(mResizeHandle[3]);
- }
+ layoutResizeCtrls();
+}
- // Close button.
- if (close_btn)
- {
- mButtonsEnabled[BUTTON_CLOSE] = TRUE;
- }
+void LLFloater::layoutResizeCtrls()
+{
+ LLRect rect;
- // Minimize button only for top draggers
- if ( !drag_on_left && minimizable )
- {
- mButtonsEnabled[BUTTON_MINIMIZE] = TRUE;
- }
+ // Resize bars (sides)
+ const S32 RESIZE_BAR_THICKNESS = 3;
+ rect = LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0);
+ mResizeBar[LLResizeBar::LEFT]->setRect(rect);
- // Keep track of whether this window has ever been dragged while it
- // was minimized. If it has, we'll remember its position for the
- // next time it's minimized.
- mHasBeenDraggedWhileMinimized = FALSE;
- mPreviousMinimizedLeft = 0;
- mPreviousMinimizedBottom = 0;
+ rect = LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS);
+ mResizeBar[LLResizeBar::TOP]->setRect(rect);
- buildButtons();
+ rect = LLRect(getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0);
+ mResizeBar[LLResizeBar::RIGHT]->setRect(rect);
- // JC - Don't do this here, because many floaters first construct themselves,
- // then show themselves. Put it in setVisibleAndFrontmost.
- // make_ui_sound("UISndWindowOpen");
+ rect = LLRect(0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0);
+ mResizeBar[LLResizeBar::BOTTOM]->setRect(rect);
- // RN: floaters are created in the invisible state
- setVisible(FALSE);
+ // Resize handles (corners)
+ rect = LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0);
+ mResizeHandle[0]->setRect(rect);
- // add self to handle->floater map
- sFloaterMap[mHandle] = this;
+ rect = LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_HANDLE_HEIGHT);
+ mResizeHandle[1]->setRect(rect);
+
+ rect = LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 );
+ mResizeHandle[2]->setRect(rect);
- if (!getParent())
+ rect = LLRect( 0, getRect().getHeight(), RESIZE_HANDLE_WIDTH, getRect().getHeight() - RESIZE_HANDLE_HEIGHT );
+ mResizeHandle[3]->setRect(rect);
+}
+
+void LLFloater::enableResizeCtrls(bool enable)
+{
+ for (S32 i = 0; i < 4; ++i)
{
- gFloaterView->addChild(this);
+ mResizeBar[i]->setVisible(enable);
+ mResizeBar[i]->setEnabled(enable);
+
+ mResizeHandle[i]->setVisible(enable);
+ mResizeHandle[i]->setEnabled(enable);
}
}
// virtual
LLFloater::~LLFloater()
{
- delete mNotificationContext;
- mNotificationContext = NULL;
-
- control_map_t::iterator itor;
- for (itor = mFloaterControls.begin(); itor != mFloaterControls.end(); ++itor)
- {
- delete itor->second;
- }
- mFloaterControls.clear();
+ LLFloaterReg::removeInstance(mInstanceName, mKey);
+
+// delete mNotificationContext;
+// mNotificationContext = NULL;
//// am I not hosted by another floater?
//if (mHostHandle.isDead())
@@ -469,12 +485,41 @@ LLFloater::~LLFloater()
delete mResizeBar[i];
delete mResizeHandle[i];
}
+
+ storeRectControl();
+ setVisible(false); // We're not visible if we're destroyed
+ storeVisibilityControl();
+ storeDockStateControl();
+}
+
+void LLFloater::storeRectControl()
+{
+ if( mRectControl.size() > 1 )
+ {
+ LLUI::sSettingGroups["floater"]->setRect( mRectControl, getRect() );
+ }
+}
+
+void LLFloater::storeVisibilityControl()
+{
+ if( !sQuitting && mVisibilityControl.size() > 1 )
+ {
+ LLUI::sSettingGroups["floater"]->setBOOL( mVisibilityControl, getVisible() );
+ }
+}
+
+void LLFloater::storeDockStateControl()
+{
+ if( !sQuitting && mDocStateControl.size() > 1 )
+ {
+ LLUI::sSettingGroups["floater"]->setBOOL( mDocStateControl, isDocked() );
+ }
}
void LLFloater::setVisible( BOOL visible )
{
- LLPanel::setVisible(visible);
+ LLPanel::setVisible(visible); // calls handleVisibilityChange()
if( visible && mFirstLook )
{
mFirstLook = FALSE;
@@ -504,10 +549,25 @@ void LLFloater::setVisible( BOOL visible )
}
++dependent_it;
}
+
+ storeVisibilityControl();
+}
+
+// virtual
+void LLFloater::handleVisibilityChange ( BOOL new_visibility )
+{
+ if (new_visibility)
+ {
+ if (getHost())
+ getHost()->setFloaterFlashing(this, FALSE);
+ }
+ LLPanel::handleVisibilityChange ( new_visibility );
}
-void LLFloater::open() /* Flawfinder: ignore */
+void LLFloater::openFloater(const LLSD& key)
{
+ mKey = key; // in case we need to open ourselves again
+
if (getSoundFlags() != SILENT
// don't play open sound for hosted (tabbed) windows
&& !getHost()
@@ -525,9 +585,11 @@ void LLFloater::open() /* Flawfinder: ignore */
// only select tabs if window they are hosted in is visible
getFloaterHost()->addFloater(this, getFloaterHost()->getVisible());
}
- else if (getHost() != NULL)
+
+ if (getHost() != NULL)
{
- // already hosted
+ getHost()->setMinimized(FALSE);
+ getHost()->setVisibleAndFrontmost(mAutoFocus);
getHost()->showFloater(this);
}
else
@@ -536,11 +598,19 @@ void LLFloater::open() /* Flawfinder: ignore */
setVisibleAndFrontmost(mAutoFocus);
}
- onOpen();
+ mOpenSignal(this, key);
+ onOpen(key);
+
+ dirtyRect();
}
-void LLFloater::close(bool app_quitting)
+void LLFloater::closeFloater(bool app_quitting)
{
+ if (app_quitting)
+ {
+ LLFloater::sQuitting = true;
+ }
+
// Always unminimize before trying to close.
// Most of the time the user will never see this state.
setMinimized(FALSE);
@@ -570,7 +640,7 @@ void LLFloater::close(bool app_quitting)
if (floaterp)
{
++dependent_it;
- floaterp->close();
+ floaterp->closeFloater(app_quitting);
}
else
{
@@ -598,8 +668,30 @@ void LLFloater::close(bool app_quitting)
}
}
- // Let floater do cleanup.
+ dirtyRect();
+
+ // Close callbacks
onClose(app_quitting);
+ mCloseSignal(this, LLSD(app_quitting));
+
+ // Hide or Destroy
+ if (mSingleInstance)
+ {
+ // Hide the instance
+ if (getHost())
+ {
+ getHost()->setVisible(FALSE);
+ }
+ else
+ {
+ setVisible(FALSE);
+ }
+ }
+ else
+ {
+ setVisible(FALSE); // hide before destroying (so handleVisibilityChange() gets called)
+ destroy();
+ }
}
}
@@ -607,6 +699,7 @@ void LLFloater::close(bool app_quitting)
void LLFloater::reshape(S32 width, S32 height, BOOL called_from_parent)
{
LLPanel::reshape(width, height, called_from_parent);
+ storeRectControl();
}
void LLFloater::releaseFocus()
@@ -616,10 +709,7 @@ void LLFloater::releaseFocus()
gFocusMgr.setTopCtrl(NULL);
}
- if( gFocusMgr.childHasKeyboardFocus( this ) )
- {
- gFocusMgr.setKeyboardFocus(NULL);
- }
+ setFocus(FALSE);
if( gFocusMgr.childHasMouseCapture( this ) )
{
@@ -664,26 +754,45 @@ void LLFloater::center()
centerWithin(gFloaterView->getRect());
}
+LLMultiFloater* LLFloater::getHost()
+{
+ return (LLMultiFloater*)mHostHandle.get();
+}
+
+void LLFloater::applySavedVariables()
+{
+ applyRectControl();
+ applyDockState();
+}
+
void LLFloater::applyRectControl()
{
- if (!getRectControl().empty())
+ if (mRectControl.size() > 1)
{
- const LLRect& rect = LLUI::sConfigGroup->getRect(getRectControl());
- translate( rect.mLeft - getRect().mLeft, rect.mBottom - getRect().mBottom);
- if (mResizable)
+ const LLRect& rect = LLUI::sSettingGroups["floater"]->getRect(mRectControl);
+ if (rect.getWidth() > 0 && rect.getHeight() > 0)
{
- reshape(llmax(mMinWidth, rect.getWidth()), llmax(mMinHeight, rect.getHeight()));
+ translate( rect.mLeft - getRect().mLeft, rect.mBottom - getRect().mBottom);
+ if (mResizable)
+ {
+ reshape(llmax(mMinWidth, rect.getWidth()), llmax(mMinHeight, rect.getHeight()));
+ }
}
}
}
-void LLFloater::applyTitle()
+void LLFloater::applyDockState()
{
- if (gNoRender)
+ if (mDocStateControl.size() > 1)
{
- return;
+ bool dockState = LLUI::sSettingGroups["floater"]->getBOOL(mDocStateControl);
+ setDocked(dockState);
}
+}
+
+void LLFloater::applyTitle()
+{
if (!mDragHandle)
{
return;
@@ -699,7 +808,7 @@ void LLFloater::applyTitle()
}
}
-const std::string& LLFloater::getCurrentTitle() const
+std::string LLFloater::getCurrentTitle() const
{
return mDragHandle ? mDragHandle->getTitle() : LLStringUtil::null;
}
@@ -710,7 +819,7 @@ void LLFloater::setTitle( const std::string& title )
applyTitle();
}
-std::string LLFloater::getTitle()
+std::string LLFloater::getTitle() const
{
if (mTitle.empty())
{
@@ -728,7 +837,7 @@ void LLFloater::setShortTitle( const std::string& short_title )
applyTitle();
}
-std::string LLFloater::getShortTitle()
+std::string LLFloater::getShortTitle() const
{
if (mShortTitle.empty())
{
@@ -740,8 +849,6 @@ std::string LLFloater::getShortTitle()
}
}
-
-
BOOL LLFloater::canSnapTo(const LLView* other_view)
{
if (NULL == other_view)
@@ -763,7 +870,7 @@ BOOL LLFloater::canSnapTo(const LLView* other_view)
return LLPanel::canSnapTo(other_view);
}
-void LLFloater::snappedTo(const LLView* snap_view)
+void LLFloater::setSnappedTo(const LLView* snap_view)
{
if (!snap_view || snap_view == getParent())
{
@@ -772,16 +879,18 @@ void LLFloater::snappedTo(const LLView* snap_view)
else
{
//RN: assume it's a floater as it must be a sibling to our parent floater
- LLFloater* floaterp = (LLFloater*)snap_view;
-
- setSnapTarget(floaterp->getHandle());
+ const LLFloater* floaterp = dynamic_cast<const LLFloater*>(snap_view);
+ if (floaterp)
+ {
+ setSnapTarget(floaterp->getHandle());
+ }
}
}
-void LLFloater::userSetShape(const LLRect& new_rect)
+void LLFloater::handleReshape(const LLRect& new_rect, bool by_user)
{
const LLRect old_rect = getRect();
- LLView::userSetShape(new_rect);
+ LLView::handleReshape(new_rect, by_user);
// if not minimized, adjust all snapped dependents to new shape
if (!isMinimized())
@@ -816,7 +925,7 @@ void LLFloater::userSetShape(const LLRect& new_rect)
delta_y += new_rect.mBottom - old_rect.mBottom;
dependent_rect.translate(delta_x, delta_y);
- floaterp->userSetShape(dependent_rect);
+ floaterp->setShape(dependent_rect, by_user);
}
}
}
@@ -834,10 +943,17 @@ void LLFloater::userSetShape(const LLRect& new_rect)
void LLFloater::setMinimized(BOOL minimize)
{
+ const LLFloater::Params& default_params = LLFloater::getDefaultParams();
+ S32 floater_header_size = default_params.header_height;
+ static LLUICachedControl<S32> minimized_width ("UIMinimizedWidth", 0);
+
if (minimize == mMinimized) return;
if (minimize)
{
+ // minimized flag should be turned on before release focus
+ mMinimized = TRUE;
+
mExpandedRect = getRect();
// If the floater has been dragged while minimized in the
@@ -899,10 +1015,8 @@ void LLFloater::setMinimized(BOOL minimize)
}
}
- mMinimized = TRUE;
-
// Reshape *after* setting mMinimized
- reshape( MINIMIZED_WIDTH, LLFLOATER_HEADER_SIZE, TRUE);
+ reshape( minimized_width, floater_header_size, TRUE);
}
else
{
@@ -968,7 +1082,7 @@ void LLFloater::setFocus( BOOL b )
}
LLUICtrl* last_focus = gFocusMgr.getLastFocusForGroup(this);
// a descendent already has focus
- BOOL child_had_focus = gFocusMgr.childHasKeyboardFocus(this);
+ BOOL child_had_focus = hasFocus();
// give focus to first valid descendent
LLPanel::setFocus(b);
@@ -996,6 +1110,14 @@ void LLFloater::setFocus( BOOL b )
}
// virtual
+void LLFloater::setRect(const LLRect &rect)
+{
+ LLPanel::setRect(rect);
+ layoutDragHandle();
+ layoutResizeCtrls();
+}
+
+// virtual
void LLFloater::setIsChrome(BOOL is_chrome)
{
// chrome floaters don't take focus at all
@@ -1143,7 +1265,7 @@ void LLFloater::removeDependentFloater(LLFloater* floaterp)
floaterp->mDependeeHandle = LLHandle<LLFloater>();
}
-BOOL LLFloater::offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButtons index)
+BOOL LLFloater::offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButton index)
{
if( mButtonsEnabled[index] )
{
@@ -1162,6 +1284,12 @@ BOOL LLFloater::offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButtons inde
return FALSE;
}
+BOOL LLFloater::handleScrollWheel(S32 x, S32 y, S32 clicks)
+{
+ LLPanel::handleScrollWheel(x,y,clicks);
+ return TRUE;//always
+}
+
// virtual
BOOL LLFloater::handleMouseDown(S32 x, S32 y, MASK mask)
{
@@ -1232,6 +1360,7 @@ void LLFloater::bringToFront( S32 x, S32 y )
// virtual
void LLFloater::setVisibleAndFrontmost(BOOL take_focus)
{
+ gFocusMgr.setTopCtrl(NULL);
setVisible(TRUE);
setFrontmost(take_focus);
}
@@ -1253,42 +1382,49 @@ void LLFloater::setFrontmost(BOOL take_focus)
}
}
-//static
-void LLFloater::setEditModeEnabled(BOOL enable)
+void LLFloater::setCanDock(bool b)
{
- if (enable != sEditModeEnabled)
+ if(b != mCanDock)
{
- S32 count = 0;
- for(handle_map_iter_t iter = sFloaterMap.begin(); iter != sFloaterMap.end(); ++iter)
+ mCanDock = b;
+ if(mCanDock)
{
- LLFloater* floater = iter->second;
- if (!floater->isDead())
- {
- iter->second->mButtonsEnabled[BUTTON_EDIT] = enable;
- iter->second->updateButtons();
- }
- count++;
+ mButtonsEnabled[BUTTON_DOCK] = !mDocked;
+ }
+ else
+ {
+ mButtonsEnabled[BUTTON_DOCK] = FALSE;
}
}
-
- sEditModeEnabled = enable;
+ updateButtons();
}
+void LLFloater::setDocked(bool docked, bool pop_on_undock)
+{
+ if(docked != mDocked && mCanDock)
+ {
+ mDocked = docked;
+ mButtonsEnabled[BUTTON_DOCK] = !mDocked;
+ updateButtons();
+
+ storeDockStateControl();
+ }
+
+}
// static
-void LLFloater::onClickMinimize(void *userdata)
+void LLFloater::onClickMinimize(LLFloater* self)
{
- LLFloater* self = (LLFloater*) userdata;
- if (!self) return;
-
+ if (!self)
+ return;
self->setMinimized( !self->isMinimized() );
}
-void LLFloater::onClickTearOff(void *userdata)
+void LLFloater::onClickTearOff(LLFloater* self)
{
- LLFloater* self = (LLFloater*) userdata;
- if (!self) return;
-
+ if (!self)
+ return;
+ S32 floater_header_size = self->mHeaderHeight;
LLMultiFloater* host_floater = self->getHost();
if (host_floater) //Tear off
{
@@ -1297,17 +1433,18 @@ void LLFloater::onClickTearOff(void *userdata)
// reparent to floater view
gFloaterView->addChild(self);
- self->open(); /* Flawfinder: ignore */
+ self->openFloater(self->getKey());
// only force position for floaters that don't have that data saved
- if (self->getRectControl().empty())
+ if (self->mRectControl.size() <= 1)
{
- new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - LLFLOATER_HEADER_SIZE - 5, self->getRect().getWidth(), self->getRect().getHeight());
+ new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - floater_header_size - 5, self->getRect().getWidth(), self->getRect().getHeight());
self->setRect(new_rect);
}
gFloaterView->adjustToFitScreen(self, FALSE);
// give focus to new window to keep continuity for the user
self->setFocus(TRUE);
+ self->setTornOff(true);
}
else //Attach to parent.
{
@@ -1317,18 +1454,34 @@ void LLFloater::onClickTearOff(void *userdata)
self->setMinimized(FALSE); // to reenable minimize button if it was minimized
new_host->showFloater(self);
// make sure host is visible
- new_host->open();
+ new_host->openFloater(new_host->getKey());
}
+ self->setTornOff(false);
}
+ self->updateButtons();
}
// static
-void LLFloater::onClickEdit(void *userdata)
+void LLFloater::onClickDock(LLFloater* self)
{
- LLFloater* self = (LLFloater*) userdata;
- if (!self) return;
+ if(self && self->mCanDock)
+ {
+ self->setDocked(!self->mDocked, true);
+ }
+}
- self->mEditing = self->mEditing ? FALSE : TRUE;
+// static
+void LLFloater::onClickHelp( LLFloater* self )
+{
+ if (self && LLUI::sHelpImpl)
+ {
+ // find the current help context for this floater
+ std::string help_topic;
+ if (self->findHelpTopic(help_topic))
+ {
+ LLUI::sHelpImpl->showTopic(help_topic);
+ }
+ }
}
// static
@@ -1354,7 +1507,8 @@ LLFloater* LLFloater::getClosableFloaterFromFocus()
// The focused floater may not be closable,
// Find and close a parental floater that is closeable, if any.
- for(LLFloater* floater_to_close = focused_floater;
+ LLFloater* prev_floater = NULL;
+ for(LLFloater* floater_to_close = focused_floater;
NULL != floater_to_close;
floater_to_close = gFloaterView->getParentFloater(floater_to_close))
{
@@ -1362,6 +1516,14 @@ LLFloater* LLFloater::getClosableFloaterFromFocus()
{
return floater_to_close;
}
+
+ // If floater has as parent root view
+ // gFloaterView->getParentFloater(floater_to_close) returns
+ // the same floater_to_close, so we need to check this.
+ if (prev_floater == floater_to_close) {
+ break;
+ }
+ prev_floater = floater_to_close;
}
return NULL;
@@ -1373,7 +1535,7 @@ void LLFloater::closeFocusedFloater()
LLFloater* floater_to_close = LLFloater::getClosableFloaterFromFocus();
if(floater_to_close)
{
- floater_to_close->close();
+ floater_to_close->closeFloater();
}
// if nothing took focus after closing focused floater
@@ -1388,18 +1550,18 @@ void LLFloater::closeFocusedFloater()
// static
-void LLFloater::onClickClose( void* userdata )
+void LLFloater::onClickClose( LLFloater* self )
{
- LLFloater* self = (LLFloater*) userdata;
- if (!self) return;
-
- self->close();
+ if (!self)
+ return;
+ self->closeFloater(false);
}
// virtual
void LLFloater::draw()
{
+ F32 alpha = getDrawContext().mAlpha;
// draw background
if( isBackgroundVisible() )
{
@@ -1408,34 +1570,56 @@ void LLFloater::draw()
S32 right = getRect().getWidth() - LLPANEL_BORDER_WIDTH;
S32 bottom = LLPANEL_BORDER_WIDTH;
- LLColor4 shadow_color = LLUI::sColorsGroup->getColor("ColorDropShadow");
- F32 shadow_offset = (F32)LLUI::sConfigGroup->getS32("DropShadowFloater");
+ static LLUICachedControl<S32> shadow_offset_S32 ("DropShadowFloater", 0);
+ static LLUIColor shadow_color_cached = LLUIColorTable::instance().getColor("ColorDropShadow");
+ LLColor4 shadow_color = shadow_color_cached;
+ F32 shadow_offset = (F32)shadow_offset_S32;
+
if (!isBackgroundOpaque())
{
shadow_offset *= 0.2f;
shadow_color.mV[VALPHA] *= 0.5f;
}
gl_drop_shadow(left, top, right, bottom,
- shadow_color,
+ shadow_color % alpha,
llround(shadow_offset));
- // No transparent windows in simple UI
+ LLUIImage* image = NULL;
+ LLColor4 color;
if (isBackgroundOpaque())
{
- gl_rect_2d( left, top, right, bottom, getBackgroundColor() );
+ // NOTE: image may not be set
+ image = getBackgroundImage();
+ color = getBackgroundColor();
}
else
{
- gl_rect_2d( left, top, right, bottom, getTransparentColor() );
+ image = getTransparentImage();
+ color = getTransparentColor();
}
- if(gFocusMgr.childHasKeyboardFocus(this) && !getIsChrome() && !getCurrentTitle().empty())
+ if (image)
+ {
+ // We're using images for this floater's backgrounds
+ image->draw(getLocalRect(), UI_VERTEX_COLOR % alpha);
+ }
+ else
{
+ // We're not using images, use old-school flat colors
+ gl_rect_2d( left, top, right, bottom, color % alpha );
+
// draw highlight on title bar to indicate focus. RDW
- const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF );
- LLRect r = getRect();
- gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - (S32)font->getLineHeight() - 1,
- LLUI::sColorsGroup->getColor("TitleBarFocusColor"), 0, TRUE);
+ if(hasFocus()
+ && !getIsChrome()
+ && !getCurrentTitle().empty())
+ {
+ static LLUIColor titlebar_focus_color = LLUIColorTable::instance().getColor("TitleBarFocusColor");
+
+ const LLFontGL* font = LLFontGL::getFontSansSerif();
+ LLRect r = getRect();
+ gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - (S32)font->getLineHeight() - 1,
+ titlebar_focus_color % alpha, 0, TRUE);
+ }
}
}
@@ -1445,9 +1629,9 @@ void LLFloater::draw()
{
if (hasFocus() && getDefaultButton()->getEnabled())
{
- LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus();
+ LLFocusableElement* focus_ctrl = gFocusMgr.getKeyboardFocus();
// is this button a direct descendent and not a nested widget (e.g. checkbox)?
- BOOL focus_is_child_button = dynamic_cast<LLButton*>(focus_ctrl) != NULL && focus_ctrl->getParent() == this;
+ BOOL focus_is_child_button = dynamic_cast<LLButton*>(focus_ctrl) != NULL && dynamic_cast<LLButton*>(focus_ctrl)->getParent() == this;
// only enable default button when current focus is not a button
getDefaultButton()->setBorderEnabled(!focus_is_child_button);
}
@@ -1466,8 +1650,9 @@ void LLFloater::draw()
}
else
{
+ //FIXME: get rid of this hack
// draw children
- LLView* focused_child = gFocusMgr.getKeyboardFocus();
+ LLView* focused_child = dynamic_cast<LLView*>(gFocusMgr.getKeyboardFocus());
BOOL focused_child_visible = FALSE;
if (focused_child && focused_child->getParent() == this)
{
@@ -1485,16 +1670,6 @@ void LLFloater::draw()
drawChild(focused_child);
}
- if( isBackgroundVisible() )
- {
- // add in a border to improve spacialized visual aclarity ;)
- // use lines instead of gl_rect_2d so we can round the edges as per james' recommendation
- LLUI::setLineWidth(1.5f);
- LLColor4 outlineColor = gFocusMgr.childHasKeyboardFocus(this) ? LLUI::sColorsGroup->getColor("FloaterFocusBorderColor") : LLUI::sColorsGroup->getColor("FloaterUnfocusBorderColor");
- gl_rect_2d_offset_local(0, getRect().getHeight() + 1, getRect().getWidth() + 1, 0, outlineColor, -LLPANEL_BORDER_WIDTH, FALSE);
- LLUI::setLineWidth(1.f);
- }
-
// update tearoff button for torn off floaters
// when last host goes away
if (mCanTearOff && !getHost())
@@ -1511,6 +1686,7 @@ void LLFloater::setCanMinimize(BOOL can_minimize)
{
// if removing minimize/restore button programmatically,
// go ahead and unminimize floater
+ mCanMinimize = can_minimize;
if (!can_minimize)
{
setMinimized(FALSE);
@@ -1524,6 +1700,7 @@ void LLFloater::setCanMinimize(BOOL can_minimize)
void LLFloater::setCanClose(BOOL can_close)
{
+ mCanClose = can_close;
mButtonsEnabled[BUTTON_CLOSE] = can_close;
updateButtons();
@@ -1538,83 +1715,10 @@ void LLFloater::setCanTearOff(BOOL can_tear_off)
}
-void LLFloater::setCanResize(BOOL can_resize)
+void LLFloater::setCanResize(BOOL can_resize)
{
- if (mResizable && !can_resize)
- {
- for (S32 i = 0; i < 4; i++)
- {
- removeChild(mResizeBar[i], TRUE);
- mResizeBar[i] = NULL;
-
- removeChild(mResizeHandle[i], TRUE);
- mResizeHandle[i] = NULL;
- }
- }
- else if (!mResizable && can_resize)
- {
- // Resize bars (sides)
- const S32 RESIZE_BAR_THICKNESS = 3;
- mResizeBar[0] = new LLResizeBar(
- std::string("resizebar_left"),
- this,
- LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0),
- mMinWidth, S32_MAX, LLResizeBar::LEFT );
- addChild( mResizeBar[0] );
-
- mResizeBar[1] = new LLResizeBar(
- std::string("resizebar_top"),
- this,
- LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS),
- mMinHeight, S32_MAX, LLResizeBar::TOP );
- addChild( mResizeBar[1] );
-
- mResizeBar[2] = new LLResizeBar(
- std::string("resizebar_right"),
- this,
- LLRect( getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0),
- mMinWidth, S32_MAX, LLResizeBar::RIGHT );
- addChild( mResizeBar[2] );
-
- mResizeBar[3] = new LLResizeBar(
- std::string("resizebar_bottom"),
- this,
- LLRect( 0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0),
- mMinHeight, S32_MAX, LLResizeBar::BOTTOM );
- addChild( mResizeBar[3] );
-
-
- // Resize handles (corners)
- mResizeHandle[0] = new LLResizeHandle(
- std::string("Resize Handle"),
- LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0),
- mMinWidth,
- mMinHeight,
- LLResizeHandle::RIGHT_BOTTOM);
- addChild(mResizeHandle[0]);
-
- mResizeHandle[1] = new LLResizeHandle( std::string("resize"),
- LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_HANDLE_HEIGHT),
- mMinWidth,
- mMinHeight,
- LLResizeHandle::RIGHT_TOP );
- addChild(mResizeHandle[1]);
-
- mResizeHandle[2] = new LLResizeHandle( std::string("resize"),
- LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 ),
- mMinWidth,
- mMinHeight,
- LLResizeHandle::LEFT_BOTTOM );
- addChild(mResizeHandle[2]);
-
- mResizeHandle[3] = new LLResizeHandle( std::string("resize"),
- LLRect( 0, getRect().getHeight(), RESIZE_HANDLE_WIDTH, getRect().getHeight() - RESIZE_HANDLE_HEIGHT ),
- mMinWidth,
- mMinHeight,
- LLResizeHandle::LEFT_TOP );
- addChild(mResizeHandle[3]);
- }
mResizable = can_resize;
+ enableResizeCtrls(can_resize);
}
void LLFloater::setCanDrag(BOOL can_drag)
@@ -1633,17 +1737,37 @@ void LLFloater::setCanDrag(BOOL can_drag)
void LLFloater::updateButtons()
{
+ static LLUICachedControl<S32> floater_close_box_size ("UIFloaterCloseBoxSize", 0);
+ static LLUICachedControl<S32> close_box_from_top ("UICloseBoxFromTop", 0);
S32 button_count = 0;
for (S32 i = 0; i < BUTTON_COUNT; i++)
{
- if(!mButtons[i]) continue;
- mButtons[i]->setEnabled(mButtonsEnabled[i]);
+ if (!mButtons[i])
+ {
+ continue;
+ }
- if (mButtonsEnabled[i]
- //*HACK: always render close button for hosted floaters
- // so that users don't accidentally hit the button when closing multiple windows
- // in the chatterbox
- || (i == BUTTON_CLOSE && mButtonScale != 1.f))
+ bool enabled = mButtonsEnabled[i];
+ if (i == BUTTON_HELP)
+ {
+ // don't show the help button if the floater is minimized
+ // or if it is a docked tear-off floater
+ if (isMinimized() || (mButtonsEnabled[BUTTON_TEAR_OFF] && ! mTornOff))
+ {
+ enabled = false;
+ }
+ }
+ if (i == BUTTON_CLOSE && mButtonScale != 1.f)
+ {
+ //*HACK: always render close button for hosted floaters so
+ //that users don't accidentally hit the button when
+ //closing multiple windows in the chatterbox
+ enabled = true;
+ }
+
+ mButtons[i]->setEnabled(enabled);
+
+ if (enabled)
{
button_count++;
@@ -1652,17 +1776,17 @@ void LLFloater::updateButtons()
{
btn_rect.setLeftTopAndSize(
LLPANEL_BORDER_WIDTH,
- getRect().getHeight() - CLOSE_BOX_FROM_TOP - (LLFLOATER_CLOSE_BOX_SIZE + 1) * button_count,
- llround((F32)LLFLOATER_CLOSE_BOX_SIZE * mButtonScale),
- llround((F32)LLFLOATER_CLOSE_BOX_SIZE * mButtonScale));
+ getRect().getHeight() - close_box_from_top - (floater_close_box_size + 1) * button_count,
+ llround((F32)floater_close_box_size * mButtonScale),
+ llround((F32)floater_close_box_size * mButtonScale));
}
else
{
btn_rect.setLeftTopAndSize(
- getRect().getWidth() - LLPANEL_BORDER_WIDTH - (LLFLOATER_CLOSE_BOX_SIZE + 1) * button_count,
- getRect().getHeight() - CLOSE_BOX_FROM_TOP,
- llround((F32)LLFLOATER_CLOSE_BOX_SIZE * mButtonScale),
- llround((F32)LLFLOATER_CLOSE_BOX_SIZE * mButtonScale));
+ getRect().getWidth() - LLPANEL_BORDER_WIDTH - (floater_close_box_size + 1) * button_count,
+ getRect().getHeight() - close_box_from_top,
+ llround((F32)floater_close_box_size * mButtonScale),
+ llround((F32)floater_close_box_size * mButtonScale));
}
mButtons[i]->setRect(btn_rect);
@@ -1670,56 +1794,65 @@ void LLFloater::updateButtons()
// the restore button should have a tab stop so that it takes action when you Ctrl-Tab to a minimized floater
mButtons[i]->setTabStop(i == BUTTON_RESTORE);
}
- else if (mButtons[i])
+ else
{
mButtons[i]->setVisible(FALSE);
}
}
if (mDragHandle)
- mDragHandle->setMaxTitleWidth(getRect().getWidth() - (button_count * (LLFLOATER_CLOSE_BOX_SIZE + 1)));
+ mDragHandle->setMaxTitleWidth(getRect().getWidth() - (button_count * (floater_close_box_size + 1)));
}
-void LLFloater::buildButtons()
+void LLFloater::buildButtons(const Params& floater_params)
{
+ static LLUICachedControl<S32> floater_close_box_size ("UIFloaterCloseBoxSize", 0);
+ static LLUICachedControl<S32> close_box_from_top ("UICloseBoxFromTop", 0);
for (S32 i = 0; i < BUTTON_COUNT; i++)
{
+ if (mButtons[i])
+ {
+ removeChild(mButtons[i]);
+ delete mButtons[i];
+ mButtons[i] = NULL;
+ }
+
LLRect btn_rect;
if (mDragOnLeft)
{
btn_rect.setLeftTopAndSize(
LLPANEL_BORDER_WIDTH,
- getRect().getHeight() - CLOSE_BOX_FROM_TOP - (LLFLOATER_CLOSE_BOX_SIZE + 1) * (i + 1),
- llround(LLFLOATER_CLOSE_BOX_SIZE * mButtonScale),
- llround(LLFLOATER_CLOSE_BOX_SIZE * mButtonScale));
+ getRect().getHeight() - close_box_from_top - (floater_close_box_size + 1) * (i + 1),
+ llround(floater_close_box_size * mButtonScale),
+ llround(floater_close_box_size * mButtonScale));
}
else
{
btn_rect.setLeftTopAndSize(
- getRect().getWidth() - LLPANEL_BORDER_WIDTH - (LLFLOATER_CLOSE_BOX_SIZE + 1) * (i + 1),
- getRect().getHeight() - CLOSE_BOX_FROM_TOP,
- llround(LLFLOATER_CLOSE_BOX_SIZE * mButtonScale),
- llround(LLFLOATER_CLOSE_BOX_SIZE * mButtonScale));
- }
-
- LLButton* buttonp = new LLButton(
- sButtonNames[i],
- btn_rect,
- sButtonActiveImageNames[i],
- sButtonPressedImageNames[i],
- LLStringUtil::null,
- sButtonCallbacks[i],
- this,
- LLFontGL::getFontSansSerif());
-
- buttonp->setTabStop(FALSE);
- buttonp->setFollowsTop();
- buttonp->setFollowsRight();
- buttonp->setToolTip( sButtonToolTips[i] );
- buttonp->setImageColor(LLUI::sColorsGroup->getColor("FloaterButtonImageColor"));
- buttonp->setHoverImages(sButtonPressedImageNames[i],
- sButtonPressedImageNames[i]);
- buttonp->setScaleImage(TRUE);
- buttonp->setSaveToXML(false);
+ getRect().getWidth() - LLPANEL_BORDER_WIDTH - (floater_close_box_size + 1) * (i + 1),
+ getRect().getHeight() - close_box_from_top,
+ llround(floater_close_box_size * mButtonScale),
+ llround(floater_close_box_size * mButtonScale));
+ }
+
+ LLButton::Params p;
+ p.name(sButtonNames[i]);
+ p.rect(btn_rect);
+ p.image_unselected = getButtonImage(floater_params, (EFloaterButton)i);
+ // Selected, no matter if hovered or not, is "pressed"
+ LLUIImage* pressed_image = getButtonPressedImage(floater_params, (EFloaterButton)i);
+ p.image_selected = pressed_image;
+ p.image_hover_selected = pressed_image;
+ // Use a glow effect when the user hovers over the button
+ // These icons are really small, need glow amount increased
+ p.hover_glow_amount( 0.33f );
+ p.click_callback.function(boost::bind(sButtonCallbacks[i], this));
+ p.tab_stop(false);
+ p.follows.flags(FOLLOWS_TOP|FOLLOWS_RIGHT);
+ p.tool_tip = getButtonTooltip(floater_params, (EFloaterButton)i);
+ p.scale_image(true);
+ p.chrome(true);
+
+ LLButton* buttonp = LLUICtrlFactory::create<LLButton>(p);
addChild(buttonp);
mButtons[i] = buttonp;
}
@@ -1727,16 +1860,66 @@ void LLFloater::buildButtons()
updateButtons();
}
+// static
+LLUIImage* LLFloater::getButtonImage(const Params& p, EFloaterButton e)
+{
+ switch(e)
+ {
+ default:
+ case BUTTON_CLOSE:
+ return p.close_image;
+ case BUTTON_RESTORE:
+ return p.restore_image;
+ case BUTTON_MINIMIZE:
+ return p.minimize_image;
+ case BUTTON_TEAR_OFF:
+ return p.tear_off_image;
+ case BUTTON_DOCK:
+ return p.dock_image;
+ case BUTTON_HELP:
+ return p.help_image;
+ }
+}
+
+// static
+LLUIImage* LLFloater::getButtonPressedImage(const Params& p, EFloaterButton e)
+{
+ switch(e)
+ {
+ default:
+ case BUTTON_CLOSE:
+ return p.close_pressed_image;
+ case BUTTON_RESTORE:
+ return p.restore_pressed_image;
+ case BUTTON_MINIMIZE:
+ return p.minimize_pressed_image;
+ case BUTTON_TEAR_OFF:
+ return p.tear_off_pressed_image;
+ case BUTTON_DOCK:
+ return p.dock_pressed_image;
+ case BUTTON_HELP:
+ return p.help_pressed_image;
+ }
+}
+
+// static
+std::string LLFloater::getButtonTooltip(const Params& p, EFloaterButton e)
+{
+ // TODO: per-floater localizable tooltips set in XML
+ return sButtonToolTips[e];
+}
+
/////////////////////////////////////////////////////
// LLFloaterView
-LLFloaterView::LLFloaterView( const std::string& name, const LLRect& rect )
-: LLUICtrl( name, rect, FALSE, NULL, NULL, FOLLOWS_ALL ),
+static LLDefaultChildRegistry::Register<LLFloaterView> r("floater_view");
+
+LLFloaterView::LLFloaterView (const Params& p)
+: LLUICtrl (p),
mFocusCycleMode(FALSE),
mSnapOffsetBottom(0)
+ ,mSnapOffsetRight(0)
{
- setTabStop(FALSE);
- resetStartingFloaterPosition();
}
// By default, adjust vertical.
@@ -1760,41 +1943,50 @@ void LLFloaterView::reshapeFloater(S32 width, S32 height, BOOL called_from_paren
// dependents use same follow flags as their "dependee"
continue;
}
- LLRect r = floaterp->getRect();
-
- // Compute absolute distance from each edge of screen
- S32 left_offset = llabs(r.mLeft - 0);
- S32 right_offset = llabs(old_width - r.mRight);
-
- S32 top_offset = llabs(old_height - r.mTop);
- S32 bottom_offset = llabs(r.mBottom - 0);
// Make if follow the edge it is closest to
U32 follow_flags = 0x0;
- if (left_offset < right_offset)
+ if (floaterp->isMinimized())
{
- follow_flags |= FOLLOWS_LEFT;
+ follow_flags |= (FOLLOWS_LEFT | FOLLOWS_TOP);
}
else
{
- follow_flags |= FOLLOWS_RIGHT;
- }
+ LLRect r = floaterp->getRect();
- // "No vertical adjustment" usually means that the bottom of the view
- // has been pushed up or down. Hence we want the floaters to follow
- // the top.
- if (!adjust_vertical)
- {
- follow_flags |= FOLLOWS_TOP;
- }
- else if (top_offset < bottom_offset)
- {
- follow_flags |= FOLLOWS_TOP;
- }
- else
- {
- follow_flags |= FOLLOWS_BOTTOM;
+ // Compute absolute distance from each edge of screen
+ S32 left_offset = llabs(r.mLeft - 0);
+ S32 right_offset = llabs(old_width - r.mRight);
+
+ S32 top_offset = llabs(old_height - r.mTop);
+ S32 bottom_offset = llabs(r.mBottom - 0);
+
+
+ if (left_offset < right_offset)
+ {
+ follow_flags |= FOLLOWS_LEFT;
+ }
+ else
+ {
+ follow_flags |= FOLLOWS_RIGHT;
+ }
+
+ // "No vertical adjustment" usually means that the bottom of the view
+ // has been pushed up or down. Hence we want the floaters to follow
+ // the top.
+ if (!adjust_vertical)
+ {
+ follow_flags |= FOLLOWS_TOP;
+ }
+ else if (top_offset < bottom_offset)
+ {
+ follow_flags |= FOLLOWS_TOP;
+ }
+ else
+ {
+ follow_flags |= FOLLOWS_BOTTOM;
+ }
}
floaterp->setFollows(follow_flags);
@@ -1830,74 +2022,11 @@ void LLFloaterView::restoreAll()
}
-void LLFloaterView::getNewFloaterPosition(S32* left,S32* top)
-{
- // Workaround: mRect may change between when this object is created and the first time it is used.
- static BOOL first = TRUE;
- if( first )
- {
- resetStartingFloaterPosition();
- first = FALSE;
- }
-
- const S32 FLOATER_PAD = 16;
- LLCoordWindow window_size;
- getWindow()->getSize(&window_size);
- LLRect full_window(0, window_size.mY, window_size.mX, 0);
- LLRect floater_creation_rect(
- 160,
- full_window.getHeight() - 2 * MENU_BAR_HEIGHT,
- full_window.getWidth() * 2 / 3,
- 130 );
- floater_creation_rect.stretch( -FLOATER_PAD );
-
- *left = mNextLeft;
- *top = mNextTop;
-
- const S32 STEP = 25;
- S32 bottom = floater_creation_rect.mBottom + 2 * STEP;
- S32 right = floater_creation_rect.mRight - 4 * STEP;
-
- mNextTop -= STEP;
- mNextLeft += STEP;
-
- if( (mNextTop < bottom ) || (mNextLeft > right) )
- {
- mColumn++;
- mNextTop = floater_creation_rect.mTop;
- mNextLeft = STEP * mColumn;
-
- if( (mNextTop < bottom) || (mNextLeft > right) )
- {
- // Advancing the column didn't work, so start back at the beginning
- resetStartingFloaterPosition();
- }
- }
-}
-
-void LLFloaterView::resetStartingFloaterPosition()
-{
- const S32 FLOATER_PAD = 16;
- LLCoordWindow window_size;
- getWindow()->getSize(&window_size);
- LLRect full_window(0, window_size.mY, window_size.mX, 0);
- LLRect floater_creation_rect(
- 160,
- full_window.getHeight() - 2 * MENU_BAR_HEIGHT,
- full_window.getWidth() * 2 / 3,
- 130 );
- floater_creation_rect.stretch( -FLOATER_PAD );
-
- mNextLeft = floater_creation_rect.mLeft;
- mNextTop = floater_creation_rect.mTop;
- mColumn = 0;
-}
-
LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLFloater* neighbor )
{
LLRect base_rect = reference_floater->getRect();
- S32 width = neighbor->getRect().getWidth();
- S32 height = neighbor->getRect().getHeight();
+ LLRect::tCoordType width = neighbor->getRect().getWidth();
+ LLRect::tCoordType height = neighbor->getRect().getHeight();
LLRect new_rect = neighbor->getRect();
LLRect expanded_base_rect = base_rect;
@@ -1910,16 +2039,16 @@ LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLF
if (sibling &&
sibling != neighbor &&
sibling->getVisible() &&
- expanded_base_rect.rectInRect(&sibling->getRect()))
+ expanded_base_rect.overlaps(sibling->getRect()))
{
base_rect.unionWith(sibling->getRect());
}
}
- S32 left_margin = llmax(0, base_rect.mLeft);
- S32 right_margin = llmax(0, getRect().getWidth() - base_rect.mRight);
- S32 top_margin = llmax(0, getRect().getHeight() - base_rect.mTop);
- S32 bottom_margin = llmax(0, base_rect.mBottom);
+ LLRect::tCoordType left_margin = llmax(0, base_rect.mLeft);
+ LLRect::tCoordType right_margin = llmax(0, getRect().getWidth() - base_rect.mRight);
+ LLRect::tCoordType top_margin = llmax(0, getRect().getHeight() - base_rect.mTop);
+ LLRect::tCoordType bottom_margin = llmax(0, base_rect.mBottom);
// find position for floater in following order
// right->left->bottom->top
@@ -2038,6 +2167,11 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus)
if (give_focus && !gFocusMgr.childHasKeyboardFocus(child))
{
child->setFocus(TRUE);
+ // floater did not take focus, so relinquish focus to world
+ if (!child->hasFocus())
+ {
+ gFocusMgr.setKeyboardFocus(NULL);
+ }
}
}
@@ -2104,16 +2238,19 @@ void LLFloaterView::focusFrontFloater()
void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom)
{
- S32 col = 0;
+ const LLFloater::Params& default_params = LLFloater::getDefaultParams();
+ S32 floater_header_size = default_params.header_height;
+ static LLUICachedControl<S32> minimized_width ("UIMinimizedWidth", 0);
LLRect snap_rect_local = getLocalSnapRect();
- for(S32 row = snap_rect_local.mBottom;
- row < snap_rect_local.getHeight() - LLFLOATER_HEADER_SIZE;
- row += LLFLOATER_HEADER_SIZE ) //loop rows
- {
- for(col = snap_rect_local.mLeft;
- col < snap_rect_local.getWidth() - MINIMIZED_WIDTH;
- col += MINIMIZED_WIDTH)
+ for(S32 col = snap_rect_local.mLeft;
+ col < snap_rect_local.getWidth() - minimized_width;
+ col += minimized_width)
+ {
+ for(S32 row = snap_rect_local.mTop - floater_header_size;
+ row > floater_header_size;
+ row -= floater_header_size ) //loop rows
{
+
bool foundGap = TRUE;
for(child_list_const_iter_t child_it = getChildList()->begin();
child_it != getChildList()->end();
@@ -2124,10 +2261,10 @@ void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom)
if(floater->isMinimized())
{
LLRect r = floater->getRect();
- if((r.mBottom < (row + LLFLOATER_HEADER_SIZE))
- && (r.mBottom > (row - LLFLOATER_HEADER_SIZE))
- && (r.mLeft < (col + MINIMIZED_WIDTH))
- && (r.mLeft > (col - MINIMIZED_WIDTH)))
+ if((r.mBottom < (row + floater_header_size))
+ && (r.mBottom > (row - floater_header_size))
+ && (r.mLeft < (col + minimized_width))
+ && (r.mLeft > (col - minimized_width)))
{
// needs the check for off grid. can't drag,
// but window resize makes them off
@@ -2179,7 +2316,7 @@ void LLFloaterView::closeAllChildren(bool app_quitting)
// dialogs to appear.
if (floaterp->canClose() && !floaterp->isDead())
{
- floaterp->close(app_quitting);
+ floaterp->closeFloater(app_quitting);
}
}
}
@@ -2202,14 +2339,13 @@ BOOL LLFloaterView::allChildrenClosed()
return true;
}
-
void LLFloaterView::refresh()
{
// Constrain children to be entirely on the screen
for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
{
- LLFloater* floaterp = (LLFloater*)*child_it;
- if( floaterp->getVisible() )
+ LLFloater* floaterp = dynamic_cast<LLFloater*>(*child_it);
+ if (floaterp && floaterp->getVisible() )
{
// minimized floaters are kept fully onscreen
adjustToFitScreen(floaterp, !floaterp->isMinimized());
@@ -2224,12 +2360,12 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out
// floater is hosted elsewhere, so ignore
return;
}
- S32 screen_width = getSnapRect().getWidth();
- S32 screen_height = getSnapRect().getHeight();
- // convert to local coordinate frame
- LLRect snap_rect_local = getLocalSnapRect();
+ LLRect::tCoordType screen_width = getSnapRect().getWidth();
+ LLRect::tCoordType screen_height = getSnapRect().getHeight();
- if( floater->isResizable() )
+
+ // only automatically resize non-minimized, resizable floaters
+ if( floater->isResizable() && !floater->isMinimized() )
{
LLRect view_rect = floater->getRect();
S32 old_width = view_rect.getWidth();
@@ -2252,21 +2388,18 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out
new_width = llmax(new_width, min_width);
new_height = llmax(new_height, min_height);
+ LLRect new_rect;
+ new_rect.setLeftTopAndSize(view_rect.mLeft,view_rect.mTop,new_width, new_height);
+
floater->reshape( new_width, new_height, TRUE );
- if (floater->followsRight())
- {
- floater->translate(old_width - new_width, 0);
- }
+ floater->setRect(new_rect);
- if (floater->followsTop())
- {
- floater->translate(0, old_height - new_height);
- }
+ floater->translateIntoRect( getLocalRect(), false );
}
}
// move window fully onscreen
- if (floater->translateIntoRect( snap_rect_local, allow_partial_outside ))
+ if (floater->translateIntoRect( getLocalRect(), allow_partial_outside ))
{
floater->clearSnapTarget();
}
@@ -2302,11 +2435,12 @@ LLRect LLFloaterView::getSnapRect() const
{
LLRect snap_rect = getRect();
snap_rect.mBottom += mSnapOffsetBottom;
+ snap_rect.mRight -= mSnapOffsetRight;
return snap_rect;
}
-LLFloater *LLFloaterView::getFocusedFloater()
+LLFloater *LLFloaterView::getFocusedFloater() const
{
for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
{
@@ -2319,7 +2453,7 @@ LLFloater *LLFloaterView::getFocusedFloater()
return NULL;
}
-LLFloater *LLFloaterView::getFrontmost()
+LLFloater *LLFloaterView::getFrontmost() const
{
for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
{
@@ -2332,7 +2466,7 @@ LLFloater *LLFloaterView::getFrontmost()
return NULL;
}
-LLFloater *LLFloaterView::getBackmost()
+LLFloater *LLFloaterView::getBackmost() const
{
LLFloater* back_most = NULL;
for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
@@ -2348,18 +2482,51 @@ LLFloater *LLFloaterView::getBackmost()
void LLFloaterView::syncFloaterTabOrder()
{
- // bring focused floater to front
- for ( child_list_const_reverse_iter_t child_it = getChildList()->rbegin(); child_it != getChildList()->rend(); ++child_it)
+ // look for a visible modal dialog, starting from first (should be only one)
+ LLModalDialog* modal_dialog = NULL;
+ for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
{
- LLFloater* floaterp = (LLFloater*)*child_it;
- if (gFocusMgr.childHasKeyboardFocus(floaterp))
+ LLModalDialog* dialog = dynamic_cast<LLModalDialog*>(*child_it);
+ if (dialog && dialog->isModal() && dialog->getVisible())
{
- bringToFront(floaterp, FALSE);
+ modal_dialog = dialog;
break;
}
}
- // then sync draw order to tab order
+ if (modal_dialog)
+ {
+ // If we have a visible modal dialog, make sure that it has focus
+ if( gFocusMgr.getTopCtrl() != modal_dialog )
+ {
+ gFocusMgr.setTopCtrl( modal_dialog );
+ }
+
+ if( !gFocusMgr.childHasKeyboardFocus( modal_dialog ) )
+ {
+ modal_dialog->setFocus(TRUE);
+ }
+
+ if( !gFocusMgr.childHasMouseCapture( modal_dialog ) )
+ {
+ gFocusMgr.setMouseCapture( modal_dialog );
+ }
+ }
+ else
+ {
+ // otherwise, make sure the focused floater is in the front of the child list
+ for ( child_list_const_reverse_iter_t child_it = getChildList()->rbegin(); child_it != getChildList()->rend(); ++child_it)
+ {
+ LLFloater* floaterp = (LLFloater*)*child_it;
+ if (gFocusMgr.childHasKeyboardFocus(floaterp))
+ {
+ bringToFront(floaterp, FALSE);
+ break;
+ }
+ }
+ }
+
+ // sync draw order to tab order
for ( child_list_const_reverse_iter_t child_it = getChildList()->rbegin(); child_it != getChildList()->rend(); ++child_it)
{
LLFloater* floaterp = (LLFloater*)*child_it;
@@ -2367,7 +2534,7 @@ void LLFloaterView::syncFloaterTabOrder()
}
}
-LLFloater* LLFloaterView::getParentFloater(LLView* viewp)
+LLFloater* LLFloaterView::getParentFloater(LLView* viewp) const
{
LLView* parentp = viewp->getParent();
@@ -2415,8 +2582,12 @@ void LLFloaterView::pushVisibleAll(BOOL visible, const skip_list_t& skip_list)
void LLFloaterView::popVisibleAll(const skip_list_t& skip_list)
{
- for (child_list_const_iter_t child_iter = getChildList()->begin();
- child_iter != getChildList()->end(); ++child_iter)
+ // make a copy of the list since some floaters change their
+ // order in the childList when changing visibility.
+ child_list_t child_list_copy = *getChildList();
+
+ for (child_list_const_iter_t child_iter = child_list_copy.begin();
+ child_iter != child_list_copy.end(); ++child_iter)
{
LLView *view = *child_iter;
if (skip_list.find(view) == skip_list.end())
@@ -2426,641 +2597,211 @@ void LLFloaterView::popVisibleAll(const skip_list_t& skip_list)
}
}
-//
-// LLMultiFloater
-//
-
-LLMultiFloater::LLMultiFloater() :
- mTabContainer(NULL),
- mTabPos(LLTabContainer::TOP),
- mAutoResize(TRUE),
- mOrigMinWidth(0),
- mOrigMinHeight(0)
-{
-
-}
-
-LLMultiFloater::LLMultiFloater(LLTabContainer::TabPosition tab_pos) :
- mTabContainer(NULL),
- mTabPos(tab_pos),
- mAutoResize(TRUE),
- mOrigMinWidth(0),
- mOrigMinHeight(0)
-{
-
-}
-
-LLMultiFloater::LLMultiFloater(const std::string &name) :
- LLFloater(name),
- mTabContainer(NULL),
- mTabPos(LLTabContainer::TOP),
- mAutoResize(FALSE),
- mOrigMinWidth(0),
- mOrigMinHeight(0)
-{
-}
-
-LLMultiFloater::LLMultiFloater(
- const std::string& name,
- const LLRect& rect,
- LLTabContainer::TabPosition tab_pos,
- BOOL auto_resize) :
- LLFloater(name, rect, name),
- mTabContainer(NULL),
- mTabPos(LLTabContainer::TOP),
- mAutoResize(auto_resize),
- mOrigMinWidth(0),
- mOrigMinHeight(0)
-{
- mTabContainer = new LLTabContainer(std::string("Preview Tabs"),
- LLRect(LLPANEL_BORDER_WIDTH, getRect().getHeight() - LLFLOATER_HEADER_SIZE, getRect().getWidth() - LLPANEL_BORDER_WIDTH, 0),
- mTabPos,
- FALSE,
- FALSE);
- mTabContainer->setFollowsAll();
- if (isResizable())
- {
- mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
- }
-
- addChild(mTabContainer);
-}
-
-LLMultiFloater::LLMultiFloater(
- const std::string& name,
- const std::string& rect_control,
- LLTabContainer::TabPosition tab_pos,
- BOOL auto_resize) :
- LLFloater(name, rect_control, name),
- mTabContainer(NULL),
- mTabPos(tab_pos),
- mAutoResize(auto_resize),
- mOrigMinWidth(0),
- mOrigMinHeight(0)
-{
- mTabContainer = new LLTabContainer(std::string("Preview Tabs"),
- LLRect(LLPANEL_BORDER_WIDTH, getRect().getHeight() - LLFLOATER_HEADER_SIZE, getRect().getWidth() - LLPANEL_BORDER_WIDTH, 0),
- mTabPos,
- FALSE,
- FALSE);
- mTabContainer->setFollowsAll();
- if (isResizable() && mTabPos == LLTabContainer::BOTTOM)
- {
- mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
- }
-
- addChild(mTabContainer);
-
-}
-
-
-void LLMultiFloater::open() /* Flawfinder: ignore */
-{
- if (mTabContainer->getTabCount() > 0)
- {
- LLFloater::open(); /* Flawfinder: ignore */
- }
- else
- {
- // for now, don't allow multifloaters
- // without any child floaters
- close();
- }
-}
-
-void LLMultiFloater::onClose(bool app_quitting)
-{
- if(closeAllFloaters() == TRUE)
- {
- LLFloater::onClose(app_quitting);
- }//else not all tabs could be closed...
-}
-
-void LLMultiFloater::draw()
+void LLFloater::setInstanceName(const std::string& name)
{
- if (mTabContainer->getTabCount() == 0)
- {
- //RN: could this potentially crash in draw hierarchy?
- close();
- }
- else
- {
- for (S32 i = 0; i < mTabContainer->getTabCount(); i++)
- {
- LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(i);
- if (floaterp->getShortTitle() != mTabContainer->getPanelTitle(i))
- {
- mTabContainer->setPanelTitle(i, floaterp->getShortTitle());
- }
- }
- LLFloater::draw();
- }
-}
-
-BOOL LLMultiFloater::closeAllFloaters()
-{
- S32 tabToClose = 0;
- S32 lastTabCount = mTabContainer->getTabCount();
- while (tabToClose < mTabContainer->getTabCount())
- {
- LLFloater* first_floater = (LLFloater*)mTabContainer->getPanelByIndex(tabToClose);
- first_floater->close();
- if(lastTabCount == mTabContainer->getTabCount())
- {
- //Tab did not actually close, possibly due to a pending Save Confirmation dialog..
- //so try and close the next one in the list...
- tabToClose++;
- }else
- {
- //Tab closed ok.
- lastTabCount = mTabContainer->getTabCount();
- }
- }
- if( mTabContainer->getTabCount() != 0 )
- return FALSE; // Couldn't close all the tabs (pending save dialog?) so return FALSE.
- return TRUE; //else all tabs were successfully closed...
-}
-
-void LLMultiFloater::growToFit(S32 content_width, S32 content_height)
-{
- S32 new_width = llmax(getRect().getWidth(), content_width + LLPANEL_BORDER_WIDTH * 2);
- S32 new_height = llmax(getRect().getHeight(), content_height + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT);
-
- if (isMinimized())
- {
- LLRect newrect;
- newrect.setLeftTopAndSize(getExpandedRect().mLeft, getExpandedRect().mTop, new_width, new_height);
- setExpandedRect(newrect);
- }
- else
- {
- S32 old_height = getRect().getHeight();
- reshape(new_width, new_height);
- // keep top left corner in same position
- translate(0, old_height - new_height);
- }
-}
-
-/**
- void addFloater(LLFloater* floaterp, BOOL select_added_floater)
-
- Adds the LLFloater pointed to by floaterp to this.
- If floaterp is already hosted by this, then it is re-added to get
- new titles, etc.
- If select_added_floater is true, the LLFloater pointed to by floaterp will
- become the selected tab in this
-
- Affects: mTabContainer, floaterp
-**/
-void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point)
-{
- if (!floaterp)
- {
- return;
- }
-
- if (!mTabContainer)
- {
- llerrs << "Tab Container used without having been initialized." << llendl;
+ if (name == mInstanceName)
return;
- }
-
- if (floaterp->getHost() == this)
- {
- // already hosted by me, remove
- // do this so we get updated title, etc.
- mFloaterDataMap.erase(floaterp->getHandle());
- mTabContainer->removeTabPanel(floaterp);
- }
- else if (floaterp->getHost())
+ llassert_always(mInstanceName.empty());
+ mInstanceName = name;
+ if (!mInstanceName.empty())
{
- // floaterp is hosted by somebody else and
- // this is adding it, so remove it from it's old host
- floaterp->getHost()->removeFloater(floaterp);
- }
- else if (floaterp->getParent() == gFloaterView)
- {
- // rehost preview floater as child panel
- gFloaterView->removeChild(floaterp);
- }
-
- // store original configuration
- LLFloaterData floater_data;
- floater_data.mWidth = floaterp->getRect().getWidth();
- floater_data.mHeight = floaterp->getRect().getHeight();
- floater_data.mCanMinimize = floaterp->isMinimizeable();
- floater_data.mCanResize = floaterp->isResizable();
-
- // remove minimize and close buttons
- floaterp->setCanMinimize(FALSE);
- floaterp->setCanResize(FALSE);
- floaterp->setCanDrag(FALSE);
- floaterp->storeRectControl();
- // avoid double rendering of floater background (makes it more opaque)
- floaterp->setBackgroundVisible(FALSE);
-
- if (mAutoResize)
- {
- growToFit(floater_data.mWidth, floater_data.mHeight);
- }
-
- //add the panel, add it to proper maps
- mTabContainer->addTabPanel(floaterp, floaterp->getShortTitle(), FALSE, onTabSelected, this, 0, FALSE, insertion_point);
- mFloaterDataMap[floaterp->getHandle()] = floater_data;
-
- updateResizeLimits();
-
- if ( select_added_floater )
- {
- mTabContainer->selectTabPanel(floaterp);
- }
- else
- {
- // reassert visible tab (hiding new floater if necessary)
- mTabContainer->selectTab(mTabContainer->getCurrentPanelIndex());
- }
-
- floaterp->setHost(this);
- if (isMinimized())
- {
- floaterp->setVisible(FALSE);
- }
-}
-
-/**
- BOOL selectFloater(LLFloater* floaterp)
-
- If the LLFloater pointed to by floaterp is hosted by this,
- then its tab is selected and returns true. Otherwise returns false.
-
- Affects: mTabContainer
-**/
-BOOL LLMultiFloater::selectFloater(LLFloater* floaterp)
-{
- return mTabContainer->selectTabPanel(floaterp);
-}
-
-// virtual
-void LLMultiFloater::selectNextFloater()
-{
- mTabContainer->selectNextTab();
-}
-
-// virtual
-void LLMultiFloater::selectPrevFloater()
-{
- mTabContainer->selectPrevTab();
-}
-
-void LLMultiFloater::showFloater(LLFloater* floaterp)
-{
- // we won't select a panel that already is selected
- // it is hard to do this internally to tab container
- // as tab selection is handled via index and the tab at a given
- // index might have changed
- if (floaterp != mTabContainer->getCurrentPanel() &&
- !mTabContainer->selectTabPanel(floaterp))
- {
- addFloater(floaterp, TRUE);
- }
-}
-
-void LLMultiFloater::removeFloater(LLFloater* floaterp)
-{
- if ( floaterp->getHost() != this )
- return;
-
- floater_data_map_t::iterator found_data_it = mFloaterDataMap.find(floaterp->getHandle());
- if (found_data_it != mFloaterDataMap.end())
- {
- LLFloaterData& floater_data = found_data_it->second;
- floaterp->setCanMinimize(floater_data.mCanMinimize);
- if (!floater_data.mCanResize)
+ // save_rect and save_visibility only apply to registered floaters
+ if (!mRectControl.empty())
{
- // restore original size
- floaterp->reshape(floater_data.mWidth, floater_data.mHeight);
+ mRectControl = LLFloaterReg::declareRectControl(mInstanceName);
}
- floaterp->setCanResize(floater_data.mCanResize);
- mFloaterDataMap.erase(found_data_it);
- }
- mTabContainer->removeTabPanel(floaterp);
- floaterp->setBackgroundVisible(TRUE);
- floaterp->setCanDrag(TRUE);
- floaterp->setHost(NULL);
- floaterp->applyRectControl();
-
- updateResizeLimits();
-
- tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), false);
-}
-
-void LLMultiFloater::tabOpen(LLFloater* opened_floater, bool from_click)
-{
- // default implementation does nothing
-}
-
-void LLMultiFloater::tabClose()
-{
- if (mTabContainer->getTabCount() == 0)
- {
- // no more children, close myself
- close();
- }
-}
-
-void LLMultiFloater::setVisible(BOOL visible)
-{
- // *FIX: shouldn't have to do this, fix adding to minimized multifloater
- LLFloater::setVisible(visible);
-
- if (mTabContainer)
- {
- LLPanel* cur_floaterp = mTabContainer->getCurrentPanel();
-
- if (cur_floaterp)
+ if (!mVisibilityControl.empty())
{
- cur_floaterp->setVisible(visible);
+ mVisibilityControl = LLFloaterReg::declareVisibilityControl(mInstanceName);
}
-
- // if no tab selected, and we're being shown,
- // select last tab to be added
- if (visible && !cur_floaterp)
+ if(!mDocStateControl.empty())
{
- mTabContainer->selectLastTab();
+ mDocStateControl = LLFloaterReg::declareDockStateControl(mInstanceName);
}
- }
-}
-BOOL LLMultiFloater::handleKeyHere(KEY key, MASK mask)
-{
- if (key == 'W' && mask == MASK_CONTROL)
- {
- LLFloater* floater = getActiveFloater();
- // is user closeable and is system closeable
- if (floater && floater->canClose() && floater->isCloseable())
- {
- floater->close();
- }
- return TRUE;
}
-
- return LLFloater::handleKeyHere(key, mask);
}
-LLFloater* LLMultiFloater::getActiveFloater()
+void LLFloater::setKey(const LLSD& newkey)
{
- return (LLFloater*)mTabContainer->getCurrentPanel();
+ // Note: We don't have to do anything special with registration when we change keys
+ mKey = newkey;
}
-S32 LLMultiFloater::getFloaterCount()
-{
- return mTabContainer->getTabCount();
-}
-
-/**
- BOOL isFloaterFlashing(LLFloater* floaterp)
-
- Returns true if the LLFloater pointed to by floaterp
- is currently in a flashing state and is hosted by this.
- False otherwise.
-
- Requires: floaterp != NULL
-**/
-BOOL LLMultiFloater::isFloaterFlashing(LLFloater* floaterp)
+//static
+void LLFloater::setupParamsForExport(Params& p, LLView* parent)
{
- if ( floaterp && floaterp->getHost() == this )
- return mTabContainer->getTabPanelFlashing(floaterp);
+ // Do rectangle munging to topleft layout first
+ LLPanel::setupParamsForExport(p, parent);
- return FALSE;
-}
+ // Copy the rectangle out to apply layout constraints
+ LLRect rect = p.rect;
-/**
- BOOL setFloaterFlashing(LLFloater* floaterp, BOOL flashing)
+ // Null out other settings
+ p.rect.left.setProvided(false);
+ p.rect.top.setProvided(false);
+ p.rect.right.setProvided(false);
+ p.rect.bottom.setProvided(false);
- Sets the current flashing state of the LLFloater pointed
- to by floaterp to be the BOOL flashing if the LLFloater pointed
- to by floaterp is hosted by this.
+ // Explicitly set width/height
+ p.rect.width.set( rect.getWidth(), true );
+ p.rect.height.set( rect.getHeight(), true );
- Requires: floaterp != NULL
-**/
-void LLMultiFloater::setFloaterFlashing(LLFloater* floaterp, BOOL flashing)
-{
- if ( floaterp && floaterp->getHost() == this )
- mTabContainer->setTabPanelFlashing(floaterp, flashing);
+ // If you can't resize this floater, don't export min_height
+ // and min_width
+ bool can_resize = p.can_resize;
+ if (!can_resize)
+ {
+ p.min_height.setProvided(false);
+ p.min_width.setProvided(false);
+ }
}
-//static
-void LLMultiFloater::onTabSelected(void* userdata, bool from_click)
+void LLFloater::initFromParams(const LLFloater::Params& p)
{
- LLMultiFloater* floaterp = (LLMultiFloater*)userdata;
+ // *NOTE: We have too many classes derived from LLFloater to retrofit them
+ // all to pass in params via constructors. So we use this method.
- floaterp->tabOpen((LLFloater*)floaterp->mTabContainer->getCurrentPanel(), from_click);
-}
+ // control_name, tab_stop, focus_lost_callback, initial_value, rect, enabled, visible
+ LLPanel::initFromParams(p);
-void LLMultiFloater::setCanResize(BOOL can_resize)
-{
- LLFloater::setCanResize(can_resize);
- if (isResizable() && mTabContainer->getTabPosition() == LLTabContainer::BOTTOM)
- {
- mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
- }
- else
- {
- mTabContainer->setRightTabBtnOffset(0);
- }
-}
+ mTitle = p.title;
+ mShortTitle = p.short_title;
+ applyTitle();
-BOOL LLMultiFloater::postBuild()
-{
- // remember any original xml minimum size
- getResizeLimits(&mOrigMinWidth, &mOrigMinHeight);
+ setCanTearOff(p.can_tear_off);
+ setCanMinimize(p.can_minimize);
+ setCanClose(p.can_close);
+ setCanDock(p.can_dock);
+ setCanResize(p.can_resize);
+ setResizeLimits(p.min_width, p.min_height);
+
+ mDragOnLeft = p.can_drag_on_left;
+ mHeaderHeight = p.header_height;
+ mLegacyHeaderHeight = p.legacy_header_height;
+ mSingleInstance = p.single_instance;
+ mAutoTile = p.auto_tile;
- if (mTabContainer)
+ if (p.save_rect)
{
- return TRUE;
+ mRectControl = "t"; // flag to build mRectControl name once mInstanceName is set
}
-
- requires<LLTabContainer>("Preview Tabs");
- if (checkRequirements())
+ if (p.save_visibility)
{
- mTabContainer = getChild<LLTabContainer>("Preview Tabs");
- return TRUE;
+ mVisibilityControl = "t"; // flag to build mVisibilityControl name once mInstanceName is set
}
- return FALSE;
-}
-
-void LLMultiFloater::updateResizeLimits()
-{
- // initialize minimum size constraint to the original xml values.
- S32 new_min_width = mOrigMinWidth;
- S32 new_min_height = mOrigMinHeight;
- // possibly increase minimum size constraint due to children's minimums.
- for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx)
+ if(p.save_dock_state)
{
- LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx);
- if (floaterp)
- {
- new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2);
- new_min_height = llmax(new_min_height, floaterp->getMinHeight() + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT);
- }
+ mDocStateControl = "t"; // flag to build mDocStateControl name once mInstanceName is set
}
- setResizeLimits(new_min_width, new_min_height);
-
- S32 cur_height = getRect().getHeight();
- S32 new_width = llmax(getRect().getWidth(), new_min_width);
- S32 new_height = llmax(getRect().getHeight(), new_min_height);
-
- if (isMinimized())
+
+ // open callback
+ if (p.open_callback.isProvided())
{
- const LLRect& expanded = getExpandedRect();
- LLRect newrect;
- newrect.setLeftTopAndSize(expanded.mLeft, expanded.mTop, llmax(expanded.getWidth(), new_width), llmax(expanded.getHeight(), new_height));
- setExpandedRect(newrect);
+ mOpenSignal.connect(initCommitCallback(p.open_callback));
}
- else
+ // close callback
+ if (p.close_callback.isProvided())
{
- reshape(new_width, new_height);
-
- // make sure upper left corner doesn't move
- translate(0, cur_height - getRect().getHeight());
-
- // make sure this window is visible on screen when it has been modified
- // (tab added, etc)
- gFloaterView->adjustToFitScreen(this, TRUE);
+ mCloseSignal.connect(initCommitCallback(p.close_callback));
}
}
-// virtual
-LLXMLNodePtr LLFloater::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLPanel::getXML();
-
- node->createChild("title", TRUE)->setStringValue(getCurrentTitle());
-
- node->createChild("can_resize", TRUE)->setBoolValue(isResizable());
-
- node->createChild("can_minimize", TRUE)->setBoolValue(isMinimizeable());
-
- node->createChild("can_close", TRUE)->setBoolValue(isCloseable());
-
- node->createChild("can_drag_on_left", TRUE)->setBoolValue(isDragOnLeft());
-
- node->createChild("min_width", TRUE)->setIntValue(getMinWidth());
-
- node->createChild("min_height", TRUE)->setIntValue(getMinHeight());
+LLFastTimer::DeclareTimer POST_BUILD("Floater Post Build");
- node->createChild("can_tear_off", TRUE)->setBoolValue(mCanTearOff);
-
- return node;
-}
-
-// static
-LLView* LLFloater::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
+bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)
{
- std::string name("floater");
- node->getAttributeString("name", name);
-
- LLFloater *floaterp = new LLFloater(name);
+ Params params(LLUICtrlFactory::getDefaultParams<LLFloater>());
+ LLXUIParser::instance().readXUI(node, params); // *TODO: Error checking
- std::string filename;
- node->getAttributeString("filename", filename);
-
- if (filename.empty())
+ if (output_node)
{
- // Load from node
- floaterp->initFloaterXML(node, parent, factory);
+ Params output_params(params);
+ setupParamsForExport(output_params, parent);
+ Params default_params(LLUICtrlFactory::getDefaultParams<LLFloater>());
+ output_node->setName(node->getName()->mString);
+ LLXUIParser::instance().writeXUI(
+ output_node, output_params, &default_params);
}
- else
+
+ // Default floater position to top-left corner of screen
+ // However, some legacy floaters have explicit top or bottom
+ // coordinates set, so respect their wishes.
+ if (!params.rect.top.isProvided() && !params.rect.bottom.isProvided())
{
- // Load from file
- factory->buildFloater(floaterp, filename);
+ params.rect.top.set(0);
}
-
- return floaterp;
-}
-
-void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory, BOOL open) /* Flawfinder: ignore */
-{
- std::string name(getName());
- std::string title(getCurrentTitle());
- std::string short_title(getShortTitle());
- std::string rect_control("");
- BOOL resizable = isResizable();
- S32 min_width = getMinWidth();
- S32 min_height = getMinHeight();
- BOOL drag_on_left = isDragOnLeft();
- BOOL minimizable = isMinimizeable();
- BOOL close_btn = isCloseable();
- LLRect rect;
-
- node->getAttributeString("name", name);
- node->getAttributeString("title", title);
- node->getAttributeString("short_title", short_title);
- node->getAttributeString("rect_control", rect_control);
- node->getAttributeBOOL("can_resize", resizable);
- node->getAttributeBOOL("can_minimize", minimizable);
- node->getAttributeBOOL("can_close", close_btn);
- node->getAttributeBOOL("can_drag_on_left", drag_on_left);
- node->getAttributeS32("min_width", min_width);
- node->getAttributeS32("min_height", min_height);
-
- if (! rect_control.empty())
+ if (!params.rect.left.isProvided() && !params.rect.right.isProvided())
{
- setRectControl(rect_control);
+ params.rect.left.set(0);
}
- createRect(node, rect, parent, LLRect());
+ params.from_xui = true;
+ applyXUILayout(params, parent);
+ initFromParams(params);
- setRect(rect);
- setName(name);
-
- initFloater(title,
- resizable,
- min_width,
- min_height,
- drag_on_left,
- minimizable,
- close_btn);
-
- setTitle(title);
- applyTitle ();
-
- setShortTitle(short_title);
-
- BOOL can_tear_off;
- if (node->getAttributeBOOL("can_tear_off", can_tear_off))
- {
- setCanTearOff(can_tear_off);
- }
+ initFloater(params);
- initFromXML(node, parent);
-
LLMultiFloater* last_host = LLFloater::getFloaterHost();
if (node->hasName("multi_floater"))
{
LLFloater::setFloaterHost((LLMultiFloater*) this);
}
- initChildrenXML(node, factory);
+ LLUICtrlFactory::createChildren(this, node, child_registry_t::instance(), output_node);
if (node->hasName("multi_floater"))
{
LLFloater::setFloaterHost(last_host);
}
+
+ // HACK: When we changed the header height to 25 pixels in Viewer 2, rather
+ // than re-layout all the floaters we use this value in pixels to make the
+ // whole floater bigger and change the top-left coordinate for widgets.
+ // The goal is to eventually set mLegacyHeaderHeight to zero, which would
+ // make the top-left corner for widget layout the same as the top-left
+ // corner of the window's content area. James
+ S32 header_stretch = (mHeaderHeight - mLegacyHeaderHeight);
+ if (header_stretch > 0)
+ {
+ // Stretch the floater vertically, don't move widgets
+ LLRect rect = getRect();
+ rect.mTop += header_stretch;
- BOOL result = postBuild();
+ // This will also update drag handle, title bar, close box, etc.
+ setRect(rect);
+ }
- if (!result)
+ BOOL result;
{
- llerrs << "Failed to construct floater " << name << llendl;
+ LLFastTimer ft(POST_BUILD);
+
+ result = postBuild();
}
- applyRectControl();
- if (open) /* Flawfinder: ignore */
+ if (!result)
{
- this->open(); /* Flawfinder: ignore */
+ llerrs << "Failed to construct floater " << getName() << llendl;
}
+ applyRectControl(); // If we have a saved rect control, apply it
+ gFloaterView->adjustToFitScreen(this, FALSE); // Floaters loaded from XML should all fit on screen
+
moveResizeHandlesToFront();
+
+ applyDockState();
+
+ return true; // *TODO: Error checking
+}
+
+bool LLFloater::isShown() const
+{
+ return ! isMinimized() && isInVisibleChain();
+}
+
+/* static */
+bool LLFloater::isShown(const LLFloater* floater)
+{
+ return floater && floater->isShown();
}
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 0e3d148b09..f70495c0f0 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -39,8 +39,7 @@
#include "llpanel.h"
#include "lluuid.h"
-#include "lltabcontainer.h"
-#include "llnotifications.h"
+//#include "llnotificationsutil.h"
#include <set>
class LLDragHandle;
@@ -50,17 +49,10 @@ class LLButton;
class LLMultiFloater;
class LLFloater;
-const S32 LLFLOATER_VPAD = 6;
-const S32 LLFLOATER_HPAD = 6;
-const S32 LLFLOATER_CLOSE_BOX_SIZE = 16;
-const S32 LLFLOATER_HEADER_SIZE = 18;
const BOOL RESIZE_YES = TRUE;
const BOOL RESIZE_NO = FALSE;
-const S32 DEFAULT_MIN_WIDTH = 100;
-const S32 DEFAULT_MIN_HEIGHT = 100;
-
const BOOL DRAG_ON_TOP = FALSE;
const BOOL DRAG_ON_LEFT = TRUE;
@@ -73,78 +65,104 @@ const BOOL CLOSE_NO = FALSE;
const BOOL ADJUST_VERTICAL_YES = TRUE;
const BOOL ADJUST_VERTICAL_NO = FALSE;
-// associates a given notification instance with a particular floater
-class LLFloaterNotificationContext :
- public LLNotificationContext
-{
-public:
- LLFloaterNotificationContext(LLHandle<LLFloater> floater_handle) :
- mFloaterHandle(floater_handle)
- {}
-
- LLFloater* getFloater() { return mFloaterHandle.get(); }
-private:
- LLHandle<LLFloater> mFloaterHandle;
-};
-
-
class LLFloater : public LLPanel
{
friend class LLFloaterView;
+friend class LLFloaterReg;
+friend class LLMultiFloater;
public:
- enum EFloaterButtons
+ struct KeyCompare
{
- BUTTON_CLOSE,
+// static bool compare(const LLSD& a, const LLSD& b);
+ static bool equate(const LLSD& a, const LLSD& b);
+/*==========================================================================*|
+ bool operator()(const LLSD& a, const LLSD& b) const
+ {
+ return compare(a, b);
+ }
+|*==========================================================================*/
+ };
+
+ enum EFloaterButton
+ {
+ BUTTON_CLOSE = 0,
BUTTON_RESTORE,
BUTTON_MINIMIZE,
BUTTON_TEAR_OFF,
- BUTTON_EDIT,
+ BUTTON_DOCK,
+ BUTTON_HELP,
BUTTON_COUNT
};
- LLFloater();
- LLFloater(const std::string& name); //simple constructor for data-driven initialization
- LLFloater( const std::string& name, const LLRect& rect, const std::string& title,
- BOOL resizable = FALSE,
- S32 min_width = DEFAULT_MIN_WIDTH,
- S32 min_height = DEFAULT_MIN_HEIGHT,
- BOOL drag_on_left = FALSE,
- BOOL minimizable = TRUE,
- BOOL close_btn = TRUE,
- BOOL bordered = BORDER_NO);
-
- LLFloater( const std::string& name, const std::string& rect_control, const std::string& title,
- BOOL resizable = FALSE,
- S32 min_width = DEFAULT_MIN_WIDTH,
- S32 min_height = DEFAULT_MIN_HEIGHT,
- BOOL drag_on_left = FALSE,
- BOOL minimizable = TRUE,
- BOOL close_btn = TRUE,
- BOOL bordered = BORDER_NO);
+ struct Params
+ : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ Optional<std::string> title,
+ short_title;
+
+ Optional<bool> single_instance,
+ auto_tile,
+ can_resize,
+ can_minimize,
+ can_close,
+ can_drag_on_left,
+ can_tear_off,
+ save_rect,
+ save_visibility,
+ save_dock_state,
+ can_dock;
+ Optional<S32> header_height,
+ legacy_header_height; // HACK see initFromXML()
+
+ // Images for top-right controls
+ Optional<LLUIImage*> close_image,
+ restore_image,
+ minimize_image,
+ tear_off_image,
+ dock_image,
+ help_image;
+ Optional<LLUIImage*> close_pressed_image,
+ restore_pressed_image,
+ minimize_pressed_image,
+ tear_off_pressed_image,
+ dock_pressed_image,
+ help_pressed_image;
+
+ Optional<CommitCallbackParam> open_callback,
+ close_callback;
+
+ Params();
+ };
+
+ // use this to avoid creating your own default LLFloater::Param instance
+ static const Params& getDefaultParams();
+
+ // Load translations for tooltips for standard buttons
+ static void initClass();
+
+ LLFloater(const LLSD& key, const Params& params = getDefaultParams());
virtual ~LLFloater();
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
- void initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory, BOOL open = TRUE);
+ // Don't export top/left for rect, only height/width
+ static void setupParamsForExport(Params& p, LLView* parent);
- /*virtual*/ void userSetShape(const LLRect& new_rect);
+ void initFromParams(const LLFloater::Params& p);
+ bool initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL);
+
+ /*virtual*/ void handleReshape(const LLRect& new_rect, bool by_user = false);
/*virtual*/ BOOL canSnapTo(const LLView* other_view);
- /*virtual*/ void snappedTo(const LLView* snap_view);
+ /*virtual*/ void setSnappedTo(const LLView* snap_view);
/*virtual*/ void setFocus( BOOL b );
/*virtual*/ void setIsChrome(BOOL is_chrome);
+ /*virtual*/ void setRect(const LLRect &rect);
- // Can be called multiple times to reset floater parameters.
- // Deletes all children of the floater.
- virtual void initFloater(const std::string& title, BOOL resizable,
- S32 min_width, S32 min_height, BOOL drag_on_left,
- BOOL minimizable, BOOL close_btn);
+ void initFloater(const Params& p);
- virtual void open(); /* Flawfinder: ignore */
+ void openFloater(const LLSD& key = LLSD());
// If allowed, close the floater cleanly, releasing focus.
- // app_quitting is passed to onClose() below.
- virtual void close(bool app_quitting = false);
+ void closeFloater(bool app_quitting = false);
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
@@ -153,18 +171,15 @@ public:
// moves to center of gFloaterView
void center();
- // applies rectangle stored in mRectControl, if any
- void applyRectControl();
-
- LLMultiFloater* getHost() { return (LLMultiFloater*)mHostHandle.get(); }
+ LLMultiFloater* getHost();
void applyTitle();
- const std::string& getCurrentTitle() const;
+ std::string getCurrentTitle() const;
void setTitle( const std::string& title);
- std::string getTitle();
+ std::string getTitle() const;
void setShortTitle( const std::string& short_title );
- std::string getShortTitle();
+ std::string getShortTitle() const;
void setTitleVisible(bool visible);
virtual void setMinimized(BOOL b);
void moveResizeHandlesToFront();
@@ -172,7 +187,14 @@ public:
void addDependentFloater(LLHandle<LLFloater> dependent_handle, BOOL reposition = TRUE);
LLFloater* getDependee() { return (LLFloater*)mDependeeHandle.get(); }
void removeDependentFloater(LLFloater* dependent);
- BOOL isMinimized() { return mMinimized; }
+ BOOL isMinimized() const { return mMinimized; }
+ /// isShown() differs from getVisible() in that isShown() also considers
+ /// isMinimized(). isShown() is true only if visible and not minimized.
+ bool isShown() const;
+ /// The static isShown() can accept a NULL pointer (which of course
+ /// returns false). When non-NULL, it calls the non-static isShown().
+ static bool isShown(const LLFloater* floater);
+ BOOL isFirstLook() { return mFirstLook; } // EXT-2653: This function is necessary to prevent overlapping for secondary showed toasts
BOOL isFrontmost();
BOOL isDependent() { return !mDependeeHandle.isDead(); }
void setCanMinimize(BOOL can_minimize);
@@ -185,33 +207,34 @@ public:
void setResizeLimits( S32 min_width, S32 min_height );
void getResizeLimits( S32* min_width, S32* min_height ) { *min_width = mMinWidth; *min_height = mMinHeight; }
- bool isMinimizeable() const{ return mButtonsEnabled[BUTTON_MINIMIZE]; }
- // Does this window have a close button, NOT can we close it right now.
- bool isCloseable() const{ return (mButtonsEnabled[BUTTON_CLOSE]); }
+ bool isMinimizeable() const{ return mCanMinimize; }
+ bool isCloseable() const{ return mCanClose; }
bool isDragOnLeft() const{ return mDragOnLeft; }
S32 getMinWidth() const{ return mMinWidth; }
S32 getMinHeight() const{ return mMinHeight; }
+ S32 getHeaderHeight() const { return mHeaderHeight; }
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask);
+
+ virtual BOOL handleScrollWheel(S32 x, S32 y, S32 mask);
+
virtual void draw();
-
- virtual void onOpen() {}
-
- // Call destroy() to free memory, or setVisible(FALSE) to keep it
- // If app_quitting, you might not want to save your visibility.
- // Defaults to destroy().
- virtual void onClose(bool app_quitting) { destroy(); }
+
+ virtual void onOpen(const LLSD& key) {}
+ virtual void onClose(bool app_quitting) {}
// This cannot be "const" until all derived floater canClose()
// methods are const as well. JC
virtual BOOL canClose() { return TRUE; }
- virtual void setVisible(BOOL visible);
+ /*virtual*/ void setVisible(BOOL visible); // do not override
+ /*virtual*/ void handleVisibilityChange ( BOOL new_visibility ); // do not override
+
void setFrontmost(BOOL take_focus = TRUE);
-
+
// Defaults to false.
virtual BOOL canSaveAs() const { return FALSE; }
@@ -222,6 +245,18 @@ public:
LLHandle<LLFloater> getSnapTarget() const { return mSnappedTo; }
LLHandle<LLFloater> getHandle() const { return mHandle; }
+ const LLSD& getKey() { return mKey; }
+ BOOL matchesKey(const LLSD& key) { return mSingleInstance || KeyCompare::equate(key, mKey); }
+
+ const std::string& getInstanceName() { return mInstanceName; }
+
+ bool isDockable() const { return mCanDock; }
+ void setCanDock(bool b);
+
+ bool isDocked() const { return mDocked; }
+ virtual void setDocked(bool docked, bool pop_on_undock = true);
+
+ virtual void setTornOff(bool torn_off) { mTornOff = torn_off; }
// Return a closeable floater, if any, given the current focus.
static LLFloater* getClosableFloaterFromFocus();
@@ -230,69 +265,118 @@ public:
// handle refocusing.
static void closeFocusedFloater();
- LLNotification::Params contextualNotification(const std::string& name)
- {
- return LLNotification::Params(name).context(mNotificationContext);
- }
+// LLNotification::Params contextualNotification(const std::string& name)
+// {
+// return LLNotification::Params(name).context(mNotificationContext);
+// }
- static void onClickClose(void *userdata);
- static void onClickMinimize(void *userdata);
- static void onClickTearOff(void *userdata);
- static void onClickEdit(void *userdata);
+ static void onClickClose(LLFloater* floater);
+ static void onClickMinimize(LLFloater* floater);
+ static void onClickTearOff(LLFloater* floater);
+ static void onClickDock(LLFloater* floater);
+ static void onClickHelp(LLFloater* floater);
static void setFloaterHost(LLMultiFloater* hostp) {sHostp = hostp; }
- static void setEditModeEnabled(BOOL enable);
- static BOOL getEditModeEnabled() { return sEditModeEnabled; }
- static LLMultiFloater* getFloaterHost() {return sHostp; }
-
+ static LLMultiFloater* getFloaterHost() {return sHostp; }
+
protected:
+ void setRectControl(const std::string& rectname) { mRectControl = rectname; };
+
+ virtual void applySavedVariables();
+
+ void applyRectControl();
+ void applyDockState();
+ void storeRectControl();
+ void storeVisibilityControl();
+ void storeDockStateControl();
+
+ void setKey(const LLSD& key);
+ void setInstanceName(const std::string& name);
+
virtual void bringToFront(S32 x, S32 y);
virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE);
- void setExpandedRect(const LLRect& rect) { mExpandedRect = rect; } // size when not minimized
+ void setExpandedRect(const LLRect& rect) { mExpandedRect = rect; } // size when not minimized
const LLRect& getExpandedRect() const { return mExpandedRect; }
void setAutoFocus(BOOL focus) { mAutoFocus = focus; } // whether to automatically take focus when opened
LLDragHandle* getDragHandle() const { return mDragHandle; }
- void destroy() { die(); } // Don't call this directly. You probably want to call close(). JC
+ void destroy() { die(); } // Don't call this directly. You probably want to call closeFloater()
private:
-
void setForeground(BOOL b); // called only by floaterview
void cleanupHandles(); // remove handles to dead floaters
void createMinimizeButton();
void updateButtons();
- void buildButtons();
- BOOL offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButtons index);
+ void buildButtons(const Params& p);
+
+ // Images and tooltips are named in the XML, but we want to look them
+ // up by index.
+ static LLUIImage* getButtonImage(const Params& p, EFloaterButton e);
+ static LLUIImage* getButtonPressedImage(const Params& p, EFloaterButton e);
+ static std::string getButtonTooltip(const Params& p, EFloaterButton e);
+
+ BOOL offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButton index);
+ void addResizeCtrls();
+ void layoutResizeCtrls();
+ void enableResizeCtrls(bool enable);
+ void addDragHandle();
+ void layoutDragHandle(); // repair layout
+
+public:
+ // Called when floater is opened, passes mKey
+ // Public so external views or floaters can watch for this floater opening
+ commit_signal_t mOpenSignal;
+
+ // Called when floater is closed, passes app_qitting as LLSD()
+ // Public so external views or floaters can watch for this floater closing
+ commit_signal_t mCloseSignal;
+
+protected:
+ std::string mRectControl;
+ std::string mVisibilityControl;
+ std::string mDocStateControl;
+ LLSD mKey; // Key used for retrieving instances; set (for now) by LLFLoaterReg
- LLRect mExpandedRect;
LLDragHandle* mDragHandle;
LLResizeBar* mResizeBar[4];
LLResizeHandle* mResizeHandle[4];
- LLButton *mMinimizeButton;
+
+private:
+ LLRect mExpandedRect;
+
+ LLUIString mTitle;
+ LLUIString mShortTitle;
+
+ BOOL mSingleInstance; // TRUE if there is only ever one instance of the floater
+ std::string mInstanceName; // Store the instance name so we can remove ourselves from the list
+ BOOL mAutoTile; // TRUE if placement of new instances tiles
+
BOOL mCanTearOff;
+ BOOL mCanMinimize;
+ BOOL mCanClose;
+ BOOL mDragOnLeft;
+ BOOL mResizable;
+
+ S32 mMinWidth;
+ S32 mMinHeight;
+ S32 mHeaderHeight; // height in pixels of header for title, drag bar
+ S32 mLegacyHeaderHeight;// HACK see initFloaterXML()
+
BOOL mMinimized;
BOOL mForeground;
LLHandle<LLFloater> mDependeeHandle;
- std::string mTitle;
- std::string mShortTitle;
+
BOOL mFirstLook; // TRUE if the _next_ time this floater is visible will be the first time in the session that it is visible.
-
- BOOL mResizable;
- S32 mMinWidth;
- S32 mMinHeight;
-
- BOOL mEditing;
typedef std::set<LLHandle<LLFloater> > handle_set_t;
typedef std::set<LLHandle<LLFloater> >::iterator handle_set_iter_t;
handle_set_t mDependents;
- bool mDragOnLeft;
- BOOL mButtonsEnabled[BUTTON_COUNT];
+ bool mButtonsEnabled[BUTTON_COUNT];
LLButton* mButtons[BUTTON_COUNT];
F32 mButtonScale;
BOOL mAutoFocus;
@@ -301,14 +385,17 @@ private:
LLHandle<LLFloater> mHostHandle;
LLHandle<LLFloater> mLastHostHandle;
+ bool mCanDock;
+ bool mDocked;
+ bool mTornOff;
+
static LLMultiFloater* sHostp;
- static BOOL sEditModeEnabled;
- static std::string sButtonActiveImageNames[BUTTON_COUNT];
- static std::string sButtonInactiveImageNames[BUTTON_COUNT];
- static std::string sButtonPressedImageNames[BUTTON_COUNT];
+ static BOOL sQuitting;
static std::string sButtonNames[BUTTON_COUNT];
static std::string sButtonToolTips[BUTTON_COUNT];
- typedef void (*click_callback)(void *);
+ static std::string sButtonToolTipsIndex[BUTTON_COUNT];
+
+ typedef void(*click_callback)(LLFloater*);
static click_callback sButtonCallbacks[BUTTON_COUNT];
typedef std::map<LLHandle<LLFloater>, LLFloater*> handle_map_t;
@@ -320,29 +407,30 @@ private:
BOOL mHasBeenDraggedWhileMinimized;
S32 mPreviousMinimizedBottom;
S32 mPreviousMinimizedLeft;
-
- LLFloaterNotificationContext* mNotificationContext;
+
+// LLFloaterNotificationContext* mNotificationContext;
LLRootHandle<LLFloater> mHandle;
};
+
/////////////////////////////////////////////////////////////
// LLFloaterView
// Parent of all floating panels
class LLFloaterView : public LLUICtrl
{
-public:
- LLFloaterView( const std::string& name, const LLRect& rect );
+protected:
+ LLFloaterView (const Params& p);
+ friend class LLUICtrlFactory;
+public:
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
void reshapeFloater(S32 width, S32 height, BOOL called_from_parent, BOOL adjust_vertical);
/*virtual*/ void draw();
/*virtual*/ LLRect getSnapRect() const;
- void refresh();
+ /*virtual*/ void refresh();
- void getNewFloaterPosition( S32* left, S32* top );
- void resetStartingFloaterPosition();
LLRect findNeighboringPosition( LLFloater* reference_floater, LLFloater* neighbor );
// Given a child of gFloaterView, make sure this view can fit entirely onscreen.
@@ -365,10 +453,10 @@ public:
void closeAllChildren(bool app_quitting);
BOOL allChildrenClosed();
- LLFloater* getFrontmost();
- LLFloater* getBackmost();
- LLFloater* getParentFloater(LLView* viewp);
- LLFloater* getFocusedFloater();
+ LLFloater* getFrontmost() const;
+ LLFloater* getBackmost() const;
+ LLFloater* getParentFloater(LLView* viewp) const;
+ LLFloater* getFocusedFloater() const;
void syncFloaterTabOrder();
// Returns z order of child provided. 0 is closest, larger numbers
@@ -377,6 +465,7 @@ public:
S32 getZOrder(LLFloater* child);
void setSnapOffsetBottom(S32 offset) { mSnapOffsetBottom = offset; }
+ void setSnapOffsetRight(S32 offset) { mSnapOffsetRight = offset; }
private:
S32 mColumn;
@@ -384,110 +473,12 @@ private:
S32 mNextTop;
BOOL mFocusCycleMode;
S32 mSnapOffsetBottom;
+ S32 mSnapOffsetRight;
};
-// https://wiki.lindenlab.com/mediawiki/index.php?title=LLMultiFloater&oldid=81376
-class LLMultiFloater : public LLFloater
-{
-public:
- LLMultiFloater();
- LLMultiFloater(LLTabContainer::TabPosition tab_pos);
- LLMultiFloater(const std::string& name);
- LLMultiFloater(const std::string& name, const LLRect& rect, LLTabContainer::TabPosition tab_pos = LLTabContainer::TOP, BOOL auto_resize = TRUE);
- LLMultiFloater(const std::string& name, const std::string& rect_control, LLTabContainer::TabPosition tab_pos = LLTabContainer::TOP, BOOL auto_resize = TRUE);
- virtual ~LLMultiFloater() {};
-
- virtual BOOL postBuild();
- /*virtual*/ void open(); /* Flawfinder: ignore */
- /*virtual*/ void onClose(bool app_quitting);
- /*virtual*/ void draw();
- /*virtual*/ void setVisible(BOOL visible);
- /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
-
- virtual void setCanResize(BOOL can_resize);
- virtual void growToFit(S32 content_width, S32 content_height);
- virtual void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END);
-
- virtual void showFloater(LLFloater* floaterp);
- virtual void removeFloater(LLFloater* floaterp);
-
- virtual void tabOpen(LLFloater* opened_floater, bool from_click);
- virtual void tabClose();
-
- virtual BOOL selectFloater(LLFloater* floaterp);
- virtual void selectNextFloater();
- virtual void selectPrevFloater();
-
- virtual LLFloater* getActiveFloater();
- virtual BOOL isFloaterFlashing(LLFloater* floaterp);
- virtual S32 getFloaterCount();
-
- virtual void setFloaterFlashing(LLFloater* floaterp, BOOL flashing);
- virtual BOOL closeAllFloaters(); //Returns FALSE if the floater could not be closed due to pending confirmation dialogs
- void setTabContainer(LLTabContainer* tab_container) { if (!mTabContainer) mTabContainer = tab_container; }
- static void onTabSelected(void* userdata, bool);
-
- virtual void updateResizeLimits();
-
-protected:
- struct LLFloaterData
- {
- S32 mWidth;
- S32 mHeight;
- BOOL mCanMinimize;
- BOOL mCanResize;
- };
-
- LLTabContainer* mTabContainer;
-
- typedef std::map<LLHandle<LLFloater>, LLFloaterData> floater_data_map_t;
- floater_data_map_t mFloaterDataMap;
-
- LLTabContainer::TabPosition mTabPos;
- BOOL mAutoResize;
- S32 mOrigMinWidth, mOrigMinHeight; // logically const but initialized late
-};
-
-// visibility policy specialized for floaters
-template<>
-class VisibilityPolicy<LLFloater>
-{
-public:
- // visibility methods
- static bool visible(LLFloater* instance, const LLSD& key)
- {
- if (instance)
- {
- return !instance->isMinimized() && instance->isInVisibleChain();
- }
- return FALSE;
- }
-
- static void show(LLFloater* instance, const LLSD& key)
- {
- if (instance)
- {
- instance->open();
- if (instance->getHost())
- {
- instance->getHost()->open();
- }
- }
- }
-
- static void hide(LLFloater* instance, const LLSD& key)
- {
- if (instance) instance->close();
- }
-};
-
-
-// singleton implementation for floaters (provides visibility policy)
-// https://wiki.lindenlab.com/mediawiki/index.php?title=LLFloaterSingleton&oldid=164990
-
-template <class T> class LLFloaterSingleton : public LLUISingleton<T, VisibilityPolicy<LLFloater> >
-{
-};
+//
+// Globals
+//
extern LLFloaterView* gFloaterView;
diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp
new file mode 100644
index 0000000000..eb67e3a561
--- /dev/null
+++ b/indra/llui/llfloaterreg.cpp
@@ -0,0 +1,461 @@
+/**
+ * @file llfloaterreg.cpp
+ * @brief LLFloaterReg Floater Registration Class
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llfloaterreg.h"
+
+#include "llfloater.h"
+#include "llmultifloater.h"
+#include "llfloaterreglistener.h"
+
+//*******************************************************
+
+//static
+LLFloaterReg::instance_list_t LLFloaterReg::sNullInstanceList;
+LLFloaterReg::instance_map_t LLFloaterReg::sInstanceMap;
+LLFloaterReg::build_map_t LLFloaterReg::sBuildMap;
+std::map<std::string,std::string> LLFloaterReg::sGroupMap;
+
+static LLFloaterRegListener sFloaterRegListener;
+
+//*******************************************************
+
+//static
+void LLFloaterReg::add(const std::string& name, const std::string& filename, const LLFloaterBuildFunc& func, const std::string& groupname)
+{
+ sBuildMap[name].mFunc = func;
+ sBuildMap[name].mFile = filename;
+ sGroupMap[name] = groupname.empty() ? name : groupname;
+ sGroupMap[groupname] = groupname; // for referencing directly by group name
+}
+
+//static
+LLRect LLFloaterReg::getFloaterRect(const std::string& name)
+{
+ LLRect rect;
+ const std::string& groupname = sGroupMap[name];
+ if (!groupname.empty())
+ {
+ instance_list_t& list = sInstanceMap[groupname];
+ if (!list.empty())
+ {
+ static LLUICachedControl<S32> floater_offset ("UIFloaterOffset", 16);
+ LLFloater* last_floater = list.back();
+ if (last_floater->getHost())
+ {
+ rect = last_floater->getHost()->getRect();
+ }
+ else
+ {
+ rect = last_floater->getRect();
+ }
+ rect.translate(floater_offset, -floater_offset);
+ }
+ }
+ return rect;
+}
+
+//static
+LLFloater* LLFloaterReg::findInstance(const std::string& name, const LLSD& key)
+{
+ LLFloater* res = NULL;
+ const std::string& groupname = sGroupMap[name];
+ if (!groupname.empty())
+ {
+ instance_list_t& list = sInstanceMap[groupname];
+ for (instance_list_t::iterator iter = list.begin(); iter != list.end(); ++iter)
+ {
+ LLFloater* inst = *iter;
+ if (inst->matchesKey(key))
+ {
+ res = inst;
+ break;
+ }
+ }
+ }
+ return res;
+}
+
+//static
+LLFloater* LLFloaterReg::getInstance(const std::string& name, const LLSD& key)
+{
+ LLFloater* res = findInstance(name, key);
+ if (!res)
+ {
+ const LLFloaterBuildFunc& build_func = sBuildMap[name].mFunc;
+ const std::string& xui_file = sBuildMap[name].mFile;
+ if (build_func)
+ {
+ const std::string& groupname = sGroupMap[name];
+ if (!groupname.empty())
+ {
+ instance_list_t& list = sInstanceMap[groupname];
+ int index = list.size();
+
+ res = build_func(key);
+
+ bool success = LLUICtrlFactory::getInstance()->buildFloater(res, xui_file, NULL);
+ if (!success)
+ {
+ llwarns << "Failed to build floater type: '" << name << "'." << llendl;
+ return NULL;
+ }
+
+ // Note: key should eventually be a non optional LLFloater arg; for now, set mKey to be safe
+ res->mKey = key;
+ res->setInstanceName(name);
+ res->applySavedVariables(); // Can't apply rect and dock state until setting instance name
+ if (res->mAutoTile && !res->getHost() && index > 0)
+ {
+ const LLRect& cur_rect = res->getRect();
+ LLRect next_rect = getFloaterRect(groupname);
+ next_rect.setLeftTopAndSize(next_rect.mLeft, next_rect.mTop, cur_rect.getWidth(), cur_rect.getHeight());
+ res->setRect(next_rect);
+ res->setRectControl(LLStringUtil::null); // don't save rect of tiled floaters
+ gFloaterView->adjustToFitScreen(res, true);
+ }
+ else
+ {
+ gFloaterView->adjustToFitScreen(res, false);
+ }
+ list.push_back(res);
+ }
+ }
+ if (!res)
+ {
+ llwarns << "Floater type: '" << name << "' not registered." << llendl;
+ }
+ }
+ return res;
+}
+
+//static
+LLFloater* LLFloaterReg::removeInstance(const std::string& name, const LLSD& key)
+{
+ LLFloater* res = NULL;
+ const std::string& groupname = sGroupMap[name];
+ if (!groupname.empty())
+ {
+ instance_list_t& list = sInstanceMap[groupname];
+ for (instance_list_t::iterator iter = list.begin(); iter != list.end(); ++iter)
+ {
+ LLFloater* inst = *iter;
+ if (inst->matchesKey(key))
+ {
+ res = inst;
+ list.erase(iter);
+ break;
+ }
+ }
+ }
+ return res;
+}
+
+//static
+// returns true if the instance existed
+bool LLFloaterReg::destroyInstance(const std::string& name, const LLSD& key)
+{
+ LLFloater* inst = removeInstance(name, key);
+ if (inst)
+ {
+ delete inst;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Iterators
+//static
+LLFloaterReg::const_instance_list_t& LLFloaterReg::getFloaterList(const std::string& name)
+{
+ instance_map_t::iterator iter = sInstanceMap.find(name);
+ if (iter != sInstanceMap.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ return sNullInstanceList;
+ }
+}
+
+// Visibility Management
+
+//static
+LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key, BOOL focus)
+{
+ LLFloater* instance = getInstance(name, key);
+ if (instance)
+ {
+ instance->openFloater(key);
+ if (focus)
+ instance->setFocus(TRUE);
+ }
+ return instance;
+}
+
+//static
+// returns true if the instance exists
+bool LLFloaterReg::hideInstance(const std::string& name, const LLSD& key)
+{
+ LLFloater* instance = findInstance(name, key);
+ if (instance)
+ {
+ // When toggling *visibility*, close the host instead of the floater when hosted
+ if (instance->getHost())
+ instance->getHost()->closeFloater();
+ else
+ instance->closeFloater();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+//static
+// returns true if the instance is visible when completed
+bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key)
+{
+ LLFloater* instance = findInstance(name, key);
+ if (LLFloater::isShown(instance))
+ {
+ // When toggling *visibility*, close the host instead of the floater when hosted
+ if (instance->getHost())
+ instance->getHost()->closeFloater();
+ else
+ instance->closeFloater();
+ return false;
+ }
+ else
+ {
+ return showInstance(name, key, TRUE) ? true : false;
+ }
+}
+
+//static
+// returns true if the instance exists and is visible
+bool LLFloaterReg::instanceVisible(const std::string& name, const LLSD& key)
+{
+ LLFloater* instance = findInstance(name, key);
+ return LLFloater::isShown(instance);
+}
+
+//static
+void LLFloaterReg::showInitialVisibleInstances()
+{
+ // Iterate through alll registered instance names and show any with a save visible state
+ for (build_map_t::iterator iter = sBuildMap.begin(); iter != sBuildMap.end(); ++iter)
+ {
+ const std::string& name = iter->first;
+ std::string controlname = getVisibilityControlName(name);
+ if (LLUI::sSettingGroups["floater"]->controlExists(controlname))
+ {
+ BOOL isvis = LLUI::sSettingGroups["floater"]->getBOOL(controlname);
+ if (isvis)
+ {
+ showInstance(name, LLSD()); // keyed floaters shouldn't set save_vis to true
+ }
+ }
+ }
+}
+
+//static
+void LLFloaterReg::hideVisibleInstances(const std::set<std::string>& exceptions)
+{
+ // Iterate through alll active instances and hide them
+ for (instance_map_t::iterator iter = sInstanceMap.begin(); iter != sInstanceMap.end(); ++iter)
+ {
+ const std::string& name = iter->first;
+ if (exceptions.find(name) != exceptions.end())
+ continue;
+ instance_list_t& list = iter->second;
+ for (instance_list_t::iterator iter = list.begin(); iter != list.end(); ++iter)
+ {
+ LLFloater* floater = *iter;
+ floater->pushVisible(FALSE);
+ }
+ }
+}
+
+//static
+void LLFloaterReg::restoreVisibleInstances()
+{
+ // Iterate through all active instances and restore visibility
+ for (instance_map_t::iterator iter = sInstanceMap.begin(); iter != sInstanceMap.end(); ++iter)
+ {
+ instance_list_t& list = iter->second;
+ for (instance_list_t::iterator iter = list.begin(); iter != list.end(); ++iter)
+ {
+ LLFloater* floater = *iter;
+ floater->popVisible();
+ }
+ }
+}
+
+//static
+std::string LLFloaterReg::getRectControlName(const std::string& name)
+{
+ std::string res = std::string("floater_rect_") + name;
+ LLStringUtil::replaceChar( res, ' ', '_' );
+ return res;
+}
+
+//static
+std::string LLFloaterReg::declareRectControl(const std::string& name)
+{
+ std::string controlname = getRectControlName(name);
+ LLUI::sSettingGroups["floater"]->declareRect(controlname, LLRect(),
+ llformat("Window Position and Size for %s", name.c_str()),
+ TRUE);
+ return controlname;
+}
+
+//static
+std::string LLFloaterReg::getVisibilityControlName(const std::string& name)
+{
+ std::string res = std::string("floater_vis_") + name;
+ LLStringUtil::replaceChar( res, ' ', '_' );
+ return res;
+}
+
+//static
+std::string LLFloaterReg::declareVisibilityControl(const std::string& name)
+{
+ std::string controlname = getVisibilityControlName(name);
+ LLUI::sSettingGroups["floater"]->declareBOOL(controlname, FALSE,
+ llformat("Window Visibility for %s", name.c_str()),
+ TRUE);
+ return controlname;
+}
+
+//static
+std::string LLFloaterReg::declareDockStateControl(const std::string& name)
+{
+ std::string controlname = getDockStateControlName(name);
+ LLUI::sSettingGroups["floater"]->declareBOOL(controlname, TRUE,
+ llformat("Window Docking state for %s", name.c_str()),
+ TRUE);
+ return controlname;
+
+}
+
+//static
+std::string LLFloaterReg::getDockStateControlName(const std::string& name)
+{
+ std::string res = std::string("floater_dock_") + name;
+ LLStringUtil::replaceChar( res, ' ', '_' );
+ return res;
+}
+
+
+//static
+void LLFloaterReg::registerControlVariables()
+{
+ // Iterate through alll registered instance names and register rect and visibility control variables
+ for (build_map_t::iterator iter = sBuildMap.begin(); iter != sBuildMap.end(); ++iter)
+ {
+ const std::string& name = iter->first;
+ if (LLUI::sSettingGroups["floater"]->controlExists(getRectControlName(name)))
+ {
+ declareRectControl(name);
+ }
+ if (LLUI::sSettingGroups["floater"]->controlExists(getVisibilityControlName(name)))
+ {
+ declareVisibilityControl(name);
+ }
+ }
+}
+
+// Callbacks
+
+// static
+// Call once (i.e use for init callbacks)
+void LLFloaterReg::initUICtrlToFloaterVisibilityControl(LLUICtrl* ctrl, const LLSD& sdname)
+{
+ // Get the visibility control name for the floater
+ std::string vis_control_name = LLFloaterReg::declareVisibilityControl(sdname.asString());
+ // Set the control value to the floater visibility control (Sets the value as well)
+ ctrl->setControlVariable(LLUI::sSettingGroups["floater"]->getControl(vis_control_name));
+}
+
+// callback args may use "floatername.key" format
+static void parse_name_key(std::string& name, LLSD& key)
+{
+ std::string instname = name;
+ std::size_t dotpos = instname.find(".");
+ if (dotpos != std::string::npos)
+ {
+ name = instname.substr(0, dotpos);
+ key = LLSD(instname.substr(dotpos+1, std::string::npos));
+ }
+}
+
+//static
+void LLFloaterReg::showFloaterInstance(const LLSD& sdname)
+{
+ LLSD key;
+ std::string name = sdname.asString();
+ parse_name_key(name, key);
+ showInstance(name, key, TRUE);
+}
+//static
+void LLFloaterReg::hideFloaterInstance(const LLSD& sdname)
+{
+ LLSD key;
+ std::string name = sdname.asString();
+ parse_name_key(name, key);
+ hideInstance(name, key);
+}
+//static
+void LLFloaterReg::toggleFloaterInstance(const LLSD& sdname)
+{
+ LLSD key;
+ std::string name = sdname.asString();
+ parse_name_key(name, key);
+ toggleInstance(name, key);
+}
+
+//static
+bool LLFloaterReg::floaterInstanceVisible(const LLSD& sdname)
+{
+ LLSD key;
+ std::string name = sdname.asString();
+ parse_name_key(name, key);
+ return instanceVisible(name, key);
+}
+
diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h
new file mode 100644
index 0000000000..634a235926
--- /dev/null
+++ b/indra/llui/llfloaterreg.h
@@ -0,0 +1,158 @@
+/**
+ * @file llfloaterreg.h
+ * @brief LLFloaterReg Floater Registration Class
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef LLFLOATERREG_H
+#define LLFLOATERREG_H
+
+/// llcommon
+#include "llboost.h"
+#include "llrect.h"
+#include "llstl.h"
+#include "llsd.h"
+
+/// llui
+#include "lluictrl.h"
+
+#include <boost/function.hpp>
+
+//*******************************************************
+//
+// Floater Class Registry
+//
+
+class LLFloater;
+
+typedef boost::function<LLFloater* (const LLSD& key)> LLFloaterBuildFunc;
+
+class LLFloaterReg
+{
+public:
+ // We use a list of LLFloater's instead of a set for two reasons:
+ // 1) With a list we have a predictable ordering, useful for finding the last opened floater of a given type.
+ // 2) We can change the key of a floater without altering the list.
+ typedef std::list<LLFloater*> instance_list_t;
+ typedef const instance_list_t const_instance_list_t;
+ typedef std::map<std::string, instance_list_t> instance_map_t;
+
+ struct BuildData
+ {
+ LLFloaterBuildFunc mFunc;
+ std::string mFile;
+ };
+ typedef std::map<std::string, BuildData> build_map_t;
+
+private:
+ friend class LLFloaterRegListener;
+ static instance_list_t sNullInstanceList;
+ static instance_map_t sInstanceMap;
+ static build_map_t sBuildMap;
+ static std::map<std::string,std::string> sGroupMap;
+
+public:
+ // Registration
+
+ // usage: LLFloaterClassRegistry::add("foo", (LLFloaterBuildFunc)&LLFloaterClassRegistry::build<LLFloaterFoo>);
+ template <class T>
+ static LLFloater* build(const LLSD& key)
+ {
+ T* floater = new T(key);
+ return floater;
+ }
+
+ static void add(const std::string& name, const std::string& file, const LLFloaterBuildFunc& func,
+ const std::string& groupname = LLStringUtil::null);
+
+ // Helpers
+ static LLRect getFloaterRect(const std::string& name);
+
+ // Find / get (create) / remove / destroy
+ static LLFloater* findInstance(const std::string& name, const LLSD& key = LLSD());
+ static LLFloater* getInstance(const std::string& name, const LLSD& key = LLSD());
+ static LLFloater* removeInstance(const std::string& name, const LLSD& key = LLSD());
+ static bool destroyInstance(const std::string& name, const LLSD& key = LLSD());
+
+ // Iterators
+ static const_instance_list_t& getFloaterList(const std::string& name);
+
+ // Visibility Management
+ // return NULL if instance not found or can't create instance (no builder)
+ static LLFloater* showInstance(const std::string& name, const LLSD& key = LLSD(), BOOL focus = FALSE);
+ // Close a floater (may destroy or set invisible)
+ // return false if can't find instance
+ static bool hideInstance(const std::string& name, const LLSD& key = LLSD());
+ // return true if instance is visible:
+ static bool toggleInstance(const std::string& name, const LLSD& key = LLSD());
+ static bool instanceVisible(const std::string& name, const LLSD& key = LLSD());
+
+ static void showInitialVisibleInstances();
+ static void hideVisibleInstances(const std::set<std::string>& exceptions = std::set<std::string>());
+ static void restoreVisibleInstances();
+
+ // Control Variables
+ static std::string getRectControlName(const std::string& name);
+ static std::string declareRectControl(const std::string& name);
+ static std::string getVisibilityControlName(const std::string& name);
+ static std::string declareVisibilityControl(const std::string& name);
+
+ static std::string declareDockStateControl(const std::string& name);
+ static std::string getDockStateControlName(const std::string& name);
+
+ static void registerControlVariables();
+
+ // Callback wrappers
+ static void initUICtrlToFloaterVisibilityControl(LLUICtrl* ctrl, const LLSD& sdname);
+ static void showFloaterInstance(const LLSD& sdname);
+ static void hideFloaterInstance(const LLSD& sdname);
+ static void toggleFloaterInstance(const LLSD& sdname);
+ static bool floaterInstanceVisible(const LLSD& sdname);
+
+ // Typed find / get / show
+ template <class T>
+ static T* findTypedInstance(const std::string& name, const LLSD& key = LLSD())
+ {
+ return dynamic_cast<T*>(findInstance(name, key));
+ }
+
+ template <class T>
+ static T* getTypedInstance(const std::string& name, const LLSD& key = LLSD())
+ {
+ return dynamic_cast<T*>(getInstance(name, key));
+ }
+
+ template <class T>
+ static T* showTypedInstance(const std::string& name, const LLSD& key = LLSD(), BOOL focus = FALSE)
+ {
+ return dynamic_cast<T*>(showInstance(name, key, focus));
+ }
+
+};
+
+#endif
diff --git a/indra/llui/llfloaterreglistener.cpp b/indra/llui/llfloaterreglistener.cpp
new file mode 100644
index 0000000000..082d7c1573
--- /dev/null
+++ b/indra/llui/llfloaterreglistener.cpp
@@ -0,0 +1,130 @@
+/**
+ * @file llfloaterreglistener.cpp
+ * @author Nat Goodspeed
+ * @date 2009-08-12
+ * @brief Implementation for llfloaterreglistener.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llfloaterreglistener.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llfloaterreg.h"
+#include "llfloater.h"
+#include "llbutton.h"
+
+LLFloaterRegListener::LLFloaterRegListener():
+ LLEventAPI("LLFloaterReg",
+ "LLFloaterReg listener to (e.g.) show/hide LLFloater instances")
+{
+ add("getBuildMap",
+ "Return on [\"reply\"] data about all registered LLFloaterReg floater names",
+ &LLFloaterRegListener::getBuildMap,
+ LLSD().with("reply", LLSD()));
+ LLSD requiredName;
+ requiredName["name"] = LLSD();
+ add("showInstance",
+ "Ask to display the floater specified in [\"name\"]",
+ &LLFloaterRegListener::showInstance,
+ requiredName);
+ add("hideInstance",
+ "Ask to hide the floater specified in [\"name\"]",
+ &LLFloaterRegListener::hideInstance,
+ requiredName);
+ add("toggleInstance",
+ "Ask to toggle the state of the floater specified in [\"name\"]",
+ &LLFloaterRegListener::toggleInstance,
+ requiredName);
+ LLSD requiredNameButton;
+ requiredNameButton["name"] = LLSD();
+ requiredNameButton["button"] = LLSD();
+ add("clickButton",
+ "Simulate clicking the named [\"button\"] in the visible floater named in [\"name\"]",
+ &LLFloaterRegListener::clickButton,
+ requiredNameButton);
+}
+
+void LLFloaterRegListener::getBuildMap(const LLSD& event) const
+{
+ // Honor the "reqid" convention by echoing event["reqid"] in our reply packet.
+ LLReqID reqID(event);
+ LLSD reply(reqID.makeResponse());
+ // Build an LLSD map that mirrors sBuildMap. Since we have no good way to
+ // represent a C++ callable in LLSD, the only part of BuildData we can
+ // store is the filename. For each LLSD map entry, it would be more
+ // extensible to store a nested LLSD map containing a single key "file" --
+ // but we don't bother, simply storing the string filename instead.
+ for (LLFloaterReg::build_map_t::const_iterator mi(LLFloaterReg::sBuildMap.begin()),
+ mend(LLFloaterReg::sBuildMap.end());
+ mi != mend; ++mi)
+ {
+ reply[mi->first] = mi->second.mFile;
+ }
+ // Send the reply to the LLEventPump named in event["reply"].
+ LLEventPumps::instance().obtain(event["reply"]).post(reply);
+}
+
+void LLFloaterRegListener::showInstance(const LLSD& event) const
+{
+ LLFloaterReg::showInstance(event["name"], event["key"], event["focus"]);
+}
+
+void LLFloaterRegListener::hideInstance(const LLSD& event) const
+{
+ LLFloaterReg::hideInstance(event["name"], event["key"]);
+}
+
+void LLFloaterRegListener::toggleInstance(const LLSD& event) const
+{
+ LLFloaterReg::toggleInstance(event["name"], event["key"]);
+}
+
+void LLFloaterRegListener::clickButton(const LLSD& event) const
+{
+ // If the caller requests a reply, build the reply.
+ LLReqID reqID(event);
+ LLSD reply(reqID.makeResponse());
+
+ LLFloater* floater = LLFloaterReg::findInstance(event["name"], event["key"]);
+ if (! LLFloater::isShown(floater))
+ {
+ reply["type"] = "LLFloater";
+ reply["name"] = event["name"];
+ reply["key"] = event["key"];
+ reply["error"] = floater? "!isShown()" : "NULL";
+ }
+ else
+ {
+ // Here 'floater' points to an LLFloater instance with the specified
+ // name and key which isShown().
+ LLButton* button = floater->findChild<LLButton>(event["button"]);
+ if (! LLButton::isAvailable(button))
+ {
+ reply["type"] = "LLButton";
+ reply["name"] = event["button"];
+ reply["error"] = button? "!isAvailable()" : "NULL";
+ }
+ else
+ {
+ // Here 'button' points to an isAvailable() LLButton child of
+ // 'floater' with the specified button name. Pretend to click it.
+ button->onCommit();
+ // Leave reply["error"] isUndefined(): no error, i.e. success.
+ }
+ }
+
+ // Send a reply only if caller asked for a reply.
+ LLSD replyPump(event["reply"]);
+ if (replyPump.isString()) // isUndefined() if absent
+ {
+ LLEventPumps::instance().obtain(replyPump).post(reply);
+ }
+}
diff --git a/indra/llui/llfloaterreglistener.h b/indra/llui/llfloaterreglistener.h
new file mode 100644
index 0000000000..a38117f6b0
--- /dev/null
+++ b/indra/llui/llfloaterreglistener.h
@@ -0,0 +1,36 @@
+/**
+ * @file llfloaterreglistener.h
+ * @author Nat Goodspeed
+ * @date 2009-08-12
+ * @brief Wrap (subset of) LLFloaterReg API with an event API
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLFLOATERREGLISTENER_H)
+#define LL_LLFLOATERREGLISTENER_H
+
+#include "lleventapi.h"
+#include <string>
+
+class LLSD;
+
+/// Event API wrapper for LLFloaterReg
+class LLFloaterRegListener: public LLEventAPI
+{
+public:
+ /// As all public LLFloaterReg methods are static, there's no point in
+ /// binding an LLFloaterReg instance.
+ LLFloaterRegListener();
+
+private:
+ void getBuildMap(const LLSD& event) const;
+ void showInstance(const LLSD& event) const;
+ void hideInstance(const LLSD& event) const;
+ void toggleInstance(const LLSD& event) const;
+ void clickButton(const LLSD& event) const;
+};
+
+#endif /* ! defined(LL_LLFLOATERREGLISTENER_H) */
diff --git a/indra/llui/llflyoutbutton.cpp b/indra/llui/llflyoutbutton.cpp
new file mode 100644
index 0000000000..abb0b869eb
--- /dev/null
+++ b/indra/llui/llflyoutbutton.cpp
@@ -0,0 +1,83 @@
+/**
+ * @file llflyoutbutton.cpp
+ * @brief LLFlyoutButton base class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+// file includes
+#include "llflyoutbutton.h"
+
+//static LLDefaultChildRegistry::Register<LLFlyoutButton> r2("flyout_button");
+
+const S32 FLYOUT_BUTTON_ARROW_WIDTH = 24;
+
+LLFlyoutButton::LLFlyoutButton(const Params& p)
+: LLComboBox(p),
+ mToggleState(FALSE),
+ mActionButton(NULL)
+{
+ // Always use text box
+ // Text label button
+ LLButton::Params bp(p.action_button);
+ bp.name(p.label);
+ bp.label(p.label);
+ bp.rect.left(0).bottom(0).width(getRect().getWidth() - FLYOUT_BUTTON_ARROW_WIDTH).height(getRect().getHeight());
+ bp.click_callback.function(boost::bind(&LLFlyoutButton::onActionButtonClick, this, _2));
+ bp.follows.flags(FOLLOWS_ALL);
+
+ mActionButton = LLUICtrlFactory::create<LLButton>(bp);
+ addChild(mActionButton);
+}
+
+void LLFlyoutButton::onActionButtonClick(const LLSD& data)
+{
+ // remember last list selection?
+ mList->deselect();
+ onCommit();
+}
+
+void LLFlyoutButton::draw()
+{
+ mActionButton->setToggleState(mToggleState);
+ mButton->setToggleState(mToggleState);
+
+ //FIXME: this should be an attribute of comboboxes, whether they have a distinct label or
+ // the label reflects the last selected item, for now we have to manually remove the label
+ setLabel(LLStringUtil::null);
+ LLComboBox::draw();
+}
+
+void LLFlyoutButton::setToggleState(BOOL state)
+{
+ mToggleState = state;
+}
+
+
diff --git a/indra/llui/llflyoutbutton.h b/indra/llui/llflyoutbutton.h
new file mode 100644
index 0000000000..d8c0f1a50d
--- /dev/null
+++ b/indra/llui/llflyoutbutton.h
@@ -0,0 +1,74 @@
+/**
+ * @file llflyoutbutton.h
+ * @brief LLFlyoutButton base class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// A control that displays the name of the chosen item, which when clicked
+// shows a scrolling box of choices.
+
+#ifndef LL_LLFLYOUTBUTTON_H
+#define LL_LLFLYOUTBUTTON_H
+
+#include "llcombobox.h"
+
+// Classes
+
+class LLFlyoutButton : public LLComboBox
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLComboBox::Params>
+ {
+ Optional<LLButton::Params> action_button;
+ Deprecated allow_text_entry;
+
+ Params()
+ : action_button("action_button"),
+ allow_text_entry("allow_text_entry")
+ {
+ LLComboBox::Params::allow_text_entry = false;
+ }
+
+ };
+protected:
+ LLFlyoutButton(const Params&);
+ friend class LLUICtrlFactory;
+public:
+ virtual void draw();
+
+ void setToggleState(BOOL state);
+
+ void onActionButtonClick(const LLSD& data);
+
+protected:
+ LLButton* mActionButton;
+ BOOL mToggleState;
+};
+
+#endif // LL_LLFLYOUTBUTTON_H
diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp
index 661ffdd467..35fbc7b0a8 100644
--- a/indra/llui/llfocusmgr.cpp
+++ b/indra/llui/llfocusmgr.cpp
@@ -38,6 +38,89 @@
const F32 FOCUS_FADE_TIME = 0.3f;
+// NOTE: the LLFocusableElement implementation has been moved here from lluictrl.cpp.
+
+LLFocusableElement::LLFocusableElement()
+: mFocusLostCallback(NULL),
+ mFocusReceivedCallback(NULL),
+ mFocusChangedCallback(NULL),
+ mTopLostCallback(NULL)
+{
+}
+
+// virtual
+BOOL LLFocusableElement::handleKey(KEY key, MASK mask, BOOL called_from_parent)
+{
+ return FALSE;
+}
+
+// virtual
+BOOL LLFocusableElement::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
+{
+ return FALSE;
+}
+
+// virtual
+LLFocusableElement::~LLFocusableElement()
+{
+ delete mFocusLostCallback;
+ delete mFocusReceivedCallback;
+ delete mFocusChangedCallback;
+ delete mTopLostCallback;
+}
+
+void LLFocusableElement::onFocusReceived()
+{
+ if (mFocusReceivedCallback) (*mFocusReceivedCallback)(this);
+ if (mFocusChangedCallback) (*mFocusChangedCallback)(this);
+}
+
+void LLFocusableElement::onFocusLost()
+{
+ if (mFocusLostCallback) (*mFocusLostCallback)(this);
+ if (mFocusChangedCallback) (*mFocusChangedCallback)(this);
+}
+
+void LLFocusableElement::onTopLost()
+{
+ if (mTopLostCallback) (*mTopLostCallback)(this);
+}
+
+BOOL LLFocusableElement::hasFocus() const
+{
+ return gFocusMgr.getKeyboardFocus() == this;
+}
+
+void LLFocusableElement::setFocus(BOOL b)
+{
+}
+
+boost::signals2::connection LLFocusableElement::setFocusLostCallback( const focus_signal_t::slot_type& cb)
+{
+ if (!mFocusLostCallback) mFocusLostCallback = new focus_signal_t();
+ return mFocusLostCallback->connect(cb);
+}
+
+boost::signals2::connection LLFocusableElement::setFocusReceivedCallback(const focus_signal_t::slot_type& cb)
+{
+ if (!mFocusReceivedCallback) mFocusReceivedCallback = new focus_signal_t();
+ return mFocusReceivedCallback->connect(cb);
+}
+
+boost::signals2::connection LLFocusableElement::setFocusChangedCallback(const focus_signal_t::slot_type& cb)
+{
+ if (!mFocusChangedCallback) mFocusChangedCallback = new focus_signal_t();
+ return mFocusChangedCallback->connect(cb);
+}
+
+boost::signals2::connection LLFocusableElement::setTopLostCallback(const focus_signal_t::slot_type& cb)
+{
+ if (!mTopLostCallback) mTopLostCallback = new focus_signal_t();
+ return mTopLostCallback->connect(cb);
+}
+
+
+
LLFocusMgr gFocusMgr;
LLFocusMgr::LLFocusMgr()
@@ -49,7 +132,6 @@ LLFocusMgr::LLFocusMgr()
mDefaultKeyboardFocus( NULL ),
mKeystrokesOnly(FALSE),
mTopCtrl( NULL ),
- mFocusWeight(0.f),
mAppHasFocus(TRUE) // Macs don't seem to notify us that we've gotten focus, so default to true
#ifdef _DEBUG
, mMouseCaptorName("none")
@@ -87,19 +169,25 @@ void LLFocusMgr::releaseFocusIfNeeded( const LLView* view )
}
-void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, BOOL lock, BOOL keystrokes_only)
+void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL keystrokes_only)
{
+ // notes if keyboard focus is changed again (by onFocusLost/onFocusReceived)
+ // making the rest of our processing unnecessary since it will already be
+ // handled by the recursive call
+ static bool focus_dirty;
+ focus_dirty = false;
+
if (mLockedView &&
(new_focus == NULL ||
- (new_focus != mLockedView && !new_focus->hasAncestor(mLockedView))))
+ (new_focus != mLockedView
+ && dynamic_cast<LLView*>(new_focus)
+ && !dynamic_cast<LLView*>(new_focus)->hasAncestor(mLockedView))))
{
// don't allow focus to go to anything that is not the locked focus
// or one of its descendants
return;
}
- //llinfos << "Keyboard focus handled by " << (new_focus ? new_focus->getName() : "nothing") << llendl;
-
mKeystrokesOnly = keystrokes_only;
if( new_focus != mKeyboardFocus )
@@ -107,21 +195,62 @@ void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, BOOL lock, BOOL keystroke
mLastKeyboardFocus = mKeyboardFocus;
mKeyboardFocus = new_focus;
- if( mLastKeyboardFocus )
+ // list of the focus and it's ancestors
+ view_handle_list_t old_focus_list = mCachedKeyboardFocusList;
+ view_handle_list_t new_focus_list;
+
+ // walk up the tree to root and add all views to the new_focus_list
+ for (LLView* ctrl = dynamic_cast<LLView*>(mKeyboardFocus); ctrl; ctrl = ctrl->getParent())
+ {
+ new_focus_list.push_back(ctrl->getHandle());
+ }
+
+ // remove all common ancestors since their focus is unchanged
+ while (!new_focus_list.empty() &&
+ !old_focus_list.empty() &&
+ new_focus_list.back() == old_focus_list.back())
{
- mLastKeyboardFocus->onFocusLost();
+ new_focus_list.pop_back();
+ old_focus_list.pop_back();
+ }
+
+ // walk up the old focus branch calling onFocusLost
+ // we bubble up the tree to release focus, and back down to add
+ for (view_handle_list_t::iterator old_focus_iter = old_focus_list.begin();
+ old_focus_iter != old_focus_list.end() && !focus_dirty;
+ old_focus_iter++)
+ {
+ LLView* old_focus_view = old_focus_iter->get();
+ if (old_focus_view)
+ {
+ mCachedKeyboardFocusList.pop_front();
+ old_focus_view->onFocusLost();
+ }
}
- // clear out any existing flash
- if (new_focus)
+ // walk down the new focus branch calling onFocusReceived
+ for (view_handle_list_t::reverse_iterator new_focus_riter = new_focus_list.rbegin();
+ new_focus_riter != new_focus_list.rend() && !focus_dirty;
+ new_focus_riter++)
+ {
+ LLView* new_focus_view = new_focus_riter->get();
+ if (new_focus_view)
+ {
+ mCachedKeyboardFocusList.push_front(new_focus_view->getHandle());
+ new_focus_view->onFocusReceived();
+ }
+ }
+
+ // if focus was changed as part of an onFocusLost or onFocusReceived call
+ // stop iterating on current list since it is now invalid
+ if (focus_dirty)
{
- mFocusWeight = 0.f;
- new_focus->onFocusReceived();
+ return;
}
- mFocusTimer.reset();
#ifdef _DEBUG
- mKeyboardFocusName = new_focus ? new_focus->getName() : std::string("none");
+ LLUICtrl* focus_ctrl = dynamic_cast<LLUICtrl*>(new_focus);
+ mKeyboardFocusName = focus_ctrl ? focus_ctrl->getName() : std::string("none");
#endif
// If we've got a default keyboard focus, and the caller is
@@ -131,8 +260,8 @@ void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, BOOL lock, BOOL keystroke
mDefaultKeyboardFocus->setFocus(TRUE);
}
- LLView* focus_subtree = mKeyboardFocus;
- LLView* viewp = mKeyboardFocus;
+ LLView* focus_subtree = dynamic_cast<LLView*>(mKeyboardFocus);
+ LLView* viewp = dynamic_cast<LLView*>(mKeyboardFocus);
// find root-most focus root
while(viewp)
{
@@ -146,7 +275,8 @@ void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, BOOL lock, BOOL keystroke
if (focus_subtree)
{
- mFocusHistory[focus_subtree->getHandle()] = mKeyboardFocus ? mKeyboardFocus->getHandle() : LLHandle<LLView>();
+ LLView* focused_view = dynamic_cast<LLView*>(mKeyboardFocus);
+ mFocusHistory[focus_subtree->getHandle()] = focused_view ? focused_view->getHandle() : LLHandle<LLView>();
}
}
@@ -154,13 +284,15 @@ void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, BOOL lock, BOOL keystroke
{
lockFocus();
}
+
+ focus_dirty = true;
}
// Returns TRUE is parent or any descedent of parent has keyboard focus.
BOOL LLFocusMgr::childHasKeyboardFocus(const LLView* parent ) const
{
- LLView* focus_view = mKeyboardFocus;
+ LLView* focus_view = dynamic_cast<LLView*>(mKeyboardFocus);
while( focus_view )
{
if( focus_view == parent )
@@ -175,7 +307,7 @@ BOOL LLFocusMgr::childHasKeyboardFocus(const LLView* parent ) const
// Returns TRUE is parent or any descedent of parent is the mouse captor.
BOOL LLFocusMgr::childHasMouseCapture( const LLView* parent ) const
{
- if( mMouseCaptor && mMouseCaptor->isView() )
+ if( mMouseCaptor && dynamic_cast<LLView*>(mMouseCaptor) != NULL )
{
LLView* captor_view = (LLView*)mMouseCaptor;
while( captor_view )
@@ -190,7 +322,7 @@ BOOL LLFocusMgr::childHasMouseCapture( const LLView* parent ) const
return FALSE;
}
-void LLFocusMgr::removeKeyboardFocusWithoutCallback( const LLView* focus )
+void LLFocusMgr::removeKeyboardFocusWithoutCallback( const LLFocusableElement* focus )
{
// should be ok to unlock here, as you have to know the locked view
// in order to unlock it
@@ -220,24 +352,19 @@ void LLFocusMgr::setMouseCapture( LLMouseHandler* new_captor )
{
LLMouseHandler* old_captor = mMouseCaptor;
mMouseCaptor = new_captor;
- /*
- if (new_captor)
+
+ if (LLView::sDebugMouseHandling)
{
- if ( new_captor->getName() == "Stickto")
+ if (new_captor)
{
llinfos << "New mouse captor: " << new_captor->getName() << llendl;
}
else
{
- llinfos << "New mouse captor: " << new_captor->getName() << llendl;
+ llinfos << "New mouse captor: NULL" << llendl;
}
}
- else
- {
- llinfos << "New mouse captor: NULL" << llendl;
- }
- */
-
+
if( old_captor )
{
old_captor->onMouseCaptureLost();
@@ -295,7 +422,7 @@ void LLFocusMgr::setTopCtrl( LLUICtrl* new_top )
if (old_top)
{
- old_top->onLostTop();
+ old_top->onTopLost();
}
}
}
@@ -313,7 +440,7 @@ void LLFocusMgr::removeTopCtrlWithoutCallback( const LLUICtrl* top_view )
void LLFocusMgr::lockFocus()
{
- mLockedView = mKeyboardFocus;
+ mLockedView = dynamic_cast<LLUICtrl*>(mKeyboardFocus);
}
void LLFocusMgr::unlockFocus()
@@ -323,12 +450,13 @@ void LLFocusMgr::unlockFocus()
F32 LLFocusMgr::getFocusFlashAmt() const
{
- return clamp_rescale(getFocusTime(), 0.f, FOCUS_FADE_TIME, mFocusWeight, 0.f);
+ return clamp_rescale(mFocusFlashTimer.getElapsedTimeF32(), 0.f, FOCUS_FADE_TIME, 1.f, 0.f);
}
LLColor4 LLFocusMgr::getFocusColor() const
{
- LLColor4 focus_color = lerp(LLUI::sColorsGroup->getColor( "FocusColor" ), LLColor4::white, getFocusFlashAmt());
+ static LLUIColor focus_color_cached = LLUIColorTable::instance().getColor("FocusColor");
+ LLColor4 focus_color = lerp(focus_color_cached, LLColor4::white, getFocusFlashAmt());
// de-emphasize keyboard focus when app has lost focus (to avoid typing into wrong window problem)
if (!mAppHasFocus)
{
@@ -339,8 +467,7 @@ LLColor4 LLFocusMgr::getFocusColor() const
void LLFocusMgr::triggerFocusFlash()
{
- mFocusTimer.reset();
- mFocusWeight = 1.f;
+ mFocusFlashTimer.reset();
}
void LLFocusMgr::setAppHasFocus(BOOL focus)
diff --git a/indra/llui/llfocusmgr.h b/indra/llui/llfocusmgr.h
index aaeb25a870..83ecd1d301 100644
--- a/indra/llui/llfocusmgr.h
+++ b/indra/llui/llfocusmgr.h
@@ -37,10 +37,44 @@
#include "llstring.h"
#include "llframetimer.h"
-#include "llview.h"
+#include "llui.h"
class LLUICtrl;
class LLMouseHandler;
+class LLView;
+
+// NOTE: the LLFocusableElement class declaration has been moved here from lluictrl.h.
+class LLFocusableElement
+{
+ friend class LLFocusMgr; // allow access to focus change handlers
+public:
+ LLFocusableElement();
+ virtual ~LLFocusableElement();
+
+ virtual void setFocus( BOOL b );
+ virtual BOOL hasFocus() const;
+
+ typedef boost::signals2::signal<void(LLFocusableElement*)> focus_signal_t;
+
+ boost::signals2::connection setFocusLostCallback( const focus_signal_t::slot_type& cb);
+ boost::signals2::connection setFocusReceivedCallback(const focus_signal_t::slot_type& cb);
+ boost::signals2::connection setFocusChangedCallback(const focus_signal_t::slot_type& cb);
+ boost::signals2::connection setTopLostCallback(const focus_signal_t::slot_type& cb);
+
+ // These were brought up the hierarchy from LLView so that we don't have to use dynamic_cast when dealing with keyboard focus.
+ virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
+ virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
+
+protected:
+ virtual void onFocusReceived();
+ virtual void onFocusLost();
+ virtual void onTopLost(); // called when registered as top ctrl and user clicks elsewhere
+ focus_signal_t* mFocusLostCallback;
+ focus_signal_t* mFocusReceivedCallback;
+ focus_signal_t* mFocusChangedCallback;
+ focus_signal_t* mTopLostCallback;
+};
+
class LLFocusMgr
{
@@ -55,15 +89,14 @@ public:
BOOL childHasMouseCapture( const LLView* parent ) const;
// Keyboard Focus
- void setKeyboardFocus(LLUICtrl* new_focus, BOOL lock = FALSE, BOOL keystrokes_only = FALSE); // new_focus = NULL to release the focus.
- LLUICtrl* getKeyboardFocus() const { return mKeyboardFocus; }
- LLUICtrl* getLastKeyboardFocus() const { return mLastKeyboardFocus; }
+ void setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock = FALSE, BOOL keystrokes_only = FALSE); // new_focus = NULL to release the focus.
+ LLFocusableElement* getKeyboardFocus() const { return mKeyboardFocus; }
+ LLFocusableElement* getLastKeyboardFocus() const { return mLastKeyboardFocus; }
BOOL childHasKeyboardFocus( const LLView* parent ) const;
- void removeKeyboardFocusWithoutCallback( const LLView* focus );
+ void removeKeyboardFocusWithoutCallback( const LLFocusableElement* focus );
BOOL getKeystrokesOnly() { return mKeystrokesOnly; }
void setKeystrokesOnly(BOOL keystrokes_only) { mKeystrokesOnly = keystrokes_only; }
- F32 getFocusTime() const { return mFocusTimer.getElapsedTimeF32(); }
F32 getFocusFlashAmt() const;
S32 getFocusFlashWidth() const { return llround(lerp(1.f, 3.f, getFocusFlashAmt())); }
LLColor4 getFocusColor() const;
@@ -75,8 +108,8 @@ public:
// If setKeyboardFocus(NULL) is called, and there is a non-NULL default
// keyboard focus view, focus goes there. JC
- void setDefaultKeyboardFocus(LLUICtrl* default_focus) { mDefaultKeyboardFocus = default_focus; }
- LLUICtrl* getDefaultKeyboardFocus() const { return mDefaultKeyboardFocus; }
+ void setDefaultKeyboardFocus(LLFocusableElement* default_focus) { mDefaultKeyboardFocus = default_focus; }
+ LLFocusableElement* getDefaultKeyboardFocus() const { return mDefaultKeyboardFocus; }
// Top View
@@ -98,16 +131,19 @@ private:
LLMouseHandler* mMouseCaptor; // Mouse events are premptively routed to this object
// Keyboard Focus
- LLUICtrl* mKeyboardFocus; // Keyboard events are preemptively routed to this object
- LLUICtrl* mLastKeyboardFocus; // who last had focus
- LLUICtrl* mDefaultKeyboardFocus;
+ LLFocusableElement* mKeyboardFocus; // Keyboard events are preemptively routed to this object
+ LLFocusableElement* mLastKeyboardFocus; // who last had focus
+ LLFocusableElement* mDefaultKeyboardFocus;
BOOL mKeystrokesOnly;
+
+ // caching list of keyboard focus ancestors for calling onFocusReceived and onFocusLost
+ typedef std::list<LLHandle<LLView> > view_handle_list_t;
+ view_handle_list_t mCachedKeyboardFocusList;
// Top View
LLUICtrl* mTopCtrl;
- LLFrameTimer mFocusTimer;
- F32 mFocusWeight;
+ LLFrameTimer mFocusFlashTimer;
BOOL mAppHasFocus;
diff --git a/indra/llui/llfunctorregistry.cpp b/indra/llui/llfunctorregistry.cpp
index 0c5b1655b1..5f9644f258 100644
--- a/indra/llui/llfunctorregistry.cpp
+++ b/indra/llui/llfunctorregistry.cpp
@@ -31,6 +31,7 @@
* $/LicenseInfo$
**/
+#include "linden_common.h"
#include "llfunctorregistry.h"
// This is a default functor always resident in the system.
diff --git a/indra/llui/llfunctorregistry.h b/indra/llui/llfunctorregistry.h
index 8864f7af15..2c0bcc6012 100644
--- a/indra/llui/llfunctorregistry.h
+++ b/indra/llui/llfunctorregistry.h
@@ -40,7 +40,7 @@
#include <boost/function.hpp>
#include "llsd.h"
-#include "llmemory.h"
+#include "llsingleton.h"
/**
* @class LLFunctorRegistry
diff --git a/indra/llui/llhandle.h b/indra/llui/llhandle.h
new file mode 100644
index 0000000000..899f6b9326
--- /dev/null
+++ b/indra/llui/llhandle.h
@@ -0,0 +1,171 @@
+/**
+* @file llhandle.h
+* @brief "Handle" to an object (usually a floater) whose lifetime you don't
+* control.
+*
+* $LicenseInfo:firstyear=2001&license=viewergpl$
+*
+* Copyright (c) 2001-2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+#ifndef LLHANDLE_H
+#define LLHANDLE_H
+
+#include "llpointer.h"
+
+template <typename T>
+class LLTombStone : public LLRefCount
+{
+public:
+ LLTombStone(T* target = NULL) : mTarget(target) {}
+
+ void setTarget(T* target) { mTarget = target; }
+ T* getTarget() const { return mTarget; }
+private:
+ T* mTarget;
+};
+
+// LLHandles are used to refer to objects whose lifetime you do not control or influence.
+// Calling get() on a handle will return a pointer to the referenced object or NULL,
+// if the object no longer exists. Note that during the lifetime of the returned pointer,
+// you are assuming that the object will not be deleted by any action you perform,
+// or any other thread, as normal when using pointers, so avoid using that pointer outside of
+// the local code block.
+//
+// https://wiki.lindenlab.com/mediawiki/index.php?title=LLHandle&oldid=79669
+
+template <typename T>
+class LLHandle
+{
+public:
+ LLHandle() : mTombStone(getDefaultTombStone()) {}
+ const LLHandle<T>& operator =(const LLHandle<T>& other)
+ {
+ mTombStone = other.mTombStone;
+ return *this;
+ }
+
+ bool isDead() const
+ {
+ return mTombStone->getTarget() == NULL;
+ }
+
+ void markDead()
+ {
+ mTombStone = getDefaultTombStone();
+ }
+
+ T* get() const
+ {
+ return mTombStone->getTarget();
+ }
+
+ friend bool operator== (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
+ {
+ return lhs.mTombStone == rhs.mTombStone;
+ }
+ friend bool operator!= (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
+ {
+ return !(lhs == rhs);
+ }
+ friend bool operator< (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
+ {
+ return lhs.mTombStone < rhs.mTombStone;
+ }
+ friend bool operator> (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
+ {
+ return lhs.mTombStone > rhs.mTombStone;
+ }
+protected:
+
+protected:
+ LLPointer<LLTombStone<T> > mTombStone;
+
+private:
+ static LLPointer<LLTombStone<T> >& getDefaultTombStone()
+ {
+ static LLPointer<LLTombStone<T> > sDefaultTombStone = new LLTombStone<T>;
+ return sDefaultTombStone;
+ }
+};
+
+template <typename T>
+class LLRootHandle : public LLHandle<T>
+{
+public:
+ LLRootHandle(T* object) { bind(object); }
+ LLRootHandle() {};
+ ~LLRootHandle() { unbind(); }
+
+ // this is redundant, since a LLRootHandle *is* an LLHandle
+ LLHandle<T> getHandle() { return LLHandle<T>(*this); }
+
+ void bind(T* object)
+ {
+ // unbind existing tombstone
+ if (LLHandle<T>::mTombStone.notNull())
+ {
+ if (LLHandle<T>::mTombStone->getTarget() == object) return;
+ LLHandle<T>::mTombStone->setTarget(NULL);
+ }
+ // tombstone reference counted, so no paired delete
+ LLHandle<T>::mTombStone = new LLTombStone<T>(object);
+ }
+
+ void unbind()
+ {
+ LLHandle<T>::mTombStone->setTarget(NULL);
+ }
+
+ //don't allow copying of root handles, since there should only be one
+private:
+ LLRootHandle(const LLRootHandle& other) {};
+};
+
+// Use this as a mixin for simple classes that need handles and when you don't
+// want handles at multiple points of the inheritance hierarchy
+template <typename T>
+class LLHandleProvider
+{
+protected:
+ typedef LLHandle<T> handle_type_t;
+ LLHandleProvider()
+ {
+ // provided here to enforce T deriving from LLHandleProvider<T>
+ }
+
+ LLHandle<T> getHandle()
+ {
+ // perform lazy binding to avoid small tombstone allocations for handle
+ // providers whose handles are never referenced
+ mHandle.bind(static_cast<T*>(this));
+ return mHandle;
+ }
+
+private:
+ LLRootHandle<T> mHandle;
+};
+
+#endif
diff --git a/indra/llui/llhelp.h b/indra/llui/llhelp.h
new file mode 100644
index 0000000000..938419d374
--- /dev/null
+++ b/indra/llui/llhelp.h
@@ -0,0 +1,49 @@
+/**
+ * @file llhelp.h
+ * @brief Abstract interface to the Help system
+ * @author Tofu Linden
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLHELP_H
+#define LL_LLHELP_H
+
+class LLHelp
+{
+ public:
+ virtual void showTopic(const std::string &topic) = 0;
+ // return default (fallback) topic name suitable for showTopic()
+ virtual std::string defaultTopic() = 0;
+ // return topic to use before the user logs in
+ virtual std::string preLoginTopic() = 0;
+ // return topic to use for the top-level help, invoked by F1
+ virtual std::string f1HelpTopic() = 0;
+};
+
+#endif // headerguard
diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp
index cb3b2a3a62..b1bd2b89a9 100644
--- a/indra/llui/lliconctrl.cpp
+++ b/indra/llui/lliconctrl.cpp
@@ -40,65 +40,36 @@
#include "llcontrol.h"
#include "llui.h"
#include "lluictrlfactory.h"
+#include "lluiimage.h"
-const F32 RESOLUTION_BUMP = 1.f;
+static LLDefaultChildRegistry::Register<LLIconCtrl> r("icon");
-static LLRegisterWidget<LLIconCtrl> r("icon");
-
-LLIconCtrl::LLIconCtrl(const std::string& name, const LLRect &rect, const LLUUID &image_id)
-: LLUICtrl(name,
- rect,
- FALSE, // mouse opaque
- NULL, NULL,
- FOLLOWS_LEFT | FOLLOWS_TOP),
- mColor( LLColor4::white )
+LLIconCtrl::Params::Params()
+: image("image_name"),
+ color("color"),
+ scale_image("scale_image")
{
- setImage( image_id );
- setTabStop(FALSE);
+ tab_stop = false;
+ mouse_opaque = false;
}
-LLIconCtrl::LLIconCtrl(const std::string& name, const LLRect &rect, const std::string &image_name)
-: LLUICtrl(name,
- rect,
- FALSE, // mouse opaque
- NULL, NULL,
- FOLLOWS_LEFT | FOLLOWS_TOP),
- mColor( LLColor4::white ),
- mImageName(image_name)
-{
- setImage( image_name );
- setTabStop(FALSE);
-}
-
-
-LLIconCtrl::~LLIconCtrl()
+LLIconCtrl::LLIconCtrl(const LLIconCtrl::Params& p)
+: LLUICtrl(p),
+ mColor(p.color()),
+ mImagep(p.image),
+ mPriority(0),
+ mDrawWidth(0),
+ mDrawHeight(0)
{
- mImagep = NULL;
-}
-
-
-void LLIconCtrl::setImage(const std::string& image_name)
-{
- //RN: support UUIDs masquerading as strings
- if (LLUUID::validate(image_name))
- {
- mImageID = LLUUID(image_name);
-
- setImage(mImageID);
- }
- else
+ if (mImagep.notNull())
{
- mImageName = image_name;
- mImagep = LLUI::sImageProvider->getUIImage(image_name);
- mImageID.setNull();
+ LLUICtrl::setValue(mImagep->getName());
}
}
-void LLIconCtrl::setImage(const LLUUID& image_id)
+LLIconCtrl::~LLIconCtrl()
{
- mImageName.clear();
- mImagep = LLUI::sImageProvider->getUIImageByID(image_id);
- mImageID = image_id;
+ mImagep = NULL;
}
@@ -106,69 +77,51 @@ void LLIconCtrl::draw()
{
if( mImagep.notNull() )
{
- mImagep->draw(getLocalRect(), mColor );
+ mImagep->draw(getLocalRect(), mColor.get() % getDrawContext().mAlpha );
}
LLUICtrl::draw();
}
// virtual
+// value might be a string or a UUID
void LLIconCtrl::setValue(const LLSD& value )
{
- if (value.isUUID())
+ LLSD tvalue(value);
+ if (value.isString() && LLUUID::validate(value.asString()))
+ {
+ //RN: support UUIDs masquerading as strings
+ tvalue = LLSD(LLUUID(value.asString()));
+ }
+ LLUICtrl::setValue(tvalue);
+ if (tvalue.isUUID())
{
- setImage(value.asUUID());
+ mImagep = LLUI::getUIImageByID(tvalue.asUUID(), mPriority);
}
else
{
- setImage(value.asString());
+ mImagep = LLUI::getUIImage(tvalue.asString(), mPriority);
}
-}
-// virtual
-LLSD LLIconCtrl::getValue() const
-{
- LLSD ret = getImage();
- return ret;
+ setIconImageDrawSize();
}
-// virtual
-LLXMLNodePtr LLIconCtrl::getXML(bool save_children) const
+std::string LLIconCtrl::getImageName() const
{
- LLXMLNodePtr node = LLUICtrl::getXML();
-
- if (mImageName != "")
- {
- node->createChild("image_name", TRUE)->setStringValue(mImageName);
- }
-
- node->createChild("color", TRUE)->setFloatValue(4, mColor.mV);
-
- return node;
+ if (getValue().isString())
+ return getValue().asString();
+ else
+ return std::string();
}
-LLView* LLIconCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
+void LLIconCtrl::setIconImageDrawSize()
{
- std::string name("icon");
- node->getAttributeString("name", name);
-
- LLRect rect;
- createRect(node, rect, parent, LLRect());
-
- std::string image_name;
- if (node->hasAttribute("image_name"))
+ if(mImagep.notNull() && mDrawWidth && mDrawHeight)
{
- node->getAttributeString("image_name", image_name);
+ if(mImagep->getImage().notNull())
+ {
+ mImagep->getImage()->setKnownDrawSize(mDrawWidth, mDrawHeight) ;
+ }
}
-
- LLColor4 color(LLColor4::white);
- LLUICtrlFactory::getAttributeColor(node,"color", color);
-
- LLIconCtrl* icon = new LLIconCtrl(name, rect, image_name);
-
- icon->setColor(color);
-
- icon->initFromXML(node, parent);
-
- return icon;
}
+
diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h
index 50778cf226..66368f979b 100644
--- a/indra/llui/lliconctrl.h
+++ b/indra/llui/lliconctrl.h
@@ -37,7 +37,6 @@
#include "v4color.h"
#include "lluictrl.h"
#include "stdenums.h"
-#include "llimagegl.h"
class LLTextBox;
class LLUICtrlFactory;
@@ -45,36 +44,49 @@ class LLUICtrlFactory;
//
// Classes
//
+
+//
class LLIconCtrl
: public LLUICtrl
{
public:
- LLIconCtrl(const std::string& name, const LLRect &rect, const LLUUID &image_id);
- LLIconCtrl(const std::string& name, const LLRect &rect, const std::string &image_name);
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<LLUIImage*> image;
+ Optional<LLUIColor> color;
+ Ignored scale_image;
+ Params();
+ };
+protected:
+ LLIconCtrl(const Params&);
+ friend class LLUICtrlFactory;
+
+public:
virtual ~LLIconCtrl();
// llview overrides
virtual void draw();
- void setImage(const std::string& image_name);
- void setImage(const LLUUID& image_name);
- const LLUUID &getImage() const { return mImageID; }
- std::string getImageName() const { return mImageName; }
-
- // Takes a UUID, wraps get/setImage
+ // lluictrl overrides
virtual void setValue(const LLSD& value );
- virtual LLSD getValue() const;
+
+ std::string getImageName() const;
void setColor(const LLColor4& color) { mColor = color; }
+
+private:
+ void setIconImageDrawSize() ;
+
+protected:
+ S32 mPriority;
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
+ //the output size of the icon image if set.
+ S32 mDrawWidth ;
+ S32 mDrawHeight ;
private:
- LLColor4 mColor;
- std::string mImageName;
- LLUUID mImageID;
- LLPointer<LLUIImage> mImagep;
+ LLUIColor mColor;
+ LLPointer<LLUIImage> mImagep;
};
#endif
diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp
index 51ef3dbacf..ede32084d0 100644
--- a/indra/llui/llkeywords.cpp
+++ b/indra/llui/llkeywords.cpp
@@ -223,19 +223,21 @@ LLColor3 LLKeywords::readColor( const std::string& s )
{
F32 r, g, b;
r = g = b = 0.0f;
- S32 read = sscanf(s.c_str(), "%f, %f, %f]", &r, &g, &b );
- if( read != 3 ) /* Flawfinder: ignore */
+ S32 values_read = sscanf(s.c_str(), "%f, %f, %f]", &r, &g, &b );
+ if( values_read != 3 )
{
llinfos << " poorly formed color in keyword file" << llendl;
}
return LLColor3( r, g, b );
}
+LLFastTimer::DeclareTimer FTM_SYNTAX_COLORING("Syntax Coloring");
+
// Walk through a string, applying the rules specified by the keyword token list and
// create a list of color segments.
-void LLKeywords::findSegments(std::vector<LLTextSegment *>* seg_list, const LLWString& wtext, const LLColor4 &defaultColor)
+void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLWString& wtext, const LLColor4 &defaultColor, LLTextEditor& editor)
{
- std::for_each(seg_list->begin(), seg_list->end(), DeletePointer());
+ LLFastTimer ft(FTM_SYNTAX_COLORING);
seg_list->clear();
if( wtext.empty() )
@@ -243,9 +245,9 @@ void LLKeywords::findSegments(std::vector<LLTextSegment *>* seg_list, const LLWS
return;
}
- S32 text_len = wtext.size();
+ S32 text_len = wtext.size() + 1;
- seg_list->push_back( new LLTextSegment( LLColor3(defaultColor), 0, text_len ) );
+ seg_list->push_back( new LLNormalTextSegment( defaultColor, 0, text_len, editor ) );
const llwchar* base = wtext.c_str();
const llwchar* cur = base;
@@ -296,9 +298,9 @@ void LLKeywords::findSegments(std::vector<LLTextSegment *>* seg_list, const LLWS
}
S32 seg_end = cur - base;
- LLTextSegment* text_segment = new LLTextSegment( cur_token->getColor(), seg_start, seg_end );
+ LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_token->getColor(), seg_start, seg_end, editor );
text_segment->setToken( cur_token );
- insertSegment( seg_list, text_segment, text_len, defaultColor);
+ insertSegment( seg_list, text_segment, text_len, defaultColor, editor);
line_done = TRUE; // to break out of second loop.
break;
}
@@ -405,9 +407,9 @@ void LLKeywords::findSegments(std::vector<LLTextSegment *>* seg_list, const LLWS
}
- LLTextSegment* text_segment = new LLTextSegment( cur_delimiter->getColor(), seg_start, seg_end );
+ LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_delimiter->getColor(), seg_start, seg_end, editor );
text_segment->setToken( cur_delimiter );
- insertSegment( seg_list, text_segment, text_len, defaultColor);
+ insertSegment( seg_list, text_segment, text_len, defaultColor, editor);
// Note: we don't increment cur, since the end of one delimited seg may be immediately
// followed by the start of another one.
@@ -438,9 +440,9 @@ void LLKeywords::findSegments(std::vector<LLTextSegment *>* seg_list, const LLWS
// llinfos << "Seg: [" << word.c_str() << "]" << llendl;
- LLTextSegment* text_segment = new LLTextSegment( cur_token->getColor(), seg_start, seg_end );
+ LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_token->getColor(), seg_start, seg_end, editor );
text_segment->setToken( cur_token );
- insertSegment( seg_list, text_segment, text_len, defaultColor);
+ insertSegment( seg_list, text_segment, text_len, defaultColor, editor);
}
cur += seg_len;
continue;
@@ -455,25 +457,24 @@ void LLKeywords::findSegments(std::vector<LLTextSegment *>* seg_list, const LLWS
}
}
-void LLKeywords::insertSegment(std::vector<LLTextSegment*>* seg_list, LLTextSegment* new_segment, S32 text_len, const LLColor4 &defaultColor )
+void LLKeywords::insertSegment(std::vector<LLTextSegmentPtr>* seg_list, LLTextSegmentPtr new_segment, S32 text_len, const LLColor4 &defaultColor, LLTextEditor& editor )
{
- LLTextSegment* last = seg_list->back();
+ LLTextSegmentPtr last = seg_list->back();
S32 new_seg_end = new_segment->getEnd();
if( new_segment->getStart() == last->getStart() )
{
- *last = *new_segment;
- delete new_segment;
+ seg_list->pop_back();
}
else
{
last->setEnd( new_segment->getStart() );
- seg_list->push_back( new_segment );
}
+ seg_list->push_back( new_segment );
if( new_seg_end < text_len )
{
- seg_list->push_back( new LLTextSegment( defaultColor, new_seg_end, text_len ) );
+ seg_list->push_back( new LLNormalTextSegment( defaultColor, new_seg_end, text_len, editor ) );
}
}
diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h
index 38f5e993c2..53377869ca 100644
--- a/indra/llui/llkeywords.h
+++ b/indra/llui/llkeywords.h
@@ -39,9 +39,10 @@
#include <map>
#include <list>
#include <deque>
+#include "llpointer.h"
class LLTextSegment;
-
+typedef LLPointer<LLTextSegment> LLTextSegmentPtr;
class LLKeywordToken
{
@@ -84,7 +85,7 @@ public:
BOOL loadFromFile(const std::string& filename);
BOOL isLoaded() const { return mLoaded; }
- void findSegments(std::vector<LLTextSegment *> *seg_list, const LLWString& text, const LLColor4 &defaultColor );
+ void findSegments(std::vector<LLTextSegmentPtr> *seg_list, const LLWString& text, const LLColor4 &defaultColor, class LLTextEditor& editor );
// Add the token as described
void addToken(LLKeywordToken::TOKEN_TYPE type,
@@ -103,7 +104,7 @@ public:
private:
LLColor3 readColor(const std::string& s);
- void insertSegment(std::vector<LLTextSegment *> *seg_list, LLTextSegment* new_segment, S32 text_len, const LLColor4 &defaultColor);
+ void insertSegment(std::vector<LLTextSegmentPtr> *seg_list, LLTextSegmentPtr new_segment, S32 text_len, const LLColor4 &defaultColor, class LLTextEditor& editor);
BOOL mLoaded;
word_token_map_t mWordTokenMap;
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
new file mode 100644
index 0000000000..1aaba88c49
--- /dev/null
+++ b/indra/llui/lllayoutstack.cpp
@@ -0,0 +1,823 @@
+/**
+ * @file lllayoutstack.cpp
+ * @brief LLLayout class - dynamic stacking of UI elements
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Opaque view with a background and a border. Can contain LLUICtrls.
+
+#include "linden_common.h"
+
+#include "lllayoutstack.h"
+
+#include "lllocalcliprect.h"
+#include "llpanel.h"
+#include "llresizebar.h"
+#include "llcriticaldamp.h"
+
+static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack", &LLLayoutStack::fromXML);
+
+
+//
+// LLLayoutStack
+//
+struct LLLayoutStack::LayoutPanel
+{
+ LayoutPanel(LLPanel* panelp, ELayoutOrientation orientation, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize) : mPanel(panelp),
+ mMinWidth(min_width),
+ mMinHeight(min_height),
+ mAutoResize(auto_resize),
+ mUserResize(user_resize),
+ mOrientation(orientation),
+ mCollapsed(FALSE),
+ mCollapseAmt(0.f),
+ mVisibleAmt(1.f), // default to fully visible
+ mResizeBar(NULL)
+ {
+ LLResizeBar::Side side = (orientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM;
+ LLRect resize_bar_rect = panelp->getRect();
+
+ S32 min_dim;
+ if (orientation == HORIZONTAL)
+ {
+ min_dim = mMinHeight;
+ }
+ else
+ {
+ min_dim = mMinWidth;
+ }
+ LLResizeBar::Params p;
+ p.name("resize");
+ p.resizing_view(mPanel);
+ p.min_size(min_dim);
+ p.side(side);
+ p.snapping_enabled(false);
+ mResizeBar = LLUICtrlFactory::create<LLResizeBar>(p);
+ // panels initialized as hidden should not start out partially visible
+ if (!mPanel->getVisible())
+ {
+ mVisibleAmt = 0.f;
+ }
+ }
+
+ ~LayoutPanel()
+ {
+ // probably not necessary, but...
+ delete mResizeBar;
+ mResizeBar = NULL;
+ }
+
+ F32 getCollapseFactor()
+ {
+ if (mOrientation == HORIZONTAL)
+ {
+ F32 collapse_amt =
+ clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)mMinWidth / (F32)llmax(1, mPanel->getRect().getWidth()));
+ return mVisibleAmt * collapse_amt;
+ }
+ else
+ {
+ F32 collapse_amt =
+ clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, llmin(1.f, (F32)mMinHeight / (F32)llmax(1, mPanel->getRect().getHeight())));
+ return mVisibleAmt * collapse_amt;
+ }
+ }
+
+ LLPanel* mPanel;
+ S32 mMinWidth;
+ S32 mMinHeight;
+ BOOL mAutoResize;
+ BOOL mUserResize;
+ BOOL mCollapsed;
+ LLResizeBar* mResizeBar;
+ ELayoutOrientation mOrientation;
+ F32 mVisibleAmt;
+ F32 mCollapseAmt;
+};
+
+LLLayoutStack::Params::Params()
+: orientation("orientation", std::string("vertical")),
+ animate("animate", true),
+ clip("clip", true),
+ border_size("border_size", LLCachedControl<S32>(*LLUI::sSettingGroups["config"], "UIResizeBarHeight", 0))
+{
+ name="stack";
+}
+
+LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p)
+: LLView(p),
+ mMinWidth(0),
+ mMinHeight(0),
+ mPanelSpacing(p.border_size),
+ mOrientation((p.orientation() == "vertical") ? VERTICAL : HORIZONTAL),
+ mAnimate(p.animate),
+ mAnimatedThisFrame(false),
+ mClip(p.clip)
+{}
+
+LLLayoutStack::~LLLayoutStack()
+{
+ e_panel_list_t panels = mPanels; // copy list of panel pointers
+ mPanels.clear(); // clear so that removeChild() calls don't cause trouble
+ std::for_each(panels.begin(), panels.end(), DeletePointer());
+}
+
+void LLLayoutStack::draw()
+{
+ updateLayout();
+
+ e_panel_list_t::iterator panel_it;
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ // clip to layout rectangle, not bounding rectangle
+ LLRect clip_rect = (*panel_it)->mPanel->getRect();
+ // scale clipping rectangle by visible amount
+ if (mOrientation == HORIZONTAL)
+ {
+ clip_rect.mRight = clip_rect.mLeft + llround((F32)clip_rect.getWidth() * (*panel_it)->getCollapseFactor());
+ }
+ else
+ {
+ clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->getCollapseFactor());
+ }
+
+ LLPanel* panelp = (*panel_it)->mPanel;
+
+ LLLocalClipRect clip(clip_rect, mClip);
+ // only force drawing invisible children if visible amount is non-zero
+ drawChild(panelp, 0, 0, !clip_rect.isEmpty());
+ }
+ mAnimatedThisFrame = false;
+}
+
+void LLLayoutStack::removeChild(LLView* view)
+{
+ LayoutPanel* embedded_panelp = findEmbeddedPanel(dynamic_cast<LLPanel*>(view));
+
+ if (embedded_panelp)
+ {
+ mPanels.erase(std::find(mPanels.begin(), mPanels.end(), embedded_panelp));
+ delete embedded_panelp;
+ }
+
+ // need to update resizebars
+
+ calcMinExtents();
+
+ LLView::removeChild(view);
+}
+
+BOOL LLLayoutStack::postBuild()
+{
+ updateLayout();
+ return TRUE;
+}
+
+static void get_attribute_s32_and_write(LLXMLNodePtr node,
+ const char* name,
+ S32 *value,
+ S32 default_value,
+ LLXMLNodePtr output_child)
+{
+ BOOL has_attr = node->getAttributeS32(name, *value);
+ if (has_attr && *value != default_value && output_child)
+ {
+ // create an attribute child node
+ LLXMLNodePtr child_attr = output_child->createChild(name, TRUE);
+ child_attr->setIntValue(*value);
+ }
+}
+
+static void get_attribute_bool_and_write(LLXMLNodePtr node,
+ const char* name,
+ BOOL *value,
+ BOOL default_value,
+ LLXMLNodePtr output_child)
+{
+ BOOL has_attr = node->getAttributeBOOL(name, *value);
+ if (has_attr && *value != default_value && output_child)
+ {
+ LLXMLNodePtr child_attr = output_child->createChild(name, TRUE);
+ child_attr->setBoolValue(*value);
+ }
+}
+//static
+LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)
+{
+ LLLayoutStack::Params p(LLUICtrlFactory::getDefaultParams<LLLayoutStack>());
+ LLXUIParser::instance().readXUI(node, p, LLUICtrlFactory::getInstance()->getCurFileName());
+
+ // Export must happen before setupParams() mungles rectangles and before
+ // this item gets added to parent (otherwise screws up last_child_rect
+ // logic). JC
+ if (output_node)
+ {
+ Params output_params(p);
+ setupParamsForExport(output_params, parent);
+ LLLayoutStack::Params default_params(LLUICtrlFactory::getDefaultParams<LLLayoutStack>());
+ output_node->setName(node->getName()->mString);
+ LLXUIParser::instance().writeXUI(
+ output_node, output_params, &default_params);
+ }
+
+ p.from_xui = true;
+ applyXUILayout(p, parent);
+ LLLayoutStack* layout_stackp = LLUICtrlFactory::create<LLLayoutStack>(p);
+
+ if (parent && layout_stackp)
+ {
+ S32 tab_group = p.tab_group.isProvided() ? p.tab_group() : parent->getLastTabGroup();
+
+ parent->addChild(layout_stackp, tab_group);
+ }
+
+ for (LLXMLNodePtr child_node = node->getFirstChild(); child_node.notNull(); child_node = child_node->getNextSibling())
+ {
+ const S32 DEFAULT_MIN_WIDTH = 0;
+ const S32 DEFAULT_MIN_HEIGHT = 0;
+ const BOOL DEFAULT_AUTO_RESIZE = TRUE;
+
+ S32 min_width = DEFAULT_MIN_WIDTH;
+ S32 min_height = DEFAULT_MIN_HEIGHT;
+ BOOL auto_resize = DEFAULT_AUTO_RESIZE;
+
+ LLXMLNodePtr output_child;
+ if (output_node)
+ {
+ output_child = output_node->createChild("", FALSE);
+ }
+
+ // Layout stack allows child nodes to acquire additional attributes,
+ // such as "min_width" in: <button label="Foo" min_width="100"/>
+ // If these attributes exist and have non-default values, write them
+ // to the output node.
+ get_attribute_s32_and_write(child_node, "min_width", &min_width,
+ DEFAULT_MIN_WIDTH, output_child);
+ get_attribute_s32_and_write(child_node, "min_height", &min_height,
+ DEFAULT_MIN_HEIGHT, output_child);
+ get_attribute_bool_and_write(child_node, "auto_resize", &auto_resize,
+ DEFAULT_AUTO_RESIZE, output_child);
+
+ if (child_node->hasName("layout_panel"))
+ {
+ BOOL user_resize = TRUE;
+ get_attribute_bool_and_write(child_node, "user_resize", &user_resize,
+ TRUE, output_child);
+ LLPanel* panelp = (LLPanel*)LLPanel::fromXML(child_node, layout_stackp, output_child);
+ if (panelp)
+ {
+ panelp->setFollowsNone();
+ layout_stackp->addPanel(panelp, min_width, min_height, auto_resize, user_resize);
+ }
+ }
+ else
+ {
+ BOOL user_resize = FALSE;
+ get_attribute_bool_and_write(child_node, "user_resize", &user_resize,
+ FALSE, output_child);
+
+ LLPanel::Params p;
+ p.mouse_opaque(false);
+ LLPanel* panelp = LLUICtrlFactory::create<LLPanel>(p);
+ LLView* new_child = LLUICtrlFactory::getInstance()->createFromXML(child_node, panelp, LLStringUtil::null, LLPanel::child_registry_t::instance(), output_child);
+ if (new_child)
+ {
+ // put child in new embedded panel
+ layout_stackp->addPanel(panelp, min_width, min_height, auto_resize, user_resize);
+ // resize panel to contain widget and move widget to be contained in panel
+ panelp->setRect(new_child->getRect());
+ new_child->setOrigin(0, 0);
+ }
+ else
+ {
+ panelp->die();
+ }
+ }
+
+ if (output_child && !output_child->mChildren && output_child->mAttributes.empty() && output_child->getValue().empty())
+ {
+ output_node->deleteChild(output_child);
+ }
+ }
+
+ if (!layout_stackp->postBuild())
+ {
+ delete layout_stackp;
+ return NULL;
+ }
+
+ return layout_stackp;
+}
+
+S32 LLLayoutStack::getDefaultHeight(S32 cur_height)
+{
+ // if we are spanning our children (crude upward propagation of size)
+ // then don't enforce our size on our children
+ if (mOrientation == HORIZONTAL)
+ {
+ cur_height = llmax(mMinHeight, getRect().getHeight());
+ }
+
+ return cur_height;
+}
+
+S32 LLLayoutStack::getDefaultWidth(S32 cur_width)
+{
+ // if we are spanning our children (crude upward propagation of size)
+ // then don't enforce our size on our children
+ if (mOrientation == VERTICAL)
+ {
+ cur_width = llmax(mMinWidth, getRect().getWidth());
+ }
+
+ return cur_width;
+}
+
+void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, EAnimate animate, S32 index)
+{
+ // panel starts off invisible (collapsed)
+ if (animate == ANIMATE)
+ {
+ panel->setVisible(FALSE);
+ }
+ LayoutPanel* embedded_panel = new LayoutPanel(panel, mOrientation, min_width, min_height, auto_resize, user_resize);
+
+ mPanels.insert(mPanels.begin() + llclamp(index, 0, (S32)mPanels.size()), embedded_panel);
+
+ if (panel->getParent() != this)
+ {
+ addChild(panel);
+ }
+ addChild(embedded_panel->mResizeBar);
+
+ // bring all resize bars to the front so that they are clickable even over the panels
+ // with a bit of overlap
+ for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ LLResizeBar* resize_barp = (*panel_it)->mResizeBar;
+ sendChildToFront(resize_barp);
+ }
+
+ // start expanding panel animation
+ if (animate == ANIMATE)
+ {
+ panel->setVisible(TRUE);
+ }
+}
+
+void LLLayoutStack::removePanel(LLPanel* panel)
+{
+ removeChild(panel);
+}
+
+void LLLayoutStack::collapsePanel(LLPanel* panel, BOOL collapsed)
+{
+ LayoutPanel* panel_container = findEmbeddedPanel(panel);
+ if (!panel_container) return;
+
+ panel_container->mCollapsed = collapsed;
+}
+
+void LLLayoutStack::updatePanelAutoResize(const std::string& panel_name, BOOL auto_resize)
+{
+ LayoutPanel* panel = findEmbeddedPanelByName(panel_name);
+
+ if (panel)
+ {
+ panel->mAutoResize = auto_resize;
+ }
+}
+
+void LLLayoutStack::setPanelUserResize(const std::string& panel_name, BOOL user_resize)
+{
+ LayoutPanel* panel = findEmbeddedPanelByName(panel_name);
+
+ if (panel)
+ {
+ panel->mUserResize = user_resize;
+ }
+}
+
+bool LLLayoutStack::getPanelMinSize(const std::string& panel_name, S32* min_widthp, S32* min_heightp)
+{
+ LayoutPanel* panel = findEmbeddedPanelByName(panel_name);
+
+ if (panel)
+ {
+ if (min_widthp) *min_widthp = panel->mMinWidth;
+ if (min_heightp) *min_heightp = panel->mMinHeight;
+ }
+
+ return NULL != panel;
+}
+
+static LLFastTimer::DeclareTimer FTM_UPDATE_LAYOUT("Update LayoutStacks");
+void LLLayoutStack::updateLayout(BOOL force_resize)
+{
+ LLFastTimer ft(FTM_UPDATE_LAYOUT);
+ static LLUICachedControl<S32> resize_bar_overlap ("UIResizeBarOverlap", 0);
+ calcMinExtents();
+
+ // calculate current extents
+ S32 total_width = 0;
+ S32 total_height = 0;
+
+ const F32 ANIM_OPEN_TIME = 0.02f;
+ const F32 ANIM_CLOSE_TIME = 0.03f;
+
+ e_panel_list_t::iterator panel_it;
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ LLPanel* panelp = (*panel_it)->mPanel;
+ if (panelp->getVisible())
+ {
+ if (mAnimate)
+ {
+ if (!mAnimatedThisFrame)
+ {
+ (*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 1.f, LLCriticalDamp::getInterpolant(ANIM_OPEN_TIME));
+ if ((*panel_it)->mVisibleAmt > 0.99f)
+ {
+ (*panel_it)->mVisibleAmt = 1.f;
+ }
+ }
+ }
+ else
+ {
+ (*panel_it)->mVisibleAmt = 1.f;
+ }
+ }
+ else // not visible
+ {
+ if (mAnimate)
+ {
+ if (!mAnimatedThisFrame)
+ {
+ (*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 0.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
+ if ((*panel_it)->mVisibleAmt < 0.001f)
+ {
+ (*panel_it)->mVisibleAmt = 0.f;
+ }
+ }
+ }
+ else
+ {
+ (*panel_it)->mVisibleAmt = 0.f;
+ }
+ }
+
+ if ((*panel_it)->mCollapsed)
+ {
+ (*panel_it)->mCollapseAmt = lerp((*panel_it)->mCollapseAmt, 1.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
+ }
+ else
+ {
+ (*panel_it)->mCollapseAmt = lerp((*panel_it)->mCollapseAmt, 0.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
+ }
+
+ if (mOrientation == HORIZONTAL)
+ {
+ // enforce minimize size constraint by default
+ if (panelp->getRect().getWidth() < (*panel_it)->mMinWidth)
+ {
+ panelp->reshape((*panel_it)->mMinWidth, panelp->getRect().getHeight());
+ }
+ total_width += llround(panelp->getRect().getWidth() * (*panel_it)->getCollapseFactor());
+ // want n-1 panel gaps for n panels
+ if (panel_it != mPanels.begin())
+ {
+ total_width += mPanelSpacing;
+ }
+ }
+ else //VERTICAL
+ {
+ // enforce minimize size constraint by default
+ if (panelp->getRect().getHeight() < (*panel_it)->mMinHeight)
+ {
+ panelp->reshape(panelp->getRect().getWidth(), (*panel_it)->mMinHeight);
+ }
+ total_height += llround(panelp->getRect().getHeight() * (*panel_it)->getCollapseFactor());
+ if (panel_it != mPanels.begin())
+ {
+ total_height += mPanelSpacing;
+ }
+ }
+ }
+
+ S32 num_resizable_panels = 0;
+ S32 shrink_headroom_available = 0;
+ S32 shrink_headroom_total = 0;
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ // panels that are not fully visible do not count towards shrink headroom
+ if ((*panel_it)->getCollapseFactor() < 1.f)
+ {
+ continue;
+ }
+
+ // if currently resizing a panel or the panel is flagged as not automatically resizing
+ // only track total available headroom, but don't use it for automatic resize logic
+ if ((*panel_it)->mResizeBar->hasMouseCapture()
+ || (!(*panel_it)->mAutoResize
+ && !force_resize))
+ {
+ if (mOrientation == HORIZONTAL)
+ {
+ shrink_headroom_total += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
+ }
+ else //VERTICAL
+ {
+ shrink_headroom_total += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
+ }
+ }
+ else
+ {
+ num_resizable_panels++;
+ if (mOrientation == HORIZONTAL)
+ {
+ shrink_headroom_available += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
+ shrink_headroom_total += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
+ }
+ else //VERTICAL
+ {
+ shrink_headroom_available += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
+ shrink_headroom_total += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
+ }
+ }
+ }
+
+ // calculate how many pixels need to be distributed among layout panels
+ // positive means panels need to grow, negative means shrink
+ S32 pixels_to_distribute;
+ if (mOrientation == HORIZONTAL)
+ {
+ pixels_to_distribute = getRect().getWidth() - total_width;
+ }
+ else //VERTICAL
+ {
+ pixels_to_distribute = getRect().getHeight() - total_height;
+ }
+
+ // now we distribute the pixels...
+ S32 cur_x = 0;
+ S32 cur_y = getRect().getHeight();
+
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ LLPanel* panelp = (*panel_it)->mPanel;
+
+ S32 cur_width = panelp->getRect().getWidth();
+ S32 cur_height = panelp->getRect().getHeight();
+ S32 new_width = llmax((*panel_it)->mMinWidth, cur_width);
+ S32 new_height = llmax((*panel_it)->mMinHeight, cur_height);
+
+ S32 delta_size = 0;
+
+ // if panel can automatically resize (not animating, and resize flag set)...
+ if ((*panel_it)->getCollapseFactor() == 1.f
+ && (force_resize || (*panel_it)->mAutoResize)
+ && !(*panel_it)->mResizeBar->hasMouseCapture())
+ {
+ if (mOrientation == HORIZONTAL)
+ {
+ // if we're shrinking
+ if (pixels_to_distribute < 0)
+ {
+ // shrink proportionally to amount over minimum
+ // so we can do this in one pass
+ delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_width - (*panel_it)->mMinWidth) / (F32)shrink_headroom_available)) : 0;
+ shrink_headroom_available -= (cur_width - (*panel_it)->mMinWidth);
+ }
+ else
+ {
+ // grow all elements equally
+ delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
+ num_resizable_panels--;
+ }
+ pixels_to_distribute -= delta_size;
+ new_width = llmax((*panel_it)->mMinWidth, cur_width + delta_size);
+ }
+ else
+ {
+ new_width = getDefaultWidth(new_width);
+ }
+
+ if (mOrientation == VERTICAL)
+ {
+ if (pixels_to_distribute < 0)
+ {
+ // shrink proportionally to amount over minimum
+ // so we can do this in one pass
+ delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_height - (*panel_it)->mMinHeight) / (F32)shrink_headroom_available)) : 0;
+ shrink_headroom_available -= (cur_height - (*panel_it)->mMinHeight);
+ }
+ else
+ {
+ delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
+ num_resizable_panels--;
+ }
+ pixels_to_distribute -= delta_size;
+ new_height = llmax((*panel_it)->mMinHeight, cur_height + delta_size);
+ }
+ else
+ {
+ new_height = getDefaultHeight(new_height);
+ }
+ }
+ else
+ {
+ if (mOrientation == HORIZONTAL)
+ {
+ new_height = getDefaultHeight(new_height);
+ }
+ else // VERTICAL
+ {
+ new_width = getDefaultWidth(new_width);
+ }
+ }
+
+ // adjust running headroom count based on new sizes
+ shrink_headroom_total += delta_size;
+
+ LLRect panel_rect;
+ panel_rect.setLeftTopAndSize(cur_x, cur_y, new_width, new_height);
+ panelp->setShape(panel_rect);
+
+ LLRect resize_bar_rect = panel_rect;
+ if (mOrientation == HORIZONTAL)
+ {
+ resize_bar_rect.mLeft = panel_rect.mRight - resize_bar_overlap;
+ resize_bar_rect.mRight = panel_rect.mRight + mPanelSpacing + resize_bar_overlap;
+ }
+ else
+ {
+ resize_bar_rect.mTop = panel_rect.mBottom + resize_bar_overlap;
+ resize_bar_rect.mBottom = panel_rect.mBottom - mPanelSpacing - resize_bar_overlap;
+ }
+ (*panel_it)->mResizeBar->setRect(resize_bar_rect);
+
+ if (mOrientation == HORIZONTAL)
+ {
+ cur_x += llround(new_width * (*panel_it)->getCollapseFactor()) + mPanelSpacing;
+ }
+ else //VERTICAL
+ {
+ cur_y -= llround(new_height * (*panel_it)->getCollapseFactor()) + mPanelSpacing;
+ }
+ }
+
+ // update resize bars with new limits
+ LLResizeBar* last_resize_bar = NULL;
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ LLPanel* panelp = (*panel_it)->mPanel;
+
+ if (mOrientation == HORIZONTAL)
+ {
+ (*panel_it)->mResizeBar->setResizeLimits(
+ (*panel_it)->mMinWidth,
+ (*panel_it)->mMinWidth + shrink_headroom_total);
+ }
+ else //VERTICAL
+ {
+ (*panel_it)->mResizeBar->setResizeLimits(
+ (*panel_it)->mMinHeight,
+ (*panel_it)->mMinHeight + shrink_headroom_total);
+ }
+
+ // toggle resize bars based on panel visibility, resizability, etc
+ BOOL resize_bar_enabled = panelp->getVisible() && (*panel_it)->mUserResize;
+ (*panel_it)->mResizeBar->setVisible(resize_bar_enabled);
+
+ if (resize_bar_enabled)
+ {
+ last_resize_bar = (*panel_it)->mResizeBar;
+ }
+ }
+
+ // hide last resize bar as there is nothing past it
+ // resize bars need to be in between two resizable panels
+ if (last_resize_bar)
+ {
+ last_resize_bar->setVisible(FALSE);
+ }
+
+ // not enough room to fit existing contents
+ if (force_resize == FALSE
+ // layout did not complete by reaching target position
+ && ((mOrientation == VERTICAL && cur_y != -mPanelSpacing)
+ || (mOrientation == HORIZONTAL && cur_x != getRect().getWidth() + mPanelSpacing)))
+ {
+ // do another layout pass with all stacked elements contributing
+ // even those that don't usually resize
+ llassert_always(force_resize == FALSE);
+ updateLayout(TRUE);
+ }
+
+ mAnimatedThisFrame = true;
+} // end LLLayoutStack::updateLayout
+
+
+LLLayoutStack::LayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const
+{
+ if (!panelp) return NULL;
+
+ e_panel_list_t::const_iterator panel_it;
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ if ((*panel_it)->mPanel == panelp)
+ {
+ return *panel_it;
+ }
+ }
+ return NULL;
+}
+
+LLLayoutStack::LayoutPanel* LLLayoutStack::findEmbeddedPanelByName(const std::string& name) const
+{
+ LayoutPanel* result = NULL;
+
+ for (e_panel_list_t::const_iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ LayoutPanel* p = *panel_it;
+
+ if (p->mPanel->getName() == name)
+ {
+ result = p;
+ break;
+ }
+ }
+
+ return result;
+}
+
+// Compute sum of min_width or min_height of children
+void LLLayoutStack::calcMinExtents()
+{
+ mMinWidth = 0;
+ mMinHeight = 0;
+
+ e_panel_list_t::iterator panel_it;
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ if (mOrientation == HORIZONTAL)
+ {
+ mMinHeight = llmax( mMinHeight,
+ (*panel_it)->mMinHeight);
+ mMinWidth += (*panel_it)->mMinWidth;
+ if (panel_it != mPanels.begin())
+ {
+ mMinWidth += mPanelSpacing;
+ }
+ }
+ else //VERTICAL
+ {
+ mMinWidth = llmax( mMinWidth,
+ (*panel_it)->mMinWidth);
+ mMinHeight += (*panel_it)->mMinHeight;
+ if (panel_it != mPanels.begin())
+ {
+ mMinHeight += mPanelSpacing;
+ }
+ }
+ }
+}
+
+// update layout stack animations, etc. once per frame
+// NOTE: we use this to size world view based on animating UI, *before* we draw the UI
+// we might still need to call updateLayout during UI draw phase, in case UI elements
+// are resizing themselves dynamically
+//static
+void LLLayoutStack::updateClass()
+{
+ for (LLLayoutStack::instance_iter it = beginInstances(); it != endInstances(); ++it)
+ {
+ it->updateLayout();
+ }
+}
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
new file mode 100644
index 0000000000..c4f10038f8
--- /dev/null
+++ b/indra/llui/lllayoutstack.h
@@ -0,0 +1,130 @@
+/**
+ * @file lllayoutstack.h
+ * @author Richard Nelson
+ * @brief LLLayout class - dynamic stacking of UI elements
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLLAYOUTSTACK_H
+#define LL_LLLAYOUTSTACK_H
+
+#include "llview.h"
+
+class LLPanel;
+
+class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack>
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
+ {
+ Optional<std::string> orientation;
+ Optional<S32> border_size;
+ Optional<bool> animate,
+ clip;
+
+ Params();
+ };
+
+ typedef enum e_layout_orientation
+ {
+ HORIZONTAL,
+ VERTICAL
+ } ELayoutOrientation;
+
+ virtual ~LLLayoutStack();
+
+ /*virtual*/ void draw();
+ /*virtual*/ void removeChild(LLView*);
+ /*virtual*/ BOOL postBuild();
+
+ static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL);
+
+ S32 getMinWidth() const { return mMinWidth; }
+ S32 getMinHeight() const { return mMinHeight; }
+
+ typedef enum e_animate
+ {
+ NO_ANIMATE,
+ ANIMATE
+ } EAnimate;
+
+ void addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, EAnimate animate = NO_ANIMATE, S32 index = S32_MAX);
+ void removePanel(LLPanel* panel);
+ void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE);
+ S32 getNumPanels() { return mPanels.size(); }
+
+ void updatePanelAutoResize(const std::string& panel_name, BOOL auto_resize);
+ void setPanelUserResize(const std::string& panel_name, BOOL user_resize);
+
+ /**
+ * Gets minimal width and/or height of the specified by name panel.
+ *
+ * If it is necessary to get only the one dimension pass NULL for another one.
+ * @returns true if specified by panel_name internal panel exists, false otherwise.
+ */
+ bool getPanelMinSize(const std::string& panel_name, S32* min_widthp, S32* min_heightp);
+
+ void updateLayout(BOOL force_resize = FALSE);
+
+ S32 getPanelSpacing() const { return mPanelSpacing; }
+ BOOL getAnimate () const { return mAnimate; }
+ void setAnimate (BOOL animate) { mAnimate = animate; }
+
+ static void updateClass();
+
+protected:
+ LLLayoutStack(const Params&);
+ friend class LLUICtrlFactory;
+
+private:
+ struct LayoutPanel;
+
+ void calcMinExtents();
+ S32 getDefaultHeight(S32 cur_height);
+ S32 getDefaultWidth(S32 cur_width);
+
+ const ELayoutOrientation mOrientation;
+
+ typedef std::vector<LayoutPanel*> e_panel_list_t;
+ e_panel_list_t mPanels;
+
+ LayoutPanel* findEmbeddedPanel(LLPanel* panelp) const;
+ LayoutPanel* findEmbeddedPanelByName(const std::string& name) const;
+
+ S32 mMinWidth; // calculated by calcMinExtents
+ S32 mMinHeight; // calculated by calcMinExtents
+ S32 mPanelSpacing;
+
+ // true if we already applied animation this frame
+ bool mAnimatedThisFrame;
+ bool mAnimate;
+ bool mClip;
+}; // end class LLLayoutStack
+
+#endif
diff --git a/indra/llui/lllazyvalue.h b/indra/llui/lllazyvalue.h
new file mode 100644
index 0000000000..cf45214628
--- /dev/null
+++ b/indra/llui/lllazyvalue.h
@@ -0,0 +1,88 @@
+/**
+ * @file lllazyvalue.h
+ * @brief generic functor/value abstraction for lazy evaluation of a value
+ * parsing construction parameters from xml and LLSD
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LAZY_VALUE_H
+#define LL_LAZY_VALUE_H
+
+#include <boost/function.hpp>
+
+// Holds on to a value of type T *or* calls a functor to generate a value of type T
+template<typename T>
+class LLLazyValue
+{
+public:
+ typedef typename boost::add_reference<typename boost::add_const<T>::type>::type T_const_ref;
+ typedef typename boost::function<T_const_ref (void)> function_type;
+
+public:
+ LLLazyValue(const function_type& value)
+ : mValueGetter(value)
+ {}
+ LLLazyValue(T_const_ref value)
+ : mValue(value)
+ {}
+ LLLazyValue()
+ : mValue()
+ {}
+
+ void set(const LLLazyValue& val)
+ {
+ mValueGetter = val.mValueGetter;
+ }
+
+ void set(T_const_ref val)
+ {
+ mValue = val;
+ mValueGetter = NULL;
+ }
+
+ T_const_ref get() const
+ {
+ if (!mValueGetter.empty())
+ {
+ return mValueGetter();
+ }
+ return mValue;
+ }
+
+ bool isUsingFunction() const
+ {
+ return mValueGetter != NULL;
+ }
+
+private:
+ function_type mValueGetter;
+ T mValue;
+};
+
+#endif // LL_LAZY_VALUE_H
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 964254d93f..73e4d126f3 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -34,10 +34,10 @@
#include "linden_common.h"
+#define LLLINEEDITOR_CPP
#include "lllineeditor.h"
#include "lltexteditor.h"
-#include "audioengine.h"
#include "llmath.h"
#include "llfontgl.h"
#include "llgl.h"
@@ -64,122 +64,133 @@
// Constants
//
-const S32 UI_LINEEDITOR_CURSOR_THICKNESS = 2;
-const S32 UI_LINEEDITOR_H_PAD = 2;
-const S32 UI_LINEEDITOR_V_PAD = 1;
const F32 CURSOR_FLASH_DELAY = 1.0f; // in seconds
const S32 SCROLL_INCREMENT_ADD = 0; // make space for typing
const S32 SCROLL_INCREMENT_DEL = 4; // make space for baskspacing
const F32 AUTO_SCROLL_TIME = 0.05f;
+const F32 TRIPLE_CLICK_INTERVAL = 0.3f; // delay between double and triple click. *TODO: make this equal to the double click interval?
-const F32 PREEDIT_MARKER_BRIGHTNESS = 0.4f;
-const S32 PREEDIT_MARKER_GAP = 1;
-const S32 PREEDIT_MARKER_POSITION = 2;
-const S32 PREEDIT_MARKER_THICKNESS = 1;
-const F32 PREEDIT_STANDOUT_BRIGHTNESS = 0.6f;
-const S32 PREEDIT_STANDOUT_GAP = 1;
-const S32 PREEDIT_STANDOUT_POSITION = 2;
-const S32 PREEDIT_STANDOUT_THICKNESS = 2;
+static LLDefaultChildRegistry::Register<LLLineEditor> r1("line_editor");
-static LLRegisterWidget<LLLineEditor> r1("line_editor");
-
-/* static */ LLPointer<LLUIImage> LLLineEditor::sImage;
+// Compiler optimization, generate extern template
+template class LLLineEditor* LLView::getChild<class LLLineEditor>(
+ const std::string& name, BOOL recurse) const;
//
// Member functions
//
-
-LLLineEditor::LLLineEditor(const std::string& name, const LLRect& rect,
- const std::string& default_text, const LLFontGL* font,
- S32 max_length_bytes,
- void (*commit_callback)(LLUICtrl* caller, void* user_data ),
- void (*keystroke_callback)(LLLineEditor* caller, void* user_data ),
- void (*focus_lost_callback)(LLFocusableElement* caller, void* user_data ),
- void* userdata,
- LLLinePrevalidateFunc prevalidate_func,
- LLViewBorder::EBevel border_bevel,
- LLViewBorder::EStyle border_style,
- S32 border_thickness)
- :
- LLUICtrl( name, rect, TRUE, commit_callback, userdata, FOLLOWS_TOP | FOLLOWS_LEFT ),
- mMaxLengthBytes(max_length_bytes),
- mCursorPos( 0 ),
- mScrollHPos( 0 ),
- mTextPadLeft(0),
- mTextPadRight(0),
- mCommitOnFocusLost( TRUE ),
- mRevertOnEsc( TRUE ),
- mKeystrokeCallback( keystroke_callback ),
- mIsSelecting( FALSE ),
- mSelectionStart( 0 ),
- mSelectionEnd( 0 ),
- mLastSelectionX(-1),
- mLastSelectionY(-1),
- mLastSelectionStart(-1),
- mLastSelectionEnd(-1),
- mPrevalidateFunc( prevalidate_func ),
- mCursorColor( LLUI::sColorsGroup->getColor( "TextCursorColor" ) ),
- mFgColor( LLUI::sColorsGroup->getColor( "TextFgColor" ) ),
- mReadOnlyFgColor( LLUI::sColorsGroup->getColor( "TextFgReadOnlyColor" ) ),
- mTentativeFgColor( LLUI::sColorsGroup->getColor( "TextFgTentativeColor" ) ),
- mWriteableBgColor( LLUI::sColorsGroup->getColor( "TextBgWriteableColor" ) ),
- mReadOnlyBgColor( LLUI::sColorsGroup->getColor( "TextBgReadOnlyColor" ) ),
- mFocusBgColor( LLUI::sColorsGroup->getColor( "TextBgFocusColor" ) ),
- mBorderThickness( border_thickness ),
- mIgnoreArrowKeys( FALSE ),
- mIgnoreTab( TRUE ),
- mDrawAsterixes( FALSE ),
- mHandleEditKeysDirectly( FALSE ),
- mSelectAllonFocusReceived( FALSE ),
- mPassDelete(FALSE),
- mReadOnly(FALSE),
- mImage( sImage ),
- mReplaceNewlinesWithSpaces( TRUE )
-{
- llassert( max_length_bytes > 0 );
-
- // line history support:
- // - initialize line history list
- mLineHistory.insert( mLineHistory.end(), "" );
- // - disable line history by default
- mHaveHistory = FALSE;
- // - reset current history line pointer
- mCurrentHistoryLine = 0;
-
- if (font)
- {
- mGLFont = font;
- }
- else
- {
- mGLFont = LLFontGL::getFontSansSerifSmall();
- }
-
- setFocusLostCallback(focus_lost_callback);
- setTextPadding(0, 0);
+void LLLineEditor::PrevalidateNamedFuncs::declareValues()
+{
+ declare("ascii", LLLineEditor::prevalidateASCII);
+ declare("float", LLLineEditor::prevalidateFloat);
+ declare("int", LLLineEditor::prevalidateInt);
+ declare("positive_s32", LLLineEditor::prevalidatePositiveS32);
+ declare("non_negative_s32", LLLineEditor::prevalidateNonNegativeS32);
+ declare("alpha_num", LLLineEditor::prevalidateAlphaNum);
+ declare("alpha_num_space", LLLineEditor::prevalidateAlphaNumSpace);
+ declare("ascii_printable_no_pipe", LLLineEditor::prevalidateASCIIPrintableNoPipe);
+ declare("ascii_printable_no_space", LLLineEditor::prevalidateASCIIPrintableNoSpace);
+}
+
+LLLineEditor::Params::Params()
+: max_length_bytes("max_length", 254),
+ keystroke_callback("keystroke_callback"),
+ prevalidate_callback("prevalidate_callback"),
+ background_image("background_image"),
+ background_image_disabled("background_image_disabled"),
+ background_image_focused("background_image_focused"),
+ select_on_focus("select_on_focus", false),
+ handle_edit_keys_directly("handle_edit_keys_directly", false),
+ revert_on_esc("revert_on_esc", true),
+ commit_on_focus_lost("commit_on_focus_lost", true),
+ ignore_tab("ignore_tab", true),
+ cursor_color("cursor_color"),
+ text_color("text_color"),
+ text_readonly_color("text_readonly_color"),
+ text_tentative_color("text_tentative_color"),
+ highlight_color("highlight_color"),
+ preedit_bg_color("preedit_bg_color"),
+ border(""),
+ bg_visible("bg_visible"),
+ text_pad_left("text_pad_left"),
+ text_pad_right("text_pad_right"),
+ default_text("default_text")
+{
+ mouse_opaque = true;
+ addSynonym(select_on_focus, "select_all_on_focus_received");
+ addSynonym(border, "border");
+ addSynonym(label, "watermark_text");
+}
+
+LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
+: LLUICtrl(p),
+ mMaxLengthBytes(p.max_length_bytes),
+ mCursorPos( 0 ),
+ mScrollHPos( 0 ),
+ mTextPadLeft(p.text_pad_left),
+ mTextPadRight(p.text_pad_right),
+ mTextLeftEdge(0), // computed in updateTextPadding() below
+ mTextRightEdge(0), // computed in updateTextPadding() below
+ mCommitOnFocusLost( p.commit_on_focus_lost ),
+ mRevertOnEsc( p.revert_on_esc ),
+ mKeystrokeCallback( p.keystroke_callback() ),
+ mIsSelecting( FALSE ),
+ mSelectionStart( 0 ),
+ mSelectionEnd( 0 ),
+ mLastSelectionX(-1),
+ mLastSelectionY(-1),
+ mLastSelectionStart(-1),
+ mLastSelectionEnd(-1),
+ mBorderThickness( 0 ),
+ mIgnoreArrowKeys( FALSE ),
+ mIgnoreTab( p.ignore_tab ),
+ mDrawAsterixes( FALSE ),
+ mHandleEditKeysDirectly(p.handle_edit_keys_directly),
+ mSelectAllonFocusReceived( p.select_on_focus ),
+ mPassDelete(FALSE),
+ mReadOnly(FALSE),
+ mBgImage( p.background_image ),
+ mBgImageDisabled( p.background_image_disabled ),
+ mBgImageFocused( p.background_image_focused ),
+ mHaveHistory(FALSE),
+ mReplaceNewlinesWithSpaces( TRUE ),
+ mLabel(p.label),
+ mCursorColor(p.cursor_color()),
+ mFgColor(p.text_color()),
+ mReadOnlyFgColor(p.text_readonly_color()),
+ mTentativeFgColor(p.text_tentative_color()),
+ mHighlightColor(p.highlight_color()),
+ mPreeditBgColor(p.preedit_bg_color()),
+ mGLFont(p.font)
+{
+ llassert( mMaxLengthBytes > 0 );
mScrollTimer.reset();
+ mTripleClickTimer.reset();
+ setText(p.default_text());
+
+ // Initialize current history line iterator
+ mCurrentHistoryLine = mLineHistory.begin();
+
+ LLRect border_rect(getLocalRect());
+ // adjust for gl line drawing glitch
+ border_rect.mTop -= 1;
+ border_rect.mRight -=1;
+ LLViewBorder::Params border_p(p.border);
+ border_p.rect = border_rect;
+ border_p.follows.flags = FOLLOWS_ALL;
+ border_p.bevel_style = LLViewBorder::BEVEL_IN;
+ mBorder = LLUICtrlFactory::create<LLViewBorder>(border_p);
+ addChild( mBorder );
- setText(default_text);
-
+ // clamp text padding to current editor size
+ updateTextPadding();
setCursor(mText.length());
- // Scalable UI somehow made these rectangles off-by-one.
- // I don't know why. JC
- LLRect border_rect(0, getRect().getHeight()-1, getRect().getWidth()-1, 0);
- mBorder = new LLViewBorder( std::string("line ed border"), border_rect, border_bevel, border_style, mBorderThickness );
- addChild( mBorder );
- mBorder->setFollows(FOLLOWS_LEFT|FOLLOWS_RIGHT|FOLLOWS_TOP|FOLLOWS_BOTTOM);
-
- if( ! sImage)
- {
- sImage = LLUI::getUIImage("sm_rounded_corners_simple.tga");
- }
- mImage = sImage;
+ setPrevalidate(p.prevalidate_callback());
}
-
-
+
LLLineEditor::~LLLineEditor()
{
mCommitOnFocusLost = FALSE;
@@ -222,15 +233,44 @@ void LLLineEditor::onFocusLost()
LLUICtrl::onFocusLost();
}
+// virtual
void LLLineEditor::onCommit()
{
// put current line into the line history
updateHistory();
+ setControlValue(getValue());
LLUICtrl::onCommit();
selectAll();
}
+// Returns TRUE if user changed value at all
+// virtual
+BOOL LLLineEditor::isDirty() const
+{
+ return mText.getString() != mPrevText;
+}
+
+// Clear dirty state
+// virtual
+void LLLineEditor::resetDirty()
+{
+ mPrevText = mText.getString();
+}
+
+// assumes UTF8 text
+// virtual
+void LLLineEditor::setValue(const LLSD& value )
+{
+ setText(value.asString());
+}
+
+//virtual
+LLSD LLLineEditor::getValue() const
+{
+ return LLSD(getText());
+}
+
// line history support
void LLLineEditor::updateHistory()
@@ -239,23 +279,38 @@ void LLLineEditor::updateHistory()
// reset current history line number.
// Be sure only to remember lines that are not empty and that are
// different from the last on the list.
- if( mHaveHistory && mText.length() && ( mLineHistory.empty() || getText() != mLineHistory.back() ) )
+ if( mHaveHistory && getLength() )
{
- // discard possible empty line at the end of the history
- // inserted by setText()
- if( !mLineHistory.back().length() )
+ if( !mLineHistory.empty() )
+ {
+ // When not empty, last line of history should always be blank.
+ if( mLineHistory.back().empty() )
+ {
+ // discard the empty line
+ mLineHistory.pop_back();
+ }
+ else
+ {
+ LL_WARNS("") << "Last line of history was not blank." << LL_ENDL;
+ }
+ }
+
+ // Add text to history, ignoring duplicates
+ if( mLineHistory.empty() || getText() != mLineHistory.back() )
{
- mLineHistory.pop_back();
+ mLineHistory.push_back( getText() );
}
- mLineHistory.insert( mLineHistory.end(), getText() );
- mCurrentHistoryLine = mLineHistory.size() - 1;
+
+ // Restore the blank line and set mCurrentHistoryLine to point at it
+ mLineHistory.push_back( "" );
+ mCurrentHistoryLine = mLineHistory.end() - 1;
}
}
void LLLineEditor::reshape(S32 width, S32 height, BOOL called_from_parent)
{
LLUICtrl::reshape(width, height, called_from_parent);
- setTextPadding(mTextPadLeft, mTextPadRight); // For clamping side-effect.
+ updateTextPadding(); // For clamping side-effect.
setCursor(mCursorPos); // For clamping side-effect.
}
@@ -273,12 +328,23 @@ void LLLineEditor::setMaxTextLength(S32 max_text_length)
mMaxLengthBytes = max_len;
}
+void LLLineEditor::getTextPadding(S32 *left, S32 *right)
+{
+ *left = mTextPadLeft;
+ *right = mTextPadRight;
+}
+
void LLLineEditor::setTextPadding(S32 left, S32 right)
{
- mTextPadLeft = llclamp(left, 0, getRect().getWidth());
- mTextPadRight = llclamp(right, 0, getRect().getWidth());
- mMinHPixels = UI_LINEEDITOR_H_PAD + mTextPadLeft;
- mMaxHPixels = getRect().getWidth() - mMinHPixels - mTextPadRight;
+ mTextPadLeft = left;
+ mTextPadRight = right;
+ updateTextPadding();
+}
+
+void LLLineEditor::updateTextPadding()
+{
+ mTextLeftEdge = llclamp(mTextPadLeft, 0, getRect().getWidth());
+ mTextRightEdge = getRect().getWidth() - llclamp(mTextPadRight, 0, getRect().getWidth());
}
@@ -319,11 +385,8 @@ void LLLineEditor::setText(const LLStringExplicit &new_text)
}
setCursor(llmin((S32)mText.length(), getCursor()));
- // Newly set text goes always in the last line of history.
- // Possible empty strings (as with chat line) will be deleted later.
- mLineHistory.insert( mLineHistory.end(), new_text );
// Set current history line to end of history.
- mCurrentHistoryLine = mLineHistory.size() - 1;
+ mCurrentHistoryLine = mLineHistory.end() - 1;
mPrevText = mText;
}
@@ -347,8 +410,8 @@ void LLLineEditor::setCursorAtLocalPos( S32 local_mouse_x )
mScrollHPos +
mGLFont->charFromPixelOffset(
wtext, mScrollHPos,
- (F32)(local_mouse_x - mMinHPixels),
- (F32)(mMaxHPixels - mMinHPixels + 1)); // min-max range is inclusive
+ (F32)(local_mouse_x - mTextLeftEdge),
+ (F32)(mTextRightEdge - mTextLeftEdge + 1)); // min-max range is inclusive
setCursor(cursor_pos);
}
@@ -358,11 +421,11 @@ void LLLineEditor::setCursor( S32 pos )
mCursorPos = llclamp( pos, 0, mText.length());
S32 pixels_after_scroll = findPixelNearestPos();
- if( pixels_after_scroll > mMaxHPixels )
+ if( pixels_after_scroll > mTextRightEdge )
{
S32 width_chars_to_left = mGLFont->getWidth(mText.getWString().c_str(), 0, mScrollHPos);
- S32 last_visible_char = mGLFont->maxDrawableChars(mText.getWString().c_str(), llmax(0.f, (F32)(mMaxHPixels - mMinHPixels + width_chars_to_left)));
- S32 min_scroll = mGLFont->firstDrawableChar(mText.getWString().c_str(), (F32)(mMaxHPixels - mMinHPixels - UI_LINEEDITOR_CURSOR_THICKNESS - UI_LINEEDITOR_H_PAD), mText.length(), getCursor());
+ S32 last_visible_char = mGLFont->maxDrawableChars(mText.getWString().c_str(), llmax(0.f, (F32)(mTextRightEdge - mTextLeftEdge + width_chars_to_left)));
+ S32 min_scroll = mGLFont->firstDrawableChar(mText.getWString().c_str(), (F32)(mTextRightEdge - mTextLeftEdge), mText.length(), getCursor());
if (old_cursor_pos == last_visible_char)
{
mScrollHPos = llmin(mText.length(), llmax(min_scroll, mScrollHPos + SCROLL_INCREMENT_ADD));
@@ -439,6 +502,7 @@ void LLLineEditor::selectAll()
BOOL LLLineEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
{
setFocus( TRUE );
+ mTripleClickTimer.setTimerExpirySec(TRIPLE_CLICK_INTERVAL);
if (mSelectionEnd == 0 && mSelectionStart == mText.length())
{
@@ -452,19 +516,19 @@ BOOL LLLineEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
BOOL doSelectAll = TRUE;
// Select the word we're on
- if( LLTextEditor::isPartOfWord( wtext[mCursorPos] ) )
+ if( LLWStringUtil::isPartOfWord( wtext[mCursorPos] ) )
{
S32 old_selection_start = mLastSelectionStart;
S32 old_selection_end = mLastSelectionEnd;
// Select word the cursor is over
- while ((mCursorPos > 0) && LLTextEditor::isPartOfWord( wtext[mCursorPos-1] ))
+ while ((mCursorPos > 0) && LLWStringUtil::isPartOfWord( wtext[mCursorPos-1] ))
{ // Find the start of the word
mCursorPos--;
}
startSelection();
- while ((mCursorPos < (S32)wtext.length()) && LLTextEditor::isPartOfWord( wtext[mCursorPos] ) )
+ while ((mCursorPos < (S32)wtext.length()) && LLWStringUtil::isPartOfWord( wtext[mCursorPos] ) )
{ // Find the end of the word
mCursorPos++;
}
@@ -502,18 +566,13 @@ BOOL LLLineEditor::handleMouseDown(S32 x, S32 y, MASK mask)
{
return TRUE;
}
- if (mSelectAllonFocusReceived
- && gFocusMgr.getKeyboardFocus() != this)
- {
- setFocus( TRUE );
- }
- else
+
+ if (!mSelectAllonFocusReceived
+ || gFocusMgr.getKeyboardFocus() == this)
{
mLastSelectionStart = -1;
mLastSelectionStart = -1;
- setFocus( TRUE );
-
if (mask & MASK_SHIFT)
{
// Handle selection extension
@@ -555,21 +614,37 @@ BOOL LLLineEditor::handleMouseDown(S32 x, S32 y, MASK mask)
}
else
{
- // Save selection for word/line selecting on double-click
- mLastSelectionStart = mSelectionStart;
- mLastSelectionEnd = mSelectionEnd;
+ if (mTripleClickTimer.hasExpired())
+ {
+ // Save selection for word/line selecting on double-click
+ mLastSelectionStart = mSelectionStart;
+ mLastSelectionEnd = mSelectionEnd;
- // Move cursor and deselect for regular click
- setCursorAtLocalPos( x );
- deselect();
- startSelection();
+ // Move cursor and deselect for regular click
+ setCursorAtLocalPos( x );
+ deselect();
+ startSelection();
+ }
+ else // handle triple click
+ {
+ selectAll();
+ // We don't want handleMouseUp() to "finish" the selection (and thereby
+ // set mSelectionEnd to where the mouse is), so we finish the selection
+ // here.
+ mIsSelecting = FALSE;
+ }
}
gFocusMgr.setMouseCapture( this );
}
+ setFocus(TRUE);
+
// delay cursor flashing
mKeystrokeTimer.reset();
+
+ if (mMouseDownSignal)
+ (*mMouseDownSignal)(this,x,y,mask);
return TRUE;
}
@@ -611,17 +686,17 @@ BOOL LLLineEditor::handleHover(S32 x, S32 y, MASK mask)
S32 increment = llround(mScrollTimer.getElapsedTimeF32() / AUTO_SCROLL_TIME);
mScrollTimer.reset();
mScrollTimer.setTimerExpirySec(AUTO_SCROLL_TIME);
- if( (x < mMinHPixels) && (mScrollHPos > 0 ) )
+ if( (x < mTextLeftEdge) && (mScrollHPos > 0 ) )
{
// Scroll to the left
mScrollHPos = llclamp(mScrollHPos - increment, 0, mText.length());
}
else
- if( (x > mMaxHPixels) && (mCursorPos < (S32)mText.length()) )
+ if( (x > mTextRightEdge) && (mCursorPos < (S32)mText.length()) )
{
// If scrolling one pixel would make a difference...
S32 pixels_after_scrolling_one_char = findPixelNearestPos(1);
- if( pixels_after_scrolling_one_char >= mMaxHPixels )
+ if( pixels_after_scrolling_one_char >= mTextRightEdge )
{
// ...scroll to the right
mScrollHPos = llclamp(mScrollHPos + increment, 0, mText.length());
@@ -683,7 +758,10 @@ BOOL LLLineEditor::handleMouseUp(S32 x, S32 y, MASK mask)
// take selection to 'primary' clipboard
updatePrimary();
}
-
+
+ // We won't call LLUICtrl::handleMouseUp to avoid double calls of childrenHandleMouseUp().Just invoke the signal manually.
+ if (mMouseUpSignal)
+ (*mMouseUpSignal)(this,x,y, mask);
return handled;
}
@@ -783,7 +861,7 @@ S32 LLLineEditor::prevWordPos(S32 cursorPos) const
{
cursorPos--;
}
- while( (cursorPos > 0) && LLTextEditor::isPartOfWord( wtext[cursorPos-1] ) )
+ while( (cursorPos > 0) && LLWStringUtil::isPartOfWord( wtext[cursorPos-1] ) )
{
cursorPos--;
}
@@ -793,7 +871,7 @@ S32 LLLineEditor::prevWordPos(S32 cursorPos) const
S32 LLLineEditor::nextWordPos(S32 cursorPos) const
{
const LLWString& wtext = mText.getWString();
- while( (cursorPos < getLength()) && LLTextEditor::isPartOfWord( wtext[cursorPos] ) )
+ while( (cursorPos < getLength()) && LLWStringUtil::isPartOfWord( wtext[cursorPos] ) )
{
cursorPos++;
}
@@ -936,7 +1014,7 @@ void LLLineEditor::cut()
else
if( mKeystrokeCallback )
{
- mKeystrokeCallback( this, mCallbackUserData );
+ mKeystrokeCallback( this );
}
}
}
@@ -1057,7 +1135,7 @@ void LLLineEditor::pasteHelper(bool is_primary)
else
if( mKeystrokeCallback )
{
- mKeystrokeCallback( this, mCallbackUserData );
+ mKeystrokeCallback( this );
}
}
}
@@ -1203,9 +1281,9 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask)
case KEY_UP:
if( mHaveHistory && ( MASK_CONTROL == mask ) )
{
- if( mCurrentHistoryLine > 0 )
+ if( mCurrentHistoryLine > mLineHistory.begin() )
{
- mText.assign( mLineHistory[ --mCurrentHistoryLine ] );
+ mText.assign( *(--mCurrentHistoryLine) );
setCursor(llmin((S32)mText.length(), getCursor()));
}
else
@@ -1220,9 +1298,9 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask)
case KEY_DOWN:
if( mHaveHistory && ( MASK_CONTROL == mask ) )
{
- if( !mLineHistory.empty() && mCurrentHistoryLine < mLineHistory.size() - 1 )
+ if( !mLineHistory.empty() && mCurrentHistoryLine < mLineHistory.end() - 1 )
{
- mText.assign( mLineHistory[ ++mCurrentHistoryLine ] );
+ mText.assign( *(++mCurrentHistoryLine) );
setCursor(llmin((S32)mText.length(), getCursor()));
}
else
@@ -1370,7 +1448,7 @@ BOOL LLLineEditor::handleKeyHere(KEY key, MASK mask )
{
if (mKeystrokeCallback)
{
- mKeystrokeCallback(this, mCallbackUserData);
+ mKeystrokeCallback(this);
}
}
}
@@ -1420,7 +1498,7 @@ BOOL LLLineEditor::handleUnicodeCharHere(llwchar uni_char)
{
// HACK! The only usage of this callback doesn't do anything with the character.
// We'll have to do something about this if something ever changes! - Doug
- mKeystrokeCallback( this, mCallbackUserData );
+ mKeystrokeCallback( this );
}
}
}
@@ -1461,16 +1539,58 @@ void LLLineEditor::doDelete()
{
if( mKeystrokeCallback )
{
- mKeystrokeCallback( this, mCallbackUserData );
+ mKeystrokeCallback( this );
}
}
}
}
+void LLLineEditor::drawBackground()
+{
+ bool has_focus = hasFocus();
+ LLUIImage* image;
+ if ( mReadOnly )
+ {
+ image = mBgImageDisabled;
+ }
+ else if ( has_focus )
+ {
+ image = mBgImageFocused;
+ }
+ else
+ {
+ image = mBgImage;
+ }
+
+ F32 alpha = getDrawContext().mAlpha;
+ // optionally draw programmatic border
+ if (has_focus)
+ {
+ LLColor4 tmp_color = gFocusMgr.getFocusColor();
+ tmp_color.setAlpha(alpha);
+ image->drawBorder(0, 0, getRect().getWidth(), getRect().getHeight(),
+ tmp_color,
+ gFocusMgr.getFocusFlashWidth());
+ }
+ LLColor4 tmp_color = UI_VERTEX_COLOR;
+ tmp_color.setAlpha(alpha);
+ image->draw(getLocalRect(), tmp_color);
+}
+
void LLLineEditor::draw()
{
+ F32 alpha = getDrawContext().mAlpha;
S32 text_len = mText.length();
+ static LLUICachedControl<S32> lineeditor_cursor_thickness ("UILineEditorCursorThickness", 0);
+ static LLUICachedControl<F32> preedit_marker_brightness ("UIPreeditMarkerBrightness", 0);
+ static LLUICachedControl<S32> preedit_marker_gap ("UIPreeditMarkerGap", 0);
+ static LLUICachedControl<S32> preedit_marker_position ("UIPreeditMarkerPosition", 0);
+ static LLUICachedControl<S32> preedit_marker_thickness ("UIPreeditMarkerThickness", 0);
+ static LLUICachedControl<F32> preedit_standout_brightness ("UIPreeditStandoutBrightness", 0);
+ static LLUICachedControl<S32> preedit_standout_gap ("UIPreeditStandoutGap", 0);
+ static LLUICachedControl<S32> preedit_standout_position ("UIPreeditStandoutPosition", 0);
+ static LLUICachedControl<S32> preedit_standout_thickness ("UIPreeditStandoutThickness", 0);
std::string saved_text;
if (mDrawAsterixes)
@@ -1488,37 +1608,14 @@ void LLLineEditor::draw()
LLRect background( 0, getRect().getHeight(), getRect().getWidth(), 0 );
background.stretch( -mBorderThickness );
- LLColor4 bg_color = mReadOnlyBgColor;
-
-#if 0 // for when we're ready for image art.
- if( hasFocus())
- {
- mImage->drawBorder(0, 0, getRect().getWidth(), getRect().getHeight(), gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());
- }
- mImage->draw(getLocalRect(), mReadOnly ? mReadOnlyBgColor : mWriteableBgColor );
-#else // the old programmer art.
- // drawing solids requires texturing be disabled
- {
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- // draw background for text
- if( !mReadOnly )
- {
- if( gFocusMgr.getKeyboardFocus() == this )
- {
- bg_color = mFocusBgColor;
- }
- else
- {
- bg_color = mWriteableBgColor;
- }
- }
- gl_rect_2d(background, bg_color);
- }
-#endif
+ S32 lineeditor_v_pad = llround((background.getHeight() - mGLFont->getLineHeight())/2);
+ drawBackground();
+
// draw text
- S32 cursor_bottom = background.mBottom + 1;
+ // With viewer-2 art files, input region is 2 pixels up
+ S32 cursor_bottom = background.mBottom + 2;
S32 cursor_top = background.mTop - 1;
LLColor4 text_color;
@@ -1526,19 +1623,21 @@ void LLLineEditor::draw()
{
if (!getTentative())
{
- text_color = mFgColor;
+ text_color = mFgColor.get();
}
else
{
- text_color = mTentativeFgColor;
+ text_color = mTentativeFgColor.get();
}
}
else
{
- text_color = mReadOnlyFgColor;
+ text_color = mReadOnlyFgColor.get();
}
- LLColor4 label_color = mTentativeFgColor;
-
+ text_color.setAlpha(alpha);
+ LLColor4 label_color = mTentativeFgColor.get();
+ label_color.setAlpha(alpha);
+
if (hasPreeditString())
{
// Draw preedit markers. This needs to be before drawing letters.
@@ -1556,27 +1655,29 @@ void LLLineEditor::draw()
}
if (mPreeditStandouts[i])
{
- gl_rect_2d(preedit_pixels_left + PREEDIT_STANDOUT_GAP,
- background.mBottom + PREEDIT_STANDOUT_POSITION,
- preedit_pixels_right - PREEDIT_STANDOUT_GAP - 1,
- background.mBottom + PREEDIT_STANDOUT_POSITION - PREEDIT_STANDOUT_THICKNESS,
- (text_color * PREEDIT_STANDOUT_BRIGHTNESS + bg_color * (1 - PREEDIT_STANDOUT_BRIGHTNESS)).setAlpha(1.0f));
+ gl_rect_2d(preedit_pixels_left + preedit_standout_gap,
+ background.mBottom + preedit_standout_position,
+ preedit_pixels_right - preedit_standout_gap - 1,
+ background.mBottom + preedit_standout_position - preedit_standout_thickness,
+ (text_color * preedit_standout_brightness
+ + mPreeditBgColor * (1 - preedit_standout_brightness)).setAlpha(alpha/*1.0f*/));
}
else
{
- gl_rect_2d(preedit_pixels_left + PREEDIT_MARKER_GAP,
- background.mBottom + PREEDIT_MARKER_POSITION,
- preedit_pixels_right - PREEDIT_MARKER_GAP - 1,
- background.mBottom + PREEDIT_MARKER_POSITION - PREEDIT_MARKER_THICKNESS,
- (text_color * PREEDIT_MARKER_BRIGHTNESS + bg_color * (1 - PREEDIT_MARKER_BRIGHTNESS)).setAlpha(1.0f));
+ gl_rect_2d(preedit_pixels_left + preedit_marker_gap,
+ background.mBottom + preedit_marker_position,
+ preedit_pixels_right - preedit_marker_gap - 1,
+ background.mBottom + preedit_marker_position - preedit_marker_thickness,
+ (text_color * preedit_marker_brightness
+ + mPreeditBgColor * (1 - preedit_marker_brightness)).setAlpha(alpha/*1.0f*/));
}
}
}
}
S32 rendered_text = 0;
- F32 rendered_pixels_right = (F32)mMinHPixels;
- F32 text_bottom = (F32)background.mBottom + (F32)UI_LINEEDITOR_V_PAD;
+ F32 rendered_pixels_right = (F32)mTextLeftEdge;
+ F32 text_bottom = (F32)background.mBottom + (F32)lineeditor_v_pad;
if( (gFocusMgr.getKeyboardFocus() == this) && hasSelection() )
{
@@ -1601,32 +1702,36 @@ void LLLineEditor::draw()
rendered_pixels_right, text_bottom,
text_color,
LLFontGL::LEFT, LLFontGL::BOTTOM,
- LLFontGL::NORMAL,
+ 0,
+ LLFontGL::NO_SHADOW,
select_left - mScrollHPos,
- mMaxHPixels - llround(rendered_pixels_right),
+ mTextRightEdge - llround(rendered_pixels_right),
&rendered_pixels_right);
}
- if( (rendered_pixels_right < (F32)mMaxHPixels) && (rendered_text < text_len) )
+ if( (rendered_pixels_right < (F32)mTextRightEdge) && (rendered_text < text_len) )
{
- LLColor4 color(1.f - bg_color.mV[0], 1.f - bg_color.mV[1], 1.f - bg_color.mV[2], 1.f);
+ LLColor4 color = mHighlightColor;
+ color.setAlpha(alpha);
// selected middle
S32 width = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos + rendered_text, select_right - mScrollHPos - rendered_text);
- width = llmin(width, mMaxHPixels - llround(rendered_pixels_right));
+ width = llmin(width, mTextRightEdge - llround(rendered_pixels_right));
gl_rect_2d(llround(rendered_pixels_right), cursor_top, llround(rendered_pixels_right)+width, cursor_bottom, color);
+ LLColor4 tmp_color( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha );
rendered_text += mGLFont->render(
mText, mScrollHPos + rendered_text,
rendered_pixels_right, text_bottom,
- LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ),
+ tmp_color,
LLFontGL::LEFT, LLFontGL::BOTTOM,
- LLFontGL::NORMAL,
+ 0,
+ LLFontGL::NO_SHADOW,
select_right - mScrollHPos - rendered_text,
- mMaxHPixels - llround(rendered_pixels_right),
+ mTextRightEdge - llround(rendered_pixels_right),
&rendered_pixels_right);
}
- if( (rendered_pixels_right < (F32)mMaxHPixels) && (rendered_text < text_len) )
+ if( (rendered_pixels_right < (F32)mTextRightEdge) && (rendered_text < text_len) )
{
// unselected, right side
mGLFont->render(
@@ -1634,9 +1739,10 @@ void LLLineEditor::draw()
rendered_pixels_right, text_bottom,
text_color,
LLFontGL::LEFT, LLFontGL::BOTTOM,
- LLFontGL::NORMAL,
+ 0,
+ LLFontGL::NO_SHADOW,
S32_MAX,
- mMaxHPixels - llround(rendered_pixels_right),
+ mTextRightEdge - llround(rendered_pixels_right),
&rendered_pixels_right);
}
}
@@ -1647,28 +1753,29 @@ void LLLineEditor::draw()
rendered_pixels_right, text_bottom,
text_color,
LLFontGL::LEFT, LLFontGL::BOTTOM,
- LLFontGL::NORMAL,
+ 0,
+ LLFontGL::NO_SHADOW,
S32_MAX,
- mMaxHPixels - llround(rendered_pixels_right),
+ mTextRightEdge - llround(rendered_pixels_right),
&rendered_pixels_right);
}
-#if 0 // for when we're ready for image art.
+#if 1 // for when we're ready for image art.
mBorder->setVisible(FALSE); // no more programmatic art.
#endif
// If we're editing...
- if( gFocusMgr.getKeyboardFocus() == this)
+ if( hasFocus())
{
//mBorder->setVisible(TRUE); // ok, programmer art just this once.
// (Flash the cursor every half second)
- if (gShowTextEditCursor && !mReadOnly)
+ if (!mReadOnly && gFocusMgr.getAppHasFocus())
{
F32 elapsed = mKeystrokeTimer.getElapsedTimeF32();
if( (elapsed < CURSOR_FLASH_DELAY ) || (S32(elapsed * 2) & 1) )
{
S32 cursor_left = findPixelNearestPos();
- cursor_left -= UI_LINEEDITOR_CURSOR_THICKNESS / 2;
- S32 cursor_right = cursor_left + UI_LINEEDITOR_CURSOR_THICKNESS;
+ cursor_left -= lineeditor_cursor_thickness / 2;
+ S32 cursor_right = cursor_left + lineeditor_cursor_thickness;
if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection())
{
const LLWString space(utf8str_to_wstring(std::string(" ")));
@@ -1681,17 +1788,19 @@ void LLLineEditor::draw()
cursor_right, cursor_bottom, text_color);
if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection())
{
- mGLFont->render(mText, getCursor(), (F32)(cursor_left + UI_LINEEDITOR_CURSOR_THICKNESS / 2), text_bottom,
- LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ),
+ LLColor4 tmp_color( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha );
+ mGLFont->render(mText, getCursor(), (F32)(cursor_left + lineeditor_cursor_thickness / 2), text_bottom,
+ tmp_color,
LLFontGL::LEFT, LLFontGL::BOTTOM,
- LLFontGL::NORMAL,
+ 0,
+ LLFontGL::NO_SHADOW,
1);
}
// Make sure the IME is in the right place
S32 pixels_after_scroll = findPixelNearestPos(); // RCalculcate for IME position
- LLRect screen_pos = getScreenRect();
- LLCoordGL ime_pos( screen_pos.mLeft + pixels_after_scroll, screen_pos.mTop - UI_LINEEDITOR_V_PAD );
+ LLRect screen_pos = calcScreenRect();
+ LLCoordGL ime_pos( screen_pos.mLeft + pixels_after_scroll, screen_pos.mTop - lineeditor_v_pad );
ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]);
ime_pos.mY = (S32) (ime_pos.mY * LLUI::sGLScaleFactor.mV[VY]);
@@ -1705,13 +1814,14 @@ void LLLineEditor::draw()
if (0 == mText.length() && mReadOnly)
{
mGLFont->render(mLabel.getWString(), 0,
- mMinHPixels, (F32)text_bottom,
+ mTextLeftEdge, (F32)text_bottom,
label_color,
LLFontGL::LEFT,
LLFontGL::BOTTOM,
- LLFontGL::NORMAL,
+ 0,
+ LLFontGL::NO_SHADOW,
S32_MAX,
- mMaxHPixels - llround(rendered_pixels_right),
+ mTextRightEdge - llround(rendered_pixels_right),
&rendered_pixels_right, FALSE);
}
@@ -1729,13 +1839,14 @@ void LLLineEditor::draw()
if (0 == mText.length())
{
mGLFont->render(mLabel.getWString(), 0,
- mMinHPixels, (F32)text_bottom,
+ mTextLeftEdge, (F32)text_bottom,
label_color,
LLFontGL::LEFT,
LLFontGL::BOTTOM,
- LLFontGL::NORMAL,
+ 0,
+ LLFontGL::NO_SHADOW,
S32_MAX,
- mMaxHPixels - llround(rendered_pixels_right),
+ mTextRightEdge - llround(rendered_pixels_right),
&rendered_pixels_right, FALSE);
}
// Draw children (border)
@@ -1753,7 +1864,7 @@ void LLLineEditor::draw()
S32 LLLineEditor::findPixelNearestPos(const S32 cursor_offset) const
{
S32 dpos = getCursor() - mScrollHPos + cursor_offset;
- S32 result = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos, dpos) + mMinHPixels;
+ S32 result = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos, dpos) + mTextLeftEdge;
return result;
}
@@ -1849,7 +1960,7 @@ void LLLineEditor::setRect(const LLRect& rect)
}
}
-void LLLineEditor::setPrevalidate(BOOL (*func)(const LLWString &))
+void LLLineEditor::setPrevalidate(LLLinePrevalidateFunc func)
{
mPrevalidateFunc = func;
updateAllowingLanguageInput();
@@ -2095,20 +2206,28 @@ BOOL LLLineEditor::prevalidateAlphaNumSpace(const LLWString &str)
return rv;
}
+// Used for most names of things stored on the server, due to old file-formats
+// that used the pipe (|) for multiline text storage. Examples include
+// inventory item names, parcel names, object names, etc.
// static
-BOOL LLLineEditor::prevalidatePrintableNotPipe(const LLWString &str)
+BOOL LLLineEditor::prevalidateASCIIPrintableNoPipe(const LLWString &str)
{
BOOL rv = TRUE;
S32 len = str.length();
if(len == 0) return rv;
while(len--)
{
- if('|' == str[len])
+ llwchar wc = str[len];
+ if (wc < 0x20
+ || wc > 0x7f
+ || wc == '|')
{
rv = FALSE;
break;
}
- if(!((' ' == str[len]) || LLStringOps::isAlnum((char)str[len]) || LLStringOps::isPunct((char)str[len])))
+ if(!(wc == ' '
+ || LLStringOps::isAlnum((char)wc)
+ || LLStringOps::isPunct((char)wc) ) )
{
rv = FALSE;
break;
@@ -2118,15 +2237,19 @@ BOOL LLLineEditor::prevalidatePrintableNotPipe(const LLWString &str)
}
+// Used for avatar names
// static
-BOOL LLLineEditor::prevalidatePrintableNoSpace(const LLWString &str)
+BOOL LLLineEditor::prevalidateASCIIPrintableNoSpace(const LLWString &str)
{
BOOL rv = TRUE;
S32 len = str.length();
if(len == 0) return rv;
while(len--)
{
- if(LLStringOps::isSpace(str[len]))
+ llwchar wc = str[len];
+ if (wc < 0x20
+ || wc > 0x7f
+ || LLStringOps::isSpace(wc))
{
rv = FALSE;
break;
@@ -2141,6 +2264,7 @@ BOOL LLLineEditor::prevalidatePrintableNoSpace(const LLWString &str)
return rv;
}
+
// static
BOOL LLLineEditor::prevalidateASCII(const LLWString &str)
{
@@ -2169,244 +2293,11 @@ void LLLineEditor::setSelectAllonFocusReceived(BOOL b)
}
-void LLLineEditor::setKeystrokeCallback(void (*keystroke_callback)(LLLineEditor* caller, void* user_data))
-{
- mKeystrokeCallback = keystroke_callback;
-}
-
-// virtual
-LLXMLNodePtr LLLineEditor::getXML(bool save_children) const
+void LLLineEditor::setKeystrokeCallback(callback_t callback, void* user_data)
{
- LLXMLNodePtr node = LLUICtrl::getXML();
-
- node->createChild("max_length", TRUE)->setIntValue(mMaxLengthBytes);
-
- node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mGLFont));
-
- if (mBorder)
- {
- std::string bevel;
- switch(mBorder->getBevel())
- {
- default:
- case LLViewBorder::BEVEL_NONE: bevel = "none"; break;
- case LLViewBorder::BEVEL_IN: bevel = "in"; break;
- case LLViewBorder::BEVEL_OUT: bevel = "out"; break;
- case LLViewBorder::BEVEL_BRIGHT:bevel = "bright"; break;
- }
- node->createChild("bevel_style", TRUE)->setStringValue(bevel);
-
- std::string style;
- switch(mBorder->getStyle())
- {
- default:
- case LLViewBorder::STYLE_LINE: style = "line"; break;
- case LLViewBorder::STYLE_TEXTURE: style = "texture"; break;
- }
- node->createChild("border_style", TRUE)->setStringValue(style);
-
- node->createChild("border_thickness", TRUE)->setIntValue(mBorder->getBorderWidth());
- }
-
- if (!mLabel.empty())
- {
- node->createChild("label", TRUE)->setStringValue(mLabel.getString());
- }
-
- node->createChild("select_all_on_focus_received", TRUE)->setBoolValue(mSelectAllonFocusReceived);
-
- node->createChild("handle_edit_keys_directly", TRUE)->setBoolValue(mHandleEditKeysDirectly );
-
- addColorXML(node, mCursorColor, "cursor_color", "TextCursorColor");
- addColorXML(node, mFgColor, "text_color", "TextFgColor");
- addColorXML(node, mReadOnlyFgColor, "text_readonly_color", "TextFgReadOnlyColor");
- addColorXML(node, mTentativeFgColor, "text_tentative_color", "TextFgTentativeColor");
- addColorXML(node, mReadOnlyBgColor, "bg_readonly_color", "TextBgReadOnlyColor");
- addColorXML(node, mWriteableBgColor, "bg_writeable_color", "TextBgWriteableColor");
- addColorXML(node, mFocusBgColor, "bg_focus_color", "TextBgFocusColor");
-
- node->createChild("select_on_focus", TRUE)->setBoolValue(mSelectAllonFocusReceived );
-
- return node;
+ mKeystrokeCallback = boost::bind(callback, _1, user_data);
}
-// static
-LLView* LLLineEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("line_editor");
- node->getAttributeString("name", name);
-
- LLRect rect;
- createRect(node, rect, parent, LLRect());
-
- S32 max_text_length = 128;
- node->getAttributeS32("max_length", max_text_length);
-
- LLFontGL* font = LLView::selectFont(node);
-
- std::string text = node->getTextContents().substr(0, max_text_length - 1);
-
- LLViewBorder::EBevel bevel_style = LLViewBorder::BEVEL_IN;
- LLViewBorder::getBevelFromAttribute(node, bevel_style);
-
- LLViewBorder::EStyle border_style = LLViewBorder::STYLE_LINE;
- std::string border_string;
- node->getAttributeString("border_style", border_string);
- LLStringUtil::toLower(border_string);
-
- if (border_string == "texture")
- {
- border_style = LLViewBorder::STYLE_TEXTURE;
- }
-
- S32 border_thickness = 1;
- node->getAttributeS32("border_thickness", border_thickness);
-
- LLUICtrlCallback commit_callback = NULL;
-
- LLLineEditor* line_editor = new LLLineEditor(name,
- rect,
- text,
- font,
- max_text_length,
- commit_callback,
- NULL,
- NULL,
- NULL,
- NULL,
- bevel_style,
- border_style,
- border_thickness);
-
- std::string label;
- if(node->getAttributeString("label", label))
- {
- line_editor->setLabel(label);
- }
- BOOL select_all_on_focus_received = FALSE;
- if (node->getAttributeBOOL("select_all_on_focus_received", select_all_on_focus_received))
- {
- line_editor->setSelectAllonFocusReceived(select_all_on_focus_received);
- }
- BOOL handle_edit_keys_directly = FALSE;
- if (node->getAttributeBOOL("handle_edit_keys_directly", handle_edit_keys_directly))
- {
- line_editor->setHandleEditKeysDirectly(handle_edit_keys_directly);
- }
- BOOL commit_on_focus_lost = TRUE;
- if (node->getAttributeBOOL("commit_on_focus_lost", commit_on_focus_lost))
- {
- line_editor->setCommitOnFocusLost(commit_on_focus_lost);
- }
-
- line_editor->setColorParameters(node);
-
- if(node->hasAttribute("select_on_focus"))
- {
- BOOL selectall = FALSE;
- node->getAttributeBOOL("select_on_focus", selectall);
- line_editor->setSelectAllonFocusReceived(selectall);
- }
-
- std::string prevalidate;
- if(node->getAttributeString("prevalidate", prevalidate))
- {
- LLStringUtil::toLower(prevalidate);
-
- if ("ascii" == prevalidate)
- {
- line_editor->setPrevalidate( LLLineEditor::prevalidateASCII );
- }
- else if ("float" == prevalidate)
- {
- line_editor->setPrevalidate( LLLineEditor::prevalidateFloat );
- }
- else if ("int" == prevalidate)
- {
- line_editor->setPrevalidate( LLLineEditor::prevalidateInt );
- }
- else if ("positive_s32" == prevalidate)
- {
- line_editor->setPrevalidate( LLLineEditor::prevalidatePositiveS32 );
- }
- else if ("non_negative_s32" == prevalidate)
- {
- line_editor->setPrevalidate( LLLineEditor::prevalidateNonNegativeS32 );
- }
- else if ("alpha_num" == prevalidate)
- {
- line_editor->setPrevalidate( LLLineEditor::prevalidateAlphaNum );
- }
- else if ("alpha_num_space" == prevalidate)
- {
- line_editor->setPrevalidate( LLLineEditor::prevalidateAlphaNumSpace );
- }
- else if ("printable_not_pipe" == prevalidate)
- {
- line_editor->setPrevalidate( LLLineEditor::prevalidatePrintableNotPipe );
- }
- else if ("printable_no_space" == prevalidate)
- {
- line_editor->setPrevalidate( LLLineEditor::prevalidatePrintableNoSpace );
- }
- }
-
- line_editor->initFromXML(node, parent);
-
- return line_editor;
-}
-
-//static
-void LLLineEditor::cleanupLineEditor()
-{
- sImage = NULL;
-}
-
-/* static */
-LLPointer<LLUIImage> LLLineEditor::parseImage(std::string name, LLXMLNodePtr from, LLPointer<LLUIImage> def)
-{
- std::string xml_name;
- if (from->hasAttribute(name.c_str())) from->getAttributeString(name.c_str(), xml_name);
- if (xml_name == LLStringUtil::null) return def;
- LLPointer<LLUIImage> image = LLUI::getUIImage(xml_name);
- return image.isNull() ? def : image;
-}
-
-void LLLineEditor::setColorParameters(LLXMLNodePtr node)
-{
- // overrides default image if supplied.
- mImage = parseImage(std::string("image"), node, mImage);
-
- LLColor4 color;
- if (LLUICtrlFactory::getAttributeColor(node,"cursor_color", color))
- {
- setCursorColor(color);
- }
- if(node->hasAttribute("text_color"))
- {
- LLUICtrlFactory::getAttributeColor(node,"text_color", color);
- setFgColor(color);
- }
- if(node->hasAttribute("text_readonly_color"))
- {
- LLUICtrlFactory::getAttributeColor(node,"text_readonly_color", color);
- setReadOnlyFgColor(color);
- }
- if (LLUICtrlFactory::getAttributeColor(node,"text_tentative_color", color))
- {
- setTentativeFgColor(color);
- }
- if(node->hasAttribute("bg_readonly_color"))
- {
- LLUICtrlFactory::getAttributeColor(node,"bg_readonly_color", color);
- setReadOnlyBgColor(color);
- }
- if(node->hasAttribute("bg_writeable_color"))
- {
- LLUICtrlFactory::getAttributeColor(node,"bg_writeable_color", color);
- setWriteableBgColor(color);
- }
-}
BOOL LLLineEditor::setTextArg( const std::string& key, const LLStringExplicit& text )
{
@@ -2429,13 +2320,19 @@ void LLLineEditor::updateAllowingLanguageInput()
// fine on 1.15.0.2, since all prevalidate func reject any
// non-ASCII characters. I'm not sure on future versions,
// however...
+ LLWindow* window = getWindow();
+ if (!window)
+ {
+ // test app, no window available
+ return;
+ }
if (hasFocus() && !mReadOnly && !mDrawAsterixes && mPrevalidateFunc == NULL)
{
- getWindow()->allowLanguageTextInput(this, TRUE);
+ window->allowLanguageTextInput(this, TRUE);
}
else
{
- getWindow()->allowLanguageTextInput(this, FALSE);
+ window->allowLanguageTextInput(this, FALSE);
}
}
@@ -2446,14 +2343,20 @@ BOOL LLLineEditor::hasPreeditString() const
void LLLineEditor::resetPreedit()
{
- if (hasPreeditString())
+ if (hasSelection())
{
- if (hasSelection())
+ if (hasPreeditString())
{
llwarns << "Preedit and selection!" << llendl;
deselect();
}
-
+ else
+ {
+ deleteSelection();
+ }
+ }
+ if (hasPreeditString())
+ {
const S32 preedit_pos = mPreeditPositions.front();
mText.erase(preedit_pos, mPreeditPositions.back() - preedit_pos);
mText.insert(preedit_pos, mPreeditOverwrittenWString);
@@ -2513,7 +2416,7 @@ void LLLineEditor::updatePreedit(const LLWString &preedit_string,
mKeystrokeTimer.reset();
if( mKeystrokeCallback )
{
- mKeystrokeCallback( this, mCallbackUserData );
+ mKeystrokeCallback( this );
}
}
@@ -2655,147 +2558,3 @@ LLWString LLLineEditor::getConvertedText() const
}
return text;
}
-
-static LLRegisterWidget<LLSearchEditor> r2("search_editor");
-
-
-LLSearchEditor::LLSearchEditor(const std::string& name,
- const LLRect& rect,
- S32 max_length_bytes,
- void (*search_callback)(const std::string& search_string, void* user_data),
- void* userdata)
- :
- LLUICtrl(name, rect, TRUE, NULL, userdata),
- mSearchCallback(search_callback)
-{
- LLRect search_edit_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
- mSearchEdit = new LLLineEditor(std::string("search edit"),
- search_edit_rect,
- LLStringUtil::null,
- NULL,
- max_length_bytes,
- NULL,
- onSearchEdit,
- NULL,
- this);
-
- mSearchEdit->setFollowsAll();
- mSearchEdit->setSelectAllonFocusReceived(TRUE);
-
- addChild(mSearchEdit);
-
- S32 btn_width = rect.getHeight(); // button is square, and as tall as search editor
- LLRect clear_btn_rect(rect.getWidth() - btn_width, rect.getHeight(), rect.getWidth(), 0);
- mClearSearchButton = new LLButton(std::string("clear search"),
- clear_btn_rect,
- std::string("icn_clear_lineeditor.tga"),
- std::string("UIImgBtnCloseInactiveUUID"),
- LLStringUtil::null,
- onClearSearch,
- this,
- NULL,
- LLStringUtil::null);
- mClearSearchButton->setFollowsRight();
- mClearSearchButton->setFollowsTop();
- mClearSearchButton->setImageColor(LLUI::sColorsGroup->getColor("TextFgTentativeColor"));
- mClearSearchButton->setTabStop(FALSE);
- mSearchEdit->addChild(mClearSearchButton);
-
- mSearchEdit->setTextPadding(0, btn_width);
-}
-
-
-//virtual
-void LLSearchEditor::setValue(const LLSD& value )
-{
- mSearchEdit->setValue(value);
-}
-
-//virtual
-LLSD LLSearchEditor::getValue() const
-{
- return mSearchEdit->getValue();
-}
-
-//virtual
-BOOL LLSearchEditor::setTextArg( const std::string& key, const LLStringExplicit& text )
-{
- return mSearchEdit->setTextArg(key, text);
-}
-
-//virtual
-BOOL LLSearchEditor::setLabelArg( const std::string& key, const LLStringExplicit& text )
-{
- return mSearchEdit->setLabelArg(key, text);
-}
-
-//virtual
-void LLSearchEditor::clear()
-{
- if (mSearchEdit)
- {
- mSearchEdit->clear();
- }
-}
-
-void LLSearchEditor::draw()
-{
- mClearSearchButton->setVisible(!mSearchEdit->getWText().empty());
-
- LLUICtrl::draw();
-}
-
-
-//static
-void LLSearchEditor::onSearchEdit(LLLineEditor* caller, void* user_data )
-{
- LLSearchEditor* search_editor = (LLSearchEditor*)user_data;
- if (search_editor->mSearchCallback)
- {
- search_editor->mSearchCallback(caller->getText(), search_editor->mCallbackUserData);
- }
-}
-
-//static
-void LLSearchEditor::onClearSearch(void* user_data)
-{
- LLSearchEditor* search_editor = (LLSearchEditor*)user_data;
-
- search_editor->setText(LLStringUtil::null);
- if (search_editor->mSearchCallback)
- {
- search_editor->mSearchCallback(LLStringUtil::null, search_editor->mCallbackUserData);
- }
-}
-
-// static
-LLView* LLSearchEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("search_editor");
- node->getAttributeString("name", name);
-
- LLRect rect;
- createRect(node, rect, parent, LLRect());
-
- S32 max_text_length = 128;
- node->getAttributeS32("max_length", max_text_length);
-
- std::string text = node->getValue().substr(0, max_text_length - 1);
-
- LLSearchEditor* search_editor = new LLSearchEditor(name,
- rect,
- max_text_length,
- NULL, NULL);
-
- std::string label;
- if(node->getAttributeString("label", label))
- {
- search_editor->mSearchEdit->setLabel(label);
- }
-
- search_editor->setText(text);
-
- search_editor->initFromXML(node, parent);
-
- return search_editor;
-}
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index fc5fcc5b90..49e9539b16 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -51,39 +51,70 @@
#include "llviewborder.h"
#include "llpreeditor.h"
+#include <boost/function.hpp>
class LLFontGL;
class LLLineEditorRollback;
class LLButton;
-typedef BOOL (*LLLinePrevalidateFunc)(const LLWString &wstr);
-
+typedef boost::function<BOOL (const LLWString &wstr)> LLLinePrevalidateFunc;
class LLLineEditor
: public LLUICtrl, public LLEditMenuHandler, protected LLPreeditor
{
-
public:
- LLLineEditor(const std::string& name,
- const LLRect& rect,
- const std::string& default_text = LLStringUtil::null,
- const LLFontGL* glfont = NULL,
- S32 max_length_bytes = 254,
- void (*commit_callback)(LLUICtrl* caller, void* user_data) = NULL,
- void (*keystroke_callback)(LLLineEditor* caller, void* user_data) = NULL,
- void (*focus_lost_callback)(LLFocusableElement* caller, void* user_data) = NULL,
- void* userdata = NULL,
- LLLinePrevalidateFunc prevalidate_func = NULL,
- LLViewBorder::EBevel border_bevel = LLViewBorder::BEVEL_IN,
- LLViewBorder::EStyle border_style = LLViewBorder::STYLE_LINE,
- S32 border_thickness = 1);
- virtual ~LLLineEditor();
+ struct PrevalidateNamedFuncs
+ : public LLInitParam::TypeValuesHelper<LLLinePrevalidateFunc, PrevalidateNamedFuncs>
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- void setColorParameters(LLXMLNodePtr node);
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
- static void cleanupLineEditor();
+ {
+ static void declareValues();
+ };
+
+ typedef boost::function<void (LLLineEditor* caller)> keystroke_callback_t;
+
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<std::string> default_text;
+ Optional<S32> max_length_bytes;
+
+ Optional<keystroke_callback_t> keystroke_callback;
+
+ Optional<LLLinePrevalidateFunc, PrevalidateNamedFuncs> prevalidate_callback;
+
+ Optional<LLViewBorder::Params> border;
+
+ Optional<LLUIImage*> background_image,
+ background_image_disabled,
+ background_image_focused;
+
+ Optional<bool> select_on_focus,
+ handle_edit_keys_directly,
+ revert_on_esc,
+ commit_on_focus_lost,
+ ignore_tab;
+
+ // colors
+ Optional<LLUIColor> cursor_color,
+ text_color,
+ text_readonly_color,
+ text_tentative_color,
+ highlight_color,
+ preedit_bg_color;
+
+ Optional<S32> text_pad_left,
+ text_pad_right;
+
+ Ignored bg_visible;
+
+ Params();
+ };
+protected:
+ LLLineEditor(const Params&);
+ friend class LLUICtrlFactory;
+ friend class LLFloaterEditUI;
+public:
+ virtual ~LLLineEditor();
// mousehandler overrides
/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
@@ -131,20 +162,22 @@ public:
virtual void setRect(const LLRect& rect);
virtual BOOL acceptsTextInput() const;
virtual void onCommit();
- virtual BOOL isDirty() const { return mText.getString() != mPrevText; } // Returns TRUE if user changed value at all
- virtual void resetDirty() { mPrevText = mText.getString(); } // Clear dirty state
+ virtual BOOL isDirty() const; // Returns TRUE if user changed value at all
+ virtual void resetDirty(); // Clear dirty state
// assumes UTF8 text
- virtual void setValue(const LLSD& value ) { setText(value.asString()); }
- virtual LLSD getValue() const { return LLSD(getText()); }
+ virtual void setValue(const LLSD& value );
+ virtual LLSD getValue() const;
virtual BOOL setTextArg( const std::string& key, const LLStringExplicit& text );
virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
void setLabel(const LLStringExplicit &new_label) { mLabel = new_label; }
+ const std::string& getLabel() { return mLabel.getString(); }
+
void setText(const LLStringExplicit &new_text);
const std::string& getText() const { return mText.getString(); }
- const LLWString& getWText() const { return mText.getWString(); }
+ LLWString getWText() const { return mText.getWString(); }
LLWString getConvertedText() const; // trimmed text with paragraphs converted to newlines
S32 getLength() const { return mText.length(); }
@@ -155,26 +188,21 @@ public:
// Selects characters 'start' to 'end'.
void setSelection(S32 start, S32 end);
+ virtual void getSelectionRange(S32 *position, S32 *length) const;
void setCommitOnFocusLost( BOOL b ) { mCommitOnFocusLost = b; }
void setRevertOnEsc( BOOL b ) { mRevertOnEsc = b; }
void setCursorColor(const LLColor4& c) { mCursorColor = c; }
- const LLColor4& getCursorColor() const { return mCursorColor; }
+ const LLColor4& getCursorColor() const { return mCursorColor.get(); }
void setFgColor( const LLColor4& c ) { mFgColor = c; }
void setReadOnlyFgColor( const LLColor4& c ) { mReadOnlyFgColor = c; }
void setTentativeFgColor(const LLColor4& c) { mTentativeFgColor = c; }
- void setWriteableBgColor( const LLColor4& c ) { mWriteableBgColor = c; }
- void setReadOnlyBgColor( const LLColor4& c ) { mReadOnlyBgColor = c; }
- void setFocusBgColor(const LLColor4& c) { mFocusBgColor = c; }
- const LLColor4& getFgColor() const { return mFgColor; }
- const LLColor4& getReadOnlyFgColor() const { return mReadOnlyFgColor; }
- const LLColor4& getTentativeFgColor() const { return mTentativeFgColor; }
- const LLColor4& getWriteableBgColor() const { return mWriteableBgColor; }
- const LLColor4& getReadOnlyBgColor() const { return mReadOnlyBgColor; }
- const LLColor4& getFocusBgColor() const { return mFocusBgColor; }
+ const LLColor4& getFgColor() const { return mFgColor.get(); }
+ const LLColor4& getReadOnlyFgColor() const { return mReadOnlyFgColor.get(); }
+ const LLColor4& getTentativeFgColor() const { return mTentativeFgColor.get(); }
void setIgnoreArrowKeys(BOOL b) { mIgnoreArrowKeys = b; }
void setIgnoreTab(BOOL b) { mIgnoreTab = b; }
@@ -193,22 +221,25 @@ public:
void setHandleEditKeysDirectly( BOOL b ) { mHandleEditKeysDirectly = b; }
void setSelectAllonFocusReceived(BOOL b);
-
- void setKeystrokeCallback(void (*keystroke_callback)(LLLineEditor* caller, void* user_data));
+
+ typedef boost::function<void (LLLineEditor* caller, void* user_data)> callback_t;
+ void setKeystrokeCallback(callback_t callback, void* user_data);
void setMaxTextLength(S32 max_text_length);
- void setTextPadding(S32 left, S32 right); // Used to specify room for children before or after text.
+ // Manipulate left and right padding for text
+ void getTextPadding(S32 *left, S32 *right);
+ void setTextPadding(S32 left, S32 right);
// Prevalidation controls which keystrokes can affect the editor
- void setPrevalidate( BOOL (*func)(const LLWString &) );
+ void setPrevalidate( LLLinePrevalidateFunc func );
static BOOL prevalidateFloat(const LLWString &str );
static BOOL prevalidateInt(const LLWString &str );
static BOOL prevalidatePositiveS32(const LLWString &str);
static BOOL prevalidateNonNegativeS32(const LLWString &str);
static BOOL prevalidateAlphaNum(const LLWString &str );
static BOOL prevalidateAlphaNumSpace(const LLWString &str );
- static BOOL prevalidatePrintableNotPipe(const LLWString &str);
- static BOOL prevalidatePrintableNoSpace(const LLWString &str);
+ static BOOL prevalidateASCIIPrintableNoPipe(const LLWString &str);
+ static BOOL prevalidateASCIIPrintableNoSpace(const LLWString &str);
static BOOL prevalidateASCII(const LLWString &str);
static BOOL postvalidateFloat(const std::string &str);
@@ -233,6 +264,10 @@ private:
BOOL handleSelectionKey(KEY key, MASK mask);
BOOL handleControlKey(KEY key, MASK mask);
S32 handleCommitKey(KEY key, MASK mask);
+ void updateTextPadding();
+
+ // Draw the background image depending on enabled/focused state.
+ void drawBackground();
//
// private data members
@@ -245,9 +280,9 @@ private:
const segment_lengths_t &preedit_segment_lengths, const standouts_t &preedit_standouts, S32 caret_position);
virtual void markAsPreedit(S32 position, S32 length);
virtual void getPreeditRange(S32 *position, S32 *length) const;
- virtual void getSelectionRange(S32 *position, S32 *length) const;
virtual BOOL getPreeditLocation(S32 query_position, LLCoordGL *coord, LLRect *bounds, LLRect *control) const;
virtual S32 getPreeditFontSize() const;
+ virtual LLWString getPreeditString() const { return getWText(); }
protected:
LLUIString mText; // The string being edited.
@@ -256,8 +291,9 @@ protected:
// line history support:
BOOL mHaveHistory; // flag for enabled line history
- std::vector<std::string> mLineHistory; // line history storage
- U32 mCurrentHistoryLine; // currently browsed history line
+ typedef std::vector<std::string> line_history_t;
+ line_history_t mLineHistory; // line history storage
+ line_history_t::iterator mCurrentHistoryLine; // currently browsed history line
LLViewBorder* mBorder;
const LLFontGL* mGLFont;
@@ -267,13 +303,13 @@ protected:
LLFrameTimer mScrollTimer;
S32 mTextPadLeft; // Used to reserve space before the beginning of the text for children.
S32 mTextPadRight; // Used to reserve space after the end of the text for children.
- S32 mMinHPixels;
- S32 mMaxHPixels;
+ S32 mTextLeftEdge; // Pixels, cached left edge of text based on left padding and width
+ S32 mTextRightEdge; // Pixels, cached right edge of text based on right padding and width
BOOL mCommitOnFocusLost;
BOOL mRevertOnEsc;
- void (*mKeystrokeCallback)( LLLineEditor* caller, void* userdata );
+ keystroke_callback_t mKeystrokeCallback;
BOOL mIsSelecting; // Selection for clipboard operations
S32 mSelectionStart;
@@ -283,18 +319,17 @@ protected:
S32 mLastSelectionStart;
S32 mLastSelectionEnd;
- S32 (*mPrevalidateFunc)(const LLWString &str);
+ LLLinePrevalidateFunc mPrevalidateFunc;
LLFrameTimer mKeystrokeTimer;
+ LLTimer mTripleClickTimer;
- LLColor4 mCursorColor;
-
- LLColor4 mFgColor;
- LLColor4 mReadOnlyFgColor;
- LLColor4 mTentativeFgColor;
- LLColor4 mWriteableBgColor;
- LLColor4 mReadOnlyBgColor;
- LLColor4 mFocusBgColor;
+ LLUIColor mCursorColor;
+ LLUIColor mFgColor;
+ LLUIColor mReadOnlyFgColor;
+ LLUIColor mTentativeFgColor;
+ LLUIColor mHighlightColor; // background for selected text
+ LLUIColor mPreeditBgColor; // preedit marker background color
S32 mBorderThickness;
@@ -314,13 +349,10 @@ protected:
LLPreeditor::standouts_t mPreeditStandouts;
private:
- // Utility on top of LLUI::getUIImage, looks up a named image in a given XML node and returns it if possible
- // or returns a given default image if anything in the process fails.
- static LLPointer<LLUIImage> parseImage(std::string name, LLXMLNodePtr from, LLPointer<LLUIImage> def);
- // Global instance used as default for member instance below.
- static LLPointer<LLUIImage> sImage;
// Instances that by default point to the statics but can be overidden in XML.
- LLPointer<LLUIImage> mImage;
+ LLPointer<LLUIImage> mBgImage;
+ LLPointer<LLUIImage> mBgImageDisabled;
+ LLPointer<LLUIImage> mBgImageFocused;
BOOL mReplaceNewlinesWithSpaces; // if false, will replace pasted newlines with paragraph symbol.
@@ -363,45 +395,10 @@ private:
}; // end class LLLineEditor
-
-
-/*
- * @brief A line editor with a button to clear it and a callback to call on every edit event.
- */
-class LLSearchEditor : public LLUICtrl
-{
-public:
- LLSearchEditor(const std::string& name,
- const LLRect& rect,
- S32 max_length_bytes,
- void (*search_callback)(const std::string& search_string, void* user_data),
- void* userdata);
-
- virtual ~LLSearchEditor() {}
-
- /*virtual*/ void draw();
-
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
-
- void setText(const LLStringExplicit &new_text) { mSearchEdit->setText(new_text); }
-
- void setSearchCallback(void (*search_callback)(const std::string& search_string, void* user_data), void* data) { mSearchCallback = search_callback; mCallbackUserData = data; }
-
- // LLUICtrl interface
- virtual void setValue(const LLSD& value );
- virtual LLSD getValue() const;
- virtual BOOL setTextArg( const std::string& key, const LLStringExplicit& text );
- virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
- virtual void clear();
-
-private:
- static void onSearchEdit(LLLineEditor* caller, void* user_data );
- static void onClearSearch(void* user_data);
-
- LLLineEditor* mSearchEdit;
- class LLButton* mClearSearchButton;
- void (*mSearchCallback)(const std::string& search_string, void* user_data);
-
-};
+// Build time optimization, generate once in .cpp file
+#ifndef LLLINEEDITOR_CPP
+extern template class LLLineEditor* LLView::getChild<class LLLineEditor>(
+ const std::string& name, BOOL recurse) const;
+#endif
#endif // LL_LINEEDITOR_
diff --git a/indra/llui/lllocalcliprect.cpp b/indra/llui/lllocalcliprect.cpp
new file mode 100644
index 0000000000..43c21e250c
--- /dev/null
+++ b/indra/llui/lllocalcliprect.cpp
@@ -0,0 +1,146 @@
+/**
+* @file lllocalcliprect.cpp
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+#include "linden_common.h"
+
+#include "lllocalcliprect.h"
+
+#include "llfontgl.h"
+#include "llgl.h"
+#include "llui.h"
+
+#include <stack>
+
+//---------------------------------------------------------------------------
+// LLScreenClipRect
+// implementation class in screen space
+//---------------------------------------------------------------------------
+class LLScreenClipRect
+{
+public:
+ LLScreenClipRect(const LLRect& rect, BOOL enabled = TRUE);
+ virtual ~LLScreenClipRect();
+
+private:
+ static void pushClipRect(const LLRect& rect);
+ static void popClipRect();
+ static void updateScissorRegion();
+
+private:
+ LLGLState mScissorState;
+ BOOL mEnabled;
+
+ static std::stack<LLRect> sClipRectStack;
+};
+
+/*static*/ std::stack<LLRect> LLScreenClipRect::sClipRectStack;
+
+
+LLScreenClipRect::LLScreenClipRect(const LLRect& rect, BOOL enabled)
+: mScissorState(GL_SCISSOR_TEST),
+ mEnabled(enabled)
+{
+ if (mEnabled)
+ {
+ pushClipRect(rect);
+ }
+ mScissorState.setEnabled(!sClipRectStack.empty());
+ updateScissorRegion();
+}
+
+LLScreenClipRect::~LLScreenClipRect()
+{
+ if (mEnabled)
+ {
+ popClipRect();
+ }
+ updateScissorRegion();
+}
+
+//static
+void LLScreenClipRect::pushClipRect(const LLRect& rect)
+{
+ LLRect combined_clip_rect = rect;
+ if (!sClipRectStack.empty())
+ {
+ LLRect top = sClipRectStack.top();
+ combined_clip_rect.intersectWith(top);
+
+ if(combined_clip_rect.isEmpty())
+ {
+ // avoid artifacts where zero area rects show up as lines
+ combined_clip_rect = LLRect::null;
+ }
+ }
+ sClipRectStack.push(combined_clip_rect);
+}
+
+//static
+void LLScreenClipRect::popClipRect()
+{
+ sClipRectStack.pop();
+}
+
+//static
+void LLScreenClipRect::updateScissorRegion()
+{
+ if (sClipRectStack.empty()) return;
+
+ // finish any deferred calls in the old clipping region
+ gGL.flush();
+
+ LLRect rect = sClipRectStack.top();
+ stop_glerror();
+ S32 x,y,w,h;
+ x = llfloor(rect.mLeft * LLUI::sGLScaleFactor.mV[VX]);
+ y = llfloor(rect.mBottom * LLUI::sGLScaleFactor.mV[VY]);
+ w = llmax(0, llceil(rect.getWidth() * LLUI::sGLScaleFactor.mV[VX])) + 1;
+ h = llmax(0, llceil(rect.getHeight() * LLUI::sGLScaleFactor.mV[VY])) + 1;
+ glScissor( x,y,w,h );
+ stop_glerror();
+}
+
+//---------------------------------------------------------------------------
+// LLLocalClipRect
+//---------------------------------------------------------------------------
+LLLocalClipRect::LLLocalClipRect(const LLRect& rect, BOOL enabled /* = TRUE */)
+{
+ LLRect screen(rect.mLeft + LLFontGL::sCurOrigin.mX,
+ rect.mTop + LLFontGL::sCurOrigin.mY,
+ rect.mRight + LLFontGL::sCurOrigin.mX,
+ rect.mBottom + LLFontGL::sCurOrigin.mY);
+ mScreenClipRect = new LLScreenClipRect(screen, enabled);
+}
+
+LLLocalClipRect::~LLLocalClipRect()
+{
+ delete mScreenClipRect;
+ mScreenClipRect = NULL;
+}
diff --git a/indra/llui/lllocalcliprect.h b/indra/llui/lllocalcliprect.h
new file mode 100644
index 0000000000..cd0c55ca72
--- /dev/null
+++ b/indra/llui/lllocalcliprect.h
@@ -0,0 +1,53 @@
+/**
+* @file lllocalcliprect.h
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+#ifndef LLLOCALCLIPRECT_H
+#define LLLOCALCLIPRECT_H
+
+#include "llrect.h" // can't forward declare, it's templated
+
+// Clip rendering to a specific rectangle using GL scissor
+// Just create one of these on the stack:
+// {
+// LLLocalClipRect(rect);
+// draw();
+// }
+class LLLocalClipRect
+{
+public:
+ LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE);
+ ~LLLocalClipRect();
+
+private:
+ // implementation class
+ class LLScreenClipRect* mScreenClipRect;
+};
+
+#endif
diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp
new file mode 100644
index 0000000000..cdbd17e4dc
--- /dev/null
+++ b/indra/llui/llmenubutton.cpp
@@ -0,0 +1,143 @@
+/**
+ * @file llbutton.cpp
+ * @brief LLButton base class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llmenubutton.h"
+
+// Linden library includes
+#include "llmenugl.h"
+#include "llstring.h"
+#include "v4color.h"
+
+static LLDefaultChildRegistry::Register<LLMenuButton> r("menu_button");
+
+
+LLMenuButton::Params::Params()
+: menu_filename("menu_filename")
+{
+}
+
+
+LLMenuButton::LLMenuButton(const LLMenuButton::Params& p)
+: LLButton(p),
+ mMenu(NULL),
+ mMenuVisibleLastFrame(false)
+{
+ std::string menu_filename = p.menu_filename;
+
+ if (!menu_filename.empty())
+ {
+ mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
+ if (!mMenu)
+ {
+ llwarns << "Error loading menu_button menu" << llendl;
+ }
+ }
+}
+
+void LLMenuButton::toggleMenu()
+{
+ if(!mMenu)
+ return;
+
+ if (mMenu->getVisible() || mMenuVisibleLastFrame)
+ {
+ mMenu->setVisible(FALSE);
+ }
+ else
+ {
+ LLRect rect = getRect();
+ //mMenu->needsArrange(); //so it recalculates the visible elements
+ LLMenuGL::showPopup(getParent(), mMenu, rect.mLeft, rect.mBottom);
+ }
+}
+
+
+void LLMenuButton::hideMenu()
+{
+ if(!mMenu)
+ return;
+ mMenu->setVisible(FALSE);
+}
+
+
+BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask )
+{
+ if( KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key))
+ {
+ toggleMenu();
+ return TRUE;
+ }
+
+ if (mMenu && mMenu->getVisible() && key == KEY_ESCAPE && mask == MASK_NONE)
+ {
+ mMenu->setVisible(FALSE);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL LLMenuButton::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ if (hasTabStop() && !getIsChrome())
+ {
+ setFocus(TRUE);
+ }
+
+ toggleMenu();
+
+ if (getSoundFlags() & MOUSE_DOWN)
+ {
+ make_ui_sound("UISndClick");
+ }
+
+ return TRUE;
+}
+
+void LLMenuButton::draw()
+{
+ //we save this off so next frame when we try to close it by
+ //button click, and it hides menus before we get to it, we know
+ mMenuVisibleLastFrame = mMenu && mMenu->getVisible();
+
+ if (mMenuVisibleLastFrame)
+ {
+ setForcePressedState(true);
+ }
+
+ LLButton::draw();
+
+ setForcePressedState(false);
+}
+
diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h
new file mode 100644
index 0000000000..d0e99d9f40
--- /dev/null
+++ b/indra/llui/llmenubutton.h
@@ -0,0 +1,70 @@
+/**
+ * @file llbutton.h
+ * @brief Header for buttons
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLMENUBUTTON_H
+#define LL_LLMENUBUTTON_H
+
+#include "llbutton.h"
+
+class LLMenuGL;
+
+class LLMenuButton
+: public LLButton
+{
+public:
+ struct Params
+ : public LLInitParam::Block<Params, LLButton::Params>
+ {
+ // filename for it's toggleable menu
+ Optional<std::string> menu_filename;
+
+ Params();
+ };
+
+ void toggleMenu();
+ /*virtual*/ void draw();
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask );
+ void hideMenu();
+ LLMenuGL* getMenu() { return mMenu; }
+
+protected:
+ friend class LLUICtrlFactory;
+ LLMenuButton(const Params&);
+
+private:
+ LLMenuGL* mMenu;
+ bool mMenuVisibleLastFrame;
+};
+
+
+#endif // LL_LLMENUBUTTON_H
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 0762d7c12d..c172a2b714 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -23,7 +23,7 @@
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
- *
+ *
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
@@ -46,21 +46,20 @@
#include "llmenugl.h"
+#include "llgl.h"
#include "llmath.h"
#include "llrender.h"
#include "llfocusmgr.h"
-#include "llfont.h"
#include "llcoord.h"
#include "llwindow.h"
#include "llcriticaldamp.h"
#include "lluictrlfactory.h"
+#include "llbutton.h"
#include "llfontgl.h"
#include "llresmgr.h"
#include "llui.h"
-#include "lluitrans.h"
-
#include "llstl.h"
#include "v2math.h"
@@ -78,7 +77,6 @@ S32 MENU_BAR_WIDTH = 0;
///============================================================================
const std::string SEPARATOR_NAME("separator");
-const std::string TEAROFF_SEPARATOR_LABEL( "~~~~~~~~~~~" );
const std::string SEPARATOR_LABEL( "-----------" );
const std::string VERTICAL_SEPARATOR_LABEL( "|" );
@@ -92,7 +90,6 @@ const U32 RIGHT_PAD_PIXELS = 2;
const U32 RIGHT_WIDTH_PIXELS = 15;
const U32 RIGHT_PLAIN_PIXELS = RIGHT_PAD_PIXELS + RIGHT_WIDTH_PIXELS;
-const U32 ACCEL_PAD_PIXELS = 10;
const U32 PLAIN_PAD_PIXELS = LEFT_PAD_PIXELS + LEFT_WIDTH_PIXELS + RIGHT_PAD_PIXELS + RIGHT_WIDTH_PIXELS;
const U32 BRIEF_PAD_PIXELS = 2;
@@ -101,8 +98,8 @@ const U32 SEPARATOR_HEIGHT_PIXELS = 8;
const S32 TEAROFF_SEPARATOR_HEIGHT_PIXELS = 10;
const S32 MENU_ITEM_PADDING = 4;
-const std::string BOOLEAN_TRUE_PREFIX( "X" );
-const std::string BRANCH_SUFFIX( ">" );
+const std::string BOOLEAN_TRUE_PREFIX( "\xE2\x9C\x94" ); // U+2714 HEAVY CHECK MARK
+const std::string BRANCH_SUFFIX( "\xE2\x96\xB6" ); // U+25B6 BLACK RIGHT-POINTING TRIANGLE
const std::string ARROW_UP ("^^^^^^^");
const std::string ARROW_DOWN("vvvvvvv");
@@ -110,12 +107,6 @@ const F32 MAX_MOUSE_SLOPE_SUB_MENU = 0.9f;
const S32 PIE_GESTURE_ACTIVATE_DISTANCE = 10;
-LLColor4 LLMenuItemGL::sEnabledColor( 0.0f, 0.0f, 0.0f, 1.0f );
-LLColor4 LLMenuItemGL::sDisabledColor( 0.5f, 0.5f, 0.5f, 1.0f );
-LLColor4 LLMenuItemGL::sHighlightBackground( 0.0f, 0.0f, 0.7f, 1.0f );
-LLColor4 LLMenuItemGL::sHighlightForeground( 1.0f, 1.0f, 1.0f, 1.0f );
-
-LLColor4 LLMenuGL::sDefaultBackgroundColor( 0.25f, 0.25f, 0.25f, 0.75f );
BOOL LLMenuGL::sKeyboardMode = FALSE;
LLHandle<LLView> LLMenuHolderGL::sItemLastSelectedHandle;
@@ -128,72 +119,109 @@ const F32 PIE_SHRINK_TIME = 0.2f; // time of transition between unbounded and bo
const F32 ACTIVATE_HIGHLIGHT_TIME = 0.3f;
+static MenuRegistry::Register<LLMenuItemGL> register_menu_item("menu_item");
+static MenuRegistry::Register<LLMenuItemSeparatorGL> register_separator("menu_item_separator");
+static MenuRegistry::Register<LLMenuItemCallGL> register_menu_item_call("menu_item_call");
+static MenuRegistry::Register<LLMenuItemCheckGL> register_menu_item_check("menu_item_check");
+// Created programmatically but we need to specify custom colors in xml
+static MenuRegistry::Register<LLMenuItemTearOffGL> register_menu_item_tear_off("menu_item_tear_off");
+static MenuRegistry::Register<LLMenuGL> register_menu("menu");
+
+static LLDefaultChildRegistry::Register<LLMenuGL> register_menu_default("menu");
+
+
+
///============================================================================
/// Class LLMenuItemGL
///============================================================================
+LLMenuItemGL::Params::Params()
+: shortcut("shortcut"),
+ jump_key("jump_key", KEY_NONE),
+ use_mac_ctrl("use_mac_ctrl", false),
+ rect("rect"),
+ left("left"),
+ top("top"),
+ right("right"),
+ bottom("bottom"),
+ width("width"),
+ height("height"),
+ bottom_delta("bottom_delta"),
+ left_delta("left_delta"),
+ enabled_color("enabled_color"),
+ disabled_color("disabled_color"),
+ highlight_bg_color("highlight_bg_color"),
+ highlight_fg_color("highlight_fg_color")
+{
+ mouse_opaque = true;
+}
+
// Default constructor
-LLMenuItemGL::LLMenuItemGL( const std::string& name, const std::string& label, KEY key, MASK mask ) :
- LLView( name, TRUE ),
- mJumpKey(KEY_NONE),
- mAcceleratorKey( key ),
- mAcceleratorMask( mask ),
+LLMenuItemGL::LLMenuItemGL(const LLMenuItemGL::Params& p)
+: LLUICtrl(p),
+ mJumpKey(p.jump_key),
mAllowKeyRepeat(FALSE),
mHighlight( FALSE ),
mGotHover( FALSE ),
mBriefItem( FALSE ),
- mFont( LLFontGL::getFontSansSerif() ),
- mStyle(LLFontGL::NORMAL),
- mDrawTextDisabled( FALSE )
+ mDrawTextDisabled( FALSE ),
+ mFont(p.font),
+ mAcceleratorKey(KEY_NONE),
+ mAcceleratorMask(MASK_NONE),
+ mLabel(p.label.isProvided() ? p.label() : p.name()),
+ mEnabledColor(p.enabled_color()),
+ mDisabledColor(p.disabled_color()),
+ mHighlightBackground(p.highlight_bg_color()),
+ mHighlightForeground(p.highlight_fg_color())
{
- setLabel( label );
-}
-
-// virtual
-LLXMLNodePtr LLMenuItemGL::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLView::getXML();
-
- node->createChild("type", TRUE)->setStringValue(getType());
-
- node->createChild("label", TRUE)->setStringValue(mLabel);
-
- if (mAcceleratorKey != KEY_NONE)
+#ifdef LL_DARWIN
+ // See if this Mac accelerator should really use the ctrl key and not get mapped to cmd
+ BOOL useMacCtrl = p.use_mac_ctrl;
+#endif // LL_DARWIN
+
+ std::string shortcut = p.shortcut;
+ if (shortcut.find("control") != shortcut.npos)
{
- std::stringstream out;
- if (mAcceleratorMask & MASK_CONTROL)
- {
- out << "control|";
- }
- if (mAcceleratorMask & MASK_ALT)
- {
- out << "alt|";
- }
- if (mAcceleratorMask & MASK_SHIFT)
- {
- out << "shift|";
- }
- out << LLKeyboard::stringFromKey(mAcceleratorKey);
-
- node->createChild("shortcut", TRUE)->setStringValue(out.str());
-
#ifdef LL_DARWIN
- // Write in special tag if this key is really a ctrl combination on the Mac
- if (mAcceleratorMask & MASK_MAC_CONTROL)
+ if ( useMacCtrl )
{
- node->createChild("useMacCtrl", TRUE)->setBoolValue( TRUE );
+ mAcceleratorMask |= MASK_MAC_CONTROL;
}
#endif // LL_DARWIN
+ mAcceleratorMask |= MASK_CONTROL;
}
+ if (shortcut.find("alt") != shortcut.npos)
+ {
+ mAcceleratorMask |= MASK_ALT;
+ }
+ if (shortcut.find("shift") != shortcut.npos)
+ {
+ mAcceleratorMask |= MASK_SHIFT;
+ }
+ S32 pipe_pos = shortcut.rfind("|");
+ std::string key_str = shortcut.substr(pipe_pos+1);
+
+ LLKeyboard::keyFromString(key_str, &mAcceleratorKey);
+
+ LL_DEBUGS("HotKeys") << "Process short cut key: shortcut: " << shortcut
+ << ", key str: " << key_str
+ << ", accelerator mask: " << mAcceleratorMask
+ << ", accelerator key: " << mAcceleratorKey
+ << LL_ENDL;
+}
- return node;
+//virtual
+void LLMenuItemGL::setValue(const LLSD& value)
+{
+ setLabel(value.asString());
}
+//virtual
BOOL LLMenuItemGL::handleAcceleratorKey(KEY key, MASK mask)
{
if( getEnabled() && (!gKeyboard->getKeyRepeated(key) || mAllowKeyRepeat) && (key == mAcceleratorKey) && (mask == (mAcceleratorMask & MASK_NORMALKEYS)) )
{
- doIt();
+ onCommit();
return TRUE;
}
return FALSE;
@@ -206,6 +234,26 @@ BOOL LLMenuItemGL::handleHover(S32 x, S32 y, MASK mask)
return TRUE;
}
+//virtual
+BOOL LLMenuItemGL::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ return LLUICtrl::handleRightMouseDown(x,y,mask);
+}
+
+//virtual
+BOOL LLMenuItemGL::handleRightMouseUp(S32 x, S32 y, MASK mask)
+{
+ // If this event came from a right-click context menu spawn,
+ // process as a left-click to allow menu items to be hit
+ if (LLMenuHolderGL::sContextMenuSpawnPos.mX != S32_MAX
+ || LLMenuHolderGL::sContextMenuSpawnPos.mY != S32_MAX)
+ {
+ BOOL handled = handleMouseUp(x, y, mask);
+ return handled;
+ }
+ return LLUICtrl::handleRightMouseUp(x,y,mask);
+}
+
// This function checks to see if the accelerator key is already in use;
// if not, it will be added to the list
BOOL LLMenuItemGL::addToAcceleratorList(std::list <LLKeyBinding*> *listp)
@@ -255,47 +303,8 @@ BOOL LLMenuItemGL::addToAcceleratorList(std::list <LLKeyBinding*> *listp)
// the current accelerator key and mask to the provided string.
void LLMenuItemGL::appendAcceleratorString( std::string& st ) const
{
- // break early if this is a silly thing to do.
- if( KEY_NONE == mAcceleratorKey )
- {
- return;
- }
-
- // Append any masks
-#ifdef LL_DARWIN
- // Standard Mac names for modifier keys in menu equivalents
- // We could use the symbol characters, but they only exist in certain fonts.
- if( mAcceleratorMask & MASK_CONTROL )
- {
- if ( mAcceleratorMask & MASK_MAC_CONTROL )
- {
- st.append( LLUITrans::getString("accel-mac-control") );
- }
- else
- {
- st.append( LLUITrans::getString("accel-mac-command") ); // Symbol would be "\xE2\x8C\x98"
- }
- }
- if( mAcceleratorMask & MASK_ALT )
- st.append( LLUITrans::getString("accel-mac-option") ); // Symbol would be "\xE2\x8C\xA5"
- if( mAcceleratorMask & MASK_SHIFT )
- st.append( LLUITrans::getString("accel-mac-shift") ); // Symbol would be "\xE2\x8C\xA7"
-#else
- if( mAcceleratorMask & MASK_CONTROL )
- st.append( LLUITrans::getString("accel-win-control") );
- if( mAcceleratorMask & MASK_ALT )
- st.append( LLUITrans::getString("accel-win-alt") );
- if( mAcceleratorMask & MASK_SHIFT )
- st.append( LLUITrans::getString("accel-win-shift") );
-#endif
-
- std::string keystr = LLKeyboard::stringFromKey( mAcceleratorKey );
- if ((mAcceleratorMask & MASK_NORMALKEYS) &&
- (keystr[0] == '-' || keystr[0] == '='))
- {
- st.append( " " );
- }
- st.append( keystr );
+ st = LLKeyboard::stringFromAccelerator( mAcceleratorMask, mAcceleratorKey );
+ LL_DEBUGS("HotKeys") << "appendAcceleratorString: " << st << LL_ENDL;
}
void LLMenuItemGL::setJumpKey(KEY key)
@@ -310,9 +319,20 @@ U32 LLMenuItemGL::getNominalHeight( void ) const
return llround(mFont->getLineHeight()) + MENU_ITEM_PADDING;
}
+//virtual
+void LLMenuItemGL::setBriefItem(BOOL brief)
+{
+ mBriefItem = brief;
+}
+
+//virtual
+BOOL LLMenuItemGL::isBriefItem() const
+{
+ return mBriefItem;
+}
// Get the parent menu for this item
-LLMenuGL* LLMenuItemGL::getMenu()
+LLMenuGL* LLMenuItemGL::getMenu() const
{
return (LLMenuGL*) getParent();
}
@@ -336,7 +356,7 @@ U32 LLMenuItemGL::getNominalWidth( void ) const
if( KEY_NONE != mAcceleratorKey )
{
- width += ACCEL_PAD_PIXELS;
+ width += getMenu()->getShortcutPad();
std::string temp;
appendAcceleratorString( temp );
width += mFont->getWidth( temp );
@@ -354,15 +374,19 @@ void LLMenuItemGL::buildDrawLabel( void )
mDrawAccelLabel = st;
}
-void LLMenuItemGL::doIt( void )
+void LLMenuItemGL::onCommit( void )
{
- // close all open menus by default
- // if parent menu is actually visible (and we are not triggering menu item via accelerator)
+ // Check torn-off status to allow left-arrow keyboard navigation back
+ // to parent menu.
+ // Also, don't hide if item triggered by keyboard shortcut (and hence
+ // parent not visible).
if (!getMenu()->getTornOff()
&& getMenu()->getVisible())
{
LLMenuGL::sMenuContainer->hideMenus();
}
+
+ LLUICtrl::onCommit();
}
// set the hover status (called by it's menu)
@@ -372,6 +396,12 @@ void LLMenuItemGL::doIt( void )
{
getMenu()->clearHoverItem();
}
+
+ if (mHighlight != highlight)
+ {
+ dirtyRect();
+ }
+
mHighlight = highlight;
}
@@ -402,7 +432,7 @@ BOOL LLMenuItemGL::handleKeyHere( KEY key, MASK mask )
// switch to keyboard navigation mode
LLMenuGL::setKeyboardMode(TRUE);
- doIt();
+ onCommit();
return TRUE;
}
}
@@ -410,25 +440,30 @@ BOOL LLMenuItemGL::handleKeyHere( KEY key, MASK mask )
return FALSE;
}
-BOOL LLMenuItemGL::handleMouseUp( S32 x, S32 y, MASK )
+BOOL LLMenuItemGL::handleMouseUp( S32 x, S32 y, MASK mask)
{
// switch to mouse navigation mode
LLMenuGL::setKeyboardMode(FALSE);
- doIt();
+ onCommit();
make_ui_sound("UISndClickRelease");
- return TRUE;
+ return LLView::handleMouseUp(x, y, mask);
}
-BOOL LLMenuItemGL::handleMouseDown( S32 x, S32 y, MASK )
+BOOL LLMenuItemGL::handleMouseDown( S32 x, S32 y, MASK mask)
{
// switch to mouse navigation mode
LLMenuGL::setKeyboardMode(FALSE);
setHighlight(TRUE);
- return TRUE;
+ return LLView::handleMouseDown(x, y, mask);
}
+BOOL LLMenuItemGL::handleScrollWheel( S32 x, S32 y, S32 clicks )
+{
+ // If the menu is scrollable let it handle the wheel event.
+ return !getMenu()->isScrollable();
+}
void LLMenuItemGL::draw( void )
{
@@ -439,55 +474,53 @@ void LLMenuItemGL::draw( void )
// let disabled items be highlighted, just don't draw them as such
if( getEnabled() && getHighlight() && !mBriefItem)
{
- gGL.color4fv( sHighlightBackground.mV );
+ int debug_count = 0;
+ if (dynamic_cast<LLMenuItemCallGL*>(this))
+ debug_count++;
+ gGL.color4fv( mHighlightBackground.get().mV );
+
gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 );
}
LLColor4 color;
- U8 font_style = mStyle;
- if (getEnabled() && !mDrawTextDisabled )
- {
- font_style |= LLFontGL::DROP_SHADOW_SOFT;
- }
-
if ( getEnabled() && getHighlight() )
{
- color = sHighlightForeground;
+ color = mHighlightForeground.get();
}
else if( getEnabled() && !mDrawTextDisabled )
{
- color = sEnabledColor;
+ color = mEnabledColor.get();
}
else
{
- color = sDisabledColor;
+ color = mDisabledColor.get();
}
// Draw the text on top.
if (mBriefItem)
{
mFont->render( mLabel, 0, BRIEF_PAD_PIXELS / 2, 0, color,
- LLFontGL::LEFT, LLFontGL::BOTTOM, font_style );
+ LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL);
}
else
{
if( !mDrawBoolLabel.empty() )
{
mFont->render( mDrawBoolLabel.getWString(), 0, (F32)LEFT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color,
- LLFontGL::LEFT, LLFontGL::BOTTOM, font_style, S32_MAX, S32_MAX, NULL, FALSE );
+ LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );
}
mFont->render( mLabel.getWString(), 0, (F32)LEFT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color,
- LLFontGL::LEFT, LLFontGL::BOTTOM, font_style, S32_MAX, S32_MAX, NULL, FALSE );
+ LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );
if( !mDrawAccelLabel.empty() )
{
mFont->render( mDrawAccelLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color,
- LLFontGL::RIGHT, LLFontGL::BOTTOM, font_style, S32_MAX, S32_MAX, NULL, FALSE );
+ LLFontGL::RIGHT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );
}
if( !mDrawBranchLabel.empty() )
{
mFont->render( mDrawBranchLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color,
- LLFontGL::RIGHT, LLFontGL::BOTTOM, font_style, S32_MAX, S32_MAX, NULL, FALSE );
+ LLFontGL::RIGHT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );
}
}
@@ -515,38 +548,40 @@ BOOL LLMenuItemGL::setLabelArg( const std::string& key, const LLStringExplicit&
return TRUE;
}
+void LLMenuItemGL::handleVisibilityChange(BOOL new_visibility)
+{
+ if (getMenu())
+ {
+ getMenu()->needsArrange();
+ }
+ LLView::handleVisibilityChange(new_visibility);
+}
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLMenuItemSeparatorGL
//
// This class represents a separator.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLMenuItemSeparatorGL : public LLMenuItemGL
+LLMenuItemSeparatorGL::Params::Params()
{
-public:
- LLMenuItemSeparatorGL( const std::string &name = SEPARATOR_NAME );
-
- virtual std::string getType() const { return "separator"; }
-
- // doIt() - do the primary funcationality of the menu item.
- virtual void doIt( void ) {}
-
- virtual void draw( void );
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
+ name = "separator";
+ label = SEPARATOR_LABEL;
+}
- virtual U32 getNominalHeight( void ) const { return SEPARATOR_HEIGHT_PIXELS; }
-};
+LLMenuItemSeparatorGL::LLMenuItemSeparatorGL(const LLMenuItemSeparatorGL::Params& p) :
+ LLMenuItemGL( p )
+{
+}
-LLMenuItemSeparatorGL::LLMenuItemSeparatorGL( const std::string &name ) :
- LLMenuItemGL( name, SEPARATOR_LABEL )
+//virtual
+U32 LLMenuItemSeparatorGL::getNominalHeight( void ) const
{
+ return SEPARATOR_HEIGHT_PIXELS;
}
void LLMenuItemSeparatorGL::draw( void )
{
- gGL.color4fv( getDisabledColor().mV );
+ gGL.color4fv( mDisabledColor.get().mV );
const S32 y = getRect().getHeight() / 2;
const S32 PAD = 6;
gl_line_2d( PAD, y, getRect().getWidth() - PAD, y );
@@ -557,11 +592,14 @@ BOOL LLMenuItemSeparatorGL::handleMouseDown(S32 x, S32 y, MASK mask)
LLMenuGL* parent_menu = getMenu();
if (y > getRect().getHeight() / 2)
{
- return parent_menu->handleMouseDown(x + getRect().mLeft, getRect().mTop + 1, mask);
+ // the menu items are in the child list in bottom up order
+ LLView* prev_menu_item = parent_menu->findNextSibling(this);
+ return prev_menu_item ? prev_menu_item->handleMouseDown(x, prev_menu_item->getRect().getHeight(), mask) : FALSE;
}
else
{
- return parent_menu->handleMouseDown(x + getRect().mLeft, getRect().mBottom - 1, mask);
+ LLView* next_menu_item = parent_menu->findPrevSibling(this);
+ return next_menu_item ? next_menu_item->handleMouseDown(x, 0, mask) : FALSE;
}
}
@@ -570,11 +608,13 @@ BOOL LLMenuItemSeparatorGL::handleMouseUp(S32 x, S32 y, MASK mask)
LLMenuGL* parent_menu = getMenu();
if (y > getRect().getHeight() / 2)
{
- return parent_menu->handleMouseUp(x + getRect().mLeft, getRect().mTop + 1, mask);
+ LLView* prev_menu_item = parent_menu->findNextSibling(this);
+ return prev_menu_item ? prev_menu_item->handleMouseUp(x, prev_menu_item->getRect().getHeight(), mask) : FALSE;
}
else
{
- return parent_menu->handleMouseUp(x + getRect().mLeft, getRect().mBottom - 1, mask);
+ LLView* next_menu_item = parent_menu->findPrevSibling(this);
+ return next_menu_item ? next_menu_item->handleMouseUp(x, 0, mask) : FALSE;
}
}
@@ -593,7 +633,6 @@ BOOL LLMenuItemSeparatorGL::handleHover(S32 x, S32 y, MASK mask)
}
}
-
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLMenuItemVerticalSeparatorGL
//
@@ -617,19 +656,19 @@ LLMenuItemVerticalSeparatorGL::LLMenuItemVerticalSeparatorGL( void )
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLMenuItemTearOffGL
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-LLMenuItemTearOffGL::LLMenuItemTearOffGL(LLHandle<LLFloater> parent_floater_handle) :
- LLMenuItemGL(std::string("tear off"), TEAROFF_SEPARATOR_LABEL),
- mParentHandle(parent_floater_handle)
+LLMenuItemTearOffGL::LLMenuItemTearOffGL(const LLMenuItemTearOffGL::Params& p)
+: LLMenuItemGL(p),
+ mParentHandle(p.parent_floater_handle)
{
}
-void LLMenuItemTearOffGL::doIt()
+void LLMenuItemTearOffGL::onCommit()
{
if (getMenu()->getTornOff())
{
LLTearOffMenu* torn_off_menu = (LLTearOffMenu*)(getMenu()->getParent());
- torn_off_menu->close();
+ torn_off_menu->closeFloater();
}
else
{
@@ -639,7 +678,7 @@ void LLMenuItemTearOffGL::doIt()
getMenu()->highlightNextItem(this);
}
- getMenu()->arrange();
+ getMenu()->needsArrange();
LLFloater* parent_floater = mParentHandle.get();
LLFloater* tear_off_menu = LLTearOffMenu::create(getMenu());
@@ -656,7 +695,7 @@ void LLMenuItemTearOffGL::doIt()
tear_off_menu->setFocus(TRUE);
}
}
- LLMenuItemGL::doIt();
+ LLMenuItemGL::onCommit();
}
void LLMenuItemTearOffGL::draw()
@@ -664,17 +703,17 @@ void LLMenuItemTearOffGL::draw()
// disabled items can be highlighted, but shouldn't render as such
if( getEnabled() && getHighlight() && !isBriefItem())
{
- gGL.color4fv( getHighlightBGColor().mV );
+ gGL.color4fv( mHighlightBackground.get().mV );
gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 );
}
if (getEnabled())
{
- gGL.color4fv( getEnabledColor().mV );
+ gGL.color4fv( mEnabledColor.get().mV );
}
else
{
- gGL.color4fv( getDisabledColor().mV );
+ gGL.color4fv( mDisabledColor.get().mV );
}
const S32 y = getRect().getHeight() / 3;
const S32 PAD = 6;
@@ -697,11 +736,16 @@ U32 LLMenuItemTearOffGL::getNominalHeight( void ) const
class LLMenuItemBlankGL : public LLMenuItemGL
{
public:
- LLMenuItemBlankGL( void ) : LLMenuItemGL( LLStringUtil::null, LLStringUtil::null )
+ struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
{
- setEnabled(FALSE);
- }
- virtual void doIt( void ) {}
+ Params()
+ {
+ name="";
+ enabled = false;
+ }
+ };
+ LLMenuItemBlankGL( const Params& p ) : LLMenuItemGL( p )
+ {}
virtual void draw( void ) {}
};
@@ -710,238 +754,137 @@ public:
/// Class LLMenuItemCallGL
///============================================================================
-LLMenuItemCallGL::LLMenuItemCallGL( const std::string& name,
- const std::string& label,
- menu_callback clicked_cb,
- enabled_callback enabled_cb,
- void* user_data,
- KEY key, MASK mask,
- BOOL enabled,
- on_disabled_callback on_disabled_cb) :
- LLMenuItemGL( name, label, key, mask ),
- mCallback( clicked_cb ),
- mEnabledCallback( enabled_cb ),
- mLabelCallback(NULL),
- mUserData( user_data ),
- mOnDisabledCallback(on_disabled_cb)
-{
- if(!enabled) setEnabled(FALSE);
-}
-
-LLMenuItemCallGL::LLMenuItemCallGL( const std::string& name,
- menu_callback clicked_cb,
- enabled_callback enabled_cb,
- void* user_data,
- KEY key, MASK mask,
- BOOL enabled,
- on_disabled_callback on_disabled_cb) :
- LLMenuItemGL( name, name, key, mask ),
- mCallback( clicked_cb ),
- mEnabledCallback( enabled_cb ),
- mLabelCallback(NULL),
- mUserData( user_data ),
- mOnDisabledCallback(on_disabled_cb)
-{
- if(!enabled) setEnabled(FALSE);
-}
-
-LLMenuItemCallGL::LLMenuItemCallGL(const std::string& name,
- const std::string& label,
- menu_callback clicked_cb,
- enabled_callback enabled_cb,
- label_callback label_cb,
- void* user_data,
- KEY key, MASK mask,
- BOOL enabled,
- on_disabled_callback on_disabled_cb) :
- LLMenuItemGL(name, label, key, mask),
- mCallback(clicked_cb),
- mEnabledCallback(enabled_cb),
- mLabelCallback(label_cb),
- mUserData(user_data),
- mOnDisabledCallback(on_disabled_cb)
-{
- if(!enabled) setEnabled(FALSE);
-}
-
-LLMenuItemCallGL::LLMenuItemCallGL(const std::string& name,
- menu_callback clicked_cb,
- enabled_callback enabled_cb,
- label_callback label_cb,
- void* user_data,
- KEY key, MASK mask,
- BOOL enabled,
- on_disabled_callback on_disabled_cb) :
- LLMenuItemGL(name, name, key, mask),
- mCallback(clicked_cb),
- mEnabledCallback(enabled_cb),
- mLabelCallback(label_cb),
- mUserData(user_data),
- mOnDisabledCallback(on_disabled_cb)
-{
- if(!enabled) setEnabled(FALSE);
-}
-
-void LLMenuItemCallGL::setEnabledControl(std::string enabled_control, LLView *context)
-{
- // Register new listener
- if (!enabled_control.empty())
- {
- LLControlVariable *control = context->findControl(enabled_control);
- if (!control)
- {
- context->addBoolControl(enabled_control, getEnabled());
- control = context->findControl(enabled_control);
- llassert_always(control);
- }
- control->getSignal()->connect(boost::bind(&LLView::controlListener, _1, getHandle(), std::string("enabled")));
- setEnabled(control->getValue());
- }
+LLMenuItemCallGL::LLMenuItemCallGL(const LLMenuItemCallGL::Params& p)
+: LLMenuItemGL(p)
+{
}
-void LLMenuItemCallGL::setVisibleControl(std::string visible_control, LLView *context)
+void LLMenuItemCallGL::initFromParams(const Params& p)
{
- // Register new listener
- if (!visible_control.empty())
+ if (p.on_visible.isProvided())
{
- LLControlVariable *control = context->findControl(visible_control);
- if (!control)
+ mVisibleSignal.connect(initEnableCallback(p.on_visible));
+ }
+ if (p.on_enable.isProvided())
+ {
+ setEnableCallback(initEnableCallback(p.on_enable));
+ // Set the enabled control variable (for backwards compatability)
+ if (p.on_enable.control_name.isProvided() && !p.on_enable.control_name().empty())
{
- context->addBoolControl(visible_control, getVisible());
- control = context->findControl(visible_control);
- llassert_always(control);
+ LLControlVariable* control = findControl(p.on_enable.control_name());
+ if (control)
+ {
+ setEnabledControlVariable(control);
+ }
}
- control->getSignal()->connect(boost::bind(&LLView::controlListener, _1, getHandle(), std::string("visible")));
- setVisible(control->getValue());
}
+ if (p.on_click.isProvided())
+ {
+ setCommitCallback(initCommitCallback(p.on_click));
+ }
+
+ LLUICtrl::initFromParams(p);
}
-// virtual
-LLXMLNodePtr LLMenuItemCallGL::getXML(bool save_children) const
+void LLMenuItemCallGL::onCommit( void )
{
- LLXMLNodePtr node = LLMenuItemGL::getXML();
-
- // Contents
+ // RN: menu item can be deleted in callback, so beware
+ getMenu()->setItemLastSelected( this );
+
+ LLMenuItemGL::onCommit();
+}
- std::vector<LLListenerEntry> listeners = mDispatcher->getListeners();
- std::vector<LLListenerEntry>::iterator itor;
- for (itor = listeners.begin(); itor != listeners.end(); ++itor)
+void LLMenuItemCallGL::updateEnabled( void )
+{
+ if (mEnableSignal.num_slots() > 0)
{
- std::string listener_name = findEventListener((LLSimpleListener*)itor->listener);
- if (!listener_name.empty())
+ bool enabled = mEnableSignal(this, LLSD());
+ if (mEnabledControlVariable)
{
- LLXMLNodePtr child_node = node->createChild("on_click", FALSE);
- child_node->createChild("function", TRUE)->setStringValue(listener_name);
- child_node->createChild("filter", TRUE)->setStringValue(itor->filter.asString());
- child_node->createChild("userdata", TRUE)->setStringValue(itor->userdata.asString());
+ if (!enabled)
+ {
+ // callback overrides control variable; this will call setEnabled()
+ mEnabledControlVariable->set(false);
+ }
+ }
+ else
+ {
+ setEnabled(enabled);
}
}
-
- return node;
}
-// doIt() - Call the callback provided
-void LLMenuItemCallGL::doIt( void )
+void LLMenuItemCallGL::updateVisible( void )
{
- // RN: menu item can be deleted in callback, so beware
- getMenu()->setItemLastSelected( this );
-
- if( mCallback )
+ if (mVisibleSignal.num_slots() > 0)
{
- mCallback( mUserData );
+ bool visible = mVisibleSignal(this, LLSD());
+ setVisible(visible);
}
- LLPointer<LLEvent> fired_event = new LLEvent(this);
- fireEvent(fired_event, "on_click");
- LLMenuItemGL::doIt();
}
void LLMenuItemCallGL::buildDrawLabel( void )
{
- LLPointer<LLEvent> fired_event = new LLEvent(this);
- fireEvent(fired_event, "on_build");
- if( mEnabledCallback )
- {
- setEnabled( mEnabledCallback( mUserData ) );
- }
- if(mLabelCallback)
- {
- std::string label;
- mLabelCallback(label, mUserData);
- mLabel = label;
- }
+ updateEnabled();
+ updateVisible();
LLMenuItemGL::buildDrawLabel();
}
+BOOL LLMenuItemCallGL::handleKeyHere( KEY key, MASK mask )
+{
+ return LLMenuItemGL::handleKeyHere(key, mask);
+}
+
BOOL LLMenuItemCallGL::handleAcceleratorKey( KEY key, MASK mask )
{
- if( (!gKeyboard->getKeyRepeated(key) || getAllowKeyRepeat()) && (key == mAcceleratorKey) && (mask == (mAcceleratorMask & MASK_NORMALKEYS)) )
+ if( (!gKeyboard->getKeyRepeated(key) || getAllowKeyRepeat()) && (key == mAcceleratorKey) && (mask == (mAcceleratorMask & MASK_NORMALKEYS)) )
{
- LLPointer<LLEvent> fired_event = new LLEvent(this);
- fireEvent(fired_event, "on_build");
- if( mEnabledCallback )
+ updateEnabled();
+ if (getEnabled())
{
- setEnabled( mEnabledCallback( mUserData ) );
- }
- if( !getEnabled() )
- {
- if( mOnDisabledCallback )
- {
- mOnDisabledCallback( mUserData );
- }
+ onCommit();
+ return TRUE;
}
}
- return LLMenuItemGL::handleAcceleratorKey(key, mask);
+ return FALSE;
}
+// handleRightMouseUp moved into base class LLMenuItemGL so clicks are
+// handled for all menu item types
+
///============================================================================
/// Class LLMenuItemCheckGL
///============================================================================
-
-LLMenuItemCheckGL::LLMenuItemCheckGL ( const std::string& name,
- const std::string& label,
- menu_callback clicked_cb,
- enabled_callback enabled_cb,
- check_callback check_cb,
- void* user_data,
- KEY key, MASK mask ) :
- LLMenuItemCallGL( name, label, clicked_cb, enabled_cb, user_data, key, mask ),
- mCheckCallback( check_cb ),
- mChecked(FALSE)
+LLMenuItemCheckGL::LLMenuItemCheckGL (const LLMenuItemCheckGL::Params& p)
+: LLMenuItemCallGL(p)
{
}
-LLMenuItemCheckGL::LLMenuItemCheckGL ( const std::string& name,
- menu_callback clicked_cb,
- enabled_callback enabled_cb,
- check_callback check_cb,
- void* user_data,
- KEY key, MASK mask ) :
- LLMenuItemCallGL( name, name, clicked_cb, enabled_cb, user_data, key, mask ),
- mCheckCallback( check_cb ),
- mChecked(FALSE)
+void LLMenuItemCheckGL::initFromParams(const Params& p)
{
+ if (p.on_check.isProvided())
+ {
+ setCheckCallback(initEnableCallback(p.on_check));
+ // Set the control name (for backwards compatability)
+ if (p.on_check.control_name.isProvided() && !p.on_check.control_name().empty())
+ {
+ setControlName(p.on_check.control_name());
+ }
+ }
+
+ LLMenuItemCallGL::initFromParams(p);
}
-LLMenuItemCheckGL::LLMenuItemCheckGL ( const std::string& name,
- const std::string& label,
- menu_callback clicked_cb,
- enabled_callback enabled_cb,
- std::string control_name,
- LLView *context,
- void* user_data,
- KEY key, MASK mask ) :
- LLMenuItemCallGL( name, label, clicked_cb, enabled_cb, user_data, key, mask ),
- mCheckCallback( NULL ),
- mChecked(FALSE)
+void LLMenuItemCheckGL::onCommit( void )
{
- setControlName(control_name, context);
+ LLMenuItemCallGL::onCommit();
}
//virtual
void LLMenuItemCheckGL::setValue(const LLSD& value)
{
- mChecked = value.asBoolean();
- if(mChecked)
+ LLUICtrl::setValue(value);
+ if(value.asBoolean())
{
mDrawBoolLabel = BOOLEAN_TRUE_PREFIX;
}
@@ -951,34 +894,21 @@ void LLMenuItemCheckGL::setValue(const LLSD& value)
}
}
-void LLMenuItemCheckGL::setCheckedControl(std::string checked_control, LLView *context)
-{
- // Register new listener
- if (!checked_control.empty())
- {
- LLControlVariable *control = context->findControl(checked_control);
- if (!control)
- {
- context->addBoolControl(checked_control, mChecked);
- control = context->findControl(checked_control);
- llassert_always(control);
- }
- control->getSignal()->connect(boost::bind(&LLView::controlListener, _1, getHandle(), std::string("value")));
- mChecked = control->getValue();
- }
-}
-
-// virtual
-LLXMLNodePtr LLMenuItemCheckGL::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLMenuItemCallGL::getXML();
- return node;
-}
-
// called to rebuild the draw label
void LLMenuItemCheckGL::buildDrawLabel( void )
{
- if(mChecked || (mCheckCallback && mCheckCallback( getUserData() ) ) )
+ // Note: mCheckSignal() returns true if no callbacks are set
+ bool checked = mCheckSignal(this, LLSD());
+ if (mControlVariable)
+ {
+ if (!checked)
+ setControlValue(false); // callback overrides control variable; this will call setValue()
+ }
+ else
+ {
+ setValue(checked);
+ }
+ if(getValue().asBoolean())
{
mDrawBoolLabel = BOOLEAN_TRUE_PREFIX;
}
@@ -989,95 +919,59 @@ void LLMenuItemCheckGL::buildDrawLabel( void )
LLMenuItemCallGL::buildDrawLabel();
}
-
///============================================================================
-/// Class LLMenuItemToggleGL
+/// Class LLMenuItemBranchGL
///============================================================================
-
-LLMenuItemToggleGL::LLMenuItemToggleGL( const std::string& name, const std::string& label, BOOL* toggle,
- KEY key, MASK mask ) :
- LLMenuItemGL( name, label, key, mask ),
- mToggle( toggle )
+LLMenuItemBranchGL::LLMenuItemBranchGL(const LLMenuItemBranchGL::Params& p)
+ : LLMenuItemGL(p)
{
-}
-
-LLMenuItemToggleGL::LLMenuItemToggleGL( const std::string& name, BOOL* toggle,
- KEY key, MASK mask ) :
- LLMenuItemGL( name, name, key, mask ),
- mToggle( toggle )
-{
-}
-
-
-// called to rebuild the draw label
-void LLMenuItemToggleGL::buildDrawLabel( void )
-{
- if( *mToggle )
- {
- mDrawBoolLabel = BOOLEAN_TRUE_PREFIX;
- }
- else
+ LLMenuGL* branch = p.branch;
+ if (branch)
{
- mDrawBoolLabel.clear();
+ mBranchHandle = branch->getHandle();
+ branch->setVisible(FALSE);
+ branch->setParentMenuItem(this);
}
- mDrawAccelLabel.clear();
- std::string st = mDrawAccelLabel;
- appendAcceleratorString( st );
- mDrawAccelLabel = st;
}
-// doIt() - do the primary funcationality of the menu item.
-void LLMenuItemToggleGL::doIt( void )
+LLMenuItemBranchGL::~LLMenuItemBranchGL()
{
- getMenu()->setItemLastSelected( this );
- //llinfos << "LLMenuItemToggleGL::doIt " << mLabel.c_str() << llendl;
- *mToggle = !(*mToggle);
- buildDrawLabel();
- LLMenuItemGL::doIt();
+ LLView::deleteViewByHandle(mBranchHandle);
}
-
-LLMenuItemBranchGL::LLMenuItemBranchGL( const std::string& name, const std::string& label, LLHandle<LLView> branch,
- KEY key, MASK mask ) :
- LLMenuItemGL( name, label, key, mask ),
- mBranch( branch )
+// virtual
+LLView* LLMenuItemBranchGL::getChildView(const std::string& name, BOOL recurse) const
{
- if(!dynamic_cast<LLMenuGL*>(branch.get()))
+ LLMenuGL* branch = getBranch();
+ if (branch)
{
- llerrs << "Non-menu handle passed as branch reference." << llendl;
- }
+ if (branch->getName() == name)
+ {
+ return branch;
+ }
- if(getBranch())
- {
- getBranch()->setVisible( FALSE );
- getBranch()->setParentMenuItem(this);
+ // Always recurse on branches
+ return branch->getChildView(name, recurse);
}
-}
-LLMenuItemBranchGL::~LLMenuItemBranchGL()
-{
- LLView::deleteViewByHandle(mBranch);
+ return LLView::getChildView(name, recurse);
}
-// virtual
-LLView* LLMenuItemBranchGL::getChildView(const std::string& name, BOOL recurse, BOOL create_if_missing) const
+LLView* LLMenuItemBranchGL::findChildView(const std::string& name, BOOL recurse) const
{
- // richard: this is redundant with parent, remove
- if (getBranch())
+ LLMenuGL* branch = getBranch();
+ if (branch)
{
- if(getBranch()->getName() == name)
+ if (branch->getName() == name)
{
- return getBranch();
+ return branch;
}
// Always recurse on branches
- LLView* child = getBranch()->getChildView(name, recurse, FALSE);
- if(child)
- {
- return child;
- }
+ return branch->findChildView(name, recurse);
}
- return LLView::getChildView(name, recurse, create_if_missing);;
+
+ return LLView::findChildView(name, recurse);
}
// virtual
@@ -1086,49 +980,35 @@ BOOL LLMenuItemBranchGL::handleMouseUp(S32 x, S32 y, MASK mask)
// switch to mouse navigation mode
LLMenuGL::setKeyboardMode(FALSE);
- doIt();
+ onCommit();
make_ui_sound("UISndClickRelease");
return TRUE;
}
BOOL LLMenuItemBranchGL::handleAcceleratorKey(KEY key, MASK mask)
{
- if(getBranch())
- {
- return getBranch()->handleAcceleratorKey(key, mask);
- }
- return FALSE;
-}
-
-// virtual
-LLXMLNodePtr LLMenuItemBranchGL::getXML(bool save_children) const
-{
- if (getBranch())
- {
- return getBranch()->getXML();
- }
-
- return LLMenuItemGL::getXML();
+ return getBranch() && getBranch()->handleAcceleratorKey(key, mask);
}
-
// This function checks to see if the accelerator key is already in use;
// if not, it will be added to the list
BOOL LLMenuItemBranchGL::addToAcceleratorList(std::list<LLKeyBinding*> *listp)
{
- if(getBranch())
- {
- U32 item_count = getBranch()->getItemCount();
- LLMenuItemGL *item;
+ LLMenuGL* branch = getBranch();
+ if (!branch)
+ return FALSE;
- while (item_count--)
+ U32 item_count = branch->getItemCount();
+ LLMenuItemGL *item;
+
+ while (item_count--)
+ {
+ if ((item = branch->getItem(item_count)))
{
- if ((item = getBranch()->getItem(item_count)))
- {
- return item->addToAcceleratorList(listp);
- }
+ return item->addToAcceleratorList(listp);
}
}
+
return FALSE;
}
@@ -1143,23 +1023,24 @@ void LLMenuItemBranchGL::buildDrawLabel( void )
mDrawBranchLabel = BRANCH_SUFFIX;
}
-// doIt() - do the primary functionality of the menu item.
-void LLMenuItemBranchGL::doIt( void )
+void LLMenuItemBranchGL::onCommit( void )
{
openMenu();
// keyboard navigation automatically propagates highlight to sub-menu
// to facilitate fast menu control via jump keys
- if (getBranch() && LLMenuGL::getKeyboardMode() && !getBranch()->getHighlightedItem())
+ if (LLMenuGL::getKeyboardMode() && getBranch()&& !getBranch()->getHighlightedItem())
{
getBranch()->highlightNextItem(NULL);
}
+
+ LLUICtrl::onCommit();
}
BOOL LLMenuItemBranchGL::handleKey(KEY key, MASK mask, BOOL called_from_parent)
{
BOOL handled = FALSE;
- if (called_from_parent && getBranch())
+ if (getBranch() && called_from_parent)
{
handled = getBranch()->handleKey(key, mask, called_from_parent);
}
@@ -1175,7 +1056,7 @@ BOOL LLMenuItemBranchGL::handleKey(KEY key, MASK mask, BOOL called_from_parent)
BOOL LLMenuItemBranchGL::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
{
BOOL handled = FALSE;
- if (called_from_parent && getBranch())
+ if (getBranch() && called_from_parent)
{
handled = getBranch()->handleUnicodeChar(uni_char, TRUE);
}
@@ -1191,21 +1072,21 @@ BOOL LLMenuItemBranchGL::handleUnicodeChar(llwchar uni_char, BOOL called_from_pa
void LLMenuItemBranchGL::setHighlight( BOOL highlight )
{
- if (highlight == getHighlight()) return;
+ if (highlight == getHighlight())
+ return;
- if(!getBranch())
- {
+ LLMenuGL* branch = getBranch();
+ if (!branch)
return;
- }
- BOOL auto_open = getEnabled() && (!getBranch()->getVisible() || getBranch()->getTornOff());
+ BOOL auto_open = getEnabled() && (!branch->getVisible() || branch->getTornOff());
// torn off menus don't open sub menus on hover unless they have focus
if (getMenu()->getTornOff() && !((LLFloater*)getMenu()->getParent())->hasFocus())
{
auto_open = FALSE;
}
// don't auto open torn off sub-menus (need to explicitly active menu item to give them focus)
- if (getBranch()->getTornOff())
+ if (branch->getTornOff())
{
auto_open = FALSE;
}
@@ -1219,14 +1100,14 @@ void LLMenuItemBranchGL::setHighlight( BOOL highlight )
}
else
{
- if (getBranch()->getTornOff())
+ if (branch->getTornOff())
{
- ((LLFloater*)getBranch()->getParent())->setFocus(FALSE);
- getBranch()->clearHoverItem();
+ ((LLFloater*)branch->getParent())->setFocus(FALSE);
+ branch->clearHoverItem();
}
else
{
- getBranch()->setVisible( FALSE );
+ branch->setVisible( FALSE );
}
}
}
@@ -1249,102 +1130,129 @@ void LLMenuItemBranchGL::updateBranchParent(LLView* parentp)
}
}
-void LLMenuItemBranchGL::onVisibilityChange( BOOL new_visibility )
+void LLMenuItemBranchGL::handleVisibilityChange( BOOL new_visibility )
{
if (new_visibility == FALSE && getBranch() && !getBranch()->getTornOff())
{
getBranch()->setVisible(FALSE);
}
- LLMenuItemGL::onVisibilityChange(new_visibility);
+ LLMenuItemGL::handleVisibilityChange(new_visibility);
}
BOOL LLMenuItemBranchGL::handleKeyHere( KEY key, MASK mask )
{
- if (getMenu()->getVisible() && getBranch() && getBranch()->getVisible() && key == KEY_LEFT)
- {
- // switch to keyboard navigation mode
- LLMenuGL::setKeyboardMode(TRUE);
+ LLMenuGL* branch = getBranch();
+ if (!branch)
+ return LLMenuItemGL::handleKeyHere(key, mask);
- BOOL handled = getBranch()->clearHoverItem();
- if (getBranch()->getTornOff())
- {
- ((LLFloater*)getBranch()->getParent())->setFocus(FALSE);
- }
- if (handled && getMenu()->getTornOff())
+ // an item is highlighted, my menu is open, and I have an active sub menu or we are in
+ // keyboard navigation mode
+ if (getHighlight()
+ && getMenu()->isOpen()
+ && (isActive() || LLMenuGL::getKeyboardMode()))
+ {
+ if (branch->getVisible() && key == KEY_LEFT)
{
- ((LLFloater*)getMenu()->getParent())->setFocus(TRUE);
- }
- return handled;
- }
+ // switch to keyboard navigation mode
+ LLMenuGL::setKeyboardMode(TRUE);
- if (getHighlight() &&
- getMenu()->isOpen() &&
- key == KEY_RIGHT && getBranch() && !getBranch()->getHighlightedItem())
- {
- // switch to keyboard navigation mode
- LLMenuGL::setKeyboardMode(TRUE);
+ BOOL handled = branch->clearHoverItem();
+ if (branch->getTornOff())
+ {
+ ((LLFloater*)branch->getParent())->setFocus(FALSE);
+ }
+ if (handled && getMenu()->getTornOff())
+ {
+ ((LLFloater*)getMenu()->getParent())->setFocus(TRUE);
+ }
+ return handled;
+ }
- LLMenuItemGL* itemp = getBranch()->highlightNextItem(NULL);
- if (itemp)
+ if (key == KEY_RIGHT && !branch->getHighlightedItem())
{
- return TRUE;
+ // switch to keyboard navigation mode
+ LLMenuGL::setKeyboardMode(TRUE);
+
+ LLMenuItemGL* itemp = branch->highlightNextItem(NULL);
+ if (itemp)
+ {
+ return TRUE;
+ }
}
}
-
return LLMenuItemGL::handleKeyHere(key, mask);
}
+//virtual
+BOOL LLMenuItemBranchGL::isActive() const
+{
+ return isOpen() && getBranch() && getBranch()->getHighlightedItem();
+}
+
+//virtual
+BOOL LLMenuItemBranchGL::isOpen() const
+{
+ return getBranch() && getBranch()->isOpen();
+}
+
void LLMenuItemBranchGL::openMenu()
{
- if(!getBranch()) return;
+ LLMenuGL* branch = getBranch();
+ if (!branch)
+ return;
- if (getBranch()->getTornOff())
+ if (branch->getTornOff())
{
- gFloaterView->bringToFront((LLFloater*)getBranch()->getParent());
+ gFloaterView->bringToFront((LLFloater*)branch->getParent());
// this might not be necessary, as torn off branches don't get focus and hence no highligth
- getBranch()->highlightNextItem(NULL);
+ branch->highlightNextItem(NULL);
}
- else if( !getBranch()->getVisible() )
+ else if( !branch->getVisible() )
{
// get valid rectangle for menus
const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect();
- getBranch()->arrange();
+ branch->arrange();
- LLRect rect = getBranch()->getRect();
+ LLRect branch_rect = branch->getRect();
// calculate root-view relative position for branch menu
S32 left = getRect().mRight;
S32 top = getRect().mTop - getRect().mBottom;
- localPointToOtherView(left, top, &left, &top, getBranch()->getParent());
+ localPointToOtherView(left, top, &left, &top, branch->getParent());
- rect.setLeftTopAndSize( left, top,
- rect.getWidth(), rect.getHeight() );
+ branch_rect.setLeftTopAndSize( left, top,
+ branch_rect.getWidth(), branch_rect.getHeight() );
- if (getBranch()->getCanTearOff())
+ if (branch->getCanTearOff())
{
- rect.translate(0, TEAROFF_SEPARATOR_HEIGHT_PIXELS);
+ branch_rect.translate(0, TEAROFF_SEPARATOR_HEIGHT_PIXELS);
}
- getBranch()->setRect( rect );
- S32 x = 0;
- S32 y = 0;
- getBranch()->localPointToOtherView( 0, 0, &x, &y, getBranch()->getParent() );
+ branch->setRect( branch_rect );
+
+ // if branch extends outside of menu region change the direction it opens in
+ S32 x, y;
S32 delta_x = 0;
S32 delta_y = 0;
+ branch->localPointToOtherView( 0, 0, &x, &y, branch->getParent() );
if( y < menu_region_rect.mBottom )
{
- delta_y = menu_region_rect.mBottom - y;
+ // open upwards if menu extends past bottom
+ // adjust by the height of the menu item branch since it is a submenu
+ delta_y = branch_rect.getHeight() - getRect().getHeight();
}
- S32 menu_region_width = menu_region_rect.getWidth();
- if( x - menu_region_rect.mLeft > menu_region_width - rect.getWidth() )
+ if( x + branch_rect.getWidth() > menu_region_rect.mRight )
{
// move sub-menu over to left side
- delta_x = llmax(-x, (-1 * (rect.getWidth() + getRect().getWidth())));
+ delta_x = llmax(-x, ( -(branch_rect.getWidth() + getRect().getWidth())));
}
- getBranch()->translate( delta_x, delta_y );
- getBranch()->setVisible( TRUE );
- getBranch()->getParent()->sendChildToFront(getBranch());
+ branch->translate( delta_x, delta_y );
+
+ branch->setVisible( TRUE );
+ branch->getParent()->sendChildToFront(branch);
+
+ dirtyRect();
}
}
@@ -1361,10 +1269,7 @@ class LLMenuItemBranchDownGL : public LLMenuItemBranchGL
protected:
public:
- LLMenuItemBranchDownGL( const std::string& name, const std::string& label, LLHandle<LLView> branch,
- KEY key = KEY_NONE, MASK mask = MASK_NONE );
-
- virtual std::string getType() const { return "menu"; }
+ LLMenuItemBranchDownGL( const Params& );
// returns the normal width of this control in pixels - this is
// used for calculating the widest item, as well as for horizontal
@@ -1392,11 +1297,8 @@ public:
virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
};
-LLMenuItemBranchDownGL::LLMenuItemBranchDownGL( const std::string& name,
- const std::string& label,
- LLHandle<LLView> branch,
- KEY key, MASK mask ) :
- LLMenuItemBranchGL( name, label, branch, key, mask )
+LLMenuItemBranchDownGL::LLMenuItemBranchDownGL( const Params& p) :
+ LLMenuItemBranchGL(p)
{
}
@@ -1471,20 +1373,26 @@ void LLMenuItemBranchDownGL::openMenu( void )
// set the hover status (called by it's menu)
void LLMenuItemBranchDownGL::setHighlight( BOOL highlight )
{
- if (highlight == getHighlight()) return;
+ if (highlight == getHighlight())
+ return;
//NOTE: Purposely calling all the way to the base to bypass auto-open.
LLMenuItemGL::setHighlight(highlight);
+
+ LLMenuGL* branch = getBranch();
+ if (!branch)
+ return;
+
if( !highlight)
{
- if (getBranch()->getTornOff())
+ if (branch->getTornOff())
{
- ((LLFloater*)getBranch()->getParent())->setFocus(FALSE);
- getBranch()->clearHoverItem();
+ ((LLFloater*)branch->getParent())->setFocus(FALSE);
+ branch->clearHoverItem();
}
else
{
- getBranch()->setVisible( FALSE );
+ branch->setVisible( FALSE );
}
}
}
@@ -1501,7 +1409,7 @@ BOOL LLMenuItemBranchDownGL::handleMouseDown( S32 x, S32 y, MASK mask )
{
// switch to mouse control mode
LLMenuGL::setKeyboardMode(FALSE);
- doIt();
+ onCommit();
make_ui_sound("UISndClick");
return TRUE;
}
@@ -1529,7 +1437,7 @@ BOOL LLMenuItemBranchDownGL::handleKeyHere(KEY key, MASK mask)
{
BOOL menu_open = getBranch()->getVisible();
// don't do keyboard navigation of top-level menus unless in keyboard mode, or menu expanded
- if (getHighlight() && getMenu()->getVisible() && (isActive() || LLMenuGL::getKeyboardMode()))
+ if (getHighlight() && getMenu()->isOpen() && (isActive() || LLMenuGL::getKeyboardMode()))
{
if (key == KEY_LEFT)
{
@@ -1540,7 +1448,7 @@ BOOL LLMenuItemBranchDownGL::handleKeyHere(KEY key, MASK mask)
// open new menu only if previous menu was open
if (itemp && itemp->getEnabled() && menu_open)
{
- itemp->doIt();
+ itemp->onCommit();
}
return TRUE;
@@ -1554,7 +1462,7 @@ BOOL LLMenuItemBranchDownGL::handleKeyHere(KEY key, MASK mask)
// open new menu only if previous menu was open
if (itemp && itemp->getEnabled() && menu_open)
{
- itemp->doIt();
+ itemp->onCommit();
}
return TRUE;
@@ -1566,7 +1474,7 @@ BOOL LLMenuItemBranchDownGL::handleKeyHere(KEY key, MASK mask)
if (!isActive())
{
- doIt();
+ onCommit();
}
getBranch()->highlightNextItem(NULL);
return TRUE;
@@ -1578,7 +1486,7 @@ BOOL LLMenuItemBranchDownGL::handleKeyHere(KEY key, MASK mask)
if (!isActive())
{
- doIt();
+ onCommit();
}
getBranch()->highlightPrevItem(NULL);
return TRUE;
@@ -1598,31 +1506,25 @@ void LLMenuItemBranchDownGL::draw( void )
if( getHighlight() )
{
- gGL.color4fv( getHighlightBGColor().mV );
+ gGL.color4fv( mHighlightBackground.get().mV );
gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 );
}
- U8 font_style = getFontStyle();
- if (getEnabled() && !getDrawTextDisabled() )
- {
- font_style |= LLFontGL::DROP_SHADOW_SOFT;
- }
-
LLColor4 color;
if (getHighlight())
{
- color = getHighlightFGColor();
+ color = mHighlightForeground.get();
}
else if( getEnabled() )
{
- color = getEnabledColor();
+ color = mEnabledColor.get();
}
else
{
- color = getDisabledColor();
+ color = mDisabledColor.get();
}
getFont()->render( mLabel.getWString(), 0, (F32)getRect().getWidth() / 2.f, (F32)LABEL_BOTTOM_PAD_PIXELS, color,
- LLFontGL::HCENTER, LLFontGL::BOTTOM, font_style );
+ LLFontGL::HCENTER, LLFontGL::BOTTOM, LLFontGL::NORMAL);
// underline navigation key only when keyboard navigation has been initiated
@@ -1645,22 +1547,116 @@ void LLMenuItemBranchDownGL::draw( void )
setHover(FALSE);
}
+
+class LLMenuScrollItem : public LLMenuItemCallGL
+{
+public:
+ enum EArrowType
+ {
+ ARROW_DOWN,
+ ARROW_UP
+ };
+ struct ArrowTypes : public LLInitParam::TypeValuesHelper<EArrowType, ArrowTypes>
+ {
+ static void declareValues()
+ {
+ declare("up", ARROW_UP);
+ declare("down", ARROW_DOWN);
+ }
+ };
+
+ struct Params : public LLInitParam::Block<Params, LLMenuItemCallGL::Params>
+ {
+ Optional<EArrowType, ArrowTypes> arrow_type;
+ Optional<CommitCallbackParam> scroll_callback;
+ };
+
+protected:
+ LLMenuScrollItem(const Params&);
+ friend class LLUICtrlFactory;
+
+public:
+ /*virtual*/ void draw();
+ /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent);
+ /*virtual*/ void setEnabled(BOOL enabled);
+ virtual void onCommit( void );
+
+private:
+ LLButton* mArrowBtn;
+};
+
+LLMenuScrollItem::LLMenuScrollItem(const Params& p)
+: LLMenuItemCallGL(p)
+{
+ std::string icon;
+ if (p.arrow_type.isProvided() && p.arrow_type == ARROW_UP)
+ {
+ icon = "arrow_up.tga";
+ }
+ else
+ {
+ icon = "arrow_down.tga";
+ }
+
+ LLButton::Params bparams;
+ bparams.mouse_opaque(true);
+ bparams.scale_image(false);
+ bparams.click_callback(p.scroll_callback);
+ bparams.mouse_held_callback(p.scroll_callback);
+ bparams.follows.flags(FOLLOWS_ALL);
+ std::string background = "transparent.j2c";
+ bparams.image_unselected.name(background);
+ bparams.image_disabled.name(background);
+ bparams.image_selected.name(background);
+ bparams.image_hover_selected.name(background);
+ bparams.image_disabled_selected.name(background);
+ bparams.image_hover_unselected.name(background);
+ bparams.image_overlay.name(icon);
+
+ mArrowBtn = LLUICtrlFactory::create<LLButton>(bparams);
+ addChild(mArrowBtn);
+}
+
+/*virtual*/
+void LLMenuScrollItem::draw()
+{
+ LLUICtrl::draw();
+}
+
+/*virtual*/
+void LLMenuScrollItem::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ mArrowBtn->reshape(width, height, called_from_parent);
+ LLView::reshape(width, height, called_from_parent);
+}
+
+/*virtual*/
+void LLMenuScrollItem::setEnabled(BOOL enabled)
+{
+ mArrowBtn->setEnabled(enabled);
+ LLView::setEnabled(enabled);
+}
+
+void LLMenuScrollItem::onCommit( void )
+{
+ LLUICtrl::onCommit();
+}
+
///============================================================================
/// Class LLMenuGL
///============================================================================
-static LLRegisterWidget<LLMenuGL> r1("menu");
-
-// Default constructor
-LLMenuGL::LLMenuGL( const std::string& name, const std::string& label, LLHandle<LLFloater> parent_floater_handle )
-: LLUICtrl( name, LLRect(), FALSE, NULL, NULL ),
- mBackgroundColor( sDefaultBackgroundColor ),
- mBgVisible( TRUE ),
- mParentMenuItem( NULL ),
- mLabel( label ),
- mDropShadowed( TRUE ),
- mHorizontalLayout( FALSE ),
- mKeepFixedSize( FALSE ),
+LLMenuGL::LLMenuGL(const LLMenuGL::Params& p)
+: LLUICtrl(p),
+ mBackgroundColor( p.bg_color() ),
+ mBgVisible( p.bg_visible ),
+ mDropShadowed( p.drop_shadow ),
+ mHorizontalLayout( p.horizontal_layout ),
+ mScrollable(mHorizontalLayout ? FALSE : p.scrollable), // Scrolling is supported only for vertical layout
+ mMaxScrollableItems(p.max_scrollable_items),
+ mPreferredWidth(p.preferred_width),
+ mKeepFixedSize( p.keep_fixed_size ),
+ mLabel (p.label),
mLastMouseX(0),
mLastMouseY(0),
mMouseVelX(0),
@@ -1668,38 +1664,41 @@ LLMenuGL::LLMenuGL( const std::string& name, const std::string& label, LLHandle<
mTornOff(FALSE),
mTearOffItem(NULL),
mSpilloverBranch(NULL),
+ mFirstVisibleItem(NULL),
+ mArrowUpItem(NULL),
+ mArrowDownItem(NULL),
mSpilloverMenu(NULL),
- mParentFloaterHandle(parent_floater_handle),
- mJumpKey(KEY_NONE)
+ mJumpKey(p.jump_key),
+ mCreateJumpKeys(p.create_jump_keys),
+ mParentFloaterHandle(p.parent_floater),
+ mNeedsArrange(FALSE),
+ mShortcutPad(p.shortcut_pad)
{
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep("_");
+ tokenizer tokens(p.label(), sep);
+ tokenizer::iterator token_iter;
+
+ S32 token_count = 0;
+ std::string new_menu_label;
+ for( token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
+ {
+ new_menu_label += (*token_iter);
+ if (token_count > 0)
+ {
+ setJumpKey((*token_iter).c_str()[0]);
+ }
+ ++token_count;
+ }
+ setLabel(new_menu_label);
+
mFadeTimer.stop();
- setCanTearOff(TRUE, parent_floater_handle);
- setTabStop(FALSE);
-}
-
-LLMenuGL::LLMenuGL( const std::string& label, LLHandle<LLFloater> parent_floater_handle )
-: LLUICtrl( label, LLRect(), FALSE, NULL, NULL ),
- mBackgroundColor( sDefaultBackgroundColor ),
- mBgVisible( TRUE ),
- mParentMenuItem( NULL ),
- mLabel( label ),
- mDropShadowed( TRUE ),
- mHorizontalLayout( FALSE ),
- mKeepFixedSize( FALSE ),
- mLastMouseX(0),
- mLastMouseY(0),
- mMouseVelX(0),
- mMouseVelY(0),
- mTornOff(FALSE),
- mTearOffItem(NULL),
- mSpilloverBranch(NULL),
- mSpilloverMenu(NULL),
- mParentFloaterHandle(parent_floater_handle),
- mJumpKey(KEY_NONE)
+}
+
+void LLMenuGL::initFromParams(const LLMenuGL::Params& p)
{
- mFadeTimer.stop();
- setCanTearOff(TRUE, parent_floater_handle);
- setTabStop(FALSE);
+ LLUICtrl::initFromParams(p);
+ setCanTearOff(p.can_tear_off, p.parent_floater);
}
// Destroys the object
@@ -1715,10 +1714,10 @@ void LLMenuGL::setCanTearOff(BOOL tear_off, LLHandle<LLFloater> parent_floater_h
{
if (tear_off && mTearOffItem == NULL)
{
- mTearOffItem = new LLMenuItemTearOffGL(parent_floater_handle);
- mItems.insert(mItems.begin(), mTearOffItem);
- addChildAtEnd(mTearOffItem);
- arrange();
+ LLMenuItemTearOffGL::Params p;
+ p.parent_floater_handle = parent_floater_handle;
+ mTearOffItem = LLUICtrlFactory::create<LLMenuItemTearOffGL>(p);
+ addChildInBack(mTearOffItem);
}
else if (!tear_off && mTearOffItem != NULL)
{
@@ -1726,313 +1725,45 @@ void LLMenuGL::setCanTearOff(BOOL tear_off, LLHandle<LLFloater> parent_floater_h
removeChild(mTearOffItem);
delete mTearOffItem;
mTearOffItem = NULL;
- arrange();
+ needsArrange();
}
}
-// virtual
-LLXMLNodePtr LLMenuGL::getXML(bool save_children) const
+bool LLMenuGL::addChild(LLView* view, S32 tab_group)
{
- LLXMLNodePtr node = LLView::getXML();
-
- // Attributes
-
- node->createChild("opaque", TRUE)->setBoolValue(mBgVisible);
-
- node->createChild("drop_shadow", TRUE)->setBoolValue(mDropShadowed);
-
- node->createChild("tear_off", TRUE)->setBoolValue((mTearOffItem != NULL));
-
- if (mBgVisible)
+ if (LLMenuGL* menup = dynamic_cast<LLMenuGL*>(view))
{
- // TomY TODO: this should save out the color control name
- node->createChild("color", TRUE)->setFloatValue(4, mBackgroundColor.mV);
+ appendMenu(menup);
+ return true;
}
-
- // Contents
- item_list_t::const_iterator item_iter;
- for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
+ else if (LLMenuItemGL* itemp = dynamic_cast<LLMenuItemGL*>(view))
{
- LLView* child = (*item_iter);
- LLMenuItemGL* item = (LLMenuItemGL*)child;
-
- LLXMLNodePtr child_node = item->getXML();
-
- node->addChild(child_node);
+ append(itemp);
+ return true;
}
-
- return node;
+ return false;
}
-void LLMenuGL::parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory *factory)
+void LLMenuGL::removeChild( LLView* ctrl)
{
- if (child->hasName(LL_MENU_GL_TAG))
+ // previously a dynamic_cast with if statement to check validity
+ // unfortunately removeChild is called by ~LLView, and at that point the
+ // object being deleted is no longer a LLMenuItemGL so a dynamic_cast will fail
+ LLMenuItemGL* itemp = static_cast<LLMenuItemGL*>(ctrl);
+
+ item_list_t::iterator found_it = std::find(mItems.begin(), mItems.end(), (itemp));
+ if (found_it != mItems.end())
{
- // SUBMENU
- LLMenuGL *submenu = (LLMenuGL*)LLMenuGL::fromXML(child, parent, factory);
- appendMenu(submenu);
- if (LLMenuGL::sMenuContainer != NULL)
- {
- submenu->updateParent(LLMenuGL::sMenuContainer);
- }
- else
- {
- submenu->updateParent(parent);
- }
+ mItems.erase(found_it);
}
- else if (child->hasName(LL_MENU_ITEM_CALL_GL_TAG) ||
- child->hasName(LL_MENU_ITEM_CHECK_GL_TAG) ||
- child->hasName(LL_MENU_ITEM_SEPARATOR_GL_TAG))
- {
- LLMenuItemGL *item = NULL;
-
- std::string type;
- std::string item_name;
- std::string source_label;
- std::string item_label;
- KEY jump_key = KEY_NONE;
-
- child->getAttributeString("type", type);
- child->getAttributeString("name", item_name);
- child->getAttributeString("label", source_label);
-
- // parse jump key out of label
- typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
- boost::char_separator<char> sep("_");
- tokenizer tokens(source_label, sep);
- tokenizer::iterator token_iter;
- S32 token_count = 0;
- for( token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
- {
- item_label += (*token_iter);
- if (token_count > 0)
- {
- jump_key = (*token_iter).c_str()[0];
- }
- ++token_count;
- }
-
-
- if (child->hasName(LL_MENU_ITEM_SEPARATOR_GL_TAG))
- {
- appendSeparator(item_name);
- }
- else
- {
- // ITEM
- if (child->hasName(LL_MENU_ITEM_CALL_GL_TAG) ||
- child->hasName(LL_MENU_ITEM_CHECK_GL_TAG))
- {
- MASK mask = 0;
-
-#ifdef LL_DARWIN
- // See if this Mac accelerator should really use the ctrl key and not get mapped to cmd
- BOOL useMacCtrl = FALSE;
- child->getAttributeBOOL("useMacCtrl", useMacCtrl);
-#endif // LL_DARWIN
-
- std::string shortcut;
- child->getAttributeString("shortcut", shortcut);
- if (shortcut.find("control") != shortcut.npos)
- {
-#ifdef LL_DARWIN
- if ( useMacCtrl )
- {
- mask |= MASK_MAC_CONTROL;
- }
-#endif // LL_DARWIN
- mask |= MASK_CONTROL;
- }
- if (shortcut.find("alt") != shortcut.npos)
- {
- mask |= MASK_ALT;
- }
- if (shortcut.find("shift") != shortcut.npos)
- {
- mask |= MASK_SHIFT;
- }
- S32 pipe_pos = shortcut.rfind("|");
- std::string key_str = shortcut.substr(pipe_pos+1);
-
- KEY key = KEY_NONE;
- LLKeyboard::keyFromString(key_str, &key);
-
- LLMenuItemCallGL *new_item;
- LLXMLNodePtr call_child;
-
- if (child->hasName(LL_MENU_ITEM_CHECK_GL_TAG))
- {
- std::string control_name;
- child->getAttributeString("control_name", control_name);
-
- new_item = new LLMenuItemCheckGL(item_name, item_label, 0, 0, control_name, parent, 0, key, mask);
-
- for (call_child = child->getFirstChild(); call_child.notNull(); call_child = call_child->getNextSibling())
- {
- if (call_child->hasName("on_check"))
- {
- std::string callback_name;
- std::string control_name;
- if (call_child->hasAttribute("function"))
- {
- call_child->getAttributeString("function", callback_name);
-
- control_name = callback_name;
-
- std::string callback_data = item_name;
- if (call_child->hasAttribute("userdata"))
- {
- call_child->getAttributeString("userdata", callback_data);
- if (!callback_data.empty())
- {
- control_name = llformat("%s(%s)", callback_name.c_str(), callback_data.c_str());
- }
- }
-
- LLSD userdata;
- userdata["control"] = control_name;
- userdata["data"] = callback_data;
-
- LLSimpleListener* callback = parent->getListenerByName(callback_name);
-
- if (!callback) continue;
-
- new_item->addListener(callback, "on_build", userdata);
- }
- else if (call_child->hasAttribute("control"))
- {
- call_child->getAttributeString("control", control_name);
- }
- else
- {
- continue;
- }
- LLControlVariable *control = parent->findControl(control_name);
- if (!control)
- {
- parent->addBoolControl(control_name, FALSE);
- }
- ((LLMenuItemCheckGL*)new_item)->setCheckedControl(control_name, parent);
- }
- }
- }
- else
- {
- new_item = new LLMenuItemCallGL(item_name, item_label, 0, 0, 0, 0, key, mask);
- }
-
- for (call_child = child->getFirstChild(); call_child.notNull(); call_child = call_child->getNextSibling())
- {
- if (call_child->hasName("on_click"))
- {
- std::string callback_name;
- call_child->getAttributeString("function", callback_name);
-
- std::string callback_data = item_name;
- if (call_child->hasAttribute("userdata"))
- {
- call_child->getAttributeString("userdata", callback_data);
- }
-
- LLSimpleListener* callback = parent->getListenerByName(callback_name);
-
- if (!callback) continue;
-
- new_item->addListener(callback, "on_click", callback_data);
- }
- if (call_child->hasName("on_enable"))
- {
- std::string callback_name;
- std::string control_name;
- if (call_child->hasAttribute("function"))
- {
- call_child->getAttributeString("function", callback_name);
-
- control_name = callback_name;
-
- std::string callback_data;
- if (call_child->hasAttribute("userdata"))
- {
- call_child->getAttributeString("userdata", callback_data);
- if (!callback_data.empty())
- {
- control_name = llformat("%s(%s)", callback_name.c_str(), callback_data.c_str());
- }
- }
-
- LLSD userdata;
- userdata["control"] = control_name;
- userdata["data"] = callback_data;
-
- LLSimpleListener* callback = parent->getListenerByName(callback_name);
-
- if (!callback) continue;
-
- new_item->addListener(callback, "on_build", userdata);
- }
- else if (call_child->hasAttribute("control"))
- {
- call_child->getAttributeString("control", control_name);
- }
- else
- {
- continue;
- }
- new_item->setEnabledControl(control_name, parent);
- }
- if (call_child->hasName("on_visible"))
- {
- std::string callback_name;
- std::string control_name;
- if (call_child->hasAttribute("function"))
- {
- call_child->getAttributeString("function", callback_name);
-
- control_name = callback_name;
-
- std::string callback_data;
- if (call_child->hasAttribute("userdata"))
- {
- call_child->getAttributeString("userdata", callback_data);
- if (!callback_data.empty())
- {
- control_name = llformat("%s(%s)", callback_name.c_str(), callback_data.c_str());
- }
- }
-
- LLSD userdata;
- userdata["control"] = control_name;
- userdata["data"] = callback_data;
- LLSimpleListener* callback = parent->getListenerByName(callback_name);
-
- if (!callback) continue;
-
- new_item->addListener(callback, "on_build", userdata);
- }
- else if (call_child->hasAttribute("control"))
- {
- call_child->getAttributeString("control", control_name);
- }
- else
- {
- continue;
- }
- new_item->setVisibleControl(control_name, parent);
- }
- }
- item = new_item;
- item->setLabel(item_label);
- if (jump_key != KEY_NONE)
- item->setJumpKey(jump_key);
- }
+ return LLUICtrl::removeChild(ctrl);
+}
- if (item != NULL)
- {
- append(item);
- }
- }
- }
+BOOL LLMenuGL::postBuild()
+{
+ createJumpKeys();
+ return LLUICtrl::postBuild();
}
// are we the childmost active menu and hence our jump keys should be enabled?
@@ -2079,77 +1810,88 @@ BOOL LLMenuGL::isOpen()
return getVisible();
}
}
-// static
-LLView* LLMenuGL::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("menu");
- node->getAttributeString("name", name);
-
- std::string label = name;
- node->getAttributeString("label", label);
- // parse jump key out of label
- std::string new_menu_label;
-
- typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
- boost::char_separator<char> sep("_");
- tokenizer tokens(label, sep);
- tokenizer::iterator token_iter;
+void LLMenuGL::scrollItemsUp()
+{
+ // Slowing down the items scrolling when arrow button is held
+ if (mScrollItemsTimer.hasExpired() && NULL != mFirstVisibleItem)
+ {
+ mScrollItemsTimer.setTimerExpirySec(.033f);
+ }
+ else
+ {
+ return;
+ }
- KEY jump_key = KEY_NONE;
- S32 token_count = 0;
- for( token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
+ item_list_t::iterator cur_item_iter;
+ item_list_t::iterator prev_item_iter;
+ for (cur_item_iter = mItems.begin(), prev_item_iter = mItems.begin(); cur_item_iter != mItems.end(); cur_item_iter++)
{
- new_menu_label += (*token_iter);
- if (token_count > 0)
+ if( (*cur_item_iter) == mFirstVisibleItem)
{
- jump_key = (*token_iter).c_str()[0];
+ break;
+ }
+ if ((*cur_item_iter)->getVisible())
+ {
+ prev_item_iter = cur_item_iter;
}
- ++token_count;
}
- BOOL opaque = FALSE;
- node->getAttributeBOOL("opaque", opaque);
-
- LLMenuGL *menu = new LLMenuGL(name, new_menu_label);
-
- menu->setJumpKey(jump_key);
-
- BOOL tear_off = FALSE;
- node->getAttributeBOOL("tear_off", tear_off);
- menu->setCanTearOff(tear_off);
+ if ((*prev_item_iter)->getVisible())
+ {
+ mFirstVisibleItem = *prev_item_iter;
+ }
+
+ mNeedsArrange = TRUE;
+ arrangeAndClear();
+}
- if (node->hasAttribute("drop_shadow"))
+void LLMenuGL::scrollItemsDown()
+{
+ // Slowing down the items scrolling when arrow button is held
+ if (mScrollItemsTimer.hasExpired())
+ {
+ mScrollItemsTimer.setTimerExpirySec(.033f);
+ }
+ else
+ {
+ return;
+ }
+
+ if (NULL == mFirstVisibleItem)
{
- BOOL drop_shadow = FALSE;
- node->getAttributeBOOL("drop_shadow", drop_shadow);
- menu->setDropShadowed(drop_shadow);
+ mFirstVisibleItem = *mItems.begin();
}
- menu->setBackgroundVisible(opaque);
- LLColor4 color(0,0,0,1);
- if (opaque && LLUICtrlFactory::getAttributeColor(node,"color", color))
+ item_list_t::iterator cur_item_iter;
+
+ for (cur_item_iter = mItems.begin(); cur_item_iter != mItems.end(); cur_item_iter++)
{
- menu->setBackgroundColor(color);
+ if( (*cur_item_iter) == mFirstVisibleItem)
+ {
+ break;
+ }
}
- BOOL create_jump_keys = FALSE;
- node->getAttributeBOOL("create_jump_keys", create_jump_keys);
+ item_list_t::iterator next_item_iter;
- LLXMLNodePtr child;
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
+ for (next_item_iter = ++cur_item_iter; next_item_iter != mItems.end(); next_item_iter++)
{
- menu->parseChildXML(child, parent, factory);
+ if( (*next_item_iter)->getVisible())
+ {
+ break;
+ }
}
- if (create_jump_keys)
+ if ((*next_item_iter)->getVisible())
{
- menu->createJumpKeys();
+ mFirstVisibleItem = *next_item_iter;
}
- return menu;
+
+ mNeedsArrange = TRUE;
+ arrangeAndClear();
}
-
// rearrange the child rects so they fit the shape of the menu.
void LLMenuGL::arrange( void )
{
@@ -2167,39 +1909,59 @@ void LLMenuGL::arrange( void )
// torn off menus are not constrained to the size of the screen
U32 max_width = getTornOff() ? U32_MAX : menu_region_rect.getWidth();
- U32 max_height = getTornOff() ? U32_MAX : menu_region_rect.getHeight();
+ U32 max_height = U32_MAX;
+ if (!getTornOff())
+ {
+ max_height = getRect().mTop - menu_region_rect.mBottom;
+ if (menu_region_rect.mTop - getRect().mTop > (S32)max_height)
+ {
+ max_height = menu_region_rect.mTop - getRect().mTop;
+ }
+ }
+
// *FIX: create the item first and then ask for its dimensions?
- S32 spillover_item_width = PLAIN_PAD_PIXELS + LLFontGL::getFontSansSerif()->getWidth( std::string("More") );
+ S32 spillover_item_width = PLAIN_PAD_PIXELS + LLFontGL::getFontSansSerif()->getWidth( std::string("More") ); // *TODO: Translate
S32 spillover_item_height = llround(LLFontGL::getFontSansSerif()->getLineHeight()) + MENU_ITEM_PADDING;
+ // Scrolling support
+ item_list_t::iterator first_visible_item_iter;
+ item_list_t::iterator first_hidden_item_iter = mItems.end();
+ S32 height_before_first_visible_item = -1;
+ S32 visible_items_height = 0;
+ U32 scrollable_items_cnt = 0;
+
if (mHorizontalLayout)
{
item_list_t::iterator item_iter;
for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
{
+ // do first so LLMenuGLItemCall can call on_visible to determine if visible
+ (*item_iter)->buildDrawLabel();
+
if ((*item_iter)->getVisible())
{
if (!getTornOff()
- && item_iter != mItems.begin() // Don't spillover the first item!
+ && *item_iter != mSpilloverBranch
&& width + (*item_iter)->getNominalWidth() > max_width - spillover_item_width)
{
// no room for any more items
createSpilloverBranch();
- item_list_t::iterator spillover_iter;
- for (spillover_iter = item_iter; spillover_iter != mItems.end(); ++spillover_iter)
+ std::vector<LLMenuItemGL*> items_to_remove;
+ std::copy(item_iter, mItems.end(), std::back_inserter(items_to_remove));
+ std::vector<LLMenuItemGL*>::iterator spillover_iter;
+ for (spillover_iter= items_to_remove.begin(); spillover_iter != items_to_remove.end(); ++spillover_iter)
{
LLMenuItemGL* itemp = (*spillover_iter);
removeChild(itemp);
- mSpilloverMenu->appendNoArrange(itemp); // *NOTE:Mani Favor addChild() in merge with skinning
+ mSpilloverMenu->addChild(itemp);
}
- mSpilloverMenu->arrange(); // *NOTE: Mani Remove line in merge with skinning/viewer2.0 branch
- mSpilloverMenu->updateParent(LLMenuGL::sMenuContainer); // *NOTE: Mani Remove line in merge with skinning/viewer2.0 branch
- mItems.erase(item_iter, mItems.end());
- mItems.push_back(mSpilloverBranch);
+
addChild(mSpilloverBranch);
+
height = llmax(height, mSpilloverBranch->getNominalHeight());
width += mSpilloverBranch->getNominalWidth();
+
break;
}
else
@@ -2214,31 +1976,38 @@ void LLMenuGL::arrange( void )
else
{
item_list_t::iterator item_iter;
+
for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
{
+ // do first so LLMenuGLItemCall can call on_visible to determine if visible
+ (*item_iter)->buildDrawLabel();
+
if ((*item_iter)->getVisible())
{
if (!getTornOff()
- && item_iter != mItems.begin() // Don't spillover the first item!
+ && !mScrollable
+ && *item_iter != mSpilloverBranch
&& height + (*item_iter)->getNominalHeight() > max_height - spillover_item_height)
{
// no room for any more items
createSpilloverBranch();
- item_list_t::iterator spillover_iter;
- for (spillover_iter= item_iter; spillover_iter != mItems.end(); ++spillover_iter)
+ std::vector<LLMenuItemGL*> items_to_remove;
+ std::copy(item_iter, mItems.end(), std::back_inserter(items_to_remove));
+ std::vector<LLMenuItemGL*>::iterator spillover_iter;
+ for (spillover_iter= items_to_remove.begin(); spillover_iter != items_to_remove.end(); ++spillover_iter)
{
LLMenuItemGL* itemp = (*spillover_iter);
removeChild(itemp);
- mSpilloverMenu->appendNoArrange(itemp); // *NOTE:Mani Favor addChild() in merge with skinning
+ mSpilloverMenu->addChild(itemp);
}
- mSpilloverMenu->arrange(); // *NOTE: Mani Remove line in merge with skinning/viewer2.0 branch
- mSpilloverMenu->updateParent(LLMenuGL::sMenuContainer); // *NOTE: Mani Remove line in merge with skinning/viewer2.0 branch
- mItems.erase(item_iter, mItems.end());
- mItems.push_back(mSpilloverBranch);
+
+
addChild(mSpilloverBranch);
+
height += mSpilloverBranch->getNominalHeight();
width = llmax( width, mSpilloverBranch->getNominalWidth() );
+
break;
}
else
@@ -2247,19 +2016,173 @@ void LLMenuGL::arrange( void )
height += (*item_iter)->getNominalHeight();
width = llmax( width, (*item_iter)->getNominalWidth() );
}
+
+ if (mScrollable)
+ {
+ // Determining visible items boundaries
+ if (NULL == mFirstVisibleItem)
+ {
+ mFirstVisibleItem = *item_iter;
+ }
+
+ if (*item_iter == mFirstVisibleItem)
+ {
+ height_before_first_visible_item = height - (*item_iter)->getNominalHeight();
+ first_visible_item_iter = item_iter;
+ scrollable_items_cnt = 0;
+ }
+
+ if (-1 != height_before_first_visible_item && 0 == visible_items_height &&
+ (++scrollable_items_cnt > mMaxScrollableItems ||
+ height - height_before_first_visible_item > max_height - spillover_item_height * 2 ))
+ {
+ first_hidden_item_iter = item_iter;
+ visible_items_height = height - height_before_first_visible_item - (*item_iter)->getNominalHeight();
+ scrollable_items_cnt--;
+ }
+ }
}
}
- }
- setRect(LLRect(getRect().mLeft, getRect().mBottom + height, getRect().mLeft + width, getRect().mBottom));
+ if (mPreferredWidth < U32_MAX)
+ width = llmin(mPreferredWidth, max_width);
+
+ if (mScrollable)
+ {
+ S32 max_items_height = max_height - spillover_item_height * 2;
+
+ if (visible_items_height == 0)
+ visible_items_height = height - height_before_first_visible_item;
+
+ // Fix mFirstVisibleItem value, if it doesn't allow to display all items, that can fit
+ if (visible_items_height < max_items_height && scrollable_items_cnt < mMaxScrollableItems)
+ {
+ item_list_t::iterator tmp_iter(first_visible_item_iter);
+ while (visible_items_height < max_items_height &&
+ scrollable_items_cnt < mMaxScrollableItems &&
+ first_visible_item_iter != mItems.begin())
+ {
+ if ((*first_visible_item_iter)->getVisible())
+ {
+ // It keeps visible item, after first_visible_item_iter
+ tmp_iter = first_visible_item_iter;
+ }
+
+ first_visible_item_iter--;
+
+ if ((*first_visible_item_iter)->getVisible())
+ {
+ visible_items_height += (*first_visible_item_iter)->getNominalHeight();
+ height_before_first_visible_item -= (*first_visible_item_iter)->getNominalHeight();
+ scrollable_items_cnt++;
+ }
+ }
+
+ // Roll back one item, that doesn't fit
+ if (visible_items_height > max_items_height)
+ {
+ visible_items_height -= (*first_visible_item_iter)->getNominalHeight();
+ height_before_first_visible_item += (*first_visible_item_iter)->getNominalHeight();
+ scrollable_items_cnt--;
+ first_visible_item_iter = tmp_iter;
+ }
+ if (!(*first_visible_item_iter)->getVisible())
+ {
+ first_visible_item_iter = tmp_iter;
+ }
+
+ mFirstVisibleItem = *first_visible_item_iter;
+ }
+ }
+ }
S32 cur_height = (S32)llmin(max_height, height);
+
+ if (mScrollable &&
+ (height_before_first_visible_item > MENU_ITEM_PADDING ||
+ height_before_first_visible_item + visible_items_height < (S32)height))
+ {
+ // Reserving 2 extra slots for arrow items
+ cur_height = visible_items_height + spillover_item_height * 2;
+ }
+
+ setRect(LLRect(getRect().mLeft, getRect().mTop, getRect().mLeft + width, getRect().mTop - cur_height));
+
S32 cur_width = 0;
+ S32 offset = 0;
+ if (mScrollable)
+ {
+ // No space for all items, creating arrow items
+ if (height_before_first_visible_item > MENU_ITEM_PADDING ||
+ height_before_first_visible_item + visible_items_height < (S32)height)
+ {
+ if (NULL == mArrowUpItem)
+ {
+ LLMenuScrollItem::Params item_params;
+ item_params.name(ARROW_UP);
+ item_params.arrow_type(LLMenuScrollItem::ARROW_UP);
+ item_params.scroll_callback.function(boost::bind(&LLMenuGL::scrollItemsUp, this));
+
+ mArrowUpItem = LLUICtrlFactory::create<LLMenuScrollItem>(item_params);
+ LLUICtrl::addChild(mArrowUpItem);
+
+ }
+ if (NULL == mArrowDownItem)
+ {
+ LLMenuScrollItem::Params item_params;
+ item_params.name(ARROW_DOWN);
+ item_params.arrow_type(LLMenuScrollItem::ARROW_DOWN);
+ item_params.scroll_callback.function(boost::bind(&LLMenuGL::scrollItemsDown, this));
+
+ mArrowDownItem = LLUICtrlFactory::create<LLMenuScrollItem>(item_params);
+ LLUICtrl::addChild(mArrowDownItem);
+ }
+
+ LLRect rect;
+ mArrowUpItem->setRect(rect.setLeftTopAndSize( 0, cur_height, width, mArrowUpItem->getNominalHeight()));
+ mArrowUpItem->setVisible(TRUE);
+ mArrowUpItem->setEnabled(height_before_first_visible_item > MENU_ITEM_PADDING);
+ mArrowUpItem->reshape(width, mArrowUpItem->getNominalHeight());
+ mArrowDownItem->setRect(rect.setLeftTopAndSize( 0, mArrowDownItem->getNominalHeight(), width, mArrowDownItem->getNominalHeight()));
+ mArrowDownItem->setVisible(TRUE);
+ mArrowDownItem->setEnabled(height_before_first_visible_item + visible_items_height < (S32)height);
+ mArrowDownItem->reshape(width, mArrowDownItem->getNominalHeight());
+
+ cur_height -= mArrowUpItem->getNominalHeight();
+
+ offset = menu_region_rect.mRight; // This moves items behind visible area
+ }
+ else
+ {
+ if (NULL != mArrowUpItem)
+ {
+ mArrowUpItem->setVisible(FALSE);
+ }
+ if (NULL != mArrowDownItem)
+ {
+ mArrowDownItem->setVisible(FALSE);
+ }
+ }
+
+ }
+
item_list_t::iterator item_iter;
for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
- {
+ {
if ((*item_iter)->getVisible())
{
+ if (mScrollable)
+ {
+ if (item_iter == first_visible_item_iter)
+ {
+ offset = 0;
+ }
+ else if (item_iter == first_hidden_item_iter)
+ {
+ offset = menu_region_rect.mRight; // This moves items behind visible area
+ }
+ }
+
// setup item rect to hold label
LLRect rect;
if (mHorizontalLayout)
@@ -2269,11 +2192,13 @@ void LLMenuGL::arrange( void )
}
else
{
- rect.setLeftTopAndSize( 0, cur_height, width, (*item_iter)->getNominalHeight());
- cur_height -= (*item_iter)->getNominalHeight();
+ rect.setLeftTopAndSize( 0 + offset, cur_height, width, (*item_iter)->getNominalHeight());
+ if (offset == 0)
+ {
+ cur_height -= (*item_iter)->getNominalHeight();
+ }
}
(*item_iter)->setRect( rect );
- (*item_iter)->buildDrawLabel();
}
}
}
@@ -2283,6 +2208,15 @@ void LLMenuGL::arrange( void )
}
}
+void LLMenuGL::arrangeAndClear( void )
+{
+ if (mNeedsArrange)
+ {
+ arrange();
+ mNeedsArrange = FALSE;
+ }
+}
+
void LLMenuGL::createSpilloverBranch()
{
if (!mSpilloverBranch)
@@ -2291,14 +2225,24 @@ void LLMenuGL::createSpilloverBranch()
delete mSpilloverMenu;
// technically, you can't tear off spillover menus, but we're passing the handle
// along just to be safe
- mSpilloverMenu = new LLMenuGL(std::string("More"), std::string("More"), mParentFloaterHandle);
+ LLMenuGL::Params p;
+ p.name("More");
+ p.label("More"); // *TODO: Translate
+ p.parent_floater(mParentFloaterHandle);
+ p.bg_color(mBackgroundColor);
+ p.bg_visible(true);
+ p.can_tear_off(false);
+ mSpilloverMenu = new LLMenuGL(p);
mSpilloverMenu->updateParent(LLMenuGL::sMenuContainer);
- // Inherit colors
- mSpilloverMenu->setBackgroundColor( mBackgroundColor );
- mSpilloverMenu->setCanTearOff(FALSE);
- mSpilloverBranch = new LLMenuItemBranchGL(std::string("More"), std::string("More"), mSpilloverMenu->getHandle());
- mSpilloverBranch->setFontStyle(LLFontGL::ITALIC);
+ LLMenuItemBranchGL::Params branch_params;
+ branch_params.name = "More";
+ branch_params.label = "More"; // *TODO: Translate
+ branch_params.branch = mSpilloverMenu;
+ branch_params.font.style = "italic";
+
+
+ mSpilloverBranch = LLUICtrlFactory::create<LLMenuItemBranchGL>(branch_params);
}
}
@@ -2309,25 +2253,15 @@ void LLMenuGL::cleanupSpilloverBranch()
// head-recursion to propagate items back up to root menu
mSpilloverMenu->cleanupSpilloverBranch();
- removeChild(mSpilloverBranch);
-
- item_list_t::iterator found_iter = std::find(mItems.begin(), mItems.end(), mSpilloverBranch);
- if (found_iter != mItems.end())
- {
- mItems.erase(found_iter);
- }
-
// pop off spillover items
while (mSpilloverMenu->getItemCount())
{
LLMenuItemGL* itemp = mSpilloverMenu->getItem(0);
mSpilloverMenu->removeChild(itemp);
- mSpilloverMenu->mItems.erase(mSpilloverMenu->mItems.begin());
// put them at the end of our own list
- mItems.push_back(itemp);
addChild(itemp);
}
-
+
// Delete the branch, and since the branch will delete the menu,
// set the menu* to null.
delete mSpilloverBranch;
@@ -2338,6 +2272,9 @@ void LLMenuGL::cleanupSpilloverBranch()
void LLMenuGL::createJumpKeys()
{
+ if (!mCreateJumpKeys) return;
+ mCreateJumpKeys = FALSE;
+
mJumpKeys.clear();
std::set<std::string> unique_words;
@@ -2414,8 +2351,8 @@ void LLMenuGL::createJumpKeys()
{
char jump_key = uppercase_word[i];
- if (LLStringOps::isDigit(jump_key) || LLStringOps::isUpper(jump_key) &&
- mJumpKeys.find(jump_key) == mJumpKeys.end())
+ if (LLStringOps::isDigit(jump_key) || (LLStringOps::isUpper(jump_key) &&
+ mJumpKeys.find(jump_key) == mJumpKeys.end()))
{
mJumpKeys.insert(std::pair<KEY, LLMenuItemGL*>(jump_key, (*item_it)));
(*item_it)->setJumpKey(jump_key);
@@ -2438,16 +2375,18 @@ void LLMenuGL::empty( void )
cleanupSpilloverBranch();
mItems.clear();
+ mFirstVisibleItem = NULL;
+ mArrowUpItem = NULL;
+ mArrowDownItem = NULL;
deleteAllChildren();
-
}
// Adjust rectangle of the menu
void LLMenuGL::setLeftAndBottom(S32 left, S32 bottom)
{
setRect(LLRect(left, getRect().mTop, getRect().mRight, bottom));
- arrange();
+ needsArrange();
}
BOOL LLMenuGL::handleJumpKey(KEY key)
@@ -2460,12 +2399,9 @@ BOOL LLMenuGL::handleJumpKey(KEY key)
// switch to keyboard navigation mode
LLMenuGL::setKeyboardMode(TRUE);
- // force highlight to close old menus and any open sub-menus
-
- //clearHoverItem();
// force highlight to close old menus and open and sub-menus
found_it->second->setHighlight(TRUE);
- found_it->second->doIt();
+ found_it->second->onCommit();
}
// if we are navigating the menus, we need to eat the keystroke
@@ -2477,30 +2413,18 @@ BOOL LLMenuGL::handleJumpKey(KEY key)
// Add the menu item to this menu.
BOOL LLMenuGL::append( LLMenuItemGL* item )
{
+ if (!item) return FALSE;
mItems.push_back( item );
- addChild( item );
- arrange();
- return TRUE;
-}
-
-// *NOTE:Mani - appendNoArrange() should be removed when merging to skinning/viewer2.0
-// Its added as a fix to a viewer 1.23 bug that has already been address by skinning work.
-BOOL LLMenuGL::appendNoArrange( LLMenuItemGL* item )
-{
- mItems.push_back( item );
- addChild( item );
+ LLUICtrl::addChild(item);
+ needsArrange();
return TRUE;
}
// add a separator to this menu
-BOOL LLMenuGL::appendSeparator( const std::string &separator_name )
+BOOL LLMenuGL::addSeparator()
{
- LLMenuItemGL* separator;
- if (separator_name.empty())
- separator = new LLMenuItemSeparatorGL(std::string("separator"));
- else
- separator = new LLMenuItemSeparatorGL(separator_name);
- return append( separator );
+ LLMenuItemGL* separator = new LLMenuItemSeparatorGL();
+ return addChild(separator);
}
// add a menu - this will create a cascading menu
@@ -2513,14 +2437,22 @@ BOOL LLMenuGL::appendMenu( LLMenuGL* menu )
}
BOOL success = TRUE;
- LLMenuItemBranchGL* branch = NULL;
- branch = new LLMenuItemBranchGL( menu->getName(), menu->getLabel(), menu->getHandle() );
- branch->setJumpKey(menu->getJumpKey());
+ LLMenuItemBranchGL::Params p;
+ p.name = menu->getName();
+ p.label = menu->getLabel();
+ p.branch = menu;
+ p.jump_key = menu->getJumpKey();
+ p.enabled_color=LLUIColorTable::instance().getColor("MenuItemEnabledColor");
+ p.disabled_color=LLUIColorTable::instance().getColor("MenuItemDisabledColor");
+ p.highlight_bg_color=LLUIColorTable::instance().getColor("MenuItemHighlightBgColor");
+ p.highlight_fg_color=LLUIColorTable::instance().getColor("MenuItemHighlightFgColor");
+
+ LLMenuItemBranchGL* branch = LLUICtrlFactory::create<LLMenuItemBranchGL>(p);
success &= append( branch );
// Inherit colors
menu->setBackgroundColor( mBackgroundColor );
-
+ menu->updateParent(LLMenuGL::sMenuContainer);
return success;
}
@@ -2558,6 +2490,7 @@ void LLMenuGL::setItemVisible( const std::string& name, BOOL visible )
if( (*item_iter)->getName() == name )
{
(*item_iter)->setVisible( visible );
+ needsArrange();
break;
}
}
@@ -2570,7 +2503,7 @@ void LLMenuGL::setItemLastSelected(LLMenuItemGL* item)
LLMenuHolderGL::setActivatedItem(item);
}
- // fix the checkmarks
+ // update enabled and checkmark status
item->buildDrawLabel();
}
@@ -2668,7 +2601,7 @@ LLMenuItemGL* LLMenuGL::highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disa
while(1)
{
// skip separators and disabled/invisible items
- if ((*next_item_iter)->getEnabled() && (*next_item_iter)->getVisible() && (*next_item_iter)->getType() != SEPARATOR_NAME)
+ if ((*next_item_iter)->getEnabled() && (*next_item_iter)->getVisible() && !dynamic_cast<LLMenuItemSeparatorGL*>(*next_item_iter))
{
if (cur_item)
{
@@ -2775,7 +2708,10 @@ void LLMenuGL::updateParent(LLView* parentp)
{
getParent()->removeChild(this);
}
- parentp->addChild(this);
+ if (parentp)
+ {
+ parentp->addChild(this);
+ }
item_list_t::iterator item_iter;
for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
{
@@ -2878,29 +2814,60 @@ BOOL LLMenuGL::handleHover( S32 x, S32 y, MASK mask )
}
}
getWindow()->setCursor(UI_CURSOR_ARROW);
+
+ // *HACK Release the mouse capture
+ // This is done to release the mouse after the Navigation Bar "Back" or "Forward" button
+ // drop-down menu is shown. Otherwise any other view won't be able to handle mouse events
+ // until the user chooses one of the drop-down menu items.
+
+ return TRUE;
+}
+
+BOOL LLMenuGL::handleScrollWheel( S32 x, S32 y, S32 clicks )
+{
+ if (!mScrollable)
+ return blockMouseEvent(x, y);
+
+ if( clicks > 0 )
+ {
+ while( clicks-- )
+ scrollItemsDown();
+ }
+ else
+ {
+ while( clicks++ )
+ scrollItemsUp();
+ }
+
return TRUE;
}
+
void LLMenuGL::draw( void )
{
+ if (mNeedsArrange)
+ {
+ arrange();
+ mNeedsArrange = FALSE;
+ }
if (mDropShadowed && !mTornOff)
{
+ static LLUICachedControl<S32> drop_shadow_floater ("DropShadowFloater", 0);
+ static LLUIColor color_drop_shadow = LLUIColorTable::instance().getColor("ColorDropShadow");
gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0,
- LLUI::sColorsGroup->getColor("ColorDropShadow"),
- LLUI::sConfigGroup->getS32("DropShadowFloater") );
+ color_drop_shadow, drop_shadow_floater );
}
- LLColor4 bg_color = mBackgroundColor;
-
if( mBgVisible )
{
- gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0, mBackgroundColor );
+ gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0, mBackgroundColor.get() );
}
LLView::draw();
}
-void LLMenuGL::drawBackground(LLMenuItemGL* itemp, LLColor4& color)
+void LLMenuGL::drawBackground(LLMenuItemGL* itemp, F32 alpha)
{
+ LLColor4 color = itemp->getHighlightBgColor() % alpha;
gGL.color4fv( color.mV );
LLRect item_rect = itemp->getRect();
gl_rect_2d( 0, item_rect.getHeight(), item_rect.getWidth(), 0);
@@ -2929,9 +2896,9 @@ void LLMenuGL::setVisible(BOOL visible)
}
}
-LLMenuGL* LLMenuGL::getChildMenuByName(const std::string& name, BOOL recurse) const
+LLMenuGL* LLMenuGL::findChildMenuByName(const std::string& name, BOOL recurse) const
{
- LLView* view = getChildView(name, recurse, FALSE);
+ LLView* view = findChildView(name, recurse);
if (view)
{
LLMenuItemBranchGL* branch = dynamic_cast<LLMenuItemBranchGL*>(view);
@@ -2970,839 +2937,71 @@ void hide_top_view( LLView* view )
}
+// x and y are the desired location for the popup, in the spawning_view's
+// coordinate frame, NOT necessarily the mouse location
// static
void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
{
- const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect();
-
- const S32 HPAD = 2;
- LLRect rect = menu->getRect();
- //LLView* cur_view = spawning_view;
- S32 left = x + HPAD;
- S32 top = y;
- spawning_view->localPointToOtherView(left, top, &left, &top, menu->getParent());
- rect.setLeftTopAndSize( left, top,
- rect.getWidth(), rect.getHeight() );
-
+ const S32 CURSOR_HEIGHT = 22; // Approximate "normal" cursor size
+ const S32 CURSOR_WIDTH = 12;
- //rect.setLeftTopAndSize(x + HPAD, y, rect.getWidth(), rect.getHeight());
- menu->setRect( rect );
+ // Save click point for detecting cursor moves before mouse-up.
+ // Must be in local coords to compare with mouseUp events.
+ // If the mouse doesn't move, the menu will stay open ala the Mac.
+ // See also LLContextMenu::show()
+ S32 mouse_x, mouse_y;
- S32 bottom;
- left = rect.mLeft;
- bottom = rect.mBottom;
- //menu->getParent()->localPointToScreen( rect.mLeft, rect.mBottom,
- // &left, &bottom );
- S32 delta_x = 0;
- S32 delta_y = 0;
- if( bottom < menu_region_rect.mBottom )
+ // Resetting scrolling position
+ if (menu->isScrollable())
{
- // At this point, we need to move the context menu to the
- // other side of the mouse.
- //delta_y = menu_region_rect.mBottom - bottom;
- delta_y = (rect.getHeight() + 2 * HPAD);
+ menu->mFirstVisibleItem = NULL;
}
- if( left > menu_region_rect.mRight - rect.getWidth() )
- {
- // At this point, we need to move the context menu to the
- // other side of the mouse.
- //delta_x = (window_width - rect.getWidth()) - x;
- delta_x = -(rect.getWidth() + 2 * HPAD);
- }
- menu->translate( delta_x, delta_y );
menu->setVisible( TRUE );
- menu->getParent()->sendChildToFront(menu);
-}
-
-//-----------------------------------------------------------------------------
-// class LLPieMenuBranch
-// A branch to another pie menu
-//-----------------------------------------------------------------------------
-class LLPieMenuBranch : public LLMenuItemGL
-{
-public:
- LLPieMenuBranch(const std::string& name, const std::string& label, LLPieMenu* branch);
-
- // called to rebuild the draw label
- virtual void buildDrawLabel( void );
-
- // doIt() - do the primary funcationality of the menu item.
- virtual void doIt( void );
-
- LLPieMenu* getBranch() { return mBranch; }
-
-protected:
- LLPieMenu* mBranch;
-};
-
-LLPieMenuBranch::LLPieMenuBranch(const std::string& name,
- const std::string& label,
- LLPieMenu* branch)
-: LLMenuItemGL( name, label, KEY_NONE, MASK_NONE ),
- mBranch( branch )
-{
- mBranch->hide(FALSE);
- mBranch->setParentMenuItem(this);
-}
-// called to rebuild the draw label
-void LLPieMenuBranch::buildDrawLabel( void )
-{
- {
- // default enablement is this -- if any of the subitems are
- // enabled, this item is enabled. JC
- U32 sub_count = mBranch->getItemCount();
- U32 i;
- BOOL any_enabled = FALSE;
- for (i = 0; i < sub_count; i++)
- {
- LLMenuItemGL* item = mBranch->getItem(i);
- item->buildDrawLabel();
- if (item->getEnabled() && !item->getDrawTextDisabled() )
- {
- any_enabled = TRUE;
- break;
- }
- }
- setDrawTextDisabled(!any_enabled);
- setEnabled(TRUE);
- }
+ // Fix menu rect if needed.
+ menu->needsArrange();
+ menu->arrangeAndClear();
- mDrawAccelLabel.clear();
- std::string st = mDrawAccelLabel;
- appendAcceleratorString( st );
- mDrawAccelLabel = st;
-
- // No special branch suffix
- mDrawBranchLabel.clear();
-}
+ LLUI::getMousePositionLocal(menu->getParent(), &mouse_x, &mouse_y);
+ LLMenuHolderGL::sContextMenuSpawnPos.set(mouse_x,mouse_y);
-// doIt() - do the primary funcationality of the menu item.
-void LLPieMenuBranch::doIt( void )
-{
- LLPieMenu *parent = (LLPieMenu *)getParent();
+ const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getRect();
- LLRect rect = parent->getRect();
- S32 center_x;
- S32 center_y;
- parent->localPointToScreen(rect.getWidth() / 2, rect.getHeight() / 2, &center_x, &center_y);
-
- parent->hide(FALSE);
- mBranch->show( center_x, center_y, FALSE );
-}
-
-//-----------------------------------------------------------------------------
-// class LLPieMenu
-// A circular menu of items, icons, etc.
-//-----------------------------------------------------------------------------
-LLPieMenu::LLPieMenu(const std::string& name, const std::string& label)
-: LLMenuGL(name, label),
- mFirstMouseDown(FALSE),
- mUseInfiniteRadius(FALSE),
- mHoverItem(NULL),
- mHoverThisFrame(FALSE),
- mHoveredAnyItem(FALSE),
- mOuterRingAlpha(1.f),
- mCurRadius(0.f),
- mRightMouseDown(FALSE)
-{
- LLMenuGL::setVisible(FALSE);
- setCanTearOff(FALSE);
-}
-
-LLPieMenu::LLPieMenu(const std::string& name)
-: LLMenuGL(name, name),
- mFirstMouseDown(FALSE),
- mUseInfiniteRadius(FALSE),
- mHoverItem(NULL),
- mHoverThisFrame(FALSE),
- mHoveredAnyItem(FALSE),
- mOuterRingAlpha(1.f),
- mCurRadius(0.f),
- mRightMouseDown(FALSE)
-{
- LLMenuGL::setVisible(FALSE);
- setCanTearOff(FALSE);
-}
-
-
-void LLPieMenu::initXML(LLXMLNodePtr node, LLView *context, LLUICtrlFactory *factory)
-{
- LLXMLNodePtr child;
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
- {
- if (child->hasName(LL_PIE_MENU_TAG))
- {
- // SUBMENU
- std::string name("menu");
- child->getAttributeString("name", name);
- std::string label(name);
- child->getAttributeString("label", label);
-
- LLPieMenu *submenu = new LLPieMenu(name, label);
- appendPieMenu(submenu);
- submenu->initXML(child, context, factory);
- }
- else
- {
- parseChildXML(child, context, factory);
- }
- }
-}
-
-// virtual
-void LLPieMenu::setVisible(BOOL visible)
-{
- if (!visible)
- {
- hide(FALSE);
- }
-}
-
-BOOL LLPieMenu::handleHover( S32 x, S32 y, MASK mask )
-{
- // This is mostly copied from the llview class, but it continues
- // the hover handle code after a hover handler has been found.
- BOOL handled = FALSE;
-
- // If we got a hover event, we've already moved the cursor
- // for any menu shifts, so subsequent mouseup messages will be in the
- // correct position. No need to correct them.
- //mShiftHoriz = 0;
- //mShiftVert = 0;
-
- // release mouse capture after short period of visibility if we're using a finite boundary
- // so that right click outside of boundary will trigger new pie menu
- if (hasMouseCapture() &&
- !mRightMouseDown &&
- mShrinkBorderTimer.getStarted() &&
- mShrinkBorderTimer.getElapsedTimeF32() >= PIE_SHRINK_TIME)
- {
- gFocusMgr.setMouseCapture(NULL);
- mUseInfiniteRadius = FALSE;
- }
-
- LLMenuItemGL *item = pieItemFromXY( x, y );
-
- if (item && item->getEnabled())
- {
- getWindow()->setCursor(UI_CURSOR_ARROW);
- lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;
- handled = TRUE;
-
- if (item != mHoverItem)
- {
- if (mHoverItem)
- {
- mHoverItem->setHighlight( FALSE );
- }
- mHoverItem = item;
- mHoverItem->setHighlight( TRUE );
-
- switch(pieItemIndexFromXY(x, y))
- {
- case 0:
- make_ui_sound("UISndPieMenuSliceHighlight0");
- break;
- case 1:
- make_ui_sound("UISndPieMenuSliceHighlight1");
- break;
- case 2:
- make_ui_sound("UISndPieMenuSliceHighlight2");
- break;
- case 3:
- make_ui_sound("UISndPieMenuSliceHighlight3");
- break;
- case 4:
- make_ui_sound("UISndPieMenuSliceHighlight4");
- break;
- case 5:
- make_ui_sound("UISndPieMenuSliceHighlight5");
- break;
- case 6:
- make_ui_sound("UISndPieMenuSliceHighlight6");
- break;
- case 7:
- make_ui_sound("UISndPieMenuSliceHighlight7");
- break;
- default:
- make_ui_sound("UISndPieMenuSliceHighlight0");
- break;
- }
- }
- mHoveredAnyItem = TRUE;
- }
- else
- {
- // clear out our selection
- if (mHoverItem)
- {
- mHoverItem->setHighlight(FALSE);
- mHoverItem = NULL;
- }
- }
-
- if( !handled && pointInView( x, y ) )
- {
- getWindow()->setCursor(UI_CURSOR_ARROW);
- lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;
- handled = TRUE;
- }
-
- mHoverThisFrame = TRUE;
-
- return handled;
-}
-
-BOOL LLPieMenu::handleMouseDown( S32 x, S32 y, MASK mask )
-{
- BOOL handled = FALSE;
- // The click was somewhere within our rectangle
- LLMenuItemGL *item = pieItemFromXY( x, y );
-
- if (item)
- {
- // lie to the item about where the click happened
- // to make sure it's within the item's rectangle
- handled = item->handleMouseDown( 0, 0, mask );
- }
- else if (!mRightMouseDown)
- {
- // call hidemenus to make sure transient selections get cleared
- ((LLMenuHolderGL*)getParent())->hideMenus();
- }
-
- // always handle mouse down as mouse up will close open menus
- return handled;
-}
-
-BOOL LLPieMenu::handleRightMouseDown(S32 x, S32 y, MASK mask)
-{
- BOOL handled = FALSE;
-
- mRightMouseDown = TRUE;
-
- // The click was somewhere within our rectangle
- LLMenuItemGL *item = pieItemFromXY( x, y );
- S32 delta_x = x /*+ mShiftHoriz*/ - getLocalRect().getCenterX();
- S32 delta_y = y /*+ mShiftVert*/ - getLocalRect().getCenterY();
- BOOL clicked_in_pie = ((delta_x * delta_x) + (delta_y * delta_y) < mCurRadius*mCurRadius) || mUseInfiniteRadius;
-
- // grab mouse if right clicking anywhere within pie (even deadzone in middle), to detect drag outside of pie
- if (clicked_in_pie)
- {
- // capture mouse cursor as if on initial menu show
- gFocusMgr.setMouseCapture(this);
- mShrinkBorderTimer.stop();
- mUseInfiniteRadius = TRUE;
- handled = TRUE;
- }
-
- if (item)
- {
- // lie to the item about where the click happened
- // to make sure it's within the item's rectangle
- if (item->handleMouseDown( 0, 0, mask ))
- {
- handled = TRUE;
- }
- }
-
- return handled;
-}
-
-BOOL LLPieMenu::handleRightMouseUp( S32 x, S32 y, MASK mask )
-{
- // release mouse capture when right mouse button released, and we're past the shrink time
- if (mShrinkBorderTimer.getStarted() &&
- mShrinkBorderTimer.getElapsedTimeF32() > PIE_SHRINK_TIME)
- {
- mUseInfiniteRadius = FALSE;
- gFocusMgr.setMouseCapture(NULL);
- }
-
- S32 delta_x = x /*+ mShiftHoriz*/ - getLocalRect().getCenterX();
- S32 delta_y = y /*+ mShiftVert*/ - getLocalRect().getCenterY();
- if (!mHoveredAnyItem && !mFirstMouseDown && (delta_x * delta_x) + (delta_y * delta_y) < PIE_CENTER_SIZE * PIE_CENTER_SIZE)
- {
- // user released right mouse button in middle of pie, interpret this as closing the menu
- sMenuContainer->hideMenus();
- return TRUE;
- }
-
-
- BOOL result = handleMouseUp( x, y, mask );
- mRightMouseDown = FALSE;
- mHoveredAnyItem = FALSE;
-
- return result;
-}
-
-BOOL LLPieMenu::handleMouseUp( S32 x, S32 y, MASK mask )
-{
- BOOL handled = FALSE;
-
- // The click was somewhere within our rectangle
- LLMenuItemGL *item = pieItemFromXY( x, y );
-
- if (item)
- {
- // lie to the item about where the click happened
- // to make sure it's within the item's rectangle
- if (item->getEnabled())
- {
- handled = item->handleMouseUp( 0, 0, mask );
- hide(TRUE);
- }
- }
- else if (!mRightMouseDown)
- {
- // call hidemenus to make sure transient selections get cleared
- ((LLMenuHolderGL*)getParent())->hideMenus();
- }
-
- if (handled)
- {
- make_ui_sound("UISndClickRelease");
- }
-
- if (!handled && !mUseInfiniteRadius)
- {
- // call hidemenus to make sure transient selections get cleared
- sMenuContainer->hideMenus();
- }
-
- if (mFirstMouseDown)
- {
- make_ui_sound("UISndPieMenuAppear");
- mFirstMouseDown = FALSE;
- }
-
- // *FIX: is this necessary?
- if (!mShrinkBorderTimer.getStarted())
- {
- mShrinkBorderTimer.start();
- }
-
- return handled;
-}
-
-
-// virtual
-void LLPieMenu::draw()
-{
- // clear hover if mouse moved away
- if (!mHoverThisFrame && mHoverItem)
- {
- mHoverItem->setHighlight(FALSE);
- mHoverItem = NULL;
- }
-
- F32 width = (F32) getRect().getWidth();
- F32 height = (F32) getRect().getHeight();
- mCurRadius = PIE_SCALE_FACTOR * llmax( width/2, height/2 );
-
- mOuterRingAlpha = mUseInfiniteRadius ? 0.f : 1.f;
- if (mShrinkBorderTimer.getStarted())
- {
- mOuterRingAlpha = clamp_rescale(mShrinkBorderTimer.getElapsedTimeF32(), 0.f, PIE_SHRINK_TIME, 0.f, 1.f);
- mCurRadius *= clamp_rescale(mShrinkBorderTimer.getElapsedTimeF32(), 0.f, PIE_SHRINK_TIME, 1.f, 1.f / PIE_SCALE_FACTOR);
- }
-
- // correct for non-square pixels
- F32 center_x = width/2;
- F32 center_y = height/2;
- S32 steps = 100;
-
- gGL.pushMatrix();
- {
- gGL.translatef(center_x, center_y, 0.f);
-
- F32 line_width = LLUI::sConfigGroup->getF32("PieMenuLineWidth");
- LLColor4 line_color = LLUI::sColorsGroup->getColor("PieMenuLineColor");
- LLColor4 bg_color = LLUI::sColorsGroup->getColor("PieMenuBgColor");
- LLColor4 selected_color = LLUI::sColorsGroup->getColor("PieMenuSelectedColor");
-
- // main body
- LLColor4 outer_color = bg_color;
- outer_color.mV[VALPHA] *= mOuterRingAlpha;
- gl_washer_2d( mCurRadius, (F32) PIE_CENTER_SIZE, steps, bg_color, outer_color );
-
- // selected wedge
- item_list_t::iterator item_iter;
- S32 i = 0;
- for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
- {
- if ((*item_iter)->getHighlight())
- {
- F32 arc_size = F_PI * 0.25f;
-
- F32 start_radians = (i * arc_size) - (arc_size * 0.5f);
- F32 end_radians = start_radians + arc_size;
-
- LLColor4 outer_color = selected_color;
- outer_color.mV[VALPHA] *= mOuterRingAlpha;
- gl_washer_segment_2d( mCurRadius, (F32)PIE_CENTER_SIZE, start_radians, end_radians, steps / 8, selected_color, outer_color );
- }
- i++;
- }
-
- LLUI::setLineWidth( line_width );
-
- // inner lines
- outer_color = line_color;
- outer_color.mV[VALPHA] *= mOuterRingAlpha;
- gl_washer_spokes_2d( mCurRadius, (F32)PIE_CENTER_SIZE, 8, line_color, outer_color );
-
- // inner circle
- gGL.color4fv( line_color.mV );
- gl_circle_2d( 0, 0, (F32)PIE_CENTER_SIZE, steps, FALSE );
-
- // outer circle
- gGL.color4fv( outer_color.mV );
- gl_circle_2d( 0, 0, mCurRadius, steps, FALSE );
-
- LLUI::setLineWidth(1.0f);
- }
- gGL.popMatrix();
-
- mHoverThisFrame = FALSE;
-
- LLView::draw();
-}
-
-void LLPieMenu::drawBackground(LLMenuItemGL* itemp, LLColor4& color)
-{
- F32 width = (F32) getRect().getWidth();
- F32 height = (F32) getRect().getHeight();
- F32 center_x = width/2;
- F32 center_y = height/2;
- S32 steps = 100;
-
- gGL.color4fv( color.mV );
- gGL.pushMatrix();
- {
- gGL.translatef(center_x - itemp->getRect().mLeft, center_y - itemp->getRect().mBottom, 0.f);
-
- item_list_t::iterator item_iter;
- S32 i = 0;
- for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
- {
- if ((*item_iter) == itemp)
- {
- F32 arc_size = F_PI * 0.25f;
-
- F32 start_radians = (i * arc_size) - (arc_size * 0.5f);
- F32 end_radians = start_radians + arc_size;
-
- LLColor4 outer_color = color;
- outer_color.mV[VALPHA] *= mOuterRingAlpha;
- gl_washer_segment_2d( mCurRadius, (F32)PIE_CENTER_SIZE, start_radians, end_radians, steps / 8, color, outer_color );
- }
- i++;
- }
- }
- gGL.popMatrix();
-}
-
-// virtual
-BOOL LLPieMenu::append(LLMenuItemGL *item)
-{
- item->setBriefItem(TRUE);
- item->setFont( LLFontGL::getFontSansSerifSmall() );
- return LLMenuGL::append(item);
-}
-
-// virtual
-BOOL LLPieMenu::appendSeparator(const std::string &separator_name)
-{
- LLMenuItemGL* separator = new LLMenuItemBlankGL();
- separator->setFont( LLFontGL::getFontSansSerifSmall() );
- return append( separator );
-}
-
-
-BOOL LLPieMenu::appendPieMenu(LLPieMenu *menu)
-{
- if (menu == this)
- {
- llerrs << "Can't attach a pie menu to itself" << llendl;
- }
- LLPieMenuBranch *item;
- item = new LLPieMenuBranch(menu->getName(), menu->getLabel(), menu);
- getParent()->addChild(item->getBranch());
- item->setFont( LLFontGL::getFontSansSerifSmall() );
- return append( item );
-}
-
-// virtual
-void LLPieMenu::arrange()
-{
- const S32 rect_height = 190;
- const S32 rect_width = 190;
-
- // all divide by 6
- const S32 CARD_X = 60;
- const S32 DIAG_X = 48;
- const S32 CARD_Y = 76;
- const S32 DIAG_Y = 42;
-
- const S32 ITEM_CENTER_X[] = { CARD_X, DIAG_X, 0, -DIAG_X, -CARD_X, -DIAG_X, 0, DIAG_X };
- const S32 ITEM_CENTER_Y[] = { 0, DIAG_Y, CARD_Y, DIAG_Y, 0, -DIAG_Y, -CARD_Y, -DIAG_Y };
-
- LLRect rect;
-
- S32 font_height = 0;
- if( mItems.size() )
- {
- font_height = (*mItems.begin())->getNominalHeight();
- }
- S32 item_width = 0;
-
-// F32 sin_delta = OO_SQRT2; // sin(45 deg)
-// F32 cos_delta = OO_SQRT2; // cos(45 deg)
-
- // TODO: Compute actual bounding rect for menu
-
- // HACK: casting away const. Should use setRect or some helper function instead.
- const_cast<LLRect&>(getRect()).setOriginAndSize(getRect().mLeft, getRect().mBottom, rect_width, rect_height );
-
- // place items around a circle, with item 0 at positive X,
- // rotating counter-clockwise
- item_list_t::iterator item_iter;
- S32 i = 0;
- for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
- {
- LLMenuItemGL *item = *item_iter;
-
- item_width = item->getNominalWidth();
-
- // Put in the right place around a circle centered at 0,0
- rect.setCenterAndSize(ITEM_CENTER_X[i],
- ITEM_CENTER_Y[i],
- item_width, font_height );
-
- // Correct for the actual rectangle size
- rect.translate( rect_width/2, rect_height/2 );
-
- item->setRect( rect );
-
- // Make sure enablement is correct
- item->buildDrawLabel();
- i++;
- }
-}
-
-LLMenuItemGL *LLPieMenu::pieItemFromXY(S32 x, S32 y)
-{
- // We might have shifted this menu on draw. If so, we need
- // to shift over mouseup events until we get a hover event.
- //x += mShiftHoriz;
- //y += mShiftVert;
-
- // An arc of the pie menu is 45 degrees
- const F32 ARC_DEG = 45.f;
- S32 delta_x = x - getRect().getWidth() / 2;
- S32 delta_y = y - getRect().getHeight() / 2;
-
- // circle safe zone in the center
- S32 dist_squared = delta_x*delta_x + delta_y*delta_y;
- if (dist_squared < PIE_CENTER_SIZE*PIE_CENTER_SIZE)
- {
- return NULL;
- }
-
- // infinite radius is only used with right clicks
- S32 radius = llmax( getRect().getWidth()/2, getRect().getHeight()/2 );
- if (!(mUseInfiniteRadius && mRightMouseDown) && dist_squared > radius * radius)
- {
- return NULL;
- }
-
- F32 angle = RAD_TO_DEG * (F32) atan2((F32)delta_y, (F32)delta_x);
-
- // rotate marks CCW so that east = [0, ARC_DEG) instead of
- // [-ARC_DEG/2, ARC_DEG/2)
- angle += ARC_DEG / 2.f;
-
- // make sure we're only using positive angles
- if (angle < 0.f) angle += 360.f;
-
- S32 which = S32( angle / ARC_DEG );
-
- if (0 <= which && which < (S32)mItems.size() )
- {
- item_list_t::iterator item_iter;
- for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
- {
- if (which == 0)
- {
- return (*item_iter);
- }
- which--;
- }
- }
-
- return NULL;
-}
-
-S32 LLPieMenu::pieItemIndexFromXY(S32 x, S32 y)
-{
- // An arc of the pie menu is 45 degrees
- const F32 ARC_DEG = 45.f;
- // correct for non-square pixels
- S32 delta_x = x - getRect().getWidth() / 2;
- S32 delta_y = y - getRect().getHeight() / 2;
-
- // circle safe zone in the center
- if (delta_x*delta_x + delta_y*delta_y < PIE_CENTER_SIZE*PIE_CENTER_SIZE)
- {
- return -1;
- }
-
- F32 angle = RAD_TO_DEG * (F32) atan2((F32)delta_y, (F32)delta_x);
-
- // rotate marks CCW so that east = [0, ARC_DEG) instead of
- // [-ARC_DEG/2, ARC_DEG/2)
- angle += ARC_DEG / 2.f;
-
- // make sure we're only using positive angles
- if (angle < 0.f) angle += 360.f;
-
- S32 which = S32( angle / ARC_DEG );
- return which;
-}
-
-void LLPieMenu::show(S32 x, S32 y, BOOL mouse_down)
-{
- S32 width = getRect().getWidth();
- S32 height = getRect().getHeight();
-
- const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect();
-
- LLView* parent_view = getParent();
- BOOL moved = FALSE;
-
- S32 local_x, local_y;
- parent_view->screenPointToLocal(x, y, &local_x, &local_y);
-
- // HACK: casting away const. Should use setRect or some helper function instead.
- const_cast<LLRect&>(getRect()).setCenterAndSize(local_x, local_y, width, height);
- arrange();
-
- // Adjust the pie rectangle to keep it on screen
- if (getRect().mLeft < menu_region_rect.mLeft)
- {
- //mShiftHoriz = menu_region_rect.mLeft - getRect().mLeft;
- //getRect().translate( mShiftHoriz, 0 );
- // HACK: casting away const. Should use setRect or some helper function instead.
- const_cast<LLRect&>(getRect()).translate( menu_region_rect.mLeft - getRect().mLeft, 0 );
- moved = TRUE;
- }
-
- if (getRect().mRight > menu_region_rect.mRight)
- {
- //mShiftHoriz = menu_region_rect.mRight - getRect().mRight;
- //getRect().translate( mShiftHoriz, 0);
- // HACK: casting away const. Should use setRect or some helper function instead.
- const_cast<LLRect&>(getRect()).translate( menu_region_rect.mRight - getRect().mRight, 0 );
- moved = TRUE;
- }
-
- if (getRect().mBottom < menu_region_rect.mBottom)
- {
- //mShiftVert = menu_region_rect.mBottom - getRect().mBottom;
- //getRect().translate( 0, mShiftVert );
- // HACK: casting away const. Should use setRect or some helper function instead.
- const_cast<LLRect&>(getRect()).translate( 0, menu_region_rect.mBottom - getRect().mBottom );
- moved = TRUE;
- }
-
-
- if (getRect().mTop > menu_region_rect.mTop)
- {
- //mShiftVert = menu_region_rect.mTop - getRect().mTop;
- //getRect().translate( 0, mShiftVert );
- // HACK: casting away const. Should use setRect or some helper function instead.
- const_cast<LLRect&>(getRect()).translate( 0, menu_region_rect.mTop - getRect().mTop );
- moved = TRUE;
- }
-
- // If we had to relocate the pie menu, put the cursor in the
- // center of its rectangle
- if (moved)
- {
- LLCoordGL center;
- center.mX = (getRect().mLeft + getRect().mRight) / 2;
- center.mY = (getRect().mTop + getRect().mBottom) / 2;
-
- LLUI::setCursorPositionLocal(getParent(), center.mX, center.mY);
- }
-
- // *FIX: what happens when mouse buttons reversed?
- mRightMouseDown = mouse_down;
- mFirstMouseDown = mouse_down;
- mUseInfiniteRadius = TRUE;
- mHoveredAnyItem = FALSE;
-
- if (!mFirstMouseDown)
- {
- make_ui_sound("UISndPieMenuAppear");
- }
-
- LLView::setVisible(TRUE);
-
- // we want all mouse events in case user does quick right click again off of pie menu
- // rectangle, to support gestural menu traversal
- gFocusMgr.setMouseCapture(this);
-
- if (mouse_down)
- {
- mShrinkBorderTimer.stop();
- }
- else
- {
- mShrinkBorderTimer.start();
- }
-}
-
-void LLPieMenu::hide(BOOL item_selected)
-{
- if (!getVisible()) return;
+ const S32 HPAD = 2;
+ LLRect rect = menu->getRect();
+ S32 left = x + HPAD;
+ S32 top = y;
+ spawning_view->localPointToOtherView(left, top, &left, &top, menu->getParent());
+ rect.setLeftTopAndSize( left, top,
+ rect.getWidth(), rect.getHeight() );
+ menu->setRect( rect );
- if (mHoverItem)
- {
- mHoverItem->setHighlight( FALSE );
- mHoverItem = NULL;
- }
- make_ui_sound("UISndPieMenuHide");
+ // Adjust context menu to fit onscreen
+ LLRect mouse_rect;
+ const S32 MOUSE_CURSOR_PADDING = 5;
+ mouse_rect.setLeftTopAndSize(mouse_x - MOUSE_CURSOR_PADDING,
+ mouse_y + MOUSE_CURSOR_PADDING,
+ CURSOR_WIDTH + MOUSE_CURSOR_PADDING * 2,
+ CURSOR_HEIGHT + MOUSE_CURSOR_PADDING * 2);
+ menu->translateIntoRectWithExclusion( menu_region_rect, mouse_rect, FALSE );
+ menu->getParent()->sendChildToFront(menu);
- mFirstMouseDown = FALSE;
- mRightMouseDown = FALSE;
- mUseInfiniteRadius = FALSE;
- mHoveredAnyItem = FALSE;
- LLView::setVisible(FALSE);
- gFocusMgr.setMouseCapture(NULL);
}
///============================================================================
/// Class LLMenuBarGL
///============================================================================
-static LLRegisterWidget<LLMenuBarGL> r2("menu_bar");
+static LLDefaultChildRegistry::Register<LLMenuBarGL> r2("menu_bar");
-// Default constructor
-LLMenuBarGL::LLMenuBarGL( const std::string& name ) : LLMenuGL ( name, name )
-{
- mHorizontalLayout = TRUE;
- setCanTearOff(FALSE);
- mKeepFixedSize = TRUE;
- mAltKeyTrigger = FALSE;
-}
+LLMenuBarGL::LLMenuBarGL( const Params& p )
+: LLMenuGL(p),
+ mAltKeyTrigger(FALSE)
+{}
// Default destructor
LLMenuBarGL::~LLMenuBarGL()
@@ -3811,108 +3010,6 @@ LLMenuBarGL::~LLMenuBarGL()
mAccelerators.clear();
}
-// virtual
-LLXMLNodePtr LLMenuBarGL::getXML(bool save_children) const
-{
- // Sorty of hacky: reparent items to this and then back at the end of the export
- LLView *orig_parent = NULL;
- item_list_t::const_iterator item_iter;
- for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
- {
- LLMenuItemGL* child = *item_iter;
- LLMenuItemBranchGL* branch = (LLMenuItemBranchGL*)child;
- LLMenuGL *menu = branch->getBranch();
- orig_parent = menu->getParent();
- menu->updateParent((LLView *)this);
- }
-
- LLXMLNodePtr node = LLMenuGL::getXML();
-
- for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
- {
- LLMenuItemGL* child = *item_iter;
- LLMenuItemBranchGL* branch = (LLMenuItemBranchGL*)child;
- LLMenuGL *menu = branch->getBranch();
- menu->updateParent(orig_parent);
- }
-
- return node;
-}
-
-LLView* LLMenuBarGL::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("menu");
- node->getAttributeString("name", name);
-
- BOOL opaque = FALSE;
- node->getAttributeBOOL("opaque", opaque);
-
- LLMenuBarGL *menubar = new LLMenuBarGL(name);
-
- LLHandle<LLFloater> parent_handle;
- LLFloater* parent_floater = dynamic_cast<LLFloater*>(parent);
- if (parent_floater)
- {
- parent_handle = parent_floater->getHandle();
- }
-
- // We need to have the rect early so that it's around when building
- // the menu items
- LLRect view_rect;
- createRect(node, view_rect, parent, menubar->getRequiredRect());
- menubar->setRect(view_rect);
-
- if (node->hasAttribute("drop_shadow"))
- {
- BOOL drop_shadow = FALSE;
- node->getAttributeBOOL("drop_shadow", drop_shadow);
- menubar->setDropShadowed(drop_shadow);
- }
-
- menubar->setBackgroundVisible(opaque);
- LLColor4 color(0,0,0,0);
- if (opaque && LLUICtrlFactory::getAttributeColor(node,"color", color))
- {
- menubar->setBackgroundColor(color);
- }
-
- LLXMLNodePtr child;
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
- {
- if (child->hasName("menu"))
- {
- LLMenuGL *menu = (LLMenuGL*)LLMenuGL::fromXML(child, parent, factory);
- // because of lazy initialization, have to disable tear off functionality
- // and then re-enable with proper parent handle
- if (menu->getCanTearOff())
- {
- menu->setCanTearOff(FALSE);
- menu->setCanTearOff(TRUE, parent_handle);
- }
- menubar->appendMenu(menu);
- if (LLMenuGL::sMenuContainer != NULL)
- {
- menu->updateParent(LLMenuGL::sMenuContainer);
- }
- else
- {
- menu->updateParent(parent);
- }
- }
- }
-
- menubar->initFromXML(node, parent);
-
- BOOL create_jump_keys = FALSE;
- node->getAttributeBOOL("create_jump_keys", create_jump_keys);
- if (create_jump_keys)
- {
- menubar->createJumpKeys();
- }
-
- return menubar;
-}
-
BOOL LLMenuBarGL::handleAcceleratorKey(KEY key, MASK mask)
{
if (getHighlightedItem() && mask == MASK_NONE)
@@ -3949,7 +3046,8 @@ BOOL LLMenuBarGL::handleAcceleratorKey(KEY key, MASK mask)
BOOL LLMenuBarGL::handleKeyHere(KEY key, MASK mask)
{
- if(key == KEY_ALT && !gKeyboard->getKeyRepeated(key) && LLUI::sConfigGroup->getBOOL("UseAltKeyForMenus"))
+ static LLUICachedControl<bool> use_altkey_for_menus ("UseAltKeyForMenus", 0);
+ if(key == KEY_ALT && !gKeyboard->getKeyRepeated(key) && use_altkey_for_menus)
{
mAltKeyTrigger = TRUE;
}
@@ -3982,7 +3080,7 @@ BOOL LLMenuBarGL::handleJumpKey(KEY key)
LLMenuGL::setKeyboardMode(TRUE);
found_it->second->setHighlight(TRUE);
- found_it->second->doIt();
+ found_it->second->onCommit();
}
return TRUE;
}
@@ -3999,19 +3097,6 @@ BOOL LLMenuBarGL::handleMouseDown(S32 x, S32 y, MASK mask)
return LLMenuGL::handleMouseDown(x, y, mask);
}
-BOOL LLMenuBarGL::handleRightMouseDown(S32 x, S32 y, MASK mask)
-{
- // clicks on menu bar closes existing menus from other contexts but leave
- // own menu open so that we get toggle behavior
- if (!getHighlightedItem() || !getHighlightedItem()->isActive())
- {
- LLMenuGL::sMenuContainer->hideMenus();
- }
-
- return LLMenuGL::handleMouseDown(x, y, mask);
-}
-
-
void LLMenuBarGL::draw()
{
LLMenuItemGL* itemp = getHighlightedItem();
@@ -4029,6 +3114,7 @@ void LLMenuBarGL::draw()
LLMenuGL::draw();
}
+
void LLMenuBarGL::checkMenuTrigger()
{
// has the ALT key been pressed and subsequently released?
@@ -4036,7 +3122,8 @@ void LLMenuBarGL::checkMenuTrigger()
{
// if alt key was released quickly, treat it as a menu access key
// otherwise it was probably an Alt-zoom or similar action
- if (gKeyboard->getKeyElapsedTime(KEY_ALT) <= LLUI::sConfigGroup->getF32("MenuAccessKeyTime") ||
+ static LLUICachedControl<F32> menu_access_key_time ("MenuAccessKeyTime", 0);
+ if (gKeyboard->getKeyElapsedTime(KEY_ALT) <= menu_access_key_time ||
gKeyboard->getKeyElapsedFrameCount(KEY_ALT) < 2)
{
if (getHighlightedItem())
@@ -4105,7 +3192,7 @@ S32 LLMenuBarGL::getRightmostMenuEdge()
}
// add a vertical separator to this menu
-BOOL LLMenuBarGL::appendSeparator( const std::string &separator_name )
+BOOL LLMenuBarGL::addSeparator()
{
LLMenuItemGL* separator = new LLMenuItemVerticalSeparatorGL();
return append( separator );
@@ -4122,11 +3209,23 @@ BOOL LLMenuBarGL::appendMenu( LLMenuGL* menu )
BOOL success = TRUE;
- LLMenuItemBranchGL* branch = NULL;
- branch = new LLMenuItemBranchDownGL( menu->getName(), menu->getLabel(), menu->getHandle());
+ // *TODO: Hack! Fix this
+ LLMenuItemBranchDownGL::Params p;
+ p.name = menu->getName();
+ p.label = menu->getLabel();
+ p.visible = menu->getVisible();
+ p.branch = menu;
+ p.enabled_color=LLUIColorTable::instance().getColor("MenuItemEnabledColor");
+ p.disabled_color=LLUIColorTable::instance().getColor("MenuItemDisabledColor");
+ p.highlight_bg_color=LLUIColorTable::instance().getColor("MenuItemHighlightBgColor");
+ p.highlight_fg_color=LLUIColorTable::instance().getColor("MenuItemHighlightFgColor");
+
+ LLMenuItemBranchDownGL* branch = LLUICtrlFactory::create<LLMenuItemBranchDownGL>(p);
success &= branch->addToAcceleratorList(&mAccelerators);
success &= append( branch );
branch->setJumpKey(branch->getJumpKey());
+ menu->updateParent(LLMenuGL::sMenuContainer);
+
return success;
}
@@ -4172,7 +3271,7 @@ BOOL LLMenuBarGL::handleHover( S32 x, S32 y, MASK mask )
handled = TRUE;
if (active_menu && active_menu != viewp)
{
- ((LLMenuItemGL*)viewp)->doIt();
+ ((LLMenuItemGL*)viewp)->onCommit();
LLMenuGL::setKeyboardMode(FALSE);
}
LLMenuGL::setKeyboardMode(FALSE);
@@ -4203,23 +3302,15 @@ BOOL LLMenuBarGL::handleHover( S32 x, S32 y, MASK mask )
///============================================================================
/// Class LLMenuHolderGL
///============================================================================
-LLMenuHolderGL::LLMenuHolderGL()
- : LLPanel(std::string("Menu Holder"))
-{
- setMouseOpaque(FALSE);
- sItemActivationTimer.stop();
- mCanHide = TRUE;
-}
+LLCoordGL LLMenuHolderGL::sContextMenuSpawnPos(S32_MAX, S32_MAX);
-LLMenuHolderGL::LLMenuHolderGL(const std::string& name, const LLRect& rect, BOOL mouse_opaque, U32 follows)
-: LLPanel(name, rect, FALSE)
+LLMenuHolderGL::LLMenuHolderGL(const LLMenuHolderGL::Params& p)
+ : LLPanel(p)
{
- setMouseOpaque(mouse_opaque);
sItemActivationTimer.stop();
mCanHide = TRUE;
}
-
void LLMenuHolderGL::draw()
{
LLView::draw();
@@ -4234,16 +3325,11 @@ void LLMenuHolderGL::draw()
selecteditem->localRectToOtherView(selecteditem->getLocalRect(), &item_rect, this);
F32 interpolant = sItemActivationTimer.getElapsedTimeF32() / ACTIVATE_HIGHLIGHT_TIME;
- F32 alpha = lerp(LLMenuItemGL::getHighlightBGColor().mV[VALPHA], 0.f, interpolant);
- LLColor4 bg_color(LLMenuItemGL::getHighlightBGColor().mV[VRED],
- LLMenuItemGL::getHighlightBGColor().mV[VGREEN],
- LLMenuItemGL::getHighlightBGColor().mV[VBLUE],
- alpha);
LLUI::pushMatrix();
{
LLUI::translate((F32)item_rect.mLeft, (F32)item_rect.mBottom, 0.f);
- selecteditem->getMenu()->drawBackground(selecteditem, bg_color);
+ selecteditem->getMenu()->drawBackground(selecteditem, interpolant);
selecteditem->draw();
}
LLUI::popMatrix();
@@ -4272,6 +3358,60 @@ BOOL LLMenuHolderGL::handleRightMouseDown( S32 x, S32 y, MASK mask )
return handled;
}
+// This occurs when you mouse-down to spawn a context menu, hold the button
+// down, move off the menu, then mouse-up. We want this to close the menu.
+BOOL LLMenuHolderGL::handleRightMouseUp( S32 x, S32 y, MASK mask )
+{
+ const S32 SLOP = 2;
+ S32 spawn_dx = (x - sContextMenuSpawnPos.mX);
+ S32 spawn_dy = (y - sContextMenuSpawnPos.mY);
+ if (-SLOP <= spawn_dx && spawn_dx <= SLOP
+ && -SLOP <= spawn_dy && spawn_dy <= SLOP)
+ {
+ // we're still inside the slop region from spawning this menu
+ // so interpret the mouse-up as a single-click to show and leave on
+ // screen
+ sContextMenuSpawnPos.set(S32_MAX, S32_MAX);
+ return TRUE;
+ }
+
+ BOOL handled = LLView::childrenHandleRightMouseUp(x, y, mask) != NULL;
+ if (!handled)
+ {
+ // clicked off of menu, hide them all
+ hideMenus();
+ }
+ return handled;
+}
+
+BOOL LLMenuHolderGL::handleKey(KEY key, MASK mask, BOOL called_from_parent)
+{
+ BOOL handled = false;
+ LLMenuGL* const pMenu = dynamic_cast<LLMenuGL*>(getVisibleMenu());
+
+ if (pMenu)
+ {
+ //handle ESCAPE and RETURN key
+ handled = LLPanel::handleKey(key, mask, called_from_parent);
+ if (!handled)
+ {
+ if (pMenu->getHighlightedItem())
+ {
+ handled = pMenu->handleKey(key, mask, TRUE);
+ }
+ else
+ {
+ //highlight first enabled one
+ pMenu->highlightNextItem(NULL);
+ handled = true;
+ }
+ }
+ }
+
+ return handled;
+
+}
+
void LLMenuHolderGL::reshape(S32 width, S32 height, BOOL called_from_parent)
{
if (width != getRect().getWidth() || height != getRect().getHeight())
@@ -4281,17 +3421,17 @@ void LLMenuHolderGL::reshape(S32 width, S32 height, BOOL called_from_parent)
LLView::reshape(width, height, called_from_parent);
}
-BOOL LLMenuHolderGL::hasVisibleMenu() const
+LLView* const LLMenuHolderGL::getVisibleMenu() const
{
for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
{
LLView* viewp = *child_it;
if (viewp->getVisible() && dynamic_cast<LLMenuBarGL*>(viewp) == NULL)
{
- return TRUE;
+ return viewp;
}
}
- return FALSE;
+ return NULL;
}
@@ -4334,51 +3474,60 @@ void LLMenuHolderGL::setActivatedItem(LLMenuItemGL* item)
/// Class LLTearOffMenu
///============================================================================
LLTearOffMenu::LLTearOffMenu(LLMenuGL* menup) :
- LLFloater(menup->getName(), LLRect(0, 100, 100, 0), menup->getLabel(), FALSE, DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT, FALSE, FALSE)
+ LLFloater(LLSD())
{
+ S32 floater_header_size = getHeaderHeight();
+
+ setName(menup->getName());
+ setTitle(menup->getLabel());
+ setCanMinimize(FALSE);
// flag menu as being torn off
menup->setTornOff(TRUE);
// update menu layout as torn off menu (no spillover menus)
- menup->arrange();
+ menup->needsArrange();
LLRect rect;
menup->localRectToOtherView(LLRect(-1, menup->getRect().getHeight(), menup->getRect().getWidth() + 3, 0), &rect, gFloaterView);
// make sure this floater is big enough for menu
- mTargetHeight = (F32)(rect.getHeight() + LLFLOATER_HEADER_SIZE + 5);
+ mTargetHeight = (F32)(rect.getHeight() + floater_header_size);
reshape(rect.getWidth(), rect.getHeight());
setRect(rect);
// attach menu to floater
- menup->setFollowsAll();
+ menup->setFollows( FOLLOWS_LEFT | FOLLOWS_BOTTOM );
mOldParent = menup->getParent();
addChild(menup);
menup->setVisible(TRUE);
- menup->translate(-menup->getRect().mLeft + 1, -menup->getRect().mBottom + 1);
+ LLRect menu_rect = menup->getRect();
+ menu_rect.setOriginAndSize( 1, 1,
+ menu_rect.getWidth(), menu_rect.getHeight());
+ menup->setRect(menu_rect);
menup->setDropShadowed(FALSE);
mMenu = menup;
// highlight first item (tear off item will be disabled)
mMenu->highlightNextItem(NULL);
+
+ // Can't do this in postBuild() because that is only called for floaters
+ // constructed from XML.
+ mCloseSignal.connect(boost::bind(&LLTearOffMenu::closeTearOff, this));
}
+LLTearOffMenu::~LLTearOffMenu()
+{
+}
void LLTearOffMenu::draw()
{
mMenu->setBackgroundVisible(isBackgroundOpaque());
- mMenu->arrange();
+ mMenu->needsArrange();
if (getRect().getHeight() != mTargetHeight)
{
// animate towards target height
reshape(getRect().getWidth(), llceil(lerp((F32)getRect().getHeight(), mTargetHeight, LLCriticalDamp::getInterpolant(0.05f))));
}
- else
- {
- // when in stasis, remain big enough to hold menu contents
- mTargetHeight = (F32)(mMenu->getRect().getHeight() + LLFLOATER_HEADER_SIZE + 4);
- reshape(mMenu->getRect().getWidth() + 3, mMenu->getRect().getHeight() + LLFLOATER_HEADER_SIZE + 5);
- }
LLFloater::draw();
}
@@ -4455,12 +3604,12 @@ LLTearOffMenu* LLTearOffMenu::create(LLMenuGL* menup)
LLTearOffMenu* tearoffp = new LLTearOffMenu(menup);
// keep onscreen
gFloaterView->adjustToFitScreen(tearoffp, FALSE);
- tearoffp->open(); /* Flawfinder: ignore */
+ tearoffp->openFloater(LLSD());
return tearoffp;
}
-void LLTearOffMenu::onClose(bool app_quitting)
+void LLTearOffMenu::closeTearOff()
{
removeChild(mMenu);
mOldParent->addChild(mMenu);
@@ -4470,6 +3619,342 @@ void LLTearOffMenu::onClose(bool app_quitting)
mMenu->setVisible(FALSE);
mMenu->setTornOff(FALSE);
mMenu->setDropShadowed(TRUE);
- destroy();
+}
+
+
+//-----------------------------------------------------------------------------
+// class LLContextMenuBranch
+// A branch to another context menu
+//-----------------------------------------------------------------------------
+class LLContextMenuBranch : public LLMenuItemGL
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
+ {
+ Mandatory<LLContextMenu*> branch;
+ };
+
+ LLContextMenuBranch(const Params&);
+
+ virtual ~LLContextMenuBranch()
+ {
+ delete mBranch;
+ }
+
+ // called to rebuild the draw label
+ virtual void buildDrawLabel( void );
+
+ // onCommit() - do the primary funcationality of the menu item.
+ virtual void onCommit( void );
+
+ LLContextMenu* getBranch() { return mBranch; }
+ void setHighlight( BOOL highlight );
+
+protected:
+ void showSubMenu();
+
+ LLContextMenu* mBranch;
+};
+
+LLContextMenuBranch::LLContextMenuBranch(const LLContextMenuBranch::Params& p)
+: LLMenuItemGL(p),
+ mBranch( p.branch )
+{
+ mBranch->hide();
+ mBranch->setParentMenuItem(this);
+}
+
+// called to rebuild the draw label
+void LLContextMenuBranch::buildDrawLabel( void )
+{
+ {
+ // default enablement is this -- if any of the subitems are
+ // enabled, this item is enabled. JC
+ U32 sub_count = mBranch->getItemCount();
+ U32 i;
+ BOOL any_enabled = FALSE;
+ for (i = 0; i < sub_count; i++)
+ {
+ LLMenuItemGL* item = mBranch->getItem(i);
+ item->buildDrawLabel();
+ if (item->getEnabled() && !item->getDrawTextDisabled() )
+ {
+ any_enabled = TRUE;
+ break;
+ }
+ }
+ setDrawTextDisabled(!any_enabled);
+ setEnabled(TRUE);
+ }
+
+ mDrawAccelLabel.clear();
+ std::string st = mDrawAccelLabel;
+ appendAcceleratorString( st );
+ mDrawAccelLabel = st;
+
+ // No special branch suffix
+ mDrawBranchLabel.clear();
+}
+
+void LLContextMenuBranch::showSubMenu()
+{
+ S32 center_x;
+ S32 center_y;
+ localPointToScreen(getRect().getWidth(), getRect().getHeight() , &center_x, &center_y);
+ mBranch->show( center_x, center_y);
+}
+
+// onCommit() - do the primary funcationality of the menu item.
+void LLContextMenuBranch::onCommit( void )
+{
+ showSubMenu();
+
+}
+void LLContextMenuBranch::setHighlight( BOOL highlight )
+{
+ if (highlight == getHighlight()) return;
+ LLMenuItemGL::setHighlight(highlight);
+ if( highlight )
+ {
+ showSubMenu();
+ }
+ else
+ {
+ mBranch->hide();
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+//-----------------------------------------------------------------------------
+// class LLContextMenu
+// A context menu
+//-----------------------------------------------------------------------------
+static LLDefaultChildRegistry::Register<LLContextMenu> context_menu_register("context_menu");
+static MenuRegistry::Register<LLContextMenu> context_menu_register2("context_menu");
+
+
+LLContextMenu::LLContextMenu(const Params& p)
+: LLMenuGL(p),
+ mHoveredAnyItem(FALSE),
+ mHoverItem(NULL)
+{
+ //setBackgroundVisible(TRUE);
+}
+
+void LLContextMenu::setVisible(BOOL visible)
+{
+ if (!visible)
+ hide();
+}
+
+// Takes cursor position in screen space?
+void LLContextMenu::show(S32 x, S32 y)
+{
+ // Save click point for detecting cursor moves before mouse-up.
+ // Must be in local coords to compare with mouseUp events.
+ // If the mouse doesn't move, the menu will stay open ala the Mac.
+ // See also LLMenuGL::showPopup()
+ LLMenuHolderGL::sContextMenuSpawnPos.set(x,y);
+
+ arrangeAndClear();
+
+ S32 width = getRect().getWidth();
+ S32 height = getRect().getHeight();
+ const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect();
+ LLView* parent_view = getParent();
+
+ // Open upwards if menu extends past bottom
+ if (y - height < menu_region_rect.mBottom)
+ {
+ if (getParentMenuItem()) // Adjust if this is a submenu
+ {
+ y += height - getParentMenuItem()->getNominalHeight();
+ }
+ else
+ {
+ y += height;
+ }
+ }
+
+ // Open out to the left if menu extends past right edge
+ if (x + width > menu_region_rect.mRight)
+ {
+ if (getParentMenuItem())
+ {
+ x -= getParentMenuItem()->getRect().getWidth() + width;
+ }
+ else
+ {
+ x -= width;
+ }
+ }
+
+ S32 local_x, local_y;
+ parent_view->screenPointToLocal(x, y, &local_x, &local_y);
+
+ LLRect rect;
+ rect.setLeftTopAndSize(local_x, local_y, width, height);
+ setRect(rect);
+ arrange();
+
+ LLView::setVisible(TRUE);
+}
+
+void LLContextMenu::hide()
+{
+ if (!getVisible()) return;
+
+ LLView::setVisible(FALSE);
+
+ if (mHoverItem)
+ {
+ mHoverItem->setHighlight( FALSE );
+ }
+ mHoverItem = NULL;
+}
+
+
+BOOL LLContextMenu::handleHover( S32 x, S32 y, MASK mask )
+{
+ LLMenuGL::handleHover(x,y,mask);
+
+ BOOL handled = FALSE;
+
+ LLMenuItemGL *item = getHighlightedItem();
+
+ if (item && item->getEnabled())
+ {
+ getWindow()->setCursor(UI_CURSOR_ARROW);
+ handled = TRUE;
+
+ if (item != mHoverItem)
+ {
+ if (mHoverItem)
+ {
+ mHoverItem->setHighlight( FALSE );
+ }
+ mHoverItem = item;
+ mHoverItem->setHighlight( TRUE );
+ }
+ mHoveredAnyItem = TRUE;
+ }
+ else
+ {
+ // clear out our selection
+ if (mHoverItem)
+ {
+ mHoverItem->setHighlight(FALSE);
+ mHoverItem = NULL;
+ }
+ }
+
+ if( !handled && pointInView( x, y ) )
+ {
+ getWindow()->setCursor(UI_CURSOR_ARROW);
+ handled = TRUE;
+ }
+
+ return handled;
+}
+
+// handleMouseDown and handleMouseUp are handled by LLMenuGL
+
+
+BOOL LLContextMenu::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = FALSE;
+
+ // The click was somewhere within our rectangle
+ LLMenuItemGL *item = getHighlightedItem();
+
+ S32 local_x = x - getRect().mLeft;
+ S32 local_y = y - getRect().mBottom;
+
+ BOOL clicked_in_menu = pointInView(local_x, local_y) ;
+
+ // grab mouse if right clicking anywhere within pie (even deadzone in middle), to detect drag outside of pie
+ if (clicked_in_menu)
+ {
+ // capture mouse cursor as if on initial menu show
+ handled = TRUE;
+ }
+
+ if (item)
+ {
+ // lie to the item about where the click happened
+ // to make sure it's within the item's rectangle
+ if (item->handleMouseDown( 0, 0, mask ))
+ {
+ handled = TRUE;
+ }
+ }
+
+ return handled;
+}
+
+BOOL LLContextMenu::handleRightMouseUp( S32 x, S32 y, MASK mask )
+{
+ S32 local_x = x - getRect().mLeft;
+ S32 local_y = y - getRect().mBottom;
+
+ if (!mHoveredAnyItem && !pointInView(local_x, local_y))
+ {
+ sMenuContainer->hideMenus();
+ return TRUE;
+ }
+
+
+ BOOL result = handleMouseUp( x, y, mask );
+ mHoveredAnyItem = FALSE;
+
+ return result;
+}
+
+void LLContextMenu::draw()
+{
+ LLMenuGL::draw();
+}
+
+BOOL LLContextMenu::appendContextSubMenu(LLContextMenu *menu)
+{
+
+ if (menu == this)
+ {
+ llerrs << "Can't attach a context menu to itself" << llendl;
+ }
+
+ LLContextMenuBranch *item;
+ LLContextMenuBranch::Params p;
+ p.name = menu->getName();
+ p.label = menu->getLabel();
+ p.branch = menu;
+ p.enabled_color=LLUIColorTable::instance().getColor("MenuItemEnabledColor");
+ p.disabled_color=LLUIColorTable::instance().getColor("MenuItemDisabledColor");
+ p.highlight_bg_color=LLUIColorTable::instance().getColor("MenuItemHighlightBgColor");
+ p.highlight_fg_color=LLUIColorTable::instance().getColor("MenuItemHighlightFgColor");
+
+ item = LLUICtrlFactory::create<LLContextMenuBranch>(p);
+ LLMenuGL::sMenuContainer->addChild(item->getBranch());
+ item->setFont( LLFontGL::getFontSansSerif() );
+
+ return append( item );
+}
+
+bool LLContextMenu::addChild(LLView* view, S32 tab_group)
+{
+ LLContextMenu* context = dynamic_cast<LLContextMenu*>(view);
+ if (context)
+ return appendContextSubMenu(context);
+
+ LLMenuItemSeparatorGL* separator = dynamic_cast<LLMenuItemSeparatorGL*>(view);
+ if (separator)
+ return append(separator);
+
+ LLMenuItemGL* item = dynamic_cast<LLMenuItemGL*>(view);
+ if (item)
+ return append(item);
+
+ return false;
}
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 030b81b58c..61e06f9e5f 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -38,85 +38,80 @@
#include "llstring.h"
#include "v4color.h"
#include "llframetimer.h"
-#include "llevent.h"
#include "llkeyboard.h"
#include "llfloater.h"
#include "lluistring.h"
#include "llview.h"
-
+#include <boost/function.hpp>
extern S32 MENU_BAR_HEIGHT;
extern S32 MENU_BAR_WIDTH;
-// These callbacks are used by the LLMenuItemCallGL and LLMenuItemCheckGL
-// classes during their work.
-typedef void (*menu_callback)(void*);
-
-// These callbacks are used by the LLMenuItemCallGL
-// classes during their work.
-typedef void (*on_disabled_callback)(void*);
-
-// This callback is used by the LLMenuItemCallGL and LLMenuItemCheckGL
-// to determine if the current menu is enabled.
-typedef BOOL (*enabled_callback)(void*);
-
-// This callback is used by LLMenuItemCheckGL to determine it's
-// 'checked' state.
-typedef BOOL (*check_callback)(void*);
-
-// This callback is potentially used by LLMenuItemCallGL. If provided,
-// this function is called whenever it's time to determine the label's
-// contents. Put the contents of the label in the provided parameter.
-typedef void (*label_callback)(std::string&,void*);
-
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLMenuItemGL
//
// The LLMenuItemGL represents a single menu item in a menu.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLMenuItemGL : public LLView
+class LLMenuItemGL : public LLUICtrl
{
public:
- // static functions to control the global color scheme.
- static void setEnabledColor( const LLColor4& color ) { sEnabledColor = color; }
- static const LLColor4& getEnabledColor() { return sEnabledColor; }
- static void setDisabledColor( const LLColor4& color ) { sDisabledColor = color; }
- static const LLColor4& getDisabledColor() { return sDisabledColor; }
- static void setHighlightBGColor( const LLColor4& color ) { sHighlightBackground = color; }
- static const LLColor4& getHighlightBGColor() { return sHighlightBackground; }
- static void setHighlightFGColor( const LLColor4& color ) { sHighlightForeground = color; }
- static const LLColor4& getHighlightFGColor() { return sHighlightForeground; }
-
- LLMenuItemGL( const std::string& name, const std::string& label, KEY key = KEY_NONE, MASK = MASK_NONE );
- virtual ~LLMenuItemGL() {};
-
- virtual void setValue(const LLSD& value) { setLabel(value.asString()); }
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<std::string> shortcut;
+ Optional<KEY> jump_key;
+ Optional<bool> use_mac_ctrl;
+
+ Ignored rect,
+ left,
+ top,
+ right,
+ bottom,
+ width,
+ height,
+ bottom_delta,
+ left_delta;
+
+ Optional<LLUIColor> enabled_color,
+ disabled_color,
+ highlight_bg_color,
+ highlight_fg_color;
+
+
+ Params();
+ };
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
-
- virtual std::string getType() const { return "item"; }
+protected:
+ LLMenuItemGL(const Params&);
+ friend class LLUICtrlFactory;
+public:
+ // LLView overrides
+ /*virtual*/ void handleVisibilityChange(BOOL new_visibility);
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
+ // LLUICtrl overrides
+ /*virtual*/ void setValue(const LLSD& value);
virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
+ LLColor4 getHighlightBgColor() { return mHighlightBackground.get(); }
+
void setJumpKey(KEY key);
KEY getJumpKey() const { return mJumpKey; }
// set the font used by this item.
void setFont(const LLFontGL* font) { mFont = font; }
const LLFontGL* getFont() const { return mFont; }
- void setFontStyle(U8 style) { mStyle = style; }
- U8 getFontStyle() const { return mStyle; }
// returns the height in pixels for the current font.
virtual U32 getNominalHeight( void ) const;
// Marks item as not needing space for check marks or accelerator keys
- virtual void setBriefItem(BOOL brief) { mBriefItem = brief; }
- virtual BOOL isBriefItem() const { return mBriefItem; }
+ virtual void setBriefItem(BOOL brief);
+ virtual BOOL isBriefItem() const;
virtual BOOL addToAcceleratorList(std::list<LLKeyBinding*> *listp);
void setAllowKeyRepeat(BOOL allow) { mAllowKeyRepeat = allow; }
@@ -128,7 +123,7 @@ public:
virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
// Get the parent menu for this item
- virtual class LLMenuGL* getMenu();
+ virtual class LLMenuGL* getMenu() const;
// returns the normal width of this control in pixels - this is
// used for calculating the widest item, as well as for horizontal
@@ -140,7 +135,7 @@ public:
// lead to visual errors if the state of the object changes
// without the knowledge of the menu item. For example, if a
// boolean being watched is changed outside of the menu item's
- // doIt() function, the draw buffer will not be updated and will
+ // onCommit() function, the draw buffer will not be updated and will
// reflect the wrong value. If this ever becomes an issue, there
// are ways to fix this.
// Returns the enabled state of the item.
@@ -149,8 +144,7 @@ public:
// for branching menu items, bring sub menus up to root level of menu hierarchy
virtual void updateBranchParent( LLView* parentp ){};
- // doIt() - do the primary funcationality of the menu item.
- virtual void doIt( void );
+ virtual void onCommit( void );
virtual void setHighlight( BOOL highlight );
virtual BOOL getHighlight() const { return mHighlight; }
@@ -167,6 +161,7 @@ public:
virtual BOOL handleKeyHere( KEY key, MASK mask );
virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );
virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask );
+ virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
virtual void draw( void );
BOOL getHover() const { return mGotHover; }
@@ -180,7 +175,8 @@ protected:
// This function appends the character string representation of
// the current accelerator key and mask to the provided string.
void appendAcceleratorString( std::string& st ) const;
-
+
+protected:
KEY mAcceleratorKey;
MASK mAcceleratorMask;
// mLabel contains the actual label specified by the user.
@@ -193,13 +189,13 @@ protected:
LLUIString mDrawAccelLabel;
LLUIString mDrawBranchLabel;
+ LLUIColor mEnabledColor;
+ LLUIColor mDisabledColor;
+ LLUIColor mHighlightBackground;
+ LLUIColor mHighlightForeground;
+
BOOL mHighlight;
private:
- static LLColor4 sEnabledColor;
- static LLColor4 sDisabledColor;
- static LLColor4 sHighlightBackground;
- static LLColor4 sHighlightForeground;
-
// Keyboard and mouse variables
BOOL mAllowKeyRepeat;
BOOL mGotHover;
@@ -210,12 +206,32 @@ private:
// Font for this item
const LLFontGL* mFont;
- U8 mStyle;
BOOL mDrawTextDisabled;
KEY mJumpKey;
};
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLMenuItemSeparatorGL
+//
+// This class represents a separator.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLMenuItemSeparatorGL : public LLMenuItemGL
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
+ {
+ Params();
+ };
+ LLMenuItemSeparatorGL(const LLMenuItemSeparatorGL::Params& p = LLMenuItemSeparatorGL::Params());
+
+ /*virtual*/ void draw( void );
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+
+ /*virtual*/ U32 getNominalHeight( void ) const;
+};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLMenuItemCallGL
@@ -224,78 +240,52 @@ private:
// calls a user defined callback.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLMenuItemCallGL : public LLMenuItemGL, public LLObservable
+class LLMenuItemCallGL : public LLMenuItemGL
{
public:
- // normal constructor
- LLMenuItemCallGL( const std::string& name,
- menu_callback clicked_cb,
- enabled_callback enabled_cb = NULL,
- void* user_data = NULL,
- KEY key = KEY_NONE, MASK mask = MASK_NONE,
- BOOL enabled = TRUE,
- on_disabled_callback on_disabled_cb = NULL);
- LLMenuItemCallGL( const std::string& name,
- const std::string& label,
- menu_callback clicked_cb,
- enabled_callback enabled_cb = NULL,
- void* user_data = NULL,
- KEY key = KEY_NONE, MASK mask = MASK_NONE,
- BOOL enabled = TRUE,
- on_disabled_callback on_disabled_cb = NULL);
-
- // constructor for when you want to trap the arrange method.
- LLMenuItemCallGL( const std::string& name,
- const std::string& label,
- menu_callback clicked_cb,
- enabled_callback enabled_cb,
- label_callback label_cb,
- void* user_data,
- KEY key = KEY_NONE, MASK mask = MASK_NONE,
- BOOL enabled = TRUE,
- on_disabled_callback on_disabled_c = NULL);
- LLMenuItemCallGL( const std::string& name,
- menu_callback clicked_cb,
- enabled_callback enabled_cb,
- label_callback label_cb,
- void* user_data,
- KEY key = KEY_NONE, MASK mask = MASK_NONE,
- BOOL enabled = TRUE,
- on_disabled_callback on_disabled_c = NULL);
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
-
- virtual std::string getType() const { return "call"; }
-
-
- void setEnabledControl(std::string enabled_control, LLView *context);
- void setVisibleControl(std::string enabled_control, LLView *context);
-
- void setMenuCallback(menu_callback callback, void* data) { mCallback = callback; mUserData = data; };
- menu_callback getMenuCallback() const { return mCallback; }
-
- void setEnabledCallback(enabled_callback callback) { mEnabledCallback = callback; };
-
- void setUserData(void *userdata) { mUserData = userdata; }
- void* getUserData() const { return mUserData; }
+ struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
+ {
+ Optional<EnableCallbackParam > on_enable;
+ Optional<CommitCallbackParam > on_click;
+ Optional<EnableCallbackParam > on_visible;
+ Params()
+ : on_enable("on_enable"),
+ on_click("on_click"),
+ on_visible("on_visible")
+ {}
+ };
+protected:
+ LLMenuItemCallGL(const Params&);
+ friend class LLUICtrlFactory;
+ void updateEnabled( void );
+ void updateVisible( void );
+public:
+ void initFromParams(const Params& p);
+
// called to rebuild the draw label
virtual void buildDrawLabel( void );
- // doIt() - do the primary funcationality of the menu item.
- virtual void doIt( void );
+ virtual void onCommit( void );
virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
-
+ virtual BOOL handleKeyHere(KEY key, MASK mask);
+
//virtual void draw();
-
-
+
+ boost::signals2::connection setClickCallback( const commit_signal_t::slot_type& cb )
+ {
+ return setCommitCallback(cb);
+ }
+
+ boost::signals2::connection setEnableCallback( const enable_signal_t::slot_type& cb )
+ {
+ return mEnableSignal.connect(cb);
+ }
+
private:
- menu_callback mCallback;
- // mEnabledCallback should return TRUE if the item should be enabled
- enabled_callback mEnabledCallback;
- label_callback mLabelCallback;
- void* mUserData;
- on_disabled_callback mOnDisabledCallback;
+ enable_signal_t mEnableSignal;
+ enable_signal_t mVisibleSignal;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -312,78 +302,37 @@ class LLMenuItemCheckGL
: public LLMenuItemCallGL
{
public:
- LLMenuItemCheckGL( const std::string& name,
- const std::string& label,
- menu_callback callback,
- enabled_callback enabled_cb,
- check_callback check,
- void* user_data,
- KEY key = KEY_NONE, MASK mask = MASK_NONE );
- LLMenuItemCheckGL( const std::string& name,
- menu_callback callback,
- enabled_callback enabled_cb,
- check_callback check,
- void* user_data,
- KEY key = KEY_NONE, MASK mask = MASK_NONE );
- LLMenuItemCheckGL( const std::string& name,
- const std::string& label,
- menu_callback callback,
- enabled_callback enabled_cb,
- std::string control_name,
- LLView *context,
- void* user_data,
- KEY key = KEY_NONE, MASK mask = MASK_NONE );
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
-
- void setCheckedControl(std::string checked_control, LLView *context);
-
- virtual void setValue(const LLSD& value);
-
- virtual std::string getType() const { return "check"; }
+ struct Params : public LLInitParam::Block<Params, LLMenuItemCallGL::Params>
+ {
+ Optional<EnableCallbackParam > on_check;
+ Params()
+ : on_check("on_check")
+ {}
+ };
- // called to rebuild the draw label
- virtual void buildDrawLabel( void );
-
-private:
- check_callback mCheckCallback;
- BOOL mChecked;
-};
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLMenuItemToggleGL
-//
-// The LLMenuItemToggleGL is a menu item that wraps around a user
-// specified and controlled boolean.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLMenuItemToggleGL : public LLMenuItemGL
-{
+protected:
+ LLMenuItemCheckGL(const Params&);
+ friend class LLUICtrlFactory;
public:
- LLMenuItemToggleGL( const std::string& name, const std::string& label,
- BOOL* toggle,
- KEY key = KEY_NONE, MASK mask = MASK_NONE );
-
- LLMenuItemToggleGL( const std::string& name,
- BOOL* toggle,
- KEY key = KEY_NONE, MASK mask = MASK_NONE );
+
+ void initFromParams(const Params& p);
- virtual std::string getType() const { return "toggle"; }
+ virtual void onCommit( void );
+
+ virtual void setValue(const LLSD& value);
// called to rebuild the draw label
virtual void buildDrawLabel( void );
-
- // doIt() - do the primary funcationality of the menu item.
- virtual void doIt( void );
-
- // LLView Functionality
- //virtual void draw( void );
-
+
+ boost::signals2::connection setCheckCallback( const enable_signal_t::slot_type& cb )
+ {
+ return mCheckSignal.connect(cb);
+ }
+
private:
- BOOL* mToggle;
+ enable_signal_t mCheckSignal;
};
-
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLMenuGL
//
@@ -395,33 +344,81 @@ private:
// it in the appendMenu() method.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// child widget registry
+struct MenuRegistry : public LLChildRegistry<MenuRegistry>
+{};
+
+
class LLMenuGL
: public LLUICtrl
-// TODO: The menu and menu item classes share a great deal of functionality and perhaps should be united.
-// I think it may make the most sense to make LLMenuGL be a subclass of LLMenuItemGL. -MG
{
+public:
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<LLHandle<LLFloater> > parent_floater;
+ Optional<KEY> jump_key;
+ Optional<bool> horizontal_layout,
+ can_tear_off,
+ drop_shadow,
+ bg_visible,
+ create_jump_keys,
+ keep_fixed_size,
+ scrollable;
+ Optional<U32> max_scrollable_items;
+ Optional<U32> preferred_width;
+ Optional<LLUIColor> bg_color;
+ Optional<S32> shortcut_pad;
+
+ Params()
+ : jump_key("jump_key", KEY_NONE),
+ horizontal_layout("horizontal_layout"),
+ can_tear_off("tear_off", false),
+ drop_shadow("drop_shadow", true),
+ bg_visible("bg_visible", true),
+ create_jump_keys("create_jump_keys", false),
+ bg_color("bg_color", LLUIColorTable::instance().getColor( "MenuDefaultBgColor" )),
+ scrollable("scrollable", false),
+ max_scrollable_items("max_scrollable_items", U32_MAX),
+ preferred_width("preferred_width", U32_MAX),
+ shortcut_pad("shortcut_pad")
+
+ {
+ addSynonym(bg_visible, "opaque");
+ addSynonym(bg_color, "color");
+
+ name = "menu";
+ }
+ };
+
+ // my valid children are contained in MenuRegistry
+ typedef MenuRegistry child_registry_t;
+
+ void initFromParams(const Params&);
+
+protected:
+ LLMenuGL(const LLMenuGL::Params& p);
+ friend class LLUICtrlFactory;
// let branching menu items use my protected traversal methods
friend class LLMenuItemBranchGL;
public:
- LLMenuGL( const std::string& name, const std::string& label, LLHandle<LLFloater> parent_floater = LLHandle<LLFloater>());
- LLMenuGL( const std::string& label, LLHandle<LLFloater> parent_floater = LLHandle<LLFloater>() );
virtual ~LLMenuGL( void );
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
-
- void parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory *factory);
+ void parseChildXML(LLXMLNodePtr child, LLView* parent);
// LLView Functionality
- virtual BOOL handleUnicodeCharHere( llwchar uni_char );
- virtual BOOL handleHover( S32 x, S32 y, MASK mask );
- virtual void draw( void );
- virtual void drawBackground(LLMenuItemGL* itemp, LLColor4& color);
- virtual void setVisible(BOOL visible);
+ /*virtual*/ BOOL handleUnicodeCharHere( llwchar uni_char );
+ /*virtual*/ BOOL handleHover( S32 x, S32 y, MASK mask );
+ /*virtual*/ BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
+ /*virtual*/ void draw( void );
+ /*virtual*/ void drawBackground(LLMenuItemGL* itemp, F32 alpha);
+ /*virtual*/ void setVisible(BOOL visible);
+ /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0);
+ /*virtual*/ void removeChild( LLView* ctrl);
+ /*virtual*/ BOOL postBuild();
virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
- LLMenuGL* getChildMenuByName(const std::string& name, BOOL recurse) const;
+ LLMenuGL* findChildMenuByName(const std::string& name, BOOL recurse) const;
BOOL clearHoverItem();
@@ -430,24 +427,13 @@ public:
void setLabel(const LLStringExplicit& label) { mLabel = label; }
// background colors
- static void setDefaultBackgroundColor( const LLColor4& color ) { sDefaultBackgroundColor = color; }
- void setBackgroundColor( const LLColor4& color ) { mBackgroundColor = color; }
- const LLColor4& getBackgroundColor() const { return mBackgroundColor; }
+ void setBackgroundColor( const LLUIColor& color ) { mBackgroundColor = color; }
+ const LLUIColor& getBackgroundColor() const { return mBackgroundColor; }
void setBackgroundVisible( BOOL b ) { mBgVisible = b; }
void setCanTearOff(BOOL tear_off, LLHandle<LLFloater> parent_floater_handle = LLHandle<LLFloater>());
- // Add the menu item to this menu.
- virtual BOOL append( LLMenuItemGL* item );
-
- // *NOTE:Mani - appendNoArrange() should be removed when merging to skinning/viewer2.0
- // Its added as a fix to a viewer 1.23 bug that has already been address by skinning work.
- virtual BOOL appendNoArrange( LLMenuItemGL* item );
-
// add a separator to this menu
- virtual BOOL appendSeparator( const std::string &separator_name = LLStringUtil::null );
-
- // add a menu - this will create a cascading menu
- virtual BOOL appendMenu( LLMenuGL* menu );
+ virtual BOOL addSeparator();
// for branching menu items, bring sub menus up to root level of menu hierarchy
virtual void updateParent( LLView* parentp );
@@ -471,19 +457,17 @@ public:
virtual BOOL isOpen();
+ void needsArrange() { mNeedsArrange = TRUE; }
// Shape this menu to fit the current state of the children, and
// adjust the child rects to fit. This is called automatically
// when you add items. *FIX: We may need to deal with visibility
// arrangement.
virtual void arrange( void );
+ void arrangeAndClear( void );
// remove all items on the menu
void empty( void );
- // Rearrange the components, and do the right thing if the menu doesn't
- // fit in the bounds.
- // virtual void arrangeWithBounds(LLRect bounds);
-
void setItemLastSelected(LLMenuItemGL* item); // must be in menu
U32 getItemCount(); // number of menu items
LLMenuItemGL* getItem(S32 number); // 0 = first item
@@ -495,17 +479,14 @@ public:
void buildDrawLabels();
void createJumpKeys();
- // Show popup in global screen space based on last mouse location.
- static void showPopup(LLMenuGL* menu);
-
- // Show popup at a specific location.
+ // Show popup at a specific location, in the spawn_view's coordinate frame
static void showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y);
// Whether to drop shadow menu bar
void setDropShadowed( const BOOL shadowed );
- void setParentMenuItem( LLMenuItemGL* parent_menu_item ) { mParentMenuItem = parent_menu_item; }
- LLMenuItemGL* getParentMenuItem() const { return mParentMenuItem; }
+ void setParentMenuItem( LLMenuItemGL* parent_menu_item ) { mParentMenuItem = parent_menu_item->getHandle(); }
+ LLMenuItemGL* getParentMenuItem() const { return dynamic_cast<LLMenuItemGL*>(mParentMenuItem.get()); }
void setTornOff(BOOL torn_off);
BOOL getTornOff() { return mTornOff; }
@@ -518,41 +499,64 @@ public:
static void setKeyboardMode(BOOL mode) { sKeyboardMode = mode; }
static BOOL getKeyboardMode() { return sKeyboardMode; }
+ S32 getShortcutPad() { return mShortcutPad; }
+
+ void scrollItemsUp();
+ void scrollItemsDown();
+ BOOL isScrollable() const { return mScrollable; }
+
static class LLMenuHolderGL* sMenuContainer;
protected:
void createSpilloverBranch();
void cleanupSpilloverBranch();
+ // Add the menu item to this menu.
+ virtual BOOL append( LLMenuItemGL* item );
+
+ // add a menu - this will create a cascading menu
+ virtual BOOL appendMenu( LLMenuGL* menu );
// TODO: create accessor methods for these?
typedef std::list< LLMenuItemGL* > item_list_t;
item_list_t mItems;
+ LLMenuItemGL*mFirstVisibleItem;
+ LLMenuItemGL *mArrowUpItem, *mArrowDownItem;
+
typedef std::map<KEY, LLMenuItemGL*> navigation_key_map_t;
navigation_key_map_t mJumpKeys;
S32 mLastMouseX;
S32 mLastMouseY;
S32 mMouseVelX;
S32 mMouseVelY;
+ U32 mMaxScrollableItems;
+ U32 mPreferredWidth;
BOOL mHorizontalLayout;
+ BOOL mScrollable;
BOOL mKeepFixedSize;
+ BOOL mNeedsArrange;
private:
+
+
static LLColor4 sDefaultBackgroundColor;
static BOOL sKeyboardMode;
- LLColor4 mBackgroundColor;
+ LLUIColor mBackgroundColor;
BOOL mBgVisible;
- LLMenuItemGL* mParentMenuItem;
+ LLHandle<LLView> mParentMenuItem;
LLUIString mLabel;
BOOL mDropShadowed; // Whether to drop shadow
BOOL mHasSelection;
LLFrameTimer mFadeTimer;
+ LLTimer mScrollItemsTimer;
BOOL mTornOff;
class LLMenuItemTearOffGL* mTearOffItem;
class LLMenuItemBranchGL* mSpilloverBranch;
LLMenuGL* mSpilloverMenu;
LLHandle<LLFloater> mParentFloaterHandle;
KEY mJumpKey;
+ BOOL mCreateJumpKeys;
+ S32 mShortcutPad;
}; // end class LLMenuGL
@@ -567,15 +571,17 @@ private:
class LLMenuItemBranchGL : public LLMenuItemGL
{
public:
- LLMenuItemBranchGL( const std::string& name, const std::string& label, LLHandle<LLView> branch,
- KEY key = KEY_NONE, MASK mask = MASK_NONE );
+ struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
+ {
+ Optional<LLMenuGL*> branch;
+ };
+protected:
+ LLMenuItemBranchGL(const Params&);
+ friend class LLUICtrlFactory;
+public:
virtual ~LLMenuItemBranchGL();
-
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
-
- virtual std::string getType() const { return "menu"; }
-
+
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
@@ -586,8 +592,7 @@ public:
// called to rebuild the draw label
virtual void buildDrawLabel( void );
- // doIt() - do the primary funcationality of the menu item.
- virtual void doIt( void );
+ virtual void onCommit( void );
virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
@@ -598,90 +603,79 @@ public:
virtual BOOL handleKeyHere(KEY key, MASK mask);
- virtual BOOL isActive() const { return isOpen() && getBranch()->getHighlightedItem(); }
+ virtual BOOL isActive() const;
- virtual BOOL isOpen() const { return getBranch() && getBranch()->isOpen(); }
+ virtual BOOL isOpen() const;
- LLMenuGL *getBranch() const { return (LLMenuGL*)(mBranch.get()); }
+ LLMenuGL* getBranch() const { return (LLMenuGL*)mBranchHandle.get(); }
virtual void updateBranchParent( LLView* parentp );
// LLView Functionality
- virtual void onVisibilityChange( BOOL curVisibilityIn );
+ virtual void handleVisibilityChange( BOOL curVisibilityIn );
virtual void draw();
- virtual void setEnabledSubMenus(BOOL enabled) { if(getBranch()) getBranch()->setEnabledSubMenus(enabled); }
+ virtual void setEnabledSubMenus(BOOL enabled) { if (getBranch()) getBranch()->setEnabledSubMenus(enabled); }
virtual void openMenu();
- virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const;
+ virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE) const;
+ virtual LLView* findChildView(const std::string& name, BOOL recurse = TRUE) const;
private:
- LLHandle<LLView> mBranch;
+ LLHandle<LLView> mBranchHandle;
}; // end class LLMenuItemBranchGL
-
//-----------------------------------------------------------------------------
-// class LLPieMenu
-// A circular menu of items, icons, etc.
+// class LLContextMenu
+// A context menu
//-----------------------------------------------------------------------------
-class LLPieMenu
+class LLContextMenu
: public LLMenuGL
{
public:
- LLPieMenu(const std::string& name, const std::string& label);
- LLPieMenu(const std::string& name);
- virtual ~LLPieMenu() {}
+ struct Params : public LLInitParam::Block<Params, LLMenuGL::Params>
+ {
+ Params()
+ {
+ visible = false;
+ }
+ };
- void initXML(LLXMLNodePtr node, LLView *context, LLUICtrlFactory *factory);
+protected:
+ LLContextMenu(const Params& p);
+ friend class LLUICtrlFactory;
+
+public:
+ virtual ~LLContextMenu() {}
// LLView Functionality
// can't set visibility directly, must call show or hide
- virtual void setVisible(BOOL visible);
+ virtual void setVisible (BOOL visible);
- virtual BOOL handleHover( S32 x, S32 y, MASK mask );
- virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );
- virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleRightMouseUp( S32 x, S32 y, MASK mask );
- virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask );
- virtual void draw();
- virtual void drawBackground(LLMenuItemGL* itemp, LLColor4& color);
+ virtual void draw ();
+
+ virtual void show (S32 x, S32 y);
+ virtual void hide ();
- virtual BOOL append(LLMenuItemGL* item);
- virtual BOOL appendSeparator( const std::string &separator_name = LLStringUtil::null );
+ virtual BOOL handleHover ( S32 x, S32 y, MASK mask );
+ virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
+ virtual BOOL handleRightMouseUp ( S32 x, S32 y, MASK mask );
- BOOL appendPieMenu(LLPieMenu *menu);
+ virtual bool addChild (LLView* view, S32 tab_group = 0);
- virtual void arrange( void );
+ BOOL appendContextSubMenu(LLContextMenu *menu);
- // Display the menu centered on this point on the screen.
- void show(S32 x, S32 y, BOOL mouse_down);
- void hide(BOOL item_selected);
-
-private:
- LLMenuItemGL *pieItemFromXY(S32 x, S32 y);
- S32 pieItemIndexFromXY(S32 x, S32 y);
-
- // These cause menu items to be spuriously selected by right-clicks
- // near the window edge at low frame rates. I don't think they are
- // needed unless you shift the menu position in the draw() function. JC
- //S32 mShiftHoriz; // non-zero if menu had to shift this frame
- //S32 mShiftVert; // non-zero if menu had to shift this frame
- BOOL mFirstMouseDown; // true from show until mouse up
- BOOL mUseInfiniteRadius; // allow picking pie menu items anywhere outside of center circle
- LLMenuItemGL* mHoverItem;
- BOOL mHoverThisFrame;
+protected:
BOOL mHoveredAnyItem;
- LLFrameTimer mShrinkBorderTimer;
- F32 mOuterRingAlpha; // for rendering pie menus as both bounded and unbounded
- F32 mCurRadius;
- BOOL mRightMouseDown;
+ LLMenuItemGL* mHoverItem;
};
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLMenuBarGL
//
@@ -691,28 +685,30 @@ private:
class LLMenuBarGL : public LLMenuGL
{
public:
- LLMenuBarGL( const std::string& name );
+ struct Params : public LLInitParam::Block<Params, LLMenuGL::Params>
+ {
+ Params()
+ {
+ can_tear_off = false;
+ keep_fixed_size = true;
+ horizontal_layout = true;
+ visible = true;
+ drop_shadow = false;
+ }
+ };
+ LLMenuBarGL( const Params& p );
virtual ~LLMenuBarGL();
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
- virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
- virtual BOOL handleKeyHere(KEY key, MASK mask);
- virtual BOOL handleJumpKey(KEY key);
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleAcceleratorKey(KEY key, MASK mask);
+ /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
+ /*virtual*/ BOOL handleJumpKey(KEY key);
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- // rearrange the child rects so they fit the shape of the menu
- // bar.
- virtual void arrange( void );
- virtual void draw();
- virtual BOOL jumpKeysActive();
+ /*virtual*/ void draw();
+ /*virtual*/ BOOL jumpKeysActive();
// add a vertical separator to this menu
- virtual BOOL appendSeparator( const std::string &separator_name = LLStringUtil::null );
-
- // add a menu - this will create a drop down menu.
- virtual BOOL appendMenu( LLMenuGL* menu );
+ virtual BOOL addSeparator();
// LLView Functionality
virtual BOOL handleHover( S32 x, S32 y, MASK mask );
@@ -723,6 +719,12 @@ public:
void resetMenuTrigger() { mAltKeyTrigger = FALSE; }
private:
+ // add a menu - this will create a drop down menu.
+ virtual BOOL appendMenu( LLMenuGL* menu );
+ // rearrange the child rects so they fit the shape of the menu
+ // bar.
+ virtual void arrange( void );
+
void checkMenuTrigger();
std::list <LLKeyBinding*> mAccelerators;
@@ -737,8 +739,9 @@ private:
class LLMenuHolderGL : public LLPanel
{
public:
- LLMenuHolderGL();
- LLMenuHolderGL(const std::string& name, const LLRect& rect, BOOL mouse_opaque, U32 follows = FOLLOWS_NONE);
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {};
+ LLMenuHolderGL(const Params& p);
virtual ~LLMenuHolderGL() {}
virtual BOOL hideMenus();
@@ -750,11 +753,20 @@ public:
virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );
virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
+ // Close context menus on right mouse up not handled by menus.
+ /*virtual*/ BOOL handleRightMouseUp( S32 x, S32 y, MASK mask );
+
+ virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
virtual const LLRect getMenuRect() const { return getLocalRect(); }
- virtual BOOL hasVisibleMenu() const;
+ LLView*const getVisibleMenu() const;
+ virtual BOOL hasVisibleMenu() const {return getVisibleMenu() != NULL;}
static void setActivatedItem(LLMenuItemGL* item);
+ // Need to detect if mouse-up after context menu spawn has moved.
+ // If not, need to keep the menu up.
+ static LLCoordGL sContextMenuSpawnPos;
+
private:
static LLHandle<LLView> sItemLastSelectedHandle;
static LLFrameTimer sItemActivationTimer;
@@ -772,8 +784,8 @@ class LLTearOffMenu : public LLFloater
{
public:
static LLTearOffMenu* create(LLMenuGL* menup);
- virtual ~LLTearOffMenu() {}
- virtual void onClose(bool app_quitting);
+ virtual ~LLTearOffMenu();
+
virtual void draw(void);
virtual void onFocusReceived();
virtual void onFocusLost();
@@ -783,7 +795,9 @@ public:
private:
LLTearOffMenu(LLMenuGL* menup);
-
+
+ void closeTearOff();
+
LLView* mOldParent;
LLMenuGL* mMenu;
F32 mTargetHeight;
@@ -798,11 +812,19 @@ private:
class LLMenuItemTearOffGL : public LLMenuItemGL
{
public:
- LLMenuItemTearOffGL( LLHandle<LLFloater> parent_floater_handle = LLHandle<LLFloater>());
-
- virtual std::string getType() const { return "tearoff_menu"; }
-
- virtual void doIt(void);
+ struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
+ {
+ Optional<LLHandle<LLFloater> > parent_floater_handle;
+ Params()
+ {
+ name = "tear off";
+ label = "~~~~~~~~~~~";
+ }
+ };
+
+ LLMenuItemTearOffGL( const Params& );
+
+ virtual void onCommit(void);
virtual void draw(void);
virtual U32 getNominalHeight() const;
@@ -824,4 +846,31 @@ private:
LLEditMenuHandlerMgr() {};
};
+
+// *TODO: Eliminate
+// For backwards compatability only; generally just use boost::bind
+class view_listener_t : public boost::signals2::trackable
+{
+public:
+ virtual bool handleEvent(const LLSD& userdata) = 0;
+ virtual ~view_listener_t() {}
+
+ static void addEnable(view_listener_t* listener, const std::string& name)
+ {
+ LLUICtrl::EnableCallbackRegistry::currentRegistrar().add(name, boost::bind(&view_listener_t::handleEvent, listener, _2));
+ }
+
+ static void addCommit(view_listener_t* listener, const std::string& name)
+ {
+ LLUICtrl::CommitCallbackRegistry::currentRegistrar().add(name, boost::bind(&view_listener_t::handleEvent, listener, _2));
+ }
+
+ static void addMenu(view_listener_t* listener, const std::string& name)
+ {
+ // For now, add to both click and enable registries
+ addEnable(listener, name);
+ addCommit(listener, name);
+ }
+};
+
#endif // LL_LLMENUGL_H
diff --git a/indra/llui/llmodaldialog.cpp b/indra/llui/llmodaldialog.cpp
index 1662ff7db6..387af05935 100644
--- a/indra/llui/llmodaldialog.cpp
+++ b/indra/llui/llmodaldialog.cpp
@@ -44,22 +44,20 @@
// static
std::list<LLModalDialog*> LLModalDialog::sModalStack;
-LLModalDialog::LLModalDialog( const std::string& title, S32 width, S32 height, BOOL modal )
- : LLFloater( std::string("modal container"),
- LLRect( 0, height, width, 0 ),
- title,
- FALSE, // resizable
- DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT,
- FALSE, // drag_on_left
- modal ? FALSE : TRUE, // minimizable
- modal ? FALSE : TRUE, // close button
- TRUE), // bordered
+LLModalDialog::LLModalDialog( const LLSD& key, BOOL modal )
+ : LLFloater(key),
mModal( modal )
{
+ if (modal)
+ {
+ setCanMinimize(FALSE);
+ setCanClose(FALSE);
+ }
setVisible( FALSE );
setBackgroundVisible(TRUE);
setBackgroundOpaque(TRUE);
centerOnScreen(); // default position
+ mCloseSignal.connect(boost::bind(&LLModalDialog::stopModal, this));
}
LLModalDialog::~LLModalDialog()
@@ -69,15 +67,27 @@ LLModalDialog::~LLModalDialog()
{
gFocusMgr.unlockFocus();
}
+
+ std::list<LLModalDialog*>::iterator iter = std::find(sModalStack.begin(), sModalStack.end(), this);
+ if (iter != sModalStack.end())
+ {
+ llerrs << "Attempt to delete dialog while still in sModalStack!" << llendl;
+ }
+}
+
+// virtual
+BOOL LLModalDialog::postBuild()
+{
+ return LLFloater::postBuild();
}
// virtual
-void LLModalDialog::open() /* Flawfinder: ignore */
+void LLModalDialog::openFloater(const LLSD& key)
{
// SJB: Hack! Make sure we don't ever host a modal dialog
LLMultiFloater* thost = LLFloater::getFloaterHost();
LLFloater::setFloaterHost(NULL);
- LLFloater::open();
+ LLFloater::openFloater(key);
LLFloater::setFloaterHost(thost);
}
@@ -87,7 +97,8 @@ void LLModalDialog::reshape(S32 width, S32 height, BOOL called_from_parent)
centerOnScreen();
}
-void LLModalDialog::startModal()
+// virtual
+void LLModalDialog::onOpen(const LLSD& key)
{
if (mModal)
{
@@ -105,8 +116,6 @@ void LLModalDialog::startModal()
sModalStack.push_front( this );
}
-
- setVisible( TRUE );
}
void LLModalDialog::stopModal()
@@ -229,48 +238,25 @@ BOOL LLModalDialog::handleKeyHere(KEY key, MASK mask )
BOOL enough_time_elapsed = mVisibleTime.getElapsedTimeF32() > 1.0f;
if (enough_time_elapsed && key == KEY_ESCAPE)
{
- close();
+ closeFloater();
return TRUE;
}
return FALSE;
}
}
-void LLModalDialog::onClose(bool app_quitting)
-{
- stopModal();
- LLFloater::onClose(app_quitting);
-}
-
// virtual
void LLModalDialog::draw()
{
- LLColor4 shadow_color = LLUI::sColorsGroup->getColor("ColorDropShadow");
- S32 shadow_lines = LLUI::sConfigGroup->getS32("DropShadowFloater");
+ static LLUIColor shadow_color = LLUIColorTable::instance().getColor("ColorDropShadow");
+ static LLUICachedControl<S32> shadow_lines ("DropShadowFloater", 0);
gl_drop_shadow( 0, getRect().getHeight(), getRect().getWidth(), 0,
shadow_color, shadow_lines);
LLFloater::draw();
-
- if (mModal)
- {
- // If we've lost focus to a non-child, get it back ASAP.
- if( gFocusMgr.getTopCtrl() != this )
- {
- gFocusMgr.setTopCtrl( this );
- }
-
- if( !gFocusMgr.childHasKeyboardFocus( this ) )
- {
- setFocus(TRUE);
- }
-
- if( !gFocusMgr.childHasMouseCapture( this ) )
- {
- gFocusMgr.setMouseCapture( this );
- }
- }
+
+ // Focus retrieval moved to LLFloaterView::refresh()
}
void LLModalDialog::centerOnScreen()
@@ -291,10 +277,7 @@ void LLModalDialog::onAppFocusLost()
gFocusMgr.setMouseCapture( NULL );
}
- if( gFocusMgr.childHasKeyboardFocus( instance ) )
- {
- gFocusMgr.setKeyboardFocus( NULL );
- }
+ instance->setFocus(FALSE);
}
}
@@ -314,5 +297,16 @@ void LLModalDialog::onAppFocusGained()
}
}
-
-
+void LLModalDialog::shutdownModals()
+{
+ // This method is only for use during app shutdown. ~LLModalDialog()
+ // checks sModalStack, and if the dialog instance is still there, it
+ // crumps with "Attempt to delete dialog while still in sModalStack!" But
+ // at app shutdown, all bets are off. If the user asks to shut down the
+ // app, we shouldn't have to care WHAT's open. Put differently, if a modal
+ // dialog is so crucial that we can't let the user terminate until s/he
+ // addresses it, we should reject a termination request. The current state
+ // of affairs is that we accept it, but then produce an llerrs popup that
+ // simply makes our software look unreliable.
+ sModalStack.clear();
+}
diff --git a/indra/llui/llmodaldialog.h b/indra/llui/llmodaldialog.h
index f6abd0a7ac..863572fb5a 100644
--- a/indra/llui/llmodaldialog.h
+++ b/indra/llui/llmodaldialog.h
@@ -45,16 +45,16 @@ class LLModalDialog;
class LLModalDialog : public LLFloater
{
public:
- LLModalDialog( const std::string& title, S32 width, S32 height, BOOL modal = true );
+ LLModalDialog( const LLSD& key, BOOL modal = true );
/*virtual*/ ~LLModalDialog();
-
- /*virtual*/ void open(); /* Flawfinder: ignore */
+
+ /*virtual*/ BOOL postBuild();
+
+ /*virtual*/ void openFloater(const LLSD& key = LLSD());
+ /*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
- /*virtual*/ void startModal();
- /*virtual*/ void stopModal();
-
/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
@@ -63,22 +63,23 @@ public:
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask );
- /*virtual*/ void onClose(bool app_quitting);
-
/*virtual*/ void setVisible(BOOL visible);
/*virtual*/ void draw();
- BOOL isModal() const { return mModal; }
+ BOOL isModal() const { return mModal; }
+ void stopModal();
static void onAppFocusLost();
static void onAppFocusGained();
static S32 activeCount() { return sModalStack.size(); }
-
+ static void shutdownModals();
+
protected:
void centerOnScreen();
private:
+
LLFrameTimer mVisibleTime;
const BOOL mModal;
diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp
new file mode 100644
index 0000000000..78738c826d
--- /dev/null
+++ b/indra/llui/llmultifloater.cpp
@@ -0,0 +1,509 @@
+/**
+ * @file llmultifloater.cpp
+ * @brief LLFloater that hosts other floaters
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Floating "windows" within the GL display, like the inventory floater,
+// mini-map floater, etc.
+
+#include "linden_common.h"
+
+#include "llmultifloater.h"
+#include "llresizehandle.h"
+
+//
+// LLMultiFloater
+//
+
+LLMultiFloater::LLMultiFloater(const LLSD& key, const LLFloater::Params& params)
+ : LLFloater(key),
+ mTabContainer(NULL),
+ mTabPos(LLTabContainer::TOP),
+ mAutoResize(TRUE),
+ mOrigMinWidth(0),
+ mOrigMinHeight(0)
+{
+}
+
+void LLMultiFloater::buildTabContainer()
+{
+ const LLFloater::Params& default_params = LLFloater::getDefaultParams();
+ S32 floater_header_size = default_params.header_height;
+
+ LLTabContainer::Params p;
+ p.name(std::string("Preview Tabs"));
+ p.rect(LLRect(LLPANEL_BORDER_WIDTH, getRect().getHeight() - floater_header_size, getRect().getWidth() - LLPANEL_BORDER_WIDTH, 0));
+ p.tab_position(mTabPos);
+ p.follows.flags(FOLLOWS_ALL);
+ p.commit_callback.function(boost::bind(&LLMultiFloater::onTabSelected, this));
+
+ mTabContainer = LLUICtrlFactory::create<LLTabContainer>(p);
+ addChild(mTabContainer);
+
+ if (isResizable())
+ {
+ mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
+ }
+}
+
+void LLMultiFloater::onOpen(const LLSD& key)
+{
+// if (mTabContainer->getTabCount() <= 0)
+// {
+// // for now, don't allow multifloaters
+// // without any child floaters
+// closeFloater();
+// }
+}
+
+void LLMultiFloater::draw()
+{
+ if (mTabContainer->getTabCount() == 0)
+ {
+ //RN: could this potentially crash in draw hierarchy?
+ closeFloater();
+ }
+ else
+ {
+ for (S32 i = 0; i < mTabContainer->getTabCount(); i++)
+ {
+ LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(i);
+ if (floaterp->getShortTitle() != mTabContainer->getPanelTitle(i))
+ {
+ mTabContainer->setPanelTitle(i, floaterp->getShortTitle());
+ }
+ }
+ LLFloater::draw();
+ }
+}
+
+BOOL LLMultiFloater::closeAllFloaters()
+{
+ S32 tabToClose = 0;
+ S32 lastTabCount = mTabContainer->getTabCount();
+ while (tabToClose < mTabContainer->getTabCount())
+ {
+ LLFloater* first_floater = (LLFloater*)mTabContainer->getPanelByIndex(tabToClose);
+ first_floater->closeFloater();
+ if(lastTabCount == mTabContainer->getTabCount())
+ {
+ //Tab did not actually close, possibly due to a pending Save Confirmation dialog..
+ //so try and close the next one in the list...
+ tabToClose++;
+ }
+ else
+ {
+ //Tab closed ok.
+ lastTabCount = mTabContainer->getTabCount();
+ }
+ }
+ if( mTabContainer->getTabCount() != 0 )
+ return FALSE; // Couldn't close all the tabs (pending save dialog?) so return FALSE.
+ return TRUE; //else all tabs were successfully closed...
+}
+
+void LLMultiFloater::growToFit(S32 content_width, S32 content_height)
+{
+ static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0);
+ const LLFloater::Params& default_params = LLFloater::getDefaultParams();
+ S32 floater_header_size = default_params.header_height;
+ S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size;
+ S32 new_width = llmax(getRect().getWidth(), content_width + LLPANEL_BORDER_WIDTH * 2);
+ S32 new_height = llmax(getRect().getHeight(), content_height + floater_header_size + tabcntr_header_height);
+
+ if (isMinimized())
+ {
+ LLRect newrect;
+ newrect.setLeftTopAndSize(getExpandedRect().mLeft, getExpandedRect().mTop, new_width, new_height);
+ setExpandedRect(newrect);
+ }
+ else
+ {
+ S32 old_height = getRect().getHeight();
+ reshape(new_width, new_height);
+ // keep top left corner in same position
+ translate(0, old_height - new_height);
+ }
+}
+
+/**
+ void addFloater(LLFloater* floaterp, BOOL select_added_floater)
+
+ Adds the LLFloater pointed to by floaterp to this.
+ If floaterp is already hosted by this, then it is re-added to get
+ new titles, etc.
+ If select_added_floater is true, the LLFloater pointed to by floaterp will
+ become the selected tab in this
+
+ Affects: mTabContainer, floaterp
+**/
+void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point)
+{
+ if (!floaterp)
+ {
+ return;
+ }
+
+ if (!mTabContainer)
+ {
+ llerrs << "Tab Container used without having been initialized." << llendl;
+ return;
+ }
+
+ if (floaterp->getHost() == this)
+ {
+ // already hosted by me, remove
+ // do this so we get updated title, etc.
+ mFloaterDataMap.erase(floaterp->getHandle());
+ mTabContainer->removeTabPanel(floaterp);
+ }
+ else if (floaterp->getHost())
+ {
+ // floaterp is hosted by somebody else and
+ // this is adding it, so remove it from it's old host
+ floaterp->getHost()->removeFloater(floaterp);
+ }
+ else if (floaterp->getParent() == gFloaterView)
+ {
+ // rehost preview floater as child panel
+ gFloaterView->removeChild(floaterp);
+ }
+
+ // store original configuration
+ LLFloaterData floater_data;
+ floater_data.mWidth = floaterp->getRect().getWidth();
+ floater_data.mHeight = floaterp->getRect().getHeight();
+ floater_data.mCanMinimize = floaterp->isMinimizeable();
+ floater_data.mCanResize = floaterp->isResizable();
+
+ // remove minimize and close buttons
+ floaterp->setCanMinimize(FALSE);
+ floaterp->setCanResize(FALSE);
+ floaterp->setCanDrag(FALSE);
+ floaterp->storeRectControl();
+ // avoid double rendering of floater background (makes it more opaque)
+ floaterp->setBackgroundVisible(FALSE);
+
+ if (mAutoResize)
+ {
+ growToFit(floater_data.mWidth, floater_data.mHeight);
+ }
+
+ //add the panel, add it to proper maps
+ mTabContainer->addTabPanel(
+ LLTabContainer::TabPanelParams()
+ .panel(floaterp)
+ .label(floaterp->getShortTitle())
+ .insert_at(insertion_point));
+ mFloaterDataMap[floaterp->getHandle()] = floater_data;
+
+ updateResizeLimits();
+
+ if ( select_added_floater )
+ {
+ mTabContainer->selectTabPanel(floaterp);
+ }
+ else
+ {
+ // reassert visible tab (hiding new floater if necessary)
+ mTabContainer->selectTab(mTabContainer->getCurrentPanelIndex());
+ }
+
+ floaterp->setHost(this);
+ if (isMinimized())
+ {
+ floaterp->setVisible(FALSE);
+ }
+
+ // Tabs sometimes overlap resize handle
+ moveResizeHandlesToFront();
+}
+
+/**
+ BOOL selectFloater(LLFloater* floaterp)
+
+ If the LLFloater pointed to by floaterp is hosted by this,
+ then its tab is selected and returns true. Otherwise returns false.
+
+ Affects: mTabContainer
+**/
+BOOL LLMultiFloater::selectFloater(LLFloater* floaterp)
+{
+ return mTabContainer->selectTabPanel(floaterp);
+}
+
+// virtual
+void LLMultiFloater::selectNextFloater()
+{
+ mTabContainer->selectNextTab();
+}
+
+// virtual
+void LLMultiFloater::selectPrevFloater()
+{
+ mTabContainer->selectPrevTab();
+}
+
+void LLMultiFloater::showFloater(LLFloater* floaterp, LLTabContainer::eInsertionPoint insertion_point)
+{
+ if(!floaterp) return;
+ // we won't select a panel that already is selected
+ // it is hard to do this internally to tab container
+ // as tab selection is handled via index and the tab at a given
+ // index might have changed
+ if (floaterp != mTabContainer->getCurrentPanel() &&
+ !mTabContainer->selectTabPanel(floaterp))
+ {
+ addFloater(floaterp, TRUE, insertion_point);
+ }
+}
+
+void LLMultiFloater::removeFloater(LLFloater* floaterp)
+{
+ if (!floaterp || floaterp->getHost() != this )
+ return;
+
+ floater_data_map_t::iterator found_data_it = mFloaterDataMap.find(floaterp->getHandle());
+ if (found_data_it != mFloaterDataMap.end())
+ {
+ LLFloaterData& floater_data = found_data_it->second;
+ floaterp->setCanMinimize(floater_data.mCanMinimize);
+ if (!floater_data.mCanResize)
+ {
+ // restore original size
+ floaterp->reshape(floater_data.mWidth, floater_data.mHeight);
+ }
+ floaterp->setCanResize(floater_data.mCanResize);
+ mFloaterDataMap.erase(found_data_it);
+ }
+ mTabContainer->removeTabPanel(floaterp);
+ floaterp->setBackgroundVisible(TRUE);
+ floaterp->setCanDrag(TRUE);
+ floaterp->setHost(NULL);
+ floaterp->applyRectControl();
+
+ updateResizeLimits();
+
+ tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), false);
+}
+
+void LLMultiFloater::tabOpen(LLFloater* opened_floater, bool from_click)
+{
+ // default implementation does nothing
+}
+
+void LLMultiFloater::tabClose()
+{
+ if (mTabContainer->getTabCount() == 0)
+ {
+ // no more children, close myself
+ closeFloater();
+ }
+}
+
+void LLMultiFloater::setVisible(BOOL visible)
+{
+ // *FIX: shouldn't have to do this, fix adding to minimized multifloater
+ LLFloater::setVisible(visible);
+
+ if (mTabContainer)
+ {
+ LLPanel* cur_floaterp = mTabContainer->getCurrentPanel();
+
+ if (cur_floaterp)
+ {
+ cur_floaterp->setVisible(visible);
+ }
+
+ // if no tab selected, and we're being shown,
+ // select last tab to be added
+ if (visible && !cur_floaterp)
+ {
+ mTabContainer->selectLastTab();
+ }
+ }
+}
+
+BOOL LLMultiFloater::handleKeyHere(KEY key, MASK mask)
+{
+ if (key == 'W' && mask == MASK_CONTROL)
+ {
+ LLFloater* floater = getActiveFloater();
+ // is user closeable and is system closeable
+ if (floater && floater->canClose() && floater->isCloseable())
+ {
+ floater->closeFloater();
+ }
+ return TRUE;
+ }
+
+ return LLFloater::handleKeyHere(key, mask);
+}
+
+bool LLMultiFloater::addChild(LLView* child, S32 tab_group)
+{
+ LLTabContainer* tab_container = dynamic_cast<LLTabContainer*>(child);
+ if (tab_container)
+ {
+ // store pointer to tab container
+ setTabContainer(tab_container);
+ }
+
+ // then go ahead and add child as usual
+ return LLFloater::addChild(child, tab_group);
+}
+
+LLFloater* LLMultiFloater::getActiveFloater()
+{
+ return (LLFloater*)mTabContainer->getCurrentPanel();
+}
+
+S32 LLMultiFloater::getFloaterCount()
+{
+ return mTabContainer->getTabCount();
+}
+
+/**
+ BOOL isFloaterFlashing(LLFloater* floaterp)
+
+ Returns true if the LLFloater pointed to by floaterp
+ is currently in a flashing state and is hosted by this.
+ False otherwise.
+
+ Requires: floaterp != NULL
+**/
+BOOL LLMultiFloater::isFloaterFlashing(LLFloater* floaterp)
+{
+ if ( floaterp && floaterp->getHost() == this )
+ return mTabContainer->getTabPanelFlashing(floaterp);
+
+ return FALSE;
+}
+
+/**
+ BOOL setFloaterFlashing(LLFloater* floaterp, BOOL flashing)
+
+ Sets the current flashing state of the LLFloater pointed
+ to by floaterp to be the BOOL flashing if the LLFloater pointed
+ to by floaterp is hosted by this.
+
+ Requires: floaterp != NULL
+**/
+void LLMultiFloater::setFloaterFlashing(LLFloater* floaterp, BOOL flashing)
+{
+ if ( floaterp && floaterp->getHost() == this )
+ mTabContainer->setTabPanelFlashing(floaterp, flashing);
+}
+
+void LLMultiFloater::onTabSelected()
+{
+ LLFloater* floaterp = dynamic_cast<LLFloater*>(mTabContainer->getCurrentPanel());
+ if (floaterp)
+ {
+ tabOpen(floaterp, true);
+ }
+}
+
+void LLMultiFloater::setCanResize(BOOL can_resize)
+{
+ LLFloater::setCanResize(can_resize);
+ if (!mTabContainer) return;
+ if (isResizable() && mTabContainer->getTabPosition() == LLTabContainer::BOTTOM)
+ {
+ mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
+ }
+ else
+ {
+ mTabContainer->setRightTabBtnOffset(0);
+ }
+}
+
+BOOL LLMultiFloater::postBuild()
+{
+ mCloseSignal.connect(boost::bind(&LLMultiFloater::closeAllFloaters, this));
+
+ // remember any original xml minimum size
+ getResizeLimits(&mOrigMinWidth, &mOrigMinHeight);
+
+ if (mTabContainer)
+ {
+ return TRUE;
+ }
+
+ mTabContainer = getChild<LLTabContainer>("Preview Tabs");
+
+ setCanResize(mResizable);
+ return TRUE;
+}
+
+void LLMultiFloater::updateResizeLimits()
+{
+ static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0);
+ const LLFloater::Params& default_params = LLFloater::getDefaultParams();
+ S32 floater_header_size = default_params.header_height;
+ S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size;
+ // initialize minimum size constraint to the original xml values.
+ S32 new_min_width = mOrigMinWidth;
+ S32 new_min_height = mOrigMinHeight;
+ // possibly increase minimum size constraint due to children's minimums.
+ for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx)
+ {
+ LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx);
+ if (floaterp)
+ {
+ new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2);
+ new_min_height = llmax(new_min_height, floaterp->getMinHeight() + floater_header_size + tabcntr_header_height);
+ }
+ }
+ setResizeLimits(new_min_width, new_min_height);
+
+ S32 cur_height = getRect().getHeight();
+ S32 new_width = llmax(getRect().getWidth(), new_min_width);
+ S32 new_height = llmax(getRect().getHeight(), new_min_height);
+
+ if (isMinimized())
+ {
+ const LLRect& expanded = getExpandedRect();
+ LLRect newrect;
+ newrect.setLeftTopAndSize(expanded.mLeft, expanded.mTop, llmax(expanded.getWidth(), new_width), llmax(expanded.getHeight(), new_height));
+ setExpandedRect(newrect);
+ }
+ else
+ {
+ reshape(new_width, new_height);
+
+ // make sure upper left corner doesn't move
+ translate(0, cur_height - getRect().getHeight());
+
+ // make sure this window is visible on screen when it has been modified
+ // (tab added, etc)
+ gFloaterView->adjustToFitScreen(this, TRUE);
+ }
+}
diff --git a/indra/llui/llmultifloater.h b/indra/llui/llmultifloater.h
new file mode 100644
index 0000000000..bbf2c56fe7
--- /dev/null
+++ b/indra/llui/llmultifloater.h
@@ -0,0 +1,106 @@
+/**
+ * @file llmultifloater.h
+ * @brief LLFloater that hosts other floaters
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Floating "windows" within the GL display, like the inventory floater,
+// mini-map floater, etc.
+
+
+#ifndef LL_MULTI_FLOATER_H
+#define LL_MULTI_FLOATER_H
+
+#include "llfloater.h"
+#include "lltabcontainer.h" // for LLTabContainer::eInsertionPoint
+
+// https://wiki.lindenlab.com/mediawiki/index.php?title=LLMultiFloater&oldid=81376
+class LLMultiFloater : public LLFloater
+{
+public:
+ LLMultiFloater(const LLSD& key, const Params& params = getDefaultParams());
+ virtual ~LLMultiFloater() {};
+
+ void buildTabContainer();
+
+ virtual BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ void draw();
+ /*virtual*/ void setVisible(BOOL visible);
+ /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
+ /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0);
+
+ virtual void setCanResize(BOOL can_resize);
+ virtual void growToFit(S32 content_width, S32 content_height);
+ virtual void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END);
+
+ virtual void showFloater(LLFloater* floaterp, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END);
+ virtual void removeFloater(LLFloater* floaterp);
+
+ virtual void tabOpen(LLFloater* opened_floater, bool from_click);
+ virtual void tabClose();
+
+ virtual BOOL selectFloater(LLFloater* floaterp);
+ virtual void selectNextFloater();
+ virtual void selectPrevFloater();
+
+ virtual LLFloater* getActiveFloater();
+ virtual BOOL isFloaterFlashing(LLFloater* floaterp);
+ virtual S32 getFloaterCount();
+
+ virtual void setFloaterFlashing(LLFloater* floaterp, BOOL flashing);
+ virtual BOOL closeAllFloaters(); //Returns FALSE if the floater could not be closed due to pending confirmation dialogs
+ void setTabContainer(LLTabContainer* tab_container) { if (!mTabContainer) mTabContainer = tab_container; }
+ void onTabSelected();
+
+ virtual void updateResizeLimits();
+
+protected:
+ struct LLFloaterData
+ {
+ S32 mWidth;
+ S32 mHeight;
+ BOOL mCanMinimize;
+ BOOL mCanResize;
+ };
+
+ LLTabContainer* mTabContainer;
+
+ typedef std::map<LLHandle<LLFloater>, LLFloaterData> floater_data_map_t;
+ floater_data_map_t mFloaterDataMap;
+
+ LLTabContainer::TabPosition mTabPos;
+ BOOL mAutoResize;
+ S32 mOrigMinWidth, mOrigMinHeight; // logically const but initialized late
+};
+
+#endif // LL_MULTI_FLOATER_H
+
+
+
diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp
index c1487be553..27a727fdf5 100644
--- a/indra/llui/llmultislider.cpp
+++ b/indra/llui/llmultislider.cpp
@@ -40,67 +40,95 @@
#include "llfocusmgr.h"
#include "llkeyboard.h" // for the MASK constants
#include "llcontrol.h"
-#include "llimagegl.h"
+#include "lluictrlfactory.h"
#include <sstream>
-static LLRegisterWidget<LLMultiSlider> r("multi_slider_bar");
+static LLDefaultChildRegistry::Register<LLMultiSlider> r("multi_slider_bar");
-const S32 MULTI_THUMB_WIDTH = 8;
-const S32 MULTI_TRACK_HEIGHT = 6;
const F32 FLOAT_THRESHOLD = 0.00001f;
-const S32 EXTRA_TRIANGLE_WIDTH = 2;
-const S32 EXTRA_TRIANGLE_HEIGHT = -2;
S32 LLMultiSlider::mNameCounter = 0;
-LLMultiSlider::LLMultiSlider(
- const std::string& name,
- const LLRect& rect,
- void (*on_commit_callback)(LLUICtrl* ctrl, void* userdata),
- void* callback_userdata,
- F32 initial_value,
- F32 min_value,
- F32 max_value,
- F32 increment,
- S32 max_sliders,
- BOOL allow_overlap,
- BOOL draw_track,
- BOOL use_triangle,
- const std::string& control_name)
- :
- LLUICtrl( name, rect, TRUE, on_commit_callback, callback_userdata,
- FOLLOWS_LEFT | FOLLOWS_TOP),
-
- mInitialValue( initial_value ),
- mMinValue( min_value ),
- mMaxValue( max_value ),
- mIncrement( increment ),
- mMaxNumSliders(max_sliders),
- mAllowOverlap(allow_overlap),
- mDrawTrack(draw_track),
- mUseTriangle(use_triangle),
+LLMultiSlider::SliderParams::SliderParams()
+: name("name"),
+ value("value", 0.f)
+{
+}
+
+LLMultiSlider::Params::Params()
+: max_sliders("max_sliders", 1),
+ allow_overlap("allow_overlap", false),
+ draw_track("draw_track", true),
+ use_triangle("use_triangle", false),
+ track_color("track_color"),
+ thumb_disabled_color("thumb_disabled_color"),
+ thumb_outline_color("thumb_outline_color"),
+ thumb_center_color("thumb_center_color"),
+ thumb_center_selected_color("thumb_center_selected_color"),
+ triangle_color("triangle_color"),
+ mouse_down_callback("mouse_down_callback"),
+ mouse_up_callback("mouse_up_callback"),
+ thumb_width("thumb_width"),
+ sliders("slider")
+{
+ name = "multi_slider_bar";
+ mouse_opaque(true);
+ follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP);
+}
+
+LLMultiSlider::LLMultiSlider(const LLMultiSlider::Params& p)
+: LLF32UICtrl(p),
mMouseOffset( 0 ),
- mDragStartThumbRect( 0, getRect().getHeight(), MULTI_THUMB_WIDTH, 0 ),
- mTrackColor( LLUI::sColorsGroup->getColor( "MultiSliderTrackColor" ) ),
- mThumbOutlineColor( LLUI::sColorsGroup->getColor( "MultiSliderThumbOutlineColor" ) ),
- mThumbCenterColor( LLUI::sColorsGroup->getColor( "MultiSliderThumbCenterColor" ) ),
- mThumbCenterSelectedColor( LLUI::sColorsGroup->getColor( "MultiSliderThumbCenterSelectedColor" ) ),
- mDisabledThumbColor(LLUI::sColorsGroup->getColor( "MultiSliderDisabledThumbColor" ) ),
- mTriangleColor(LLUI::sColorsGroup->getColor( "MultiSliderTriangleColor" ) ),
- mMouseDownCallback( NULL ),
- mMouseUpCallback( NULL )
+ mDragStartThumbRect( 0, getRect().getHeight(), p.thumb_width, 0 ),
+ mMaxNumSliders(p.max_sliders),
+ mAllowOverlap(p.allow_overlap),
+ mDrawTrack(p.draw_track),
+ mUseTriangle(p.use_triangle),
+ mTrackColor(p.track_color()),
+ mThumbOutlineColor(p.thumb_outline_color()),
+ mThumbCenterColor(p.thumb_center_color()),
+ mThumbCenterSelectedColor(p.thumb_center_selected_color()),
+ mDisabledThumbColor(p.thumb_disabled_color()),
+ mTriangleColor(p.triangle_color()),
+ mThumbWidth(p.thumb_width),
+ mMouseDownSignal(NULL),
+ mMouseUpSignal(NULL)
{
mValue.emptyMap();
mCurSlider = LLStringUtil::null;
+
+ if (p.mouse_down_callback.isProvided())
+ {
+ setMouseDownCallback(initCommitCallback(p.mouse_down_callback));
+ }
+ if (p.mouse_up_callback.isProvided())
+ {
+ setMouseUpCallback(initCommitCallback(p.mouse_up_callback));
+ }
- // properly handle setting the starting thumb rect
- // do it this way to handle both the operating-on-settings
- // and standalone ways of using this
- setControlName(control_name, NULL);
- setValue(getValue());
+ for (LLInitParam::ParamIterator<SliderParams>::const_iterator it = p.sliders().begin();
+ it != p.sliders().end();
+ ++it)
+ {
+ if (it->name.isProvided())
+ {
+ addSlider(it->value, it->name);
+ }
+ else
+ {
+ addSlider(it->value);
+ }
+ }
+}
+
+LLMultiSlider::~LLMultiSlider()
+{
+ delete mMouseDownSignal;
+ delete mMouseUpSignal;
}
+
void LLMultiSlider::setSliderValue(const std::string& name, F32 value, BOOL from_event)
{
// exit if not there
@@ -152,12 +180,12 @@ void LLMultiSlider::setSliderValue(const std::string& name, F32 value, BOOL from
F32 t = (newValue - mMinValue) / (mMaxValue - mMinValue);
- S32 left_edge = MULTI_THUMB_WIDTH/2;
- S32 right_edge = getRect().getWidth() - (MULTI_THUMB_WIDTH/2);
+ S32 left_edge = mThumbWidth/2;
+ S32 right_edge = getRect().getWidth() - (mThumbWidth/2);
S32 x = left_edge + S32( t * (right_edge - left_edge) );
- mThumbRects[name].mLeft = x - (MULTI_THUMB_WIDTH/2);
- mThumbRects[name].mRight = x + (MULTI_THUMB_WIDTH/2);
+ mThumbRects[name].mLeft = x - (mThumbWidth/2);
+ mThumbRects[name].mRight = x + (mThumbWidth/2);
}
void LLMultiSlider::setValue(const LLSD& value)
@@ -211,7 +239,7 @@ const std::string& LLMultiSlider::addSlider(F32 val)
}
// add a new thumb rect
- mThumbRects[newName.str()] = LLRect( 0, getRect().getHeight(), MULTI_THUMB_WIDTH, 0 );
+ mThumbRects[newName.str()] = LLRect( 0, getRect().getHeight(), mThumbWidth, 0 );
// add the value and set the current slider to this one
mValue.insert(newName.str(), initVal);
@@ -223,6 +251,30 @@ const std::string& LLMultiSlider::addSlider(F32 val)
return mCurSlider;
}
+void LLMultiSlider::addSlider(F32 val, const std::string& name)
+{
+ F32 initVal = val;
+
+ if(mValue.size() >= mMaxNumSliders) {
+ return;
+ }
+
+ bool foundOne = findUnusedValue(initVal);
+ if(!foundOne) {
+ return;
+ }
+
+ // add a new thumb rect
+ mThumbRects[name] = LLRect( 0, getRect().getHeight(), mThumbWidth, 0 );
+
+ // add the value and set the current slider to this one
+ mValue.insert(name, initVal);
+ mCurSlider = name;
+
+ // move the slider
+ setSliderValue(mCurSlider, initVal, TRUE);
+}
+
bool LLMultiSlider::findUnusedValue(F32& initVal)
{
bool firstTry = true;
@@ -295,15 +347,15 @@ void LLMultiSlider::clear()
deleteCurSlider();
}
- LLUICtrl::clear();
+ LLF32UICtrl::clear();
}
BOOL LLMultiSlider::handleHover(S32 x, S32 y, MASK mask)
{
if( gFocusMgr.getMouseCapture() == this )
{
- S32 left_edge = MULTI_THUMB_WIDTH/2;
- S32 right_edge = getRect().getWidth() - (MULTI_THUMB_WIDTH/2);
+ S32 left_edge = mThumbWidth/2;
+ S32 right_edge = getRect().getWidth() - (mThumbWidth/2);
x += mMouseOffset;
x = llclamp( x, left_edge, right_edge );
@@ -331,10 +383,9 @@ BOOL LLMultiSlider::handleMouseUp(S32 x, S32 y, MASK mask)
{
gFocusMgr.setMouseCapture( NULL );
- if( mMouseUpCallback )
- {
- mMouseUpCallback( this, mCallbackUserData );
- }
+ if (mMouseUpSignal)
+ (*mMouseUpSignal)( this, LLSD() );
+
handled = TRUE;
make_ui_sound("UISndClickRelease");
}
@@ -353,10 +404,8 @@ BOOL LLMultiSlider::handleMouseDown(S32 x, S32 y, MASK mask)
{
setFocus(TRUE);
}
- if( mMouseDownCallback )
- {
- mMouseDownCallback( this, mCallbackUserData );
- }
+ if (mMouseDownSignal)
+ (*mMouseDownSignal)( this, LLSD() );
if (MASK_CONTROL & mask) // if CTRL is modifying
{
@@ -379,7 +428,7 @@ BOOL LLMultiSlider::handleMouseDown(S32 x, S32 y, MASK mask)
// Find the offset of the actual mouse location from the center of the thumb.
if (mThumbRects[mCurSlider].pointInRect(x,y))
{
- mMouseOffset = (mThumbRects[mCurSlider].mLeft + MULTI_THUMB_WIDTH/2) - x;
+ mMouseOffset = (mThumbRects[mCurSlider].mLeft + mThumbWidth/2) - x;
}
else
{
@@ -424,6 +473,8 @@ BOOL LLMultiSlider::handleKeyHere(KEY key, MASK mask)
void LLMultiSlider::draw()
{
+ static LLUICachedControl<S32> extra_triangle_height ("UIExtraTriangleHeight", 0);
+ static LLUICachedControl<S32> extra_triangle_width ("UIExtraTriangleWidth", 0);
LLColor4 curThumbColor;
std::map<std::string, LLRect>::iterator mIt;
@@ -439,16 +490,17 @@ void LLMultiSlider::draw()
F32 opacity = getEnabled() ? 1.f : 0.3f;
// Track
- LLUIImagePtr thumb_imagep = LLUI::sImageProvider->getUIImage("rounded_square.tga");
+ LLUIImagePtr thumb_imagep = LLUI::getUIImage("Rounded_Square");
- S32 height_offset = (getRect().getHeight() - MULTI_TRACK_HEIGHT) / 2;
+ static LLUICachedControl<S32> multi_track_height ("UIMultiTrackHeight", 0);
+ S32 height_offset = (getRect().getHeight() - multi_track_height) / 2;
LLRect track_rect(0, getRect().getHeight() - height_offset, getRect().getWidth(), height_offset );
if(mDrawTrack)
{
track_rect.stretch(-1);
- thumb_imagep->draw(track_rect, mTrackColor % opacity);
+ thumb_imagep->draw(track_rect, mTrackColor.get() % opacity);
}
// if we're supposed to use a drawn triangle
@@ -458,13 +510,13 @@ void LLMultiSlider::draw()
for(mIt = mThumbRects.begin(); mIt != mThumbRects.end(); mIt++) {
gl_triangle_2d(
- mIt->second.mLeft - EXTRA_TRIANGLE_WIDTH,
- mIt->second.mTop + EXTRA_TRIANGLE_HEIGHT,
- mIt->second.mRight + EXTRA_TRIANGLE_WIDTH,
- mIt->second.mTop + EXTRA_TRIANGLE_HEIGHT,
+ mIt->second.mLeft - extra_triangle_width,
+ mIt->second.mTop + extra_triangle_height,
+ mIt->second.mRight + extra_triangle_width,
+ mIt->second.mTop + extra_triangle_height,
mIt->second.mLeft + mIt->second.getWidth() / 2,
- mIt->second.mBottom - EXTRA_TRIANGLE_HEIGHT,
- mTriangleColor, TRUE);
+ mIt->second.mBottom - extra_triangle_height,
+ mTriangleColor.get(), TRUE);
}
}
else if (!thumb_imagep)
@@ -474,7 +526,7 @@ void LLMultiSlider::draw()
for(mIt = mThumbRects.begin(); mIt != mThumbRects.end(); mIt++) {
// choose the color
- curThumbColor = mThumbCenterColor;
+ curThumbColor = mThumbCenterColor.get();
if(mIt->first == mCurSlider) {
curSldrIt = mIt;
@@ -488,19 +540,19 @@ void LLMultiSlider::draw()
// now draw the current slider
if(curSldrIt != mThumbRects.end()) {
- gl_rect_2d(curSldrIt->second, mThumbCenterSelectedColor, TRUE);
+ gl_rect_2d(curSldrIt->second, mThumbCenterSelectedColor.get(), TRUE);
}
// and draw the drag start
if (gFocusMgr.getMouseCapture() == this)
{
- gl_rect_2d(mDragStartThumbRect, mThumbCenterColor % opacity, FALSE);
+ gl_rect_2d(mDragStartThumbRect, mThumbCenterColor.get() % opacity, FALSE);
}
}
else if( gFocusMgr.getMouseCapture() == this )
{
// draw drag start
- thumb_imagep->drawSolid(mDragStartThumbRect, mThumbCenterColor % 0.3f);
+ thumb_imagep->drawSolid(mDragStartThumbRect, mThumbCenterColor.get() % 0.3f);
// draw the highlight
if (hasFocus())
@@ -513,7 +565,7 @@ void LLMultiSlider::draw()
for(mIt = mThumbRects.begin(); mIt != mThumbRects.end(); mIt++)
{
// choose the color
- curThumbColor = mThumbCenterColor;
+ curThumbColor = mThumbCenterColor.get();
if(mIt->first == mCurSlider)
{
// don't draw now, draw last
@@ -528,7 +580,7 @@ void LLMultiSlider::draw()
// draw cur slider last
if(curSldrIt != mThumbRects.end())
{
- thumb_imagep->drawSolid(curSldrIt->second, mThumbCenterSelectedColor);
+ thumb_imagep->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get());
}
}
@@ -546,7 +598,7 @@ void LLMultiSlider::draw()
{
// choose the color
- curThumbColor = mThumbCenterColor;
+ curThumbColor = mThumbCenterColor.get();
if(mIt->first == mCurSlider)
{
curSldrIt = mIt;
@@ -559,74 +611,20 @@ void LLMultiSlider::draw()
if(curSldrIt != mThumbRects.end())
{
- thumb_imagep->drawSolid(curSldrIt->second, mThumbCenterSelectedColor % opacity);
+ thumb_imagep->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get() % opacity);
}
}
- LLUICtrl::draw();
+ LLF32UICtrl::draw();
}
-
-// virtual
-LLXMLNodePtr LLMultiSlider::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLUICtrl::getXML();
-
- node->createChild("initial_val", TRUE)->setFloatValue(getInitialValue());
- node->createChild("min_val", TRUE)->setFloatValue(getMinValue());
- node->createChild("max_val", TRUE)->setFloatValue(getMaxValue());
- node->createChild("increment", TRUE)->setFloatValue(getIncrement());
-
- return node;
+boost::signals2::connection LLMultiSlider::setMouseDownCallback( const commit_signal_t::slot_type& cb )
+{
+ if (!mMouseDownSignal) mMouseDownSignal = new commit_signal_t();
+ return mMouseDownSignal->connect(cb);
}
-
-//static
-LLView* LLMultiSlider::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("multi_slider_bar");
- node->getAttributeString("name", name);
-
- LLRect rect;
- createRect(node, rect, parent, LLRect());
-
- F32 initial_value = 0.f;
- node->getAttributeF32("initial_val", initial_value);
-
- F32 min_value = 0.f;
- node->getAttributeF32("min_val", min_value);
-
- F32 max_value = 1.f;
- node->getAttributeF32("max_val", max_value);
-
- F32 increment = 0.1f;
- node->getAttributeF32("increment", increment);
-
- S32 max_sliders = 1;
- node->getAttributeS32("max_sliders", max_sliders);
-
- BOOL allow_overlap = FALSE;
- node->getAttributeBOOL("allow_overlap", allow_overlap);
-
- BOOL draw_track = TRUE;
- node->getAttributeBOOL("draw_track", draw_track);
-
- BOOL use_triangle = FALSE;
- node->getAttributeBOOL("use_triangle", use_triangle);
-
- LLMultiSlider* multiSlider = new LLMultiSlider(name,
- rect,
- NULL,
- NULL,
- initial_value,
- min_value,
- max_value,
- increment,
- max_sliders,
- allow_overlap,
- draw_track,
- use_triangle);
-
- multiSlider->initFromXML(node, parent);
-
- return multiSlider;
+boost::signals2::connection LLMultiSlider::setMouseUpCallback( const commit_signal_t::slot_type& cb )
+{
+ if (!mMouseUpSignal) mMouseUpSignal = new commit_signal_t();
+ return mMouseUpSignal->connect(cb);
}
diff --git a/indra/llui/llmultislider.h b/indra/llui/llmultislider.h
index cdbdb597f9..88576da85b 100644
--- a/indra/llui/llmultislider.h
+++ b/indra/llui/llmultislider.h
@@ -33,75 +33,79 @@
#ifndef LL_MULTI_SLIDER_H
#define LL_MULTI_SLIDER_H
-#include "lluictrl.h"
+#include "llf32uictrl.h"
#include "v4color.h"
class LLUICtrlFactory;
-class LLMultiSlider : public LLUICtrl
+class LLMultiSlider : public LLF32UICtrl
{
public:
- LLMultiSlider(
- const std::string& name,
- const LLRect& rect,
- void (*on_commit_callback)(LLUICtrl* ctrl, void* userdata),
- void* callback_userdata,
- F32 initial_value,
- F32 min_value,
- F32 max_value,
- F32 increment,
- S32 max_sliders,
- BOOL allow_overlap,
- BOOL draw_track,
- BOOL use_triangle,
- const std::string& control_name = LLStringUtil::null );
-
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
-
- void setSliderValue(const std::string& name, F32 value, BOOL from_event = FALSE);
- F32 getSliderValue(const std::string& name) const;
-
- const std::string& getCurSlider() const { return mCurSlider; }
- F32 getCurSliderValue() const { return getSliderValue(mCurSlider); }
- void setCurSlider(const std::string& name);
- void setCurSliderValue(F32 val, BOOL from_event = false) { setSliderValue(mCurSlider, val, from_event); }
-
- virtual void setValue(const LLSD& value);
- virtual LLSD getValue() const { return mValue; }
-
- virtual void setMinValue(LLSD min_value) { setMinValue((F32)min_value.asReal()); }
- virtual void setMaxValue(LLSD max_value) { setMaxValue((F32)max_value.asReal()); }
-
- F32 getInitialValue() const { return mInitialValue; }
- F32 getMinValue() const { return mMinValue; }
- F32 getMaxValue() const { return mMaxValue; }
- F32 getIncrement() const { return mIncrement; }
- void setMinValue(F32 min_value) { mMinValue = min_value; }
- void setMaxValue(F32 max_value) { mMaxValue = max_value; }
- void setIncrement(F32 increment) { mIncrement = increment; }
- void setMouseDownCallback( void (*cb)(LLUICtrl* ctrl, void* userdata) ) { mMouseDownCallback = cb; }
- void setMouseUpCallback( void (*cb)(LLUICtrl* ctrl, void* userdata) ) { mMouseUpCallback = cb; }
-
- bool findUnusedValue(F32& initVal);
+ struct SliderParams : public LLInitParam::Block<SliderParams>
+ {
+ Optional<std::string> name;
+ Mandatory<F32> value;
+ SliderParams();
+ };
+
+ struct Params : public LLInitParam::Block<Params, LLF32UICtrl::Params>
+ {
+ Optional<S32> max_sliders;
+
+ Optional<bool> allow_overlap,
+ draw_track,
+ use_triangle;
+
+ Optional<LLUIColor> track_color,
+ thumb_disabled_color,
+ thumb_outline_color,
+ thumb_center_color,
+ thumb_center_selected_color,
+ triangle_color;
+
+ Optional<CommitCallbackParam> mouse_down_callback,
+ mouse_up_callback;
+ Optional<S32> thumb_width;
+
+ Multiple<SliderParams> sliders;
+ Params();
+ };
+
+protected:
+ LLMultiSlider(const Params&);
+ friend class LLUICtrlFactory;
+public:
+ virtual ~LLMultiSlider();
+ void setSliderValue(const std::string& name, F32 value, BOOL from_event = FALSE);
+ F32 getSliderValue(const std::string& name) const;
+
+ const std::string& getCurSlider() const { return mCurSlider; }
+ F32 getCurSliderValue() const { return getSliderValue(mCurSlider); }
+ void setCurSlider(const std::string& name);
+ void setCurSliderValue(F32 val, BOOL from_event = false) { setSliderValue(mCurSlider, val, from_event); }
+
+ /*virtual*/ void setValue(const LLSD& value);
+ /*virtual*/ LLSD getValue() const { return mValue; }
+
+ boost::signals2::connection setMouseDownCallback( const commit_signal_t::slot_type& cb );
+ boost::signals2::connection setMouseUpCallback( const commit_signal_t::slot_type& cb );
+
+ bool findUnusedValue(F32& initVal);
const std::string& addSlider();
const std::string& addSlider(F32 val);
- void deleteSlider(const std::string& name);
- void deleteCurSlider() { deleteSlider(mCurSlider); }
- void clear();
+ void addSlider(F32 val, const std::string& name);
+ void deleteSlider(const std::string& name);
+ void deleteCurSlider() { deleteSlider(mCurSlider); }
+ void clear();
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleKeyHere(KEY key, MASK mask);
- virtual void draw();
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
+ /*virtual*/ void draw();
protected:
LLSD mValue;
- F32 mInitialValue;
- F32 mMinValue;
- F32 mMaxValue;
- F32 mIncrement;
std::string mCurSlider;
static S32 mNameCounter;
@@ -112,17 +116,19 @@ protected:
S32 mMouseOffset;
LLRect mDragStartThumbRect;
-
- std::map<std::string, LLRect> mThumbRects;
- LLColor4 mTrackColor;
- LLColor4 mThumbOutlineColor;
- LLColor4 mThumbCenterColor;
- LLColor4 mThumbCenterSelectedColor;
- LLColor4 mDisabledThumbColor;
- LLColor4 mTriangleColor;
+ S32 mThumbWidth;
+
+ std::map<std::string, LLRect>
+ mThumbRects;
+ LLUIColor mTrackColor;
+ LLUIColor mThumbOutlineColor;
+ LLUIColor mThumbCenterColor;
+ LLUIColor mThumbCenterSelectedColor;
+ LLUIColor mDisabledThumbColor;
+ LLUIColor mTriangleColor;
- void (*mMouseDownCallback)(LLUICtrl* ctrl, void* userdata);
- void (*mMouseUpCallback)(LLUICtrl* ctrl, void* userdata);
+ commit_signal_t* mMouseDownSignal;
+ commit_signal_t* mMouseUpSignal;
};
-#endif // LL_LLSLIDER_H
+#endif // LL_MULTI_SLIDER_H
diff --git a/indra/llui/llmultisliderctrl.cpp b/indra/llui/llmultisliderctrl.cpp
index 8bcf9f9b76..f4434a0f78 100644
--- a/indra/llui/llmultisliderctrl.cpp
+++ b/indra/llui/llmultisliderctrl.cpp
@@ -34,9 +34,6 @@
#include "llmultisliderctrl.h"
-#include "audioengine.h"
-#include "sound_ids.h"
-
#include "llmath.h"
#include "llfontgl.h"
#include "llgl.h"
@@ -50,90 +47,101 @@
#include "llcontrol.h"
#include "llfocusmgr.h"
#include "llresmgr.h"
+#include "lluictrlfactory.h"
-static LLRegisterWidget<LLMultiSliderCtrl> r("multi_slider");
+static LLDefaultChildRegistry::Register<LLMultiSliderCtrl> r("multi_slider");
const U32 MAX_STRING_LENGTH = 10;
-
+LLMultiSliderCtrl::Params::Params()
+: text_width("text_width"),
+ label_width("label_width"),
+ show_text("show_text", true),
+ can_edit_text("can_edit_text", false),
+ max_sliders("max_sliders", 1),
+ allow_overlap("allow_overlap", false),
+ draw_track("draw_track", true),
+ use_triangle("use_triangle", false),
+ decimal_digits("decimal_digits", 3),
+ text_color("text_color"),
+ text_disabled_color("text_disabled_color"),
+ mouse_down_callback("mouse_down_callback"),
+ mouse_up_callback("mouse_up_callback"),
+ sliders("slider")
+{
+ mouse_opaque = true;
+}
-LLMultiSliderCtrl::LLMultiSliderCtrl(const std::string& name, const LLRect& rect,
- const std::string& label,
- const LLFontGL* font,
- S32 label_width,
- S32 text_left,
- BOOL show_text,
- BOOL can_edit_text,
- void (*commit_callback)(LLUICtrl*, void*),
- void* callback_user_data,
- F32 initial_value, F32 min_value, F32 max_value, F32 increment,
- S32 max_sliders, BOOL allow_overlap,
- BOOL draw_track,
- BOOL use_triangle,
- const std::string& control_which)
- : LLUICtrl(name, rect, TRUE, commit_callback, callback_user_data ),
- mFont(font),
- mShowText( show_text ),
- mCanEditText( can_edit_text ),
- mPrecision( 3 ),
- mLabelBox( NULL ),
- mLabelWidth( label_width ),
-
- mEditor( NULL ),
- mTextBox( NULL ),
- mTextEnabledColor( LLUI::sColorsGroup->getColor( "LabelTextColor" ) ),
- mTextDisabledColor( LLUI::sColorsGroup->getColor( "LabelDisabledColor" ) ),
- mSliderMouseUpCallback( NULL ),
- mSliderMouseDownCallback( NULL )
+LLMultiSliderCtrl::LLMultiSliderCtrl(const LLMultiSliderCtrl::Params& p)
+: LLF32UICtrl(p),
+ mLabelBox( NULL ),
+ mEditor( NULL ),
+ mTextBox( NULL ),
+ mTextEnabledColor(p.text_color()),
+ mTextDisabledColor(p.text_disabled_color())
{
+ static LLUICachedControl<S32> multi_sliderctrl_spacing ("UIMultiSliderctrlSpacing", 0);
+
S32 top = getRect().getHeight();
S32 bottom = 0;
S32 left = 0;
+ S32 label_width = p.label_width;
+ S32 text_width = p.text_width;
+
// Label
- if( !label.empty() )
+ if( !p.label().empty() )
{
- if (label_width == 0)
+ if (p.label_width == 0)
{
- label_width = font->getWidth(label);
+ label_width = p.font()->getWidth(p.label);
}
LLRect label_rect( left, top, label_width, bottom );
- mLabelBox = new LLTextBox( std::string("MultiSliderCtrl Label"), label_rect, label, font );
+ LLTextBox::Params params;
+ params.name("MultiSliderCtrl Label");
+ params.rect(label_rect);
+ params.initial_value(p.label());
+ params.font(p.font);
+ mLabelBox = LLUICtrlFactory::create<LLTextBox> (params);
addChild(mLabelBox);
}
S32 slider_right = getRect().getWidth();
- if( show_text )
- {
- slider_right = text_left - MULTI_SLIDERCTRL_SPACING;
- }
- S32 slider_left = label_width ? label_width + MULTI_SLIDERCTRL_SPACING : 0;
- LLRect slider_rect( slider_left, top, slider_right, bottom );
- mMultiSlider = new LLMultiSlider(
- std::string("multi_slider"),
- slider_rect,
- LLMultiSliderCtrl::onSliderCommit, this,
- initial_value, min_value, max_value, increment,
- max_sliders, allow_overlap, draw_track,
- use_triangle,
- control_which );
- addChild( mMultiSlider );
- mCurValue = mMultiSlider->getCurSliderValue();
-
- if( show_text )
+ if (p.show_text)
{
+ if (!p.text_width.isProvided())
+ {
+ text_width = 0;
+ // calculate the size of the text box (log max_value is number of digits - 1 so plus 1)
+ if ( p.max_value() )
+ text_width = p.font()->getWidth(std::string("0")) * ( static_cast < S32 > ( log10 ( p.max_value ) ) + p.decimal_digits + 1 );
+
+ if ( p.increment < 1.0f )
+ text_width += p.font()->getWidth(std::string(".")); // (mostly) take account of decimal point in value
+
+ if ( p.min_value < 0.0f || p.max_value < 0.0f )
+ text_width += p.font()->getWidth(std::string("-")); // (mostly) take account of minus sign
+
+ // padding to make things look nicer
+ text_width += 8;
+ }
+ S32 text_left = getRect().getWidth() - text_width;
+
+ slider_right = text_left - multi_sliderctrl_spacing;
+
LLRect text_rect( text_left, top, getRect().getWidth(), bottom );
- if( can_edit_text )
+ if( p.can_edit_text )
{
- mEditor = new LLLineEditor( std::string("MultiSliderCtrl Editor"), text_rect,
- LLStringUtil::null, font,
- MAX_STRING_LENGTH,
- &LLMultiSliderCtrl::onEditorCommit, NULL, NULL, this,
- &LLLineEditor::prevalidateFloat );
- mEditor->setFollowsLeft();
- mEditor->setFollowsBottom();
- mEditor->setFocusReceivedCallback( &LLMultiSliderCtrl::onEditorGainFocus );
- mEditor->setIgnoreTab(TRUE);
+ LLLineEditor::Params params;
+ params.name("MultiSliderCtrl Editor");
+ params.rect(text_rect);
+ params.font(p.font);
+ params.max_length_bytes(MAX_STRING_LENGTH);
+ params.commit_callback.function(LLMultiSliderCtrl::onEditorCommit);
+ params.prevalidate_callback(&LLLineEditor::prevalidateFloat);
+ params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
+ mEditor = LLUICtrlFactory::create<LLLineEditor> (params);
+ mEditor->setFocusReceivedCallback( boost::bind(LLMultiSliderCtrl::onEditorGainFocus, _1, this) );
// don't do this, as selecting the entire text is single clicking in some cases
// and double clicking in others
//mEditor->setSelectAllonFocusReceived(TRUE);
@@ -141,13 +149,38 @@ LLMultiSliderCtrl::LLMultiSliderCtrl(const std::string& name, const LLRect& rect
}
else
{
- mTextBox = new LLTextBox( std::string("MultiSliderCtrl Text"), text_rect, LLStringUtil::null, font);
- mTextBox->setFollowsLeft();
- mTextBox->setFollowsBottom();
+ LLTextBox::Params params;
+ params.name("MultiSliderCtrl Text");
+ params.rect(text_rect);
+ params.font(p.font);
+ params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
+ mTextBox = LLUICtrlFactory::create<LLTextBox> (params);
addChild(mTextBox);
}
}
+ S32 slider_left = label_width ? label_width + multi_sliderctrl_spacing : 0;
+ LLRect slider_rect( slider_left, top, slider_right, bottom );
+ LLMultiSlider::Params params;
+ params.sliders = p.sliders;
+ params.rect(slider_rect);
+ params.commit_callback.function( LLMultiSliderCtrl::onSliderCommit );
+ params.mouse_down_callback( p.mouse_down_callback );
+ params.mouse_up_callback( p.mouse_up_callback );
+ params.initial_value(p.initial_value());
+ params.min_value(p.min_value);
+ params.max_value(p.max_value);
+ params.increment(p.increment);
+ params.max_sliders(p.max_sliders);
+ params.allow_overlap(p.allow_overlap);
+ params.draw_track(p.draw_track);
+ params.use_triangle(p.use_triangle);
+ params.control_name(p.control_name);
+ mMultiSlider = LLUICtrlFactory::create<LLMultiSlider> (params);
+ addChild( mMultiSlider );
+ mCurValue = mMultiSlider->getCurSliderValue();
+
+
updateText();
}
@@ -203,7 +236,8 @@ BOOL LLMultiSliderCtrl::setLabelArg( const std::string& key, const LLStringExpli
S32 delta = rect.mRight - prev_right;
rect = mMultiSlider->getRect();
S32 left = rect.mLeft + delta;
- left = llclamp(left, 0, rect.mRight-MULTI_SLIDERCTRL_SPACING);
+ static LLUICachedControl<S32> multi_slider_ctrl_spacing ("UIMultiSliderctrlSpacing", 0);
+ left = llclamp(left, 0, rect.mRight - multi_slider_ctrl_spacing);
rect.mLeft = left;
mMultiSlider->setRect(rect);
}
@@ -294,11 +328,12 @@ void LLMultiSliderCtrl::updateText()
}
// static
-void LLMultiSliderCtrl::onEditorCommit( LLUICtrl* caller, void *userdata )
+void LLMultiSliderCtrl::onEditorCommit( LLUICtrl* ctrl, const LLSD& userdata)
{
- LLMultiSliderCtrl* self = (LLMultiSliderCtrl*) userdata;
- llassert( caller == self->mEditor );
-
+ LLMultiSliderCtrl* self = dynamic_cast<LLMultiSliderCtrl*>(ctrl->getParent());
+ if (!ctrl)
+ return;
+
BOOL success = FALSE;
F32 val = self->mCurValue;
F32 saved_val = self->mCurValue;
@@ -310,17 +345,9 @@ void LLMultiSliderCtrl::onEditorCommit( LLUICtrl* caller, void *userdata )
val = (F32) atof( text.c_str() );
if( self->mMultiSlider->getMinValue() <= val && val <= self->mMultiSlider->getMaxValue() )
{
- if( self->mValidateCallback )
- {
- self->setCurSliderValue( val ); // set the value temporarily so that the callback can retrieve it.
- if( self->mValidateCallback( self, self->mCallbackUserData ) )
- {
- success = TRUE;
- }
- }
- else
+ self->setCurSliderValue( val ); // set the value temporarily so that the callback can retrieve it.
+ if( !self->mValidateSignal || (*(self->mValidateSignal))( self, val ) )
{
- self->setCurSliderValue( val );
success = TRUE;
}
}
@@ -342,26 +369,19 @@ void LLMultiSliderCtrl::onEditorCommit( LLUICtrl* caller, void *userdata )
}
// static
-void LLMultiSliderCtrl::onSliderCommit( LLUICtrl* caller, void *userdata )
+void LLMultiSliderCtrl::onSliderCommit(LLUICtrl* ctrl, const LLSD& userdata)
{
- LLMultiSliderCtrl* self = (LLMultiSliderCtrl*) userdata;
- //llassert( caller == self->mSlider );
-
+ LLMultiSliderCtrl* self = dynamic_cast<LLMultiSliderCtrl*>(ctrl->getParent());
+ if (!self)
+ return;
+
BOOL success = FALSE;
F32 saved_val = self->mCurValue;
F32 new_val = self->mMultiSlider->getCurSliderValue();
- if( self->mValidateCallback )
+ self->mCurValue = new_val; // set the value temporarily so that the callback can retrieve it.
+ if( !self->mValidateSignal || (*(self->mValidateSignal))( self, new_val ) )
{
- self->mCurValue = new_val; // set the value temporarily so that the callback can retrieve it.
- if( self->mValidateCallback( self, self->mCallbackUserData ) )
- {
- success = TRUE;
- }
- }
- else
- {
- self->mCurValue = new_val;
success = TRUE;
}
@@ -382,11 +402,11 @@ void LLMultiSliderCtrl::onSliderCommit( LLUICtrl* caller, void *userdata )
void LLMultiSliderCtrl::setEnabled(BOOL b)
{
- LLUICtrl::setEnabled( b );
+ LLF32UICtrl::setEnabled( b );
if( mLabelBox )
{
- mLabelBox->setColor( b ? mTextEnabledColor : mTextDisabledColor );
+ mLabelBox->setColor( b ? mTextEnabledColor.get() : mTextDisabledColor.get() );
}
mMultiSlider->setEnabled( b );
@@ -398,7 +418,7 @@ void LLMultiSliderCtrl::setEnabled(BOOL b)
if( mTextBox )
{
- mTextBox->setColor( b ? mTextEnabledColor : mTextDisabledColor );
+ mTextBox->setColor( b ? mTextEnabledColor.get() : mTextDisabledColor.get() );
}
}
@@ -409,7 +429,7 @@ void LLMultiSliderCtrl::setTentative(BOOL b)
{
mEditor->setTentative(b);
}
- LLUICtrl::setTentative(b);
+ LLF32UICtrl::setTentative(b);
}
@@ -422,7 +442,8 @@ void LLMultiSliderCtrl::onCommit()
mEditor->setTentative(FALSE);
}
- LLUICtrl::onCommit();
+ setControlValue(getValueF32());
+ LLF32UICtrl::onCommit();
}
@@ -438,37 +459,14 @@ void LLMultiSliderCtrl::setPrecision(S32 precision)
updateText();
}
-void LLMultiSliderCtrl::setSliderMouseDownCallback( void (*slider_mousedown_callback)(LLUICtrl* caller, void* userdata) )
+boost::signals2::connection LLMultiSliderCtrl::setSliderMouseDownCallback( const commit_signal_t::slot_type& cb )
{
- mSliderMouseDownCallback = slider_mousedown_callback;
- mMultiSlider->setMouseDownCallback( LLMultiSliderCtrl::onSliderMouseDown );
+ return mMultiSlider->setMouseDownCallback( cb );
}
-// static
-void LLMultiSliderCtrl::onSliderMouseDown(LLUICtrl* caller, void* userdata)
+boost::signals2::connection LLMultiSliderCtrl::setSliderMouseUpCallback( const commit_signal_t::slot_type& cb )
{
- LLMultiSliderCtrl* self = (LLMultiSliderCtrl*) userdata;
- if( self->mSliderMouseDownCallback )
- {
- self->mSliderMouseDownCallback( self, self->mCallbackUserData );
- }
-}
-
-
-void LLMultiSliderCtrl::setSliderMouseUpCallback( void (*slider_mouseup_callback)(LLUICtrl* caller, void* userdata) )
-{
- mSliderMouseUpCallback = slider_mouseup_callback;
- mMultiSlider->setMouseUpCallback( LLMultiSliderCtrl::onSliderMouseUp );
-}
-
-// static
-void LLMultiSliderCtrl::onSliderMouseUp(LLUICtrl* caller, void* userdata)
-{
- LLMultiSliderCtrl* self = (LLMultiSliderCtrl*) userdata;
- if( self->mSliderMouseUpCallback )
- {
- self->mSliderMouseUpCallback( self, self->mCallbackUserData );
- }
+ return mMultiSlider->setMouseUpCallback( cb );
}
void LLMultiSliderCtrl::onTabInto()
@@ -484,154 +482,9 @@ void LLMultiSliderCtrl::reportInvalidData()
make_ui_sound("UISndBadKeystroke");
}
-//virtual
-std::string LLMultiSliderCtrl::getControlName() const
-{
- return mMultiSlider->getControlName();
-}
-
// virtual
void LLMultiSliderCtrl::setControlName(const std::string& control_name, LLView* context)
{
mMultiSlider->setControlName(control_name, context);
}
-// virtual
-LLXMLNodePtr LLMultiSliderCtrl::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLUICtrl::getXML();
-
- node->createChild("show_text", TRUE)->setBoolValue(mShowText);
-
- node->createChild("can_edit_text", TRUE)->setBoolValue(mCanEditText);
-
- node->createChild("decimal_digits", TRUE)->setIntValue(mPrecision);
-
- if (mLabelBox)
- {
- node->createChild("label", TRUE)->setStringValue(mLabelBox->getText());
- }
-
- // TomY TODO: Do we really want to export the transient state of the slider?
- node->createChild("value", TRUE)->setFloatValue(mCurValue);
-
- if (mMultiSlider)
- {
- node->createChild("initial_val", TRUE)->setFloatValue(mMultiSlider->getInitialValue());
- node->createChild("min_val", TRUE)->setFloatValue(mMultiSlider->getMinValue());
- node->createChild("max_val", TRUE)->setFloatValue(mMultiSlider->getMaxValue());
- node->createChild("increment", TRUE)->setFloatValue(mMultiSlider->getIncrement());
- }
- addColorXML(node, mTextEnabledColor, "text_enabled_color", "LabelTextColor");
- addColorXML(node, mTextDisabledColor, "text_disabled_color", "LabelDisabledColor");
-
- return node;
-}
-
-LLView* LLMultiSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("multi_slider");
- node->getAttributeString("name", name);
-
- std::string label;
- node->getAttributeString("label", label);
-
- LLRect rect;
- createRect(node, rect, parent, LLRect());
-
- LLFontGL* font = LLView::selectFont(node);
-
- // HACK: Font might not be specified.
- if (!font)
- {
- font = LLFontGL::getFontSansSerifSmall();
- }
-
- S32 label_width = 0;
- node->getAttributeS32("label_width", label_width);
-
- BOOL show_text = TRUE;
- node->getAttributeBOOL("show_text", show_text);
-
- BOOL can_edit_text = FALSE;
- node->getAttributeBOOL("can_edit_text", can_edit_text);
-
- BOOL allow_overlap = FALSE;
- node->getAttributeBOOL("allow_overlap", allow_overlap);
-
- BOOL draw_track = TRUE;
- node->getAttributeBOOL("draw_track", draw_track);
-
- BOOL use_triangle = FALSE;
- node->getAttributeBOOL("use_triangle", use_triangle);
-
- F32 initial_value = 0.f;
- node->getAttributeF32("initial_val", initial_value);
-
- F32 min_value = 0.f;
- node->getAttributeF32("min_val", min_value);
-
- F32 max_value = 1.f;
- node->getAttributeF32("max_val", max_value);
-
- F32 increment = 0.1f;
- node->getAttributeF32("increment", increment);
-
- U32 precision = 3;
- node->getAttributeU32("decimal_digits", precision);
-
- S32 max_sliders = 1;
- node->getAttributeS32("max_sliders", max_sliders);
-
-
- S32 text_left = 0;
- if (show_text)
- {
- // calculate the size of the text box (log max_value is number of digits - 1 so plus 1)
- if ( max_value )
- text_left = font->getWidth(std::string("0")) * ( static_cast < S32 > ( log10 ( max_value ) ) + precision + 1 );
-
- if ( increment < 1.0f )
- text_left += font->getWidth(std::string(".")); // (mostly) take account of decimal point in value
-
- if ( min_value < 0.0f || max_value < 0.0f )
- text_left += font->getWidth(std::string("-")); // (mostly) take account of minus sign
-
- // padding to make things look nicer
- text_left += 8;
- }
-
- LLUICtrlCallback callback = NULL;
-
- if (label.empty())
- {
- label.assign(node->getTextContents());
- }
-
- LLMultiSliderCtrl* slider = new LLMultiSliderCtrl(name,
- rect,
- label,
- font,
- label_width,
- rect.getWidth() - text_left,
- show_text,
- can_edit_text,
- callback,
- NULL,
- initial_value,
- min_value,
- max_value,
- increment,
- max_sliders,
- allow_overlap,
- draw_track,
- use_triangle);
-
- slider->setPrecision(precision);
-
- slider->initFromXML(node, parent);
-
- slider->updateText();
-
- return slider;
-}
diff --git a/indra/llui/llmultisliderctrl.h b/indra/llui/llmultisliderctrl.h
index b62b5ec323..e8366d09c2 100644
--- a/indra/llui/llmultisliderctrl.h
+++ b/indra/llui/llmultisliderctrl.h
@@ -33,17 +33,12 @@
#ifndef LL_MULTI_SLIDERCTRL_H
#define LL_MULTI_SLIDERCTRL_H
-#include "lluictrl.h"
+#include "llf32uictrl.h"
#include "v4color.h"
#include "llmultislider.h"
#include "lltextbox.h"
#include "llrect.h"
-//
-// Constants
-//
-const S32 MULTI_SLIDERCTRL_SPACING = 4; // space between label, slider, and text
-const S32 MULTI_SLIDERCTRL_HEIGHT = 16;
//
// Classes
@@ -53,27 +48,37 @@ class LLLineEditor;
class LLSlider;
-class LLMultiSliderCtrl : public LLUICtrl
+class LLMultiSliderCtrl : public LLF32UICtrl
{
public:
- LLMultiSliderCtrl(const std::string& name,
- const LLRect& rect,
- const std::string& label,
- const LLFontGL* font,
- S32 slider_left,
- S32 text_left,
- BOOL show_text,
- BOOL can_edit_text,
- void (*commit_callback)(LLUICtrl*, void*),
- void* callback_userdata,
- F32 initial_value, F32 min_value, F32 max_value, F32 increment,
- S32 max_sliders, BOOL allow_overlap, BOOL draw_track,
- BOOL use_triangle,
- const std::string& control_which = LLStringUtil::null );
-
+ struct Params : public LLInitParam::Block<Params, LLF32UICtrl::Params>
+ {
+ Optional<S32> label_width,
+ text_width;
+ Optional<bool> show_text,
+ can_edit_text;
+ Optional<S32> decimal_digits;
+ Optional<S32> max_sliders;
+ Optional<bool> allow_overlap,
+ draw_track,
+ use_triangle;
+
+ Optional<LLUIColor> text_color,
+ text_disabled_color;
+
+ Optional<CommitCallbackParam> mouse_down_callback,
+ mouse_up_callback;
+
+ Multiple<LLMultiSlider::SliderParams> sliders;
+
+ Params();
+ };
+
+protected:
+ LLMultiSliderCtrl(const Params&);
+ friend class LLUICtrlFactory;
+public:
virtual ~LLMultiSliderCtrl();
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
F32 getSliderValue(const std::string& name) const;
void setSliderValue(const std::string& name, F32 v, BOOL from_event = FALSE);
@@ -87,8 +92,8 @@ public:
void setCurSlider(const std::string& name);
void setCurSliderValue(F32 val, BOOL from_event = false) { setSliderValue(mMultiSlider->getCurSlider(), val, from_event); }
- virtual void setMinValue(LLSD min_value) { setMinValue((F32)min_value.asReal()); }
- virtual void setMaxValue(LLSD max_value) { setMaxValue((F32)max_value.asReal()); }
+ virtual void setMinValue(const LLSD& min_value) { setMinValue((F32)min_value.asReal()); }
+ virtual void setMaxValue(const LLSD& max_value) { setMaxValue((F32)max_value.asReal()); }
BOOL isMouseHeldDown();
@@ -105,15 +110,15 @@ public:
void deleteSlider(const std::string& name);
void deleteCurSlider() { deleteSlider(mMultiSlider->getCurSlider()); }
- F32 getMinValue() { return mMultiSlider->getMinValue(); }
- F32 getMaxValue() { return mMultiSlider->getMaxValue(); }
+ F32 getMinValue() const { return mMultiSlider->getMinValue(); }
+ F32 getMaxValue() const { return mMultiSlider->getMaxValue(); }
void setLabel(const std::string& label) { if (mLabelBox) mLabelBox->setText(label); }
void setLabelColor(const LLColor4& c) { mTextEnabledColor = c; }
void setDisabledLabelColor(const LLColor4& c) { mTextDisabledColor = c; }
- void setSliderMouseDownCallback( void (*slider_mousedown_callback)(LLUICtrl* caller, void* userdata) );
- void setSliderMouseUpCallback( void (*slider_mouseup_callback)(LLUICtrl* caller, void* userdata) );
+ boost::signals2::connection setSliderMouseDownCallback( const commit_signal_t::slot_type& cb );
+ boost::signals2::connection setSliderMouseUpCallback( const commit_signal_t::slot_type& cb );
virtual void onTabInto();
@@ -121,13 +126,10 @@ public:
virtual void onCommit(); // mark not tentative, then commit
virtual void setControlName(const std::string& control_name, LLView* context);
- virtual std::string getControlName() const;
- static void onSliderCommit(LLUICtrl* caller, void* userdata);
- static void onSliderMouseDown(LLUICtrl* caller,void* userdata);
- static void onSliderMouseUp(LLUICtrl* caller,void* userdata);
-
- static void onEditorCommit(LLUICtrl* caller, void* userdata);
+ static void onSliderCommit(LLUICtrl* caller, const LLSD& userdata);
+
+ static void onEditorCommit(LLUICtrl* ctrl, const LLSD& userdata);
static void onEditorGainFocus(LLFocusableElement* caller, void *userdata);
static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata);
@@ -149,11 +151,8 @@ private:
LLLineEditor* mEditor;
LLTextBox* mTextBox;
- LLColor4 mTextEnabledColor;
- LLColor4 mTextDisabledColor;
-
- void (*mSliderMouseUpCallback)( LLUICtrl* ctrl, void* userdata );
- void (*mSliderMouseDownCallback)( LLUICtrl* ctrl, void* userdata );
+ LLUIColor mTextEnabledColor;
+ LLUIColor mTextDisabledColor;
};
#endif // LL_MULTI_SLIDERCTRL_H
diff --git a/indra/llui/llnotificationptr.h b/indra/llui/llnotificationptr.h
new file mode 100644
index 0000000000..0718f7d182
--- /dev/null
+++ b/indra/llui/llnotificationptr.h
@@ -0,0 +1,41 @@
+/**
+ * @file llnotificationptr.h
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef LLNOTIFICATIONPTR_H
+#define LLNOTIFICATIONPTR_H
+
+// Many classes just store a single LLNotificationPtr
+// and llnotifications.h is very large, so define this ligher header.
+#include <boost/shared_ptr.hpp>
+
+class LLNotification;
+typedef boost::shared_ptr<LLNotification> LLNotificationPtr;
+
+#endif
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 6b7dd0a3de..86989012ee 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -31,11 +31,16 @@
*/
#include "linden_common.h"
+
+#include "llnotifications.h"
+
+#include "llxmlnode.h"
+#include "lluictrl.h"
#include "lluictrlfactory.h"
#include "lldir.h"
#include "llsdserialize.h"
-
-#include "llnotifications.h"
+#include "lltrans.h"
+#include "llnotificationslistener.h"
#include <algorithm>
#include <boost/regex.hpp>
@@ -76,6 +81,11 @@ private:
void savePersistentNotifications()
{
+ /* NOTE: As of 2009-11-09 the reload of notifications on startup does not
+ work, and has not worked for months. Skip saving notifications until the
+ read can be fixed, because this hits the disk once per notification and
+ causes log spam. James
+
llinfos << "Saving open notifications to " << mFileName << llendl;
llofstream notify_file(mFileName.c_str());
@@ -102,6 +112,7 @@ private:
LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
formatter->format(output, notify_file, LLSDFormatter::OPTIONS_PRETTY);
+ */
}
void loadPersistentNotifications()
@@ -157,11 +168,17 @@ private:
bool filterIgnoredNotifications(LLNotificationPtr notification)
{
+ // filter everything if we are to ignore ALL
+ if(LLNotifications::instance().getIgnoreAllNotifications())
+ {
+ return false;
+ }
+
LLNotificationFormPtr form = notification->getForm();
// Check to see if the user wants to ignore this alert
if (form->getIgnoreType() != LLNotificationForm::IGNORE_NO)
{
- return LLUI::sConfigGroup->getWarning(notification->getName());
+ return LLUI::sSettingGroups["ignores"]->getBOOL(notification->getName());
}
return true;
@@ -182,7 +199,7 @@ bool handleIgnoredNotification(const LLSD& payload)
response = pNotif->getResponseTemplate(LLNotification::WITH_DEFAULT_BUTTON);
break;
case LLNotificationForm::IGNORE_WITH_LAST_RESPONSE:
- response = LLUI::sIgnoresGroup->getLLSD("Default" + pNotif->getName());
+ response = LLUI::sSettingGroups["ignores"]->getLLSD("Default" + pNotif->getName());
break;
case LLNotificationForm::IGNORE_SHOW_AGAIN:
break;
@@ -228,7 +245,7 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLXMLNodeP
LLSD item_entry;
std::string element_name = child->getName()->mString;
- if (element_name == "ignore")
+ if (element_name == "ignore" )
{
bool save_option = false;
child->getAttribute_bool("save_option", save_option);
@@ -240,10 +257,11 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLXMLNodeP
{
// remember last option chosen by user and automatically respond with that in the future
mIgnore = IGNORE_WITH_LAST_RESPONSE;
- LLUI::sIgnoresGroup->declareLLSD(std::string("Default") + name, "", std::string("Default response for notification " + name));
+ LLUI::sSettingGroups["ignores"]->declareLLSD(std::string("Default") + name, "", std::string("Default response for notification " + name));
}
child->getAttributeString("text", mIgnoreMsg);
- LLUI::sIgnoresGroup->addWarning(name);
+ BOOL show_notification = TRUE;
+ LLUI::sSettingGroups["ignores"]->declareBOOL(name, show_notification, "Ignore notification with this name", TRUE);
}
else
{
@@ -339,13 +357,13 @@ void LLNotificationForm::formatElements(const LLSD& substitutions)
if ((*it).has("text"))
{
std::string text = (*it)["text"].asString();
- text = LLNotification::format(text, substitutions);
+ LLStringUtil::format(text, substitutions);
(*it)["text"] = text;
}
if ((*it)["type"].asString() == "text" && (*it).has("value"))
{
std::string value = (*it)["value"].asString();
- value = LLNotification::format(value, substitutions);
+ LLStringUtil::format(value, substitutions);
(*it)["value"] = value;
}
}
@@ -366,6 +384,7 @@ LLNotificationTemplate::LLNotificationTemplate() :
mExpireSeconds(0),
mExpireOption(-1),
mURLOption(-1),
+ mURLOpenExternally(-1),
mUnique(false),
mPriority(NOTIFICATION_PRIORITY_NORMAL)
{
@@ -373,17 +392,28 @@ LLNotificationTemplate::LLNotificationTemplate() :
}
LLNotification::LLNotification(const LLNotification::Params& p) :
- mTimestamp(p.timestamp),
+ mTimestamp(p.time_stamp),
mSubstitutions(p.substitutions),
mPayload(p.payload),
mExpiresAt(0),
- mResponseFunctorName(p.functor_name),
- mTemporaryResponder(p.mTemporaryResponder),
+ mTemporaryResponder(false),
mRespondedTo(false),
mPriority(p.priority),
mCancelled(false),
mIgnored(false)
{
+ if (p.functor.name.isChosen())
+ {
+ mResponseFunctorName = p.functor.name;
+ }
+ else if (p.functor.function.isChosen())
+ {
+ mResponseFunctorName = LLUUID::generateNewID().asString();
+ LLNotificationFunctorRegistry::instance().registerFunctor(mResponseFunctorName, p.functor.function());
+
+ mTemporaryResponder = true;
+ }
+
mId.generate();
init(p.name, p.form_elements);
}
@@ -540,10 +570,11 @@ void LLNotification::respond(const LLSD& response)
if (mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO)
{
- LLUI::sIgnoresGroup->setWarning(getName(), !mIgnored);
+ BOOL show_notification = mIgnored ? FALSE : TRUE;
+ LLUI::sSettingGroups["ignores"]->setBOOL(getName(), show_notification);
if (mIgnored && mForm->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
{
- LLUI::sIgnoresGroup->setLLSD("Default" + getName(), response);
+ LLUI::sSettingGroups["ignores"]->setLLSD("Default" + getName(), response);
}
}
@@ -601,8 +632,12 @@ void LLNotification::init(const std::string& template_name, const LLSD& form_ele
if (!mTemplatep) return;
// add default substitutions
- // TODO: change this to read from the translatable strings file!
- mSubstitutions["SECOND_LIFE"] = "Second Life";
+ const LLStringUtil::format_map_t& default_args = LLTrans::getDefaultArgs();
+ for (LLStringUtil::format_map_t::const_iterator iter = default_args.begin();
+ iter != default_args.end(); ++iter)
+ {
+ mSubstitutions[iter->first] = iter->second;
+ }
mSubstitutions["_URL"] = getURL();
mSubstitutions["_NAME"] = template_name;
// TODO: something like this so that a missing alert is sensible:
@@ -636,64 +671,6 @@ std::string LLNotification::summarize() const
return s;
}
-//static
-std::string LLNotification::format(const std::string& s, const LLSD& substitutions)
-{
- if (!substitutions.isMap())
- {
- return s;
- }
-
- std::ostringstream output;
- // match strings like [NAME]
- const boost::regex key("\\[([0-9_A-Z]+)]");
-
- std::string::const_iterator start = s.begin();
- std::string::const_iterator end = s.end();
- boost::smatch match;
-
- while (boost::regex_search(start, end, match, key, boost::match_default))
- {
- bool found_replacement = false;
- std::string replacement;
-
- // see if we have a replacement for the bracketed string (without the brackets)
- // test first using has() because if we just look up with operator[] we get back an
- // empty string even if the value is missing. We want to distinguish between
- // missing replacements and deliberately empty replacement strings.
- if (substitutions.has(std::string(match[1].first, match[1].second)))
- {
- replacement = substitutions[std::string(match[1].first, match[1].second)].asString();
- found_replacement = true;
- }
- // if not, see if there's one WITH brackets
- else if (substitutions.has(std::string(match[0].first, match[0].second)))
- {
- replacement = substitutions[std::string(match[0].first, match[0].second)].asString();
- found_replacement = true;
- }
-
- if (found_replacement)
- {
- // found a replacement
- // "hello world" is output
- output << std::string(start, match[0].first) << replacement;
- }
- else
- {
- // we had no replacement, so leave the string we searched for so that it gets noticed by QA
- // "hello [NAME_NOT_FOUND]" is output
- output << std::string(start, match[0].second);
- }
-
- // update search position
- start = match[0].second;
- }
- // send the remainder of the string (with no further matches for bracketed names)
- output << std::string(start, end);
- return output.str();
-}
-
std::string LLNotification::getMessage() const
{
// all our callers cache this result, so it gives us more flexibility
@@ -701,20 +678,32 @@ std::string LLNotification::getMessage() const
// cache it in the notification
if (!mTemplatep)
return std::string();
- return format(mTemplatep->mMessage, mSubstitutions);
+
+ std::string message = mTemplatep->mMessage;
+ LLStringUtil::format(message, mSubstitutions);
+ return message;
}
std::string LLNotification::getLabel() const
{
- return (mTemplatep ? format(mTemplatep->mLabel, mSubstitutions) : "");
+ std::string label = mTemplatep->mLabel;
+ LLStringUtil::format(label, mSubstitutions);
+ return (mTemplatep ? label : "");
}
-
+std::string LLNotification::getURL() const
+{
+ if (!mTemplatep)
+ return std::string();
+ std::string url = mTemplatep->mURL;
+ LLStringUtil::format(url, mSubstitutions);
+ return (mTemplatep ? url : "");
+}
// =========================================================
// LLNotificationChannel implementation
// ---
-void LLNotificationChannelBase::connectChanged(const LLStandardSignal::slot_type& slot)
+LLBoundListener LLNotificationChannelBase::connectChangedImpl(const LLEventListener& slot)
{
// when someone wants to connect to a channel, we first throw them
// all of the notifications that are already in the channel
@@ -722,23 +711,32 @@ void LLNotificationChannelBase::connectChanged(const LLStandardSignal::slot_type
// only about new notifications
for (LLNotificationSet::iterator it = mItems.begin(); it != mItems.end(); ++it)
{
- slot.get_slot_function()(LLSD().insert("sigtype", "load").insert("id", (*it)->id()));
+ slot(LLSD().with("sigtype", "load").with("id", (*it)->id()));
}
// and then connect the signal so that all future notifications will also be
// forwarded.
- mChanged.connect(slot);
+ return mChanged.connect(slot);
}
-void LLNotificationChannelBase::connectPassedFilter(const LLStandardSignal::slot_type& slot)
+LLBoundListener LLNotificationChannelBase::connectAtFrontChangedImpl(const LLEventListener& slot)
+{
+ for (LLNotificationSet::iterator it = mItems.begin(); it != mItems.end(); ++it)
+ {
+ slot(LLSD().with("sigtype", "load").with("id", (*it)->id()));
+ }
+ return mChanged.connect(slot, boost::signals2::at_front);
+}
+
+LLBoundListener LLNotificationChannelBase::connectPassedFilterImpl(const LLEventListener& slot)
{
// these two filters only fire for notifications added after the current one, because
// they don't participate in the hierarchy.
- mPassedFilter.connect(slot);
+ return mPassedFilter.connect(slot);
}
-void LLNotificationChannelBase::connectFailedFilter(const LLStandardSignal::slot_type& slot)
+LLBoundListener LLNotificationChannelBase::connectFailedFilterImpl(const LLEventListener& slot)
{
- mFailedFilter.connect(slot);
+ return mFailedFilter.connect(slot);
}
// external call, conforms to our standard signature
@@ -896,8 +894,7 @@ mParent(parent)
else
{
LLNotificationChannelPtr p = LLNotifications::instance().getChannel(parent);
- LLStandardSignal::slot_type f = boost::bind(&LLNotificationChannelBase::updateItem, this, _1);
- p->connectChanged(f);
+ p->connectChanged(boost::bind(&LLNotificationChannelBase::updateItem, this, _1));
}
}
@@ -910,7 +907,7 @@ void LLNotificationChannel::setComparator(LLNotificationComparator comparator)
mItems.swap(s2);
// notify clients that we've been resorted
- mChanged(LLSD().insert("sigtype", "sort"));
+ mChanged(LLSD().with("sigtype", "sort"));
}
bool LLNotificationChannel::isEmpty() const
@@ -951,8 +948,12 @@ std::string LLNotificationChannel::summarize()
// LLNotifications implementation
// ---
LLNotifications::LLNotifications() : LLNotificationChannelBase(LLNotificationFilters::includeEverything,
- LLNotificationComparators::orderByUUID())
+ LLNotificationComparators::orderByUUID()),
+ mIgnoreAllNotifications(false)
{
+ LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2));
+
+ mListener.reset(new LLNotificationsListener(*this));
}
@@ -1093,18 +1094,18 @@ void LLNotifications::createDefaultChannels()
// connect action methods to these channels
LLNotifications::instance().getChannel("Expiration")->
- connectChanged(boost::bind(&LLNotifications::expirationHandler, this, _1));
+ connectChanged(boost::bind(&LLNotifications::expirationHandler, this, _1));
+ // uniqueHandler slot should be added as first slot of the signal due to
+ // usage LLStopWhenHandled combiner in LLStandardSignal
LLNotifications::instance().getChannel("Unique")->
- connectChanged(boost::bind(&LLNotifications::uniqueHandler, this, _1));
- LLNotifications::instance().getChannel("Unique")->
- connectFailedFilter(boost::bind(&LLNotifications::failedUniquenessTest, this, _1));
+ connectAtFrontChanged(boost::bind(&LLNotifications::uniqueHandler, this, _1));
+// failedUniquenessTest slot isn't necessary
+// LLNotifications::instance().getChannel("Unique")->
+// connectFailedFilter(boost::bind(&LLNotifications::failedUniquenessTest, this, _1));
LLNotifications::instance().getChannel("Ignore")->
connectFailedFilter(&handleIgnoredNotification);
}
-static std::string sStringSkipNextTime("Skip this dialog next time");
-static std::string sStringAlwaysChoose("Always choose this option");
-
bool LLNotifications::addTemplate(const std::string &name,
LLNotificationTemplatePtr theTemplate)
{
@@ -1325,8 +1326,17 @@ bool LLNotifications::loadTemplates()
item->getAttributeString("sound", sound);
if (!sound.empty())
{
- // TODO: test for bad sound effect name / missing effect
- pTemplate->mSoundEffect = LLUUID(LLUI::sConfigGroup->getString(sound.c_str()));
+ // test for bad sound effect name / missing effect
+ if (LLUI::sSettingGroups["config"]->controlExists(sound))
+ {
+ pTemplate->mSoundEffect =
+ LLUUID(LLUI::sSettingGroups["config"]->getString(sound));
+ }
+ else
+ {
+ llwarns << "Unknown sound effect control name " << sound
+ << llendl;
+ }
}
for (LLXMLNodePtr child = item->getFirstChild();
@@ -1339,6 +1349,7 @@ bool LLNotifications::loadTemplates()
{
pTemplate->mURL = child->getTextContents();
child->getAttributeU32("option", pTemplate->mURLOption);
+ child->getAttributeU32("openexternally", pTemplate->mURLOpenExternally);
}
if (child->hasName("unique"))
@@ -1378,28 +1389,40 @@ bool LLNotifications::loadTemplates()
return true;
}
-// we provide a couple of simple add notification functions so that it's reasonable to create notifications in one line
-LLNotificationPtr LLNotifications::add(const std::string& name,
- const LLSD& substitutions,
- const LLSD& payload)
+// Add a simple notification (from XUI)
+void LLNotifications::addFromCallback(const LLSD& name)
{
- return add(LLNotification::Params(name).substitutions(substitutions).payload(payload));
+ add(LLNotification::Params().name(name.asString()));
}
LLNotificationPtr LLNotifications::add(const std::string& name,
- const LLSD& substitutions,
- const LLSD& payload,
- const std::string& functor_name)
+ const LLSD& substitutions,
+ const LLSD& payload)
{
- return add(LLNotification::Params(name).substitutions(substitutions).payload(payload).functor_name(functor_name));
+ LLNotification::Params::Functor functor_p;
+ functor_p.name = name;
+ return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));
}
LLNotificationPtr LLNotifications::add(const std::string& name,
+ const LLSD& substitutions,
+ const LLSD& payload,
+ const std::string& functor_name)
+{
+ LLNotification::Params::Functor functor_p;
+ functor_p.name = functor_name;
+ return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));
+}
+
+//virtual
+LLNotificationPtr LLNotifications::add(const std::string& name,
const LLSD& substitutions,
const LLSD& payload,
LLNotificationFunctorRegistry::ResponseFunctor functor)
{
- return add(LLNotification::Params(name).substitutions(substitutions).payload(payload).functor(functor));
+ LLNotification::Params::Functor functor_p;
+ functor_p.function = functor;
+ return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));
}
// generalized add function that takes a parameter block object for more complex instantiations
@@ -1420,7 +1443,7 @@ void LLNotifications::add(const LLNotificationPtr pNotif)
llerrs << "Notification added a second time to the master notification channel." << llendl;
}
- updateItem(LLSD().insert("sigtype", "add").insert("id", pNotif->id()), pNotif);
+ updateItem(LLSD().with("sigtype", "add").with("id", pNotif->id()), pNotif);
}
void LLNotifications::cancel(LLNotificationPtr pNotif)
@@ -1430,8 +1453,8 @@ void LLNotifications::cancel(LLNotificationPtr pNotif)
{
llerrs << "Attempted to delete nonexistent notification " << pNotif->getName() << llendl;
}
- updateItem(LLSD().insert("sigtype", "delete").insert("id", pNotif->id()), pNotif);
pNotif->cancel();
+ updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif);
}
void LLNotifications::update(const LLNotificationPtr pNotif)
@@ -1439,7 +1462,7 @@ void LLNotifications::update(const LLNotificationPtr pNotif)
LLNotificationSet::iterator it=mItems.find(pNotif);
if (it != mItems.end())
{
- updateItem(LLSD().insert("sigtype", "change").insert("id", pNotif->id()), pNotif);
+ updateItem(LLSD().with("sigtype", "change").with("id", pNotif->id()), pNotif);
}
}
@@ -1479,6 +1502,14 @@ std::string LLNotifications::getGlobalString(const std::string& key) const
}
}
+void LLNotifications::setIgnoreAllNotifications(bool setting)
+{
+ mIgnoreAllNotifications = setting;
+}
+bool LLNotifications::getIgnoreAllNotifications()
+{
+ return mIgnoreAllNotifications;
+}
// ---
// END OF LLNotifications implementation
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index bb379121cc..aeb4cebf1b 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -91,48 +91,19 @@
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
-#include <boost/signal.hpp>
+#include <boost/enable_shared_from_this.hpp>
#include <boost/type_traits.hpp>
// we want to minimize external dependencies, but this one is important
#include "llsd.h"
// and we need this to manage the notification callbacks
+#include "llevents.h"
#include "llfunctorregistry.h"
-#include "llui.h"
-
-class LLNotification;
-typedef boost::shared_ptr<LLNotification> LLNotificationPtr;
-
-/*****************************************************************************
-* Signal and handler declarations
-* Using a single handler signature means that we can have a common handler
-* type, rather than needing a distinct one for each different handler.
-*****************************************************************************/
-
-/**
- * A boost::signals Combiner that stops the first time a handler returns true
- * We need this because we want to have our handlers return bool, so that
- * we have the option to cause a handler to stop further processing. The
- * default handler fails when the signal returns a value but has no slots.
- */
-struct LLStopWhenHandled
-{
- typedef bool result_type;
-
- template<typename InputIterator>
- result_type operator()(InputIterator first, InputIterator last) const
- {
- for (InputIterator si = first; si != last; ++si)
- {
- if (*si)
- {
- return true;
- }
- }
- return false;
- }
-};
+#include "llpointer.h"
+#include "llinitparam.h"
+#include "llnotificationslistener.h"
+#include "llnotificationptr.h"
typedef enum e_notification_priority
@@ -144,27 +115,11 @@ typedef enum e_notification_priority
NOTIFICATION_PRIORITY_CRITICAL
} ENotificationPriority;
-/**
- * We want to have a standard signature for all signals; this way,
- * we can easily document a protocol for communicating across
- * dlls and into scripting languages someday.
- * we want to return a bool to indicate whether the signal has been
- * handled and should NOT be passed on to other listeners.
- * Return true to stop further handling of the signal, and false
- * to continue.
- * We take an LLSD because this way the contents of the signal
- * are independent of the API used to communicate it.
- * It is const ref because then there's low cost to pass it;
- * if you only need to inspect it, it's very cheap.
- */
-
typedef boost::function<void (const LLSD&, const LLSD&)> LLNotificationResponder;
typedef LLFunctorRegistry<LLNotificationResponder> LLNotificationFunctorRegistry;
typedef LLFunctorRegistration<LLNotificationResponder> LLNotificationFunctorRegistration;
-typedef boost::signal<bool(const LLSD&), LLStopWhenHandled> LLStandardSignal;
-
// context data that can be looked up via a notification's payload by the display logic
// derive from this class to implement specific contexts
class LLNotificationContext : public LLInstanceTracker<LLNotificationContext, LLUUID>
@@ -202,7 +157,8 @@ public:
LLNotificationForm();
LLNotificationForm(const LLSD& sd);
- LLNotificationForm(const std::string& name, const LLXMLNodePtr xml_node);
+ LLNotificationForm(const std::string& name,
+ const LLPointer<class LLXMLNode> xml_node);
LLSD asLLSD() const;
@@ -280,6 +236,11 @@ struct LLNotificationTemplate
// that URL. Obsolete this and eliminate the buttons for affected
// messages when we allow clickable URLs in the UI
U32 mURLOption;
+
+ U32 mURLOpenExternally;
+ //This is a flag that tells if the url needs to open externally dispite
+ //what the user setting is.
+
// does this notification persist across sessions? if so, it will be
// serialized to disk on first receipt and read on startup
bool mPersist;
@@ -322,42 +283,53 @@ friend class LLNotifications;
public:
// parameter object used to instantiate a new notification
- class Params : public LLParamBlock<Params>
+ struct Params : public LLInitParam::Block<Params>
{
friend class LLNotification;
- public:
- Params(const std::string& _name)
- : name(_name),
- mTemporaryResponder(false),
- functor_name(_name),
- priority(NOTIFICATION_PRIORITY_UNSPECIFIED),
- timestamp(LLDate::now())
+
+ Mandatory<std::string> name;
+
+ // optional
+ Optional<LLSD> substitutions;
+ Optional<LLSD> payload;
+ Optional<ENotificationPriority> priority;
+ Optional<LLSD> form_elements;
+ Optional<LLDate> time_stamp;
+ Optional<LLNotificationContext*> context;
+
+ struct Functor : public LLInitParam::Choice<Functor>
{
+ Alternative<std::string> name;
+ Alternative<LLNotificationFunctorRegistry::ResponseFunctor> function;
+
+ Functor()
+ : name("functor_name"),
+ function("functor")
+ {}
+ };
+ Optional<Functor> functor;
+
+ Params()
+ : name("name"),
+ priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED),
+ time_stamp("time_stamp"),
+ payload("payload"),
+ form_elements("form_elements")
+ {
+ time_stamp = LLDate::now();
}
- // pseudo-param
- Params& functor(LLNotificationFunctorRegistry::ResponseFunctor f)
- {
- functor_name = LLUUID::generateNewID().asString();
- LLNotificationFunctorRegistry::instance().registerFunctor(functor_name, f);
-
- mTemporaryResponder = true;
- return *this;
+ Params(const std::string& _name)
+ : name("name"),
+ priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED),
+ time_stamp("time_stamp"),
+ payload("payload"),
+ form_elements("form_elements")
+ {
+ functor.name = _name;
+ name = _name;
+ time_stamp = LLDate::now();
}
-
- LLMandatoryParam<std::string> name;
-
- // optional
- LLOptionalParam<LLSD> substitutions;
- LLOptionalParam<LLSD> payload;
- LLOptionalParam<ENotificationPriority> priority;
- LLOptionalParam<LLSD> form_elements;
- LLOptionalParam<LLDate> timestamp;
- LLOptionalParam<LLNotificationContext*> context;
- LLOptionalParam<std::string> functor_name;
-
- private:
- bool mTemporaryResponder;
};
private:
@@ -410,10 +382,6 @@ public:
// constructor from a saved notification
LLNotification(const LLSD& sd);
- // This is a string formatter for substituting into the message directly
- // from LLSD without going through the hopefully-to-be-obsoleted LLString
- static std::string format(const std::string& text, const LLSD& substitutions);
-
void setResponseFunctor(std::string const &responseFunctorName);
typedef enum e_response_template_type
@@ -505,16 +473,21 @@ public:
std::string getMessage() const;
std::string getLabel() const;
- std::string getURL() const
- {
- return (mTemplatep ? mTemplatep->mURL : "");
- }
+ std::string getURL() const;
+// {
+// return (mTemplatep ? mTemplatep->mURL : "");
+// }
S32 getURLOption() const
{
return (mTemplatep ? mTemplatep->mURLOption : -1);
}
-
+
+ S32 getURLOpenExternally() const
+ {
+ return(mTemplatep? mTemplatep->mURLOpenExternally : -1);
+ }
+
const LLNotificationFormPtr getForm();
const LLDate getExpiration() const
@@ -699,7 +672,7 @@ typedef std::multimap<std::string, LLNotificationPtr> LLNotificationMap;
// all of the built-in tests should attach to the "Visible" channel
//
class LLNotificationChannelBase :
- public boost::signals::trackable
+ public LLEventTrackable
{
LOG_CLASS(LLNotificationChannelBase);
public:
@@ -709,15 +682,54 @@ public:
virtual ~LLNotificationChannelBase() {}
// you can also connect to a Channel, so you can be notified of
// changes to this channel
- virtual void connectChanged(const LLStandardSignal::slot_type& slot);
- virtual void connectPassedFilter(const LLStandardSignal::slot_type& slot);
- virtual void connectFailedFilter(const LLStandardSignal::slot_type& slot);
+ template <typename LISTENER>
+ LLBoundListener connectChanged(const LISTENER& slot)
+ {
+ // Examine slot to see if it binds an LLEventTrackable subclass, or a
+ // boost::shared_ptr to something, or a boost::weak_ptr to something.
+ // Call this->connectChangedImpl() to actually connect it.
+ return LLEventDetail::visit_and_connect(slot,
+ boost::bind(&LLNotificationChannelBase::connectChangedImpl,
+ this,
+ _1));
+ }
+ template <typename LISTENER>
+ LLBoundListener connectAtFrontChanged(const LISTENER& slot)
+ {
+ return LLEventDetail::visit_and_connect(slot,
+ boost::bind(&LLNotificationChannelBase::connectAtFrontChangedImpl,
+ this,
+ _1));
+ }
+ template <typename LISTENER>
+ LLBoundListener connectPassedFilter(const LISTENER& slot)
+ {
+ // see comments in connectChanged()
+ return LLEventDetail::visit_and_connect(slot,
+ boost::bind(&LLNotificationChannelBase::connectPassedFilterImpl,
+ this,
+ _1));
+ }
+ template <typename LISTENER>
+ LLBoundListener connectFailedFilter(const LISTENER& slot)
+ {
+ // see comments in connectChanged()
+ return LLEventDetail::visit_and_connect(slot,
+ boost::bind(&LLNotificationChannelBase::connectFailedFilterImpl,
+ this,
+ _1));
+ }
// use this when items change or to add a new one
bool updateItem(const LLSD& payload);
const LLNotificationFilter& getFilter() { return mFilter; }
protected:
+ LLBoundListener connectChangedImpl(const LLEventListener& slot);
+ LLBoundListener connectAtFrontChangedImpl(const LLEventListener& slot);
+ LLBoundListener connectPassedFilterImpl(const LLEventListener& slot);
+ LLBoundListener connectFailedFilterImpl(const LLEventListener& slot);
+
LLNotificationSet mItems;
LLStandardSignal mChanged;
LLStandardSignal mPassedFilter;
@@ -799,9 +811,19 @@ private:
LLNotificationComparator mComparator;
};
-
+// An interface class to provide a clean linker seam to the LLNotifications class.
+// Extend this interface as needed for your use of LLNotifications.
+class LLNotificationsInterface
+{
+public:
+ virtual LLNotificationPtr add(const std::string& name,
+ const LLSD& substitutions,
+ const LLSD& payload,
+ LLNotificationFunctorRegistry::ResponseFunctor functor) = 0;
+};
class LLNotifications :
+ public LLNotificationsInterface,
public LLSingleton<LLNotifications>,
public LLNotificationChannelBase
{
@@ -812,17 +834,21 @@ public:
// load notification descriptions from file;
// OK to call more than once because it will reload
bool loadTemplates();
- LLXMLNodePtr checkForXMLTemplate(LLXMLNodePtr item);
-
- // we provide a collection of simple add notification functions so that it's reasonable to create notifications in one line
+ LLPointer<class LLXMLNode> checkForXMLTemplate(LLPointer<class LLXMLNode> item);
+
+ // Add a simple notification (from XUI)
+ void addFromCallback(const LLSD& name);
+
+ // *NOTE: To add simple notifications, #include "llnotificationsutil.h"
+ // and use LLNotificationsUtil::add("MyNote") or add("MyNote", args)
LLNotificationPtr add(const std::string& name,
- const LLSD& substitutions = LLSD(),
- const LLSD& payload = LLSD());
+ const LLSD& substitutions,
+ const LLSD& payload);
LLNotificationPtr add(const std::string& name,
const LLSD& substitutions,
const LLSD& payload,
const std::string& functor_name);
- LLNotificationPtr add(const std::string& name,
+ /* virtual */ LLNotificationPtr add(const std::string& name,
const LLSD& substitutions,
const LLSD& payload,
LLNotificationFunctorRegistry::ResponseFunctor functor);
@@ -868,6 +894,9 @@ public:
std::string getGlobalString(const std::string& key) const;
+ void setIgnoreAllNotifications(bool ignore);
+ bool getIgnoreAllNotifications();
+
private:
// we're a singleton, so we don't have a public constructor
LLNotifications();
@@ -889,13 +918,17 @@ private:
std::string mFileName;
- typedef std::map<std::string, LLXMLNodePtr> XMLTemplateMap;
+ typedef std::map<std::string, LLPointer<class LLXMLNode> > XMLTemplateMap;
XMLTemplateMap mXmlTemplates;
LLNotificationMap mUniqueNotifications;
typedef std::map<std::string, std::string> GlobalStringMap;
GlobalStringMap mGlobalStrings;
+
+ bool mIgnoreAllNotifications;
+
+ boost::scoped_ptr<LLNotificationsListener> mListener;
};
diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp
new file mode 100644
index 0000000000..ee6ec0f88f
--- /dev/null
+++ b/indra/llui/llnotificationslistener.cpp
@@ -0,0 +1,332 @@
+/**
+ * @file llnotificationslistener.cpp
+ * @author Brad Kittenbrink
+ * @date 2009-07-08
+ * @brief Implementation for llnotificationslistener.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llnotificationslistener.h"
+#include "llnotifications.h"
+#include "llsd.h"
+#include "llui.h"
+
+LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications) :
+ LLEventAPI("LLNotifications",
+ "LLNotifications listener to (e.g.) pop up a notification"),
+ mNotifications(notifications)
+{
+ add("requestAdd",
+ "Add a notification with specified [\"name\"], [\"substitutions\"] and [\"payload\"].\n"
+ "If optional [\"reply\"] specified, arrange to send user response on that LLEventPump.",
+ &LLNotificationsListener::requestAdd);
+ add("listChannels",
+ "Post to [\"reply\"] a map of info on existing channels",
+ &LLNotificationsListener::listChannels,
+ LLSD().with("reply", LLSD()));
+ add("listChannelNotifications",
+ "Post to [\"reply\"] an array of info on notifications in channel [\"channel\"]",
+ &LLNotificationsListener::listChannelNotifications,
+ LLSD().with("reply", LLSD()).with("channel", LLSD()));
+ add("respond",
+ "Respond to notification [\"uuid\"] with data in [\"response\"]",
+ &LLNotificationsListener::respond,
+ LLSD().with("uuid", LLSD()));
+ add("cancel",
+ "Cancel notification [\"uuid\"]",
+ &LLNotificationsListener::cancel,
+ LLSD().with("uuid", LLSD()));
+ add("ignore",
+ "Ignore future notification [\"name\"]\n"
+ "(from <notification name= > in notifications.xml)\n"
+ "according to boolean [\"ignore\"].\n"
+ "If [\"name\"] is omitted or undefined, [un]ignore all future notifications.\n"
+ "Note that ignored notifications are not forwarded unless intercepted before\n"
+ "the \"Ignore\" channel.",
+ &LLNotificationsListener::ignore);
+ add("forward",
+ "Forward to [\"pump\"] future notifications on channel [\"channel\"]\n"
+ "according to boolean [\"forward\"]. When enabled, only types matching\n"
+ "[\"types\"] are forwarded, as follows:\n"
+ "omitted or undefined: forward all notifications\n"
+ "string: forward only the specific named [sig]type\n"
+ "array of string: forward any notification matching any named [sig]type.\n"
+ "When boolean [\"respond\"] is true, we auto-respond to each forwarded\n"
+ "notification.",
+ &LLNotificationsListener::forward,
+ LLSD().with("channel", LLSD()));
+}
+
+// This is here in the .cpp file so we don't need the definition of class
+// Forwarder in the header file.
+LLNotificationsListener::~LLNotificationsListener()
+{
+}
+
+void LLNotificationsListener::requestAdd(const LLSD& event_data) const
+{
+ if(event_data.has("reply"))
+ {
+ mNotifications.add(event_data["name"],
+ event_data["substitutions"],
+ event_data["payload"],
+ boost::bind(&LLNotificationsListener::NotificationResponder,
+ this,
+ event_data["reply"].asString(),
+ _1, _2
+ )
+ );
+ }
+ else
+ {
+ mNotifications.add(event_data["name"],
+ event_data["substitutions"],
+ event_data["payload"]);
+ }
+}
+
+void LLNotificationsListener::NotificationResponder(const std::string& reply_pump,
+ const LLSD& notification,
+ const LLSD& response) const
+{
+ LLSD reponse_event;
+ reponse_event["notification"] = notification;
+ reponse_event["response"] = response;
+ LLEventPumps::getInstance()->obtain(reply_pump).post(reponse_event);
+}
+
+void LLNotificationsListener::listChannels(const LLSD& params) const
+{
+ LLReqID reqID(params);
+ LLSD response(reqID.makeResponse());
+ for (LLNotifications::ChannelMap::const_iterator cmi(mNotifications.mChannels.begin()),
+ cmend(mNotifications.mChannels.end());
+ cmi != cmend; ++cmi)
+ {
+ LLSD channelInfo;
+ channelInfo["parent"] = cmi->second->getParentChannelName();
+ response[cmi->first] = channelInfo;
+ }
+ LLEventPumps::instance().obtain(params["reply"]).post(response);
+}
+
+void LLNotificationsListener::listChannelNotifications(const LLSD& params) const
+{
+ LLReqID reqID(params);
+ LLSD response(reqID.makeResponse());
+ LLNotificationChannelPtr channel(mNotifications.getChannel(params["channel"]));
+ if (channel)
+ {
+ LLSD notifications(LLSD::emptyArray());
+ for (LLNotificationChannel::Iterator ni(channel->begin()), nend(channel->end());
+ ni != nend; ++ni)
+ {
+ notifications.append(asLLSD(*ni));
+ }
+ response["notifications"] = notifications;
+ }
+ LLEventPumps::instance().obtain(params["reply"]).post(response);
+}
+
+void LLNotificationsListener::respond(const LLSD& params) const
+{
+ LLNotificationPtr notification(mNotifications.find(params["uuid"]));
+ if (notification)
+ {
+ notification->respond(params["response"]);
+ }
+}
+
+void LLNotificationsListener::cancel(const LLSD& params) const
+{
+ LLNotificationPtr notification(mNotifications.find(params["uuid"]));
+ if (notification)
+ {
+ mNotifications.cancel(notification);
+ }
+}
+
+void LLNotificationsListener::ignore(const LLSD& params) const
+{
+ // Calling a method named "ignore", but omitting its "ignore" Boolean
+ // argument, should by default cause something to be ignored. Explicitly
+ // pass ["ignore"] = false to cancel ignore.
+ bool ignore = true;
+ if (params.has("ignore"))
+ {
+ ignore = params["ignore"].asBoolean();
+ }
+ // This method can be used to affect either a single notification name or
+ // all future notifications. The two use substantially different mechanisms.
+ if (params["name"].isDefined())
+ {
+ // ["name"] was passed: ignore just that notification
+ LLUI::sSettingGroups["ignores"]->setBOOL(params["name"], ignore);
+ }
+ else
+ {
+ // no ["name"]: ignore all future notifications
+ mNotifications.setIgnoreAllNotifications(ignore);
+ }
+}
+
+class LLNotificationsListener::Forwarder: public LLEventTrackable
+{
+ LOG_CLASS(LLNotificationsListener::Forwarder);
+public:
+ Forwarder(LLNotifications& llnotifications, const std::string& channel):
+ mNotifications(llnotifications),
+ mRespond(false)
+ {
+ // Connect to the specified channel on construction. Because
+ // LLEventTrackable is a base, we should automatically disconnect when
+ // destroyed.
+ LLNotificationChannelPtr channelptr(llnotifications.getChannel(channel));
+ if (channelptr)
+ {
+ // Insert our processing as a "passed filter" listener. This way
+ // we get to run before all the "changed" listeners, and we get to
+ // swipe it (hide it from the other listeners) if desired.
+ channelptr->connectPassedFilter(boost::bind(&Forwarder::handle, this, _1));
+ }
+ }
+
+ void setPumpName(const std::string& name) { mPumpName = name; }
+ void setTypes(const LLSD& types) { mTypes = types; }
+ void setRespond(bool respond) { mRespond = respond; }
+
+private:
+ bool handle(const LLSD& notification) const;
+ bool matchType(const LLSD& filter, const std::string& type) const;
+
+ LLNotifications& mNotifications;
+ std::string mPumpName;
+ LLSD mTypes;
+ bool mRespond;
+};
+
+void LLNotificationsListener::forward(const LLSD& params)
+{
+ std::string channel(params["channel"]);
+ // First decide whether we're supposed to start forwarding or stop it.
+ // Default to true.
+ bool forward = true;
+ if (params.has("forward"))
+ {
+ forward = params["forward"].asBoolean();
+ }
+ if (! forward)
+ {
+ // This is a request to stop forwarding notifications on the specified
+ // channel. The rest of the params don't matter.
+ // Because mForwarders contains scoped_ptrs, erasing the map entry
+ // DOES delete the heap Forwarder object. Because Forwarder derives
+ // from LLEventTrackable, destroying it disconnects it from the
+ // channel.
+ mForwarders.erase(channel);
+ return;
+ }
+ // From here on, we know we're being asked to start (or modify) forwarding
+ // on the specified channel. Find or create an appropriate Forwarder.
+ ForwarderMap::iterator
+ entry(mForwarders.insert(ForwarderMap::value_type(channel, ForwarderMap::mapped_type())).first);
+ if (! entry->second)
+ {
+ entry->second.reset(new Forwarder(mNotifications, channel));
+ }
+ // Now, whether this Forwarder is brand-new or not, update it with the new
+ // request info.
+ Forwarder& fwd(*entry->second);
+ fwd.setPumpName(params["pump"]);
+ fwd.setTypes(params["types"]);
+ fwd.setRespond(params["respond"]);
+}
+
+bool LLNotificationsListener::Forwarder::handle(const LLSD& notification) const
+{
+ LL_INFOS("LLNotificationsListener") << "handle(" << notification << ")" << LL_ENDL;
+ if (notification["sigtype"].asString() == "delete")
+ {
+ LL_INFOS("LLNotificationsListener") << "ignoring delete" << LL_ENDL;
+ // let other listeners see the "delete" operation
+ return false;
+ }
+ LLNotificationPtr note(mNotifications.find(notification["id"]));
+ if (! note)
+ {
+ LL_INFOS("LLNotificationsListener") << notification["id"] << " not found" << LL_ENDL;
+ return false;
+ }
+ if (! matchType(mTypes, note->getType()))
+ {
+ LL_INFOS("LLNotificationsListener") << "didn't match types " << mTypes << LL_ENDL;
+ // We're not supposed to intercept this particular notification. Let
+ // other listeners process it.
+ return false;
+ }
+ LL_INFOS("LLNotificationsListener") << "sending via '" << mPumpName << "'" << LL_ENDL;
+ // This is a notification we care about. Forward it through specified
+ // LLEventPump.
+ LLEventPumps::instance().obtain(mPumpName).post(asLLSD(note));
+ // Are we also being asked to auto-respond?
+ if (mRespond)
+ {
+ LL_INFOS("LLNotificationsListener") << "should respond" << LL_ENDL;
+ note->respond(LLSD::emptyMap());
+ // Did that succeed in removing the notification? Only cancel() if
+ // it's still around -- otherwise we get an LL_ERRS crash!
+ note = mNotifications.find(notification["id"]);
+ if (note)
+ {
+ LL_INFOS("LLNotificationsListener") << "respond() didn't clear, canceling" << LL_ENDL;
+ mNotifications.cancel(note);
+ }
+ }
+ // If we've auto-responded to this notification, then it's going to be
+ // deleted. Other listeners would get the change operation, try to look it
+ // up and be baffled by lookup failure. So when we auto-respond, suppress
+ // this notification: don't pass it to other listeners.
+ return mRespond;
+}
+
+bool LLNotificationsListener::Forwarder::matchType(const LLSD& filter, const std::string& type) const
+{
+ // Decide whether this notification matches filter:
+ // undefined: forward all notifications
+ if (filter.isUndefined())
+ {
+ return true;
+ }
+ // array of string: forward any notification matching any named type
+ if (filter.isArray())
+ {
+ for (LLSD::array_const_iterator ti(filter.beginArray()), tend(filter.endArray());
+ ti != tend; ++ti)
+ {
+ if (ti->asString() == type)
+ {
+ return true;
+ }
+ }
+ // Didn't match any entry in the array
+ return false;
+ }
+ // string: forward only the specific named type
+ return (filter.asString() == type);
+}
+
+LLSD LLNotificationsListener::asLLSD(LLNotificationPtr note)
+{
+ LLSD notificationInfo(note->asLLSD());
+ // For some reason the following aren't included in LLNotification::asLLSD().
+ notificationInfo["summary"] = note->summarize();
+ notificationInfo["id"] = note->id();
+ notificationInfo["type"] = note->getType();
+ notificationInfo["message"] = note->getMessage();
+ notificationInfo["label"] = note->getLabel();
+ return notificationInfo;
+}
diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h
new file mode 100644
index 0000000000..de208b57f0
--- /dev/null
+++ b/indra/llui/llnotificationslistener.h
@@ -0,0 +1,52 @@
+/**
+ * @file llnotificationslistener.h
+ * @author Brad Kittenbrink
+ * @date 2009-07-08
+ * @brief Wrap subset of LLNotifications API in event API for test scripts.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLNOTIFICATIONSLISTENER_H
+#define LL_LLNOTIFICATIONSLISTENER_H
+
+#include "lleventapi.h"
+#include "llnotificationptr.h"
+#include <boost/shared_ptr.hpp>
+#include <map>
+#include <string>
+
+class LLNotifications;
+class LLSD;
+
+class LLNotificationsListener : public LLEventAPI
+{
+public:
+ LLNotificationsListener(LLNotifications & notifications);
+ ~LLNotificationsListener();
+
+private:
+ void requestAdd(LLSD const & event_data) const;
+
+ void NotificationResponder(const std::string& replypump,
+ const LLSD& notification,
+ const LLSD& response) const;
+
+ void listChannels(const LLSD& params) const;
+ void listChannelNotifications(const LLSD& params) const;
+ void respond(const LLSD& params) const;
+ void cancel(const LLSD& params) const;
+ void ignore(const LLSD& params) const;
+ void forward(const LLSD& params);
+
+ static LLSD asLLSD(LLNotificationPtr);
+
+ class Forwarder;
+ typedef std::map<std::string, boost::shared_ptr<Forwarder> > ForwarderMap;
+ ForwarderMap mForwarders;
+ LLNotifications & mNotifications;
+};
+
+#endif // LL_LLNOTIFICATIONSLISTENER_H
diff --git a/indra/llui/llnotificationsutil.cpp b/indra/llui/llnotificationsutil.cpp
new file mode 100644
index 0000000000..f343d27cb4
--- /dev/null
+++ b/indra/llui/llnotificationsutil.cpp
@@ -0,0 +1,96 @@
+/**
+ * @file llnotificationsutil.cpp
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+
+#include "llnotificationsutil.h"
+
+#include "llnotifications.h"
+#include "llsd.h"
+#include "llxmlnode.h" // apparently needed to call LLNotifications::instance()
+
+LLNotificationPtr LLNotificationsUtil::add(const std::string& name)
+{
+ LLNotification::Params::Functor functor_p;
+ functor_p.name = name;
+ return LLNotifications::instance().add(
+ LLNotification::Params().name(name).substitutions(LLSD()).payload(LLSD()).functor(functor_p));
+}
+
+LLNotificationPtr LLNotificationsUtil::add(const std::string& name,
+ const LLSD& substitutions)
+{
+ LLNotification::Params::Functor functor_p;
+ functor_p.name = name;
+ return LLNotifications::instance().add(
+ LLNotification::Params().name(name).substitutions(substitutions).payload(LLSD()).functor(functor_p));
+}
+
+LLNotificationPtr LLNotificationsUtil::add(const std::string& name,
+ const LLSD& substitutions,
+ const LLSD& payload)
+{
+ LLNotification::Params::Functor functor_p;
+ functor_p.name = name;
+ return LLNotifications::instance().add(
+ LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));
+}
+
+LLNotificationPtr LLNotificationsUtil::add(const std::string& name,
+ const LLSD& substitutions,
+ const LLSD& payload,
+ const std::string& functor_name)
+{
+ LLNotification::Params::Functor functor_p;
+ functor_p.name = functor_name;
+ return LLNotifications::instance().add(
+ LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));
+}
+
+LLNotificationPtr LLNotificationsUtil::add(const std::string& name,
+ const LLSD& substitutions,
+ const LLSD& payload,
+ boost::function<void (const LLSD&, const LLSD&)> functor)
+{
+ LLNotification::Params::Functor functor_p;
+ functor_p.function = functor;
+ return LLNotifications::instance().add(
+ LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));
+}
+
+S32 LLNotificationsUtil::getSelectedOption(const LLSD& notification, const LLSD& response)
+{
+ return LLNotification::getSelectedOption(notification, response);
+}
+
+void LLNotificationsUtil::cancel(LLNotificationPtr pNotif)
+{
+ LLNotifications::instance().cancel(pNotif);
+}
diff --git a/indra/llui/llnotificationsutil.h b/indra/llui/llnotificationsutil.h
new file mode 100644
index 0000000000..d552fa915b
--- /dev/null
+++ b/indra/llui/llnotificationsutil.h
@@ -0,0 +1,70 @@
+/**
+ * @file llnotificationsutil.h
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef LLNOTIFICATIONSUTIL_H
+#define LLNOTIFICATIONSUTIL_H
+
+// The vast majority of clients of the notifications system just want to add
+// a notification to the screen, so define this lightweight public interface
+// to avoid including the heavyweight llnotifications.h
+
+#include "llnotificationptr.h"
+
+#include <boost/function.hpp>
+
+class LLSD;
+
+namespace LLNotificationsUtil
+{
+ LLNotificationPtr add(const std::string& name);
+
+ LLNotificationPtr add(const std::string& name,
+ const LLSD& substitutions);
+
+ LLNotificationPtr add(const std::string& name,
+ const LLSD& substitutions,
+ const LLSD& payload);
+
+ LLNotificationPtr add(const std::string& name,
+ const LLSD& substitutions,
+ const LLSD& payload,
+ const std::string& functor_name);
+
+ LLNotificationPtr add(const std::string& name,
+ const LLSD& substitutions,
+ const LLSD& payload,
+ boost::function<void (const LLSD&, const LLSD&)> functor);
+
+ S32 getSelectedOption(const LLSD& notification, const LLSD& response);
+
+ void cancel(LLNotificationPtr pNotif);
+}
+
+#endif
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index 28780c7adb..7f23fe2671 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -34,15 +34,17 @@
#include "linden_common.h"
+#define LLPANEL_CPP
#include "llpanel.h"
-#include "llalertdialog.h"
#include "llfocusmgr.h"
#include "llfontgl.h"
#include "llrect.h"
#include "llerror.h"
#include "lltimer.h"
+#include "llaccordionctrltab.h"
+#include "llbutton.h"
#include "llmenugl.h"
//#include "llstatusbar.h"
#include "llui.h"
@@ -53,75 +55,78 @@
#include "lluictrl.h"
#include "lluictrlfactory.h"
#include "llviewborder.h"
-#include "llbutton.h"
-
-// LLLayoutStack
-#include "llresizebar.h"
-#include "llcriticaldamp.h"
-
-const S32 RESIZE_BAR_OVERLAP = 1;
-const S32 RESIZE_BAR_HEIGHT = 3;
-
-static LLRegisterWidget<LLPanel> r1("panel");
-
-void LLPanel::init()
-{
- // mRectControl
- mBgColorAlpha = LLUI::sColorsGroup->getColor( "DefaultBackgroundColor" );
- mBgColorOpaque = LLUI::sColorsGroup->getColor( "FocusBackgroundColor" );
- mDefaultBtnHighlight = LLUI::sColorsGroup->getColor( "DefaultHighlightLight" );
- mBgVisible = FALSE;
- mBgOpaque = FALSE;
- mBorder = NULL;
- mDefaultBtn = NULL;
- setIsChrome(FALSE); //is this a decorator to a live window or a form?
- mLastTabGroup = 0;
-
- mPanelHandle.bind(this);
- setTabStop(FALSE);
-}
-
-LLPanel::LLPanel()
-: mRectControl()
-{
- init();
- setName(std::string("panel"));
-}
-
-LLPanel::LLPanel(const std::string& name)
-: LLUICtrl(name, LLRect(0, 0, 0, 0), TRUE, NULL, NULL),
- mRectControl()
-{
- init();
-}
-
-
-LLPanel::LLPanel(const std::string& name, const LLRect& rect, BOOL bordered)
-: LLUICtrl(name, rect, TRUE, NULL, NULL),
- mRectControl()
-{
- init();
- if (bordered)
- {
- addBorder();
- }
-}
-
-
-LLPanel::LLPanel(const std::string& name, const std::string& rect_control, BOOL bordered)
-: LLUICtrl(name, LLUI::sConfigGroup->getRect(rect_control), TRUE, NULL, NULL),
- mRectControl( rect_control )
-{
- init();
- if (bordered)
- {
- addBorder();
+#include "lltabcontainer.h"
+
+static LLDefaultChildRegistry::Register<LLPanel> r1("panel", &LLPanel::fromXML);
+
+// Compiler optimization, generate extern template
+template class LLPanel* LLView::getChild<class LLPanel>(
+ const std::string& name, BOOL recurse) const;
+
+LLPanel::LocalizedString::LocalizedString()
+: name("name"),
+ value("value")
+{}
+
+const LLPanel::Params& LLPanel::getDefaultParams()
+{
+ return LLUICtrlFactory::getDefaultParams<LLPanel>();
+}
+
+LLPanel::Params::Params()
+: has_border("border", false),
+ border(""),
+ background_visible("background_visible", false),
+ background_opaque("background_opaque", false),
+ bg_opaque_color("bg_opaque_color"),
+ bg_alpha_color("bg_alpha_color"),
+ bg_opaque_image("bg_opaque_image"),
+ bg_alpha_image("bg_alpha_image"),
+ min_width("min_width", 100),
+ min_height("min_height", 100),
+ strings("string"),
+ filename("filename"),
+ class_name("class"),
+ help_topic("help_topic"),
+ visible_callback("visible_callback")
+{
+ name = "panel";
+ addSynonym(background_visible, "bg_visible");
+ addSynonym(has_border, "border_visible");
+ addSynonym(label, "title");
+}
+
+
+LLPanel::LLPanel(const LLPanel::Params& p)
+: LLUICtrl(p),
+ mBgVisible(p.background_visible),
+ mBgOpaque(p.background_opaque),
+ mBgOpaqueColor(p.bg_opaque_color()),
+ mBgAlphaColor(p.bg_alpha_color()),
+ mBgOpaqueImage(p.bg_opaque_image()),
+ mBgAlphaImage(p.bg_alpha_image()),
+ mDefaultBtn(NULL),
+ mBorder(NULL),
+ mLabel(p.label),
+ mHelpTopic(p.help_topic),
+ mCommitCallbackRegistrar(false),
+ mEnableCallbackRegistrar(false),
+ mXMLFilename(p.filename),
+ mVisibleSignal(NULL)
+ // *NOTE: Be sure to also change LLPanel::initFromParams(). We have too
+ // many classes derived from LLPanel to retrofit them all to pass in params.
+{
+ if (p.has_border)
+ {
+ addBorder(p.border);
}
+
+ mPanelHandle.bind(this);
}
LLPanel::~LLPanel()
{
- storeRectControl();
+ delete mVisibleSignal;
}
// virtual
@@ -130,27 +135,31 @@ BOOL LLPanel::isPanel() const
return TRUE;
}
-// virtual
-BOOL LLPanel::postBuild()
-{
- return TRUE;
-}
-
-void LLPanel::addBorder(LLViewBorder::EBevel border_bevel,
- LLViewBorder::EStyle border_style, S32 border_thickness)
+void LLPanel::addBorder(LLViewBorder::Params p)
{
removeBorder();
- mBorder = new LLViewBorder( std::string("panel border"),
- LLRect(0, getRect().getHeight(), getRect().getWidth(), 0),
- border_bevel, border_style, border_thickness );
- mBorder->setSaveToXML(false);
+ p.rect = getLocalRect();
+
+ mBorder = LLUICtrlFactory::create<LLViewBorder>(p);
addChild( mBorder );
}
+void LLPanel::addBorder()
+{
+ LLViewBorder::Params p;
+ p.border_thickness(LLPANEL_BORDER_WIDTH);
+ addBorder(p);
+}
+
+
void LLPanel::removeBorder()
{
- delete mBorder;
- mBorder = NULL;
+ if (mBorder)
+ {
+ removeChild(mBorder);
+ delete mBorder;
+ mBorder = NULL;
+ }
}
@@ -179,22 +188,36 @@ void LLPanel::setCtrlsEnabled( BOOL b )
void LLPanel::draw()
{
+ F32 alpha = getDrawContext().mAlpha;
+
// draw background
if( mBgVisible )
{
- //RN: I don't see the point of this
- S32 left = 0;//LLPANEL_BORDER_WIDTH;
- S32 top = getRect().getHeight();// - LLPANEL_BORDER_WIDTH;
- S32 right = getRect().getWidth();// - LLPANEL_BORDER_WIDTH;
- S32 bottom = 0;//LLPANEL_BORDER_WIDTH;
-
+ LLRect local_rect = getLocalRect();
if (mBgOpaque )
{
- gl_rect_2d( left, top, right, bottom, mBgColorOpaque );
+ // opaque, in-front look
+ if (mBgOpaqueImage.notNull())
+ {
+ mBgOpaqueImage->draw( local_rect, UI_VERTEX_COLOR % alpha );
+ }
+ else
+ {
+ // fallback to flat colors when there are no images
+ gl_rect_2d( local_rect, mBgOpaqueColor.get() % alpha);
+ }
}
else
{
- gl_rect_2d( left, top, right, bottom, mBgColorAlpha );
+ // transparent, in-back look
+ if (mBgAlphaImage.notNull())
+ {
+ mBgAlphaImage->draw( local_rect, UI_VERTEX_COLOR % alpha );
+ }
+ else
+ {
+ gl_rect_2d( local_rect, mBgAlphaColor.get() % alpha );
+ }
}
}
@@ -205,16 +228,11 @@ void LLPanel::draw()
void LLPanel::updateDefaultBtn()
{
- // This method does not call LLView::draw() so callers will need
- // to take care of that themselves at the appropriate place in
- // their rendering sequence
-
if( mDefaultBtn)
{
if (gFocusMgr.childHasKeyboardFocus( this ) && mDefaultBtn->getEnabled())
{
- LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus();
- LLButton* buttonp = dynamic_cast<LLButton*>(focus_ctrl);
+ LLButton* buttonp = dynamic_cast<LLButton*>(gFocusMgr.getKeyboardFocus());
BOOL focus_is_child_button = buttonp && buttonp->getCommitOnReturn();
// only enable default button when current focus is not a return-capturing button
mDefaultBtn->setBorderEnabled(!focus_is_child_button);
@@ -258,30 +276,16 @@ void LLPanel::setDefaultBtn(const std::string& id)
}
}
-void LLPanel::addCtrl( LLUICtrl* ctrl, S32 tab_group)
-{
- mLastTabGroup = tab_group;
-
- LLView::addCtrl(ctrl, tab_group);
-}
-
-void LLPanel::addCtrlAtEnd( LLUICtrl* ctrl, S32 tab_group)
-{
- mLastTabGroup = tab_group;
-
- LLView::addCtrlAtEnd(ctrl, tab_group);
-}
-
BOOL LLPanel::handleKeyHere( KEY key, MASK mask )
{
BOOL handled = FALSE;
- LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus();
+ LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
// handle user hitting ESC to defocus
if (key == KEY_ESCAPE)
{
- gFocusMgr.setKeyboardFocus(NULL);
+ setFocus(FALSE);
return TRUE;
}
else if( (mask == MASK_SHIFT) && (KEY_TAB == key))
@@ -308,29 +312,26 @@ BOOL LLPanel::handleKeyHere( KEY key, MASK mask )
}
}
}
-
- // If we have a default button, click it when
- // return is pressed, unless current focus is a return-capturing button
- // in which case *that* button will handle the return key
- LLButton* focused_button = dynamic_cast<LLButton*>(cur_focus);
- if (cur_focus && !(focused_button && focused_button->getCommitOnReturn()))
+
+ // If RETURN was pressed and something has focus, call onCommit()
+ if (!handled && cur_focus && key == KEY_RETURN && mask == MASK_NONE)
{
- // RETURN key means hit default button in this case
- if (key == KEY_RETURN && mask == MASK_NONE
- && mDefaultBtn != NULL
- && mDefaultBtn->getVisible()
- && mDefaultBtn->getEnabled())
+ LLButton* focused_button = dynamic_cast<LLButton*>(cur_focus);
+ if (focused_button && focused_button->getCommitOnReturn())
+ {
+ // current focus is a return-capturing button,
+ // let *that* button handle the return key
+ handled = FALSE;
+ }
+ else if (mDefaultBtn && mDefaultBtn->getVisible() && mDefaultBtn->getEnabled())
{
+ // If we have a default button, click it when return is pressed
mDefaultBtn->onCommit();
handled = TRUE;
}
- }
-
- if (key == KEY_RETURN && mask == MASK_NONE)
- {
- // set keyboard focus to self to trigger commitOnFocusLost behavior on current ctrl
- if (cur_focus && cur_focus->acceptsTextInput())
+ else if (cur_focus->acceptsTextInput())
{
+ // call onCommit for text input handling control
cur_focus->onCommit();
handled = TRUE;
}
@@ -339,55 +340,25 @@ BOOL LLPanel::handleKeyHere( KEY key, MASK mask )
return handled;
}
-BOOL LLPanel::checkRequirements()
+void LLPanel::handleVisibilityChange ( BOOL new_visibility )
{
- if (!mRequirementsError.empty())
- {
- LLSD args;
- args["COMPONENTS"] = mRequirementsError;
- args["FLOATER"] = getName();
-
- llwarns << getName() << " failed requirements check on: \n"
- << mRequirementsError << llendl;
-
- LLNotifications::instance().add(LLNotification::Params("FailedRequirementsCheck").payload(args));
- mRequirementsError.clear();
- return FALSE;
- }
-
- return TRUE;
+ LLUICtrl::handleVisibilityChange ( new_visibility );
+ if (mVisibleSignal)
+ (*mVisibleSignal)(this, LLSD(new_visibility) ); // Pass BOOL as LLSD
}
void LLPanel::setFocus(BOOL b)
{
- if( b )
+ if( b && !hasFocus())
{
- if (!gFocusMgr.childHasKeyboardFocus(this))
- {
- //refresh();
- if (!focusFirstItem())
- {
- LLUICtrl::setFocus(TRUE);
- }
- onFocusReceived();
- }
+ // give ourselves focus preemptively, to avoid infinite loop
+ LLUICtrl::setFocus(TRUE);
+ // then try to pass to first valid child
+ focusFirstItem();
}
else
{
- if( this == gFocusMgr.getKeyboardFocus() )
- {
- gFocusMgr.setKeyboardFocus( NULL );
- }
- else
- {
- //RN: why is this here?
- LLView::ctrl_list_t ctrls = getCtrlList();
- for (LLView::ctrl_list_t::iterator ctrl_it = ctrls.begin(); ctrl_it != ctrls.end(); ++ctrl_it)
- {
- LLUICtrl* ctrl = *ctrl_it;
- ctrl->setFocus( FALSE );
- }
- }
+ LLUICtrl::setFocus(b);
}
}
@@ -399,191 +370,208 @@ void LLPanel::setBorderVisible(BOOL b)
}
}
-// virtual
-LLXMLNodePtr LLPanel::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLView::getXML();
+LLFastTimer::DeclareTimer FTM_PANEL_CONSTRUCTION("Panel Construction");
- if (mBorder && mBorder->getVisible())
- {
- node->createChild("border", TRUE)->setBoolValue(TRUE);
- }
-
- if (!mRectControl.empty())
- {
- node->createChild("rect_control", TRUE)->setStringValue(mRectControl);
- }
+LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLXMLNodePtr output_node)
+{
+ std::string name("panel");
+ node->getAttributeString("name", name);
- if (!mLabel.empty())
- {
- node->createChild("label", TRUE)->setStringValue(mLabel);
- }
+ std::string class_attr;
+ node->getAttributeString("class", class_attr);
- if (save_children)
+ LLPanel* panelp = NULL;
+
{
- LLView::child_list_const_reverse_iter_t rit;
- for (rit = getChildList()->rbegin(); rit != getChildList()->rend(); ++rit)
+ LLFastTimer timer(FTM_PANEL_CONSTRUCTION);
+
+ if(!class_attr.empty())
{
- LLView* childp = *rit;
-
- if (childp->getSaveToXML())
+ panelp = LLRegisterPanelClass::instance().createPanelClass(class_attr);
+ if (!panelp)
{
- LLXMLNodePtr xml_node = childp->getXML();
-
- node->addChild(xml_node);
+ llwarns << "Panel class \"" << class_attr << "\" not registered." << llendl;
}
}
- }
-
- return node;
-}
-LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory *factory)
-{
- std::string name("panel");
- node->getAttributeString("name", name);
+ if (!panelp)
+ {
+ panelp = LLUICtrlFactory::getInstance()->createFactoryPanel(name);
+ }
- LLPanel* panelp = factory->createFactoryPanel(name);
- // Fall back on a default panel, if there was no special factory.
- if (!panelp)
- {
- LLRect rect;
- createRect(node, rect, parent, LLRect());
- // create a new panel without a border, by default
- panelp = new LLPanel(name, rect, FALSE);
- panelp->initPanelXML(node, parent, factory);
- // preserve panel's width and height, but override the location
- const LLRect& panelrect = panelp->getRect();
- S32 w = panelrect.getWidth();
- S32 h = panelrect.getHeight();
- rect.setLeftTopAndSize(rect.mLeft, rect.mTop, w, h);
- panelp->setRect(rect);
}
- else
+ // factory panels may have registered their own factory maps
+ if (!panelp->getFactoryMap().empty())
+ {
+ LLUICtrlFactory::instance().pushFactoryFunctions(&panelp->getFactoryMap());
+ }
+ // for local registry callbacks; define in constructor, referenced in XUI or postBuild
+ panelp->mCommitCallbackRegistrar.pushScope();
+ panelp->mEnableCallbackRegistrar.pushScope();
+
+ panelp->initPanelXML(node, parent, output_node);
+
+ panelp->mCommitCallbackRegistrar.popScope();
+ panelp->mEnableCallbackRegistrar.popScope();
+
+ if (panelp && !panelp->getFactoryMap().empty())
{
- panelp->initPanelXML(node, parent, factory);
+ LLUICtrlFactory::instance().popFactoryFunctions();
}
return panelp;
}
-BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
+void LLPanel::initFromParams(const LLPanel::Params& p)
{
- std::string name = getName();
- node->getAttributeString("name", name);
- setName(name);
-
- setPanelParameters(node, parent);
-
- initChildrenXML(node, factory);
-
- std::string xml_filename;
- node->getAttributeString("filename", xml_filename);
+ //setting these here since panel constructor not called with params
+ //and LLView::initFromParams will use them to set visible and enabled
+ setVisible(p.visible);
+ setEnabled(p.enabled);
- BOOL didPost;
+ setSoundFlags(p.sound_flags);
- if (!xml_filename.empty())
+ // control_name, tab_stop, focus_lost_callback, initial_value, rect, enabled, visible
+ LLUICtrl::initFromParams(p);
+
+ // visible callback
+ if (p.visible_callback.isProvided())
{
- didPost = factory->buildPanel(this, xml_filename, NULL);
-
- LLRect new_rect = getRect();
- // override rectangle with embedding parameters as provided
- createRect(node, new_rect, parent);
- setOrigin(new_rect.mLeft, new_rect.mBottom);
- reshape(new_rect.getWidth(), new_rect.getHeight());
- // optionally override follows flags from including nodes
- parseFollowsFlags(node);
+ setVisibleCallback(initCommitCallback(p.visible_callback));
}
- else
+
+ for (LLInitParam::ParamIterator<LocalizedString>::const_iterator it = p.strings().begin();
+ it != p.strings().end();
+ ++it)
{
- didPost = FALSE;
+ mUIStrings[it->name] = it->value;
}
+
+ setLabel(p.label());
+ setHelpTopic(p.help_topic);
+ setShape(p.rect);
+ parseFollowsFlags(p);
+
+ setToolTip(p.tool_tip());
+ setFromXUI(p.from_xui);
+
+ mHoverCursor = getCursorFromString(p.hover_cursor);
- if (!didPost)
+ if (p.has_border)
{
- postBuild();
- didPost = TRUE;
+ addBorder(p.border);
}
-
- return didPost;
+ // let constructors set this value if not provided
+ if (p.use_bounding_rect.isProvided())
+ {
+ setUseBoundingRect(p.use_bounding_rect);
+ }
+ setDefaultTabGroup(p.default_tab_group);
+ setMouseOpaque(p.mouse_opaque);
+
+ setBackgroundVisible(p.background_visible);
+ setBackgroundOpaque(p.background_opaque);
+ setBackgroundColor(p.bg_opaque_color().get());
+ setTransparentColor(p.bg_alpha_color().get());
+ mBgOpaqueImage = p.bg_opaque_image();
+ mBgAlphaImage = p.bg_alpha_image();
}
-void LLPanel::initChildrenXML(LLXMLNodePtr node, LLUICtrlFactory* factory)
+static LLFastTimer::DeclareTimer FTM_PANEL_SETUP("Panel Setup");
+static LLFastTimer::DeclareTimer FTM_EXTERNAL_PANEL_LOAD("Load Extern Panel Reference");
+static LLFastTimer::DeclareTimer FTM_PANEL_POSTBUILD("Panel PostBuild");
+
+BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)
{
- LLXMLNodePtr child;
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
+ const LLPanel::Params& default_params(LLUICtrlFactory::getDefaultParams<LLPanel>());
+ Params params(default_params);
+
{
- // look for string declarations for programmatic text
- if (child->hasName("string"))
+ LLFastTimer timer(FTM_PANEL_SETUP);
+
+ LLXMLNodePtr referenced_xml;
+ std::string xml_filename = mXMLFilename;
+
+ // if the panel didn't provide a filename, check the node
+ if (xml_filename.empty())
{
- std::string string_name;
- child->getAttributeString("name", string_name);
- if (!string_name.empty())
- {
- mUIStrings[string_name] = child->getTextContents();
- }
+ node->getAttributeString("filename", xml_filename);
}
- else
+
+ if (!xml_filename.empty())
{
- factory->createWidget(this, child);
- }
- }
-}
+ LLFastTimer timer(FTM_EXTERNAL_PANEL_LOAD);
+ if (output_node)
+ {
+ //if we are exporting, we want to export the current xml
+ //not the referenced xml
+ LLXUIParser::instance().readXUI(node, params, xml_filename);
+ Params output_params(params);
+ setupParamsForExport(output_params, parent);
+ output_node->setName(node->getName()->mString);
+ LLXUIParser::instance().writeXUI(
+ output_node, output_params, &default_params);
+ return TRUE;
+ }
+
+ if (!LLUICtrlFactory::getLayeredXMLNode(xml_filename, referenced_xml))
+ {
+ llwarns << "Couldn't parse panel from: " << xml_filename << llendl;
-void LLPanel::setPanelParameters(LLXMLNodePtr node, LLView* parent)
-{
- /////// Rect, follows, tool_tip, enabled, visible attributes ///////
- initFromXML(node, parent);
+ return FALSE;
+ }
- /////// Border attributes ///////
- BOOL border = mBorder != NULL;
- node->getAttributeBOOL("border", border);
- if (border)
- {
- LLViewBorder::EBevel bevel_style = LLViewBorder::BEVEL_OUT;
- LLViewBorder::getBevelFromAttribute(node, bevel_style);
+ LLXUIParser::instance().readXUI(referenced_xml, params, xml_filename);
- LLViewBorder::EStyle border_style = LLViewBorder::STYLE_LINE;
- std::string border_string;
- node->getAttributeString("border_style", border_string);
- LLStringUtil::toLower(border_string);
+ // add children using dimensions from referenced xml for consistent layout
+ setShape(params.rect);
+ LLUICtrlFactory::createChildren(this, referenced_xml, child_registry_t::instance());
+
+ setXMLFilename(xml_filename);
+ }
- if (border_string == "texture")
+ // ask LLUICtrlFactory for filename, since xml_filename might be empty
+ LLXUIParser::instance().readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
+
+ if (output_node)
{
- border_style = LLViewBorder::STYLE_TEXTURE;
+ Params output_params(params);
+ setupParamsForExport(output_params, parent);
+ output_node->setName(node->getName()->mString);
+ LLXUIParser::instance().writeXUI(
+ output_node, output_params, &default_params);
+ }
+
+ params.from_xui = true;
+ applyXUILayout(params, parent);
+ {
+ LLFastTimer timer(FTM_PANEL_CONSTRUCTION);
+ initFromParams(params);
}
- S32 border_thickness = LLPANEL_BORDER_WIDTH;
- node->getAttributeS32("border_thickness", border_thickness);
+ // add children
+ LLUICtrlFactory::createChildren(this, node, child_registry_t::instance(), output_node);
- addBorder(bevel_style, border_style, border_thickness);
- }
- else
- {
- removeBorder();
+ // Connect to parent after children are built, because tab containers
+ // do a reshape() on their child panels, which requires that the children
+ // be built/added. JC
+ if (parent)
+ {
+ S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : parent->getLastTabGroup();
+ parent->addChild(this, tab_group);
+ }
+
+ {
+ LLFastTimer timer(FTM_PANEL_POSTBUILD);
+ postBuild();
+ }
}
+ return TRUE;
+}
- /////// Background attributes ///////
- BOOL background_visible = mBgVisible;
- node->getAttributeBOOL("background_visible", background_visible);
- setBackgroundVisible(background_visible);
-
- BOOL background_opaque = mBgOpaque;
- node->getAttributeBOOL("background_opaque", background_opaque);
- setBackgroundOpaque(background_opaque);
-
- LLColor4 color;
- color = mBgColorOpaque;
- LLUICtrlFactory::getAttributeColor(node,"bg_opaque_color", color);
- setBackgroundColor(color);
-
- color = mBgColorAlpha;
- LLUICtrlFactory::getAttributeColor(node,"bg_alpha_color", color);
- setTransparentColor(color);
-
- std::string label = getLabel();
- node->getAttributeString("label", label);
- setLabel(label);
+bool LLPanel::hasString(const std::string& name)
+{
+ return mUIStrings.find(name) != mUIStrings.end();
}
std::string LLPanel::getString(const std::string& name, const LLStringUtil::format_map_t& args) const
@@ -597,9 +585,7 @@ std::string LLPanel::getString(const std::string& name, const LLStringUtil::form
return formatted_string.getString();
}
std::string err_str("Failed to find string " + name + " in panel " + getName()); //*TODO: Translate
- // *TODO: once the QAR-369 ui-cleanup work on settings is in we need to change the following line to be
- //if(LLUI::sConfigGroup->getBOOL("QAMode"))
- if(LLUI::sQAMode)
+ if(LLUI::sSettingGroups["config"]->getBOOL("QAMode"))
{
llerrs << err_str << llendl;
}
@@ -618,7 +604,7 @@ std::string LLPanel::getString(const std::string& name) const
return found_it->second;
}
std::string err_str("Failed to find string " + name + " in panel " + getName()); //*TODO: Translate
- if(LLUI::sQAMode)
+ if(LLUI::sSettingGroups["config"]->getBOOL("QAMode"))
{
llerrs << err_str << llendl;
}
@@ -632,7 +618,7 @@ std::string LLPanel::getString(const std::string& name) const
void LLPanel::childSetVisible(const std::string& id, bool visible)
{
- LLView* child = getChild<LLView>(id);
+ LLView* child = findChild<LLView>(id);
if (child)
{
child->setVisible(visible);
@@ -641,7 +627,7 @@ void LLPanel::childSetVisible(const std::string& id, bool visible)
bool LLPanel::childIsVisible(const std::string& id) const
{
- LLView* child = getChild<LLView>(id);
+ LLView* child = findChild<LLView>(id);
if (child)
{
return (bool)child->getVisible();
@@ -651,7 +637,7 @@ bool LLPanel::childIsVisible(const std::string& id) const
void LLPanel::childSetEnabled(const std::string& id, bool enabled)
{
- LLView* child = getChild<LLView>(id);
+ LLView* child = findChild<LLView>(id);
if (child)
{
child->setEnabled(enabled);
@@ -660,7 +646,7 @@ void LLPanel::childSetEnabled(const std::string& id, bool enabled)
void LLPanel::childSetTentative(const std::string& id, bool tentative)
{
- LLView* child = getChild<LLView>(id);
+ LLView* child = findChild<LLView>(id);
if (child)
{
child->setTentative(tentative);
@@ -669,7 +655,7 @@ void LLPanel::childSetTentative(const std::string& id, bool tentative)
bool LLPanel::childIsEnabled(const std::string& id) const
{
- LLView* child = getChild<LLView>(id);
+ LLView* child = findChild<LLView>(id);
if (child)
{
return (bool)child->getEnabled();
@@ -680,7 +666,7 @@ bool LLPanel::childIsEnabled(const std::string& id) const
void LLPanel::childSetToolTip(const std::string& id, const std::string& msg)
{
- LLView* child = getChild<LLView>(id);
+ LLView* child = findChild<LLView>(id);
if (child)
{
child->setToolTip(msg);
@@ -689,7 +675,7 @@ void LLPanel::childSetToolTip(const std::string& id, const std::string& msg)
void LLPanel::childSetRect(const std::string& id, const LLRect& rect)
{
- LLView* child = getChild<LLView>(id);
+ LLView* child = findChild<LLView>(id);
if (child)
{
child->setRect(rect);
@@ -698,7 +684,7 @@ void LLPanel::childSetRect(const std::string& id, const LLRect& rect)
bool LLPanel::childGetRect(const std::string& id, LLRect& rect) const
{
- LLView* child = getChild<LLView>(id);
+ LLView* child = findChild<LLView>(id);
if (child)
{
rect = child->getRect();
@@ -709,7 +695,7 @@ bool LLPanel::childGetRect(const std::string& id, LLRect& rect) const
void LLPanel::childSetFocus(const std::string& id, BOOL focus)
{
- LLUICtrl* child = getChild<LLUICtrl>(id, true);
+ LLUICtrl* child = findChild<LLUICtrl>(id);
if (child)
{
child->setFocus(focus);
@@ -718,72 +704,42 @@ void LLPanel::childSetFocus(const std::string& id, BOOL focus)
BOOL LLPanel::childHasFocus(const std::string& id)
{
- LLUICtrl* child = getChild<LLUICtrl>(id, true);
+ LLUICtrl* child = findChild<LLUICtrl>(id);
if (child)
{
return child->hasFocus();
}
else
{
- childNotFound(id);
return FALSE;
}
}
-
-void LLPanel::childSetFocusChangedCallback(const std::string& id, void (*cb)(LLFocusableElement*, void*), void* user_data)
-{
- LLUICtrl* child = getChild<LLUICtrl>(id, true);
- if (child)
- {
- child->setFocusChangedCallback(cb, user_data);
- }
-}
-
-void LLPanel::childSetCommitCallback(const std::string& id, void (*cb)(LLUICtrl*, void*), void *userdata )
+// *TODO: Deprecate; for backwards compatability only:
+// Prefer getChild<LLUICtrl>("foo")->setCommitCallback(boost:bind(...)),
+// which takes a generic slot. Or use mCommitCallbackRegistrar.add() with
+// a named callback and reference it in XML.
+void LLPanel::childSetCommitCallback(const std::string& id, boost::function<void (LLUICtrl*,void*)> cb, void* data)
{
- LLUICtrl* child = getChild<LLUICtrl>(id, true);
+ LLUICtrl* child = findChild<LLUICtrl>(id);
if (child)
{
- child->setCommitCallback(cb);
- child->setCallbackUserData(userdata);
+ child->setCommitCallback(boost::bind(cb, child, data));
}
}
-void LLPanel::childSetDoubleClickCallback(const std::string& id, void (*cb)(void*), void *userdata )
+void LLPanel::childSetValidate(const std::string& id, boost::function<bool (const LLSD& data)> cb)
{
- LLUICtrl* child = getChild<LLUICtrl>(id, true);
- if (child)
- {
- child->setDoubleClickCallback(cb);
- if (userdata)
- {
- child->setCallbackUserData(userdata);
- }
- }
-}
-
-void LLPanel::childSetValidate(const std::string& id, BOOL (*cb)(LLUICtrl*, void*))
-{
- LLUICtrl* child = getChild<LLUICtrl>(id, true);
+ LLUICtrl* child = findChild<LLUICtrl>(id);
if (child)
{
child->setValidateBeforeCommit(cb);
}
}
-void LLPanel::childSetUserData(const std::string& id, void* userdata)
-{
- LLUICtrl* child = getChild<LLUICtrl>(id, true);
- if (child)
- {
- child->setCallbackUserData(userdata);
- }
-}
-
void LLPanel::childSetColor(const std::string& id, const LLColor4& color)
{
- LLUICtrl* child = getChild<LLUICtrl>(id, true);
+ LLUICtrl* child = findChild<LLUICtrl>(id);
if (child)
{
child->setColor(color);
@@ -792,7 +748,7 @@ void LLPanel::childSetColor(const std::string& id, const LLColor4& color)
LLCtrlSelectionInterface* LLPanel::childGetSelectionInterface(const std::string& id) const
{
- LLUICtrl* child = getChild<LLUICtrl>(id, true);
+ LLUICtrl* child = findChild<LLUICtrl>(id);
if (child)
{
return child->getSelectionInterface();
@@ -802,7 +758,7 @@ LLCtrlSelectionInterface* LLPanel::childGetSelectionInterface(const std::string&
LLCtrlListInterface* LLPanel::childGetListInterface(const std::string& id) const
{
- LLUICtrl* child = getChild<LLUICtrl>(id, true);
+ LLUICtrl* child = findChild<LLUICtrl>(id);
if (child)
{
return child->getListInterface();
@@ -812,7 +768,7 @@ LLCtrlListInterface* LLPanel::childGetListInterface(const std::string& id) const
LLCtrlScrollInterface* LLPanel::childGetScrollInterface(const std::string& id) const
{
- LLUICtrl* child = getChild<LLUICtrl>(id, true);
+ LLUICtrl* child = findChild<LLUICtrl>(id);
if (child)
{
return child->getScrollInterface();
@@ -822,7 +778,7 @@ LLCtrlScrollInterface* LLPanel::childGetScrollInterface(const std::string& id) c
void LLPanel::childSetValue(const std::string& id, LLSD value)
{
- LLView* child = getChild<LLView>(id, true);
+ LLUICtrl* child = findChild<LLUICtrl>(id);
if (child)
{
child->setValue(value);
@@ -831,7 +787,7 @@ void LLPanel::childSetValue(const std::string& id, LLSD value)
LLSD LLPanel::childGetValue(const std::string& id) const
{
- LLView* child = getChild<LLView>(id, true);
+ LLUICtrl* child = findChild<LLUICtrl>(id);
if (child)
{
return child->getValue();
@@ -842,7 +798,7 @@ LLSD LLPanel::childGetValue(const std::string& id) const
BOOL LLPanel::childSetTextArg(const std::string& id, const std::string& key, const LLStringExplicit& text)
{
- LLUICtrl* child = getChild<LLUICtrl>(id, true);
+ LLUICtrl* child = findChild<LLUICtrl>(id);
if (child)
{
return child->setTextArg(key, text);
@@ -852,7 +808,7 @@ BOOL LLPanel::childSetTextArg(const std::string& id, const std::string& key, con
BOOL LLPanel::childSetLabelArg(const std::string& id, const std::string& key, const LLStringExplicit& text)
{
- LLView* child = getChild<LLView>(id);
+ LLView* child = findChild<LLView>(id);
if (child)
{
return child->setLabelArg(key, text);
@@ -862,7 +818,7 @@ BOOL LLPanel::childSetLabelArg(const std::string& id, const std::string& key, co
BOOL LLPanel::childSetToolTipArg(const std::string& id, const std::string& key, const LLStringExplicit& text)
{
- LLView* child = getChildView(id, true, FALSE);
+ LLView* child = findChild<LLView>(id);
if (child)
{
return child->setToolTipArg(key, text);
@@ -870,27 +826,9 @@ BOOL LLPanel::childSetToolTipArg(const std::string& id, const std::string& key,
return FALSE;
}
-void LLPanel::childSetMinValue(const std::string& id, LLSD min_value)
-{
- LLUICtrl* child = getChild<LLUICtrl>(id, true);
- if (child)
- {
- child->setMinValue(min_value);
- }
-}
-
-void LLPanel::childSetMaxValue(const std::string& id, LLSD max_value)
-{
- LLUICtrl* child = getChild<LLUICtrl>(id, true);
- if (child)
- {
- child->setMaxValue(max_value);
- }
-}
-
void LLPanel::childShowTab(const std::string& id, const std::string& tabname, bool visible)
{
- LLTabContainer* child = getChild<LLTabContainer>(id);
+ LLTabContainer* child = findChild<LLTabContainer>(id);
if (child)
{
child->selectTabByName(tabname);
@@ -899,7 +837,7 @@ void LLPanel::childShowTab(const std::string& id, const std::string& tabname, bo
LLPanel *LLPanel::childGetVisibleTab(const std::string& id) const
{
- LLTabContainer* child = getChild<LLTabContainer>(id);
+ LLTabContainer* child = findChild<LLTabContainer>(id);
if (child)
{
return child->getCurrentPanel();
@@ -907,742 +845,140 @@ LLPanel *LLPanel::childGetVisibleTab(const std::string& id) const
return NULL;
}
-void LLPanel::childSetTabChangeCallback(const std::string& id, const std::string& tabname, void (*on_tab_clicked)(void*, bool), void *userdata, void (*on_precommit)(void*,bool))
+static LLPanel *childGetVisibleTabWithHelp(LLView *parent)
{
- LLTabContainer* child = getChild<LLTabContainer>(id);
- if (child)
- {
- LLPanel *panel = child->getPanelByName(tabname);
- if (panel)
- {
- child->setTabChangeCallback(panel, on_tab_clicked);
- child->setTabUserData(panel, userdata);
- if (on_precommit)
- {
- child->setTabPrecommitChangeCallback(panel, on_precommit);
- }
- }
- }
-}
+ LLView *child;
-void LLPanel::childSetKeystrokeCallback(const std::string& id, void (*keystroke_callback)(LLLineEditor* caller, void* user_data), void *user_data)
-{
- LLLineEditor* child = getChild<LLLineEditor>(id);
- if (child)
+ // look through immediate children first for an active tab with help
+ for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child))
{
- child->setKeystrokeCallback(keystroke_callback);
- if (user_data)
- {
- child->setCallbackUserData(user_data);
- }
- }
-}
+ LLPanel *curTabPanel = NULL;
-void LLPanel::childSetPrevalidate(const std::string& id, BOOL (*func)(const LLWString &) )
-{
- LLLineEditor* child = getChild<LLLineEditor>(id);
- if (child)
- {
- child->setPrevalidate(func);
- }
-}
-
-void LLPanel::childSetWrappedText(const std::string& id, const std::string& text, bool visible)
-{
- LLTextBox* child = getChild<LLTextBox>(id);
- if (child)
- {
- child->setVisible(visible);
- child->setWrappedText(text);
- }
-}
-
-void LLPanel::childSetAction(const std::string& id, void(*function)(void*), void* value)
-{
- LLButton* button = getChild<LLButton>(id);
- if (button)
- {
- button->setClickedCallback(function, value);
- }
-}
-
-void LLPanel::childSetActionTextbox(const std::string& id, void(*function)(void*), void* value)
-{
- LLTextBox* textbox = getChild<LLTextBox>(id);
- if (textbox)
- {
- textbox->setClickedCallback(function, value);
- }
-}
-
-void LLPanel::childSetControlName(const std::string& id, const std::string& control_name)
-{
- LLView* view = getChild<LLView>(id);
- if (view)
- {
- view->setControlName(control_name, NULL);
- }
-}
-
-//virtual
-LLView* LLPanel::getChildView(const std::string& name, BOOL recurse, BOOL create_if_missing) const
-{
- // just get child, don't try to create a dummy one
- LLView* view = LLUICtrl::getChildView(name, recurse, FALSE);
- if (!view && !recurse)
- {
- childNotFound(name);
- }
- if (!view && create_if_missing)
- {
- view = createDummyWidget<LLView>(name);
- }
- return view;
-}
-
-void LLPanel::childNotFound(const std::string& id) const
-{
- if (mExpectedMembers.find(id) == mExpectedMembers.end())
- {
- mNewExpectedMembers.insert(id);
- }
-}
-
-void LLPanel::childDisplayNotFound()
-{
- if (mNewExpectedMembers.empty())
- {
- return;
- }
- std::string msg;
- expected_members_list_t::iterator itor;
- for (itor=mNewExpectedMembers.begin(); itor!=mNewExpectedMembers.end(); ++itor)
- {
- msg.append(*itor);
- msg.append("\n");
- mExpectedMembers.insert(*itor);
- }
- mNewExpectedMembers.clear();
- LLSD args;
- args["CONTROLS"] = msg;
- LLNotifications::instance().add("FloaterNotFound", args);
-}
-
-void LLPanel::storeRectControl()
-{
- if( !mRectControl.empty() )
- {
- LLUI::sConfigGroup->setRect( mRectControl, getRect() );
- }
-}
-
-
-//
-// LLLayoutStack
-//
-struct LLLayoutStack::LLEmbeddedPanel
-{
- LLEmbeddedPanel(LLPanel* panelp, eLayoutOrientation orientation, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize) :
- mPanel(panelp),
- mMinWidth(min_width),
- mMinHeight(min_height),
- mAutoResize(auto_resize),
- mUserResize(user_resize),
- mOrientation(orientation),
- mCollapsed(FALSE),
- mCollapseAmt(0.f),
- mVisibleAmt(1.f) // default to fully visible
- {
- LLResizeBar::Side side = (orientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM;
- LLRect resize_bar_rect = panelp->getRect();
-
- S32 min_dim;
- if (orientation == HORIZONTAL)
+ // do we have a tab container?
+ LLTabContainer *tab = dynamic_cast<LLTabContainer *>(child);
+ if (tab && tab->getVisible())
{
- min_dim = mMinHeight;
+ curTabPanel = tab->getCurrentPanel();
}
- else
+
+ // do we have an accordion tab?
+ LLAccordionCtrlTab* accordion = dynamic_cast<LLAccordionCtrlTab *>(child);
+ if (accordion && accordion->getDisplayChildren())
{
- min_dim = mMinWidth;
+ curTabPanel = dynamic_cast<LLPanel *>(accordion->getAccordionView());
}
- mResizeBar = new LLResizeBar(std::string("resizer"), mPanel, LLRect(), min_dim, S32_MAX, side);
- mResizeBar->setEnableSnapping(FALSE);
- // panels initialized as hidden should not start out partially visible
- if (!mPanel->getVisible())
+
+ // if we found a valid tab, does it have a help topic?
+ if (curTabPanel && !curTabPanel->getHelpTopic().empty())
{
- mVisibleAmt = 0.f;
+ return curTabPanel;
}
}
- ~LLEmbeddedPanel()
- {
- // probably not necessary, but...
- delete mResizeBar;
- mResizeBar = NULL;
- }
-
- F32 getCollapseFactor()
+ // then try a bit harder and recurse through all children
+ for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child))
{
- if (mOrientation == HORIZONTAL)
- {
- F32 collapse_amt =
- clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)mMinWidth / (F32)llmax(1, mPanel->getRect().getWidth()));
- return mVisibleAmt * collapse_amt;
- }
- else
+ if (child->getVisible())
{
- F32 collapse_amt =
- clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, llmin(1.f, (F32)mMinHeight / (F32)llmax(1, mPanel->getRect().getHeight())));
- return mVisibleAmt * collapse_amt;
+ LLPanel* tab = ::childGetVisibleTabWithHelp(child);
+ if (tab)
+ {
+ return tab;
+ }
}
}
- LLPanel* mPanel;
- S32 mMinWidth;
- S32 mMinHeight;
- BOOL mAutoResize;
- BOOL mUserResize;
- BOOL mCollapsed;
- LLResizeBar* mResizeBar;
- eLayoutOrientation mOrientation;
- F32 mVisibleAmt;
- F32 mCollapseAmt;
-};
-
-static LLRegisterWidget<LLLayoutStack> r2("layout_stack");
-
-LLLayoutStack::LLLayoutStack(eLayoutOrientation orientation) :
- mOrientation(orientation),
- mMinWidth(0),
- mMinHeight(0),
- mPanelSpacing(RESIZE_BAR_HEIGHT)
-{
+ // couldn't find any active tabs with a help topic string
+ return NULL;
}
-LLLayoutStack::~LLLayoutStack()
+LLPanel *LLPanel::childGetVisibleTabWithHelp()
{
- std::for_each(mPanels.begin(), mPanels.end(), DeletePointer());
+ // find a visible tab with a help topic (to determine help context)
+ return ::childGetVisibleTabWithHelp(this);
}
-void LLLayoutStack::draw()
+static LLPanel *childGetVisiblePanelWithHelp(LLView *parent)
{
- updateLayout();
+ LLView *child;
- e_panel_list_t::iterator panel_it;
- for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ // look through immediate children first for an active panel with help
+ for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child))
{
- // clip to layout rectangle, not bounding rectangle
- LLRect clip_rect = (*panel_it)->mPanel->getRect();
- // scale clipping rectangle by visible amount
- if (mOrientation == HORIZONTAL)
- {
- clip_rect.mRight = clip_rect.mLeft + llround((F32)clip_rect.getWidth() * (*panel_it)->getCollapseFactor());
- }
- else
+ // do we have a panel with a help topic?
+ LLPanel *panel = dynamic_cast<LLPanel *>(child);
+ if (panel && panel->getVisible() && !panel->getHelpTopic().empty())
{
- clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->getCollapseFactor());
+ return panel;
}
-
- LLPanel* panelp = (*panel_it)->mPanel;
-
- LLLocalClipRect clip(clip_rect);
- // only force drawing invisible children if visible amount is non-zero
- drawChild(panelp, 0, 0, !clip_rect.isNull());
- }
-}
-
-void LLLayoutStack::removeCtrl(LLUICtrl* ctrl)
-{
- LLEmbeddedPanel* embedded_panelp = findEmbeddedPanel((LLPanel*)ctrl);
-
- if (embedded_panelp)
- {
- mPanels.erase(std::find(mPanels.begin(), mPanels.end(), embedded_panelp));
- delete embedded_panelp;
- }
-
- // need to update resizebars
-
- calcMinExtents();
-
- LLView::removeCtrl(ctrl);
-}
-
-LLXMLNodePtr LLLayoutStack::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLView::getXML();
- return node;
-}
-
-//static
-LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string orientation_string("vertical");
- node->getAttributeString("orientation", orientation_string);
-
- eLayoutOrientation orientation = VERTICAL;
-
- if (orientation_string == "horizontal")
- {
- orientation = HORIZONTAL;
- }
- else if (orientation_string == "vertical")
- {
- orientation = VERTICAL;
}
- else
- {
- llwarns << "Unknown orientation " << orientation_string << ", using vertical" << llendl;
- }
-
- LLLayoutStack* layout_stackp = new LLLayoutStack(orientation);
-
- node->getAttributeS32("border_size", layout_stackp->mPanelSpacing);
- // don't allow negative spacing values
- layout_stackp->mPanelSpacing = llmax(layout_stackp->mPanelSpacing, 0);
-
- std::string name("stack");
- node->getAttributeString("name", name);
-
- layout_stackp->setName(name);
- layout_stackp->initFromXML(node, parent);
- LLXMLNodePtr child;
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
+ // then try a bit harder and recurse through all children
+ for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child))
{
- S32 min_width = 0;
- S32 min_height = 0;
- BOOL auto_resize = TRUE;
-
- child->getAttributeS32("min_width", min_width);
- child->getAttributeS32("min_height", min_height);
- child->getAttributeBOOL("auto_resize", auto_resize);
-
- if (child->hasName("layout_panel"))
+ if (child->getVisible())
{
- BOOL user_resize = TRUE;
- child->getAttributeBOOL("user_resize", user_resize);
- LLPanel* panelp = (LLPanel*)LLPanel::fromXML(child, layout_stackp, factory);
- if (panelp)
+ LLPanel* panel = ::childGetVisiblePanelWithHelp(child);
+ if (panel)
{
- panelp->setFollowsNone();
- layout_stackp->addPanel(panelp, min_width, min_height, auto_resize, user_resize);
- }
- }
- else
- {
- BOOL user_resize = FALSE;
- child->getAttributeBOOL("user_resize", user_resize);
-
- LLPanel* panelp = new LLPanel(std::string("auto_panel"));
- LLView* new_child = factory->createWidget(panelp, child);
- if (new_child)
- {
- // put child in new embedded panel
- layout_stackp->addPanel(panelp, min_width, min_height, auto_resize, user_resize);
- // resize panel to contain widget and move widget to be contained in panel
- panelp->setRect(new_child->getRect());
- new_child->setOrigin(0, 0);
- }
- else
- {
- panelp->die();
+ return panel;
}
}
}
- layout_stackp->updateLayout();
- return layout_stackp;
+ // couldn't find any active panels with a help topic string
+ return NULL;
}
-S32 LLLayoutStack::getDefaultHeight(S32 cur_height)
+LLPanel *LLPanel::childGetVisiblePanelWithHelp()
{
- // if we are spanning our children (crude upward propagation of size)
- // then don't enforce our size on our children
- if (mOrientation == HORIZONTAL)
- {
- cur_height = llmax(mMinHeight, getRect().getHeight());
- }
-
- return cur_height;
+ // find a visible tab with a help topic (to determine help context)
+ return ::childGetVisiblePanelWithHelp(this);
}
-S32 LLLayoutStack::getDefaultWidth(S32 cur_width)
+void LLPanel::childSetPrevalidate(const std::string& id, BOOL (*func)(const LLWString &) )
{
- // if we are spanning our children (crude upward propagation of size)
- // then don't enforce our size on our children
- if (mOrientation == VERTICAL)
+ LLLineEditor* child = findChild<LLLineEditor>(id);
+ if (child)
{
- cur_width = llmax(mMinWidth, getRect().getWidth());
+ child->setPrevalidate(func);
}
-
- return cur_width;
}
-void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, EAnimate animate, S32 index)
-{
- // panel starts off invisible (collapsed)
- if (animate == ANIMATE)
- {
- panel->setVisible(FALSE);
- }
- LLEmbeddedPanel* embedded_panel = new LLEmbeddedPanel(panel, mOrientation, min_width, min_height, auto_resize, user_resize);
-
- mPanels.insert(mPanels.begin() + llclamp(index, 0, (S32)mPanels.size()), embedded_panel);
-
- addChild(panel);
- addChild(embedded_panel->mResizeBar);
-
- // bring all resize bars to the front so that they are clickable even over the panels
- // with a bit of overlap
- for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
- {
- LLResizeBar* resize_barp = (*panel_it)->mResizeBar;
- sendChildToFront(resize_barp);
- }
- // start expanding panel animation
- if (animate == ANIMATE)
+void LLPanel::childSetAction(const std::string& id, boost::function<void(void*)> function, void* value)
+{
+ LLButton* button = findChild<LLButton>(id);
+ if (button)
{
- panel->setVisible(TRUE);
+ button->setClickedCallback(boost::bind(function, value));
}
}
-void LLLayoutStack::removePanel(LLPanel* panel)
-{
- removeChild(panel);
-}
-
-void LLLayoutStack::collapsePanel(LLPanel* panel, BOOL collapsed)
-{
- LLEmbeddedPanel* panel_container = findEmbeddedPanel(panel);
- if (!panel_container) return;
-
- panel_container->mCollapsed = collapsed;
-}
-
-void LLLayoutStack::updateLayout(BOOL force_resize)
+void LLPanel::childSetActionTextbox(const std::string& id, boost::function<void(void*)> function, void* value)
{
- calcMinExtents();
-
- // calculate current extents
- S32 total_width = 0;
- S32 total_height = 0;
-
- const F32 ANIM_OPEN_TIME = 0.02f;
- const F32 ANIM_CLOSE_TIME = 0.03f;
-
- e_panel_list_t::iterator panel_it;
- for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
- {
- LLPanel* panelp = (*panel_it)->mPanel;
- if (panelp->getVisible())
- {
- (*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 1.f, LLCriticalDamp::getInterpolant(ANIM_OPEN_TIME));
- if ((*panel_it)->mVisibleAmt > 0.99f)
- {
- (*panel_it)->mVisibleAmt = 1.f;
- }
- }
- else // not visible
- {
- (*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 0.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
- if ((*panel_it)->mVisibleAmt < 0.001f)
- {
- (*panel_it)->mVisibleAmt = 0.f;
- }
- }
-
- if ((*panel_it)->mCollapsed)
- {
- (*panel_it)->mCollapseAmt = lerp((*panel_it)->mCollapseAmt, 1.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
- }
- else
- {
- (*panel_it)->mCollapseAmt = lerp((*panel_it)->mCollapseAmt, 0.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
- }
-
- if (mOrientation == HORIZONTAL)
- {
- // enforce minimize size constraint by default
- if (panelp->getRect().getWidth() < (*panel_it)->mMinWidth)
- {
- panelp->reshape((*panel_it)->mMinWidth, panelp->getRect().getHeight());
- }
- total_width += llround(panelp->getRect().getWidth() * (*panel_it)->getCollapseFactor());
- // want n-1 panel gaps for n panels
- if (panel_it != mPanels.begin())
- {
- total_width += mPanelSpacing;
- }
- }
- else //VERTICAL
- {
- // enforce minimize size constraint by default
- if (panelp->getRect().getHeight() < (*panel_it)->mMinHeight)
- {
- panelp->reshape(panelp->getRect().getWidth(), (*panel_it)->mMinHeight);
- }
- total_height += llround(panelp->getRect().getHeight() * (*panel_it)->getCollapseFactor());
- if (panel_it != mPanels.begin())
- {
- total_height += mPanelSpacing;
- }
- }
- }
-
- S32 num_resizable_panels = 0;
- S32 shrink_headroom_available = 0;
- S32 shrink_headroom_total = 0;
- for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
- {
- // panels that are not fully visible do not count towards shrink headroom
- if ((*panel_it)->getCollapseFactor() < 1.f)
- {
- continue;
- }
-
- // if currently resizing a panel or the panel is flagged as not automatically resizing
- // only track total available headroom, but don't use it for automatic resize logic
- if ((*panel_it)->mResizeBar->hasMouseCapture()
- || (!(*panel_it)->mAutoResize
- && !force_resize))
- {
- if (mOrientation == HORIZONTAL)
- {
- shrink_headroom_total += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
- }
- else //VERTICAL
- {
- shrink_headroom_total += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
- }
- }
- else
- {
- num_resizable_panels++;
- if (mOrientation == HORIZONTAL)
- {
- shrink_headroom_available += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
- shrink_headroom_total += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
- }
- else //VERTICAL
- {
- shrink_headroom_available += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
- shrink_headroom_total += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
- }
- }
- }
-
- // calculate how many pixels need to be distributed among layout panels
- // positive means panels need to grow, negative means shrink
- S32 pixels_to_distribute;
- if (mOrientation == HORIZONTAL)
- {
- pixels_to_distribute = getRect().getWidth() - total_width;
- }
- else //VERTICAL
- {
- pixels_to_distribute = getRect().getHeight() - total_height;
- }
-
- // now we distribute the pixels...
- S32 cur_x = 0;
- S32 cur_y = getRect().getHeight();
-
- for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
- {
- LLPanel* panelp = (*panel_it)->mPanel;
-
- S32 cur_width = panelp->getRect().getWidth();
- S32 cur_height = panelp->getRect().getHeight();
- S32 new_width = llmax((*panel_it)->mMinWidth, cur_width);
- S32 new_height = llmax((*panel_it)->mMinHeight, cur_height);
-
- S32 delta_size = 0;
-
- // if panel can automatically resize (not animating, and resize flag set)...
- if ((*panel_it)->getCollapseFactor() == 1.f
- && (force_resize || (*panel_it)->mAutoResize)
- && !(*panel_it)->mResizeBar->hasMouseCapture())
- {
- if (mOrientation == HORIZONTAL)
- {
- // if we're shrinking
- if (pixels_to_distribute < 0)
- {
- // shrink proportionally to amount over minimum
- // so we can do this in one pass
- delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_width - (*panel_it)->mMinWidth) / (F32)shrink_headroom_available)) : 0;
- shrink_headroom_available -= (cur_width - (*panel_it)->mMinWidth);
- }
- else
- {
- // grow all elements equally
- delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
- num_resizable_panels--;
- }
- pixels_to_distribute -= delta_size;
- new_width = llmax((*panel_it)->mMinWidth, cur_width + delta_size);
- }
- else
- {
- new_width = getDefaultWidth(new_width);
- }
-
- if (mOrientation == VERTICAL)
- {
- if (pixels_to_distribute < 0)
- {
- // shrink proportionally to amount over minimum
- // so we can do this in one pass
- delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_height - (*panel_it)->mMinHeight) / (F32)shrink_headroom_available)) : 0;
- shrink_headroom_available -= (cur_height - (*panel_it)->mMinHeight);
- }
- else
- {
- delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
- num_resizable_panels--;
- }
- pixels_to_distribute -= delta_size;
- new_height = llmax((*panel_it)->mMinHeight, cur_height + delta_size);
- }
- else
- {
- new_height = getDefaultHeight(new_height);
- }
- }
- else
- {
- if (mOrientation == HORIZONTAL)
- {
- new_height = getDefaultHeight(new_height);
- }
- else // VERTICAL
- {
- new_width = getDefaultWidth(new_width);
- }
- }
-
- // adjust running headroom count based on new sizes
- shrink_headroom_total += delta_size;
-
- panelp->reshape(new_width, new_height);
- panelp->setOrigin(cur_x, cur_y - new_height);
-
- LLRect panel_rect = panelp->getRect();
- LLRect resize_bar_rect = panel_rect;
- if (mOrientation == HORIZONTAL)
- {
- resize_bar_rect.mLeft = panel_rect.mRight - RESIZE_BAR_OVERLAP;
- resize_bar_rect.mRight = panel_rect.mRight + mPanelSpacing + RESIZE_BAR_OVERLAP;
- }
- else
- {
- resize_bar_rect.mTop = panel_rect.mBottom + RESIZE_BAR_OVERLAP;
- resize_bar_rect.mBottom = panel_rect.mBottom - mPanelSpacing - RESIZE_BAR_OVERLAP;
- }
- (*panel_it)->mResizeBar->setRect(resize_bar_rect);
-
- if (mOrientation == HORIZONTAL)
- {
- cur_x += llround(new_width * (*panel_it)->getCollapseFactor()) + mPanelSpacing;
- }
- else //VERTICAL
- {
- cur_y -= llround(new_height * (*panel_it)->getCollapseFactor()) + mPanelSpacing;
- }
- }
-
- // update resize bars with new limits
- LLResizeBar* last_resize_bar = NULL;
- for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
- {
- LLPanel* panelp = (*panel_it)->mPanel;
-
- if (mOrientation == HORIZONTAL)
- {
- (*panel_it)->mResizeBar->setResizeLimits(
- (*panel_it)->mMinWidth,
- (*panel_it)->mMinWidth + shrink_headroom_total);
- }
- else //VERTICAL
- {
- (*panel_it)->mResizeBar->setResizeLimits(
- (*panel_it)->mMinHeight,
- (*panel_it)->mMinHeight + shrink_headroom_total);
- }
-
- // toggle resize bars based on panel visibility, resizability, etc
- BOOL resize_bar_enabled = panelp->getVisible() && (*panel_it)->mUserResize;
- (*panel_it)->mResizeBar->setVisible(resize_bar_enabled);
-
- if (resize_bar_enabled)
- {
- last_resize_bar = (*panel_it)->mResizeBar;
- }
- }
-
- // hide last resize bar as there is nothing past it
- // resize bars need to be in between two resizable panels
- if (last_resize_bar)
- {
- last_resize_bar->setVisible(FALSE);
- }
-
- // not enough room to fit existing contents
- if (force_resize == FALSE
- // layout did not complete by reaching target position
- && ((mOrientation == VERTICAL && cur_y != -mPanelSpacing)
- || (mOrientation == HORIZONTAL && cur_x != getRect().getWidth() + mPanelSpacing)))
+ LLTextBox* textbox = findChild<LLTextBox>(id);
+ if (textbox)
{
- // do another layout pass with all stacked elements contributing
- // even those that don't usually resize
- llassert_always(force_resize == FALSE);
- updateLayout(TRUE);
+ textbox->setClickedCallback(boost::bind(function, value));
}
-} // end LLLayoutStack::updateLayout
-
+}
-LLLayoutStack::LLEmbeddedPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const
+void LLPanel::childSetControlName(const std::string& id, const std::string& control_name)
{
- e_panel_list_t::const_iterator panel_it;
- for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ LLUICtrl* view = findChild<LLUICtrl>(id);
+ if (view)
{
- if ((*panel_it)->mPanel == panelp)
- {
- return *panel_it;
- }
+ view->setControlName(control_name, NULL);
}
- return NULL;
}
-void LLLayoutStack::calcMinExtents()
+boost::signals2::connection LLPanel::setVisibleCallback( const commit_signal_t::slot_type& cb )
{
- mMinWidth = 0;
- mMinHeight = 0;
-
- e_panel_list_t::iterator panel_it;
- for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ if (!mVisibleSignal)
{
- if (mOrientation == HORIZONTAL)
- {
- mMinHeight = llmax( mMinHeight,
- (*panel_it)->mMinHeight);
- mMinWidth += (*panel_it)->mMinWidth;
- if (panel_it != mPanels.begin())
- {
- mMinWidth += mPanelSpacing;
- }
- }
- else //VERTICAL
- {
- mMinWidth = llmax( mMinWidth,
- (*panel_it)->mMinWidth);
- mMinHeight += (*panel_it)->mMinHeight;
- if (panel_it != mPanels.begin())
- {
- mMinHeight += mPanelSpacing;
- }
- }
+ mVisibleSignal = new commit_signal_t();
}
+
+ return mVisibleSignal->connect(cb);
}
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index 756d02ef7d..6de83fe3a7 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -37,8 +37,6 @@
#include "llcallbackmap.h"
#include "lluictrl.h"
-#include "llbutton.h"
-#include "lllineeditor.h"
#include "llviewborder.h"
#include "lluistring.h"
#include "v4color.h"
@@ -49,6 +47,8 @@ const S32 LLPANEL_BORDER_WIDTH = 1;
const BOOL BORDER_YES = TRUE;
const BOOL BORDER_NO = FALSE;
+class LLButton;
+class LLUIImage;
/*
* General purpose concrete view base class.
@@ -56,66 +56,87 @@ const BOOL BORDER_NO = FALSE;
* With or without border,
* Can contain LLUICtrls.
*/
-class LLPanel : public LLUICtrl, public boost::signals::trackable
+class LLPanel : public LLUICtrl
{
public:
+ struct LocalizedString : public LLInitParam::Block<LocalizedString>
+ {
+ Mandatory<std::string> name;
+ Mandatory<std::string> value;
+
+ LocalizedString();
+ };
+
+ struct Params
+ : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<bool> has_border;
+ Optional<LLViewBorder::Params> border;
+
+ Optional<bool> background_visible,
+ background_opaque;
+
+ Optional<LLUIColor> bg_opaque_color,
+ bg_alpha_color;
+ // opaque image is for "panel in foreground" look
+ Optional<LLUIImage*> bg_opaque_image,
+ bg_alpha_image;
+
+ Optional<S32> min_width,
+ min_height;
+
+ Optional<std::string> filename;
+ Optional<std::string> class_name;
+ Optional<std::string> help_topic;
- // minimal constructor for data-driven initialization
- LLPanel();
- LLPanel(const std::string& name);
+ Multiple<LocalizedString> strings;
+
+ Optional<CommitCallbackParam> visible_callback;
+
+ Params();
+ };
- // Position and size not saved
- LLPanel(const std::string& name, const LLRect& rect, BOOL bordered = TRUE);
+ // valid children for LLPanel are stored in this registry
+ typedef LLDefaultChildRegistry child_registry_t;
- // Position and size are saved to rect_control
- LLPanel(const std::string& name, const std::string& rect_control, BOOL bordered = TRUE);
+protected:
+ friend class LLUICtrlFactory;
+ // RN: for some reason you can't just use LLUICtrlFactory::getDefaultParams as a default argument in VC8
+ static const LLPanel::Params& getDefaultParams();
+
+ // Panels can get constructed directly
+ LLPanel(const LLPanel::Params& params = getDefaultParams());
+public:
+// LLPanel(const std::string& name, const LLRect& rect = LLRect(), BOOL bordered = TRUE);
/*virtual*/ ~LLPanel();
// LLView interface
/*virtual*/ BOOL isPanel() const;
/*virtual*/ void draw();
/*virtual*/ BOOL handleKeyHere( KEY key, MASK mask );
- /*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const;
- // Override to set not found list:
- virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const;
+ /*virtual*/ void handleVisibilityChange ( BOOL new_visibility );
// From LLFocusableElement
/*virtual*/ void setFocus( BOOL b );
// New virtuals
virtual void refresh(); // called in setFocus()
- virtual BOOL postBuild();
virtual void clearCtrls(); // overridden in LLPanelObject and LLPanelVolume
// Border controls
- void addBorder( LLViewBorder::EBevel border_bevel = LLViewBorder::BEVEL_OUT,
- LLViewBorder::EStyle border_style = LLViewBorder::STYLE_LINE,
- S32 border_thickness = LLPANEL_BORDER_WIDTH );
+ void addBorder( LLViewBorder::Params p);
+ void addBorder();
void removeBorder();
BOOL hasBorder() const { return mBorder != NULL; }
void setBorderVisible( BOOL b );
- template <class T> void requires(const std::string& name)
- {
- // check for widget with matching type and name
- if (LLView::getChild<T>(name) == NULL)
- {
- mRequirementsError += name + "\n";
- }
- }
-
- // requires LLView by default
- void requires(const std::string& name)
- {
- requires<LLView>(name);
- }
- BOOL checkRequirements();
-
- void setBackgroundColor( const LLColor4& color ) { mBgColorOpaque = color; }
- const LLColor4& getBackgroundColor() const { return mBgColorOpaque; }
- void setTransparentColor(const LLColor4& color) { mBgColorAlpha = color; }
- const LLColor4& getTransparentColor() const { return mBgColorAlpha; }
+ void setBackgroundColor( const LLColor4& color ) { mBgOpaqueColor = color; }
+ const LLColor4& getBackgroundColor() const { return mBgOpaqueColor; }
+ void setTransparentColor(const LLColor4& color) { mBgAlphaColor = color; }
+ const LLColor4& getTransparentColor() const { return mBgAlphaColor; }
+ LLPointer<LLUIImage> getBackgroundImage() const { return mBgOpaqueImage; }
+ LLPointer<LLUIImage> getTransparentImage() const { return mBgAlphaImage; }
void setBackgroundVisible( BOOL b ) { mBgVisible = b; }
BOOL isBackgroundVisible() const { return mBgVisible; }
void setBackgroundOpaque(BOOL b) { mBgOpaque = b; }
@@ -125,23 +146,22 @@ public:
void updateDefaultBtn();
void setLabel(const LLStringExplicit& label) { mLabel = label; }
std::string getLabel() const { return mLabel; }
+ void setHelpTopic(const std::string& help_topic) { mHelpTopic = help_topic; }
+ std::string getHelpTopic() const { return mHelpTopic; }
- void setRectControl(const std::string& rect_control) { mRectControl.assign(rect_control); }
- const std::string& getRectControl() const { return mRectControl; }
- void storeRectControl();
-
void setCtrlsEnabled(BOOL b);
LLHandle<LLPanel> getHandle() const { return mPanelHandle; }
- S32 getLastTabGroup() const { return mLastTabGroup; }
-
const LLCallbackMap::map_t& getFactoryMap() const { return mFactoryMap; }
-
- BOOL initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
- void initChildrenXML(LLXMLNodePtr node, LLUICtrlFactory* factory);
- void setPanelParameters(LLXMLNodePtr node, LLView *parentp);
-
+
+ CommitCallbackRegistry::ScopedRegistrar& getCommitCallbackRegistrar() { return mCommitCallbackRegistrar; }
+ EnableCallbackRegistry::ScopedRegistrar& getEnableCallbackRegistrar() { return mEnableCallbackRegistrar; }
+
+ void initFromParams(const Params& p);
+ BOOL initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL);
+
+ bool hasString(const std::string& name);
std::string getString(const std::string& name, const LLStringUtil::format_map_t& args) const;
std::string getString(const std::string& name) const;
@@ -166,12 +186,14 @@ public:
// LLUICtrl
void childSetFocus(const std::string& id, BOOL focus = TRUE);
BOOL childHasFocus(const std::string& id);
- void childSetFocusChangedCallback(const std::string& id, void (*cb)(LLFocusableElement*, void*), void* user_data = NULL);
- void childSetCommitCallback(const std::string& id, void (*cb)(LLUICtrl*, void*), void* userdata = NULL );
- void childSetDoubleClickCallback(const std::string& id, void (*cb)(void*), void* userdata = NULL );
- void childSetValidate(const std::string& id, BOOL (*cb)(LLUICtrl*, void*) );
- void childSetUserData(const std::string& id, void* userdata);
+ // *TODO: Deprecate; for backwards compatability only:
+ // Prefer getChild<LLUICtrl>("foo")->setCommitCallback(boost:bind(...)),
+ // which takes a generic slot. Or use mCommitCallbackRegistrar.add() with
+ // a named callback and reference it in XML.
+ void childSetCommitCallback(const std::string& id, boost::function<void (LLUICtrl*,void*)> cb, void* data);
+
+ void childSetValidate(const std::string& id, boost::function<bool (const LLSD& data)> cb );
void childSetColor(const std::string& id, const LLColor4& color);
@@ -189,124 +211,76 @@ public:
BOOL childSetLabelArg(const std::string& id, const std::string& key, const LLStringExplicit& text);
BOOL childSetToolTipArg(const std::string& id, const std::string& key, const LLStringExplicit& text);
- // LLSlider / LLMultiSlider / LLSpinCtrl
- void childSetMinValue(const std::string& id, LLSD min_value);
- void childSetMaxValue(const std::string& id, LLSD max_value);
-
// LLTabContainer
void childShowTab(const std::string& id, const std::string& tabname, bool visible = true);
LLPanel *childGetVisibleTab(const std::string& id) const;
- void childSetTabChangeCallback(const std::string& id, const std::string& tabname, void (*on_tab_clicked)(void*, bool), void *userdata, void (*on_precommit)(void*,bool) = NULL);
- // LLTextBox
- void childSetWrappedText(const std::string& id, const std::string& text, bool visible = true);
+ // Find a child with a nonempty Help topic
+ LLPanel *childGetVisibleTabWithHelp();
+ LLPanel *childGetVisiblePanelWithHelp();
// LLTextBox/LLTextEditor/LLLineEditor
void childSetText(const std::string& id, const LLStringExplicit& text) { childSetValue(id, LLSD(text)); }
+
+ // *NOTE: Does not return text from <string> tags, use getString()
std::string childGetText(const std::string& id) const { return childGetValue(id).asString(); }
// LLLineEditor
- void childSetKeystrokeCallback(const std::string& id, void (*keystroke_callback)(LLLineEditor* caller, void* user_data), void *user_data);
void childSetPrevalidate(const std::string& id, BOOL (*func)(const LLWString &) );
// LLButton
- void childSetAction(const std::string& id, void(*function)(void*), void* value);
- void childSetActionTextbox(const std::string& id, void(*function)(void*), void* value = NULL);
+ void childSetAction(const std::string& id, boost::function<void(void*)> function, void* value = NULL);
+
+ // LLTextBox
+ void childSetActionTextbox(const std::string& id, boost::function<void(void*)> function, void* value = NULL);
+
void childSetControlName(const std::string& id, const std::string& control_name);
- // Error reporting
- void childNotFound(const std::string& id) const;
- void childDisplayNotFound();
+ static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL);
+
+ //call onOpen to let panel know when it's about to be shown or activated
+ virtual void onOpen(const LLSD& key) {}
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
+ void setXMLFilename(std::string filename) { mXMLFilename = filename; };
+ std::string getXMLFilename() { return mXMLFilename; };
+ boost::signals2::connection setVisibleCallback( const commit_signal_t::slot_type& cb );
+
protected:
// Override to set not found list
LLButton* getDefaultButton() { return mDefaultBtn; }
LLCallbackMap::map_t mFactoryMap;
+ CommitCallbackRegistry::ScopedRegistrar mCommitCallbackRegistrar;
+ EnableCallbackRegistry::ScopedRegistrar mEnableCallbackRegistrar;
+
+ commit_signal_t* mVisibleSignal; // Called when visibility changes, passes new visibility as LLSD()
+ std::string mHelpTopic; // the name of this panel's help topic to display in the Help Viewer
+
private:
- // common construction logic
- void init();
-
- // From LLView
- virtual void addCtrl( LLUICtrl* ctrl, S32 tab_group );
- virtual void addCtrlAtEnd( LLUICtrl* ctrl, S32 tab_group);
-
- // Unified error reporting for the child* functions
- typedef std::set<std::string> expected_members_list_t;
- mutable expected_members_list_t mExpectedMembers;
- mutable expected_members_list_t mNewExpectedMembers;
-
- std::string mRectControl;
- LLColor4 mBgColorAlpha;
- LLColor4 mBgColorOpaque;
- LLColor4 mDefaultBtnHighlight;
- BOOL mBgVisible;
- BOOL mBgOpaque;
+ BOOL mBgVisible; // any background at all?
+ BOOL mBgOpaque; // use opaque color or image
+ LLUIColor mBgOpaqueColor;
+ LLUIColor mBgAlphaColor;
+ LLPointer<LLUIImage> mBgOpaqueImage; // "panel in front" look
+ LLPointer<LLUIImage> mBgAlphaImage; // "panel in back" look
LLViewBorder* mBorder;
LLButton* mDefaultBtn;
- std::string mLabel;
- S32 mLastTabGroup;
+ LLUIString mLabel;
LLRootHandle<LLPanel> mPanelHandle;
typedef std::map<std::string, std::string> ui_string_map_t;
ui_string_map_t mUIStrings;
- std::string mRequirementsError;
+ // for setting the xml filename when building panel in context dependent cases
+ std::string mXMLFilename;
}; // end class LLPanel
-
-class LLLayoutStack : public LLView
-{
-public:
- typedef enum e_layout_orientation
- {
- HORIZONTAL,
- VERTICAL
- } eLayoutOrientation;
-
- LLLayoutStack(eLayoutOrientation orientation);
- virtual ~LLLayoutStack();
-
- /*virtual*/ void draw();
- /*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const;
- /*virtual*/ void removeCtrl(LLUICtrl* ctrl);
-
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
-
- S32 getMinWidth() const { return mMinWidth; }
- S32 getMinHeight() const { return mMinHeight; }
-
- typedef enum e_animate
- {
- NO_ANIMATE,
- ANIMATE
- } EAnimate;
-
- void addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, EAnimate animate = NO_ANIMATE, S32 index = S32_MAX);
- void removePanel(LLPanel* panel);
- void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE);
- S32 getNumPanels() { return mPanels.size(); }
-
-private:
- struct LLEmbeddedPanel;
-
- void updateLayout(BOOL force_resize = FALSE);
- void calcMinExtents();
- S32 getDefaultHeight(S32 cur_height);
- S32 getDefaultWidth(S32 cur_width);
-
- const eLayoutOrientation mOrientation;
-
- typedef std::vector<LLEmbeddedPanel*> e_panel_list_t;
- e_panel_list_t mPanels;
- LLEmbeddedPanel* findEmbeddedPanel(LLPanel* panelp) const;
-
- S32 mMinWidth;
- S32 mMinHeight;
- S32 mPanelSpacing;
-}; // end class LLLayoutStack
+// Build time optimization, generate once in .cpp file
+#ifndef LLPANEL_CPP
+extern template class LLPanel* LLView::getChild<class LLPanel>(
+ const std::string& name, BOOL recurse) const;
+#endif
#endif
diff --git a/indra/llui/llprogressbar.cpp b/indra/llui/llprogressbar.cpp
index 8833494af8..62ca569e6c 100644
--- a/indra/llui/llprogressbar.cpp
+++ b/indra/llui/llprogressbar.cpp
@@ -39,31 +39,30 @@
#include "llgl.h"
#include "llui.h"
#include "llfontgl.h"
-#include "llimagegl.h"
#include "lltimer.h"
#include "llglheaders.h"
#include "llfocusmgr.h"
+#include "lluictrlfactory.h"
-static LLRegisterWidget<LLProgressBar> r("progress_bar");
+static LLDefaultChildRegistry::Register<LLProgressBar> r("progress_bar");
-LLProgressBar::LLProgressBar(const std::string& name, const LLRect &rect)
- : LLView(name, rect, FALSE),
- mImageBar( NULL ),
- mImageShadow( NULL )
-{
- mPercentDone = 0.f;
-
- // Defaults:
+LLProgressBar::Params::Params()
+: image_bar("image_bar"),
+ image_fill("image_fill"),
+ color_bar("color_bar"),
+ color_bg("color_bg")
+{}
- setImageBar("rounded_square.tga");
- setImageShadow("rounded_square_soft.tga");
- mColorBackground = LLColor4(0.3254f, 0.4000f, 0.5058f, 1.0f);
- mColorBar = LLColor4(0.5764f, 0.6627f, 0.8352f, 1.0f);
- mColorBar2 = LLColor4(0.5764f, 0.6627f, 0.8352f, 1.0f);
- mColorShadow = LLColor4(0.2000f, 0.2000f, 0.4000f, 1.0f);
-}
+LLProgressBar::LLProgressBar(const LLProgressBar::Params& p)
+: LLView(p),
+ mImageBar(p.image_bar),
+ mImageFill(p.image_fill),
+ mColorBackground(p.color_bg()),
+ mColorBar(p.color_bar()),
+ mPercentDone(0.f)
+{}
LLProgressBar::~LLProgressBar()
{
@@ -73,109 +72,21 @@ LLProgressBar::~LLProgressBar()
void LLProgressBar::draw()
{
static LLTimer timer;
-
- LLUIImagePtr shadow_imagep = LLUI::getUIImage("rounded_square_soft.tga");
- LLUIImagePtr bar_fg_imagep = LLUI::getUIImage("progressbar_fill.tga");
- LLUIImagePtr bar_bg_imagep = LLUI::getUIImage("progressbar_track.tga");
- LLUIImagePtr bar_imagep = LLUI::getUIImage("rounded_square.tga");
- LLColor4 background_color = LLUI::sColorsGroup->getColor("LoginProgressBarBgColor");
+ F32 alpha = getDrawContext().mAlpha;
- bar_bg_imagep->draw(getLocalRect(),
- background_color);
+ LLColor4 image_bar_color = mColorBackground.get();
+ image_bar_color.setAlpha(alpha);
+ mImageBar->draw(getLocalRect(), image_bar_color);
- F32 alpha = 0.5f + 0.5f*0.5f*(1.f + (F32)sin(3.f*timer.getElapsedTimeF32()));
- LLColor4 bar_color = LLUI::sColorsGroup->getColor("LoginProgressBarFgColor");
- bar_color.mV[3] = alpha;
+ alpha *= 0.5f + 0.5f*0.5f*(1.f + (F32)sin(3.f*timer.getElapsedTimeF32()));
+ LLColor4 bar_color = mColorBar.get();
+ bar_color.mV[VALPHA] *= alpha; // modulate alpha
LLRect progress_rect = getLocalRect();
progress_rect.mRight = llround(getRect().getWidth() * (mPercentDone / 100.f));
- bar_fg_imagep->draw(progress_rect);
+ mImageFill->draw(progress_rect, bar_color);
}
void LLProgressBar::setPercent(const F32 percent)
{
mPercentDone = llclamp(percent, 0.f, 100.f);
}
-
-void LLProgressBar::setImageBar( const std::string &bar_name )
-{
- mImageBar = LLUI::sImageProvider->getUIImage(bar_name)->getImage();
-}
-
-void LLProgressBar::setImageShadow(const std::string &shadow_name)
-{
- mImageShadow = LLUI::sImageProvider->getUIImage(shadow_name)->getImage();
-}
-
-void LLProgressBar::setColorBar(const LLColor4 &c)
-{
- mColorBar = c;
-}
-void LLProgressBar::setColorBar2(const LLColor4 &c)
-{
- mColorBar2 = c;
-}
-void LLProgressBar::setColorShadow(const LLColor4 &c)
-{
- mColorShadow = c;
-}
-void LLProgressBar::setColorBackground(const LLColor4 &c)
-{
- mColorBackground = c;
-}
-
-
-// static
-LLView* LLProgressBar::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("progress_bar");
- node->getAttributeString("name", name);
-
- LLProgressBar *progress = new LLProgressBar(name, LLRect());
-
-
- std::string image_bar;
- if (node->hasAttribute("image_bar")) node->getAttributeString("image_bar",image_bar);
- if (image_bar != LLStringUtil::null) progress->setImageBar(image_bar);
-
-
- std::string image_shadow;
- if (node->hasAttribute("image_shadow")) node->getAttributeString("image_shadow",image_shadow);
- if (image_shadow != LLStringUtil::null) progress->setImageShadow(image_shadow);
-
-
- LLColor4 color_bar;
- if (node->hasAttribute("color_bar"))
- {
- node->getAttributeColor4("color_bar",color_bar);
- progress->setColorBar(color_bar);
- }
-
-
- LLColor4 color_bar2;
- if (node->hasAttribute("color_bar2"))
- {
- node->getAttributeColor4("color_bar2",color_bar2);
- progress->setColorBar2(color_bar2);
- }
-
-
- LLColor4 color_shadow;
- if (node->hasAttribute("color_shadow"))
- {
- node->getAttributeColor4("color_shadow",color_shadow);
- progress->setColorShadow(color_shadow);
- }
-
-
- LLColor4 color_bg;
- if (node->hasAttribute("color_bg"))
- {
- node->getAttributeColor4("color_bg",color_bg);
- progress->setColorBackground(color_bg);
- }
-
-
- progress->initFromXML(node, parent);
-
- return progress;
-}
diff --git a/indra/llui/llprogressbar.h b/indra/llui/llprogressbar.h
index 00ad61d540..b6a5b0400d 100644
--- a/indra/llui/llprogressbar.h
+++ b/indra/llui/llprogressbar.h
@@ -40,37 +40,32 @@ class LLProgressBar
: public LLView
{
public:
- LLProgressBar(const std::string& name, const LLRect &rect);
- virtual ~LLProgressBar();
-
- void setPercent(const F32 percent);
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
+ {
+ Optional<LLUIImage*> image_bar,
+ image_fill;
- void setImageBar(const std::string &bar_name);
- void setImageShadow(const std::string &shadow_name);
+ Optional<LLUIColor> color_bar,
+ color_bg;
- void setColorBar(const LLColor4 &c);
- void setColorBar2(const LLColor4 &c);
- void setColorShadow(const LLColor4 &c);
- void setColorBackground(const LLColor4 &c);
+ Params();
+ };
+ LLProgressBar(const Params&);
+ virtual ~LLProgressBar();
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
+ void setPercent(const F32 percent);
/*virtual*/ void draw();
-protected:
+private:
F32 mPercentDone;
- LLPointer<LLImageGL> mImageBar;
- //LLUUID mImageBarID;
- //LLString mImageBarName;
- LLColor4 mColorBar;
- LLColor4 mColorBar2;
+ LLPointer<LLUIImage> mImageBar;
+ LLUIColor mColorBar;
- LLPointer<LLImageGL> mImageShadow;
- //LLUUID mImageShadowID;
- //LLString mImageShadowName;
- LLColor4 mColorShadow;
- LLColor4 mColorBackground;
+ LLUIColor mColorBackground;
+
+ LLPointer<LLUIImage> mImageFill;
};
#endif // LL_LLPROGRESSBAR_H
diff --git a/indra/llui/llradiogroup.cpp b/indra/llui/llradiogroup.cpp
index 33b93985d7..4087b484aa 100644
--- a/indra/llui/llradiogroup.cpp
+++ b/indra/llui/llradiogroup.cpp
@@ -42,63 +42,107 @@
#include "llcontrol.h"
#include "llui.h"
#include "llfocusmgr.h"
+#include "lluictrlfactory.h"
+#include "llsdutil.h"
-static LLRegisterWidget<LLRadioGroup> r("radio_group");
+static LLDefaultChildRegistry::Register<LLRadioGroup> r1("radio_group");
-LLRadioGroup::LLRadioGroup(const std::string& name, const LLRect& rect,
- const std::string& control_name,
- LLUICtrlCallback callback,
- void* userdata,
- BOOL border)
-: LLUICtrl(name, rect, TRUE, callback, userdata, FOLLOWS_LEFT | FOLLOWS_TOP),
- mSelectedIndex(0)
+/*
+ * An invisible view containing multiple mutually exclusive toggling
+ * buttons (usually radio buttons). Automatically handles the mutex
+ * condition by highlighting only one button at a time.
+ */
+class LLRadioCtrl : public LLCheckBoxCtrl
{
- setControlName(control_name, NULL);
- init(border);
-}
+public:
+ typedef LLRadioGroup::ItemParams Params;
+ /*virtual*/ ~LLRadioCtrl();
+ /*virtual*/ void setValue(const LLSD& value);
+
+ /*virtual*/ BOOL postBuild();
+
+ LLSD getPayload() { return mPayload; }
+
+ // Ensure label is in an attribute, not the contents
+ static void setupParamsForExport(Params& p, LLView* parent);
+
+protected:
+ LLRadioCtrl(const LLRadioGroup::ItemParams& p);
+ friend class LLUICtrlFactory;
+
+ LLSD mPayload; // stores data that this item represents in the radio group
+};
+static LLWidgetNameRegistry::StaticRegistrar register_radio_item(&typeid(LLRadioGroup::ItemParams), "radio_item");
-LLRadioGroup::LLRadioGroup(const std::string& name, const LLRect& rect,
- S32 initial_index,
- LLUICtrlCallback callback,
- void* userdata,
- BOOL border) :
- LLUICtrl(name, rect, TRUE, callback, userdata, FOLLOWS_LEFT | FOLLOWS_TOP),
- mSelectedIndex(initial_index)
+LLRadioGroup::Params::Params()
+: has_border("draw_border"),
+ items("item")
{
- init(border);
+ addSynonym(items, "radio_item");
+
+ name = "radio_group";
+ mouse_opaque = true;
+ follows.flags = FOLLOWS_LEFT | FOLLOWS_TOP;
+ // radio items are not tabbable until they are selected
+ tab_stop = false;
}
-void LLRadioGroup::init(BOOL border)
-{
- if (border)
+LLRadioGroup::LLRadioGroup(const LLRadioGroup::Params& p)
+: LLUICtrl(p),
+ mFont(p.font.isProvided() ? p.font() : LLFontGL::getFontSansSerifSmall()),
+ mSelectedIndex(-1),
+ mHasBorder(p.has_border)
+{
+ if (mHasBorder)
{
- addChild( new LLViewBorder( std::string("radio group border"),
- LLRect(0, getRect().getHeight(), getRect().getWidth(), 0),
- LLViewBorder::BEVEL_NONE,
- LLViewBorder::STYLE_LINE,
- 1 ) );
+ LLViewBorder::Params params;
+ params.name("radio group border");
+ params.rect(LLRect(0, getRect().getHeight(), getRect().getWidth(), 0));
+ params.bevel_style(LLViewBorder::BEVEL_NONE);
+ LLViewBorder * vb = LLUICtrlFactory::create<LLViewBorder> (params);
+ addChild (vb);
}
- mHasBorder = border;
}
+void LLRadioGroup::initFromParams(const Params& p)
+{
+ LLUICtrl::initFromParams(p);
+ for (LLInitParam::ParamIterator<ItemParams>::const_iterator it = p.items().begin();
+ it != p.items().end();
+ ++it)
+ {
+ LLRadioGroup::ItemParams item_params(*it);
+
+ item_params.font.setIfNotProvided(mFont); // apply radio group font by default
+ item_params.commit_callback.function = boost::bind(&LLRadioGroup::onClickButton, this, _1);
+ item_params.from_xui = p.from_xui;
+ if (p.from_xui)
+ {
+ applyXUILayout(item_params, this);
+ }
+ LLRadioCtrl* item = LLUICtrlFactory::create<LLRadioCtrl>(item_params, this);
+ mRadioButtons.push_back(item);
+ }
+}
LLRadioGroup::~LLRadioGroup()
{
}
-
// virtual
-void LLRadioGroup::setEnabled(BOOL enabled)
+BOOL LLRadioGroup::postBuild()
{
- for (child_list_const_iter_t child_iter = getChildList()->begin();
- child_iter != getChildList()->end(); ++child_iter)
+ if (!mRadioButtons.empty())
{
- LLView *child = *child_iter;
- child->setEnabled(enabled);
+ mRadioButtons[0]->setTabStop(true);
}
- LLView::setEnabled(enabled);
+ if (mControlVariable)
+ {
+ setSelectedIndex(mControlVariable->getValue().asInteger());
+ }
+ return TRUE;
}
void LLRadioGroup::setIndexEnabled(S32 index, BOOL enabled)
@@ -148,16 +192,36 @@ void LLRadioGroup::setIndexEnabled(S32 index, BOOL enabled)
BOOL LLRadioGroup::setSelectedIndex(S32 index, BOOL from_event)
{
- if (index < 0 || index >= (S32)mRadioButtons.size())
+ if (index < 0 || (S32)mRadioButtons.size() <= index )
{
return FALSE;
}
+ if (mSelectedIndex >= 0)
+ {
+ LLRadioCtrl* old_radio_item = mRadioButtons[mSelectedIndex];
+ old_radio_item->setTabStop(false);
+ old_radio_item->setValue( FALSE );
+ }
+ else
+ {
+ mRadioButtons[0]->setTabStop(false);
+ }
+
mSelectedIndex = index;
+ LLRadioCtrl* radio_item = mRadioButtons[mSelectedIndex];
+ radio_item->setTabStop(true);
+ radio_item->setValue( TRUE );
+
+ if (hasFocus())
+ {
+ mRadioButtons[mSelectedIndex]->focusFirstItem(FALSE, FALSE);
+ }
+
if (!from_event)
{
- setControlValue(getSelectedIndex());
+ setControlValue(getValue());
}
return TRUE;
@@ -222,76 +286,45 @@ BOOL LLRadioGroup::handleKeyHere(KEY key, MASK mask)
return handled;
}
-void LLRadioGroup::draw()
+BOOL LLRadioGroup::handleMouseDown(S32 x, S32 y, MASK mask)
{
- S32 current_button = 0;
-
- BOOL take_focus = FALSE;
- if (gFocusMgr.childHasKeyboardFocus(this))
- {
- take_focus = TRUE;
- }
-
- for (button_list_t::iterator iter = mRadioButtons.begin();
- iter != mRadioButtons.end(); ++iter)
+ // grab focus preemptively, before child button takes mousecapture
+ //
+ if (hasTabStop())
{
- LLRadioCtrl* radio = *iter;
- BOOL selected = (current_button == mSelectedIndex);
- radio->setValue( selected );
- if (take_focus && selected && !gFocusMgr.childHasKeyboardFocus(radio))
- {
- // don't flash keyboard focus when navigating via keyboard
- BOOL DONT_FLASH = FALSE;
- radio->focusFirstItem(FALSE, DONT_FLASH);
- }
- current_button++;
+ focusFirstItem(FALSE, FALSE);
}
- LLView::draw();
+ return LLUICtrl::handleMouseDown(x, y, mask);
}
-// When adding a button, we need to ensure that the radio
-// group gets a message when the button is clicked.
-LLRadioCtrl* LLRadioGroup::addRadioButton(const std::string& name, const std::string& label, const LLRect& rect, const LLFontGL* font )
-{
- // Highlight will get fixed in draw method above
- LLRadioCtrl* radio = new LLRadioCtrl(name, rect, label, font,
- onClickButton, this);
- addChild(radio);
- mRadioButtons.push_back(radio);
- return radio;
-}
-
// Handle one button being clicked. All child buttons must have this
// function as their callback function.
-// static
-void LLRadioGroup::onClickButton(LLUICtrl* ui_ctrl, void* userdata)
+void LLRadioGroup::onClickButton(LLUICtrl* ctrl)
{
// llinfos << "LLRadioGroup::onClickButton" << llendl;
-
- LLRadioCtrl* clickedRadio = (LLRadioCtrl*) ui_ctrl;
- LLRadioGroup* self = (LLRadioGroup*) userdata;
-
- S32 counter = 0;
- for (button_list_t::iterator iter = self->mRadioButtons.begin();
- iter != self->mRadioButtons.end(); ++iter)
+ LLRadioCtrl* clicked_radio = dynamic_cast<LLRadioCtrl*>(ctrl);
+ if (!clicked_radio)
+ return;
+ S32 index = 0;
+ for (button_list_t::iterator iter = mRadioButtons.begin();
+ iter != mRadioButtons.end(); ++iter)
{
LLRadioCtrl* radio = *iter;
- if (radio == clickedRadio)
+ if (radio == clicked_radio)
{
- // llinfos << "clicked button " << counter << llendl;
- self->setSelectedIndex(counter);
- self->setControlValue(counter);
+ // llinfos << "clicked button " << index << llendl;
+ setSelectedIndex(index);
// BUG: Calls click callback even if button didn't actually change
- self->onCommit();
+ onCommit();
return;
}
- counter++;
+ index++;
}
llwarns << "LLRadioGroup::onClickButton - clicked button that isn't a child" << llendl;
@@ -299,13 +332,12 @@ void LLRadioGroup::onClickButton(LLUICtrl* ui_ctrl, void* userdata)
void LLRadioGroup::setValue( const LLSD& value )
{
- std::string value_name = value.asString();
int idx = 0;
for (button_list_t::const_iterator iter = mRadioButtons.begin();
iter != mRadioButtons.end(); ++iter)
{
LLRadioCtrl* radio = *iter;
- if (radio->getName() == value_name)
+ if (radio->getPayload().asString() == value.asString())
{
setSelectedIndex(idx);
idx = -1;
@@ -322,7 +354,7 @@ void LLRadioGroup::setValue( const LLSD& value )
}
else
{
- llwarns << "LLRadioGroup::setValue: value not found: " << value_name << llendl;
+ llwarns << "LLRadioGroup::setValue: value not found: " << value.asString() << llendl;
}
}
}
@@ -334,113 +366,12 @@ LLSD LLRadioGroup::getValue() const
for (button_list_t::const_iterator iter = mRadioButtons.begin();
iter != mRadioButtons.end(); ++iter)
{
- if (idx == index) return LLSD((*iter)->getName());
+ if (idx == index) return LLSD((*iter)->getPayload());
++idx;
}
return LLSD();
}
-// virtual
-LLXMLNodePtr LLRadioGroup::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLUICtrl::getXML();
-
- // Attributes
-
- node->createChild("draw_border", TRUE)->setBoolValue(mHasBorder);
-
- // Contents
-
- for (button_list_t::const_iterator iter = mRadioButtons.begin();
- iter != mRadioButtons.end(); ++iter)
- {
- LLRadioCtrl* radio = *iter;
-
- LLXMLNodePtr child_node = radio->LLView::getXML();
- child_node->setStringValue(radio->getLabel());
- child_node->setName(std::string("radio_item"));
-
- node->addChild(child_node);
- }
-
- return node;
-}
-
-// static
-LLView* LLRadioGroup::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("radio_group");
- node->getAttributeString("name", name);
-
- U32 initial_value = 0;
- node->getAttributeU32("initial_value", initial_value);
-
- BOOL draw_border = TRUE;
- node->getAttributeBOOL("draw_border", draw_border);
-
- LLRect rect;
- createRect(node, rect, parent, LLRect());
-
- LLRadioGroup* radio_group = new LLRadioGroup(name,
- rect,
- initial_value,
- NULL,
- NULL,
- draw_border);
-
- const std::string& contents = node->getValue();
-
- LLRect group_rect = radio_group->getRect();
-
- LLFontGL *font = LLView::selectFont(node);
-
- if (contents.find_first_not_of(" \n\t") != contents.npos)
- {
- // ...old school default vertical layout
- typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
- boost::char_separator<char> sep("\t\n");
- tokenizer tokens(contents, sep);
- tokenizer::iterator token_iter = tokens.begin();
-
- const S32 HPAD = 4, VPAD = 4;
- S32 cur_y = group_rect.getHeight() - VPAD;
-
- while(token_iter != tokens.end())
- {
- const std::string& line = *token_iter;
- LLRect rect(HPAD, cur_y, group_rect.getWidth() - (2 * HPAD), cur_y - 15);
- cur_y -= VPAD + 15;
- radio_group->addRadioButton(std::string("radio"), line, rect, font);
- ++token_iter;
- }
- llwarns << "Legacy radio group format used! Please convert to use <radio_item> tags!" << llendl;
- }
- else
- {
- // ...per pixel layout
- LLXMLNodePtr child;
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
- {
- if (child->hasName("radio_item"))
- {
- LLRect item_rect;
- createRect(child, item_rect, radio_group, rect);
-
- std::string radioname("radio");
- child->getAttributeString("name", radioname);
- std::string item_label = child->getTextContents();
- LLRadioCtrl* radio = radio_group->addRadioButton(radioname, item_label, item_rect, font);
-
- radio->initFromXML(child, radio_group);
- }
- }
- }
-
- radio_group->initFromXML(node, parent);
-
- return radio_group;
-}
-
// LLCtrlSelectionInterface functions
BOOL LLRadioGroup::setCurrentByID( const LLUUID& id )
{
@@ -455,11 +386,10 @@ LLUUID LLRadioGroup::getCurrentID() const
BOOL LLRadioGroup::setSelectedByValue(const LLSD& value, BOOL selected)
{
S32 idx = 0;
- std::string value_string = value.asString();
for (button_list_t::const_iterator iter = mRadioButtons.begin();
iter != mRadioButtons.end(); ++iter)
{
- if((*iter)->getName() == value_string)
+ if((*iter)->getPayload().asString() == value.asString())
{
setSelectedIndex(idx);
return TRUE;
@@ -478,11 +408,10 @@ LLSD LLRadioGroup::getSelectedValue()
BOOL LLRadioGroup::isSelected(const LLSD& value) const
{
S32 idx = 0;
- std::string value_string = value.asString();
for (button_list_t::const_iterator iter = mRadioButtons.begin();
iter != mRadioButtons.end(); ++iter)
{
- if((*iter)->getName() == value_string)
+ if((*iter)->getPayload().asString() == value.asString())
{
if (idx == mSelectedIndex)
{
@@ -504,6 +433,34 @@ BOOL LLRadioGroup::operateOnAll(EOperation op)
return FALSE;
}
+LLRadioGroup::ItemParams::ItemParams()
+: value("value")
+{
+ addSynonym(value, "initial_value");
+}
+
+LLRadioCtrl::LLRadioCtrl(const LLRadioGroup::ItemParams& p)
+: LLCheckBoxCtrl(p),
+ mPayload(p.value)
+{
+ // use name as default "Value" for backwards compatibility
+ if (!p.value.isProvided())
+ {
+ mPayload = p.name();
+ }
+}
+
+BOOL LLRadioCtrl::postBuild()
+{
+ // Old-style radio_item used the text contents to indicate the label,
+ // but new-style radio_item uses label attribute.
+ std::string value = getValue().asString();
+ if (!value.empty())
+ {
+ setLabel(value);
+ }
+ return TRUE;
+}
LLRadioCtrl::~LLRadioCtrl()
{
@@ -515,3 +472,19 @@ void LLRadioCtrl::setValue(const LLSD& value)
mButton->setTabStop(value.asBoolean());
}
+// *TODO: Remove this function after the initial XUI XML re-export pass.
+// static
+void LLRadioCtrl::setupParamsForExport(Params& p, LLView* parent)
+{
+ std::string label = p.label;
+ if (label.empty())
+ {
+ // We don't have a label attribute, so move the text contents
+ // stored in "value" into the label
+ std::string initial_value = p.LLUICtrl::Params::initial_value();
+ p.label = initial_value;
+ p.LLUICtrl::Params::initial_value = LLSD();
+ }
+
+ LLCheckBoxCtrl::setupParamsForExport(p, parent);
+}
diff --git a/indra/llui/llradiogroup.h b/indra/llui/llradiogroup.h
index 3410b74104..b178bb36ca 100644
--- a/indra/llui/llradiogroup.h
+++ b/indra/llui/llradiogroup.h
@@ -37,25 +37,6 @@
#include "llcheckboxctrl.h"
#include "llctrlselectioninterface.h"
-
-/*
- * A checkbox control with use_radio_style == true.
- */
-class LLRadioCtrl : public LLCheckBoxCtrl
-{
-public:
- LLRadioCtrl(const std::string& name, const LLRect& rect, const std::string& label, const LLFontGL* font = NULL,
- void (*commit_callback)(LLUICtrl*, void*) = NULL, void* callback_userdata = NULL) :
- LLCheckBoxCtrl(name, rect, label, font, commit_callback, callback_userdata, FALSE, RADIO_STYLE)
- {
- setTabStop(FALSE);
- }
- /*virtual*/ ~LLRadioCtrl();
-
- /*virtual*/ void setValue(const LLSD& value);
-};
-
-
/*
* An invisible view containing multiple mutually exclusive toggling
* buttons (usually radio buttons). Automatically handles the mutex
@@ -65,32 +46,37 @@ class LLRadioGroup
: public LLUICtrl, public LLCtrlSelectionInterface
{
public:
- // Build a radio group. The number (0...n-1) of the currently selected
- // element will be stored in the named control. After the control is
- // changed the callback will be called.
- LLRadioGroup(const std::string& name, const LLRect& rect,
- const std::string& control_name,
- LLUICtrlCallback callback = NULL,
- void* userdata = NULL,
- BOOL border = TRUE);
-
- // Another radio group constructor, but this one doesn't rely on
- // needing a control
- LLRadioGroup(const std::string& name, const LLRect& rect,
- S32 initial_index,
- LLUICtrlCallback callback = NULL,
- void* userdata = NULL,
- BOOL border = TRUE);
- virtual ~LLRadioGroup();
+ struct ItemParams : public LLInitParam::Block<ItemParams, LLCheckBoxCtrl::Params>
+ {
+ Optional<LLSD> value;
+ ItemParams();
+ };
+
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<bool> has_border;
+ Multiple<ItemParams, AtLeast<1> > items;
+ Params();
+ };
+
+protected:
+ LLRadioGroup(const Params&);
+ friend class LLUICtrlFactory;
+
+public:
+ /*virtual*/ void initFromParams(const Params&);
+
+ virtual ~LLRadioGroup();
+
+ virtual BOOL postBuild();
+
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+
virtual BOOL handleKeyHere(KEY key, MASK mask);
- virtual void setEnabled(BOOL enabled);
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
void setIndexEnabled(S32 index, BOOL enabled);
-
// return the index value of the selected item
S32 getSelectedIndex() const { return mSelectedIndex; }
@@ -101,16 +87,8 @@ public:
virtual void setValue(const LLSD& value );
virtual LLSD getValue() const;
- // Draw the group, but also fix the highlighting based on the control.
- void draw();
-
- // You must use this method to add buttons to a radio group.
- // Don't use addChild -- it won't set the callback function
- // correctly.
- LLRadioCtrl* addRadioButton(const std::string& name, const std::string& label, const LLRect& rect, const LLFontGL* font);
- LLRadioCtrl* getRadioButton(const S32& index) { return mRadioButtons[index]; }
// Update the control as needed. Userdata must be a pointer to the button.
- static void onClickButton(LLUICtrl* radio, void* userdata);
+ void onClickButton(LLUICtrl* clicked_radio);
//========================================================================
LLCtrlSelectionInterface* getSelectionInterface() { return (LLCtrlSelectionInterface*)this; };
@@ -131,15 +109,12 @@ public:
/*virtual*/ BOOL operateOnAll(EOperation op);
private:
- // protected function shared by the two constructors.
- void init(BOOL border);
-
+ const LLFontGL* mFont;
S32 mSelectedIndex;
- typedef std::vector<LLRadioCtrl*> button_list_t;
+ typedef std::vector<class LLRadioCtrl*> button_list_t;
button_list_t mRadioButtons;
BOOL mHasBorder;
};
-
#endif
diff --git a/indra/llui/llresizebar.cpp b/indra/llui/llresizebar.cpp
index 5b9fe72e99..0c46edf300 100644
--- a/indra/llui/llresizebar.cpp
+++ b/indra/llui/llresizebar.cpp
@@ -40,22 +40,22 @@
#include "llfocusmgr.h"
#include "llwindow.h"
-LLResizeBar::LLResizeBar( const std::string& name, LLView* resizing_view, const LLRect& rect, S32 min_size, S32 max_size, Side side )
- :
- LLView( name, rect, TRUE ),
+LLResizeBar::LLResizeBar(const LLResizeBar::Params& p)
+: LLView(p),
mDragLastScreenX( 0 ),
mDragLastScreenY( 0 ),
mLastMouseScreenX( 0 ),
mLastMouseScreenY( 0 ),
- mMinSize( min_size ),
- mMaxSize( max_size ),
- mSide( side ),
- mSnappingEnabled(TRUE),
- mAllowDoubleClickSnapping(TRUE),
- mResizingView(resizing_view)
+ mMinSize( p.min_size ),
+ mMaxSize( p.max_size ),
+ mSide( p.side ),
+ mSnappingEnabled(p.snapping_enabled),
+ mAllowDoubleClickSnapping(p.allow_double_click_snapping),
+ mResizingView(p.resizing_view)
{
+ setFollowsNone();
// set up some generically good follow code.
- switch( side )
+ switch( mSide )
{
case LEFT:
setFollowsLeft();
@@ -80,8 +80,6 @@ LLResizeBar::LLResizeBar( const std::string& name, LLView* resizing_view, const
default:
break;
}
- // this is just a decorator
- setSaveToXML(FALSE);
}
@@ -145,6 +143,13 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask)
if( valid_rect.localPointInRect( screen_x, screen_y ) && mResizingView )
{
+ // undock floater when user resize it
+ LLFloater* parent = dynamic_cast<LLFloater*>( getParent());
+ if (parent && parent->isDocked())
+ {
+ parent->setDocked( false, false);
+ }
+
// Resize the parent
LLRect orig_rect = mResizingView->getRect();
LLRect scaled_rect = orig_rect;
@@ -185,30 +190,31 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask)
if (mSnappingEnabled)
{
+ static LLUICachedControl<S32> snap_margin ("SnapMargin", 0);
switch( mSide )
{
case LEFT:
- snap_view = mResizingView->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
+ snap_view = mResizingView->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, snap_margin);
break;
case TOP:
- snap_view = mResizingView->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
+ snap_view = mResizingView->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, snap_margin);
break;
case RIGHT:
- snap_view = mResizingView->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
+ snap_view = mResizingView->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, snap_margin);
break;
case BOTTOM:
- snap_view = mResizingView->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
+ snap_view = mResizingView->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, snap_margin);
break;
}
}
// register "snap" behavior with snapped view
- mResizingView->snappedTo(snap_view);
+ mResizingView->setSnappedTo(snap_view);
// restore original rectangle so the appropriate changes are detected
mResizingView->setRect(orig_rect);
// change view shape as user operation
- mResizingView->userSetShape(scaled_rect);
+ mResizingView->setShape(scaled_rect, true);
// update last valid mouse cursor position based on resized view's actual size
LLRect new_rect = mResizingView->getRect();
@@ -284,7 +290,7 @@ BOOL LLResizeBar::handleDoubleClick(S32 x, S32 y, MASK mask)
break;
}
- mResizingView->userSetShape(scaled_rect);
+ mResizingView->setShape(scaled_rect, true);
}
return TRUE;
diff --git a/indra/llui/llresizebar.h b/indra/llui/llresizebar.h
index b9fc40593d..a7bc3c60f5 100644
--- a/indra/llui/llresizebar.h
+++ b/indra/llui/llresizebar.h
@@ -41,7 +41,31 @@ class LLResizeBar : public LLView
public:
enum Side { LEFT, TOP, RIGHT, BOTTOM };
- LLResizeBar(const std::string& name, LLView* resizing_view, const LLRect& rect, S32 min_size, S32 max_size, Side side );
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
+ {
+ Mandatory<LLView*> resizing_view;
+ Mandatory<Side> side;
+
+ Optional<S32> min_size;
+ Optional<S32> max_size;
+ Optional<bool> snapping_enabled;
+ Optional<bool> allow_double_click_snapping;
+
+ Params()
+ : max_size("max_size", S32_MAX),
+ snapping_enabled("snapping_enabled", true),
+ resizing_view("resizing_view"),
+ side("side"),
+ allow_double_click_snapping("allow_double_click_snapping", true)
+ {
+ name = "resize_bar";
+ }
+ };
+
+protected:
+ LLResizeBar(const LLResizeBar::Params& p);
+ friend class LLUICtrlFactory;
+public:
// virtual void draw(); No appearance
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
diff --git a/indra/llui/llresizehandle.cpp b/indra/llui/llresizehandle.cpp
index c5d57d8d6c..3df09d124a 100644
--- a/indra/llui/llresizehandle.cpp
+++ b/indra/llui/llresizehandle.cpp
@@ -44,37 +44,39 @@
const S32 RESIZE_BORDER_WIDTH = 3;
-LLResizeHandle::LLResizeHandle( const std::string& name, const LLRect& rect, S32 min_width, S32 min_height, ECorner corner )
- :
- LLView( name, rect, TRUE ),
+LLResizeHandle::Params::Params()
+: corner("corner"),
+ min_width("min_width"),
+ min_height("min_height")
+{
+ name = "resize_handle";
+}
+
+LLResizeHandle::LLResizeHandle(const LLResizeHandle::Params& p)
+: LLView(p),
mDragLastScreenX( 0 ),
mDragLastScreenY( 0 ),
mLastMouseScreenX( 0 ),
mLastMouseScreenY( 0 ),
mImage( NULL ),
- mMinWidth( min_width ),
- mMinHeight( min_height ),
- mCorner( corner )
+ mMinWidth( p.min_width ),
+ mMinHeight( p.min_height ),
+ mCorner( p.corner )
{
- setSaveToXML(false);
-
if( RIGHT_BOTTOM == mCorner)
{
- mImage = LLUI::sImageProvider->getUIImage("UIImgResizeBottomRightUUID");
+ mImage = LLUI::getUIImage("Resize_Corner");
}
-
- switch( mCorner )
+ switch( p.corner )
{
- case LEFT_TOP: setFollows( FOLLOWS_LEFT | FOLLOWS_TOP ); break;
- case LEFT_BOTTOM: setFollows( FOLLOWS_LEFT | FOLLOWS_BOTTOM ); break;
- case RIGHT_TOP: setFollows( FOLLOWS_RIGHT | FOLLOWS_TOP ); break;
- case RIGHT_BOTTOM: setFollows( FOLLOWS_RIGHT | FOLLOWS_BOTTOM ); break;
+ case LEFT_TOP: setFollows( FOLLOWS_LEFT | FOLLOWS_TOP ); break;
+ case LEFT_BOTTOM: setFollows( FOLLOWS_LEFT | FOLLOWS_BOTTOM ); break;
+ case RIGHT_TOP: setFollows( FOLLOWS_RIGHT | FOLLOWS_TOP ); break;
+ case RIGHT_BOTTOM: setFollows( FOLLOWS_RIGHT | FOLLOWS_BOTTOM ); break;
}
-
- // decorator object, don't serialize
- setSaveToXML(FALSE);
}
+
BOOL LLResizeHandle::handleMouseDown(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
@@ -122,7 +124,7 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
{
// Make sure the mouse in still over the application. We don't want to make the parent
// so big that we can't see the resize handle any more.
-
+
S32 screen_x;
S32 screen_y;
localPointToScreen(x, y, &screen_x, &screen_y);
@@ -133,108 +135,108 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
LLView* resizing_view = getParent();
if( resizing_view )
{
+ // undock floater when user resize it
+ if (((LLFloater*)getParent())->isDocked())
+ {
+ ((LLFloater*)getParent())->setDocked(false, false);
+ }
+
// Resize the parent
LLRect orig_rect = resizing_view->getRect();
LLRect scaled_rect = orig_rect;
S32 delta_x = screen_x - mDragLastScreenX;
S32 delta_y = screen_y - mDragLastScreenY;
+
+ if(delta_x == 0 && delta_y == 0)
+ return FALSE;
+
LLCoordGL mouse_dir;
// use hysteresis on mouse motion to preserve user intent when mouse stops moving
mouse_dir.mX = (screen_x == mLastMouseScreenX) ? mLastMouseDir.mX : screen_x - mLastMouseScreenX;
mouse_dir.mY = (screen_y == mLastMouseScreenY) ? mLastMouseDir.mY : screen_y - mLastMouseScreenY;
+
mLastMouseScreenX = screen_x;
mLastMouseScreenY = screen_y;
mLastMouseDir = mouse_dir;
- S32 x_multiple = 1;
- S32 y_multiple = 1;
- switch( mCorner )
- {
- case LEFT_TOP:
- x_multiple = -1;
- y_multiple = 1;
- break;
- case LEFT_BOTTOM:
- x_multiple = -1;
- y_multiple = -1;
- break;
- case RIGHT_TOP:
- x_multiple = 1;
- y_multiple = 1;
- break;
- case RIGHT_BOTTOM:
- x_multiple = 1;
- y_multiple = -1;
- break;
- }
-
- S32 new_width = orig_rect.getWidth() + x_multiple * delta_x;
- if( new_width < mMinWidth )
- {
- new_width = mMinWidth;
- delta_x = x_multiple * (mMinWidth - orig_rect.getWidth());
- }
+ S32 new_width = orig_rect.getWidth();
+ S32 new_height = orig_rect.getHeight();
- S32 new_height = orig_rect.getHeight() + y_multiple * delta_y;
- if( new_height < mMinHeight )
- {
- new_height = mMinHeight;
- delta_y = y_multiple * (mMinHeight - orig_rect.getHeight());
- }
+ S32 new_pos_x = orig_rect.mLeft;
+ S32 new_pos_y = orig_rect.mTop;
switch( mCorner )
{
- case LEFT_TOP:
- scaled_rect.translate(delta_x, 0);
+ case LEFT_TOP:
+ new_width-=delta_x;
+ new_height+=delta_y;
+ new_pos_x+=delta_x;
+ new_pos_y+=delta_y;
break;
case LEFT_BOTTOM:
- scaled_rect.translate(delta_x, delta_y);
+ new_width-=delta_x;
+ new_height-=delta_y;
+ new_pos_x+=delta_x;
break;
case RIGHT_TOP:
+ new_width+=delta_x;
+ new_height+=delta_y;
+ new_pos_y+=delta_y;
break;
case RIGHT_BOTTOM:
- scaled_rect.translate(0, delta_y);
+ new_width+=delta_x;
+ new_height-=delta_y;
break;
}
+ new_width = llmax(new_width,mMinWidth);
+ new_height = llmax(new_height,mMinHeight);
+
+ LLRect::tCoordType screen_width = resizing_view->getParent()->getSnapRect().getWidth();
+ LLRect::tCoordType screen_height = resizing_view->getParent()->getSnapRect().getHeight();
+
+ new_width = llmin(new_width, screen_width);
+ new_height = llmin(new_height, screen_height);
+
// temporarily set new parent rect
- scaled_rect.mRight = scaled_rect.mLeft + new_width;
- scaled_rect.mTop = scaled_rect.mBottom + new_height;
+ scaled_rect.setLeftTopAndSize(new_pos_x,new_pos_y,new_width,new_height);
+
resizing_view->setRect(scaled_rect);
LLView* snap_view = NULL;
LLView* test_view = NULL;
+ static LLUICachedControl<S32> snap_margin ("SnapMargin", 0);
// now do snapping
switch(mCorner)
{
case LEFT_TOP:
- snap_view = resizing_view->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
- test_view = resizing_view->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
+ snap_view = resizing_view->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, snap_margin);
+ test_view = resizing_view->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, snap_margin);
if (!snap_view)
{
snap_view = test_view;
}
break;
case LEFT_BOTTOM:
- snap_view = resizing_view->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
- test_view = resizing_view->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
+ snap_view = resizing_view->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, snap_margin);
+ test_view = resizing_view->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, snap_margin);
if (!snap_view)
{
snap_view = test_view;
}
break;
case RIGHT_TOP:
- snap_view = resizing_view->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
- test_view = resizing_view->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
+ snap_view = resizing_view->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, snap_margin);
+ test_view = resizing_view->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, snap_margin);
if (!snap_view)
{
snap_view = test_view;
}
break;
case RIGHT_BOTTOM:
- snap_view = resizing_view->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
- test_view = resizing_view->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
+ snap_view = resizing_view->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, snap_margin);
+ test_view = resizing_view->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, snap_margin);
if (!snap_view)
{
snap_view = test_view;
@@ -243,13 +245,17 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask)
}
// register "snap" behavior with snapped view
- resizing_view->snappedTo(snap_view);
+ resizing_view->setSnappedTo(snap_view);
// reset parent rect
resizing_view->setRect(orig_rect);
// translate and scale to new shape
- resizing_view->userSetShape(scaled_rect);
+ resizing_view->reshape(scaled_rect.getWidth(),scaled_rect.getHeight());
+ resizing_view->setRect(scaled_rect);
+ //set shape to handle dependent floaters...
+ resizing_view->handleReshape(scaled_rect, false);
+
// update last valid mouse cursor position based on resized view's actual size
LLRect new_rect = resizing_view->getRect();
diff --git a/indra/llui/llresizehandle.h b/indra/llui/llresizehandle.h
index 0e23d526fa..1c09cbb1bd 100644
--- a/indra/llui/llresizehandle.h
+++ b/indra/llui/llresizehandle.h
@@ -35,7 +35,6 @@
#include "stdtypes.h"
#include "llview.h"
-#include "llimagegl.h"
#include "llcoord.h"
@@ -44,9 +43,18 @@ class LLResizeHandle : public LLView
public:
enum ECorner { LEFT_TOP, LEFT_BOTTOM, RIGHT_TOP, RIGHT_BOTTOM };
-
- LLResizeHandle(const std::string& name, const LLRect& rect, S32 min_width, S32 min_height, ECorner corner = RIGHT_BOTTOM );
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
+ {
+ Mandatory<ECorner> corner;
+ Optional<S32> min_width;
+ Optional<S32> min_height;
+ Params();
+ };
+protected:
+ LLResizeHandle(const LLResizeHandle::Params&);
+ friend class LLUICtrlFactory;
+public:
virtual void draw();
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
@@ -68,8 +76,8 @@ private:
const ECorner mCorner;
};
-const S32 RESIZE_HANDLE_HEIGHT = 16;
-const S32 RESIZE_HANDLE_WIDTH = 16;
+const S32 RESIZE_HANDLE_HEIGHT = 11;
+const S32 RESIZE_HANDLE_WIDTH = 11;
#endif // LL_RESIZEHANDLE_H
diff --git a/indra/llui/llresmgr.cpp b/indra/llui/llresmgr.cpp
index 141b08c39d..ed870d46d5 100644
--- a/indra/llui/llresmgr.cpp
+++ b/indra/llui/llresmgr.cpp
@@ -43,106 +43,8 @@
LLResMgr::LLResMgr()
{
- U32 i;
-
- // Init values for each locale.
- // Note: This is only the most bare-bones version. In the future, load these dynamically, on demand.
-
- //////////////////////////////////////////////////////////////////////////////
- // USA
- // USA Fonts
- for( i=0; i<LLFONT_COUNT; i++ )
- {
- mUSAFonts[i] = NULL;
- }
- mUSAFonts[ LLFONT_OCRA ] = LLFontGL::getFontMonospace();
- mUSAFonts[ LLFONT_SANSSERIF ] = LLFontGL::getFontSansSerif();
- mUSAFonts[ LLFONT_SANSSERIF_SMALL ] = LLFontGL::getFontSansSerifSmall();
- mUSAFonts[ LLFONT_SANSSERIF_BIG ] = LLFontGL::getFontSansSerifBig();
- mUSAFonts[ LLFONT_SMALL ] = LLFontGL::getFontMonospace();
-/*
- // USA Strings
- for( i=0; i<LLSTR_COUNT; i++ )
- {
- mUSAStrings[i] = "";
- }
- mUSAStrings[ LLSTR_HELLO ] = "hello";
- mUSAStrings[ LLSTR_GOODBYE ] = "goodbye";
- mUSAStrings[ LLSTR_CHAT_LABEL ] = "Chat";
- mUSAStrings[ LLSTR_STATUS_LABEL ] = "Properties";
- mUSAStrings[ LLSTR_X ] = "X";
- mUSAStrings[ LLSTR_Y ] = "Y";
- mUSAStrings[ LLSTR_Z ] = "Z";
- mUSAStrings[ LLSTR_POSITION ] = "Position (meters)";
- mUSAStrings[ LLSTR_SCALE ] = "Size (meters)";
- mUSAStrings[ LLSTR_ROTATION ] = "Rotation (degrees)";
- mUSAStrings[ LLSTR_HAS_PHYSICS ] = "Has Physics";
- mUSAStrings[ LLSTR_SCRIPT ] = "Script";
- mUSAStrings[ LLSTR_HELP ] = "Help";
- mUSAStrings[ LLSTR_REMOVE ] = "Remove";
- mUSAStrings[ LLSTR_CLEAR ] = "Clear";
- mUSAStrings[ LLSTR_APPLY ] = "Apply";
- mUSAStrings[ LLSTR_CANCEL ] = "Cancel";
- mUSAStrings[ LLSTR_MATERIAL ] = "Material";
- mUSAStrings[ LLSTR_FACE ] = "Face";
- mUSAStrings[ LLSTR_TEXTURE ] = "Texture";
- mUSAStrings[ LLSTR_TEXTURE_SIZE ] = "Repeats per Face";
- mUSAStrings[ LLSTR_TEXTURE_OFFSET ] = "Offset";
- mUSAStrings[ LLSTR_TEXTURE_ROTATION ] = "Rotation (degrees)";
- mUSAStrings[ LLSTR_U ] = "U";
- mUSAStrings[ LLSTR_V ] = "V";
- mUSAStrings[ LLSTR_OWNERSHIP ] = "Ownership";
- mUSAStrings[ LLSTR_PUBLIC ] = "Public";
- mUSAStrings[ LLSTR_PRIVATE ] = "Private";
- mUSAStrings[ LLSTR_REVERT ] = "Revert";
- mUSAStrings[ LLSTR_INSERT_SAMPLE ] = "Insert Sample";
- mUSAStrings[ LLSTR_SET_TEXTURE ] = "Set Texture";
- mUSAStrings[ LLSTR_EDIT_SCRIPT ] = "Edit Script...";
- mUSAStrings[ LLSTR_MOUSELOOK_INSTRUCTIONS ] = "Press ESC to leave Mouselook.";
- mUSAStrings[ LLSTR_EDIT_FACE_INSTRUCTIONS ] = "Click on face to select part. Click and hold on a picture to look more like that. Press ESC to leave Face Edit Mode.";
- mUSAStrings[ LLSTR_CLOSE ] = "Close";
- mUSAStrings[ LLSTR_MOVE ] = "Move";
- mUSAStrings[ LLSTR_ROTATE ] = "Rotate";
- mUSAStrings[ LLSTR_RESIZE ] = "Resize";
- mUSAStrings[ LLSTR_PLACE_BOX ] = "Place Box";
- mUSAStrings[ LLSTR_PLACE_PRISM ] = "Place Prism";
- mUSAStrings[ LLSTR_PLACE_PYRAMID ] = "Place Pyramid";
- mUSAStrings[ LLSTR_PLACE_TETRAHEDRON ] = "Place Tetrahedron";
- mUSAStrings[ LLSTR_PLACE_CYLINDER ] = "Place Cylinder";
- mUSAStrings[ LLSTR_PLACE_HALF_CYLINDER ] = "Place Half-Cylinder";
- mUSAStrings[ LLSTR_PLACE_CONE ] = "Place Cone";
- mUSAStrings[ LLSTR_PLACE_HALF_CONE ] = "Place Half-Cone";
- mUSAStrings[ LLSTR_PLACE_SPHERE ] = "Place Sphere";
- mUSAStrings[ LLSTR_PLACE_HALF_SPHERE ] = "Place Half-Sphere";
- mUSAStrings[ LLSTR_PLACE_BIRD ] = "Place Bird";
- mUSAStrings[ LLSTR_PLACE_SNAKE ] = "Place Silly Snake";
- mUSAStrings[ LLSTR_PLACE_ROCK ] = "Place Rock";
- mUSAStrings[ LLSTR_PLACE_TREE ] = "Place Tree";
- mUSAStrings[ LLSTR_PLACE_GRASS ] = "Place Grass";
- mUSAStrings[ LLSTR_MODIFY_LAND ] = "Modify Land";
-*/
- //////////////////////////////////////////////////////////////////////////////
- // UK
- // The Brits are a lot like us Americans, so initially assume we're the same and only code the exceptions.
-
- // UK Fonts
- for( i=0; i<LLFONT_COUNT; i++ )
- {
- mUKFonts[i] = mUSAFonts[i];
- }
-/*
- // UK Strings
- for( i=0; i<LLSTR_COUNT; i++ )
- {
- mUKStrings[i] = mUSAStrings[i];
- }
- mUKStrings[ LLSTR_HELLO ] = "hullo";
- mUKStrings[ LLSTR_GOODBYE ] = "cheerio";
-*/
- //////////////////////////////////////////////////////////////////////////////
// Set default
setLocale( LLLOCALE_USA );
-
}
@@ -151,9 +53,9 @@ void LLResMgr::setLocale( LLLOCALE_ID locale_id )
mLocale = locale_id;
//RN: for now, use normal 'C' locale for everything but specific UI input/output routines
- switch( locale_id )
- {
- case LLLOCALE_USA:
+// switch( locale_id )
+// {
+// case LLLOCALE_USA:
//#if LL_WINDOWS
// // Windows doesn't use ISO country codes.
// llinfos << "Setting locale to " << setlocale( LC_ALL, "english-usa" ) << llendl;
@@ -161,11 +63,8 @@ void LLResMgr::setLocale( LLLOCALE_ID locale_id )
// // posix version should work everywhere else.
// llinfos << "Setting locale to " << setlocale( LC_ALL, "en_US" ) << llendl;
//#endif
-
-// mStrings = mUSAStrings;
- mFonts = mUSAFonts;
- break;
- case LLLOCALE_UK:
+// break;
+// case LLLOCALE_UK:
//#if LL_WINDOWS
// // Windows doesn't use ISO country codes.
// llinfos << "Setting locale to " << setlocale( LC_ALL, "english-uk" ) << llendl;
@@ -173,15 +72,12 @@ void LLResMgr::setLocale( LLLOCALE_ID locale_id )
// // posix version should work everywhere else.
// llinfos << "Setting locale to " << setlocale( LC_ALL, "en_GB" ) << llendl;
//#endif
-
-// mStrings = mUKStrings;
- mFonts = mUKFonts;
- break;
- default:
- llassert(0);
- setLocale(LLLOCALE_USA);
- break;
- }
+// break;
+// default:
+// llassert(0);
+// setLocale(LLLOCALE_USA);
+// break;
+// }
}
char LLResMgr::getDecimalPoint() const
@@ -383,6 +279,14 @@ std::string LLResMgr::getMonetaryString( S32 input ) const
void LLResMgr::getIntegerString( std::string& output, S32 input ) const
{
+ // handle special case of input value being zero
+ if (input == 0)
+ {
+ output = "0";
+ return;
+ }
+
+ // *NOTE: this method does not handle negative input integers correctly
S32 fraction = 0;
std::string fraction_string;
S32 remaining_count = input;
@@ -418,27 +322,6 @@ void LLResMgr::getIntegerString( std::string& output, S32 input ) const
}
}
-const std::string LLFONT_ID_NAMES[] =
-{
- std::string("OCRA"),
- std::string("SANSSERIF"),
- std::string("SANSSERIF_SMALL"),
- std::string("SANSSERIF_BIG"),
- std::string("SMALL"),
-};
-
-const LLFontGL* LLResMgr::getRes( std::string font_id ) const
-{
- for (S32 i=0; i<LLFONT_COUNT; ++i)
- {
- if (LLFONT_ID_NAMES[i] == font_id)
- {
- return getRes((LLFONT_ID)i);
- }
- }
- return NULL;
-}
-
#if LL_WINDOWS
const std::string LLLocale::USER_LOCALE("English_United States.1252");// = LLStringUtil::null;
const std::string LLLocale::SYSTEM_LOCALE("English_United States.1252");
diff --git a/indra/llui/llresmgr.h b/indra/llui/llresmgr.h
index d54505c503..c8fa340990 100644
--- a/indra/llui/llresmgr.h
+++ b/indra/llui/llresmgr.h
@@ -37,7 +37,7 @@
#include "locale.h"
#include "stdtypes.h"
#include "llstring.h"
-#include "llmemory.h"
+#include "llsingleton.h"
enum LLLOCALE_ID
{
@@ -46,18 +46,6 @@ enum LLLOCALE_ID
LLLOCALE_COUNT // Number of values in this enum. Keep at end.
};
-enum LLFONT_ID
-{
- LLFONT_OCRA,
- LLFONT_SANSSERIF,
- LLFONT_SANSSERIF_SMALL,
- LLFONT_SANSSERIF_BIG,
- LLFONT_SMALL,
- LLFONT_COUNT // Number of values in this enum. Keep at end.
-};
-
-class LLFontGL;
-
class LLResMgr : public LLSingleton<LLResMgr>
{
public:
@@ -74,20 +62,9 @@ public:
std::string getMonetaryString( S32 input ) const;
void getIntegerString( std::string& output, S32 input ) const;
-// const char* getRes( LLSTR_ID string_id ) const { return mStrings[ string_id ]; }
- const LLFontGL* getRes( LLFONT_ID font_id ) const { return mFonts[ font_id ]; }
- const LLFontGL* getRes( std::string font_id ) const;
private:
LLLOCALE_ID mLocale;
-// const char** mStrings;
- const LLFontGL** mFonts;
-
-// const char* mUSAStrings[LLSTR_COUNT];
- const LLFontGL* mUSAFonts[LLFONT_COUNT];
-
-// const char* mUKStrings[LLSTR_COUNT];
- const LLFontGL* mUKFonts[LLFONT_COUNT];
};
class LLLocale
diff --git a/indra/llui/llrngwriter.cpp b/indra/llui/llrngwriter.cpp
new file mode 100644
index 0000000000..7e3d4b92d3
--- /dev/null
+++ b/indra/llui/llrngwriter.cpp
@@ -0,0 +1,316 @@
+/**
+ * @file llrngwriter.cpp
+ * @brief Generates Relax NG schema from param blocks
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llrngwriter.h"
+#include "lluicolor.h"
+#include "lluictrlfactory.h"
+
+//
+// LLRNGWriter - writes Relax NG schema files based on a param block
+//
+LLRNGWriter::LLRNGWriter()
+{
+ // register various callbacks for inspecting the contents of a param block
+ registerInspectFunc<bool>(boost::bind(&LLRNGWriter::writeAttribute, this, "boolean", _1, _2, _3, _4));
+ registerInspectFunc<std::string>(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4));
+ registerInspectFunc<U8>(boost::bind(&LLRNGWriter::writeAttribute, this, "unsignedByte", _1, _2, _3, _4));
+ registerInspectFunc<S8>(boost::bind(&LLRNGWriter::writeAttribute, this, "signedByte", _1, _2, _3, _4));
+ registerInspectFunc<U16>(boost::bind(&LLRNGWriter::writeAttribute, this, "unsignedShort", _1, _2, _3, _4));
+ registerInspectFunc<S16>(boost::bind(&LLRNGWriter::writeAttribute, this, "signedShort", _1, _2, _3, _4));
+ registerInspectFunc<U32>(boost::bind(&LLRNGWriter::writeAttribute, this, "unsignedInt", _1, _2, _3, _4));
+ registerInspectFunc<S32>(boost::bind(&LLRNGWriter::writeAttribute, this, "integer", _1, _2, _3, _4));
+ registerInspectFunc<F32>(boost::bind(&LLRNGWriter::writeAttribute, this, "float", _1, _2, _3, _4));
+ registerInspectFunc<F64>(boost::bind(&LLRNGWriter::writeAttribute, this, "double", _1, _2, _3, _4));
+ registerInspectFunc<LLColor4>(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4));
+ registerInspectFunc<LLUIColor>(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4));
+ registerInspectFunc<LLUUID>(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4));
+ registerInspectFunc<LLSD>(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4));
+}
+
+void LLRNGWriter::writeRNG(const std::string& type_name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace)
+{
+ mGrammarNode = node;
+ mGrammarNode->setName("grammar");
+ mGrammarNode->createChild("xmlns", true)->setStringValue("http://relaxng.org/ns/structure/1.0");
+ mGrammarNode->createChild("datatypeLibrary", true)->setStringValue("http://www.w3.org/2001/XMLSchema-datatypes");
+ mGrammarNode->createChild("ns", true)->setStringValue(xml_namespace);
+
+ node = mGrammarNode->createChild("start", false);
+ node = node->createChild("ref", false);
+ node->createChild("name", true)->setStringValue(type_name);
+
+ addDefinition(type_name, block);
+}
+
+void LLRNGWriter::addDefinition(const std::string& type_name, const LLInitParam::BaseBlock& block)
+{
+ if (mDefinedElements.find(type_name) != mDefinedElements.end()) return;
+ mDefinedElements.insert(type_name);
+
+ LLXMLNodePtr node = mGrammarNode->createChild("define", false);
+ node->createChild("name", true)->setStringValue(type_name);
+
+ mElementNode = node->createChild("element", false);
+ mElementNode->createChild("name", true)->setStringValue(type_name);
+ mChildrenNode = mElementNode->createChild("zeroOrMore", false)->createChild("choice", false);
+
+ mAttributesWritten.first = mElementNode;
+ mAttributesWritten.second.clear();
+ mElementsWritten.clear();
+
+ block.inspectBlock(*this);
+
+ // add includes for all possible children
+ const std::type_info* type = *LLWidgetTypeRegistry::instance().getValue(type_name);
+ const widget_registry_t* widget_registryp = LLChildRegistryRegistry::instance().getValue(type);
+
+ // add include declarations for all valid children
+ for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems();
+ it != widget_registryp->currentRegistrar().endItems();
+ ++it)
+ {
+ std::string child_name = it->first;
+ if (child_name == type_name)
+ {
+ continue;
+ }
+
+ LLXMLNodePtr old_element_node = mElementNode;
+ LLXMLNodePtr old_child_node = mChildrenNode;
+ //FIXME: add LLDefaultParamBlockRegistry back when working on schema generation
+ //addDefinition(child_name, (*LLDefaultParamBlockRegistry::instance().getValue(type))());
+ mElementNode = old_element_node;
+ mChildrenNode = old_child_node;
+
+ mChildrenNode->createChild("ref", false)->createChild("name", true)->setStringValue(child_name);
+ }
+
+ if (mChildrenNode->mChildren.isNull())
+ {
+ // remove unused children node
+ mChildrenNode->mParent->mParent->deleteChild(mChildrenNode->mParent);
+ }
+}
+
+void LLRNGWriter::writeAttribute(const std::string& type, const Parser::name_stack_t& stack, S32 min_count, S32 max_count, const std::vector<std::string>* possible_values)
+{
+ if (max_count == 0) return;
+
+ name_stack_t non_empty_names;
+ std::string attribute_name;
+ for (name_stack_t::const_iterator it = stack.begin();
+ it != stack.end();
+ ++it)
+ {
+ const std::string& name = it->first;
+ if (!name.empty())
+ {
+ non_empty_names.push_back(*it);
+ }
+ }
+
+ if (non_empty_names.empty()) return;
+
+ for (name_stack_t::const_iterator it = non_empty_names.begin();
+ it != non_empty_names.end();
+ ++it)
+ {
+ if (!attribute_name.empty())
+ {
+ attribute_name += ".";
+ }
+ attribute_name += it->first;
+ }
+
+ // singular attribute, e.g. <foo bar="1"/>
+ if (non_empty_names.size() == 1 && max_count == 1)
+ {
+ if (mAttributesWritten.second.find(attribute_name) == mAttributesWritten.second.end())
+ {
+ LLXMLNodePtr node = createCardinalityNode(mElementNode, min_count, max_count)->createChild("attribute", false);
+ node->createChild("name", true)->setStringValue(attribute_name);
+ node->createChild("data", false)->createChild("type", true)->setStringValue(type);
+
+ mAttributesWritten.second.insert(attribute_name);
+ }
+ }
+ // compound attribute
+ else
+ {
+ std::string element_name;
+
+ // traverse all but last element, leaving that as an attribute name
+ name_stack_t::const_iterator end_it = non_empty_names.end();
+ end_it--;
+
+ for (name_stack_t::const_iterator it = non_empty_names.begin();
+ it != end_it;
+ ++it)
+ {
+ if (it != non_empty_names.begin())
+ {
+ element_name += ".";
+ }
+ element_name += it->first;
+ }
+
+ elements_map_t::iterator found_it = mElementsWritten.find(element_name);
+ // <choice>
+ // <group>
+ // <optional>
+ // <attribute name="foo.bar"><data type="string"/></attribute>
+ // </optional>
+ // <optional>
+ // <attribute name="foo.baz"><data type="integer"/></attribute>
+ // </optional>
+ // </group>
+ // <element name="foo">
+ // <optional>
+ // <attribute name="bar"><data type="string"/></attribute>
+ // </optional>
+ // <optional>
+ // <attribute name="baz"><data type="string"/></attribute>
+ // </optional>
+ // </element>
+ // <element name="outer.foo">
+ // <ref name="foo"/>
+ // </element>
+ // </choice>
+
+ if (found_it != mElementsWritten.end())
+ {
+ // reuse existing element
+ LLXMLNodePtr choice_node = found_it->second.first;
+
+ // attribute with this name not already written?
+ if (found_it->second.second.find(attribute_name) == found_it->second.second.end())
+ {
+ // append to <group>
+ LLXMLNodePtr node = choice_node->mChildren->head;
+ node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false);
+ node->createChild("name", true)->setStringValue(attribute_name);
+ addTypeNode(node, type, possible_values);
+
+ // append to <element>
+ node = choice_node->mChildren->head->mNext->mChildren->head;
+ node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false);
+ node->createChild("name", true)->setStringValue(non_empty_names.back().first);
+ addTypeNode(node, type, possible_values);
+
+ // append to <element>
+ //node = choice_node->mChildren->head->mNext->mNext->mChildren->head;
+ //node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false);
+ //node->createChild("name", true)->setStringValue(non_empty_names.back().first);
+ //addTypeNode(node, type, possible_values);
+
+ found_it->second.second.insert(attribute_name);
+ }
+ }
+ else
+ {
+ LLXMLNodePtr choice_node = mElementNode->createChild("choice", false);
+
+ LLXMLNodePtr node = choice_node->createChild("group", false);
+ node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false);
+ node->createChild("name", true)->setStringValue(attribute_name);
+ addTypeNode(node, type, possible_values);
+
+ node = choice_node->createChild("optional", false);
+ node = node->createChild("element", false);
+ node->createChild("name", true)->setStringValue(element_name);
+ node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false);
+ node->createChild("name", true)->setStringValue(non_empty_names.back().first);
+ addTypeNode(node, type, possible_values);
+
+ //node = choice_node->createChild("optional", false);
+ //node = node->createChild("element", false);
+ //node->createChild("name", true)->setStringValue(mDefinitionName + "." + element_name);
+ //node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false);
+ //node->createChild("name", true)->setStringValue(non_empty_names.back().first);
+ //addTypeNode(node, type, possible_values);
+
+ attribute_data_t& attribute_data = mElementsWritten[element_name];
+ attribute_data.first = choice_node;
+ attribute_data.second.insert(attribute_name);
+ }
+ }
+}
+
+void LLRNGWriter::addTypeNode(LLXMLNodePtr parent_node, const std::string& type, const std::vector<std::string>* possible_values)
+{
+ if (possible_values)
+ {
+ LLXMLNodePtr enum_node = parent_node->createChild("choice", false);
+ for (std::vector<std::string>::const_iterator it = possible_values->begin();
+ it != possible_values->end();
+ ++it)
+ {
+ enum_node->createChild("value", false)->setStringValue(*it);
+ }
+ }
+ else
+ {
+ parent_node->createChild("data", false)->createChild("type", true)->setStringValue(type);
+ }
+}
+
+LLXMLNodePtr LLRNGWriter::createCardinalityNode(LLXMLNodePtr parent_node, S32 min_count, S32 max_count)
+{
+ // unlinked by default, meaning this attribute is forbidden
+ LLXMLNodePtr count_node = new LLXMLNode();
+ if (min_count == 0)
+ {
+ if (max_count == 1)
+ {
+ count_node = parent_node->createChild("optional", false);
+ }
+ else if (max_count > 1)
+ {
+ count_node = parent_node->createChild("zeroOrMore", false);
+ }
+ }
+ else if (min_count >= 1)
+ {
+ if (max_count == 1 && min_count == 1)
+ {
+ // just add raw element, will count as 1 and only 1
+ count_node = parent_node;
+ }
+ else
+ {
+ count_node = parent_node->createChild("oneOrMore", false);
+ }
+ }
+ return count_node;
+}
diff --git a/indra/llui/llrngwriter.h b/indra/llui/llrngwriter.h
new file mode 100644
index 0000000000..66807577b5
--- /dev/null
+++ b/indra/llui/llrngwriter.h
@@ -0,0 +1,69 @@
+/**
+ * @file llrngwriter.h
+ * @brief Generates Relax NG schema files from a param block
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLRNGWRITER_H
+#define LLRNGWRITER_H
+
+#include "llinitparam.h"
+#include "llxmlnode.h"
+
+class LLRNGWriter : public LLInitParam::Parser
+{
+ LOG_CLASS(LLRNGWriter);
+public:
+ void writeRNG(const std::string& name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace);
+ void addDefinition(const std::string& type_name, const LLInitParam::BaseBlock& block);
+
+ /*virtual*/ std::string getCurrentElementName() { return LLStringUtil::null; }
+
+ LLRNGWriter();
+
+private:
+ LLXMLNodePtr createCardinalityNode(LLXMLNodePtr parent_node, S32 min_count, S32 max_count);
+ void addTypeNode(LLXMLNodePtr parent_node, const std::string& type, const std::vector<std::string>* possible_values);
+
+ void writeAttribute(const std::string& type, const Parser::name_stack_t&, S32 min_count, S32 max_count, const std::vector<std::string>* possible_values);
+ LLXMLNodePtr mElementNode;
+ LLXMLNodePtr mChildrenNode;
+ LLXMLNodePtr mGrammarNode;
+ std::string mDefinitionName;
+
+ typedef std::pair<LLXMLNodePtr, std::set<std::string> > attribute_data_t;
+ typedef std::map<std::string, attribute_data_t> elements_map_t;
+ typedef std::set<std::string> defined_elements_t;
+
+ defined_elements_t mDefinedElements;
+ attribute_data_t mAttributesWritten;
+ elements_map_t mElementsWritten;
+};
+
+#endif //LLRNGWRITER_H
diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp
index 65086d833d..dfd315d451 100644
--- a/indra/llui/llscrollbar.cpp
+++ b/indra/llui/llscrollbar.cpp
@@ -46,101 +46,92 @@
#include "llwindow.h"
#include "llcontrol.h"
#include "llrender.h"
+#include "lluictrlfactory.h"
+
+static LLDefaultChildRegistry::Register<LLScrollbar> register_scrollbar("scroll_bar");
+
+LLScrollbar::Params::Params()
+: orientation ("orientation", HORIZONTAL),
+ doc_size ("doc_size", 0),
+ doc_pos ("doc_pos", 0),
+ page_size ("page_size", 0),
+ step_size ("step_size", 1),
+ thumb_image_vertical("thumb_image_vertical"),
+ thumb_image_horizontal("thumb_image_horizontal"),
+ track_image_vertical("track_image_vertical"),
+ track_image_horizontal("track_image_horizontal"),
+ track_color("track_color"),
+ thumb_color("thumb_color"),
+ thickness("thickness"),
+ up_button("up_button"),
+ down_button("down_button"),
+ left_button("left_button"),
+ right_button("right_button"),
+ bg_visible("bg_visible", false),
+ bg_color("bg_color", LLColor4::black)
+{
+ tab_stop = false;
+}
-LLScrollbar::LLScrollbar(
- const std::string& name, LLRect rect,
- LLScrollbar::ORIENTATION orientation,
- S32 doc_size, S32 doc_pos, S32 page_size,
- void (*change_callback)( S32 new_pos, LLScrollbar* self, void* userdata ),
- void* callback_user_data,
- S32 step_size)
-: LLUICtrl( name, rect, TRUE, NULL, NULL ),
-
- mChangeCallback( change_callback ),
- mCallbackUserData( callback_user_data ),
- mOrientation( orientation ),
- mDocSize( doc_size ),
- mDocPos( doc_pos ),
- mPageSize( page_size ),
- mStepSize( step_size ),
+LLScrollbar::LLScrollbar(const Params & p)
+: LLUICtrl(p),
+ mChangeCallback( p.change_callback() ),
+ mOrientation( p.orientation ),
+ mDocSize( p.doc_size ),
+ mDocPos( p.doc_pos ),
+ mPageSize( p.page_size ),
+ mStepSize( p.step_size ),
mDocChanged(FALSE),
mDragStartX( 0 ),
mDragStartY( 0 ),
mHoverGlowStrength(0.15f),
mCurGlowStrength(0.f),
- mTrackColor( LLUI::sColorsGroup->getColor("ScrollbarTrackColor") ),
- mThumbColor ( LLUI::sColorsGroup->getColor("ScrollbarThumbColor") ),
- mHighlightColor ( LLUI::sColorsGroup->getColor("DefaultHighlightLight") ),
- mShadowColor ( LLUI::sColorsGroup->getColor("DefaultShadowLight") ),
- mOnScrollEndCallback( NULL ),
- mOnScrollEndData( NULL )
+ mTrackColor( p.track_color() ),
+ mThumbColor ( p.thumb_color() ),
+ mThumbImageV(p.thumb_image_vertical),
+ mThumbImageH(p.thumb_image_horizontal),
+ mTrackImageV(p.track_image_vertical),
+ mTrackImageH(p.track_image_horizontal),
+ mThickness(p.thickness.isProvided() ? p.thickness : LLUI::sSettingGroups["config"]->getS32("UIScrollbarSize")),
+ mBGVisible(p.bg_visible),
+ mBGColor(p.bg_color)
{
- //llassert( 0 <= mDocSize );
- //llassert( 0 <= mDocPos && mDocPos <= mDocSize );
-
- setTabStop(FALSE);
updateThumbRect();
// Page up and page down buttons
LLRect line_up_rect;
- std::string line_up_img;
- std::string line_up_selected_img;
- std::string line_down_img;
- std::string line_down_selected_img;
-
LLRect line_down_rect;
- if( LLScrollbar::VERTICAL == mOrientation )
+ if( VERTICAL == mOrientation )
{
- line_up_rect.setLeftTopAndSize( 0, getRect().getHeight(), SCROLLBAR_SIZE, SCROLLBAR_SIZE );
- line_up_img="UIImgBtnScrollUpOutUUID";
- line_up_selected_img="UIImgBtnScrollUpInUUID";
-
- line_down_rect.setOriginAndSize( 0, 0, SCROLLBAR_SIZE, SCROLLBAR_SIZE );
- line_down_img="UIImgBtnScrollDownOutUUID";
- line_down_selected_img="UIImgBtnScrollDownInUUID";
+ line_up_rect.setLeftTopAndSize( 0, getRect().getHeight(), mThickness, mThickness );
+ line_down_rect.setOriginAndSize( 0, 0, mThickness, mThickness );
}
- else
+ else // HORIZONTAL
{
- // Horizontal
- line_up_rect.setOriginAndSize( 0, 0, SCROLLBAR_SIZE, SCROLLBAR_SIZE );
- line_up_img="UIImgBtnScrollLeftOutUUID";
- line_up_selected_img="UIImgBtnScrollLeftInUUID";
-
- line_down_rect.setOriginAndSize( getRect().getWidth() - SCROLLBAR_SIZE, 0, SCROLLBAR_SIZE, SCROLLBAR_SIZE );
- line_down_img="UIImgBtnScrollRightOutUUID";
- line_down_selected_img="UIImgBtnScrollRightInUUID";
+ line_up_rect.setOriginAndSize( 0, 0, mThickness, mThickness );
+ line_down_rect.setOriginAndSize( getRect().getWidth() - mThickness, 0, mThickness, mThickness );
}
- LLButton* line_up_btn = new LLButton(std::string("Line Up"), line_up_rect,
- line_up_img, line_up_selected_img, LLStringUtil::null,
- &LLScrollbar::onLineUpBtnPressed, this, LLFontGL::getFontSansSerif() );
- if( LLScrollbar::VERTICAL == mOrientation )
- {
- line_up_btn->setFollowsRight();
- line_up_btn->setFollowsTop();
- }
- else
- {
- // horizontal
- line_up_btn->setFollowsLeft();
- line_up_btn->setFollowsBottom();
- }
- line_up_btn->setHeldDownCallback( &LLScrollbar::onLineUpBtnPressed );
- line_up_btn->setTabStop(FALSE);
- line_up_btn->setScaleImage(TRUE);
-
- addChild(line_up_btn);
-
- LLButton* line_down_btn = new LLButton(std::string("Line Down"), line_down_rect,
- line_down_img, line_down_selected_img, LLStringUtil::null,
- &LLScrollbar::onLineDownBtnPressed, this, LLFontGL::getFontSansSerif() );
- line_down_btn->setFollowsRight();
- line_down_btn->setFollowsBottom();
- line_down_btn->setHeldDownCallback( &LLScrollbar::onLineDownBtnPressed );
- line_down_btn->setTabStop(FALSE);
- line_down_btn->setScaleImage(TRUE);
- addChild(line_down_btn);
+ LLButton::Params up_btn(mOrientation == VERTICAL ? p.up_button : p.left_button);
+ up_btn.name(std::string("Line Up"));
+ up_btn.rect(line_up_rect);
+ up_btn.click_callback.function(boost::bind(&LLScrollbar::onLineUpBtnPressed, this, _2));
+ up_btn.mouse_held_callback.function(boost::bind(&LLScrollbar::onLineUpBtnPressed, this, _2));
+ up_btn.tab_stop(false);
+ up_btn.follows.flags = (mOrientation == VERTICAL ? (FOLLOWS_RIGHT | FOLLOWS_TOP) : (FOLLOWS_LEFT | FOLLOWS_BOTTOM));
+
+ addChild(LLUICtrlFactory::create<LLButton>(up_btn));
+
+ LLButton::Params down_btn(mOrientation == VERTICAL ? p.down_button : p.right_button);
+ down_btn.name(std::string("Line Down"));
+ down_btn.rect(line_down_rect);
+ down_btn.follows.flags(FOLLOWS_RIGHT|FOLLOWS_BOTTOM);
+ down_btn.click_callback.function(boost::bind(&LLScrollbar::onLineDownBtnPressed, this, _2));
+ down_btn.mouse_held_callback.function(boost::bind(&LLScrollbar::onLineDownBtnPressed, this, _2));
+ down_btn.tab_stop(false);
+
+ addChild(LLUICtrlFactory::create<LLButton>(down_btn));
}
@@ -158,7 +149,8 @@ void LLScrollbar::setDocParams( S32 size, S32 pos )
updateThumbRect();
}
-void LLScrollbar::setDocPos(S32 pos, BOOL update_thumb)
+// returns true if document position really changed
+bool LLScrollbar::setDocPos(S32 pos, BOOL update_thumb)
{
pos = llclamp(pos, 0, getDocPosMax());
if (pos != mDocPos)
@@ -168,14 +160,16 @@ void LLScrollbar::setDocPos(S32 pos, BOOL update_thumb)
if( mChangeCallback )
{
- mChangeCallback( mDocPos, this, mCallbackUserData );
+ mChangeCallback( mDocPos, this );
}
if( update_thumb )
{
updateThumbRect();
}
+ return true;
}
+ return false;
}
void LLScrollbar::setDocSize(S32 size)
@@ -221,7 +215,7 @@ void LLScrollbar::updateThumbRect()
const S32 THUMB_MIN_LENGTH = 16;
S32 window_length = (mOrientation == LLScrollbar::HORIZONTAL) ? getRect().getWidth() : getRect().getHeight();
- S32 thumb_bg_length = llmax(0, window_length - 2 * SCROLLBAR_SIZE);
+ S32 thumb_bg_length = llmax(0, window_length - 2 * mThickness);
S32 visible_lines = llmin( mDocSize, mPageSize );
S32 thumb_length = mDocSize ? llmin(llmax( visible_lines * thumb_bg_length / mDocSize, THUMB_MIN_LENGTH), thumb_bg_length) : thumb_bg_length;
@@ -229,32 +223,27 @@ void LLScrollbar::updateThumbRect()
if( mOrientation == LLScrollbar::VERTICAL )
{
- S32 thumb_start_max = thumb_bg_length + SCROLLBAR_SIZE;
- S32 thumb_start_min = SCROLLBAR_SIZE + THUMB_MIN_LENGTH;
+ S32 thumb_start_max = thumb_bg_length + mThickness;
+ S32 thumb_start_min = mThickness + THUMB_MIN_LENGTH;
S32 thumb_start = variable_lines ? llmin( llmax(thumb_start_max - (mDocPos * (thumb_bg_length - thumb_length)) / variable_lines, thumb_start_min), thumb_start_max ) : thumb_start_max;
mThumbRect.mLeft = 0;
mThumbRect.mTop = thumb_start;
- mThumbRect.mRight = SCROLLBAR_SIZE;
+ mThumbRect.mRight = mThickness;
mThumbRect.mBottom = thumb_start - thumb_length;
}
else
{
// Horizontal
- S32 thumb_start_max = thumb_bg_length + SCROLLBAR_SIZE - thumb_length;
- S32 thumb_start_min = SCROLLBAR_SIZE;
+ S32 thumb_start_max = thumb_bg_length + mThickness - thumb_length;
+ S32 thumb_start_min = mThickness;
S32 thumb_start = variable_lines ? llmin(llmax( thumb_start_min + (mDocPos * (thumb_bg_length - thumb_length)) / variable_lines, thumb_start_min), thumb_start_max ) : thumb_start_min;
mThumbRect.mLeft = thumb_start;
- mThumbRect.mTop = SCROLLBAR_SIZE;
+ mThumbRect.mTop = mThickness;
mThumbRect.mRight = thumb_start + thumb_length;
mThumbRect.mBottom = 0;
}
-
- if (mOnScrollEndCallback && mOnScrollEndData && (mDocPos == getDocPosMax()))
- {
- mOnScrollEndCallback(mOnScrollEndData);
- }
}
BOOL LLScrollbar::handleMouseDown(S32 x, S32 y, MASK mask)
@@ -318,21 +307,21 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask)
// S32 old_pos = mThumbRect.mTop;
S32 delta_pixels = y - mDragStartY;
- if( mOrigRect.mBottom + delta_pixels < SCROLLBAR_SIZE )
+ if( mOrigRect.mBottom + delta_pixels < mThickness )
{
- delta_pixels = SCROLLBAR_SIZE - mOrigRect.mBottom - 1;
+ delta_pixels = mThickness - mOrigRect.mBottom - 1;
}
else
- if( mOrigRect.mTop + delta_pixels > height - SCROLLBAR_SIZE )
+ if( mOrigRect.mTop + delta_pixels > height - mThickness )
{
- delta_pixels = height - SCROLLBAR_SIZE - mOrigRect.mTop + 1;
+ delta_pixels = height - mThickness - mOrigRect.mTop + 1;
}
mThumbRect.mTop = mOrigRect.mTop + delta_pixels;
mThumbRect.mBottom = mOrigRect.mBottom + delta_pixels;
S32 thumb_length = mThumbRect.getHeight();
- S32 thumb_track_length = height - 2 * SCROLLBAR_SIZE;
+ S32 thumb_track_length = height - 2 * mThickness;
if( delta_pixels != mLastDelta || mDocChanged)
@@ -343,7 +332,7 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask)
{
S32 variable_lines = getDocPosMax();
S32 pos = mThumbRect.mTop;
- F32 ratio = F32(pos - SCROLLBAR_SIZE - thumb_length) / usable_track_length;
+ F32 ratio = F32(pos - mThickness - thumb_length) / usable_track_length;
S32 new_pos = llclamp( S32(variable_lines - ratio * variable_lines + 0.5f), 0, variable_lines );
// Note: we do not call updateThumbRect() here. Instead we let the thumb and the document go slightly
@@ -362,21 +351,21 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask)
S32 delta_pixels = x - mDragStartX;
- if( mOrigRect.mLeft + delta_pixels < SCROLLBAR_SIZE )
+ if( mOrigRect.mLeft + delta_pixels < mThickness )
{
- delta_pixels = SCROLLBAR_SIZE - mOrigRect.mLeft - 1;
+ delta_pixels = mThickness - mOrigRect.mLeft - 1;
}
else
- if( mOrigRect.mRight + delta_pixels > width - SCROLLBAR_SIZE )
+ if( mOrigRect.mRight + delta_pixels > width - mThickness )
{
- delta_pixels = width - SCROLLBAR_SIZE - mOrigRect.mRight + 1;
+ delta_pixels = width - mThickness - mOrigRect.mRight + 1;
}
mThumbRect.mLeft = mOrigRect.mLeft + delta_pixels;
mThumbRect.mRight = mOrigRect.mRight + delta_pixels;
S32 thumb_length = mThumbRect.getWidth();
- S32 thumb_track_length = width - 2 * SCROLLBAR_SIZE;
+ S32 thumb_track_length = width - 2 * mThickness;
if( delta_pixels != mLastDelta || mDocChanged)
{
@@ -386,7 +375,7 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask)
{
S32 variable_lines = getDocPosMax();
S32 pos = mThumbRect.mLeft;
- F32 ratio = F32(pos - SCROLLBAR_SIZE) / usable_track_length;
+ F32 ratio = F32(pos - mThickness) / usable_track_length;
S32 new_pos = llclamp( S32(ratio * variable_lines + 0.5f), 0, variable_lines);
@@ -405,7 +394,7 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask)
}
else
{
- handled = childrenHandleMouseUp( x, y, mask ) != NULL;
+ handled = childrenHandleHover( x, y, mask ) != NULL;
}
// Opaque
@@ -423,8 +412,8 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask)
BOOL LLScrollbar::handleScrollWheel(S32 x, S32 y, S32 clicks)
{
- changeLine( clicks * mStepSize, TRUE );
- return TRUE;
+ BOOL handled = changeLine( clicks * mStepSize, TRUE );
+ return handled;
}
BOOL LLScrollbar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
@@ -466,6 +455,13 @@ BOOL LLScrollbar::handleMouseUp(S32 x, S32 y, MASK mask)
return handled;
}
+BOOL LLScrollbar::handleDoubleClick(S32 x, S32 y, MASK mask)
+{
+ // just treat a double click as a second click
+ return handleMouseDown(x, y, mask);
+}
+
+
void LLScrollbar::reshape(S32 width, S32 height, BOOL called_from_parent)
{
if (width == getRect().getWidth() && height == getRect().getHeight()) return;
@@ -475,14 +471,14 @@ void LLScrollbar::reshape(S32 width, S32 height, BOOL called_from_parent)
if (mOrientation == VERTICAL)
{
- up_button->reshape(up_button->getRect().getWidth(), llmin(getRect().getHeight() / 2, SCROLLBAR_SIZE));
- down_button->reshape(down_button->getRect().getWidth(), llmin(getRect().getHeight() / 2, SCROLLBAR_SIZE));
+ up_button->reshape(up_button->getRect().getWidth(), llmin(getRect().getHeight() / 2, mThickness));
+ down_button->reshape(down_button->getRect().getWidth(), llmin(getRect().getHeight() / 2, mThickness));
up_button->setOrigin(up_button->getRect().mLeft, getRect().getHeight() - up_button->getRect().getHeight());
}
else
{
- up_button->reshape(llmin(getRect().getWidth() / 2, SCROLLBAR_SIZE), up_button->getRect().getHeight());
- down_button->reshape(llmin(getRect().getWidth() / 2, SCROLLBAR_SIZE), down_button->getRect().getHeight());
+ up_button->reshape(llmin(getRect().getWidth() / 2, mThickness), up_button->getRect().getHeight());
+ down_button->reshape(llmin(getRect().getWidth() / 2, mThickness), down_button->getRect().getHeight());
down_button->setOrigin(getRect().getWidth() - down_button->getRect().getWidth(), down_button->getRect().mBottom);
}
updateThumbRect();
@@ -493,9 +489,14 @@ void LLScrollbar::draw()
{
if (!getRect().isValid()) return;
+ if(mBGVisible)
+ {
+ gl_rect_2d(getLocalRect(), mBGColor.get(), TRUE);
+ }
+
S32 local_mouse_x;
S32 local_mouse_y;
- LLUI::getCursorPositionLocal(this, &local_mouse_x, &local_mouse_y);
+ LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y);
BOOL other_captor = gFocusMgr.getMouseCapture() && gFocusMgr.getMouseCapture() != this;
BOOL hovered = getEnabled() && !other_captor && (hasMouseCapture() || mThumbRect.pointInRect(local_mouse_x, local_mouse_y));
if (hovered)
@@ -507,52 +508,67 @@ void LLScrollbar::draw()
mCurGlowStrength = lerp(mCurGlowStrength, 0.f, LLCriticalDamp::getInterpolant(0.05f));
}
-
// Draw background and thumb.
- LLUIImage* rounded_rect_imagep = LLUI::sImageProvider->getUIImage("rounded_square.tga");
-
- if (!rounded_rect_imagep)
+ if ( ( mOrientation == VERTICAL&&(mThumbImageV.isNull() || mThumbImageH.isNull()) )
+ || (mOrientation == HORIZONTAL&&(mTrackImageH.isNull() || mTrackImageV.isNull()) ))
{
- gl_rect_2d(mOrientation == HORIZONTAL ? SCROLLBAR_SIZE : 0,
- mOrientation == VERTICAL ? getRect().getHeight() - 2 * SCROLLBAR_SIZE : getRect().getHeight(),
- mOrientation == HORIZONTAL ? getRect().getWidth() - 2 * SCROLLBAR_SIZE : getRect().getWidth(),
- mOrientation == VERTICAL ? SCROLLBAR_SIZE : 0, mTrackColor, TRUE);
+ gl_rect_2d(mOrientation == HORIZONTAL ? mThickness : 0,
+ mOrientation == VERTICAL ? getRect().getHeight() - 2 * mThickness : getRect().getHeight(),
+ mOrientation == HORIZONTAL ? getRect().getWidth() - 2 * mThickness : getRect().getWidth(),
+ mOrientation == VERTICAL ? mThickness : 0, mTrackColor.get(), TRUE);
- gl_rect_2d(mThumbRect, mThumbColor, TRUE);
+ gl_rect_2d(mThumbRect, mThumbColor.get(), TRUE);
}
else
{
- // Background
- rounded_rect_imagep->drawSolid(mOrientation == HORIZONTAL ? SCROLLBAR_SIZE : 0,
- mOrientation == VERTICAL ? SCROLLBAR_SIZE : 0,
- mOrientation == HORIZONTAL ? getRect().getWidth() - 2 * SCROLLBAR_SIZE : getRect().getWidth(),
- mOrientation == VERTICAL ? getRect().getHeight() - 2 * SCROLLBAR_SIZE : getRect().getHeight(),
- mTrackColor);
-
// Thumb
LLRect outline_rect = mThumbRect;
outline_rect.stretch(2);
-
- if (gFocusMgr.getKeyboardFocus() == this)
+ // Background
+
+ if(mOrientation == HORIZONTAL)
{
- rounded_rect_imagep->draw(outline_rect, gFocusMgr.getFocusColor());
+ mTrackImageH->drawSolid(mThickness //S32 x
+ , 0 //S32 y
+ , getRect().getWidth() - 2 * mThickness //S32 width
+ , getRect().getHeight() //S32 height
+ , mTrackColor.get()); //const LLColor4& color
+
+ if (gFocusMgr.getKeyboardFocus() == this)
+ {
+ mTrackImageH->draw(outline_rect, gFocusMgr.getFocusColor());
+ }
+
+ mThumbImageH->draw(mThumbRect, mThumbColor.get());
+ if (mCurGlowStrength > 0.01f)
+ {
+ gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
+ mThumbImageH->drawSolid(mThumbRect, LLColor4(1.f, 1.f, 1.f, mCurGlowStrength));
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ }
+
}
-
- rounded_rect_imagep->draw(mThumbRect, mThumbColor);
- if (mCurGlowStrength > 0.01f)
+ else if(mOrientation == VERTICAL)
{
- gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
- rounded_rect_imagep->drawSolid(mThumbRect, LLColor4(1.f, 1.f, 1.f, mCurGlowStrength));
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ mTrackImageV->drawSolid( 0 //S32 x
+ , mThickness //S32 y
+ , getRect().getWidth() //S32 width
+ , getRect().getHeight() - 2 * mThickness //S32 height
+ , mTrackColor.get()); //const LLColor4& color
+ if (gFocusMgr.getKeyboardFocus() == this)
+ {
+ mTrackImageV->draw(outline_rect, gFocusMgr.getFocusColor());
+ }
+
+ mThumbImageV->draw(mThumbRect, mThumbColor.get());
+ if (mCurGlowStrength > 0.01f)
+ {
+ gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
+ mThumbImageV->drawSolid(mThumbRect, LLColor4(1.f, 1.f, 1.f, mCurGlowStrength));
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ }
}
-
- }
-
- BOOL was_scrolled_to_bottom = (getDocPos() == getDocPosMax());
- if (mOnScrollEndCallback && was_scrolled_to_bottom)
- {
- mOnScrollEndCallback(mOnScrollEndData);
}
// Draw children
@@ -560,9 +576,9 @@ void LLScrollbar::draw()
} // end draw
-void LLScrollbar::changeLine( S32 delta, BOOL update_thumb )
+bool LLScrollbar::changeLine( S32 delta, BOOL update_thumb )
{
- setDocPos(mDocPos + delta, update_thumb);
+ return setDocPos(mDocPos + delta, update_thumb);
}
void LLScrollbar::setValue(const LLSD& value)
@@ -625,19 +641,12 @@ void LLScrollbar::pageDown(S32 overlap)
}
}
-// static
-void LLScrollbar::onLineUpBtnPressed( void* userdata )
+void LLScrollbar::onLineUpBtnPressed( const LLSD& data )
{
- LLScrollbar* self = (LLScrollbar*) userdata;
-
- self->changeLine( - self->mStepSize, TRUE );
+ changeLine( -mStepSize, TRUE );
}
-// static
-void LLScrollbar::onLineDownBtnPressed( void* userdata )
+void LLScrollbar::onLineDownBtnPressed( const LLSD& data )
{
- LLScrollbar* self = (LLScrollbar*) userdata;
- self->changeLine( self->mStepSize, TRUE );
+ changeLine( mStepSize, TRUE );
}
-
-
diff --git a/indra/llui/llscrollbar.h b/indra/llui/llscrollbar.h
index 0bbf8662aa..a9f028f9ae 100644
--- a/indra/llui/llscrollbar.h
+++ b/indra/llui/llscrollbar.h
@@ -36,12 +36,7 @@
#include "stdtypes.h"
#include "lluictrl.h"
#include "v4color.h"
-
-//
-// Constants
-//
-const S32 SCROLLBAR_SIZE = 16;
-
+#include "llbutton.h"
//
// Classes
@@ -50,15 +45,46 @@ class LLScrollbar
: public LLUICtrl
{
public:
- enum ORIENTATION { HORIZONTAL, VERTICAL };
- LLScrollbar(const std::string& name, LLRect rect,
- ORIENTATION orientation,
- S32 doc_size, S32 doc_pos, S32 page_size,
- void(*change_callback)( S32 new_pos, LLScrollbar* self, void* userdata ),
- void* callback_user_data = NULL,
- S32 step_size = 1);
+ enum ORIENTATION { HORIZONTAL, VERTICAL };
+
+ typedef boost::function<void (S32, LLScrollbar*)> callback_t;
+ struct Params
+ : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Mandatory<ORIENTATION> orientation;
+ Mandatory<S32> doc_size;
+ Mandatory<S32> doc_pos;
+ Mandatory<S32> page_size;
+
+ Optional<callback_t> change_callback;
+ Optional<S32> step_size;
+ Optional<S32> thickness;
+
+ Optional<LLUIImage*> thumb_image_vertical,
+ thumb_image_horizontal,
+ track_image_horizontal,
+ track_image_vertical;
+
+ Optional<bool> bg_visible;
+
+ Optional<LLUIColor> track_color,
+ thumb_color,
+ bg_color;
+
+ Optional<LLButton::Params> up_button;
+ Optional<LLButton::Params> down_button;
+ Optional<LLButton::Params> left_button;
+ Optional<LLButton::Params> right_button;
+
+ Params();
+ };
+
+protected:
+ LLScrollbar (const Params & p);
+ friend class LLUICtrlFactory;
+public:
virtual ~LLScrollbar();
virtual void setValue(const LLSD& value);
@@ -67,6 +93,7 @@ public:
virtual BOOL handleKeyHere(KEY key, MASK mask);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
@@ -82,7 +109,7 @@ public:
// How many "lines" the "document" has scrolled.
// 0 <= DocPos <= DocSize - DocVisibile
- void setDocPos( S32 pos, BOOL update_thumb = TRUE );
+ bool setDocPos( S32 pos, BOOL update_thumb = TRUE );
S32 getDocPos() const { return mDocPos; }
BOOL isAtBeginning();
@@ -101,22 +128,14 @@ public:
void pageUp(S32 overlap);
void pageDown(S32 overlap);
- static void onLineUpBtnPressed(void* userdata);
- static void onLineDownBtnPressed(void* userdata);
-
- void setTrackColor( const LLColor4& color ) { mTrackColor = color; }
- void setThumbColor( const LLColor4& color ) { mThumbColor = color; }
- void setHighlightColor( const LLColor4& color ) { mHighlightColor = color; }
- void setShadowColor( const LLColor4& color ) { mShadowColor = color; }
-
- void setOnScrollEndCallback(void (*callback)(void*), void* userdata) { mOnScrollEndCallback = callback; mOnScrollEndData = userdata;}
+ void onLineUpBtnPressed(const LLSD& data);
+ void onLineDownBtnPressed(const LLSD& data);
private:
void updateThumbRect();
- void changeLine(S32 delta, BOOL update_thumb );
+ bool changeLine(S32 delta, BOOL update_thumb );
- void (*mChangeCallback)( S32 new_pos, LLScrollbar* self, void* userdata );
- void* mCallbackUserData;
+ callback_t mChangeCallback;
const ORIENTATION mOrientation;
S32 mDocSize; // Size of the document that the scrollbar is modeling. Units depend on the user. 0 <= mDocSize.
@@ -134,16 +153,19 @@ private:
LLRect mOrigRect;
S32 mLastDelta;
- LLColor4 mTrackColor;
- LLColor4 mThumbColor;
- LLColor4 mFocusColor;
- LLColor4 mHighlightColor;
- LLColor4 mShadowColor;
+ LLUIColor mTrackColor;
+ LLUIColor mThumbColor;
+ LLUIColor mBGColor;
- void (*mOnScrollEndCallback)(void*);
- void *mOnScrollEndData;
-};
+ bool mBGVisible;
+
+ LLUIImagePtr mThumbImageV;
+ LLUIImagePtr mThumbImageH;
+ LLUIImagePtr mTrackImageV;
+ LLUIImagePtr mTrackImageH;
+ S32 mThickness;
+};
#endif // LL_SCROLLBAR_H
diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp
index cf03259879..94465a67ce 100644
--- a/indra/llui/llscrollcontainer.cpp
+++ b/indra/llui/llscrollcontainer.cpp
@@ -1,6 +1,6 @@
/**
* @file llscrollcontainer.cpp
- * @brief LLScrollableContainerView base class
+ * @brief LLScrollContainer base class
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
@@ -33,8 +33,13 @@
#include "linden_common.h"
-#include "llrender.h"
#include "llscrollcontainer.h"
+
+#include "llrender.h"
+#include "llcontainerview.h"
+#include "lllocalcliprect.h"
+// #include "llfolderview.h"
+#include "llscrollingpanellist.h"
#include "llscrollbar.h"
#include "llui.h"
#include "llkeyboard.h"
@@ -42,6 +47,7 @@
#include "llfocusmgr.h"
#include "llframetimer.h"
#include "lluictrlfactory.h"
+#include "llpanel.h"
#include "llfontgl.h"
///----------------------------------------------------------------------------
@@ -50,103 +56,97 @@
static const S32 HORIZONTAL_MULTIPLE = 8;
static const S32 VERTICAL_MULTIPLE = 16;
-static const F32 MIN_AUTO_SCROLL_RATE = 120.f;
-static const F32 MAX_AUTO_SCROLL_RATE = 500.f;
static const F32 AUTO_SCROLL_RATE_ACCEL = 120.f;
///----------------------------------------------------------------------------
-/// Class LLScrollableContainerView
+/// Class LLScrollContainer
///----------------------------------------------------------------------------
-static LLRegisterWidget<LLScrollableContainerView> r("scroll_container");
+static LLDefaultChildRegistry::Register<LLScrollContainer> r("scroll_container");
-// Default constructor
-LLScrollableContainerView::LLScrollableContainerView( const std::string& name,
- const LLRect& rect,
- LLView* scrolled_view,
- BOOL is_opaque,
- const LLColor4& bg_color ) :
- LLUICtrl( name, rect, FALSE, NULL, NULL ),
- mScrolledView( scrolled_view ),
- mIsOpaque( is_opaque ),
- mBackgroundColor( bg_color ),
- mReserveScrollCorner( FALSE ),
- mAutoScrolling( FALSE ),
- mAutoScrollRate( 0.f )
-{
- if( mScrolledView )
- {
- addChild( mScrolledView );
- }
+#include "llscrollingpanellist.h"
+#include "llcontainerview.h"
+#include "llpanel.h"
- init();
-}
+static ScrollContainerRegistry::Register<LLScrollingPanelList> r1("scrolling_panel_list");
+static ScrollContainerRegistry::Register<LLContainerView> r2("container_view");
+static ScrollContainerRegistry::Register<LLPanel> r3("panel", &LLPanel::fromXML);
-// LLUICtrl constructor
-LLScrollableContainerView::LLScrollableContainerView( const std::string& name, const LLRect& rect,
- LLUICtrl* scrolled_ctrl, BOOL is_opaque,
- const LLColor4& bg_color) :
- LLUICtrl( name, rect, FALSE, NULL, NULL ),
- mScrolledView( scrolled_ctrl ),
- mIsOpaque( is_opaque ),
- mBackgroundColor( bg_color ),
- mReserveScrollCorner( FALSE ),
- mAutoScrolling( FALSE ),
- mAutoScrollRate( 0.f )
+LLScrollContainer::Params::Params()
+: is_opaque("opaque"),
+ bg_color("color"),
+ border_visible("border_visible"),
+ hide_scrollbar("hide_scrollbar"),
+ min_auto_scroll_rate("min_auto_scroll_rate", 100),
+ max_auto_scroll_rate("max_auto_scroll_rate", 1000),
+ reserve_scroll_corner("reserve_scroll_corner", false)
{
- if( scrolled_ctrl )
- {
- addChild( scrolled_ctrl );
- }
-
- init();
+ name = "scroll_container";
+ mouse_opaque(true);
+ tab_stop(false);
}
-void LLScrollableContainerView::init()
+
+// Default constructor
+LLScrollContainer::LLScrollContainer(const LLScrollContainer::Params& p)
+: LLUICtrl(p),
+ mAutoScrolling( FALSE ),
+ mAutoScrollRate( 0.f ),
+ mBackgroundColor(p.bg_color()),
+ mIsOpaque(p.is_opaque),
+ mHideScrollbar(p.hide_scrollbar),
+ mReserveScrollCorner(p.reserve_scroll_corner),
+ mMinAutoScrollRate(p.min_auto_scroll_rate),
+ mMaxAutoScrollRate(p.max_auto_scroll_rate),
+ mScrolledView(NULL)
{
+ static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
LLRect border_rect( 0, getRect().getHeight(), getRect().getWidth(), 0 );
- mBorder = new LLViewBorder( std::string("scroll border"), border_rect, LLViewBorder::BEVEL_IN );
- addChild( mBorder );
+ LLViewBorder::Params params;
+ params.name("scroll border");
+ params.rect(border_rect);
+ params.visible(p.border_visible);
+ params.bevel_style(LLViewBorder::BEVEL_IN);
+ mBorder = LLUICtrlFactory::create<LLViewBorder> (params);
+ LLView::addChild( mBorder );
mInnerRect.set( 0, getRect().getHeight(), getRect().getWidth(), 0 );
- mInnerRect.stretch( -mBorder->getBorderWidth() );
+ mInnerRect.stretch( -getBorderWidth() );
LLRect vertical_scroll_rect = mInnerRect;
- vertical_scroll_rect.mLeft = vertical_scroll_rect.mRight - SCROLLBAR_SIZE;
- mScrollbar[VERTICAL] = new LLScrollbar( std::string("scrollable vertical"),
- vertical_scroll_rect,
- LLScrollbar::VERTICAL,
- mInnerRect.getHeight(),
- 0,
- mInnerRect.getHeight(),
- NULL, this,
- VERTICAL_MULTIPLE);
- addChild( mScrollbar[VERTICAL] );
- mScrollbar[VERTICAL]->setVisible( FALSE );
- mScrollbar[VERTICAL]->setFollowsRight();
- mScrollbar[VERTICAL]->setFollowsTop();
- mScrollbar[VERTICAL]->setFollowsBottom();
+ vertical_scroll_rect.mLeft = vertical_scroll_rect.mRight - scrollbar_size;
+ LLScrollbar::Params sbparams;
+ sbparams.name("scrollable vertical");
+ sbparams.rect(vertical_scroll_rect);
+ sbparams.orientation(LLScrollbar::VERTICAL);
+ sbparams.doc_size(mInnerRect.getHeight());
+ sbparams.doc_pos(0);
+ sbparams.page_size(mInnerRect.getHeight());
+ sbparams.step_size(VERTICAL_MULTIPLE);
+ sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
+ sbparams.visible(false);
+ sbparams.change_callback(p.scroll_callback);
+ mScrollbar[VERTICAL] = LLUICtrlFactory::create<LLScrollbar> (sbparams);
+ LLView::addChild( mScrollbar[VERTICAL] );
LLRect horizontal_scroll_rect = mInnerRect;
- horizontal_scroll_rect.mTop = horizontal_scroll_rect.mBottom + SCROLLBAR_SIZE;
- mScrollbar[HORIZONTAL] = new LLScrollbar( std::string("scrollable horizontal"),
- horizontal_scroll_rect,
- LLScrollbar::HORIZONTAL,
- mInnerRect.getWidth(),
- 0,
- mInnerRect.getWidth(),
- NULL, this,
- HORIZONTAL_MULTIPLE);
- addChild( mScrollbar[HORIZONTAL] );
- mScrollbar[HORIZONTAL]->setVisible( FALSE );
- mScrollbar[HORIZONTAL]->setFollowsLeft();
- mScrollbar[HORIZONTAL]->setFollowsRight();
-
- setTabStop(FALSE);
+ horizontal_scroll_rect.mTop = horizontal_scroll_rect.mBottom + scrollbar_size;
+ sbparams.name("scrollable horizontal");
+ sbparams.rect(horizontal_scroll_rect);
+ sbparams.orientation(LLScrollbar::HORIZONTAL);
+ sbparams.doc_size(mInnerRect.getWidth());
+ sbparams.doc_pos(0);
+ sbparams.page_size(mInnerRect.getWidth());
+ sbparams.step_size(VERTICAL_MULTIPLE);
+ sbparams.visible(false);
+ sbparams.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT);
+ sbparams.change_callback(p.scroll_callback);
+ mScrollbar[HORIZONTAL] = LLUICtrlFactory::create<LLScrollbar> (sbparams);
+ LLView::addChild( mScrollbar[HORIZONTAL] );
}
// Destroys the object
-LLScrollableContainerView::~LLScrollableContainerView( void )
+LLScrollContainer::~LLScrollContainer( void )
{
// mScrolledView and mScrollbar are child views, so the LLView
// destructor takes care of memory deallocation.
@@ -159,9 +159,9 @@ LLScrollableContainerView::~LLScrollableContainerView( void )
// internal scrollbar handlers
// virtual
-void LLScrollableContainerView::scrollHorizontal( S32 new_pos )
+void LLScrollContainer::scrollHorizontal( S32 new_pos )
{
- //llinfos << "LLScrollableContainerView::scrollHorizontal()" << llendl;
+ //llinfos << "LLScrollContainer::scrollHorizontal()" << llendl;
if( mScrolledView )
{
LLRect doc_rect = mScrolledView->getRect();
@@ -171,9 +171,9 @@ void LLScrollableContainerView::scrollHorizontal( S32 new_pos )
}
// virtual
-void LLScrollableContainerView::scrollVertical( S32 new_pos )
+void LLScrollContainer::scrollVertical( S32 new_pos )
{
- // llinfos << "LLScrollableContainerView::scrollVertical() " << new_pos << llendl;
+ // llinfos << "LLScrollContainer::scrollVertical() " << new_pos << llendl;
if( mScrolledView )
{
LLRect doc_rect = mScrolledView->getRect();
@@ -183,13 +183,13 @@ void LLScrollableContainerView::scrollVertical( S32 new_pos )
}
// LLView functionality
-void LLScrollableContainerView::reshape(S32 width, S32 height,
+void LLScrollContainer::reshape(S32 width, S32 height,
BOOL called_from_parent)
{
LLUICtrl::reshape( width, height, called_from_parent );
- mInnerRect.set( 0, getRect().getHeight(), getRect().getWidth(), 0 );
- mInnerRect.stretch( -mBorder->getBorderWidth() );
+ mInnerRect = getLocalRect();
+ mInnerRect.stretch( -getBorderWidth() );
if (mScrolledView)
{
@@ -199,22 +199,33 @@ void LLScrollableContainerView::reshape(S32 width, S32 height,
S32 visible_height = 0;
BOOL show_v_scrollbar = FALSE;
BOOL show_h_scrollbar = FALSE;
- calcVisibleSize( scrolled_rect, &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar );
+ calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar );
mScrollbar[VERTICAL]->setDocSize( scrolled_rect.getHeight() );
mScrollbar[VERTICAL]->setPageSize( visible_height );
mScrollbar[HORIZONTAL]->setDocSize( scrolled_rect.getWidth() );
mScrollbar[HORIZONTAL]->setPageSize( visible_width );
+ updateScroll();
}
}
-BOOL LLScrollableContainerView::handleKeyHere(KEY key, MASK mask)
+BOOL LLScrollContainer::handleKeyHere(KEY key, MASK mask)
{
+ // allow scrolled view to handle keystrokes in case it delegated keyboard focus
+ // to the scroll container.
+ // NOTE: this should not recurse indefinitely as handleKeyHere
+ // should not propagate to parent controls, so mScrolledView should *not*
+ // call LLScrollContainer::handleKeyHere in turn
+ if (mScrolledView && mScrolledView->handleKeyHere(key, mask))
+ {
+ return TRUE;
+ }
for( S32 i = 0; i < SCROLLBAR_COUNT; i++ )
{
if( mScrollbar[i]->handleKeyHere(key, mask) )
{
+ updateScroll();
return TRUE;
}
}
@@ -222,203 +233,194 @@ BOOL LLScrollableContainerView::handleKeyHere(KEY key, MASK mask)
return FALSE;
}
-BOOL LLScrollableContainerView::handleScrollWheel( S32 x, S32 y, S32 clicks )
+BOOL LLScrollContainer::handleScrollWheel( S32 x, S32 y, S32 clicks )
{
- for( S32 i = 0; i < SCROLLBAR_COUNT; i++ )
+ // Give event to my child views - they may have scroll bars
+ // (Bad UI design, but technically possible.)
+ if (LLUICtrl::handleScrollWheel(x,y,clicks))
+ return TRUE;
+
+ // When the vertical scrollbar is visible, scroll wheel
+ // only affects vertical scrolling. It's confusing to have
+ // scroll wheel perform both vertical and horizontal in a
+ // single container.
+ LLScrollbar* vertical = mScrollbar[VERTICAL];
+ if (vertical->getVisible()
+ && vertical->getEnabled())
{
- // Note: tries vertical and then horizontal
-
// Pretend the mouse is over the scrollbar
- if( mScrollbar[i]->handleScrollWheel( 0, 0, clicks ) )
+ if (vertical->handleScrollWheel( 0, 0, clicks ) )
{
- return TRUE;
+ updateScroll();
}
+ // Always eat the event
+ return TRUE;
}
- // Eat scroll wheel event (to avoid scrolling nested containers?)
- return TRUE;
-}
-
-BOOL LLScrollableContainerView::needsToScroll(S32 x, S32 y, LLScrollableContainerView::SCROLL_ORIENTATION axis) const
-{
- if(mScrollbar[axis]->getVisible())
+ LLScrollbar* horizontal = mScrollbar[HORIZONTAL];
+ // Test enablement and visibility for consistency with
+ // LLView::childrenHandleScrollWheel().
+ if (horizontal->getVisible()
+ && horizontal->getEnabled()
+ && horizontal->handleScrollWheel( 0, 0, clicks ) )
{
- LLRect inner_rect_local( 0, mInnerRect.getHeight(), mInnerRect.getWidth(), 0 );
- const S32 AUTOSCROLL_SIZE = 10;
- if(mScrollbar[axis]->getVisible())
- {
- inner_rect_local.mRight -= SCROLLBAR_SIZE;
- inner_rect_local.mTop += AUTOSCROLL_SIZE;
- inner_rect_local.mBottom = inner_rect_local.mTop - AUTOSCROLL_SIZE;
- }
- if( inner_rect_local.pointInRect( x, y ) && (mScrollbar[axis]->getDocPos() > 0) )
- {
- return TRUE;
- }
-
+ updateScroll();
+ return TRUE;
}
return FALSE;
}
-BOOL LLScrollableContainerView::handleDragAndDrop(S32 x, S32 y, MASK mask,
+BOOL LLScrollContainer::handleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg)
{
+ static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
// Scroll folder view if needed. Never accepts a drag or drop.
*accept = ACCEPT_NO;
- BOOL handled = FALSE;
+ BOOL handled = autoScroll(x, y);
+
+ if( !handled )
+ {
+ handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type,
+ cargo_data, accept, tooltip_msg) != NULL;
+ }
+
+ return TRUE;
+}
+
+bool LLScrollContainer::autoScroll(S32 x, S32 y)
+{
+ static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+
+ bool scrolling = false;
if( mScrollbar[HORIZONTAL]->getVisible() || mScrollbar[VERTICAL]->getVisible() )
{
- const S32 AUTOSCROLL_SIZE = 10;
- S32 auto_scroll_speed = llround(mAutoScrollRate * LLFrameTimer::getFrameDeltaTimeF32());
-
+ LLRect screen_local_extents;
+ screenRectToLocal(getRootView()->getLocalRect(), &screen_local_extents);
+
LLRect inner_rect_local( 0, mInnerRect.getHeight(), mInnerRect.getWidth(), 0 );
if( mScrollbar[HORIZONTAL]->getVisible() )
{
- inner_rect_local.mBottom += SCROLLBAR_SIZE;
+ inner_rect_local.mBottom += scrollbar_size;
}
if( mScrollbar[VERTICAL]->getVisible() )
{
- inner_rect_local.mRight -= SCROLLBAR_SIZE;
+ inner_rect_local.mRight -= scrollbar_size;
}
+ // clip rect against root view
+ inner_rect_local.intersectWith(screen_local_extents);
+
+ S32 auto_scroll_speed = llround(mAutoScrollRate * LLFrameTimer::getFrameDeltaTimeF32());
+ // autoscroll region should take up no more than one third of visible scroller area
+ S32 auto_scroll_region_width = llmin(inner_rect_local.getWidth() / 3, 10);
+ S32 auto_scroll_region_height = llmin(inner_rect_local.getHeight() / 3, 10);
+
if( mScrollbar[HORIZONTAL]->getVisible() )
{
- LLRect left_scroll_rect = inner_rect_local;
- left_scroll_rect.mRight = AUTOSCROLL_SIZE;
+ LLRect left_scroll_rect = screen_local_extents;
+ left_scroll_rect.mRight = inner_rect_local.mLeft + auto_scroll_region_width;
if( left_scroll_rect.pointInRect( x, y ) && (mScrollbar[HORIZONTAL]->getDocPos() > 0) )
{
mScrollbar[HORIZONTAL]->setDocPos( mScrollbar[HORIZONTAL]->getDocPos() - auto_scroll_speed );
mAutoScrolling = TRUE;
- handled = TRUE;
+ scrolling = true;
}
- LLRect right_scroll_rect = inner_rect_local;
- right_scroll_rect.mLeft = inner_rect_local.mRight - AUTOSCROLL_SIZE;
+ LLRect right_scroll_rect = screen_local_extents;
+ right_scroll_rect.mLeft = inner_rect_local.mRight - auto_scroll_region_width;
if( right_scroll_rect.pointInRect( x, y ) && (mScrollbar[HORIZONTAL]->getDocPos() < mScrollbar[HORIZONTAL]->getDocPosMax()) )
{
mScrollbar[HORIZONTAL]->setDocPos( mScrollbar[HORIZONTAL]->getDocPos() + auto_scroll_speed );
mAutoScrolling = TRUE;
- handled = TRUE;
+ scrolling = true;
}
}
if( mScrollbar[VERTICAL]->getVisible() )
{
- LLRect bottom_scroll_rect = inner_rect_local;
- bottom_scroll_rect.mTop = AUTOSCROLL_SIZE + bottom_scroll_rect.mBottom;
+ LLRect bottom_scroll_rect = screen_local_extents;
+ bottom_scroll_rect.mTop = inner_rect_local.mBottom + auto_scroll_region_height;
if( bottom_scroll_rect.pointInRect( x, y ) && (mScrollbar[VERTICAL]->getDocPos() < mScrollbar[VERTICAL]->getDocPosMax()) )
{
mScrollbar[VERTICAL]->setDocPos( mScrollbar[VERTICAL]->getDocPos() + auto_scroll_speed );
mAutoScrolling = TRUE;
- handled = TRUE;
+ scrolling = true;
}
- LLRect top_scroll_rect = inner_rect_local;
- top_scroll_rect.mBottom = inner_rect_local.mTop - AUTOSCROLL_SIZE;
+ LLRect top_scroll_rect = screen_local_extents;
+ top_scroll_rect.mBottom = inner_rect_local.mTop - auto_scroll_region_height;
if( top_scroll_rect.pointInRect( x, y ) && (mScrollbar[VERTICAL]->getDocPos() > 0) )
{
mScrollbar[VERTICAL]->setDocPos( mScrollbar[VERTICAL]->getDocPos() - auto_scroll_speed );
mAutoScrolling = TRUE;
- handled = TRUE;
+ scrolling = true;
}
}
}
-
- if( !handled )
- {
- handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type,
- cargo_data, accept, tooltip_msg) != NULL;
- }
-
- return TRUE;
-}
-
-
-BOOL LLScrollableContainerView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect)
-{
- S32 local_x, local_y;
- for( S32 i = 0; i < SCROLLBAR_COUNT; i++ )
- {
- local_x = x - mScrollbar[i]->getRect().mLeft;
- local_y = y - mScrollbar[i]->getRect().mBottom;
- if( mScrollbar[i]->handleToolTip(local_x, local_y, msg, sticky_rect) )
- {
- return TRUE;
- }
- }
- // Handle 'child' view.
- if( mScrolledView )
- {
- local_x = x - mScrolledView->getRect().mLeft;
- local_y = y - mScrolledView->getRect().mBottom;
- if( mScrolledView->handleToolTip(local_x, local_y, msg, sticky_rect) )
- {
- return TRUE;
- }
- }
-
- // Opaque
- return TRUE;
-}
-
-void LLScrollableContainerView::calcVisibleSize( S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const
-{
- const LLRect& rect = mScrolledView->getRect();
- calcVisibleSize(rect, visible_width, visible_height, show_h_scrollbar, show_v_scrollbar);
+ return scrolling;
}
-void LLScrollableContainerView::calcVisibleSize( const LLRect& doc_rect, S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const
+void LLScrollContainer::calcVisibleSize( S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const
{
+ const LLRect& doc_rect = getScrolledViewRect();
+ static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
S32 doc_width = doc_rect.getWidth();
S32 doc_height = doc_rect.getHeight();
- *visible_width = getRect().getWidth() - 2 * mBorder->getBorderWidth();
- *visible_height = getRect().getHeight() - 2 * mBorder->getBorderWidth();
+ S32 border_width = getBorderWidth();
+ *visible_width = getRect().getWidth() - 2 * border_width;
+ *visible_height = getRect().getHeight() - 2 * border_width;
*show_v_scrollbar = FALSE;
- if( *visible_height < doc_height )
- {
- *show_v_scrollbar = TRUE;
- *visible_width -= SCROLLBAR_SIZE;
- }
-
*show_h_scrollbar = FALSE;
- if( *visible_width < doc_width )
- {
- *show_h_scrollbar = TRUE;
- *visible_height -= SCROLLBAR_SIZE;
- // Must retest now that visible_height has changed
- if( !*show_v_scrollbar && (*visible_height < doc_height) )
+ if (!mHideScrollbar)
+ {
+ if( *visible_height < doc_height )
{
*show_v_scrollbar = TRUE;
- *visible_width -= SCROLLBAR_SIZE;
+ *visible_width -= scrollbar_size;
+ }
+
+ if( *visible_width < doc_width )
+ {
+ *show_h_scrollbar = TRUE;
+ *visible_height -= scrollbar_size;
+
+ // Must retest now that visible_height has changed
+ if( !*show_v_scrollbar && (*visible_height < doc_height) )
+ {
+ *show_v_scrollbar = TRUE;
+ *visible_width -= scrollbar_size;
+ }
}
}
}
+
-void LLScrollableContainerView::draw()
+void LLScrollContainer::draw()
{
+ static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
if (mAutoScrolling)
{
// add acceleration to autoscroll
- mAutoScrollRate = llmin(mAutoScrollRate + (LLFrameTimer::getFrameDeltaTimeF32() * AUTO_SCROLL_RATE_ACCEL), MAX_AUTO_SCROLL_RATE);
+ mAutoScrollRate = llmin(mAutoScrollRate + (LLFrameTimer::getFrameDeltaTimeF32() * AUTO_SCROLL_RATE_ACCEL), mMaxAutoScrollRate);
}
else
{
- // reset to minimum
- mAutoScrollRate = MIN_AUTO_SCROLL_RATE;
+ // reset to minimum for next time
+ mAutoScrollRate = mMinAutoScrollRate;
}
- // clear this flag to be set on next call to handleDragAndDrop
+ // clear this flag to be set on next call to autoScroll
mAutoScrolling = FALSE;
// auto-focus when scrollbar active
// this allows us to capture user intent (i.e. stop automatically scrolling the view/etc)
- if (!gFocusMgr.childHasKeyboardFocus(this) &&
- (mScrollbar[VERTICAL]->hasMouseCapture() || mScrollbar[HORIZONTAL]->hasMouseCapture()))
+ if (!hasFocus()
+ && (mScrollbar[VERTICAL]->hasMouseCapture() || mScrollbar[HORIZONTAL]->hasMouseCapture()))
{
focusFirstItem();
}
@@ -427,7 +429,7 @@ void LLScrollableContainerView::draw()
if( mIsOpaque )
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.color4fv( mBackgroundColor.mV );
+ gGL.color4fv( mBackgroundColor.get().mV );
gl_rect_2d( mInnerRect );
}
@@ -445,12 +447,12 @@ void LLScrollableContainerView::draw()
S32 visible_height = 0;
BOOL show_v_scrollbar = FALSE;
BOOL show_h_scrollbar = FALSE;
- calcVisibleSize( mScrolledView->getRect(), &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar );
+ calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar );
LLLocalClipRect clip(LLRect(mInnerRect.mLeft,
- mInnerRect.mBottom + (show_h_scrollbar ? SCROLLBAR_SIZE : 0) + visible_height,
- visible_width,
- mInnerRect.mBottom + (show_h_scrollbar ? SCROLLBAR_SIZE : 0)
+ mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0) + visible_height,
+ mInnerRect.mRight - (show_v_scrollbar ? scrollbar_size: 0),
+ mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0)
));
drawChild(mScrolledView);
}
@@ -481,16 +483,32 @@ void LLScrollableContainerView::draw()
sDepth--;
}
}
+} // end draw
- if (sDebugRects)
+bool LLScrollContainer::addChild(LLView* view, S32 tab_group)
+{
+ if (!mScrolledView)
{
- drawDebugRect();
+ // Use the first panel or container as the scrollable view (bit of a hack)
+ mScrolledView = view;
}
-} // end draw
+ bool ret_val = LLView::addChild(view, tab_group);
-void LLScrollableContainerView::updateScroll()
+ //bring the scrollbars to the front
+ sendChildToFront( mScrollbar[HORIZONTAL] );
+ sendChildToFront( mScrollbar[VERTICAL] );
+
+ return ret_val;
+}
+
+void LLScrollContainer::updateScroll()
{
+ if (!mScrolledView)
+ {
+ return;
+ }
+ static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
LLRect doc_rect = mScrolledView->getRect();
S32 doc_width = doc_rect.getWidth();
S32 doc_height = doc_rect.getHeight();
@@ -498,9 +516,9 @@ void LLScrollableContainerView::updateScroll()
S32 visible_height = 0;
BOOL show_v_scrollbar = FALSE;
BOOL show_h_scrollbar = FALSE;
- calcVisibleSize( doc_rect, &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar );
+ calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar );
- S32 border_width = mBorder->getBorderWidth();
+ S32 border_width = getBorderWidth();
if( show_v_scrollbar )
{
if( doc_rect.mTop < getRect().getHeight() - border_width )
@@ -514,15 +532,15 @@ void LLScrollableContainerView::updateScroll()
S32 v_scrollbar_height = visible_height;
if( !show_h_scrollbar && mReserveScrollCorner )
{
- v_scrollbar_height -= SCROLLBAR_SIZE;
+ v_scrollbar_height -= scrollbar_size;
}
- mScrollbar[VERTICAL]->reshape( SCROLLBAR_SIZE, v_scrollbar_height, TRUE );
+ mScrollbar[VERTICAL]->reshape( scrollbar_size, v_scrollbar_height, TRUE );
// Make room for the horizontal scrollbar (or not)
S32 v_scrollbar_offset = 0;
if( show_h_scrollbar || mReserveScrollCorner )
{
- v_scrollbar_offset = SCROLLBAR_SIZE;
+ v_scrollbar_offset = scrollbar_size;
}
LLRect r = mScrollbar[VERTICAL]->getRect();
r.translate( 0, mInnerRect.mBottom - r.mBottom + v_scrollbar_offset );
@@ -552,9 +570,9 @@ void LLScrollableContainerView::updateScroll()
S32 h_scrollbar_width = visible_width;
if( !show_v_scrollbar && mReserveScrollCorner )
{
- h_scrollbar_width -= SCROLLBAR_SIZE;
+ h_scrollbar_width -= scrollbar_size;
}
- mScrollbar[HORIZONTAL]->reshape( h_scrollbar_width, SCROLLBAR_SIZE, TRUE );
+ mScrollbar[HORIZONTAL]->reshape( h_scrollbar_width, scrollbar_size, TRUE );
}
else
{
@@ -571,104 +589,119 @@ void LLScrollableContainerView::updateScroll()
mScrollbar[VERTICAL]->setPageSize( visible_height );
} // end updateScroll
-void LLScrollableContainerView::setBorderVisible(BOOL b)
+void LLScrollContainer::setBorderVisible(BOOL b)
{
mBorder->setVisible( b );
+ // Recompute inner rect, as border visibility changes it
+ mInnerRect = getLocalRect();
+ mInnerRect.stretch( -getBorderWidth() );
}
-// Scroll so that as much of rect as possible is showing (where rect is defined in the space of scroller view, not scrolled)
-void LLScrollableContainerView::scrollToShowRect(const LLRect& rect, const LLCoordGL& desired_offset)
+LLRect LLScrollContainer::getVisibleContentRect()
{
- if (!mScrolledView)
- {
- llwarns << "LLScrollableContainerView::scrollToShowRect with no view!" << llendl;
- return;
- }
+ updateScroll();
+ LLRect visible_rect = getContentWindowRect();
+ LLRect contents_rect = mScrolledView->getRect();
+ visible_rect.translate(-contents_rect.mLeft, -contents_rect.mBottom);
+ return visible_rect;
+}
+LLRect LLScrollContainer::getContentWindowRect()
+{
+ updateScroll();
+ LLRect scroller_view_rect;
S32 visible_width = 0;
S32 visible_height = 0;
- BOOL show_v_scrollbar = FALSE;
BOOL show_h_scrollbar = FALSE;
- const LLRect& scrolled_rect = mScrolledView->getRect();
- calcVisibleSize( scrolled_rect, &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar );
-
- // can't be so far left that right side of rect goes off screen, or so far right that left side does
- S32 horiz_offset = llclamp(desired_offset.mX, llmin(0, -visible_width + rect.getWidth()), 0);
- // can't be so high that bottom of rect goes off screen, or so low that top does
- S32 vert_offset = llclamp(desired_offset.mY, 0, llmax(0, visible_height - rect.getHeight()));
-
- // Vertical
- // 1. First make sure the top is visible
- // 2. Then, if possible without hiding the top, make the bottom visible.
- S32 vert_pos = mScrollbar[VERTICAL]->getDocPos();
-
- // find scrollbar position to get top of rect on screen (scrolling up)
- S32 top_offset = scrolled_rect.mTop - rect.mTop - vert_offset;
- // find scrollbar position to get bottom of rect on screen (scrolling down)
- S32 bottom_offset = vert_offset == 0 ? scrolled_rect.mTop - rect.mBottom - visible_height : top_offset;
- // scroll up far enough to see top or scroll down just enough if item is bigger than visual area
- if( vert_pos >= top_offset || visible_height < rect.getHeight())
- {
- vert_pos = top_offset;
- }
- // else scroll down far enough to see bottom
- else
- if( vert_pos <= bottom_offset )
+ BOOL show_v_scrollbar = FALSE;
+ calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar );
+ S32 border_width = getBorderWidth();
+ scroller_view_rect.setOriginAndSize(border_width,
+ show_h_scrollbar ? mScrollbar[HORIZONTAL]->getRect().mTop : border_width,
+ visible_width,
+ visible_height);
+ return scroller_view_rect;
+}
+
+// rect is in document coordinates, constraint is in display coordinates relative to content window rect
+void LLScrollContainer::scrollToShowRect(const LLRect& rect, const LLRect& constraint)
+{
+ if (!mScrolledView)
{
- vert_pos = bottom_offset;
+ llwarns << "LLScrollContainer::scrollToShowRect with no view!" << llendl;
+ return;
}
+ LLRect content_window_rect = getContentWindowRect();
+ // get document rect
+ LLRect scrolled_rect = mScrolledView->getRect();
+
+ // shrink target rect to fit within constraint region, biasing towards top left
+ LLRect rect_to_constrain = rect;
+ rect_to_constrain.mBottom = llmax(rect_to_constrain.mBottom, rect_to_constrain.mTop - constraint.getHeight());
+ rect_to_constrain.mRight = llmin(rect_to_constrain.mRight, rect_to_constrain.mLeft + constraint.getWidth());
+
+ // calculate allowable positions for scroller window in document coordinates
+ LLRect allowable_scroll_rect(rect_to_constrain.mRight - constraint.mRight,
+ rect_to_constrain.mBottom - constraint.mBottom,
+ rect_to_constrain.mLeft - constraint.mLeft,
+ rect_to_constrain.mTop - constraint.mTop);
+
+ // translate from allowable region for lower left corner to upper left corner
+ allowable_scroll_rect.translate(0, content_window_rect.getHeight());
+
+ S32 vert_pos = llclamp(mScrollbar[VERTICAL]->getDocPos(),
+ mScrollbar[VERTICAL]->getDocSize() - allowable_scroll_rect.mTop, // min vertical scroll
+ mScrollbar[VERTICAL]->getDocSize() - allowable_scroll_rect.mBottom); // max vertical scroll
+
mScrollbar[VERTICAL]->setDocSize( scrolled_rect.getHeight() );
- mScrollbar[VERTICAL]->setPageSize( visible_height );
+ mScrollbar[VERTICAL]->setPageSize( content_window_rect.getHeight() );
mScrollbar[VERTICAL]->setDocPos( vert_pos );
- // Horizontal
- // 1. First make sure left side is visible
- // 2. Then, if possible without hiding the left side, make the right side visible.
- S32 horiz_pos = mScrollbar[HORIZONTAL]->getDocPos();
- S32 left_offset = rect.mLeft - scrolled_rect.mLeft + horiz_offset;
- S32 right_offset = horiz_offset == 0 ? rect.mRight - scrolled_rect.mLeft - visible_width : left_offset;
+ S32 horizontal_pos = llclamp(mScrollbar[HORIZONTAL]->getDocPos(),
+ allowable_scroll_rect.mLeft,
+ allowable_scroll_rect.mRight);
- if( horiz_pos >= left_offset || visible_width < rect.getWidth() )
- {
- horiz_pos = left_offset;
- }
- else if( horiz_pos <= right_offset )
- {
- horiz_pos = right_offset;
- }
-
mScrollbar[HORIZONTAL]->setDocSize( scrolled_rect.getWidth() );
- mScrollbar[HORIZONTAL]->setPageSize( visible_width );
- mScrollbar[HORIZONTAL]->setDocPos( horiz_pos );
+ mScrollbar[HORIZONTAL]->setPageSize( content_window_rect.getWidth() );
+ mScrollbar[HORIZONTAL]->setDocPos( horizontal_pos );
// propagate scroll to document
updateScroll();
+
+ // In case we are in accordion tab notify parent to show selected rectangle
+ LLRect screen_rc;
+ localRectToScreen(rect_to_constrain, &screen_rc);
+ notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue()));
}
-void LLScrollableContainerView::pageUp(S32 overlap)
+void LLScrollContainer::pageUp(S32 overlap)
{
mScrollbar[VERTICAL]->pageUp(overlap);
+ updateScroll();
}
-void LLScrollableContainerView::pageDown(S32 overlap)
+void LLScrollContainer::pageDown(S32 overlap)
{
mScrollbar[VERTICAL]->pageDown(overlap);
+ updateScroll();
}
-void LLScrollableContainerView::goToTop()
+void LLScrollContainer::goToTop()
{
mScrollbar[VERTICAL]->setDocPos(0);
+ updateScroll();
}
-void LLScrollableContainerView::goToBottom()
+void LLScrollContainer::goToBottom()
{
mScrollbar[VERTICAL]->setDocPos(mScrollbar[VERTICAL]->getDocSize());
+ updateScroll();
}
-S32 LLScrollableContainerView::getBorderWidth() const
+S32 LLScrollContainer::getBorderWidth() const
{
- if (mBorder)
+ if (mBorder->getVisible())
{
return mBorder->getBorderWidth();
}
@@ -676,73 +709,3 @@ S32 LLScrollableContainerView::getBorderWidth() const
return 0;
}
-// virtual
-LLXMLNodePtr LLScrollableContainerView::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLView::getXML();
-
- // Attributes
-
- node->createChild("opaque", TRUE)->setBoolValue(mIsOpaque);
-
- if (mIsOpaque)
- {
- node->createChild("color", TRUE)->setFloatValue(4, mBackgroundColor.mV);
- }
-
- // Contents
-
- LLXMLNodePtr child_node = mScrolledView->getXML();
-
- node->addChild(child_node);
-
- return node;
-}
-
-LLView* LLScrollableContainerView::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("scroll_container");
- node->getAttributeString("name", name);
-
- LLRect rect;
- createRect(node, rect, parent, LLRect());
-
- BOOL opaque = FALSE;
- node->getAttributeBOOL("opaque", opaque);
-
- LLColor4 color(0,0,0,0);
- LLUICtrlFactory::getAttributeColor(node,"color", color);
-
- // Create the scroll view
- LLScrollableContainerView *ret = new LLScrollableContainerView(name, rect, (LLPanel*)NULL, opaque, color);
-
- LLPanel* panelp = NULL;
-
- // Find a child panel to add
- LLXMLNodePtr child;
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
- {
- LLView *control = factory->createCtrlWidget(panelp, child);
- if (control && control->isPanel())
- {
- if (panelp)
- {
- llinfos << "Warning! Attempting to put multiple panels into a scrollable container view!" << llendl;
- delete control;
- }
- else
- {
- panelp = (LLPanel*)control;
- }
- }
- }
-
- if (panelp == NULL)
- {
- panelp = new LLPanel(std::string("dummy"), LLRect::null, FALSE);
- }
-
- ret->mScrolledView = panelp;
-
- return ret;
-}
diff --git a/indra/llui/llscrollcontainer.h b/indra/llui/llscrollcontainer.h
index 70fc9087d7..25dcd071ab 100644
--- a/indra/llui/llscrollcontainer.h
+++ b/indra/llui/llscrollcontainer.h
@@ -1,6 +1,6 @@
/**
* @file llscrollcontainer.h
- * @brief LLScrollableContainerView class header file.
+ * @brief LLScrollContainer class header file.
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
@@ -53,40 +53,59 @@ class LLUICtrlFactory;
* the width and height of the view you're scrolling.
*
*****************************************************************************/
-class LLScrollableContainerView : public LLUICtrl
+
+struct ScrollContainerRegistry : public LLChildRegistry<ScrollContainerRegistry>
+{};
+
+class LLScrollContainer : public LLUICtrl
{
public:
// Note: vertical comes before horizontal because vertical
// scrollbars have priority for mouse and keyboard events.
enum SCROLL_ORIENTATION { VERTICAL, HORIZONTAL, SCROLLBAR_COUNT };
- LLScrollableContainerView( const std::string& name, const LLRect& rect,
- LLView* scrolled_view, BOOL is_opaque = FALSE,
- const LLColor4& bg_color = LLColor4(0,0,0,0) );
- LLScrollableContainerView( const std::string& name, const LLRect& rect,
- LLUICtrl* scrolled_ctrl, BOOL is_opaque = FALSE,
- const LLColor4& bg_color = LLColor4(0,0,0,0) );
- virtual ~LLScrollableContainerView( void );
-
- void setScrolledView(LLView* view) { mScrolledView = view; }
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<bool> is_opaque,
+ reserve_scroll_corner,
+ border_visible,
+ hide_scrollbar;
+ Optional<F32> min_auto_scroll_rate,
+ max_auto_scroll_rate;
+ Optional<LLUIColor> bg_color;
+ Optional<LLScrollbar::callback_t> scroll_callback;
+
+ Params();
+ };
+
+ // my valid children are stored in this registry
+ typedef ScrollContainerRegistry child_registry_t;
+
+protected:
+ LLScrollContainer(const Params&);
+ friend class LLUICtrlFactory;
+public:
+ virtual ~LLScrollContainer( void );
- virtual void setValue(const LLSD& value) { mInnerRect.setValue(value); }
+ virtual void setValue(const LLSD& value) { mInnerRect.setValue(value); }
- void calcVisibleSize( S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const;
- void calcVisibleSize( const LLRect& doc_rect, S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const;
void setBorderVisible( BOOL b );
- void scrollToShowRect( const LLRect& rect, const LLCoordGL& desired_offset );
+ void scrollToShowRect( const LLRect& rect, const LLRect& constraint);
+ void scrollToShowRect( const LLRect& rect) { scrollToShowRect(rect, LLRect(0, mInnerRect.getHeight(), mInnerRect.getWidth(), 0)); }
+
void setReserveScrollCorner( BOOL b ) { mReserveScrollCorner = b; }
- const LLRect& getScrolledViewRect() const { return mScrolledView->getRect(); }
+ LLRect getVisibleContentRect();
+ LLRect getContentWindowRect();
+ const LLRect& getScrolledViewRect() const { return mScrolledView ? mScrolledView->getRect() : LLRect::null; }
void pageUp(S32 overlap = 0);
void pageDown(S32 overlap = 0);
void goToTop();
void goToBottom();
+ bool isAtTop() { return mScrollbar[VERTICAL]->isAtBeginning(); }
+ bool isAtBottom() { return mScrollbar[VERTICAL]->isAtEnd(); }
S32 getBorderWidth() const;
- BOOL needsToScroll(S32 x, S32 y, SCROLL_ORIENTATION axis) const;
-
// LLView functionality
virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
virtual BOOL handleKeyHere(KEY key, MASK mask);
@@ -97,30 +116,31 @@ public:
EAcceptance* accept,
std::string& tooltip_msg);
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect);
virtual void draw();
-
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
+ virtual bool addChild(LLView* view, S32 tab_group = 0);
+
+ bool autoScroll(S32 x, S32 y);
private:
- void init();
-
// internal scrollbar handlers
virtual void scrollHorizontal( S32 new_pos );
virtual void scrollVertical( S32 new_pos );
void updateScroll();
+ void calcVisibleSize( S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const;
LLScrollbar* mScrollbar[SCROLLBAR_COUNT];
LLView* mScrolledView;
S32 mSize;
BOOL mIsOpaque;
- LLColor4 mBackgroundColor;
+ LLUIColor mBackgroundColor;
LLRect mInnerRect;
LLViewBorder* mBorder;
BOOL mReserveScrollCorner;
BOOL mAutoScrolling;
F32 mAutoScrollRate;
+ F32 mMinAutoScrollRate;
+ F32 mMaxAutoScrollRate;
+ bool mHideScrollbar;
};
diff --git a/indra/llui/llscrollingpanellist.cpp b/indra/llui/llscrollingpanellist.cpp
index 05d0c6f753..4f55c0507c 100644
--- a/indra/llui/llscrollingpanellist.cpp
+++ b/indra/llui/llscrollingpanellist.cpp
@@ -35,7 +35,7 @@
#include "llscrollingpanellist.h"
-static LLRegisterWidget<LLScrollingPanelList> r("scrolling_panel_list");
+static LLDefaultChildRegistry::Register<LLScrollingPanelList> r("scrolling_panel_list");
/////////////////////////////////////////////////////////////////////
@@ -50,11 +50,73 @@ void LLScrollingPanelList::clearPanels()
reshape( 1, 1, FALSE );
}
-void LLScrollingPanelList::addPanel( LLScrollingPanel* panel )
+S32 LLScrollingPanelList::addPanel( LLScrollingPanel* panel )
{
- addChildAtEnd( panel );
+ addChildInBack( panel );
mPanelList.push_front( panel );
-
+
+ // Resize this view
+ S32 total_height = 0;
+ S32 max_width = 0;
+ S32 cur_gap = 0;
+ for (std::deque<LLScrollingPanel*>::iterator iter = mPanelList.begin();
+ iter != mPanelList.end(); ++iter)
+ {
+ LLScrollingPanel *childp = *iter;
+ total_height += childp->getRect().getHeight() + cur_gap;
+ max_width = llmax( max_width, childp->getRect().getWidth() );
+ cur_gap = GAP_BETWEEN_PANELS;
+ }
+ reshape( max_width, total_height, FALSE );
+
+ // Reposition each of the child views
+ S32 cur_y = total_height;
+ for (std::deque<LLScrollingPanel*>::iterator iter = mPanelList.begin();
+ iter != mPanelList.end(); ++iter)
+ {
+ LLScrollingPanel *childp = *iter;
+ cur_y -= childp->getRect().getHeight();
+ childp->translate( -childp->getRect().mLeft, cur_y - childp->getRect().mBottom);
+ cur_y -= GAP_BETWEEN_PANELS;
+ }
+
+ return total_height;
+}
+
+void LLScrollingPanelList::removePanel(LLScrollingPanel* panel)
+{
+ U32 index = 0;
+ LLScrollingPanelList::panel_list_t::const_iterator iter;
+
+ if (!mPanelList.empty())
+ {
+ for (iter = mPanelList.begin(); iter != mPanelList.end(); ++iter, ++index)
+ {
+ if (*iter == panel)
+ {
+ break;
+ }
+ }
+ if(iter != mPanelList.end())
+ {
+ removePanel(index);
+ }
+ }
+}
+
+void LLScrollingPanelList::removePanel( U32 panel_index )
+{
+ if ( mPanelList.empty() || panel_index >= mPanelList.size() )
+ {
+ llwarns << "Panel index " << panel_index << " is out of range!" << llendl;
+ return;
+ }
+ else
+ {
+ removeChild( mPanelList.at(panel_index) );
+ mPanelList.erase( mPanelList.begin() + panel_index );
+ }
+
const S32 GAP_BETWEEN_PANELS = 6;
// Resize this view
@@ -82,7 +144,7 @@ void LLScrollingPanelList::addPanel( LLScrollingPanel* panel )
cur_y -= GAP_BETWEEN_PANELS;
}
}
-
+
void LLScrollingPanelList::updatePanels(BOOL allow_modify)
{
for (std::deque<LLScrollingPanel*>::iterator iter = mPanelList.begin();
@@ -138,18 +200,3 @@ void LLScrollingPanelList::draw()
LLUICtrl::draw();
}
-
-// static
-LLView* LLScrollingPanelList::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("scrolling_panel_list");
- node->getAttributeString("name", name);
-
- LLRect rect;
- createRect(node, rect, parent, LLRect());
-
- LLScrollingPanelList* scrolling_panel_list = new LLScrollingPanelList(name, rect);
- scrolling_panel_list->initFromXML(node, parent);
- return scrolling_panel_list;
-}
-
diff --git a/indra/llui/llscrollingpanellist.h b/indra/llui/llscrollingpanellist.h
index b9d730978f..3abfbcbbe7 100644
--- a/indra/llui/llscrollingpanellist.h
+++ b/indra/llui/llscrollingpanellist.h
@@ -29,6 +29,9 @@
* $/LicenseInfo$
*/
+#ifndef LL_LLSCROLLINGPANELLIST_H
+#define LL_LLSCROLLINGPANELLIST_H
+
#include <vector>
#include "llui.h"
@@ -42,7 +45,7 @@
class LLScrollingPanel : public LLPanel
{
public:
- LLScrollingPanel(const std::string& name, const LLRect& rect) : LLPanel(name, rect) { }
+ LLScrollingPanel(const LLPanel::Params& params) : LLPanel(params) {}
virtual void updatePanel(BOOL allow_modify) = 0;
};
@@ -53,23 +56,37 @@ public:
class LLScrollingPanelList : public LLUICtrl
{
public:
- LLScrollingPanelList(const std::string& name, const LLRect& rect)
- : LLUICtrl(name, rect, TRUE, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_BOTTOM ) {}
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Params()
+ {
+ name = "scrolling_panel_list";
+ follows.flags = FOLLOWS_LEFT | FOLLOWS_BOTTOM;
+ }
+ };
+ LLScrollingPanelList(const Params& p)
+ : LLUICtrl(p)
+ {}
+
+ static const S32 GAP_BETWEEN_PANELS = 6;
+
+ typedef std::deque<LLScrollingPanel*> panel_list_t;
virtual void setValue(const LLSD& value) {};
- virtual LLXMLNodePtr getXML(bool save_children) const { return LLUICtrl::getXML(); }
-
virtual void draw();
void clearPanels();
- void addPanel( LLScrollingPanel* panel );
+ S32 addPanel( LLScrollingPanel* panel );
+ void removePanel( LLScrollingPanel* panel );
+ void removePanel( U32 panel_index );
void updatePanels(BOOL allow_modify);
+ const panel_list_t& getPanelList() { return mPanelList; }
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
-
private:
void updatePanelVisiblilty();
- std::deque<LLScrollingPanel*> mPanelList;
+ panel_list_t mPanelList;
};
+
+#endif //LL_LLSCROLLINGPANELLIST_H
diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp
new file mode 100644
index 0000000000..3cc92baa8d
--- /dev/null
+++ b/indra/llui/llscrolllistcell.cpp
@@ -0,0 +1,441 @@
+/**
+ * @file llscrolllistcell.cpp
+ * @brief Scroll lists are composed of rows (items), each of which
+ * contains columns (cells).
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llscrolllistcell.h"
+
+#include "llcheckboxctrl.h"
+#include "llui.h" // LLUIImage
+#include "lluictrlfactory.h"
+
+//static
+LLScrollListCell* LLScrollListCell::create(const LLScrollListCell::Params& cell_p)
+{
+ LLScrollListCell* cell = NULL;
+
+ if (cell_p.type() == "icon")
+ {
+ cell = new LLScrollListIcon(cell_p);
+ }
+ else if (cell_p.type() == "checkbox")
+ {
+ cell = new LLScrollListCheck(cell_p);
+ }
+ else if (cell_p.type() == "date")
+ {
+ cell = new LLScrollListDate(cell_p);
+ }
+ else // default is "text"
+ {
+ cell = new LLScrollListText(cell_p);
+ }
+
+ if (cell_p.value.isProvided())
+ {
+ cell->setValue(cell_p.value);
+ }
+
+ return cell;
+}
+
+
+LLScrollListCell::LLScrollListCell(const LLScrollListCell::Params& p)
+: mWidth(p.width),
+ mToolTip(p.tool_tip)
+{}
+
+// virtual
+const LLSD LLScrollListCell::getValue() const
+{
+ return LLStringUtil::null;
+}
+
+//
+// LLScrollListIcon
+//
+LLScrollListIcon::LLScrollListIcon(const LLScrollListCell::Params& p)
+: LLScrollListCell(p),
+ mIcon(LLUI::getUIImage(p.value().asString())),
+ mColor(p.color),
+ mAlignment(p.font_halign)
+{}
+
+LLScrollListIcon::~LLScrollListIcon()
+{
+}
+
+/*virtual*/
+S32 LLScrollListIcon::getHeight() const
+{ return mIcon ? mIcon->getHeight() : 0; }
+
+/*virtual*/
+const LLSD LLScrollListIcon::getValue() const
+{ return mIcon.isNull() ? LLStringUtil::null : mIcon->getName(); }
+
+void LLScrollListIcon::setValue(const LLSD& value)
+{
+ if (value.isUUID())
+ {
+ // don't use default image specified by LLUUID::null, use no image in that case
+ LLUUID image_id = value.asUUID();
+ mIcon = image_id.notNull() ? LLUI::getUIImageByID(image_id) : LLUIImagePtr(NULL);
+ }
+ else
+ {
+ std::string value_string = value.asString();
+ if (LLUUID::validate(value_string))
+ {
+ setValue(LLUUID(value_string));
+ }
+ else if (!value_string.empty())
+ {
+ mIcon = LLUI::getUIImage(value.asString());
+ }
+ else
+ {
+ mIcon = NULL;
+ }
+ }
+}
+
+
+void LLScrollListIcon::setColor(const LLColor4& color)
+{
+ mColor = color;
+}
+
+S32 LLScrollListIcon::getWidth() const
+{
+ // if no specified fix width, use width of icon
+ if (LLScrollListCell::getWidth() == 0 && mIcon.notNull())
+ {
+ return mIcon->getWidth();
+ }
+ return LLScrollListCell::getWidth();
+}
+
+
+void LLScrollListIcon::draw(const LLColor4& color, const LLColor4& highlight_color) const
+{
+ if (mIcon)
+ {
+ switch(mAlignment)
+ {
+ case LLFontGL::LEFT:
+ mIcon->draw(0, 0, mColor);
+ break;
+ case LLFontGL::RIGHT:
+ mIcon->draw(getWidth() - mIcon->getWidth(), 0, mColor);
+ break;
+ case LLFontGL::HCENTER:
+ mIcon->draw((getWidth() - mIcon->getWidth()) / 2, 0, mColor);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+//
+// LLScrollListText
+//
+U32 LLScrollListText::sCount = 0;
+
+LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p)
+: LLScrollListCell(p),
+ mText(p.value().asString()),
+ mFont(p.font),
+ mColor(p.color),
+ mUseColor(p.color.isProvided()),
+ mFontAlignment(p.font_halign),
+ mVisible(p.visible),
+ mHighlightCount( 0 ),
+ mHighlightOffset( 0 )
+{
+ sCount++;
+
+ // initialize rounded rect image
+ if (!mRoundedRectImage)
+ {
+ mRoundedRectImage = LLUI::getUIImage("Rounded_Square");
+ }
+}
+
+//virtual
+void LLScrollListText::highlightText(S32 offset, S32 num_chars)
+{
+ mHighlightOffset = offset;
+ mHighlightCount = num_chars;
+}
+
+//virtual
+BOOL LLScrollListText::isText() const
+{
+ return TRUE;
+}
+
+// virtual
+const std::string &LLScrollListText::getToolTip() const
+{
+ // If base class has a tooltip, return that
+ if (! LLScrollListCell::getToolTip().empty())
+ return LLScrollListCell::getToolTip();
+
+ // ...otherwise, return the value itself as the tooltip
+ return mText.getString();
+}
+
+// virtual
+BOOL LLScrollListText::needsToolTip() const
+{
+ // If base class has a tooltip, return that
+ if (LLScrollListCell::needsToolTip())
+ return LLScrollListCell::needsToolTip();
+
+ // ...otherwise, show tooltips for truncated text
+ return mFont->getWidth(mText.getString()) > getWidth();
+}
+
+//virtual
+BOOL LLScrollListText::getVisible() const
+{
+ return mVisible;
+}
+
+//virtual
+S32 LLScrollListText::getHeight() const
+{
+ return llround(mFont->getLineHeight());
+}
+
+
+LLScrollListText::~LLScrollListText()
+{
+ sCount--;
+}
+
+S32 LLScrollListText::getContentWidth() const
+{
+ return mFont->getWidth(mText.getString());
+}
+
+
+void LLScrollListText::setColor(const LLColor4& color)
+{
+ mColor = color;
+ mUseColor = TRUE;
+}
+
+void LLScrollListText::setText(const LLStringExplicit& text)
+{
+ mText = text;
+}
+
+void LLScrollListText::setFontStyle(const U8 font_style)
+{
+ LLFontDescriptor new_desc(mFont->getFontDesc());
+ new_desc.setStyle(font_style);
+ mFont = LLFontGL::getFont(new_desc);
+}
+
+//virtual
+void LLScrollListText::setValue(const LLSD& text)
+{
+ setText(text.asString());
+}
+
+//virtual
+const LLSD LLScrollListText::getValue() const
+{
+ return LLSD(mText.getString());
+}
+
+
+void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_color) const
+{
+ LLColor4 display_color;
+ if (mUseColor)
+ {
+ display_color = mColor;
+ }
+ else
+ {
+ display_color = color;
+ }
+
+ if (mHighlightCount > 0)
+ {
+ S32 left = 0;
+ switch(mFontAlignment)
+ {
+ case LLFontGL::LEFT:
+ left = mFont->getWidth(mText.getString(), 0, mHighlightOffset);
+ break;
+ case LLFontGL::RIGHT:
+ left = getWidth() - mFont->getWidth(mText.getString(), mHighlightOffset, S32_MAX);
+ break;
+ case LLFontGL::HCENTER:
+ left = (getWidth() - mFont->getWidth(mText.getString())) / 2;
+ break;
+ }
+ LLRect highlight_rect(left - 2,
+ llround(mFont->getLineHeight()) + 1,
+ left + mFont->getWidth(mText.getString(), mHighlightOffset, mHighlightCount) + 1,
+ 1);
+ mRoundedRectImage->draw(highlight_rect, highlight_color);
+ }
+
+ // Try to draw the entire string
+ F32 right_x;
+ U32 string_chars = mText.length();
+ F32 start_x = 0.f;
+ switch(mFontAlignment)
+ {
+ case LLFontGL::LEFT:
+ start_x = 0.f;
+ break;
+ case LLFontGL::RIGHT:
+ start_x = (F32)getWidth();
+ break;
+ case LLFontGL::HCENTER:
+ start_x = (F32)getWidth() * 0.5f;
+ break;
+ }
+ mFont->render(mText.getWString(), 0,
+ start_x, 2.f,
+ display_color,
+ mFontAlignment,
+ LLFontGL::BOTTOM,
+ 0,
+ LLFontGL::NO_SHADOW,
+ string_chars,
+ getWidth(),
+ &right_x,
+ TRUE);
+}
+
+//
+// LLScrollListCheck
+//
+LLScrollListCheck::LLScrollListCheck(const LLScrollListCell::Params& p)
+: LLScrollListCell(p)
+{
+ LLCheckBoxCtrl::Params checkbox_p;
+ checkbox_p.name("checkbox");
+ checkbox_p.rect = LLRect(0, p.width, p.width, 0);
+ checkbox_p.enabled(p.enabled);
+ checkbox_p.initial_value(p.value());
+
+ mCheckBox = LLUICtrlFactory::create<LLCheckBoxCtrl>(checkbox_p);
+
+ LLRect rect(mCheckBox->getRect());
+ if (p.width)
+ {
+ rect.mRight = rect.mLeft + p.width;
+ mCheckBox->setRect(rect);
+ setWidth(p.width);
+ }
+ else
+ {
+ setWidth(rect.getWidth()); //check_box->getWidth();
+ }
+
+ mCheckBox->setColor(p.color);
+}
+
+
+LLScrollListCheck::~LLScrollListCheck()
+{
+ delete mCheckBox;
+ mCheckBox = NULL;
+}
+
+void LLScrollListCheck::draw(const LLColor4& color, const LLColor4& highlight_color) const
+{
+ mCheckBox->draw();
+}
+
+BOOL LLScrollListCheck::handleClick()
+{
+ if (mCheckBox->getEnabled())
+ {
+ mCheckBox->toggle();
+ }
+ // don't change selection when clicking on embedded checkbox
+ return TRUE;
+}
+
+/*virtual*/
+const LLSD LLScrollListCheck::getValue() const
+{
+ return mCheckBox->getValue();
+}
+
+/*virtual*/
+void LLScrollListCheck::setValue(const LLSD& value)
+{
+ mCheckBox->setValue(value);
+}
+
+/*virtual*/
+void LLScrollListCheck::onCommit()
+{
+ mCheckBox->onCommit();
+}
+
+/*virtual*/
+void LLScrollListCheck::setEnabled(BOOL enable)
+{
+ mCheckBox->setEnabled(enable);
+}
+
+//
+// LLScrollListDate
+//
+
+LLScrollListDate::LLScrollListDate( const LLScrollListCell::Params& p)
+: LLScrollListText(p),
+ mDate(p.value().asDate())
+{}
+
+void LLScrollListDate::setValue(const LLSD& value)
+{
+ mDate = value.asDate();
+ LLScrollListText::setValue(mDate.asRFC1123());
+}
+
+const LLSD LLScrollListDate::getValue() const
+{
+ return mDate;
+}
diff --git a/indra/llui/llscrolllistcell.h b/indra/llui/llscrolllistcell.h
new file mode 100644
index 0000000000..5fecf5aade
--- /dev/null
+++ b/indra/llui/llscrolllistcell.h
@@ -0,0 +1,227 @@
+/**
+ * @file llscrolllistcell.h
+ * @brief Scroll lists are composed of rows (items), each of which
+ * contains columns (cells).
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLSCROLLLISTCELL_H
+#define LLSCROLLLISTCELL_H
+
+#include "llfontgl.h" // HAlign
+#include "llpointer.h" // LLPointer<>
+#include "lluistring.h"
+#include "v4color.h"
+#include "llui.h"
+
+class LLCheckBoxCtrl;
+class LLSD;
+class LLUIImage;
+
+/*
+ * Represents a cell in a scrollable table.
+ *
+ * Sub-classes must return height and other properties
+ * though width accessors are implemented by the base class.
+ * It is therefore important for sub-class constructors to call
+ * setWidth() with realistic values.
+ */
+class LLScrollListCell
+{
+public:
+ struct Params : public LLInitParam::Block<Params>
+ {
+ Optional<std::string> type,
+ column;
+
+ Optional<S32> width;
+ Optional<bool> enabled,
+ visible;
+
+ Optional<void*> userdata;
+ Optional<LLSD> value;
+ Optional<std::string> tool_tip;
+
+ Optional<const LLFontGL*> font;
+ Optional<LLColor4> font_color;
+ Optional<LLFontGL::HAlign> font_halign;
+
+ Optional<LLColor4> color;
+
+ Params()
+ : type("type", "text"),
+ column("column"),
+ width("width"),
+ enabled("enabled", true),
+ visible("visible", true),
+ value("value"),
+ tool_tip("tool_tip", ""),
+ font("font", LLFontGL::getFontSansSerifSmall()),
+ font_color("font_color", LLColor4::black),
+ color("color", LLColor4::white),
+ font_halign("halign", LLFontGL::LEFT)
+ {
+ addSynonym(column, "name");
+ addSynonym(font_color, "font-color");
+ }
+ };
+
+ static LLScrollListCell* create(const Params&);
+
+ LLScrollListCell(const LLScrollListCell::Params&);
+ virtual ~LLScrollListCell() {};
+
+ virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const {}; // truncate to given width, if possible
+ virtual S32 getWidth() const {return mWidth;}
+ virtual S32 getContentWidth() const { return 0; }
+ virtual S32 getHeight() const { return 0; }
+ virtual const LLSD getValue() const;
+ virtual void setValue(const LLSD& value) { }
+ virtual const std::string &getToolTip() const { return mToolTip; }
+ virtual void setToolTip(const std::string &str) { mToolTip = str; }
+ virtual BOOL getVisible() const { return TRUE; }
+ virtual void setWidth(S32 width) { mWidth = width; }
+ virtual void highlightText(S32 offset, S32 num_chars) {}
+ virtual BOOL isText() const { return FALSE; }
+ virtual BOOL needsToolTip() const { return ! mToolTip.empty(); }
+ virtual void setColor(const LLColor4&) {}
+ virtual void onCommit() {};
+
+ virtual BOOL handleClick() { return FALSE; }
+ virtual void setEnabled(BOOL enable) { }
+
+private:
+ S32 mWidth;
+ std::string mToolTip;
+};
+
+class LLScrollListSpacer : public LLScrollListCell
+{
+public:
+ LLScrollListSpacer(const LLScrollListCell::Params& p) : LLScrollListCell(p) {}
+ /*virtual*/ ~LLScrollListSpacer() {};
+ /*virtual*/ void draw(const LLColor4& color, const LLColor4& highlight_color) const {}
+};
+
+/*
+ * Cell displaying a text label.
+ */
+class LLScrollListText : public LLScrollListCell
+{
+public:
+ LLScrollListText(const LLScrollListCell::Params&);
+ /*virtual*/ ~LLScrollListText();
+
+ /*virtual*/ void draw(const LLColor4& color, const LLColor4& highlight_color) const;
+ /*virtual*/ S32 getContentWidth() const;
+ /*virtual*/ S32 getHeight() const;
+ /*virtual*/ void setValue(const LLSD& value);
+ /*virtual*/ const LLSD getValue() const;
+ /*virtual*/ BOOL getVisible() const;
+ /*virtual*/ void highlightText(S32 offset, S32 num_chars);
+
+ /*virtual*/ void setColor(const LLColor4&);
+ /*virtual*/ BOOL isText() const;
+ /*virtual*/ const std::string & getToolTip() const;
+ /*virtual*/ BOOL needsToolTip() const;
+
+ void setText(const LLStringExplicit& text);
+ void setFontStyle(const U8 font_style);
+
+private:
+ LLUIString mText;
+ const LLFontGL* mFont;
+ LLColor4 mColor;
+ U8 mUseColor;
+ LLFontGL::HAlign mFontAlignment;
+ BOOL mVisible;
+ S32 mHighlightCount;
+ S32 mHighlightOffset;
+
+ LLPointer<LLUIImage> mRoundedRectImage;
+
+ static U32 sCount;
+};
+
+/*
+ * Cell displaying an image.
+ */
+class LLScrollListIcon : public LLScrollListCell
+{
+public:
+ LLScrollListIcon(const LLScrollListCell::Params& p);
+ /*virtual*/ ~LLScrollListIcon();
+ /*virtual*/ void draw(const LLColor4& color, const LLColor4& highlight_color) const;
+ /*virtual*/ S32 getWidth() const;
+ /*virtual*/ S32 getHeight() const;
+ /*virtual*/ const LLSD getValue() const;
+ /*virtual*/ void setColor(const LLColor4&);
+ /*virtual*/ void setValue(const LLSD& value);
+
+private:
+ LLPointer<LLUIImage> mIcon;
+ LLColor4 mColor;
+ LLFontGL::HAlign mAlignment;
+};
+
+/*
+ * An interactive cell containing a check box.
+ */
+class LLScrollListCheck : public LLScrollListCell
+{
+public:
+ LLScrollListCheck( const LLScrollListCell::Params&);
+ /*virtual*/ ~LLScrollListCheck();
+ /*virtual*/ void draw(const LLColor4& color, const LLColor4& highlight_color) const;
+ /*virtual*/ S32 getHeight() const { return 0; }
+ /*virtual*/ const LLSD getValue() const;
+ /*virtual*/ void setValue(const LLSD& value);
+ /*virtual*/ void onCommit();
+
+ /*virtual*/ BOOL handleClick();
+ /*virtual*/ void setEnabled(BOOL enable);
+
+ LLCheckBoxCtrl* getCheckBox() { return mCheckBox; }
+
+private:
+ LLCheckBoxCtrl* mCheckBox;
+};
+
+class LLScrollListDate : public LLScrollListText
+{
+public:
+ LLScrollListDate( const LLScrollListCell::Params& p );
+ virtual void setValue(const LLSD& value);
+ virtual const LLSD getValue() const;
+
+private:
+ LLDate mDate;
+};
+
+#endif
diff --git a/indra/llui/llscrolllistcolumn.cpp b/indra/llui/llscrolllistcolumn.cpp
new file mode 100644
index 0000000000..d281341202
--- /dev/null
+++ b/indra/llui/llscrolllistcolumn.cpp
@@ -0,0 +1,338 @@
+/**
+ * @file llscrollcolumnheader.cpp
+ * @brief Scroll lists are composed of rows (items), each of which
+ * contains columns (cells).
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llscrolllistcolumn.h"
+
+#include "llbutton.h"
+#include "llresizebar.h"
+#include "llscrolllistcell.h"
+#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "lluictrlfactory.h"
+
+const S32 MIN_COLUMN_WIDTH = 20;
+
+// defaults for LLScrollColumnHeader param block pulled from widgets/scroll_column_header.xml
+static LLWidgetNameRegistry::StaticRegistrar sRegisterColumnHeaderParams(&typeid(LLScrollColumnHeader::Params), "scroll_column_header");
+
+//---------------------------------------------------------------------------
+// LLScrollColumnHeader
+//---------------------------------------------------------------------------
+LLScrollColumnHeader::Params::Params()
+: column("column")
+{
+ name = "column_header";
+ tab_stop(false);
+}
+
+
+LLScrollColumnHeader::LLScrollColumnHeader(const LLScrollColumnHeader::Params& p)
+: LLButton(p), // use combobox params to steal images
+ mColumn(p.column),
+ mHasResizableElement(FALSE)
+{
+ setClickedCallback(boost::bind(&LLScrollColumnHeader::onClick, this, _2));
+
+ // resize handles on left and right
+ const S32 RESIZE_BAR_THICKNESS = 3;
+ LLResizeBar::Params resize_bar_p;
+ resize_bar_p.resizing_view(this);
+ resize_bar_p.rect(LLRect(getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0));
+ resize_bar_p.min_size(MIN_COLUMN_WIDTH);
+ resize_bar_p.side(LLResizeBar::RIGHT);
+ resize_bar_p.enabled(false);
+ mResizeBar = LLUICtrlFactory::create<LLResizeBar>(resize_bar_p);
+ addChild(mResizeBar);
+}
+
+LLScrollColumnHeader::~LLScrollColumnHeader()
+{}
+
+void LLScrollColumnHeader::draw()
+{
+ std::string sort_column = mColumn->mParentCtrl->getSortColumnName();
+ BOOL draw_arrow = !mColumn->mLabel.empty()
+ && mColumn->mParentCtrl->isSorted()
+ // check for indirect sorting column as well as column's sorting name
+ && (sort_column == mColumn->mSortingColumn || sort_column == mColumn->mName);
+
+ BOOL is_ascending = mColumn->mParentCtrl->getSortAscending();
+ setImageOverlay(is_ascending ? "up_arrow.tga" : "down_arrow.tga", LLFontGL::RIGHT, draw_arrow ? LLColor4::white : LLColor4::transparent);
+
+ // Draw children
+ LLButton::draw();
+}
+
+BOOL LLScrollColumnHeader::handleDoubleClick(S32 x, S32 y, MASK mask)
+{
+ if (canResize() && mResizeBar->getRect().pointInRect(x, y))
+ {
+ // reshape column to max content width
+ LLRect column_rect = getRect();
+ column_rect.mRight = column_rect.mLeft + mColumn->mMaxContentWidth;
+ setShape(column_rect, true);
+ }
+ else
+ {
+ onClick(LLSD());
+ }
+ return TRUE;
+}
+
+void LLScrollColumnHeader::onClick(const LLSD& data)
+{
+ if (mColumn)
+ {
+ LLScrollListCtrl::onClickColumn(mColumn);
+ }
+}
+
+LLView* LLScrollColumnHeader::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding)
+{
+ // this logic assumes dragging on right
+ llassert(snap_edge == SNAP_RIGHT);
+
+ // use higher snap threshold for column headers
+ threshold = llmin(threshold, 10);
+
+ LLRect snap_rect = getSnapRect();
+
+ S32 snap_delta = mColumn->mMaxContentWidth - snap_rect.getWidth();
+
+ // x coord growing means column growing, so same signs mean we're going in right direction
+ if (llabs(snap_delta) <= threshold && mouse_dir.mX * snap_delta > 0 )
+ {
+ new_edge_val = snap_rect.mRight + snap_delta;
+ }
+ else
+ {
+ LLScrollListColumn* next_column = mColumn->mParentCtrl->getColumn(mColumn->mIndex + 1);
+ while (next_column)
+ {
+ if (next_column->mHeader)
+ {
+ snap_delta = (next_column->mHeader->getSnapRect().mRight - next_column->mMaxContentWidth) - snap_rect.mRight;
+ if (llabs(snap_delta) <= threshold && mouse_dir.mX * snap_delta > 0 )
+ {
+ new_edge_val = snap_rect.mRight + snap_delta;
+ }
+ break;
+ }
+ next_column = mColumn->mParentCtrl->getColumn(next_column->mIndex + 1);
+ }
+ }
+
+ return this;
+}
+
+void LLScrollColumnHeader::handleReshape(const LLRect& new_rect, bool by_user)
+{
+ S32 new_width = new_rect.getWidth();
+ S32 delta_width = new_width - (getRect().getWidth() /*+ mColumn->mParentCtrl->getColumnPadding()*/);
+
+ if (delta_width != 0)
+ {
+ S32 remaining_width = -delta_width;
+ S32 col;
+ for (col = mColumn->mIndex + 1; col < mColumn->mParentCtrl->getNumColumns(); col++)
+ {
+ LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
+ if (!columnp) continue;
+
+ if (columnp->mHeader && columnp->mHeader->canResize())
+ {
+ // how many pixels in width can this column afford to give up?
+ S32 resize_buffer_amt = llmax(0, columnp->getWidth() - MIN_COLUMN_WIDTH);
+
+ // user shrinking column, need to add width to other columns
+ if (delta_width < 0)
+ {
+ if (columnp->getWidth() > 0)
+ {
+ // statically sized column, give all remaining width to this column
+ columnp->setWidth(columnp->getWidth() + remaining_width);
+ if (columnp->mRelWidth > 0.f)
+ {
+ columnp->mRelWidth = (F32)columnp->getWidth() / (F32)mColumn->mParentCtrl->getItemListRect().getWidth();
+ }
+ // all padding went to this widget, we're done
+ break;
+ }
+ }
+ else
+ {
+ // user growing column, need to take width from other columns
+ remaining_width += resize_buffer_amt;
+
+ if (columnp->getWidth() > 0)
+ {
+ columnp->setWidth(columnp->getWidth() - llmin(columnp->getWidth() - MIN_COLUMN_WIDTH, delta_width));
+ if (columnp->mRelWidth > 0.f)
+ {
+ columnp->mRelWidth = (F32)columnp->getWidth() / (F32)mColumn->mParentCtrl->getItemListRect().getWidth();
+ }
+ }
+
+ if (remaining_width >= 0)
+ {
+ // width sucked up from neighboring columns, done
+ break;
+ }
+ }
+ }
+ }
+
+ // clamp resize amount to maximum that can be absorbed by other columns
+ if (delta_width > 0)
+ {
+ delta_width += llmin(remaining_width, 0);
+ }
+
+ // propagate constrained delta_width to new width for this column
+ new_width = getRect().getWidth() + delta_width - mColumn->mParentCtrl->getColumnPadding();
+
+ // use requested width
+ mColumn->setWidth(new_width);
+
+ // update proportional spacing
+ if (mColumn->mRelWidth > 0.f)
+ {
+ mColumn->mRelWidth = (F32)new_width / (F32)mColumn->mParentCtrl->getItemListRect().getWidth();
+ }
+
+ // tell scroll list to layout columns again
+ // do immediate update to get proper feedback to resize handle
+ // which needs to know how far the resize actually went
+ mColumn->mParentCtrl->updateColumns();
+ }
+}
+
+void LLScrollColumnHeader::setHasResizableElement(BOOL resizable)
+{
+ if (mHasResizableElement != resizable)
+ {
+ mColumn->mParentCtrl->dirtyColumns();
+ mHasResizableElement = resizable;
+ }
+}
+
+void LLScrollColumnHeader::updateResizeBars()
+{
+ S32 num_resizable_columns = 0;
+ S32 col;
+ for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++)
+ {
+ LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
+ if (columnp->mHeader && columnp->mHeader->canResize())
+ {
+ num_resizable_columns++;
+ }
+ }
+
+ S32 num_resizers_enabled = 0;
+
+ // now enable/disable resize handles on resizable columns if we have at least two
+ for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++)
+ {
+ LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
+ if (!columnp->mHeader) continue;
+ BOOL enable = num_resizable_columns >= 2 && num_resizers_enabled < (num_resizable_columns - 1) && columnp->mHeader->canResize();
+ columnp->mHeader->enableResizeBar(enable);
+ if (enable)
+ {
+ num_resizers_enabled++;
+ }
+ }
+}
+
+void LLScrollColumnHeader::enableResizeBar(BOOL enable)
+{
+ mResizeBar->setEnabled(enable);
+}
+
+BOOL LLScrollColumnHeader::canResize()
+{
+ return getVisible() && (mHasResizableElement || mColumn->mDynamicWidth);
+}
+
+void LLScrollListColumn::SortNames::declareValues()
+{
+ declare("ascending", LLScrollListColumn::ASCENDING);
+ declare("descending", LLScrollListColumn::DESCENDING);
+}
+
+//
+// LLScrollListColumn
+//
+//static
+const LLScrollListColumn::Params& LLScrollListColumn::getDefaultParams()
+{
+ return LLUICtrlFactory::getDefaultParams<LLScrollListColumn>();
+}
+
+
+LLScrollListColumn::LLScrollListColumn(const Params& p, LLScrollListCtrl* parent)
+: mWidth(0),
+ mIndex (-1),
+ mParentCtrl(parent),
+ mName(p.name),
+ mLabel(p.header.label),
+ mHeader(NULL),
+ mMaxContentWidth(0),
+ mDynamicWidth(p.width.dynamic_width),
+ mRelWidth(p.width.relative_width),
+ mFontAlignment(p.halign),
+ mSortingColumn(p.sort_column)
+{
+ if (p.sort_ascending.isProvided())
+ {
+ mSortDirection = p.sort_ascending() ? ASCENDING : DESCENDING;
+ }
+ else
+ {
+ mSortDirection = p.sort_direction;
+ }
+
+ setWidth(p.width.pixel_width);
+}
+
+void LLScrollListColumn::setWidth(S32 width)
+{
+ if (!mDynamicWidth && mRelWidth <= 0.f)
+ {
+ mParentCtrl->updateStaticColumnWidth(this, width);
+ }
+ mWidth = width;
+}
diff --git a/indra/llui/llscrolllistcolumn.h b/indra/llui/llscrolllistcolumn.h
new file mode 100644
index 0000000000..5aef6e8e94
--- /dev/null
+++ b/indra/llui/llscrolllistcolumn.h
@@ -0,0 +1,178 @@
+/**
+ * @file llscrollcolumnheader.h
+ * @brief Scroll lists are composed of rows (items), each of which
+ * contains columns (cells).
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLSCROLLLISTCOLUMN_H
+#define LLSCROLLLISTCOLUMN_H
+
+#include "llrect.h"
+#include "lluistring.h"
+#include "llbutton.h"
+#include "llinitparam.h"
+
+class LLScrollListColumn;
+class LLResizeBar;
+class LLScrollListCtrl;
+
+class LLScrollColumnHeader : public LLButton
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLButton::Params>
+ {
+ Mandatory<LLScrollListColumn*> column;
+
+ Params();
+ };
+ LLScrollColumnHeader(const Params&);
+ ~LLScrollColumnHeader();
+
+ /*virtual*/ void draw();
+ /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
+
+ /*virtual*/ LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding);
+ /*virtual*/ void handleReshape(const LLRect& new_rect, bool by_user = false);
+
+ LLScrollListColumn* getColumn() { return mColumn; }
+ void setHasResizableElement(BOOL resizable);
+ void updateResizeBars();
+ BOOL canResize();
+ void enableResizeBar(BOOL enable);
+
+ void onClick(const LLSD& data);
+
+private:
+ LLScrollListColumn* mColumn;
+ LLResizeBar* mResizeBar;
+ BOOL mHasResizableElement;
+};
+
+/*
+ * A simple data class describing a column within a scroll list.
+ */
+class LLScrollListColumn
+{
+public:
+ typedef enum e_sort_direction
+ {
+ DESCENDING,
+ ASCENDING
+ } ESortDirection;
+
+ struct SortNames
+ : public LLInitParam::TypeValuesHelper<LLScrollListColumn::ESortDirection, SortNames>
+ {
+ static void declareValues();
+ };
+
+ struct Params : public LLInitParam::Block<Params>
+ {
+ Optional<std::string> name,
+ tool_tip;
+ Optional<std::string> sort_column;
+ Optional<ESortDirection, SortNames> sort_direction;
+ Optional<bool> sort_ascending;
+
+ struct Width : public LLInitParam::Choice<Width>
+ {
+ Alternative<bool> dynamic_width;
+ Alternative<S32> pixel_width;
+ Alternative<F32> relative_width;
+
+ Width()
+ : dynamic_width("dynamic_width", false),
+ pixel_width("width"),
+ relative_width("relative_width", -1.f)
+ {
+ addSynonym(relative_width, "relwidth");
+ }
+ };
+ Optional<Width> width;
+
+ // either an image or label is used in column header
+ struct Header : public LLInitParam::Choice<Header>
+ {
+ Alternative<std::string> label;
+ Alternative<LLUIImage*> image;
+
+ Header()
+ : label("label"),
+ image("image")
+ {}
+ };
+ Optional<Header> header;
+
+ Optional<LLFontGL::HAlign> halign;
+
+ Params()
+ : name("name"),
+ tool_tip("tool_tip"),
+ sort_column("sort_column"),
+ sort_direction("sort_direction"),
+ sort_ascending("sort_ascending", true),
+ halign("halign", LLFontGL::LEFT)
+ {
+ // default choice to "dynamic_width"
+ width.dynamic_width = true;
+
+ addSynonym(sort_column, "sort");
+ }
+ };
+
+ static const Params& getDefaultParams();
+
+ //NOTE: this is default constructible so we can store it in a map.
+ LLScrollListColumn(const Params& p = getDefaultParams(), LLScrollListCtrl* = NULL);
+
+ void setWidth(S32 width);
+ S32 getWidth() const { return mWidth; }
+
+public:
+ // Public data is fine so long as this remains a simple struct-like data class.
+ // If it ever gets any smarter than that, these should all become private
+ // with protected or public accessor methods added as needed. -MG
+ std::string mName;
+ std::string mSortingColumn;
+ ESortDirection mSortDirection;
+ LLUIString mLabel;
+ F32 mRelWidth;
+ BOOL mDynamicWidth;
+ S32 mMaxContentWidth;
+ S32 mIndex;
+ LLScrollListCtrl* mParentCtrl;
+ LLScrollColumnHeader* mHeader;
+ LLFontGL::HAlign mFontAlignment;
+
+private:
+ S32 mWidth;
+};
+
+#endif
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 5dd4e2d0ee..4e84013db0 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -1,6 +1,7 @@
/**
* @file llscrolllistctrl.cpp
- * @brief LLScrollListCtrl base class
+ * @brief Scroll lists are composed of rows (items), each of which
+ * contains columns (cells).
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
@@ -30,34 +31,42 @@
* $/LicenseInfo$
*/
-#include <algorithm>
-
#include "linden_common.h"
-#include "llstl.h"
-#include "llboost.h"
#include "llscrolllistctrl.h"
-#include "indra_constants.h"
+#include <algorithm>
+
+#include "llstl.h"
+#include "llboost.h"
+//#include "indra_constants.h"
#include "llcheckboxctrl.h"
#include "llclipboard.h"
#include "llfocusmgr.h"
-#include "llrender.h"
+#include "llgl.h" // LLGLSUIDefault()
+#include "lllocalcliprect.h"
+//#include "llrender.h"
#include "llresmgr.h"
#include "llscrollbar.h"
+#include "llscrolllistcell.h"
#include "llstring.h"
#include "llui.h"
#include "lluictrlfactory.h"
#include "llwindow.h"
#include "llcontrol.h"
#include "llkeyboard.h"
-#include "llresizebar.h"
+#include "llviewborder.h"
+#include "lltextbox.h"
+#include "llsdparam.h"
+#include "llcachename.h"
+#include "llmenugl.h"
+#include "llurlaction.h"
+#include "lltooltip.h"
-const S32 MIN_COLUMN_WIDTH = 20;
-const S32 LIST_SNAP_PADDING = 5;
+#include <boost/bind.hpp>
-static LLRegisterWidget<LLScrollListCtrl> r("scroll_list");
+static LLDefaultChildRegistry::Register<LLScrollListCtrl> r("scroll_list");
// local structures & classes.
struct SortScrollListItem
@@ -96,510 +105,95 @@ struct SortScrollListItem
const sort_order_t& mSortOrders;
};
-
-//
-// LLScrollListIcon
-//
-LLScrollListIcon::LLScrollListIcon(LLUIImagePtr icon, S32 width)
- : LLScrollListCell(width),
- mIcon(icon),
- mColor(LLColor4::white)
-{
-}
-
-LLScrollListIcon::LLScrollListIcon(const LLSD& value, S32 width)
- : LLScrollListCell(width),
- mColor(LLColor4::white)
-{
- setValue(value);
-}
-
-
-LLScrollListIcon::~LLScrollListIcon()
-{
-}
-
-void LLScrollListIcon::setValue(const LLSD& value)
-{
- if (value.isUUID())
- {
- // don't use default image specified by LLUUID::null, use no image in that case
- LLUUID image_id = value.asUUID();
- mIcon = image_id.notNull() ? LLUI::sImageProvider->getUIImageByID(image_id) : LLUIImagePtr(NULL);
- }
- else
- {
- std::string value_string = value.asString();
- if (LLUUID::validate(value_string))
- {
- setValue(LLUUID(value_string));
- }
- else if (!value_string.empty())
- {
- mIcon = LLUI::getUIImage(value.asString());
- }
- else
- {
- mIcon = NULL;
- }
- }
-}
-
-
-void LLScrollListIcon::setColor(const LLColor4& color)
-{
- mColor = color;
-}
-
-S32 LLScrollListIcon::getWidth() const
-{
- // if no specified fix width, use width of icon
- if (LLScrollListCell::getWidth() == 0 && mIcon.notNull())
- {
- return mIcon->getWidth();
- }
- return LLScrollListCell::getWidth();
-}
-
-
-void LLScrollListIcon::draw(const LLColor4& color, const LLColor4& highlight_color) const
-{
- if (mIcon)
- {
- mIcon->draw(0, 0, mColor);
- }
-}
-
-//
-// LLScrollListCheck
-//
-LLScrollListCheck::LLScrollListCheck(LLCheckBoxCtrl* check_box, S32 width)
-{
- mCheckBox = check_box;
- LLRect rect(mCheckBox->getRect());
- if (width)
- {
-
- rect.mRight = rect.mLeft + width;
- mCheckBox->setRect(rect);
- setWidth(width);
- }
- else
- {
- setWidth(rect.getWidth()); //check_box->getWidth();
- }
-}
-
-LLScrollListCheck::~LLScrollListCheck()
-{
- delete mCheckBox;
-}
-
-void LLScrollListCheck::draw(const LLColor4& color, const LLColor4& highlight_color) const
-{
- mCheckBox->draw();
-}
-
-BOOL LLScrollListCheck::handleClick()
-{
- if (mCheckBox->getEnabled())
- {
- mCheckBox->toggle();
- }
- // don't change selection when clicking on embedded checkbox
- return TRUE;
-}
-
-//
-// LLScrollListSeparator
-//
-LLScrollListSeparator::LLScrollListSeparator(S32 width) : LLScrollListCell(width)
-{
-}
-
-//virtual
-S32 LLScrollListSeparator::getHeight() const
-{
- return 5;
-}
-
-
-void LLScrollListSeparator::draw(const LLColor4& color, const LLColor4& highlight_color) const
-{
- //*FIXME: use dynamic item heights and make separators narrow, and inactive
- gl_line_2d(5, 8, llmax(5, getWidth() - 5), 8, color);
-}
-
-//
-// LLScrollListText
-//
-U32 LLScrollListText::sCount = 0;
-
-LLScrollListText::LLScrollListText( const std::string& text, const LLFontGL* font, S32 width, U8 font_style, LLFontGL::HAlign font_alignment, LLColor4& color, BOOL use_color, BOOL visible)
-: LLScrollListCell(width),
- mText( text ),
- mFont( font ),
- mColor(color),
- mUseColor(use_color),
- mFontStyle( font_style ),
- mFontAlignment( font_alignment ),
- mVisible( visible ),
- mHighlightCount( 0 ),
- mHighlightOffset( 0 )
-{
- sCount++;
-
- // initialize rounded rect image
- if (!mRoundedRectImage)
- {
- mRoundedRectImage = LLUI::sImageProvider->getUIImage("rounded_square.tga");
- }
-}
-//virtual
-void LLScrollListText::highlightText(S32 offset, S32 num_chars)
-{
- mHighlightOffset = offset;
- mHighlightCount = num_chars;
-}
-
-//virtual
-BOOL LLScrollListText::isText() const
-{
- return TRUE;
-}
-
-//virtual
-BOOL LLScrollListText::getVisible() const
-{
- return mVisible;
-}
-
-//virtual
-S32 LLScrollListText::getHeight() const
-{
- return llround(mFont->getLineHeight());
-}
-
-
-LLScrollListText::~LLScrollListText()
-{
- sCount--;
-}
-
-S32 LLScrollListText::getContentWidth() const
-{
- return mFont->getWidth(mText.getString());
-}
-
-
-void LLScrollListText::setColor(const LLColor4& color)
-{
- mColor = color;
- mUseColor = TRUE;
-}
-
-void LLScrollListText::setText(const LLStringExplicit& text)
-{
- mText = text;
-}
-
-//virtual
-void LLScrollListText::setValue(const LLSD& text)
-{
- setText(text.asString());
-}
-
-//virtual
-const LLSD LLScrollListText::getValue() const
-{
- return LLSD(mText.getString());
-}
-
-
-void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_color) const
-{
- LLColor4 display_color;
- if (mUseColor)
- {
- display_color = mColor;
- }
- else
- {
- display_color = color;
- }
-
- if (mHighlightCount > 0)
- {
- S32 left = 0;
- switch(mFontAlignment)
- {
- case LLFontGL::LEFT:
- left = mFont->getWidth(mText.getString(), 0, mHighlightOffset);
- break;
- case LLFontGL::RIGHT:
- left = getWidth() - mFont->getWidth(mText.getString(), mHighlightOffset, S32_MAX);
- break;
- case LLFontGL::HCENTER:
- left = (getWidth() - mFont->getWidth(mText.getString())) / 2;
- break;
- }
- LLRect highlight_rect(left - 2,
- llround(mFont->getLineHeight()) + 1,
- left + mFont->getWidth(mText.getString(), mHighlightOffset, mHighlightCount) + 1,
- 1);
- mRoundedRectImage->draw(highlight_rect, highlight_color);
- }
-
- // Try to draw the entire string
- F32 right_x;
- U32 string_chars = mText.length();
- F32 start_x = 0.f;
- switch(mFontAlignment)
- {
- case LLFontGL::LEFT:
- start_x = 0.f;
- break;
- case LLFontGL::RIGHT:
- start_x = (F32)getWidth();
- break;
- case LLFontGL::HCENTER:
- start_x = (F32)getWidth() * 0.5f;
- break;
- }
- mFont->render(mText.getWString(), 0,
- start_x, 2.f,
- display_color,
- mFontAlignment,
- LLFontGL::BOTTOM,
- mFontStyle,
- string_chars,
- getWidth(),
- &right_x,
- FALSE,
- TRUE);
-}
-
-LLScrollListDate::LLScrollListDate( const LLDate& date, const LLFontGL* font, S32 width, U8 font_style, LLFontGL::HAlign font_alignment, LLColor4& color, BOOL use_color, BOOL visible)
-: LLScrollListText(date.asRFC1123(), font, width, font_style, font_alignment, color, use_color, visible),
- mDate(date)
-{
-}
-
-void LLScrollListDate::setValue(const LLSD& value)
-{
- mDate = value.asDate();
- LLScrollListText::setValue(mDate.asRFC1123());
-}
-
-const LLSD LLScrollListDate::getValue() const
-{
- return mDate;
-}
-
-LLScrollListItem::~LLScrollListItem()
-{
- std::for_each(mColumns.begin(), mColumns.end(), DeletePointer());
-}
-
-void LLScrollListItem::setNumColumns(S32 columns)
-{
- S32 prev_columns = mColumns.size();
- if (columns < prev_columns)
- {
- std::for_each(mColumns.begin()+columns, mColumns.end(), DeletePointer());
- }
-
- mColumns.resize(columns);
-
- for (S32 col = prev_columns; col < columns; ++col)
- {
- mColumns[col] = NULL;
- }
-}
-
-void LLScrollListItem::setColumn( S32 column, LLScrollListCell *cell )
-{
- if (column < (S32)mColumns.size())
- {
- delete mColumns[column];
- mColumns[column] = cell;
- }
- else
- {
- llerrs << "LLScrollListItem::setColumn: bad column: " << column << llendl;
- }
-}
-
-std::string LLScrollListItem::getContentsCSV() const
-{
- std::string ret;
-
- S32 count = getNumColumns();
- for (S32 i=0; i<count; ++i)
- {
- ret += getColumn(i)->getValue().asString();
- if (i < count-1)
- {
- ret += ", ";
- }
- }
-
- return ret;
-}
-
-void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding)
-{
- // draw background rect
- LLRect bg_rect = rect;
- {
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.color4fv(bg_color.mV);
- gl_rect_2d( bg_rect );
- }
-
- S32 cur_x = rect.mLeft;
- S32 num_cols = getNumColumns();
- S32 cur_col = 0;
-
- for (LLScrollListCell* cell = getColumn(0); cur_col < num_cols; cell = getColumn(++cur_col))
- {
- // Two ways a cell could be hidden
- if (cell->getWidth() < 0
- || !cell->getVisible()) continue;
-
- LLUI::pushMatrix();
- {
- LLUI::translate((F32) cur_x, (F32) rect.mBottom, 0.0f);
-
- cell->draw( fg_color, highlight_color );
- }
- LLUI::popMatrix();
-
- cur_x += cell->getWidth() + column_padding;
- }
-}
-
-
-void LLScrollListItem::setEnabled(BOOL b)
-{
- mEnabled = b;
-}
-
-//---------------------------------------------------------------------------
-// LLScrollListItemComment
-//---------------------------------------------------------------------------
-LLScrollListItemComment::LLScrollListItemComment(const std::string& comment_string, const LLColor4& color)
-: LLScrollListItem(FALSE),
- mColor(color)
-{
- addColumn( comment_string, LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ) );
-}
-
-void LLScrollListItemComment::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding)
-{
- LLScrollListCell* cell = getColumn(0);
- if (cell)
- {
- // Two ways a cell could be hidden
- if (cell->getWidth() < 0
- || !cell->getVisible()) return;
-
- LLUI::pushMatrix();
- {
- LLUI::translate((F32)rect.mLeft, (F32)rect.mBottom, 0.0f);
-
- // force first cell to be width of entire item
- cell->setWidth(rect.getWidth());
- cell->draw( mColor, highlight_color );
- }
- LLUI::popMatrix();
- }
-}
-
-//---------------------------------------------------------------------------
-// LLScrollListItemSeparator
-//---------------------------------------------------------------------------
-LLScrollListItemSeparator::LLScrollListItemSeparator()
-: LLScrollListItem(FALSE)
-{
- LLScrollListSeparator* cell = new LLScrollListSeparator(0);
- setNumColumns(1);
- setColumn(0, cell);
-}
-
-void LLScrollListItemSeparator::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding)
-{
- //TODO* move LLScrollListSeparator::draw into here and get rid of it
- LLScrollListCell* cell = getColumn(0);
- if (cell)
- {
- // Two ways a cell could be hidden
- if (cell->getWidth() < 0
- || !cell->getVisible()) return;
-
- LLUI::pushMatrix();
- {
- LLUI::translate((F32)rect.mLeft, (F32)rect.mBottom, 0.0f);
-
- // force first cell to be width of entire item
- cell->setWidth(rect.getWidth());
- cell->draw( fg_color, highlight_color );
- }
- LLUI::popMatrix();
- }
-}
-
//---------------------------------------------------------------------------
// LLScrollListCtrl
//---------------------------------------------------------------------------
-LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect,
- void (*commit_callback)(LLUICtrl* ctrl, void* userdata),
- void* callback_user_data,
- BOOL allow_multiple_selection,
- BOOL show_border
- )
- : LLUICtrl(name, rect, TRUE, commit_callback, callback_user_data),
+LLScrollListCtrl::Contents::Contents()
+: columns("column"),
+ rows("row")
+{
+ addSynonym(columns, "columns");
+ addSynonym(rows, "rows");
+}
+
+LLScrollListCtrl::Params::Params()
+: multi_select("multi_select", false),
+ has_border("draw_border"),
+ draw_heading("draw_heading"),
+ search_column("search_column", 0),
+ sort_column("sort_column", -1),
+ sort_ascending("sort_ascending", true),
+ commit_on_keyboard_movement("commit_on_keyboard_movement", true),
+ heading_height("heading_height"),
+ page_lines("page_lines", 0),
+ background_visible("background_visible"),
+ draw_stripes("draw_stripes"),
+ column_padding("column_padding"),
+ fg_unselected_color("fg_unselected_color"),
+ fg_selected_color("fg_selected_color"),
+ bg_selected_color("bg_selected_color"),
+ fg_disable_color("fg_disable_color"),
+ bg_writeable_color("bg_writeable_color"),
+ bg_readonly_color("bg_readonly_color"),
+ bg_stripe_color("bg_stripe_color"),
+ hovered_color("hovered_color"),
+ highlighted_color("highlighted_color"),
+ contents(""),
+ scroll_bar_bg_visible("scroll_bar_bg_visible"),
+ scroll_bar_bg_color("scroll_bar_bg_color")
+ , border("border")
+{
+ name = "scroll_list";
+ mouse_opaque = true;
+}
+
+LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
+: LLUICtrl(p),
mLineHeight(0),
mScrollLines(0),
- mPageLines(0),
- mHeadingHeight(20),
+ mPageLines(p.page_lines),
mMaxSelectable(0),
- mAllowMultipleSelection( allow_multiple_selection ),
mAllowKeyboardMovement(TRUE),
- mCommitOnKeyboardMovement(TRUE),
+ mCommitOnKeyboardMovement(p.commit_on_keyboard_movement),
mCommitOnSelectionChange(FALSE),
mSelectionChanged(FALSE),
mNeedsScroll(FALSE),
mCanSelect(TRUE),
- mDisplayColumnHeaders(FALSE),
mColumnsDirty(FALSE),
mMaxItemCount(INT_MAX),
mMaxContentWidth(0),
- mBackgroundVisible( TRUE ),
- mDrawStripes(TRUE),
- mBgWriteableColor( LLUI::sColorsGroup->getColor( "ScrollBgWriteableColor" ) ),
- mBgReadOnlyColor( LLUI::sColorsGroup->getColor( "ScrollBgReadOnlyColor" ) ),
- mBgSelectedColor( LLUI::sColorsGroup->getColor("ScrollSelectedBGColor") ),
- mBgStripeColor( LLUI::sColorsGroup->getColor("ScrollBGStripeColor") ),
- mFgSelectedColor( LLUI::sColorsGroup->getColor("ScrollSelectedFGColor") ),
- mFgUnselectedColor( LLUI::sColorsGroup->getColor("ScrollUnselectedColor") ),
- mFgDisabledColor( LLUI::sColorsGroup->getColor("ScrollDisabledColor") ),
- mHighlightedColor( LLUI::sColorsGroup->getColor("ScrollHighlightedColor") ),
mBorderThickness( 2 ),
mOnDoubleClickCallback( NULL ),
mOnMaximumSelectCallback( NULL ),
mOnSortChangedCallback( NULL ),
mHighlightedItem(-1),
mBorder(NULL),
- mSearchColumn(0),
+ mPopupMenu(NULL),
mNumDynamicWidthColumns(0),
mTotalStaticColumnWidth(0),
mTotalColumnPadding(0),
- mSorted(TRUE),
+ mSorted(false),
mDirty(FALSE),
mOriginalSelection(-1),
- mDrewSelected(FALSE)
+ mLastSelected(NULL),
+ mHeadingHeight(p.heading_height),
+ mAllowMultipleSelection(p.multi_select),
+ mDisplayColumnHeaders(p.draw_heading),
+ mBackgroundVisible(p.background_visible),
+ mDrawStripes(p.draw_stripes),
+ mBgWriteableColor(p.bg_writeable_color()),
+ mBgReadOnlyColor(p.bg_readonly_color()),
+ mBgSelectedColor(p.bg_selected_color()),
+ mBgStripeColor(p.bg_stripe_color()),
+ mFgSelectedColor(p.fg_selected_color()),
+ mFgUnselectedColor(p.fg_unselected_color()),
+ mFgDisabledColor(p.fg_disable_color()),
+ mHighlightedColor(p.highlighted_color()),
+ mHoveredColor(p.hovered_color()),
+ mSearchColumn(p.search_column),
+ mColumnPadding(p.column_padding),
+ mContextMenuType(MENU_NONE)
{
mItemListRect.setOriginAndSize(
mBorderThickness,
@@ -609,40 +203,74 @@ LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect,
updateLineHeight();
- mPageLines = mLineHeight? (mItemListRect.getHeight()) / mLineHeight : 0;
-
// Init the scrollbar
+ static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+
LLRect scroll_rect;
scroll_rect.setOriginAndSize(
- getRect().getWidth() - mBorderThickness - SCROLLBAR_SIZE,
+ getRect().getWidth() - mBorderThickness - scrollbar_size,
mItemListRect.mBottom,
- SCROLLBAR_SIZE,
+ scrollbar_size,
mItemListRect.getHeight());
- mScrollbar = new LLScrollbar( std::string("Scrollbar"), scroll_rect,
- LLScrollbar::VERTICAL,
- getItemCount(),
- mScrollLines,
- mPageLines,
- &LLScrollListCtrl::onScrollChange, this );
- mScrollbar->setFollowsRight();
- mScrollbar->setFollowsTop();
- mScrollbar->setFollowsBottom();
- mScrollbar->setEnabled( TRUE );
- // scrollbar is visible only when needed
- mScrollbar->setVisible(FALSE);
+
+ LLScrollbar::Params sbparams;
+ sbparams.name("Scrollbar");
+ sbparams.rect(scroll_rect);
+ sbparams.orientation(LLScrollbar::VERTICAL);
+ sbparams.doc_size(getItemCount());
+ sbparams.doc_pos(mScrollLines);
+ sbparams.page_size( getLinesPerPage() );
+ sbparams.change_callback(boost::bind(&LLScrollListCtrl::onScrollChange, this, _1, _2));
+ sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
+ sbparams.visible(false);
+ sbparams.bg_visible(p.scroll_bar_bg_visible);
+ sbparams.bg_color(p.scroll_bar_bg_color);
+ mScrollbar = LLUICtrlFactory::create<LLScrollbar> (sbparams);
addChild(mScrollbar);
// Border
- if (show_border)
+ if (p.has_border)
{
- LLRect border_rect( 0, getRect().getHeight(), getRect().getWidth(), 0 );
- mBorder = new LLViewBorder( std::string("dlg border"), border_rect, LLViewBorder::BEVEL_IN, LLViewBorder::STYLE_LINE, 1 );
+ LLRect border_rect = getLocalRect();
+ LLViewBorder::Params params = p.border;
+ params.rect(border_rect);
+ mBorder = LLUICtrlFactory::create<LLViewBorder> (params);
addChild(mBorder);
}
- mColumnPadding = 5;
+ // set border *after* rect is fully initialized
+ if (mBorder)
+ {
+ mBorder->setRect(getLocalRect());
+ mBorder->reshape(getRect().getWidth(), getRect().getHeight());
+ }
- mLastSelected = NULL;
+ if (p.sort_column >= 0)
+ {
+ sortByColumnIndex(p.sort_column, p.sort_ascending);
+ }
+
+
+ for (LLInitParam::ParamIterator<LLScrollListColumn::Params>::const_iterator row_it = p.contents.columns().begin();
+ row_it != p.contents.columns().end();
+ ++row_it)
+ {
+ addColumn(*row_it);
+ }
+
+ for (LLInitParam::ParamIterator<LLScrollListItem::Params>::const_iterator row_it = p.contents.rows().begin();
+ row_it != p.contents.rows().end();
+ ++row_it)
+ {
+ addRow(*row_it);
+ }
+
+ LLTextBox::Params text_p;
+ text_p.name("comment_text");
+ text_p.border_visible(false);
+ text_p.rect(mItemListRect);
+ text_p.follows.flags(FOLLOWS_ALL);
+ addChild(LLUICtrlFactory::create<LLTextBox>(text_p));
}
S32 LLScrollListCtrl::getSearchColumn()
@@ -666,6 +294,18 @@ S32 LLScrollListCtrl::getSearchColumn()
}
return llclamp(mSearchColumn, 0, getNumColumns());
}
+/*virtual*/
+bool LLScrollListCtrl::preProcessChildNode(LLXMLNodePtr child)
+{
+ if (child->hasName("column") || child->hasName("row"))
+ {
+ return true; // skip
+ }
+ else
+ {
+ return false;
+ }
+}
LLScrollListCtrl::~LLScrollListCtrl()
{
@@ -746,6 +386,10 @@ std::vector<LLScrollListItem*> LLScrollListCtrl::getAllSelected() const
S32 LLScrollListCtrl::getFirstSelectedIndex() const
{
S32 CurSelectedIndex = 0;
+
+ // make sure sort is up to date before returning an index
+ updateSort();
+
item_list::const_iterator iter;
for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
{
@@ -818,6 +462,7 @@ void LLScrollListCtrl::reshape( S32 width, S32 height, BOOL called_from_parent )
void LLScrollListCtrl::updateLayout()
{
+ static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
// reserve room for column headers, if needed
S32 heading_size = (mDisplayColumnHeaders ? mHeadingHeight : 0);
mItemListRect.setOriginAndSize(
@@ -826,23 +471,21 @@ void LLScrollListCtrl::updateLayout()
getRect().getWidth() - 2 * mBorderThickness,
getRect().getHeight() - (2 * mBorderThickness ) - heading_size );
+ getChildView("comment_text")->setShape(mItemListRect);
+
// how many lines of content in a single "page"
- mPageLines = mLineHeight? mItemListRect.getHeight() / mLineHeight : 0;
- BOOL scrollbar_visible = getItemCount() > mPageLines;
+ S32 page_lines = getLinesPerPage();
+
+ BOOL scrollbar_visible = mLineHeight * getItemCount() > mItemListRect.getHeight();
if (scrollbar_visible)
{
// provide space on the right for scrollbar
- mItemListRect.mRight = getRect().getWidth() - mBorderThickness - SCROLLBAR_SIZE;
- }
-
- // don't allow scrolling off bottom
- if (mScrollLines + mPageLines > getItemCount())
- {
- setScrollPos(llmax(0, getItemCount() - mPageLines));
+ mItemListRect.mRight = getRect().getWidth() - mBorderThickness - scrollbar_size;
}
- mScrollbar->reshape(SCROLLBAR_SIZE, mItemListRect.getHeight() + (mDisplayColumnHeaders ? mHeadingHeight : 0));
- mScrollbar->setPageSize( mPageLines );
+ mScrollbar->setOrigin(getRect().getWidth() - mBorderThickness - scrollbar_size, mItemListRect.mBottom);
+ mScrollbar->reshape(scrollbar_size, mItemListRect.getHeight() + (mDisplayColumnHeaders ? mHeadingHeight : 0));
+ mScrollbar->setPageSize(page_lines);
mScrollbar->setDocSize( getItemCount() );
mScrollbar->setVisible(scrollbar_visible);
@@ -854,6 +497,9 @@ void LLScrollListCtrl::updateLayout()
void LLScrollListCtrl::fitContents(S32 max_width, S32 max_height)
{
S32 height = llmin( getRequiredRect().getHeight(), max_height );
+ if(mPageLines)
+ height = llmin( mPageLines * mLineHeight + (mDisplayColumnHeaders ? mHeadingHeight : 0), height );
+
S32 width = getRect().getWidth();
reshape( width, height );
@@ -881,7 +527,7 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r
{
case ADD_TOP:
mItemList.push_front(item);
- setSorted(FALSE);
+ setNeedsSort();
break;
case ADD_SORTED:
@@ -898,29 +544,29 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r
// ADD_SORTED just sorts by first column...
// this might not match user sort criteria, so flag list as being in unsorted state
- setSorted(FALSE);
+ setNeedsSort();
break;
}
case ADD_BOTTOM:
mItemList.push_back(item);
- setSorted(FALSE);
+ setNeedsSort();
break;
default:
llassert(0);
mItemList.push_back(item);
- setSorted(FALSE);
+ setNeedsSort();
break;
}
// create new column on demand
if (mColumns.empty() && requires_column)
{
- LLSD new_column;
- new_column["name"] = "default_column";
- new_column["label"] = "";
- new_column["dynamicwidth"] = TRUE;
- addColumn(new_column);
+ LLScrollListColumn::Params col_params;
+ col_params.name = "default_column";
+ col_params.header.label = "";
+ col_params.width.dynamic_width = true;
+ addColumn(col_params);
}
updateLineHeightInsert(item);
@@ -1017,7 +663,7 @@ void LLScrollListCtrl::updateColumns()
// update column headers
std::vector<LLScrollListColumn*>::iterator column_ordered_it;
S32 left = mItemListRect.mLeft;
- LLColumnHeader* last_header = NULL;
+ LLScrollColumnHeader* last_header = NULL;
for (column_ordered_it = mColumnsIndexed.begin(); column_ordered_it != mColumnsIndexed.end(); ++column_ordered_it)
{
if ((*column_ordered_it)->getWidth() < 0)
@@ -1052,7 +698,7 @@ void LLScrollListCtrl::updateColumns()
}
// expand last column header we encountered to full list width
- if (last_header && last_header->canResize())
+ if (last_header)
{
S32 new_width = llmax(0, mItemListRect.mRight - last_header->getRect().mLeft);
last_header->reshape(new_width, last_header->getRect().getHeight());
@@ -1077,13 +723,6 @@ void LLScrollListCtrl::updateColumns()
}
-void LLScrollListCtrl::setDisplayHeading(BOOL display)
-{
- mDisplayColumnHeaders = display;
-
- updateLayout();
-}
-
void LLScrollListCtrl::setHeadingHeight(S32 heading_height)
{
mHeadingHeight = heading_height;
@@ -1091,6 +730,12 @@ void LLScrollListCtrl::setHeadingHeight(S32 heading_height)
updateLayout();
}
+void LLScrollListCtrl::setPageLines(S32 new_page_lines)
+{
+ mPageLines = new_page_lines;
+
+ updateLayout();
+}
BOOL LLScrollListCtrl::selectFirstItem()
{
@@ -1140,6 +785,9 @@ BOOL LLScrollListCtrl::selectItemRange( S32 first_index, S32 last_index )
return FALSE;
}
+ // make sure sort is up to date
+ updateSort();
+
S32 listlen = (S32)mItemList.size();
first_index = llclamp(first_index, 0, listlen-1);
@@ -1193,6 +841,7 @@ void LLScrollListCtrl::swapWithNext(S32 index)
// At end of list, doesn't do anything
return;
}
+ updateSort();
LLScrollListItem *cur_itemp = mItemList[index];
mItemList[index] = mItemList[index + 1];
mItemList[index + 1] = cur_itemp;
@@ -1206,6 +855,7 @@ void LLScrollListCtrl::swapWithPrevious(S32 index)
// At beginning of list, don't do anything
}
+ updateSort();
LLScrollListItem *cur_itemp = mItemList[index];
mItemList[index] = mItemList[index - 1];
mItemList[index - 1] = cur_itemp;
@@ -1219,6 +869,8 @@ void LLScrollListCtrl::deleteSingleItem(S32 target_index)
return;
}
+ updateSort();
+
LLScrollListItem *itemp;
itemp = mItemList[target_index];
if (itemp == mLastSelected)
@@ -1275,7 +927,15 @@ void LLScrollListCtrl::deleteSelectedItems()
dirtyColumns();
}
-void LLScrollListCtrl::highlightNthItem(S32 target_index)
+void LLScrollListCtrl::clearHighlightedItems()
+{
+ for (item_list::iterator iter = mItemList.begin(); iter != mItemList.end(); ++iter)
+ {
+ (*iter)->setHighlighted(false);
+ }
+}
+
+void LLScrollListCtrl::mouseOverHighlightNthItem(S32 target_index)
{
if (mHighlightedItem != target_index)
{
@@ -1283,14 +943,14 @@ void LLScrollListCtrl::highlightNthItem(S32 target_index)
}
}
-S32 LLScrollListCtrl::selectMultiple( LLDynamicArray<LLUUID> ids )
+S32 LLScrollListCtrl::selectMultiple( std::vector<LLUUID> ids )
{
item_list::iterator iter;
S32 count = 0;
for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
{
LLScrollListItem* item = *iter;
- LLDynamicArray<LLUUID>::iterator iditr;
+ std::vector<LLUUID>::iterator iditr;
for(iditr = ids.begin(); iditr != ids.end(); ++iditr)
{
if (item->getEnabled() && (item->getUUID() == (*iditr)))
@@ -1312,6 +972,8 @@ S32 LLScrollListCtrl::selectMultiple( LLDynamicArray<LLUUID> ids )
S32 LLScrollListCtrl::getItemIndex( LLScrollListItem* target_item ) const
{
+ updateSort();
+
S32 index = 0;
item_list::const_iterator iter;
for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
@@ -1328,6 +990,8 @@ S32 LLScrollListCtrl::getItemIndex( LLScrollListItem* target_item ) const
S32 LLScrollListCtrl::getItemIndex( const LLUUID& target_id ) const
{
+ updateSort();
+
S32 index = 0;
item_list::const_iterator iter;
for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
@@ -1353,6 +1017,8 @@ void LLScrollListCtrl::selectPrevItem( BOOL extend_selection)
}
else
{
+ updateSort();
+
item_list::iterator iter;
for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
{
@@ -1395,6 +1061,8 @@ void LLScrollListCtrl::selectNextItem( BOOL extend_selection)
}
else
{
+ updateSort();
+
item_list::reverse_iterator iter;
for (iter = mItemList.rbegin(); iter != mItemList.rend(); iter++)
{
@@ -1446,35 +1114,51 @@ void LLScrollListCtrl::deselectAllItems(BOOL no_commit_on_change)
///////////////////////////////////////////////////////////////////////////////////////////////////
// Use this to add comment text such as "Searching", which ignores column settings of list
-LLScrollListItem* LLScrollListCtrl::addCommentText(const std::string& comment_text, EAddPosition pos)
+void LLScrollListCtrl::setCommentText(const std::string& comment_text)
{
- LLScrollListItem* item = NULL;
- if (getItemCount() < mMaxItemCount)
- {
- // always draw comment text with "enabled" color
- item = new LLScrollListItemComment( comment_text, mFgUnselectedColor );
- addItem( item, pos, FALSE );
- }
- return item;
+ getChild<LLTextBox>("comment_text")->setValue(comment_text);
}
LLScrollListItem* LLScrollListCtrl::addSeparator(EAddPosition pos)
{
- LLScrollListItem* item = new LLScrollListItemSeparator();
- addItem(item, pos, FALSE);
- return item;
+ LLScrollListItem::Params separator_params;
+ separator_params.enabled(false);
+ LLScrollListCell::Params column_params;
+ column_params.type = "icon";
+ column_params.value = "menu_separator";
+ column_params.color = LLColor4(0.f, 0.f, 0.f, 0.7f);
+ column_params.font_halign = LLFontGL::HCENTER;
+ separator_params.columns.add(column_params);
+ return addRow( separator_params, pos );
}
// Selects first enabled item of the given name.
// Returns false if item not found.
+// Calls getItemByLabel in order to combine functionality
BOOL LLScrollListCtrl::selectItemByLabel(const std::string& label, BOOL case_sensitive)
{
- // ensure that no stale items are selected, even if we don't find a match
- deselectAllItems(TRUE);
- //RN: assume no empty items
- if (label.empty())
+ deselectAllItems(TRUE); // ensure that no stale items are selected, even if we don't find a match
+ LLScrollListItem* item = getItemByLabel(label, case_sensitive);
+
+ bool found = NULL != item;
+ if(found)
{
- return FALSE;
+ selectItem(item);
+ }
+
+ if (mCommitOnSelectionChange)
+ {
+ commitIfChanged();
+ }
+
+ return found;
+}
+
+LLScrollListItem* LLScrollListCtrl::getItemByLabel(const std::string& label, BOOL case_sensitive, S32 column)
+{
+ if (label.empty()) //RN: assume no empty items
+ {
+ return NULL;
}
std::string target_text = label;
@@ -1483,34 +1167,21 @@ BOOL LLScrollListCtrl::selectItemByLabel(const std::string& label, BOOL case_sen
LLStringUtil::toLower(target_text);
}
- BOOL found = FALSE;
-
item_list::iterator iter;
- S32 index = 0;
for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
{
LLScrollListItem* item = *iter;
- // Only select enabled items with matching names
- std::string item_text = item->getColumn(0)->getValue().asString();
+ std::string item_text = item->getColumn(column)->getValue().asString(); // Only select enabled items with matching names
if (!case_sensitive)
{
LLStringUtil::toLower(item_text);
}
- BOOL select = !found && item->getEnabled() && item_text == target_text;
- if (select)
+ if(item_text == target_text)
{
- selectItem(item);
+ return item;
}
- found = found || select;
- index++;
}
-
- if (mCommitOnSelectionChange)
- {
- commitIfChanged();
- }
-
- return found;
+ return NULL;
}
@@ -1612,16 +1283,18 @@ const std::string LLScrollListCtrl::getSelectedItemLabel(S32 column) const
// "StringUUID" interface: use this when you're creating a list that contains non-unique strings each of which
// has an associated, unique UUID, and only one of which can be selected at a time.
-LLScrollListItem* LLScrollListCtrl::addStringUUIDItem(const std::string& item_text, const LLUUID& id, EAddPosition pos, BOOL enabled, S32 column_width)
+LLScrollListItem* LLScrollListCtrl::addStringUUIDItem(const std::string& item_text, const LLUUID& id, EAddPosition pos, BOOL enabled)
{
- LLScrollListItem* item = NULL;
if (getItemCount() < mMaxItemCount)
{
- item = new LLScrollListItem( enabled, NULL, id );
- item->addColumn(item_text, LLResMgr::getInstance()->getRes(LLFONT_SANSSERIF_SMALL), column_width);
- addItem( item, pos );
+ LLScrollListItem::Params item_p;
+ item_p.enabled(enabled);
+ item_p.value(id);
+ item_p.columns.add().value(item_text).type("text");
+
+ return addRow( item_p, pos );
}
- return item;
+ return NULL;
}
// Select the line or lines that match this UUID
@@ -1709,7 +1382,7 @@ void LLScrollListCtrl::drawItems()
S32 y = mItemListRect.mTop - mLineHeight;
// allow for partial line at bottom
- S32 num_page_lines = mPageLines + 1;
+ S32 num_page_lines = getLinesPerPage();
LLRect item_rect;
@@ -1720,13 +1393,11 @@ void LLScrollListCtrl::drawItems()
S32 cur_y = y;
- mDrewSelected = FALSE;
-
S32 line = 0;
S32 max_columns = 0;
LLColor4 highlight_color = LLColor4::white;
- F32 type_ahead_timeout = LLUI::sConfigGroup->getF32("TypeAheadTimeout");
+ static LLUICachedControl<F32> type_ahead_timeout ("TypeAheadTimeout", 0);
highlight_color.mV[VALPHA] = clamp_rescale(mSearchTimer.getElapsedTimeF32(), type_ahead_timeout * 0.7f, type_ahead_timeout, 0.4f, 0.f);
item_list::iterator iter;
@@ -1739,14 +1410,10 @@ void LLScrollListCtrl::drawItems()
cur_y,
mItemListRect.getWidth(),
mLineHeight );
+ item->setRect(item_rect);
//llinfos << item_rect.getWidth() << llendl;
- if (item->getSelected())
- {
- mDrewSelected = TRUE;
- }
-
max_columns = llmax(max_columns, item->getNumColumns());
LLColor4 fg_color;
@@ -1754,27 +1421,46 @@ void LLScrollListCtrl::drawItems()
if( mScrollLines <= line && line < mScrollLines + num_page_lines )
{
- fg_color = (item->getEnabled() ? mFgUnselectedColor : mFgDisabledColor);
+ fg_color = (item->getEnabled() ? mFgUnselectedColor.get() : mFgDisabledColor.get());
if( item->getSelected() && mCanSelect)
{
- bg_color = mBgSelectedColor;
- fg_color = (item->getEnabled() ? mFgSelectedColor : mFgDisabledColor);
+ if(item->getHighlighted()) // if it's highlighted, average the colors
+ {
+ bg_color = lerp(mBgSelectedColor.get(), mHighlightedColor.get(), 0.5f);
+ }
+ else // otherwise just select-highlight it
+ {
+ bg_color = mBgSelectedColor.get();
+ }
+
+ fg_color = (item->getEnabled() ? mFgSelectedColor.get() : mFgDisabledColor.get());
}
else if (mHighlightedItem == line && mCanSelect)
{
- bg_color = mHighlightedColor;
+ if(item->getHighlighted()) // if it's highlighted, average the colors
+ {
+ bg_color = lerp(mHoveredColor.get(), mHighlightedColor.get(), 0.5f);
+ }
+ else // otherwise just hover-highlight it
+ {
+ bg_color = mHoveredColor.get();
+ }
+ }
+ else if (item->getHighlighted())
+ {
+ bg_color = mHighlightedColor.get();
}
else
{
if (mDrawStripes && (line % 2 == 0) && (max_columns > 1))
{
- bg_color = mBgStripeColor;
+ bg_color = mBgStripeColor.get();
}
}
if (!item->getEnabled())
{
- bg_color = mBgReadOnlyColor;
+ bg_color = mBgReadOnlyColor.get();
}
item->draw(item_rect, fg_color, bg_color, highlight_color, mColumnPadding);
@@ -1792,10 +1478,7 @@ void LLScrollListCtrl::draw()
LLLocalClipRect clip(getLocalRect());
// if user specifies sort, make sure it is maintained
- if (needsSorting() && !isSorted())
- {
- sortItems();
- }
+ updateSort();
if (mNeedsScroll)
{
@@ -1807,8 +1490,7 @@ void LLScrollListCtrl::draw()
if (mBackgroundVisible)
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.color4fv( getEnabled() ? mBgWriteableColor.mV : mBgReadOnlyColor.mV );
- gl_rect_2d(background);
+ gl_rect_2d(background, getEnabled() ? mBgWriteableColor.get() : mBgReadOnlyColor.get() );
}
if (mColumnsDirty)
@@ -1817,11 +1499,13 @@ void LLScrollListCtrl::draw()
mColumnsDirty = FALSE;
}
+ getChildView("comment_text")->setVisible(mItemList.empty());
+
drawItems();
if (mBorder)
{
- mBorder->setKeyboardFocusHighlight(gFocusMgr.getKeyboardFocus() == this);
+ mBorder->setKeyboardFocusHighlight(hasFocus());
}
LLUICtrl::draw();
@@ -1842,7 +1526,19 @@ BOOL LLScrollListCtrl::handleScrollWheel(S32 x, S32 y, S32 clicks)
return handled;
}
-BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
+// *NOTE: Requires a valid row_index and column_index
+LLRect LLScrollListCtrl::getCellRect(S32 row_index, S32 column_index)
+{
+ LLRect cell_rect;
+ S32 rect_left = getColumnOffsetFromIndex(column_index) + mItemListRect.mLeft;
+ S32 rect_bottom = getRowOffsetFromIndex(row_index);
+ LLScrollListColumn* columnp = getColumn(column_index);
+ cell_rect.setOriginAndSize(rect_left, rect_bottom,
+ rect_left + columnp->getWidth(), mLineHeight);
+ return cell_rect;
+}
+
+BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, MASK mask)
{
S32 column_index = getColumnIndexFromOffset(x);
LLScrollListColumn* columnp = getColumn(column_index);
@@ -1856,34 +1552,32 @@ BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sti
{
LLScrollListCell* hit_cell = hit_item->getColumn(column_index);
if (!hit_cell) return FALSE;
- //S32 cell_required_width = hit_cell->getContentWidth();
if (hit_cell
- && hit_cell->isText())
+ && hit_cell->isText()
+ && hit_cell->needsToolTip())
{
-
- S32 rect_left = getColumnOffsetFromIndex(column_index) + mItemListRect.mLeft;
- S32 rect_bottom = getRowOffsetFromIndex(getItemIndex(hit_item));
- LLRect cell_rect;
- cell_rect.setOriginAndSize(rect_left, rect_bottom, rect_left + columnp->getWidth(), mLineHeight);
+ S32 row_index = getItemIndex(hit_item);
+ LLRect cell_rect = getCellRect(row_index, column_index);
// Convert rect local to screen coordinates
- localPointToScreen(
- cell_rect.mLeft, cell_rect.mBottom,
- &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
- localPointToScreen(
- cell_rect.mRight, cell_rect.mTop,
- &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) );
+ LLRect sticky_rect;
+ localRectToScreen(cell_rect, &sticky_rect);
- msg = hit_cell->getValue().asString();
+ // display tooltip exactly over original cell, in same font
+ LLToolTipMgr::instance().show(LLToolTip::Params()
+ .message(hit_cell->getToolTip())
+ .font(LLFontGL::getFontSansSerifSmall())
+ .pos(LLCoordGL(sticky_rect.mLeft - 5, sticky_rect.mTop + 6))
+ .delay_time(0.2f)
+ .sticky_rect(sticky_rect));
}
handled = TRUE;
}
// otherwise, look for a tooltip associated with this column
- LLColumnHeader* headerp = columnp->mHeader;
+ LLScrollColumnHeader* headerp = columnp->mHeader;
if (headerp && !handled)
{
- headerp->handleToolTip(x, y, msg, sticky_rect_screen);
- handled = !msg.empty();
+ handled = headerp->handleToolTip(x, y, mask);
}
return handled;
@@ -1922,7 +1616,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
{
if(mOnMaximumSelectCallback)
{
- mOnMaximumSelectCallback(mCallbackUserData);
+ mOnMaximumSelectCallback();
}
break;
}
@@ -1960,7 +1654,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
{
if(mOnMaximumSelectCallback)
{
- mOnMaximumSelectCallback(mCallbackUserData);
+ mOnMaximumSelectCallback();
}
}
}
@@ -2014,7 +1708,7 @@ BOOL LLScrollListCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
}
BOOL LLScrollListCtrl::handleMouseUp(S32 x, S32 y, MASK mask)
-{
+{
if (hasMouseCapture())
{
// release mouse capture immediately so
@@ -2038,6 +1732,72 @@ BOOL LLScrollListCtrl::handleMouseUp(S32 x, S32 y, MASK mask)
return LLUICtrl::handleMouseUp(x, y, mask);
}
+// virtual
+BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ LLScrollListItem *item = hitItem(x, y);
+ if (item)
+ {
+ // check to see if we have a UUID for this row
+ std::string id = item->getValue().asString();
+ LLUUID uuid(id);
+ if (! uuid.isNull() && mContextMenuType != MENU_NONE)
+ {
+ // set up the callbacks for all of the avatar/group menu items
+ // (N.B. callbacks don't take const refs as id is local scope)
+ bool is_group = (mContextMenuType == MENU_GROUP);
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("Url.Execute", boost::bind(&LLScrollListCtrl::showNameDetails, id, is_group));
+ registrar.add("Url.CopyLabel", boost::bind(&LLScrollListCtrl::copyNameToClipboard, id, is_group));
+ registrar.add("Url.CopyUrl", boost::bind(&LLScrollListCtrl::copySLURLToClipboard, id, is_group));
+
+ // create the context menu from the XUI file and display it
+ std::string menu_name = is_group ? "menu_url_group.xml" : "menu_url_agent.xml";
+ delete mPopupMenu;
+ mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
+ menu_name, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
+ if (mPopupMenu)
+ {
+ mPopupMenu->show(x, y);
+ LLMenuGL::showPopup(this, mPopupMenu, x, y);
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+void LLScrollListCtrl::showNameDetails(std::string id, bool is_group)
+{
+ // show the resident's profile or the group profile
+ std::string sltype = is_group ? "group" : "agent";
+ std::string slurl = "secondlife:///app/" + sltype + "/" + id + "/about";
+ LLUrlAction::clickAction(slurl);
+}
+
+void LLScrollListCtrl::copyNameToClipboard(std::string id, bool is_group)
+{
+ // copy the name of the avatar or group to the clipboard
+ std::string name;
+ if (is_group)
+ {
+ gCacheName->getGroupName(LLUUID(id), name);
+ }
+ else
+ {
+ gCacheName->getFullName(LLUUID(id), name);
+ }
+ LLUrlAction::copyURLToClipboard(name);
+}
+
+void LLScrollListCtrl::copySLURLToClipboard(std::string id, bool is_group)
+{
+ // copy a SLURL for the avatar or group to the clipboard
+ std::string sltype = is_group ? "group" : "agent";
+ std::string slurl = "secondlife:///app/" + sltype + "/" + id + "/about";
+ LLUrlAction::copyURLToClipboard(slurl);
+}
+
BOOL LLScrollListCtrl::handleDoubleClick(S32 x, S32 y, MASK mask)
{
//BOOL handled = FALSE;
@@ -2049,9 +1809,10 @@ BOOL LLScrollListCtrl::handleDoubleClick(S32 x, S32 y, MASK mask)
// so the scroll bars will work.
if (NULL == LLView::childrenHandleDoubleClick(x, y, mask))
{
- if( mCanSelect && mOnDoubleClickCallback )
+ // Run the callback only if an item is being double-clicked.
+ if( mCanSelect && hitItem(x, y) && mOnDoubleClickCallback )
{
- mOnDoubleClickCallback( mCallbackUserData );
+ mOnDoubleClickCallback();
}
}
}
@@ -2118,6 +1879,8 @@ LLScrollListItem* LLScrollListCtrl::hitItem( S32 x, S32 y )
// Excludes disabled items.
LLScrollListItem* hit_item = NULL;
+ updateSort();
+
LLRect item_rect;
item_rect.setLeftTopAndSize(
mItemListRect.mLeft,
@@ -2126,7 +1889,7 @@ LLScrollListItem* LLScrollListCtrl::hitItem( S32 x, S32 y )
mLineHeight );
// allow for partial line at bottom
- S32 num_page_lines = mPageLines + 1;
+ S32 num_page_lines = getLinesPerPage();
S32 line = 0;
item_list::iterator iter;
@@ -2197,8 +1960,7 @@ S32 LLScrollListCtrl::getColumnOffsetFromIndex(S32 index)
S32 LLScrollListCtrl::getRowOffsetFromIndex(S32 index)
{
- S32 row_bottom = ((mItemListRect.mTop - (index - mScrollLines)) * mLineHeight)
- - mLineHeight;
+ S32 row_bottom = (mItemListRect.mTop - ((index - mScrollLines + 1) * mLineHeight) );
return row_bottom;
}
@@ -2221,11 +1983,11 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask)
LLScrollListItem* item = hitItem(x, y);
if (item)
{
- highlightNthItem(getItemIndex(item));
+ mouseOverHighlightNthItem(getItemIndex(item));
}
else
{
- highlightNthItem(-1);
+ mouseOverHighlightNthItem(-1);
}
}
@@ -2234,6 +1996,11 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask)
return handled;
}
+void LLScrollListCtrl::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ // clear mouse highlight
+ mouseOverHighlightNthItem(-1);
+}
BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask )
{
@@ -2378,7 +2145,8 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char)
}
// perform incremental search based on keyboard input
- if (mSearchTimer.getElapsedTimeF32() > LLUI::sConfigGroup->getF32("TypeAheadTimeout"))
+ static LLUICachedControl<F32> type_ahead_timeout ("TypeAheadTimeout", 0);
+ if (mSearchTimer.getElapsedTimeF32() > type_ahead_timeout)
{
mSearchString.clear();
}
@@ -2554,9 +2322,11 @@ BOOL LLScrollListCtrl::setSort(S32 column_idx, BOOL ascending)
LLScrollListColumn* sort_column = getColumn(column_idx);
if (!sort_column) return FALSE;
- sort_column->mSortAscending = ascending;
+ sort_column->mSortDirection = ascending ? LLScrollListColumn::ASCENDING : LLScrollListColumn::DESCENDING;
sort_column_t new_sort_column(column_idx, ascending);
+
+ setNeedsSort();
if (mSortColumns.empty())
{
@@ -2578,12 +2348,24 @@ BOOL LLScrollListCtrl::setSort(S32 column_idx, BOOL ascending)
}
}
+S32 LLScrollListCtrl::getLinesPerPage()
+{
+ //if mPageLines is NOT provided display all item
+ if(mPageLines)
+ {
+ return mPageLines;
+ }
+ else
+ {
+ return mLineHeight ? mItemListRect.getHeight() / mLineHeight : getItemCount();
+ }
+}
+
+
// Called by scrollbar
-//static
-void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar, void* userdata )
+void LLScrollListCtrl::onScrollChange( S32 new_pos, LLScrollbar* scrollbar )
{
- LLScrollListCtrl* self = (LLScrollListCtrl*) userdata;
- self->mScrollLines = new_pos;
+ mScrollLines = new_pos;
}
@@ -2599,21 +2381,22 @@ void LLScrollListCtrl::sortByColumn(const std::string& name, BOOL ascending)
// First column is column 0
void LLScrollListCtrl::sortByColumnIndex(U32 column, BOOL ascending)
{
- if (setSort(column, ascending))
- {
- sortItems();
- }
+ setSort(column, ascending);
+ updateSort();
}
-void LLScrollListCtrl::sortItems()
+void LLScrollListCtrl::updateSort() const
{
- // do stable sort to preserve any previous sorts
- std::stable_sort(
- mItemList.begin(),
- mItemList.end(),
- SortScrollListItem(mSortColumns));
+ if (hasSortOrder() && !isSorted())
+ {
+ // do stable sort to preserve any previous sorts
+ std::stable_sort(
+ mItemList.begin(),
+ mItemList.end(),
+ SortScrollListItem(mSortColumns));
- setSorted(TRUE);
+ mSorted = true;
+ }
}
// for one-shot sorts, does not save sort column/order
@@ -2656,7 +2439,7 @@ void LLScrollListCtrl::setScrollPos( S32 pos )
{
mScrollbar->setDocPos( pos );
- onScrollChange(mScrollbar->getDocPos(), mScrollbar, this);
+ onScrollChange(mScrollbar->getDocPos(), mScrollbar);
}
@@ -2669,10 +2452,7 @@ void LLScrollListCtrl::scrollToShowSelected()
return;
}
- if (needsSorting() && !isSorted())
- {
- sortItems();
- }
+ updateSort();
S32 index = getFirstSelectedIndex();
if (index < 0)
@@ -2688,7 +2468,8 @@ void LLScrollListCtrl::scrollToShowSelected()
}
S32 lowest = mScrollLines;
- S32 highest = mScrollLines + mPageLines;
+ S32 page_lines = getLinesPerPage();
+ S32 highest = mScrollLines + page_lines;
if (index < lowest)
{
@@ -2697,7 +2478,7 @@ void LLScrollListCtrl::scrollToShowSelected()
}
else if (highest <= index)
{
- setScrollPos(index - mPageLines + 1);
+ setScrollPos(index - page_lines + 1);
}
}
@@ -2706,293 +2487,6 @@ void LLScrollListCtrl::updateStaticColumnWidth(LLScrollListColumn* col, S32 new_
mTotalStaticColumnWidth += llmax(0, new_width) - llmax(0, col->getWidth());
}
-
-// virtual
-LLXMLNodePtr LLScrollListCtrl::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLUICtrl::getXML();
-
- // Attributes
-
- node->createChild("multi_select", TRUE)->setBoolValue(mAllowMultipleSelection);
-
- node->createChild("draw_border", TRUE)->setBoolValue((mBorder != NULL));
-
- node->createChild("draw_heading", TRUE)->setBoolValue(mDisplayColumnHeaders);
-
- node->createChild("background_visible", TRUE)->setBoolValue(mBackgroundVisible);
-
- node->createChild("draw_stripes", TRUE)->setBoolValue(mDrawStripes);
-
- node->createChild("column_padding", TRUE)->setIntValue(mColumnPadding);
-
- addColorXML(node, mBgWriteableColor, "bg_writeable_color", "ScrollBgWriteableColor");
- addColorXML(node, mBgReadOnlyColor, "bg_read_only_color", "ScrollBgReadOnlyColor");
- addColorXML(node, mBgSelectedColor, "bg_selected_color", "ScrollSelectedBGColor");
- addColorXML(node, mBgStripeColor, "bg_stripe_color", "ScrollBGStripeColor");
- addColorXML(node, mFgSelectedColor, "fg_selected_color", "ScrollSelectedFGColor");
- addColorXML(node, mFgUnselectedColor, "fg_unselected_color", "ScrollUnselectedColor");
- addColorXML(node, mFgDisabledColor, "fg_disable_color", "ScrollDisabledColor");
- addColorXML(node, mHighlightedColor, "highlighted_color", "ScrollHighlightedColor");
-
- // Contents
-
- std::map<std::string, LLScrollListColumn>::const_iterator itor;
- std::vector<const LLScrollListColumn*> sorted_list;
- sorted_list.resize(mColumns.size());
- for (itor = mColumns.begin(); itor != mColumns.end(); ++itor)
- {
- sorted_list[itor->second.mIndex] = &itor->second;
- }
-
- std::vector<const LLScrollListColumn*>::iterator itor2;
- for (itor2 = sorted_list.begin(); itor2 != sorted_list.end(); ++itor2)
- {
- LLXMLNodePtr child_node = node->createChild("column", FALSE);
- const LLScrollListColumn *column = *itor2;
-
- child_node->createChild("name", TRUE)->setStringValue(column->mName);
- child_node->createChild("label", TRUE)->setStringValue(column->mLabel);
- child_node->createChild("width", TRUE)->setIntValue(column->getWidth());
- }
-
- return node;
-}
-
-void LLScrollListCtrl::setScrollListParameters(LLXMLNodePtr node)
-{
- // James: This is not a good way to do colors. We need a central "UI style"
- // manager that sets the colors for ALL scroll lists, buttons, etc.
-
- LLColor4 color;
- if(node->hasAttribute("fg_unselected_color"))
- {
- LLUICtrlFactory::getAttributeColor(node,"fg_unselected_color", color);
- setFgUnselectedColor(color);
- }
- if(node->hasAttribute("fg_selected_color"))
- {
- LLUICtrlFactory::getAttributeColor(node,"fg_selected_color", color);
- setFgSelectedColor(color);
- }
- if(node->hasAttribute("bg_selected_color"))
- {
- LLUICtrlFactory::getAttributeColor(node,"bg_selected_color", color);
- setBgSelectedColor(color);
- }
- if(node->hasAttribute("fg_disable_color"))
- {
- LLUICtrlFactory::getAttributeColor(node,"fg_disable_color", color);
- setFgDisableColor(color);
- }
- if(node->hasAttribute("bg_writeable_color"))
- {
- LLUICtrlFactory::getAttributeColor(node,"bg_writeable_color", color);
- setBgWriteableColor(color);
- }
- if(node->hasAttribute("bg_read_only_color"))
- {
- LLUICtrlFactory::getAttributeColor(node,"bg_read_only_color", color);
- setReadOnlyBgColor(color);
- }
- if (LLUICtrlFactory::getAttributeColor(node,"bg_stripe_color", color))
- {
- setBgStripeColor(color);
- }
- if (LLUICtrlFactory::getAttributeColor(node,"highlighted_color", color))
- {
- setHighlightedColor(color);
- }
-
- if(node->hasAttribute("background_visible"))
- {
- BOOL background_visible;
- node->getAttributeBOOL("background_visible", background_visible);
- setBackgroundVisible(background_visible);
- }
-
- if(node->hasAttribute("draw_stripes"))
- {
- BOOL draw_stripes;
- node->getAttributeBOOL("draw_stripes", draw_stripes);
- setDrawStripes(draw_stripes);
- }
-
- if(node->hasAttribute("column_padding"))
- {
- S32 column_padding;
- node->getAttributeS32("column_padding", column_padding);
- setColumnPadding(column_padding);
- }
-}
-
-// static
-LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("scroll_list");
- node->getAttributeString("name", name);
-
- LLRect rect;
- createRect(node, rect, parent, LLRect());
-
- BOOL multi_select = FALSE;
- node->getAttributeBOOL("multi_select", multi_select);
-
- BOOL draw_border = TRUE;
- node->getAttributeBOOL("draw_border", draw_border);
-
- BOOL draw_heading = FALSE;
- node->getAttributeBOOL("draw_heading", draw_heading);
-
- S32 search_column = 0;
- node->getAttributeS32("search_column", search_column);
-
- S32 sort_column = -1;
- node->getAttributeS32("sort_column", sort_column);
-
- BOOL sort_ascending = TRUE;
- node->getAttributeBOOL("sort_ascending", sort_ascending);
-
- LLUICtrlCallback callback = NULL;
-
- LLScrollListCtrl* scroll_list = new LLScrollListCtrl(
- name,
- rect,
- callback,
- NULL,
- multi_select,
- draw_border);
-
- scroll_list->setDisplayHeading(draw_heading);
- if (node->hasAttribute("heading_height"))
- {
- S32 heading_height;
- node->getAttributeS32("heading_height", heading_height);
- scroll_list->setHeadingHeight(heading_height);
- }
-
- scroll_list->setScrollListParameters(node);
-
- scroll_list->initFromXML(node, parent);
-
- scroll_list->setSearchColumn(search_column);
-
- LLSD columns;
- S32 index = 0;
- LLXMLNodePtr child;
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
- {
- if (child->hasName("column"))
- {
- std::string labelname("");
- child->getAttributeString("label", labelname);
-
- std::string columnname(labelname);
- child->getAttributeString("name", columnname);
-
- std::string sortname(columnname);
- child->getAttributeString("sort", sortname);
-
- BOOL sort_ascending = TRUE;
- child->getAttributeBOOL("sort_ascending", sort_ascending);
-
- std::string imagename;
- child->getAttributeString("image", imagename);
-
- BOOL columndynamicwidth = FALSE;
- child->getAttributeBOOL("dynamicwidth", columndynamicwidth);
-
- S32 columnwidth = -1;
- child->getAttributeS32("width", columnwidth);
-
- std::string tooltip;
- child->getAttributeString("tool_tip", tooltip);
-
- F32 columnrelwidth = 0.f;
- child->getAttributeF32("relwidth", columnrelwidth);
-
- LLFontGL::HAlign h_align = LLFontGL::LEFT;
- h_align = LLView::selectFontHAlign(child);
-
- columns[index]["name"] = columnname;
- columns[index]["sort"] = sortname;
- columns[index]["sort_ascending"] = sort_ascending;
- columns[index]["image"] = imagename;
- columns[index]["label"] = labelname;
- columns[index]["width"] = columnwidth;
- columns[index]["relwidth"] = columnrelwidth;
- columns[index]["dynamicwidth"] = columndynamicwidth;
- columns[index]["halign"] = (S32)h_align;
- columns[index]["tool_tip"] = tooltip;
-
- index++;
- }
- }
- scroll_list->setColumnHeadings(columns);
-
- if (sort_column >= 0)
- {
- scroll_list->sortByColumnIndex(sort_column, sort_ascending);
- }
-
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
- {
- if (child->hasName("row"))
- {
- LLUUID id;
- child->getAttributeUUID("id", id);
-
- LLSD row;
-
- row["id"] = id;
-
- S32 column_idx = 0;
- LLXMLNodePtr row_child;
- for (row_child = child->getFirstChild(); row_child.notNull(); row_child = row_child->getNextSibling())
- {
- if (row_child->hasName("column"))
- {
- std::string value = row_child->getTextContents();
-
- std::string columnname("");
- row_child->getAttributeString("name", columnname);
-
- std::string font("");
- row_child->getAttributeString("font", font);
-
- std::string font_style("");
- row_child->getAttributeString("font-style", font_style);
-
- row["columns"][column_idx]["column"] = columnname;
- row["columns"][column_idx]["value"] = value;
- row["columns"][column_idx]["font"] = font;
- row["columns"][column_idx]["font-style"] = font_style;
- column_idx++;
- }
- }
- scroll_list->addElement(row);
- }
- }
-
- std::string contents = node->getTextContents();
- if (!contents.empty())
- {
- typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
- boost::char_separator<char> sep("\t\n");
- tokenizer tokens(contents, sep);
- tokenizer::iterator token_iter = tokens.begin();
-
- while(token_iter != tokens.end())
- {
- const std::string& line = *token_iter;
- scroll_list->addSimpleElement(line);
- ++token_iter;
- }
- }
-
- return scroll_list;
-}
-
// LLEditMenuHandler functions
// virtual
@@ -3068,20 +2562,27 @@ BOOL LLScrollListCtrl::canDeselect() const
void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos)
{
- std::string name = column["name"].asString();
+ LLScrollListColumn::Params p;
+ LLParamSDParser::instance().readSD(column, p);
+ addColumn(p, pos);
+}
+
+void LLScrollListCtrl::addColumn(const LLScrollListColumn::Params& column_params, EAddPosition pos)
+{
+ if (!column_params.validateBlock()) return;
+
+ std::string name = column_params.name;
// if no column name provided, just use ordinal as name
if (name.empty())
{
- std::ostringstream new_name;
- new_name << mColumnsIndexed.size();
- name = new_name.str();
+ name = llformat("%d", mColumnsIndexed.size());
}
+
if (mColumns.find(name) == mColumns.end())
{
// Add column
- mColumns[name] = LLScrollListColumn(column, this);
+ mColumns[name] = LLScrollListColumn(column_params, this);
LLScrollListColumn* new_column = &mColumns[name];
- new_column->mParentCtrl = this;
new_column->mIndex = mColumns.size()-1;
// Add button
@@ -3101,44 +2602,47 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos)
new_column->setWidth((mItemListRect.getWidth() - mTotalStaticColumnWidth - mTotalColumnPadding) / mNumDynamicWidthColumns);
}
S32 top = mItemListRect.mTop;
+
S32 left = mItemListRect.mLeft;
+ for (std::map<std::string, LLScrollListColumn>::iterator itor = mColumns.begin();
+ itor != mColumns.end();
+ ++itor)
{
- std::map<std::string, LLScrollListColumn>::iterator itor;
- for (itor = mColumns.begin(); itor != mColumns.end(); ++itor)
+ if (itor->second.mIndex < new_column->mIndex &&
+ itor->second.getWidth() > 0)
{
- if (itor->second.mIndex < new_column->mIndex &&
- itor->second.getWidth() > 0)
- {
- left += itor->second.getWidth() + mColumnPadding;
- }
+ left += itor->second.getWidth() + mColumnPadding;
}
}
- std::string button_name = "btn_" + name;
+
S32 right = left+new_column->getWidth();
if (new_column->mIndex != (S32)mColumns.size()-1)
{
right += mColumnPadding;
}
+
LLRect temp_rect = LLRect(left,top+mHeadingHeight,right,top);
- new_column->mHeader = new LLColumnHeader(button_name, temp_rect, new_column);
- if(column["image"].asString() != "")
+
+ LLScrollColumnHeader::Params params(LLUICtrlFactory::getDefaultParams<LLScrollColumnHeader>());
+ params.name = "btn_" + name;
+ params.rect = temp_rect;
+ params.column = new_column;
+ params.tool_tip = column_params.tool_tip;
+ params.tab_stop = false;
+ params.visible = mDisplayColumnHeaders;
+
+ if(column_params.header.image.isProvided())
{
- //new_column->mHeader->setScaleImage(false);
- new_column->mHeader->setImage(column["image"].asString());
+ params.image_selected = column_params.header.image;
+ params.image_unselected = column_params.header.image;
}
else
{
- new_column->mHeader->setLabel(new_column->mLabel);
- //new_column->mHeader->setLabel(new_column->mLabel);
+ params.label = column_params.header.label;
}
- new_column->mHeader->setToolTip(column["tool_tip"].asString());
-
- //RN: although it might be useful to change sort order with the keyboard,
- // mixing tab stops on child items along with the parent item is not supported yet
- new_column->mHeader->setTabStop(FALSE);
+ new_column->mHeader = LLUICtrlFactory::create<LLScrollColumnHeader>(params);
addChild(new_column->mHeader);
- new_column->mHeader->setVisible(mDisplayColumnHeaders);
sendChildToFront(mScrollbar);
}
@@ -3159,7 +2663,7 @@ void LLScrollListCtrl::onClickColumn(void *userdata)
S32 column_index = info->mIndex;
LLScrollListColumn* column = parent->mColumnsIndexed[info->mIndex];
- bool ascending = column->mSortAscending;
+ bool ascending = column->mSortDirection == LLScrollListColumn::ASCENDING;
if (column->mSortingColumn != column->mName
&& parent->mColumns.find(column->mSortingColumn) != parent->mColumns.end())
{
@@ -3178,7 +2682,7 @@ void LLScrollListCtrl::onClickColumn(void *userdata)
if (parent->mOnSortChangedCallback)
{
- parent->mOnSortChangedCallback(parent->getCallbackUserData());
+ parent->mOnSortChangedCallback();
}
}
@@ -3190,7 +2694,7 @@ std::string LLScrollListCtrl::getSortColumnName()
else return "";
}
-BOOL LLScrollListCtrl::needsSorting()
+BOOL LLScrollListCtrl::hasSortOrder() const
{
return !mSortColumns.empty();
}
@@ -3200,7 +2704,7 @@ void LLScrollListCtrl::clearColumns()
std::map<std::string, LLScrollListColumn>::iterator itor;
for (itor = mColumns.begin(); itor != mColumns.end(); ++itor)
{
- LLColumnHeader *header = itor->second.mHeader;
+ LLScrollColumnHeader *header = itor->second.mHeader;
if (header)
{
removeChild(header);
@@ -3215,13 +2719,13 @@ void LLScrollListCtrl::clearColumns()
void LLScrollListCtrl::setColumnLabel(const std::string& column, const std::string& label)
{
- std::map<std::string, LLScrollListColumn>::iterator itor = mColumns.find(column);
- if (itor != mColumns.end())
+ LLScrollListColumn* columnp = getColumn(column);
+ if (columnp)
{
- itor->second.mLabel = label;
- if (itor->second.mHeader)
+ columnp->mLabel = label;
+ if (columnp->mHeader)
{
- itor->second.mHeader->setLabel(label);
+ columnp->mHeader->setLabel(label);
}
}
}
@@ -3235,74 +2739,62 @@ LLScrollListColumn* LLScrollListCtrl::getColumn(S32 index)
return mColumnsIndexed[index];
}
-void LLScrollListCtrl::setColumnHeadings(LLSD headings)
+LLScrollListColumn* LLScrollListCtrl::getColumn(const std::string& name)
{
- mColumns.clear();
- LLSD::array_const_iterator itor;
- for (itor = headings.beginArray(); itor != headings.endArray(); ++itor)
+ column_map_t::iterator column_itor = mColumns.find(name);
+ if (column_itor != mColumns.end())
{
- addColumn(*itor);
+ return &column_itor->second;
}
+ return NULL;
}
-LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition pos, void* userdata)
+
+LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition pos, void* userdata)
{
- // ID
- LLSD id = value["id"];
+ LLScrollListItem::Params item_params;
+ LLParamSDParser::instance().readSD(element, item_params);
+ item_params.userdata = userdata;
+ return addRow(item_params, pos);
+}
- LLScrollListItem *new_item = new LLScrollListItem(id, userdata);
- if (value.has("enabled"))
- {
- new_item->setEnabled( value["enabled"].asBoolean() );
- }
+LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_p, EAddPosition pos)
+{
+ if (!item_p.validateBlock()) return NULL;
+ LLScrollListItem *new_item = new LLScrollListItem(item_p);
new_item->setNumColumns(mColumns.size());
// Add any columns we don't already have
- LLSD columns = value["columns"];
- LLSD::array_const_iterator itor;
- S32 col_index = 0 ;
- for (itor = columns.beginArray(); itor != columns.endArray(); ++itor)
- {
- if (itor->isUndefined())
- {
- // skip unused columns in item passed in
- continue;
- }
- std::string column = (*itor)["column"].asString();
+ S32 col_index = 0;
- LLScrollListColumn* columnp = NULL;
+ for(LLInitParam::ParamIterator<LLScrollListCell::Params>::const_iterator itor = item_p.columns().begin();
+ itor != item_p.columns().end();
+ ++itor)
+ {
+ LLScrollListCell::Params cell_p = *itor;
+ std::string column = cell_p.column;
// empty columns strings index by ordinal
if (column.empty())
{
- std::ostringstream new_name;
- new_name << col_index;
- column = new_name.str();
+ column = llformat("%d", col_index);
}
- std::map<std::string, LLScrollListColumn>::iterator column_itor;
- column_itor = mColumns.find(column);
- if (column_itor != mColumns.end())
- {
- columnp = &column_itor->second;
- }
+ LLScrollListColumn* columnp = getColumn(column);
// create new column on demand
if (!columnp)
{
- LLSD new_column;
- new_column["name"] = column;
- new_column["label"] = column;
+ LLScrollListColumn::Params new_column;
+ new_column.name = column;
+ new_column.header.label = column;
+
// if width supplied for column, use it, otherwise
// use adaptive width
- if (itor->has("width"))
+ if (cell_p.width.isProvided())
{
- new_column["width"] = (*itor)["width"];
- }
- else
- {
- new_column["dynamicwidth"] = true;
+ new_column.width.pixel_width = cell_p.width;
}
addColumn(new_column);
columnp = &mColumns[column];
@@ -3310,91 +2802,48 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
}
S32 index = columnp->mIndex;
- S32 width = columnp->getWidth();
- LLFontGL::HAlign font_alignment = columnp->mFontAlignment;
- LLColor4 fcolor = LLColor4::black;
-
- LLSD value = (*itor)["value"];
- std::string fontname = (*itor)["font"].asString();
- std::string fontstyle = (*itor)["font-style"].asString();
- std::string type = (*itor)["type"].asString();
-
- if ((*itor).has("font-color"))
- {
- LLSD sd_color = (*itor)["font-color"];
- fcolor.setValue(sd_color);
- }
-
- BOOL has_color = (*itor).has("color");
- LLColor4 color = ((*itor)["color"]);
- BOOL enabled = !(*itor).has("enabled") || (*itor)["enabled"].asBoolean() == true;
+ cell_p.width.setIfNotProvided(columnp->getWidth());
- const LLFontGL *font = LLResMgr::getInstance()->getRes(fontname);
- if (!font)
- {
- font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL );
- }
- U8 font_style = LLFontGL::getStyleFromString(fontstyle);
+ LLScrollListCell* cell = LLScrollListCell::create(cell_p);
- if (type == "icon")
- {
- LLScrollListIcon* cell = new LLScrollListIcon(value, width);
- if (has_color)
- {
- cell->setColor(color);
- }
- new_item->setColumn(index, cell);
- }
- else if (type == "checkbox")
+ if (cell)
{
- LLCheckBoxCtrl* ctrl = new LLCheckBoxCtrl(std::string("check"),
- LLRect(0, width, width, 0), std::string(" "));
- ctrl->setEnabled(enabled);
- ctrl->setValue(value);
- LLScrollListCheck* cell = new LLScrollListCheck(ctrl,width);
- if (has_color)
- {
- cell->setColor(color);
- }
new_item->setColumn(index, cell);
- }
- else if (type == "separator")
- {
- LLScrollListSeparator* cell = new LLScrollListSeparator(width);
- if (has_color)
+ if (columnp->mHeader
+ && cell->isText()
+ && !cell->getValue().asString().empty())
{
- cell->setColor(color);
+ columnp->mHeader->setHasResizableElement(TRUE);
}
- new_item->setColumn(index, cell);
}
- else if (type == "date")
+
+ col_index++;
+ }
+
+ if (item_p.columns().empty())
+ {
+ if (mColumns.empty())
{
- LLScrollListDate* cell = new LLScrollListDate(value.asDate(), font, width, font_style, font_alignment);
- if (has_color)
- {
- cell->setColor(color);
- }
- new_item->setColumn(index, cell);
- if (columnp->mHeader && !value.asString().empty())
- {
- columnp->mHeader->setHasResizableElement(TRUE);
- }
+ LLScrollListColumn::Params new_column;
+ new_column.name = "0";
+
+ addColumn(new_column);
+ new_item->setNumColumns(mColumns.size());
}
- else
+
+ LLScrollListCell* cell = LLScrollListCell::create(LLScrollListCell::Params().value(item_p.value));
+ if (cell)
{
- LLScrollListText* cell = new LLScrollListText(value.asString(), font, width, font_style, font_alignment, fcolor, TRUE);
- if (has_color)
- {
- cell->setColor(color);
- }
- new_item->setColumn(index, cell);
- if (columnp->mHeader && !value.asString().empty())
+ LLScrollListColumn* columnp = &(mColumns.begin()->second);
+
+ new_item->setColumn(0, cell);
+ if (columnp->mHeader
+ && cell->isText()
+ && !cell->getValue().asString().empty())
{
columnp->mHeader->setHasResizableElement(TRUE);
}
}
-
- col_index++;
}
// add dummy cells for missing columns
@@ -3404,12 +2853,14 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
if (new_item->getColumn(column_idx) == NULL)
{
LLScrollListColumn* column_ptr = &column_it->second;
- new_item->setColumn(column_idx, new LLScrollListText(LLStringUtil::null, LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ), column_ptr->getWidth(), LLFontGL::NORMAL));
+ LLScrollListCell::Params cell_p;
+ cell_p.width = column_ptr->getWidth();
+
+ new_item->setColumn(column_idx, new LLScrollListSpacer(cell_p));
}
}
addItem(new_item, pos);
-
return new_item;
}
@@ -3422,14 +2873,13 @@ LLScrollListItem* LLScrollListCtrl::addSimpleElement(const std::string& value, E
entry_id = value;
}
- LLScrollListItem *new_item = new LLScrollListItem(entry_id);
-
- const LLFontGL *font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL );
-
- new_item->addColumn(value, font, getRect().getWidth());
-
- addItem(new_item, pos);
- return new_item;
+ LLScrollListItem::Params item_params;
+ item_params.value(entry_id);
+ item_params.columns.add()
+ .value(value)
+ .font(LLFontGL::getFontSansSerifSmall());
+
+ return addRow(item_params, pos);
}
void LLScrollListCtrl::setValue(const LLSD& value )
@@ -3530,484 +2980,3 @@ void LLScrollListCtrl::onFocusLost()
LLUICtrl::onFocusLost();
}
-LLColumnHeader::LLColumnHeader(const std::string& label, const LLRect &rect, LLScrollListColumn* column, const LLFontGL* fontp) :
- LLComboBox(label, rect, label, NULL, NULL),
- mColumn(column),
- mOrigLabel(label),
- mShowSortOptions(FALSE),
- mHasResizableElement(FALSE)
-{
- mListPosition = LLComboBox::ABOVE;
- setCommitCallback(onSelectSort);
- setCallbackUserData(this);
- mButton->setTabStop(FALSE);
- // require at least two frames between mouse down and mouse up event to capture intentional "hold" not just bad framerate
- mButton->setHeldDownDelay(LLUI::sConfigGroup->getF32("ColumnHeaderDropDownDelay"), 2);
- mButton->setHeldDownCallback(onHeldDown);
- mButton->setClickedCallback(onClick);
- mButton->setMouseDownCallback(onMouseDown);
-
- mButton->setCallbackUserData(this);
- mButton->setToolTip(label);
-
- mAscendingText = std::string("[LOW]...[HIGH](Ascending)"); // *TODO: Translate
- mDescendingText = std::string("[HIGH]...[LOW](Descending)"); // *TODO: Translate
-
- mList->reshape(llmax(mList->getRect().getWidth(), 110, getRect().getWidth()), mList->getRect().getHeight());
-
- // resize handles on left and right
- const S32 RESIZE_BAR_THICKNESS = 3;
- mResizeBar = new LLResizeBar(
- std::string("resizebar"),
- this,
- LLRect( getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0),
- MIN_COLUMN_WIDTH, S32_MAX, LLResizeBar::RIGHT );
- addChild(mResizeBar);
-
- mResizeBar->setEnabled(FALSE);
-}
-
-LLColumnHeader::~LLColumnHeader()
-{
-}
-
-void LLColumnHeader::draw()
-{
- BOOL draw_arrow = !mColumn->mLabel.empty() && mColumn->mParentCtrl->isSorted() && mColumn->mParentCtrl->getSortColumnName() == mColumn->mSortingColumn;
-
- BOOL is_ascending = mColumn->mParentCtrl->getSortAscending();
- mButton->setImageOverlay(is_ascending ? "up_arrow.tga" : "down_arrow.tga", LLFontGL::RIGHT, draw_arrow ? LLColor4::white : LLColor4::transparent);
- mArrowImage = mButton->getImageOverlay();
-
- //BOOL clip = getRect().mRight > mColumn->mParentCtrl->getItemListRect().getWidth();
- //LLGLEnable scissor_test(clip ? GL_SCISSOR_TEST : GL_FALSE);
-
- //LLRect column_header_local_rect(-getRect().mLeft, getRect().getHeight(), mColumn->mParentCtrl->getItemListRect().getWidth() - getRect().mLeft, 0);
- //LLUI::setScissorRegionLocal(column_header_local_rect);
-
- // Draw children
- LLComboBox::draw();
-
- if (mList->getVisible())
- {
- // sync sort order with list selection every frame
- mColumn->mParentCtrl->sortByColumn(mColumn->mSortingColumn, getCurrentIndex() == 0);
- }
-}
-
-BOOL LLColumnHeader::handleDoubleClick(S32 x, S32 y, MASK mask)
-{
- if (canResize() && mResizeBar->getRect().pointInRect(x, y))
- {
- // reshape column to max content width
- LLRect column_rect = getRect();
- column_rect.mRight = column_rect.mLeft + mColumn->mMaxContentWidth;
- userSetShape(column_rect);
- }
- else
- {
- onClick(this);
- }
- return TRUE;
-}
-
-void LLColumnHeader::setImage(const std::string &image_name)
-{
- if (mButton)
- {
- mButton->setImageSelected(image_name);
- mButton->setImageUnselected(image_name);
- }
-}
-
-//static
-void LLColumnHeader::onClick(void* user_data)
-{
- LLColumnHeader* headerp = (LLColumnHeader*)user_data;
- if (!headerp) return;
-
- LLScrollListColumn* column = headerp->mColumn;
- if (!column) return;
-
- if (headerp->mList->getVisible())
- {
- headerp->hideList();
- }
-
- LLScrollListCtrl::onClickColumn(column);
-
- // propagate new sort order to sort order list
- headerp->mList->selectNthItem(column->mParentCtrl->getSortAscending() ? 0 : 1);
-}
-
-//static
-void LLColumnHeader::onMouseDown(void* user_data)
-{
- // for now, do nothing but block the normal showList() behavior
- return;
-}
-
-//static
-void LLColumnHeader::onHeldDown(void* user_data)
-{
- LLColumnHeader* headerp = (LLColumnHeader*)user_data;
- headerp->showList();
-}
-
-void LLColumnHeader::showList()
-{
- if (mShowSortOptions)
- {
- //LLSD item_val = mColumn->mParentCtrl->getFirstData()->getValue();
- mOrigLabel = mButton->getLabelSelected();
-
- // move sort column over to this column and do initial sort
- mColumn->mParentCtrl->sortByColumn(mColumn->mSortingColumn, mColumn->mParentCtrl->getSortAscending());
-
- std::string low_item_text;
- std::string high_item_text;
-
- LLScrollListItem* itemp = mColumn->mParentCtrl->getFirstData();
- if (itemp)
- {
- LLScrollListCell* cell = itemp->getColumn(mColumn->mIndex);
- if (cell && cell->isText())
- {
- if (mColumn->mParentCtrl->getSortAscending())
- {
- low_item_text = cell->getValue().asString();
- }
- else
- {
- high_item_text = cell->getValue().asString();
- }
- }
- }
-
- itemp = mColumn->mParentCtrl->getLastData();
- if (itemp)
- {
- LLScrollListCell* cell = itemp->getColumn(mColumn->mIndex);
- if (cell && cell->isText())
- {
- if (mColumn->mParentCtrl->getSortAscending())
- {
- high_item_text = cell->getValue().asString();
- }
- else
- {
- low_item_text = cell->getValue().asString();
- }
- }
- }
-
- LLStringUtil::truncate(low_item_text, 3);
- LLStringUtil::truncate(high_item_text, 3);
-
- std::string ascending_string;
- std::string descending_string;
-
- if (low_item_text.empty() || high_item_text.empty())
- {
- ascending_string = "Ascending";
- descending_string = "Descending";
- }
- else
- {
- mAscendingText.setArg("[LOW]", low_item_text);
- mAscendingText.setArg("[HIGH]", high_item_text);
- mDescendingText.setArg("[LOW]", low_item_text);
- mDescendingText.setArg("[HIGH]", high_item_text);
- ascending_string = mAscendingText.getString();
- descending_string = mDescendingText.getString();
- }
-
- S32 text_width = LLFontGL::getFontSansSerifSmall()->getWidth(ascending_string);
- text_width = llmax(text_width, LLFontGL::getFontSansSerifSmall()->getWidth(descending_string)) + 10;
- text_width = llmax(text_width, getRect().getWidth() - 30);
-
- mList->getColumn(0)->setWidth(text_width);
- ((LLScrollListText*)mList->getFirstData()->getColumn(0))->setText(ascending_string);
- ((LLScrollListText*)mList->getLastData()->getColumn(0))->setText(descending_string);
-
- mList->reshape(llmax(text_width + 30, 110, getRect().getWidth()), mList->getRect().getHeight());
-
- LLComboBox::showList();
- }
-}
-
-//static
-void LLColumnHeader::onSelectSort(LLUICtrl* ctrl, void* user_data)
-{
- LLColumnHeader* headerp = (LLColumnHeader*)user_data;
- if (!headerp) return;
-
- LLScrollListColumn* column = headerp->mColumn;
- if (!column) return;
- LLScrollListCtrl *parent = column->mParentCtrl;
- if (!parent) return;
-
- if (headerp->getCurrentIndex() == 0)
- {
- // ascending
- parent->sortByColumn(column->mSortingColumn, TRUE);
- }
- else
- {
- // descending
- parent->sortByColumn(column->mSortingColumn, FALSE);
- }
-
- // restore original column header
- headerp->setLabel(headerp->mOrigLabel);
-}
-
-LLView* LLColumnHeader::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding)
-{
- // this logic assumes dragging on right
- llassert(snap_edge == SNAP_RIGHT);
-
- // use higher snap threshold for column headers
- threshold = llmin(threshold, 10);
-
- LLRect snap_rect = getSnapRect();
-
- S32 snap_delta = mColumn->mMaxContentWidth - snap_rect.getWidth();
-
- // x coord growing means column growing, so same signs mean we're going in right direction
- if (llabs(snap_delta) <= threshold && mouse_dir.mX * snap_delta > 0 )
- {
- new_edge_val = snap_rect.mRight + snap_delta;
- }
- else
- {
- LLScrollListColumn* next_column = mColumn->mParentCtrl->getColumn(mColumn->mIndex + 1);
- while (next_column)
- {
- if (next_column->mHeader)
- {
- snap_delta = (next_column->mHeader->getSnapRect().mRight - next_column->mMaxContentWidth) - snap_rect.mRight;
- if (llabs(snap_delta) <= threshold && mouse_dir.mX * snap_delta > 0 )
- {
- new_edge_val = snap_rect.mRight + snap_delta;
- }
- break;
- }
- next_column = mColumn->mParentCtrl->getColumn(next_column->mIndex + 1);
- }
- }
-
- return this;
-}
-
-void LLColumnHeader::userSetShape(const LLRect& new_rect)
-{
- S32 new_width = new_rect.getWidth();
- S32 delta_width = new_width - (getRect().getWidth() /*+ mColumn->mParentCtrl->getColumnPadding()*/);
-
- if (delta_width != 0)
- {
- S32 remaining_width = -delta_width;
- S32 col;
- for (col = mColumn->mIndex + 1; col < mColumn->mParentCtrl->getNumColumns(); col++)
- {
- LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
- if (!columnp) continue;
-
- if (columnp->mHeader && columnp->mHeader->canResize())
- {
- // how many pixels in width can this column afford to give up?
- S32 resize_buffer_amt = llmax(0, columnp->getWidth() - MIN_COLUMN_WIDTH);
-
- // user shrinking column, need to add width to other columns
- if (delta_width < 0)
- {
- if (/*!columnp->mDynamicWidth && */columnp->getWidth() > 0)
- {
- // statically sized column, give all remaining width to this column
- columnp->setWidth(columnp->getWidth() + remaining_width);
- if (columnp->mRelWidth > 0.f)
- {
- columnp->mRelWidth = (F32)columnp->getWidth() / (F32)mColumn->mParentCtrl->getItemListRect().getWidth();
- }
- // all padding went to this widget, we're done
- break;
- }
- }
- else
- {
- // user growing column, need to take width from other columns
- remaining_width += resize_buffer_amt;
-
- if (/*!columnp->mDynamicWidth && */columnp->getWidth() > 0)
- {
- columnp->setWidth(columnp->getWidth() - llmin(columnp->getWidth() - MIN_COLUMN_WIDTH, delta_width));
- if (columnp->mRelWidth > 0.f)
- {
- columnp->mRelWidth = (F32)columnp->getWidth() / (F32)mColumn->mParentCtrl->getItemListRect().getWidth();
- }
- }
-
- if (remaining_width >= 0)
- {
- // width sucked up from neighboring columns, done
- break;
- }
- }
- }
- }
-
- // clamp resize amount to maximum that can be absorbed by other columns
- if (delta_width > 0)
- {
- delta_width += llmin(remaining_width, 0);
- }
-
- // propagate constrained delta_width to new width for this column
- new_width = getRect().getWidth() + delta_width - mColumn->mParentCtrl->getColumnPadding();
-
- // use requested width
- mColumn->setWidth(new_width);
-
- // update proportional spacing
- if (mColumn->mRelWidth > 0.f)
- {
- mColumn->mRelWidth = (F32)new_width / (F32)mColumn->mParentCtrl->getItemListRect().getWidth();
- }
-
- // tell scroll list to layout columns again
- // do immediate update to get proper feedback to resize handle
- // which needs to know how far the resize actually went
- mColumn->mParentCtrl->updateColumns();
- }
-}
-
-void LLColumnHeader::setHasResizableElement(BOOL resizable)
-{
- // for now, dynamically spaced columns can't be resized
-// if (mColumn->mDynamicWidth) return;
-
- if (mHasResizableElement != resizable)
- {
- mColumn->mParentCtrl->dirtyColumns();
- mHasResizableElement = resizable;
- }
-}
-
-void LLColumnHeader::updateResizeBars()
-{
- S32 num_resizable_columns = 0;
- S32 col;
- for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++)
- {
- LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
- if (columnp->mHeader && columnp->mHeader->canResize())
- {
- num_resizable_columns++;
- }
- }
-
- S32 num_resizers_enabled = 0;
-
- // now enable/disable resize handles on resizable columns if we have at least two
- for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++)
- {
- LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
- if (!columnp->mHeader) continue;
- BOOL enable = num_resizable_columns >= 2 && num_resizers_enabled < (num_resizable_columns - 1) && columnp->mHeader->canResize();
- columnp->mHeader->enableResizeBar(enable);
- if (enable)
- {
- num_resizers_enabled++;
- }
- }
-}
-
-void LLColumnHeader::enableResizeBar(BOOL enable)
-{
- // for now, dynamically spaced columns can't be resized
- //if (!mColumn->mDynamicWidth)
- {
- mResizeBar->setEnabled(enable);
- }
-}
-
-BOOL LLColumnHeader::canResize()
-{
- return getVisible() && (mHasResizableElement || mColumn->mDynamicWidth);
-}
-
-void LLScrollListColumn::setWidth(S32 width)
-{
- if (!mDynamicWidth && mRelWidth <= 0.f)
- {
- mParentCtrl->updateStaticColumnWidth(this, width);
- }
- mWidth = width;
-}
-
-// Default constructor
-LLScrollListColumn::LLScrollListColumn() :
- mName(),
- mSortingColumn(),
- mSortAscending(TRUE),
- mLabel(),
- mWidth(-1),
- mRelWidth(-1.0),
- mDynamicWidth(FALSE),
- mMaxContentWidth(0),
- mIndex(-1),
- mParentCtrl(NULL),
- mHeader(NULL),
- mFontAlignment(LLFontGL::LEFT)
-{ }
-
-LLScrollListColumn::LLScrollListColumn(const LLSD &sd, LLScrollListCtrl* parent) :
- mWidth(0),
- mIndex (-1),
- mParentCtrl(parent),
- mHeader(NULL),
- mMaxContentWidth(0),
- mDynamicWidth(FALSE),
- mRelWidth(-1.f)
-{
- mName = sd.get("name").asString();
- mSortingColumn = mName;
- if (sd.has("sort"))
- {
- mSortingColumn = sd.get("sort").asString();
- }
- mSortAscending = TRUE;
- if (sd.has("sort_ascending"))
- {
- mSortAscending = sd.get("sort_ascending").asBoolean();
- }
- mLabel = sd.get("label").asString();
- if (sd.has("relwidth") && (F32)sd.get("relwidth").asReal() > 0)
- {
- mRelWidth = (F32)sd.get("relwidth").asReal();
- if (mRelWidth < 0) mRelWidth = 0;
- if (mRelWidth > 1) mRelWidth = 1;
- mDynamicWidth = FALSE;
- }
- else if(sd.has("dynamicwidth") && (BOOL)sd.get("dynamicwidth").asBoolean() == TRUE)
- {
- mDynamicWidth = TRUE;
- mRelWidth = -1;
- }
- else
- {
-
- setWidth(sd.get("width").asInteger());
- }
-
- if (sd.has("halign"))
- {
- mFontAlignment = (LLFontGL::HAlign)llclamp(sd.get("halign").asInteger(), (S32)LLFontGL::LEFT, (S32)LLFontGL::HCENTER);
- }
- else
- {
- mFontAlignment = LLFontGL::LEFT;
- }
-
-}
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index 72d8894afa..907dc90bea 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -1,5 +1,8 @@
/**
* @file llscrolllistctrl.h
+ * @brief A scrolling list of items. This is the one you want to use
+ * in UI code. LLScrollListCell, LLScrollListItem, etc. are utility
+ * classes.
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
@@ -37,346 +40,115 @@
#include "lluictrl.h"
#include "llctrlselectioninterface.h"
-#include "lldarray.h"
+//#include "lldarray.h"
#include "llfontgl.h"
#include "llui.h"
-#include "llstring.h"
-#include "llimagegl.h"
+#include "llstring.h" // LLWString
#include "lleditmenuhandler.h"
#include "llframetimer.h"
-#include "llcheckboxctrl.h"
-#include "llcombobox.h"
+
#include "llscrollbar.h"
-#include "llresizebar.h"
#include "lldate.h"
+#include "llscrolllistitem.h"
+#include "llscrolllistcolumn.h"
+#include "llviewborder.h"
-/*
- * Represents a cell in a scrollable table.
- *
- * Sub-classes must return height and other properties
- * though width accessors are implemented by the base class.
- * It is therefore important for sub-class constructors to call
- * setWidth() with realistic values.
- */
-class LLScrollListCell
-{
-public:
- LLScrollListCell(S32 width = 0) : mWidth(width) {};
- virtual ~LLScrollListCell() {};
- virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const = 0; // truncate to given width, if possible
- virtual S32 getWidth() const {return mWidth;}
- virtual S32 getContentWidth() const { return 0; }
- virtual S32 getHeight() const = 0;
- virtual const LLSD getValue() const { return LLStringUtil::null; }
- virtual void setValue(const LLSD& value) { }
- virtual BOOL getVisible() const { return TRUE; }
- virtual void setWidth(S32 width) { mWidth = width; }
- virtual void highlightText(S32 offset, S32 num_chars) {}
- virtual BOOL isText() const = 0;
- virtual void setColor(const LLColor4&) {}
- virtual void onCommit() {};
-
- virtual BOOL handleClick() { return FALSE; }
- virtual void setEnabled(BOOL enable) { }
-
-private:
- S32 mWidth;
-};
-
-/*
- * Draws a horizontal line.
- */
-class LLScrollListSeparator : public LLScrollListCell
-{
-public:
- LLScrollListSeparator(S32 width);
- virtual ~LLScrollListSeparator() {};
- virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const; // truncate to given width, if possible
- virtual S32 getHeight() const;
- virtual BOOL isText() const { return FALSE; }
-};
-
-/*
- * Cell displaying a text label.
- */
-class LLScrollListText : public LLScrollListCell
-{
-public:
- LLScrollListText( const std::string& text, const LLFontGL* font, S32 width = 0, U8 font_style = LLFontGL::NORMAL, LLFontGL::HAlign font_alignment = LLFontGL::LEFT, LLColor4& color = LLColor4::black, BOOL use_color = FALSE, BOOL visible = TRUE);
- /*virtual*/ ~LLScrollListText();
-
- virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const;
- virtual S32 getContentWidth() const;
- virtual S32 getHeight() const;
- virtual void setValue(const LLSD& value);
- virtual const LLSD getValue() const;
- virtual BOOL getVisible() const;
- virtual void highlightText(S32 offset, S32 num_chars);
-
- virtual void setColor(const LLColor4&);
- virtual BOOL isText() const;
-
- void setText(const LLStringExplicit& text);
- void setFontStyle(const U8 font_style) { mFontStyle = font_style; }
-
-private:
- LLUIString mText;
- const LLFontGL* mFont;
- LLColor4 mColor;
- U8 mUseColor;
- U8 mFontStyle;
- LLFontGL::HAlign mFontAlignment;
- BOOL mVisible;
- S32 mHighlightCount;
- S32 mHighlightOffset;
-
- LLPointer<LLUIImage> mRoundedRectImage;
-
- static U32 sCount;
-};
-
-
-class LLScrollListDate : public LLScrollListText
-{
-public:
- LLScrollListDate( const LLDate& date, const LLFontGL* font, S32 width=0, U8 font_style = LLFontGL::NORMAL, LLFontGL::HAlign font_alignment = LLFontGL::LEFT, LLColor4& color = LLColor4::black, BOOL use_color = FALSE, BOOL visible = TRUE);
- virtual void setValue(const LLSD& value);
- virtual const LLSD getValue() const;
-
-private:
- LLDate mDate;
-};
-
-/*
- * Cell displaying an image.
- */
-class LLScrollListIcon : public LLScrollListCell
-{
-public:
- LLScrollListIcon( LLUIImagePtr icon, S32 width = 0);
- LLScrollListIcon(const LLSD& value, S32 width = 0);
- /*virtual*/ ~LLScrollListIcon();
- virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const;
- virtual S32 getWidth() const;
- virtual S32 getHeight() const { return mIcon ? mIcon->getHeight() : 0; }
- virtual const LLSD getValue() const { return mIcon.isNull() ? LLStringUtil::null : mIcon->getName(); }
- virtual void setColor(const LLColor4&);
- virtual BOOL isText()const { return FALSE; }
- virtual void setValue(const LLSD& value);
-
-private:
- LLUIImagePtr mIcon;
- LLColor4 mColor;
-};
-
-/*
- * An interactive cell containing a check box.
- */
-class LLScrollListCheck : public LLScrollListCell
-{
-public:
- LLScrollListCheck( LLCheckBoxCtrl* check_box, S32 width = 0);
- /*virtual*/ ~LLScrollListCheck();
- virtual void draw(const LLColor4& color, const LLColor4& highlight_color) const;
- virtual S32 getHeight() const { return 0; }
- virtual const LLSD getValue() const { return mCheckBox->getValue(); }
- virtual void setValue(const LLSD& value) { mCheckBox->setValue(value); }
- virtual void onCommit() { mCheckBox->onCommit(); }
-
- virtual BOOL handleClick();
- virtual void setEnabled(BOOL enable) { mCheckBox->setEnabled(enable); }
-
- LLCheckBoxCtrl* getCheckBox() { return mCheckBox; }
- virtual BOOL isText() const { return FALSE; }
-
-private:
- LLCheckBoxCtrl* mCheckBox;
-};
-
-/*
- * A simple data class describing a column within a scroll list.
- */
-class LLScrollListColumn
-{
-public:
- LLScrollListColumn();
- LLScrollListColumn(const LLSD &sd, LLScrollListCtrl* parent);
-
- void setWidth(S32 width);
- S32 getWidth() const { return mWidth; }
-
- // Public data is fine so long as this remains a simple struct-like data class.
- // If it ever gets any smarter than that, these should all become private
- // with protected or public accessor methods added as needed. -MG
- std::string mName;
- std::string mSortingColumn;
- BOOL mSortAscending;
- std::string mLabel;
- F32 mRelWidth;
- BOOL mDynamicWidth;
- S32 mMaxContentWidth;
- S32 mIndex;
- LLScrollListCtrl* mParentCtrl;
- class LLColumnHeader* mHeader;
- LLFontGL::HAlign mFontAlignment;
-
-private:
- S32 mWidth;
-
-};
+class LLScrollListCell;
+class LLTextBox;
+class LLContextMenu;
-class LLColumnHeader : public LLComboBox
-{
-public:
- LLColumnHeader(const std::string& label, const LLRect &rect, LLScrollListColumn* column, const LLFontGL *font = NULL);
- ~LLColumnHeader();
-
- /*virtual*/ void draw();
- /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
-
- /*virtual*/ void showList();
- /*virtual*/ LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding);
- /*virtual*/ void userSetShape(const LLRect& new_rect);
-
- void setImage(const std::string &image_name);
- LLScrollListColumn* getColumn() { return mColumn; }
- void setHasResizableElement(BOOL resizable);
- void updateResizeBars();
- BOOL canResize();
- void enableResizeBar(BOOL enable);
- std::string getLabel() { return mOrigLabel; }
-
- static void onSelectSort(LLUICtrl* ctrl, void* user_data);
- static void onClick(void* user_data);
- static void onMouseDown(void* user_data);
- static void onHeldDown(void* user_data);
-
-private:
- LLScrollListColumn* mColumn;
- LLResizeBar* mResizeBar;
- std::string mOrigLabel;
- LLUIString mAscendingText;
- LLUIString mDescendingText;
- BOOL mShowSortOptions;
- BOOL mHasResizableElement;
-};
-
-class LLScrollListItem
+class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
+ public LLCtrlListInterface, public LLCtrlScrollInterface
{
public:
- LLScrollListItem( BOOL enabled = TRUE, void* userdata = NULL, const LLUUID& uuid = LLUUID::null )
- : mSelected(FALSE), mEnabled( enabled ), mUserdata( userdata ), mItemValue( uuid ), mColumns() {}
- LLScrollListItem( LLSD item_value, void* userdata = NULL )
- : mSelected(FALSE), mEnabled( TRUE ), mUserdata( userdata ), mItemValue( item_value ), mColumns() {}
-
- virtual ~LLScrollListItem();
-
- void setSelected( BOOL b ) { mSelected = b; }
- BOOL getSelected() const { return mSelected; }
-
- void setEnabled( BOOL b );
- BOOL getEnabled() const { return mEnabled; }
+ struct Contents : public LLInitParam::Block<Contents>
+ {
+ Multiple<LLScrollListColumn::Params> columns;
+ Multiple<LLScrollListItem::Params> rows;
- void setUserdata( void* userdata ) { mUserdata = userdata; }
- void* getUserdata() const { return mUserdata; }
+ //Multiple<Contents> groups;
- LLUUID getUUID() const { return mItemValue.asUUID(); }
- LLSD getValue() const { return mItemValue; }
+ Contents();
+ };
- // If width = 0, just use the width of the text. Otherwise override with
- // specified width in pixels.
- void addColumn( const std::string& text, const LLFontGL* font, S32 width = 0 , U8 font_style = LLFontGL::NORMAL, LLFontGL::HAlign font_alignment = LLFontGL::LEFT, BOOL visible = TRUE)
- { mColumns.push_back( new LLScrollListText(text, font, width, font_style, font_alignment, LLColor4::black, FALSE, visible) ); }
-
- void addColumn( LLUIImagePtr icon, S32 width = 0 )
- { mColumns.push_back( new LLScrollListIcon(icon, width) ); }
-
- void addColumn( LLCheckBoxCtrl* check, S32 width = 0 )
- { mColumns.push_back( new LLScrollListCheck(check,width) ); }
-
- void setNumColumns(S32 columns);
-
- void setColumn( S32 column, LLScrollListCell *cell );
+ // *TODO: Add callbacks to Params
+ typedef boost::function<void (void)> callback_t;
- S32 getNumColumns() const { return mColumns.size(); }
-
- LLScrollListCell *getColumn(const S32 i) const { if (0 <= i && i < (S32)mColumns.size()) { return mColumns[i]; } return NULL; }
-
- std::string getContentsCSV() const;
-
- virtual void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding);
-
-private:
- BOOL mSelected;
- BOOL mEnabled;
- void* mUserdata;
- LLSD mItemValue;
- std::vector<LLScrollListCell *> mColumns;
-};
-
-/*
- * A graphical control representing a scrollable table.
- * Cells in the table can be simple text or more complicated things
- * such as icons or even interactive elements like check boxes.
- */
-class LLScrollListItemComment : public LLScrollListItem
-{
-public:
- LLScrollListItemComment(const std::string& comment_string, const LLColor4& color);
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ // behavioral flags
+ Optional<bool> multi_select,
+ commit_on_keyboard_movement;
+
+ // display flags
+ Optional<bool> has_border,
+ draw_heading,
+ draw_stripes,
+ background_visible,
+ scroll_bar_bg_visible;
+
+ // layout
+ Optional<S32> column_padding,
+ page_lines,
+ heading_height;
+
+ // sort and search behavior
+ Optional<S32> search_column,
+ sort_column;
+ Optional<bool> sort_ascending;
+
+ // colors
+ Optional<LLUIColor> fg_unselected_color,
+ fg_selected_color,
+ bg_selected_color,
+ fg_disable_color,
+ bg_writeable_color,
+ bg_readonly_color,
+ bg_stripe_color,
+ hovered_color,
+ highlighted_color,
+ scroll_bar_bg_color;
+
+ Optional<Contents> contents;
+
+ Optional<LLViewBorder::Params> border;
+
+ Params();
+ };
- /*virtual*/ void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding);
-private:
- LLColor4 mColor;
-};
-
-class LLScrollListItemSeparator : public LLScrollListItem
-{
-public:
- LLScrollListItemSeparator();
+protected:
+ friend class LLUICtrlFactory;
- /*virtual*/ void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding);
-};
+ LLScrollListCtrl(const Params&);
-class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
- public LLCtrlListInterface, public LLCtrlScrollInterface
-{
public:
- LLScrollListCtrl(
- const std::string& name,
- const LLRect& rect,
- void (*commit_callback)(LLUICtrl*, void*),
- void* callback_userdata,
- BOOL allow_multiple_selection,
- BOOL draw_border = TRUE);
-
virtual ~LLScrollListCtrl();
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- void setScrollListParameters(LLXMLNodePtr node);
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
-
S32 isEmpty() const;
void deleteAllItems() { clearRows(); }
// Sets an array of column descriptors
- void setColumnHeadings(LLSD headings);
+ void setColumnHeadings(const LLSD& headings);
void sortByColumnIndex(U32 column, BOOL ascending);
// LLCtrlListInterface functions
virtual S32 getItemCount() const;
// Adds a single column descriptor: ["name" : string, "label" : string, "width" : integer, "relwidth" : integer ]
- virtual void addColumn(const LLSD& column, EAddPosition pos = ADD_BOTTOM);
+ virtual void addColumn(const LLScrollListColumn::Params& column, EAddPosition pos = ADD_BOTTOM);
+ virtual void addColumn(const LLSD& column, EAddPosition pos = ADD_BOTTOM);
virtual void clearColumns();
virtual void setColumnLabel(const std::string& column, const std::string& label);
-
+ virtual bool preProcessChildNode(LLXMLNodePtr child);
virtual LLScrollListColumn* getColumn(S32 index);
+ virtual LLScrollListColumn* getColumn(const std::string& name);
virtual S32 getNumColumns() const { return mColumnsIndexed.size(); }
// Adds a single element, from an array of:
// "columns" => [ "column" => column name, "value" => value, "type" => type, "font" => font, "font-style" => style ], "id" => uuid
// Creates missing columns automatically.
- virtual LLScrollListItem* addElement(const LLSD& value, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL);
+ virtual LLScrollListItem* addElement(const LLSD& element, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL);
+ virtual LLScrollListItem* addRow(const LLScrollListItem::Params& value, EAddPosition pos = ADD_BOTTOM);
// Simple add element. Takes a single array of:
// [ "value" => value, "font" => font, "font-style" => style ]
virtual void clearRows(); // clears all elements
@@ -421,10 +193,14 @@ public:
void deleteSelectedItems();
void deselectAllItems(BOOL no_commit_on_change = FALSE); // by default, go ahead and commit on selection change
- void highlightNthItem( S32 index );
- void setDoubleClickCallback( void (*cb)(void*) ) { mOnDoubleClickCallback = cb; }
- void setMaximumSelectCallback( void (*cb)(void*) ) { mOnMaximumSelectCallback = cb; }
- void setSortChangedCallback( void (*cb)(void*) ) { mOnSortChangedCallback = cb; }
+ void clearHighlightedItems();
+ void mouseOverHighlightNthItem( S32 index );
+
+ void setDoubleClickCallback( callback_t cb ) { mOnDoubleClickCallback = cb; }
+ void setMaximumSelectCallback( callback_t cb) { mOnMaximumSelectCallback = cb; }
+ void setSortChangedCallback( callback_t cb) { mOnSortChangedCallback = cb; }
+ // Convenience function; *TODO: replace with setter above + boost::bind() in calling code
+ void setDoubleClickCallback( boost::function<void (void* userdata)> cb, void* userdata) { mOnDoubleClickCallback = boost::bind(cb, userdata); }
void swapWithNext(S32 index);
void swapWithPrevious(S32 index);
@@ -435,24 +211,24 @@ public:
S32 getItemIndex( LLScrollListItem* item ) const;
S32 getItemIndex( const LLUUID& item_id ) const;
- LLScrollListItem* addCommentText( const std::string& comment_text, EAddPosition pos = ADD_BOTTOM);
+ void setCommentText( const std::string& comment_text);
LLScrollListItem* addSeparator(EAddPosition pos);
// "Simple" interface: use this when you're creating a list that contains only unique strings, only
// one of which can be selected at a time.
virtual LLScrollListItem* addSimpleElement(const std::string& value, EAddPosition pos = ADD_BOTTOM, const LLSD& id = LLSD());
-
BOOL selectItemByLabel( const std::string& item, BOOL case_sensitive = TRUE ); // FALSE if item not found
BOOL selectItemByPrefix(const std::string& target, BOOL case_sensitive = TRUE);
BOOL selectItemByPrefix(const LLWString& target, BOOL case_sensitive = TRUE);
+ LLScrollListItem* getItemByLabel( const std::string& item, BOOL case_sensitive = TRUE, S32 column = 0 );
const std::string getSelectedItemLabel(S32 column = 0) const;
LLSD getSelectedValue();
- // DEPRECATED: Use LLSD versions of addCommentText() and getSelectedValue().
+ // DEPRECATED: Use LLSD versions of setCommentText() and getSelectedValue().
// "StringUUID" interface: use this when you're creating a list that contains non-unique strings each of which
// has an associated, unique UUID, and only one of which can be selected at a time.
- LLScrollListItem* addStringUUIDItem(const std::string& item_text, const LLUUID& id, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE, S32 column_width = 0);
+ LLScrollListItem* addStringUUIDItem(const std::string& item_text, const LLUUID& id, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE);
LLUUID getStringUUIDSelectedItem() const;
LLScrollListItem* getFirstSelected() const;
@@ -475,7 +251,8 @@ public:
void setBgStripeColor(const LLColor4& c) { mBgStripeColor = c; }
void setFgSelectedColor(const LLColor4 &c) { mFgSelectedColor = c; }
void setFgUnselectedColor(const LLColor4 &c){ mFgUnselectedColor = c; }
- void setHighlightedColor(const LLColor4 &c) { mHighlightedColor = c; }
+ void setHoveredColor(const LLColor4 &c) { mHoveredColor = c; }
+ void setHighlightedColor(const LLColor4 &c) { mHighlightedColor = c; }
void setFgDisableColor(const LLColor4 &c) { mFgDisabledColor = c; }
void setBackgroundVisible(BOOL b) { mBackgroundVisible = b; }
@@ -500,20 +277,26 @@ public:
void clearSearchString() { mSearchString.clear(); }
+ // support right-click context menus for avatar/group lists
+ enum ContextMenuType { MENU_NONE, MENU_AVATAR, MENU_GROUP };
+ void setContextMenu(const ContextMenuType &menu) { mContextMenuType = menu; }
+
// Overridden from LLView
/*virtual*/ void draw();
/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
/*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char);
/*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
- /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect);
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
/*virtual*/ void setEnabled(BOOL enabled);
/*virtual*/ void setFocus( BOOL b );
/*virtual*/ void onFocusReceived();
/*virtual*/ void onFocusLost();
+ /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
virtual BOOL isDirty() const;
@@ -527,17 +310,24 @@ public:
LLRect getItemListRect() { return mItemListRect; }
+ /// Returns rect, in local coords, of a given row/column
+ LLRect getCellRect(S32 row_index, S32 column_index);
+
// Used "internally" by the scroll bar.
- static void onScrollChange( S32 new_pos, LLScrollbar* src, void* userdata );
+ void onScrollChange( S32 new_pos, LLScrollbar* src );
static void onClickColumn(void *userdata);
- void updateColumns();
+ virtual void updateColumns();
void calcColumnWidths();
S32 getMaxContentWidth() { return mMaxContentWidth; }
- void setDisplayHeading(BOOL display);
void setHeadingHeight(S32 heading_height);
+ /**
+ * Sets max visible lines without scroolbar, if this value equals to 0,
+ * then display all items.
+ */
+ void setPageLines(S32 page_lines );
void setCollapseEmptyColumns(BOOL collapse);
LLScrollListItem* hitItem(S32 x,S32 y);
@@ -559,15 +349,16 @@ public:
std::string getSortColumnName();
BOOL getSortAscending() { return mSortColumns.empty() ? TRUE : mSortColumns.back().second; }
- BOOL needsSorting();
+ BOOL hasSortOrder() const;
- S32 selectMultiple( LLDynamicArray<LLUUID> ids );
- void sortItems();
+ S32 selectMultiple( std::vector<LLUUID> ids );
+ // conceptually const, but mutates mItemList
+ void updateSort() const;
// sorts a list without affecting the permanent sort order (so further list insertions can be unsorted, for example)
void sortOnce(S32 column, BOOL ascending);
// manually call this whenever editing list items in place to flag need for resorting
- void setSorted(BOOL sorted) { mSorted = sorted; }
+ void setNeedsSort(bool val = true) { mSorted = !val; }
void dirtyColumns(); // some operation has potentially affected column layout or ordering
protected:
@@ -591,11 +382,13 @@ protected:
typedef std::deque<LLScrollListItem *> item_list;
item_list& getItemList() { return mItemList; }
+ void updateLineHeight();
+
private:
void selectPrevItem(BOOL extend_selection);
void selectNextItem(BOOL extend_selection);
void drawItems();
- void updateLineHeight();
+
void updateLineHeightInsert(LLScrollListItem* item);
void reportInvalidInput();
BOOL isRepeatedChars(const LLWString& string) const;
@@ -603,10 +396,11 @@ private:
void deselectItem(LLScrollListItem* itemp);
void commitIfChanged();
BOOL setSort(S32 column, BOOL ascending);
+ S32 getLinesPerPage();
-
- S32 mCurIndex; // For get[First/Next]Data
- S32 mCurSelectedIndex; // For get[First/Next]Selected
+ static void showNameDetails(std::string id, bool is_group);
+ static void copyNameToClipboard(std::string id, bool is_group);
+ static void copySLURLToClipboard(std::string id, bool is_group);
S32 mLineHeight; // the max height of a single line
S32 mScrollLines; // how many lines we've scrolled down
@@ -621,10 +415,10 @@ private:
BOOL mSelectionChanged;
BOOL mNeedsScroll;
BOOL mCanSelect;
- BOOL mDisplayColumnHeaders;
+ const BOOL mDisplayColumnHeaders;
BOOL mColumnsDirty;
- item_list mItemList;
+ mutable item_list mItemList;
LLScrollListItem *mLastSelected;
@@ -637,22 +431,24 @@ private:
BOOL mBackgroundVisible;
BOOL mDrawStripes;
- LLColor4 mBgWriteableColor;
- LLColor4 mBgReadOnlyColor;
- LLColor4 mBgSelectedColor;
- LLColor4 mBgStripeColor;
- LLColor4 mFgSelectedColor;
- LLColor4 mFgUnselectedColor;
- LLColor4 mFgDisabledColor;
- LLColor4 mHighlightedColor;
+ LLUIColor mBgWriteableColor;
+ LLUIColor mBgReadOnlyColor;
+ LLUIColor mBgSelectedColor;
+ LLUIColor mBgStripeColor;
+ LLUIColor mFgSelectedColor;
+ LLUIColor mFgUnselectedColor;
+ LLUIColor mFgDisabledColor;
+ LLUIColor mHoveredColor;
+ LLUIColor mHighlightedColor;
S32 mBorderThickness;
- void (*mOnDoubleClickCallback)(void* userdata);
- void (*mOnMaximumSelectCallback)(void* userdata );
- void (*mOnSortChangedCallback)(void* userdata);
+ callback_t mOnDoubleClickCallback;
+ callback_t mOnMaximumSelectCallback;
+ callback_t mOnSortChangedCallback;
S32 mHighlightedItem;
class LLViewBorder* mBorder;
+ LLContextMenu *mPopupMenu;
LLWString mSearchString;
LLFrameTimer mSearchTimer;
@@ -662,7 +458,7 @@ private:
S32 mTotalStaticColumnWidth;
S32 mTotalColumnPadding;
- BOOL mSorted;
+ mutable bool mSorted;
typedef std::map<std::string, LLScrollListColumn> column_map_t;
column_map_t mColumns;
@@ -670,15 +466,13 @@ private:
BOOL mDirty;
S32 mOriginalSelection;
+ ContextMenuType mContextMenuType;
+
typedef std::vector<LLScrollListColumn*> ordered_columns_t;
ordered_columns_t mColumnsIndexed;
typedef std::pair<S32, BOOL> sort_column_t;
std::vector<sort_column_t> mSortColumns;
-
- // HACK: Did we draw one selected item this frame?
- BOOL mDrewSelected;
}; // end class LLScrollListCtrl
-
#endif // LL_SCROLLLISTCTRL_H
diff --git a/indra/llui/llscrolllistitem.cpp b/indra/llui/llscrolllistitem.cpp
new file mode 100644
index 0000000000..2c5e0d24cd
--- /dev/null
+++ b/indra/llui/llscrolllistitem.cpp
@@ -0,0 +1,156 @@
+/**
+ * @file llscrolllistitem.cpp
+ * @brief Scroll lists are composed of rows (items), each of which
+ * contains columns (cells).
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llscrolllistitem.h"
+
+#include "llrect.h"
+#include "llui.h"
+
+
+//---------------------------------------------------------------------------
+// LLScrollListItem
+//---------------------------------------------------------------------------
+
+LLScrollListItem::LLScrollListItem( const Params& p )
+: mSelected(FALSE),
+ mHighlighted(FALSE),
+ mEnabled(p.enabled),
+ mUserdata(p.userdata),
+ mItemValue(p.value)
+{
+}
+
+
+LLScrollListItem::~LLScrollListItem()
+{
+ std::for_each(mColumns.begin(), mColumns.end(), DeletePointer());
+}
+
+void LLScrollListItem::addColumn(const LLScrollListCell::Params& p)
+{
+ mColumns.push_back(LLScrollListCell::create(p));
+}
+
+void LLScrollListItem::setNumColumns(S32 columns)
+{
+ S32 prev_columns = mColumns.size();
+ if (columns < prev_columns)
+ {
+ std::for_each(mColumns.begin()+columns, mColumns.end(), DeletePointer());
+ }
+
+ mColumns.resize(columns);
+
+ for (S32 col = prev_columns; col < columns; ++col)
+ {
+ mColumns[col] = NULL;
+ }
+}
+
+void LLScrollListItem::setColumn( S32 column, LLScrollListCell *cell )
+{
+ if (column < (S32)mColumns.size())
+ {
+ delete mColumns[column];
+ mColumns[column] = cell;
+ }
+ else
+ {
+ llerrs << "LLScrollListItem::setColumn: bad column: " << column << llendl;
+ }
+}
+
+
+S32 LLScrollListItem::getNumColumns() const
+{
+ return mColumns.size();
+}
+
+LLScrollListCell* LLScrollListItem::getColumn(const S32 i) const
+{
+ if (0 <= i && i < (S32)mColumns.size())
+ {
+ return mColumns[i];
+ }
+ return NULL;
+}
+
+std::string LLScrollListItem::getContentsCSV() const
+{
+ std::string ret;
+
+ S32 count = getNumColumns();
+ for (S32 i=0; i<count; ++i)
+ {
+ ret += getColumn(i)->getValue().asString();
+ if (i < count-1)
+ {
+ ret += ", ";
+ }
+ }
+
+ return ret;
+}
+
+
+void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding)
+{
+ // draw background rect
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ LLRect bg_rect = rect;
+ gl_rect_2d( bg_rect, bg_color );
+
+ S32 cur_x = rect.mLeft;
+ S32 num_cols = getNumColumns();
+ S32 cur_col = 0;
+
+ for (LLScrollListCell* cell = getColumn(0); cur_col < num_cols; cell = getColumn(++cur_col))
+ {
+ // Two ways a cell could be hidden
+ if (cell->getWidth() < 0
+ || !cell->getVisible()) continue;
+
+ LLUI::pushMatrix();
+ {
+ LLUI::translate((F32) cur_x, (F32) rect.mBottom, 0.0f);
+
+ cell->draw( fg_color, highlight_color );
+ }
+ LLUI::popMatrix();
+
+ cur_x += cell->getWidth() + column_padding;
+ }
+}
+
diff --git a/indra/llui/llscrolllistitem.h b/indra/llui/llscrolllistitem.h
new file mode 100644
index 0000000000..15b86cc945
--- /dev/null
+++ b/indra/llui/llscrolllistitem.h
@@ -0,0 +1,131 @@
+/**
+ * @file llscrolllistitem.h
+ * @brief Scroll lists are composed of rows (items), each of which
+ * contains columns (cells).
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLSCROLLLISTITEM_H
+#define LLSCROLLLISTITEM_H
+
+#include "llpointer.h" // LLPointer<>
+#include "llsd.h"
+#include "v4color.h"
+#include "llinitparam.h"
+#include "llscrolllistcell.h"
+
+#include <vector>
+
+class LLCoordGL;
+class LLCheckBoxCtrl;
+class LLResizeBar;
+class LLScrollListCtrl;
+class LLScrollColumnHeader;
+class LLUIImage;
+
+//---------------------------------------------------------------------------
+// LLScrollListItem
+//---------------------------------------------------------------------------
+class LLScrollListItem
+{
+ friend class LLScrollListCtrl;
+public:
+ struct Params : public LLInitParam::Block<Params>
+ {
+ Optional<bool> enabled;
+ Optional<void*> userdata;
+ Optional<LLSD> value;
+
+ Ignored name; // use for localization tools
+ Ignored type;
+ Ignored length;
+
+ Multiple<LLScrollListCell::Params> columns;
+
+ Params()
+ : enabled("enabled", true),
+ value("value"),
+ name("name"),
+ type("type"),
+ length("length"),
+ columns("columns")
+ {
+ addSynonym(columns, "column");
+ addSynonym(value, "id");
+ }
+ };
+
+ virtual ~LLScrollListItem();
+
+ void setSelected( BOOL b ) { mSelected = b; }
+ BOOL getSelected() const { return mSelected; }
+
+ void setEnabled( BOOL b ) { mEnabled = b; }
+ BOOL getEnabled() const { return mEnabled; }
+
+ void setHighlighted( BOOL b ) { mHighlighted = b; }
+ BOOL getHighlighted() const { return mHighlighted; }
+
+ void setUserdata( void* userdata ) { mUserdata = userdata; }
+ void* getUserdata() const { return mUserdata; }
+
+ LLUUID getUUID() const { return mItemValue.asUUID(); }
+ LLSD getValue() const { return mItemValue; }
+
+ void setRect(LLRect rect) { mRectangle = rect; }
+ LLRect getRect() const { return mRectangle; }
+
+ void addColumn( const LLScrollListCell::Params& p );
+
+ void setNumColumns(S32 columns);
+
+ void setColumn( S32 column, LLScrollListCell *cell );
+
+ S32 getNumColumns() const;
+
+ LLScrollListCell *getColumn(const S32 i) const;
+
+ std::string getContentsCSV() const;
+
+ virtual void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding);
+
+protected:
+ LLScrollListItem( const Params& );
+
+private:
+ BOOL mSelected;
+ BOOL mHighlighted;
+ BOOL mEnabled;
+ void* mUserdata;
+ LLSD mItemValue;
+ std::vector<LLScrollListCell *> mColumns;
+ LLRect mRectangle;
+};
+
+#endif
diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp
new file mode 100644
index 0000000000..4bb45a3065
--- /dev/null
+++ b/indra/llui/llsdparam.cpp
@@ -0,0 +1,150 @@
+/**
+ * @file llsdparam.cpp
+ * @brief parameter block abstraction for creating complex objects and
+ * parsing construction parameters from xml and LLSD
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+// Project includes
+#include "llsdparam.h"
+
+//
+// LLParamSDParser
+//
+LLParamSDParser::LLParamSDParser()
+{
+ using boost::bind;
+
+ registerParserFuncs<S32>(bind(&LLParamSDParser::readTypedValue<S32>, this, _1, &LLSD::asInteger),
+ bind(&LLParamSDParser::writeTypedValue<S32>, this, _1, _2));
+ registerParserFuncs<U32>(bind(&LLParamSDParser::readTypedValue<U32>, this, _1, &LLSD::asInteger),
+ bind(&LLParamSDParser::writeU32Param, this, _1, _2));
+ registerParserFuncs<F32>(bind(&LLParamSDParser::readTypedValue<F32>, this, _1, &LLSD::asReal),
+ bind(&LLParamSDParser::writeTypedValue<F32>, this, _1, _2));
+ registerParserFuncs<F64>(bind(&LLParamSDParser::readTypedValue<F64>, this, _1, &LLSD::asReal),
+ bind(&LLParamSDParser::writeTypedValue<F64>, this, _1, _2));
+ registerParserFuncs<bool>(bind(&LLParamSDParser::readTypedValue<F32>, this, _1, &LLSD::asBoolean),
+ bind(&LLParamSDParser::writeTypedValue<F32>, this, _1, _2));
+ registerParserFuncs<std::string>(bind(&LLParamSDParser::readTypedValue<std::string>, this, _1, &LLSD::asString),
+ bind(&LLParamSDParser::writeTypedValue<std::string>, this, _1, _2));
+ registerParserFuncs<LLUUID>(bind(&LLParamSDParser::readTypedValue<LLUUID>, this, _1, &LLSD::asUUID),
+ bind(&LLParamSDParser::writeTypedValue<LLUUID>, this, _1, _2));
+ registerParserFuncs<LLDate>(bind(&LLParamSDParser::readTypedValue<LLDate>, this, _1, &LLSD::asDate),
+ bind(&LLParamSDParser::writeTypedValue<LLDate>, this, _1, _2));
+ registerParserFuncs<LLURI>(bind(&LLParamSDParser::readTypedValue<LLURI>, this, _1, &LLSD::asURI),
+ bind(&LLParamSDParser::writeTypedValue<LLURI>, this, _1, _2));
+ registerParserFuncs<LLSD>(bind(&LLParamSDParser::readSDParam, this, _1),
+ bind(&LLParamSDParser::writeTypedValue<LLSD>, this, _1, _2));
+}
+
+bool LLParamSDParser::readSDParam(void* value_ptr)
+{
+ if (!mCurReadSD) return false;
+ *((LLSD*)value_ptr) = *mCurReadSD;
+ return true;
+}
+
+// special case handling of U32 due to ambiguous LLSD::assign overload
+bool LLParamSDParser::writeU32Param(const void* val_ptr, const parser_t::name_stack_t& name_stack)
+{
+ if (!mWriteSD) return false;
+
+ LLSD* sd_to_write = getSDWriteNode(name_stack);
+ if (!sd_to_write) return false;
+
+ sd_to_write->assign((S32)*((const U32*)val_ptr));
+ return true;
+}
+
+void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent)
+{
+ mCurReadSD = NULL;
+ mNameStack.clear();
+ setParseSilently(silent);
+
+ readSDValues(sd, block);
+}
+
+void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block)
+{
+ mWriteSD = &sd;
+ block.serializeBlock(*this);
+}
+
+void LLParamSDParser::readSDValues(const LLSD& sd, LLInitParam::BaseBlock& block)
+{
+ if (sd.isMap())
+ {
+ for (LLSD::map_const_iterator it = sd.beginMap();
+ it != sd.endMap();
+ ++it)
+ {
+ mNameStack.push_back(make_pair(it->first, newParseGeneration()));
+ readSDValues(it->second, block);
+ mNameStack.pop_back();
+ }
+ }
+ else if (sd.isArray())
+ {
+ for (LLSD::array_const_iterator it = sd.beginArray();
+ it != sd.endArray();
+ ++it)
+ {
+ mNameStack.back().second = newParseGeneration();
+ readSDValues(*it, block);
+ }
+ }
+ else
+ {
+ mCurReadSD = &sd;
+ block.submitValue(mNameStack, *this);
+ }
+}
+
+/*virtual*/ std::string LLParamSDParser::getCurrentElementName()
+{
+ std::string full_name = "sd";
+ for (name_stack_t::iterator it = mNameStack.begin();
+ it != mNameStack.end();
+ ++it)
+ {
+ full_name += llformat("[%s]", it->first.c_str());
+ }
+
+ return full_name;
+}
+
+LLSD* LLParamSDParser::getSDWriteNode(const parser_t::name_stack_t& name_stack)
+{
+ //TODO: implement nested LLSD writing
+ return mWriteSD;
+}
+
diff --git a/indra/llui/llsdparam.h b/indra/llui/llsdparam.h
new file mode 100644
index 0000000000..12f28f876f
--- /dev/null
+++ b/indra/llui/llsdparam.h
@@ -0,0 +1,107 @@
+/**
+ * @file llsdparam.h
+ * @brief parameter block abstraction for creating complex objects and
+ * parsing construction parameters from xml and LLSD
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSDPARAM_H
+#define LL_LLSDPARAM_H
+
+#include "llinitparam.h"
+
+class LLParamSDParser
+: public LLInitParam::Parser,
+ public LLSingleton<LLParamSDParser>
+{
+LOG_CLASS(LLParamSDParser);
+
+typedef LLInitParam::Parser parser_t;
+
+protected:
+ LLParamSDParser();
+ friend class LLSingleton<LLParamSDParser>;
+public:
+ void readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent = false);
+ void writeSD(LLSD& sd, const LLInitParam::BaseBlock& block);
+
+ /*virtual*/ std::string getCurrentElementName();
+
+private:
+ void readSDValues(const LLSD& sd, LLInitParam::BaseBlock& block);
+
+ template<typename T>
+ bool readTypedValue(void* val_ptr, boost::function<T(const LLSD&)> parser_func)
+ {
+ if (!mCurReadSD) return false;
+
+ *((T*)val_ptr) = parser_func(*mCurReadSD);
+ return true;
+ }
+
+ template<typename T>
+ bool writeTypedValue(const void* val_ptr, const parser_t::name_stack_t& name_stack)
+ {
+ if (!mWriteSD) return false;
+
+ LLSD* sd_to_write = getSDWriteNode(name_stack);
+ if (!sd_to_write) return false;
+
+ sd_to_write->assign(*((const T*)val_ptr));
+ return true;
+ }
+
+ LLSD* getSDWriteNode(const parser_t::name_stack_t& name_stack);
+
+ bool readSDParam(void* value_ptr);
+ bool writeU32Param(const void* value_ptr, const parser_t::name_stack_t& name_stack);
+
+ Parser::name_stack_t mNameStack;
+ const LLSD* mCurReadSD;
+ LLSD* mWriteSD;
+};
+
+template<typename T>
+class LLSDParamAdapter : public T
+ {
+ public:
+ LLSDParamAdapter() {}
+ LLSDParamAdapter(const LLSD& sd)
+ {
+ LLParamSDParser::instance().readSD(sd, *this);
+ }
+
+ LLSDParamAdapter(const T& val)
+ {
+ T::operator=(val);
+ }
+ };
+
+#endif // LL_LLSDPARAM_H
+
diff --git a/indra/llui/llsearcheditor.cpp b/indra/llui/llsearcheditor.cpp
new file mode 100644
index 0000000000..6fa99df82e
--- /dev/null
+++ b/indra/llui/llsearcheditor.cpp
@@ -0,0 +1,165 @@
+/**
+ * @file llsearcheditor.cpp
+ * @brief LLSearchEditor implementation
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Text editor widget to let users enter a single line.
+
+#include "linden_common.h"
+
+#include "llsearcheditor.h"
+
+LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)
+: LLUICtrl(p),
+ mSearchButton(NULL),
+ mClearButton(NULL)
+{
+ S32 srch_btn_top = p.search_button.top_pad + p.search_button.rect.height;
+ S32 srch_btn_right = p.search_button.rect.width + p.search_button.left_pad;
+ LLRect srch_btn_rect(p.search_button.left_pad, srch_btn_top, srch_btn_right, p.search_button.top_pad);
+ S32 text_pad_left = p.text_pad_left;
+
+ if (p.search_button_visible)
+ text_pad_left += srch_btn_rect.getWidth();
+
+ // Set up line editor.
+ LLLineEditor::Params line_editor_params(p);
+ line_editor_params.name("filter edit box");
+ line_editor_params.rect(getLocalRect());
+ line_editor_params.follows.flags(FOLLOWS_ALL);
+ line_editor_params.text_pad_left(text_pad_left);
+ line_editor_params.revert_on_esc(false);
+ line_editor_params.commit_callback.function(boost::bind(&LLUICtrl::onCommit, this));
+ line_editor_params.keystroke_callback(boost::bind(&LLSearchEditor::handleKeystroke, this));
+
+ mSearchEditor = LLUICtrlFactory::create<LLLineEditor>(line_editor_params);
+ addChild(mSearchEditor);
+
+ if (p.search_button_visible)
+ {
+ // Set up search button.
+ LLButton::Params srch_btn_params(p.search_button);
+ srch_btn_params.name(std::string("search button"));
+ srch_btn_params.rect(srch_btn_rect) ;
+ srch_btn_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_TOP);
+ srch_btn_params.tab_stop(false);
+ srch_btn_params.click_callback.function(boost::bind(&LLUICtrl::onCommit, this));
+
+ mSearchButton = LLUICtrlFactory::create<LLButton>(srch_btn_params);
+ mSearchEditor->addChild(mSearchButton);
+ }
+
+ if (p.clear_button_visible)
+ {
+ // Set up clear button.
+ S32 clr_btn_width = getRect().getHeight(); // button is square, and as tall as search editor
+ LLRect clear_btn_rect(getRect().getWidth() - clr_btn_width, getRect().getHeight(), getRect().getWidth(), 0);
+ LLButton::Params clr_btn_params(p.clear_button);
+ clr_btn_params.name(std::string("clear button"));
+ clr_btn_params.rect(clear_btn_rect) ;
+ clr_btn_params.follows.flags(FOLLOWS_RIGHT|FOLLOWS_TOP);
+ clr_btn_params.tab_stop(false);
+ clr_btn_params.click_callback.function(boost::bind(&LLSearchEditor::onClearButtonClick, this, _2));
+
+ mClearButton = LLUICtrlFactory::create<LLButton>(clr_btn_params);
+ mSearchEditor->addChild(mClearButton);
+ }
+}
+
+//virtual
+void LLSearchEditor::draw()
+{
+ if (mClearButton)
+ mClearButton->setVisible(!mSearchEditor->getWText().empty());
+
+ LLUICtrl::draw();
+}
+
+//virtual
+void LLSearchEditor::setValue(const LLSD& value )
+{
+ mSearchEditor->setValue(value);
+}
+
+//virtual
+LLSD LLSearchEditor::getValue() const
+{
+ return mSearchEditor->getValue();
+}
+
+//virtual
+BOOL LLSearchEditor::setTextArg( const std::string& key, const LLStringExplicit& text )
+{
+ return mSearchEditor->setTextArg(key, text);
+}
+
+//virtual
+BOOL LLSearchEditor::setLabelArg( const std::string& key, const LLStringExplicit& text )
+{
+ return mSearchEditor->setLabelArg(key, text);
+}
+
+//virtual
+void LLSearchEditor::setLabel( const LLStringExplicit &new_label )
+{
+ mSearchEditor->setLabel(new_label);
+}
+
+//virtual
+void LLSearchEditor::clear()
+{
+ if (mSearchEditor)
+ {
+ mSearchEditor->clear();
+ }
+}
+
+//virtual
+void LLSearchEditor::setFocus( BOOL b )
+{
+ if (mSearchEditor)
+ {
+ mSearchEditor->setFocus(b);
+ }
+}
+
+void LLSearchEditor::onClearButtonClick(const LLSD& data)
+{
+ setText(LLStringUtil::null);
+ mSearchEditor->doDelete(); // force keystroke callback
+}
+
+void LLSearchEditor::handleKeystroke()
+{
+ if (mKeystrokeCallback)
+ {
+ mKeystrokeCallback(this, getValue());
+ }
+}
diff --git a/indra/llui/llsearcheditor.h b/indra/llui/llsearcheditor.h
new file mode 100644
index 0000000000..714aca9337
--- /dev/null
+++ b/indra/llui/llsearcheditor.h
@@ -0,0 +1,102 @@
+/**
+ * @file llsearcheditor.h
+ * @brief Text editor widget that represents a search operation
+ *
+ * Features:
+ * Text entry of a single line (text, delete, left and right arrow, insert, return).
+ * Callbacks either on every keystroke or just on the return key.
+ * Focus (allow multiple text entry widgets)
+ * Clipboard (cut, copy, and paste)
+ * Horizontal scrolling to allow strings longer than widget size allows
+ * Pre-validation (limit which keys can be used)
+ * Optional line history so previous entries can be recalled by CTRL UP/DOWN
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_SEARCHEDITOR_H
+#define LL_SEARCHEDITOR_H
+
+#include "lllineeditor.h"
+#include "llbutton.h"
+
+class LLSearchEditor : public LLUICtrl
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLLineEditor::Params>
+ {
+ Optional<LLButton::Params> search_button,
+ clear_button;
+ Optional<bool> search_button_visible,
+ clear_button_visible;
+ Optional<commit_callback_t> keystroke_callback;
+
+ Params()
+ : search_button("search_button"),
+ search_button_visible("search_button_visible"),
+ clear_button("clear_button"),
+ clear_button_visible("clear_button_visible")
+ {
+ name = "search_editor";
+ }
+ };
+
+protected:
+ LLSearchEditor(const Params&);
+ friend class LLUICtrlFactory;
+
+public:
+ virtual ~LLSearchEditor() {}
+
+ /*virtual*/ void draw();
+
+ void setText(const LLStringExplicit &new_text) { mSearchEditor->setText(new_text); }
+ const std::string& getText() const { return mSearchEditor->getText(); }
+
+ // LLUICtrl interface
+ virtual void setValue(const LLSD& value );
+ virtual LLSD getValue() const;
+ virtual BOOL setTextArg( const std::string& key, const LLStringExplicit& text );
+ virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
+ virtual void setLabel( const LLStringExplicit &new_label );
+ virtual void clear();
+ virtual void setFocus( BOOL b );
+
+ void setKeystrokeCallback( commit_callback_t cb ) { mKeystrokeCallback = cb; }
+
+protected:
+ void onClearButtonClick(const LLSD& data);
+ virtual void handleKeystroke();
+
+ commit_callback_t mKeystrokeCallback;
+ LLLineEditor* mSearchEditor;
+ LLButton* mSearchButton;
+ LLButton* mClearButton;
+};
+
+#endif // LL_SEARCHEDITOR_H
diff --git a/indra/llui/llslider.cpp b/indra/llui/llslider.cpp
index 4dfc904581..a6f729b396 100644
--- a/indra/llui/llslider.cpp
+++ b/indra/llui/llslider.cpp
@@ -40,53 +40,68 @@
#include "llfocusmgr.h"
#include "llkeyboard.h" // for the MASK constants
#include "llcontrol.h"
-#include "llimagegl.h"
-
-static LLRegisterWidget<LLSlider> r1("slider_bar");
-static LLRegisterWidget<LLSlider> r2("volume_slider");
-
-
-LLSlider::LLSlider(
- const std::string& name,
- const LLRect& rect,
- void (*on_commit_callback)(LLUICtrl* ctrl, void* userdata),
- void* callback_userdata,
- F32 initial_value,
- F32 min_value,
- F32 max_value,
- F32 increment,
- BOOL volume,
- const std::string& control_name)
- :
- LLUICtrl( name, rect, TRUE, on_commit_callback, callback_userdata,
- FOLLOWS_LEFT | FOLLOWS_TOP),
- mValue( initial_value ),
- mInitialValue( initial_value ),
- mMinValue( min_value ),
- mMaxValue( max_value ),
- mIncrement( increment ),
- mVolumeSlider( volume ),
- mMouseOffset( 0 ),
- mTrackColor( LLUI::sColorsGroup->getColor( "SliderTrackColor" ) ),
- mThumbOutlineColor( LLUI::sColorsGroup->getColor( "SliderThumbOutlineColor" ) ),
- mThumbCenterColor( LLUI::sColorsGroup->getColor( "SliderThumbCenterColor" ) ),
- mMouseDownCallback( NULL ),
- mMouseUpCallback( NULL )
+#include "lluictrlfactory.h"
+
+static LLDefaultChildRegistry::Register<LLSlider> r1("slider_bar");
+//FIXME: make this into an unregistered template so that code constructed sliders don't
+// have ambigious template lookup problem
+
+LLSlider::Params::Params()
+: orientation ("orientation", std::string ("horizontal")),
+ track_color("track_color"),
+ thumb_outline_color("thumb_outline_color"),
+ thumb_center_color("thumb_center_color"),
+ thumb_image("thumb_image"),
+ thumb_image_pressed("thumb_image_pressed"),
+ thumb_image_disabled("thumb_image_disabled"),
+ track_image_horizontal("track_image_horizontal"),
+ track_image_vertical("track_image_vertical"),
+ track_highlight_horizontal_image("track_highlight_horizontal_image"),
+ track_highlight_vertical_image("track_highlight_vertical_image"),
+ mouse_down_callback("mouse_down_callback"),
+ mouse_up_callback("mouse_up_callback")
{
- mThumbImage = LLUI::sImageProvider->getUIImage("icn_slide-thumb_dark.tga");
- mTrackImage = LLUI::sImageProvider->getUIImage("icn_slide-groove_dark.tga");
- mTrackHighlightImage = LLUI::sImageProvider->getUIImage("icn_slide-highlight.tga");
-
- // properly handle setting the starting thumb rect
- // do it this way to handle both the operating-on-settings
- // and standalone ways of using this
- setControlName(control_name, NULL);
- setValue(getValueF32());
+ follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP);
+}
+LLSlider::LLSlider(const LLSlider::Params& p)
+: LLF32UICtrl(p),
+ mMouseOffset( 0 ),
+ mOrientation ((p.orientation() == "horizontal") ? HORIZONTAL : VERTICAL),
+ mTrackColor(p.track_color()),
+ mThumbOutlineColor(p.thumb_outline_color()),
+ mThumbCenterColor(p.thumb_center_color()),
+ mThumbImage(p.thumb_image),
+ mThumbImagePressed(p.thumb_image_pressed),
+ mThumbImageDisabled(p.thumb_image_disabled),
+ mTrackImageHorizontal(p.track_image_horizontal),
+ mTrackImageVertical(p.track_image_vertical),
+ mTrackHighlightHorizontalImage(p.track_highlight_horizontal_image),
+ mTrackHighlightVerticalImage(p.track_highlight_vertical_image),
+ mMouseDownSignal(NULL),
+ mMouseUpSignal(NULL)
+{
+ mViewModel->setValue(p.initial_value);
updateThumbRect();
mDragStartThumbRect = mThumbRect;
+ setControlName(p.control_name, NULL);
+ setValue(getValueF32());
+
+ if (p.mouse_down_callback.isProvided())
+ {
+ setMouseDownCallback(initCommitCallback(p.mouse_down_callback));
+ }
+ if (p.mouse_up_callback.isProvided())
+ {
+ setMouseUpCallback(initCommitCallback(p.mouse_up_callback));
+ }
}
+LLSlider::~LLSlider()
+{
+ delete mMouseDownSignal;
+ delete mMouseUpSignal;
+}
void LLSlider::setValue(F32 value, BOOL from_event)
{
@@ -98,38 +113,54 @@ void LLSlider::setValue(F32 value, BOOL from_event)
value -= fmod(value, mIncrement);
value += mMinValue;
- if (!from_event && mValue != value)
+ if (!from_event && getValueF32() != value)
{
setControlValue(value);
}
- mValue = value;
+ LLF32UICtrl::setValue(value);
updateThumbRect();
}
void LLSlider::updateThumbRect()
{
- F32 t = (mValue - mMinValue) / (mMaxValue - mMinValue);
-
- S32 thumb_width = mThumbImage->getWidth();
- S32 thumb_height = mThumbImage->getHeight();
- S32 left_edge = (thumb_width / 2);
- S32 right_edge = getRect().getWidth() - (thumb_width / 2);
-
- S32 x = left_edge + S32( t * (right_edge - left_edge) );
- mThumbRect.mLeft = x - (thumb_width / 2);
- mThumbRect.mRight = mThumbRect.mLeft + thumb_width;
- mThumbRect.mBottom = getLocalRect().getCenterY() - (thumb_height / 2);
- mThumbRect.mTop = mThumbRect.mBottom + thumb_height;
+ const S32 DEFAULT_THUMB_SIZE = 16;
+ F32 t = (getValueF32() - mMinValue) / (mMaxValue - mMinValue);
+
+ S32 thumb_width = mThumbImage ? mThumbImage->getWidth() : DEFAULT_THUMB_SIZE;
+ S32 thumb_height = mThumbImage ? mThumbImage->getHeight() : DEFAULT_THUMB_SIZE;
+
+ if ( mOrientation == HORIZONTAL )
+ {
+ S32 left_edge = (thumb_width / 2);
+ S32 right_edge = getRect().getWidth() - (thumb_width / 2);
+
+ S32 x = left_edge + S32( t * (right_edge - left_edge) );
+ mThumbRect.mLeft = x - (thumb_width / 2);
+ mThumbRect.mRight = mThumbRect.mLeft + thumb_width;
+ mThumbRect.mBottom = getLocalRect().getCenterY() - (thumb_height / 2);
+ mThumbRect.mTop = mThumbRect.mBottom + thumb_height;
+ }
+ else
+ {
+ S32 top_edge = (thumb_height / 2);
+ S32 bottom_edge = getRect().getHeight() - (thumb_height / 2);
+
+ S32 y = top_edge + S32( t * (bottom_edge - top_edge) );
+ mThumbRect.mLeft = getLocalRect().getCenterX() - (thumb_width / 2);
+ mThumbRect.mRight = mThumbRect.mLeft + thumb_width;
+ mThumbRect.mBottom = y - (thumb_height / 2);
+ mThumbRect.mTop = mThumbRect.mBottom + thumb_height;
+ }
}
void LLSlider::setValueAndCommit(F32 value)
{
- F32 old_value = mValue;
+ F32 old_value = getValueF32();
setValue(value);
- if (mValue != old_value)
+ if (getValueF32() != old_value)
{
onCommit();
}
@@ -140,18 +171,32 @@ BOOL LLSlider::handleHover(S32 x, S32 y, MASK mask)
{
if( hasMouseCapture() )
{
- S32 thumb_half_width = mThumbImage->getWidth()/2;
- S32 left_edge = thumb_half_width;
- S32 right_edge = getRect().getWidth() - (thumb_half_width);
+ if ( mOrientation == HORIZONTAL )
+ {
+ S32 thumb_half_width = mThumbImage->getWidth()/2;
+ S32 left_edge = thumb_half_width;
+ S32 right_edge = getRect().getWidth() - (thumb_half_width);
- x += mMouseOffset;
- x = llclamp( x, left_edge, right_edge );
+ x += mMouseOffset;
+ x = llclamp( x, left_edge, right_edge );
- F32 t = F32(x - left_edge) / (right_edge - left_edge);
- setValueAndCommit(t * (mMaxValue - mMinValue) + mMinValue );
+ F32 t = F32(x - left_edge) / (right_edge - left_edge);
+ setValueAndCommit(t * (mMaxValue - mMinValue) + mMinValue );
+ }
+ else // mOrientation == VERTICAL
+ {
+ S32 thumb_half_height = mThumbImage->getHeight()/2;
+ S32 top_edge = thumb_half_height;
+ S32 bottom_edge = getRect().getHeight() - (thumb_half_height);
+
+ y += mMouseOffset;
+ y = llclamp(y, top_edge, bottom_edge);
+ F32 t = F32(y - top_edge) / (bottom_edge - top_edge);
+ setValueAndCommit(t * (mMaxValue - mMinValue) + mMinValue );
+ }
getWindow()->setCursor(UI_CURSOR_ARROW);
- lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" << llendl;
+ lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" << llendl;
}
else
{
@@ -169,10 +214,9 @@ BOOL LLSlider::handleMouseUp(S32 x, S32 y, MASK mask)
{
gFocusMgr.setMouseCapture( NULL );
- if( mMouseUpCallback )
- {
- mMouseUpCallback( this, mCallbackUserData );
- }
+ if (mMouseUpSignal)
+ (*mMouseUpSignal)( this, getValueF32() );
+
handled = TRUE;
make_ui_sound("UISndClickRelease");
}
@@ -191,10 +235,8 @@ BOOL LLSlider::handleMouseDown(S32 x, S32 y, MASK mask)
{
setFocus(TRUE);
}
- if( mMouseDownCallback )
- {
- mMouseDownCallback( this, mCallbackUserData );
- }
+ if (mMouseDownSignal)
+ (*mMouseDownSignal)( this, getValueF32() );
if (MASK_CONTROL & mask) // if CTRL is modifying
{
@@ -205,7 +247,9 @@ BOOL LLSlider::handleMouseDown(S32 x, S32 y, MASK mask)
// Find the offset of the actual mouse location from the center of the thumb.
if (mThumbRect.pointInRect(x,y))
{
- mMouseOffset = (mThumbRect.mLeft + mThumbImage->getWidth()/2) - x;
+ mMouseOffset = (mOrientation == HORIZONTAL)
+ ? (mThumbRect.mLeft + mThumbImage->getWidth()/2) - x
+ : (mThumbRect.mBottom + mThumbImage->getHeight()/2) - y;
}
else
{
@@ -227,15 +271,12 @@ BOOL LLSlider::handleKeyHere(KEY key, MASK mask)
BOOL handled = FALSE;
switch(key)
{
- case KEY_UP:
case KEY_DOWN:
- // eat up and down keys to be consistent
- handled = TRUE;
- break;
case KEY_LEFT:
setValueAndCommit(getValueF32() - getIncrement());
handled = TRUE;
break;
+ case KEY_UP:
case KEY_RIGHT:
setValueAndCommit(getValueF32() + getIncrement());
handled = TRUE;
@@ -246,8 +287,21 @@ BOOL LLSlider::handleKeyHere(KEY key, MASK mask)
return handled;
}
+BOOL LLSlider::handleScrollWheel(S32 x, S32 y, S32 clicks)
+{
+ if ( mOrientation == VERTICAL )
+ {
+ F32 new_val = getValueF32() - clicks * getIncrement();
+ setValueAndCommit(new_val);
+ return TRUE;
+ }
+ return LLF32UICtrl::handleScrollWheel(x,y,clicks);
+}
+
void LLSlider::draw()
{
+ F32 alpha = getDrawContext().mAlpha;
+
// since thumb image might still be decoding, need thumb to accomodate image size
updateThumbRect();
@@ -256,86 +310,83 @@ void LLSlider::draw()
// drawing solids requires texturing be disabled
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- F32 opacity = getEnabled() ? 1.f : 0.3f;
- LLColor4 center_color = (mThumbCenterColor % opacity);
- LLColor4 track_color = (mTrackColor % opacity);
-
// Track
- LLRect track_rect(mThumbImage->getWidth() / 2,
- getLocalRect().getCenterY() + (mTrackImage->getHeight() / 2),
- getRect().getWidth() - mThumbImage->getWidth() / 2,
- getLocalRect().getCenterY() - (mTrackImage->getHeight() / 2) );
- LLRect highlight_rect(track_rect.mLeft, track_rect.mTop, mThumbRect.getCenterX(), track_rect.mBottom);
- mTrackImage->draw(track_rect);
- mTrackHighlightImage->draw(highlight_rect);
+ LLPointer<LLUIImage>& trackImage = ( mOrientation == HORIZONTAL )
+ ? mTrackImageHorizontal
+ : mTrackImageVertical;
- // Thumb
- if( hasMouseCapture() )
+ LLPointer<LLUIImage>& trackHighlightImage = ( mOrientation == HORIZONTAL )
+ ? mTrackHighlightHorizontalImage
+ : mTrackHighlightVerticalImage;
+
+ LLRect track_rect;
+ LLRect highlight_rect;
+
+ if ( mOrientation == HORIZONTAL )
{
- // Show ghost where thumb was before dragging began.
- mThumbImage->draw(mDragStartThumbRect, mThumbCenterColor % 0.3f);
+ track_rect.set(mThumbImage->getWidth() / 2,
+ getLocalRect().getCenterY() + (trackImage->getHeight() / 2),
+ getRect().getWidth() - mThumbImage->getWidth() / 2,
+ getLocalRect().getCenterY() - (trackImage->getHeight() / 2) );
+ highlight_rect.set(track_rect.mLeft, track_rect.mTop, mThumbRect.getCenterX(), track_rect.mBottom);
+ }
+ else
+ {
+ track_rect.set(getLocalRect().getCenterX() - (trackImage->getWidth() / 2),
+ getRect().getHeight(),
+ getLocalRect().getCenterX() + (trackImage->getWidth() / 2),
+ 0);
+ highlight_rect.set(track_rect.mLeft, track_rect.mTop, track_rect.mRight, track_rect.mBottom);
}
+
+ trackImage->draw(track_rect, LLColor4::white % alpha);
+ trackHighlightImage->draw(highlight_rect, LLColor4::white % alpha);
+
+ // Thumb
if (hasFocus())
{
// Draw focus highlighting.
- mThumbImage->drawBorder(mThumbRect, gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());
+ mThumbImage->drawBorder(mThumbRect, gFocusMgr.getFocusColor() % alpha, gFocusMgr.getFocusFlashWidth());
}
- // Fill in the thumb.
- mThumbImage->draw(mThumbRect, hasMouseCapture() ? mThumbOutlineColor : center_color);
+ if( hasMouseCapture() ) // currently clicking on slider
+ {
+ // Show ghost where thumb was before dragging began.
+ if (mThumbImage.notNull())
+ {
+ mThumbImage->draw(mDragStartThumbRect, mThumbCenterColor.get() % (0.3f * alpha));
+ }
+ if (mThumbImagePressed.notNull())
+ {
+ mThumbImagePressed->draw(mThumbRect, mThumbOutlineColor % alpha);
+ }
+ }
+ else if (!isInEnabledChain())
+ {
+ if (mThumbImageDisabled.notNull())
+ {
+ mThumbImageDisabled->draw(mThumbRect, mThumbCenterColor % alpha);
+ }
+ }
+ else
+ {
+ if (mThumbImage.notNull())
+ {
+ mThumbImage->draw(mThumbRect, mThumbCenterColor % alpha);
+ }
+ }
+
LLUICtrl::draw();
}
-// virtual
-LLXMLNodePtr LLSlider::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLUICtrl::getXML();
-
- node->createChild("initial_val", TRUE)->setFloatValue(getInitialValue());
- node->createChild("min_val", TRUE)->setFloatValue(getMinValue());
- node->createChild("max_val", TRUE)->setFloatValue(getMaxValue());
- node->createChild("increment", TRUE)->setFloatValue(getIncrement());
- node->createChild("volume", TRUE)->setBoolValue(mVolumeSlider);
-
- return node;
+boost::signals2::connection LLSlider::setMouseDownCallback( const commit_signal_t::slot_type& cb )
+{
+ if (!mMouseDownSignal) mMouseDownSignal = new commit_signal_t();
+ return mMouseDownSignal->connect(cb);
}
-
-//static
-LLView* LLSlider::fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory)
-{
- std::string name("slider_bar");
- node->getAttributeString("name", name);
-
- LLRect rect;
- createRect(node, rect, parent, LLRect());
-
- F32 initial_value = 0.f;
- node->getAttributeF32("initial_val", initial_value);
-
- F32 min_value = 0.f;
- node->getAttributeF32("min_val", min_value);
-
- F32 max_value = 1.f;
- node->getAttributeF32("max_val", max_value);
-
- F32 increment = 0.1f;
- node->getAttributeF32("increment", increment);
-
- BOOL volume = node->hasName("volume_slider") ? TRUE : FALSE;
- node->getAttributeBOOL("volume", volume);
-
- LLSlider* slider = new LLSlider(name,
- rect,
- NULL,
- NULL,
- initial_value,
- min_value,
- max_value,
- increment,
- volume);
-
- slider->initFromXML(node, parent);
-
- return slider;
+boost::signals2::connection LLSlider::setMouseUpCallback( const commit_signal_t::slot_type& cb )
+{
+ if (!mMouseUpSignal) mMouseUpSignal = new commit_signal_t();
+ return mMouseUpSignal->connect(cb);
}
diff --git a/indra/llui/llslider.h b/indra/llui/llslider.h
index 154685fac1..45f8f81e40 100644
--- a/indra/llui/llslider.h
+++ b/indra/llui/llslider.h
@@ -33,79 +33,85 @@
#ifndef LL_LLSLIDER_H
#define LL_LLSLIDER_H
-#include "lluictrl.h"
+#include "llf32uictrl.h"
#include "v4color.h"
-class LLImageGL;
-
-class LLSlider : public LLUICtrl
+class LLSlider : public LLF32UICtrl
{
public:
- LLSlider(
- const std::string& name,
- const LLRect& rect,
- void (*on_commit_callback)(LLUICtrl* ctrl, void* userdata),
- void* callback_userdata,
- F32 initial_value,
- F32 min_value,
- F32 max_value,
- F32 increment,
- BOOL volume, //TODO: create a "volume" slider sub-class or just use image art, no? -MG
- const std::string& control_name = LLStringUtil::null );
-
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory);
+ enum ORIENTATION { HORIZONTAL, VERTICAL };
- void setValue( F32 value, BOOL from_event = FALSE );
- F32 getValueF32() const { return mValue; }
+ struct Params : public LLInitParam::Block<Params, LLF32UICtrl::Params>
+ {
+ Optional<std::string> orientation;
+
+ Optional<LLUIColor> track_color,
+ thumb_outline_color,
+ thumb_center_color;
+
+ Optional<LLUIImage*> thumb_image,
+ thumb_image_pressed,
+ thumb_image_disabled,
+ track_image_horizontal,
+ track_image_vertical,
+ track_highlight_horizontal_image,
+ track_highlight_vertical_image;
+
+ Optional<CommitCallbackParam> mouse_down_callback,
+ mouse_up_callback;
- virtual void setValue(const LLSD& value ) { setValue((F32)value.asReal(), TRUE); }
- virtual LLSD getValue() const { return LLSD(getValueF32()); }
- virtual void setMinValue(LLSD min_value) { setMinValue((F32)min_value.asReal()); }
- virtual void setMaxValue(LLSD max_value) { setMaxValue((F32)max_value.asReal()); }
+ Params();
+ };
+protected:
+ LLSlider(const Params&);
+ friend class LLUICtrlFactory;
+public:
+ virtual ~LLSlider();
+ void setValue( F32 value, BOOL from_event = FALSE );
+ // overrides for LLF32UICtrl methods
+ virtual void setValue(const LLSD& value ) { setValue((F32)value.asReal(), TRUE); }
+
+ virtual void setMinValue(const LLSD& min_value) { setMinValue((F32)min_value.asReal()); }
+ virtual void setMaxValue(const LLSD& max_value) { setMaxValue((F32)max_value.asReal()); }
+ virtual void setMinValue(F32 min_value) { LLF32UICtrl::setMinValue(min_value); updateThumbRect(); }
+ virtual void setMaxValue(F32 max_value) { LLF32UICtrl::setMaxValue(max_value); updateThumbRect(); }
- F32 getInitialValue() const { return mInitialValue; }
- F32 getMinValue() const { return mMinValue; }
- F32 getMaxValue() const { return mMaxValue; }
- F32 getIncrement() const { return mIncrement; }
- void setMinValue(F32 min_value) {mMinValue = min_value; updateThumbRect(); }
- void setMaxValue(F32 max_value) {mMaxValue = max_value; updateThumbRect(); }
- void setIncrement(F32 increment) {mIncrement = increment;}
- void setMouseDownCallback( void (*cb)(LLUICtrl* ctrl, void* userdata) ) { mMouseDownCallback = cb; }
- void setMouseUpCallback( void (*cb)(LLUICtrl* ctrl, void* userdata) ) { mMouseUpCallback = cb; }
+ boost::signals2::connection setMouseDownCallback( const commit_signal_t::slot_type& cb );
+ boost::signals2::connection setMouseUpCallback( const commit_signal_t::slot_type& cb );
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleKeyHere(KEY key, MASK mask);
+ virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
virtual void draw();
private:
void setValueAndCommit(F32 value);
void updateThumbRect();
- F32 mValue;
- F32 mInitialValue;
- F32 mMinValue;
- F32 mMaxValue;
- F32 mIncrement;
-
BOOL mVolumeSlider;
S32 mMouseOffset;
LLRect mDragStartThumbRect;
- LLUIImage* mThumbImage;
- LLUIImage* mTrackImage;
- LLUIImage* mTrackHighlightImage;
+ LLPointer<LLUIImage> mThumbImage;
+ LLPointer<LLUIImage> mThumbImagePressed;
+ LLPointer<LLUIImage> mThumbImageDisabled;
+ LLPointer<LLUIImage> mTrackImageHorizontal;
+ LLPointer<LLUIImage> mTrackImageVertical;
+ LLPointer<LLUIImage> mTrackHighlightHorizontalImage;
+ LLPointer<LLUIImage> mTrackHighlightVerticalImage;
+
+ const ORIENTATION mOrientation;
- LLRect mThumbRect;
- LLColor4 mTrackColor;
- LLColor4 mThumbOutlineColor;
- LLColor4 mThumbCenterColor;
+ LLRect mThumbRect;
+ LLUIColor mTrackColor;
+ LLUIColor mThumbOutlineColor;
+ LLUIColor mThumbCenterColor;
- void (*mMouseDownCallback)(LLUICtrl* ctrl, void* userdata);
- void (*mMouseUpCallback)(LLUICtrl* ctrl, void* userdata);
+ commit_signal_t* mMouseDownSignal;
+ commit_signal_t* mMouseUpSignal;
};
#endif // LL_LLSLIDER_H
diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp
index 31baddd7cc..01c274bb4e 100644
--- a/indra/llui/llsliderctrl.cpp
+++ b/indra/llui/llsliderctrl.cpp
@@ -34,8 +34,6 @@
#include "llsliderctrl.h"
-#include "audioengine.h"
-
#include "llmath.h"
#include "llfontgl.h"
#include "llgl.h"
@@ -49,84 +47,104 @@
#include "llcontrol.h"
#include "llfocusmgr.h"
#include "llresmgr.h"
+#include "lluictrlfactory.h"
const U32 MAX_STRING_LENGTH = 10;
-static LLRegisterWidget<LLSliderCtrl> r("slider");
-
-LLSliderCtrl::LLSliderCtrl(const std::string& name, const LLRect& rect,
- const std::string& label,
- const LLFontGL* font,
- S32 label_width,
- S32 text_left,
- BOOL show_text,
- BOOL can_edit_text,
- BOOL volume,
- void (*commit_callback)(LLUICtrl*, void*),
- void* callback_user_data,
- F32 initial_value, F32 min_value, F32 max_value, F32 increment,
- const std::string& control_which)
- : LLUICtrl(name, rect, TRUE, commit_callback, callback_user_data ),
- mFont(font),
- mShowText( show_text ),
- mCanEditText( can_edit_text ),
- mVolumeSlider( volume ),
- mPrecision( 3 ),
- mLabelBox( NULL ),
- mLabelWidth( label_width ),
- mValue( initial_value ),
- mEditor( NULL ),
- mTextBox( NULL ),
- mTextEnabledColor( LLUI::sColorsGroup->getColor( "LabelTextColor" ) ),
- mTextDisabledColor( LLUI::sColorsGroup->getColor( "LabelDisabledColor" ) ),
- mSliderMouseUpCallback( NULL ),
- mSliderMouseDownCallback( NULL )
+static LLDefaultChildRegistry::Register<LLSliderCtrl> r("slider");
+
+LLSliderCtrl::LLSliderCtrl(const LLSliderCtrl::Params& p)
+: LLF32UICtrl(p),
+ mLabelBox( NULL ),
+ mEditor( NULL ),
+ mTextBox( NULL ),
+ mFont(p.font),
+ mShowText(p.show_text),
+ mCanEditText(p.can_edit_text),
+ mPrecision(p.decimal_digits),
+ mTextEnabledColor(p.text_color()),
+ mTextDisabledColor(p.text_disabled_color())
{
S32 top = getRect().getHeight();
S32 bottom = 0;
S32 left = 0;
+ S32 label_width = p.label_width;
+ S32 text_width = p.text_width;
+
// Label
- if( !label.empty() )
+ if( !p.label().empty() )
{
- if (label_width == 0)
+ if (!p.label_width.isProvided())
{
- label_width = font->getWidth(label);
+ label_width = p.font()->getWidth(p.label);
}
LLRect label_rect( left, top, label_width, bottom );
- mLabelBox = new LLTextBox( std::string("SliderCtrl Label"), label_rect, label, font );
+ LLTextBox::Params params(p.slider_label);
+ params.rect.setIfNotProvided(label_rect);
+ params.font.setIfNotProvided(p.font);
+ params.initial_value(p.label());
+ mLabelBox = LLUICtrlFactory::create<LLTextBox> (params);
addChild(mLabelBox);
}
+ if (p.show_text && !p.text_width.isProvided())
+ {
+ // calculate the size of the text box (log max_value is number of digits - 1 so plus 1)
+ if ( p.max_value )
+ text_width = p.font()->getWidth(std::string("0")) * ( static_cast < S32 > ( log10 ( p.max_value ) ) + p.decimal_digits + 1 );
+
+ if ( p.increment < 1.0f )
+ text_width += p.font()->getWidth(std::string(".")); // (mostly) take account of decimal point in value
+
+ if ( p.min_value < 0.0f || p.max_value < 0.0f )
+ text_width += p.font()->getWidth(std::string("-")); // (mostly) take account of minus sign
+
+ // padding to make things look nicer
+ text_width += 8;
+ }
+
+
+ S32 text_left = getRect().getWidth() - text_width;
+ static LLUICachedControl<S32> sliderctrl_spacing ("UISliderctrlSpacing", 0);
+
S32 slider_right = getRect().getWidth();
- if( show_text )
+ if( p.show_text )
{
- slider_right = text_left - SLIDERCTRL_SPACING;
+ slider_right = text_left - sliderctrl_spacing;
}
- S32 slider_left = label_width ? label_width + SLIDERCTRL_SPACING : 0;
- LLRect slider_rect( slider_left, top, slider_right, bottom );
- mSlider = new LLSlider(std::string("slider"),
- slider_rect,
- LLSliderCtrl::onSliderCommit, this,
- initial_value, min_value, max_value, increment, volume,
- control_which );
+ S32 slider_left = label_width ? label_width + sliderctrl_spacing : 0;
+ LLSlider::Params slider_p(p.slider_bar);
+ slider_p.name("slider_bar");
+ slider_p.rect.setIfNotProvided(LLRect(slider_left,top,slider_right,bottom));
+ slider_p.initial_value.setIfNotProvided(p.initial_value().asReal());
+ slider_p.min_value.setIfNotProvided(p.min_value);
+ slider_p.max_value.setIfNotProvided(p.max_value);
+ slider_p.increment.setIfNotProvided(p.increment);
+ slider_p.orientation.setIfNotProvided(p.orientation);
+
+ slider_p.commit_callback.function(&LLSliderCtrl::onSliderCommit);
+ slider_p.control_name(p.control_name);
+ slider_p.mouse_down_callback( p.mouse_down_callback );
+ slider_p.mouse_up_callback( p.mouse_up_callback );
+ mSlider = LLUICtrlFactory::create<LLSlider> (slider_p);
+
addChild( mSlider );
- if( show_text )
+ if( p.show_text() )
{
LLRect text_rect( text_left, top, getRect().getWidth(), bottom );
- if( can_edit_text )
+ if( p.can_edit_text() )
{
- mEditor = new LLLineEditor( std::string("SliderCtrl Editor"), text_rect,
- LLStringUtil::null, font,
- MAX_STRING_LENGTH,
- &LLSliderCtrl::onEditorCommit, NULL, NULL, this,
- &LLLineEditor::prevalidateFloat );
- mEditor->setFollowsLeft();
- mEditor->setFollowsBottom();
- mEditor->setFocusReceivedCallback( &LLSliderCtrl::onEditorGainFocus, this );
- mEditor->setIgnoreTab(TRUE);
+ LLLineEditor::Params line_p(p.value_editor);
+ line_p.rect.setIfNotProvided(text_rect);
+ line_p.font.setIfNotProvided(p.font);
+ line_p.commit_callback.function(&LLSliderCtrl::onEditorCommit);
+ line_p.prevalidate_callback(&LLLineEditor::prevalidateFloat);
+ mEditor = LLUICtrlFactory::create<LLLineEditor>(line_p);
+
+ mEditor->setFocusReceivedCallback( boost::bind(&LLSliderCtrl::onEditorGainFocus, _1, this ));
// don't do this, as selecting the entire text is single clicking in some cases
// and double clicking in others
//mEditor->setSelectAllonFocusReceived(TRUE);
@@ -134,9 +152,10 @@ LLSliderCtrl::LLSliderCtrl(const std::string& name, const LLRect& rect,
}
else
{
- mTextBox = new LLTextBox( std::string("SliderCtrl Text"), text_rect, LLStringUtil::null, font);
- mTextBox->setFollowsLeft();
- mTextBox->setFollowsBottom();
+ LLTextBox::Params text_p(p.value_text);
+ text_p.rect.setIfNotProvided(text_rect);
+ text_p.font.setIfNotProvided(p.font);
+ mTextBox = LLUICtrlFactory::create<LLTextBox>(text_p);
addChild(mTextBox);
}
}
@@ -144,7 +163,6 @@ LLSliderCtrl::LLSliderCtrl(const std::string& name, const LLRect& rect,
updateText();
}
-
// static
void LLSliderCtrl::onEditorGainFocus( LLFocusableElement* caller, void *userdata )
{
@@ -179,7 +197,8 @@ BOOL LLSliderCtrl::setLabelArg( const std::string& key, const LLStringExplicit&
S32 delta = rect.mRight - prev_right;
rect = mSlider->getRect();
S32 left = rect.mLeft + delta;
- left = llclamp(left, 0, rect.mRight-SLIDERCTRL_SPACING);
+ static LLUICachedControl<S32> sliderctrl_spacing ("UISliderctrlSpacing", 0);
+ left = llclamp(left, 0, rect.mRight - sliderctrl_spacing);
rect.mLeft = left;
mSlider->setRect(rect);
}
@@ -224,10 +243,11 @@ void LLSliderCtrl::updateText()
}
// static
-void LLSliderCtrl::onEditorCommit( LLUICtrl* caller, void *userdata )
+void LLSliderCtrl::onEditorCommit( LLUICtrl* ctrl, const LLSD& userdata )
{
- LLSliderCtrl* self = (LLSliderCtrl*) userdata;
- llassert( caller == self->mEditor );
+ LLSliderCtrl* self = dynamic_cast<LLSliderCtrl*>(ctrl->getParent());
+ if (!self)
+ return;
BOOL success = FALSE;
F32 val = self->mValue;
@@ -240,17 +260,9 @@ void LLSliderCtrl::onEditorCommit( LLUICtrl* caller, void *userdata )
val = (F32) atof( text.c_str() );
if( self->mSlider->getMinValue() <= val && val <= self->mSlider->getMaxValue() )
{
- if( self->mValidateCallback )
+ self->setValue( val ); // set the value temporarily so that the callback can retrieve it.
+ if( !self->mValidateSignal || (*(self->mValidateSignal))( self, val ) )
{
- self->setValue( val ); // set the value temporarily so that the callback can retrieve it.
- if( self->mValidateCallback( self, self->mCallbackUserData ) )
- {
- success = TRUE;
- }
- }
- else
- {
- self->setValue( val );
success = TRUE;
}
}
@@ -272,26 +284,19 @@ void LLSliderCtrl::onEditorCommit( LLUICtrl* caller, void *userdata )
}
// static
-void LLSliderCtrl::onSliderCommit( LLUICtrl* caller, void *userdata )
+void LLSliderCtrl::onSliderCommit( LLUICtrl* ctrl, const LLSD& userdata )
{
- LLSliderCtrl* self = (LLSliderCtrl*) userdata;
- llassert( caller == self->mSlider );
+ LLSliderCtrl* self = dynamic_cast<LLSliderCtrl*>(ctrl->getParent());
+ if (!self)
+ return;
BOOL success = FALSE;
F32 saved_val = self->mValue;
F32 new_val = self->mSlider->getValueF32();
- if( self->mValidateCallback )
- {
- self->mValue = new_val; // set the value temporarily so that the callback can retrieve it.
- if( self->mValidateCallback( self, self->mCallbackUserData ) )
- {
- success = TRUE;
- }
- }
- else
+ self->mValue = new_val; // set the value temporarily so that the callback can retrieve it.
+ if( !self->mValidateSignal || (*(self->mValidateSignal))( self, new_val ) )
{
- self->mValue = new_val;
success = TRUE;
}
@@ -316,7 +321,7 @@ void LLSliderCtrl::setEnabled(BOOL b)
if( mLabelBox )
{
- mLabelBox->setColor( b ? mTextEnabledColor : mTextDisabledColor );
+ mLabelBox->setColor( b ? mTextEnabledColor.get() : mTextDisabledColor.get() );
}
mSlider->setEnabled( b );
@@ -328,7 +333,7 @@ void LLSliderCtrl::setEnabled(BOOL b)
if( mTextBox )
{
- mTextBox->setColor( b ? mTextEnabledColor : mTextDisabledColor );
+ mTextBox->setColor( b ? mTextEnabledColor.get() : mTextDisabledColor.get() );
}
}
@@ -339,7 +344,7 @@ void LLSliderCtrl::setTentative(BOOL b)
{
mEditor->setTentative(b);
}
- LLUICtrl::setTentative(b);
+ LLF32UICtrl::setTentative(b);
}
@@ -351,8 +356,9 @@ void LLSliderCtrl::onCommit()
{
mEditor->setTentative(FALSE);
}
-
- LLUICtrl::onCommit();
+
+ setControlValue(getValueF32());
+ LLF32UICtrl::onCommit();
}
@@ -368,37 +374,14 @@ void LLSliderCtrl::setPrecision(S32 precision)
updateText();
}
-void LLSliderCtrl::setSliderMouseDownCallback( void (*slider_mousedown_callback)(LLUICtrl* caller, void* userdata) )
+boost::signals2::connection LLSliderCtrl::setSliderMouseDownCallback( const commit_signal_t::slot_type& cb )
{
- mSliderMouseDownCallback = slider_mousedown_callback;
- mSlider->setMouseDownCallback( LLSliderCtrl::onSliderMouseDown );
+ return mSlider->setMouseDownCallback( cb );
}
-// static
-void LLSliderCtrl::onSliderMouseDown(LLUICtrl* caller, void* userdata)
+boost::signals2::connection LLSliderCtrl::setSliderMouseUpCallback( const commit_signal_t::slot_type& cb )
{
- LLSliderCtrl* self = (LLSliderCtrl*) userdata;
- if( self->mSliderMouseDownCallback )
- {
- self->mSliderMouseDownCallback( self, self->mCallbackUserData );
- }
-}
-
-
-void LLSliderCtrl::setSliderMouseUpCallback( void (*slider_mouseup_callback)(LLUICtrl* caller, void* userdata) )
-{
- mSliderMouseUpCallback = slider_mouseup_callback;
- mSlider->setMouseUpCallback( LLSliderCtrl::onSliderMouseUp );
-}
-
-// static
-void LLSliderCtrl::onSliderMouseUp(LLUICtrl* caller, void* userdata)
-{
- LLSliderCtrl* self = (LLSliderCtrl*) userdata;
- if( self->mSliderMouseUpCallback )
- {
- self->mSliderMouseUpCallback( self, self->mCallbackUserData );
- }
+ return mSlider->setMouseUpCallback( cb );
}
void LLSliderCtrl::onTabInto()
@@ -414,131 +397,3 @@ void LLSliderCtrl::reportInvalidData()
make_ui_sound("UISndBadKeystroke");
}
-// virtual
-LLXMLNodePtr LLSliderCtrl::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLUICtrl::getXML();
-
- node->createChild("show_text", TRUE)->setBoolValue(mShowText);
-
- node->createChild("can_edit_text", TRUE)->setBoolValue(mCanEditText);
-
- node->createChild("volume", TRUE)->setBoolValue(mVolumeSlider);
-
- node->createChild("decimal_digits", TRUE)->setIntValue(mPrecision);
-
- if (mLabelBox)
- {
- node->createChild("label", TRUE)->setStringValue(mLabelBox->getText());
- }
-
- // TomY TODO: Do we really want to export the transient state of the slider?
- node->createChild("value", TRUE)->setFloatValue(mValue);
-
- if (mSlider)
- {
- node->createChild("initial_val", TRUE)->setFloatValue(mSlider->getInitialValue());
- node->createChild("min_val", TRUE)->setFloatValue(mSlider->getMinValue());
- node->createChild("max_val", TRUE)->setFloatValue(mSlider->getMaxValue());
- node->createChild("increment", TRUE)->setFloatValue(mSlider->getIncrement());
- }
- addColorXML(node, mTextEnabledColor, "text_enabled_color", "LabelTextColor");
- addColorXML(node, mTextDisabledColor, "text_disabled_color", "LabelDisabledColor");
-
- return node;
-}
-
-LLView* LLSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("slider");
- node->getAttributeString("name", name);
-
- std::string label;
- node->getAttributeString("label", label);
-
- LLRect rect;
- createRect(node, rect, parent, LLRect());
-
- LLFontGL* font = LLView::selectFont(node);
-
- // HACK: Font might not be specified.
- if (!font)
- {
- font = LLFontGL::getFontSansSerifSmall();
- }
-
- S32 label_width = 0;
- node->getAttributeS32("label_width", label_width);
-
- BOOL show_text = TRUE;
- node->getAttributeBOOL("show_text", show_text);
-
- BOOL can_edit_text = FALSE;
- node->getAttributeBOOL("can_edit_text", can_edit_text);
-
- BOOL volume = FALSE;
- node->getAttributeBOOL("volume", volume);
-
- F32 initial_value = 0.f;
- node->getAttributeF32("initial_val", initial_value);
-
- F32 min_value = 0.f;
- node->getAttributeF32("min_val", min_value);
-
- F32 max_value = 1.f;
- node->getAttributeF32("max_val", max_value);
-
- F32 increment = 0.1f;
- node->getAttributeF32("increment", increment);
-
- U32 precision = 3;
- node->getAttributeU32("decimal_digits", precision);
-
- S32 text_left = 0;
- if (show_text)
- {
- // calculate the size of the text box (log max_value is number of digits - 1 so plus 1)
- if ( max_value )
- text_left = font->getWidth(std::string("0")) * ( static_cast < S32 > ( log10 ( max_value ) ) + precision + 1 );
-
- if ( increment < 1.0f )
- text_left += font->getWidth(std::string(".")); // (mostly) take account of decimal point in value
-
- if ( min_value < 0.0f || max_value < 0.0f )
- text_left += font->getWidth(std::string("-")); // (mostly) take account of minus sign
-
- // padding to make things look nicer
- text_left += 8;
- }
-
- LLUICtrlCallback callback = NULL;
-
- if (label.empty())
- {
- label.assign(node->getTextContents());
- }
-
- LLSliderCtrl* slider = new LLSliderCtrl(name,
- rect,
- label,
- font,
- label_width,
- rect.getWidth() - text_left,
- show_text,
- can_edit_text,
- volume,
- callback,
- NULL,
- initial_value,
- min_value,
- max_value,
- increment);
-
- slider->setPrecision(precision);
-
- slider->initFromXML(node, parent);
-
- slider->updateText();
-
- return slider;
-}
diff --git a/indra/llui/llsliderctrl.h b/indra/llui/llsliderctrl.h
index 272dd7ffd3..c425849782 100644
--- a/indra/llui/llsliderctrl.h
+++ b/indra/llui/llsliderctrl.h
@@ -38,83 +38,101 @@
#include "llslider.h"
#include "lltextbox.h"
#include "llrect.h"
+#include "lllineeditor.h"
-//
-// Constants
-//
-const S32 SLIDERCTRL_SPACING = 4; // space between label, slider, and text
-const S32 SLIDERCTRL_HEIGHT = 16;
-
-class LLSliderCtrl : public LLUICtrl
+class LLSliderCtrl : public LLF32UICtrl
{
public:
- LLSliderCtrl(const std::string& name,
- const LLRect& rect,
- const std::string& label,
- const LLFontGL* font,
- S32 slider_left,
- S32 text_left,
- BOOL show_text,
- BOOL can_edit_text,
- BOOL volume, //TODO: create a "volume" slider sub-class or just use image art, no? -MG
- void (*commit_callback)(LLUICtrl*, void*),
- void* callback_userdata,
- F32 initial_value, F32 min_value, F32 max_value, F32 increment,
- const std::string& control_which = LLStringUtil::null );
-
+ struct Params : public LLInitParam::Block<Params, LLF32UICtrl::Params>
+ {
+ Optional<std::string> orientation;
+ Optional<S32> label_width;
+ Optional<S32> text_width;
+ Optional<bool> show_text;
+ Optional<bool> can_edit_text;
+ Optional<bool> is_volume_slider;
+ Optional<S32> decimal_digits;
+
+ Optional<LLUIColor> text_color,
+ text_disabled_color;
+
+ Optional<CommitCallbackParam> mouse_down_callback,
+ mouse_up_callback;
+
+ Optional<LLSlider::Params> slider_bar;
+ Optional<LLLineEditor::Params> value_editor;
+ Optional<LLTextBox::Params> value_text;
+ Optional<LLTextBox::Params> slider_label;
+
+ Params()
+ : text_width("text_width"),
+ label_width("label_width"),
+ show_text("show_text"),
+ can_edit_text("can_edit_text"),
+ is_volume_slider("volume"),
+ decimal_digits("decimal_digits", 3),
+ text_color("text_color"),
+ text_disabled_color("text_disabled_color"),
+ slider_bar("slider_bar"),
+ value_editor("value_editor"),
+ value_text("value_text"),
+ slider_label("slider_label"),
+ mouse_down_callback("mouse_down_callback"),
+ mouse_up_callback("mouse_up_callback"),
+ orientation("orientation", std::string ("horizontal"))
+ {}
+ };
+protected:
+ LLSliderCtrl(const Params&);
+ friend class LLUICtrlFactory;
+public:
virtual ~LLSliderCtrl() {} // Children all cleaned up by default view destructor.
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
-
- F32 getValueF32() const { return mSlider->getValueF32(); }
+ /*virtual*/ F32 getValueF32() const { return mSlider->getValueF32(); }
void setValue(F32 v, BOOL from_event = FALSE);
- virtual void setValue(const LLSD& value) { setValue((F32)value.asReal(), TRUE); }
- virtual LLSD getValue() const { return LLSD(getValueF32()); }
- virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
-
- virtual void setMinValue(LLSD min_value) { setMinValue((F32)min_value.asReal()); }
- virtual void setMaxValue(LLSD max_value) { setMaxValue((F32)max_value.asReal()); }
+ /*virtual*/ void setValue(const LLSD& value) { setValue((F32)value.asReal(), TRUE); }
+ /*virtual*/ LLSD getValue() const { return LLSD(getValueF32()); }
+ /*virtual*/ BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
BOOL isMouseHeldDown() const { return mSlider->hasMouseCapture(); }
- virtual void setEnabled( BOOL b );
- virtual void clear();
virtual void setPrecision(S32 precision);
- void setMinValue(F32 min_value) { mSlider->setMinValue(min_value); updateText(); }
- void setMaxValue(F32 max_value) { mSlider->setMaxValue(max_value); updateText(); }
- void setIncrement(F32 increment) { mSlider->setIncrement(increment);}
- F32 getMinValue() { return mSlider->getMinValue(); }
- F32 getMaxValue() { return mSlider->getMaxValue(); }
+ /*virtual*/ void setEnabled( BOOL b );
+ /*virtual*/ void clear();
+
+ /*virtual*/ void setMinValue(const LLSD& min_value) { setMinValue((F32)min_value.asReal()); }
+ /*virtual*/ void setMaxValue(const LLSD& max_value) { setMaxValue((F32)max_value.asReal()); }
+ /*virtual*/ void setMinValue(F32 min_value) { mSlider->setMinValue(min_value); updateText(); }
+ /*virtual*/ void setMaxValue(F32 max_value) { mSlider->setMaxValue(max_value); updateText(); }
+ /*virtual*/ void setIncrement(F32 increment) { mSlider->setIncrement(increment);}
+
+ F32 getMinValue() const { return mSlider->getMinValue(); }
+ F32 getMaxValue() const { return mSlider->getMaxValue(); }
void setLabel(const LLStringExplicit& label) { if (mLabelBox) mLabelBox->setText(label); }
void setLabelColor(const LLColor4& c) { mTextEnabledColor = c; }
void setDisabledLabelColor(const LLColor4& c) { mTextDisabledColor = c; }
- void setSliderMouseDownCallback( void (*slider_mousedown_callback)(LLUICtrl* caller, void* userdata) );
- void setSliderMouseUpCallback( void (*slider_mouseup_callback)(LLUICtrl* caller, void* userdata) );
+ boost::signals2::connection setSliderMouseDownCallback( const commit_signal_t::slot_type& cb );
+ boost::signals2::connection setSliderMouseUpCallback( const commit_signal_t::slot_type& cb );
- virtual void onTabInto();
+ /*virtual*/ void onTabInto();
- virtual void setTentative(BOOL b); // marks value as tentative
- virtual void onCommit(); // mark not tentative, then commit
+ /*virtual*/ void setTentative(BOOL b); // marks value as tentative
+ /*virtual*/ void onCommit(); // mark not tentative, then commit
- virtual void setControlName(const std::string& control_name, LLView* context)
+ /*virtual*/ void setControlName(const std::string& control_name, LLView* context)
{
- LLView::setControlName(control_name, context);
+ LLUICtrl::setControlName(control_name, context);
mSlider->setControlName(control_name, context);
}
- virtual std::string getControlName() const { return mSlider->getControlName(); }
+ static void onSliderCommit(LLUICtrl* caller, const LLSD& userdata);
- static void onSliderCommit(LLUICtrl* caller, void* userdata);
- static void onSliderMouseDown(LLUICtrl* caller,void* userdata);
- static void onSliderMouseUp(LLUICtrl* caller,void* userdata);
-
- static void onEditorCommit(LLUICtrl* caller, void* userdata);
+ static void onEditorCommit(LLUICtrl* ctrl, const LLSD& userdata);
static void onEditorGainFocus(LLFocusableElement* caller, void *userdata);
static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata);
@@ -125,7 +143,6 @@ private:
const LLFontGL* mFont;
BOOL mShowText;
BOOL mCanEditText;
- BOOL mVolumeSlider;
S32 mPrecision;
LLTextBox* mLabelBox;
@@ -136,11 +153,8 @@ private:
class LLLineEditor* mEditor;
LLTextBox* mTextBox;
- LLColor4 mTextEnabledColor;
- LLColor4 mTextDisabledColor;
-
- void (*mSliderMouseUpCallback)( LLUICtrl* ctrl, void* userdata );
- void (*mSliderMouseDownCallback)( LLUICtrl* ctrl, void* userdata );
+ LLUIColor mTextEnabledColor;
+ LLUIColor mTextDisabledColor;
};
#endif // LL_LLSLIDERCTRL_H
diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp
index c54a2cd140..20a1ab7af3 100644
--- a/indra/llui/llspinctrl.cpp
+++ b/indra/llui/llspinctrl.cpp
@@ -45,101 +45,102 @@
#include "lltextbox.h"
#include "llkeyboard.h"
#include "llmath.h"
-#include "audioengine.h"
#include "llcontrol.h"
#include "llfocusmgr.h"
#include "llresmgr.h"
+#include "lluictrlfactory.h"
const U32 MAX_STRING_LENGTH = 32;
-static LLRegisterWidget<LLSpinCtrl> r2("spinner");
-
-LLSpinCtrl::LLSpinCtrl( const std::string& name, const LLRect& rect, const std::string& label, const LLFontGL* font,
- void (*commit_callback)(LLUICtrl*, void*),
- void* callback_user_data,
- F32 initial_value, F32 min_value, F32 max_value, F32 increment,
- const std::string& control_name,
- S32 label_width)
- :
- LLUICtrl(name, rect, TRUE, commit_callback, callback_user_data, FOLLOWS_LEFT | FOLLOWS_TOP ),
- mValue( initial_value ),
- mInitialValue( initial_value ),
- mMaxValue( max_value ),
- mMinValue( min_value ),
- mIncrement( increment ),
- mPrecision( 3 ),
- mLabelBox( NULL ),
- mTextEnabledColor( LLUI::sColorsGroup->getColor( "LabelTextColor" ) ),
- mTextDisabledColor( LLUI::sColorsGroup->getColor( "LabelDisabledColor" ) ),
- mbHasBeenSet( FALSE )
+static LLDefaultChildRegistry::Register<LLSpinCtrl> r2("spinner");
+
+LLSpinCtrl::Params::Params()
+: label_width("label_width"),
+ decimal_digits("decimal_digits"),
+ allow_text_entry("allow_text_entry", true),
+ text_enabled_color("text_enabled_color"),
+ text_disabled_color("text_disabled_color"),
+ up_button("up_button"),
+ down_button("down_button")
+{}
+
+LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
+: LLF32UICtrl(p),
+ mLabelBox(NULL),
+ mbHasBeenSet( FALSE ),
+ mPrecision(p.decimal_digits),
+ mTextEnabledColor(p.text_enabled_color()),
+ mTextDisabledColor(p.text_disabled_color())
{
- S32 top = getRect().getHeight();
- S32 bottom = top - 2 * SPINCTRL_BTN_HEIGHT;
- S32 centered_top = top;
- S32 centered_bottom = bottom;
+ static LLUICachedControl<S32> spinctrl_spacing ("UISpinctrlSpacing", 0);
+ static LLUICachedControl<S32> spinctrl_btn_width ("UISpinctrlBtnWidth", 0);
+ static LLUICachedControl<S32> spinctrl_btn_height ("UISpinctrlBtnHeight", 0);
+ S32 centered_top = getRect().getHeight();
+ S32 centered_bottom = getRect().getHeight() - 2 * spinctrl_btn_height;
S32 btn_left = 0;
+ // reserve space for spinner
+ S32 label_width = llclamp(p.label_width(), 0, llmax(0, getRect().getWidth() - 40));
// Label
- if( !label.empty() )
+ if( !p.label().empty() )
{
LLRect label_rect( 0, centered_top, label_width, centered_bottom );
- mLabelBox = new LLTextBox( std::string("SpinCtrl Label"), label_rect, label, font );
+ LLTextBox::Params params;
+ params.name("SpinCtrl Label");
+ params.rect(label_rect);
+ params.initial_value(p.label());
+ if (p.font.isProvided())
+ {
+ params.font(p.font);
+ }
+ mLabelBox = LLUICtrlFactory::create<LLTextBox> (params);
addChild(mLabelBox);
- btn_left += label_rect.mRight + SPINCTRL_SPACING;
+ btn_left += label_rect.mRight + spinctrl_spacing;
}
- S32 btn_right = btn_left + SPINCTRL_BTN_WIDTH;
+ S32 btn_right = btn_left + spinctrl_btn_width;
// Spin buttons
- LLRect up_rect( btn_left, top, btn_right, top - SPINCTRL_BTN_HEIGHT );
- std::string out_id = "UIImgBtnSpinUpOutUUID";
- std::string in_id = "UIImgBtnSpinUpInUUID";
- mUpBtn = new LLButton(std::string("SpinCtrl Up"), up_rect,
- out_id,
- in_id,
- LLStringUtil::null,
- &LLSpinCtrl::onUpBtn, this, LLFontGL::getFontSansSerif() );
- mUpBtn->setFollowsLeft();
- mUpBtn->setFollowsBottom();
- mUpBtn->setHeldDownCallback( &LLSpinCtrl::onUpBtn );
- mUpBtn->setTabStop(FALSE);
+ LLButton::Params up_button_params(p.up_button);
+ up_button_params.rect = LLRect(btn_left, getRect().getHeight(), btn_right, getRect().getHeight() - spinctrl_btn_height);
+ up_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2));
+ up_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2));
+
+ mUpBtn = LLUICtrlFactory::create<LLButton>(up_button_params);
addChild(mUpBtn);
- LLRect down_rect( btn_left, top - SPINCTRL_BTN_HEIGHT, btn_right, bottom );
- out_id = "UIImgBtnSpinDownOutUUID";
- in_id = "UIImgBtnSpinDownInUUID";
- mDownBtn = new LLButton(std::string("SpinCtrl Down"), down_rect,
- out_id,
- in_id,
- LLStringUtil::null,
- &LLSpinCtrl::onDownBtn, this, LLFontGL::getFontSansSerif() );
- mDownBtn->setFollowsLeft();
- mDownBtn->setFollowsBottom();
- mDownBtn->setHeldDownCallback( &LLSpinCtrl::onDownBtn );
- mDownBtn->setTabStop(FALSE);
+ LLButton::Params down_button_params(p.down_button);
+ down_button_params.rect = LLRect(btn_left, getRect().getHeight() - spinctrl_btn_height, btn_right, getRect().getHeight() - 2 * spinctrl_btn_height);
+ down_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2));
+ down_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2));
+ mDownBtn = LLUICtrlFactory::create<LLButton>(down_button_params);
addChild(mDownBtn);
LLRect editor_rect( btn_right + 1, centered_top, getRect().getWidth(), centered_bottom );
- mEditor = new LLLineEditor( std::string("SpinCtrl Editor"), editor_rect, LLStringUtil::null, font,
- MAX_STRING_LENGTH,
- &LLSpinCtrl::onEditorCommit, NULL, NULL, this,
- &LLLineEditor::prevalidateFloat );
- mEditor->setFollowsLeft();
- mEditor->setFollowsBottom();
- mEditor->setFocusReceivedCallback( &LLSpinCtrl::onEditorGainFocus, this );
+ LLLineEditor::Params params;
+ params.name("SpinCtrl Editor");
+ params.rect(editor_rect);
+ if (p.font.isProvided())
+ {
+ params.font(p.font);
+ }
+ params.max_length_bytes(MAX_STRING_LENGTH);
+ params.commit_callback.function((boost::bind(&LLSpinCtrl::onEditorCommit, this, _2)));
+ params.prevalidate_callback(&LLLineEditor::prevalidateFloat);
+ params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
+ mEditor = LLUICtrlFactory::create<LLLineEditor> (params);
+ mEditor->setFocusReceivedCallback( boost::bind(&LLSpinCtrl::onEditorGainFocus, _1, this ));
//RN: this seems to be a BAD IDEA, as it makes the editor behavior different when it has focus
// than when it doesn't. Instead, if you always have to double click to select all the text,
// it's easier to understand
//mEditor->setSelectAllonFocusReceived(TRUE);
- mEditor->setIgnoreTab(TRUE);
addChild(mEditor);
updateEditor();
setUseBoundingRect( TRUE );
}
-
F32 clamp_precision(F32 value, S32 decimal_precision)
{
// pow() isn't perfect
@@ -157,69 +158,71 @@ F32 clamp_precision(F32 value, S32 decimal_precision)
}
-// static
-void LLSpinCtrl::onUpBtn( void *userdata )
+void LLSpinCtrl::onUpBtn( const LLSD& data )
{
- LLSpinCtrl* self = (LLSpinCtrl*) userdata;
- if( self->getEnabled() )
+ if( getEnabled() )
{
- // use getValue()/setValue() to force reload from/to control
- F32 val = (F32)self->getValue().asReal() + self->mIncrement;
- val = clamp_precision(val, self->mPrecision);
- val = llmin( val, self->mMaxValue );
-
- if( self->mValidateCallback )
+ std::string text = mEditor->getText();
+ if( LLLineEditor::postvalidateFloat( text ) )
{
- F32 saved_val = (F32)self->getValue().asReal();
- self->setValue(val);
- if( !self->mValidateCallback( self, self->mCallbackUserData ) )
+
+ LLLocale locale(LLLocale::USER_LOCALE);
+ F32 cur_val = (F32) atof(text.c_str());
+
+ // use getValue()/setValue() to force reload from/to control
+ F32 val = cur_val + mIncrement;
+ val = clamp_precision(val, mPrecision);
+ val = llmin( val, mMaxValue );
+ if (val < mMinValue) val = mMinValue;
+ if (val > mMaxValue) val = mMaxValue;
+
+ F32 saved_val = (F32)getValue().asReal();
+ setValue(val);
+ if( mValidateSignal && !(*mValidateSignal)( this, val ) )
{
- self->setValue( saved_val );
- self->reportInvalidData();
- self->updateEditor();
+ setValue( saved_val );
+ reportInvalidData();
+ updateEditor();
return;
}
- }
- else
- {
- self->setValue(val);
- }
- self->updateEditor();
- self->onCommit();
+ updateEditor();
+ onCommit();
+ }
}
}
-// static
-void LLSpinCtrl::onDownBtn( void *userdata )
+void LLSpinCtrl::onDownBtn( const LLSD& data )
{
- LLSpinCtrl* self = (LLSpinCtrl*) userdata;
-
- if( self->getEnabled() )
+ if( getEnabled() )
{
- F32 val = (F32)self->getValue().asReal() - self->mIncrement;
- val = clamp_precision(val, self->mPrecision);
- val = llmax( val, self->mMinValue );
-
- if( self->mValidateCallback )
+ std::string text = mEditor->getText();
+ if( LLLineEditor::postvalidateFloat( text ) )
{
- F32 saved_val = (F32)self->getValue().asReal();
- self->setValue(val);
- if( !self->mValidateCallback( self, self->mCallbackUserData ) )
+
+ LLLocale locale(LLLocale::USER_LOCALE);
+ F32 cur_val = (F32) atof(text.c_str());
+
+ F32 val = cur_val - mIncrement;
+ val = clamp_precision(val, mPrecision);
+ val = llmax( val, mMinValue );
+
+ if (val < mMinValue) val = mMinValue;
+ if (val > mMaxValue) val = mMaxValue;
+
+ F32 saved_val = (F32)getValue().asReal();
+ setValue(val);
+ if( mValidateSignal && !(*mValidateSignal)( this, val ) )
{
- self->setValue( saved_val );
- self->reportInvalidData();
- self->updateEditor();
+ setValue( saved_val );
+ reportInvalidData();
+ updateEditor();
return;
}
- }
- else
- {
- self->setValue(val);
- }
- self->updateEditor();
- self->onCommit();
+ updateEditor();
+ onCommit();
+ }
}
}
@@ -235,10 +238,10 @@ void LLSpinCtrl::onEditorGainFocus( LLFocusableElement* caller, void *userdata )
void LLSpinCtrl::setValue(const LLSD& value )
{
F32 v = (F32)value.asReal();
- if (mValue != v || !mbHasBeenSet)
+ if (getValueF32() != v || !mbHasBeenSet)
{
mbHasBeenSet = TRUE;
- mValue = v;
+ LLF32UICtrl::setValue(value);
if (!mEditor->hasFocus())
{
@@ -251,10 +254,10 @@ void LLSpinCtrl::setValue(const LLSD& value )
void LLSpinCtrl::forceSetValue(const LLSD& value )
{
F32 v = (F32)value.asReal();
- if (mValue != v || !mbHasBeenSet)
+ if (getValueF32() != v || !mbHasBeenSet)
{
mbHasBeenSet = TRUE;
- mValue = v;
+ LLF32UICtrl::setValue(value);
updateEditor();
}
@@ -286,55 +289,43 @@ void LLSpinCtrl::updateEditor()
mEditor->setText( text );
}
-void LLSpinCtrl::onEditorCommit( LLUICtrl* caller, void *userdata )
+void LLSpinCtrl::onEditorCommit( const LLSD& data )
{
BOOL success = FALSE;
- LLSpinCtrl* self = (LLSpinCtrl*) userdata;
- llassert( caller == self->mEditor );
-
- std::string text = self->mEditor->getText();
+ std::string text = mEditor->getText();
if( LLLineEditor::postvalidateFloat( text ) )
{
LLLocale locale(LLLocale::USER_LOCALE);
F32 val = (F32) atof(text.c_str());
- if (val < self->mMinValue) val = self->mMinValue;
- if (val > self->mMaxValue) val = self->mMaxValue;
+ if (val < mMinValue) val = mMinValue;
+ if (val > mMaxValue) val = mMaxValue;
- if( self->mValidateCallback )
+ F32 saved_val = getValueF32();
+ setValue(val);
+ if( !mValidateSignal || (*mValidateSignal)( this, val ) )
{
- F32 saved_val = self->mValue;
- self->mValue = val;
- if( self->mValidateCallback( self, self->mCallbackUserData ) )
- {
- success = TRUE;
- self->onCommit();
- }
- else
- {
- self->mValue = saved_val;
- }
+ success = TRUE;
+ onCommit();
}
else
{
- self->mValue = val;
- self->onCommit();
- success = TRUE;
+ setValue(saved_val);
}
}
- self->updateEditor();
+ updateEditor();
if( !success )
{
- self->reportInvalidData();
+ reportInvalidData();
}
}
void LLSpinCtrl::forceEditorCommit()
{
- onEditorCommit(mEditor, this);
+ onEditorCommit( LLSD() );
}
@@ -348,6 +339,10 @@ void LLSpinCtrl::setEnabled(BOOL b)
{
LLView::setEnabled( b );
mEditor->setEnabled( b );
+ if( mLabelBox )
+ {
+ mLabelBox->setColor( b ? mTextEnabledColor.get() : mTextDisabledColor.get() );
+ }
}
@@ -368,8 +363,8 @@ BOOL LLSpinCtrl::isMouseHeldDown() const
void LLSpinCtrl::onCommit()
{
setTentative(FALSE);
- setControlValue(mValue);
- LLUICtrl::onCommit();
+ setControlValue(getValueF32());
+ LLF32UICtrl::onCommit();
}
@@ -414,29 +409,19 @@ void LLSpinCtrl::reportInvalidData()
make_ui_sound("UISndBadKeystroke");
}
-void LLSpinCtrl::draw()
-{
- if( mLabelBox )
- {
- mLabelBox->setColor( getEnabled() ? mTextEnabledColor : mTextDisabledColor );
- }
- LLUICtrl::draw();
-}
-
-
BOOL LLSpinCtrl::handleScrollWheel(S32 x, S32 y, S32 clicks)
{
if( clicks > 0 )
{
while( clicks-- )
{
- LLSpinCtrl::onDownBtn(this);
+ onDownBtn(getValue());
}
}
else
while( clicks++ )
{
- LLSpinCtrl::onUpBtn(this);
+ onUpBtn(getValue());
}
return TRUE;
@@ -456,105 +441,15 @@ BOOL LLSpinCtrl::handleKeyHere(KEY key, MASK mask)
}
if(key == KEY_UP)
{
- LLSpinCtrl::onUpBtn(this);
+ onUpBtn(getValue());
return TRUE;
}
if(key == KEY_DOWN)
{
- LLSpinCtrl::onDownBtn(this);
+ onDownBtn(getValue());
return TRUE;
}
}
return FALSE;
}
-// virtual
-LLXMLNodePtr LLSpinCtrl::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLUICtrl::getXML();
-
- node->createChild("decimal_digits", TRUE)->setIntValue(mPrecision);
-
- if (mLabelBox)
- {
- node->createChild("label", TRUE)->setStringValue(mLabelBox->getText());
-
- node->createChild("label_width", TRUE)->setIntValue(mLabelBox->getRect().getWidth());
- }
-
- node->createChild("initial_val", TRUE)->setFloatValue(mInitialValue);
-
- node->createChild("min_val", TRUE)->setFloatValue(mMinValue);
-
- node->createChild("max_val", TRUE)->setFloatValue(mMaxValue);
-
- node->createChild("increment", TRUE)->setFloatValue(mIncrement);
-
- addColorXML(node, mTextEnabledColor, "text_enabled_color", "LabelTextColor");
- addColorXML(node, mTextDisabledColor, "text_disabled_color", "LabelDisabledColor");
-
- return node;
-}
-
-LLView* LLSpinCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("spinner");
- node->getAttributeString("name", name);
-
- std::string label;
- node->getAttributeString("label", label);
-
- LLRect rect;
- createRect(node, rect, parent, LLRect());
-
- LLFontGL* font = LLView::selectFont(node);
-
- F32 initial_value = 0.f;
- node->getAttributeF32("initial_val", initial_value);
-
- F32 min_value = 0.f;
- node->getAttributeF32("min_val", min_value);
-
- F32 max_value = 1.f;
- node->getAttributeF32("max_val", max_value);
-
- F32 increment = 0.1f;
- node->getAttributeF32("increment", increment);
-
- U32 precision = 3;
- node->getAttributeU32("decimal_digits", precision);
-
- S32 label_width = llmin(40, rect.getWidth() - 40);
- node->getAttributeS32("label_width", label_width);
-
- BOOL allow_text_entry = TRUE;
- node->getAttributeBOOL("allow_text_entry", allow_text_entry);
-
- LLUICtrlCallback callback = NULL;
-
- if(label.empty())
- {
- label.assign( node->getValue() );
- }
-
- LLSpinCtrl* spinner = new LLSpinCtrl(name,
- rect,
- label,
- font,
- callback,
- NULL,
- initial_value,
- min_value,
- max_value,
- increment,
- LLStringUtil::null,
- label_width);
-
- spinner->setPrecision(precision);
-
- spinner->initFromXML(node, parent);
- spinner->setAllowEdit(allow_text_entry);
-
- return spinner;
-}
-
diff --git a/indra/llui/llspinctrl.h b/indra/llui/llspinctrl.h
index dfd0eb3ac1..0e610b7741 100644
--- a/indra/llui/llspinctrl.h
+++ b/indra/llui/llspinctrl.h
@@ -35,62 +35,50 @@
#include "stdtypes.h"
-#include "lluictrl.h"
+#include "llbutton.h"
+#include "llf32uictrl.h"
#include "v4color.h"
#include "llrect.h"
-//
-// Constants
-//
-const S32 SPINCTRL_BTN_HEIGHT = 8;
-const S32 SPINCTRL_BTN_WIDTH = 16;
-const S32 SPINCTRL_SPACING = 2; // space between label right and button left
-const S32 SPINCTRL_HEIGHT = 2 * SPINCTRL_BTN_HEIGHT;
-const S32 SPINCTRL_DEFAULT_LABEL_WIDTH = 10;
-
class LLSpinCtrl
-: public LLUICtrl
+: public LLF32UICtrl
{
public:
- LLSpinCtrl(const std::string& name, const LLRect& rect,
- const std::string& label,
- const LLFontGL* font,
- void (*commit_callback)(LLUICtrl*, void*),
- void* callback_userdata,
- F32 initial_value, F32 min_value, F32 max_value, F32 increment,
- const std::string& control_name = std::string(),
- S32 label_width = SPINCTRL_DEFAULT_LABEL_WIDTH );
-
+ struct Params : public LLInitParam::Block<Params, LLF32UICtrl::Params>
+ {
+ Optional<S32> label_width;
+ Optional<U32> decimal_digits;
+ Optional<bool> allow_text_entry;
+
+ Optional<LLUIColor> text_enabled_color;
+ Optional<LLUIColor> text_disabled_color;
+
+ Optional<LLButton::Params> up_button;
+ Optional<LLButton::Params> down_button;
+
+ Params();
+ };
+protected:
+ LLSpinCtrl(const Params&);
+ friend class LLUICtrlFactory;
+public:
virtual ~LLSpinCtrl() {} // Children all cleaned up by default view destructor.
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory);
-
virtual void forceSetValue(const LLSD& value ) ;
virtual void setValue(const LLSD& value );
- virtual LLSD getValue() const { return mValue; }
- F32 get() const { return (F32)getValue().asReal(); }
+ F32 get() const { return getValueF32(); }
void set(F32 value) { setValue(value); mInitialValue = value; }
- virtual void setMinValue(LLSD min_value) { setMinValue((F32)min_value.asReal()); }
- virtual void setMaxValue(LLSD max_value) { setMaxValue((F32)max_value.asReal()); }
-
BOOL isMouseHeldDown() const;
virtual void setEnabled( BOOL b );
virtual void setFocus( BOOL b );
virtual void clear();
- virtual BOOL isDirty() const { return( mValue != mInitialValue ); }
- virtual void resetDirty() { mInitialValue = mValue; }
+ virtual BOOL isDirty() const { return( getValueF32() != mInitialValue ); }
+ virtual void resetDirty() { mInitialValue = getValueF32(); }
virtual void setPrecision(S32 precision);
- virtual void setMinValue(F32 min) { mMinValue = min; }
- virtual void setMaxValue(F32 max) { mMaxValue = max; }
- virtual void setIncrement(F32 inc) { mIncrement = inc; }
- virtual F32 getMinValue() { return mMinValue ; }
- virtual F32 getMaxValue() { return mMaxValue ; }
- virtual F32 getIncrement() { return mIncrement ; }
void setLabel(const LLStringExplicit& label);
void setLabelColor(const LLColor4& c) { mTextEnabledColor = c; }
@@ -107,31 +95,23 @@ public:
virtual BOOL handleScrollWheel(S32 x,S32 y,S32 clicks);
virtual BOOL handleKeyHere(KEY key, MASK mask);
- virtual void draw();
-
- static void onEditorCommit(LLUICtrl* caller, void* userdata);
+ void onEditorCommit(const LLSD& data);
static void onEditorGainFocus(LLFocusableElement* caller, void *userdata);
static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata);
- static void onUpBtn(void *userdata);
- static void onDownBtn(void *userdata);
+ void onUpBtn(const LLSD& data);
+ void onDownBtn(const LLSD& data);
private:
void updateEditor();
void reportInvalidData();
- F32 mValue;
- F32 mInitialValue;
- F32 mMaxValue;
- F32 mMinValue;
- F32 mIncrement;
-
S32 mPrecision;
class LLTextBox* mLabelBox;
class LLLineEditor* mEditor;
- LLColor4 mTextEnabledColor;
- LLColor4 mTextDisabledColor;
+ LLUIColor mTextEnabledColor;
+ LLUIColor mTextDisabledColor;
class LLButton* mUpBtn;
class LLButton* mDownBtn;
diff --git a/indra/llui/llstatbar.cpp b/indra/llui/llstatbar.cpp
new file mode 100644
index 0000000000..bd74b285a7
--- /dev/null
+++ b/indra/llui/llstatbar.cpp
@@ -0,0 +1,293 @@
+/**
+ * @file llstatbar.cpp
+ * @brief A little map of the world with network information
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+//#include "llviewerprecompiledheaders.h"
+#include "linden_common.h"
+
+#include "llstatbar.h"
+
+#include "llmath.h"
+#include "llui.h"
+#include "llgl.h"
+#include "llfontgl.h"
+
+#include "llstat.h"
+#include "lluictrlfactory.h"
+
+///////////////////////////////////////////////////////////////////////////////////
+
+LLStatBar::LLStatBar(const Params& p)
+ : LLView(p),
+ mLabel(p.label),
+ mUnitLabel(p.unit_label),
+ mMinBar(p.bar_min),
+ mMaxBar(p.bar_max),
+ mStatp(LLStat::getStat(p.stat)),
+ mTickSpacing(p.tick_spacing),
+ mLabelSpacing(p.label_spacing),
+ mPrecision(p.precision),
+ mUpdatesPerSec(p.update_rate),
+ mPerSec(p.show_per_sec),
+ mDisplayBar(p.show_bar),
+ mDisplayHistory(p.show_history),
+ mDisplayMean(p.show_mean)
+{
+}
+
+BOOL LLStatBar::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ if (mDisplayBar)
+ {
+ if (mDisplayHistory)
+ {
+ mDisplayBar = FALSE;
+ mDisplayHistory = FALSE;
+ }
+ else
+ {
+ mDisplayHistory = TRUE;
+ }
+ }
+ else
+ {
+ mDisplayBar = TRUE;
+ }
+
+ LLView* parent = getParent();
+ parent->reshape(parent->getRect().getWidth(), parent->getRect().getHeight(), FALSE);
+
+ return FALSE;
+}
+
+void LLStatBar::draw()
+{
+ if (!mStatp)
+ {
+// llinfos << "No stats for statistics bar!" << llendl;
+ return;
+ }
+
+ // Get the values.
+ F32 current, min, max, mean;
+ if (mPerSec)
+ {
+ current = mStatp->getCurrentPerSec();
+ min = mStatp->getMinPerSec();
+ max = mStatp->getMaxPerSec();
+ mean = mStatp->getMeanPerSec();
+ }
+ else
+ {
+ current = mStatp->getCurrent();
+ min = mStatp->getMin();
+ max = mStatp->getMax();
+ mean = mStatp->getMean();
+ }
+
+
+ if ((mUpdatesPerSec == 0.f) || (mUpdateTimer.getElapsedTimeF32() > 1.f/mUpdatesPerSec) || (mValue == 0.f))
+ {
+ if (mDisplayMean)
+ {
+ mValue = mean;
+ }
+ else
+ {
+ mValue = current;
+ }
+ mUpdateTimer.reset();
+ }
+
+ S32 width = getRect().getWidth() - 40;
+ S32 max_width = width;
+ S32 bar_top = getRect().getHeight() - 15; // 16 pixels from top.
+ S32 bar_height = bar_top - 20;
+ S32 tick_height = 4;
+ S32 tick_width = 1;
+ S32 left, top, right, bottom;
+
+ F32 value_scale = max_width/(mMaxBar - mMinBar);
+
+ LLFontGL::getFontMonospace()->renderUTF8(mLabel, 0, 0, getRect().getHeight(), LLColor4(1.f, 1.f, 1.f, 1.f),
+ LLFontGL::LEFT, LLFontGL::TOP);
+
+ std::string value_format;
+ std::string value_str;
+ if (!mUnitLabel.empty())
+ {
+ value_format = llformat( "%%.%df%%s", mPrecision);
+ value_str = llformat( value_format.c_str(), mValue, mUnitLabel.c_str());
+ }
+ else
+ {
+ value_format = llformat( "%%.%df", mPrecision);
+ value_str = llformat( value_format.c_str(), mValue);
+ }
+
+ // Draw the value.
+ LLFontGL::getFontMonospace()->renderUTF8(value_str, 0, width, getRect().getHeight(),
+ LLColor4(1.f, 1.f, 1.f, 0.5f),
+ LLFontGL::RIGHT, LLFontGL::TOP);
+
+ value_format = llformat( "%%.%df", mPrecision);
+ if (mDisplayBar)
+ {
+ std::string tick_label;
+
+ // Draw the tick marks.
+ F32 tick_value;
+ top = bar_top;
+ bottom = bar_top - bar_height - tick_height/2;
+
+ LLGLSUIDefault gls_ui;
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ for (tick_value = mMinBar; tick_value <= mMaxBar; tick_value += mTickSpacing)
+ {
+ left = llfloor((tick_value - mMinBar)*value_scale);
+ right = left + tick_width;
+ gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 1.f, 1.f, 0.1f));
+ }
+
+ // Draw the tick labels (and big ticks).
+ bottom = bar_top - bar_height - tick_height;
+ for (tick_value = mMinBar; tick_value <= mMaxBar; tick_value += mLabelSpacing)
+ {
+ left = llfloor((tick_value - mMinBar)*value_scale);
+ right = left + tick_width;
+ gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 1.f, 1.f, 0.25f));
+
+ tick_label = llformat( value_format.c_str(), tick_value);
+ // draw labels for the tick marks
+ LLFontGL::getFontMonospace()->renderUTF8(tick_label, 0, left - 1, bar_top - bar_height - tick_height,
+ LLColor4(1.f, 1.f, 1.f, 0.5f),
+ LLFontGL::LEFT, LLFontGL::TOP);
+ }
+
+ // Now, draw the bars
+ top = bar_top;
+ bottom = bar_top - bar_height;
+
+ // draw background bar.
+ left = 0;
+ right = width;
+ gl_rect_2d(left, top, right, bottom, LLColor4(0.f, 0.f, 0.f, 0.25f));
+
+ if (mStatp->getNumValues() == 0)
+ {
+ // No data, don't draw anything...
+ return;
+ }
+ // draw min and max
+ left = (S32) ((min - mMinBar) * value_scale);
+
+ if (left < 0)
+ {
+ left = 0;
+ llwarns << "Min:" << min << llendl;
+ }
+
+ right = (S32) ((max - mMinBar) * value_scale);
+ gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 0.f, 0.f, 0.25f));
+
+ S32 num_values = mStatp->getNumValues() - 1;
+ if (mDisplayHistory)
+ {
+ S32 i;
+ for (i = 0; i < num_values; i++)
+ {
+ if (i == mStatp->getNextBin())
+ {
+ continue;
+ }
+ if (mPerSec)
+ {
+ left = (S32)((mStatp->getPrevPerSec(i) - mMinBar) * value_scale);
+ right = (S32)((mStatp->getPrevPerSec(i) - mMinBar) * value_scale) + 1;
+ gl_rect_2d(left, bottom+i+1, right, bottom+i, LLColor4(1.f, 0.f, 0.f, 1.f));
+ }
+ else
+ {
+ left = (S32)((mStatp->getPrev(i) - mMinBar) * value_scale);
+ right = (S32)((mStatp->getPrev(i) - mMinBar) * value_scale) + 1;
+ gl_rect_2d(left, bottom+i+1, right, bottom+i, LLColor4(1.f, 0.f, 0.f, 1.f));
+ }
+ }
+ }
+ else
+ {
+ // draw current
+ left = (S32) ((current - mMinBar) * value_scale) - 1;
+ right = (S32) ((current - mMinBar) * value_scale) + 1;
+ gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 0.f, 0.f, 1.f));
+ }
+
+ // draw mean bar
+ top = bar_top + 2;
+ bottom = bar_top - bar_height - 2;
+ left = (S32) ((mean - mMinBar) * value_scale) - 1;
+ right = (S32) ((mean - mMinBar) * value_scale) + 1;
+ gl_rect_2d(left, top, right, bottom, LLColor4(0.f, 1.f, 0.f, 1.f));
+ }
+
+ LLView::draw();
+}
+
+void LLStatBar::setRange(F32 bar_min, F32 bar_max, F32 tick_spacing, F32 label_spacing)
+{
+ mMinBar = bar_min;
+ mMaxBar = bar_max;
+ mTickSpacing = tick_spacing;
+ mLabelSpacing = label_spacing;
+}
+
+LLRect LLStatBar::getRequiredRect()
+{
+ LLRect rect;
+
+ if (mDisplayBar)
+ {
+ if (mDisplayHistory)
+ {
+ rect.mTop = 67;
+ }
+ else
+ {
+ rect.mTop = 40;
+ }
+ }
+ else
+ {
+ rect.mTop = 14;
+ }
+ return rect;
+}
diff --git a/indra/llui/llstatbar.h b/indra/llui/llstatbar.h
new file mode 100644
index 0000000000..7de782a24f
--- /dev/null
+++ b/indra/llui/llstatbar.h
@@ -0,0 +1,108 @@
+/**
+ * @file llstatbar.h
+ * @brief A little map of the world with network information
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSTATBAR_H
+#define LL_LLSTATBAR_H
+
+#include "llview.h"
+#include "llframetimer.h"
+
+class LLStat;
+
+class LLStatBar : public LLView
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
+ {
+ Optional<std::string> label;
+ Optional<std::string> unit_label;
+ Optional<F32> bar_min;
+ Optional<F32> bar_max;
+ Optional<F32> tick_spacing;
+ Optional<F32> label_spacing;
+ Optional<U32> precision;
+ Optional<F32> update_rate;
+ Optional<bool> show_per_sec;
+ Optional<bool> show_bar;
+ Optional<bool> show_history;
+ Optional<bool> show_mean;
+ Optional<std::string> stat;
+ Params()
+ : label("label"),
+ unit_label("unit_label"),
+ bar_min("bar_min", 0.0f),
+ bar_max("bar_max", 50.0f),
+ tick_spacing("tick_spacing", 10.0f),
+ label_spacing("label_spacing", 10.0f),
+ precision("precision", 0),
+ update_rate("update_rate", 5.0f),
+ show_per_sec("show_per_sec", TRUE),
+ show_bar("show_bar", TRUE),
+ show_history("show_history", FALSE),
+ show_mean("show_mean", TRUE),
+ stat("stat")
+ {
+ follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT);
+ }
+ };
+ LLStatBar(const Params&);
+
+ virtual void draw();
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+
+ void setStat(LLStat* stat) { mStatp = stat; }
+ void setRange(F32 bar_min, F32 bar_max, F32 tick_spacing, F32 label_spacing);
+ void getRange(F32& bar_min, F32& bar_max) { bar_min = mMinBar; bar_max = mMaxBar; }
+
+ /*virtual*/ LLRect getRequiredRect(); // Return the height of this object, given the set options.
+
+private:
+ F32 mMinBar;
+ F32 mMaxBar;
+ F32 mTickSpacing;
+ F32 mLabelSpacing;
+ U32 mPrecision;
+ F32 mUpdatesPerSec;
+ BOOL mPerSec; // Use the per sec stats.
+ BOOL mDisplayBar; // Display the bar graph.
+ BOOL mDisplayHistory;
+ BOOL mDisplayMean; // If true, display mean, if false, display current value
+
+ LLStat* mStatp;
+
+ LLFrameTimer mUpdateTimer;
+ LLUIString mLabel;
+ std::string mUnitLabel;
+ F32 mValue;
+};
+
+#endif
diff --git a/indra/llui/llstatgraph.cpp b/indra/llui/llstatgraph.cpp
new file mode 100644
index 0000000000..55d6b3159f
--- /dev/null
+++ b/indra/llui/llstatgraph.cpp
@@ -0,0 +1,163 @@
+/**
+ * @file llstatgraph.cpp
+ * @brief Simpler compact stat graph with tooltip
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+//#include "llviewerprecompiledheaders.h"
+#include "linden_common.h"
+
+#include "llstatgraph.h"
+#include "llrender.h"
+
+#include "llmath.h"
+#include "llui.h"
+#include "llstat.h"
+#include "llgl.h"
+#include "llglheaders.h"
+//#include "llviewercontrol.h"
+
+///////////////////////////////////////////////////////////////////////////////////
+
+LLStatGraph::LLStatGraph(const LLView::Params& p)
+: LLView(p)
+{
+ mStatp = NULL;
+ setToolTip(p.name());
+ mNumThresholds = 3;
+ mThresholdColors[0] = LLColor4(0.f, 1.f, 0.f, 1.f);
+ mThresholdColors[1] = LLColor4(1.f, 1.f, 0.f, 1.f);
+ mThresholdColors[2] = LLColor4(1.f, 0.f, 0.f, 1.f);
+ mThresholdColors[3] = LLColor4(1.f, 0.f, 0.f, 1.f);
+ mThresholds[0] = 50.f;
+ mThresholds[1] = 75.f;
+ mThresholds[2] = 100.f;
+ mMin = 0.f;
+ mMax = 125.f;
+ mPerSec = TRUE;
+ mValue = 0.f;
+ mPrecision = 0;
+}
+
+void LLStatGraph::draw()
+{
+ F32 range, frac;
+ range = mMax - mMin;
+ if (mStatp)
+ {
+ if (mPerSec)
+ {
+ mValue = mStatp->getMeanPerSec();
+ }
+ else
+ {
+ mValue = mStatp->getMean();
+ }
+ }
+ frac = (mValue - mMin) / range;
+ frac = llmax(0.f, frac);
+ frac = llmin(1.f, frac);
+
+ if (mUpdateTimer.getElapsedTimeF32() > 0.5f)
+ {
+ std::string format_str;
+ std::string tmp_str;
+ format_str = llformat("%%s%%.%df%%s", mPrecision);
+ tmp_str = llformat(format_str.c_str(), mLabel.c_str(), mValue, mUnits.c_str());
+ setToolTip(tmp_str);
+
+ mUpdateTimer.reset();
+ }
+
+ LLColor4 color;
+
+ S32 i;
+ for (i = 0; i < mNumThresholds - 1; i++)
+ {
+ if (mThresholds[i] > mValue)
+ {
+ break;
+ }
+ }
+
+ //gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0,
+ // LLUIColorTable::instance().getColor("ColorDropShadow"),
+ // (S32) gSavedSettings.getF32("DropShadowFloater") );
+
+ color = LLUIColorTable::instance().getColor( "MenuDefaultBgColor" );
+ gGL.color4fv(color.mV);
+ gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, TRUE);
+
+ gGL.color4fv(LLColor4::black.mV);
+ gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, FALSE);
+
+ color = mThresholdColors[i];
+ gGL.color4fv(color.mV);
+ gl_rect_2d(1, llround(frac*getRect().getHeight()), getRect().getWidth() - 1, 0, TRUE);
+}
+
+void LLStatGraph::setValue(const LLSD& value)
+{
+ mValue = (F32)value.asReal();
+}
+
+void LLStatGraph::setMin(const F32 min)
+{
+ mMin = min;
+}
+
+void LLStatGraph::setMax(const F32 max)
+{
+ mMax = max;
+}
+
+void LLStatGraph::setStat(LLStat *statp)
+{
+ mStatp = statp;
+}
+
+void LLStatGraph::setLabel(const std::string& label)
+{
+ mLabel = label;
+}
+
+void LLStatGraph::setUnits(const std::string& units)
+{
+ mUnits = units;
+}
+
+void LLStatGraph::setPrecision(const S32 precision)
+{
+ mPrecision = precision;
+}
+
+void LLStatGraph::setThreshold(const S32 i, F32 value)
+{
+ mThresholds[i] = value;
+}
diff --git a/indra/llui/llstatgraph.h b/indra/llui/llstatgraph.h
new file mode 100644
index 0000000000..dd38050b1b
--- /dev/null
+++ b/indra/llui/llstatgraph.h
@@ -0,0 +1,76 @@
+/**
+ * @file llstatgraph.h
+ * @brief Simpler compact stat graph with tooltip
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSTATGRAPH_H
+#define LL_LLSTATGRAPH_H
+
+#include "llview.h"
+#include "llframetimer.h"
+#include "v4color.h"
+
+class LLStat;
+
+class LLStatGraph : public LLView
+{
+public:
+ LLStatGraph(const LLView::Params&);
+
+ virtual void draw();
+
+ void setLabel(const std::string& label);
+ void setUnits(const std::string& units);
+ void setPrecision(const S32 precision);
+ void setStat(LLStat *statp);
+ void setThreshold(const S32 i, F32 value);
+ void setMin(const F32 min);
+ void setMax(const F32 max);
+
+ /*virtual*/ void setValue(const LLSD& value);
+
+ LLStat *mStatp;
+ BOOL mPerSec;
+private:
+ F32 mValue;
+
+ F32 mMin;
+ F32 mMax;
+ LLFrameTimer mUpdateTimer;
+ std::string mLabel;
+ std::string mUnits;
+ S32 mPrecision; // Num of digits of precision after dot
+
+ S32 mNumThresholds;
+ F32 mThresholds[4];
+ LLColor4 mThresholdColors[4];
+};
+
+#endif // LL_LLSTATGRAPH_H
diff --git a/indra/llui/llstatview.cpp b/indra/llui/llstatview.cpp
new file mode 100644
index 0000000000..9580c76e2a
--- /dev/null
+++ b/indra/llui/llstatview.cpp
@@ -0,0 +1,73 @@
+/**
+ * @file llstatview.cpp
+ * @brief Container for all statistics info.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llstatview.h"
+
+#include "llerror.h"
+#include "llstatbar.h"
+#include "llfontgl.h"
+#include "llgl.h"
+#include "llui.h"
+
+#include "llstatbar.h"
+
+LLStatView::LLStatView(const LLStatView::Params& p)
+: LLContainerView(p),
+ mSetting(p.setting)
+{
+ BOOL isopen = getDisplayChildren();
+ if (mSetting.length() > 0)
+ {
+ isopen = LLUI::sSettingGroups["config"]->getBOOL(mSetting);
+ }
+ setDisplayChildren(isopen);
+}
+
+LLStatView::~LLStatView()
+{
+ // Children all cleaned up by default view destructor.
+ if (mSetting.length() > 0)
+ {
+ BOOL isopen = getDisplayChildren();
+ LLUI::sSettingGroups["config"]->setBOOL(mSetting, isopen);
+ }
+}
+
+
+static StatViewRegistry::Register<LLStatBar> r1("stat_bar");
+static StatViewRegistry::Register<LLStatView> r2("stat_view");
+// stat_view can be a child of panels/etc.
+static LLDefaultChildRegistry::Register<LLStatView> r3("stat_view");
+
+
diff --git a/indra/llui/llstatview.h b/indra/llui/llstatview.h
new file mode 100644
index 0000000000..eee4e2b7e4
--- /dev/null
+++ b/indra/llui/llstatview.h
@@ -0,0 +1,72 @@
+/**
+ * @file llstatview.h
+ * @brief Container for all statistics info.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSTATVIEW_H
+#define LL_LLSTATVIEW_H
+
+#include "llstatbar.h"
+#include "llcontainerview.h"
+#include <vector>
+
+class LLStatBar;
+
+// widget registrars
+struct StatViewRegistry : public LLChildRegistry<StatViewRegistry>
+{};
+
+class LLStatView : public LLContainerView
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLContainerView::Params>
+ {
+ Optional<std::string> setting;
+ Params()
+ : setting("setting")
+ {
+ follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT);
+ }
+ };
+
+ // my valid children are stored in this registry
+ typedef StatViewRegistry child_registry_t;
+
+ ~LLStatView();
+
+protected:
+ LLStatView(const Params&);
+ friend class LLUICtrlFactory;
+
+protected:
+ std::string mSetting;
+
+};
+#endif // LL_STATVIEW_
diff --git a/indra/llui/llstyle.cpp b/indra/llui/llstyle.cpp
index a716cbbaec..71511f69a4 100644
--- a/indra/llui/llstyle.cpp
+++ b/indra/llui/llstyle.cpp
@@ -33,112 +33,42 @@
#include "linden_common.h"
#include "llstyle.h"
+
+#include "llfontgl.h"
#include "llstring.h"
#include "llui.h"
-//#include "llviewerimagelist.h"
-
-LLStyle::LLStyle()
-{
- init(TRUE, LLColor4(0,0,0,1),LLStringUtil::null);
-}
-
-LLStyle::LLStyle(const LLStyle &style)
-{
- if (this != &style)
- {
- init(style.isVisible(),style.getColor(),style.getFontString());
- if (style.isLink())
- {
- setLinkHREF(style.getLinkHREF());
- }
- mItalic = style.mItalic;
- mBold = style.mBold;
- mUnderline = style.mUnderline;
- mDropShadow = style.mDropShadow;
- mImageHeight = style.mImageHeight;
- mImageWidth = style.mImageWidth;
- mImagep = style.mImagep;
- mIsEmbeddedItem = style.mIsEmbeddedItem;
- }
- else
- {
- init(TRUE, LLColor4(0,0,0,1),LLStringUtil::null);
- }
-}
-
-LLStyle::LLStyle(BOOL is_visible, const LLColor4 &color, const std::string& font_name)
-{
- init(is_visible, color, font_name);
-}
-
-void LLStyle::init(BOOL is_visible, const LLColor4 &color, const std::string& font_name)
+LLStyle::Params::Params()
+: visible("visible", true),
+ drop_shadow("drop_shadow", LLFontGL::NO_SHADOW),
+ color("color", LLColor4::black),
+ font("font", LLFontGL::getFontMonospace()),
+ image("image"),
+ link_href("href")
+{}
+
+
+LLStyle::LLStyle(const LLStyle::Params& p)
+: mVisible(p.visible),
+ mColor(p.color()),
+ mReadOnlyColor(p.readonly_color()),
+ mFont(p.font()),
+ mLink(p.link_href),
+ mDropShadow(p.drop_shadow),
+ mImagep(p.image())
+{}
+
+void LLStyle::setFont(const LLFontGL* font)
{
- mVisible = is_visible;
- mColor = color;
- setFontName(font_name);
- setLinkHREF(LLStringUtil::null);
- mItalic = FALSE;
- mBold = FALSE;
- mUnderline = FALSE;
- mDropShadow = FALSE;
- mImageHeight = 0;
- mImageWidth = 0;
- mIsEmbeddedItem = FALSE;
+ mFont = font;
}
-// Copy assignment
-LLStyle &LLStyle::operator=(const LLStyle &rhs)
+const LLFontGL* LLStyle::getFont() const
{
- if (this != &rhs)
- {
- setVisible(rhs.isVisible());
- setColor(rhs.getColor());
- this->mFontName = rhs.getFontString();
- this->mLink = rhs.getLinkHREF();
- mImagep = rhs.mImagep;
- mImageHeight = rhs.mImageHeight;
- mImageWidth = rhs.mImageWidth;
- mItalic = rhs.mItalic;
- mBold = rhs.mBold;
- mUnderline = rhs.mUnderline;
- mDropShadow = rhs.mDropShadow;
- mIsEmbeddedItem = rhs.mIsEmbeddedItem;
- }
-
- return *this;
+ return mFont;
}
-
-void LLStyle::setFontName(const std::string& fontname)
-{
- mFontName = fontname;
-
- std::string fontname_lc = fontname;
- LLStringUtil::toLower(fontname_lc);
-
- mFontID = LLFONT_OCRA; // default
-
- if ((fontname_lc == "sansserif") || (fontname_lc == "sans-serif"))
- {
- mFontID = LLFONT_SANSSERIF;
- }
- else if ((fontname_lc == "serif"))
- {
- mFontID = LLFONT_SMALL;
- }
- else if ((fontname_lc == "sansserifbig"))
- {
- mFontID = LLFONT_SANSSERIF_BIG;
- }
- else if (fontname_lc == "small")
- {
- mFontID = LLFONT_SANSSERIF_SMALL;
- }
-}
-
-
void LLStyle::setLinkHREF(const std::string& href)
{
mLink = href;
@@ -166,12 +96,10 @@ LLUIImagePtr LLStyle::getImage() const
void LLStyle::setImage(const LLUUID& src)
{
- mImagep = LLUI::sImageProvider->getUIImageByID(src);
+ mImagep = LLUI::getUIImageByID(src);
}
-
-void LLStyle::setImageSize(S32 width, S32 height)
+void LLStyle::setImage(const std::string& name)
{
- mImageWidth = width;
- mImageHeight = height;
+ mImagep = LLUI::getUIImage(name);
}
diff --git a/indra/llui/llstyle.h b/indra/llui/llstyle.h
index 3ad379cdd9..ee9ca730e9 100644
--- a/indra/llui/llstyle.h
+++ b/indra/llui/llstyle.h
@@ -34,60 +34,64 @@
#define LL_LLSTYLE_H
#include "v4color.h"
-#include "llresmgr.h"
-#include "llfont.h"
#include "llui.h"
+#include "llinitparam.h"
+
+class LLFontGL;
class LLStyle : public LLRefCount
{
public:
- LLStyle();
- LLStyle(const LLStyle &style);
- LLStyle(BOOL is_visible, const LLColor4 &color, const std::string& font_name);
-
- LLStyle &operator=(const LLStyle &rhs);
-
- virtual void init (BOOL is_visible, const LLColor4 &color, const std::string& font_name);
+ struct Params : public LLInitParam::Block<Params>
+ {
+ Optional<bool> visible;
+ Optional<LLFontGL::ShadowType> drop_shadow;
+ Optional<LLUIColor> color,
+ readonly_color;
+ Optional<const LLFontGL*> font;
+ Optional<LLUIImage*> image;
+ Optional<std::string> link_href;
+ Params();
+ };
+ LLStyle(const Params& p = Params());
+public:
+ const LLColor4& getColor() const { return mColor; }
+ void setColor(const LLColor4 &color) { mColor = color; }
- virtual const LLColor4& getColor() const { return mColor; }
- virtual void setColor(const LLColor4 &color) { mColor = color; }
+ const LLColor4& getReadOnlyColor() const { return mReadOnlyColor; }
- virtual BOOL isVisible() const;
- virtual void setVisible(BOOL is_visible);
+ BOOL isVisible() const;
+ void setVisible(BOOL is_visible);
- virtual const std::string& getFontString() const { return mFontName; }
- virtual void setFontName(const std::string& fontname);
- virtual LLFONT_ID getFontID() const { return mFontID; }
+ LLFontGL::ShadowType getShadowType() { return mDropShadow; }
- virtual const std::string& getLinkHREF() const { return mLink; }
- virtual void setLinkHREF(const std::string& href);
- virtual BOOL isLink() const;
+ void setFont(const LLFontGL* font);
+ const LLFontGL* getFont() const;
- virtual LLUIImagePtr getImage() const;
- virtual void setImage(const LLUUID& src);
+ const std::string& getLinkHREF() const { return mLink; }
+ void setLinkHREF(const std::string& href);
+ BOOL isLink() const;
- virtual BOOL isImage() const { return ((mImageWidth != 0) && (mImageHeight != 0)); }
- virtual void setImageSize(S32 width, S32 height);
+ LLUIImagePtr getImage() const;
+ void setImage(const LLUUID& src);
+ void setImage(const std::string& name);
- BOOL getIsEmbeddedItem() const { return mIsEmbeddedItem; }
- void setIsEmbeddedItem( BOOL b ) { mIsEmbeddedItem = b; }
+ BOOL isImage() const { return mImagep.notNull(); }
// inlined here to make it easier to compare to member data below. -MG
bool operator==(const LLStyle &rhs) const
{
return
- mVisible == rhs.isVisible()
- && mColor == rhs.getColor()
- && mFontName == rhs.getFontString()
- && mLink == rhs.getLinkHREF()
+ mVisible == rhs.mVisible
+ && mColor == rhs.mColor
+ && mReadOnlyColor == rhs.mReadOnlyColor
+ && mFont == rhs.mFont
+ && mLink == rhs.mLink
&& mImagep == rhs.mImagep
- && mImageHeight == rhs.mImageHeight
- && mImageWidth == rhs.mImageWidth
&& mItalic == rhs.mItalic
&& mBold == rhs.mBold
&& mUnderline == rhs.mUnderline
- && mDropShadow == rhs.mDropShadow
- && mIsEmbeddedItem == rhs.mIsEmbeddedItem;
+ && mDropShadow == rhs.mDropShadow;
}
bool operator!=(const LLStyle& rhs) const { return !(*this == rhs); }
@@ -96,21 +100,19 @@ public:
BOOL mItalic;
BOOL mBold;
BOOL mUnderline;
- BOOL mDropShadow;
- S32 mImageWidth;
- S32 mImageHeight;
+ LLFontGL::ShadowType mDropShadow;
protected:
- virtual ~LLStyle() { }
+ ~LLStyle() { }
private:
BOOL mVisible;
- LLColor4 mColor;
+ LLUIColor mColor;
+ LLUIColor mReadOnlyColor;
std::string mFontName;
- LLFONT_ID mFontID;
+ const LLFontGL* mFont; // cached for performance
std::string mLink;
LLUIImagePtr mImagep;
- BOOL mIsEmbeddedItem;
};
typedef LLPointer<LLStyle> LLStyleSP;
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index f4169488d4..43c44f2253 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -31,77 +31,159 @@
*/
#include "linden_common.h"
+
#include "lltabcontainer.h"
+
#include "llfocusmgr.h"
#include "llbutton.h"
+#include "lllocalcliprect.h"
#include "llrect.h"
-#include "llresmgr.h"
#include "llresizehandle.h"
#include "lltextbox.h"
#include "llcriticaldamp.h"
#include "lluictrlfactory.h"
-#include "lltabcontainervertical.h"
#include "llrender.h"
+#include "llfloater.h"
+#include "lltrans.h"
+
+//----------------------------------------------------------------------------
+
+// Implementation Notes:
+// - Each tab points to a LLPanel (see LLTabTuple below)
+// - When a tab is selected, the validation callback
+// (LLUICtrl::mValidateSignal) is called
+// - If the validation callback returns true (or none is provided),
+// the tab is changed and the commit callback
+// (LLUICtrl::mCommitSignal) is called
+// - Callbacks pass the LLTabContainer as the control,
+// and the NAME of the selected PANEL as the LLSD data
+
+//----------------------------------------------------------------------------
const F32 SCROLL_STEP_TIME = 0.4f;
const F32 SCROLL_DELAY_TIME = 0.5f;
-const S32 TAB_PADDING = 15;
-const S32 TABCNTR_TAB_MIN_WIDTH = 60;
-const S32 TABCNTR_VERT_TAB_MIN_WIDTH = 100;
-const S32 TABCNTR_TAB_MAX_WIDTH = 150;
-const S32 TABCNTR_TAB_PARTIAL_WIDTH = 12; // When tabs are parially obscured, how much can you still see.
-const S32 TABCNTR_TAB_HEIGHT = 16;
-const S32 TABCNTR_ARROW_BTN_SIZE = 16;
-const S32 TABCNTR_BUTTON_PANEL_OVERLAP = 1; // how many pixels the tab buttons and tab panels overlap.
-const S32 TABCNTR_TAB_H_PAD = 4;
-
-const S32 TABCNTR_CLOSE_BTN_SIZE = 16;
-const S32 TABCNTR_HEADER_HEIGHT = LLPANEL_BORDER_WIDTH + TABCNTR_CLOSE_BTN_SIZE;
-
-const S32 TABCNTRV_CLOSE_BTN_SIZE = 16;
-const S32 TABCNTRV_HEADER_HEIGHT = LLPANEL_BORDER_WIDTH + TABCNTRV_CLOSE_BTN_SIZE;
-//const S32 TABCNTRV_TAB_WIDTH = 100;
-const S32 TABCNTRV_ARROW_BTN_SIZE = 16;
-const S32 TABCNTRV_PAD = 0;
-
-static LLRegisterWidget<LLTabContainer> r("tab_container");
-
-LLTabContainer::LLTabContainer(const std::string& name, const LLRect& rect, TabPosition pos,
- BOOL bordered, BOOL is_vertical )
- :
- LLPanel(name, rect, bordered),
+
+void LLTabContainer::TabPositions::declareValues()
+{
+ declare("top", LLTabContainer::TOP);
+ declare("bottom", LLTabContainer::BOTTOM);
+ declare("left", LLTabContainer::LEFT);
+}
+
+//----------------------------------------------------------------------------
+
+// Structure used to map tab buttons to and from tab panels
+class LLTabTuple
+{
+public:
+ LLTabTuple( LLTabContainer* c, LLPanel* p, LLButton* b, LLTextBox* placeholder = NULL)
+ :
+ mTabContainer(c),
+ mTabPanel(p),
+ mButton(b),
+ mOldState(FALSE),
+ mPlaceholderText(placeholder),
+ mPadding(0)
+ {}
+
+ LLTabContainer* mTabContainer;
+ LLPanel* mTabPanel;
+ LLButton* mButton;
+ BOOL mOldState;
+ LLTextBox* mPlaceholderText;
+ S32 mPadding;
+};
+
+//----------------------------------------------------------------------------
+
+struct LLPlaceHolderPanel : public LLPanel
+{
+ // create dummy param block to register with "placeholder" nane
+ struct Params : public LLPanel::Params{};
+ LLPlaceHolderPanel(const Params& p) : LLPanel(p)
+ {}
+};
+static LLDefaultChildRegistry::Register<LLPlaceHolderPanel> r1("placeholder");
+static LLDefaultChildRegistry::Register<LLTabContainer> r2("tab_container");
+
+LLTabContainer::TabParams::TabParams()
+: tab_top_image_unselected("tab_top_image_unselected"),
+ tab_top_image_selected("tab_top_image_selected"),
+ tab_bottom_image_unselected("tab_bottom_image_unselected"),
+ tab_bottom_image_selected("tab_bottom_image_selected"),
+ tab_left_image_unselected("tab_left_image_unselected"),
+ tab_left_image_selected("tab_left_image_selected")
+{}
+
+LLTabContainer::Params::Params()
+: tab_width("tab_width"),
+ tab_min_width("tab_min_width"),
+ tab_max_width("tab_max_width"),
+ tab_height("tab_height"),
+ label_pad_bottom("label_pad_bottom"),
+ label_pad_left("label_pad_left"),
+ tab_position("tab_position"),
+ hide_tabs("hide_tabs", false),
+ tab_padding_right("tab_padding_right"),
+ first_tab("first_tab"),
+ middle_tab("middle_tab"),
+ last_tab("last_tab")
+{
+ name(std::string("tab_container"));
+ mouse_opaque = false;
+}
+
+LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
+: LLPanel(p),
mCurrentTabIdx(-1),
- mNextTabIdx(-1),
- mTabsHidden(FALSE),
+ mTabsHidden(p.hide_tabs),
mScrolled(FALSE),
mScrollPos(0),
mScrollPosPixels(0),
mMaxScrollPos(0),
- mCloseCallback( NULL ),
- mCallbackUserdata( NULL ),
mTitleBox(NULL),
mTopBorderHeight(LLPANEL_BORDER_WIDTH),
- mTabPosition(pos),
mLockedTabCount(0),
- mMinTabWidth(TABCNTR_TAB_MIN_WIDTH),
- mMaxTabWidth(TABCNTR_TAB_MAX_WIDTH),
+ mMinTabWidth(0),
+ mMaxTabWidth(p.tab_max_width),
+ mTabHeight(p.tab_height),
+ mLabelPadBottom(p.label_pad_bottom),
+ mLabelPadLeft(p.label_pad_left),
mPrevArrowBtn(NULL),
mNextArrowBtn(NULL),
- mIsVertical(is_vertical),
+ mIsVertical( p.tab_position == LEFT ),
// Horizontal Specific
mJumpPrevArrowBtn(NULL),
mJumpNextArrowBtn(NULL),
- mRightTabBtnOffset(0),
- mTotalTabWidth(0)
-{
- //RN: HACK to support default min width for legacy vertical tab containers
- if (mIsVertical)
+ mRightTabBtnOffset(p.tab_padding_right),
+ mTotalTabWidth(0),
+ mTabPosition(p.tab_position),
+ mFontHalign(p.font_halign),
+ mFont(p.font),
+ mFirstTabParams(p.first_tab),
+ mMiddleTabParams(p.middle_tab),
+ mLastTabParams(p.last_tab)
+{
+ static LLUICachedControl<S32> tabcntr_vert_tab_min_width ("UITabCntrVertTabMinWidth", 0);
+
+ mDragAndDropDelayTimer.stop();
+
+ if (p.tab_width.isProvided())
+ {
+ mMinTabWidth = p.tab_width;
+ }
+ else if (!mIsVertical)
{
- mMinTabWidth = TABCNTR_VERT_TAB_MIN_WIDTH;
+ mMinTabWidth = p.tab_min_width;
}
- setMouseOpaque(FALSE);
+ else
+ {
+ // *HACK: support default min width for legacy vertical
+ // tab containers
+ mMinTabWidth = tabcntr_vert_tab_min_width;
+ }
+
initButtons( );
- mDragAndDropDelayTimer.stop();
}
LLTabContainer::~LLTabContainer()
@@ -123,7 +205,7 @@ void LLTabContainer::reshape(S32 width, S32 height, BOOL called_from_parent)
}
//virtual
-LLView* LLTabContainer::getChildView(const std::string& name, BOOL recurse, BOOL create_if_missing) const
+LLView* LLTabContainer::getChildView(const std::string& name, BOOL recurse) const
{
tuple_list_t::const_iterator itor;
for (itor = mTabList.begin(); itor != mTabList.end(); ++itor)
@@ -140,26 +222,81 @@ LLView* LLTabContainer::getChildView(const std::string& name, BOOL recurse, BOOL
for (itor = mTabList.begin(); itor != mTabList.end(); ++itor)
{
LLPanel *panel = (*itor)->mTabPanel;
- LLView *child = panel->getChildView(name, recurse, FALSE);
+ LLView *child = panel->getChildView(name, recurse);
if (child)
{
return child;
}
}
}
- return LLView::getChildView(name, recurse, create_if_missing);
+ return LLView::getChildView(name, recurse);
+}
+
+//virtual
+LLView* LLTabContainer::findChildView(const std::string& name, BOOL recurse) const
+{
+ tuple_list_t::const_iterator itor;
+ for (itor = mTabList.begin(); itor != mTabList.end(); ++itor)
+ {
+ LLPanel *panel = (*itor)->mTabPanel;
+ if (panel->getName() == name)
+ {
+ return panel;
+ }
+ }
+
+ if (recurse)
+ {
+ for (itor = mTabList.begin(); itor != mTabList.end(); ++itor)
+ {
+ LLPanel *panel = (*itor)->mTabPanel;
+ LLView *child = panel->findChildView(name, recurse);
+ if (child)
+ {
+ return child;
+ }
+ }
+ }
+ return LLView::findChildView(name, recurse);
+}
+
+bool LLTabContainer::addChild(LLView* view, S32 tab_group)
+{
+ LLPanel* panelp = dynamic_cast<LLPanel*>(view);
+
+ if (panelp)
+ {
+ addTabPanel(TabPanelParams().panel(panelp).label(panelp->getLabel()).is_placeholder(dynamic_cast<LLPlaceHolderPanel*>(view) != NULL));
+ return true;
+ }
+ else
+ {
+ return LLUICtrl::addChild(view, tab_group);
+ }
+}
+
+BOOL LLTabContainer::postBuild()
+{
+ selectFirstTab();
+
+ return TRUE;
}
// virtual
void LLTabContainer::draw()
{
+ static LLUICachedControl<S32> tabcntrv_pad ("UITabCntrvPad", 0);
+ static LLUICachedControl<S32> tabcntrv_arrow_btn_size ("UITabCntrvArrowBtnSize", 0);
+ static LLUICachedControl<S32> tabcntr_tab_h_pad ("UITabCntrTabHPad", 0);
+ static LLUICachedControl<S32> tabcntr_arrow_btn_size ("UITabCntrArrowBtnSize", 0);
+ static LLUICachedControl<S32> tabcntr_tab_partial_width ("UITabCntrTabPartialWidth", 0);
S32 target_pixel_scroll = 0;
S32 cur_scroll_pos = getScrollPos();
if (cur_scroll_pos > 0)
{
+ S32 available_width_with_arrows = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + tabcntr_arrow_btn_size + tabcntr_arrow_btn_size + 1);
if (!mIsVertical)
{
- S32 available_width_with_arrows = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1);
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
if (cur_scroll_pos == 0)
@@ -171,31 +308,15 @@ void LLTabContainer::draw()
}
// Show part of the tab to the left of what is fully visible
- target_pixel_scroll -= TABCNTR_TAB_PARTIAL_WIDTH;
+ target_pixel_scroll -= tabcntr_tab_partial_width;
// clamp so that rightmost tab never leaves right side of screen
target_pixel_scroll = llmin(mTotalTabWidth - available_width_with_arrows, target_pixel_scroll);
}
- else
- {
- S32 available_height_with_arrows = getRect().getHeight() - getTopBorderHeight() - (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1);
- for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
- {
- if (cur_scroll_pos==0)
- {
- break;
- }
- target_pixel_scroll += (*iter)->mButton->getRect().getHeight();
- cur_scroll_pos--;
- }
- S32 total_tab_height = (BTN_HEIGHT + TABCNTRV_PAD) * getTabCount() + TABCNTRV_PAD;
- // clamp so that the bottom tab never leaves bottom of panel
- target_pixel_scroll = llmin(total_tab_height - available_height_with_arrows, target_pixel_scroll);
- }
}
setScrollPosPixels((S32)lerp((F32)getScrollPosPixels(), (F32)target_pixel_scroll, LLCriticalDamp::getInterpolant(0.08f)));
- BOOL has_scroll_arrows = (mMaxScrollPos > 0) || (mScrollPosPixels > 0);
+ BOOL has_scroll_arrows = !getTabsHidden() && ((mMaxScrollPos > 0) || (mScrollPosPixels > 0));
if (!mIsVertical)
{
mJumpPrevArrowBtn->setVisible( has_scroll_arrows );
@@ -207,24 +328,33 @@ void LLTabContainer::draw()
S32 left = 0, top = 0;
if (mIsVertical)
{
- top = getRect().getHeight() - getTopBorderHeight() - LLPANEL_BORDER_WIDTH - 1 - (has_scroll_arrows ? TABCNTRV_ARROW_BTN_SIZE : 0);
+ top = getRect().getHeight() - getTopBorderHeight() - LLPANEL_BORDER_WIDTH - 1 - (has_scroll_arrows ? tabcntrv_arrow_btn_size : 0);
top += getScrollPosPixels();
}
else
{
// Set the leftmost position of the tab buttons.
- left = LLPANEL_BORDER_WIDTH + (has_scroll_arrows ? (TABCNTR_ARROW_BTN_SIZE * 2) : TABCNTR_TAB_H_PAD);
+ left = LLPANEL_BORDER_WIDTH + (has_scroll_arrows ? (tabcntr_arrow_btn_size * 2) : tabcntr_tab_h_pad);
left -= getScrollPosPixels();
}
// Hide all the buttons
- for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ if (getTabsHidden())
{
- LLTabTuple* tuple = *iter;
- tuple->mButton->setVisible( FALSE );
+ for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ {
+ LLTabTuple* tuple = *iter;
+ tuple->mButton->setVisible( FALSE );
+ }
}
- LLPanel::draw();
+ {
+ LLRect clip_rect = getLocalRect();
+ clip_rect.mLeft+=(LLPANEL_BORDER_WIDTH + 2);
+ clip_rect.mRight-=(LLPANEL_BORDER_WIDTH + 2);
+ LLLocalClipRect clip(clip_rect);
+ LLPanel::draw();
+ }
// if tabs are hidden, don't draw them and leave them in the invisible state
if (!getTabsHidden())
@@ -236,24 +366,6 @@ void LLTabContainer::draw()
tuple->mButton->setVisible( TRUE );
}
- // Draw some of the buttons...
- LLRect clip_rect = getLocalRect();
- if (has_scroll_arrows)
- {
- // ...but clip them.
- if (mIsVertical)
- {
- clip_rect.mBottom = mNextArrowBtn->getRect().mTop + 3*TABCNTRV_PAD;
- clip_rect.mTop = mPrevArrowBtn->getRect().mBottom - 3*TABCNTRV_PAD;
- }
- else
- {
- clip_rect.mLeft = mPrevArrowBtn->getRect().mRight;
- clip_rect.mRight = mNextArrowBtn->getRect().mLeft;
- }
- }
- LLLocalClipRect clip(clip_rect);
-
S32 max_scroll_visible = getTabCount() - getMaxScrollPos() + getScrollPos();
S32 idx = 0;
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
@@ -262,7 +374,7 @@ void LLTabContainer::draw()
tuple->mButton->translate( left ? left - tuple->mButton->getRect().mLeft : 0,
top ? top - tuple->mButton->getRect().mTop : 0 );
- if (top) top -= BTN_HEIGHT + TABCNTRV_PAD;
+ if (top) top -= BTN_HEIGHT + tabcntrv_pad;
if (left) left += tuple->mButton->getRect().getWidth();
if (!mIsVertical)
@@ -282,12 +394,6 @@ void LLTabContainer::draw()
}
}
}
- LLUI::pushMatrix();
- {
- LLUI::translate((F32)tuple->mButton->getRect().mLeft, (F32)tuple->mButton->getRect().mBottom, 0.f);
- tuple->mButton->draw();
- }
- LLUI::popMatrix();
idx++;
}
@@ -316,8 +422,9 @@ void LLTabContainer::draw()
// virtual
BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
{
+ static LLUICachedControl<S32> tabcntrv_pad ("UITabCntrvPad", 0);
BOOL handled = FALSE;
- BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
+ BOOL has_scroll_arrows = (getMaxScrollPos() > 0) && !getTabsHidden();
if (has_scroll_arrows)
{
@@ -359,9 +466,9 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
if (mIsVertical)
{
tab_rect = LLRect(firsttuple->mButton->getRect().mLeft,
- has_scroll_arrows ? mPrevArrowBtn->getRect().mBottom - TABCNTRV_PAD : mPrevArrowBtn->getRect().mTop,
+ has_scroll_arrows ? mPrevArrowBtn->getRect().mBottom - tabcntrv_pad : mPrevArrowBtn->getRect().mTop,
firsttuple->mButton->getRect().mRight,
- has_scroll_arrows ? mNextArrowBtn->getRect().mTop + TABCNTRV_PAD : mNextArrowBtn->getRect().mBottom );
+ has_scroll_arrows ? mNextArrowBtn->getRect().mTop + tabcntrv_pad : mNextArrowBtn->getRect().mBottom );
}
else
{
@@ -376,7 +483,7 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
index = llclamp(index, 0, tab_count-1);
LLButton* tab_button = getTab(index)->mButton;
gFocusMgr.setMouseCapture(this);
- gFocusMgr.setKeyboardFocus(tab_button);
+ tab_button->setFocus(TRUE);
}
}
return handled;
@@ -386,7 +493,7 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
BOOL LLTabContainer::handleHover( S32 x, S32 y, MASK mask )
{
BOOL handled = FALSE;
- BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
+ BOOL has_scroll_arrows = (getMaxScrollPos() > 0) && !getTabsHidden();
if (has_scroll_arrows)
{
@@ -428,7 +535,7 @@ BOOL LLTabContainer::handleHover( S32 x, S32 y, MASK mask )
BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
{
BOOL handled = FALSE;
- BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
+ BOOL has_scroll_arrows = (getMaxScrollPos() > 0) && !getTabsHidden();
if (has_scroll_arrows)
{
@@ -481,9 +588,10 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
}
// virtual
-BOOL LLTabContainer::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect )
+BOOL LLTabContainer::handleToolTip( S32 x, S32 y, MASK mask)
{
- BOOL handled = LLPanel::handleToolTip( x, y, msg, sticky_rect );
+ static LLUICachedControl<S32> tabcntrv_pad ("UITabCntrvPad", 0);
+ BOOL handled = LLPanel::handleToolTip( x, y, mask);
if (!handled && getTabCount() > 0)
{
LLTabTuple* firsttuple = getTab(0);
@@ -493,9 +601,9 @@ BOOL LLTabContainer::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* stic
if (mIsVertical)
{
clip = LLRect(firsttuple->mButton->getRect().mLeft,
- has_scroll_arrows ? mPrevArrowBtn->getRect().mBottom - TABCNTRV_PAD : mPrevArrowBtn->getRect().mTop,
+ has_scroll_arrows ? mPrevArrowBtn->getRect().mBottom - tabcntrv_pad : mPrevArrowBtn->getRect().mTop,
firsttuple->mButton->getRect().mRight,
- has_scroll_arrows ? mNextArrowBtn->getRect().mTop + TABCNTRV_PAD : mNextArrowBtn->getRect().mBottom );
+ has_scroll_arrows ? mNextArrowBtn->getRect().mTop + tabcntrv_pad : mNextArrowBtn->getRect().mBottom );
}
else
{
@@ -513,19 +621,13 @@ BOOL LLTabContainer::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* stic
tuple->mButton->setVisible( TRUE );
S32 local_x = x - tuple->mButton->getRect().mLeft;
S32 local_y = y - tuple->mButton->getRect().mBottom;
- handled = tuple->mButton->handleToolTip( local_x, local_y, msg, sticky_rect );
+ handled = tuple->mButton->handleToolTip( local_x, local_y, mask);
if( handled )
{
break;
}
}
}
-
- for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
- {
- LLTabTuple* tuple = *iter;
- tuple->mButton->setVisible( FALSE );
- }
}
return handled;
}
@@ -617,19 +719,11 @@ BOOL LLTabContainer::handleKeyHere(KEY key, MASK mask)
}
// virtual
-LLXMLNodePtr LLTabContainer::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLPanel::getXML();
- node->createChild("tab_position", TRUE)->setStringValue((getTabPosition() == TOP ? "top" : "bottom"));
- return node;
-}
-
-// virtual
BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType type, void* cargo_data, EAcceptance *accept, std::string &tooltip)
{
BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
- if( mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME )
+ if( mDragAndDropDelayTimer.getStarted() && mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME )
{
if (has_scroll_arrows)
{
@@ -676,21 +770,53 @@ BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDrag
return LLView::handleDragAndDrop(x, y, mask, drop, type, cargo_data, accept, tooltip);
}
-void LLTabContainer::addTabPanel(LLPanel* child,
- const std::string& label,
- BOOL select,
- void (*on_tab_clicked)(void*, bool),
- void* userdata,
- S32 indent,
- BOOL placeholder,
- eInsertionPoint insertion_point)
+void LLTabContainer::addTabPanel(LLPanel* panelp)
+{
+ addTabPanel(TabPanelParams().panel(panelp));
+}
+
+// function to update images
+void LLTabContainer::update_images(LLTabTuple* tuple, TabParams params, LLTabContainer::TabPosition pos)
+{
+ if (tuple && tuple->mButton)
+ {
+ if (pos == LLTabContainer::TOP)
+ {
+ tuple->mButton->setImageUnselected(static_cast<LLUIImage*>(params.tab_top_image_unselected));
+ tuple->mButton->setImageSelected(static_cast<LLUIImage*>(params.tab_top_image_selected));
+ }
+ else if (pos == LLTabContainer::BOTTOM)
+ {
+ tuple->mButton->setImageUnselected(static_cast<LLUIImage*>(params.tab_bottom_image_unselected));
+ tuple->mButton->setImageSelected(static_cast<LLUIImage*>(params.tab_bottom_image_selected));
+ }
+ else if (pos == LLTabContainer::LEFT)
+ {
+ tuple->mButton->setImageUnselected(static_cast<LLUIImage*>(params.tab_left_image_unselected));
+ tuple->mButton->setImageSelected(static_cast<LLUIImage*>(params.tab_left_image_selected));
+ }
+ }
+}
+
+void LLTabContainer::addTabPanel(const TabPanelParams& panel)
{
+ LLPanel* child = panel.panel();
+ const std::string& label = panel.label.isProvided()
+ ? panel.label()
+ : panel.panel()->getLabel();
+ BOOL select = panel.select_tab();
+ S32 indent = panel.indent();
+ BOOL placeholder = panel.is_placeholder;
+ eInsertionPoint insertion_point = panel.insert_at();
+
+ static LLUICachedControl<S32> tabcntrv_pad ("UITabCntrvPad", 0);
+ static LLUICachedControl<S32> tabcntr_button_panel_overlap ("UITabCntrButtonPanelOverlap", 0);
+ static LLUICachedControl<S32> tab_padding ("UITabPadding", 0);
if (child->getParent() == this)
{
// already a child of mine
return;
}
- const LLFontGL* font = LLResMgr::getInstance()->getRes( mIsVertical ? LLFONT_SANSSERIF : LLFONT_SANSSERIF_SMALL );
// Store the original label for possible xml export.
child->setLabel(label);
@@ -700,28 +826,37 @@ void LLTabContainer::addTabPanel(LLPanel* child,
S32 button_width = mMinTabWidth;
if (!mIsVertical)
{
- button_width = llclamp(font->getWidth(trimmed_label) + TAB_PADDING, mMinTabWidth, mMaxTabWidth);
+ button_width = llclamp(mFont->getWidth(trimmed_label) + tab_padding, mMinTabWidth, mMaxTabWidth);
}
// Tab panel
S32 tab_panel_top;
S32 tab_panel_bottom;
- if( getTabPosition() == LLTabContainer::TOP )
+ if (!getTabsHidden())
{
- S32 tab_height = mIsVertical ? BTN_HEIGHT : TABCNTR_TAB_HEIGHT;
- tab_panel_top = getRect().getHeight() - getTopBorderHeight() - (tab_height - TABCNTR_BUTTON_PANEL_OVERLAP);
- tab_panel_bottom = LLPANEL_BORDER_WIDTH;
+ if( getTabPosition() == LLTabContainer::TOP )
+ {
+ S32 tab_height = mIsVertical ? BTN_HEIGHT : mTabHeight;
+ tab_panel_top = getRect().getHeight() - getTopBorderHeight() - (tab_height - tabcntr_button_panel_overlap);
+ tab_panel_bottom = LLPANEL_BORDER_WIDTH;
+ }
+ else
+ {
+ tab_panel_top = getRect().getHeight() - getTopBorderHeight();
+ tab_panel_bottom = (mTabHeight - tabcntr_button_panel_overlap); // Run to the edge, covering up the border
+ }
}
else
{
- tab_panel_top = getRect().getHeight() - getTopBorderHeight();
- tab_panel_bottom = (TABCNTR_TAB_HEIGHT - TABCNTR_BUTTON_PANEL_OVERLAP); // Run to the edge, covering up the border
+ //Scip tab button space if they are invisible(EXT - 576)
+ tab_panel_top = getRect().getHeight();
+ tab_panel_bottom = LLPANEL_BORDER_WIDTH;
}
-
+
LLRect tab_panel_rect;
- if (mIsVertical)
+ if (!getTabsHidden() && mIsVertical)
{
- tab_panel_rect = LLRect(mMinTabWidth + (LLPANEL_BORDER_WIDTH * 2) + TABCNTRV_PAD,
+ tab_panel_rect = LLRect(mMinTabWidth + (LLPANEL_BORDER_WIDTH * 2) + tabcntrv_pad,
getRect().getHeight() - LLPANEL_BORDER_WIDTH,
getRect().getWidth() - LLPANEL_BORDER_WIDTH,
LLPANEL_BORDER_WIDTH);
@@ -744,28 +879,28 @@ void LLTabContainer::addTabPanel(LLPanel* child,
// Tab button
LLRect btn_rect; // Note: btn_rect.mLeft is just a dummy. Will be updated in draw().
- std::string tab_img;
- std::string tab_selected_img;
+ LLUIImage* tab_img = NULL;
+ LLUIImage* tab_selected_img = NULL;
S32 tab_fudge = 1; // To make new tab art look better, nudge buttons up 1 pel
if (mIsVertical)
{
- btn_rect.setLeftTopAndSize(TABCNTRV_PAD + LLPANEL_BORDER_WIDTH + 2, // JC - Fudge factor
- (getRect().getHeight() - getTopBorderHeight() - LLPANEL_BORDER_WIDTH - 1) - ((BTN_HEIGHT + TABCNTRV_PAD) * getTabCount()),
+ btn_rect.setLeftTopAndSize(tabcntrv_pad + LLPANEL_BORDER_WIDTH + 2, // JC - Fudge factor
+ (getRect().getHeight() - getTopBorderHeight() - LLPANEL_BORDER_WIDTH - 1) - ((BTN_HEIGHT + tabcntrv_pad) * getTabCount()),
mMinTabWidth,
BTN_HEIGHT);
}
else if( getTabPosition() == LLTabContainer::TOP )
{
- btn_rect.setLeftTopAndSize( 0, getRect().getHeight() - getTopBorderHeight() + tab_fudge, button_width, TABCNTR_TAB_HEIGHT );
- tab_img = "tab_top_blue.tga";
- tab_selected_img = "tab_top_selected_blue.tga";
+ btn_rect.setLeftTopAndSize( 0, getRect().getHeight() - getTopBorderHeight() + tab_fudge, button_width, mTabHeight);
+ tab_img = mMiddleTabParams.tab_top_image_unselected;
+ tab_selected_img = mMiddleTabParams.tab_top_image_selected;
}
else
{
- btn_rect.setOriginAndSize( 0, 0 + tab_fudge, button_width, TABCNTR_TAB_HEIGHT );
- tab_img = "tab_bottom_blue.tga";
- tab_selected_img = "tab_bottom_selected_blue.tga";
+ btn_rect.setOriginAndSize( 0, 0 + tab_fudge, button_width, mTabHeight);
+ tab_img = mMiddleTabParams.tab_bottom_image_unselected;
+ tab_selected_img = mMiddleTabParams.tab_bottom_image_selected;
}
LLTextBox* textbox = NULL;
@@ -773,89 +908,132 @@ void LLTabContainer::addTabPanel(LLPanel* child,
if (placeholder)
{
- btn_rect.translate(0, -LLBUTTON_V_PAD-2);
- textbox = new LLTextBox(trimmed_label, btn_rect, trimmed_label, font);
+ btn_rect.translate(0, -6); // *TODO: make configurable
+ LLTextBox::Params params;
+ params.name(trimmed_label);
+ params.rect(btn_rect);
+ params.initial_value(trimmed_label);
+ params.font(mFont);
+ textbox = LLUICtrlFactory::create<LLTextBox> (params);
- btn = new LLButton(LLStringUtil::null, LLRect(0,0,0,0));
+ LLButton::Params p;
+ p.name("placeholder");
+ btn = LLUICtrlFactory::create<LLButton>(p);
}
else
{
if (mIsVertical)
{
- btn = new LLButton(std::string("vert tab button"),
- btn_rect,
- LLStringUtil::null,
- LLStringUtil::null,
- LLStringUtil::null,
- &LLTabContainer::onTabBtn, NULL,
- font,
- trimmed_label, trimmed_label);
- btn->setImages(std::string("tab_left.tga"), std::string("tab_left_selected.tga"));
- btn->setScaleImage(TRUE);
- btn->setHAlign(LLFontGL::LEFT);
- btn->setFollows(FOLLOWS_TOP | FOLLOWS_LEFT);
- btn->setTabStop(FALSE);
+ LLButton::Params p;
+ p.name(std::string("vert tab button"));
+ p.rect(btn_rect);
+ p.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT);
+ p.click_callback.function(boost::bind(&LLTabContainer::onTabBtn, this, _2, child));
+ p.font(mFont);
+ p.label(trimmed_label);
+ p.image_unselected(mMiddleTabParams.tab_left_image_unselected);
+ p.image_selected(mMiddleTabParams.tab_left_image_selected);
+ p.scale_image(true);
+ p.font_halign = mFontHalign;
+ p.pad_bottom( mLabelPadBottom );
+ p.tab_stop(false);
+ p.label_shadow(false);
if (indent)
{
- btn->setLeftHPad(indent);
+ p.pad_left(indent);
}
+ btn = LLUICtrlFactory::create<LLButton>(p);
}
else
{
- std::string tooltip = trimmed_label;
- tooltip += "\nAlt-Left arrow for previous tab";
- tooltip += "\nAlt-Right arrow for next tab";
-
- btn = new LLButton(std::string(child->getName()) + " tab",
- btn_rect,
- LLStringUtil::null, LLStringUtil::null, LLStringUtil::null,
- &LLTabContainer::onTabBtn, NULL, // set userdata below
- font,
- trimmed_label, trimmed_label );
- btn->setVisible( FALSE );
- btn->setToolTip( tooltip );
- btn->setScaleImage(TRUE);
- btn->setImages(tab_img, tab_selected_img);
-
+ LLButton::Params p;
+ p.name(std::string(child->getName()) + " tab");
+ p.rect(btn_rect);
+ p.click_callback.function(boost::bind(&LLTabContainer::onTabBtn, this, _2, child));
+ p.font(mFont);
+ p.label(trimmed_label);
+ p.visible(false);
+ p.scale_image(true);
+ p.image_unselected(tab_img);
+ p.image_selected(tab_selected_img);
+ p.tab_stop(false);
+ p.label_shadow(false);
// Try to squeeze in a bit more text
- btn->setLeftHPad( 4 );
- btn->setRightHPad( 2 );
- btn->setHAlign(LLFontGL::LEFT);
- btn->setTabStop(FALSE);
+ p.pad_left( mLabelPadLeft );
+ p.pad_right(2);
+ p.pad_bottom( mLabelPadBottom );
+ p.font_halign = mFontHalign;
+ p.follows.flags = FOLLOWS_LEFT;
+ p.follows.flags = FOLLOWS_LEFT;
+
if (indent)
{
- btn->setLeftHPad(indent);
+ p.pad_left(indent);
}
if( getTabPosition() == TOP )
{
- btn->setFollowsTop();
+ p.follows.flags = p.follows.flags() | FOLLOWS_TOP;
}
else
{
- btn->setFollowsBottom();
+ p.follows.flags = p.follows.flags() | FOLLOWS_BOTTOM;
}
+
+++ btn = LLUICtrlFactory::create<LLButton>(p);
}
}
- LLTabTuple* tuple = new LLTabTuple( this, child, btn, on_tab_clicked, userdata, textbox );
+ LLTabTuple* tuple = new LLTabTuple( this, child, btn, textbox );
insertTuple( tuple, insertion_point );
- if (textbox)
+ // if new tab was added as a first or last tab, update button image
+ // and update button image of any tab it may have affected
+ if (tuple == mTabList.front())
+ {
+ update_images(tuple, mFirstTabParams, getTabPosition());
+
+ if (mTabList.size() == 2)
+ {
+ update_images(mTabList[1], mLastTabParams, getTabPosition());
+ }
+ else if (mTabList.size() > 2)
+ {
+ update_images(mTabList[1], mMiddleTabParams, getTabPosition());
+ }
+ }
+ else if (tuple == mTabList.back())
{
- textbox->setSaveToXML(false);
- addChild( textbox, 0 );
+ update_images(tuple, mLastTabParams, getTabPosition());
+
+ if (mTabList.size() > 2)
+ {
+ update_images(mTabList[mTabList.size()-2], mMiddleTabParams, getTabPosition());
+ }
}
- if (btn)
+
+ //Don't add button and textbox if tab buttons are invisible(EXT - 576)
+ if (!getTabsHidden())
{
- btn->setSaveToXML(false);
- btn->setCallbackUserData( tuple );
- addChild( btn, 0 );
+ if (textbox)
+ {
+ addChild( textbox, 0 );
+ }
+ if (btn)
+ {
+ addChild( btn, 0 );
+ }
}
+
if (child)
{
- addChild(child, 1);
+ LLUICtrl::addChild(child, 1);
}
+
+ sendChildToFront(mPrevArrowBtn);
+ sendChildToFront(mNextArrowBtn);
+ sendChildToFront(mJumpPrevArrowBtn);
+ sendChildToFront(mJumpNextArrowBtn);
if( select )
{
@@ -867,11 +1045,12 @@ void LLTabContainer::addTabPanel(LLPanel* child,
void LLTabContainer::addPlaceholder(LLPanel* child, const std::string& label)
{
- addTabPanel(child, label, FALSE, NULL, NULL, 0, TRUE);
+ addTabPanel(TabPanelParams().panel(child).label(label).is_placeholder(true));
}
void LLTabContainer::removeTabPanel(LLPanel* child)
{
+ static LLUICachedControl<S32> tabcntrv_pad ("UITabCntrvPad", 0);
if (mIsVertical)
{
// Fix-up button sizes
@@ -880,8 +1059,8 @@ void LLTabContainer::removeTabPanel(LLPanel* child)
{
LLTabTuple* tuple = *iter;
LLRect rect;
- rect.setLeftTopAndSize(TABCNTRV_PAD + LLPANEL_BORDER_WIDTH + 2, // JC - Fudge factor
- (getRect().getHeight() - LLPANEL_BORDER_WIDTH - 1) - ((BTN_HEIGHT + TABCNTRV_PAD) * (tab_count)),
+ rect.setLeftTopAndSize(tabcntrv_pad + LLPANEL_BORDER_WIDTH + 2, // JC - Fudge factor
+ (getRect().getHeight() - LLPANEL_BORDER_WIDTH - 1) - ((BTN_HEIGHT + tabcntrv_pad) * (tab_count)),
mMinTabWidth,
BTN_HEIGHT);
if (tuple->mPlaceholderText)
@@ -917,7 +1096,17 @@ void LLTabContainer::removeTabPanel(LLPanel* child)
LLTabTuple* tuple = *iter;
if( tuple->mTabPanel == child )
{
- removeChild( tuple->mButton );
+ // update tab button images if removing the first or last tab
+ if ((tuple == mTabList.front()) && (mTabList.size() > 1))
+ {
+ update_images(mTabList[1], mFirstTabParams, getTabPosition());
+ }
+ else if ((tuple == mTabList.back()) && (mTabList.size() > 2))
+ {
+ update_images(mTabList[mTabList.size()-2], mLastTabParams, getTabPosition());
+ }
+
+ removeChild( tuple->mButton );
delete tuple->mButton;
removeChild( tuple->mTabPanel );
@@ -1044,7 +1233,7 @@ S32 LLTabContainer::getPanelIndexByTitle(const std::string& title)
return -1;
}
-LLPanel *LLTabContainer::getPanelByName(const std::string& name)
+LLPanel* LLTabContainer::getPanelByName(const std::string& name)
{
for (S32 index = 0 ; index < (S32)mTabList.size(); index++)
{
@@ -1138,42 +1327,36 @@ BOOL LLTabContainer::selectTabPanel(LLPanel* child)
BOOL LLTabContainer::selectTab(S32 which)
{
- if (which >= getTabCount()) return FALSE;
- if (which < 0) return FALSE;
-
- //if( gFocusMgr.childHasKeyboardFocus( this ) )
- //{
- // gFocusMgr.setKeyboardFocus( NULL );
- //}
+ if (which >= getTabCount() || which < 0)
+ return FALSE;
LLTabTuple* selected_tuple = getTab(which);
if (!selected_tuple)
{
return FALSE;
}
+
+ LLSD cbdata;
+ if (selected_tuple->mTabPanel)
+ cbdata = selected_tuple->mTabPanel->getName();
- if (!selected_tuple->mPrecommitChangeCallback)
+ BOOL res = FALSE;
+ if( !mValidateSignal || (*mValidateSignal)( this, cbdata ) )
{
- return setTab(which);
+ res = setTab(which);
+ if (res && mCommitSignal)
+ {
+ (*mCommitSignal)(this, cbdata);
+ }
}
-
- mNextTabIdx = which;
- selected_tuple->mPrecommitChangeCallback(selected_tuple->mUserData, false);
- return TRUE;
+
+ return res;
}
+// private
BOOL LLTabContainer::setTab(S32 which)
{
- if (which == -1)
- {
- if (mNextTabIdx == -1)
- {
- return FALSE;
- }
- which = mNextTabIdx;
- mNextTabIdx = -1;
- }
-
+ static LLUICachedControl<S32> tabcntr_arrow_btn_size ("UITabCntrArrowBtnSize", 0);
LLTabTuple* selected_tuple = getTab(which);
if (!selected_tuple)
{
@@ -1196,7 +1379,7 @@ BOOL LLTabContainer::setTab(S32 which)
// RN: this limits tab-stops to active button only, which would require arrow keys to switch tabs
tuple->mButton->setTabStop( is_selected );
- if( is_selected && (mIsVertical || (getMaxScrollPos() > 0)))
+ if (is_selected)
{
// Make sure selected tab is within scroll region
if (mIsVertical)
@@ -1212,7 +1395,7 @@ BOOL LLTabContainer::setTab(S32 which)
is_visible = FALSE;
}
}
- else
+ else if (getMaxScrollPos() > 0)
{
if( i < getScrollPos() )
{
@@ -1220,7 +1403,7 @@ BOOL LLTabContainer::setTab(S32 which)
}
else
{
- S32 available_width_with_arrows = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1);
+ S32 available_width_with_arrows = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + tabcntr_arrow_btn_size + tabcntr_arrow_btn_size + 1);
S32 running_tab_width = tuple->mButton->getRect().getWidth();
S32 j = i - 1;
S32 min_scroll_pos = i;
@@ -1243,13 +1426,13 @@ BOOL LLTabContainer::setTab(S32 which)
}
is_visible = TRUE;
}
+ else
+ {
+ is_visible = TRUE;
+ }
}
i++;
}
- if( selected_tuple->mOnChangeCallback )
- {
- selected_tuple->mOnChangeCallback( selected_tuple->mUserData, false );
- }
}
if (mIsVertical && getCurrentPanelIndex() >= 0)
{
@@ -1295,6 +1478,7 @@ void LLTabContainer::setTabPanelFlashing(LLPanel* child, BOOL state )
void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const LLColor4& color)
{
+ static LLUICachedControl<S32> tab_padding ("UITabPadding", 0);
LLTabTuple* tuple = getTabByPanel(child);
if( tuple )
{
@@ -1302,7 +1486,6 @@ void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const L
if (!mIsVertical)
{
- const LLFontGL* fontp = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL );
// remove current width from total tab strip width
mTotalTabWidth -= tuple->mButton->getRect().getWidth();
@@ -1313,7 +1496,38 @@ void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const L
tuple->mPadding = image_overlay_width;
tuple->mButton->setRightHPad(6);
- tuple->mButton->reshape(llclamp(fontp->getWidth(tuple->mButton->getLabelSelected()) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth),
+ tuple->mButton->reshape(llclamp(mFont->getWidth(tuple->mButton->getLabelSelected()) + tab_padding + tuple->mPadding, mMinTabWidth, mMaxTabWidth),
+ tuple->mButton->getRect().getHeight());
+ // add back in button width to total tab strip width
+ mTotalTabWidth += tuple->mButton->getRect().getWidth();
+
+ // tabs have changed size, might need to scroll to see current tab
+ updateMaxScrollPos();
+ }
+ }
+}
+
+void LLTabContainer::setTabImage(LLPanel* child, const LLUUID& image_id, const LLColor4& color)
+{
+ static LLUICachedControl<S32> tab_padding ("UITabPadding", 0);
+ LLTabTuple* tuple = getTabByPanel(child);
+ if( tuple )
+ {
+ tuple->mButton->setImageOverlay(image_id, LLFontGL::RIGHT, color);
+
+ if (!mIsVertical)
+ {
+ // remove current width from total tab strip width
+ mTotalTabWidth -= tuple->mButton->getRect().getWidth();
+
+ S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
+ tuple->mButton->getImageOverlay()->getImage()->getWidth(0) :
+ 0;
+
+ tuple->mPadding = image_overlay_width;
+
+ tuple->mButton->setRightHPad(6);
+ tuple->mButton->reshape(llclamp(mFont->getWidth(tuple->mButton->getLabelSelected()) + tab_padding + tuple->mPadding, mMinTabWidth, mMaxTabWidth),
tuple->mButton->getRect().getHeight());
// add back in button width to total tab strip width
mTotalTabWidth += tuple->mButton->getRect().getWidth();
@@ -1352,33 +1566,6 @@ S32 LLTabContainer::getTopBorderHeight() const
return mTopBorderHeight;
}
-void LLTabContainer::setTabChangeCallback(LLPanel* tab, void (*on_tab_clicked)(void*, bool))
-{
- LLTabTuple* tuplep = getTabByPanel(tab);
- if (tuplep)
- {
- tuplep->mOnChangeCallback = on_tab_clicked;
- }
-}
-
-void LLTabContainer::setTabPrecommitChangeCallback(LLPanel* tab, void (*on_precommit)(void*, bool))
-{
- LLTabTuple* tuplep = getTabByPanel(tab);
- if (tuplep)
- {
- tuplep->mPrecommitChangeCallback = on_precommit;
- }
-}
-
-void LLTabContainer::setTabUserData(LLPanel* tab, void* userdata)
-{
- LLTabTuple* tuplep = getTabByPanel(tab);
- if (tuplep)
- {
- tuplep->mUserData = userdata;
- }
-}
-
void LLTabContainer::setRightTabBtnOffset(S32 offset)
{
mNextArrowBtn->translate( -offset - mRightTabBtnOffset, 0 );
@@ -1388,13 +1575,15 @@ void LLTabContainer::setRightTabBtnOffset(S32 offset)
void LLTabContainer::setPanelTitle(S32 index, const std::string& title)
{
+ static LLUICachedControl<S32> tab_padding ("UITabPadding", 0);
+
if (index >= 0 && index < getTabCount())
{
LLTabTuple* tuple = getTab(index);
LLButton* tab_button = tuple->mButton;
- const LLFontGL* fontp = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL );
+ const LLFontGL* fontp = LLFontGL::getFontSansSerifSmall();
mTotalTabWidth -= tab_button->getRect().getWidth();
- tab_button->reshape(llclamp(fontp->getWidth(title) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth), tab_button->getRect().getHeight());
+ tab_button->reshape(llclamp(fontp->getWidth(title) + tab_padding + tuple->mPadding, mMinTabWidth, mMaxTabWidth), tab_button->getRect().getHeight());
mTotalTabWidth += tab_button->getRect().getWidth();
tab_button->setLabelSelected(title);
tab_button->setLabelUnselected(title);
@@ -1403,182 +1592,60 @@ void LLTabContainer::setPanelTitle(S32 index, const std::string& title)
}
-// static
-void LLTabContainer::onTabBtn( void* userdata )
+void LLTabContainer::onTabBtn( const LLSD& data, LLPanel* panel )
{
- LLTabTuple* tuple = (LLTabTuple*) userdata;
- LLTabContainer* self = tuple->mTabContainer;
- self->selectTabPanel( tuple->mTabPanel );
+ LLTabTuple* tuple = getTabByPanel(panel);
+ selectTabPanel( panel );
tuple->mTabPanel->setFocus(TRUE);
}
-// static
-void LLTabContainer::onCloseBtn( void* userdata )
-{
- LLTabContainer* self = (LLTabContainer*) userdata;
- if( self->mCloseCallback )
- {
- self->mCloseCallback( self->mCallbackUserdata );
- }
-}
-
-// static
-void LLTabContainer::onNextBtn( void* userdata )
+void LLTabContainer::onNextBtn( const LLSD& data )
{
- // Scroll tabs to the left
- LLTabContainer* self = (LLTabContainer*) userdata;
- if (!self->mScrolled)
+ if (!mScrolled)
{
- self->scrollNext();
+ scrollNext();
}
- self->mScrolled = FALSE;
+ mScrolled = FALSE;
}
-// static
-void LLTabContainer::onNextBtnHeld( void* userdata )
+void LLTabContainer::onNextBtnHeld( const LLSD& data )
{
- LLTabContainer* self = (LLTabContainer*) userdata;
- if (self->mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME)
+ if (mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME)
{
- self->mScrollTimer.reset();
- self->scrollNext();
- self->mScrolled = TRUE;
+ mScrollTimer.reset();
+ scrollNext();
+ mScrolled = TRUE;
}
}
-// static
-void LLTabContainer::onPrevBtn( void* userdata )
+void LLTabContainer::onPrevBtn( const LLSD& data )
{
- LLTabContainer* self = (LLTabContainer*) userdata;
- if (!self->mScrolled)
+ if (!mScrolled)
{
- self->scrollPrev();
+ scrollPrev();
}
- self->mScrolled = FALSE;
+ mScrolled = FALSE;
}
-// static
-void LLTabContainer::onJumpFirstBtn( void* userdata )
+void LLTabContainer::onJumpFirstBtn( const LLSD& data )
{
- LLTabContainer* self = (LLTabContainer*) userdata;
- self->mScrollPos = 0;
+ mScrollPos = 0;
}
-// static
-void LLTabContainer::onJumpLastBtn( void* userdata )
+void LLTabContainer::onJumpLastBtn( const LLSD& data )
{
- LLTabContainer* self = (LLTabContainer*) userdata;
- self->mScrollPos = self->mMaxScrollPos;
+ mScrollPos = mMaxScrollPos;
}
-// static
-void LLTabContainer::onPrevBtnHeld( void* userdata )
+void LLTabContainer::onPrevBtnHeld( const LLSD& data )
{
- LLTabContainer* self = (LLTabContainer*) userdata;
- if (self->mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME)
- {
- self->mScrollTimer.reset();
- self->scrollPrev();
- self->mScrolled = TRUE;
- }
-}
-
-// static
-LLView* LLTabContainer::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("tab_container");
- node->getAttributeString("name", name);
-
- // Figure out if we are creating a vertical or horizontal tab container.
- bool is_vertical = false;
- LLTabContainer::TabPosition tab_position = LLTabContainer::TOP;
- if (node->hasAttribute("tab_position"))
- {
- std::string tab_position_string;
- node->getAttributeString("tab_position", tab_position_string);
- LLStringUtil::toLower(tab_position_string);
-
- if ("top" == tab_position_string)
- {
- tab_position = LLTabContainer::TOP;
- is_vertical = false;
- }
- else if ("bottom" == tab_position_string)
- {
- tab_position = LLTabContainer::BOTTOM;
- is_vertical = false;
- }
- else if ("left" == tab_position_string)
- {
- is_vertical = true;
- }
- }
- BOOL border = FALSE;
- node->getAttributeBOOL("border", border);
-
- LLTabContainer* tab_container = new LLTabContainer(name, LLRect::null, tab_position, border, is_vertical);
-
- S32 tab_min_width = tab_container->mMinTabWidth;
- if (node->hasAttribute("tab_width"))
- {
- node->getAttributeS32("tab_width", tab_min_width);
- }
- else if( node->hasAttribute("tab_min_width"))
- {
- node->getAttributeS32("tab_min_width", tab_min_width);
- }
-
- S32 tab_max_width = tab_container->mMaxTabWidth;
- if (node->hasAttribute("tab_max_width"))
- {
- node->getAttributeS32("tab_max_width", tab_max_width);
- }
-
- tab_container->setMinTabWidth(tab_min_width);
- tab_container->setMaxTabWidth(tab_max_width);
-
- BOOL hidden(tab_container->getTabsHidden());
- node->getAttributeBOOL("hide_tabs", hidden);
- tab_container->setTabsHidden(hidden);
-
- tab_container->setPanelParameters(node, parent);
-
- if (LLFloater::getFloaterHost())
+ if (mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME)
{
- LLFloater::getFloaterHost()->setTabContainer(tab_container);
- }
-
- //parent->addChild(tab_container);
-
- // Add all tab panels.
- LLXMLNodePtr child;
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
- {
- LLView *control = factory->createCtrlWidget(tab_container, child);
- if (control && control->isPanel())
- {
- LLPanel* panelp = (LLPanel*)control;
- std::string label;
- child->getAttributeString("label", label);
- if (label.empty())
- {
- label = panelp->getLabel();
- }
- BOOL placeholder = FALSE;
- child->getAttributeBOOL("placeholder", placeholder);
- tab_container->addTabPanel(panelp, label, false,
- NULL, NULL, 0, placeholder);
- }
+ mScrollTimer.reset();
+ scrollPrev();
+ mScrolled = TRUE;
}
-
- tab_container->selectFirstTab();
-
- tab_container->postBuild();
-
- tab_container->initButtons(); // now that we have the correct rect
-
- return tab_container;
}
// private
@@ -1591,99 +1658,105 @@ void LLTabContainer::initButtons()
return; // Don't have a rect yet or already got called
}
- std::string out_id;
- std::string in_id;
-
if (mIsVertical)
{
+ static LLUICachedControl<S32> tabcntrv_arrow_btn_size ("UITabCntrvArrowBtnSize", 0);
// Left and right scroll arrows (for when there are too many tabs to show all at once).
S32 btn_top = getRect().getHeight();
- S32 btn_top_lower = getRect().mBottom+TABCNTRV_ARROW_BTN_SIZE;
+ S32 btn_top_lower = getRect().mBottom+tabcntrv_arrow_btn_size;
LLRect up_arrow_btn_rect;
- up_arrow_btn_rect.setLeftTopAndSize( mMinTabWidth/2 , btn_top, TABCNTRV_ARROW_BTN_SIZE, TABCNTRV_ARROW_BTN_SIZE );
+ up_arrow_btn_rect.setLeftTopAndSize( mMinTabWidth/2 , btn_top, tabcntrv_arrow_btn_size, tabcntrv_arrow_btn_size );
LLRect down_arrow_btn_rect;
- down_arrow_btn_rect.setLeftTopAndSize( mMinTabWidth/2 , btn_top_lower, TABCNTRV_ARROW_BTN_SIZE, TABCNTRV_ARROW_BTN_SIZE );
-
- out_id = "UIImgBtnScrollUpOutUUID";
- in_id = "UIImgBtnScrollUpInUUID";
- mPrevArrowBtn = new LLButton(std::string("Up Arrow"), up_arrow_btn_rect,
- out_id, in_id, LLStringUtil::null,
- &onPrevBtn, this, NULL );
- mPrevArrowBtn->setFollowsTop();
- mPrevArrowBtn->setFollowsLeft();
-
- out_id = "UIImgBtnScrollDownOutUUID";
- in_id = "UIImgBtnScrollDownInUUID";
- mNextArrowBtn = new LLButton(std::string("Down Arrow"), down_arrow_btn_rect,
- out_id, in_id, LLStringUtil::null,
- &onNextBtn, this, NULL );
- mNextArrowBtn->setFollowsBottom();
- mNextArrowBtn->setFollowsLeft();
+ down_arrow_btn_rect.setLeftTopAndSize( mMinTabWidth/2 , btn_top_lower, tabcntrv_arrow_btn_size, tabcntrv_arrow_btn_size );
+
+ LLButton::Params prev_btn_params;
+ prev_btn_params.name(std::string("Up Arrow"));
+ prev_btn_params.rect(up_arrow_btn_rect);
+ prev_btn_params.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT);
+ prev_btn_params.image_unselected.name("scrollbutton_up_out_blue.tga");
+ prev_btn_params.image_selected.name("scrollbutton_up_in_blue.tga");
+ prev_btn_params.click_callback.function(boost::bind(&LLTabContainer::onPrevBtn, this, _2));
+ mPrevArrowBtn = LLUICtrlFactory::create<LLButton>(prev_btn_params);
+
+ LLButton::Params next_btn_params;
+ next_btn_params.name(std::string("Down Arrow"));
+ next_btn_params.rect(down_arrow_btn_rect);
+ next_btn_params.follows.flags(FOLLOWS_BOTTOM | FOLLOWS_LEFT);
+ next_btn_params.image_unselected.name("scrollbutton_down_out_blue.tga");
+ next_btn_params.image_selected.name("scrollbutton_down_in_blue.tga");
+ next_btn_params.click_callback.function(boost::bind(&LLTabContainer::onNextBtn, this, _2));
+ mNextArrowBtn = LLUICtrlFactory::create<LLButton>(next_btn_params);
}
else // Horizontal
{
+ static LLUICachedControl<S32> tabcntr_arrow_btn_size ("UITabCntrArrowBtnSize", 0);
S32 arrow_fudge = 1; // match new art better
- // tabs on bottom reserve room for resize handle (just in case)
- if (getTabPosition() == BOTTOM)
- {
- mRightTabBtnOffset = RESIZE_HANDLE_WIDTH;
- }
-
// Left and right scroll arrows (for when there are too many tabs to show all at once).
- S32 btn_top = (getTabPosition() == TOP ) ? getRect().getHeight() - getTopBorderHeight() : TABCNTR_ARROW_BTN_SIZE + 1;
+ S32 btn_top = (getTabPosition() == TOP ) ? getRect().getHeight() - getTopBorderHeight() : tabcntr_arrow_btn_size + 1;
LLRect left_arrow_btn_rect;
- left_arrow_btn_rect.setLeftTopAndSize( LLPANEL_BORDER_WIDTH+1+TABCNTR_ARROW_BTN_SIZE, btn_top + arrow_fudge, TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE );
+ left_arrow_btn_rect.setLeftTopAndSize( LLPANEL_BORDER_WIDTH+1+tabcntr_arrow_btn_size, btn_top + arrow_fudge, tabcntr_arrow_btn_size, mTabHeight );
LLRect jump_left_arrow_btn_rect;
- jump_left_arrow_btn_rect.setLeftTopAndSize( LLPANEL_BORDER_WIDTH+1, btn_top + arrow_fudge, TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE );
+ jump_left_arrow_btn_rect.setLeftTopAndSize( LLPANEL_BORDER_WIDTH+1, btn_top + arrow_fudge, tabcntr_arrow_btn_size, mTabHeight );
- S32 right_pad = TABCNTR_ARROW_BTN_SIZE + LLPANEL_BORDER_WIDTH + 1;
+ S32 right_pad = tabcntr_arrow_btn_size + LLPANEL_BORDER_WIDTH + 1;
LLRect right_arrow_btn_rect;
- right_arrow_btn_rect.setLeftTopAndSize( getRect().getWidth() - mRightTabBtnOffset - right_pad - TABCNTR_ARROW_BTN_SIZE,
+ right_arrow_btn_rect.setLeftTopAndSize( getRect().getWidth() - mRightTabBtnOffset - right_pad - tabcntr_arrow_btn_size,
btn_top + arrow_fudge,
- TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE );
+ tabcntr_arrow_btn_size, mTabHeight );
LLRect jump_right_arrow_btn_rect;
jump_right_arrow_btn_rect.setLeftTopAndSize( getRect().getWidth() - mRightTabBtnOffset - right_pad,
btn_top + arrow_fudge,
- TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE );
-
- out_id = "UIImgBtnJumpLeftOutUUID";
- in_id = "UIImgBtnJumpLeftInUUID";
- mJumpPrevArrowBtn = new LLButton(std::string("Jump Left Arrow"), jump_left_arrow_btn_rect,
- out_id, in_id, LLStringUtil::null,
- &LLTabContainer::onJumpFirstBtn, this, LLFontGL::getFontSansSerif() );
- mJumpPrevArrowBtn->setFollowsLeft();
-
- out_id = "UIImgBtnScrollLeftOutUUID";
- in_id = "UIImgBtnScrollLeftInUUID";
- mPrevArrowBtn = new LLButton(std::string("Left Arrow"), left_arrow_btn_rect,
- out_id, in_id, LLStringUtil::null,
- &LLTabContainer::onPrevBtn, this, LLFontGL::getFontSansSerif() );
- mPrevArrowBtn->setHeldDownCallback(onPrevBtnHeld);
- mPrevArrowBtn->setFollowsLeft();
-
- out_id = "UIImgBtnJumpRightOutUUID";
- in_id = "UIImgBtnJumpRightInUUID";
- mJumpNextArrowBtn = new LLButton(std::string("Jump Right Arrow"), jump_right_arrow_btn_rect,
- out_id, in_id, LLStringUtil::null,
- &LLTabContainer::onJumpLastBtn, this,
- LLFontGL::getFontSansSerif());
- mJumpNextArrowBtn->setFollowsRight();
-
- out_id = "UIImgBtnScrollRightOutUUID";
- in_id = "UIImgBtnScrollRightInUUID";
- mNextArrowBtn = new LLButton(std::string("Right Arrow"), right_arrow_btn_rect,
- out_id, in_id, LLStringUtil::null,
- &LLTabContainer::onNextBtn, this,
- LLFontGL::getFontSansSerif());
- mNextArrowBtn->setFollowsRight();
+ tabcntr_arrow_btn_size, mTabHeight );
+
+ LLButton::Params p;
+ p.name(std::string("Jump Left Arrow"));
+ p.image_unselected.name("jump_left_out.tga");
+ p.image_selected.name("jump_left_in.tga");
+ p.click_callback.function(boost::bind(&LLTabContainer::onJumpFirstBtn, this, _2));
+ p.rect(jump_left_arrow_btn_rect);
+ p.follows.flags(FOLLOWS_LEFT);
+
+ mJumpPrevArrowBtn = LLUICtrlFactory::create<LLButton>(p);
+
+ p = LLButton::Params();
+ p.name(std::string("Left Arrow"));
+ p.rect(left_arrow_btn_rect);
+ p.follows.flags(FOLLOWS_LEFT);
+ p.image_unselected.name("scrollbutton_left_out_blue.tga");
+ p.image_selected.name("scrollbutton_left_in_blue.tga");
+ p.click_callback.function(boost::bind(&LLTabContainer::onPrevBtn, this, _2));
+ p.mouse_held_callback.function(boost::bind(&LLTabContainer::onPrevBtnHeld, this, _2));
+
+ mPrevArrowBtn = LLUICtrlFactory::create<LLButton>(p);
+
+ p = LLButton::Params();
+ p.name(std::string("Jump Right Arrow"));
+ p.rect(jump_right_arrow_btn_rect);
+ p.follows.flags(FOLLOWS_RIGHT);
+ p.image_unselected.name("jump_right_out.tga");
+ p.image_selected.name("jump_right_in.tga");
+ p.click_callback.function(boost::bind(&LLTabContainer::onJumpLastBtn, this, _2));
+
+ mJumpNextArrowBtn = LLUICtrlFactory::create<LLButton>(p);
+
+ p = LLButton::Params();
+ p.name(std::string("Right Arrow"));
+ p.rect(right_arrow_btn_rect);
+ p.follows.flags(FOLLOWS_RIGHT);
+ p.image_unselected.name("scrollbutton_right_out_blue.tga");
+ p.image_selected.name("scrollbutton_right_in_blue.tga");
+ p.click_callback.function(boost::bind(&LLTabContainer::onNextBtn, this, _2));
+ p.mouse_held_callback.function(boost::bind(&LLTabContainer::onNextBtnHeld, this, _2));
+
+ mNextArrowBtn = LLUICtrlFactory::create<LLButton>(p);
if( getTabPosition() == TOP )
{
@@ -1701,26 +1774,20 @@ void LLTabContainer::initButtons()
}
}
- mPrevArrowBtn->setHeldDownCallback(onPrevBtnHeld);
- mPrevArrowBtn->setSaveToXML(false);
mPrevArrowBtn->setTabStop(FALSE);
addChild(mPrevArrowBtn);
- mNextArrowBtn->setHeldDownCallback(onNextBtnHeld);
- mNextArrowBtn->setSaveToXML(false);
mNextArrowBtn->setTabStop(FALSE);
addChild(mNextArrowBtn);
if (mJumpPrevArrowBtn)
{
- mJumpPrevArrowBtn->setSaveToXML(false);
mJumpPrevArrowBtn->setTabStop(FALSE);
addChild(mJumpPrevArrowBtn);
}
if (mJumpNextArrowBtn)
{
- mJumpNextArrowBtn->setSaveToXML(false);
mJumpNextArrowBtn->setTabStop(FALSE);
addChild(mJumpNextArrowBtn);
}
@@ -1729,7 +1796,17 @@ void LLTabContainer::initButtons()
setDefaultTabGroup(1);
}
-LLTabContainer::LLTabTuple* LLTabContainer::getTabByPanel(LLPanel* child)
+//this is a work around for the current LLPanel::initFromParams hack
+//so that it doesn't overwrite the default tab group.
+//will be removed when LLPanel is fixed soon.
+void LLTabContainer::initFromParams(const LLPanel::Params& p)
+{
+ LLPanel::initFromParams(p);
+
+ setDefaultTabGroup(1);
+}
+
+LLTabTuple* LLTabContainer::getTabByPanel(LLPanel* child)
{
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
@@ -1775,14 +1852,16 @@ void LLTabContainer::insertTuple(LLTabTuple * tuple, eInsertionPoint insertion_p
void LLTabContainer::updateMaxScrollPos()
{
+ static LLUICachedControl<S32> tabcntrv_pad ("UITabCntrvPad", 0);
BOOL no_scroll = TRUE;
if (mIsVertical)
{
- S32 tab_total_height = (BTN_HEIGHT + TABCNTRV_PAD) * getTabCount();
+ S32 tab_total_height = (BTN_HEIGHT + tabcntrv_pad) * getTabCount();
S32 available_height = getRect().getHeight() - getTopBorderHeight();
if( tab_total_height > available_height )
{
- S32 available_height_with_arrows = getRect().getHeight() - 2*(TABCNTRV_ARROW_BTN_SIZE + 3*TABCNTRV_PAD);
+ static LLUICachedControl<S32> tabcntrv_arrow_btn_size ("UITabCntrvArrowBtnSize", 0);
+ S32 available_height_with_arrows = getRect().getHeight() - 2*(tabcntrv_arrow_btn_size + 3*tabcntrv_pad);
S32 additional_needed = tab_total_height - available_height_with_arrows;
setMaxScrollPos((S32) ceil(additional_needed / float(BTN_HEIGHT) ) );
no_scroll = FALSE;
@@ -1790,16 +1869,19 @@ void LLTabContainer::updateMaxScrollPos()
}
else
{
+ static LLUICachedControl<S32> tabcntr_tab_h_pad ("UITabCntrTabHPad", 0);
+ static LLUICachedControl<S32> tabcntr_arrow_btn_size ("UITabCntrArrowBtnSize", 0);
+ static LLUICachedControl<S32> tabcntr_tab_partial_width ("UITabCntrTabPartialWidth", 0);
S32 tab_space = 0;
S32 available_space = 0;
tab_space = mTotalTabWidth;
- available_space = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_TAB_H_PAD);
+ available_space = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + tabcntr_tab_h_pad);
if( tab_space > available_space )
{
- S32 available_width_with_arrows = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1);
+ S32 available_width_with_arrows = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + tabcntr_arrow_btn_size + tabcntr_arrow_btn_size + 1);
// subtract off reserved portion on left
- available_width_with_arrows -= TABCNTR_TAB_PARTIAL_WIDTH;
+ available_width_with_arrows -= tabcntr_tab_partial_width;
S32 running_tab_width = 0;
setMaxScrollPos(getTabCount());
@@ -1830,12 +1912,11 @@ void LLTabContainer::updateMaxScrollPos()
void LLTabContainer::commitHoveredButton(S32 x, S32 y)
{
- if (hasMouseCapture())
+ if (!getTabsHidden() && hasMouseCapture())
{
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
LLTabTuple* tuple = *iter;
- tuple->mButton->setVisible( TRUE );
S32 local_x = x - tuple->mButton->getRect().mLeft;
S32 local_y = y - tuple->mButton->getRect().mBottom;
if (tuple->mButton->pointInView(local_x, local_y) && tuple->mButton->getEnabled() && !tuple->mTabPanel->getVisible())
@@ -1845,6 +1926,3 @@ void LLTabContainer::commitHoveredButton(S32 x, S32 y)
}
}
}
-
-
-
diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h
index 8117cdee9b..33c49e0d6f 100644
--- a/indra/llui/lltabcontainer.h
+++ b/indra/llui/lltabcontainer.h
@@ -37,7 +37,7 @@
#include "lltextbox.h"
#include "llframetimer.h"
-extern const S32 TABCNTR_HEADER_HEIGHT;
+class LLTabTuple;
class LLTabContainer : public LLPanel
{
@@ -56,8 +56,50 @@ public:
RIGHT_OF_CURRENT
} eInsertionPoint;
- LLTabContainer( const std::string& name, const LLRect& rect, TabPosition pos,
- BOOL bordered, BOOL is_vertical);
+ struct TabPositions : public LLInitParam::TypeValuesHelper<LLTabContainer::TabPosition, TabPositions>
+ {
+ static void declareValues();
+ };
+
+ struct TabParams : public LLInitParam::Block<TabParams>
+ {
+ Optional<LLUIImage*> tab_top_image_unselected,
+ tab_top_image_selected,
+ tab_bottom_image_unselected,
+ tab_bottom_image_selected,
+ tab_left_image_unselected,
+ tab_left_image_selected;
+ TabParams();
+ };
+
+ struct Params
+ : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ Optional<TabPosition, TabPositions> tab_position;
+ Optional<S32> tab_width,
+ tab_min_width,
+ tab_max_width,
+ tab_height,
+ label_pad_bottom,
+ label_pad_left;
+
+ Optional<bool> hide_tabs;
+ Optional<S32> tab_padding_right;
+
+ Optional<TabParams> first_tab,
+ middle_tab,
+ last_tab;
+
+ Params();
+ };
+
+protected:
+ LLTabContainer(const Params&);
+ friend class LLUICtrlFactory;
+
+public:
+ //LLTabContainer( const std::string& name, const LLRect& rect, TabPosition pos,
+ // BOOL bordered, BOOL is_vertical);
/*virtual*/ ~LLTabContainer();
@@ -69,22 +111,40 @@ public:
/*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask );
/*virtual*/ BOOL handleHover( S32 x, S32 y, MASK mask );
/*virtual*/ BOOL handleMouseUp( S32 x, S32 y, MASK mask );
- /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect );
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
/*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType type, void* cargo_data,
EAcceptance* accept, std::string& tooltip);
- /*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const;
- /*virtual*/ LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const;
-
- void addTabPanel(LLPanel* child,
- const std::string& label,
- BOOL select = FALSE,
- void (*on_tab_clicked)(void*, bool) = NULL,
- void* userdata = NULL,
- S32 indent = 0,
- BOOL placeholder = FALSE,
- eInsertionPoint insertion_point = END);
+ /*virtual*/ LLView* getChildView(const std::string& name, BOOL recurse = TRUE) const;
+ /*virtual*/ LLView* findChildView(const std::string& name, BOOL recurse = TRUE) const;
+ /*virtual*/ void initFromParams(const LLPanel::Params& p);
+ /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0);
+ /*virtual*/ BOOL postBuild();
+
+ struct TabPanelParams : public LLInitParam::Block<TabPanelParams>
+ {
+ Mandatory<LLPanel*> panel;
+
+ Optional<std::string> label;
+ Optional<bool> select_tab,
+ is_placeholder;
+ Optional<S32> indent;
+ Optional<eInsertionPoint> insert_at;
+ Optional<void*> user_data;
+
+ TabPanelParams()
+ : panel("panel", NULL),
+ label("label"),
+ select_tab("select_tab"),
+ is_placeholder("is_placeholder"),
+ indent("indent"),
+ insert_at("insert_at", END)
+ {}
+ };
+
+ void addTabPanel(LLPanel* panel);
+ void addTabPanel(const TabPanelParams& panel);
void addPlaceholder(LLPanel* child, const std::string& label);
void removeTabPanel( LLPanel* child );
void lockTabs(S32 num_tabs = 0);
@@ -108,21 +168,17 @@ public:
BOOL selectTabPanel( LLPanel* child );
BOOL selectTab(S32 which);
BOOL selectTabByName(const std::string& title);
- BOOL setTab(S32 which);
BOOL getTabPanelFlashing(LLPanel* child);
void setTabPanelFlashing(LLPanel* child, BOOL state);
void setTabImage(LLPanel* child, std::string img_name, const LLColor4& color = LLColor4::white);
+ void setTabImage(LLPanel* child, const LLUUID& img_id, const LLColor4& color = LLColor4::white);
void setTitle( const std::string& title );
const std::string getPanelTitle(S32 index);
void setTopBorderHeight(S32 height);
S32 getTopBorderHeight() const;
- void setTabChangeCallback(LLPanel* tab, void (*on_tab_clicked)(void*,bool));
- void setTabPrecommitChangeCallback(LLPanel* tab, void (*on_precommit)(void*, bool));
- void setTabUserData(LLPanel* tab, void* userdata);
-
void setRightTabBtnOffset( S32 offset );
void setPanelTitle(S32 index, const std::string& title);
@@ -134,51 +190,20 @@ public:
void startDragAndDropDelayTimer() { mDragAndDropDelayTimer.start(); }
- static void onCloseBtn(void* userdata);
- static void onTabBtn(void* userdata);
- static void onNextBtn(void* userdata);
- static void onNextBtnHeld(void* userdata);
- static void onPrevBtn(void* userdata);
- static void onPrevBtnHeld(void* userdata);
- static void onJumpFirstBtn( void* userdata );
- static void onJumpLastBtn( void* userdata );
-
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
+ void onTabBtn( const LLSD& data, LLPanel* panel );
+ void onNextBtn(const LLSD& data);
+ void onNextBtnHeld(const LLSD& data);
+ void onPrevBtn(const LLSD& data);
+ void onPrevBtnHeld(const LLSD& data);
+ void onJumpFirstBtn( const LLSD& data );
+ void onJumpLastBtn( const LLSD& data );
private:
- // Structure used to map tab buttons to and from tab panels
- struct LLTabTuple
- {
- LLTabTuple( LLTabContainer* c, LLPanel* p, LLButton* b,
- void (*cb)(void*,bool), void* userdata, LLTextBox* placeholder = NULL,
- void (*pcb)(void*,bool) = NULL)
- :
- mTabContainer(c),
- mTabPanel(p),
- mButton(b),
- mOnChangeCallback( cb ),
- mPrecommitChangeCallback( pcb ),
- mUserData( userdata ),
- mOldState(FALSE),
- mPlaceholderText(placeholder),
- mPadding(0)
- {}
-
- LLTabContainer* mTabContainer;
- LLPanel* mTabPanel;
- LLButton* mButton;
- void (*mOnChangeCallback)(void*, bool);
- void (*mPrecommitChangeCallback)(void*,bool); // Precommit callback gets called before tab is changed and
- // can prevent it from being changed. onChangeCallback is called
- // immediately after tab is actually changed - Nyx
- void* mUserData;
- BOOL mOldState;
- LLTextBox* mPlaceholderText;
- S32 mPadding;
- };
void initButtons();
+ BOOL setTab(S32 which);
+
LLTabTuple* getTab(S32 index) { return mTabList[index]; }
LLTabTuple* getTabByPanel(LLPanel* child);
void insertTuple(LLTabTuple * tuple, eInsertionPoint insertion_point);
@@ -201,13 +226,15 @@ private:
void updateMaxScrollPos();
void commitHoveredButton(S32 x, S32 y);
+ // updates tab button images given the tuple, tab position and the corresponding params
+ void update_images(LLTabTuple* tuple, TabParams params, LLTabContainer::TabPosition pos);
+
// Variables
typedef std::vector<LLTabTuple*> tuple_list_t;
tuple_list_t mTabList;
S32 mCurrentTabIdx;
- S32 mNextTabIdx;
BOOL mTabsHidden;
BOOL mScrolled;
@@ -216,9 +243,6 @@ private:
S32 mScrollPosPixels;
S32 mMaxScrollPos;
- void (*mCloseCallback)(void*);
- void* mCallbackUserdata;
-
LLTextBox* mTitleBox;
S32 mTopBorderHeight;
@@ -238,9 +262,21 @@ private:
S32 mMaxTabWidth;
S32 mTotalTabWidth;
+ S32 mTabHeight;
+
+ // Padding under the text labels of tab buttons
+ S32 mLabelPadBottom;
+ // Padding to the left of text labels of tab buttons
+ S32 mLabelPadLeft;
LLFrameTimer mDragAndDropDelayTimer;
-};
+
+ LLFontGL::HAlign mFontHalign;
+ const LLFontGL* mFont;
+ TabParams mFirstTabParams;
+ TabParams mMiddleTabParams;
+ TabParams mLastTabParams;
+};
#endif // LL_TABCONTAINER_H
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
new file mode 100644
index 0000000000..47db990a37
--- /dev/null
+++ b/indra/llui/lltextbase.cpp
@@ -0,0 +1,2640 @@
+/**
+ * @file lltextbase.cpp
+ * @author Martin Reddy
+ * @brief The base class of text box/editor, providing Url handling support
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltextbase.h"
+
+#include "lllocalcliprect.h"
+#include "llmenugl.h"
+#include "llscrollcontainer.h"
+#include "llstl.h"
+#include "lltextparser.h"
+#include "lltooltip.h"
+#include "lluictrl.h"
+#include "llurlaction.h"
+#include "llurlregistry.h"
+#include "llview.h"
+#include "llwindow.h"
+#include <boost/bind.hpp>
+
+const F32 CURSOR_FLASH_DELAY = 1.0f; // in seconds
+const S32 CURSOR_THICKNESS = 2;
+
+LLTextBase::line_info::line_info(S32 index_start, S32 index_end, LLRect rect, S32 line_num)
+: mDocIndexStart(index_start),
+ mDocIndexEnd(index_end),
+ mRect(rect),
+ mLineNum(line_num)
+{}
+
+bool LLTextBase::compare_segment_end::operator()(const LLTextSegmentPtr& a, const LLTextSegmentPtr& b) const
+{
+ // sort empty spans (e.g. 11-11) after previous non-empty spans (e.g. 5-11)
+ if (a->getEnd() == b->getEnd())
+ {
+ return a->getStart() < b->getStart();
+ }
+ return a->getEnd() < b->getEnd();
+}
+
+
+// helper functors
+struct LLTextBase::compare_bottom
+{
+ bool operator()(const S32& a, const LLTextBase::line_info& b) const
+ {
+ return a > b.mRect.mBottom; // bottom of a is higher than bottom of b
+ }
+
+ bool operator()(const LLTextBase::line_info& a, const S32& b) const
+ {
+ return a.mRect.mBottom > b; // bottom of a is higher than bottom of b
+ }
+
+ bool operator()(const LLTextBase::line_info& a, const LLTextBase::line_info& b) const
+ {
+ return a.mRect.mBottom > b.mRect.mBottom; // bottom of a is higher than bottom of b
+ }
+
+};
+
+// helper functors
+struct LLTextBase::compare_top
+{
+ bool operator()(const S32& a, const LLTextBase::line_info& b) const
+ {
+ return a > b.mRect.mTop; // top of a is higher than top of b
+ }
+
+ bool operator()(const LLTextBase::line_info& a, const S32& b) const
+ {
+ return a.mRect.mTop > b; // top of a is higher than top of b
+ }
+
+ bool operator()(const LLTextBase::line_info& a, const LLTextBase::line_info& b) const
+ {
+ return a.mRect.mTop > b.mRect.mTop; // top of a is higher than top of b
+ }
+};
+
+struct LLTextBase::line_end_compare
+{
+ bool operator()(const S32& pos, const LLTextBase::line_info& info) const
+ {
+ return (pos < info.mDocIndexEnd);
+ }
+
+ bool operator()(const LLTextBase::line_info& info, const S32& pos) const
+ {
+ return (info.mDocIndexEnd < pos);
+ }
+
+ bool operator()(const LLTextBase::line_info& a, const LLTextBase::line_info& b) const
+ {
+ return (a.mDocIndexEnd < b.mDocIndexEnd);
+ }
+
+};
+
+//////////////////////////////////////////////////////////////////////////
+//
+// LLTextBase
+//
+
+// register LLTextBase::Params under name "textbase"
+static LLWidgetNameRegistry::StaticRegistrar sRegisterTextBaseParams(&typeid(LLTextBase::Params), "textbase");
+
+LLTextBase::LineSpacingParams::LineSpacingParams()
+: multiple("multiple", 1.f),
+ pixels("pixels", 0)
+{
+}
+
+
+LLTextBase::Params::Params()
+: cursor_color("cursor_color"),
+ text_color("text_color"),
+ text_readonly_color("text_readonly_color"),
+ bg_visible("bg_visible", false),
+ border_visible("border_visible", false),
+ bg_readonly_color("bg_readonly_color"),
+ bg_writeable_color("bg_writeable_color"),
+ bg_focus_color("bg_focus_color"),
+ allow_scroll("allow_scroll", true),
+ track_end("track_end", false),
+ read_only("read_only", false),
+ v_pad("v_pad", 0),
+ h_pad("h_pad", 0),
+ clip_partial("clip_partial", true),
+ line_spacing("line_spacing"),
+ max_text_length("max_length", 255),
+ font_shadow("font_shadow"),
+ wrap("wrap"),
+ use_ellipses("use_ellipses", false),
+ allow_html("allow_html", false),
+ parse_highlights("parse_highlights", false)
+{
+ addSynonym(track_end, "track_bottom");
+ addSynonym(wrap, "word_wrap");
+}
+
+
+LLTextBase::LLTextBase(const LLTextBase::Params &p)
+: LLUICtrl(p, LLTextViewModelPtr(new LLTextViewModel)),
+ mURLClickSignal(),
+ mMaxTextByteLength( p.max_text_length ),
+ mDefaultFont(p.font),
+ mFontShadow(p.font_shadow),
+ mPopupMenu(NULL),
+ mReadOnly(p.read_only),
+ mCursorColor(p.cursor_color),
+ mFgColor(p.text_color),
+ mBorderVisible( p.border_visible ),
+ mReadOnlyFgColor(p.text_readonly_color),
+ mWriteableBgColor(p.bg_writeable_color),
+ mReadOnlyBgColor(p.bg_readonly_color),
+ mFocusBgColor(p.bg_focus_color),
+ mReflowNeeded(FALSE),
+ mCursorPos( 0 ),
+ mScrollNeeded(FALSE),
+ mDesiredXPixel(-1),
+ mHPad(p.h_pad),
+ mVPad(p.v_pad),
+ mHAlign(p.font_halign),
+ mLineSpacingMult(p.line_spacing.multiple),
+ mLineSpacingPixels(p.line_spacing.pixels),
+ mClipPartial(p.clip_partial && !p.allow_scroll),
+ mTrackEnd( p.track_end ),
+ mScrollIndex(-1),
+ mSelectionStart( 0 ),
+ mSelectionEnd( 0 ),
+ mIsSelecting( FALSE ),
+ mWordWrap(p.wrap),
+ mUseEllipses( p.use_ellipses ),
+ mParseHTML(p.allow_html),
+ mParseHighlights(p.parse_highlights),
+ mBGVisible(p.bg_visible),
+ mScroller(NULL)
+{
+ if(p.allow_scroll)
+ {
+ LLScrollContainer::Params scroll_params;
+ scroll_params.name = "text scroller";
+ scroll_params.rect = getLocalRect();
+ scroll_params.follows.flags = FOLLOWS_ALL;
+ scroll_params.is_opaque = false;
+ scroll_params.mouse_opaque = false;
+ scroll_params.min_auto_scroll_rate = 200;
+ scroll_params.max_auto_scroll_rate = 800;
+ scroll_params.border_visible = p.border_visible;
+ mScroller = LLUICtrlFactory::create<LLScrollContainer>(scroll_params);
+ addChild(mScroller);
+ }
+
+ LLView::Params view_params;
+ view_params.name = "text_contents";
+ view_params.rect = LLRect(0, 500, 500, 0);
+ view_params.mouse_opaque = false;
+
+ mDocumentView = LLUICtrlFactory::create<LLView>(view_params);
+ if (mScroller)
+ {
+ mScroller->addChild(mDocumentView);
+ }
+ else
+ {
+ addChild(mDocumentView);
+ }
+
+ createDefaultSegment();
+
+ updateRects();
+}
+
+LLTextBase::~LLTextBase()
+{
+ delete mPopupMenu;
+ clearSegments();
+}
+
+void LLTextBase::initFromParams(const LLTextBase::Params& p)
+{
+ LLUICtrl::initFromParams(p);
+ resetDirty(); // Update saved text state
+ updateSegments();
+
+ // HACK: work around enabled == readonly design bug -- RN
+ // setEnabled will modify our read only status, so do this after
+ // LLTextBase::initFromParams
+ if (p.read_only.isProvided())
+ {
+ mReadOnly = p.read_only;
+ }
+
+ // HACK: text editors always need to be enabled so that we can scroll
+ LLView::setEnabled(true);
+}
+
+bool LLTextBase::truncate()
+{
+ BOOL did_truncate = FALSE;
+
+ // First rough check - if we're less than 1/4th the size, we're OK
+ if (getLength() >= S32(mMaxTextByteLength / 4))
+ {
+ // Have to check actual byte size
+ LLWString text(getWText());
+ S32 utf8_byte_size = wstring_utf8_length(text);
+ if ( utf8_byte_size > mMaxTextByteLength )
+ {
+ // Truncate safely in UTF-8
+ std::string temp_utf8_text = wstring_to_utf8str(text);
+ temp_utf8_text = utf8str_truncate( temp_utf8_text, mMaxTextByteLength );
+ LLWString text = utf8str_to_wstring( temp_utf8_text );
+ // remove extra bit of current string, to preserve formatting, etc.
+ removeStringNoUndo(text.size(), getWText().size() - text.size());
+ did_truncate = TRUE;
+ }
+ }
+
+ return did_truncate;
+}
+
+LLStyle::Params LLTextBase::getDefaultStyle()
+{
+ return LLStyle::Params().color(mFgColor.get()).readonly_color(mReadOnlyFgColor.get()).font(mDefaultFont).drop_shadow(mFontShadow);
+}
+
+void LLTextBase::onValueChange(S32 start, S32 end)
+{
+}
+
+
+// Draws the black box behind the selected text
+void LLTextBase::drawSelectionBackground()
+{
+ // Draw selection even if we don't have keyboard focus for search/replace
+ if( hasSelection() && !mLineInfoList.empty())
+ {
+ LLWString text = getWText();
+ std::vector<LLRect> selection_rects;
+
+ S32 selection_left = llmin( mSelectionStart, mSelectionEnd );
+ S32 selection_right = llmax( mSelectionStart, mSelectionEnd );
+ LLRect selection_rect = mVisibleTextRect;
+
+ // Skip through the lines we aren't drawing.
+ LLRect content_display_rect = getVisibleDocumentRect();
+
+ // binary search for line that starts before top of visible buffer
+ line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mTop, compare_bottom());
+ line_list_t::const_iterator end_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mBottom, compare_top());
+
+ bool done = false;
+
+ // Find the coordinates of the selected area
+ for (;line_iter != end_iter && !done; ++line_iter)
+ {
+ // is selection visible on this line?
+ if (line_iter->mDocIndexEnd > selection_left && line_iter->mDocIndexStart < selection_right)
+ {
+ segment_set_t::iterator segment_iter;
+ S32 segment_offset;
+ getSegmentAndOffset(line_iter->mDocIndexStart, &segment_iter, &segment_offset);
+
+ LLRect selection_rect;
+ selection_rect.mLeft = line_iter->mRect.mLeft;
+ selection_rect.mRight = line_iter->mRect.mLeft;
+ selection_rect.mBottom = line_iter->mRect.mBottom;
+ selection_rect.mTop = line_iter->mRect.mTop;
+
+ for(;segment_iter != mSegments.end(); ++segment_iter, segment_offset = 0)
+ {
+ LLTextSegmentPtr segmentp = *segment_iter;
+
+ S32 segment_line_start = segmentp->getStart() + segment_offset;
+ S32 segment_line_end = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd);
+
+ S32 segment_width = 0;
+ S32 segment_height = 0;
+
+ // if selection after beginning of segment
+ if(selection_left >= segment_line_start)
+ {
+ S32 num_chars = llmin(selection_left, segment_line_end) - segment_line_start;
+ segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height);
+ selection_rect.mLeft += segment_width;
+ }
+
+ // if selection spans end of current segment...
+ if (selection_right > segment_line_end)
+ {
+ // extend selection slightly beyond end of line
+ // to indicate selection of newline character (use "n" character to determine width)
+ S32 num_chars = segment_line_end - segment_line_start;
+ segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height);
+ selection_rect.mRight += segment_width;
+ }
+ // else if selection ends on current segment...
+ else
+ {
+ S32 num_chars = selection_right - segment_line_start;
+ segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height);
+ selection_rect.mRight += segment_width;
+
+ break;
+ }
+ }
+ selection_rects.push_back(selection_rect);
+ }
+ }
+
+ // Draw the selection box (we're using a box instead of reversing the colors on the selected text).
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ const LLColor4& color = mReadOnly ? mReadOnlyFgColor.get() : mFgColor.get();
+ F32 alpha = hasFocus() ? 0.7f : 0.3f;
+ alpha *= getDrawContext().mAlpha;
+ LLColor4 selection_color(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], alpha);
+
+ for (std::vector<LLRect>::iterator rect_it = selection_rects.begin();
+ rect_it != selection_rects.end();
+ ++rect_it)
+ {
+ LLRect selection_rect = *rect_it;
+ selection_rect.translate(mVisibleTextRect.mLeft - content_display_rect.mLeft, mVisibleTextRect.mBottom - content_display_rect.mBottom);
+ gl_rect_2d(selection_rect, selection_color);
+ }
+ }
+}
+
+void LLTextBase::drawCursor()
+{
+ F32 alpha = getDrawContext().mAlpha;
+
+ if( hasFocus()
+ && gFocusMgr.getAppHasFocus()
+ && !mReadOnly)
+ {
+ LLWString wtext = getWText();
+ const llwchar* text = wtext.c_str();
+
+ LLRect cursor_rect = getLocalRectFromDocIndex(mCursorPos);
+ cursor_rect.translate(-1, 0);
+ segment_set_t::iterator seg_it = getSegIterContaining(mCursorPos);
+
+ // take style from last segment
+ LLTextSegmentPtr segmentp;
+
+ if (seg_it != mSegments.end())
+ {
+ segmentp = *seg_it;
+ }
+ else
+ {
+ //segmentp = mSegments.back();
+ return;
+ }
+
+ // Draw the cursor
+ // (Flash the cursor every half second starting a fixed time after the last keystroke)
+ F32 elapsed = mCursorBlinkTimer.getElapsedTimeF32();
+ if( (elapsed < CURSOR_FLASH_DELAY ) || (S32(elapsed * 2) & 1) )
+ {
+
+ if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection())
+ {
+ S32 segment_width = 0;
+ S32 segment_height = 0;
+ segmentp->getDimensions(mCursorPos - segmentp->getStart(), 1, segment_width, segment_height);
+ S32 width = llmax(CURSOR_THICKNESS, segment_width);
+ cursor_rect.mRight = cursor_rect.mLeft + width;
+ }
+ else
+ {
+ cursor_rect.mRight = cursor_rect.mLeft + CURSOR_THICKNESS;
+ }
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ LLColor4 cursor_color = mCursorColor.get() % alpha;
+ gGL.color4fv( cursor_color.mV );
+
+ gl_rect_2d(cursor_rect);
+
+ if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection() && text[mCursorPos] != '\n')
+ {
+ LLColor4 text_color;
+ const LLFontGL* fontp;
+ if (segmentp)
+ {
+ text_color = segmentp->getColor();
+ fontp = segmentp->getStyle()->getFont();
+ }
+ else if (mReadOnly)
+ {
+ text_color = mReadOnlyFgColor.get();
+ fontp = mDefaultFont;
+ }
+ else
+ {
+ text_color = mFgColor.get();
+ fontp = mDefaultFont;
+ }
+ fontp->render(text, mCursorPos, cursor_rect.mLeft, cursor_rect.mTop,
+ LLColor4(1.f - text_color.mV[VRED], 1.f - text_color.mV[VGREEN], 1.f - text_color.mV[VBLUE], alpha),
+ LLFontGL::LEFT, LLFontGL::TOP,
+ LLFontGL::NORMAL,
+ LLFontGL::NO_SHADOW,
+ 1);
+ }
+
+ // Make sure the IME is in the right place
+ LLRect screen_pos = calcScreenRect();
+ LLCoordGL ime_pos( screen_pos.mLeft + llfloor(cursor_rect.mLeft), screen_pos.mBottom + llfloor(cursor_rect.mTop) );
+
+ ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]);
+ ime_pos.mY = (S32) (ime_pos.mY * LLUI::sGLScaleFactor.mV[VY]);
+ getWindow()->setLanguageTextInput( ime_pos );
+ }
+ }
+}
+
+void LLTextBase::drawText()
+{
+ LLWString text = getWText();
+ const S32 text_len = getLength();
+ if( text_len <= 0 )
+ {
+ return;
+ }
+ S32 selection_left = -1;
+ S32 selection_right = -1;
+ // Draw selection even if we don't have keyboard focus for search/replace
+ if( hasSelection())
+ {
+ selection_left = llmin( mSelectionStart, mSelectionEnd );
+ selection_right = llmax( mSelectionStart, mSelectionEnd );
+ }
+
+ LLRect scrolled_view_rect = getVisibleDocumentRect();
+ std::pair<S32, S32> line_range = getVisibleLines(mClipPartial);
+ S32 first_line = line_range.first;
+ S32 last_line = line_range.second;
+ if (first_line >= last_line)
+ {
+ return;
+ }
+
+ S32 line_start = getLineStart(first_line);
+ // find first text segment that spans top of visible portion of text buffer
+ segment_set_t::iterator seg_iter = getSegIterContaining(line_start);
+ if (seg_iter == mSegments.end())
+ {
+ return;
+ }
+
+ LLTextSegmentPtr cur_segment = *seg_iter;
+
+ for (S32 cur_line = first_line; cur_line < last_line; cur_line++)
+ {
+ S32 next_line = cur_line + 1;
+ line_info& line = mLineInfoList[cur_line];
+
+ S32 next_start = -1;
+ S32 line_end = text_len;
+
+ if (next_line < getLineCount())
+ {
+ next_start = getLineStart(next_line);
+ line_end = next_start;
+ }
+
+ LLRect text_rect(line.mRect.mLeft + mVisibleTextRect.mLeft - scrolled_view_rect.mLeft,
+ line.mRect.mTop - scrolled_view_rect.mBottom + mVisibleTextRect.mBottom,
+ llmin(mDocumentView->getRect().getWidth(), line.mRect.mRight) - scrolled_view_rect.mLeft,
+ line.mRect.mBottom - scrolled_view_rect.mBottom + mVisibleTextRect.mBottom);
+
+ // draw a single line of text
+ S32 seg_start = line_start;
+ while( seg_start < line_end )
+ {
+ while( cur_segment->getEnd() <= seg_start )
+ {
+ seg_iter++;
+ if (seg_iter == mSegments.end())
+ {
+ llwarns << "Ran off the segmentation end!" << llendl;
+
+ return;
+ }
+ cur_segment = *seg_iter;
+ }
+
+ S32 clipped_end = llmin( line_end, cur_segment->getEnd() ) - cur_segment->getStart();
+
+ if (mUseEllipses // using ellipses
+ && clipped_end == line_end // last segment on line
+ && next_line == last_line // this is the last visible line
+ && last_line < (S32)mLineInfoList.size()) // and there is more text to display
+ {
+ // more lines of text to go, but we can't fit them
+ // so shrink text rect to force ellipses
+ text_rect.mRight -= 2;
+ }
+
+ text_rect.mLeft = (S32)(cur_segment->draw(seg_start - cur_segment->getStart(), clipped_end, selection_left, selection_right, text_rect));
+
+ seg_start = clipped_end + cur_segment->getStart();
+ }
+
+ line_start = next_start;
+ }
+}
+
+///////////////////////////////////////////////////////////////////
+// Returns change in number of characters in mWText
+
+S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::segment_vec_t* segments )
+{
+ LLWString text(getWText());
+ S32 old_len = text.length(); // length() returns character length
+ S32 insert_len = wstr.length();
+
+ pos = getEditableIndex(pos, true);
+
+ segment_set_t::iterator seg_iter = getSegIterContaining(pos);
+
+ LLTextSegmentPtr default_segment;
+
+ LLTextSegmentPtr segmentp;
+ if (seg_iter != mSegments.end())
+ {
+ segmentp = *seg_iter;
+ }
+ else
+ {
+ //segmentp = mSegments.back();
+ return pos;
+ }
+
+ if (segmentp->canEdit())
+ {
+ segmentp->setEnd(segmentp->getEnd() + insert_len);
+ if (seg_iter != mSegments.end())
+ {
+ ++seg_iter;
+ }
+ }
+ else
+ {
+ // create default editable segment to hold new text
+ default_segment = new LLNormalTextSegment( new LLStyle(getDefaultStyle()), pos, pos + insert_len, *this);
+ }
+
+ // shift remaining segments to right
+ for(;seg_iter != mSegments.end(); ++seg_iter)
+ {
+ LLTextSegmentPtr segmentp = *seg_iter;
+ segmentp->setStart(segmentp->getStart() + insert_len);
+ segmentp->setEnd(segmentp->getEnd() + insert_len);
+ }
+
+ // insert new segments
+ if (segments)
+ {
+ if (default_segment.notNull())
+ {
+ // potentially overwritten by segments passed in
+ insertSegment(default_segment);
+ }
+ for (segment_vec_t::iterator seg_iter = segments->begin();
+ seg_iter != segments->end();
+ ++seg_iter)
+ {
+ LLTextSegment* segmentp = *seg_iter;
+ insertSegment(segmentp);
+ }
+ }
+
+ text.insert(pos, wstr);
+ getViewModel()->setDisplay(text);
+
+ if ( truncate() )
+ {
+ insert_len = getLength() - old_len;
+ }
+
+ onValueChange(pos, pos + insert_len);
+ needsReflow();
+
+ return insert_len;
+}
+
+S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length)
+{
+ LLWString text(getWText());
+ segment_set_t::iterator seg_iter = getSegIterContaining(pos);
+ while(seg_iter != mSegments.end())
+ {
+ LLTextSegmentPtr segmentp = *seg_iter;
+ S32 end = pos + length;
+ if (segmentp->getStart() < pos)
+ {
+ // deleting from middle of segment
+ if (segmentp->getEnd() > end)
+ {
+ segmentp->setEnd(segmentp->getEnd() - length);
+ }
+ // truncating segment
+ else
+ {
+ segmentp->setEnd(pos);
+ }
+ }
+ else if (segmentp->getStart() < end)
+ {
+ // deleting entire segment
+ if (segmentp->getEnd() <= end)
+ {
+ // remove segment
+ segmentp->unlinkFromDocument(this);
+ segment_set_t::iterator seg_to_erase(seg_iter++);
+ mSegments.erase(seg_to_erase);
+ continue;
+ }
+ // deleting head of segment
+ else
+ {
+ segmentp->setStart(pos);
+ segmentp->setEnd(segmentp->getEnd() - length);
+ }
+ }
+ else
+ {
+ // shifting segments backward to fill deleted portion
+ segmentp->setStart(segmentp->getStart() - length);
+ segmentp->setEnd(segmentp->getEnd() - length);
+ }
+ ++seg_iter;
+ }
+
+ text.erase(pos, length);
+ getViewModel()->setDisplay(text);
+
+ // recreate default segment in case we erased everything
+ createDefaultSegment();
+
+ onValueChange(pos, pos);
+ needsReflow();
+
+ return -length; // This will be wrong if someone calls removeStringNoUndo with an excessive length
+}
+
+S32 LLTextBase::overwriteCharNoUndo(S32 pos, llwchar wc)
+{
+ if (pos > (S32)getLength())
+ {
+ return 0;
+ }
+ LLWString text(getWText());
+ text[pos] = wc;
+ getViewModel()->setDisplay(text);
+
+ onValueChange(pos, pos + 1);
+ needsReflow();
+
+ return 1;
+}
+
+
+void LLTextBase::createDefaultSegment()
+{
+ // ensures that there is always at least one segment
+ if (mSegments.empty())
+ {
+ LLTextSegmentPtr default_segment = new LLNormalTextSegment( new LLStyle(getDefaultStyle()), 0, getLength() + 1, *this);
+ mSegments.insert(default_segment);
+ default_segment->linkToDocument(this);
+ }
+}
+
+void LLTextBase::insertSegment(LLTextSegmentPtr segment_to_insert)
+{
+ if (segment_to_insert.isNull())
+ {
+ return;
+ }
+
+ segment_set_t::iterator cur_seg_iter = getSegIterContaining(segment_to_insert->getStart());
+
+ if (cur_seg_iter == mSegments.end())
+ {
+ mSegments.insert(segment_to_insert);
+ segment_to_insert->linkToDocument(this);
+ }
+ else
+ {
+ LLTextSegmentPtr cur_segmentp = *cur_seg_iter;
+ if (cur_segmentp->getStart() < segment_to_insert->getStart())
+ {
+ S32 old_segment_end = cur_segmentp->getEnd();
+ // split old at start point for new segment
+ cur_segmentp->setEnd(segment_to_insert->getStart());
+ // advance to next segment
+ // insert remainder of old segment
+ LLTextSegmentPtr remainder_segment = new LLNormalTextSegment( cur_segmentp->getStyle(), segment_to_insert->getStart(), old_segment_end, *this);
+ mSegments.insert(cur_seg_iter, remainder_segment);
+ remainder_segment->linkToDocument(this);
+ // insert new segment before remainder of old segment
+ mSegments.insert(cur_seg_iter, segment_to_insert);
+
+ segment_to_insert->linkToDocument(this);
+ // at this point, there will be two overlapping segments owning the text
+ // associated with the incoming segment
+ }
+ else
+ {
+ mSegments.insert(cur_seg_iter, segment_to_insert);
+ segment_to_insert->linkToDocument(this);
+ }
+
+ // now delete/truncate remaining segments as necessary
+ // cur_seg_iter points to segment before incoming segment
+ while(cur_seg_iter != mSegments.end())
+ {
+ cur_segmentp = *cur_seg_iter;
+ if (cur_segmentp == segment_to_insert)
+ {
+ ++cur_seg_iter;
+ continue;
+ }
+
+ if (cur_segmentp->getStart() >= segment_to_insert->getStart())
+ {
+ if(cur_segmentp->getEnd() <= segment_to_insert->getEnd())
+ {
+ cur_segmentp->unlinkFromDocument(this);
+ // grab copy of iterator to erase, and bump it
+ segment_set_t::iterator seg_to_erase(cur_seg_iter++);
+ mSegments.erase(seg_to_erase);
+ continue;
+ }
+ else
+ {
+ // last overlapping segment, clip to end of incoming segment
+ // and stop traversal
+ cur_segmentp->setStart(segment_to_insert->getEnd());
+ break;
+ }
+ }
+ ++cur_seg_iter;
+ }
+ }
+
+ // layout potentially changed
+ needsReflow();
+}
+
+BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->handleMouseDown(x, y, mask))
+ {
+ return TRUE;
+ }
+
+ return LLUICtrl::handleMouseDown(x, y, mask);
+}
+
+BOOL LLTextBase::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+ LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->handleMouseUp(x, y, mask))
+ {
+ // Did we just click on a link?
+ if (cur_segment->getStyle()
+ && cur_segment->getStyle()->isLink())
+ {
+ // *TODO: send URL here?
+ mURLClickSignal(this, LLSD() );
+ }
+ return TRUE;
+ }
+
+ return LLUICtrl::handleMouseUp(x, y, mask);
+}
+
+BOOL LLTextBase::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
+{
+ LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->handleMiddleMouseDown(x, y, mask))
+ {
+ return TRUE;
+ }
+
+ return LLUICtrl::handleMiddleMouseDown(x, y, mask);
+}
+
+BOOL LLTextBase::handleMiddleMouseUp(S32 x, S32 y, MASK mask)
+{
+ LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->handleMiddleMouseUp(x, y, mask))
+ {
+ return TRUE;
+ }
+
+ return LLUICtrl::handleMiddleMouseUp(x, y, mask);
+}
+
+BOOL LLTextBase::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->handleRightMouseDown(x, y, mask))
+ {
+ return TRUE;
+ }
+
+ return LLUICtrl::handleRightMouseDown(x, y, mask);
+}
+
+BOOL LLTextBase::handleRightMouseUp(S32 x, S32 y, MASK mask)
+{
+ LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->handleRightMouseUp(x, y, mask))
+ {
+ return TRUE;
+ }
+
+ return LLUICtrl::handleRightMouseUp(x, y, mask);
+}
+
+BOOL LLTextBase::handleDoubleClick(S32 x, S32 y, MASK mask)
+{
+ LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->handleDoubleClick(x, y, mask))
+ {
+ return TRUE;
+ }
+
+ return LLUICtrl::handleDoubleClick(x, y, mask);
+}
+
+BOOL LLTextBase::handleHover(S32 x, S32 y, MASK mask)
+{
+ LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->handleHover(x, y, mask))
+ {
+ return TRUE;
+ }
+
+ return LLUICtrl::handleHover(x, y, mask);
+}
+
+BOOL LLTextBase::handleScrollWheel(S32 x, S32 y, S32 clicks)
+{
+ LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->handleScrollWheel(x, y, clicks))
+ {
+ return TRUE;
+ }
+
+ return LLUICtrl::handleScrollWheel(x, y, clicks);
+}
+
+BOOL LLTextBase::handleToolTip(S32 x, S32 y, MASK mask)
+{
+ LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
+ if (cur_segment && cur_segment->handleToolTip(x, y, mask))
+ {
+ return TRUE;
+ }
+
+ return LLUICtrl::handleToolTip(x, y, mask);
+}
+
+
+void LLTextBase::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ if (width != getRect().getWidth() || height != getRect().getHeight())
+ {
+ LLUICtrl::reshape( width, height, called_from_parent );
+
+ // do this first after reshape, because other things depend on
+ // up-to-date mVisibleTextRect
+ updateRects();
+
+ needsReflow();
+ }
+}
+
+void LLTextBase::draw()
+{
+ // reflow if needed, on demand
+ reflow();
+
+ // then update scroll position, as cursor may have moved
+ if (!mReadOnly)
+ {
+ updateScrollFromCursor();
+ }
+
+ LLRect doc_rect;
+ if (mScroller)
+ {
+ mScroller->localRectToOtherView(mScroller->getContentWindowRect(), &doc_rect, this);
+ }
+ else
+ {
+ doc_rect = getLocalRect();
+ }
+
+ if (mBGVisible)
+ {
+ // clip background rect against extents, if we support scrolling
+ LLLocalClipRect clip(doc_rect, mScroller != NULL);
+
+ LLColor4 bg_color = mReadOnly
+ ? mReadOnlyBgColor.get()
+ : hasFocus()
+ ? mFocusBgColor.get()
+ : mWriteableBgColor.get();
+ gl_rect_2d(mVisibleTextRect, bg_color, TRUE);
+ }
+
+ // draw document view
+ LLUICtrl::draw();
+
+ {
+ // only clip if we support scrolling (mScroller != NULL)
+ LLLocalClipRect clip(doc_rect, mScroller != NULL);
+ drawSelectionBackground();
+ drawText();
+ drawCursor();
+ }
+}
+
+
+//virtual
+void LLTextBase::setColor( const LLColor4& c )
+{
+ mFgColor = c;
+ //textsegments have own style property ,
+ //so we have to update it also to apply changes, EXT-4433
+ for(segment_set_t::iterator it = mSegments.begin(); it != mSegments.end(); it++)
+ {
+ LLTextSegment* segment = it->get();
+ if(segment)
+ {
+ segment->setColor(mFgColor);
+ }
+ }
+}
+
+//virtual
+void LLTextBase::setReadOnlyColor(const LLColor4 &c)
+{
+ mReadOnlyFgColor = c;
+}
+
+//virtual
+void LLTextBase::setValue(const LLSD& value )
+{
+ setText(value.asString());
+}
+
+//virtual
+void LLTextBase::deselect()
+{
+ mSelectionStart = 0;
+ mSelectionEnd = 0;
+ mIsSelecting = FALSE;
+}
+
+
+// Sets the scrollbar from the cursor position
+void LLTextBase::updateScrollFromCursor()
+{
+ // Update scroll position even in read-only mode (when there's no cursor displayed)
+ // because startOfDoc()/endOfDoc() modify cursor position. See EXT-736.
+
+ if (!mScrollNeeded || !mScroller)
+ {
+ return;
+ }
+ mScrollNeeded = FALSE;
+
+ // scroll so that the cursor is at the top of the page
+ LLRect scroller_doc_window = getVisibleDocumentRect();
+ LLRect cursor_rect_doc = getLocalRectFromDocIndex(mCursorPos);
+ cursor_rect_doc.translate(scroller_doc_window.mLeft, scroller_doc_window.mBottom);
+ mScroller->scrollToShowRect(cursor_rect_doc, LLRect(0, scroller_doc_window.getHeight() - 5, scroller_doc_window.getWidth(), 5));
+}
+
+S32 LLTextBase::getLeftOffset(S32 width)
+{
+ switch (mHAlign)
+ {
+ case LLFontGL::LEFT:
+ return mHPad;
+ case LLFontGL::HCENTER:
+ return mHPad + (mVisibleTextRect.getWidth() - width - mHPad) / 2;
+ case LLFontGL::RIGHT:
+ return mVisibleTextRect.getWidth() - width;
+ default:
+ return mHPad;
+ }
+}
+
+
+static LLFastTimer::DeclareTimer FTM_TEXT_REFLOW ("Text Reflow");
+void LLTextBase::reflow(S32 start_index)
+{
+ LLFastTimer ft(FTM_TEXT_REFLOW);
+
+ updateSegments();
+
+ while(mReflowNeeded)
+ {
+ mReflowNeeded = false;
+
+ // shrink document to minimum size (visible portion of text widget)
+ // to force inlined widgets with follows set to shrink
+ mDocumentView->reshape(mVisibleTextRect.getWidth(), mDocumentView->getRect().getHeight());
+
+ bool scrolled_to_bottom = mScroller ? mScroller->isAtBottom() : false;
+
+ LLRect old_cursor_rect = getLocalRectFromDocIndex(mCursorPos);
+ bool follow_selection = mVisibleTextRect.overlaps(old_cursor_rect); // cursor is visible
+ old_cursor_rect.translate(-mVisibleTextRect.mLeft, -mVisibleTextRect.mBottom);
+
+ S32 first_line = getFirstVisibleLine();
+
+ // if scroll anchor not on first line, update it to first character of first line
+ if (!mLineInfoList.empty()
+ && (mScrollIndex < mLineInfoList[first_line].mDocIndexStart
+ || mScrollIndex >= mLineInfoList[first_line].mDocIndexEnd))
+ {
+ mScrollIndex = mLineInfoList[first_line].mDocIndexStart;
+ }
+ LLRect first_char_rect = getLocalRectFromDocIndex(mScrollIndex);
+ // subtract off effect of horizontal scrollbar from local position of first char
+ first_char_rect.translate(-mVisibleTextRect.mLeft, -mVisibleTextRect.mBottom);
+
+ S32 cur_top = 0;
+
+ segment_set_t::iterator seg_iter = mSegments.begin();
+ S32 seg_offset = 0;
+ S32 line_start_index = 0;
+ const S32 text_available_width = mVisibleTextRect.getWidth() - mHPad; // reserve room for margin
+ S32 remaining_pixels = text_available_width;
+ LLWString text(getWText());
+ S32 line_count = 0;
+
+ // find and erase line info structs starting at start_index and going to end of document
+ if (!mLineInfoList.empty())
+ {
+ // find first element whose end comes after start_index
+ line_list_t::iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), start_index, line_end_compare());
+ line_start_index = iter->mDocIndexStart;
+ line_count = iter->mLineNum;
+ getSegmentAndOffset(iter->mDocIndexStart, &seg_iter, &seg_offset);
+ mLineInfoList.erase(iter, mLineInfoList.end());
+ }
+
+ S32 line_height = 0;
+
+ while(seg_iter != mSegments.end())
+ {
+ LLTextSegmentPtr segment = *seg_iter;
+
+ // track maximum height of any segment on this line
+ S32 cur_index = segment->getStart() + seg_offset;
+
+ // ask segment how many character fit in remaining space
+ S32 character_count = segment->getNumChars(getWordWrap() ? llmax(0, remaining_pixels) : S32_MAX,
+ seg_offset,
+ cur_index - line_start_index,
+ S32_MAX);
+
+ S32 segment_width, segment_height;
+ bool force_newline = segment->getDimensions(seg_offset, character_count, segment_width, segment_height);
+ // grow line height as necessary based on reported height of this segment
+ line_height = llmax(line_height, segment_height);
+ remaining_pixels -= segment_width;
+ if (remaining_pixels < 0)
+ {
+ // getNumChars() and getDimensions() should return consistent results
+ remaining_pixels = 0;
+ }
+
+ seg_offset += character_count;
+
+ S32 last_segment_char_on_line = segment->getStart() + seg_offset;
+
+ S32 text_actual_width = text_available_width - remaining_pixels;
+ S32 text_left = getLeftOffset(text_actual_width);
+ LLRect line_rect(text_left,
+ cur_top,
+ text_left + text_actual_width,
+ cur_top - line_height);
+
+ // if we didn't finish the current segment...
+ if (last_segment_char_on_line < segment->getEnd())
+ {
+ // add line info and keep going
+ mLineInfoList.push_back(line_info(
+ line_start_index,
+ last_segment_char_on_line,
+ line_rect,
+ line_count));
+
+ line_start_index = segment->getStart() + seg_offset;
+ cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels;
+ remaining_pixels = text_available_width;
+ line_height = 0;
+ }
+ // ...just consumed last segment..
+ else if (++segment_set_t::iterator(seg_iter) == mSegments.end())
+ {
+ mLineInfoList.push_back(line_info(
+ line_start_index,
+ last_segment_char_on_line,
+ line_rect,
+ line_count));
+ cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels;
+ break;
+ }
+ // ...or finished a segment and there are segments remaining on this line
+ else
+ {
+ // subtract pixels used and increment segment
+ if (force_newline)
+ {
+ mLineInfoList.push_back(line_info(
+ line_start_index,
+ last_segment_char_on_line,
+ line_rect,
+ line_count));
+ line_start_index = segment->getStart() + seg_offset;
+ cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels;
+ line_height = 0;
+ remaining_pixels = text_available_width;
+ }
+ ++seg_iter;
+ seg_offset = 0;
+ }
+ if (force_newline)
+ {
+ line_count++;
+ }
+ }
+
+ // calculate visible region for diplaying text
+ updateRects();
+
+ for (segment_set_t::iterator segment_it = mSegments.begin();
+ segment_it != mSegments.end();
+ ++segment_it)
+ {
+ LLTextSegmentPtr segmentp = *segment_it;
+ segmentp->updateLayout(*this);
+
+ }
+
+ // apply scroll constraints after reflowing text
+ if (!hasMouseCapture() && mScroller)
+ {
+ if (scrolled_to_bottom && mTrackEnd)
+ {
+ // keep bottom of text buffer visible
+ endOfDoc();
+ }
+ else if (hasSelection() && follow_selection)
+ {
+ // keep cursor in same vertical position on screen when selecting text
+ LLRect new_cursor_rect_doc = getDocRectFromDocIndex(mCursorPos);
+ mScroller->scrollToShowRect(new_cursor_rect_doc, old_cursor_rect);
+ }
+ else
+ {
+ // keep first line of text visible
+ LLRect new_first_char_rect = getDocRectFromDocIndex(mScrollIndex);
+ mScroller->scrollToShowRect(new_first_char_rect, first_char_rect);
+ }
+ }
+
+ // reset desired x cursor position
+ updateCursorXPos();
+ }
+}
+
+LLRect LLTextBase::getTextBoundingRect()
+{
+ reflow();
+ return mTextBoundingRect;
+}
+
+
+void LLTextBase::clearSegments()
+{
+ mSegments.clear();
+ createDefaultSegment();
+}
+
+S32 LLTextBase::getLineStart( S32 line ) const
+{
+ S32 num_lines = getLineCount();
+ if (num_lines == 0)
+ {
+ return 0;
+ }
+
+ line = llclamp(line, 0, num_lines-1);
+ return mLineInfoList[line].mDocIndexStart;
+}
+
+S32 LLTextBase::getLineEnd( S32 line ) const
+{
+ S32 num_lines = getLineCount();
+ if (num_lines == 0)
+ {
+ return 0;
+ }
+
+ line = llclamp(line, 0, num_lines-1);
+ return mLineInfoList[line].mDocIndexEnd;
+}
+
+
+
+S32 LLTextBase::getLineNumFromDocIndex( S32 doc_index, bool include_wordwrap) const
+{
+ if (mLineInfoList.empty())
+ {
+ return 0;
+ }
+ else
+ {
+ line_list_t::const_iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), doc_index, line_end_compare());
+ if (include_wordwrap)
+ {
+ return iter - mLineInfoList.begin();
+ }
+ else
+ {
+ if (iter == mLineInfoList.end())
+ {
+ return mLineInfoList.back().mLineNum;
+ }
+ else
+ {
+ return iter->mLineNum;
+ }
+ }
+ }
+}
+
+// Given an offset into text (pos), find the corresponding line (from the start of the doc) and an offset into the line.
+S32 LLTextBase::getLineOffsetFromDocIndex( S32 startpos, bool include_wordwrap) const
+{
+ if (mLineInfoList.empty())
+ {
+ return startpos;
+ }
+ else
+ {
+ line_list_t::const_iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), startpos, line_end_compare());
+ return startpos - iter->mDocIndexStart;
+ }
+}
+
+S32 LLTextBase::getFirstVisibleLine() const
+{
+ LLRect visible_region = getVisibleDocumentRect();
+
+ // binary search for line that starts before top of visible buffer
+ line_list_t::const_iterator iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mTop, compare_bottom());
+
+ return iter - mLineInfoList.begin();
+}
+
+std::pair<S32, S32> LLTextBase::getVisibleLines(bool fully_visible)
+{
+ LLRect visible_region = getVisibleDocumentRect();
+ line_list_t::const_iterator first_iter;
+ line_list_t::const_iterator last_iter;
+
+ // make sure we have an up-to-date mLineInfoList
+ reflow();
+
+ if (fully_visible)
+ {
+ first_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mTop, compare_top());
+ last_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mBottom, compare_bottom());
+ }
+ else
+ {
+ first_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mTop, compare_bottom());
+ last_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), visible_region.mBottom, compare_top());
+ }
+ return std::pair<S32, S32>(first_iter - mLineInfoList.begin(), last_iter - mLineInfoList.begin());
+}
+
+
+
+LLTextViewModel* LLTextBase::getViewModel() const
+{
+ return (LLTextViewModel*)mViewModel.get();
+}
+
+void LLTextBase::addDocumentChild(LLView* view)
+{
+ mDocumentView->addChild(view);
+}
+
+void LLTextBase::removeDocumentChild(LLView* view)
+{
+ mDocumentView->removeChild(view);
+}
+
+
+static LLFastTimer::DeclareTimer FTM_UPDATE_TEXT_SEGMENTS("Update Text Segments");
+void LLTextBase::updateSegments()
+{
+ LLFastTimer ft(FTM_UPDATE_TEXT_SEGMENTS);
+ createDefaultSegment();
+}
+
+void LLTextBase::getSegmentAndOffset( S32 startpos, segment_set_t::const_iterator* seg_iter, S32* offsetp ) const
+{
+ *seg_iter = getSegIterContaining(startpos);
+ if (*seg_iter == mSegments.end())
+ {
+ *offsetp = 0;
+ }
+ else
+ {
+ *offsetp = startpos - (**seg_iter)->getStart();
+ }
+}
+
+void LLTextBase::getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg_iter, S32* offsetp )
+{
+ *seg_iter = getSegIterContaining(startpos);
+ if (*seg_iter == mSegments.end())
+ {
+ *offsetp = 0;
+ }
+ else
+ {
+ *offsetp = startpos - (**seg_iter)->getStart();
+ }
+}
+
+LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index)
+{
+ segment_set_t::iterator it = mSegments.upper_bound(new LLIndexSegment(index));
+ return it;
+}
+
+LLTextBase::segment_set_t::const_iterator LLTextBase::getSegIterContaining(S32 index) const
+{
+ LLTextBase::segment_set_t::const_iterator it = mSegments.upper_bound(new LLIndexSegment(index));
+ return it;
+}
+
+// Finds the text segment (if any) at the give local screen position
+LLTextSegmentPtr LLTextBase::getSegmentAtLocalPos( S32 x, S32 y )
+{
+ // Find the cursor position at the requested local screen position
+ S32 offset = getDocIndexFromLocalCoord( x, y, FALSE );
+ segment_set_t::iterator seg_iter = getSegIterContaining(offset);
+ if (seg_iter != mSegments.end())
+ {
+ return *seg_iter;
+ }
+ else
+ {
+ return LLTextSegmentPtr();
+ }
+}
+
+void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
+{
+ // work out the XUI menu file to use for this url
+ LLUrlMatch match;
+ std::string url = in_url;
+ if (! LLUrlRegistry::instance().findUrl(url, match))
+ {
+ return;
+ }
+
+ std::string xui_file = match.getMenuName();
+ if (xui_file.empty())
+ {
+ return;
+ }
+
+ // set up the callbacks for all of the potential menu items, N.B. we
+ // don't use const ref strings in callbacks in case url goes out of scope
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("Url.Open", boost::bind(&LLUrlAction::openURL, url));
+ registrar.add("Url.OpenInternal", boost::bind(&LLUrlAction::openURLInternal, url));
+ registrar.add("Url.OpenExternal", boost::bind(&LLUrlAction::openURLExternal, url));
+ registrar.add("Url.Execute", boost::bind(&LLUrlAction::executeSLURL, url));
+ registrar.add("Url.Teleport", boost::bind(&LLUrlAction::teleportToLocation, url));
+ registrar.add("Url.ShowOnMap", boost::bind(&LLUrlAction::showLocationOnMap, url));
+ registrar.add("Url.CopyLabel", boost::bind(&LLUrlAction::copyLabelToClipboard, url));
+ registrar.add("Url.CopyUrl", boost::bind(&LLUrlAction::copyURLToClipboard, url));
+
+ // create and return the context menu from the XUI file
+ delete mPopupMenu;
+ mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(xui_file, LLMenuGL::sMenuContainer,
+ LLMenuHolderGL::child_registry_t::instance());
+ if (mPopupMenu)
+ {
+ mPopupMenu->show(x, y);
+ LLMenuGL::showPopup(this, mPopupMenu, x, y);
+ }
+}
+
+void LLTextBase::setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params)
+{
+ // clear out the existing text and segments
+ getViewModel()->setDisplay(LLWStringUtil::null);
+
+ clearSegments();
+// createDefaultSegment();
+
+ deselect();
+
+ // append the new text (supports Url linking)
+ std::string text(utf8str);
+ LLStringUtil::removeCRLF(text);
+
+ // appendText modifies mCursorPos...
+ appendText(text, false, input_params);
+ // ...so move cursor to top after appending text
+ startOfDoc();
+
+ onValueChange(0, getLength());
+}
+
+//virtual
+std::string LLTextBase::getText() const
+{
+ return getViewModel()->getValue().asString();
+}
+
+void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params)
+{
+ LLStyle::Params style_params(input_params);
+ style_params.fillFrom(getDefaultStyle());
+
+ if (!style_params.font.isProvided())
+ {
+ style_params.font = mDefaultFont;
+ }
+ if (!style_params.drop_shadow.isProvided())
+ {
+ style_params.drop_shadow = mFontShadow;
+ }
+
+ S32 part = (S32)LLTextParser::WHOLE;
+ if(mParseHTML)
+ {
+ S32 start=0,end=0;
+ LLUrlMatch match;
+ std::string text = new_text;
+ while ( LLUrlRegistry::instance().findUrl(text, match,
+ boost::bind(&LLTextBase::replaceUrlLabel, this, _1, _2)) )
+ {
+ start = match.getStart();
+ end = match.getEnd()+1;
+
+ LLStyle::Params link_params = style_params;
+ link_params.color = match.getColor();
+ link_params.readonly_color = match.getColor();
+ // apply font name from requested style_params
+ std::string font_name = LLFontGL::nameFromFont(style_params.font());
+ std::string font_size = LLFontGL::sizeFromFont(style_params.font());
+ link_params.font.name(font_name);
+ link_params.font.size(font_size);
+ link_params.font.style("UNDERLINE");
+
+ link_params.link_href = match.getUrl();
+
+ // output the text before the Url
+ if (start > 0)
+ {
+ if (part == (S32)LLTextParser::WHOLE ||
+ part == (S32)LLTextParser::START)
+ {
+ part = (S32)LLTextParser::START;
+ }
+ else
+ {
+ part = (S32)LLTextParser::MIDDLE;
+ }
+ std::string subtext=text.substr(0,start);
+ appendAndHighlightText(subtext, prepend_newline, part, style_params);
+ prepend_newline = false;
+ }
+
+ // output an optional icon before the Url
+ if (! match.getIcon().empty())
+ {
+ LLUIImagePtr image = LLUI::getUIImage(match.getIcon());
+ if (image)
+ {
+ LLStyle::Params icon;
+ icon.image = image;
+ // HACK: fix spacing of images and remove the fixed char spacing
+ appendAndHighlightText(" ", prepend_newline, part, icon);
+ prepend_newline = false;
+ }
+ }
+ // output the styled Url
+ appendAndHighlightText(match.getLabel(), prepend_newline, part, link_params);
+ prepend_newline = false;
+
+ // set the tooltip for the Url label
+ if (! match.getTooltip().empty())
+ {
+ segment_set_t::iterator it = getSegIterContaining(getLength()-1);
+ if (it != mSegments.end())
+ {
+ LLTextSegmentPtr segment = *it;
+ segment->setToolTip(match.getTooltip());
+ }
+ }
+
+ // move on to the rest of the text after the Url
+ if (end < (S32)text.length())
+ {
+ text = text.substr(end,text.length() - end);
+ end=0;
+ part=(S32)LLTextParser::END;
+ }
+ else
+ {
+ break;
+ }
+ }
+ if (part != (S32)LLTextParser::WHOLE) part=(S32)LLTextParser::END;
+ if (end < (S32)text.length()) appendAndHighlightText(text, prepend_newline, part, style_params);
+ }
+ else
+ {
+ appendAndHighlightText(new_text, prepend_newline, part, style_params);
+ }
+}
+
+void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepend_newline, S32 highlight_part, const LLStyle::Params& stylep)
+{
+ if (new_text.empty()) return;
+
+ // Save old state
+ S32 selection_start = mSelectionStart;
+ S32 selection_end = mSelectionEnd;
+ BOOL was_selecting = mIsSelecting;
+ S32 cursor_pos = mCursorPos;
+ S32 old_length = getLength();
+ BOOL cursor_was_at_end = (mCursorPos == old_length);
+
+ deselect();
+
+ setCursorPos(old_length);
+
+ LLTextParser* highlight = LLTextParser::getInstance();
+
+ if (mParseHighlights && highlight)
+ {
+ LLStyle::Params highlight_params = stylep;
+
+ LLSD pieces = highlight->parsePartialLineHighlights(new_text, highlight_params.color(), (LLTextParser::EHighlightPosition)highlight_part);
+ for (S32 i = 0; i < pieces.size(); i++)
+ {
+ LLSD color_llsd = pieces[i]["color"];
+ LLColor4 lcolor;
+ lcolor.setValue(color_llsd);
+ highlight_params.color = lcolor;
+
+ LLWString wide_text;
+ if (prepend_newline && (i == 0 || pieces.size() <= 1 ))
+ {
+ wide_text = utf8str_to_wstring(std::string("\n") + pieces[i]["text"].asString());
+ }
+ else
+ {
+ wide_text = utf8str_to_wstring(pieces[i]["text"].asString());
+ }
+ S32 cur_length = getLength();
+ LLTextSegmentPtr segmentp = new LLNormalTextSegment(new LLStyle(highlight_params), cur_length, cur_length + wide_text.size(), *this);
+ segment_vec_t segments;
+ segments.push_back(segmentp);
+ insertStringNoUndo(cur_length, wide_text, &segments);
+ }
+ }
+ else
+ {
+ LLWString wide_text;
+
+ // Add carriage return if not first line
+ if (getLength() != 0
+ && prepend_newline)
+ {
+ wide_text = utf8str_to_wstring(std::string("\n") + new_text);
+ }
+ else
+ {
+ wide_text = utf8str_to_wstring(new_text);
+ }
+
+ segment_vec_t segments;
+ S32 segment_start = old_length;
+ S32 segment_end = old_length + wide_text.size();
+ segments.push_back(new LLNormalTextSegment(new LLStyle(stylep), segment_start, segment_end, *this ));
+
+ insertStringNoUndo(getLength(), wide_text, &segments);
+ }
+
+ // Set the cursor and scroll position
+ if( selection_start != selection_end )
+ {
+ mSelectionStart = selection_start;
+ mSelectionEnd = selection_end;
+
+ mIsSelecting = was_selecting;
+ setCursorPos(cursor_pos);
+ }
+ else if( cursor_was_at_end )
+ {
+ setCursorPos(getLength());
+ }
+ else
+ {
+ setCursorPos(cursor_pos);
+ }
+
+ //if( !allow_undo )
+ //{
+ // blockUndo();
+ //}
+}
+
+
+void LLTextBase::replaceUrlLabel(const std::string &url,
+ const std::string &label)
+{
+ // get the full (wide) text for the editor so we can change it
+ LLWString text = getWText();
+ LLWString wlabel = utf8str_to_wstring(label);
+ bool modified = false;
+ S32 seg_start = 0;
+
+ // iterate through each segment looking for ones styled as links
+ segment_set_t::iterator it;
+ for (it = mSegments.begin(); it != mSegments.end(); ++it)
+ {
+ LLTextSegment *seg = *it;
+ const LLStyleSP style = seg->getStyle();
+
+ // update segment start/end length in case we replaced text earlier
+ S32 seg_length = seg->getEnd() - seg->getStart();
+ seg->setStart(seg_start);
+ seg->setEnd(seg_start + seg_length);
+
+ // if we find a link with our Url, then replace the label
+ if (style->isLink() && style->getLinkHREF() == url)
+ {
+ S32 start = seg->getStart();
+ S32 end = seg->getEnd();
+ text = text.substr(0, start) + wlabel + text.substr(end, text.size() - end + 1);
+ seg->setEnd(start + wlabel.size());
+ modified = true;
+ }
+
+ // work out the character offset for the next segment
+ seg_start = seg->getEnd();
+ }
+
+ // update the editor with the new (wide) text string
+ if (modified)
+ {
+ getViewModel()->setDisplay(text);
+ deselect();
+ setCursorPos(mCursorPos);
+ needsReflow();
+ }
+}
+
+
+void LLTextBase::setWText(const LLWString& text)
+{
+ setText(wstring_to_utf8str(text));
+}
+
+LLWString LLTextBase::getWText() const
+{
+ return getViewModel()->getDisplay();
+}
+
+// If round is true, if the position is on the right half of a character, the cursor
+// will be put to its right. If round is false, the cursor will always be put to the
+// character's left.
+
+S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const
+{
+ // Figure out which line we're nearest to.
+ LLRect visible_region = getVisibleDocumentRect();
+
+ // binary search for line that starts before local_y
+ line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), local_y - mVisibleTextRect.mBottom + visible_region.mBottom, compare_bottom());
+
+ if (line_iter == mLineInfoList.end())
+ {
+ return getLength(); // past the end
+ }
+
+ S32 pos = getLength();
+ S32 start_x = mVisibleTextRect.mLeft + line_iter->mRect.mLeft;
+
+ segment_set_t::iterator line_seg_iter;
+ S32 line_seg_offset;
+ for(getSegmentAndOffset(line_iter->mDocIndexStart, &line_seg_iter, &line_seg_offset);
+ line_seg_iter != mSegments.end();
+ ++line_seg_iter, line_seg_offset = 0)
+ {
+ const LLTextSegmentPtr segmentp = *line_seg_iter;
+
+ S32 segment_line_start = segmentp->getStart() + line_seg_offset;
+ S32 segment_line_length = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd - 1) - segment_line_start;
+ S32 text_width, text_height;
+ segmentp->getDimensions(line_seg_offset, segment_line_length, text_width, text_height);
+ if (local_x < start_x + text_width // cursor to left of right edge of text
+ || segmentp->getEnd() >= line_iter->mDocIndexEnd - 1) // or this segment wraps to next line
+ {
+ // Figure out which character we're nearest to.
+ S32 offset;
+ if (!segmentp->canEdit())
+ {
+ S32 segment_width, segment_height;
+ segmentp->getDimensions(0, segmentp->getEnd() - segmentp->getStart(), segment_width, segment_height);
+ if (round && local_x - start_x > segment_width / 2)
+ {
+ offset = segment_line_length;
+ }
+ else
+ {
+ offset = 0;
+ }
+ }
+ else
+ {
+ offset = segmentp->getOffset(local_x - start_x, line_seg_offset, segment_line_length, round);
+ }
+ pos = segment_line_start + offset;
+ break;
+ }
+ start_x += text_width;
+ }
+
+ return pos;
+}
+
+// returns rectangle of insertion caret
+// in document coordinate frame from given index into text
+LLRect LLTextBase::getDocRectFromDocIndex(S32 pos) const
+{
+ if (mLineInfoList.empty())
+ {
+ return LLRect();
+ }
+
+ LLRect doc_rect;
+
+ // clamp pos to valid values
+ pos = llclamp(pos, 0, mLineInfoList.back().mDocIndexEnd - 1);
+
+ // find line that contains cursor
+ line_list_t::const_iterator line_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), pos, line_end_compare());
+
+ doc_rect.mLeft = line_iter->mRect.mLeft;
+ doc_rect.mBottom = line_iter->mRect.mBottom;
+ doc_rect.mTop = line_iter->mRect.mTop;
+
+ segment_set_t::iterator line_seg_iter;
+ S32 line_seg_offset;
+ segment_set_t::iterator cursor_seg_iter;
+ S32 cursor_seg_offset;
+ getSegmentAndOffset(line_iter->mDocIndexStart, &line_seg_iter, &line_seg_offset);
+ getSegmentAndOffset(pos, &cursor_seg_iter, &cursor_seg_offset);
+
+ while(line_seg_iter != mSegments.end())
+ {
+ const LLTextSegmentPtr segmentp = *line_seg_iter;
+
+ if (line_seg_iter == cursor_seg_iter)
+ {
+ // cursor advanced to right based on difference in offset of cursor to start of line
+ S32 segment_width, segment_height;
+ segmentp->getDimensions(line_seg_offset, cursor_seg_offset - line_seg_offset, segment_width, segment_height);
+ doc_rect.mLeft += segment_width;
+
+ break;
+ }
+ else
+ {
+ // add remainder of current text segment to cursor position
+ S32 segment_width, segment_height;
+ segmentp->getDimensions(line_seg_offset, (segmentp->getEnd() - segmentp->getStart()) - line_seg_offset, segment_width, segment_height);
+ doc_rect.mLeft += segment_width;
+ // offset will be 0 for all segments after the first
+ line_seg_offset = 0;
+ // go to next text segment on this line
+ ++line_seg_iter;
+ }
+ }
+
+ // set rect to 0 width
+ doc_rect.mRight = doc_rect.mLeft;
+
+ return doc_rect;
+}
+
+LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const
+{
+ LLRect local_rect;
+ if (mLineInfoList.empty())
+ {
+ // return default height rect in upper left
+ local_rect = mVisibleTextRect;
+ local_rect.mBottom = local_rect.mTop - (S32)(mDefaultFont->getLineHeight());
+ return local_rect;
+ }
+
+ // get the rect in document coordinates
+ LLRect doc_rect = getDocRectFromDocIndex(pos);
+
+ // compensate for scrolled, inset view of doc
+ LLRect scrolled_view_rect = getVisibleDocumentRect();
+ local_rect = doc_rect;
+ local_rect.translate(mVisibleTextRect.mLeft - scrolled_view_rect.mLeft,
+ mVisibleTextRect.mBottom - scrolled_view_rect.mBottom);
+
+ return local_rect;
+}
+
+void LLTextBase::updateCursorXPos()
+{
+ // reset desired x cursor position
+ mDesiredXPixel = getLocalRectFromDocIndex(mCursorPos).mLeft;
+}
+
+
+void LLTextBase::startOfLine()
+{
+ S32 offset = getLineOffsetFromDocIndex(mCursorPos);
+ setCursorPos(mCursorPos - offset);
+}
+
+void LLTextBase::endOfLine()
+{
+ S32 line = getLineNumFromDocIndex(mCursorPos);
+ S32 num_lines = getLineCount();
+ if (line + 1 >= num_lines)
+ {
+ setCursorPos(getLength());
+ }
+ else
+ {
+ setCursorPos( getLineStart(line + 1) - 1 );
+ }
+}
+
+void LLTextBase::startOfDoc()
+{
+ setCursorPos(0);
+ if (mScroller)
+ {
+ mScroller->goToTop();
+ }
+}
+
+void LLTextBase::endOfDoc()
+{
+ setCursorPos(getLength());
+ if (mScroller)
+ {
+ mScroller->goToBottom();
+ }
+}
+
+void LLTextBase::changePage( S32 delta )
+{
+ const S32 PIXEL_OVERLAP_ON_PAGE_CHANGE = 10;
+ if (delta == 0 || !mScroller) return;
+
+ LLRect cursor_rect = getLocalRectFromDocIndex(mCursorPos);
+
+ if( delta == -1 )
+ {
+ mScroller->pageUp(PIXEL_OVERLAP_ON_PAGE_CHANGE);
+ }
+ else
+ if( delta == 1 )
+ {
+ mScroller->pageDown(PIXEL_OVERLAP_ON_PAGE_CHANGE);
+ }
+
+ if (getLocalRectFromDocIndex(mCursorPos) == cursor_rect)
+ {
+ // cursor didn't change apparent position, so move to top or bottom of document, respectively
+ if (delta < 0)
+ {
+ startOfDoc();
+ }
+ else
+ {
+ endOfDoc();
+ }
+ }
+ else
+ {
+ setCursorAtLocalPos(cursor_rect.getCenterX(), cursor_rect.getCenterY(), true, false);
+ }
+}
+
+// Picks a new cursor position based on the screen size of text being drawn.
+void LLTextBase::setCursorAtLocalPos( S32 local_x, S32 local_y, bool round, bool keep_cursor_offset )
+{
+ setCursorPos(getDocIndexFromLocalCoord(local_x, local_y, round), keep_cursor_offset);
+}
+
+
+void LLTextBase::changeLine( S32 delta )
+{
+ S32 line = getLineNumFromDocIndex(mCursorPos);
+
+ S32 new_line = line;
+ if( (delta < 0) && (line > 0 ) )
+ {
+ new_line = line - 1;
+ }
+ else if( (delta > 0) && (line < (getLineCount() - 1)) )
+ {
+ new_line = line + 1;
+ }
+
+ LLRect visible_region = getVisibleDocumentRect();
+
+ S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel, mLineInfoList[new_line].mRect.mBottom + mVisibleTextRect.mBottom - visible_region.mBottom, TRUE);
+ setCursorPos(new_cursor_pos, true);
+}
+
+bool LLTextBase::scrolledToStart()
+{
+ return mScroller->isAtTop();
+}
+
+bool LLTextBase::scrolledToEnd()
+{
+ return mScroller->isAtBottom();
+}
+
+
+bool LLTextBase::setCursor(S32 row, S32 column)
+{
+ if (0 <= row && row < (S32)mLineInfoList.size())
+ {
+ S32 doc_pos = mLineInfoList[row].mDocIndexStart;
+ column = llclamp(column, 0, mLineInfoList[row].mDocIndexEnd - mLineInfoList[row].mDocIndexStart - 1);
+ doc_pos += column;
+ updateCursorXPos();
+
+ return setCursorPos(doc_pos);
+ }
+ return false;
+}
+
+
+bool LLTextBase::setCursorPos(S32 cursor_pos, bool keep_cursor_offset)
+{
+ S32 new_cursor_pos = cursor_pos;
+ if (new_cursor_pos != mCursorPos)
+ {
+ new_cursor_pos = getEditableIndex(new_cursor_pos, new_cursor_pos >= mCursorPos);
+ }
+
+ mCursorPos = llclamp(new_cursor_pos, 0, (S32)getLength());
+ needsScroll();
+ if (!keep_cursor_offset)
+ updateCursorXPos();
+ // did we get requested position?
+ return new_cursor_pos == cursor_pos;
+}
+
+// constraint cursor to editable segments of document
+S32 LLTextBase::getEditableIndex(S32 index, bool increasing_direction)
+{
+ segment_set_t::iterator segment_iter;
+ S32 offset;
+ getSegmentAndOffset(index, &segment_iter, &offset);
+ if (segment_iter == mSegments.end())
+ {
+ return 0;
+ }
+
+ LLTextSegmentPtr segmentp = *segment_iter;
+
+ if (segmentp->canEdit())
+ {
+ return segmentp->getStart() + offset;
+ }
+ else if (segmentp->getStart() < index && index < segmentp->getEnd())
+ {
+ // bias towards document end
+ if (increasing_direction)
+ {
+ return segmentp->getEnd();
+ }
+ // bias towards document start
+ else
+ {
+ return segmentp->getStart();
+ }
+ }
+ else
+ {
+ return index;
+ }
+}
+
+void LLTextBase::updateRects()
+{
+ if (mLineInfoList.empty())
+ {
+ mTextBoundingRect = LLRect(0, mVPad, mHPad, 0);
+ }
+ else
+ {
+ mTextBoundingRect = mLineInfoList.begin()->mRect;
+ for (line_list_t::const_iterator line_iter = ++mLineInfoList.begin();
+ line_iter != mLineInfoList.end();
+ ++line_iter)
+ {
+ mTextBoundingRect.unionWith(line_iter->mRect);
+ }
+
+ mTextBoundingRect.mTop += mVPad;
+ // subtract a pixel off the bottom to deal with rounding errors in measuring font height
+ mTextBoundingRect.mBottom -= 1;
+
+ S32 delta_pos = -mTextBoundingRect.mBottom;
+ // move line segments to fit new document rect
+ for (line_list_t::iterator it = mLineInfoList.begin(); it != mLineInfoList.end(); ++it)
+ {
+ it->mRect.translate(0, delta_pos);
+ }
+ mTextBoundingRect.translate(0, delta_pos);
+ }
+
+ // update document container dimensions according to text contents
+ LLRect doc_rect = mTextBoundingRect;
+ // use old mVisibleTextRect constraint document to width of viewable region
+ doc_rect.mLeft = 0;
+
+ // allow horizontal scrolling?
+ // if so, use entire width of text contents
+ // otherwise, stop at width of mVisibleTextRect
+ doc_rect.mRight = mScroller
+ ? llmax(mVisibleTextRect.getWidth(), mTextBoundingRect.mRight)
+ : mVisibleTextRect.getWidth();
+
+ mDocumentView->setShape(doc_rect);
+
+ //update mVisibleTextRect *after* mDocumentView has been resized
+ // so that scrollbars are added if document needs to scroll
+ // since mVisibleTextRect does not include scrollbars
+ LLRect old_text_rect = mVisibleTextRect;
+ mVisibleTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect();
+ //FIXME: replace border with image?
+ if (mBorderVisible)
+ {
+ mVisibleTextRect.stretch(-1);
+ }
+ if (mVisibleTextRect != old_text_rect)
+ {
+ needsReflow();
+ }
+
+ // update document container again, using new mVisibleTextRect (that has scrollbars enabled as needed)
+ doc_rect.mRight = mScroller
+ ? llmax(mVisibleTextRect.getWidth(), mTextBoundingRect.mRight)
+ : mVisibleTextRect.getWidth();
+ mDocumentView->setShape(doc_rect);
+}
+
+
+void LLTextBase::startSelection()
+{
+ if( !mIsSelecting )
+ {
+ mIsSelecting = TRUE;
+ mSelectionStart = mCursorPos;
+ mSelectionEnd = mCursorPos;
+ }
+}
+
+void LLTextBase::endSelection()
+{
+ if( mIsSelecting )
+ {
+ mIsSelecting = FALSE;
+ mSelectionEnd = mCursorPos;
+ }
+}
+
+// get portion of document that is visible in text editor
+LLRect LLTextBase::getVisibleDocumentRect() const
+{
+ if (mScroller)
+ {
+ return mScroller->getVisibleContentRect();
+ }
+ else
+ {
+ // entire document rect is visible when not scrolling
+ // but offset according to height of widget
+ LLRect doc_rect = mDocumentView->getLocalRect();
+ doc_rect.mLeft -= mDocumentView->getRect().mLeft;
+ // adjust for height of text above widget baseline
+ doc_rect.mBottom = doc_rect.getHeight() - mVisibleTextRect.getHeight();
+ return doc_rect;
+ }
+}
+
+//
+// LLTextSegment
+//
+
+LLTextSegment::~LLTextSegment()
+{}
+
+bool LLTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const { width = 0; height = 0; return false;}
+S32 LLTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const { return 0; }
+S32 LLTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const { return 0; }
+void LLTextSegment::updateLayout(const LLTextBase& editor) {}
+F32 LLTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect) { return draw_rect.mLeft; }
+bool LLTextSegment::canEdit() const { return false; }
+void LLTextSegment::unlinkFromDocument(LLTextBase*) {}
+void LLTextSegment::linkToDocument(LLTextBase*) {}
+const LLColor4& LLTextSegment::getColor() const { return LLColor4::white; }
+void LLTextSegment::setColor(const LLColor4 &color) {}
+const LLStyleSP LLTextSegment::getStyle() const {static LLStyleSP sp(new LLStyle()); return sp; }
+void LLTextSegment::setStyle(const LLStyleSP &style) {}
+void LLTextSegment::setToken( LLKeywordToken* token ) {}
+LLKeywordToken* LLTextSegment::getToken() const { return NULL; }
+void LLTextSegment::setToolTip( const std::string &msg ) {}
+void LLTextSegment::dump() const {}
+BOOL LLTextSegment::handleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }
+BOOL LLTextSegment::handleMouseUp(S32 x, S32 y, MASK mask) { return FALSE; }
+BOOL LLTextSegment::handleMiddleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }
+BOOL LLTextSegment::handleMiddleMouseUp(S32 x, S32 y, MASK mask) { return FALSE; }
+BOOL LLTextSegment::handleRightMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }
+BOOL LLTextSegment::handleRightMouseUp(S32 x, S32 y, MASK mask) { return FALSE; }
+BOOL LLTextSegment::handleDoubleClick(S32 x, S32 y, MASK mask) { return FALSE; }
+BOOL LLTextSegment::handleHover(S32 x, S32 y, MASK mask) { return FALSE; }
+BOOL LLTextSegment::handleScrollWheel(S32 x, S32 y, S32 clicks) { return FALSE; }
+BOOL LLTextSegment::handleToolTip(S32 x, S32 y, MASK mask) { return FALSE; }
+std::string LLTextSegment::getName() const { return ""; }
+void LLTextSegment::onMouseCaptureLost() {}
+void LLTextSegment::screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const {}
+void LLTextSegment::localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const {}
+BOOL LLTextSegment::hasMouseCapture() { return FALSE; }
+
+//
+// LLNormalTextSegment
+//
+
+LLNormalTextSegment::LLNormalTextSegment( const LLStyleSP& style, S32 start, S32 end, LLTextBase& editor )
+: LLTextSegment(start, end),
+ mStyle( style ),
+ mToken(NULL),
+ mEditor(editor)
+{
+ mFontHeight = llceil(mStyle->getFont()->getLineHeight());
+
+ LLUIImagePtr image = mStyle->getImage();
+ if (image.notNull())
+ {
+ mImageLoadedConnection = image->addLoadedCallback(boost::bind(&LLTextBase::needsReflow, &mEditor));
+ }
+}
+
+LLNormalTextSegment::LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible)
+: LLTextSegment(start, end),
+ mToken(NULL),
+ mEditor(editor)
+{
+ mStyle = new LLStyle(LLStyle::Params().visible(is_visible).color(color));
+
+ mFontHeight = llceil(mStyle->getFont()->getLineHeight());
+}
+
+LLNormalTextSegment::~LLNormalTextSegment()
+{
+ mImageLoadedConnection.disconnect();
+}
+
+
+F32 LLNormalTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
+{
+ if( end - start > 0 )
+ {
+ if ( mStyle->isImage() && (start >= 0) && (end <= mEnd - mStart))
+ {
+ LLColor4 color = LLColor4::white % mEditor.getDrawContext().mAlpha;
+ LLUIImagePtr image = mStyle->getImage();
+ S32 style_image_height = image->getHeight();
+ S32 style_image_width = image->getWidth();
+ // Center the image vertically
+ S32 image_bottom = draw_rect.getCenterY() - (style_image_height/2);
+ image->draw(draw_rect.mLeft, image_bottom,
+ style_image_width, style_image_height, color);
+ }
+
+ return drawClippedSegment( getStart() + start, getStart() + end, selection_start, selection_end, draw_rect);
+ }
+ return draw_rect.mLeft;
+}
+
+// Draws a single text segment, reversing the color for selection if needed.
+F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 selection_start, S32 selection_end, LLRect rect)
+{
+ F32 alpha = LLViewDrawContext::getCurrentContext().mAlpha;
+
+ const LLWString &text = mEditor.getWText();
+
+ if ( text[seg_end-1] == '\n' )
+ {
+ --seg_end;
+ }
+
+ F32 right_x = rect.mLeft;
+ if (!mStyle->isVisible())
+ {
+ return right_x;
+ }
+
+ const LLFontGL* font = mStyle->getFont();
+
+ LLColor4 color = (mEditor.getReadOnly() ? mStyle->getReadOnlyColor() : mStyle->getColor()) % alpha;
+
+ font = mStyle->getFont();
+
+ if( selection_start > seg_start )
+ {
+ // Draw normally
+ S32 start = seg_start;
+ S32 end = llmin( selection_start, seg_end );
+ S32 length = end - start;
+ font->render(text, start,
+ rect.mLeft, rect.mTop,
+ color,
+ LLFontGL::LEFT, LLFontGL::TOP,
+ LLFontGL::NORMAL,
+ mStyle->getShadowType(),
+ length, rect.getWidth(),
+ &right_x,
+ mEditor.getUseEllipses());
+ }
+ rect.mLeft = (S32)ceil(right_x);
+
+ if( (selection_start < seg_end) && (selection_end > seg_start) )
+ {
+ // Draw reversed
+ S32 start = llmax( selection_start, seg_start );
+ S32 end = llmin( selection_end, seg_end );
+ S32 length = end - start;
+
+ font->render(text, start,
+ rect.mLeft, rect.mTop,
+ LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ),
+ LLFontGL::LEFT, LLFontGL::TOP,
+ LLFontGL::NORMAL,
+ LLFontGL::NO_SHADOW,
+ length, rect.getWidth(),
+ &right_x,
+ mEditor.getUseEllipses());
+ }
+ rect.mLeft = (S32)ceil(right_x);
+ if( selection_end < seg_end )
+ {
+ // Draw normally
+ S32 start = llmax( selection_end, seg_start );
+ S32 end = seg_end;
+ S32 length = end - start;
+ font->render(text, start,
+ rect.mLeft, rect.mTop,
+ color,
+ LLFontGL::LEFT, LLFontGL::TOP,
+ LLFontGL::NORMAL,
+ mStyle->getShadowType(),
+ length, rect.getWidth(),
+ &right_x,
+ mEditor.getUseEllipses());
+ }
+ return right_x;
+}
+
+BOOL LLNormalTextSegment::handleHover(S32 x, S32 y, MASK mask)
+{
+ if (getStyle() && getStyle()->isLink())
+ {
+ LLUI::getWindow()->setCursor(UI_CURSOR_HAND);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL LLNormalTextSegment::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ if (getStyle() && getStyle()->isLink())
+ {
+ mEditor.createUrlContextMenu(x, y, getStyle()->getLinkHREF());
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL LLNormalTextSegment::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ if (getStyle() && getStyle()->isLink())
+ {
+ // eat mouse down event on hyperlinks, so we get the mouse up
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL LLNormalTextSegment::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+ if (getStyle() && getStyle()->isLink())
+ {
+ LLUrlAction::clickAction(getStyle()->getLinkHREF());
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL LLNormalTextSegment::handleToolTip(S32 x, S32 y, MASK mask)
+{
+ std::string msg;
+ // do we have a tooltip for a loaded keyword (for script editor)?
+ if (mToken && !mToken->getToolTip().empty())
+ {
+ const LLWString& wmsg = mToken->getToolTip();
+ LLToolTipMgr::instance().show(wstring_to_utf8str(wmsg));
+ return TRUE;
+ }
+ // or do we have an explicitly set tooltip (e.g., for Urls)
+ if (!mTooltip.empty())
+ {
+ LLToolTipMgr::instance().show(mTooltip);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void LLNormalTextSegment::setToolTip(const std::string& tooltip)
+{
+ // we cannot replace a keyword tooltip that's loaded from a file
+ if (mToken)
+ {
+ llwarns << "LLTextSegment::setToolTip: cannot replace keyword tooltip." << llendl;
+ return;
+ }
+ mTooltip = tooltip;
+}
+
+bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const
+{
+ height = 0;
+ width = 0;
+ bool force_newline = false;
+ if (num_chars > 0)
+ {
+ height = mFontHeight;
+ LLWString text = mEditor.getWText();
+ // if last character is a newline, then return true, forcing line break
+ llwchar last_char = text[mStart + first_char + num_chars - 1];
+ if (last_char == '\n')
+ {
+ force_newline = true;
+ // don't count newline in font width
+ width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars - 1);
+ }
+ else
+ {
+ width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars);
+ }
+ }
+
+ LLUIImagePtr image = mStyle->getImage();
+ if( image.notNull())
+ {
+ width += image->getWidth();
+ height = llmax(height, image->getHeight());
+ }
+
+ return force_newline;
+}
+
+S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const
+{
+ LLWString text = mEditor.getWText();
+ return mStyle->getFont()->charFromPixelOffset(text.c_str(), mStart + start_offset,
+ (F32)segment_local_x_coord,
+ F32_MAX,
+ num_chars,
+ round);
+}
+
+S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const
+{
+ LLWString text = mEditor.getWText();
+
+ LLUIImagePtr image = mStyle->getImage();
+ if( image.notNull())
+ {
+ num_pixels -= image->getWidth();
+ }
+
+ // search for newline and if found, truncate there
+ S32 last_char = mStart + segment_offset;
+ for (; last_char != mEnd; ++last_char)
+ {
+ if (text[last_char] == '\n')
+ {
+ break;
+ }
+ }
+
+ // set max characters to length of segment, or to first newline
+ max_chars = llmin(max_chars, last_char - (mStart + segment_offset));
+
+ // if no character yet displayed on this line, don't require word wrapping since
+ // we can just move to the next line, otherwise insist on it so we make forward progress
+ LLFontGL::EWordWrapStyle word_wrap_style = (line_offset == 0)
+ ? LLFontGL::WORD_BOUNDARY_IF_POSSIBLE
+ : LLFontGL::ONLY_WORD_BOUNDARIES;
+ S32 num_chars = mStyle->getFont()->maxDrawableChars(text.c_str() + segment_offset + mStart,
+ (F32)num_pixels,
+ max_chars,
+ word_wrap_style);
+
+ if (num_chars == 0
+ && line_offset == 0
+ && max_chars > 0)
+ {
+ // If at the beginning of a line, and a single character won't fit, draw it anyway
+ num_chars = 1;
+ }
+
+ // include *either* the EOF or newline character in this run of text
+ // but not both
+ S32 last_char_in_run = mStart + segment_offset + num_chars;
+ // check length first to avoid indexing off end of string
+ if (last_char_in_run < mEnd
+ && (last_char_in_run >= mEditor.getLength()
+ || text[last_char_in_run] == '\n'))
+ {
+ num_chars++;
+ }
+ return num_chars;
+}
+
+void LLNormalTextSegment::dump() const
+{
+ llinfos << "Segment [" <<
+// mColor.mV[VX] << ", " <<
+// mColor.mV[VY] << ", " <<
+// mColor.mV[VZ] << "]\t[" <<
+ mStart << ", " <<
+ getEnd() << "]" <<
+ llendl;
+}
+
+
+//
+// LLInlineViewSegment
+//
+
+LLInlineViewSegment::LLInlineViewSegment(const Params& p, S32 start, S32 end)
+: LLTextSegment(start, end),
+ mView(p.view),
+ mForceNewLine(p.force_newline),
+ mLeftPad(p.left_pad),
+ mRightPad(p.right_pad),
+ mTopPad(p.top_pad),
+ mBottomPad(p.bottom_pad)
+{
+}
+
+LLInlineViewSegment::~LLInlineViewSegment()
+{
+ mView->die();
+}
+
+bool LLInlineViewSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const
+{
+ if (first_char == 0 && num_chars == 0)
+ {
+ // we didn't fit on a line, the widget will fall on the next line
+ // so dimensions here are 0
+ width = 0;
+ height = 0;
+ }
+ else
+ {
+ width = mLeftPad + mRightPad + mView->getRect().getWidth();
+ height = mBottomPad + mTopPad + mView->getRect().getHeight();
+ }
+
+ return false;
+}
+
+S32 LLInlineViewSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const
+{
+ // if putting a widget anywhere but at the beginning of a line
+ // and the widget doesn't fit or mForceNewLine is true
+ // then return 0 chars for that line, and all characters for the next
+ if (line_offset != 0
+ && (mForceNewLine || num_pixels < mView->getRect().getWidth()))
+ {
+ return 0;
+ }
+ else
+ {
+ return mEnd - mStart;
+ }
+}
+
+void LLInlineViewSegment::updateLayout(const LLTextBase& editor)
+{
+ LLRect start_rect = editor.getDocRectFromDocIndex(mStart);
+ mView->setOrigin(start_rect.mLeft + mLeftPad, start_rect.mBottom + mBottomPad);
+}
+
+F32 LLInlineViewSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
+{
+ // return padded width of widget
+ // widget is actually drawn during mDocumentView's draw()
+ return (F32)(draw_rect.mLeft + mView->getRect().getWidth() + mLeftPad + mRightPad);
+}
+
+void LLInlineViewSegment::unlinkFromDocument(LLTextBase* editor)
+{
+ editor->removeDocumentChild(mView);
+}
+
+void LLInlineViewSegment::linkToDocument(LLTextBase* editor)
+{
+ editor->addDocumentChild(mView);
+}
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
new file mode 100644
index 0000000000..038b9eaa62
--- /dev/null
+++ b/indra/llui/lltextbase.h
@@ -0,0 +1,505 @@
+/**
+ * @file lltextbase.h
+ * @author Martin Reddy
+ * @brief The base class of text box/editor, providing Url handling support
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTEXTBASE_H
+#define LL_LLTEXTBASE_H
+
+#include "v4color.h"
+#include "lleditmenuhandler.h"
+#include "llstyle.h"
+#include "llkeywords.h"
+#include "llpanel.h"
+
+#include <string>
+#include <set>
+
+#include <boost/signals2.hpp>
+
+class LLContextMenu;
+class LLTextSegment;
+
+typedef LLPointer<LLTextSegment> LLTextSegmentPtr;
+
+///
+/// The LLTextBase class provides a base class for all text fields, such
+/// as LLTextEditor and LLTextBox. It implements shared functionality
+/// such as Url highlighting and opening.
+///
+class LLTextBase
+: public LLUICtrl,
+ protected LLEditMenuHandler
+{
+public:
+ struct LineSpacingParams : public LLInitParam::Choice<LineSpacingParams>
+ {
+ Alternative<F32> multiple;
+ Alternative<S32> pixels;
+ LineSpacingParams();
+ };
+
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<LLUIColor> cursor_color,
+ text_color,
+ text_readonly_color,
+ bg_readonly_color,
+ bg_writeable_color,
+ bg_focus_color;
+
+ Optional<bool> bg_visible,
+ border_visible,
+ track_end,
+ read_only,
+ allow_scroll,
+ wrap,
+ use_ellipses,
+ allow_html,
+ parse_highlights,
+ clip_partial;
+
+ Optional<S32> v_pad,
+ h_pad;
+
+
+ Optional<LineSpacingParams>
+ line_spacing;
+
+ Optional<S32> max_text_length;
+
+ Optional<LLFontGL::ShadowType> font_shadow;
+
+ Params();
+ };
+
+ // LLMouseHandler interface
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMiddleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
+
+ // LLView interface
+ /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+ /*virtual*/ void draw();
+
+ // LLUICtrl interface
+ /*virtual*/ BOOL acceptsTextInput() const { return !mReadOnly; }
+ /*virtual*/ void setColor( const LLColor4& c );
+ virtual void setReadOnlyColor(const LLColor4 &c);
+
+ /*virtual*/ void setValue(const LLSD& value );
+ /*virtual*/ LLTextViewModel* getViewModel() const;
+
+ // LLEditMenuHandler interface
+ /*virtual*/ void deselect();
+
+ // used by LLTextSegment layout code
+ bool getWordWrap() { return mWordWrap; }
+ bool getUseEllipses() { return mUseEllipses; }
+ bool truncate(); // returns true of truncation occurred
+
+ // TODO: move into LLTextSegment?
+ void createUrlContextMenu(S32 x, S32 y, const std::string &url); // create a popup context menu for the given Url
+
+ // Text accessors
+ // TODO: add optional style parameter
+ virtual void setText(const LLStringExplicit &utf8str , const LLStyle::Params& input_params = LLStyle::Params()); // uses default style
+ virtual std::string getText() const;
+ void setMaxTextLength(S32 length) { mMaxTextByteLength = length; }
+
+ // wide-char versions
+ void setWText(const LLWString& text);
+ LLWString getWText() const;
+
+ void appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params = LLStyle::Params());
+ // force reflow of text
+ void needsReflow() { mReflowNeeded = TRUE; }
+
+ S32 getLength() const { return getWText().length(); }
+ S32 getLineCount() const { return mLineInfoList.size(); }
+
+ void addDocumentChild(LLView* view);
+ void removeDocumentChild(LLView* view);
+ const LLView* getDocumentView() const { return mDocumentView; }
+ LLRect getVisibleTextRect() { return mVisibleTextRect; }
+ LLRect getTextBoundingRect();
+ LLRect getVisibleDocumentRect() const;
+
+ S32 getVPad() { return mVPad; }
+ S32 getHPad() { return mHPad; }
+
+ S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const;
+ LLRect getLocalRectFromDocIndex(S32 pos) const;
+ LLRect getDocRectFromDocIndex(S32 pos) const;
+
+ void setReadOnly(bool read_only) { mReadOnly = read_only; }
+ bool getReadOnly() { return mReadOnly; }
+
+ // cursor manipulation
+ bool setCursor(S32 row, S32 column);
+ bool setCursorPos(S32 cursor_pos, bool keep_cursor_offset = false);
+ void startOfLine();
+ void endOfLine();
+ void startOfDoc();
+ void endOfDoc();
+ void changePage( S32 delta );
+ void changeLine( S32 delta );
+
+ bool scrolledToStart();
+ bool scrolledToEnd();
+
+ const LLFontGL* getDefaultFont() const { return mDefaultFont; }
+ LLStyle::Params getDefaultStyle();
+
+public:
+ // Fired when a URL link is clicked
+ commit_signal_t mURLClickSignal;
+
+protected:
+ // helper structs
+ struct compare_bottom;
+ struct compare_top;
+ struct line_end_compare;
+ typedef std::vector<LLTextSegmentPtr> segment_vec_t;
+
+ // Abstract inner base class representing an undoable editor command.
+ // Concrete sub-classes can be defined for operations such as insert, remove, etc.
+ // Used as arguments to the execute() method below.
+ class TextCmd
+ {
+ public:
+ TextCmd( S32 pos, BOOL group_with_next, LLTextSegmentPtr segment = LLTextSegmentPtr() )
+ : mPos(pos),
+ mGroupWithNext(group_with_next)
+ {
+ if (segment.notNull())
+ {
+ mSegments.push_back(segment);
+ }
+ }
+ virtual ~TextCmd() {}
+ virtual BOOL execute(LLTextBase* editor, S32* delta) = 0;
+ virtual S32 undo(LLTextBase* editor) = 0;
+ virtual S32 redo(LLTextBase* editor) = 0;
+ virtual BOOL canExtend(S32 pos) const { return FALSE; }
+ virtual void blockExtensions() {}
+ virtual BOOL extendAndExecute( LLTextBase* editor, S32 pos, llwchar c, S32* delta ) { llassert(0); return 0; }
+ virtual BOOL hasExtCharValue( llwchar value ) const { return FALSE; }
+
+ // Defined here so they can access protected LLTextEditor editing methods
+ S32 insert(LLTextBase* editor, S32 pos, const LLWString &wstr) { return editor->insertStringNoUndo( pos, wstr, &mSegments ); }
+ S32 remove(LLTextBase* editor, S32 pos, S32 length) { return editor->removeStringNoUndo( pos, length ); }
+ S32 overwrite(LLTextBase* editor, S32 pos, llwchar wc) { return editor->overwriteCharNoUndo(pos, wc); }
+
+ S32 getPosition() const { return mPos; }
+ BOOL groupWithNext() const { return mGroupWithNext; }
+
+ protected:
+ const S32 mPos;
+ BOOL mGroupWithNext;
+ segment_vec_t mSegments;
+ };
+
+ struct compare_segment_end
+ {
+ bool operator()(const LLTextSegmentPtr& a, const LLTextSegmentPtr& b) const;
+ };
+ typedef std::multiset<LLTextSegmentPtr, compare_segment_end> segment_set_t;
+
+ // protected member variables
+ // List of offsets and segment index of the start of each line. Always has at least one node (0).
+ struct line_info
+ {
+ line_info(S32 index_start, S32 index_end, LLRect rect, S32 line_num);
+ S32 mDocIndexStart;
+ S32 mDocIndexEnd;
+ LLRect mRect;
+ S32 mLineNum; // actual line count (ignoring soft newlines due to word wrap)
+ };
+ typedef std::vector<line_info> line_list_t;
+
+ // member functions
+ LLTextBase(const Params &p);
+ virtual ~LLTextBase();
+ void initFromParams(const Params& p);
+ virtual void onValueChange(S32 start, S32 end);
+
+ // draw methods
+ void drawSelectionBackground(); // draws the black box behind the selected text
+ void drawCursor();
+ void drawText();
+
+ // modify contents
+ S32 insertStringNoUndo(S32 pos, const LLWString &wstr, segment_vec_t* segments = NULL); // returns num of chars actually inserted
+ S32 removeStringNoUndo(S32 pos, S32 length);
+ S32 overwriteCharNoUndo(S32 pos, llwchar wc);
+ void appendAndHighlightText(const std::string &new_text, bool prepend_newline, S32 highlight_part, const LLStyle::Params& stylep);
+
+
+ // manage segments
+ void getSegmentAndOffset( S32 startpos, segment_set_t::const_iterator* seg_iter, S32* offsetp ) const;
+ void getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg_iter, S32* offsetp );
+ LLTextSegmentPtr getSegmentAtLocalPos( S32 x, S32 y );
+ segment_set_t::iterator getSegIterContaining(S32 index);
+ segment_set_t::const_iterator getSegIterContaining(S32 index) const;
+ void clearSegments();
+ void createDefaultSegment();
+ virtual void updateSegments();
+ void insertSegment(LLTextSegmentPtr segment_to_insert);
+
+ // manage lines
+ S32 getLineStart( S32 line ) const;
+ S32 getLineEnd( S32 line ) const;
+ S32 getLineNumFromDocIndex( S32 doc_index, bool include_wordwrap = true) const;
+ S32 getLineOffsetFromDocIndex( S32 doc_index, bool include_wordwrap = true) const;
+ S32 getFirstVisibleLine() const;
+ std::pair<S32, S32> getVisibleLines(bool fully_visible = false);
+ S32 getLeftOffset(S32 width);
+ void reflow(S32 start_index = 0);
+
+ // cursor
+ void updateCursorXPos();
+ void setCursorAtLocalPos( S32 local_x, S32 local_y, bool round, bool keep_cursor_offset=false );
+ S32 getEditableIndex(S32 index, bool increasing_direction); // constraint cursor to editable segments of document
+ void resetCursorBlink() { mCursorBlinkTimer.reset(); }
+ void updateScrollFromCursor();
+
+ // text selection
+ bool hasSelection() const { return (mSelectionStart !=mSelectionEnd); }
+ void startSelection();
+ void endSelection();
+
+ // misc
+ void updateRects();
+ void needsScroll() { mScrollNeeded = TRUE; }
+ void replaceUrlLabel(const std::string &url, const std::string &label);
+
+protected:
+ // text segmentation and flow
+ segment_set_t mSegments;
+ line_list_t mLineInfoList;
+ LLRect mVisibleTextRect; // The rect in which text is drawn. Excludes borders.
+ LLRect mTextBoundingRect;
+
+ // colors
+ LLUIColor mCursorColor;
+ LLUIColor mFgColor;
+ LLUIColor mReadOnlyFgColor;
+ LLUIColor mWriteableBgColor;
+ LLUIColor mReadOnlyBgColor;
+ LLUIColor mFocusBgColor;
+
+ // cursor
+ S32 mCursorPos; // I-beam is just after the mCursorPos-th character.
+ S32 mDesiredXPixel; // X pixel position where the user wants the cursor to be
+ LLFrameTimer mCursorBlinkTimer; // timer that controls cursor blinking
+
+ // selection
+ S32 mSelectionStart;
+ S32 mSelectionEnd;
+
+ BOOL mIsSelecting; // Are we in the middle of a drag-select?
+
+ // configuration
+ S32 mHPad; // padding on left of text
+ S32 mVPad; // padding above text
+ LLFontGL::HAlign mHAlign;
+ F32 mLineSpacingMult; // multiple of line height used as space for a single line of text (e.g. 1.5 to get 50% padding)
+ S32 mLineSpacingPixels; // padding between lines
+ const LLFontGL* mDefaultFont; // font that is used when none specified
+ LLFontGL::ShadowType mFontShadow;
+ bool mBorderVisible;
+ bool mParseHTML; // make URLs interactive
+ bool mParseHighlights; // highlight user-defined keywords
+ bool mWordWrap;
+ bool mUseEllipses;
+ bool mTrackEnd; // if true, keeps scroll position at end of document during resize
+ bool mReadOnly;
+ bool mBGVisible; // render background?
+ bool mClipPartial; // false if we show lines that are partially inside bounding rect
+ S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes
+
+ // support widgets
+ LLContextMenu* mPopupMenu;
+ LLView* mDocumentView;
+ class LLScrollContainer* mScroller;
+
+ // transient state
+ bool mReflowNeeded; // need to reflow text because of change to text contents or display region
+ bool mScrollNeeded; // need to change scroll region because of change to cursor position
+ S32 mScrollIndex; // index of first character to keep visible in scroll region
+
+};
+
+///
+/// A text segment is used to specify a subsection of a text string
+/// that should be formatted differently, such as a hyperlink. It
+/// includes a start/end offset from the start of the string, a
+/// style to render with, an optional tooltip, etc.
+///
+class LLTextSegment : public LLRefCount, public LLMouseHandler
+{
+public:
+ LLTextSegment(S32 start, S32 end) : mStart(start), mEnd(end){};
+ virtual ~LLTextSegment();
+
+ virtual bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const;
+ virtual S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const;
+ virtual S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;
+ virtual void updateLayout(const class LLTextBase& editor);
+ virtual F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect);
+ virtual bool canEdit() const;
+ virtual void unlinkFromDocument(class LLTextBase* editor);
+ virtual void linkToDocument(class LLTextBase* editor);
+
+ virtual const LLColor4& getColor() const;
+ virtual void setColor(const LLColor4 &color);
+ virtual const LLStyleSP getStyle() const;
+ virtual void setStyle(const LLStyleSP &style);
+ virtual void setToken( LLKeywordToken* token );
+ virtual LLKeywordToken* getToken() const;
+ virtual void setToolTip(const std::string& tooltip);
+ virtual void dump() const;
+
+ // LLMouseHandler interface
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMiddleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
+ /*virtual*/ std::string getName() const;
+ /*virtual*/ void onMouseCaptureLost();
+ /*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const;
+ /*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const;
+ /*virtual*/ BOOL hasMouseCapture();
+
+ S32 getStart() const { return mStart; }
+ void setStart(S32 start) { mStart = start; }
+ S32 getEnd() const { return mEnd; }
+ void setEnd( S32 end ) { mEnd = end; }
+
+protected:
+ S32 mStart;
+ S32 mEnd;
+};
+
+class LLNormalTextSegment : public LLTextSegment
+{
+public:
+ LLNormalTextSegment( const LLStyleSP& style, S32 start, S32 end, LLTextBase& editor );
+ LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible = TRUE);
+ ~LLNormalTextSegment();
+
+ /*virtual*/ bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const;
+ /*virtual*/ S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const;
+ /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;
+ /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect);
+ /*virtual*/ bool canEdit() const { return true; }
+ /*virtual*/ const LLColor4& getColor() const { return mStyle->getColor(); }
+ /*virtual*/ void setColor(const LLColor4 &color) { mStyle->setColor(color); }
+ /*virtual*/ const LLStyleSP getStyle() const { return mStyle; }
+ /*virtual*/ void setStyle(const LLStyleSP &style) { mStyle = style; }
+ /*virtual*/ void setToken( LLKeywordToken* token ) { mToken = token; }
+ /*virtual*/ LLKeywordToken* getToken() const { return mToken; }
+ /*virtual*/ BOOL getToolTip( std::string& msg ) const;
+ /*virtual*/ void setToolTip(const std::string& tooltip);
+ /*virtual*/ void dump() const;
+
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
+
+protected:
+ F32 drawClippedSegment(S32 seg_start, S32 seg_end, S32 selection_start, S32 selection_end, LLRect rect);
+
+protected:
+ class LLTextBase& mEditor;
+ LLStyleSP mStyle;
+ S32 mFontHeight;
+ LLKeywordToken* mToken;
+ std::string mTooltip;
+ boost::signals2::connection mImageLoadedConnection;
+};
+
+class LLIndexSegment : public LLTextSegment
+{
+public:
+ LLIndexSegment(S32 pos) : LLTextSegment(pos, pos) {}
+};
+
+class LLInlineViewSegment : public LLTextSegment
+{
+public:
+ struct Params : public LLInitParam::Block<Params>
+ {
+ Mandatory<LLView*> view;
+ Optional<bool> force_newline;
+ Optional<S32> left_pad,
+ right_pad,
+ bottom_pad,
+ top_pad;
+ };
+
+ LLInlineViewSegment(const Params& p, S32 start, S32 end);
+ ~LLInlineViewSegment();
+ /*virtual*/ bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const;
+ /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;
+ /*virtual*/ void updateLayout(const class LLTextBase& editor);
+ /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect);
+ /*virtual*/ bool canEdit() const { return false; }
+ /*virtual*/ void unlinkFromDocument(class LLTextBase* editor);
+ /*virtual*/ void linkToDocument(class LLTextBase* editor);
+
+private:
+ S32 mLeftPad;
+ S32 mRightPad;
+ S32 mTopPad;
+ S32 mBottomPad;
+ LLView* mView;
+ bool mForceNewLine;
+};
+
+
+#endif
diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp
index 89893bcf8d..a1f5b5726b 100644
--- a/indra/llui/lltextbox.cpp
+++ b/indra/llui/lltextbox.cpp
@@ -31,435 +31,144 @@
*/
#include "linden_common.h"
+
+#define LLTEXTBOX_CPP
#include "lltextbox.h"
+
#include "lluictrlfactory.h"
#include "llfocusmgr.h"
#include "llwindow.h"
+#include "llurlregistry.h"
+#include "llstyle.h"
-static LLRegisterWidget<LLTextBox> r("text");
+static LLDefaultChildRegistry::Register<LLTextBox> r("text");
-LLTextBox::LLTextBox(const std::string& name, const LLRect& rect, const std::string& text,
- const LLFontGL* font, BOOL mouse_opaque)
-: LLUICtrl(name, rect, mouse_opaque, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP ),
- mFontGL(font ? font : LLFontGL::getFontSansSerifSmall())
-{
- initDefaults();
- setText( text );
- setTabStop(FALSE);
-}
+// Compiler optimization, generate extern template
+template class LLTextBox* LLView::getChild<class LLTextBox>(
+ const std::string& name, BOOL recurse) const;
-LLTextBox::LLTextBox(const std::string& name, const std::string& text, F32 max_width,
- const LLFontGL* font, BOOL mouse_opaque) :
- LLUICtrl(name, LLRect(0, 0, 1, 1), mouse_opaque, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP),
- mFontGL(font ? font : LLFontGL::getFontSansSerifSmall())
-{
- initDefaults();
- setWrappedText(text, max_width);
- reshapeToFitText();
- setTabStop(FALSE);
-}
+LLTextBox::LLTextBox(const LLTextBox::Params& p)
+: LLTextBase(p),
+ mClickedCallback(NULL)
+{}
-LLTextBox::LLTextBox(const std::string& name_and_label, const LLRect& rect) :
- LLUICtrl(name_and_label, rect, TRUE, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP),
- mFontGL(LLFontGL::getFontSansSerifSmall())
-{
- initDefaults();
- setText( name_and_label );
- setTabStop(FALSE);
-}
-
-void LLTextBox::initDefaults()
-{
- mTextColor = LLUI::sColorsGroup->getColor("LabelTextColor");
- mDisabledColor = LLUI::sColorsGroup->getColor("LabelDisabledColor");
- mBackgroundColor = LLUI::sColorsGroup->getColor("DefaultBackgroundColor");
- mBorderColor = LLUI::sColorsGroup->getColor("DefaultHighlightLight");
- mHoverColor = LLUI::sColorsGroup->getColor( "LabelSelectedColor" );
- mHoverActive = FALSE;
- mHasHover = FALSE;
- mBackgroundVisible = FALSE;
- mBorderVisible = FALSE;
- mFontStyle = LLFontGL::DROP_SHADOW_SOFT;
- mBorderDropShadowVisible = FALSE;
- mUseEllipses = FALSE;
- mLineSpacing = 0;
- mHPad = 0;
- mVPad = 0;
- mHAlign = LLFontGL::LEFT;
- mVAlign = LLFontGL::TOP;
- mClickedCallback = NULL;
- mCallbackUserData = NULL;
-}
+LLTextBox::~LLTextBox()
+{}
BOOL LLTextBox::handleMouseDown(S32 x, S32 y, MASK mask)
{
- BOOL handled = FALSE;
+ BOOL handled = LLTextBase::handleMouseDown(x, y, mask);
- // HACK: Only do this if there actually is a click callback, so that
- // overly large text boxes in the older UI won't start eating clicks.
- if (mClickedCallback)
+ if (getSoundFlags() & MOUSE_DOWN)
{
- handled = TRUE;
+ make_ui_sound("UISndClick");
+ }
+ if (!handled && mClickedCallback)
+ {
// Route future Mouse messages here preemptively. (Release on mouse up.)
gFocusMgr.setMouseCapture( this );
-
- if (getSoundFlags() & MOUSE_DOWN)
- {
- make_ui_sound("UISndClick");
- }
+
+ handled = TRUE;
}
return handled;
}
-
BOOL LLTextBox::handleMouseUp(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
- // We only handle the click if the click both started and ended within us
-
- // HACK: Only do this if there actually is a click callback, so that
- // overly large text boxes in the older UI won't start eating clicks.
- if (mClickedCallback
- && hasMouseCapture())
+ if (getSoundFlags() & MOUSE_UP)
{
- handled = TRUE;
+ make_ui_sound("UISndClickRelease");
+ }
+ // We only handle the click if the click both started and ended within us
+ if (hasMouseCapture())
+ {
// Release the mouse
gFocusMgr.setMouseCapture( NULL );
- if (getSoundFlags() & MOUSE_UP)
+ // DO THIS AT THE VERY END to allow the button to be destroyed
+ // as a result of being clicked. If mouseup in the widget,
+ // it's been clicked
+ if (mClickedCallback && !handled)
{
- make_ui_sound("UISndClickRelease");
- }
-
- // DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked.
- // If mouseup in the widget, it's been clicked
- if (mClickedCallback)
- {
- (*mClickedCallback)( mCallbackUserData );
+ mClickedCallback();
+ handled = TRUE;
}
}
+ else
+ {
+ handled = LLTextBase::handleMouseUp(x, y, mask);
+ }
return handled;
}
BOOL LLTextBox::handleHover(S32 x, S32 y, MASK mask)
{
- BOOL handled = LLView::handleHover(x,y,mask);
- if(mHoverActive)
+ BOOL handled = LLTextBase::handleHover(x, y, mask);
+ if (!handled && mClickedCallback)
{
- mHasHover = TRUE; // This should be set every frame during a hover.
- getWindow()->setCursor(UI_CURSOR_ARROW);
+ // Clickable text boxes change the cursor to a hand
+ LLUI::getWindow()->setCursor(UI_CURSOR_HAND);
+ return TRUE;
}
-
- return (handled || mHasHover);
+ return handled;
}
-void LLTextBox::setText(const LLStringExplicit& text)
+void LLTextBox::setText(const LLStringExplicit& text , const LLStyle::Params& input_params )
{
+ // does string argument insertion
mText.assign(text);
- setLineLengths();
-}
-
-void LLTextBox::setLineLengths()
-{
- mLineLengthList.clear();
- std::string::size_type cur = 0;
- std::string::size_type len = mText.getWString().size();
-
- while (cur < len)
- {
- std::string::size_type end = mText.getWString().find('\n', cur);
- std::string::size_type runLen;
-
- if (end == std::string::npos)
- {
- runLen = len - cur;
- cur = len;
- }
- else
- {
- runLen = end - cur;
- cur = end + 1; // skip the new line character
- }
-
- mLineLengthList.push_back( (S32)runLen );
- }
+ LLTextBase::setText(mText.getString(), input_params );
}
-void LLTextBox::setWrappedText(const LLStringExplicit& in_text, F32 max_width)
+void LLTextBox::setClickedCallback( boost::function<void (void*)> cb, void* userdata /*= NULL */ )
{
- if (max_width < 0.0)
- {
- max_width = (F32)getRect().getWidth();
- }
-
- LLWString wtext = utf8str_to_wstring(in_text);
- LLWString final_wtext;
-
- LLWString::size_type cur = 0;;
- LLWString::size_type len = wtext.size();
-
- while (cur < len)
- {
- LLWString::size_type end = wtext.find('\n', cur);
- if (end == LLWString::npos)
- {
- end = len;
- }
-
- LLWString::size_type runLen = end - cur;
- if (runLen > 0)
- {
- LLWString run(wtext, cur, runLen);
- LLWString::size_type useLen =
- mFontGL->maxDrawableChars(run.c_str(), max_width, runLen, TRUE);
-
- final_wtext.append(wtext, cur, useLen);
- cur += useLen;
- }
-
- if (cur < len)
- {
- if (wtext[cur] == '\n')
- {
- cur += 1;
- }
- final_wtext += '\n';
- }
- }
-
- std::string final_text = wstring_to_utf8str(final_wtext);
- setText(final_text);
+ mClickedCallback = boost::bind(cb, userdata);
}
S32 LLTextBox::getTextPixelWidth()
{
- S32 max_line_width = 0;
- if( mLineLengthList.size() > 0 )
- {
- S32 cur_pos = 0;
- for (std::vector<S32>::iterator iter = mLineLengthList.begin();
- iter != mLineLengthList.end(); ++iter)
- {
- S32 line_length = *iter;
- S32 line_width = mFontGL->getWidth( mText.getWString().c_str(), cur_pos, line_length );
- if( line_width > max_line_width )
- {
- max_line_width = line_width;
- }
- cur_pos += line_length+1;
- }
- }
- else
- {
- max_line_width = mFontGL->getWidth(mText.getWString().c_str());
- }
- return max_line_width;
+ return getTextBoundingRect().getWidth();
}
S32 LLTextBox::getTextPixelHeight()
{
- S32 num_lines = mLineLengthList.size();
- if( num_lines < 1 )
- {
- num_lines = 1;
- }
- return (S32)(num_lines * mFontGL->getLineHeight());
+ return getTextBoundingRect().getHeight();
}
-BOOL LLTextBox::setTextArg( const std::string& key, const LLStringExplicit& text )
+LLSD LLTextBox::getValue() const
{
- mText.setArg(key, text);
- setLineLengths();
- return TRUE;
+ return LLSD(getText());
}
-void LLTextBox::draw()
+BOOL LLTextBox::setTextArg( const std::string& key, const LLStringExplicit& text )
{
- if (mBorderVisible)
- {
- gl_rect_2d_offset_local(getLocalRect(), 2, FALSE);
- }
-
- if( mBorderDropShadowVisible )
- {
- static LLColor4 color_drop_shadow = LLUI::sColorsGroup->getColor("ColorDropShadow");
- static S32 drop_shadow_tooltip = LLUI::sConfigGroup->getS32("DropShadowTooltip");
- gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0,
- color_drop_shadow, drop_shadow_tooltip);
- }
-
- if (mBackgroundVisible)
- {
- LLRect r( 0, getRect().getHeight(), getRect().getWidth(), 0 );
- gl_rect_2d( r, mBackgroundColor );
- }
-
- S32 text_x = 0;
- switch( mHAlign )
- {
- case LLFontGL::LEFT:
- text_x = mHPad;
- break;
- case LLFontGL::HCENTER:
- text_x = getRect().getWidth() / 2;
- break;
- case LLFontGL::RIGHT:
- text_x = getRect().getWidth() - mHPad;
- break;
- }
-
- S32 text_y = getRect().getHeight() - mVPad;
-
- if ( getEnabled() )
- {
- if(mHasHover)
- {
- drawText( text_x, text_y, mHoverColor );
- }
- else
- {
- drawText( text_x, text_y, mTextColor );
- }
- }
- else
- {
- drawText( text_x, text_y, mDisabledColor );
- }
-
- if (sDebugRects)
- {
- drawDebugRect();
- }
-
- mHasHover = FALSE; // This is reset every frame.
-}
+ mText.setArg(key, text);
+ LLTextBase::setText(mText.getString());
-void LLTextBox::reshape(S32 width, S32 height, BOOL called_from_parent)
-{
- // reparse line lengths
- setLineLengths();
- LLView::reshape(width, height, called_from_parent);
+ return TRUE;
}
-void LLTextBox::drawText( S32 x, S32 y, const LLColor4& color )
-{
- if( mLineLengthList.empty() )
- {
- mFontGL->render(mText.getWString(), 0, (F32)x, (F32)y, color,
- mHAlign, mVAlign,
- mFontStyle,
- S32_MAX, getRect().getWidth(), NULL, TRUE, mUseEllipses);
- }
- else
- {
- S32 cur_pos = 0;
- for (std::vector<S32>::iterator iter = mLineLengthList.begin();
- iter != mLineLengthList.end(); ++iter)
- {
- S32 line_length = *iter;
- mFontGL->render(mText.getWString(), cur_pos, (F32)x, (F32)y, color,
- mHAlign, mVAlign,
- mFontStyle,
- line_length, getRect().getWidth(), NULL, TRUE, mUseEllipses );
- cur_pos += line_length + 1;
- y -= llfloor(mFontGL->getLineHeight()) + mLineSpacing;
- }
- }
-}
void LLTextBox::reshapeToFitText()
{
+ reflow();
+
S32 width = getTextPixelWidth();
S32 height = getTextPixelHeight();
- reshape( width + 2 * mHPad, height + 2 * mVPad );
+ reshape( width + 2 * mHPad, height + 2 * mVPad, FALSE );
}
-// virtual
-LLXMLNodePtr LLTextBox::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLUICtrl::getXML();
-
- // Attributes
- node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mFontGL));
- node->createChild("halign", TRUE)->setStringValue(LLFontGL::nameFromHAlign(mHAlign));
- addColorXML(node, mTextColor, "text_color", "LabelTextColor");
- addColorXML(node, mDisabledColor, "disabled_color", "LabelDisabledColor");
- addColorXML(node, mBackgroundColor, "bg_color", "DefaultBackgroundColor");
- addColorXML(node, mBorderColor, "border_color", "DefaultHighlightLight");
- node->createChild("bg_visible", TRUE)->setBoolValue(mBackgroundVisible);
- node->createChild("border_visible", TRUE)->setBoolValue(mBorderVisible);
- node->createChild("border_drop_shadow_visible", TRUE)->setBoolValue(mBorderDropShadowVisible);
- node->createChild("h_pad", TRUE)->setIntValue(mHPad);
- node->createChild("v_pad", TRUE)->setIntValue(mVPad);
-
- // Contents
- node->setStringValue(mText);
-
- return node;
-}
-// static
-LLView* LLTextBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
+void LLTextBox::onUrlLabelUpdated(const std::string &url, const std::string &label)
{
- std::string name("text_box");
- node->getAttributeString("name", name);
- LLFontGL* font = LLView::selectFont(node);
-
- std::string text = node->getTextContents();
-
- LLTextBox* text_box = new LLTextBox(name,
- LLRect(),
- text,
- font,
- FALSE);
-
-
- LLFontGL::HAlign halign = LLView::selectFontHAlign(node);
- text_box->setHAlign(halign);
-
- text_box->initFromXML(node, parent);
-
- node->getAttributeS32("line_spacing", text_box->mLineSpacing);
-
- std::string font_style;
- if (node->getAttributeString("font-style", font_style))
- {
- text_box->mFontStyle = LLFontGL::getStyleFromString(font_style);
- }
-
- BOOL mouse_opaque = text_box->getMouseOpaque();
- if (node->getAttributeBOOL("mouse_opaque", mouse_opaque))
- {
- text_box->setMouseOpaque(mouse_opaque);
- }
-
- if(node->hasAttribute("text_color"))
- {
- LLColor4 color;
- LLUICtrlFactory::getAttributeColor(node, "text_color", color);
- text_box->setColor(color);
- }
-
- if(node->hasAttribute("hover_color"))
- {
- LLColor4 color;
- LLUICtrlFactory::getAttributeColor(node, "hover_color", color);
- text_box->setHoverColor(color);
- text_box->setHoverActive(true);
- }
-
- BOOL hover_active = FALSE;
- if(node->getAttributeBOOL("hover", hover_active))
- {
- text_box->setHoverActive(hover_active);
- }
-
- return text_box;
+ needsReflow();
}
+
diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h
index 07a6aa3622..3a045534d3 100644
--- a/indra/llui/lltextbox.h
+++ b/indra/llui/lltextbox.h
@@ -33,110 +33,56 @@
#ifndef LL_LLTEXTBOX_H
#define LL_LLTEXTBOX_H
-#include "lluictrl.h"
-#include "v4color.h"
-#include "llstring.h"
#include "lluistring.h"
+#include "lltextbase.h"
-
-class LLTextBox
-: public LLUICtrl
+class LLTextBox :
+ public LLTextBase
{
public:
- // By default, follows top and left and is mouse-opaque.
- // If no text, text = name.
- // If no font, uses default system font.
- LLTextBox(const std::string& name, const LLRect& rect, const std::string& text,
- const LLFontGL* font = NULL, BOOL mouse_opaque = TRUE );
-
- // Construct a textbox which handles word wrapping for us.
- LLTextBox(const std::string& name, const std::string& text, F32 max_width = 200,
- const LLFontGL* font = NULL, BOOL mouse_opaque = TRUE );
-
- // "Simple" constructors for text boxes that have the same name and label *TO BE DEPRECATED*
- LLTextBox(const std::string& name_and_label, const LLRect& rect);
-
- // Consolidate common member initialization
- // 20+ initializers times 3+ constructors is unmaintainable.
- void initDefaults();
-
- virtual ~LLTextBox() {}
-
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory);
-
- virtual void draw();
- virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+ // *TODO: Add callback to Params
+ typedef boost::function<void (void)> callback_t;
+
+ struct Params : public LLInitParam::Block<Params, LLTextBase::Params>
+ {};
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
+protected:
+ LLTextBox(const Params&);
+ friend class LLUICtrlFactory;
- void setColor( const LLColor4& c ) { mTextColor = c; }
- void setDisabledColor( const LLColor4& c) { mDisabledColor = c; }
- void setBackgroundColor( const LLColor4& c) { mBackgroundColor = c; }
- void setBorderColor( const LLColor4& c) { mBorderColor = c; }
+public:
+ virtual ~LLTextBox();
- void setHoverColor( const LLColor4& c ) { mHoverColor = c; }
- void setHoverActive( BOOL active ) { mHoverActive = active; }
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
- void setText( const LLStringExplicit& text );
- void setWrappedText(const LLStringExplicit& text, F32 max_width = -1.0); // -1 means use existing control width
- void setUseEllipses( BOOL use_ellipses ) { mUseEllipses = use_ellipses; }
+ /*virtual*/ void setText( const LLStringExplicit& text, const LLStyle::Params& input_params = LLStyle::Params() );
- void setBackgroundVisible(BOOL visible) { mBackgroundVisible = visible; }
- void setBorderVisible(BOOL visible) { mBorderVisible = visible; }
- void setFontStyle(U8 style) { mFontStyle = style; }
- void setBorderDropshadowVisible(BOOL visible){ mBorderDropShadowVisible = visible; }
- void setHPad(S32 pixels) { mHPad = pixels; }
- void setVPad(S32 pixels) { mVPad = pixels; }
void setRightAlign() { mHAlign = LLFontGL::RIGHT; }
void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; }
- void setClickedCallback( void (*cb)(void *data), void* data = NULL ){ mClickedCallback = cb; mCallbackUserData = data; } // mouse down and up within button
-
- const LLFontGL* getFont() const { return mFontGL; }
+ void setClickedCallback( boost::function<void (void*)> cb, void* userdata = NULL );
void reshapeToFitText();
- const std::string& getText() const { return mText.getString(); }
S32 getTextPixelWidth();
S32 getTextPixelHeight();
- virtual void setValue(const LLSD& value ) { setText(value.asString()); }
- virtual LLSD getValue() const { return LLSD(getText()); }
- virtual BOOL setTextArg( const std::string& key, const LLStringExplicit& text );
-
-private:
- void setLineLengths();
- void drawText(S32 x, S32 y, const LLColor4& color );
+ /*virtual*/ LLSD getValue() const;
+ /*virtual*/ BOOL setTextArg( const std::string& key, const LLStringExplicit& text );
- LLUIString mText;
- const LLFontGL* mFontGL;
- LLColor4 mTextColor;
- LLColor4 mDisabledColor;
- LLColor4 mBackgroundColor;
- LLColor4 mBorderColor;
- LLColor4 mHoverColor;
-
- BOOL mHoverActive;
- BOOL mHasHover;
- BOOL mBackgroundVisible;
- BOOL mBorderVisible;
-
- U8 mFontStyle; // style bit flags for font
- BOOL mBorderDropShadowVisible;
- BOOL mUseEllipses;
+protected:
+ void onUrlLabelUpdated(const std::string &url, const std::string &label);
- S32 mLineSpacing;
-
- S32 mHPad;
- S32 mVPad;
- LLFontGL::HAlign mHAlign;
- LLFontGL::VAlign mVAlign;
-
- std::vector<S32> mLineLengthList;
- void (*mClickedCallback)(void* data );
- void* mCallbackUserData;
+ LLUIString mText;
+ callback_t mClickedCallback;
};
+// Build time optimization, generate once in .cpp file
+#ifndef LLTEXTBOX_CPP
+extern template class LLTextBox* LLView::getChild<class LLTextBox>(
+ const std::string& name, BOOL recurse) const;
+#endif
+
#endif
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 5e54c7a307..f2c3879a6c 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -1,6 +1,5 @@
/**
* @file lltexteditor.cpp
- * @brief LLTextEditor base class
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
@@ -34,9 +33,13 @@
#include "linden_common.h"
+#define LLTEXTEDITOR_CPP
#include "lltexteditor.h"
+#include "llfontfreetype.h" // for LLFontFreetype::FIRST_CHAR
#include "llfontgl.h"
+#include "llgl.h" // LLGLSUIDefault()
+#include "lllocalcliprect.h"
#include "llrender.h"
#include "llui.h"
#include "lluictrlfactory.h"
@@ -45,7 +48,6 @@
#include "lltimer.h"
#include "llmath.h"
-#include "audioengine.h"
#include "llclipboard.h"
#include "llscrollbar.h"
#include "llstl.h"
@@ -55,70 +57,56 @@
#include "llundo.h"
#include "llviewborder.h"
#include "llcontrol.h"
-#include "llimagegl.h"
#include "llwindow.h"
#include "lltextparser.h"
+#include "llscrollcontainer.h"
+#include "llpanel.h"
+#include "llurlregistry.h"
+#include "lltooltip.h"
+#include "llmenugl.h"
+
#include <queue>
+#include "llcombobox.h"
//
// Globals
//
-static LLRegisterWidget<LLTextEditor> r("simple_text_editor");
+static LLDefaultChildRegistry::Register<LLTextEditor> r("simple_text_editor");
-BOOL gDebugTextEditorTips = FALSE;
+// Compiler optimization, generate extern template
+template class LLTextEditor* LLView::getChild<class LLTextEditor>(
+ const std::string& name, BOOL recurse) const;
//
// Constants
//
-const S32 UI_TEXTEDITOR_BUFFER_BLOCK_SIZE = 512;
-const S32 UI_TEXTEDITOR_BORDER = 1;
-const S32 UI_TEXTEDITOR_H_PAD = 4;
-const S32 UI_TEXTEDITOR_V_PAD_TOP = 4;
const S32 UI_TEXTEDITOR_LINE_NUMBER_MARGIN = 32;
const S32 UI_TEXTEDITOR_LINE_NUMBER_DIGITS = 4;
-const F32 CURSOR_FLASH_DELAY = 1.0f; // in seconds
-const S32 CURSOR_THICKNESS = 2;
const S32 SPACES_PER_TAB = 4;
-const F32 PREEDIT_MARKER_BRIGHTNESS = 0.4f;
-const S32 PREEDIT_MARKER_GAP = 1;
-const S32 PREEDIT_MARKER_POSITION = 2;
-const S32 PREEDIT_MARKER_THICKNESS = 1;
-const F32 PREEDIT_STANDOUT_BRIGHTNESS = 0.6f;
-const S32 PREEDIT_STANDOUT_GAP = 1;
-const S32 PREEDIT_STANDOUT_POSITION = 2;
-const S32 PREEDIT_STANDOUT_THICKNESS = 2;
-
-
-LLColor4 LLTextEditor::mLinkColor = LLColor4::blue;
-void (* LLTextEditor::mURLcallback)(const std::string&) = NULL;
-bool (* LLTextEditor::mSecondlifeURLcallback)(const std::string&) = NULL;
-bool (* LLTextEditor::mSecondlifeURLcallbackRightClick)(const std::string&) = NULL;
-
-
///////////////////////////////////////////////////////////////////
-class LLTextEditor::LLTextCmdInsert : public LLTextEditor::LLTextCmd
+class LLTextEditor::TextCmdInsert : public LLTextBase::TextCmd
{
public:
- LLTextCmdInsert(S32 pos, BOOL group_with_next, const LLWString &ws)
- : LLTextCmd(pos, group_with_next), mWString(ws)
+ TextCmdInsert(S32 pos, BOOL group_with_next, const LLWString &ws, LLTextSegmentPtr segment)
+ : TextCmd(pos, group_with_next, segment), mWString(ws)
{
}
- virtual ~LLTextCmdInsert() {}
- virtual BOOL execute( LLTextEditor* editor, S32* delta )
+ virtual ~TextCmdInsert() {}
+ virtual BOOL execute( LLTextBase* editor, S32* delta )
{
*delta = insert(editor, getPosition(), mWString );
LLWStringUtil::truncate(mWString, *delta);
//mWString = wstring_truncate(mWString, *delta);
return (*delta != 0);
}
- virtual S32 undo( LLTextEditor* editor )
+ virtual S32 undo( LLTextBase* editor )
{
remove(editor, getPosition(), mWString.length() );
return getPosition();
}
- virtual S32 redo( LLTextEditor* editor )
+ virtual S32 redo( LLTextBase* editor )
{
insert(editor, getPosition(), mWString );
return getPosition() + mWString.length();
@@ -129,11 +117,11 @@ private:
};
///////////////////////////////////////////////////////////////////
-class LLTextEditor::LLTextCmdAddChar : public LLTextEditor::LLTextCmd
+class LLTextEditor::TextCmdAddChar : public LLTextBase::TextCmd
{
public:
- LLTextCmdAddChar( S32 pos, BOOL group_with_next, llwchar wc)
- : LLTextCmd(pos, group_with_next), mWString(1, wc), mBlockExtensions(FALSE)
+ TextCmdAddChar( S32 pos, BOOL group_with_next, llwchar wc, LLTextSegmentPtr segment)
+ : TextCmd(pos, group_with_next, segment), mWString(1, wc), mBlockExtensions(FALSE)
{
}
virtual void blockExtensions()
@@ -142,16 +130,19 @@ public:
}
virtual BOOL canExtend(S32 pos) const
{
+ // cannot extend text with custom segments
+ if (!mSegments.empty()) return FALSE;
+
return !mBlockExtensions && (pos == getPosition() + (S32)mWString.length());
}
- virtual BOOL execute( LLTextEditor* editor, S32* delta )
+ virtual BOOL execute( LLTextBase* editor, S32* delta )
{
*delta = insert(editor, getPosition(), mWString);
LLWStringUtil::truncate(mWString, *delta);
//mWString = wstring_truncate(mWString, *delta);
return (*delta != 0);
}
- virtual BOOL extendAndExecute( LLTextEditor* editor, S32 pos, llwchar wc, S32* delta )
+ virtual BOOL extendAndExecute( LLTextBase* editor, S32 pos, llwchar wc, S32* delta )
{
LLWString ws;
ws += wc;
@@ -163,12 +154,12 @@ public:
}
return (*delta != 0);
}
- virtual S32 undo( LLTextEditor* editor )
+ virtual S32 undo( LLTextBase* editor )
{
remove(editor, getPosition(), mWString.length() );
return getPosition();
}
- virtual S32 redo( LLTextEditor* editor )
+ virtual S32 redo( LLTextBase* editor )
{
insert(editor, getPosition(), mWString );
return getPosition() + mWString.length();
@@ -182,25 +173,25 @@ private:
///////////////////////////////////////////////////////////////////
-class LLTextEditor::LLTextCmdOverwriteChar : public LLTextEditor::LLTextCmd
+class LLTextEditor::TextCmdOverwriteChar : public LLTextBase::TextCmd
{
public:
- LLTextCmdOverwriteChar( S32 pos, BOOL group_with_next, llwchar wc)
- : LLTextCmd(pos, group_with_next), mChar(wc), mOldChar(0) {}
+ TextCmdOverwriteChar( S32 pos, BOOL group_with_next, llwchar wc)
+ : TextCmd(pos, group_with_next), mChar(wc), mOldChar(0) {}
- virtual BOOL execute( LLTextEditor* editor, S32* delta )
+ virtual BOOL execute( LLTextBase* editor, S32* delta )
{
- mOldChar = editor->getWChar(getPosition());
+ mOldChar = editor->getWText()[getPosition()];
overwrite(editor, getPosition(), mChar);
*delta = 0;
return TRUE;
}
- virtual S32 undo( LLTextEditor* editor )
+ virtual S32 undo( LLTextBase* editor )
{
overwrite(editor, getPosition(), mOldChar);
return getPosition();
}
- virtual S32 redo( LLTextEditor* editor )
+ virtual S32 redo( LLTextBase* editor )
{
overwrite(editor, getPosition(), mChar);
return getPosition()+1;
@@ -213,25 +204,26 @@ private:
///////////////////////////////////////////////////////////////////
-class LLTextEditor::LLTextCmdRemove : public LLTextEditor::LLTextCmd
+class LLTextEditor::TextCmdRemove : public LLTextBase::TextCmd
{
public:
- LLTextCmdRemove( S32 pos, BOOL group_with_next, S32 len ) :
- LLTextCmd(pos, group_with_next), mLen(len)
+ TextCmdRemove( S32 pos, BOOL group_with_next, S32 len, segment_vec_t& segments ) :
+ TextCmd(pos, group_with_next), mLen(len)
{
+ std::swap(mSegments, segments);
}
- virtual BOOL execute( LLTextEditor* editor, S32* delta )
+ virtual BOOL execute( LLTextBase* editor, S32* delta )
{
- mWString = editor->getWSubString(getPosition(), mLen);
+ mWString = editor->getWText().substr(getPosition(), mLen);
*delta = remove(editor, getPosition(), mLen );
return (*delta != 0);
}
- virtual S32 undo( LLTextEditor* editor )
+ virtual S32 undo( LLTextBase* editor )
{
- insert(editor, getPosition(), mWString );
+ insert(editor, getPosition(), mWString);
return getPosition() + mWString.length();
}
- virtual S32 redo( LLTextEditor* editor )
+ virtual S32 redo( LLTextBase* editor )
{
remove(editor, getPosition(), mLen );
return getPosition();
@@ -243,109 +235,69 @@ private:
///////////////////////////////////////////////////////////////////
-
-LLTextEditor::LLTextEditor(
- const std::string& name,
- const LLRect& rect,
- S32 max_length, // In bytes
- const std::string &default_text,
- const LLFontGL* font,
- BOOL allow_embedded_items)
- :
- LLUICtrl( name, rect, TRUE, NULL, NULL, FOLLOWS_TOP | FOLLOWS_LEFT ),
- mTextIsUpToDate(TRUE),
- mMaxTextByteLength( max_length ),
+LLTextEditor::Params::Params()
+: default_text("default_text"),
+ embedded_items("embedded_items", false),
+ ignore_tab("ignore_tab", true),
+ handle_edit_keys_directly("handle_edit_keys_directly", false),
+ show_line_numbers("show_line_numbers", false),
+ default_color("default_color"),
+ commit_on_focus_lost("commit_on_focus_lost", false)
+{}
+
+LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
+ LLTextBase(p),
mBaseDocIsPristine(TRUE),
mPristineCmd( NULL ),
mLastCmd( NULL ),
- mCursorPos( 0 ),
- mIsSelecting( FALSE ),
- mSelectionStart( 0 ),
- mSelectionEnd( 0 ),
- mScrolledToBottom( TRUE ),
- mOnScrollEndCallback( NULL ),
- mOnScrollEndData( NULL ),
- mCursorColor( LLUI::sColorsGroup->getColor( "TextCursorColor" ) ),
- mFgColor( LLUI::sColorsGroup->getColor( "TextFgColor" ) ),
- mDefaultColor( LLUI::sColorsGroup->getColor( "TextDefaultColor" ) ),
- mReadOnlyFgColor( LLUI::sColorsGroup->getColor( "TextFgReadOnlyColor" ) ),
- mWriteableBgColor( LLUI::sColorsGroup->getColor( "TextBgWriteableColor" ) ),
- mReadOnlyBgColor( LLUI::sColorsGroup->getColor( "TextBgReadOnlyColor" ) ),
- mFocusBgColor( LLUI::sColorsGroup->getColor( "TextBgFocusColor" ) ),
- mReadOnly(FALSE),
- mWordWrap( FALSE ),
- mShowLineNumbers ( FALSE ),
- mTabsToNextField( TRUE ),
- mCommitOnFocusLost( FALSE ),
- mHideScrollbarForShortDocs( FALSE ),
- mTakesNonScrollClicks( TRUE ),
- mTrackBottom( FALSE ),
- mAllowEmbeddedItems( allow_embedded_items ),
- mAcceptCallingCardNames(FALSE),
- mHandleEditKeysDirectly( FALSE ),
+ mDefaultColor( p.default_color() ),
+ mShowLineNumbers ( p.show_line_numbers ),
+ mCommitOnFocusLost( p.commit_on_focus_lost),
+ mAllowEmbeddedItems( p.embedded_items ),
+ mHandleEditKeysDirectly( p.handle_edit_keys_directly ),
mMouseDownX(0),
mMouseDownY(0),
- mLastSelectionX(-1),
- mLastSelectionY(-1),
- mReflowNeeded(FALSE),
- mScrollNeeded(FALSE)
+ mTabsToNextField(p.ignore_tab),
+ mContextMenu(NULL)
{
+ mDefaultFont = p.font;
+
mSourceID.generate();
- // reset desired x cursor position
- mDesiredXPixel = -1;
+ //FIXME: use image?
+ LLViewBorder::Params params;
+ params.name = "text ed border";
+ params.rect = getLocalRect();
+ params.bevel_style = LLViewBorder::BEVEL_IN;
+ params.border_thickness = 1;
+ params.visible = p.border_visible;
+ mBorder = LLUICtrlFactory::create<LLViewBorder> (params);
+ addChild( mBorder );
+
+ setText(p.default_text());
- if (font)
+ if (mShowLineNumbers)
{
- mGLFont = font;
+ mHPad += UI_TEXTEDITOR_LINE_NUMBER_MARGIN;
+ updateRects();
}
- else
- {
- mGLFont = LLFontGL::getFontSansSerif();
- }
-
- updateTextRect();
-
- S32 line_height = llround( mGLFont->getLineHeight() );
- S32 page_size = mTextRect.getHeight() / line_height;
-
- // Init the scrollbar
- LLRect scroll_rect;
- scroll_rect.setOriginAndSize(
- getRect().getWidth() - SCROLLBAR_SIZE,
- 1,
- SCROLLBAR_SIZE,
- getRect().getHeight() - 1);
- S32 lines_in_doc = getLineCount();
- mScrollbar = new LLScrollbar( std::string("Scrollbar"), scroll_rect,
- LLScrollbar::VERTICAL,
- lines_in_doc,
- 0,
- page_size,
- NULL, this );
- mScrollbar->setFollowsRight();
- mScrollbar->setFollowsTop();
- mScrollbar->setFollowsBottom();
- mScrollbar->setEnabled( TRUE );
- mScrollbar->setVisible( TRUE );
- mScrollbar->setOnScrollEndCallback(mOnScrollEndCallback, mOnScrollEndData);
- addChild(mScrollbar);
-
- mBorder = new LLViewBorder( std::string("text ed border"), LLRect(0, getRect().getHeight(), getRect().getWidth(), 0), LLViewBorder::BEVEL_IN, LLViewBorder::STYLE_LINE, UI_TEXTEDITOR_BORDER );
- addChild( mBorder );
+}
- appendText(default_text, FALSE, FALSE);
-
- resetDirty(); // Update saved text state
+void LLTextEditor::initFromParams( const LLTextEditor::Params& p)
+{
+ LLTextBase::initFromParams(p);
- mParseHTML=FALSE;
- mHTML.clear();
+ if (p.commit_on_focus_lost.isProvided())
+ {
+ mCommitOnFocusLost = p.commit_on_focus_lost;
+ }
+
+ updateAllowingLanguageInput();
}
-
LLTextEditor::~LLTextEditor()
{
- gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit()
+ gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() while LLTextEditor still valid
// Route menu back to the default
if( gEditMenuHandler == this )
@@ -354,254 +306,26 @@ LLTextEditor::~LLTextEditor()
}
// Scrollbar is deleted by LLView
- mHoverSegment = NULL;
- std::for_each(mSegments.begin(), mSegments.end(), DeletePointer());
-
std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer());
-}
-
-void LLTextEditor::setTrackColor( const LLColor4& color )
-{
- mScrollbar->setTrackColor(color);
-}
-void LLTextEditor::setThumbColor( const LLColor4& color )
-{
- mScrollbar->setThumbColor(color);
-}
-
-void LLTextEditor::setHighlightColor( const LLColor4& color )
-{
- mScrollbar->setHighlightColor(color);
-}
-
-void LLTextEditor::setShadowColor( const LLColor4& color )
-{
- mScrollbar->setShadowColor(color);
-}
-
-void LLTextEditor::updateLineStartList(S32 startpos)
-{
- updateSegments();
-
- bindEmbeddedChars(mGLFont);
-
- S32 seg_num = mSegments.size();
- S32 seg_idx = 0;
- S32 seg_offset = 0;
-
- if (!mLineStartList.empty())
- {
- getSegmentAndOffset(startpos, &seg_idx, &seg_offset);
- line_info t(seg_idx, seg_offset);
- line_list_t::iterator iter = std::upper_bound(mLineStartList.begin(), mLineStartList.end(), t, line_info_compare());
- if (iter != mLineStartList.begin()) --iter;
- seg_idx = iter->mSegment;
- seg_offset = iter->mOffset;
- mLineStartList.erase(iter, mLineStartList.end());
- }
-
- while( seg_idx < seg_num )
- {
- mLineStartList.push_back(line_info(seg_idx,seg_offset));
- BOOL line_ended = FALSE;
- S32 start_x = mShowLineNumbers ? UI_TEXTEDITOR_LINE_NUMBER_MARGIN : 0;
- S32 line_width = start_x;
- while(!line_ended && seg_idx < seg_num)
- {
- LLTextSegment* segment = mSegments[seg_idx];
- S32 start_idx = segment->getStart() + seg_offset;
- S32 end_idx = start_idx;
- while (end_idx < segment->getEnd() && mWText[end_idx] != '\n')
- {
- end_idx++;
- }
- if (start_idx == end_idx)
- {
- if (end_idx >= segment->getEnd())
- {
- // empty segment
- seg_idx++;
- seg_offset = 0;
- }
- else
- {
- // empty line
- line_ended = TRUE;
- seg_offset++;
- }
- }
- else
- {
- const llwchar* str = mWText.c_str() + start_idx;
- S32 drawn = mGLFont->maxDrawableChars(str, (F32)abs(mTextRect.getWidth()) - line_width,
- end_idx - start_idx, mWordWrap, mAllowEmbeddedItems );
- if( 0 == drawn && line_width == start_x)
- {
- // If at the beginning of a line, draw at least one character, even if it doesn't all fit.
- drawn = 1;
- }
- seg_offset += drawn;
- line_width += mGLFont->getWidth(str, 0, drawn, mAllowEmbeddedItems);
- end_idx = segment->getStart() + seg_offset;
- if (end_idx < segment->getEnd())
- {
- line_ended = TRUE;
- if (mWText[end_idx] == '\n')
- {
- seg_offset++; // skip newline
- }
- }
- else
- {
- // finished with segment
- seg_idx++;
- seg_offset = 0;
- }
- }
- }
- }
-
- unbindEmbeddedChars(mGLFont);
-
- mScrollbar->setDocSize( getLineCount() );
-
- if (mHideScrollbarForShortDocs)
- {
- BOOL short_doc = (mScrollbar->getDocSize() <= mScrollbar->getPageSize());
- mScrollbar->setVisible(!short_doc);
- }
-
- // if scrolled to bottom, stay at bottom
- // unless user is selecting text
- // do this after updating page size
- if (mScrolledToBottom && mTrackBottom && !hasMouseCapture())
- {
- endOfDoc();
- }
+ // context menu is owned by menu holder, not us
+ //delete mContextMenu;
}
////////////////////////////////////////////////////////////
// LLTextEditor
// Public methods
-BOOL LLTextEditor::truncate()
-{
- BOOL did_truncate = FALSE;
-
- // First rough check - if we're less than 1/4th the size, we're OK
- if (mWText.size() >= (size_t) (mMaxTextByteLength / 4))
- {
- // Have to check actual byte size
- S32 utf8_byte_size = wstring_utf8_length( mWText );
- if ( utf8_byte_size > mMaxTextByteLength )
- {
- // Truncate safely in UTF-8
- std::string temp_utf8_text = wstring_to_utf8str( mWText );
- temp_utf8_text = utf8str_truncate( temp_utf8_text, mMaxTextByteLength );
- mWText = utf8str_to_wstring( temp_utf8_text );
- mTextIsUpToDate = FALSE;
- did_truncate = TRUE;
- }
- }
-
- return did_truncate;
-}
-
-void LLTextEditor::setText(const LLStringExplicit &utf8str)
+void LLTextEditor::setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params)
{
- // LLStringUtil::removeCRLF(utf8str);
- mUTF8Text = utf8str_removeCRLF(utf8str);
- // mUTF8Text = utf8str;
- mWText = utf8str_to_wstring(mUTF8Text);
- mTextIsUpToDate = TRUE;
-
- truncate();
blockUndo();
-
- setCursorPos(0);
deselect();
- needsReflow();
+ LLTextBase::setText(utf8str, input_params);
resetDirty();
}
-void LLTextEditor::setWText(const LLWString &wtext)
-{
- mWText = wtext;
- mUTF8Text.clear();
- mTextIsUpToDate = FALSE;
-
- truncate();
- blockUndo();
-
- setCursorPos(0);
- deselect();
-
- needsReflow();
-
- resetDirty();
-}
-
-// virtual
-void LLTextEditor::setValue(const LLSD& value)
-{
- setText(value.asString());
-}
-
-const std::string& LLTextEditor::getText() const
-{
- if (!mTextIsUpToDate)
- {
- if (mAllowEmbeddedItems)
- {
- llwarns << "getText() called on text with embedded items (not supported)" << llendl;
- }
- mUTF8Text = wstring_to_utf8str(mWText);
- mTextIsUpToDate = TRUE;
- }
- return mUTF8Text;
-}
-
-// virtual
-LLSD LLTextEditor::getValue() const
-{
- return LLSD(getText());
-}
-
-void LLTextEditor::setWordWrap(BOOL b)
-{
- mWordWrap = b;
-
- setCursorPos(0);
- deselect();
-
- needsReflow();
-}
-
-
-void LLTextEditor::setBorderVisible(BOOL b)
-{
- mBorder->setVisible(b);
-}
-
-BOOL LLTextEditor::isBorderVisible() const
-{
- return mBorder->getVisible();
-}
-
-void LLTextEditor::setHideScrollbarForShortDocs(BOOL b)
-{
- mHideScrollbarForShortDocs = b;
-
- if (mHideScrollbarForShortDocs)
- {
- BOOL short_doc = (mScrollbar->getDocSize() <= mScrollbar->getPageSize());
- mScrollbar->setVisible(!short_doc);
- }
-}
-
void LLTextEditor::selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap)
{
if (search_text_in.empty())
@@ -624,7 +348,7 @@ void LLTextEditor::selectNext(const std::string& search_text_in, BOOL case_insen
if (selected_text == search_text)
{
// We already have this word selected, we are searching for the next.
- mCursorPos += search_text.size();
+ setCursorPos(mCursorPos + search_text.size());
}
}
@@ -687,9 +411,7 @@ BOOL LLTextEditor::replaceText(const std::string& search_text_in, const std::str
void LLTextEditor::replaceTextAll(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive)
{
- S32 cur_pos = mScrollbar->getDocPos();
-
- setCursorPos(0);
+ startOfDoc();
selectNext(search_text, case_insensitive, FALSE);
BOOL replaced = TRUE;
@@ -697,24 +419,16 @@ void LLTextEditor::replaceTextAll(const std::string& search_text, const std::str
{
replaced = replaceText(search_text,replace_text, case_insensitive, FALSE);
}
-
- mScrollbar->setDocPos(cur_pos);
-}
-
-// Picks a new cursor position based on the screen size of text being drawn.
-void LLTextEditor::setCursorAtLocalPos( S32 local_x, S32 local_y, BOOL round )
-{
- setCursorPos(getCursorPosFromLocalCoord(local_x, local_y, round));
}
S32 LLTextEditor::prevWordPos(S32 cursorPos) const
{
- const LLWString& wtext = mWText;
+ LLWString wtext(getWText());
while( (cursorPos > 0) && (wtext[cursorPos-1] == ' ') )
{
cursorPos--;
}
- while( (cursorPos > 0) && isPartOfWord( wtext[cursorPos-1] ) )
+ while( (cursorPos > 0) && LLWStringUtil::isPartOfWord( wtext[cursorPos-1] ) )
{
cursorPos--;
}
@@ -723,8 +437,8 @@ S32 LLTextEditor::prevWordPos(S32 cursorPos) const
S32 LLTextEditor::nextWordPos(S32 cursorPos) const
{
- const LLWString& wtext = mWText;
- while( (cursorPos < getLength()) && isPartOfWord( wtext[cursorPos] ) )
+ LLWString wtext(getWText());
+ while( (cursorPos < getLength()) && LLWStringUtil::isPartOfWord( wtext[cursorPos] ) )
{
cursorPos++;
}
@@ -735,163 +449,45 @@ S32 LLTextEditor::nextWordPos(S32 cursorPos) const
return cursorPos;
}
-S32 LLTextEditor::getLineStart( S32 line ) const
+const LLTextSegmentPtr LLTextEditor::getPreviousSegment() const
{
- S32 num_lines = getLineCount();
- if (num_lines == 0)
- {
- return 0;
- }
-
- line = llclamp(line, 0, num_lines-1);
- S32 segidx = mLineStartList[line].mSegment;
- S32 segoffset = mLineStartList[line].mOffset;
- LLTextSegment* seg = mSegments[segidx];
- S32 res = seg->getStart() + segoffset;
- if (res > seg->getEnd()) llerrs << "wtf" << llendl;
- return res;
-}
+ // find segment index at character to left of cursor (or rightmost edge of selection)
+ segment_set_t::const_iterator it = mSegments.lower_bound(new LLIndexSegment(mCursorPos));
-// Given an offset into text (pos), find the corresponding line (from the start of the doc) and an offset into the line.
-void LLTextEditor::getLineAndOffset( S32 startpos, S32* linep, S32* offsetp ) const
-{
- if (mLineStartList.empty())
+ if (it != mSegments.end())
{
- *linep = 0;
- *offsetp = startpos;
+ return *it;
}
else
{
- S32 seg_idx, seg_offset;
- getSegmentAndOffset( startpos, &seg_idx, &seg_offset );
-
- line_info tline(seg_idx, seg_offset);
- line_list_t::const_iterator iter = std::upper_bound(mLineStartList.begin(), mLineStartList.end(), tline, line_info_compare());
- if (iter != mLineStartList.begin()) --iter;
- *linep = iter - mLineStartList.begin();
- S32 line_start = mSegments[iter->mSegment]->getStart() + iter->mOffset;
- *offsetp = startpos - line_start;
+ return LLTextSegmentPtr();
}
}
-void LLTextEditor::getSegmentAndOffset( S32 startpos, S32* segidxp, S32* offsetp ) const
-{
- if (mSegments.empty())
- {
- *segidxp = -1;
- *offsetp = startpos;
- }
-
- LLTextSegment tseg(startpos);
- segment_list_t::const_iterator seg_iter;
- seg_iter = std::upper_bound(mSegments.begin(), mSegments.end(), &tseg, LLTextSegment::compare());
- if (seg_iter != mSegments.begin()) --seg_iter;
- *segidxp = seg_iter - mSegments.begin();
- *offsetp = startpos - (*seg_iter)->getStart();
-}
-
-const LLTextSegment* LLTextEditor::getPreviousSegment() const
-{
- // find segment index at character to left of cursor (or rightmost edge of selection)
- S32 idx = llmax(0, getSegmentIdxAtOffset(mCursorPos) - 1);
- return idx >= 0 ? mSegments[idx] : NULL;
-}
-
-void LLTextEditor::getSelectedSegments(std::vector<const LLTextSegment*>& segments) const
+void LLTextEditor::getSelectedSegments(LLTextEditor::segment_vec_t& segments) const
{
S32 left = hasSelection() ? llmin(mSelectionStart, mSelectionEnd) : mCursorPos;
S32 right = hasSelection() ? llmax(mSelectionStart, mSelectionEnd) : mCursorPos;
- S32 first_idx = llmax(0, getSegmentIdxAtOffset(left));
- S32 last_idx = llmax(0, first_idx, getSegmentIdxAtOffset(right));
- for (S32 idx = first_idx; idx <= last_idx; ++idx)
- {
- segments.push_back(mSegments[idx]);
- }
+ return getSegmentsInRange(segments, left, right, true);
}
-S32 LLTextEditor::getCursorPosFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const
+void LLTextEditor::getSegmentsInRange(LLTextEditor::segment_vec_t& segments_out, S32 start, S32 end, bool include_partial) const
{
- if(mShowLineNumbers)
- {
- local_x -= UI_TEXTEDITOR_LINE_NUMBER_MARGIN;
- }
-
- // If round is true, if the position is on the right half of a character, the cursor
- // will be put to its right. If round is false, the cursor will always be put to the
- // character's left.
+ segment_set_t::const_iterator first_it = getSegIterContaining(start);
+ segment_set_t::const_iterator end_it = getSegIterContaining(end - 1);
+ if (end_it != mSegments.end()) ++end_it;
- // Figure out which line we're nearest to.
- S32 total_lines = getLineCount();
- S32 line_height = llround( mGLFont->getLineHeight() );
- S32 max_visible_lines = mTextRect.getHeight() / line_height;
- S32 scroll_lines = mScrollbar->getDocPos();
- S32 visible_lines = llmin( total_lines - scroll_lines, max_visible_lines ); // Lines currently visible
-
- //S32 line = S32( 0.5f + ((mTextRect.mTop - local_y) / mGLFont->getLineHeight()) );
- S32 line = (mTextRect.mTop - 1 - local_y) / line_height;
- if (line >= total_lines)
+ for (segment_set_t::const_iterator it = first_it; it != end_it; ++it)
{
- return getLength(); // past the end
- }
-
- line = llclamp( line, 0, visible_lines ) + scroll_lines;
-
- S32 line_start = getLineStart(line);
- S32 next_start = getLineStart(line+1);
- S32 line_end = (next_start != line_start) ? next_start - 1 : getLength();
-
- if(line_start == -1)
- {
- return 0;
- }
- else
- {
- S32 line_len = line_end - line_start;
- S32 pos;
-
- if (mAllowEmbeddedItems)
- {
- // Figure out which character we're nearest to.
- bindEmbeddedChars(mGLFont);
- pos = mGLFont->charFromPixelOffset(mWText.c_str(), line_start,
- (F32)(local_x - mTextRect.mLeft),
- (F32)(mTextRect.getWidth()),
- line_len,
- round, TRUE);
- unbindEmbeddedChars(mGLFont);
- }
- else
+ LLTextSegmentPtr segment = *it;
+ if (include_partial
+ || (segment->getStart() >= start
+ && segment->getEnd() <= end))
{
- pos = mGLFont->charFromPixelOffset(mWText.c_str(), line_start,
- (F32)(local_x - mTextRect.mLeft),
- (F32)mTextRect.getWidth(),
- line_len,
- round);
+ segments_out.push_back(segment);
}
-
- return line_start + pos;
- }
-}
-
-void LLTextEditor::setCursor(S32 row, S32 column)
-{
- const llwchar* doc = mWText.c_str();
- const char CR = 10;
- while(row--)
- {
- while (CR != *doc++);
}
- doc += column;
- setCursorPos(doc - mWText.c_str());
-}
-
-void LLTextEditor::setCursorPos(S32 offset)
-{
- mCursorPos = llclamp(offset, 0, (S32)getLength());
- needsScroll();
- // reset desired x cursor position
- mDesiredXPixel = -1;
}
// virtual
@@ -909,25 +505,6 @@ void LLTextEditor::deselect()
}
-void LLTextEditor::startSelection()
-{
- if( !mIsSelecting )
- {
- mIsSelecting = TRUE;
- mSelectionStart = mCursorPos;
- mSelectionEnd = mCursorPos;
- }
-}
-
-void LLTextEditor::endSelection()
-{
- if( mIsSelecting )
- {
- mIsSelecting = FALSE;
- mSelectionEnd = mCursorPos;
- }
-}
-
BOOL LLTextEditor::selectionContainsLineBreaks()
{
if (hasSelection())
@@ -935,7 +512,7 @@ BOOL LLTextEditor::selectionContainsLineBreaks()
S32 left = llmin(mSelectionStart, mSelectionEnd);
S32 right = left + llabs(mSelectionStart - mSelectionEnd);
- const LLWString &wtext = mWText;
+ LLWString wtext = getWText();
for( S32 i = left; i < right; i++ )
{
if (wtext[i] == '\n')
@@ -972,7 +549,7 @@ S32 LLTextEditor::indentLine( S32 pos, S32 spaces )
// Unindent
for(S32 i=0; i < -spaces; i++)
{
- const LLWString &wtext = mWText;
+ LLWString wtext = getWText();
if (wtext[pos] == ' ')
{
delta_spaces += remove( pos, 1, FALSE );
@@ -987,7 +564,7 @@ void LLTextEditor::indentSelectedLines( S32 spaces )
{
if( hasSelection() )
{
- const LLWString &text = mWText;
+ LLWString text = getWText();
S32 left = llmin( mSelectionStart, mSelectionEnd );
S32 right = left + llabs( mSelectionStart - mSelectionEnd );
BOOL cursor_on_right = (mSelectionEnd > mSelectionStart);
@@ -1032,7 +609,7 @@ void LLTextEditor::indentSelectedLines( S32 spaces )
}
right += delta_spaces;
- //text = mWText;
+ text = getWText();
// Find the next new line
while( (cur < right) && (text[cur] != '\n') )
@@ -1058,7 +635,7 @@ void LLTextEditor::indentSelectedLines( S32 spaces )
mSelectionStart = right;
mSelectionEnd = left;
}
- mCursorPos = mSelectionEnd;
+ setCursorPos(mSelectionEnd);
}
}
@@ -1073,64 +650,24 @@ void LLTextEditor::selectAll()
{
mSelectionStart = getLength();
mSelectionEnd = 0;
- mCursorPos = mSelectionEnd;
+ setCursorPos(mSelectionEnd);
}
-
-BOOL LLTextEditor::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
+BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
{
- for ( child_list_const_iter_t child_it = getChildList()->begin();
- child_it != getChildList()->end(); ++child_it)
- {
- LLView* viewp = *child_it;
- S32 local_x = x - viewp->getRect().mLeft;
- S32 local_y = y - viewp->getRect().mBottom;
- if( viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ) )
- {
- return TRUE;
- }
- }
-
- if( mSegments.empty() )
- {
- return TRUE;
- }
+ BOOL handled = FALSE;
- const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
- if( cur_segment )
+ // set focus first, in case click callbacks want to change it
+ // RN: do we really need to have a tab stop?
+ if (hasTabStop())
{
- BOOL has_tool_tip = FALSE;
- has_tool_tip = cur_segment->getToolTip( msg );
-
- if( has_tool_tip )
- {
- // Just use a slop area around the cursor
- // Convert rect local to screen coordinates
- S32 SLOP = 8;
- localPointToScreen(
- x - SLOP, y - SLOP,
- &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
- sticky_rect_screen->mRight = sticky_rect_screen->mLeft + 2 * SLOP;
- sticky_rect_screen->mTop = sticky_rect_screen->mBottom + 2 * SLOP;
- }
+ setFocus( TRUE );
}
- return TRUE;
-}
-
-BOOL LLTextEditor::handleScrollWheel(S32 x, S32 y, S32 clicks)
-{
- // Pretend the mouse is over the scrollbar
- return mScrollbar->handleScrollWheel( 0, 0, clicks );
-}
-
-BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
-{
- BOOL handled = FALSE;
// Let scrollbar have first dibs
- handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL;
+ handled = LLTextBase::handleMouseDown(x, y, mask);
- if( !handled && mTakesNonScrollClicks)
+ if( !handled )
{
if (!(mask & MASK_SHIFT))
{
@@ -1144,31 +681,10 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
if (mask & MASK_SHIFT)
{
S32 old_cursor_pos = mCursorPos;
- setCursorAtLocalPos( x, y, TRUE );
+ setCursorAtLocalPos( x, y, true );
if (hasSelection())
{
- /* Mac-like behavior - extend selection towards the cursor
- if (mCursorPos < mSelectionStart
- && mCursorPos < mSelectionEnd)
- {
- // ...left of selection
- mSelectionStart = llmax(mSelectionStart, mSelectionEnd);
- mSelectionEnd = mCursorPos;
- }
- else if (mCursorPos > mSelectionStart
- && mCursorPos > mSelectionEnd)
- {
- // ...right of selection
- mSelectionStart = llmin(mSelectionStart, mSelectionEnd);
- mSelectionEnd = mCursorPos;
- }
- else
- {
- mSelectionEnd = mCursorPos;
- }
- */
- // Windows behavior
mSelectionEnd = mCursorPos;
}
else
@@ -1181,7 +697,7 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
}
else
{
- setCursorAtLocalPos( x, y, TRUE );
+ setCursorAtLocalPos( x, y, true );
startSelection();
}
gFocusMgr.setMouseCapture( this );
@@ -1190,26 +706,42 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
handled = TRUE;
}
- if (hasTabStop())
- {
- setFocus( TRUE );
- handled = TRUE;
- }
-
// Delay cursor flashing
- resetKeystrokeTimer();
+ resetCursorBlink();
return handled;
}
+BOOL LLTextEditor::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ if (hasTabStop())
+ {
+ setFocus(TRUE);
+ }
+ if (!LLTextBase::handleRightMouseDown(x, y, mask))
+ {
+ showContextMenu(x, y);
+ }
+ return TRUE;
+}
+
+
BOOL LLTextEditor::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
{
- setFocus( TRUE );
- if( canPastePrimary() )
+ if (hasTabStop())
+ {
+ setFocus(TRUE);
+ }
+
+ if (!LLTextBase::handleMouseDown(x, y, mask))
{
- setCursorAtLocalPos( x, y, TRUE );
- pastePrimary();
+ if( canPastePrimary() )
+ {
+ setCursorAtLocalPos( x, y, true );
+ // does not rely on focus being set
+ pastePrimary();
+ }
}
return TRUE;
}
@@ -1219,31 +751,19 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
- mHoverSegment = NULL;
if(hasMouseCapture() )
{
if( mIsSelecting )
{
- if (x != mLastSelectionX || y != mLastSelectionY)
- {
- mLastSelectionX = x;
- mLastSelectionY = y;
- }
-
- if( y > mTextRect.mTop )
- {
- mScrollbar->setDocPos( mScrollbar->getDocPos() - 1 );
- }
- else
- if( y < mTextRect.mBottom )
- {
- mScrollbar->setDocPos( mScrollbar->getDocPos() + 1 );
+ if(mScroller)
+ {
+ mScroller->autoScroll(x, y);
}
-
- setCursorAtLocalPos( x, y, TRUE );
+ S32 clamped_x = llclamp(x, mVisibleTextRect.mLeft, mVisibleTextRect.mRight);
+ S32 clamped_y = llclamp(y, mVisibleTextRect.mBottom, mVisibleTextRect.mTop);
+ setCursorAtLocalPos( clamped_x, clamped_y, true );
mSelectionEnd = mCursorPos;
}
-
lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" << llendl;
getWindow()->setCursor(UI_CURSOR_IBEAM);
handled = TRUE;
@@ -1252,61 +772,21 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask)
if( !handled )
{
// Pass to children
- handled = LLView::childrenHandleHover(x, y, mask) != NULL;
+ handled = LLTextBase::handleHover(x, y, mask);
}
if( handled )
{
// Delay cursor flashing
- resetKeystrokeTimer();
+ resetCursorBlink();
}
- // Opaque
- if( !handled && mTakesNonScrollClicks)
+ if( !handled )
{
- // Check to see if we're over an HTML-style link
- if( !mSegments.empty() )
- {
- const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
- if( cur_segment )
- {
- if(cur_segment->getStyle()->isLink())
- {
- lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (over link, inactive)" << llendl;
- getWindow()->setCursor(UI_CURSOR_HAND);
- handled = TRUE;
- }
- else
- if(cur_segment->getStyle()->getIsEmbeddedItem())
- {
- lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (over embedded item, inactive)" << llendl;
- getWindow()->setCursor(UI_CURSOR_HAND);
- //getWindow()->setCursor(UI_CURSOR_ARROW);
- handled = TRUE;
- }
- mHoverSegment = cur_segment;
- }
- }
-
- if( !handled )
- {
- lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (inactive)" << llendl;
- if (!mScrollbar->getVisible() || x < getRect().getWidth() - SCROLLBAR_SIZE)
- {
- getWindow()->setCursor(UI_CURSOR_IBEAM);
- }
- else
- {
- getWindow()->setCursor(UI_CURSOR_ARROW);
- }
- handled = TRUE;
- }
+ getWindow()->setCursor(UI_CURSOR_IBEAM);
+ handled = TRUE;
}
- if (mOnScrollEndCallback && mOnScrollEndData && (mScrollbar->getDocPos() == mScrollbar->getDocPosMax()))
- {
- mOnScrollEndCallback(mOnScrollEndData);
- }
return handled;
}
@@ -1315,33 +795,27 @@ BOOL LLTextEditor::handleMouseUp(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
- // let scrollbar have first dibs
- handled = LLView::childrenHandleMouseUp(x, y, mask) != NULL;
+ // if I'm not currently selecting text
+ if (!(hasSelection() && hasMouseCapture()))
+ {
+ // let text segments handle mouse event
+ handled = LLTextBase::handleMouseUp(x, y, mask);
+ }
- if( !handled && mTakesNonScrollClicks)
+ if( !handled )
{
if( mIsSelecting )
{
- // Finish selection
- if( y > mTextRect.mTop )
+ if(mScroller)
{
- mScrollbar->setDocPos( mScrollbar->getDocPos() - 1 );
+ mScroller->autoScroll(x, y);
}
- else
- if( y < mTextRect.mBottom )
- {
- mScrollbar->setDocPos( mScrollbar->getDocPos() + 1 );
- }
-
- setCursorAtLocalPos( x, y, TRUE );
+ S32 clamped_x = llclamp(x, mVisibleTextRect.mLeft, mVisibleTextRect.mRight);
+ S32 clamped_y = llclamp(y, mVisibleTextRect.mBottom, mVisibleTextRect.mTop);
+ setCursorAtLocalPos( clamped_x, clamped_y, true );
endSelection();
}
- if( !hasSelection() )
- {
- handleMouseUpOverSegment( x, y, mask );
- }
-
// take selection to 'primary' clipboard
updatePrimary();
@@ -1349,7 +823,7 @@ BOOL LLTextEditor::handleMouseUp(S32 x, S32 y, MASK mask)
}
// Delay cursor flashing
- resetKeystrokeTimer();
+ resetCursorBlink();
if( hasMouseCapture() )
{
@@ -1366,28 +840,28 @@ BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
- // let scrollbar have first dibs
- handled = LLView::childrenHandleDoubleClick(x, y, mask) != NULL;
+ // let scrollbar and text segments have first dibs
+ handled = LLTextBase::handleDoubleClick(x, y, mask);
- if( !handled && mTakesNonScrollClicks)
+ if( !handled )
{
- setCursorAtLocalPos( x, y, FALSE );
+ setCursorAtLocalPos( x, y, false );
deselect();
- const LLWString &text = mWText;
+ LLWString text = getWText();
- if( isPartOfWord( text[mCursorPos] ) )
+ if( LLWStringUtil::isPartOfWord( text[mCursorPos] ) )
{
// Select word the cursor is over
- while ((mCursorPos > 0) && isPartOfWord(text[mCursorPos-1]))
+ while ((mCursorPos > 0) && LLWStringUtil::isPartOfWord(text[mCursorPos-1]))
{
- mCursorPos--;
+ if (!setCursorPos(mCursorPos - 1)) break;
}
startSelection();
- while ((mCursorPos < (S32)text.length()) && isPartOfWord( text[mCursorPos] ) )
+ while ((mCursorPos < (S32)text.length()) && LLWStringUtil::isPartOfWord( text[mCursorPos] ) )
{
- mCursorPos++;
+ if (!setCursorPos(mCursorPos + 1)) break;
}
mSelectionEnd = mCursorPos;
@@ -1396,7 +870,7 @@ BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
{
// Select the character the cursor is over
startSelection();
- mCursorPos++;
+ setCursorPos(mCursorPos + 1);
mSelectionEnd = mCursorPos;
}
@@ -1405,7 +879,7 @@ BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
mIsSelecting = FALSE;
// delay cursor flashing
- resetKeystrokeTimer();
+ resetCursorBlink();
// take selection to 'primary' clipboard
updatePrimary();
@@ -1417,35 +891,18 @@ BOOL LLTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
}
-// Allow calling cards to be dropped onto text fields. Append the name and
-// a carriage return.
-// virtual
-BOOL LLTextEditor::handleDragAndDrop(S32 x, S32 y, MASK mask,
- BOOL drop, EDragAndDropType cargo_type, void *cargo_data,
- EAcceptance *accept,
- std::string& tooltip_msg)
-{
- *accept = ACCEPT_NO;
-
- return TRUE;
-}
-
//----------------------------------------------------------------------------
// Returns change in number of characters in mText
-S32 LLTextEditor::execute( LLTextCmd* cmd )
+S32 LLTextEditor::execute( TextCmd* cmd )
{
S32 delta = 0;
if( cmd->execute(this, &delta) )
{
// Delete top of undo stack
undo_stack_t::iterator enditer = std::find(mUndoStack.begin(), mUndoStack.end(), mLastCmd);
- if (enditer != mUndoStack.begin())
- {
- --enditer;
- std::for_each(mUndoStack.begin(), enditer, DeletePointer());
- mUndoStack.erase(mUndoStack.begin(), enditer);
- }
+ std::for_each(mUndoStack.begin(), enditer, DeletePointer());
+ mUndoStack.erase(mUndoStack.begin(), enditer);
// Push the new command is now on the top (front) of the undo stack.
mUndoStack.push_front(cmd);
mLastCmd = cmd;
@@ -1459,30 +916,31 @@ S32 LLTextEditor::execute( LLTextCmd* cmd )
return delta;
}
-S32 LLTextEditor::insert(const S32 pos, const LLWString &wstr, const BOOL group_with_next_op)
+S32 LLTextEditor::insert(S32 pos, const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment)
{
- return execute( new LLTextCmdInsert( pos, group_with_next_op, wstr ) );
+ return execute( new TextCmdInsert( pos, group_with_next_op, wstr, segment ) );
}
-S32 LLTextEditor::remove(const S32 pos, const S32 length, const BOOL group_with_next_op)
+S32 LLTextEditor::remove(S32 pos, S32 length, bool group_with_next_op)
{
- return execute( new LLTextCmdRemove( pos, group_with_next_op, length ) );
-}
+ S32 end_pos = getEditableIndex(pos + length, true);
-S32 LLTextEditor::append(const LLWString &wstr, const BOOL group_with_next_op)
-{
- return insert(mWText.length(), wstr, group_with_next_op);
+ segment_vec_t segments_to_remove;
+ // store text segments
+ getSegmentsInRange(segments_to_remove, pos, pos + length, false);
+
+ return execute( new TextCmdRemove( pos, group_with_next_op, end_pos - pos, segments_to_remove ) );
}
S32 LLTextEditor::overwriteChar(S32 pos, llwchar wc)
{
- if ((S32)mWText.length() == pos)
+ if ((S32)getLength() == pos)
{
return addChar(pos, wc);
}
else
{
- return execute(new LLTextCmdOverwriteChar(pos, FALSE, wc));
+ return execute(new TextCmdOverwriteChar(pos, FALSE, wc));
}
}
@@ -1498,12 +956,11 @@ void LLTextEditor::removeCharOrTab()
{
S32 chars_to_remove = 1;
- const LLWString &text = mWText;
+ LLWString text = getWText();
if (text[mCursorPos - 1] == ' ')
{
// Try to remove a "tab"
- S32 line, offset;
- getLineAndOffset(mCursorPos, &line, &offset);
+ S32 offset = getLineOffsetFromDocIndex(mCursorPos);
if (offset > 0)
{
chars_to_remove = offset % SPACES_PER_TAB;
@@ -1563,7 +1020,7 @@ void LLTextEditor::removeChar()
// Add a single character to the text
S32 LLTextEditor::addChar(S32 pos, llwchar wc)
{
- if ( (wstring_utf8_length( mWText ) + wchar_utf8_length( wc )) >= mMaxTextByteLength)
+ if ( (wstring_utf8_length( getWText() ) + wchar_utf8_length( wc )) > mMaxTextByteLength)
{
make_ui_sound("UISndBadKeystroke");
return 0;
@@ -1577,7 +1034,7 @@ S32 LLTextEditor::addChar(S32 pos, llwchar wc)
}
else
{
- return execute(new LLTextCmdAddChar(pos, FALSE, wc));
+ return execute(new TextCmdAddChar(pos, FALSE, wc, LLTextSegmentPtr()));
}
}
@@ -1614,10 +1071,10 @@ BOOL LLTextEditor::handleSelectionKey(const KEY key, const MASK mask)
if( 0 < mCursorPos )
{
startSelection();
- mCursorPos--;
+ setCursorPos(mCursorPos - 1);
if( mask & MASK_CONTROL )
{
- mCursorPos = prevWordPos(mCursorPos);
+ setCursorPos(prevWordPos(mCursorPos));
}
mSelectionEnd = mCursorPos;
}
@@ -1627,10 +1084,10 @@ BOOL LLTextEditor::handleSelectionKey(const KEY key, const MASK mask)
if( mCursorPos < getLength() )
{
startSelection();
- mCursorPos++;
+ setCursorPos(mCursorPos + 1);
if( mask & MASK_CONTROL )
{
- mCursorPos = nextWordPos(mCursorPos);
+ setCursorPos(nextWordPos(mCursorPos));
}
mSelectionEnd = mCursorPos;
}
@@ -1652,7 +1109,7 @@ BOOL LLTextEditor::handleSelectionKey(const KEY key, const MASK mask)
startSelection();
if( mask & MASK_CONTROL )
{
- mCursorPos = 0;
+ setCursorPos(0);
}
else
{
@@ -1677,7 +1134,7 @@ BOOL LLTextEditor::handleSelectionKey(const KEY key, const MASK mask)
startSelection();
if( mask & MASK_CONTROL )
{
- mCursorPos = getLength();
+ setCursorPos(getLength());
}
else
{
@@ -1728,14 +1185,7 @@ BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask)
switch( key )
{
case KEY_UP:
- if (mReadOnly)
- {
- mScrollbar->setDocPos(mScrollbar->getDocPos() - 1);
- }
- else
- {
- changeLine( -1 );
- }
+ changeLine( -1 );
break;
case KEY_PAGE_UP:
@@ -1743,25 +1193,11 @@ BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask)
break;
case KEY_HOME:
- if (mReadOnly)
- {
- mScrollbar->setDocPos(0);
- }
- else
- {
- startOfLine();
- }
+ startOfLine();
break;
case KEY_DOWN:
- if (mReadOnly)
- {
- mScrollbar->setDocPos(mScrollbar->getDocPos() + 1);
- }
- else
- {
- changeLine( 1 );
- }
+ changeLine( 1 );
break;
case KEY_PAGE_DOWN:
@@ -1769,21 +1205,10 @@ BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask)
break;
case KEY_END:
- if (mReadOnly)
- {
- mScrollbar->setDocPos(mScrollbar->getDocPosMax());
- }
- else
- {
- endOfLine();
- }
+ endOfLine();
break;
case KEY_LEFT:
- if (mReadOnly)
- {
- break;
- }
if( hasSelection() )
{
setCursorPos(llmin( mCursorPos - 1, mSelectionStart, mSelectionEnd ));
@@ -1802,10 +1227,6 @@ BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask)
break;
case KEY_RIGHT:
- if (mReadOnly)
- {
- break;
- }
if( hasSelection() )
{
setCursorPos(llmax( mCursorPos + 1, mSelectionStart, mSelectionEnd ));
@@ -1829,10 +1250,6 @@ BOOL LLTextEditor::handleNavigationKey(const KEY key, const MASK mask)
}
}
- if (mOnScrollEndCallback && mOnScrollEndData && (mScrollbar->getDocPos() == mScrollbar->getDocPosMax()))
- {
- mOnScrollEndCallback(mOnScrollEndData);
- }
return handled;
}
@@ -1865,10 +1282,12 @@ void LLTextEditor::cut()
}
S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
S32 length = llabs( mSelectionStart - mSelectionEnd );
- gClipboard.copyFromSubstring( mWText, left_pos, length, mSourceID );
+ gClipboard.copyFromSubstring( getWText(), left_pos, length, mSourceID );
deleteSelection( FALSE );
needsReflow();
+
+ onKeyStroke();
}
BOOL LLTextEditor::canCopy() const
@@ -1885,7 +1304,7 @@ void LLTextEditor::copy()
}
S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
S32 length = llabs( mSelectionStart - mSelectionEnd );
- gClipboard.copyFromSubstring(mWText, left_pos, length, mSourceID);
+ gClipboard.copyFromSubstring(getWText(), left_pos, length, mSourceID);
}
BOOL LLTextEditor::canPaste() const
@@ -1957,7 +1376,7 @@ void LLTextEditor::pasteHelper(bool is_primary)
for( S32 i = 0; i < len; i++ )
{
llwchar wc = clean_string[i];
- if( (wc < LLFont::FIRST_CHAR) && (wc != LF) )
+ if( (wc < LLFontFreetype::FIRST_CHAR) && (wc != LF) )
{
clean_string[i] = LL_UNKNOWN_CHAR;
}
@@ -1969,10 +1388,12 @@ void LLTextEditor::pasteHelper(bool is_primary)
}
// Insert the new text into the existing text.
- setCursorPos(mCursorPos + insert(mCursorPos, clean_string, FALSE));
+ setCursorPos(mCursorPos + insert(mCursorPos, clean_string, FALSE, LLTextSegmentPtr()));
deselect();
needsReflow();
+
+ onKeyStroke();
}
@@ -1986,7 +1407,7 @@ void LLTextEditor::copyPrimary()
}
S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
S32 length = llabs( mSelectionStart - mSelectionEnd );
- gClipboard.copyFromPrimarySubstring(mWText, left_pos, length, mSourceID);
+ gClipboard.copyFromPrimarySubstring(getWText(), left_pos, length, mSourceID);
}
BOOL LLTextEditor::canPastePrimary() const
@@ -2016,7 +1437,7 @@ BOOL LLTextEditor::handleControlKey(const KEY key, const MASK mask)
if( mask & MASK_SHIFT )
{
startSelection();
- mCursorPos = 0;
+ setCursorPos(0);
mSelectionEnd = mCursorPos;
}
else
@@ -2024,7 +1445,7 @@ BOOL LLTextEditor::handleControlKey(const KEY key, const MASK mask)
// Ctrl-Home, Ctrl-Left, Ctrl-Right, Ctrl-Down
// all move the cursor as if clicking, so should deselect.
deselect();
- setCursorPos(0);
+ startOfDoc();
}
break;
@@ -2213,8 +1634,7 @@ BOOL LLTextEditor::handleSpecialKey(const KEY key, const MASK mask, BOOL* return
deleteSelection(FALSE);
}
- S32 line, offset;
- getLineAndOffset( mCursorPos, &line, &offset );
+ S32 offset = getLineOffsetFromDocIndex(mCursorPos);
S32 spaces_needed = SPACES_PER_TAB - (offset % SPACES_PER_TAB);
for( S32 i=0; i < spaces_needed; i++ )
@@ -2237,7 +1657,7 @@ void LLTextEditor::unindentLineBeforeCloseBrace()
{
if( mCursorPos >= 1 )
{
- const LLWString &text = mWText;
+ LLWString text = getWText();
if( ' ' == text[ mCursorPos - 1 ] )
{
removeCharOrTab();
@@ -2253,42 +1673,95 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask )
BOOL return_key_hit = FALSE;
BOOL text_may_have_changed = TRUE;
- if ( gFocusMgr.getKeyboardFocus() == this )
+ // Special case for TAB. If want to move to next field, report
+ // not handled and let the parent take care of field movement.
+ if (KEY_TAB == key && mTabsToNextField)
+ {
+ return FALSE;
+ }
+ /*
+ if (KEY_F10 == key)
+ {
+ LLComboBox::Params cp;
+ cp.name = "combo box";
+ cp.label = "my combo";
+ cp.rect.width = 100;
+ cp.rect.height = 20;
+ cp.items.add().label = "item 1";
+ cp.items.add().label = "item 2";
+ cp.items.add().label = "item 3";
+
+ appendWidget(LLUICtrlFactory::create<LLComboBox>(cp), "combo", true, false);
+ }
+ if (KEY_F11 == key)
{
- // Special case for TAB. If want to move to next field, report
- // not handled and let the parent take care of field movement.
- if (KEY_TAB == key && mTabsToNextField)
+ LLButton::Params bp;
+ bp.name = "text button";
+ bp.label = "Click me";
+ bp.rect.width = 100;
+ bp.rect.height = 20;
+
+ appendWidget(LLUICtrlFactory::create<LLButton>(bp), "button", true, false);
+ }
+ */
+ if (mReadOnly)
+ {
+ if(mScroller)
{
- return FALSE;
+ handled = mScroller->handleKeyHere( key, mask );
+ }
+ else
+ {
+ handled = handleNavigationKey( key, mask );
}
+ }
+ else
+ {
+ // handle navigation keys ourself
handled = handleNavigationKey( key, mask );
+ }
+
+
+ if( handled )
+ {
+ text_may_have_changed = FALSE;
+ }
+
+ if( !handled )
+ {
+ handled = handleSelectionKey( key, mask );
if( handled )
{
- text_may_have_changed = FALSE;
+ selection_modified = TRUE;
}
-
- if( !handled )
+ }
+
+ if( !handled )
+ {
+ handled = handleControlKey( key, mask );
+ if( handled )
{
- handled = handleSelectionKey( key, mask );
- if( handled )
- {
- selection_modified = TRUE;
- }
+ selection_modified = TRUE;
}
-
- if( !handled )
+ }
+
+ if( !handled && mHandleEditKeysDirectly )
+ {
+ handled = handleEditKey( key, mask );
+ if( handled )
{
- handled = handleControlKey( key, mask );
- if( handled )
- {
- selection_modified = TRUE;
- }
+ selection_modified = TRUE;
+ text_may_have_changed = TRUE;
}
+ }
- if( !handled && mHandleEditKeysDirectly )
+ // Handle most keys only if the text editor is writeable.
+ if( !mReadOnly )
+ {
+ if( !handled )
{
- handled = handleEditKey( key, mask );
+ handled = handleSpecialKey( key, mask, &return_key_hit );
if( handled )
{
selection_modified = TRUE;
@@ -2296,41 +1769,29 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask )
}
}
- // Handle most keys only if the text editor is writeable.
- if( !mReadOnly )
- {
- if( !handled )
- {
- handled = handleSpecialKey( key, mask, &return_key_hit );
- if( handled )
- {
- selection_modified = TRUE;
- text_may_have_changed = TRUE;
- }
- }
+ }
+ if( handled )
+ {
+ resetCursorBlink();
+
+ // Most keystrokes will make the selection box go away, but not all will.
+ if( !selection_modified &&
+ KEY_SHIFT != key &&
+ KEY_CONTROL != key &&
+ KEY_ALT != key &&
+ KEY_CAPSLOCK )
+ {
+ deselect();
}
- if( handled )
+ if(text_may_have_changed)
{
- resetKeystrokeTimer();
-
- // Most keystrokes will make the selection box go away, but not all will.
- if( !selection_modified &&
- KEY_SHIFT != key &&
- KEY_CONTROL != key &&
- KEY_ALT != key &&
- KEY_CAPSLOCK )
- {
- deselect();
- }
+ needsReflow();
- if(text_may_have_changed)
- {
- needsReflow();
- }
- needsScroll();
+ onKeyStroke();
}
+ needsScroll();
}
return handled;
@@ -2346,34 +1807,33 @@ BOOL LLTextEditor::handleUnicodeCharHere(llwchar uni_char)
BOOL handled = FALSE;
- if ( gFocusMgr.getKeyboardFocus() == this )
+ // Handle most keys only if the text editor is writeable.
+ if( !mReadOnly )
{
- // Handle most keys only if the text editor is writeable.
- if( !mReadOnly )
+ if( '}' == uni_char )
{
- if( '}' == uni_char )
- {
- unindentLineBeforeCloseBrace();
- }
+ unindentLineBeforeCloseBrace();
+ }
- // TODO: KLW Add auto show of tool tip on (
- addChar( uni_char );
+ // TODO: KLW Add auto show of tool tip on (
+ addChar( uni_char );
- // Keys that add characters temporarily hide the cursor
- getWindow()->hideCursorUntilMouseMove();
+ // Keys that add characters temporarily hide the cursor
+ getWindow()->hideCursorUntilMouseMove();
- handled = TRUE;
- }
+ handled = TRUE;
+ }
- if( handled )
- {
- resetKeystrokeTimer();
+ if( handled )
+ {
+ resetCursorBlink();
- // Most keystrokes will make the selection box go away, but not all will.
- deselect();
+ // Most keystrokes will make the selection box go away, but not all will.
+ deselect();
- needsReflow();
- }
+ needsReflow();
+
+ onKeyStroke();
}
return handled;
@@ -2401,12 +1861,11 @@ void LLTextEditor::doDelete()
{
S32 i;
S32 chars_to_remove = 1;
- const LLWString &text = mWText;
+ LLWString text = getWText();
if( (text[ mCursorPos ] == ' ') && (mCursorPos + SPACES_PER_TAB < getLength()) )
{
// Try to remove a full tab's worth of spaces
- S32 line, offset;
- getLineAndOffset( mCursorPos, &line, &offset );
+ S32 offset = getLineOffsetFromDocIndex(mCursorPos);
chars_to_remove = SPACES_PER_TAB - (offset % SPACES_PER_TAB);
if( chars_to_remove == 0 )
{
@@ -2428,8 +1887,11 @@ void LLTextEditor::doDelete()
setCursorPos(mCursorPos + 1);
removeChar();
}
+
}
+ onKeyStroke();
+
needsReflow();
}
@@ -2474,6 +1936,8 @@ void LLTextEditor::undo()
setCursorPos(pos);
needsReflow();
+
+ onKeyStroke();
}
BOOL LLTextEditor::canRedo() const
@@ -2516,11 +1980,13 @@ void LLTextEditor::redo()
setCursorPos(pos);
needsReflow();
+
+ onKeyStroke();
}
void LLTextEditor::onFocusReceived()
{
- LLUICtrl::onFocusReceived();
+ LLTextBase::onFocusReceived();
updateAllowingLanguageInput();
}
@@ -2543,344 +2009,75 @@ void LLTextEditor::onFocusLost()
// Make sure cursor is shown again
getWindow()->showCursorFromMouseMove();
- LLUICtrl::onFocusLost();
+ LLTextBase::onFocusLost();
+}
+
+void LLTextEditor::onCommit()
+{
+ setControlValue(getValue());
+ LLTextBase::onCommit();
}
void LLTextEditor::setEnabled(BOOL enabled)
{
// just treat enabled as read-only flag
- BOOL read_only = !enabled;
+ bool read_only = !enabled;
if (read_only != mReadOnly)
{
- mReadOnly = read_only;
+ //mReadOnly = read_only;
+ LLTextBase::setReadOnly(read_only);
updateSegments();
updateAllowingLanguageInput();
}
}
-void LLTextEditor::drawBackground()
+void LLTextEditor::showContextMenu(S32 x, S32 y)
{
- S32 left = 0;
- S32 top = getRect().getHeight();
- S32 right = getRect().getWidth();
- S32 bottom = 0;
-
- LLColor4 bg_color = mReadOnly ? mReadOnlyBgColor
- : gFocusMgr.getKeyboardFocus() == this ? mFocusBgColor : mWriteableBgColor;
- if( mShowLineNumbers ) {
- gl_rect_2d(left, top, UI_TEXTEDITOR_LINE_NUMBER_MARGIN, bottom, mReadOnlyBgColor ); // line number area always read-only
- gl_rect_2d(UI_TEXTEDITOR_LINE_NUMBER_MARGIN, top, right, bottom, bg_color); // body text area to the right of line numbers
- gl_rect_2d(UI_TEXTEDITOR_LINE_NUMBER_MARGIN, top, UI_TEXTEDITOR_LINE_NUMBER_MARGIN-1, bottom, LLColor4::grey3); // separator
- } else {
- gl_rect_2d(left, top, right, bottom, bg_color); // body text area
- }
-
- LLView::draw();
-}
-
-// Draws the black box behind the selected text
-void LLTextEditor::drawSelectionBackground()
-{
- // Draw selection even if we don't have keyboard focus for search/replace
- if( hasSelection() )
+ if (!mContextMenu)
{
- const LLWString &text = mWText;
- const S32 text_len = getLength();
- std::queue<S32> line_endings;
-
- S32 line_height = llround( mGLFont->getLineHeight() );
-
- S32 selection_left = llmin( mSelectionStart, mSelectionEnd );
- S32 selection_right = llmax( mSelectionStart, mSelectionEnd );
- S32 selection_left_x = mTextRect.mLeft;
- S32 selection_left_y = mTextRect.mTop - line_height;
- S32 selection_right_x = mTextRect.mRight;
- S32 selection_right_y = mTextRect.mBottom;
-
- BOOL selection_left_visible = FALSE;
- BOOL selection_right_visible = FALSE;
-
- // Skip through the lines we aren't drawing.
- S32 cur_line = mScrollbar->getDocPos();
-
- S32 left_line_num = cur_line;
- S32 num_lines = getLineCount();
- S32 right_line_num = num_lines - 1;
-
- S32 line_start = -1;
- if (cur_line >= num_lines)
- {
- return;
- }
-
- line_start = getLineStart(cur_line);
-
- S32 left_visible_pos = line_start;
- S32 right_visible_pos = line_start;
-
- S32 text_y = mTextRect.mTop - line_height;
-
- // Find the coordinates of the selected area
- while((cur_line < num_lines))
- {
- S32 next_line = -1;
- S32 line_end = text_len;
-
- if ((cur_line + 1) < num_lines)
- {
- next_line = getLineStart(cur_line + 1);
- line_end = next_line;
-
- line_end = ( (line_end - line_start)==0 || text[next_line-1] == '\n' || text[next_line-1] == '\0' || text[next_line-1] == ' ' || text[next_line-1] == '\t' ) ? next_line-1 : next_line;
- }
-
- const llwchar* line = text.c_str() + line_start;
-
- if( line_start <= selection_left && selection_left <= line_end )
- {
- left_line_num = cur_line;
- selection_left_visible = TRUE;
- selection_left_x = mTextRect.mLeft + mGLFont->getWidth(line, 0, selection_left - line_start, mAllowEmbeddedItems);
- selection_left_y = text_y;
- }
- if( line_start <= selection_right && selection_right <= line_end )
- {
- right_line_num = cur_line;
- selection_right_visible = TRUE;
- selection_right_x = mTextRect.mLeft + mGLFont->getWidth(line, 0, selection_right - line_start, mAllowEmbeddedItems);
- if (selection_right == line_end)
- {
- // add empty space for "newline"
- //selection_right_x += mGLFont->getWidth("n");
- }
- selection_right_y = text_y;
- }
-
- // if selection spans end of current line...
- if (selection_left <= line_end && line_end < selection_right && selection_left != selection_right)
- {
- // extend selection slightly beyond end of line
- // to indicate selection of newline character (use "n" character to determine width)
- const LLWString nstr(utf8str_to_wstring(std::string("n")));
- line_endings.push(mTextRect.mLeft + mGLFont->getWidth(line, 0, line_end - line_start, mAllowEmbeddedItems) + mGLFont->getWidth(nstr.c_str()));
- }
-
- // move down one line
- text_y -= line_height;
-
- right_visible_pos = line_end;
- line_start = next_line;
- cur_line++;
-
- if (selection_right_visible)
- {
- break;
- }
- }
-
- // Draw the selection box (we're using a box instead of reversing the colors on the selected text).
- BOOL selection_visible = (left_visible_pos <= selection_right) && (selection_left <= right_visible_pos);
- if( selection_visible )
- {
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- const LLColor4& color = mReadOnly ? mReadOnlyBgColor : mWriteableBgColor;
- F32 alpha = hasFocus() ? 1.f : 0.5f;
- gGL.color4f( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], alpha );
- S32 margin_offset = mShowLineNumbers ? UI_TEXTEDITOR_LINE_NUMBER_MARGIN : 0;
-
- if( selection_left_y == selection_right_y )
- {
- // Draw from selection start to selection end
- gl_rect_2d( selection_left_x + margin_offset, selection_left_y + line_height + 1,
- selection_right_x + margin_offset, selection_right_y);
- }
- else
- {
- // Draw from selection start to the end of the first line
- if( mTextRect.mRight == selection_left_x )
- {
- selection_left_x -= CURSOR_THICKNESS;
- }
-
- S32 line_end = line_endings.front();
- line_endings.pop();
- gl_rect_2d( selection_left_x + margin_offset, selection_left_y + line_height + 1,
- line_end + margin_offset, selection_left_y );
-
- S32 line_num = left_line_num + 1;
- while(line_endings.size())
- {
- S32 vert_offset = -(line_num - left_line_num) * line_height;
- // Draw the block between the two lines
- gl_rect_2d( mTextRect.mLeft + margin_offset, selection_left_y + vert_offset + line_height + 1,
- line_endings.front() + margin_offset, selection_left_y + vert_offset);
- line_endings.pop();
- line_num++;
- }
-
- // Draw from the start of the last line to selection end
- if( mTextRect.mLeft == selection_right_x )
- {
- selection_right_x += CURSOR_THICKNESS;
- }
- gl_rect_2d( mTextRect.mLeft + margin_offset, selection_right_y + line_height + 1,
- selection_right_x + margin_offset, selection_right_y );
- }
- }
+ mContextMenu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>("menu_text_editor.xml",
+ LLMenuGL::sMenuContainer,
+ LLMenuHolderGL::child_registry_t::instance());
}
-}
-
-void LLTextEditor::drawCursor()
-{
- if( gFocusMgr.getKeyboardFocus() == this
- && gShowTextEditCursor && !mReadOnly)
- {
- const LLWString &text = mWText;
- const S32 text_len = getLength();
-
- // Skip through the lines we aren't drawing.
- S32 cur_pos = mScrollbar->getDocPos();
-
- S32 num_lines = getLineCount();
- if (cur_pos >= num_lines)
- {
- return;
- }
- S32 line_start = getLineStart(cur_pos);
-
- F32 line_height = mGLFont->getLineHeight();
- F32 text_y = (F32)(mTextRect.mTop) - line_height;
-
- F32 cursor_left = 0.f;
- F32 next_char_left = 0.f;
- F32 cursor_bottom = 0.f;
- BOOL cursor_visible = FALSE;
-
- S32 line_end = 0;
- // Determine if the cursor is visible and if so what its coordinates are.
- while( (mTextRect.mBottom <= llround(text_y)) && (cur_pos < num_lines))
- {
- line_end = text_len + 1;
- S32 next_line = -1;
-
- if ((cur_pos + 1) < num_lines)
- {
- next_line = getLineStart(cur_pos + 1);
- line_end = next_line - 1;
- }
-
- const llwchar* line = text.c_str() + line_start;
-
- // Find the cursor and selection bounds
- if( line_start <= mCursorPos && mCursorPos <= line_end )
- {
- cursor_visible = TRUE;
- next_char_left = (F32)mTextRect.mLeft + mGLFont->getWidthF32(line, 0, mCursorPos - line_start, mAllowEmbeddedItems );
- cursor_left = next_char_left - 1.f;
- cursor_bottom = text_y;
- break;
- }
-
- // move down one line
- text_y -= line_height;
- line_start = next_line;
- cur_pos++;
- }
-
- if(mShowLineNumbers)
- {
- cursor_left += UI_TEXTEDITOR_LINE_NUMBER_MARGIN;
- }
-
- // Draw the cursor
- if( cursor_visible )
- {
- // (Flash the cursor every half second starting a fixed time after the last keystroke)
- F32 elapsed = mKeystrokeTimer.getElapsedTimeF32();
- if( (elapsed < CURSOR_FLASH_DELAY ) || (S32(elapsed * 2) & 1) )
- {
- F32 cursor_top = cursor_bottom + line_height + 1.f;
- F32 cursor_right = cursor_left + (F32)CURSOR_THICKNESS;
- if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection())
- {
- cursor_left += CURSOR_THICKNESS;
- const LLWString space(utf8str_to_wstring(std::string(" ")));
- F32 spacew = mGLFont->getWidthF32(space.c_str());
- if (mCursorPos == line_end)
- {
- cursor_right = cursor_left + spacew;
- }
- else
- {
- F32 width = mGLFont->getWidthF32(text.c_str(), mCursorPos, 1, mAllowEmbeddedItems);
- cursor_right = cursor_left + llmax(spacew, width);
- }
- }
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- gGL.color4fv( mCursorColor.mV );
-
- gl_rect_2d(llfloor(cursor_left), llfloor(cursor_top),
- llfloor(cursor_right), llfloor(cursor_bottom));
-
- if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection() && text[mCursorPos] != '\n')
- {
- const LLTextSegment* segmentp = getSegmentAtOffset(mCursorPos);
- LLColor4 text_color;
- if (segmentp)
- {
- text_color = segmentp->getColor();
- }
- else if (mReadOnly)
- {
- text_color = mReadOnlyFgColor;
- }
- else
- {
- text_color = mFgColor;
- }
- mGLFont->render(text, mCursorPos, next_char_left, cursor_bottom + line_height,
- LLColor4(1.f - text_color.mV[VRED], 1.f - text_color.mV[VGREEN], 1.f - text_color.mV[VBLUE], 1.f),
- LLFontGL::LEFT, LLFontGL::TOP,
- LLFontGL::NORMAL,
- 1);
- }
-
- // Make sure the IME is in the right place
- LLRect screen_pos = getScreenRect();
- LLCoordGL ime_pos( screen_pos.mLeft + llfloor(cursor_left), screen_pos.mBottom + llfloor(cursor_top) );
- ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]);
- ime_pos.mY = (S32) (ime_pos.mY * LLUI::sGLScaleFactor.mV[VY]);
- getWindow()->setLanguageTextInput( ime_pos );
- }
- }
- }
+ S32 screen_x, screen_y;
+ localPointToScreen(x, y, &screen_x, &screen_y);
+ mContextMenu->show(screen_x, screen_y);
}
+
void LLTextEditor::drawPreeditMarker()
{
+ static LLUICachedControl<F32> preedit_marker_brightness ("UIPreeditMarkerBrightness", 0);
+ static LLUICachedControl<S32> preedit_marker_gap ("UIPreeditMarkerGap", 0);
+ static LLUICachedControl<S32> preedit_marker_position ("UIPreeditMarkerPosition", 0);
+ static LLUICachedControl<S32> preedit_marker_thickness ("UIPreeditMarkerThickness", 0);
+ static LLUICachedControl<F32> preedit_standout_brightness ("UIPreeditStandoutBrightness", 0);
+ static LLUICachedControl<S32> preedit_standout_gap ("UIPreeditStandoutGap", 0);
+ static LLUICachedControl<S32> preedit_standout_position ("UIPreeditStandoutPosition", 0);
+ static LLUICachedControl<S32> preedit_standout_thickness ("UIPreeditStandoutThickness", 0);
+
if (!hasPreeditString())
{
return;
}
- const llwchar *text = mWText.c_str();
+ const LLWString textString(getWText());
+ const llwchar *text = textString.c_str();
const S32 text_len = getLength();
const S32 num_lines = getLineCount();
- S32 cur_line = mScrollbar->getDocPos();
+ S32 cur_line = getFirstVisibleLine();
if (cur_line >= num_lines)
{
return;
}
- const S32 line_height = llround( mGLFont->getLineHeight() );
+ const S32 line_height = llround( mDefaultFont->getLineHeight() );
S32 line_start = getLineStart(cur_line);
- S32 line_y = mTextRect.mTop - line_height;
- while((mTextRect.mBottom <= line_y) && (num_lines > cur_line))
+ S32 line_y = mVisibleTextRect.mTop - line_height;
+ while((mVisibleTextRect.mBottom <= line_y) && (num_lines > cur_line))
{
S32 next_start = -1;
S32 line_end = text_len;
@@ -2912,36 +2109,36 @@ void LLTextEditor::drawPreeditMarker()
continue;
}
- S32 preedit_left = mTextRect.mLeft;
+ S32 preedit_left = mVisibleTextRect.mLeft;
if (left > line_start)
{
- preedit_left += mGLFont->getWidth(text, line_start, left - line_start, mAllowEmbeddedItems);
+ preedit_left += mDefaultFont->getWidth(text, line_start, left - line_start);
}
- S32 preedit_right = mTextRect.mLeft;
+ S32 preedit_right = mVisibleTextRect.mLeft;
if (right < line_end)
{
- preedit_right += mGLFont->getWidth(text, line_start, right - line_start, mAllowEmbeddedItems);
+ preedit_right += mDefaultFont->getWidth(text, line_start, right - line_start);
}
else
{
- preedit_right += mGLFont->getWidth(text, line_start, line_end - line_start, mAllowEmbeddedItems);
+ preedit_right += mDefaultFont->getWidth(text, line_start, line_end - line_start);
}
if (mPreeditStandouts[i])
{
- gl_rect_2d(preedit_left + PREEDIT_STANDOUT_GAP,
- line_y + PREEDIT_STANDOUT_POSITION,
- preedit_right - PREEDIT_STANDOUT_GAP - 1,
- line_y + PREEDIT_STANDOUT_POSITION - PREEDIT_STANDOUT_THICKNESS,
- (mCursorColor * PREEDIT_STANDOUT_BRIGHTNESS + mWriteableBgColor * (1 - PREEDIT_STANDOUT_BRIGHTNESS)).setAlpha(1.0f));
+ gl_rect_2d(preedit_left + preedit_standout_gap,
+ line_y + preedit_standout_position,
+ preedit_right - preedit_standout_gap - 1,
+ line_y + preedit_standout_position - preedit_standout_thickness,
+ (mCursorColor.get() * preedit_standout_brightness + mWriteableBgColor.get() * (1 - preedit_standout_brightness)).setAlpha(1.0f));
}
else
{
- gl_rect_2d(preedit_left + PREEDIT_MARKER_GAP,
- line_y + PREEDIT_MARKER_POSITION,
- preedit_right - PREEDIT_MARKER_GAP - 1,
- line_y + PREEDIT_MARKER_POSITION - PREEDIT_MARKER_THICKNESS,
- (mCursorColor * PREEDIT_MARKER_BRIGHTNESS + mWriteableBgColor * (1 - PREEDIT_MARKER_BRIGHTNESS)).setAlpha(1.0f));
+ gl_rect_2d(preedit_left + preedit_marker_gap,
+ line_y + preedit_marker_position,
+ preedit_right - preedit_marker_gap - 1,
+ line_y + preedit_marker_position - preedit_marker_thickness,
+ (mCursorColor.get() * preedit_marker_brightness + mWriteableBgColor.get() * (1 - preedit_marker_brightness)).setAlpha(1.0f));
}
}
}
@@ -2954,292 +2151,85 @@ void LLTextEditor::drawPreeditMarker()
}
-void LLTextEditor::drawText()
+void LLTextEditor::drawLineNumbers()
{
- const LLWString &text = mWText;
- const S32 text_len = getLength();
- if( text_len <= 0 ) return;
- S32 selection_left = -1;
- S32 selection_right = -1;
- // Draw selection even if we don't have keyboard focus for search/replace
- if( hasSelection())
- {
- selection_left = llmin( mSelectionStart, mSelectionEnd );
- selection_right = llmax( mSelectionStart, mSelectionEnd );
- }
-
LLGLSUIDefault gls_ui;
-
- // There are several concepts that are important for understanding the following drawing code.
- // The document is logically a sequence of characters (stored in a LLWString).
- // Variables below with "start" or "end" in their names refer to positions or offsets into it.
- // Next there are two kinds of "line" variables to understand. Newline characters in the
- // character sequence represent logical lines. These are what get numbered and so variables
- // representing this kind of line have "num" in their names.
- // The others represent line fragments or displayed lines which the scrollbar deals with.
- // When the "show line numbers" property is turned on, we draw line numbers to the left of the
- // beginning of each logical line and not in front of wrapped "continuation" display lines. -MG
-
- S32 cur_line = mScrollbar->getDocPos(); // scrollbar counts each wrap as a new line.
+ LLRect scrolled_view_rect = getVisibleDocumentRect();
+ LLRect content_rect = getVisibleTextRect();
+ LLLocalClipRect clip(content_rect);
+ S32 first_line = getFirstVisibleLine();
S32 num_lines = getLineCount();
- if (cur_line >= num_lines) return;
- S32 line_start = getLineStart(cur_line);
- S32 prev_start = getLineStart(cur_line-1);
- S32 cur_line_num = getLineForPosition(line_start); // doesn't count wraps. i.e. only counts newlines.
- S32 prev_line_num = getLineForPosition(prev_start);
- BOOL cur_line_is_continuation = cur_line_num > 0 && cur_line_num == prev_line_num;
- BOOL line_wraps = FALSE;
-
- LLTextSegment t(line_start);
- segment_list_t::iterator seg_iter;
- seg_iter = std::upper_bound(mSegments.begin(), mSegments.end(), &t, LLTextSegment::compare());
- if (seg_iter == mSegments.end() || (*seg_iter)->getStart() > line_start) --seg_iter;
- LLTextSegment* cur_segment = *seg_iter;
+ if (first_line >= num_lines)
+ {
+ return;
+ }
- S32 line_height = llround( mGLFont->getLineHeight() );
- F32 text_y = (F32)(mTextRect.mTop - line_height);
- while((mTextRect.mBottom <= text_y) && (cur_line < num_lines))
+ S32 cursor_line = mLineInfoList[getLineNumFromDocIndex(mCursorPos)].mLineNum;
+
+ if (mShowLineNumbers)
{
- S32 next_start = -1;
- S32 line_end = text_len;
+ S32 left = 0;
+ S32 top = getRect().getHeight();
+ S32 bottom = 0;
- if ((cur_line + 1) < num_lines)
- {
- next_start = getLineStart(cur_line + 1);
- line_end = next_start;
- }
- line_wraps = text[line_end-1] != '\n';
- if ( ! line_wraps )
- {
- --line_end; // don't attempt to draw the newline char.
- }
-
- F32 text_start = (F32)mTextRect.mLeft;
- F32 text_x = text_start + (mShowLineNumbers ? UI_TEXTEDITOR_LINE_NUMBER_MARGIN : 0);
-
- // draw the line numbers
- if( mShowLineNumbers && !cur_line_is_continuation)
- {
- const LLFontGL *num_font = LLFontGL::getFontMonospace();
- F32 y_top = text_y + ((F32)llround(num_font->getLineHeight()) / 2);
- const LLWString ltext = utf8str_to_wstring(llformat("%*d", UI_TEXTEDITOR_LINE_NUMBER_DIGITS, cur_line_num ));
- BOOL is_cur_line = getCurrentLine() == cur_line_num;
- const U8 style = is_cur_line ? LLFontGL::BOLD : LLFontGL::NORMAL;
- const LLColor4 fg_color = is_cur_line ? mCursorColor : mReadOnlyFgColor;
- num_font->render(
- ltext, // string to draw
- 0, // begin offset
- 3., // x
- y_top, // y
- fg_color,
- LLFontGL::LEFT, // horizontal alignment
- LLFontGL::VCENTER, // vertical alignment
- style,
- S32_MAX, // max chars
- UI_TEXTEDITOR_LINE_NUMBER_MARGIN); // max pixels
- }
+ gl_rect_2d(left, top, UI_TEXTEDITOR_LINE_NUMBER_MARGIN, bottom, mReadOnlyBgColor.get() ); // line number area always read-only
+ gl_rect_2d(UI_TEXTEDITOR_LINE_NUMBER_MARGIN, top, UI_TEXTEDITOR_LINE_NUMBER_MARGIN-1, bottom, LLColor4::grey3); // separator
- S32 seg_start = line_start;
- while( seg_start < line_end )
+ S32 last_line_num = -1;
+
+ for (S32 cur_line = first_line; cur_line < num_lines; cur_line++)
{
- while( cur_segment->getEnd() <= seg_start )
+ line_info& line = mLineInfoList[cur_line];
+
+ if ((line.mRect.mTop - scrolled_view_rect.mBottom) < mVisibleTextRect.mBottom)
{
- seg_iter++;
- if (seg_iter == mSegments.end())
- {
- llwarns << "Ran off the segmentation end!" << llendl;
- return;
- }
- cur_segment = *seg_iter;
+ break;
}
-
- // Draw a segment within the line
- S32 clipped_end = llmin( line_end, cur_segment->getEnd() );
- S32 clipped_len = clipped_end - seg_start;
- if( clipped_len > 0 )
- {
- LLStyleSP style = cur_segment->getStyle();
- if ( style->isImage() && (cur_segment->getStart() >= seg_start) && (cur_segment->getStart() <= clipped_end))
- {
- S32 style_image_height = style->mImageHeight;
- S32 style_image_width = style->mImageWidth;
- LLUIImagePtr image = style->getImage();
- image->draw(llround(text_x), llround(text_y)+line_height-style_image_height,
- style_image_width, style_image_height);
- }
- if (cur_segment == mHoverSegment && style->getIsEmbeddedItem())
- {
- style->mUnderline = TRUE;
- }
-
- S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
-
- if ( (mParseHTML) && (left_pos > seg_start) && (left_pos < clipped_end) && mIsSelecting && (mSelectionStart == mSelectionEnd) )
- {
- mHTML = style->getLinkHREF();
- }
-
- drawClippedSegment( text, seg_start, clipped_end, text_x, text_y, selection_left, selection_right, style, &text_x );
-
- if( text_x == text_start && mShowLineNumbers )
- {
- text_x += UI_TEXTEDITOR_LINE_NUMBER_MARGIN;
- }
-
- // Note: text_x is incremented by drawClippedSegment()
- seg_start += clipped_len;
+ S32 line_bottom = line.mRect.mBottom - scrolled_view_rect.mBottom + mVisibleTextRect.mBottom;
+ // draw the line numbers
+ if(line.mLineNum != last_line_num && line.mRect.mTop <= scrolled_view_rect.mTop)
+ {
+ const LLFontGL *num_font = LLFontGL::getFontMonospace();
+ const LLWString ltext = utf8str_to_wstring(llformat("%d", line.mLineNum ));
+ BOOL is_cur_line = cursor_line == line.mLineNum;
+ const U8 style = is_cur_line ? LLFontGL::BOLD : LLFontGL::NORMAL;
+ const LLColor4 fg_color = is_cur_line ? mCursorColor : mReadOnlyFgColor;
+ num_font->render(
+ ltext, // string to draw
+ 0, // begin offset
+ UI_TEXTEDITOR_LINE_NUMBER_MARGIN - 2, // x
+ line_bottom, // y
+ fg_color,
+ LLFontGL::RIGHT, // horizontal alignment
+ LLFontGL::BOTTOM, // vertical alignment
+ style,
+ LLFontGL::NO_SHADOW,
+ S32_MAX, // max chars
+ UI_TEXTEDITOR_LINE_NUMBER_MARGIN - 2); // max pixels
+ last_line_num = line.mLineNum;
}
}
-
- // move down one line
- text_y -= (F32)line_height;
-
- if( line_wraps )
- {
- cur_line_num--;
- }
- cur_line_is_continuation = line_wraps; // so as to not not number the continuation lines
-
- line_start = next_start;
- cur_line++;
- cur_line_num++;
}
}
-// Draws a single text segment, reversing the color for selection if needed.
-void LLTextEditor::drawClippedSegment(const LLWString &text, S32 seg_start, S32 seg_end, F32 x, F32 y, S32 selection_left, S32 selection_right, const LLStyleSP& style, F32* right_x )
-{
- if (!style->isVisible())
- {
- return;
- }
-
- const LLFontGL* font = mGLFont;
-
- LLColor4 color = style->getColor();
-
- if ( style->getFontString()[0] )
- {
- font = LLResMgr::getInstance()->getRes(style->getFontID());
- }
-
- U8 font_flags = LLFontGL::NORMAL;
-
- if (style->mBold)
- {
- font_flags |= LLFontGL::BOLD;
- }
- if (style->mItalic)
- {
- font_flags |= LLFontGL::ITALIC;
- }
- if (style->mUnderline)
- {
- font_flags |= LLFontGL::UNDERLINE;
- }
-
- if (style->getIsEmbeddedItem())
- {
- if (mReadOnly)
- {
- color = LLUI::sColorsGroup->getColor("TextEmbeddedItemReadOnlyColor");
- }
- else
- {
- color = LLUI::sColorsGroup->getColor("TextEmbeddedItemColor");
- }
- }
-
- F32 y_top = y + (F32)llround(font->getLineHeight());
-
- if( selection_left > seg_start )
- {
- // Draw normally
- S32 start = seg_start;
- S32 end = llmin( selection_left, seg_end );
- S32 length = end - start;
- font->render(text, start, x, y_top, color, LLFontGL::LEFT, LLFontGL::TOP, font_flags, length, S32_MAX, right_x, mAllowEmbeddedItems);
- }
- x = *right_x;
-
- if( (selection_left < seg_end) && (selection_right > seg_start) )
- {
- // Draw reversed
- S32 start = llmax( selection_left, seg_start );
- S32 end = llmin( selection_right, seg_end );
- S32 length = end - start;
-
- font->render(text, start, x, y_top,
- LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ),
- LLFontGL::LEFT, LLFontGL::TOP, font_flags, length, S32_MAX, right_x, mAllowEmbeddedItems);
- }
- x = *right_x;
- if( selection_right < seg_end )
- {
- // Draw normally
- S32 start = llmax( selection_right, seg_start );
- S32 end = seg_end;
- S32 length = end - start;
- font->render(text, start, x, y_top, color, LLFontGL::LEFT, LLFontGL::TOP, font_flags, length, S32_MAX, right_x, mAllowEmbeddedItems);
- }
- }
-
-
void LLTextEditor::draw()
{
- // do on-demand reflow
- if (mReflowNeeded)
- {
- updateLineStartList();
- mReflowNeeded = FALSE;
- }
-
- // then update scroll position, as cursor may have moved
- if (mScrollNeeded)
- {
- updateScrollFromCursor();
- mScrollNeeded = FALSE;
- }
-
{
- LLLocalClipRect clip(LLRect(0, getRect().getHeight(), getRect().getWidth() - (mScrollbar->getVisible() ? SCROLLBAR_SIZE : 0), 0));
-
- bindEmbeddedChars(mGLFont);
-
- drawBackground();
- drawSelectionBackground();
- drawPreeditMarker();
- drawText();
- drawCursor();
-
- unbindEmbeddedChars(mGLFont);
-
- //RN: the decision was made to always show the orange border for keyboard focus but do not put an insertion caret
- // when in readonly mode
- mBorder->setKeyboardFocusHighlight( gFocusMgr.getKeyboardFocus() == this);// && !mReadOnly);
+ // pad clipping rectangle so that cursor can draw at full width
+ // when at left edge of mVisibleTextRect
+ LLRect clip_rect(mVisibleTextRect);
+ clip_rect.stretch(1);
+ LLLocalClipRect clip(clip_rect);
+ drawPreeditMarker();
}
-
- LLView::draw(); // Draw children (scrollbar and border)
-
- // remember if we are supposed to be at the bottom of the buffer
- mScrolledToBottom = isScrolledToBottom();
-}
+ LLTextBase::draw();
+ drawLineNumbers();
-void LLTextEditor::onTabInto()
-{
- // selecting all on tabInto causes users to hit tab twice and replace their text with a tab character
- // theoretically, one could selectAll if mTabsToNextField is true, but we couldn't think of a use case
- // where you'd want to select all anyway
- // preserve insertion point when returning to the editor
- //selectAll();
-}
-
-// virtual
-void LLTextEditor::clear()
-{
- setText(LLStringUtil::null);
+ //RN: the decision was made to always show the orange border for keyboard focus but do not put an insertion caret
+ // when in readonly mode
+ mBorder->setKeyboardFocusHighlight( hasFocus() );// && !mReadOnly);
}
// Start or stop the editor from accepting text-editing keystrokes
@@ -3257,7 +2247,7 @@ void LLTextEditor::setFocus( BOOL new_state )
getWindow()->allowLanguageTextInput(this, FALSE);
}
- LLUICtrl::setFocus( new_state );
+ LLTextBase::setFocus( new_state );
if( new_state )
{
@@ -3265,7 +2255,7 @@ void LLTextEditor::setFocus( BOOL new_state )
gEditMenuHandler = this;
// Don't start the cursor flashing right away
- resetKeystrokeTimer();
+ resetCursorBlink();
}
else
{
@@ -3279,289 +2269,28 @@ void LLTextEditor::setFocus( BOOL new_state )
}
}
-// virtual
-BOOL LLTextEditor::acceptsTextInput() const
-{
- return !mReadOnly;
-}
-
-// Given a line (from the start of the doc) and an offset into the line, find the offset (pos) into text.
-S32 LLTextEditor::getPos( S32 line, S32 offset )
-{
- S32 line_start = getLineStart(line);
- S32 next_start = getLineStart(line+1);
- if (next_start == line_start)
- {
- next_start = getLength() + 1;
- }
- S32 line_length = next_start - line_start - 1;
- line_length = llmax(line_length, 0);
- return line_start + llmin( offset, line_length );
-}
-
-
-void LLTextEditor::changePage( S32 delta )
-{
- S32 line, offset;
- getLineAndOffset( mCursorPos, &line, &offset );
-
- // get desired x position to remember previous position
- S32 desired_x_pixel = mDesiredXPixel;
-
- // allow one line overlap
- S32 page_size = mScrollbar->getPageSize() - 1;
- if( delta == -1 )
- {
- line = llmax( line - page_size, 0);
- setCursorPos(getPos( line, offset ));
- mScrollbar->setDocPos( mScrollbar->getDocPos() - page_size );
- }
- else
- if( delta == 1 )
- {
- setCursorPos(getPos( line + page_size, offset ));
- mScrollbar->setDocPos( mScrollbar->getDocPos() + page_size );
- }
-
- // put desired position into remember-buffer after setCursorPos()
- mDesiredXPixel = desired_x_pixel;
-
- if (mOnScrollEndCallback && mOnScrollEndData && (mScrollbar->getDocPos() == mScrollbar->getDocPosMax()))
- {
- mOnScrollEndCallback(mOnScrollEndData);
- }
-}
-
-void LLTextEditor::changeLine( S32 delta )
-{
- bindEmbeddedChars(mGLFont);
-
- S32 line, offset;
- getLineAndOffset( mCursorPos, &line, &offset );
-
- S32 line_start = getLineStart(line);
-
- // set desired x position to remembered previous position
- S32 desired_x_pixel = mDesiredXPixel;
- // if remembered position was reset (thus -1), calculate new one here
- if( desired_x_pixel == -1 )
- {
- desired_x_pixel = mGLFont->getWidth(mWText.c_str(), line_start, offset, mAllowEmbeddedItems );
- }
-
- S32 new_line = 0;
- if( (delta < 0) && (line > 0 ) )
- {
- new_line = line - 1;
- }
- else
- if( (delta > 0) && (line < (getLineCount() - 1)) )
- {
- new_line = line + 1;
- }
- else
- {
- unbindEmbeddedChars(mGLFont);
- return;
- }
-
- S32 num_lines = getLineCount();
- S32 new_line_start = getLineStart(new_line);
- S32 new_line_end = getLength();
- if (new_line + 1 < num_lines)
- {
- new_line_end = getLineStart(new_line + 1) - 1;
- }
-
- S32 new_line_len = new_line_end - new_line_start;
-
- S32 new_offset;
- new_offset = mGLFont->charFromPixelOffset(mWText.c_str(), new_line_start,
- (F32)desired_x_pixel,
- (F32)mTextRect.getWidth(),
- new_line_len,
- mAllowEmbeddedItems);
-
- setCursorPos (getPos( new_line, new_offset ));
-
- // put desired position into remember-buffer after setCursorPos()
- mDesiredXPixel = desired_x_pixel;
- unbindEmbeddedChars(mGLFont);
-}
-
-BOOL LLTextEditor::isScrolledToTop()
-{
- return mScrollbar->isAtBeginning();
-}
-
-BOOL LLTextEditor::isScrolledToBottom()
-{
- return mScrollbar->isAtEnd();
-}
-
-
-void LLTextEditor::startOfLine()
-{
- S32 line, offset;
- getLineAndOffset( mCursorPos, &line, &offset );
- setCursorPos(mCursorPos - offset);
-}
-
-
// public
void LLTextEditor::setCursorAndScrollToEnd()
{
deselect();
endOfDoc();
- needsScroll();
-}
-
-void LLTextEditor::getLineAndColumnForPosition( S32 position, S32* line, S32* col, BOOL include_wordwrap )
-{
- if( include_wordwrap )
- {
- getLineAndOffset( mCursorPos, line, col );
- }
- else
- {
- const LLWString &text = mWText;
- S32 line_count = 0;
- S32 line_start = 0;
- S32 i;
- for( i = 0; text[i] && (i < position); i++ )
- {
- if( '\n' == text[i] )
- {
- line_start = i + 1;
- line_count++;
- }
- }
- *line = line_count;
- *col = i - line_start;
- }
}
void LLTextEditor::getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wordwrap )
{
- getLineAndColumnForPosition(mCursorPos, line, col, include_wordwrap);
-}
-
-S32 LLTextEditor::getCurrentLine()
-{
- return getLineForPosition(mCursorPos);
-}
-
-S32 LLTextEditor::getLineForPosition(S32 position)
-{
- S32 line, col;
- getLineAndColumnForPosition(position, &line, &col, FALSE);
- return line;
-}
-
-
-void LLTextEditor::endOfLine()
-{
- S32 line, offset;
- getLineAndOffset( mCursorPos, &line, &offset );
- S32 num_lines = getLineCount();
- if (line + 1 >= num_lines)
- {
- setCursorPos(getLength());
- }
- else
- {
- setCursorPos( getLineStart(line + 1) - 1 );
- }
-}
-
-void LLTextEditor::endOfDoc()
-{
- mScrollbar->setDocPos(mScrollbar->getDocPosMax());
- mScrolledToBottom = true;
-
- S32 len = getLength();
- if( len )
- {
- setCursorPos(len);
- }
- if (mOnScrollEndCallback && mOnScrollEndData && (mScrollbar->getDocPos() == mScrollbar->getDocPosMax()))
- {
- mOnScrollEndCallback(mOnScrollEndData);
- }
-}
-
-// Sets the scrollbar from the cursor position
-void LLTextEditor::updateScrollFromCursor()
-{
- mScrollbar->setDocSize( getLineCount() );
-
- if (mReadOnly)
- {
- // no cursor in read only mode
- return;
- }
-
- S32 line, offset;
- getLineAndOffset( mCursorPos, &line, &offset );
-
- S32 page_size = mScrollbar->getPageSize();
-
- if( line < mScrollbar->getDocPos() )
- {
- // scroll so that the cursor is at the top of the page
- mScrollbar->setDocPos( line );
- }
- else if( line >= mScrollbar->getDocPos() + page_size - 1 )
- {
- S32 new_pos = 0;
- if( line < mScrollbar->getDocSize() - 1 )
- {
- // scroll so that the cursor is one line above the bottom of the page,
- new_pos = line - page_size + 1;
- }
- else
- {
- // if there is less than a page of text remaining, scroll so that the cursor is at the bottom
- new_pos = mScrollbar->getDocPosMax();
- }
- mScrollbar->setDocPos( new_pos );
- }
-
- // Check if we've scrolled to bottom for callback if asked for callback
- if (mOnScrollEndCallback && mOnScrollEndData && (mScrollbar->getDocPos() == mScrollbar->getDocPosMax()))
- {
- mOnScrollEndCallback(mOnScrollEndData);
- }
-}
-
-void LLTextEditor::reshape(S32 width, S32 height, BOOL called_from_parent)
-{
- LLView::reshape( width, height, called_from_parent );
-
- // do this first after reshape, because other things depend on
- // up-to-date mTextRect
- updateTextRect();
-
- needsReflow();
-
- // propagate shape information to scrollbar
- mScrollbar->setDocSize( getLineCount() );
-
- S32 line_height = llround( mGLFont->getLineHeight() );
- S32 page_lines = mTextRect.getHeight() / line_height;
- mScrollbar->setPageSize( page_lines );
+ *line = getLineNumFromDocIndex(mCursorPos, include_wordwrap);
+ *col = getLineOffsetFromDocIndex(mCursorPos, include_wordwrap);
}
void LLTextEditor::autoIndent()
{
// Count the number of spaces in the current line
- S32 line, offset;
- getLineAndOffset( mCursorPos, &line, &offset );
+ S32 line = getLineNumFromDocIndex(mCursorPos);
S32 line_start = getLineStart(line);
S32 space_count = 0;
S32 i;
- const LLWString &text = mWText;
+ LLWString text = getWText();
while( ' ' == text[line_start] )
{
space_count++;
@@ -3594,129 +2323,16 @@ void LLTextEditor::insertText(const std::string &new_text)
deleteSelection(TRUE);
}
- setCursorPos(mCursorPos + insert( mCursorPos, utf8str_to_wstring(new_text), FALSE ));
+ setCursorPos(mCursorPos + insert( mCursorPos, utf8str_to_wstring(new_text), FALSE, LLTextSegmentPtr() ));
needsReflow();
setEnabled( enabled );
}
-
-void LLTextEditor::appendColoredText(const std::string &new_text,
- bool allow_undo,
- bool prepend_newline,
- const LLColor4 &color,
- const std::string& font_name)
-{
- LLColor4 lcolor=color;
- if (mParseHighlights)
- {
- LLTextParser* highlight = LLTextParser::getInstance();
- highlight->parseFullLineHighlights(new_text, &lcolor);
- }
-
- LLStyleSP style(new LLStyle);
- style->setVisible(true);
- style->setColor(lcolor);
- style->setFontName(font_name);
- appendStyledText(new_text, allow_undo, prepend_newline, style);
-}
-
-void LLTextEditor::appendStyledText(const std::string &new_text,
- bool allow_undo,
- bool prepend_newline,
- LLStyleSP stylep)
-{
- S32 part = (S32)LLTextParser::WHOLE;
- if(mParseHTML)
- {
-
- S32 start=0,end=0;
- std::string text = new_text;
- while ( findHTML(text, &start, &end) )
- {
- LLStyleSP html(new LLStyle);
- html->setVisible(true);
- html->setColor(mLinkColor);
- if (stylep)
- {
- html->setFontName(stylep->getFontString());
- }
- html->mUnderline = TRUE;
-
- if (start > 0)
- {
- if (part == (S32)LLTextParser::WHOLE ||
- part == (S32)LLTextParser::START)
- {
- part = (S32)LLTextParser::START;
- }
- else
- {
- part = (S32)LLTextParser::MIDDLE;
- }
- std::string subtext=text.substr(0,start);
- appendHighlightedText(subtext,allow_undo, prepend_newline, part, stylep);
- }
-
- html->setLinkHREF(text.substr(start,end-start));
- appendText(text.substr(start, end-start),allow_undo, prepend_newline, html);
- if (end < (S32)text.length())
- {
- text = text.substr(end,text.length() - end);
- end=0;
- part=(S32)LLTextParser::END;
- }
- else
- {
- break;
- }
- }
- if (part != (S32)LLTextParser::WHOLE) part=(S32)LLTextParser::END;
- if (end < (S32)text.length()) appendHighlightedText(text,allow_undo, prepend_newline, part, stylep);
- }
- else
- {
- appendHighlightedText(new_text, allow_undo, prepend_newline, part, stylep);
- }
-}
-
-void LLTextEditor::appendHighlightedText(const std::string &new_text,
- bool allow_undo,
- bool prepend_newline,
- S32 highlight_part,
- LLStyleSP stylep)
-{
- if (mParseHighlights)
- {
- LLTextParser* highlight = LLTextParser::getInstance();
-
- if (highlight && stylep)
- {
- LLSD pieces = highlight->parsePartialLineHighlights(new_text, stylep->getColor(), highlight_part);
- bool lprepend=prepend_newline;
- for (S32 i=0;i<pieces.size();i++)
- {
- LLSD color_llsd = pieces[i]["color"];
- LLColor4 lcolor;
- lcolor.setValue(color_llsd);
- LLStyleSP lstylep(new LLStyle(*stylep));
- lstylep->setColor(lcolor);
- if (i != 0 && (pieces.size() > 1) ) lprepend=FALSE;
- appendText((std::string)pieces[i]["text"], allow_undo, lprepend, lstylep);
- }
- return;
- }
- }
- appendText(new_text, allow_undo, prepend_newline, stylep);
-}
-
-// Appends new text to end of document
-void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool prepend_newline,
- const LLStyleSP stylep)
+void LLTextEditor::appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo)
{
// Save old state
- BOOL was_scrolled_to_bottom = (mScrollbar->getDocPos() == mScrollbar->getDocPosMax());
S32 selection_start = mSelectionStart;
S32 selection_end = mSelectionEnd;
BOOL was_selecting = mIsSelecting;
@@ -3728,50 +2344,19 @@ void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool
setCursorPos(old_length);
- // Add carriage return if not first line
- if (getLength() != 0
- && prepend_newline)
- {
- std::string final_text = "\n";
- final_text += new_text;
- append(utf8str_to_wstring(final_text), TRUE);
- }
- else
- {
- append(utf8str_to_wstring(new_text), TRUE );
- }
+ LLWString widget_wide_text = utf8str_to_wstring(text);
+
+ LLTextSegmentPtr segment = new LLInlineViewSegment(params, old_length, old_length + widget_wide_text.size());
+ insert(getLength(), widget_wide_text, FALSE, segment);
- if (stylep)
- {
- S32 segment_start = old_length;
- S32 segment_end = getLength();
- LLTextSegment* segment = new LLTextSegment(stylep, segment_start, segment_end );
- mSegments.push_back(segment);
- }
-
needsReflow();
// Set the cursor and scroll position
- // Maintain the scroll position unless the scroll was at the end of the doc (in which
- // case, move it to the new end of the doc) or unless the user was doing actively selecting
- if( was_scrolled_to_bottom && !was_selecting )
- {
- if( selection_start != selection_end )
- {
- // maintain an existing non-active selection
- mSelectionStart = selection_start;
- mSelectionEnd = selection_end;
- }
- endOfDoc();
- }
- else if( selection_start != selection_end )
+ if( selection_start != selection_end )
{
mSelectionStart = selection_start;
mSelectionEnd = selection_end;
-
-
-
mIsSelecting = was_selecting;
setCursorPos(cursor_pos);
}
@@ -3784,67 +2369,71 @@ void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool
setCursorPos(cursor_pos);
}
- if( !allow_undo )
+ if (!allow_undo)
{
blockUndo();
}
}
-void LLTextEditor::removeTextFromEnd(S32 num_chars)
-{
- if (num_chars <= 0) return;
-
- remove(getLength() - num_chars, num_chars, FALSE);
- S32 len = getLength();
- mCursorPos = llclamp(mCursorPos, 0, len);
- mSelectionStart = llclamp(mSelectionStart, 0, len);
- mSelectionEnd = llclamp(mSelectionEnd, 0, len);
+void LLTextEditor::replaceUrlLabel(const std::string &url,
+ const std::string &label)
+{
+ // get the full (wide) text for the editor so we can change it
+ LLWString text = getWText();
+ LLWString wlabel = utf8str_to_wstring(label);
+ bool modified = false;
+ S32 seg_start = 0;
- pruneSegments();
-
- // pruneSegments will invalidate mLineStartList.
- updateLineStartList();
- needsScroll();
-}
+ // iterate through each segment looking for ones styled as links
+ segment_set_t::iterator it;
+ for (it = mSegments.begin(); it != mSegments.end(); ++it)
+ {
+ LLTextSegment *seg = *it;
+ const LLStyleSP style = seg->getStyle();
-///////////////////////////////////////////////////////////////////
-// Returns change in number of characters in mWText
+ // update segment start/end length in case we replaced text earlier
+ S32 seg_length = seg->getEnd() - seg->getStart();
+ seg->setStart(seg_start);
+ seg->setEnd(seg_start + seg_length);
-S32 LLTextEditor::insertStringNoUndo(const S32 pos, const LLWString &wstr)
-{
- S32 old_len = mWText.length(); // length() returns character length
- S32 insert_len = wstr.length();
+ // if we find a link with our Url, then replace the label
+ if (style->isLink() && style->getLinkHREF() == url)
+ {
+ S32 start = seg->getStart();
+ S32 end = seg->getEnd();
+ text = text.substr(0, start) + wlabel + text.substr(end, text.size() - end + 1);
+ seg->setEnd(start + wlabel.size());
+ modified = true;
+ }
- mWText.insert(pos, wstr);
- mTextIsUpToDate = FALSE;
+ // work out the character offset for the next segment
+ seg_start = seg->getEnd();
+ }
- if ( truncate() )
+ // update the editor with the new (wide) text string
+ if (modified)
{
- // The user's not getting everything he's hoping for
- make_ui_sound("UISndBadKeystroke");
- insert_len = mWText.length() - old_len;
+ getViewModel()->setDisplay(text);
+ deselect();
+ setCursorPos(mCursorPos);
+ needsReflow();
}
-
- return insert_len;
}
-S32 LLTextEditor::removeStringNoUndo(S32 pos, S32 length)
+void LLTextEditor::removeTextFromEnd(S32 num_chars)
{
- mWText.erase(pos, length);
- mTextIsUpToDate = FALSE;
- return -length; // This will be wrong if someone calls removeStringNoUndo with an excessive length
-}
+ if (num_chars <= 0) return;
-S32 LLTextEditor::overwriteCharNoUndo(S32 pos, llwchar wc)
-{
- if (pos > (S32)mWText.length())
- {
- return 0;
- }
- mWText[pos] = wc;
- mTextIsUpToDate = FALSE;
- return 1;
+ remove(getLength() - num_chars, num_chars, FALSE);
+
+ S32 len = getLength();
+ setCursorPos (llclamp(mCursorPos, 0, len));
+ mSelectionStart = llclamp(mSelectionStart, 0, len);
+ mSelectionEnd = llclamp(mSelectionEnd, 0, len);
+
+ needsReflow();
+ needsScroll();
}
//----------------------------------------------------------------------------
@@ -3910,20 +2499,13 @@ BOOL LLTextEditor::tryToRevertToPristineState()
}
-void LLTextEditor::updateTextRect()
-{
- mTextRect.setOriginAndSize(
- UI_TEXTEDITOR_BORDER + UI_TEXTEDITOR_H_PAD,
- UI_TEXTEDITOR_BORDER,
- getRect().getWidth() - SCROLLBAR_SIZE - 2 * (UI_TEXTEDITOR_BORDER + UI_TEXTEDITOR_H_PAD),
- getRect().getHeight() - 2 * UI_TEXTEDITOR_BORDER - UI_TEXTEDITOR_V_PAD_TOP );
-}
-
+static LLFastTimer::DeclareTimer FTM_SYNTAX_HIGHLIGHTING("Syntax Highlighting");
void LLTextEditor::loadKeywords(const std::string& filename,
const std::vector<std::string>& funcs,
const std::vector<std::string>& tooltips,
const LLColor3& color)
{
+ LLFastTimer ft(FTM_SYNTAX_HIGHLIGHTING);
if(mKeywords.loadFromFile(filename))
{
S32 count = llmin(funcs.size(), tooltips.size());
@@ -3932,199 +2514,70 @@ void LLTextEditor::loadKeywords(const std::string& filename,
std::string name = utf8str_trim(funcs[i]);
mKeywords.addToken(LLKeywordToken::WORD, name, color, tooltips[i] );
}
+ segment_vec_t segment_list;
+ mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this);
- mKeywords.findSegments( &mSegments, mWText, mDefaultColor );
-
- llassert( mSegments.front()->getStart() == 0 );
- llassert( mSegments.back()->getEnd() == getLength() );
+ mSegments.clear();
+ segment_set_t::iterator insert_it = mSegments.begin();
+ for (segment_vec_t::iterator list_it = segment_list.begin(); list_it != segment_list.end(); ++list_it)
+ {
+ insert_it = mSegments.insert(insert_it, *list_it);
+ }
}
}
void LLTextEditor::updateSegments()
{
+ LLFastTimer ft(FTM_SYNTAX_HIGHLIGHTING);
if (mKeywords.isLoaded())
{
// HACK: No non-ascii keywords for now
- mKeywords.findSegments(&mSegments, mWText, mDefaultColor);
- }
- else if (mAllowEmbeddedItems)
- {
- findEmbeddedItemSegments();
- }
+ segment_vec_t segment_list;
+ mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this);
- // Make sure we have at least one segment
- if (mSegments.size() == 1 && mSegments[0]->getIsDefault())
- {
- delete mSegments[0];
- mSegments.clear(); // create default segment
- }
- if (mSegments.empty())
- {
- LLColor4& text_color = ( mReadOnly ? mReadOnlyFgColor : mFgColor );
- LLTextSegment* default_segment = new LLTextSegment( text_color, 0, mWText.length() );
- default_segment->setIsDefault(TRUE);
- mSegments.push_back(default_segment);
- }
-}
-
-// Only effective if text was removed from the end of the editor
-// *NOTE: Using this will invalidate references to mSegments from mLineStartList.
-void LLTextEditor::pruneSegments()
-{
- S32 len = mWText.length();
- // Find and update the first valid segment
- segment_list_t::iterator iter = mSegments.end();
- while(iter != mSegments.begin())
- {
- --iter;
- LLTextSegment* seg = *iter;
- if (seg->getStart() < len)
+ clearSegments();
+ segment_set_t::iterator insert_it = mSegments.begin();
+ for (segment_vec_t::iterator list_it = segment_list.begin(); list_it != segment_list.end(); ++list_it)
{
- // valid segment
- if (seg->getEnd() > len)
- {
- seg->setEnd(len);
- }
- break; // done
- }
- }
- if (iter != mSegments.end())
- {
- // erase invalid segments
- ++iter;
- std::for_each(iter, mSegments.end(), DeletePointer());
- mSegments.erase(iter, mSegments.end());
- }
- else
- {
- llwarns << "Tried to erase end of empty LLTextEditor" << llendl;
- }
-}
-
-void LLTextEditor::findEmbeddedItemSegments()
-{
- mHoverSegment = NULL;
- std::for_each(mSegments.begin(), mSegments.end(), DeletePointer());
- mSegments.clear();
-
- BOOL found_embedded_items = FALSE;
- const LLWString &text = mWText;
- S32 idx = 0;
- while( text[idx] )
- {
- if( text[idx] >= FIRST_EMBEDDED_CHAR && text[idx] <= LAST_EMBEDDED_CHAR )
- {
- found_embedded_items = TRUE;
- break;
+ insertSegment(*list_it);
}
- ++idx;
- }
-
- if( !found_embedded_items )
- {
- return;
- }
-
- S32 text_len = text.length();
-
- BOOL in_text = FALSE;
-
- LLColor4& text_color = ( mReadOnly ? mReadOnlyFgColor : mFgColor );
-
- if( idx > 0 )
- {
- mSegments.push_back( new LLTextSegment( text_color, 0, text_len ) ); // text
- in_text = TRUE;
}
- LLStyleSP embedded_style(new LLStyle);
- embedded_style->setIsEmbeddedItem( TRUE );
-
- // Start with i just after the first embedded item
- while ( text[idx] )
- {
- if( text[idx] >= FIRST_EMBEDDED_CHAR && text[idx] <= LAST_EMBEDDED_CHAR )
- {
- if( in_text )
- {
- mSegments.back()->setEnd( idx );
- }
- mSegments.push_back( new LLTextSegment( embedded_style, idx, idx + 1 ) ); // item
- in_text = FALSE;
- }
- else
- if( !in_text )
- {
- mSegments.push_back( new LLTextSegment( text_color, idx, text_len ) ); // text
- in_text = TRUE;
- }
- ++idx;
- }
+ LLTextBase::updateSegments();
}
-BOOL LLTextEditor::handleMouseUpOverSegment(S32 x, S32 y, MASK mask)
+void LLTextEditor::updateLinkSegments()
{
- if ( hasMouseCapture() )
+ LLWString wtext = getWText();
+
+ // update any segments that contain a link
+ for (segment_set_t::iterator it = mSegments.begin(); it != mSegments.end(); ++it)
{
- // This mouse up was part of a click.
- // Regardless of where the cursor is, see if we recently touched a link
- // and launch it if we did.
- if (mParseHTML && mHTML.length() > 0)
+ LLTextSegment *segment = *it;
+ if (segment && segment->getStyle() && segment->getStyle()->isLink())
{
- //Special handling for slurls
- if ( (mSecondlifeURLcallback!=NULL) && !(*mSecondlifeURLcallback)(mHTML) )
+ // if the link's label (what the user can edit) is a valid Url,
+ // then update the link's HREF to be the same as the label text.
+ // This lets users edit Urls in-place.
+ LLStyleSP style = static_cast<LLStyleSP>(segment->getStyle());
+ LLWString url_label = wtext.substr(segment->getStart(), segment->getEnd()-segment->getStart());
+ if (LLUrlRegistry::instance().hasUrl(url_label))
{
- if (mURLcallback!=NULL) (*mURLcallback)(mHTML);
+ std::string new_url = wstring_to_utf8str(url_label);
+ LLStringUtil::trim(new_url);
+ style->setLinkHREF(new_url);
}
- mHTML.clear();
}
}
-
- return FALSE;
}
-// Finds the text segment (if any) at the give local screen position
-const LLTextSegment* LLTextEditor::getSegmentAtLocalPos( S32 x, S32 y ) const
-{
- // Find the cursor position at the requested local screen position
- S32 offset = getCursorPosFromLocalCoord( x, y, FALSE );
- S32 idx = getSegmentIdxAtOffset(offset);
- return idx >= 0 ? mSegments[idx] : NULL;
-}
-
-const LLTextSegment* LLTextEditor::getSegmentAtOffset(S32 offset) const
-{
- S32 idx = getSegmentIdxAtOffset(offset);
- return idx >= 0 ? mSegments[idx] : NULL;
-}
-
-S32 LLTextEditor::getSegmentIdxAtOffset(S32 offset) const
-{
- if (mSegments.empty() || offset < 0 || offset >= getLength())
- {
- return -1;
- }
- else
- {
- S32 segidx, segoff;
- getSegmentAndOffset(offset, &segidx, &segoff);
- return segidx;
- }
-}
void LLTextEditor::onMouseCaptureLost()
{
endSelection();
}
-void LLTextEditor::setOnScrollEndCallback(void (*callback)(void*), void* userdata)
-{
- mOnScrollEndCallback = callback;
- mOnScrollEndData = userdata;
- mScrollbar->setOnScrollEndCallback(callback, userdata);
-}
-
///////////////////////////////////////////////////////////////////
// Hack for Notecards
@@ -4208,7 +2661,7 @@ BOOL LLTextEditor::importBuffer(const char* buffer, S32 length )
delete[] text;
- setCursorPos(0);
+ startOfDoc();
deselect();
needsReflow();
@@ -4222,350 +2675,28 @@ BOOL LLTextEditor::exportBuffer(std::string &buffer )
outstream << "Linden text version 1\n";
outstream << "{\n";
- outstream << llformat("Text length %d\n", mWText.length() );
+ outstream << llformat("Text length %d\n", getLength() );
outstream << getText();
outstream << "}\n";
return TRUE;
}
-//////////////////////////////////////////////////////////////////////////
-// LLTextSegment
-
-LLTextSegment::LLTextSegment(S32 start) :
- mStart(start),
- mEnd(0),
- mToken(NULL),
- mIsDefault(FALSE)
-{
-}
-LLTextSegment::LLTextSegment( const LLStyleSP& style, S32 start, S32 end ) :
- mStyle( style ),
- mStart( start),
- mEnd( end ),
- mToken(NULL),
- mIsDefault(FALSE)
-{
-}
-LLTextSegment::LLTextSegment( const LLColor4& color, S32 start, S32 end, BOOL is_visible) :
- mStyle(new LLStyle(is_visible,color,LLStringUtil::null)),
- mStart( start),
- mEnd( end ),
- mToken(NULL),
- mIsDefault(FALSE)
-{
-}
-LLTextSegment::LLTextSegment( const LLColor4& color, S32 start, S32 end ) :
- mStyle(new LLStyle(TRUE, color,LLStringUtil::null )),
- mStart( start),
- mEnd( end ),
- mToken(NULL),
- mIsDefault(FALSE)
-{
-}
-LLTextSegment::LLTextSegment( const LLColor3& color, S32 start, S32 end ) :
- mStyle(new LLStyle(TRUE, color,LLStringUtil::null )),
- mStart( start),
- mEnd( end ),
- mToken(NULL),
- mIsDefault(FALSE)
-{
-}
-
-BOOL LLTextSegment::getToolTip(std::string& msg) const
-{
- if (mToken && !mToken->getToolTip().empty())
- {
- const LLWString& wmsg = mToken->getToolTip();
- msg = wstring_to_utf8str(wmsg);
- return TRUE;
- }
- return FALSE;
-}
-
-
-
-void LLTextSegment::dump() const
-{
- llinfos << "Segment [" <<
-// mColor.mV[VX] << ", " <<
-// mColor.mV[VY] << ", " <<
-// mColor.mV[VZ] << "]\t[" <<
- mStart << ", " <<
- getEnd() << "]" <<
- llendl;
-
-}
-
-// virtual
-LLXMLNodePtr LLTextEditor::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLUICtrl::getXML();
-
- // Attributes
-
- node->createChild("max_length", TRUE)->setIntValue(getMaxLength());
- node->createChild("embedded_items", TRUE)->setBoolValue(mAllowEmbeddedItems);
- node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mGLFont));
- node->createChild("word_wrap", TRUE)->setBoolValue(mWordWrap);
- node->createChild("hide_scrollbar", TRUE)->setBoolValue(mHideScrollbarForShortDocs);
-
- addColorXML(node, mCursorColor, "cursor_color", "TextCursorColor");
- addColorXML(node, mFgColor, "text_color", "TextFgColor");
- addColorXML(node, mDefaultColor, "text_default_color", "TextDefaultColor");
- addColorXML(node, mReadOnlyFgColor, "text_readonly_color", "TextFgReadOnlyColor");
- addColorXML(node, mReadOnlyBgColor, "bg_readonly_color", "TextBgReadOnlyColor");
- addColorXML(node, mWriteableBgColor, "bg_writeable_color", "TextBgWriteableColor");
- addColorXML(node, mFocusBgColor, "bg_focus_color", "TextBgFocusColor");
-
- // Contents
- node->setStringValue(getText());
-
- return node;
-}
-
-// static
-LLView* LLTextEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("text_editor");
- node->getAttributeString("name", name);
-
- LLRect rect;
- createRect(node, rect, parent, LLRect());
-
- U32 max_text_length = 255;
- node->getAttributeU32("max_length", max_text_length);
-
- BOOL allow_embedded_items;
- node->getAttributeBOOL("embedded_items", allow_embedded_items);
-
- LLFontGL* font = LLView::selectFont(node);
-
- std::string text = node->getTextContents().substr(0, max_text_length - 1);
-
- LLTextEditor* text_editor = new LLTextEditor(name,
- rect,
- max_text_length,
- text,
- font,
- allow_embedded_items);
-
- text_editor->setTextEditorParameters(node);
-
- BOOL hide_scrollbar = FALSE;
- node->getAttributeBOOL("hide_scrollbar",hide_scrollbar);
- text_editor->setHideScrollbarForShortDocs(hide_scrollbar);
-
- text_editor->initFromXML(node, parent);
-
- return text_editor;
-}
-
-void LLTextEditor::setTextEditorParameters(LLXMLNodePtr node)
-{
- BOOL word_wrap = FALSE;
- node->getAttributeBOOL("word_wrap", word_wrap);
- setWordWrap(word_wrap);
-
- node->getAttributeBOOL("show_line_numbers", mShowLineNumbers);
-
- node->getAttributeBOOL("track_bottom", mTrackBottom);
-
- LLColor4 color;
- if (LLUICtrlFactory::getAttributeColor(node,"cursor_color", color))
- {
- setCursorColor(color);
- }
- if(LLUICtrlFactory::getAttributeColor(node,"text_color", color))
- {
- setFgColor(color);
- }
- if(LLUICtrlFactory::getAttributeColor(node,"text_readonly_color", color))
- {
- setReadOnlyFgColor(color);
- }
- if(LLUICtrlFactory::getAttributeColor(node,"bg_readonly_color", color))
- {
- setReadOnlyBgColor(color);
- }
- if(LLUICtrlFactory::getAttributeColor(node,"bg_writeable_color", color))
- {
- setWriteableBgColor(color);
- }
-}
-
-///////////////////////////////////////////////////////////////////
-// Refactoring note: We may eventually want to replace this with boost::regex or
-// boost::tokenizer capabilities since we've already fixed at least two JIRAs
-// concerning logic issues associated with this function.
-S32 LLTextEditor::findHTMLToken(const std::string &line, S32 pos, BOOL reverse) const
-{
- std::string openers=" \t\n('\"[{<>";
- std::string closers=" \t\n)'\"]}><;";
-
- if (reverse)
- {
- for (int index=pos; index >= 0; index--)
- {
- char c = line[index];
- S32 m2 = openers.find(c);
- if (m2 >= 0)
- {
- return index+1;
- }
- }
- return 0; // index is -1, don't want to return that.
- }
- else
- {
- // adjust the search slightly, to allow matching parenthesis inside the URL
- S32 paren_count = 0;
- for (int index=pos; index<(S32)line.length(); index++)
- {
- char c = line[index];
-
- if (c == '(')
- {
- paren_count++;
- }
- else if (c == ')')
- {
- if (paren_count <= 0)
- {
- return index;
- }
- else
- {
- paren_count--;
- }
- }
- else
- {
- S32 m2 = closers.find(c);
- if (m2 >= 0)
- {
- return index;
- }
- }
- }
- return line.length();
- }
-}
-
-BOOL LLTextEditor::findHTML(const std::string &line, S32 *begin, S32 *end) const
+void LLTextEditor::updateAllowingLanguageInput()
{
-
- S32 m1,m2,m3;
- BOOL matched = FALSE;
-
- m1=line.find("://",*end);
-
- if (m1 >= 0) //Easy match.
- {
- *begin = findHTMLToken(line, m1, TRUE);
- *end = findHTMLToken(line, m1, FALSE);
-
- //Load_url only handles http and https so don't hilite ftp, smb, etc.
- m2 = line.substr(*begin,(m1 - *begin)).find("http");
- m3 = line.substr(*begin,(m1 - *begin)).find("secondlife");
-
- std::string badneighbors=".,<>?';\"][}{=-+_)(*&^%$#@!~`\t\r\n\\";
-
- if (m2 >= 0 || m3>=0)
- {
- S32 bn = badneighbors.find(line.substr(m1+3,1));
-
- if (bn < 0)
- {
- matched = TRUE;
- }
- }
- }
-/* matches things like secondlife.com (no http://) needs a whitelist to really be effective.
- else //Harder match.
- {
- m1 = line.find(".",*end);
-
- if (m1 >= 0)
- {
- *end = findHTMLToken(line, m1, FALSE);
- *begin = findHTMLToken(line, m1, TRUE);
-
- m1 = line.rfind(".",*end);
-
- if ( ( *end - m1 ) > 2 && m1 > *begin)
- {
- std::string badneighbors=".,<>/?';\"][}{=-+_)(*&^%$#@!~`";
- m2 = badneighbors.find(line.substr(m1+1,1));
- m3 = badneighbors.find(line.substr(m1-1,1));
- if (m3<0 && m2<0)
- {
- matched = TRUE;
- }
- }
- }
- }
- */
-
- if (matched)
- {
- S32 strpos, strpos2;
-
- std::string url = line.substr(*begin,*end - *begin);
- std::string slurlID = "slurl.com/secondlife/";
- strpos = url.find(slurlID);
-
- if (strpos < 0)
- {
- slurlID="secondlife://";
- strpos = url.find(slurlID);
- }
-
- if (strpos < 0)
- {
- slurlID="sl://";
- strpos = url.find(slurlID);
- }
-
- if (strpos >= 0)
- {
- strpos+=slurlID.length();
-
- while ( ( strpos2=url.find("/",strpos) ) == -1 )
- {
- if ((*end+2) >= (S32)line.length() || line.substr(*end,1) != " " )
- {
- matched=FALSE;
- break;
- }
-
- strpos = (*end + 1) - *begin;
-
- *end = findHTMLToken(line,(*begin + strpos),FALSE);
- url = line.substr(*begin,*end - *begin);
- }
- }
-
- }
-
- if (!matched)
+ LLWindow* window = getWindow();
+ if (!window)
{
- *begin=*end=0;
+ // test app, no window available
+ return;
}
- return matched;
-}
-
-
-
-void LLTextEditor::updateAllowingLanguageInput()
-{
if (hasFocus() && !mReadOnly)
{
- getWindow()->allowLanguageTextInput(this, TRUE);
+ window->allowLanguageTextInput(this, TRUE);
}
else
{
- getWindow()->allowLanguageTextInput(this, FALSE);
+ window->allowLanguageTextInput(this, FALSE);
}
}
@@ -4586,7 +2717,7 @@ void LLTextEditor::resetPreedit()
deselect();
}
- mCursorPos = mPreeditPositions.front();
+ setCursorPos(mPreeditPositions.front());
removeStringNoUndo(mCursorPos, mPreeditPositions.back() - mCursorPos);
insertStringNoUndo(mCursorPos, mPreeditOverwrittenWString);
@@ -4626,7 +2757,7 @@ void LLTextEditor::updatePreedit(const LLWString &preedit_string,
if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
{
- mPreeditOverwrittenWString = getWSubString(insert_preedit_at, mPreeditWString.length());
+ mPreeditOverwrittenWString = getWText().substr(insert_preedit_at, mPreeditWString.length());
removeStringNoUndo(insert_preedit_at, mPreeditWString.length());
}
else
@@ -4641,7 +2772,9 @@ void LLTextEditor::updatePreedit(const LLWString &preedit_string,
setCursorPos(insert_preedit_at + caret_position);
// Update of the preedit should be caused by some key strokes.
- mKeystrokeTimer.reset();
+ resetCursorBlink();
+
+ onKeyStroke();
}
BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect *bounds, LLRect *control) const
@@ -4649,7 +2782,7 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect
if (control)
{
LLRect control_rect_screen;
- localRectToScreen(mTextRect, &control_rect_screen);
+ localRectToScreen(mVisibleTextRect, &control_rect_screen);
LLUI::screenRectToGL(control_rect_screen, control);
}
@@ -4670,7 +2803,7 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect
return FALSE;
}
- const S32 first_visible_line = mScrollbar->getDocPos();
+ const S32 first_visible_line = getFirstVisibleLine();
if (query < getLineStart(first_visible_line))
{
return FALSE;
@@ -4694,13 +2827,14 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect
current_line++;
}
- const llwchar * const text = mWText.c_str();
- const S32 line_height = llround(mGLFont->getLineHeight());
+ const LLWString textString(getWText());
+ const llwchar * const text = textString.c_str();
+ const S32 line_height = llround(mDefaultFont->getLineHeight());
if (coord)
{
- const S32 query_x = mTextRect.mLeft + mGLFont->getWidth(text, current_line_start, query - current_line_start, mAllowEmbeddedItems);
- const S32 query_y = mTextRect.mTop - (current_line - first_visible_line) * line_height - line_height / 2;
+ const S32 query_x = mVisibleTextRect.mLeft + mDefaultFont->getWidth(text, current_line_start, query - current_line_start);
+ const S32 query_y = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height - line_height / 2;
S32 query_screen_x, query_screen_y;
localPointToScreen(query_x, query_y, &query_screen_x, &query_screen_y);
LLUI::screenPointToGL(query_screen_x, query_screen_y, &coord->mX, &coord->mY);
@@ -4708,23 +2842,23 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect
if (bounds)
{
- S32 preedit_left = mTextRect.mLeft;
+ S32 preedit_left = mVisibleTextRect.mLeft;
if (preedit_left_position > current_line_start)
{
- preedit_left += mGLFont->getWidth(text, current_line_start, preedit_left_position - current_line_start, mAllowEmbeddedItems);
+ preedit_left += mDefaultFont->getWidth(text, current_line_start, preedit_left_position - current_line_start);
}
- S32 preedit_right = mTextRect.mLeft;
+ S32 preedit_right = mVisibleTextRect.mLeft;
if (preedit_right_position < current_line_end)
{
- preedit_right += mGLFont->getWidth(text, current_line_start, preedit_right_position - current_line_start, mAllowEmbeddedItems);
+ preedit_right += mDefaultFont->getWidth(text, current_line_start, preedit_right_position - current_line_start);
}
else
{
- preedit_right += mGLFont->getWidth(text, current_line_start, current_line_end - current_line_start, mAllowEmbeddedItems);
+ preedit_right += mDefaultFont->getWidth(text, current_line_start, current_line_end - current_line_start);
}
- const S32 preedit_top = mTextRect.mTop - (current_line - first_visible_line) * line_height;
+ const S32 preedit_top = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height;
const S32 preedit_bottom = preedit_top - line_height;
const LLRect preedit_rect_local(preedit_left, preedit_top, preedit_right, preedit_bottom);
@@ -4772,7 +2906,7 @@ void LLTextEditor::markAsPreedit(S32 position, S32 length)
{
llwarns << "markAsPreedit invoked when hasPreeditString is true." << llendl;
}
- mPreeditWString = LLWString( mWText, position, length );
+ mPreeditWString = LLWString( getWText(), position, length );
if (length > 0)
{
mPreeditPositions.resize(2);
@@ -4798,5 +2932,39 @@ void LLTextEditor::markAsPreedit(S32 position, S32 length)
S32 LLTextEditor::getPreeditFontSize() const
{
- return llround(mGLFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]);
+ return llround(mDefaultFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]);
+}
+
+BOOL LLTextEditor::isDirty() const
+{
+ if(mReadOnly)
+ {
+ return FALSE;
+ }
+
+ if( mPristineCmd )
+ {
+ return ( mPristineCmd == mLastCmd );
+ }
+ else
+ {
+ return ( NULL != mLastCmd );
+ }
+}
+
+void LLTextEditor::setKeystrokeCallback(const keystroke_signal_t::slot_type& callback)
+{
+ mKeystrokeSignal.connect(callback);
+}
+
+void LLTextEditor::onKeyStroke()
+{
+ mKeystrokeSignal(this);
+}
+
+//virtual
+void LLTextEditor::clear()
+{
+ getViewModel()->setDisplay(LLWStringUtil::null);
+ clearSegments();
}
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index 9291e1c436..043dda8fa6 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -37,25 +37,50 @@
#include "llrect.h"
#include "llkeywords.h"
-#include "lluictrl.h"
#include "llframetimer.h"
#include "lldarray.h"
#include "llstyle.h"
#include "lleditmenuhandler.h"
#include "lldarray.h"
+#include "llviewborder.h" // for params
+#include "lltextbase.h"
#include "llpreeditor.h"
+#include "llcontrol.h"
class LLFontGL;
class LLScrollbar;
-class LLViewBorder;
class LLKeywordToken;
-class LLTextCmd;
+class TextCmd;
class LLUICtrlFactory;
+class LLScrollContainer;
-class LLTextEditor : public LLUICtrl, LLEditMenuHandler, protected LLPreeditor
+class LLTextEditor :
+ public LLTextBase,
+ protected LLPreeditor
{
public:
+ struct Params : public LLInitParam::Block<Params, LLTextBase::Params>
+ {
+ Optional<std::string> default_text;
+
+ Optional<bool> embedded_items,
+ ignore_tab,
+ handle_edit_keys_directly,
+ show_line_numbers,
+ commit_on_focus_lost;
+
+ //colors
+ Optional<LLUIColor> default_color;
+
+ Params();
+ };
+
+ void initFromParams(const Params&);
+protected:
+ LLTextEditor(const Params&);
+ friend class LLUICtrlFactory;
+public:
//
// Constants
//
@@ -63,51 +88,38 @@ public:
static const llwchar LAST_EMBEDDED_CHAR = 0x10ffff;
static const S32 MAX_EMBEDDED_ITEMS = LAST_EMBEDDED_CHAR - FIRST_EMBEDDED_CHAR + 1;
- LLTextEditor(const std::string& name,
- const LLRect& rect,
- S32 max_length,
- const std::string &default_text,
- const LLFontGL* glfont = NULL,
- BOOL allow_embedded_items = FALSE);
-
virtual ~LLTextEditor();
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory);
- void setTextEditorParameters(LLXMLNodePtr node);
- void setParseHTML(BOOL parsing) {mParseHTML=parsing;}
+ typedef boost::signals2::signal<void (LLTextEditor* caller)> keystroke_signal_t;
+
+ void setKeystrokeCallback(const keystroke_signal_t::slot_type& callback);
+
void setParseHighlights(BOOL parsing) {mParseHighlights=parsing;}
// mousehandler overrides
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask );
virtual BOOL handleMiddleMouseDown(S32 x,S32 y,MASK mask);
virtual BOOL handleKeyHere(KEY key, MASK mask );
virtual BOOL handleUnicodeCharHere(llwchar uni_char);
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect);
- virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
- EDragAndDropType cargo_type, void *cargo_data,
- EAcceptance *accept, std::string& tooltip_msg);
virtual void onMouseCaptureLost();
// view overrides
- virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
virtual void draw();
virtual void onFocusReceived();
virtual void onFocusLost();
+ virtual void onCommit();
virtual void setEnabled(BOOL enabled);
// uictrl overrides
- virtual void onTabInto();
virtual void clear();
virtual void setFocus( BOOL b );
- virtual BOOL acceptsTextInput() const;
- virtual BOOL isDirty() const { return( mLastCmd != NULL || (mPristineCmd && (mPristineCmd != mLastCmd)) ); }
+ virtual BOOL isDirty() const;
// LLEditMenuHandler interface
virtual void undo();
@@ -137,6 +149,7 @@ public:
void selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap = TRUE);
BOOL replaceText(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive, BOOL wrap = TRUE);
void replaceTextAll(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive);
+ void replaceUrlLabel(const std::string &url, const std::string &label);
// Undo/redo stack
void blockUndo();
@@ -146,38 +159,27 @@ public:
BOOL isPristine() const;
BOOL allowsEmbeddedItems() const { return mAllowEmbeddedItems; }
+ //
+ // Text manipulation
+ //
+
// inserts text at cursor
void insertText(const std::string &text);
- // appends text at end
- void appendText(const std::string &wtext, bool allow_undo, bool prepend_newline,
- const LLStyleSP stylep = NULL);
-
- void appendColoredText(const std::string &wtext, bool allow_undo,
- bool prepend_newline,
- const LLColor4 &color,
- const std::string& font_name = LLStringUtil::null);
- // if styled text starts a line, you need to prepend a newline.
- void appendStyledText(const std::string &new_text, bool allow_undo,
- bool prepend_newline,
- LLStyleSP stylep = NULL);
- void appendHighlightedText(const std::string &new_text, bool allow_undo,
- bool prepend_newline, S32 highlight_part,
- LLStyleSP stylep);
-
+
+ void appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo);
+ // Non-undoable
+ void setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params = LLStyle::Params());
+
+
// Removes text from the end of document
// Does not change highlight or cursor position.
void removeTextFromEnd(S32 num_chars);
BOOL tryToRevertToPristineState();
- void setCursor(S32 row, S32 column);
- void setCursorPos(S32 offset);
void setCursorAndScrollToEnd();
- void getLineAndColumnForPosition( S32 position, S32* line, S32* col, BOOL include_wordwrap );
void getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wordwrap );
- S32 getLineForPosition(S32 position);
- S32 getCurrentLine();
void loadKeywords(const std::string& filename,
const std::vector<std::string>& funcs,
@@ -186,114 +188,31 @@ public:
LLKeywords::keyword_iterator_t keywordsBegin() { return mKeywords.begin(); }
LLKeywords::keyword_iterator_t keywordsEnd() { return mKeywords.end(); }
- // Color support
- void setCursorColor(const LLColor4& c) { mCursorColor = c; }
- void setFgColor( const LLColor4& c ) { mFgColor = c; }
- void setTextDefaultColor( const LLColor4& c ) { mDefaultColor = c; }
- void setReadOnlyFgColor( const LLColor4& c ) { mReadOnlyFgColor = c; }
- void setWriteableBgColor( const LLColor4& c ) { mWriteableBgColor = c; }
- void setReadOnlyBgColor( const LLColor4& c ) { mReadOnlyBgColor = c; }
- void setTrackColor( const LLColor4& color );
- void setThumbColor( const LLColor4& color );
- void setHighlightColor( const LLColor4& color );
- void setShadowColor( const LLColor4& color );
-
// Hacky methods to make it into a word-wrapping, potentially scrolling,
// read-only text box.
- void setBorderVisible(BOOL b);
- BOOL isBorderVisible() const;
- void setTakesNonScrollClicks(BOOL b) { mTakesNonScrollClicks = b; }
- void setHideScrollbarForShortDocs(BOOL b);
-
- void setWordWrap( BOOL b );
- void setTabsToNextField(BOOL b) { mTabsToNextField = b; }
- BOOL tabsToNextField() const { return mTabsToNextField; }
void setCommitOnFocusLost(BOOL b) { mCommitOnFocusLost = b; }
// Hack to handle Notecards
virtual BOOL importBuffer(const char* buffer, S32 length );
virtual BOOL exportBuffer(std::string& buffer );
- // If takes focus, will take keyboard focus on click.
- void setTakesFocus(BOOL b) { mTakesFocus = b; }
-
- void setSourceID(const LLUUID& id) { mSourceID = id; }
const LLUUID& getSourceID() const { return mSourceID; }
- void setAcceptCallingCardNames(BOOL enable) { mAcceptCallingCardNames = enable; }
- BOOL acceptsCallingCardNames() const { return mAcceptCallingCardNames; }
-
- void setHandleEditKeysDirectly( BOOL b ) { mHandleEditKeysDirectly = b; }
-
- // Callbacks
- static void setLinkColor(LLColor4 color) { mLinkColor = color; }
- static void setURLCallbacks(void (*callback1) (const std::string& url),
- bool (*callback2) (const std::string& url),
- bool (*callback3) (const std::string& url) )
- { mURLcallback = callback1; mSecondlifeURLcallback = callback2; mSecondlifeURLcallbackRightClick = callback3;}
-
- void setOnScrollEndCallback(void (*callback)(void*), void* userdata);
-
- // new methods
- void setValue(const LLSD& value);
- LLSD getValue() const;
-
- const std::string& getText() const;
-
- // Non-undoable
- void setText(const LLStringExplicit &utf8str);
- void setWText(const LLWString &wtext);
-
- // Returns byte length limit
- S32 getMaxLength() const { return mMaxTextByteLength; }
-
- // Change cursor
- void startOfLine();
- void endOfLine();
- void endOfDoc();
- BOOL isScrolledToTop();
- BOOL isScrolledToBottom();
-
- // Getters
- const LLWString& getWText() const { return mWText; }
- llwchar getWChar(S32 pos) const { return mWText[pos]; }
- LLWString getWSubString(S32 pos, S32 len) const { return mWText.substr(pos, len); }
-
- const LLTextSegment* getCurrentSegment() const { return getSegmentAtOffset(mCursorPos); }
- const LLTextSegment* getPreviousSegment() const;
- void getSelectedSegments(std::vector<const LLTextSegment*>& segments) const;
-
- static bool isPartOfWord(llwchar c) { return (c == '_') || LLStringOps::isAlnum((char)c); }
+ const LLTextSegmentPtr getPreviousSegment() const;
+ void getSelectedSegments(segment_vec_t& segments) const;
protected:
- //
- // Methods
- //
-
- S32 getLength() const { return mWText.length(); }
- void getSegmentAndOffset( S32 startpos, S32* segidxp, S32* offsetp ) const;
+ void showContextMenu(S32 x, S32 y);
void drawPreeditMarker();
- void updateLineStartList(S32 startpos = 0);
- void updateScrollFromCursor();
- void updateTextRect();
- const LLRect& getTextRect() const { return mTextRect; }
-
void assignEmbedded(const std::string &s);
- BOOL truncate(); // Returns true if truncation occurs
void removeCharOrTab();
- void setCursorAtLocalPos(S32 x, S32 y, BOOL round);
- S32 getCursorPosFromLocalCoord( S32 local_x, S32 local_y, BOOL round ) const;
void indentSelectedLines( S32 spaces );
S32 indentLine( S32 pos, S32 spaces );
void unindentLineBeforeCloseBrace();
- S32 getSegmentIdxAtOffset(S32 offset) const;
- const LLTextSegment* getSegmentAtLocalPos(S32 x, S32 y) const;
- const LLTextSegment* getSegmentAtOffset(S32 offset) const;
-
void reportBadKeystroke() { make_ui_sound("UISndBadKeystroke"); }
BOOL handleNavigationKey(const KEY key, const MASK mask);
@@ -302,66 +221,22 @@ protected:
BOOL handleControlKey(const KEY key, const MASK mask);
BOOL handleEditKey(const KEY key, const MASK mask);
- BOOL hasSelection() const { return (mSelectionStart !=mSelectionEnd); }
BOOL selectionContainsLineBreaks();
- void startSelection();
- void endSelection();
void deleteSelection(BOOL transient_operation);
S32 prevWordPos(S32 cursorPos) const;
S32 nextWordPos(S32 cursorPos) const;
- S32 getLineCount() const { return mLineStartList.size(); }
- S32 getLineStart( S32 line ) const;
- void getLineAndOffset(S32 pos, S32* linep, S32* offsetp) const;
- S32 getPos(S32 line, S32 offset);
-
- void changePage(S32 delta);
- void changeLine(S32 delta);
-
void autoIndent();
- void findEmbeddedItemSegments();
-
- virtual BOOL handleMouseUpOverSegment(S32 x, S32 y, MASK mask);
+ void findEmbeddedItemSegments(S32 start, S32 end);
+ void getSegmentsInRange(segment_vec_t& segments, S32 start, S32 end, bool include_partial) const;
virtual llwchar pasteEmbeddedItem(llwchar ext_char) { return ext_char; }
- virtual void bindEmbeddedChars(const LLFontGL* font) const {}
- virtual void unbindEmbeddedChars(const LLFontGL* font) const {}
- S32 findHTMLToken(const std::string &line, S32 pos, BOOL reverse) const;
- BOOL findHTML(const std::string &line, S32 *begin, S32 *end) const;
- // Abstract inner base class representing an undoable editor command.
- // Concrete sub-classes can be defined for operations such as insert, remove, etc.
- // Used as arguments to the execute() method below.
- class LLTextCmd
- {
- public:
- LLTextCmd( S32 pos, BOOL group_with_next ) : mPos(pos), mGroupWithNext(group_with_next) {}
- virtual ~LLTextCmd() {}
- virtual BOOL execute(LLTextEditor* editor, S32* delta) = 0;
- virtual S32 undo(LLTextEditor* editor) = 0;
- virtual S32 redo(LLTextEditor* editor) = 0;
- virtual BOOL canExtend(S32 pos) const { return FALSE; }
- virtual void blockExtensions() {}
- virtual BOOL extendAndExecute( LLTextEditor* editor, S32 pos, llwchar c, S32* delta ) { llassert(0); return 0; }
- virtual BOOL hasExtCharValue( llwchar value ) const { return FALSE; }
-
- // Defined here so they can access protected LLTextEditor editing methods
- S32 insert(LLTextEditor* editor, S32 pos, const LLWString &wstr) { return editor->insertStringNoUndo( pos, wstr ); }
- S32 remove(LLTextEditor* editor, S32 pos, S32 length) { return editor->removeStringNoUndo( pos, length ); }
- S32 overwrite(LLTextEditor* editor, S32 pos, llwchar wc) { return editor->overwriteCharNoUndo(pos, wc); }
-
- S32 getPosition() const { return mPos; }
- BOOL groupWithNext() const { return mGroupWithNext; }
-
- private:
- const S32 mPos;
- BOOL mGroupWithNext;
- };
// Here's the method that takes and applies text commands.
- S32 execute(LLTextCmd* cmd);
+ S32 execute(TextCmd* cmd);
// Undoable operations
void addChar(llwchar c); // at mCursorPos
@@ -369,17 +244,9 @@ protected:
S32 overwriteChar(S32 pos, llwchar wc);
void removeChar();
S32 removeChar(S32 pos);
- S32 insert(const S32 pos, const LLWString &wstr, const BOOL group_with_next_op);
- S32 remove(const S32 pos, const S32 length, const BOOL group_with_next_op);
- S32 append(const LLWString &wstr, const BOOL group_with_next_op);
+ S32 insert(S32 pos, const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment);
+ S32 remove(S32 pos, S32 length, bool group_with_next_op);
- // Direct operations
- S32 insertStringNoUndo(S32 pos, const LLWString &wstr); // returns num of chars actually inserted
- S32 removeStringNoUndo(S32 pos, S32 length);
- S32 overwriteCharNoUndo(S32 pos, llwchar wc);
-
- void resetKeystrokeTimer() { mKeystrokeTimer.reset(); }
-
void updateAllowingLanguageInput();
BOOL hasPreeditString() const;
@@ -392,6 +259,7 @@ protected:
virtual void getSelectionRange(S32 *position, S32 *length) const;
virtual BOOL getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect *bounds, LLRect *control) const;
virtual S32 getPreeditFontSize() const;
+ virtual LLWString getPreeditString() const { return getWText(); }
//
// Protected data
//
@@ -399,149 +267,60 @@ protected:
// as possible behind protected accessor methods.
//
- // I-beam is just after the mCursorPos-th character.
- S32 mCursorPos;
-
// Use these to determine if a click on an embedded item is a drag or not.
S32 mMouseDownX;
S32 mMouseDownY;
- // Are we in the middle of a drag-select? To figure out if there is a current
- // selection, call hasSelection().
- BOOL mIsSelecting;
- S32 mSelectionStart;
- S32 mSelectionEnd;
- S32 mLastSelectionX;
- S32 mLastSelectionY;
-
- BOOL mParseHTML;
- BOOL mParseHighlights;
- std::string mHTML;
-
- typedef std::vector<LLTextSegment *> segment_list_t;
- segment_list_t mSegments;
- const LLTextSegment* mHoverSegment;
-
- // Scrollbar data
- class LLScrollbar* mScrollbar;
- BOOL mHideScrollbarForShortDocs;
- BOOL mTakesNonScrollClicks;
- void (*mOnScrollEndCallback)(void*);
- void *mOnScrollEndData;
-
LLWString mPreeditWString;
LLWString mPreeditOverwrittenWString;
std::vector<S32> mPreeditPositions;
std::vector<BOOL> mPreeditStandouts;
-
-private:
+protected:
+ LLUIColor mDefaultColor;
+
+ BOOL mShowLineNumbers;
+
+ /*virtual*/ void updateSegments();
+ void updateLinkSegments();
+
+private:
//
// Methods
//
- void pasteHelper(bool is_primary);
+ void pasteHelper(bool is_primary);
- void updateSegments();
- void pruneSegments();
+ void drawLineNumbers();
- void drawBackground();
- void drawSelectionBackground();
- void drawCursor();
- void drawText();
- void drawClippedSegment(const LLWString &wtext, S32 seg_start, S32 seg_end, F32 x, F32 y, S32 selection_left, S32 selection_right, const LLStyleSP& color, F32* right_x);
-
- void needsReflow()
- {
- mReflowNeeded = TRUE;
- // cursor might have moved, need to scroll
- mScrollNeeded = TRUE;
- }
- void needsScroll() { mScrollNeeded = TRUE; }
+ void onKeyStroke();
//
// Data
//
LLKeywords mKeywords;
- static LLColor4 mLinkColor;
- static void (*mURLcallback) (const std::string& url);
- static bool (*mSecondlifeURLcallback) (const std::string& url);
- static bool (*mSecondlifeURLcallbackRightClick) (const std::string& url);
-
- // Concrete LLTextCmd sub-classes used by the LLTextEditor base class
- class LLTextCmdInsert;
- class LLTextCmdAddChar;
- class LLTextCmdOverwriteChar;
- class LLTextCmdRemove;
-
- LLWString mWText;
- mutable std::string mUTF8Text;
- mutable BOOL mTextIsUpToDate;
-
- S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes
- const LLFontGL* mGLFont;
+ // Concrete TextCmd sub-classes used by the LLTextEditor base class
+ class TextCmdInsert;
+ class TextCmdAddChar;
+ class TextCmdOverwriteChar;
+ class TextCmdRemove;
class LLViewBorder* mBorder;
BOOL mBaseDocIsPristine;
- LLTextCmd* mPristineCmd;
+ TextCmd* mPristineCmd;
- LLTextCmd* mLastCmd;
+ TextCmd* mLastCmd;
- typedef std::deque<LLTextCmd*> undo_stack_t;
+ typedef std::deque<TextCmd*> undo_stack_t;
undo_stack_t mUndoStack;
- S32 mDesiredXPixel; // X pixel position where the user wants the cursor to be
- LLRect mTextRect; // The rect in which text is drawn. Excludes borders.
- // List of offsets and segment index of the start of each line. Always has at least one node (0).
- struct line_info
- {
- line_info(S32 segment, S32 offset) : mSegment(segment), mOffset(offset) {}
- S32 mSegment;
- S32 mOffset;
- };
- struct line_info_compare
- {
- bool operator()(const line_info& a, const line_info& b) const
- {
- if (a.mSegment < b.mSegment)
- return true;
- else if (a.mSegment > b.mSegment)
- return false;
- else
- return a.mOffset < b.mOffset;
- }
- };
- typedef std::vector<line_info> line_list_t;
- line_list_t mLineStartList;
- BOOL mReflowNeeded;
- BOOL mScrollNeeded;
-
- LLFrameTimer mKeystrokeTimer;
-
- LLColor4 mCursorColor;
-
- LLColor4 mFgColor;
- LLColor4 mDefaultColor;
- LLColor4 mReadOnlyFgColor;
- LLColor4 mWriteableBgColor;
- LLColor4 mReadOnlyBgColor;
- LLColor4 mFocusBgColor;
-
- BOOL mReadOnly;
- BOOL mWordWrap;
- BOOL mShowLineNumbers;
-
BOOL mTabsToNextField; // if true, tab moves focus to next field, else inserts spaces
BOOL mCommitOnFocusLost;
BOOL mTakesFocus;
- BOOL mTrackBottom; // if true, keeps scroll position at bottom during resize
- BOOL mScrolledToBottom;
BOOL mAllowEmbeddedItems;
- BOOL mAcceptCallingCardNames;
-
LLUUID mSourceID;
// If true, the standard edit keys (Ctrl-X, Delete, etc,) are handled here
@@ -549,50 +328,16 @@ private:
BOOL mHandleEditKeysDirectly;
LLCoordGL mLastIMEPosition; // Last position of the IME editor
-}; // end class LLTextEditor
-
+ keystroke_signal_t mKeystrokeSignal;
-class LLTextSegment
-{
-public:
- // for creating a compare value
- LLTextSegment(S32 start);
- LLTextSegment( const LLStyleSP& style, S32 start, S32 end );
- LLTextSegment( const LLColor4& color, S32 start, S32 end, BOOL is_visible);
- LLTextSegment( const LLColor4& color, S32 start, S32 end );
- LLTextSegment( const LLColor3& color, S32 start, S32 end );
-
- S32 getStart() const { return mStart; }
- S32 getEnd() const { return mEnd; }
- void setEnd( S32 end ) { mEnd = end; }
- const LLColor4& getColor() const { return mStyle->getColor(); }
- void setColor(const LLColor4 &color) { mStyle->setColor(color); }
- const LLStyleSP& getStyle() const { return mStyle; }
- void setStyle(const LLStyleSP &style) { mStyle = style; }
- void setIsDefault(BOOL b) { mIsDefault = b; }
- BOOL getIsDefault() const { return mIsDefault; }
- void setToken( LLKeywordToken* token ) { mToken = token; }
- LLKeywordToken* getToken() const { return mToken; }
- BOOL getToolTip( std::string& msg ) const;
-
- void dump() const;
-
- struct compare
- {
- bool operator()(const LLTextSegment* a, const LLTextSegment* b) const
- {
- return a->mStart < b->mStart;
- }
- };
-
-private:
- LLStyleSP mStyle;
- S32 mStart;
- S32 mEnd;
- LLKeywordToken* mToken;
- BOOL mIsDefault;
-};
+ LLContextMenu* mContextMenu;
+}; // end class LLTextEditor
+// Build time optimization, generate once in .cpp file
+#ifndef LLTEXTEDITOR_CPP
+extern template class LLTextEditor* LLView::getChild<class LLTextEditor>(
+ const std::string& name, BOOL recurse) const;
+#endif
#endif // LL_TEXTEDITOR_
diff --git a/indra/llui/lltextparser.cpp b/indra/llui/lltextparser.cpp
index 227d24a865..76a39e3094 100644
--- a/indra/llui/lltextparser.cpp
+++ b/indra/llui/lltextparser.cpp
@@ -1,10 +1,9 @@
/**
- * @file lltexteditor.cpp
- * @brief LLTextEditor base class
+ * @file lltextparser.cpp
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
- * Copyright (c) 2001-2007, Linden Research, Inc.
+ * Copyright (c) 2001-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -12,12 +11,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
@@ -31,6 +31,8 @@
#include "linden_common.h"
+#include "lltextparser.h"
+
#include "llsd.h"
#include "llsdserialize.h"
#include "llerror.h"
@@ -39,23 +41,13 @@
#include "message.h"
#include "llmath.h"
#include "v4color.h"
-#include "audioengine.h"
-#include "llwindow.h"
#include "lldir.h"
-#include "lltextparser.h"
-//#include "lltexttospeech.h"
-
// Routines used for parsing text for TextParsers and html
LLTextParser* LLTextParser::sInstance = NULL;
//
-// Constants
-//
-const F32 SOUND_GAIN = 1.0f;
-
-//
// Member Functions
//
@@ -75,38 +67,7 @@ LLTextParser* LLTextParser::getInstance()
return sInstance;
}
-void LLTextParser::triggerAlerts(LLUUID agent_id, LLVector3d position, std::string text, LLWindow* viewer_window)
-{
-// bool spoken=FALSE;
- for (S32 i=0;i<mHighlights.size();i++)
- {
- if (findPattern(text,mHighlights[i]) >= 0 )
- {
- if(gAudiop)
- {
- if ((std::string)mHighlights[i]["sound_lluuid"] != LLUUID::null.asString())
- {
- gAudiop->triggerSound(mHighlights[i]["sound_lluuid"].asUUID(), agent_id, SOUND_GAIN, LLAudioEngine::AUDIO_TYPE_UI, position);
- }
-/*
- if (!spoken)
- {
- LLTextToSpeech* text_to_speech = NULL;
- text_to_speech = LLTextToSpeech::getInstance();
- spoken = text_to_speech->speak((LLString)mHighlights[i]["voice"],text);
- }
- */
- }
- if (mHighlights[i]["flash"])
- {
- if (viewer_window && viewer_window->getMinimized())
- {
- viewer_window->flashIcon(5.f);
- }
- }
- }
- }
-}
+// Moved triggerAlerts() to llfloaterchat.cpp to break llui/llaudio library dependency.
S32 LLTextParser::findPattern(const std::string &text, LLSD highlight)
{
@@ -142,7 +103,7 @@ S32 LLTextParser::findPattern(const std::string &text, LLSD highlight)
return found;
}
-LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLColor4 &color, S32 part, S32 index)
+LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLColor4 &color, EHighlightPosition part, S32 index)
{
//evil recursive string atomizer.
LLSD ret_llsd, start_llsd, middle_llsd, end_llsd;
@@ -161,7 +122,7 @@ LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLC
{
S32 end = std::string(mHighlights[i]["pattern"]).length();
S32 len = text.length();
- S32 newpart;
+ EHighlightPosition newpart;
if (start==0)
{
start_llsd[0]["text"] =text.substr(0,end);
diff --git a/indra/llui/lltextparser.h b/indra/llui/lltextparser.h
index 5c5c3f3301..072ac0f300 100644
--- a/indra/llui/lltextparser.h
+++ b/indra/llui/lltextparser.h
@@ -3,6 +3,30 @@
* @brief GUI for user-defined highlights
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*
*/
@@ -10,12 +34,8 @@
#ifndef LL_LLTEXTPARSER_H
#define LL_LLTEXTPARSER_H
-#include <vector>
-#include "linden_common.h"
+#include "llsd.h"
-#include "lltextparser.h"
-
-class LLSD;
class LLUUID;
class LLVector3d;
class LLColor4;
@@ -23,25 +43,25 @@ class LLColor4;
class LLTextParser
{
public:
- enum ConditionType { CONTAINS, MATCHES, STARTS_WITH, ENDS_WITH };
- enum HighlightType { PART, ALL };
- enum HighlightPosition { WHOLE, START, MIDDLE, END };
- enum DialogAction { ACTION_NONE, ACTION_CLOSE, ACTION_ADD, ACTION_COPY, ACTION_UPDATE };
+ typedef enum e_condition_type { CONTAINS, MATCHES, STARTS_WITH, ENDS_WITH } EConditionType;
+ typedef enum e_highlight_type { PART, ALL } EHighlightType;
+ typedef enum e_highlight_position { WHOLE, START, MIDDLE, END } EHighlightPosition;
+ typedef enum e_dialog_action { ACTION_NONE, ACTION_CLOSE, ACTION_ADD, ACTION_COPY, ACTION_UPDATE } EDialogAction;
static LLTextParser* getInstance();
LLTextParser(){};
~LLTextParser();
S32 findPattern(const std::string &text, LLSD highlight);
- LLSD parsePartialLineHighlights(const std::string &text,const LLColor4 &color,S32 part=WHOLE, S32 index=0);
+ LLSD parsePartialLineHighlights(const std::string &text,const LLColor4 &color, EHighlightPosition part=WHOLE, S32 index=0);
bool parseFullLineHighlights(const std::string &text, LLColor4 *color);
- void triggerAlerts(LLUUID agent_id, LLVector3d position, std::string text, LLWindow* viewer_window);
std::string getFileName();
LLSD loadFromDisk();
bool saveToDisk(LLSD highlights);
+
public:
- LLSD mHighlights;
+ LLSD mHighlights;
private:
static LLTextParser* sInstance;
};
diff --git a/indra/llui/lltoggleablemenu.cpp b/indra/llui/lltoggleablemenu.cpp
new file mode 100644
index 0000000000..5df1d35383
--- /dev/null
+++ b/indra/llui/lltoggleablemenu.cpp
@@ -0,0 +1,89 @@
+/**
+ * @file lltoggleablemenu.cpp
+ * @brief Menu toggled by a button press
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "linden_common.h"
+
+#include "lltoggleablemenu.h"
+#include "lluictrlfactory.h"
+
+static LLDefaultChildRegistry::Register<LLToggleableMenu> r("toggleable_menu");
+
+LLToggleableMenu::LLToggleableMenu(const LLToggleableMenu::Params& p)
+: LLMenuGL(p),
+ mButtonRect(),
+ mClosedByButtonClick(false)
+{
+}
+
+// virtual
+void LLToggleableMenu::handleVisibilityChange (BOOL curVisibilityIn)
+{
+ S32 x,y;
+ LLUI::getMousePositionLocal(LLUI::getRootView(), &x, &y);
+
+ if (!curVisibilityIn && mButtonRect.pointInRect(x, y))
+ {
+ mClosedByButtonClick = true;
+ }
+}
+
+void LLToggleableMenu::setButtonRect(const LLRect& rect, LLView* current_view)
+{
+ LLRect screen;
+ current_view->localRectToScreen(rect, &screen);
+ mButtonRect = screen;
+}
+
+void LLToggleableMenu::setButtonRect(LLView* current_view)
+{
+ LLRect rect = current_view->getLocalRect();
+ setButtonRect(rect, current_view);
+}
+
+bool LLToggleableMenu::toggleVisibility()
+{
+ if (mClosedByButtonClick)
+ {
+ mClosedByButtonClick = false;
+ return false;
+ }
+
+ if (getVisible())
+ {
+ setVisible(FALSE);
+ mClosedByButtonClick = false;
+ return false;
+ }
+
+ return true;
+}
diff --git a/indra/llui/lltoggleablemenu.h b/indra/llui/lltoggleablemenu.h
new file mode 100644
index 0000000000..9d8c5261b9
--- /dev/null
+++ b/indra/llui/lltoggleablemenu.h
@@ -0,0 +1,68 @@
+/**
+ * @file lltoggleablemenu.h
+ * @brief Menu toggled by a button press
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTOGGLEABLEMENU_H
+#define LL_LLTOGGLEABLEMENU_H
+
+#include "llmenugl.h"
+
+class LLToggleableMenu : public LLMenuGL
+{
+public:
+ //adding blank params to work around registration issue
+ //where LLToggleableMenu was owning the LLMenuGL param
+ //and menu.xml was never loaded
+ struct Params : public LLInitParam::Block<Params, LLMenuGL::Params>
+ {};
+protected:
+ LLToggleableMenu(const Params&);
+ friend class LLUICtrlFactory;
+public:
+ virtual void handleVisibilityChange (BOOL curVisibilityIn);
+
+ const LLRect& getButtonRect() const { return mButtonRect; }
+
+ // Converts the given local button rect to a screen rect
+ void setButtonRect(const LLRect& rect, LLView* current_view);
+ void setButtonRect(LLView* current_view);
+
+ // Returns "true" if menu was not closed by button click
+ // and is not still visible. If menu is visible toggles
+ // its visibility off.
+ bool toggleVisibility();
+
+protected:
+ bool mClosedByButtonClick;
+ LLRect mButtonRect;
+};
+
+#endif // LL_LLTOGGLEABLEMENU_H
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
new file mode 100644
index 0000000000..01c7a81309
--- /dev/null
+++ b/indra/llui/lltooltip.cpp
@@ -0,0 +1,600 @@
+/**
+ * @file lltooltip.cpp
+ * @brief LLToolTipMgr class implementation and related classes
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+// self include
+#include "lltooltip.h"
+
+// Library includes
+#include "lltextbox.h"
+#include "lliconctrl.h"
+#include "llbutton.h"
+#include "llmenugl.h" // hideMenus()
+#include "llui.h" // positionViewNearMouse()
+#include "llwindow.h"
+#include "lltrans.h"
+//
+// Constants
+//
+
+//
+// Local globals
+//
+
+LLToolTipView *gToolTipView = NULL;
+
+//
+// Member functions
+//
+
+static LLDefaultChildRegistry::Register<LLToolTipView> register_tooltip_view("tooltip_view");
+
+LLToolTipView::Params::Params()
+{
+ mouse_opaque = false;
+}
+
+LLToolTipView::LLToolTipView(const LLToolTipView::Params& p)
+: LLView(p)
+{
+}
+
+void LLToolTipView::draw()
+{
+ LLToolTipMgr::instance().updateToolTipVisibility();
+
+ // do the usual thing
+ LLView::draw();
+}
+
+BOOL LLToolTipView::handleHover(S32 x, S32 y, MASK mask)
+{
+ static S32 last_x = x;
+ static S32 last_y = y;
+
+ LLToolTipMgr& tooltip_mgr = LLToolTipMgr::instance();
+
+ if (x != last_x && y != last_y)
+ {
+ // allow new tooltips because mouse moved
+ tooltip_mgr.unblockToolTips();
+ }
+
+ last_x = x;
+ last_y = y;
+ return LLView::handleHover(x, y, mask);
+}
+
+BOOL LLToolTipView::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ LLToolTipMgr::instance().blockToolTips();
+
+ if (LLView::handleMouseDown(x, y, mask))
+ {
+ // If we are handling the mouse event menu holder
+ // won't get a chance to close menus so do this here
+ LLMenuGL::sMenuContainer->hideMenus();
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL LLToolTipView::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
+{
+ LLToolTipMgr::instance().blockToolTips();
+ return LLView::handleMiddleMouseDown(x, y, mask);
+}
+
+BOOL LLToolTipView::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ LLToolTipMgr::instance().blockToolTips();
+ return LLView::handleRightMouseDown(x, y, mask);
+}
+
+
+BOOL LLToolTipView::handleScrollWheel( S32 x, S32 y, S32 clicks )
+{
+ LLToolTipMgr::instance().blockToolTips();
+ return FALSE;
+}
+
+void LLToolTipView::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ LLToolTipMgr::instance().blockToolTips();
+}
+
+
+void LLToolTipView::drawStickyRect()
+{
+ gl_rect_2d(LLToolTipMgr::instance().getMouseNearRect(), LLColor4::white, false);
+}
+
+// defaults for floater param block pulled from widgets/floater.xml
+static LLWidgetNameRegistry::StaticRegistrar sRegisterInspectorParams(&typeid(LLInspector::Params), "inspector");
+
+//
+// LLToolTip
+//
+
+
+static LLDefaultChildRegistry::Register<LLToolTip> register_tooltip("tool_tip");
+
+
+LLToolTip::Params::Params()
+: max_width("max_width", 200),
+ padding("padding", 4),
+ wrap("wrap", true),
+ pos("pos"),
+ message("message"),
+ delay_time("delay_time", LLUI::sSettingGroups["config"]->getF32( "ToolTipDelay" )),
+ visible_time_over("visible_time_over", LLUI::sSettingGroups["config"]->getF32( "ToolTipVisibleTimeOver" )),
+ visible_time_near("visible_time_near", LLUI::sSettingGroups["config"]->getF32( "ToolTipVisibleTimeNear" )),
+ visible_time_far("visible_time_far", LLUI::sSettingGroups["config"]->getF32( "ToolTipVisibleTimeFar" )),
+ sticky_rect("sticky_rect"),
+ image("image"),
+ text_color("text_color"),
+ time_based_media("time_based_media", false),
+ web_based_media("web_based_media", false),
+ media_playing("media_playing", false)
+{
+ chrome = true;
+}
+
+LLToolTip::LLToolTip(const LLToolTip::Params& p)
+: LLPanel(p),
+ mHasClickCallback(p.click_callback.isProvided()),
+ mPadding(p.padding),
+ mTextBox(NULL),
+ mInfoButton(NULL),
+ mPlayMediaButton(NULL),
+ mHomePageButton(NULL)
+{
+ LLTextBox::Params params;
+ params.name = params.initial_value().asString();
+ // bake textbox padding into initial rect
+ params.rect = LLRect (mPadding, mPadding + 1, mPadding + 1, mPadding);
+ params.h_pad = 0;
+ params.v_pad = 0;
+ params.mouse_opaque = false;
+ params.text_color = p.text_color;
+ params.bg_visible = false;
+ params.font = p.font;
+ params.use_ellipses = true;
+ params.wrap = p.wrap;
+ params.allow_html = false; // disallow hyperlinks in tooltips, as they want to spawn their own explanatory tooltips
+ mTextBox = LLUICtrlFactory::create<LLTextBox> (params);
+ addChild(mTextBox);
+
+ S32 TOOLTIP_ICON_SIZE = 0;
+ S32 TOOLTIP_PLAYBUTTON_SIZE = 0;
+ if (p.image.isProvided())
+ {
+ LLButton::Params icon_params;
+ icon_params.name = "tooltip_info";
+ icon_params.label(""); // provid label but set to empty so name does not overwrite it -angela
+ LLRect icon_rect;
+ LLUIImage* imagep = p.image;
+ TOOLTIP_ICON_SIZE = (imagep ? imagep->getWidth() : 16);
+ icon_rect.setOriginAndSize(mPadding, mPadding, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE);
+ icon_params.rect = icon_rect;
+ icon_params.image_unselected(imagep);
+ icon_params.image_selected(imagep);
+
+ icon_params.scale_image(true);
+ icon_params.flash_color(icon_params.highlight_color());
+ mInfoButton = LLUICtrlFactory::create<LLButton>(icon_params);
+ if (p.click_callback.isProvided())
+ {
+ mInfoButton->setCommitCallback(boost::bind(p.click_callback()));
+ }
+ addChild(mInfoButton);
+
+ // move text over to fit image in
+ mTextBox->translate(TOOLTIP_ICON_SIZE + mPadding, 0);
+ }
+
+ if (p.time_based_media)
+ {
+ LLButton::Params p_button;
+ p_button.name(std::string("play_media"));
+ p_button.label(""); // provide label but set to empty so name does not overwrite it -angela
+ TOOLTIP_PLAYBUTTON_SIZE = 16;
+ LLRect button_rect;
+ button_rect.setOriginAndSize((mPadding +TOOLTIP_ICON_SIZE+ mPadding ), mPadding, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE);
+ p_button.rect = button_rect;
+ p_button.image_selected.name("button_anim_pause.tga");
+ p_button.image_unselected.name("button_anim_play.tga");
+ p_button.scale_image(true);
+
+ mPlayMediaButton = LLUICtrlFactory::create<LLButton>(p_button);
+ if(p.click_playmedia_callback.isProvided())
+ {
+ mPlayMediaButton->setCommitCallback(boost::bind(p.click_playmedia_callback()));
+ }
+ mPlayMediaButton->setToggleState(p.media_playing);
+ addChild(mPlayMediaButton);
+
+ // move text over to fit image in
+ mTextBox->translate(TOOLTIP_PLAYBUTTON_SIZE + mPadding, 0);
+ }
+
+ if (p.web_based_media)
+ {
+ LLButton::Params p_w_button;
+ p_w_button.name(std::string("home_page"));
+ p_w_button.label(""); // provid label but set to empty so name does not overwrite it -angela
+ TOOLTIP_PLAYBUTTON_SIZE = 16;
+ LLRect button_rect;
+ button_rect.setOriginAndSize((mPadding +TOOLTIP_ICON_SIZE+ mPadding ), mPadding, TOOLTIP_ICON_SIZE, TOOLTIP_ICON_SIZE);
+ p_w_button.rect = button_rect;
+ p_w_button.image_unselected.name("map_home.tga");
+ p_w_button.scale_image(true);
+
+ mHomePageButton = LLUICtrlFactory::create<LLButton>(p_w_button);
+ if(p.click_homepage_callback.isProvided())
+ {
+ mHomePageButton->setCommitCallback(boost::bind(p.click_homepage_callback()));
+ }
+ addChild(mHomePageButton);
+
+ // move text over to fit image in
+ mTextBox->translate(TOOLTIP_PLAYBUTTON_SIZE + mPadding, 0);
+ }
+
+ if (p.click_callback.isProvided())
+ {
+ setMouseUpCallback(boost::bind(p.click_callback()));
+ }
+}
+
+void LLToolTip::initFromParams(const LLToolTip::Params& p)
+{
+ LLPanel::initFromParams(p);
+
+ // do this *after* we've had our size set in LLPanel::initFromParams();
+ const S32 REALLY_LARGE_HEIGHT = 10000;
+ mTextBox->reshape(p.max_width, REALLY_LARGE_HEIGHT);
+
+ if (p.styled_message.isProvided())
+ {
+ for (LLInitParam::ParamIterator<LLToolTip::StyledText>::const_iterator text_it = p.styled_message().begin();
+ text_it != p.styled_message().end();
+ ++text_it)
+ {
+ mTextBox->appendText(text_it->text(), false, text_it->style);
+ }
+ }
+ else
+ {
+ mTextBox->setText(p.message());
+ }
+
+ S32 text_width = llmin(p.max_width(), mTextBox->getTextPixelWidth());
+ S32 text_height = mTextBox->getTextPixelHeight();
+ mTextBox->reshape(text_width, text_height);
+
+ // reshape tooltip panel to fit text box
+ LLRect tooltip_rect = calcBoundingRect();
+ tooltip_rect.mTop += mPadding;
+ tooltip_rect.mRight += mPadding;
+ tooltip_rect.mBottom = 0;
+ tooltip_rect.mLeft = 0;
+
+ setShape(tooltip_rect);
+}
+
+void LLToolTip::setVisible(BOOL visible)
+{
+ // fade out tooltip over time
+ if (visible)
+ {
+ mVisibleTimer.start();
+ mFadeTimer.stop();
+ LLPanel::setVisible(TRUE);
+ }
+ else
+ {
+ mVisibleTimer.stop();
+ // don't actually change mVisible state, start fade out transition instead
+ if (!mFadeTimer.getStarted())
+ {
+ mFadeTimer.start();
+ }
+ }
+}
+
+BOOL LLToolTip::handleHover(S32 x, S32 y, MASK mask)
+{
+ //mInfoButton->setFlashing(true);
+ if(mInfoButton)
+ mInfoButton->setHighlight(true);
+
+ LLPanel::handleHover(x, y, mask);
+ if (mHasClickCallback)
+ {
+ getWindow()->setCursor(UI_CURSOR_HAND);
+ }
+ return TRUE;
+}
+
+void LLToolTip::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ //mInfoButton->setFlashing(true);
+ if(mInfoButton)
+ mInfoButton->setHighlight(false);
+ LLUICtrl::onMouseLeave(x, y, mask);
+}
+
+void LLToolTip::draw()
+{
+ F32 alpha = 1.f;
+
+ if (mFadeTimer.getStarted())
+ {
+ F32 tool_tip_fade_time = LLUI::sSettingGroups["config"]->getF32("ToolTipFadeTime");
+ alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, tool_tip_fade_time, 1.f, 0.f);
+ if (alpha == 0.f)
+ {
+ // finished fading out, so hide ourselves
+ mFadeTimer.stop();
+ LLPanel::setVisible(false);
+ }
+ }
+
+ // draw tooltip contents with appropriate alpha
+ {
+ LLViewDrawContext context(alpha);
+ LLPanel::draw();
+ }
+}
+
+bool LLToolTip::isFading()
+{
+ return mFadeTimer.getStarted();
+}
+
+F32 LLToolTip::getVisibleTime()
+{
+ return mVisibleTimer.getStarted() ? mVisibleTimer.getElapsedTimeF32() : 0.f;
+}
+
+bool LLToolTip::hasClickCallback()
+{
+ return mHasClickCallback;
+}
+
+
+//
+// LLToolTipMgr
+//
+
+LLToolTipMgr::LLToolTipMgr()
+: mToolTip(NULL),
+ mNeedsToolTip(false)
+{}
+
+void LLToolTipMgr::createToolTip(const LLToolTip::Params& params)
+{
+ // block all other tooltips until tooltips re-enabled (e.g. mouse moved)
+ blockToolTips();
+
+ delete mToolTip;
+
+ LLToolTip::Params tooltip_params(params);
+ // block mouse events if there is a click handler registered (specifically, hover)
+ if (params.click_callback.isProvided())
+ {
+ // set mouse_opaque to true if it wasn't already set to something else
+ // this prevents mouse down from going "through" the tooltip and ultimately
+ // causing the tooltip to disappear
+ tooltip_params.mouse_opaque.setIfNotProvided(true);
+ }
+ tooltip_params.rect = LLRect (0, 1, 1, 0);
+
+ mToolTip = LLUICtrlFactory::create<LLToolTip> (tooltip_params);
+
+ gToolTipView->addChild(mToolTip);
+
+ if (params.pos.isProvided())
+ {
+ LLCoordGL pos = params.pos;
+ // try to spawn at requested position
+ LLUI::positionViewNearMouse(mToolTip, pos.mX, pos.mY);
+ }
+ else
+ {
+ // just spawn at mouse location
+ LLUI::positionViewNearMouse(mToolTip);
+ }
+
+ //...update "sticky" rect and tooltip position
+ if (params.sticky_rect.isProvided())
+ {
+ mMouseNearRect = params.sticky_rect;
+ }
+ else
+ {
+ S32 mouse_x;
+ S32 mouse_y;
+ LLUI::getMousePositionLocal(gToolTipView->getParent(), &mouse_x, &mouse_y);
+
+ // allow mouse a little bit of slop before changing tooltips
+ mMouseNearRect.setCenterAndSize(mouse_x, mouse_y, 3, 3);
+ }
+
+ // allow mouse to move all the way to the tooltip without changing tooltips
+ // (tooltip can still time out)
+ if (mToolTip->hasClickCallback())
+ {
+ // keep tooltip up when we mouse over it
+ mMouseNearRect.unionWith(mToolTip->getRect());
+ }
+}
+
+
+void LLToolTipMgr::show(const std::string& msg)
+{
+ show(LLToolTip::Params().message(msg));
+}
+
+void LLToolTipMgr::show(const LLToolTip::Params& params)
+{
+ // fill in default tooltip params from tool_tip.xml
+ LLToolTip::Params params_with_defaults(params);
+ params_with_defaults.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLToolTip>());
+ if (!params_with_defaults.validateBlock())
+ {
+ llwarns << "Could not display tooltip!" << llendl;
+ return;
+ }
+
+ S32 mouse_x;
+ S32 mouse_y;
+ LLUI::getMousePositionLocal(gToolTipView, &mouse_x, &mouse_y);
+
+ // are we ready to show the tooltip?
+ if (!mToolTipsBlocked // we haven't hit a key, moved the mouse, etc.
+ && LLUI::getMouseIdleTime() > params_with_defaults.delay_time) // the mouse has been still long enough
+ {
+ bool tooltip_changed = mLastToolTipParams.message() != params_with_defaults.message()
+ || mLastToolTipParams.pos() != params_with_defaults.pos()
+ || mLastToolTipParams.time_based_media() != params_with_defaults.time_based_media()
+ || mLastToolTipParams.web_based_media() != params_with_defaults.web_based_media();
+
+ bool tooltip_shown = mToolTip
+ && mToolTip->getVisible()
+ && !mToolTip->isFading();
+
+ mNeedsToolTip = tooltip_changed || !tooltip_shown;
+ // store description of tooltip for later creation
+ mNextToolTipParams = params_with_defaults;
+ }
+}
+
+// allow new tooltips to be created, e.g. after mouse has moved
+void LLToolTipMgr::unblockToolTips()
+{
+ mToolTipsBlocked = false;
+}
+
+// disallow new tooltips until unblockTooltips called
+void LLToolTipMgr::blockToolTips()
+{
+ hideToolTips();
+ mToolTipsBlocked = true;
+}
+
+void LLToolTipMgr::hideToolTips()
+{
+ if (mToolTip)
+ {
+ mToolTip->setVisible(FALSE);
+ }
+}
+
+bool LLToolTipMgr::toolTipVisible()
+{
+ return mToolTip ? mToolTip->isInVisibleChain() : false;
+}
+
+LLRect LLToolTipMgr::getToolTipRect()
+{
+ if (mToolTip && mToolTip->getVisible())
+ {
+ return mToolTip->getRect();
+ }
+ return LLRect();
+}
+
+
+LLRect LLToolTipMgr::getMouseNearRect()
+{
+ return toolTipVisible() ? mMouseNearRect : LLRect();
+}
+
+// every frame, determine if current tooltip should be hidden
+void LLToolTipMgr::updateToolTipVisibility()
+{
+ // create new tooltip if we have one ready to go
+ if (mNeedsToolTip)
+ {
+ mNeedsToolTip = false;
+ createToolTip(mNextToolTipParams);
+ mLastToolTipParams = mNextToolTipParams;
+
+ return;
+ }
+
+ // hide tooltips when mouse cursor is hidden
+ if (LLUI::getWindow()->isCursorHidden())
+ {
+ blockToolTips();
+ return;
+ }
+
+ // hide existing tooltips if they have timed out
+ S32 mouse_x, mouse_y;
+ LLUI::getMousePositionLocal(gToolTipView, &mouse_x, &mouse_y);
+
+ F32 tooltip_timeout = 0.f;
+ if (toolTipVisible())
+ {
+ // mouse far away from tooltip
+ tooltip_timeout = mLastToolTipParams.visible_time_far;
+ // mouse near rect will only include the tooltip if the
+ // tooltip is clickable
+ if (mMouseNearRect.pointInRect(mouse_x, mouse_y))
+ {
+ // mouse "close" to tooltip
+ tooltip_timeout = mLastToolTipParams.visible_time_near;
+
+ // if tooltip is clickable (has large mMouseNearRect)
+ // than having cursor over tooltip keeps it up indefinitely
+ if (mToolTip->parentPointInView(mouse_x, mouse_y))
+ {
+ // mouse over tooltip itself, don't time out
+ tooltip_timeout = mLastToolTipParams.visible_time_over;
+ }
+ }
+
+ if (mToolTip->getVisibleTime() > tooltip_timeout)
+ {
+ hideToolTips();
+ }
+ }
+}
+
+
+
+// EOF
diff --git a/indra/llui/lltooltip.h b/indra/llui/lltooltip.h
new file mode 100644
index 0000000000..7978b6a583
--- /dev/null
+++ b/indra/llui/lltooltip.h
@@ -0,0 +1,173 @@
+/**
+ * @file lltooltip.h
+ * @brief LLToolTipMgr class definition and related classes
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTOOLTIP_H
+#define LL_LLTOOLTIP_H
+
+// Library includes
+#include "llsingleton.h"
+#include "llinitparam.h"
+#include "llpanel.h"
+#include "llstyle.h"
+
+//
+// Classes
+//
+class LLToolTipView : public LLView
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
+ {
+ Params();
+ };
+ LLToolTipView(const LLToolTipView::Params&);
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
+
+ /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
+
+ void drawStickyRect();
+
+ /*virtual*/ void draw();
+};
+
+class LLToolTip : public LLPanel
+{
+public:
+
+ struct StyledText : public LLInitParam::Block<StyledText>
+ {
+ Mandatory<std::string> text;
+ Optional<LLStyle::Params> style;
+ };
+
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ typedef boost::function<void(void)> click_callback_t;
+
+ Optional<std::string> message;
+ Multiple<StyledText> styled_message;
+
+ Optional<LLCoordGL> pos;
+ Optional<F32> delay_time,
+ visible_time_over, // time for which tooltip is visible while mouse on it
+ visible_time_near, // time for which tooltip is visible while mouse near it
+ visible_time_far; // time for which tooltip is visible while mouse moved away
+ Optional<LLRect> sticky_rect;
+ Optional<const LLFontGL*> font;
+ Optional<LLUIImage*> image;
+ Optional<LLUIColor> text_color;
+ Optional<bool> time_based_media,
+ web_based_media,
+ media_playing;
+ Optional<click_callback_t> click_callback,
+ click_playmedia_callback,
+ click_homepage_callback;
+ Optional<S32> max_width,
+ padding;
+ Optional<bool> wrap;
+
+ Params();
+ };
+ /*virtual*/ void draw();
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+ /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
+ /*virtual*/ void setVisible(BOOL visible);
+
+ bool isFading();
+ F32 getVisibleTime();
+ bool hasClickCallback();
+
+ LLToolTip(const Params& p);
+ void initFromParams(const LLToolTip::Params& params);
+
+private:
+ class LLTextBox* mTextBox;
+ class LLButton* mInfoButton;
+ class LLButton* mPlayMediaButton;
+ class LLButton* mHomePageButton;
+
+ LLFrameTimer mFadeTimer;
+ LLFrameTimer mVisibleTimer;
+ bool mHasClickCallback;
+ S32 mPadding; // pixels
+};
+
+// used for the inspector tooltips which need different background images etc.
+class LLInspector : public LLToolTip
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLToolTip::Params> {};
+};
+
+class LLToolTipMgr : public LLSingleton<LLToolTipMgr>
+{
+ LOG_CLASS(LLToolTipMgr);
+public:
+ LLToolTipMgr();
+ void show(const LLToolTip::Params& params);
+ void show(const std::string& message);
+
+ void unblockToolTips();
+ void blockToolTips();
+
+ void hideToolTips();
+ bool toolTipVisible();
+ LLRect getToolTipRect();
+ LLRect getMouseNearRect();
+ void updateToolTipVisibility();
+
+private:
+ void createToolTip(const LLToolTip::Params& params);
+
+ bool mToolTipsBlocked;
+ class LLToolTip* mToolTip;
+
+ // tooltip creation is deferred until the UI is drawn every frame
+ // so the last tooltip to be created in a given frame will win
+ LLToolTip::Params mLastToolTipParams; // description of last tooltip we showed
+ LLToolTip::Params mNextToolTipParams; // description of next tooltip we want to show
+ bool mNeedsToolTip; // do we want to show a tooltip
+
+ LLRect mMouseNearRect;
+};
+
+//
+// Globals
+//
+
+extern LLToolTipView *gToolTipView;
+
+#endif
diff --git a/indra/llui/lltransutil.cpp b/indra/llui/lltransutil.cpp
new file mode 100644
index 0000000000..eaee260c7a
--- /dev/null
+++ b/indra/llui/lltransutil.cpp
@@ -0,0 +1,67 @@
+/**
+ * @file lltrans.cpp
+ * @brief LLTrans implementation
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltrans.h"
+#include "lluictrlfactory.h"
+
+#include "lltransutil.h"
+
+
+bool LLTransUtil::parseStrings(const std::string& xml_filename, const std::set<std::string>& default_args)
+{
+ LLXMLNodePtr root;
+ BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root);
+ if (!success)
+ {
+ llerrs << "Couldn't load string table" << llendl;
+ return false;
+ }
+
+ return LLTrans::parseStrings(root, default_args);
+}
+
+
+bool LLTransUtil::parseLanguageStrings(const std::string& xml_filename)
+{
+ LLXMLNodePtr root;
+ BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root);
+
+ if (!success)
+ {
+ llerrs << "Couldn't load string table " << xml_filename << llendl;
+ return false;
+ }
+
+ return LLTrans::parseLanguageStrings(root);
+}
diff --git a/indra/llui/lltransutil.h b/indra/llui/lltransutil.h
new file mode 100644
index 0000000000..2ddfd81361
--- /dev/null
+++ b/indra/llui/lltransutil.h
@@ -0,0 +1,51 @@
+/**
+ * @file lltransutil.h
+ * @brief LLTrans helper
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_TRANSUTIL_H
+#define LL_TRANSUTIL_H
+
+#include "lltrans.h"
+
+namespace LLTransUtil
+{
+ /**
+ * @brief Parses the xml file that holds the strings. Used once on startup
+ * @param xml_filename Filename to parse
+ * @param default_args Set of strings (expected to be in the file) to use as default replacement args, e.g. "SECOND_LIFE"
+ * @returns true if the file was parsed successfully, true if something went wrong
+ */
+ bool parseStrings(const std::string& xml_filename, const std::set<std::string>& default_args);
+
+ bool parseLanguageStrings(const std::string& xml_filename);
+};
+
+#endif
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index 57ce13c9c6..d0ed3b6fca 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -38,45 +38,60 @@
#include <map>
// Linden library includes
-#include "audioengine.h"
#include "v2math.h"
#include "v4color.h"
#include "llrender.h"
#include "llrect.h"
-#include "llimagegl.h"
#include "lldir.h"
-#include "llfontgl.h"
+#include "llgl.h"
// Project includes
#include "llcontrol.h"
#include "llui.h"
+#include "lluicolortable.h"
#include "llview.h"
#include "lllineeditor.h"
+#include "llfloater.h"
+#include "llfloaterreg.h"
+#include "llmenugl.h"
+#include "llmenubutton.h"
#include "llwindow.h"
+// for registration
+#include "llfiltereditor.h"
+#include "llflyoutbutton.h"
+#include "llsearcheditor.h"
+
+// for XUIParse
+#include "llquaternion.h"
+#include <boost/tokenizer.hpp>
+
//
// Globals
//
const LLColor4 UI_VERTEX_COLOR(1.f, 1.f, 1.f, 1.f);
-// Used to hide the flashing text cursor when window doesn't have focus.
-BOOL gShowTextEditCursor = TRUE;
-
// Language for UI construction
std::map<std::string, std::string> gTranslation;
std::list<std::string> gUntranslated;
+/*static*/ LLUI::settings_map_t LLUI::sSettingGroups;
+/*static*/ LLImageProviderInterface* LLUI::sImageProvider = NULL;
+/*static*/ LLUIAudioCallback LLUI::sAudioCallback = NULL;
+/*static*/ LLVector2 LLUI::sGLScaleFactor(1.f, 1.f);
+/*static*/ LLWindow* LLUI::sWindow = NULL;
+/*static*/ LLView* LLUI::sRootView = NULL;
+/*static*/ BOOL LLUI::sDirty = FALSE;
+/*static*/ LLRect LLUI::sDirtyRect;
+/*static*/ LLHelp* LLUI::sHelpImpl = NULL;
+/*static*/ std::vector<std::string> LLUI::sXUIPaths;
+/*static*/ LLFrameTimer LLUI::sMouseIdleTimer;
+
+// register filtereditor here
+static LLDefaultChildRegistry::Register<LLFilterEditor> register_filter_editor("filter_editor");
+static LLDefaultChildRegistry::Register<LLFlyoutButton> register_flyout_button("flyout_button");
+static LLDefaultChildRegistry::Register<LLSearchEditor> register_search_editor("search_editor");
+static LLDefaultChildRegistry::Register<LLMenuButton> register_menu_button("menu_button");
-LLControlGroup* LLUI::sConfigGroup = NULL;
-LLControlGroup* LLUI::sIgnoresGroup = NULL;
-LLControlGroup* LLUI::sColorsGroup = NULL;
-LLImageProviderInterface* LLUI::sImageProvider = NULL;
-LLUIAudioCallback LLUI::sAudioCallback = NULL;
-LLVector2 LLUI::sGLScaleFactor(1.f, 1.f);
-LLWindow* LLUI::sWindow = NULL;
-LLHtmlHelp* LLUI::sHtmlHelp = NULL;
-BOOL LLUI::sShowXUINames = FALSE;
-std::stack<LLRect> LLScreenClipRect::sClipRectStack;
-BOOL LLUI::sQAMode = FALSE;
//
// Functions
@@ -84,18 +99,18 @@ BOOL LLUI::sQAMode = FALSE;
void make_ui_sound(const char* namep)
{
std::string name = ll_safe_string(namep);
- if (!LLUI::sConfigGroup->controlExists(name))
+ if (!LLUI::sSettingGroups["config"]->controlExists(name))
{
llwarns << "tried to make ui sound for unknown sound name: " << name << llendl;
}
else
{
- LLUUID uuid(LLUI::sConfigGroup->getString(name));
+ LLUUID uuid(LLUI::sSettingGroups["config"]->getString(name));
if (uuid.isNull())
{
- if (LLUI::sConfigGroup->getString(name) == LLUUID::null.asString())
+ if (LLUI::sSettingGroups["config"]->getString(name) == LLUUID::null.asString())
{
- if (LLUI::sConfigGroup->getBOOL("UISndDebugSpamToggle"))
+ if (LLUI::sSettingGroups["config"]->getBOOL("UISndDebugSpamToggle"))
{
llinfos << "ui sound name: " << name << " triggered but silent (null uuid)" << llendl;
}
@@ -108,7 +123,7 @@ void make_ui_sound(const char* namep)
}
else if (LLUI::sAudioCallback != NULL)
{
- if (LLUI::sConfigGroup->getBOOL("UISndDebugSpamToggle"))
+ if (LLUI::sSettingGroups["config"]->getBOOL("UISndDebugSpamToggle"))
{
llinfos << "ui sound name: " << name << llendl;
}
@@ -408,7 +423,7 @@ void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max
}
-void gl_draw_image( S32 x, S32 y, LLImageGL* image, const LLColor4& color, const LLRectf& uv_rect )
+void gl_draw_image( S32 x, S32 y, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect )
{
if (NULL == image)
{
@@ -418,7 +433,7 @@ void gl_draw_image( S32 x, S32 y, LLImageGL* image, const LLColor4& color, const
gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), 0.f, image, color, uv_rect );
}
-void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color, const LLRectf& uv_rect)
+void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect)
{
if (NULL == image)
{
@@ -428,7 +443,7 @@ void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLImageGL* image,
gl_draw_scaled_rotated_image( x, y, width, height, 0.f, image, color, uv_rect );
}
-void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLImageGL* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect)
+void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect)
{
if (NULL == image)
{
@@ -444,7 +459,7 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border
gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect);
}
-void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect, const LLRectf& scale_rect)
+void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect, const LLRectf& scale_rect)
{
stop_glerror();
@@ -630,12 +645,12 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLIma
}
}
-void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLImageGL* image, const LLColor4& color, const LLRectf& uv_rect)
+void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect)
{
gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color, uv_rect );
}
-void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLImageGL* image, const LLColor4& color, const LLRectf& uv_rect)
+void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect)
{
if (NULL == image)
{
@@ -681,44 +696,6 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre
}
-void gl_draw_scaled_image_inverted(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color, const LLRectf& uv_rect)
-{
- if (NULL == image)
- {
- llwarns << "image == NULL; aborting function" << llendl;
- return;
- }
-
- LLGLSUIDefault gls_ui;
-
- gGL.pushMatrix();
- {
- gGL.translatef((F32)x, (F32)y, 0.f);
-
- gGL.getTexUnit(0)->bind(image);
-
- gGL.color4fv(color.mV);
-
- gGL.begin(LLRender::QUADS);
- {
- gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
- gGL.vertex2i(width, height );
-
- gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
- gGL.vertex2i(0, height );
-
- gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
- gGL.vertex2i(0, 0);
-
- gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
- gGL.vertex2i(width, 0);
- }
- gGL.end();
- }
- gGL.popMatrix();
-}
-
-
void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase )
{
phase = fmod(phase, 1.f);
@@ -1548,27 +1525,17 @@ void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3
gl_segmented_rect_3d_tex(border_scale, border_width, border_height, width_vec, height_vec, ROUNDED_RECT_TOP);
}
-bool handleShowXUINamesChanged(const LLSD& newvalue)
-{
- LLUI::sShowXUINames = newvalue.asBoolean();
- return true;
-}
-
-void LLUI::initClass(LLControlGroup* config,
- LLControlGroup* ignores,
- LLControlGroup* colors,
+void LLUI::initClass(const settings_map_t& settings,
LLImageProviderInterface* image_provider,
LLUIAudioCallback audio_callback,
const LLVector2* scale_factor,
const std::string& language)
{
- sConfigGroup = config;
- sIgnoresGroup = ignores;
- sColorsGroup = colors;
+ sSettingGroups = settings;
- if (sConfigGroup == NULL
- || sIgnoresGroup == NULL
- || sColorsGroup == NULL)
+ if ((get_ptr_in_map(sSettingGroups, std::string("config")) == NULL) ||
+ (get_ptr_in_map(sSettingGroups, std::string("floater")) == NULL) ||
+ (get_ptr_in_map(sSettingGroups, std::string("ignores")) == NULL))
{
llerrs << "Failure to initialize configuration groups" << llendl;
}
@@ -1577,18 +1544,49 @@ void LLUI::initClass(LLControlGroup* config,
sAudioCallback = audio_callback;
sGLScaleFactor = (scale_factor == NULL) ? LLVector2(1.f, 1.f) : *scale_factor;
sWindow = NULL; // set later in startup
- LLFontGL::sShadowColor = colors->getColor("ColorDropShadow");
+ LLFontGL::sShadowColor = LLUIColorTable::instance().getColor("ColorDropShadow");
+
+ // Callbacks for associating controls with floater visibilty:
+ LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Floater.Toggle", boost::bind(&LLFloaterReg::toggleFloaterInstance, _2));
+ LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Floater.Show", boost::bind(&LLFloaterReg::showFloaterInstance, _2));
+ LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Floater.Hide", boost::bind(&LLFloaterReg::hideFloaterInstance, _2));
+ LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Floater.InitToVisibilityControl", boost::bind(&LLFloaterReg::initUICtrlToFloaterVisibilityControl, _1, _2));
+
+ // Button initialization callback for toggle buttons
+ LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Button.SetFloaterToggle", boost::bind(&LLButton::setFloaterToggle, _1, _2));
+
+ // Button initialization callback for toggle buttons on dockale floaters
+ LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Button.SetDockableFloaterToggle", boost::bind(&LLButton::setDockableFloaterToggle, _1, _2));
+
+ // Display the help topic for the current context
+ LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Button.ShowHelp", boost::bind(&LLButton::showHelp, _1, _2));
- LLUI::sShowXUINames = LLUI::sConfigGroup->getBOOL("ShowXUINames");
- LLUI::sConfigGroup->getControl("ShowXUINames")->getSignal()->connect(&handleShowXUINamesChanged);
+ // Currently unused, but kept for reference:
+ LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Button.ToggleFloater", boost::bind(&LLButton::toggleFloaterAndSetToggleState, _1, _2));
+
+ // Used by menus along with Floater.Toggle to display visibility as a checkmark
+ LLUICtrl::EnableCallbackRegistry::defaultRegistrar().add("Floater.Visible", boost::bind(&LLFloaterReg::floaterInstanceVisible, _2));
}
void LLUI::cleanupClass()
{
sImageProvider->cleanUp();
- LLLineEditor::cleanupLineEditor();
}
+//static
+void LLUI::dirtyRect(LLRect rect)
+{
+ if (!sDirty)
+ {
+ sDirtyRect = rect;
+ sDirty = TRUE;
+ }
+ else
+ {
+ sDirtyRect.unionWith(rect);
+ }
+}
+
//static
void LLUI::translate(F32 x, F32 y, F32 z)
@@ -1637,7 +1635,7 @@ void LLUI::setLineWidth(F32 width)
}
//static
-void LLUI::setCursorPositionScreen(S32 x, S32 y)
+void LLUI::setMousePositionScreen(S32 x, S32 y)
{
S32 screen_x, screen_y;
screen_x = llround((F32)x * sGLScaleFactor.mV[VX]);
@@ -1650,26 +1648,34 @@ void LLUI::setCursorPositionScreen(S32 x, S32 y)
}
//static
-void LLUI::setCursorPositionLocal(const LLView* viewp, S32 x, S32 y)
+void LLUI::getMousePositionScreen(S32 *x, S32 *y)
+{
+ LLCoordWindow cursor_pos_window;
+ getWindow()->getCursorPosition(&cursor_pos_window);
+ LLCoordGL cursor_pos_gl;
+ getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl);
+ *x = llround((F32)cursor_pos_gl.mX / sGLScaleFactor.mV[VX]);
+ *y = llround((F32)cursor_pos_gl.mY / sGLScaleFactor.mV[VX]);
+}
+
+//static
+void LLUI::setMousePositionLocal(const LLView* viewp, S32 x, S32 y)
{
S32 screen_x, screen_y;
viewp->localPointToScreen(x, y, &screen_x, &screen_y);
- setCursorPositionScreen(screen_x, screen_y);
+ setMousePositionScreen(screen_x, screen_y);
}
//static
-void LLUI::getCursorPositionLocal(const LLView* viewp, S32 *x, S32 *y)
+void LLUI::getMousePositionLocal(const LLView* viewp, S32 *x, S32 *y)
{
- LLCoordWindow cursor_pos_window;
- LLView::getWindow()->getCursorPosition(&cursor_pos_window);
- LLCoordGL cursor_pos_gl;
- LLView::getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl);
- cursor_pos_gl.mX = llround((F32)cursor_pos_gl.mX / LLUI::sGLScaleFactor.mV[VX]);
- cursor_pos_gl.mY = llround((F32)cursor_pos_gl.mY / LLUI::sGLScaleFactor.mV[VY]);
- viewp->screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, x, y);
+ S32 screen_x, screen_y;
+ getMousePositionScreen(&screen_x, &screen_y);
+ viewp->screenPointToLocal(screen_x, screen_y, x, y);
}
+
// On Windows, the user typically sets the language when they install the
// app (by running it with a shortcut that sets InstallLanguage). On Mac,
// or on Windows if the SecondLife.exe executable is run directly, the
@@ -1678,27 +1684,61 @@ void LLUI::getCursorPositionLocal(const LLView* viewp, S32 *x, S32 *y)
// static
std::string LLUI::getLanguage()
{
- std::string language = "en-us";
- if (sConfigGroup)
+ std::string language = "en";
+ if (sSettingGroups["config"])
{
- language = sConfigGroup->getString("Language");
+ language = sSettingGroups["config"]->getString("Language");
if (language.empty() || language == "default")
{
- language = sConfigGroup->getString("InstallLanguage");
+ language = sSettingGroups["config"]->getString("InstallLanguage");
}
if (language.empty() || language == "default")
{
- language = sConfigGroup->getString("SystemLanguage");
+ language = sSettingGroups["config"]->getString("SystemLanguage");
}
if (language.empty() || language == "default")
{
- language = "en-us";
+ language = "en";
}
}
return language;
}
//static
+void LLUI::setupPaths()
+{
+ std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, "paths.xml");
+
+ LLXMLNodePtr root;
+ BOOL success = LLXMLNode::parseFile(filename, root, NULL);
+ sXUIPaths.clear();
+
+ if (success)
+ {
+ LLStringUtil::format_map_t path_args;
+ path_args["[LANGUAGE]"] = LLUI::getLanguage();
+
+ for (LLXMLNodePtr path = root->getFirstChild(); path.notNull(); path = path->getNextSibling())
+ {
+ std::string path_val_ui(path->getValue());
+ LLStringUtil::format(path_val_ui, path_args);
+ if (std::find(sXUIPaths.begin(), sXUIPaths.end(), path_val_ui) == sXUIPaths.end())
+ {
+ sXUIPaths.push_back(path_val_ui);
+ }
+ }
+ }
+ else // parsing failed
+ {
+ std::string slash = gDirUtilp->getDirDelimiter();
+ std::string dir = "xui" + slash + "en";
+ llwarns << "XUI::config file unable to open: " << filename << llendl;
+ sXUIPaths.push_back(dir);
+ }
+}
+
+
+//static
std::string LLUI::locateSkin(const std::string& filename)
{
std::string slash = gDirUtilp->getDirDelimiter();
@@ -1707,7 +1747,7 @@ std::string LLUI::locateSkin(const std::string& filename)
{
found_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename); // Should be CUSTOM_SKINS?
}
- if (sConfigGroup && sConfigGroup->controlExists("Language"))
+ if (sSettingGroups["config"] && sSettingGroups["config"]->controlExists("Language"))
{
if (!gDirUtilp->fileExists(found_file))
{
@@ -1718,7 +1758,7 @@ std::string LLUI::locateSkin(const std::string& filename)
}
if (!gDirUtilp->fileExists(found_file))
{
- std::string local_skin = "xui" + slash + "en-us" + slash + filename;
+ std::string local_skin = "xui" + slash + "en" + slash + filename;
found_file = gDirUtilp->findSkinnedFilename(local_skin);
}
if (!gDirUtilp->fileExists(found_file))
@@ -1765,186 +1805,299 @@ void LLUI::glRectToScreen(const LLRect& gl, LLRect *screen)
glPointToScreen(gl.mRight, gl.mBottom, &screen->mRight, &screen->mBottom);
}
-//static
-LLUIImage* LLUI::getUIImage(const std::string& name)
+//static
+LLPointer<LLUIImage> LLUI::getUIImageByID(const LLUUID& image_id, S32 priority)
{
- if (!name.empty())
- return sImageProvider->getUIImage(name);
+ if (sImageProvider)
+ {
+ return sImageProvider->getUIImageByID(image_id, priority);
+ }
else
+ {
return NULL;
-}
-
-// static
-void LLUI::setHtmlHelp(LLHtmlHelp* html_help)
-{
- LLUI::sHtmlHelp = html_help;
+ }
}
//static
-void LLUI::setQAMode(BOOL b)
+LLPointer<LLUIImage> LLUI::getUIImage(const std::string& name, S32 priority)
{
- LLUI::sQAMode = b;
+ if (!name.empty() && sImageProvider)
+ return sImageProvider->getUIImage(name, priority);
+ else
+ return NULL;
}
-LLScreenClipRect::LLScreenClipRect(const LLRect& rect, BOOL enabled) : mScissorState(GL_SCISSOR_TEST), mEnabled(enabled)
+LLControlGroup& LLUI::getControlControlGroup (const std::string& controlname)
{
- if (mEnabled)
+ for (settings_map_t::iterator itor = sSettingGroups.begin();
+ itor != sSettingGroups.end(); ++itor)
{
- pushClipRect(rect);
+ LLControlGroup* control_group = itor->second;
+ if(control_group != NULL)
+ {
+ if (control_group->controlExists(controlname))
+ return *control_group;
+ }
}
- mScissorState.setEnabled(!sClipRectStack.empty());
- updateScissorRegion();
-}
-LLScreenClipRect::~LLScreenClipRect()
-{
- if (mEnabled)
- {
- popClipRect();
- }
- updateScissorRegion();
+ return *sSettingGroups["config"]; // default group
}
-//static
-void LLScreenClipRect::pushClipRect(const LLRect& rect)
+//static
+// spawn_x and spawn_y are top left corner of view in screen GL coordinates
+void LLUI::positionViewNearMouse(LLView* view, S32 spawn_x, S32 spawn_y)
{
- LLRect combined_clip_rect = rect;
- if (!sClipRectStack.empty())
+ const S32 CURSOR_HEIGHT = 16; // Approximate "normal" cursor size
+ const S32 CURSOR_WIDTH = 8;
+
+ LLView* parent = view->getParent();
+
+ S32 mouse_x;
+ S32 mouse_y;
+ LLUI::getMousePositionScreen(&mouse_x, &mouse_y);
+
+ // If no spawn location provided, use mouse position
+ if (spawn_x == S32_MAX || spawn_y == S32_MAX)
{
- LLRect top = sClipRectStack.top();
- combined_clip_rect.intersectWith(top);
+ spawn_x = mouse_x + CURSOR_WIDTH;
+ spawn_y = mouse_y - CURSOR_HEIGHT;
}
- sClipRectStack.push(combined_clip_rect);
-}
-//static
-void LLScreenClipRect::popClipRect()
-{
- sClipRectStack.pop();
-}
+ LLRect virtual_window_rect = parent->getLocalRect();
-//static
-void LLScreenClipRect::updateScissorRegion()
-{
- if (sClipRectStack.empty()) return;
+ LLRect mouse_rect;
+ const S32 MOUSE_CURSOR_PADDING = 1;
+ mouse_rect.setLeftTopAndSize(mouse_x - MOUSE_CURSOR_PADDING,
+ mouse_y + MOUSE_CURSOR_PADDING,
+ CURSOR_WIDTH + MOUSE_CURSOR_PADDING * 2,
+ CURSOR_HEIGHT + MOUSE_CURSOR_PADDING * 2);
- LLRect rect = sClipRectStack.top();
- stop_glerror();
- S32 x,y,w,h;
- x = llfloor(rect.mLeft * LLUI::sGLScaleFactor.mV[VX]);
- y = llfloor(rect.mBottom * LLUI::sGLScaleFactor.mV[VY]);
- w = llmax(0, llceil(rect.getWidth() * LLUI::sGLScaleFactor.mV[VX])) + 1;
- h = llmax(0, llceil(rect.getHeight() * LLUI::sGLScaleFactor.mV[VY])) + 1;
- glScissor( x,y,w,h );
- stop_glerror();
+ S32 local_x, local_y;
+ // convert screen coordinates to tooltipview-local coordinates
+ parent->screenPointToLocal(spawn_x, spawn_y, &local_x, &local_y);
+
+ // Start at spawn position (using left/top)
+ view->setOrigin( local_x, local_y - view->getRect().getHeight());
+ // Make sure we're onscreen and not overlapping the mouse
+ view->translateIntoRectWithExclusion( virtual_window_rect, mouse_rect, FALSE );
}
-LLLocalClipRect::LLLocalClipRect(const LLRect &rect, BOOL enabled)
-: LLScreenClipRect(LLRect(rect.mLeft + LLFontGL::sCurOrigin.mX,
- rect.mTop + LLFontGL::sCurOrigin.mY,
- rect.mRight + LLFontGL::sCurOrigin.mX,
- rect.mBottom + LLFontGL::sCurOrigin.mY),
- enabled)
+// LLLocalClipRect and LLScreenClipRect moved to lllocalcliprect.h/cpp
+
+namespace LLInitParam
{
-}
+ TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
+ : super_t(descriptor, name, value, func, min_count, max_count),
+ red("red"),
+ green("green"),
+ blue("blue"),
+ alpha("alpha"),
+ control("")
+ {}
+ void TypedParam<LLUIColor>::setValueFromBlock() const
+ {
+ if (control.isProvided())
+ {
+ mData.mValue = LLUIColorTable::instance().getColor(control);
+ }
+ else
+ {
+ mData.mValue = LLColor4(red, green, blue, alpha);
+ }
+ }
+
+ void TypedParam<LLUIColor>::setBlockFromValue()
+ {
+ LLColor4 color = mData.mValue.get();
+ red = color.mV[VRED];
+ green = color.mV[VGREEN];
+ blue = color.mV[VBLUE];
+ alpha = color.mV[VALPHA];
+ control.set("", false);
+ }
-//
-// LLUIImage
-//
+ void TypeValues<LLUIColor>::declareValues()
+ {
+ declare("white", LLColor4::white);
+ declare("black", LLColor4::black);
+ declare("red", LLColor4::red);
+ declare("green", LLColor4::green);
+ declare("blue", LLColor4::blue);
+ }
-LLUIImage::LLUIImage(const std::string& name, LLPointer<LLImageGL> image) :
- mName(name),
- mImage(image),
- mScaleRegion(0.f, 1.f, 1.f, 0.f),
- mClipRegion(0.f, 1.f, 1.f, 0.f),
- mUniformScaling(TRUE),
- mNoClip(TRUE)
-{
-}
+ bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b)
+ {
+ return !(a->getFontDesc() < b->getFontDesc())
+ && !(b->getFontDesc() < a->getFontDesc());
+ }
-void LLUIImage::setClipRegion(const LLRectf& region)
-{
- mClipRegion = region;
- mNoClip = mClipRegion.mLeft == 0.f
- && mClipRegion.mRight == 1.f
- && mClipRegion.mBottom == 0.f
- && mClipRegion.mTop == 1.f;
-}
+ TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
+ : super_t(descriptor, _name, value, func, min_count, max_count),
+ name("name"),
+ size("size"),
+ style("style")
+ {
+ addSynonym(name, "");
+ }
-void LLUIImage::setScaleRegion(const LLRectf& region)
-{
- mScaleRegion = region;
- mUniformScaling = mScaleRegion.mLeft == 0.f
- && mScaleRegion.mRight == 1.f
- && mScaleRegion.mBottom == 0.f
- && mScaleRegion.mTop == 1.f;
-}
+ void TypedParam<const LLFontGL*>::setValueFromBlock() const
+ {
+ const LLFontGL* res_fontp = LLFontGL::getFontByName(name);
+ if (res_fontp)
+ {
+ mData.mValue = res_fontp;
+ return;
+ }
-//TODO: move drawing implementation inside class
-void LLUIImage::draw(S32 x, S32 y, const LLColor4& color) const
-{
- gl_draw_image(x, y, mImage, color, mClipRegion);
-}
+ U8 fontstyle = 0;
+ fontstyle = LLFontGL::getStyleFromString(style());
+ LLFontDescriptor desc(name(), size(), fontstyle);
+ const LLFontGL* fontp = LLFontGL::getFont(desc);
+ if (fontp)
+ {
+ mData.mValue = fontp;
+ }
+ }
+
+ void TypedParam<const LLFontGL*>::setBlockFromValue()
+ {
+ if (mData.mValue)
+ {
+ name = LLFontGL::nameFromFont(mData.mValue);
+ size = LLFontGL::sizeFromFont(mData.mValue);
+ style = LLFontGL::getStringFromStyle(mData.mValue->getFontDesc().getStyle());
+ }
+ }
-void LLUIImage::draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const
-{
- if (mUniformScaling)
+ TypedParam<LLRect>::TypedParam(BlockDescriptor& descriptor, const char* name, const LLRect& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
+ : super_t(descriptor, name, value, func, min_count, max_count),
+ left("left"),
+ top("top"),
+ right("right"),
+ bottom("bottom"),
+ width("width"),
+ height("height")
+ {}
+
+ void TypedParam<LLRect>::setValueFromBlock() const
+ {
+ LLRect rect;
+
+ //calculate from params
+ // prefer explicit left and right
+ if (left.isProvided() && right.isProvided())
+ {
+ rect.mLeft = left;
+ rect.mRight = right;
+ }
+ // otherwise use width along with specified side, if any
+ else if (width.isProvided())
+ {
+ // only right + width provided
+ if (right.isProvided())
+ {
+ rect.mRight = right;
+ rect.mLeft = right - width;
+ }
+ else // left + width, or just width
+ {
+ rect.mLeft = left;
+ rect.mRight = left + width;
+ }
+ }
+ // just left, just right, or none
+ else
+ {
+ rect.mLeft = left;
+ rect.mRight = right;
+ }
+
+ // prefer explicit bottom and top
+ if (bottom.isProvided() && top.isProvided())
+ {
+ rect.mBottom = bottom;
+ rect.mTop = top;
+ }
+ // otherwise height along with specified side, if any
+ else if (height.isProvided())
+ {
+ // top + height provided
+ if (top.isProvided())
+ {
+ rect.mTop = top;
+ rect.mBottom = top - height;
+ }
+ // bottom + height or just height
+ else
+ {
+ rect.mBottom = bottom;
+ rect.mTop = bottom + height;
+ }
+ }
+ // just bottom, just top, or none
+ else
+ {
+ rect.mBottom = bottom;
+ rect.mTop = top;
+ }
+ mData.mValue = rect;
+ }
+
+ void TypedParam<LLRect>::setBlockFromValue()
{
- gl_draw_scaled_image(x, y, width, height, mImage, color, mClipRegion);
+ // because of the ambiguity in specifying a rect by position and/or dimensions
+ // we clear the "provided" flag so that values from xui/etc have priority
+ // over those calculated from the rect object
+
+ left.set(mData.mValue.mLeft, false);
+ right.set(mData.mValue.mRight, false);
+ bottom.set(mData.mValue.mBottom, false);
+ top.set(mData.mValue.mTop, false);
+ width.set(mData.mValue.getWidth(), false);
+ height.set(mData.mValue.getHeight(), false);
}
- else
+
+ TypedParam<LLCoordGL>::TypedParam(BlockDescriptor& descriptor, const char* name, LLCoordGL value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
+ : super_t(descriptor, name, value, func, min_count, max_count),
+ x("x"),
+ y("y")
{
- gl_draw_scaled_image_with_border(
- x, y,
- width, height,
- mImage,
- color,
- FALSE,
- mClipRegion,
- mScaleRegion);
}
-}
-void LLUIImage::drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const
-{
- gl_draw_scaled_image_with_border(
- x, y,
- width, height,
- mImage,
- color,
- TRUE,
- mClipRegion,
- mScaleRegion);
-}
+ void TypedParam<LLCoordGL>::setValueFromBlock() const
+ {
+ mData.mValue.set(x, y);
+ }
+
+ void TypedParam<LLCoordGL>::setBlockFromValue()
+ {
+ x = mData.mValue.mX;
+ y = mData.mValue.mY;
+ }
-void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const
-{
- LLRect border_rect;
- border_rect.setOriginAndSize(x, y, width, height);
- border_rect.stretch(border_width, border_width);
- drawSolid(border_rect, color);
-}
-S32 LLUIImage::getWidth() const
-{
- // return clipped dimensions of actual image area
- return llround((F32)mImage->getWidth(0) * mClipRegion.getWidth());
-}
+ void TypeValues<LLFontGL::HAlign>::declareValues()
+ {
+ declare("left", LLFontGL::LEFT);
+ declare("right", LLFontGL::RIGHT);
+ declare("center", LLFontGL::HCENTER);
+ }
-S32 LLUIImage::getHeight() const
-{
- // return clipped dimensions of actual image area
- return llround((F32)mImage->getHeight(0) * mClipRegion.getHeight());
-}
+ void TypeValues<LLFontGL::VAlign>::declareValues()
+ {
+ declare("top", LLFontGL::TOP);
+ declare("center", LLFontGL::VCENTER);
+ declare("baseline", LLFontGL::BASELINE);
+ declare("bottom", LLFontGL::BOTTOM);
+ }
-S32 LLUIImage::getTextureWidth() const
-{
- return mImage->getWidth(0);
+ void TypeValues<LLFontGL::ShadowType>::declareValues()
+ {
+ declare("none", LLFontGL::NO_SHADOW);
+ declare("hard", LLFontGL::DROP_SHADOW);
+ declare("soft", LLFontGL::DROP_SHADOW_SOFT);
+ }
}
-S32 LLUIImage::getTextureHeight() const
-{
- return mImage->getHeight(0);
-}
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index ebcc7304b1..5840e76f5c 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -35,28 +35,35 @@
#ifndef LL_LLUI_H
#define LL_LLUI_H
+#include "llpointer.h" // LLPointer<>
#include "llrect.h"
#include "llcontrol.h"
-#include "llrect.h"
#include "llcoord.h"
-//#include "llhtmlhelp.h"
-#include "llgl.h" // *TODO: break this dependency
-#include <stack>
-//#include "llimagegl.h"
-#include <boost/signal.hpp>
+#include "lluiimage.h" // *TODO: break this dependency, need to add #include "lluiimage.h" to all widgets that hold an Optional<LLUIImage*> in their paramblocks
+#include "llinitparam.h"
+#include "llregistry.h"
+#include "lluicolor.h"
+#include "lluicolortable.h"
+#include <boost/signals2.hpp>
+#include "lllazyvalue.h"
+#include "llhandle.h" // *TODO: remove this dependency, added as a
+ // convenience when LLHandle moved to llhandle.h
+#include "llframetimer.h"
// LLUIFactory
#include "llsd.h"
+// for initparam specialization
+#include "llfontgl.h"
+
class LLColor4;
-class LLHtmlHelp;
-class LLImageGL;
class LLVector3;
class LLVector2;
+class LLUIImage;
class LLUUID;
class LLWindow;
class LLView;
-class LLUIImage;
+class LLHelp;
// UI colors
extern const LLColor4 UI_VERTEX_COLOR;
@@ -91,14 +98,12 @@ void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4&
void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color);
void gl_washer_spokes_2d(F32 outer_radius, F32 inner_radius, S32 count, const LLColor4& inner_color, const LLColor4& outer_color);
-void gl_draw_image(S32 x, S32 y, LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
-void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
-void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
-void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees,LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
-void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLImageGL* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
-void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
-// Flip vertical, used for LLFloaterHTML
-void gl_draw_scaled_image_inverted(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
+void gl_draw_image(S32 x, S32 y, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
+void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
+void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
+void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees,LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
+void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
+void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_rect_2d_xor(S32 left, S32 top, S32 right, S32 bottom);
void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f );
@@ -143,9 +148,6 @@ inline void gl_rect_2d_offset_local( const LLRect& rect, S32 pixel_offset, BOOL
gl_rect_2d_offset_local( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, pixel_offset, filled );
}
-// Used to hide the flashing text cursor when window doesn't have focus.
-extern BOOL gShowTextEditCursor;
-
class LLImageProviderInterface;
typedef void (*LLUIAudioCallback)(const LLUUID& uuid);
@@ -157,9 +159,8 @@ public:
//
// Methods
//
- static void initClass(LLControlGroup* config,
- LLControlGroup* ignores,
- LLControlGroup* colors,
+ typedef std::map<std::string, LLControlGroup*> settings_map_t;
+ static void initClass(const settings_map_t& settings,
LLImageProviderInterface* image_provider,
LLUIAudioCallback audio_callback = NULL,
const LLVector2 *scale_factor = NULL,
@@ -171,497 +172,84 @@ public:
static void loadIdentity();
static void translate(F32 x, F32 y, F32 z = 0.0f);
+ static LLRect sDirtyRect;
+ static BOOL sDirty;
+ static void dirtyRect(LLRect rect);
+
// Return the ISO639 language name ("en", "ko", etc.) for the viewer UI.
// http://www.loc.gov/standards/iso639-2/php/code_list.php
static std::string getLanguage();
+
+ static void setupPaths();
+ static const std::vector<std::string>& getXUIPaths() { return sXUIPaths; }
+ static std::string getSkinPath() { return sXUIPaths.front(); }
+ static std::string getLocalizedSkinPath() { return sXUIPaths.back(); } //all files may not exist at the localized path
//helper functions (should probably move free standing rendering helper functions here)
+ static LLView* getRootView() { return sRootView; }
+ static void setRootView(LLView* view) { sRootView = view; }
static std::string locateSkin(const std::string& filename);
- static void setCursorPositionScreen(S32 x, S32 y);
- static void setCursorPositionLocal(const LLView* viewp, S32 x, S32 y);
- static void getCursorPositionLocal(const LLView* viewp, S32 *x, S32 *y);
+ static void setMousePositionScreen(S32 x, S32 y);
+ static void getMousePositionScreen(S32 *x, S32 *y);
+ static void setMousePositionLocal(const LLView* viewp, S32 x, S32 y);
+ static void getMousePositionLocal(const LLView* viewp, S32 *x, S32 *y);
static void setScaleFactor(const LLVector2& scale_factor);
static void setLineWidth(F32 width);
- static LLUIImage* getUIImage(const std::string& name);
+ static LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0);
+ static LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0);
static LLVector2 getWindowSize();
static void screenPointToGL(S32 screen_x, S32 screen_y, S32 *gl_x, S32 *gl_y);
static void glPointToScreen(S32 gl_x, S32 gl_y, S32 *screen_x, S32 *screen_y);
static void screenRectToGL(const LLRect& screen, LLRect *gl);
static void glRectToScreen(const LLRect& gl, LLRect *screen);
- static void setHtmlHelp(LLHtmlHelp* html_help);
+ // Returns the control group containing the control name, or the default group
+ static LLControlGroup& getControlControlGroup (const std::string& controlname);
+ static F32 getMouseIdleTime() { return sMouseIdleTimer.getElapsedTimeF32(); }
+ static void resetMouseIdleTimer() { sMouseIdleTimer.reset(); }
+ static LLWindow* getWindow() { return sWindow; }
+
+ // Ensures view does not overlap mouse cursor, but is inside
+ // the view's parent rectangle. Used for tooltips, inspectors.
+ // Optionally override the view's default X/Y, which are relative to the
+ // view's parent.
+ static void positionViewNearMouse(LLView* view, S32 spawn_x = S32_MAX, S32 spawn_y = S32_MAX);
//
// Data
//
- static LLControlGroup* sConfigGroup;
- static LLControlGroup* sIgnoresGroup;
- static LLControlGroup* sColorsGroup;
- static LLImageProviderInterface* sImageProvider;
+ static settings_map_t sSettingGroups;
static LLUIAudioCallback sAudioCallback;
static LLVector2 sGLScaleFactor;
static LLWindow* sWindow;
- static BOOL sShowXUINames;
- static LLHtmlHelp* sHtmlHelp;
-
- // *TODO: remove the following when QAR-369 settings clean-up work is in.
- // Also remove the call to this method which will then be obsolete.
- // Search for QAR-369 below to enable the proper accessing of this feature. -MG
- static void setQAMode(BOOL b);
- static BOOL sQAMode;
-
-};
-
-// FactoryPolicy is a static class that controls the creation and lookup of UI elements,
-// such as floaters.
-// The key parameter is used to provide a unique identifier and/or associated construction
-// parameters for a given UI instance
-//
-// Specialize this traits for different types, or provide a class with an identical interface
-// in the place of the traits parameter
-//
-// For example:
-//
-// template <>
-// class FactoryPolicy<MyClass> /* FactoryPolicy specialized for MyClass */
-// {
-// public:
-// static MyClass* findInstance(const LLSD& key = LLSD())
-// {
-// /* return instance of MyClass associated with key */
-// }
-//
-// static MyClass* createInstance(const LLSD& key = LLSD())
-// {
-// /* create new instance of MyClass using key for construction parameters */
-// }
-// }
-//
-// class MyClass : public LLUIFactory<MyClass>
-// {
-// /* uses FactoryPolicy<MyClass> by default */
-// }
-
-template <class T>
-class FactoryPolicy
-{
-public:
- // basic factory methods
- static T* findInstance(const LLSD& key); // unimplemented, provide specialiation
- static T* createInstance(const LLSD& key); // unimplemented, provide specialiation
-};
-
-// VisibilityPolicy controls the visibility of UI elements, such as floaters.
-// The key parameter is used to store the unique identifier of a given UI instance
-//
-// Specialize this traits for different types, or duplicate this interface for specific instances
-// (see above)
-
-template <class T>
-class VisibilityPolicy
-{
-public:
- // visibility methods
- static bool visible(T* instance, const LLSD& key); // unimplemented, provide specialiation
- static void show(T* instance, const LLSD& key); // unimplemented, provide specialiation
- static void hide(T* instance, const LLSD& key); // unimplemented, provide specialiation
-};
-
-// Manages generation of UI elements by LLSD, such that (generally) there is
-// a unique instance per distinct LLSD parameter
-// Class T is the instance type being managed, and the FACTORY_POLICY and VISIBILITY_POLICY
-// classes provide static methods for creating, accessing, showing and hiding the associated
-// element T
-template <class T, class FACTORY_POLICY = FactoryPolicy<T>, class VISIBILITY_POLICY = VisibilityPolicy<T> >
-class LLUIFactory
-{
-public:
- // give names to the template parameters so derived classes can refer to them
- // except this doesn't work in gcc
- typedef FACTORY_POLICY factory_policy_t;
- typedef VISIBILITY_POLICY visibility_policy_t;
-
- LLUIFactory()
- {
- }
-
- virtual ~LLUIFactory()
- {
- }
-
- // default show and hide methods
- static T* showInstance(const LLSD& key = LLSD())
- {
- T* instance = getInstance(key);
- if (instance != NULL)
- {
- VISIBILITY_POLICY::show(instance, key);
- }
- return instance;
- }
-
- static void hideInstance(const LLSD& key = LLSD())
- {
- T* instance = getInstance(key);
- if (instance != NULL)
- {
- VISIBILITY_POLICY::hide(instance, key);
- }
- }
-
- static void toggleInstance(const LLSD& key = LLSD())
- {
- if (instanceVisible(key))
- {
- hideInstance(key);
- }
- else
- {
- showInstance(key);
- }
- }
-
- static bool instanceVisible(const LLSD& key = LLSD())
- {
- T* instance = FACTORY_POLICY::findInstance(key);
- return instance != NULL && VISIBILITY_POLICY::visible(instance, key);
- }
-
- static T* getInstance(const LLSD& key = LLSD())
- {
- T* instance = FACTORY_POLICY::findInstance(key);
- if (instance == NULL)
- {
- instance = FACTORY_POLICY::createInstance(key);
- }
- return instance;
- }
-
-};
-
-
-// Creates a UI singleton by ignoring the identifying parameter
-// and always generating the same instance via the LLUIFactory interface.
-// Note that since UI elements can be destroyed by their hierarchy, this singleton
-// pattern uses a static pointer to an instance that will be re-created as needed.
-//
-// Usage Pattern:
-//
-// class LLFloaterFoo : public LLFloater, public LLUISingleton<LLFloaterFoo>
-// {
-// friend class LLUISingleton<LLFloaterFoo>;
-// private:
-// LLFloaterFoo(const LLSD& key);
-// };
-//
-// Note that LLUISingleton takes an option VisibilityPolicy parameter that defines
-// how showInstance(), hideInstance(), etc. work.
-//
-// https://wiki.lindenlab.com/mediawiki/index.php?title=LLUISingleton&oldid=79352
-
-template <class T, class VISIBILITY_POLICY = VisibilityPolicy<T> >
-class LLUISingleton: public LLUIFactory<T, LLUISingleton<T, VISIBILITY_POLICY>, VISIBILITY_POLICY>
-{
-protected:
-
- // T must derive from LLUISingleton<T>
- LLUISingleton() { sInstance = static_cast<T*>(this); }
-
- ~LLUISingleton() { sInstance = NULL; }
-
-public:
- static T* findInstance(const LLSD& key = LLSD())
- {
- return sInstance;
- }
-
- static T* createInstance(const LLSD& key = LLSD())
- {
- if (sInstance == NULL)
- {
- sInstance = new T(key);
- }
- return sInstance;
- }
-
-private:
- static T* sInstance;
-};
-
-template <class T, class U> T* LLUISingleton<T,U>::sInstance = NULL;
-
-class LLScreenClipRect
-{
-public:
- LLScreenClipRect(const LLRect& rect, BOOL enabled = TRUE);
- virtual ~LLScreenClipRect();
-
-private:
- static void pushClipRect(const LLRect& rect);
- static void popClipRect();
- static void updateScissorRegion();
-
-private:
- LLGLState mScissorState;
- BOOL mEnabled;
-
- static std::stack<LLRect> sClipRectStack;
-};
-
-class LLLocalClipRect : public LLScreenClipRect
-{
-public:
- LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE);
-};
-
-class LLUIImage : public LLRefCount
-{
-public:
- LLUIImage(const std::string& name, LLPointer<LLImageGL> image);
-
- void setClipRegion(const LLRectf& region);
- void setScaleRegion(const LLRectf& region);
-
- LLPointer<LLImageGL> getImage() { return mImage; }
- const LLPointer<LLImageGL>& getImage() const { return mImage; }
-
- void draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color = UI_VERTEX_COLOR) const;
- void draw(S32 x, S32 y, const LLColor4& color = UI_VERTEX_COLOR) const;
- void draw(const LLRect& rect, const LLColor4& color = UI_VERTEX_COLOR) const { draw(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); }
-
- void drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const;
- void drawSolid(const LLRect& rect, const LLColor4& color) const { drawSolid(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); }
- void drawSolid(S32 x, S32 y, const LLColor4& color) const { drawSolid(x, y, mImage->getWidth(0), mImage->getHeight(0), color); }
-
- void drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const;
- void drawBorder(const LLRect& rect, const LLColor4& color, S32 border_width) const { drawBorder(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color, border_width); }
- void drawBorder(S32 x, S32 y, const LLColor4& color, S32 border_width) const { drawBorder(x, y, mImage->getWidth(0), mImage->getHeight(0), color, border_width); }
-
- const std::string& getName() const { return mName; }
-
- S32 getWidth() const;
- S32 getHeight() const;
-
- // returns dimensions of underlying textures, which might not be equal to ui image portion
- S32 getTextureWidth() const;
- S32 getTextureHeight() const;
-
-protected:
- std::string mName;
- LLRectf mScaleRegion;
- LLRectf mClipRegion;
- LLPointer<LLImageGL> mImage;
- BOOL mUniformScaling;
- BOOL mNoClip;
-};
-
-typedef LLPointer<LLUIImage> LLUIImagePtr;
-
-template <typename T>
-class LLTombStone : public LLRefCount
-{
-public:
- LLTombStone(T* target = NULL) : mTarget(target) {}
-
- void setTarget(T* target) { mTarget = target; }
- T* getTarget() const { return mTarget; }
-private:
- T* mTarget;
-};
-
-// LLHandles are used to refer to objects whose lifetime you do not control or influence.
-// Calling get() on a handle will return a pointer to the referenced object or NULL,
-// if the object no longer exists. Note that during the lifetime of the returned pointer,
-// you are assuming that the object will not be deleted by any action you perform,
-// or any other thread, as normal when using pointers, so avoid using that pointer outside of
-// the local code block.
-//
-// https://wiki.lindenlab.com/mediawiki/index.php?title=LLHandle&oldid=79669
-
-template <typename T>
-class LLHandle
-{
-public:
- LLHandle() : mTombStone(sDefaultTombStone) {}
- const LLHandle<T>& operator =(const LLHandle<T>& other)
- {
- mTombStone = other.mTombStone;
- return *this;
- }
-
- bool isDead() const
- {
- return mTombStone->getTarget() == NULL;
- }
-
- void markDead()
- {
- mTombStone = sDefaultTombStone;
- }
-
- T* get() const
- {
- return mTombStone->getTarget();
- }
-
- friend bool operator== (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
- {
- return lhs.mTombStone == rhs.mTombStone;
- }
- friend bool operator!= (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
- {
- return !(lhs == rhs);
- }
- friend bool operator< (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
- {
- return lhs.mTombStone < rhs.mTombStone;
- }
- friend bool operator> (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
- {
- return lhs.mTombStone > rhs.mTombStone;
- }
-protected:
-
-protected:
- LLPointer<LLTombStone<T> > mTombStone;
-
+ static LLView* sRootView;
+ static LLHelp* sHelpImpl;
private:
- static LLPointer<LLTombStone<T> > sDefaultTombStone;
-};
-
-// initialize static "empty" tombstone pointer
-template <typename T> LLPointer<LLTombStone<T> > LLHandle<T>::sDefaultTombStone = new LLTombStone<T>();
-
-
-template <typename T>
-class LLRootHandle : public LLHandle<T>
-{
-public:
- LLRootHandle(T* object) { bind(object); }
- LLRootHandle() {};
- ~LLRootHandle() { unbind(); }
-
- // this is redundant, since a LLRootHandle *is* an LLHandle
- LLHandle<T> getHandle() { return LLHandle<T>(*this); }
-
- void bind(T* object)
- {
- // unbind existing tombstone
- if (LLHandle<T>::mTombStone.notNull())
- {
- if (LLHandle<T>::mTombStone->getTarget() == object) return;
- LLHandle<T>::mTombStone->setTarget(NULL);
- }
- // tombstone reference counted, so no paired delete
- LLHandle<T>::mTombStone = new LLTombStone<T>(object);
- }
-
- void unbind()
- {
- LLHandle<T>::mTombStone->setTarget(NULL);
- }
-
- //don't allow copying of root handles, since there should only be one
-private:
- LLRootHandle(const LLRootHandle& other) {};
+ static LLImageProviderInterface* sImageProvider;
+ static std::vector<std::string> sXUIPaths;
+ static LLFrameTimer sMouseIdleTimer;
};
-// Use this as a mixin for simple classes that need handles and when you don't
-// want handles at multiple points of the inheritance hierarchy
-template <typename T>
-class LLHandleProvider
-{
-protected:
- typedef LLHandle<T> handle_type_t;
- LLHandleProvider()
- {
- // provided here to enforce T deriving from LLHandleProvider<T>
- }
-
- LLHandle<T> getHandle()
- {
- // perform lazy binding to avoid small tombstone allocations for handle
- // providers whose handles are never referenced
- mHandle.bind(static_cast<T*>(this));
- return mHandle;
- }
-private:
- LLRootHandle<T> mHandle;
-};
+// Moved LLLocalClipRect to lllocalcliprect.h
+// Moved all LLHandle-related code to llhandle.h
//RN: maybe this needs to moved elsewhere?
class LLImageProviderInterface
{
-public:
+protected:
LLImageProviderInterface() {};
virtual ~LLImageProviderInterface() {};
-
- virtual LLUIImagePtr getUIImage(const std::string& name) = 0;
- virtual LLUIImagePtr getUIImageByID(const LLUUID& id) = 0;
- virtual void cleanUp() = 0;
-};
-
-// This mix-in class adds support for tracking all instances of the specificed class parameter T
-// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup
-// If KEY is not provided, then instances are stored in a simple list
-template<typename T, typename KEY = T*>
-class LLInstanceTracker : boost::noncopyable
-{
public:
- typedef typename std::map<KEY, T*>::iterator instance_iter;
- typedef typename std::map<KEY, T*>::const_iterator instance_const_iter;
-
- static T* getInstance(KEY k) { instance_iter found = sInstances.find(k); return (found == sInstances.end()) ? NULL : found->second; }
-
- static instance_iter beginInstances() { return sInstances.begin(); }
- static instance_iter endInstances() { return sInstances.end(); }
- static S32 instanceCount() { return sInstances.size(); }
-protected:
- LLInstanceTracker(KEY key) { add(key); }
- virtual ~LLInstanceTracker() { remove(); }
- virtual void setKey(KEY key) { remove(); add(key); }
- virtual const KEY& getKey() const { return mKey; }
-
-private:
- void add(KEY key)
- {
- mKey = key;
- sInstances[key] = static_cast<T*>(this);
- }
- void remove() { sInstances.erase(mKey); }
-
-private:
-
- KEY mKey;
- static std::map<KEY, T*> sInstances;
-};
-
-template<typename T>
-class LLInstanceTracker<T, T*> : boost::noncopyable
-{
-public:
- typedef typename std::set<T*>::iterator instance_iter;
- typedef typename std::set<T*>::const_iterator instance_const_iter;
-
- static instance_iter instancesBegin() { return sInstances.begin(); }
- static instance_iter instancesEnd() { return sInstances.end(); }
- static S32 instanceCount() { return sInstances.size(); }
-
-protected:
- LLInstanceTracker() { sInstances.insert(static_cast<T*>(this)); }
- virtual ~LLInstanceTracker() { sInstances.erase(static_cast<T*>(this)); }
-
- static std::set<T*> sInstances;
+ virtual LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority) = 0;
+ virtual LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority) = 0;
+ virtual void cleanUp() = 0;
};
-template <typename T, typename KEY> std::map<KEY, T*> LLInstanceTracker<T, KEY>::sInstances;
-template <typename T> std::set<T*> LLInstanceTracker<T, T*>::sInstances;
-
class LLCallbackRegistry
{
public:
- typedef boost::signal<void()> callback_signal_t;
+ typedef boost::signals2::signal<void()> callback_signal_t;
void registerCallback(const callback_signal_t::slot_type& slot)
{
@@ -746,93 +334,145 @@ private:
template <typename T> LLRegisterWith<LLInitClassList> LLInitClass<T>::sRegister(&T::initClass);
template <typename T> LLRegisterWith<LLDestroyClassList> LLDestroyClass<T>::sRegister(&T::destroyClass);
-
-template <typename DERIVED>
-class LLParamBlock
+// useful parameter blocks
+struct TimeIntervalParam : public LLInitParam::Choice<TimeIntervalParam>
{
-protected:
- LLParamBlock() { sBlock = (DERIVED*)this; }
+ Alternative<F32> seconds;
+ Alternative<S32> frames;
+ TimeIntervalParam()
+ : seconds("seconds"),
+ frames("frames")
+ {}
+};
- typedef typename boost::add_const<DERIVED>::type Tconst;
+template <class T>
+class LLUICachedControl : public LLCachedControl<T>
+{
+public:
+ // This constructor will declare a control if it doesn't exist in the contol group
+ LLUICachedControl(const std::string& name,
+ const T& default_value,
+ const std::string& comment = "Declared In Code")
+ : LLCachedControl<T>(LLUI::getControlControlGroup(name), name, default_value, comment)
+ {}
+
+ // This constructor will signal an error if the control doesn't exist in the control group
+ LLUICachedControl(const std::string& name)
+ : LLCachedControl<T>(LLUI::getControlControlGroup(name), name)
+ {}
+};
- template <typename T>
- class LLMandatoryParam
+namespace LLInitParam
+{
+ template<>
+ class TypedParam<LLRect>
+ : public BlockValue<LLRect>
{
+ typedef BlockValue<LLRect> super_t;
public:
- typedef typename boost::add_const<T>::type T_const;
+ Optional<S32> left,
+ top,
+ right,
+ bottom,
+ width,
+ height;
- LLMandatoryParam(T_const initial_val) : mVal(initial_val), mBlock(sBlock) {}
- LLMandatoryParam(const LLMandatoryParam<T>& other) : mVal(other.mVal) {}
+ TypedParam(BlockDescriptor& descriptor, const char* name, const LLRect& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count);
- DERIVED& operator ()(T_const set_value) { mVal = set_value; return *mBlock; }
- operator T() const { return mVal; }
- T operator=(T_const set_value) { mVal = set_value; return mVal; }
+ void setValueFromBlock() const;
+ void setBlockFromValue();
+ };
- private:
- T mVal;
- DERIVED* mBlock;
+ template<>
+ struct TypeValues<LLUIColor> : public TypeValuesHelper<LLUIColor>
+ {
+ static void declareValues();
};
- template <typename T>
- class LLOptionalParam
+ template<>
+ class TypedParam<LLUIColor>
+ : public BlockValue<LLUIColor>
{
+ typedef BlockValue<LLUIColor> super_t;
public:
- typedef typename boost::add_const<T>::type T_const;
-
- LLOptionalParam(T_const initial_val) : mVal(initial_val), mBlock(sBlock) {}
- LLOptionalParam() : mBlock(sBlock) {}
- LLOptionalParam(const LLOptionalParam<T>& other) : mVal(other.mVal) {}
-
- DERIVED& operator ()(T_const set_value) { mVal = set_value; return *mBlock; }
- operator T() const { return mVal; }
- T operator=(T_const set_value) { mVal = set_value; return mVal; }
+ Optional<F32> red,
+ green,
+ blue,
+ alpha;
+ Optional<std::string> control;
+
+ TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count);
+ void setValueFromBlock() const;
+ void setBlockFromValue();
+ };
- private:
- T mVal;
- DERIVED* mBlock;
+ // provide a better default for Optional<const LLFontGL*> than NULL
+ template <>
+ struct DefaultInitializer<const LLFontGL*>
+ {
+ // return reference to a single default instance of T
+ // built-in types will be initialized to zero, default constructor otherwise
+ static const LLFontGL* get()
+ {
+ static const LLFontGL* sDefaultFont = LLFontGL::getFontDefault();
+ return sDefaultFont;
+ }
};
- // specialization that requires initialization for reference types
- template <typename T>
- class LLOptionalParam <T&>
+
+ template<>
+ class TypedParam<const LLFontGL*>
+ : public BlockValue<const LLFontGL*>
{
+ typedef BlockValue<const LLFontGL*> super_t;
public:
- typedef typename boost::add_const<T&>::type T_const;
+ Mandatory<std::string> name;
+ Optional<std::string> size,
+ style;
+
+ TypedParam(BlockDescriptor& descriptor, const char* name, const LLFontGL* const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count);
+ void setValueFromBlock() const;
+ void setBlockFromValue();
+ };
- LLOptionalParam(T_const initial_val) : mVal(initial_val), mBlock(sBlock) {}
- LLOptionalParam(const LLOptionalParam<T&>& other) : mVal(other.mVal) {}
+ template<>
+ struct TypeValues<LLFontGL::HAlign> : public TypeValuesHelper<LLFontGL::HAlign>
+ {
+ static void declareValues();
+ };
- DERIVED& operator ()(T_const set_value) { mVal = set_value; return *mBlock; }
- operator T&() const { return mVal; }
- T& operator=(T_const set_value) { mVal = set_value; return mVal; }
+ template<>
+ struct TypeValues<LLFontGL::VAlign> : public TypeValuesHelper<LLFontGL::VAlign>
+ {
+ static void declareValues();
+ };
- private:
- T& mVal;
- DERIVED* mBlock;
+ template<>
+ struct TypeValues<LLFontGL::ShadowType> : public TypeValuesHelper<LLFontGL::ShadowType>
+ {
+ static void declareValues();
};
- // specialization that initializes pointer params to NULL
- template<typename T>
- class LLOptionalParam<T*>
+ template<>
+ struct ParamCompare<const LLFontGL*, false>
{
- public:
- typedef typename boost::add_const<T*>::type T_const;
-
- LLOptionalParam(T_const initial_val) : mVal(initial_val), mBlock(sBlock) {}
- LLOptionalParam() : mVal((T*)NULL), mBlock(sBlock) {}
- LLOptionalParam(const LLOptionalParam<T*>& other) : mVal(other.mVal) {}
-
- DERIVED& operator ()(T_const set_value) { mVal = set_value; return *mBlock; }
- operator T*() const { return mVal; }
- T* operator=(T_const set_value) { mVal = set_value; return mVal; }
- private:
- T* mVal;
- DERIVED* mBlock;
+ static bool equals(const LLFontGL* a, const LLFontGL* b);
};
- static DERIVED* sBlock;
-};
-template <typename T> T* LLParamBlock<T>::sBlock = NULL;
+ template<>
+ class TypedParam<LLCoordGL>
+ : public BlockValue<LLCoordGL>
+ {
+ typedef BlockValue<LLCoordGL> super_t;
+ public:
+ Optional<S32> x,
+ y;
+
+ TypedParam(BlockDescriptor& descriptor, const char* name, LLCoordGL value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count);
+ void setValueFromBlock() const;
+ void setBlockFromValue();
+ };
+}
#endif
diff --git a/indra/llui/lluicolortable.cpp b/indra/llui/lluicolortable.cpp
new file mode 100644
index 0000000000..9be33483d0
--- /dev/null
+++ b/indra/llui/lluicolortable.cpp
@@ -0,0 +1,332 @@
+/**
+ * @file lluicolortable.cpp
+ * @brief brief LLUIColorTable class implementation file
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include <queue>
+
+#include "lldir.h"
+#include "llui.h"
+#include "lluicolortable.h"
+#include "lluictrlfactory.h"
+
+LLUIColorTable::ColorParams::ColorParams()
+: value("value"),
+ reference("reference")
+{
+}
+
+LLUIColorTable::ColorEntryParams::ColorEntryParams()
+: name("name"),
+ color("")
+{
+}
+
+LLUIColorTable::Params::Params()
+: color_entries("color")
+{
+}
+
+void LLUIColorTable::insertFromParams(const Params& p)
+{
+ // this map will contain all color references after the following loop
+ typedef std::map<std::string, std::string> string_string_map_t;
+ string_string_map_t unresolved_refs;
+
+ for(LLInitParam::ParamIterator<ColorEntryParams>::const_iterator it = p.color_entries().begin();
+ it != p.color_entries().end();
+ ++it)
+ {
+ ColorEntryParams color_entry = *it;
+ if(color_entry.color.value.isChosen())
+ {
+ if(mUserSetColors.find(color_entry.name)!=mUserSetColors.end())
+ {
+ setColor(color_entry.name, color_entry.color.value);
+ }
+ else
+ {
+ setColor(color_entry.name, color_entry.color.value, mLoadedColors);
+ }
+ }
+ else
+ {
+ unresolved_refs.insert(string_string_map_t::value_type(color_entry.name, color_entry.color.reference));
+ }
+ }
+
+ // maintain an in order queue of visited references for better debugging of cycles
+ typedef std::queue<std::string> string_queue_t;
+ string_queue_t ref_chain;
+
+ // maintain a map of the previously visited references in the reference chain for detecting cycles
+ typedef std::map<std::string, string_string_map_t::iterator> string_color_ref_iter_map_t;
+ string_color_ref_iter_map_t visited_refs;
+
+ // loop through the unresolved color references until there are none left
+ while(!unresolved_refs.empty())
+ {
+ // we haven't visited any references yet
+ visited_refs.clear();
+
+ string_string_map_t::iterator current = unresolved_refs.begin();
+ string_string_map_t::iterator previous;
+
+ while(true)
+ {
+ if(current != unresolved_refs.end())
+ {
+ // locate the current reference in the previously visited references...
+ string_color_ref_iter_map_t::iterator visited = visited_refs.lower_bound(current->first);
+ if(visited != visited_refs.end()
+ && !(visited_refs.key_comp()(current->first, visited->first)))
+ {
+ // ...if we find the current reference in the previously visited references
+ // we know that there is a cycle
+ std::string ending_ref = current->first;
+ std::string warning("The following colors form a cycle: ");
+
+ // warn about the references in the chain and remove them from
+ // the unresolved references map because they cannot be resolved
+ for(string_color_ref_iter_map_t::iterator iter = visited_refs.begin();
+ iter != visited_refs.end();
+ ++iter)
+ {
+ if(!ref_chain.empty())
+ {
+ warning += ref_chain.front() + "->";
+ ref_chain.pop();
+ }
+ unresolved_refs.erase(iter->second);
+ }
+
+ llwarns << warning + ending_ref << llendl;
+
+ break;
+ }
+ else
+ {
+ // ...continue along the reference chain
+ ref_chain.push(current->first);
+ visited_refs.insert(visited, string_color_ref_iter_map_t::value_type(current->first, current));
+ }
+ }
+ else
+ {
+ // since this reference does not refer to another reference it must refer to an
+ // actual color, lets find it...
+ string_color_map_t::iterator color_value = mLoadedColors.find(previous->second);
+
+ if(color_value != mLoadedColors.end())
+ {
+ // ...we found the color, and we now add every reference in the reference chain
+ // to the color map
+ for(string_color_ref_iter_map_t::iterator iter = visited_refs.begin();
+ iter != visited_refs.end();
+ ++iter)
+ {
+ setColor(iter->first, color_value->second, mLoadedColors);
+ unresolved_refs.erase(iter->second);
+ }
+
+ break;
+ }
+ else
+ {
+ // ... we did not find the color which imples that the current reference
+ // references a non-existant color
+ for(string_color_ref_iter_map_t::iterator iter = visited_refs.begin();
+ iter != visited_refs.end();
+ ++iter)
+ {
+ llwarns << iter->first << " references a non-existent color" << llendl;
+ unresolved_refs.erase(iter->second);
+ }
+
+ break;
+ }
+ }
+
+ // find the next color reference in the reference chain
+ previous = current;
+ current = unresolved_refs.find(current->second);
+ }
+ }
+}
+
+void LLUIColorTable::clear()
+{
+ clearTable(mLoadedColors);
+ clearTable(mUserSetColors);
+}
+
+LLUIColor LLUIColorTable::getColor(const std::string& name, const LLColor4& default_color) const
+{
+ string_color_map_t::const_iterator iter = mUserSetColors.find(name);
+
+ if(iter != mUserSetColors.end())
+ {
+ return LLUIColor(&iter->second);
+ }
+
+ iter = mLoadedColors.find(name);
+
+ if(iter != mLoadedColors.end())
+ {
+ return LLUIColor(&iter->second);
+ }
+
+ return LLUIColor(default_color);
+}
+
+// update user color, loaded colors are parsed on initialization
+void LLUIColorTable::setColor(const std::string& name, const LLColor4& color)
+{
+ setColor(name, color, mUserSetColors);
+ setColor(name, color, mLoadedColors);
+}
+
+bool LLUIColorTable::loadFromSettings()
+{
+ bool result = false;
+
+ std::string default_filename = gDirUtilp->getExpandedFilename(LL_PATH_DEFAULT_SKIN, "colors.xml");
+ result |= loadFromFilename(default_filename);
+
+ std::string current_filename = gDirUtilp->getExpandedFilename(LL_PATH_TOP_SKIN, "colors.xml");
+ if(current_filename != default_filename)
+ {
+ result |= loadFromFilename(current_filename);
+ }
+
+ std::string user_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "colors.xml");
+ loadFromFilename(user_filename);
+
+ return result;
+}
+
+void LLUIColorTable::saveUserSettings() const
+{
+ Params params;
+
+ for(string_color_map_t::const_iterator it = mUserSetColors.begin();
+ it != mUserSetColors.end();
+ ++it)
+ {
+ ColorEntryParams color_entry;
+ color_entry.name = it->first;
+ color_entry.color.value = it->second;
+
+ params.color_entries.add(color_entry);
+ }
+
+ LLXMLNodePtr output_node = new LLXMLNode("colors", false);
+ LLXUIParser::instance().writeXUI(output_node, params);
+
+ if(!output_node->isNull())
+ {
+ const std::string& filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "colors.xml");
+ LLFILE *fp = LLFile::fopen(filename, "w");
+
+ if(fp != NULL)
+ {
+ LLXMLNode::writeHeaderToFile(fp);
+ output_node->writeToFile(fp);
+
+ fclose(fp);
+ }
+ }
+}
+
+bool LLUIColorTable::colorExists(const std::string& color_name) const
+{
+ return ((mLoadedColors.find(color_name) != mLoadedColors.end())
+ || (mUserSetColors.find(color_name) != mUserSetColors.end()));
+}
+
+void LLUIColorTable::clearTable(string_color_map_t& table)
+{
+ for(string_color_map_t::iterator it = table.begin();
+ it != table.end();
+ ++it)
+ {
+ it->second = LLColor4::magenta;
+ }
+}
+
+// this method inserts a color into the table if it does not exist
+// if the color already exists it changes the color
+void LLUIColorTable::setColor(const std::string& name, const LLColor4& color, string_color_map_t& table)
+{
+ string_color_map_t::iterator it = table.lower_bound(name);
+ if(it != table.end()
+ && !(table.key_comp()(name, it->first)))
+ {
+ it->second = color;
+ }
+ else
+ {
+ table.insert(it, string_color_map_t::value_type(name, color));
+ }
+}
+
+bool LLUIColorTable::loadFromFilename(const std::string& filename)
+{
+ LLXMLNodePtr root;
+
+ if(!LLXMLNode::parseFile(filename, root, NULL))
+ {
+ llwarns << "Unable to parse color file " << filename << llendl;
+ return false;
+ }
+
+ if(!root->hasName("colors"))
+ {
+ llwarns << filename << " is not a valid color definition file" << llendl;
+ return false;
+ }
+
+ Params params;
+ LLXUIParser::instance().readXUI(root, params, filename);
+
+ if(params.validateBlock())
+ {
+ insertFromParams(params);
+ }
+ else
+ {
+ llwarns << filename << " failed to load" << llendl;
+ return false;
+ }
+
+ return true;
+}
diff --git a/indra/llui/lluicolortable.h b/indra/llui/lluicolortable.h
new file mode 100644
index 0000000000..59be0c4f9a
--- /dev/null
+++ b/indra/llui/lluicolortable.h
@@ -0,0 +1,106 @@
+/**
+ * @file lluicolortable.h
+ * @brief brief LLUIColorTable class header file
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLUICOLORTABLE_H_
+#define LL_LLUICOLORTABLE_H_
+
+#include <map>
+
+#include "llinitparam.h"
+#include "llsingleton.h"
+
+#include "v4color.h"
+
+class LLUIColor;
+
+class LLUIColorTable : public LLSingleton<LLUIColorTable>
+{
+LOG_CLASS(LLUIColorTable);
+public:
+ struct ColorParams : LLInitParam::Choice<ColorParams>
+ {
+ Alternative<LLColor4> value;
+ Alternative<std::string> reference;
+
+ ColorParams();
+ };
+
+ struct ColorEntryParams : LLInitParam::Block<ColorEntryParams>
+ {
+ Mandatory<std::string> name;
+ Mandatory<ColorParams> color;
+
+ ColorEntryParams();
+ };
+
+ struct Params : LLInitParam::Block<Params>
+ {
+ Multiple<ColorEntryParams> color_entries;
+
+ Params();
+ };
+
+ // define colors by passing in a param block that can be generated via XUI file or manually
+ void insertFromParams(const Params& p);
+
+ // reset all colors to default magenta color
+ void clear();
+
+ // color lookup
+ LLUIColor getColor(const std::string& name, const LLColor4& default_color = LLColor4::magenta) const;
+
+ // if the color is in the table, it's value is changed, otherwise it is added
+ void setColor(const std::string& name, const LLColor4& color);
+
+ // returns true if color_name exists in the table
+ bool colorExists(const std::string& color_name) const;
+
+ // loads colors from settings files
+ bool loadFromSettings();
+
+ // saves colors specified by the user to the users skin directory
+ void saveUserSettings() const;
+
+private:
+ bool loadFromFilename(const std::string& filename);
+
+ // consider using sorted vector, can be much faster
+ typedef std::map<std::string, LLColor4> string_color_map_t;
+
+ void clearTable(string_color_map_t& table);
+ void setColor(const std::string& name, const LLColor4& color, string_color_map_t& table);
+
+ string_color_map_t mLoadedColors;
+ string_color_map_t mUserSetColors;
+};
+
+#endif // LL_LLUICOLORTABLE_H
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index 9d97312ab0..3ade46d367 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -31,108 +31,343 @@
* $/LicenseInfo$
*/
-//#include "llviewerprecompiledheaders.h"
#include "linden_common.h"
+
+#define LLUICTRL_CPP
#include "lluictrl.h"
+
#include "llfocusmgr.h"
#include "llpanel.h"
+#include "lluictrlfactory.h"
+
+static LLDefaultChildRegistry::Register<LLUICtrl> r("ui_ctrl");
-static LLRegisterWidget<LLUICtrl> r("ui_ctrl");
+// Compiler optimization, generate extern template
+template class LLUICtrl* LLView::getChild<class LLUICtrl>(
+ const std::string& name, BOOL recurse) const;
-LLFocusableElement::LLFocusableElement()
-: mFocusLostCallback(NULL),
- mFocusReceivedCallback(NULL),
- mFocusChangedCallback(NULL),
- mFocusCallbackUserData(NULL)
+LLUICtrl::CallbackParam::CallbackParam()
+: name("name"),
+ function_name("function"),
+ parameter("parameter"),
+ control_name("control") // Shortcut to control -> "control_name" for backwards compatability
{
+ addSynonym(parameter, "userdata");
}
-//virtual
-LLFocusableElement::~LLFocusableElement()
+LLUICtrl::EnableControls::EnableControls()
+: enabled("enabled_control"),
+ disabled("disabled_control")
+{}
+
+LLUICtrl::ControlVisibility::ControlVisibility()
+: visible("visibility_control"),
+ invisible("invisibility_control")
{
+ addSynonym(visible, "visiblity_control");
+ addSynonym(invisible, "invisiblity_control");
}
-void LLFocusableElement::onFocusReceived()
+LLUICtrl::Params::Params()
+: tab_stop("tab_stop", true),
+ chrome("chrome", false),
+ label("label"),
+ initial_value("value"),
+ init_callback("init_callback"),
+ commit_callback("commit_callback"),
+ validate_callback("validate_callback"),
+ mouseenter_callback("mouseenter_callback"),
+ mouseleave_callback("mouseleave_callback"),
+ control_name("control_name"),
+ font("font", LLFontGL::getFontSansSerif()),
+ font_halign("halign"),
+ font_valign("valign"),
+ length("length"), // ignore LLXMLNode cruft
+ type("type") // ignore LLXMLNode cruft
+{
+ addSynonym(initial_value, "initial_value");
+}
+
+// NOTE: the LLFocusableElement implementation has been moved from here to llfocusmgr.cpp.
+
+//static
+const LLUICtrl::Params& LLUICtrl::getDefaultParams()
{
- if( mFocusReceivedCallback )
+ return LLUICtrlFactory::getDefaultParams<LLUICtrl>();
+}
+
+
+LLUICtrl::LLUICtrl(const LLUICtrl::Params& p, const LLViewModelPtr& viewmodel)
+: LLView(p),
+ mTentative(FALSE),
+ mIsChrome(FALSE),
+ mViewModel(viewmodel),
+ mControlVariable(NULL),
+ mEnabledControlVariable(NULL),
+ mDisabledControlVariable(NULL),
+ mMakeVisibleControlVariable(NULL),
+ mMakeInvisibleControlVariable(NULL),
+ mCommitSignal(NULL),
+ mValidateSignal(NULL),
+ mMouseEnterSignal(NULL),
+ mMouseLeaveSignal(NULL),
+ mMouseDownSignal(NULL),
+ mMouseUpSignal(NULL),
+ mRightMouseDownSignal(NULL),
+ mRightMouseUpSignal(NULL),
+ mDoubleClickSignal(NULL)
+{
+ mUICtrlHandle.bind(this);
+}
+
+void LLUICtrl::initFromParams(const Params& p)
+{
+ LLView::initFromParams(p);
+
+ setIsChrome(p.chrome);
+ setControlName(p.control_name);
+ if(p.enabled_controls.isProvided())
+ {
+ if (p.enabled_controls.enabled.isChosen())
+ {
+ LLControlVariable* control = findControl(p.enabled_controls.enabled);
+ if (control)
+ setEnabledControlVariable(control);
+ }
+ else if(p.enabled_controls.disabled.isChosen())
+ {
+ LLControlVariable* control = findControl(p.enabled_controls.disabled);
+ if (control)
+ setDisabledControlVariable(control);
+ }
+ }
+ if(p.controls_visibility.isProvided())
+ {
+ if (p.controls_visibility.visible.isChosen())
+ {
+ LLControlVariable* control = findControl(p.controls_visibility.visible);
+ if (control)
+ setMakeVisibleControlVariable(control);
+ }
+ else if (p.controls_visibility.invisible.isChosen())
+ {
+ LLControlVariable* control = findControl(p.controls_visibility.invisible);
+ if (control)
+ setMakeInvisibleControlVariable(control);
+ }
+ }
+
+ setTabStop(p.tab_stop);
+
+ if (p.initial_value.isProvided()
+ && !p.control_name.isProvided())
+ {
+ setValue(p.initial_value);
+ }
+
+ if (p.commit_callback.isProvided())
+ {
+ setCommitCallback(initCommitCallback(p.commit_callback));
+ }
+
+ if (p.validate_callback.isProvided())
+ {
+ setValidateCallback(initEnableCallback(p.validate_callback));
+ }
+
+ if (p.init_callback.isProvided())
+ {
+ if (p.init_callback.function.isProvided())
+ {
+ p.init_callback.function()(this, p.init_callback.parameter);
+ }
+ else
+ {
+ commit_callback_t* initfunc = (CommitCallbackRegistry::getValue(p.init_callback.function_name));
+ if (initfunc)
+ {
+ (*initfunc)(this, p.init_callback.parameter);
+ }
+ }
+ }
+
+ if(p.mouseenter_callback.isProvided())
{
- mFocusReceivedCallback( this, mFocusCallbackUserData );
+ setMouseEnterCallback(initCommitCallback(p.mouseenter_callback));
}
- if( mFocusChangedCallback )
+
+ if(p.mouseleave_callback.isProvided())
{
- mFocusChangedCallback( this, mFocusCallbackUserData );
+ setMouseLeaveCallback(initCommitCallback(p.mouseleave_callback));
}
}
-void LLFocusableElement::onFocusLost()
+
+LLUICtrl::~LLUICtrl()
{
- if( mFocusLostCallback )
+ gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit()
+
+ if( gFocusMgr.getTopCtrl() == this )
{
- mFocusLostCallback( this, mFocusCallbackUserData );
+ llwarns << "UI Control holding top ctrl deleted: " << getName() << ". Top view removed." << llendl;
+ gFocusMgr.removeTopCtrlWithoutCallback( this );
}
- if( mFocusChangedCallback )
+ delete mCommitSignal;
+ delete mValidateSignal;
+ delete mMouseEnterSignal;
+ delete mMouseLeaveSignal;
+ delete mMouseDownSignal;
+ delete mMouseUpSignal;
+ delete mRightMouseDownSignal;
+ delete mRightMouseUpSignal;
+ delete mDoubleClickSignal;
+}
+
+void default_commit_handler(LLUICtrl* ctrl, const LLSD& param)
+{}
+
+bool default_enable_handler(LLUICtrl* ctrl, const LLSD& param)
+{
+ return true;
+}
+
+
+LLUICtrl::commit_signal_t::slot_type LLUICtrl::initCommitCallback(const CommitCallbackParam& cb)
+{
+ if (cb.function.isProvided())
{
- mFocusChangedCallback( this, mFocusCallbackUserData );
+ if (cb.parameter.isProvided())
+ return boost::bind(cb.function(), _1, cb.parameter);
+ else
+ return cb.function();
}
+ else
+ {
+ std::string function_name = cb.function_name;
+ commit_callback_t* func = (CommitCallbackRegistry::getValue(function_name));
+ if (func)
+ {
+ if (cb.parameter.isProvided())
+ return boost::bind((*func), _1, cb.parameter);
+ else
+ return commit_signal_t::slot_type(*func);
+ }
+ else if (!function_name.empty())
+ {
+ llwarns << "No callback found for: '" << function_name << "' in control: " << getName() << llendl;
+ }
+ }
+ return default_commit_handler;
}
-BOOL LLFocusableElement::hasFocus() const
+LLUICtrl::enable_signal_t::slot_type LLUICtrl::initEnableCallback(const EnableCallbackParam& cb)
{
- return FALSE;
+ // Set the callback function
+ if (cb.function.isProvided())
+ {
+ if (cb.parameter.isProvided())
+ return boost::bind(cb.function(), this, cb.parameter);
+ else
+ return cb.function();
+ }
+ else
+ {
+ enable_callback_t* func = (EnableCallbackRegistry::getValue(cb.function_name));
+ if (func)
+ {
+ if (cb.parameter.isProvided())
+ return boost::bind((*func), this, cb.parameter);
+ else
+ return enable_signal_t::slot_type(*func);
+ }
+ }
+ return default_enable_handler;
}
-void LLFocusableElement::setFocus(BOOL b)
+// virtual
+void LLUICtrl::onMouseEnter(S32 x, S32 y, MASK mask)
{
+ if (mMouseEnterSignal)
+ {
+ (*mMouseEnterSignal)(this, getValue());
+ }
}
+// virtual
+void LLUICtrl::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ if(mMouseLeaveSignal)
+ {
+ (*mMouseLeaveSignal)(this, getValue());
+ }
+}
-
-LLUICtrl::LLUICtrl() :
- mCommitCallback(NULL),
- mLostTopCallback(NULL),
- mValidateCallback(NULL),
- mCallbackUserData(NULL),
- mTentative(FALSE),
- mTabStop(TRUE),
- mIsChrome(FALSE)
+//virtual
+BOOL LLUICtrl::handleMouseDown(S32 x, S32 y, MASK mask)
{
+ BOOL handled = LLView::handleMouseDown(x,y,mask);
+ if (mMouseDownSignal)
+ {
+ (*mMouseDownSignal)(this,x,y,mask);
+ }
+ return handled;
}
-LLUICtrl::LLUICtrl(const std::string& name, const LLRect& rect, BOOL mouse_opaque,
- void (*on_commit_callback)(LLUICtrl*, void*),
- void* callback_userdata,
- U32 reshape)
-: // can't make this automatically follow top and left, breaks lots
- // of buttons in the UI. JC 7/20/2002
- LLView( name, rect, mouse_opaque, reshape ),
- mCommitCallback( on_commit_callback) ,
- mLostTopCallback( NULL ),
- mValidateCallback( NULL ),
- mCallbackUserData( callback_userdata ),
- mTentative( FALSE ),
- mTabStop( TRUE ),
- mIsChrome(FALSE)
+//virtual
+BOOL LLUICtrl::handleMouseUp(S32 x, S32 y, MASK mask)
{
+ BOOL handled = LLView::handleMouseUp(x,y,mask);
+ if (mMouseUpSignal)
+ {
+ (*mMouseUpSignal)(this,x,y,mask);
+ }
+ return handled;
}
-LLUICtrl::~LLUICtrl()
+//virtual
+BOOL LLUICtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
- gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit()
+ BOOL handled = LLView::handleRightMouseDown(x,y,mask);
+ if (mRightMouseDownSignal)
+ {
+ (*mRightMouseDownSignal)(this,x,y,mask);
+ }
+ return handled;
+}
- if( gFocusMgr.getTopCtrl() == this )
+//virtual
+BOOL LLUICtrl::handleRightMouseUp(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = LLView::handleRightMouseUp(x,y,mask);
+ if(mRightMouseUpSignal)
{
- llwarns << "UI Control holding top ctrl deleted: " << getName() << ". Top view removed." << llendl;
- gFocusMgr.removeTopCtrlWithoutCallback( this );
+ (*mRightMouseUpSignal)(this,x,y,mask);
}
+ return handled;
}
-void LLUICtrl::onCommit()
+BOOL LLUICtrl::handleDoubleClick(S32 x, S32 y, MASK mask)
{
- if( mCommitCallback )
+ BOOL handled = LLView::handleDoubleClick(x, y, mask);
+ if (mDoubleClickSignal)
{
- mCommitCallback( this, mCallbackUserData );
+ (*mDoubleClickSignal)(this, x, y, mask);
}
+ return handled;
+}
+
+// can't tab to children of a non-tab-stop widget
+BOOL LLUICtrl::canFocusChildren() const
+{
+ return hasTabStop();
+}
+
+
+void LLUICtrl::onCommit()
+{
+ if (mCommitSignal)
+ (*mCommitSignal)(this, getValue());
}
//virtual
@@ -141,10 +376,170 @@ BOOL LLUICtrl::isCtrl() const
return TRUE;
}
+//virtual
+void LLUICtrl::setValue(const LLSD& value)
+{
+ mViewModel->setValue(value);
+}
+
//virtual
LLSD LLUICtrl::getValue() const
{
- return LLSD();
+ return mViewModel->getValue();
+}
+
+/// When two widgets are displaying the same data (e.g. during a skin
+/// change), share their ViewModel.
+void LLUICtrl::shareViewModelFrom(const LLUICtrl& other)
+{
+ // Because mViewModel is an LLViewModelPtr, this assignment will quietly
+ // dispose of the previous LLViewModel -- unless it's already shared by
+ // somebody else.
+ mViewModel = other.mViewModel;
+}
+
+//virtual
+LLViewModel* LLUICtrl::getViewModel() const
+{
+ return mViewModel;
+}
+
+bool LLUICtrl::setControlValue(const LLSD& value)
+{
+ if (mControlVariable)
+ {
+ mControlVariable->set(value);
+ return true;
+ }
+ return false;
+}
+
+void LLUICtrl::setControlVariable(LLControlVariable* control)
+{
+ if (mControlVariable)
+ {
+ //RN: this will happen in practice, should we try to avoid it?
+ //llwarns << "setControlName called twice on same control!" << llendl;
+ mControlConnection.disconnect(); // disconnect current signal
+ mControlVariable = NULL;
+ }
+
+ if (control)
+ {
+ mControlVariable = control;
+ mControlConnection = mControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getUICtrlHandle(), std::string("value")));
+ setValue(mControlVariable->getValue());
+ }
+}
+
+//virtual
+void LLUICtrl::setControlName(const std::string& control_name, LLView *context)
+{
+ if (context == NULL)
+ {
+ context = this;
+ }
+
+ // Register new listener
+ if (!control_name.empty())
+ {
+ LLControlVariable* control = context->findControl(control_name);
+ setControlVariable(control);
+ }
+}
+
+void LLUICtrl::setEnabledControlVariable(LLControlVariable* control)
+{
+ if (mEnabledControlVariable)
+ {
+ mEnabledControlConnection.disconnect(); // disconnect current signal
+ mEnabledControlVariable = NULL;
+ }
+ if (control)
+ {
+ mEnabledControlVariable = control;
+ mEnabledControlConnection = mEnabledControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getUICtrlHandle(), std::string("enabled")));
+ setEnabled(mEnabledControlVariable->getValue().asBoolean());
+ }
+}
+
+void LLUICtrl::setDisabledControlVariable(LLControlVariable* control)
+{
+ if (mDisabledControlVariable)
+ {
+ mDisabledControlConnection.disconnect(); // disconnect current signal
+ mDisabledControlVariable = NULL;
+ }
+ if (control)
+ {
+ mDisabledControlVariable = control;
+ mDisabledControlConnection = mDisabledControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getUICtrlHandle(), std::string("disabled")));
+ setEnabled(!(mDisabledControlVariable->getValue().asBoolean()));
+ }
+}
+
+void LLUICtrl::setMakeVisibleControlVariable(LLControlVariable* control)
+{
+ if (mMakeVisibleControlVariable)
+ {
+ mMakeVisibleControlConnection.disconnect(); // disconnect current signal
+ mMakeVisibleControlVariable = NULL;
+ }
+ if (control)
+ {
+ mMakeVisibleControlVariable = control;
+ mMakeVisibleControlConnection = mMakeVisibleControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getUICtrlHandle(), std::string("visible")));
+ setVisible(mMakeVisibleControlVariable->getValue().asBoolean());
+ }
+}
+
+void LLUICtrl::setMakeInvisibleControlVariable(LLControlVariable* control)
+{
+ if (mMakeInvisibleControlVariable)
+ {
+ mMakeInvisibleControlConnection.disconnect(); // disconnect current signal
+ mMakeInvisibleControlVariable = NULL;
+ }
+ if (control)
+ {
+ mMakeInvisibleControlVariable = control;
+ mMakeInvisibleControlConnection = mMakeInvisibleControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getUICtrlHandle(), std::string("invisible")));
+ setVisible(!(mMakeInvisibleControlVariable->getValue().asBoolean()));
+ }
+}
+// static
+bool LLUICtrl::controlListener(const LLSD& newvalue, LLHandle<LLUICtrl> handle, std::string type)
+{
+ LLUICtrl* ctrl = handle.get();
+ if (ctrl)
+ {
+ if (type == "value")
+ {
+ ctrl->setValue(newvalue);
+ return true;
+ }
+ else if (type == "enabled")
+ {
+ ctrl->setEnabled(newvalue.asBoolean());
+ return true;
+ }
+ else if(type =="disabled")
+ {
+ ctrl->setEnabled(!newvalue.asBoolean());
+ return true;
+ }
+ else if (type == "visible")
+ {
+ ctrl->setVisible(newvalue.asBoolean());
+ return true;
+ }
+ else if (type == "invisible")
+ {
+ ctrl->setVisible(!newvalue.asBoolean());
+ return true;
+ }
+ }
+ return false;
}
// virtual
@@ -205,58 +600,6 @@ void LLUICtrl::setFocus(BOOL b)
}
}
-void LLUICtrl::onFocusReceived()
-{
- // trigger callbacks
- LLFocusableElement::onFocusReceived();
-
- // find first view in hierarchy above new focus that is a LLUICtrl
- LLView* viewp = getParent();
- LLUICtrl* last_focus = gFocusMgr.getLastKeyboardFocus();
-
- while (viewp && !viewp->isCtrl())
- {
- viewp = viewp->getParent();
- }
-
- // and if it has newly gained focus, call onFocusReceived()
- LLUICtrl* ctrlp = static_cast<LLUICtrl*>(viewp);
- if (ctrlp && (!last_focus || !last_focus->hasAncestor(ctrlp)))
- {
- ctrlp->onFocusReceived();
- }
-}
-
-void LLUICtrl::onFocusLost()
-{
- // trigger callbacks
- LLFocusableElement::onFocusLost();
-
- // find first view in hierarchy above old focus that is a LLUICtrl
- LLView* viewp = getParent();
- while (viewp && !viewp->isCtrl())
- {
- viewp = viewp->getParent();
- }
-
- // and if it has just lost focus, call onFocusReceived()
- LLUICtrl* ctrlp = static_cast<LLUICtrl*>(viewp);
- // hasFocus() includes any descendants
- if (ctrlp && !ctrlp->hasFocus())
- {
- ctrlp->onFocusLost();
- }
-}
-
-void LLUICtrl::onLostTop()
-{
- if (mLostTopCallback)
- {
- mLostTopCallback(this, mCallbackUserData);
- }
-}
-
-
// virtual
void LLUICtrl::setTabStop( BOOL b )
{
@@ -278,12 +621,13 @@ BOOL LLUICtrl::acceptsTextInput() const
//virtual
BOOL LLUICtrl::isDirty() const
{
- return FALSE;
+ return mViewModel->isDirty();
};
//virtual
void LLUICtrl::resetDirty()
{
+ mViewModel->resetDirty();
}
// virtual
@@ -305,7 +649,6 @@ void LLUICtrl::setIsChrome(BOOL is_chrome)
// virtual
BOOL LLUICtrl::getIsChrome() const
{
-
LLView* parent_ctrl = getParent();
while(parent_ctrl)
{
@@ -456,7 +799,8 @@ BOOL LLUICtrl::focusNextItem(BOOL text_fields_only)
{
// this assumes that this method is called on the focus root.
LLCtrlQuery query = getTabOrderQuery();
- if(text_fields_only || LLUI::sConfigGroup->getBOOL("TabToTextFieldsOnly"))
+ static LLUICachedControl<bool> tab_to_text_fields_only ("TabToTextFieldsOnly", false);
+ if(text_fields_only || tab_to_text_fields_only)
{
query.addPreFilter(LLUICtrl::LLTextInputFilter::getInstance());
}
@@ -468,7 +812,8 @@ BOOL LLUICtrl::focusPrevItem(BOOL text_fields_only)
{
// this assumes that this method is called on the focus root.
LLCtrlQuery query = getTabOrderQuery();
- if(text_fields_only || LLUI::sConfigGroup->getBOOL("TabToTextFieldsOnly"))
+ static LLUICachedControl<bool> tab_to_text_fields_only ("TabToTextFieldsOnly", false);
+ if(text_fields_only || tab_to_text_fields_only)
{
query.addPreFilter(LLUICtrl::LLTextInputFilter::getInstance());
}
@@ -492,65 +837,6 @@ LLUICtrl* LLUICtrl::findRootMostFocusRoot()
return focus_root;
}
-
-/*
-// Don't let the children handle the tool tip. Handle it here instead.
-BOOL LLUICtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
-{
- BOOL handled = FALSE;
- if (getVisible() && pointInView( x, y ) )
- {
- if( !mToolTipMsg.empty() )
- {
- msg = mToolTipMsg;
-
- // Convert rect local to screen coordinates
- localPointToScreen(
- 0, 0,
- &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
- localPointToScreen(
- getRect().getWidth(), getRect().getHeight(),
- &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) );
-
- handled = TRUE;
- }
- }
-
- if (!handled)
- {
- return LLView::handleToolTip(x, y, msg, sticky_rect_screen);
- }
-
- return handled;
-}*/
-
-void LLUICtrl::initFromXML(LLXMLNodePtr node, LLView* parent)
-{
- BOOL has_tab_stop = hasTabStop();
- node->getAttributeBOOL("tab_stop", has_tab_stop);
-
- setTabStop(has_tab_stop);
-
- LLView::initFromXML(node, parent);
-}
-
-LLXMLNodePtr LLUICtrl::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLView::getXML(save_children);
- node->createChild("tab_stop", TRUE)->setBoolValue(hasTabStop());
-
- return node;
-}
-
-//static
-LLView* LLUICtrl::fromXML(LLXMLNodePtr node, LLView* parent, class LLUICtrlFactory* factory)
-{
- LLUICtrl* ctrl = new LLUICtrl();
- ctrl->initFromXML(node, parent);
- return ctrl;
-}
-
-
// Skip over any parents that are not LLUICtrl's
// Used in focus logic since only LLUICtrl elements can have focus
LLUICtrl* LLUICtrl::getParentUICtrl() const
@@ -570,6 +856,59 @@ LLUICtrl* LLUICtrl::getParentUICtrl() const
return NULL;
}
+bool LLUICtrl::findHelpTopic(std::string& help_topic_out)
+{
+ LLUICtrl* ctrl = this;
+
+ // search back through the control's parents for a panel
+ // or tab with a help_topic string defined
+ while (ctrl)
+ {
+ LLPanel *panel = dynamic_cast<LLPanel *>(ctrl);
+
+ if (panel)
+ {
+ // does the panel have a sub-panel with a help topic?
+ LLPanel *subpanel = panel->childGetVisiblePanelWithHelp();
+ if (subpanel)
+ {
+ help_topic_out = subpanel->getHelpTopic();
+ return true; // success (subpanel)
+ }
+
+ // does the panel have an active tab with a help topic?
+ LLPanel *tab = panel->childGetVisibleTabWithHelp();
+ if (tab)
+ {
+ help_topic_out = tab->getHelpTopic();
+ return true; // success (tab)
+ }
+
+ // otherwise, does the panel have a help topic itself?
+ if (!panel->getHelpTopic().empty())
+ {
+ help_topic_out = panel->getHelpTopic();
+ return true; // success (panel)
+ }
+ }
+
+ ctrl = ctrl->getParentUICtrl();
+ }
+
+ return false; // no help topic found
+}
+
+// *TODO: Deprecate; for backwards compatability only:
+boost::signals2::connection LLUICtrl::setCommitCallback( boost::function<void (LLUICtrl*,void*)> cb, void* data)
+{
+ return setCommitCallback( boost::bind(cb, _1, data));
+}
+boost::signals2::connection LLUICtrl::setValidateBeforeCommit( boost::function<bool (const LLSD& data)> cb )
+{
+ if (!mValidateSignal) mValidateSignal = new enable_signal_t();
+ return mValidateSignal->connect(boost::bind(cb, _2));
+}
+
// virtual
void LLUICtrl::setTentative(BOOL b)
{
@@ -583,18 +922,59 @@ BOOL LLUICtrl::getTentative() const
}
// virtual
-void LLUICtrl::setDoubleClickCallback( void (*cb)(void*) )
+void LLUICtrl::setColor(const LLColor4& color)
+{ }
+
+boost::signals2::connection LLUICtrl::setCommitCallback( const commit_signal_t::slot_type& cb )
{
+ if (!mCommitSignal) mCommitSignal = new commit_signal_t();
+ return mCommitSignal->connect(cb);
}
-// virtual
-void LLUICtrl::setColor(const LLColor4& color)
-{ }
+boost::signals2::connection LLUICtrl::setValidateCallback( const enable_signal_t::slot_type& cb )
+{
+ if (!mValidateSignal) mValidateSignal = new enable_signal_t();
+ return mValidateSignal->connect(cb);
+}
-// virtual
-void LLUICtrl::setMinValue(LLSD min_value)
-{ }
+boost::signals2::connection LLUICtrl::setMouseEnterCallback( const commit_signal_t::slot_type& cb )
+{
+ if (!mMouseEnterSignal) mMouseEnterSignal = new commit_signal_t();
+ return mMouseEnterSignal->connect(cb);
+}
-// virtual
-void LLUICtrl::setMaxValue(LLSD max_value)
-{ }
+boost::signals2::connection LLUICtrl::setMouseLeaveCallback( const commit_signal_t::slot_type& cb )
+{
+ if (!mMouseLeaveSignal) mMouseLeaveSignal = new commit_signal_t();
+ return mMouseLeaveSignal->connect(cb);
+}
+
+boost::signals2::connection LLUICtrl::setMouseDownCallback( const mouse_signal_t::slot_type& cb )
+{
+ if (!mMouseDownSignal) mMouseDownSignal = new mouse_signal_t();
+ return mMouseDownSignal->connect(cb);
+}
+
+boost::signals2::connection LLUICtrl::setMouseUpCallback( const mouse_signal_t::slot_type& cb )
+{
+ if (!mMouseUpSignal) mMouseUpSignal = new mouse_signal_t();
+ return mMouseUpSignal->connect(cb);
+}
+
+boost::signals2::connection LLUICtrl::setRightMouseDownCallback( const mouse_signal_t::slot_type& cb )
+{
+ if (!mRightMouseDownSignal) mRightMouseDownSignal = new mouse_signal_t();
+ return mRightMouseDownSignal->connect(cb);
+}
+
+boost::signals2::connection LLUICtrl::setRightMouseUpCallback( const mouse_signal_t::slot_type& cb )
+{
+ if (!mRightMouseUpSignal) mRightMouseUpSignal = new mouse_signal_t();
+ return mRightMouseUpSignal->connect(cb);
+}
+
+boost::signals2::connection LLUICtrl::setDoubleClickCallback( const mouse_signal_t::slot_type& cb )
+{
+ if (!mDoubleClickSignal) mDoubleClickSignal = new mouse_signal_t();
+ return mDoubleClickSignal->connect(cb);
+}
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index db41af8470..b9a4f61e15 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -34,57 +34,133 @@
#ifndef LL_LLUICTRL_H
#define LL_LLUICTRL_H
-#include "llview.h"
+//#include "llboost.h"
#include "llrect.h"
#include "llsd.h"
+#include <boost/function.hpp>
+#include <boost/signals2.hpp>
+
+#include "llinitparam.h"
+#include "llview.h"
+#include "llviewmodel.h" // *TODO move dependency to .cpp file
+
+const BOOL TAKE_FOCUS_YES = TRUE;
+const BOOL TAKE_FOCUS_NO = FALSE;
+// NOTE: the LLFocusableElement class declaration has been moved from here to llfocusmgr.h.
-class LLFocusableElement
+class LLUICtrl
+ : public LLView, public boost::signals2::trackable
{
- friend class LLFocusMgr; // allow access to focus change handlers
public:
- LLFocusableElement();
- virtual ~LLFocusableElement();
- virtual void setFocus( BOOL b );
- virtual BOOL hasFocus() const;
- void setFocusLostCallback(void (*cb)(LLFocusableElement* caller, void*), void* user_data = NULL) { mFocusLostCallback = cb; mFocusCallbackUserData = user_data; }
- void setFocusReceivedCallback( void (*cb)(LLFocusableElement*, void*), void* user_data = NULL) { mFocusReceivedCallback = cb; mFocusCallbackUserData = user_data; }
- void setFocusChangedCallback( void (*cb)(LLFocusableElement*, void*), void* user_data = NULL ) { mFocusChangedCallback = cb; mFocusCallbackUserData = user_data; }
+ typedef boost::function<void (LLUICtrl* ctrl, const LLSD& param)> commit_callback_t;
+ typedef boost::signals2::signal<void (LLUICtrl* ctrl, const LLSD& param)> commit_signal_t;
+ // *TODO: add xml support for this type of signal in the future
+ typedef boost::signals2::signal<void (LLUICtrl* ctrl, S32 x, S32 y, MASK mask)> mouse_signal_t;
+
+ typedef boost::function<bool (LLUICtrl* ctrl, const LLSD& param)> enable_callback_t;
+ typedef boost::signals2::signal<bool (LLUICtrl* ctrl, const LLSD& param), boost_boolean_combiner> enable_signal_t;
+
+ struct CallbackParam : public LLInitParam::Block<CallbackParam>
+ {
+ Ignored name;
-protected:
- virtual void onFocusReceived();
- virtual void onFocusLost();
- void (*mFocusLostCallback)( LLFocusableElement* caller, void* userdata );
- void (*mFocusReceivedCallback)( LLFocusableElement* ctrl, void* userdata );
- void (*mFocusChangedCallback)( LLFocusableElement* ctrl, void* userdata );
- void* mFocusCallbackUserData;
-};
+ Optional<std::string> function_name;
+ Optional<LLSD> parameter;
+
+ Optional<std::string> control_name;
+
+ CallbackParam();
+ };
+
+ struct CommitCallbackParam : public LLInitParam::Block<CommitCallbackParam, CallbackParam >
+ {
+ Optional<commit_callback_t> function;
+ };
+
+ // also used for visible callbacks
+ struct EnableCallbackParam : public LLInitParam::Block<EnableCallbackParam, CallbackParam >
+ {
+ Optional<enable_callback_t> function;
+ };
+
+ struct EnableControls : public LLInitParam::Choice<EnableControls>
+ {
+ Alternative<std::string> enabled;
+ Alternative<std::string> disabled;
+
+ EnableControls();
+ };
+ struct ControlVisibility : public LLInitParam::Choice<ControlVisibility>
+ {
+ Alternative<std::string> visible;
+ Alternative<std::string> invisible;
+
+ ControlVisibility();
+ };
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
+ {
+ Optional<std::string> label;
+ Optional<bool> tab_stop,
+ chrome;
+ Optional<LLSD> initial_value;
+
+ Optional<CommitCallbackParam> init_callback,
+ commit_callback;
+ Optional<EnableCallbackParam> validate_callback;
+
+ Optional<CommitCallbackParam> mouseenter_callback;
+ Optional<CommitCallbackParam> mouseleave_callback;
+
+ Optional<std::string> control_name;
+ Optional<EnableControls> enabled_controls;
+ Optional<ControlVisibility> controls_visibility;
+
+ // font params
+ Optional<const LLFontGL*> font;
+ Optional<LLFontGL::HAlign> font_halign;
+ Optional<LLFontGL::VAlign> font_valign;
+
+ // cruft from LLXMLNode implementation
+ Ignored type,
+ length;
+
+ Params();
+ };
-class LLUICtrl
-: public LLView, public LLFocusableElement
-{
-public:
- typedef void (*LLUICtrlCallback)(LLUICtrl* ctrl, void* userdata);
- typedef BOOL (*LLUICtrlValidate)(LLUICtrl* ctrl, void* userdata);
-
- LLUICtrl();
- LLUICtrl( const std::string& name, const LLRect& rect, BOOL mouse_opaque,
- LLUICtrlCallback callback,
- void* callback_userdata,
- U32 reshape=FOLLOWS_NONE);
/*virtual*/ ~LLUICtrl();
+ void initFromParams(const Params& p);
+protected:
+ friend class LLUICtrlFactory;
+ static const Params& getDefaultParams();
+ LLUICtrl(const Params& p = getDefaultParams(),
+ const LLViewModelPtr& viewmodel=LLViewModelPtr(new LLViewModel));
+
+ commit_signal_t::slot_type initCommitCallback(const CommitCallbackParam& cb);
+ enable_signal_t::slot_type initEnableCallback(const EnableCallbackParam& cb);
+
+ // We need this virtual so we can override it with derived versions
+ virtual LLViewModel* getViewModel() const;
+ // We shouldn't ever need to set this directly
+ //virtual void setViewModel(const LLViewModelPtr&);
+
+public:
// LLView interface
- /*virtual*/ void initFromXML(LLXMLNodePtr node, LLView* parent);
- /*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const;
/*virtual*/ BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
- /*virtual*/ void onFocusReceived();
- /*virtual*/ void onFocusLost();
/*virtual*/ BOOL isCtrl() const;
/*virtual*/ void setTentative(BOOL b);
/*virtual*/ BOOL getTentative() const;
+ /*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask);
+ /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL canFocusChildren() const;
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
// From LLFocusableElement
/*virtual*/ void setFocus( BOOL b );
@@ -97,7 +173,23 @@ public:
virtual class LLCtrlListInterface* getListInterface();
virtual class LLCtrlScrollInterface* getScrollInterface();
+ bool setControlValue(const LLSD& value);
+ void setControlVariable(LLControlVariable* control);
+ virtual void setControlName(const std::string& control, LLView *context = NULL);
+
+ LLControlVariable* getControlVariable() { return mControlVariable; }
+
+ void setEnabledControlVariable(LLControlVariable* control);
+ void setDisabledControlVariable(LLControlVariable* control);
+ void setMakeVisibleControlVariable(LLControlVariable* control);
+ void setMakeInvisibleControlVariable(LLControlVariable* control);
+
+ virtual void setValue(const LLSD& value);
virtual LLSD getValue() const;
+ /// When two widgets are displaying the same data (e.g. during a skin
+ /// change), share their ViewModel.
+ virtual void shareViewModelFrom(const LLUICtrl& other);
+
virtual BOOL setTextArg( const std::string& key, const LLStringExplicit& text );
virtual void setIsChrome(BOOL is_chrome);
@@ -108,17 +200,17 @@ public:
virtual BOOL isDirty() const; // Defauls to false
virtual void resetDirty(); //Defaults to no-op
- // Call appropriate callbacks
- virtual void onLostTop(); // called when registered as top ctrl and user clicks elsewhere
+ // Call appropriate callback
virtual void onCommit();
// Default to no-op:
virtual void onTabInto();
+
+ // Clear any user-provided input (text in a text editor, checked checkbox,
+ // selected radio button, etc.). Defaults to no-op.
virtual void clear();
- virtual void setDoubleClickCallback( void (*cb)(void*) );
+
virtual void setColor(const LLColor4& color);
- virtual void setMinValue(LLSD min_value);
- virtual void setMaxValue(LLSD max_value);
BOOL focusNextItem(BOOL text_entry_only);
BOOL focusPrevItem(BOOL text_entry_only);
@@ -126,6 +218,7 @@ public:
BOOL focusLastItem(BOOL prefer_text_fields = FALSE);
// Non Virtuals
+ LLHandle<LLUICtrl> getUICtrlHandle() const { return mUICtrlHandle; }
BOOL getIsChrome() const;
void setTabStop( BOOL b );
@@ -133,16 +226,28 @@ public:
LLUICtrl* getParentUICtrl() const;
- void* getCallbackUserData() const { return mCallbackUserData; }
- void setCallbackUserData( void* data ) { mCallbackUserData = data; }
+ // return true if help topic found by crawling through parents -
+ // topic then put in help_topic_out
+ bool findHelpTopic(std::string& help_topic_out);
+
+ boost::signals2::connection setCommitCallback( const commit_signal_t::slot_type& cb );
+ boost::signals2::connection setValidateCallback( const enable_signal_t::slot_type& cb );
+
+ boost::signals2::connection setMouseEnterCallback( const commit_signal_t::slot_type& cb );
+ boost::signals2::connection setMouseLeaveCallback( const commit_signal_t::slot_type& cb );
- void setCommitCallback( void (*cb)(LLUICtrl*, void*) ) { mCommitCallback = cb; }
- void setValidateBeforeCommit( BOOL(*cb)(LLUICtrl*, void*) ) { mValidateCallback = cb; }
- void setLostTopCallback( void (*cb)(LLUICtrl*, void*) ) { mLostTopCallback = cb; }
+ boost::signals2::connection setMouseDownCallback( const mouse_signal_t::slot_type& cb );
+ boost::signals2::connection setMouseUpCallback( const mouse_signal_t::slot_type& cb );
+ boost::signals2::connection setRightMouseDownCallback( const mouse_signal_t::slot_type& cb );
+ boost::signals2::connection setRightMouseUpCallback( const mouse_signal_t::slot_type& cb );
- static LLView* fromXML(LLXMLNodePtr node, LLView* parent, class LLUICtrlFactory* factory);
+ boost::signals2::connection setDoubleClickCallback( const mouse_signal_t::slot_type& cb );
+
+ // *TODO: Deprecate; for backwards compatability only:
+ boost::signals2::connection setCommitCallback( boost::function<void (LLUICtrl*,void*)> cb, void* data);
+ boost::signals2::connection setValidateBeforeCommit( boost::function<bool (const LLSD& data)> cb );
- LLUICtrl* findRootMostFocusRoot();
+ LLUICtrl* findRootMostFocusRoot();
class LLTextInputFilter : public LLQueryFilter, public LLSingleton<LLTextInputFilter>
{
@@ -151,22 +256,57 @@ public:
return filterResult_t(view->isCtrl() && static_cast<const LLUICtrl *>(view)->acceptsTextInput(), TRUE);
}
};
+
+ template <typename F, typename DERIVED> class CallbackRegistry : public LLRegistrySingleton<std::string, F, DERIVED >
+ {};
+ class CommitCallbackRegistry : public CallbackRegistry<commit_callback_t, CommitCallbackRegistry>{};
+ // the enable callback registry is also used for visiblity callbacks
+ class EnableCallbackRegistry : public CallbackRegistry<enable_callback_t, EnableCallbackRegistry>{};
+
protected:
- void (*mCommitCallback)( LLUICtrl* ctrl, void* userdata );
- void (*mLostTopCallback)( LLUICtrl* ctrl, void* userdata );
- BOOL (*mValidateCallback)( LLUICtrl* ctrl, void* userdata );
+ static bool controlListener(const LLSD& newvalue, LLHandle<LLUICtrl> handle, std::string type);
+
+ commit_signal_t* mCommitSignal;
+ enable_signal_t* mValidateSignal;
+
+ commit_signal_t* mMouseEnterSignal;
+ commit_signal_t* mMouseLeaveSignal;
+
+ mouse_signal_t* mMouseDownSignal;
+ mouse_signal_t* mMouseUpSignal;
+ mouse_signal_t* mRightMouseDownSignal;
+ mouse_signal_t* mRightMouseUpSignal;
- void* mCallbackUserData;
+ mouse_signal_t* mDoubleClickSignal;
+
+ LLViewModelPtr mViewModel;
+ LLControlVariable* mControlVariable;
+ boost::signals2::connection mControlConnection;
+ LLControlVariable* mEnabledControlVariable;
+ boost::signals2::connection mEnabledControlConnection;
+ LLControlVariable* mDisabledControlVariable;
+ boost::signals2::connection mDisabledControlConnection;
+ LLControlVariable* mMakeVisibleControlVariable;
+ boost::signals2::connection mMakeVisibleControlConnection;
+ LLControlVariable* mMakeInvisibleControlVariable;
+ boost::signals2::connection mMakeInvisibleControlConnection;
private:
BOOL mTabStop;
BOOL mIsChrome;
BOOL mTentative;
+ LLRootHandle<LLUICtrl> mUICtrlHandle;
class DefaultTabGroupFirstSorter;
};
+// Build time optimization, generate once in .cpp file
+#ifndef LLUICTRL_CPP
+extern template class LLUICtrl* LLView::getChild<class LLUICtrl>(
+ const std::string& name, BOOL recurse) const;
+#endif
+
#endif // LL_LLUICTRL_H
diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp
index 983cc53f69..27237800d4 100644
--- a/indra/llui/lluictrlfactory.cpp
+++ b/indra/llui/lluictrlfactory.cpp
@@ -32,8 +32,11 @@
#include "linden_common.h"
+#define LLUICTRLFACTORY_CPP
#include "lluictrlfactory.h"
+#include "llxmlnode.h"
+
#include <fstream>
#include <boost/tokenizer.hpp>
@@ -41,216 +44,199 @@
#include "llcontrol.h"
#include "lldir.h"
#include "v4color.h"
+#include "v3dmath.h"
+#include "llquaternion.h"
// this library includes
-#include "llbutton.h"
-#include "llcheckboxctrl.h"
-//#include "llcolorswatch.h"
-#include "llcombobox.h"
-#include "llcontrol.h"
-#include "lldir.h"
-#include "llevent.h"
#include "llfloater.h"
-#include "lliconctrl.h"
-#include "lllineeditor.h"
-#include "llmenugl.h"
-#include "llradiogroup.h"
-#include "llscrollcontainer.h"
-#include "llscrollingpanellist.h"
-#include "llscrolllistctrl.h"
-#include "llslider.h"
-#include "llsliderctrl.h"
-#include "llmultislider.h"
-#include "llmultisliderctrl.h"
-#include "llspinctrl.h"
-#include "lltabcontainer.h"
-#include "lltabcontainervertical.h"
-#include "lltextbox.h"
-#include "lltexteditor.h"
-#include "llui.h"
-#include "llviewborder.h"
-
-const char XML_HEADER[] = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n";
-
-const S32 HPAD = 4;
-const S32 VPAD = 4;
-const S32 FLOATER_H_MARGIN = 15;
-const S32 MIN_WIDGET_HEIGHT = 10;
-
-std::vector<std::string> LLUICtrlFactory::sXUIPaths;
+
+LLFastTimer::DeclareTimer FTM_WIDGET_CONSTRUCTION("Widget Construction");
+LLFastTimer::DeclareTimer FTM_INIT_FROM_PARAMS("Widget InitFromParams");
+LLFastTimer::DeclareTimer FTM_WIDGET_SETUP("Widget Setup");
+
+//-----------------------------------------------------------------------------
// UI Ctrl class for padding
class LLUICtrlLocate : public LLUICtrl
{
public:
- LLUICtrlLocate() : LLUICtrl(std::string("locate"), LLRect(0,0,0,0), FALSE, NULL, NULL) { setTabStop(FALSE); }
- virtual void draw() { }
-
- static LLView *fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
{
- std::string name("pad");
- node->getAttributeString("name", name);
+ Params()
+ {
+ name = "locate";
+ tab_stop = false;
+ }
+ };
+
+ LLUICtrlLocate(const Params& p) : LLUICtrl(p) {}
+ virtual void draw() { }
- LLUICtrlLocate *new_ctrl = new LLUICtrlLocate();
- new_ctrl->setName(name);
- new_ctrl->initFromXML(node, parent);
- return new_ctrl;
- }
};
-static LLRegisterWidget<LLUICtrlLocate> r1("locate");
-static LLRegisterWidget<LLUICtrlLocate> r2("pad");
+static LLDefaultChildRegistry::Register<LLUICtrlLocate> r1("locate");
+
+// Build time optimization, generate this once in .cpp file
+template class LLUICtrlFactory* LLSingleton<class LLUICtrlFactory>::getInstance();
//-----------------------------------------------------------------------------
// LLUICtrlFactory()
//-----------------------------------------------------------------------------
LLUICtrlFactory::LLUICtrlFactory()
- : mDummyPanel(NULL)
+ : mDummyPanel(NULL) // instantiated when first needed
{
- setupPaths();
}
LLUICtrlFactory::~LLUICtrlFactory()
{
- delete mDummyPanel;
- mDummyPanel = NULL;
+ // go ahead and leak mDummyPanel since this is static destructor time
+ //delete mDummyPanel;
+ //mDummyPanel = NULL;
}
-void LLUICtrlFactory::setupPaths()
+void LLUICtrlFactory::loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block)
{
- std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, "paths.xml");
+ std::string filename = std::string("widgets") + gDirUtilp->getDirDelimiter() + widget_tag + ".xml";
+ LLXMLNodePtr root_node;
- LLXMLNodePtr root;
- BOOL success = LLXMLNode::parseFile(filename, root, NULL);
- sXUIPaths.clear();
-
- if (success)
+ if (LLUICtrlFactory::getLayeredXMLNode(filename, root_node))
{
- LLXMLNodePtr path;
-
- for (path = root->getFirstChild(); path.notNull(); path = path->getNextSibling())
+ LLXUIParser::instance().readXUI(root_node, block, filename);
+ }
+}
+
+static LLFastTimer::DeclareTimer FTM_CREATE_CHILDREN("Create XUI Children");
+
+//static
+void LLUICtrlFactory::createChildren(LLView* viewp, LLXMLNodePtr node, const widget_registry_t& registry, LLXMLNodePtr output_node)
+{
+ LLFastTimer ft(FTM_CREATE_CHILDREN);
+ if (node.isNull()) return;
+
+ for (LLXMLNodePtr child_node = node->getFirstChild(); child_node.notNull(); child_node = child_node->getNextSibling())
+ {
+ LLXMLNodePtr outputChild;
+ if (output_node)
{
- LLUIString path_val_ui(path->getValue());
- std::string language = LLUI::getLanguage();
- path_val_ui.setArg("[LANGUAGE]", language);
+ outputChild = output_node->createChild("", FALSE);
+ }
- if (std::find(sXUIPaths.begin(), sXUIPaths.end(), path_val_ui.getString()) == sXUIPaths.end())
+ if (!instance().createFromXML(child_node, viewp, LLStringUtil::null, registry, outputChild))
+ {
+ // child_node is not a valid child for the current parent
+ std::string child_name = std::string(child_node->getName()->mString);
+ if (LLDefaultChildRegistry::instance().getValue(child_name))
{
- sXUIPaths.push_back(path_val_ui.getString());
+ // This means that the registry assocaited with the parent widget does not have an entry
+ // for the child widget
+ // You might need to add something like:
+ // static ParentWidgetRegistry::Register<ChildWidgetType> register("child_widget_name");
+ llwarns << child_name << " is not a valid child of " << node->getName()->mString << llendl;
+ }
+ else
+ {
+ llwarns << "Could not create widget named " << child_node->getName()->mString << llendl;
}
}
+
+ if (outputChild && !outputChild->mChildren && outputChild->mAttributes.empty() && outputChild->getValue().empty())
+ {
+ output_node->deleteChild(outputChild);
+ }
}
- else // parsing failed
- {
- std::string slash = gDirUtilp->getDirDelimiter();
- std::string dir = "xui" + slash + "en-us";
- llwarns << "XUI::config file unable to open: " << filename << llendl;
- sXUIPaths.push_back(dir);
- }
-}
-// static
-const std::vector<std::string>& LLUICtrlFactory::getXUIPaths()
-{
- return sXUIPaths;
}
+static LLFastTimer::DeclareTimer FTM_XML_PARSE("XML Reading/Parsing");
//-----------------------------------------------------------------------------
// getLayeredXMLNode()
//-----------------------------------------------------------------------------
bool LLUICtrlFactory::getLayeredXMLNode(const std::string &xui_filename, LLXMLNodePtr& root)
{
- std::string full_filename = gDirUtilp->findSkinnedFilename(sXUIPaths.front(), xui_filename);
- if (full_filename.empty())
- {
- llwarns << "Couldn't find UI description file: " << sXUIPaths.front() + gDirUtilp->getDirDelimiter() + xui_filename << llendl;
- return false;
- }
+ LLFastTimer timer(FTM_XML_PARSE);
+ return LLXMLNode::getLayeredXMLNode(xui_filename, root, LLUI::getXUIPaths());
+}
+
+//-----------------------------------------------------------------------------
+// getLocalizedXMLNode()
+//-----------------------------------------------------------------------------
+bool LLUICtrlFactory::getLocalizedXMLNode(const std::string &xui_filename, LLXMLNodePtr& root)
+{
+ LLFastTimer timer(FTM_XML_PARSE);
+ std::string full_filename = gDirUtilp->findSkinnedFilename(LLUI::getLocalizedSkinPath(), xui_filename);
if (!LLXMLNode::parseFile(full_filename, root, NULL))
{
- // try filename as passed in since sometimes we load an xml file from a user-supplied path
- if (!LLXMLNode::parseFile(xui_filename, root, NULL))
- {
- llwarns << "Problem reading UI description file: " << xui_filename << llendl;
- return false;
- }
+ return false;
}
-
- LLXMLNodePtr updateRoot;
-
- std::vector<std::string>::const_iterator itor;
-
- for (itor = sXUIPaths.begin(), ++itor; itor != sXUIPaths.end(); ++itor)
+ else
{
- std::string nodeName;
- std::string updateName;
-
- std::string layer_filename = gDirUtilp->findSkinnedFilename((*itor), xui_filename);
- if(layer_filename.empty())
- {
- // no localized version of this file, that's ok, keep looking
- continue;
- }
-
- if (!LLXMLNode::parseFile(layer_filename, updateRoot, NULL))
- {
- llwarns << "Problem reading localized UI description file: " << (*itor) + gDirUtilp->getDirDelimiter() + xui_filename << llendl;
- return false;
- }
-
- updateRoot->getAttributeString("name", updateName);
- root->getAttributeString("name", nodeName);
-
- if (updateName == nodeName)
- {
- LLXMLNode::updateNode(root, updateRoot);
- }
+ return true;
}
-
- return true;
}
+static LLFastTimer::DeclareTimer FTM_BUILD_FLOATERS("Build Floaters");
//-----------------------------------------------------------------------------
// buildFloater()
//-----------------------------------------------------------------------------
-void LLUICtrlFactory::buildFloater(LLFloater* floaterp, const std::string& filename,
- const LLCallbackMap::map_t* factory_map, BOOL open) /* Flawfinder: ignore */
+bool LLUICtrlFactory::buildFloater(LLFloater* floaterp, const std::string& filename, LLXMLNodePtr output_node)
{
+ LLFastTimer timer(FTM_BUILD_FLOATERS);
LLXMLNodePtr root;
- if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
+ //if exporting, only load the language being exported,
+ //instead of layering localized version on top of english
+ if (output_node)
+ {
+ if (!LLUICtrlFactory::getLocalizedXMLNode(filename, root))
+ {
+ llwarns << "Couldn't parse floater from: " << LLUI::getLocalizedSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl;
+ return false;
+ }
+ }
+ else if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
{
- return;
+ llwarns << "Couldn't parse floater from: " << LLUI::getSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl;
+ return false;
}
// root must be called floater
- if( !(root->hasName("floater") || root->hasName("multi_floater") ) )
+ if( !(root->hasName("floater") || root->hasName("multi_floater")) )
{
llwarns << "Root node should be named floater in: " << filename << llendl;
- return;
- }
-
- if (factory_map)
- {
- mFactoryStack.push_front(factory_map);
+ return false;
}
-
- floaterp->initFloaterXML(root, NULL, this, open); /* Flawfinder: ignore */
-
- if (LLUI::sShowXUINames)
+
+ bool res = true;
+
+ lldebugs << "Building floater " << filename << llendl;
+ mFileNames.push_back(gDirUtilp->findSkinnedFilename(LLUI::getSkinPath(), filename));
{
- floaterp->setToolTip(filename);
- }
+ if (!floaterp->getFactoryMap().empty())
+ {
+ mFactoryStack.push_front(&floaterp->getFactoryMap());
+ }
- if (factory_map)
- {
- mFactoryStack.pop_front();
+ // for local registry callbacks; define in constructor, referenced in XUI or postBuild
+ floaterp->getCommitCallbackRegistrar().pushScope();
+ floaterp->getEnableCallbackRegistrar().pushScope();
+
+ res = floaterp->initFloaterXML(root, floaterp->getParent(), output_node);
+
+ floaterp->setXMLFilename(filename);
+
+ floaterp->getCommitCallbackRegistrar().popScope();
+ floaterp->getEnableCallbackRegistrar().popScope();
+
+ if (!floaterp->getFactoryMap().empty())
+ {
+ mFactoryStack.pop_front();
+ }
}
-
- LLHandle<LLFloater> handle = floaterp->getHandle();
- mBuiltFloaters[handle] = filename;
+ mFileNames.pop_back();
+
+ return res;
}
//-----------------------------------------------------------------------------
@@ -258,34 +244,33 @@ void LLUICtrlFactory::buildFloater(LLFloater* floaterp, const std::string& filen
//-----------------------------------------------------------------------------
S32 LLUICtrlFactory::saveToXML(LLView* viewp, const std::string& filename)
{
- llofstream out(filename);
- if (!out.good())
- {
- llwarns << "Unable to open " << filename << " for output." << llendl;
- return 1;
- }
-
- out << XML_HEADER;
-
- LLXMLNodePtr xml_node = viewp->getXML();
-
- xml_node->writeToOstream(out);
-
- out.close();
return 0;
}
+static LLFastTimer::DeclareTimer FTM_BUILD_PANELS("Build Panels");
+
//-----------------------------------------------------------------------------
// buildPanel()
//-----------------------------------------------------------------------------
-BOOL LLUICtrlFactory::buildPanel(LLPanel* panelp, const std::string& filename,
- const LLCallbackMap::map_t* factory_map)
+BOOL LLUICtrlFactory::buildPanel(LLPanel* panelp, const std::string& filename, LLXMLNodePtr output_node)
{
+ LLFastTimer timer(FTM_BUILD_PANELS);
BOOL didPost = FALSE;
LLXMLNodePtr root;
- if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
+ //if exporting, only load the language being exported,
+ //instead of layering localized version on top of english
+ if (output_node)
+ {
+ if (!LLUICtrlFactory::getLocalizedXMLNode(filename, root))
+ {
+ llwarns << "Couldn't parse panel from: " << LLUI::getLocalizedSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl;
+ return didPost;
+ }
+ }
+ else if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
{
+ llwarns << "Couldn't parse panel from: " << LLUI::getSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl;
return didPost;
}
@@ -296,167 +281,49 @@ BOOL LLUICtrlFactory::buildPanel(LLPanel* panelp, const std::string& filename,
return didPost;
}
- if (factory_map)
- {
- mFactoryStack.push_front(factory_map);
- }
-
- didPost = panelp->initPanelXML(root, NULL, this);
-
- if (LLUI::sShowXUINames)
- {
- panelp->setToolTip(filename);
- }
-
- LLHandle<LLPanel> handle = panelp->getHandle();
- mBuiltPanels[handle] = filename;
-
- if (factory_map)
- {
- mFactoryStack.pop_front();
- }
-
- return didPost;
-}
-
-//-----------------------------------------------------------------------------
-// buildMenu()
-//-----------------------------------------------------------------------------
-LLMenuGL *LLUICtrlFactory::buildMenu(const std::string &filename, LLView* parentp)
-{
- // TomY TODO: Break this function into buildMenu and buildMenuBar
- LLXMLNodePtr root;
- LLMenuGL* menu;
-
- if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
- {
- return NULL;
- }
-
- // root must be called panel
- if( !root->hasName( "menu_bar" ) && !root->hasName( "menu" ))
- {
- llwarns << "Root node should be named menu bar or menu in : " << filename << llendl;
- return NULL;
- }
-
- if (root->hasName("menu"))
- {
- menu = (LLMenuGL*)LLMenuGL::fromXML(root, parentp, this);
- }
- else
- {
- menu = (LLMenuGL*)LLMenuBarGL::fromXML(root, parentp, this);
- }
-
- if (LLUI::sShowXUINames)
- {
- menu->setToolTip(filename);
- }
-
- return menu;
-}
-
-//-----------------------------------------------------------------------------
-// buildMenu()
-//-----------------------------------------------------------------------------
-LLPieMenu *LLUICtrlFactory::buildPieMenu(const std::string &filename, LLView* parentp)
-{
- LLXMLNodePtr root;
-
- if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
- {
- return NULL;
- }
-
- // root must be called panel
- if( !root->hasName( LL_PIE_MENU_TAG ))
- {
- llwarns << "Root node should be named " << LL_PIE_MENU_TAG << " in : " << filename << llendl;
- return NULL;
- }
-
- std::string name("menu");
- root->getAttributeString("name", name);
-
- LLPieMenu *menu = new LLPieMenu(name);
- parentp->addChild(menu);
- menu->initXML(root, parentp, this);
-
- if (LLUI::sShowXUINames)
- {
- menu->setToolTip(filename);
- }
-
- return menu;
-}
+ lldebugs << "Building panel " << filename << llendl;
-//-----------------------------------------------------------------------------
-// rebuild()
-//-----------------------------------------------------------------------------
-void LLUICtrlFactory::rebuild()
-{
- built_panel_t::iterator built_panel_it;
- for (built_panel_it = mBuiltPanels.begin();
- built_panel_it != mBuiltPanels.end();
- ++built_panel_it)
+ mFileNames.push_back(gDirUtilp->findSkinnedFilename(LLUI::getSkinPath(), filename));
{
- std::string filename = built_panel_it->second;
- LLPanel* panelp = built_panel_it->first.get();
- if (!panelp)
+ if (!panelp->getFactoryMap().empty())
{
- continue;
+ mFactoryStack.push_front(&panelp->getFactoryMap());
}
- llinfos << "Rebuilding UI panel " << panelp->getName()
- << " from " << filename
- << llendl;
- BOOL visible = panelp->getVisible();
- panelp->setVisible(FALSE);
- panelp->setFocus(FALSE);
- panelp->deleteAllChildren();
-
- buildPanel(panelp, filename.c_str(), &panelp->getFactoryMap());
- panelp->setVisible(visible);
- }
-
- built_floater_t::iterator built_floater_it;
- for (built_floater_it = mBuiltFloaters.begin();
- built_floater_it != mBuiltFloaters.end();
- ++built_floater_it)
- {
- LLFloater* floaterp = built_floater_it->first.get();
- if (!floaterp)
+
+ // for local registry callbacks; define in constructor, referenced in XUI or postBuild
+ panelp->getCommitCallbackRegistrar().pushScope();
+ panelp->getEnableCallbackRegistrar().pushScope();
+
+ didPost = panelp->initPanelXML(root, NULL, output_node);
+
+ panelp->getCommitCallbackRegistrar().popScope();
+ panelp->getEnableCallbackRegistrar().popScope();
+
+ panelp->setXMLFilename(filename);
+
+ if (!panelp->getFactoryMap().empty())
{
- continue;
+ mFactoryStack.pop_front();
}
- std::string filename = built_floater_it->second;
- llinfos << "Rebuilding UI floater " << floaterp->getName()
- << " from " << filename
- << llendl;
- BOOL visible = floaterp->getVisible();
- floaterp->setVisible(FALSE);
- floaterp->setFocus(FALSE);
- floaterp->deleteAllChildren();
-
- gFloaterView->removeChild(floaterp);
- buildFloater(floaterp, filename, &floaterp->getFactoryMap());
- floaterp->setVisible(visible);
}
+ mFileNames.pop_back();
+ return didPost;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
-LLView *LLUICtrlFactory::createCtrlWidget(LLPanel *parent, LLXMLNodePtr node)
+static LLFastTimer::DeclareTimer FTM_CREATE_FROM_XML("Create child widget");
+
+LLView *LLUICtrlFactory::createFromXML(LLXMLNodePtr node, LLView* parent, const std::string& filename, const widget_registry_t& registry, LLXMLNodePtr output_node)
{
+ LLFastTimer timer(FTM_CREATE_FROM_XML);
std::string ctrl_type = node->getName()->mString;
LLStringUtil::toLower(ctrl_type);
-
- LLWidgetClassRegistry::factory_func_t func = LLWidgetClassRegistry::getInstance()->getCreatorFunc(ctrl_type);
- if (func == NULL)
+ const LLWidgetCreatorFunc* funcp = registry.getValue(ctrl_type);
+ if (funcp == NULL)
{
- llwarns << "Unknown control type " << ctrl_type << llendl;
return NULL;
}
@@ -464,27 +331,13 @@ LLView *LLUICtrlFactory::createCtrlWidget(LLPanel *parent, LLXMLNodePtr node)
{
if (mDummyPanel == NULL)
{
- mDummyPanel = new LLPanel;
+ LLPanel::Params p;
+ mDummyPanel = create<LLPanel>(p);
}
parent = mDummyPanel;
}
- LLView *ctrl = func(node, parent, this);
-
- return ctrl;
-}
-
-LLView* LLUICtrlFactory::createWidget(LLPanel *parent, LLXMLNodePtr node)
-{
- LLView* view = createCtrlWidget(parent, node);
-
- S32 tab_group = parent->getLastTabGroup();
- node->getAttributeS32("tab_group", tab_group);
-
- if (view)
- {
- parent->addChild(view, tab_group);
- }
-
+ LLView *view = (*funcp)(node, parent, output_node);
+
return view;
}
@@ -507,7 +360,8 @@ LLPanel* LLUICtrlFactory::createFactoryPanel(const std::string& name)
return ret;
}
}
- return NULL;
+ LLPanel::Params panel_p;
+ return create<LLPanel>(panel_p);
}
//-----------------------------------------------------------------------------
@@ -517,11 +371,11 @@ BOOL LLUICtrlFactory::getAttributeColor(LLXMLNodePtr node, const std::string& na
{
std::string colorstring;
BOOL res = node->getAttributeString(name.c_str(), colorstring);
- if (res && LLUI::sColorsGroup)
+ if (res)
{
- if (LLUI::sColorsGroup->controlExists(colorstring))
+ if (LLUIColorTable::instance().colorExists(colorstring))
{
- color.setVec(LLUI::sColorsGroup->getColor(colorstring));
+ color.setVec(LLUIColorTable::instance().getColor(colorstring));
}
else
{
@@ -539,3 +393,67 @@ BOOL LLUICtrlFactory::getAttributeColor(LLXMLNodePtr node, const std::string& na
return res;
}
+//static
+void LLUICtrlFactory::setCtrlParent(LLView* view, LLView* parent, S32 tab_group)
+{
+ if (tab_group == S32_MAX) tab_group = parent->getLastTabGroup();
+ parent->addChild(view, tab_group);
+}
+
+
+// Avoid directly using LLUI and LLDir in the template code
+//static
+std::string LLUICtrlFactory::findSkinnedFilename(const std::string& filename)
+{
+ return gDirUtilp->findSkinnedFilename(LLUI::getSkinPath(), filename);
+}
+
+void LLUICtrlFactory::pushFactoryFunctions(const LLCallbackMap::map_t* map)
+{
+ mFactoryStack.push_back(map);
+}
+
+void LLUICtrlFactory::popFactoryFunctions()
+{
+ if (!mFactoryStack.empty())
+ {
+ mFactoryStack.pop_back();
+ }
+}
+
+//static
+void LLUICtrlFactory::copyName(LLXMLNodePtr src, LLXMLNodePtr dest)
+{
+ dest->setName(src->getName()->mString);
+}
+
+// adds a widget and its param block to various registries
+//static
+void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, dummy_widget_creator_func_t creator_func, const std::string& tag)
+{
+ // associate parameter block type with template .xml file
+ std::string* existing_tag = LLWidgetNameRegistry::instance().getValue(param_block_type);
+ if (existing_tag != NULL && *existing_tag != tag)
+ {
+ llerrs << "Duplicate entry for T::Params, try creating empty param block in derived classes that inherit T::Params" << llendl;
+ }
+ LLWidgetNameRegistry ::instance().defaultRegistrar().add(param_block_type, tag);
+ // associate widget type with factory function
+ LLDefaultWidgetRegistry::instance().defaultRegistrar().add(widget_type, creator_func);
+ //FIXME: comment this in when working on schema generation
+ //LLWidgetTypeRegistry::instance().defaultRegistrar().add(tag, widget_type);
+ //LLDefaultParamBlockRegistry::instance().defaultRegistrar().add(widget_type, &getEmptyParamBlock<T>);
+}
+
+//static
+dummy_widget_creator_func_t* LLUICtrlFactory::getDefaultWidgetFunc(const std::type_info* widget_type)
+{
+ return LLDefaultWidgetRegistry::instance().getValue(widget_type);
+}
+
+//static
+const std::string* LLUICtrlFactory::getWidgetTag(const std::type_info* widget_type)
+{
+ return LLWidgetNameRegistry::instance().getValue(widget_type);
+}
+
diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h
index 5e7c24efc0..b1fa6add67 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -33,68 +33,400 @@
#ifndef LLUICTRLFACTORY_H
#define LLUICTRLFACTORY_H
+#include "llcallbackmap.h"
+#include "llinitparam.h"
+#include "llregistry.h"
+#include "v4color.h"
+#include "llfasttimer.h"
+
+#include "llxuiparser.h"
+
+#include <boost/function.hpp>
#include <iosfwd>
#include <stack>
+#include <set>
-#include "llcallbackmap.h"
-#include "llfloater.h"
-
-class LLView;
class LLPanel;
+class LLFloater;
+class LLView;
-class LLUICtrlFactory : public LLSingleton<LLUICtrlFactory>
+
+// sort functor for typeid maps
+struct LLCompareTypeID
+{
+ bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
+ {
+ return lhs->before(*rhs);
+ }
+};
+
+// lookup widget constructor funcs by widget name
+template <typename DERIVED_TYPE>
+class LLChildRegistry : public LLRegistrySingleton<std::string, LLWidgetCreatorFunc, DERIVED_TYPE>
{
public:
+ typedef LLRegistrySingleton<std::string, LLWidgetCreatorFunc, DERIVED_TYPE> super_t;
+ // local static instance for registering a particular widget
+ template<typename T>
+ class Register : public super_t::StaticRegistrar
+ {
+ public:
+ // register with either the provided builder, or the generic templated builder
+ Register(const char* tag, LLWidgetCreatorFunc func = NULL);
+ };
+
+protected:
+ LLChildRegistry() {}
+};
+
+class LLDefaultChildRegistry : public LLChildRegistry<LLDefaultChildRegistry>
+{
+protected:
+ LLDefaultChildRegistry(){}
+ friend class LLSingleton<LLDefaultChildRegistry>;
+};
+
+// lookup widget name by type
+class LLWidgetNameRegistry
+: public LLRegistrySingleton<const std::type_info*, std::string, LLWidgetNameRegistry , LLCompareTypeID>
+{};
+
+// lookup factory functions for default widget instances by widget type
+typedef LLView* (*dummy_widget_creator_func_t)(const std::string&);
+class LLDefaultWidgetRegistry
+: public LLRegistrySingleton<const std::type_info*, dummy_widget_creator_func_t, LLDefaultWidgetRegistry, LLCompareTypeID>
+{};
+
+// lookup function for generating empty param block by widget type
+// this is used for schema generation
+//typedef const LLInitParam::BaseBlock& (*empty_param_block_func_t)();
+//class LLDefaultParamBlockRegistry
+//: public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry, LLCompareTypeID>
+//{};
+
+extern LLFastTimer::DeclareTimer FTM_WIDGET_SETUP;
+extern LLFastTimer::DeclareTimer FTM_WIDGET_CONSTRUCTION;
+extern LLFastTimer::DeclareTimer FTM_INIT_FROM_PARAMS;
+
+// Build time optimization, generate this once in .cpp file
+#ifndef LLUICTRLFACTORY_CPP
+extern template class LLUICtrlFactory* LLSingleton<class LLUICtrlFactory>::getInstance();
+#endif
+
+class LLUICtrlFactory : public LLSingleton<LLUICtrlFactory>
+{
+private:
+ friend class LLSingleton<LLUICtrlFactory>;
LLUICtrlFactory();
- // do not call! needs to be public so run-time can clean up the singleton
- virtual ~LLUICtrlFactory();
+ ~LLUICtrlFactory();
+
+ // only partial specialization allowed in inner classes, so use extra dummy parameter
+ template <typename PARAM_BLOCK, int DUMMY>
+ class ParamDefaults : public LLSingleton<ParamDefaults<PARAM_BLOCK, DUMMY> >
+ {
+ public:
+ ParamDefaults()
+ {
+ // recursively initialize from base class param block
+ ((typename PARAM_BLOCK::base_block_t&)mPrototype).fillFrom(ParamDefaults<typename PARAM_BLOCK::base_block_t, DUMMY>::instance().get());
+ // after initializing base classes, look up template file for this param block
+ const std::string* param_block_tag = getWidgetTag(&typeid(PARAM_BLOCK));
+ if (param_block_tag)
+ {
+ LLUICtrlFactory::loadWidgetTemplate(*param_block_tag, mPrototype);
+ }
+ }
+
+ const PARAM_BLOCK& get() { return mPrototype; }
- void setupPaths();
+ private:
+ PARAM_BLOCK mPrototype;
+ };
- void buildFloater(LLFloater* floaterp, const std::string &filename,
- const LLCallbackMap::map_t* factory_map = NULL, BOOL open = TRUE);
- BOOL buildPanel(LLPanel* panelp, const std::string &filename,
- const LLCallbackMap::map_t* factory_map = NULL);
+ // base case for recursion, there are NO base classes of LLInitParam::BaseBlock
+ template<int DUMMY>
+ class ParamDefaults<LLInitParam::BaseBlock, DUMMY> : public LLSingleton<ParamDefaults<LLInitParam::BaseBlock, DUMMY> >
+ {
+ public:
+ const LLInitParam::BaseBlock& get() { return mBaseBlock; }
+ private:
+ LLInitParam::BaseBlock mBaseBlock;
+ };
+
+public:
- void removePanel(LLPanel* panelp) { mBuiltPanels.erase(panelp->getHandle()); }
- void removeFloater(LLFloater* floaterp) { mBuiltFloaters.erase(floaterp->getHandle()); }
+ // get default parameter block for widget of a specific type
+ template<typename T>
+ static const typename T::Params& getDefaultParams()
+ {
+ //#pragma message("Generating ParamDefaults")
+ return ParamDefaults<typename T::Params, 0>::instance().get();
+ }
- class LLMenuGL *buildMenu(const std::string &filename, LLView* parentp);
- class LLPieMenu *buildPieMenu(const std::string &filename, LLView* parentp);
+ bool buildFloater(LLFloater* floaterp, const std::string &filename, LLXMLNodePtr output_node);
+ BOOL buildPanel(LLPanel* panelp, const std::string &filename, LLXMLNodePtr output_node = NULL);
// Does what you want for LLFloaters and LLPanels
// Returns 0 on success
S32 saveToXML(LLView* viewp, const std::string& filename);
- // Rebuilds all currently built panels.
- void rebuild();
+ std::string getCurFileName() { return mFileNames.empty() ? "" : mFileNames.back(); }
static BOOL getAttributeColor(LLXMLNodePtr node, const std::string& name, LLColor4& color);
LLPanel* createFactoryPanel(const std::string& name);
- virtual LLView* createCtrlWidget(LLPanel *parent, LLXMLNodePtr node);
- virtual LLView* createWidget(LLPanel *parent, LLXMLNodePtr node);
+ void pushFactoryFunctions(const LLCallbackMap::map_t* map);
+ void popFactoryFunctions();
+
+ template<typename T>
+ static T* createWidget(typename T::Params& params, LLView* parent = NULL)
+ {
+ T* widget = NULL;
+
+ if (!params.validateBlock())
+ {
+ llwarns << getInstance()->getCurFileName() << ": Invalid parameter block for " << typeid(T).name() << llendl;
+ //return NULL;
+ }
+
+ {
+ LLFastTimer timer(FTM_WIDGET_CONSTRUCTION);
+ widget = new T(params);
+ }
+ {
+ LLFastTimer timer(FTM_INIT_FROM_PARAMS);
+ widget->initFromParams(params);
+ }
+
+ if (parent)
+ {
+ S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : S32_MAX;
+ setCtrlParent(widget, parent, tab_group);
+ }
+ return widget;
+ }
+
+ template<typename T>
+ static T* create(typename T::Params& params, LLView* parent = NULL)
+ {
+ params.fillFrom(ParamDefaults<typename T::Params, 0>::instance().get());
+
+ T* widget = createWidget<T>(params, parent);
+ if (widget)
+ {
+ widget->postBuild();
+ }
+
+ return widget;
+ }
+
+ LLView* createFromXML(LLXMLNodePtr node, LLView* parent, const std::string& filename, const widget_registry_t&, LLXMLNodePtr output_node );
+
+ template<typename T>
+ static T* createFromFile(const std::string &filename, LLView *parent, const widget_registry_t& registry, LLXMLNodePtr output_node = NULL)
+ {
+ T* widget = NULL;
+
+ std::string skinned_filename = findSkinnedFilename(filename);
+ getInstance()->mFileNames.push_back(skinned_filename);
+ {
+ LLXMLNodePtr root_node;
+
+ //if exporting, only load the language being exported,
+ //instead of layering localized version on top of english
+ if (output_node)
+ {
+ if (!LLUICtrlFactory::getLocalizedXMLNode(filename, root_node))
+ {
+ llwarns << "Couldn't parse XUI file: " << filename << llendl;
+ goto fail;
+ }
+ }
+ else if (!LLUICtrlFactory::getLayeredXMLNode(filename, root_node))
+ {
+ llwarns << "Couldn't parse XUI file: " << skinned_filename << llendl;
+ goto fail;
+ }
+
+ LLView* view = getInstance()->createFromXML(root_node, parent, filename, registry, output_node);
+ if (view)
+ {
+ widget = dynamic_cast<T*>(view);
+ // not of right type, so delete it
+ if (!widget)
+ {
+ delete view;
+ view = NULL;
+ }
+
+ }
+ }
+fail:
+ getInstance()->mFileNames.pop_back();
+ return widget;
+ }
+
+ template<class T>
+ static T* getDefaultWidget(const std::string& name)
+ {
+ dummy_widget_creator_func_t* dummy_func = getDefaultWidgetFunc(&typeid(T));
+ return dummy_func ? dynamic_cast<T*>((*dummy_func)(name)) : NULL;
+ }
+
+ template <class T>
+ static LLView* createDefaultWidget(const std::string& name)
+ {
+ typename T::Params params;
+ params.name(name);
+
+ return create<T>(params);
+ }
+
+ static void copyName(LLXMLNodePtr src, LLXMLNodePtr dest);
+
+ template<typename T>
+ static T* defaultBuilder(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)
+ {
+ LLFastTimer timer(FTM_WIDGET_SETUP);
+
+ typename T::Params params(getDefaultParams<T>());
+
+ LLXUIParser::instance().readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
+
+ if (output_node)
+ {
+ // We always want to output top-left coordinates
+ typename T::Params output_params(params);
+ T::setupParamsForExport(output_params, parent);
+ // Export only the differences between this any default params
+ typename T::Params default_params(getDefaultParams<T>());
+ copyName(node, output_node);
+ LLXUIParser::instance().writeXUI(
+ output_node, output_params, &default_params);
+ }
+
+ // Apply layout transformations, usually munging rect
+ params.from_xui = true;
+ T::applyXUILayout(params, parent);
+ T* widget = createWidget<T>(params, parent);
+
+ typedef typename T::child_registry_t registry_t;
+
+ createChildren(widget, node, registry_t::instance(), output_node);
+
+ if (widget && !widget->postBuild())
+ {
+ delete widget;
+ widget = NULL;
+ }
+
+ return widget;
+ }
+
+ static void createChildren(LLView* viewp, LLXMLNodePtr node, const widget_registry_t&, LLXMLNodePtr output_node = NULL);
static bool getLayeredXMLNode(const std::string &filename, LLXMLNodePtr& root);
+
+ static bool getLocalizedXMLNode(const std::string &xui_filename, LLXMLNodePtr& root);
- static const std::vector<std::string>& getXUIPaths();
+ static void loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block);
+
+ // helper function for adding widget type info to various registries
+ static void registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, dummy_widget_creator_func_t creator_func, const std::string& tag);
private:
- bool getLayeredXMLNodeImpl(const std::string &filename, LLXMLNodePtr& root);
+ // return default widget instance factory func for a given type
+ static dummy_widget_creator_func_t* getDefaultWidgetFunc(const std::type_info* widget_type);
+
+ static const std::string* getWidgetTag(const std::type_info* widget_type);
+
+ // this exists to get around dependency on llview
+ static void setCtrlParent(LLView* view, LLView* parent, S32 tab_group);
+
+ // Avoid directly using LLUI and LLDir in the template code
+ static std::string findSkinnedFilename(const std::string& filename);
- typedef std::map<LLHandle<LLPanel>, std::string> built_panel_t;
- built_panel_t mBuiltPanels;
+ typedef std::deque<const LLCallbackMap::map_t*> factory_stack_t;
+ factory_stack_t mFactoryStack;
- typedef std::map<LLHandle<LLFloater>, std::string> built_floater_t;
- built_floater_t mBuiltFloaters;
+ LLPanel* mDummyPanel;
+ std::vector<std::string> mFileNames;
+};
+
+template<typename T>
+const LLInitParam::BaseBlock& getEmptyParamBlock()
+{
+ static typename T::Params params;
+ return params;
+}
+
+// this is here to make gcc happy with reference to LLUICtrlFactory
+template<typename DERIVED>
+template<typename T>
+LLChildRegistry<DERIVED>::Register<T>::Register(const char* tag, LLWidgetCreatorFunc func)
+: LLChildRegistry<DERIVED>::StaticRegistrar(tag, func.empty() ? (LLWidgetCreatorFunc)&LLUICtrlFactory::defaultBuilder<T> : func)
+{
+ // add this widget to various registries
+ LLUICtrlFactory::instance().registerWidget(&typeid(T), &typeid(typename T::Params), &LLUICtrlFactory::createDefaultWidget<T>, tag);
+
+ // since registry_t depends on T, do this in line here
+ typedef typename T::child_registry_t registry_t;
+ LLChildRegistryRegistry::instance().defaultRegistrar().add(&typeid(T), registry_t::instance());
+}
- std::deque<const LLCallbackMap::map_t*> mFactoryStack;
- static std::vector<std::string> sXUIPaths;
+typedef boost::function<LLPanel* (void)> LLPanelClassCreatorFunc;
+
+// local static instance for registering a particular panel class
+
+class LLRegisterPanelClass
+: public LLSingleton< LLRegisterPanelClass >
+{
+public:
+ // reigister with either the provided builder, or the generic templated builder
+ void addPanelClass(const std::string& tag,LLPanelClassCreatorFunc func)
+ {
+ mPanelClassesNames[tag] = func;
+ }
+
+ LLPanel* createPanelClass(const std::string& tag)
+ {
+ param_name_map_t::iterator iT = mPanelClassesNames.find(tag);
+ if(iT == mPanelClassesNames.end())
+ return 0;
+ return iT->second();
+ }
+ template<typename T>
+ static T* defaultPanelClassBuilder()
+ {
+ T* pT = new T();
+ return pT;
+ }
- LLPanel* mDummyPanel;
+private:
+ typedef std::map< std::string, LLPanelClassCreatorFunc> param_name_map_t;
+
+ param_name_map_t mPanelClassesNames;
};
+// local static instance for registering a particular panel class
+template<typename T>
+class LLRegisterPanelClassWrapper
+: public LLRegisterPanelClass
+{
+public:
+ // reigister with either the provided builder, or the generic templated builder
+ LLRegisterPanelClassWrapper(const std::string& tag);
+};
+
+
+template<typename T>
+LLRegisterPanelClassWrapper<T>::LLRegisterPanelClassWrapper(const std::string& tag)
+{
+ LLRegisterPanelClass::instance().addPanelClass(tag,&LLRegisterPanelClass::defaultPanelClassBuilder<T>);
+}
+
+
#endif //LLUICTRLFACTORY_H
diff --git a/indra/llui/lluifwd.h b/indra/llui/lluifwd.h
index 32d5c9b44f..f99bb39fdd 100644
--- a/indra/llui/lluifwd.h
+++ b/indra/llui/lluifwd.h
@@ -53,7 +53,6 @@ class LLSlider;
class LLSliderCtrl;
class LLSpinCtrl;
class LLTabContainer;
-class LLTabContainerVertical;
class LLTextBox;
class LLTextEditor;
class LLTextureCtrl;
diff --git a/indra/llui/lluiimage.cpp b/indra/llui/lluiimage.cpp
new file mode 100644
index 0000000000..966d919dc7
--- /dev/null
+++ b/indra/llui/lluiimage.cpp
@@ -0,0 +1,205 @@
+/**
+ * @file lluiimage.cpp
+ * @brief UI implementation
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Utilities functions the user interface needs
+
+//#include "llviewerprecompiledheaders.h"
+#include "linden_common.h"
+
+// Project includes
+#include "lluiimage.h"
+#include "llui.h"
+
+LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image)
+: mName(name),
+ mImage(image),
+ mScaleRegion(0.f, 1.f, 1.f, 0.f),
+ mClipRegion(0.f, 1.f, 1.f, 0.f),
+ mUniformScaling(TRUE),
+ mNoClip(TRUE),
+ mImageLoaded(NULL)
+{
+}
+
+LLUIImage::~LLUIImage()
+{
+ delete mImageLoaded;
+}
+
+void LLUIImage::setClipRegion(const LLRectf& region)
+{
+ mClipRegion = region;
+ mNoClip = mClipRegion.mLeft == 0.f
+ && mClipRegion.mRight == 1.f
+ && mClipRegion.mBottom == 0.f
+ && mClipRegion.mTop == 1.f;
+}
+
+void LLUIImage::setScaleRegion(const LLRectf& region)
+{
+ mScaleRegion = region;
+ mUniformScaling = mScaleRegion.mLeft == 0.f
+ && mScaleRegion.mRight == 1.f
+ && mScaleRegion.mBottom == 0.f
+ && mScaleRegion.mTop == 1.f;
+}
+
+//TODO: move drawing implementation inside class
+void LLUIImage::draw(S32 x, S32 y, const LLColor4& color) const
+{
+ gl_draw_scaled_image(x, y, getWidth(), getHeight(), mImage, color, mClipRegion);
+}
+
+void LLUIImage::draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const
+{
+ if (mUniformScaling)
+ {
+ gl_draw_scaled_image(x, y, width, height, mImage, color, mClipRegion);
+ }
+ else
+ {
+ gl_draw_scaled_image_with_border(
+ x, y,
+ width, height,
+ mImage,
+ color,
+ FALSE,
+ mClipRegion,
+ mScaleRegion);
+ }
+}
+
+void LLUIImage::drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const
+{
+ gl_draw_scaled_image_with_border(
+ x, y,
+ width, height,
+ mImage,
+ color,
+ TRUE,
+ mClipRegion,
+ mScaleRegion);
+}
+
+void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const
+{
+ LLRect border_rect;
+ border_rect.setOriginAndSize(x, y, width, height);
+ border_rect.stretch(border_width, border_width);
+ drawSolid(border_rect, color);
+}
+
+S32 LLUIImage::getWidth() const
+{
+ // return clipped dimensions of actual image area
+ return llround((F32)mImage->getWidth(0) * mClipRegion.getWidth());
+}
+
+S32 LLUIImage::getHeight() const
+{
+ // return clipped dimensions of actual image area
+ return llround((F32)mImage->getHeight(0) * mClipRegion.getHeight());
+}
+
+S32 LLUIImage::getTextureWidth() const
+{
+ return mImage->getWidth(0);
+}
+
+S32 LLUIImage::getTextureHeight() const
+{
+ return mImage->getHeight(0);
+}
+
+boost::signals2::connection LLUIImage::addLoadedCallback( const image_loaded_signal_t::slot_type& cb )
+{
+ if (!mImageLoaded)
+ {
+ mImageLoaded = new image_loaded_signal_t();
+ }
+ return mImageLoaded->connect(cb);
+}
+
+
+void LLUIImage::onImageLoaded()
+{
+ if (mImageLoaded)
+ {
+ (*mImageLoaded)();
+ }
+}
+
+
+namespace LLInitParam
+{
+ void TypedParam<LLUIImage*>::setValueFromBlock() const
+ {
+ // The keyword "none" is specifically requesting a null image
+ // do not default to current value. Used to overwrite template images.
+ if (name() == "none")
+ {
+ mData.mValue = NULL;
+ return;
+ }
+
+ LLUIImage* imagep = LLUI::getUIImage(name());
+ if (imagep)
+ {
+ mData.mValue = imagep;
+ }
+ }
+
+ void TypedParam<LLUIImage*>::setBlockFromValue()
+ {
+ if (mData.mValue == NULL)
+ {
+ name = "none";
+ }
+ else
+ {
+ name = mData.mValue->getName();
+ }
+ }
+
+
+ bool ParamCompare<LLUIImage*, false>::equals(
+ LLUIImage* const &a,
+ LLUIImage* const &b)
+ {
+ // force all LLUIImages for XML UI export to be "non-default"
+ if (!a && !b)
+ return false;
+ else
+ return (a == b);
+ }
+}
+
diff --git a/indra/llui/lluiimage.h b/indra/llui/lluiimage.h
new file mode 100644
index 0000000000..bdfc44262d
--- /dev/null
+++ b/indra/llui/lluiimage.h
@@ -0,0 +1,128 @@
+/**
+ * @file lluiimage.h
+ * @brief wrapper for images used in the UI that handles smart scaling, etc.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLUIIMAGE_H
+#define LL_LLUIIMAGE_H
+
+#include "v4color.h"
+#include "llpointer.h"
+#include "llrefcount.h"
+#include "llrefcount.h"
+#include "llrect.h"
+#include <boost/function.hpp>
+#include <boost/signals2.hpp>
+#include "llinitparam.h"
+#include "lltexture.h"
+
+extern const LLColor4 UI_VERTEX_COLOR;
+
+class LLUIImage : public LLRefCount
+{
+public:
+ typedef boost::signals2::signal<void (void)> image_loaded_signal_t;
+
+ LLUIImage(const std::string& name, LLPointer<LLTexture> image);
+ virtual ~LLUIImage();
+
+ void setClipRegion(const LLRectf& region);
+ void setScaleRegion(const LLRectf& region);
+
+ LLPointer<LLTexture> getImage() { return mImage; }
+ const LLPointer<LLTexture>& getImage() const { return mImage; }
+
+ void draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color = UI_VERTEX_COLOR) const;
+ void draw(S32 x, S32 y, const LLColor4& color = UI_VERTEX_COLOR) const;
+ void draw(const LLRect& rect, const LLColor4& color = UI_VERTEX_COLOR) const { draw(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); }
+
+ void drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const;
+ void drawSolid(const LLRect& rect, const LLColor4& color) const { drawSolid(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); }
+ void drawSolid(S32 x, S32 y, const LLColor4& color) const { drawSolid(x, y, getWidth(), getHeight(), color); }
+
+ void drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const;
+ void drawBorder(const LLRect& rect, const LLColor4& color, S32 border_width) const { drawBorder(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color, border_width); }
+ void drawBorder(S32 x, S32 y, const LLColor4& color, S32 border_width) const { drawBorder(x, y, getWidth(), getHeight(), color, border_width); }
+
+ const std::string& getName() const { return mName; }
+
+ virtual S32 getWidth() const;
+ virtual S32 getHeight() const;
+
+ // returns dimensions of underlying textures, which might not be equal to ui image portion
+ S32 getTextureWidth() const;
+ S32 getTextureHeight() const;
+
+ boost::signals2::connection addLoadedCallback( const image_loaded_signal_t::slot_type& cb );
+
+ void onImageLoaded();
+
+protected:
+ image_loaded_signal_t* mImageLoaded;
+
+ std::string mName;
+ LLRectf mScaleRegion;
+ LLRectf mClipRegion;
+ LLPointer<LLTexture> mImage;
+ BOOL mUniformScaling;
+ BOOL mNoClip;
+};
+
+namespace LLInitParam
+{
+ template<>
+ class TypedParam<LLUIImage*, TypeValues<LLUIImage*>, false>
+ : public BlockValue<LLUIImage*>
+ {
+ typedef boost::add_reference<boost::add_const<LLUIImage*>::type>::type T_const_ref;
+ typedef BlockValue<LLUIImage*> super_t;
+ public:
+ Optional<std::string> name;
+
+ TypedParam(BlockDescriptor& descriptor, const char* name, super_t::value_assignment_t value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
+ : super_t(descriptor, name, value, func, min_count, max_count)
+ {
+ }
+
+ void setValueFromBlock() const;
+ void setBlockFromValue();
+ };
+
+ // Need custom comparison function for our test app, which only loads
+ // LLUIImage* as NULL.
+ template<>
+ struct ParamCompare<LLUIImage*, false>
+ {
+ static bool equals(LLUIImage* const &a, LLUIImage* const &b);
+ };
+}
+
+typedef LLPointer<LLUIImage> LLUIImagePtr;
+#endif
diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp
index 0b76b8e814..f7a53e87de 100644
--- a/indra/llui/lluistring.cpp
+++ b/indra/llui/lluistring.cpp
@@ -33,31 +33,35 @@
#include "linden_common.h"
#include "lluistring.h"
#include "llsd.h"
+#include "lltrans.h"
-const LLStringUtil::format_map_t LLUIString::sNullArgs;
+LLFastTimer::DeclareTimer FTM_UI_STRING("UI String");
LLUIString::LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args)
- : mOrig(instring),
- mArgs(args)
+: mOrig(instring),
+ mArgs(args)
{
- format();
+ dirty();
}
void LLUIString::assign(const std::string& s)
{
mOrig = s;
- format();
+ dirty();
}
void LLUIString::setArgList(const LLStringUtil::format_map_t& args)
+
{
mArgs = args;
- format();
+ dirty();
}
void LLUIString::setArgs(const LLSD& sd)
{
+ LLFastTimer timer(FTM_UI_STRING);
+
if (!sd.isMap()) return;
for(LLSD::map_const_iterator sd_it = sd.beginMap();
sd_it != sd.endMap();
@@ -65,40 +69,40 @@ void LLUIString::setArgs(const LLSD& sd)
{
setArg(sd_it->first, sd_it->second.asString());
}
- format();
+ dirty();
}
void LLUIString::setArg(const std::string& key, const std::string& replacement)
{
mArgs[key] = replacement;
- format();
+ dirty();
}
void LLUIString::truncate(S32 maxchars)
{
- if (mWResult.size() > (size_t)maxchars)
+ if (getUpdatedWResult().size() > (size_t)maxchars)
{
- LLWStringUtil::truncate(mWResult, maxchars);
- mResult = wstring_to_utf8str(mWResult);
+ LLWStringUtil::truncate(getUpdatedWResult(), maxchars);
+ mResult = wstring_to_utf8str(getUpdatedWResult());
}
}
void LLUIString::erase(S32 charidx, S32 len)
{
- mWResult.erase(charidx, len);
- mResult = wstring_to_utf8str(mWResult);
+ getUpdatedWResult().erase(charidx, len);
+ mResult = wstring_to_utf8str(getUpdatedWResult());
}
void LLUIString::insert(S32 charidx, const LLWString& wchars)
{
- mWResult.insert(charidx, wchars);
- mResult = wstring_to_utf8str(mWResult);
+ getUpdatedWResult().insert(charidx, wchars);
+ mResult = wstring_to_utf8str(getUpdatedWResult());
}
void LLUIString::replace(S32 charidx, llwchar wc)
{
- mWResult[charidx] = wc;
- mResult = wstring_to_utf8str(mWResult);
+ getUpdatedWResult()[charidx] = wc;
+ mResult = wstring_to_utf8str(getUpdatedWResult());
}
void LLUIString::clear()
@@ -109,9 +113,36 @@ void LLUIString::clear()
mWResult.clear();
}
-void LLUIString::format()
+void LLUIString::dirty()
+{
+ mNeedsResult = true;
+ mNeedsWResult = true;
+}
+
+void LLUIString::updateResult() const
{
+ mNeedsResult = false;
+
+ LLFastTimer timer(FTM_UI_STRING);
+
+ // optimize for empty strings (don't attempt string replacement)
+ if (mOrig.empty())
+ {
+ mResult.clear();
+ mWResult.clear();
+ return;
+ }
mResult = mOrig;
- LLStringUtil::format(mResult, mArgs);
- mWResult = utf8str_to_wstring(mResult);
+
+ // get the defailt args + local args
+ LLStringUtil::format_map_t combined_args = LLTrans::getDefaultArgs();
+ combined_args.insert(mArgs.begin(), mArgs.end());
+ LLStringUtil::format(mResult, combined_args);
+}
+
+void LLUIString::updateWResult() const
+{
+ mNeedsWResult = false;
+
+ mWResult = utf8str_to_wstring(getUpdatedResult());
}
diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h
index aedeca27cb..7ec0fd603a 100644
--- a/indra/llui/lluistring.h
+++ b/indra/llui/lluistring.h
@@ -51,9 +51,9 @@
// llinfos << mMessage.getString() << llendl; // outputs "Welcome Steve to Second Life"
// mMessage.setArg("[USERNAME]", "Joe");
// llinfos << mMessage.getString() << llendl; // outputs "Welcome Joe to Second Life"
-// mMessage = "Recepci￳n a la [SECONDLIFE] [USERNAME]"
+// mMessage = "Bienvenido a la [SECONDLIFE] [USERNAME]"
// mMessage.setArg("[SECONDLIFE]", "Segunda Vida");
-// llinfos << mMessage.getString() << llendl; // outputs "Recepci￳n a la Segunda Vida Joe"
+// llinfos << mMessage.getString() << llendl; // outputs "Bienvenido a la Segunda Vida Joe"
// Implementation Notes:
// Attempting to have operator[](const std::string& s) return mArgs[s] fails because we have
@@ -76,34 +76,44 @@ public:
void setArgs(const class LLSD& sd);
void setArg(const std::string& key, const std::string& replacement);
- const std::string& getString() const { return mResult; }
- operator std::string() const { return mResult; }
+ const std::string& getString() const { return getUpdatedResult(); }
+ operator std::string() const { return getUpdatedResult(); }
- const LLWString& getWString() const { return mWResult; }
- operator LLWString() const { return mWResult; }
+ const LLWString& getWString() const { return getUpdatedWResult(); }
+ operator LLWString() const { return getUpdatedWResult(); }
- bool empty() const { return mWResult.empty(); }
- S32 length() const { return mWResult.size(); }
+ bool empty() const { return getUpdatedResult().empty(); }
+ S32 length() const { return getUpdatedWResult().size(); }
void clear();
void clearArgs() { mArgs.clear(); }
- // These utuilty functions are included for text editing.
+ // These utility functions are included for text editing.
// They do not affect mOrig and do not perform argument substitution
void truncate(S32 maxchars);
void erase(S32 charidx, S32 len);
void insert(S32 charidx, const LLWString& wchars);
void replace(S32 charidx, llwchar wc);
- static const LLStringUtil::format_map_t sNullArgs;
-
private:
- void format();
+ // something changed, requiring reformatting of strings
+ void dirty();
+
+ std::string& getUpdatedResult() const { if (mNeedsResult) { updateResult(); } return mResult; }
+ LLWString& getUpdatedWResult() const{ if (mNeedsWResult) { updateWResult(); } return mWResult; }
+
+ // do actual work of updating strings (non-inlined)
+ void updateResult() const;
+ void updateWResult() const;
std::string mOrig;
- std::string mResult;
- LLWString mWResult; // for displaying
+ mutable std::string mResult;
+ mutable LLWString mWResult; // for displaying
LLStringUtil::format_map_t mArgs;
+
+ // controls lazy evaluation
+ mutable bool mNeedsResult;
+ mutable bool mNeedsWResult;
};
#endif // LL_LLUISTRING_H
diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp
new file mode 100644
index 0000000000..679db5e39b
--- /dev/null
+++ b/indra/llui/llurlaction.cpp
@@ -0,0 +1,148 @@
+/**
+ * @file llurlaction.cpp
+ * @author Martin Reddy
+ * @brief A set of actions that can performed on Urls
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llurlaction.h"
+#include "llview.h"
+#include "llwindow.h"
+#include "llurlregistry.h"
+
+// global state for the callback functions
+void (*LLUrlAction::sOpenURLCallback) (const std::string& url) = NULL;
+void (*LLUrlAction::sOpenURLInternalCallback) (const std::string& url) = NULL;
+void (*LLUrlAction::sOpenURLExternalCallback) (const std::string& url) = NULL;
+bool (*LLUrlAction::sExecuteSLURLCallback) (const std::string& url) = NULL;
+
+
+void LLUrlAction::setOpenURLCallback(void (*cb) (const std::string& url))
+{
+ sOpenURLCallback = cb;
+}
+
+void LLUrlAction::setOpenURLInternalCallback(void (*cb) (const std::string& url))
+{
+ sOpenURLInternalCallback = cb;
+}
+
+void LLUrlAction::setOpenURLExternalCallback(void (*cb) (const std::string& url))
+{
+ sOpenURLExternalCallback = cb;
+}
+
+void LLUrlAction::setExecuteSLURLCallback(bool (*cb) (const std::string& url))
+{
+ sExecuteSLURLCallback = cb;
+}
+
+void LLUrlAction::openURL(std::string url)
+{
+ if (sOpenURLCallback)
+ {
+ (*sOpenURLCallback)(url);
+ }
+}
+
+void LLUrlAction::openURLInternal(std::string url)
+{
+ if (sOpenURLInternalCallback)
+ {
+ (*sOpenURLInternalCallback)(url);
+ }
+}
+
+void LLUrlAction::openURLExternal(std::string url)
+{
+ if (sOpenURLExternalCallback)
+ {
+ (*sOpenURLExternalCallback)(url);
+ }
+}
+
+void LLUrlAction::executeSLURL(std::string url)
+{
+ if (sExecuteSLURLCallback)
+ {
+ (*sExecuteSLURLCallback)(url);
+ }
+}
+
+void LLUrlAction::clickAction(std::string url)
+{
+ // Try to handle as SLURL first, then http Url
+ if ( (sExecuteSLURLCallback) && !(*sExecuteSLURLCallback)(url) )
+ {
+ if (sOpenURLCallback)
+ {
+ (*sOpenURLCallback)(url);
+ }
+ }
+}
+
+void LLUrlAction::teleportToLocation(std::string url)
+{
+ LLUrlMatch match;
+ if (LLUrlRegistry::instance().findUrl(url, match))
+ {
+ if (! match.getLocation().empty())
+ {
+ executeSLURL("secondlife:///app/teleport/" + match.getLocation());
+ }
+ }
+}
+
+void LLUrlAction::showLocationOnMap(std::string url)
+{
+ LLUrlMatch match;
+ if (LLUrlRegistry::instance().findUrl(url, match))
+ {
+ if (! match.getLocation().empty())
+ {
+ executeSLURL("secondlife:///app/worldmap/" + match.getLocation());
+ }
+ }
+}
+
+void LLUrlAction::copyURLToClipboard(std::string url)
+{
+ LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(url));
+}
+
+void LLUrlAction::copyLabelToClipboard(std::string url)
+{
+ LLUrlMatch match;
+ if (LLUrlRegistry::instance().findUrl(url, match))
+ {
+ LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(match.getLabel()));
+ }
+}
diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h
new file mode 100644
index 0000000000..4830cf27ef
--- /dev/null
+++ b/indra/llui/llurlaction.h
@@ -0,0 +1,96 @@
+/**
+ * @file llurlaction.h
+ * @author Martin Reddy
+ * @brief A set of actions that can performed on Urls
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLURLACTION_H
+#define LL_LLURLACTION_H
+
+#include <string>
+
+///
+/// The LLUrlAction class provides a number of static functions that
+/// let you open Urls in web browsers, execute SLURLs, and copy Urls
+/// to the clipboard. Many of these functions are not available at
+/// the llui level, and must be supplied via a set of callbacks.
+///
+/// N.B. The action functions specifically do not use const ref
+/// strings so that a url parameter can be used into a boost::bind()
+/// call under situations when that input string is deallocated before
+/// the callback is executed.
+///
+class LLUrlAction
+{
+public:
+ LLUrlAction();
+
+ /// load a Url in the user's preferred web browser
+ static void openURL(std::string url);
+
+ /// load a Url in the internal Second Life web browser
+ static void openURLInternal(std::string url);
+
+ /// load a Url in the operating system's default web browser
+ static void openURLExternal(std::string url);
+
+ /// execute the given secondlife: SLURL
+ static void executeSLURL(std::string url);
+
+ /// if the Url specifies an SL location, teleport there
+ static void teleportToLocation(std::string url);
+
+ /// if the Url specifies an SL location, show it on a map
+ static void showLocationOnMap(std::string url);
+
+ /// perform the appropriate action for left-clicking on a Url
+ static void clickAction(std::string url);
+
+ /// copy the label for a Url to the clipboard
+ static void copyLabelToClipboard(std::string url);
+
+ /// copy a Url to the clipboard
+ static void copyURLToClipboard(std::string url);
+
+ /// specify the callbacks to enable this class's functionality
+ static void setOpenURLCallback(void (*cb) (const std::string& url));
+ static void setOpenURLInternalCallback(void (*cb) (const std::string& url));
+ static void setOpenURLExternalCallback(void (*cb) (const std::string& url));
+ static void setExecuteSLURLCallback(bool (*cb) (const std::string& url));
+
+private:
+ // callbacks for operations we can perform on Urls
+ static void (*sOpenURLCallback) (const std::string& url);
+ static void (*sOpenURLInternalCallback) (const std::string& url);
+ static void (*sOpenURLExternalCallback) (const std::string& url);
+ static bool (*sExecuteSLURLCallback) (const std::string& url);
+};
+
+#endif
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
new file mode 100644
index 0000000000..4927e57a52
--- /dev/null
+++ b/indra/llui/llurlentry.cpp
@@ -0,0 +1,643 @@
+/**
+ * @file llurlentry.cpp
+ * @author Martin Reddy
+ * @brief Describes the Url types that can be registered in LLUrlRegistry
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llurlentry.h"
+#include "lluri.h"
+
+#include "llcachename.h"
+#include "lltrans.h"
+#include "lluicolortable.h"
+
+LLUrlEntryBase::LLUrlEntryBase()
+: mColor(LLUIColorTable::instance().getColor("HTMLLinkColor"))
+{
+}
+
+LLUrlEntryBase::~LLUrlEntryBase()
+{
+}
+
+std::string LLUrlEntryBase::getUrl(const std::string &string)
+{
+ return escapeUrl(string);
+}
+
+std::string LLUrlEntryBase::getIDStringFromUrl(const std::string &url) const
+{
+ // return the id from a SLURL in the format /app/{cmd}/{id}/about
+ LLURI uri(url);
+ LLSD path_array = uri.pathArray();
+ if (path_array.size() == 4)
+ {
+ return path_array.get(2).asString();
+ }
+ return "";
+}
+
+std::string LLUrlEntryBase::unescapeUrl(const std::string &url) const
+{
+ return LLURI::unescape(url);
+}
+
+std::string LLUrlEntryBase::escapeUrl(const std::string &url) const
+{
+ static std::string no_escape_chars;
+ static bool initialized = false;
+ if (!initialized)
+ {
+ no_escape_chars =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "-._~!$?&()*+,@:;=/%#";
+
+ std::sort(no_escape_chars.begin(), no_escape_chars.end());
+ initialized = true;
+ }
+ return LLURI::escape(url, no_escape_chars, true);
+}
+
+std::string LLUrlEntryBase::getLabelFromWikiLink(const std::string &url)
+{
+ // return the label part from [http://www.example.org Label]
+ const char *text = url.c_str();
+ S32 start = 0;
+ while (! isspace(text[start]))
+ {
+ start++;
+ }
+ while (text[start] == ' ' || text[start] == '\t')
+ {
+ start++;
+ }
+ return unescapeUrl(url.substr(start, url.size()-start-1));
+}
+
+std::string LLUrlEntryBase::getUrlFromWikiLink(const std::string &string)
+{
+ // return the url part from [http://www.example.org Label]
+ const char *text = string.c_str();
+ S32 end = 0;
+ while (! isspace(text[end]))
+ {
+ end++;
+ }
+ return escapeUrl(string.substr(1, end-1));
+}
+
+void LLUrlEntryBase::addObserver(const std::string &id,
+ const std::string &url,
+ const LLUrlLabelCallback &cb)
+{
+ // add a callback to be notified when we have a label for the uuid
+ LLUrlEntryObserver observer;
+ observer.url = url;
+ observer.signal = new LLUrlLabelSignal();
+ if (observer.signal)
+ {
+ observer.signal->connect(cb);
+ mObservers.insert(std::pair<std::string, LLUrlEntryObserver>(id, observer));
+ }
+}
+
+void LLUrlEntryBase::callObservers(const std::string &id, const std::string &label)
+{
+ // notify all callbacks waiting on the given uuid
+ std::multimap<std::string, LLUrlEntryObserver>::iterator it;
+ for (it = mObservers.find(id); it != mObservers.end();)
+ {
+ // call the callback - give it the new label
+ LLUrlEntryObserver &observer = it->second;
+ (*observer.signal)(it->second.url, label);
+ // then remove the signal - we only need to call it once
+ delete observer.signal;
+ mObservers.erase(it++);
+ }
+}
+
+static std::string getStringAfterToken(const std::string str, const std::string token)
+{
+ size_t pos = str.find(token);
+ if (pos == std::string::npos)
+ {
+ return "";
+ }
+
+ pos += token.size();
+ return str.substr(pos, str.size() - pos);
+}
+
+//
+// LLUrlEntryHTTP Describes generic http: and https: Urls
+//
+LLUrlEntryHTTP::LLUrlEntryHTTP()
+{
+ mPattern = boost::regex("https?://([-\\w\\.]+)+(:\\d+)?(:\\w+)?(@\\d+)?(@\\w+)?/?\\S*",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_http.xml";
+ mTooltip = LLTrans::getString("TooltipHttpUrl");
+}
+
+std::string LLUrlEntryHTTP::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ return unescapeUrl(url);
+}
+
+//
+// LLUrlEntryHTTP Describes generic http: and https: Urls with custom label
+// We use the wikipedia syntax of [http://www.example.org Text]
+//
+LLUrlEntryHTTPLabel::LLUrlEntryHTTPLabel()
+{
+ mPattern = boost::regex("\\[https?://\\S+[ \t]+[^\\]]+\\]",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_http.xml";
+ mTooltip = LLTrans::getString("TooltipHttpUrl");
+}
+
+std::string LLUrlEntryHTTPLabel::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ return getLabelFromWikiLink(url);
+}
+
+std::string LLUrlEntryHTTPLabel::getUrl(const std::string &string)
+{
+ return getUrlFromWikiLink(string);
+}
+
+//
+// LLUrlEntryHTTPNoProtocol Describes generic Urls like www.google.com
+//
+LLUrlEntryHTTPNoProtocol::LLUrlEntryHTTPNoProtocol()
+{
+ mPattern = boost::regex("("
+ "\\bwww\\.\\S+\\.\\S+" // i.e. www.FOO.BAR
+ "|" // or
+ "(?<!@)\\b[^[:space:]:@/]+\\.(?:com|net|edu|org)([/:]\\S*)?\\b" // i.e. FOO.net
+ ")",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_http.xml";
+ mTooltip = LLTrans::getString("TooltipHttpUrl");
+}
+
+std::string LLUrlEntryHTTPNoProtocol::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ return unescapeUrl(url);
+}
+
+std::string LLUrlEntryHTTPNoProtocol::getUrl(const std::string &string)
+{
+ if (string.find("://") == std::string::npos)
+ {
+ return "http://" + escapeUrl(string);
+ }
+ return escapeUrl(string);
+}
+
+//
+// LLUrlEntrySLURL Describes generic http: and https: Urls
+//
+LLUrlEntrySLURL::LLUrlEntrySLURL()
+{
+ // see http://slurl.com/about.php for details on the SLURL format
+ mPattern = boost::regex("http://slurl.com/secondlife/\\S+/?(\\d+)?/?(\\d+)?/?(\\d+)?/?\\S*",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_slurl.xml";
+ mTooltip = LLTrans::getString("TooltipSLURL");
+}
+
+std::string LLUrlEntrySLURL::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ //
+ // we handle SLURLs in the following formats:
+ // - http://slurl.com/secondlife/Place/X/Y/Z
+ // - http://slurl.com/secondlife/Place/X/Y
+ // - http://slurl.com/secondlife/Place/X
+ // - http://slurl.com/secondlife/Place
+ //
+ LLURI uri(url);
+ LLSD path_array = uri.pathArray();
+ S32 path_parts = path_array.size();
+ if (path_parts == 5)
+ {
+ // handle slurl with (X,Y,Z) coordinates
+ std::string location = unescapeUrl(path_array[path_parts-4]);
+ std::string x = path_array[path_parts-3];
+ std::string y = path_array[path_parts-2];
+ std::string z = path_array[path_parts-1];
+ return location + " (" + x + "," + y + "," + z + ")";
+ }
+ else if (path_parts == 4)
+ {
+ // handle slurl with (X,Y) coordinates
+ std::string location = unescapeUrl(path_array[path_parts-3]);
+ std::string x = path_array[path_parts-2];
+ std::string y = path_array[path_parts-1];
+ return location + " (" + x + "," + y + ")";
+ }
+ else if (path_parts == 3)
+ {
+ // handle slurl with (X) coordinate
+ std::string location = unescapeUrl(path_array[path_parts-2]);
+ std::string x = path_array[path_parts-1];
+ return location + " (" + x + ")";
+ }
+ else if (path_parts == 2)
+ {
+ // handle slurl with no coordinates
+ std::string location = unescapeUrl(path_array[path_parts-1]);
+ return location;
+ }
+
+ return url;
+}
+
+std::string LLUrlEntrySLURL::getLocation(const std::string &url) const
+{
+ // return the part of the Url after slurl.com/secondlife/
+ const std::string search_string = "secondlife";
+ size_t pos = url.find(search_string);
+ if (pos == std::string::npos)
+ {
+ return "";
+ }
+
+ pos += search_string.size() + 1;
+ return url.substr(pos, url.size() - pos);
+}
+
+//
+// LLUrlEntryAgent Describes a Second Life agent Url, e.g.,
+// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
+//
+LLUrlEntryAgent::LLUrlEntryAgent()
+{
+ mPattern = boost::regex("secondlife:///app/agent/[\\da-f-]+/\\w+",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_agent.xml";
+ mIcon = "Generic_Person";
+ mColor = LLUIColorTable::instance().getColor("AgentLinkColor");
+}
+
+void LLUrlEntryAgent::onAgentNameReceived(const LLUUID& id,
+ const std::string& first,
+ const std::string& last,
+ BOOL is_group)
+{
+ // received the agent name from the server - tell our observers
+ callObservers(id.asString(), first + " " + last);
+}
+
+std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ if (!gCacheName)
+ {
+ // probably at the login screen, use short string for layout
+ return LLTrans::getString("LoadingData");
+ }
+
+ std::string agent_id_string = getIDStringFromUrl(url);
+ if (agent_id_string.empty())
+ {
+ // something went wrong, just give raw url
+ return unescapeUrl(url);
+ }
+
+ LLUUID agent_id(agent_id_string);
+ std::string full_name;
+ if (agent_id.isNull())
+ {
+ return LLTrans::getString("AvatarNameNobody");
+ }
+ else if (gCacheName->getFullName(agent_id, full_name))
+ {
+ return full_name;
+ }
+ else
+ {
+ gCacheName->get(agent_id, FALSE,
+ boost::bind(&LLUrlEntryAgent::onAgentNameReceived,
+ this, _1, _2, _3, _4));
+ addObserver(agent_id_string, url, cb);
+ return LLTrans::getString("LoadingData");
+ }
+}
+
+//
+// LLUrlEntryGroup Describes a Second Life group Url, e.g.,
+// secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about
+// secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/inspect
+//
+LLUrlEntryGroup::LLUrlEntryGroup()
+{
+ mPattern = boost::regex("secondlife:///app/group/[\\da-f-]+/\\w+",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_group.xml";
+ mIcon = "Generic_Group";
+ mTooltip = LLTrans::getString("TooltipGroupUrl");
+ mColor = LLUIColorTable::instance().getColor("GroupLinkColor");
+}
+
+void LLUrlEntryGroup::onGroupNameReceived(const LLUUID& id,
+ const std::string& first,
+ const std::string& last,
+ BOOL is_group)
+{
+ // received the group name from the server - tell our observers
+ callObservers(id.asString(), first);
+}
+
+std::string LLUrlEntryGroup::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ if (!gCacheName)
+ {
+ // probably at login screen, give something short for layout
+ return LLTrans::getString("LoadingData");
+ }
+
+ std::string group_id_string = getIDStringFromUrl(url);
+ if (group_id_string.empty())
+ {
+ // something went wrong, give raw url
+ return unescapeUrl(url);
+ }
+
+ LLUUID group_id(group_id_string);
+ std::string group_name;
+ if (group_id.isNull())
+ {
+ return LLTrans::getString("GroupNameNone");
+ }
+ else if (gCacheName->getGroupName(group_id, group_name))
+ {
+ return group_name;
+ }
+ else
+ {
+ gCacheName->get(group_id, TRUE,
+ boost::bind(&LLUrlEntryGroup::onGroupNameReceived,
+ this, _1, _2, _3, _4));
+ addObserver(group_id_string, url, cb);
+ return LLTrans::getString("LoadingData");
+ }
+}
+
+//
+// LLUrlEntryInventory Describes a Second Life inventory Url, e.g.,
+// secondlife:///app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select
+//
+LLUrlEntryInventory::LLUrlEntryInventory()
+{
+ //*TODO: add supporting of inventory item names with whitespaces
+ //this pattern cann't parse for example
+ //secondlife:///app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select?name=name with spaces&param2=value
+ mPattern = boost::regex("secondlife:///app/inventory/[\\da-f-]+/\\w+\\S*",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_inventory.xml";
+}
+
+std::string LLUrlEntryInventory::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ std::string label = getStringAfterToken(url, "name=");
+ return LLURI::unescape(label.empty() ? url : label);
+}
+
+///
+/// LLUrlEntryParcel Describes a Second Life parcel Url, e.g.,
+/// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about
+///
+LLUrlEntryParcel::LLUrlEntryParcel()
+{
+ mPattern = boost::regex("secondlife:///app/parcel/[\\da-f-]+/about",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_parcel.xml";
+ mTooltip = LLTrans::getString("TooltipParcelUrl");
+}
+
+std::string LLUrlEntryParcel::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ return unescapeUrl(url);
+}
+
+//
+// LLUrlEntryPlace Describes secondlife://<location> URLs
+//
+LLUrlEntryPlace::LLUrlEntryPlace()
+{
+ mPattern = boost::regex("secondlife://\\S+/?(\\d+/\\d+/\\d+|\\d+/\\d+)/?",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_slurl.xml";
+ mTooltip = LLTrans::getString("TooltipSLURL");
+}
+
+std::string LLUrlEntryPlace::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ //
+ // we handle SLURLs in the following formats:
+ // - secondlife://Place/X/Y/Z
+ // - secondlife://Place/X/Y
+ //
+ LLURI uri(url);
+ std::string location = unescapeUrl(uri.hostName());
+ LLSD path_array = uri.pathArray();
+ S32 path_parts = path_array.size();
+ if (path_parts == 3)
+ {
+ // handle slurl with (X,Y,Z) coordinates
+ std::string x = path_array[0];
+ std::string y = path_array[1];
+ std::string z = path_array[2];
+ return location + " (" + x + "," + y + "," + z + ")";
+ }
+ else if (path_parts == 2)
+ {
+ // handle slurl with (X,Y) coordinates
+ std::string x = path_array[0];
+ std::string y = path_array[1];
+ return location + " (" + x + "," + y + ")";
+ }
+
+ return url;
+}
+
+std::string LLUrlEntryPlace::getLocation(const std::string &url) const
+{
+ // return the part of the Url after secondlife:// part
+ return ::getStringAfterToken(url, "://");
+}
+
+//
+// LLUrlEntryTeleport Describes a Second Life teleport Url, e.g.,
+// secondlife:///app/teleport/Ahern/50/50/50/
+//
+LLUrlEntryTeleport::LLUrlEntryTeleport()
+{
+ mPattern = boost::regex("secondlife:///app/teleport/\\S+(/\\d+)?(/\\d+)?(/\\d+)?/?\\S*",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_teleport.xml";
+ mTooltip = LLTrans::getString("TooltipTeleportUrl");
+}
+
+std::string LLUrlEntryTeleport::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ //
+ // we handle teleport SLURLs in the following formats:
+ // - secondlife:///app/teleport/Place/X/Y/Z
+ // - secondlife:///app/teleport/Place/X/Y
+ // - secondlife:///app/teleport/Place/X
+ // - secondlife:///app/teleport/Place
+ //
+ LLURI uri(url);
+ LLSD path_array = uri.pathArray();
+ S32 path_parts = path_array.size();
+ const std::string label = LLTrans::getString("SLurlLabelTeleport");
+ if (path_parts == 6)
+ {
+ // handle teleport url with (X,Y,Z) coordinates
+ std::string location = unescapeUrl(path_array[path_parts-4]);
+ std::string x = path_array[path_parts-3];
+ std::string y = path_array[path_parts-2];
+ std::string z = path_array[path_parts-1];
+ return label + " " + location + " (" + x + "," + y + "," + z + ")";
+ }
+ else if (path_parts == 5)
+ {
+ // handle teleport url with (X,Y) coordinates
+ std::string location = unescapeUrl(path_array[path_parts-3]);
+ std::string x = path_array[path_parts-2];
+ std::string y = path_array[path_parts-1];
+ return label + " " + location + " (" + x + "," + y + ")";
+ }
+ else if (path_parts == 4)
+ {
+ // handle teleport url with (X) coordinate only
+ std::string location = unescapeUrl(path_array[path_parts-2]);
+ std::string x = path_array[path_parts-1];
+ return label + " " + location + " (" + x + ")";
+ }
+ else if (path_parts == 3)
+ {
+ // handle teleport url with no coordinates
+ std::string location = unescapeUrl(path_array[path_parts-1]);
+ return label + " " + location;
+ }
+
+ return url;
+}
+
+std::string LLUrlEntryTeleport::getLocation(const std::string &url) const
+{
+ // return the part of the Url after ///app/teleport
+ return ::getStringAfterToken(url, "app/teleport/");
+}
+
+//
+// LLUrlEntrySL Describes a generic SLURL, e.g., a Url that starts
+// with secondlife:// (used as a catch-all for cases not matched above)
+//
+LLUrlEntrySL::LLUrlEntrySL()
+{
+ mPattern = boost::regex("secondlife://(\\w+)?(:\\d+)?/\\S+",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_slapp.xml";
+ mTooltip = LLTrans::getString("TooltipSLAPP");
+}
+
+std::string LLUrlEntrySL::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ return unescapeUrl(url);
+}
+
+//
+// LLUrlEntrySLLabel Describes a generic SLURL, e.g., a Url that starts
+/// with secondlife:// with the ability to specify a custom label.
+//
+LLUrlEntrySLLabel::LLUrlEntrySLLabel()
+{
+ mPattern = boost::regex("\\[secondlife://\\S+[ \t]+[^\\]]+\\]",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_slapp.xml";
+ mTooltip = LLTrans::getString("TooltipSLAPP");
+}
+
+std::string LLUrlEntrySLLabel::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ return getLabelFromWikiLink(url);
+}
+
+std::string LLUrlEntrySLLabel::getUrl(const std::string &string)
+{
+ return getUrlFromWikiLink(string);
+}
+
+//
+// LLUrlEntryWorldMap Describes secondlife:///<location> URLs
+//
+LLUrlEntryWorldMap::LLUrlEntryWorldMap()
+{
+ mPattern = boost::regex("secondlife:///app/worldmap/\\S+/?(\\d+)?/?(\\d+)?/?(\\d+)?/?\\S*",
+ boost::regex::perl|boost::regex::icase);
+ mMenuName = "menu_url_map.xml";
+ mTooltip = LLTrans::getString("TooltipMapUrl");
+}
+
+std::string LLUrlEntryWorldMap::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ //
+ // we handle SLURLs in the following formats:
+ // - secondlife:///app/worldmap/PLACE/X/Y/Z
+ // - secondlife:///app/worldmap/PLACE/X/Y
+ // - secondlife:///app/worldmap/PLACE/X
+ //
+ LLURI uri(url);
+ LLSD path_array = uri.pathArray();
+ S32 path_parts = path_array.size();
+ if (path_parts < 3)
+ {
+ return url;
+ }
+
+ const std::string label = LLTrans::getString("SLurlLabelShowOnMap");
+ std::string location = path_array[2];
+ std::string x = (path_parts > 3) ? path_array[3] : "128";
+ std::string y = (path_parts > 4) ? path_array[4] : "128";
+ std::string z = (path_parts > 5) ? path_array[5] : "0";
+ return label + " " + location + " (" + x + "," + y + "," + z + ")";
+}
+
+std::string LLUrlEntryWorldMap::getLocation(const std::string &url) const
+{
+ // return the part of the Url after secondlife:///app/worldmap/ part
+ return ::getStringAfterToken(url, "app/worldmap/");
+}
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
new file mode 100644
index 0000000000..4adffde99c
--- /dev/null
+++ b/indra/llui/llurlentry.h
@@ -0,0 +1,270 @@
+/**
+ * @file llurlentry.h
+ * @author Martin Reddy
+ * @brief Describes the Url types that can be registered in LLUrlRegistry
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLURLENTRY_H
+#define LL_LLURLENTRY_H
+
+#include "lluuid.h"
+#include "lluicolor.h"
+#include <boost/signals2.hpp>
+#include <boost/regex.hpp>
+#include <string>
+#include <map>
+
+typedef boost::signals2::signal<void (const std::string& url,
+ const std::string& label)> LLUrlLabelSignal;
+typedef LLUrlLabelSignal::slot_type LLUrlLabelCallback;
+
+///
+/// LLUrlEntryBase is the base class of all Url types registered in the
+/// LLUrlRegistry. Each derived classes provides a regular expression
+/// to match the Url type (e.g., http://... or secondlife://...) along
+/// with an optional icon to display next to instances of the Url in
+/// a text display and a XUI file to use for any context menu popup.
+/// Functions are also provided to compute an appropriate label and
+/// tooltip/status bar text for the Url.
+///
+/// Some derived classes of LLUrlEntryBase may wish to compute an
+/// appropriate label for a Url by asking the server for information.
+/// You must therefore provide a callback method, so that you can be
+/// notified when an updated label has been received from the server.
+/// This label should then be used to replace any previous label
+/// that you received from getLabel() for the Url in question.
+///
+class LLUrlEntryBase
+{
+public:
+ LLUrlEntryBase();
+ virtual ~LLUrlEntryBase();
+
+ /// Return the regex pattern that matches this Url
+ boost::regex getPattern() const { return mPattern; }
+
+ /// Return the url from a string that matched the regex
+ virtual std::string getUrl(const std::string &string);
+
+ /// Given a matched Url, return a label for the Url
+ virtual std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) { return url; }
+
+ /// Return an icon that can be displayed next to Urls of this type
+ std::string getIcon() const { return mIcon; }
+
+ /// Return the color to render the displayed text
+ LLUIColor getColor() const { return mColor; }
+
+ /// Given a matched Url, return a tooltip string for the hyperlink
+ std::string getTooltip() const { return mTooltip; }
+
+ /// Return the name of a XUI file containing the context menu items
+ std::string getMenuName() const { return mMenuName; }
+
+ /// Return the name of a SL location described by this Url, if any
+ virtual std::string getLocation(const std::string &url) const { return ""; }
+
+protected:
+ std::string getIDStringFromUrl(const std::string &url) const;
+ std::string escapeUrl(const std::string &url) const;
+ std::string unescapeUrl(const std::string &url) const;
+ std::string getLabelFromWikiLink(const std::string &url);
+ std::string getUrlFromWikiLink(const std::string &string);
+ void addObserver(const std::string &id, const std::string &url, const LLUrlLabelCallback &cb);
+ void callObservers(const std::string &id, const std::string &label);
+
+ typedef struct {
+ std::string url;
+ LLUrlLabelSignal *signal;
+ } LLUrlEntryObserver;
+
+ boost::regex mPattern;
+ std::string mIcon;
+ std::string mMenuName;
+ std::string mTooltip;
+ LLUIColor mColor;
+ std::multimap<std::string, LLUrlEntryObserver> mObservers;
+};
+
+///
+/// LLUrlEntryHTTP Describes generic http: and https: Urls
+///
+class LLUrlEntryHTTP : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryHTTP();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+};
+
+///
+/// LLUrlEntryHTTPLabel Describes generic http: and https: Urls with custom labels
+///
+class LLUrlEntryHTTPLabel : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryHTTPLabel();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ std::string getUrl(const std::string &string);
+};
+
+///
+/// LLUrlEntryHTTPNoProtocol Describes generic Urls like www.google.com
+///
+class LLUrlEntryHTTPNoProtocol : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryHTTPNoProtocol();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ std::string getUrl(const std::string &string);
+};
+
+///
+/// LLUrlEntrySLURL Describes http://slurl.com/... Urls
+///
+class LLUrlEntrySLURL : public LLUrlEntryBase
+{
+public:
+ LLUrlEntrySLURL();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ std::string getLocation(const std::string &url) const;
+};
+
+///
+/// LLUrlEntryAgent Describes a Second Life agent Url, e.g.,
+/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
+///
+class LLUrlEntryAgent : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryAgent();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+private:
+ void onAgentNameReceived(const LLUUID& id, const std::string& first,
+ const std::string& last, BOOL is_group);
+};
+
+///
+/// LLUrlEntryGroup Describes a Second Life group Url, e.g.,
+/// secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about
+///
+class LLUrlEntryGroup : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryGroup();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+private:
+ void onGroupNameReceived(const LLUUID& id, const std::string& first,
+ const std::string& last, BOOL is_group);
+};
+
+///
+/// LLUrlEntryInventory Describes a Second Life inventory Url, e.g.,
+/// secondlife:///app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select
+///
+class LLUrlEntryInventory : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryInventory();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+private:
+};
+
+
+///
+/// LLUrlEntryParcel Describes a Second Life parcel Url, e.g.,
+/// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about
+///
+class LLUrlEntryParcel : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryParcel();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+};
+
+///
+/// LLUrlEntryPlace Describes a Second Life location Url, e.g.,
+/// secondlife://Ahern/50/50/50
+///
+class LLUrlEntryPlace : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryPlace();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ std::string getLocation(const std::string &url) const;
+};
+
+///
+/// LLUrlEntryTeleport Describes a Second Life teleport Url, e.g.,
+/// secondlife:///app/teleport/Ahern/50/50/50/
+///
+class LLUrlEntryTeleport : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryTeleport();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ std::string getLocation(const std::string &url) const;
+};
+
+///
+/// LLUrlEntrySL Describes a generic SLURL, e.g., a Url that starts
+/// with secondlife:// (used as a catch-all for cases not matched above)
+///
+class LLUrlEntrySL : public LLUrlEntryBase
+{
+public:
+ LLUrlEntrySL();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+};
+
+///
+/// LLUrlEntrySLLabel Describes a generic SLURL, e.g., a Url that starts
+/// with secondlife:// with the ability to specify a custom label.
+///
+class LLUrlEntrySLLabel : public LLUrlEntryBase
+{
+public:
+ LLUrlEntrySLLabel();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ std::string getUrl(const std::string &string);
+};
+
+///
+/// LLUrlEntryWorldMap Describes a Second Life worldmap Url, e.g.,
+/// secondlife:///app/worldmap/Ahern/50/50/50
+///
+class LLUrlEntryWorldMap : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryWorldMap();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ std::string getLocation(const std::string &url) const;
+};
+
+#endif
diff --git a/indra/llui/llurlmatch.cpp b/indra/llui/llurlmatch.cpp
new file mode 100644
index 0000000000..3b47145a22
--- /dev/null
+++ b/indra/llui/llurlmatch.cpp
@@ -0,0 +1,62 @@
+/**
+ * @file llurlmatch.cpp
+ * @author Martin Reddy
+ * @brief Specifies a matched Url in a string, as returned by LLUrlRegistry
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llurlmatch.h"
+
+LLUrlMatch::LLUrlMatch() :
+ mStart(0),
+ mEnd(0),
+ mUrl(""),
+ mLabel(""),
+ mTooltip(""),
+ mIcon(""),
+ mMenuName("")
+{
+}
+
+void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
+ const std::string &label, const std::string &tooltip,
+ const std::string &icon, const LLUIColor& color,
+ const std::string &menu, const std::string &location)
+{
+ mStart = start;
+ mEnd = end;
+ mUrl = url;
+ mLabel = label;
+ mTooltip = tooltip;
+ mIcon = icon;
+ mColor = color;
+ mMenuName = menu;
+ mLocation = location;
+}
diff --git a/indra/llui/llurlmatch.h b/indra/llui/llurlmatch.h
new file mode 100644
index 0000000000..7f5767923a
--- /dev/null
+++ b/indra/llui/llurlmatch.h
@@ -0,0 +1,104 @@
+/**
+ * @file llurlmatch.h
+ * @author Martin Reddy
+ * @brief Specifies a matched Url in a string, as returned by LLUrlRegistry
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLURLMATCH_H
+#define LL_LLURLMATCH_H
+
+#include "linden_common.h"
+
+#include <string>
+#include <vector>
+#include "lluicolor.h"
+
+///
+/// LLUrlMatch describes a single Url that was matched within a string by
+/// the LLUrlRegistry::findUrl() method. It includes the actual Url that
+/// was matched along with its first/last character offset in the string.
+/// An alternate label is also provided for creating a hyperlink, as well
+/// as tooltip/status text, an icon, and a XUI file for a context menu
+/// that can be used in a popup for a Url (e.g., Open, Copy URL, etc.)
+///
+class LLUrlMatch
+{
+public:
+ LLUrlMatch();
+
+ /// return true if this object does not contain a valid Url match yet
+ bool empty() const { return mUrl.empty(); }
+
+ /// return the offset in the string for the first character of the Url
+ U32 getStart() const { return mStart; }
+
+ /// return the offset in the string for the last character of the Url
+ U32 getEnd() const { return mEnd; }
+
+ /// return the Url that has been matched in the input string
+ std::string getUrl() const { return mUrl; }
+
+ /// return a label that can be used for the display of this Url
+ std::string getLabel() const { return mLabel; }
+
+ /// return a message that could be displayed in a tooltip or status bar
+ std::string getTooltip() const { return mTooltip; }
+
+ /// return the filename for an icon that can be displayed next to this Url
+ std::string getIcon() const { return mIcon; }
+
+ /// Return the color to render the displayed text
+ LLUIColor getColor() const { return mColor; }
+
+ /// Return the name of a XUI file containing the context menu items
+ std::string getMenuName() const { return mMenuName; }
+
+ /// return the SL location that this Url describes, or "" if none.
+ std::string getLocation() const { return mLocation; }
+
+ /// Change the contents of this match object (used by LLUrlRegistry)
+ void setValues(U32 start, U32 end, const std::string &url, const std::string &label,
+ const std::string &tooltip, const std::string &icon,
+ const LLUIColor& color, const std::string &menu,
+ const std::string &location);
+
+private:
+ U32 mStart;
+ U32 mEnd;
+ std::string mUrl;
+ std::string mLabel;
+ std::string mTooltip;
+ std::string mIcon;
+ std::string mMenuName;
+ std::string mLocation;
+ LLUIColor mColor;
+};
+
+#endif
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
new file mode 100644
index 0000000000..ad5c0911f8
--- /dev/null
+++ b/indra/llui/llurlregistry.cpp
@@ -0,0 +1,245 @@
+/**
+ * @file llurlregistry.cpp
+ * @author Martin Reddy
+ * @brief Contains a set of Url types that can be matched in a string
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llurlregistry.h"
+
+#include <boost/regex.hpp>
+
+// default dummy callback that ignores any label updates from the server
+void LLUrlRegistryNullCallback(const std::string &url, const std::string &label)
+{
+}
+
+LLUrlRegistry::LLUrlRegistry()
+{
+ // Urls are matched in the order that they were registered
+ registerUrl(new LLUrlEntrySLURL());
+ registerUrl(new LLUrlEntryHTTP());
+ registerUrl(new LLUrlEntryHTTPLabel());
+ registerUrl(new LLUrlEntryAgent());
+ registerUrl(new LLUrlEntryGroup());
+ registerUrl(new LLUrlEntryParcel());
+ registerUrl(new LLUrlEntryTeleport());
+ registerUrl(new LLUrlEntryWorldMap());
+ registerUrl(new LLUrlEntryPlace());
+ registerUrl(new LLUrlEntryInventory());
+ //LLUrlEntrySL and LLUrlEntrySLLabel have more common pattern,
+ //so it should be registered in the end of list
+ registerUrl(new LLUrlEntrySL());
+ registerUrl(new LLUrlEntrySLLabel());
+ // most common pattern is a URL without any protocol,
+ // e.g., "secondlife.com"
+ registerUrl(new LLUrlEntryHTTPNoProtocol());
+}
+
+LLUrlRegistry::~LLUrlRegistry()
+{
+ // free all of the LLUrlEntryBase objects we are holding
+ std::vector<LLUrlEntryBase *>::iterator it;
+ for (it = mUrlEntry.begin(); it != mUrlEntry.end(); ++it)
+ {
+ delete *it;
+ }
+}
+
+void LLUrlRegistry::registerUrl(LLUrlEntryBase *url)
+{
+ if (url)
+ {
+ mUrlEntry.push_back(url);
+ }
+}
+
+static bool matchRegex(const char *text, boost::regex regex, U32 &start, U32 &end)
+{
+ boost::cmatch result;
+ bool found;
+
+ // regex_search can potentially throw an exception, so check for it
+ try
+ {
+ found = boost::regex_search(text, result, regex);
+ }
+ catch (std::runtime_error &)
+ {
+ return false;
+ }
+
+ if (! found)
+ {
+ return false;
+ }
+
+ // return the first/last character offset for the matched substring
+ start = static_cast<U32>(result[0].first - text);
+ end = static_cast<U32>(result[0].second - text) - 1;
+
+ // we allow certain punctuation to terminate a Url but not match it,
+ // e.g., "http://foo.com/." should just match "http://foo.com/"
+ if (text[end] == '.' || text[end] == ',')
+ {
+ end--;
+ }
+ // ignore a terminating ')' when Url contains no matching '('
+ // see DEV-19842 for details
+ else if (text[end] == ')' && std::string(text+start, end-start).find('(') == std::string::npos)
+ {
+ end--;
+ }
+
+ return true;
+}
+
+static bool stringHasUrl(const std::string &text)
+{
+ // fast heuristic test for a URL in a string. This is used
+ // to avoid lots of costly regex calls, BUT it needs to be
+ // kept in sync with the LLUrlEntry regexes we support.
+ return (text.find("://") != std::string::npos ||
+ text.find("www.") != std::string::npos ||
+ text.find(".com") != std::string::npos ||
+ text.find(".net") != std::string::npos ||
+ text.find(".edu") != std::string::npos ||
+ text.find(".org") != std::string::npos);
+}
+
+bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb)
+{
+ // avoid costly regexes if there is clearly no URL in the text
+ if (! stringHasUrl(text))
+ {
+ return false;
+ }
+
+ // find the first matching regex from all url entries in the registry
+ U32 match_start = 0, match_end = 0;
+ LLUrlEntryBase *match_entry = NULL;
+
+ std::vector<LLUrlEntryBase *>::iterator it;
+ for (it = mUrlEntry.begin(); it != mUrlEntry.end(); ++it)
+ {
+ LLUrlEntryBase *url_entry = *it;
+
+ U32 start = 0, end = 0;
+ if (matchRegex(text.c_str(), url_entry->getPattern(), start, end))
+ {
+ // does this match occur in the string before any other match
+ if (start < match_start || match_entry == NULL)
+ {
+ match_start = start;
+ match_end = end;
+ match_entry = url_entry;
+ }
+ }
+ }
+
+ // did we find a match? if so, return its details in the match object
+ if (match_entry)
+ {
+ // fill in the LLUrlMatch object and return it
+ std::string url = text.substr(match_start, match_end - match_start + 1);
+ match.setValues(match_start, match_end,
+ match_entry->getUrl(url),
+ match_entry->getLabel(url, cb),
+ match_entry->getTooltip(),
+ match_entry->getIcon(),
+ match_entry->getColor(),
+ match_entry->getMenuName(),
+ match_entry->getLocation(url));
+ return true;
+ }
+
+ return false;
+}
+
+bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUrlLabelCallback &cb)
+{
+ // boost::regex_search() only works on char or wchar_t
+ // types, but wchar_t is only 2-bytes on Win32 (not 4).
+ // So we use UTF-8 to make this work the same everywhere.
+ std::string utf8_text = wstring_to_utf8str(text);
+ if (findUrl(utf8_text, match, cb))
+ {
+ // we cannot blindly return the start/end offsets from
+ // the UTF-8 string because it is a variable-length
+ // character encoding, so we need to update the start
+ // and end values to be correct for the wide string.
+ LLWString wurl = utf8str_to_wstring(match.getUrl());
+ S32 start = text.find(wurl);
+ if (start == std::string::npos)
+ {
+ return false;
+ }
+ S32 end = start + wurl.size() - 1;
+
+ match.setValues(start, end, match.getUrl(),
+ match.getLabel(), match.getTooltip(),
+ match.getIcon(), match.getColor(),
+ match.getMenuName(), match.getLocation());
+ return true;
+ }
+ return false;
+}
+
+bool LLUrlRegistry::hasUrl(const std::string &text)
+{
+ LLUrlMatch match;
+ return findUrl(text, match);
+}
+
+bool LLUrlRegistry::hasUrl(const LLWString &text)
+{
+ LLUrlMatch match;
+ return findUrl(text, match);
+}
+
+bool LLUrlRegistry::isUrl(const std::string &text)
+{
+ LLUrlMatch match;
+ if (findUrl(text, match))
+ {
+ return (match.getStart() == 0 && match.getEnd() >= text.size()-1);
+ }
+ return false;
+}
+
+bool LLUrlRegistry::isUrl(const LLWString &text)
+{
+ LLUrlMatch match;
+ if (findUrl(text, match))
+ {
+ return (match.getStart() == 0 && match.getEnd() >= text.size()-1);
+ }
+ return false;
+}
diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h
new file mode 100644
index 0000000000..399ee0a988
--- /dev/null
+++ b/indra/llui/llurlregistry.h
@@ -0,0 +1,99 @@
+/**
+ * @file llurlregistry.h
+ * @author Martin Reddy
+ * @brief Contains a set of Url types that can be matched in a string
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLURLREGISTRY_H
+#define LL_LLURLREGISTRY_H
+
+#include "llurlentry.h"
+#include "llurlmatch.h"
+#include "llsingleton.h"
+#include "llstring.h"
+
+#include <string>
+#include <vector>
+
+/// This default callback for findUrl() simply ignores any label updates
+void LLUrlRegistryNullCallback(const std::string &url, const std::string &label);
+
+///
+/// LLUrlRegistry is a singleton that contains a set of Url types that
+/// can be matched in string. E.g., http:// or secondlife:// Urls.
+///
+/// Clients call the findUrl() method on a string to locate the first
+/// occurence of a supported Urls in that string. If findUrl() returns
+/// true, the LLUrlMatch object will be updated to describe the Url
+/// that was matched, including a label that can be used to hyperlink
+/// the Url, an icon to display next to the Url, and a XUI menu that
+/// can be used as a popup context menu for that Url.
+///
+/// New Url types can be added to the registry with the registerUrl
+/// method. E.g., to add support for a new secondlife:///app/ Url.
+///
+/// Computing the label for a Url could involve a roundtrip request
+/// to the server (e.g., to find the actual agent or group name).
+/// As such, you can provide a callback method that will get invoked
+/// when a new label is available for one of your matched Urls.
+///
+class LLUrlRegistry : public LLSingleton<LLUrlRegistry>
+{
+public:
+ ~LLUrlRegistry();
+
+ /// add a new Url handler to the registry (will be freed on destruction)
+ void registerUrl(LLUrlEntryBase *url);
+
+ /// get the next Url in an input string, starting at a given character offset
+ /// your callback is invoked if the matched Url's label changes in the future
+ bool findUrl(const std::string &text, LLUrlMatch &match,
+ const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback);
+
+ /// a slightly less efficient version of findUrl for wide strings
+ bool findUrl(const LLWString &text, LLUrlMatch &match,
+ const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback);
+
+ // return true if the given string contains a URL that findUrl would match
+ bool hasUrl(const std::string &text);
+ bool hasUrl(const LLWString &text);
+
+ // return true if the given string is a URL that findUrl would match
+ bool isUrl(const std::string &text);
+ bool isUrl(const LLWString &text);
+
+private:
+ LLUrlRegistry();
+ friend class LLSingleton<LLUrlRegistry>;
+
+ std::vector<LLUrlEntryBase *> mUrlEntry;
+};
+
+#endif
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 2350ea6050..f1b08c380b 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -33,6 +33,7 @@
#include "linden_common.h"
+#define LLVIEW_CPP
#include "llview.h"
#include <cassert>
@@ -40,7 +41,6 @@
#include "llrender.h"
#include "llevent.h"
-#include "llfontgl.h"
#include "llfocusmgr.h"
#include "llrect.h"
#include "llstl.h"
@@ -49,6 +49,7 @@
#include "llwindow.h"
#include "v3color.h"
#include "lluictrlfactory.h"
+#include "lltooltip.h"
// for ui edit hack
#include "llbutton.h"
@@ -56,95 +57,106 @@
#include "lltexteditor.h"
#include "lltextbox.h"
-//HACK: this allows you to instantiate LLView from xml with "<view/>" which we don't want
-static LLRegisterWidget<LLView> r("view");
-
-BOOL LLView::sDebugRects = FALSE;
-BOOL LLView::sDebugKeys = FALSE;
S32 LLView::sDepth = 0;
-BOOL LLView::sDebugMouseHandling = FALSE;
+bool LLView::sDebugRects = false;
+bool LLView::sDebugRectsShowNames = true;
+bool LLView::sDebugKeys = false;
+bool LLView::sDebugMouseHandling = false;
std::string LLView::sMouseHandlerMessage;
-BOOL LLView::sEditingUI = FALSE;
BOOL LLView::sForceReshape = FALSE;
-LLView* LLView::sEditingUIView = NULL;
+std::set<LLView*> LLView::sPreviewHighlightedElements;
+BOOL LLView::sHighlightingDiffs = FALSE;
+LLView* LLView::sPreviewClickedElement = NULL;
+BOOL LLView::sDrawPreviewHighlights = FALSE;
S32 LLView::sLastLeftXML = S32_MIN;
S32 LLView::sLastBottomXML = S32_MIN;
+std::vector<LLViewDrawContext*> LLViewDrawContext::sDrawContextStack;
+
#if LL_DEBUG
BOOL LLView::sIsDrawing = FALSE;
#endif
-LLView::LLView() :
- mParentView(NULL),
- mReshapeFlags(FOLLOWS_NONE),
- mDefaultTabGroup(0),
- mEnabled(TRUE),
- mMouseOpaque(TRUE),
- mSoundFlags(MOUSE_UP), // default to only make sound on mouse up
- mSaveToXML(TRUE),
- mIsFocusRoot(FALSE),
- mLastVisible(TRUE),
- mUseBoundingRect(FALSE),
- mVisible(TRUE),
- mNextInsertionOrdinal(0),
- mHoverCursor(UI_CURSOR_ARROW)
-{
-}
-
-LLView::LLView(const std::string& name, BOOL mouse_opaque) :
+// Compiler optimization, generate extern template
+template class LLView* LLView::getChild<class LLView>(
+ const std::string& name, BOOL recurse) const;
+
+static LLDefaultChildRegistry::Register<LLView> r("view");
+
+LLView::Follows::Follows()
+: string(""),
+ flags("flags", FOLLOWS_LEFT | FOLLOWS_TOP)
+{}
+
+LLView::Params::Params()
+: name("name", std::string("unnamed")),
+ enabled("enabled", true),
+ visible("visible", true),
+ mouse_opaque("mouse_opaque", true),
+ follows("follows"),
+ hover_cursor("hover_cursor", "UI_CURSOR_ARROW"),
+ use_bounding_rect("use_bounding_rect", false),
+ tab_group("tab_group", 0),
+ default_tab_group("default_tab_group"),
+ tool_tip("tool_tip"),
+ sound_flags("sound_flags", MOUSE_UP),
+ layout("layout"),
+ rect("rect"),
+ bottom_delta("bottom_delta", S32_MAX),
+ top_pad("top_pad"),
+ top_delta("top_delta", S32_MAX),
+ left_pad("left_pad"),
+ left_delta("left_delta", S32_MAX),
+ center_horiz("center_horiz", false),
+ center_vert("center_vert", false),
+ from_xui("from_xui", false),
+ user_resize("user_resize"),
+ auto_resize("auto_resize"),
+ needs_translate("translate"),
+ xmlns("xmlns"),
+ xmlns_xsi("xmlns:xsi"),
+ xsi_schemaLocation("xsi:schemaLocation"),
+ xsi_type("xsi:type")
+
+{
+ addSynonym(rect, "");
+}
+
+LLView::LLView(const LLView::Params& p)
+: mName(p.name),
mParentView(NULL),
- mName(name),
mReshapeFlags(FOLLOWS_NONE),
- mDefaultTabGroup(0),
- mEnabled(TRUE),
- mMouseOpaque(mouse_opaque),
- mSoundFlags(MOUSE_UP), // default to only make sound on mouse up
- mSaveToXML(TRUE),
+ mFromXUI(p.from_xui),
mIsFocusRoot(FALSE),
- mLastVisible(TRUE),
- mUseBoundingRect(FALSE),
- mVisible(TRUE),
+ mLastVisible(FALSE),
mNextInsertionOrdinal(0),
- mHoverCursor(UI_CURSOR_ARROW)
-{
-}
-
-
-LLView::LLView(
- const std::string& name, const LLRect& rect, BOOL mouse_opaque, U32 reshape) :
- mParentView(NULL),
- mName(name),
- mRect(rect),
- mBoundingRect(rect),
- mReshapeFlags(reshape),
- mDefaultTabGroup(0),
- mEnabled(TRUE),
- mMouseOpaque(mouse_opaque),
- mSoundFlags(MOUSE_UP), // default to only make sound on mouse up
- mSaveToXML(TRUE),
- mIsFocusRoot(FALSE),
- mLastVisible(TRUE),
- mUseBoundingRect(FALSE),
- mVisible(TRUE),
- mNextInsertionOrdinal(0),
- mHoverCursor(UI_CURSOR_ARROW)
+ mHoverCursor(getCursorFromString(p.hover_cursor)),
+ mEnabled(p.enabled),
+ mVisible(p.visible),
+ mMouseOpaque(p.mouse_opaque),
+ mSoundFlags(p.sound_flags),
+ mUseBoundingRect(p.use_bounding_rect),
+ mDefaultTabGroup(p.default_tab_group),
+ mLastTabGroup(0),
+ mToolTipMsg((LLStringExplicit)p.tool_tip()),
+ mDefaultWidgets(NULL)
{
+ // create rect first, as this will supply initial follows flags
+ setShape(p.rect);
+ parseFollowsFlags(p);
}
-
LLView::~LLView()
{
+ dirtyRect();
//llinfos << "Deleting view " << mName << ":" << (void*) this << llendl;
// llassert(LLView::sIsDrawing == FALSE);
- if( gFocusMgr.getKeyboardFocus() == this )
- {
- llwarns << "View holding keyboard focus deleted: " << getName() << ". Keyboard focus removed." << llendl;
- gFocusMgr.removeKeyboardFocusWithoutCallback( this );
- }
-
+
+// llassert_always(sDepth == 0); // avoid deleting views while drawing! It can subtly break list iterators
+
if( hasMouseCapture() )
{
- llwarns << "View holding mouse capture deleted: " << getName() << ". Mouse capture removed." << llendl;
+ //llwarns << "View holding mouse capture deleted: " << getName() << ". Mouse capture removed." << llendl;
gFocusMgr.removeMouseCaptureWithoutCallback( this );
}
@@ -155,22 +167,13 @@ LLView::~LLView()
mParentView->removeChild(this);
}
- dispatch_list_t::iterator itor;
- for (itor = mDispatchList.begin(); itor != mDispatchList.end(); ++itor)
+ if (mDefaultWidgets)
{
- (*itor).second->clearDispatchers();
+ std::for_each(mDefaultWidgets->begin(), mDefaultWidgets->end(),
+ DeletePairedPointer());
+ delete mDefaultWidgets;
+ mDefaultWidgets = NULL;
}
-
- std::for_each(mFloaterControls.begin(), mFloaterControls.end(),
- DeletePairedPointer());
- std::for_each(mDummyWidgets.begin(), mDummyWidgets.end(),
- DeletePairedPointer());
-}
-
-// virtual
-BOOL LLView::isView() const
-{
- return TRUE;
}
// virtual
@@ -185,7 +188,6 @@ BOOL LLView::isPanel() const
return FALSE;
}
-// virtual
void LLView::setToolTip(const LLStringExplicit& msg)
{
mToolTipMsg = msg;
@@ -224,27 +226,38 @@ BOOL LLView::getUseBoundingRect()
}
// virtual
-const std::string& LLView::getName() const
+std::string LLView::getName() const
{
- static const std::string unnamed("(no name)");
- return mName.empty() ? unnamed : mName;
+ return mName.empty() ? std::string("(no name)") : mName;
}
void LLView::sendChildToFront(LLView* child)
{
+// llassert_always(sDepth == 0); // Avoid re-ordering while drawing; it can cause subtle iterator bugs
if (child && child->getParent() == this)
{
- mChildList.remove( child );
- mChildList.push_front(child);
+ // minor optimization, but more importantly,
+ // won't temporarily create an empty list
+ if (child != mChildList.front())
+ {
+ mChildList.remove( child );
+ mChildList.push_front(child);
+ }
}
}
void LLView::sendChildToBack(LLView* child)
{
+// llassert_always(sDepth == 0); // Avoid re-ordering while drawing; it can cause subtle iterator bugs
if (child && child->getParent() == this)
{
- mChildList.remove( child );
- mChildList.push_back(child);
+ // minor optimization, but more importantly,
+ // won't temporarily create an empty list
+ if (child != mChildList.back())
+ {
+ mChildList.remove( child );
+ mChildList.push_back(child);
+ }
}
}
@@ -264,12 +277,18 @@ void LLView::moveChildToBackOfTabGroup(LLUICtrl* child)
}
}
-void LLView::addChild(LLView* child, S32 tab_group)
+// virtual
+bool LLView::addChild(LLView* child, S32 tab_group)
{
+ if (!child)
+ {
+ return false;
+ }
if (mParentView == child)
{
llerrs << "Adding view " << child->getName() << " as child of itself" << llendl;
}
+
// remove from current parent
if (child->mParentView)
{
@@ -282,55 +301,46 @@ void LLView::addChild(LLView* child, S32 tab_group)
// add to ctrl list if is LLUICtrl
if (child->isCtrl())
{
- // controls are stored in reverse order from render order
- addCtrlAtEnd((LLUICtrl*) child, tab_group);
+ LLUICtrl* ctrl = static_cast<LLUICtrl*>(child);
+ mCtrlOrder.insert(tab_order_pair_t(ctrl,
+ tab_order_t(tab_group, mNextInsertionOrdinal)));
+
+ mNextInsertionOrdinal++;
}
child->mParentView = this;
updateBoundingRect();
+ mLastTabGroup = tab_group;
+ return true;
}
-void LLView::addChildAtEnd(LLView* child, S32 tab_group)
+bool LLView::addChildInBack(LLView* child, S32 tab_group)
{
- if (mParentView == child)
- {
- llerrs << "Adding view " << child->getName() << " as child of itself" << llendl;
- }
- // remove from current parent
- if (child->mParentView)
+ if(addChild(child, tab_group))
{
- child->mParentView->removeChild(child);
+ sendChildToBack(child);
+ return true;
}
- // add to back of child list
- mChildList.push_back(child);
-
- // add to ctrl list if is LLUICtrl
- if (child->isCtrl())
- {
- // controls are stored in reverse order from render order
- addCtrl((LLUICtrl*) child, tab_group);
- }
-
- child->mParentView = this;
- updateBoundingRect();
+ return false;
}
// remove the specified child from the view, and set it's parent to NULL.
-void LLView::removeChild(LLView* child, BOOL deleteIt)
+void LLView::removeChild(LLView* child)
{
+ //llassert_always(sDepth == 0); // Avoid re-ordering while drawing; it can cause subtle iterator bugs
if (child->mParentView == this)
{
mChildList.remove( child );
child->mParentView = NULL;
if (child->isCtrl())
{
- removeCtrl((LLUICtrl*)child);
- }
- if (deleteIt)
- {
- delete child;
+ child_tab_order_t::iterator found = mCtrlOrder.find(static_cast<LLUICtrl*>(child));
+ if(found != mCtrlOrder.end())
+ {
+ mCtrlOrder.erase(found);
+ }
}
}
else
@@ -340,28 +350,6 @@ void LLView::removeChild(LLView* child, BOOL deleteIt)
updateBoundingRect();
}
-void LLView::addCtrlAtEnd(LLUICtrl* ctrl, S32 tab_group)
-{
- mCtrlOrder.insert(tab_order_pair_t(ctrl,
- tab_order_t(tab_group, mNextInsertionOrdinal++)));
-}
-
-void LLView::addCtrl( LLUICtrl* ctrl, S32 tab_group)
-{
- // add to front of list by using negative ordinal, which monotonically increases
- mCtrlOrder.insert(tab_order_pair_t(ctrl,
- tab_order_t(tab_group, -1 * mNextInsertionOrdinal++)));
-}
-
-void LLView::removeCtrl(LLUICtrl* ctrl)
-{
- child_tab_order_t::iterator found = mCtrlOrder.find(ctrl);
- if(found != mCtrlOrder.end())
- {
- mCtrlOrder.erase(found);
- }
-}
-
LLView::ctrl_list_t LLView::getCtrlList() const
{
ctrl_list_t controls;
@@ -411,32 +399,28 @@ bool LLCompareByTabOrder::operator() (const LLView* const a, const LLView* const
return (a_score == b_score) ? a < b : a_score < b_score;
}
-BOOL LLView::isInVisibleChain() const
+bool LLView::trueToRoot(const boost::function<bool (const LLView*)>& predicate) const
{
const LLView* cur_view = this;
while(cur_view)
{
- if (!cur_view->getVisible())
+ if(!predicate(cur_view))
{
- return FALSE;
+ return false;
}
cur_view = cur_view->getParent();
}
- return TRUE;
+ return true;
+}
+
+BOOL LLView::isInVisibleChain() const
+{
+ return trueToRoot(&LLView::getVisible);
}
BOOL LLView::isInEnabledChain() const
{
- const LLView* cur_view = this;
- while(cur_view)
- {
- if (!cur_view->getEnabled())
- {
- return FALSE;
- }
- cur_view = cur_view->getParent();
- }
- return TRUE;
+ return trueToRoot(&LLView::getEnabled);
}
// virtual
@@ -463,31 +447,33 @@ void LLView::setEnabled(BOOL enabled)
}
//virtual
-BOOL LLView::setLabelArg( const std::string& key, const LLStringExplicit& text )
+bool LLView::isAvailable() const
{
- return FALSE;
+ return isInEnabledChain() && isInVisibleChain();
}
-//virtual
-LLRect LLView::getSnapRect() const
+//static
+bool LLView::isAvailable(const LLView* view)
{
- return mRect;
+ return view && view->isAvailable();
}
//virtual
-LLRect LLView::getRequiredRect()
+BOOL LLView::setLabelArg( const std::string& key, const LLStringExplicit& text )
{
- return mRect;
+ return FALSE;
}
//virtual
-void LLView::onFocusLost()
+LLRect LLView::getSnapRect() const
{
+ return mRect;
}
//virtual
-void LLView::onFocusReceived()
+LLRect LLView::getRequiredRect()
{
+ return mRect;
}
BOOL LLView::focusNextRoot()
@@ -617,14 +603,15 @@ void LLView::setVisible(BOOL visible)
if (!getParent() || getParent()->isInVisibleChain())
{
// tell all children of this view that the visibility may have changed
- onVisibilityChange( visible );
+ dirtyRect();
+ handleVisibilityChange( visible );
}
updateBoundingRect();
}
}
// virtual
-void LLView::onVisibilityChange ( BOOL new_visibility )
+void LLView::handleVisibilityChange ( BOOL new_visibility )
{
for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
{
@@ -632,7 +619,7 @@ void LLView::onVisibilityChange ( BOOL new_visibility )
// only views that are themselves visible will have their overall visibility affected by their ancestors
if (viewp->getVisible())
{
- viewp->onVisibilityChange ( new_visibility );
+ viewp->handleVisibilityChange ( new_visibility );
}
}
}
@@ -651,119 +638,111 @@ BOOL LLView::canSnapTo(const LLView* other_view)
}
// virtual
-void LLView::snappedTo(const LLView* snap_view)
+void LLView::setSnappedTo(const LLView* snap_view)
{
}
BOOL LLView::handleHover(S32 x, S32 y, MASK mask)
{
- BOOL handled = childrenHandleHover( x, y, mask ) != NULL;
- if( !handled
- && blockMouseEvent(x, y) )
- {
- LLUI::sWindow->setCursor(mHoverCursor);
- lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;
- handled = TRUE;
- }
+ return childrenHandleHover( x, y, mask ) != NULL;
+}
- return handled;
+void LLView::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+ //llinfos << "Mouse entered " << getName() << llendl;
}
-std::string LLView::getShowNamesToolTip()
+void LLView::onMouseLeave(S32 x, S32 y, MASK mask)
{
- LLView* view = getParent();
- std::string name;
- std::string tool_tip = mName;
+ //llinfos << "Mouse left " << getName() << llendl;
+}
- while (view)
- {
- name = view->getName();
- if (name == "root") break;
+LLView* LLView::childrenHandleToolTip(S32 x, S32 y, MASK mask)
+{
+ LLView* handled_view = NULL;
+ for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
+ {
+ LLView* viewp = *child_it;
+ S32 local_x = x - viewp->getRect().mLeft;
+ S32 local_y = y - viewp->getRect().mBottom;
+ if(!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible())
+ {
+ continue;
+ }
- if (view->getToolTip().find(".xml") != std::string::npos)
+ if (viewp->handleToolTip(local_x, local_y, mask) )
{
- tool_tip = view->getToolTip() + "/" + tool_tip;
+ if (sDebugMouseHandling)
+ {
+ sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
+ }
+
+ handled_view = viewp;
break;
}
- else
+
+ if (viewp->blockMouseEvent(local_x, local_y))
{
- tool_tip = view->getName() + "/" + tool_tip;
+ handled_view = viewp;
+ break;
}
-
- view = view->getParent();
}
-
- return "/" + tool_tip;
+ return handled_view;
}
-BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
+LLView* LLView::childFromPoint(S32 x, S32 y)
{
- BOOL handled = FALSE;
-
- std::string tool_tip;
-
+ if (!getVisible() )
+ return false;
for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
{
LLView* viewp = *child_it;
- S32 local_x = x - viewp->mRect.mLeft;
- S32 local_y = y - viewp->mRect.mBottom;
- // Allow tooltips for disabled views so we can explain to the user why
- // the view is disabled. JC
- if( viewp->pointInView(local_x, local_y)
- && viewp->getVisible()
- // && viewp->getEnabled()
- && viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ))
- {
- // child provided a tooltip, just return
- if (!msg.empty()) return TRUE;
-
- // otherwise, one of our children ate the event so don't traverse
- // siblings however, our child did not actually provide a tooltip
- // so we might want to
- handled = TRUE;
- break;
+ S32 local_x = x - viewp->getRect().mLeft;
+ S32 local_y = y - viewp->getRect().mBottom;
+ if (!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible() )
+ {
+ continue;
}
- }
+ return viewp;
- // get our own tooltip
- tool_tip = mToolTipMsg.getString();
- if (
- LLUI::sShowXUINames
- && (tool_tip.find(".xml", 0) == std::string::npos)
- && (mName.find("Drag", 0) == std::string::npos))
- {
- tool_tip = getShowNamesToolTip();
}
+ return 0;
+}
- BOOL show_names_text_box = LLUI::sShowXUINames && dynamic_cast<LLTextBox*>(this) != NULL;
+BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = FALSE;
- // don't allow any siblings to handle this event
- // even if we don't have a tooltip
- if (getMouseOpaque() || show_names_text_box)
+ // parents provide tooltips first, which are optionally
+ // overridden by children, in case child is mouse_opaque
+ if (!mToolTipMsg.empty())
{
+ // allow "scrubbing" over ui by showing next tooltip immediately
+ // if previous one was still visible
+ F32 timeout = LLToolTipMgr::instance().toolTipVisible()
+ ? 0.f
+ : LLUI::sSettingGroups["config"]->getF32( "ToolTipDelay" );
+ LLToolTipMgr::instance().show(LLToolTip::Params()
+ .message(mToolTipMsg)
+ .sticky_rect(calcScreenRect())
+ .delay_time(timeout));
+
handled = TRUE;
}
- if(!tool_tip.empty())
+ // child tooltips will override our own
+ LLView* child_handler = childrenHandleToolTip(x, y, mask);
+ if (child_handler)
{
- msg = tool_tip;
-
- // Convert rect local to screen coordinates
- localPointToScreen(
- 0, 0,
- &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
- localPointToScreen(
- mRect.getWidth(), mRect.getHeight(),
- &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) );
-
handled = TRUE;
}
return handled;
}
-
BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
{
BOOL handled = FALSE;
@@ -844,20 +823,7 @@ BOOL LLView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EAcceptance* accept,
std::string& tooltip_msg)
{
- // CRO this is an experiment to allow drag and drop into object inventory based on the DragAndDrop tool's permissions rather than the parent
- BOOL handled = childrenHandleDragAndDrop( x, y, mask, drop,
- cargo_type,
- cargo_data,
- accept,
- tooltip_msg) != NULL;
- if( !handled && blockMouseEvent(x, y) )
- {
- *accept = ACCEPT_NO;
- handled = TRUE;
- lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLView " << getName() << llendl;
- }
-
- return handled;
+ return childrenHandleDragAndDrop( x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL;
}
LLView* LLView::childrenHandleDragAndDrop(S32 x, S32 y, MASK mask,
@@ -867,28 +833,33 @@ LLView* LLView::childrenHandleDragAndDrop(S32 x, S32 y, MASK mask,
EAcceptance* accept,
std::string& tooltip_msg)
{
- LLView* handled_view = FALSE;
- // CRO this is an experiment to allow drag and drop into object inventory based on the DragAndDrop tool's permissions rather than the parent
- if( getVisible() )
-// if( getVisible() && getEnabled() )
+ LLView* handled_view = NULL;
+ for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
{
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
+ LLView* viewp = *child_it;
+ S32 local_x = x - viewp->getRect().mLeft;
+ S32 local_y = y - viewp->getRect().mBottom;
+ if( !viewp->pointInView(local_x, local_y) ||
+ !viewp->getVisible() ||
+ !viewp->getEnabled())
{
- LLView* viewp = *child_it;
- S32 local_x = x - viewp->getRect().mLeft;
- S32 local_y = y - viewp->getRect().mBottom;
- if( viewp->pointInView(local_x, local_y) &&
- viewp->getVisible() &&
- viewp->getEnabled() &&
- viewp->handleDragAndDrop(local_x, local_y, mask, drop,
- cargo_type,
- cargo_data,
- accept,
- tooltip_msg))
- {
- handled_view = viewp;
- break;
- }
+ continue;
+ }
+ if (viewp->handleDragAndDrop(local_x, local_y, mask, drop,
+ cargo_type,
+ cargo_data,
+ accept,
+ tooltip_msg))
+ {
+ handled_view = viewp;
+ break;
+ }
+
+ if (viewp->blockMouseEvent(x, y))
+ {
+ *accept = ACCEPT_NO;
+ handled_view = viewp;
+ break;
}
}
return handled_view;
@@ -905,110 +876,42 @@ BOOL LLView::hasMouseCapture()
BOOL LLView::handleMouseUp(S32 x, S32 y, MASK mask)
{
- BOOL handled = childrenHandleMouseUp( x, y, mask ) != NULL;
- if( !handled && blockMouseEvent(x, y) )
- {
- handled = TRUE;
- }
- return handled;
+ return childrenHandleMouseUp( x, y, mask ) != NULL;
}
BOOL LLView::handleMouseDown(S32 x, S32 y, MASK mask)
{
- LLView* handled_view = childrenHandleMouseDown( x, y, mask );
- BOOL handled = (handled_view != NULL);
- if( !handled && blockMouseEvent(x, y) )
- {
- handled = TRUE;
- handled_view = this;
- }
-
- // HACK If we're editing UI, select the leaf view that ate the click.
- if (sEditingUI && handled_view)
- {
- // need to find leaf views, big hack
- LLButton* buttonp = dynamic_cast<LLButton*>(handled_view);
- LLLineEditor* line_editorp = dynamic_cast<LLLineEditor*>(handled_view);
- LLTextEditor* text_editorp = dynamic_cast<LLTextEditor*>(handled_view);
- LLTextBox* text_boxp = dynamic_cast<LLTextBox*>(handled_view);
- if (buttonp
- || line_editorp
- || text_editorp
- || text_boxp)
- {
- sEditingUIView = handled_view;
- }
- }
-
- return handled;
+ return childrenHandleMouseDown( x, y, mask ) != NULL;
}
BOOL LLView::handleDoubleClick(S32 x, S32 y, MASK mask)
{
- BOOL handled = childrenHandleDoubleClick( x, y, mask ) != NULL;
- if( !handled && blockMouseEvent(x, y) )
- {
- handleMouseDown(x, y, mask);
- handled = TRUE;
- }
- return handled;
+ return childrenHandleDoubleClick( x, y, mask ) != NULL;
}
BOOL LLView::handleScrollWheel(S32 x, S32 y, S32 clicks)
{
- BOOL handled = FALSE;
- if( getVisible() && getEnabled() )
- {
- handled = childrenHandleScrollWheel( x, y, clicks ) != NULL;
- if( !handled && blockMouseEvent(x, y) )
- {
- handled = TRUE;
- }
- }
- return handled;
+ return childrenHandleScrollWheel( x, y, clicks ) != NULL;
}
BOOL LLView::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
- BOOL handled = childrenHandleRightMouseDown( x, y, mask ) != NULL;
- if( !handled && blockMouseEvent(x, y) )
- {
- handled = TRUE;
- }
- return handled;
+ return childrenHandleRightMouseDown( x, y, mask ) != NULL;
}
BOOL LLView::handleRightMouseUp(S32 x, S32 y, MASK mask)
{
- BOOL handled = childrenHandleRightMouseUp( x, y, mask ) != NULL;
- if( !handled && blockMouseEvent(x, y) )
- {
- handled = TRUE;
- }
- return handled;
+ return childrenHandleRightMouseUp( x, y, mask ) != NULL;
}
BOOL LLView::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
{
- LLView* handled_view = childrenHandleMiddleMouseDown( x, y, mask );
- BOOL handled = (handled_view != NULL);
- if( !handled && blockMouseEvent(x, y) )
- {
- handled = TRUE;
- handled_view = this;
- }
-
- return handled;
+ return childrenHandleMiddleMouseDown( x, y, mask ) != NULL;
}
BOOL LLView::handleMiddleMouseUp(S32 x, S32 y, MASK mask)
{
- BOOL handled = childrenHandleMiddleMouseUp( x, y, mask ) != NULL;
- if( !handled && blockMouseEvent(x, y) )
- {
- handled = TRUE;
- }
- return handled;
+ return childrenHandleMiddleMouseUp( x, y, mask ) != NULL;
}
@@ -1022,14 +925,18 @@ LLView* LLView::childrenHandleScrollWheel(S32 x, S32 y, S32 clicks)
LLView* viewp = *child_it;
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if (viewp->pointInView(local_x, local_y)
- && viewp->getVisible()
- && viewp->getEnabled()
- && viewp->handleScrollWheel( local_x, local_y, clicks ))
+ if (!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible()
+ || !viewp->getEnabled())
+ {
+ continue;
+ }
+
+ if (viewp->handleScrollWheel( local_x, local_y, clicks ))
{
if (sDebugMouseHandling)
{
- sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage;
+ sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
}
handled_view = viewp;
@@ -1050,19 +957,31 @@ LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask)
LLView* viewp = *child_it;
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if(viewp->pointInView(local_x, local_y) &&
- viewp->getVisible() &&
- viewp->getEnabled() &&
- viewp->handleHover(local_x, local_y, mask) )
+ if(!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible()
+ || !viewp->getEnabled())
+ {
+ continue;
+ }
+
+ if (viewp->handleHover(local_x, local_y, mask) )
{
if (sDebugMouseHandling)
{
- sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage;
+ sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
}
handled_view = viewp;
break;
}
+
+ if (viewp->blockMouseEvent(local_x, local_y))
+ {
+ LLUI::sWindow->setCursor(viewp->getHoverCursor());
+
+ handled_view = viewp;
+ break;
+ }
}
}
return handled_view;
@@ -1128,18 +1047,28 @@ LLView* LLView::childrenHandleMouseDown(S32 x, S32 y, MASK mask)
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if (viewp->pointInView(local_x, local_y) &&
- viewp->getVisible() &&
- viewp->getEnabled() &&
- viewp->handleMouseDown( local_x, local_y, mask ))
+ if (!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible()
+ || !viewp->getEnabled())
+ {
+ continue;
+ }
+
+ if(viewp->handleMouseDown( local_x, local_y, mask ))
{
if (sDebugMouseHandling)
{
- sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage;
+ sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
}
handled_view = viewp;
break;
}
+
+ if(viewp->blockMouseEvent(local_x, local_y))
+ {
+ handled_view = viewp;
+ break;
+ }
}
return handled_view;
}
@@ -1155,15 +1084,27 @@ LLView* LLView::childrenHandleRightMouseDown(S32 x, S32 y, MASK mask)
LLView* viewp = *child_it;
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if (viewp->pointInView(local_x, local_y) &&
- viewp->getVisible() &&
- viewp->getEnabled() &&
- viewp->handleRightMouseDown( local_x, local_y, mask ))
+
+ if (!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible()
+ || !viewp->getEnabled())
+ {
+ continue;
+ }
+
+ if (viewp->handleRightMouseDown( local_x, local_y, mask ))
{
if (sDebugMouseHandling)
{
- sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage;
+ sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
}
+
+ handled_view = viewp;
+ break;
+ }
+
+ if (viewp->blockMouseEvent(local_x, local_y))
+ {
handled_view = viewp;
break;
}
@@ -1183,18 +1124,28 @@ LLView* LLView::childrenHandleMiddleMouseDown(S32 x, S32 y, MASK mask)
LLView* viewp = *child_it;
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if (viewp->pointInView(local_x, local_y) &&
- viewp->getVisible() &&
- viewp->getEnabled() &&
- viewp->handleMiddleMouseDown( local_x, local_y, mask ))
+ if (!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible()
+ || !viewp->getEnabled())
+ {
+ continue;
+ }
+
+ if(viewp->handleMiddleMouseDown( local_x, local_y, mask ))
{
if (sDebugMouseHandling)
{
- sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage;
+ sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
}
handled_view = viewp;
break;
}
+
+ if (viewp->blockMouseEvent(local_x, local_y))
+ {
+ handled_view = viewp;
+ break;
+ }
}
}
return handled_view;
@@ -1211,18 +1162,29 @@ LLView* LLView::childrenHandleDoubleClick(S32 x, S32 y, MASK mask)
LLView* viewp = *child_it;
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if (viewp->pointInView(local_x, local_y) &&
- viewp->getVisible() &&
- viewp->getEnabled() &&
- viewp->handleDoubleClick( local_x, local_y, mask ))
+
+ if (!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible()
+ || !viewp->getEnabled())
+ {
+ continue;
+ }
+
+ if (viewp->handleDoubleClick( local_x, local_y, mask ))
{
if (sDebugMouseHandling)
{
- sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage;
+ sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
}
handled_view = viewp;
break;
}
+
+ if (viewp->blockMouseEvent(local_x, local_y))
+ {
+ handled_view = viewp;
+ break;
+ }
}
}
return handled_view;
@@ -1238,21 +1200,28 @@ LLView* LLView::childrenHandleMouseUp(S32 x, S32 y, MASK mask)
LLView* viewp = *child_it;
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if (!viewp->pointInView(local_x, local_y))
- continue;
- if (!viewp->getVisible())
- continue;
- if (!viewp->getEnabled())
+ if (!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible()
+ || !viewp->getEnabled())
+ {
continue;
+ }
+
if (viewp->handleMouseUp( local_x, local_y, mask ))
{
if (sDebugMouseHandling)
{
- sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage;
+ sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
}
handled_view = viewp;
break;
}
+
+ if (viewp->blockMouseEvent(local_x, local_y))
+ {
+ handled_view = viewp;
+ break;
+ }
}
}
return handled_view;
@@ -1268,18 +1237,28 @@ LLView* LLView::childrenHandleRightMouseUp(S32 x, S32 y, MASK mask)
LLView* viewp = *child_it;
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if (viewp->pointInView(local_x, local_y) &&
- viewp->getVisible() &&
- viewp->getEnabled() &&
- viewp->handleRightMouseUp( local_x, local_y, mask ))
+ if (!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible()
+ || !viewp->getEnabled() )
+ {
+ continue;
+ }
+
+ if(viewp->handleRightMouseUp( local_x, local_y, mask ))
{
if (sDebugMouseHandling)
{
- sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage;
+ sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
}
handled_view = viewp;
break;
}
+
+ if(viewp->blockMouseEvent(local_x, local_y))
+ {
+ handled_view = viewp;
+ break;
+ }
}
}
return handled_view;
@@ -1295,18 +1274,28 @@ LLView* LLView::childrenHandleMiddleMouseUp(S32 x, S32 y, MASK mask)
LLView* viewp = *child_it;
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if (viewp->pointInView(local_x, local_y) &&
- viewp->getVisible() &&
- viewp->getEnabled() &&
- viewp->handleMiddleMouseUp( local_x, local_y, mask ))
+ if (!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible()
+ || !viewp->getEnabled())
+ {
+ continue;
+ }
+
+ if(viewp->handleMiddleMouseUp( local_x, local_y, mask ))
{
if (sDebugMouseHandling)
{
- sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage;
+ sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
}
handled_view = viewp;
break;
}
+
+ if (viewp->blockMouseEvent(local_x, local_y))
+ {
+ handled_view = viewp;
+ break;
+ }
}
}
return handled_view;
@@ -1314,67 +1303,77 @@ LLView* LLView::childrenHandleMiddleMouseUp(S32 x, S32 y, MASK mask)
void LLView::draw()
{
- if (sDebugRects)
- {
- drawDebugRect();
-
- // Check for bogus rectangle
- if (getRect().mRight <= getRect().mLeft
- || getRect().mTop <= getRect().mBottom)
- {
- llwarns << "Bogus rectangle for " << getName() << " with " << mRect << llendl;
- }
- }
-
- LLRect rootRect = getRootView()->getRect();
- LLRect screenRect;
+ drawChildren();
+}
- // draw focused control on top of everything else
- LLView* focus_view = gFocusMgr.getKeyboardFocus();
- if (focus_view && focus_view->getParent() != this)
+void LLView::drawChildren()
+{
+ if (!mChildList.empty())
{
- focus_view = NULL;
- }
+ LLRect rootRect = getRootView()->getRect();
+ LLRect screenRect;
- ++sDepth;
- for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend(); ++child_iter)
- {
- LLView *viewp = *child_iter;
+ ++sDepth;
- if (viewp->getVisible() && viewp != focus_view && viewp->getRect().isValid())
+ for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend();) // ++child_iter)
{
- // Only draw views that are within the root view
- localRectToScreen(viewp->getRect(),&screenRect);
- if ( rootRect.rectInRect(&screenRect) )
+ child_list_reverse_iter_t child = child_iter++;
+ LLView *viewp = *child;
+
+ if (viewp->getVisible() && viewp->getRect().isValid())
{
- glMatrixMode(GL_MODELVIEW);
- LLUI::pushMatrix();
+ // Only draw views that are within the root view
+ localRectToScreen(viewp->getRect(),&screenRect);
+ if ( rootRect.overlaps(screenRect) && LLUI::sDirtyRect.overlaps(screenRect))
{
- LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f);
- viewp->draw();
+ glMatrixMode(GL_MODELVIEW);
+ LLUI::pushMatrix();
+ {
+ LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f);
+ viewp->draw();
+
+ if (sDebugRects)
+ {
+ viewp->drawDebugRect();
+
+ // Check for bogus rectangle
+ if (!getRect().isValid())
+ {
+ llwarns << "Bogus rectangle for " << getName() << " with " << mRect << llendl;
+ }
+ }
+ }
+ LLUI::popMatrix();
}
- LLUI::popMatrix();
}
- }
+ }
+ --sDepth;
}
- --sDepth;
- if (focus_view && focus_view->getVisible())
- {
- drawChild(focus_view);
- }
+ gGL.getTexUnit(0)->disable();
+}
- // HACK
- if (sEditingUI && this == sEditingUIView)
- {
- drawDebugRect();
+void LLView::dirtyRect()
+{
+ LLView* child = getParent();
+ LLView* parent = child ? child->getParent() : NULL;
+ LLView* cur = this;
+ while (child && parent && parent->getParent())
+ { //find third to top-most view
+ cur = child;
+ child = parent;
+ parent = parent->getParent();
}
+
+ LLUI::dirtyRect(cur->calcScreenRect());
}
//Draw a box for debugging.
void LLView::drawDebugRect()
{
+ std::set<LLView*>::iterator preview_iter = std::find(sPreviewHighlightedElements.begin(), sPreviewHighlightedElements.end(), this); // figure out if it's a previewed element
+
LLUI::pushMatrix();
{
// drawing solids requires texturing be disabled
@@ -1388,10 +1387,18 @@ void LLView::drawDebugRect()
LLRect debug_rect = mUseBoundingRect ? mBoundingRect : mRect;
// draw red rectangle for the border
- LLColor4 border_color(0.f, 0.f, 0.f, 1.f);
- if (sEditingUI)
+ LLColor4 border_color(0.25f, 0.25f, 0.25f, 1.f);
+ if(preview_iter != sPreviewHighlightedElements.end())
{
- border_color.mV[0] = 1.f;
+ if(LLView::sPreviewClickedElement && this == sPreviewClickedElement)
+ {
+ border_color = LLColor4::red;
+ }
+ else
+ {
+ static LLUIColor scroll_highlighted_color = LLUIColorTable::instance().getColor("ScrollHighlightedColor");
+ border_color = scroll_highlighted_color;
+ }
}
else
{
@@ -1414,8 +1421,10 @@ void LLView::drawDebugRect()
gGL.vertex2i(0, debug_rect.getHeight() - 1);
gGL.end();
- // Draw the name if it's not a leaf node
- if (mChildList.size() && !sEditingUI)
+ // Draw the name if it's not a leaf node or not in editing or preview mode
+ if (mChildList.size()
+ && preview_iter == sPreviewHighlightedElements.end()
+ && sDebugRectsShowNames)
{
//char temp[256];
S32 x, y;
@@ -1425,7 +1434,7 @@ void LLView::drawDebugRect()
std::string debug_text = llformat("%s (%d x %d)", getName().c_str(),
debug_rect.getWidth(), debug_rect.getHeight());
LLFontGL::getFontSansSerifSmall()->renderUTF8(debug_text, 0, (F32)x, (F32)y, border_color,
- LLFontGL::HCENTER, LLFontGL::BASELINE, LLFontGL::NORMAL,
+ LLFontGL::HCENTER, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
S32_MAX, S32_MAX, NULL, FALSE);
}
}
@@ -1529,45 +1538,53 @@ void LLView::reshape(S32 width, S32 height, BOOL called_from_parent)
updateBoundingRect();
}
-void LLView::updateBoundingRect()
+LLRect LLView::calcBoundingRect()
{
- if (isDead()) return;
+ LLRect local_bounding_rect = LLRect::null;
- if (mUseBoundingRect)
+ child_list_const_iter_t child_it;
+ for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
{
- LLRect local_bounding_rect = LLRect::null;
-
- child_list_const_iter_t child_it;
- for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
+ LLView* childp = *child_it;
+ // ignore invisible and "top" children when calculating bounding rect
+ // such as combobox popups
+ if (!childp->getVisible() || childp == gFocusMgr.getTopCtrl())
{
- LLView* childp = *child_it;
- // ignore invisible and "top" children when calculating bounding rect
- // such as combobox popups
- if (!childp->getVisible() || childp == gFocusMgr.getTopCtrl())
- {
- continue;
- }
+ continue;
+ }
- LLRect child_bounding_rect = childp->getBoundingRect();
+ LLRect child_bounding_rect = childp->getBoundingRect();
- if (local_bounding_rect.isNull())
- {
- // start out with bounding rect equal to first visible child's bounding rect
- local_bounding_rect = child_bounding_rect;
- }
- else
+ if (local_bounding_rect.isEmpty())
+ {
+ // start out with bounding rect equal to first visible child's bounding rect
+ local_bounding_rect = child_bounding_rect;
+ }
+ else
+ {
+ // accumulate non-null children rectangles
+ if (!child_bounding_rect.isEmpty())
{
- // accumulate non-null children rectangles
- if (!child_bounding_rect.isNull())
- {
- local_bounding_rect.unionWith(child_bounding_rect);
- }
+ local_bounding_rect.unionWith(child_bounding_rect);
}
}
+ }
+
+ // convert to parent-relative coordinates
+ local_bounding_rect.translate(mRect.mLeft, mRect.mBottom);
+ return local_bounding_rect;
+}
+
- mBoundingRect = local_bounding_rect;
- // translate into parent-relative coordinates
- mBoundingRect.translate(mRect.mLeft, mRect.mBottom);
+void LLView::updateBoundingRect()
+{
+ if (isDead()) return;
+
+ LLRect cur_rect = mBoundingRect;
+
+ if (mUseBoundingRect)
+ {
+ mBoundingRect = calcBoundingRect();
}
else
{
@@ -1579,17 +1596,36 @@ void LLView::updateBoundingRect()
{
getParent()->updateBoundingRect();
}
+
+ if (mBoundingRect != cur_rect)
+ {
+ dirtyRect();
+ }
+
}
-LLRect LLView::getScreenRect() const
+LLRect LLView::calcScreenRect() const
{
- // *FIX: check for one-off error
LLRect screen_rect;
localPointToScreen(0, 0, &screen_rect.mLeft, &screen_rect.mBottom);
localPointToScreen(getRect().getWidth(), getRect().getHeight(), &screen_rect.mRight, &screen_rect.mTop);
return screen_rect;
}
+LLRect LLView::calcScreenBoundingRect() const
+{
+ LLRect screen_rect;
+ // get bounding rect, if used
+ LLRect bounding_rect = mUseBoundingRect ? mBoundingRect : mRect;
+
+ // convert to local coordinates, as defined by mRect
+ bounding_rect.translate(-mRect.mLeft, -mRect.mBottom);
+
+ localPointToScreen(bounding_rect.mLeft, bounding_rect.mBottom, &screen_rect.mLeft, &screen_rect.mBottom);
+ localPointToScreen(bounding_rect.mRight, bounding_rect.mTop, &screen_rect.mRight, &screen_rect.mTop);
+ return screen_rect;
+}
+
LLRect LLView::getLocalBoundingRect() const
{
LLRect local_bounding_rect = getBoundingRect();
@@ -1636,7 +1672,7 @@ BOOL LLView::hasAncestor(const LLView* parentp) const
BOOL LLView::childHasKeyboardFocus( const std::string& childname ) const
{
- LLView *child = getChildView(childname, TRUE, FALSE);
+ LLView *child = findChildView(childname, TRUE);
if (child)
{
return gFocusMgr.childHasKeyboardFocus(child);
@@ -1651,14 +1687,31 @@ BOOL LLView::childHasKeyboardFocus( const std::string& childname ) const
BOOL LLView::hasChild(const std::string& childname, BOOL recurse) const
{
- return getChildView(childname, recurse, FALSE) != NULL;
+ return findChildView(childname, recurse) != NULL;
}
//-----------------------------------------------------------------------------
// getChildView()
//-----------------------------------------------------------------------------
-LLView* LLView::getChildView(const std::string& name, BOOL recurse, BOOL create_if_missing) const
+LLView* LLView::getChildView(const std::string& name, BOOL recurse) const
+{
+ LLView* child = findChildView(name, recurse);
+ if (!child)
+ {
+ child = getDefaultWidget<LLView>(name);
+ if (!child)
+ {
+ child = LLUICtrlFactory::createDefaultWidget<LLView>(name);
+ }
+ }
+ return child;
+}
+
+static LLFastTimer::DeclareTimer FTM_FIND_VIEWS("Find Widgets");
+
+LLView* LLView::findChildView(const std::string& name, BOOL recurse) const
{
+ LLFastTimer ft(FTM_FIND_VIEWS);
//richard: should we allow empty names?
//if(name.empty())
// return NULL;
@@ -1678,18 +1731,13 @@ LLView* LLView::getChildView(const std::string& name, BOOL recurse, BOOL create_
for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
{
LLView* childp = *child_it;
- LLView* viewp = childp->getChildView(name, recurse, FALSE);
+ LLView* viewp = childp->findChildView(name, recurse);
if ( viewp )
{
return viewp;
}
}
}
-
- if (create_if_missing)
- {
- return createDummyWidget<LLView>(name);
- }
return NULL;
}
@@ -1777,82 +1825,152 @@ LLView* LLView::getRootView()
return view;
}
-BOOL LLView::deleteViewByHandle(LLHandle<LLView> handle)
+LLView* LLView::findPrevSibling(LLView* child)
+{
+ child_list_t::iterator prev_it = std::find(mChildList.begin(), mChildList.end(), child);
+ if (prev_it != mChildList.end() && prev_it != mChildList.begin())
+ {
+ return *(--prev_it);
+ }
+ return NULL;
+}
+
+LLView* LLView::findNextSibling(LLView* child)
+{
+ child_list_t::iterator next_it = std::find(mChildList.begin(), mChildList.end(), child);
+ if (next_it != mChildList.end())
+ {
+ next_it++;
+ }
+
+ return (next_it != mChildList.end()) ? *next_it : NULL;
+}
+
+void LLView::deleteViewByHandle(LLHandle<LLView> handle)
{
LLView* viewp = handle.get();
delete viewp;
- return viewp != NULL;
}
-// Moves the view so that it is entirely inside of constraint.
-// If the view will not fit because it's too big, aligns with the top and left.
-// (Why top and left? That's where the drag bars are for floaters.)
-BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outside )
+LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, BOOL allow_partial_outside)
{
- S32 delta_x = 0;
- S32 delta_y = 0;
+ LLCoordGL delta;
if (allow_partial_outside)
{
const S32 KEEP_ONSCREEN_PIXELS = 16;
- if( getRect().mRight - KEEP_ONSCREEN_PIXELS < constraint.mLeft )
+ if( input.mRight - KEEP_ONSCREEN_PIXELS < constraint.mLeft )
{
- delta_x = constraint.mLeft - (getRect().mRight - KEEP_ONSCREEN_PIXELS);
+ delta.mX = constraint.mLeft - (input.mRight - KEEP_ONSCREEN_PIXELS);
}
else
- if( getRect().mLeft + KEEP_ONSCREEN_PIXELS > constraint.mRight )
+ if( input.mLeft + KEEP_ONSCREEN_PIXELS > constraint.mRight )
{
- delta_x = constraint.mRight - (getRect().mLeft + KEEP_ONSCREEN_PIXELS);
+ delta.mX = constraint.mRight - (input.mLeft + KEEP_ONSCREEN_PIXELS);
}
- if( getRect().mTop > constraint.mTop )
+ if( input.mTop > constraint.mTop )
{
- delta_y = constraint.mTop - getRect().mTop;
+ delta.mY = constraint.mTop - input.mTop;
}
else
- if( getRect().mTop - KEEP_ONSCREEN_PIXELS < constraint.mBottom )
+ if( input.mTop - KEEP_ONSCREEN_PIXELS < constraint.mBottom )
{
- delta_y = constraint.mBottom - (getRect().mTop - KEEP_ONSCREEN_PIXELS);
+ delta.mY = constraint.mBottom - (input.mTop - KEEP_ONSCREEN_PIXELS);
}
}
else
{
- if( getRect().mLeft < constraint.mLeft )
+ if( input.mLeft < constraint.mLeft )
{
- delta_x = constraint.mLeft - getRect().mLeft;
+ delta.mX = constraint.mLeft - input.mLeft;
}
else
- if( getRect().mRight > constraint.mRight )
+ if( input.mRight > constraint.mRight )
{
- delta_x = constraint.mRight - getRect().mRight;
+ delta.mX = constraint.mRight - input.mRight;
// compensate for left edge possible going off screen
- delta_x += llmax( 0, getRect().getWidth() - constraint.getWidth() );
+ delta.mX += llmax( 0, input.getWidth() - constraint.getWidth() );
}
- if( getRect().mTop > constraint.mTop )
+ if( input.mTop > constraint.mTop )
{
- delta_y = constraint.mTop - getRect().mTop;
+ delta.mY = constraint.mTop - input.mTop;
}
else
- if( getRect().mBottom < constraint.mBottom )
+ if( input.mBottom < constraint.mBottom )
{
- delta_y = constraint.mBottom - getRect().mBottom;
+ delta.mY = constraint.mBottom - input.mBottom;
// compensate for top edge possible going off screen
- delta_y -= llmax( 0, getRect().getHeight() - constraint.getHeight() );
+ delta.mY -= llmax( 0, input.getHeight() - constraint.getHeight() );
}
}
- if (delta_x != 0 || delta_y != 0)
+ return delta;
+}
+
+// Moves the view so that it is entirely inside of constraint.
+// If the view will not fit because it's too big, aligns with the top and left.
+// (Why top and left? That's where the drag bars are for floaters.)
+BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outside )
+{
+ LLCoordGL translation = getNeededTranslation(getRect(), constraint, allow_partial_outside);
+
+ if (translation.mX != 0 || translation.mY != 0)
+ {
+ translate(translation.mX, translation.mY);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// move this view into "inside" but not onto "exclude"
+// NOTE: if this view is already contained in "inside", we ignore the "exclude" rect
+BOOL LLView::translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, BOOL allow_partial_outside )
+{
+ LLCoordGL translation = getNeededTranslation(getRect(), inside, allow_partial_outside);
+
+ if (translation.mX != 0 || translation.mY != 0)
{
- translate(delta_x, delta_y);
+ // translate ourselves into constraint rect
+ translate(translation.mX, translation.mY);
+
+ // do we overlap with exclusion area?
+ // keep moving in the same direction to the other side of the exclusion rect
+ if (exclude.overlaps(getRect()))
+ {
+ // moving right
+ if (translation.mX > 0)
+ {
+ translate(exclude.mRight - getRect().mLeft, 0);
+ }
+ // moving left
+ else if (translation.mX < 0)
+ {
+ translate(exclude.mLeft - getRect().mRight, 0);
+ }
+
+ // moving up
+ if (translation.mY > 0)
+ {
+ translate(0, exclude.mTop - getRect().mBottom);
+ }
+ // moving down
+ else if (translation.mY < 0)
+ {
+ translate(0, exclude.mBottom - getRect().mTop);
+ }
+ }
+
return TRUE;
}
return FALSE;
}
+
void LLView::centerWithin(const LLRect& bounds)
{
S32 left = bounds.mLeft + (bounds.getWidth() - getRect().getWidth()) / 2;
@@ -1943,132 +2061,6 @@ BOOL LLView::localRectToOtherView( const LLRect& local, LLRect* other, LLView* o
return FALSE;
}
-// virtual
-LLXMLNodePtr LLView::getXML(bool save_children) const
-{
- //FIXME: need to provide actual derived type tag, probably outside this method
- LLXMLNodePtr node = new LLXMLNode("view", FALSE);
-
- node->createChild("name", TRUE)->setStringValue(getName());
- node->createChild("width", TRUE)->setIntValue(getRect().getWidth());
- node->createChild("height", TRUE)->setIntValue(getRect().getHeight());
-
- LLView* parent = getParent();
- S32 left = getRect().mLeft;
- S32 bottom = getRect().mBottom;
- if (parent) bottom -= parent->getRect().getHeight();
-
- node->createChild("left", TRUE)->setIntValue(left);
- node->createChild("bottom", TRUE)->setIntValue(bottom);
-
- U32 follows_flags = getFollows();
- if (follows_flags)
- {
- std::stringstream buffer;
- bool pipe = false;
- if (followsLeft())
- {
- buffer << "left";
- pipe = true;
- }
- if (followsTop())
- {
- if (pipe) buffer << "|";
- buffer << "top";
- pipe = true;
- }
- if (followsRight())
- {
- if (pipe) buffer << "|";
- buffer << "right";
- pipe = true;
- }
- if (followsBottom())
- {
- if (pipe) buffer << "|";
- buffer << "bottom";
- }
- node->createChild("follows", TRUE)->setStringValue(buffer.str());
- }
- // Export all widgets as enabled and visible - code must disable.
- node->createChild("mouse_opaque", TRUE)->setBoolValue(mMouseOpaque );
- if (!mToolTipMsg.getString().empty())
- {
- node->createChild("tool_tip", TRUE)->setStringValue(mToolTipMsg.getString());
- }
- if (mSoundFlags != MOUSE_UP)
- {
- node->createChild("sound_flags", TRUE)->setIntValue((S32)mSoundFlags);
- }
-
- node->createChild("enabled", TRUE)->setBoolValue(getEnabled());
-
- if (!mControlName.empty())
- {
- node->createChild("control_name", TRUE)->setStringValue(mControlName);
- }
- return node;
-}
-
-//static
-LLView* LLView::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- LLView* viewp = new LLView();
- viewp->initFromXML(node, parent);
- return viewp;
-}
-
-// static
-void LLView::addColorXML(LLXMLNodePtr node, const LLColor4& color,
- const char* xml_name, const char* control_name)
-{
- if (color != LLUI::sColorsGroup->getColor(ll_safe_string(control_name)))
- {
- node->createChild(xml_name, TRUE)->setFloatValue(4, color.mV);
- }
-}
-
-//static
-std::string LLView::escapeXML(const std::string& xml, std::string& indent)
-{
- std::string ret = indent + "\"" + LLXMLNode::escapeXML(xml);
-
- //replace every newline with a close quote, new line, indent, open quote
- size_t index = ret.size()-1;
- size_t fnd;
-
- while ((fnd = ret.rfind("\n", index)) != std::string::npos)
- {
- ret.replace(fnd, 1, "\"\n" + indent + "\"");
- index = fnd-1;
- }
-
- //append close quote
- ret.append("\"");
-
- return ret;
-}
-
-// static
-LLWString LLView::escapeXML(const LLWString& xml)
-{
- LLWString out;
- for (LLWString::size_type i = 0; i < xml.size(); ++i)
- {
- llwchar c = xml[i];
- switch(c)
- {
- case '"': out.append(utf8string_to_wstring("&quot;")); break;
- case '\'': out.append(utf8string_to_wstring("&apos;")); break;
- case '&': out.append(utf8string_to_wstring("&amp;")); break;
- case '<': out.append(utf8string_to_wstring("&lt;")); break;
- case '>': out.append(utf8string_to_wstring("&gt;")); break;
- default: out.push_back(c); break;
- }
- }
- return out;
-}
-
// static
const LLCtrlQuery & LLView::getTabOrderQuery()
{
@@ -2105,7 +2097,12 @@ const LLCtrlQuery & LLView::getFocusRootsQuery()
}
-void LLView::userSetShape(const LLRect& new_rect)
+void LLView::setShape(const LLRect& new_rect, bool by_user)
+{
+ handleReshape(new_rect, by_user);
+}
+
+void LLView::handleReshape(const LLRect& new_rect, bool by_user)
{
reshape(new_rect.getWidth(), new_rect.getHeight());
translate(new_rect.mLeft - getRect().mLeft, new_rect.mBottom - getRect().mBottom);
@@ -2353,560 +2350,534 @@ LLView* LLView::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESna
// Listener dispatch functions
//-----------------------------------------------------------------------------
-void LLView::registerEventListener(std::string name, LLSimpleListener* function)
-{
- mDispatchList.insert(std::pair<std::string, LLSimpleListener*>(name, function));
-}
-
-void LLView::deregisterEventListener(std::string name)
-{
- dispatch_list_t::iterator itor = mDispatchList.find(name);
- if (itor != mDispatchList.end())
- {
- mDispatchList.erase(itor);
- }
-}
-std::string LLView::findEventListener(LLSimpleListener *listener) const
+LLControlVariable *LLView::findControl(const std::string& name)
{
- dispatch_list_t::const_iterator itor;
- for (itor = mDispatchList.begin(); itor != mDispatchList.end(); ++itor)
+ // parse the name to locate which group it belongs to
+ std::size_t key_pos= name.find(".");
+ if(key_pos!= std::string::npos )
{
- if (itor->second == listener)
+ std::string control_group_key = name.substr(0, key_pos);
+ LLControlVariable* control;
+ // check if it's in the control group that name indicated
+ if(LLUI::sSettingGroups[control_group_key])
{
- return itor->first;
+ control = LLUI::sSettingGroups[control_group_key]->getControl(name);
+ if (control)
+ {
+ return control;
+ }
}
}
- if (mParentView)
- {
- return mParentView->findEventListener(listener);
- }
- return LLStringUtil::null;
+
+ LLControlGroup& control_group = LLUI::getControlControlGroup(name);
+ return control_group.getControl(name);
}
-LLSimpleListener* LLView::getListenerByName(const std::string& callback_name)
+const S32 FLOATER_H_MARGIN = 15;
+const S32 MIN_WIDGET_HEIGHT = 10;
+const S32 VPAD = 4;
+
+void LLView::initFromParams(const LLView::Params& params)
{
- LLSimpleListener* callback = NULL;
- dispatch_list_t::iterator itor = mDispatchList.find(callback_name);
- if (itor != mDispatchList.end())
- {
- callback = itor->second;
- }
- else if (mParentView)
+ LLRect required_rect = getRequiredRect();
+
+ S32 width = llmax(getRect().getWidth(), required_rect.getWidth());
+ S32 height = llmax(getRect().getHeight(), required_rect.getHeight());
+
+ reshape(width, height);
+
+ // call virtual methods with most recent data
+ // use getters because these values might not come through parameter block
+ setEnabled(getEnabled());
+ setVisible(getVisible());
+
+ if (!params.name().empty())
{
- callback = mParentView->getListenerByName(callback_name);
+ setName(params.name());
}
- return callback;
+
+ mLayout = params.layout();
}
-LLControlVariable *LLView::findControl(const std::string& name)
+void LLView::parseFollowsFlags(const LLView::Params& params)
{
- control_map_t::iterator itor = mFloaterControls.find(name);
- if (itor != mFloaterControls.end())
+ // preserve follows flags set by code if user did not override
+ if (!params.follows.isProvided())
{
- return itor->second;
+ return;
}
- if (mParentView)
+
+ // interpret either string or bitfield version of follows
+ if (params.follows.string.isChosen())
{
- return mParentView->findControl(name);
- }
- return LLUI::sConfigGroup->getControl(name);
-}
+ setFollows(FOLLOWS_NONE);
-const S32 FLOATER_H_MARGIN = 15;
-const S32 MIN_WIDGET_HEIGHT = 10;
-const S32 VPAD = 4;
+ std::string follows = params.follows.string;
-// static
-U32 LLView::createRect(LLXMLNodePtr node, LLRect &rect, LLView* parent_view, const LLRect &required_rect)
-{
- U32 follows = 0;
- S32 x = rect.mLeft;
- S32 y = rect.mBottom;
- S32 w = rect.getWidth();
- S32 h = rect.getHeight();
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep("|");
+ tokenizer tokens(follows, sep);
+ tokenizer::iterator token_iter = tokens.begin();
- U32 last_x = 0;
- U32 last_y = 0;
- if (parent_view)
- {
- last_y = parent_view->getRect().getHeight();
- child_list_t::const_iterator itor = parent_view->getChildList()->begin();
- if (itor != parent_view->getChildList()->end())
+ while(token_iter != tokens.end())
{
- LLView *last_view = (*itor);
- if (last_view->getSaveToXML())
+ const std::string& token_str = *token_iter;
+ if (token_str == "left")
{
- last_x = last_view->getRect().mLeft;
- last_y = last_view->getRect().mBottom;
+ setFollowsLeft();
}
+ else if (token_str == "right")
+ {
+ setFollowsRight();
+ }
+ else if (token_str == "top")
+ {
+ setFollowsTop();
+ }
+ else if (token_str == "bottom")
+ {
+ setFollowsBottom();
+ }
+ else if (token_str == "all")
+ {
+ setFollowsAll();
+ }
+ ++token_iter;
}
}
-
- std::string rect_control;
- node->getAttributeString("rect_control", rect_control);
- if (! rect_control.empty())
+ else if (params.follows.flags.isChosen())
{
- LLRect rect = LLUI::sConfigGroup->getRect(rect_control);
- x = rect.mLeft;
- y = rect.mBottom;
- w = rect.getWidth();
- h = rect.getHeight();
- }
-
- if (node->hasAttribute("left"))
- {
- node->getAttributeS32("left", x);
- }
- if (node->hasAttribute("bottom"))
- {
- node->getAttributeS32("bottom", y);
+ setFollows(params.follows.flags);
}
+}
- // Make your width the width of the containing
- // view if you don't specify a width.
- if (parent_view)
- {
- if(w == 0)
- {
- w = llmax(required_rect.getWidth(), parent_view->getRect().getWidth() - (FLOATER_H_MARGIN) - x);
- }
- if(h == 0)
- {
- h = llmax(MIN_WIDGET_HEIGHT, required_rect.getHeight());
+// static
+//LLFontGL::HAlign LLView::selectFontHAlign(LLXMLNodePtr node)
+//{
+// LLFontGL::HAlign gl_hfont_align = LLFontGL::LEFT;
+//
+// if (node->hasAttribute("halign"))
+// {
+// std::string horizontal_align_name;
+// node->getAttributeString("halign", horizontal_align_name);
+// gl_hfont_align = LLFontGL::hAlignFromName(horizontal_align_name);
+// }
+// return gl_hfont_align;
+//}
+
+// Return the rectangle of the last-constructed child,
+// if present and a first-class widget (eg, not a close box or drag handle)
+// Returns true if found
+static bool get_last_child_rect(LLView* parent, LLRect *rect)
+{
+ if (!parent) return false;
+
+ LLView::child_list_t::const_iterator itor =
+ parent->getChildList()->begin();
+ for (;itor != parent->getChildList()->end(); ++itor)
+ {
+ LLView *last_view = (*itor);
+ if (last_view->getFromXUI())
+ {
+ *rect = last_view->getRect();
+ return true;
}
}
+ return false;
+}
- if (node->hasAttribute("width"))
- {
- node->getAttributeS32("width", w);
- }
- if (node->hasAttribute("height"))
+//static
+void LLView::applyXUILayout(LLView::Params& p, LLView* parent)
+{
+ const S32 VPAD = 4;
+ const S32 MIN_WIDGET_HEIGHT = 10;
+
+ // *NOTE: This will confuse export of floater/panel coordinates unless
+ // the default is also "topleft". JC
+ if (p.layout().empty() && parent)
{
- node->getAttributeS32("height", h);
+ p.layout = parent->getLayout();
}
- if (parent_view)
+
+ if (parent)
{
- if (node->hasAttribute("left_delta"))
- {
- S32 left_delta = 0;
- node->getAttributeS32("left_delta", left_delta);
- x = last_x + left_delta;
- }
- else if (node->hasAttribute("left") && node->hasAttribute("right"))
+ LLRect parent_rect = parent->getLocalRect();
+ // overwrite uninitialized rect params, using context
+ LLRect last_rect = parent->getLocalRect();
+
+ bool layout_topleft = (p.layout() == "topleft");
+ if (layout_topleft)
{
- // compute width based on left and right
- S32 right = 0;
- node->getAttributeS32("right", right);
- if (right < 0)
- {
- right = parent_view->getRect().getWidth() + right;
- }
- w = right - x;
+ //invert top to bottom
+ if (p.rect.top.isProvided()) p.rect.top = parent_rect.getHeight() - p.rect.top;
+ if (p.rect.bottom.isProvided()) p.rect.bottom = parent_rect.getHeight() - p.rect.bottom;
}
- else if (node->hasAttribute("left"))
+
+ // convert negative or centered coordinates to parent relative values
+ // Note: some of this logic matches the logic in TypedParam<LLRect>::setValueFromBlock()
+
+ if (p.center_horiz)
{
- if (x < 0)
+ if (p.rect.left.isProvided() && p.rect.right.isProvided())
{
- x = parent_view->getRect().getWidth() + x;
- follows |= FOLLOWS_RIGHT;
+ S32 width = p.rect.right - p.rect.left;
+ width = llmax(width, 0);
+ S32 offset = parent_rect.getWidth()/2 - width/2;
+ p.rect.left = p.rect.left + offset;
+ p.rect.right = p.rect.right + offset;
}
else
{
- follows |= FOLLOWS_LEFT;
+ p.rect.left = p.rect.left + parent_rect.getWidth()/2 - p.rect.width/2;
+ p.rect.right.setProvided(false); // recalculate the right
}
}
- else if (node->hasAttribute("width") && node->hasAttribute("right"))
+ else
+ {
+ if (p.rect.left.isProvided() && p.rect.left < 0) p.rect.left = p.rect.left + parent_rect.getWidth();
+ if (p.rect.right.isProvided() && p.rect.right < 0) p.rect.right = p.rect.right + parent_rect.getWidth();
+ }
+ if (p.center_vert)
{
- S32 right = 0;
- node->getAttributeS32("right", right);
- if (right < 0)
+ if (p.rect.bottom.isProvided() && p.rect.top.isProvided())
{
- right = parent_view->getRect().getWidth() + right;
+ S32 height = p.rect.top - p.rect.bottom;
+ height = llmax(height, 0);
+ S32 offset = parent_rect.getHeight()/2 - height/2;
+ p.rect.bottom = p.rect.bottom + offset;
+ p.rect.top = p.rect.top + offset;
+ }
+ else
+ {
+ p.rect.bottom = p.rect.bottom + parent_rect.getHeight()/2 - p.rect.height/2;
+ p.rect.top.setProvided(false); // recalculate the top
}
- x = right - w;
}
else
{
- // left not specified, same as last
- x = last_x;
+ if (p.rect.bottom.isProvided() && p.rect.bottom < 0) p.rect.bottom = p.rect.bottom + parent_rect.getHeight();
+ if (p.rect.top.isProvided() && p.rect.top < 0) p.rect.top = p.rect.top + parent_rect.getHeight();
}
- if (node->hasAttribute("bottom_delta"))
+
+ // DEPRECATE: automatically fall back to height of MIN_WIDGET_HEIGHT pixels
+ if (!p.rect.height.isProvided() && !p.rect.top.isProvided() && p.rect.height == 0)
{
- S32 bottom_delta = 0;
- node->getAttributeS32("bottom_delta", bottom_delta);
- y = last_y + bottom_delta;
+ p.rect.height = MIN_WIDGET_HEIGHT;
}
- else if (node->hasAttribute("top"))
+
+ last_rect.translate(0, last_rect.getHeight());
+
+ // If there was a recently constructed child, use its rectangle
+ get_last_child_rect(parent, &last_rect);
+
+ if (layout_topleft)
{
- // compute height based on top
- S32 top = 0;
- node->getAttributeS32("top", top);
- if (top < 0)
+ p.bottom_delta.setIfNotProvided(0, false);
+
+ // Invert the sense of bottom_delta for topleft layout
+ if (p.bottom_delta.isProvided())
{
- top = parent_view->getRect().getHeight() + top;
+ p.bottom_delta = -p.bottom_delta;
}
- h = top - y;
- }
- else if (node->hasAttribute("bottom"))
- {
- if (y < 0)
+ else if (p.top_pad.isProvided())
{
- y = parent_view->getRect().getHeight() + y;
- follows |= FOLLOWS_TOP;
+ p.bottom_delta = -(p.rect.height + p.top_pad);
}
- else
+ else if (p.top_delta.isProvided())
{
- follows |= FOLLOWS_BOTTOM;
+ p.bottom_delta =
+ -(p.top_delta + p.rect.height - last_rect.getHeight());
}
- }
- else
- {
- // if bottom not specified, generate automatically
- if (last_y == 0)
+ else if (!p.bottom_delta.isProvided()
+ && !p.left_delta.isProvided()
+ && !p.top_pad.isProvided()
+ && !p.left_pad.isProvided())
{
- // treat first child as "bottom"
- y = parent_view->getRect().getHeight() - (h + VPAD);
- follows |= FOLLOWS_TOP;
+ // set default position is just below last rect
+ p.bottom_delta.set(-(p.rect.height + VPAD), false);
}
- else
+
+ // default to same left edge
+ p.left_delta.setIfNotProvided(0, false);
+ if (p.left_pad.isProvided())
{
- // treat subsequent children as "bottom_delta"
- y = last_y - (h + VPAD);
+ // left_pad is based on prior widget's right edge
+ p.left_delta.set(p.left_pad + last_rect.getWidth(), false);
}
+
+ last_rect.translate(p.left_delta, p.bottom_delta);
+ }
+ else
+ {
+ // set default position is just below last rect
+ p.bottom_delta.setIfNotProvided(-(p.rect.height + VPAD), false);
+ p.left_delta.setIfNotProvided(0, false);
+ last_rect.translate(p.left_delta, p.bottom_delta);
}
- }
- else
- {
- x = llmax(x, 0);
- y = llmax(y, 0);
- follows = FOLLOWS_LEFT | FOLLOWS_TOP;
- }
- rect.setOriginAndSize(x, y, w, h);
-
- return follows;
-}
-
-void LLView::initFromXML(LLXMLNodePtr node, LLView* parent)
-{
- // create rect first, as this will supply initial follows flags
- LLRect view_rect;
- U32 follows_flags = createRect(node, view_rect, parent, getRequiredRect());
- // call reshape in case there are any child elements that need to be layed out
- reshape(view_rect.getWidth(), view_rect.getHeight());
- setRect(view_rect);
- setFollows(follows_flags);
-
- parseFollowsFlags(node);
- if (node->hasAttribute("control_name"))
- {
- std::string control_name;
- node->getAttributeString("control_name", control_name);
- setControlName(control_name, NULL);
- }
+ // this handles case where *both* x and x_delta are provided
+ // ignore x in favor of default x + x_delta
+ if (p.bottom_delta.isProvided()) p.rect.bottom.set(0, false);
+ if (p.left_delta.isProvided()) p.rect.left.set(0, false);
- if (node->hasAttribute("tool_tip"))
- {
- std::string tool_tip_msg;
- node->getAttributeString("tool_tip", tool_tip_msg);
- setToolTip(tool_tip_msg);
+ // selectively apply rectangle defaults, making sure that
+ // params are not flagged as having been "provided"
+ // as rect params are overconstrained and rely on provided flags
+ p.rect.left.setIfNotProvided(last_rect.mLeft, false);
+ p.rect.bottom.setIfNotProvided(last_rect.mBottom, false);
+ p.rect.top.setIfNotProvided(last_rect.mTop, false);
+ p.rect.right.setIfNotProvided(last_rect.mRight, false);
+ p.rect.width.setIfNotProvided(last_rect.getWidth(), false);
+ p.rect.height.setIfNotProvided(last_rect.getHeight(), false);
}
+}
- if (node->hasAttribute("enabled"))
- {
- BOOL enabled;
- node->getAttributeBOOL("enabled", enabled);
- setEnabled(enabled);
- }
-
- if (node->hasAttribute("visible"))
+static S32 invert_vertical(S32 y, LLView* parent)
+{
+ if (y < 0)
{
- BOOL visible;
- node->getAttributeBOOL("visible", visible);
- setVisible(visible);
+ // already based on top-left, just invert
+ return -y;
}
-
- if (node->hasAttribute("hover_cursor"))
+ else if (parent)
{
- std::string cursor_string;
- node->getAttributeString("hover_cursor", cursor_string);
- mHoverCursor = getCursorFromString(cursor_string);
+ // use parent to flip coordinate
+ S32 parent_height = parent->getRect().getHeight();
+ return parent_height - y;
}
-
- node->getAttributeBOOL("use_bounding_rect", mUseBoundingRect);
- node->getAttributeBOOL("mouse_opaque", mMouseOpaque);
-
- node->getAttributeS32("default_tab_group", mDefaultTabGroup);
-
- reshape(view_rect.getWidth(), view_rect.getHeight());
-}
-
-void LLView::parseFollowsFlags(LLXMLNodePtr node)
-{
- if (node->hasAttribute("follows"))
+ else
{
- setFollowsNone();
-
- std::string follows;
- node->getAttributeString("follows", follows);
-
- typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
- boost::char_separator<char> sep("|");
- tokenizer tokens(follows, sep);
- tokenizer::iterator token_iter = tokens.begin();
-
- while(token_iter != tokens.end())
- {
- const std::string& token_str = *token_iter;
- if (token_str == "left")
- {
- setFollowsLeft();
- }
- else if (token_str == "right")
+ llwarns << "Attempting to convert layout to top-left with no parent" << llendl;
+ return y;
+ }
+}
+
+// Assumes that input is in bottom-left coordinates, hence must call
+// _before_ convert_coords_to_top_left().
+static void convert_to_relative_layout(LLView::Params& p, LLView* parent)
+{
+ // Use setupParams to get the final widget rectangle
+ // according to our wacky layout rules.
+ LLView::Params final = p;
+ LLView::applyXUILayout(final, parent);
+ // Must actually extract the rectangle to get consistent
+ // right = left+width, top = bottom+height
+ LLRect final_rect = final.rect;
+
+ // We prefer to write out top edge instead of bottom, regardless
+ // of whether we use relative positioning
+ bool converted_top = false;
+
+ // Look for a last rectangle
+ LLRect last_rect;
+ if (get_last_child_rect(parent, &last_rect))
+ {
+ // ...we have a previous widget to compare to
+ const S32 EDGE_THRESHOLD_PIXELS = 4;
+ S32 left_pad = final_rect.mLeft - last_rect.mRight;
+ S32 left_delta = final_rect.mLeft - last_rect.mLeft;
+ S32 top_pad = final_rect.mTop - last_rect.mBottom;
+ S32 top_delta = final_rect.mTop - last_rect.mTop;
+ // If my left edge is almost the same, or my top edge is
+ // almost the same...
+ if (llabs(left_delta) <= EDGE_THRESHOLD_PIXELS
+ || llabs(top_delta) <= EDGE_THRESHOLD_PIXELS)
+ {
+ // ...use relative positioning
+ // prefer top_pad if widgets are stacking vertically
+ // (coordinate system is still bottom-left here)
+ if (top_pad < 0)
{
- setFollowsRight();
+ p.top_pad = top_pad;
+ p.top_delta.setProvided(false);
}
- else if (token_str == "top")
+ else
{
- setFollowsTop();
+ p.top_pad.setProvided(false);
+ p.top_delta = top_delta;
}
- else if (token_str == "bottom")
+ // null out other vertical specifiers
+ p.rect.top.setProvided(false);
+ p.rect.bottom.setProvided(false);
+ p.bottom_delta.setProvided(false);
+ converted_top = true;
+
+ // prefer left_pad if widgets are stacking horizontally
+ if (left_pad > 0)
{
- setFollowsBottom();
+ p.left_pad = left_pad;
+ p.left_delta.setProvided(false);
}
- else if (token_str == "all")
+ else
{
- setFollowsAll();
+ p.left_pad.setProvided(false);
+ p.left_delta = left_delta;
}
- ++token_iter;
+ p.rect.left.setProvided(false);
+ p.rect.right.setProvided(false);
}
}
+
+ if (!converted_top)
+ {
+ // ...this is the first widget, or one that wasn't aligned
+ // prefer top/left specification
+ p.rect.top = final_rect.mTop;
+ p.rect.bottom.setProvided(false);
+ p.bottom_delta.setProvided(false);
+ p.top_pad.setProvided(false);
+ p.top_delta.setProvided(false);
+ }
}
-// static
-LLFontGL* LLView::selectFont(LLXMLNodePtr node)
+static void convert_coords_to_top_left(LLView::Params& p, LLView* parent)
{
- std::string font_name, font_size, font_style;
- U8 style = 0;
-
- if (node->hasAttribute("font"))
+ // Convert the coordinate system to be top-left based.
+ if (p.rect.top.isProvided())
{
- node->getAttributeString("font", font_name);
+ p.rect.top = invert_vertical(p.rect.top, parent);
}
-
- if (node->hasAttribute("font_size"))
+ if (p.rect.bottom.isProvided())
{
- node->getAttributeString("font_size", font_size);
+ p.rect.bottom = invert_vertical(p.rect.bottom, parent);
}
-
- if (node->hasAttribute("font_style"))
+ if (p.top_pad.isProvided())
{
- node->getAttributeString("font_style", font_style);
- style = LLFontGL::getStyleFromString(font_style);
+ p.top_pad = -p.top_pad;
}
-
- if (node->hasAttribute("font-style"))
+ if (p.top_delta.isProvided())
{
- node->getAttributeString("font-style", font_style);
- style = LLFontGL::getStyleFromString(font_style);
+ p.top_delta = -p.top_delta;
}
-
- if (font_name.empty())
- return NULL;
-
- LLFontDescriptor desc(font_name, font_size, style);
- LLFontGL* gl_font = LLFontGL::getFont(desc);
-
- return gl_font;
-}
-
-// static
-LLFontGL::HAlign LLView::selectFontHAlign(LLXMLNodePtr node)
-{
- LLFontGL::HAlign gl_hfont_align = LLFontGL::LEFT;
-
- if (node->hasAttribute("halign"))
+ if (p.bottom_delta.isProvided())
{
- std::string horizontal_align_name;
- node->getAttributeString("halign", horizontal_align_name);
- gl_hfont_align = LLFontGL::hAlignFromName(horizontal_align_name);
+ p.bottom_delta = -p.bottom_delta;
}
- return gl_hfont_align;
+ p.layout = "topleft";
}
-// static
-LLFontGL::VAlign LLView::selectFontVAlign(LLXMLNodePtr node)
+//static
+void LLView::setupParamsForExport(Params& p, LLView* parent)
{
- LLFontGL::VAlign gl_vfont_align = LLFontGL::BASELINE;
-
- if (node->hasAttribute("valign"))
+ // Don't convert if already top-left based
+ if (p.layout() == "topleft")
{
- std::string vert_align_name;
- node->getAttributeString("valign", vert_align_name);
- gl_vfont_align = LLFontGL::vAlignFromName(vert_align_name);
+ return;
}
- return gl_vfont_align;
-}
-
-// static
-LLFontGL::StyleFlags LLView::selectFontStyle(LLXMLNodePtr node)
-{
- LLFontGL::StyleFlags gl_font_style = LLFontGL::NORMAL;
- if (node->hasAttribute("style"))
+ // heuristic: Many of our floaters and panels were bulk-exported.
+ // These specify exactly bottom/left and height/width.
+ // Others were done by hand using bottom_delta and/or left_delta.
+ // Some rely on not specifying left to mean align with left edge.
+ // Try to convert both to use relative layout, but using top-left
+ // coordinates.
+ // Avoid rectangles where top/bottom/left/right was specified.
+ if (p.rect.height.isProvided() && p.rect.width.isProvided())
{
- std::string style_flags_name;
- node->getAttributeString("style", style_flags_name);
-
- if (style_flags_name == "normal")
- {
- gl_font_style = LLFontGL::NORMAL;
- }
- else if (style_flags_name == "bold")
+ if (p.rect.bottom.isProvided() && p.rect.left.isProvided())
{
- gl_font_style = LLFontGL::BOLD;
+ // standard bulk export, convert it
+ convert_to_relative_layout(p, parent);
}
- else if (style_flags_name == "italic")
+ else if (p.rect.bottom.isProvided() && p.left_delta.isProvided())
{
- gl_font_style = LLFontGL::ITALIC;
+ // hand layout with left_delta
+ convert_to_relative_layout(p, parent);
}
- else if (style_flags_name == "underline")
+ else if (p.bottom_delta.isProvided())
{
- gl_font_style = LLFontGL::UNDERLINE;
+ // hand layout with bottom_delta
+ // don't check for p.rect.left or p.left_delta because sometimes
+ // this layout doesn't set it for widgets that are left-aligned
+ convert_to_relative_layout(p, parent);
}
- //else leave left
}
- return gl_font_style;
+
+ convert_coords_to_top_left(p, parent);
}
-bool LLView::setControlValue(const LLSD& value)
-{
- std::string ctrlname = getControlName();
- if (!ctrlname.empty())
- {
- LLUI::sConfigGroup->setValue(ctrlname, value);
- return true;
- }
- return false;
+LLView::tree_iterator_t LLView::beginTreeDFS()
+{
+ return tree_iterator_t(this,
+ boost::bind(boost::mem_fn(&LLView::beginChild), _1),
+ boost::bind(boost::mem_fn(&LLView::endChild), _1));
}
-//virtual
-void LLView::setControlName(const std::string& control_name, LLView *context)
-{
- if (context == NULL)
- {
- context = this;
- }
+LLView::tree_iterator_t LLView::endTreeDFS()
+{
+ // an empty iterator is an "end" iterator
+ return tree_iterator_t();
+}
- if (!mControlName.empty())
- {
- llwarns << "setControlName called twice on same control!" << llendl;
- mControlConnection.disconnect(); // disconnect current signal
- mControlName.clear();
- }
-
- // Register new listener
- if (!control_name.empty())
- {
- LLControlVariable *control = context->findControl(control_name);
- if (control)
- {
- mControlName = control_name;
- mControlConnection = control->getSignal()->connect(boost::bind(&controlListener, _1, getHandle(), std::string("value")));
- setValue(control->getValue());
- }
- }
+LLView::tree_post_iterator_t LLView::beginTreeDFSPost()
+{
+ return tree_post_iterator_t(this,
+ boost::bind(boost::mem_fn(&LLView::beginChild), _1),
+ boost::bind(boost::mem_fn(&LLView::endChild), _1));
}
-// static
-bool LLView::controlListener(const LLSD& newvalue, LLHandle<LLView> handle, std::string type)
+LLView::tree_post_iterator_t LLView::endTreeDFSPost()
+{
+ // an empty iterator is an "end" iterator
+ return tree_post_iterator_t();
+}
+
+
+LLView::root_to_view_iterator_t LLView::beginRootToView()
{
- LLView* view = handle.get();
- if (view)
- {
- if (type == "value")
- {
- view->setValue(newvalue);
- return true;
- }
- else if (type == "enabled")
- {
- view->setEnabled(newvalue.asBoolean());
- return true;
- }
- else if (type == "visible")
- {
- view->setVisible(newvalue.asBoolean());
- return true;
- }
- }
- return false;
+ return root_to_view_iterator_t(this, boost::bind(&LLView::getParent, _1));
}
-void LLView::addBoolControl(const std::string& name, bool initial_value)
+LLView::root_to_view_iterator_t LLView::endRootToView()
{
- mFloaterControls[name] = new LLControlVariable(name, TYPE_BOOLEAN, initial_value, std::string("Internal floater control"));
+ return root_to_view_iterator_t();
}
-LLControlVariable *LLView::getControl(const std::string& name)
+
+// only create maps on demand, as they incur heap allocation/deallocation cost
+// when a view is constructed/deconstructed
+LLView::default_widget_map_t& LLView::getDefaultWidgetMap() const
{
- control_map_t::iterator itor = mFloaterControls.find(name);
- if (itor != mFloaterControls.end())
+ if (!mDefaultWidgets)
{
- return itor->second;
+ mDefaultWidgets = new default_widget_map_t();
}
- return NULL;
+ return *mDefaultWidgets;
}
-//virtual
-void LLView::setValue(const LLSD& value)
+S32 LLView::notifyParent(const LLSD& info)
{
+ LLView* parent = getParent();
+ if(parent)
+ return parent->notifyParent(info);
+ return 0;
}
-
-//virtual
-LLSD LLView::getValue() const
+bool LLView::notifyChildren(const LLSD& info)
{
- return LLSD();
+ bool ret = false;
+ for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
+ {
+ ret |= (*child_it)->notifyChildren(info);
+ }
+ return ret;
}
-LLView* LLView::createWidget(LLXMLNodePtr xml_node) const
+// convenient accessor for draw context
+const LLViewDrawContext& LLView::getDrawContext()
{
- // forward requests to ui ctrl factory
- return LLUICtrlFactory::getInstance()->createCtrlWidget(NULL, xml_node);
-}
-
-//
-// LLWidgetClassRegistry
-//
-
-LLWidgetClassRegistry::LLWidgetClassRegistry()
-{
-}
-
-void LLWidgetClassRegistry::registerCtrl(const std::string& tag, LLWidgetClassRegistry::factory_func_t function)
-{
- std::string lower_case_tag = tag;
- LLStringUtil::toLower(lower_case_tag);
-
- mCreatorFunctions[lower_case_tag] = function;
+ return LLViewDrawContext::getCurrentContext();
}
-BOOL LLWidgetClassRegistry::isTagRegistered(const std::string &tag)
-{
- return mCreatorFunctions.find(tag) != mCreatorFunctions.end();
-}
+const LLViewDrawContext& LLViewDrawContext::getCurrentContext()
+{
+ static LLViewDrawContext default_context;
-LLWidgetClassRegistry::factory_func_t LLWidgetClassRegistry::getCreatorFunc(const std::string& ctrl_type)
-{
- factory_map_t::const_iterator found_it = mCreatorFunctions.find(ctrl_type);
- if (found_it == mCreatorFunctions.end())
- {
- return NULL;
- }
- return found_it->second;
+ if (sDrawContextStack.empty())
+ return default_context;
+
+ return *sDrawContextStack.back();
}
-
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index e0e0f6ba47..c4d7313743 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -37,22 +37,26 @@
// the HUD or a dialog box or a button. It can also contain sub-views
// and child widgets
+#include "stdtypes.h"
#include "llcoord.h"
#include "llfontgl.h"
#include "llmortician.h"
#include "llmousehandler.h"
-#include "llnametable.h"
-#include "llsd.h"
#include "llstring.h"
#include "llrect.h"
#include "llui.h"
#include "lluistring.h"
-#include "lluixmltags.h"
#include "llviewquery.h"
-#include "llxmlnode.h"
#include "stdenums.h"
#include "lluistring.h"
#include "llcursortypes.h"
+#include "lluictrlfactory.h"
+#include "lltreeiterators.h"
+#include "llfocusmgr.h"
+
+#include <list>
+
+class LLSD;
const U32 FOLLOWS_NONE = 0x00;
const U32 FOLLOWS_LEFT = 0x01;
@@ -66,150 +70,106 @@ const BOOL NOT_MOUSE_OPAQUE = FALSE;
const U32 GL_NAME_UI_RESERVED = 2;
-/*
-// virtual functions defined in LLView:
-
-virtual BOOL isCtrl() const;
- LLUICtrl
-virtual BOOL isPanel();
- LLPanel
-virtual void setRect(const LLRect &rect);
- LLLineEditor
-virtual void addCtrl( LLUICtrl* ctrl, S32 tab_group);
-virtual void addCtrlAtEnd( LLUICtrl* ctrl, S32 tab_group);
-virtual void removeCtrl( LLUICtrl* ctrl);
- LLPanel
-virtual BOOL canFocusChildren() const { return TRUE; }
- LLFolderView
-virtual void deleteAllChildren();
- LLFolderView, LLPanelInventory
-virtual void setTentative(BOOL b) {}
- LLUICtrl, LLSliderCtrl, LLSpinCtrl
-virtual BOOL getTentative() const { return FALSE; }
- LLUICtrl, LLCheckBoxCtrl
-virtual void setVisible(BOOL visible);
- LLFloater, LLAlertDialog, LLMenuItemGL, LLModalDialog
-virtual void setEnabled(BOOL enabled) { mEnabled = enabled; }
- LLCheckBoxCtrl, LLComboBox, LLLineEditor, LLMenuGL, LLRadioGroup, etc
-virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ) { return FALSE; }
- LLUICtrl, LLButton, LLCheckBoxCtrl, LLLineEditor, LLMenuGL, LLSliderCtrl
-virtual void onVisibilityChange ( BOOL curVisibilityIn );
- LLMenuGL
-virtual LLRect getSnapRect() const { return mRect; } *TODO: Make non virtual
- LLFloater
-virtual LLRect getRequiredRect() { return mRect; }
- LLScrolllistCtrl
-virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
- LLUICtrl, et. al.
-virtual void translate( S32 x, S32 y );
- LLMenuGL
-virtual void userSetShape(const LLRect& new_rect);
- LLFloater, LLScrollLIstVtrl
-virtual LLView* findSnapRect(LLRect& new_rect, const LLCoordGL& mouse_dir, LLView::ESnapType snap_type, S32 threshold, S32 padding = 0);
-virtual LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding = 0);
- LLScrollListCtrl
-virtual BOOL canSnapTo(const LLView* other_view) { return other_view != this && other_view->getVisible(); }
- LLFloater
-virtual void snappedTo(const LLView* snap_view) {}
- LLFloater
-virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
- *
-virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
- *
-virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,EDragAndDropType cargo_type,void* cargo_data,EAcceptance* accept,std::string& tooltip_msg);
- *
-virtual void draw();
- *
-
- *
-virtual LLXMLNodePtr getXML(bool save_children = true) const;
- *
-virtual void initFromXML(LLXMLNodePtr node, LLView* parent);
- *
-virtual void onFocusLost() {}
- LLUICtrl, LLScrollListCtrl, LLMenuGL, LLLineEditor, LLComboBox
-virtual void onFocusReceived() {}
- LLUICtrl, LLTextEditor, LLScrollListVtrl, LLMenuGL, LLLineEditor
-virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const;
- LLTabContainer, LLPanel, LLMenuGL
-virtual void setControlName(const std::string& control, LLView *context);
- LLSliderCtrl, LLCheckBoxCtrl
-virtual std::string getControlName() const { return mControlName; }
- LLSliderCtrl, LLCheckBoxCtrl
-virtual bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata);
- LLMenuItem
-virtual void setValue(const LLSD& value);
- *
-
-protected:
-virtual BOOL handleKeyHere(KEY key, MASK mask);
- *
-virtual BOOL handleUnicodeCharHere(llwchar uni_char);
- *
-*/
-class LLUICtrlFactory;
-
-// maps xml strings to widget classes
-class LLWidgetClassRegistry : public LLSingleton<LLWidgetClassRegistry>
+// maintains render state during traversal of UI tree
+class LLViewDrawContext
{
- friend class LLSingleton<LLWidgetClassRegistry>;
public:
- typedef LLView* (*factory_func_t)(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
- typedef std::map<std::string, factory_func_t> factory_map_t;
-
- void registerCtrl(const std::string& xml_tag, factory_func_t function);
- BOOL isTagRegistered(const std::string& xml_tag);
- factory_func_t getCreatorFunc(const std::string& xml_tag);
+ F32 mAlpha;
- // get (first) xml tag for a given class
- template <class T> std::string getTag()
+ LLViewDrawContext(F32 alpha = 1.f)
+ : mAlpha(alpha)
{
- factory_map_t::iterator it;
- for(it = mCreatorFunctions.begin(); it != mCreatorFunctions.end(); ++it)
+ if (!sDrawContextStack.empty())
{
- if (it->second == T::fromXML)
- {
- return it->first;
- }
+ LLViewDrawContext* context_top = sDrawContextStack.back();
+ // merge with top of stack
+ mAlpha *= context_top->mAlpha;
}
-
- return "";
+ sDrawContextStack.push_back(this);
}
-private:
- LLWidgetClassRegistry();
- virtual ~LLWidgetClassRegistry() {};
+ ~LLViewDrawContext()
+ {
+ sDrawContextStack.pop_back();
+ }
- typedef std::set<std::string> ctrl_name_set_t;
- ctrl_name_set_t mUICtrlNames;
+ static const LLViewDrawContext& getCurrentContext();
- // map of xml tags to widget creator functions
- factory_map_t mCreatorFunctions;
+private:
+ static std::vector<LLViewDrawContext*> sDrawContextStack;
};
-template<class T>
-class LLRegisterWidget
+class LLViewWidgetRegistry : public LLChildRegistry<LLViewWidgetRegistry>
+{};
+
+class LLView : public LLMouseHandler, public LLMortician, public LLFocusableElement
{
public:
- LLRegisterWidget(const std::string& tag)
+ struct Follows : public LLInitParam::Choice<Follows>
{
- LLWidgetClassRegistry* registry = LLWidgetClassRegistry::getInstance();
- if (registry->isTagRegistered(tag))
- {
- //error!
- llerrs << "Widget named " << tag << " already registered!" << llendl;
- }
- else
- {
- registry->registerCtrl(tag, T::fromXML);
- }
- }
-};
+ Alternative<std::string> string;
+ Alternative<U32> flags;
-class LLView : public LLMouseHandler, public LLMortician
-{
+ Follows();
+ };
+
+ struct Params : public LLInitParam::Block<Params>
+ {
+ Mandatory<std::string> name;
+
+ Optional<bool> enabled,
+ visible,
+ mouse_opaque,
+ use_bounding_rect,
+ from_xui;
+
+ Optional<S32> tab_group,
+ default_tab_group;
+ Optional<std::string> tool_tip;
+
+ Optional<S32> sound_flags;
+ Optional<Follows> follows;
+ Optional<std::string> hover_cursor;
+
+ Optional<std::string> layout;
+ Optional<LLRect> rect;
+ // Historical bottom-left layout used bottom_delta and left_delta
+ // for relative positioning. New layout "topleft" prefers specifying
+ // based on top edge.
+ Optional<S32> bottom_delta, // deprecated
+ top_pad, // from last bottom to my top
+ top_delta, // from last top to my top
+ left_pad, // from last right to my left
+ left_delta; // from last left to my left
+
+ Optional<bool> center_horiz,
+ center_vert;
+
+ // these are nested attributes for LLLayoutPanel
+ //FIXME: get parent context involved in parsing traversal
+ Ignored user_resize,
+ auto_resize,
+ needs_translate,
+ xmlns,
+ xmlns_xsi,
+ xsi_schemaLocation,
+ xsi_type;
+
+ Params();
+ };
+
+ typedef LLViewWidgetRegistry child_registry_t;
+
+ void initFromParams(const LLView::Params&);
+
+protected:
+ LLView(const LLView::Params&);
+ friend class LLUICtrlFactory;
+private:
+ // widgets in general are not copyable
+ LLView(const LLView& other) {};
public:
#if LL_DEBUG
static BOOL sIsDrawing;
@@ -253,15 +213,8 @@ public:
typedef child_tab_order_t::reverse_iterator child_tab_order_reverse_iter_t;
typedef child_tab_order_t::const_reverse_iterator child_tab_order_const_reverse_iter_t;
- LLView();
- LLView(const std::string& name, BOOL mouse_opaque);
- LLView(const std::string& name, const LLRect& rect, BOOL mouse_opaque, U32 follows=FOLLOWS_NONE);
-
virtual ~LLView();
- // Hack to support LLFocusMgr (from LLMouseHandler)
- /*virtual*/ BOOL isView() const;
-
// Some UI widgets need to be added as controls. Others need to
// be added as regular view children. isCtrl should return TRUE
// if a widget needs to be added as a ctrl
@@ -294,21 +247,24 @@ public:
void setUseBoundingRect( BOOL use_bounding_rect );
BOOL getUseBoundingRect();
+ ECursorType getHoverCursor() { return mHoverCursor; }
+
const std::string& getToolTip() const { return mToolTipMsg.getString(); }
void sendChildToFront(LLView* child);
void sendChildToBack(LLView* child);
void moveChildToFrontOfTabGroup(LLUICtrl* child);
void moveChildToBackOfTabGroup(LLUICtrl* child);
+
+ virtual bool addChild(LLView* view, S32 tab_group = 0);
+
+ // implemented in terms of addChild()
+ bool addChildInBack(LLView* view, S32 tab_group = 0);
- void addChild(LLView* view, S32 tab_group = 0);
- void addChildAtEnd(LLView* view, S32 tab_group = 0);
// remove the specified child from the view, and set it's parent to NULL.
- void removeChild(LLView* view, BOOL deleteIt = FALSE);
+ virtual void removeChild(LLView* view);
- virtual void addCtrl( LLUICtrl* ctrl, S32 tab_group);
- virtual void addCtrlAtEnd( LLUICtrl* ctrl, S32 tab_group);
- virtual void removeCtrl( LLUICtrl* ctrl);
+ virtual BOOL postBuild() { return TRUE; }
child_tab_order_t getCtrlOrder() const { return mCtrlOrder; }
ctrl_list_t getCtrlList() const;
@@ -316,7 +272,9 @@ public:
void setDefaultTabGroup(S32 d) { mDefaultTabGroup = d; }
S32 getDefaultTabGroup() const { return mDefaultTabGroup; }
+ S32 getLastTabGroup() { return mLastTabGroup; }
+ bool trueToRoot(const boost::function<bool (const LLView*)>& predicate) const;
BOOL isInVisibleChain() const;
BOOL isInEnabledChain() const;
@@ -340,14 +298,19 @@ public:
BOOL getVisible() const { return mVisible; }
virtual void setEnabled(BOOL enabled);
BOOL getEnabled() const { return mEnabled; }
+ /// 'available' in this context means 'visible and enabled': in other
+ /// words, can a user actually interact with this?
+ virtual bool isAvailable() const;
+ /// The static isAvailable() tests an LLView* that could be NULL.
+ static bool isAvailable(const LLView* view);
U8 getSoundFlags() const { return mSoundFlags; }
virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
- virtual void onVisibilityChange ( BOOL curVisibilityIn );
+ virtual void handleVisibilityChange ( BOOL new_visibility );
void pushVisible(BOOL visible) { mLastVisible = mVisible; setVisible(visible); }
- void popVisible() { setVisible(mLastVisible); mLastVisible = TRUE; }
+ void popVisible() { setVisible(mLastVisible); }
LLHandle<LLView> getHandle() { mHandle.bind(this); return mHandle; }
@@ -361,24 +324,43 @@ public:
const LLRect& getRect() const { return mRect; }
const LLRect& getBoundingRect() const { return mBoundingRect; }
LLRect getLocalBoundingRect() const;
- LLRect getScreenRect() const;
+ LLRect calcScreenRect() const;
+ LLRect calcScreenBoundingRect() const;
LLRect getLocalRect() const;
virtual LLRect getSnapRect() const;
LLRect getLocalSnapRect() const;
+ std::string getLayout() { return mLayout; }
+
// Override and return required size for this object. 0 for width/height means don't care.
virtual LLRect getRequiredRect();
+ LLRect calcBoundingRect();
void updateBoundingRect();
LLView* getRootView();
LLView* getParent() const { return mParentView; }
LLView* getFirstChild() const { return (mChildList.empty()) ? NULL : *(mChildList.begin()); }
+ LLView* findPrevSibling(LLView* child);
+ LLView* findNextSibling(LLView* child);
S32 getChildCount() const { return (S32)mChildList.size(); }
template<class _Pr3> void sortChildren(_Pr3 _Pred) { mChildList.sort(_Pred); }
BOOL hasAncestor(const LLView* parentp) const;
BOOL hasChild(const std::string& childname, BOOL recurse = FALSE) const;
BOOL childHasKeyboardFocus( const std::string& childname ) const;
+
+ // these iterators are used for collapsing various tree traversals into for loops
+ typedef LLTreeDFSIter<LLView, child_list_const_iter_t> tree_iterator_t;
+ tree_iterator_t beginTreeDFS();
+ tree_iterator_t endTreeDFS();
+
+ typedef LLTreeDFSPostIter<LLView, child_list_const_iter_t> tree_post_iterator_t;
+ tree_post_iterator_t beginTreeDFSPost();
+ tree_post_iterator_t endTreeDFSPost();
+
+ typedef LLTreeDownIter<LLView> root_to_view_iterator_t;
+ root_to_view_iterator_t beginRootToView();
+ root_to_view_iterator_t endRootToView();
//
// UTILITIES
@@ -389,40 +371,32 @@ public:
virtual void translate( S32 x, S32 y );
void setOrigin( S32 x, S32 y ) { mRect.translate( x - mRect.mLeft, y - mRect.mBottom ); }
BOOL translateIntoRect( const LLRect& constraint, BOOL allow_partial_outside );
+ BOOL translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, BOOL allow_partial_outside );
void centerWithin(const LLRect& bounds);
- virtual void userSetShape(const LLRect& new_rect);
+ void setShape(const LLRect& new_rect, bool by_user = false);
virtual LLView* findSnapRect(LLRect& new_rect, const LLCoordGL& mouse_dir, LLView::ESnapType snap_type, S32 threshold, S32 padding = 0);
virtual LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding = 0);
-
virtual BOOL canSnapTo(const LLView* other_view);
+ virtual void setSnappedTo(const LLView* snap_view);
- virtual void snappedTo(const LLView* snap_view);
+ // inherited from LLFocusableElement
+ /* virtual */ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
+ /* virtual */ BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
- virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
- virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg);
- std::string getShowNamesToolTip();
-
virtual void draw();
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- //FIXME: make LLView non-instantiable from XML
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory);
- virtual void initFromXML(LLXMLNodePtr node, LLView* parent);
- void parseFollowsFlags(LLXMLNodePtr node);
+ void parseFollowsFlags(const LLView::Params& params);
// Some widgets, like close box buttons, don't need to be saved
- BOOL getSaveToXML() const { return mSaveToXML; }
- void setSaveToXML(BOOL b) { mSaveToXML = b; }
-
- virtual void onFocusLost();
- virtual void onFocusReceived();
+ BOOL getFromXUI() const { return mFromXUI; }
+ void setFromXUI(BOOL b) { mFromXUI = b; }
typedef enum e_hit_test_type
{
@@ -440,25 +414,16 @@ public:
void screenRectToLocal( const LLRect& screen, LLRect* local ) const;
void localRectToScreen( const LLRect& local, LLRect* screen ) const;
- // Listener dispatching functions (Dispatcher deletes pointers to listeners on deregistration or destruction)
- LLSimpleListener* getListenerByName(const std::string& callback_name);
- void registerEventListener(std::string name, LLSimpleListener* function);
- void deregisterEventListener(std::string name);
- std::string findEventListener(LLSimpleListener *listener) const;
- void addListenerToControl(LLEventDispatcher *observer, const std::string& name, LLSD filter, LLSD userdata);
-
- void addBoolControl(const std::string& name, bool initial_value);
- LLControlVariable *getControl(const std::string& name);
LLControlVariable *findControl(const std::string& name);
- bool setControlValue(const LLSD& value);
- virtual void setControlName(const std::string& control, LLView *context);
- virtual std::string getControlName() const { return mControlName; }
+ // Moved setValue(), getValue(), setControlValue(), setControlName(),
+ // controlListener() to LLUICtrl because an LLView is NOT assumed to
+ // contain a value. If that's what you want, use LLUICtrl instead.
// virtual bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata);
- virtual void setValue(const LLSD& value);
- virtual LLSD getValue() const;
const child_list_t* getChildList() const { return &mChildList; }
+ const child_list_const_iter_t beginChild() { return mChildList.begin(); }
+ const child_list_const_iter_t endChild() { return mChildList.end(); }
// LLMouseHandler functions
// Default behavior is to pass events to children
@@ -471,107 +436,53 @@ public:
/*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
- /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect); // Display mToolTipMsg if no child handles it.
- /*virtual*/ const std::string& getName() const;
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
+
+ /*virtual*/ std::string getName() const;
/*virtual*/ void onMouseCaptureLost();
/*virtual*/ BOOL hasMouseCapture();
- /*virtual*/ BOOL isView(); // Hack to support LLFocusMgr
/*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const;
/*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const;
- template <class T> T* getChild(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const
+ virtual LLView* childFromPoint(S32 x, S32 y);
+
+ // view-specific handlers
+ virtual void onMouseEnter(S32 x, S32 y, MASK mask);
+ virtual void onMouseLeave(S32 x, S32 y, MASK mask);
+
+
+ template <class T> T* findChild(const std::string& name, BOOL recurse = TRUE) const
{
- LLView* child = getChildView(name, recurse, FALSE);
+ LLView* child = findChildView(name, recurse);
T* result = dynamic_cast<T*>(child);
- if (!result)
- {
- // did we find *something* with that name?
- if (child)
- {
- llwarns << "Found child named " << name << " but of wrong type " << typeid(child).name() << ", expecting " << typeid(T).name() << llendl;
- }
- if (create_if_missing)
- {
- // create dummy widget instance here
- result = createDummyWidget<T>(name);
- }
- }
return result;
}
+ template <class T> T* getChild(const std::string& name, BOOL recurse = TRUE) const;
+
template <class T> T& getChildRef(const std::string& name, BOOL recurse = TRUE) const
{
- return *getChild<T>(name, recurse, TRUE);
+ return *getChild<T>(name, recurse);
}
- virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const;
+ virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE) const;
+ virtual LLView* findChildView(const std::string& name, BOOL recurse = TRUE) const;
- template <class T> T* createDummyWidget(const std::string& name) const
+ template <class T> T* getDefaultWidget(const std::string& name) const
{
- T* widget = getDummyWidget<T>(name);
- if (!widget)
- {
- // get xml tag name corresponding to requested widget type (e.g. "button")
- std::string xml_tag = LLWidgetClassRegistry::getInstance()->getTag<T>();
- if (xml_tag.empty())
- {
- llwarns << "No xml tag registered for this class " << llendl;
- return NULL;
- }
- // create dummy xml node (<button name="foo"/>)
- LLXMLNodePtr new_node_ptr = new LLXMLNode(xml_tag.c_str(), FALSE);
- new_node_ptr->createChild("name", TRUE)->setStringValue(name);
-
- widget = dynamic_cast<T*>(createWidget(new_node_ptr));
- if (widget)
- {
- // need non-const to update private dummy widget cache
- llwarns << "Making dummy " << xml_tag << " named " << name << " in " << getName() << llendl;
- mDummyWidgets.insert(std::make_pair(name, widget));
- }
- else
- {
- // dynamic cast will fail if T::fromXML only registered for base class
- llwarns << "Failed to create dummy widget of requested type " << llendl;
- return NULL;
- }
- }
- return widget;
- }
-
- template <class T> T* getDummyWidget(const std::string& name) const
- {
- dummy_widget_map_t::const_iterator found_it = mDummyWidgets.find(name);
- if (found_it == mDummyWidgets.end())
+ default_widget_map_t::const_iterator found_it = getDefaultWidgetMap().find(name);
+ if (found_it == getDefaultWidgetMap().end())
{
return NULL;
}
return dynamic_cast<T*>(found_it->second);
}
- LLView* createWidget(LLXMLNodePtr xml_node) const;
-
-
+ //////////////////////////////////////////////
// statics
- static U32 createRect(LLXMLNodePtr node, LLRect &rect, LLView* parent_view, const LLRect &required_rect = LLRect());
+ //////////////////////////////////////////////
+ //static LLFontGL::HAlign selectFontHAlign(LLXMLNodePtr node);
- static LLFontGL* selectFont(LLXMLNodePtr node);
- static LLFontGL::HAlign selectFontHAlign(LLXMLNodePtr node);
- static LLFontGL::VAlign selectFontVAlign(LLXMLNodePtr node);
- static LLFontGL::StyleFlags selectFontStyle(LLXMLNodePtr node);
-
-
- // Only saves color if different from default setting.
- static void addColorXML(LLXMLNodePtr node, const LLColor4& color,
- const char* xml_name, const char* control_name);
- // Escapes " (quot) ' (apos) & (amp) < (lt) > (gt)
- //static std::string escapeXML(const std::string& xml);
- static LLWString escapeXML(const LLWString& xml);
-
- //same as above, but wraps multiple lines in quotes and prepends
- //indent as leading white space on each line
- static std::string escapeXML(const std::string& xml, std::string& indent);
-
// focuses the item in the list after the currently-focused item, wrapping if necessary
static BOOL focusNext(LLView::child_list_t & result);
// focuses the item in the list before the currently-focused item, wrapping if necessary
@@ -582,16 +493,40 @@ public:
// return query for iterating over focus roots in tab order
static const LLCtrlQuery & getFocusRootsQuery();
- static BOOL deleteViewByHandle(LLHandle<LLView> handle);
+ static void deleteViewByHandle(LLHandle<LLView> handle);
static LLWindow* getWindow(void) { return LLUI::sWindow; }
+ // Set up params after XML load before calling new(),
+ // usually to adjust layout.
+ static void applyXUILayout(Params& p, LLView* parent);
+
+ // For re-export of floaters and panels, convert the coordinate system
+ // to be top-left based.
+ static void setupParamsForExport(Params& p, LLView* parent);
-protected:
+ //virtual BOOL addChildFromParam(const LLInitParam::BaseBlock& params) { return TRUE; }
virtual BOOL handleKeyHere(KEY key, MASK mask);
virtual BOOL handleUnicodeCharHere(llwchar uni_char);
+ virtual void handleReshape(const LLRect& rect, bool by_user);
+ virtual void dirtyRect();
+
+ //send custom notification to LLView parent
+ virtual S32 notifyParent(const LLSD& info);
+
+ //send custom notification to all view childrend
+ // return true if _any_ children return true. otherwise false.
+ virtual bool notifyChildren(const LLSD& info);
+
+ //send custom notification to current view
+ virtual S32 notify(const LLSD& info) { return 0;};
+
+ static const LLViewDrawContext& getDrawContext();
+
+protected:
void drawDebugRect();
void drawChild(LLView* childp, S32 x_offset = 0, S32 y_offset = 0, BOOL force_draw = FALSE);
+ void drawChildren();
LLView* childrenHandleKey(KEY key, MASK mask);
LLView* childrenHandleUnicodeChar(llwchar uni_char);
@@ -611,13 +546,12 @@ protected:
LLView* childrenHandleScrollWheel(S32 x, S32 y, S32 clicks);
LLView* childrenHandleRightMouseDown(S32 x, S32 y, MASK mask);
LLView* childrenHandleRightMouseUp(S32 x, S32 y, MASK mask);
+ LLView* childrenHandleToolTip(S32 x, S32 y, MASK mask);
- static bool controlListener(const LLSD& newvalue, LLHandle<LLView> handle, std::string type);
-
- typedef std::map<std::string, LLControlVariable*> control_map_t;
- control_map_t mFloaterControls;
-
+ ECursorType mHoverCursor;
+
private:
+
LLView* mParentView;
child_list_t mChildList;
@@ -625,11 +559,13 @@ private:
// location in pixels, relative to surrounding structure, bottom,left=0,0
LLRect mRect;
LLRect mBoundingRect;
+ std::string mLayout;
U32 mReshapeFlags;
child_tab_order_t mCtrlOrder;
S32 mDefaultTabGroup;
+ S32 mLastTabGroup;
BOOL mEnabled; // Enabled means "accepts input that has an effect on the state of the application."
// A disabled view, for example, may still have a scrollbar that responds to mouse events.
@@ -637,7 +573,7 @@ private:
LLUIString mToolTipMsg; // isNull() is true if none.
U8 mSoundFlags;
- BOOL mSaveToXML;
+ BOOL mFromXUI;
BOOL mIsFocusRoot;
BOOL mUseBoundingRect; // hit test against bounding rectangle that includes all child elements
@@ -651,27 +587,31 @@ private:
static LLWindow* sWindow; // All root views must know about their window.
- typedef std::map<std::string, LLPointer<LLSimpleListener> > dispatch_list_t;
- dispatch_list_t mDispatchList;
-
- std::string mControlName;
+ typedef std::map<std::string, LLView*> default_widget_map_t;
+ // allocate this map no demand, as it is rarely needed
+ mutable default_widget_map_t* mDefaultWidgets;
- typedef std::map<std::string, LLView*> dummy_widget_map_t;
- mutable dummy_widget_map_t mDummyWidgets;
+ default_widget_map_t& getDefaultWidgetMap() const;
- boost::signals::connection mControlConnection;
-
- ECursorType mHoverCursor;
-
public:
- static BOOL sDebugRects; // Draw debug rects behind everything.
- static BOOL sDebugKeys;
+ // Depth in view hierarchy during rendering
static S32 sDepth;
- static BOOL sDebugMouseHandling;
+
+ // Draw debug rectangles around widgets to help with alignment and spacing
+ static bool sDebugRects;
+
+ // Draw widget names and sizes when drawing debug rectangles, turning this
+ // off is useful to make the rectangles themselves easier to see.
+ static bool sDebugRectsShowNames;
+
+ static bool sDebugKeys;
+ static bool sDebugMouseHandling;
static std::string sMouseHandlerMessage;
static S32 sSelectID;
- static BOOL sEditingUI;
- static LLView* sEditingUIView;
+ static std::set<LLView*> sPreviewHighlightedElements; // DEV-16869
+ static BOOL sHighlightingDiffs; // DEV-16869
+ static LLView* sPreviewClickedElement; // DEV-16869
+ static BOOL sDrawPreviewHighlights;
static S32 sLastLeftXML;
static S32 sLastBottomXML;
static BOOL sForceReshape;
@@ -688,5 +628,46 @@ private:
LLView::child_tab_order_t mTabOrder;
};
+template <class T> T* LLView::getChild(const std::string& name, BOOL recurse) const
+{
+ LLView* child = findChildView(name, recurse);
+ T* result = dynamic_cast<T*>(child);
+ if (!result)
+ {
+ // did we find *something* with that name?
+ if (child)
+ {
+ llwarns << "Found child named " << name << " but of wrong type " << typeid(*child).name() << ", expecting " << typeid(T*).name() << llendl;
+ }
+ result = getDefaultWidget<T>(name);
+ if (!result)
+ {
+ result = LLUICtrlFactory::getDefaultWidget<T>(name);
+
+ if (result)
+ {
+ // *NOTE: You cannot call mFoo = getChild<LLFoo>("bar")
+ // in a floater or panel constructor. The widgets will not
+ // be ready. Instead, put it in postBuild().
+ llwarns << "Making dummy " << typeid(T).name() << " named \"" << name << "\" in " << getName() << llendl;
+ }
+ else
+ {
+ llwarns << "Failed to create dummy " << typeid(T).name() << llendl;
+ return NULL;
+ }
+
+ getDefaultWidgetMap()[name] = result;
+ }
+ }
+ return result;
+}
+
+// Compiler optimization - don't generate these specializations inline,
+// require explicit specialization. See llbutton.cpp for an example.
+#ifndef LLVIEW_CPP
+extern template class LLView* LLView::getChild<class LLView>(
+ const std::string& name, BOOL recurse) const;
+#endif
#endif //LL_LLVIEW_H
diff --git a/indra/llui/llviewborder.cpp b/indra/llui/llviewborder.cpp
index d4a9e9d1bf..30717f87de 100644
--- a/indra/llui/llviewborder.cpp
+++ b/indra/llui/llviewborder.cpp
@@ -33,25 +33,54 @@
#include "llviewborder.h"
#include "llrender.h"
#include "llfocusmgr.h"
+#include "lluictrlfactory.h"
-static LLRegisterWidget<LLViewBorder> r("view_border");
-
-LLViewBorder::LLViewBorder( const std::string& name, const LLRect& rect, EBevel bevel, EStyle style, S32 width )
- :
- LLView( name, rect, FALSE ),
- mBevel( bevel ),
- mStyle( style ),
- mHighlightLight( LLUI::sColorsGroup->getColor( "DefaultHighlightLight" ) ),
- mHighlightDark( LLUI::sColorsGroup->getColor( "DefaultHighlightDark" ) ),
- mShadowLight( LLUI::sColorsGroup->getColor( "DefaultShadowLight" ) ),
- mShadowDark( LLUI::sColorsGroup->getColor( "DefaultShadowDark" ) ),
- mBorderWidth( width ),
- mTexture( NULL ),
- mHasKeyboardFocus( FALSE )
+static LLDefaultChildRegistry::Register<LLViewBorder> r("view_border");
+
+void LLViewBorder::BevelValues::declareValues()
+{
+ declare("in", LLViewBorder::BEVEL_IN);
+ declare("out", LLViewBorder::BEVEL_OUT);
+ declare("bright", LLViewBorder::BEVEL_BRIGHT);
+ declare("none", LLViewBorder::BEVEL_NONE);
+}
+
+void LLViewBorder::StyleValues::declareValues()
{
- setFollowsAll();
+ declare("line", LLViewBorder::STYLE_LINE);
+ declare("texture", LLViewBorder::STYLE_TEXTURE);
}
+LLViewBorder::Params::Params()
+: bevel_style("bevel_style", BEVEL_OUT),
+ render_style("border_style", STYLE_LINE),
+ border_thickness("border_thickness"),
+ highlight_light_color("highlight_light_color"),
+ highlight_dark_color("highlight_dark_color"),
+ shadow_light_color("shadow_light_color"),
+ shadow_dark_color("shadow_dark_color")
+{
+ addSynonym(border_thickness, "thickness");
+ addSynonym(render_style, "style");
+ name = "view_border";
+ mouse_opaque = false;
+ follows.flags = FOLLOWS_ALL;
+}
+
+
+LLViewBorder::LLViewBorder(const LLViewBorder::Params& p)
+: LLView(p),
+ mTexture( NULL ),
+ mHasKeyboardFocus( FALSE ),
+ mBorderWidth(p.border_thickness),
+ mHighlightLight(p.highlight_light_color()),
+ mHighlightDark(p.highlight_dark_color()),
+ mShadowLight(p.shadow_light_color()),
+ mShadowDark(p.shadow_dark_color()),
+ mBevel(p.bevel_style),
+ mStyle(p.render_style)
+{}
+
void LLViewBorder::setColors( const LLColor4& shadow_dark, const LLColor4& highlight_light )
{
mShadowDark = shadow_dark;
@@ -69,7 +98,7 @@ void LLViewBorder::setColorsExtended( const LLColor4& shadow_light, const LLColo
void LLViewBorder::setTexture( const LLUUID &image_id )
{
- mTexture = LLUI::sImageProvider->getUIImageByID(image_id);
+ mTexture = LLUI::getUIImageByID(image_id);
}
@@ -105,26 +134,24 @@ void LLViewBorder::draw()
}
}
- // draw the children
LLView::draw();
-
}
void LLViewBorder::drawOnePixelLines()
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- LLColor4 top_color = mHighlightLight;
- LLColor4 bottom_color = mHighlightLight;
+ LLColor4 top_color = mHighlightLight.get();
+ LLColor4 bottom_color = mHighlightLight.get();
switch( mBevel )
{
case BEVEL_OUT:
- top_color = mHighlightLight;
- bottom_color = mShadowDark;
+ top_color = mHighlightLight.get();
+ bottom_color = mShadowDark.get();
break;
case BEVEL_IN:
- top_color = mShadowDark;
- bottom_color = mHighlightLight;
+ top_color = mShadowDark.get();
+ bottom_color = mHighlightLight.get();
break;
case BEVEL_NONE:
// use defaults
@@ -163,31 +190,36 @@ void LLViewBorder::drawTwoPixelLines()
LLColor4 focus_color = gFocusMgr.getFocusColor();
- F32* top_in_color = mShadowDark.mV;
- F32* top_out_color = mShadowDark.mV;
- F32* bottom_in_color = mShadowDark.mV;
- F32* bottom_out_color = mShadowDark.mV;
+ LLColor4 top_in_color;
+ LLColor4 top_out_color;
+ LLColor4 bottom_in_color;
+ LLColor4 bottom_out_color;
+
switch( mBevel )
{
case BEVEL_OUT:
- top_in_color = mHighlightLight.mV;
- top_out_color = mHighlightDark.mV;
- bottom_in_color = mShadowLight.mV;
- bottom_out_color = mShadowDark.mV;
+ top_in_color = mHighlightLight.get();
+ top_out_color = mHighlightDark.get();
+ bottom_in_color = mShadowLight.get();
+ bottom_out_color = mShadowDark.get();
break;
case BEVEL_IN:
- top_in_color = mShadowDark.mV;
- top_out_color = mShadowLight.mV;
- bottom_in_color = mHighlightDark.mV;
- bottom_out_color = mHighlightLight.mV;
+ top_in_color = mShadowDark.get();
+ top_out_color = mShadowLight.get();
+ bottom_in_color = mHighlightDark.get();
+ bottom_out_color = mHighlightLight.get();
break;
case BEVEL_BRIGHT:
- top_in_color = mHighlightLight.mV;
- top_out_color = mHighlightLight.mV;
- bottom_in_color = mHighlightLight.mV;
- bottom_out_color = mHighlightLight.mV;
+ top_in_color = mHighlightLight.get();
+ top_out_color = mHighlightLight.get();
+ bottom_in_color = mHighlightLight.get();
+ bottom_out_color = mHighlightLight.get();
break;
case BEVEL_NONE:
+ top_in_color = mShadowDark.get();
+ top_out_color = mShadowDark.get();
+ bottom_in_color = mShadowDark.get();
+ bottom_out_color = mShadowDark.get();
// use defaults
break;
default:
@@ -196,8 +228,8 @@ void LLViewBorder::drawTwoPixelLines()
if( mHasKeyboardFocus )
{
- top_out_color = focus_color.mV;
- bottom_out_color = focus_color.mV;
+ top_out_color = focus_color;
+ bottom_out_color = focus_color;
}
S32 left = 0;
@@ -206,19 +238,19 @@ void LLViewBorder::drawTwoPixelLines()
S32 bottom = 0;
// draw borders
- gGL.color3fv( top_out_color );
+ gGL.color3fv( top_out_color.mV );
gl_line_2d(left, bottom, left, top-1);
gl_line_2d(left, top-1, right, top-1);
- gGL.color3fv( top_in_color );
+ gGL.color3fv( top_in_color.mV );
gl_line_2d(left+1, bottom+1, left+1, top-2);
gl_line_2d(left+1, top-2, right-1, top-2);
- gGL.color3fv( bottom_out_color );
+ gGL.color3fv( bottom_out_color.mV );
gl_line_2d(right-1, top-1, right-1, bottom);
gl_line_2d(left, bottom, right, bottom);
- gGL.color3fv( bottom_in_color );
+ gGL.color3fv( bottom_in_color.mV );
gl_line_2d(right-2, top-2, right-2, bottom+1);
gl_line_2d(left+1, bottom+1, right-1, bottom+1);
}
@@ -302,26 +334,3 @@ BOOL LLViewBorder::getBevelFromAttribute(LLXMLNodePtr node, LLViewBorder::EBevel
return FALSE;
}
-
-// static
-LLView* LLViewBorder::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("view_border");
- node->getAttributeString("name", name);
-
- LLViewBorder::EBevel bevel_style = LLViewBorder::BEVEL_IN;
- getBevelFromAttribute(node, bevel_style);
-
- S32 border_thickness = 1;
- node->getAttributeS32("border_thickness", border_thickness);
-
- LLViewBorder* border = new LLViewBorder(name,
- LLRect(),
- bevel_style,
- LLViewBorder::STYLE_LINE,
- border_thickness);
-
- border->initFromXML(node, parent);
-
- return border;
-}
diff --git a/indra/llui/llviewborder.h b/indra/llui/llviewborder.h
index a40e6534a8..92fd569325 100644
--- a/indra/llui/llviewborder.h
+++ b/indra/llui/llviewborder.h
@@ -35,15 +35,41 @@
#include "llview.h"
-
class LLViewBorder : public LLView
{
public:
- enum EBevel { BEVEL_IN, BEVEL_OUT, BEVEL_BRIGHT, BEVEL_NONE };
- enum EStyle { STYLE_LINE, STYLE_TEXTURE };
-
- LLViewBorder( const std::string& name, const LLRect& rect, EBevel bevel = BEVEL_OUT, EStyle style = STYLE_LINE, S32 width = 1 );
-
+ typedef enum e_bevel { BEVEL_IN, BEVEL_OUT, BEVEL_BRIGHT, BEVEL_NONE } EBevel ;
+ typedef enum e_style { STYLE_LINE, STYLE_TEXTURE } EStyle;
+
+ struct BevelValues
+ : public LLInitParam::TypeValuesHelper<LLViewBorder::EBevel, BevelValues>
+ {
+ static void declareValues();
+ };
+
+ struct StyleValues
+ : public LLInitParam::TypeValuesHelper<LLViewBorder::EStyle, StyleValues>
+ {
+ static void declareValues();
+ };
+
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
+ {
+ Optional<EBevel, BevelValues> bevel_style;
+ Optional<EStyle, StyleValues> render_style;
+ Optional<S32> border_thickness;
+
+ Optional<LLUIColor> highlight_light_color,
+ highlight_dark_color,
+ shadow_light_color,
+ shadow_dark_color;
+
+ Params();
+ };
+protected:
+ LLViewBorder(const Params&);
+ friend class LLUICtrlFactory;
+public:
virtual void setValue(const LLSD& val) { setRect(LLRect(val)); }
virtual BOOL isCtrl() const { return FALSE; }
@@ -51,7 +77,6 @@ public:
// llview functionality
virtual void draw();
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory);
static BOOL getBevelFromAttribute(LLXMLNodePtr node, LLViewBorder::EBevel& bevel_style);
void setBorderWidth(S32 width) { mBorderWidth = width; }
@@ -63,8 +88,8 @@ public:
const LLColor4& highlight_light, const LLColor4& highlight_dark );
void setTexture( const class LLUUID &image_id );
- LLColor4 getHighlightLight() {return mHighlightLight;}
- LLColor4 getShadowDark() {return mHighlightDark;}
+ LLColor4 getHighlightLight() {return mHighlightLight.get();}
+ LLColor4 getShadowDark() {return mHighlightDark.get();}
EStyle getStyle() const { return mStyle; }
@@ -77,14 +102,14 @@ private:
void drawTextureTrapezoid( F32 degrees, S32 width, S32 length, F32 start_x, F32 start_y );
EBevel mBevel;
- const EStyle mStyle;
- LLColor4 mHighlightLight;
- LLColor4 mHighlightDark;
- LLColor4 mShadowLight;
- LLColor4 mShadowDark;
- LLColor4 mBackgroundColor;
+ EStyle mStyle;
+ LLUIColor mHighlightLight;
+ LLUIColor mHighlightDark;
+ LLUIColor mShadowLight;
+ LLUIColor mShadowDark;
+ LLUIColor mBackgroundColor;
S32 mBorderWidth;
- LLUIImagePtr mTexture;
+ LLPointer<LLUIImage> mTexture;
BOOL mHasKeyboardFocus;
};
diff --git a/indra/llui/llviewmodel.cpp b/indra/llui/llviewmodel.cpp
new file mode 100644
index 0000000000..4107289e85
--- /dev/null
+++ b/indra/llui/llviewmodel.cpp
@@ -0,0 +1,163 @@
+/**
+ * @file llviewmodel.cpp
+ * @author Nat Goodspeed
+ * @date 2008-08-08
+ * @brief Implementation for llviewmodel.
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llviewmodel.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+
+///
+LLViewModel::LLViewModel()
+ : mDirty(false)
+{
+}
+
+/// Instantiate an LLViewModel with an existing data value
+LLViewModel::LLViewModel(const LLSD& value)
+ : mDirty(false)
+{
+ setValue(value);
+}
+
+/// Update the stored value
+void LLViewModel::setValue(const LLSD& value)
+{
+ mValue = value;
+ mDirty = true;
+}
+
+LLSD LLViewModel::getValue() const
+{
+ return mValue;
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+///
+LLTextViewModel::LLTextViewModel()
+ : LLViewModel(false),
+ mUpdateFromDisplay(false)
+{
+}
+
+/// Instantiate an LLViewModel with an existing data value
+LLTextViewModel::LLTextViewModel(const LLSD& value)
+ : LLViewModel(value),
+ mUpdateFromDisplay(false)
+{
+}
+
+/// Update the stored value
+void LLTextViewModel::setValue(const LLSD& value)
+{
+ LLViewModel::setValue(value);
+ mDisplay = utf8str_to_wstring(value.asString());
+ // mDisplay and mValue agree
+ mUpdateFromDisplay = false;
+}
+
+void LLTextViewModel::setDisplay(const LLWString& value)
+{
+ // This is the strange way to alter the value. Normally we'd setValue()
+ // and do the utf8str_to_wstring() to get the corresponding mDisplay
+ // value. But a text editor might want to edit the display string
+ // directly, then convert back to UTF8 on commit.
+ mDisplay = value;
+ mDirty = true;
+ // Don't immediately convert to UTF8 -- do it lazily -- we expect many
+ // more setDisplay() calls than getValue() calls. Just flag that it needs
+ // doing.
+ mUpdateFromDisplay = true;
+}
+
+LLSD LLTextViewModel::getValue() const
+{
+ // Has anyone called setDisplay() since the last setValue()? If so, have
+ // to convert mDisplay back to UTF8.
+ if (mUpdateFromDisplay)
+ {
+ // The fact that we're lazily updating fields in this object should be
+ // transparent to clients, which is why this method is left
+ // conventionally const. Nor do we particularly want to make these
+ // members mutable. Just cast away constness in this one place.
+ LLTextViewModel* nthis = const_cast<LLTextViewModel*>(this);
+ nthis->mUpdateFromDisplay = false;
+ nthis->mValue = wstring_to_utf8str(mDisplay);
+ }
+ return LLViewModel::getValue();
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+
+LLListViewModel::LLListViewModel(const LLSD& values)
+ : LLViewModel()
+{
+}
+
+void LLListViewModel::addColumn(const LLSD& column, EAddPosition pos)
+{
+}
+
+void LLListViewModel::clearColumns()
+{
+}
+
+void LLListViewModel::setColumnLabel(const std::string& column, const std::string& label)
+{
+}
+
+LLScrollListItem* LLListViewModel::addElement(const LLSD& value, EAddPosition pos,
+ void* userdata)
+{
+ return NULL;
+}
+
+LLScrollListItem* LLListViewModel::addSimpleElement(const std::string& value, EAddPosition pos,
+ const LLSD& id)
+{
+ return NULL;
+}
+
+void LLListViewModel::clearRows()
+{
+}
+
+void LLListViewModel::sortByColumn(const std::string& name, bool ascending)
+{
+}
diff --git a/indra/llui/llviewmodel.h b/indra/llui/llviewmodel.h
new file mode 100644
index 0000000000..c8a9b52cca
--- /dev/null
+++ b/indra/llui/llviewmodel.h
@@ -0,0 +1,219 @@
+/**
+ * @file llviewmodel.h
+ * @author Nat Goodspeed
+ * @date 2008-08-08
+ * @brief Define "View Model" classes intended to store data values for use
+ * by LLUICtrl subclasses. The phrase is borrowed from Microsoft
+ * terminology, in which "View Model" means the storage object
+ * underlying a specific widget object -- as in our case -- rather
+ * than the business "model" object underlying the overall "view"
+ * presented by the collection of widgets.
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLVIEWMODEL_H)
+#define LL_LLVIEWMODEL_H
+
+#include "llpointer.h"
+#include "llsd.h"
+#include "llrefcount.h"
+#include "stdenums.h"
+#include "llstring.h"
+#include <string>
+
+class LLScrollListItem;
+
+class LLViewModel;
+class LLTextViewModel;
+class LLListViewModel;
+// Because LLViewModel is derived from LLRefCount, always pass, store
+// and return LLViewModelPtr rather than plain LLViewModel*.
+typedef LLPointer<LLViewModel> LLViewModelPtr;
+typedef LLPointer<LLTextViewModel> LLTextViewModelPtr;
+typedef LLPointer<LLListViewModel> LLListViewModelPtr;
+
+/**
+ * LLViewModel stores a scalar LLSD data item, the current display value of a
+ * scalar LLUICtrl widget. LLViewModel subclasses are used to store data
+ * collections used for aggregate widgets. LLViewModel is ref-counted because
+ * -- for multiple skins -- we may have distinct widgets sharing the same
+ * LLViewModel data. This way, the LLViewModel is quietly deleted when the
+ * last referencing widget is destroyed.
+ */
+class LLViewModel: public LLRefCount
+{
+public:
+ LLViewModel();
+ /// Instantiate an LLViewModel with an existing data value
+ LLViewModel(const LLSD& value);
+
+ /// Update the stored value
+ virtual void setValue(const LLSD& value);
+ /// Get the stored value, in appropriate type.
+ virtual LLSD getValue() const;
+
+ /// Has the value been changed since last time we checked?
+ bool isDirty() const { return mDirty; }
+ /// Once the value has been saved to a file, or otherwise consumed by the
+ /// app, we no longer need to enable the Save button
+ void resetDirty() { mDirty = false; }
+ //
+ void setDirty() { mDirty = true; }
+
+protected:
+ LLSD mValue;
+ bool mDirty;
+};
+
+/**
+ * LLTextViewModel stores a value displayed as text.
+ */
+class LLTextViewModel: public LLViewModel
+{
+public:
+ LLTextViewModel();
+ /// Instantiate an LLViewModel with an existing data value
+ LLTextViewModel(const LLSD& value);
+
+ // LLViewModel functions
+ virtual void setValue(const LLSD& value);
+ virtual LLSD getValue() const;
+
+ // New functions
+ /// Get the stored value in string form
+ LLWString getDisplay() const { return mDisplay; }
+ /**
+ * Set the display string directly (see LLTextEditor). What the user is
+ * editing is actually the LLWString value rather than the underlying
+ * UTF-8 value.
+ */
+ void setDisplay(const LLWString& value);
+
+private:
+ /// To avoid converting every widget's stored value from LLSD to LLWString
+ /// every frame, cache the converted value
+ LLWString mDisplay;
+ /// As the user edits individual characters (setDisplay()), defer
+ /// LLWString-to-UTF8 conversions until s/he's done.
+ bool mUpdateFromDisplay;
+};
+
+/**
+ * LLListViewModel stores a list of data items. The semantics are borrowed
+ * from LLScrollListCtrl.
+ */
+class LLListViewModel: public LLViewModel
+{
+public:
+ LLListViewModel() {}
+ LLListViewModel(const LLSD& values);
+
+ virtual void addColumn(const LLSD& column, EAddPosition pos = ADD_BOTTOM);
+ virtual void clearColumns();
+ virtual void setColumnLabel(const std::string& column, const std::string& label);
+ virtual LLScrollListItem* addElement(const LLSD& value, EAddPosition pos = ADD_BOTTOM,
+ void* userdata = NULL);
+ virtual LLScrollListItem* addSimpleElement(const std::string& value, EAddPosition pos,
+ const LLSD& id);
+ virtual void clearRows();
+ virtual void sortByColumn(const std::string& name, bool ascending);
+};
+
+//namespace LLViewModel
+//{
+// class Value
+// {
+// public:
+// Value(const LLSD& value = LLSD());
+//
+// LLSD getValue() const { return mValue; }
+// void setValue(const LLSD& value) { mValue = value; }
+//
+// bool isAvailable() const { return false; }
+// bool isReadOnly() const { return false; }
+//
+// bool undo() { return false; }
+// bool redo() { return false; }
+//
+// /// Has the value been changed since last time we checked?
+// bool isDirty() const { return mDirty; }
+// /// Once the value has been saved to a file, or otherwise consumed by the
+// /// app, we no longer need to enable the Save button
+// void resetDirty() { mDirty = false; }
+// //
+// void setDirty() { mDirty = true; }
+//
+// protected:
+// LLSD mValue;
+// bool mDirty;
+// };
+//
+// class Numeric : public Value
+// {
+// public:
+// Numeric(S32 value = 0);
+// Numeric(F32 value);
+//
+// F32 getPrecision();
+// F32 getMin();
+// F32 getMax();
+//
+// void increment();
+// void decrement();
+// };
+//
+// class MultipleValues : public Value
+// {
+// class Selector
+// {};
+//
+// MultipleValues();
+// virtual S32 numElements();
+// };
+//
+// class Tuple : public MultipleValues
+// {
+// Tuple(S32 size);
+// LLSD getValue(S32 which) const;
+// void setValue(S32 which, const LLSD& value);
+// };
+//
+// class List : public MultipleValues
+// {
+// List();
+//
+// void add(const ValueModel& value);
+// bool remove(const Selector& item);
+//
+// void setSortElement(const Selector& element);
+// void sort();
+// };
+//
+//};
+#endif /* ! defined(LL_LLVIEWMODEL_H) */
diff --git a/indra/llui/llviewquery.h b/indra/llui/llviewquery.h
index e87795f9a3..98d9bf8796 100644
--- a/indra/llui/llviewquery.h
+++ b/indra/llui/llviewquery.h
@@ -35,7 +35,7 @@
#include <list>
-#include "llmemory.h"
+#include "llsingleton.h"
#include "llui.h"
class LLView;
diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp
new file mode 100644
index 0000000000..26d1f2e067
--- /dev/null
+++ b/indra/llui/tests/llurlentry_stub.cpp
@@ -0,0 +1,64 @@
+/**
+ * @file llurlentry_stub.cpp
+ * @author Martin Reddy
+ * @brief Stub implementations for LLUrlEntry unit test dependencies
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+ * this source code is governed by the Linden Lab Source Code Disclosure
+ * Agreement ("Agreement") previously entered between you and Linden
+ * Lab. By accessing, using, copying, modifying or distributing this
+ * software, you acknowledge that you have been informed of your
+ * obligations under the Agreement and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llstring.h"
+#include "llfile.h"
+#include "llcachename.h"
+#include "lluuid.h"
+
+#include <string>
+
+//
+// Stub implementation for LLCacheName
+//
+BOOL LLCacheName::getFullName(const LLUUID& id, std::string& fullname)
+{
+ fullname = "Lynx Linden";
+ return TRUE;
+}
+
+BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
+{
+ group = "My Group";
+ return TRUE;
+}
+
+boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, const LLCacheNameCallback& callback)
+{
+ return boost::signals2::connection();
+}
+
+LLCacheName* gCacheName = NULL;
+
+//
+// Stub implementation for LLTrans
+//
+class LLTrans
+{
+public:
+ static std::string getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args);
+};
+
+std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args)
+{
+ return std::string();
+}
diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp
new file mode 100644
index 0000000000..80be8fcbf7
--- /dev/null
+++ b/indra/llui/tests/llurlentry_test.cpp
@@ -0,0 +1,614 @@
+/**
+ * @file llurlentry_test.cpp
+ * @author Martin Reddy
+ * @brief Unit tests for LLUrlEntry objects
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+ * this source code is governed by the Linden Lab Source Code Disclosure
+ * Agreement ("Agreement") previously entered between you and Linden
+ * Lab. By accessing, using, copying, modifying or distributing this
+ * software, you acknowledge that you have been informed of your
+ * obligations under the Agreement and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../llurlentry.h"
+#include "llurlentry_stub.cpp"
+#include "lltut.h"
+#include "../lluicolortable.h"
+
+#include <boost/regex.hpp>
+
+LLUIColor LLUIColorTable::getColor(const std::string& name, const LLColor4& default_color) const
+{
+ return LLUIColor();
+}
+
+LLUIColor::LLUIColor() {}
+
+namespace tut
+{
+ struct LLUrlEntryData
+ {
+ };
+
+ typedef test_group<LLUrlEntryData> factory;
+ typedef factory::object object;
+}
+
+namespace
+{
+ tut::factory tf("LLUrlEntry");
+}
+
+namespace tut
+{
+ void testRegex(const std::string &testname, boost::regex regex,
+ const char *text, const std::string &expected)
+ {
+ std::string url = "";
+ boost::cmatch result;
+ bool found = boost::regex_search(text, result, regex);
+ if (found)
+ {
+ S32 start = static_cast<U32>(result[0].first - text);
+ S32 end = static_cast<U32>(result[0].second - text);
+ url = std::string(text+start, end-start);
+ }
+ ensure_equals(testname, url, expected);
+ }
+
+ template<> template<>
+ void object::test<1>()
+ {
+ //
+ // test LLUrlEntryHTTP - standard http Urls
+ //
+ LLUrlEntryHTTP url;
+ boost::regex r = url.getPattern();
+
+ testRegex("no valid url", r,
+ "htp://slurl.com/",
+ "");
+
+ testRegex("simple http (1)", r,
+ "http://slurl.com/",
+ "http://slurl.com/");
+
+ testRegex("simple http (2)", r,
+ "http://slurl.com",
+ "http://slurl.com");
+
+ testRegex("simple http (3)", r,
+ "http://slurl.com/about.php",
+ "http://slurl.com/about.php");
+
+ testRegex("simple https", r,
+ "https://slurl.com/about.php",
+ "https://slurl.com/about.php");
+
+ testRegex("http in text (1)", r,
+ "XX http://slurl.com/ XX",
+ "http://slurl.com/");
+
+ testRegex("http in text (2)", r,
+ "XX http://slurl.com/about.php XX",
+ "http://slurl.com/about.php");
+
+ testRegex("https in text", r,
+ "XX https://slurl.com/about.php XX",
+ "https://slurl.com/about.php");
+
+ testRegex("two http urls", r,
+ "XX http://slurl.com/about.php http://secondlife.com/ XX",
+ "http://slurl.com/about.php");
+
+ testRegex("http url with port and username", r,
+ "XX http://nobody@slurl.com:80/about.php http://secondlife.com/ XX",
+ "http://nobody@slurl.com:80/about.php");
+
+ testRegex("http url with port, username, and query string", r,
+ "XX http://nobody@slurl.com:80/about.php?title=hi%20there http://secondlife.com/ XX",
+ "http://nobody@slurl.com:80/about.php?title=hi%20there");
+
+ // note: terminating commas will be removed by LLUrlRegistry:findUrl()
+ testRegex("http url with commas in middle and terminating", r,
+ "XX http://slurl.com/?title=Hi,There, XX",
+ "http://slurl.com/?title=Hi,There,");
+
+ // note: terminating periods will be removed by LLUrlRegistry:findUrl()
+ testRegex("http url with periods in middle and terminating", r,
+ "XX http://slurl.com/index.php. XX",
+ "http://slurl.com/index.php.");
+
+ // DEV-19842: Closing parenthesis ")" breaks urls
+ testRegex("http url with brackets (1)", r,
+ "XX http://en.wikipedia.org/wiki/JIRA_(software) XX",
+ "http://en.wikipedia.org/wiki/JIRA_(software)");
+
+ // DEV-19842: Closing parenthesis ")" breaks urls
+ testRegex("http url with brackets (2)", r,
+ "XX http://jira.secondlife.com/secure/attachment/17990/eggy+avs+in+1.21.0+(93713)+public+nightly.jpg XX",
+ "http://jira.secondlife.com/secure/attachment/17990/eggy+avs+in+1.21.0+(93713)+public+nightly.jpg");
+
+ // DEV-10353: URLs in chat log terminated incorrectly when newline in chat
+ testRegex("http url with newlines", r,
+ "XX\nhttp://www.secondlife.com/\nXX",
+ "http://www.secondlife.com/");
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ //
+ // test LLUrlEntryHTTPLabel - wiki-style http Urls with labels
+ //
+ LLUrlEntryHTTPLabel url;
+ boost::regex r = url.getPattern();
+
+ testRegex("invalid wiki url [1]", r,
+ "[http://www.example.org]",
+ "");
+
+ testRegex("invalid wiki url [2]", r,
+ "[http://www.example.org",
+ "");
+
+ testRegex("invalid wiki url [3]", r,
+ "[http://www.example.org Label",
+ "");
+
+ testRegex("example.org with label (spaces)", r,
+ "[http://www.example.org Text]",
+ "[http://www.example.org Text]");
+
+ testRegex("example.org with label (tabs)", r,
+ "[http://www.example.org\t Text]",
+ "[http://www.example.org\t Text]");
+
+ testRegex("SL http URL with label", r,
+ "[http://www.secondlife.com/ Second Life]",
+ "[http://www.secondlife.com/ Second Life]");
+
+ testRegex("SL https URL with label", r,
+ "XXX [https://www.secondlife.com/ Second Life] YYY",
+ "[https://www.secondlife.com/ Second Life]");
+
+ testRegex("SL http URL with label", r,
+ "[http://www.secondlife.com/?test=Hi%20There Second Life]",
+ "[http://www.secondlife.com/?test=Hi%20There Second Life]");
+ }
+
+ template<> template<>
+ void object::test<3>()
+ {
+ //
+ // test LLUrlEntrySLURL - second life URLs
+ //
+ LLUrlEntrySLURL url;
+ boost::regex r = url.getPattern();
+
+ testRegex("no valid slurl [1]", r,
+ "htp://slurl.com/secondlife/Ahern/50/50/50/",
+ "");
+
+ testRegex("no valid slurl [2]", r,
+ "http://slurl.com/secondlife/",
+ "");
+
+ testRegex("no valid slurl [3]", r,
+ "hhtp://slurl.com/secondlife/Ahern/50/FOO/50/",
+ "");
+
+ testRegex("Ahern (50,50,50) [1]", r,
+ "http://slurl.com/secondlife/Ahern/50/50/50/",
+ "http://slurl.com/secondlife/Ahern/50/50/50/");
+
+ testRegex("Ahern (50,50,50) [2]", r,
+ "XXX http://slurl.com/secondlife/Ahern/50/50/50/ XXX",
+ "http://slurl.com/secondlife/Ahern/50/50/50/");
+
+ testRegex("Ahern (50,50,50) [3]", r,
+ "XXX http://slurl.com/secondlife/Ahern/50/50/50 XXX",
+ "http://slurl.com/secondlife/Ahern/50/50/50");
+
+ testRegex("Ahern (50,50,50) multicase", r,
+ "XXX http://SLUrl.com/SecondLife/Ahern/50/50/50/ XXX",
+ "http://SLUrl.com/SecondLife/Ahern/50/50/50/");
+
+ testRegex("Ahern (50,50) [1]", r,
+ "XXX http://slurl.com/secondlife/Ahern/50/50/ XXX",
+ "http://slurl.com/secondlife/Ahern/50/50/");
+
+ testRegex("Ahern (50,50) [2]", r,
+ "XXX http://slurl.com/secondlife/Ahern/50/50 XXX",
+ "http://slurl.com/secondlife/Ahern/50/50");
+
+ testRegex("Ahern (50)", r,
+ "XXX http://slurl.com/secondlife/Ahern/50 XXX",
+ "http://slurl.com/secondlife/Ahern/50");
+
+ testRegex("Ahern", r,
+ "XXX http://slurl.com/secondlife/Ahern/ XXX",
+ "http://slurl.com/secondlife/Ahern/");
+
+ testRegex("Ahern SLURL with title", r,
+ "XXX http://slurl.com/secondlife/Ahern/50/50/50/?title=YOUR%20TITLE%20HERE! XXX",
+ "http://slurl.com/secondlife/Ahern/50/50/50/?title=YOUR%20TITLE%20HERE!");
+
+ testRegex("Ahern SLURL with msg", r,
+ "XXX http://slurl.com/secondlife/Ahern/50/50/50/?msg=Your%20text%20here. XXX",
+ "http://slurl.com/secondlife/Ahern/50/50/50/?msg=Your%20text%20here.");
+
+ // DEV-21577: In-world SLURLs containing "(" or ")" are not treated as a hyperlink in chat
+ testRegex("SLURL with brackets", r,
+ "XXX http://slurl.com/secondlife/Burning%20Life%20(Hyper)/27/210/30 XXX",
+ "http://slurl.com/secondlife/Burning%20Life%20(Hyper)/27/210/30");
+
+ // DEV-35459: SLURLs and teleport Links not parsed properly
+ testRegex("SLURL with quote", r,
+ "XXX http://slurl.com/secondlife/A'ksha%20Oasis/41/166/701 XXX",
+ "http://slurl.com/secondlife/A'ksha%20Oasis/41/166/701");
+ }
+
+ template<> template<>
+ void object::test<4>()
+ {
+ //
+ // test LLUrlEntryAgent - secondlife://app/agent Urls
+ //
+ LLUrlEntryAgent url;
+ boost::regex r = url.getPattern();
+
+ testRegex("Invalid Agent Url", r,
+ "secondlife:///app/agent/0e346d8b-4433-4d66-XXXX-fd37083abc4c/about",
+ "");
+
+ testRegex("Agent Url ", r,
+ "secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about",
+ "secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about");
+
+ testRegex("Agent Url in text", r,
+ "XXX secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about XXX",
+ "secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about");
+
+ testRegex("Agent Url multicase", r,
+ "XXX secondlife:///App/AGENT/0E346D8B-4433-4d66-a6b0-fd37083abc4c/About XXX",
+ "secondlife:///App/AGENT/0E346D8B-4433-4d66-a6b0-fd37083abc4c/About");
+
+ testRegex("Agent Url alternate command", r,
+ "XXX secondlife:///App/AGENT/0E346D8B-4433-4d66-a6b0-fd37083abc4c/foobar",
+ "secondlife:///App/AGENT/0E346D8B-4433-4d66-a6b0-fd37083abc4c/foobar");
+
+ }
+
+ template<> template<>
+ void object::test<5>()
+ {
+ //
+ // test LLUrlEntryGroup - secondlife://app/group Urls
+ //
+ LLUrlEntryGroup url;
+ boost::regex r = url.getPattern();
+
+ testRegex("Invalid Group Url", r,
+ "secondlife:///app/group/00005ff3-4044-c79f-XXXX-fb28ae0df991/about",
+ "");
+
+ testRegex("Group Url ", r,
+ "secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about",
+ "secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about");
+
+ testRegex("Group Url ", r,
+ "secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/inspect",
+ "secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/inspect");
+
+ testRegex("Group Url in text", r,
+ "XXX secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about XXX",
+ "secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about");
+
+ testRegex("Group Url multicase", r,
+ "XXX secondlife:///APP/Group/00005FF3-4044-c79f-9de8-fb28ae0df991/About XXX",
+ "secondlife:///APP/Group/00005FF3-4044-c79f-9de8-fb28ae0df991/About");
+ }
+
+ template<> template<>
+ void object::test<6>()
+ {
+ //
+ // test LLUrlEntryPlace - secondlife://<location> URLs
+ //
+ LLUrlEntryPlace url;
+ boost::regex r = url.getPattern();
+
+ testRegex("no valid slurl [1]", r,
+ "secondlife://Ahern/FOO/50/",
+ "");
+
+ testRegex("Ahern (50,50,50) [1]", r,
+ "secondlife://Ahern/50/50/50/",
+ "secondlife://Ahern/50/50/50/");
+
+ testRegex("Ahern (50,50,50) [2]", r,
+ "XXX secondlife://Ahern/50/50/50/ XXX",
+ "secondlife://Ahern/50/50/50/");
+
+ testRegex("Ahern (50,50,50) [3]", r,
+ "XXX secondlife://Ahern/50/50/50 XXX",
+ "secondlife://Ahern/50/50/50");
+
+ testRegex("Ahern (50,50,50) multicase", r,
+ "XXX SecondLife://Ahern/50/50/50/ XXX",
+ "SecondLife://Ahern/50/50/50/");
+
+ testRegex("Ahern (50,50) [1]", r,
+ "XXX secondlife://Ahern/50/50/ XXX",
+ "secondlife://Ahern/50/50/");
+
+ testRegex("Ahern (50,50) [2]", r,
+ "XXX secondlife://Ahern/50/50 XXX",
+ "secondlife://Ahern/50/50");
+
+ // DEV-21577: In-world SLURLs containing "(" or ")" are not treated as a hyperlink in chat
+ testRegex("SLURL with brackets", r,
+ "XXX secondlife://Burning%20Life%20(Hyper)/27/210/30 XXX",
+ "secondlife://Burning%20Life%20(Hyper)/27/210/30");
+
+ // DEV-35459: SLURLs and teleport Links not parsed properly
+ testRegex("SLURL with quote", r,
+ "XXX secondlife://A'ksha%20Oasis/41/166/701 XXX",
+ "secondlife://A'ksha%20Oasis/41/166/701");
+ }
+
+ template<> template<>
+ void object::test<7>()
+ {
+ //
+ // test LLUrlEntryParcel - secondlife://app/parcel Urls
+ //
+ LLUrlEntryParcel url;
+ boost::regex r = url.getPattern();
+
+ testRegex("Invalid Classified Url", r,
+ "secondlife:///app/parcel/0000060e-4b39-e00b-XXXX-d98b1934e3a8/about",
+ "");
+
+ testRegex("Classified Url ", r,
+ "secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about",
+ "secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about");
+
+ testRegex("Classified Url in text", r,
+ "XXX secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about XXX",
+ "secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about");
+
+ testRegex("Classified Url multicase", r,
+ "XXX secondlife:///APP/Parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/About XXX",
+ "secondlife:///APP/Parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/About");
+ }
+ template<> template<>
+ void object::test<8>()
+ {
+ //
+ // test LLUrlEntryTeleport - secondlife://app/teleport URLs
+ //
+ LLUrlEntryTeleport url;
+ boost::regex r = url.getPattern();
+
+ testRegex("no valid teleport [1]", r,
+ "http://slurl.com/secondlife/Ahern/50/50/50/",
+ "");
+
+ testRegex("no valid teleport [2]", r,
+ "secondlife:///app/teleport/",
+ "");
+
+ testRegex("no valid teleport [3]", r,
+ "second-life:///app/teleport/Ahern/50/50/50/",
+ "");
+
+ testRegex("no valid teleport [3]", r,
+ "hhtp://slurl.com/secondlife/Ahern/50/FOO/50/",
+ "");
+
+ testRegex("Ahern (50,50,50) [1]", r,
+ "secondlife:///app/teleport/Ahern/50/50/50/",
+ "secondlife:///app/teleport/Ahern/50/50/50/");
+
+ testRegex("Ahern (50,50,50) [2]", r,
+ "XXX secondlife:///app/teleport/Ahern/50/50/50/ XXX",
+ "secondlife:///app/teleport/Ahern/50/50/50/");
+
+ testRegex("Ahern (50,50,50) [3]", r,
+ "XXX secondlife:///app/teleport/Ahern/50/50/50 XXX",
+ "secondlife:///app/teleport/Ahern/50/50/50");
+
+ testRegex("Ahern (50,50,50) multicase", r,
+ "XXX secondlife:///app/teleport/Ahern/50/50/50/ XXX",
+ "secondlife:///app/teleport/Ahern/50/50/50/");
+
+ testRegex("Ahern (50,50) [1]", r,
+ "XXX secondlife:///app/teleport/Ahern/50/50/ XXX",
+ "secondlife:///app/teleport/Ahern/50/50/");
+
+ testRegex("Ahern (50,50) [2]", r,
+ "XXX secondlife:///app/teleport/Ahern/50/50 XXX",
+ "secondlife:///app/teleport/Ahern/50/50");
+
+ testRegex("Ahern (50)", r,
+ "XXX secondlife:///app/teleport/Ahern/50 XXX",
+ "secondlife:///app/teleport/Ahern/50");
+
+ testRegex("Ahern", r,
+ "XXX secondlife:///app/teleport/Ahern/ XXX",
+ "secondlife:///app/teleport/Ahern/");
+
+ testRegex("Ahern teleport with title", r,
+ "XXX secondlife:///app/teleport/Ahern/50/50/50/?title=YOUR%20TITLE%20HERE! XXX",
+ "secondlife:///app/teleport/Ahern/50/50/50/?title=YOUR%20TITLE%20HERE!");
+
+ testRegex("Ahern teleport with msg", r,
+ "XXX secondlife:///app/teleport/Ahern/50/50/50/?msg=Your%20text%20here. XXX",
+ "secondlife:///app/teleport/Ahern/50/50/50/?msg=Your%20text%20here.");
+
+ // DEV-21577: In-world SLURLs containing "(" or ")" are not treated as a hyperlink in chat
+ testRegex("Teleport with brackets", r,
+ "XXX secondlife:///app/teleport/Burning%20Life%20(Hyper)/27/210/30 XXX",
+ "secondlife:///app/teleport/Burning%20Life%20(Hyper)/27/210/30");
+
+ // DEV-35459: SLURLs and teleport Links not parsed properly
+ testRegex("Teleport url with quote", r,
+ "XXX secondlife:///app/teleport/A'ksha%20Oasis/41/166/701 XXX",
+ "secondlife:///app/teleport/A'ksha%20Oasis/41/166/701");
+ }
+
+ template<> template<>
+ void object::test<9>()
+ {
+ //
+ // test LLUrlEntrySL - general secondlife:// URLs
+ //
+ LLUrlEntrySL url;
+ boost::regex r = url.getPattern();
+
+ testRegex("no valid slapp [1]", r,
+ "http:///app/",
+ "");
+
+ testRegex("valid slapp [1]", r,
+ "secondlife:///app/",
+ "secondlife:///app/");
+
+ testRegex("valid slapp [2]", r,
+ "secondlife:///app/teleport/Ahern/50/50/50/",
+ "secondlife:///app/teleport/Ahern/50/50/50/");
+
+ testRegex("valid slapp [3]", r,
+ "secondlife:///app/foo",
+ "secondlife:///app/foo");
+
+ testRegex("valid slapp [4]", r,
+ "secondlife:///APP/foo?title=Hi%20There",
+ "secondlife:///APP/foo?title=Hi%20There");
+
+ testRegex("valid slapp [5]", r,
+ "secondlife://host/app/",
+ "secondlife://host/app/");
+
+ testRegex("valid slapp [6]", r,
+ "secondlife://host:8080/foo/bar",
+ "secondlife://host:8080/foo/bar");
+ }
+
+ template<> template<>
+ void object::test<10>()
+ {
+ //
+ // test LLUrlEntrySLLabel - general secondlife:// URLs with labels
+ //
+ LLUrlEntrySLLabel url;
+ boost::regex r = url.getPattern();
+
+ testRegex("invalid wiki url [1]", r,
+ "[secondlife:///app/]",
+ "");
+
+ testRegex("invalid wiki url [2]", r,
+ "[secondlife:///app/",
+ "");
+
+ testRegex("invalid wiki url [3]", r,
+ "[secondlife:///app/ Label",
+ "");
+
+ testRegex("agent slurl with label (spaces)", r,
+ "[secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about Text]",
+ "[secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about Text]");
+
+ testRegex("agent slurl with label (tabs)", r,
+ "[secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about\t Text]",
+ "[secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about\t Text]");
+
+ testRegex("agent slurl with label", r,
+ "[secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about FirstName LastName]",
+ "[secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about FirstName LastName]");
+
+ testRegex("teleport slurl with label", r,
+ "XXX [secondlife:///app/teleport/Ahern/50/50/50/ Teleport to Ahern] YYY",
+ "[secondlife:///app/teleport/Ahern/50/50/50/ Teleport to Ahern]");
+ }
+
+ template<> template<>
+ void object::test<11>()
+ {
+ //
+ // test LLUrlEntryHTTPNoProtocol - general URLs without a protocol
+ //
+ LLUrlEntryHTTPNoProtocol url;
+ boost::regex r = url.getPattern();
+
+ testRegex("naked .com URL", r,
+ "see google.com",
+ "google.com");
+
+ testRegex("naked .org URL", r,
+ "see en.wikipedia.org for details",
+ "en.wikipedia.org");
+
+ testRegex("naked .net URL", r,
+ "example.net",
+ "example.net");
+
+ testRegex("naked .edu URL (2 instances)", r,
+ "MIT web site is at web.mit.edu and also www.mit.edu",
+ "web.mit.edu");
+
+ testRegex("don't match e-mail addresses", r,
+ "test@lindenlab.com",
+ "");
+
+ testRegex(".com URL with path", r,
+ "see secondlife.com/status for grid status",
+ "secondlife.com/status");
+
+ testRegex(".com URL with port", r,
+ "secondlife.com:80",
+ "secondlife.com:80");
+
+ testRegex(".com URL with port and path", r,
+ "see secondlife.com:80/status",
+ "secondlife.com:80/status");
+
+ testRegex("www.*.com URL with port and path", r,
+ "see www.secondlife.com:80/status",
+ "www.secondlife.com:80/status");
+
+ testRegex("invalid .com URL [1]", r,
+ "..com",
+ "");
+
+ testRegex("invalid .com URL [2]", r,
+ "you.come",
+ "");
+
+ testRegex("invalid .com URL [3]", r,
+ "recommended",
+ "");
+
+ testRegex("invalid .edu URL", r,
+ "hi there scheduled maitenance has begun",
+ "");
+
+ testRegex("invalid .net URL", r,
+ "foo.netty",
+ "");
+ }
+}
diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp
new file mode 100644
index 0000000000..e8cf135346
--- /dev/null
+++ b/indra/llui/tests/llurlmatch_test.cpp
@@ -0,0 +1,181 @@
+/**
+ * @file llurlmatch_test.cpp
+ * @author Martin Reddy
+ * @brief Unit tests for LLUrlMatch
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+ * this source code is governed by the Linden Lab Source Code Disclosure
+ * Agreement ("Agreement") previously entered between you and Linden
+ * Lab. By accessing, using, copying, modifying or distributing this
+ * software, you acknowledge that you have been informed of your
+ * obligations under the Agreement and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "../llurlmatch.h"
+#include "lltut.h"
+
+// link seam
+LLUIColor::LLUIColor()
+{}
+
+namespace tut
+{
+ struct LLUrlMatchData
+ {
+ };
+
+ typedef test_group<LLUrlMatchData> factory;
+ typedef factory::object object;
+}
+
+namespace
+{
+ tut::factory tf("LLUrlMatch");
+}
+
+namespace tut
+{
+ template<> template<>
+ void object::test<1>()
+ {
+ //
+ // test the empty() method
+ //
+ LLUrlMatch match;
+ ensure("empty()", match.empty());
+
+ match.setValues(0, 1, "http://secondlife.com", "Second Life", "", "", LLUIColor(), "", "");
+ ensure("! empty()", ! match.empty());
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ //
+ // test the getStart() method
+ //
+ LLUrlMatch match;
+ ensure_equals("getStart() == 0", match.getStart(), 0);
+
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
+ ensure_equals("getStart() == 10", match.getStart(), 10);
+ }
+
+ template<> template<>
+ void object::test<3>()
+ {
+ //
+ // test the getEnd() method
+ //
+ LLUrlMatch match;
+ ensure_equals("getEnd() == 0", match.getEnd(), 0);
+
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
+ ensure_equals("getEnd() == 20", match.getEnd(), 20);
+ }
+
+ template<> template<>
+ void object::test<4>()
+ {
+ //
+ // test the getUrl() method
+ //
+ LLUrlMatch match;
+ ensure_equals("getUrl() == ''", match.getUrl(), "");
+
+ match.setValues(10, 20, "http://slurl.com/", "", "", "", LLUIColor(), "", "");
+ ensure_equals("getUrl() == 'http://slurl.com/'", match.getUrl(), "http://slurl.com/");
+
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
+ ensure_equals("getUrl() == '' (2)", match.getUrl(), "");
+ }
+
+ template<> template<>
+ void object::test<5>()
+ {
+ //
+ // test the getLabel() method
+ //
+ LLUrlMatch match;
+ ensure_equals("getLabel() == ''", match.getLabel(), "");
+
+ match.setValues(10, 20, "", "Label", "", "", LLUIColor(), "", "");
+ ensure_equals("getLabel() == 'Label'", match.getLabel(), "Label");
+
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
+ ensure_equals("getLabel() == '' (2)", match.getLabel(), "");
+ }
+
+ template<> template<>
+ void object::test<6>()
+ {
+ //
+ // test the getTooltip() method
+ //
+ LLUrlMatch match;
+ ensure_equals("getTooltip() == ''", match.getTooltip(), "");
+
+ match.setValues(10, 20, "", "", "Info", "", LLUIColor(), "", "");
+ ensure_equals("getTooltip() == 'Info'", match.getTooltip(), "Info");
+
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
+ ensure_equals("getTooltip() == '' (2)", match.getTooltip(), "");
+ }
+
+ template<> template<>
+ void object::test<7>()
+ {
+ //
+ // test the getIcon() method
+ //
+ LLUrlMatch match;
+ ensure_equals("getIcon() == ''", match.getIcon(), "");
+
+ match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "", "");
+ ensure_equals("getIcon() == 'Icon'", match.getIcon(), "Icon");
+
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
+ ensure_equals("getIcon() == '' (2)", match.getIcon(), "");
+ }
+
+ template<> template<>
+ void object::test<8>()
+ {
+ //
+ // test the getMenuName() method
+ //
+ LLUrlMatch match;
+ ensure("getMenuName() empty", match.getMenuName().empty());
+
+ match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "");
+ ensure_equals("getMenuName() == \"xui_file.xml\"", match.getMenuName(), "xui_file.xml");
+
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
+ ensure("getMenuName() empty (2)", match.getMenuName().empty());
+ }
+
+ template<> template<>
+ void object::test<9>()
+ {
+ //
+ // test the getLocation() method
+ //
+ LLUrlMatch match;
+ ensure("getLocation() empty", match.getLocation().empty());
+
+ match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "Paris");
+ ensure_equals("getLocation() == \"Paris\"", match.getLocation(), "Paris");
+
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
+ ensure("getLocation() empty (2)", match.getLocation().empty());
+ }
+}
diff --git a/indra/llvfs/CMakeLists.txt b/indra/llvfs/CMakeLists.txt
index cc0297e3dc..05c7c7860c 100644
--- a/indra/llvfs/CMakeLists.txt
+++ b/indra/llvfs/CMakeLists.txt
@@ -23,6 +23,7 @@ set(llvfs_HEADER_FILES
CMakeLists.txt
lldir.h
+ lldirguard.h
lllfsthread.h
llpidlock.h
llvfile.h
@@ -64,3 +65,17 @@ if (DARWIN)
find_library(CARBON_LIBRARY Carbon)
target_link_libraries(llvfs ${CARBON_LIBRARY})
endif (DARWIN)
+
+
+# Add tests
+include(LLAddBuildTest)
+# UNIT TESTS
+SET(llvfs_TEST_SOURCE_FILES
+ # none so far
+ )
+LL_ADD_PROJECT_UNIT_TESTS(llvfs "${llvfs_TEST_SOURCE_FILES}")
+
+# INTEGRATION TESTS
+set(test_libs llmath llcommon llvfs ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
+# TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests.
+LL_ADD_INTEGRATION_TEST(lldir "" "${test_libs}")
diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp
index d6a6eca341..da4abde451 100644
--- a/indra/llvfs/lldir.cpp
+++ b/indra/llvfs/lldir.cpp
@@ -41,7 +41,9 @@
#endif
#include "lldir.h"
+
#include "llerror.h"
+#include "lltimer.h" // ms_sleep()
#include "lluuid.h"
#if LL_WINDOWS
@@ -125,16 +127,20 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask)
}
const std::string LLDir::findFile(const std::string &filename,
- const std::string searchPath1,
- const std::string searchPath2,
- const std::string searchPath3) const
+ const std::string& searchPath1,
+ const std::string& searchPath2,
+ const std::string& searchPath3) const
{
std::vector<std::string> search_paths;
search_paths.push_back(searchPath1);
search_paths.push_back(searchPath2);
search_paths.push_back(searchPath3);
+ return findFile(filename, search_paths);
+}
- std::vector<std::string>::iterator search_path_iter;
+const std::string LLDir::findFile(const std::string& filename, const std::vector<std::string> search_paths) const
+{
+ std::vector<std::string>::const_iterator search_path_iter;
for (search_path_iter = search_paths.begin();
search_path_iter != search_paths.end();
++search_path_iter)
@@ -194,6 +200,11 @@ const std::string &LLDir::getOSUserAppDir() const
const std::string &LLDir::getLindenUserDir() const
{
+ if (mLindenUserDir.empty())
+ {
+ lldebugs << "getLindenUserDir() called early, we don't have the user name yet - returning empty string to caller" << llendl;
+ }
+
return mLindenUserDir;
}
@@ -287,13 +298,13 @@ const std::string& LLDir::getDefaultSkinDir() const
const std::string LLDir::getSkinBaseDir() const
{
- std::string dir = getAppRODataDir();
- dir += mDirDelimiter;
- dir += "skins";
-
- return dir;
+ return mSkinBaseDir;
}
+const std::string &LLDir::getLLPluginDir() const
+{
+ return mLLPluginDir;
+}
std::string LLDir::getExpandedFilename(ELLPath location, const std::string& filename) const
{
@@ -319,25 +330,19 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
prefix += mDirDelimiter;
prefix += "app_settings";
break;
-
+
case LL_PATH_CHARACTER:
prefix = getAppRODataDir();
prefix += mDirDelimiter;
prefix += "character";
break;
- case LL_PATH_MOTIONS:
- prefix = getAppRODataDir();
- prefix += mDirDelimiter;
- prefix += "motions";
- break;
-
case LL_PATH_HELP:
prefix = "help";
break;
case LL_PATH_CACHE:
- prefix = getCacheDir();
+ prefix = getCacheDir();
break;
case LL_PATH_USER_SETTINGS:
@@ -348,6 +353,11 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
case LL_PATH_PER_SL_ACCOUNT:
prefix = getLindenUserDir();
+ if (prefix.empty())
+ {
+ // if we're asking for the per-SL-account directory but we haven't logged in yet (or otherwise don't know the account name from which to build this string), then intentionally return a blank string to the caller and skip the below warning about a blank prefix.
+ return std::string();
+ }
break;
case LL_PATH_CHAT_LOGS:
@@ -372,28 +382,38 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
prefix = getSkinDir();
break;
- case LL_PATH_SKINS:
- prefix = getAppRODataDir();
+ case LL_PATH_DEFAULT_SKIN:
+ prefix = getDefaultSkinDir();
+ break;
+
+ case LL_PATH_USER_SKIN:
+ prefix = getOSUserAppDir();
+ prefix += mDirDelimiter;
+ prefix += "user_settings";
prefix += mDirDelimiter;
prefix += "skins";
break;
- //case LL_PATH_HTML:
- // prefix = getSkinDir();
- // prefix += mDirDelimiter;
- // prefix += "html";
- // break;
+ case LL_PATH_SKINS:
+ prefix = getSkinBaseDir();
+ break;
- case LL_PATH_MOZILLA_PROFILE:
- prefix = getOSUserAppDir();
+ case LL_PATH_LOCAL_ASSETS:
+ prefix = getAppRODataDir();
prefix += mDirDelimiter;
- prefix += "browser_profile";
+ prefix += "local_assets";
break;
case LL_PATH_EXECUTABLE:
prefix = getExecutableDir();
break;
+ case LL_PATH_FONTS:
+ prefix = getAppRODataDir();
+ prefix += mDirDelimiter;
+ prefix += "fonts";
+ break;
+
default:
llassert(0);
}
@@ -409,6 +429,11 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
filename = subdir1 + mDirDelimiter + filename;
}
+ if (prefix.empty())
+ {
+ llwarns << "prefix is empty, possible bad filename" << llendl;
+ }
+
std::string expanded_filename;
if (!filename.empty())
{
@@ -465,6 +490,8 @@ std::string LLDir::getDirName(const std::string& filepath) const
std::string LLDir::getExtension(const std::string& filepath) const
{
+ if (filepath.empty())
+ return std::string();
std::string basename = getBaseFileName(filepath, false);
std::size_t offset = basename.find_last_of('.');
std::string exten = (offset == std::string::npos || offset == 0) ? "" : basename.substr(offset+1);
@@ -488,11 +515,14 @@ std::string LLDir::findSkinnedFilename(const std::string &subdir1, const std::st
std::string subdirs = ((subdir1.empty() ? "" : mDirDelimiter) + subdir1)
+ ((subdir2.empty() ? "" : mDirDelimiter) + subdir2);
- std::string found_file = findFile(filename,
- getUserSkinDir() + subdirs, // first look in user skin override
- getSkinDir() + subdirs, // then in current skin
- getDefaultSkinDir() + subdirs); // and last in default skin
+ std::vector<std::string> search_paths;
+
+ search_paths.push_back(getUserSkinDir() + subdirs); // first look in user skin override
+ search_paths.push_back(getSkinDir() + subdirs); // then in current skin
+ search_paths.push_back(getDefaultSkinDir() + subdirs); // then default skin
+ search_paths.push_back(getCacheDir() + subdirs); // and last in preload directory
+ std::string found_file = findFile(filename, search_paths);
return found_file;
}
@@ -537,7 +567,7 @@ std::string LLDir::getForbiddenFileChars()
void LLDir::setLindenUserDir(const std::string &first, const std::string &last)
{
- // if both first and last aren't set, assume we're grabbing the cached dir
+ // if both first and last aren't set, that's bad.
if (!first.empty() && !last.empty())
{
// some platforms have case-sensitive filesystems, so be
@@ -551,10 +581,11 @@ void LLDir::setLindenUserDir(const std::string &first, const std::string &last)
mLindenUserDir += firstlower;
mLindenUserDir += "_";
mLindenUserDir += lastlower;
+ llinfos << "Got name for LLDir::setLindenUserDir(first='" << first << "', last='" << last << "')" << llendl;
}
else
{
- llerrs << "Invalid name for LLDir::setLindenUserDir" << llendl;
+ llerrs << "Invalid name for LLDir::setLindenUserDir(first='" << first << "', last='" << last << "')" << llendl;
}
dumpCurrentDirectories();
@@ -597,9 +628,7 @@ void LLDir::setPerAccountChatLogsDir(const std::string &first, const std::string
void LLDir::setSkinFolder(const std::string &skin_folder)
{
- mSkinDir = getAppRODataDir();
- mSkinDir += mDirDelimiter;
- mSkinDir += "skins";
+ mSkinDir = getSkinBaseDir();
mSkinDir += mDirDelimiter;
mSkinDir += skin_folder;
@@ -613,9 +642,7 @@ void LLDir::setSkinFolder(const std::string &skin_folder)
// base skin which is used as fallback for all skinned files
// e.g. c:\program files\secondlife\skins\default
- mDefaultSkinDir = getAppRODataDir();
- mDefaultSkinDir += mDirDelimiter;
- mDefaultSkinDir += "skins";
+ mDefaultSkinDir = getSkinBaseDir();
mDefaultSkinDir += mDirDelimiter;
mDefaultSkinDir += "default";
}
@@ -660,12 +687,8 @@ void LLDir::dumpCurrentDirectories()
LL_DEBUGS2("AppInit","Directories") << " LindenUserDir: " << getLindenUserDir() << LL_ENDL;
LL_DEBUGS2("AppInit","Directories") << " TempDir: " << getTempDir() << LL_ENDL;
LL_DEBUGS2("AppInit","Directories") << " CAFile: " << getCAFile() << LL_ENDL;
+ LL_DEBUGS2("AppInit","Directories") << " SkinBaseDir: " << getSkinBaseDir() << LL_ENDL;
LL_DEBUGS2("AppInit","Directories") << " SkinDir: " << getSkinDir() << LL_ENDL;
-
-#if LL_LIBXUL_ENABLED
- LL_DEBUGS2("AppInit","Directories") << " HTML Path: " << getExpandedFilename( LL_PATH_HTML, "" ) << llendl;
- LL_DEBUGS2("AppInit","Directories") << " Mozilla Profile Path: " << getExpandedFilename( LL_PATH_MOZILLA_PROFILE, "" ) << llendl;
-#endif
}
diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h
index 760b6512a5..9067d75bac 100644
--- a/indra/llvfs/lldir.h
+++ b/indra/llvfs/lldir.h
@@ -38,26 +38,27 @@
#define MAX_PATH MAXPATHLEN
#endif
-// these numbers *may* get serialized, so we need to be explicit
+// these numbers *may* get serialized (really??), so we need to be explicit
typedef enum ELLPath
{
LL_PATH_NONE = 0,
LL_PATH_USER_SETTINGS = 1,
LL_PATH_APP_SETTINGS = 2,
- LL_PATH_PER_SL_ACCOUNT = 3,
+ LL_PATH_PER_SL_ACCOUNT = 3, // returns/expands to blank string if we don't know the account name yet
LL_PATH_CACHE = 4,
LL_PATH_CHARACTER = 5,
- LL_PATH_MOTIONS = 6,
- LL_PATH_HELP = 7,
- LL_PATH_LOGS = 8,
- LL_PATH_TEMP = 9,
- LL_PATH_SKINS = 10,
- LL_PATH_TOP_SKIN = 11,
- LL_PATH_CHAT_LOGS = 12,
- LL_PATH_PER_ACCOUNT_CHAT_LOGS = 13,
- LL_PATH_MOZILLA_PROFILE = 14,
-// LL_PATH_HTML = 15,
+ LL_PATH_HELP = 6,
+ LL_PATH_LOGS = 7,
+ LL_PATH_TEMP = 8,
+ LL_PATH_SKINS = 9,
+ LL_PATH_TOP_SKIN = 10,
+ LL_PATH_CHAT_LOGS = 11,
+ LL_PATH_PER_ACCOUNT_CHAT_LOGS = 12,
+ LL_PATH_USER_SKIN = 14,
+ LL_PATH_LOCAL_ASSETS = 15,
LL_PATH_EXECUTABLE = 16,
+ LL_PATH_DEFAULT_SKIN = 17,
+ LL_PATH_FONTS = 18,
LL_PATH_LAST
} ELLPath;
@@ -68,8 +69,13 @@ class LLDir
LLDir();
virtual ~LLDir();
- virtual void initAppDirs(const std::string &app_name) = 0;
- public:
+ // app_name - Usually SecondLife, used for creating settings directories
+ // in OS-specific location, such as C:\Documents and Settings
+ // app_read_only_data_dir - Usually the source code directory, used
+ // for test applications to read newview data files.
+ virtual void initAppDirs(const std::string &app_name,
+ const std::string& app_read_only_data_dir = "") = 0;
+
virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask);
// pure virtual functions
@@ -79,7 +85,12 @@ class LLDir
virtual std::string getCurPath() = 0;
virtual BOOL fileExists(const std::string &filename) const = 0;
- const std::string findFile(const std::string &filename, const std::string searchPath1 = "", const std::string searchPath2 = "", const std::string searchPath3 = "") const;
+ const std::string findFile(const std::string& filename, const std::vector<std::string> filenames) const;
+ const std::string findFile(const std::string& filename, const std::string& searchPath1 = "", const std::string& searchPath2 = "", const std::string& searchPath3 = "") const;
+
+ virtual std::string getLLPluginLauncher() = 0; // full path and name for the plugin shell
+ virtual std::string getLLPluginFilename(std::string base_name) = 0; // full path and name to the plugin DSO for this base_name (i.e. 'FOO' -> '/bar/baz/libFOO.so')
+
const std::string &getExecutablePathAndName() const; // Full pathname of the executable
const std::string &getAppName() const; // install directory under progams/ ie "SecondLife"
const std::string &getExecutableDir() const; // Directory where the executable is located
@@ -100,6 +111,7 @@ class LLDir
const std::string &getUserSkinDir() const; // User-specified skin folder with user modifications. e.g. c:\documents and settings\username\application data\second life\skins\curskin
const std::string &getDefaultSkinDir() const; // folder for default skin. e.g. c:\program files\second life\skins\default
const std::string getSkinBaseDir() const; // folder that contains all installed skins (not user modifications). e.g. c:\program files\second life\skins
+ const std::string &getLLPluginDir() const; // Directory containing plugins and plugin shell
// Expanded filename
std::string getExpandedFilename(ELLPath location, const std::string &filename) const;
@@ -153,9 +165,11 @@ protected:
std::string mDefaultCacheDir; // default cache diretory
std::string mOSCacheDir; // operating system cache dir
std::string mDirDelimiter;
+ std::string mSkinBaseDir; // Base for skins paths.
std::string mSkinDir; // Location for current skin info.
std::string mDefaultSkinDir; // Location for default skin info.
std::string mUserSkinDir; // Location for user-modified skin info.
+ std::string mLLPluginDir; // Location for plugins and plugin shell
};
void dir_exists_or_crash(const std::string &dir_name);
diff --git a/indra/llvfs/lldir_linux.cpp b/indra/llvfs/lldir_linux.cpp
index 8ff8c5d1c6..a9736560ec 100644
--- a/indra/llvfs/lldir_linux.cpp
+++ b/indra/llvfs/lldir_linux.cpp
@@ -99,9 +99,23 @@ LLDir_Linux::LLDir_Linux()
#else
mAppRODataDir = tmp_str;
#endif
+ U32 indra_pos = mExecutableDir.find("/indra");
+ if (indra_pos != std::string::npos)
+ {
+ // ...we're in a dev checkout
+ mSkinBaseDir = mExecutableDir.substr(0, indra_pos) + "/indra/newview/skins";
+ llinfos << "Running in dev checkout with mSkinBaseDir "
+ << mSkinBaseDir << llendl;
+ }
+ else
+ {
+ // ...normal installation running
+ mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
+ }
+
mOSUserDir = getCurrentUserHome(tmp_str);
mOSUserAppDir = "";
- mLindenUserDir = tmp_str;
+ mLindenUserDir = "";
char path [32]; /* Flawfinder: ignore */
@@ -128,6 +142,8 @@ LLDir_Linux::LLDir_Linux()
}
}
+ mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin";
+
// *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something.
mTempDir = "/tmp";
}
@@ -139,8 +155,15 @@ LLDir_Linux::~LLDir_Linux()
// Implementation
-void LLDir_Linux::initAppDirs(const std::string &app_name)
+void LLDir_Linux::initAppDirs(const std::string &app_name,
+ const std::string& app_read_only_data_dir)
{
+ // Allow override so test apps can read newview directory
+ if (!app_read_only_data_dir.empty())
+ {
+ mAppRODataDir = app_read_only_data_dir;
+ mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
+ }
mAppName = app_name;
std::string upper_app_name(app_name);
@@ -203,15 +226,6 @@ void LLDir_Linux::initAppDirs(const std::string &app_name)
}
}
- res = LLFile::mkdir(getExpandedFilename(LL_PATH_MOZILLA_PROFILE,""));
- if (res == -1)
- {
- if (errno != EEXIST)
- {
- llwarns << "Couldn't create LL_PATH_MOZILLA_PROFILE dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl;
- }
- }
-
mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem");
}
@@ -370,3 +384,15 @@ BOOL LLDir_Linux::fileExists(const std::string &filename) const
}
}
+
+/*virtual*/ std::string LLDir_Linux::getLLPluginLauncher()
+{
+ return gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() +
+ "SLPlugin";
+}
+
+/*virtual*/ std::string LLDir_Linux::getLLPluginFilename(std::string base_name)
+{
+ return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() +
+ "lib" + base_name + ".so";
+}
diff --git a/indra/llvfs/lldir_linux.h b/indra/llvfs/lldir_linux.h
index 20b408f8dc..1fec15c5c6 100644
--- a/indra/llvfs/lldir_linux.h
+++ b/indra/llvfs/lldir_linux.h
@@ -44,7 +44,8 @@ public:
LLDir_Linux();
virtual ~LLDir_Linux();
- virtual void initAppDirs(const std::string &app_name);
+ /*virtual*/ void initAppDirs(const std::string &app_name,
+ const std::string& app_read_only_data_dir);
public:
virtual std::string getCurPath();
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
@@ -52,6 +53,9 @@ public:
virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
/*virtual*/ BOOL fileExists(const std::string &filename) const;
+ /*virtual*/ std::string getLLPluginLauncher();
+ /*virtual*/ std::string getLLPluginFilename(std::string base_name);
+
private:
DIR *mDirp;
int mCurrentDirIndex;
diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp
index d4dee5a02e..7bc6f63e1f 100644
--- a/indra/llvfs/lldir_mac.cpp
+++ b/indra/llvfs/lldir_mac.cpp
@@ -68,7 +68,8 @@ static void CFStringRefToLLString(CFStringRef stringRef, std::string &llString,
{
if (stringRef)
{
- long bufferSize = CFStringGetLength(stringRef) + 1;
+ long stringSize = CFStringGetLength(stringRef) + 1;
+ long bufferSize = CFStringGetMaximumSizeForEncoding(stringSize,kCFStringEncodingUTF8);
char* buffer = new char[bufferSize];
memset(buffer, 0, bufferSize);
if (CFStringGetCString(stringRef, buffer, bufferSize, kCFStringEncodingUTF8))
@@ -142,9 +143,34 @@ LLDir_Mac::LLDir_Mac()
CFURLRefToLLString(executableParentURLRef, mExecutableDir, true);
// mAppRODataDir
- CFURLRef resourcesURLRef = CFBundleCopyResourcesDirectoryURL(mainBundleRef);
+
+
+ // *NOTE: When running in a dev tree, use the copy of
+ // skins in indra/newview/ rather than in the application bundle. This
+ // mirrors Windows dev environment behavior and allows direct checkin
+ // of edited skins/xui files. JC
+
+ // MBW -- This keeps the mac application from finding other things.
+ // If this is really for skins, it should JUST apply to skins.
+
+ CFURLRef resourcesURLRef = CFBundleCopyResourcesDirectoryURL(mainBundleRef);
CFURLRefToLLString(resourcesURLRef, mAppRODataDir, true);
+ U32 indra_pos = mExecutableDir.find("/indra");
+ if (indra_pos != std::string::npos)
+ {
+ // ...we're in a dev checkout
+ mSkinBaseDir = mExecutableDir.substr(0, indra_pos)
+ + "/indra/newview/skins";
+ llinfos << "Running in dev checkout with mSkinBaseDir "
+ << mSkinBaseDir << llendl;
+ }
+ else
+ {
+ // ...normal installation running
+ mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
+ }
+
// mOSUserDir
error = FSFindFolder(kUserDomain, kApplicationSupportFolderType, true, &fileRef);
if (error == noErr)
@@ -190,6 +216,8 @@ LLDir_Mac::LLDir_Mac()
}
mWorkingDir = getCurPath();
+
+ mLLPluginDir = mAppRODataDir + mDirDelimiter + "llplugin";
CFRelease(executableURLRef);
executableURLRef = NULL;
@@ -203,8 +231,15 @@ LLDir_Mac::~LLDir_Mac()
// Implementation
-void LLDir_Mac::initAppDirs(const std::string &app_name)
+void LLDir_Mac::initAppDirs(const std::string &app_name,
+ const std::string& app_read_only_data_dir)
{
+ // Allow override so test apps can read newview directory
+ if (!app_read_only_data_dir.empty())
+ {
+ mAppRODataDir = app_read_only_data_dir;
+ mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
+ }
mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem");
//dumpCurrentDirectories();
@@ -388,4 +423,17 @@ BOOL LLDir_Mac::fileExists(const std::string &filename) const
}
+/*virtual*/ std::string LLDir_Mac::getLLPluginLauncher()
+{
+ return gDirUtilp->getAppRODataDir() + gDirUtilp->getDirDelimiter() +
+ "SLPlugin";
+}
+
+/*virtual*/ std::string LLDir_Mac::getLLPluginFilename(std::string base_name)
+{
+ return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() +
+ base_name + ".dylib";
+}
+
+
#endif // LL_DARWIN
diff --git a/indra/llvfs/lldir_mac.h b/indra/llvfs/lldir_mac.h
index 28d48a0b6a..834acc7262 100644
--- a/indra/llvfs/lldir_mac.h
+++ b/indra/llvfs/lldir_mac.h
@@ -43,7 +43,8 @@ public:
LLDir_Mac();
virtual ~LLDir_Mac();
- virtual void initAppDirs(const std::string &app_name);
+ /*virtual*/ void initAppDirs(const std::string &app_name,
+ const std::string& app_read_only_data_dir);
public:
virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask);
virtual std::string getCurPath();
@@ -52,6 +53,9 @@ public:
virtual void getRandomFileInDir(const std::string &dirname, const std::string &ask, std::string &fname);
virtual BOOL fileExists(const std::string &filename) const;
+ /*virtual*/ std::string getLLPluginLauncher();
+ /*virtual*/ std::string getLLPluginFilename(std::string base_name);
+
private:
int mCurrentDirIndex;
int mCurrentDirCount;
diff --git a/indra/llvfs/lldir_solaris.cpp b/indra/llvfs/lldir_solaris.cpp
index 9553d923aa..8ac5a41e93 100644
--- a/indra/llvfs/lldir_solaris.cpp
+++ b/indra/llvfs/lldir_solaris.cpp
@@ -100,7 +100,7 @@ LLDir_Solaris::LLDir_Solaris()
mAppRODataDir = strdup(tmp_str);
mOSUserDir = getCurrentUserHome(tmp_str);
mOSUserAppDir = "";
- mLindenUserDir = tmp_str;
+ mLindenUserDir = "";
char path [LL_MAX_PATH]; /* Flawfinder: ignore */
@@ -161,6 +161,8 @@ LLDir_Solaris::LLDir_Solaris()
}
}
+ mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin";
+
// *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something.
mTempDir = "/tmp";
}
@@ -172,8 +174,14 @@ LLDir_Solaris::~LLDir_Solaris()
// Implementation
-void LLDir_Solaris::initAppDirs(const std::string &app_name)
+void LLDir_Solaris::initAppDirs(const std::string &app_name,
+ const std::string& app_read_only_data_dir)
{
+ // Allow override so test apps can read newview directory
+ if (!app_read_only_data_dir.empty())
+ {
+ mAppRODataDir = app_read_only_data_dir;
+ }
mAppName = app_name;
std::string upper_app_name(app_name);
@@ -236,15 +244,6 @@ void LLDir_Solaris::initAppDirs(const std::string &app_name)
}
}
- res = LLFile::mkdir(getExpandedFilename(LL_PATH_MOZILLA_PROFILE,""));
- if (res == -1)
- {
- if (errno != EEXIST)
- {
- llwarns << "Couldn't create LL_PATH_MOZILLA_PROFILE dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl;
- }
- }
-
mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem");
}
diff --git a/indra/llvfs/lldir_solaris.h b/indra/llvfs/lldir_solaris.h
index 139754ba28..1fa8348355 100644
--- a/indra/llvfs/lldir_solaris.h
+++ b/indra/llvfs/lldir_solaris.h
@@ -44,7 +44,8 @@ public:
LLDir_Solaris();
virtual ~LLDir_Solaris();
- virtual void initAppDirs(const std::string &app_name);
+ /*virtual*/ void initAppDirs(const std::string &app_name,
+ const std::string& app_read_only_data_dir);
public:
virtual std::string getCurPath();
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp
index 19b9bcc6ea..4eb10c842b 100644
--- a/indra/llvfs/lldir_win32.cpp
+++ b/indra/llvfs/lldir_win32.cpp
@@ -121,15 +121,21 @@ LLDir_Win32::LLDir_Win32()
GetCurrentDirectory(MAX_PATH, w_str);
mExecutableDir = utf16str_to_utf8str(llutf16string(w_str));
#endif
-
- // When running in a dev tree, app_settings is under indra/newview/
- // but in production it is under Program Files/SecondLife/
- // Attempt to detect which one we're using. JC
- if (mExecutableDir.find("indra") != std::string::npos)
- mAppRODataDir = getCurPath();
- else
- mAppRODataDir = mExecutableDir;
+ mAppRODataDir = ".";
+
+ mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
+
+ if (mExecutableDir.find("indra") == std::string::npos)
+ {
+ // Running from installed directory. Make sure current
+ // directory isn't something crazy (e.g. if invoking from
+ // command line).
+ SetCurrentDirectory(utf8str_to_utf16str(mExecutableDir).c_str());
+ GetCurrentDirectory(MAX_PATH, w_str);
+ mWorkingDir = utf16str_to_utf8str(llutf16string(w_str));
+ }
+ llinfos << "mAppRODataDir = " << mAppRODataDir << llendl;
// Build the default cache directory
mDefaultCacheDir = buildSLOSCacheDir();
@@ -143,6 +149,8 @@ LLDir_Win32::LLDir_Win32()
llwarns << "Couldn't create LL_PATH_CACHE dir " << mDefaultCacheDir << llendl;
}
}
+
+ mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin";
}
LLDir_Win32::~LLDir_Win32()
@@ -151,8 +159,15 @@ LLDir_Win32::~LLDir_Win32()
// Implementation
-void LLDir_Win32::initAppDirs(const std::string &app_name)
+void LLDir_Win32::initAppDirs(const std::string &app_name,
+ const std::string& app_read_only_data_dir)
{
+ // Allow override so test apps can read newview directory
+ if (!app_read_only_data_dir.empty())
+ {
+ mAppRODataDir = app_read_only_data_dir;
+ mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
+ }
mAppName = app_name;
mOSUserAppDir = mOSUserDir;
mOSUserAppDir += "\\";
@@ -197,15 +212,14 @@ void LLDir_Win32::initAppDirs(const std::string &app_name)
}
}
- res = LLFile::mkdir(getExpandedFilename(LL_PATH_MOZILLA_PROFILE,""));
+ res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SKIN,""));
if (res == -1)
{
if (errno != EEXIST)
{
- llwarns << "Couldn't create LL_PATH_MOZILLA_PROFILE dir " << getExpandedFilename(LL_PATH_MOZILLA_PROFILE,"") << llendl;
+ llwarns << "Couldn't create LL_PATH_SKINS dir " << getExpandedFilename(LL_PATH_USER_SKIN,"") << llendl;
}
}
-
mCAFile = getExpandedFilename(LL_PATH_APP_SETTINGS, "CA.pem");
}
@@ -378,6 +392,19 @@ BOOL LLDir_Win32::fileExists(const std::string &filename) const
}
+/*virtual*/ std::string LLDir_Win32::getLLPluginLauncher()
+{
+ return gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() +
+ "SLPlugin.exe";
+}
+
+/*virtual*/ std::string LLDir_Win32::getLLPluginFilename(std::string base_name)
+{
+ return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() +
+ base_name + ".dll";
+}
+
+
#if 0
// Utility function to get version number of a DLL
diff --git a/indra/llvfs/lldir_win32.h b/indra/llvfs/lldir_win32.h
index 8710ca50e1..c2acfa6bd4 100644
--- a/indra/llvfs/lldir_win32.h
+++ b/indra/llvfs/lldir_win32.h
@@ -41,7 +41,8 @@ public:
LLDir_Win32();
virtual ~LLDir_Win32();
- /*virtual*/ void initAppDirs(const std::string &app_name);
+ /*virtual*/ void initAppDirs(const std::string &app_name,
+ const std::string& app_read_only_data_dir);
/*virtual*/ std::string getCurPath();
/*virtual*/ U32 countFilesInDir(const std::string &dirname, const std::string &mask);
@@ -49,6 +50,9 @@ public:
/*virtual*/ void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
/*virtual*/ BOOL fileExists(const std::string &filename) const;
+ /*virtual*/ std::string getLLPluginLauncher();
+ /*virtual*/ std::string getLLPluginFilename(std::string base_name);
+
private:
BOOL LLDir_Win32::getNextFileInDir(const llutf16string &dirname, const std::string &mask, std::string &fname, BOOL wrap);
diff --git a/indra/llvfs/lldirguard.h b/indra/llvfs/lldirguard.h
new file mode 100644
index 0000000000..85366120d8
--- /dev/null
+++ b/indra/llvfs/lldirguard.h
@@ -0,0 +1,78 @@
+/**
+ * @file lldirguard.h
+ * @brief Protect working directory from being changed in scope.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_DIRGUARD_H
+#define LL_DIRGUARD_H
+
+#include "linden_common.h"
+#include "llerror.h"
+
+#if LL_WINDOWS
+class LLDirectoryGuard
+{
+public:
+ LLDirectoryGuard()
+ {
+ mOrigDirLen = GetCurrentDirectory(MAX_PATH, mOrigDir);
+ }
+
+ ~LLDirectoryGuard()
+ {
+ mFinalDirLen = GetCurrentDirectory(MAX_PATH, mFinalDir);
+ if ((mOrigDirLen!=mFinalDirLen) ||
+ (wcsncmp(mOrigDir,mFinalDir,mOrigDirLen)!=0))
+ {
+ // Dir has changed
+ std::string mOrigDirUtf8 = utf16str_to_utf8str(llutf16string(mOrigDir));
+ std::string mFinalDirUtf8 = utf16str_to_utf8str(llutf16string(mFinalDir));
+ llinfos << "Resetting working dir from " << mFinalDirUtf8 << " to " << mOrigDirUtf8 << llendl;
+ SetCurrentDirectory(mOrigDir);
+ }
+ }
+
+private:
+ TCHAR mOrigDir[MAX_PATH];
+ DWORD mOrigDirLen;
+ TCHAR mFinalDir[MAX_PATH];
+ DWORD mFinalDirLen;
+};
+#else // No-op outside Windows.
+class LLDirectoryGuard
+{
+public:
+ LLDirectoryGuard() {}
+ ~LLDirectoryGuard() {}
+};
+#endif
+
+
+#endif
diff --git a/indra/llvfs/lllfsthread.cpp b/indra/llvfs/lllfsthread.cpp
index 704e1ab142..e85cc437f4 100644
--- a/indra/llvfs/lllfsthread.cpp
+++ b/indra/llvfs/lllfsthread.cpp
@@ -189,7 +189,7 @@ bool LLLFSThread::Request::processRequest()
{
llassert(mOffset >= 0);
LLAPRFile infile ;
- infile.open(mThread->getLocalAPRFilePool(), mFileName, LL_APR_RB);
+ infile.open(mFileName, LL_APR_RB, mThread->getLocalAPRFilePool());
if (!infile.getFileHandle())
{
llwarns << "LLLFS: Unable to read file: " << mFileName << llendl;
@@ -213,7 +213,7 @@ bool LLLFSThread::Request::processRequest()
if (mOffset < 0)
flags |= APR_APPEND;
LLAPRFile outfile ;
- outfile.open(mThread->getLocalAPRFilePool(), mFileName, flags);
+ outfile.open(mFileName, flags, mThread->getLocalAPRFilePool());
if (!outfile.getFileHandle())
{
llwarns << "LLLFS: Unable to write file: " << mFileName << llendl;
diff --git a/indra/llvfs/lllfsthread.h b/indra/llvfs/lllfsthread.h
index 5a11cb33d7..3139693302 100644
--- a/indra/llvfs/lllfsthread.h
+++ b/indra/llvfs/lllfsthread.h
@@ -39,7 +39,7 @@
#include <set>
#include "llapr.h"
-
+#include "llpointer.h"
#include "llqueuedthread.h"
//============================================================================
diff --git a/indra/llvfs/llpidlock.cpp b/indra/llvfs/llpidlock.cpp
index e231002a52..95e3692e10 100755
--- a/indra/llvfs/llpidlock.cpp
+++ b/indra/llvfs/llpidlock.cpp
@@ -5,7 +5,7 @@
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
- * Copyright (c) 2007, Linden Research, Inc.
+ * Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -13,12 +13,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
@@ -40,6 +41,15 @@
#include "llframetimer.h"
#if LL_WINDOWS //For windows platform.
+
+#include <windows.h>
+
+namespace {
+ inline DWORD getpid() {
+ return GetCurrentProcessId();
+ }
+}
+
bool isProcessAlive(U32 pid)
{
return (bool) GetProcessVersion((DWORD)pid);
@@ -61,7 +71,7 @@ class LLPidLockFile
mSaving(FALSE), mWaiting(FALSE),
mClean(TRUE), mPID(getpid())
{
- mLockName = gDirUtilp->getTempDir() + "/savelock";
+ mLockName = gDirUtilp->getTempDir() + gDirUtilp->getDirDelimiter() + "savelock";
}
bool requestLock(LLNameTable<void *> *name_table, bool autosave,
bool force_immediate=FALSE, F32 timeout=300.0);
diff --git a/indra/llvfs/llpidlock.h b/indra/llvfs/llpidlock.h
index 44ed8caf46..496e99cf5a 100755
--- a/indra/llvfs/llpidlock.h
+++ b/indra/llvfs/llpidlock.h
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
- * Copyright (c) 2001-2007, Linden Research, Inc.
+ * Copyright (c) 2001-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -12,12 +12,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
@@ -36,17 +37,9 @@
class LLSD;
class LLFrameTimer;
-#if LL_WINDOWS //For windows platform.
-
-#include <windows.h>
-
-#define getpid GetCurrentProcessId
-
-#else //Everyone Else
-
+#if !LL_WINDOWS //For non-windows platforms.
#include <signal.h>
-
-#endif //Everyone else.
+#endif
namespace LLPidLock
{
diff --git a/indra/llvfs/llvfile.cpp b/indra/llvfs/llvfile.cpp
index 6b1563bab1..5fdf41188d 100644
--- a/indra/llvfs/llvfile.cpp
+++ b/indra/llvfs/llvfile.cpp
@@ -44,6 +44,8 @@ const S32 LLVFile::WRITE = 0x00000002;
const S32 LLVFile::READ_WRITE = 0x00000003; // LLVFile::READ & LLVFile::WRITE
const S32 LLVFile::APPEND = 0x00000006; // 0x00000004 & LLVFile::WRITE
+static LLFastTimer::DeclareTimer FTM_VFILE_WAIT("VFile Wait");
+
//----------------------------------------------------------------------------
LLVFSThread* LLVFile::sVFSThread = NULL;
BOOL LLVFile::sAllocdVFSThread = FALSE;
@@ -318,7 +320,7 @@ BOOL LLVFile::setMaxSize(S32 size)
if (!mVFS->checkAvailable(size))
{
- LLFastTimer t(LLFastTimer::FTM_VFILE_WAIT);
+ LLFastTimer t(FTM_VFILE_WAIT);
S32 count = 0;
while (sVFSThread->getPending() > 1000)
{
@@ -426,7 +428,7 @@ bool LLVFile::isLocked(EVFSLock lock)
void LLVFile::waitForLock(EVFSLock lock)
{
- LLFastTimer t(LLFastTimer::FTM_VFILE_WAIT);
+ LLFastTimer t(FTM_VFILE_WAIT);
// spin until the lock clears
while (isLocked(lock))
{
diff --git a/indra/llvfs/llvfs.cpp b/indra/llvfs/llvfs.cpp
index ef8c4d6c7f..9ce1e75d06 100644
--- a/indra/llvfs/llvfs.cpp
+++ b/indra/llvfs/llvfs.cpp
@@ -46,7 +46,9 @@
#endif
#include "llvfs.h"
+
#include "llstl.h"
+#include "lltimer.h"
const S32 FILE_BLOCK_MASK = 0x000003FF; // 1024-byte blocks
const S32 VFS_CLEANUP_SIZE = 5242880; // how much space we free up in a single stroke
diff --git a/indra/llvfs/tests/lldir_test.cpp b/indra/llvfs/tests/lldir_test.cpp
new file mode 100644
index 0000000000..9befa59477
--- /dev/null
+++ b/indra/llvfs/tests/lldir_test.cpp
@@ -0,0 +1,266 @@
+/**
+ * @file lldir_test.cpp
+ * @date 2008-05
+ * @brief LLDir test cases.
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../lldir.h"
+
+#include "../test/lltut.h"
+
+
+namespace tut
+{
+ struct LLDirTest
+ {
+ };
+ typedef test_group<LLDirTest> LLDirTest_t;
+ typedef LLDirTest_t::object LLDirTest_object_t;
+ tut::LLDirTest_t tut_LLDirTest("LLDir");
+
+ template<> template<>
+ void LLDirTest_object_t::test<1>()
+ // getDirDelimiter
+ {
+ ensure("getDirDelimiter", !gDirUtilp->getDirDelimiter().empty());
+ }
+
+ template<> template<>
+ void LLDirTest_object_t::test<2>()
+ // getBaseFileName
+ {
+ std::string delim = gDirUtilp->getDirDelimiter();
+ std::string rawFile = "foo";
+ std::string rawFileExt = "foo.bAr";
+ std::string rawFileNullExt = "foo.";
+ std::string rawExt = ".bAr";
+ std::string rawDot = ".";
+ std::string pathNoExt = "aa" + delim + "bb" + delim + "cc" + delim + "dd" + delim + "ee";
+ std::string pathExt = pathNoExt + ".eXt";
+ std::string dottedPathNoExt = "aa" + delim + "bb" + delim + "cc.dd" + delim + "ee";
+ std::string dottedPathExt = dottedPathNoExt + ".eXt";
+
+ // foo[.bAr]
+
+ ensure_equals("getBaseFileName/r-no-ext/no-strip-exten",
+ gDirUtilp->getBaseFileName(rawFile, false),
+ "foo");
+
+ ensure_equals("getBaseFileName/r-no-ext/strip-exten",
+ gDirUtilp->getBaseFileName(rawFile, true),
+ "foo");
+
+ ensure_equals("getBaseFileName/r-ext/no-strip-exten",
+ gDirUtilp->getBaseFileName(rawFileExt, false),
+ "foo.bAr");
+
+ ensure_equals("getBaseFileName/r-ext/strip-exten",
+ gDirUtilp->getBaseFileName(rawFileExt, true),
+ "foo");
+
+ // foo.
+
+ ensure_equals("getBaseFileName/rn-no-ext/no-strip-exten",
+ gDirUtilp->getBaseFileName(rawFileNullExt, false),
+ "foo.");
+
+ ensure_equals("getBaseFileName/rn-no-ext/strip-exten",
+ gDirUtilp->getBaseFileName(rawFileNullExt, true),
+ "foo");
+
+ // .bAr
+ // interesting case - with no basename, this IS the basename, not the extension.
+
+ ensure_equals("getBaseFileName/e-ext/no-strip-exten",
+ gDirUtilp->getBaseFileName(rawExt, false),
+ ".bAr");
+
+ ensure_equals("getBaseFileName/e-ext/strip-exten",
+ gDirUtilp->getBaseFileName(rawExt, true),
+ ".bAr");
+
+ // .
+
+ ensure_equals("getBaseFileName/d/no-strip-exten",
+ gDirUtilp->getBaseFileName(rawDot, false),
+ ".");
+
+ ensure_equals("getBaseFileName/d/strip-exten",
+ gDirUtilp->getBaseFileName(rawDot, true),
+ ".");
+
+ // aa/bb/cc/dd/ee[.eXt]
+
+ ensure_equals("getBaseFileName/no-ext/no-strip-exten",
+ gDirUtilp->getBaseFileName(pathNoExt, false),
+ "ee");
+
+ ensure_equals("getBaseFileName/no-ext/strip-exten",
+ gDirUtilp->getBaseFileName(pathNoExt, true),
+ "ee");
+
+ ensure_equals("getBaseFileName/ext/no-strip-exten",
+ gDirUtilp->getBaseFileName(pathExt, false),
+ "ee.eXt");
+
+ ensure_equals("getBaseFileName/ext/strip-exten",
+ gDirUtilp->getBaseFileName(pathExt, true),
+ "ee");
+
+ // aa/bb/cc.dd/ee[.eXt]
+
+ ensure_equals("getBaseFileName/d-no-ext/no-strip-exten",
+ gDirUtilp->getBaseFileName(dottedPathNoExt, false),
+ "ee");
+
+ ensure_equals("getBaseFileName/d-no-ext/strip-exten",
+ gDirUtilp->getBaseFileName(dottedPathNoExt, true),
+ "ee");
+
+ ensure_equals("getBaseFileName/d-ext/no-strip-exten",
+ gDirUtilp->getBaseFileName(dottedPathExt, false),
+ "ee.eXt");
+
+ ensure_equals("getBaseFileName/d-ext/strip-exten",
+ gDirUtilp->getBaseFileName(dottedPathExt, true),
+ "ee");
+ }
+
+ template<> template<>
+ void LLDirTest_object_t::test<3>()
+ // getDirName
+ {
+ std::string delim = gDirUtilp->getDirDelimiter();
+ std::string rawFile = "foo";
+ std::string rawFileExt = "foo.bAr";
+ std::string pathNoExt = "aa" + delim + "bb" + delim + "cc" + delim + "dd" + delim + "ee";
+ std::string pathExt = pathNoExt + ".eXt";
+ std::string dottedPathNoExt = "aa" + delim + "bb" + delim + "cc.dd" + delim + "ee";
+ std::string dottedPathExt = dottedPathNoExt + ".eXt";
+
+ // foo[.bAr]
+
+ ensure_equals("getDirName/r-no-ext",
+ gDirUtilp->getDirName(rawFile),
+ "");
+
+ ensure_equals("getDirName/r-ext",
+ gDirUtilp->getDirName(rawFileExt),
+ "");
+
+ // aa/bb/cc/dd/ee[.eXt]
+
+ ensure_equals("getDirName/no-ext",
+ gDirUtilp->getDirName(pathNoExt),
+ "aa" + delim + "bb" + delim + "cc" + delim + "dd");
+
+ ensure_equals("getDirName/ext",
+ gDirUtilp->getDirName(pathExt),
+ "aa" + delim + "bb" + delim + "cc" + delim + "dd");
+
+ // aa/bb/cc.dd/ee[.eXt]
+
+ ensure_equals("getDirName/d-no-ext",
+ gDirUtilp->getDirName(dottedPathNoExt),
+ "aa" + delim + "bb" + delim + "cc.dd");
+
+ ensure_equals("getDirName/d-ext",
+ gDirUtilp->getDirName(dottedPathExt),
+ "aa" + delim + "bb" + delim + "cc.dd");
+ }
+
+ template<> template<>
+ void LLDirTest_object_t::test<4>()
+ // getExtension
+ {
+ std::string delim = gDirUtilp->getDirDelimiter();
+ std::string rawFile = "foo";
+ std::string rawFileExt = "foo.bAr";
+ std::string rawFileNullExt = "foo.";
+ std::string rawExt = ".bAr";
+ std::string rawDot = ".";
+ std::string pathNoExt = "aa" + delim + "bb" + delim + "cc" + delim + "dd" + delim + "ee";
+ std::string pathExt = pathNoExt + ".eXt";
+ std::string dottedPathNoExt = "aa" + delim + "bb" + delim + "cc.dd" + delim + "ee";
+ std::string dottedPathExt = dottedPathNoExt + ".eXt";
+
+ // foo[.bAr]
+
+ ensure_equals("getExtension/r-no-ext",
+ gDirUtilp->getExtension(rawFile),
+ "");
+
+ ensure_equals("getExtension/r-ext",
+ gDirUtilp->getExtension(rawFileExt),
+ "bar");
+
+ // foo.
+
+ ensure_equals("getExtension/rn-no-ext",
+ gDirUtilp->getExtension(rawFileNullExt),
+ "");
+
+ // .bAr
+ // interesting case - with no basename, this IS the basename, not the extension.
+
+ ensure_equals("getExtension/e-ext",
+ gDirUtilp->getExtension(rawExt),
+ "");
+
+ // .
+
+ ensure_equals("getExtension/d",
+ gDirUtilp->getExtension(rawDot),
+ "");
+
+ // aa/bb/cc/dd/ee[.eXt]
+
+ ensure_equals("getExtension/no-ext",
+ gDirUtilp->getExtension(pathNoExt),
+ "");
+
+ ensure_equals("getExtension/ext",
+ gDirUtilp->getExtension(pathExt),
+ "ext");
+
+ // aa/bb/cc.dd/ee[.eXt]
+
+ ensure_equals("getExtension/d-no-ext",
+ gDirUtilp->getExtension(dottedPathNoExt),
+ "");
+
+ ensure_equals("getExtension/d-ext",
+ gDirUtilp->getExtension(dottedPathExt),
+ "ext");
+ }
+}
+
diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt
index e1f7406287..7b1cab696f 100644
--- a/indra/llwindow/CMakeLists.txt
+++ b/indra/llwindow/CMakeLists.txt
@@ -19,7 +19,6 @@ include(LLRender)
include(LLVFS)
include(LLWindow)
include(LLXML)
-include(Mozlib)
include(UI)
include_directories(
@@ -35,13 +34,15 @@ include_directories(
set(llwindow_SOURCE_FILES
llkeyboard.cpp
llwindowheadless.cpp
+ llwindowcallbacks.cpp
)
-set(llwindows_HEADER_FILES
+set(llwindow_HEADER_FILES
CMakeLists.txt
llkeyboard.h
llwindowheadless.h
+ llwindowcallbacks.h
)
set(viewer_SOURCE_FILES
@@ -57,10 +58,12 @@ set(viewer_HEADER_FILES
# Libraries on which this library depends, needed for Linux builds
# Sort by high-level to low-level
-set(llwindow_LINK_LIBRARIES
- ${UI_LIBRARIES} # for GTK
- ${SDL_LIBRARY}
- )
+if (NOT LINUX OR VIEWER)
+ set(llwindow_LINK_LIBRARIES
+ ${UI_LIBRARIES} # for GTK
+ ${SDL_LIBRARY}
+ )
+endif (NOT LINUX OR VIEWER)
if (DARWIN)
list(APPEND llwindow_SOURCE_FILES
@@ -83,7 +86,7 @@ if (DARWIN)
)
endif (DARWIN)
-if (LINUX)
+if (LINUX AND VIEWER)
list(APPEND viewer_SOURCE_FILES
llkeyboardsdl.cpp
llwindowsdl.cpp
@@ -92,7 +95,7 @@ if (LINUX)
llkeyboardsdl.h
llwindowsdl.h
)
-endif (LINUX)
+endif (LINUX AND VIEWER)
if (WINDOWS)
list(APPEND llwindow_SOURCE_FILES
@@ -143,7 +146,7 @@ if (SERVER AND NOT WINDOWS AND NOT DARWIN)
${llwindow_SOURCE_FILES}
${server_SOURCE_FILES}
)
- # *TODO: This should probably have target_link_libraries
+ target_link_libraries (llwindowheadless ${llwindow_LINK_LIBRARIES})
endif (SERVER AND NOT WINDOWS AND NOT DARWIN)
if (llwindow_HEADER_FILES)
diff --git a/indra/llwindow/lldxhardware.cpp b/indra/llwindow/lldxhardware.cpp
index e0cb82d2be..d8058baf53 100644
--- a/indra/llwindow/lldxhardware.cpp
+++ b/indra/llwindow/lldxhardware.cpp
@@ -47,6 +47,7 @@
#include "llstring.h"
#include "llstl.h"
+#include "lltimer.h"
void (*gWriteDebug)(const char* msg) = NULL;
LLDXHardware gDXHardware;
diff --git a/indra/llwindow/llkeyboard.cpp b/indra/llwindow/llkeyboard.cpp
index 02b4ed17c2..16cbf815e0 100644
--- a/indra/llwindow/llkeyboard.cpp
+++ b/indra/llwindow/llkeyboard.cpp
@@ -34,8 +34,7 @@
#include "indra_constants.h"
#include "llkeyboard.h"
-#include "llwindow.h"
-
+#include "llwindowcallbacks.h"
//
// Globals
@@ -46,6 +45,8 @@ LLKeyboard *gKeyboard = NULL;
//static
std::map<KEY,std::string> LLKeyboard::sKeysToNames;
std::map<std::string,KEY> LLKeyboard::sNamesToKeys;
+LLKeyStringTranslatorFunc* LLKeyboard::mStringTranslator = NULL; // Used for l10n + PC/Mac/Linux accelerator labeling
+
//
// Class Implementation
@@ -346,6 +347,65 @@ std::string LLKeyboard::stringFromKey(KEY key)
}
+//static
+std::string LLKeyboard::stringFromAccelerator( MASK accel_mask, KEY key )
+{
+ std::string res;
+
+ // break early if this is a silly thing to do.
+ if( KEY_NONE == key )
+ {
+ return res;
+ }
+
+ LLKeyStringTranslatorFunc *trans = gKeyboard->mStringTranslator;
+
+ if( trans == NULL )
+ {
+ llerrs << "No mKeyStringTranslator" << llendl;
+ return res;
+ }
+
+ // Append any masks
+#ifdef LL_DARWIN
+ // Standard Mac names for modifier keys in menu equivalents
+ // We could use the symbol characters, but they only exist in certain fonts.
+ if( accel_mask & MASK_CONTROL )
+ {
+ if ( accel_mask & MASK_MAC_CONTROL )
+ {
+ res.append( trans("accel-mac-control") );
+ }
+ else
+ {
+ res.append( trans("accel-mac-command") ); // Symbol would be "\xE2\x8C\x98"
+ }
+ }
+ if( accel_mask & MASK_ALT )
+ res.append( trans("accel-mac-option") ); // Symbol would be "\xE2\x8C\xA5"
+ if( accel_mask & MASK_SHIFT )
+ res.append( trans("accel-mac-shift") ); // Symbol would be "\xE2\x8C\xA7"
+#else
+ if( accel_mask & MASK_CONTROL )
+ res.append( trans("accel-win-control") );
+ if( accel_mask & MASK_ALT )
+ res.append( trans("accel-win-alt") );
+ if( accel_mask & MASK_SHIFT )
+ res.append( trans("accel-win-shift") );
+#endif
+ std::string key_string = LLKeyboard::stringFromKey(key);
+ if ((accel_mask & MASK_NORMALKEYS) &&
+ (key_string[0] == '-' || key_string[0] == '=' || key_string[0] == '+'))
+ {
+ res.append( " " );
+ }
+
+ std::string keystr = stringFromKey( key );
+ res.append( keystr );
+
+ return res;
+}
+
//static
BOOL LLKeyboard::maskFromString(const std::string& str, MASK *mask)
@@ -396,3 +456,10 @@ BOOL LLKeyboard::maskFromString(const std::string& str, MASK *mask)
return FALSE;
}
}
+
+
+//static
+void LLKeyboard::setStringTranslatorFunc( LLKeyStringTranslatorFunc *trans_func )
+{
+ mStringTranslator = trans_func;
+}
diff --git a/indra/llwindow/llkeyboard.h b/indra/llwindow/llkeyboard.h
index 0261bcbeb3..d545034070 100644
--- a/indra/llwindow/llkeyboard.h
+++ b/indra/llwindow/llkeyboard.h
@@ -47,7 +47,8 @@ enum EKeystate
};
typedef void (*LLKeyFunc)(EKeystate keystate);
-
+typedef std::string (LLKeyStringTranslatorFunc)(const char *label);
+
enum EKeyboardInsertMode
{
LL_KIM_INSERT,
@@ -111,7 +112,7 @@ public:
static BOOL maskFromString(const std::string& str, MASK *mask); // False on failure
static BOOL keyFromString(const std::string& str, KEY *key); // False on failure
static std::string stringFromKey(KEY key);
-
+ static std::string stringFromAccelerator( MASK accel_mask, KEY key );
e_numpad_distinct getNumpadDistinct() { return mNumpadDistinct; }
void setNumpadDistinct(e_numpad_distinct val) { mNumpadDistinct = val; }
@@ -119,6 +120,8 @@ public:
F32 getKeyElapsedTime( KEY key ); // Returns time in seconds since key was pressed.
S32 getKeyElapsedFrameCount( KEY key ); // Returns time in frames since key was pressed.
+ static void setStringTranslatorFunc( LLKeyStringTranslatorFunc *trans_func );
+
protected:
void addKeyName(KEY key, const std::string& name);
@@ -136,6 +139,8 @@ protected:
KEY mCurTranslatedKey;
KEY mCurScanKey; // Used during the scanKeyboard()
+ static LLKeyStringTranslatorFunc* mStringTranslator; // Used for l10n + PC/Mac/Linux accelerator labeling
+
e_numpad_distinct mNumpadDistinct;
EKeyboardInsertMode mInsertMode;
diff --git a/indra/llwindow/llkeyboardmacosx.cpp b/indra/llwindow/llkeyboardmacosx.cpp
index ec82032161..f53773c393 100644
--- a/indra/llwindow/llkeyboardmacosx.cpp
+++ b/indra/llwindow/llkeyboardmacosx.cpp
@@ -34,7 +34,7 @@
#include "linden_common.h"
#include "llkeyboardmacosx.h"
-#include "llwindow.h"
+#include "llwindowcallbacks.h"
#include <Carbon/Carbon.h>
diff --git a/indra/llwindow/llkeyboardsdl.cpp b/indra/llwindow/llkeyboardsdl.cpp
index 8a6b6d6298..8a0b1de98c 100644
--- a/indra/llwindow/llkeyboardsdl.cpp
+++ b/indra/llwindow/llkeyboardsdl.cpp
@@ -34,7 +34,7 @@
#include "linden_common.h"
#include "llkeyboardsdl.h"
-#include "llwindow.h"
+#include "llwindowcallbacks.h"
#include "SDL/SDL.h"
LLKeyboardSDL::LLKeyboardSDL()
diff --git a/indra/llwindow/llkeyboardwin32.cpp b/indra/llwindow/llkeyboardwin32.cpp
index a06f19149c..ab5ecb4e63 100644
--- a/indra/llwindow/llkeyboardwin32.cpp
+++ b/indra/llwindow/llkeyboardwin32.cpp
@@ -34,14 +34,16 @@
#include "linden_common.h"
-#include "llkeyboardwin32.h"
-
-#include "llwindow.h"
-
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
+#include "llkeyboardwin32.h"
+
+#include "llwindowcallbacks.h"
+
+
+
LLKeyboardWin32::LLKeyboardWin32()
{
// Set up key mapping for windows - eventually can read this from a file?
@@ -63,7 +65,7 @@ LLKeyboardWin32::LLKeyboardWin32()
// numpad number keys
for (cur_char = 0x60; cur_char <= 0x69; cur_char++)
{
- mTranslateKeyMap[cur_char] = (KEY)('0' + (0x60 - cur_char));
+ mTranslateKeyMap[cur_char] = (KEY)('0' + (cur_char - 0x60));
}
@@ -78,7 +80,7 @@ LLKeyboardWin32::LLKeyboardWin32()
mTranslateKeyMap[VK_OEM_COMMA] = ',';
mTranslateKeyMap[VK_OEM_MINUS] = '-';
mTranslateKeyMap[VK_OEM_PERIOD] = '.';
- mTranslateKeyMap[VK_OEM_2] = KEY_PAD_DIVIDE;
+ mTranslateKeyMap[VK_OEM_2] = '/';//This used to be KEY_PAD_DIVIDE, but that breaks typing into text fields in media prims
mTranslateKeyMap[VK_OEM_3] = '`';
mTranslateKeyMap[VK_OEM_4] = '[';
mTranslateKeyMap[VK_OEM_5] = '\\';
diff --git a/indra/llwindow/llmousehandler.h b/indra/llwindow/llmousehandler.h
index 7bd0f2eebf..d758a1638a 100644
--- a/indra/llwindow/llmousehandler.h
+++ b/indra/llwindow/llmousehandler.h
@@ -45,17 +45,20 @@ class LLMouseHandler
public:
LLMouseHandler() {}
virtual ~LLMouseHandler() {}
+
typedef enum {
SHOW_NEVER,
SHOW_IF_NOT_BLOCKED,
SHOW_ALWAYS,
} EShowToolTip;
+
typedef enum {
CLICK_LEFT,
CLICK_MIDDLE,
CLICK_RIGHT,
CLICK_DOUBLELEFT
} EClickType;
+
virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) = 0;
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) = 0;
@@ -67,15 +70,11 @@ public:
virtual BOOL handleHover(S32 x, S32 y, MASK mask) = 0;
virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) = 0;
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) = 0;
- virtual EShowToolTip getShowToolTip() { return SHOW_IF_NOT_BLOCKED; };
- virtual const std::string& getName() const = 0;
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask) = 0;
+ virtual std::string getName() const = 0;
virtual void onMouseCaptureLost() = 0;
- // Hack to support LLFocusMgr
- virtual BOOL isView() const = 0;
-
virtual void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const = 0;
virtual void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const = 0;
diff --git a/indra/llwindow/llpreeditor.h b/indra/llwindow/llpreeditor.h
index 370f76cb85..fcb39515e7 100644
--- a/indra/llwindow/llpreeditor.h
+++ b/indra/llwindow/llpreeditor.h
@@ -94,7 +94,7 @@ public:
// Get the contents of this preeditor as a LLWString. If there is an active preedit,
// the returned LLWString contains it.
- virtual const LLWString & getWText() const = 0;
+ virtual LLWString getPreeditString() const = 0;
// Handle a UTF-32 char on this preeditor, i.e., add the character
// to the contents.
diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp
index 7e412a14de..1c6c9e6e9d 100644
--- a/indra/llwindow/llwindow.cpp
+++ b/indra/llwindow/llwindow.cpp
@@ -46,14 +46,12 @@
#include "llerror.h"
#include "llkeyboard.h"
#include "linked_lists.h"
+#include "llwindowcallbacks.h"
-//static instance for default callbacks
-LLWindowCallbacks LLWindow::sDefaultCallbacks;
//
-// LLWindowCallbacks
+// Globals
//
-
LLSplashScreen *gSplashScreenp = NULL;
BOOL gDebugClicks = FALSE;
BOOL gDebugWindowProc = FALSE;
@@ -67,158 +65,6 @@ const std::string gURLProtocolWhitelist[] = { "file:", "http:", "https:" };
// Important - these lists should match - protocol to handler
const std::string gURLProtocolWhitelistHandler[] = { "http", "http", "https" };
-BOOL LLWindowCallbacks::handleTranslatedKeyDown(const KEY key, const MASK mask, BOOL repeated)
-{
- return FALSE;
-}
-
-
-BOOL LLWindowCallbacks::handleTranslatedKeyUp(const KEY key, const MASK mask)
-{
- return FALSE;
-}
-
-void LLWindowCallbacks::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
-{
-}
-
-BOOL LLWindowCallbacks::handleUnicodeChar(llwchar uni_char, MASK mask)
-{
- return FALSE;
-}
-
-
-BOOL LLWindowCallbacks::handleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)
-{
- return FALSE;
-}
-
-BOOL LLWindowCallbacks::handleMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask)
-{
- return FALSE;
-}
-
-void LLWindowCallbacks::handleMouseLeave(LLWindow *window)
-{
- return;
-}
-
-BOOL LLWindowCallbacks::handleCloseRequest(LLWindow *window)
-{
- //allow the window to close
- return TRUE;
-}
-
-void LLWindowCallbacks::handleQuit(LLWindow *window)
-{
- if(LLWindowManager::destroyWindow(window) == FALSE)
- {
- llerrs << "LLWindowCallbacks::handleQuit() : Couldn't destroy window" << llendl;
- }
-}
-
-BOOL LLWindowCallbacks::handleRightMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)
-{
- return FALSE;
-}
-
-BOOL LLWindowCallbacks::handleRightMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask)
-{
- return FALSE;
-}
-
-BOOL LLWindowCallbacks::handleMiddleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)
-{
- return FALSE;
-}
-
-BOOL LLWindowCallbacks::handleMiddleMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask)
-{
- return FALSE;
-}
-
-BOOL LLWindowCallbacks::handleActivate(LLWindow *window, BOOL activated)
-{
- return FALSE;
-}
-
-BOOL LLWindowCallbacks::handleActivateApp(LLWindow *window, BOOL activating)
-{
- return FALSE;
-}
-
-void LLWindowCallbacks::handleMouseMove(LLWindow *window, const LLCoordGL pos, MASK mask)
-{
-}
-
-void LLWindowCallbacks::handleScrollWheel(LLWindow *window, S32 clicks)
-{
-}
-
-void LLWindowCallbacks::handleResize(LLWindow *window, const S32 width, const S32 height)
-{
-}
-
-void LLWindowCallbacks::handleFocus(LLWindow *window)
-{
-}
-
-void LLWindowCallbacks::handleFocusLost(LLWindow *window)
-{
-}
-
-void LLWindowCallbacks::handleMenuSelect(LLWindow *window, const S32 menu_item)
-{
-}
-
-BOOL LLWindowCallbacks::handlePaint(LLWindow *window, const S32 x, const S32 y,
- const S32 width, const S32 height)
-{
- return FALSE;
-}
-
-BOOL LLWindowCallbacks::handleDoubleClick(LLWindow *window, const LLCoordGL pos, MASK mask)
-{
- return FALSE;
-}
-
-void LLWindowCallbacks::handleWindowBlock(LLWindow *window)
-{
-}
-
-void LLWindowCallbacks::handleWindowUnblock(LLWindow *window)
-{
-}
-
-void LLWindowCallbacks::handleDataCopy(LLWindow *window, S32 data_type, void *data)
-{
-}
-
-BOOL LLWindowCallbacks::handleTimerEvent(LLWindow *window)
-{
- return FALSE;
-}
-
-BOOL LLWindowCallbacks::handleDeviceChange(LLWindow *window)
-{
- return FALSE;
-}
-
-void LLWindowCallbacks::handlePingWatchdog(LLWindow *window, const char * msg)
-{
-
-}
-
-void LLWindowCallbacks::handlePauseWatchdog(LLWindow *window)
-{
-
-}
-
-void LLWindowCallbacks::handleResumeWatchdog(LLWindow *window)
-{
-
-}
-
S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type)
{
@@ -257,8 +103,8 @@ S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type)
// LLWindow
//
-LLWindow::LLWindow(BOOL fullscreen, U32 flags)
- : mCallbacks(&sDefaultCallbacks),
+LLWindow::LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags)
+ : mCallbacks(callbacks),
mPostQuit(TRUE),
mFullscreen(fullscreen),
mFullscreenWidth(0),
@@ -275,9 +121,23 @@ LLWindow::LLWindow(BOOL fullscreen, U32 flags)
mHideCursorPermanent(FALSE),
mFlags(flags),
mHighSurrogate(0)
+{ }
+
+LLWindow::~LLWindow()
+{ }
+
+//virtual
+BOOL LLWindow::isValid()
{
+ return TRUE;
}
-
+
+//virtual
+BOOL LLWindow::canDelete()
+{
+ return TRUE;
+}
+
// virtual
void LLWindow::incBusyCount()
{
@@ -293,13 +153,28 @@ void LLWindow::decBusyCount()
}
}
-void LLWindow::setCallbacks(LLWindowCallbacks *callbacks)
+//virtual
+void LLWindow::resetBusyCount()
{
- mCallbacks = callbacks;
- if (gKeyboard)
- {
- gKeyboard->setCallbacks(callbacks);
- }
+ mBusyCount = 0;
+}
+
+//virtual
+S32 LLWindow::getBusyCount() const
+{
+ return mBusyCount;
+}
+
+//virtual
+ECursorType LLWindow::getCursor() const
+{
+ return mCurrentCursor;
+}
+
+//virtual
+BOOL LLWindow::dialogColorPicker(F32 *r, F32 *g, F32 *b)
+{
+ return FALSE;
}
void *LLWindow::getMediaWindow()
@@ -462,23 +337,7 @@ void LLSplashScreen::hide()
static std::set<LLWindow*> sWindowList;
LLWindow* LLWindowManager::createWindow(
- const std::string& title,
- const std::string& name,
- LLCoordScreen upper_left,
- LLCoordScreen size,
- U32 flags,
- BOOL fullscreen,
- BOOL clearBg,
- BOOL disable_vsync,
- BOOL use_gl,
- BOOL ignore_pixel_depth)
-{
- return createWindow(
- title, name, upper_left.mX, upper_left.mY, size.mX, size.mY, flags,
- fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
-}
-
-LLWindow* LLWindowManager::createWindow(
+ LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags,
BOOL fullscreen,
BOOL clearBg,
@@ -492,26 +351,26 @@ LLWindow* LLWindowManager::createWindow(
if (use_gl)
{
#if LL_MESA_HEADLESS
- new_window = new LLWindowMesaHeadless(
+ new_window = new LLWindowMesaHeadless(callbacks,
title, name, x, y, width, height, flags,
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
#elif LL_SDL
- new_window = new LLWindowSDL(
+ new_window = new LLWindowSDL(callbacks,
title, x, y, width, height, flags,
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
#elif LL_WINDOWS
- new_window = new LLWindowWin32(
+ new_window = new LLWindowWin32(callbacks,
title, name, x, y, width, height, flags,
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
#elif LL_DARWIN
- new_window = new LLWindowMacOSX(
+ new_window = new LLWindowMacOSX(callbacks,
title, name, x, y, width, height, flags,
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
#endif
}
else
{
- new_window = new LLWindowHeadless(
+ new_window = new LLWindowHeadless(callbacks,
title, name, x, y, width, height, flags,
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
}
diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h
index 8361771b66..127dbf45e0 100644
--- a/indra/llwindow/llwindow.h
+++ b/indra/llwindow/llwindow.h
@@ -39,52 +39,8 @@
#include "llcursortypes.h"
class LLSplashScreen;
-
-class LLWindow;
-
class LLPreeditor;
-
-class LLWindowCallbacks
-{
-public:
- virtual ~LLWindowCallbacks() {}
- virtual BOOL handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated);
- virtual BOOL handleTranslatedKeyUp(KEY key, MASK mask);
- virtual void handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level);
- virtual BOOL handleUnicodeChar(llwchar uni_char, MASK mask);
-
- virtual BOOL handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
- virtual BOOL handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
- virtual void handleMouseLeave(LLWindow *window);
- // return TRUE to allow window to close, which will then cause handleQuit to be called
- virtual BOOL handleCloseRequest(LLWindow *window);
- // window is about to be destroyed, clean up your business
- virtual void handleQuit(LLWindow *window);
- virtual BOOL handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
- virtual BOOL handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
- virtual BOOL handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
- virtual BOOL handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
- virtual BOOL handleActivate(LLWindow *window, BOOL activated);
- virtual BOOL handleActivateApp(LLWindow *window, BOOL activating);
- virtual void handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask);
- virtual void handleScrollWheel(LLWindow *window, S32 clicks);
- virtual void handleResize(LLWindow *window, S32 width, S32 height);
- virtual void handleFocus(LLWindow *window);
- virtual void handleFocusLost(LLWindow *window);
- virtual void handleMenuSelect(LLWindow *window, S32 menu_item);
- virtual BOOL handlePaint(LLWindow *window, S32 x, S32 y, S32 width, S32 height);
- virtual BOOL handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK mask); // double-click of left mouse button
- virtual void handleWindowBlock(LLWindow *window); // window is taking over CPU for a while
- virtual void handleWindowUnblock(LLWindow *window); // window coming back after taking over CPU for a while
- virtual void handleDataCopy(LLWindow *window, S32 data_type, void *data);
- virtual BOOL handleTimerEvent(LLWindow *window);
- virtual BOOL handleDeviceChange(LLWindow *window);
-
- virtual void handlePingWatchdog(LLWindow *window, const char * msg);
- virtual void handlePauseWatchdog(LLWindow *window);
- virtual void handleResumeWatchdog(LLWindow *window);
-
-};
+class LLWindowCallbacks;
// Refer to llwindow_test in test/common/llwindow for usage example
@@ -114,6 +70,8 @@ public:
virtual BOOL getMinimized() = 0;
virtual BOOL getMaximized() = 0;
virtual BOOL maximize() = 0;
+ virtual void minimize() = 0;
+ virtual void restore() = 0;
BOOL getFullscreen() { return mFullscreen; };
virtual BOOL getPosition(LLCoordScreen *position) = 0;
virtual BOOL getSize(LLCoordScreen *size) = 0;
@@ -134,12 +92,12 @@ public:
// arrow/hour if busycount > 0.
virtual void incBusyCount();
virtual void decBusyCount();
- virtual void resetBusyCount() { mBusyCount = 0; }
- virtual S32 getBusyCount() const { return mBusyCount; }
+ virtual void resetBusyCount();
+ virtual S32 getBusyCount() const;
// Sets cursor, may set to arrow+hourglass
virtual void setCursor(ECursorType cursor) = 0;
- virtual ECursorType getCursor() const { return mCurrentCursor; }
+ virtual ECursorType getCursor() const;
virtual void captureMouse() = 0;
virtual void releaseMouse() = 0;
@@ -183,13 +141,12 @@ public:
virtual F32 getPixelAspectRatio() = 0;
virtual void setNativeAspectRatio(F32 aspect) = 0;
- void setCallbacks(LLWindowCallbacks *callbacks);
-
virtual void beforeDialog() {}; // prepare to put up an OS dialog (if special measures are required, such as in fullscreen mode)
virtual void afterDialog() {}; // undo whatever was done in beforeDialog()
-// opens system default color picker
- virtual BOOL dialog_color_picker (F32 *r, F32 *g, F32 *b) { return FALSE; };
+ // opens system default color picker, modally
+ // Returns TRUE if valid color selected
+ virtual BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b);
// return a platform-specific window reference (HWND on Windows, WindowRef on the Mac, Gtk window on Linux)
virtual void *getPlatformWindow() = 0;
@@ -207,12 +164,12 @@ public:
static std::vector<std::string> getDynamicFallbackFontList();
protected:
- LLWindow(BOOL fullscreen, U32 flags);
- virtual ~LLWindow() {}
- virtual BOOL isValid() {return TRUE;}
- virtual BOOL canDelete() {return TRUE;}
-protected:
- static LLWindowCallbacks sDefaultCallbacks;
+ LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags);
+ virtual ~LLWindow();
+ // Defaults to true
+ virtual BOOL isValid();
+ // Defaults to true
+ virtual BOOL canDelete();
protected:
LLWindowCallbacks* mCallbacks;
@@ -294,18 +251,8 @@ const S32 OSBTN_CANCEL = 3;
class LLWindowManager
{
public:
- static LLWindow* createWindow(
- const std::string& title,
- const std::string& name,
- LLCoordScreen upper_left = LLCoordScreen(10, 10),
- LLCoordScreen size = LLCoordScreen(320, 240),
- U32 flags = 0,
- BOOL fullscreen = FALSE,
- BOOL clearBg = FALSE,
- BOOL disable_vsync = TRUE,
- BOOL use_gl = TRUE,
- BOOL ignore_pixel_depth = FALSE);
static LLWindow *createWindow(
+ LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
U32 flags = 0,
BOOL fullscreen = FALSE,
diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp
new file mode 100644
index 0000000000..72f9997149
--- /dev/null
+++ b/indra/llwindow/llwindowcallbacks.cpp
@@ -0,0 +1,201 @@
+/**
+ * @file llwindowcallbacks.cpp
+ * @brief OS event callback class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llwindowcallbacks.h"
+
+#include "llcoord.h"
+
+//
+// LLWindowCallbacks
+//
+
+BOOL LLWindowCallbacks::handleTranslatedKeyDown(const KEY key, const MASK mask, BOOL repeated)
+{
+ return FALSE;
+}
+
+
+BOOL LLWindowCallbacks::handleTranslatedKeyUp(const KEY key, const MASK mask)
+{
+ return FALSE;
+}
+
+void LLWindowCallbacks::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
+{
+}
+
+BOOL LLWindowCallbacks::handleUnicodeChar(llwchar uni_char, MASK mask)
+{
+ return FALSE;
+}
+
+
+BOOL LLWindowCallbacks::handleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)
+{
+ return FALSE;
+}
+
+BOOL LLWindowCallbacks::handleMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask)
+{
+ return FALSE;
+}
+
+void LLWindowCallbacks::handleMouseLeave(LLWindow *window)
+{
+ return;
+}
+
+BOOL LLWindowCallbacks::handleCloseRequest(LLWindow *window)
+{
+ //allow the window to close
+ return TRUE;
+}
+
+void LLWindowCallbacks::handleQuit(LLWindow *window)
+{
+}
+
+BOOL LLWindowCallbacks::handleRightMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)
+{
+ return FALSE;
+}
+
+BOOL LLWindowCallbacks::handleRightMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask)
+{
+ return FALSE;
+}
+
+BOOL LLWindowCallbacks::handleMiddleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask)
+{
+ return FALSE;
+}
+
+BOOL LLWindowCallbacks::handleMiddleMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask)
+{
+ return FALSE;
+}
+
+BOOL LLWindowCallbacks::handleActivate(LLWindow *window, BOOL activated)
+{
+ return FALSE;
+}
+
+BOOL LLWindowCallbacks::handleActivateApp(LLWindow *window, BOOL activating)
+{
+ return FALSE;
+}
+
+void LLWindowCallbacks::handleMouseMove(LLWindow *window, const LLCoordGL pos, MASK mask)
+{
+}
+
+void LLWindowCallbacks::handleScrollWheel(LLWindow *window, S32 clicks)
+{
+}
+
+void LLWindowCallbacks::handleResize(LLWindow *window, const S32 width, const S32 height)
+{
+}
+
+void LLWindowCallbacks::handleFocus(LLWindow *window)
+{
+}
+
+void LLWindowCallbacks::handleFocusLost(LLWindow *window)
+{
+}
+
+void LLWindowCallbacks::handleMenuSelect(LLWindow *window, const S32 menu_item)
+{
+}
+
+BOOL LLWindowCallbacks::handlePaint(LLWindow *window, const S32 x, const S32 y,
+ const S32 width, const S32 height)
+{
+ return FALSE;
+}
+
+BOOL LLWindowCallbacks::handleDoubleClick(LLWindow *window, const LLCoordGL pos, MASK mask)
+{
+ return FALSE;
+}
+
+void LLWindowCallbacks::handleWindowBlock(LLWindow *window)
+{
+}
+
+void LLWindowCallbacks::handleWindowUnblock(LLWindow *window)
+{
+}
+
+void LLWindowCallbacks::handleDataCopy(LLWindow *window, S32 data_type, void *data)
+{
+}
+
+BOOL LLWindowCallbacks::handleTimerEvent(LLWindow *window)
+{
+ return FALSE;
+}
+
+BOOL LLWindowCallbacks::handleDeviceChange(LLWindow *window)
+{
+ return FALSE;
+}
+
+void LLWindowCallbacks::handlePingWatchdog(LLWindow *window, const char * msg)
+{
+
+}
+
+void LLWindowCallbacks::handlePauseWatchdog(LLWindow *window)
+{
+
+}
+
+void LLWindowCallbacks::handleResumeWatchdog(LLWindow *window)
+{
+
+}
+
+std::string LLWindowCallbacks::translateString(const char* tag)
+{
+ return std::string();
+}
+
+//virtual
+std::string LLWindowCallbacks::translateString(const char* tag,
+ const std::map<std::string, std::string>& args)
+{
+ return std::string();
+}
diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h
new file mode 100644
index 0000000000..abc66c42a2
--- /dev/null
+++ b/indra/llwindow/llwindowcallbacks.h
@@ -0,0 +1,85 @@
+/**
+ * @file llwindowcallbacks.h
+ * @brief OS event callback class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef LLWINDOWCALLBACKS_H
+#define LLWINDOWCALLBACKS_H
+
+class LLCoordGL;
+class LLWindow;
+
+class LLWindowCallbacks
+{
+public:
+ virtual ~LLWindowCallbacks() {}
+ virtual BOOL handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated);
+ virtual BOOL handleTranslatedKeyUp(KEY key, MASK mask);
+ virtual void handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level);
+ virtual BOOL handleUnicodeChar(llwchar uni_char, MASK mask);
+
+ virtual BOOL handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
+ virtual BOOL handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
+ virtual void handleMouseLeave(LLWindow *window);
+ // return TRUE to allow window to close, which will then cause handleQuit to be called
+ virtual BOOL handleCloseRequest(LLWindow *window);
+ // window is about to be destroyed, clean up your business
+ virtual void handleQuit(LLWindow *window);
+ virtual BOOL handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
+ virtual BOOL handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
+ virtual BOOL handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
+ virtual BOOL handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
+ virtual BOOL handleActivate(LLWindow *window, BOOL activated);
+ virtual BOOL handleActivateApp(LLWindow *window, BOOL activating);
+ virtual void handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask);
+ virtual void handleScrollWheel(LLWindow *window, S32 clicks);
+ virtual void handleResize(LLWindow *window, S32 width, S32 height);
+ virtual void handleFocus(LLWindow *window);
+ virtual void handleFocusLost(LLWindow *window);
+ virtual void handleMenuSelect(LLWindow *window, S32 menu_item);
+ virtual BOOL handlePaint(LLWindow *window, S32 x, S32 y, S32 width, S32 height);
+ virtual BOOL handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK mask); // double-click of left mouse button
+ virtual void handleWindowBlock(LLWindow *window); // window is taking over CPU for a while
+ virtual void handleWindowUnblock(LLWindow *window); // window coming back after taking over CPU for a while
+ virtual void handleDataCopy(LLWindow *window, S32 data_type, void *data);
+ virtual BOOL handleTimerEvent(LLWindow *window);
+ virtual BOOL handleDeviceChange(LLWindow *window);
+
+ virtual void handlePingWatchdog(LLWindow *window, const char * msg);
+ virtual void handlePauseWatchdog(LLWindow *window);
+ virtual void handleResumeWatchdog(LLWindow *window);
+
+ // Look up a localized string, usually for an error message
+ virtual std::string translateString(const char* tag);
+ virtual std::string translateString(const char* tag,
+ const std::map<std::string, std::string>& args);
+};
+
+
+#endif
diff --git a/indra/llwindow/llwindowheadless.cpp b/indra/llwindow/llwindowheadless.cpp
index 3742846440..b4e9009321 100644
--- a/indra/llwindow/llwindowheadless.cpp
+++ b/indra/llwindow/llwindowheadless.cpp
@@ -38,10 +38,10 @@
//
// LLWindowHeadless
//
-LLWindowHeadless::LLWindowHeadless(const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
- U32 flags, BOOL fullscreen, BOOL clearBg,
+LLWindowHeadless::LLWindowHeadless(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
+ U32 flags, BOOL fullscreen, BOOL clear_background,
BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth)
- : LLWindow(fullscreen, flags)
+ : LLWindow(callbacks, fullscreen, flags)
{
}
diff --git a/indra/llwindow/llwindowheadless.h b/indra/llwindow/llwindowheadless.h
index 4353d157b5..59fc2ec657 100644
--- a/indra/llwindow/llwindowheadless.h
+++ b/indra/llwindow/llwindowheadless.h
@@ -45,6 +45,8 @@ public:
/*virtual*/ BOOL getMinimized() {return FALSE;};
/*virtual*/ BOOL getMaximized() {return FALSE;};
/*virtual*/ BOOL maximize() {return FALSE;};
+ /*virtual*/ void minimize() {};
+ /*virtual*/ void restore() {};
/*virtual*/ BOOL getFullscreen() {return FALSE;};
/*virtual*/ BOOL getPosition(LLCoordScreen *position) {return FALSE;};
/*virtual*/ BOOL getSize(LLCoordScreen *size) {return FALSE;};
@@ -94,9 +96,12 @@ public:
/*virtual*/ void *getPlatformWindow() { return 0; };
/*virtual*/ void bringToFront() {};
- LLWindowHeadless(const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
- U32 flags, BOOL fullscreen, BOOL clearBg,
- BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth);
+ LLWindowHeadless(LLWindowCallbacks* callbacks,
+ const std::string& title, const std::string& name,
+ S32 x, S32 y,
+ S32 width, S32 height,
+ U32 flags, BOOL fullscreen, BOOL clear_background,
+ BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth);
virtual ~LLWindowHeadless();
private:
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index 65a40dcef4..ed62faece6 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -32,19 +32,21 @@
#include "linden_common.h"
-#include <Carbon/Carbon.h>
-#include <OpenGL/OpenGL.h>
-
#include "llwindowmacosx.h"
+
#include "llkeyboardmacosx.h"
+#include "llwindowcallbacks.h"
+#include "llwindowmacosx-objc.h"
+#include "llpreeditor.h"
+
#include "llerror.h"
#include "llgl.h"
#include "llstring.h"
#include "lldir.h"
#include "indra_constants.h"
-#include "llwindowmacosx-objc.h"
-#include "llpreeditor.h"
+#include <Carbon/Carbon.h>
+#include <OpenGL/OpenGL.h>
extern BOOL gDebugWindowProc;
@@ -214,19 +216,27 @@ static LLWindowMacOSX *gWindowImplementation = NULL;
-LLWindowMacOSX::LLWindowMacOSX(const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
+LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
+ const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
S32 height, U32 flags,
BOOL fullscreen, BOOL clearBg,
BOOL disable_vsync, BOOL use_gl,
BOOL ignore_pixel_depth,
U32 fsaa_samples)
- : LLWindow(fullscreen, flags)
+ : LLWindow(NULL, fullscreen, flags)
{
+ // *HACK: During window construction we get lots of OS events for window
+ // reshape, activate, etc. that the viewer isn't ready to handle.
+ // Route them to a dummy callback structure until the end of constructor.
+ LLWindowCallbacks null_callbacks;
+ mCallbacks = &null_callbacks;
+
// Voodoo for calling cocoa from carbon (see llwindowmacosx-objc.mm).
setupCocoa();
// Initialize the keyboard
gKeyboard = new LLKeyboardMacOSX();
+ gKeyboard->setCallbacks(callbacks);
// Ignore use_gl for now, only used for drones on PC
mWindow = NULL;
@@ -315,6 +325,7 @@ LLWindowMacOSX::LLWindowMacOSX(const std::string& title, const std::string& name
setCursor( UI_CURSOR_ARROW );
}
+ mCallbacks = callbacks;
stop_glerror();
}
@@ -511,7 +522,6 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
if (mTSMDocument)
{
ActivateTSMDocument(mTSMDocument);
- UseInputWindow(mTSMDocument, FALSE);
allowLanguageTextInput(NULL, FALSE);
}
}
@@ -1023,6 +1033,7 @@ void LLWindowMacOSX::hide()
HideWindow(mWindow);
}
+//virtual
void LLWindowMacOSX::minimize()
{
setMouseClipping(FALSE);
@@ -1030,6 +1041,7 @@ void LLWindowMacOSX::minimize()
CollapseWindow(mWindow, true);
}
+//virtual
void LLWindowMacOSX::restore()
{
show();
@@ -1378,11 +1390,11 @@ void LLWindowMacOSX::setMouseClipping( BOOL b )
if(b)
{
- // llinfos << "setMouseClipping(TRUE)" << llendl
+ // llinfos << "setMouseClipping(TRUE)" << llendl;
}
else
{
- // llinfos << "setMouseClipping(FALSE)" << llendl
+ // llinfos << "setMouseClipping(FALSE)" << llendl;
}
adjustCursorDecouple();
@@ -1400,7 +1412,7 @@ BOOL LLWindowMacOSX::setCursorPosition(const LLCoordWindow position)
CGPoint newPosition;
- // llinfos << "setCursorPosition(" << screen_pos.mX << ", " << screen_pos.mY << ")" << llendl
+ // llinfos << "setCursorPosition(" << screen_pos.mX << ", " << screen_pos.mY << ")" << llendl;
newPosition.x = screen_pos.mX;
newPosition.y = screen_pos.mY;
@@ -1431,7 +1443,7 @@ static void fixOrigin(void)
::GetPortBounds(port, &portrect);
if((portrect.left != 0) || (portrect.top != 0))
{
- // Mozilla sometimes changes our port origin. Fuckers.
+ // Mozilla sometimes changes our port origin.
::SetOrigin(0,0);
}
}
@@ -2005,7 +2017,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
// Although the spec. is unclear, replace range should
// not present when there is an active preedit. We just
// ignore the case. markAsPreedit will detect the case and warn it.
- const LLWString & text = mPreeditor->getWText();
+ const LLWString & text = mPreeditor->getPreeditString();
const S32 location = wstring_wstring_length_from_utf16_length(text, 0, range.location);
const S32 length = wstring_wstring_length_from_utf16_length(text, location, range.length);
mPreeditor->markAsPreedit(location, length);
@@ -2203,7 +2215,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
{
S32 preedit, preedit_length;
mPreeditor->getPreeditRange(&preedit, &preedit_length);
- const LLWString & text = mPreeditor->getWText();
+ const LLWString & text = mPreeditor->getPreeditString();
LLCoordGL caret_coord;
LLRect preedit_bounds;
@@ -2240,7 +2252,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
mPreeditor->getSelectionRange(&selection, &selection_length);
if (selection_length)
{
- const LLWString text = mPreeditor->getWText().substr(selection, selection_length);
+ const LLWString text = mPreeditor->getPreeditString().substr(selection, selection_length);
const llutf16string text_utf16 = wstring_to_utf16str(text);
result = SetEventParameter(event, kEventParamTextInputReplyText, typeUnicodeText,
text_utf16.length() * sizeof(U16), text_utf16.c_str());
@@ -2626,7 +2638,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
S32 preedit, preedit_length;
mPreeditor->getPreeditRange(&preedit, &preedit_length);
- const LLWString & text = mPreeditor->getWText();
+ const LLWString & text = mPreeditor->getPreeditString();
const CFIndex length = wstring_utf16_length(text, 0, preedit)
+ wstring_utf16_length(text, preedit + preedit_length, text.length());
result = SetEventParameter(event, kEventParamTSMDocAccessCharacterCount, typeCFIndex, sizeof(length), &length);
@@ -2643,7 +2655,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
S32 preedit, preedit_length;
mPreeditor->getPreeditRange(&preedit, &preedit_length);
- const LLWString & text = mPreeditor->getWText();
+ const LLWString & text = mPreeditor->getPreeditString();
CFRange range;
if (preedit_length)
@@ -2677,7 +2689,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
{
S32 preedit, preedit_length;
mPreeditor->getPreeditRange(&preedit, &preedit_length);
- const LLWString & text = mPreeditor->getWText();
+ const LLWString & text = mPreeditor->getPreeditString();
// The GetCharacters event of TSMDA has a fundamental flaw;
// An input method need to decide the starting offset and length
@@ -2752,10 +2764,6 @@ const char* cursorIDToName(int id)
case UI_CURSOR_TOOLPAN: return "UI_CURSOR_TOOLPAN";
case UI_CURSOR_TOOLZOOMIN: return "UI_CURSOR_TOOLZOOMIN";
case UI_CURSOR_TOOLPICKOBJECT3: return "UI_CURSOR_TOOLPICKOBJECT3";
- case UI_CURSOR_TOOLSIT: return "UI_CURSOR_TOOLSIT";
- case UI_CURSOR_TOOLBUY: return "UI_CURSOR_TOOLBUY";
- case UI_CURSOR_TOOLPAY: return "UI_CURSOR_TOOLPAY";
- case UI_CURSOR_TOOLOPEN: return "UI_CURSOR_TOOLOPEN";
case UI_CURSOR_TOOLPLAY: return "UI_CURSOR_TOOLPLAY";
case UI_CURSOR_TOOLPAUSE: return "UI_CURSOR_TOOLPAUSE";
case UI_CURSOR_TOOLMEDIAOPEN: return "UI_CURSOR_TOOLMEDIAOPEN";
@@ -2851,10 +2859,6 @@ void LLWindowMacOSX::setCursor(ECursorType cursor)
case UI_CURSOR_TOOLPAN:
case UI_CURSOR_TOOLZOOMIN:
case UI_CURSOR_TOOLPICKOBJECT3:
- case UI_CURSOR_TOOLSIT:
- case UI_CURSOR_TOOLBUY:
- case UI_CURSOR_TOOLPAY:
- case UI_CURSOR_TOOLOPEN:
case UI_CURSOR_TOOLPLAY:
case UI_CURSOR_TOOLPAUSE:
case UI_CURSOR_TOOLMEDIAOPEN:
@@ -2896,10 +2900,6 @@ void LLWindowMacOSX::initCursors()
initPixmapCursor(UI_CURSOR_TOOLPAN, 7, 6);
initPixmapCursor(UI_CURSOR_TOOLZOOMIN, 7, 6);
initPixmapCursor(UI_CURSOR_TOOLPICKOBJECT3, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLSIT, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLBUY, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLPAY, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLOPEN, 1, 1);
initPixmapCursor(UI_CURSOR_TOOLPLAY, 1, 1);
initPixmapCursor(UI_CURSOR_TOOLPAUSE, 1, 1);
initPixmapCursor(UI_CURSOR_TOOLMEDIAOPEN, 1, 1);
@@ -3202,7 +3202,7 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url)
}
-BOOL LLWindowMacOSX::dialog_color_picker ( F32 *r, F32 *g, F32 *b)
+BOOL LLWindowMacOSX::dialogColorPicker( F32 *r, F32 *g, F32 *b)
{
BOOL retval = FALSE;
OSErr error = noErr;
@@ -3318,6 +3318,8 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
return;
}
+ UseInputWindow(mTSMDocument, !b);
+
// Take care of old and new preeditors.
if (preeditor != mPreeditor || !b)
{
diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h
index 3886782732..fbfa07fab4 100644
--- a/indra/llwindow/llwindowmacosx.h
+++ b/indra/llwindow/llwindowmacosx.h
@@ -35,6 +35,8 @@
#include "llwindow.h"
+#include "lltimer.h"
+
#include <Carbon/Carbon.h>
#include <AGL/agl.h>
@@ -54,6 +56,8 @@ public:
/*virtual*/ BOOL getMinimized();
/*virtual*/ BOOL getMaximized();
/*virtual*/ BOOL maximize();
+ /*virtual*/ void minimize();
+ /*virtual*/ void restore();
/*virtual*/ BOOL getFullscreen();
/*virtual*/ BOOL getPosition(LLCoordScreen *position);
/*virtual*/ BOOL getSize(LLCoordScreen *size);
@@ -103,7 +107,7 @@ public:
/*virtual*/ void beforeDialog();
/*virtual*/ void afterDialog();
- /*virtual*/ BOOL dialog_color_picker(F32 *r, F32 *g, F32 *b);
+ /*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b);
/*virtual*/ void *getPlatformWindow();
/*virtual*/ void *getMediaWindow();
@@ -116,7 +120,7 @@ public:
static std::vector<std::string> getDynamicFallbackFontList();
protected:
- LLWindowMacOSX(
+ LLWindowMacOSX(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl,
BOOL ignore_pixel_depth,
@@ -137,9 +141,6 @@ protected:
// Restore the display resolution to its value before we ran the app.
BOOL resetDisplayResolution();
- void minimize();
- void restore();
-
BOOL shouldPostQuit() { return mPostQuit; }
diff --git a/indra/llwindow/llwindowmesaheadless.cpp b/indra/llwindow/llwindowmesaheadless.cpp
index c1f9d2095e..48736d9207 100644
--- a/indra/llwindow/llwindowmesaheadless.cpp
+++ b/indra/llwindow/llwindowmesaheadless.cpp
@@ -44,10 +44,11 @@ U16 *gMesaBuffer = NULL;
//
// LLWindowMesaHeadless
//
-LLWindowMesaHeadless::LLWindowMesaHeadless(const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
+LLWindowMesaHeadless::LLWindowMesaHeadless(LLWindowCallbacks* callbacks,
+ const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
U32 flags, BOOL fullscreen, BOOL clearBg,
BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth)
- : LLWindow(fullscreen, flags)
+ : LLWindow(callbacks, fullscreen, flags)
{
if (use_gl)
{
diff --git a/indra/llwindow/llwindowmesaheadless.h b/indra/llwindow/llwindowmesaheadless.h
index ab562d9ffe..06146afde7 100644
--- a/indra/llwindow/llwindowmesaheadless.h
+++ b/indra/llwindow/llwindowmesaheadless.h
@@ -49,6 +49,8 @@ public:
/*virtual*/ BOOL getMinimized() {return FALSE;};
/*virtual*/ BOOL getMaximized() {return FALSE;};
/*virtual*/ BOOL maximize() {return FALSE;};
+ /*virtual*/ void minimize() {};
+ /*virtual*/ void restore() {};
/*virtual*/ BOOL getFullscreen() {return FALSE;};
/*virtual*/ BOOL getPosition(LLCoordScreen *position) {return FALSE;};
/*virtual*/ BOOL getSize(LLCoordScreen *size) {return FALSE;};
@@ -98,7 +100,8 @@ public:
/*virtual*/ void *getPlatformWindow() { return 0; };
/*virtual*/ void bringToFront() {};
- LLWindowMesaHeadless(const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
+ LLWindowMesaHeadless(LLWindowCallbacks* callbacks,
+ const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
U32 flags, BOOL fullscreen, BOOL clearBg,
BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth);
~LLWindowMesaHeadless();
diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp
index 24bd70d57f..bfdf1147a1 100644
--- a/indra/llwindow/llwindowsdl.cpp
+++ b/indra/llwindow/llwindowsdl.cpp
@@ -36,15 +36,16 @@
#include "linden_common.h"
#include "llwindowsdl.h"
+
+#include "llwindowcallbacks.h"
#include "llkeyboardsdl.h"
+
#include "llerror.h"
#include "llgl.h"
#include "llstring.h"
#include "lldir.h"
#include "llfindlocale.h"
-#include "indra_constants.h"
-
#if LL_GTK
extern "C" {
# include "gtk/gtk.h"
@@ -69,7 +70,7 @@ extern BOOL gDebugWindowProc;
const S32 MAX_NUM_RESOLUTIONS = 200;
// static variable for ATI mouse cursor crash work-around:
-static bool ATIbug = false;
+static bool ATIbug = false;
//
// LLWindowSDL
@@ -187,16 +188,19 @@ Display* LLWindowSDL::get_SDL_Display(void)
#endif // LL_X11
-LLWindowSDL::LLWindowSDL(const std::string& title, S32 x, S32 y, S32 width,
+LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
+ const std::string& title, S32 x, S32 y, S32 width,
S32 height, U32 flags,
BOOL fullscreen, BOOL clearBg,
BOOL disable_vsync, BOOL use_gl,
BOOL ignore_pixel_depth, U32 fsaa_samples)
- : LLWindow(fullscreen, flags), Lock_Display(NULL),
+ : LLWindow(callbacks, fullscreen, flags),
+ Lock_Display(NULL),
Unlock_Display(NULL), mGamma(1.0f)
{
// Initialize the keyboard
gKeyboard = new LLKeyboardSDL();
+ gKeyboard->setCallbacks(callbacks);
// Note that we can't set up key-repeat until after SDL has init'd video
// Ignore use_gl for now, only used for drones on PC
@@ -215,8 +219,7 @@ LLWindowSDL::LLWindowSDL(const std::string& title, S32 x, S32 y, S32 width,
#endif // LL_X11
#if LL_GTK
- // We MUST be the first to initialize GTK, i.e. we have to beat
- // our embedded Mozilla to the punch so that GTK doesn't get badly
+ // We MUST be the first to initialize GTK so that GTK doesn't get badly
// initialized with a non-C locale and cause lots of serious random
// weirdness.
ll_try_gtk_init();
@@ -415,7 +418,6 @@ static int x11_detect_VRAM_kb()
BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync)
{
//bool glneedsinit = false;
-// const char *gllibname = null;
llinfos << "createContext, fullscreen=" << fullscreen <<
" size=" << width << "x" << height << llendl;
@@ -670,12 +672,12 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
glGetIntegerv(GL_DEPTH_BITS, &depthBits);
glGetIntegerv(GL_STENCIL_BITS, &stencilBits);
- llinfos << "GL buffer:" << llendl
- llinfos << " Red Bits " << S32(redBits) << llendl
- llinfos << " Green Bits " << S32(greenBits) << llendl
- llinfos << " Blue Bits " << S32(blueBits) << llendl
- llinfos << " Alpha Bits " << S32(alphaBits) << llendl
- llinfos << " Depth Bits " << S32(depthBits) << llendl
+ llinfos << "GL buffer:" << llendl;
+ llinfos << " Red Bits " << S32(redBits) << llendl;
+ llinfos << " Green Bits " << S32(greenBits) << llendl;
+ llinfos << " Blue Bits " << S32(blueBits) << llendl;
+ llinfos << " Alpha Bits " << S32(alphaBits) << llendl;
+ llinfos << " Depth Bits " << S32(depthBits) << llendl;
llinfos << " Stencil Bits " << S32(stencilBits) << llendl;
GLint colorBits = redBits + greenBits + blueBits + alphaBits;
@@ -837,11 +839,13 @@ void LLWindowSDL::hide()
// *FIX: What to do with SDL?
}
+//virtual
void LLWindowSDL::minimize()
{
// *FIX: What to do with SDL?
}
+//virtual
void LLWindowSDL::restore()
{
// *FIX: What to do with SDL?
@@ -1936,11 +1940,6 @@ void LLWindowSDL::setCursor(ECursorType cursor)
}
}
-ECursorType LLWindowSDL::getCursor()
-{
- return mCurrentCursor;
-}
-
void LLWindowSDL::initCursors()
{
int i;
@@ -1982,10 +1981,6 @@ void LLWindowSDL::initCursors()
mSDLCursors[UI_CURSOR_TOOLPAN] = makeSDLCursorFromBMP("lltoolpan.BMP",7,5);
mSDLCursors[UI_CURSOR_TOOLZOOMIN] = makeSDLCursorFromBMP("lltoolzoomin.BMP",7,5);
mSDLCursors[UI_CURSOR_TOOLPICKOBJECT3] = makeSDLCursorFromBMP("toolpickobject3.BMP",0,0);
- mSDLCursors[UI_CURSOR_TOOLSIT] = makeSDLCursorFromBMP("toolsit.BMP",0,0);
- mSDLCursors[UI_CURSOR_TOOLBUY] = makeSDLCursorFromBMP("toolbuy.BMP",0,0);
- mSDLCursors[UI_CURSOR_TOOLPAY] = makeSDLCursorFromBMP("toolpay.BMP",0,0);
- mSDLCursors[UI_CURSOR_TOOLOPEN] = makeSDLCursorFromBMP("toolopen.BMP",0,0);
mSDLCursors[UI_CURSOR_TOOLPLAY] = makeSDLCursorFromBMP("toolplay.BMP",0,0);
mSDLCursors[UI_CURSOR_TOOLPAUSE] = makeSDLCursorFromBMP("toolpause.BMP",0,0);
mSDLCursors[UI_CURSOR_TOOLMEDIAOPEN] = makeSDLCursorFromBMP("toolmediaopen.BMP",0,0);
@@ -2229,7 +2224,7 @@ static void color_changed_callback(GtkWidget *widget,
gtk_color_selection_get_current_color(colorsel, colorp);
}
-BOOL LLWindowSDL::dialog_color_picker ( F32 *r, F32 *g, F32 *b)
+BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b)
{
BOOL rtn = FALSE;
@@ -2257,6 +2252,7 @@ BOOL LLWindowSDL::dialog_color_picker ( F32 *r, F32 *g, F32 *b)
GtkColorSelection *colorsel = GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG(win)->colorsel);
GdkColor color, orig_color;
+ orig_color.pixel = 0;
orig_color.red = guint16(65535 * *r);
orig_color.green= guint16(65535 * *g);
orig_color.blue = guint16(65535 * *b);
@@ -2306,7 +2302,7 @@ S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 typ
return 0;
}
-BOOL LLWindowSDL::dialog_color_picker ( F32 *r, F32 *g, F32 *b)
+BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b)
{
return (FALSE);
}
@@ -2363,8 +2359,10 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url)
# endif // LL_X11
std::string cmd, arg;
- cmd = gDirUtilp->getAppRODataDir().c_str();
- cmd += gDirUtilp->getDirDelimiter().c_str();
+ cmd = gDirUtilp->getAppRODataDir();
+ cmd += gDirUtilp->getDirDelimiter();
+ cmd += "etc";
+ cmd += gDirUtilp->getDirDelimiter();
cmd += "launch_url.sh";
arg = escaped_url;
exec_cmd(cmd, arg);
diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h
index 632d8fc1fa..0ba1c861da 100644
--- a/indra/llwindow/llwindowsdl.h
+++ b/indra/llwindow/llwindowsdl.h
@@ -36,6 +36,7 @@
// Simple Directmedia Layer (http://libsdl.org/) implementation of LLWindow class
#include "llwindow.h"
+#include "lltimer.h"
#include "SDL/SDL.h"
#include "SDL/SDL_endian.h"
@@ -61,6 +62,8 @@ public:
/*virtual*/ BOOL getMinimized();
/*virtual*/ BOOL getMaximized();
/*virtual*/ BOOL maximize();
+ /*virtual*/ void minimize();
+ /*virtual*/ void restore();
/*virtual*/ BOOL getFullscreen();
/*virtual*/ BOOL getPosition(LLCoordScreen *position);
/*virtual*/ BOOL getSize(LLCoordScreen *size);
@@ -76,7 +79,6 @@ public:
/*virtual*/ void hideCursorUntilMouseMove();
/*virtual*/ BOOL isCursorHidden();
/*virtual*/ void setCursor(ECursorType cursor);
- /*virtual*/ ECursorType getCursor();
/*virtual*/ void captureMouse();
/*virtual*/ void releaseMouse();
/*virtual*/ void setMouseClipping( BOOL b );
@@ -118,7 +120,7 @@ public:
/*virtual*/ void beforeDialog();
/*virtual*/ void afterDialog();
- /*virtual*/ BOOL dialog_color_picker(F32 *r, F32 *g, F32 *b);
+ /*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b);
/*virtual*/ void *getPlatformWindow();
/*virtual*/ void bringToFront();
@@ -147,7 +149,7 @@ public:
#endif // LL_X11
protected:
- LLWindowSDL(
+ LLWindowSDL(LLWindowCallbacks* callbacks,
const std::string& title, int x, int y, int width, int height, U32 flags,
BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl,
BOOL ignore_pixel_depth, U32 fsaa_samples);
@@ -165,9 +167,6 @@ protected:
// Go back to last fullscreen display resolution.
BOOL setFullscreenResolution();
- void minimize();
- void restore();
-
BOOL shouldPostQuit() { return mPostQuit; }
protected:
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 6280868dfb..b591111b75 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -36,6 +36,17 @@
#include "llwindowwin32.h"
+// LLWindow library includes
+#include "llkeyboardwin32.h"
+#include "llpreeditor.h"
+#include "llwindowcallbacks.h"
+
+// Linden library includes
+#include "llerror.h"
+#include "llgl.h"
+#include "llstring.h"
+
+// System includes
#include <commdlg.h>
#include <WinUser.h>
#include <mapi.h>
@@ -49,16 +60,7 @@
#include <dinput.h>
#include <Dbt.h.>
-#include "llkeyboardwin32.h"
-#include "llerror.h"
-#include "llgl.h"
-#include "llstring.h"
-#include "lldir.h"
-
-#include "indra_constants.h"
-
-#include "llpreeditor.h"
-
+#include "llmemtype.h"
// culled from winuser.h
#ifndef WM_MOUSEWHEEL /* Added to be compatible with later SDK's */
const S32 WM_MOUSEWHEEL = 0x020A;
@@ -358,13 +360,14 @@ LLWinImm::~LLWinImm()
}
-LLWindowWin32::LLWindowWin32(const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
+LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
+ const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
S32 height, U32 flags,
BOOL fullscreen, BOOL clearBg,
BOOL disable_vsync, BOOL use_gl,
BOOL ignore_pixel_depth,
U32 fsaa_samples)
- : LLWindow(fullscreen, flags)
+ : LLWindow(callbacks, fullscreen, flags)
{
mFSAASamples = fsaa_samples;
mIconResource = gIconResource;
@@ -378,6 +381,7 @@ LLWindowWin32::LLWindowWin32(const std::string& title, const std::string& name,
// Initialize the keyboard
gKeyboard = new LLKeyboardWin32();
+ gKeyboard->setCallbacks(callbacks);
// Initialize (boot strap) the Language text input management,
// based on the system's (user's) default settings.
@@ -481,7 +485,8 @@ LLWindowWin32::LLWindowWin32(const std::string& title, const std::string& name,
if (!RegisterClass(&wc))
{
- OSMessageBox("RegisterClass failed", "Error", OSMB_OK);
+ OSMessageBox(mCallbacks->translateString("MBRegClassFailed"),
+ mCallbacks->translateString("MBError"), OSMB_OK);
return;
}
sIsClassRegistered = TRUE;
@@ -572,8 +577,11 @@ LLWindowWin32::LLWindowWin32(const std::string& title, const std::string& name,
mFullscreenBits = -1;
mFullscreenRefresh = -1;
- std::string error = llformat("Unable to run fullscreen at %d x %d.\nRunning in window.", width, height);
- OSMessageBox(error, "Error", OSMB_OK);
+ std::map<std::string,std::string> args;
+ args["[WIDTH]"] = llformat("%d", width);
+ args["[HEIGHT]"] = llformat ("%d", height);
+ OSMessageBox(mCallbacks->translateString("MBFullScreenErr", args),
+ mCallbacks->translateString("MBError"), OSMB_OK);
}
}
@@ -635,6 +643,7 @@ void LLWindowWin32::hide()
ShowWindow(mWindowHandle, SW_HIDE);
}
+//virtual
void LLWindowWin32::minimize()
{
setMouseClipping(FALSE);
@@ -642,7 +651,7 @@ void LLWindowWin32::minimize()
ShowWindow(mWindowHandle, SW_MINIMIZE);
}
-
+//virtual
void LLWindowWin32::restore()
{
ShowWindow(mWindowHandle, SW_RESTORE);
@@ -712,7 +721,9 @@ void LLWindowWin32::close()
// This causes WM_DESTROY to be sent *immediately*
if (!DestroyWindow(mWindowHandle))
{
- OSMessageBox("DestroyWindow(mWindowHandle) failed", "Shutdown Error", OSMB_OK);
+ OSMessageBox(mCallbacks->translateString("MBDestroyWinFailed"),
+ mCallbacks->translateString("MBShutdownErr"),
+ OSMB_OK);
}
mWindowHandle = NULL;
@@ -1015,14 +1026,16 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
if (!(mhDC = GetDC(mWindowHandle)))
{
close();
- OSMessageBox("Can't make GL device context", "Error", OSMB_OK);
+ OSMessageBox(mCallbacks->translateString("MBDevContextErr"),
+ mCallbacks->translateString("MBError"), OSMB_OK);
return FALSE;
}
if (!(pixel_format = ChoosePixelFormat(mhDC, &pfd)))
{
close();
- OSMessageBox("Can't find suitable pixel format", "Error", OSMB_OK);
+ OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"),
+ mCallbacks->translateString("MBError"), OSMB_OK);
return FALSE;
}
@@ -1031,57 +1044,48 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
&pfd))
{
close();
- OSMessageBox("Can't get pixel format description", "Error", OSMB_OK);
+ OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"),
+ mCallbacks->translateString("MBError"), OSMB_OK);
return FALSE;
}
if (pfd.cColorBits < 32)
{
close();
- OSMessageBox(
- "Second Life requires True Color (32-bit) to run in a window.\n"
- "Please go to Control Panels -> Display -> Settings and\n"
- "set the screen to 32-bit color.\n"
- "Alternately, if you choose to run fullscreen, Second Life\n"
- "will automatically adjust the screen each time it runs.",
- "Error",
- OSMB_OK);
+ OSMessageBox(mCallbacks->translateString("MBTrueColorWindow"),
+ mCallbacks->translateString("MBError"), OSMB_OK);
return FALSE;
}
if (pfd.cAlphaBits < 8)
{
close();
- OSMessageBox(
- "Second Life is unable to run because it can't get an 8 bit alpha\n"
- "channel. Usually this is due to video card driver issues.\n"
- "Please make sure you have the latest video card drivers installed.\n"
- "Also be sure your monitor is set to True Color (32-bit) in\n"
- "Control Panels -> Display -> Settings.\n"
- "If you continue to receive this message, contact customer service.",
- "Error",
- OSMB_OK);
+ OSMessageBox(mCallbacks->translateString("MBAlpha"),
+ mCallbacks->translateString("MBError"), OSMB_OK);
return FALSE;
}
if (!SetPixelFormat(mhDC, pixel_format, &pfd))
{
close();
- OSMessageBox("Can't set pixel format", "Error", OSMB_OK);
+ OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"),
+ mCallbacks->translateString("MBError"), OSMB_OK);
return FALSE;
}
if (!(mhRC = wglCreateContext(mhDC)))
{
close();
- OSMessageBox("Can't create GL rendering context", "Error", OSMB_OK);
+ OSMessageBox(mCallbacks->translateString("MBGLContextErr"),
+ mCallbacks->translateString("MBError"), OSMB_OK);
return FALSE;
}
if (!wglMakeCurrent(mhDC, mhRC))
{
close();
- OSMessageBox("Can't activate GL rendering context", "Error", OSMB_OK);
+ OSMessageBox(mCallbacks->translateString("MBGLContextActErr"),
+ mCallbacks->translateString("MBError"), OSMB_OK);
return FALSE;
}
@@ -1243,14 +1247,15 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
if (!(mhDC = GetDC(mWindowHandle)))
{
close();
- OSMessageBox("Can't make GL device context", "Error", OSMB_OK);
+ OSMessageBox(mCallbacks->translateString("MBDevContextErr"), mCallbacks->translateString("MBError"), OSMB_OK);
return FALSE;
}
if (!SetPixelFormat(mhDC, pixel_format, &pfd))
{
close();
- OSMessageBox("Can't set pixel format", "Error", OSMB_OK);
+ OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"),
+ mCallbacks->translateString("MBError"), OSMB_OK);
return FALSE;
}
@@ -1287,7 +1292,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
&pfd))
{
close();
- OSMessageBox("Can't get pixel format description", "Error", OSMB_OK);
+ OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"), mCallbacks->translateString("MBError"), OSMB_OK);
return FALSE;
}
@@ -1300,57 +1305,35 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
if (pfd.cColorBits < 32 || GetDeviceCaps(mhDC, BITSPIXEL) < 32)
{
close();
- OSMessageBox(
- "Second Life requires True Color (32-bit) to run in a window.\n"
- "Please go to Control Panels -> Display -> Settings and\n"
- "set the screen to 32-bit color.\n"
- "Alternately, if you choose to run fullscreen, Second Life\n"
- "will automatically adjust the screen each time it runs.",
- "Error",
- OSMB_OK);
+ OSMessageBox(mCallbacks->translateString("MBTrueColorWindow"), mCallbacks->translateString("MBError"), OSMB_OK);
return FALSE;
}
if (pfd.cAlphaBits < 8)
{
close();
- OSMessageBox(
- "Second Life is unable to run because it can't get an 8 bit alpha\n"
- "channel. Usually this is due to video card driver issues.\n"
- "Please make sure you have the latest video card drivers installed.\n"
- "Also be sure your monitor is set to True Color (32-bit) in\n"
- "Control Panels -> Display -> Settings.\n"
- "If you continue to receive this message, contact customer service.",
- "Error",
- OSMB_OK);
+ OSMessageBox(mCallbacks->translateString("MBAlpha"), mCallbacks->translateString("MBError"), OSMB_OK);
return FALSE;
}
if (!(mhRC = wglCreateContext(mhDC)))
{
close();
- OSMessageBox("Can't create GL rendering context", "Error", OSMB_OK);
+ OSMessageBox(mCallbacks->translateString("MBGLContextErr"), mCallbacks->translateString("MBError"), OSMB_OK);
return FALSE;
}
if (!wglMakeCurrent(mhDC, mhRC))
{
close();
- OSMessageBox("Can't activate GL rendering context", "Error", OSMB_OK);
+ OSMessageBox(mCallbacks->translateString("MBGLContextActErr"), mCallbacks->translateString("MBError"), OSMB_OK);
return FALSE;
}
if (!gGLManager.initGL())
{
close();
- OSMessageBox(
- "Second Life is unable to run because your video card drivers\n"
- "did not install properly, are out of date, or are for unsupported\n"
- "hardware. Please make sure you have the latest video card drivers\n"
- "and even if you do have the latest, try reinstalling them.\n\n"
- "If you continue to receive this message, contact customer service.",
- "Error",
- OSMB_OK);
+ OSMessageBox(mCallbacks->translateString("MBVideoDrvErr"), mCallbacks->translateString("MBError"), OSMB_OK);
return FALSE;
}
@@ -1545,10 +1528,6 @@ void LLWindowWin32::initCursors()
mCursor[ UI_CURSOR_PIPETTE ] = LoadCursor(module, TEXT("TOOLPIPETTE"));
// Color cursors
- mCursor[UI_CURSOR_TOOLSIT] = loadColorCursor(TEXT("TOOLSIT"));
- mCursor[UI_CURSOR_TOOLBUY] = loadColorCursor(TEXT("TOOLBUY"));
- mCursor[UI_CURSOR_TOOLPAY] = loadColorCursor(TEXT("TOOLPAY"));
- mCursor[UI_CURSOR_TOOLOPEN] = loadColorCursor(TEXT("TOOLOPEN"));
mCursor[UI_CURSOR_TOOLPLAY] = loadColorCursor(TEXT("TOOLPLAY"));
mCursor[UI_CURSOR_TOOLPAUSE] = loadColorCursor(TEXT("TOOLPAUSE"));
mCursor[UI_CURSOR_TOOLMEDIAOPEN] = loadColorCursor(TEXT("TOOLMEDIAOPEN"));
@@ -1612,6 +1591,8 @@ void LLWindowWin32::gatherInput()
MSG msg;
int msg_count = 0;
+ LLMemType m1(LLMemType::MTYPE_GATHER_INPUT);
+
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) && msg_count < MAX_MESSAGE_PER_UPDATE)
{
mCallbacks->handlePingWatchdog(this, "Main:TranslateGatherInput");
@@ -1661,6 +1642,9 @@ void LLWindowWin32::gatherInput()
mMousePositionModified = FALSE;
}
+static LLFastTimer::DeclareTimer FTM_KEYHANDLER("Handle Keyboard");
+static LLFastTimer::DeclareTimer FTM_MOUSEHANDLER("Handle Mouse");
+
LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param)
{
LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(h_wnd, GWL_USERDATA);
@@ -1894,7 +1878,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_KEYUP:
{
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYUP");
- LLFastTimer t2(LLFastTimer::FTM_KEYHANDLER);
+ LLFastTimer t2(FTM_KEYHANDLER);
if (gDebugWindowProc)
{
@@ -2003,7 +1987,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_LBUTTONDOWN:
{
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONDOWN");
- LLFastTimer t2(LLFastTimer::FTM_MOUSEHANDLER);
+ LLFastTimer t2(FTM_MOUSEHANDLER);
if (LLWinImm::isAvailable() && window_imp->mPreeditor)
{
window_imp->interruptLanguageTextInput();
@@ -2067,7 +2051,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_LBUTTONUP:
{
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONUP");
- LLFastTimer t2(LLFastTimer::FTM_MOUSEHANDLER);
+ LLFastTimer t2(FTM_MOUSEHANDLER);
//if (gDebugClicks)
//{
// LL_INFOS("Window") << "WndProc left button up" << LL_ENDL;
@@ -2101,7 +2085,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_RBUTTONDOWN:
{
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_RBUTTONDOWN");
- LLFastTimer t2(LLFastTimer::FTM_MOUSEHANDLER);
+ LLFastTimer t2(FTM_MOUSEHANDLER);
if (LLWinImm::isAvailable() && window_imp->mPreeditor)
{
window_imp->interruptLanguageTextInput();
@@ -2135,7 +2119,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_RBUTTONUP:
{
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_RBUTTONUP");
- LLFastTimer t2(LLFastTimer::FTM_MOUSEHANDLER);
+ LLFastTimer t2(FTM_MOUSEHANDLER);
// Because we move the cursor position in the app, we need to query
// to find out where the cursor at the time the event is handled.
// If we don't do this, many clicks could get buffered up, and if the
@@ -2165,7 +2149,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// case WM_MBUTTONDBLCLK:
{
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONDOWN");
- LLFastTimer t2(LLFastTimer::FTM_MOUSEHANDLER);
+ LLFastTimer t2(FTM_MOUSEHANDLER);
if (LLWinImm::isAvailable() && window_imp->mPreeditor)
{
window_imp->interruptLanguageTextInput();
@@ -2199,8 +2183,8 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_MBUTTONUP:
{
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONUP");
- LLFastTimer t2(LLFastTimer::FTM_MOUSEHANDLER);
- // Because we move the cursor position in tllviewerhe app, we need to query
+ LLFastTimer t2(FTM_MOUSEHANDLER);
+ // Because we move the cursor position in the llviewer app, we need to query
// to find out where the cursor at the time the event is handled.
// If we don't do this, many clicks could get buffered up, and if the
// first click changes the cursor position, all subsequent clicks
@@ -2230,7 +2214,27 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEWHEEL");
static short z_delta = 0;
- z_delta += HIWORD(w_param);
+ RECT client_rect;
+
+ // eat scroll events that occur outside our window, since we use mouse position to direct scroll
+ // instead of keyboard focus
+ // NOTE: mouse_coord is in *window* coordinates for scroll events
+ POINT mouse_coord = {(S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param)};
+
+ if (ScreenToClient(window_imp->mWindowHandle, &mouse_coord)
+ && GetClientRect(window_imp->mWindowHandle, &client_rect))
+ {
+ // we have a valid mouse point and client rect
+ if (mouse_coord.x < client_rect.left || client_rect.right < mouse_coord.x
+ || mouse_coord.y < client_rect.top || client_rect.bottom < mouse_coord.y)
+ {
+ // mouse is outside of client rect, so don't do anything
+ return 0;
+ }
+ }
+
+ S16 incoming_z_delta = HIWORD(w_param);
+ z_delta += incoming_z_delta;
// cout << "z_delta " << z_delta << endl;
// current mouse wheels report changes in increments of zDelta (+120, -120)
@@ -3030,7 +3034,7 @@ void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url )
}
-BOOL LLWindowWin32::dialog_color_picker ( F32 *r, F32 *g, F32 *b )
+BOOL LLWindowWin32::dialogColorPicker( F32 *r, F32 *g, F32 *b )
{
BOOL retval = FALSE;
@@ -3557,7 +3561,7 @@ BOOL LLWindowWin32::handleImeRequests(U32 request, U32 param, LRESULT *result)
// WCHARs, i.e., UTF-16 encoding units, so we can't simply pass the
// number to getPreeditLocation.
- const LLWString & wtext = mPreeditor->getWText();
+ const LLWString & wtext = mPreeditor->getPreeditString();
S32 preedit, preedit_length;
mPreeditor->getPreeditRange(&preedit, &preedit_length);
LLCoordGL caret_coord;
@@ -3584,7 +3588,7 @@ BOOL LLWindowWin32::handleImeRequests(U32 request, U32 param, LRESULT *result)
case IMR_RECONVERTSTRING:
{
mPreeditor->resetPreedit();
- const LLWString & wtext = mPreeditor->getWText();
+ const LLWString & wtext = mPreeditor->getPreeditString();
S32 select, select_length;
mPreeditor->getSelectionRange(&select, &select_length);
@@ -3626,7 +3630,7 @@ BOOL LLWindowWin32::handleImeRequests(U32 request, U32 param, LRESULT *result)
}
case IMR_DOCUMENTFEED:
{
- const LLWString & wtext = mPreeditor->getWText();
+ const LLWString & wtext = mPreeditor->getPreeditString();
S32 preedit, preedit_length;
mPreeditor->getPreeditRange(&preedit, &preedit_length);
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index 237f834318..e4e9179db7 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -54,6 +54,8 @@ public:
/*virtual*/ BOOL getMinimized();
/*virtual*/ BOOL getMaximized();
/*virtual*/ BOOL maximize();
+ /*virtual*/ void minimize();
+ /*virtual*/ void restore();
/*virtual*/ BOOL getFullscreen();
/*virtual*/ BOOL getPosition(LLCoordScreen *position);
/*virtual*/ BOOL getSize(LLCoordScreen *size);
@@ -100,7 +102,7 @@ public:
/*virtual*/ F32 getPixelAspectRatio();
/*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; }
- /*virtual*/ BOOL dialog_color_picker (F32 *r, F32 *g, F32 *b );
+ /*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b );
/*virtual*/ void *getPlatformWindow();
/*virtual*/ void bringToFront();
@@ -115,7 +117,7 @@ public:
static std::vector<std::string> getDynamicFallbackFontList();
protected:
- LLWindowWin32(
+ LLWindowWin32(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl,
BOOL ignore_pixel_depth, U32 fsaa_samples);
@@ -137,9 +139,6 @@ protected:
// Restore the display resolution to its value before we ran the app.
BOOL resetDisplayResolution();
- void minimize();
- void restore();
-
BOOL shouldPostQuit() { return mPostQuit; }
void fillCompositionForm(const LLRect& bounds, COMPOSITIONFORM *form);
diff --git a/indra/llxml/CMakeLists.txt b/indra/llxml/CMakeLists.txt
index dc7787beea..fbcfade383 100644
--- a/indra/llxml/CMakeLists.txt
+++ b/indra/llxml/CMakeLists.txt
@@ -5,11 +5,13 @@ project(llxml)
include(00-Common)
include(LLCommon)
include(LLMath)
+include(LLVFS)
include(LLXML)
include_directories(
${LLCOMMON_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS}
+ ${LLVFS_INCLUDE_DIRS}
)
set(llxml_SOURCE_FILES
@@ -38,7 +40,29 @@ add_library (llxml ${llxml_SOURCE_FILES})
# Libraries on which this library depends, needed for Linux builds
# Sort by high-level to low-level
target_link_libraries( llxml
+ llvfs
llmath
- ${BOOST_SIGNALS_LIBRARY}
${EXPAT_LIBRARIES}
)
+
+# tests
+
+# unit tests
+
+SET(llxml_TEST_SOURCE_FILES
+ # none yet!
+ )
+LL_ADD_PROJECT_UNIT_TESTS(llxml "${llxml_TEST_SOURCE_FILES}")
+
+# integration tests
+
+# set(TEST_DEBUG on)
+set(test_libs
+ ${LLXML_LIBRARIES}
+ ${WINDOWS_LIBRARIES}
+ ${LLMATH_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+ )
+
+LL_ADD_INTEGRATION_TEST(llcontrol "" "${test_libs}")
+
diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp
index 8bd04d727c..9d0cdacb1d 100644
--- a/indra/llxml/llcontrol.cpp
+++ b/indra/llxml/llcontrol.cpp
@@ -56,6 +56,45 @@
#define CONTROL_ERRS LL_WARNS("ControlErrors")
#endif
+
+template <> eControlType get_control_type<U32>();
+template <> eControlType get_control_type<S32>();
+template <> eControlType get_control_type<F32>();
+template <> eControlType get_control_type<bool>();
+// Yay BOOL, its really an S32.
+//template <> eControlType get_control_type<BOOL> () ;
+template <> eControlType get_control_type<std::string>();
+
+template <> eControlType get_control_type<LLVector3>();
+template <> eControlType get_control_type<LLVector3d>();
+template <> eControlType get_control_type<LLRect>();
+template <> eControlType get_control_type<LLColor4>();
+template <> eControlType get_control_type<LLColor3>();
+template <> eControlType get_control_type<LLColor4U>();
+template <> eControlType get_control_type<LLSD>();
+
+template <> LLSD convert_to_llsd<U32>(const U32& in);
+template <> LLSD convert_to_llsd<LLVector3>(const LLVector3& in);
+template <> LLSD convert_to_llsd<LLVector3d>(const LLVector3d& in);
+template <> LLSD convert_to_llsd<LLRect>(const LLRect& in);
+template <> LLSD convert_to_llsd<LLColor4>(const LLColor4& in);
+template <> LLSD convert_to_llsd<LLColor3>(const LLColor3& in);
+template <> LLSD convert_to_llsd<LLColor4U>(const LLColor4U& in);
+
+template <> bool convert_from_llsd<bool>(const LLSD& sd, eControlType type, const std::string& control_name);
+template <> S32 convert_from_llsd<S32>(const LLSD& sd, eControlType type, const std::string& control_name);
+template <> U32 convert_from_llsd<U32>(const LLSD& sd, eControlType type, const std::string& control_name);
+template <> F32 convert_from_llsd<F32>(const LLSD& sd, eControlType type, const std::string& control_name);
+template <> std::string convert_from_llsd<std::string>(const LLSD& sd, eControlType type, const std::string& control_name);
+template <> LLWString convert_from_llsd<LLWString>(const LLSD& sd, eControlType type, const std::string& control_name);
+template <> LLVector3 convert_from_llsd<LLVector3>(const LLSD& sd, eControlType type, const std::string& control_name);
+template <> LLVector3d convert_from_llsd<LLVector3d>(const LLSD& sd, eControlType type, const std::string& control_name);
+template <> LLRect convert_from_llsd<LLRect>(const LLSD& sd, eControlType type, const std::string& control_name);
+template <> LLColor4 convert_from_llsd<LLColor4>(const LLSD& sd, eControlType type, const std::string& control_name);
+template <> LLColor4U convert_from_llsd<LLColor4U>(const LLSD& sd, eControlType type, const std::string& control_name);
+template <> LLColor3 convert_from_llsd<LLColor3>(const LLSD& sd, eControlType type, const std::string& control_name);
+template <> LLSD convert_from_llsd<LLSD>(const LLSD& sd, eControlType type, const std::string& control_name);
+
//this defines the current version of the settings file
const S32 CURRENT_VERSION = 101;
@@ -87,9 +126,6 @@ bool LLControlVariable::llsd_compare(const LLSD& a, const LLSD & b)
case TYPE_COL3:
result = LLColor3(a) == LLColor3(b);
break;
- case TYPE_COL4U:
- result = LLColor4U(a) == LLColor4U(b);
- break;
case TYPE_STRING:
result = a.asString() == b.asString();
break;
@@ -148,9 +184,15 @@ LLSD LLControlVariable::getComparableValue(const LLSD& value)
return storable_value;
}
-void LLControlVariable::setValue(const LLSD& value, bool saved_value)
+void LLControlVariable::setValue(const LLSD& new_value, bool saved_value)
{
- LLSD storable_value = getComparableValue(value);
+ if (mValidateSignal(this, new_value) == false)
+ {
+ // can not set new value, exit
+ return;
+ }
+
+ LLSD storable_value = getComparableValue(new_value);
bool value_changed = llsd_compare(getValue(), storable_value) == FALSE;
if(saved_value)
{
@@ -163,7 +205,7 @@ void LLControlVariable::setValue(const LLSD& value, bool saved_value)
}
else
{
- // This is a unsaved value. Its needs to reside at
+ // This is an unsaved value. Its needs to reside at
// mValues[2] (or greater). It must not affect
// the result of getSaveValue()
if (llsd_compare(mValues.back(), storable_value) == FALSE)
@@ -185,10 +227,9 @@ void LLControlVariable::setValue(const LLSD& value, bool saved_value)
}
}
-
if(value_changed)
{
- mSignal(storable_value);
+ mCommitSignal(this, storable_value);
}
}
@@ -262,7 +303,8 @@ LLPointer<LLControlVariable> LLControlGroup::getControl(const std::string& name)
////////////////////////////////////////////////////////////////////////////
-LLControlGroup::LLControlGroup()
+LLControlGroup::LLControlGroup(const std::string& name)
+: LLInstanceTracker<LLControlGroup, std::string>(name)
{
mTypeString[TYPE_U32] = "U32";
mTypeString[TYPE_S32] = "S32";
@@ -274,7 +316,6 @@ LLControlGroup::LLControlGroup()
mTypeString[TYPE_RECT] = "Rect";
mTypeString[TYPE_COL4] = "Color4";
mTypeString[TYPE_COL3] = "Color3";
- mTypeString[TYPE_COL4U] = "Color4u";
mTypeString[TYPE_LLSD] = "LLSD";
}
@@ -370,11 +411,6 @@ BOOL LLControlGroup::declareRect(const std::string& name, const LLRect &initial_
return declareControl(name, TYPE_RECT, initial_val.getValue(), comment, persist);
}
-BOOL LLControlGroup::declareColor4U(const std::string& name, const LLColor4U &initial_val, const std::string& comment, BOOL persist )
-{
- return declareControl(name, TYPE_COL4U, initial_val.getValue(), comment, persist);
-}
-
BOOL LLControlGroup::declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, BOOL persist )
{
return declareControl(name, TYPE_COL4, initial_val.getValue(), comment, persist);
@@ -392,81 +428,32 @@ BOOL LLControlGroup::declareLLSD(const std::string& name, const LLSD &initial_va
BOOL LLControlGroup::getBOOL(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_BOOLEAN))
- return control->get().asBoolean();
- else
- {
- CONTROL_ERRS << "Invalid BOOL control " << name << llendl;
- return FALSE;
- }
+ return (BOOL)get<bool>(name);
}
S32 LLControlGroup::getS32(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_S32))
- return control->get().asInteger();
- else
- {
- CONTROL_ERRS << "Invalid S32 control " << name << llendl;
- return 0;
- }
+ return get<S32>(name);
}
U32 LLControlGroup::getU32(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_U32))
- return control->get().asInteger();
- else
- {
- CONTROL_ERRS << "Invalid U32 control " << name << llendl;
- return 0;
- }
+ return get<U32>(name);
}
F32 LLControlGroup::getF32(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_F32))
- return (F32) control->get().asReal();
- else
- {
- CONTROL_ERRS << "Invalid F32 control " << name << llendl;
- return 0.0f;
- }
-}
-
-std::string LLControlGroup::findString(const std::string& name)
-{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_STRING))
- return control->get().asString();
- return LLStringUtil::null;
+ return get<F32>(name);
}
std::string LLControlGroup::getString(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_STRING))
- return control->get().asString();
- else
- {
- CONTROL_ERRS << "Invalid string control " << name << llendl;
- return LLStringUtil::null;
- }
+ return get<std::string>(name);
}
LLWString LLControlGroup::getWString(const std::string& name)
{
- return utf8str_to_wstring(getString(name));
+ return get<LLWString>(name);
}
std::string LLControlGroup::getText(const std::string& name)
@@ -479,123 +466,38 @@ std::string LLControlGroup::getText(const std::string& name)
LLVector3 LLControlGroup::getVector3(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_VEC3))
- return control->get();
- else
- {
- CONTROL_ERRS << "Invalid LLVector3 control " << name << llendl;
- return LLVector3::zero;
- }
+ return get<LLVector3>(name);
}
LLVector3d LLControlGroup::getVector3d(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_VEC3D))
- return control->get();
- else
- {
- CONTROL_ERRS << "Invalid LLVector3d control " << name << llendl;
- return LLVector3d::zero;
- }
+ return get<LLVector3d>(name);
}
LLRect LLControlGroup::getRect(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_RECT))
- return control->get();
- else
- {
- CONTROL_ERRS << "Invalid rect control " << name << llendl;
- return LLRect::null;
- }
+ return get<LLRect>(name);
}
LLColor4 LLControlGroup::getColor(const std::string& name)
{
- ctrl_name_table_t::const_iterator i = mNameTable.find(name);
-
- if (i != mNameTable.end())
- {
- LLControlVariable* control = i->second;
-
- switch(control->mType)
- {
- case TYPE_COL4:
- {
- return LLColor4(control->get());
- }
- case TYPE_COL4U:
- {
- return LLColor4(LLColor4U(control->get()));
- }
- default:
- {
- CONTROL_ERRS << "Control " << name << " not a color" << llendl;
- return LLColor4::white;
- }
- }
- }
- else
- {
- CONTROL_ERRS << "Invalid getColor control " << name << llendl;
- return LLColor4::white;
- }
-}
-
-LLColor4U LLControlGroup::getColor4U(const std::string& name)
-{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_COL4U))
- return control->get();
- else
- {
- CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl;
- return LLColor4U::white;
- }
+ return get<LLColor4>(name);
}
LLColor4 LLControlGroup::getColor4(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_COL4))
- return control->get();
- else
- {
- CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl;
- return LLColor4::white;
- }
+ return get<LLColor4>(name);
}
LLColor3 LLControlGroup::getColor3(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_COL3))
- return control->get();
- else
- {
- CONTROL_ERRS << "Invalid LLColor3 control " << name << llendl;
- return LLColor3::white;
- }
+ return get<LLColor3>(name);
}
LLSD LLControlGroup::getLLSD(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_LLSD))
- return control->getValue();
- CONTROL_ERRS << "Invalid LLSD control " << name << llendl;
- return LLSD();
+ return get<LLSD>(name);
}
BOOL LLControlGroup::controlExists(const std::string& name)
@@ -604,170 +506,67 @@ BOOL LLControlGroup::controlExists(const std::string& name)
return iter != mNameTable.end();
}
+
//-------------------------------------------------------------------
// Set functions
//-------------------------------------------------------------------
void LLControlGroup::setBOOL(const std::string& name, BOOL val)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_BOOLEAN))
- {
- control->set(val);
- }
- else
- {
- CONTROL_ERRS << "Invalid control " << name << llendl;
- }
+ set<bool>(name, val);
}
void LLControlGroup::setS32(const std::string& name, S32 val)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_S32))
- {
- control->set(val);
- }
- else
- {
- CONTROL_ERRS << "Invalid control " << name << llendl;
- }
+ set(name, val);
}
void LLControlGroup::setF32(const std::string& name, F32 val)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_F32))
- {
- control->set(val);
- }
- else
- {
- CONTROL_ERRS << "Invalid control " << name << llendl;
- }
+ set(name, val);
}
void LLControlGroup::setU32(const std::string& name, U32 val)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_U32))
- {
- control->set((LLSD::Integer) val);
- }
- else
- {
- CONTROL_ERRS << "Invalid control " << name << llendl;
- }
+ set(name, val);
}
void LLControlGroup::setString(const std::string& name, const std::string &val)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_STRING))
- {
- control->set(val);
- }
- else
- {
- CONTROL_ERRS << "Invalid control " << name << llendl;
- }
+ set(name, val);
}
void LLControlGroup::setVector3(const std::string& name, const LLVector3 &val)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_VEC3))
- {
- control->set(val.getValue());
- }
- else
- {
- CONTROL_ERRS << "Invalid control " << name << llendl;
- }
+ set(name, val);
}
void LLControlGroup::setVector3d(const std::string& name, const LLVector3d &val)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_VEC3D))
- {
- control->set(val.getValue());
- }
- else
- {
- CONTROL_ERRS << "Invalid control " << name << llendl;
- }
+ set(name, val);
}
void LLControlGroup::setRect(const std::string& name, const LLRect &val)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_RECT))
- {
- control->set(val.getValue());
- }
- else
- {
- CONTROL_ERRS << "Invalid rect control " << name << llendl;
- }
-}
-
-void LLControlGroup::setColor4U(const std::string& name, const LLColor4U &val)
-{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_COL4U))
- {
- control->set(val.getValue());
- }
- else
- {
- CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl;
- }
+ set(name, val);
}
void LLControlGroup::setColor4(const std::string& name, const LLColor4 &val)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_COL4))
- {
- control->set(val.getValue());
- }
- else
- {
- CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl;
- }
+ set(name, val);
}
void LLControlGroup::setLLSD(const std::string& name, const LLSD& val)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_LLSD))
- {
- setValue(name, val);
- }
- else
- {
- CONTROL_ERRS << "Invalid LLSD control " << name << llendl;
- }
+ set(name, val);
}
-void LLControlGroup::setValue(const std::string& name, const LLSD& val)
+void LLControlGroup::setUntypedValue(const std::string& name, const LLSD& val)
{
if (name.empty())
{
@@ -778,7 +577,7 @@ void LLControlGroup::setValue(const std::string& name, const LLSD& val)
if (control)
{
- control->set(val);
+ control->setValue(val);
}
else
{
@@ -786,6 +585,7 @@ void LLControlGroup::setValue(const std::string& name, const LLSD& val)
}
}
+
//---------------------------------------------------------------
// Load and save
//---------------------------------------------------------------
@@ -854,9 +654,6 @@ U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require
case TYPE_COL4:
declareColor4(name, LLColor4::white, LLStringUtil::null, NO_PERSIST);
break;
- case TYPE_COL4U:
- declareColor4U(name, LLColor4U::white, LLStringUtil::null, NO_PERSIST);
- break;
case TYPE_STRING:
default:
declareString(name, LLStringUtil::null, LLStringUtil::null, NO_PERSIST);
@@ -954,15 +751,6 @@ U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require
validitems++;
}
break;
- case TYPE_COL4U:
- {
- LLColor4U color;
-
- child_nodep->getAttributeColor4U("value", color);
- control->set(color.getValue());
- validitems++;
- }
- break;
case TYPE_COL4:
{
LLColor4 color;
@@ -1063,6 +851,7 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v
U32 validitems = 0;
bool hidefromsettingseditor = false;
+
for(LLSD::map_const_iterator itr = settings.beginMap(); itr != settings.endMap(); ++itr)
{
bool persist = true;
@@ -1156,55 +945,6 @@ void LLControlGroup::applyToAll(ApplyFunctor* func)
}
//============================================================================
-// First-use
-
-static std::string get_warn_name(const std::string& name)
-{
- std::string warnname = "Warn" + name;
- for (std::string::iterator iter = warnname.begin(); iter != warnname.end(); ++iter)
- {
- char c = *iter;
- if (!isalnum(c))
- {
- *iter = '_';
- }
- }
- return warnname;
-}
-
-void LLControlGroup::addWarning(const std::string& name)
-{
- // Note: may get called more than once per warning
- // (e.g. if allready loaded from a settings file),
- // but that is OK, declareBOOL will handle it
- std::string warnname = get_warn_name(name);
- std::string comment = std::string("Enables ") + name + std::string(" warning dialog");
- declareBOOL(warnname, TRUE, comment);
- mWarnings.insert(warnname);
-}
-
-BOOL LLControlGroup::getWarning(const std::string& name)
-{
- std::string warnname = get_warn_name(name);
- return getBOOL(warnname);
-}
-
-void LLControlGroup::setWarning(const std::string& name, BOOL val)
-{
- std::string warnname = get_warn_name(name);
- setBOOL(warnname, val);
-}
-
-void LLControlGroup::resetWarnings()
-{
- for (std::set<std::string>::iterator iter = mWarnings.begin();
- iter != mWarnings.end(); ++iter)
- {
- setBOOL(*iter, TRUE);
- }
-}
-
-//============================================================================
#ifdef TEST_HARNESS
void main()
@@ -1268,4 +1008,297 @@ void main()
#endif
+template <> eControlType get_control_type<U32>()
+{
+ return TYPE_U32;
+}
+
+template <> eControlType get_control_type<S32>()
+{
+ return TYPE_S32;
+}
+
+template <> eControlType get_control_type<F32>()
+{
+ return TYPE_F32;
+}
+
+template <> eControlType get_control_type<bool> ()
+{
+ return TYPE_BOOLEAN;
+}
+/*
+// Yay BOOL, its really an S32.
+template <> eControlType get_control_type<BOOL> ()
+{
+ return TYPE_BOOLEAN;
+}
+*/
+template <> eControlType get_control_type<std::string>()
+{
+ return TYPE_STRING;
+}
+
+template <> eControlType get_control_type<LLVector3>()
+{
+ return TYPE_VEC3;
+}
+
+template <> eControlType get_control_type<LLVector3d>()
+{
+ return TYPE_VEC3D;
+}
+
+template <> eControlType get_control_type<LLRect>()
+{
+ return TYPE_RECT;
+}
+
+template <> eControlType get_control_type<LLColor4>()
+{
+ return TYPE_COL4;
+}
+
+template <> eControlType get_control_type<LLColor3>()
+{
+ return TYPE_COL3;
+}
+
+template <> eControlType get_control_type<LLSD>()
+{
+ return TYPE_LLSD;
+}
+
+
+template <> LLSD convert_to_llsd<U32>(const U32& in)
+{
+ return (LLSD::Integer)in;
+}
+
+template <> LLSD convert_to_llsd<LLVector3>(const LLVector3& in)
+{
+ return in.getValue();
+}
+
+template <> LLSD convert_to_llsd<LLVector3d>(const LLVector3d& in)
+{
+ return in.getValue();
+}
+
+template <> LLSD convert_to_llsd<LLRect>(const LLRect& in)
+{
+ return in.getValue();
+}
+
+template <> LLSD convert_to_llsd<LLColor4>(const LLColor4& in)
+{
+ return in.getValue();
+}
+
+template <> LLSD convert_to_llsd<LLColor3>(const LLColor3& in)
+{
+ return in.getValue();
+}
+
+template <> LLSD convert_to_llsd<LLColor4U>(const LLColor4U& in)
+{
+ return in.getValue();
+}
+
+
+template<>
+bool convert_from_llsd<bool>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ if (type == TYPE_BOOLEAN)
+ return sd.asBoolean();
+ else
+ {
+ CONTROL_ERRS << "Invalid BOOL value" << llendl;
+ return FALSE;
+ }
+}
+
+template<>
+S32 convert_from_llsd<S32>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ if (type == TYPE_S32)
+ return sd.asInteger();
+ else
+ {
+ CONTROL_ERRS << "Invalid S32 value" << llendl;
+ return 0;
+ }
+}
+
+template<>
+U32 convert_from_llsd<U32>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ if (type == TYPE_U32)
+ return sd.asInteger();
+ else
+ {
+ CONTROL_ERRS << "Invalid U32 value" << llendl;
+ return 0;
+ }
+}
+
+template<>
+F32 convert_from_llsd<F32>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ if (type == TYPE_F32)
+ return (F32) sd.asReal();
+ else
+ {
+ CONTROL_ERRS << "Invalid F32 value" << llendl;
+ return 0.0f;
+ }
+}
+
+template<>
+std::string convert_from_llsd<std::string>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ if (type == TYPE_STRING)
+ return sd.asString();
+ else
+ {
+ CONTROL_ERRS << "Invalid string value" << llendl;
+ return LLStringUtil::null;
+ }
+}
+
+template<>
+LLWString convert_from_llsd<LLWString>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ return utf8str_to_wstring(convert_from_llsd<std::string>(sd, type, control_name));
+}
+
+template<>
+LLVector3 convert_from_llsd<LLVector3>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ if (type == TYPE_VEC3)
+ return (LLVector3)sd;
+ else
+ {
+ CONTROL_ERRS << "Invalid LLVector3 value" << llendl;
+ return LLVector3::zero;
+ }
+}
+
+template<>
+LLVector3d convert_from_llsd<LLVector3d>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ if (type == TYPE_VEC3D)
+ return (LLVector3d)sd;
+ else
+ {
+ CONTROL_ERRS << "Invalid LLVector3d value" << llendl;
+ return LLVector3d::zero;
+ }
+}
+
+template<>
+LLRect convert_from_llsd<LLRect>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ if (type == TYPE_RECT)
+ return LLRect(sd);
+ else
+ {
+ CONTROL_ERRS << "Invalid rect value" << llendl;
+ return LLRect::null;
+ }
+}
+
+
+template<>
+LLColor4 convert_from_llsd<LLColor4>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ if (type == TYPE_COL4)
+ {
+ LLColor4 color(sd);
+ if (color.mV[VRED] < 0.f || color.mV[VRED] > 1.f)
+ {
+ llwarns << "Color " << control_name << " value out of range " << llendl;
+ }
+ else if (color.mV[VGREEN] < 0.f || color.mV[VGREEN] > 1.f)
+ {
+ llwarns << "Color " << control_name << " value out of range " << llendl;
+ }
+ else if (color.mV[VBLUE] < 0.f || color.mV[VBLUE] > 1.f)
+ {
+ llwarns << "Color " << control_name << " value out of range " << llendl;
+ }
+ else if (color.mV[VALPHA] < 0.f || color.mV[VALPHA] > 1.f)
+ {
+ llwarns << "Color " << control_name << " value out of range " << llendl;
+ }
+
+ return LLColor4(sd);
+ }
+ else
+ {
+ CONTROL_ERRS << "Control " << control_name << " not a color" << llendl;
+ return LLColor4::white;
+ }
+}
+
+template<>
+LLColor3 convert_from_llsd<LLColor3>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ if (type == TYPE_COL3)
+ return sd;
+ else
+ {
+ CONTROL_ERRS << "Invalid LLColor3 value" << llendl;
+ return LLColor3::white;
+ }
+}
+
+template<>
+LLSD convert_from_llsd<LLSD>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ return sd;
+}
+
+
+#if TEST_CACHED_CONTROL
+
+#define DECL_LLCC(T, V) static LLCachedControl<T> mySetting_##T("TestCachedControl"#T, V)
+DECL_LLCC(U32, (U32)666);
+DECL_LLCC(S32, (S32)-666);
+DECL_LLCC(F32, (F32)-666.666);
+DECL_LLCC(bool, true);
+DECL_LLCC(BOOL, FALSE);
+static LLCachedControl<std::string> mySetting_string("TestCachedControlstring", "Default String Value");
+DECL_LLCC(LLVector3, LLVector3(1.0f, 2.0f, 3.0f));
+DECL_LLCC(LLVector3d, LLVector3d(6.0f, 5.0f, 4.0f));
+DECL_LLCC(LLRect, LLRect(0, 0, 100, 500));
+DECL_LLCC(LLColor4, LLColor4(0.0f, 0.5f, 1.0f));
+DECL_LLCC(LLColor3, LLColor3(1.0f, 0.f, 0.5f));
+DECL_LLCC(LLColor4U, LLColor4U(255, 200, 100, 255));
+
+LLSD test_llsd = LLSD()["testing1"] = LLSD()["testing2"];
+DECL_LLCC(LLSD, test_llsd);
+
+static LLCachedControl<std::string> test_BrowserHomePage("BrowserHomePage", "hahahahahha", "Not the real comment");
+
+void test_cached_control()
+{
+#define TEST_LLCC(T, V) if((T)mySetting_##T != V) llerrs << "Fail "#T << llendl
+ TEST_LLCC(U32, 666);
+ TEST_LLCC(S32, (S32)-666);
+ TEST_LLCC(F32, (F32)-666.666);
+ TEST_LLCC(bool, true);
+ TEST_LLCC(BOOL, FALSE);
+ if((std::string)mySetting_string != "Default String Value") llerrs << "Fail string" << llendl;
+ TEST_LLCC(LLVector3, LLVector3(1.0f, 2.0f, 3.0f));
+ TEST_LLCC(LLVector3d, LLVector3d(6.0f, 5.0f, 4.0f));
+ TEST_LLCC(LLRect, LLRect(0, 0, 100, 500));
+ TEST_LLCC(LLColor4, LLColor4(0.0f, 0.5f, 1.0f));
+ TEST_LLCC(LLColor3, LLColor3(1.0f, 0.f, 0.5f));
+ TEST_LLCC(LLColor4U, LLColor4U(255, 200, 100, 255));
+//There's no LLSD comparsion for LLCC yet. TEST_LLCC(LLSD, test_llsd);
+
+ if((std::string)test_BrowserHomePage != "http://www.secondlife.com") llerrs << "Fail BrowserHomePage" << llendl;
+}
+#endif // TEST_CACHED_CONTROL
diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h
index ba0a1c7cbf..7d94601568 100644
--- a/indra/llxml/llcontrol.h
+++ b/indra/llxml/llcontrol.h
@@ -33,11 +33,14 @@
#ifndef LL_LLCONTROL_H
#define LL_LLCONTROL_H
+#include "llboost.h"
#include "llevent.h"
#include "llnametable.h"
#include "llmap.h"
#include "llstring.h"
#include "llrect.h"
+#include "llrefcount.h"
+#include "llinstancetracker.h"
#include "llcontrolgroupreader.h"
@@ -53,7 +56,16 @@
#endif
#include <boost/bind.hpp>
-#include <boost/signal.hpp>
+
+#if LL_WINDOWS
+ #pragma warning (push)
+ #pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
+ #pragma warning (disable : 4264)
+#endif
+#include <boost/signals2.hpp>
+#if LL_WINDOWS
+ #pragma warning (pop)
+#endif
#if LL_WINDOWS
# if (_MSC_VER >= 1300 && _MSC_VER < 1400)
@@ -65,7 +77,6 @@ class LLVector3;
class LLVector3d;
class LLColor4;
class LLColor3;
-class LLColor4U;
const BOOL NO_PERSIST = FALSE;
@@ -81,7 +92,6 @@ typedef enum e_control_type
TYPE_RECT,
TYPE_COL4,
TYPE_COL3,
- TYPE_COL4U,
TYPE_LLSD,
TYPE_COUNT
} eControlType;
@@ -89,7 +99,10 @@ typedef enum e_control_type
class LLControlVariable : public LLRefCount
{
friend class LLControlGroup;
- typedef boost::signal<void(const LLSD&)> signal_t;
+
+public:
+ typedef boost::signals2::signal<bool(LLControlVariable* control, const LLSD&), boost_boolean_combiner> validate_signal_t;
+ typedef boost::signals2::signal<void(LLControlVariable* control, const LLSD&)> commit_signal_t;
private:
std::string mName;
@@ -99,7 +112,8 @@ private:
bool mHideFromSettingsEditor;
std::vector<LLSD> mValues;
- signal_t mSignal;
+ commit_signal_t mCommitSignal;
+ validate_signal_t mValidateSignal;
public:
LLControlVariable(const std::string& name, eControlType type,
@@ -116,7 +130,9 @@ public:
void resetToDefault(bool fire_signal = false);
- signal_t* getSignal() { return &mSignal; }
+ commit_signal_t* getSignal() { return &mCommitSignal; } // shorthand for commit signal
+ commit_signal_t* getCommitSignal() { return &mCommitSignal; }
+ validate_signal_t* getValidateSignal() { return &mValidateSignal; }
bool isDefault() { return (mValues.size() == 1); }
bool isSaveValueDefault();
@@ -136,31 +152,55 @@ public:
void firePropertyChanged()
{
- mSignal(mValues.back());
+ mCommitSignal(this, mValues.back());
}
private:
LLSD getComparableValue(const LLSD& value);
bool llsd_compare(const LLSD& a, const LLSD & b);
-
};
+typedef LLPointer<LLControlVariable> LLControlVariablePtr;
+
+//! Helper functions for converting between static types and LLControl values
+template <class T>
+eControlType get_control_type()
+{
+ llwarns << "Usupported control type: " << typeid(T).name() << "." << llendl;
+ return TYPE_COUNT;
+}
+
+template <class T>
+LLSD convert_to_llsd(const T& in)
+{
+ // default implementation
+ return LLSD(in);
+}
+
+template <class T>
+T convert_from_llsd(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ // needs specialization
+ return T(sd);
+}
+
//const U32 STRING_CACHE_SIZE = 10000;
-class LLControlGroup : public LLControlGroupReader
+class LLControlGroup : public LLInstanceTracker<LLControlGroup, std::string>
{
protected:
- typedef std::map<std::string, LLPointer<LLControlVariable> > ctrl_name_table_t;
+ typedef std::map<std::string, LLControlVariablePtr > ctrl_name_table_t;
ctrl_name_table_t mNameTable;
- std::set<std::string> mWarnings;
std::string mTypeString[TYPE_COUNT];
eControlType typeStringToEnum(const std::string& typestr);
std::string typeEnumToString(eControlType typeenum);
public:
- LLControlGroup();
+ LLControlGroup(const std::string& name);
~LLControlGroup();
void cleanup();
- LLPointer<LLControlVariable> getControl(const std::string& name);
+ typedef LLInstanceTracker<LLControlGroup, std::string>::instance_iter instance_iter;
+
+ LLControlVariablePtr getControl(const std::string& name);
struct ApplyFunctor
{
@@ -178,33 +218,47 @@ public:
BOOL declareVec3(const std::string& name, const LLVector3 &initial_val,const std::string& comment, BOOL persist = TRUE);
BOOL declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, BOOL persist = TRUE);
BOOL declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, BOOL persist = TRUE);
- BOOL declareColor4U(const std::string& name, const LLColor4U &initial_val, const std::string& comment, BOOL persist = TRUE);
BOOL declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, BOOL persist = TRUE);
BOOL declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, BOOL persist = TRUE);
BOOL declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, BOOL persist = TRUE);
-
- std::string findString(const std::string& name);
- std::string getString(const std::string& name);
- LLWString getWString(const std::string& name);
- std::string getText(const std::string& name);
- LLVector3 getVector3(const std::string& name);
- LLVector3d getVector3d(const std::string& name);
- LLRect getRect(const std::string& name);
+ std::string getString(const std::string& name);
+ std::string getText(const std::string& name);
BOOL getBOOL(const std::string& name);
S32 getS32(const std::string& name);
F32 getF32(const std::string& name);
U32 getU32(const std::string& name);
+
+ LLWString getWString(const std::string& name);
+ LLVector3 getVector3(const std::string& name);
+ LLVector3d getVector3d(const std::string& name);
+ LLRect getRect(const std::string& name);
LLSD getLLSD(const std::string& name);
- // Note: If an LLColor4U control exists, it will cast it to the correct
- // LLColor4 for you.
LLColor4 getColor(const std::string& name);
- LLColor4U getColor4U(const std::string& name);
LLColor4 getColor4(const std::string& name);
LLColor3 getColor3(const std::string& name);
+ // generic getter
+ template<typename T> T get(const std::string& name)
+ {
+ LLControlVariable* control = getControl(name);
+ LLSD value;
+ eControlType type = TYPE_COUNT;
+
+ if (control)
+ {
+ value = control->get();
+ type = control->type();
+ }
+ else
+ {
+ llwarns << "Control " << name << " not found." << llendl;
+ }
+ return convert_from_llsd<T>(value, type, name);
+ }
+
void setBOOL(const std::string& name, BOOL val);
void setS32(const std::string& name, S32 val);
void setF32(const std::string& name, F32 val);
@@ -213,12 +267,26 @@ public:
void setVector3(const std::string& name, const LLVector3 &val);
void setVector3d(const std::string& name, const LLVector3d &val);
void setRect(const std::string& name, const LLRect &val);
- void setColor4U(const std::string& name, const LLColor4U &val);
void setColor4(const std::string& name, const LLColor4 &val);
- void setColor3(const std::string& name, const LLColor3 &val);
void setLLSD(const std::string& name, const LLSD& val);
- void setValue(const std::string& name, const LLSD& val);
+
+ // type agnostic setter that takes LLSD
+ void setUntypedValue(const std::string& name, const LLSD& val);
+
+ // generic setter
+ template<typename T> void set(const std::string& name, const T& val)
+ {
+ LLControlVariable* control = getControl(name);
+ if (control && control->isType(get_control_type<T>()))
+ {
+ control->set(convert_to_llsd(val));
+ }
+ else
+ {
+ llwarns << "Invalid control " << name << llendl;
+ }
+ }
BOOL controlExists(const std::string& name);
@@ -229,17 +297,166 @@ public:
U32 saveToFile(const std::string& filename, BOOL nondefault_only);
U32 loadFromFile(const std::string& filename, bool default_values = false);
void resetToDefaults();
+};
+
+//! Publish/Subscribe object to interact with LLControlGroups.
+
+//! Use an LLCachedControl instance to connect to a LLControlVariable
+//! without have to manually create and bind a listener to a local
+//! object.
+template <class T>
+class LLControlCache : public LLRefCount, public LLInstanceTracker<LLControlCache<T>, std::string>
+{
+public:
+ // This constructor will declare a control if it doesn't exist in the contol group
+ LLControlCache(LLControlGroup& group,
+ const std::string& name,
+ const T& default_value,
+ const std::string& comment)
+ : LLInstanceTracker<LLControlCache<T>, std::string >(name)
+ {
+ if(!group.controlExists(name))
+ {
+ if(!declareTypedControl(group, name, default_value, comment))
+ {
+ llerrs << "The control could not be created!!!" << llendl;
+ }
+ }
+
+ bindToControl(group, name);
+ }
+
+ LLControlCache(LLControlGroup& group,
+ const std::string& name)
+ : LLInstanceTracker<LLControlCache<T>, std::string >(name)
+ {
+ if(!group.controlExists(name))
+ {
+ llerrs << "Control named " << name << "not found." << llendl;
+ }
+
+ bindToControl(group, name);
+ }
+
+ ~LLControlCache()
+ {
+ }
+
+ const T& getValue() const { return mCachedValue; }
- // Ignorable Warnings
-
- // Add a config variable to be reset on resetWarnings()
- void addWarning(const std::string& name);
- BOOL getWarning(const std::string& name);
- void setWarning(const std::string& name, BOOL val);
-
- // Resets all ignorables
- void resetWarnings();
+private:
+ void bindToControl(LLControlGroup& group, const std::string& name)
+ {
+ LLControlVariablePtr controlp = group.getControl(name);
+ mType = controlp->type();
+ mCachedValue = convert_from_llsd<T>(controlp->get(), mType, name);
+
+ // Add a listener to the controls signal...
+ mConnection = controlp->getSignal()->connect(
+ boost::bind(&LLControlCache<T>::handleValueChange, this, _2)
+ );
+ mType = controlp->type();
+ }
+ bool declareTypedControl(LLControlGroup& group,
+ const std::string& name,
+ const T& default_value,
+ const std::string& comment)
+ {
+ LLSD init_value;
+ eControlType type = get_control_type<T>();
+ init_value = convert_to_llsd(default_value);
+ if(type < TYPE_COUNT)
+ {
+ group.declareControl(name, type, init_value, comment, FALSE);
+ return true;
+ }
+ return false;
+ }
+
+ bool handleValueChange(const LLSD& newvalue)
+ {
+ mCachedValue = convert_from_llsd<T>(newvalue, mType, "");
+ return true;
+ }
+
+private:
+ T mCachedValue;
+ eControlType mType;
+ boost::signals2::scoped_connection mConnection;
};
+template <typename T>
+class LLCachedControl
+{
+public:
+ LLCachedControl(LLControlGroup& group,
+ const std::string& name,
+ const T& default_value,
+ const std::string& comment = "Declared In Code")
+ {
+ mCachedControlPtr = LLControlCache<T>::getInstance(name);
+ if (mCachedControlPtr.isNull())
+ {
+ mCachedControlPtr = new LLControlCache<T>(group, name, default_value, comment);
+ }
+ }
+
+ LLCachedControl(LLControlGroup& group,
+ const std::string& name)
+ {
+ mCachedControlPtr = LLControlCache<T>::getInstance(name);
+ if (mCachedControlPtr.isNull())
+ {
+ mCachedControlPtr = new LLControlCache<T>(group, name);
+ }
+ }
+
+ operator const T&() const { return mCachedControlPtr->getValue(); }
+ operator boost::function<const T&()> () const { return boost::function<const T&()>(*this); }
+ const T& operator()() { return mCachedControlPtr->getValue(); }
+
+private:
+ LLPointer<LLControlCache<T> > mCachedControlPtr;
+};
+
+template <> eControlType get_control_type<U32>();
+template <> eControlType get_control_type<S32>();
+template <> eControlType get_control_type<F32>();
+template <> eControlType get_control_type<bool>();
+// Yay BOOL, its really an S32.
+//template <> eControlType get_control_type<BOOL> ()
+template <> eControlType get_control_type<std::string>();
+template <> eControlType get_control_type<LLVector3>();
+template <> eControlType get_control_type<LLVector3d>();
+template <> eControlType get_control_type<LLRect>();
+template <> eControlType get_control_type<LLColor4>();
+template <> eControlType get_control_type<LLColor3>();
+template <> eControlType get_control_type<LLSD>();
+
+template <> LLSD convert_to_llsd<U32>(const U32& in);
+template <> LLSD convert_to_llsd<LLVector3>(const LLVector3& in);
+template <> LLSD convert_to_llsd<LLVector3d>(const LLVector3d& in);
+template <> LLSD convert_to_llsd<LLRect>(const LLRect& in);
+template <> LLSD convert_to_llsd<LLColor4>(const LLColor4& in);
+template <> LLSD convert_to_llsd<LLColor3>(const LLColor3& in);
+
+template<> std::string convert_from_llsd<std::string>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> LLWString convert_from_llsd<LLWString>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> LLVector3 convert_from_llsd<LLVector3>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> LLVector3d convert_from_llsd<LLVector3d>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> LLRect convert_from_llsd<LLRect>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> bool convert_from_llsd<bool>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> S32 convert_from_llsd<S32>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> F32 convert_from_llsd<F32>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> U32 convert_from_llsd<U32>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> LLColor3 convert_from_llsd<LLColor3>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> LLColor4 convert_from_llsd<LLColor4>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> LLSD convert_from_llsd<LLSD>(const LLSD& sd, eControlType type, const std::string& control_name);
+
+//#define TEST_CACHED_CONTROL 1
+#ifdef TEST_CACHED_CONTROL
+void test_cached_control();
+#endif // TEST_CACHED_CONTROL
+
#endif
diff --git a/indra/llxml/llcontrolgroupreader.h b/indra/llxml/llcontrolgroupreader.h
index 960b19036e..116ea2eae0 100644
--- a/indra/llxml/llcontrolgroupreader.h
+++ b/indra/llxml/llcontrolgroupreader.h
@@ -3,7 +3,30 @@
* @brief Interface providing readonly access to LLControlGroup (intended for unit testing)
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
* Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
@@ -13,9 +36,11 @@
#include "stdtypes.h"
#include <string>
-// Many of the types below are commented out because for the purposes of the early testing we're doing,
-// we don't need them and we don't want to pull in all the machinery to support them.
-// But the model is here for future unit test extensions.
+#include "v3math.h"
+#include "v3dmath.h"
+#include "v3color.h"
+#include "v4color.h"
+#include "llrect.h"
class LLControlGroupReader
{
@@ -23,22 +48,32 @@ public:
LLControlGroupReader() {}
virtual ~LLControlGroupReader() {}
- virtual std::string getString(const std::string& name) = 0;
- //virtual LLWString getWString(const std::string& name) = 0;
- virtual std::string getText(const std::string& name) = 0;
- //virtual LLVector3 getVector3(const std::string& name) = 0;
- //virtual LLVector3d getVector3d(const std::string& name) = 0;
- //virtual LLRect getRect(const std::string& name) = 0;
- virtual BOOL getBOOL(const std::string& name) = 0;
- virtual S32 getS32(const std::string& name) = 0;
- virtual F32 getF32(const std::string& name) = 0;
- virtual U32 getU32(const std::string& name) = 0;
- //virtual LLSD getLLSD(const std::string& name) = 0;
-
- //virtual LLColor4 getColor(const std::string& name) = 0;
- //virtual LLColor4U getColor4U(const std::string& name) = 0;
- //virtual LLColor4 getColor4(const std::string& name) = 0;
- //virtual LLColor3 getColor3(const std::string& name) = 0;
+ virtual std::string getString(const std::string& name) { return ""; }
+ virtual LLWString getWString(const std::string& name) { return LLWString(); }
+ virtual std::string getText(const std::string& name) { return ""; }
+ virtual LLVector3 getVector3(const std::string& name) { return LLVector3(); }
+ virtual LLVector3d getVector3d(const std::string& name) { return LLVector3d(); }
+ virtual LLRect getRect(const std::string& name) { return LLRect(); }
+ virtual BOOL getBOOL(const std::string& name) { return FALSE; }
+ virtual S32 getS32(const std::string& name) { return 0; }
+ virtual F32 getF32(const std::string& name) {return 0.0f; }
+ virtual U32 getU32(const std::string& name) {return 0; }
+ virtual LLSD getLLSD(const std::string& name) { return LLSD(); }
+
+ virtual LLColor4 getColor(const std::string& name) { return LLColor4(); }
+ virtual LLColor4 getColor4(const std::string& name) { return LLColor4(); }
+ virtual LLColor3 getColor3(const std::string& name) { return LLColor3(); }
+
+ virtual void setBOOL(const std::string& name, BOOL val) {}
+ virtual void setS32(const std::string& name, S32 val) {}
+ virtual void setF32(const std::string& name, F32 val) {}
+ virtual void setU32(const std::string& name, U32 val) {}
+ virtual void setString(const std::string& name, const std::string& val) {}
+ virtual void setVector3(const std::string& name, const LLVector3 &val) {}
+ virtual void setVector3d(const std::string& name, const LLVector3d &val) {}
+ virtual void setRect(const std::string& name, const LLRect &val) {}
+ virtual void setColor4(const std::string& name, const LLColor4 &val) {}
+ virtual void setLLSD(const std::string& name, const LLSD& val) {}
};
#endif /* LL_LLCONTROLGROUPREADER_H */
diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp
index 800b13573f..07cc612a0a 100644
--- a/indra/llxml/llxmlnode.cpp
+++ b/indra/llxml/llxmlnode.cpp
@@ -47,6 +47,7 @@
#include "llquaternion.h"
#include "llstring.h"
#include "lluuid.h"
+#include "lldir.h"
const S32 MAX_COLUMN_WIDTH = 80;
@@ -64,6 +65,7 @@ LLXMLNode::LLXMLNode() :
mPrecision(64),
mType(TYPE_CONTAINER),
mEncoding(ENCODING_DEFAULT),
+ mLineNumber(-1),
mParent(NULL),
mChildren(NULL),
mAttributes(),
@@ -85,6 +87,7 @@ LLXMLNode::LLXMLNode(const char* name, BOOL is_attribute) :
mPrecision(64),
mType(TYPE_CONTAINER),
mEncoding(ENCODING_DEFAULT),
+ mLineNumber(-1),
mParent(NULL),
mChildren(NULL),
mAttributes(),
@@ -106,6 +109,7 @@ LLXMLNode::LLXMLNode(LLStringTableEntry* name, BOOL is_attribute) :
mPrecision(64),
mType(TYPE_CONTAINER),
mEncoding(ENCODING_DEFAULT),
+ mLineNumber(-1),
mParent(NULL),
mChildren(NULL),
mAttributes(),
@@ -145,7 +149,7 @@ LLXMLNodePtr LLXMLNode::deepCopy()
if (mChildren.notNull())
{
for (LLXMLChildList::iterator iter = mChildren->map.begin();
- iter != mChildren->map.end(); ++iter)
+ iter != mChildren->map.end(); ++iter)
{
newnode->addChild(iter->second->deepCopy());
}
@@ -226,6 +230,10 @@ BOOL LLXMLNode::removeChild(LLXMLNode *target_child)
{
mChildren->head = target_child->mNext;
}
+ if (target_child == mChildren->tail)
+ {
+ mChildren->tail = target_child->mPrev;
+ }
LLXMLNodePtr prev = target_child->mPrev;
LLXMLNodePtr next = target_child->mNext;
@@ -294,6 +302,22 @@ void LLXMLNode::addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child)
mChildren->tail = new_child;
}
}
+ // if after_child == parent, then put new_child at beginning
+ else if (after_child == this)
+ {
+ // add to front of list
+ new_child->mNext = mChildren->head;
+ if (mChildren->head)
+ {
+ mChildren->head->mPrev = new_child;
+ mChildren->head = new_child;
+ }
+ else // no children
+ {
+ mChildren->head = new_child;
+ mChildren->tail = new_child;
+ }
+ }
else
{
if (after_child->mNext.notNull())
@@ -387,6 +411,7 @@ void XMLCALL StartXMLNode(void *userData,
{
// Create a new node
LLXMLNode *new_node_ptr = new LLXMLNode(name, FALSE);
+
LLXMLNodePtr new_node = new_node_ptr;
new_node->mID.clear();
LLXMLNodePtr ptr_new_node = new_node;
@@ -401,7 +426,8 @@ void XMLCALL StartXMLNode(void *userData,
}
new_node_ptr->mParser = parent->mParser;
-
+ new_node_ptr->setLineNumber(XML_GetCurrentLineNumber(*new_node_ptr->mParser));
+
// Set the current active node to the new node
XML_Parser *parser = parent->mParser;
XML_SetUserData(*parser, (void *)new_node_ptr);
@@ -492,6 +518,7 @@ void XMLCALL StartXMLNode(void *userData,
if (!new_node->getAttribute(attr_name.c_str(), attr_node, FALSE))
{
attr_node = new LLXMLNode(attr_name.c_str(), TRUE);
+ attr_node->setLineNumber(XML_GetCurrentLineNumber(*new_node_ptr->mParser));
}
attr_node->setValue(attr_value);
new_node->addChild(attr_node);
@@ -836,12 +863,66 @@ BOOL LLXMLNode::isFullyDefault()
}
// static
-void LLXMLNode::writeHeaderToFile(LLFILE *fOut)
+bool LLXMLNode::getLayeredXMLNode(const std::string &xui_filename, LLXMLNodePtr& root,
+ const std::vector<std::string>& paths)
{
- fprintf(fOut, "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n");
+ std::string full_filename = gDirUtilp->findSkinnedFilename(paths.front(), xui_filename);
+ if (full_filename.empty())
+ {
+ return false;
+ }
+
+ if (!LLXMLNode::parseFile(full_filename, root, NULL))
+ {
+ // try filename as passed in since sometimes we load an xml file from a user-supplied path
+ if (!LLXMLNode::parseFile(xui_filename, root, NULL))
+ {
+ llwarns << "Problem reading UI description file: " << xui_filename << llendl;
+ return false;
+ }
+ }
+
+ LLXMLNodePtr updateRoot;
+
+ std::vector<std::string>::const_iterator itor;
+
+ for (itor = paths.begin(), ++itor; itor != paths.end(); ++itor)
+ {
+ std::string nodeName;
+ std::string updateName;
+
+ std::string layer_filename = gDirUtilp->findSkinnedFilename((*itor), xui_filename);
+ if(layer_filename.empty())
+ {
+ // no localized version of this file, that's ok, keep looking
+ continue;
+ }
+
+ if (!LLXMLNode::parseFile(layer_filename, updateRoot, NULL))
+ {
+ llwarns << "Problem reading localized UI description file: " << (*itor) + gDirUtilp->getDirDelimiter() + xui_filename << llendl;
+ return false;
+ }
+
+ updateRoot->getAttributeString("name", updateName);
+ root->getAttributeString("name", nodeName);
+
+ if (updateName == nodeName)
+ {
+ LLXMLNode::updateNode(root, updateRoot);
+ }
+ }
+
+ return true;
}
-void LLXMLNode::writeToFile(LLFILE *fOut, const std::string& indent)
+// static
+void LLXMLNode::writeHeaderToFile(LLFILE *out_file)
+{
+ fprintf(out_file, "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n");
+}
+
+void LLXMLNode::writeToFile(LLFILE *out_file, const std::string& indent, bool use_type_decorations)
{
if (isFullyDefault())
{
@@ -850,15 +931,16 @@ void LLXMLNode::writeToFile(LLFILE *fOut, const std::string& indent)
}
std::ostringstream ostream;
- writeToOstream(ostream, indent);
+ writeToOstream(ostream, indent, use_type_decorations);
std::string outstring = ostream.str();
- if (fwrite(outstring.c_str(), 1, outstring.length(), fOut) != outstring.length())
+ size_t written = fwrite(outstring.c_str(), 1, outstring.length(), out_file);
+ if (written != outstring.length())
{
llwarns << "Short write" << llendl;
}
}
-void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& indent)
+void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& indent, bool use_type_decorations)
{
if (isFullyDefault())
{
@@ -872,84 +954,86 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
BOOL has_default_length = mDefault.isNull()?FALSE:(mLength == mDefault->mLength);
// stream the name
- output_stream << indent << "<" << mName->mString;
+ output_stream << indent << "<" << mName->mString << "\n";
- // ID
- if (mID != "")
+ if (use_type_decorations)
{
- output_stream << " id=\"" << mID << "\"";
- }
+ // ID
+ if (mID != "")
+ {
+ output_stream << indent << " id=\"" << mID << "\"\n";
+ }
- // Type
- if (!has_default_type)
- {
- switch (mType)
+ // Type
+ if (!has_default_type)
{
- case TYPE_BOOLEAN:
- output_stream << " type=\"boolean\"";
- break;
- case TYPE_INTEGER:
- output_stream << " type=\"integer\"";
- break;
- case TYPE_FLOAT:
- output_stream << " type=\"float\"";
- break;
- case TYPE_STRING:
- output_stream << " type=\"string\"";
- break;
- case TYPE_UUID:
- output_stream << " type=\"uuid\"";
- break;
- case TYPE_NODEREF:
- output_stream << " type=\"noderef\"";
- break;
- default:
- // default on switch(enum) eliminates a warning on linux
- break;
- };
- }
+ switch (mType)
+ {
+ case TYPE_BOOLEAN:
+ output_stream << indent << " type=\"boolean\"\n";
+ break;
+ case TYPE_INTEGER:
+ output_stream << indent << " type=\"integer\"\n";
+ break;
+ case TYPE_FLOAT:
+ output_stream << indent << " type=\"float\"\n";
+ break;
+ case TYPE_STRING:
+ output_stream << indent << " type=\"string\"\n";
+ break;
+ case TYPE_UUID:
+ output_stream << indent << " type=\"uuid\"\n";
+ break;
+ case TYPE_NODEREF:
+ output_stream << indent << " type=\"noderef\"\n";
+ break;
+ default:
+ // default on switch(enum) eliminates a warning on linux
+ break;
+ };
+ }
- // Encoding
- if (!has_default_encoding)
- {
- switch (mEncoding)
+ // Encoding
+ if (!has_default_encoding)
{
- case ENCODING_DECIMAL:
- output_stream << " encoding=\"decimal\"";
- break;
- case ENCODING_HEX:
- output_stream << " encoding=\"hex\"";
- break;
- /*case ENCODING_BASE32:
- output_stream << " encoding=\"base32\"";
- break;*/
- default:
- // default on switch(enum) eliminates a warning on linux
- break;
- };
- }
+ switch (mEncoding)
+ {
+ case ENCODING_DECIMAL:
+ output_stream << indent << " encoding=\"decimal\"\n";
+ break;
+ case ENCODING_HEX:
+ output_stream << indent << " encoding=\"hex\"\n";
+ break;
+ /*case ENCODING_BASE32:
+ output_stream << indent << " encoding=\"base32\"\n";
+ break;*/
+ default:
+ // default on switch(enum) eliminates a warning on linux
+ break;
+ };
+ }
- // Precision
- if (!has_default_precision && (mType == TYPE_INTEGER || mType == TYPE_FLOAT))
- {
- output_stream << " precision=\"" << mPrecision << "\"";
- }
+ // Precision
+ if (!has_default_precision && (mType == TYPE_INTEGER || mType == TYPE_FLOAT))
+ {
+ output_stream << indent << " precision=\"" << mPrecision << "\"\n";
+ }
- // Version
- if (mVersionMajor > 0 || mVersionMinor > 0)
- {
- output_stream << " version=\"" << mVersionMajor << "." << mVersionMinor << "\"";
- }
+ // Version
+ if (mVersionMajor > 0 || mVersionMinor > 0)
+ {
+ output_stream << indent << " version=\"" << mVersionMajor << "." << mVersionMinor << "\"\n";
+ }
- // Array length
- if (!has_default_length && mLength > 0)
- {
- output_stream << " length=\"" << mLength << "\"";
+ // Array length
+ if (!has_default_length && mLength > 0)
+ {
+ output_stream << indent << " length=\"" << mLength << "\"\n";
+ }
}
{
// Write out attributes
- S32 col_pos = 0;
LLXMLAttribList::const_iterator attr_itr;
LLXMLAttribList::const_iterator attr_end = mAttributes.end();
for (attr_itr = mAttributes.begin(); attr_itr != attr_end; ++attr_itr)
@@ -958,12 +1042,13 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
if (child->mDefault.isNull() || child->mDefault->mValue != child->mValue)
{
std::string attr = child->mName->mString;
- if (attr == "id" ||
- attr == "type" ||
- attr == "encoding" ||
- attr == "precision" ||
- attr == "version" ||
- attr == "length")
+ if (use_type_decorations
+ && (attr == "id" ||
+ attr == "type" ||
+ attr == "encoding" ||
+ attr == "precision" ||
+ attr == "version" ||
+ attr == "length"))
{
continue; // skip built-in attributes
}
@@ -971,17 +1056,14 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
std::string attr_str = llformat(" %s=\"%s\"",
attr.c_str(),
escapeXML(child->mValue).c_str());
- if (col_pos + (S32)attr_str.length() > MAX_COLUMN_WIDTH)
- {
- output_stream << "\n" << indent << " ";
- col_pos = 4;
- }
- col_pos += attr_str.length();
- output_stream << attr_str;
+ output_stream << indent << attr_str << "\n";
}
}
}
+ // erase last \n before attaching final > or />
+ output_stream.seekp(-1, std::ios::cur);
+
if (mChildren.isNull() && mValue == "")
{
output_stream << " />\n";
@@ -993,16 +1075,16 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
if (mChildren.notNull())
{
// stream non-attributes
- std::string next_indent = indent + "\t";
+ std::string next_indent = indent + " ";
for (LLXMLNode* child = getFirstChild(); child; child = child->getNextSibling())
{
- child->writeToOstream(output_stream, next_indent);
+ child->writeToOstream(output_stream, next_indent, use_type_decorations);
}
}
if (!mValue.empty())
{
std::string contents = getTextContents();
- output_stream << indent << "\t" << escapeXML(contents) << "\n";
+ output_stream << indent << " " << escapeXML(contents) << "\n";
}
output_stream << indent << "</" << mName->mString << ">\n";
}
@@ -2475,14 +2557,15 @@ std::string LLXMLNode::escapeXML(const std::string& xml)
return out;
}
-void LLXMLNode::setStringValue(U32 length, const std::string *array)
+void LLXMLNode::setStringValue(U32 length, const std::string *strings)
{
if (length == 0) return;
std::string new_value;
for (U32 pos=0; pos<length; ++pos)
{
- new_value.append(escapeXML(array[pos]));
+ // *NOTE: Do not escape strings here - do it on output
+ new_value.append( strings[pos] );
if (pos < length-1) new_value.append(" ");
}
@@ -3150,6 +3233,19 @@ LLXMLNodePtr LLXMLNode::getNextSibling() const
return ret;
}
+std::string LLXMLNode::getSanitizedValue() const
+{
+ if (mIsAttribute)
+ {
+ return getValue() ;
+ }
+ else
+ {
+ return getTextContents();
+ }
+}
+
+
std::string LLXMLNode::getTextContents() const
{
std::string msg;
@@ -3215,3 +3311,13 @@ std::string LLXMLNode::getTextContents() const
}
return msg;
}
+
+void LLXMLNode::setLineNumber(S32 line_number)
+{
+ mLineNumber = line_number;
+}
+
+S32 LLXMLNode::getLineNumber()
+{
+ return mLineNumber;
+}
diff --git a/indra/llxml/llxmlnode.h b/indra/llxml/llxmlnode.h
index d4e127b05c..7823607c3b 100644
--- a/indra/llxml/llxmlnode.h
+++ b/indra/llxml/llxmlnode.h
@@ -34,7 +34,7 @@
#define LL_LLXMLNODE_H
#ifndef XML_STATIC
-#define XML_STATIC 1
+#define XML_STATIC
#endif
#ifdef LL_STANDALONE
#include <expat.h>
@@ -44,10 +44,11 @@
#include <map>
#include "indra_constants.h"
-#include "llmemory.h"
-#include "llthread.h"
+#include "llpointer.h"
+#include "llthread.h" // LLThreadSafeRefCount
#include "llstring.h"
#include "llstringtable.h"
+#include "llfile.h"
class LLVector3;
@@ -153,9 +154,19 @@ public:
LLXMLNodePtr& node,
LLXMLNodePtr& update_node);
static LLXMLNodePtr replaceNode(LLXMLNodePtr node, LLXMLNodePtr replacement_node);
- static void writeHeaderToFile(LLFILE *fOut);
- void writeToFile(LLFILE *fOut, const std::string& indent = std::string());
- void writeToOstream(std::ostream& output_stream, const std::string& indent = std::string());
+
+ static bool getLayeredXMLNode(const std::string &xui_filename, LLXMLNodePtr& root,
+ const std::vector<std::string>& paths);
+
+
+ // Write standard XML file header:
+ // <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+ static void writeHeaderToFile(LLFILE *out_file);
+
+ // Write XML to file with one attribute per line.
+ // XML escapes values as they are written.
+ void writeToFile(LLFILE *out_file, const std::string& indent = std::string(), bool use_type_decorations=true);
+ void writeToOstream(std::ostream& output_stream, const std::string& indent = std::string(), bool use_type_decorations=true);
// Utility
void findName(const std::string& name, LLXMLNodeList &results);
@@ -207,6 +218,7 @@ public:
U32 getLength() const { return mLength; }
U32 getPrecision() const { return mPrecision; }
const std::string& getValue() const { return mValue; }
+ std::string getSanitizedValue() const;
std::string getTextContents() const;
const LLStringTableEntry* getName() const { return mName; }
BOOL hasName(const char* name) const { return mName == gStringTable.checkStringEntry(name); }
@@ -227,6 +239,8 @@ public:
bool getAttribute(const char* name, LLXMLNodePtr& node, BOOL use_default_if_missing = TRUE);
bool getAttribute(const LLStringTableEntry* name, LLXMLNodePtr& node, BOOL use_default_if_missing = TRUE);
+ S32 getLineNumber();
+
// The following skip over attributes
LLXMLNodePtr getFirstChild() const;
LLXMLNodePtr getNextSibling() const;
@@ -262,6 +276,8 @@ public:
void setName(const std::string& name);
void setName(LLStringTableEntry* name);
+ void setLineNumber(S32 line_number);
+
// Escapes " (quot) ' (apos) & (amp) < (lt) > (gt)
static std::string escapeXML(const std::string& xml);
@@ -300,6 +316,7 @@ public:
U32 mPrecision; // The number of BITS per array item
ValueType mType; // The value type
Encoding mEncoding; // The value encoding
+ S32 mLineNumber; // line number in source file, if applicable
LLXMLNode* mParent; // The parent node
LLXMLChildrenPtr mChildren; // The child nodes
@@ -312,7 +329,11 @@ public:
protected:
LLStringTableEntry *mName; // The name of this node
- std::string mValue; // The value of this node (use getters/setters only)
+
+ // The value of this node (use getters/setters only)
+ // Values are not XML-escaped in memory
+ // They may contain " (quot) ' (apos) & (amp) < (lt) > (gt)
+ std::string mValue;
LLXMLNodePtr mDefault; // Mirror node in the default tree
diff --git a/indra/llxml/llxmlparser.h b/indra/llxml/llxmlparser.h
index d7595f6a68..fa9e8175e2 100644
--- a/indra/llxml/llxmlparser.h
+++ b/indra/llxml/llxmlparser.h
@@ -34,7 +34,7 @@
#define LL_LLXMLPARSER_H
#ifndef XML_STATIC
-#define XML_STATIC 1
+#define XML_STATIC
#endif
#ifdef LL_STANDALONE
#include <expat.h>
diff --git a/indra/llxml/tests/llcontrol_test.cpp b/indra/llxml/tests/llcontrol_test.cpp
new file mode 100644
index 0000000000..1ab564264d
--- /dev/null
+++ b/indra/llxml/tests/llcontrol_test.cpp
@@ -0,0 +1,161 @@
+/**
+ * @file llcontrol_tut.cpp
+ * @date February 2008
+ * @brief control group unit tests
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llsdserialize.h"
+
+#include "../llcontrol.h"
+
+#include "../test/lltut.h"
+
+namespace tut
+{
+
+ struct control_group
+ {
+ LLControlGroup* mCG;
+ std::string mTestConfigDir;
+ std::string mTestConfigFile;
+ static bool mListenerFired;
+ control_group()
+ {
+ mCG = new LLControlGroup("foo");
+ LLUUID random;
+ random.generate();
+ // generate temp dir
+ std::ostringstream oStr;
+
+#ifdef LL_WINDOWS
+ char* tmp_dir = getenv("TMP");
+ if(tmp_dir)
+ {
+ oStr << tmp_dir << "/llcontrol-test-" << random << "/";
+ }
+ else
+ {
+ oStr << "c:/tmp/llcontrol-test-" << random << "/";
+ }
+#else
+ oStr << "/tmp/llcontrol-test-" << random << "/";
+#endif
+
+ mTestConfigDir = oStr.str();
+ mTestConfigFile = mTestConfigDir + "settings.xml";
+ LLFile::mkdir(mTestConfigDir);
+ LLSD config;
+ config["TestSetting"]["Comment"] = "Dummy setting used for testing";
+ config["TestSetting"]["Persist"] = 1;
+ config["TestSetting"]["Type"] = "U32";
+ config["TestSetting"]["Value"] = 12;
+ writeSettingsFile(config);
+ }
+ ~control_group()
+ {
+ //Remove test files
+ delete mCG;
+ }
+ void writeSettingsFile(const LLSD& config)
+ {
+ llofstream file(mTestConfigFile);
+ if (file.is_open())
+ {
+ LLSDSerialize::toPrettyXML(config, file);
+ }
+ file.close();
+ }
+ static bool handleListenerTest()
+ {
+ control_group::mListenerFired = true;
+ return true;
+ }
+ };
+
+ bool control_group::mListenerFired = false;
+
+ typedef test_group<control_group> control_group_test;
+ typedef control_group_test::object control_group_t;
+ control_group_test tut_control_group("control_group");
+
+ //load settings from files - LLSD
+ template<> template<>
+ void control_group_t::test<1>()
+ {
+ int results = mCG->loadFromFile(mTestConfigFile.c_str());
+ ensure("number of settings", (results == 1));
+ ensure("value of setting", (mCG->getU32("TestSetting") == 12));
+ }
+
+ //save settings to files
+ template<> template<>
+ void control_group_t::test<2>()
+ {
+ int results = mCG->loadFromFile(mTestConfigFile.c_str());
+ mCG->setU32("TestSetting", 13);
+ ensure_equals("value of changed setting", mCG->getU32("TestSetting"), 13);
+ LLControlGroup test_cg("foo2");
+ std::string temp_test_file = (mTestConfigDir + "setting_llsd_temp.xml");
+ mCG->saveToFile(temp_test_file.c_str(), TRUE);
+ results = test_cg.loadFromFile(temp_test_file.c_str());
+ ensure("number of changed settings loaded", (results == 1));
+ ensure("value of changed settings loaded", (test_cg.getU32("TestSetting") == 13));
+ }
+
+ //priorities
+ template<> template<>
+ void control_group_t::test<3>()
+ {
+ int results = mCG->loadFromFile(mTestConfigFile.c_str());
+ LLControlVariable* control = mCG->getControl("TestSetting");
+ LLSD new_value = 13;
+ control->setValue(new_value, FALSE);
+ ensure_equals("value of changed setting", mCG->getU32("TestSetting"), 13);
+ LLControlGroup test_cg("foo3");
+ std::string temp_test_file = (mTestConfigDir + "setting_llsd_persist_temp.xml");
+ mCG->saveToFile(temp_test_file.c_str(), TRUE);
+ results = test_cg.loadFromFile(temp_test_file.c_str());
+ //If we haven't changed any settings, then we shouldn't have any settings to load
+ ensure("number of non-persisted changed settings loaded", (results == 0));
+ }
+
+ //listeners
+ template<> template<>
+ void control_group_t::test<4>()
+ {
+ int results = mCG->loadFromFile(mTestConfigFile.c_str());
+ ensure("number of settings", (results == 1));
+ mCG->getControl("TestSetting")->getSignal()->connect(boost::bind(&this->handleListenerTest));
+ mCG->setU32("TestSetting", 13);
+ ensure("listener fired on changed setting", mListenerFired);
+ }
+
+}
diff --git a/indra/llxuixml/CMakeLists.txt b/indra/llxuixml/CMakeLists.txt
new file mode 100644
index 0000000000..daed4de6ce
--- /dev/null
+++ b/indra/llxuixml/CMakeLists.txt
@@ -0,0 +1,45 @@
+# -*- cmake -*-
+
+project(llxuixml)
+
+include(00-Common)
+include(LLCommon)
+include(LLMath)
+include(LLXML)
+
+include_directories(
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LLMATH_INCLUDE_DIRS}
+ ${LLXML_INCLUDE_DIRS}
+ )
+
+set(llxuixml_SOURCE_FILES
+ llinitparam.cpp
+ lltrans.cpp
+ lluicolor.cpp
+ llxuiparser.cpp
+ )
+
+set(llxuixml_HEADER_FILES
+ CMakeLists.txt
+
+ llinitparam.h
+ lltrans.h
+ llregistry.h
+ lluicolor.h
+ llxuiparser.h
+ )
+
+set_source_files_properties(${llxuixml_HEADER_FILES}
+ PROPERTIES HEADER_FILE_ONLY TRUE)
+
+list(APPEND llxuixml_SOURCE_FILES ${llxuixml_HEADER_FILES})
+
+add_library (llxuixml ${llxuixml_SOURCE_FILES})
+# Libraries on which this library depends, needed for Linux builds
+# Sort by high-level to low-level
+target_link_libraries(llxuixml
+ llxml
+ llcommon
+ llmath
+ )
diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp
new file mode 100644
index 0000000000..4c050844f8
--- /dev/null
+++ b/indra/llxuixml/llinitparam.cpp
@@ -0,0 +1,505 @@
+/**
+ * @file llinitparam.cpp
+ * @brief parameter block abstraction for creating complex objects and
+ * parsing construction parameters from xml and LLSD
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llinitparam.h"
+
+
+namespace LLInitParam
+{
+ //
+ // Param
+ //
+ Param::Param(BaseBlock* enclosing_block)
+ : mIsProvided(false)
+ {
+ const U8* my_addr = reinterpret_cast<const U8*>(this);
+ const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
+ mEnclosingBlockOffset = (U16)(my_addr - block_addr);
+ }
+
+ //
+ // Parser
+ //
+ Parser::~Parser()
+ {}
+
+ void Parser::parserWarning(const std::string& message)
+ {
+ if (mParseSilently) return;
+ llwarns << message << llendl;
+ }
+
+ void Parser::parserError(const std::string& message)
+ {
+ if (mParseSilently) return;
+ llerrs << message << llendl;
+ }
+
+
+ //
+ // BlockDescriptor
+ //
+ void BlockDescriptor::aggregateBlockData(BlockDescriptor& src_block_data)
+ {
+ mNamedParams.insert(src_block_data.mNamedParams.begin(), src_block_data.mNamedParams.end());
+ mSynonyms.insert(src_block_data.mSynonyms.begin(), src_block_data.mSynonyms.end());
+ std::copy(src_block_data.mUnnamedParams.begin(), src_block_data.mUnnamedParams.end(), std::back_inserter(mUnnamedParams));
+ std::copy(src_block_data.mValidationList.begin(), src_block_data.mValidationList.end(), std::back_inserter(mValidationList));
+ std::copy(src_block_data.mAllParams.begin(), src_block_data.mAllParams.end(), std::back_inserter(mAllParams));
+ }
+
+ //
+ // BaseBlock
+ //
+ BaseBlock::BaseBlock()
+ : mLastChangedParam(0),
+ mChangeVersion(0)
+ {}
+
+ BaseBlock::~BaseBlock()
+ {}
+
+ // called by each derived class in least to most derived order
+ void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)
+ {
+ mBlockDescriptor = &descriptor;
+
+ descriptor.mCurrentBlockPtr = this;
+ descriptor.mMaxParamOffset = block_size;
+
+ switch(descriptor.mInitializationState)
+ {
+ case BlockDescriptor::UNINITIALIZED:
+ // copy params from base class here
+ descriptor.aggregateBlockData(base_descriptor);
+
+ descriptor.mInitializationState = BlockDescriptor::INITIALIZING;
+ break;
+ case BlockDescriptor::INITIALIZING:
+ descriptor.mInitializationState = BlockDescriptor::INITIALIZED;
+ break;
+ case BlockDescriptor::INITIALIZED:
+ // nothing to do
+ break;
+ }
+ }
+
+ param_handle_t BaseBlock::getHandleFromParam(const Param* param) const
+ {
+ const U8* param_address = reinterpret_cast<const U8*>(param);
+ const U8* baseblock_address = reinterpret_cast<const U8*>(this);
+ return (param_address - baseblock_address);
+ }
+
+ bool BaseBlock::submitValue(const Parser::name_stack_t& name_stack, Parser& p, bool silent)
+ {
+ if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end())))
+ {
+ if (!silent)
+ {
+ p.parserWarning(llformat("Failed to parse parameter \"%s\"", p.getCurrentElementName().c_str()));
+ }
+ return false;
+ }
+ return true;
+ }
+
+
+ bool BaseBlock::validateBlock(bool silent) const
+ {
+ const BlockDescriptor& block_data = getBlockDescriptor();
+ for (BlockDescriptor::param_validation_list_t::const_iterator it = block_data.mValidationList.begin(); it != block_data.mValidationList.end(); ++it)
+ {
+ const Param* param = getParamFromHandle(it->first);
+ if (!it->second(param))
+ {
+ if (!silent)
+ {
+ llwarns << "Invalid param \"" << getParamName(block_data, param) << "\"" << llendl;
+ }
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const
+ {
+ // named param is one like LLView::Params::follows
+ // unnamed param is like LLView::Params::rect - implicit
+ const BlockDescriptor& block_data = getBlockDescriptor();
+
+ for (BlockDescriptor::param_list_t::const_iterator it = block_data.mUnnamedParams.begin();
+ it != block_data.mUnnamedParams.end();
+ ++it)
+ {
+ param_handle_t param_handle = (*it)->mParamHandle;
+ const Param* param = getParamFromHandle(param_handle);
+ ParamDescriptor::serialize_func_t serialize_func = (*it)->mSerializeFunc;
+ if (serialize_func)
+ {
+ const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
+ // each param descriptor remembers its serial number
+ // so we can inspect the same param under different names
+ // and see that it has the same number
+ (*it)->mGeneration = parser.newParseGeneration();
+ name_stack.push_back(std::make_pair("", (*it)->mGeneration));
+ serialize_func(*param, parser, name_stack, diff_param);
+ name_stack.pop_back();
+ }
+ }
+
+ for(BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin();
+ it != block_data.mNamedParams.end();
+ ++it)
+ {
+ param_handle_t param_handle = it->second->mParamHandle;
+ const Param* param = getParamFromHandle(param_handle);
+ ParamDescriptor::serialize_func_t serialize_func = it->second->mSerializeFunc;
+ if (serialize_func)
+ {
+ // Ensure this param has not already been serialized
+ // Prevents <rect> from being serialized as its own tag.
+ bool duplicate = false;
+ for (BlockDescriptor::param_list_t::const_iterator it2 = block_data.mUnnamedParams.begin();
+ it2 != block_data.mUnnamedParams.end();
+ ++it2)
+ {
+ if (param_handle == (*it2)->mParamHandle)
+ {
+ duplicate = true;
+ break;
+ }
+ }
+
+ //FIXME: for now, don't attempt to serialize values under synonyms, as current parsers
+ // don't know how to detect them
+ if (duplicate)
+ {
+ continue;
+ }
+
+ if (!duplicate)
+ {
+ it->second->mGeneration = parser.newParseGeneration();
+ }
+
+ name_stack.push_back(std::make_pair(it->first, it->second->mGeneration));
+ const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
+ serialize_func(*param, parser, name_stack, diff_param);
+ name_stack.pop_back();
+ }
+ }
+
+ return true;
+ }
+
+ bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack) const
+ {
+ // named param is one like LLView::Params::follows
+ // unnamed param is like LLView::Params::rect - implicit
+ const BlockDescriptor& block_data = getBlockDescriptor();
+
+ for (BlockDescriptor::param_list_t::const_iterator it = block_data.mUnnamedParams.begin();
+ it != block_data.mUnnamedParams.end();
+ ++it)
+ {
+ param_handle_t param_handle = (*it)->mParamHandle;
+ const Param* param = getParamFromHandle(param_handle);
+ ParamDescriptor::inspect_func_t inspect_func = (*it)->mInspectFunc;
+ if (inspect_func)
+ {
+ (*it)->mGeneration = parser.newParseGeneration();
+ name_stack.push_back(std::make_pair("", (*it)->mGeneration));
+ inspect_func(*param, parser, name_stack, (*it)->mMinCount, (*it)->mMaxCount);
+ name_stack.pop_back();
+ }
+ }
+
+ for(BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin();
+ it != block_data.mNamedParams.end();
+ ++it)
+ {
+ param_handle_t param_handle = it->second->mParamHandle;
+ const Param* param = getParamFromHandle(param_handle);
+ ParamDescriptor::inspect_func_t inspect_func = it->second->mInspectFunc;
+ if (inspect_func)
+ {
+ // Ensure this param has not already been inspected
+ bool duplicate = false;
+ for (BlockDescriptor::param_list_t::const_iterator it2 = block_data.mUnnamedParams.begin();
+ it2 != block_data.mUnnamedParams.end();
+ ++it2)
+ {
+ if (param_handle == (*it2)->mParamHandle)
+ {
+ duplicate = true;
+ break;
+ }
+ }
+
+ if (!duplicate)
+ {
+ it->second->mGeneration = parser.newParseGeneration();
+ }
+ name_stack.push_back(std::make_pair(it->first, it->second->mGeneration));
+ inspect_func(*param, parser, name_stack, it->second->mMinCount, it->second->mMaxCount);
+ name_stack.pop_back();
+ }
+ }
+
+ for(BlockDescriptor::param_map_t::const_iterator it = block_data.mSynonyms.begin();
+ it != block_data.mSynonyms.end();
+ ++it)
+ {
+ param_handle_t param_handle = it->second->mParamHandle;
+ const Param* param = getParamFromHandle(param_handle);
+ ParamDescriptor::inspect_func_t inspect_func = it->second->mInspectFunc;
+ if (inspect_func)
+ {
+ // use existing serial number for param
+ name_stack.push_back(std::make_pair(it->first, it->second->mGeneration));
+ inspect_func(*param, parser, name_stack, it->second->mMinCount, it->second->mMaxCount);
+ name_stack.pop_back();
+ }
+ }
+
+ return true;
+ }
+
+ bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack)
+ {
+ BlockDescriptor& block_data = getBlockDescriptor();
+ bool names_left = name_stack.first != name_stack.second;
+
+ if (names_left)
+ {
+ const std::string& top_name = name_stack.first->first;
+
+ ParamDescriptor::deserialize_func_t deserialize_func = NULL;
+ Param* paramp = NULL;
+
+ BlockDescriptor::param_map_t::iterator found_it = block_data.mNamedParams.find(top_name);
+ if (found_it != block_data.mNamedParams.end())
+ {
+ // find pointer to member parameter from offset table
+ paramp = getParamFromHandle(found_it->second->mParamHandle);
+ deserialize_func = found_it->second->mDeserializeFunc;
+ }
+ else
+ {
+ BlockDescriptor::param_map_t::iterator found_it = block_data.mSynonyms.find(top_name);
+ if (found_it != block_data.mSynonyms.end())
+ {
+ // find pointer to member parameter from offset table
+ paramp = getParamFromHandle(found_it->second->mParamHandle);
+ deserialize_func = found_it->second->mDeserializeFunc;
+ }
+ }
+
+ Parser::name_stack_range_t new_name_stack(name_stack.first, name_stack.second);
+ ++new_name_stack.first;
+ if (deserialize_func)
+ {
+ return deserialize_func(*paramp, p, new_name_stack, name_stack.first == name_stack.second ? -1 : name_stack.first->second);
+ }
+ }
+
+ // try to parse unnamed parameters, in declaration order
+ for ( BlockDescriptor::param_list_t::iterator it = block_data.mUnnamedParams.begin();
+ it != block_data.mUnnamedParams.end();
+ ++it)
+ {
+ Param* paramp = getParamFromHandle((*it)->mParamHandle);
+ ParamDescriptor::deserialize_func_t deserialize_func = (*it)->mDeserializeFunc;
+
+ if (deserialize_func && deserialize_func(*paramp, p, name_stack, name_stack.first == name_stack.second ? -1 : name_stack.first->second))
+ {
+ mLastChangedParam = (*it)->mParamHandle;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ //static
+ void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptor& in_param, const char* char_name)
+ {
+ // create a copy of the paramdescriptor in allparams
+ // so other data structures can store a pointer to it
+ block_data.mAllParams.push_back(in_param);
+ ParamDescriptor& param(block_data.mAllParams.back());
+
+ std::string name(char_name);
+ if ((size_t)param.mParamHandle > block_data.mMaxParamOffset)
+ {
+ llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl;
+ }
+
+ if (name.empty())
+ {
+ block_data.mUnnamedParams.push_back(&param);
+ }
+ else
+ {
+ // don't use insert, since we want to overwrite existing entries
+ block_data.mNamedParams[name] = &param;
+ }
+
+ if (param.mValidationFunc)
+ {
+ block_data.mValidationList.push_back(std::make_pair(param.mParamHandle, param.mValidationFunc));
+ }
+ }
+
+ void BaseBlock::addSynonym(Param& param, const std::string& synonym)
+ {
+ BlockDescriptor& block_data = getBlockDescriptor();
+ if (block_data.mInitializationState == BlockDescriptor::INITIALIZING)
+ {
+ param_handle_t handle = getHandleFromParam(&param);
+
+ // check for invalid derivation from a paramblock (i.e. without using
+ // Block<T, Base_Class>
+ if ((size_t)handle > block_data.mMaxParamOffset)
+ {
+ llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl;
+ }
+
+ ParamDescriptor* param_descriptor = findParamDescriptor(handle);
+ if (param_descriptor)
+ {
+ if (synonym.empty())
+ {
+ block_data.mUnnamedParams.push_back(param_descriptor);
+ }
+ else
+ {
+ block_data.mSynonyms[synonym] = param_descriptor;
+ }
+ }
+ }
+ }
+
+ void BaseBlock::setLastChangedParam(const Param& last_param, bool user_provided)
+ {
+ mLastChangedParam = getHandleFromParam(&last_param);
+ mChangeVersion++;
+ }
+
+ const std::string& BaseBlock::getParamName(const BlockDescriptor& block_data, const Param* paramp) const
+ {
+ param_handle_t handle = getHandleFromParam(paramp);
+ for (BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin(); it != block_data.mNamedParams.end(); ++it)
+ {
+ if (it->second->mParamHandle == handle)
+ {
+ return it->first;
+ }
+ }
+
+ for (BlockDescriptor::param_map_t::const_iterator it = block_data.mSynonyms.begin(); it != block_data.mSynonyms.end(); ++it)
+ {
+ if (it->second->mParamHandle == handle)
+ {
+ return it->first;
+ }
+ }
+
+ return LLStringUtil::null;
+ }
+
+ ParamDescriptor* BaseBlock::findParamDescriptor(param_handle_t handle)
+ {
+ BlockDescriptor& descriptor = getBlockDescriptor();
+ BlockDescriptor::all_params_list_t::iterator end_it = descriptor.mAllParams.end();
+ for (BlockDescriptor::all_params_list_t::iterator it = descriptor.mAllParams.begin();
+ it != end_it;
+ ++it)
+ {
+ if (it->mParamHandle == handle) return &(*it);
+ }
+ return NULL;
+ }
+
+ // take all provided params from other and apply to self
+ // NOTE: this requires that "other" is of the same derived type as this
+ bool BaseBlock::overwriteFromImpl(BlockDescriptor& block_data, const BaseBlock& other)
+ {
+ bool param_changed = false;
+ BlockDescriptor::all_params_list_t::const_iterator end_it = block_data.mAllParams.end();
+ for (BlockDescriptor::all_params_list_t::const_iterator it = block_data.mAllParams.begin();
+ it != end_it;
+ ++it)
+ {
+ const Param* other_paramp = other.getParamFromHandle(it->mParamHandle);
+ ParamDescriptor::merge_func_t merge_func = it->mMergeFunc;
+ if (merge_func)
+ {
+ Param* paramp = getParamFromHandle(it->mParamHandle);
+ param_changed |= merge_func(*paramp, *other_paramp, true);
+ mLastChangedParam = it->mParamHandle;
+ }
+ }
+ return param_changed;
+ }
+
+ // take all provided params that are not already provided, and apply to self
+ bool BaseBlock::fillFromImpl(BlockDescriptor& block_data, const BaseBlock& other)
+ {
+ bool param_changed = false;
+ BlockDescriptor::all_params_list_t::const_iterator end_it = block_data.mAllParams.end();
+ for (BlockDescriptor::all_params_list_t::const_iterator it = block_data.mAllParams.begin();
+ it != end_it;
+ ++it)
+ {
+ const Param* other_paramp = other.getParamFromHandle(it->mParamHandle);
+ ParamDescriptor::merge_func_t merge_func = it->mMergeFunc;
+ if (merge_func)
+ {
+ Param* paramp = getParamFromHandle(it->mParamHandle);
+ param_changed |= merge_func(*paramp, *other_paramp, false);
+ mLastChangedParam = it->mParamHandle;
+ }
+ }
+ return param_changed;
+ }
+
+ bool ParamCompare<LLSD, false>::equals(const LLSD &a, const LLSD &b)
+ {
+ return false;
+ }
+}
diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h
new file mode 100644
index 0000000000..7e1e4a3d21
--- /dev/null
+++ b/indra/llxuixml/llinitparam.h
@@ -0,0 +1,1831 @@
+/**
+f * @file llinitparam.h
+ * @brief parameter block abstraction for creating complex objects and
+ * parsing construction parameters from xml and LLSD
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPARAM_H
+#define LL_LLPARAM_H
+
+#include <vector>
+
+#include <stddef.h>
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include "llregistry.h"
+#include "llmemory.h"
+
+
+namespace LLInitParam
+{
+
+ template <typename T, bool IS_BOOST_FUNCTION = boost::is_convertible<T, boost::function_base>::value >
+ struct ParamCompare
+ {
+ static bool equals(const T &a, const T &b)
+ {
+ return a == b;
+ }
+ };
+
+ // boost function types are not comparable
+ template<typename T>
+ struct ParamCompare<T, true>
+ {
+ static bool equals(const T&a, const T &b)
+ {
+ return false;
+ }
+ };
+
+ // default constructor adaptor for InitParam Values
+ // constructs default instances of the given type, returned by const reference
+ template <typename T>
+ struct DefaultInitializer
+ {
+ typedef const T& T_const_ref;
+ // return reference to a single default instance of T
+ // built-in types will be initialized to zero, default constructor otherwise
+ static T_const_ref get() { static T t = T(); return t; }
+ };
+
+ // helper functions and classes
+ typedef ptrdiff_t param_handle_t;
+
+ template <typename T>
+ class TypeValues
+ {
+ public:
+ // empty default implemenation of key cache
+ class KeyCache
+ {
+ public:
+ void setKey(const std::string& key) {}
+ std::string getKey() const { return ""; }
+ void clearKey(){}
+ };
+
+ static bool get(const std::string& name, T& value)
+ {
+ return false;
+ }
+
+ static bool empty()
+ {
+ return true;
+ }
+
+ static std::vector<std::string>* getPossibleValues() { return NULL; }
+ };
+
+ template <typename T, typename DERIVED_TYPE = TypeValues<T> >
+ class TypeValuesHelper
+ : public LLRegistrySingleton<std::string, T, DERIVED_TYPE >
+ {
+ typedef LLRegistrySingleton<std::string, T, DERIVED_TYPE> super_t;
+ typedef LLSingleton<DERIVED_TYPE> singleton_t;
+ public:
+
+ //TODO: cache key by index to save on param block size
+ class KeyCache
+ {
+ public:
+ void setKey(const std::string& key)
+ {
+ mKey = key;
+ }
+
+ void clearKey()
+ {
+ mKey = "";
+ }
+
+ std::string getKey() const
+ {
+ return mKey;
+ }
+
+ private:
+ std::string mKey;
+ };
+
+ static bool get(const std::string& name, T& value)
+ {
+ if (!singleton_t::instance().exists(name)) return false;
+
+ value = *singleton_t::instance().getValue(name);
+ return true;
+ }
+
+ static bool empty()
+ {
+ return singleton_t::instance().LLRegistry<std::string, T>::empty();
+ }
+
+ //override this to add name value pairs
+ static void declareValues() {}
+
+ void initSingleton()
+ {
+ DERIVED_TYPE::declareValues();
+ }
+
+ static const std::vector<std::string>* getPossibleValues()
+ {
+ // in order to return a pointer to a member, we lazily
+ // evaluate the result and store it in mValues here
+ if (singleton_t::instance().mValues.empty())
+ {
+ typename super_t::Registrar::registry_map_t::const_iterator it;
+ for (it = super_t::defaultRegistrar().beginItems(); it != super_t::defaultRegistrar().endItems(); ++it)
+ {
+ singleton_t::instance().mValues.push_back(it->first);
+ }
+ }
+ return &singleton_t::instance().mValues;
+ }
+
+
+ protected:
+ static void declare(const std::string& name, const T& value)
+ {
+ super_t::defaultRegistrar().add(name, value);
+ }
+
+ private:
+ std::vector<std::string> mValues;
+ };
+
+ class Parser
+ {
+ LOG_CLASS(Parser);
+
+ public:
+
+ struct CompareTypeID
+ {
+ bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
+ {
+ return lhs->before(*rhs);
+ }
+ };
+
+ typedef std::vector<std::pair<std::string, S32> > name_stack_t;
+ typedef std::pair<name_stack_t::const_iterator, name_stack_t::const_iterator> name_stack_range_t;
+ typedef std::vector<std::string> possible_values_t;
+
+ typedef boost::function<bool (void*)> parser_read_func_t;
+ typedef boost::function<bool (const void*, const name_stack_t&)> parser_write_func_t;
+ typedef boost::function<void (const name_stack_t&, S32, S32, const possible_values_t*)> parser_inspect_func_t;
+
+ typedef std::map<const std::type_info*, parser_read_func_t, CompareTypeID> parser_read_func_map_t;
+ typedef std::map<const std::type_info*, parser_write_func_t, CompareTypeID> parser_write_func_map_t;
+ typedef std::map<const std::type_info*, parser_inspect_func_t, CompareTypeID> parser_inspect_func_map_t;
+
+ Parser()
+ : mParseSilently(false),
+ mParseGeneration(0)
+ {}
+ virtual ~Parser();
+
+ template <typename T> bool readValue(T& param)
+ {
+ parser_read_func_map_t::iterator found_it = mParserReadFuncs.find(&typeid(T));
+ if (found_it != mParserReadFuncs.end())
+ {
+ return found_it->second((void*)&param);
+ }
+ return false;
+ }
+
+ template <typename T> bool writeValue(const T& param, const name_stack_t& name_stack)
+ {
+ parser_write_func_map_t::iterator found_it = mParserWriteFuncs.find(&typeid(T));
+ if (found_it != mParserWriteFuncs.end())
+ {
+ return found_it->second((const void*)&param, name_stack);
+ }
+ return false;
+ }
+
+ // dispatch inspection to registered inspection functions, for each parameter in a param block
+ template <typename T> bool inspectValue(const name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values)
+ {
+ parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs.find(&typeid(T));
+ if (found_it != mParserInspectFuncs.end())
+ {
+ found_it->second(name_stack, min_count, max_count, possible_values);
+ return true;
+ }
+ return false;
+ }
+
+ virtual std::string getCurrentElementName() = 0;
+ virtual void parserWarning(const std::string& message);
+ virtual void parserError(const std::string& message);
+ void setParseSilently(bool silent) { mParseSilently = silent; }
+ bool getParseSilently() { return mParseSilently; }
+
+ S32 getParseGeneration() { return mParseGeneration; }
+ S32 newParseGeneration() { return ++mParseGeneration; }
+
+
+ protected:
+ template <typename T>
+ void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func)
+ {
+ mParserReadFuncs.insert(std::make_pair(&typeid(T), read_func));
+ mParserWriteFuncs.insert(std::make_pair(&typeid(T), write_func));
+ }
+
+ template <typename T>
+ void registerInspectFunc(parser_inspect_func_t inspect_func)
+ {
+ mParserInspectFuncs.insert(std::make_pair(&typeid(T), inspect_func));
+ }
+
+ bool mParseSilently;
+
+ private:
+ parser_read_func_map_t mParserReadFuncs;
+ parser_write_func_map_t mParserWriteFuncs;
+ parser_inspect_func_map_t mParserInspectFuncs;
+ S32 mParseGeneration;
+ };
+
+ class BaseBlock;
+
+ class Param
+ {
+ public:
+ // public to allow choice blocks to clear provided flag on stale choices
+ void setProvided(bool is_provided) { mIsProvided = is_provided; }
+
+ protected:
+ bool getProvided() const { return mIsProvided; }
+
+ Param(class BaseBlock* enclosing_block);
+
+ // store pointer to enclosing block as offset to reduce space and allow for quick copying
+ BaseBlock& enclosingBlock() const
+ {
+ const U8* my_addr = reinterpret_cast<const U8*>(this);
+ // get address of enclosing BLOCK class using stored offset to enclosing BaseBlock class
+ return *const_cast<BaseBlock*>(
+ reinterpret_cast<const BaseBlock*>(my_addr - (ptrdiff_t)(S32)mEnclosingBlockOffset));
+ }
+
+ private:
+ friend class BaseBlock;
+
+ bool mIsProvided;
+ U16 mEnclosingBlockOffset;
+ };
+
+ // various callbacks and constraints associated with an individual param
+ struct ParamDescriptor
+ {
+ public:
+ typedef bool(*merge_func_t)(Param&, const Param&, bool);
+ typedef bool(*deserialize_func_t)(Param&, Parser&, const Parser::name_stack_range_t&, S32);
+ typedef void(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const Param* diff_param);
+ typedef void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32 min_count, S32 max_count);
+ typedef bool(*validation_func_t)(const Param*);
+
+ ParamDescriptor(param_handle_t p,
+ merge_func_t merge_func,
+ deserialize_func_t deserialize_func,
+ serialize_func_t serialize_func,
+ validation_func_t validation_func,
+ inspect_func_t inspect_func,
+ S32 min_count,
+ S32 max_count)
+ : mParamHandle(p),
+ mMergeFunc(merge_func),
+ mDeserializeFunc(deserialize_func),
+ mSerializeFunc(serialize_func),
+ mValidationFunc(validation_func),
+ mInspectFunc(inspect_func),
+ mMinCount(min_count),
+ mMaxCount(max_count),
+ mNumRefs(0)
+ {}
+
+ ParamDescriptor()
+ : mParamHandle(0),
+ mMergeFunc(NULL),
+ mDeserializeFunc(NULL),
+ mSerializeFunc(NULL),
+ mValidationFunc(NULL),
+ mInspectFunc(NULL),
+ mMinCount(0),
+ mMaxCount(0),
+ mGeneration(0),
+ mNumRefs(0)
+ {}
+
+ param_handle_t mParamHandle;
+
+ merge_func_t mMergeFunc;
+ deserialize_func_t mDeserializeFunc;
+ serialize_func_t mSerializeFunc;
+ inspect_func_t mInspectFunc;
+ validation_func_t mValidationFunc;
+ S32 mMinCount;
+ S32 mMaxCount;
+ S32 mGeneration;
+ S32 mNumRefs;
+ };
+
+ // each derived Block class keeps a static data structure maintaining offsets to various params
+ class BlockDescriptor
+ {
+ public:
+ BlockDescriptor()
+ : mMaxParamOffset(0),
+ mInitializationState(UNINITIALIZED)
+ {}
+
+ typedef enum e_initialization_state
+ {
+ UNINITIALIZED,
+ INITIALIZING,
+ INITIALIZED
+ } EInitializationState;
+
+ void aggregateBlockData(BlockDescriptor& src_block_data);
+
+ public:
+ typedef std::map<const std::string, ParamDescriptor*> param_map_t; // references param descriptors stored in mAllParams
+ typedef std::vector<ParamDescriptor*> param_list_t;
+
+ typedef std::list<ParamDescriptor> all_params_list_t;// references param descriptors stored in mAllParams
+ typedef std::vector<std::pair<param_handle_t, ParamDescriptor::validation_func_t> > param_validation_list_t;
+
+ param_map_t mNamedParams; // parameters with associated names
+ param_map_t mSynonyms; // parameters with alternate names
+ param_list_t mUnnamedParams; // parameters with_out_ associated names
+ param_validation_list_t mValidationList; // parameters that must be validated
+ all_params_list_t mAllParams; // all parameters, owns descriptors
+
+ size_t mMaxParamOffset;
+
+ EInitializationState mInitializationState; // whether or not static block data has been initialized
+ class BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed
+ };
+
+ class BaseBlock
+ {
+ public:
+ // "Multiple" constraint types
+ struct AnyAmount
+ {
+ static U32 minCount() { return 0; }
+ static U32 maxCount() { return U32_MAX; }
+ };
+
+ template<U32 MIN_AMOUNT>
+ struct AtLeast
+ {
+ static U32 minCount() { return MIN_AMOUNT; }
+ static U32 maxCount() { return U32_MAX; }
+ };
+
+ template<U32 MAX_AMOUNT>
+ struct AtMost
+ {
+ static U32 minCount() { return 0; }
+ static U32 maxCount() { return MAX_AMOUNT; }
+ };
+
+ template<U32 MIN_AMOUNT, U32 MAX_AMOUNT>
+ struct Between
+ {
+ static U32 minCount() { return MIN_AMOUNT; }
+ static U32 maxCount() { return MAX_AMOUNT; }
+ };
+
+ template<U32 EXACT_COUNT>
+ struct Exactly
+ {
+ static U32 minCount() { return EXACT_COUNT; }
+ static U32 maxCount() { return EXACT_COUNT; }
+ };
+
+ // this typedef identifies derived classes as being blocks
+ typedef void baseblock_base_class_t;
+ LOG_CLASS(BaseBlock);
+ friend class Param;
+
+ BaseBlock();
+ virtual ~BaseBlock();
+ bool submitValue(const Parser::name_stack_t& name_stack, Parser& p, bool silent=false);
+
+ param_handle_t getHandleFromParam(const Param* param) const;
+ bool validateBlock(bool silent = false) const;
+
+ Param* getParamFromHandle(const param_handle_t param_handle)
+ {
+ if (param_handle == 0) return NULL;
+ U8* baseblock_address = reinterpret_cast<U8*>(this);
+ return reinterpret_cast<Param*>(baseblock_address + param_handle);
+ }
+
+ const Param* getParamFromHandle(const param_handle_t param_handle) const
+ {
+ const U8* baseblock_address = reinterpret_cast<const U8*>(this);
+ return reinterpret_cast<const Param*>(baseblock_address + param_handle);
+ }
+
+ void addSynonym(Param& param, const std::string& synonym);
+
+ // Blocks can override this to do custom tracking of changes
+ virtual void setLastChangedParam(const Param& last_param, bool user_provided);
+
+ const Param* getLastChangedParam() const { return mLastChangedParam ? getParamFromHandle(mLastChangedParam) : NULL; }
+ S32 getLastChangeVersion() const { return mChangeVersion; }
+ bool isDefault() const { return mChangeVersion == 0; }
+
+ bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack);
+ bool serializeBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), const BaseBlock* diff_block = NULL) const;
+ virtual bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t()) const;
+
+ const BlockDescriptor& getBlockDescriptor() const { return *mBlockDescriptor; }
+ BlockDescriptor& getBlockDescriptor() { return *mBlockDescriptor; }
+
+ // take all provided params from other and apply to self
+ bool overwriteFrom(const BaseBlock& other)
+ {
+ return false;
+ }
+
+ // take all provided params that are not already provided, and apply to self
+ bool fillFrom(const BaseBlock& other)
+ {
+ return false;
+ }
+
+ static void addParam(BlockDescriptor& block_data, const ParamDescriptor& param, const char* name);
+ protected:
+ void init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size);
+
+
+ // take all provided params from other and apply to self
+ bool overwriteFromImpl(BlockDescriptor& block_data, const BaseBlock& other);
+
+ // take all provided params that are not already provided, and apply to self
+ bool fillFromImpl(BlockDescriptor& block_data, const BaseBlock& other);
+
+ // can be updated in getters
+ mutable param_handle_t mLastChangedParam;
+ mutable S32 mChangeVersion;
+
+ BlockDescriptor* mBlockDescriptor; // most derived block descriptor
+
+ static BlockDescriptor& blockDescriptor()
+ {
+ static BlockDescriptor sBlockDescriptor;
+ return sBlockDescriptor;
+ }
+
+ private:
+ const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const;
+ ParamDescriptor* findParamDescriptor(param_handle_t handle);
+ };
+
+
+ template<typename T>
+ struct ParamIterator
+ {
+ typedef typename std::vector<T>::const_iterator const_iterator;
+ typedef typename std::vector<T>::iterator iterator;
+ };
+
+ // these templates allow us to distinguish between template parameters
+ // that derive from BaseBlock and those that don't
+ // this is supposedly faster than boost::is_convertible and its ilk
+ template<typename T, typename Void = void>
+ struct IsBaseBlock
+ {
+ static const bool value = false;
+ };
+
+ template<typename T>
+ struct IsBaseBlock<T, typename T::baseblock_base_class_t>
+ {
+ static const bool value = true;
+ };
+
+ // specialize for custom parsing/decomposition of specific classes
+ // e.g. TypedParam<LLRect> has left, top, right, bottom, etc...
+ template<typename T,
+ typename NAME_VALUE_LOOKUP = TypeValues<T>,
+ bool HAS_MULTIPLE_VALUES = false,
+ bool VALUE_IS_BLOCK = IsBaseBlock<T>::value>
+ class TypedParam
+ : public Param
+ {
+ public:
+ typedef const T& value_const_ref_t;
+ typedef value_const_ref_t value_assignment_t;
+ typedef typename NAME_VALUE_LOOKUP::KeyCache key_cache_t;
+ typedef TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK> self_t;
+
+ TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
+ : Param(block_descriptor.mCurrentBlockPtr)
+ {
+ if (block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)
+ {
+ ParamDescriptor param_descriptor(block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
+ &mergeWith,
+ &deserializeParam,
+ &serializeParam,
+ validate_func,
+ &inspectParam,
+ min_count, max_count);
+ BaseBlock::addParam(block_descriptor, param_descriptor, name);
+ }
+
+ mData.mValue = value;
+ }
+
+ bool isProvided() const { return Param::getProvided(); }
+
+ static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation)
+ {
+ self_t& typed_param = static_cast<self_t&>(param);
+ // no further names in stack, attempt to parse value now
+ if (name_stack.first == name_stack.second)
+ {
+ if (parser.readValue<T>(typed_param.mData.mValue))
+ {
+ typed_param.setProvided(true);
+ typed_param.enclosingBlock().setLastChangedParam(param, true);
+ return true;
+ }
+
+ // try to parse a known named value
+ if(!NAME_VALUE_LOOKUP::empty())
+ {
+ // try to parse a known named value
+ std::string name;
+ if (parser.readValue<std::string>(name))
+ {
+ // try to parse a per type named value
+ if (NAME_VALUE_LOOKUP::get(name, typed_param.mData.mValue))
+ {
+ typed_param.mData.setKey(name);
+ typed_param.setProvided(true);
+ typed_param.enclosingBlock().setLastChangedParam(param, true);
+ return true;
+ }
+
+ }
+ }
+ }
+ return false;
+ }
+
+ static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+ {
+ const self_t& typed_param = static_cast<const self_t&>(param);
+ if (!typed_param.isProvided()) return;
+
+ if (!name_stack.empty())
+ {
+ name_stack.back().second = parser.newParseGeneration();
+ }
+
+ std::string key = typed_param.mData.getKey();
+
+ // first try to write out name of name/value pair
+
+ if (!key.empty())
+ {
+ if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->mData.getKey(), key))
+ {
+ if (!parser.writeValue<std::string>(key, name_stack))
+ {
+ return;
+ }
+ }
+ }
+ // then try to serialize value directly
+ else if (!diff_param || !ParamCompare<T>::equals(typed_param.get(), static_cast<const self_t*>(diff_param)->get())) {
+ if (!parser.writeValue<T>(typed_param.mData.mValue, name_stack))
+ {
+ return;
+ }
+ }
+ }
+
+ static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
+ {
+ // tell parser about our actual type
+ parser.inspectValue<T>(name_stack, min_count, max_count, NULL);
+ // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4)
+ if (NAME_VALUE_LOOKUP::getPossibleValues())
+ {
+ parser.inspectValue<std::string>(name_stack, min_count, max_count, NAME_VALUE_LOOKUP::getPossibleValues());
+ }
+ }
+
+ void set(value_assignment_t val, bool flag_as_provided = true)
+ {
+ mData.mValue = val;
+ mData.clearKey();
+ setProvided(flag_as_provided);
+ Param::enclosingBlock().setLastChangedParam(*this, flag_as_provided);
+ }
+
+ void setIfNotProvided(value_assignment_t val, bool flag_as_provided = true)
+ {
+ if (!isProvided())
+ {
+ set(val, flag_as_provided);
+ }
+ }
+
+ // implicit conversion
+ operator value_assignment_t() const { return get(); }
+ // explicit conversion
+ value_assignment_t operator()() const { return get(); }
+
+ protected:
+ value_assignment_t get() const
+ {
+ return mData.mValue;
+ }
+
+ static bool mergeWith(Param& dst, const Param& src, bool overwrite)
+ {
+ const self_t& src_typed_param = static_cast<const self_t&>(src);
+ self_t& dst_typed_param = static_cast<self_t&>(dst);
+ if (src_typed_param.isProvided()
+ && (overwrite || !dst_typed_param.isProvided()))
+ {
+ dst_typed_param.mData.clearKey();
+ dst_typed_param = src_typed_param;
+ return true;
+ }
+ return false;
+ }
+
+ struct Data : public key_cache_t
+ {
+ T mValue;
+ };
+
+ Data mData;
+ };
+
+ // parameter that is a block
+ template <typename T, typename NAME_VALUE_LOOKUP>
+ class TypedParam<T, NAME_VALUE_LOOKUP, false, true>
+ : public T,
+ public Param
+ {
+ public:
+ typedef const T value_const_t;
+ typedef T value_t;
+ typedef value_const_t& value_const_ref_t;
+ typedef value_const_ref_t value_assignment_t;
+ typedef typename NAME_VALUE_LOOKUP::KeyCache key_cache_t;
+ typedef TypedParam<T, NAME_VALUE_LOOKUP, false, true> self_t;
+
+ TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
+ : Param(block_descriptor.mCurrentBlockPtr),
+ T(value)
+ {
+ if (block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)
+ {
+ ParamDescriptor param_descriptor(block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
+ &mergeWith,
+ &deserializeParam,
+ &serializeParam,
+ validate_func,
+ &inspectParam,
+ min_count, max_count);
+ BaseBlock::addParam(block_descriptor, param_descriptor, name);
+ }
+ }
+
+ static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation)
+ {
+ self_t& typed_param = static_cast<self_t&>(param);
+ // attempt to parse block...
+ if(typed_param.deserializeBlock(parser, name_stack))
+ {
+ typed_param.enclosingBlock().setLastChangedParam(param, true);
+ return true;
+ }
+
+ if(!NAME_VALUE_LOOKUP::empty())
+ {
+ // try to parse a known named value
+ std::string name;
+ if (parser.readValue<std::string>(name))
+ {
+ // try to parse a per type named value
+ if (NAME_VALUE_LOOKUP::get(name, typed_param))
+ {
+ typed_param.enclosingBlock().setLastChangedParam(param, true);
+ typed_param.mData.setKey(name);
+ typed_param.mData.mKeyVersion = typed_param.getLastChangeVersion();
+ return true;
+ }
+
+ }
+ }
+ return false;
+ }
+
+ static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+ {
+ const self_t& typed_param = static_cast<const self_t&>(param);
+ if (!name_stack.empty())
+ {
+ name_stack.back().second = parser.newParseGeneration();
+ }
+
+ std::string key = typed_param.mData.getKey();
+ if (!key.empty() && typed_param.mData.mKeyVersion == typed_param.getLastChangeVersion())
+ {
+ if (!parser.writeValue<std::string>(key, name_stack))
+ {
+ return;
+ }
+ }
+ else
+ {
+ typed_param.serializeBlock(parser, name_stack, static_cast<const self_t*>(diff_param));
+ }
+ }
+
+ static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
+ {
+ // I am a param that is also a block, so just recurse into my contents
+ const self_t& typed_param = static_cast<const self_t&>(param);
+ typed_param.inspectBlock(parser, name_stack);
+ }
+
+ // a param-that-is-a-block is provided when the user has set one of its child params
+ // *and* the block as a whole validates
+ bool isProvided() const
+ {
+ // only validate block when it hasn't already passed validation and user has supplied *some* value
+ if (Param::getProvided() && mData.mValidatedVersion < T::getLastChangeVersion())
+ {
+ // a sub-block is "provided" when it has been filled in enough to be valid
+ mData.mValidated = T::validateBlock(true);
+ mData.mValidatedVersion = T::getLastChangeVersion();
+ }
+ return Param::getProvided() && mData.mValidated;
+ }
+
+ // assign block contents to this param-that-is-a-block
+ void set(value_assignment_t val, bool flag_as_provided = true)
+ {
+ value_t::operator=(val);
+ mData.clearKey();
+ // force revalidation of block by clearing known provided version
+ // next call to isProvided() will update provision status based on validity
+ mData.mValidatedVersion = 0;
+ setProvided(flag_as_provided);
+ Param::enclosingBlock().setLastChangedParam(*this, flag_as_provided);
+ }
+
+ void setIfNotProvided(value_assignment_t val, bool flag_as_provided = true)
+ {
+ if (!isProvided())
+ {
+ set(val, flag_as_provided);
+ }
+ }
+
+ // propagate changed status up to enclosing block
+ /*virtual*/ void setLastChangedParam(const Param& last_param, bool user_provided)
+ {
+ T::setLastChangedParam(last_param, user_provided);
+ Param::enclosingBlock().setLastChangedParam(*this, user_provided);
+ if (user_provided)
+ {
+ // a child param has been explicitly changed
+ // so *some* aspect of this block is now provided
+ setProvided(true);
+ }
+ }
+
+ // implicit conversion
+ operator value_assignment_t() const { return get(); }
+ // explicit conversion
+ value_assignment_t operator()() const { return get(); }
+
+ protected:
+ value_assignment_t get() const
+ {
+ return *this;
+ }
+
+ static bool mergeWith(Param& dst, const Param& src, bool overwrite)
+ {
+ const self_t& src_typed_param = static_cast<const self_t&>(src);
+ self_t& dst_typed_param = static_cast<self_t&>(dst);
+ if (overwrite)
+ {
+ if (dst_typed_param.T::overwriteFrom(src_typed_param))
+ {
+ dst_typed_param.mData.clearKey();
+ return true;
+ }
+ }
+ else
+ {
+ if (dst_typed_param.T::fillFrom(src_typed_param))
+ {
+ dst_typed_param.mData.clearKey();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ struct Data : public key_cache_t
+ {
+ S32 mKeyVersion;
+ mutable S32 mValidatedVersion;
+ mutable bool mValidated; // lazy validation flag
+
+ Data()
+ : mKeyVersion(0),
+ mValidatedVersion(0),
+ mValidated(false)
+ {}
+ };
+ Data mData;
+ };
+
+ // container of non-block parameters
+ template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP>
+ class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false>
+ : public Param
+ {
+ public:
+ typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false> self_t;
+ typedef typename std::vector<VALUE_TYPE> container_t;
+ typedef const container_t& value_assignment_t;
+
+ typedef VALUE_TYPE value_t;
+ typedef value_t& value_ref_t;
+ typedef const value_t& value_const_ref_t;
+
+ typedef typename NAME_VALUE_LOOKUP::KeyCache key_cache_t;
+
+ TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
+ : Param(block_descriptor.mCurrentBlockPtr),
+ mValues(value)
+ {
+ mCachedKeys.resize(mValues.size());
+ if (block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)
+ {
+ ParamDescriptor param_descriptor(block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
+ &mergeWith,
+ &deserializeParam,
+ &serializeParam,
+ validate_func,
+ &inspectParam,
+ min_count, max_count);
+ BaseBlock::addParam(block_descriptor, param_descriptor, name);
+ }
+ }
+
+ bool isProvided() const { return Param::getProvided(); }
+
+ static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation)
+ {
+ self_t& typed_param = static_cast<self_t&>(param);
+ value_t value;
+ // no further names in stack, attempt to parse value now
+ if (name_stack.first == name_stack.second)
+ {
+ // attempt to read value directly
+ if (parser.readValue<value_t>(value))
+ {
+ typed_param.mValues.push_back(value);
+ // save an empty name/value key as a placeholder
+ typed_param.mCachedKeys.push_back(key_cache_t());
+ typed_param.enclosingBlock().setLastChangedParam(param, true);
+ typed_param.setProvided(true);
+ return true;
+ }
+
+ // try to parse a known named value
+ if(!NAME_VALUE_LOOKUP::empty())
+ {
+ // try to parse a known named value
+ std::string name;
+ if (parser.readValue<std::string>(name))
+ {
+ // try to parse a per type named value
+ if (NAME_VALUE_LOOKUP::get(name, typed_param.mValues))
+ {
+ typed_param.mValues.push_back(value);
+ typed_param.mCachedKeys.push_back(key_cache_t());
+ typed_param.mCachedKeys.back().setKey(name);
+ typed_param.enclosingBlock().setLastChangedParam(param, true);
+ typed_param.setProvided(true);
+ return true;
+ }
+
+ }
+ }
+ }
+ return false;
+ }
+
+ static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+ {
+ const self_t& typed_param = static_cast<const self_t&>(param);
+ if (!typed_param.isProvided() || name_stack.empty()) return;
+
+ typename container_t::const_iterator it = typed_param.mValues.begin();
+ for (typename std::vector<key_cache_t>::const_iterator key_it = typed_param.mCachedKeys.begin();
+ it != typed_param.mValues.end();
+ ++key_it, ++it)
+ {
+ std::string key = key_it->get();
+ name_stack.back().second = parser.newParseGeneration();
+
+ if(!key.empty())
+ {
+ if(!parser.writeValue<std::string>(key, name_stack))
+ {
+ return;
+ }
+ }
+ // not parse via name values, write out value directly
+ else if (!parser.writeValue<VALUE_TYPE>(*it, name_stack))
+ {
+ return;
+ }
+ }
+ }
+
+ static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
+ {
+ parser.inspectValue<VALUE_TYPE>(name_stack, min_count, max_count, NULL);
+ if (NAME_VALUE_LOOKUP::getPossibleValues())
+ {
+ parser.inspectValue<std::string>(name_stack, min_count, max_count, NAME_VALUE_LOOKUP::getPossibleValues());
+ }
+ }
+
+ void set(value_assignment_t val, bool flag_as_provided = true)
+ {
+ mValues = val;
+ mCachedKeys.clear();
+ mCachedKeys.resize(mValues.size());
+ setProvided(flag_as_provided);
+ Param::enclosingBlock().setLastChangedParam(*this, flag_as_provided);
+ }
+
+
+ void setIfNotProvided(value_assignment_t val, bool flag_as_provided = true)
+ {
+ if (!isProvided())
+ {
+ set(val, flag_as_provided);
+ }
+ }
+
+ value_ref_t add()
+ {
+ mValues.push_back(value_t());
+ mCachedKeys.push_back(key_cache_t());
+ setProvided(true);
+ return mValues.back();
+ }
+
+ void add(value_const_ref_t item)
+ {
+ mValues.push_back(item);
+ mCachedKeys.push_back(key_cache_t());
+ setProvided(true);
+ }
+
+ // implicit conversion
+ operator value_assignment_t() const { return self_t::get(); }
+ // explicit conversion
+ value_assignment_t operator()() const { return get(); }
+
+ U32 numValidElements() const
+ {
+ return mValues.size();
+ }
+
+ protected:
+ value_assignment_t get() const
+ {
+ return mValues;
+ }
+
+ static bool mergeWith(Param& dst, const Param& src, bool overwrite)
+ {
+ const self_t& src_typed_param = static_cast<const self_t&>(src);
+ self_t& dst_typed_param = static_cast<self_t&>(dst);
+
+ if (src_typed_param.isProvided()
+ && (overwrite || !isProvided()))
+ {
+ dst_typed_param = src_typed_param;
+ return true;
+ }
+ return false;
+ }
+
+ container_t mValues;
+ std::vector<key_cache_t> mCachedKeys;
+ };
+
+ // container of block parameters
+ template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP>
+ class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true>
+ : public Param
+ {
+ public:
+ typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true> self_t;
+ typedef typename std::vector<VALUE_TYPE> container_t;
+ typedef const container_t& value_assignment_t;
+
+ typedef VALUE_TYPE value_t;
+ typedef value_t& value_ref_t;
+ typedef const value_t& value_const_ref_t;
+
+ typedef typename NAME_VALUE_LOOKUP::KeyCache key_cache_t;
+
+ TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
+ : Param(block_descriptor.mCurrentBlockPtr),
+ mValues(value),
+ mLastParamGeneration(0)
+ {
+ mCachedKeys.resize(mValues.size());
+ if (block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)
+ {
+ ParamDescriptor param_descriptor(block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
+ &mergeWith,
+ &deserializeParam,
+ &serializeParam,
+ validate_func,
+ &inspectParam,
+ min_count, max_count);
+ BaseBlock::addParam(block_descriptor, param_descriptor, name);
+ }
+ }
+
+ bool isProvided() const { return Param::getProvided(); }
+
+ value_ref_t operator[](S32 index) { return mValues[index]; }
+ value_const_ref_t operator[](S32 index) const { return mValues[index]; }
+
+ static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation)
+ {
+ self_t& typed_param = static_cast<self_t&>(param);
+ if (generation != typed_param.mLastParamGeneration || typed_param.mValues.empty())
+ {
+ typed_param.mValues.push_back(value_t());
+ typed_param.mCachedKeys.push_back(Data());
+ typed_param.enclosingBlock().setLastChangedParam(param, true);
+ typed_param.mLastParamGeneration = generation;
+ }
+
+ value_t& value = typed_param.mValues.back();
+
+ // attempt to parse block...
+ if(value.deserializeBlock(parser, name_stack))
+ {
+ typed_param.setProvided(true);
+ return true;
+ }
+
+ if(!NAME_VALUE_LOOKUP::empty())
+ {
+ // try to parse a known named value
+ std::string name;
+ if (parser.readValue<std::string>(name))
+ {
+ // try to parse a per type named value
+ if (NAME_VALUE_LOOKUP::get(name, value))
+ {
+ typed_param.mCachedKeys.back().setKey(name);
+ typed_param.mCachedKeys.back().mKeyVersion = value.getLastChangeVersion();
+ typed_param.enclosingBlock().setLastChangedParam(param, true);
+ typed_param.setProvided(true);
+ return true;
+ }
+
+ }
+ }
+
+ return false;
+ }
+
+ static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+ {
+ const self_t& typed_param = static_cast<const self_t&>(param);
+ if (!typed_param.isProvided() || name_stack.empty()) return;
+
+ typename container_t::const_iterator it = typed_param.mValues.begin();
+ for (typename std::vector<Data>::const_iterator key_it = typed_param.mCachedKeys.begin();
+ it != typed_param.mValues.end();
+ ++key_it, ++it)
+ {
+ name_stack.back().second = parser.newParseGeneration();
+
+ std::string key = key_it->getKey();
+ if (!key.empty() && key_it->mKeyVersion == it->getLastChangeVersion())
+ {
+ if(!parser.writeValue<std::string>(key, name_stack))
+ {
+ return;
+ }
+ }
+ // Not parsed via named values, write out value directly
+ // NOTE: currently we don't worry about removing default values in Multiple
+ else if (!it->serializeBlock(parser, name_stack, NULL))
+ {
+ return;
+ }
+ }
+ }
+
+ static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
+ {
+ // I am a vector of blocks, so describe my contents recursively
+ value_t().inspectBlock(parser, name_stack);
+ }
+
+ void set(value_assignment_t val, bool flag_as_provided = true)
+ {
+ mValues = val;
+ mCachedKeys.clear();
+ mCachedKeys.resize(mValues.size());
+ setProvided(flag_as_provided);
+ Param::enclosingBlock().setLastChangedParam(*this, flag_as_provided);
+ }
+
+ void setIfNotProvided(value_assignment_t val, bool flag_as_provided = true)
+ {
+ if (!isProvided())
+ {
+ set(val, flag_as_provided);
+ }
+ }
+
+ value_ref_t add()
+ {
+ mValues.push_back(value_t());
+ mCachedKeys.push_back(Data());
+ setProvided(true);
+ return mValues.back();
+ }
+
+ void add(value_const_ref_t item)
+ {
+ mValues.push_back(item);
+ mCachedKeys.push_back(Data());
+ setProvided(true);
+ }
+
+ // implicit conversion
+ operator value_assignment_t() const { return self_t::get(); }
+ // explicit conversion
+ value_assignment_t operator()() const { return get(); }
+
+ U32 numValidElements() const
+ {
+ U32 count = 0;
+ for (typename container_t::const_iterator it = mValues.begin();
+ it != mValues.end();
+ ++it)
+ {
+ if(it->validateBlock(true)) count++;
+ }
+ return count;
+ }
+
+ protected:
+ value_assignment_t get() const
+ {
+ return mValues;
+ }
+
+ static bool mergeWith(Param& dst, const Param& src, bool overwrite)
+ {
+ const self_t& src_typed_param = static_cast<const self_t&>(src);
+ self_t& dst_typed_param = static_cast<self_t&>(dst);
+
+ if (src_typed_param.isProvided()
+ && (overwrite || !dst_typed_param.isProvided()))
+ {
+ dst_typed_param = src_typed_param;
+ return true;
+ }
+ return false;
+ }
+
+ struct Data : public key_cache_t
+ {
+ S32 mKeyVersion; // version of block for which key was last valid
+
+ Data() : mKeyVersion(0) {}
+ };
+
+ container_t mValues;
+ std::vector<Data> mCachedKeys;
+
+ S32 mLastParamGeneration;
+ };
+
+ template <typename DERIVED_BLOCK>
+ class Choice : public BaseBlock
+ {
+ typedef Choice<DERIVED_BLOCK> self_t;
+ typedef Choice<DERIVED_BLOCK> enclosing_block_t;
+
+ LOG_CLASS(self_t);
+ public:
+ // take all provided params from other and apply to self
+ bool overwriteFrom(const self_t& other)
+ {
+ mCurChoice = other.mCurChoice;
+ return BaseBlock::overwriteFromImpl(blockDescriptor(), other);
+ }
+
+ // take all provided params that are not already provided, and apply to self
+ bool fillFrom(const self_t& other)
+ {
+ return false;
+ }
+
+ // clear out old choice when param has changed
+ /*virtual*/ void setLastChangedParam(const Param& last_param, bool user_provided)
+ {
+ param_handle_t changed_param_handle = BaseBlock::getHandleFromParam(&last_param);
+ // if we have a new choice...
+ if (changed_param_handle != mCurChoice)
+ {
+ // clear provided flag on previous choice
+ Param* previous_choice = BaseBlock::getParamFromHandle(mCurChoice);
+ if (previous_choice)
+ {
+ previous_choice->setProvided(false);
+ }
+ mCurChoice = changed_param_handle;
+ }
+ BaseBlock::setLastChangedParam(last_param, user_provided);
+ }
+
+ protected:
+ Choice()
+ : mCurChoice(0)
+ {
+ BaseBlock::init(blockDescriptor(), BaseBlock::blockDescriptor(), sizeof(DERIVED_BLOCK));
+ }
+
+ // Alternatives are mutually exclusive wrt other Alternatives in the same block.
+ // One alternative in a block will always have isChosen() == true.
+ // At most one alternative in a block will have isProvided() == true.
+ template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
+ class Alternative : public TypedParam<T, NAME_VALUE_LOOKUP, false>
+ {
+ public:
+ friend class Choice<DERIVED_BLOCK>;
+
+ typedef Alternative<T, NAME_VALUE_LOOKUP> self_t;
+ typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBaseBlock<T>::value> super_t;
+ typedef typename super_t::value_assignment_t value_assignment_t;
+
+ explicit Alternative(const char* name, value_assignment_t val = DefaultInitializer<T>::get())
+ : super_t(DERIVED_BLOCK::blockDescriptor(), name, val, NULL, 0, 1),
+ mOriginalValue(val)
+ {
+ // assign initial choice to first declared option
+ DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::blockDescriptor().mCurrentBlockPtr);
+ if (DERIVED_BLOCK::blockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING
+ && blockp->mCurChoice == 0)
+ {
+ blockp->mCurChoice = Param::enclosingBlock().getHandleFromParam(this);
+ }
+ }
+
+ Alternative& operator=(value_assignment_t val)
+ {
+ super_t::set(val);
+ return *this;
+ }
+
+ void operator()(typename super_t::value_assignment_t val)
+ {
+ super_t::set(val);
+ }
+
+ operator value_assignment_t() const
+ {
+ if (static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this)
+ {
+ return super_t::get();
+ }
+ return mOriginalValue;
+ }
+
+ value_assignment_t operator()() const
+ {
+ if (static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this)
+ {
+ return super_t::get();
+ }
+ return mOriginalValue;
+ }
+
+ bool isChosen() const
+ {
+ return static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this;
+ }
+
+ private:
+ T mOriginalValue;
+ };
+
+ protected:
+ static BlockDescriptor& blockDescriptor()
+ {
+ static BlockDescriptor sBlockDescriptor;
+ return sBlockDescriptor;
+ }
+
+ private:
+ param_handle_t mCurChoice;
+
+ const Param* getCurrentChoice() const
+ {
+ return BaseBlock::getParamFromHandle(mCurChoice);
+ }
+ };
+
+ template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock>
+ class Block
+ : public BASE_BLOCK
+ {
+ typedef Block<DERIVED_BLOCK, BASE_BLOCK> self_t;
+ typedef Block<DERIVED_BLOCK, BASE_BLOCK> block_t;
+
+ public:
+ typedef BASE_BLOCK base_block_t;
+
+ // take all provided params from other and apply to self
+ bool overwriteFrom(const self_t& other)
+ {
+ return BaseBlock::overwriteFromImpl(blockDescriptor(), other);
+ }
+
+ // take all provided params that are not already provided, and apply to self
+ bool fillFrom(const self_t& other)
+ {
+ return BaseBlock::fillFromImpl(blockDescriptor(), other);
+ }
+ protected:
+ Block()
+ {
+ //#pragma message("Parsing LLInitParam::Block")
+ BaseBlock::init(blockDescriptor(), BASE_BLOCK::blockDescriptor(), sizeof(DERIVED_BLOCK));
+ }
+
+ //
+ // Nested classes for declaring parameters
+ //
+ template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
+ class Optional : public TypedParam<T, NAME_VALUE_LOOKUP, false>
+ {
+ public:
+ typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBaseBlock<T>::value> super_t;
+ typedef typename super_t::value_assignment_t value_assignment_t;
+
+ explicit Optional(const char* name = "", value_assignment_t val = DefaultInitializer<T>::get())
+ : super_t(DERIVED_BLOCK::blockDescriptor(), name, val, NULL, 0, 1)
+ {
+ //#pragma message("Parsing LLInitParam::Block::Optional")
+ }
+
+ Optional& operator=(value_assignment_t val)
+ {
+ set(val);
+ return *this;
+ }
+
+ DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val)
+ {
+ super_t::set(val);
+ return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
+ }
+ using super_t::operator();
+ };
+
+ template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >
+ class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false>
+ {
+ public:
+ typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBaseBlock<T>::value> super_t;
+ typedef Mandatory<T, NAME_VALUE_LOOKUP> self_t;
+ typedef typename super_t::value_assignment_t value_assignment_t;
+
+ // mandatory parameters require a name to be parseable
+ explicit Mandatory(const char* name = "", value_assignment_t val = DefaultInitializer<T>::get())
+ : super_t(DERIVED_BLOCK::blockDescriptor(), name, val, &validate, 1, 1)
+ {}
+
+ Mandatory& operator=(value_assignment_t val)
+ {
+ set(val);
+ return *this;
+ }
+
+ DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val)
+ {
+ super_t::set(val);
+ return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
+ }
+ using super_t::operator();
+
+ static bool validate(const Param* p)
+ {
+ // valid only if provided
+ return static_cast<const self_t*>(p)->isProvided();
+ }
+
+ };
+
+ template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = TypeValues<T> >
+ class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true>
+ {
+ public:
+ typedef TypedParam<T, NAME_VALUE_LOOKUP, true, IsBaseBlock<T>::value> super_t;
+ typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP> self_t;
+ typedef typename super_t::container_t container_t;
+ typedef typename super_t::value_assignment_t value_assignment_t;
+ typedef typename container_t::iterator iterator;
+ typedef typename container_t::const_iterator const_iterator;
+
+ explicit Multiple(const char* name = "", value_assignment_t val = DefaultInitializer<container_t>::get())
+ : super_t(DERIVED_BLOCK::blockDescriptor(), name, val, &validate, RANGE::minCount(), RANGE::maxCount())
+ {}
+
+ using super_t::operator();
+
+ Multiple& operator=(value_assignment_t val)
+ {
+ set(val);
+ return *this;
+ }
+
+ DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val)
+ {
+ super_t::set(val);
+ return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());
+ }
+
+ static bool validate(const Param* paramp)
+ {
+ U32 num_valid = ((super_t*)paramp)->numValidElements();
+ return RANGE::minCount() <= num_valid && num_valid <= RANGE::maxCount();
+ }
+ };
+
+ class Deprecated : public Param
+ {
+ public:
+ explicit Deprecated(const char* name)
+ : Param(DERIVED_BLOCK::blockDescriptor().mCurrentBlockPtr)
+ {
+ BlockDescriptor& block_descriptor = DERIVED_BLOCK::blockDescriptor();
+ if (block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)
+ {
+ ParamDescriptor param_descriptor(block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
+ NULL,
+ &deserializeParam,
+ NULL,
+ NULL,
+ NULL,
+ 0, S32_MAX);
+ BaseBlock::addParam(block_descriptor, param_descriptor, name);
+ }
+ }
+
+ static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation)
+ {
+ if (name_stack.first == name_stack.second)
+ {
+ //std::string message = llformat("Deprecated value %s ignored", getName().c_str());
+ //parser.parserWarning(message);
+ return true;
+ }
+
+ return false;
+ }
+ };
+
+ typedef Deprecated Ignored;
+
+ protected:
+ static BlockDescriptor& blockDescriptor()
+ {
+ static BlockDescriptor sBlockDescriptor;
+ return sBlockDescriptor;
+ }
+ };
+
+ template<typename T, typename DERIVED = TypedParam<T> >
+ class BlockValue
+ : public Block<TypedParam<T, TypeValues<T>, false> >,
+ public Param
+ {
+ public:
+ typedef BlockValue<T> self_t;
+ typedef Block<TypedParam<T, TypeValues<T>, false> > block_t;
+ typedef const T& value_const_ref_t;
+ typedef value_const_ref_t value_assignment_t;
+ typedef typename TypeValues<T>::KeyCache key_cache_t;
+
+ BlockValue(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
+ : Param(block_descriptor.mCurrentBlockPtr),
+ mData(value)
+ {
+ if (block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)
+ {
+ ParamDescriptor param_descriptor(block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
+ &mergeWith,
+ &deserializeParam,
+ &serializeParam,
+ validate_func,
+ &inspectParam,
+ min_count, max_count);
+ BaseBlock::addParam(block_descriptor, param_descriptor, name);
+ }
+ }
+
+ // implicit conversion
+ operator value_assignment_t() const { return get(); }
+ // explicit conversion
+ value_assignment_t operator()() const { return get(); }
+
+ static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation)
+ {
+ self_t& typed_param = static_cast<self_t&>(param);
+ // type to apply parse direct value T
+ if (name_stack.first == name_stack.second)
+ {
+ if(parser.readValue<T>(typed_param.mData.mValue))
+ {
+ typed_param.enclosingBlock().setLastChangedParam(param, true);
+ typed_param.setProvided(true);
+ typed_param.mData.mLastParamVersion = typed_param.BaseBlock::getLastChangeVersion();
+ return true;
+ }
+
+ if(!TypeValues<T>::empty())
+ {
+ // try to parse a known named value
+ std::string name;
+ if (parser.readValue<std::string>(name))
+ {
+ // try to parse a per type named value
+ if (TypeValues<T>::get(name, typed_param.mData.mValue))
+ {
+ typed_param.mData.setKey(name);
+ typed_param.enclosingBlock().setLastChangedParam(param, true);
+ typed_param.setProvided(true);
+ typed_param.mData.mLastParamVersion = typed_param.BaseBlock::getLastChangeVersion();
+ return true;
+ }
+ }
+ }
+ }
+
+ // fall back on parsing block components for T
+ // if we deserialized at least one component...
+ if (typed_param.BaseBlock::deserializeBlock(parser, name_stack))
+ {
+ // ...our block is provided, and considered changed
+ typed_param.enclosingBlock().setLastChangedParam(param, true);
+ typed_param.setProvided(true);
+ return true;
+ }
+ return false;
+ }
+
+ static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+ {
+ const self_t& typed_param = static_cast<const self_t&>(param);
+
+ if (!typed_param.isProvided()) return;
+
+ std::string key = typed_param.mData.getKey();
+
+ // first try to write out name of name/value pair
+ if (!key.empty())
+ {
+ if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->mData.getKey(), key))
+ {
+ if (!parser.writeValue<std::string>(key, name_stack))
+ {
+ return;
+ }
+ }
+ }
+ // then try to serialize value directly
+ else if (!diff_param || !ParamCompare<T>::equals(typed_param.get(), (static_cast<const self_t*>(diff_param))->get()))
+ {
+
+ if (parser.writeValue<T>(typed_param.mData.mValue, name_stack))
+ {
+ return;
+ }
+
+ //RN: *always* serialize provided components of BlockValue (don't pass diff_param on),
+ // since these tend to be viewed as the constructor arguments for the value T. It seems
+ // cleaner to treat the uniqueness of a BlockValue according to the generated value, and
+ // not the individual components. This way <color red="0" green="1" blue="0"/> will not
+ // be exported as <color green="1"/>, since it was probably the intent of the user to
+ // be specific about the RGB color values. This also fixes an issue where we distinguish
+ // between rect.left not being provided and rect.left being explicitly set to 0 (same as default)
+ typed_param.BaseBlock::serializeBlock(parser, name_stack, NULL);
+ }
+ }
+
+ static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
+ {
+ // first, inspect with actual type...
+ parser.inspectValue<T>(name_stack, min_count, max_count, NULL);
+ if (TypeValues<T>::getPossibleValues())
+ {
+ //...then inspect with possible string values...
+ parser.inspectValue<std::string>(name_stack, min_count, max_count, TypeValues<T>::getPossibleValues());
+ }
+ // then recursively inspect contents...
+ const self_t& typed_param = static_cast<const self_t&>(param);
+ typed_param.inspectBlock(parser, name_stack);
+ }
+
+
+ bool isProvided() const
+ {
+ // either param value provided directly or block is sufficiently filled in
+ // if cached value is stale, regenerate from params
+ if (Param::getProvided() && mData.mLastParamVersion < BaseBlock::getLastChangeVersion())
+ {
+ if (block_t::validateBlock(true))
+ {
+ static_cast<const DERIVED*>(this)->setValueFromBlock();
+ // clear stale keyword associated with old value
+ mData.clearKey();
+ mData.mLastParamVersion = BaseBlock::getLastChangeVersion();
+ return true;
+ }
+ else
+ {
+ //block value incomplete, so not considered provided
+ // will attempt to revalidate on next call to isProvided()
+ return false;
+ }
+ }
+ // either no data provided, or we have a valid value in hand
+ return Param::getProvided();
+ }
+
+ void set(value_assignment_t val, bool flag_as_provided = true)
+ {
+ Param::enclosingBlock().setLastChangedParam(*this, flag_as_provided);
+ // set param version number to be up to date, so we ignore block contents
+ mData.mLastParamVersion = BaseBlock::getLastChangeVersion();
+
+ mData.mValue = val;
+ mData.clearKey();
+ setProvided(flag_as_provided);
+ static_cast<DERIVED*>(this)->setBlockFromValue();
+ }
+
+ void setIfNotProvided(value_assignment_t val, bool flag_as_provided = true)
+ {
+ // don't override any user provided value
+ if (!isProvided())
+ {
+ set(val, flag_as_provided);
+ }
+ }
+
+ // propagate change status up to enclosing block
+ /*virtual*/ void setLastChangedParam(const Param& last_param, bool user_provided)
+ {
+ BaseBlock::setLastChangedParam(last_param, user_provided);
+ Param::enclosingBlock().setLastChangedParam(*this, user_provided);
+ if (user_provided)
+ {
+ setProvided(true); // some component provided
+ }
+ }
+
+ protected:
+ value_assignment_t get() const
+ {
+ // if some parameters were provided, issue warnings on invalid blocks
+ if (Param::getProvided() && (mData.mLastParamVersion < BaseBlock::getLastChangeVersion()))
+ {
+ // go ahead and issue warnings at this point if any param is invalid
+ if(block_t::validateBlock(false))
+ {
+ static_cast<const DERIVED*>(this)->setValueFromBlock();
+ mData.clearKey();
+ mData.mLastParamVersion = BaseBlock::getLastChangeVersion();
+ }
+ }
+
+ return mData.mValue;
+ }
+
+ // mutable to allow lazy updates on get
+ struct Data : public key_cache_t
+ {
+ Data(const T& value)
+ : mValue(value),
+ mLastParamVersion(0)
+ {}
+
+ T mValue;
+ S32 mLastParamVersion;
+ };
+
+ mutable Data mData;
+
+ private:
+ static bool mergeWith(Param& dst, const Param& src, bool overwrite)
+ {
+ const self_t& src_param = static_cast<const self_t&>(src);
+ self_t& dst_typed_param = static_cast<self_t&>(dst);
+
+ if (src_param.isProvided()
+ && (overwrite || !dst_typed_param.isProvided()))
+ {
+ // assign individual parameters
+ if (overwrite)
+ {
+ dst_typed_param.BaseBlock::overwriteFromImpl(block_t::blockDescriptor(), src_param);
+ }
+ else
+ {
+ dst_typed_param.BaseBlock::fillFromImpl(block_t::blockDescriptor(), src_param);
+ }
+ // then copy actual value
+ dst_typed_param.mData.mValue = src_param.get();
+ dst_typed_param.mData.clearKey();
+ dst_typed_param.setProvided(true);
+ return true;
+ }
+ return false;
+ }
+ };
+
+ template<>
+ struct ParamCompare<LLSD, false>
+ {
+ static bool equals(const LLSD &a, const LLSD &b);
+ };
+}
+
+#endif // LL_LLPARAM_H
diff --git a/indra/llxuixml/llregistry.h b/indra/llxuixml/llregistry.h
new file mode 100644
index 0000000000..2c04d8c419
--- /dev/null
+++ b/indra/llxuixml/llregistry.h
@@ -0,0 +1,347 @@
+/**
+ * @file llregistry.h
+ * @brief template classes for registering name, value pairs in nested scopes, statically, etc.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLREGISTRY_H
+#define LL_LLREGISTRY_H
+
+#include <list>
+
+#include <boost/type_traits.hpp>
+#include "llsingleton.h"
+
+template <typename T>
+class LLRegistryDefaultComparator
+{
+ bool operator()(const T& lhs, const T& rhs) { return lhs < rhs; }
+};
+
+template <typename KEY, typename VALUE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
+class LLRegistry
+{
+public:
+ typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t;
+ typedef typename boost::add_reference<typename boost::add_const<KEY>::type>::type ref_const_key_t;
+ typedef typename boost::add_reference<typename boost::add_const<VALUE>::type>::type ref_const_value_t;
+ typedef typename boost::add_reference<VALUE>::type ref_value_t;
+ typedef typename boost::add_pointer<typename boost::add_const<VALUE>::type>::type ptr_const_value_t;
+ typedef typename boost::add_pointer<VALUE>::type ptr_value_t;
+
+ class Registrar
+ {
+ friend class LLRegistry<KEY, VALUE, COMPARATOR>;
+ public:
+ typedef typename std::map<KEY, VALUE> registry_map_t;
+
+ bool add(ref_const_key_t key, ref_const_value_t value)
+ {
+ if (mMap.insert(std::make_pair(key, value)).second == false)
+ {
+ llwarns << "Tried to register " << key << " but it was already registered!" << llendl;
+ return false;
+ }
+ return true;
+ }
+
+ void remove(ref_const_key_t key)
+ {
+ mMap.erase(key);
+ }
+
+ typename registry_map_t::const_iterator beginItems() const
+ {
+ return mMap.begin();
+ }
+
+ typename registry_map_t::const_iterator endItems() const
+ {
+ return mMap.end();
+ }
+
+ protected:
+ ptr_value_t getValue(ref_const_key_t key)
+ {
+ typename registry_map_t::iterator found_it = mMap.find(key);
+ if (found_it != mMap.end())
+ {
+ return &(found_it->second);
+ }
+ return NULL;
+ }
+
+ ptr_const_value_t getValue(ref_const_key_t key) const
+ {
+ typename registry_map_t::const_iterator found_it = mMap.find(key);
+ if (found_it != mMap.end())
+ {
+ return &(found_it->second);
+ }
+ return NULL;
+ }
+
+ // if the registry is used to store pointers, and null values are valid entries
+ // then use this function to check the existence of an entry
+ bool exists(ref_const_key_t key) const
+ {
+ return mMap.find(key) != mMap.end();
+ }
+
+ bool empty() const
+ {
+ return mMap.empty();
+ }
+
+ protected:
+ // use currentRegistrar() or defaultRegistrar()
+ Registrar() {}
+ ~Registrar() {}
+
+ private:
+ registry_map_t mMap;
+ };
+
+ typedef typename std::list<Registrar*> scope_list_t;
+ typedef typename std::list<Registrar*>::iterator scope_list_iterator_t;
+ typedef typename std::list<Registrar*>::const_iterator scope_list_const_iterator_t;
+
+ LLRegistry()
+ {}
+
+ ~LLRegistry() {}
+
+ ptr_value_t getValue(ref_const_key_t key)
+ {
+ for(scope_list_iterator_t it = mActiveScopes.begin();
+ it != mActiveScopes.end();
+ ++it)
+ {
+ ptr_value_t valuep = (*it)->getValue(key);
+ if (valuep != NULL) return valuep;
+ }
+ return mDefaultRegistrar.getValue(key);
+ }
+
+ ptr_const_value_t getValue(ref_const_key_t key) const
+ {
+ for(scope_list_const_iterator_t it = mActiveScopes.begin();
+ it != mActiveScopes.end();
+ ++it)
+ {
+ ptr_value_t valuep = (*it)->getValue(key);
+ if (valuep != NULL) return valuep;
+ }
+ return mDefaultRegistrar.getValue(key);
+ }
+
+ bool exists(ref_const_key_t key) const
+ {
+ for(scope_list_const_iterator_t it = mActiveScopes.begin();
+ it != mActiveScopes.end();
+ ++it)
+ {
+ if ((*it)->exists(key)) return true;
+ }
+
+ return mDefaultRegistrar.exists(key);
+ }
+
+ bool empty() const
+ {
+ for(scope_list_const_iterator_t it = mActiveScopes.begin();
+ it != mActiveScopes.end();
+ ++it)
+ {
+ if (!(*it)->empty()) return false;
+ }
+
+ return mDefaultRegistrar.empty();
+ }
+
+
+ Registrar& defaultRegistrar()
+ {
+ return mDefaultRegistrar;
+ }
+
+ const Registrar& defaultRegistrar() const
+ {
+ return mDefaultRegistrar;
+ }
+
+
+ Registrar& currentRegistrar()
+ {
+ if (!mActiveScopes.empty())
+ {
+ return *mActiveScopes.front();
+ }
+
+ return mDefaultRegistrar;
+ }
+
+ const Registrar& currentRegistrar() const
+ {
+ if (!mActiveScopes.empty())
+ {
+ return *mActiveScopes.front();
+ }
+
+ return mDefaultRegistrar;
+ }
+
+
+protected:
+ void addScope(Registrar* scope)
+ {
+ // newer scopes go up front
+ mActiveScopes.insert(mActiveScopes.begin(), scope);
+ }
+
+ void removeScope(Registrar* scope)
+ {
+ // O(N) but should be near the beggining and N should be small and this is safer than storing iterators
+ scope_list_iterator_t iter = std::find(mActiveScopes.begin(), mActiveScopes.end(), scope);
+ if (iter != mActiveScopes.end())
+ {
+ mActiveScopes.erase(iter);
+ }
+ }
+
+private:
+ scope_list_t mActiveScopes;
+ Registrar mDefaultRegistrar;
+};
+
+template <typename KEY, typename VALUE, typename DERIVED_TYPE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
+class LLRegistrySingleton
+ : public LLRegistry<KEY, VALUE, COMPARATOR>,
+ public LLSingleton<DERIVED_TYPE>
+{
+ friend class LLSingleton<DERIVED_TYPE>;
+public:
+ typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t;
+ typedef const KEY& ref_const_key_t;
+ typedef const VALUE& ref_const_value_t;
+ typedef VALUE* ptr_value_t;
+ typedef const VALUE* ptr_const_value_t;
+ typedef LLSingleton<DERIVED_TYPE> singleton_t;
+
+ class ScopedRegistrar : public registry_t::Registrar
+ {
+ public:
+ ScopedRegistrar(bool push_scope = true)
+ {
+ if (push_scope)
+ {
+ pushScope();
+ }
+ }
+
+ ~ScopedRegistrar()
+ {
+ if (!singleton_t::destroyed())
+ {
+ popScope();
+ }
+ }
+
+ void pushScope()
+ {
+ singleton_t::instance().addScope(this);
+ }
+
+ void popScope()
+ {
+ singleton_t::instance().removeScope(this);
+ }
+
+ ptr_value_t getValueFromScope(ref_const_key_t key)
+ {
+ return getValue(key);
+ }
+
+ ptr_const_value_t getValueFromScope(ref_const_key_t key) const
+ {
+ return getValue(key);
+ }
+
+ private:
+ typename std::list<typename registry_t::Registrar*>::iterator mListIt;
+ };
+
+ class StaticRegistrar : public registry_t::Registrar
+ {
+ public:
+ virtual ~StaticRegistrar() {}
+ StaticRegistrar(ref_const_key_t key, ref_const_value_t value)
+ {
+ singleton_t::instance().mStaticScope->add(key, value);
+ }
+ };
+
+ // convenience functions
+ typedef typename LLRegistry<KEY, VALUE, COMPARATOR>::Registrar& ref_registrar_t;
+ static ref_registrar_t currentRegistrar()
+ {
+ return singleton_t::instance().registry_t::currentRegistrar();
+ }
+
+ static ref_registrar_t defaultRegistrar()
+ {
+ return singleton_t::instance().registry_t::defaultRegistrar();
+ }
+
+ static ptr_value_t getValue(ref_const_key_t key)
+ {
+ return singleton_t::instance().registry_t::getValue(key);
+ }
+
+protected:
+ // DERIVED_TYPE needs to derive from LLRegistrySingleton
+ LLRegistrySingleton()
+ : mStaticScope(NULL)
+ {}
+
+ virtual void initSingleton()
+ {
+ mStaticScope = new ScopedRegistrar();
+ }
+
+ virtual ~LLRegistrySingleton()
+ {
+ delete mStaticScope;
+ }
+
+private:
+ ScopedRegistrar* mStaticScope;
+};
+
+#endif
diff --git a/indra/llxuixml/lltrans.cpp b/indra/llxuixml/lltrans.cpp
new file mode 100644
index 0000000000..d6f17dbb08
--- /dev/null
+++ b/indra/llxuixml/lltrans.cpp
@@ -0,0 +1,261 @@
+/**
+ * @file lltrans.cpp
+ * @brief LLTrans implementation
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltrans.h"
+
+#include "llfasttimer.h" // for call count statistics
+#include "llxuiparser.h"
+
+#include <map>
+
+LLTrans::template_map_t LLTrans::sStringTemplates;
+LLStringUtil::format_map_t LLTrans::sDefaultArgs;
+
+struct StringDef : public LLInitParam::Block<StringDef>
+{
+ Mandatory<std::string> name;
+ Mandatory<std::string> value;
+
+ StringDef()
+ : name("name"),
+ value("value")
+ {}
+};
+
+struct StringTable : public LLInitParam::Block<StringTable>
+{
+ Multiple<StringDef> strings;
+ StringTable()
+ : strings("string")
+ {}
+};
+
+//static
+bool LLTrans::parseStrings(LLXMLNodePtr &root, const std::set<std::string>& default_args)
+{
+ std::string xml_filename = "(strings file)";
+ if (!root->hasName("strings"))
+ {
+ llerrs << "Invalid root node name in " << xml_filename
+ << ": was " << root->getName() << ", expected \"strings\"" << llendl;
+ }
+
+ StringTable string_table;
+ LLXUIParser::instance().readXUI(root, string_table, xml_filename);
+
+ if (!string_table.validateBlock())
+ {
+ llerrs << "Problem reading strings: " << xml_filename << llendl;
+ return false;
+ }
+
+ sStringTemplates.clear();
+ sDefaultArgs.clear();
+
+ for(LLInitParam::ParamIterator<StringDef>::const_iterator it = string_table.strings().begin();
+ it != string_table.strings().end();
+ ++it)
+ {
+ LLTransTemplate xml_template(it->name, it->value);
+ sStringTemplates[xml_template.mName] = xml_template;
+
+ std::set<std::string>::const_iterator iter = default_args.find(xml_template.mName);
+ if (iter != default_args.end())
+ {
+ std::string name = *iter;
+ if (name[0] != '[')
+ name = llformat("[%s]",name.c_str());
+ sDefaultArgs[name] = xml_template.mText;
+ }
+ }
+
+ return true;
+}
+
+
+//static
+bool LLTrans::parseLanguageStrings(LLXMLNodePtr &root)
+{
+ std::string xml_filename = "(language strings file)";
+ if (!root->hasName("strings"))
+ {
+ llerrs << "Invalid root node name in " << xml_filename
+ << ": was " << root->getName() << ", expected \"strings\"" << llendl;
+ }
+
+ StringTable string_table;
+ LLXUIParser::instance().readXUI(root, string_table, xml_filename);
+
+ if (!string_table.validateBlock())
+ {
+ llerrs << "Problem reading strings: " << xml_filename << llendl;
+ return false;
+ }
+
+ for(LLInitParam::ParamIterator<StringDef>::const_iterator it = string_table.strings().begin();
+ it != string_table.strings().end();
+ ++it)
+ {
+ // share the same map with parseStrings() so we can search the strings using the same getString() function.- angela
+ LLTransTemplate xml_template(it->name, it->value);
+ sStringTemplates[xml_template.mName] = xml_template;
+ }
+
+ return true;
+}
+
+
+
+static LLFastTimer::DeclareTimer FTM_GET_TRANS("Translate string");
+
+//static
+std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& msg_args)
+{
+ // Don't care about time as much as call count. Make sure we're not
+ // calling LLTrans::getString() in an inner loop. JC
+ LLFastTimer timer(FTM_GET_TRANS);
+
+ template_map_t::iterator iter = sStringTemplates.find(xml_desc);
+ if (iter != sStringTemplates.end())
+ {
+ std::string text = iter->second.mText;
+ LLStringUtil::format_map_t args = sDefaultArgs;
+ args.insert(msg_args.begin(), msg_args.end());
+ LLStringUtil::format(text, args);
+
+ return text;
+ }
+ else
+ {
+ LLSD args;
+ args["STRING_NAME"] = xml_desc;
+ LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL;
+
+ //LLNotificationsUtil::add("MissingString", args); // *TODO: resurrect
+ //return xml_desc;
+
+ return "MissingString("+xml_desc+")";
+ }
+}
+
+//static
+bool LLTrans::findString(std::string &result, const std::string &xml_desc, const LLStringUtil::format_map_t& msg_args)
+{
+ LLFastTimer timer(FTM_GET_TRANS);
+
+ template_map_t::iterator iter = sStringTemplates.find(xml_desc);
+ if (iter != sStringTemplates.end())
+ {
+ std::string text = iter->second.mText;
+ LLStringUtil::format_map_t args = sDefaultArgs;
+ args.insert(msg_args.begin(), msg_args.end());
+ LLStringUtil::format(text, args);
+ result = text;
+ return true;
+ }
+ else
+ {
+ LLSD args;
+ args["STRING_NAME"] = xml_desc;
+ LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL;
+ //LLNotificationsUtil::add("MissingString", args);
+
+ return false;
+ }
+}
+
+//static
+std::string LLTrans::getCountString(const std::string& language, const std::string& xml_desc, S32 count)
+{
+ // Compute which string identifier to use
+ const char* form = "";
+ if (language == "ru") // Russian
+ {
+ // From GNU ngettext()
+ // Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;
+ if (count % 10 == 1
+ && count % 100 != 11)
+ {
+ // singular, "1 item"
+ form = "A";
+ }
+ else if (count % 10 >= 2
+ && count % 10 <= 4
+ && (count % 100 < 10 || count % 100 >= 20) )
+ {
+ // special case "2 items", "23 items", but not "13 items"
+ form = "B";
+ }
+ else
+ {
+ // English-style plural, "5 items"
+ form = "C";
+ }
+ }
+ else if (language == "fr" || language == "pt") // French, Brazilian Portuguese
+ {
+ // French and Portuguese treat zero as a singular "0 item" not "0 items"
+ if (count == 0 || count == 1)
+ {
+ form = "A";
+ }
+ else
+ {
+ // English-style plural
+ form = "B";
+ }
+ }
+ else // default
+ {
+ // languages like English with 2 forms, singular and plural
+ if (count == 1)
+ {
+ // "1 item"
+ form = "A";
+ }
+ else
+ {
+ // "2 items", also use plural for "0 items"
+ form = "B";
+ }
+ }
+
+ // Translate that string
+ LLStringUtil::format_map_t args;
+ args["[COUNT]"] = llformat("%d", count);
+
+ // Look up "AgeYearsB" or "AgeWeeksC" including the "form"
+ std::string key = llformat("%s%s", xml_desc.c_str(), form);
+ return getString(key, args);
+}
diff --git a/indra/llxuixml/lltrans.h b/indra/llxuixml/lltrans.h
new file mode 100644
index 0000000000..856b9e04fc
--- /dev/null
+++ b/indra/llxuixml/lltrans.h
@@ -0,0 +1,130 @@
+/**
+ * @file lltrans.h
+ * @brief LLTrans definition
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_TRANS_H
+#define LL_TRANS_H
+
+#include <map>
+
+#include "llstring.h"
+#include "llxmlnode.h"
+
+/**
+ * @brief String template loaded from strings.xml
+ */
+class LLTransTemplate
+{
+public:
+ LLTransTemplate(const std::string& name = LLStringUtil::null, const std::string& text = LLStringUtil::null) : mName(name), mText(text) {}
+
+ std::string mName;
+ std::string mText;
+};
+
+/**
+ * @brief Localized strings class
+ * This class is used to retrieve translations of strings used to build larger ones, as well as
+ * strings with a general usage that don't belong to any specific floater. For example,
+ * "Owner:", "Retrieving..." used in the place of a not yet known name, etc.
+ */
+class LLTrans
+{
+public:
+ LLTrans();
+
+ /**
+ * @brief Parses the xml root that holds the strings. Used once on startup
+// *FIXME * @param xml_filename Filename to parse
+ * @param default_args Set of strings (expected to be in the file) to use as default replacement args, e.g. "SECOND_LIFE"
+ * @returns true if the file was parsed successfully, true if something went wrong
+ */
+ static bool parseStrings(LLXMLNodePtr& root, const std::set<std::string>& default_args);
+
+ static bool parseLanguageStrings(LLXMLNodePtr &root);
+
+ /**
+ * @brief Returns a translated string
+ * @param xml_desc String's description
+ * @param args A list of substrings to replace in the string
+ * @returns Translated string
+ */
+ static std::string getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args);
+ static bool findString(std::string &result, const std::string &xml_desc, const LLStringUtil::format_map_t& args);
+
+ // Returns translated string with [COUNT] replaced with a number, following
+ // special per-language logic for plural nouns. For example, some languages
+ // may have different plurals for 0, 1, 2 and > 2.
+ // See "AgeWeeksA", "AgeWeeksB", etc. in strings.xml for examples.
+ static std::string getCountString(const std::string& language, const std::string& xml_desc, S32 count);
+
+ /**
+ * @brief Returns a translated string
+ * @param xml_desc String's description
+ * @returns Translated string
+ */
+ static std::string getString(const std::string &xml_desc)
+ {
+ LLStringUtil::format_map_t empty;
+ return getString(xml_desc, empty);
+ }
+
+ static bool findString(std::string &result, const std::string &xml_desc)
+ {
+ LLStringUtil::format_map_t empty;
+ return findString(result, xml_desc, empty);
+ }
+
+ static std::string getKeyboardString(const char* keystring)
+ {
+ // These map directly - no need to specialize
+ return getString( ll_safe_string(keystring) );
+ }
+
+ // get the default args
+ static const LLStringUtil::format_map_t& getDefaultArgs()
+ {
+ return sDefaultArgs;
+ }
+
+ // insert default args into an arg list
+ static void getArgs(LLStringUtil::format_map_t& args)
+ {
+ args.insert(sDefaultArgs.begin(), sDefaultArgs.end());
+ }
+
+private:
+ typedef std::map<std::string, LLTransTemplate > template_map_t;
+ static template_map_t sStringTemplates;
+ static LLStringUtil::format_map_t sDefaultArgs;
+};
+
+#endif
diff --git a/indra/llxuixml/lluicolor.cpp b/indra/llxuixml/lluicolor.cpp
new file mode 100644
index 0000000000..424d878a6b
--- /dev/null
+++ b/indra/llxuixml/lluicolor.cpp
@@ -0,0 +1,68 @@
+/**
+ * @file lluicolor.cpp
+ * @brief brief LLUIColor class implementation file
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lluicolor.h"
+
+LLUIColor::LLUIColor()
+ :mColorPtr(NULL)
+{
+}
+
+LLUIColor::LLUIColor(const LLColor4* color)
+ :mColorPtr(color)
+{
+}
+
+LLUIColor::LLUIColor(const LLColor4& color)
+ :mColor(color), mColorPtr(NULL)
+{
+}
+
+void LLUIColor::set(const LLColor4& color)
+{
+ mColor = color;
+ mColorPtr = NULL;
+}
+
+void LLUIColor::set(const LLColor4* color)
+{
+ mColorPtr = color;
+}
+
+const LLColor4& LLUIColor::get() const
+{
+ return (mColorPtr == NULL ? mColor : *mColorPtr);
+}
+
+LLUIColor::operator const LLColor4& () const
+{
+ return get();
+}
+
+const LLColor4& LLUIColor::operator()() const
+{
+ return get();
+}
+
+bool LLUIColor::isReference() const
+{
+ return mColorPtr != NULL;
+}
+
+namespace LLInitParam
+{
+ // used to detect equivalence with default values on export
+ bool ParamCompare<LLUIColor, false>::equals(const LLUIColor &a, const LLUIColor &b)
+ {
+ // do not detect value equivalence, treat pointers to colors as distinct from color values
+ return (a.mColorPtr == NULL && b.mColorPtr == NULL ? a.mColor == b.mColor : a.mColorPtr == b.mColorPtr);
+ }
+}
diff --git a/indra/llxuixml/lluicolor.h b/indra/llxuixml/lluicolor.h
new file mode 100644
index 0000000000..bb0f786326
--- /dev/null
+++ b/indra/llxuixml/lluicolor.h
@@ -0,0 +1,54 @@
+/**
+ * @file lluicolor.h
+ * @brief brief LLUIColor class header file
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLUICOLOR_H_
+#define LL_LLUICOLOR_H_
+
+#include "v4color.h"
+
+namespace LLInitParam
+{
+ template<typename T, bool>
+ struct ParamCompare;
+}
+
+class LLUIColor
+{
+public:
+ LLUIColor();
+ LLUIColor(const LLColor4* color);
+ LLUIColor(const LLColor4& color);
+
+ void set(const LLColor4& color);
+ void set(const LLColor4* color);
+
+ const LLColor4& get() const;
+
+ operator const LLColor4& () const;
+ const LLColor4& operator()() const;
+
+ bool isReference() const;
+
+private:
+ friend struct LLInitParam::ParamCompare<LLUIColor, false>;
+
+ const LLColor4* mColorPtr;
+ LLColor4 mColor;
+};
+
+namespace LLInitParam
+{
+ template<>
+ struct ParamCompare<LLUIColor, false>
+ {
+ static bool equals(const class LLUIColor& a, const class LLUIColor& b);
+ };
+}
+
+#endif
diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp
new file mode 100644
index 0000000000..17399865e5
--- /dev/null
+++ b/indra/llxuixml/llxuiparser.cpp
@@ -0,0 +1,970 @@
+/**
+ * @file llxuiparser.cpp
+ * @brief Utility functions for handling XUI structures in XML
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llxuiparser.h"
+
+#include "llxmlnode.h"
+#include <fstream>
+#include <boost/tokenizer.hpp>
+
+#include "lluicolor.h"
+
+const S32 MAX_STRING_ATTRIBUTE_SIZE = 40;
+
+//
+// LLXSDWriter
+//
+LLXSDWriter::LLXSDWriter()
+{
+ registerInspectFunc<bool>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:boolean", _1, _2, _3, _4));
+ registerInspectFunc<std::string>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
+ registerInspectFunc<U8>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedByte", _1, _2, _3, _4));
+ registerInspectFunc<S8>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:signedByte", _1, _2, _3, _4));
+ registerInspectFunc<U16>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedShort", _1, _2, _3, _4));
+ registerInspectFunc<S16>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:signedShort", _1, _2, _3, _4));
+ registerInspectFunc<U32>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:unsignedInt", _1, _2, _3, _4));
+ registerInspectFunc<S32>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:integer", _1, _2, _3, _4));
+ registerInspectFunc<F32>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:float", _1, _2, _3, _4));
+ registerInspectFunc<F64>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:double", _1, _2, _3, _4));
+ registerInspectFunc<LLColor4>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
+ registerInspectFunc<LLUIColor>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
+ registerInspectFunc<LLUUID>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
+ registerInspectFunc<LLSD>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
+}
+
+void LLXSDWriter::writeXSD(const std::string& type_name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace)
+{
+ mSchemaNode = node;
+ node->setName("xs:schema");
+ node->createChild("attributeFormDefault", true)->setStringValue("unqualified");
+ node->createChild("elementFormDefault", true)->setStringValue("qualified");
+ node->createChild("targetNamespace", true)->setStringValue(xml_namespace);
+ node->createChild("xmlns:xs", true)->setStringValue("http://www.w3.org/2001/XMLSchema");
+ node->createChild("xmlns", true)->setStringValue(xml_namespace);
+
+ node = node->createChild("xs:complexType", false);
+ node->createChild("name", true)->setStringValue(type_name);
+ node->createChild("mixed", true)->setStringValue("true");
+
+ mAttributeNode = node;
+ mElementNode = node->createChild("xs:choice", false);
+ mElementNode->createChild("minOccurs", true)->setStringValue("0");
+ mElementNode->createChild("maxOccurs", true)->setStringValue("unbounded");
+ block.inspectBlock(*this);
+
+ // duplicate element choices
+ LLXMLNodeList children;
+ mElementNode->getChildren("xs:element", children, FALSE);
+ for (LLXMLNodeList::iterator child_it = children.begin(); child_it != children.end(); ++child_it)
+ {
+ LLXMLNodePtr child_copy = child_it->second->deepCopy();
+ std::string child_name;
+ child_copy->getAttributeString("name", child_name);
+ child_copy->setAttributeString("name", type_name + "." + child_name);
+ mElementNode->addChild(child_copy);
+ }
+
+ LLXMLNodePtr element_declaration_node = mSchemaNode->createChild("xs:element", false);
+ element_declaration_node->createChild("name", true)->setStringValue(type_name);
+ element_declaration_node->createChild("type", true)->setStringValue(type_name);
+}
+
+void LLXSDWriter::writeAttribute(const std::string& type, const Parser::name_stack_t& stack, S32 min_count, S32 max_count, const std::vector<std::string>* possible_values)
+{
+ name_stack_t non_empty_names;
+ std::string attribute_name;
+ for (name_stack_t::const_iterator it = stack.begin();
+ it != stack.end();
+ ++it)
+ {
+ const std::string& name = it->first;
+ if (!name.empty())
+ {
+ non_empty_names.push_back(*it);
+ }
+ }
+
+ for (name_stack_t::const_iterator it = non_empty_names.begin();
+ it != non_empty_names.end();
+ ++it)
+ {
+ if (!attribute_name.empty())
+ {
+ attribute_name += ".";
+ }
+ attribute_name += it->first;
+ }
+
+ // only flag non-nested attributes as mandatory, nested attributes have variant syntax
+ // that can't be properly constrained in XSD
+ // e.g. <foo mandatory.value="bar"/> vs <foo><mandatory value="bar"/></foo>
+ bool attribute_mandatory = min_count == 1 && max_count == 1 && non_empty_names.size() == 1;
+
+ // don't bother supporting "Multiple" params as xml attributes
+ if (max_count <= 1)
+ {
+ // add compound attribute to root node
+ addAttributeToSchema(mAttributeNode, attribute_name, type, attribute_mandatory, possible_values);
+ }
+
+ // now generated nested elements for compound attributes
+ if (non_empty_names.size() > 1 && !attribute_mandatory)
+ {
+ std::string element_name;
+
+ // traverse all but last element, leaving that as an attribute name
+ name_stack_t::const_iterator end_it = non_empty_names.end();
+ end_it--;
+
+ for (name_stack_t::const_iterator it = non_empty_names.begin();
+ it != end_it;
+ ++it)
+ {
+ if (it != non_empty_names.begin())
+ {
+ element_name += ".";
+ }
+ element_name += it->first;
+ }
+
+ std::string short_attribute_name = non_empty_names.back().first;
+
+ LLXMLNodePtr complex_type_node;
+
+ // find existing element node here, starting at tail of child list
+ if (mElementNode->mChildren.notNull())
+ {
+ for(LLXMLNodePtr element = mElementNode->mChildren->tail;
+ element.notNull();
+ element = element->mPrev)
+ {
+ std::string name;
+ if(element->getAttributeString("name", name) && name == element_name)
+ {
+ complex_type_node = element->mChildren->head;
+ break;
+ }
+ }
+ }
+ //create complex_type node
+ //
+ //<xs:element
+ // maxOccurs="1"
+ // minOccurs="0"
+ // name="name">
+ // <xs:complexType>
+ // </xs:complexType>
+ //</xs:element>
+ if(complex_type_node.isNull())
+ {
+ complex_type_node = mElementNode->createChild("xs:element", false);
+
+ complex_type_node->createChild("minOccurs", true)->setIntValue(min_count);
+ complex_type_node->createChild("maxOccurs", true)->setIntValue(max_count);
+ complex_type_node->createChild("name", true)->setStringValue(element_name);
+ complex_type_node = complex_type_node->createChild("xs:complexType", false);
+ }
+
+ addAttributeToSchema(complex_type_node, short_attribute_name, type, false, possible_values);
+ }
+}
+
+void LLXSDWriter::addAttributeToSchema(LLXMLNodePtr type_declaration_node, const std::string& attribute_name, const std::string& type, bool mandatory, const std::vector<std::string>* possible_values)
+{
+ if (!attribute_name.empty())
+ {
+ LLXMLNodePtr new_enum_type_node;
+ if (possible_values != NULL)
+ {
+ // custom attribute type, for example
+ //<xs:simpleType>
+ // <xs:restriction
+ // base="xs:string">
+ // <xs:enumeration
+ // value="a" />
+ // <xs:enumeration
+ // value="b" />
+ // </xs:restriction>
+ // </xs:simpleType>
+ new_enum_type_node = new LLXMLNode("xs:simpleType", false);
+
+ LLXMLNodePtr restriction_node = new_enum_type_node->createChild("xs:restriction", false);
+ restriction_node->createChild("base", true)->setStringValue("xs:string");
+
+ for (std::vector<std::string>::const_iterator it = possible_values->begin();
+ it != possible_values->end();
+ ++it)
+ {
+ LLXMLNodePtr enum_node = restriction_node->createChild("xs:enumeration", false);
+ enum_node->createChild("value", true)->setStringValue(*it);
+ }
+ }
+
+ string_set_t& attributes_written = mAttributesWritten[type_declaration_node];
+
+ string_set_t::iterator found_it = attributes_written.lower_bound(attribute_name);
+
+ // attribute not yet declared
+ if (found_it == attributes_written.end() || attributes_written.key_comp()(attribute_name, *found_it))
+ {
+ attributes_written.insert(found_it, attribute_name);
+
+ LLXMLNodePtr attribute_node = type_declaration_node->createChild("xs:attribute", false);
+
+ // attribute name
+ attribute_node->createChild("name", true)->setStringValue(attribute_name);
+
+ if (new_enum_type_node.notNull())
+ {
+ attribute_node->addChild(new_enum_type_node);
+ }
+ else
+ {
+ // simple attribute type
+ attribute_node->createChild("type", true)->setStringValue(type);
+ }
+
+ // required or optional
+ attribute_node->createChild("use", true)->setStringValue(mandatory ? "required" : "optional");
+ }
+ // attribute exists...handle collision of same name attributes with potentially different types
+ else
+ {
+ LLXMLNodePtr attribute_declaration;
+ if (type_declaration_node.notNull())
+ {
+ for(LLXMLNodePtr node = type_declaration_node->mChildren->tail;
+ node.notNull();
+ node = node->mPrev)
+ {
+ std::string name;
+ if (node->getAttributeString("name", name) && name == attribute_name)
+ {
+ attribute_declaration = node;
+ break;
+ }
+ }
+ }
+
+ bool new_type_is_enum = new_enum_type_node.notNull();
+ bool existing_type_is_enum = !attribute_declaration->hasAttribute("type");
+
+ // either type is enum, revert to string in collision
+ // don't bother to check for enum equivalence
+ if (new_type_is_enum || existing_type_is_enum)
+ {
+ if (attribute_declaration->hasAttribute("type"))
+ {
+ attribute_declaration->setAttributeString("type", "xs:string");
+ }
+ else
+ {
+ attribute_declaration->createChild("type", true)->setStringValue("xs:string");
+ }
+ attribute_declaration->deleteChildren("xs:simpleType");
+ }
+ else
+ {
+ // check for collision of different standard types
+ std::string existing_type;
+ attribute_declaration->getAttributeString("type", existing_type);
+ // if current type is not the same as the new type, revert to strnig
+ if (existing_type != type)
+ {
+ // ...than use most general type, string
+ attribute_declaration->setAttributeString("type", "string");
+ }
+ }
+ }
+ }
+}
+
+//
+// LLXUIXSDWriter
+//
+void LLXUIXSDWriter::writeXSD(const std::string& type_name, const std::string& path, const LLInitParam::BaseBlock& block)
+{
+ std::string file_name(path);
+ file_name += type_name + ".xsd";
+ LLXMLNodePtr root_nodep = new LLXMLNode();
+
+ LLXSDWriter::writeXSD(type_name, root_nodep, block, "http://www.lindenlab.com/xui");
+
+ // add includes for all possible children
+ const std::type_info* type = *LLWidgetTypeRegistry::instance().getValue(type_name);
+ const widget_registry_t* widget_registryp = LLChildRegistryRegistry::instance().getValue(type);
+
+ // add include declarations for all valid children
+ for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems();
+ it != widget_registryp->currentRegistrar().endItems();
+ ++it)
+ {
+ std::string widget_name = it->first;
+ if (widget_name == type_name)
+ {
+ continue;
+ }
+ LLXMLNodePtr nodep = new LLXMLNode("xs:include", false);
+ nodep->createChild("schemaLocation", true)->setStringValue(widget_name + ".xsd");
+
+ // add to front of schema
+ mSchemaNode->addChild(nodep, mSchemaNode);
+ }
+
+ // add choices for valid children
+ if (widget_registryp)
+ {
+ for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems();
+ it != widget_registryp->currentRegistrar().endItems();
+ ++it)
+ {
+ std::string widget_name = it->first;
+ //<xs:element name="widget_name" type="widget_name">
+ LLXMLNodePtr widget_node = mElementNode->createChild("xs:element", false);
+ widget_node->createChild("name", true)->setStringValue(widget_name);
+ widget_node->createChild("type", true)->setStringValue(widget_name);
+ }
+ }
+
+ LLFILE* xsd_file = LLFile::fopen(file_name.c_str(), "w");
+ LLXMLNode::writeHeaderToFile(xsd_file);
+ root_nodep->writeToFile(xsd_file);
+ fclose(xsd_file);
+}
+
+//
+// LLXUIParser
+//
+LLXUIParser::LLXUIParser()
+: mLastWriteGeneration(-1),
+ mCurReadDepth(0)
+{
+ registerParserFuncs<bool>(boost::bind(&LLXUIParser::readBoolValue, this, _1),
+ boost::bind(&LLXUIParser::writeBoolValue, this, _1, _2));
+ registerParserFuncs<std::string>(boost::bind(&LLXUIParser::readStringValue, this, _1),
+ boost::bind(&LLXUIParser::writeStringValue, this, _1, _2));
+ registerParserFuncs<U8>(boost::bind(&LLXUIParser::readU8Value, this, _1),
+ boost::bind(&LLXUIParser::writeU8Value, this, _1, _2));
+ registerParserFuncs<S8>(boost::bind(&LLXUIParser::readS8Value, this, _1),
+ boost::bind(&LLXUIParser::writeS8Value, this, _1, _2));
+ registerParserFuncs<U16>(boost::bind(&LLXUIParser::readU16Value, this, _1),
+ boost::bind(&LLXUIParser::writeU16Value, this, _1, _2));
+ registerParserFuncs<S16>(boost::bind(&LLXUIParser::readS16Value, this, _1),
+ boost::bind(&LLXUIParser::writeS16Value, this, _1, _2));
+ registerParserFuncs<U32>(boost::bind(&LLXUIParser::readU32Value, this, _1),
+ boost::bind(&LLXUIParser::writeU32Value, this, _1, _2));
+ registerParserFuncs<S32>(boost::bind(&LLXUIParser::readS32Value, this, _1),
+ boost::bind(&LLXUIParser::writeS32Value, this, _1, _2));
+ registerParserFuncs<F32>(boost::bind(&LLXUIParser::readF32Value, this, _1),
+ boost::bind(&LLXUIParser::writeF32Value, this, _1, _2));
+ registerParserFuncs<F64>(boost::bind(&LLXUIParser::readF64Value, this, _1),
+ boost::bind(&LLXUIParser::writeF64Value, this, _1, _2));
+ registerParserFuncs<LLColor4>(boost::bind(&LLXUIParser::readColor4Value, this, _1),
+ boost::bind(&LLXUIParser::writeColor4Value, this, _1, _2));
+ registerParserFuncs<LLUIColor>(boost::bind(&LLXUIParser::readUIColorValue, this, _1),
+ boost::bind(&LLXUIParser::writeUIColorValue, this, _1, _2));
+ registerParserFuncs<LLUUID>(boost::bind(&LLXUIParser::readUUIDValue, this, _1),
+ boost::bind(&LLXUIParser::writeUUIDValue, this, _1, _2));
+ registerParserFuncs<LLSD>(boost::bind(&LLXUIParser::readSDValue, this, _1),
+ boost::bind(&LLXUIParser::writeSDValue, this, _1, _2));
+}
+
+static LLFastTimer::DeclareTimer FTM_PARSE_XUI("XUI Parsing");
+
+void LLXUIParser::readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, const std::string& filename, bool silent)
+{
+ LLFastTimer timer(FTM_PARSE_XUI);
+ mNameStack.clear();
+ mCurFileName = filename;
+ mCurReadDepth = 0;
+ setParseSilently(silent);
+
+ if (node.isNull())
+ {
+ parserWarning("Invalid node");
+ }
+ else
+ {
+ readXUIImpl(node, std::string(node->getName()->mString), block);
+ }
+}
+
+bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, const std::string& scope, LLInitParam::BaseBlock& block)
+{
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep(".");
+
+ bool values_parsed = false;
+
+ // submit attributes for current node
+ values_parsed |= readAttributes(nodep, block);
+
+ // treat text contents of xml node as "value" parameter
+ std::string text_contents = nodep->getSanitizedValue();
+ if (!text_contents.empty())
+ {
+ mCurReadNode = nodep;
+ mNameStack.push_back(std::make_pair(std::string("value"), newParseGeneration()));
+ // child nodes are not necessarily valid parameters (could be a child widget)
+ // so don't complain once we've recursed
+ bool silent = mCurReadDepth > 0;
+ if (!block.submitValue(mNameStack, *this, true))
+ {
+ mNameStack.pop_back();
+ block.submitValue(mNameStack, *this, silent);
+ }
+ else
+ {
+ mNameStack.pop_back();
+ }
+ }
+
+ // then traverse children
+ // child node must start with last name of parent node (our "scope")
+ // for example: "<button><button.param nested_param1="foo"><param.nested_param2 nested_param3="bar"/></button.param></button>"
+ // which equates to the following nesting:
+ // button
+ // param
+ // nested_param1
+ // nested_param2
+ // nested_param3
+ mCurReadDepth++;
+ for(LLXMLNodePtr childp = nodep->getFirstChild(); childp.notNull();)
+ {
+ std::string child_name(childp->getName()->mString);
+ S32 num_tokens_pushed = 0;
+
+ // for non "dotted" child nodes check to see if child node maps to another widget type
+ // and if not, treat as a child element of the current node
+ // e.g. <button><rect left="10"/></button> will interpret <rect> as "button.rect"
+ // since there is no widget named "rect"
+ if (child_name.find(".") == std::string::npos)
+ {
+ mNameStack.push_back(std::make_pair(child_name, newParseGeneration()));
+ num_tokens_pushed++;
+ }
+ else
+ {
+ // parse out "dotted" name into individual tokens
+ tokenizer name_tokens(child_name, sep);
+
+ tokenizer::iterator name_token_it = name_tokens.begin();
+ if(name_token_it == name_tokens.end())
+ {
+ childp = childp->getNextSibling();
+ continue;
+ }
+
+ // check for proper nesting
+ if(!scope.empty() && *name_token_it != scope)
+ {
+ childp = childp->getNextSibling();
+ continue;
+ }
+
+ // now ignore first token
+ ++name_token_it;
+
+ // copy remaining tokens on to our running token list
+ for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push)
+ {
+ mNameStack.push_back(std::make_pair(*token_to_push, newParseGeneration()));
+ num_tokens_pushed++;
+ }
+ }
+
+ // recurse and visit children XML nodes
+ if(readXUIImpl(childp, mNameStack.empty() ? scope : mNameStack.back().first, block))
+ {
+ // child node successfully parsed, remove from DOM
+
+ values_parsed = true;
+ LLXMLNodePtr node_to_remove = childp;
+ childp = childp->getNextSibling();
+
+ nodep->deleteChild(node_to_remove);
+ }
+ else
+ {
+ childp = childp->getNextSibling();
+ }
+
+ while(num_tokens_pushed-- > 0)
+ {
+ mNameStack.pop_back();
+ }
+ }
+ mCurReadDepth--;
+ return values_parsed;
+}
+
+bool LLXUIParser::readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block)
+{
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep(".");
+
+ bool any_parsed = false;
+
+ for(LLXMLAttribList::const_iterator attribute_it = nodep->mAttributes.begin();
+ attribute_it != nodep->mAttributes.end();
+ ++attribute_it)
+ {
+ S32 num_tokens_pushed = 0;
+ std::string attribute_name(attribute_it->first->mString);
+ mCurReadNode = attribute_it->second;
+
+ tokenizer name_tokens(attribute_name, sep);
+ // copy remaining tokens on to our running token list
+ for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push)
+ {
+ mNameStack.push_back(std::make_pair(*token_to_push, newParseGeneration()));
+ num_tokens_pushed++;
+ }
+
+ // child nodes are not necessarily valid attributes, so don't complain once we've recursed
+ bool silent = mCurReadDepth > 0;
+ any_parsed |= block.submitValue(mNameStack, *this, silent);
+
+ while(num_tokens_pushed-- > 0)
+ {
+ mNameStack.pop_back();
+ }
+ }
+
+ return any_parsed;
+}
+
+void LLXUIParser::writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock &block, const LLInitParam::BaseBlock* diff_block)
+{
+ mWriteRootNode = node;
+ block.serializeBlock(*this, Parser::name_stack_t(), diff_block);
+ mOutNodes.clear();
+}
+
+// go from a stack of names to a specific XML node
+LLXMLNodePtr LLXUIParser::getNode(const name_stack_t& stack)
+{
+ name_stack_t name_stack;
+ for (name_stack_t::const_iterator it = stack.begin();
+ it != stack.end();
+ ++it)
+ {
+ if (!it->first.empty())
+ {
+ name_stack.push_back(*it);
+ }
+ }
+
+ LLXMLNodePtr out_node = mWriteRootNode;
+
+ name_stack_t::const_iterator next_it = name_stack.begin();
+ for (name_stack_t::const_iterator it = name_stack.begin();
+ it != name_stack.end();
+ it = next_it)
+ {
+ ++next_it;
+ if (it->first.empty())
+ {
+ continue;
+ }
+
+ out_nodes_t::iterator found_it = mOutNodes.lower_bound(it->second);
+
+ // node with this name not yet written
+ if (found_it == mOutNodes.end() || mOutNodes.key_comp()(found_it->first, it->second))
+ {
+ // make an attribute if we are the last element on the name stack
+ bool is_attribute = next_it == name_stack.end();
+ LLXMLNodePtr new_node = new LLXMLNode(it->first.c_str(), is_attribute);
+ out_node->addChild(new_node);
+ mOutNodes.insert(found_it, std::make_pair(it->second, new_node));
+ out_node = new_node;
+ }
+ else
+ {
+ out_node = found_it->second;
+ }
+ }
+
+ return (out_node == mWriteRootNode ? LLXMLNodePtr(NULL) : out_node);
+}
+
+
+bool LLXUIParser::readBoolValue(void* val_ptr)
+{
+ S32 value;
+ bool success = mCurReadNode->getBoolValue(1, &value);
+ *((bool*)val_ptr) = (value != FALSE);
+ return success;
+}
+
+bool LLXUIParser::writeBoolValue(const void* val_ptr, const name_stack_t& stack)
+{
+ LLXMLNodePtr node = getNode(stack);
+ if (node.notNull())
+ {
+ node->setBoolValue(*((bool*)val_ptr));
+ return true;
+ }
+ return false;
+}
+
+bool LLXUIParser::readStringValue(void* val_ptr)
+{
+ *((std::string*)val_ptr) = mCurReadNode->getSanitizedValue();
+ return true;
+}
+
+bool LLXUIParser::writeStringValue(const void* val_ptr, const name_stack_t& stack)
+{
+ LLXMLNodePtr node = getNode(stack);
+ if (node.notNull())
+ {
+ const std::string* string_val = reinterpret_cast<const std::string*>(val_ptr);
+ if (string_val->find('\n') != std::string::npos
+ || string_val->size() > MAX_STRING_ATTRIBUTE_SIZE)
+ {
+ // don't write strings with newlines into attributes
+ std::string attribute_name = node->getName()->mString;
+ LLXMLNodePtr parent_node = node->mParent;
+ parent_node->deleteChild(node);
+ // write results in text contents of node
+ if (attribute_name == "value")
+ {
+ // "value" is implicit, just write to parent
+ node = parent_node;
+ }
+ else
+ {
+ // create a child that is not an attribute, but with same name
+ node = parent_node->createChild(attribute_name.c_str(), false);
+ }
+ }
+ node->setStringValue(*string_val);
+ return true;
+ }
+ return false;
+}
+
+bool LLXUIParser::readU8Value(void* val_ptr)
+{
+ return mCurReadNode->getByteValue(1, (U8*)val_ptr);
+}
+
+bool LLXUIParser::writeU8Value(const void* val_ptr, const name_stack_t& stack)
+{
+ LLXMLNodePtr node = getNode(stack);
+ if (node.notNull())
+ {
+ node->setUnsignedValue(*((U8*)val_ptr));
+ return true;
+ }
+ return false;
+}
+
+bool LLXUIParser::readS8Value(void* val_ptr)
+{
+ S32 value;
+ if(mCurReadNode->getIntValue(1, &value))
+ {
+ *((S8*)val_ptr) = value;
+ return true;
+ }
+ return false;
+}
+
+bool LLXUIParser::writeS8Value(const void* val_ptr, const name_stack_t& stack)
+{
+ LLXMLNodePtr node = getNode(stack);
+ if (node.notNull())
+ {
+ node->setIntValue(*((S8*)val_ptr));
+ return true;
+ }
+ return false;
+}
+
+bool LLXUIParser::readU16Value(void* val_ptr)
+{
+ U32 value;
+ if(mCurReadNode->getUnsignedValue(1, &value))
+ {
+ *((U16*)val_ptr) = value;
+ return true;
+ }
+ return false;
+}
+
+bool LLXUIParser::writeU16Value(const void* val_ptr, const name_stack_t& stack)
+{
+ LLXMLNodePtr node = getNode(stack);
+ if (node.notNull())
+ {
+ node->setUnsignedValue(*((U16*)val_ptr));
+ return true;
+ }
+ return false;
+}
+
+bool LLXUIParser::readS16Value(void* val_ptr)
+{
+ S32 value;
+ if(mCurReadNode->getIntValue(1, &value))
+ {
+ *((S16*)val_ptr) = value;
+ return true;
+ }
+ return false;
+}
+
+bool LLXUIParser::writeS16Value(const void* val_ptr, const name_stack_t& stack)
+{
+ LLXMLNodePtr node = getNode(stack);
+ if (node.notNull())
+ {
+ node->setIntValue(*((S16*)val_ptr));
+ return true;
+ }
+ return false;
+}
+
+bool LLXUIParser::readU32Value(void* val_ptr)
+{
+ return mCurReadNode->getUnsignedValue(1, (U32*)val_ptr);
+}
+
+bool LLXUIParser::writeU32Value(const void* val_ptr, const name_stack_t& stack)
+{
+ LLXMLNodePtr node = getNode(stack);
+ if (node.notNull())
+ {
+ node->setUnsignedValue(*((U32*)val_ptr));
+ return true;
+ }
+ return false;
+}
+
+bool LLXUIParser::readS32Value(void* val_ptr)
+{
+ return mCurReadNode->getIntValue(1, (S32*)val_ptr);
+}
+
+bool LLXUIParser::writeS32Value(const void* val_ptr, const name_stack_t& stack)
+{
+ LLXMLNodePtr node = getNode(stack);
+ if (node.notNull())
+ {
+ node->setIntValue(*((S32*)val_ptr));
+ return true;
+ }
+ return false;
+}
+
+bool LLXUIParser::readF32Value(void* val_ptr)
+{
+ return mCurReadNode->getFloatValue(1, (F32*)val_ptr);
+}
+
+bool LLXUIParser::writeF32Value(const void* val_ptr, const name_stack_t& stack)
+{
+ LLXMLNodePtr node = getNode(stack);
+ if (node.notNull())
+ {
+ node->setFloatValue(*((F32*)val_ptr));
+ return true;
+ }
+ return false;
+}
+
+bool LLXUIParser::readF64Value(void* val_ptr)
+{
+ return mCurReadNode->getDoubleValue(1, (F64*)val_ptr);
+}
+
+bool LLXUIParser::writeF64Value(const void* val_ptr, const name_stack_t& stack)
+{
+ LLXMLNodePtr node = getNode(stack);
+ if (node.notNull())
+ {
+ node->setDoubleValue(*((F64*)val_ptr));
+ return true;
+ }
+ return false;
+}
+
+bool LLXUIParser::readColor4Value(void* val_ptr)
+{
+ LLColor4* colorp = (LLColor4*)val_ptr;
+ if(mCurReadNode->getFloatValue(4, colorp->mV) >= 3)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+bool LLXUIParser::writeColor4Value(const void* val_ptr, const name_stack_t& stack)
+{
+ LLXMLNodePtr node = getNode(stack);
+ if (node.notNull())
+ {
+ LLColor4 color = *((LLColor4*)val_ptr);
+ node->setFloatValue(4, color.mV);
+ return true;
+ }
+ return false;
+}
+
+bool LLXUIParser::readUIColorValue(void* val_ptr)
+{
+ LLUIColor* param = (LLUIColor*)val_ptr;
+ LLColor4 color;
+ bool success = mCurReadNode->getFloatValue(4, color.mV) >= 3;
+ if (success)
+ {
+ param->set(color);
+ return true;
+ }
+ return false;
+}
+
+bool LLXUIParser::writeUIColorValue(const void* val_ptr, const name_stack_t& stack)
+{
+ LLXMLNodePtr node = getNode(stack);
+ if (node.notNull())
+ {
+ LLUIColor color = *((LLUIColor*)val_ptr);
+ //RN: don't write out the color that is represented by a function
+ // rely on param block exporting to get the reference to the color settings
+ if (color.isReference()) return false;
+ node->setFloatValue(4, color.get().mV);
+ return true;
+ }
+ return false;
+}
+
+bool LLXUIParser::readUUIDValue(void* val_ptr)
+{
+ LLUUID temp_id;
+ // LLUUID::set is destructive, so use temporary value
+ if (temp_id.set(mCurReadNode->getSanitizedValue()))
+ {
+ *(LLUUID*)(val_ptr) = temp_id;
+ return true;
+ }
+ return false;
+}
+
+bool LLXUIParser::writeUUIDValue(const void* val_ptr, const name_stack_t& stack)
+{
+ LLXMLNodePtr node = getNode(stack);
+ if (node.notNull())
+ {
+ node->setStringValue(((LLUUID*)val_ptr)->asString());
+ return true;
+ }
+ return false;
+}
+
+bool LLXUIParser::readSDValue(void* val_ptr)
+{
+ *((LLSD*)val_ptr) = LLSD(mCurReadNode->getSanitizedValue());
+ return true;
+}
+
+bool LLXUIParser::writeSDValue(const void* val_ptr, const name_stack_t& stack)
+{
+ LLXMLNodePtr node = getNode(stack);
+ if (node.notNull())
+ {
+ std::string string_val = ((LLSD*)val_ptr)->asString();
+ if (string_val.find('\n') != std::string::npos || string_val.size() > MAX_STRING_ATTRIBUTE_SIZE)
+ {
+ // don't write strings with newlines into attributes
+ std::string attribute_name = node->getName()->mString;
+ LLXMLNodePtr parent_node = node->mParent;
+ parent_node->deleteChild(node);
+ // write results in text contents of node
+ if (attribute_name == "value")
+ {
+ // "value" is implicit, just write to parent
+ node = parent_node;
+ }
+ else
+ {
+ node = parent_node->createChild(attribute_name.c_str(), false);
+ }
+ }
+
+ node->setStringValue(string_val);
+ return true;
+ }
+ return false;
+}
+
+/*virtual*/ std::string LLXUIParser::getCurrentElementName()
+{
+ std::string full_name;
+ for (name_stack_t::iterator it = mNameStack.begin();
+ it != mNameStack.end();
+ ++it)
+ {
+ full_name += it->first + "."; // build up dotted names: "button.param.nestedparam."
+ }
+
+ return full_name;
+}
+
+void LLXUIParser::parserWarning(const std::string& message)
+{
+#ifdef LL_WINDOWS
+ // use Visual Studo friendly formatting of output message for easy access to originating xml
+ llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str());
+ utf16str += '\n';
+ OutputDebugString(utf16str.c_str());
+#else
+ Parser::parserWarning(message);
+#endif
+}
+
+void LLXUIParser::parserError(const std::string& message)
+{
+#ifdef LL_WINDOWS
+ llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", mCurFileName.c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str());
+ utf16str += '\n';
+ OutputDebugString(utf16str.c_str());
+#else
+ Parser::parserError(message);
+#endif
+}
diff --git a/indra/llxuixml/llxuiparser.h b/indra/llxuixml/llxuiparser.h
new file mode 100644
index 0000000000..884f4f7578
--- /dev/null
+++ b/indra/llxuixml/llxuiparser.h
@@ -0,0 +1,177 @@
+/**
+ * @file llxuiparser.h
+ * @brief Utility functions for handling XUI structures in XML
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLXUIPARSER_H
+#define LLXUIPARSER_H
+
+#include "llinitparam.h"
+#include "llfasttimer.h"
+#include "llregistry.h"
+#include "llpointer.h"
+
+#include <boost/function.hpp>
+#include <iosfwd>
+#include <stack>
+#include <set>
+
+
+
+class LLView;
+
+
+typedef LLPointer<class LLXMLNode> LLXMLNodePtr;
+
+
+// lookup widget type by name
+class LLWidgetTypeRegistry
+: public LLRegistrySingleton<std::string, const std::type_info*, LLWidgetTypeRegistry>
+{};
+
+
+// global static instance for registering all widget types
+typedef boost::function<LLView* (LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)> LLWidgetCreatorFunc;
+
+typedef LLRegistry<std::string, LLWidgetCreatorFunc> widget_registry_t;
+
+class LLChildRegistryRegistry
+: public LLRegistrySingleton<const std::type_info*, widget_registry_t, LLChildRegistryRegistry>
+{};
+
+
+
+class LLXSDWriter : public LLInitParam::Parser
+{
+ LOG_CLASS(LLXSDWriter);
+public:
+ void writeXSD(const std::string& name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace);
+
+ /*virtual*/ std::string getCurrentElementName() { return LLStringUtil::null; }
+
+ LLXSDWriter();
+
+protected:
+ void writeAttribute(const std::string& type, const Parser::name_stack_t&, S32 min_count, S32 max_count, const std::vector<std::string>* possible_values);
+ void addAttributeToSchema(LLXMLNodePtr nodep, const std::string& attribute_name, const std::string& type, bool mandatory, const std::vector<std::string>* possible_values);
+ LLXMLNodePtr mAttributeNode;
+ LLXMLNodePtr mElementNode;
+ LLXMLNodePtr mSchemaNode;
+
+ typedef std::set<std::string> string_set_t;
+ typedef std::map<LLXMLNodePtr, string_set_t> attributes_map_t;
+ attributes_map_t mAttributesWritten;
+};
+
+
+
+// NOTE: DOES NOT WORK YET
+// should support child widgets for XUI
+class LLXUIXSDWriter : public LLXSDWriter
+{
+public:
+ void writeXSD(const std::string& name, const std::string& path, const LLInitParam::BaseBlock& block);
+};
+
+
+
+class LLXUIParser : public LLInitParam::Parser, public LLSingleton<LLXUIParser>
+{
+LOG_CLASS(LLXUIParser);
+
+protected:
+ LLXUIParser();
+ friend class LLSingleton<LLXUIParser>;
+public:
+ typedef LLInitParam::Parser::name_stack_t name_stack_t;
+
+ /*virtual*/ std::string getCurrentElementName();
+ /*virtual*/ void parserWarning(const std::string& message);
+ /*virtual*/ void parserError(const std::string& message);
+
+ void readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, const std::string& filename = LLStringUtil::null, bool silent=false);
+ void writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const LLInitParam::BaseBlock* diff_block = NULL);
+
+private:
+ typedef std::list<std::pair<std::string, bool> > token_list_t;
+
+ bool readXUIImpl(LLXMLNodePtr node, const std::string& scope, LLInitParam::BaseBlock& block);
+ bool readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block);
+
+ //reader helper functions
+ bool readBoolValue(void* val_ptr);
+ bool readStringValue(void* val_ptr);
+ bool readU8Value(void* val_ptr);
+ bool readS8Value(void* val_ptr);
+ bool readU16Value(void* val_ptr);
+ bool readS16Value(void* val_ptr);
+ bool readU32Value(void* val_ptr);
+ bool readS32Value(void* val_ptr);
+ bool readF32Value(void* val_ptr);
+ bool readF64Value(void* val_ptr);
+ bool readColor4Value(void* val_ptr);
+ bool readUIColorValue(void* val_ptr);
+ bool readUUIDValue(void* val_ptr);
+ bool readSDValue(void* val_ptr);
+
+ //writer helper functions
+ bool writeBoolValue(const void* val_ptr, const name_stack_t&);
+ bool writeStringValue(const void* val_ptr, const name_stack_t&);
+ bool writeU8Value(const void* val_ptr, const name_stack_t&);
+ bool writeS8Value(const void* val_ptr, const name_stack_t&);
+ bool writeU16Value(const void* val_ptr, const name_stack_t&);
+ bool writeS16Value(const void* val_ptr, const name_stack_t&);
+ bool writeU32Value(const void* val_ptr, const name_stack_t&);
+ bool writeS32Value(const void* val_ptr, const name_stack_t&);
+ bool writeF32Value(const void* val_ptr, const name_stack_t&);
+ bool writeF64Value(const void* val_ptr, const name_stack_t&);
+ bool writeColor4Value(const void* val_ptr, const name_stack_t&);
+ bool writeUIColorValue(const void* val_ptr, const name_stack_t&);
+ bool writeUUIDValue(const void* val_ptr, const name_stack_t&);
+ bool writeSDValue(const void* val_ptr, const name_stack_t&);
+
+ LLXMLNodePtr getNode(const name_stack_t& stack);
+
+private:
+ Parser::name_stack_t mNameStack;
+ LLXMLNodePtr mCurReadNode;
+ // Root of the widget XML sub-tree, for example, "line_editor"
+ LLXMLNodePtr mWriteRootNode;
+
+ typedef std::map<S32, LLXMLNodePtr> out_nodes_t;
+ out_nodes_t mOutNodes;
+ S32 mLastWriteGeneration;
+ LLXMLNodePtr mLastWrittenChild;
+ S32 mCurReadDepth;
+ std::string mCurFileName;
+};
+
+
+#endif //LLXUIPARSER_H
diff --git a/indra/lscript/lscript_byteformat.h b/indra/lscript/lscript_byteformat.h
index ba2c46bef2..a54ebd5831 100644
--- a/indra/lscript/lscript_byteformat.h
+++ b/indra/lscript/lscript_byteformat.h
@@ -556,7 +556,7 @@ const U32 LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_EOF] =
// http_request string constants
extern const char* URL_REQUEST_GRANTED;
extern const char* URL_REQUEST_DENIED;
-extern const U64 LSL_HTTP_REQUEST_TIMEOUT;
+extern const U64 LSL_HTTP_REQUEST_TIMEOUT_USEC;
#endif
diff --git a/indra/lscript/lscript_compile/CMakeLists.txt b/indra/lscript/lscript_compile/CMakeLists.txt
index 252085bab2..3ed2892e0e 100644
--- a/indra/lscript/lscript_compile/CMakeLists.txt
+++ b/indra/lscript/lscript_compile/CMakeLists.txt
@@ -5,6 +5,7 @@ include(LLCommon)
include(LLMath)
include(LLMessage)
include(LLInventory)
+include(LLPrimitive)
include(LScript)
include(FindCygwin)
@@ -41,6 +42,7 @@ include_directories(
${LLMATH_INCLUDE_DIRS}
${LLMESSAGE_INCLUDE_DIRS}
${LLINVENTORY_INCLUDE_DIRS}
+ ${LLPRIMITIVE_INCLUDE_DIRS}
${LSCRIPT_INCLUDE_DIRS}
)
diff --git a/indra/lscript/lscript_compile/indra.l b/indra/lscript/lscript_compile/indra.l
index ac524326fc..8fe9f5ed29 100644
--- a/indra/lscript/lscript_compile/indra.l
+++ b/indra/lscript/lscript_compile/indra.l
@@ -34,6 +34,7 @@ FS (f|F)
#include "llregionflags.h"
#include "lscript_http.h"
#include "llclickaction.h"
+#include "llmediaentry.h"
void count();
void line_comment();
@@ -150,6 +151,7 @@ extern "C" { int yyerror(const char *fmt, ...); }
"AGENT_CROUCHING" { count(); yylval.ival = AGENT_CROUCHING; return(INTEGER_CONSTANT); }
"AGENT_BUSY" { count(); yylval.ival = AGENT_BUSY; return(INTEGER_CONSTANT); }
"AGENT_ALWAYS_RUN" { count(); yylval.ival = AGENT_ALWAYS_RUN; return(INTEGER_CONSTANT); }
+"AGENT_AUTOPILOT" { count(); yylval.ival = AGENT_AUTOPILOT; return(INTEGER_CONSTANT); }
"CAMERA_PITCH" { count(); yylval.ival = FOLLOWCAM_PITCH; return(INTEGER_CONSTANT); }
"CAMERA_FOCUS_OFFSET" { count(); yylval.ival = FOLLOWCAM_FOCUS_OFFSET; return (INTEGER_CONSTANT); }
@@ -232,7 +234,8 @@ extern "C" { int yyerror(const char *fmt, ...); }
"CHANGED_OWNER" { count(); yylval.ival = CHANGED_OWNER; return(INTEGER_CONSTANT); }
"CHANGED_REGION" { count(); yylval.ival = CHANGED_REGION; return(INTEGER_CONSTANT); }
"CHANGED_TELEPORT" { count(); yylval.ival = CHANGED_TELEPORT; return(INTEGER_CONSTANT); }
-"CHANGED_REGION_START" { count(); yylval.ival = CHANGED_REGION_START; return(INTEGER_CONSTANT); }
+"CHANGED_REGION_START" { count(); yylval.ival = CHANGED_REGION_START; return(INTEGER_CONSTANT); }
+"CHANGED_MEDIA" { count(); yylval.ival = CHANGED_MEDIA; return(INTEGER_CONSTANT); }
"OBJECT_UNKNOWN_DETAIL" { count(); yylval.ival = OBJECT_UNKNOWN_DETAIL; return(INTEGER_CONSTANT); }
"OBJECT_NAME" { count(); yylval.ival = OBJECT_NAME; return(INTEGER_CONSTANT); }
@@ -610,6 +613,7 @@ extern "C" { int yyerror(const char *fmt, ...); }
"CLICK_ACTION_OPEN" { count(); yylval.ival = CLICK_ACTION_OPEN; return(INTEGER_CONSTANT); }
"CLICK_ACTION_PLAY" { count(); yylval.ival = CLICK_ACTION_PLAY; return(INTEGER_CONSTANT); }
"CLICK_ACTION_OPEN_MEDIA" { count(); yylval.ival = CLICK_ACTION_OPEN_MEDIA; return(INTEGER_CONSTANT); }
+"CLICK_ACTION_ZOOM" { count(); yylval.ival = CLICK_ACTION_ZOOM; return(INTEGER_CONSTANT); }
"TEXTURE_BLANK" { yylval.sval = new char[UUID_STR_LENGTH]; strcpy(yylval.sval, "5748decc-f629-461c-9a36-a35a221fe21f"); return(STRING_CONSTANT); }
"TEXTURE_DEFAULT" { yylval.sval = new char[UUID_STR_LENGTH]; strcpy(yylval.sval, "89556747-24cb-43ed-920b-47caed15465f"); return(STRING_CONSTANT); }
@@ -621,6 +625,45 @@ extern "C" { int yyerror(const char *fmt, ...); }
"TOUCH_INVALID_VECTOR" { count(); return(TOUCH_INVALID_VECTOR); }
"TOUCH_INVALID_TEXCOORD" { count(); return(TOUCH_INVALID_TEXCOORD); }
+"PRIM_MEDIA_ALT_IMAGE_ENABLE" { count(); yylval.ival = LLMediaEntry::ALT_IMAGE_ENABLE_ID; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_CONTROLS" { count(); yylval.ival = LLMediaEntry::CONTROLS_ID; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_CURRENT_URL" { count(); yylval.ival = LLMediaEntry::CURRENT_URL_ID; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_HOME_URL" { count(); yylval.ival = LLMediaEntry::HOME_URL_ID; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_AUTO_LOOP" { count(); yylval.ival = LLMediaEntry::AUTO_LOOP_ID; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_AUTO_PLAY" { count(); yylval.ival = LLMediaEntry::AUTO_PLAY_ID; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_AUTO_SCALE" { count(); yylval.ival = LLMediaEntry::AUTO_SCALE_ID; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_AUTO_ZOOM" { count(); yylval.ival = LLMediaEntry::AUTO_ZOOM_ID; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_FIRST_CLICK_INTERACT" { count(); yylval.ival = LLMediaEntry::FIRST_CLICK_INTERACT_ID; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_WIDTH_PIXELS" { count(); yylval.ival = LLMediaEntry::WIDTH_PIXELS_ID; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_HEIGHT_PIXELS" { count(); yylval.ival = LLMediaEntry::HEIGHT_PIXELS_ID; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_WHITELIST_ENABLE" { count(); yylval.ival = LLMediaEntry::WHITELIST_ENABLE_ID; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_WHITELIST" { count(); yylval.ival = LLMediaEntry::WHITELIST_ID; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_PERMS_INTERACT" { count(); yylval.ival = LLMediaEntry::PERMS_INTERACT_ID; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_PERMS_CONTROL" { count(); yylval.ival = LLMediaEntry::PERMS_CONTROL_ID; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_PARAM_MAX" { count(); yylval.ival = LLMediaEntry::PARAM_MAX_ID; return(INTEGER_CONSTANT); }
+
+"PRIM_MEDIA_CONTROLS_STANDARD" { count(); yylval.ival = LLMediaEntry::STANDARD; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_CONTROLS_MINI" { count(); yylval.ival = LLMediaEntry::MINI; return(INTEGER_CONSTANT); }
+
+"PRIM_MEDIA_PERM_NONE" { count(); yylval.ival = LLMediaEntry::PERM_NONE; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_PERM_OWNER" { count(); yylval.ival = LLMediaEntry::PERM_OWNER; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_PERM_GROUP" { count(); yylval.ival = LLMediaEntry::PERM_GROUP; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_PERM_ANYONE" { count(); yylval.ival = LLMediaEntry::PERM_ANYONE; return(INTEGER_CONSTANT); }
+
+"PRIM_MEDIA_MAX_URL_LENGTH" { count(); yylval.ival = LLMediaEntry::MAX_URL_LENGTH; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_MAX_WHITELIST_SIZE" { count(); yylval.ival = LLMediaEntry::MAX_WHITELIST_SIZE; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_MAX_WHITELIST_COUNT" { count(); yylval.ival = LLMediaEntry::MAX_WHITELIST_COUNT; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_MAX_WIDTH_PIXELS" { count(); yylval.ival = LLMediaEntry::MAX_WIDTH_PIXELS; return(INTEGER_CONSTANT); }
+"PRIM_MEDIA_MAX_HEIGHT_PIXELS" { count(); yylval.ival = LLMediaEntry::MAX_HEIGHT_PIXELS; return(INTEGER_CONSTANT); }
+
+"STATUS_OK" { count(); yylval.ival = LSL_STATUS_OK; return(INTEGER_CONSTANT); }
+"STATUS_MALFORMED_PARAMS" { count(); yylval.ival = LSL_STATUS_MALFORMED_PARAMS; return(INTEGER_CONSTANT); }
+"STATUS_TYPE_MISMATCH" { count(); yylval.ival = LSL_STATUS_TYPE_MISMATCH; return(INTEGER_CONSTANT); }
+"STATUS_BOUNDS_ERROR" { count(); yylval.ival = LSL_STATUS_BOUNDS_ERROR; return(INTEGER_CONSTANT); }
+"STATUS_NOT_FOUND" { count(); yylval.ival = LSL_STATUS_NOT_FOUND; return(INTEGER_CONSTANT); }
+"STATUS_NOT_SUPPORTED" { count(); yylval.ival = LSL_STATUS_NOT_SUPPORTED; return(INTEGER_CONSTANT); }
+"STATUS_INTERNAL_ERROR" { count(); yylval.ival = LSL_STATUS_INTERNAL_ERROR; return(INTEGER_CONSTANT); }
+"STATUS_WHITELIST_FAILED" { count(); yylval.ival = LSL_STATUS_WHITELIST_FAILED; return(INTEGER_CONSTANT); }
{L}({L}|{N})* { count(); yylval.sval = new char[strlen(yytext) + 1]; strcpy(yylval.sval, yytext); return(IDENTIFIER); }
diff --git a/indra/lscript/lscript_compile/lscript_tree.cpp b/indra/lscript/lscript_compile/lscript_tree.cpp
index e291d4c6f8..3b8bbbe805 100644
--- a/indra/lscript/lscript_compile/lscript_tree.cpp
+++ b/indra/lscript/lscript_compile/lscript_tree.cpp
@@ -631,9 +631,7 @@ static void print_cil_cast(LLFILE* fp, LSCRIPTType srcType, LSCRIPTType targetTy
switch(targetType)
{
case LST_INTEGER:
- //fprintf(fp, "call int32 [LslLibrary]LindenLab.SecondLife.LslRunTime::ToInteger(float32)\n");
- fprintf(fp, "conv.i4\n"); // TODO replace this line with the above
- // we the entire grid is > 1.25.1
+ fprintf(fp, "call int32 [LslLibrary]LindenLab.SecondLife.LslRunTime::ToInteger(float32)\n");
break;
case LST_STRING:
fprintf(fp, "call string [LslLibrary]LindenLab.SecondLife.LslRunTime::ToString(float32)\n");
@@ -8375,10 +8373,18 @@ void LLScriptStateChange::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp
chunk->addInteger(mIdentifier->mScopeEntry->mCount);
}
break;
+ case LSCP_TYPE:
+ mReturnType = basetype;
+ break;
case LSCP_EMIT_CIL_ASSEMBLY:
fprintf(fp, "ldarg.0\n");
fprintf(fp, "ldstr \"%s\"\n", mIdentifier->mName);
fprintf(fp, "call instance void class [LslUserScript]LindenLab.SecondLife.LslUserScript::ChangeState(string)\n");
+ // We are doing a state change. In the LSL interpreter, this is basically a longjmp. We emulate it
+ // here using a call to the ChangeState followed by a short cut return of the current method. To
+ // maintain type safety we need to push an arbitrary variable of the current method's return type
+ // onto the stack before returning. This will be ignored and discarded.
+ print_cil_init_variable(fp, mReturnType);
fprintf(fp, "ret\n");
break;
default:
@@ -10673,20 +10679,21 @@ void LLScriptScript::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePa
{
mGlobalScope = new LLScriptScope(gScopeStringTable);
// zeroth, add library functions to global scope
- S32 i;
+ U16 function_index = 0;
const char *arg;
LLScriptScopeEntry *sentry;
- for (i = 0; i < gScriptLibrary.mNextNumber; i++)
+ for (std::vector<LLScriptLibraryFunction>::const_iterator i = gScriptLibrary.mFunctions.begin();
+ i != gScriptLibrary.mFunctions.end(); ++i)
{
// First, check to make sure this isn't a god only function, or that the viewer's agent is a god.
- if (!gScriptLibrary.mFunctions[i]->mGodOnly || mGodLike)
+ if (!i->mGodOnly || mGodLike)
{
- if (gScriptLibrary.mFunctions[i]->mReturnType)
- sentry = mGlobalScope->addEntry(gScriptLibrary.mFunctions[i]->mName, LIT_LIBRARY_FUNCTION, char2type(*gScriptLibrary.mFunctions[i]->mReturnType));
+ if (i->mReturnType)
+ sentry = mGlobalScope->addEntry(i->mName, LIT_LIBRARY_FUNCTION, char2type(*i->mReturnType));
else
- sentry = mGlobalScope->addEntry(gScriptLibrary.mFunctions[i]->mName, LIT_LIBRARY_FUNCTION, LST_NULL);
- sentry->mLibraryNumber = i;
- arg = gScriptLibrary.mFunctions[i]->mArgs;
+ sentry = mGlobalScope->addEntry(i->mName, LIT_LIBRARY_FUNCTION, LST_NULL);
+ sentry->mLibraryNumber = function_index;
+ arg = i->mArgs;
if (arg)
{
while (*arg)
@@ -10698,6 +10705,7 @@ void LLScriptScript::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePa
}
}
}
+ function_index++;
}
// first go and collect all the global variables
if (mGlobals)
diff --git a/indra/lscript/lscript_compile/lscript_tree.h b/indra/lscript/lscript_compile/lscript_tree.h
index 12c16908af..a667e1eb5b 100644
--- a/indra/lscript/lscript_compile/lscript_tree.h
+++ b/indra/lscript/lscript_compile/lscript_tree.h
@@ -1888,6 +1888,7 @@ public:
S32 getSize();
LLScriptIdentifier *mIdentifier;
+ LSCRIPTType mReturnType;
};
class LLScriptJump : public LLScriptStatement
diff --git a/indra/lscript/lscript_execute.h b/indra/lscript/lscript_execute.h
index 9a631c4c8f..96855abea0 100644
--- a/indra/lscript/lscript_execute.h
+++ b/indra/lscript/lscript_execute.h
@@ -37,6 +37,8 @@
#include "linked_lists.h"
#include "lscript_library.h"
+class LLTimer;
+
// Return values for run() methods
const U32 NO_DELETE_FLAG = 0x0000;
const U32 DELETE_FLAG = 0x0001;
@@ -369,8 +371,7 @@ class LLScriptExecute
{
public:
LLScriptExecute();
- virtual ~LLScriptExecute() {;}
-
+ virtual ~LLScriptExecute() = 0;
virtual S32 getVersion() const = 0;
virtual void deleteAllEvents() = 0;
virtual void addEvent(LLScriptDataCollection* event) = 0;
diff --git a/indra/lscript/lscript_execute/llscriptresource.cpp b/indra/lscript/lscript_execute/llscriptresource.cpp
index 6c4776c2e4..cd3696ab3f 100644
--- a/indra/lscript/lscript_execute/llscriptresource.cpp
+++ b/indra/lscript/lscript_execute/llscriptresource.cpp
@@ -30,6 +30,8 @@
* $/LicenseInfo$
*/
+#include "linden_common.h"
+
#include "llscriptresource.h"
#include "llerror.h"
diff --git a/indra/lscript/lscript_execute/lscript_execute.cpp b/indra/lscript/lscript_execute/lscript_execute.cpp
index 05fee9a419..e849fa9a6e 100644
--- a/indra/lscript/lscript_execute/lscript_execute.cpp
+++ b/indra/lscript/lscript_execute/lscript_execute.cpp
@@ -41,6 +41,8 @@
#include "lscript_library.h"
#include "lscript_heapruntime.h"
#include "lscript_alloc.h"
+#include "llstat.h"
+
// Static
const S32 DEFAULT_SCRIPT_TIMER_CHECK_SKIP = 4;
@@ -72,7 +74,7 @@ const char* URL_REQUEST_GRANTED = "URL_REQUEST_GRANTED";
const char* URL_REQUEST_DENIED = "URL_REQUEST_DENIED";
// HTTP Requests to LSL scripts will time out after 25 seconds.
-const U64 LSL_HTTP_REQUEST_TIMEOUT = 25 * USEC_PER_SEC;
+const U64 LSL_HTTP_REQUEST_TIMEOUT_USEC = 25 * USEC_PER_SEC;
LLScriptExecuteLSL2::LLScriptExecuteLSL2(LLFILE *fp)
{
@@ -110,6 +112,7 @@ LLScriptExecuteLSL2::LLScriptExecuteLSL2(const U8* bytecode, U32 bytecode_size)
init();
}
+LLScriptExecute::~LLScriptExecute() {}
LLScriptExecuteLSL2::~LLScriptExecuteLSL2()
{
delete[] mBuffer;
@@ -4234,19 +4237,16 @@ S32 lscript_push_variable(LLScriptLibData *data, U8 *buffer)
return 4;
}
-BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
+
+// Shared code for run_calllib() and run_calllib_two_byte()
+BOOL run_calllib_common(U8 *buffer, S32 &offset, const LLUUID &id, U16 arg)
{
- if (b_print)
- printf("[0x%X]\tCALLLIB ", offset);
- offset++;
- U8 arg = safe_instruction_bytestream2byte(buffer, offset);
- if (arg >= gScriptLibrary.mNextNumber)
+ if (arg >= gScriptLibrary.mFunctions.size())
{
set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
return FALSE;
}
- if (b_print)
- printf("%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg]->mName);
+ LLScriptLibraryFunction const & function = gScriptLibrary.mFunctions[arg];
// pull out the arguments and the return values
LLScriptLibData *arguments = NULL;
@@ -4254,14 +4254,14 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
S32 i, number;
- if (gScriptLibrary.mFunctions[arg]->mReturnType)
+ if (function.mReturnType)
{
returnvalue = new LLScriptLibData;
}
- if (gScriptLibrary.mFunctions[arg]->mArgs)
+ if (function.mArgs)
{
- number = (S32)strlen(gScriptLibrary.mFunctions[arg]->mArgs); /*Flawfinder: ignore*/
+ number = (S32)strlen(function.mArgs); //Flawfinder: ignore
arguments = new LLScriptLibData[number];
}
else
@@ -4271,24 +4271,18 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
for (i = number - 1; i >= 0; i--)
{
- lscript_pop_variable(&arguments[i], buffer, gScriptLibrary.mFunctions[arg]->mArgs[i]);
+ lscript_pop_variable(&arguments[i], buffer, function.mArgs[i]);
}
- if (b_print)
- {
- printf("%s\n", gScriptLibrary.mFunctions[arg]->mDesc);
- }
+ // Actually execute the function call
+ function.mExecFunc(returnvalue, arguments, id);
- {
- // LLFastTimer time_in_libraries1(LLFastTimer::FTM_TEMP7);
- gScriptLibrary.mFunctions[arg]->mExecFunc(returnvalue, arguments, id);
- }
- add_register_fp(buffer, LREG_ESR, -gScriptLibrary.mFunctions[arg]->mEnergyUse);
- add_register_fp(buffer, LREG_SLR, gScriptLibrary.mFunctions[arg]->mSleepTime);
+ add_register_fp(buffer, LREG_ESR, -(function.mEnergyUse));
+ add_register_fp(buffer, LREG_SLR, function.mSleepTime);
if (returnvalue)
{
- returnvalue->mType = char2type(*gScriptLibrary.mFunctions[arg]->mReturnType);
+ returnvalue->mType = char2type(*function.mReturnType);
lscript_push_return_variable(returnvalue, buffer);
}
@@ -4305,72 +4299,32 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
}
-BOOL run_calllib_two_byte(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
+BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
- if (b_print)
- printf("[0x%X]\tCALLLIB ", offset);
offset++;
- U16 arg = safe_instruction_bytestream2u16(buffer, offset);
- if (arg >= gScriptLibrary.mNextNumber)
+ U16 arg = (U16) safe_instruction_bytestream2byte(buffer, offset);
+ if (b_print &&
+ arg < gScriptLibrary.mFunctions.size())
{
- set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
- return FALSE;
- }
- if (b_print)
- printf("%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg]->mName);
-
- // pull out the arguments and the return values
- LLScriptLibData *arguments = NULL;
- LLScriptLibData *returnvalue = NULL;
-
- S32 i, number;
-
- if (gScriptLibrary.mFunctions[arg]->mReturnType)
- {
- returnvalue = new LLScriptLibData;
- }
-
- if (gScriptLibrary.mFunctions[arg]->mArgs)
- {
- number = (S32)strlen(gScriptLibrary.mFunctions[arg]->mArgs); /*Flawfinder: ignore*/
- arguments = new LLScriptLibData[number];
- }
- else
- {
- number = 0;
- }
-
- for (i = number - 1; i >= 0; i--)
- {
- lscript_pop_variable(&arguments[i], buffer, gScriptLibrary.mFunctions[arg]->mArgs[i]);
- }
-
- if (b_print)
- {
- printf("%s\n", gScriptLibrary.mFunctions[arg]->mDesc);
- }
-
- {
- // LLFastTimer time_in_libraries2(LLFastTimer::FTM_TEMP8);
- gScriptLibrary.mFunctions[arg]->mExecFunc(returnvalue, arguments, id);
+ printf("[0x%X]\tCALLLIB ", offset);
+ LLScriptLibraryFunction const & function = gScriptLibrary.mFunctions[arg];
+ printf("%d (%s)\n", (U32)arg, function.mName);
+ //printf("%s\n", function.mDesc);
}
- add_register_fp(buffer, LREG_ESR, -gScriptLibrary.mFunctions[arg]->mEnergyUse);
- add_register_fp(buffer, LREG_SLR, gScriptLibrary.mFunctions[arg]->mSleepTime);
+ return run_calllib_common(buffer, offset, id, arg);
+}
- if (returnvalue)
+BOOL run_calllib_two_byte(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
+{
+ offset++;
+ U16 arg = safe_instruction_bytestream2u16(buffer, offset);
+ if (b_print &&
+ arg < gScriptLibrary.mFunctions.size())
{
- returnvalue->mType = char2type(*gScriptLibrary.mFunctions[arg]->mReturnType);
- lscript_push_return_variable(returnvalue, buffer);
+ printf("[0x%X]\tCALLLIB ", (offset-1));
+ LLScriptLibraryFunction const & function = gScriptLibrary.mFunctions[arg];
+ printf("%d (%s)\n", (U32)arg, function.mName);
+ //printf("%s\n", function.mDesc);
}
-
- delete [] arguments;
- delete returnvalue;
-
- // reset the BP after calling the library files
- S32 bp = lscript_pop_int(buffer);
- set_bp(buffer, bp);
-
- // pop off the spot for the instruction pointer
- lscript_poparg(buffer, 4);
- return FALSE;
+ return run_calllib_common(buffer, offset, id, arg);
}
diff --git a/indra/lscript/lscript_execute/lscript_readlso.cpp b/indra/lscript/lscript_execute/lscript_readlso.cpp
index faf4fba0e0..2948ebca63 100644
--- a/indra/lscript/lscript_execute/lscript_readlso.cpp
+++ b/indra/lscript/lscript_execute/lscript_readlso.cpp
@@ -1579,7 +1579,7 @@ void print_calllib(LLFILE *fp, U8 *buffer, S32 &offset, S32 tabs)
lso_print_tabs(fp, tabs);
fprintf(fp, "[0x%X]\tCALLLIB ", offset++);
arg = *(buffer + offset++);
- fprintf(fp, "%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg]->mName);
+ fprintf(fp, "%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg].mName);
}
@@ -1589,6 +1589,6 @@ void print_calllib_two_byte(LLFILE *fp, U8 *buffer, S32 &offset, S32 tabs)
lso_print_tabs(fp, tabs);
fprintf(fp, "[0x%X]\tCALLLIB_TWO_BYTE ", offset++);
arg = bytestream2u16(buffer, offset);
- fprintf(fp, "%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg]->mName);
+ fprintf(fp, "%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg].mName);
}
diff --git a/indra/lscript/lscript_export.h b/indra/lscript/lscript_export.h
index d4626a8cd2..4c883582e2 100644
--- a/indra/lscript/lscript_export.h
+++ b/indra/lscript/lscript_export.h
@@ -35,6 +35,6 @@
#include "lscript_library.h"
-extern LLScriptLibrary gScriptLibrary;
+
#endif
diff --git a/indra/lscript/lscript_library.h b/indra/lscript/lscript_library.h
index fa3b06b7d9..363d11f3aa 100644
--- a/indra/lscript/lscript_library.h
+++ b/indra/lscript/lscript_library.h
@@ -44,7 +44,7 @@ class LLScriptLibData;
class LLScriptLibraryFunction
{
public:
- LLScriptLibraryFunction(F32 eu, F32 st, void (*exec_func)(LLScriptLibData *, LLScriptLibData *, const LLUUID &), const char *name, const char *ret_type, const char *args, const char *desc, BOOL god_only = FALSE);
+ LLScriptLibraryFunction(F32 eu, F32 st, void (*exec_func)(LLScriptLibData *, LLScriptLibData *, const LLUUID &), const char *name, const char *ret_type, const char *args, BOOL god_only = FALSE);
~LLScriptLibraryFunction();
F32 mEnergyUse;
@@ -53,7 +53,6 @@ public:
const char *mName;
const char *mReturnType;
const char *mArgs;
- const char *mDesc;
BOOL mGodOnly;
};
@@ -65,14 +64,13 @@ public:
void init();
- void addFunction(LLScriptLibraryFunction *func);
+ void addFunction(F32 eu, F32 st, void (*exec_func)(LLScriptLibData *, LLScriptLibData *, const LLUUID &), const char *name, const char *ret_type, const char *args, BOOL god_only = FALSE);
void assignExec(const char *name, void (*exec_func)(LLScriptLibData *, LLScriptLibData *, const LLUUID &));
- S32 mNextNumber;
- LLScriptLibraryFunction **mFunctions;
+ std::vector<LLScriptLibraryFunction> mFunctions;
};
-extern LLScriptLibrary gScriptLibrary;
+
class LLScriptLibData
{
@@ -430,4 +428,6 @@ public:
};
+extern LLScriptLibrary gScriptLibrary;
+
#endif
diff --git a/indra/lscript/lscript_library/lscript_library.cpp b/indra/lscript/lscript_library/lscript_library.cpp
index 0342c97429..5e394644c2 100644
--- a/indra/lscript/lscript_library/lscript_library.cpp
+++ b/indra/lscript/lscript_library/lscript_library.cpp
@@ -49,20 +49,12 @@
#include "lscript_library.h"
LLScriptLibrary::LLScriptLibrary()
-: mNextNumber(0), mFunctions(NULL)
{
init();
}
LLScriptLibrary::~LLScriptLibrary()
{
- S32 i;
- for (i = 0; i < mNextNumber; i++)
- {
- delete mFunctions[i];
- mFunctions[i] = NULL;
- }
- delete [] mFunctions;
}
void dummy_func(LLScriptLibData *retval, LLScriptLibData *args, const LLUUID &id)
@@ -75,388 +67,393 @@ void LLScriptLibrary::init()
// Otherwise the bytecode numbers for each call will be wrong, and all
// existing scripts will crash.
- // energy, sleep, dummy_func, name, return type, parameters, help text, gods-only
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSin", "f", "f", "float llSin(float theta)\ntheta in radians"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llCos", "f", "f", "float llCos(float theta)\ntheta in radians"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llTan", "f", "f", "float llTan(float theta)\ntheta radians"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llAtan2", "f", "ff", "float llAtan2(float y, float x)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSqrt", "f", "f", "float llSqrt(float val)\nreturns 0 and triggers a Math Error for imaginary results"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llPow", "f", "ff", "float llPow(float base, float exponent)\nreturns 0 and triggers Math Error for imaginary results"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llAbs", "i", "i", "integer llAbs(integer val)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llFabs", "f", "f", "float llFabs(float val)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llFrand", "f", "f", "float llFrand(float mag)\nreturns random number in range [0,mag)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llFloor", "i", "f", "integer llFloor(float val)\nreturns largest integer value <= val"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llCeil", "i", "f", "integer llCeil(float val)\nreturns smallest integer value >= val"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llRound", "i", "f", "integer llRound(float val)\nreturns val rounded to the nearest integer"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llVecMag", "f", "v", "float llVecMag(vector v)\nreturns the magnitude of v"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llVecNorm", "v", "v", "vector llVecNorm(vector v)\nreturns the v normalized"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llVecDist", "f", "vv", "float llVecDist(vector v1, vector v2)\nreturns the 3D distance between v1 and v2"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llRot2Euler", "v", "q", "vector llRot2Euler(rotation q)\nreturns the Euler representation (roll, pitch, yaw) of q"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llEuler2Rot", "q", "v", "rotation llEuler2Rot(vector v)\nreturns the rotation representation of Euler Angles v"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llAxes2Rot", "q", "vvv", "rotation llAxes2Rot(vector fwd, vector left, vector up)\nreturns the rotation defined by the coordinate axes"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llRot2Fwd", "v", "q", "vector llRot2Fwd(rotation q)\nreturns the forward vector defined by q"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llRot2Left", "v", "q", "vector llRot2Left(rotation q)\nreturns the left vector defined by q"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llRot2Up", "v", "q", "vector llRot2Up(rotation q)\nreturns the up vector defined by q"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llRotBetween", "q", "vv", "rotation llRotBetween(vector v1, vector v2)\nreturns the rotation to rotate v1 to v2"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llWhisper", NULL, "is", "llWhisper(integer channel, string msg)\nwhispers msg on channel"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSay", NULL, "is", "llSay(integer channel, string msg)\nsays msg on channel"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llShout", NULL, "is", "llShout(integer channel, string msg)\nshouts msg on channel"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llListen", "i", "isks", "integer llListen(integer channel, string name, key id, string msg)\nsets a callback for msg on channel from name and id (name, id, and/or msg can be empty) and returns an identifier that can be used to deactivate or remove the listen"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llListenControl", NULL, "ii", "llListenControl(integer number, integer active)\nmakes a listen event callback active or inactive"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llListenRemove", NULL, "i", "llListenRemove(integer number)\nremoves listen event callback number"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSensor", NULL, "skiff", "llSensor(string name, key id, integer type, float range, float arc)\nPerforms a single scan for name and id with type (AGENT, ACTIVE, PASSIVE, and/or SCRIPTED) within range meters and arc radians of forward vector (name, id, and/or keytype can be empty or 0)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSensorRepeat", NULL, "skifff", "llSensorRepeat(string name, key id, integer type, float range, float arc, float rate)\nsets a callback for name and id with type (AGENT, ACTIVE, PASSIVE, and/or SCRIPTED) within range meters and arc radians of forward vector (name, id, and/or keytype can be empty or 0) and repeats every rate seconds"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSensorRemove", NULL, NULL, "llSensorRemove()\nremoves sensor"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedName", "s", "i", "string llDetectedName(integer number)\nreturns the name of detected object number (returns empty string if number is not valid sensed object)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedKey", "k", "i", "key llDetectedKey(integer number)\nreturns the key of detected object number (returns empty key if number is not valid sensed object)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedOwner", "k", "i", "key llDetectedOwner(integer number)\nreturns the key of detected object's owner (returns empty key if number is not valid sensed object)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedType", "i", "i", "integer llDetectedType(integer number)\nreturns the type (AGENT, ACTIVE, PASSIVE, SCRIPTED) of detected object (returns 0 if number is not valid sensed object)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedPos", "v", "i", "vector llDetectedPos(integer number)\nreturns the position of detected object number (returns <0,0,0> if number is not valid sensed object)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedVel", "v", "i", "vector llDetectedVel(integer number)\nreturns the velocity of detected object number (returns <0,0,0> if number is not valid sensed object)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedGrab", "v", "i", "vector llDetectedGrab(integer number)\nreturns the grab offset of the user touching object (returns <0,0,0> if number is not valid sensed object)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedRot", "q", "i", "rotation llDetectedRot(integer number)\nreturns the rotation of detected object number (returns <0,0,0,1> if number is not valid sensed object)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedGroup", "i", "i", "integer llDetectedGroup(integer number)\nReturns TRUE if detected object is part of same group as owner"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedLinkNumber", "i", "i", "integer llDetectedLinkNumber(integer number)\nreturns the link position of the triggered event for touches and collisions only"));
- addFunction(new LLScriptLibraryFunction(0.f, 0.f, dummy_func, "llDie", NULL, NULL, "llDie()\ndeletes the object"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGround", "f", "v", "float llGround(vector v)\nreturns the ground height below the object position + v"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llCloud", "f", "v", "float llCloud(vector v)\nreturns the cloud density at the object position + v"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llWind", "v", "v", "vector llWind(vector v)\nreturns the wind velocity at the object position + v"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetStatus", NULL, "ii", "llSetStatus(integer status, integer value)\nsets status (STATUS_PHYSICS, STATUS_PHANTOM, STATUS_BLOCK_GRAB,\nSTATUS_ROTATE_X, STATUS_ROTATE_Y, and/or STATUS_ROTATE_Z) to value"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetStatus", "i", "i", "integer llGetStatus(integer status)\ngets value of status (STATUS_PHYSICS, STATUS_PHANTOM, STATUS_BLOCK_GRAB,\nSTATUS_ROTATE_X, STATUS_ROTATE_Y, and/or STATUS_ROTATE_Z)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetScale", NULL, "v", "llSetScale(vector scale)\nsets the scale"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetScale", "v", NULL, "vector llGetScale()\ngets the scale"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetColor", NULL, "vi", "llSetColor(vector color, integer face)\nsets the color"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetAlpha", "f", "i", "float llGetAlpha(integer face)\ngets the alpha"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetAlpha", NULL, "fi", "llSetAlpha(float alpha, integer face)\nsets the alpha"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetColor", "v", "i", "vector llGetColor(integer face)\ngets the color"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.2f, dummy_func, "llSetTexture", NULL, "si", "llSetTexture(string texture, integer face)\nsets the texture of face"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.2f, dummy_func, "llScaleTexture", NULL, "ffi", "llScaleTexture(float scales, float scalet, integer face)\nsets the texture s, t scales for the chosen face"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.2f, dummy_func, "llOffsetTexture", NULL, "ffi", "llOffsetTexture(float offsets, float offsett, integer face)\nsets the texture s, t offsets for the chosen face"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.2f, dummy_func, "llRotateTexture", NULL, "fi", "llRotateTexture(float rotation, integer face)\nsets the texture rotation for the chosen face"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetTexture", "s", "i", "string llGetTexture(integer face)\ngets the texture of face (if it's a texture in the object inventory, otherwise the key in a string)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.2f, dummy_func, "llSetPos", NULL, "v", "llSetPos(vector pos)\nsets the position (if the script isn't physical)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetPos", "v", NULL, "vector llGetPos()\ngets the position (if the script isn't physical)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetLocalPos", "v", NULL, "vector llGetLocalPos()\ngets the position relative to the root (if the script isn't physical)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.2f, dummy_func, "llSetRot", NULL, "q", "llSetRot(rotation rot)\nsets the rotation (if the script isn't physical)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetRot", "q", NULL, "rotation llGetRot()\ngets the rotation (if the script isn't physical)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetLocalRot", "q", NULL, "rotation llGetLocalRot()\ngets the rotation local to the root (if the script isn't physical)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetForce", NULL, "vi", "llSetForce(vector force, integer local)\nsets force on object, in local coords if local == TRUE (if the script is physical)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetForce", "v", NULL, "vector llGetForce()\ngets the force (if the script is physical)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llTarget", "i", "vf", "integer llTarget(vector position, float range)\nset positions within range of position as a target and return an ID for the target"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llTargetRemove", NULL, "i", "llTargetRemove(integer number)\nremoves target number"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llRotTarget", "i", "qf", "integer llRotTarget(rotation rot, float error)\nset rotations with error of rot as a rotational target and return an ID for the rotational target"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llRotTargetRemove", NULL, "i", "llRotTargetRemove(integer number)\nremoves rotational target number"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llMoveToTarget", NULL, "vf", "llMoveToTarget(vector target, float tau)\ncritically damp to target in tau seconds (if the script is physical)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llStopMoveToTarget", NULL, NULL, "llStopMoveToTarget()\nStops critically damped motion"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llApplyImpulse", NULL, "vi", "llApplyImpulse(vector force, integer local)\napplies impulse to object, in local coords if local == TRUE (if the script is physical)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llApplyRotationalImpulse", NULL, "vi", "llApplyRotationalImpulse(vector force, integer local)\napplies rotational impulse to object, in local coords if local == TRUE (if the script is physical)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetTorque", NULL, "vi", "llSetTorque(vector torque, integer local)\nsets the torque of object, in local coords if local == TRUE (if the script is physical)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetTorque", "v", NULL, "vector llGetTorque()\ngets the torque (if the script is physical)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetForceAndTorque", NULL, "vvi", "llSetForceAndTorque(vector force, vector torque, integer local)\nsets the force and torque of object, in local coords if local == TRUE (if the script is physical)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetVel", "v", NULL, "vector llGetVel()\ngets the velocity"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetAccel", "v", NULL, "vector llGetAccel()\ngets the acceleration"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetOmega", "v", NULL, "vector llGetOmega()\ngets the omega"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetTimeOfDay", "f", "", "float llGetTimeOfDay()\ngets the time in seconds since Second Life server midnight (or since server up-time; whichever is smaller)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetWallclock", "f", "", "float llGetWallclock()\ngets the time in seconds since midnight"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetTime", "f", NULL, "float llGetTime()\ngets the time in seconds since creation"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llResetTime", NULL, NULL, "llResetTime()\nsets the time to zero"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetAndResetTime", "f", NULL, "float llGetAndResetTime()\ngets the time in seconds since creation and sets the time to zero"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSound", NULL, "sfii", "llSound(string sound, float volume, integer queue, integer loop)\nplays sound at volume and whether it should loop or not"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llPlaySound", NULL, "sf", "llPlaySound(string sound, float volume)\nplays attached sound once at volume (0.0 - 1.0)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llLoopSound", NULL, "sf", "llLoopSound(string sound, float volume)\nplays attached sound looping indefinitely at volume (0.0 - 1.0)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llLoopSoundMaster", NULL, "sf", "llLoopSoundMaster(string sound, float volume)\nplays attached sound looping at volume (0.0 - 1.0), declares it a sync master"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llLoopSoundSlave", NULL, "sf", "llLoopSoundSlave(string sound, float volume)\nplays attached sound looping at volume (0.0 - 1.0), synced to most audible sync master"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llPlaySoundSlave", NULL, "sf", "llPlaySoundSlave(string sound, float volume)\nplays attached sound once at volume (0.0 - 1.0), synced to next loop of most audible sync master"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llTriggerSound", NULL, "sf", "llTriggerSound(string sound, float volume)\nplays sound at volume (0.0 - 1.0), centered at but not attached to object"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llStopSound", NULL, "", "llStopSound()\nStops currently attached sound"));
- addFunction(new LLScriptLibraryFunction(10.f, 1.f, dummy_func, "llPreloadSound", NULL, "s", "llPreloadSound(string sound)\npreloads a sound on viewers within range"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetSubString", "s", "sii", "string llGetSubString(string src, integer start, integer end)\nreturns the indicated substring"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDeleteSubString", "s", "sii", "string llDeleteSubString(string src, integer start, integer end)\nremoves the indicated substring and returns the result"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llInsertString", "s", "sis", "string llInsertString(string dst, integer position, string src)\ninserts src into dst at position and returns the result"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llToUpper", "s", "s", "string llToUpper(string src)\nconvert src to all upper case and returns the result"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llToLower", "s", "s", "string llToLower(string src)\nconvert src to all lower case and returns the result"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGiveMoney", "i", "ki", "llGiveMoney(key destination, integer amount)\ntransfer amount of money from script owner to destination"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.1f, dummy_func, "llMakeExplosion", NULL, "iffffsv", "llMakeExplosion(integer particles, float scale, float vel, float lifetime, float arc, string texture, vector offset)\nMake a round explosion of particles"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.1f, dummy_func, "llMakeFountain", NULL, "iffffisvf", "llMakeFountain(integer particles, float scale, float vel, float lifetime, float arc, integer bounce, string texture, vector offset, float bounce_offset)\nMake a fountain of particles"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.1f, dummy_func, "llMakeSmoke", NULL, "iffffsv", "llMakeSmoke(integer particles, float scale, float vel, float lifetime, float arc, string texture, vector offset)\nMake smoke like particles"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.1f, dummy_func, "llMakeFire", NULL, "iffffsv", "llMakeFire(integer particles, float scale, float vel, float lifetime, float arc, string texture, vector offset)\nMake fire like particles"));
- addFunction(new LLScriptLibraryFunction(200.f, 0.1f, dummy_func, "llRezObject", NULL, "svvqi", "llRezObject(string inventory, vector pos, vector vel, rotation rot, integer param)\nInstanciate owners inventory object at pos with velocity vel and rotation rot with start parameter param"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llLookAt", NULL, "vff", "llLookAt(vector target, F32 strength, F32 damping)\nCause object name to point it's forward axis towards target"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llStopLookAt", NULL, NULL, "llStopLookAt()\nStop causing object name to point at a target"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetTimerEvent", NULL, "f", "llSetTimerEvent(float sec)\nCause the timer event to be triggered every sec seconds"));
- addFunction(new LLScriptLibraryFunction(0.f, 0.f, dummy_func, "llSleep", NULL, "f", "llSleep(float sec)\nPut script to sleep for sec seconds"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetMass", "f", NULL, "float llGetMass()\nGet the mass of task name that script is attached to"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llCollisionFilter", NULL, "ski", "llCollisionFilter(string name, key id, integer accept)\nif accept == TRUE, only accept collisions with objects name and id (either is optional), otherwise with objects not name or id"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llTakeControls", NULL, "iii", "llTakeControls(integer controls, integer accept, integer pass_on)\nTake controls from agent task has permissions for. If (accept == (controls & input)), send input to task. If pass_on send to agent also."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llReleaseControls", NULL, NULL, "llReleaseControls()\nStop taking inputs"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llAttachToAvatar", NULL, "i", "llAttachToAvatar(integer attachment)\nAttach to avatar task has permissions for at point attachment"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetachFromAvatar", NULL, NULL, "llDetachFromAvatar()\nDrop off of avatar"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llTakeCamera", NULL, "k", "llTakeCamera(key avatar)\nMove avatar's viewpoint to task"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llReleaseCamera", NULL, "k", "llReleaseCamera(key avatar)\nReturn camera to agent"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetOwner", "k", NULL, "key llGetOwner()\nReturns the owner of the task"));
- addFunction(new LLScriptLibraryFunction(10.f, 2.f, dummy_func, "llInstantMessage", NULL, "ks", "llInstantMessage(key user, string message)\nIMs message to the user"));
- addFunction(new LLScriptLibraryFunction(10.f, 20.f, dummy_func, "llEmail", NULL, "sss", "llEmail(string address, string subject, string message)\nSends email to address with subject and message"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetNextEmail", NULL, "ss", "llGetNextEmail(string address, string subject)\nGet the next waiting email with appropriate address and/or subject (if blank they are ignored)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetKey", "k", NULL, "key llGetKey()\nGet the key for the task the script is attached to"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetBuoyancy", NULL, "f", "llSetBuoyancy(float buoyancy)\nSet the tasks buoyancy (0 is none, < 1.0 sinks, 1.0 floats, > 1.0 rises)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetHoverHeight", NULL, "fif", "llSetHoverHeight(float height, integer water, float tau)\nCritically damps to a height (either above ground level or above the higher of land and water if water == TRUE)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llStopHover", NULL, NULL, "llStopHover()\nStop hovering to a height"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llMinEventDelay", NULL, "f", "llMinEventDelay(float delay)\nSet the minimum time between events being handled"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSoundPreload", NULL, "s", "llSoundPreload(string sound)\npreloads a sound on viewers within range"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llRotLookAt", NULL, "qff", "llRotLookAt(rotation target, F32 strength, F32 damping)\nCause object name to point it's forward axis towards target"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llStringLength", "i", "s", "integer llStringLength(string str)\nReturns the length of string"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llStartAnimation", NULL, "s", "llStartAnimation(string anim)\nStart animation anim for agent that owns object"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llStopAnimation", NULL, "s", "llStopAnimation(string anim)\nStop animation anim for agent that owns object"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llPointAt", NULL, "v", "llPointAt(vector pos)\nMake agent that owns object point at pos"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llStopPointAt", NULL, NULL, "llStopPointAt()\nStop agent that owns object pointing"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llTargetOmega", NULL, "vff", "llTargetOmega(vector axis, float spinrate, float gain)\nAttempt to spin at spinrate with strength gain"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetStartParameter", "i", NULL, "integer llGetStartParameter()\nGet's the start paramter passed to llRezObject"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGodLikeRezObject", NULL, "kv", "llGodLikeRezObject(key inventory, vector pos)\nrez directly off of a UUID if owner has dog-bit set", TRUE));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llRequestPermissions", NULL, "ki", "llRequestPermissions(key agent, integer perm)\nask agent to allow the script to do perm (NB: Debit, ownership, link, joint, and permission requests can only go to the task's owner)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetPermissionsKey", "k", NULL, "key llGetPermissionsKey()\nReturn agent that permissions are enabled for. NULL_KEY if not enabled"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetPermissions", "i", NULL, "integer llGetPermissions()\nreturn what permissions have been enabled"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetLinkNumber", "i", NULL, "integer llGetLinkNumber()\nReturns what number in a link set the script is attached to (0 means no link, 1 the root, 2 for first child, &c)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetLinkColor", NULL, "ivi", "llSetLinkColor(integer linknumber, vector color, integer face)\nIf a task exists in the link chain at linknumber, set face to color"));
- addFunction(new LLScriptLibraryFunction(10.f, 1.f, dummy_func, "llCreateLink", NULL, "ki", "llCreateLink(key target, integer parent)\nAttempt to link task script is attached to and target (requires permission PERMISSION_CHANGE_LINKS be set). If parent == TRUE, task script is attached to is the root"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llBreakLink", NULL, "i", "llBreakLink(integer linknum)\nDelinks the task with the given link number (requires permission PERMISSION_CHANGE_LINKS be set)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llBreakAllLinks", NULL, NULL, "llBreakAllLinks()\nDelinks all tasks in the link set (requires permission PERMISSION_CHANGE_LINKS be set)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetLinkKey", "k", "i", "key llGetLinkKey(integer linknum)\nGet the key of linknumber in link set"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetLinkName", "s", "i", "string llGetLinkName(integer linknum)\nGet the name of linknumber in link set"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetInventoryNumber", "i", "i", "integer llGetInventoryNumber(integer type)\nGet the number of items of a given type in the task's inventory.\nValid types: INVENTORY_TEXTURE, INVENTORY_SOUND, INVENTORY_OBJECT, INVENTORY_SCRIPT, INVENTORY_CLOTHING, INVENTORY_BODYPART, INVENTORY_NOTECARD, INVENTORY_LANDMARK, INVENTORY_ALL"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetInventoryName", "s", "ii", "string llGetInventoryName(integer type, integer number)\nGet the name of the inventory item number of type"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetScriptState", NULL, "si", "llSetScriptState(string name, integer run)\nControl the state of a script name."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetEnergy", "f", NULL, "float llGetEnergy()\nReturns how much energy is in the object as a percentage of maximum"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGiveInventory", NULL, "ks", "llGiveInventory(key destination, string inventory)\nGive inventory to destination"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llRemoveInventory", NULL, "s", "llRemoveInventory(string inventory)\nRemove the named inventory item"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetText", NULL, "svf", "llSetText(string text, vector color, float alpha)\nSet text floating over object"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llWater", "f", "v", "float llWater(vector v)\nreturns the water height below the object position + v"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llPassTouches", NULL, "i", "llPassTouches(integer pass)\nif pass == TRUE, touches are passed from children on to parents (default is FALSE)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.1f, dummy_func, "llRequestAgentData", "k", "ki", "key llRequestAgentData(key id, integer data)\nRequests data about agent id. When data is available the dataserver event will be raised"));
- addFunction(new LLScriptLibraryFunction(10.f, 1.f, dummy_func, "llRequestInventoryData", "k", "s", "key llRequestInventoryData(string name)\nRequests data from object's inventory object. When data is available the dataserver event will be raised"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetDamage", NULL, "f", "llSetDamage(float damage)\nSets the amount of damage that will be done to an object that this task hits. Task will be killed."));
- addFunction(new LLScriptLibraryFunction(100.f, 5.f, dummy_func, "llTeleportAgentHome", NULL, "k", "llTeleportAgentHome(key id)\nTeleports agent on owner's land to agent's home location"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llModifyLand", NULL, "ii", "llModifyLand(integer action, integer size)\nModify land with action (LAND_LEVEL, LAND_RAISE, LAND_LOWER, LAND_SMOOTH, LAND_NOISE, LAND_REVERT)\non size (LAND_SMALL_BRUSH, LAND_MEDIUM_BRUSH, LAND_LARGE_BRUSH)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llCollisionSound", NULL, "sf", "llCollisionSound(string impact_sound, float impact_volume)\nSuppress default collision sounds, replace default impact sounds with impact_sound (empty string to just suppress)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llCollisionSprite", NULL, "s", "llCollisionSprite(string impact_sprite)\nSuppress default collision sprites, replace default impact sprite with impact_sprite (empty string to just suppress)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetAnimation", "s", "k", "string llGetAnimation(key id)\nGet the currently playing locomotion animation for avatar id"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llResetScript", NULL, NULL, "llResetScript()\nResets the script"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llMessageLinked", NULL, "iisk", "llMessageLinked(integer linknum, integer num, string str, key id)\nSends num, str, and id to members of the link set (LINK_ROOT sends to root task in a linked set,\nLINK_SET sends to all tasks,\nLINK_ALL_OTHERS to all other tasks,\nLINK_ALL_CHILDREN to all children,\nLINK_THIS to the task the script it is in)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llPushObject", NULL, "kvvi", "llPushObject(key id, vector impulse, vector ang_impulse, integer local)\nApplies impulse and ang_impulse to object id"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llPassCollisions", NULL, "i", "llPassCollisions(integer pass)\nif pass == TRUE, collisions are passed from children on to parents (default is FALSE)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetScriptName", "s", NULL, "llGetScriptName()\nReturns the script name"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetNumberOfSides", "i", NULL, "integer llGetNumberOfSides()\nReturns the number of sides"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llAxisAngle2Rot", "q", "vf", "rotation llAxisAngle2Rot(vector axis, float angle)\nReturns the rotation generated angle about axis"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llRot2Axis", "v", "q", "vector llRot2Axis(rotation rot)\nReturns the rotation axis represented by rot"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llRot2Angle", "f", "q", "float llRot2Angle(rotation rot)\nReturns the rotation angle represented by rot"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llAcos", "f", "f", "float llAcos(float val)\nReturns the arccosine in radians of val"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llAsin", "f", "f", "float llAsin(float val)\nReturns the arcsine in radians of val"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llAngleBetween", "f", "qq", "float llAngleBetween(rotation a, rotation b)\nReturns angle between rotation a and b"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetInventoryKey", "k", "s", "key llGetInventoryKey(string name)\nReturns the key of the inventory name"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llAllowInventoryDrop", NULL, "i", "llAllowInventoryDrop(integer add)\nIf add == TRUE, users without permissions can still drop inventory items onto task"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetSunDirection", "v", NULL, "vector llGetSunDirection()\nReturns the sun direction on the simulator"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetTextureOffset", "v", "i", "vector llGetTextureOffset(integer side)\nReturns the texture offset of side in the x and y components of a vector"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetTextureScale", "v", "i", "vector llGetTextureScale(integer side)\nReturns the texture scale of side in the x and y components of a vector"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetTextureRot", "f", "i", "float llGetTextureRot(integer side)\nReturns the texture rotation of side"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSubStringIndex", "i", "ss", "integer llSubStringIndex(string source, string pattern)\nFinds index in source where pattern first appears (returns -1 if not found)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetOwnerKey", "k", "k", "key llGetOwnerKey(key id)\nFind the owner of id"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetCenterOfMass", "v", NULL, "vector llGetCenterOfMass()\nGet the object's center of mass"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llListSort", "l", "lii", "list llListSort(list src, integer stride, integer ascending)\nSort the list into blocks of stride in ascending order if ascending == TRUE. Note that sort only works between same types."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetListLength", "i", "l", "integer llGetListLength(list src)\nGet the number of elements in the list"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llList2Integer", "i", "li", "integer llList2Integer(list src, integer index)\nCopy the integer at index in the list"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llList2Float", "f", "li", "float llList2Float(list src, integer index)\nCopy the float at index in the list"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llList2String", "s", "li", "string llList2String(list src, integer index)\nCopy the string at index in the list"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llList2Key", "k", "li", "key llList2Key(list src, integer index)\nCopy the key at index in the list"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llList2Vector", "v", "li", "vector llList2Vector(list src, integer index)\nCopy the vector at index in the list"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llList2Rot", "q", "li", "rotation llList2Rot(list src, integer index)\nCopy the rotation at index in the list"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llList2List", "l", "lii", "list llList2List(list src, integer start, integer end)\nCopy the slice of the list from start to end"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDeleteSubList", "l", "lii", "list llDeleteSubList(list src, integer start, integer end)\nRemove the slice from the list and return the remainder"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetListEntryType", "i", "li", "integer llGetListEntryType(list src, integer index)\nReturns the type of the index entry in the list\n(TYPE_INTEGER, TYPE_FLOAT, TYPE_STRING, TYPE_KEY, TYPE_VECTOR, TYPE_ROTATION, or TYPE_INVALID if index is off list)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llList2CSV", "s", "l", "string llList2CSV(list src)\nCreate a string of comma separated values from list"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llCSV2List", "l", "s", "list llCSV2List(string src)\nCreate a list from a string of comma separated values"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llListRandomize", "l", "li", "list llListRandomize(list src, integer stride)\nReturns a randomized list of blocks of size stride"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llList2ListStrided", "l", "liii", "list llList2ListStrided(list src, integer start, integer end, integer stride)\nCopy the strided slice of the list from start to end"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetRegionCorner", "v", NULL, "vector llGetRegionCorner()\nReturns a vector with the south west corner x,y position of the region the object is in"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llListInsertList", "l", "lli", "list llListInsertList(list dest, list src, integer start)\nInserts src into dest at position start"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llListFindList", "i", "ll", "integer llListFindList(list src, list test)\nReturns the start of the first instance of test in src, -1 if not found"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetObjectName", "s", NULL, "string llGetObjectName()\nReturns the name of the object script is attached to"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetObjectName", NULL, "s", "llSetObjectName(string name)\nSets the objects name"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetDate", "s", NULL, "string llGetDate()\nGets the date as YYYY-MM-DD"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llEdgeOfWorld", "i", "vv", "integer llEdgeOfWorld(vector pos, vector dir)\nChecks to see whether the border hit by dir from pos is the edge of the world (has no neighboring simulator)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetAgentInfo", "i", "k", "integer llGetAgentInfo(key id)\nGets information about agent ID.\nReturns AGENT_FLYING, AGENT_ATTACHMENTS, AGENT_SCRIPTED, AGENT_SITTING, AGENT_ON_OBJECT, AGENT_MOUSELOOK, AGENT_AWAY, AGENT_BUSY, AGENT_TYPING, AGENT_CROUCHING, AGENT_ALWAYS_RUN, AGENT_WALKING and/or AGENT_IN_AIR."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.1f, dummy_func, "llAdjustSoundVolume", NULL, "f", "llAdjustSoundVolume(float volume)\nadjusts volume of attached sound (0.0 - 1.0)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetSoundQueueing", NULL, "i", "llSetSoundQueueing(integer queue)\ndetermines whether attached sound calls wait for the current sound to finish (0 = no [default], nonzero = yes)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetSoundRadius", NULL, "f", "llSetSoundRadius(float radius)\nestablishes a hard cut-off radius for audibility of scripted sounds (both attached and triggered)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llKey2Name", "s", "k", "string llKey2Name(key id)\nReturns the name of the object key, iff the object is in the current simulator, otherwise the empty string"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetTextureAnim", NULL, "iiiifff", "llSetTextureAnim(integer mode, integer face, integer sizex, integer sizey, float start, float length, float rate)\nAnimate the texture on the specified face/faces"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llTriggerSoundLimited", NULL, "sfvv", "llTriggerSoundLimited(string sound, float volume, vector tne, vector bsw)\nplays sound at volume (0.0 - 1.0), centered at but not attached to object, limited to AABB defined by vectors top-north-east and bottom-south-west"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llEjectFromLand", NULL, "k", "llEjectFromLand(key pest)\nEjects pest from land that you own"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llParseString2List", "l", "sll", "list llParseString2List(string src, list separators, list spacers)\nBreaks src into a list, discarding separators, keeping spacers (separators and spacers must be lists of strings, maximum of 8 each)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llOverMyLand", "i", "k", "integer llOverMyLand(key id)\nReturns TRUE if id is over land owner of object owns, FALSE otherwise"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetLandOwnerAt", "k", "v", "key llGetLandOwnerAt(vector pos)\nReturns the key of the land owner, NULL_KEY if public"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.1f, dummy_func, "llGetNotecardLine", "k", "si", "key llGetNotecardLine(string name, integer line)\nReturns line line of notecard name via the dataserver event"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetAgentSize", "v", "k", "vector llGetAgentSize(key id)\nIf the agent is in the same sim as the object, returns the size of the avatar"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSameGroup", "i", "k", "integer llSameGroup(key id)\nReturns TRUE if ID is in the same sim and has the same active group, otherwise FALSE"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llUnSit", NULL, "k", "key llUnSit(key id)\nIf agent identified by id is sitting on the object the script is attached to or is over land owned by the objects owner, the agent is forced to stand up"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGroundSlope", "v", "v", "vector llGroundSlope(vector v)\nreturns the ground slope below the object position + v"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGroundNormal", "v", "v", "vector llGroundNormal(vector v)\nreturns the ground normal below the object position + v"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGroundContour", "v", "v", "vector llGroundCountour(vector v)\nreturns the ground contour below the object position + v"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetAttached", "i", NULL, "integer llGetAttached()\nreturns the object attachment point or 0 if not attached"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetFreeMemory", "i", NULL, "integer llGetFreeMemory()\nreturns the available heap space for the current script"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetRegionName", "s", NULL, "string llGetRegionName()\nreturns the current region name"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetRegionTimeDilation", "f", NULL, "float llGetRegionTimeDilation()\nreturns the current time dilation as a float between 0 and 1"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetRegionFPS", "f", NULL, "float llGetRegionFPS()\nreturns the mean region frames per second"));
-
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llParticleSystem", NULL, "l", "llParticleSystem(list rules)\nCreates a particle system based on rules. Empty list removes particle system from object.\nList format is [ rule1, data1, rule2, data2 . . . rulen, datan ]"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGroundRepel", NULL, "fif", "llGroundRepel(float height, integer water, float tau)\nCritically damps to height if within height*0.5 of level (either above ground level or above the higher of land and water if water == TRUE)"));
- addFunction(new LLScriptLibraryFunction(10.f, 3.f, dummy_func, "llGiveInventoryList", NULL, "ksl", "llGiveInventoryList(key destination, string category, list inventory)\nGive inventory to destination in a new category"));
+ // energy, sleep, dummy_func, name, return type, parameters, gods-only
+ addFunction(10.f, 0.f, dummy_func, "llSin", "f", "f");
+ addFunction(10.f, 0.f, dummy_func, "llCos", "f", "f");
+ addFunction(10.f, 0.f, dummy_func, "llTan", "f", "f");
+ addFunction(10.f, 0.f, dummy_func, "llAtan2", "f", "ff");
+ addFunction(10.f, 0.f, dummy_func, "llSqrt", "f", "f");
+ addFunction(10.f, 0.f, dummy_func, "llPow", "f", "ff");
+ addFunction(10.f, 0.f, dummy_func, "llAbs", "i", "i");
+ addFunction(10.f, 0.f, dummy_func, "llFabs", "f", "f");
+ addFunction(10.f, 0.f, dummy_func, "llFrand", "f", "f");
+ addFunction(10.f, 0.f, dummy_func, "llFloor", "i", "f");
+ addFunction(10.f, 0.f, dummy_func, "llCeil", "i", "f");
+ addFunction(10.f, 0.f, dummy_func, "llRound", "i", "f");
+ addFunction(10.f, 0.f, dummy_func, "llVecMag", "f", "v");
+ addFunction(10.f, 0.f, dummy_func, "llVecNorm", "v", "v");
+ addFunction(10.f, 0.f, dummy_func, "llVecDist", "f", "vv");
+ addFunction(10.f, 0.f, dummy_func, "llRot2Euler", "v", "q");
+ addFunction(10.f, 0.f, dummy_func, "llEuler2Rot", "q", "v");
+ addFunction(10.f, 0.f, dummy_func, "llAxes2Rot", "q", "vvv");
+ addFunction(10.f, 0.f, dummy_func, "llRot2Fwd", "v", "q");
+ addFunction(10.f, 0.f, dummy_func, "llRot2Left", "v", "q");
+ addFunction(10.f, 0.f, dummy_func, "llRot2Up", "v", "q");
+ addFunction(10.f, 0.f, dummy_func, "llRotBetween", "q", "vv");
+ addFunction(10.f, 0.f, dummy_func, "llWhisper", NULL, "is");
+ addFunction(10.f, 0.f, dummy_func, "llSay", NULL, "is");
+ addFunction(10.f, 0.f, dummy_func, "llShout", NULL, "is");
+ addFunction(10.f, 0.f, dummy_func, "llListen", "i", "isks");
+ addFunction(10.f, 0.f, dummy_func, "llListenControl", NULL, "ii");
+ addFunction(10.f, 0.f, dummy_func, "llListenRemove", NULL, "i");
+ addFunction(10.f, 0.f, dummy_func, "llSensor", NULL, "skiff");
+ addFunction(10.f, 0.f, dummy_func, "llSensorRepeat", NULL, "skifff");
+ addFunction(10.f, 0.f, dummy_func, "llSensorRemove", NULL, NULL);
+ addFunction(10.f, 0.f, dummy_func, "llDetectedName", "s", "i");
+ addFunction(10.f, 0.f, dummy_func, "llDetectedKey", "k", "i");
+ addFunction(10.f, 0.f, dummy_func, "llDetectedOwner", "k", "i");
+ addFunction(10.f, 0.f, dummy_func, "llDetectedType", "i", "i");
+ addFunction(10.f, 0.f, dummy_func, "llDetectedPos", "v", "i");
+ addFunction(10.f, 0.f, dummy_func, "llDetectedVel", "v", "i");
+ addFunction(10.f, 0.f, dummy_func, "llDetectedGrab", "v", "i");
+ addFunction(10.f, 0.f, dummy_func, "llDetectedRot", "q", "i");
+ addFunction(10.f, 0.f, dummy_func, "llDetectedGroup", "i", "i");
+ addFunction(10.f, 0.f, dummy_func, "llDetectedLinkNumber", "i", "i");
+ addFunction(0.f, 0.f, dummy_func, "llDie", NULL, NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGround", "f", "v");
+ addFunction(10.f, 0.f, dummy_func, "llCloud", "f", "v");
+ addFunction(10.f, 0.f, dummy_func, "llWind", "v", "v");
+ addFunction(10.f, 0.f, dummy_func, "llSetStatus", NULL, "ii");
+ addFunction(10.f, 0.f, dummy_func, "llGetStatus", "i", "i");
+ addFunction(10.f, 0.f, dummy_func, "llSetScale", NULL, "v");
+ addFunction(10.f, 0.f, dummy_func, "llGetScale", "v", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llSetColor", NULL, "vi");
+ addFunction(10.f, 0.f, dummy_func, "llGetAlpha", "f", "i");
+ addFunction(10.f, 0.f, dummy_func, "llSetAlpha", NULL, "fi");
+ addFunction(10.f, 0.f, dummy_func, "llGetColor", "v", "i");
+ addFunction(10.f, 0.2f, dummy_func, "llSetTexture", NULL, "si");
+ addFunction(10.f, 0.2f, dummy_func, "llScaleTexture", NULL, "ffi");
+ addFunction(10.f, 0.2f, dummy_func, "llOffsetTexture", NULL, "ffi");
+ addFunction(10.f, 0.2f, dummy_func, "llRotateTexture", NULL, "fi");
+ addFunction(10.f, 0.f, dummy_func, "llGetTexture", "s", "i");
+ addFunction(10.f, 0.2f, dummy_func, "llSetPos", NULL, "v");
+ addFunction(10.f, 0.f, dummy_func, "llGetPos", "v", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGetLocalPos", "v", NULL);
+ addFunction(10.f, 0.2f, dummy_func, "llSetRot", NULL, "q");
+ addFunction(10.f, 0.f, dummy_func, "llGetRot", "q", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGetLocalRot", "q", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llSetForce", NULL, "vi");
+ addFunction(10.f, 0.f, dummy_func, "llGetForce", "v", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llTarget", "i", "vf");
+ addFunction(10.f, 0.f, dummy_func, "llTargetRemove", NULL, "i");
+ addFunction(10.f, 0.f, dummy_func, "llRotTarget", "i", "qf");
+ addFunction(10.f, 0.f, dummy_func, "llRotTargetRemove", NULL, "i");
+ addFunction(10.f, 0.f, dummy_func, "llMoveToTarget", NULL, "vf");
+ addFunction(10.f, 0.f, dummy_func, "llStopMoveToTarget", NULL, NULL);
+ addFunction(10.f, 0.f, dummy_func, "llApplyImpulse", NULL, "vi");
+ addFunction(10.f, 0.f, dummy_func, "llApplyRotationalImpulse", NULL, "vi");
+ addFunction(10.f, 0.f, dummy_func, "llSetTorque", NULL, "vi");
+ addFunction(10.f, 0.f, dummy_func, "llGetTorque", "v", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llSetForceAndTorque", NULL, "vvi");
+ addFunction(10.f, 0.f, dummy_func, "llGetVel", "v", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGetAccel", "v", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGetOmega", "v", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGetTimeOfDay", "f", "");
+ addFunction(10.f, 0.f, dummy_func, "llGetWallclock", "f", "");
+ addFunction(10.f, 0.f, dummy_func, "llGetTime", "f", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llResetTime", NULL, NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGetAndResetTime", "f", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llSound", NULL, "sfii");
+ addFunction(10.f, 0.f, dummy_func, "llPlaySound", NULL, "sf");
+ addFunction(10.f, 0.f, dummy_func, "llLoopSound", NULL, "sf");
+ addFunction(10.f, 0.f, dummy_func, "llLoopSoundMaster", NULL, "sf");
+ addFunction(10.f, 0.f, dummy_func, "llLoopSoundSlave", NULL, "sf");
+ addFunction(10.f, 0.f, dummy_func, "llPlaySoundSlave", NULL, "sf");
+ addFunction(10.f, 0.f, dummy_func, "llTriggerSound", NULL, "sf");
+ addFunction(10.f, 0.f, dummy_func, "llStopSound", NULL, "");
+ addFunction(10.f, 1.f, dummy_func, "llPreloadSound", NULL, "s");
+ addFunction(10.f, 0.f, dummy_func, "llGetSubString", "s", "sii");
+ addFunction(10.f, 0.f, dummy_func, "llDeleteSubString", "s", "sii");
+ addFunction(10.f, 0.f, dummy_func, "llInsertString", "s", "sis");
+ addFunction(10.f, 0.f, dummy_func, "llToUpper", "s", "s");
+ addFunction(10.f, 0.f, dummy_func, "llToLower", "s", "s");
+ addFunction(10.f, 0.f, dummy_func, "llGiveMoney", "i", "ki");
+ addFunction(10.f, 0.1f, dummy_func, "llMakeExplosion", NULL, "iffffsv");
+ addFunction(10.f, 0.1f, dummy_func, "llMakeFountain", NULL, "iffffisvf");
+ addFunction(10.f, 0.1f, dummy_func, "llMakeSmoke", NULL, "iffffsv");
+ addFunction(10.f, 0.1f, dummy_func, "llMakeFire", NULL, "iffffsv");
+ addFunction(200.f, 0.1f, dummy_func, "llRezObject", NULL, "svvqi");
+ addFunction(10.f, 0.f, dummy_func, "llLookAt", NULL, "vff");
+ addFunction(10.f, 0.f, dummy_func, "llStopLookAt", NULL, NULL);
+ addFunction(10.f, 0.f, dummy_func, "llSetTimerEvent", NULL, "f");
+ addFunction(0.f, 0.f, dummy_func, "llSleep", NULL, "f");
+ addFunction(10.f, 0.f, dummy_func, "llGetMass", "f", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llCollisionFilter", NULL, "ski");
+ addFunction(10.f, 0.f, dummy_func, "llTakeControls", NULL, "iii");
+ addFunction(10.f, 0.f, dummy_func, "llReleaseControls", NULL, NULL);
+ addFunction(10.f, 0.f, dummy_func, "llAttachToAvatar", NULL, "i");
+ addFunction(10.f, 0.f, dummy_func, "llDetachFromAvatar", NULL, NULL);
+ addFunction(10.f, 0.f, dummy_func, "llTakeCamera", NULL, "k");
+ addFunction(10.f, 0.f, dummy_func, "llReleaseCamera", NULL, "k");
+ addFunction(10.f, 0.f, dummy_func, "llGetOwner", "k", NULL);
+ addFunction(10.f, 2.f, dummy_func, "llInstantMessage", NULL, "ks");
+ addFunction(10.f, 20.f, dummy_func, "llEmail", NULL, "sss");
+ addFunction(10.f, 0.f, dummy_func, "llGetNextEmail", NULL, "ss");
+ addFunction(10.f, 0.f, dummy_func, "llGetKey", "k", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llSetBuoyancy", NULL, "f");
+ addFunction(10.f, 0.f, dummy_func, "llSetHoverHeight", NULL, "fif");
+ addFunction(10.f, 0.f, dummy_func, "llStopHover", NULL, NULL);
+ addFunction(10.f, 0.f, dummy_func, "llMinEventDelay", NULL, "f");
+ addFunction(10.f, 0.f, dummy_func, "llSoundPreload", NULL, "s");
+ addFunction(10.f, 0.f, dummy_func, "llRotLookAt", NULL, "qff");
+ addFunction(10.f, 0.f, dummy_func, "llStringLength", "i", "s");
+ addFunction(10.f, 0.f, dummy_func, "llStartAnimation", NULL, "s");
+ addFunction(10.f, 0.f, dummy_func, "llStopAnimation", NULL, "s");
+ addFunction(10.f, 0.f, dummy_func, "llPointAt", NULL, "v");
+ addFunction(10.f, 0.f, dummy_func, "llStopPointAt", NULL, NULL);
+ addFunction(10.f, 0.f, dummy_func, "llTargetOmega", NULL, "vff");
+ addFunction(10.f, 0.f, dummy_func, "llGetStartParameter", "i", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGodLikeRezObject", NULL, "kv", TRUE);
+ addFunction(10.f, 0.f, dummy_func, "llRequestPermissions", NULL, "ki");
+ addFunction(10.f, 0.f, dummy_func, "llGetPermissionsKey", "k", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGetPermissions", "i", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGetLinkNumber", "i", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llSetLinkColor", NULL, "ivi");
+ addFunction(10.f, 1.f, dummy_func, "llCreateLink", NULL, "ki");
+ addFunction(10.f, 0.f, dummy_func, "llBreakLink", NULL, "i");
+ addFunction(10.f, 0.f, dummy_func, "llBreakAllLinks", NULL, NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGetLinkKey", "k", "i");
+ addFunction(10.f, 0.f, dummy_func, "llGetLinkName", "s", "i");
+ addFunction(10.f, 0.f, dummy_func, "llGetInventoryNumber", "i", "i");
+ addFunction(10.f, 0.f, dummy_func, "llGetInventoryName", "s", "ii");
+ addFunction(10.f, 0.f, dummy_func, "llSetScriptState", NULL, "si");
+ addFunction(10.f, 0.f, dummy_func, "llGetEnergy", "f", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGiveInventory", NULL, "ks");
+ addFunction(10.f, 0.f, dummy_func, "llRemoveInventory", NULL, "s");
+ addFunction(10.f, 0.f, dummy_func, "llSetText", NULL, "svf");
+ addFunction(10.f, 0.f, dummy_func, "llWater", "f", "v");
+ addFunction(10.f, 0.f, dummy_func, "llPassTouches", NULL, "i");
+ addFunction(10.f, 0.1f, dummy_func, "llRequestAgentData", "k", "ki");
+ addFunction(10.f, 1.f, dummy_func, "llRequestInventoryData", "k", "s");
+ addFunction(10.f, 0.f, dummy_func, "llSetDamage", NULL, "f");
+ addFunction(100.f, 5.f, dummy_func, "llTeleportAgentHome", NULL, "k");
+ addFunction(10.f, 0.f, dummy_func, "llModifyLand", NULL, "ii");
+ addFunction(10.f, 0.f, dummy_func, "llCollisionSound", NULL, "sf");
+ addFunction(10.f, 0.f, dummy_func, "llCollisionSprite", NULL, "s");
+ addFunction(10.f, 0.f, dummy_func, "llGetAnimation", "s", "k");
+ addFunction(10.f, 0.f, dummy_func, "llResetScript", NULL, NULL);
+ addFunction(10.f, 0.f, dummy_func, "llMessageLinked", NULL, "iisk");
+ addFunction(10.f, 0.f, dummy_func, "llPushObject", NULL, "kvvi");
+ addFunction(10.f, 0.f, dummy_func, "llPassCollisions", NULL, "i");
+ addFunction(10.f, 0.f, dummy_func, "llGetScriptName", "s", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGetNumberOfSides", "i", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llAxisAngle2Rot", "q", "vf");
+ addFunction(10.f, 0.f, dummy_func, "llRot2Axis", "v", "q");
+ addFunction(10.f, 0.f, dummy_func, "llRot2Angle", "f", "q");
+ addFunction(10.f, 0.f, dummy_func, "llAcos", "f", "f");
+ addFunction(10.f, 0.f, dummy_func, "llAsin", "f", "f");
+ addFunction(10.f, 0.f, dummy_func, "llAngleBetween", "f", "qq");
+ addFunction(10.f, 0.f, dummy_func, "llGetInventoryKey", "k", "s");
+ addFunction(10.f, 0.f, dummy_func, "llAllowInventoryDrop", NULL, "i");
+ addFunction(10.f, 0.f, dummy_func, "llGetSunDirection", "v", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGetTextureOffset", "v", "i");
+ addFunction(10.f, 0.f, dummy_func, "llGetTextureScale", "v", "i");
+ addFunction(10.f, 0.f, dummy_func, "llGetTextureRot", "f", "i");
+ addFunction(10.f, 0.f, dummy_func, "llSubStringIndex", "i", "ss");
+ addFunction(10.f, 0.f, dummy_func, "llGetOwnerKey", "k", "k");
+ addFunction(10.f, 0.f, dummy_func, "llGetCenterOfMass", "v", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llListSort", "l", "lii");
+ addFunction(10.f, 0.f, dummy_func, "llGetListLength", "i", "l");
+ addFunction(10.f, 0.f, dummy_func, "llList2Integer", "i", "li");
+ addFunction(10.f, 0.f, dummy_func, "llList2Float", "f", "li");
+ addFunction(10.f, 0.f, dummy_func, "llList2String", "s", "li");
+ addFunction(10.f, 0.f, dummy_func, "llList2Key", "k", "li");
+ addFunction(10.f, 0.f, dummy_func, "llList2Vector", "v", "li");
+ addFunction(10.f, 0.f, dummy_func, "llList2Rot", "q", "li");
+ addFunction(10.f, 0.f, dummy_func, "llList2List", "l", "lii");
+ addFunction(10.f, 0.f, dummy_func, "llDeleteSubList", "l", "lii");
+ addFunction(10.f, 0.f, dummy_func, "llGetListEntryType", "i", "li");
+ addFunction(10.f, 0.f, dummy_func, "llList2CSV", "s", "l");
+ addFunction(10.f, 0.f, dummy_func, "llCSV2List", "l", "s");
+ addFunction(10.f, 0.f, dummy_func, "llListRandomize", "l", "li");
+ addFunction(10.f, 0.f, dummy_func, "llList2ListStrided", "l", "liii");
+ addFunction(10.f, 0.f, dummy_func, "llGetRegionCorner", "v", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llListInsertList", "l", "lli");
+ addFunction(10.f, 0.f, dummy_func, "llListFindList", "i", "ll");
+ addFunction(10.f, 0.f, dummy_func, "llGetObjectName", "s", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llSetObjectName", NULL, "s");
+ addFunction(10.f, 0.f, dummy_func, "llGetDate", "s", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llEdgeOfWorld", "i", "vv");
+ addFunction(10.f, 0.f, dummy_func, "llGetAgentInfo", "i", "k");
+ addFunction(10.f, 0.1f, dummy_func, "llAdjustSoundVolume", NULL, "f");
+ addFunction(10.f, 0.f, dummy_func, "llSetSoundQueueing", NULL, "i");
+ addFunction(10.f, 0.f, dummy_func, "llSetSoundRadius", NULL, "f");
+ addFunction(10.f, 0.f, dummy_func, "llKey2Name", "s", "k");
+ addFunction(10.f, 0.f, dummy_func, "llSetTextureAnim", NULL, "iiiifff");
+ addFunction(10.f, 0.f, dummy_func, "llTriggerSoundLimited", NULL, "sfvv");
+ addFunction(10.f, 0.f, dummy_func, "llEjectFromLand", NULL, "k");
+ addFunction(10.f, 0.f, dummy_func, "llParseString2List", "l", "sll");
+ addFunction(10.f, 0.f, dummy_func, "llOverMyLand", "i", "k");
+ addFunction(10.f, 0.f, dummy_func, "llGetLandOwnerAt", "k", "v");
+ addFunction(10.f, 0.1f, dummy_func, "llGetNotecardLine", "k", "si");
+ addFunction(10.f, 0.f, dummy_func, "llGetAgentSize", "v", "k");
+ addFunction(10.f, 0.f, dummy_func, "llSameGroup", "i", "k");
+ addFunction(10.f, 0.f, dummy_func, "llUnSit", NULL, "k");
+ addFunction(10.f, 0.f, dummy_func, "llGroundSlope", "v", "v");
+ addFunction(10.f, 0.f, dummy_func, "llGroundNormal", "v", "v");
+ addFunction(10.f, 0.f, dummy_func, "llGroundContour", "v", "v");
+ addFunction(10.f, 0.f, dummy_func, "llGetAttached", "i", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGetFreeMemory", "i", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGetRegionName", "s", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGetRegionTimeDilation", "f", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGetRegionFPS", "f", NULL);
+
+ addFunction(10.f, 0.f, dummy_func, "llParticleSystem", NULL, "l");
+ addFunction(10.f, 0.f, dummy_func, "llGroundRepel", NULL, "fif");
+ addFunction(10.f, 3.f, dummy_func, "llGiveInventoryList", NULL, "ksl");
// script calls for vehicle action
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetVehicleType", NULL, "i", "llSetVehicleType(integer type)\nsets vehicle to one of the default types"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetVehicleFloatParam", NULL, "if", "llSetVehicleFloatParam(integer param, float value)\nsets the specified vehicle float parameter"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetVehicleVectorParam", NULL, "iv", "llSetVehicleVectorParam(integer param, vector vec)\nsets the specified vehicle vector parameter"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetVehicleRotationParam", NULL, "iq", "llSetVehicleVectorParam(integer param, rotation rot)\nsets the specified vehicle rotation parameter"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetVehicleFlags", NULL, "i", "llSetVehicleFlags(integer flags)\nsets the enabled bits in 'flags'"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llRemoveVehicleFlags", NULL, "i", "llRemoveVehicleFlags(integer flags)\nremoves the enabled bits in 'flags'"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSitTarget", NULL, "vq", "llSitTarget(vector offset, rotation rot)\nSet the sit location for this object (if offset == <0,0,0> clear it)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llAvatarOnSitTarget", "k", NULL, "key llAvatarOnSitTarget()\nIf an avatar is sitting on the sit target, return the avatar's key, NULL_KEY otherwise"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.1f, dummy_func, "llAddToLandPassList", NULL, "kf", "llAddToLandPassList(key avatar, float hours)\nAdd avatar to the land pass list for hours"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetTouchText", NULL, "s", "llSetTouchText(string text)\nDisplays text in pie menu that acts as a touch"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetSitText", NULL, "s", "llSetSitText(string text)\nDisplays text rather than sit in pie menu"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetCameraEyeOffset", NULL, "v", "llSetCameraEyeOffset(vector offset)\nSets the camera eye offset used in this object if an avatar sits on it"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetCameraAtOffset", NULL, "v", "llSetCameraAtOffset(vector offset)\nSets the camera at offset used in this object if an avatar sits on it"));
-
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDumpList2String", "s", "ls", "string llDumpList2String(list src, string separator)\nWrite the list out in a single string using separator between values"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llScriptDanger", "i", "v", "integer llScriptDanger(vector pos)\nReturns true if pos is over public land, sandbox land, land that doesn't allow everyone to edit and build, or land that doesn't allow outside scripts"));
- addFunction(new LLScriptLibraryFunction(10.f, 1.f, dummy_func, "llDialog", NULL, "ksli", "llDialog(key avatar, string message, list buttons, integer chat_channel\nShows a dialog box on the avatar's screen with the message.\nUp to 12 strings in the list form buttons.\nIf a button is clicked, the name is chatted on chat_channel."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llVolumeDetect", NULL, "i", "llVolumeDetect(integer detect)\nIf detect = TRUE, object becomes phantom but triggers collision_start and collision_end events\nwhen other objects start and stop interpenetrating.\nMust be applied to the root object."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llResetOtherScript", NULL, "s", "llResetOtherScript(string name)\nResets script name"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetScriptState", "i", "s", "integer llGetScriptState(string name)\nResets TRUE if script name is running"));
- addFunction(new LLScriptLibraryFunction(10.f, 3.f, dummy_func, "llRemoteLoadScript", NULL, "ksii", "Deprecated. Please use llRemoteLoadScriptPin instead."));
-
- addFunction(new LLScriptLibraryFunction(10.f, 0.2f, dummy_func, "llSetRemoteScriptAccessPin", NULL, "i", "llSetRemoteScriptAccessPin(integer pin)\nIf pin is set to a non-zero number, the task will accept remote script\nloads via llRemoteLoadScriptPin if it passes in the correct pin.\nOthersise, llRemoteLoadScriptPin is ignored."));
- addFunction(new LLScriptLibraryFunction(10.f, 3.f, dummy_func, "llRemoteLoadScriptPin", NULL, "ksiii", "llRemoteLoadScriptPin(key target, string name, integer pin, integer running, integer start_param)\nIf the owner of the object this script is attached can modify target,\nthey are in the same region,\nand the matching pin is used,\ncopy script name onto target,\nif running == TRUE, start the script with param."));
+ addFunction(10.f, 0.f, dummy_func, "llSetVehicleType", NULL, "i");
+ addFunction(10.f, 0.f, dummy_func, "llSetVehicleFloatParam", NULL, "if");
+ addFunction(10.f, 0.f, dummy_func, "llSetVehicleVectorParam", NULL, "iv");
+ addFunction(10.f, 0.f, dummy_func, "llSetVehicleRotationParam", NULL, "iq");
+ addFunction(10.f, 0.f, dummy_func, "llSetVehicleFlags", NULL, "i");
+ addFunction(10.f, 0.f, dummy_func, "llRemoveVehicleFlags", NULL, "i");
+ addFunction(10.f, 0.f, dummy_func, "llSitTarget", NULL, "vq");
+ addFunction(10.f, 0.f, dummy_func, "llAvatarOnSitTarget", "k", NULL);
+ addFunction(10.f, 0.1f, dummy_func, "llAddToLandPassList", NULL, "kf");
+ addFunction(10.f, 0.f, dummy_func, "llSetTouchText", NULL, "s");
+ addFunction(10.f, 0.f, dummy_func, "llSetSitText", NULL, "s");
+ addFunction(10.f, 0.f, dummy_func, "llSetCameraEyeOffset", NULL, "v");
+ addFunction(10.f, 0.f, dummy_func, "llSetCameraAtOffset", NULL, "v");
+
+ addFunction(10.f, 0.f, dummy_func, "llDumpList2String", "s", "ls");
+ addFunction(10.f, 0.f, dummy_func, "llScriptDanger", "i", "v");
+ addFunction(10.f, 1.f, dummy_func, "llDialog", NULL, "ksli");
+ addFunction(10.f, 0.f, dummy_func, "llVolumeDetect", NULL, "i");
+ addFunction(10.f, 0.f, dummy_func, "llResetOtherScript", NULL, "s");
+ addFunction(10.f, 0.f, dummy_func, "llGetScriptState", "i", "s");
+ addFunction(10.f, 3.f, dummy_func, "llRemoteLoadScript", NULL, "ksii");
+
+ addFunction(10.f, 0.2f, dummy_func, "llSetRemoteScriptAccessPin", NULL, "i");
+ addFunction(10.f, 3.f, dummy_func, "llRemoteLoadScriptPin", NULL, "ksiii");
- addFunction(new LLScriptLibraryFunction(10.f, 1.f, dummy_func, "llOpenRemoteDataChannel", NULL, NULL, "llOpenRemoteDataChannel()\nCreates a channel to listen for XML-RPC calls. Will trigger a remote_data event with channel id once it is available."));
- addFunction(new LLScriptLibraryFunction(10.f, 3.f, dummy_func, "llSendRemoteData", "k", "ksis", "key llSendRemoteData(key channel, string dest, integer idata, string sdata)\nSend an XML-RPC request to dest through channel with payload of channel (in a string), integer idata and string sdata.\nA message identifier key is returned.\nAn XML-RPC reply will trigger a remote_data event and reference the message id.\nThe message_id is returned."));
- addFunction(new LLScriptLibraryFunction(10.f, 3.f, dummy_func, "llRemoteDataReply", NULL, "kksi", "llRemoteDataReply(key channel, key message_id, string sdata, integer idata)\nSend an XML-RPC reply to message_id on channel with payload of string sdata and integer idata"));
- addFunction(new LLScriptLibraryFunction(10.f, 1.f, dummy_func, "llCloseRemoteDataChannel", NULL, "k", "llCloseRemoteDataChannel(key channel)\nCloses XML-RPC channel."));
-
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llMD5String", "s", "si", "string llMD5String(string src, integer nonce)\nPerforms a RSA Data Security, Inc. MD5 Message-Digest Algorithm on string with nonce. Returns a 32 character hex string."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.2f, dummy_func, "llSetPrimitiveParams", NULL, "l", "llSetPrimitiveParams(list rules)\nSet primitive parameters based on rules."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llStringToBase64", "s", "s", "string llStringToBase64(string str)\nConverts a string to the Base 64 representation of the string."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llBase64ToString", "s", "s", "string llBase64ToString(string str)\nConverts a Base 64 string to a conventional string. If the conversion creates any unprintable characters, they are converted to spaces."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.3f, dummy_func, "llXorBase64Strings", "s", "ss", "string llXorBase64Strings(string s1, string s2)\nDEPRECATED! Please use llXorBase64StringsCorrect instead!! Incorrectly performs an exclusive or on two Base 64 strings and returns a Base 64 string. s2 repeats if it is shorter than s1. Retained for backwards compatability."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llRemoteDataSetRegion", NULL, NULL, "llRemoteDataSetRegion()\nIf an object using remote data channels changes regions, you must call this function to reregister the remote data channels.\nYou do not need to make this call if you don't change regions."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llLog10", "f", "f", "float llLog10(float val)\nReturns the base 10 log of val if val > 0, otherwise returns 0."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llLog", "f", "f", "float llLog(float val)\nReturns the base e log of val if val > 0, otherwise returns 0."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetAnimationList", "l", "k", "list llGetAnimationList(key id)\nGets a list of all playing animations for avatar id"));
- addFunction(new LLScriptLibraryFunction(10.f, 2.f, dummy_func, "llSetParcelMusicURL", NULL, "s", "llSetParcelMusicURL(string url)\nSets the streaming audio URL for the parcel object is on"));
+ addFunction(10.f, 1.f, dummy_func, "llOpenRemoteDataChannel", NULL, NULL);
+ addFunction(10.f, 3.f, dummy_func, "llSendRemoteData", "k", "ksis");
+ addFunction(10.f, 3.f, dummy_func, "llRemoteDataReply", NULL, "kksi");
+ addFunction(10.f, 1.f, dummy_func, "llCloseRemoteDataChannel", NULL, "k");
+
+ addFunction(10.f, 0.f, dummy_func, "llMD5String", "s", "si");
+ addFunction(10.f, 0.2f, dummy_func, "llSetPrimitiveParams", NULL, "l");
+ addFunction(10.f, 0.f, dummy_func, "llStringToBase64", "s", "s");
+ addFunction(10.f, 0.f, dummy_func, "llBase64ToString", "s", "s");
+ addFunction(10.f, 0.3f, dummy_func, "llXorBase64Strings", "s", "ss");
+ addFunction(10.f, 0.f, dummy_func, "llRemoteDataSetRegion", NULL, NULL);
+ addFunction(10.f, 0.f, dummy_func, "llLog10", "f", "f");
+ addFunction(10.f, 0.f, dummy_func, "llLog", "f", "f");
+ addFunction(10.f, 0.f, dummy_func, "llGetAnimationList", "l", "k");
+ addFunction(10.f, 2.f, dummy_func, "llSetParcelMusicURL", NULL, "s");
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetRootPosition", "v", NULL, "vector llGetRootPosition()\nGets the global position of the root object of the object script is attached to"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetRootRotation", "q", NULL, "rotation llGetRootRotation()\nGets the global rotation of the root object of the object script is attached to"));
-
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetObjectDesc", "s", NULL, "string llGetObjectDesc()\nReturns the description of the object the script is attached to"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetObjectDesc", NULL, "s", "llSetObjectDesc(string name)\nSets the object's description"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetCreator", "k", NULL, "key llGetCreator()\nReturns the creator of the object"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetTimestamp", "s", NULL, "string llGetTimestamp()\nGets the timestamp in the format: YYYY-MM-DDThh:mm:ss.ff..fZ"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetLinkAlpha", NULL, "ifi", "llSetLinkAlpha(integer linknumber, float alpha, integer face)\nIf a prim exists in the link chain at linknumber, set face to alpha"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetNumberOfPrims", "i", NULL, "integer llGetNumberOfPrims()\nReturns the number of prims in a link set the script is attached to"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.1f, dummy_func, "llGetNumberOfNotecardLines", "k", "s", "key llGetNumberOfNotecardLines(string name)\nReturns number of lines in notecard 'name' via the dataserver event (cast return value to integer)"));
-
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetBoundingBox", "l", "k", "list llGetBoundingBox(key object)\nReturns the bounding box around an object (including any linked prims) relative to the root prim, in a list: [ (vector) min_corner, (vector) max_corner ]"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetGeometricCenter", "v", NULL, "vector llGetGeometricCenter()\nReturns the geometric center of the linked set the script is attached to."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.2f, dummy_func, "llGetPrimitiveParams", "l", "l", "list llGetPrimitiveParams(list params)\nGets primitive parameters specified in the params list."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.0f, dummy_func, "llIntegerToBase64", "s", "i", "string llIntegerToBase64(integer number)\nBig endian encode of of integer as a Base64 string."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.0f, dummy_func, "llBase64ToInteger", "i", "s", "integer llBase64ToInteger(string str)\nBig endian decode of a Base64 string into an integer."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetGMTclock", "f", "", "float llGetGMTclock()\nGets the time in seconds since midnight in GMT"));
- addFunction(new LLScriptLibraryFunction(10.f, 10.f, dummy_func, "llGetSimulatorHostname", "s", "", "string llGetSimulatorHostname()\nGets the hostname of the machine script is running on (same as string in viewer Help dialog)"));
+ addFunction(10.f, 0.f, dummy_func, "llGetRootPosition", "v", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGetRootRotation", "q", NULL);
+
+ addFunction(10.f, 0.f, dummy_func, "llGetObjectDesc", "s", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llSetObjectDesc", NULL, "s");
+ addFunction(10.f, 0.f, dummy_func, "llGetCreator", "k", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGetTimestamp", "s", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llSetLinkAlpha", NULL, "ifi");
+ addFunction(10.f, 0.f, dummy_func, "llGetNumberOfPrims", "i", NULL);
+ addFunction(10.f, 0.1f, dummy_func, "llGetNumberOfNotecardLines", "k", "s");
+
+ addFunction(10.f, 0.f, dummy_func, "llGetBoundingBox", "l", "k");
+ addFunction(10.f, 0.f, dummy_func, "llGetGeometricCenter", "v", NULL);
+ addFunction(10.f, 0.2f, dummy_func, "llGetPrimitiveParams", "l", "l");
+ addFunction(10.f, 0.0f, dummy_func, "llIntegerToBase64", "s", "i");
+ addFunction(10.f, 0.0f, dummy_func, "llBase64ToInteger", "i", "s");
+ addFunction(10.f, 0.f, dummy_func, "llGetGMTclock", "f", "");
+ addFunction(10.f, 10.f, dummy_func, "llGetSimulatorHostname", "s", "");
- addFunction(new LLScriptLibraryFunction(10.f, 0.2f, dummy_func, "llSetLocalRot", NULL, "q", "llSetLocalRot(rotation rot)\nsets the rotation of a child prim relative to the root prim"));
+ addFunction(10.f, 0.2f, dummy_func, "llSetLocalRot", NULL, "q");
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llParseStringKeepNulls", "l", "sll", "list llParseStringKeepNulls(string src, list separators, list spacers)\nBreaks src into a list, discarding separators, keeping spacers (separators and spacers must be lists of strings, maximum of 8 each), keeping any null values generated."));
- addFunction(new LLScriptLibraryFunction(200.f, 0.1f, dummy_func, "llRezAtRoot", NULL, "svvqi", "llRezAtRoot(string inventory, vector pos, vector vel, rotation rot, integer param)\nInstantiate owner's inventory object at pos with velocity vel and rotation rot with start parameter param.\nThe last selected root object's location will be set to pos"));
+ addFunction(10.f, 0.f, dummy_func, "llParseStringKeepNulls", "l", "sll");
+ addFunction(200.f, 0.1f, dummy_func, "llRezAtRoot", NULL, "svvqi");
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetObjectPermMask", "i", "i", "integer llGetObjectPermMask(integer mask)\nReturns the requested permission mask for the root object the task is attached to.", FALSE));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetObjectPermMask", NULL, "ii", "llSetObjectPermMask(integer mask, integer value)\nSets the given permission mask to the new value on the root object the task is attached to.", TRUE));
+ addFunction(10.f, 0.f, dummy_func, "llGetObjectPermMask", "i", "i", FALSE);
+ addFunction(10.f, 0.f, dummy_func, "llSetObjectPermMask", NULL, "ii", TRUE);
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetInventoryPermMask", "i", "si", "integer llGetInventoryPermMask(string item, integer mask)\nReturns the requested permission mask for the inventory item.", FALSE));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetInventoryPermMask", NULL, "sii", "llSetInventoryPermMask(string item, integer mask, integer value)\nSets the given permission mask to the new value on the inventory item.", TRUE));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetInventoryCreator", "k", "s", "key llGetInventoryCreator(string item)\nReturns the key for the creator of the inventory item.", FALSE));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llOwnerSay", NULL, "s", "llOwnerSay(string msg)\nsays msg to owner only (if owner in sim)"));
- addFunction(new LLScriptLibraryFunction(10.f, 1.f, dummy_func, "llRequestSimulatorData", "k", "si", "key llRequestSimulatorData(string simulator, integer data)\nRequests data about simulator. When data is available the dataserver event will be raised"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llForceMouselook", NULL, "i", "llForceMouselook(integer mouselook)\nIf mouselook is TRUE any avatar that sits on this object is forced into mouselook mode"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetObjectMass", "f", "k", "float llGetObjectMass(key id)\nGet the mass of the object with key id"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llListReplaceList", "l", "llii", "list llListReplaceList(list dest, list src, integer start, integer end)\nReplaces start through end of dest with src."));
- addFunction(new LLScriptLibraryFunction(10.f, 10.f, dummy_func, "llLoadURL", NULL, "kss", "llLoadURL(key avatar_id, string message, string url)\nShows dialog to avatar avatar_id offering to load web page at URL. If user clicks yes, launches their web browser."));
+ addFunction(10.f, 0.f, dummy_func, "llGetInventoryPermMask", "i", "si", FALSE);
+ addFunction(10.f, 0.f, dummy_func, "llSetInventoryPermMask", NULL, "sii", TRUE);
+ addFunction(10.f, 0.f, dummy_func, "llGetInventoryCreator", "k", "s", FALSE);
+ addFunction(10.f, 0.f, dummy_func, "llOwnerSay", NULL, "s");
+ addFunction(10.f, 1.f, dummy_func, "llRequestSimulatorData", "k", "si");
+ addFunction(10.f, 0.f, dummy_func, "llForceMouselook", NULL, "i");
+ addFunction(10.f, 0.f, dummy_func, "llGetObjectMass", "f", "k");
+ addFunction(10.f, 0.f, dummy_func, "llListReplaceList", "l", "llii");
+ addFunction(10.f, 10.f, dummy_func, "llLoadURL", NULL, "kss");
- addFunction(new LLScriptLibraryFunction(10.f, 2.f, dummy_func, "llParcelMediaCommandList", NULL, "l", "llParcelMediaCommandList(list command)\nSends a list of commands, some with arguments, to a parcel."));
- addFunction(new LLScriptLibraryFunction(10.f, 2.f, dummy_func, "llParcelMediaQuery", "l", "l", "list llParcelMediaQuery(list query)\nSends a list of queries, returns a list of results."));
+ addFunction(10.f, 2.f, dummy_func, "llParcelMediaCommandList", NULL, "l");
+ addFunction(10.f, 2.f, dummy_func, "llParcelMediaQuery", "l", "l");
- addFunction(new LLScriptLibraryFunction(10.f, 1.f, dummy_func, "llModPow", "i", "iii", "integer llModPow(integer a, integer b, integer c)\nReturns a raised to the b power, mod c. ( (a**b)%c ). b is capped at 0xFFFF (16 bits)."));
+ addFunction(10.f, 1.f, dummy_func, "llModPow", "i", "iii");
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetInventoryType", "i", "s", "integer llGetInventoryType(string name)\nReturns the type of the inventory name"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetPayPrice", NULL, "il", "llSetPayPrice(integer price, list quick_pay_buttons)\nSets the default amount when someone chooses to pay this object."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetCameraPos", "v", "", "vector llGetCameraPos()\nGets current camera position for agent task has permissions for."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetCameraRot", "q", "", "rotation llGetCameraRot()\nGets current camera orientation for agent task has permissions for."));
+ addFunction(10.f, 0.f, dummy_func, "llGetInventoryType", "i", "s");
+ addFunction(10.f, 0.f, dummy_func, "llSetPayPrice", NULL, "il");
+ addFunction(10.f, 0.f, dummy_func, "llGetCameraPos", "v", "");
+ addFunction(10.f, 0.f, dummy_func, "llGetCameraRot", "q", "");
- addFunction(new LLScriptLibraryFunction(10.f, 20.f, dummy_func, "llSetPrimURL", NULL, "s", "llSetPrimURL(string url)\nUpdates the URL for the web page shown on the sides of the object."));
- addFunction(new LLScriptLibraryFunction(10.f, 20.f, dummy_func, "llRefreshPrimURL", NULL, "", "llRefreshPrimURL()\nReloads the web page shown on the sides of the object."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llEscapeURL", "s", "s", "string llEscapeURL(string url)\nReturns and escaped/encoded version of url, replacing spaces with %20 etc."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llUnescapeURL", "s", "s", "string llUnescapeURL(string url)\nReturns and unescaped/unencoded version of url, replacing %20 with spaces etc."));
-
- addFunction(new LLScriptLibraryFunction(10.f, 1.f, dummy_func, "llMapDestination", NULL, "svv", "llMapDestination(string simname, vector pos, vector look_at)\nOpens world map centered on region with pos highlighted.\nOnly works for scripts attached to avatar, or during touch events.\n(NOTE: look_at currently does nothing)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.1f, dummy_func, "llAddToLandBanList", NULL, "kf", "llAddToLandBanList(key avatar, float hours)\nAdd avatar to the land ban list for hours"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.1f, dummy_func, "llRemoveFromLandPassList", NULL, "k", "llRemoveFromLandPassList(key avatar)\nRemove avatar from the land pass list"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.1f, dummy_func, "llRemoveFromLandBanList", NULL, "k", "llRemoveFromLandBanList(key avatar)\nRemove avatar from the land ban list"));
-
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetCameraParams", NULL, "l", "llSetCameraParams(list rules)\nSets multiple camera parameters at once.\nList format is [ rule1, data1, rule2, data2 . . . rulen, datan ]"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llClearCameraParams", NULL, NULL, "llClearCameraParams()\nResets all camera parameters to default values and turns off scripted camera control."));
+ addFunction(10.f, 20.f, dummy_func, "llSetPrimURL", NULL, "s");
+ addFunction(10.f, 20.f, dummy_func, "llRefreshPrimURL", NULL, "");
+ addFunction(10.f, 0.f, dummy_func, "llEscapeURL", "s", "s");
+ addFunction(10.f, 0.f, dummy_func, "llUnescapeURL", "s", "s");
+
+ addFunction(10.f, 1.f, dummy_func, "llMapDestination", NULL, "svv");
+ addFunction(10.f, 0.1f, dummy_func, "llAddToLandBanList", NULL, "kf");
+ addFunction(10.f, 0.1f, dummy_func, "llRemoveFromLandPassList", NULL, "k");
+ addFunction(10.f, 0.1f, dummy_func, "llRemoveFromLandBanList", NULL, "k");
+
+ addFunction(10.f, 0.f, dummy_func, "llSetCameraParams", NULL, "l");
+ addFunction(10.f, 0.f, dummy_func, "llClearCameraParams", NULL, NULL);
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llListStatistics", "f", "il", "float llListStatistics(integer operation, list l)\nPerform statistical aggregate functions on list l using LIST_STAT_* operations."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetUnixTime", "i", NULL, "integer llGetUnixTime()\nGet the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC from the system clock."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetParcelFlags", "i", "v", "integer llGetParcelFlags(vector pos)\nGet the parcel flags (PARCEL_FLAG_*) for the parcel including the point pos."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetRegionFlags", "i", NULL, "integer llGetRegionFlags()\nGet the region flags (REGION_FLAG_*) for the region the object is in."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llXorBase64StringsCorrect", "s", "ss", "string llXorBase64StringsCorrect(string s1, string s2)\nCorrectly performs an exclusive or on two Base 64 strings and returns a Base 64 string. s2 repeats if it is shorter than s1."));
+ addFunction(10.f, 0.f, dummy_func, "llListStatistics", "f", "il");
+ addFunction(10.f, 0.f, dummy_func, "llGetUnixTime", "i", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llGetParcelFlags", "i", "v");
+ addFunction(10.f, 0.f, dummy_func, "llGetRegionFlags", "i", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llXorBase64StringsCorrect", "s", "ss");
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llHTTPRequest", "k", "sls", "llHTTPRequest(string url, list parameters, string body)\nSend an HTTP request."));
+ addFunction(10.f, 0.f, dummy_func, "llHTTPRequest", "k", "sls");
- addFunction(new LLScriptLibraryFunction(10.f, 0.1f, dummy_func, "llResetLandBanList", NULL, NULL, "llResetLandBanList()\nRemoves all residents from the land ban list."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.1f, dummy_func, "llResetLandPassList", NULL, NULL, "llResetLandPassList()\nRemoves all residents from the land access/pass list."));
+ addFunction(10.f, 0.1f, dummy_func, "llResetLandBanList", NULL, NULL);
+ addFunction(10.f, 0.1f, dummy_func, "llResetLandPassList", NULL, NULL);
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetObjectPrimCount", "i", "k", "integer llGetObjectPrimCount(key object_id)\nReturns the total number of prims for an object."));
- addFunction(new LLScriptLibraryFunction(10.f, 2.0f, dummy_func, "llGetParcelPrimOwners", "l", "v", "list llGetParcelPrimOwners(vector pos)\nReturns a list of all residents who own objects on the parcel and the number of objects they own.\nRequires owner-like permissions for the parcel."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetParcelPrimCount", "i", "vii","integer llGetParcelPrimCount(vector pos, integer category, integer sim_wide)\nGets the number of prims on the parcel of the given category.\nCategories: PARCEL_COUNT_TOTAL, _OWNER, _GROUP, _OTHER, _SELECTED, _TEMP."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetParcelMaxPrims", "i", "vi","integer llGetParcelMaxPrims(vector pos, integer sim_wide)\nGets the maximum number of prims allowed on the parcel at pos."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetParcelDetails", "l", "vl","list llGetParcelDetails(vector pos, list params)\nGets the parcel details specified in params for the parcel at pos.\nParams is one or more of: PARCEL_DETAILS_NAME, _DESC, _OWNER, _GROUP, _AREA"));
+ addFunction(10.f, 0.f, dummy_func, "llGetObjectPrimCount", "i", "k");
+ addFunction(10.f, 2.0f, dummy_func, "llGetParcelPrimOwners", "l", "v");
+ addFunction(10.f, 0.f, dummy_func, "llGetParcelPrimCount", "i", "vii");
+ addFunction(10.f, 0.f, dummy_func, "llGetParcelMaxPrims", "i", "vi");
+ addFunction(10.f, 0.f, dummy_func, "llGetParcelDetails", "l", "vl");
- addFunction(new LLScriptLibraryFunction(10.f, 0.2f, dummy_func, "llSetLinkPrimitiveParams", NULL, "il", "llSetLinkPrimitiveParams(integer linknumber, list rules)\nSet primitive parameters for linknumber based on rules."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.2f, dummy_func, "llSetLinkTexture", NULL, "isi", "llSetLinkTexture(integer link_pos, string texture, integer face)\nSets the texture of face for link_pos"));
+ addFunction(10.f, 0.2f, dummy_func, "llSetLinkPrimitiveParams", NULL, "il");
+ addFunction(10.f, 0.2f, dummy_func, "llSetLinkTexture", NULL, "isi");
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llStringTrim", "s", "si", "string llStringTrim(string src, integer trim_type)\nTrim leading and/or trailing spaces from a string.\nUses trim_type of STRING_TRIM, STRING_TRIM_HEAD or STRING_TRIM_TAIL."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llRegionSay", NULL, "is", "llRegionSay(integer channel, string msg)\nbroadcasts msg to entire region on channel (not 0.)"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetObjectDetails", "l", "kl", "list llGetObjectDetails(key id, list params)\nGets the object details specified in params for the object with key id.\nDetails are OBJECT_NAME, _DESC, _POS, _ROT, _VELOCITY, _OWNER, _GROUP, _CREATOR."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSetClickAction", NULL, "i", "llSetClickAction(integer action)\nSets the action performed when a prim is clicked upon."));
-
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetRegionAgentCount", "i", NULL, "int llGetRegionAgentCount()\nreturns the number of agents in a region"));
- addFunction(new LLScriptLibraryFunction(10.f, 1.f, dummy_func, "llTextBox", NULL, "ksi", "llTextBox(key avatar, string message, integer chat_channel\nShows a dialog box on the avatar's screen with the message.\nA text box asks for input, and if entered the text is chatted on chat_channel."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetAgentLanguage", "s", "k", "string llGetAgentLanguage(key id)\nGets the agents preferred language.."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedTouchUV", "v", "i", "vector llDetectedTouchUV(integer number)\nreturns the u and v coordinates in the first two components of a vector, for a triggered touch event"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedTouchFace", "i", "i", "integer llDetectedTouchFace(integer number)\nreturns the index of the face on the object for a triggered touch event"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedTouchPos", "v", "i", "vector llDetectedTouchPos(integer number)\nreturns the position touched for a triggered touch event"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedTouchNormal", "v", "i", "vector llDetectedTouchNormal(integer number)\nreturns the surface normal for a triggered touch event"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedTouchBinormal", "v", "i", "vector llDetectedTouchBinormal(integer number)\nreturns the surface binormal for a triggered touch event"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedTouchST", "v", "i", "vector llDetectedTouchST(integer number)\nreturns the s and t coordinates in the first two components of a vector, for a triggered touch event"));
-
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llSHA1String", "s", "s", "string llSHA1String(string sr)\nPerforms a SHA1 security Hash. Returns a 40 character hex string."));
-
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetFreeURLs", "i", NULL, "integer llGetFreeURLs()\nreturns the available urls for the current script"));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llRequestURL", "k", NULL, "key llRequestURL()\nRequests one HTTP:// url for use by this object\nTriggers an http_server event with results."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llRequestSecureURL", "k", NULL, "key llRequestSecureURL()\nRequests one HTTPS:// (SSL) url for use by this object\nTriggers an http_server event with results."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llReleaseURL", NULL, "s", "llReleaseURL(string url)\nReleases the specified URL, it will no longer be usable."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llHTTPResponse", NULL, "kis", "llHTTPResponse(key id, integer status, string body)\nResponds to request id with status and body."));
- addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetHTTPHeader", "s", "ks", "string llGetHTTPHeader(key id, string header)\nGet the value for header for request id."));
+ addFunction(10.f, 0.f, dummy_func, "llStringTrim", "s", "si");
+ addFunction(10.f, 0.f, dummy_func, "llRegionSay", NULL, "is");
+ addFunction(10.f, 0.f, dummy_func, "llGetObjectDetails", "l", "kl");
+ addFunction(10.f, 0.f, dummy_func, "llSetClickAction", NULL, "i");
+
+ addFunction(10.f, 0.f, dummy_func, "llGetRegionAgentCount", "i", NULL);
+ addFunction(10.f, 1.f, dummy_func, "llTextBox", NULL, "ksi");
+ addFunction(10.f, 0.f, dummy_func, "llGetAgentLanguage", "s", "k");
+ addFunction(10.f, 0.f, dummy_func, "llDetectedTouchUV", "v", "i");
+ addFunction(10.f, 0.f, dummy_func, "llDetectedTouchFace", "i", "i");
+ addFunction(10.f, 0.f, dummy_func, "llDetectedTouchPos", "v", "i");
+ addFunction(10.f, 0.f, dummy_func, "llDetectedTouchNormal", "v", "i");
+ addFunction(10.f, 0.f, dummy_func, "llDetectedTouchBinormal", "v", "i");
+ addFunction(10.f, 0.f, dummy_func, "llDetectedTouchST", "v", "i");
+
+ addFunction(10.f, 0.f, dummy_func, "llSHA1String", "s", "s");
+
+ addFunction(10.f, 0.f, dummy_func, "llGetFreeURLs", "i", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llRequestURL", "k", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llRequestSecureURL", "k", NULL);
+ addFunction(10.f, 0.f, dummy_func, "llReleaseURL", NULL, "s");
+ addFunction(10.f, 0.f, dummy_func, "llHTTPResponse", NULL, "kis");
+ addFunction(10.f, 0.f, dummy_func, "llGetHTTPHeader", "s", "ks");
+
+ // Prim media (see lscript_prim_media.h)
+ addFunction(10.f, 1.0f, dummy_func, "llSetPrimMediaParams", "i", "il");
+ addFunction(10.f, 1.0f, dummy_func, "llGetPrimMediaParams", "l", "il");
+ addFunction(10.f, 1.0f, dummy_func, "llClearPrimMedia", "i", "i");
// energy, sleep, dummy_func, name, return type, parameters, help text, gods-only
@@ -465,58 +462,34 @@ void LLScriptLibrary::init()
// existing scripts will crash.
}
-LLScriptLibraryFunction::LLScriptLibraryFunction(F32 eu, F32 st, void (*exec_func)(LLScriptLibData *, LLScriptLibData *, const LLUUID &), const char *name, const char *ret_type, const char *args, const char *desc, BOOL god_only)
+LLScriptLibraryFunction::LLScriptLibraryFunction(F32 eu, F32 st, void (*exec_func)(LLScriptLibData *, LLScriptLibData *, const LLUUID &), const char *name, const char *ret_type, const char *args, BOOL god_only)
: mEnergyUse(eu), mSleepTime(st), mExecFunc(exec_func), mName(name), mReturnType(ret_type), mArgs(args), mGodOnly(god_only)
{
- char *mDesc_ = new char[512];
- if (mSleepTime)
- {
- snprintf( /* Flawfinder: ignore */
- mDesc_,
- 512,
- "%s\nSleeps script for %.1f seconds.",
- desc,
- mSleepTime);
- }
- else
- {
- strncpy(mDesc_, desc, 512); /* Flawfinder: ignore */
- mDesc_[511] = '\0'; // just in case.
- }
- mDesc = mDesc_;
}
LLScriptLibraryFunction::~LLScriptLibraryFunction()
{
- delete [] mDesc;
}
-void LLScriptLibrary::addFunction(LLScriptLibraryFunction *func)
+void LLScriptLibrary::addFunction(F32 eu, F32 st, void (*exec_func)(LLScriptLibData *, LLScriptLibData *, const LLUUID &), const char *name, const char *ret_type, const char *args, BOOL god_only)
{
- LLScriptLibraryFunction **temp = new LLScriptLibraryFunction*[mNextNumber + 1];
- if (mNextNumber)
- {
- memcpy( /* Flawfinder: ignore */
- temp,
- mFunctions,
- sizeof(LLScriptLibraryFunction*)*mNextNumber);
- delete [] mFunctions;
- }
- mFunctions = temp;
- mFunctions[mNextNumber] = func;
- mNextNumber++;
+ LLScriptLibraryFunction func(eu, st, exec_func, name, ret_type, args, god_only);
+ mFunctions.push_back(func);
}
void LLScriptLibrary::assignExec(const char *name, void (*exec_func)(LLScriptLibData *, LLScriptLibData *, const LLUUID &))
{
- S32 i;
- for (i = 0; i < mNextNumber; i++)
+ for (std::vector<LLScriptLibraryFunction>::iterator i = mFunctions.begin();
+ i != mFunctions.end(); ++i)
{
- if (!strcmp(name, mFunctions[i]->mName))
+ if (!strcmp(name, i->mName))
{
- mFunctions[i]->mExecFunc = exec_func;
+ i->mExecFunc = exec_func;
+ return;
}
}
+
+ llerrs << "Unknown LSL function in assignExec: " << name << llendl;
}
void LLScriptLibData::print(std::ostream &s, BOOL b_prepend_comma)
@@ -527,7 +500,7 @@ void LLScriptLibData::print(std::ostream &s, BOOL b_prepend_comma)
s << ", ";
}
switch (mType)
- {
+ {
case LST_INTEGER:
s << mInteger;
break;
diff --git a/indra/mac_crash_logger/CMakeLists.txt b/indra/mac_crash_logger/CMakeLists.txt
index daf3e10857..420e836e36 100644
--- a/indra/mac_crash_logger/CMakeLists.txt
+++ b/indra/mac_crash_logger/CMakeLists.txt
@@ -10,6 +10,7 @@ include(LLMessage)
include(LLVFS)
include(LLXML)
include(Linking)
+include(LLSharedLibs)
include_directories(
${LLCOMMON_INCLUDE_DIRS}
@@ -74,3 +75,6 @@ add_custom_command(
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/mac-crash-logger.app/Contents/Resources/CrashReporter.nib
)
+ll_deploy_sharedlibs_command(mac-crash-logger)
+
+
diff --git a/indra/mac_updater/CMakeLists.txt b/indra/mac_updater/CMakeLists.txt
index 0eac76fa69..57d426aa24 100644
--- a/indra/mac_updater/CMakeLists.txt
+++ b/indra/mac_updater/CMakeLists.txt
@@ -77,3 +77,4 @@ add_custom_command(
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/mac-updater.app/Contents/Resources/AutoUpdater.nib
)
+ll_deploy_sharedlibs_command(mac-updater)
diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt
new file mode 100644
index 0000000000..cc03d9cb72
--- /dev/null
+++ b/indra/media_plugins/CMakeLists.txt
@@ -0,0 +1,13 @@
+# -*- cmake -*-
+
+add_subdirectory(base)
+
+add_subdirectory(webkit)
+
+add_subdirectory(gstreamer010)
+
+if (WINDOWS OR DARWIN)
+ add_subdirectory(quicktime)
+endif (WINDOWS OR DARWIN)
+
+add_subdirectory(example)
diff --git a/indra/media_plugins/base/CMakeLists.txt b/indra/media_plugins/base/CMakeLists.txt
new file mode 100644
index 0000000000..3ad94b0c64
--- /dev/null
+++ b/indra/media_plugins/base/CMakeLists.txt
@@ -0,0 +1,49 @@
+# -*- cmake -*-
+
+project(media_plugin_base)
+
+include(00-Common)
+include(LLCommon)
+include(LLImage)
+include(LLPlugin)
+include(LLMath)
+include(LLRender)
+include(LLWindow)
+include(Linking)
+include(PluginAPI)
+include(FindOpenGL)
+
+include_directories(
+ ${LLPLUGIN_INCLUDE_DIRS}
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LLMATH_INCLUDE_DIRS}
+ ${LLIMAGE_INCLUDE_DIRS}
+ ${LLRENDER_INCLUDE_DIRS}
+ ${LLWINDOW_INCLUDE_DIRS}
+)
+
+
+### media_plugin_base
+
+if(NOT WORD_SIZE EQUAL 32)
+ if(WINDOWS)
+ add_definitions(/FIXED:NO)
+ else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
+ add_definitions(-fPIC)
+ endif(WINDOWS)
+endif(NOT WORD_SIZE EQUAL 32)
+
+set(media_plugin_base_SOURCE_FILES
+ media_plugin_base.cpp
+)
+
+set(media_plugin_base_HEADER_FILES
+ CMakeLists.txt
+
+ media_plugin_base.h
+)
+
+add_library(media_plugin_base
+ ${media_plugin_base_SOURCE_FILES}
+)
+
diff --git a/indra/media_plugins/base/media_plugin_base.cpp b/indra/media_plugins/base/media_plugin_base.cpp
new file mode 100644
index 0000000000..658783e064
--- /dev/null
+++ b/indra/media_plugins/base/media_plugin_base.cpp
@@ -0,0 +1,211 @@
+/**
+ * @file media_plugin_base.cpp
+ * @brief Media plugin base class for LLMedia API plugin system
+ *
+ * All plugins should be a subclass of MediaPluginBase.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "linden_common.h"
+#include "media_plugin_base.h"
+
+
+// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint
+////////////////////////////////////////////////////////////////////////////////
+/// Media plugin constructor.
+///
+/// @param[in] host_send_func Function for sending messages from plugin to plugin loader shell
+/// @param[in] host_user_data Message data for messages from plugin to plugin loader shell
+
+MediaPluginBase::MediaPluginBase(
+ LLPluginInstance::sendMessageFunction host_send_func,
+ void *host_user_data )
+{
+ mHostSendFunction = host_send_func;
+ mHostUserData = host_user_data;
+ mDeleteMe = false;
+ mPixels = 0;
+ mWidth = 0;
+ mHeight = 0;
+ mTextureWidth = 0;
+ mTextureHeight = 0;
+ mDepth = 0;
+ mStatus = STATUS_NONE;
+}
+
+/**
+ * Converts current media status enum value into string (STATUS_LOADING into "loading", etc.)
+ *
+ * @return Media status string ("loading", "playing", "paused", etc)
+ *
+ */
+std::string MediaPluginBase::statusString()
+{
+ std::string result;
+
+ switch(mStatus)
+ {
+ case STATUS_LOADING: result = "loading"; break;
+ case STATUS_LOADED: result = "loaded"; break;
+ case STATUS_ERROR: result = "error"; break;
+ case STATUS_PLAYING: result = "playing"; break;
+ case STATUS_PAUSED: result = "paused"; break;
+ case STATUS_DONE: result = "done"; break;
+ default:
+ // keep the empty string
+ break;
+ }
+
+ return result;
+}
+
+/**
+ * Set media status.
+ *
+ * @param[in] status Media status (STATUS_LOADING, STATUS_PLAYING, STATUS_PAUSED, etc)
+ *
+ */
+void MediaPluginBase::setStatus(EStatus status)
+{
+ if(mStatus != status)
+ {
+ mStatus = status;
+ sendStatus();
+ }
+}
+
+
+/**
+ * Receive message from plugin loader shell.
+ *
+ * @param[in] message_string Message string
+ * @param[in] user_data Message data
+ *
+ */
+void MediaPluginBase::staticReceiveMessage(const char *message_string, void **user_data)
+{
+ MediaPluginBase *self = (MediaPluginBase*)*user_data;
+
+ if(self != NULL)
+ {
+ self->receiveMessage(message_string);
+
+ // If the plugin has processed the delete message, delete it.
+ if(self->mDeleteMe)
+ {
+ delete self;
+ *user_data = NULL;
+ }
+ }
+}
+
+/**
+ * Send message to plugin loader shell.
+ *
+ * @param[in] message Message data being sent to plugin loader shell
+ *
+ */
+void MediaPluginBase::sendMessage(const LLPluginMessage &message)
+{
+ std::string output = message.generate();
+ mHostSendFunction(output.c_str(), &mHostUserData);
+}
+
+/**
+ * Notifies plugin loader shell that part of display area needs to be redrawn.
+ *
+ * @param[in] left Left X coordinate of area to redraw (0,0 is at top left corner)
+ * @param[in] top Top Y coordinate of area to redraw (0,0 is at top left corner)
+ * @param[in] right Right X-coordinate of area to redraw (0,0 is at top left corner)
+ * @param[in] bottom Bottom Y-coordinate of area to redraw (0,0 is at top left corner)
+ *
+ */
+void MediaPluginBase::setDirty(int left, int top, int right, int bottom)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated");
+
+ message.setValueS32("left", left);
+ message.setValueS32("top", top);
+ message.setValueS32("right", right);
+ message.setValueS32("bottom", bottom);
+
+ sendMessage(message);
+}
+
+/**
+ * Sends "media_status" message to plugin loader shell ("loading", "playing", "paused", etc.)
+ *
+ */
+void MediaPluginBase::sendStatus()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "media_status");
+
+ message.setValue("status", statusString());
+
+ sendMessage(message);
+}
+
+
+#if LL_WINDOWS
+# define LLSYMEXPORT __declspec(dllexport)
+#elif LL_LINUX
+# define LLSYMEXPORT __attribute__ ((visibility("default")))
+#else
+# define LLSYMEXPORT /**/
+#endif
+
+extern "C"
+{
+ LLSYMEXPORT int LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data);
+}
+
+/**
+ * Plugin initialization and entry point. Establishes communication channel for messages between plugin and plugin loader shell. TODO:DOC - Please check!
+ *
+ * @param[in] host_send_func Function for sending messages from plugin to plugin loader shell
+ * @param[in] host_user_data Message data for messages from plugin to plugin loader shell
+ * @param[out] plugin_send_func Function for plugin to receive messages from plugin loader shell
+ * @param[out] plugin_user_data Pointer to plugin instance
+ *
+ * @return int, where 0=success
+ *
+ */
+LLSYMEXPORT int
+LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
+{
+ return init_media_plugin(host_send_func, host_user_data, plugin_send_func, plugin_user_data);
+}
+
+#ifdef WIN32
+int WINAPI DllEntryPoint( HINSTANCE hInstance, unsigned long reason, void* params )
+{
+ return 1;
+}
+#endif
diff --git a/indra/media_plugins/base/media_plugin_base.exp b/indra/media_plugins/base/media_plugin_base.exp
new file mode 100644
index 0000000000..d8c7bb712a
--- /dev/null
+++ b/indra/media_plugins/base/media_plugin_base.exp
@@ -0,0 +1,2 @@
+_LLPluginInitEntryPoint
+
diff --git a/indra/media_plugins/base/media_plugin_base.h b/indra/media_plugins/base/media_plugin_base.h
new file mode 100644
index 0000000000..ed4dc0cfa9
--- /dev/null
+++ b/indra/media_plugins/base/media_plugin_base.h
@@ -0,0 +1,134 @@
+/**
+ * @file media_plugin_base.h
+ * @brief Media plugin base class for LLMedia API plugin system
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "linden_common.h"
+
+#include "llplugininstance.h"
+#include "llpluginmessage.h"
+#include "llpluginmessageclasses.h"
+
+
+class MediaPluginBase
+{
+public:
+ MediaPluginBase(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
+ /** Media plugin destructor. */
+ virtual ~MediaPluginBase() {}
+
+ /** Handle received message from plugin loader shell. */
+ virtual void receiveMessage(const char *message_string) = 0;
+
+ static void staticReceiveMessage(const char *message_string, void **user_data);
+
+protected:
+
+ /** Plugin status. */
+ typedef enum
+ {
+ STATUS_NONE,
+ STATUS_LOADING,
+ STATUS_LOADED,
+ STATUS_ERROR,
+ STATUS_PLAYING,
+ STATUS_PAUSED,
+ STATUS_DONE
+ } EStatus;
+
+ /** Plugin shared memory. */
+ class SharedSegmentInfo
+ {
+ public:
+ /** Shared memory address. */
+ void *mAddress;
+ /** Shared memory size. */
+ size_t mSize;
+ };
+
+ void sendMessage(const LLPluginMessage &message);
+ void sendStatus();
+ std::string statusString();
+ void setStatus(EStatus status);
+
+ /// Note: The quicktime plugin overrides this to add current time and duration to the message.
+ virtual void setDirty(int left, int top, int right, int bottom);
+
+ /** Map of shared memory names to shared memory. */
+ typedef std::map<std::string, SharedSegmentInfo> SharedSegmentMap;
+
+
+ /** Function to send message from plugin to plugin loader shell. */
+ LLPluginInstance::sendMessageFunction mHostSendFunction;
+ /** Message data being sent to plugin loader shell by mHostSendFunction. */
+ void *mHostUserData;
+ /** Flag to delete plugin instance (self). */
+ bool mDeleteMe;
+ /** Pixel array to display. TODO:DOC are pixels always 24-bit RGB format, aligned on 32-bit boundary? Also: calling this a pixel array may be misleading since 1 pixel > 1 char. */
+ unsigned char* mPixels;
+ /** TODO:DOC what's this for -- does a texture have its own piece of shared memory? updated on size_change_request, cleared on shm_remove */
+ std::string mTextureSegmentName;
+ /** Width of plugin display in pixels. */
+ int mWidth;
+ /** Height of plugin display in pixels. */
+ int mHeight;
+ /** Width of plugin texture. */
+ int mTextureWidth;
+ /** Height of plugin texture. */
+ int mTextureHeight;
+ /** Pixel depth (pixel size in bytes). */
+ int mDepth;
+ /** Current status of plugin. */
+ EStatus mStatus;
+ /** Map of shared memory segments. */
+ SharedSegmentMap mSharedSegments;
+
+};
+
+/** The plugin <b>must</b> define this function to create its instance.
+ * It should look something like this:
+ * @code
+ * {
+ * MediaPluginFoo *self = new MediaPluginFoo(host_send_func, host_user_data);
+ * *plugin_send_func = MediaPluginFoo::staticReceiveMessage;
+ * *plugin_user_data = (void*)self;
+ *
+ * return 0;
+ * }
+ * @endcode
+ */
+int init_media_plugin(
+ LLPluginInstance::sendMessageFunction host_send_func,
+ void *host_user_data,
+ LLPluginInstance::sendMessageFunction *plugin_send_func,
+ void **plugin_user_data);
+
+
diff --git a/indra/media_plugins/example/CMakeLists.txt b/indra/media_plugins/example/CMakeLists.txt
new file mode 100644
index 0000000000..56cefde4bd
--- /dev/null
+++ b/indra/media_plugins/example/CMakeLists.txt
@@ -0,0 +1,82 @@
+# -*- cmake -*-
+
+project(media_plugin_example)
+
+include(00-Common)
+include(LLCommon)
+include(LLImage)
+include(LLPlugin)
+include(LLMath)
+include(LLRender)
+include(LLWindow)
+include(Linking)
+include(PluginAPI)
+include(MediaPluginBase)
+include(FindOpenGL)
+
+include(ExamplePlugin)
+
+include_directories(
+ ${LLPLUGIN_INCLUDE_DIRS}
+ ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS}
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LLMATH_INCLUDE_DIRS}
+ ${LLIMAGE_INCLUDE_DIRS}
+ ${LLRENDER_INCLUDE_DIRS}
+ ${LLWINDOW_INCLUDE_DIRS}
+)
+
+
+### media_plugin_example
+
+if(NOT WORD_SIZE EQUAL 32)
+ if(WINDOWS)
+ add_definitions(/FIXED:NO)
+ else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
+ add_definitions(-fPIC)
+ endif(WINDOWS)
+endif(NOT WORD_SIZE EQUAL 32)
+
+set(media_plugin_example_SOURCE_FILES
+ media_plugin_example.cpp
+ )
+
+add_library(media_plugin_example
+ SHARED
+ ${media_plugin_example_SOURCE_FILES}
+)
+
+target_link_libraries(media_plugin_example
+ ${LLPLUGIN_LIBRARIES}
+ ${MEDIA_PLUGIN_BASE_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+ ${EXAMPLE_PLUGIN_LIBRARIES}
+ ${PLUGIN_API_WINDOWS_LIBRARIES}
+)
+
+add_dependencies(media_plugin_example
+ ${LLPLUGIN_LIBRARIES}
+ ${MEDIA_PLUGIN_BASE_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+)
+
+if (WINDOWS)
+ set_target_properties(
+ media_plugin_example
+ PROPERTIES
+ LINK_FLAGS "/MANIFEST:NO"
+ )
+endif (WINDOWS)
+
+if (DARWIN)
+ # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name
+ set_target_properties(
+ media_plugin_example
+ PROPERTIES
+ PREFIX ""
+ BUILD_WITH_INSTALL_RPATH 1
+ INSTALL_NAME_DIR "@executable_path"
+ LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp"
+ )
+
+endif (DARWIN) \ No newline at end of file
diff --git a/indra/media_plugins/example/media_plugin_example.cpp b/indra/media_plugins/example/media_plugin_example.cpp
new file mode 100644
index 0000000000..f5b077fea0
--- /dev/null
+++ b/indra/media_plugins/example/media_plugin_example.cpp
@@ -0,0 +1,490 @@
+/**
+ * @file media_plugin_example.cpp
+ * @brief Example plugin for LLMedia API plugin system
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "linden_common.h"
+
+#include "llgl.h"
+#include "llplugininstance.h"
+#include "llpluginmessage.h"
+#include "llpluginmessageclasses.h"
+#include "media_plugin_base.h"
+
+#include <time.h>
+
+////////////////////////////////////////////////////////////////////////////////
+//
+class MediaPluginExample :
+ public MediaPluginBase
+{
+ public:
+ MediaPluginExample( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data );
+ ~MediaPluginExample();
+
+ /*virtual*/ void receiveMessage( const char* message_string );
+
+ private:
+ bool init();
+ void update( F64 milliseconds );
+ void write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b );
+ bool mFirstTime;
+
+ time_t mLastUpdateTime;
+ enum Constants { ENumObjects = 10 };
+ unsigned char* mBackgroundPixels;
+ int mColorR[ ENumObjects ];
+ int mColorG[ ENumObjects ];
+ int mColorB[ ENumObjects ];
+ int mXpos[ ENumObjects ];
+ int mYpos[ ENumObjects ];
+ int mXInc[ ENumObjects ];
+ int mYInc[ ENumObjects ];
+ int mBlockSize[ ENumObjects ];
+ bool mMouseButtonDown;
+ bool mStopAction;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+MediaPluginExample::MediaPluginExample( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ) :
+ MediaPluginBase( host_send_func, host_user_data )
+{
+ mFirstTime = true;
+ mWidth = 0;
+ mHeight = 0;
+ mDepth = 4;
+ mPixels = 0;
+ mMouseButtonDown = false;
+ mStopAction = false;
+ mLastUpdateTime = 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+MediaPluginExample::~MediaPluginExample()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginExample::receiveMessage( const char* message_string )
+{
+ LLPluginMessage message_in;
+
+ if ( message_in.parse( message_string ) >= 0 )
+ {
+ std::string message_class = message_in.getClass();
+ std::string message_name = message_in.getName();
+
+ if ( message_class == LLPLUGIN_MESSAGE_CLASS_BASE )
+ {
+ if ( message_name == "init" )
+ {
+ LLPluginMessage message( "base", "init_response" );
+ LLSD versions = LLSD::emptyMap();
+ versions[ LLPLUGIN_MESSAGE_CLASS_BASE ] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
+ versions[ LLPLUGIN_MESSAGE_CLASS_MEDIA ] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
+ versions[ LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER ] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION;
+ message.setValueLLSD( "versions", versions );
+
+ std::string plugin_version = "Example media plugin, Example Version 1.0.0.0";
+ message.setValue( "plugin_version", plugin_version );
+ sendMessage( message );
+
+ // Plugin gets to decide the texture parameters to use.
+ message.setMessage( LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params" );
+ message.setValueS32( "default_width", mWidth );
+ message.setValueS32( "default_height", mHeight );
+ message.setValueS32( "depth", mDepth );
+ message.setValueU32( "internalformat", GL_RGBA );
+ message.setValueU32( "format", GL_RGBA );
+ message.setValueU32( "type", GL_UNSIGNED_BYTE );
+ message.setValueBoolean( "coords_opengl", false );
+ sendMessage( message );
+ }
+ else
+ if ( message_name == "idle" )
+ {
+ // no response is necessary here.
+ F64 time = message_in.getValueReal( "time" );
+
+ // Convert time to milliseconds for update()
+ update( time );
+ }
+ else
+ if ( message_name == "cleanup" )
+ {
+ // clean up here
+ }
+ else
+ if ( message_name == "shm_added" )
+ {
+ SharedSegmentInfo info;
+ info.mAddress = message_in.getValuePointer( "address" );
+ info.mSize = ( size_t )message_in.getValueS32( "size" );
+ std::string name = message_in.getValue( "name" );
+
+ mSharedSegments.insert( SharedSegmentMap::value_type( name, info ) );
+
+ }
+ else
+ if ( message_name == "shm_remove" )
+ {
+ std::string name = message_in.getValue( "name" );
+
+ SharedSegmentMap::iterator iter = mSharedSegments.find( name );
+ if( iter != mSharedSegments.end() )
+ {
+ if ( mPixels == iter->second.mAddress )
+ {
+ // This is the currently active pixel buffer.
+ // Make sure we stop drawing to it.
+ mPixels = NULL;
+ mTextureSegmentName.clear();
+ };
+ mSharedSegments.erase( iter );
+ }
+ else
+ {
+ //std::cerr << "MediaPluginExample::receiveMessage: unknown shared memory region!" << std::endl;
+ };
+
+ // Send the response so it can be cleaned up.
+ LLPluginMessage message( "base", "shm_remove_response" );
+ message.setValue( "name", name );
+ sendMessage( message );
+ }
+ else
+ {
+ //std::cerr << "MediaPluginExample::receiveMessage: unknown base message: " << message_name << std::endl;
+ };
+ }
+ else
+ if ( message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA )
+ {
+ if ( message_name == "size_change" )
+ {
+ std::string name = message_in.getValue( "name" );
+ S32 width = message_in.getValueS32( "width" );
+ S32 height = message_in.getValueS32( "height" );
+ S32 texture_width = message_in.getValueS32( "texture_width" );
+ S32 texture_height = message_in.getValueS32( "texture_height" );
+
+ if ( ! name.empty() )
+ {
+ // Find the shared memory region with this name
+ SharedSegmentMap::iterator iter = mSharedSegments.find( name );
+ if ( iter != mSharedSegments.end() )
+ {
+ mPixels = ( unsigned char* )iter->second.mAddress;
+ mWidth = width;
+ mHeight = height;
+
+ mTextureWidth = texture_width;
+ mTextureHeight = texture_height;
+
+ init();
+ };
+ };
+
+ LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response" );
+ message.setValue( "name", name );
+ message.setValueS32( "width", width );
+ message.setValueS32( "height", height );
+ message.setValueS32( "texture_width", texture_width );
+ message.setValueS32( "texture_height", texture_height );
+ sendMessage( message );
+ }
+ else
+ if ( message_name == "load_uri" )
+ {
+ std::string uri = message_in.getValue( "uri" );
+ if ( ! uri.empty() )
+ {
+ };
+ }
+ else
+ if ( message_name == "mouse_event" )
+ {
+ std::string event = message_in.getValue( "event" );
+ S32 button = message_in.getValueS32( "button" );
+
+ // left mouse button
+ if ( button == 0 )
+ {
+ int mouse_x = message_in.getValueS32( "x" );
+ int mouse_y = message_in.getValueS32( "y" );
+ std::string modifiers = message_in.getValue( "modifiers" );
+
+ if ( event == "move" )
+ {
+ if ( mMouseButtonDown )
+ write_pixel( mouse_x, mouse_y, rand() % 0x80 + 0x80, rand() % 0x80 + 0x80, rand() % 0x80 + 0x80 );
+ }
+ else
+ if ( event == "down" )
+ {
+ mMouseButtonDown = true;
+ }
+ else
+ if ( event == "up" )
+ {
+ mMouseButtonDown = false;
+ }
+ else
+ if ( event == "double_click" )
+ {
+ };
+ };
+ }
+ else
+ if ( message_name == "key_event" )
+ {
+ std::string event = message_in.getValue( "event" );
+ S32 key = message_in.getValueS32( "key" );
+ std::string modifiers = message_in.getValue( "modifiers" );
+
+ if ( event == "down" )
+ {
+ if ( key == ' ')
+ {
+ mLastUpdateTime = 0;
+ update( 0.0f );
+ };
+ };
+ }
+ else
+ {
+ //std::cerr << "MediaPluginExample::receiveMessage: unknown media message: " << message_string << std::endl;
+ };
+ }
+ else
+ if ( message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER )
+ {
+ if ( message_name == "browse_reload" )
+ {
+ mLastUpdateTime = 0;
+ mFirstTime = true;
+ mStopAction = false;
+ update( 0.0f );
+ }
+ else
+ if ( message_name == "browse_stop" )
+ {
+ for( int n = 0; n < ENumObjects; ++n )
+ mXInc[ n ] = mYInc[ n ] = 0;
+
+ mStopAction = true;
+ update( 0.0f );
+ }
+ else
+ {
+ //std::cerr << "MediaPluginExample::receiveMessage: unknown media_browser message: " << message_string << std::endl;
+ };
+ }
+ else
+ {
+ //std::cerr << "MediaPluginExample::receiveMessage: unknown message class: " << message_class << std::endl;
+ };
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginExample::write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b )
+{
+ // make sure we don't write outside the buffer
+ if ( ( x < 0 ) || ( x >= mWidth ) || ( y < 0 ) || ( y >= mHeight ) )
+ return;
+
+ if ( mBackgroundPixels != NULL )
+ {
+ unsigned char *pixel = mBackgroundPixels;
+ pixel += y * mWidth * mDepth;
+ pixel += ( x * mDepth );
+ pixel[ 0 ] = b;
+ pixel[ 1 ] = g;
+ pixel[ 2 ] = r;
+
+ setDirty( x, y, x + 1, y + 1 );
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void MediaPluginExample::update( F64 milliseconds )
+{
+ if ( mWidth < 1 || mWidth > 2048 || mHeight < 1 || mHeight > 2048 )
+ return;
+
+ if ( mPixels == 0 )
+ return;
+
+ if ( mFirstTime )
+ {
+ for( int n = 0; n < ENumObjects; ++n )
+ {
+ mXpos[ n ] = ( mWidth / 2 ) + rand() % ( mWidth / 16 ) - ( mWidth / 32 );
+ mYpos[ n ] = ( mHeight / 2 ) + rand() % ( mHeight / 16 ) - ( mHeight / 32 );
+
+ mColorR[ n ] = rand() % 0x60 + 0x60;
+ mColorG[ n ] = rand() % 0x60 + 0x60;
+ mColorB[ n ] = rand() % 0x60 + 0x60;
+
+ mXInc[ n ] = 0;
+ while ( mXInc[ n ] == 0 )
+ mXInc[ n ] = rand() % 7 - 3;
+
+ mYInc[ n ] = 0;
+ while ( mYInc[ n ] == 0 )
+ mYInc[ n ] = rand() % 9 - 4;
+
+ mBlockSize[ n ] = rand() % 0x30 + 0x10;
+ };
+
+ delete [] mBackgroundPixels;
+
+ mBackgroundPixels = new unsigned char[ mWidth * mHeight * mDepth ];
+
+ mFirstTime = false;
+ };
+
+ if ( mStopAction )
+ return;
+
+ if ( time( NULL ) > mLastUpdateTime + 3 )
+ {
+ const int num_squares = rand() % 20 + 4;
+ int sqr1_r = rand() % 0x80 + 0x20;
+ int sqr1_g = rand() % 0x80 + 0x20;
+ int sqr1_b = rand() % 0x80 + 0x20;
+ int sqr2_r = rand() % 0x80 + 0x20;
+ int sqr2_g = rand() % 0x80 + 0x20;
+ int sqr2_b = rand() % 0x80 + 0x20;
+
+ for ( int y1 = 0; y1 < num_squares; ++y1 )
+ {
+ for ( int x1 = 0; x1 < num_squares; ++x1 )
+ {
+ int px_start = mWidth * x1 / num_squares;
+ int px_end = ( mWidth * ( x1 + 1 ) ) / num_squares;
+ int py_start = mHeight * y1 / num_squares;
+ int py_end = ( mHeight * ( y1 + 1 ) ) / num_squares;
+
+ for( int y2 = py_start; y2 < py_end; ++y2 )
+ {
+ for( int x2 = px_start; x2 < px_end; ++x2 )
+ {
+ int rowspan = mWidth * mDepth;
+
+ if ( ( y1 % 2 ) ^ ( x1 % 2 ) )
+ {
+ mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr1_r;
+ mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr1_g;
+ mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr1_b;
+ }
+ else
+ {
+ mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr2_r;
+ mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr2_g;
+ mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr2_b;
+ };
+ };
+ };
+ };
+ };
+
+ time( &mLastUpdateTime );
+ };
+
+ memcpy( mPixels, mBackgroundPixels, mWidth * mHeight * mDepth );
+
+ for( int n = 0; n < ENumObjects; ++n )
+ {
+ if ( rand() % 50 == 0 )
+ {
+ mXInc[ n ] = 0;
+ while ( mXInc[ n ] == 0 )
+ mXInc[ n ] = rand() % 7 - 3;
+
+ mYInc[ n ] = 0;
+ while ( mYInc[ n ] == 0 )
+ mYInc[ n ] = rand() % 9 - 4;
+ };
+
+ if ( mXpos[ n ] + mXInc[ n ] < 0 || mXpos[ n ] + mXInc[ n ] >= mWidth - mBlockSize[ n ] )
+ mXInc[ n ] =- mXInc[ n ];
+
+ if ( mYpos[ n ] + mYInc[ n ] < 0 || mYpos[ n ] + mYInc[ n ] >= mHeight - mBlockSize[ n ] )
+ mYInc[ n ] =- mYInc[ n ];
+
+ mXpos[ n ] += mXInc[ n ];
+ mYpos[ n ] += mYInc[ n ];
+
+ for( int y = 0; y < mBlockSize[ n ]; ++y )
+ {
+ for( int x = 0; x < mBlockSize[ n ]; ++x )
+ {
+ mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 0 ] = mColorR[ n ];
+ mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 1 ] = mColorG[ n ];
+ mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 2 ] = mColorB[ n ];
+ };
+ };
+ };
+
+ setDirty( 0, 0, mWidth, mHeight );
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+bool MediaPluginExample::init()
+{
+ LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text" );
+ message.setValue( "name", "Example Plugin" );
+ sendMessage( message );
+
+ return true;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+int init_media_plugin( LLPluginInstance::sendMessageFunction host_send_func,
+ void* host_user_data,
+ LLPluginInstance::sendMessageFunction *plugin_send_func,
+ void **plugin_user_data )
+{
+ MediaPluginExample* self = new MediaPluginExample( host_send_func, host_user_data );
+ *plugin_send_func = MediaPluginExample::staticReceiveMessage;
+ *plugin_user_data = ( void* )self;
+
+ return 0;
+}
diff --git a/indra/media_plugins/gstreamer010/CMakeLists.txt b/indra/media_plugins/gstreamer010/CMakeLists.txt
new file mode 100644
index 0000000000..ba66166c55
--- /dev/null
+++ b/indra/media_plugins/gstreamer010/CMakeLists.txt
@@ -0,0 +1,79 @@
+# -*- cmake -*-
+
+project(media_plugin_gstreamer010)
+
+include(00-Common)
+include(LLCommon)
+include(LLImage)
+include(LLPlugin)
+include(LLMath)
+include(LLRender)
+include(LLWindow)
+include(Linking)
+include(PluginAPI)
+include(MediaPluginBase)
+include(FindOpenGL)
+
+include(GStreamer010Plugin)
+
+include_directories(
+ ${LLPLUGIN_INCLUDE_DIRS}
+ ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS}
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LLMATH_INCLUDE_DIRS}
+ ${LLIMAGE_INCLUDE_DIRS}
+ ${LLRENDER_INCLUDE_DIRS}
+ ${LLWINDOW_INCLUDE_DIRS}
+ ${GSTREAMER010_INCLUDE_DIRS}
+ ${GSTREAMER010_PLUGINS_BASE_INCLUDE_DIRS}
+)
+
+### media_plugin_gstreamer010
+
+if(NOT WORD_SIZE EQUAL 32)
+ if(WINDOWS)
+ add_definitions(/FIXED:NO)
+ else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
+ add_definitions(-fPIC)
+ endif(WINDOWS)
+endif(NOT WORD_SIZE EQUAL 32)
+
+set(media_plugin_gstreamer010_SOURCE_FILES
+ media_plugin_gstreamer010.cpp
+ llmediaimplgstreamer_syms.cpp
+ llmediaimplgstreamervidplug.cpp
+ )
+
+set(media_plugin_gstreamer010_HEADER_FILES
+ llmediaimplgstreamervidplug.h
+ llmediaimplgstreamer_syms.h
+ llmediaimplgstreamertriviallogging.h
+ )
+
+if (${CXX_VERSION_NUMBER} MATCHES "4[23].")
+ # Work around a bad interaction between broken gstreamer headers and
+ # g++ 4.3's increased strictness.
+ set_source_files_properties(llmediaimplgstreamervidplug.cpp PROPERTIES
+ COMPILE_FLAGS -Wno-write-strings)
+endif (${CXX_VERSION_NUMBER} MATCHES "4[23].")
+
+add_library(media_plugin_gstreamer010
+ SHARED
+ ${media_plugin_gstreamer010_SOURCE_FILES}
+)
+
+target_link_libraries(media_plugin_gstreamer010
+ ${LLPLUGIN_LIBRARIES}
+ ${MEDIA_PLUGIN_BASE_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+ ${PLUGIN_API_WINDOWS_LIBRARIES}
+ ${GSTREAMER010_LIBRARIES}
+)
+
+add_dependencies(media_plugin_gstreamer010
+ ${LLPLUGIN_LIBRARIES}
+ ${MEDIA_PLUGIN_BASE_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+)
+
+
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h
new file mode 100644
index 0000000000..48accd3e66
--- /dev/null
+++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h
@@ -0,0 +1,59 @@
+/**
+ * @file llmediaimplgstreamer.h
+ * @author Tofu Linden
+ * @brief implementation that supports media playback via GStreamer.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+// header guard
+#ifndef llmediaimplgstreamer_h
+#define llmediaimplgstreamer_h
+
+#if LL_GSTREAMER010_ENABLED
+
+extern "C" {
+#include <stdio.h>
+#include <gst/gst.h>
+
+#include "apr_pools.h"
+#include "apr_dso.h"
+}
+
+
+extern "C" {
+gboolean llmediaimplgstreamer_bus_callback (GstBus *bus,
+ GstMessage *message,
+ gpointer data);
+}
+
+#endif // LL_GSTREAMER010_ENABLED
+
+#endif // llmediaimplgstreamer_h
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp
new file mode 100644
index 0000000000..52cea46d46
--- /dev/null
+++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp
@@ -0,0 +1,173 @@
+/**
+ * @file llmediaimplgstreamer_syms.cpp
+ * @brief dynamic GStreamer symbol-grabbing code
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#if LL_GSTREAMER010_ENABLED
+
+#include <string>
+
+extern "C" {
+#include <gst/gst.h>
+
+#include "apr_pools.h"
+#include "apr_dso.h"
+}
+
+#include "llmediaimplgstreamertriviallogging.h"
+
+#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) RTN (*ll##GSTSYM)(__VA_ARGS__) = NULL
+#include "llmediaimplgstreamer_syms_raw.inc"
+#include "llmediaimplgstreamer_syms_rawv.inc"
+#undef LL_GST_SYM
+
+// a couple of stubs for disgusting reasons
+GstDebugCategory*
+ll_gst_debug_category_new(gchar *name, guint color, gchar *description)
+{
+ static GstDebugCategory dummy;
+ return &dummy;
+}
+void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname)
+{
+}
+
+static bool sSymsGrabbed = false;
+static apr_pool_t *sSymGSTDSOMemoryPool = NULL;
+static apr_dso_handle_t *sSymGSTDSOHandleG = NULL;
+static apr_dso_handle_t *sSymGSTDSOHandleV = NULL;
+
+
+bool grab_gst_syms(std::string gst_dso_name,
+ std::string gst_dso_name_vid)
+{
+ if (sSymsGrabbed)
+ {
+ // already have grabbed good syms
+ return TRUE;
+ }
+
+ bool sym_error = false;
+ bool rtn = false;
+ apr_status_t rv;
+ apr_dso_handle_t *sSymGSTDSOHandle = NULL;
+
+#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##GSTSYM, sSymGSTDSOHandle, #GSTSYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #GSTSYM); if (REQ) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #GSTSYM, (void*)ll##GSTSYM);}while(0)
+
+ //attempt to load the shared libraries
+ apr_pool_create(&sSymGSTDSOMemoryPool, NULL);
+
+ if ( APR_SUCCESS == (rv = apr_dso_load(&sSymGSTDSOHandle,
+ gst_dso_name.c_str(),
+ sSymGSTDSOMemoryPool) ))
+ {
+ INFOMSG("Found DSO: %s", gst_dso_name.c_str());
+#include "llmediaimplgstreamer_syms_raw.inc"
+
+ if ( sSymGSTDSOHandle )
+ {
+ sSymGSTDSOHandleG = sSymGSTDSOHandle;
+ sSymGSTDSOHandle = NULL;
+ }
+
+ if ( APR_SUCCESS ==
+ (rv = apr_dso_load(&sSymGSTDSOHandle,
+ gst_dso_name_vid.c_str(),
+ sSymGSTDSOMemoryPool) ))
+ {
+ INFOMSG("Found DSO: %s", gst_dso_name_vid.c_str());
+#include "llmediaimplgstreamer_syms_rawv.inc"
+ rtn = !sym_error;
+ }
+ else
+ {
+ INFOMSG("Couldn't load DSO: %s", gst_dso_name_vid.c_str());
+ rtn = false; // failure
+ }
+ }
+ else
+ {
+ INFOMSG("Couldn't load DSO: %s", gst_dso_name.c_str());
+ rtn = false; // failure
+ }
+
+ if (sym_error)
+ {
+ WARNMSG("Failed to find necessary symbols in GStreamer libraries.");
+ }
+
+ if ( sSymGSTDSOHandle )
+ {
+ sSymGSTDSOHandleV = sSymGSTDSOHandle;
+ sSymGSTDSOHandle = NULL;
+ }
+#undef LL_GST_SYM
+
+ sSymsGrabbed = !!rtn;
+ return rtn;
+}
+
+
+void ungrab_gst_syms()
+{
+ // should be safe to call regardless of whether we've
+ // actually grabbed syms.
+
+ if ( sSymGSTDSOHandleG )
+ {
+ apr_dso_unload(sSymGSTDSOHandleG);
+ sSymGSTDSOHandleG = NULL;
+ }
+
+ if ( sSymGSTDSOHandleV )
+ {
+ apr_dso_unload(sSymGSTDSOHandleV);
+ sSymGSTDSOHandleV = NULL;
+ }
+
+ if ( sSymGSTDSOMemoryPool )
+ {
+ apr_pool_destroy(sSymGSTDSOMemoryPool);
+ sSymGSTDSOMemoryPool = NULL;
+ }
+
+ // NULL-out all of the symbols we'd grabbed
+#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{ll##GSTSYM = NULL;}while(0)
+#include "llmediaimplgstreamer_syms_raw.inc"
+#include "llmediaimplgstreamer_syms_rawv.inc"
+#undef LL_GST_SYM
+
+ sSymsGrabbed = false;
+}
+
+
+#endif // LL_GSTREAMER010_ENABLED
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h
new file mode 100644
index 0000000000..88f100af6e
--- /dev/null
+++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h
@@ -0,0 +1,80 @@
+/**
+ * @file llmediaimplgstreamer_syms.h
+ * @brief dynamic GStreamer symbol-grabbing code
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "linden_common.h"
+
+#if LL_GSTREAMER010_ENABLED
+
+extern "C" {
+#include <gst/gst.h>
+}
+
+bool grab_gst_syms(std::string gst_dso_name,
+ std::string gst_dso_name_vid);
+void ungrab_gst_syms();
+
+#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) extern RTN (*ll##GSTSYM)(__VA_ARGS__)
+#include "llmediaimplgstreamer_syms_raw.inc"
+#include "llmediaimplgstreamer_syms_rawv.inc"
+#undef LL_GST_SYM
+
+// regrettable hacks to give us better runtime compatibility with older systems
+#define llg_return_if_fail(COND) do{if (!(COND)) return;}while(0)
+#define llg_return_val_if_fail(COND,V) do{if (!(COND)) return V;}while(0)
+
+// regrettable hacks because GStreamer was not designed for runtime loading
+#undef GST_TYPE_MESSAGE
+#define GST_TYPE_MESSAGE (llgst_message_get_type())
+#undef GST_TYPE_OBJECT
+#define GST_TYPE_OBJECT (llgst_object_get_type())
+#undef GST_TYPE_PIPELINE
+#define GST_TYPE_PIPELINE (llgst_pipeline_get_type())
+#undef GST_TYPE_ELEMENT
+#define GST_TYPE_ELEMENT (llgst_element_get_type())
+#undef GST_TYPE_VIDEO_SINK
+#define GST_TYPE_VIDEO_SINK (llgst_video_sink_get_type())
+// more regrettable hacks to stub-out these .h-exposed GStreamer internals
+void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname);
+#undef _gst_debug_register_funcptr
+#define _gst_debug_register_funcptr ll_gst_debug_register_funcptr
+GstDebugCategory* ll_gst_debug_category_new(gchar *name, guint color, gchar *description);
+#undef _gst_debug_category_new
+#define _gst_debug_category_new ll_gst_debug_category_new
+#undef __gst_debug_enabled
+#define __gst_debug_enabled (0)
+
+// more hacks
+#define LLGST_MESSAGE_TYPE_NAME(M) (llgst_message_type_get_name(GST_MESSAGE_TYPE(M)))
+
+#endif // LL_GSTREAMER010_ENABLED
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc
new file mode 100644
index 0000000000..b33e59363d
--- /dev/null
+++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc
@@ -0,0 +1,51 @@
+
+// required symbols to grab
+LL_GST_SYM(true, gst_pad_peer_accept_caps, gboolean, GstPad *pad, GstCaps *caps);
+LL_GST_SYM(true, gst_buffer_new, GstBuffer*, void);
+LL_GST_SYM(true, gst_buffer_set_caps, void, GstBuffer*, GstCaps *);
+LL_GST_SYM(true, gst_structure_set_value, void, GstStructure *, const gchar *, const GValue*);
+LL_GST_SYM(true, gst_init_check, gboolean, int *argc, char **argv[], GError ** err);
+LL_GST_SYM(true, gst_message_get_type, GType, void);
+LL_GST_SYM(true, gst_message_type_get_name, const gchar*, GstMessageType type);
+LL_GST_SYM(true, gst_message_parse_error, void, GstMessage *message, GError **gerror, gchar **debug);
+LL_GST_SYM(true, gst_message_parse_warning, void, GstMessage *message, GError **gerror, gchar **debug);
+LL_GST_SYM(true, gst_message_parse_state_changed, void, GstMessage *message, GstState *oldstate, GstState *newstate, GstState *pending);
+LL_GST_SYM(true, gst_element_set_state, GstStateChangeReturn, GstElement *element, GstState state);
+LL_GST_SYM(true, gst_object_unref, void, gpointer object);
+LL_GST_SYM(true, gst_object_get_type, GType, void);
+LL_GST_SYM(true, gst_pipeline_get_type, GType, void);
+LL_GST_SYM(true, gst_pipeline_get_bus, GstBus*, GstPipeline *pipeline);
+LL_GST_SYM(true, gst_bus_add_watch, guint, GstBus * bus, GstBusFunc func, gpointer user_data);
+LL_GST_SYM(true, gst_element_factory_make, GstElement*, const gchar *factoryname, const gchar *name);
+LL_GST_SYM(true, gst_element_get_type, GType, void);
+LL_GST_SYM(true, gst_static_pad_template_get, GstPadTemplate*, GstStaticPadTemplate *pad_template);
+LL_GST_SYM(true, gst_element_class_add_pad_template, void, GstElementClass *klass, GstPadTemplate *temp);
+LL_GST_SYM(true, gst_element_class_set_details, void, GstElementClass *klass, const GstElementDetails *details);
+LL_GST_SYM(true, gst_caps_unref, void, GstCaps* caps);
+LL_GST_SYM(true, gst_caps_ref, GstCaps *, GstCaps* caps);
+//LL_GST_SYM(true, gst_caps_is_empty, gboolean, const GstCaps *caps);
+LL_GST_SYM(true, gst_caps_from_string, GstCaps *, const gchar *string);
+LL_GST_SYM(true, gst_caps_replace, void, GstCaps **caps, GstCaps *newcaps);
+LL_GST_SYM(true, gst_caps_get_structure, GstStructure *, const GstCaps *caps, guint index);
+LL_GST_SYM(true, gst_caps_copy, GstCaps *, const GstCaps * caps);
+//LL_GST_SYM(true, gst_caps_intersect, GstCaps *, const GstCaps *caps1, const GstCaps *caps2);
+LL_GST_SYM(true, gst_element_register, gboolean, GstPlugin *plugin, const gchar *name, guint rank, GType type);
+LL_GST_SYM(true, _gst_plugin_register_static, void, GstPluginDesc *desc);
+LL_GST_SYM(true, gst_structure_get_int, gboolean, const GstStructure *structure, const gchar *fieldname, gint *value);
+LL_GST_SYM(true, gst_structure_get_value, G_CONST_RETURN GValue *, const GstStructure *structure, const gchar *fieldname);
+LL_GST_SYM(true, gst_value_get_fraction_numerator, gint, const GValue *value);
+LL_GST_SYM(true, gst_value_get_fraction_denominator, gint, const GValue *value);
+LL_GST_SYM(true, gst_structure_get_name, G_CONST_RETURN gchar *, const GstStructure *structure);
+LL_GST_SYM(true, gst_element_seek, bool, GstElement *, gdouble, GstFormat, GstSeekFlags, GstSeekType, gint64, GstSeekType, gint64);
+
+// optional symbols to grab
+LL_GST_SYM(false, gst_registry_fork_set_enabled, void, gboolean enabled);
+LL_GST_SYM(false, gst_segtrap_set_enabled, void, gboolean enabled);
+LL_GST_SYM(false, gst_message_parse_buffering, void, GstMessage *message, gint *percent);
+LL_GST_SYM(false, gst_message_parse_info, void, GstMessage *message, GError **gerror, gchar **debug);
+LL_GST_SYM(false, gst_element_query_position, gboolean, GstElement *element, GstFormat *format, gint64 *cur);
+LL_GST_SYM(false, gst_version, void, guint *major, guint *minor, guint *micro, guint *nano);
+
+// GStreamer 'internal' symbols which may not be visible in some runtimes but are still used in expanded GStreamer header macros - yuck! We'll substitute our own stubs for these.
+//LL_GST_SYM(true, _gst_debug_register_funcptr, void, GstDebugFuncPtr func, gchar* ptrname);
+//LL_GST_SYM(true, _gst_debug_category_new, GstDebugCategory *, gchar *name, guint color, gchar *description);
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc
new file mode 100644
index 0000000000..14fbcb48b9
--- /dev/null
+++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc
@@ -0,0 +1,5 @@
+
+// required symbols to grab
+LL_GST_SYM(true, gst_video_sink_get_type, GType, void);
+
+// optional symbols to grab
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h
new file mode 100644
index 0000000000..799808aa8b
--- /dev/null
+++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h
@@ -0,0 +1,61 @@
+/**
+ * @file llmediaimplgstreamertriviallogging.h
+ * @brief minimal logging utilities.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#ifndef __LLMEDIAIMPLGSTREAMERTRIVIALLOGGING_H__
+#define __LLMEDIAIMPLGSTREAMERTRIVIALLOGGING_H__
+
+#include <cstdio>
+
+extern "C" {
+#include <sys/types.h>
+#include <unistd.h>
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Debug/Info/Warning macros.
+#define MSGMODULEFOO "(media plugin)"
+#define STDERRMSG(...) do{\
+ fprintf(stderr, " pid:%d: ", (int)getpid());\
+ fprintf(stderr, MSGMODULEFOO " %s:%d: ", __FUNCTION__, __LINE__);\
+ fprintf(stderr, __VA_ARGS__);\
+ fputc('\n',stderr);\
+ }while(0)
+#define NULLMSG(...) do{}while(0)
+
+#define DEBUGMSG NULLMSG
+#define INFOMSG STDERRMSG
+#define WARNMSG STDERRMSG
+/////////////////////////////////////////////////////////////////////////
+
+#endif /* __LLMEDIAIMPLGSTREAMERTRIVIALLOGGING_H__ */
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
new file mode 100644
index 0000000000..484948bd9f
--- /dev/null
+++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
@@ -0,0 +1,533 @@
+/**
+ * @file llmediaimplgstreamervidplug.h
+ * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#if LL_GSTREAMER010_ENABLED
+
+#include "linden_common.h"
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gst/video/gstvideosink.h>
+
+#include "llmediaimplgstreamer_syms.h"
+#include "llmediaimplgstreamertriviallogging.h"
+
+#include "llmediaimplgstreamervidplug.h"
+
+
+GST_DEBUG_CATEGORY_STATIC (gst_slvideo_debug);
+#define GST_CAT_DEFAULT gst_slvideo_debug
+
+
+#define SLV_SIZECAPS ", width=(int)[1,2048], height=(int)[1,2048] "
+#define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS
+
+static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE (
+ "sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SLV_ALLCAPS)
+ );
+
+GST_BOILERPLATE (GstSLVideo, gst_slvideo, GstVideoSink,
+ GST_TYPE_VIDEO_SINK);
+
+static void gst_slvideo_set_property (GObject * object, guint prop_id,
+ const GValue * value,
+ GParamSpec * pspec);
+static void gst_slvideo_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+static void
+gst_slvideo_base_init (gpointer gclass)
+{
+ static GstElementDetails element_details = {
+ (gchar*)"PluginTemplate",
+ (gchar*)"Generic/PluginTemplate",
+ (gchar*)"Generic Template Element",
+ (gchar*)"Linden Lab"
+ };
+ GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
+
+ llgst_element_class_add_pad_template (element_class,
+ llgst_static_pad_template_get (&sink_factory));
+ llgst_element_class_set_details (element_class, &element_details);
+}
+
+
+static void
+gst_slvideo_finalize (GObject * object)
+{
+ GstSLVideo *slvideo;
+ slvideo = GST_SLVIDEO (object);
+ if (slvideo->caps)
+ {
+ llgst_caps_unref(slvideo->caps);
+ }
+
+ G_OBJECT_CLASS(parent_class)->finalize (object);
+}
+
+
+static GstFlowReturn
+gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf)
+{
+ GstSLVideo *slvideo;
+ llg_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
+
+ slvideo = GST_SLVIDEO(bsink);
+
+ DEBUGMSG("transferring a frame of %dx%d <- %p (%d)",
+ slvideo->width, slvideo->height, GST_BUFFER_DATA(buf),
+ slvideo->format);
+
+ if (GST_BUFFER_DATA(buf))
+ {
+ // copy frame and frame info into neutral territory
+ GST_OBJECT_LOCK(slvideo);
+ slvideo->retained_frame_ready = TRUE;
+ slvideo->retained_frame_width = slvideo->width;
+ slvideo->retained_frame_height = slvideo->height;
+ slvideo->retained_frame_format = slvideo->format;
+ int rowbytes =
+ SLVPixelFormatBytes[slvideo->retained_frame_format] *
+ slvideo->retained_frame_width;
+ int needbytes = rowbytes * slvideo->retained_frame_width;
+ // resize retained frame hunk only if necessary
+ if (needbytes != slvideo->retained_frame_allocbytes)
+ {
+ delete[] slvideo->retained_frame_data;
+ slvideo->retained_frame_data = new unsigned char[needbytes];
+ slvideo->retained_frame_allocbytes = needbytes;
+
+ }
+ // copy the actual frame data to neutral territory -
+ // flipped, for GL reasons
+ for (int ypos=0; ypos<slvideo->height; ++ypos)
+ {
+ memcpy(&slvideo->retained_frame_data[(slvideo->height-1-ypos)*rowbytes],
+ &(((unsigned char*)GST_BUFFER_DATA(buf))[ypos*rowbytes]),
+ rowbytes);
+ }
+ // done with the shared data
+ GST_OBJECT_UNLOCK(slvideo);
+ }
+
+ return GST_FLOW_OK;
+}
+
+
+static GstStateChangeReturn
+gst_slvideo_change_state(GstElement * element, GstStateChange transition)
+{
+ GstSLVideo *slvideo;
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+
+ slvideo = GST_SLVIDEO (element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ break;
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ break;
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ return ret;
+
+ switch (transition) {
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ slvideo->fps_n = 0;
+ slvideo->fps_d = 1;
+ GST_VIDEO_SINK_WIDTH(slvideo) = 0;
+ GST_VIDEO_SINK_HEIGHT(slvideo) = 0;
+ break;
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+
+static GstCaps *
+gst_slvideo_get_caps (GstBaseSink * bsink)
+{
+ GstSLVideo *slvideo;
+ slvideo = GST_SLVIDEO(bsink);
+
+ return llgst_caps_ref (slvideo->caps);
+}
+
+
+/* this function handles the link with other elements */
+static gboolean
+gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps)
+{
+ GstSLVideo *filter;
+ GstStructure *structure;
+
+ GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps);
+
+ filter = GST_SLVIDEO(bsink);
+
+ int width, height;
+ gboolean ret;
+ const GValue *fps;
+ const GValue *par;
+ structure = llgst_caps_get_structure (caps, 0);
+ ret = llgst_structure_get_int (structure, "width", &width);
+ ret = ret && llgst_structure_get_int (structure, "height", &height);
+ fps = llgst_structure_get_value (structure, "framerate");
+ ret = ret && (fps != NULL);
+ par = llgst_structure_get_value (structure, "pixel-aspect-ratio");
+ if (!ret)
+ return FALSE;
+
+ INFOMSG("** filter caps set with width=%d, height=%d", width, height);
+
+ GST_OBJECT_LOCK(filter);
+
+ filter->width = width;
+ filter->height = height;
+
+ filter->fps_n = llgst_value_get_fraction_numerator(fps);
+ filter->fps_d = llgst_value_get_fraction_denominator(fps);
+ if (par)
+ {
+ filter->par_n = llgst_value_get_fraction_numerator(par);
+ filter->par_d = llgst_value_get_fraction_denominator(par);
+ }
+ else
+ {
+ filter->par_n = 1;
+ filter->par_d = 1;
+ }
+ GST_VIDEO_SINK_WIDTH(filter) = width;
+ GST_VIDEO_SINK_HEIGHT(filter) = height;
+
+ // crufty lump - we *always* accept *only* RGBX now.
+ /*
+ filter->format = SLV_PF_UNKNOWN;
+ if (0 == strcmp(llgst_structure_get_name(structure),
+ "video/x-raw-rgb"))
+ {
+ int red_mask;
+ int green_mask;
+ int blue_mask;
+ llgst_structure_get_int(structure, "red_mask", &red_mask);
+ llgst_structure_get_int(structure, "green_mask", &green_mask);
+ llgst_structure_get_int(structure, "blue_mask", &blue_mask);
+ if ((unsigned int)red_mask == 0xFF000000 &&
+ (unsigned int)green_mask == 0x00FF0000 &&
+ (unsigned int)blue_mask == 0x0000FF00)
+ {
+ filter->format = SLV_PF_RGBX;
+ //fprintf(stderr, "\n\nPIXEL FORMAT RGB\n\n");
+ } else if ((unsigned int)red_mask == 0x0000FF00 &&
+ (unsigned int)green_mask == 0x00FF0000 &&
+ (unsigned int)blue_mask == 0xFF000000)
+ {
+ filter->format = SLV_PF_BGRX;
+ //fprintf(stderr, "\n\nPIXEL FORMAT BGR\n\n");
+ }
+ }*/
+
+ filter->format = SLV_PF_RGBX;
+
+ GST_OBJECT_UNLOCK(filter);
+
+ return TRUE;
+}
+
+
+static gboolean
+gst_slvideo_start (GstBaseSink * bsink)
+{
+ GstSLVideo *slvideo;
+ gboolean ret = TRUE;
+
+ slvideo = GST_SLVIDEO(bsink);
+
+ return ret;
+}
+
+static gboolean
+gst_slvideo_stop (GstBaseSink * bsink)
+{
+ GstSLVideo *slvideo;
+ slvideo = GST_SLVIDEO(bsink);
+
+ // free-up retained frame buffer
+ GST_OBJECT_LOCK(slvideo);
+ slvideo->retained_frame_ready = FALSE;
+ delete[] slvideo->retained_frame_data;
+ slvideo->retained_frame_data = NULL;
+ slvideo->retained_frame_allocbytes = 0;
+ GST_OBJECT_UNLOCK(slvideo);
+
+ return TRUE;
+}
+
+
+static GstFlowReturn
+gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
+ GstCaps * caps, GstBuffer ** buf)
+{
+ gint width, height;
+ GstStructure *structure = NULL;
+ GstSLVideo *slvideo;
+ slvideo = GST_SLVIDEO(bsink);
+
+ // caps == requested caps
+ // we can ignore these and reverse-negotiate our preferred dimensions with
+ // the peer if we like - we need to do this to obey dynamic resize requests
+ // flowing in from the app.
+ structure = llgst_caps_get_structure (caps, 0);
+ if (!llgst_structure_get_int(structure, "width", &width) ||
+ !llgst_structure_get_int(structure, "height", &height))
+ {
+ GST_WARNING_OBJECT (slvideo, "no width/height in caps %" GST_PTR_FORMAT, caps);
+ return GST_FLOW_NOT_NEGOTIATED;
+ }
+
+ GstBuffer *newbuf = llgst_buffer_new();
+ bool made_bufferdata_ptr = false;
+#define MAXDEPTHHACK 4
+
+ GST_OBJECT_LOCK(slvideo);
+ if (slvideo->resize_forced_always) // app is giving us a fixed size to work with
+ {
+ gint slwantwidth, slwantheight;
+ slwantwidth = slvideo->resize_try_width;
+ slwantheight = slvideo->resize_try_height;
+
+ if (slwantwidth != width ||
+ slwantheight != height)
+ {
+ // don't like requested caps, we will issue our own suggestion - copy
+ // the requested caps but substitute our own width and height and see
+ // if our peer is happy with that.
+
+ GstCaps *desired_caps;
+ GstStructure *desired_struct;
+ desired_caps = llgst_caps_copy (caps);
+ desired_struct = llgst_caps_get_structure (desired_caps, 0);
+
+ GValue value = {0};
+ g_value_init(&value, G_TYPE_INT);
+ g_value_set_int(&value, slwantwidth);
+ llgst_structure_set_value (desired_struct, "width", &value);
+ g_value_unset(&value);
+ g_value_init(&value, G_TYPE_INT);
+ g_value_set_int(&value, slwantheight);
+ llgst_structure_set_value (desired_struct, "height", &value);
+
+ if (llgst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (slvideo),
+ desired_caps))
+ {
+ // todo: re-use buffers from a pool?
+ // todo: set MALLOCDATA to null, set DATA to point straight to shm?
+
+ // peer likes our cap suggestion
+ DEBUGMSG("peer loves us :)");
+ GST_BUFFER_SIZE(newbuf) = slwantwidth * slwantheight * MAXDEPTHHACK;
+ GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf));
+ GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf);
+ llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), desired_caps);
+
+ made_bufferdata_ptr = true;
+ } else {
+ // peer hates our cap suggestion
+ INFOMSG("peer hates us :(");
+ llgst_caps_unref(desired_caps);
+ }
+ }
+ }
+
+ GST_OBJECT_UNLOCK(slvideo);
+
+ if (!made_bufferdata_ptr) // need to fallback to malloc at original size
+ {
+ GST_BUFFER_SIZE(newbuf) = width * height * MAXDEPTHHACK;
+ GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf));
+ GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf);
+ llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps);
+ }
+
+ *buf = GST_BUFFER_CAST(newbuf);
+
+ return GST_FLOW_OK;
+}
+
+
+/* initialize the plugin's class */
+static void
+gst_slvideo_class_init (GstSLVideoClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+ GstBaseSinkClass *gstbasesink_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
+ gstbasesink_class = (GstBaseSinkClass *) klass;
+
+ gobject_class->finalize = gst_slvideo_finalize;
+ gobject_class->set_property = gst_slvideo_set_property;
+ gobject_class->get_property = gst_slvideo_get_property;
+
+ gstelement_class->change_state = gst_slvideo_change_state;
+
+#define LLGST_DEBUG_FUNCPTR(p) (p)
+ gstbasesink_class->get_caps = LLGST_DEBUG_FUNCPTR (gst_slvideo_get_caps);
+ gstbasesink_class->set_caps = LLGST_DEBUG_FUNCPTR( gst_slvideo_set_caps);
+ gstbasesink_class->buffer_alloc=LLGST_DEBUG_FUNCPTR(gst_slvideo_buffer_alloc);
+ //gstbasesink_class->get_times = LLGST_DEBUG_FUNCPTR (gst_slvideo_get_times);
+ gstbasesink_class->preroll = LLGST_DEBUG_FUNCPTR (gst_slvideo_show_frame);
+ gstbasesink_class->render = LLGST_DEBUG_FUNCPTR (gst_slvideo_show_frame);
+
+ gstbasesink_class->start = LLGST_DEBUG_FUNCPTR (gst_slvideo_start);
+ gstbasesink_class->stop = LLGST_DEBUG_FUNCPTR (gst_slvideo_stop);
+
+ // gstbasesink_class->unlock = LLGST_DEBUG_FUNCPTR (gst_slvideo_unlock);
+#undef LLGST_DEBUG_FUNCPTR
+}
+
+
+/* initialize the new element
+ * instantiate pads and add them to element
+ * set functions
+ * initialize structure
+ */
+static void
+gst_slvideo_init (GstSLVideo * filter,
+ GstSLVideoClass * gclass)
+{
+ filter->caps = NULL;
+ filter->width = -1;
+ filter->height = -1;
+
+ // this is the info we share with the client app
+ GST_OBJECT_LOCK(filter);
+ filter->retained_frame_ready = FALSE;
+ filter->retained_frame_data = NULL;
+ filter->retained_frame_allocbytes = 0;
+ filter->retained_frame_width = filter->width;
+ filter->retained_frame_height = filter->height;
+ filter->retained_frame_format = SLV_PF_UNKNOWN;
+ GstCaps *caps = llgst_caps_from_string (SLV_ALLCAPS);
+ llgst_caps_replace (&filter->caps, caps);
+ filter->resize_forced_always = false;
+ filter->resize_try_width = -1;
+ filter->resize_try_height = -1;
+ GST_OBJECT_UNLOCK(filter);
+}
+
+static void
+gst_slvideo_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ llg_return_if_fail (GST_IS_SLVIDEO (object));
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_slvideo_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ llg_return_if_fail (GST_IS_SLVIDEO (object));
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+/* entry point to initialize the plug-in
+ * initialize the plug-in itself
+ * register the element factories and pad templates
+ * register the features
+ */
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ DEBUGMSG("PLUGIN INIT");
+
+ GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, (gchar*)"private-slvideo-plugin",
+ 0, (gchar*)"Second Life Video Sink");
+
+ return llgst_element_register (plugin, "private-slvideo",
+ GST_RANK_NONE, GST_TYPE_SLVIDEO);
+}
+
+/* this is the structure that gstreamer looks for to register plugins
+ */
+/* NOTE: Can't rely upon GST_PLUGIN_DEFINE_STATIC to self-register, since
+ some g++ versions buggily avoid __attribute__((constructor)) functions -
+ so we provide an explicit plugin init function.
+ */
+void gst_slvideo_init_class (void)
+{
+#define PACKAGE "packagehack"
+ // this macro quietly refers to PACKAGE internally
+ static GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "private-slvideoplugin",
+ "SL Video sink plugin",
+ plugin_init, "0.1", GST_LICENSE_UNKNOWN,
+ "Second Life",
+ "http://www.secondlife.com/");
+#undef PACKAGE
+ ll_gst_plugin_register_static (&gst_plugin_desc);
+ DEBUGMSG("CLASS INIT");
+}
+
+#endif // LL_GSTREAMER010_ENABLED
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h
new file mode 100644
index 0000000000..8f1cf84978
--- /dev/null
+++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h
@@ -0,0 +1,111 @@
+/**
+ * @file llmediaimplgstreamervidplug.h
+ * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#ifndef __GST_SLVIDEO_H__
+#define __GST_SLVIDEO_H__
+
+#if LL_GSTREAMER010_ENABLED
+
+extern "C" {
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gst/video/gstvideosink.h>
+}
+
+G_BEGIN_DECLS
+
+/* #defines don't like whitespacey bits */
+#define GST_TYPE_SLVIDEO \
+ (gst_slvideo_get_type())
+#define GST_SLVIDEO(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SLVIDEO,GstSLVideo))
+#define GST_SLVIDEO_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SLVIDEO,GstSLVideoClass))
+#define GST_IS_SLVIDEO(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SLVIDEO))
+#define GST_IS_SLVIDEO_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SLVIDEO))
+
+typedef struct _GstSLVideo GstSLVideo;
+typedef struct _GstSLVideoClass GstSLVideoClass;
+
+typedef enum {
+ SLV_PF_UNKNOWN = 0,
+ SLV_PF_RGBX = 1,
+ SLV_PF_BGRX = 2,
+ SLV__END = 3
+} SLVPixelFormat;
+const int SLVPixelFormatBytes[SLV__END] = {1, 4, 4};
+
+struct _GstSLVideo
+{
+ GstVideoSink video_sink;
+
+ GstCaps *caps;
+
+ int fps_n, fps_d;
+ int par_n, par_d;
+ int height, width;
+ SLVPixelFormat format;
+
+ // SHARED WITH APPLICATION:
+ // Access to the following should be protected by GST_OBJECT_LOCK() on
+ // the GstSLVideo object, and should be totally consistent upon UNLOCK
+ // (i.e. all written at once to reflect the current retained frame info
+ // when the retained frame is updated.)
+ bool retained_frame_ready; // new frame ready since flag last reset. (*TODO: could get the writer to wait on a semaphore instead of having the reader poll, potentially making dropped frames somewhat cheaper.)
+ unsigned char* retained_frame_data;
+ int retained_frame_allocbytes;
+ int retained_frame_width, retained_frame_height;
+ SLVPixelFormat retained_frame_format;
+ // sticky resize info
+ bool resize_forced_always;
+ int resize_try_width;
+ int resize_try_height;
+};
+
+struct _GstSLVideoClass
+{
+ GstVideoSinkClass parent_class;
+};
+
+GType gst_slvideo_get_type (void);
+
+void gst_slvideo_init_class (void);
+
+G_END_DECLS
+
+#endif // LL_GSTREAMER010_ENABLED
+
+#endif /* __GST_SLVIDEO_H__ */
diff --git a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp b/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp
new file mode 100644
index 0000000000..26173314a7
--- /dev/null
+++ b/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp
@@ -0,0 +1,1215 @@
+/**
+ * @file media_plugin_gstreamer010.cpp
+ * @brief GStreamer-0.10 plugin for LLMedia API plugin system
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "linden_common.h"
+
+#include "llgl.h"
+
+#include "llplugininstance.h"
+#include "llpluginmessage.h"
+#include "llpluginmessageclasses.h"
+#include "media_plugin_base.h"
+
+#if LL_GSTREAMER010_ENABLED
+
+extern "C" {
+#include <gst/gst.h>
+}
+
+#include "llmediaimplgstreamer.h"
+#include "llmediaimplgstreamertriviallogging.h"
+
+#include "llmediaimplgstreamervidplug.h"
+
+#include "llmediaimplgstreamer_syms.h"
+
+//////////////////////////////////////////////////////////////////////////////
+//
+class MediaPluginGStreamer010 : public MediaPluginBase
+{
+public:
+ MediaPluginGStreamer010(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
+ ~MediaPluginGStreamer010();
+
+ /* virtual */ void receiveMessage(const char *message_string);
+
+ static bool startup();
+ static bool closedown();
+
+ gboolean processGSTEvents(GstBus *bus,
+ GstMessage *message);
+
+private:
+ std::string getVersion();
+ bool navigateTo( const std::string urlIn );
+ bool seek( double time_sec );
+ bool setVolume( float volume );
+
+ // misc
+ bool pause();
+ bool stop();
+ bool play(double rate);
+ bool getTimePos(double &sec_out);
+
+ static const double MIN_LOOP_SEC = 1.0F;
+
+ bool mIsLooping;
+
+ enum ECommand {
+ COMMAND_NONE,
+ COMMAND_STOP,
+ COMMAND_PLAY,
+ COMMAND_FAST_FORWARD,
+ COMMAND_FAST_REWIND,
+ COMMAND_PAUSE,
+ COMMAND_SEEK,
+ };
+ ECommand mCommand;
+
+private:
+ bool unload();
+ bool load();
+
+ bool update(int milliseconds);
+ void mouseDown( int x, int y );
+ void mouseUp( int x, int y );
+ void mouseMove( int x, int y );
+
+ void sizeChanged();
+
+ static bool mDoneInit;
+
+ guint mBusWatchID;
+
+ float mVolume;
+
+ int mDepth;
+
+ // media NATURAL size
+ int mNaturalWidth;
+ int mNaturalHeight;
+ // media current size
+ int mCurrentWidth;
+ int mCurrentHeight;
+ int mCurrentRowbytes;
+ // previous media size so we can detect changes
+ int mPreviousWidth;
+ int mPreviousHeight;
+ // desired render size from host
+ int mWidth;
+ int mHeight;
+ // padded texture size we need to write into
+ int mTextureWidth;
+ int mTextureHeight;
+
+ int mTextureFormatPrimary;
+ int mTextureFormatType;
+
+ bool mSeekWanted;
+ double mSeekDestination;
+
+ // Very GStreamer-specific
+ GMainLoop *mPump; // event pump for this media
+ GstElement *mPlaybin;
+ GstSLVideo *mVideoSink;
+};
+
+//static
+bool MediaPluginGStreamer010::mDoneInit = false;
+
+MediaPluginGStreamer010::MediaPluginGStreamer010(
+ LLPluginInstance::sendMessageFunction host_send_func,
+ void *host_user_data ) :
+ MediaPluginBase(host_send_func, host_user_data),
+ mBusWatchID ( 0 ),
+ mCurrentRowbytes ( 4 ),
+ mTextureFormatPrimary ( GL_RGBA ),
+ mTextureFormatType ( GL_UNSIGNED_INT_8_8_8_8_REV ),
+ mSeekWanted(false),
+ mSeekDestination(0.0),
+ mPump ( NULL ),
+ mPlaybin ( NULL ),
+ mVideoSink ( NULL ),
+ mCommand ( COMMAND_NONE )
+{
+ std::ostringstream str;
+ INFOMSG("MediaPluginGStreamer010 constructor - my PID=%u", U32(getpid()));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+//#define LL_GST_REPORT_STATE_CHANGES
+#ifdef LL_GST_REPORT_STATE_CHANGES
+static char* get_gst_state_name(GstState state)
+{
+ switch (state) {
+ case GST_STATE_VOID_PENDING: return "VOID_PENDING";
+ case GST_STATE_NULL: return "NULL";
+ case GST_STATE_READY: return "READY";
+ case GST_STATE_PAUSED: return "PAUSED";
+ case GST_STATE_PLAYING: return "PLAYING";
+ }
+ return "(unknown)";
+}
+#endif // LL_GST_REPORT_STATE_CHANGES
+
+gboolean
+MediaPluginGStreamer010::processGSTEvents(GstBus *bus,
+ GstMessage *message)
+{
+ if (!message)
+ return TRUE; // shield against GStreamer bug
+
+ if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_STATE_CHANGED &&
+ GST_MESSAGE_TYPE(message) != GST_MESSAGE_BUFFERING)
+ {
+ DEBUGMSG("Got GST message type: %s",
+ LLGST_MESSAGE_TYPE_NAME (message));
+ }
+ else
+ {
+ // TODO: grok 'duration' message type
+ DEBUGMSG("Got GST message type: %s",
+ LLGST_MESSAGE_TYPE_NAME (message));
+ }
+
+ switch (GST_MESSAGE_TYPE (message)) {
+ case GST_MESSAGE_BUFFERING: {
+ // NEEDS GST 0.10.11+
+ if (llgst_message_parse_buffering)
+ {
+ gint percent = 0;
+ llgst_message_parse_buffering(message, &percent);
+ DEBUGMSG("GST buffering: %d%%", percent);
+ }
+ break;
+ }
+ case GST_MESSAGE_STATE_CHANGED: {
+ GstState old_state;
+ GstState new_state;
+ GstState pending_state;
+ llgst_message_parse_state_changed(message,
+ &old_state,
+ &new_state,
+ &pending_state);
+#ifdef LL_GST_REPORT_STATE_CHANGES
+ // not generally very useful, and rather spammy.
+ DEBUGMSG("state change (old,<new>,pending): %s,<%s>,%s",
+ get_gst_state_name(old_state),
+ get_gst_state_name(new_state),
+ get_gst_state_name(pending_state));
+#endif // LL_GST_REPORT_STATE_CHANGES
+
+ switch (new_state) {
+ case GST_STATE_VOID_PENDING:
+ break;
+ case GST_STATE_NULL:
+ break;
+ case GST_STATE_READY:
+ setStatus(STATUS_LOADED);
+ break;
+ case GST_STATE_PAUSED:
+ setStatus(STATUS_PAUSED);
+ break;
+ case GST_STATE_PLAYING:
+ setStatus(STATUS_PLAYING);
+ break;
+ }
+ break;
+ }
+ case GST_MESSAGE_ERROR: {
+ GError *err = NULL;
+ gchar *debug = NULL;
+
+ llgst_message_parse_error (message, &err, &debug);
+ WARNMSG("GST error: %s", err?err->message:"(unknown)");
+ if (err)
+ g_error_free (err);
+ g_free (debug);
+
+ mCommand = COMMAND_STOP;
+
+ setStatus(STATUS_ERROR);
+
+ break;
+ }
+ case GST_MESSAGE_INFO: {
+ if (llgst_message_parse_info)
+ {
+ GError *err = NULL;
+ gchar *debug = NULL;
+
+ llgst_message_parse_info (message, &err, &debug);
+ INFOMSG("GST info: %s", err?err->message:"(unknown)");
+ if (err)
+ g_error_free (err);
+ g_free (debug);
+ }
+ break;
+ }
+ case GST_MESSAGE_WARNING: {
+ GError *err = NULL;
+ gchar *debug = NULL;
+
+ llgst_message_parse_warning (message, &err, &debug);
+ WARNMSG("GST warning: %s", err?err->message:"(unknown)");
+ if (err)
+ g_error_free (err);
+ g_free (debug);
+
+ break;
+ }
+ case GST_MESSAGE_EOS:
+ /* end-of-stream */
+ DEBUGMSG("GST end-of-stream.");
+ if (mIsLooping)
+ {
+ DEBUGMSG("looping media...");
+ double eos_pos_sec = 0.0F;
+ bool got_eos_position = getTimePos(eos_pos_sec);
+
+ if (got_eos_position && eos_pos_sec < MIN_LOOP_SEC)
+ {
+ // if we know that the movie is really short, don't
+ // loop it else it can easily become a time-hog
+ // because of GStreamer spin-up overhead
+ DEBUGMSG("really short movie (%0.3fsec) - not gonna loop this, pausing instead.", eos_pos_sec);
+ // inject a COMMAND_PAUSE
+ mCommand = COMMAND_PAUSE;
+ }
+ else
+ {
+#undef LLGST_LOOP_BY_SEEKING
+// loop with a stop-start instead of a seek, because it actually seems rather
+// faster than seeking on remote streams.
+#ifdef LLGST_LOOP_BY_SEEKING
+ // first, try looping by an explicit rewind
+ bool seeksuccess = seek(0.0);
+ if (seeksuccess)
+ {
+ play(1.0);
+ }
+ else
+#endif // LLGST_LOOP_BY_SEEKING
+ { // use clumsy stop-start to loop
+ DEBUGMSG("didn't loop by rewinding - stopping and starting instead...");
+ stop();
+ play(1.0);
+ }
+ }
+ }
+ else // not a looping media
+ {
+ // inject a COMMAND_STOP
+ mCommand = COMMAND_STOP;
+ }
+ break;
+ default:
+ /* unhandled message */
+ break;
+ }
+
+ /* we want to be notified again the next time there is a message
+ * on the bus, so return true (false means we want to stop watching
+ * for messages on the bus and our callback should not be called again)
+ */
+ return TRUE;
+}
+
+extern "C" {
+gboolean
+llmediaimplgstreamer_bus_callback (GstBus *bus,
+ GstMessage *message,
+ gpointer data)
+{
+ MediaPluginGStreamer010 *impl = (MediaPluginGStreamer010*)data;
+ return impl->processGSTEvents(bus, message);
+}
+} // extern "C"
+
+
+
+bool
+MediaPluginGStreamer010::navigateTo ( const std::string urlIn )
+{
+ if (!mDoneInit)
+ return false; // error
+
+ setStatus(STATUS_LOADING);
+
+ DEBUGMSG("Setting media URI: %s", urlIn.c_str());
+
+ mSeekWanted = false;
+
+ if (NULL == mPump ||
+ NULL == mPlaybin)
+ {
+ setStatus(STATUS_ERROR);
+ return false; // error
+ }
+
+ // set URI
+ g_object_set (G_OBJECT (mPlaybin), "uri", urlIn.c_str(), NULL);
+ //g_object_set (G_OBJECT (mPlaybin), "uri", "file:///tmp/movie", NULL);
+
+ // navigateTo implicitly plays, too.
+ play(1.0);
+
+ return true;
+}
+
+
+bool
+MediaPluginGStreamer010::update(int milliseconds)
+{
+ if (!mDoneInit)
+ return false; // error
+
+ DEBUGMSG("updating media...");
+
+ // sanity check
+ if (NULL == mPump ||
+ NULL == mPlaybin)
+ {
+ DEBUGMSG("dead media...");
+ return false;
+ }
+
+ // see if there's an outstanding seek wanted
+ if (mSeekWanted &&
+ // bleh, GST has to be happy that the movie is really truly playing
+ // or it may quietly ignore the seek (with rtsp:// at least).
+ (GST_STATE(mPlaybin) == GST_STATE_PLAYING))
+ {
+ seek(mSeekDestination);
+ mSeekWanted = false;
+ }
+
+ // *TODO: time-limit - but there isn't a lot we can do here, most
+ // time is spent in gstreamer's own opaque worker-threads. maybe
+ // we can do something sneaky like only unlock the video object
+ // for 'milliseconds' and otherwise hold the lock.
+ while (g_main_context_pending(g_main_loop_get_context(mPump)))
+ {
+ g_main_context_iteration(g_main_loop_get_context(mPump), FALSE);
+ }
+
+ // check for availability of a new frame
+
+ if (mVideoSink)
+ {
+ GST_OBJECT_LOCK(mVideoSink);
+ if (mVideoSink->retained_frame_ready)
+ {
+ DEBUGMSG("NEW FRAME READY");
+
+ if (mVideoSink->retained_frame_width != mCurrentWidth ||
+ mVideoSink->retained_frame_height != mCurrentHeight)
+ // *TODO: also check for change in format
+ {
+ // just resize container, don't consume frame
+ int neww = mVideoSink->retained_frame_width;
+ int newh = mVideoSink->retained_frame_height;
+
+ int newd = 4;
+ mTextureFormatPrimary = GL_RGBA;
+ mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV;
+
+ /*
+ int newd = SLVPixelFormatBytes[mVideoSink->retained_frame_format];
+ if (SLV_PF_BGRX == mVideoSink->retained_frame_format)
+ {
+ mTextureFormatPrimary = GL_BGRA;
+ mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV;
+ }
+ else
+ {
+ mTextureFormatPrimary = GL_RGBA;
+ mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV;
+ }
+ */
+
+ GST_OBJECT_UNLOCK(mVideoSink);
+
+ mCurrentRowbytes = neww * newd;
+ DEBUGMSG("video container resized to %dx%d",
+ neww, newh);
+
+ mDepth = newd;
+ mCurrentWidth = neww;
+ mCurrentHeight = newh;
+ sizeChanged();
+ return true;
+ }
+
+ if (mPixels &&
+ mCurrentHeight <= mHeight &&
+ mCurrentWidth <= mWidth &&
+ !mTextureSegmentName.empty())
+ {
+ // we're gonna totally consume this frame - reset 'ready' flag
+ mVideoSink->retained_frame_ready = FALSE;
+ int destination_rowbytes = mWidth * mDepth;
+ for (int row=0; row<mCurrentHeight; ++row)
+ {
+ memcpy(&mPixels
+ [destination_rowbytes * row],
+ &mVideoSink->retained_frame_data
+ [mCurrentRowbytes * row],
+ mCurrentRowbytes);
+ }
+
+ GST_OBJECT_UNLOCK(mVideoSink);
+ DEBUGMSG("NEW FRAME REALLY TRULY CONSUMED, TELLING HOST");
+
+ setDirty(0,0,mCurrentWidth,mCurrentHeight);
+ }
+ else
+ {
+ // new frame ready, but we're not ready to
+ // consume it.
+
+ GST_OBJECT_UNLOCK(mVideoSink);
+
+ DEBUGMSG("NEW FRAME not consumed, still waiting for a shm segment and/or shm resize");
+ }
+
+ return true;
+ }
+ else
+ {
+ // nothing to do yet.
+ GST_OBJECT_UNLOCK(mVideoSink);
+ return true;
+ }
+ }
+
+ return true;
+}
+
+
+void
+MediaPluginGStreamer010::mouseDown( int x, int y )
+{
+ // do nothing
+}
+
+void
+MediaPluginGStreamer010::mouseUp( int x, int y )
+{
+ // do nothing
+}
+
+void
+MediaPluginGStreamer010::mouseMove( int x, int y )
+{
+ // do nothing
+}
+
+
+bool
+MediaPluginGStreamer010::pause()
+{
+ DEBUGMSG("pausing media...");
+ // todo: error-check this?
+ llgst_element_set_state(mPlaybin, GST_STATE_PAUSED);
+ return true;
+}
+
+bool
+MediaPluginGStreamer010::stop()
+{
+ DEBUGMSG("stopping media...");
+ // todo: error-check this?
+ llgst_element_set_state(mPlaybin, GST_STATE_READY);
+ return true;
+}
+
+bool
+MediaPluginGStreamer010::play(double rate)
+{
+ // NOTE: we don't actually support non-natural rate.
+
+ DEBUGMSG("playing media... rate=%f", rate);
+ // todo: error-check this?
+ llgst_element_set_state(mPlaybin, GST_STATE_PLAYING);
+ return true;
+}
+
+bool
+MediaPluginGStreamer010::setVolume( float volume )
+{
+ // we try to only update volume as conservatively as
+ // possible, as many gst-plugins-base versions up to at least
+ // November 2008 have critical race-conditions in setting volume - sigh
+ if (mVolume == volume)
+ return true; // nothing to do, everything's fine
+
+ mVolume = volume;
+ if (mDoneInit && mPlaybin)
+ {
+ g_object_set(mPlaybin, "volume", mVolume, NULL);
+ return true;
+ }
+
+ return false;
+}
+
+bool
+MediaPluginGStreamer010::seek(double time_sec)
+{
+ bool success = false;
+ if (mDoneInit && mPlaybin)
+ {
+ success = llgst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME,
+ GstSeekFlags(GST_SEEK_FLAG_FLUSH |
+ GST_SEEK_FLAG_KEY_UNIT),
+ GST_SEEK_TYPE_SET, gint64(time_sec*GST_SECOND),
+ GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
+ }
+ DEBUGMSG("MEDIA SEEK REQUEST to %fsec result was %d",
+ float(time_sec), int(success));
+ return success;
+}
+
+bool
+MediaPluginGStreamer010::getTimePos(double &sec_out)
+{
+ bool got_position = false;
+ if (mPlaybin)
+ {
+ gint64 pos;
+ GstFormat timefmt = GST_FORMAT_TIME;
+ got_position =
+ llgst_element_query_position &&
+ llgst_element_query_position(mPlaybin,
+ &timefmt,
+ &pos);
+ got_position = got_position
+ && (timefmt == GST_FORMAT_TIME);
+ // GStreamer may have other ideas, but we consider the current position
+ // undefined if not PLAYING or PAUSED
+ got_position = got_position &&
+ (GST_STATE(mPlaybin) == GST_STATE_PLAYING ||
+ GST_STATE(mPlaybin) == GST_STATE_PAUSED);
+ if (got_position && !GST_CLOCK_TIME_IS_VALID(pos))
+ {
+ if (GST_STATE(mPlaybin) == GST_STATE_PLAYING)
+ {
+ // if we're playing then we treat an invalid clock time
+ // as 0, for complicated reasons (insert reason here)
+ pos = 0;
+ }
+ else
+ {
+ got_position = false;
+ }
+
+ }
+ // If all the preconditions succeeded... we can trust the result.
+ if (got_position)
+ {
+ sec_out = double(pos) / double(GST_SECOND); // gst to sec
+ }
+ }
+ return got_position;
+}
+
+bool
+MediaPluginGStreamer010::load()
+{
+ if (!mDoneInit)
+ return false; // error
+
+ setStatus(STATUS_LOADING);
+
+ DEBUGMSG("setting up media...");
+
+ mIsLooping = false;
+ mVolume = 0.1234567; // minor hack to force an initial volume update
+
+ // Create a pumpable main-loop for this media
+ mPump = g_main_loop_new (NULL, FALSE);
+ if (!mPump)
+ {
+ setStatus(STATUS_ERROR);
+ return false; // error
+ }
+
+ // instantiate a playbin element to do the hard work
+ mPlaybin = llgst_element_factory_make ("playbin", "play");
+ if (!mPlaybin)
+ {
+ setStatus(STATUS_ERROR);
+ return false; // error
+ }
+
+ // get playbin's bus
+ GstBus *bus = llgst_pipeline_get_bus (GST_PIPELINE (mPlaybin));
+ if (!bus)
+ {
+ setStatus(STATUS_ERROR);
+ return false; // error
+ }
+ mBusWatchID = llgst_bus_add_watch (bus,
+ llmediaimplgstreamer_bus_callback,
+ this);
+ llgst_object_unref (bus);
+
+ if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) {
+ // instantiate a custom video sink
+ mVideoSink =
+ GST_SLVIDEO(llgst_element_factory_make ("private-slvideo", "slvideo"));
+ if (!mVideoSink)
+ {
+ WARNMSG("Could not instantiate private-slvideo element.");
+ // todo: cleanup.
+ setStatus(STATUS_ERROR);
+ return false; // error
+ }
+
+ // connect the pieces
+ g_object_set(mPlaybin, "video-sink", mVideoSink, NULL);
+ }
+
+ return true;
+}
+
+bool
+MediaPluginGStreamer010::unload ()
+{
+ if (!mDoneInit)
+ return false; // error
+
+ DEBUGMSG("unloading media...");
+
+ // stop getting callbacks for this bus
+ g_source_remove(mBusWatchID);
+ mBusWatchID = 0;
+
+ if (mPlaybin)
+ {
+ llgst_element_set_state (mPlaybin, GST_STATE_NULL);
+ llgst_object_unref (GST_OBJECT (mPlaybin));
+ mPlaybin = NULL;
+ }
+
+ if (mPump)
+ {
+ g_main_loop_quit(mPump);
+ mPump = NULL;
+ }
+
+ mVideoSink = NULL;
+
+ setStatus(STATUS_NONE);
+
+ return true;
+}
+
+
+//static
+bool
+MediaPluginGStreamer010::startup()
+{
+ // first - check if GStreamer is explicitly disabled
+ if (NULL != getenv("LL_DISABLE_GSTREAMER"))
+ return false;
+
+ // only do global GStreamer initialization once.
+ if (!mDoneInit)
+ {
+ g_thread_init(NULL);
+
+ // Init the glib type system - we need it.
+ g_type_init();
+
+ // Get symbols!
+#if LL_DARWIN
+ if (! grab_gst_syms("libgstreamer-0.10.dylib",
+ "libgstvideo-0.10.dylib") )
+#elseif LL_WINDOWS
+ if (! grab_gst_syms("libgstreamer-0.10.dll",
+ "libgstvideo-0.10.dll") )
+#else // linux or other ELFy unixoid
+ if (! grab_gst_syms("libgstreamer-0.10.so.0",
+ "libgstvideo-0.10.so.0") )
+#endif
+ {
+ WARNMSG("Couldn't find suitable GStreamer 0.10 support on this system - video playback disabled.");
+ return false;
+ }
+
+ if (llgst_segtrap_set_enabled)
+ {
+ llgst_segtrap_set_enabled(FALSE);
+ }
+ else
+ {
+ WARNMSG("gst_segtrap_set_enabled() is not available; plugin crashes won't be caught.");
+ }
+
+#if LL_LINUX
+ // Gstreamer tries a fork during init, waitpid-ing on it,
+ // which conflicts with any installed SIGCHLD handler...
+ struct sigaction tmpact, oldact;
+ if (llgst_registry_fork_set_enabled) {
+ // if we can disable SIGCHLD-using forking behaviour,
+ // do it.
+ llgst_registry_fork_set_enabled(false);
+ }
+ else {
+ // else temporarily install default SIGCHLD handler
+ // while GStreamer initialises
+ tmpact.sa_handler = SIG_DFL;
+ sigemptyset( &tmpact.sa_mask );
+ tmpact.sa_flags = SA_SIGINFO;
+ sigaction(SIGCHLD, &tmpact, &oldact);
+ }
+#endif // LL_LINUX
+
+ // Protect against GStreamer resetting the locale, yuck.
+ static std::string saved_locale;
+ saved_locale = setlocale(LC_ALL, NULL);
+
+ // finally, try to initialize GStreamer!
+ GError *err = NULL;
+ gboolean init_gst_success = llgst_init_check(NULL, NULL, &err);
+
+ // restore old locale
+ setlocale(LC_ALL, saved_locale.c_str() );
+
+#if LL_LINUX
+ // restore old SIGCHLD handler
+ if (!llgst_registry_fork_set_enabled)
+ sigaction(SIGCHLD, &oldact, NULL);
+#endif // LL_LINUX
+
+ if (!init_gst_success) // fail
+ {
+ if (err)
+ {
+ WARNMSG("GST init failed: %s", err->message);
+ g_error_free(err);
+ }
+ else
+ {
+ WARNMSG("GST init failed for unspecified reason.");
+ }
+ return false;
+ }
+
+ // Init our custom plugins - only really need do this once.
+ gst_slvideo_init_class();
+
+ mDoneInit = true;
+ }
+
+ return true;
+}
+
+
+void
+MediaPluginGStreamer010::sizeChanged()
+{
+ // the shared writing space has possibly changed size/location/whatever
+
+ // Check to see whether the movie's NATURAL size has been set yet
+ if (1 == mNaturalWidth &&
+ 1 == mNaturalHeight)
+ {
+ mNaturalWidth = mCurrentWidth;
+ mNaturalHeight = mCurrentHeight;
+ DEBUGMSG("Media NATURAL size better detected as %dx%d",
+ mNaturalWidth, mNaturalHeight);
+ }
+
+ // if the size has changed then the shm has changed and the app needs telling
+ if (mCurrentWidth != mPreviousWidth ||
+ mCurrentHeight != mPreviousHeight)
+ {
+ mPreviousWidth = mCurrentWidth;
+ mPreviousHeight = mCurrentHeight;
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request");
+ message.setValue("name", mTextureSegmentName);
+ message.setValueS32("width", mNaturalWidth);
+ message.setValueS32("height", mNaturalHeight);
+ DEBUGMSG("<--- Sending size change request to application with name: '%s' - natural size is %d x %d", mTextureSegmentName.c_str(), mNaturalWidth, mNaturalHeight);
+ sendMessage(message);
+ }
+}
+
+
+
+//static
+bool
+MediaPluginGStreamer010::closedown()
+{
+ if (!mDoneInit)
+ return false; // error
+
+ ungrab_gst_syms();
+
+ mDoneInit = false;
+
+ return true;
+}
+
+MediaPluginGStreamer010::~MediaPluginGStreamer010()
+{
+ DEBUGMSG("MediaPluginGStreamer010 destructor");
+
+ closedown();
+
+ DEBUGMSG("GStreamer010 closing down");
+}
+
+
+std::string
+MediaPluginGStreamer010::getVersion()
+{
+ std::string plugin_version = "GStreamer010 media plugin, GStreamer version ";
+ if (mDoneInit &&
+ llgst_version)
+ {
+ guint major, minor, micro, nano;
+ llgst_version(&major, &minor, &micro, &nano);
+ plugin_version += llformat("%u.%u.%u.%u (runtime), %u.%u.%u.%u (headers)", (unsigned int)major, (unsigned int)minor, (unsigned int)micro, (unsigned int)nano, (unsigned int)GST_VERSION_MAJOR, (unsigned int)GST_VERSION_MINOR, (unsigned int)GST_VERSION_MICRO, (unsigned int)GST_VERSION_NANO);
+ }
+ else
+ {
+ plugin_version += "(unknown)";
+ }
+ return plugin_version;
+}
+
+void MediaPluginGStreamer010::receiveMessage(const char *message_string)
+{
+ //std::cerr << "MediaPluginGStreamer010::receiveMessage: received message: \"" << message_string << "\"" << std::endl;
+
+ LLPluginMessage message_in;
+
+ if(message_in.parse(message_string) >= 0)
+ {
+ std::string message_class = message_in.getClass();
+ std::string message_name = message_in.getName();
+ if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
+ {
+ if(message_name == "init")
+ {
+ LLPluginMessage message("base", "init_response");
+ LLSD versions = LLSD::emptyMap();
+ versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
+ versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
+ versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION;
+ message.setValueLLSD("versions", versions);
+
+ if ( load() )
+ {
+ DEBUGMSG("GStreamer010 media instance set up");
+ }
+ else
+ {
+ WARNMSG("GStreamer010 media instance failed to set up");
+ }
+
+ message.setValue("plugin_version", getVersion());
+ sendMessage(message);
+
+ // Plugin gets to decide the texture parameters to use.
+ message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
+ // lame to have to decide this now, it depends on the movie. Oh well.
+ mDepth = 4;
+
+ mCurrentWidth = 1;
+ mCurrentHeight = 1;
+ mPreviousWidth = 1;
+ mPreviousHeight = 1;
+ mNaturalWidth = 1;
+ mNaturalHeight = 1;
+ mWidth = 1;
+ mHeight = 1;
+ mTextureWidth = 1;
+ mTextureHeight = 1;
+
+ message.setValueU32("format", GL_RGBA);
+ message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV);
+
+ message.setValueS32("depth", mDepth);
+ message.setValueS32("default_width", mWidth);
+ message.setValueS32("default_height", mHeight);
+ message.setValueU32("internalformat", GL_RGBA8);
+ message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left.
+ message.setValueBoolean("allow_downsample", true); // we respond with grace and performance if asked to downscale
+ sendMessage(message);
+ }
+ else if(message_name == "idle")
+ {
+ // no response is necessary here.
+ double time = message_in.getValueReal("time");
+
+ // Convert time to milliseconds for update()
+ update((int)(time * 1000.0f));
+ }
+ else if(message_name == "cleanup")
+ {
+ unload();
+ closedown();
+ }
+ else if(message_name == "shm_added")
+ {
+ SharedSegmentInfo info;
+ info.mAddress = message_in.getValuePointer("address");
+ info.mSize = (size_t)message_in.getValueS32("size");
+ std::string name = message_in.getValue("name");
+
+ std::ostringstream str;
+ INFOMSG("MediaPluginGStreamer010::receiveMessage: shared memory added, name: %s, size: %d, address: %p", name.c_str(), int(info.mSize), info.mAddress);
+
+ mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
+ }
+ else if(message_name == "shm_remove")
+ {
+ std::string name = message_in.getValue("name");
+
+ DEBUGMSG("MediaPluginGStreamer010::receiveMessage: shared memory remove, name = %s", name.c_str());
+
+ SharedSegmentMap::iterator iter = mSharedSegments.find(name);
+ if(iter != mSharedSegments.end())
+ {
+ if(mPixels == iter->second.mAddress)
+ {
+ // This is the currently active pixel buffer. Make sure we stop drawing to it.
+ mPixels = NULL;
+ mTextureSegmentName.clear();
+
+ // Make sure the movie decoder is no longer pointed at the shared segment.
+ sizeChanged();
+ }
+ mSharedSegments.erase(iter);
+ }
+ else
+ {
+ WARNMSG("MediaPluginGStreamer010::receiveMessage: unknown shared memory region!");
+ }
+
+ // Send the response so it can be cleaned up.
+ LLPluginMessage message("base", "shm_remove_response");
+ message.setValue("name", name);
+ sendMessage(message);
+ }
+ else
+ {
+ std::ostringstream str;
+ INFOMSG("MediaPluginGStreamer010::receiveMessage: unknown base message: %s", message_name.c_str());
+ }
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
+ {
+ if(message_name == "size_change")
+ {
+ std::string name = message_in.getValue("name");
+ S32 width = message_in.getValueS32("width");
+ S32 height = message_in.getValueS32("height");
+ S32 texture_width = message_in.getValueS32("texture_width");
+ S32 texture_height = message_in.getValueS32("texture_height");
+
+ std::ostringstream str;
+ INFOMSG("---->Got size change instruction from application with shm name: %s - size is %d x %d", name.c_str(), width, height);
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
+ message.setValue("name", name);
+ message.setValueS32("width", width);
+ message.setValueS32("height", height);
+ message.setValueS32("texture_width", texture_width);
+ message.setValueS32("texture_height", texture_height);
+ sendMessage(message);
+
+ if(!name.empty())
+ {
+ // Find the shared memory region with this name
+ SharedSegmentMap::iterator iter = mSharedSegments.find(name);
+ if(iter != mSharedSegments.end())
+ {
+ INFOMSG("*** Got size change with matching shm, new size is %d x %d", width, height);
+ INFOMSG("*** Got size change with matching shm, texture size size is %d x %d", texture_width, texture_height);
+
+ mPixels = (unsigned char*)iter->second.mAddress;
+ mTextureSegmentName = name;
+ mWidth = width;
+ mHeight = height;
+
+ if (texture_width > 1 ||
+ texture_height > 1) // not a dummy size from the app, a real explicit forced size
+ {
+ INFOMSG("**** = REAL RESIZE REQUEST FROM APP");
+
+ GST_OBJECT_LOCK(mVideoSink);
+ mVideoSink->resize_forced_always = true;
+ mVideoSink->resize_try_width = texture_width;
+ mVideoSink->resize_try_height = texture_height;
+ GST_OBJECT_UNLOCK(mVideoSink);
+ }
+
+ mTextureWidth = texture_width;
+ mTextureHeight = texture_height;
+ }
+ }
+ }
+ else if(message_name == "load_uri")
+ {
+ std::string uri = message_in.getValue("uri");
+ navigateTo( uri );
+ sendStatus();
+ }
+ else if(message_name == "mouse_event")
+ {
+ std::string event = message_in.getValue("event");
+ S32 x = message_in.getValueS32("x");
+ S32 y = message_in.getValueS32("y");
+
+ if(event == "down")
+ {
+ mouseDown(x, y);
+ }
+ else if(event == "up")
+ {
+ mouseUp(x, y);
+ }
+ else if(event == "move")
+ {
+ mouseMove(x, y);
+ };
+ };
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
+ {
+ if(message_name == "stop")
+ {
+ stop();
+ }
+ else if(message_name == "start")
+ {
+ double rate = 0.0;
+ if(message_in.hasValue("rate"))
+ {
+ rate = message_in.getValueReal("rate");
+ }
+ // NOTE: we don't actually support rate.
+ play(rate);
+ }
+ else if(message_name == "pause")
+ {
+ pause();
+ }
+ else if(message_name == "seek")
+ {
+ double time = message_in.getValueReal("time");
+ // defer the actual seek in case we haven't
+ // really truly started yet in which case there
+ // is nothing to seek upon
+ mSeekWanted = true;
+ mSeekDestination = time;
+ }
+ else if(message_name == "set_loop")
+ {
+ bool loop = message_in.getValueBoolean("loop");
+ mIsLooping = loop;
+ }
+ else if(message_name == "set_volume")
+ {
+ double volume = message_in.getValueReal("volume");
+ setVolume(volume);
+ }
+ }
+ else
+ {
+ INFOMSG("MediaPluginGStreamer010::receiveMessage: unknown message class: %s", message_class.c_str());
+ }
+ }
+}
+
+int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
+{
+ if (MediaPluginGStreamer010::startup())
+ {
+ MediaPluginGStreamer010 *self = new MediaPluginGStreamer010(host_send_func, host_user_data);
+ *plugin_send_func = MediaPluginGStreamer010::staticReceiveMessage;
+ *plugin_user_data = (void*)self;
+
+ return 0; // okay
+ }
+ else
+ {
+ return -1; // failed to init
+ }
+}
+
+#else // LL_GSTREAMER010_ENABLED
+
+// Stubbed-out class with constructor/destructor (necessary or windows linker
+// will just think its dead code and optimize it all out)
+class MediaPluginGStreamer010 : public MediaPluginBase
+{
+public:
+ MediaPluginGStreamer010(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
+ ~MediaPluginGStreamer010();
+ /* virtual */ void receiveMessage(const char *message_string);
+};
+
+MediaPluginGStreamer010::MediaPluginGStreamer010(
+ LLPluginInstance::sendMessageFunction host_send_func,
+ void *host_user_data ) :
+ MediaPluginBase(host_send_func, host_user_data)
+{
+ // no-op
+}
+
+MediaPluginGStreamer010::~MediaPluginGStreamer010()
+{
+ // no-op
+}
+
+void MediaPluginGStreamer010::receiveMessage(const char *message_string)
+{
+ // no-op
+}
+
+// We're building without GStreamer enabled. Just refuse to initialize.
+int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
+{
+ return -1;
+}
+
+#endif // LL_GSTREAMER010_ENABLED
diff --git a/indra/media_plugins/quicktime/CMakeLists.txt b/indra/media_plugins/quicktime/CMakeLists.txt
new file mode 100644
index 0000000000..f0b8f0d167
--- /dev/null
+++ b/indra/media_plugins/quicktime/CMakeLists.txt
@@ -0,0 +1,91 @@
+# -*- cmake -*-
+
+project(media_plugin_quicktime)
+
+include(00-Common)
+include(LLCommon)
+include(LLImage)
+include(LLPlugin)
+include(LLMath)
+include(LLRender)
+include(LLWindow)
+include(Linking)
+include(PluginAPI)
+include(MediaPluginBase)
+include(FindOpenGL)
+include(QuickTimePlugin)
+
+include_directories(
+ ${LLPLUGIN_INCLUDE_DIRS}
+ ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS}
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LLMATH_INCLUDE_DIRS}
+ ${LLIMAGE_INCLUDE_DIRS}
+ ${LLRENDER_INCLUDE_DIRS}
+ ${LLWINDOW_INCLUDE_DIRS}
+)
+
+if (DARWIN)
+ include(CMakeFindFrameworks)
+ find_library(CARBON_LIBRARY Carbon)
+endif (DARWIN)
+
+
+### media_plugin_quicktime
+
+set(media_plugin_quicktime_SOURCE_FILES
+ media_plugin_quicktime.cpp
+ )
+
+add_library(media_plugin_quicktime
+ SHARED
+ ${media_plugin_quicktime_SOURCE_FILES}
+)
+
+target_link_libraries(media_plugin_quicktime
+ ${LLPLUGIN_LIBRARIES}
+ ${MEDIA_PLUGIN_BASE_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+ ${QUICKTIME_LIBRARY}
+ ${PLUGIN_API_WINDOWS_LIBRARIES}
+)
+
+add_dependencies(media_plugin_quicktime
+ ${LLPLUGIN_LIBRARIES}
+ ${MEDIA_PLUGIN_BASE_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+)
+
+if (WINDOWS)
+ set_target_properties(
+ media_plugin_quicktime
+ PROPERTIES
+ LINK_FLAGS "/MANIFEST:NO"
+ )
+endif (WINDOWS)
+
+if (QUICKTIME)
+
+ add_definitions(-DLL_QUICKTIME_ENABLED=1)
+
+ if (DARWIN)
+ # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name
+ set_target_properties(
+ media_plugin_quicktime
+ PROPERTIES
+ PREFIX ""
+ BUILD_WITH_INSTALL_RPATH 1
+ INSTALL_NAME_DIR "@executable_path"
+ LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp"
+ )
+
+# We use a bunch of deprecated system APIs.
+ set_source_files_properties(
+ media_plugin_quicktime.cpp PROPERTIES
+ COMPILE_FLAGS -Wno-deprecated-declarations
+ )
+ find_library(CARBON_LIBRARY Carbon)
+ target_link_libraries(media_plugin_quicktime ${CARBON_LIBRARY})
+ endif (DARWIN)
+endif (QUICKTIME)
+
diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
new file mode 100644
index 0000000000..dbc44c8334
--- /dev/null
+++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
@@ -0,0 +1,1112 @@
+/**
+ * @file media_plugin_quicktime.cpp
+ * @brief QuickTime plugin for LLMedia API plugin system
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "linden_common.h"
+
+#include "llgl.h"
+
+#include "llplugininstance.h"
+#include "llpluginmessage.h"
+#include "llpluginmessageclasses.h"
+#include "media_plugin_base.h"
+
+#if LL_QUICKTIME_ENABLED
+
+#if defined(LL_DARWIN)
+ #include <QuickTime/QuickTime.h>
+#elif defined(LL_WINDOWS)
+ #include "MacTypes.h"
+ #include "QTML.h"
+ #include "Movies.h"
+ #include "QDoffscreen.h"
+ #include "FixMath.h"
+ #include "QTLoadLibraryUtils.h"
+#endif
+
+// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint
+////////////////////////////////////////////////////////////////////////////////
+//
+class MediaPluginQuickTime : public MediaPluginBase
+{
+public:
+ MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
+ ~MediaPluginQuickTime();
+
+ /* virtual */ void receiveMessage(const char *message_string);
+
+private:
+
+ int mNaturalWidth;
+ int mNaturalHeight;
+ Movie mMovieHandle;
+ GWorldPtr mGWorldHandle;
+ ComponentInstance mMovieController;
+ int mCurVolume;
+ bool mMediaSizeChanging;
+ bool mIsLooping;
+ std::string mMovieTitle;
+ bool mReceivedTitle;
+ const int mMinWidth;
+ const int mMaxWidth;
+ const int mMinHeight;
+ const int mMaxHeight;
+ F64 mPlayRate;
+ std::string mNavigateURL;
+
+ enum ECommand {
+ COMMAND_NONE,
+ COMMAND_STOP,
+ COMMAND_PLAY,
+ COMMAND_FAST_FORWARD,
+ COMMAND_FAST_REWIND,
+ COMMAND_PAUSE,
+ COMMAND_SEEK,
+ };
+ ECommand mCommand;
+
+ // Override this to add current time and duration to the message
+ /*virtual*/ void setDirty(int left, int top, int right, int bottom)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated");
+
+ message.setValueS32("left", left);
+ message.setValueS32("top", top);
+ message.setValueS32("right", right);
+ message.setValueS32("bottom", bottom);
+
+ if(mMovieHandle)
+ {
+ message.setValueReal("current_time", getCurrentTime());
+ message.setValueReal("duration", getDuration());
+ message.setValueReal("current_rate", Fix2X(GetMovieRate(mMovieHandle)));
+ }
+
+ sendMessage(message);
+ }
+
+
+ static Rect rectFromSize(int width, int height)
+ {
+ Rect result;
+
+
+ result.left = 0;
+ result.top = 0;
+ result.right = width;
+ result.bottom = height;
+
+ return result;
+ }
+
+ Fixed getPlayRate(void)
+ {
+ Fixed result;
+ if(mPlayRate == 0.0f)
+ {
+ // Default to the movie's preferred rate
+ result = GetMoviePreferredRate(mMovieHandle);
+ if(result == 0)
+ {
+ // Don't return a 0 play rate, ever.
+ std::cerr << "Movie's preferred rate is 0, forcing to 1.0." << std::endl;
+ result = X2Fix(1.0f);
+ }
+ }
+ else
+ {
+ result = X2Fix(mPlayRate);
+ }
+
+ return result;
+ }
+
+ void load( const std::string url )
+ {
+
+ if ( url.empty() )
+ return;
+
+ // Stop and unload any existing movie before starting another one.
+ unload();
+
+ setStatus(STATUS_LOADING);
+
+ //In case std::string::c_str() makes a copy of the url data,
+ //make sure there is memory to hold it before allocating memory for handle.
+ //if fails, NewHandleClear(...) should return NULL.
+ const char* url_string = url.c_str() ;
+ Handle handle = NewHandleClear( ( Size )( url.length() + 1 ) );
+
+ if ( NULL == handle || noErr != MemError() || NULL == *handle )
+ {
+ setStatus(STATUS_ERROR);
+ return;
+ }
+
+ BlockMove( url_string, *handle, ( Size )( url.length() + 1 ) );
+
+ OSErr err = NewMovieFromDataRef( &mMovieHandle, newMovieActive | newMovieDontInteractWithUser | newMovieAsyncOK | newMovieIdleImportOK, nil, handle, URLDataHandlerSubType );
+ DisposeHandle( handle );
+ if ( noErr != err )
+ {
+ setStatus(STATUS_ERROR);
+ return;
+ };
+
+ mNavigateURL = url;
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin");
+ message.setValue("uri", mNavigateURL);
+ sendMessage(message);
+
+ // do pre-roll actions (typically fired for streaming movies but not always)
+ PrePrerollMovie( mMovieHandle, 0, getPlayRate(), moviePrePrerollCompleteCallback, ( void * )this );
+
+ Rect movie_rect = rectFromSize(mWidth, mHeight);
+
+ // make a new movie controller
+ mMovieController = NewMovieController( mMovieHandle, &movie_rect, mcNotVisible | mcTopLeftMovie );
+
+ // movie controller
+ MCSetActionFilterWithRefCon( mMovieController, mcActionFilterCallBack, ( long )this );
+
+ SetMoviePlayHints( mMovieHandle, hintsAllowDynamicResize, hintsAllowDynamicResize );
+
+ // function that gets called when a frame is drawn
+ SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, movieDrawingCompleteCallback, ( long )this );
+
+ setStatus(STATUS_LOADED);
+
+ sizeChanged();
+ };
+
+ bool unload()
+ {
+ // new movie and have to get title again
+ mReceivedTitle = false;
+
+ if ( mMovieHandle )
+ {
+ StopMovie( mMovieHandle );
+ if ( mMovieController )
+ {
+ MCMovieChanged( mMovieController, mMovieHandle );
+ };
+ };
+
+ if ( mMovieController )
+ {
+ MCSetActionFilterWithRefCon( mMovieController, NULL, (long)this );
+ DisposeMovieController( mMovieController );
+ mMovieController = NULL;
+ };
+
+ if ( mMovieHandle )
+ {
+ SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, nil, ( long )this );
+ DisposeMovie( mMovieHandle );
+ mMovieHandle = NULL;
+ };
+
+ if ( mGWorldHandle )
+ {
+ DisposeGWorld( mGWorldHandle );
+ mGWorldHandle = NULL;
+ };
+
+ setStatus(STATUS_NONE);
+
+ return true;
+ }
+
+ bool navigateTo( const std::string url )
+ {
+ unload();
+ load( url );
+
+ return true;
+ };
+
+ bool sizeChanged()
+ {
+ if ( ! mMovieHandle )
+ return false;
+
+ // Check to see whether the movie's natural size has updated
+ {
+ int width, height;
+ getMovieNaturalSize(&width, &height);
+ if((width != 0) && (height != 0) && ((width != mNaturalWidth) || (height != mNaturalHeight)))
+ {
+ mNaturalWidth = width;
+ mNaturalHeight = height;
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request");
+ message.setValue("name", mTextureSegmentName);
+ message.setValueS32("width", width);
+ message.setValueS32("height", height);
+ sendMessage(message);
+ //std::cerr << "<--- Sending size change request to application with name: " << mTextureSegmentName << " - size is " << width << " x " << height << std::endl;
+ }
+ }
+
+ // sanitize destination size
+ Rect dest_rect = rectFromSize(mWidth, mHeight);
+
+ // media depth won't change
+ int depth_bits = mDepth * 8;
+ long rowbytes = mDepth * mTextureWidth;
+
+ GWorldPtr old_gworld_handle = mGWorldHandle;
+
+ if(mPixels != NULL)
+ {
+ // We have pixels. Set up a GWorld pointing at the texture.
+ OSErr result = NewGWorldFromPtr( &mGWorldHandle, depth_bits, &dest_rect, NULL, NULL, 0, (Ptr)mPixels, rowbytes);
+ if ( noErr != result )
+ {
+ // TODO: unrecoverable?? throw exception? return something?
+ return false;
+ }
+ }
+ else
+ {
+ // We don't have pixels. Create a fake GWorld we can point the movie at when it's not safe to render normally.
+ Rect tempRect = rectFromSize(1, 1);
+ OSErr result = NewGWorld( &mGWorldHandle, depth_bits, &tempRect, NULL, NULL, 0);
+ if ( noErr != result )
+ {
+ // TODO: unrecoverable?? throw exception? return something?
+ return false;
+ }
+ }
+
+ SetMovieGWorld( mMovieHandle, mGWorldHandle, GetGWorldDevice( mGWorldHandle ) );
+
+ // If the GWorld was already set up, delete it.
+ if(old_gworld_handle != NULL)
+ {
+ DisposeGWorld( old_gworld_handle );
+ }
+
+ // Set up the movie display matrix
+ {
+ // scale movie to fit rect and invert vertically to match opengl image format
+ MatrixRecord transform;
+ SetIdentityMatrix( &transform ); // transforms are additive so start from identify matrix
+ double scaleX = (double) mWidth / mNaturalWidth;
+ double scaleY = -1.0 * (double) mHeight / mNaturalHeight;
+ double centerX = mWidth / 2.0;
+ double centerY = mHeight / 2.0;
+ ScaleMatrix( &transform, X2Fix( scaleX ), X2Fix( scaleY ), X2Fix( centerX ), X2Fix( centerY ) );
+ SetMovieMatrix( mMovieHandle, &transform );
+ }
+
+ // update movie controller
+ if ( mMovieController )
+ {
+ MCSetControllerPort( mMovieController, mGWorldHandle );
+ MCPositionController( mMovieController, &dest_rect, &dest_rect,
+ mcTopLeftMovie | mcPositionDontInvalidate );
+ MCMovieChanged( mMovieController, mMovieHandle );
+ }
+
+
+ // Emit event with size change so the calling app knows about it too
+ // TODO:
+ //LLMediaEvent event( this );
+ //mEventEmitter.update( &LLMediaObserver::onMediaSizeChange, event );
+
+ return true;
+ }
+ static Boolean mcActionFilterCallBack( MovieController mc, short action, void *params, long ref )
+ {
+ Boolean result = false;
+
+ MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref;
+
+ switch( action )
+ {
+ // handle window resizing
+ case mcActionControllerSizeChanged:
+ // Ensure that the movie draws correctly at the new size
+ self->sizeChanged();
+ break;
+
+ // Block any movie controller actions that open URLs.
+ case mcActionLinkToURL:
+ case mcActionGetNextURL:
+ case mcActionLinkToURLExtended:
+ // Prevent the movie controller from handling the message
+ result = true;
+ break;
+
+ default:
+ break;
+ };
+
+ return result;
+ };
+
+ static OSErr movieDrawingCompleteCallback( Movie call_back_movie, long ref )
+ {
+ MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref;
+
+ // IMPORTANT: typically, a consumer who is observing this event will set a flag
+ // when this event is fired then render later. Be aware that the media stream
+ // can change during this period - dimensions, depth, format etc.
+ //LLMediaEvent event( self );
+// self->updateQuickTime();
+ // TODO ^^^
+
+
+ if ( self->mWidth > 0 && self->mHeight > 0 )
+ self->setDirty( 0, 0, self->mWidth, self->mHeight );
+
+ return noErr;
+ };
+
+ static void moviePrePrerollCompleteCallback( Movie movie, OSErr preroll_err, void *ref )
+ {
+ MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref;
+
+ // TODO:
+ //LLMediaEvent event( self );
+ //self->mEventEmitter.update( &LLMediaObserver::onMediaPreroll, event );
+
+ // Send a "navigate complete" event.
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete");
+ message.setValue("uri", self->mNavigateURL);
+ message.setValueS32("result_code", 200);
+ message.setValue("result_string", "OK");
+ self->sendMessage(message);
+ };
+
+
+ void rewind()
+ {
+ GoToBeginningOfMovie( mMovieHandle );
+ MCMovieChanged( mMovieController, mMovieHandle );
+ };
+
+ bool processState()
+ {
+ if ( mCommand == COMMAND_PLAY )
+ {
+ if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING || mStatus == STATUS_DONE )
+ {
+ long state = GetMovieLoadState( mMovieHandle );
+
+ if ( state >= kMovieLoadStatePlaythroughOK )
+ {
+ // if the movie is at the end (generally because it reached it naturally)
+ // and we play is requested, jump back to the start of the movie.
+ // note: this is different from having loop flag set.
+ if ( IsMovieDone( mMovieHandle ) )
+ {
+ Fixed rate = X2Fix( 0.0 );
+ MCDoAction( mMovieController, mcActionPlay, (void*)rate );
+ rewind();
+ };
+
+ MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() );
+ MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
+ setStatus(STATUS_PLAYING);
+ mCommand = COMMAND_NONE;
+ };
+ };
+ }
+ else
+ if ( mCommand == COMMAND_STOP )
+ {
+ if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED || mStatus == STATUS_DONE )
+ {
+ if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK )
+ {
+ Fixed rate = X2Fix( 0.0 );
+ MCDoAction( mMovieController, mcActionPlay, (void*)rate );
+ rewind();
+
+ setStatus(STATUS_LOADED);
+ mCommand = COMMAND_NONE;
+ };
+ };
+ }
+ else
+ if ( mCommand == COMMAND_PAUSE )
+ {
+ if ( mStatus == STATUS_PLAYING )
+ {
+ if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK )
+ {
+ Fixed rate = X2Fix( 0.0 );
+ MCDoAction( mMovieController, mcActionPlay, (void*)rate );
+ setStatus(STATUS_PAUSED);
+ mCommand = COMMAND_NONE;
+ };
+ };
+ };
+
+ return true;
+ };
+
+ void play(F64 rate)
+ {
+ mPlayRate = rate;
+ mCommand = COMMAND_PLAY;
+ };
+
+ void stop()
+ {
+ mCommand = COMMAND_STOP;
+ };
+
+ void pause()
+ {
+ mCommand = COMMAND_PAUSE;
+ };
+
+ void getMovieNaturalSize(int *movie_width, int *movie_height)
+ {
+ Rect rect;
+
+ GetMovieNaturalBoundsRect( mMovieHandle, &rect );
+
+ int width = ( rect.right - rect.left );
+ int height = ( rect.bottom - rect.top );
+
+ // make sure width and height fall in valid range
+ if ( width < mMinWidth )
+ width = mMinWidth;
+
+ if ( width > mMaxWidth )
+ width = mMaxWidth;
+
+ if ( height < mMinHeight )
+ height = mMinHeight;
+
+ if ( height > mMaxHeight )
+ height = mMaxHeight;
+
+ // return the new rect
+ *movie_width = width;
+ *movie_height = height;
+ }
+
+ void updateQuickTime(int milliseconds)
+ {
+ if ( ! mMovieHandle )
+ return;
+
+ if ( ! mMovieController )
+ return;
+
+ // this wasn't required in 1.xx viewer but we have to manually
+ // work the Windows message pump now
+ #if defined( LL_WINDOWS )
+ MSG msg;
+ while ( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
+ {
+ GetMessage( &msg, NULL, 0, 0 );
+ TranslateMessage( &msg );
+ DispatchMessage( &msg );
+ };
+ #endif
+
+ MCIdle( mMovieController );
+
+ if ( ! mGWorldHandle )
+ return;
+
+ if ( mMediaSizeChanging )
+ return;
+
+ // update state machine
+ processState();
+
+ // see if title arrived and if so, update member variable with contents
+ checkTitle();
+
+ // QT call to see if we are at the end - can't do with controller
+ if ( IsMovieDone( mMovieHandle ) )
+ {
+ // special code for looping - need to rewind at the end of the movie
+ if ( mIsLooping )
+ {
+ // go back to start
+ rewind();
+
+ if ( mMovieController )
+ {
+ // kick off new play
+ MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() );
+
+ // set the volume
+ MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
+ };
+ }
+ else
+ {
+ if(mStatus == STATUS_PLAYING)
+ {
+ setStatus(STATUS_DONE);
+ }
+ }
+ }
+
+ };
+
+ int getDataWidth() const
+ {
+ if ( mGWorldHandle )
+ {
+ int depth = mDepth;
+
+ if (depth < 1)
+ depth = 1;
+
+ // ALWAYS use the row bytes from the PixMap if we have a GWorld because
+ // sometimes it's not the same as mMediaDepth * mMediaWidth !
+ PixMapHandle pix_map_handle = GetGWorldPixMap( mGWorldHandle );
+ return QTGetPixMapHandleRowBytes( pix_map_handle ) / depth;
+ }
+ else
+ {
+ // TODO : return LLMediaImplCommon::getaDataWidth();
+ return 0;
+ }
+ };
+
+ void seek( F64 time )
+ {
+ if ( mMovieController )
+ {
+ TimeRecord when;
+ when.scale = GetMovieTimeScale( mMovieHandle );
+ when.base = 0;
+
+ // 'time' is in (floating point) seconds. The timebase time will be in 'units', where
+ // there are 'scale' units per second.
+ SInt64 raw_time = ( SInt64 )( time * (double)( when.scale ) );
+
+ when.value.hi = ( SInt32 )( raw_time >> 32 );
+ when.value.lo = ( SInt32 )( ( raw_time & 0x00000000FFFFFFFF ) );
+
+ MCDoAction( mMovieController, mcActionGoToTime, &when );
+ };
+ };
+
+ F64 getLoadedDuration()
+ {
+ TimeValue duration;
+ if(GetMaxLoadedTimeInMovie( mMovieHandle, &duration ) != noErr)
+ {
+ // If GetMaxLoadedTimeInMovie returns an error, return the full duration of the movie.
+ duration = GetMovieDuration( mMovieHandle );
+ }
+ TimeValue scale = GetMovieTimeScale( mMovieHandle );
+
+ return (F64)duration / (F64)scale;
+ };
+
+ F64 getDuration()
+ {
+ TimeValue duration = GetMovieDuration( mMovieHandle );
+ TimeValue scale = GetMovieTimeScale( mMovieHandle );
+
+ return (F64)duration / (F64)scale;
+ };
+
+ F64 getCurrentTime()
+ {
+ TimeValue curr_time = GetMovieTime( mMovieHandle, 0 );
+ TimeValue scale = GetMovieTimeScale( mMovieHandle );
+
+ return (F64)curr_time / (F64)scale;
+ };
+
+ void setVolume( F64 volume )
+ {
+ mCurVolume = (short)(volume * ( double ) 0x100 );
+
+ if ( mMovieController )
+ {
+ MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
+ };
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ void update(int milliseconds = 0)
+ {
+ updateQuickTime(milliseconds);
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ void mouseDown( int x, int y )
+ {
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ void mouseUp( int x, int y )
+ {
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ void mouseMove( int x, int y )
+ {
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ void keyPress( unsigned char key )
+ {
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Grab movie title into mMovieTitle - should be called repeatedly
+ // until it returns true since movie title takes a while to become
+ // available.
+ const bool getMovieTitle()
+ {
+ // grab meta data from movie
+ QTMetaDataRef media_data_ref;
+ OSErr result = QTCopyMovieMetaData( mMovieHandle, &media_data_ref );
+ if ( noErr != result )
+ return false;
+
+ // look up "Display Name" in meta data
+ OSType meta_data_key = kQTMetaDataCommonKeyDisplayName;
+ QTMetaDataItem item = kQTMetaDataItemUninitialized;
+ result = QTMetaDataGetNextItem( media_data_ref, kQTMetaDataStorageFormatWildcard,
+ 0, kQTMetaDataKeyFormatCommon,
+ (const UInt8 *)&meta_data_key,
+ sizeof( meta_data_key ), &item );
+ if ( noErr != result )
+ return false;
+
+ // find the size of the title
+ ByteCount size;
+ result = QTMetaDataGetItemValue( media_data_ref, item, NULL, 0, &size );
+ if ( noErr != result || size <= 0 /*|| size > 1024 FIXME: arbitrary limit */ )
+ return false;
+
+ // allocate some space and grab it
+ UInt8* item_data = new UInt8( size + 1 );
+ memset( item_data, 0, ( size + 1 ) * sizeof( UInt8* ) );
+ result = QTMetaDataGetItemValue( media_data_ref, item, item_data, size, NULL );
+ if ( noErr != result )
+ {
+ delete [] item_data;
+ return false;
+ };
+
+ // save it
+ if ( strlen( (char*)item_data ) )
+ mMovieTitle = std::string( (char* )item_data );
+ else
+ mMovieTitle = "";
+
+ // clean up
+ delete [] item_data;
+
+ return true;
+ };
+
+ // called regularly to see if title changed
+ void checkTitle()
+ {
+ // we did already receive title so keep checking
+ if ( ! mReceivedTitle )
+ {
+ // grab title from movie meta data
+ if ( getMovieTitle() )
+ {
+ // pass back to host application
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
+ message.setValue("name", mMovieTitle );
+ sendMessage( message );
+
+ // stop looking once we find a title for this movie.
+ // TODO: this may to be reset if movie title changes
+ // during playback but this is okay for now
+ mReceivedTitle = true;
+ };
+ };
+ };
+};
+
+MediaPluginQuickTime::MediaPluginQuickTime(
+ LLPluginInstance::sendMessageFunction host_send_func,
+ void *host_user_data ) :
+ MediaPluginBase(host_send_func, host_user_data),
+ mMinWidth( 0 ),
+ mMaxWidth( 2048 ),
+ mMinHeight( 0 ),
+ mMaxHeight( 2048 )
+{
+// std::cerr << "MediaPluginQuickTime constructor" << std::endl;
+
+ mNaturalWidth = -1;
+ mNaturalHeight = -1;
+ mMovieHandle = 0;
+ mGWorldHandle = 0;
+ mMovieController = 0;
+ mCurVolume = 0x99;
+ mMediaSizeChanging = false;
+ mIsLooping = false;
+ mMovieTitle = std::string();
+ mReceivedTitle = false;
+ mCommand = COMMAND_NONE;
+ mPlayRate = 0.0f;
+ mStatus = STATUS_NONE;
+}
+
+MediaPluginQuickTime::~MediaPluginQuickTime()
+{
+// std::cerr << "MediaPluginQuickTime destructor" << std::endl;
+
+ ExitMovies();
+
+#ifdef LL_WINDOWS
+ TerminateQTML();
+// std::cerr << "QuickTime closing down" << std::endl;
+#endif
+}
+
+
+void MediaPluginQuickTime::receiveMessage(const char *message_string)
+{
+// std::cerr << "MediaPluginQuickTime::receiveMessage: received message: \"" << message_string << "\"" << std::endl;
+ LLPluginMessage message_in;
+
+ if(message_in.parse(message_string) >= 0)
+ {
+ std::string message_class = message_in.getClass();
+ std::string message_name = message_in.getName();
+ if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
+ {
+ if(message_name == "init")
+ {
+ LLPluginMessage message("base", "init_response");
+ LLSD versions = LLSD::emptyMap();
+ versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
+ versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
+ // Normally a plugin would only specify one of these two subclasses, but this is a demo...
+ versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION;
+ message.setValueLLSD("versions", versions);
+
+ #ifdef LL_WINDOWS
+
+ // QuickTime 7.6.4 has an issue (that was not present in 7.6.2) with initializing QuickTime
+ // according to this article: http://lists.apple.com/archives/QuickTime-API/2009/Sep/msg00097.html
+ // The solution presented there appears to work.
+ QTLoadLibrary("qtcf.dll");
+
+ // main initialization for QuickTime - only required on Windows
+ OSErr result = InitializeQTML( 0L );
+ if ( result != noErr )
+ {
+ //TODO: If no QT on Windows, this fails - respond accordingly.
+ }
+ else
+ {
+ //std::cerr << "QuickTime initialized" << std::endl;
+ };
+ #endif
+
+ // required for both Windows and Mac
+ EnterMovies();
+
+ std::string plugin_version = "QuickTime media plugin, QuickTime version ";
+
+ long version = 0;
+ Gestalt( gestaltQuickTimeVersion, &version );
+ std::ostringstream codec( "" );
+ codec << std::hex << version << std::dec;
+ plugin_version += codec.str();
+ message.setValue("plugin_version", plugin_version);
+ sendMessage(message);
+
+ // Plugin gets to decide the texture parameters to use.
+ message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
+ #if defined(LL_WINDOWS)
+ // Values for Windows
+ mDepth = 3;
+ message.setValueU32("format", GL_RGB);
+ message.setValueU32("type", GL_UNSIGNED_BYTE);
+
+ // We really want to pad the texture width to a multiple of 32 bytes, but since we're using 3-byte pixels, it doesn't come out even.
+ // Padding to a multiple of 3*32 guarantees it'll divide out properly.
+ message.setValueU32("padding", 32 * 3);
+ #else
+ // Values for Mac
+ mDepth = 4;
+ message.setValueU32("format", GL_BGRA_EXT);
+ #ifdef __BIG_ENDIAN__
+ message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV );
+ #else
+ message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8);
+ #endif
+
+ // Pad texture width to a multiple of 32 bytes, to line up with cache lines.
+ message.setValueU32("padding", 32);
+ #endif
+ message.setValueS32("depth", mDepth);
+ message.setValueU32("internalformat", GL_RGB);
+ message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left.
+ message.setValueBoolean("allow_downsample", true);
+ sendMessage(message);
+ }
+ else if(message_name == "idle")
+ {
+ // no response is necessary here.
+ F64 time = message_in.getValueReal("time");
+
+ // Convert time to milliseconds for update()
+ update((int)(time * 1000.0f));
+ }
+ else if(message_name == "cleanup")
+ {
+ // TODO: clean up here
+ }
+ else if(message_name == "shm_added")
+ {
+ SharedSegmentInfo info;
+ info.mAddress = message_in.getValuePointer("address");
+ info.mSize = (size_t)message_in.getValueS32("size");
+ std::string name = message_in.getValue("name");
+// std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory added, name: " << name
+// << ", size: " << info.mSize
+// << ", address: " << info.mAddress
+// << std::endl;
+
+ mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
+
+ }
+ else if(message_name == "shm_remove")
+ {
+ std::string name = message_in.getValue("name");
+
+// std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory remove, name = " << name << std::endl;
+
+ SharedSegmentMap::iterator iter = mSharedSegments.find(name);
+ if(iter != mSharedSegments.end())
+ {
+ if(mPixels == iter->second.mAddress)
+ {
+ // This is the currently active pixel buffer. Make sure we stop drawing to it.
+ mPixels = NULL;
+ mTextureSegmentName.clear();
+
+ // Make sure the movie GWorld is no longer pointed at the shared segment.
+ sizeChanged();
+ }
+ mSharedSegments.erase(iter);
+ }
+ else
+ {
+// std::cerr << "MediaPluginQuickTime::receiveMessage: unknown shared memory region!" << std::endl;
+ }
+
+ // Send the response so it can be cleaned up.
+ LLPluginMessage message("base", "shm_remove_response");
+ message.setValue("name", name);
+ sendMessage(message);
+ }
+ else
+ {
+// std::cerr << "MediaPluginQuickTime::receiveMessage: unknown base message: " << message_name << std::endl;
+ }
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
+ {
+ if(message_name == "size_change")
+ {
+ std::string name = message_in.getValue("name");
+ S32 width = message_in.getValueS32("width");
+ S32 height = message_in.getValueS32("height");
+ S32 texture_width = message_in.getValueS32("texture_width");
+ S32 texture_height = message_in.getValueS32("texture_height");
+
+ //std::cerr << "---->Got size change instruction from application with name: " << name << " - size is " << width << " x " << height << std::endl;
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
+ message.setValue("name", name);
+ message.setValueS32("width", width);
+ message.setValueS32("height", height);
+ message.setValueS32("texture_width", texture_width);
+ message.setValueS32("texture_height", texture_height);
+ sendMessage(message);
+
+ if(!name.empty())
+ {
+ // Find the shared memory region with this name
+ SharedSegmentMap::iterator iter = mSharedSegments.find(name);
+ if(iter != mSharedSegments.end())
+ {
+// std::cerr << "%%% Got size change, new size is " << width << " by " << height << std::endl;
+// std::cerr << "%%%% texture size is " << texture_width << " by " << texture_height << std::endl;
+
+ mPixels = (unsigned char*)iter->second.mAddress;
+ mTextureSegmentName = name;
+ mWidth = width;
+ mHeight = height;
+
+ mTextureWidth = texture_width;
+ mTextureHeight = texture_height;
+
+ mMediaSizeChanging = false;
+
+ sizeChanged();
+
+ update();
+ };
+ };
+ }
+ else if(message_name == "load_uri")
+ {
+ std::string uri = message_in.getValue("uri");
+ load( uri );
+ sendStatus();
+ }
+ else if(message_name == "mouse_event")
+ {
+ std::string event = message_in.getValue("event");
+ S32 x = message_in.getValueS32("x");
+ S32 y = message_in.getValueS32("y");
+
+ if(event == "down")
+ {
+ mouseDown(x, y);
+ }
+ else if(event == "up")
+ {
+ mouseUp(x, y);
+ }
+ else if(event == "move")
+ {
+ mouseMove(x, y);
+ };
+ };
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
+ {
+ if(message_name == "stop")
+ {
+ stop();
+ }
+ else if(message_name == "start")
+ {
+ F64 rate = 0.0;
+ if(message_in.hasValue("rate"))
+ {
+ rate = message_in.getValueReal("rate");
+ }
+ play(rate);
+ }
+ else if(message_name == "pause")
+ {
+ pause();
+ }
+ else if(message_name == "seek")
+ {
+ F64 time = message_in.getValueReal("time");
+ seek(time);
+ }
+ else if(message_name == "set_loop")
+ {
+ bool loop = message_in.getValueBoolean("loop");
+ mIsLooping = loop;
+ }
+ else if(message_name == "set_volume")
+ {
+ F64 volume = message_in.getValueReal("volume");
+ setVolume(volume);
+ }
+ }
+ else
+ {
+// std::cerr << "MediaPluginQuickTime::receiveMessage: unknown message class: " << message_class << std::endl;
+ };
+ };
+}
+
+int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
+{
+ MediaPluginQuickTime *self = new MediaPluginQuickTime(host_send_func, host_user_data);
+ *plugin_send_func = MediaPluginQuickTime::staticReceiveMessage;
+ *plugin_user_data = (void*)self;
+
+ return 0;
+}
+
+#else // LL_QUICKTIME_ENABLED
+
+// Stubbed-out class with constructor/destructor (necessary or windows linker
+// will just think its dead code and optimize it all out)
+class MediaPluginQuickTime : public MediaPluginBase
+{
+public:
+ MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
+ ~MediaPluginQuickTime();
+ /* virtual */ void receiveMessage(const char *message_string);
+};
+
+MediaPluginQuickTime::MediaPluginQuickTime(
+ LLPluginInstance::sendMessageFunction host_send_func,
+ void *host_user_data ) :
+ MediaPluginBase(host_send_func, host_user_data)
+{
+ // no-op
+}
+
+MediaPluginQuickTime::~MediaPluginQuickTime()
+{
+ // no-op
+}
+
+void MediaPluginQuickTime::receiveMessage(const char *message_string)
+{
+ // no-op
+}
+
+// We're building without quicktime enabled. Just refuse to initialize.
+int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
+{
+ return -1;
+}
+
+#endif // LL_QUICKTIME_ENABLED
diff --git a/indra/media_plugins/webkit/CMakeLists.txt b/indra/media_plugins/webkit/CMakeLists.txt
new file mode 100644
index 0000000000..673e059c34
--- /dev/null
+++ b/indra/media_plugins/webkit/CMakeLists.txt
@@ -0,0 +1,90 @@
+# -*- cmake -*-
+
+project(media_plugin_webkit)
+
+include(00-Common)
+include(LLCommon)
+include(LLImage)
+include(LLPlugin)
+include(LLMath)
+include(LLRender)
+include(LLWindow)
+include(Linking)
+include(PluginAPI)
+include(MediaPluginBase)
+include(FindOpenGL)
+
+include(WebKitLibPlugin)
+
+include_directories(
+ ${LLPLUGIN_INCLUDE_DIRS}
+ ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS}
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LLMATH_INCLUDE_DIRS}
+ ${LLIMAGE_INCLUDE_DIRS}
+ ${LLRENDER_INCLUDE_DIRS}
+ ${LLWINDOW_INCLUDE_DIRS}
+)
+
+
+### media_plugin_webkit
+
+if(NOT WORD_SIZE EQUAL 32)
+ if(WINDOWS)
+ add_definitions(/FIXED:NO)
+ else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
+ add_definitions(-fPIC)
+ endif(WINDOWS)
+endif(NOT WORD_SIZE EQUAL 32)
+
+set(media_plugin_webkit_SOURCE_FILES
+ media_plugin_webkit.cpp
+ )
+
+add_library(media_plugin_webkit
+ SHARED
+ ${media_plugin_webkit_SOURCE_FILES}
+)
+
+target_link_libraries(media_plugin_webkit
+ ${LLPLUGIN_LIBRARIES}
+ ${MEDIA_PLUGIN_BASE_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+ ${WEBKIT_PLUGIN_LIBRARIES}
+ ${PLUGIN_API_WINDOWS_LIBRARIES}
+)
+
+add_dependencies(media_plugin_webkit
+ ${LLPLUGIN_LIBRARIES}
+ ${MEDIA_PLUGIN_BASE_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+)
+
+if (WINDOWS)
+ set_target_properties(
+ media_plugin_webkit
+ PROPERTIES
+ LINK_FLAGS "/MANIFEST:NO"
+ )
+endif (WINDOWS)
+
+if (DARWIN)
+ # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name
+ set_target_properties(
+ media_plugin_webkit
+ PROPERTIES
+ PREFIX ""
+ BUILD_WITH_INSTALL_RPATH 1
+ INSTALL_NAME_DIR "@executable_path"
+ LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp"
+ )
+
+ # copy the webkit dylib to the build directory
+ add_custom_command(
+ TARGET media_plugin_webkit POST_BUILD
+# OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/libllqtwebkit.dylib
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libllqtwebkit.dylib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/
+ DEPENDS media_plugin_webkit ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libllqtwebkit.dylib
+ )
+
+endif (DARWIN) \ No newline at end of file
diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp
new file mode 100644
index 0000000000..42d680ade6
--- /dev/null
+++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp
@@ -0,0 +1,1000 @@
+/**
+ * @file media_plugin_webkit.cpp
+ * @brief Webkit plugin for LLMedia API plugin system
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "llqtwebkit.h"
+
+#include "linden_common.h"
+#include "indra_constants.h" // for indra keyboard codes
+
+#include "llgl.h"
+
+#include "llplugininstance.h"
+#include "llpluginmessage.h"
+#include "llpluginmessageclasses.h"
+#include "media_plugin_base.h"
+
+#if LL_WINDOWS
+#include <direct.h>
+#else
+#include <unistd.h>
+#include <stdlib.h>
+#endif
+
+#if LL_WINDOWS
+ // *NOTE:Mani - This captures the module handle fo rthe dll. This is used below
+ // to get the path to this dll for webkit initialization.
+ // I don't know how/if this can be done with apr...
+ namespace { HMODULE gModuleHandle;};
+ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+ {
+ gModuleHandle = (HMODULE) hinstDLL;
+ return TRUE;
+ }
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+//
+class MediaPluginWebKit :
+ public MediaPluginBase,
+ public LLEmbeddedBrowserWindowObserver
+{
+public:
+ MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
+ ~MediaPluginWebKit();
+
+ /*virtual*/ void receiveMessage(const char *message_string);
+
+private:
+
+ std::string mProfileDir;
+
+ enum
+ {
+ INIT_STATE_UNINITIALIZED, // Browser instance hasn't been set up yet
+ INIT_STATE_NAVIGATING, // Browser instance has been set up and initial navigate to about:blank has been issued
+ INIT_STATE_NAVIGATE_COMPLETE, // initial navigate to about:blank has completed
+ INIT_STATE_WAIT_REDRAW, // First real navigate begin has been received, waiting for page changed event to start handling redraws
+ INIT_STATE_WAIT_COMPLETE, // Waiting for first real navigate complete event
+ INIT_STATE_RUNNING // All initialization gymnastics are complete.
+ };
+ int mBrowserWindowId;
+ int mInitState;
+ std::string mInitialNavigateURL;
+ bool mNeedsUpdate;
+
+ bool mCanCut;
+ bool mCanCopy;
+ bool mCanPaste;
+ int mLastMouseX;
+ int mLastMouseY;
+ bool mFirstFocus;
+ F32 mBackgroundR;
+ F32 mBackgroundG;
+ F32 mBackgroundB;
+
+ void setInitState(int state)
+ {
+// std::cerr << "changing init state to " << state << std::endl;
+ mInitState = state;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ void update(int milliseconds)
+ {
+ LLQtWebKit::getInstance()->pump( milliseconds );
+
+ checkEditState();
+
+ if(mInitState == INIT_STATE_NAVIGATE_COMPLETE)
+ {
+ if(!mInitialNavigateURL.empty())
+ {
+ // We already have the initial navigate URL -- kick off the navigate.
+ LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, mInitialNavigateURL );
+ mInitialNavigateURL.clear();
+ }
+ }
+
+ if ( (mInitState > INIT_STATE_WAIT_REDRAW) && mNeedsUpdate )
+ {
+ const unsigned char* browser_pixels = LLQtWebKit::getInstance()->grabBrowserWindow( mBrowserWindowId );
+
+ unsigned int buffer_size = LLQtWebKit::getInstance()->getBrowserRowSpan( mBrowserWindowId ) * LLQtWebKit::getInstance()->getBrowserHeight( mBrowserWindowId );
+
+// std::cerr << "webkit plugin: updating" << std::endl;
+
+ // TODO: should get rid of this memcpy if possible
+ if ( mPixels && browser_pixels )
+ {
+// std::cerr << " memcopy of " << buffer_size << " bytes" << std::endl;
+ memcpy( mPixels, browser_pixels, buffer_size );
+ }
+
+ if ( mWidth > 0 && mHeight > 0 )
+ {
+// std::cerr << "Setting dirty, " << mWidth << " x " << mHeight << std::endl;
+ setDirty( 0, 0, mWidth, mHeight );
+ }
+
+ mNeedsUpdate = false;
+ };
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ bool initBrowser()
+ {
+ // already initialized
+ if ( mInitState > INIT_STATE_UNINITIALIZED )
+ return true;
+
+ // not enough information to initialize the browser yet.
+ if ( mWidth < 0 || mHeight < 0 || mDepth < 0 ||
+ mTextureWidth < 0 || mTextureHeight < 0 )
+ {
+ return false;
+ };
+
+ // set up directories
+ char cwd[ FILENAME_MAX ]; // I *think* this is defined on all platforms we use
+ if (NULL == getcwd( cwd, FILENAME_MAX - 1 ))
+ {
+ llwarns << "Couldn't get cwd - probably too long - failing to init." << llendl;
+ return false;
+ }
+ std::string application_dir = std::string( cwd );
+
+#if LL_DARWIN
+ // When running under the Xcode debugger, there's a setting called "Break on Debugger()/DebugStr()" which defaults to being turned on.
+ // This causes the environment variable USERBREAK to be set to 1, which causes these legacy calls to break into the debugger.
+ // This wouldn't cause any problems except for the fact that the current release version of the Flash plugin has a call to Debugger() in it
+ // which gets hit when the plugin is probed by webkit.
+ // Unsetting the environment variable here works around this issue.
+ unsetenv("USERBREAK");
+#endif
+
+#if LL_WINDOWS
+ //*NOTE:Mani - On windows, at least, the component path is the
+ // location of this dll's image file.
+ std::string component_dir;
+ char dll_path[_MAX_PATH];
+ DWORD len = GetModuleFileNameA(gModuleHandle, (LPCH)&dll_path, _MAX_PATH);
+ while(len && dll_path[ len ] != ('\\') )
+ {
+ len--;
+ }
+ if(len >= 0)
+ {
+ dll_path[len] = 0;
+ component_dir = dll_path;
+ }
+ else
+ {
+ // *NOTE:Mani - This case should be an rare exception.
+ // GetModuleFileNameA should always give you a full path, no?
+ component_dir = application_dir;
+ }
+#else
+ std::string component_dir = application_dir;
+#endif
+
+ // window handle - needed on Windows and must be app window.
+#if LL_WINDOWS
+ char window_title[ MAX_PATH ];
+ GetConsoleTitleA( window_title, MAX_PATH );
+ void* native_window_handle = (void*)FindWindowA( NULL, window_title );
+#else
+ void* native_window_handle = 0;
+#endif
+
+ // main browser initialization
+ bool result = LLQtWebKit::getInstance()->init( application_dir, component_dir, mProfileDir, native_window_handle );
+ if ( result )
+ {
+ // create single browser window
+ mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow( mWidth, mHeight );
+#if LL_WINDOWS
+ // Enable plugins
+ LLQtWebKit::getInstance()->enablePlugins(true);
+#elif LL_DARWIN
+ // Enable plugins
+ LLQtWebKit::getInstance()->enablePlugins(true);
+#elif LL_LINUX
+ // Enable plugins
+ LLQtWebKit::getInstance()->enablePlugins(true);
+#endif
+ // Enable cookies
+ LLQtWebKit::getInstance()->enableCookies( true );
+
+ // tell LLQtWebKit about the size of the browser window
+ LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight );
+
+ // observer events that LLQtWebKit emits
+ LLQtWebKit::getInstance()->addObserver( mBrowserWindowId, this );
+
+ // append details to agent string
+ LLQtWebKit::getInstance()->setBrowserAgentId( "LLPluginMedia Web Browser" );
+
+ // don't flip bitmap
+ LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true );
+
+ // set background color
+ // convert background color channels from [0.0, 1.0] to [0, 255];
+ LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, int(mBackgroundR * 255.0f), int(mBackgroundG * 255.0f), int(mBackgroundB * 255.0f) );
+
+ // Set state _before_ starting the navigate, since onNavigateBegin might get called before this call returns.
+ setInitState(INIT_STATE_NAVIGATING);
+
+ // Don't do this here -- it causes the dreaded "white flash" when loading a browser instance.
+ // FIXME: Re-added this because navigating to a "page" initializes things correctly - especially
+ // for the HTTP AUTH dialog issues (DEV-41731). Will fix at a later date.
+ // Build a data URL like this: "data:text/html,%3Chtml%3E%3Cbody bgcolor=%22#RRGGBB%22%3E%3C/body%3E%3C/html%3E"
+ // where RRGGBB is the background color in HTML style
+ std::stringstream url;
+
+ url << "data:text/html,%3Chtml%3E%3Cbody%20bgcolor=%22#";
+ // convert background color channels from [0.0, 1.0] to [0, 255];
+ url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundR * 255.0f);
+ url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundG * 255.0f);
+ url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundB * 255.0f);
+ url << "%22%3E%3C/body%3E%3C/html%3E";
+
+ lldebugs << "data url is: " << url.str() << llendl;
+
+ LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, url.str() );
+// LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" );
+
+ return true;
+ };
+
+ return false;
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onCursorChanged(const EventType& event)
+ {
+ LLQtWebKit::ECursor llqt_cursor = (LLQtWebKit::ECursor)event.getIntValue();
+ std::string name;
+
+ switch(llqt_cursor)
+ {
+ case LLQtWebKit::C_ARROW:
+ name = "arrow";
+ break;
+ case LLQtWebKit::C_IBEAM:
+ name = "ibeam";
+ break;
+ case LLQtWebKit::C_SPLITV:
+ name = "splitv";
+ break;
+ case LLQtWebKit::C_SPLITH:
+ name = "splith";
+ break;
+ case LLQtWebKit::C_POINTINGHAND:
+ name = "hand";
+ break;
+
+ default:
+ llwarns << "Unknown cursor ID: " << (int)llqt_cursor << llendl;
+ break;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "cursor_changed");
+ message.setValue("name", name);
+ sendMessage(message);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onPageChanged( const EventType& event )
+ {
+ if(mInitState == INIT_STATE_WAIT_REDRAW)
+ {
+ setInitState(INIT_STATE_WAIT_COMPLETE);
+ }
+
+ // flag that an update is required
+ mNeedsUpdate = true;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onNavigateBegin(const EventType& event)
+ {
+ if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin");
+ message.setValue("uri", event.getEventUri());
+ sendMessage(message);
+
+ setStatus(STATUS_LOADING);
+ }
+
+ if(mInitState == INIT_STATE_NAVIGATE_COMPLETE)
+ {
+ // Skip the WAIT_REDRAW state now -- with the right background color set, it should no longer be necessary.
+// setInitState(INIT_STATE_WAIT_REDRAW);
+ setInitState(INIT_STATE_WAIT_COMPLETE);
+ }
+
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onNavigateComplete(const EventType& event)
+ {
+ if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
+ {
+ if(mInitState < INIT_STATE_RUNNING)
+ {
+ setInitState(INIT_STATE_RUNNING);
+
+ // Clear the history, so the "back" button doesn't take you back to "about:blank".
+ LLQtWebKit::getInstance()->clearHistory(mBrowserWindowId);
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete");
+ message.setValue("uri", event.getEventUri());
+ message.setValueS32("result_code", event.getIntValue());
+ message.setValue("result_string", event.getStringValue());
+ message.setValueBoolean("history_back_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK));
+ message.setValueBoolean("history_forward_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD));
+ sendMessage(message);
+
+ setStatus(STATUS_LOADED);
+ }
+ else if(mInitState == INIT_STATE_NAVIGATING)
+ {
+ setInitState(INIT_STATE_NAVIGATE_COMPLETE);
+ }
+
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onUpdateProgress(const EventType& event)
+ {
+ if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "progress");
+ message.setValueS32("percent", event.getIntValue());
+ sendMessage(message);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onStatusTextChange(const EventType& event)
+ {
+ if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "status_text");
+ message.setValue("status", event.getStringValue());
+ sendMessage(message);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onTitleChange(const EventType& event)
+ {
+ if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
+ message.setValue("name", event.getStringValue());
+ sendMessage(message);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onLocationChange(const EventType& event)
+ {
+ if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed");
+ message.setValue("uri", event.getEventUri());
+ sendMessage(message);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onClickLinkHref(const EventType& event)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_href");
+ message.setValue("uri", event.getStringValue());
+ message.setValue("target", event.getStringValue2());
+ message.setValueU32("target_type", event.getLinkType());
+ sendMessage(message);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onClickLinkNoFollow(const EventType& event)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow");
+ message.setValue("uri", event.getStringValue());
+ sendMessage(message);
+ }
+
+ LLQtWebKit::EKeyboardModifier decodeModifiers(std::string &modifiers)
+ {
+ int result = 0;
+
+ if(modifiers.find("shift") != std::string::npos)
+ result |= LLQtWebKit::KM_MODIFIER_SHIFT;
+
+ if(modifiers.find("alt") != std::string::npos)
+ result |= LLQtWebKit::KM_MODIFIER_ALT;
+
+ if(modifiers.find("control") != std::string::npos)
+ result |= LLQtWebKit::KM_MODIFIER_CONTROL;
+
+ if(modifiers.find("meta") != std::string::npos)
+ result |= LLQtWebKit::KM_MODIFIER_META;
+
+ return (LLQtWebKit::EKeyboardModifier)result;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ void keyEvent(LLQtWebKit::EKeyEvent key_event, int key, LLQtWebKit::EKeyboardModifier modifiers)
+ {
+ int llqt_key;
+
+ // The incoming values for 'key' will be the ones from indra_constants.h
+ // the outgoing values are the ones from llqtwebkit.h
+
+ switch((KEY)key)
+ {
+ // This is the list that the llqtwebkit implementation actually maps into Qt keys.
+// case KEY_XXX: llqt_key = LL_DOM_VK_CANCEL; break;
+// case KEY_XXX: llqt_key = LL_DOM_VK_HELP; break;
+ case KEY_BACKSPACE: llqt_key = LL_DOM_VK_BACK_SPACE; break;
+ case KEY_TAB: llqt_key = LL_DOM_VK_TAB; break;
+// case KEY_XXX: llqt_key = LL_DOM_VK_CLEAR; break;
+ case KEY_RETURN: llqt_key = LL_DOM_VK_RETURN; break;
+ case KEY_PAD_RETURN: llqt_key = LL_DOM_VK_ENTER; break;
+ case KEY_SHIFT: llqt_key = LL_DOM_VK_SHIFT; break;
+ case KEY_CONTROL: llqt_key = LL_DOM_VK_CONTROL; break;
+ case KEY_ALT: llqt_key = LL_DOM_VK_ALT; break;
+// case KEY_XXX: llqt_key = LL_DOM_VK_PAUSE; break;
+ case KEY_CAPSLOCK: llqt_key = LL_DOM_VK_CAPS_LOCK; break;
+ case KEY_ESCAPE: llqt_key = LL_DOM_VK_ESCAPE; break;
+ case KEY_PAGE_UP: llqt_key = LL_DOM_VK_PAGE_UP; break;
+ case KEY_PAGE_DOWN: llqt_key = LL_DOM_VK_PAGE_DOWN; break;
+ case KEY_END: llqt_key = LL_DOM_VK_END; break;
+ case KEY_HOME: llqt_key = LL_DOM_VK_HOME; break;
+ case KEY_LEFT: llqt_key = LL_DOM_VK_LEFT; break;
+ case KEY_UP: llqt_key = LL_DOM_VK_UP; break;
+ case KEY_RIGHT: llqt_key = LL_DOM_VK_RIGHT; break;
+ case KEY_DOWN: llqt_key = LL_DOM_VK_DOWN; break;
+// case KEY_XXX: llqt_key = LL_DOM_VK_PRINTSCREEN; break;
+ case KEY_INSERT: llqt_key = LL_DOM_VK_INSERT; break;
+ case KEY_DELETE: llqt_key = LL_DOM_VK_DELETE; break;
+// case KEY_XXX: llqt_key = LL_DOM_VK_CONTEXT_MENU; break;
+
+ default:
+ if(key < KEY_SPECIAL)
+ {
+ // Pass the incoming key through -- it should be regular ASCII, which should be correct for webkit.
+ llqt_key = key;
+ }
+ else
+ {
+ // Don't pass through untranslated special keys -- they'll be all wrong.
+ llqt_key = 0;
+ }
+ break;
+ }
+
+// std::cerr << "keypress, original code = 0x" << std::hex << key << ", converted code = 0x" << std::hex << llqt_key << std::dec << std::endl;
+
+ if(llqt_key != 0)
+ {
+ LLQtWebKit::getInstance()->keyEvent( mBrowserWindowId, key_event, llqt_key, modifiers);
+ }
+
+ checkEditState();
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ void unicodeInput( const std::string &utf8str, LLQtWebKit::EKeyboardModifier modifiers)
+ {
+ LLWString wstr = utf8str_to_wstring(utf8str);
+
+ unsigned int i;
+ for(i=0; i < wstr.size(); i++)
+ {
+// std::cerr << "unicode input, code = 0x" << std::hex << (unsigned long)(wstr[i]) << std::dec << std::endl;
+
+ if(wstr[i] == 32)
+ {
+ // For some reason, the webkit plugin really wants the space bar to come in through the key-event path, not the unicode path.
+ LLQtWebKit::getInstance()->keyEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_DOWN, 32, modifiers);
+ LLQtWebKit::getInstance()->keyEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_UP, 32, modifiers);
+ }
+ else
+ {
+ LLQtWebKit::getInstance()->unicodeInput(mBrowserWindowId, wstr[i], modifiers);
+ }
+ }
+
+ checkEditState();
+ };
+
+ void checkEditState(void)
+ {
+ bool can_cut = LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_EDIT_CUT);
+ bool can_copy = LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_EDIT_COPY);
+ bool can_paste = LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_EDIT_PASTE);
+
+ if((can_cut != mCanCut) || (can_copy != mCanCopy) || (can_paste != mCanPaste))
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_state");
+
+ if(can_cut != mCanCut)
+ {
+ mCanCut = can_cut;
+ message.setValueBoolean("cut", can_cut);
+ }
+
+ if(can_copy != mCanCopy)
+ {
+ mCanCopy = can_copy;
+ message.setValueBoolean("copy", can_copy);
+ }
+
+ if(can_paste != mCanPaste)
+ {
+ mCanPaste = can_paste;
+ message.setValueBoolean("paste", can_paste);
+ }
+
+ sendMessage(message);
+
+ }
+ }
+
+};
+
+MediaPluginWebKit::MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) :
+ MediaPluginBase(host_send_func, host_user_data)
+{
+// std::cerr << "MediaPluginWebKit constructor" << std::endl;
+
+ mBrowserWindowId = 0;
+ mInitState = INIT_STATE_UNINITIALIZED;
+ mNeedsUpdate = true;
+ mCanCut = false;
+ mCanCopy = false;
+ mCanPaste = false;
+ mLastMouseX = 0;
+ mLastMouseY = 0;
+ mFirstFocus = true;
+}
+
+MediaPluginWebKit::~MediaPluginWebKit()
+{
+ // unhook observer
+ LLQtWebKit::getInstance()->remObserver( mBrowserWindowId, this );
+
+ // clean up
+ LLQtWebKit::getInstance()->reset();
+
+// std::cerr << "MediaPluginWebKit destructor" << std::endl;
+}
+
+void MediaPluginWebKit::receiveMessage(const char *message_string)
+{
+// std::cerr << "MediaPluginWebKit::receiveMessage: received message: \"" << message_string << "\"" << std::endl;
+ LLPluginMessage message_in;
+
+ if(message_in.parse(message_string) >= 0)
+ {
+ std::string message_class = message_in.getClass();
+ std::string message_name = message_in.getName();
+ if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
+ {
+ if(message_name == "init")
+ {
+ std::string user_data_path = message_in.getValue("user_data_path"); // n.b. always has trailing platform-specific dir-delimiter
+ mProfileDir = user_data_path + "browser_profile";
+
+ LLPluginMessage message("base", "init_response");
+ LLSD versions = LLSD::emptyMap();
+ versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
+ versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
+ versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION;
+ message.setValueLLSD("versions", versions);
+
+ std::string plugin_version = "Webkit media plugin, Webkit version ";
+ plugin_version += LLQtWebKit::getInstance()->getVersion();
+ message.setValue("plugin_version", plugin_version);
+ sendMessage(message);
+
+ // Plugin gets to decide the texture parameters to use.
+ mDepth = 4;
+
+ message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
+ message.setValueS32("default_width", 1024);
+ message.setValueS32("default_height", 1024);
+ message.setValueS32("depth", mDepth);
+ message.setValueU32("internalformat", GL_RGBA);
+ message.setValueU32("format", GL_RGBA);
+ message.setValueU32("type", GL_UNSIGNED_BYTE);
+ message.setValueBoolean("coords_opengl", true);
+ sendMessage(message);
+ }
+ else if(message_name == "idle")
+ {
+ // no response is necessary here.
+ F64 time = message_in.getValueReal("time");
+
+ // Convert time to milliseconds for update()
+ update((int)(time * 1000.0f));
+ }
+ else if(message_name == "cleanup")
+ {
+ // DTOR most likely won't be called but the recent change to the way this process
+ // is (not) killed means we see this message and can do what we need to here.
+ // Note: this cleanup is ultimately what writes cookies to the disk
+ LLQtWebKit::getInstance()->remObserver( mBrowserWindowId, this );
+ LLQtWebKit::getInstance()->reset();
+ }
+ else if(message_name == "shm_added")
+ {
+ SharedSegmentInfo info;
+ info.mAddress = message_in.getValuePointer("address");
+ info.mSize = (size_t)message_in.getValueS32("size");
+ std::string name = message_in.getValue("name");
+
+// std::cerr << "MediaPluginWebKit::receiveMessage: shared memory added, name: " << name
+// << ", size: " << info.mSize
+// << ", address: " << info.mAddress
+// << std::endl;
+
+ mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
+
+ }
+ else if(message_name == "shm_remove")
+ {
+ std::string name = message_in.getValue("name");
+
+// std::cerr << "MediaPluginWebKit::receiveMessage: shared memory remove, name = " << name << std::endl;
+
+ SharedSegmentMap::iterator iter = mSharedSegments.find(name);
+ if(iter != mSharedSegments.end())
+ {
+ if(mPixels == iter->second.mAddress)
+ {
+ // This is the currently active pixel buffer. Make sure we stop drawing to it.
+ mPixels = NULL;
+ mTextureSegmentName.clear();
+ }
+ mSharedSegments.erase(iter);
+ }
+ else
+ {
+// std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl;
+ }
+
+ // Send the response so it can be cleaned up.
+ LLPluginMessage message("base", "shm_remove_response");
+ message.setValue("name", name);
+ sendMessage(message);
+ }
+ else
+ {
+// std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl;
+ }
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
+ {
+ if(message_name == "size_change")
+ {
+ std::string name = message_in.getValue("name");
+ S32 width = message_in.getValueS32("width");
+ S32 height = message_in.getValueS32("height");
+ S32 texture_width = message_in.getValueS32("texture_width");
+ S32 texture_height = message_in.getValueS32("texture_height");
+ mBackgroundR = message_in.getValueReal("background_r");
+ mBackgroundG = message_in.getValueReal("background_g");
+ mBackgroundB = message_in.getValueReal("background_b");
+// mBackgroundA = message_in.setValueReal("background_a"); // Ignore any alpha
+
+ if(!name.empty())
+ {
+ // Find the shared memory region with this name
+ SharedSegmentMap::iterator iter = mSharedSegments.find(name);
+ if(iter != mSharedSegments.end())
+ {
+ mPixels = (unsigned char*)iter->second.mAddress;
+ mWidth = width;
+ mHeight = height;
+
+ // initialize (only gets called once)
+ initBrowser();
+
+ // size changed so tell the browser
+ LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight );
+
+// std::cerr << "webkit plugin: set size to " << mWidth << " x " << mHeight
+// << ", rowspan is " << LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) << std::endl;
+
+ S32 real_width = LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) / LLQtWebKit::getInstance()->getBrowserDepth(mBrowserWindowId);
+
+ // The actual width the browser will be drawing to is probably smaller... let the host know by modifying texture_width in the response.
+ if(real_width <= texture_width)
+ {
+ texture_width = real_width;
+ }
+ else
+ {
+ // This won't work -- it'll be bigger than the allocated memory. This is a fatal error.
+// std::cerr << "Fatal error: browser rowbytes greater than texture width" << std::endl;
+ mDeleteMe = true;
+ return;
+ }
+
+ mTextureWidth = texture_width;
+ mTextureHeight = texture_height;
+
+ };
+ };
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
+ message.setValue("name", name);
+ message.setValueS32("width", width);
+ message.setValueS32("height", height);
+ message.setValueS32("texture_width", texture_width);
+ message.setValueS32("texture_height", texture_height);
+ sendMessage(message);
+
+ }
+ else if(message_name == "load_uri")
+ {
+ std::string uri = message_in.getValue("uri");
+
+// std::cout << "loading URI: " << uri << std::endl;
+
+ if(!uri.empty())
+ {
+ if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
+ {
+ LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, uri );
+ }
+ else
+ {
+ mInitialNavigateURL = uri;
+ }
+ }
+ }
+ else if(message_name == "mouse_event")
+ {
+ std::string event = message_in.getValue("event");
+ S32 button = message_in.getValueS32("button");
+ mLastMouseX = message_in.getValueS32("x");
+ mLastMouseY = message_in.getValueS32("y");
+ std::string modifiers = message_in.getValue("modifiers");
+
+ // Treat unknown mouse events as mouse-moves.
+ LLQtWebKit::EMouseEvent mouse_event = LLQtWebKit::ME_MOUSE_MOVE;
+ if(event == "down")
+ {
+ mouse_event = LLQtWebKit::ME_MOUSE_DOWN;
+ }
+ else if(event == "up")
+ {
+ mouse_event = LLQtWebKit::ME_MOUSE_UP;
+ }
+ else if(event == "double_click")
+ {
+ mouse_event = LLQtWebKit::ME_MOUSE_DOUBLE_CLICK;
+ }
+
+ LLQtWebKit::getInstance()->mouseEvent( mBrowserWindowId, mouse_event, button, mLastMouseX, mLastMouseY, decodeModifiers(modifiers));
+ checkEditState();
+ }
+ else if(message_name == "scroll_event")
+ {
+ S32 x = message_in.getValueS32("x");
+ S32 y = message_in.getValueS32("y");
+ std::string modifiers = message_in.getValue("modifiers");
+
+ // Incoming scroll events are adjusted so that 1 detent is approximately 1 unit.
+ // Qt expects 1 detent to be 120 units.
+ // It also seems that our y scroll direction is inverted vs. what Qt expects.
+
+ x *= 120;
+ y *= -120;
+
+ LLQtWebKit::getInstance()->scrollWheelEvent(mBrowserWindowId, mLastMouseX, mLastMouseY, x, y, decodeModifiers(modifiers));
+ }
+ else if(message_name == "key_event")
+ {
+ std::string event = message_in.getValue("event");
+ S32 key = message_in.getValueS32("key");
+ std::string modifiers = message_in.getValue("modifiers");
+
+ // Treat unknown events as key-up for safety.
+ LLQtWebKit::EKeyEvent key_event = LLQtWebKit::KE_KEY_UP;
+ if(event == "down")
+ {
+ key_event = LLQtWebKit::KE_KEY_DOWN;
+ }
+ else if(event == "repeat")
+ {
+ key_event = LLQtWebKit::KE_KEY_REPEAT;
+ }
+
+ keyEvent(key_event, key, decodeModifiers(modifiers));
+ }
+ else if(message_name == "text_event")
+ {
+ std::string text = message_in.getValue("text");
+ std::string modifiers = message_in.getValue("modifiers");
+
+ unicodeInput(text, decodeModifiers(modifiers));
+ }
+ if(message_name == "edit_cut")
+ {
+ LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_CUT );
+ checkEditState();
+ }
+ if(message_name == "edit_copy")
+ {
+ LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_COPY );
+ checkEditState();
+ }
+ if(message_name == "edit_paste")
+ {
+ LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_PASTE );
+ checkEditState();
+ }
+ else
+ {
+// std::cerr << "MediaPluginWebKit::receiveMessage: unknown media message: " << message_string << std::endl;
+ };
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
+ {
+ if(message_name == "focus")
+ {
+ bool val = message_in.getValueBoolean("focused");
+ LLQtWebKit::getInstance()->focusBrowser( mBrowserWindowId, val );
+
+ if(mFirstFocus && val)
+ {
+ // On the first focus, post a tab key event. This fixes a problem with initial focus.
+ std::string empty;
+ keyEvent(LLQtWebKit::KE_KEY_DOWN, KEY_TAB, decodeModifiers(empty));
+ keyEvent(LLQtWebKit::KE_KEY_UP, KEY_TAB, decodeModifiers(empty));
+ mFirstFocus = false;
+ }
+ }
+ else if(message_name == "clear_cache")
+ {
+ LLQtWebKit::getInstance()->clearCache();
+ }
+ else if(message_name == "clear_cookies")
+ {
+ LLQtWebKit::getInstance()->clearAllCookies();
+ }
+ else if(message_name == "enable_cookies")
+ {
+ bool val = message_in.getValueBoolean("enable");
+ LLQtWebKit::getInstance()->enableCookies( val );
+ }
+ else if(message_name == "proxy_setup")
+ {
+ bool val = message_in.getValueBoolean("enable");
+ std::string host = message_in.getValue("host");
+ int port = message_in.getValueS32("port");
+ LLQtWebKit::getInstance()->enableProxy( val, host, port );
+ }
+ else if(message_name == "browse_stop")
+ {
+ LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_STOP );
+ }
+ else if(message_name == "browse_reload")
+ {
+ // foo = message_in.getValueBoolean("ignore_cache");
+ LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_RELOAD );
+ }
+ else if(message_name == "browse_forward")
+ {
+ LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD );
+ }
+ else if(message_name == "browse_back")
+ {
+ LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK );
+ }
+ else if(message_name == "set_status_redirect")
+ {
+ int code = message_in.getValueS32("code");
+ std::string url = message_in.getValue("url");
+ if ( 404 == code ) // browser lib only supports 404 right now
+ {
+ LLQtWebKit::getInstance()->set404RedirectUrl( mBrowserWindowId, url );
+ };
+ }
+ else if(message_name == "set_user_agent")
+ {
+ std::string user_agent = message_in.getValue("user_agent");
+ LLQtWebKit::getInstance()->setBrowserAgentId( user_agent );
+ }
+ else if(message_name == "init_history")
+ {
+ // Initialize browser history
+ LLSD history = message_in.getValueLLSD("history");
+ // First, clear the URL history
+ LLQtWebKit::getInstance()->clearHistory(mBrowserWindowId);
+ // Then, add the history items in order
+ LLSD::array_iterator iter_history = history.beginArray();
+ LLSD::array_iterator end_history = history.endArray();
+ for(; iter_history != end_history; ++iter_history)
+ {
+ std::string url = (*iter_history).asString();
+ if(! url.empty()) {
+ LLQtWebKit::getInstance()->prependHistoryUrl(mBrowserWindowId, url);
+ }
+ }
+ }
+ else
+ {
+// std::cerr << "MediaPluginWebKit::receiveMessage: unknown media_browser message: " << message_string << std::endl;
+ };
+ }
+ else
+ {
+// std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl;
+ };
+ }
+}
+
+int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data)
+{
+ MediaPluginWebKit *self = new MediaPluginWebKit(host_send_func, host_user_data);
+ *plugin_send_func = MediaPluginWebKit::staticReceiveMessage;
+ *plugin_user_data = (void*)self;
+
+ return 0;
+}
+
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 7b1c3003f0..5373556c20 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -11,7 +11,6 @@ include(ELFIO)
include(FMOD)
include(OPENAL)
include(FindOpenGL)
-include(LLAddBuildTest)
include(LLAudio)
include(LLCharacter)
include(LLCommon)
@@ -19,17 +18,17 @@ include(LLImage)
include(LLImageJ2COJ)
include(LLInventory)
include(LLMath)
-include(LLMedia)
include(LLMessage)
+include(LLPlugin)
include(LLPrimitive)
include(LLRender)
include(LLUI)
include(LLVFS)
include(LLWindow)
include(LLXML)
+include(LLXUIXML)
include(LScript)
include(Linking)
-include(Mozlib)
include(NDOF)
include(GooglePerfTools)
include(TemplateCheck)
@@ -37,10 +36,8 @@ include(UI)
include(UnixInstall)
include(LLKDU)
include(ViewerMiscLibs)
-
-if (WINDOWS)
- include(CopyWinLibs)
-endif (WINDOWS)
+include(LLLogin)
+include(CMakeCopyIfDifferent)
include_directories(
${DBUSGLIB_INCLUDE_DIRS}
@@ -51,16 +48,18 @@ include_directories(
${LLIMAGE_INCLUDE_DIRS}
${LLINVENTORY_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS}
- ${LLMEDIA_INCLUDE_DIRS}
${LLMESSAGE_INCLUDE_DIRS}
+ ${LLPLUGIN_INCLUDE_DIRS}
${LLPRIMITIVE_INCLUDE_DIRS}
${LLRENDER_INCLUDE_DIRS}
${LLUI_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS}
${LLWINDOW_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS}
+ ${LLXUIXML_INCLUDE_DIRS}
${LSCRIPT_INCLUDE_DIRS}
${LSCRIPT_INCLUDE_DIRS}/lscript_compile
+ ${LLLOGIN_INCLUDE_DIRS}
)
set(viewer_SOURCE_FILES
@@ -68,41 +67,59 @@ set(viewer_SOURCE_FILES
llagentaccess.cpp
llagentdata.cpp
llagentlanguage.cpp
+ llagentlistener.cpp
+ llagentpicksinfo.cpp
llagentpilot.cpp
+ llagentui.cpp
+ llagentwearables.cpp
llanimstatelabels.cpp
+ llappearancemgr.cpp
llappviewer.cpp
- llassetuploadresponders.cpp
+ llappviewerlistener.cpp
llassetuploadqueue.cpp
+ llassetuploadresponders.cpp
llaudiosourcevo.cpp
- llbbox.cpp
+ llavataractions.cpp
+ llavatariconctrl.cpp
+ llavatarlist.cpp
+ llavatarlistitem.cpp
+ llavatarpropertiesprocessor.cpp
+ llbottomtray.cpp
llbox.cpp
+ llbreadcrumbview.cpp
llcallbacklist.cpp
+ llcallfloater.cpp
llcallingcard.cpp
+ llcapabilitylistener.cpp
llcaphttpsender.cpp
+ llchannelmanager.cpp
llchatbar.cpp
+ llchathistory.cpp
+ llchatitemscontainerctrl.cpp
+ llchatmsgbox.cpp
+ llchiclet.cpp
llclassifiedinfo.cpp
llclassifiedstatsresponder.cpp
llcloud.cpp
- llcolorscheme.cpp
llcolorswatch.cpp
+ llcommanddispatcherlistener.cpp
llcommandhandler.cpp
llcommandlineparser.cpp
- llcompass.cpp
llcompilequeue.cpp
llconfirmationmanager.cpp
- llconsole.cpp
- llcontainerview.cpp
llcurrencyuimanager.cpp
llcylinder.cpp
+ lldateutil.cpp
lldebugmessagebox.cpp
lldebugview.cpp
lldelayedgestureerror.cpp
lldirpicker.cpp
+ lldndbutton.cpp
lldrawable.cpp
+ lldrawpool.cpp
lldrawpoolalpha.cpp
lldrawpoolavatar.cpp
lldrawpoolbump.cpp
- lldrawpool.cpp
lldrawpoolground.cpp
lldrawpoolsimple.cpp
lldrawpoolsky.cpp
@@ -116,8 +133,10 @@ set(viewer_SOURCE_FILES
lleventinfo.cpp
lleventnotifier.cpp
lleventpoll.cpp
+ llexpandabletextbox.cpp
llface.cpp
llfasttimerview.cpp
+ llfavoritesbar.cpp
llfeaturemanager.cpp
llfilepicker.cpp
llfirstuse.cpp
@@ -126,59 +145,49 @@ set(viewer_SOURCE_FILES
llfloateractivespeakers.cpp
llfloateranimpreview.cpp
llfloaterauction.cpp
- llfloateravatarinfo.cpp
llfloateravatarpicker.cpp
llfloateravatartextures.cpp
llfloaterbeacons.cpp
llfloaterbuildoptions.cpp
llfloaterbulkpermission.cpp
llfloaterbump.cpp
- llfloaterbuycontents.cpp
llfloaterbuy.cpp
+ llfloaterbuycontents.cpp
llfloaterbuycurrency.cpp
llfloaterbuyland.cpp
llfloatercamera.cpp
- llfloaterchat.cpp
llfloaterchatterbox.cpp
- llfloaterclassified.cpp
llfloatercolorpicker.cpp
llfloatercustomize.cpp
llfloaterdaycycle.cpp
- llfloaterdirectory.cpp
- llfloatereditui.cpp
llfloaterenvsettings.cpp
- llfloaterevent.cpp
- llfloaterfriends.cpp
llfloaterfonttest.cpp
+ llfloaterfriends.cpp
llfloatergesture.cpp
llfloatergodtools.cpp
- llfloatergroupinfo.cpp
llfloatergroupinvite.cpp
llfloatergroups.cpp
llfloaterhandler.cpp
llfloaterhardwaresettings.cpp
- llfloaterhtml.cpp
- llfloaterhtmlcurrency.cpp
- llfloaterhtmlhelp.cpp
- llfloaterhtmlsimple.cpp
+ llfloaterhelpbrowser.cpp
llfloaterhud.cpp
llfloaterimagepreview.cpp
llfloaterinspect.cpp
+ llfloaterinventory.cpp
llfloaterjoystick.cpp
llfloaterlagmeter.cpp
llfloaterland.cpp
llfloaterlandholdings.cpp
- llfloaterlandmark.cpp
llfloatermap.cpp
+ llfloatermediabrowser.cpp
+ llfloatermediasettings.cpp
llfloatermemleak.cpp
- llfloatermute.cpp
llfloaternamedesc.cpp
- llfloaternewim.cpp
+ llfloaternearbymedia.cpp
llfloaternotificationsconsole.cpp
- llfloaterobjectiminfo.cpp
llfloateropenobject.cpp
llfloaterparcel.cpp
- llfloaterpermissionsmgr.cpp
+ llfloaterpay.cpp
llfloaterperms.cpp
llfloaterpostcard.cpp
llfloaterpostprocess.cpp
@@ -187,34 +196,39 @@ set(viewer_SOURCE_FILES
llfloaterregioninfo.cpp
llfloaterreporter.cpp
llfloaterscriptdebug.cpp
+ llfloaterscriptlimits.cpp
+ llfloatersearch.cpp
llfloatersellland.cpp
llfloatersettingsdebug.cpp
llfloatersnapshot.cpp
- llfloaterstats.cpp
llfloatertelehub.cpp
- llfloatertest.cpp
+ llfloatertestinspectors.cpp
+ llfloatertestlistview.cpp
llfloatertools.cpp
llfloatertopobjects.cpp
llfloatertos.cpp
+ llfloateruipreview.cpp
llfloaterurldisplay.cpp
llfloaterurlentry.cpp
llfloatervoicedevicesettings.cpp
llfloaterwater.cpp
+ llfloaterwhitelistentry.cpp
llfloaterwindlight.cpp
+ llfloaterwindowsize.cpp
llfloaterworldmap.cpp
llfolderview.cpp
+ llfolderviewitem.cpp
llfollowcam.cpp
- llframestats.cpp
- llframestatview.cpp
+ llfriendcard.cpp
llgesturemgr.cpp
- llgivemoney.cpp
llglsandbox.cpp
+ llgroupactions.cpp
+ llgroupiconctrl.cpp
+ llgrouplist.cpp
llgroupmgr.cpp
- llgroupnotify.cpp
llhomelocationresponder.cpp
- llhoverview.cpp
- llhudeffectbeam.cpp
llhudeffect.cpp
+ llhudeffectbeam.cpp
llhudeffectlookat.cpp
llhudeffectpointat.cpp
llhudeffecttrail.cpp
@@ -224,25 +238,45 @@ set(viewer_SOURCE_FILES
llhudrender.cpp
llhudtext.cpp
llhudview.cpp
+ llimfloater.cpp
+ llimfloatercontainer.cpp
+ llimhandler.cpp
llimpanel.cpp
llimview.cpp
- llinventoryactions.cpp
+ llinspect.cpp
+ llinspectavatar.cpp
+ llinspectgroup.cpp
+ llinspectobject.cpp
+ llinspectremoteobject.cpp
+ llinspecttoast.cpp
llinventorybridge.cpp
llinventoryclipboard.cpp
+ llinventoryfilter.cpp
+ llinventoryfunctions.cpp
llinventorymodel.cpp
- llinventoryview.cpp
+ llinventoryobserver.cpp
+ llinventorypanel.cpp
lljoystickbutton.cpp
+ lllandmarkactions.cpp
lllandmarklist.cpp
+ lllistbrowser.cpp
+ lllistview.cpp
+ lllocaltextureobject.cpp
+ lllocationhistory.cpp
+ lllocationinputctrl.cpp
lllogchat.cpp
llloginhandler.cpp
+ lllogininstance.cpp
llmanip.cpp
llmaniprotate.cpp
llmanipscale.cpp
llmaniptranslate.cpp
- llmapresponders.cpp
+ llmediactrl.cpp
+ llmediadataclient.cpp
llmediaremotectrl.cpp
llmemoryview.cpp
llmenucommands.cpp
+ llmetricperformancetester.cpp
llmimetypes.cpp
llmorphview.cpp
llmoveview.cpp
@@ -250,93 +284,144 @@ set(viewer_SOURCE_FILES
llnamebox.cpp
llnameeditor.cpp
llnamelistctrl.cpp
+ llnavigationbar.cpp
+ llnearbychat.cpp
+ llnearbychatbar.cpp
+ llnearbychathandler.cpp
llnetmap.cpp
- llnotify.cpp
+ llnotificationalerthandler.cpp
+ llnotificationgrouphandler.cpp
+ llnotificationhandlerutil.cpp
+ llnotificationmanager.cpp
+ llnotificationofferhandler.cpp
+ llnotificationscripthandler.cpp
+ llnotificationtiphandler.cpp
+ lloutputmonitorctrl.cpp
lloverlaybar.cpp
- llpanelaudioprefs.cpp
- llpanelaudiovolume.cpp
llpanelavatar.cpp
+ llpanelavatartag.cpp
+ llpanelblockedlist.cpp
llpanelclassified.cpp
llpanelcontents.cpp
- llpaneldebug.cpp
- llpaneldirbrowser.cpp
- llpaneldirclassified.cpp
- llpaneldirevents.cpp
- llpaneldirfind.cpp
- llpaneldirgroups.cpp
- llpaneldirland.cpp
- llpaneldirpeople.cpp
- llpaneldirplaces.cpp
- llpaneldirpopular.cpp
- llpaneldisplay.cpp
+ llpaneleditwearable.cpp
llpanelevent.cpp
llpanelface.cpp
- llpanelgeneral.cpp
llpanelgroup.cpp
llpanelgroupgeneral.cpp
llpanelgroupinvite.cpp
llpanelgrouplandmoney.cpp
llpanelgroupnotices.cpp
llpanelgrouproles.cpp
- llpanelinput.cpp
- llpanelinventory.cpp
+ llpanelhome.cpp
+ llpanelimcontrolpanel.cpp
llpanelland.cpp
+ llpanellandaudio.cpp
+ llpanellandmarkinfo.cpp
+ llpanellandmarks.cpp
llpanellandmedia.cpp
- llpanellandobjects.cpp
- llpanellandoptions.cpp
llpanellogin.cpp
- llpanelmorph.cpp
- llpanelmsgs.cpp
- llpanelnetwork.cpp
+ llpanelloginlistener.cpp
+ llpanellookinfo.cpp
+ llpanelmaininventory.cpp
+ llpanelmediasettingsgeneral.cpp
+ llpanelmediasettingspermissions.cpp
+ llpanelmediasettingssecurity.cpp
+ llpanelme.cpp
llpanelobject.cpp
+ llpanelobjectinventory.cpp
+ llpaneloutfitsinventory.cpp
+ llpanelpeople.cpp
+ llpanelpeoplemenus.cpp
llpanelpermissions.cpp
llpanelpick.cpp
+ llpanelpicks.cpp
llpanelplace.cpp
- llpanelskins.cpp
+ llpanelplaceinfo.cpp
+ llpanelplaceprofile.cpp
+ llpanelplaces.cpp
+ llpanelplacestab.cpp
+ llpanelprimmediacontrols.cpp
+ llpanelprofile.cpp
+ llpanelprofileview.cpp
+ llpanelshower.cpp
+ llpanelteleporthistory.cpp
llpanelvolume.cpp
- llpanelweb.cpp
+ llpanelvolumepulldown.cpp
llparcelselection.cpp
+ llparticipantlist.cpp
llpatchvertexarray.cpp
+ llplacesinventorybridge.cpp
+ llplacesinventorypanel.cpp
llpolymesh.cpp
llpolymorph.cpp
- llprefschat.cpp
- llprefsim.cpp
- llprefsvoice.cpp
- llpreviewanim.cpp
llpreview.cpp
+ llpreviewanim.cpp
llpreviewgesture.cpp
- llpreviewlandmark.cpp
llpreviewnotecard.cpp
llpreviewscript.cpp
llpreviewsound.cpp
llpreviewtexture.cpp
llproductinforequest.cpp
llprogressview.cpp
+ llrecentpeople.cpp
llregionposition.cpp
llremoteparcelrequest.cpp
llsavedsettingsglue.cpp
+ llscreenchannel.cpp
+ llscriptfloater.cpp
+ llscrollingpanelparam.cpp
+ llsearchcombobox.cpp
+ llsearchhistory.cpp
llselectmgr.cpp
+ llsidepanelappearance.cpp
+ llsidepanelinventory.cpp
+ llsidepanelinventorysubpanel.cpp
+ llsidepaneliteminfo.cpp
+ llsidepaneltaskinfo.cpp
+ llsidetray.cpp
+ llsidetraypanelcontainer.cpp
llsky.cpp
+ llslurl.cpp
llspatialpartition.cpp
+ llspeakbutton.cpp
+ llspeakers.cpp
+ llspeakingindicatormanager.cpp
+ llsplitbutton.cpp
llsprite.cpp
- llsrv.cpp
llstartup.cpp
- llstatbar.cpp
- llstatgraph.cpp
+ llstartuplistener.cpp
llstatusbar.cpp
- llstatview.cpp
llstylemap.cpp
llsurface.cpp
llsurfacepatch.cpp
+ llsyswellitem.cpp
+ llsyswellwindow.cpp
+ llteleporthistory.cpp
+ llteleporthistorystorage.cpp
+ lltexglobalcolor.cpp
lltexlayer.cpp
+ lltexlayerparams.cpp
+ lltextureatlas.cpp
+ lltextureatlasmanager.cpp
lltexturecache.cpp
lltexturectrl.cpp
lltexturefetch.cpp
+ lltextureinfo.cpp
+ lltextureinfodetails.cpp
+ lltexturestats.cpp
+ lltexturestatsuploader.cpp
lltextureview.cpp
+ lltextutil.cpp
+ lltoast.cpp
+ lltoastalertpanel.cpp
+ lltoastgroupnotifypanel.cpp
+ lltoastimpanel.cpp
+ lltoastnotifypanel.cpp
+ lltoastpanel.cpp
+ lltool.cpp
lltoolbar.cpp
lltoolbrush.cpp
lltoolcomp.cpp
- lltool.cpp
lltooldraganddrop.cpp
lltoolface.cpp
lltoolfocus.cpp
@@ -352,39 +437,49 @@ set(viewer_SOURCE_FILES
lltoolselect.cpp
lltoolselectland.cpp
lltoolselectrect.cpp
- lltoolview.cpp
lltracker.cpp
- lltrans.cpp
+ lltransientdockablefloater.cpp
+ lltransientfloatermgr.cpp
+ lluilistener.cpp
lluploaddialog.cpp
llurl.cpp
llurldispatcher.cpp
+ llurldispatcherlistener.cpp
llurlhistory.cpp
+ llurllineeditorctrl.cpp
llurlsimstring.cpp
llurlwhitelist.cpp
- lluserauth.cpp
llvectorperfoptions.cpp
- llvelocitybar.cpp
+ llversioninfo.cpp
llviewchildren.cpp
llviewerassetstorage.cpp
+ llviewerassettype.cpp
llvieweraudio.cpp
llviewercamera.cpp
+ llviewerchat.cpp
llviewercontrol.cpp
+ llviewercontrollistener.cpp
llviewerdisplay.cpp
+ llviewerfloaterreg.cpp
+ llviewerfoldertype.cpp
llviewergenericmessage.cpp
- llviewergesture.cpp
- llviewerimage.cpp
- llviewerimagelist.cpp
+ llviewergesture.cpp
+ llviewerhelp.cpp
+ llviewerhelputil.cpp
+ llviewerhome.cpp
llviewerinventory.cpp
- llviewerjointattachment.cpp
llviewerjoint.cpp
+ llviewerjointattachment.cpp
llviewerjointmesh.cpp
- llviewerjointmesh_sse2.cpp
llviewerjointmesh_sse.cpp
+ llviewerjointmesh_sse2.cpp
llviewerjointmesh_vec.cpp
llviewerjoystick.cpp
llviewerkeyboard.cpp
llviewerlayer.cpp
llviewermedia.cpp
+ llviewermedia_streamingaudio.cpp
+ llviewermediafocus.cpp
llviewermenu.cpp
llviewermenufile.cpp
llviewermessage.cpp
@@ -401,18 +496,23 @@ set(viewer_SOURCE_FILES
llviewershadermgr.cpp
llviewerstats.cpp
llviewertexteditor.cpp
+ llviewertexture.cpp
llviewertextureanim.cpp
+ llviewertexturelist.cpp
llviewerthrottle.cpp
llviewervisualparam.cpp
llviewerwindow.cpp
+ llviewerwindowlistener.cpp
llvlcomposition.cpp
llvlmanager.cpp
llvoavatar.cpp
llvoavatardefines.cpp
+ llvoavatarself.cpp
llvocache.cpp
llvoclouds.cpp
llvograss.cpp
llvoground.cpp
+ llvoicechannel.cpp
llvoiceclient.cpp
llvoiceremotectrl.cpp
llvoicevisualizer.cpp
@@ -429,9 +529,9 @@ set(viewer_SOURCE_FILES
llwaterparammanager.cpp
llwaterparamset.cpp
llwearable.cpp
+ llwearabledictionary.cpp
llwearablelist.cpp
llweb.cpp
- llwebbrowserctrl.cpp
llwind.cpp
llwlanimator.cpp
llwldaycycle.cpp
@@ -439,7 +539,10 @@ set(viewer_SOURCE_FILES
llwlparamset.cpp
llworld.cpp
llworldmap.cpp
+ llworldmapmessage.cpp
+ llworldmipmap.cpp
llworldmapview.cpp
+ llxmlrpclistener.cpp
llxmlrpctransaction.cpp
noise.cpp
pipeline.cpp
@@ -465,42 +568,60 @@ endif (LINUX)
set(viewer_HEADER_FILES
CMakeLists.txt
ViewerInstall.cmake
-
llagent.h
llagentaccess.h
llagentdata.h
llagentlanguage.h
+ llagentlistener.h
+ llagentpicksinfo.h
llagentpilot.h
+ llagentui.h
+ llagentwearables.h
llanimstatelabels.h
llappearance.h
+ llappearancemgr.h
llappviewer.h
- llassetuploadresponders.h
+ llappviewerlistener.h
llassetuploadqueue.h
+ llassetuploadresponders.h
llaudiosourcevo.h
- llbbox.h
+ llavataractions.h
+ llavatariconctrl.h
+ llavatarlist.h
+ llavatarlistitem.h
+ llavatarpropertiesprocessor.h
+ llbottomtray.h
llbox.h
+ llbreadcrumbview.h
llcallbacklist.h
+ llcallfloater.h
llcallingcard.h
+ llcapabilitylistener.h
+ llcapabilityprovider.h
llcaphttpsender.h
+ llchannelmanager.h
llchatbar.h
+ llchathistory.h
+ llchatitemscontainerctrl.h
+ llchatmsgbox.h
+ llchiclet.h
llclassifiedinfo.h
llclassifiedstatsresponder.h
llcloud.h
- llcolorscheme.h
llcolorswatch.h
+ llcommanddispatcherlistener.h
llcommandhandler.h
llcommandlineparser.h
- llcompass.h
llcompilequeue.h
llconfirmationmanager.h
- llconsole.h
- llcontainerview.h
llcurrencyuimanager.h
llcylinder.h
+ lldateutil.h
lldebugmessagebox.h
lldebugview.h
lldelayedgestureerror.h
lldirpicker.h
+ lldndbutton.h
lldrawable.h
lldrawpool.h
lldrawpoolalpha.h
@@ -520,8 +641,10 @@ set(viewer_HEADER_FILES
lleventinfo.h
lleventnotifier.h
lleventpoll.h
+ llexpandabletextbox.h
llface.h
llfasttimerview.h
+ llfavoritesbar.h
llfeaturemanager.h
llfilepicker.h
llfirstuse.h
@@ -530,7 +653,6 @@ set(viewer_HEADER_FILES
llfloateractivespeakers.h
llfloateranimpreview.h
llfloaterauction.h
- llfloateravatarinfo.h
llfloateravatarpicker.h
llfloateravatartextures.h
llfloaterbeacons.h
@@ -542,80 +664,77 @@ set(viewer_HEADER_FILES
llfloaterbuycurrency.h
llfloaterbuyland.h
llfloatercamera.h
- llfloaterchat.h
llfloaterchatterbox.h
- llfloaterclassified.h
llfloatercolorpicker.h
llfloatercustomize.h
llfloaterdaycycle.h
- llfloaterdirectory.h
- llfloatereditui.h
llfloaterenvsettings.h
- llfloaterevent.h
llfloaterfonttest.h
llfloaterfriends.h
llfloatergesture.h
llfloatergodtools.h
- llfloatergroupinfo.h
llfloatergroupinvite.h
llfloatergroups.h
llfloaterhandler.h
llfloaterhardwaresettings.h
- llfloaterhtml.h
- llfloaterhtmlcurrency.h
- llfloaterhtmlhelp.h
- llfloaterhtmlsimple.h
+ llfloaterhelpbrowser.h
llfloaterhud.h
llfloaterimagepreview.h
llfloaterinspect.h
+ llfloaterinventory.h
llfloaterjoystick.h
llfloaterlagmeter.h
llfloaterland.h
llfloaterlandholdings.h
- llfloaterlandmark.h
llfloatermap.h
+ llfloatermediabrowser.h
+ llfloatermediasettings.h
llfloatermemleak.h
- llfloatermute.h
llfloaternamedesc.h
- llfloaternewim.h
+ llfloaternearbymedia.h
llfloaternotificationsconsole.h
- llfloaterobjectiminfo.h
llfloateropenobject.h
llfloaterparcel.h
- llfloaterpermissionsmgr.h
+ llfloaterpay.h
+ llfloaterperms.h
llfloaterpostcard.h
llfloaterpostprocess.h
llfloaterpreference.h
- llfloaterperms.h
llfloaterproperties.h
llfloaterregioninfo.h
llfloaterreporter.h
llfloaterscriptdebug.h
+ llfloaterscriptlimits.h
+ llfloatersearch.h
llfloatersellland.h
llfloatersettingsdebug.h
llfloatersnapshot.h
- llfloaterstats.h
llfloatertelehub.h
- llfloatertest.h
+ llfloatertestinspectors.h
+ llfloatertestlistview.h
llfloatertools.h
llfloatertopobjects.h
llfloatertos.h
+ llfloateruipreview.h
llfloaterurldisplay.h
llfloaterurlentry.h
llfloatervoicedevicesettings.h
llfloaterwater.h
+ llfloaterwhitelistentry.h
llfloaterwindlight.h
+ llfloaterwindowsize.h
llfloaterworldmap.h
llfolderview.h
+ llfoldervieweventlistener.h
+ llfolderviewitem.h
llfollowcam.h
- llframestats.h
- llframestatview.h
+ llfriendcard.h
llgesturemgr.h
- llgivemoney.h
+ llgroupactions.h
+ llgroupiconctrl.h
+ llgrouplist.h
llgroupmgr.h
- llgroupnotify.h
llhomelocationresponder.h
- llhoverview.h
llhudeffect.h
llhudeffectbeam.h
llhudeffectlookat.h
@@ -627,25 +746,45 @@ set(viewer_HEADER_FILES
llhudrender.h
llhudtext.h
llhudview.h
+ llimfloater.h
+ llimfloatercontainer.h
llimpanel.h
llimview.h
+ llinspect.h
+ llinspectavatar.h
+ llinspectgroup.h
+ llinspectobject.h
+ llinspectremoteobject.h
+ llinspecttoast.h
llinventorybridge.h
llinventoryclipboard.h
+ llinventoryfilter.h
+ llinventoryfunctions.h
llinventorymodel.h
- llinventoryview.h
+ llinventoryobserver.h
+ llinventorypanel.h
lljoystickbutton.h
+ lllandmarkactions.h
lllandmarklist.h
lllightconstants.h
+ lllistbrowser.h
+ lllistview.h
+ lllocaltextureobject.h
+ lllocationhistory.h
+ lllocationinputctrl.h
lllogchat.h
llloginhandler.h
+ lllogininstance.h
llmanip.h
llmaniprotate.h
llmanipscale.h
llmaniptranslate.h
- llmapresponders.h
+ llmediactrl.h
+ llmediadataclient.h
llmediaremotectrl.h
llmemoryview.h
llmenucommands.h
+ llmetricperformancetester.h
llmimetypes.h
llmorphview.h
llmoveview.h
@@ -653,92 +792,138 @@ set(viewer_HEADER_FILES
llnamebox.h
llnameeditor.h
llnamelistctrl.h
+ llnavigationbar.h
+ llnearbychat.h
+ llnearbychatbar.h
+ llnearbychathandler.h
llnetmap.h
- llnotify.h
+ llnotificationhandler.h
+ llnotificationmanager.h
+ lloutputmonitorctrl.h
lloverlaybar.h
- llpanelaudioprefs.h
- llpanelaudiovolume.h
llpanelavatar.h
+ llpanelavatartag.h
+ llpanelblockedlist.h
llpanelclassified.h
llpanelcontents.h
- llpaneldebug.h
- llpaneldirbrowser.h
- llpaneldirclassified.h
- llpaneldirevents.h
- llpaneldirfind.h
- llpaneldirgroups.h
- llpaneldirland.h
- llpaneldirpeople.h
- llpaneldirplaces.h
- llpaneldirpopular.h
- llpaneldisplay.h
+ llpaneleditwearable.h
llpanelevent.h
llpanelface.h
- llpanelgeneral.h
llpanelgroup.h
llpanelgroupgeneral.h
llpanelgroupinvite.h
llpanelgrouplandmoney.h
llpanelgroupnotices.h
llpanelgrouproles.h
- llpanelinput.h
- llpanelinventory.h
+ llpanelhome.h
+ llpanelimcontrolpanel.h
llpanelland.h
+ llpanellandaudio.h
+ llpanellandmarkinfo.h
+ llpanellandmarks.h
llpanellandmedia.h
- llpanellandobjects.h
- llpanellandoptions.h
- llpanelLCD.h
llpanellogin.h
- llpanelmorph.h
- llpanelmsgs.h
- llpanelnetwork.h
+ llpanelloginlistener.h
+ llpanellookinfo.h
+ llpanelmaininventory.h
+ llpanelmediasettingsgeneral.h
+ llpanelmediasettingspermissions.h
+ llpanelmediasettingssecurity.h
+ llpanelme.h
llpanelobject.h
+ llpanelobjectinventory.h
+ llpaneloutfitsinventory.h
+ llpanelpeople.h
+ llpanelpeoplemenus.h
llpanelpermissions.h
llpanelpick.h
+ llpanelpicks.h
llpanelplace.h
- llpanelskins.h
+ llpanelplaceinfo.h
+ llpanelplaceprofile.h
+ llpanelplaces.h
+ llpanelplacestab.h
+ llpanelprimmediacontrols.h
+ llpanelprofile.h
+ llpanelprofileview.h
+ llpanelshower.h
+ llpanelteleporthistory.h
llpanelvolume.h
- llpanelweb.h
+ llpanelvolumepulldown.h
llparcelselection.h
+ llparticipantlist.h
llpatchvertexarray.h
+ llplacesinventorybridge.h
+ llplacesinventorypanel.h
llpolymesh.h
llpolymorph.h
- llprefschat.h
- llprefsim.h
- llprefsvoice.h
llpreview.h
llpreviewanim.h
llpreviewgesture.h
- llpreviewlandmark.h
llpreviewnotecard.h
llpreviewscript.h
llpreviewsound.h
llpreviewtexture.h
llproductinforequest.h
llprogressview.h
+ llrecentpeople.h
llregionposition.h
llremoteparcelrequest.h
llresourcedata.h
+ llrootview.h
llsavedsettingsglue.h
+ llscreenchannel.h
+ llscriptfloater.h
+ llscrollingpanelparam.h
+ llsearchcombobox.h
+ llsearchhistory.h
llselectmgr.h
+ llsidepanelappearance.h
+ llsidepanelinventory.h
+ llsidepanelinventorysubpanel.h
+ llsidepaneliteminfo.h
+ llsidepaneltaskinfo.h
+ llsidetray.h
+ llsidetraypanelcontainer.h
llsky.h
+ llslurl.h
llspatialpartition.h
+ llspeakbutton.h
+ llspeakers.h
+ llspeakingindicatormanager.h
+ llsplitbutton.h
llsprite.h
- llsrv.h
llstartup.h
- llstatbar.h
- llstatgraph.h
+ llstartuplistener.h
llstatusbar.h
- llstatview.h
llstylemap.h
llsurface.h
llsurfacepatch.h
+ llsyswellitem.h
+ llsyswellwindow.h
lltable.h
+ llteleporthistory.h
+ llteleporthistorystorage.h
+ lltexglobalcolor.h
lltexlayer.h
+ lltexlayerparams.h
+ lltextureatlas.h
+ lltextureatlasmanager.h
lltexturecache.h
lltexturectrl.h
lltexturefetch.h
+ lltextureinfo.h
+ lltextureinfodetails.h
+ lltexturestats.h
+ lltexturestatsuploader.h
lltextureview.h
+ lltextutil.h
+ lltoast.h
+ lltoastalertpanel.h
+ lltoastgroupnotifypanel.h
+ lltoastimpanel.h
+ lltoastnotifypanel.h
+ lltoastpanel.h
lltool.h
lltoolbar.h
lltoolbrush.h
@@ -758,30 +943,36 @@ set(viewer_HEADER_FILES
lltoolselect.h
lltoolselectland.h
lltoolselectrect.h
- lltoolview.h
lltracker.h
- lltrans.h
+ lltransientdockablefloater.h
+ lltransientfloatermgr.h
lluiconstants.h
+ lluilistener.h
lluploaddialog.h
llurl.h
llurldispatcher.h
+ llurldispatcherlistener.h
llurlhistory.h
+ llurllineeditorctrl.h
llurlsimstring.h
llurlwhitelist.h
- lluserauth.h
llvectorperfoptions.h
- llvelocitybar.h
+ llversioninfo.h
llviewchildren.h
llviewerassetstorage.h
+ llviewerassettype.h
llvieweraudio.h
- llviewerbuild.h
llviewercamera.h
+ llviewerchat.h
llviewercontrol.h
+ llviewercontrollistener.h
llviewerdisplay.h
+ llviewerfloaterreg.h
+ llviewerfoldertype.h
llviewergenericmessage.h
- llviewergesture.h
- llviewerimage.h
- llviewerimagelist.h
+ llviewergesture.h
+ llviewerhelp.h
+ llviewerhome.h
llviewerinventory.h
llviewerjoint.h
llviewerjointattachment.h
@@ -790,6 +981,8 @@ set(viewer_HEADER_FILES
llviewerkeyboard.h
llviewerlayer.h
llviewermedia.h
+ llviewermediafocus.h
+ llviewermediaobserver.h
llviewermenu.h
llviewermenufile.h
llviewermessage.h
@@ -807,18 +1000,23 @@ set(viewer_HEADER_FILES
llviewershadermgr.h
llviewerstats.h
llviewertexteditor.h
+ llviewertexture.h
llviewertextureanim.h
+ llviewertexturelist.h
llviewerthrottle.h
llviewervisualparam.h
llviewerwindow.h
+ llviewerwindowlistener.h
llvlcomposition.h
llvlmanager.h
llvoavatar.h
llvoavatardefines.h
+ llvoavatarself.h
llvocache.h
llvoclouds.h
llvograss.h
llvoground.h
+ llvoicechannel.h
llvoiceclient.h
llvoiceremotectrl.h
llvoicevisualizer.h
@@ -836,9 +1034,9 @@ set(viewer_HEADER_FILES
llwaterparammanager.h
llwaterparamset.h
llwearable.h
+ llwearabledictionary.h
llwearablelist.h
llweb.h
- llwebbrowserctrl.h
llwind.h
llwindebug.h
llwlanimator.h
@@ -847,12 +1045,14 @@ set(viewer_HEADER_FILES
llwlparamset.h
llworld.h
llworldmap.h
+ llworldmapmessage.h
+ llworldmipmap.h
llworldmapview.h
+ llxmlrpclistener.h
llxmlrpctransaction.h
macmain.h
noise.h
pipeline.h
- randgauss.h
VertexCache.h
VorbisFramework.h
)
@@ -900,7 +1100,7 @@ endif (DARWIN)
if (LINUX)
LIST(APPEND viewer_SOURCE_FILES llappviewerlinux.cpp)
LIST(APPEND viewer_SOURCE_FILES llappviewerlinux_api_dbus.cpp)
- LIST(APPEND CMAKE_EXE_LINKER_FLAGS -Wl,--as-needed)
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed")
set(viewer_LIBRARIES
Xinerama
@@ -923,18 +1123,13 @@ if (WINDOWS)
# the .pch file.
# All sources added to viewer_SOURCE_FILES
# at this point use it.
- set_source_files_properties(llviewerprecompiledheaders.cpp
- PROPERTIES
- COMPILE_FLAGS "/Ycllviewerprecompiledheaders.h"
- )
- foreach( src_file ${viewer_SOURCE_FILES} )
- set_source_files_properties(
- ${src_file}
+ if(USE_PRECOMPILED_HEADERS)
+ set_source_files_properties(llviewerprecompiledheaders.cpp
PROPERTIES
- COMPILE_FLAGS "/Yullviewerprecompiledheaders.h"
- )
- endforeach( src_file ${viewer_SOURCE_FILES} )
- list(APPEND viewer_SOURCE_FILES llviewerprecompiledheaders.cpp)
+ COMPILE_FLAGS "/Ycllviewerprecompiledheaders.h"
+ )
+ set(viewer_SOURCE_FILES "${viewer_SOURCE_FILES}" llviewerprecompiledheaders.cpp)
+ endif(USE_PRECOMPILED_HEADERS)
# Add resource files to the project.
# viewerRes.rc is the only buildable file, but
@@ -968,14 +1163,10 @@ if (WINDOWS)
res/ll_icon.BMP
res/ll_icon.ico
res/resource.h
- res/toolbuy.cur
- res/toolopen.cur
- res/toolpay.cur
res/toolpickobject.cur
res/toolpickobject2.cur
res/toolpickobject3.cur
res/toolpipette.cur
- res/toolsit.cur
)
set_source_files_properties(${viewer_RESOURCE_FILES}
@@ -988,7 +1179,9 @@ if (WINDOWS)
SOURCE_GROUP("Resource Files" FILES ${viewer_RESOURCE_FILES})
- list(APPEND viewer_SOURCE_FILES ${viewer_RESOURCE_FILES})
+ if (NOT STANDALONE)
+ list(APPEND viewer_SOURCE_FILES ${viewer_RESOURCE_FILES})
+ endif (NOT STANDALONE)
find_library(DINPUT_LIBRARY dinput8 ${DIRECTX_LIBRARY_DIR})
find_library(DXGUID_LIBRARY dxguid ${DIRECTX_LIBRARY_DIR})
@@ -998,12 +1191,10 @@ if (WINDOWS)
)
set(viewer_LIBRARIES
- advapi32
+ ${WINDOWS_LIBRARIES}
comdlg32
${DINPUT_LIBRARY}
${DXGUID_LIBRARY}
- fmodvc
- gdi32
kernel32
odbc32
odbccp32
@@ -1011,7 +1202,6 @@ if (WINDOWS)
oleaut32
opengl32
shell32
- user32
Vfw32
winspool
)
@@ -1033,16 +1223,30 @@ endif (WINDOWS)
# Add the xui files. This is handy for searching for xui elements
# from within the IDE.
+set(viewer_XUI_FILES
+ skins/default/colors.xml
+ skins/default/textures/textures.xml
+
-file(GLOB viewer_XUI_FILE_GLOB_LIST
- ${CMAKE_CURRENT_SOURCE_DIR}/skins/default/xui/en-us/*.xml)
-set(viewer_XUI_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/skins/default/colors.xml
- ${CMAKE_CURRENT_SOURCE_DIR}/skins/default/colors_base.xml
)
+file(GLOB DEFAULT_XUI_FILE_GLOB_LIST
+ ${CMAKE_CURRENT_SOURCE_DIR}/skins/default/xui/en/*.xml)
+list(APPEND viewer_XUI_FILES ${DEFAULT_XUI_FILE_GLOB_LIST})
+
+file(GLOB DEFAULT_WIDGET_FILE_GLOB_LIST
+ ${CMAKE_CURRENT_SOURCE_DIR}/skins/default/xui/en/widgets/*.xml)
+list(APPEND viewer_XUI_FILES ${DEFAULT_WIDGET_FILE_GLOB_LIST})
+
+file(GLOB SILVER_XUI_FILE_GLOB_LIST
+ ${CMAKE_CURRENT_SOURCE_DIR}/skins/silver/xui/en-us/*.xml)
+list(APPEND viewer_XUI_FILES ${SILVER_XUI_FILE_GLOB_LIST})
+
+# Cannot append empty lists in CMake, wait until we have files here.
+#file(GLOB SILVER_WIDGET_FILE_GLOB_LIST
+# ${CMAKE_CURRENT_SOURCE_DIR}/skins/silver/xui/en-us/widgets/*.xml)
+#list(APPEND viewer_XUI_FILES ${SILVER_WIDGET_FILE_GLOB_LIST})
-list(APPEND viewer_XUI_FILES ${viewer_XUI_FILE_GLOB_LIST})
list(SORT viewer_XUI_FILES)
source_group("XUI Files" FILES ${viewer_XUI_FILES})
@@ -1095,8 +1299,9 @@ source_group("Character File" FILES ${viewer_CHARACTER_FILES})
set_source_files_properties(${viewer_CHARACTER_FILES}
PROPERTIES HEADER_FILE_ONLY TRUE)
-
-list(APPEND viewer_SOURCE_FILES ${viewer_CHARACTER_FILES})
+if (NOT STANDALONE)
+ list(APPEND viewer_SOURCE_FILES ${viewer_CHARACTER_FILES})
+endif (NOT STANDALONE)
if (WINDOWS)
file(GLOB viewer_INSTALLER_FILES installers/windows/*.nsi)
@@ -1116,23 +1321,23 @@ endif (OPENAL)
if (FMOD)
set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMOD")
- if (NOT WINDOWS)
+ if (DARWIN)
set(fmodwrapper_SOURCE_FILES fmodwrapper.cpp)
add_library(fmodwrapper SHARED ${fmodwrapper_SOURCE_FILES})
- set(fmodwrapper_needed_LIBRARIES ${FMOD_LIBRARY})
- if (DARWIN)
- list(APPEND fmodwrapper_needed_LIBRARIES ${CARBON_LIBRARY})
- set_target_properties(
- fmodwrapper
- PROPERTIES
- BUILD_WITH_INSTALL_RPATH 1
- INSTALL_NAME_DIR "@executable_path/../Resources"
- LINK_FLAGS "-unexported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/fmod_hidden_symbols.exp"
- )
- endif (DARWIN)
+ set(fmodwrapper_needed_LIBRARIES ${FMOD_LIBRARY} ${CARBON_LIBRARY})
+ set_target_properties(
+ fmodwrapper
+ PROPERTIES
+ BUILD_WITH_INSTALL_RPATH 1
+ INSTALL_NAME_DIR "@executable_path/../Resources"
+ LINK_FLAGS "-unexported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/fmod_hidden_symbols.exp"
+ )
set(FMODWRAPPER_LIBRARY fmodwrapper)
target_link_libraries(fmodwrapper ${fmodwrapper_needed_LIBRARIES})
- endif (NOT WINDOWS)
+ else (DARWIN)
+ # fmodwrapper unnecessary on linux or windows
+ set(FMODWRAPPER_LIBRARY ${FMOD_LIBRARY})
+ endif (DARWIN)
endif (FMOD)
set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}")
@@ -1147,13 +1352,17 @@ add_executable(${VIEWER_BINARY_NAME}
MACOSX_BUNDLE
${viewer_SOURCE_FILES}
)
-check_message_template(${VIEWER_BINARY_NAME})
if (LLKDU_LIBRARY)
add_dependencies(${VIEWER_BINARY_NAME} ${LLKDU_LIBRARY})
endif (LLKDU_LIBRARY)
-set(PACKAGE OFF CACHE BOOL
+# add package files
+file(GLOB EVENT_HOST_SCRIPT_GLOB_LIST
+ ${CMAKE_CURRENT_SOURCE_DIR}/../viewer_components/*.py)
+list(APPEND EVENT_HOST_SCRIPTS ${EVENT_HOST_SCRIPT_GLOB_LIST})
+
+set(PACKAGE ON CACHE BOOL
"Add a package target that builds an installer package.")
if (WINDOWS)
@@ -1165,73 +1374,219 @@ if (WINDOWS)
set_target_properties(${VIEWER_BINARY_NAME}
PROPERTIES
+ # *TODO -reenable this once we get server usage sorted out
+ #LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /INCLUDE:\"__tcmalloc\""
LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS"
- LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\""
+ LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO"
LINK_FLAGS_RELEASE ${release_flags}
)
+ if(USE_PRECOMPILED_HEADERS)
+ set_target_properties(
+ ${VIEWER_BINARY_NAME}
+ PROPERTIES
+ COMPILE_FLAGS "/Yullviewerprecompiledheaders.h"
+ )
+ endif(USE_PRECOMPILED_HEADERS)
+
+ # If adding a file to viewer_manifest.py in the WindowsManifest.construct() method, be sure to add the dependency
+ # here.
+ # *NOTE:Mani - This is a crappy hack to have important dependecies for the viewer_manifest copy action
+ # be met. I'm looking forward to a source-code split-up project next year that will address this kind of thing.
+ # In the meantime, if you have any ideas on how to easily maintain one list, either here or in viewer_manifest.py
+ # and have the build deps get tracked *please* tell me about it.
+
+ if(LLKDU_LIBRARY)
+ # Configure a var for llkdu which may not exist for all builds.
+ set(LLKDU_DLL_SOURCE ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/llkdu.dll)
+ endif(LLKDU_LIBRARY)
+
+ if(USE_GOOGLE_PERFTOOLS)
+ # Configure a var for tcmalloc location, if used.
+ # Note the need to specify multiple names explicitly.
+ set(GOOGLE_PERF_TOOLS_SOURCE
+ ${SHARED_LIB_STAGING_DIR}/Release/libtcmalloc_minimal.dll
+ ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libtcmalloc_minimal.dll
+ ${SHARED_LIB_STAGING_DIR}/Debug/libtcmalloc_minimal-debug.dll
+ )
+ endif(USE_GOOGLE_PERFTOOLS)
+
+
+ set(COPY_INPUT_DEPENDECIES
+ # The following commented dependencies are determined at variably at build time. Can't do this here.
+ #${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libtcmalloc_minimal.dll => None ... Skipping libtcmalloc_minimal.dll
+ ${CMAKE_SOURCE_DIR}/../etc/message.xml
+ ${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg
+ ${LLKDU_DLL_SOURCE}
+ ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/llcommon.dll
+ ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libapr-1.dll
+ ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libaprutil-1.dll
+ ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libapriconv-1.dll
+ ${SHARED_LIB_STAGING_DIR}/Release/openjpeg.dll
+ ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/openjpeg.dll
+ ${SHARED_LIB_STAGING_DIR}/Debug/openjpegd.dll
+ ${SHARED_LIB_STAGING_DIR}/Release/msvcr80.dll
+ ${SHARED_LIB_STAGING_DIR}/Release/msvcp80.dll
+ ${SHARED_LIB_STAGING_DIR}/Release/Microsoft.VC80.CRT.manifest
+ ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/msvcr80.dll
+ ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/msvcp80.dll
+ ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/Microsoft.VC80.CRT.manifest
+ ${SHARED_LIB_STAGING_DIR}/Debug/msvcr80d.dll
+ ${SHARED_LIB_STAGING_DIR}/Debug/msvcp80d.dll
+ ${SHARED_LIB_STAGING_DIR}/Debug/Microsoft.VC80.DebugCRT.manifest
+ ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/SLVoice.exe
+ ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/vivoxsdk.dll
+ ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/ortp.dll
+ ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libsndfile-1.dll
+ ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/zlib1.dll
+ ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/vivoxplatform.dll
+ ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/vivoxoal.dll
+ ${GOOGLE_PERF_TOOLS_SOURCE}
+ ${CMAKE_CURRENT_SOURCE_DIR}/licenses-win32.txt
+ ${CMAKE_CURRENT_SOURCE_DIR}/featuretable.txt
+ ${CMAKE_CURRENT_SOURCE_DIR}/dbghelp.dll
+ ${CMAKE_CURRENT_SOURCE_DIR}/fmod.dll
+ ${CMAKE_BINARY_DIR}/media_plugins/quicktime/${CMAKE_CFG_INTDIR}/media_plugin_quicktime.dll
+ ${CMAKE_BINARY_DIR}/media_plugins/quicktime/${CMAKE_CFG_INTDIR}/media_plugin_webkit.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/libeay32.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/qtcore4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/qtgui4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/qtnetwork4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/qtopengl4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/qtwebkit4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/qtxmlpatterns4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/ssleay32.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qgif4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qico4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qjpeg4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qmng4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qsvg4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qtiff4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qcncodecs4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qjpcodecs4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qkrcodecs4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qtwcodecs4.dll
+ ${ARCH_PREBUILT_DIRS_DEBUG}/libeay32.dll
+ ${ARCH_PREBUILT_DIRS_DEBUG}/qtcored4.dll
+ ${ARCH_PREBUILT_DIRS_DEBUG}/qtguid4.dll
+ ${ARCH_PREBUILT_DIRS_DEBUG}/qtnetworkd4.dll
+ ${ARCH_PREBUILT_DIRS_DEBUG}/qtopengld4.dll
+ ${ARCH_PREBUILT_DIRS_DEBUG}/qtwebkitd4.dll
+ ${ARCH_PREBUILT_DIRS_DEBUG}/qtxmlpatternsd4.dll
+ ${ARCH_PREBUILT_DIRS_DEBUG}/ssleay32.dll
+ ${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qgifd4.dll
+ ${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qicod4.dll
+ ${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qjpegd4.dll
+ ${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qmngd4.dll
+ ${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qsvgd4.dll
+ ${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qtiffd4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qcncodecsd4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qjpcodecsd4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qkrcodecsd4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qtwcodecsd4.dll
+ SLPlugin
+ media_plugin_quicktime
+ media_plugin_webkit
+ windows-crash-logger
+ windows-updater
+ )
+
+ add_custom_command(
+ OUTPUT ${CMAKE_CFG_INTDIR}/copy_touched.bat
+ COMMAND ${PYTHON_EXECUTABLE}
+ ARGS
+ ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
+ --actions=copy
+ --artwork=${ARTWORK_DIR}
+ --build=${CMAKE_CURRENT_BINARY_DIR}
+ --buildtype=${CMAKE_BUILD_TYPE}
+ --configuration=${CMAKE_CFG_INTDIR}
+ --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}
+ --grid=${GRID}
+ --source=${CMAKE_CURRENT_SOURCE_DIR}
+ --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/copy_touched.bat
+ DEPENDS
+ ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
+ stage_third_party_libs
+ ${COPY_INPUT_DEPENDECIES}
+ COMMENT "Performing viewer_manifest copy"
+ )
+
+ add_custom_target(copy_w_viewer_manifest ALL DEPENDS ${CMAKE_CFG_INTDIR}/copy_touched.bat)
+
+ add_dependencies(${VIEWER_BINARY_NAME} stage_third_party_libs llcommon copy_w_viewer_manifest)
+
+ if(LLKDU_LIBRARY)
+ # kdu may not exist!
+ add_dependencies(copy_w_viewer_manifest llkdu)
+ endif(LLKDU_LIBRARY)
+
+ if (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts)
+ add_dependencies(${VIEWER_BINARY_NAME} copy_win_scripts)
+ endif (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts)
+
+ add_dependencies(${VIEWER_BINARY_NAME}
+ SLPlugin
+ media_plugin_quicktime
+ media_plugin_webkit
+ windows-updater
+ windows-crash-logger
+ )
# sets the 'working directory' for debugging from visual studio.
if (NOT UNATTENDED)
add_custom_command(
- TARGET ${VIEWER_BINARY_NAME} PRE_BUILD
+ TARGET ${VIEWER_BINARY_NAME} POST_BUILD
COMMAND ${CMAKE_SOURCE_DIR}/tools/vstool/vstool.exe
ARGS
--solution
${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.sln
--workingdir
${VIEWER_BINARY_NAME}
- ${CMAKE_CURRENT_SOURCE_DIR}
+ "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Setting the ${VIEWER_BINARY_NAME} working directory for debugging."
)
endif (NOT UNATTENDED)
- add_custom_command(
- TARGET ${VIEWER_BINARY_NAME} PRE_BUILD
- COMMAND ${CMAKE_COMMAND}
- ARGS
- -E
- copy_if_different
- ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/messages/message_template.msg
- ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/app_settings/message_template.msg
- COMMENT "Copying message_template.msg to the runtime folder."
- )
-
- add_custom_command(
- TARGET ${VIEWER_BINARY_NAME} PRE_BUILD
- COMMAND ${CMAKE_COMMAND}
+ if (PACKAGE)
+ add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.bz2
+ COMMAND ${PYTHON_EXECUTABLE}
ARGS
- -E
- copy_if_different
- ${CMAKE_CURRENT_SOURCE_DIR}/../../etc/message.xml
- ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/app_settings/message.xml
- COMMENT "Copying message.xml to the runtime folder."
+ ${CMAKE_CURRENT_SOURCE_DIR}/event_host_manifest.py
+ ${CMAKE_CURRENT_SOURCE_DIR}/..
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CFG_INTDIR}
+ DEPENDS
+ lleventhost
+ ${EVENT_HOST_SCRIPTS}
+ ${CMAKE_CURRENT_SOURCE_DIR}/event_host_manifest.py
)
-
- add_dependencies(${VIEWER_BINARY_NAME} copy_win_libs)
-
- if (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts)
- add_dependencies(${VIEWER_BINARY_NAME} copy_win_scripts)
- endif (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts)
-
- add_custom_command(
+
+ add_custom_command(
OUTPUT ${CMAKE_CFG_INTDIR}/touched.bat
COMMAND ${PYTHON_EXECUTABLE}
ARGS
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
- --configuration=${CMAKE_CFG_INTDIR}
+ --artwork=${ARTWORK_DIR}
+ --build=${CMAKE_CURRENT_BINARY_DIR}
+ --buildtype=${CMAKE_BUILD_TYPE}
--channel=${VIEWER_CHANNEL}
- --login_channel=${VIEWER_LOGIN_CHANNEL}
+ --configuration=${CMAKE_CFG_INTDIR}
+ --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}
--grid=${GRID}
+ --login_channel=${VIEWER_LOGIN_CHANNEL}
--source=${CMAKE_CURRENT_SOURCE_DIR}
- --artwork=${ARTWORK_DIR}
- --build=${CMAKE_CURRENT_BINARY_DIR}
- --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}
- --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/touched.bat
+ --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/touched.bat
DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
)
- if (PACKAGE)
+
add_custom_target(package ALL DEPENDS ${CMAKE_CFG_INTDIR}/touched.bat)
- add_dependencies(package windows-updater windows-crash-logger)
+ # temporarily disable packaging of event_host until hg subrepos get
+ # sorted out on the parabuild cluster...
+ #${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.bz2)
+
+ check_message_template(package)
+
endif (PACKAGE)
endif (WINDOWS)
@@ -1241,8 +1596,8 @@ target_link_libraries(${VIEWER_BINARY_NAME}
${LLIMAGE_LIBRARIES}
${LLIMAGEJ2COJ_LIBRARIES}
${LLINVENTORY_LIBRARIES}
- ${LLMEDIA_LIBRARIES}
${LLMESSAGE_LIBRARIES}
+ ${LLPLUGIN_LIBRARIES}
${LLPRIMITIVE_LIBRARIES}
${LLRENDER_LIBRARIES}
${FREETYPE_LIBRARIES}
@@ -1250,6 +1605,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
${LLVFS_LIBRARIES}
${LLWINDOW_LIBRARIES}
${LLXML_LIBRARIES}
+ ${LLXUIXML_LIBRARIES}
${LSCRIPT_LIBRARIES}
${LLMATH_LIBRARIES}
${LLCOMMON_LIBRARIES}
@@ -1259,16 +1615,16 @@ target_link_libraries(${VIEWER_BINARY_NAME}
${BOOST_REGEX_LIBRARY}
${DBUSGLIB_LIBRARIES}
${OPENGL_LIBRARIES}
- ${FMODWRAPPER_LIBRARY}
+ ${FMODWRAPPER_LIBRARY} # must come after LLAudio
${OPENGL_LIBRARIES}
- ${MOZLIB_LIBRARIES}
${SDL_LIBRARY}
${SMARTHEAP_LIBRARY}
${UI_LIBRARIES}
- ${QUICKTIME_LIBRARY}
${WINDOWS_LIBRARIES}
${XMLRPCEPI_LIBRARIES}
${ELFIO_LIBRARIES}
+ ${LLLOGIN_LIBRARIES}
+ ${GOOGLE_PERFTOOLS_LIBRARIES}
)
build_version(viewer)
@@ -1292,22 +1648,28 @@ if (LINUX)
COMMAND ${PYTHON_EXECUTABLE}
ARGS
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
- --grid=${GRID}
- --channel=${VIEWER_CHANNEL}
- --login_channel=${VIEWER_LOGIN_CHANNEL}
- --installer_name=${product}
--arch=${ARCH}
- --source=${CMAKE_CURRENT_SOURCE_DIR}
--artwork=${ARTWORK_DIR}
--build=${CMAKE_CURRENT_BINARY_DIR}
+ --buildtype=${CMAKE_BUILD_TYPE}
+ --channel=${VIEWER_CHANNEL}
+ --configuration=${CMAKE_CFG_INTDIR}
--dest=${CMAKE_CURRENT_BINARY_DIR}/packaged
+ --grid=${GRID}
+ --installer_name=${product}
+ --login_channel=${VIEWER_LOGIN_CHANNEL}
+ --source=${CMAKE_CURRENT_SOURCE_DIR}
--touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched
DEPENDS secondlife-stripped ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
)
+ add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_gstreamer010 media_plugin_webkit)
+
if (NOT INSTALL)
add_custom_target(package ALL DEPENDS ${product}.tar.bz2)
add_dependencies(package linux-crash-logger-strip-target)
+ add_dependencies(package linux-updater-strip-target)
+ check_message_template(package)
endif (NOT INSTALL)
endif (LINUX)
@@ -1332,18 +1694,22 @@ if (DARWIN)
COMMAND ${PYTHON_EXECUTABLE}
ARGS
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
- --grid=${GRID}
--actions=copy
- --configuration=${CMAKE_CFG_INTDIR}
- --source=${CMAKE_CURRENT_SOURCE_DIR}
--artwork=${ARTWORK_DIR}
--build=${CMAKE_CURRENT_BINARY_DIR}
+ --buildtype=${CMAKE_BUILD_TYPE}
+ --configuration=${CMAKE_CFG_INTDIR}
--dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app
+ --grid=${GRID}
+ --source=${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
)
+ add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit)
+
if (PACKAGE)
add_custom_target(package ALL DEPENDS ${VIEWER_BINARY_NAME})
+ check_message_template(package)
add_dependencies(package mac-updater mac-crash-logger)
add_custom_command(
@@ -1352,6 +1718,7 @@ if (DARWIN)
ARGS
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
--grid=${GRID}
+ --buildtype=${CMAKE_BUILD_TYPE}
--configuration=${CMAKE_CFG_INTDIR}
--channel=${VIEWER_CHANNEL}
--login_channel=${VIEWER_LOGIN_CHANNEL}
@@ -1371,6 +1738,7 @@ if (DARWIN)
ARGS
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
--grid=${GRID}
+ --buildtype=${CMAKE_BUILD_TYPE}
--configuration=${CMAKE_CFG_INTDIR}
--channel=${VIEWER_CHANNEL}
--login_channel=${VIEWER_LOGIN_CHANNEL}
@@ -1390,4 +1758,61 @@ if (INSTALL)
include(${CMAKE_CURRENT_SOURCE_DIR}/ViewerInstall.cmake)
endif (INSTALL)
-ADD_VIEWER_BUILD_TEST(llagentaccess viewer)
+if (LL_TESTS)
+ # To add a viewer unit test, just add the test .cpp file below
+ # This creates a separate test project per file listed.
+ include(LLAddBuildTest)
+ SET(viewer_TEST_SOURCE_FILES
+ llagentaccess.cpp
+ lldateutil.cpp
+ llmediadataclient.cpp
+ lllogininstance.cpp
+ llviewerhelputil.cpp
+ )
+
+ ##################################################
+ # DISABLING PRECOMPILED HEADERS USAGE FOR TESTS
+ ##################################################
+ # if(USE_PRECOMPILED_HEADERS)
+ # set_source_files_properties(
+ # ${viewer_TEST_SOURCE_FILES}
+ # PROPERTIES
+ # LL_TEST_ADDITIONAL_SOURCE_FILES llviewerprecompiledheaders.cpp
+ # )
+ # endif(USE_PRECOMPILED_HEADERS)
+ LL_ADD_PROJECT_UNIT_TESTS(${VIEWER_BINARY_NAME} "${viewer_TEST_SOURCE_FILES}")
+
+ #set(TEST_DEBUG on)
+ set(test_sources llcapabilitylistener.cpp)
+ ##################################################
+ # DISABLING PRECOMPILED HEADERS USAGE FOR TESTS
+ ##################################################
+ # if(USE_PRECOMPILED_HEADERS)
+ # set(test_sources "${test_sources}" llviewerprecompiledheaders.cpp)
+ # endif(USE_PRECOMPILED_HEADERS)
+ set(test_libs
+ ${LLMESSAGE_LIBRARIES}
+ ${WINDOWS_LIBRARIES}
+ ${LLVFS_LIBRARIES}
+ ${LLMATH_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+ ${GOOGLEMOCK_LIBRARIES}
+ )
+
+ LL_ADD_INTEGRATION_TEST(llcapabilitylistener
+ "${test_sources}"
+ "${test_libs}"
+ ${PYTHON_EXECUTABLE}
+ "${CMAKE_SOURCE_DIR}/llmessage/tests/test_llsdmessage_peer.py"
+ )
+
+ #ADD_VIEWER_BUILD_TEST(llmemoryview viewer)
+ #ADD_VIEWER_BUILD_TEST(llagentaccess viewer)
+ #ADD_VIEWER_BUILD_TEST(llworldmap viewer)
+ #ADD_VIEWER_BUILD_TEST(llworldmipmap viewer)
+ #ADD_VIEWER_BUILD_TEST(lltextureinfo viewer)
+ #ADD_VIEWER_BUILD_TEST(lltextureinfodetails viewer)
+ #ADD_VIEWER_BUILD_TEST(lltexturestatsuploader viewer)
+endif (LL_TESTS)
+
+
diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings
index 0a1235b85d..879408d6e4 100644
--- a/indra/newview/English.lproj/InfoPlist.strings
+++ b/indra/newview/English.lproj/InfoPlist.strings
@@ -2,6 +2,6 @@
CFBundleName = "Second Life";
-CFBundleShortVersionString = "Second Life version 1.24.0.0";
-CFBundleGetInfoString = "Second Life version 1.24.0.0, Copyright 2004-2008 Linden Research, Inc.";
+CFBundleShortVersionString = "Second Life version 2.0.0.200030";
+CFBundleGetInfoString = "Second Life version 2.0.0.200030, Copyright 2004-2009 Linden Research, Inc.";
diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist
index baa5ccf1b9..38ebb22b84 100644
--- a/indra/newview/Info-SecondLife.plist
+++ b/indra/newview/Info-SecondLife.plist
@@ -32,7 +32,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
- <string>1.24.0.0</string>
+ <string>2.0.0.200030</string>
<key>CSResourcesFileMapped</key>
<true/>
</dict>
diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml
index 5f11ed8e22..5f143431de 100644
--- a/indra/newview/app_settings/cmd_line.xml
+++ b/indra/newview/app_settings/cmd_line.xml
@@ -106,6 +106,54 @@
<string>QuitAfterSeconds</string>
</map>
+ <key>logperformance</key>
+ <map>
+ <key>desc</key>
+ <string>Log performance metrics for benchmarking</string>
+ <key>map-to</key>
+ <string>LogPerformance</string>
+ </map>
+
+ <key>logmetrics</key>
+ <map>
+ <key>desc</key>
+ <string>Log metrics for benchmarking</string>
+ <key>map-to</key>
+ <string>LogMetrics</string>
+ </map>
+
+ <key>analyzeperformance</key>
+ <map>
+ <key>desc</key>
+ <string>When used in conjunction with logperformance, analyzes result of log against baseline.</string>
+ <key>map-to</key>
+ <string>AnalyzePerformance</string>
+ </map>
+
+ <key>debugsession</key>
+ <map>
+ <key>desc</key>
+ <string>Run as if RenderDebugGL is TRUE, but log errors until end of session.</string>
+ <key>map-to</key>
+ <string>DebugSession</string>
+ </map>
+
+ <key>replaysession</key>
+ <map>
+ <key>desc</key>
+ <string>After login, replay last recorded session and quit.</string>
+ <key>map-to</key>
+ <string>ReplaySession</string>
+ </map>
+
+ <key>nonotifications</key>
+ <map>
+ <key>desc</key>
+ <string>User will not get any notifications. NOTE: All notifications that occur will get added to ignore file for future runs.</string>
+ <key>map-to</key>
+ <string>IgnoreAllNotifications</string>
+ </map>
+
<key>rotate</key>
<map>
<key>map-to</key>
@@ -166,6 +214,16 @@
<string>UserLogFile</string>
</map>
+ <key>graphicslevel</key>
+ <map>
+ <key>desc</key>
+ <string>Set the detail level.
+ 0 - low, 1 - medium, 2 - high, 3 - ultra
+ </string>
+ <key>count</key>
+ <integer>1</integer>
+ </map>
+
<key>setdefault</key>
<map>
<key>desc</key>
diff --git a/indra/newview/app_settings/foldertypes.xml b/indra/newview/app_settings/foldertypes.xml
new file mode 100644
index 0000000000..0d539177f3
--- /dev/null
+++ b/indra/newview/app_settings/foldertypes.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<ensemble_defs>
+ <ensemble
+ foldertype_num="27"
+ xui_name="head"
+ icon_name="inv_folder_outfit_head.tga"
+ allowed="hair,eyes"
+ />
+ <ensemble
+ foldertype_num="28"
+ xui_name="gloves"
+ icon_name="inv_folder_outfit_gloves.tga"
+ allowed="gloves"
+ />
+ <ensemble
+ foldertype_num="29"
+ xui_name="jacket"
+ icon_name="inv_folder_outfit_jacket.tga"
+ allowed="jacket"
+ />
+ <ensemble
+ foldertype_num="30"
+ xui_name="pants"
+ icon_name="inv_folder_outfit_pants.tga"
+ allowed="pants,underpants"
+ />
+ <ensemble
+ foldertype_num="31"
+ xui_name="shape"
+ icon_name="inv_folder_outfit_shape.tga"
+ allowed="shape,skin,hair,eyes"
+ />
+ <ensemble
+ foldertype_num="32"
+ xui_name="shoes"
+ icon_name="inv_folder_outfit_shoes.tga"
+ allowed="shoes,socks"
+ />
+ <ensemble
+ foldertype_num="33"
+ xui_name="shirt"
+ icon_name="inv_folder_outfit_shirt.tga"
+ allowed="shirt,undershirt"
+ />
+ <ensemble
+ foldertype_num="34"
+ xui_name="skirt"
+ icon_name="inv_folder_outfit_skirt.tga"
+ allowed=""
+ />
+ <ensemble
+ foldertype_num="35"
+ xui_name="underpants"
+ icon_name="inv_folder_outfit_underpants.tga"
+ allowed="underpants"
+ />
+ <ensemble
+ foldertype_num="36"
+ xui_name="undershirt"
+ icon_name="inv_folder_outfit_undershirt.tga"
+ allowed="undershirt"
+ />
+</ensemble_defs>
diff --git a/indra/newview/app_settings/ignorable_dialogs.xml b/indra/newview/app_settings/ignorable_dialogs.xml
new file mode 100644
index 0000000000..e825f13e82
--- /dev/null
+++ b/indra/newview/app_settings/ignorable_dialogs.xml
@@ -0,0 +1,280 @@
+<?xml version="1.0" ?>
+<llsd>
+<map>
+ <key>FirstAppearance</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables FirstAppearance warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>FirstAttach</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables FirstAttach warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>FirstBalanceDecrease</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables FirstBalanceDecrease warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>FirstBalanceIncrease</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables FirstBalanceIncrease warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>FirstBuild</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables FirstBuild warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>FirstDebugMenus</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables FirstDebugMenus warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>FirstFlexible</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables FirstFlexible warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>FirstGoTo</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables FirstGoTo warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>FirstInventory</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables FirstInventory warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>FirstLeftClickNoHit</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables FirstLeftClickNoHit warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>FirstMap</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables FirstMap warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>FirstMedia</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables FirstMedia warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>FirstOverrideKeys</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables FirstOverrideKeys warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>FirstSandbox</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables FirstSandbox warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>FirstSculptedPrim</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables FirstSculptedPrim warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>FirstSit</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables FirstSit warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>FirstStreamingMedia</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables FirstStreamingMedia warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>FirstTeleport</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables FirstTeleport warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>FirstVoice</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables FirstVoice warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>AboutDirectX9</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables AboutDirectX9 warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>BrowserLaunch</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables BrowserLaunch warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>DeedObject</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables DeedObject warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>NewClassified</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables NewClassified warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>QuickTimeInstalled</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables QuickTimeInstalled warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>ReturnToOwner</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables ReturnToOwner warning dialog</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ </map>
+</llsd>
diff --git a/indra/newview/app_settings/keywords.ini b/indra/newview/app_settings/keywords.ini
index cd7b533e7a..0805e94b10 100644
--- a/indra/newview/app_settings/keywords.ini
+++ b/indra/newview/app_settings/keywords.ini
@@ -40,14 +40,14 @@ not_at_rot_target not_at_rot_target():Result of LLRotTarget library function cal
money money(key id, integer amount):Triggered when L$ is given to task
email email(string time, string address, string subj, string message, integer num_left):Triggered when task receives email
run_time_permissions run_time_permissions(integer perm):Triggered when an agent grants run time permissions to task
-attach attach(key id):Triggered when an agent attaches or detaches from agent
+attach attach(key id):Triggered when task attaches or detaches from agent
dataserver dataserver(key queryid, string data):Triggered when task receives asynchronous data
moving_start moving_start():Triggered when task begins moving
moving_end moving_end():Triggered when task stops moving
on_rez on_rez(integer start_param):Triggered when task is rezed in from inventory or another task
object_rez object_rez(key id):Triggered when task rezes in another task
link_message link_message(integer sender_num, integer num, string str, key id):Triggered when task receives a link message via LLMessageLinked library function call
-changed changed( integer change ):Triggered various event change the task:(test change with CHANGED_INVENTORY, CHANGED_COLOR, CHANGED_SHAPE, CHANGED_SCALE, CHANGED_TEXTURE, CHANGED_LINK, CHANGED_ALLOWED_DROP, CHANGED_OWNER, CHANGED_REGION, CHANGED_TELEPORT)
+changed changed( integer change ):Triggered various event change the task:(test change with CHANGED_INVENTORY, CHANGED_COLOR, CHANGED_SHAPE, CHANGED_SCALE, CHANGED_TEXTURE, CHANGED_LINK, CHANGED_ALLOWED_DROP, CHANGED_OWNER, CHANGED_REGION, CHANGED_TELEPORT, CHANGED_REGION_START, CHANGED_MEDIA)
remote_data remote_data(integer event_type, key channel, key message_id, string sender,integer idata, string sdata):Triggered by various XML-RPC calls (event_type will be one of REMOTE_DATA_CHANNEL, REMOTE_DATA_REQUEST, REMOTE_DATA_REPLY)
http_response http_response(key request_id, integer status, list metadata, string body):Triggered when task receives a response to one of its llHTTPRequests
http_request http_request(key id, string method, string body):Triggered when task receives an http request against a public URL
@@ -108,6 +108,7 @@ AGENT_TYPING Returned by llGetAgentInfo if the Agent is typing
AGENT_CROUCHING Returned by llGetAgentInfo if the Agent is crouching
AGENT_BUSY Returned by llGetAgentInfo if the Agent is busy
AGENT_ALWAYS_RUN Returned by llGetAgentInfo if the Agent has 'Always Run' enabled
+AGENT_AUTOPILOT Returned by llGetAgentInfo if the Agent is under autopilot control
PSYS_PART_FLAGS
PSYS_PART_START_COLOR
@@ -267,8 +268,8 @@ ATTACH_LHIP Passed to llAttachToAvatar to attach task to left hip
ATTACH_LULEG Passed to llAttachToAvatar to attach task to left upper leg
ATTACH_LLLEG Passed to llAttachToAvatar to attach task to left lower leg
ATTACH_BELLY Passed to llAttachToAvatar to attach task to belly
-ATTACH_RPEC Passed to llAttachToAvatar to attach task to right pectoral
-ATTACH_LPEC Passed to llAttachToAvatar to attach task to left pectoral
+ATTACH_LEFT_PEC Passed to llAttachToAvatar to attach task to left pectoral
+ATTACH_RIGHT_PEC Passed to llAttachToAvatar to attach task to right pectoral
LAND_LEVEL Passed to llModifyLand to level terrain
LAND_RAISE Passed to llModifyLand to raise terrain
@@ -319,6 +320,7 @@ CHANGED_OWNER Parameter of changed event handler used to indicate change to tas
CHANGED_REGION Parameter of changed event handler used to indicate the region has changed
CHANGED_TELEPORT Parameter of changed event handler used to indicate teleport has completed
CHANGED_REGION_START Parameter of changed event handler used to indicate the region has been restarted
+CHANGED_MEDIA Parameter of changed event handler used to indicate that media has changed on a face of the task
TYPE_INTEGER Indicates that the list entry is holding an integer
TYPE_FLOAT Indicates that the list entry is holding an float
@@ -457,6 +459,7 @@ PARCEL_FLAG_ALLOW_LANDMARK Used with llGetParcelFlags to find if a parcel allo
PARCEL_FLAG_ALLOW_TERRAFORM Used with llGetParcelFlags to find if a parcel allows anyone to terraform the land
PARCEL_FLAG_ALLOW_DAMAGE Used with llGetParcelFlags to find if a parcel allows damage
PARCEL_FLAG_ALLOW_CREATE_OBJECTS Used with llGetParcelFlags to find if a parcel allows anyone to create objects
+PARCEL_FLAG_ALLOW_CREATE_GROUP_OBJECTS Used with llGetParcelFlags to find if a parcel allows group members or objects to create objects
PARCEL_FLAG_USE_ACCESS_GROUP Used with llGetParcelFlags to find if a parcel limits access to a group
PARCEL_FLAG_USE_ACCESS_LIST Used with llGetParcelFlags to find if a parcel limits access to a list of residents
PARCEL_FLAG_USE_BAN_LIST Used with llGetParcelFlags to find if a parcel uses a ban list
@@ -507,17 +510,59 @@ CLICK_ACTION_PAY Used with llSetClickAction to set pay as the default act
CLICK_ACTION_OPEN Used with llSetClickAction to set open as the default action when object is clicked
CLICK_ACTION_PLAY Used with llSetClickAction to set play as the default action when object is clicked
CLICK_ACTION_OPEN_MEDIA Used with llSetClickAction to set open-media as the default action when object is clicked
+CLICK_ACTION_ZOOM Used with llSetClickAction to set zoom in as the default action when object is clicked
TOUCH_INVALID_TEXCOORD Value returned by llDetectedTouchUV() and llDetectedTouchST() when the touch position is not valid.
TOUCH_INVALID_VECTOR Value returned by llDetectedTouchPos(), llDetectedTouchNormal(), and llDetectedTouchBinormal() when the touch position is not valid.
TOUCH_INVALID_FACE Value returned by llDetectedTouchFace() when the touch position is not valid.
+PRIM_MEDIA_ALT_IMAGE_ENABLE Used with ll{Get,Set}PrimMediaParams to enable the default alt image for media
+PRIM_MEDIA_CONTROLS Used with ll{Get,Set}PrimMediaParams to determine the controls shown for media
+PRIM_MEDIA_CURRENT_URL Used with ll{Get,Set}PrimMediaParams to navigate/access the current URL
+PRIM_MEDIA_HOME_URL Used with ll{Get,Set}PrimMediaParams to access the home URL
+PRIM_MEDIA_AUTO_LOOP Used with ll{Get,Set}PrimMediaParams to determine if media should auto-loop (if applicable)
+PRIM_MEDIA_AUTO_PLAY Used with ll{Get,Set}PrimMediaParams to determine if media should start playing as soon as it is created
+PRIM_MEDIA_AUTO_SCALE Used with ll{Get,Set}PrimMediaParams to determine if media should scale to fit the face it is on
+PRIM_MEDIA_AUTO_ZOOM Used with ll{Get,Set}PrimMediaParams to determine if the user would zoom in when viewing media
+PRIM_MEDIA_FIRST_CLICK_INTERACT Used with ll{Get,Set}PrimMediaParams to determine whether the user interacts with media or not when she first clicks it (versus selection)
+PRIM_MEDIA_WIDTH_PIXELS Used with ll{Get,Set}PrimMediaParams to access the media's width in pixels
+PRIM_MEDIA_HEIGHT_PIXELS Used with ll{Get,Set}PrimMediaParams to access the media's height in pixels
+PRIM_MEDIA_WHITELIST_ENABLE Used with ll{Get,Set}PrimMediaParams to determine if the domain whitelist is enabled
+PRIM_MEDIA_WHITELIST Used with ll{Get,Set}PrimMediaParams to access the media's list of allowable URL prefixes to navigate to
+PRIM_MEDIA_PERMS_INTERACT Used with ll{Get,Set}PrimMediaParams to determine the permissions for who can interact with the media
+PRIM_MEDIA_PERMS_CONTROL Used with ll{Get,Set}PrimMediaParams to determine the permissions for who has controls
+PRIM_MEDIA_PARAM_MAX The value of the largest media param
+
+PRIM_MEDIA_CONTROLS_STANDARD Used with ll{Get,Set}PrimMediaParams, a PRIM_MEDIA_CONTROLS value meaning "standard controls"
+PRIM_MEDIA_CONTROLS_MINI Used with ll{Get,Set}PrimMediaParams, a PRIM_MEDIA_CONTROLS value meaning "mini controls"
+
+PRIM_MEDIA_PERM_NONE Used with ll{Get,Set}PrimMediaParams, a PRIM_MEDIA_PERMS_INTERACT or PRIM_MEDIA_PERMS_CONTROL bit, no permissions
+PRIM_MEDIA_PERM_OWNER Used with ll{Get,Set}PrimMediaParams, a PRIM_MEDIA_PERMS_INTERACT or PRIM_MEDIA_PERMS_CONTROL bit, owner permissions
+PRIM_MEDIA_PERM_GROUP Used with ll{Get,Set}PrimMediaParams, a PRIM_MEDIA_PERMS_INTERACT or PRIM_MEDIA_PERMS_CONTROL bit, group permissions
+PRIM_MEDIA_PERM_ANYONE Used with ll{Get,Set}PrimMediaParams, a PRIM_MEDIA_PERMS_INTERACT or PRIM_MEDIA_PERMS_CONTROL bit, anyone has permissions
+
+PRIM_MEDIA_MAX_URL_LENGTH Used with ll{Get,Set}PrimMediaParams, the maximum length of PRIM_MEDIA_CURRENT_URL or PRIM_MEDIA_HOME_URL
+PRIM_MEDIA_MAX_WHITELIST_SIZE Used with ll{Get,Set}PrimMediaParams, the maximum length, in bytes, of PRIM_MEDIA_WHITELIST
+PRIM_MEDIA_MAX_WHITELIST_COUNT Used with ll{Get,Set}PrimMediaParams, the maximum number of items allowed in PRIM_MEDIA_WHITELIST
+PRIM_MEDIA_MAX_WIDTH_PIXELS Used with ll{Get,Set}PrimMediaParams, the maximum width allowed in PRIM_MEDIA_WIDTH_PIXELS
+PRIM_MEDIA_MAX_HEIGHT_PIXELS Used with ll{Get,Set}PrimMediaParams, the maximum width allowed in PRIM_MEDIA_HEIGHT_PIXELS
+
+STATUS_OK Result of function call was success
+STATUS_MALFORMED_PARAMS Function was called with malformed params
+STATUS_TYPE_MISMATCH Argument(s) passed to function had a type mismatch
+STATUS_BOUNDS_ERROR Argument(s) passed to function had a bounds error
+STATUS_NOT_FOUND Object or other item was not found
+STATUS_NOT_SUPPORTED Feature not supported
+STATUS_INTERNAL_ERROR An internal error occurred
+STATUS_WHITELIST_FAILED URL failed to pass whitelist
+
# string constants
[word .1, .3, .5]
NULL_KEY Indicates an empty key
EOF Indicates the last line of a notecard was read
TEXTURE_BLANK UUID for the "Blank" texture
-TEXTURE_DEFAULT UUID for the "Default Media" texture
+TEXTURE_DEFAULT Alias for TEXTURE_PLYWOOD
+TEXTURE_MEDIA UUID for the "Default Media" texture
TEXTURE_PLYWOOD UUID for the default "Plywood" texture
TEXTURE_TRANSPARENT UUID for the "White - Transparent" texture
diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index a49ccb77b4..d7bb64ce8a 100644
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -40,7 +40,6 @@
</array>
<key>tags</key>
<array>
- <string>ShaderLoading</string>
</array>
</map>
</array>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 7ae92129dc..093e4f4894 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -8,7 +8,7 @@
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>F32</string>
+ <string>S32</string>
<key>Value</key>
<real>300.0</real>
</map>
@@ -23,37 +23,16 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>UserChatColor</key>
- <map>
- <key>Comment</key>
- <string>Color of your chat messages</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>AgentChatColor</key>
+ <key>AgentPause</key>
<map>
<key>Comment</key>
- <string>Color of chat messages from other residents</string>
+ <string>Ask the simulator to stop updating the agent while enabled</string>
<key>Persist</key>
- <integer>1</integer>
+ <integer>0</integer>
<key>Type</key>
- <string>Color4</string>
+ <string>Boolean</string>
<key>Value</key>
- <array>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- </array>
+ <integer>0</integer>
</map>
<key>AlertedUnsupportedHardware</key>
<map>
@@ -66,17 +45,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>AllowIdleAFK</key>
- <map>
- <key>Comment</key>
- <string>Automatically set AFK (away from keyboard) mode when idle</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
<key>AllowMultipleViewers</key>
<map>
<key>Comment</key>
@@ -154,7 +122,7 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>ArrowKeysMoveAvatar</key>
+ <key>ArrowKeysAlwaysMove</key>
<map>
<key>Comment</key>
<string>While cursor is in chat entry box, arrow keys still control your avatar</string>
@@ -163,7 +131,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>1</integer>
+ <integer>0</integer>
</map>
<key>AskedAboutCrashReports</key>
<map>
@@ -198,17 +166,6 @@
<key>Value</key>
<real>0.5</real>
</map>
- <key>AudioLevelDistance</key>
- <map>
- <key>Comment</key>
- <string>Scale factor for audio engine (multiple of world scale, 2.0 = audio falls off twice as fast)</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>F32</string>
- <key>Value</key>
- <real>1.0</real>
- </map>
<key>AudioLevelDoppler</key>
<map>
<key>Comment</key>
@@ -308,29 +265,51 @@
<key>Value</key>
<real>0.5</real>
</map>
- <key>AudioStreamingMusic</key>
+ <key>AudioLevelWind</key>
<map>
<key>Comment</key>
- <string>Enable streaming audio</string>
+ <string>Audio level of wind noise when standing still</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.5</real>
+ </map>
+ <key>AudioStreamingMedia</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable streaming</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
- <key>AudioStreamingVideo</key>
+ <key>AudioStreamingMusic</key>
<map>
<key>Comment</key>
- <string>Enable streaming video</string>
+ <string>Enable streaming audio</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
- <key>AutoAcceptNewInventory</key>
+ <key>AuditTexture</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable texture auditting.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>AutoAcceptNewInventory</key>
<map>
<key>Comment</key>
<string>Automatically accept new notecards/textures/landmarks</string>
@@ -418,6 +397,17 @@
<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>
@@ -594,22 +584,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>BackgroundChatColor</key>
- <map>
- <key>Comment</key>
- <string>Color of chat bubble background</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.0</real>
- <real>0.0</real>
- <real>0.0</real>
- <real>1.0</real>
- </array>
- </map>
<key>BackgroundYieldTime</key>
<map>
<key>Comment</key>
@@ -621,42 +595,10 @@
<key>Value</key>
<integer>40</integer>
</map>
- <key>BackwardBtnRect</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>45</integer>
- <integer>29</integer>
- <integer>66</integer>
- <integer>4</integer>
- </array>
- </map>
- <key>BasicHelpRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for help window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>404</integer>
- <integer>467</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>BeaconAlwaysOn</key>
+ <key>BottomPanelNew</key>
<map>
<key>Comment</key>
- <string>Beacons / highlighting always on</string>
+ <string>Enable the new bottom panel</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -873,17 +815,6 @@
<key>Value</key>
<real>1.0</real>
</map>
- <key>BuildBtnState</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>BuildFeathering</key>
<map>
<key>Comment</key>
@@ -972,17 +903,6 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>BulkChangeIncludeLandmarks</key>
- <map>
- <key>Comment</key>
- <string>Bulk permission changes affect landmarks</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
<key>BulkChangeIncludeNotecards</key>
<map>
<key>Comment</key>
@@ -1124,7 +1044,7 @@
<key>Type</key>
<string>S32</string>
<key>Value</key>
- <integer>10</integer>
+ <integer>4</integer>
</map>
<key>ButtonHeight</key>
<map>
@@ -1135,7 +1055,7 @@
<key>Type</key>
<string>S32</string>
<key>Value</key>
- <integer>20</integer>
+ <integer>23</integer>
</map>
<key>ButtonHeightSmall</key>
<map>
@@ -1146,20 +1066,31 @@
<key>Type</key>
<string>S32</string>
<key>Value</key>
- <integer>16</integer>
+ <integer>23</integer>
</map>
- <key>ButtonVPad</key>
+ <key>CacheLocation</key>
<map>
<key>Comment</key>
- <string>Default vertical spacing between buttons (pixels)</string>
+ <string>Controls the location of the local disk cache</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>S32</string>
+ <string>String</string>
<key>Value</key>
- <integer>1</integer>
+ <string />
</map>
- <key>CacheLocation</key>
+ <key>CacheLocationTopFolder</key>
+ <map>
+ <key>Comment</key>
+ <string>Controls the top folder location of the local disk cache</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string />
+ </map>
+ <key>CacheLocationTopFolder</key>
<map>
<key>Comment</key>
<string>Controls the location of the local disk cache</string>
@@ -1169,7 +1100,7 @@
<string>String</string>
<key>Value</key>
<string />
- </map>
+ </map>
<key>CacheSize</key>
<map>
<key>Comment</key>
@@ -1179,7 +1110,7 @@
<key>Type</key>
<string>U32</string>
<key>Value</key>
- <integer>500</integer>
+ <integer>512</integer>
</map>
<key>CacheValidateCounter</key>
<map>
@@ -1199,9 +1130,9 @@
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Boolean</string>
+ <string>S32</string>
<key>Value</key>
- <integer>1</integer>
+ <integer>5</integer>
</map>
<key>CameraAngle</key>
<map>
@@ -1240,10 +1171,10 @@
<real>6.0</real>
</array>
</map>
- <key>CameraOffsetDefault</key>
+ <key>CameraOffsetRearView</key>
<map>
<key>Comment</key>
- <string>Default camera offset from avatar</string>
+ <string>Initial camera offset from avatar in Rear View</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -1255,6 +1186,36 @@
<real>0.75</real>
</array>
</map>
+ <key>CameraOffsetFrontView</key>
+ <map>
+ <key>Comment</key>
+ <string>Initial camera offset from avatar in Front View</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Vector3</string>
+ <key>Value</key>
+ <array>
+ <real>2.2</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ </array>
+ </map>
+ <key>CameraOffsetGroupView</key>
+ <map>
+ <key>Comment</key>
+ <string>Initial camera offset from avatar in Group View</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Vector3</string>
+ <key>Value</key>
+ <array>
+ <real>-1.0</real>
+ <real>0.7</real>
+ <real>0.5</real>
+ </array>
+ </map>
<key>CameraOffsetScale</key>
<map>
<key>Comment</key>
@@ -1292,6 +1253,17 @@
<key>Value</key>
<real>1.0</real>
</map>
+ <key>CameraPreset</key>
+ <map>
+ <key>Comment</key>
+ <string>Preset camera position - view (0 - rear, 1 - front, 2 - group)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>ChatBarStealsFocus</key>
<map>
<key>Comment</key>
@@ -1391,21 +1363,16 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>ChatterboxRect</key>
+ <key>ChatWindow</key>
<map>
<key>Comment</key>
- <string>Rectangle for chatterbox window</string>
+ <string>Show chat in multiple windows(by default) or in one multi-tabbed window(requires restart)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>S32</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>400</integer>
- <integer>350</integer>
- <integer>0</integer>
- </array>
+ <integer>0</integer>
</map>
<key>CheesyBeacon</key>
<map>
@@ -1421,7 +1388,7 @@
<key>ClientSettingsFile</key>
<map>
<key>Comment</key>
- <string>Persisted client settings file name (per install).</string>
+ <string>Client settings file name (per install).</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
@@ -1497,545 +1464,17 @@
<string />
</array>
</map>
- <key>ColorPaletteEntry01</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.0</real>
- <real>0.0</real>
- <real>0.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry02</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.5</real>
- <real>0.5</real>
- <real>0.5</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry03</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.5</real>
- <real>0.0</real>
- <real>0.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry04</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.5</real>
- <real>0.5</real>
- <real>0.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry05</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.0</real>
- <real>0.5</real>
- <real>0.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry06</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.0</real>
- <real>0.5</real>
- <real>0.5</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry07</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.0</real>
- <real>0.0</real>
- <real>0.5</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry08</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.5</real>
- <real>0.0</real>
- <real>0.5</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry09</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.5</real>
- <real>0.5</real>
- <real>0.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry10</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.0</real>
- <real>0.25</real>
- <real>0.25</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry11</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.0</real>
- <real>0.5</real>
- <real>1.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry12</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.0</real>
- <real>0.25</real>
- <real>0.5</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry13</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.5</real>
- <real>0.0</real>
- <real>1.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry14</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.5</real>
- <real>0.25</real>
- <real>0.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry15</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry16</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry17</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry18</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.75</real>
- <real>0.75</real>
- <real>0.75</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry19</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>1.0</real>
- <real>0.0</real>
- <real>0.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry20</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>1.0</real>
- <real>1.0</real>
- <real>0.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry21</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.0</real>
- <real>1.0</real>
- <real>0.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry22</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.0</real>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry23</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.0</real>
- <real>0.0</real>
- <real>1.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry24</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>1.0</real>
- <real>0.0</real>
- <real>1.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry25</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>1.0</real>
- <real>1.0</real>
- <real>0.5</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry26</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.0</real>
- <real>1.0</real>
- <real>0.5</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry27</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.5</real>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry28</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.5</real>
- <real>0.5</real>
- <real>1.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry29</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>1.0</real>
- <real>0.0</real>
- <real>0.5</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry30</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>1.0</real>
- <real>0.5</real>
- <real>0.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry31</key>
+ <key>CompressSnapshotsToDisk</key>
<map>
<key>Comment</key>
- <string>Color picker palette entry</string>
+ <string>Compress snapshots saved to disk (Using JPEG 2000)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColorPaletteEntry32</key>
- <map>
- <key>Comment</key>
- <string>Color picker palette entry</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ColumnHeaderDropDownDelay</key>
- <map>
- <key>Comment</key>
- <string>Time in seconds of mouse click before column header shows sort options list</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>F32</string>
- <key>Value</key>
- <real>0.300000011921</real>
- </map>
- <key>CompileOutputRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for script Recompile Everything output window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
+ <string>Boolean</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>400</integer>
- <integer>300</integer>
- <integer>0</integer>
- </array>
- </map>
+ <integer>0</integer>
+ </map>
<key>ConnectAsGod</key>
<map>
<key>Comment</key>
@@ -2171,7 +1610,7 @@
<key>Cursor3D</key>
<map>
<key>Comment</key>
- <string>Tread Joystick values as absolute positions (not deltas).</string>
+ <string>Treat Joystick values as absolute positions (not deltas).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -2223,6 +1662,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>DebugPluginDisableTimeout</key>
+ <map>
+ <key>Comment</key>
+ <string>Disable the code which watches for plugins that are crashed or hung</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>DebugShowColor</key>
<map>
<key>Comment</key>
@@ -2267,7 +1717,18 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>DebugStatModeFPS</key>
+ <key>DebugShowXUINames</key>
+ <map>
+ <key>Comment</key>
+ <string>Show tooltips with XUI path to widget</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>DebugStatModeFPS</key>
<map>
<key>Comment</key>
<string>Mode of stat in Statistics floater</string>
@@ -2894,6 +2355,17 @@
<key>Value</key>
<string>89556747-24cb-43ed-920b-47caed15465f</string>
</map>
+ <key>DefaultUploadCost</key>
+ <map>
+ <key>Comment</key>
+ <string>Default sound/image/file upload cost(in case economy data is not available).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>10</integer>
+ </map>
<key>DisableCameraConstraints</key>
<map>
<key>Comment</key>
@@ -3136,32 +2608,27 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>EffectColor</key>
+ <key>EnableRippleWater</key>
<map>
<key>Comment</key>
- <string>Particle effects color</string>
+ <string>Whether to use ripple water shader or not</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Color4</string>
+ <string>Boolean</string>
<key>Value</key>
- <array>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- </array>
+ <integer>1</integer>
</map>
- <key>EnableRippleWater</key>
+ <key>EnableTextureAtlas</key>
<map>
<key>Comment</key>
- <string>Whether to use ripple water shader or not</string>
+ <string>Whether to use texture atlas or not</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>1</integer>
+ <integer>0</integer>
</map>
<key>EnableVoiceChat</key>
<map>
@@ -3339,17 +2806,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>FirstPersonBtnState</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>FirstRunThisInstall</key>
<map>
<key>Comment</key>
@@ -3361,48 +2817,38 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>FixedWeather</key>
+ <key>FirstSelectedDisabledPopups</key>
<map>
<key>Comment</key>
- <string>Weather effects do not change over time</string>
+ <string>Return false if there is not disabled popup selected in the list of floater preferences popups</string>
<key>Persist</key>
- <integer>1</integer>
+ <integer>0</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
- </map>
- <key>FloaterAboutRect</key>
+ </map>
+ <key>FirstSelectedEnabledPopups</key>
<map>
<key>Comment</key>
- <string>Rectangle for About window</string>
+ <string>Return false if there is not enable popup selected in the list of floater preferences popups</string>
<key>Persist</key>
- <integer>1</integer>
+ <integer>0</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>Boolean</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>440</integer>
- <integer>470</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterActiveSpeakersRect</key>
+ <integer>0</integer>
+ </map>
+ <key>FixedWeather</key>
<map>
<key>Comment</key>
- <string>Rectangle for active speakers window</string>
+ <string>Weather effects do not change over time</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>Boolean</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>300</integer>
- <integer>250</integer>
- <integer>0</integer>
- </array>
+ <integer>0</integer>
</map>
<key>FloaterActiveSpeakersSortAscending</key>
<map>
@@ -3426,618 +2872,95 @@
<key>Value</key>
<string>speaking_status</string>
</map>
- <key>FloaterAdvancedSkyRect</key>
+ <key>FloaterMapNorth</key>
<map>
<key>Comment</key>
- <string>Rectangle for Advanced Sky Editor</string>
+ <string>Floater Map North Label</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>220</integer>
- <integer>700</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterAdvancedWaterRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for Advanced Water Editor</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>240</integer>
- <integer>700</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterAudioVolumeRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for Audio Volume window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>440</integer>
- <integer>470</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterBeaconsRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for beacon and highlight controls</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>200</integer>
- <integer>250</integer>
- <integer>250</integer>
- <integer>200</integer>
- </array>
- </map>
- <key>FloaterBuildOptionsRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for build options window.</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>0</integer>
- <integer>0</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterBumpRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for Bumps/Hits window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>180</integer>
- <integer>400</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterBuyContentsRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for Buy Contents window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>250</integer>
- <integer>300</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterBuyRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for buy window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>250</integer>
- <integer>300</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterCameraRect3</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for camera control window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>64</integer>
- <integer>176</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterChatRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for chat history</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>172</integer>
- <integer>500</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterClothingRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for clothing window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>480</integer>
- <integer>320</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterContactsRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for chat history</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>390</integer>
- <integer>395</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterCustomizeAppearanceRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for avatar customization window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>540</integer>
- <integer>494</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterDayCycleRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for Day Cycle Editor</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>646</integer>
- <integer>275</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterEnvRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for Environment Editor</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>150</integer>
- <integer>600</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterFindRect2</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for Find window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>570</integer>
- <integer>780</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterFriendsRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for friends window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>400</integer>
- <integer>250</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterGestureRect2</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for gestures window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>465</integer>
- <integer>350</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterHUDRect2</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for HUD Floater window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
-<!-- NOTE: Height and width must match values in settings.xml for
- FloaterHUDRect because this floater is resized to those values
- in LLViewerWindow initialization. JC -->
- <array>
- <integer>0</integer>
- <integer>292</integer>
- <integer>362</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterHtmlRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for HTML window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>100</integer>
- <integer>460</integer>
- <integer>370</integer>
- <integer>100</integer>
- </array>
- </map>
- <key>FloaterIMRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for IM window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>160</integer>
- <integer>500</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterInspectRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for Object Inspect window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>400</integer>
- <integer>400</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterInventoryRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for inventory window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>400</integer>
- <integer>300</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterJoystickRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for joystick controls window.</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
+ <string>String</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>0</integer>
- <integer>0</integer>
- <integer>0</integer>
- </array>
+ <string>N</string>
</map>
- <key>FloaterLagMeter</key>
+ <key>FloaterMapNorthEast</key>
<map>
<key>Comment</key>
- <string>Rectangle for lag meter</string>
+ <string>Floater Map North-East Label</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>String</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>142</integer>
- <integer>350</integer>
- <integer>0</integer>
- </array>
+ <string>NE</string>
</map>
- <key>FloaterLandRect5</key>
+ <key>FloaterMapNorthWest</key>
<map>
<key>Comment</key>
- <string>Rectangle for About Land window</string>
+ <string>Floater Map North-West Label</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>String</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>370</integer>
- <integer>460</integer>
- <integer>0</integer>
- </array>
+ <string>NW</string>
</map>
- <key>FloaterLandmarkRect</key>
+ <key>FloaterMapEast</key>
<map>
<key>Comment</key>
- <string>Rectangle for landmark picker</string>
+ <string>Floater Map East Label</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>String</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>290</integer>
- <integer>310</integer>
- <integer>0</integer>
- </array>
+ <string>E</string>
</map>
- <key>FloaterMediaRect</key>
+ <key>FloaterMapWest</key>
<map>
<key>Comment</key>
- <string>Rectangle for media browser window</string>
+ <string>Floater Map West Label</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>String</string>
<key>Value</key>
- <array>
- <integer>16</integer>
- <integer>650</integer>
- <integer>600</integer>
- <integer>128</integer>
- </array>
+ <string>W</string>
</map>
- <key>FloaterMiniMapRect</key>
+ <key>FloaterMapSouth</key>
<map>
<key>Comment</key>
- <string>Rectangle for world map</string>
+ <string>Floater Map South Label</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>String</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>225</integer>
- <integer>200</integer>
- <integer>0</integer>
- </array>
+ <string>S</string>
</map>
- <key>FloaterMoveRect2</key>
+ <key>FloaterMapSouthEast</key>
<map>
<key>Comment</key>
- <string>Rectangle for avatar control window</string>
+ <string>Floater Map South-East Label</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>String</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>58</integer>
- <integer>135</integer>
- <integer>0</integer>
- </array>
+ <string>SE</string>
</map>
- <key>FloaterMuteRect3</key>
+ <key>FloaterMapSouthWest</key>
<map>
<key>Comment</key>
- <string>Rectangle for mute window</string>
+ <string>Floater Map South-West Label</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>String</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>300</integer>
- <integer>300</integer>
- <integer>0</integer>
- </array>
+ <string>SW</string>
</map>
- <key>FloaterObjectIMInfo</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for floater object im info windows</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>300</integer>
- <integer>300</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterOpenObjectRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for Open Object window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>350</integer>
- <integer>300</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterPayRectB</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for pay window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>150</integer>
- <integer>400</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterPermPrefsRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for initial permissions preferences</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>200</integer>
- <integer>250</integer>
- <integer>250</integer>
- <integer>200</integer>
- </array>
- </map>
- <key>FloaterRegionInfo</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for region info window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>512</integer>
- <integer>480</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterScriptDebugRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for Script Error/Debug window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>130</integer>
- <integer>450</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FloaterSnapshotRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for snapshot window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>200</integer>
- <integer>200</integer>
- <integer>400</integer>
- </array>
- </map>
<key>FloaterStatisticsRect</key>
<map>
<key>Comment</key>
@@ -4054,44 +2977,6 @@
<integer>0</integer>
</array>
</map>
- <key>FloaterViewBottom</key>
- <map>
- <key>Comment</key>
- <string>[DO NOT MODIFY] Controls layout of floating windows within SL window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>S32</string>
- <key>Value</key>
- <integer>-1</integer>
- </map>
- <key>FloaterWorldMapRect2</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for world map window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>0</integer>
- <integer>0</integer>
- <integer>0</integer>
- </array>
- </map>
- <key>FlyBtnState</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>FlycamAbsolute</key>
<map>
<key>Comment</key>
@@ -4290,14 +3175,14 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>FocusOffsetDefault</key>
+ <key>FocusOffsetRearView</key>
<map>
<key>Comment</key>
- <string>Default focus point offset relative to avatar (x-axis is forward)</string>
+ <string>Initial focus point offset relative to avatar for the camera preset Rear View (x-axis is forward)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Vector3</string>
+ <string>Vector3D</string>
<key>Value</key>
<array>
<real>1.0</real>
@@ -4305,6 +3190,36 @@
<real>1.0</real>
</array>
</map>
+ <key>FocusOffsetFrontView</key>
+ <map>
+ <key>Comment</key>
+ <string>Initial focus point offset relative to avatar for the camera preset Front View</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Vector3D</string>
+ <key>Value</key>
+ <array>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ </array>
+ </map>
+ <key>FocusOffsetGroupView</key>
+ <map>
+ <key>Comment</key>
+ <string>Initial focus point offset relative to avatar for the camera preset Group View</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Vector3D</string>
+ <key>Value</key>
+ <array>
+ <real>1.5</real>
+ <real>0.7</real>
+ <real>1.0</real>
+ </array>
+ </map>
<key>FocusPosOnLogout</key>
<map>
<key>Comment</key>
@@ -4496,22 +3411,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>ForwardBtnRect</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>45</integer>
- <integer>54</integer>
- <integer>66</integer>
- <integer>29</integer>
- </array>
- </map>
<key>FreezeTime</key>
<map>
<key>Comment</key>
@@ -4523,17 +3422,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>FullScreen</key>
- <map>
- <key>Comment</key>
- <string>Run SL in fullscreen mode</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>FullScreenAspectRatio</key>
<map>
<key>Comment</key>
@@ -4675,45 +3563,51 @@
<key>Type</key>
<string>S32</string>
<key>Value</key>
- <integer>400</integer>
+ <integer>305</integer>
</map>
- <key>HTMLLinkColor</key>
+ <key>HelpUseLocal</key>
<map>
<key>Comment</key>
- <string>Color of hyperlinks</string>
+ <string>If set, always use this for help: skins/default/html/[LANGUAGE]/help-offline/index.html</string>
<key>Persist</key>
- <integer>1</integer>
+ <integer>0</integer>
<key>Type</key>
- <string>Color4</string>
+ <string>Boolean</string>
<key>Value</key>
- <array>
- <real>0.600000023842</real>
- <real>0.600000023842</real>
- <real>1.0</real>
- <real>1.0</real>
- </array>
+ <integer>0</integer>
</map>
- <key>HelpHomeURL</key>
+ <key>HelpURLFormat</key>
<map>
<key>Comment</key>
- <string>URL of initial help page</string>
+ <string>URL pattern for help page; arguments will be encoded; see llviewerhelp.cpp:buildHelpURL for arguments</string>
<key>Persist</key>
- <integer>1</integer>
+ <integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>help/index.html</string>
+ <string>http://viewer-help.secondlife.com/[LANGUAGE]/[CHANNEL]/[VERSION]/[TOPIC][DEBUG_MODE]</string>
</map>
- <key>HelpLastVisitedURL</key>
+ <key>HomeSidePanelURL</key>
<map>
<key>Comment</key>
- <string>URL of last help page, will be shown next time help is accessed</string>
+ <string>URL for the web page to display in the Home side panel</string>
<key>Persist</key>
- <integer>1</integer>
+ <integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>help/index.html</string>
+ <string>http://lecs.viewer-sidebar.secondlife.com.s3.amazonaws.com/sidebar.html?p=[AUTH_TOKEN]&amp;lang=[LANGUAGE]&amp;channel=[CHANNEL]&amp;version=[VERSION]&amp;major=[VERSION_MAJOR]&amp;minor=[VERSION_MINOR]</string>
+ </map>
+ <key>SearchURL</key>
+ <map>
+ <key>Comment</key>
+ <string>URL for Search website, displayed in the Find floater</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>http://search.secondlife.com/viewer/[CATEGORY]?q=[QUERY]&amp;p=[AUTH_TOKEN]&amp;r=[MATURITY]&amp;lang=[LANGUAGE]&amp;g=[GODLIKE]&amp;sid=[SESSION_ID]&amp;rid=[REGION_ID]&amp;pid=[PARCEL_ID]</string>
</map>
<key>HighResSnapshot</key>
<map>
@@ -4726,22 +3620,17 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>HtmlFindRect</key>
+ <key>HideSelectedObjects</key>
<map>
<key>Comment</key>
- <string>Rectangle for HTML find window</string>
+ <string>Hide Selected Objects</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>Boolean</string>
<key>Value</key>
- <array>
- <integer>16</integer>
- <integer>650</integer>
- <integer>600</integer>
- <integer>128</integer>
- </array>
- </map>
+ <integer>0</integer>
+ </map>
<key>HtmlHelpLastPage</key>
<map>
<key>Comment</key>
@@ -4753,58 +3642,21 @@
<key>Value</key>
<string />
</map>
- <key>HtmlHelpRect</key>
+ <key>IMShowTimestamps</key>
<map>
<key>Comment</key>
- <string>Rectangle for HTML help window</string>
+ <string>Show timestamps in IM</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>Boolean</string>
<key>Value</key>
- <array>
- <integer>16</integer>
- <integer>650</integer>
- <integer>600</integer>
- <integer>128</integer>
- </array>
- </map>
- <key>HtmlReleaseMessage</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for HTML Release Message Floater window</string>
- <key>Persist</key>
<integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>46</integer>
- <integer>520</integer>
- <integer>400</integer>
- <integer>128</integer>
- </array>
</map>
- <key>IMChatColor</key>
+ <key>IMShowControlPanel</key>
<map>
<key>Comment</key>
- <string>Color of instant messages from other residents</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- </array>
- </map>
- <key>IMInChatConsole</key>
- <map>
- <key>Comment</key>
- <string>Copy IM into background chat console</string>
+ <string>Show IM Control Panel</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -4812,17 +3664,17 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>IMShowTimestamps</key>
+ <key>IgnoreAllNotifications</key>
<map>
<key>Comment</key>
- <string>Show timestamps in IM</string>
+ <string>Ignore all notifications so we never need user input on them.</string>
<key>Persist</key>
- <integer>1</integer>
+ <integer>0</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>1</integer>
- </map>
+ <integer>0</integer>
+ </map>
<key>IgnorePixelDepth</key>
<map>
<key>Comment</key>
@@ -4856,6 +3708,28 @@
<key>Value</key>
<real>0.0</real>
</map>
+ <key>InspectorFadeTime</key>
+ <map>
+ <key>Comment</key>
+ <string>Fade out timing for inspectors</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.5</real>
+ </map>
+ <key>InspectorShowTime</key>
+ <map>
+ <key>Comment</key>
+ <string>Stay timing for inspectors</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>3.0</real>
+ </map>
<key>InstallLanguage</key>
<map>
<key>Comment</key>
@@ -5032,6 +3906,17 @@
<key>Value</key>
<string />
</map>
+ <key>JoystickMouselookYaw</key>
+ <map>
+ <key>Comment</key>
+ <string>Pass joystick yaw to scripts in Mouselook.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>JoystickRunThreshold</key>
<map>
<key>Comment</key>
@@ -5087,22 +3972,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>LSLHelpRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for LSL help window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>400</integer>
- <integer>400</integer>
- <integer>0</integer>
- </array>
- </map>
<key>LSLHelpURL</key>
<map>
<key>Comment</key>
@@ -5191,6 +4060,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>LastMediaSettingsTab</key>
+ <map>
+ <key>Comment</key>
+ <string>Last selected tab in media settings window</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>LastRunVersion</key>
<map>
<key>Comment</key>
@@ -5344,7 +4224,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
<key>LipSyncOoh</key>
<map>
@@ -5390,7 +4270,29 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>LogMessages</key>
+ <key>LoginSRVTimeout</key>
+ <map>
+ <key>Comment</key>
+ <string>Duration in seconds of the login SRV request timeout</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>10.0</real>
+ </map>
+ <key>LoginSRVPump</key>
+ <map>
+ <key>Comment</key>
+ <string>Name of the message pump that handles SRV request</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>LLAres</string>
+ </map>
+ <key>LogMessages</key>
<map>
<key>Comment</key>
<string>Log network traffic</string>
@@ -5412,16 +4314,16 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>LoginLastLocation</key>
+ <key>LoginLocation</key>
<map>
<key>Comment</key>
<string>Login at same location you last logged out</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Boolean</string>
+ <string>String</string>
<key>Value</key>
- <integer>1</integer>
+ <string>last</string>
</map>
<key>LoginPage</key>
<map>
@@ -5621,7 +4523,51 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>MemoryLogFrequency</key>
+ <key>MediaControlFadeTime</key>
+ <map>
+ <key>Comment</key>
+ <string>Amount of time (in seconds) that the media control fades</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.5</real>
+ </map>
+ <key>MediaControlTimeout</key>
+ <map>
+ <key>Comment</key>
+ <string>Amount of time (in seconds) for media controls to fade with no mouse activity</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>3.0</real>
+ </map>
+ <key>MediaOnAPrimUI</key>
+ <map>
+ <key>Comment</key>
+ <string>Whether or not to show the "link sharing" UI</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>MediaPerformanceManagerDebug</key>
+ <map>
+ <key>Comment</key>
+ <string>Whether to show debug data for the media performance manager in the nearby media list.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>MemoryLogFrequency</key>
<map>
<key>Comment</key>
<string>Seconds between display of Memory in log (0 for never)</string>
@@ -5632,6 +4578,17 @@
<key>Value</key>
<real>600.0</real>
</map>
+ <key>MemProfiling</key>
+ <map>
+ <key>Comment</key>
+ <string>You want to use tcmalloc's memory profiling options.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>MenuAccessKeyTime</key>
<map>
<key>Comment</key>
@@ -5676,6 +4633,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>MiniMapPrimMaxRadius</key>
+ <map>
+ <key>Comment</key>
+ <string>Radius of the largest prim to show on the MiniMap. Increasing beyond 256 may cause client lag.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>256.0</real>
+ </map>
<key>MiniMapRotate</key>
<map>
<key>Comment</key>
@@ -5690,7 +4658,7 @@
<key>MiniMapScale</key>
<map>
<key>Comment</key>
- <string>Miniature world map zoom levle (pixels per region)</string>
+ <string>Miniature world map zoom level (pixels per region)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -5731,49 +4699,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>MouselookBtnState</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
- <key>MoveDownBtnRect</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>91</integer>
- <integer>29</integer>
- <integer>116</integer>
- <integer>4</integer>
- </array>
- </map>
- <key>MoveUpBtnRect</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>91</integer>
- <integer>54</integer>
- <integer>116</integer>
- <integer>29</integer>
- </array>
- </map>
<key>MuteAmbient</key>
<map>
<key>Comment</key>
@@ -5860,8 +4785,19 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>1</integer>
+ <integer>0</integer>
</map>
+ <key>MyOutfitsAutofill</key>
+ <map>
+ <key>Comment</key>
+ <string>Always autofill My Outfits from library when empty (else happens just once).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>NearMeRange</key>
<map>
<key>Comment</key>
@@ -5871,7 +4807,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
- <integer>20</integer>
+ <integer>130</integer>
</map>
<key>NextOwnerCopy</key>
<map>
@@ -5917,6 +4853,17 @@
<key>Value</key>
<string />
</map>
+ <key>NewCacheLocationTopFolder</key>
+ <map>
+ <key>Comment</key>
+ <string>Change the top folder location of the local disk cache to this</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string />
+ </map>
<key>NextLoginLocation</key>
<map>
<key>Comment</key>
@@ -5983,43 +4930,160 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>NotecardEditorRect</key>
+ <key>NotifyBoxHeight</key>
<map>
<key>Comment</key>
- <string>Rectangle for notecard editor</string>
+ <string>Height of notification messages</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>S32</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>400</integer>
- <integer>400</integer>
- <integer>0</integer>
- </array>
+ <integer>200</integer>
</map>
- <key>NotifyBoxHeight</key>
+ <key>NotifyBoxWidth</key>
<map>
<key>Comment</key>
- <string>Height of notification messages</string>
+ <string>Width of notification messages</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
- <integer>200</integer>
+ <integer>305</integer>
</map>
- <key>NotifyBoxWidth</key>
+ <key>NotificationToastLifeTime</key>
<map>
<key>Comment</key>
- <string>Width of notification messages</string>
+ <string>Number of seconds while a notification toast exists</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>5</integer>
+ </map>
+ <key>NotificationTipToastLifeTime</key>
+ <map>
+ <key>Comment</key>
+ <string>Number of seconds while a notification tip toast exist</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
- <integer>350</integer>
+ <integer>10</integer>
+ </map>
+ <key>ToastFadingTime</key>
+ <map>
+ <key>Comment</key>
+ <string>Number of seconds while a toast is fading </string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>NearbyToastFadingTime</key>
+ <map>
+ <key>Comment</key>
+ <string>Number of seconds while a nearby chat toast is fading </string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>3</integer>
+ </map>
+ <key>NearbyToastLifeTime</key>
+ <map>
+ <key>Comment</key>
+ <string>Number of seconds while a nearby chat toast exists</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>23</integer>
+ </map>
+ <key>StartUpToastLifeTime</key>
+ <map>
+ <key>Comment</key>
+ <string>Number of seconds while a StartUp toast exist</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>5</integer>
+ </map>
+ <key>ToastGap</key>
+ <map>
+ <key>Comment</key>
+ <string>Gap between toasts on a screen</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>5</integer>
+ </map>
+ <key>ToastButtonWidth</key>
+ <map>
+ <key>Comment</key>
+ <string>Default width of buttons in the toast.
+ Note if required width will be less then this one, a button will be reshaped to default size , otherwise to required</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>90</integer>
+ </map>
+ <key>ChannelBottomPanelMargin</key>
+ <map>
+ <key>Comment</key>
+ <string>Space from a lower toast to the Bottom Tray</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>35</integer>
+ </map>
+ <key>NotificationChannelRightMargin</key>
+ <map>
+ <key>Comment</key>
+ <string>Space between toasts and a right border of an area where they can appear</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>5</integer>
+ </map>
+ <key>NotificationChannelHeightRatio</key>
+ <map>
+ <key>Comment</key>
+ <string>Notification channel and World View ratio(0.0 - always show 1 notification, 1.0 - max ratio).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.5</real>
+ </map>
+ <key>OverflowToastHeight</key>
+ <map>
+ <key>Comment</key>
+ <string>Height of an overflow toast</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>72</integer>
</map>
<key>NotifyMoneyChange</key>
<map>
@@ -6065,22 +5129,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>ObjectChatColor</key>
- <map>
- <key>Comment</key>
- <string>Color of chat messages from objects</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.699999988079</real>
- <real>0.899999976158</real>
- <real>0.699999988079</real>
- <real>1</real>
- </array>
- </map>
<key>OpenDebugStatAdvanced</key>
<map>
<key>Comment</key>
@@ -6183,29 +5231,24 @@
<key>OutBandwidth</key>
<map>
<key>Comment</key>
- <string>Outgoing bandwidth throttle (bps)</string>
+ <string>Expand render stats display</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>F32</string>
+ <string>Boolean</string>
<key>Value</key>
- <real>0.0</real>
+ <integer>1</integer>
</map>
- <key>OverdrivenColor</key>
+ <key>OutBandwidth</key>
<map>
<key>Comment</key>
- <string>Color of various indicators when resident is speaking too loud.</string>
+ <string>Outgoing bandwidth throttle (bps)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Color4</string>
+ <string>F32</string>
<key>Value</key>
- <array>
- <real>1.0</real>
- <real>0.0</real>
- <real>0.0</real>
- <real>1.0</real>
- </array>
+ <real>0.0</real>
</map>
<key>OverlayTitle</key>
<map>
@@ -6284,22 +5327,6 @@
<key>Value</key>
<integer>344</integer>
</map>
- <key>PermissionsManagerRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for permissions manager window</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>85</integer>
- <integer>300</integer>
- <integer>0</integer>
- </array>
- </map>
<key>PickerContextOpacity</key>
<map>
<key>Comment</key>
@@ -6344,17 +5371,6 @@
<key>Value</key>
<real>2.5</real>
</map>
- <key>PinTalkViewOpen</key>
- <map>
- <key>Comment</key>
- <string>Stay in IM after hitting return</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
<key>PingInterpolate</key>
<map>
<key>Comment</key>
@@ -6388,214 +5404,183 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>PrecachingDelay</key>
+ <key>PluginAttachDebuggerToPlugins</key>
<map>
<key>Comment</key>
- <string>Delay when logging in to load world before showing it (seconds)</string>
+ <string>If true, attach a debugger session to each plugin process as it's launched.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>F32</string>
+ <string>Boolean</string>
<key>Value</key>
- <real>6.0</real>
+ <integer>0</integer>
</map>
- <key>PreferredMaturity</key>
+ <key>PluginInstancesCPULimit</key>
<map>
<key>Comment</key>
- <string>Setting for the user's preferred maturity level.</string>
+ <string>Amount of total plugin CPU usage before inworld plugins start getting turned down to "slideshow" priority. Set to 0 to disable this check.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>U32</string>
+ <string>F32</string>
<key>Value</key>
- <integer>13</integer>
+ <real>1.0</real>
</map>
- <key>PreviewAnimRect</key>
+
+ <key>PlainTextChatHistory</key>
<map>
<key>Comment</key>
- <string>Rectangle for animation preview window</string>
+ <string>Enable/Disable plain text chat history style</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>Boolean</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>85</integer>
- <integer>300</integer>
- <integer>0</integer>
- </array>
+ <integer>0</integer>
</map>
- <key>PreviewClassifiedRect</key>
+
+ <key>PluginInstancesLow</key>
<map>
<key>Comment</key>
- <string>Rectangle for URL preview window</string>
+ <string>Limit on the number of inworld media plugins that will run at "low" priority</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>U32</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>530</integer>
- <integer>420</integer>
- <integer>0</integer>
- </array>
+ <integer>4</integer>
</map>
- <key>PreviewEventRect</key>
+ <key>PluginInstancesNormal</key>
<map>
<key>Comment</key>
- <string>Rectangle for Event preview window</string>
+ <string>Limit on the number of inworld media plugins that will run at "normal" or higher priority</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>U32</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>530</integer>
- <integer>420</integer>
- <integer>0</integer>
- </array>
+ <integer>2</integer>
</map>
- <key>PreviewLandmarkRect</key>
+ <key>PluginInstancesTotal</key>
<map>
<key>Comment</key>
- <string>Rectangle for landmark preview window</string>
+ <string>Hard limit on the number of plugins that will be instantiated at once for inworld media</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>U32</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>90</integer>
- <integer>300</integer>
- <integer>0</integer>
- </array>
+ <integer>8</integer>
</map>
- <key>PreviewObjectRect</key>
+ <key>PrecachingDelay</key>
<map>
<key>Comment</key>
- <string>Rectangle for object preview window</string>
+ <string>Delay when logging in to load world before showing it (seconds)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>F32</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>85</integer>
- <integer>300</integer>
- <integer>0</integer>
- </array>
+ <real>6.0</real>
</map>
- <key>PreviewScriptRect</key>
+ <key>PreferredMaturity</key>
<map>
<key>Comment</key>
- <string>Rectangle for script preview window</string>
+ <string>Setting for the user's preferred maturity level.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>U32</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>586</integer>
- <integer>576</integer>
- <integer>0</integer>
- </array>
+ <integer>13</integer>
+ </map>
+ <key>PrimMediaMasterEnabled</key>
+ <map>
+ <key>Comment</key>
+ <string>Whether or not Media on a Prim is enabled.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>PrimMediaControlsUseHoverControlSet</key>
+ <map>
+ <key>Comment</key>
+ <string>Whether or not hovering over prim media uses minimal "hover" controls or the authored control set.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
</map>
- <key>PreviewSoundRect</key>
+ <key>PrimMediaMaxRetries</key>
<map>
<key>Comment</key>
- <string>Rectangle for sound preview window</string>
+ <string>Maximum number of retries for media queries.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>U32</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>85</integer>
- <integer>300</integer>
- <integer>0</integer>
- </array>
+ <integer>4</integer>
</map>
- <key>PreviewTextureRect</key>
+ <key>PrimMediaRequestQueueDelay</key>
<map>
<key>Comment</key>
- <string>Rectangle for texture preview window</string>
+ <string>Timer delay for fetching media from the queue (in seconds).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>F32</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>400</integer>
- <integer>400</integer>
- <integer>0</integer>
- </array>
+ <real>1.0</real>
</map>
- <key>PreviewURLRect</key>
+ <key>PrimMediaRetryTimerDelay</key>
<map>
<key>Comment</key>
- <string>Rectangle for URL preview window</string>
+ <string>Timer delay for retrying on media queries (in seconds).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>F32</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>90</integer>
- <integer>300</integer>
- <integer>0</integer>
- </array>
+ <real>5.0</real>
</map>
- <key>PreviewWearableRect</key>
+ <key>PrimMediaMaxSortedQueueSize</key>
<map>
<key>Comment</key>
- <string>Rectangle for wearable preview window</string>
+ <string>Maximum number of objects the viewer will load media for initially</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>U32</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>85</integer>
- <integer>300</integer>
- <integer>0</integer>
- </array>
+ <integer>100000</integer>
</map>
- <key>ProbeHardwareOnStartup</key>
+ <key>PrimMediaMaxRoundRobinQueueSize</key>
<map>
<key>Comment</key>
- <string>Query current hardware configuration on application startup</string>
+ <string>Maximum number of objects the viewer will continuously update media for</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Boolean</string>
+ <string>U32</string>
<key>Value</key>
- <integer>1</integer>
+ <integer>100000</integer>
</map>
- <key>PropertiesRect</key>
+ <key>ProbeHardwareOnStartup</key>
<map>
<key>Comment</key>
- <string>Rectangle for inventory item properties window</string>
+ <string>Query current hardware configuration on application startup</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>Boolean</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>320</integer>
- <integer>350</integer>
- <integer>0</integer>
- </array>
+ <integer>1</integer>
</map>
<key>PurgeCacheOnNextStartup</key>
<map>
@@ -6639,7 +5624,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
<key>QAMode</key>
<map>
@@ -6652,6 +5637,28 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>QAModeEventHostPort</key>
+ <map>
+ <key>Comment</key>
+ <string>Port on which lleventhost should listen</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>-1</integer>
+ </map>
+ <key>QAModeTermCode</key>
+ <map>
+ <key>Comment</key>
+ <string>On LL_ERRS, terminate with this code instead of OS message box</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>-1</integer>
+ </map>
<key>QuietSnapshotsToDisk</key>
<map>
<key>Comment</key>
@@ -6729,6 +5736,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>RegInClient</key>
+ <map>
+ <key>Comment</key>
+ <string>Experimental: Embed registration in login screen</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>RegionTextureSize</key>
<map>
<key>Comment</key>
@@ -6794,8 +5812,19 @@
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
- </map>
- <key>RenderAvatarCloth</key>
+ </map>
+ <key>RenderAvatar</key>
+ <map>
+ <key>Comment</key>
+ <string>Render Avatars</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>RenderAvatarCloth</key>
<map>
<key>Comment</key>
<string>Controls if avatars use wavy cloth</string>
@@ -6828,17 +5857,6 @@
<key>Value</key>
<integer>35</integer>
</map>
- <key>RenderAvatarInvisible</key>
- <map>
- <key>Comment</key>
- <string>Set your avatar as Invisible</string>
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>RenderAvatarVP</key>
<map>
<key>Comment</key>
@@ -6850,42 +5868,56 @@
<key>Value</key>
<integer>1</integer>
</map>
-
- <key>RenderShadowGaussian</key>
+
+ <key>RenderShadowNearDist</key>
<map>
<key>Comment</key>
- <string>Gaussian coefficients for the two shadow/SSAO blurring passes (z component unused).</string>
+ <string>Near clip plane of shadow camera (affects precision of depth shadows).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Vector3</string>
<key>Value</key>
<array>
- <real>2.0</real>
- <real>2.0</real>
- <real>0.0</real>
+ <real>256</real>
+ <real>256</real>
+ <real>256</real>
</array>
</map>
-
- <key>RenderShadowNearDist</key>
+ <key>RenderShadowClipPlanes</key>
<map>
<key>Comment</key>
- <string>Near clip plane of shadow camera (affects precision of depth shadows).</string>
+ <string>Near clip plane split distances for shadow map frusta.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Vector3</string>
<key>Value</key>
<array>
- <real>256</real>
- <real>256</real>
- <real>256</real>
+ <real>1.0</real>
+ <real>12.0</real>
+ <real>32.0</real>
</array>
</map>
- <key>RenderShadowClipPlanes</key>
+ <key>RenderShadowSplitExponent</key>
<map>
<key>Comment</key>
- <string>Near clip plane split distances for shadow map frusta.</string>
+ <string>Near clip plane split distances for shadow map frusta (x=perspective, y=ortho, z=transition rate).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Vector3</string>
+ <key>Value</key>
+ <array>
+ <real>3.0</real>
+ <real>3.0</real>
+ <real>2.0</real>
+ </array>
+ </map>
+ <key>RenderShadowOrthoClipPlanes</key>
+ <map>
+ <key>Comment</key>
+ <string>Near clip plane split distances for orthographic shadow map frusta.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -6897,6 +5929,39 @@
<real>24.0</real>
</array>
</map>
+ <key>RenderShadowProjOffset</key>
+ <map>
+ <key>Comment</key>
+ <string>Amount to scale distance to virtual origin of shadow perspective projection.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>2.0</real>
+ </map>
+ <key>RenderShadowSlopeThreshold</key>
+ <map>
+ <key>Comment</key>
+ <string>Cutoff slope value for points to affect perspective shadow generation</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.0</real>
+ </map>
+ <key>RenderShadowProjExponent</key>
+ <map>
+ <key>Comment</key>
+ <string>Exponent applied to transition between ortho and perspective shadow projections based on viewing angle and light vector.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.5</real>
+ </map>
<key>RenderSSAOScale</key>
<map>
<key>Comment</key>
@@ -6965,7 +6030,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
- <real>128</real>
+ <real>64</real>
</map>
<key>RenderCubeMap</key>
<map>
@@ -6978,16 +6043,16 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>RenderCustomSettings</key>
+ <key>RenderDebugAlphaMask</key>
<map>
<key>Comment</key>
- <string>Do you want to set the graphics settings yourself</string>
+ <string>Test Alpha Masking Cutoffs.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Boolean</string>
+ <string>F32</string>
<key>Value</key>
- <integer>0</integer>
+ <real>0.5</real>
</map>
<key>RenderDebugGL</key>
<map>
@@ -7044,7 +6109,7 @@
<key>Value</key>
<integer>0</integer>
</map>
-
+
<key>RenderAnimateTrees</key>
<map>
<key>Comment</key>
@@ -7056,6 +6121,174 @@
<key>Value</key>
<integer>0</integer>
</map>
+
+ <key>RenderGIRange</key>
+ <map>
+ <key>Comment</key>
+ <string>Distance to cut off GI effect.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>96</real>
+ </map>
+
+ <key>RenderGILuminance</key>
+ <map>
+ <key>Comment</key>
+ <string>Luminance factor of global illumination contribution.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.075</real>
+ </map>
+
+ <key>RenderGIBrightness</key>
+ <map>
+ <key>Comment</key>
+ <string>Brightness factor of global illumination contribution.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.3</real>
+ </map>
+
+ <key>RenderGINoise</key>
+ <map>
+ <key>Comment</key>
+ <string>Noise of position sampling for GI photon mapping.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.7</real>
+ </map>
+
+ <key>RenderGIAttenuation</key>
+ <map>
+ <key>Comment</key>
+ <string>Distance attenuation factor for indirect lighting.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.1</real>
+ </map>
+
+ <key>RenderGIBlurBrightness</key>
+ <map>
+ <key>Comment</key>
+ <string>Brightness factor of global illumination blur effect.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.025</real>
+ </map>
+
+ <key>RenderGIBlurEdgeWeight</key>
+ <map>
+ <key>Comment</key>
+ <string>Edge weight for GI soften filter (sharpness).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.8</real>
+ </map>
+
+ <key>RenderGIBlurIncrement</key>
+ <map>
+ <key>Comment</key>
+ <string>Increment of scale for each pass of global illumination blur effect.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.8</real>
+ </map>
+
+ <key>RenderLuminanceScale</key>
+ <map>
+ <key>Comment</key>
+ <string>Luminance value scalar for darkening effect.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.0</real>
+ </map>
+
+ <key>RenderSunLuminanceScale</key>
+ <map>
+ <key>Comment</key>
+ <string>Sun Luminance value scalar for darkening effect.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.0</real>
+ </map>
+
+ <key>RenderSunLuminanceOffset</key>
+ <map>
+ <key>Comment</key>
+ <string>Sun Luminance value offset for darkening effect.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0</real>
+ </map>
+
+ <key>RenderLuminanceDetail</key>
+ <map>
+ <key>Comment</key>
+ <string>Mipmap level to use for luminance</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>16.0</real>
+ </map>
+
+ <key>RenderEdgeDepthCutoff</key>
+ <map>
+ <key>Comment</key>
+ <string>Cutoff for depth difference that amounts to an edge.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.01</real>
+ </map>
+ <key>RenderEdgeNormCutoff</key>
+ <map>
+ <key>Comment</key>
+ <string>Cutoff for normal difference that amounts to an edge.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.25</real>
+ </map>
+
<key>RenderDeferredAlphaSoften</key>
<map>
<key>Comment</key>
@@ -7078,6 +6311,190 @@
<key>Value</key>
<real>4</real>
</map>
+ <key>RenderDeferredSpotShadowBias</key>
+ <map>
+ <key>Comment</key>
+ <string>Bias value for spot shadows (prevent shadow acne).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>-64.0</real>
+ </map>
+ <key>RenderDeferredSpotShadowOffset</key>
+ <map>
+ <key>Comment</key>
+ <string>Offset value for spot shadows (prevent shadow acne).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.8</real>
+ </map>
+
+ <key>RenderShadowBias</key>
+ <map>
+ <key>Comment</key>
+ <string>Bias value for shadows (prevent shadow acne).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>-0.008</real>
+ </map>
+ <key>RenderShadowOffset</key>
+ <map>
+ <key>Comment</key>
+ <string>Offset value for shadows (prevent shadow acne).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.01</real>
+ </map>
+
+ <key>RenderShadowResolutionScale</key>
+ <map>
+ <key>Comment</key>
+ <string>Scale of shadow map resolution vs. screen resolution</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.0</real>
+ </map>
+
+
+
+ <key>RenderDeferredTreeShadowBias</key>
+ <map>
+ <key>Comment</key>
+ <string>Bias value for tree shadows (prevent shadow acne).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.0</real>
+ </map>
+ <key>RenderDeferredTreeShadowOffset</key>
+ <map>
+ <key>Comment</key>
+ <string>Offset value for tree shadows (prevent shadow acne).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.0</real>
+ </map>
+
+ <key>RenderHoverGlowEnable</key>
+ <map>
+ <key>Comment</key>
+ <string>Show glow effect when hovering on interactive objects.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+
+ <key>RenderHighlightFadeTime</key>
+ <map>
+ <key>Comment</key>
+ <string>Transition time for mouseover highlights.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.1</real>
+ </map>
+
+ <key>RenderHighlightBrightness</key>
+ <map>
+ <key>Comment</key>
+ <string>Brightness of mouseover highlights.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>4.0</real>
+ </map>
+
+ <key>RenderHighlightThickness</key>
+ <map>
+ <key>Comment</key>
+ <string>Thickness of mouseover highlights.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.6</real>
+ </map>
+
+ <key>RenderHighlightColor</key>
+ <map>
+ <key>Comment</key>
+ <string>Brightness of mouseover highlights.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Color4</string>
+ <key>Value</key>
+ <array>
+ <real>0.4</real>
+ <real>0.98</real>
+ <real>0.93</real>
+ <real>1.0</real>
+ </array>
+ </map>
+
+ <key>RenderSpecularResX</key>
+ <map>
+ <key>Comment</key>
+ <string>Spec map resolution.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <real>128</real>
+ </map>
+
+ <key>RenderSpecularResY</key>
+ <map>
+ <key>Comment</key>
+ <string>Spec map resolution.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <real>128</real>
+ </map>
+
+ <key>RenderSpecularExponent</key>
+ <map>
+ <key>Comment</key>
+ <string>Specular exponent for generating spec map</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1</real>
+ </map>
+
<key>RenderDeferred</key>
<map>
<key>Comment</key>
@@ -7089,6 +6506,31 @@
<key>Value</key>
<integer>0</integer>
</map>
+
+ <key>RenderDeferredShadow</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable shadows in deferred renderer.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+
+ <key>RenderDeferredGI</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable GI in deferred renderer.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+
<key>RenderDeferredSunShadow</key>
<map>
<key>Comment</key>
@@ -7100,6 +6542,67 @@
<key>Value</key>
<integer>1</integer>
</map>
+
+ <key>RenderDeferredSun</key>
+ <map>
+ <key>Comment</key>
+ <string>Execute sunlight shader in deferred renderer.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+
+ <key>RenderDeferredAtmospheric</key>
+ <map>
+ <key>Comment</key>
+ <string>Execute atmospheric shader in deferred renderer.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+
+ <key>RenderDeferredBlurLight</key>
+ <map>
+ <key>Comment</key>
+ <string>Execute shadow softening shader in deferred renderer.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+
+ <key>RenderDeferredLocalLights</key>
+ <map>
+ <key>Comment</key>
+ <string>Execute local lighting shader in deferred renderer.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+
+ <key>RenderDeferredFullscreenLights</key>
+ <map>
+ <key>Comment</key>
+ <string>Execute local lighting shader in deferred renderer.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+
<key>RenderDeferredSunWash</key>
<map>
<key>Comment</key>
@@ -7122,6 +6625,45 @@
<key>Value</key>
<real>-0.0001</real>
</map>
+ <key>RenderShadowErrorCutoff</key>
+ <map>
+ <key>Comment</key>
+ <string>Cutoff error value to use ortho instead of perspective projection.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>5.0</real>
+ </map>
+ <key>RenderShadowFOVCutoff</key>
+ <map>
+ <key>Comment</key>
+ <string>Cutoff FOV to use ortho instead of perspective projection.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.1</real>
+ </map>
+
+ <key>RenderShadowGaussian</key>
+ <map>
+ <key>Comment</key>
+ <string>Gaussian coefficients for the two shadow/SSAO blurring passes (z component unused).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Vector3</string>
+ <key>Value</key>
+ <array>
+ <real>3.0</real>
+ <real>2.0</real>
+ <real>0.0</real>
+ </array>
+ </map>
+
<key>RenderShadowBlurSize</key>
<map>
<key>Comment</key>
@@ -7131,7 +6673,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
- <real>0.7</real>
+ <real>1.4</real>
</map>
<key>RenderShadowBlurSamples</key>
<map>
@@ -7142,8 +6684,106 @@
<key>Type</key>
<string>U32</string>
<key>Value</key>
- <real>5</real>
+ <real>4</real>
+ </map>
+ <key>RenderShadowBlurDistFactor</key>
+ <map>
+ <key>Comment</key>
+ <string>Distance scaler for shadow blur.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.1</real>
+ </map>
+
+ <key>RenderGIAmbiance</key>
+ <map>
+ <key>Comment</key>
+ <string>Ambiance factor of global illumination contribution.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.5</real>
+ </map>
+
+ <key>RenderGIMinRenderSize</key>
+ <map>
+ <key>Comment</key>
+ <string>Minimum size of objects to put into GI source map.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.5</real>
+ </map>
+
+ <key>RenderGIBlurColorCurve</key>
+ <map>
+ <key>Comment</key>
+ <string>Color curve for GI softening kernel</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Vector3</string>
+ <key>Value</key>
+ <array>
+ <real>1.0</real>
+ <real>0.6</real>
+ <real>0.02</real>
+ </array>
+ </map>
+
+ <key>RenderGIBlurPasses</key>
+ <map>
+ <key>Comment</key>
+ <string>Scale of GI softening kernel.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <real>4</real>
+ </map>
+
+ <key>RenderGIBlurSize</key>
+ <map>
+ <key>Comment</key>
+ <string>Scale of GI softening kernel.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>4.0</real>
+ </map>
+ <key>RenderGIBlurSamples</key>
+ <map>
+ <key>Comment</key>
+ <string>Number of samples to take for each pass of GI blur (value range 1-16). Actual number of samples is value * 2 - 1.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <real>16</real>
</map>
+ <key>RenderGIBlurDistFactor</key>
+ <map>
+ <key>Comment</key>
+ <string>Distance scaler for GI blur.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.0</real>
+ </map>
+
<key>RenderDynamicLOD</key>
<map>
<key>Comment</key>
@@ -7416,7 +7056,7 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>RenderHideGroupTitleAll</key>
+ <key>RenderShowGroupTitleAll</key>
<map>
<key>Comment</key>
<string>Show group titles in name labels</string>
@@ -7425,7 +7065,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
<key>RenderInitError</key>
<map>
@@ -7480,7 +7120,7 @@
<key>Type</key>
<string>S32</string>
<key>Value</key>
- <integer>4096</integer>
+ <integer>8192</integer>
</map>
<key>RenderMaxVBOSize</key>
<map>
@@ -7493,17 +7133,6 @@
<key>Value</key>
<integer>512</integer>
</map>
- <key>RenderName</key>
- <map>
- <key>Comment</key>
- <string>Controls display of names above avatars (0 = never, 1 = fade, 2 = always)</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>S32</string>
- <key>Value</key>
- <integer>2</integer>
- </map>
<key>RenderNameFadeDuration</key>
<map>
<key>Comment</key>
@@ -7515,16 +7144,16 @@
<key>Value</key>
<real>1.0</real>
</map>
- <key>RenderNameHideSelf</key>
+ <key>RenderNameShowSelf</key>
<map>
<key>Comment</key>
- <string>Don't display own name above avatar</string>
+ <string>Display own name above avatar</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
<key>RenderNameShowTime</key>
<map>
@@ -7702,6 +7331,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>RenderUIBuffer</key>
+ <map>
+ <key>Comment</key>
+ <string>Cache ui render in a screen aligned buffer.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>RenderUnloadedAvatar</key>
<map>
<key>Comment</key>
@@ -7856,17 +7496,6 @@
<key>Value</key>
<real>1.0</real>
</map>
- <key>RunBtnState</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>RunMultipleThreads</key>
<map>
<key>Comment</key>
@@ -7933,33 +7562,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>ScriptErrorColor</key>
- <map>
- <key>Comment</key>
- <string>Color of script error messages</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.8235294117</real>
- <real>0.2745098039</real>
- <real>0.2745098039</real>
- <real>1.0</real>
- </array>
- </map>
- <key>ScriptErrorsAsChat</key>
- <map>
- <key>Comment</key>
- <string>Display script errors and warning in chat history</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>ScriptHelpFollowsCursor</key>
<map>
<key>Comment</key>
@@ -7971,45 +7573,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>SearchURLDefault</key>
- <map>
- <key>Comment</key>
- <string>URL to load for empty searches</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>HideFromEditor</key>
- <integer>1</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>http://search.secondlife.com/client_search.php?</string>
- </map>
- <key>SearchURLQuery</key>
- <map>
- <key>Comment</key>
- <string>URL to use for searches</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>HideFromEditor</key>
- <integer>1</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>http://search.secondlife.com/client_search.php?q=[QUERY]&amp;s=[COLLECTION]&amp;</string>
- </map>
- <key>SearchURLSuffix2</key>
- <map>
- <key>Comment</key>
- <string>Parameters added to end of search queries</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>HideFromEditor</key>
- <integer>1</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>lang=[LANG]&amp;mat=[MATURITY]&amp;t=[TEEN]&amp;region=[REGION]&amp;x=[X]&amp;y=[Y]&amp;z=[Z]&amp;session=[SESSION]</string>
- </map>
<key>SelectMovableOnly</key>
<map>
<key>Comment</key>
@@ -8131,10 +7694,10 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>ShowActiveSpeakers</key>
+ <key>ShowAdvancedGraphicsSettings</key>
<map>
<key>Comment</key>
- <string>Display active speakers list on login</string>
+ <string>Show advanced graphics settings</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -8153,6 +7716,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>AvatarNameTagMode</key>
+ <map>
+ <key>Comment</key>
+ <string>Select Avatar Name Tag Mode</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>ShowAxes</key>
<map>
<key>Comment</key>
@@ -8175,43 +7749,76 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>ShowCameraControls</key>
+ <key>ShowConsoleWindow</key>
<map>
<key>Comment</key>
- <string>Display camera controls on login</string>
+ <string>Show log in separate OS window</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>1</integer>
+ <integer>0</integer>
</map>
- <key>ShowChatHistory</key>
+ <key>NavBarShowCoordinates</key>
<map>
<key>Comment</key>
- <string />
+ <string>Show coordinates in navigation bar</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
- <key>ShowCommunicate</key>
+ <key>NavBarShowParcelProperties</key>
<map>
<key>Comment</key>
- <string />
+ <string>Show parcel property icons in navigation bar</string>
<key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>ShowCrosshairs</key>
+ <map>
+ <key>Comment</key>
+ <string>Display crosshairs when in mouselook mode</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>ShowDebugConsole</key>
+ <map>
+ <key>Comment</key>
+ <string>Show log in SL window</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
<integer>0</integer>
+ </map>
+ <key>ShowDebugAppearanceEditor</key>
+ <map>
+ <key>Comment</key>
+ <string>Show debugging appearance editor</string>
+ <key>Persist</key>
+ <integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
- <key>ShowConsoleWindow</key>
+ <key>ShowEmptyFoldersWhenSearching</key>
<map>
<key>Comment</key>
- <string>Show log in separate OS window</string>
+ <string>Shows folders that do not have any visible contents when applying a filter to inventory</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -8219,10 +7826,10 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>ShowCrosshairs</key>
+ <key>ShowHoverTips</key>
<map>
<key>Comment</key>
- <string>Display crosshairs when in mouselook mode</string>
+ <string>Show descriptive tooltip when mouse hovers over items in world</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -8230,98 +7837,197 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>ShowDebugConsole</key>
+ <key>ShowLandHoverTip</key>
<map>
<key>Comment</key>
- <string>Show log in SL window</string>
+ <string>Show descriptive tooltip when mouse hovers over land</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
+ </map>
+ <key>ShowCameraButton</key>
+ <map>
+ <key>Comment</key>
+ <string>Show/Hide Camera button in the bottom tray</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
</map>
- <key>ShowDebugStats</key>
+ <key>ShowScriptErrors</key>
<map>
<key>Comment</key>
- <string>Show performance stats display</string>
+ <string>Show script errors</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
- <key>ShowDirectory</key>
+ <key>ShowScriptErrorsLocation</key>
<map>
<key>Comment</key>
- <string />
+ <string>Show script error in chat or window</string>
<key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
<integer>0</integer>
+ </map>
+ <key>ShowSnapshotButton</key>
+ <map>
+ <key>Comment</key>
+ <string>Show/Hide Snapshot button button in the bottom tray</string>
+ <key>Persist</key>
+ <integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
- <key>ShowEmptyFoldersWhenSearching</key>
+ <key>ShowMoveButton</key>
<map>
<key>Comment</key>
- <string>Shows folders that do not have any visible contents when applying a filter to inventory</string>
+ <string>Show/Hide Move button in the bottom tray</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
+ </map>
+ <key>ShowGestureButton</key>
+ <map>
+ <key>Comment</key>
+ <string>Show/Hide Gesture button in the bottom tray</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
</map>
- <key>ShowHoverTips</key>
+ <key>ShowObjectRenderingCost</key>
<map>
<key>Comment</key>
- <string>Show descriptive tooltip when mouse hovers over items in world</string>
+ <string>Show the object rendering cost in build tools</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>ShowNavbarFavoritesPanel</key>
+ <map>
+ <key>Comment</key>
+ <string>Show/Hide Navigation Bar Favorites Panel</string>
+ <key>Persist</key>
<integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
</map>
- <key>ShowInventory</key>
+ <key>ShowNavbarNavigationPanel</key>
<map>
<key>Comment</key>
- <string>Open inventory window on login</string>
+ <string>Show/Hide Navigation Bar Navigation Panel</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
- <key>ShowLandHoverTip</key>
+ <key>GroupListShowIcons</key>
<map>
<key>Comment</key>
- <string>Show descriptive tooltip when mouse hovers over land</string>
+ <string>Show/hide group icons in the group list</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
- <key>ShowLeaders</key>
+ <key>FriendsListShowIcons</key>
<map>
<key>Comment</key>
- <string />
+ <string>Show/hide online and all friends icons in the friend list</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>NearbyListShowIcons</key>
+ <map>
+ <key>Comment</key>
+ <string>Show/hide people icons in nearby list</string>
+ <key>Persist</key>
+ <integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>RecentListShowIcons</key>
+ <map>
+ <key>Comment</key>
+ <string>Show/hide people icons in recent list</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>FriendsSortOrder</key>
+ <map>
+ <key>Comment</key>
+ <string>Specifies sort order for friends (0 = by name, 1 = by online status)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
<integer>0</integer>
</map>
- <key>ShowPGSearchAll</key>
+ <key>NearbyPeopleSortOrder</key>
+ <map>
+ <key>Comment</key>
+ <string>Specifies sort order for nearby people (0 = by name, 2 = by most recent)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>2</integer>
+ </map>
+ <key>RecentPeopleSortOrder</key>
+ <map>
+ <key>Comment</key>
+ <string>Specifies sort order for recent people (0 = by name, 2 = by most recent)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>2</integer>
+ </map>
+ <key>ShowPGSearchAll</key>
<map>
<key>Comment</key>
- <string>Display results of search All that are flagged as PG</string>
+ <string>Display results of search All that are flagged as general</string>
<key>Persist</key>
<integer>1</integer>
<key>HideFromEditor</key>
@@ -8334,7 +8040,7 @@
<key>ShowMatureSearchAll</key>
<map>
<key>Comment</key>
- <string>Display results of search All that are flagged as mature</string>
+ <string>Display results of search All that are flagged as moderate</string>
<key>Persist</key>
<integer>1</integer>
<key>HideFromEditor</key>
@@ -8360,7 +8066,7 @@
<key>ShowPGGroups</key>
<map>
<key>Comment</key>
- <string>Display results of find groups that are flagged as PG</string>
+ <string>Display results of find groups that are flagged as general</string>
<key>Persist</key>
<integer>1</integer>
<key>HideFromEditor</key>
@@ -8373,7 +8079,7 @@
<key>ShowMatureGroups</key>
<map>
<key>Comment</key>
- <string>Display results of find groups that are flagged as mature</string>
+ <string>Display results of find groups that are flagged as moderate</string>
<key>Persist</key>
<integer>1</integer>
<key>HideFromEditor</key>
@@ -8399,7 +8105,7 @@
<key>ShowPGClassifieds</key>
<map>
<key>Comment</key>
- <string>Display results of find classifieds that are flagged as PG</string>
+ <string>Display results of find classifieds that are flagged as general</string>
<key>Persist</key>
<integer>1</integer>
<key>HideFromEditor</key>
@@ -8412,7 +8118,7 @@
<key>ShowMatureClassifieds</key>
<map>
<key>Comment</key>
- <string>Display results of find classifieds that are flagged as mature</string>
+ <string>Display results of find classifieds that are flagged as moderate</string>
<key>Persist</key>
<integer>1</integer>
<key>HideFromEditor</key>
@@ -8438,7 +8144,7 @@
<key>ShowPGEvents</key>
<map>
<key>Comment</key>
- <string>Display results of find events that are flagged as PG</string>
+ <string>Display results of find events that are flagged as general</string>
<key>Persist</key>
<integer>1</integer>
<key>HideFromEditor</key>
@@ -8451,7 +8157,7 @@
<key>ShowMatureEvents</key>
<map>
<key>Comment</key>
- <string>Display results of find events that are flagged as mature</string>
+ <string>Display results of find events that are flagged as moderate</string>
<key>Persist</key>
<integer>1</integer>
<key>HideFromEditor</key>
@@ -8477,7 +8183,7 @@
<key>ShowPGLand</key>
<map>
<key>Comment</key>
- <string>Display results of find land sales that are flagged as PG</string>
+ <string>Display results of find land sales that are flagged as general</string>
<key>Persist</key>
<integer>1</integer>
<key>HideFromEditor</key>
@@ -8490,7 +8196,7 @@
<key>ShowMatureLand</key>
<map>
<key>Comment</key>
- <string>Display results of find land sales that are flagged as mature</string>
+ <string>Display results of find land sales that are flagged as moderate</string>
<key>Persist</key>
<integer>1</integer>
<key>HideFromEditor</key>
@@ -8516,7 +8222,7 @@
<key>ShowPGSims</key>
<map>
<key>Comment</key>
- <string>Display results of find places or find popular that are in PG sims</string>
+ <string>Display results of find places or find popular that are in general sims</string>
<key>Persist</key>
<integer>1</integer>
<key>HideFromEditor</key>
@@ -8529,7 +8235,7 @@
<key>ShowMatureSims</key>
<map>
<key>Comment</key>
- <string>Display results of find places or find popular that are in mature sims</string>
+ <string>Display results of find places or find popular that are in moderate sims</string>
<key>Persist</key>
<integer>1</integer>
<key>HideFromEditor</key>
@@ -8552,28 +8258,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>ShowMiniMap</key>
- <map>
- <key>Comment</key>
- <string>Display mini map on login</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
- <key>ShowMovementControls</key>
- <map>
- <key>Comment</key>
- <string>Display movement controls on login</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
<key>ShowNearClip</key>
<map>
<key>Comment</key>
@@ -8662,7 +8346,7 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>ShowSearchBar</key>
+ <key>ShowNetStats</key>
<map>
<key>Comment</key>
<string>Show the Search Bar in the Status Overlay</string>
@@ -8671,7 +8355,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>1</integer>
+ <integer>0</integer>
</map>
<key>ShowSelectionBeam</key>
<map>
@@ -8693,7 +8377,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
<key>ShowTangentBasis</key>
<map>
@@ -8717,17 +8401,6 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>ShowTools</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>ShowTutorial</key>
<map>
<key>Comment</key>
@@ -8761,49 +8434,27 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>ShowWorldMap</key>
- <map>
- <key>Comment</key>
- <string>Display world map on login</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
- <key>ShowXUINames</key>
+ <key>SkinCurrent</key>
<map>
<key>Comment</key>
- <string>Display XUI Names as Tooltips</string>
+ <string>The currently selected skin.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Boolean</string>
+ <string>String</string>
<key>Value</key>
- <integer>0</integer>
+ <string>default</string>
</map>
- <key>SitBtnState</key>
+ <key>SkinningSettingsFile</key>
<map>
<key>Comment</key>
- <string />
+ <string>Client skin color setting file name (per install).</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
- <key>SkinCurrent</key>
- <map>
- <key>Comment</key>
- <string>The currently selected skin.</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
<string>String</string>
<key>Value</key>
- <string>default</string>
+ <string />
</map>
<key>SkyAmbientScale</key>
<map>
@@ -8837,8 +8488,8 @@
<string>Color3</string>
<key>Value</key>
<array>
- <real>0.699999988079</real>
- <real>0.699999988079</real>
+ <real>0.67</real>
+ <real>0.67</real>
<real>1.0</real>
</array>
</map>
@@ -8879,38 +8530,6 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>SlideLeftBtnRect</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>20</integer>
- <integer>54</integer>
- <integer>45</integer>
- <integer>29</integer>
- </array>
- </map>
- <key>SlideRightBtnRect</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>66</integer>
- <integer>54</integer>
- <integer>91</integer>
- <integer>29</integer>
- </array>
- </map>
<key>SmallAvatarNames</key>
<map>
<key>Comment</key>
@@ -9010,22 +8629,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>SpeakingColor</key>
- <map>
- <key>Comment</key>
- <string>Color of various indicators when resident is speaking on a voice channel.</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.0</real>
- <real>1.0</real>
- <real>0.0</real>
- <real>1.0</real>
- </array>
- </map>
<key>SpeedTest</key>
<map>
<key>Comment</key>
@@ -9114,59 +8717,54 @@
<key>Value</key>
<string>fss.txt</string>
</map>
- <key>StatusBarHeight</key>
+ <key>SystemLanguage</key>
<map>
<key>Comment</key>
- <string>Height of menu/status bar at top of screen (pixels)</string>
+ <string>Language indicated by system settings (for UI)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>S32</string>
+ <string>String</string>
<key>Value</key>
- <integer>26</integer>
+ <string>en</string>
</map>
- <key>StatusBarPad</key>
+ <key>TabToTextFieldsOnly</key>
<map>
<key>Comment</key>
- <string>Spacing between popup buttons at bottom of screen (Stand up, Release Controls)</string>
+ <string>TAB key takes you to next text entry field, instead of next widget</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>S32</string>
+ <string>Boolean</string>
<key>Value</key>
- <integer>10</integer>
+ <integer>0</integer>
</map>
- <key>SystemChatColor</key>
+ <key>TerrainColorHeightRange</key>
<map>
<key>Comment</key>
- <string>Color of chat messages from SL System</string>
+ <string>Altitude range over which a given terrain texture has effect (meters)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Color4</string>
+ <string>F32</string>
<key>Value</key>
- <array>
- <real>0.800000011921</real>
- <real>1.0</real>
- <real>1.0</real>
- <real>1.0</real>
- </array>
+ <real>60.0</real>
</map>
- <key>SystemLanguage</key>
+ <key>TerrainColorStartHeight</key>
<map>
<key>Comment</key>
- <string>Language indicated by system settings (for UI)</string>
+ <string>Starting altitude for terrain texturing (meters)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>F32</string>
<key>Value</key>
- <string>en-us</string>
+ <real>20.0</real>
</map>
- <key>TabToTextFieldsOnly</key>
+ <key>TextureDecodeDisabled</key>
<map>
<key>Comment</key>
- <string>TAB key takes you to next text entry field, instead of next widget</string>
+ <string>If TRUE, do not fetch and decode any textures</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -9174,27 +8772,27 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>TerrainColorHeightRange</key>
+ <key>TextureDisable</key>
<map>
<key>Comment</key>
- <string>Altitude range over which a given terrain texture has effect (meters)</string>
+ <string>If TRUE, do not load textures for in-world content</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>F32</string>
+ <string>Boolean</string>
<key>Value</key>
- <real>60.0</real>
+ <integer>0</integer>
</map>
- <key>TerrainColorStartHeight</key>
+ <key>TextureLoadFullRes</key>
<map>
<key>Comment</key>
- <string>Starting altitude for terrain texturing (meters)</string>
+ <string>If TRUE, always load textures at full resolution (discard = 0)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>F32</string>
+ <string>Boolean</string>
<key>Value</key>
- <real>20.0</real>
+ <integer>0</integer>
</map>
<key>TextureMemory</key>
<map>
@@ -9207,22 +8805,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>TexturePickerRect</key>
- <map>
- <key>Comment</key>
- <string>Rectangle for texture picker</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Rect</string>
- <key>Value</key>
- <array>
- <integer>0</integer>
- <integer>290</integer>
- <integer>350</integer>
- <integer>0</integer>
- </array>
- </map>
<key>TexturePickerShowFolders</key>
<map>
<key>Comment</key>
@@ -9245,17 +8827,6 @@
<key>Value</key>
<integer>2</integer>
</map>
- <key>ThirdPersonBtnState</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
<key>ThrottleBandwidthKBPS</key>
<map>
<key>Comment</key>
@@ -9267,102 +8838,82 @@
<key>Value</key>
<real>500.0</real>
</map>
- <key>ToolHelpRect</key>
+ <key>ToolTipDelay</key>
<map>
<key>Comment</key>
- <string />
+ <string>Seconds before displaying tooltip when mouse stops over UI element</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>F32</string>
<key>Value</key>
- <array>
- <integer>8</integer>
- <integer>178</integer>
- <integer>75</integer>
- <integer>162</integer>
- </array>
+ <real>0.699999988079</real>
</map>
- <key>ToolTipDelay</key>
+ <key>ToolTipFadeTime</key>
<map>
<key>Comment</key>
- <string>Seconds before displaying tooltip when mouse stops over UI element</string>
+ <string>Seconds over which tooltip fades away</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
- <real>0.699999988079</real>
+ <real>0.2</real>
</map>
- <key>ToolboxAutoMove</key>
+ <key>ToolTipVisibleTimeFar</key>
<map>
<key>Comment</key>
- <string>[NOT USED]</string>
+ <string>Fade tooltip after after time passes (seconds) while mouse not near tooltip</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Boolean</string>
+ <string>F32</string>
<key>Value</key>
- <integer>0</integer>
+ <real>1.0</real>
</map>
- <key>ToolboxRect</key>
+ <key>ToolTipVisibleTimeNear</key>
<map>
<key>Comment</key>
- <string>Rectangle for tools window</string>
+ <string>Fade tooltip after after time passes (seconds) while mouse near tooltip or original position</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>F32</string>
<key>Value</key>
- <array>
- <integer>0</integer>
- <integer>100</integer>
- <integer>100</integer>
- <integer>100</integer>
- </array>
+ <real>10.0</real>
</map>
- <key>TrackFocusObject</key>
+ <key>ToolTipVisibleTimeOver</key>
<map>
<key>Comment</key>
- <string>Camera tracks last object zoomed on</string>
+ <string>Fade tooltip after after time passes (seconds) while mouse over tooltip</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Boolean</string>
+ <string>F32</string>
<key>Value</key>
- <integer>1</integer>
+ <real>1000.0</real>
</map>
- <key>TurnLeftBtnRect</key>
+ <key>ToolboxAutoMove</key>
<map>
<key>Comment</key>
- <string />
+ <string>[NOT USED]</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>Boolean</string>
<key>Value</key>
- <array>
- <integer>20</integer>
- <integer>29</integer>
- <integer>45</integer>
- <integer>4</integer>
- </array>
+ <integer>0</integer>
</map>
- <key>TurnRightBtnRect</key>
+ <key>TrackFocusObject</key>
<map>
<key>Comment</key>
- <string />
+ <string>Camera tracks last object zoomed on</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>Rect</string>
+ <string>Boolean</string>
<key>Value</key>
- <array>
- <integer>66</integer>
- <integer>29</integer>
- <integer>91</integer>
- <integer>4</integer>
- </array>
+ <integer>1</integer>
</map>
<key>TutorialURL</key>
<map>
@@ -9397,656 +8948,194 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>UIFloaterTestBool</key>
+ <key>UIAvatariconctrlSymbolHPad</key>
<map>
<key>Comment</key>
- <string>Example saved setting for the test floater</string>
+ <string>UI Avatar Icon Control Symbol Horizontal Pad</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
- <key>UIImgBtnCloseActiveUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>47a8c844-cd2a-4b1a-be01-df8b1612fe5d</string>
- </map>
- <key>UIImgBtnCloseInactiveUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>779e4fa3-9b13-f74a-fba9-3886fe9c86ba</string>
- </map>
- <key>UIImgBtnClosePressedUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>e5821134-23c0-4bd0-af06-7fa95b9fb01a</string>
- </map>
- <key>UIImgBtnForwardInUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>54197a61-f5d1-4c29-95d2-c071d08849cb</string>
- </map>
- <key>UIImgBtnForwardOutUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>a0eb4021-1b20-4a53-892d-8faa9265a6f5</string>
- </map>
- <key>UIImgBtnJumpLeftInUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>9cad3e6d-2d6d-107d-f8ab-5ba272b5bfe1</string>
- </map>
- <key>UIImgBtnJumpLeftOutUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>3c18c87e-5f50-14e2-e744-f44734aa365f</string>
- </map>
- <key>UIImgBtnJumpRightInUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>7dabc040-ec13-2309-ddf7-4f161f6de2f4</string>
- </map>
- <key>UIImgBtnJumpRightOutUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>ff9a71eb-7414-4cf8-866e-a701deb7c3cf</string>
- </map>
- <key>UIImgBtnLeftInUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>95463c78-aaa6-464d-892d-3a805b6bb7bf</string>
- </map>
- <key>UIImgBtnLeftOutUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>13a93910-6b44-45eb-ad3a-4d1324c59bac</string>
- </map>
- <key>UIImgBtnMinimizeActiveUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>34c9398d-bb78-4643-9633-46a2fa3e9637</string>
- </map>
- <key>UIImgBtnMinimizeInactiveUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>6e72abba-1378-437f-bf7a-f0c15f3e99a3</string>
- </map>
- <key>UIImgBtnMinimizePressedUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>39801651-26cb-4926-af57-7af9352c273c</string>
- </map>
- <key>UIImgBtnMoveDownInUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>b92a70b9-c841-4c94-b4b3-cee9eb460d48</string>
- </map>
- <key>UIImgBtnMoveDownOutUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>b5abc9fa-9e62-4e03-bc33-82c4c1b6b689</string>
- </map>
- <key>UIImgBtnMoveUpInUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>49b4b357-e430-4b56-b9e0-05b8759c3c82</string>
- </map>
- <key>UIImgBtnMoveUpOutUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>f887146d-829f-4e39-9211-cf872b78f97c</string>
- </map>
- <key>UIImgBtnPanDownInUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>e5821134-23c0-4bd0-af06-7fa95b9fb01a</string>
- </map>
- <key>UIImgBtnPanDownOutUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>47a8c844-cd2a-4b1a-be01-df8b1612fe5d</string>
- </map>
- <key>UIImgBtnPanLeftInUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>e5821134-23c0-4bd0-af06-7fa95b9fb01a</string>
- </map>
- <key>UIImgBtnPanLeftOutUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>47a8c844-cd2a-4b1a-be01-df8b1612fe5d</string>
- </map>
- <key>UIImgBtnPanRightInUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>e5821134-23c0-4bd0-af06-7fa95b9fb01a</string>
- </map>
- <key>UIImgBtnPanRightOutUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>47a8c844-cd2a-4b1a-be01-df8b1612fe5d</string>
- </map>
- <key>UIImgBtnPanUpInUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>e5821134-23c0-4bd0-af06-7fa95b9fb01a</string>
- </map>
- <key>UIImgBtnPanUpOutUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>47a8c844-cd2a-4b1a-be01-df8b1612fe5d</string>
- </map>
- <key>UIImgBtnRestoreActiveUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>111b39de-8928-4690-b7b2-e17d5c960277</string>
- </map>
- <key>UIImgBtnRestoreInactiveUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>0eafa471-70af-4882-b8c1-40a310929744</string>
- </map>
- <key>UIImgBtnRestorePressedUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>90a0ed5c-2e7b-4845-9958-a64a1b30f312</string>
- </map>
- <key>UIImgBtnRightInUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>5e616d0d-4335-476f-9977-560bccd009da</string>
- </map>
- <key>UIImgBtnRightOutUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>5a44fd04-f52b-4c30-8b00-4a31e27614bd</string>
- </map>
- <key>UIImgBtnScrollDownInUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>d2421bab-2eaf-4863-b8f6-5e4c52519247</string>
- </map>
- <key>UIImgBtnScrollDownOutUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>b4ecdecf-5c8d-44e7-b882-17a77e88ed55</string>
- </map>
- <key>UIImgBtnScrollLeftInUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>ea137a32-6718-4d05-9c22-7d570d27b2cd</string>
- </map>
- <key>UIImgBtnScrollLeftOutUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>43773e8d-49aa-48e0-80f3-a04715f4677a</string>
- </map>
- <key>UIImgBtnScrollRightInUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>b749de64-e903-4c3c-ac0b-25fb6fa39cb5</string>
- </map>
- <key>UIImgBtnScrollRightOutUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>3d700d19-e708-465d-87f2-46c8c0ee7938</string>
- </map>
- <key>UIImgBtnScrollUpInUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>a93abdf3-27b5-4e22-a8fa-c48216cd2e3a</string>
- </map>
- <key>UIImgBtnScrollUpOutUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>dad084d7-9a46-452a-b0ff-4b9f1cefdde9</string>
- </map>
- <key>UIImgBtnSlideLeftInUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>724996f5-b956-46f6-9844-4fcfce1d5e83</string>
- </map>
- <key>UIImgBtnSlideLeftOutUUID</key>
+ <real>2</real>
+ </map>
+ <key>UIAvatariconctrlSymbolVPad</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI Avatar Icon Control Symbol Vertical Pad</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>82476321-0374-4c26-9567-521535ab4cd7</string>
- </map>
- <key>UIImgBtnSlideRightInUUID</key>
+ <real>2</real>
+ </map>
+ <key>UIAvatariconctrlSymbolSize</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI Avatar Icon Control Symbol Size</string>
<key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>7eeb57d2-3f37-454d-a729-8b217b8be443</string>
- </map>
- <key>UIImgBtnSlideRightOutUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>1fbe4e60-0607-44d1-a50a-032eff56ae75</string>
- </map>
- <key>UIImgBtnSpinDownInUUID</key>
+ <real>5</real>
+ </map>
+ <key>UIAvatariconctrlSymbolPosition</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI Avatar Icon Control Symbol Position (TopLeft|TopRight|BottomLeft|BottomRight)</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>a985ac71-052f-48e6-9c33-d931c813ac92</string>
+ <string>BottomRight</string>
</map>
- <key>UIImgBtnSpinDownOutUUID</key>
+ <key>UIButtonOrigHPad</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI Button Original Horizontal Pad</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>b6d240dd-5602-426f-b606-bbb49a30726d</string>
+ <real>6</real>
</map>
- <key>UIImgBtnSpinUpInUUID</key>
+ <key>UICheckboxctrlBtnSize</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI Checkbox Control Button Size</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>c8450082-96a0-4319-8090-d3ff900b4954</string>
+ <real>13</real>
</map>
- <key>UIImgBtnSpinUpOutUUID</key>
+ <key>UICheckboxctrlHeight</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI Checkbox Control Height</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>56576e6e-6710-4e66-89f9-471b59122794</string>
+ <real>16</real>
</map>
- <key>UIImgBtnTabBottomInUUID</key>
+ <key>UICheckboxctrlHPad</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI Checkbox Control Horizontal Pad</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>c001d8fd-a869-4b6f-86a1-fdcb106df9c7</string>
+ <real>2</real>
</map>
- <key>UIImgBtnTabBottomOutUUID</key>
+ <key>UICheckboxctrlSpacing</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI Checkbox Control Spacing</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>bf0a8779-689b-48c3-bb9a-6af546366ef4</string>
+ <real>5</real>
</map>
- <key>UIImgBtnTabBottomPartialInUUID</key>
+ <key>UICheckboxctrlVPad</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI Checkbox Control Vertical Pad</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>eb0b0904-8c91-4f24-b500-1180b91140de</string>
+ <real>2</real>
</map>
- <key>UIImgBtnTabBottomPartialOutUUID</key>
+ <key>UICloseBoxFromTop</key>
<map>
<key>Comment</key>
- <string />
+ <string>Distance from top of floater to top of close box icon, pixels</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>8dca716c-b29c-403a-9886-91c028357d6e</string>
+ <real>5</real>
</map>
- <key>UIImgBtnTabTopInUUID</key>
+ <key>UIExtraTriangleHeight</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI extra triangle height</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>16d032e8-817b-4368-8a4e-b7b947ae3889</string>
+ <real>-2</real>
</map>
- <key>UIImgBtnTabTopOutUUID</key>
+ <key>UIExtraTriangleWidth</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI extra triangle width</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>1ed83f57-41cf-4052-a3b4-2e8bb78d8191</string>
+ <real>2</real>
</map>
- <key>UIImgBtnTabTopPartialInUUID</key>
+ <key>UIFloaterCloseBoxSize</key>
<map>
<key>Comment</key>
- <string />
+ <string>Size of UI floater close box size</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>7c6c6c26-0e25-4438-89bd-30d8b8e9d704</string>
+ <real>16</real>
</map>
- <key>UIImgBtnTabTopPartialOutUUID</key>
+ <key>UIFloaterHPad</key>
<map>
<key>Comment</key>
- <string />
+ <string>Size of UI floater horizontal pad</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>932ad585-0e45-4a57-aa23-4cf81beeb7b0</string>
+ <real>6</real>
</map>
- <key>UIImgBtnTearOffActiveUUID</key>
+ <key>UIFloaterTestBool</key>
<map>
<key>Comment</key>
- <string />
+ <string>Example saved setting for the test floater</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>Boolean</string>
<key>Value</key>
- <string>74e1a96f-4833-a24d-a1bb-1bce1468b0e7</string>
- </map>
- <key>UIImgBtnTearOffInactiveUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
<integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>74e1a96f-4833-a24d-a1bb-1bce1468b0e7</string>
</map>
- <key>UIImgBtnTearOffPressedUUID</key>
+ <key>UIFloaterTitleVPad</key>
<map>
<key>Comment</key>
- <string />
+ <string>Distance from top of floater to top of title string, pixels</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>d2524c13-4ba6-af7c-e305-8ac6cc18d86a</string>
+ <real>7</real>
</map>
- <key>UIImgCheckboxActiveSelectedUUID</key>
+ <key>UIImgDefaultEyesUUID</key>
<map>
<key>Comment</key>
<string />
@@ -10055,9 +9144,9 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>cf4a2ed7-1533-4686-9dde-df9a37ddca55</string>
+ <string>6522e74d-1660-4e7f-b601-6f48c1659a77</string>
</map>
- <key>UIImgCheckboxActiveUUID</key>
+ <key>UIImgDefaultGlovesUUID</key>
<map>
<key>Comment</key>
<string />
@@ -10066,9 +9155,9 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>05bb64ee-96fd-4243-b74e-f40a41bc53ba</string>
+ <string>5748decc-f629-461c-9a36-a35a221fe21f</string>
</map>
- <key>UIImgCheckboxInactiveSelectedUUID</key>
+ <key>UIImgDefaultHairUUID</key>
<map>
<key>Comment</key>
<string />
@@ -10077,9 +9166,9 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>c817c642-9abd-4236-9287-ae0513fe7d2b</string>
+ <string>7ca39b4c-bd19-4699-aff7-f93fd03d3e7b</string>
</map>
- <key>UIImgCheckboxInactiveUUID</key>
+ <key>UIImgDefaultJacketUUID</key>
<map>
<key>Comment</key>
<string />
@@ -10088,9 +9177,9 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>7d94cb59-32a2-49bf-a516-9e5a2045f9d9</string>
+ <string>5748decc-f629-461c-9a36-a35a221fe21f</string>
</map>
- <key>UIImgCreateSelectedUUID</key>
+ <key>UIImgDefaultPantsUUID</key>
<map>
<key>Comment</key>
<string />
@@ -10099,9 +9188,9 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>0098b015-3daf-4cfe-a72f-915369ea97c2</string>
+ <string>5748decc-f629-461c-9a36-a35a221fe21f</string>
</map>
- <key>UIImgCreateUUID</key>
+ <key>UIImgDefaultShirtUUID</key>
<map>
<key>Comment</key>
<string />
@@ -10110,20 +9199,9 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>7a0b1bdb-b5d9-4df5-bac2-ba230da93b5b</string>
- </map>
- <key>UIImgCrosshairsUUID</key>
- <map>
- <key>Comment</key>
- <string>Image to use for crosshair display (UUID texture reference)</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>6e1a3980-bf2d-4274-8970-91e60d85fb52</string>
+ <string>5748decc-f629-461c-9a36-a35a221fe21f</string>
</map>
- <key>UIImgDefaultEyesUUID</key>
+ <key>UIImgDefaultShoesUUID</key>
<map>
<key>Comment</key>
<string />
@@ -10132,9 +9210,9 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>6522e74d-1660-4e7f-b601-6f48c1659a77</string>
+ <string>5748decc-f629-461c-9a36-a35a221fe21f</string>
</map>
- <key>UIImgDefaultGlovesUUID</key>
+ <key>UIImgDefaultSkirtUUID</key>
<map>
<key>Comment</key>
<string />
@@ -10145,7 +9223,7 @@
<key>Value</key>
<string>5748decc-f629-461c-9a36-a35a221fe21f</string>
</map>
- <key>UIImgDefaultHairUUID</key>
+ <key>UIImgDefaultSocksUUID</key>
<map>
<key>Comment</key>
<string />
@@ -10154,9 +9232,9 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>7ca39b4c-bd19-4699-aff7-f93fd03d3e7b</string>
+ <string>5748decc-f629-461c-9a36-a35a221fe21f</string>
</map>
- <key>UIImgDefaultJacketUUID</key>
+ <key>UIImgDefaultAlphaUUID</key>
<map>
<key>Comment</key>
<string />
@@ -10167,7 +9245,7 @@
<key>Value</key>
<string>5748decc-f629-461c-9a36-a35a221fe21f</string>
</map>
- <key>UIImgDefaultPantsUUID</key>
+ <key>UIImgDefaultUnderwearUUID</key>
<map>
<key>Comment</key>
<string />
@@ -10178,7 +9256,7 @@
<key>Value</key>
<string>5748decc-f629-461c-9a36-a35a221fe21f</string>
</map>
- <key>UIImgDefaultShirtUUID</key>
+ <key>StartUpChannelUUID</key>
<map>
<key>Comment</key>
<string />
@@ -10187,9 +9265,9 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>5748decc-f629-461c-9a36-a35a221fe21f</string>
- </map>
- <key>UIImgDefaultShoesUUID</key>
+ <string>B56AF90D-6684-48E4-B1E4-722D3DEB2CB6</string>
+ </map>
+ <key>NearByChatChannelUUID</key>
<map>
<key>Comment</key>
<string />
@@ -10198,9 +9276,9 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>5748decc-f629-461c-9a36-a35a221fe21f</string>
- </map>
- <key>UIImgDefaultSkirtUUID</key>
+ <string>E1158BD6-661C-4981-9DAD-4DCBFF062502</string>
+ </map>
+ <key>NotificationChannelUUID</key>
<map>
<key>Comment</key>
<string />
@@ -10209,9 +9287,9 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>5748decc-f629-461c-9a36-a35a221fe21f</string>
- </map>
- <key>UIImgDefaultSocksUUID</key>
+ <string>AEED3193-8709-4693-8558-7452CCA97AE5</string>
+ </map>
+ <key>AlertChannelUUID</key>
<map>
<key>Comment</key>
<string />
@@ -10220,9 +9298,9 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>5748decc-f629-461c-9a36-a35a221fe21f</string>
- </map>
- <key>UIImgDefaultUnderwearUUID</key>
+ <string>F3E07BC8-A973-476D-8C7F-F3B7293975D1</string>
+ </map>
+ <key>UIImgWhiteUUID</key>
<map>
<key>Comment</key>
<string />
@@ -10233,225 +9311,214 @@
<key>Value</key>
<string>5748decc-f629-461c-9a36-a35a221fe21f</string>
</map>
- <key>UIImgDirectionArrowUUID</key>
+ <key>UILineEditorCursorThickness</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI Line Editor Cursor Thickness</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>586383e8-4d9b-4fba-9196-2b5938e79c2c</string>
- </map>
- <key>UIImgFaceSelectedUUID</key>
+ <integer>2</integer>
+ </map>
+ <key>UIMaxComboWidth</key>
<map>
<key>Comment</key>
- <string />
+ <string>Maximum width of combo box</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>b4870163-6208-42a9-9801-93133bf9a6cd</string>
+ <real>500</real>
</map>
- <key>UIImgFaceUUID</key>
+ <key>UIMinimizedWidth</key>
<map>
<key>Comment</key>
- <string />
+ <string>Size of UI floater minimized width</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>ce15fd63-b0b6-463c-a37d-ea6393208b3e</string>
+ <real>160</real>
</map>
- <key>UIImgFocusSelectedUUID</key>
+ <key>UIMultiSliderctrlSpacing</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI multi slider ctrl spacing</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>ab6a730e-ddfd-4982-9a32-c6de3de6d31d</string>
+ <real>4</real>
</map>
- <key>UIImgFocusUUID</key>
+ <key>UIMultiTrackHeight</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI multi track height</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>57bc39d1-288c-4519-aea6-6d1786a5c274</string>
+ <real>6</real>
</map>
- <key>UIImgGrabSelectedUUID</key>
+ <key>UIPreeditMarkerBrightness</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI Preedit Marker Brightness</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>F32</string>
<key>Value</key>
- <string>c1e21504-f136-451d-b8e9-929037812f1d</string>
+ <real>0.4</real>
</map>
- <key>UIImgGrabUUID</key>
+ <key>UIPreeditMarkerGap</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI Preedit Marker Gap</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>c63f124c-6340-4fbf-b59e-0869a44adb64</string>
+ <real>1</real>
</map>
- <key>UIImgMoveSelectedUUID</key>
+ <key>UIPreeditMarkerPosition</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI Preedit Marker Position</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>46f17c7b-8381-48c3-b628-6a406e060dd6</string>
+ <integer>4</integer>
</map>
- <key>UIImgMoveUUID</key>
+ <key>UIPreeditMarkerThickness</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI Preedit Marker Thickness</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>2fa5dc06-bcdd-4e09-a426-f9f262d4fa65</string>
+ <real>1</real>
</map>
- <key>UIImgRadioActiveSelectedUUID</key>
+ <key>UIPreeditStandoutBrightness</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI Preedit Standout Brightness</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>F32</string>
<key>Value</key>
- <string>52f09e07-5816-4052-953c-94c6c10479b7</string>
+ <real>0.6</real>
</map>
- <key>UIImgRadioActiveUUID</key>
+ <key>UIPreeditStandoutGap</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI Preedit Standout Gap</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>7a1ba9b8-1047-4d1e-9cfc-bc478c80b63f</string>
+ <real>1</real>
</map>
- <key>UIImgRadioInactiveSelectedUUID</key>
+ <key>UIPreeditStandoutPosition</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI Preedit Standout Position</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>1975db39-aa29-4251-aea0-409ac09d414d</string>
+ <integer>4</integer>
</map>
- <key>UIImgRadioInactiveUUID</key>
+ <key>UIPreeditStandoutThickness</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI Preedit Standout Thickness</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>90688481-67ff-4af0-be69-4aa084bcad1e</string>
+ <integer>2</integer>
</map>
- <key>UIImgResizeBottomRightUUID</key>
+ <key>UIResizeBarHeight</key>
<map>
<key>Comment</key>
- <string />
+ <string>Size of UI resize bar height</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>e3690e25-9690-4f6c-a745-e7dcd885285a</string>
+ <real>3</real>
</map>
- <key>UIImgRotateSelectedUUID</key>
+ <key>UIResizeBarOverlap</key>
<map>
<key>Comment</key>
- <string />
+ <string>Size of UI resize bar overlap</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>cdfb7fde-0d13-418a-9d89-2bd91019fc95</string>
+ <real>1</real>
</map>
- <key>UIImgRotateUUID</key>
+ <key>UIScaleFactor</key>
<map>
<key>Comment</key>
- <string />
+ <string>Size of UI relative to default layout on 1024x768 screen</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>F32</string>
<key>Value</key>
- <string>c34b1eaa-aae3-4351-b082-e26c0b636779</string>
+ <real>1.0</real>
</map>
- <key>UIImgScaleSelectedUUID</key>
+ <key>UIScrollbarSize</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI scrollbar size</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>55aa57ef-508a-47f7-8867-85d21c5a810d</string>
+ <real>15</real>
</map>
- <key>UIImgScaleUUID</key>
+ <key>UISliderctrlHeight</key>
<map>
<key>Comment</key>
- <string />
+ <string>UI slider ctrl height</string>
<key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>88a90fef-b448-4883-9344-ecf378a60433</string>
- </map>
- <key>UIImgWhiteUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>5748decc-f629-461c-9a36-a35a221fe21f</string>
+ <real>16</real>
</map>
- <key>UIScaleFactor</key>
+ <key>UISliderctrlSpacing</key>
<map>
<key>Comment</key>
- <string>Size of UI relative to default layout on 1024x768 screen</string>
+ <string>UI slider ctrl spacing</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>F32</string>
+ <string>S32</string>
<key>Value</key>
- <real>1.0</real>
+ <real>4</real>
</map>
<key>UISndAlert</key>
<map>
@@ -10640,181 +9707,214 @@
<key>Value</key>
<string>00000000-0000-0000-0000-000000000000</string>
</map>
- <key>UISndPieMenuAppear</key>
+ <key>UISndSnapshot</key>
<map>
<key>Comment</key>
- <string>Sound file for opening pie menu (uuid for sound asset)</string>
+ <string>Sound file for taking a snapshot (uuid for sound asset)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>8eaed61f-92ff-6485-de83-4dcc938a478e</string>
+ <string>3d09f582-3851-c0e0-f5ba-277ac5c73fb4</string>
</map>
- <key>UISndPieMenuHide</key>
+ <key>UISndStartIM</key>
<map>
<key>Comment</key>
- <string>Sound file for closing pie menu (uuid for sound asset)</string>
+ <string>Sound file for starting a new IM session (uuid for sound asset)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>00000000-0000-0000-0000-000000000000</string>
+ <string>c825dfbc-9827-7e02-6507-3713d18916c1</string>
</map>
- <key>UISndPieMenuSliceHighlight0</key>
+ <key>UISndTeleportOut</key>
<map>
<key>Comment</key>
- <string>Sound file for selecting pie menu item 0 (uuid for sound asset)</string>
+ <string>Sound file for teleporting (uuid for sound asset)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>d9f73cf8-17b4-6f7a-1565-7951226c305d</string>
+ <string>d7a9a565-a013-2a69-797d-5332baa1a947</string>
</map>
- <key>UISndPieMenuSliceHighlight1</key>
+ <key>UISndTyping</key>
<map>
<key>Comment</key>
- <string>Sound file for selecting pie menu item 1 (uuid for sound asset)</string>
+ <string>Sound file for starting to type a chat message (uuid for sound asset)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>f6ba9816-dcaf-f755-7b67-51b31b6233e5</string>
+ <string>5e191c7b-8996-9ced-a177-b2ac32bfea06</string>
</map>
- <key>UISndPieMenuSliceHighlight2</key>
+ <key>UISndWindowClose</key>
<map>
<key>Comment</key>
- <string>Sound file for selecting pie menu item 2 (uuid for sound asset)</string>
+ <string>Sound file for closing a window (uuid for sound asset)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>7aff2265-d05b-8b72-63c7-dbf96dc2f21f</string>
+ <string>2c346eda-b60c-ab33-1119-b8941916a499</string>
</map>
- <key>UISndPieMenuSliceHighlight3</key>
+ <key>UISndWindowOpen</key>
<map>
<key>Comment</key>
- <string>Sound file for selecting pie menu item 3 (uuid for sound asset)</string>
+ <string>Sound file for opening a window (uuid for sound asset)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>09b2184e-8601-44e2-afbb-ce37434b8ba1</string>
+ <string>c80260ba-41fd-8a46-768a-6bf236360e3a</string>
</map>
- <key>UISndPieMenuSliceHighlight4</key>
+ <key>UISpinctrlBtnHeight</key>
<map>
<key>Comment</key>
- <string>Sound file for selecting pie menu item 4 (uuid for sound asset)</string>
+ <string>UI spin control button height</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>bbe4c7fc-7044-b05e-7b89-36924a67593c</string>
+ <integer>11</integer>
</map>
- <key>UISndPieMenuSliceHighlight5</key>
+ <key>UISpinctrlBtnWidth</key>
<map>
<key>Comment</key>
- <string>Sound file for selecting pie menu item 5 (uuid for sound asset)</string>
+ <string>UI spin control button width</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>d166039b-b4f5-c2ec-4911-c85c727b016c</string>
+ <integer>16</integer>
</map>
- <key>UISndPieMenuSliceHighlight6</key>
+ <key>UISpinctrlDefaultLabelWidth</key>
<map>
<key>Comment</key>
- <string>Sound file for selecting pie menu item 6 (uuid for sound asset)</string>
+ <string>UI spin control default label width</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>242af82b-43c2-9a3b-e108-3b0c7e384981</string>
+ <integer>10</integer>
</map>
- <key>UISndPieMenuSliceHighlight7</key>
+ <key>UISpinctrlSpacing</key>
<map>
<key>Comment</key>
- <string>Sound file for selecting pie menu item 7 (uuid for sound asset)</string>
+ <string>UI spin control spacing</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>c1f334fb-a5be-8fe7-22b3-29631c21cf0b</string>
+ <integer>2</integer>
</map>
- <key>UISndSnapshot</key>
+ <key>UITabCntrArrowBtnSize</key>
<map>
<key>Comment</key>
- <string>Sound file for taking a snapshot (uuid for sound asset)</string>
+ <string>UI Tab Container Arrow Button Size</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>3d09f582-3851-c0e0-f5ba-277ac5c73fb4</string>
+ <integer>16</integer>
</map>
- <key>UISndStartIM</key>
+ <key>UITabCntrvArrowBtnSize</key>
<map>
<key>Comment</key>
- <string>Sound file for starting a new IM session (uuid for sound asset)</string>
+ <string>UI Tab Container V Arrow Button Size</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>c825dfbc-9827-7e02-6507-3713d18916c1</string>
+ <integer>16</integer>
</map>
- <key>UISndTeleportOut</key>
+ <key>UITabCntrvPad</key>
<map>
<key>Comment</key>
- <string>Sound file for teleporting (uuid for sound asset)</string>
+ <string>UI Tab Container V Pad</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>d7a9a565-a013-2a69-797d-5332baa1a947</string>
+ <integer>0</integer>
</map>
- <key>UISndTyping</key>
+ <key>UITabCntrButtonPanelOverlap</key>
<map>
<key>Comment</key>
- <string>Sound file for starting to type a chat message (uuid for sound asset)</string>
+ <string>UI Tab Container Button Panel Overlap</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>5e191c7b-8996-9ced-a177-b2ac32bfea06</string>
+ <integer>1</integer>
</map>
- <key>UISndWindowClose</key>
+ <key>UITabCntrCloseBtnSize</key>
<map>
<key>Comment</key>
- <string>Sound file for closing a window (uuid for sound asset)</string>
+ <string>UI Tab Container Close Button Size</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>2c346eda-b60c-ab33-1119-b8941916a499</string>
+ <integer>16</integer>
</map>
- <key>UISndWindowOpen</key>
+ <key>UITabCntrTabHPad</key>
<map>
<key>Comment</key>
- <string>Sound file for opening a window (uuid for sound asset)</string>
+ <string>UI Tab Container Tab Horizontal Pad</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>S32</string>
<key>Value</key>
- <string>c80260ba-41fd-8a46-768a-6bf236360e3a</string>
+ <integer>4</integer>
+ </map>
+ <key>UITabCntrTabPartialWidth</key>
+ <map>
+ <key>Comment</key>
+ <string>UI Tab Container Tab Partial Width</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>12</integer>
+ </map>
+ <key>UITabCntrVertTabMinWidth</key>
+ <map>
+ <key>Comment</key>
+ <string>UI Tab Container Vertical Tab Minimum Width</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>100</integer>
+ </map>
+ <key>UITabPadding</key>
+ <map>
+ <key>Comment</key>
+ <string>UI Tab Padding</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>15</integer>
</map>
<key>UploadBakedTexOld</key>
<map>
@@ -10849,6 +9949,28 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>UseCircuitCodeMaxRetries</key>
+ <map>
+ <key>Comment</key>
+ <string>Max timeout count for the initial UseCircuitCode message</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <real>3</real>
+ </map>
+ <key>UseCircuitCodeTimeout</key>
+ <map>
+ <key>Comment</key>
+ <string>Timeout duration in seconds for the initial UseCircuitCode message</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>5.0</real>
+ </map>
<key>UseDebugLogin</key>
<map>
<key>Comment</key>
@@ -10937,6 +10059,18 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>SpeakerParticipantRemoveDelay</key>
+ <map>
+ <key>Comment</key>
+ <string>Timeout to remove participants who is not in channel before removed from list of active speakers (text/voice chat)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>10.0</real>
+ </map>
+
<key>UseStartScreen</key>
<map>
<key>Comment</key>
@@ -11086,7 +10220,7 @@
<key>Comment</key>
<string>Versioning Channel Name.</string>
<key>Persist</key>
- <integer>1</integer>
+ <integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
@@ -11169,6 +10303,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>VoiceDefaultInternalLevel</key>
+ <map>
+ <key>Comment</key>
+ <string>Internal level of voice set by default. Is equivalent to 0.5 (from 0.0-1.0 range) external voice level (internal = 400 * external^2).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>100</integer>
+ </map>
<key>VoiceEarLocation</key>
<map>
<key>Comment</key>
@@ -11290,346 +10435,49 @@
<key>Value</key>
<string>Default</string>
</map>
- <key>VoicePort</key>
+ <key>VoiceParticipantLeftRemoveDelay</key>
<map>
<key>Comment</key>
- <string>Client SLVoice port to connect to</string>
+ <string>Timeout to remove participants who has left Voice chat from the list in Voice Controls Panel</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>U32</string>
+ <string>S32</string>
<key>Value</key>
- <integer>44125</integer>
+ <integer>10</integer>
</map>
- <key>WLSkyDetail</key>
+ <key>VoicePort</key>
<map>
<key>Comment</key>
- <string>Controls vertex detail on the WindLight sky. Lower numbers will give better performance and uglier skies.</string>
+ <string>Client SLVoice port to connect to</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
- <integer>64</integer>
- </map>
- <key>WarnAboutBadPCI</key>
- <map>
- <key>Comment</key>
- <string>Enables AboutBadPCI warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnAboutDirectX9</key>
- <map>
- <key>Comment</key>
- <string>Enables AboutDirectX9 warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnAboutOldGraphicsDriver</key>
- <map>
- <key>Comment</key>
- <string>Enables AboutOldGraphicsDriver warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnAboutPCIGraphics</key>
- <map>
- <key>Comment</key>
- <string>Enables AboutPCIGraphics warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnBrowserLaunch</key>
- <map>
- <key>Comment</key>
- <string>Enables BrowserLaunch warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnDeedObject</key>
- <map>
- <key>Comment</key>
- <string>Enables DeedObject warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnFirstAppearance</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstAppearance warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnFirstAttach</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstAttach warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnFirstBalanceDecrease</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstBalanceDecrease warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnFirstBalanceIncrease</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstBalanceIncrease warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnFirstBuild</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstBuild warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnFirstDebugMenus</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstDebugMenus warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnFirstFlexible</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstFlexible warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnFirstGoTo</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstGoTo warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnFirstInventory</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstInventory warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnFirstLeftClickNoHit</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstLeftClickNoHit warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnFirstMap</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstMap warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnFirstMedia</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstMedia warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnFirstOverrideKeys</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstOverrideKeys warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnFirstSandbox</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstSandbox warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnFirstSculptedPrim</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstSculptedPrim warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnFirstSit</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstSit warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnFirstStreamingMusic</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstStreamingMusic warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnFirstStreamingVideo</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstStreamingVideo warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnFirstTeleport</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstTeleport warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnFirstVoice</key>
- <map>
- <key>Comment</key>
- <string>Enables FirstVoice warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>WarnNewClassified</key>
- <map>
- <key>Comment</key>
- <string>Enables NewClassified warning dialog</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
+ <integer>44125</integer>
</map>
- <key>WarnQuickTimeInstalled</key>
+ <key>WarningsAsChat</key>
<map>
<key>Comment</key>
- <string>Enables QuickTimeInstalled warning dialog</string>
+ <string>Display warning messages in chat history</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>1</integer>
+ <integer>0</integer>
</map>
- <key>WarnReturnToOwner</key>
+ <key>WLSkyDetail</key>
<map>
<key>Comment</key>
- <string>Enables ReturnToOwner warning dialog</string>
+ <string>Controls vertex detail on the WindLight sky. Lower numbers will give better performance and uglier skies.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Boolean</string>
+ <string>U32</string>
<key>Value</key>
- <integer>1</integer>
+ <integer>64</integer>
</map>
<key>WatchdogEnabled</key>
<map>
@@ -11697,6 +10545,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>WindowFullScreen</key>
+ <map>
+ <key>Comment</key>
+ <string>Run SL in fullscreen mode</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>WindowHeight</key>
<map>
<key>Comment</key>
@@ -11763,6 +10622,17 @@
<key>Value</key>
<real>150000.0</real>
</map>
+ <key>XUIEditor</key>
+ <map>
+ <key>Comment</key>
+ <string>Path to program used to edit XUI files</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <real>150000.0</real>
+ </map>
<key>YawFromMousePosition</key>
<map>
<key>Comment</key>
@@ -11774,6 +10644,17 @@
<key>Value</key>
<real>90.0</real>
</map>
+ <key>YouAreHereDistance</key>
+ <map>
+ <key>Comment</key>
+ <string>Radius of distance for banner that indicates if the resident is "on" the Place.(meters from avatar to requested place)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>10.0</real>
+ </map>
<key>YieldTime</key>
<map>
<key>Comment</key>
@@ -11807,22 +10688,6 @@
<key>Value</key>
<real>0.40000000596</real>
</map>
- <key>llOwnerSayChatColor</key>
- <map>
- <key>Comment</key>
- <string>Color of chat messages from objects only visible to the owner</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.990000009537</real>
- <real>0.990000009537</real>
- <real>0.689999997616</real>
- <real>1.0</real>
- </array>
- </map>
<key>particlesbeacon</key>
<map>
<key>Comment</key>
@@ -11889,6 +10754,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>ShowDeviceSettings</key>
+ <map>
+ <key>Comment</key>
+ <string>Show device settings</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>soundsbeacon</key>
<map>
<key>Comment</key>
@@ -11900,5 +10776,38 @@
<key>Value</key>
<integer>0</integer>
</map>
- </map>
+ <key>LogTextureDownloadsToViewerLog</key>
+ <map>
+ <key>Comment</key>
+ <string>Send texture download details to the viewer log</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>LogTextureDownloadsToSimulator</key>
+ <map>
+ <key>Comment</key>
+ <string>Send a digest of texture info to the sim</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>TextureLoggingThreshold</key>
+ <map>
+ <key>Comment</key>
+ <string>Specifies the byte threshold at which texture download data should be sent to the sim.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+</map>
</llsd>
diff --git a/indra/newview/app_settings/settings_files.xml b/indra/newview/app_settings/settings_files.xml
index ec55745358..aa5b301959 100644
--- a/indra/newview/app_settings/settings_files.xml
+++ b/indra/newview/app_settings/settings_files.xml
@@ -4,10 +4,10 @@
<map>
<!--
The Locations LLSD block specifies the usage pattern of
- the settings file types listed above.
+ the settings file types
Each location is represented by a LLSD containing the following values:
PathIndex = hard coded path indicies.
- Files = map of files to load, from above 'Files' section.
+ Files = map of files to load
Each file can have:
Requirement = level of necessity for loading.
0 ( or Req. no key) = do not load
@@ -50,6 +50,13 @@
<key>Requirement</key>
<integer>1</integer>
</map>
+ <key>Warnings</key>
+ <map>
+ <key>Name</key>
+ <string>ignorable_dialogs.xml</string>
+ <key>Requirement</key>
+ <integer>1</integer>
+ </map>
</map>
</map>
<key>User</key>
@@ -70,6 +77,13 @@
<key>Name</key>
<string>settings_crash_behavior.xml</string>
</map>
+ <key>Warnings</key>
+ <map>
+ <key>Name</key>
+ <string>ignorable_dialogs.xml</string>
+ <key>NameFromSetting</key>
+ <string>WarningSettingsFile</string>
+ </map>
</map>
</map>
<key>Account</key>
@@ -82,6 +96,49 @@
<map>
<key>Name</key>
<string>settings_per_account.xml</string>
+ <key>NameFromSetting</key>
+ <string>PerAccountSettingsFile</string>
+ </map>
+ </map>
+ </map>
+ <key>DefaultSkin</key>
+ <map>
+ <key>PathIndex</key>
+ <integer>17</integer>
+ <key>Files</key>
+ <map>
+ <key>Skinning</key>
+ <map>
+ <key>Name</key>
+ <string>colors.xml</string>
+ </map>
+ </map>
+ </map>
+ <key>CurrentSkin</key>
+ <map>
+ <key>PathIndex</key>
+ <integer>10</integer>
+ <key>Files</key>
+ <map>
+ <key>Skinning</key>
+ <map>
+ <key>Name</key>
+ <string>colors.xml</string>
+ </map>
+ </map>
+ </map>
+ <key>UserSkin</key>
+ <map>
+ <key>PathIndex</key>
+ <integer>14</integer>
+ <key>Files</key>
+ <map>
+ <key>Skinning</key>
+ <map>
+ <key>Name</key>
+ <string>colors.xml</string>
+ <key>NameFromSetting</key>
+ <string>SkinningSettingsFile</string>
</map>
</map>
</map>
diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml
index dab88a5ec3..af5fa4f388 100644
--- a/indra/newview/app_settings/settings_per_account.xml
+++ b/indra/newview/app_settings/settings_per_account.xml
@@ -22,17 +22,17 @@
<key>Value</key>
<string>|TOKEN COPY BusyModeResponse|</string>
</map>
- <key>IMLogTimestamp</key>
+ <key>InstantMessageLogFolder</key>
<map>
<key>Comment</key>
- <string>Log Timestamp of Instant Messages</string>
+ <string>Top level folder to your log files.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Boolean</string>
+ <string>String</string>
<key>Value</key>
- <integer>1</integer>
- </map>
+ <string />
+ </map>
<key>InstantMessageLogPath</key>
<map>
<key>Comment</key>
@@ -64,29 +64,18 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
- </map>
- <key>LogChatIM</key>
- <map>
- <key>Comment</key>
- <string>Log Incoming Instant Messages with Chat</string>
- <key>Persist</key>
<integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
</map>
- <key>LogChatTimestamp</key>
+ <key>LogTimestamp</key>
<map>
<key>Comment</key>
- <string>Log Timestamp of Chat</string>
+ <string>Log Timestamp</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
<key>LogInstantMessages</key>
<map>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
index a91e9fa15b..4fb109d687 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
@@ -8,14 +8,10 @@
#extension GL_ARB_texture_rectangle : enable
uniform sampler2D diffuseMap;
-uniform sampler2DShadow shadowMap0;
-uniform sampler2DShadow shadowMap1;
-uniform sampler2DShadow shadowMap2;
-uniform sampler2DShadow shadowMap3;
uniform sampler2D noiseMap;
-uniform sampler2DRect positionMap;
+uniform sampler2DRect depthMap;
-uniform mat4 shadow_matrix[4];
+uniform mat4 shadow_matrix[6];
uniform vec4 shadow_clip;
uniform vec2 screen_res;
@@ -26,52 +22,42 @@ varying vec3 vary_ambient;
varying vec3 vary_directional;
varying vec3 vary_fragcoord;
varying vec3 vary_position;
+varying vec3 vary_light;
uniform float alpha_soften;
+uniform mat4 inv_proj;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
void main()
{
vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
frag *= screen_res;
- vec3 samp_pos = texture2DRect(positionMap, frag).xyz;
+ vec3 samp_pos = getPosition(frag).xyz;
- float shadow = 1.0;
vec4 pos = vec4(vary_position, 1.0);
- if (pos.z > -shadow_clip.w)
- {
- if (pos.z < -shadow_clip.z)
- {
- vec4 lpos = shadow_matrix[3]*pos;
- shadow = shadow2DProj(shadowMap3, lpos).x;
- shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
- }
- else if (pos.z < -shadow_clip.y)
- {
- vec4 lpos = shadow_matrix[2]*pos;
- shadow = shadow2DProj(shadowMap2, lpos).x;
- }
- else if (pos.z < -shadow_clip.x)
- {
- vec4 lpos = shadow_matrix[1]*pos;
- shadow = shadow2DProj(shadowMap1, lpos).x;
- }
- else
- {
- vec4 lpos = shadow_matrix[0]*pos;
- shadow = shadow2DProj(shadowMap0, lpos).x;
- }
- }
-
- vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, gl_Color.a);
+ vec4 col = vec4(vary_ambient + vary_directional.rgb, gl_Color.a);
vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * col;
color.rgb = atmosLighting(color.rgb);
color.rgb = scaleSoftClip(color.rgb);
- if (samp_pos.z != 0.0)
+ if (samp_pos.z != 0.0 && gl_Color.a < 1.0)
{
float dist_factor = alpha_soften;
float a = gl_Color.a;
@@ -83,6 +69,7 @@ void main()
//gl_FragColor = gl_Color;
gl_FragColor = color;
//gl_FragColor = vec4(1,0,1,1);
+ //gl_FragColor = vec4(1,0,1,1)*shadow;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
index b496bd674f..1a7d58b07b 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
@@ -20,8 +20,11 @@ varying vec3 vary_ambient;
varying vec3 vary_directional;
varying vec3 vary_fragcoord;
varying vec3 vary_position;
+varying vec3 vary_light;
uniform float near_clip;
+uniform float shadow_offset;
+uniform float shadow_bias;
void main()
{
@@ -32,8 +35,9 @@ void main()
vec4 pos = (gl_ModelViewMatrix * gl_Vertex);
vec3 norm = normalize(gl_NormalMatrix * gl_Normal);
- vary_position = pos.xyz;
+ vary_position = pos.xyz + norm.xyz * (-pos.z/64.0*shadow_offset+shadow_bias);
+
calcAtmospherics(pos.xyz);
//vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.));
@@ -54,6 +58,8 @@ void main()
col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz);
col.rgb = scaleDownLight(col.rgb);
+ vary_light = gl_LightSource[0].position.xyz;
+
vary_ambient = col.rgb*gl_Color.rgb;
vary_directional.rgb = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a)));
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl
index 6c94f5c5a7..ff64a6b0c3 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl
@@ -12,7 +12,7 @@ uniform sampler2DShadow shadowMap2;
uniform sampler2DShadow shadowMap3;
uniform sampler2D noiseMap;
-uniform mat4 shadow_matrix[4];
+uniform mat4 shadow_matrix[6];
uniform vec4 shadow_clip;
vec3 atmosLighting(vec3 light);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
index 58aa5a9cb5..75df388941 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
@@ -8,13 +8,18 @@
uniform sampler2D diffuseMap;
varying vec3 vary_normal;
-varying vec4 vary_position;
void main()
{
- gl_FragData[0] = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy);
+ vec4 diff = gl_Color*texture2D(diffuseMap, gl_TexCoord[0].xy);
+
+ if (diff.a < 0.2)
+ {
+ discard;
+ }
+
+ gl_FragData[0] = vec4(diff.rgb, 0.0);
gl_FragData[1] = vec4(0,0,0,0);
- gl_FragData[2] = vec4(normalize(vary_normal), 0.0);
- gl_FragData[3] = vary_position;
+ gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl
index 27c09db922..00083eb6b3 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl
@@ -10,6 +10,7 @@ uniform sampler2D diffuseMap;
void main()
{
- gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy));
+ gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy).a);
+ //gl_FragColor = vec4(1,1,1,1);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl
index 14da6b1ad4..8c8489d087 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl
@@ -28,8 +28,7 @@ void main()
norm = normalize(norm);
pos = gl_ProjectionMatrix * pos;
- //smash geometry against near clip plane
- pos.z = max(pos.z, -1.0);
+ pos.z = max(pos.z, -pos.w+0.01);
gl_Position = pos;
gl_FrontColor = gl_Color;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl
index 12a7ff7f29..471a1f0407 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl
@@ -10,7 +10,6 @@ mat4 getSkinnedTransform();
attribute vec4 weight;
varying vec3 vary_normal;
-varying vec4 vary_position;
void main()
{
@@ -30,7 +29,6 @@ void main()
norm.z = dot(trans[2].xyz, gl_Normal);
norm = normalize(norm);
- vary_position = pos;
vary_normal = norm;
gl_Position = gl_ProjectionMatrix * pos;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
index 3c6700a871..bd5e9dd758 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
@@ -7,10 +7,12 @@
#extension GL_ARB_texture_rectangle : enable
-uniform sampler2DRect positionMap;
+uniform sampler2DRect depthMap;
uniform sampler2DRect normalMap;
uniform sampler2DRect lightMap;
+uniform sampler2DRect giLightMap;
+uniform float dist_factor;
uniform float blur_size;
uniform vec2 delta;
uniform vec3 kern[32];
@@ -19,30 +21,52 @@ uniform float kern_scale;
varying vec2 vary_fragcoord;
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
void main()
{
- vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz;
- vec3 pos = texture2DRect(positionMap, vary_fragcoord.xy).xyz;
- vec2 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rg;
+ vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0;
+ vec3 pos = getPosition(vary_fragcoord.xy).xyz;
+ vec4 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rgba;
vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy);
+ dlt /= max(-pos.z*dist_factor, 1.0);
+
vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free'
- vec2 col = defined_weight * ccol;
+ vec4 col = defined_weight.xyxx * ccol;
for (int i = 1; i < kern_length; i++)
{
vec2 tc = vary_fragcoord.xy + kern[i].z*dlt;
- vec3 samppos = texture2DRect(positionMap, tc).xyz;
+ vec3 samppos = getPosition(tc).xyz;
float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
if (d*d <= 0.003)
{
- col += texture2DRect(lightMap, tc).rg*kern[i].xy;
+ col += texture2DRect(lightMap, tc)*kern[i].xyxx;
defined_weight += kern[i].xy;
}
}
- col /= defined_weight;
- gl_FragColor = vec4(col.r, col.g, 0.0, 1.0);
+
+ col /= defined_weight.xyxx;
+
+ gl_FragColor = col;
+
+ //gl_FragColor = ccol;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
index a8712bc8cc..1c29dae5f7 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
@@ -11,7 +11,6 @@ uniform sampler2D bumpMap;
varying vec3 vary_mat0;
varying vec3 vary_mat1;
varying vec3 vary_mat2;
-varying vec4 vary_position;
void main()
{
@@ -22,8 +21,7 @@ void main()
dot(norm,vary_mat1),
dot(norm,vary_mat2));
- gl_FragData[0].rgb = gl_Color.rgb*col;
- gl_FragData[1] = vec4(col*(gl_Color.a*1.5), gl_Color.a);
- gl_FragData[2] = vec4(normalize(tnorm), 0.0);
- gl_FragData[3] = vary_position;
+ gl_FragData[0] = vec4(gl_Color.rgb*col, 0.0);
+ gl_FragData[1] = vec4(col*gl_Color.a, gl_Color.a);
+ gl_FragData[2] = vec4(normalize(tnorm)*0.5+0.5, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl
index ba180922cc..9589912c6c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl
@@ -8,7 +8,6 @@
varying vec3 vary_mat0;
varying vec3 vary_mat1;
varying vec3 vary_mat2;
-varying vec4 vary_position;
void main()
{
@@ -16,8 +15,6 @@ void main()
gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
- vary_position = gl_ModelViewMatrix * gl_Vertex;
-
vec3 n = normalize(gl_NormalMatrix * gl_Normal);
vec3 b = normalize(gl_NormalMatrix * gl_MultiTexCoord2.xyz);
vec3 t = cross(b, n);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
index f2ba2df69a..5895ebda84 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
@@ -8,13 +8,11 @@
uniform sampler2D diffuseMap;
varying vec3 vary_normal;
-varying vec4 vary_position;
void main()
{
vec3 col = texture2D(diffuseMap, gl_TexCoord[0].xy).rgb;
- gl_FragData[0] = vec4(gl_Color.rgb*col, 1.0);
+ gl_FragData[0] = vec4(gl_Color.rgb*col, 0.0);
gl_FragData[1] = vec4(col*(gl_Color.a*1.5), gl_Color.a);
- gl_FragData[2] = vec4(normalize(vary_normal), 0.0);
- gl_FragData[3] = vary_position;
+ gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
index 3413a7f9d6..44468cdfa2 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
@@ -6,16 +6,13 @@
*/
varying vec3 vary_normal;
-varying vec4 vary_position;
void main()
{
//transform vertex
- gl_Position = ftransform();
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
- vary_position = gl_ModelViewMatrix * gl_Vertex;
-
vary_normal = normalize(gl_NormalMatrix * gl_Normal);
gl_FrontColor = gl_Color;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
index 2a811c5897..e518bddb98 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
@@ -8,14 +8,9 @@
#extension GL_ARB_texture_rectangle : enable
uniform sampler2D diffuseMap;
-uniform sampler2DShadow shadowMap0;
-uniform sampler2DShadow shadowMap1;
-uniform sampler2DShadow shadowMap2;
-uniform sampler2DShadow shadowMap3;
+uniform sampler2DRect depthMap;
uniform sampler2D noiseMap;
-uniform sampler2DRect positionMap;
-uniform mat4 shadow_matrix[4];
uniform vec4 shadow_clip;
uniform vec2 screen_res;
@@ -30,12 +25,27 @@ varying vec3 vary_fragcoord;
uniform float alpha_soften;
+uniform mat4 inv_proj;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
void main()
{
vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
frag *= screen_res;
- vec3 samp_pos = texture2DRect(positionMap, frag).xyz;
+ vec3 samp_pos = getPosition(frag).xyz;
float shadow = 1.0;
vec4 pos = vary_position;
@@ -46,10 +56,10 @@ void main()
color.rgb = fullbrightScaleSoftClip(color.rgb);
- if (samp_pos.z != 0.0)
+ if (samp_pos.z != 0.0 && color.a < 1.0)
{
float dist_factor = alpha_soften;
- float a = gl_Color.a;
+ float a = color.a;
a *= a;
dist_factor *= 1.0/(1.0-a);
color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
index 6381a1ced8..aff51178b0 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
@@ -12,12 +12,12 @@ vec3 atmosAffectDirectionalLight(float lightIntensity);
vec3 scaleDownLight(vec3 light);
vec3 scaleUpLight(vec3 light);
-varying vec4 vary_position;
varying vec3 vary_ambient;
varying vec3 vary_directional;
varying vec3 vary_normal;
varying vec3 vary_fragcoord;
uniform float near_clip;
+varying vec4 vary_position;
void main()
{
diff --git a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl
new file mode 100644
index 0000000000..b351eec6e5
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl
@@ -0,0 +1,165 @@
+/**
+ * @file giF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform sampler2D noiseMap;
+
+uniform sampler2D diffuseGIMap;
+uniform sampler2D normalGIMap;
+uniform sampler2D depthGIMap;
+
+uniform sampler2D lightFunc;
+
+// Inputs
+varying vec2 vary_fragcoord;
+
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+uniform mat4 gi_mat; //gPipeline.mGIMatrix - eye space to sun space
+uniform mat4 gi_mat_proj; //gPipeline.mGIMatrixProj - eye space to projected sun space
+uniform mat4 gi_norm_mat; //gPipeline.mGINormalMatrix - eye space normal to sun space normal matrix
+uniform mat4 gi_inv_proj; //gPipeline.mGIInvProj - projected sun space to sun space
+uniform float gi_radius;
+uniform float gi_intensity;
+uniform int gi_samples;
+uniform vec2 gi_kern[25];
+uniform vec2 gi_scale;
+uniform vec3 gi_quad;
+uniform vec3 gi_spec;
+uniform float gi_direction_weight;
+uniform float gi_light_offset;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+vec4 getGIPosition(vec2 gi_tc)
+{
+ float depth = texture2D(depthGIMap, gi_tc).a;
+ vec2 sc = gi_tc*2.0;
+ sc -= vec2(1.0, 1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = gi_inv_proj*ndc;
+ pos.xyz /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+vec3 giAmbient(vec3 pos, vec3 norm)
+{
+ vec4 gi_c = gi_mat_proj * vec4(pos, 1.0);
+ gi_c.xyz /= gi_c.w;
+
+ vec4 gi_pos = gi_mat*vec4(pos,1.0);
+ vec3 gi_norm = (gi_norm_mat*vec4(norm,1.0)).xyz;
+ gi_norm = normalize(gi_norm);
+
+ vec2 tcx = gi_norm.xy;
+ vec2 tcy = gi_norm.yx;
+
+ vec4 eye_pos = gi_mat*vec4(0,0,0,1.0);
+
+ vec3 eye_dir = normalize(gi_pos.xyz-eye_pos.xyz/eye_pos.w);
+
+ //vec3 eye_dir = vec3(0,0,-1);
+ //eye_dir = (gi_norm_mat*vec4(eye_dir, 1.0)).xyz;
+ //eye_dir = normalize(eye_dir);
+
+ //float round_x = gi_scale.x;
+ //float round_y = gi_scale.y;
+
+ vec3 debug = texture2D(normalGIMap, gi_c.xy).rgb*0.5+0.5;
+ debug.xz = vec2(0.0,0.0);
+ //debug = fract(debug);
+
+ float round_x = 1.0/64.0;
+ float round_y = 1.0/64.0;
+
+ //gi_c.x = floor(gi_c.x/round_x+0.5)*round_x;
+ //gi_c.y = floor(gi_c.y/round_y+0.5)*round_y;
+
+ float fda = 0.0;
+ vec3 fdiff = vec3(0,0,0);
+
+ vec3 rcol = vec3(0,0,0);
+
+ float fsa = 0.0;
+
+ for (int i = -1; i < 2; i+=2 )
+ {
+ for (int j = -1; j < 2; j+=2)
+ {
+ vec2 tc = vec2(i, j)*0.75;
+ vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0+tc*0.5).xyz;
+ //tc += gi_norm.xy*nz.z;
+ tc += nz.xy*2.0;
+ tc /= gi_samples;
+ tc += gi_c.xy;
+
+ vec3 lnorm = -normalize(texture2D(normalGIMap, tc.xy).xyz*2.0-1.0);
+ vec3 lpos = getGIPosition(tc.xy).xyz;
+
+ vec3 at = lpos-gi_pos.xyz;
+ float dist = dot(at,at);
+ float da = clamp(1.0/(gi_spec.x*dist), 0.0, 1.0);
+
+ if (da > 0.0)
+ {
+ //add angular attenuation
+ vec3 ldir = at;
+ float ang_atten = clamp(dot(ldir, gi_norm), 0.0, 1.0);
+
+ float ld = -dot(ldir, lnorm);
+
+ if (ang_atten > 0.0 && ld < 0.0)
+ {
+ vec3 diff = texture2D(diffuseGIMap, tc.xy).xyz;
+ da = da*ang_atten;
+ fda += da;
+ fdiff += diff*da;
+ }
+ }
+ }
+ }
+
+ fdiff /= max(gi_spec.y*fda, gi_quad.z);
+ fdiff = clamp(fdiff, vec3(0), vec3(1));
+
+ vec3 ret = fda*fdiff;
+ //ret = ret*ret*gi_quad.x+ret*gi_quad.y+gi_quad.z;
+
+ //fda *= nz.z;
+
+ //rcol.rgb *= gi_intensity;
+ //return rcol.rgb+vary_AmblitColor.rgb*0.25;
+ //return vec4(debug, 0.0);
+ //return vec4(fda*fdiff, 0.0);
+ return clamp(ret,vec3(0.0), vec3(1.0));
+ //return debug.xyz;
+}
+
+void main()
+{
+ vec2 pos_screen = vary_fragcoord.xy;
+ vec4 pos = getPosition(pos_screen);
+ vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0;
+
+ gl_FragData[0].xyz = giAmbient(pos, norm);
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/giV.glsl b/indra/newview/app_settings/shaders/class1/deferred/giV.glsl
new file mode 100644
index 0000000000..71dcea9628
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/giV.glsl
@@ -0,0 +1,22 @@
+/**
+ * @file giV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res;
+ vec4 tex = gl_MultiTexCoord0;
+ tex.w = 1.0;
+
+ gl_FrontColor = gl_Color;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
index 20a3f3df5b..8c140a7b4f 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
@@ -9,12 +9,9 @@ uniform sampler2D diffuseMap;
uniform sampler2D normalMap;
uniform sampler2D specularMap;
-varying vec4 vary_position;
-
void main()
{
gl_FragData[0] = texture2D(diffuseMap, gl_TexCoord[0].xy);
gl_FragData[1] = texture2D(specularMap, gl_TexCoord[0].xy);
- gl_FragData[2] = vec4(texture2D(normalMap, gl_TexCoord[0].xy).xyz, vary_position.z);
- gl_FragData[3] = vary_position;
+ gl_FragData[2] = vec4(texture2D(normalMap, gl_TexCoord[0].xy).xyz, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl
index 9c5ae31541..57532a30b3 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl
@@ -5,15 +5,11 @@
* $License$
*/
-varying vec4 vary_position;
-
void main()
{
//transform vertex
gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
- vary_position = gl_ModelViewMatrix * gl_Vertex;
-
gl_FrontColor = gl_Color;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl
new file mode 100644
index 0000000000..e8b53b0293
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl
@@ -0,0 +1,15 @@
+/**
+ * @file luminanceF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+uniform sampler2DRect diffuseMap;
+
+varying vec2 vary_fragcoord;
+
+void main()
+{
+ gl_FragColor = texture2DRect(diffuseMap, vary_fragcoord.xy);
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl
new file mode 100644
index 0000000000..db8775f024
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl
@@ -0,0 +1,20 @@
+/**
+ * @file giV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res;
+
+ gl_FrontColor = gl_Color;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
index 3689d12840..797b9e9f3b 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
@@ -7,13 +7,14 @@
#extension GL_ARB_texture_rectangle : enable
+uniform sampler2DRect depthMap;
uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
-uniform sampler2DRect positionMap;
uniform sampler2DRect normalMap;
uniform samplerCube environmentMap;
-uniform sampler2DRect lightMap;
uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+
uniform vec3 env_mat[3];
uniform float sun_wash;
@@ -23,24 +24,48 @@ uniform int light_count;
uniform vec4 light[16];
uniform vec4 light_col[16];
-varying vec3 vary_fragcoord;
+varying vec4 vary_fragcoord;
uniform vec2 screen_res;
+uniform float far_z;
+
+uniform mat4 inv_proj;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
void main()
{
vec2 frag = (vary_fragcoord.xy*0.5+0.5)*screen_res;
- vec3 pos = texture2DRect(positionMap, frag.xy).xyz;
- vec3 norm = normalize(texture2DRect(normalMap, frag.xy).xyz);
+ vec3 pos = getPosition(frag.xy).xyz;
+ if (pos.z < far_z)
+ {
+ discard;
+ }
+
+ vec3 norm = normalize(texture2DRect(normalMap, frag.xy).xyz*2.0-1.0);
vec4 spec = texture2DRect(specularRect, frag.xy);
vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb;
float noise = texture2D(noiseMap, frag.xy/128.0).b;
vec3 out_col = vec3(0,0,0);
+ vec3 npos = normalize(-pos);
for (int i = 0; i < light_count; ++i)
{
vec3 lv = light[i].xyz-pos;
float dist2 = dot(lv,lv);
- if (dist2 > light[i].w)
+ dist2 /= light[i].w;
+ if (dist2 > 1.0)
{
continue;
}
@@ -55,29 +80,38 @@ void main()
da = dot(norm, lv);
float fa = light_col[i].a+1.0;
- float dist_atten = clamp(1.0-(dist2-light[i].w*(1.0-fa))/(light[i].w*fa), 0.0, 1.0);
+ float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
dist_atten *= noise;
float lit = da * dist_atten;
vec3 col = light_col[i].rgb*lit*diff;
+ //vec3 col = vec3(dist2, light_col[i].a, lit);
if (spec.a > 0.0)
{
- vec3 ref = reflect(normalize(pos), norm);
- float sa = dot(ref,lv);
- sa = max(sa, 0.0);
- sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0);
- sa *= noise;
- col += da*sa*light_col[i].rgb*spec.rgb;
+ //vec3 ref = dot(pos+lv, norm);
+
+ float sa = dot(normalize(lv+npos),norm);
+
+ if (sa > 0.0)
+ {
+ sa = texture2D(lightFunc,vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
+ sa *= noise;
+ col += da*sa*light_col[i].rgb*spec.rgb;
+ }
}
out_col += col;
}
- //attenuate point light contribution by SSAO component
- out_col *= texture2DRect(lightMap, frag.xy).g;
+ if (dot(out_col, out_col) <= 0.0)
+ {
+ discard;
+ }
gl_FragColor.rgb = out_col;
gl_FragColor.a = 0.0;
+
+ //gl_FragColor = vec4(0.1, 0.025, 0.025/4.0, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
new file mode 100644
index 0000000000..28bcd720c0
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
@@ -0,0 +1,178 @@
+/**
+ * @file multiSpotLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+
+#version 120
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect specularRect;
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform samplerCube environmentMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+uniform sampler2D projectionMap;
+
+uniform mat4 proj_mat; //screen space to light space
+uniform float proj_near; //near clip for projection
+uniform vec3 proj_p; //plane projection is emitting from (in screen space)
+uniform vec3 proj_n;
+uniform float proj_focus; //distance from plane to begin blurring
+uniform float proj_lod; //(number of mips in proj map)
+uniform float proj_range; //range between near clip and far clip plane of projection
+uniform float proj_ambiance;
+uniform float near_clip;
+uniform float far_clip;
+
+uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
+uniform float sun_wash;
+
+varying vec4 vary_light;
+
+varying vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+void main()
+{
+ vec4 frag = vary_fragcoord;
+ frag.xyz /= frag.w;
+ frag.xyz = frag.xyz*0.5+0.5;
+ frag.xy *= screen_res;
+
+ vec3 pos = getPosition(frag.xy).xyz;
+ vec3 lv = vary_light.xyz-pos.xyz;
+ float dist2 = dot(lv,lv);
+ dist2 /= vary_light.w;
+ if (dist2 > 1.0)
+ {
+ discard;
+ }
+
+ vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0;
+
+ norm = normalize(norm);
+ float l_dist = -dot(lv, proj_n);
+
+ vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
+ if (proj_tc.z < 0.0)
+ {
+ discard;
+ }
+
+ proj_tc.xyz /= proj_tc.w;
+
+ float fa = gl_Color.a+1.0;
+ float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
+
+ lv = proj_origin-pos.xyz;
+ lv = normalize(lv);
+ float da = dot(norm, lv);
+
+ vec3 col = vec3(0,0,0);
+
+ vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
+
+ float noise = texture2D(noiseMap, frag.xy/128.0).b;
+ if (proj_tc.z > 0.0 &&
+ proj_tc.x < 1.0 &&
+ proj_tc.y < 1.0 &&
+ proj_tc.x > 0.0 &&
+ proj_tc.y > 0.0)
+ {
+ float lit = 0.0;
+ if (da > 0.0)
+ {
+ float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+
+ vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
+
+ vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a;
+
+ lit = da * dist_atten * noise;
+
+ col = lcol*lit*diff_tex;
+ }
+
+ float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+ vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
+ //float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0));
+ float amb_da = proj_ambiance;
+
+ amb_da += (da*da*0.5+0.5)*proj_ambiance;
+
+ amb_da *= dist_atten * noise;
+
+ amb_da = min(amb_da, 1.0-lit);
+
+ col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
+ }
+
+
+ vec4 spec = texture2DRect(specularRect, frag.xy);
+ if (spec.a > 0.0)
+ {
+ vec3 ref = reflect(normalize(pos), norm);
+
+ //project from point pos in direction ref to plane proj_p, proj_n
+ vec3 pdelta = proj_p-pos;
+ float ds = dot(ref, proj_n);
+
+ if (ds < 0.0)
+ {
+ vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+
+ vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz;
+
+ if (stc.z > 0.0)
+ {
+ stc.xy /= stc.z+proj_near;
+
+ if (stc.x < 1.0 &&
+ stc.y < 1.0 &&
+ stc.x > 0.0 &&
+ stc.y > 0.0)
+ {
+ vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
+ col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb;
+ }
+ }
+ }
+ }
+
+ /*if (spec.a > 0.0)
+ {
+ //vec3 ref = reflect(normalize(pos), norm);
+ float sa = dot(normalize(lv-normalize(pos)),norm);;
+ //sa = max(sa, 0.0);
+ //sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0);
+ sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
+ sa *= noise;
+ col += da*sa*lcol*spec.rgb;
+ }*/
+
+ gl_FragColor.rgb = col;
+ gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
index 52bad1f34c..78256e20cc 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
@@ -9,33 +9,53 @@
uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
-uniform sampler2DRect positionMap;
uniform sampler2DRect normalMap;
uniform samplerCube environmentMap;
-uniform sampler2DRect lightMap;
uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+uniform sampler2DRect depthMap;
uniform vec3 env_mat[3];
uniform float sun_wash;
varying vec4 vary_light;
-varying vec3 vary_fragcoord;
+varying vec4 vary_fragcoord;
uniform vec2 screen_res;
+uniform mat4 inv_proj;
+uniform vec4 viewport;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = (pos_screen.xy-viewport.xy)*2.0;
+ sc /= viewport.zw;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
void main()
{
- vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
- frag *= screen_res;
- vec3 pos = texture2DRect(positionMap, frag).xyz;
+ vec4 frag = vary_fragcoord;
+ frag.xyz /= frag.w;
+ frag.xyz = frag.xyz*0.5+0.5;
+ frag.xy *= screen_res;
+
+ vec3 pos = getPosition(frag.xy).xyz;
vec3 lv = vary_light.xyz-pos;
float dist2 = dot(lv,lv);
- if (dist2 > vary_light.w)
+ dist2 /= vary_light.w;
+ if (dist2 > 1.0)
{
discard;
}
- vec3 norm = texture2DRect(normalMap, frag).xyz;
+ vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0;
float da = dot(norm, lv);
if (da < 0.0)
{
@@ -46,30 +66,32 @@ void main()
lv = normalize(lv);
da = dot(norm, lv);
- float noise = texture2D(noiseMap, frag/128.0).b;
+ float noise = texture2D(noiseMap, frag.xy/128.0).b;
- vec3 col = texture2DRect(diffuseRect, frag).rgb;
+ vec3 col = texture2DRect(diffuseRect, frag.xy).rgb;
float fa = gl_Color.a+1.0;
- float dist_atten = clamp(1.0-(dist2-vary_light.w*(1.0-fa))/(vary_light.w*fa), 0.0, 1.0);
+ float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
float lit = da * dist_atten * noise;
col = gl_Color.rgb*lit*col;
- vec4 spec = texture2DRect(specularRect, frag);
+ vec4 spec = texture2DRect(specularRect, frag.xy);
if (spec.a > 0.0)
{
- vec3 ref = reflect(normalize(pos), norm);
- float sa = dot(ref,lv);
- sa = max(sa, 0.0);
- sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0);
- sa *= noise;
- col += da*sa*gl_Color.rgb*spec.rgb;
+ float sa = dot(normalize(lv-normalize(pos)),norm);
+ if (sa > 0.0)
+ {
+ sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
+ sa *= noise;
+ col += da*sa*gl_Color.rgb*spec.rgb;
+ }
}
- //attenuate point light contribution by SSAO component
- col *= texture2DRect(lightMap, frag.xy).g;
-
-
+ if (dot(col, col) <= 0.0)
+ {
+ discard;
+ }
+
gl_FragColor.rgb = col;
gl_FragColor.a = 0.0;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
index a4edb88259..e815ca260f 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
@@ -6,7 +6,7 @@
*/
varying vec4 vary_light;
-varying vec3 vary_fragcoord;
+varying vec4 vary_fragcoord;
uniform vec2 screen_res;
uniform float near_clip;
@@ -14,10 +14,10 @@ uniform float near_clip;
void main()
{
//transform vertex
- gl_Position = ftransform();
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
- vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip);
+ vary_fragcoord = pos;
vec4 tex = gl_MultiTexCoord0;
tex.w = 1.0;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
new file mode 100644
index 0000000000..71de03663c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
@@ -0,0 +1,57 @@
+/**
+ * @file postDeferredF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect localLightMap;
+uniform sampler2DRect sunLightMap;
+uniform sampler2DRect giLightMap;
+uniform sampler2D luminanceMap;
+uniform sampler2DRect lightMap;
+
+uniform vec3 lum_quad;
+uniform float lum_lod;
+uniform vec4 ambient;
+
+uniform vec3 gi_quad;
+
+uniform vec2 screen_res;
+varying vec2 vary_fragcoord;
+
+void main()
+{
+ vec2 tc = vary_fragcoord.xy;
+ vec3 lum = texture2DLod(luminanceMap, tc/screen_res, lum_lod).rgb;
+ float luminance = lum.r;
+ luminance = luminance*lum_quad.y+lum_quad.z;
+
+ vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy);
+
+ float ambocc = texture2DRect(lightMap, vary_fragcoord.xy).g;
+
+ vec3 gi_col = texture2DRect(giLightMap, vary_fragcoord.xy).rgb;
+ gi_col = gi_col*gi_col*gi_quad.x + gi_col*gi_quad.y+gi_quad.z*ambocc*ambient.rgb;
+ gi_col *= diff;
+
+ vec4 sun_col = texture2DRect(sunLightMap, vary_fragcoord.xy);
+
+ vec3 local_col = texture2DRect(localLightMap, vary_fragcoord.xy).rgb;
+
+
+ sun_col *= 1.0/min(luminance, 1.0);
+ gi_col *= 1.0/luminance;
+
+ vec3 col = sun_col.rgb+gi_col+local_col;
+
+ gl_FragColor.rgb = col.rgb;
+ col.rgb = max(col.rgb-vec3(1.0,1.0,1.0), vec3(0.0, 0.0, 0.0));
+
+ gl_FragColor.a = 0.0; // max(dot(col.rgb,col.rgb)*lum_quad.x, sun_col.a);
+
+ //gl_FragColor.rgb = vec3(lum_lod);
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl
new file mode 100644
index 0000000000..9819232fd5
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl
@@ -0,0 +1,17 @@
+/**
+ * @file postDeferredV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
new file mode 100644
index 0000000000..9612aee405
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
@@ -0,0 +1,79 @@
+/**
+ * @file postgiF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform sampler2DRect giLightMap;
+uniform sampler2D noiseMap;
+
+uniform vec2 kern[32];
+uniform float dist_factor;
+uniform float blur_size;
+uniform vec2 delta;
+uniform int kern_length;
+uniform float kern_scale;
+uniform vec3 blur_quad;
+
+varying vec2 vary_fragcoord;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+void main()
+{
+ vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0;
+ vec3 pos = getPosition(vary_fragcoord.xy).xyz;
+
+
+ vec3 ccol = texture2DRect(giLightMap, vary_fragcoord.xy).rgb;
+ vec2 dlt = kern_scale * delta/(1.0+norm.xy*norm.xy);
+ dlt /= max(-pos.z*dist_factor, 1.0);
+ float defined_weight = kern[0].x;
+ vec3 col = vec3(0.0);
+
+ for (int i = 0; i < kern_length; i++)
+ {
+ vec2 tc = vary_fragcoord.xy + kern[i].y*dlt;
+ vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz*2.0-1.0;
+
+ float d = dot(norm.xyz, sampNorm);
+
+ if (d > 0.8)
+ {
+ vec3 samppos = getPosition(tc.xy).xyz;
+ samppos -= pos;
+ if (dot(samppos,samppos) < -0.05*pos.z)
+ {
+ col += texture2DRect(giLightMap, tc).rgb*kern[i].x;
+ defined_weight += kern[i].x;
+ }
+ }
+ }
+
+ col /= defined_weight;
+
+ //col = ccol;
+
+ col = col*col*blur_quad.x + col*blur_quad.y + blur_quad.z;
+
+ gl_FragData[0].xyz = col;
+
+ //gl_FragColor = ccol;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl
new file mode 100644
index 0000000000..6adcda82a3
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl
@@ -0,0 +1,17 @@
+/**
+ * @file postgiV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl
index b3758c3638..b0b31fd4ba 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl
@@ -7,8 +7,11 @@
uniform sampler2D diffuseMap;
+varying vec4 post_pos;
void main()
{
gl_FragColor = vec4(1,1,1,texture2D(diffuseMap, gl_TexCoord[0].xy).a * gl_Color.a);
+
+ gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl
index aae1beeae3..7214d246a4 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl
@@ -5,13 +5,17 @@
* $License$
*/
+varying vec4 post_pos;
+
void main()
{
//transform vertex
vec4 pos = gl_ModelViewProjectionMatrix*gl_Vertex;
- //smash geometry against the near clip plane (great for ortho projections)
- pos.z = max(pos.z, -1.0);
- gl_Position = pos;
+
+ post_pos = pos;
+
+ gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_FrontColor = gl_Color;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index d5671a6ce4..b4b0d0ce9d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -12,9 +12,9 @@ uniform sampler2DRect specularRect;
uniform sampler2DRect positionMap;
uniform sampler2DRect normalMap;
uniform sampler2DRect depthMap;
-uniform sampler2DRect lightMap;
uniform sampler2D noiseMap;
uniform samplerCube environmentMap;
+uniform sampler2D lightFunc;
uniform float blur_size;
uniform float blur_fidelity;
@@ -38,9 +38,9 @@ uniform vec4 max_y;
uniform vec4 glow;
uniform float scene_light_strength;
uniform vec3 env_mat[3];
-uniform mat4 shadow_matrix[3];
-uniform vec4 shadow_clip;
-uniform mat3 ssao_effect_mat;
+//uniform mat4 shadow_matrix[3];
+//uniform vec4 shadow_clip;
+//uniform mat3 ssao_effect_mat;
varying vec4 vary_light;
varying vec2 vary_fragcoord;
@@ -52,6 +52,22 @@ vec3 vary_AmblitColor;
vec3 vary_AdditiveColor;
vec3 vary_AtmosAttenuation;
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+vec4 getPosition(vec2 pos_screen)
+{ //get position in screen space (world units) given window coordinate and depth map
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
vec3 getPositionEye()
{
return vary_PositionEye;
@@ -162,17 +178,7 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
temp2.x += .25;
//increase ambient when there are more clouds
- vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5;
-
- /* decrease value and saturation (that in HSV, not HSL) for occluded areas
- * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
- * // The following line of code performs the equivalent of:
- * float ambAlpha = tmpAmbient.a;
- * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
- * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
- * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha);
- */
- tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
+ vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5;
//haze color
setAdditiveColor(
@@ -235,36 +241,27 @@ vec3 scaleSoftClip(vec3 light)
void main()
{
vec2 tc = vary_fragcoord.xy;
- vec3 pos = texture2DRect(positionMap, tc).xyz;
- vec3 norm = texture2DRect(normalMap, tc).xyz;
- vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz;
+ vec3 pos = getPosition(tc).xyz;
+ vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0;
+ //vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz;
float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
- vec4 diffuse = vec4(texture2DRect(diffuseRect, tc).rgb, 1.0);
+ vec4 diffuse = texture2DRect(diffuseRect, tc);
vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
- vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
- float scol = scol_ambocc.r;
- float ambocc = scol_ambocc.g;
-
- calcAtmospherics(pos.xyz, ambocc);
+ calcAtmospherics(pos.xyz, 0.0);
vec3 col = atmosAmbient(vec3(0));
- col += atmosAffectDirectionalLight(min(da, scol));
+ col += atmosAffectDirectionalLight(clamp(da, diffuse.a, 1.0));
col *= diffuse.rgb;
- if (spec.a > 0.2)
+ if (spec.a > 0.0)
{
- vec3 ref = reflect(pos.xyz, norm.xyz);
- vec3 rc;
- rc.x = dot(ref, env_mat[0]);
- rc.y = dot(ref, env_mat[1]);
- rc.z = dot(ref, env_mat[2]);
-
- vec3 refcol = textureCube(environmentMap, rc).rgb;
- col.rgb += refcol * spec.rgb;
+ vec3 ref = normalize(reflect(pos.xyz, norm.xyz));
+ float sa = dot(ref, vary_light.xyz);
+ col.rgb += vary_SunlitColor*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a;
}
col = atmosLighting(col);
@@ -272,8 +269,4 @@ void main()
gl_FragColor.rgb = col;
gl_FragColor.a = 0.0;
- //gl_FragColor.rg = scol_ambocc.rg;
- //gl_FragColor.rgb = norm.rgb*0.5+0.5;
- //gl_FragColor.rgb = vec3(ambocc);
- //gl_FragColor.rgb = vec3(scol);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
new file mode 100644
index 0000000000..2a7234fd83
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
@@ -0,0 +1,177 @@
+/**
+ * @file spotLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#version 120
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect specularRect;
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform samplerCube environmentMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+uniform sampler2D projectionMap;
+
+uniform mat4 proj_mat; //screen space to light space
+uniform float proj_near; //near clip for projection
+uniform vec3 proj_p; //plane projection is emitting from (in screen space)
+uniform vec3 proj_n;
+uniform float proj_focus; //distance from plane to begin blurring
+uniform float proj_lod; //(number of mips in proj map)
+uniform float proj_range; //range between near clip and far clip plane of projection
+uniform float proj_ambiance;
+uniform float near_clip;
+uniform float far_clip;
+
+uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
+uniform float sun_wash;
+
+varying vec4 vary_light;
+
+varying vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+void main()
+{
+ vec4 frag = vary_fragcoord;
+ frag.xyz /= frag.w;
+ frag.xyz = frag.xyz*0.5+0.5;
+ frag.xy *= screen_res;
+
+ vec3 pos = getPosition(frag.xy).xyz;
+ vec3 lv = vary_light.xyz-pos.xyz;
+ float dist2 = dot(lv,lv);
+ dist2 /= vary_light.w;
+ if (dist2 > 1.0)
+ {
+ discard;
+ }
+
+ vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0;
+
+ norm = normalize(norm);
+ float l_dist = -dot(lv, proj_n);
+
+ vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
+ if (proj_tc.z < 0.0)
+ {
+ discard;
+ }
+
+ proj_tc.xyz /= proj_tc.w;
+
+ float fa = gl_Color.a+1.0;
+ float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
+
+ lv = proj_origin-pos.xyz;
+ lv = normalize(lv);
+ float da = dot(norm, lv);
+
+ vec3 col = vec3(0,0,0);
+
+ vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
+
+ float noise = texture2D(noiseMap, frag.xy/128.0).b;
+ if (proj_tc.z > 0.0 &&
+ proj_tc.x < 1.0 &&
+ proj_tc.y < 1.0 &&
+ proj_tc.x > 0.0 &&
+ proj_tc.y > 0.0)
+ {
+ float lit = 0.0;
+ if (da > 0.0)
+ {
+ float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+
+ vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
+
+ vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a;
+
+ lit = da * dist_atten * noise;
+
+ col = lcol*lit*diff_tex;
+ }
+
+ float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+ vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
+ //float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0));
+ float amb_da = proj_ambiance;
+
+ amb_da += (da*da*0.5+0.5)*proj_ambiance;
+
+ amb_da *= dist_atten * noise;
+
+ amb_da = min(amb_da, 1.0-lit);
+
+ col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
+ }
+
+
+ vec4 spec = texture2DRect(specularRect, frag.xy);
+ if (spec.a > 0.0)
+ {
+ vec3 ref = reflect(normalize(pos), norm);
+
+ //project from point pos in direction ref to plane proj_p, proj_n
+ vec3 pdelta = proj_p-pos;
+ float ds = dot(ref, proj_n);
+
+ if (ds < 0.0)
+ {
+ vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+
+ vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz;
+
+ if (stc.z > 0.0)
+ {
+ stc.xy /= stc.z+proj_near;
+
+ if (stc.x < 1.0 &&
+ stc.y < 1.0 &&
+ stc.x > 0.0 &&
+ stc.y > 0.0)
+ {
+ vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
+ col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb;
+ }
+ }
+ }
+ }
+
+ /*if (spec.a > 0.0)
+ {
+ //vec3 ref = reflect(normalize(pos), norm);
+ float sa = dot(normalize(lv-normalize(pos)),norm);;
+ //sa = max(sa, 0.0);
+ //sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0);
+ sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
+ sa *= noise;
+ col += da*sa*lcol*spec.rgb;
+ }*/
+
+ gl_FragColor.rgb = col;
+ gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl
index d43fe6ca95..22bdd2c7f3 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl
@@ -7,17 +7,21 @@
#extension GL_ARB_texture_rectangle : enable
-uniform sampler2DRect positionMap;
-uniform sampler2DRect normalMap;
uniform sampler2DRect depthMap;
-uniform sampler2DShadow shadowMap0;
-uniform sampler2DShadow shadowMap1;
-uniform sampler2DShadow shadowMap2;
-uniform sampler2DShadow shadowMap3;
+uniform sampler2DRect normalMap;
+uniform sampler2DRectShadow shadowMap0;
+uniform sampler2DRectShadow shadowMap1;
+uniform sampler2DRectShadow shadowMap2;
+uniform sampler2DRectShadow shadowMap3;
+uniform sampler2DRectShadow shadowMap4;
+uniform sampler2DRectShadow shadowMap5;
uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+
+
// Inputs
-uniform mat4 shadow_matrix[4];
+uniform mat4 shadow_matrix[6];
uniform vec4 shadow_clip;
uniform float ssao_radius;
uniform float ssao_max_radius;
@@ -27,6 +31,25 @@ uniform float ssao_factor_inv;
varying vec2 vary_fragcoord;
varying vec4 vary_light;
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+uniform float shadow_bias;
+uniform float shadow_offset;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
//calculate decreases in ambient lighting when crowded out (SSAO)
float calcAmbientOcclusion(vec4 pos, vec3 norm)
{
@@ -54,7 +77,7 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm)
for (int i = 0; i < 8; i++)
{
vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect);
- vec3 samppos_world = texture2DRect(positionMap, samppos_screen).xyz;
+ vec3 samppos_world = getPosition(samppos_screen).xyz;
vec3 diff = pos_world - samppos_world;
float dist2 = dot(diff, diff);
@@ -74,14 +97,18 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm)
angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
- return 1.0 - (float(points != 0) * angle_hidden);
+ return (1.0 - (float(points != 0) * angle_hidden));
}
void main()
{
vec2 pos_screen = vary_fragcoord.xy;
- vec4 pos = vec4(texture2DRect(positionMap, pos_screen).xyz, 1.0);
- vec3 norm = texture2DRect(normalMap, pos_screen).xyz;
+
+ //try doing an unproject here
+
+ vec4 pos = getPosition(pos_screen);
+
+ vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0;
/*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL
{
@@ -90,35 +117,45 @@ void main()
}*/
float shadow = 1.0;
- float dp_directional_light = max(0.0, dot(norm, vary_light.xyz));
+ float dp_directional_light = max(0.0, dot(norm, vary_light.xyz));
+ vec4 spos = vec4(pos.xyz + norm.xyz * (-pos.z/64.0*shadow_offset+shadow_bias), 1.0);
+
+ //vec3 debug = vec3(0,0,0);
+
if (dp_directional_light == 0.0)
{
// if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup
shadow = 0.0;
}
- else if (pos.z > -shadow_clip.w)
+ else if (spos.z > -shadow_clip.w)
{
- if (pos.z < -shadow_clip.z)
+ vec4 lpos;
+
+ if (spos.z < -shadow_clip.z)
{
- vec4 lpos = shadow_matrix[3]*pos;
- shadow = shadow2DProj(shadowMap3, lpos).x;
+ lpos = shadow_matrix[3]*spos;
+ lpos.xy *= screen_res;
+ shadow = shadow2DRectProj(shadowMap3, lpos).x;
shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
}
- else if (pos.z < -shadow_clip.y)
+ else if (spos.z < -shadow_clip.y)
{
- vec4 lpos = shadow_matrix[2]*pos;
- shadow = shadow2DProj(shadowMap2, lpos).x;
+ lpos = shadow_matrix[2]*spos;
+ lpos.xy *= screen_res;
+ shadow = shadow2DRectProj(shadowMap2, lpos).x;
}
- else if (pos.z < -shadow_clip.x)
+ else if (spos.z < -shadow_clip.x)
{
- vec4 lpos = shadow_matrix[1]*pos;
- shadow = shadow2DProj(shadowMap1, lpos).x;
+ lpos = shadow_matrix[1]*spos;
+ lpos.xy *= screen_res;
+ shadow = shadow2DRectProj(shadowMap1, lpos).x;
}
else
{
- vec4 lpos = shadow_matrix[0]*pos;
- shadow = shadow2DProj(shadowMap0, lpos).x;
+ lpos = shadow_matrix[0]*spos;
+ lpos.xy *= screen_res;
+ shadow = shadow2DRectProj(shadowMap0, lpos).x;
}
// take the most-shadowed value out of these two:
@@ -126,6 +163,17 @@ void main()
// * an unblurred dot product between the sun and this norm
// the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting
shadow = min(shadow, dp_directional_light);
+
+ /*debug.r = lpos.y / (lpos.w*screen_res.y);
+
+ lpos.xy /= lpos.w*32.0;
+ if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1)
+ {
+ debug.gb = vec2(0.5, 0.5);
+ }
+
+ debug += (1.0-shadow)*0.5;*/
+
}
else
{
@@ -135,5 +183,18 @@ void main()
gl_FragColor[0] = shadow;
gl_FragColor[1] = calcAmbientOcclusion(pos, norm);
- //gl_FragColor[2] is unused as of August 2008, may be used for debugging
+
+ //spotlight shadow 1
+ vec4 lpos = shadow_matrix[4]*spos;
+ lpos.xy *= screen_res;
+ gl_FragColor[2] = shadow2DRectProj(shadowMap4, lpos).x;
+
+ //spotlight shadow 2
+ lpos = shadow_matrix[5]*spos;
+ lpos.xy *= screen_res;
+ gl_FragColor[3] = shadow2DRectProj(shadowMap5, lpos).x;
+
+ //gl_FragColor.rgb = pos.xyz;
+ //gl_FragColor.b = shadow;
+ //gl_FragColor.rgb = debug;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
index 211b2e0397..3cccfb7202 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
@@ -12,7 +12,6 @@ uniform sampler2D detail_3;
uniform sampler2D alpha_ramp;
varying vec3 vary_normal;
-varying vec4 vary_position;
void main()
{
@@ -28,9 +27,8 @@ void main()
float alphaFinal = texture2D(alpha_ramp, gl_TexCoord[1].zw).a;
vec4 outColor = mix( mix(color3, color2, alpha2), mix(color1, color0, alpha1), alphaFinal );
- gl_FragData[0] = vec4(outColor.rgb, 1.0);
+ gl_FragData[0] = vec4(outColor.rgb, 0.0);
gl_FragData[1] = vec4(outColor.rgb*0.2, 0.2);
- gl_FragData[2] = vec4(normalize(vary_normal), 0.0);
- gl_FragData[3] = vary_position;
+ gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl
index e9d6dcabff..3038b14772 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl
@@ -6,7 +6,6 @@
*/
varying vec3 vary_normal;
-varying vec4 vary_position;
vec4 texgen_object(vec4 vpos, vec4 tc, mat4 mat, vec4 tp0, vec4 tp1)
{
@@ -27,7 +26,6 @@ void main()
//transform vertex
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
- vary_position = gl_ModelViewMatrix * gl_Vertex;
vary_normal = normalize(gl_NormalMatrix * gl_Normal);
// Transform and pass tex coords
diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
index bc2c9816dc..258acee08c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
@@ -8,13 +8,11 @@
uniform sampler2D diffuseMap;
varying vec3 vary_normal;
-varying vec4 vary_position;
void main()
{
vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy);
- gl_FragData[0] = gl_Color*col;
+ gl_FragData[0] = vec4(gl_Color.rgb*col.rgb, col.a <= 0.5 ? 0.0 : 0.005);
gl_FragData[1] = vec4(0,0,0,0);
- gl_FragData[2] = vec4(normalize(vary_normal), 0.0);
- gl_FragData[3] = vary_position;
+ gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl
index 9131d7c2b3..6b9dc2defb 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl
@@ -6,7 +6,6 @@
*/
varying vec3 vary_normal;
-varying vec4 vary_position;
void main()
{
@@ -14,8 +13,6 @@ void main()
gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
- vary_position = gl_ModelViewMatrix * gl_Vertex;
-
vary_normal = normalize(gl_NormalMatrix * gl_Normal);
gl_FrontColor = gl_Color;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
index 0a1f019e3d..d21575119d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
@@ -5,19 +5,21 @@
* $License$
*/
+#extension GL_ARB_texture_rectangle : enable
+
vec3 scaleSoftClip(vec3 inColor);
vec3 atmosTransport(vec3 inColor);
uniform sampler2D bumpMap;
uniform sampler2D screenTex;
uniform sampler2D refTex;
-uniform sampler2DShadow shadowMap0;
-uniform sampler2DShadow shadowMap1;
-uniform sampler2DShadow shadowMap2;
-uniform sampler2DShadow shadowMap3;
+uniform sampler2DRectShadow shadowMap0;
+uniform sampler2DRectShadow shadowMap1;
+uniform sampler2DRectShadow shadowMap2;
+uniform sampler2DRectShadow shadowMap3;
uniform sampler2D noiseMap;
-uniform mat4 shadow_matrix[4];
+uniform mat4 shadow_matrix[6];
uniform vec4 shadow_clip;
uniform float sunAngle;
@@ -32,7 +34,8 @@ uniform vec3 normScale;
uniform float fresnelScale;
uniform float fresnelOffset;
uniform float blurMultiplier;
-
+uniform vec2 screen_res;
+uniform mat4 norm_mat; //region space to screen space
//bigWave is (refCoord.w, view.w);
varying vec4 refCoord;
@@ -88,7 +91,7 @@ void main()
refcol *= df1 * 0.333;
vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
- wavef.z *= max(-viewVec.z, 0.1);
+ //wavef.z *= max(-viewVec.z, 0.1);
wavef = normalize(wavef);
float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset;
@@ -101,10 +104,10 @@ void main()
refcol = mix(baseCol*df2, refcol, dweight);
//get specular component
- float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0);
+ //float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0);
//harden specular
- spec = pow(spec, 128.0);
+ //spec = pow(spec, 128.0);
//figure out distortion vector (ripply)
vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0);
@@ -118,40 +121,21 @@ void main()
float shadow = 1.0;
vec4 pos = vary_position;
- vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz;
-
- if (pos.z > -shadow_clip.w)
- {
- vec4 spos = pos;
-
- if (pos.z < -shadow_clip.z)
- {
- vec4 lpos = (shadow_matrix[3]*spos);
- shadow = shadow2DProj(shadowMap3, lpos).x;
- }
- else if (pos.z < -shadow_clip.y)
- {
- vec4 lpos = (shadow_matrix[2]*spos);
- shadow = shadow2DProj(shadowMap2, lpos).x;
- }
- else if (pos.z < -shadow_clip.x)
- {
- vec4 lpos = (shadow_matrix[1]*spos);
- shadow = shadow2DProj(shadowMap1, lpos).x;
- }
- else
- {
- vec4 lpos = (shadow_matrix[0]*spos);
- shadow = shadow2DProj(shadowMap0, lpos).x;
- }
- }
-
- spec *= shadow;
- color.rgb += spec * specular;
-
- color.rgb = atmosTransport(color.rgb);
- color.rgb = scaleSoftClip(color.rgb);
- color.a = spec * sunAngle2;
+ //vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz;
+ vec4 spos = pos;
+
+ //spec *= shadow;
+ //color.rgb += spec * specular;
+
+ //color.rgb = atmosTransport(color.rgb);
+ //color.rgb = scaleSoftClip(color.rgb);
+ //color.a = spec * sunAngle2;
- gl_FragColor = color;
+ //wavef.z = -0.25f;
+ wavef = normalize(wavef);
+ wavef = (norm_mat*vec4(wavef, 1.0)).xyz;
+
+ gl_FragData[0] = vec4(color.rgb, 0.75);
+ gl_FragData[1] = vec4(1,1,1, 0.8);
+ gl_FragData[2] = vec4(wavef*0.5+0.5, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
new file mode 100644
index 0000000000..ad16de6d81
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
@@ -0,0 +1,132 @@
+/**
+ * @file alphaF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2D diffuseMap;
+uniform sampler2DRectShadow shadowMap0;
+uniform sampler2DRectShadow shadowMap1;
+uniform sampler2DRectShadow shadowMap2;
+uniform sampler2DRectShadow shadowMap3;
+uniform sampler2D noiseMap;
+uniform sampler2DRect depthMap;
+
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
+uniform vec2 screen_res;
+uniform vec2 shadow_res;
+
+vec3 atmosLighting(vec3 light);
+vec3 scaleSoftClip(vec3 light);
+
+varying vec3 vary_ambient;
+varying vec3 vary_directional;
+varying vec3 vary_fragcoord;
+varying vec3 vary_position;
+varying vec3 vary_light;
+
+uniform float alpha_soften;
+
+uniform float shadow_bias;
+
+uniform mat4 inv_proj;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos.xyz /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
+{
+ stc.xyz /= stc.w;
+ stc.z += shadow_bias;
+
+ float cs = shadow2DRect(shadowMap, stc.xyz).x;
+ float shadow = cs;
+
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs);
+
+ return shadow/5.0;
+}
+
+
+void main()
+{
+ vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
+ frag *= screen_res;
+
+ vec3 samp_pos = getPosition(frag).xyz;
+
+ float shadow = 1.0;
+ vec4 pos = vec4(vary_position, 1.0);
+
+ vec4 spos = pos;
+
+ if (spos.z > -shadow_clip.w)
+ {
+ vec4 lpos;
+
+ if (spos.z < -shadow_clip.z)
+ {
+ lpos = shadow_matrix[3]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap3, lpos, 1.5);
+ shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
+ }
+ else if (spos.z < -shadow_clip.y)
+ {
+ lpos = shadow_matrix[2]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap2, lpos, 1.5);
+ }
+ else if (spos.z < -shadow_clip.x)
+ {
+ lpos = shadow_matrix[1]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap1, lpos, 1.5);
+ }
+ else
+ {
+ lpos = shadow_matrix[0]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap0, lpos, 1.5);
+ }
+ }
+
+ vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, gl_Color.a);
+ vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * col;
+
+ color.rgb = atmosLighting(color.rgb);
+
+ color.rgb = scaleSoftClip(color.rgb);
+
+ if (samp_pos.z != 0.0 && gl_Color.a < 1.0)
+ {
+ float dist_factor = alpha_soften;
+ float a = gl_Color.a;
+ a *= a;
+ dist_factor *= 1.0/(1.0-a);
+ color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0);
+ }
+
+ //gl_FragColor = gl_Color;
+ gl_FragColor = color;
+ //gl_FragColor = vec4(1,0,1,1)*shadow;
+
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
new file mode 100644
index 0000000000..5991e1f3b5
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
@@ -0,0 +1,76 @@
+/**
+ * @file alphaV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
+void calcAtmospherics(vec3 inPositionEye);
+
+float calcDirectionalLight(vec3 n, vec3 l);
+float calcPointLight(vec3 v, vec3 n, vec4 lp, float la);
+
+vec3 atmosAmbient(vec3 light);
+vec3 atmosAffectDirectionalLight(float lightIntensity);
+vec3 scaleDownLight(vec3 light);
+vec3 scaleUpLight(vec3 light);
+
+varying vec3 vary_ambient;
+varying vec3 vary_directional;
+varying vec3 vary_fragcoord;
+varying vec3 vary_position;
+varying vec3 vary_light;
+
+uniform float near_clip;
+uniform float shadow_offset;
+uniform float shadow_bias;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+
+ gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+
+ vec4 pos = (gl_ModelViewMatrix * gl_Vertex);
+ vec3 norm = normalize(gl_NormalMatrix * gl_Normal);
+
+ float dp_directional_light = max(0.0, dot(norm, gl_LightSource[0].position.xyz));
+ vary_position = pos.xyz + gl_LightSource[0].position.xyz * (1.0-dp_directional_light)*shadow_offset;
+
+ calcAtmospherics(pos.xyz);
+
+ //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.));
+ vec4 col;
+ col.a = gl_Color.a;
+
+ // Add windlight lights
+ col.rgb = atmosAmbient(vec3(0.));
+ col.rgb = scaleUpLight(col.rgb);
+
+ // Collect normal lights (need to be divided by two, as we later multiply by 2)
+ col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation);
+ col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation);
+ col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation);
+ col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation);
+ col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation);
+ col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation);
+ col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz);
+ col.rgb = scaleDownLight(col.rgb);
+
+ vary_light = gl_LightSource[0].position.xyz;
+
+ vary_ambient = col.rgb*gl_Color.rgb;
+ vary_directional.rgb = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a)));
+
+ col.rgb = min(col.rgb*gl_Color.rgb, 1.0);
+
+ gl_FrontColor = col;
+
+ gl_FogFragCoord = pos.z;
+
+ pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip);
+
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl
new file mode 100644
index 0000000000..a81e4caf4c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl
@@ -0,0 +1,98 @@
+/**
+ * @file avatarAlphaF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2D diffuseMap;
+uniform sampler2DRectShadow shadowMap0;
+uniform sampler2DRectShadow shadowMap1;
+uniform sampler2DRectShadow shadowMap2;
+uniform sampler2DRectShadow shadowMap3;
+uniform sampler2D noiseMap;
+
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
+uniform vec2 screen_res;
+uniform vec2 shadow_res;
+
+vec3 atmosLighting(vec3 light);
+vec3 scaleSoftClip(vec3 light);
+
+varying vec3 vary_ambient;
+varying vec3 vary_directional;
+varying vec3 vary_position;
+varying vec3 vary_normal;
+
+uniform float shadow_bias;
+
+float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
+{
+ stc.xyz /= stc.w;
+ stc.z += shadow_bias;
+
+ float cs = shadow2DRect(shadowMap, stc.xyz).x;
+ float shadow = cs;
+
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs);
+
+ return shadow/5.0;
+}
+
+void main()
+{
+ float shadow = 1.0;
+ vec4 pos = vec4(vary_position, 1.0);
+ vec3 norm = normalize(vary_normal);
+
+ //vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz;
+
+ vec4 spos = pos;
+
+ if (spos.z > -shadow_clip.w)
+ {
+ vec4 lpos;
+
+ if (spos.z < -shadow_clip.z)
+ {
+ lpos = shadow_matrix[3]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap3, lpos, 1.5);
+ shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
+ }
+ else if (spos.z < -shadow_clip.y)
+ {
+ lpos = shadow_matrix[2]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap2, lpos, 1.5);
+ }
+ else if (spos.z < -shadow_clip.x)
+ {
+ lpos = shadow_matrix[1]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap1, lpos, 1.5);
+ }
+ else
+ {
+ lpos = shadow_matrix[0]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap0, lpos, 1.5);
+ }
+ }
+
+
+ vec4 col = vec4(vary_ambient + vary_directional*shadow, gl_Color.a);
+ vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * col;
+
+ color.rgb = atmosLighting(color.rgb);
+
+ color.rgb = scaleSoftClip(color.rgb);
+
+ gl_FragColor = color;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
new file mode 100644
index 0000000000..a939499b17
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
@@ -0,0 +1,84 @@
+/**
+ * @file avatarAlphaV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
+mat4 getSkinnedTransform();
+void calcAtmospherics(vec3 inPositionEye);
+
+float calcDirectionalLight(vec3 n, vec3 l);
+float calcPointLight(vec3 v, vec3 n, vec4 lp, float la);
+
+vec3 atmosAmbient(vec3 light);
+vec3 atmosAffectDirectionalLight(float lightIntensity);
+vec3 scaleDownLight(vec3 light);
+vec3 scaleUpLight(vec3 light);
+
+varying vec3 vary_position;
+varying vec3 vary_ambient;
+varying vec3 vary_directional;
+varying vec3 vary_normal;
+
+uniform float near_clip;
+uniform float shadow_offset;
+uniform float shadow_bias;
+
+void main()
+{
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+
+ vec4 pos;
+ vec3 norm;
+
+ mat4 trans = getSkinnedTransform();
+ pos.x = dot(trans[0], gl_Vertex);
+ pos.y = dot(trans[1], gl_Vertex);
+ pos.z = dot(trans[2], gl_Vertex);
+ pos.w = 1.0;
+
+ norm.x = dot(trans[0].xyz, gl_Normal);
+ norm.y = dot(trans[1].xyz, gl_Normal);
+ norm.z = dot(trans[2].xyz, gl_Normal);
+ norm = normalize(norm);
+
+ gl_Position = gl_ProjectionMatrix * pos;
+
+ float dp_directional_light = max(0.0, dot(norm, gl_LightSource[0].position.xyz));
+ vary_position = pos.xyz + gl_LightSource[0].position.xyz * (1.0-dp_directional_light)*shadow_offset;
+ vary_normal = norm;
+
+ calcAtmospherics(pos.xyz);
+
+ //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.));
+ vec4 col;
+ col.a = gl_Color.a;
+
+ // Add windlight lights
+ col.rgb = atmosAmbient(vec3(0.));
+ col.rgb = scaleUpLight(col.rgb);
+
+ // Collect normal lights (need to be divided by two, as we later multiply by 2)
+ col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation);
+ col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation);
+ col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation);
+ col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation);
+ col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation);
+ col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation);
+ col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz);
+ col.rgb = scaleDownLight(col.rgb);
+
+ vary_ambient = col.rgb*gl_Color.rgb;
+ vary_directional = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a)));
+
+ col.rgb = min(col.rgb*gl_Color.rgb, 1.0);
+
+ gl_FrontColor = col;
+
+ gl_FogFragCoord = pos.z;
+
+}
+
+
diff --git a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl
new file mode 100644
index 0000000000..0fad5b4b50
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl
@@ -0,0 +1,80 @@
+/**
+ * @file blurLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform sampler2DRect lightMap;
+
+uniform float dist_factor;
+uniform float blur_size;
+uniform vec2 delta;
+uniform vec3 kern[4];
+uniform float kern_scale;
+
+varying vec2 vary_fragcoord;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+void main()
+{
+ vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0;
+ vec3 pos = getPosition(vary_fragcoord.xy).xyz;
+ vec4 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rgba;
+
+ vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy);
+
+ dlt /= max(-pos.z*dist_factor, 1.0);
+
+ vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free'
+ vec4 col = defined_weight.xyxx * ccol;
+
+ for (int i = 1; i < 4; i++)
+ {
+ vec2 tc = vary_fragcoord.xy + kern[i].z*dlt;
+ vec3 samppos = getPosition(tc).xyz;
+ float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
+ if (d*d <= 0.003)
+ {
+ col += texture2DRect(lightMap, tc)*kern[i].xyxx;
+ defined_weight += kern[i].xy;
+ }
+ }
+ for (int i = 1; i < 4; i++)
+ {
+ vec2 tc = vary_fragcoord.xy - kern[i].z*dlt;
+ vec3 samppos = getPosition(tc).xyz;
+ float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
+ if (d*d <= 0.003)
+ {
+ col += texture2DRect(lightMap, tc)*kern[i].xyxx;
+ defined_weight += kern[i].xy;
+ }
+ }
+
+
+
+ col /= defined_weight.xyxx;
+
+ gl_FragColor = col;
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl
new file mode 100644
index 0000000000..b7f07e5702
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl
@@ -0,0 +1,17 @@
+/**
+ * @file blurLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl
new file mode 100644
index 0000000000..02beddd43b
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl
@@ -0,0 +1,58 @@
+/**
+ * @file edgeF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+
+uniform float gi_dist_cutoff;
+
+varying vec2 vary_fragcoord;
+
+uniform float depth_cutoff;
+uniform float norm_cutoff;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+float getDepth(vec2 pos_screen)
+{
+ float z = texture2DRect(depthMap, pos_screen.xy).a;
+ z = z*2.0-1.0;
+ vec4 ndc = vec4(0.0, 0.0, z, 1.0);
+ vec4 p = inv_proj*ndc;
+ return p.z/p.w;
+}
+
+void main()
+{
+ vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0;
+ float depth = getDepth(vary_fragcoord.xy);
+
+ vec2 tc = vary_fragcoord.xy;
+
+ float sc = 0.75;
+
+ vec2 de;
+ de.x = (depth-getDepth(tc+vec2(sc, sc))) + (depth-getDepth(tc+vec2(-sc, -sc)));
+ de.y = (depth-getDepth(tc+vec2(-sc, sc))) + (depth-getDepth(tc+vec2(sc, -sc)));
+ de /= depth;
+ de *= de;
+ de = step(depth_cutoff, de);
+
+ vec2 ne;
+ ne.x = dot(texture2DRect(normalMap, tc+vec2(-sc,-sc)).rgb*2.0-1.0, norm);
+ ne.y = dot(texture2DRect(normalMap, tc+vec2(sc,sc)).rgb*2.0-1.0, norm);
+
+ ne = 1.0-ne;
+
+ ne = step(norm_cutoff, ne);
+
+ gl_FragColor.a = dot(de,de)+dot(ne,ne);
+ //gl_FragColor.a = dot(de,de);
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl b/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl
new file mode 100644
index 0000000000..f1938c92b8
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl
@@ -0,0 +1,17 @@
+/**
+ * @file edgeV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
new file mode 100644
index 0000000000..651959413c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
@@ -0,0 +1,188 @@
+/**
+ * @file multiSpotLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#version 120
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect specularRect;
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform samplerCube environmentMap;
+uniform sampler2DRect lightMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+uniform sampler2D projectionMap;
+
+uniform mat4 proj_mat; //screen space to light space
+uniform float proj_near; //near clip for projection
+uniform vec3 proj_p; //plane projection is emitting from (in screen space)
+uniform vec3 proj_n;
+uniform float proj_focus; //distance from plane to begin blurring
+uniform float proj_lod; //(number of mips in proj map)
+uniform float proj_range; //range between near clip and far clip plane of projection
+uniform float proj_ambient_lod;
+uniform float proj_ambiance;
+uniform float near_clip;
+uniform float far_clip;
+
+uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
+uniform float sun_wash;
+uniform int proj_shadow_idx;
+uniform float shadow_fade;
+
+varying vec4 vary_light;
+
+varying vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+void main()
+{
+ vec4 frag = vary_fragcoord;
+ frag.xyz /= frag.w;
+ frag.xyz = frag.xyz*0.5+0.5;
+ frag.xy *= screen_res;
+
+ vec3 pos = getPosition(frag.xy).xyz;
+ vec3 lv = vary_light.xyz-pos.xyz;
+ float dist2 = dot(lv,lv);
+ dist2 /= vary_light.w;
+ if (dist2 > 1.0)
+ {
+ discard;
+ }
+
+ float shadow = 1.0;
+
+ if (proj_shadow_idx >= 0)
+ {
+ vec4 shd = texture2DRect(lightMap, frag.xy);
+ float sh[2];
+ sh[0] = shd.b;
+ sh[1] = shd.a;
+ shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0);
+ }
+
+ vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0;
+
+ norm = normalize(norm);
+ float l_dist = -dot(lv, proj_n);
+
+ vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
+ if (proj_tc.z < 0.0)
+ {
+ discard;
+ }
+
+ proj_tc.xyz /= proj_tc.w;
+
+ float fa = gl_Color.a+1.0;
+ float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0);
+ if (dist_atten <= 0.0)
+ {
+ discard;
+ }
+
+ lv = proj_origin-pos.xyz;
+ lv = normalize(lv);
+ float da = dot(norm, lv);
+
+ vec3 col = vec3(0,0,0);
+
+ vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
+
+ float noise = texture2D(noiseMap, frag.xy/128.0).b;
+ if (proj_tc.z > 0.0 &&
+ proj_tc.x < 1.0 &&
+ proj_tc.y < 1.0 &&
+ proj_tc.x > 0.0 &&
+ proj_tc.y > 0.0)
+ {
+ float lit = 0.0;
+ float amb_da = proj_ambiance;
+
+ if (da > 0.0)
+ {
+ float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+
+ vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
+
+ vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a;
+
+ lit = da * dist_atten * noise;
+
+ col = lcol*lit*diff_tex*shadow;
+ amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance;
+ }
+
+ //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+ vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, proj_ambient_lod);
+
+ amb_da += (da*da*0.5+0.5)*proj_ambiance;
+
+ amb_da *= dist_atten * noise;
+
+ amb_da = min(amb_da, 1.0-lit);
+
+ col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
+ }
+
+
+ vec4 spec = texture2DRect(specularRect, frag.xy);
+ if (spec.a > 0.0)
+ {
+ vec3 ref = reflect(normalize(pos), norm);
+
+ //project from point pos in direction ref to plane proj_p, proj_n
+ vec3 pdelta = proj_p-pos;
+ float ds = dot(ref, proj_n);
+
+ if (ds < 0.0)
+ {
+ vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+
+ vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+
+ if (stc.z > 0.0)
+ {
+ stc.xy /= stc.w;
+
+ if (stc.x < 1.0 &&
+ stc.y < 1.0 &&
+ stc.x > 0.0 &&
+ stc.y > 0.0)
+ {
+ vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
+ col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow;
+ }
+ }
+ }
+ }
+
+ //attenuate point light contribution by SSAO component
+ col *= texture2DRect(lightMap, frag.xy).g;
+
+ gl_FragColor.rgb = col;
+ gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl
new file mode 100644
index 0000000000..ee0e9d6367
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl
@@ -0,0 +1,59 @@
+/**
+ * @file postDeferredF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect localLightMap;
+uniform sampler2DRect sunLightMap;
+uniform sampler2DRect giLightMap;
+uniform sampler2D luminanceMap;
+uniform sampler2DRect lightMap;
+
+uniform vec3 gi_lum_quad;
+uniform vec3 sun_lum_quad;
+uniform vec3 lum_quad;
+uniform float lum_lod;
+uniform vec4 ambient;
+
+uniform vec3 gi_quad;
+
+uniform vec2 screen_res;
+varying vec2 vary_fragcoord;
+
+void main()
+{
+ vec2 tc = vary_fragcoord.xy;
+ vec3 lcol = texture2DLod(luminanceMap, tc/screen_res, lum_lod).rgb;
+
+ float lum = sqrt(lcol.r)*lum_quad.x+lcol.r*lcol.r*lum_quad.y+lcol.r*lum_quad.z;
+
+ vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy);
+
+ float ambocc = texture2DRect(lightMap, vary_fragcoord.xy).g;
+
+ vec3 gi_col = texture2DRect(giLightMap, vary_fragcoord.xy).rgb;
+ gi_col = gi_col*gi_col*gi_quad.x + gi_col*gi_quad.y+gi_quad.z*ambocc*ambient.rgb;
+ gi_col *= diff;
+
+ vec4 sun_col = texture2DRect(sunLightMap, vary_fragcoord.xy);
+
+ vec3 local_col = texture2DRect(localLightMap, vary_fragcoord.xy).rgb;
+
+
+ float sun_lum = 1.0-lum;
+ sun_lum = sun_lum*sun_lum*sun_lum_quad.x + sun_lum*sun_lum_quad.y+sun_lum_quad.z;
+
+ float gi_lum = lum;
+ gi_lum = gi_lum*gi_lum*gi_lum_quad.x+gi_lum*gi_lum_quad.y+gi_lum_quad.z;
+ gi_col *= 1.0/gi_lum;
+
+ vec3 col = sun_col.rgb*(1.0+max(sun_lum,0.0))+gi_col+local_col;
+
+ gl_FragColor.rgb = col.rgb;
+ gl_FragColor.a = max(sun_lum*min(sun_col.r+sun_col.g+sun_col.b, 1.0), sun_col.a);
+
+ //gl_FragColor.rgb = texture2DRect(giLightMap, vary_fragcoord.xy).rgb;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl b/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl
new file mode 100644
index 0000000000..9819232fd5
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl
@@ -0,0 +1,17 @@
+/**
+ * @file postDeferredV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
new file mode 100644
index 0000000000..531f7376a3
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -0,0 +1,294 @@
+/**
+ * @file softenLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect specularRect;
+uniform sampler2DRect normalMap;
+uniform sampler2DRect lightMap;
+uniform sampler2D noiseMap;
+uniform samplerCube environmentMap;
+uniform sampler2D lightFunc;
+uniform vec3 gi_quad;
+
+uniform float blur_size;
+uniform float blur_fidelity;
+
+// Inputs
+uniform vec4 morphFactor;
+uniform vec3 camPosLocal;
+//uniform vec4 camPosWorld;
+uniform vec4 gamma;
+uniform vec4 lightnorm;
+uniform vec4 sunlight_color;
+uniform vec4 ambient;
+uniform vec4 blue_horizon;
+uniform vec4 blue_density;
+uniform vec4 haze_horizon;
+uniform vec4 haze_density;
+uniform vec4 cloud_shadow;
+uniform vec4 density_multiplier;
+uniform vec4 distance_multiplier;
+uniform vec4 max_y;
+uniform vec4 glow;
+uniform float scene_light_strength;
+uniform vec3 env_mat[3];
+uniform vec4 shadow_clip;
+uniform mat3 ssao_effect_mat;
+
+uniform sampler2DRect depthMap;
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+varying vec4 vary_light;
+varying vec2 vary_fragcoord;
+
+vec3 vary_PositionEye;
+
+vec3 vary_SunlitColor;
+vec3 vary_AmblitColor;
+vec3 vary_AdditiveColor;
+vec3 vary_AtmosAttenuation;
+
+vec4 getPosition(vec2 pos_screen)
+{ //get position in screen space (world units) given window coordinate and depth map
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+vec3 getPositionEye()
+{
+ return vary_PositionEye;
+}
+vec3 getSunlitColor()
+{
+ return vary_SunlitColor;
+}
+vec3 getAmblitColor()
+{
+ return vary_AmblitColor;
+}
+vec3 getAdditiveColor()
+{
+ return vary_AdditiveColor;
+}
+vec3 getAtmosAttenuation()
+{
+ return vary_AtmosAttenuation;
+}
+
+
+void setPositionEye(vec3 v)
+{
+ vary_PositionEye = v;
+}
+
+void setSunlitColor(vec3 v)
+{
+ vary_SunlitColor = v;
+}
+
+void setAmblitColor(vec3 v)
+{
+ vary_AmblitColor = v;
+}
+
+void setAdditiveColor(vec3 v)
+{
+ vary_AdditiveColor = v;
+}
+
+void setAtmosAttenuation(vec3 v)
+{
+ vary_AtmosAttenuation = v;
+}
+
+void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
+
+ vec3 P = inPositionEye;
+ setPositionEye(P);
+
+ //(TERRAIN) limit altitude
+ if (P.y > max_y.x) P *= (max_y.x / P.y);
+ if (P.y < -max_y.x) P *= (-max_y.x / P.y);
+
+ vec3 tmpLightnorm = lightnorm.xyz;
+
+ vec3 Pn = normalize(P);
+ float Plen = length(P);
+
+ vec4 temp1 = vec4(0);
+ vec3 temp2 = vec3(0);
+ vec4 blue_weight;
+ vec4 haze_weight;
+ vec4 sunlight = sunlight_color;
+ vec4 light_atten;
+
+ //sunlight attenuation effect (hue and brightness) due to atmosphere
+ //this is used later for sunlight modulation at various altitudes
+ light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x);
+ //I had thought blue_density and haze_density should have equal weighting,
+ //but attenuation due to haze_density tends to seem too strong
+
+ temp1 = blue_density + vec4(haze_density.r);
+ blue_weight = blue_density / temp1;
+ haze_weight = vec4(haze_density.r) / temp1;
+
+ //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
+ temp2.y = max(0.0, tmpLightnorm.y);
+ temp2.y = 1. / temp2.y;
+ sunlight *= exp( - light_atten * temp2.y);
+
+ // main atmospheric scattering line integral
+ temp2.z = Plen * density_multiplier.x;
+
+ // Transparency (-> temp1)
+ // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati
+ // compiler gets confused.
+ temp1 = exp(-temp1 * temp2.z * distance_multiplier.x);
+
+ //final atmosphere attenuation factor
+ setAtmosAttenuation(temp1.rgb);
+
+ //compute haze glow
+ //(can use temp2.x as temp because we haven't used it yet)
+ temp2.x = dot(Pn, tmpLightnorm.xyz);
+ temp2.x = 1. - temp2.x;
+ //temp2.x is 0 at the sun and increases away from sun
+ temp2.x = max(temp2.x, .03); //was glow.y
+ //set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+ temp2.x *= glow.x;
+ //higher glow.x gives dimmer glow (because next step is 1 / "angle")
+ temp2.x = pow(temp2.x, glow.z);
+ //glow.z should be negative, so we're doing a sort of (1 / "angle") function
+
+ //add "minimum anti-solar illumination"
+ temp2.x += .25;
+
+ //increase ambient when there are more clouds
+ vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5;
+
+ /* decrease value and saturation (that in HSV, not HSL) for occluded areas
+ * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
+ * // The following line of code performs the equivalent of:
+ * float ambAlpha = tmpAmbient.a;
+ * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
+ * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
+ * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha);
+ */
+ tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
+
+ //haze color
+ setAdditiveColor(
+ vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient)
+ + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x
+ + tmpAmbient)));
+
+ //brightness of surface both sunlight and ambient
+ setSunlitColor(vec3(sunlight * .5));
+ setAmblitColor(vec3(tmpAmbient * .25));
+ setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
+}
+
+vec3 atmosLighting(vec3 light)
+{
+ light *= getAtmosAttenuation().r;
+ light += getAdditiveColor();
+ return (2.0 * light);
+}
+
+vec3 atmosTransport(vec3 light) {
+ light *= getAtmosAttenuation().r;
+ light += getAdditiveColor() * 2.0;
+ return light;
+}
+vec3 atmosGetDiffuseSunlightColor()
+{
+ return getSunlitColor();
+}
+
+vec3 scaleDownLight(vec3 light)
+{
+ return (light / scene_light_strength );
+}
+
+vec3 scaleUpLight(vec3 light)
+{
+ return (light * scene_light_strength);
+}
+
+vec3 atmosAmbient(vec3 light)
+{
+ return getAmblitColor() + light / 2.0;
+}
+
+vec3 atmosAffectDirectionalLight(float lightIntensity)
+{
+ return getSunlitColor() * lightIntensity;
+}
+
+vec3 scaleSoftClip(vec3 light)
+{
+ //soft clip effect:
+ light = 1. - clamp(light, vec3(0.), vec3(1.));
+ light = 1. - pow(light, gamma.xxx);
+
+ return light;
+}
+
+void main()
+{
+ vec2 tc = vary_fragcoord.xy;
+ vec3 pos = getPosition(tc).xyz;
+ vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0;
+ //vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz;
+
+ float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
+
+ vec4 diffuse = texture2DRect(diffuseRect, tc);
+ vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
+
+ vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
+ float scol = max(scol_ambocc.r, diffuse.a);
+ float ambocc = scol_ambocc.g;
+
+ calcAtmospherics(pos.xyz, ambocc);
+
+ vec3 col = atmosAmbient(vec3(0));
+ col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
+
+ col *= diffuse.rgb;
+
+ if (spec.a > 0.0)
+ {
+ vec3 ref = normalize(reflect(pos.xyz, norm.xyz));
+ float sa = dot(ref, vary_light.xyz);
+ col.rgb += vary_SunlitColor*scol*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a;
+ }
+
+ col = atmosLighting(col);
+ col = scaleSoftClip(col);
+
+ gl_FragColor.rgb = col;
+
+ //gl_FragColor.rgb = gi_col.rgb;
+ gl_FragColor.a = 0.0;
+
+ //gl_FragColor.rg = scol_ambocc.rg;
+ //gl_FragColor.rgb = texture2DRect(lightMap, vary_fragcoord.xy).rgb;
+ //gl_FragColor.rgb = norm.rgb*0.5+0.5;
+ //gl_FragColor.rgb = vec3(ambocc);
+ //gl_FragColor.rgb = vec3(scol);
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl
new file mode 100644
index 0000000000..ad8af4780d
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl
@@ -0,0 +1,24 @@
+/**
+ * @file softenLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+uniform vec2 screen_res;
+
+varying vec4 vary_light;
+varying vec2 vary_fragcoord;
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+
+ vec4 tex = gl_MultiTexCoord0;
+ tex.w = 1.0;
+
+ vary_light = gl_MultiTexCoord0;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
new file mode 100644
index 0000000000..d6534083cf
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
@@ -0,0 +1,199 @@
+/**
+ * @file spotLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#version 120
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect specularRect;
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform samplerCube environmentMap;
+uniform sampler2DRect lightMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+uniform sampler2D projectionMap;
+
+uniform mat4 proj_mat; //screen space to light space
+uniform float proj_near; //near clip for projection
+uniform vec3 proj_p; //plane projection is emitting from (in screen space)
+uniform vec3 proj_n;
+uniform float proj_focus; //distance from plane to begin blurring
+uniform float proj_lod; //(number of mips in proj map)
+uniform float proj_range; //range between near clip and far clip plane of projection
+uniform float proj_ambiance;
+uniform float near_clip;
+uniform float far_clip;
+
+uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
+uniform float sun_wash;
+uniform int proj_shadow_idx;
+uniform float shadow_fade;
+
+varying vec4 vary_light;
+
+varying vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+void main()
+{
+ vec4 frag = vary_fragcoord;
+ frag.xyz /= frag.w;
+ frag.xyz = frag.xyz*0.5+0.5;
+ frag.xy *= screen_res;
+
+ float shadow = 1.0;
+
+ if (proj_shadow_idx >= 0)
+ {
+ vec4 shd = texture2DRect(lightMap, frag.xy);
+ float sh[2];
+ sh[0] = shd.b;
+ sh[1] = shd.a;
+ shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0);
+ }
+
+ vec3 pos = getPosition(frag.xy).xyz;
+ vec3 lv = vary_light.xyz-pos.xyz;
+ float dist2 = dot(lv,lv);
+ dist2 /= vary_light.w;
+ if (dist2 > 1.0)
+ {
+ discard;
+ }
+
+ vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0;
+
+ norm = normalize(norm);
+ float l_dist = -dot(lv, proj_n);
+
+ vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
+ if (proj_tc.z < 0.0)
+ {
+ discard;
+ }
+
+ proj_tc.xyz /= proj_tc.w;
+
+ float fa = gl_Color.a+1.0;
+ float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
+
+ lv = proj_origin-pos.xyz;
+ lv = normalize(lv);
+ float da = dot(norm, lv);
+
+ vec3 col = vec3(0,0,0);
+
+ vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
+
+ float noise = texture2D(noiseMap, frag.xy/128.0).b;
+ if (proj_tc.z > 0.0 &&
+ proj_tc.x < 1.0 &&
+ proj_tc.y < 1.0 &&
+ proj_tc.x > 0.0 &&
+ proj_tc.y > 0.0)
+ {
+ float lit = 0.0;
+ if (da > 0.0)
+ {
+ float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+
+ vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
+
+ vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a;
+
+ lit = da * dist_atten * noise;
+
+ col = lcol*lit*diff_tex*shadow;
+ }
+
+ float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+ vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
+ //float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0));
+ float amb_da = proj_ambiance;
+ if (da > 0.0)
+ {
+ amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance;
+ }
+
+ amb_da += (da*da*0.5+0.5)*proj_ambiance;
+
+ amb_da *= dist_atten * noise;
+
+ amb_da = min(amb_da, 1.0-lit);
+
+ col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
+ }
+
+
+ vec4 spec = texture2DRect(specularRect, frag.xy);
+ if (spec.a > 0.0)
+ {
+ vec3 ref = reflect(normalize(pos), norm);
+
+ //project from point pos in direction ref to plane proj_p, proj_n
+ vec3 pdelta = proj_p-pos;
+ float ds = dot(ref, proj_n);
+
+ if (ds < 0.0)
+ {
+ vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+
+ vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz;
+
+ if (stc.z > 0.0)
+ {
+ stc.xy /= stc.z+proj_near;
+
+ if (stc.x < 1.0 &&
+ stc.y < 1.0 &&
+ stc.x > 0.0 &&
+ stc.y > 0.0)
+ {
+ vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
+ col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow;
+ }
+ }
+ }
+ }
+
+ /*if (spec.a > 0.0)
+ {
+ //vec3 ref = reflect(normalize(pos), norm);
+ float sa = dot(normalize(lv-normalize(pos)),norm);;
+ //sa = max(sa, 0.0);
+ //sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0);
+ sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
+ sa *= noise;
+ col += da*sa*lcol*spec.rgb;
+ }*/
+
+ //attenuate point light contribution by SSAO component
+ col *= texture2DRect(lightMap, frag.xy).g;
+
+
+ gl_FragColor.rgb = col;
+ gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
new file mode 100644
index 0000000000..a0026edcd2
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
@@ -0,0 +1,235 @@
+/**
+ * @file sunLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform sampler2DRectShadow shadowMap0;
+uniform sampler2DRectShadow shadowMap1;
+uniform sampler2DRectShadow shadowMap2;
+uniform sampler2DRectShadow shadowMap3;
+uniform sampler2DShadow shadowMap4;
+uniform sampler2DShadow shadowMap5;
+uniform sampler2D noiseMap;
+
+uniform sampler2D lightFunc;
+
+
+// Inputs
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
+uniform float ssao_radius;
+uniform float ssao_max_radius;
+uniform float ssao_factor;
+uniform float ssao_factor_inv;
+
+varying vec2 vary_fragcoord;
+varying vec4 vary_light;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+uniform vec2 shadow_res;
+uniform vec2 proj_shadow_res;
+
+uniform float shadow_bias;
+uniform float shadow_offset;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+//calculate decreases in ambient lighting when crowded out (SSAO)
+float calcAmbientOcclusion(vec4 pos, vec3 norm)
+{
+ vec2 kern[8];
+ // exponentially (^2) distant occlusion samples spread around origin
+ kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
+ kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
+ kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
+ kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
+ kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
+ kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
+ kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
+ kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
+
+ vec2 pos_screen = vary_fragcoord.xy;
+ vec3 pos_world = pos.xyz;
+ vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
+
+ float angle_hidden = 0.0;
+ int points = 0;
+
+ float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
+
+ // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
+ for (int i = 0; i < 8; i++)
+ {
+ vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect);
+ vec3 samppos_world = getPosition(samppos_screen).xyz;
+
+ vec3 diff = pos_world - samppos_world;
+ float dist2 = dot(diff, diff);
+
+ // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
+ // --> solid angle shrinking by the square of distance
+ //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
+ //(k should vary inversely with # of samples, but this is taken care of later)
+
+ //if (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) // -0.05*norm to shift sample point back slightly for flat surfaces
+ // angle_hidden += min(1.0/dist2, ssao_factor_inv); // dist != 0 follows from conditional. max of 1.0 (= ssao_factor_inv * ssao_factor)
+ angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
+
+ // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion"
+ points = points + int(diff.z > -1.0);
+ }
+
+ angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
+
+ return (1.0 - (float(points != 0) * angle_hidden));
+}
+
+float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
+{
+ stc.xyz /= stc.w;
+ stc.z += shadow_bias*scl;
+
+ float cs = shadow2DRect(shadowMap, stc.xyz).x;
+ float shadow = cs;
+
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs);
+
+ return shadow/5.0;
+
+ //return shadow;
+}
+
+float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl)
+{
+ stc.xyz /= stc.w;
+ stc.z += shadow_bias*scl;
+
+ float cs = shadow2D(shadowMap, stc.xyz).x;
+ float shadow = cs;
+
+ vec2 off = 1.5/proj_shadow_res;
+
+ shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs);
+ shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs);
+ shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs);
+ shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs);
+
+
+ return shadow/5.0;
+
+ //return shadow;
+}
+
+void main()
+{
+ vec2 pos_screen = vary_fragcoord.xy;
+
+ //try doing an unproject here
+
+ vec4 pos = getPosition(pos_screen);
+
+ vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0;
+
+ /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL
+ {
+ gl_FragColor = vec4(0.0); // doesn't matter
+ return;
+ }*/
+
+ float shadow = 1.0;
+ float dp_directional_light = max(0.0, dot(norm, vary_light.xyz));
+
+ vec4 spos = vec4(pos.xyz + vary_light.xyz * (1.0-dp_directional_light)*shadow_offset, 1.0);
+
+ if (spos.z > -shadow_clip.w)
+ {
+ if (dp_directional_light == 0.0)
+ {
+ // if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup
+ shadow = 0.0;
+ }
+ else
+ {
+ vec4 lpos;
+
+ if (spos.z < -shadow_clip.z)
+ {
+ lpos = shadow_matrix[3]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap3, lpos, 0.25);
+ shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
+ }
+ else if (spos.z < -shadow_clip.y)
+ {
+ lpos = shadow_matrix[2]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap2, lpos, 0.5);
+ }
+ else if (spos.z < -shadow_clip.x)
+ {
+ lpos = shadow_matrix[1]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap1, lpos, 0.75);
+ }
+ else
+ {
+ lpos = shadow_matrix[0]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap0, lpos, 1.0);
+ }
+
+ // take the most-shadowed value out of these two:
+ // * the blurred sun shadow in the light (shadow) map
+ // * an unblurred dot product between the sun and this norm
+ // the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting
+ shadow = min(shadow, dp_directional_light);
+
+ //lpos.xy /= lpos.w*32.0;
+ //if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1)
+ //{
+ // shadow = 0.0;
+ //}
+
+ }
+ }
+ else
+ {
+ // more distant than the shadow map covers
+ shadow = 1.0;
+ }
+
+ gl_FragColor[0] = shadow;
+ gl_FragColor[1] = calcAmbientOcclusion(pos, norm);
+
+ //spotlight shadow 1
+ vec4 lpos = shadow_matrix[4]*spos;
+ gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.1).x;
+
+ //spotlight shadow 2
+ lpos = shadow_matrix[5]*spos;
+ gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.1).x;
+
+ //gl_FragColor.rgb = pos.xyz;
+ //gl_FragColor.b = shadow;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl
new file mode 100644
index 0000000000..5081485c4b
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl
@@ -0,0 +1,25 @@
+/**
+ * @file sunLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec4 vary_light;
+varying vec2 vary_fragcoord;
+
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res;
+ vec4 tex = gl_MultiTexCoord0;
+ tex.w = 1.0;
+
+ vary_light = gl_MultiTexCoord0;
+
+ gl_FrontColor = gl_Color;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl
new file mode 100644
index 0000000000..7325825d6d
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl
@@ -0,0 +1,84 @@
+/**
+ * @file giDownsampleF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+uniform sampler2DRect giLightMap;
+
+uniform vec2 kern[32];
+uniform float dist_factor;
+uniform float blur_size;
+uniform vec2 delta;
+uniform int kern_length;
+uniform float kern_scale;
+uniform vec3 blur_quad;
+
+varying vec2 vary_fragcoord;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+float getDepth(vec2 pos_screen)
+{
+ float z = texture2DRect(depthMap, pos_screen.xy).a;
+ z = z*2.0-1.0;
+ vec4 ndc = vec4(0.0, 0.0, z, 1.0);
+ vec4 p = inv_proj*ndc;
+ return p.z/p.w;
+}
+
+void main()
+{
+ vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0;
+ float depth = getDepth(vary_fragcoord.xy);
+
+ vec3 ccol = texture2DRect(giLightMap, vary_fragcoord.xy).rgb;
+ vec2 dlt = kern_scale * delta/(vec2(1.0,1.0)+norm.xy*norm.xy);
+ dlt /= clamp(-depth*blur_quad.x, 1.0, 3.0);
+ float defined_weight = kern[0].x;
+ vec3 col = ccol*kern[0].x;
+
+ for (int i = 0; i < kern_length; i++)
+ {
+ vec2 tc = vary_fragcoord.xy + kern[i].y*dlt;
+ vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz*2.0-1.0;
+
+ float d = dot(norm.xyz, sampNorm);
+
+ if (d > 0.5)
+ {
+ float sampdepth = getDepth(tc.xy);
+ sampdepth -= depth;
+ if (sampdepth*sampdepth < blur_quad.z)
+ {
+ col += texture2DRect(giLightMap, tc).rgb*kern[i].x;
+ defined_weight += kern[i].x;
+ }
+ }
+ }
+
+ col /= defined_weight;
+
+ //col = ccol;
+
+ col = col*blur_quad.y;
+
+ gl_FragData[0].xyz = col;
+
+ //gl_FragColor = ccol;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl
new file mode 100644
index 0000000000..6adcda82a3
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl
@@ -0,0 +1,17 @@
+/**
+ * @file postgiV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giF.glsl
new file mode 100644
index 0000000000..939710cb56
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/giF.glsl
@@ -0,0 +1,190 @@
+/**
+ * @file giF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform sampler2DRect lightMap;
+uniform sampler2DRect specularRect;
+
+uniform sampler2D noiseMap;
+
+uniform sampler2D diffuseGIMap;
+uniform sampler2D specularGIMap;
+uniform sampler2D normalGIMap;
+uniform sampler2D depthGIMap;
+
+uniform sampler2D lightFunc;
+
+// Inputs
+varying vec2 vary_fragcoord;
+
+uniform vec2 screen_res;
+
+uniform vec4 sunlight_color;
+
+uniform mat4 inv_proj;
+uniform mat4 gi_mat; //gPipeline.mGIMatrix - eye space to sun space
+uniform mat4 gi_mat_proj; //gPipeline.mGIMatrixProj - eye space to projected sun space
+uniform mat4 gi_norm_mat; //gPipeline.mGINormalMatrix - eye space normal to sun space normal matrix
+uniform mat4 gi_inv_proj; //gPipeline.mGIInvProj - projected sun space to sun space
+uniform float gi_sample_width;
+uniform float gi_noise;
+uniform float gi_attenuation;
+uniform float gi_range;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+vec4 getGIPosition(vec2 gi_tc)
+{
+ float depth = texture2D(depthGIMap, gi_tc).a;
+ vec2 sc = gi_tc*2.0;
+ sc -= vec2(1.0, 1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = gi_inv_proj*ndc;
+ pos.xyz /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+vec3 giAmbient(vec3 pos, vec3 norm)
+{
+ vec4 gi_c = gi_mat_proj * vec4(pos, 1.0);
+ gi_c.xyz /= gi_c.w;
+
+ vec4 gi_pos = gi_mat*vec4(pos,1.0);
+ vec3 gi_norm = (gi_norm_mat*vec4(norm,1.0)).xyz;
+ gi_norm = normalize(gi_norm);
+
+ vec4 c_spec = texture2DRect(specularRect, vary_fragcoord.xy);
+ vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).rgb;
+ gi_pos.xyz += nz.x*gi_noise*gi_norm.xyz;
+ vec2 tcx = gi_norm.xy;
+ vec2 tcy = gi_norm.yx;
+
+ vec4 eye_pos = gi_mat*vec4(0,0,0,1.0);
+
+ vec3 eye_dir = normalize(gi_pos.xyz-eye_pos.xyz);
+ vec3 eye_ref = reflect(eye_dir, gi_norm);
+
+ float da = 0.0; //texture2DRect(lightMap, vary_fragcoord.xy).r*0.5;
+ vec3 fdiff = vec3(da);
+ float fda = da;
+
+ vec3 rcol = vec3(0,0,0);
+
+ float fsa = 0.0;
+
+
+ for (int i = -1; i <= 1; i += 2 )
+ {
+ for (int j = -1; j <= 1; j+= 2)
+ {
+ vec2 tc = vec2(i, j)*0.75+gi_norm.xy*nz.z;
+ tc += nz.xy*2.0;
+ tc *= gi_sample_width*0.25;
+ tc += gi_c.xy;
+
+ vec3 lnorm = -(texture2D(normalGIMap, tc.xy).xyz*2.0-1.0);
+ vec3 lpos = getGIPosition(tc.xy).xyz;
+
+ vec3 at = lpos-gi_pos.xyz;
+ float dist = length(at);
+ float dist_atten = clamp(1.0/(gi_attenuation*dist), 0.0, 1.0);
+
+
+ if (dist_atten > 0.01)
+ { //possible contribution of indirect light to this surface
+ vec3 ldir = at;
+
+ float ld = -dot(ldir, lnorm);
+
+ if (ld < 0.0)
+ {
+ float ang_atten = dot(ldir, gi_norm);
+
+ if (ang_atten > 0.0)
+ {
+ vec4 spec = texture2D(specularGIMap, tc.xy);
+ at = normalize(at);
+ vec3 diff;
+
+ float da = 0.0;
+
+ //contribution from indirect source to visible pixel
+ vec3 ha = at;
+ ha.z -= 1.0;
+ ha = normalize(ha);
+ if (spec.a > 0.0)
+ {
+ float sa = dot(ha,lnorm);
+ da = texture2D(lightFunc, vec2(sa, spec.a)).a;
+ }
+ else
+ {
+ da = -lnorm.z;
+ }
+
+ diff = texture2D(diffuseGIMap, tc.xy).rgb+spec.rgb*spec.a*2.0;
+
+ if (da > 0.0)
+ { //contribution from visible pixel to eye
+ vec3 ha = normalize(at-eye_dir);
+ if (c_spec.a > 0.0)
+ {
+ float sa = dot(ha, gi_norm);
+ da = dist_atten*texture2D(lightFunc, vec2(sa, c_spec.a)).a;
+ }
+ else
+ {
+ da = dist_atten*dot(gi_norm, normalize(ldir));
+ }
+ fda += da;
+ fdiff += da*(c_spec.rgb*c_spec.a*2.0+vec3(1,1,1))*diff.rgb;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ fdiff *= sunlight_color.rgb;
+
+ vec3 ret = fda*fdiff;
+
+ return clamp(ret,vec3(0.0), vec3(1.0));
+}
+
+void main()
+{
+ vec2 pos_screen = vary_fragcoord.xy;
+ vec4 pos = getPosition(pos_screen);
+
+ float rad = gi_range*0.5;
+
+ vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0;
+ float dist = max(length(pos.xyz)-rad, 0.0);
+
+ float da = clamp(1.0-dist/rad, 0.0, 1.0);
+
+ vec3 ambient = da > 0.0 ? giAmbient(pos.xyz, norm) : vec3(0);
+
+
+ gl_FragData[0].xyz = mix(vec3(0), ambient, da);
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl
new file mode 100644
index 0000000000..e0eeebf8b6
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl
@@ -0,0 +1,25 @@
+/**
+ * @file giFinalF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2D bloomMap;
+uniform sampler2DRect edgeMap;
+
+uniform vec2 screen_res;
+varying vec2 vary_fragcoord;
+
+
+void main()
+{
+ vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res);
+ vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy);
+
+ gl_FragColor = bloom + diff;
+ //gl_FragColor.rgb = vec3(texture2DRect(edgeMap, vary_fragcoord.xy).a);
+} \ No newline at end of file
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl
new file mode 100644
index 0000000000..41a29c31bd
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl
@@ -0,0 +1,17 @@
+/**
+ * @file giFinalV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giV.glsl
new file mode 100644
index 0000000000..71dcea9628
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/giV.glsl
@@ -0,0 +1,22 @@
+/**
+ * @file giV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res;
+ vec4 tex = gl_MultiTexCoord0;
+ tex.w = 1.0;
+
+ gl_FrontColor = gl_Color;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl
new file mode 100644
index 0000000000..406a7e07cf
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl
@@ -0,0 +1,19 @@
+/**
+ * @file luminanceF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect lightMap;
+uniform sampler2DRect diffuseRect;
+
+varying vec2 vary_fragcoord;
+void main()
+{
+ float i = texture2DRect(lightMap, vary_fragcoord.xy).r;
+ gl_FragColor.rgb = vec3(i);
+ gl_FragColor.a = 1.0;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl b/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl
new file mode 100644
index 0000000000..db8775f024
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl
@@ -0,0 +1,20 @@
+/**
+ * @file giV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res;
+
+ gl_FrontColor = gl_Color;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl
new file mode 100644
index 0000000000..5e69bf36d9
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl
@@ -0,0 +1,80 @@
+/**
+ * @file postDeferredF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect specularRect;
+
+uniform sampler2DRect localLightMap;
+uniform sampler2DRect sunLightMap;
+uniform sampler2DRect giLightMap;
+uniform sampler2DRect edgeMap;
+
+uniform sampler2D luminanceMap;
+
+uniform sampler2DRect lightMap;
+
+uniform sampler2D lightFunc;
+uniform sampler2D noiseMap;
+
+uniform float sun_lum_scale;
+uniform float sun_lum_offset;
+uniform float lum_scale;
+uniform float lum_lod;
+uniform vec4 ambient;
+uniform float gi_brightness;
+uniform float gi_luminance;
+
+uniform vec4 sunlight_color;
+
+uniform vec2 screen_res;
+varying vec2 vary_fragcoord;
+
+void main()
+{
+ vec2 tc = vary_fragcoord.xy;
+ vec4 lcol = texture2DLod(luminanceMap, vec2(0.5, 0.5), lum_lod);
+
+ vec3 gi_col = texture2DRect(giLightMap, vary_fragcoord.xy).rgb;
+ vec4 sun_col = texture2DRect(sunLightMap, vary_fragcoord.xy);
+ vec3 local_col = texture2DRect(localLightMap, vary_fragcoord.xy).rgb;
+
+ float scol = texture2DRect(lightMap, vary_fragcoord.xy).r;
+
+ vec3 diff = texture2DRect(diffuseRect, vary_fragcoord.xy).rgb;
+ vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
+
+ gi_col = gi_col*(diff.rgb+spec.rgb*spec.a);
+
+ float lum = 1.0-clamp(pow(lcol.r, gi_brightness)+sun_lum_offset, 0.0, 1.0);
+
+ lum *= sun_lum_scale;
+
+ sun_col *= 1.0+(lum*lum_scale*scol);
+
+ vec4 col;
+ col.rgb = gi_col+sun_col.rgb+local_col;
+
+ col.a = sun_col.a;
+
+ vec3 bcol = vec3(0,0,0);
+ float tweight = 0.0;
+ for (int i = 0; i < 16; i++)
+ {
+ float weight = (float(i)+1.0)/2.0;
+ bcol += texture2DLod(luminanceMap, vary_fragcoord.xy/screen_res, weight).rgb*weight*weight*weight;
+ tweight += weight*weight;
+ }
+
+ bcol /= tweight;
+ bcol *= gi_luminance;
+ col.rgb += bcol*lum;
+
+ gl_FragColor = col;
+ //gl_FragColor.rgb = texture2DRect(giLightMap, vary_fragcoord.xy).rgb;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl b/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl
new file mode 100644
index 0000000000..9819232fd5
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl
@@ -0,0 +1,17 @@
+/**
+ * @file postDeferredV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl
new file mode 100644
index 0000000000..901b60af59
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl
@@ -0,0 +1,69 @@
+/**
+ * @file postgiF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform sampler2DRect giLightMap;
+uniform sampler2D noiseMap;
+uniform sampler2D giMip;
+uniform sampler2DRect edgeMap;
+
+
+uniform vec2 delta;
+uniform float kern_scale;
+uniform float gi_edge_weight;
+uniform float gi_blur_brightness;
+
+varying vec2 vary_fragcoord;
+
+void main()
+{
+ vec2 dlt = kern_scale*delta;
+ float defined_weight = 0.0;
+ vec3 col = vec3(0.0);
+
+ float e = 1.0;
+
+ for (int i = 1; i < 8; i++)
+ {
+ vec2 tc = vary_fragcoord.xy + float(i) * dlt;
+
+ e = max(e, 0.0);
+ float wght = e;
+
+ col += texture2DRect(giLightMap, tc).rgb*wght;
+ defined_weight += wght;
+
+ e *= e;
+ e -=(texture2DRect(edgeMap, tc.xy-dlt*0.25).a+
+ texture2DRect(edgeMap, tc.xy+dlt*0.25).a)*gi_edge_weight;
+ }
+
+ e = 1.0;
+
+ for (int i = 1; i < 8; i++)
+ {
+ vec2 tc = vary_fragcoord.xy - float(i) * dlt;
+
+ e = max(e,0.0);
+ float wght = e;
+
+ col += texture2DRect(giLightMap, tc).rgb*wght;
+ defined_weight += wght;
+
+ e *= e;
+ e -= (texture2DRect(edgeMap, tc.xy-dlt*0.25).a+
+ texture2DRect(edgeMap, tc.xy+dlt*0.25).a)*gi_edge_weight;
+
+ }
+
+ col /= max(defined_weight, 0.01);
+
+ gl_FragColor.rgb = col * gi_blur_brightness;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl b/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl
new file mode 100644
index 0000000000..6adcda82a3
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl
@@ -0,0 +1,17 @@
+/**
+ * @file postgiV.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+varying vec2 vary_fragcoord;
+uniform vec2 screen_res;
+
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
new file mode 100644
index 0000000000..96a083b522
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -0,0 +1,297 @@
+/**
+ * @file softenLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect specularRect;
+uniform sampler2DRect normalMap;
+uniform sampler2DRect lightMap;
+uniform sampler2D noiseMap;
+uniform samplerCube environmentMap;
+uniform sampler2D lightFunc;
+uniform vec3 gi_quad;
+
+uniform float blur_size;
+uniform float blur_fidelity;
+
+// Inputs
+uniform vec4 morphFactor;
+uniform vec3 camPosLocal;
+//uniform vec4 camPosWorld;
+uniform vec4 gamma;
+uniform vec4 lightnorm;
+uniform vec4 sunlight_color;
+uniform vec4 ambient;
+uniform vec4 blue_horizon;
+uniform vec4 blue_density;
+uniform vec4 haze_horizon;
+uniform vec4 haze_density;
+uniform vec4 cloud_shadow;
+uniform vec4 density_multiplier;
+uniform vec4 distance_multiplier;
+uniform vec4 max_y;
+uniform vec4 glow;
+uniform float scene_light_strength;
+uniform vec3 env_mat[3];
+uniform vec4 shadow_clip;
+uniform mat3 ssao_effect_mat;
+
+uniform sampler2DRect depthMap;
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+varying vec4 vary_light;
+varying vec2 vary_fragcoord;
+
+vec3 vary_PositionEye;
+
+vec3 vary_SunlitColor;
+vec3 vary_AmblitColor;
+vec3 vary_AdditiveColor;
+vec3 vary_AtmosAttenuation;
+uniform float gi_ambiance;
+
+vec4 getPosition(vec2 pos_screen)
+{ //get position in screen space (world units) given window coordinate and depth map
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+vec3 getPositionEye()
+{
+ return vary_PositionEye;
+}
+vec3 getSunlitColor()
+{
+ return vary_SunlitColor;
+}
+vec3 getAmblitColor()
+{
+ return vary_AmblitColor;
+}
+vec3 getAdditiveColor()
+{
+ return vary_AdditiveColor;
+}
+vec3 getAtmosAttenuation()
+{
+ return vary_AtmosAttenuation;
+}
+
+
+void setPositionEye(vec3 v)
+{
+ vary_PositionEye = v;
+}
+
+void setSunlitColor(vec3 v)
+{
+ vary_SunlitColor = v;
+}
+
+void setAmblitColor(vec3 v)
+{
+ vary_AmblitColor = v;
+}
+
+void setAdditiveColor(vec3 v)
+{
+ vary_AdditiveColor = v;
+}
+
+void setAtmosAttenuation(vec3 v)
+{
+ vary_AtmosAttenuation = v;
+}
+
+void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
+
+ vec3 P = inPositionEye;
+ setPositionEye(P);
+
+ //(TERRAIN) limit altitude
+ if (P.y > max_y.x) P *= (max_y.x / P.y);
+ if (P.y < -max_y.x) P *= (-max_y.x / P.y);
+
+ vec3 tmpLightnorm = lightnorm.xyz;
+
+ vec3 Pn = normalize(P);
+ float Plen = length(P);
+
+ vec4 temp1 = vec4(0);
+ vec3 temp2 = vec3(0);
+ vec4 blue_weight;
+ vec4 haze_weight;
+ vec4 sunlight = sunlight_color;
+ vec4 light_atten;
+
+ //sunlight attenuation effect (hue and brightness) due to atmosphere
+ //this is used later for sunlight modulation at various altitudes
+ light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x);
+ //I had thought blue_density and haze_density should have equal weighting,
+ //but attenuation due to haze_density tends to seem too strong
+
+ temp1 = blue_density + vec4(haze_density.r);
+ blue_weight = blue_density / temp1;
+ haze_weight = vec4(haze_density.r) / temp1;
+
+ //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
+ temp2.y = max(0.0, tmpLightnorm.y);
+ temp2.y = 1. / temp2.y;
+ sunlight *= exp( - light_atten * temp2.y);
+
+ // main atmospheric scattering line integral
+ temp2.z = Plen * density_multiplier.x;
+
+ // Transparency (-> temp1)
+ // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati
+ // compiler gets confused.
+ temp1 = exp(-temp1 * temp2.z * distance_multiplier.x);
+
+ //final atmosphere attenuation factor
+ setAtmosAttenuation(temp1.rgb);
+
+ //compute haze glow
+ //(can use temp2.x as temp because we haven't used it yet)
+ temp2.x = dot(Pn, tmpLightnorm.xyz);
+ temp2.x = 1. - temp2.x;
+ //temp2.x is 0 at the sun and increases away from sun
+ temp2.x = max(temp2.x, .03); //was glow.y
+ //set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+ temp2.x *= glow.x;
+ //higher glow.x gives dimmer glow (because next step is 1 / "angle")
+ temp2.x = pow(temp2.x, glow.z);
+ //glow.z should be negative, so we're doing a sort of (1 / "angle") function
+
+ //add "minimum anti-solar illumination"
+ temp2.x += .25;
+
+ //increase ambient when there are more clouds
+ vec4 tmpAmbient = ambient*gi_ambiance + (vec4(1.) - ambient*gi_ambiance) * cloud_shadow.x * 0.5;
+
+ /* decrease value and saturation (that in HSV, not HSL) for occluded areas
+ * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
+ * // The following line of code performs the equivalent of:
+ * float ambAlpha = tmpAmbient.a;
+ * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
+ * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
+ * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha);
+ */
+ tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
+
+ //haze color
+ setAdditiveColor(
+ vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient)
+ + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x
+ + tmpAmbient)));
+
+ //brightness of surface both sunlight and ambient
+ setSunlitColor(vec3(sunlight * .5));
+ setAmblitColor(vec3(tmpAmbient * .25));
+ setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
+}
+
+vec3 atmosLighting(vec3 light)
+{
+ light *= getAtmosAttenuation().r;
+ light += getAdditiveColor();
+ return (2.0 * light);
+}
+
+vec3 atmosTransport(vec3 light) {
+ light *= getAtmosAttenuation().r;
+ light += getAdditiveColor() * 2.0;
+ return light;
+}
+vec3 atmosGetDiffuseSunlightColor()
+{
+ return getSunlitColor();
+}
+
+vec3 scaleDownLight(vec3 light)
+{
+ return (light / scene_light_strength );
+}
+
+vec3 scaleUpLight(vec3 light)
+{
+ return (light * scene_light_strength);
+}
+
+vec3 atmosAmbient(vec3 light)
+{
+ return getAmblitColor() + light / 2.0;
+}
+
+vec3 atmosAffectDirectionalLight(float lightIntensity)
+{
+ return getSunlitColor() * lightIntensity;
+}
+
+vec3 scaleSoftClip(vec3 light)
+{
+ //soft clip effect:
+ light = 1. - clamp(light, vec3(0.), vec3(1.));
+ light = 1. - pow(light, gamma.xxx);
+
+ return light;
+}
+
+void main()
+{
+ vec2 tc = vary_fragcoord.xy;
+ vec3 pos = getPosition(tc).xyz;
+ vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0;
+ //vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz;
+
+ float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
+
+ vec4 diffuse = texture2DRect(diffuseRect, tc);
+ vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
+
+ da = texture2D(lightFunc, vec2(da, 0.0)).a;
+
+ vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
+ float scol = max(scol_ambocc.r, diffuse.a);
+ float ambocc = scol_ambocc.g;
+
+ calcAtmospherics(pos.xyz, ambocc);
+
+ vec3 col = atmosAmbient(vec3(0));
+ col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
+
+ col *= diffuse.rgb;
+
+ if (spec.a > 0.0)
+ {
+ vec3 ref = normalize(reflect(pos.xyz, norm.xyz));
+ float sa = dot(ref, vary_light.xyz);
+ col.rgb += vary_SunlitColor*scol*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a;
+ }
+
+ col = atmosLighting(col);
+ col = scaleSoftClip(col);
+
+ gl_FragColor.rgb = col;
+
+ //gl_FragColor.rgb = gi_col.rgb;
+ gl_FragColor.a = 0.0;
+
+ //gl_FragColor.rg = scol_ambocc.rg;
+ //gl_FragColor.rgb = texture2DRect(lightMap, vary_fragcoord.xy).rgb;
+ //gl_FragColor.rgb = norm.rgb*0.5+0.5;
+ //gl_FragColor.rgb = vec3(ambocc);
+ //gl_FragColor.rgb = vec3(scol);
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl
new file mode 100644
index 0000000000..ad8af4780d
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl
@@ -0,0 +1,24 @@
+/**
+ * @file softenLightF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+uniform vec2 screen_res;
+
+varying vec4 vary_light;
+varying vec2 vary_fragcoord;
+void main()
+{
+ //transform vertex
+ gl_Position = ftransform();
+
+ vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+
+ vec4 tex = gl_MultiTexCoord0;
+ tex.w = 1.0;
+
+ vary_light = gl_MultiTexCoord0;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl
new file mode 100644
index 0000000000..258acee08c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl
@@ -0,0 +1,18 @@
+/**
+ * @file treeF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+uniform sampler2D diffuseMap;
+
+varying vec3 vary_normal;
+
+void main()
+{
+ vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy);
+ gl_FragData[0] = vec4(gl_Color.rgb*col.rgb, col.a <= 0.5 ? 0.0 : 0.005);
+ gl_FragData[1] = vec4(0,0,0,0);
+ gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0);
+}
diff --git a/indra/newview/app_settings/std_bump.ini b/indra/newview/app_settings/std_bump.ini
index f34e21ce32..561e04c33c 100644
--- a/indra/newview/app_settings/std_bump.ini
+++ b/indra/newview/app_settings/std_bump.ini
@@ -1,18 +1,18 @@
LLStandardBumpmap version 1
-woodgrain 058c75c0-a0d5-f2f8-43f3-e9699a89c2fc.j2c
-bark 6c9fa78a-1c69-2168-325b-3e03ffa348ce.j2c
-bricks b8eed5f0-64b7-6e12-b67f-43fa8e773440.j2c
-checker 9deab416-9c63-78d6-d558-9a156f12044c.j2c
-concrete db9d39ec-a896-c287-1ced-64566217021e.j2c
-crustytile f2d7b6f6-4200-1e9a-fd5b-96459e950f94.j2c
-cutstone d9258671-868f-7511-c321-7baef9e948a4.j2c
-discs d21e44ca-ff1c-a96e-b2ef-c0753426b7d9.j2c
-gravel 4726f13e-bd07-f2fb-feb0-bfa2ac58ab61.j2c
-petridish e569711a-27c2-aad4-9246-0c910239a179.j2c
-siding 073c9723-540c-5449-cdd4-0e87fdc159e3.j2c
-stonetile ae874d1a-93ef-54fb-5fd3-eb0cb156afc0.j2c
-stucco 92e66e00-f56f-598a-7997-048aa64cde18.j2c
-suction 83b77fc6-10b4-63ec-4de7-f40629f238c5.j2c
-weave 735198cf-6ea0-2550-e222-21d3c6a341ae.j2c
+woodgrain 058c75c0-a0d5-f2f8-43f3-e9699a89c2fc
+bark 6c9fa78a-1c69-2168-325b-3e03ffa348ce
+bricks b8eed5f0-64b7-6e12-b67f-43fa8e773440
+checker 9deab416-9c63-78d6-d558-9a156f12044c
+concrete db9d39ec-a896-c287-1ced-64566217021e
+crustytile f2d7b6f6-4200-1e9a-fd5b-96459e950f94
+cutstone d9258671-868f-7511-c321-7baef9e948a4
+discs d21e44ca-ff1c-a96e-b2ef-c0753426b7d9
+gravel 4726f13e-bd07-f2fb-feb0-bfa2ac58ab61
+petridish e569711a-27c2-aad4-9246-0c910239a179
+siding 073c9723-540c-5449-cdd4-0e87fdc159e3
+stonetile ae874d1a-93ef-54fb-5fd3-eb0cb156afc0
+stucco 92e66e00-f56f-598a-7997-048aa64cde18
+suction 83b77fc6-10b4-63ec-4de7-f40629f238c5
+weave 735198cf-6ea0-2550-e222-21d3c6a341ae
diff --git a/indra/newview/build_win32_appConfig.py b/indra/newview/build_win32_appConfig.py
new file mode 100644
index 0000000000..8eadf0068f
--- /dev/null
+++ b/indra/newview/build_win32_appConfig.py
@@ -0,0 +1,74 @@
+# @file build_win32_appConfig.py
+# @brief Create the windows app.config file to redirect crt linkage.
+#
+# $LicenseInfo:firstyear=2009&license=viewergpl$
+#
+# Copyright (c) 2009, Linden Research, Inc.
+#
+# Second Life Viewer Source Code
+# The source code in this file ("Source Code") is provided by Linden Lab
+# to you under the terms of the GNU General Public License, version 2.0
+# ("GPL"), unless you have obtained a separate licensing agreement
+# ("Other License"), formally executed by you and Linden Lab. Terms of
+# the GPL can be found in doc/GPL-license.txt in this distribution, or
+# online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+#
+# There are special exceptions to the terms and conditions of the GPL as
+# it is applied to this Source Code. View the full text of the exception
+# in the file doc/FLOSS-exception.txt in this software distribution, or
+# online at
+# http://secondlifegrid.net/programs/open_source/licensing/flossexception
+#
+# By copying, modifying or distributing this software, you acknowledge
+# that you have read and understood your obligations described above,
+# and agree to abide by those obligations.
+#
+# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+# COMPLETENESS OR PERFORMANCE.
+# $/LicenseInfo$
+
+import sys, os, re
+from xml.dom.minidom import parse
+
+def munge_binding_redirect_version(src_manifest_name, src_config_name, dst_config_name):
+ manifest_dom = parse(src_manifest_name)
+ node = manifest_dom.getElementsByTagName('assemblyIdentity')[0]
+ manifest_assm_ver = node.getAttribute('version')
+
+ config_dom = parse(src_config_name)
+ node = config_dom.getElementsByTagName('bindingRedirect')[0]
+ node.setAttribute('newVersion', manifest_assm_ver)
+ src_old_ver = re.match('([^-]*-).*', node.getAttribute('oldVersion')).group(1)
+ node.setAttribute('oldVersion', src_old_ver + manifest_assm_ver)
+ comment = config_dom.createComment("This file is automatically generated by the build. see indra/newview/build_win32_appConfig.py")
+ config_dom.insertBefore(comment, config_dom.childNodes[0])
+
+ print "Writing: " + dst_config_name
+ f = open(dst_config_name, 'w')
+ config_dom.writexml(f)
+ f.close()
+
+
+
+def main():
+ config = sys.argv[1]
+ src_dir = sys.argv[2]
+ dst_dir = sys.argv[3]
+ dst_name = sys.argv[4]
+
+ if config.lower() == 'debug':
+ src_manifest_name = dst_dir + '/Microsoft.VC80.DebugCRT.manifest'
+ src_config_name = src_dir + '/SecondLifeDebug.exe.config'
+ else:
+ src_manifest_name = dst_dir + '/Microsoft.VC80.CRT.manifest'
+ src_config_name = src_dir + '/SecondLife.exe.config'
+
+ dst_config_name = dst_dir + '/' + dst_name
+
+ munge_binding_redirect_version(src_manifest_name, src_config_name, dst_config_name)
+
+ return 0
+
+if __name__ == "__main__":
+ main()
diff --git a/indra/newview/character/avatar_eye.llm b/indra/newview/character/avatar_eye.llm
new file mode 100644
index 0000000000..8c6e74e1de
--- /dev/null
+++ b/indra/newview/character/avatar_eye.llm
Binary files differ
diff --git a/indra/newview/character/avatar_eye_1.llm b/indra/newview/character/avatar_eye_1.llm
new file mode 100644
index 0000000000..7a3b0d6f28
--- /dev/null
+++ b/indra/newview/character/avatar_eye_1.llm
Binary files differ
diff --git a/indra/newview/character/avatar_eyelashes.llm b/indra/newview/character/avatar_eyelashes.llm
new file mode 100644
index 0000000000..99995b5758
--- /dev/null
+++ b/indra/newview/character/avatar_eyelashes.llm
Binary files differ
diff --git a/indra/newview/character/avatar_hair.llm b/indra/newview/character/avatar_hair.llm
new file mode 100644
index 0000000000..df99de8db7
--- /dev/null
+++ b/indra/newview/character/avatar_hair.llm
Binary files differ
diff --git a/indra/newview/character/avatar_hair_1.llm b/indra/newview/character/avatar_hair_1.llm
new file mode 100644
index 0000000000..6de31fdc23
--- /dev/null
+++ b/indra/newview/character/avatar_hair_1.llm
Binary files differ
diff --git a/indra/newview/character/avatar_hair_2.llm b/indra/newview/character/avatar_hair_2.llm
new file mode 100644
index 0000000000..47d02ba9ce
--- /dev/null
+++ b/indra/newview/character/avatar_hair_2.llm
Binary files differ
diff --git a/indra/newview/character/avatar_hair_3.llm b/indra/newview/character/avatar_hair_3.llm
new file mode 100644
index 0000000000..107f9e2a53
--- /dev/null
+++ b/indra/newview/character/avatar_hair_3.llm
Binary files differ
diff --git a/indra/newview/character/avatar_hair_4.llm b/indra/newview/character/avatar_hair_4.llm
new file mode 100644
index 0000000000..1b9a12a0ca
--- /dev/null
+++ b/indra/newview/character/avatar_hair_4.llm
Binary files differ
diff --git a/indra/newview/character/avatar_hair_5.llm b/indra/newview/character/avatar_hair_5.llm
new file mode 100644
index 0000000000..1b9a12a0ca
--- /dev/null
+++ b/indra/newview/character/avatar_hair_5.llm
Binary files differ
diff --git a/indra/newview/character/avatar_head.llm b/indra/newview/character/avatar_head.llm
new file mode 100644
index 0000000000..8d8b5e0442
--- /dev/null
+++ b/indra/newview/character/avatar_head.llm
Binary files differ
diff --git a/indra/newview/character/avatar_head_1.llm b/indra/newview/character/avatar_head_1.llm
new file mode 100644
index 0000000000..26291e6584
--- /dev/null
+++ b/indra/newview/character/avatar_head_1.llm
Binary files differ
diff --git a/indra/newview/character/avatar_head_2.llm b/indra/newview/character/avatar_head_2.llm
new file mode 100644
index 0000000000..c2b808b1a6
--- /dev/null
+++ b/indra/newview/character/avatar_head_2.llm
Binary files differ
diff --git a/indra/newview/character/avatar_head_3.llm b/indra/newview/character/avatar_head_3.llm
new file mode 100644
index 0000000000..a0676b1f1c
--- /dev/null
+++ b/indra/newview/character/avatar_head_3.llm
Binary files differ
diff --git a/indra/newview/character/avatar_head_4.llm b/indra/newview/character/avatar_head_4.llm
new file mode 100644
index 0000000000..5035585770
--- /dev/null
+++ b/indra/newview/character/avatar_head_4.llm
Binary files differ
diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml
index 0ed5663ec1..448e20b382 100644
--- a/indra/newview/character/avatar_lad.xml
+++ b/indra/newview/character/avatar_lad.xml
@@ -1,310 +1,309 @@
<?xml version="1.0" encoding="US-ASCII" standalone="yes"?>
<linden_avatar
- version="1.0"
- wearable_definition_version="22">
- <!-- The wearable_definition_version is checked during asset upload. -->
- <!-- If you increment it, check indra/lib/python/indra/assetutil.py. -->
- <skeleton
- file_name="avatar_skeleton.xml">
- <attachment_point
- id="1"
- group="6"
- pie_slice="2"
- name="Chest"
- joint="mChest"
- position="0.15 0 -0.1"
- rotation="0 90 90"
- visible_in_first_person="true" />
-
- <attachment_point
- id="2"
- group="2"
- pie_slice="2"
- name="Skull"
- joint="mHead"
- position="0 0 0.15"
- rotation="0 0 90"
- visible_in_first_person="false" />
-
- <attachment_point
- id="3"
- group="3"
- pie_slice="3"
- name="Left Shoulder"
- joint="mCollarLeft"
- position="0 0 0.08"
- rotation="0 0 0"
- visible_in_first_person="true" />
+ version="1.0" wearable_definition_version="22">
+ <!-- The wearable_definition_version is checked during asset upload. -->
+ <!-- If you increment it, check indra/lib/python/indra/assetutil.py. -->
+ <skeleton
+ file_name="avatar_skeleton.xml">
+ <attachment_point
+ id="1"
+ group="6"
+ pie_slice="2"
+ name="Chest"
+ joint="mChest"
+ position="0.15 0 -0.1"
+ rotation="0 90 90"
+ visible_in_first_person="true" />
- <attachment_point
- id="4"
- group="1"
- pie_slice="1"
- name="Right Shoulder"
- joint="mCollarRight"
- position="0 0 0.08"
- rotation="0 0 0"
- visible_in_first_person="true"/>
-
- <attachment_point
- id="5"
- group="4"
- name="Left Hand"
- joint="mWristLeft"
- position="0 0.08 -0.02"
- rotation="0 0 0"
- visible_in_first_person="true"
- max_attachment_offset="1.5" />
+ <attachment_point
+ id="2"
+ group="2"
+ pie_slice="2"
+ name="Skull"
+ joint="mHead"
+ position="0 0 0.15"
+ rotation="0 0 90"
+ visible_in_first_person="false" />
- <attachment_point
- id="6"
- group="0"
- name="Right Hand"
- joint="mWristRight"
- position="0 -0.08 -0.02"
- rotation="0 0 0"
- visible_in_first_person="true"
- max_attachment_offset="1.5" />
-
- <attachment_point
- id="7"
- group="5"
- pie_slice="6"
- name="Left Foot"
- joint="mFootLeft"
- position="0 0.0 0.0"
- rotation="0 0 0"
- visible_in_first_person="true"/>
-
- <attachment_point
- id="8"
- group="7"
- pie_slice="6"
- name="Right Foot"
- joint="mFootRight"
- position="0 0.0 0.0"
- rotation="0 0 0"
- visible_in_first_person="true"/>
-
- <attachment_point
- id="9"
- group="6"
- pie_slice="7"
- name="Spine"
- joint="mChest"
- position="-0.15 0 -0.1"
- rotation="0 -90 90"
- visible_in_first_person="true" />
-
- <attachment_point
- id="10"
- group="6"
- pie_slice="6"
- name="Pelvis"
- joint="mPelvis"
- position="0 0 -0.15"
- rotation="0 0 0"
- visible_in_first_person="true" />
-
- <attachment_point
- id="11"
- group="2"
- pie_slice="6"
- name="Mouth"
- joint="mHead"
- position="0.12 0 0.001"
- rotation="0 0 0"
- visible_in_first_person="false"/>
-
- <attachment_point
- id="12"
- group="2"
- pie_slice="7"
- name="Chin"
- joint="mHead"
- position="0.12 0 -0.04"
- rotation="0 0 0"
- visible_in_first_person="false" />
-
- <attachment_point
- id="13"
- group="2"
- pie_slice="4"
- name="Left Ear"
- joint="mHead"
- position="0.015 0.08 0.017"
- rotation="0 0 0"
- visible_in_first_person="false" />
-
- <attachment_point
- id="14"
- group="2"
- pie_slice="0"
- name="Right Ear"
- joint="mHead"
- position="0.015 -0.08 0.017"
- rotation="0 0 0"
- visible_in_first_person="false" />
-
- <attachment_point
- id="15"
- group="2"
- pie_slice="3"
- name="Left Eyeball"
- joint="mEyeLeft"
- position="0 0 0"
- rotation="0 0 0"
- visible_in_first_person="false"/>
-
- <attachment_point
- id="16"
- group="2"
- pie_slice="1"
- name="Right Eyeball"
- joint="mEyeRight"
- position="0 0 0"
- rotation="0 0 0"
- visible_in_first_person="false" />
-
- <attachment_point
- id="17"
- group="2"
- pie_slice="5"
- name="Nose"
- joint="mHead"
- position="0.1 0 0.05"
- rotation="0 0 0"
- visible_in_first_person="false"/>
-
- <attachment_point
- id="18"
- group="1"
- pie_slice="0"
- name="R Upper Arm"
- joint="mShoulderRight"
- position="0.01 -0.13 0.01"
- rotation="0 0 0"
- visible_in_first_person="true" />
+ <attachment_point
+ id="3"
+ group="3"
+ pie_slice="3"
+ name="Left Shoulder"
+ joint="mCollarLeft"
+ position="0 0 0.08"
+ rotation="0 0 0"
+ visible_in_first_person="true" />
- <attachment_point
- id="19"
- group="1"
- pie_slice="7"
- name="R Forearm"
- joint="mElbowRight"
- position="0 -0.12 0"
- rotation="0 0 0"
- visible_in_first_person="true"/>
-
- <attachment_point
- id="20"
- group="3"
- pie_slice="4"
- name="L Upper Arm"
- joint="mShoulderLeft"
- position="0.01 0.15 -0.01"
- rotation="0 0 0"
- visible_in_first_person="true" />
-
- <attachment_point
- id="21"
- group="3"
- pie_slice="5"
- name="L Forearm"
- joint="mElbowLeft"
- position="0 0.113 0"
- rotation="0 0 0"
- visible_in_first_person="true" />
-
- <attachment_point
- id="22"
- group="7"
- pie_slice="1"
- name="Right Hip"
- joint="mHipRight"
- position="0 0 0"
- rotation="0 0 0"
- visible_in_first_person="true" />
-
- <attachment_point
- id="23"
- group="7"
- pie_slice="0"
- name="R Upper Leg"
- joint="mHipRight"
- position="-0.017 0.041 -0.310"
- rotation="0 0 0"
- visible_in_first_person="true" />
-
- <attachment_point
- id="24"
- group="7"
- pie_slice="7"
- name="R Lower Leg"
- joint="mKneeRight"
- position="-0.044 -0.007 -0.262"
- rotation="0 0 0"
- visible_in_first_person="true" />
-
- <attachment_point
- id="25"
- group="5"
- pie_slice="3"
- name="Left Hip"
- joint="mHipLeft"
- position="0 0 0"
- rotation="0 0 0"
- visible_in_first_person="true" />
-
- <attachment_point
- id="26"
- group="5"
- pie_slice="4"
- name="L Upper Leg"
- joint="mHipLeft"
- position="-0.019 -0.034 -0.310"
- rotation="0 0 0"
- visible_in_first_person="true"/>
-
- <attachment_point
- id="27"
- group="5"
- pie_slice="5"
- name="L Lower Leg"
- joint="mKneeLeft"
- position="-0.044 -0.007 -0.261"
- rotation="0 0 0"
- visible_in_first_person="true" />
-
- <attachment_point
- id="28"
- group="6"
- pie_slice="5"
- name="Stomach"
- joint="mPelvis"
- position="0.092 0.0 0.088"
- rotation="0 0 0"
- visible_in_first_person="true" />
-
- <attachment_point
- id="29"
- group="6"
- pie_slice="3"
- name="Left Pec"
- joint="mTorso"
- position="0.104 0.082 0.247"
- rotation="0 0 0"
- visible_in_first_person="true" />
-
- <attachment_point
- id="30"
- group="6"
- pie_slice="1"
- name="Right Pec"
- joint="mTorso"
- position="0.104 -0.082 0.247"
- rotation="0 0 0"
- visible_in_first_person="true" />
+ <attachment_point
+ id="4"
+ group="1"
+ pie_slice="1"
+ name="Right Shoulder"
+ joint="mCollarRight"
+ position="0 0 0.08"
+ rotation="0 0 0"
+ visible_in_first_person="true"/>
+
+ <attachment_point
+ id="5"
+ group="4"
+ name="Left Hand"
+ joint="mWristLeft"
+ position="0 0.08 -0.02"
+ rotation="0 0 0"
+ visible_in_first_person="true"
+ max_attachment_offset="1.5" />
+
+ <attachment_point
+ id="6"
+ group="0"
+ name="Right Hand"
+ joint="mWristRight"
+ position="0 -0.08 -0.02"
+ rotation="0 0 0"
+ visible_in_first_person="true"
+ max_attachment_offset="1.5" />
+
+ <attachment_point
+ id="7"
+ group="5"
+ pie_slice="6"
+ name="Left Foot"
+ joint="mFootLeft"
+ position="0 0.0 0.0"
+ rotation="0 0 0"
+ visible_in_first_person="true"/>
+
+ <attachment_point
+ id="8"
+ group="7"
+ pie_slice="6"
+ name="Right Foot"
+ joint="mFootRight"
+ position="0 0.0 0.0"
+ rotation="0 0 0"
+ visible_in_first_person="true"/>
+
+ <attachment_point
+ id="9"
+ group="6"
+ pie_slice="7"
+ name="Spine"
+ joint="mChest"
+ position="-0.15 0 -0.1"
+ rotation="0 -90 90"
+ visible_in_first_person="true" />
+
+ <attachment_point
+ id="10"
+ group="6"
+ pie_slice="6"
+ name="Pelvis"
+ joint="mPelvis"
+ position="0 0 -0.15"
+ rotation="0 0 0"
+ visible_in_first_person="true" />
+
+ <attachment_point
+ id="11"
+ group="2"
+ pie_slice="6"
+ name="Mouth"
+ joint="mHead"
+ position="0.12 0 0.001"
+ rotation="0 0 0"
+ visible_in_first_person="false"/>
+
+ <attachment_point
+ id="12"
+ group="2"
+ pie_slice="7"
+ name="Chin"
+ joint="mHead"
+ position="0.12 0 -0.04"
+ rotation="0 0 0"
+ visible_in_first_person="false" />
+
+ <attachment_point
+ id="13"
+ group="2"
+ pie_slice="4"
+ name="Left Ear"
+ joint="mHead"
+ position="0.015 0.08 0.017"
+ rotation="0 0 0"
+ visible_in_first_person="false" />
+
+ <attachment_point
+ id="14"
+ group="2"
+ pie_slice="0"
+ name="Right Ear"
+ joint="mHead"
+ position="0.015 -0.08 0.017"
+ rotation="0 0 0"
+ visible_in_first_person="false" />
+
+ <attachment_point
+ id="15"
+ group="2"
+ pie_slice="3"
+ name="Left Eyeball"
+ joint="mEyeLeft"
+ position="0 0 0"
+ rotation="0 0 0"
+ visible_in_first_person="false"/>
+
+ <attachment_point
+ id="16"
+ group="2"
+ pie_slice="1"
+ name="Right Eyeball"
+ joint="mEyeRight"
+ position="0 0 0"
+ rotation="0 0 0"
+ visible_in_first_person="false" />
+
+ <attachment_point
+ id="17"
+ group="2"
+ pie_slice="5"
+ name="Nose"
+ joint="mHead"
+ position="0.1 0 0.05"
+ rotation="0 0 0"
+ visible_in_first_person="false"/>
+
+ <attachment_point
+ id="18"
+ group="1"
+ pie_slice="0"
+ name="R Upper Arm"
+ joint="mShoulderRight"
+ position="0.01 -0.13 0.01"
+ rotation="0 0 0"
+ visible_in_first_person="true" />
+
+ <attachment_point
+ id="19"
+ group="1"
+ pie_slice="7"
+ name="R Forearm"
+ joint="mElbowRight"
+ position="0 -0.12 0"
+ rotation="0 0 0"
+ visible_in_first_person="true"/>
+
+ <attachment_point
+ id="20"
+ group="3"
+ pie_slice="4"
+ name="L Upper Arm"
+ joint="mShoulderLeft"
+ position="0.01 0.15 -0.01"
+ rotation="0 0 0"
+ visible_in_first_person="true" />
+
+ <attachment_point
+ id="21"
+ group="3"
+ pie_slice="5"
+ name="L Forearm"
+ joint="mElbowLeft"
+ position="0 0.113 0"
+ rotation="0 0 0"
+ visible_in_first_person="true" />
+
+ <attachment_point
+ id="22"
+ group="7"
+ pie_slice="1"
+ name="Right Hip"
+ joint="mHipRight"
+ position="0 0 0"
+ rotation="0 0 0"
+ visible_in_first_person="true" />
+
+ <attachment_point
+ id="23"
+ group="7"
+ pie_slice="0"
+ name="R Upper Leg"
+ joint="mHipRight"
+ position="-0.017 0.041 -0.310"
+ rotation="0 0 0"
+ visible_in_first_person="true" />
+
+ <attachment_point
+ id="24"
+ group="7"
+ pie_slice="7"
+ name="R Lower Leg"
+ joint="mKneeRight"
+ position="-0.044 -0.007 -0.262"
+ rotation="0 0 0"
+ visible_in_first_person="true" />
+
+ <attachment_point
+ id="25"
+ group="5"
+ pie_slice="3"
+ name="Left Hip"
+ joint="mHipLeft"
+ position="0 0 0"
+ rotation="0 0 0"
+ visible_in_first_person="true" />
+
+ <attachment_point
+ id="26"
+ group="5"
+ pie_slice="4"
+ name="L Upper Leg"
+ joint="mHipLeft"
+ position="-0.019 -0.034 -0.310"
+ rotation="0 0 0"
+ visible_in_first_person="true"/>
+
+ <attachment_point
+ id="27"
+ group="5"
+ pie_slice="5"
+ name="L Lower Leg"
+ joint="mKneeLeft"
+ position="-0.044 -0.007 -0.261"
+ rotation="0 0 0"
+ visible_in_first_person="true" />
+
+ <attachment_point
+ id="28"
+ group="6"
+ pie_slice="5"
+ name="Stomach"
+ joint="mPelvis"
+ position="0.092 0.0 0.088"
+ rotation="0 0 0"
+ visible_in_first_person="true" />
+
+ <attachment_point
+ id="29"
+ group="6"
+ pie_slice="3"
+ name="Left Pec"
+ joint="mTorso"
+ position="0.104 0.082 0.247"
+ rotation="0 0 0"
+ visible_in_first_person="true" />
+
+ <attachment_point
+ id="30"
+ group="6"
+ pie_slice="1"
+ name="Right Pec"
+ joint="mTorso"
+ position="0.104 -0.082 0.247"
+ rotation="0 0 0"
+ visible_in_first_person="true" />
<attachment_point
id="31"
@@ -394,6 +393,7 @@
max_attachment_offset="2.0"
visible_in_first_person="true" />
+
<param
id="32"
group="1"
@@ -403,10860 +403,11002 @@
label_max="Male"
value_min="0"
value_max="1">
- <param_skeleton>
- <bone
- name="mNeck"
- scale="0 0 .2" />
+ <param_skeleton>
+ <bone
+ name="mNeck"
+ scale="0 0 .2" />
- <bone
- name="mCollarLeft"
- scale="0 .4 0" />
+ <bone
+ name="mCollarLeft"
+ scale="0 .4 0" />
- <bone
- name="mCollarRight"
- scale="0 .4 0" />
+ <bone
+ name="mCollarRight"
+ scale="0 .4 0" />
- <bone
- name="mShoulderLeft"
- scale="0 .35 0" />
+ <bone
+ name="mShoulderLeft"
+ scale="0 .35 0" />
- <bone
- name="mShoulderRight"
- scale="0 .35 0" />
+ <bone
+ name="mShoulderRight"
+ scale="0 .35 0" />
- <bone
- name="mElbowLeft"
- scale="0 .1 0" />
+ <bone
+ name="mElbowLeft"
+ scale="0 .1 0" />
- <bone
- name="mElbowRight"
- scale="0 .1 0" />
+ <bone
+ name="mElbowRight"
+ scale="0 .1 0" />
- <bone
- name="mChest"
- scale=".05 .05 .05" />
+ <bone
+ name="mChest"
+ scale=".05 .05 .05" />
- <bone
- name="mTorso"
- scale="0 0 .05" />
+ <bone
+ name="mTorso"
+ scale="0 0 .05" />
- <bone
- name="mPelvis"
- scale="0 0 0" />
+ <bone
+ name="mPelvis"
+ scale="0 0 0" />
- <bone
- name="mHipLeft"
- scale=".05 .05 0" />
+ <bone
+ name="mHipLeft"
+ scale=".05 .05 0" />
- <bone
- name="mHipRight"
- scale=".05 .05 0" />
+ <bone
+ name="mHipRight"
+ scale=".05 .05 0" />
- <bone
- name="mKneeLeft"
- scale=".05 .05 .1" />
+ <bone
+ name="mKneeLeft"
+ scale=".05 .05 .1" />
- <bone
- name="mKneeRight"
- scale=".05 .05 .1" />
- </param_skeleton>
- </param>
+ <bone
+ name="mKneeRight"
+ scale=".05 .05 .1" />
+ </param_skeleton>
+ </param>
- <param
- id="33"
- group="0"
- name="Height"
- label="Height"
- wearable="shape"
- edit_group="shape_body"
- edit_group_order="1"
- label_min="Short"
- label_max="Tall"
- show_simple="true"
- value_min="-2.3"
- value_max="2"
- camera_distance="2.2">
- <param_skeleton>
- <bone
- name="mNeck"
- scale="0 0 .02" />
+ <param
+ id="33"
+ group="0"
+ name="Height"
+ label="Height"
+ wearable="shape"
+ edit_group="shape_body"
+ edit_group_order="1"
+ label_min="Short"
+ label_max="Tall"
+ show_simple="true"
+ value_min="-2.3"
+ value_max="2"
+ camera_distance="2.2">
+ <param_skeleton>
+ <bone
+ name="mNeck"
+ scale="0 0 .02" />
+
+ <bone
+ name="mCollarLeft"
+ scale="0 0 0" />
+
+ <bone
+ name="mCollarRight"
+ scale="0 0 0" />
+
+ <bone
+ name="mShoulderLeft"
+ scale="0 0.08 0" />
+
+ <bone
+ name="mShoulderRight"
+ scale="0 0.08 0" />
+
+ <bone
+ name="mElbowLeft"
+ scale="0 0.06 0" />
+
+ <bone
+ name="mElbowRight"
+ scale="0 0.06 0" />
+
+ <bone
+ name="mChest"
+ scale="0 0 0.05" />
+
+ <bone
+ name="mTorso"
+ scale="0 0 0.05" />
+
+ <bone
+ name="mPelvis"
+ scale="0 0 0" />
+
+ <bone
+ name="mHipLeft"
+ scale="0 0 0.1" />
+
+ <bone
+ name="mHipRight"
+ scale="0 0 0.1" />
+
+ <bone
+ name="mKneeLeft"
+ scale="0 0 0.1" />
+
+ <bone
+ name="mKneeRight"
+ scale="0 0 0.1" />
+ </param_skeleton>
+ </param>
- <bone
- name="mCollarLeft"
- scale="0 0 0" />
+ <param
+ id="34"
+ group="0"
+ name="Thickness"
+ label="Body Thickness"
+ wearable="shape"
+ edit_group="shape_body"
+ edit_group_order="2"
+ label_min="Body Thin"
+ label_max="Body Thick"
+ show_simple="true"
+ value_min="-0.7"
+ value_max="1.5"
+ camera_distance="1.8">
+ <param_skeleton>
+ <bone
+ name="mNeck"
+ scale="0.1 0.1 0" />
+
+ <bone
+ name="mCollarLeft"
+ scale="0 0.2 0" />
+
+ <bone
+ name="mCollarRight"
+ scale="0 0.2 0" />
+
+ <bone
+ name="mShoulderLeft"
+ scale="0.1 0 0.1" />
+
+ <bone
+ name="mShoulderRight"
+ scale="0.1 0 0.1" />
+
+ <bone
+ name="mElbowLeft"
+ scale="0.1 0 0.1" />
+
+ <bone
+ name="mElbowRight"
+ scale="0.1 0 0.1" />
+
+ <bone
+ name="mChest"
+ scale="0.1 0.1 0" />
+
+ <bone
+ name="mTorso"
+ scale="0.1 0.1 0" />
+
+ <bone
+ name="mPelvis"
+ scale="0.1 0.1 0" />
+
+ <bone
+ name="mHipLeft"
+ scale="0.13 0.13 0" />
+
+ <bone
+ name="mHipRight"
+ scale="0.13 0.13 0" />
+
+ <bone
+ name="mKneeLeft"
+ scale="0.12 0.12 0" />
+
+ <bone
+ name="mKneeRight"
+ scale="0.12 0.12 0" />
+ </param_skeleton>
+ </param>
- <bone
- name="mCollarRight"
- scale="0 0 0" />
+ <param
+ id="36"
+ group="0"
+ name="Shoulders"
+ label="Shoulders"
+ wearable="shape"
+ edit_group="shape_torso"
+ edit_group_order="4"
+ label_min="Narrow"
+ label_max="Broad"
+ show_simple="true"
+ value_min="-1.8"
+ value_max="1.4"
+ value_default="-0.5"
+ camera_elevation=".1"
+ camera_distance="1.2"
+ camera_angle="0">
+ <param_skeleton>
+ <bone
+ name="mNeck"
+ scale="0.01 0.03 0" />
+
+ <bone
+ name="mCollarLeft"
+ scale="0 0 0"
+ offset="0 .02 0" />
+
+ <bone
+ name="mCollarRight"
+ scale="0 0 0"
+ offset="0 -.02 0" />
+
+ <bone
+ name="mChest"
+ scale="0.02 0.08 0" />
+ </param_skeleton>
+ </param>
- <bone
- name="mShoulderLeft"
- scale="0 0.08 0" />
+ <param
+ id="37"
+ group="0"
+ name="Hip Width"
+ label="Hip Width"
+ wearable="shape"
+ edit_group="shape_legs"
+ edit_group_order="3"
+ label_min="Narrow"
+ label_max="Wide"
+ show_simple="true"
+ value_min="-3.2"
+ value_max="2.8"
+ camera_distance="1.8">
+ <param_skeleton>
+ <bone
+ name="mPelvis"
+ scale="0 0.1 0" />
+
+ <bone
+ name="mHipLeft"
+ scale="0 0 0"
+ offset="0 .004 0" />
+
+ <bone
+ name="mHipRight"
+ scale="0 0 0"
+ offset="0 -.004 0" />
+ </param_skeleton>
+ </param>
- <bone
- name="mShoulderRight"
- scale="0 0.08 0" />
+ <param
+ id="842"
+ group="0"
+ name="Hip Length"
+ wearable="shape"
+ edit_group="shape_legs"
+ edit_group_order="3.2"
+ label_min="Short hips"
+ label_max="Long Hips"
+ value_min="-1"
+ value_max="1"
+ camera_distance="1.8">
+ <param_skeleton>
+ <bone
+ name="mPelvis"
+ scale="0 0 0.3" />
+ </param_skeleton>
+ </param>
- <bone
- name="mElbowLeft"
- scale="0 0.06 0" />
+ <param
+ id="38"
+ group="0"
+ name="Torso Length"
+ wearable="shape"
+ edit_group="shape_torso"
+ edit_group_order="11"
+ label_min="Short Torso"
+ label_max="Long Torso"
+ value_min="-1"
+ value_max="1"
+ camera_distance="1.8">
+ <param_skeleton>
+ <bone
+ name="mTorso"
+ scale="0 0 .3" />
+
+ <bone
+ name="mPelvis"
+ scale="0 0 .1" />
+
+ <bone
+ name="mHipLeft"
+ scale="0 0 -.1" />
+
+ <bone
+ name="mHipRight"
+ scale="0 0 -.1" />
+
+ <bone
+ name="mKneeRight"
+ scale="0 0 -.05" />
+
+ <bone
+ name="mKneeLeft"
+ scale="0 0 -.05" />
+ </param_skeleton>
+ </param>
- <bone
- name="mElbowRight"
- scale="0 0.06 0" />
+ <param
+ id="195"
+ group="1"
+ name="EyeBone_Spread"
+ wearable="shape"
+ edit_group="shape_eyes"
+ label_min="Eyes Together"
+ label_max="Eyes Spread"
+ value_min="-1"
+ value_max="1">
+ <param_skeleton>
+ <bone
+ name="mEyeLeft"
+ scale="0 0 0"
+ offset="0 .009 0" />
+
+ <bone
+ name="mEyeRight"
+ scale="0 0 0"
+ offset="0 -.009 0" />
+ </param_skeleton>
+ </param>
- <bone
- name="mChest"
- scale="0 0 0.05" />
+ <param
+ id="661"
+ group="1"
+ name="EyeBone_Head_Shear"
+ wearable="shape"
+ edit_group="shape_eyes"
+ label_min="Eyes Shear Left Up"
+ label_max="Eyes Shear Right Up"
+ value_min="-2"
+ value_max="2">
+ <param_skeleton>
+ <bone
+ name="mEyeLeft"
+ scale="0 0 0"
+ offset="0 0 .004" />
+
+ <bone
+ name="mEyeRight"
+ scale="0 0 0"
+ offset="0 0 -.004" />
+ </param_skeleton>
+ </param>
- <bone
- name="mTorso"
- scale="0 0 0.05" />
+ <param
+ id="772"
+ group="1"
+ name="EyeBone_Head_Elongate"
+ wearable="shape"
+ edit_group="shape_eyes"
+ label_min="Eyes Short Head"
+ label_max="Eyes Long Head"
+ value_min="-1"
+ value_max="1">
+ <param_skeleton>
+ <bone
+ name="mEyeLeft"
+ scale="0 0 0"
+ offset=".016 0 0" />
+
+ <bone
+ name="mEyeRight"
+ scale="0 0 0"
+ offset=".016 0 0" />
+ </param_skeleton>
+ </param>
- <bone
- name="mPelvis"
- scale="0 0 0" />
+ <param
+ id="768"
+ group="1"
+ name="EyeBone_Bug"
+ wearable="shape"
+ edit_group="shape_eyes"
+ label_min="Eyes Sunken"
+ label_max="Eyes Bugged"
+ value_min="-2"
+ value_max="2">
+ <param_skeleton>
+ <bone
+ name="mEyeLeft"
+ scale="0 0 0"
+ offset=".005 0 0" />
+
+ <bone
+ name="mEyeRight"
+ scale="0 0 0"
+ offset=".005 0 0" />
+ </param_skeleton>
+ </param>
- <bone
- name="mHipLeft"
- scale="0 0 0.1" />
+ <param
+ id="655"
+ group="1"
+ name="Head Size"
+ label="Head Size"
+ wearable="shape"
+ edit_group="shape_head"
+ label_min="Small Head"
+ label_max="Big Head"
+ show_simple="true"
+ value_min="-.25"
+ value_max=".10">
+ <param_skeleton>
+ <bone
+ name="mSkull"
+ scale="1 1 1"
+ offset="0 0 0.1" />
+
+ <bone
+ name="mHead"
+ scale="1 1 1"
+ offset="0 0 0" />
+
+ <bone
+ name="mEyeLeft"
+ scale="1 1 1"
+ offset="0 0 0" />
+
+ <bone
+ name="mEyeRight"
+ scale="1 1 1"
+ offset="0 0 0" />
+ </param_skeleton>
+ </param>
- <bone
- name="mHipRight"
- scale="0 0 0.1" />
+ <param
+ id="197"
+ group="1"
+ wearable="shoes"
+ name="Shoe_Heels"
+ edit_group="shoes"
+ label_min="No Heels"
+ label_max="High Heels"
+ value_min="0"
+ value_max="1">
+ <param_skeleton>
+ <bone
+ name="mFootRight"
+ scale="0 0 0"
+ offset="0 0 -.08" />
+
+ <bone
+ name="mFootLeft"
+ scale="0 0 0"
+ offset="0 0 -.08" />
+ </param_skeleton>
+ </param>
- <bone
- name="mKneeLeft"
- scale="0 0 0.1" />
+ <param
+ id="502"
+ group="1"
+ wearable="shoes"
+ name="Shoe_Platform"
+ edit_group="shoes"
+ label_min="No Heels"
+ label_max="High Heels"
+ value_min="0"
+ value_max="1">
+ <param_skeleton>
+ <bone
+ name="mFootRight"
+ scale="0 0 0"
+ offset="0 0 -.07" />
+
+ <bone
+ name="mFootLeft"
+ scale="0 0 0"
+ offset="0 0 -.07" />
+ </param_skeleton>
+ </param>
- <bone
- name="mKneeRight"
- scale="0 0 0.1" />
- </param_skeleton>
- </param>
+ <param
+ id="675"
+ group="0"
+ name="Hand Size"
+ wearable="shape"
+ edit_group="shape_torso"
+ edit_group_order="10"
+ label_min="Small Hands"
+ label_max="Large Hands"
+ value_min="-.3"
+ value_max=".3"
+ camera_elevation=".1"
+ camera_distance="1.4"
+ camera_angle="0">
+ <param_skeleton>
+ <bone
+ name="mWristRight"
+ scale="1 1 1"
+ offset="0 0 0" />
+
+ <bone
+ name="mWristLeft"
+ scale="1 1 1"
+ offset="0 0 0" />
+ </param_skeleton>
+ </param>
- <param
- id="34"
- group="0"
- name="Thickness"
- label="Body Thickness"
- wearable="shape"
- edit_group="shape_body"
- edit_group_order="2"
- label_min="Body Thin"
- label_max="Body Thick"
- show_simple="true"
- value_min="-0.7"
- value_max="1.5"
- camera_distance="1.8">
- <param_skeleton>
- <bone
- name="mNeck"
- scale="0.1 0.1 0" />
+ <param
+ id="683"
+ group="0"
+ name="Neck Thickness"
+ wearable="shape"
+ edit_group="shape_torso"
+ edit_group_order="2"
+ label_min="Skinny Neck"
+ label_max="Thick Neck"
+ value_min="-.4"
+ value_max=".2"
+ value_default="-.15"
+ camera_elevation=".3"
+ camera_distance=".8"
+ camera_angle="15">
+ <param_skeleton>
+ <bone
+ name="mNeck"
+ scale="1 1 0"
+ offset="0 0 0" />
+ </param_skeleton>
+ </param>
- <bone
- name="mCollarLeft"
- scale="0 0.2 0" />
+ <param
+ id="689"
+ group="1"
+ wearable="shape"
+ name="EyeBone_Big_Eyes"
+ edit_group="shape_eyes"
+ label_min="Eyes Back"
+ label_max="Eyes Forward"
+ value_min="-1"
+ value_max="1">
+ <param_skeleton>
+ <bone
+ name="mEyeLeft"
+ scale="0 0 0"
+ offset="-.005 0 0" />
+
+ <bone
+ name="mEyeRight"
+ scale="0 0 0"
+ offset="-.005 0 0" />
+ </param_skeleton>
+ </param>
- <bone
- name="mCollarRight"
- scale="0 0.2 0" />
+ <param
+ id="692"
+ group="0"
+ name="Leg Length"
+ wearable="shape"
+ edit_group="shape_legs"
+ edit_group_order="2"
+ label_min="Short Legs"
+ label_max="Long Legs"
+ value_min="-1"
+ value_max="1"
+ camera_distance="2.5">
+ <param_skeleton>
+ <bone
+ name="mHipLeft"
+ scale="0 0 .2" />
+
+ <bone
+ name="mHipRight"
+ scale="0 0 .2" />
+
+ <bone
+ name="mKneeRight"
+ scale="0 0 .2" />
+
+ <bone
+ name="mKneeLeft"
+ scale="0 0 .2" />
+ </param_skeleton>
+ </param>
- <bone
- name="mShoulderLeft"
- scale="0.1 0 0.1" />
+ <param
+ id="693"
+ group="0"
+ name="Arm Length"
+ wearable="shape"
+ edit_group="shape_torso"
+ edit_group_order="9"
+ label_min="Short Arms"
+ label_max="Long arms"
+ value_min="-1"
+ value_max="1"
+ value_default=".6"
+ camera_distance="1.5">
+ <param_skeleton>
+ <bone
+ name="mShoulderLeft"
+ scale="0 .2 0" />
+
+ <bone
+ name="mShoulderRight"
+ scale="0 .2 0" />
+
+ <bone
+ name="mElbowRight"
+ scale="0 .3 0" />
+
+ <bone
+ name="mElbowLeft"
+ scale="0 .3 0" />
+ </param_skeleton>
+ </param>
- <bone
- name="mShoulderRight"
- scale="0.1 0 0.1" />
+ <param
+ id="756"
+ group="0"
+ name="Neck Length"
+ wearable="shape"
+ edit_group="shape_torso"
+ edit_group_order="3"
+ label_min="Short Neck"
+ label_max="Long Neck"
+ value_min="-1"
+ value_max="1"
+ value_default="0"
+ camera_elevation=".3"
+ camera_distance=".8"
+ camera_angle="15">
+ <param_skeleton>
+ <bone
+ name="mNeck"
+ scale="0 0 .5" />
+ </param_skeleton>
+ </param>
+ </skeleton>
+
+ <mesh
+ type="hairMesh"
+ lod="0"
+ file_name="avatar_hair.llm"
+ min_pixel_width="320">
+ <!-- begin morph targets -->
+ <param
+ id="180"
+ group="1"
+ name="Hair_Volume"
+ label="Hair Volume"
+ show_simple="true"
+ wearable="hair"
+ clothing_morph="true"
+ edit_group="hair_style"
+ label_min="Less"
+ label_max="More"
+ value_min="0"
+ value_max="1.3"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_morph />
+ </param>
- <bone
- name="mElbowLeft"
- scale="0.1 0 0.1" />
+ <param
+ id="761"
+ group="1"
+ name="Hair_Volume_Small"
+ label="Hair Volume"
+ show_simple="true"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="Less"
+ label_max="More"
+ value_min="0"
+ value_max="1.3"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_morph />
+ </param>
- <bone
- name="mElbowRight"
- scale="0.1 0 0.1" />
+ <param
+ id="181"
+ group="0"
+ name="Hair_Big_Front"
+ label="Big Hair Front"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="5"
+ label_min="Less"
+ label_max="More"
+ value_min="-1"
+ value_max="1"
+ value_default="0.14"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="90">
+ <param_morph />
+ </param>
- <bone
- name="mChest"
- scale="0.1 0.1 0" />
+ <param
+ id="182"
+ group="0"
+ name="Hair_Big_Top"
+ label="Big Hair Top"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="6"
+ label_min="Less"
+ label_max="More"
+ value_min="-1"
+ value_max="1"
+ value_default=".7"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="90">
+ <param_morph />
+ </param>
- <bone
- name="mTorso"
- scale="0.1 0.1 0" />
+ <param
+ id="183"
+ group="0"
+ name="Hair_Big_Back"
+ clothing_morph="true"
+ label="Big Hair Back"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="7"
+ label_min="Less"
+ label_max="More"
+ value_min="-1"
+ value_max="1"
+ value_default="0.05"
+ camera_elevation=".1"
+ camera_distance=".7"
+ camera_angle="90">
+ <param_morph />
+ </param>
- <bone
- name="mPelvis"
- scale="0.1 0.1 0" />
+ <param
+ id="184"
+ group="0"
+ name="Hair_Spiked"
+ label="Spiked Hair"
+ show_simple="true"
+ wearable="hair"
+ clothing_morph="true"
+ edit_group="hair_style"
+ edit_group_order="15"
+ label_min="No Spikes"
+ label_max="Big Spikes"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_morph />
+ </param>
- <bone
- name="mHipLeft"
- scale="0.13 0.13 0" />
+ <param
+ id="140"
+ group="0"
+ name="Hair_Part_Middle"
+ label="Middle Part"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="17"
+ label_min="No Part"
+ label_max="Part"
+ value_min="0"
+ value_max="2"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="0">
+ <param_morph />
+ </param>
- <bone
- name="mHipRight"
- scale="0.13 0.13 0" />
+ <param
+ id="141"
+ group="0"
+ name="Hair_Part_Right"
+ label="Right Part"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="18"
+ label_min="No Part"
+ label_max="Part"
+ value_min="0"
+ value_max="2"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="0">
+ <param_morph />
+ </param>
- <bone
- name="mKneeLeft"
- scale="0.12 0.12 0" />
+ <param
+ id="142"
+ group="0"
+ name="Hair_Part_Left"
+ label="Left Part"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="19"
+ label_min="No Part"
+ label_max="Part"
+ value_min="0"
+ value_max="2"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="0">
+ <param_morph />
+ </param>
- <bone
- name="mKneeRight"
- scale="0.12 0.12 0" />
- </param_skeleton>
- </param>
+ <param
+ id="143"
+ group="0"
+ name="Hair_Sides_Full"
+ label="Full Hair Sides"
+ show_simple="true"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="11"
+ label_min="Mowhawk"
+ label_max="Full Sides"
+ value_min="-4"
+ value_max="1.5"
+ value_default="0.125"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_morph />
+ </param>
- <param
- id="36"
- group="0"
- name="Shoulders"
- label="Shoulders"
- wearable="shape"
- edit_group="shape_torso"
- edit_group_order="4"
- label_min="Narrow"
- label_max="Broad"
- show_simple="true"
- value_min="-1.8"
- value_max="1.4"
- value_default="-0.5"
- camera_elevation=".1"
- camera_distance="1.2"
- camera_angle="0">
- <param_skeleton>
- <bone
- name="mNeck"
- scale="0.01 0.03 0" />
+ <param
+ id="144"
+ group="1"
+ name="Bangs_Front_Up"
+ label="Front Bangs Up"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="Bangs"
+ label_max="Bangs Up"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_morph />
+ </param>
- <bone
- name="mCollarLeft"
- scale="0 0 0"
- offset="0 .02 0" />
+ <param
+ id="145"
+ group="1"
+ clothing_morph="true"
+ name="Bangs_Front_Down"
+ label="Front Bangs Down"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="Bangs"
+ label_max="Bangs Down"
+ value_min="0"
+ value_max="5"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_morph />
+ </param>
- <bone
- name="mCollarRight"
- scale="0 0 0"
- offset="0 -.02 0" />
+ <param
+ id="146"
+ group="1"
+ name="Bangs_Sides_Up"
+ label="Side Bangs Up"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="Side Bangs"
+ label_max="Side Bangs Up"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_morph />
+ </param>
- <bone
- name="mChest"
- scale="0.02 0.08 0" />
- </param_skeleton>
- </param>
+ <param
+ id="147"
+ group="1"
+ clothing_morph="true"
+ name="Bangs_Sides_Down"
+ label="Side Bangs Down"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="Side Bangs"
+ label_max="Side Bangs Down"
+ value_min="0"
+ value_max="2"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_morph />
+ </param>
- <param
- id="37"
- group="0"
- name="Hip Width"
- label="Hip Width"
- wearable="shape"
- edit_group="shape_legs"
- edit_group_order="3"
- label_min="Narrow"
- label_max="Wide"
- show_simple="true"
- value_min="-3.2"
- value_max="2.8"
- camera_distance="1.8">
- <param_skeleton>
- <bone
- name="mPelvis"
- scale="0 0.1 0" />
-
- <bone
- name="mHipLeft"
- scale="0 0 0"
- offset="0 .004 0" />
-
- <bone
- name="mHipRight"
- scale="0 0 0"
- offset="0 -.004 0" />
- </param_skeleton>
- </param>
-
- <param
- id="842"
- group="0"
- name="Hip Length"
- wearable="shape"
- edit_group="shape_legs"
- edit_group_order="3.2"
- label_min="Short hips"
- label_max="Long Hips"
- value_min="-1"
- value_max="1"
- camera_distance="1.8">
- <param_skeleton>
- <bone
- name="mPelvis"
- scale="0 0 0.3" />
- </param_skeleton>
- </param>
+ <param
+ id="148"
+ group="1"
+ name="Bangs_Back_Up"
+ label="Back Bangs Up"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="Back Bangs"
+ label_max="Back Bangs Up"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="150">
+ <param_morph />
+ </param>
- <param
- id="38"
- group="0"
- name="Torso Length"
- wearable="shape"
- edit_group="shape_torso"
- edit_group_order="11"
- label_min="Short Torso"
- label_max="Long Torso"
- value_min="-1"
- value_max="1"
- camera_distance="1.8">
- <param_skeleton>
- <bone
- name="mTorso"
- scale="0 0 .3" />
+ <param
+ id="149"
+ group="1"
+ name="Bangs_Back_Down"
+ label="Back Bangs Down"
+ clothing_morph="true"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="Back Bangs"
+ label_max="Back Bangs Down"
+ value_min="0"
+ value_max="2"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="150">
+ <param_morph />
+ </param>
- <bone
- name="mPelvis"
- scale="0 0 .1" />
+ <param
+ id="171"
+ group="1"
+ name="Hair_Front_Down"
+ label="Front Hair Down"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="Front Hair"
+ label_max="Front Hair Down"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_morph />
+ </param>
- <bone
- name="mHipLeft"
- scale="0 0 -.1" />
+ <param
+ id="172"
+ group="1"
+ name="Hair_Front_Up"
+ label="Front Hair Up"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="Front Hair"
+ label_max="Front Hair Up"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_morph />
+ </param>
- <bone
- name="mHipRight"
- scale="0 0 -.1" />
+ <param
+ id="173"
+ group="1"
+ name="Hair_Sides_Down"
+ label="Sides Hair Down"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="Sides Hair"
+ label_max="Sides Hair Down"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_morph />
+ </param>
- <bone
- name="mKneeRight"
- scale="0 0 -.05" />
+ <param
+ id="174"
+ group="1"
+ name="Hair_Sides_Up"
+ label="Sides Hair Up"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="Sides Hair"
+ label_max="Sides Hair Up"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_morph />
+ </param>
- <bone
- name="mKneeLeft"
- scale="0 0 -.05" />
- </param_skeleton>
- </param>
+ <param
+ id="175"
+ group="1"
+ name="Hair_Back_Down"
+ label="Back Hair Down"
+ clothing_morph="true"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="Back Hair"
+ label_max="Back Hair Down"
+ value_min="0"
+ value_max="3"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="150">
+ <param_morph />
+ </param>
- <param
- id="195"
- group="1"
- name="EyeBone_Spread"
- wearable="shape"
- edit_group="shape_eyes"
- label_min="Eyes Together"
- label_max="Eyes Spread"
- value_min="-1"
- value_max="1">
- <param_skeleton>
- <bone
- name="mEyeLeft"
- scale="0 0 0"
- offset="0 .009 0" />
+ <param
+ id="176"
+ group="1"
+ name="Hair_Back_Up"
+ label="Back Hair Up"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="Back Hair"
+ label_max="Back Hair Up"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="150">
+ <param_morph />
+ </param>
- <bone
- name="mEyeRight"
- scale="0 0 0"
- offset="0 -.009 0" />
- </param_skeleton>
- </param>
+ <param
+ id="177"
+ group="0"
+ name="Hair_Rumpled"
+ label="Rumpled Hair"
+ show_simple="true"
+ wearable="hair"
+ clothing_morph="true"
+ edit_group="hair_style"
+ edit_group_order="14.5"
+ label_min="Smooth Hair"
+ label_max="Rumpled Hair"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_morph />
+ </param>
- <param
- id="661"
- group="1"
- name="EyeBone_Head_Shear"
- wearable="shape"
- edit_group="shape_eyes"
- label_min="Eyes Shear Left Up"
- label_max="Eyes Shear Right Up"
- value_min="-2"
- value_max="2">
- <param_skeleton>
- <bone
- name="mEyeLeft"
- scale="0 0 0"
- offset="0 0 .004" />
+ <param
+ id="178"
+ group="1"
+ name="Hair_Swept_Back"
+ label="Swept Back Hair"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="NotHair"
+ label_max="Swept Back"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="90">
+ <param_morph />
+ </param>
- <bone
- name="mEyeRight"
- scale="0 0 0"
- offset="0 0 -.004" />
- </param_skeleton>
- </param>
+ <param
+ id="179"
+ group="1"
+ name="Hair_Swept_Forward"
+ label="Swept Forward Hair"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="Hair"
+ label_max="Swept Forward"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="90">
+ <param_morph />
+ </param>
- <param
- id="772"
- group="1"
- name="EyeBone_Head_Elongate"
- wearable="shape"
- edit_group="shape_eyes"
- label_min="Eyes Short Head"
- label_max="Eyes Long Head"
- value_min="-1"
- value_max="1">
- <param_skeleton>
- <bone
- name="mEyeLeft"
- scale="0 0 0"
- offset=".016 0 0" />
+ <param
+ id="190"
+ group="1"
+ name="Hair_Tilt_Right"
+ label="Hair Tilted Right"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="Hair"
+ label_max="Tilt Right"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="0">
+ <param_morph />
+ </param>
- <bone
- name="mEyeRight"
- scale="0 0 0"
- offset=".016 0 0" />
- </param_skeleton>
- </param>
+ <param
+ id="191"
+ group="1"
+ name="Hair_Tilt_Left"
+ label="Hair Tilted Left"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="Hair"
+ label_max="Tilt Left"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="0">
+ <param_morph />
+ </param>
- <param
- id="768"
- group="1"
- name="EyeBone_Bug"
- wearable="shape"
- edit_group="shape_eyes"
- label_min="Eyes Sunken"
- label_max="Eyes Bugged"
- value_min="-2"
- value_max="2">
- <param_skeleton>
- <bone
- name="mEyeLeft"
- scale="0 0 0"
- offset=".005 0 0" />
+ <param
+ id="192"
+ group="0"
+ name="Bangs_Part_Middle"
+ label="Part Bangs"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="20"
+ label_min="No Part"
+ label_max="Part Bangs"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="0">
+ <param_morph />
+ </param>
- <bone
- name="mEyeRight"
- scale="0 0 0"
- offset=".005 0 0" />
- </param_skeleton>
- </param>
+ <param
+ id="640"
+ group="1"
+ name="Hair_Egg_Head"
+ wearable="hair"
+ edit_group="hair_style"
+ cross_wearable="true"
+ value_min="-1.3"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="655"
- group="1"
- name="Head Size"
- label="Head Size"
- wearable="shape"
- edit_group="shape_head"
- label_min="Small Head"
- label_max="Big Head"
- show_simple="true"
- value_min="-.25"
- value_max=".10">
- <param_skeleton>
- <bone
- name="mSkull"
- scale="1 1 1"
- offset="0 0 0.1" />
-
- <bone
- name="mHead"
- scale="1 1 1"
- offset="0 0 0" />
-
- <bone
- name="mEyeLeft"
- scale="1 1 1"
- offset="0 0 0" />
-
- <bone
- name="mEyeRight"
- scale="1 1 1"
- offset="0 0 0" />
- </param_skeleton>
- </param>
-
- <param
- id="197"
- group="1"
- wearable="shoes"
- name="Shoe_Heels"
- edit_group="shoes"
- label_min="No Heels"
- label_max="High Heels"
- value_min="0"
- value_max="1">
- <param_skeleton>
- <bone
- name="mFootRight"
- scale="0 0 0"
- offset="0 0 -.08" />
+ <param
+ id="641"
+ group="1"
+ name="Hair_Squash_Stretch_Head"
+ wearable="hair"
+ edit_group="hair_style"
+ cross_wearable="true"
+ value_min="-.5"
+ value_max="1">
+ <param_morph />
+ </param>
- <bone
- name="mFootLeft"
- scale="0 0 0"
- offset="0 0 -.08" />
- </param_skeleton>
- </param>
+ <param
+ id="642"
+ group="1"
+ name="Hair_Square_Head"
+ wearable="hair"
+ edit_group="hair_style"
+ cross_wearable="true"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="502"
- group="1"
- wearable="shoes"
- name="Shoe_Platform"
- edit_group="shoes"
- label_min="No Heels"
- label_max="High Heels"
- value_min="0"
- value_max="1">
- <param_skeleton>
- <bone
- name="mFootRight"
- scale="0 0 0"
- offset="0 0 -.07" />
+ <param
+ id="643"
+ group="1"
+ name="Hair_Round_Head"
+ wearable="hair"
+ edit_group="hair_style"
+ cross_wearable="true"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <bone
- name="mFootLeft"
- scale="0 0 0"
- offset="0 0 -.07" />
- </param_skeleton>
- </param>
+ <param
+ id="644"
+ group="1"
+ name="Hair_Forehead_Round"
+ wearable="hair"
+ edit_group="hair_style"
+ cross_wearable="true"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="675"
- group="0"
- name="Hand Size"
- wearable="shape"
- edit_group="shape_torso"
- edit_group_order="10"
- label_min="Small Hands"
- label_max="Large Hands"
- value_min="-.3"
- value_max=".3"
- camera_elevation=".1"
- camera_distance="1.4"
- camera_angle="0">
- <param_skeleton>
- <bone
- name="mWristRight"
- scale="1 1 1"
- offset="0 0 0" />
+ <param
+ id="645"
+ group="1"
+ name="Hair_Forehead_Slant"
+ wearable="hair"
+ edit_group="hair_style"
+ cross_wearable="true"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <bone
- name="mWristLeft"
- scale="1 1 1"
- offset="0 0 0" />
- </param_skeleton>
- </param>
+ <param
+ id="774"
+ group="1"
+ name="Shear_Head_Hair"
+ wearable="hair"
+ edit_group="hair_style"
+ cross_wearable="true"
+ value_min="-2"
+ value_max="2">
+ <param_morph />
+ </param>
- <param
- id="683"
- group="0"
- name="Neck Thickness"
- wearable="shape"
- edit_group="shape_torso"
- edit_group_order="2"
- label_min="Skinny Neck"
- label_max="Thick Neck"
- value_min="-.4"
- value_max=".2"
- value_default="-.15"
- camera_elevation=".3"
- camera_distance=".8"
- camera_angle="15">
- <param_skeleton>
- <bone
- name="mNeck"
- scale="1 1 0"
- offset="0 0 0" />
- </param_skeleton>
- </param>
-
- <param
- id="689"
- group="1"
- wearable="shape"
- name="EyeBone_Big_Eyes"
- edit_group="shape_eyes"
- label_min="Eyes Back"
- label_max="Eyes Forward"
- value_min="-1"
- value_max="1">
- <param_skeleton>
- <bone
- name="mEyeLeft"
- scale="0 0 0"
- offset="-.005 0 0" />
+ <param
+ id="771"
+ group="1"
+ name="Elongate_Head_Hair"
+ wearable="hair"
+ edit_group="hair_style"
+ cross_wearable="true"
+ value_min="-1"
+ value_max="1">
+ <param_morph />
+ </param>
- <bone
- name="mEyeRight"
- scale="0 0 0"
- offset="-.005 0 0" />
- </param_skeleton>
- </param>
+ <param
+ id="674"
+ group="0"
+ name="Hair_Shear_Back"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="12"
+ label="Shear Back"
+ label_min="Full Back"
+ label_max="Sheared Back"
+ value_min="-1"
+ value_max="2"
+ value_default="-0.3"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="100">
+ <param_morph />
+ </param>
- <param
- id="692"
- group="0"
- name="Leg Length"
- wearable="shape"
- edit_group="shape_legs"
- edit_group_order="2"
- label_min="Short Legs"
- label_max="Long Legs"
- value_min="-1"
- value_max="1"
- camera_distance="2.5">
- <param_skeleton>
- <bone
- name="mHipLeft"
- scale="0 0 .2" />
+ <param
+ id="762"
+ group="0"
+ name="Hair_Shear_Front"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="11.8"
+ label="Shear Front"
+ show_simple="true"
+ label_min="Full Front"
+ label_max="Sheared Front"
+ value_min="0"
+ value_max="3"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="30">
+ <param_morph />
+ </param>
- <bone
- name="mHipRight"
- scale="0 0 .2" />
+ <param
+ id="754"
+ group="0"
+ name="Hair_Taper_Back"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="14"
+ label="Taper Back"
+ label_min="Wide Back"
+ label_max="Narrow Back"
+ value_min="-1"
+ value_max="2"
+ value_default="0"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="160">
+ <param_morph />
+ </param>
- <bone
- name="mKneeRight"
- scale="0 0 .2" />
+ <param
+ id="755"
+ group="0"
+ name="Hair_Taper_Front"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="13"
+ label="Taper Front"
+ label_min="Wide Front"
+ label_max="Narrow Front"
+ value_min="-1.5"
+ value_max="1.5"
+ value_default="0.05"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_morph />
+ </param>
- <bone
- name="mKneeLeft"
- scale="0 0 .2" />
- </param_skeleton>
- </param>
+ <param
+ id="782"
+ group="1"
+ clothing_morph="true"
+ name="Hair_Pigtails_Short"
+ wearable="hair"
+ edit_group="hair_style"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="693"
- group="0"
- name="Arm Length"
- wearable="shape"
- edit_group="shape_torso"
- edit_group_order="9"
- label_min="Short Arms"
- label_max="Long arms"
- value_min="-1"
- value_max="1"
- value_default=".6"
- camera_distance="1.5">
- <param_skeleton>
- <bone
- name="mShoulderLeft"
- scale="0 .2 0" />
+ <param
+ id="783"
+ group="1"
+ clothing_morph="true"
+ name="Hair_Pigtails_Med"
+ wearable="hair"
+ edit_group="hair_style"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <bone
- name="mShoulderRight"
- scale="0 .2 0" />
+ <param
+ id="790"
+ group="1"
+ clothing_morph="true"
+ name="Hair_Pigtails_Medlong"
+ wearable="hair"
+ edit_group="hair_style"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <bone
- name="mElbowRight"
- scale="0 .3 0" />
+ <param
+ id="784"
+ group="1"
+ clothing_morph="true"
+ name="Hair_Pigtails_Long"
+ wearable="hair"
+ edit_group="hair_style"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <bone
- name="mElbowLeft"
- scale="0 .3 0" />
- </param_skeleton>
- </param>
+ <param
+ id="786"
+ group="1"
+ name="Hair_Ponytail_Short"
+ wearable="hair"
+ edit_group="hair_style"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="756"
+ <param
+ id="787"
+ group="1"
+ name="Hair_Ponytail_Med"
+ wearable="hair"
+ edit_group="hair_style"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="788"
+ group="1"
+ name="Hair_Ponytail_Long"
+ clothing_morph="true"
+ wearable="hair"
+ edit_group="hair_style"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <!-- #end morph targets -->
+ </mesh>
+
+ <mesh
+ type="hairMesh"
+ lod="1"
+ file_name="avatar_hair_1.llm"
+ min_pixel_width="160"
+ reference="avatar_hair.llm">
+ </mesh>
+
+ <mesh
+ type="hairMesh"
+ lod="2"
+ file_name="avatar_hair_2.llm"
+ min_pixel_width="80"
+ reference="avatar_hair.llm">
+ </mesh>
+
+ <mesh
+ type="hairMesh"
+ lod="3"
+ file_name="avatar_hair_3.llm"
+ min_pixel_width="40"
+ reference="avatar_hair.llm">
+ </mesh>
+
+ <mesh
+ type="hairMesh"
+ lod="4"
+ file_name="avatar_hair_4.llm"
+ min_pixel_width="20"
+ reference="avatar_hair.llm">
+ </mesh>
+
+ <mesh
+ type="hairMesh"
+ lod="5"
+ file_name="avatar_hair_5.llm"
+ min_pixel_width="0"
+ reference="avatar_hair.llm">
+ </mesh>
+
+ <mesh
+ type="headMesh"
+ lod="0"
+ file_name="avatar_head.llm"
+ min_pixel_width="320">
+ <!--
+ begin morph targets
+ #############
+ tweakable morphs
+ #############
+ -->
+ <param
+ id="1"
+ group="0"
+ name="Big_Brow"
+ label="Brow Size"
+ wearable="shape"
+ edit_group="shape_head"
+ edit_group_order="7"
+ label_min="Small"
+ label_max="Large"
+ value_min="-.3"
+ value_max="2"
+ camera_elevation=".1"
+ camera_distance=".4"
+ camera_angle="45">
+ <param_morph />
+ </param>
+
+ <param
+ id="2"
+ group="0"
+ name="Nose_Big_Out"
+ label="Nose Size"
+ wearable="shape"
+ edit_group="shape_nose"
+ edit_group_order="1"
+ label_min="Small"
+ label_max="Large"
+ show_simple="true"
+ value_min="-0.8"
+ value_max="2.5"
+ camera_elevation=".1"
+ camera_distance=".35"
+ camera_angle="50">
+ <param_morph />
+ </param>
+
+ <param
+ id="4"
+ group="0"
+ name="Broad_Nostrils"
+ label="Nostril Width"
+ wearable="shape"
+ edit_group="shape_nose"
+ edit_group_order="3"
+ label_min="Narrow"
+ label_max="Broad"
+ value_min="-.5"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".3"
+ camera_angle="-20">
+ <param_morph />
+ </param>
+
+ <param
+ id="759"
+ group="0"
+ name="Low_Septum_Nose"
+ label="Nostril Division"
+ wearable="shape"
+ edit_group="shape_nose"
+ edit_group_order="3.5"
+ label_min="High"
+ label_max="Low"
+ value_min="-1"
+ value_max="1.5"
+ value_default="0.5"
+ camera_elevation=".1"
+ camera_distance=".3"
+ camera_angle="-20">
+ <param_morph />
+ </param>
+
+ <param
+ id="517"
+ group="0"
+ name="Wide_Nose"
+ label="Nose Width"
+ wearable="shape"
+ edit_group="shape_nose"
+ edit_group_order="2"
+ label_min="Narrow"
+ label_max="Wide"
+ show_simple="true"
+ value_min="-.5"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".3"
+ camera_angle="-20">
+ <param_morph />
+ </param>
+
+ <param
+ id="5"
+ group="0"
+ name="Cleft_Chin"
+ label="Chin Cleft"
+ wearable="shape"
+ edit_group="shape_chin"
+ edit_group_order="6"
+ label_min="Round"
+ label_max="Cleft"
+ value_min="-.1"
+ value_max="1"
+ camera_elevation="0"
+ camera_distance=".28"
+ camera_angle="-20">
+ <param_morph />
+ </param>
+
+ <param
+ id="6"
+ group="0"
+ name="Bulbous_Nose_Tip"
+ label="Nose Tip Shape"
+ wearable="shape"
+ edit_group="shape_nose"
+ edit_group_order="8"
+ label_min="Pointy"
+ label_max="Bulbous"
+ value_min="-.3"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".35"
+ camera_angle="15">
+ <param_morph />
+ </param>
+
+ <param
+ id="7"
+ group="0"
+ name="Weak_Chin"
+ label="Chin Angle"
+ wearable="shape"
+ edit_group="shape_chin"
+ edit_group_order="1"
+ label_min="Chin Out"
+ label_max="Chin In"
+ value_min="-.5"
+ value_max=".5"
+ camera_elevation=".1"
+ camera_distance=".4"
+ camera_angle="45">
+ <param_morph />
+ </param>
+
+ <param
+ id="8"
+ group="0"
+ name="Double_Chin"
+ label="Chin-Neck"
+ wearable="shape"
+ edit_group="shape_chin"
+ edit_group_order="8"
+ label_min="Tight Chin"
+ label_max="Double Chin"
+ value_min="-.5"
+ value_max="1.5"
+ camera_elevation="-.1"
+ camera_distance=".3"
+ camera_angle="60">
+ <param_morph />
+ </param>
+
+ <param
+ id="10"
+ group="0"
+ name="Sunken_Cheeks"
+ label="Lower Cheeks"
+ wearable="shape"
+ edit_group="shape_head"
+ edit_group_order="9"
+ label_min="Well-Fed"
+ label_max="Sunken"
+ show_simple="true"
+ value_min="-1.5"
+ value_max="3"
+ camera_elevation=".1"
+ camera_distance=".4"
+ camera_angle="5">
+ <param_morph />
+ </param>
+
+ <param
+ id="11"
+ group="0"
+ name="Noble_Nose_Bridge"
+ label="Upper Bridge"
+ wearable="shape"
+ edit_group="shape_nose"
+ edit_group_order="5"
+ label_min="Low"
+ label_max="High"
+ value_min="-.5"
+ value_max="1.5"
+ camera_elevation=".1"
+ camera_distance=".35"
+ camera_angle="70">
+ <param_morph />
+ </param>
+
+ <param
+ id="758"
+ group="0"
+ name="Lower_Bridge_Nose"
+ label="Lower Bridge"
+ wearable="shape"
+ edit_group="shape_nose"
+ edit_group_order="5.5"
+ label_min="Low"
+ label_max="High"
+ value_min="-1.5"
+ value_max="1.5"
+ camera_elevation=".1"
+ camera_distance=".35"
+ camera_angle="70">
+ <param_morph />
+ </param>
+
+ <param
+ id="12"
+ group="0"
+ name="Jowls"
+ wearable="shape"
+ edit_group="shape_chin"
+ edit_group_order="5"
+ label_min="Less"
+ label_max="More"
+ value_min="-.5"
+ value_max="2.5"
+ camera_elevation=".1"
+ camera_distance=".4"
+ camera_angle="0">
+ <param_morph />
+ </param>
+
+ <param
+ id="13"
+ group="0"
+ name="Cleft_Chin_Upper"
+ label="Upper Chin Cleft"
+ wearable="shape"
+ edit_group="shape_chin"
+ edit_group_order="7"
+ label_min="Round"
+ label_max="Cleft"
+ value_min="0"
+ value_max="1.5"
+ camera_elevation="0"
+ camera_distance=".28"
+ camera_angle="-20">
+ <param_morph />
+ </param>
+
+ <param
+ id="14"
+ group="0"
+ name="High_Cheek_Bones"
+ label="Cheek Bones"
+ wearable="shape"
+ edit_group="shape_head"
+ edit_group_order="10"
+ label_min="Low"
+ label_max="High"
+ value_min="-.5"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".3"
+ camera_angle="-20">
+ <param_morph />
+ </param>
+
+ <param
+ id="15"
+ group="0"
+ name="Ears_Out"
+ label="Ear Angle"
+ wearable="shape"
+ edit_group="shape_ears"
+ edit_group_order="2"
+ label_min="In"
+ label_max="Out"
+ value_min="-.5"
+ value_max="1.5"
+ camera_elevation=".1"
+ camera_distance=".3"
+ camera_angle="-20">
+ <param_morph />
+ </param>
+
+ <!--Pointy eyebrows became a driver/driven param with new max value for backwards compatibility between 1.0 and 1.1-->
+ <param
+ id="870"
+ group="1"
+ name="Pointy_Eyebrows"
+ label="Eyebrow Points"
+ wearable="hair"
+ edit_group="hair_eyebrows"
+ edit_group_order="4"
+ label_min="Smooth"
+ label_max="Pointy"
+ value_min="-.5"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".3">
+ <param_morph />
+ </param>
+
+ <param
+ id="17"
+ group="0"
+ name="Square_Jaw"
+ label="Jaw Shape"
+ wearable="shape"
+ edit_group="shape_chin"
+ edit_group_order="2"
+ label_min="Pointy"
+ label_max="Square"
+ value_min="-.5"
+ value_max="1"
+ camera_distance=".3"
+ camera_elevation=".04"
+ camera_angle="-20">
+ <param_morph />
+ </param>
+
+ <param
+ id="18"
+ group="0"
+ name="Puffy_Upper_Cheeks"
+ label="Upper Cheeks"
+ wearable="shape"
+ edit_group="shape_head"
+ edit_group_order="8"
+ label_min="Thin"
+ label_max="Puffy"
+ value_min="-1.5"
+ value_max="2.5"
+ camera_elevation=".1"
+ camera_distance=".3"
+ camera_angle="-20">
+ <param_morph />
+ </param>
+
+ <param
+ id="19"
+ group="0"
+ name="Upturned_Nose_Tip"
+ label="Nose Tip Angle"
+ wearable="shape"
+ edit_group="shape_nose"
+ edit_group_order="7"
+ label_min="Downturned"
+ label_max="Upturned"
+ value_min="-1.5"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".35"
+ camera_angle="15">
+ <param_morph />
+ </param>
+
+ <param
+ id="20"
+ group="0"
+ name="Bulbous_Nose"
+ label="Nose Thickness"
+ wearable="shape"
+ edit_group="shape_nose"
+ edit_group_order="4"
+ label_min="Thin Nose"
+ label_max="Bulbous Nose"
+ show_simple="true"
+ value_min="-.5"
+ value_max="1.5"
+ camera_elevation=".1"
+ camera_distance=".3">
+ <param_morph />
+ </param>
+
+ <param
+ id="21"
+ group="0"
+ name="Upper_Eyelid_Fold"
+ label="Upper Eyelid Fold"
+ wearable="shape"
+ edit_group="shape_eyes"
+ edit_group_order="5"
+ label_min="Uncreased"
+ label_max="Creased"
+ value_min="-0.2"
+ value_max="1.3"
+ camera_elevation=".1"
+ camera_distance=".35">
+ <param_morph />
+ </param>
+
+ <param
+ id="22"
+ group="0"
+ name="Attached_Earlobes"
+ label="Attached Earlobes"
+ wearable="shape"
+ edit_group="shape_ears"
+ edit_group_order="3"
+ label_min="Unattached"
+ label_max="Attached"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".3"
+ camera_angle="45">
+ <param_morph />
+ </param>
+
+ <param
+ id="23"
+ group="0"
+ name="Baggy_Eyes"
+ label="Eye Bags"
+ wearable="shape"
+ edit_group="shape_eyes"
+ edit_group_order="6"
+ label_min="Smooth"
+ label_max="Baggy"
+ value_min="-.5"
+ value_max="1.5"
+ camera_elevation=".1"
+ camera_distance=".35">
+ <param_morph />
+ </param>
+
+ <param
+ id="765"
+ group="0"
+ name="Puffy_Lower_Lids"
+ label="Puffy Eyelids"
+ wearable="shape"
+ edit_group="shape_eyes"
+ edit_group_order="6.1"
+ label_min="Flat"
+ label_max="Puffy"
+ value_min="-.3"
+ value_max="2.5"
+ camera_elevation=".1"
+ camera_distance=".35">
+ <param_morph />
+ </param>
+
+ <param
+ id="24"
+ group="0"
+ name="Wide_Eyes"
+ label="Eye Opening"
+ wearable="shape"
+ edit_group="shape_eyes"
+ edit_group_order="1.1"
+ label_min="Narrow"
+ label_max="Wide"
+ value_min="-1.5"
+ value_max="2"
+ show_simple="true"
+ camera_elevation=".1"
+ camera_distance=".35">
+ <param_morph />
+ </param>
+
+ <param
+ id="25"
+ group="0"
+ name="Wide_Lip_Cleft"
+ label="Lip Cleft"
+ wearable="shape"
+ edit_group="shape_mouth"
+ edit_group_order="6"
+ label_min="Narrow"
+ label_max="Wide"
+ value_min="-.8"
+ value_max="1.5"
+ camera_elevation="0"
+ camera_distance=".28">
+ <param_morph />
+ </param>
+
+ <param
+ id="764"
+ group="0"
+ name="Lip_Cleft_Deep"
+ label="Lip Cleft Depth"
+ wearable="shape"
+ edit_group="shape_mouth"
+ edit_group_order="5.8"
+ label_min="Shallow"
+ label_max="Deep"
+ value_min="-.5"
+ value_max="1.2"
+ camera_elevation="0"
+ camera_distance=".28">
+ <param_morph />
+ </param>
+
+ <param
+ id="26"
+ group="1"
+ wearable="shape"
+ name="Lips_Thin"
+ edit_group="driven"
+ value_min="0"
+ value_max=".7">
+ <param_morph />
+ </param>
+
+ <param
+ id="27"
+ group="0"
+ name="Wide_Nose_Bridge"
+ label="Bridge Width"
+ wearable="shape"
+ edit_group="shape_nose"
+ edit_group_order="6"
+ label_min="Narrow"
+ label_max="Wide"
+ value_min="-1.3"
+ value_max="1.2"
+ camera_elevation=".1"
+ camera_distance=".3"
+ camera_angle="-20">
+ <param_morph />
+ </param>
+
+ <param
+ id="28"
+ group="1"
+ name="Lips_Fat"
+ wearable="shape"
+ edit_group="driven"
+ value_min="0"
+ value_max="2">
+ <param_morph />
+ </param>
+
+ <param
+ id="29"
+ group="1"
+ name="Wide_Upper_Lip"
+ wearable="shape"
+ edit_group="driven"
+ value_min="-.7"
+ value_max="1.3">
+ <param_morph />
+ </param>
+
+ <param
+ id="30"
+ group="1"
+ name="Wide_Lower_Lip"
+ wearable="shape"
+ edit_group="driven"
+ value_min="-.7"
+ value_max="1.3">
+ <param_morph />
+ </param>
+
+ <!--Arced eyebrows became a driver/driven param with new max value for backwards compatibility between 1.0 and 1.1-->
+ <param
+ id="872"
+ group="1"
+ name="Arced_Eyebrows"
+ label="Eyebrow Arc"
+ wearable="hair"
+ edit_group="hair_eyebrows"
+ edit_group_order="3"
+ label_min="Flat"
+ label_max="Arced"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <!--Lower eyebrows became a driver/driven param with new min value for backwards compatibility between 1.0 and 1.1-->
+ <param
+ id="871"
+ group="1"
+ name="Lower_Eyebrows"
+ label="Eyebrow Height"
+ show_simple="true"
+ wearable="hair"
+ edit_group="hair_eyebrows"
+ edit_group_order="2.5"
+ label_min="Higher"
+ label_max="Lower"
+ value_min="-2"
+ value_max="2">
+ <param_morph />
+ </param>
+
+ <param
+ id="35"
+ group="0"
+ name="Big_Ears"
+ label="Ear Size"
+ wearable="shape"
+ edit_group="shape_ears"
+ edit_group_order="1"
+ label_min="Small"
+ label_max="Large"
+ value_min="-1"
+ value_max="2"
+ camera_elevation=".1"
+ camera_distance=".3"
+ camera_angle="45">
+ <param_morph />
+ </param>
+
+ <param
+ id="796"
+ group="0"
+ name="Pointy_Ears"
+ label="Ear Tips"
+ wearable="shape"
+ edit_group="shape_ears"
+ edit_group_order="4"
+ label_min="Flat"
+ label_max="Pointy"
+ value_min="-.4"
+ value_max="3"
+ camera_elevation=".1"
+ camera_distance=".3"
+ camera_angle="45">
+ <param_morph />
+ </param>
+
+ <param
+ id="185"
+ group="0"
+ name="Deep_Chin"
+ label="Chin Depth"
+ wearable="shape"
+ edit_group="shape_chin"
+ edit_group_order="3"
+ label_min="Shallow"
+ label_max="Deep"
+ value_min="-1"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".4"
+ camera_angle="30">
+ <param_morph />
+ </param>
+
+ <param
+ id="186"
+ group="1"
+ name="Egg_Head"
+ label="Egg Head"
+ wearable="shape"
+ edit_group="shape_head"
+ label_min="Chin Heavy"
+ label_max="Forehead Heavy"
+ value_min="-1.3"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_morph />
+ </param>
+
+ <param
+ id="187"
+ group="1"
+ name="Squash_Stretch_Head"
+ label="Squash/Stretch Head"
+ wearable="shape"
+ edit_group="shape_head"
+ label_min="Squash Head"
+ label_max="Stretch Head"
+ value_min="-.5"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_morph>
+ <volume_morph
+ name="HEAD"
+ scale="-0.008 -0.006 0.015"/>
+ </param_morph>
+ </param>
+
+ <param
+ id="188"
+ group="1"
+ name="Square_Head"
+ wearable="shape"
+ label_min="Less Square"
+ label_max="More Square"
+ value_min="0"
+ value_max=".7"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_morph />
+ </param>
+
+ <param
+ id="189"
+ group="1"
+ wearable="shape"
+ name="Round_Head"
+ label_min="Less Round"
+ label_max="More Round"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_morph />
+ </param>
+
+ <param
+ id="194"
+ group="1"
+ name="Eye_Spread"
+ wearable="shape"
+ edit_group="shape_eyes"
+ label_min="Eyes Together"
+ label_max="Eyes Spread"
+ value_min="-2"
+ value_max="2">
+ <param_morph />
+ </param>
+
+ <param
+ id="400"
+ sex="male"
+ group="1"
+ name="Displace_Hair_Facial"
+ label="Hair Thickess"
+ wearable="hair"
+ edit_group="hair_facial"
+ label_min="Cropped Hair"
+ label_max="Bushy Hair"
+ value_min="0"
+ value_max="2">
+ <param_morph />
+ </param>
+
+ <param
+ id="506"
+ group="0"
+ name="Mouth_Height"
+ wearable="shape"
+ label="Mouth Position"
+ show_simple="true"
+ edit_group="shape_mouth"
+ edit_group_order="4"
+ label_min="High"
+ label_max="Low"
+ value_min="-2"
+ value_max="2"
+ camera_distance=".3"
+ camera_elevation=".04">
+ <param_morph />
+ </param>
+
+ <param
+ id="633"
+ group="1"
+ name="Fat_Head"
+ label="Fat Head"
+ wearable="shape"
+ edit_group="shape_body"
+ label_min="Skinny"
+ label_max="Fat"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".3">
+ <param_morph/>
+ </param>
+
+ <param
+ id="630"
+ group="1"
+ name="Forehead_Round"
+ label="Round Forehead"
+ wearable="shape"
+ label_min="Less"
+ label_max="More"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="631"
+ group="1"
+ name="Forehead_Slant"
+ label="Slanted Forehead"
+ wearable="shape"
+ label_min="Less"
+ label_max="More"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="650"
+ group="0"
+ name="Eyelid_Corner_Up"
+ label="Outer Eye Corner"
+ wearable="shape"
+ edit_group="shape_eyes"
+ edit_group_order="4"
+ label_min="Corner Down"
+ label_max="Corner Up"
+ value_min="-1.3"
+ value_max="1.2"
+ camera_elevation=".1"
+ camera_distance=".30">
+ <param_morph />
+ </param>
+
+ <param
+ id="880"
group="0"
- name="Neck Length"
+ name="Eyelid_Inner_Corner_Up"
+ label="Inner Eye Corner"
wearable="shape"
- edit_group="shape_torso"
- edit_group_order="3"
- label_min="Short Neck"
- label_max="Long Neck"
- value_min="-1"
- value_max="1"
- value_default="0"
- camera_elevation=".3"
- camera_distance=".8"
- camera_angle="15">
- <param_skeleton>
- <bone
- name="mNeck"
- scale="0 0 .5" />
- </param_skeleton>
- </param>
- </skeleton>
-
- <mesh
- type="hairMesh"
- lod="0"
- file_name="avatar_hair.llm"
- min_pixel_width="320">
-<!-- begin morph targets -->
- <param
- id="180"
- group="1"
- name="Hair_Volume"
- label="Hair Volume"
- show_simple="true"
- wearable="hair"
- clothing_morph="true"
- edit_group="hair_style"
- label_min="Less"
- label_max="More"
- value_min="0"
- value_max="1.3"
+ edit_group="shape_eyes"
+ edit_group_order="4.2"
+ label_min="Corner Down"
+ label_max="Corner Up"
+ value_min="-1.3"
+ value_max="1.2"
camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_morph />
- </param>
+ camera_distance=".30">
+ <param_morph />
+ </param>
+
- <param
- id="761"
- group="1"
- name="Hair_Volume_Small"
- label="Hair Volume"
- show_simple="true"
- wearable="hair"
- edit_group="hair_style"
- label_min="Less"
- label_max="More"
- value_min="0"
- value_max="1.3"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_morph />
- </param>
+ <param
+ id="653"
+ group="0"
+ name="Tall_Lips"
+ wearable="shape"
+ label="Lip Fullness"
+ show_simple="true"
+ edit_group="shape_mouth"
+ edit_group_order="2"
+ label_min="Less Full"
+ label_max="More Full"
+ value_min="-1"
+ value_max="2"
+ camera_distance=".3"
+ camera_elevation=".04">
+ <param_morph />
+ </param>
- <param
- id="181"
- group="0"
- name="Hair_Big_Front"
- label="Big Hair Front"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="5"
- label_min="Less"
- label_max="More"
- value_min="-1"
- value_max="1"
- value_default="0.14"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="90">
- <param_morph />
- </param>
+ <param
+ id="656"
+ group="0"
+ name="Crooked_Nose"
+ wearable="shape"
+ label="Crooked Nose"
+ edit_group="shape_nose"
+ edit_group_order="9"
+ label_min="Nose Left"
+ label_max="Nose Right"
+ value_min="-2"
+ value_max="2"
+ camera_distance=".3"
+ camera_elevation=".04"
+ camera_angle="-20">
+ <param_morph />
+ </param>
- <param
- id="182"
- group="0"
- name="Hair_Big_Top"
- label="Big Hair Top"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="6"
- label_min="Less"
- label_max="More"
- value_min="-1"
- value_max="1"
- value_default=".7"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="90">
- <param_morph />
- </param>
+ <param
+ id="657"
+ group="1"
+ name="Smile_Mouth"
+ wearable="shape"
+ label="Mouth Corner"
+ edit_group="shape_mouth"
+ label_min="Corner Normal"
+ label_max="Corner Up"
+ value_min="0"
+ value_max="1.4"
+ camera_distance=".3"
+ camera_elevation=".04">
+ <param_morph />
+ </param>
- <param
- id="183"
- group="0"
- name="Hair_Big_Back"
- clothing_morph="true"
- label="Big Hair Back"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="7"
- label_min="Less"
- label_max="More"
- value_min="-1"
- value_max="1"
- value_default="0.05"
- camera_elevation=".1"
- camera_distance=".7"
- camera_angle="90">
- <param_morph />
- </param>
+ <param
+ id="658"
+ group="1"
+ name="Frown_Mouth"
+ wearable="shape"
+ label="Mouth Corner"
+ edit_group="shape_mouth"
+ label_min="Corner Normal"
+ label_max="Corner Down"
+ value_min="0"
+ value_max="1.2"
+ camera_distance=".3"
+ camera_elevation=".04">
+ <param_morph />
+ </param>
- <param
- id="184"
- group="0"
- name="Hair_Spiked"
- label="Spiked Hair"
- show_simple="true"
- wearable="hair"
- clothing_morph="true"
- edit_group="hair_style"
- edit_group_order="15"
- label_min="No Spikes"
- label_max="Big Spikes"
- value_min="0"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_morph />
- </param>
+ <param
+ id="797"
+ group="1"
+ name="Fat_Upper_Lip"
+ wearable="shape"
+ label="Fat Upper Lip"
+ edit_group="shape_mouth"
+ label_min="Normal Upper"
+ label_max="Fat Upper"
+ value_min="0"
+ value_max="1.5"
+ camera_distance=".3"
+ camera_elevation=".04">
+ <param_morph />
+ </param>
- <param
- id="140"
- group="0"
- name="Hair_Part_Middle"
- label="Middle Part"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="17"
- label_min="No Part"
- label_max="Part"
- value_min="0"
- value_max="2"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="0">
- <param_morph />
- </param>
+ <param
+ id="798"
+ group="1"
+ name="Fat_Lower_Lip"
+ wearable="shape"
+ label="Fat Lower Lip"
+ edit_group="shape_mouth"
+ label_min="Normal Lower"
+ label_max="Fat Lower"
+ value_min="0"
+ value_max="1.5"
+ camera_distance=".3"
+ camera_elevation=".04">
+ <param_morph />
+ </param>
- <param
- id="141"
- group="0"
- name="Hair_Part_Right"
- label="Right Part"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="18"
- label_min="No Part"
- label_max="Part"
- value_min="0"
- value_max="2"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="0">
- <param_morph />
- </param>
+ <param
+ id="660"
+ group="1"
+ name="Shear_Head"
+ wearable="shape"
+ label="Shear Face"
+ edit_group="shape_head"
+ label_min="Shear Left"
+ label_max="Shear Right"
+ value_min="-2"
+ value_max="2"
+ value_default="0"
+ camera_distance=".5"
+ camera_elevation=".04">
+ <param_morph />
+ </param>
- <param
- id="142"
- group="0"
- name="Hair_Part_Left"
- label="Left Part"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="19"
- label_min="No Part"
- label_max="Part"
- value_min="0"
- value_max="2"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="0">
- <param_morph />
- </param>
+ <param
+ id="770"
+ group="1"
+ name="Elongate_Head"
+ wearable="shape"
+ label="Shear Face"
+ edit_group="shape_head"
+ label_min="Flat Head"
+ label_max="Long Head"
+ value_min="-1"
+ value_max="1"
+ value_default="0"
+ camera_distance=".5"
+ camera_elevation=".04">
+ <param_morph>
+ <volume_morph
+ name="HEAD"
+ scale="0.02 0.0 0.0"/>
+ </param_morph>
+ </param>
- <param
- id="143"
- group="0"
- name="Hair_Sides_Full"
- label="Full Hair Sides"
- show_simple="true"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="11"
- label_min="Mowhawk"
- label_max="Full Sides"
- value_min="-4"
- value_max="1.5"
- value_default="0.125"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_morph />
- </param>
+ <param
+ id="663"
+ group="0"
+ name="Shift_Mouth"
+ wearable="shape"
+ label="Shift Mouth"
+ edit_group="shape_mouth"
+ edit_group_order="7"
+ label_min="Shift Left"
+ label_max="Shift Right"
+ value_min="-2"
+ value_max="2"
+ value_default="0"
+ camera_distance=".35"
+ camera_elevation=".04"
+ camera_angle="-20">
+ <param_morph />
+ </param>
- <param
- id="144"
- group="1"
- name="Bangs_Front_Up"
- label="Front Bangs Up"
- wearable="hair"
- edit_group="hair_style"
- label_min="Bangs"
- label_max="Bangs Up"
- value_min="0"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_morph />
- </param>
+ <param
+ id="664"
+ group="0"
+ name="Pop_Eye"
+ wearable="shape"
+ label="Eye Pop"
+ edit_group="shape_eyes"
+ edit_group_order="8"
+ label_min="Pop Right Eye"
+ label_max="Pop Left Eye"
+ value_min="-1.3"
+ value_max="1.3"
+ value_default="0"
+ camera_elevation=".1"
+ camera_distance=".35">
+ <param_morph />
+ </param>
- <param
- id="145"
- group="1"
- clothing_morph="true"
- name="Bangs_Front_Down"
- label="Front Bangs Down"
- wearable="hair"
- edit_group="hair_style"
- label_min="Bangs"
- label_max="Bangs Down"
- value_min="0"
- value_max="5"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_morph />
- </param>
+ <param
+ id="760"
+ group="0"
+ name="Jaw_Angle"
+ wearable="shape"
+ label="Jaw Angle"
+ edit_group="shape_chin"
+ edit_group_order="3.5"
+ label_min="Low Jaw"
+ label_max="High Jaw"
+ value_min="-1.2"
+ value_max="2"
+ value_default="0"
+ camera_distance=".5"
+ camera_elevation=".04"
+ camera_angle="70">
+ <param_morph />
+ </param>
- <param
- id="146"
- group="1"
- name="Bangs_Sides_Up"
- label="Side Bangs Up"
- wearable="hair"
- edit_group="hair_style"
- label_min="Side Bangs"
- label_max="Side Bangs Up"
- value_min="0"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_morph />
- </param>
+ <param
+ id="665"
+ group="0"
+ name="Jaw_Jut"
+ wearable="shape"
+ label="Jaw Jut"
+ edit_group="shape_chin"
+ edit_group_order="4"
+ label_min="Overbite"
+ label_max="Underbite"
+ value_min="-2"
+ value_max="2"
+ value_default="0"
+ camera_distance=".5"
+ camera_elevation=".04"
+ camera_angle="70">
+ <param_morph />
+ </param>
- <param
- id="147"
- group="1"
- clothing_morph="true"
- name="Bangs_Sides_Down"
- label="Side Bangs Down"
- wearable="hair"
- edit_group="hair_style"
- label_min="Side Bangs"
- label_max="Side Bangs Down"
- value_min="0"
- value_max="2"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_morph />
- </param>
+ <param
+ id="686"
+ group="1"
+ name="Head_Eyes_Big"
+ wearable="shape"
+ label="Eye Size"
+ edit_group="shape_eyes"
+ label_min="Beady Eyes"
+ label_max="Anime Eyes"
+ show_simple="true"
+ value_min="-2"
+ value_max="2"
+ value_default="0">
+ <param_morph />
+ </param>
- <param
- id="148"
- group="1"
- name="Bangs_Back_Up"
- label="Back Bangs Up"
- wearable="hair"
- edit_group="hair_style"
- label_min="Back Bangs"
- label_max="Back Bangs Up"
- value_min="0"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="150">
- <param_morph />
- </param>
+ <param
+ id="767"
+ group="1"
+ name="Bug_Eyed_Head"
+ wearable="shape"
+ label="Eye Depth"
+ edit_group="shape_eyes"
+ edit_group_order="4.5"
+ label_min="Sunken Eyes"
+ label_max="Bug Eyes"
+ value_min="-2"
+ value_max="2"
+ value_default="0">
+ <param_morph />
+ </param>
+
+ <!--
+ #Fat_Lips = Fat_Lips 34 1 0 1
+ #Wide_Lips = Wide_Lips 35 1 0 1
+ #Wide_Nose = Wide_Nose 36 1 0 1
+ -->
+ <!--
+ ##############
+ # Facial Expression morphs
+ ##############
+ -->
+ <param
+ id="300"
+ group="1"
+ name="Express_Closed_Mouth"
+ value_default="1"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="149"
- group="1"
- name="Bangs_Back_Down"
- label="Back Bangs Down"
- clothing_morph="true"
- wearable="hair"
- edit_group="hair_style"
- label_min="Back Bangs"
- label_max="Back Bangs Down"
- value_min="0"
- value_max="2"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="150">
- <param_morph />
- </param>
+ <param
+ id="301"
+ group="1"
+ name="Express_Tongue_Out"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="171"
- group="1"
- name="Hair_Front_Down"
- label="Front Hair Down"
- wearable="hair"
- edit_group="hair_style"
- label_min="Front Hair"
- label_max="Front Hair Down"
- value_min="0"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_morph />
- </param>
+ <param
+ id="302"
+ group="1"
+ name="Express_Surprise_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="172"
- group="1"
- name="Hair_Front_Up"
- label="Front Hair Up"
- wearable="hair"
- edit_group="hair_style"
- label_min="Front Hair"
- label_max="Front Hair Up"
- value_min="0"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_morph />
- </param>
+ <param
+ id="303"
+ group="1"
+ name="Express_Wink_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="173"
- group="1"
- name="Hair_Sides_Down"
- label="Sides Hair Down"
- wearable="hair"
- edit_group="hair_style"
- label_min="Sides Hair"
- label_max="Sides Hair Down"
- value_min="0"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_morph />
- </param>
+ <param
+ id="304"
+ group="1"
+ name="Express_Embarrassed_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="174"
- group="1"
- name="Hair_Sides_Up"
- label="Sides Hair Up"
- wearable="hair"
- edit_group="hair_style"
- label_min="Sides Hair"
- label_max="Sides Hair Up"
- value_min="0"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_morph />
- </param>
+ <param
+ id="305"
+ group="1"
+ name="Express_Shrug_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="175"
- group="1"
- name="Hair_Back_Down"
- label="Back Hair Down"
- clothing_morph="true"
- wearable="hair"
- edit_group="hair_style"
- label_min="Back Hair"
- label_max="Back Hair Down"
- value_min="0"
- value_max="3"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="150">
- <param_morph />
- </param>
+ <param
+ id="306"
+ group="1"
+ name="Express_Kiss"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="176"
- group="1"
- name="Hair_Back_Up"
- label="Back Hair Up"
- wearable="hair"
- edit_group="hair_style"
- label_min="Back Hair"
- label_max="Back Hair Up"
- value_min="0"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="150">
- <param_morph />
- </param>
+ <param
+ id="307"
+ group="1"
+ name="Express_Bored_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="177"
- group="0"
- name="Hair_Rumpled"
- label="Rumpled Hair"
- show_simple="true"
- wearable="hair"
- clothing_morph="true"
- edit_group="hair_style"
- edit_group_order="14.5"
- label_min="Smooth Hair"
- label_max="Rumpled Hair"
- value_min="0"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_morph />
- </param>
+ <param
+ id="308"
+ group="1"
+ name="Express_Repulsed_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="178"
- group="1"
- name="Hair_Swept_Back"
- label="Swept Back Hair"
- wearable="hair"
- edit_group="hair_style"
- label_min="NotHair"
- label_max="Swept Back"
- value_min="0"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="90">
- <param_morph />
- </param>
+ <param
+ id="309"
+ group="1"
+ name="Express_Disdain"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="179"
- group="1"
- name="Hair_Swept_Forward"
- label="Swept Forward Hair"
- wearable="hair"
- edit_group="hair_style"
- label_min="Hair"
- label_max="Swept Forward"
- value_min="0"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="90">
- <param_morph />
- </param>
+ <param
+ id="310"
+ group="1"
+ name="Express_Afraid_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="190"
- group="1"
- name="Hair_Tilt_Right"
- label="Hair Tilted Right"
- wearable="hair"
- edit_group="hair_style"
- label_min="Hair"
- label_max="Tilt Right"
- value_min="0"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="0">
- <param_morph />
- </param>
+ <param
+ id="311"
+ group="1"
+ name="Express_Worry_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="191"
- group="1"
- name="Hair_Tilt_Left"
- label="Hair Tilted Left"
- wearable="hair"
- edit_group="hair_style"
- label_min="Hair"
- label_max="Tilt Left"
- value_min="0"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="0">
- <param_morph />
- </param>
+ <param
+ id="312"
+ group="1"
+ name="Express_Cry_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="192"
- group="0"
- name="Bangs_Part_Middle"
- label="Part Bangs"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="20"
- label_min="No Part"
- label_max="Part Bangs"
- value_min="0"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="0">
- <param_morph />
- </param>
+ <param
+ id="313"
+ group="1"
+ name="Express_Sad_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="640"
- group="1"
- name="Hair_Egg_Head"
- wearable="hair"
- edit_group="hair_style"
- value_min="-1.3"
- value_max="1">
- <param_morph />
- </param>
+ <param
+ id="314"
+ group="1"
+ name="Express_Anger_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="641"
- group="1"
- name="Hair_Squash_Stretch_Head"
- wearable="hair"
- edit_group="hair_style"
- value_min="-.5"
- value_max="1">
- <param_morph />
- </param>
+ <param
+ id="315"
+ group="1"
+ name="Express_Frown"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="642"
- group="1"
- name="Hair_Square_Head"
- wearable="hair"
- edit_group="hair_style"
- value_min="0"
- value_max="1">
- <param_morph />
- </param>
+ <param
+ id="316"
+ group="1"
+ name="Express_Laugh_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
- <param
- id="643"
- group="1"
- name="Hair_Round_Head"
- wearable="hair"
- edit_group="hair_style"
- value_min="0"
- value_max="1">
- <param_morph />
- </param>
+ <param
+ id="317"
+ group="1"
+ name="Express_Toothsmile"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="318"
+ group="1"
+ name="Express_Smile"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="632"
+ group="1"
+ name="Express_Open_Mouth"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <!--
+ ##############
+ # Lipsync morphs
+ ##############
+ -->
+
+ <param
+ id="70"
+ group="1"
+ name="Lipsync_Aah"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="71"
+ group="1"
+ name="Lipsync_Ooh"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <!--
+ ##############
+ # other morphs (not user controlled)
+ ##############
+ -->
+ <param
+ id="40"
+ group="1"
+ name="Male_Head"
+ wearable="shape"
+ edit_group="driven"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="41"
+ group="1"
+ name="Old"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <!--
+ ##############
+ # animatable morphs
+ ##############
+ -->
+ <param
+ id="51"
+ group="1"
+ name="Furrowed_Eyebrows"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="53"
+ group="1"
+ name="Surprised_Eyebrows"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="54"
+ group="1"
+ name="Worried_Eyebrows"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="55"
+ group="1"
+ name="Frown_Mouth"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="57"
+ group="1"
+ name="Smile_Mouth"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="58"
+ group="1"
+ name="Blink_Left"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="59"
+ group="1"
+ name="Blink_Right"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <!--
+ #end morph targets
+ -->
+ </mesh>
+
+ <mesh
+ type="headMesh"
+ lod="1"
+ file_name="avatar_head_1.llm"
+ min_pixel_width="160"
+ reference="avatar_head.llm">
+ </mesh>
+
+ <mesh
+ type="headMesh"
+ lod="2"
+ file_name="avatar_head_2.llm"
+ min_pixel_width="80"
+ reference="avatar_head.llm">
+ </mesh>
+
+ <mesh
+ type="headMesh"
+ lod="3"
+ file_name="avatar_head_3.llm"
+ min_pixel_width="40"
+ reference="avatar_head.llm">
+ </mesh>
+
+ <mesh
+ type="headMesh"
+ lod="4"
+ file_name="avatar_head_4.llm"
+ min_pixel_width="0"
+ reference="avatar_head.llm">
+ </mesh>
+
+ <mesh
+ type="eyelashMesh"
+ lod="0"
+ file_name="avatar_eyelashes.llm"
+ min_pixel_width="320">
+ <param
+ shared="1"
+ id="660"
+ group="1"
+ name="Shear_Head"
+ wearable="shape"
+ label="Shear Face"
+ edit_group="shape_head"
+ label_min="Shear Left"
+ label_max="Shear Right"
+ value_min="-2"
+ value_max="2"
+ value_default="0"
+ camera_distance=".5"
+ camera_elevation=".04">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="770"
+ group="1"
+ name="Elongate_Head"
+ wearable="shape"
+ label="Shear Face"
+ edit_group="shape_head"
+ label_min="Flat Head"
+ label_max="Long Head"
+ value_min="-1"
+ value_max="1"
+ value_default="0"
+ camera_distance=".5"
+ camera_elevation=".04">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="664"
+ group="0"
+ name="Pop_Eye"
+ wearable="shape"
+ label="Eye Pop"
+ edit_group="shape_eyes"
+ edit_group_order="8"
+ label_min="Pop Right Eye"
+ label_max="Pop Left Eye"
+ value_min="-2"
+ value_max="2"
+ value_default="0"
+ camera_distance=".5"
+ camera_elevation=".04"
+ camera_angle="-20">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="21"
+ group="0"
+ name="Upper_Eyelid_Fold"
+ label="Upper Eyelid Fold"
+ wearable="shape"
+ edit_group="shape_eyes"
+ label_min="Uncreased"
+ label_max="Creased"
+ value_min="-0.2"
+ value_max="1.3"
+ camera_elevation=".1"
+ camera_distance=".35">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="24"
+ group="0"
+ name="Wide_Eyes"
+ label="Eye Opening"
+ wearable="shape"
+ edit_group="shape_eyes"
+ label_min="Narrow"
+ label_max="Wide"
+ show_simple="true"
+ value_min="-1.5"
+ value_max="2"
+ camera_elevation=".1"
+ camera_distance=".3">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="186"
+ group="1"
+ name="Egg_Head"
+ label="Egg Head"
+ wearable="shape"
+ edit_group="shape_head"
+ label_min="Chin Heavy"
+ label_max="Forehead Heavy"
+ value_min="-1.3"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="187"
+ group="1"
+ name="Squash_Stretch_Head"
+ label="Squash/Stretch Head"
+ wearable="shape"
+ edit_group="shape_head"
+ label_min="Squash Head"
+ label_max="Stretch Head"
+ value_min="-.5"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="194"
+ group="1"
+ name="Eye_Spread"
+ edit_group="shape_eyes"
+ label_min="Eyes Together"
+ label_max="Eyes Spread"
+ value_min="-2"
+ value_max="2">
+ <param_morph />
+ </param>
+
+ <param
+ id="518"
+ group="0"
+ name="Eyelashes_Long"
+ wearable="shape"
+ label="Eyelash Length"
+ edit_group="shape_eyes"
+ edit_group_order="7"
+ label_min="Short"
+ label_max="Long"
+ value_min="-.3"
+ value_max="1.5"
+ camera_elevation=".1"
+ camera_distance=".30"
+ camera_angle="-20">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="650"
+ group="0"
+ name="Eyelid_Corner_Up"
+ label="Outer Eye Corner"
+ wearable="shape"
+ edit_group="shape_eyes"
+ label_min="Corner Down"
+ label_max="Corner Up"
+ value_min="-1.3"
+ value_max="1.2"
+ camera_elevation=".1"
+ camera_distance=".3">
+ <param_morph />
+ </param>
+
+
+ <param
+ shared="1"
+ id="880"
+ group="0"
+ name="Eyelid_Inner_Corner_Up"
+ label="Inner Eye Corner"
+ wearable="shape"
+ edit_group="shape_eyes"
+ label_min="Corner Down"
+ label_max="Corner Up"
+ value_min="-1.3"
+ value_max="1.2"
+ camera_elevation=".1"
+ camera_distance=".3">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="686"
+ group="1"
+ name="Head_Eyes_Big"
+ wearable="shape"
+ label="Eye Size"
+ edit_group="shape_eyes"
+ label_min="Beady Eyes"
+ label_max="Anime Eyes"
+ value_min="-2"
+ value_max="2"
+ show_simple="true"
+ value_default="0">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="767"
+ group="1"
+ name="Bug_Eyed_Head"
+ wearable="shape"
+ label="Eye Depth"
+ edit_group="shape_eyes"
+ edit_group_order="4.5"
+ label_min="Sunken Eyes"
+ label_max="Bug Eyes"
+ value_min="-2"
+ value_max="2"
+ value_default="0">
+ <param_morph />
+ </param>
+
+ <!--
+ ##############
+ # Facial Expression morphs
+ ##############
+ -->
+ <param
+ shared="1"
+ id="301"
+ group="1"
+ name="Express_Tongue_Out"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="302"
+ group="1"
+ name="Express_Surprise_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="303"
+ group="1"
+ name="Express_Wink_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="304"
+ group="1"
+ name="Express_Embarrassed_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="305"
+ group="1"
+ name="Express_Shrug_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="306"
+ group="1"
+ name="Express_Kiss"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="307"
+ group="1"
+ name="Express_Bored_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="308"
+ group="1"
+ name="Express_Repulsed_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="309"
+ group="1"
+ name="Express_Disdain"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="310"
+ group="1"
+ name="Express_Afraid_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="312"
+ group="1"
+ name="Express_Cry_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="313"
+ group="1"
+ name="Express_Sad_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="314"
+ group="1"
+ name="Express_Anger_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="315"
+ group="1"
+ name="Express_Frown"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="316"
+ group="1"
+ name="Express_Laugh_Emote"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="317"
+ group="1"
+ name="Express_Toothsmile"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="318"
+ group="1"
+ name="Express_Smile"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <!--
+ ##############
+ # other morphs (not user controlled)
+ ##############
+ -->
+ <param
+ shared="1"
+ id="41"
+ group="1"
+ name="Old"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <!--
+ ##############
+ # animatable morphs
+ ##############
+ -->
+ <param
+ shared="1"
+ id="58"
+ group="1"
+ name="Blink_Left"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ shared="1"
+ id="59"
+ group="1"
+ name="Blink_Right"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+ </mesh>
+
+ <!--
+ #headMesh2 =
+ #headMesh3 =
+ -->
+ <mesh
+ type="upperBodyMesh"
+ lod="0"
+ file_name="avatar_upper_body.llm"
+ min_pixel_width="320">
+ <!--
+ #begin morph targets
+ #############
+ # tweakable morphs
+ #############
+ -->
+ <param
+ id="104"
+ group="1"
+ name="Big_Belly_Torso"
+ wearable="shape"
+ edit_group="driven"
+ value_min="0"
+ value_max="1">
+ <param_morph>
+ <volume_morph
+ name="BELLY"
+ scale="0.075 0.04 0.03"
+ pos="0.07 0 -0.07"/>
+ </param_morph>
+ </param>
+
+ <param
+ id="626"
+ sex="female"
+ group="1"
+ name="Big_Chest"
+ label="Chest Size"
+ wearable="shape"
+ edit_group="shape_torso"
+ label_min="Small"
+ label_max="Large"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance="1"
+ camera_angle="15">
+ <param_morph />
+ </param>
+
+ <param
+ id="627"
+ sex="female"
+ group="1"
+ name="Small_Chest"
+ label="Chest Size"
+ wearable="shape"
+ edit_group="shape_torso"
+ label_min="Large"
+ label_max="Small"
+ value_min="0"
+ value_max="1"
+ camera_elevation="0"
+ camera_distance=".28">
+ <param_morph />
+ </param>
+
+ <param
+ id="843"
+ sex="female"
+ group="1"
+ name="No_Chest"
+ label="Chest Size"
+ wearable="shape"
+ edit_group="shape_torso"
+ label_min="Some"
+ label_max="None"
+ value_min="0"
+ value_max="1"
+ camera_elevation="0"
+ camera_distance=".28">
+ <param_morph />
+ </param>
+
+ <param
+ id="106"
+ group="1"
+ name="Muscular_Torso"
+ label="Torso Muscles"
+ show_simple="true"
+ wearable="shape"
+ edit_group="shape_torso"
+ label_min="Regular"
+ label_max="Muscular"
+ value_min="0"
+ value_max="1.4"
+ camera_elevation=".3"
+ camera_distance="1.2">
+ <param_morph>
+ <volume_morph
+ name="L_CLAVICLE"
+ scale="0.02 0.0 0.005"
+ pos="0.0 0 0.005"/>
+ <volume_morph
+ name="L_UPPER_ARM"
+ scale="0.015 0.0 0.005"
+ pos="0.015 0 0"/>
+ <volume_morph
+ name="L_LOWER_ARM"
+ scale="0.005 0.0 0.005"
+ pos="0.005 0 0"/>
+ <volume_morph
+ name="R_CLAVICLE"
+ scale="0.02 0.0 0.005"
+ pos="0.0 0 0.005"/>
+ <volume_morph
+ name="R_UPPER_ARM"
+ scale="0.015 0.0 0.005"
+ pos="0.015 0 0"/>
+ <volume_morph
+ name="R_LOWER_ARM"
+ scale="0.005 0.0 0.005"
+ pos="0.005 0 0"/>
+ </param_morph>
+ </param>
+
+ <param
+ id="648"
+ group="1"
+ sex="female"
+ name="Scrawny_Torso"
+ label="Torso Muscles"
+ show_simple="true"
+ wearable="shape"
+ edit_group="shape_torso"
+ label_min="Regular"
+ label_max="Scrawny"
+ value_min="0"
+ value_max="1.3"
+ camera_elevation=".3"
+ camera_distance="1.2">
+ <param_morph>
+ <volume_morph
+ name="BELLY"
+ scale="0.0 -0.01 0.0"
+ pos="0.0 0.0 0"/>
+ <volume_morph
+ name="CHEST"
+ scale="-0.01 -0.01 0.0"
+ pos="0.01 0.0 0"/>
+ <volume_morph
+ name="L_CLAVICLE"
+ scale="0.0 -0.03 -0.005"
+ pos="0.0 0 -0.005"/>
+ <volume_morph
+ name="L_UPPER_ARM"
+ scale="-0.01 -0.01 -0.02"
+ pos="0 0 0"/>
+ <volume_morph
+ name="L_LOWER_ARM"
+ scale="-0.005 0.0 -0.01"
+ pos="-0.005 0 0"/>
+ <volume_morph
+ name="R_CLAVICLE"
+ scale="0.0 -0.03 -0.005"
+ pos="0.0 0 -0.005"/>
+ <volume_morph
+ name="R_UPPER_ARM"
+ scale="-0.01 -0.01 -0.02"
+ pos="0 0 0"/>
+ <volume_morph
+ name="R_LOWER_ARM"
+ scale="-0.005 0.0 -0.01"
+ pos="-0.005 0 0"/>
+ </param_morph>
+ </param>
+
+ <param
+ id="677"
+ group="1"
+ sex="male"
+ name="Scrawny_Torso_Male"
+ label="Torso Scrawny"
+ wearable="shape"
+ edit_group="shape_torso"
+ label_min="Regular"
+ label_max="Scrawny"
+ value_min="0"
+ value_max="1.3"
+ camera_elevation=".3"
+ camera_distance="1.2">
+ <param_morph>
+ <volume_morph
+ name="BELLY"
+ scale="-0.01 -0.01 0.0"
+ pos="0.01 0.0 0"/>
+ <volume_morph
+ name="CHEST"
+ scale="-0.02 -0.02 0.0"
+ pos="0.01 0.0 0"/>
+ <volume_morph
+ name="L_CLAVICLE"
+ scale="0.0 -0.03 -0.005"
+ pos="0.0 0 -0.005"/>
+ <volume_morph
+ name="L_UPPER_ARM"
+ scale="-0.01 -0.01 -0.02"
+ pos="0 0 0"/>
+ <volume_morph
+ name="L_LOWER_ARM"
+ scale="-0.005 0.0 -0.01"
+ pos="-0.005 0 0"/>
+ <volume_morph
+ name="R_CLAVICLE"
+ scale="0.0 -0.03 -0.005"
+ pos="0.0 0 -0.005"/>
+ <volume_morph
+ name="R_UPPER_ARM"
+ scale="-0.01 -0.01 -0.02"
+ pos="0 0 0"/>
+ <volume_morph
+ name="R_LOWER_ARM"
+ scale="-0.005 0.0 -0.01"
+ pos="-0.005 0 0"/>
+ </param_morph>
+ </param>
+
+ <param
+ id="634"
+ group="1"
+ name="Fat_Torso"
+ label="Fat Torso"
+ wearable="shape"
+ edit_group="shape_body"
+ label_min="skinny"
+ label_max="fat"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".3">
+ <param_morph>
+ <volume_morph
+ name="CHEST"
+ scale="0.02 0.03 0.03"
+ pos="0 0 -0.03"/>
+ <volume_morph
+ name="BELLY"
+ scale="0.09 0.08 0.07"
+ pos="0 0 -0.05"/>
+ <volume_morph
+ name="L_CLAVICLE"
+ scale="0.0 0.0 0.015"/>
+ <volume_morph
+ name="L_UPPER_ARM"
+ scale="0.02 0.0 0.02"
+ pos="0.0 0.0 -0.02"/>
+ <volume_morph
+ name="L_LOWER_ARM"
+ scale="0.01 0.0 0.01"
+ pos="0.0 0.0 -0.01"/>
+ <volume_morph
+ name="R_CLAVICLE"
+ scale="0.0 0.0 0.015"/>
+ <volume_morph
+ name="R_UPPER_ARM"
+ scale="0.02 0.0 0.02"
+ pos="0.0 0.0 -0.02"/>
+ <volume_morph
+ name="R_LOWER_ARM"
+ scale="0.01 0.0 0.01"
+ pos="0.0 0.0 -0.01"/>
+ <volume_morph
+ name="NECK"
+ scale="0.015 0.01 0.0"/>
+ <volume_morph
+ name="HEAD"
+ scale="0.0 0.0 0.01"
+ pos="0 0 -0.01"/>
+ </param_morph>
+
+ </param>
+
+ <param
+ id="507"
+ group="0"
+ sex="female"
+ name="Breast_Gravity"
+ label="Breast Buoyancy"
+ wearable="shape"
+ edit_group="shape_torso"
+ edit_group_order="7"
+ label_min="Less Gravity"
+ label_max="More Gravity"
+ value_default="0"
+ value_min="-1.5"
+ value_max="2"
+ camera_elevation=".3"
+ camera_distance=".8">
+ <param_morph />
+ </param>
+
+ <param
+ id="628"
+ group="1"
+ name="Displace_Loose_Upperbody"
+ label="Shirt Fit"
+ wearable="shirt"
+ edit_group="driven"
+ clothing_morph="true"
+ value_min="0"
+ value_max="1"
+ value_default="0">
+ <param_morph />
+ </param>
+
+ <param
+ id="840"
+ group="0"
+ name="Shirtsleeve_flair"
+ label="Sleeve Looseness"
+ show_simple="true"
+ wearable="shirt"
+ edit_group="shirt"
+ edit_group_order="6"
+ clothing_morph="true"
+ label_min="Tight Sleeves"
+ label_max="Loose Sleeves"
+ value_min="0"
+ value_max="1.5"
+ camera_distance="1.8"
+ camera_angle="30"
+ camera_elevation="-.3">
+ <param_morph />
+ </param>
+
+ <param
+ id="855"
+ group="1"
+ name="Love_Handles"
+ wearable="shape"
+ edit_group="driven"
+ value_default="0"
+ value_min="-1"
+ value_max="2">
+ <param_morph>
+ <volume_morph
+ name="BELLY"
+ scale="0.0 0.02 0.0"/>
+ </param_morph>
+ </param>
+
+ <param
+ id="684"
+ group="0"
+ sex="female"
+ name="Breast_Female_Cleavage"
+ label="Breast Cleavage"
+ wearable="shape"
+ edit_group="shape_torso"
+ edit_group_order="8"
+ label_min="Separate"
+ label_max="Join"
+ value_default="0"
+ value_min="-.3"
+ value_max="1.3"
+ camera_elevation=".3"
+ camera_distance=".8">
+ <param_morph />
+ </param>
+
+ <param
+ id="685"
+ group="0"
+ sex="male"
+ name="Chest_Male_No_Pecs"
+ label="Pectorals"
+ wearable="shape"
+ edit_group="shape_torso"
+ edit_group_order="5"
+ label_min="Big Pectorals"
+ label_max="Sunken Chest"
+ value_default="0"
+ value_min="-.5"
+ value_max="1.1"
+ camera_elevation=".3"
+ camera_distance="1.2">
+ <param_morph />
+ </param>
+
+ <!-- ############# #
+ other morphs (not user controlled)
+ ############# -->
+ <param
+ id="100"
+ group="1"
+ name="Male_Torso"
+ wearable="shape"
+ edit_group="driven"
+ label_min="Male_Torso"
+ value_min="0"
+ value_max="1">
+ <param_morph>
+ <volume_morph
+ name="CHEST"
+ scale="0.03 0.04 0.02"
+ pos="-0.03 0 -0.01"/>
+ <volume_morph
+ name="BELLY"
+ scale="0.03 0.03 0.0"
+ pos="-0.03 0 0.02"/>
+ <volume_morph
+ name="L_CLAVICLE"
+ scale="0.02 0.0 0.01"
+ pos="-0.02 0 0"/>
+ <volume_morph
+ name="L_UPPER_ARM"
+ scale="0.01 0.0 0.01"
+ pos="0.0 0.0 -0.01"/>
+ <volume_morph
+ name="L_LOWER_ARM"
+ scale="0.005 0.0 0.005"
+ pos="0.0 0.0 -0.005"/>
+ <volume_morph
+ name="R_CLAVICLE"
+ scale="0.02 0.0 0.01"
+ pos="-0.02 0 0"/>
+ <volume_morph
+ name="R_UPPER_ARM"
+ scale="0.01 0.0 0.01"
+ pos="0.0 0.0 -0.01"/>
+ <volume_morph
+ name="R_LOWER_ARM"
+ scale="0.005 0.0 0.005"
+ pos="0.0 0.0 -0.005"/>
+ <volume_morph
+ name="NECK"
+ scale="0.015 0.01 0.0"/>
+ <volume_morph
+ name="HEAD"
+ scale="0.0 0.0 0.01"
+ pos="0 0 -0.01"/>
+ </param_morph>
+ </param>
+
+ <!--
+ ##############
+ # animatable morphs
+ ##############
+ -->
+ <param
+ id="101"
+ group="1"
+ name="Hands_Relaxed"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="102"
+ group="1"
+ name="Hands_Point"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="103"
+ group="1"
+ name="Hands_Fist"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="666"
+ group="1"
+ name="Hands_Relaxed_L"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="667"
+ group="1"
+ name="Hands_Point_L"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="668"
+ group="1"
+ name="Hands_Fist_L"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="669"
+ group="1"
+ name="Hands_Relaxed_R"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="670"
+ group="1"
+ name="Hands_Point_R"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="671"
+ group="1"
+ name="Hands_Fist_R"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="672"
+ group="1"
+ name="Hands_Typing"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="766"
+ group="1"
+ name="Hands_Salute_R"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="791"
+ group="1"
+ name="Hands_Peace_R"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="792"
+ group="1"
+ name="Hands_Spread_R"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <!--
+ #end morph targets
+ -->
+ </mesh>
+
+ <mesh
+ type="upperBodyMesh"
+ lod="1"
+ file_name="avatar_upper_body_1.llm"
+ min_pixel_width="160"
+ reference="avatar_upper_body.llm">
+ </mesh>
+
+ <mesh
+ type="upperBodyMesh"
+ lod="2"
+ file_name="avatar_upper_body_2.llm"
+ min_pixel_width="80"
+ reference="avatar_upper_body.llm">
+ </mesh>
+
+ <mesh
+ type="upperBodyMesh"
+ lod="3"
+ file_name="avatar_upper_body_3.llm"
+ min_pixel_width="40"
+ reference="avatar_upper_body.llm">
+ </mesh>
+
+ <mesh
+ type="upperBodyMesh"
+ lod="4"
+ file_name="avatar_upper_body_4.llm"
+ min_pixel_width="0"
+ reference="avatar_upper_body.llm">
+ </mesh>
+
+ <!--
+ #upperBodyMesh2 =
+ #upperBodyMesh3 =
+ -->
+ <mesh
+ type="lowerBodyMesh"
+ lod="0"
+ file_name="avatar_lower_body.llm"
+ min_pixel_width="320">
+ <!--
+ #begin morph targets
+ #############
+ # tweakable morphs
+ #############
+ -->
+ <param
+ id="156"
+ group="1"
+ name="Big_Belly_Legs"
+ wearable="shape"
+ edit_group="driven"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="151"
+ group="1"
+ name="Big_Butt_Legs"
+ label="Butt Size"
+ wearable="shape"
+ edit_group="shape_legs"
+ label_min="Regular"
+ label_max="Large"
+ value_min="0"
+ value_max="1">
+ <param_morph>
+ <volume_morph
+ name="PELVIS"
+ scale="0.03 0.0 0.02"
+ pos="-0.03 0 -0.025"/>
+ </param_morph>
+ </param>
+
+ <param
+ id="794"
+ group="1"
+ name="Small_Butt"
+ label="Butt Size"
+ wearable="shape"
+ edit_group="shape_legs"
+ label_min="Regular"
+ label_max="Small"
+ value_min="0"
+ value_max="1">
+ <param_morph>
+ <volume_morph
+ name="PELVIS"
+ scale="-0.01 0.0 0.0"
+ pos="0.01 0 0.0"/>
+ </param_morph>
+ </param>
+
+ <param
+ id="152"
+ group="1"
+ name="Muscular_Legs"
+ label="Leg Muscles"
+ show_simple="true"
+ wearable="shape"
+ edit_group="shape_legs"
+ label_min="Regular Muscles"
+ label_max="More Muscles"
+ value_min="0"
+ value_max="1.5"
+ camera_distance="1.3"
+ camera_elevation="-.5">
+ <param_morph>
+ <volume_morph
+ name="L_UPPER_LEG"
+ scale="0.015 0.015 0.0"
+ pos="0.0 0 0.0"/>
+ <volume_morph
+ name="L_LOWER_LEG"
+ scale="0.01 0.01 0.0"
+ pos="0.0 0 0.0"/>
+ <volume_morph
+ name="R_UPPER_LEG"
+ scale="0.015 0.015 0.0"
+ pos="0.0 0 0.0"/>
+ <volume_morph
+ name="R_LOWER_LEG"
+ scale="0.01 0.01 0.0"
+ pos="0.0 0 0.0"/>
+ </param_morph>
+ </param>
+
+ <param
+ id="651"
+ group="1"
+ name="Scrawny_Legs"
+ label="Scrawny Leg"
+ wearable="shape"
+ edit_group="shape_legs"
+ label_min="Regular Muscles"
+ label_max="Less Muscles"
+ value_min="0"
+ value_max="1.5"
+ camera_distance="1.3"
+ camera_elevation="-.5">
+ <param_morph>
+ <volume_morph
+ name="L_UPPER_LEG"
+ scale="-0.03 -0.03 0.0"
+ pos="0.0 0 0.0"/>
+ <volume_morph
+ name="L_LOWER_LEG"
+ scale="-0.015 -0.015 0.0"
+ pos="0.0 0 0.0"/>
+ <volume_morph
+ name="R_UPPER_LEG"
+ scale="-0.03 -0.03 0.0"
+ pos="0.0 0 0.0"/>
+ <volume_morph
+ name="R_LOWER_LEG"
+ scale="-0.015 -0.015 0.0"
+ pos="0.0 0 0.0"/>
+ </param_morph>
+ </param>
+
+ <param
+ id="853"
+ group="1"
+ name="Bowed_Legs"
+ label="Knee Angle"
+ wearable="shape"
+ value_min="-1"
+ value_max="1">
+ <param_morph>
+ <volume_morph
+ name="L_UPPER_LEG"
+ pos="0.0 0.03 0.0"/>
+ <volume_morph
+ name="L_LOWER_LEG"
+ pos="0.0 0.03 0.0"/>
+ <volume_morph
+ name="R_UPPER_LEG"
+ pos="0.0 -0.03 0.0"/>
+ <volume_morph
+ name="R_LOWER_LEG"
+ pos="0.0 -0.03 0.0"/>
+ </param_morph>
+ </param>
+
+ <param
+ id="500"
+ group="1"
+ name="Shoe_Heel_Height"
+ label="Heel Height"
+ wearable="shoes"
+ edit_group="shoes"
+ label_min="Low Heels"
+ label_max="High Heels"
+ value_min="0"
+ value_max="1"
+ camera_distance="1.5"
+ camera_elevation="-.5">
+ <param_morph />
+ </param>
+
+ <param
+ id="501"
+ group="1"
+ name="Shoe_Platform_Height"
+ label="Platform Height"
+ wearable="shoes"
+ edit_group="shoes"
+ label_min="Low Platforms"
+ label_max="High Platforms"
+ value_min="0"
+ value_max="1"
+ camera_distance="1.5"
+ camera_elevation="-.5">
+ <param_morph />
+ </param>
+
+ <param
+ id="508"
+ group="0"
+ name="Shoe_Platform_Width"
+ label="Platform Width"
+ wearable="shoes"
+ edit_group="shoes"
+ edit_group_order="7"
+ label_min="Narrow"
+ label_max="Wide"
+ value_min="-1"
+ value_max="2"
+ camera_angle="15"
+ camera_distance="1.5"
+ camera_elevation="-1">
+ <param_morph />
+ </param>
+
+ <param
+ id="509"
+ group="1"
+ name="Shoe_Heel_Point"
+ label="Heel Shape"
+ wearable="shoes"
+ edit_group="shoes"
+ label_min="Default Heels"
+ label_max="Pointy Heels"
+ value_min="0"
+ value_max="1"
+ camera_distance="1.3"
+ camera_elevation="-.5">
+ <param_morph />
+ </param>
+
+ <param
+ id="510"
+ group="1"
+ name="Shoe_Heel_Thick"
+ label="Heel Shape"
+ wearable="shoes"
+ edit_group="shoes"
+ label_min="default Heels"
+ label_max="Thick Heels"
+ value_min="0"
+ value_max="1"
+ camera_distance="1.3"
+ camera_elevation="-.5">
+ <param_morph />
+ </param>
+
+ <param
+ id="511"
+ group="1"
+ name="Shoe_Toe_Point"
+ label="Toe Shape"
+ wearable="shoes"
+ edit_group="shoes"
+ label_min="Default Toe"
+ label_max="Pointy Toe"
+ value_min="0"
+ value_max="1"
+ camera_distance="1.3"
+ camera_elevation="-.5">
+ <param_morph />
+ </param>
+
+ <param
+ id="512"
+ group="1"
+ name="Shoe_Toe_Square"
+ label="Toe Shape"
+ wearable="shoes"
+ edit_group="shoes"
+ label_min="Default Toe"
+ label_max="Square Toe"
+ value_min="0"
+ value_max="1"
+ camera_distance="1.5"
+ camera_elevation="-.5">
+ <param_morph />
+ </param>
+
+ <param
+ id="654"
+ group="0"
+ name="Shoe_Toe_Thick"
+ label="Toe Thickness"
+ wearable="shoes"
+ edit_group="shoes"
+ edit_group_order="5"
+ label_min="Flat Toe"
+ label_max="Thick Toe"
+ value_min="0"
+ value_max="2"
+ camera_angle="15"
+ camera_distance="1.5"
+ camera_elevation="-1">
+ <param_morph />
+ </param>
+
+ <param
+ id="515"
+ group="0"
+ name="Foot_Size"
+ label="Foot Size"
+ wearable="shape"
+ edit_group="shape_legs"
+ edit_group_order="6"
+ label_min="Small"
+ label_max="Big"
+ value_min="-1"
+ value_max="3"
+ camera_angle="45"
+ camera_distance="1.1"
+ camera_elevation="-1">
+ <param_morph>
+ <volume_morph
+ name="L_FOOT"
+ scale="0.02 0.01 0.0"
+ pos="0.01 0 0"/>
+ <volume_morph
+ name="R_FOOT"
+ scale="0.02 0.01 0.0"
+ pos="0.01 0 0"/>
+ </param_morph>
+ </param>
+
+ <param
+ id="516"
+ group="1"
+ name="Displace_Loose_Lowerbody"
+ label="Pants Fit"
+ wearable="pants"
+ edit_group="driven"
+ clothing_morph="true"
+ value_min="0"
+ value_max="1"
+ value_default="0">
+ <param_morph />
+ </param>
+
+ <param
+ id="625"
+ group="0"
+ name="Leg_Pantflair"
+ label="Cuff Flare"
+ show_simple="true"
+ wearable="pants"
+ edit_group="pants"
+ edit_group_order="3"
+ clothing_morph="true"
+ label_min="Tight Cuffs"
+ label_max="Flared Cuffs"
+ value_min="0"
+ value_max="1.5"
+ camera_distance="1.8"
+ camera_angle="30"
+ camera_elevation="-.3">
+ <param_morph />
+ </param>
+
+ <param
+ id="793"
+ group="1"
+ name="Leg_Longcuffs"
+ label="Longcuffs"
+ wearable="pants"
+ edit_group="driven"
+ clothing_morph="true"
+ value_min="0"
+ value_max="3"
+ value_default="0">
+ <param_morph />
+ </param>
+
+ <param
+ id="638"
+ group="0"
+ name="Low_Crotch"
+ label="Pants Crotch"
+ wearable="pants"
+ clothing_morph="true"
+ edit_group="pants"
+ edit_group_order="4"
+ label_min="High and Tight"
+ label_max="Low and Loose"
+ value_min="0"
+ value_max="1.3"
+ camera_distance="1.2"
+ camera_angle="-20"
+ camera_elevation="-.3">
+ <param_morph />
+ </param>
+
+ <param
+ id="635"
+ group="1"
+ name="Fat_Legs"
+ label="Fat Torso"
+ wearable="shape"
+ edit_group="shape_body"
+ label_min="skinny"
+ label_max="fat"
+ value_min="0"
+ value_max="1">
+ <param_morph>
+ <volume_morph
+ name="PELVIS"
+ scale="0.03 0.06 0.0"/>
+ <volume_morph
+ name="R_UPPER_LEG"
+ scale="0.02 0.02 0.0"
+ pos="0.0 -0.02 0.0"/>
+ <volume_morph
+ name="R_LOWER_LEG"
+ scale="0.01 0.01 0.0"/>
+ <volume_morph
+ name="L_UPPER_LEG"
+ scale="0.02 0.02 0.0"
+ pos="0.0 0.02 0.0"/>
+ <volume_morph
+ name="L_LOWER_LEG"
+ scale="0.01 0.01 0.0"/>
+ </param_morph>
+ </param>
+
+ <param
+ id="854"
+ group="1"
+ name="Saddlebags"
+ wearable="shape"
+ edit_grouo="driven"
+ value_min="-.5"
+ value_max="3">
+ <param_morph>
+ <volume_morph
+ name="PELVIS"
+ scale="0.0 0.025 0.0"/>
+ </param_morph>
+
+ </param>
+
+ <param
+ id="879"
+ group="0"
+ sex="male"
+ name="Male_Package"
+ label="Package"
+ wearable="shape"
+ edit_group="shape_legs"
+ edit_group_order="4.6"
+ label_min="Coin Purse"
+ label_max="Duffle Bag"
+ value_default="0"
+ value_min="-.5"
+ value_max="2"
+ camera_angle="60"
+ camera_distance=".6">
+ <param_morph />
+ </param>
+
+ <!--
+ #############
+ # other morphs (not user controlled)
+ #############
+ -->
+ <param
+ id="153"
+ group="1"
+ name="Male_Legs"
+ wearable="shape"
+ edit_group="driven"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <!--
+ #end morph targets
+ -->
+ </mesh>
+
+ <mesh
+ type="lowerBodyMesh"
+ lod="1"
+ file_name="avatar_lower_body_1.llm"
+ min_pixel_width="160"
+ reference="avatar_lower_body.llm">
+ </mesh>
+
+ <mesh
+ type="lowerBodyMesh"
+ lod="2"
+ file_name="avatar_lower_body_2.llm"
+ min_pixel_width="80"
+ reference="avatar_lower_body.llm">
+ </mesh>
+
+ <mesh
+ type="lowerBodyMesh"
+ lod="3"
+ file_name="avatar_lower_body_3.llm"
+ min_pixel_width="40"
+ reference="avatar_lower_body.llm">
+ </mesh>
+
+ <mesh
+ type="lowerBodyMesh"
+ lod="4"
+ file_name="avatar_lower_body_4.llm"
+ min_pixel_width="0"
+ reference="avatar_lower_body.llm">
+ </mesh>
+
+ <!--
+ #lowerBodyMesh2 =
+ #lowerBodyMesh3 =
+ -->
+ <!--
+ #eyeLidLeftMesh =
+ -->
+ <mesh
+ type="eyeBallLeftMesh"
+ lod="0"
+ file_name="avatar_eye.llm"
+ min_pixel_width="320">
+ <!-- begin morph_params -->
+ <param
+ id="679"
+ group="1"
+ name="Eyeball_Size"
+ label="Eyeball Size"
+ wearable="shape"
+ edit_group="shape_eyes"
+ label_min="small eye"
+ label_max="big eye"
+ value_min="-.25"
+ value_max=".10">
+ <param_morph />
+ </param>
+
+ <param
+ id="687"
+ group="1"
+ name="Eyeball_Size"
+ label="Big Eyeball"
+ wearable="shape"
+ edit_group="shape_eyes"
+ label_min="small eye"
+ label_max="big eye"
+ value_min="-.25"
+ value_max=".25">
+ <param_morph />
+ </param>
+ </mesh>
+
+ <mesh
+ type="eyeBallLeftMesh"
+ lod="1"
+ file_name="avatar_eye_1.llm"
+ min_pixel_width="80">
+ <!-- begin morph_params -->
+ <param
+ id="694"
+ group="1"
+ name="Eyeball_Size"
+ label="Eyeball Size"
+ wearable="shape"
+ edit_group="shape_eyes"
+ label_min="small eye"
+ label_max="big eye"
+ value_min="-.25"
+ value_max=".10">
+ <param_morph />
+ </param>
+
+ <param
+ id="695"
+ group="1"
+ name="Eyeball_Size"
+ label="Big Eyeball"
+ wearable="shape"
+ edit_group="shape_eyes"
+ label_min="small eye"
+ label_max="big eye"
+ value_min="-.25"
+ value_max=".25">
+ <param_morph />
+ </param>
+ </mesh>
+
+ <!--
+ #eyeLidRightMesh =
+ -->
+ <mesh
+ type="eyeBallRightMesh"
+ lod="0"
+ file_name="avatar_eye.llm"
+ min_pixel_width="320">
+ <!-- begin morph_params -->
+ <param
+ id="680"
+ group="1"
+ name="Eyeball_Size"
+ label="Eyeball Size"
+ wearable="shape"
+ label_min="small eye"
+ label_max="big eye"
+ value_min="-.25"
+ value_max=".10">
+ <param_morph />
+ </param>
+
+ <param
+ id="688"
+ group="1"
+ name="Eyeball_Size"
+ label="Big Eyeball"
+ wearable="shape"
+ label_min="small eye"
+ label_max="big eye"
+ value_min="-.25"
+ value_max=".25">
+ <param_morph />
+ </param>
+ </mesh>
+
+ <mesh
+ type="eyeBallRightMesh"
+ lod="1"
+ file_name="avatar_eye_1.llm"
+ min_pixel_width="80">
+ <!-- begin morph_params -->
+ <param
+ id="681"
+ group="1"
+ name="Eyeball_Size"
+ label="Eyeball Size"
+ wearable="shape"
+ edit_group="shape_eyes"
+ label_min="small eye"
+ label_max="big eye"
+ value_min="-.25"
+ value_max=".10">
+ <param_morph />
+ </param>
+
+ <param
+ id="691"
+ group="1"
+ name="Eyeball_Size"
+ label="Big Eyeball"
+ wearable="shape"
+ edit_group="shape_eyes"
+ label_min="small eye"
+ label_max="big eye"
+ value_min="-.25"
+ value_max=".25">
+ <param_morph />
+ </param>
+ </mesh>
+
+ <mesh
+ type="skirtMesh"
+ lod="0"
+ file_name="avatar_skirt.llm"
+ min_pixel_width="320">
+ <param
+ id="845"
+ group="1"
+ name="skirt_poofy"
+ label="poofy skirt"
+ clothing_morph="true"
+ wearable="skirt"
+ edit_group="skirt"
+ label_min="less poofy"
+ label_max="more poofy"
+ value_min="0"
+ value_max="1.5">
+ <param_morph />
+ </param>
+
+ <param
+ id="846"
+ group="1"
+ name="skirt_loose"
+ label="loose skirt"
+ clothing_morph="true"
+ wearable="skirt"
+ edit_group="skirt"
+ label_min="form fitting"
+ label_max="loose"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="866"
+ group="1"
+ name="skirt_tight"
+ label="tight skirt"
+ clothing_morph="true"
+ wearable="skirt"
+ edit_group="skirt"
+ label_min="form fitting"
+ label_max="loose"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="867"
+ group="1"
+ name="skirt_smallbutt"
+ label="tight skirt"
+ clothing_morph="false"
+ wearable="skirt"
+ edit_group="skirt"
+ cross_wearable="true"
+ label_min="form fitting"
+ label_max="loose"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="848"
+ group="0"
+ name="skirt_bustle"
+ label="bustle skirt"
+ clothing_morph="true"
+ wearable="skirt"
+ edit_group_order="3"
+ edit_group="skirt"
+ label_min="no bustle"
+ label_max="more bustle"
+ value_min="0"
+ value_max="2"
+ value_default=".2"
+ camera_angle="100"
+ camera_distance="1.3"
+ camera_elevation="-.5">
+ <param_morph />
+ </param>
+
+ <param
+ id="847"
+ group="1"
+ name="skirt_bowlegs"
+ label="legs skirt"
+ wearable="skirt"
+ edit_group="driven"
+ cross_wearable="true"
+ value_min="-1"
+ value_max="1"
+ value_default="0">
+ <param_morph />
+ </param>
+
+ <param
+ id="852"
+ group="1"
+ name="skirt_bigbutt"
+ wearable="skirt"
+ edit_group="driven"
+ cross_wearable="true"
+ label="bigbutt skirt"
+ label_min="less"
+ label_max="more"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="849"
+ group="1"
+ name="skirt_belly"
+ wearable="skirt"
+ edit_group="driven"
+ cross_wearable="true"
+ label="big belly skirt"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
+ id="850"
+ group="1"
+ wearable="skirt"
+ edit_group="driven"
+ cross_wearable="true"
+ name="skirt_saddlebags"
+ value_min="-.5"
+ value_max="3">
+ <param_morph />
+ </param>
+
+ <param
+ id="851"
+ group="1"
+ name="skirt_chubby"
+ wearable="skirt"
+ edit_group="driven"
+ cross_wearable="true"
+ label_min="less"
+ label_max="more"
+ value_min="0"
+ value_max="1"
+ value_default="0">
+ <param_morph />
+ </param>
+
+ <param
+ id="856"
+ group="1"
+ name="skirt_lovehandles"
+ wearable="skirt"
+ edit_group="driven"
+ cross_wearable="true"
+ label_min="less"
+ label_max="more"
+ value_min="-1"
+ value_max="2"
+ value_default="0">
+ <param_morph />
+ </param>
+
+ <!--
+ #############
+ # other morphs (not user controlled)
+ #############
+ -->
+ <param
+ id="857"
+ group="1"
+ name="skirt_male"
+ wearable="skirt"
+ edit_group="driven"
+ cross_wearable="true"
+ value_min="0"
+ value_max="1">
+ <param_morph />
+ </param>
+ </mesh>
+
+ <mesh
+ type="skirtMesh"
+ lod="1"
+ file_name="avatar_skirt_1.llm"
+ min_pixel_width="160"
+ reference="avatar_skirt.llm">
+ </mesh>
+
+ <mesh
+ type="skirtMesh"
+ lod="2"
+ file_name="avatar_skirt_2.llm"
+ min_pixel_width="80"
+ reference="avatar_skirt.llm">
+ </mesh>
+
+ <mesh
+ type="skirtMesh"
+ lod="3"
+ file_name="avatar_skirt_3.llm"
+ min_pixel_width="40"
+ reference="avatar_skirt.llm">
+ </mesh>
+
+ <mesh
+ type="skirtMesh"
+ lod="4"
+ file_name="avatar_skirt_4.llm"
+ min_pixel_width="0"
+ reference="avatar_skirt.llm">
+ </mesh>
+
+ <!-- =========================================================== -->
+ <global_color
+ name="skin_color">
+ <param
+ id="111"
+ group="0"
+ wearable="skin"
+ edit_group="skin_color"
+ edit_group_order="1"
+ name="Pigment"
+ show_simple="true"
+ label_min="Light"
+ label_max="Dark"
+ value_min="0"
+ value_max="1"
+ value_default=".5">
+ <param_color>
+ <value
+ color="252, 215, 200, 255" />
+
+ <value
+ color="240, 177, 112, 255" />
+
+ <value
+ color="90, 40, 16, 255" />
+
+ <value
+ color="29, 9, 6, 255" />
+ </param_color>
+ </param>
+
+ <param
+ id="110"
+ group="0"
+ wearable="skin"
+ edit_group="skin_color"
+ edit_group_order="2"
+ name="Red Skin"
+ label="Ruddiness"
+ label_min="Pale"
+ label_max="Ruddy"
+ value_min="0"
+ value_max="0.1">
+ <param_color
+ operation="blend">
+ <value
+ color="218, 41, 37, 255" />
+ </param_color>
+ </param>
+
+ <param
+ id="108"
+ group="0"
+ wearable="skin"
+ edit_group="skin_color"
+ edit_group_order="3"
+ name="Rainbow Color"
+ show_simple="true"
+ label_min="None"
+ label_max="Wild"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5">
+ <param_color>
+ <value
+ color=" 0, 0, 0, 255" />
+
+ <value
+ color="255, 0, 255, 255" />
+
+ <value
+ color="255, 0, 0, 255" />
+
+ <value
+ color="255, 255, 0, 255" />
+
+ <value
+ color=" 0, 255, 0, 255" />
+
+ <value
+ color=" 0, 255, 255, 255" />
+
+ <value
+ color=" 0, 0, 255, 255" />
+
+ <value
+ color="255, 0, 255, 255" />
+ </param_color>
+ </param>
+ </global_color>
+
+ <!-- =========================================================== -->
+ <global_color
+ name="hair_color">
+ <param
+ id="114"
+ group="0"
+ wearable="hair"
+ edit_group="hair_color"
+ edit_group_order="3"
+ name="Blonde Hair"
+ show_simple="true"
+ label_min="Black"
+ label_max="Blonde"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_elevation=".1"
+ camera_distance=".5">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
+
+ <value
+ color="22, 6, 6, 255" />
+
+ <value
+ color="29, 9, 6, 255" />
+
+ <value
+ color="45, 21, 11, 255" />
+
+ <value
+ color="78, 39, 11, 255" />
+
+ <value
+ color="90, 53, 16, 255" />
+
+ <value
+ color="136, 92, 21, 255" />
+
+ <value
+ color="150, 106, 33, 255" />
+
+ <value
+ color="198, 156, 74, 255" />
+
+ <value
+ color="233, 192, 103, 255" />
+
+ <value
+ color="238, 205, 136, 255" />
+ </param_color>
+ </param>
+
+ <param
+ id="113"
+ group="0"
+ wearable="hair"
+ edit_group="hair_color"
+ edit_group_order="4"
+ name="Red Hair"
+ show_simple="true"
+ label_min="No Red"
+ label_max="Very Red"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
+
+ <value
+ color="118, 47, 19, 255" />
+ </param_color>
+ </param>
+
+ <param
+ id="115"
+ group="0"
+ wearable="hair"
+ edit_group="hair_color"
+ edit_group_order="1"
+ name="White Hair"
+ show_simple="true"
+ label_min="No White"
+ label_max="All White"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
+
+ <value
+ color="255, 255, 255, 255" />
+ </param_color>
+ </param>
+
+ <param
+ id="112"
+ group="0"
+ wearable="hair"
+ edit_group="hair_color"
+ edit_group_order="2"
+ name="Rainbow Color"
+ show_simple="true"
+ label_min="None"
+ label_max="Wild"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5">
+ <param_color>
+ <value
+ color=" 0, 0, 0, 255" />
+
+ <value
+ color="255, 0, 255, 255" />
+
+ <value
+ color="255, 0, 0, 255" />
+
+ <value
+ color="255, 255, 0, 255" />
+
+ <value
+ color=" 0, 255, 0, 255" />
+
+ <value
+ color=" 0, 255, 255, 255" />
+
+ <value
+ color=" 0, 0, 255, 255" />
+
+ <value
+ color="255, 0, 255, 255" />
+ </param_color>
+ </param>
+ </global_color>
+
+ <!-- =========================================================== -->
+ <global_color
+ name="eye_color">
+ <param
+ id="99"
+ group="0"
+ wearable="eyes"
+ edit_group="eyes"
+ edit_group_order="1"
+ name="Eye Color"
+ show_simple="true"
+ label_min="Natural"
+ label_max="Unnatural"
+ value_min="0"
+ value_max="1"
+ value_default="0"
+ camera_elevation=".1"
+ camera_distance=".3">
+ <!-- default to natural brown eyes-->
+ <param_color>
+ <value
+ color="50, 25, 5, 255" />
+
+ <!-- natural dark brown eyes-->
+ <value
+ color="109, 55, 15, 255" />
+
+ <!-- natural brown eyes-->
+ <value
+ color="150, 93, 49, 255" />
+
+ <!-- natural light brown eyes-->
+ <value
+ color="152, 118, 25, 255" />
+
+ <!--natural hazel eyes-->
+ <value
+ color="95, 179, 107, 255" />
+
+ <!--natural green eyes-->
+ <value
+ color="87, 192, 191, 255" />
+
+ <!--natural aqua eyes-->
+ <value
+ color="95, 172, 179, 255" />
+
+ <!--natural blue eyes-->
+ <value
+ color="128, 128, 128, 255" />
+
+ <!--natural grey eyes-->
+ <value
+ color="0, 0, 0, 255" />
+
+ <!--black eyes-->
+ <value
+ color="255, 255, 0, 255" />
+
+ <!--bright yellow eyes-->
+ <value
+ color=" 0, 255, 0, 255" />
+
+ <!-- bright green eyes-->
+ <value
+ color=" 0, 255, 255, 255" />
+
+ <!-- bright cyan eyes-->
+ <value
+ color=" 0, 0, 255, 255" />
+
+ <!--bright blue eyes-->
+ <value
+ color="255, 0, 255, 255" />
+
+ <!-- bright violet eyes-->
+ <value
+ color="255, 0, 0, 255" />
+
+ <!--bright red eyes-->
+ </param_color>
+ </param>
+
+ <param
+ id="98"
+ group="0"
+ wearable="eyes"
+ edit_group="eyes"
+ edit_group_order="2"
+ name="Eye Lightness"
+ show_simple="true"
+ label_min="Darker"
+ label_max="Lighter"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".3">
+ <param_color>
+ <value
+ color="0, 0, 0, 0" />
+
+ <value
+ color="255, 255, 255, 255" />
+ </param_color>
+ </param>
+ </global_color>
+
+ <!-- =========================================================== -->
+ <layer_set
+ body_region="hair"
+ width="512"
+ height="512"
+ clear_alpha="false">
+ <layer
+ name="base"
+ global_color="hair_color"
+ write_all_channels="true">
+ <texture
+ local_texture="hair_grain" />
+ </layer>
+
+ <layer
+ name="hair texture alpha layer"
+ visibility_mask="TRUE">
+ <texture
+ local_texture="hair_grain" />
+ </layer>
+
+ <layer
+ name="hair alpha"
+ visibility_mask="TRUE">
+ <texture
+ local_texture="hair_alpha" />
+ </layer>
+
+ </layer_set>
+ <!-- =========================================================== -->
+
+ <layer_set
+ body_region="head"
+ width="512"
+ height="512">
+ <layer
+ name="head bump base"
+ fixed_color = "128,128,128,255"
+ render_pass="bump">
+ </layer>
+
+ <layer
+ name="head bump definition"
+ render_pass="bump">
+
+
+ <texture
+ tga_file="bump_head_base.tga"
+ file_is_mask="FALSE"/>
<param
- id="644"
+ id="873"
group="1"
- name="Hair_Forehead_Round"
- wearable="hair"
- edit_group="hair_style"
+ wearable="skin"
+ edit_group="driven"
+ edit_group_order="12"
+ name="Bump base"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ domain="0" />
</param>
+ </layer>
+
+ <layer
+ name="base"
+ global_color="skin_color">
+ <texture
+ tga_file="head_skingrain.tga" />
+ </layer>
+
+ <layer
+ name="headcolor">
+ <texture
+ tga_file="head_color.tga" />
+ </layer>
+
+ <layer
+ name="shadow">
+ <texture
+ tga_file="head_shading_alpha.tga"
+ file_is_mask="TRUE" />
<param
- id="645"
+ id="158"
group="1"
- name="Hair_Forehead_Slant"
- wearable="hair"
- edit_group="hair_style"
+ wearable="skin"
+ name="Shading"
value_min="0"
value_max="1">
- <param_morph />
- </param>
+ <param_color>
+ <value
+ color="0, 0, 0, 0" />
- <param
- id="774"
- group="1"
- name="Shear_Head_Hair"
- wearable="hair"
- edit_group="hair_style"
- value_min="-2"
- value_max="2">
- <param_morph />
+ <value
+ color="0, 0, 0, 128" />
+ </param_color>
</param>
+ </layer>
+
+ <layer
+ name="highlight">
+ <texture
+ tga_file="head_highlights_alpha.tga"
+file_is_mask="TRUE" />
+
<param
- id="771"
- group="1"
- name="Elongate_Head_Hair"
- wearable="hair"
- edit_group="hair_style"
- value_min="-1"
+ id="159"
+ group="1"
+ name="Shading"
+ wearable="skin"
+ value_min="0"
value_max="1">
- <param_morph />
- </param>
+ <param_color>
+ <value
+color="255, 255, 255, 0" />
- <param
- id="674"
- group="0"
- name="Hair_Shear_Back"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="12"
- label="Shear Back"
- label_min="Full Back"
- label_max="Sheared Back"
- value_min="-1"
- value_max="2"
- value_default="-0.3"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="100">
- <param_morph />
- </param>
- <param
- id="762"
- group="0"
- name="Hair_Shear_Front"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="11.8"
- label="Shear Front"
- show_simple="true"
- label_min="Full Front"
- label_max="Sheared Front"
- value_min="0"
- value_max="3"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="30">
- <param_morph />
+ <value
+ color="255, 255, 255, 64" />
+ </param_color>
</param>
+ </layer>
+ <layer
+ name="rosyface">
+ <texture
+ tga_file="rosyface_alpha.tga"
+ file_is_mask="true" />
<param
- id="754"
+ id="116"
group="0"
- name="Hair_Taper_Back"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="14"
- label="Taper Back"
- label_min="Wide Back"
- label_max="Narrow Back"
- value_min="-1"
- value_max="2"
- value_default="0"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="160">
- <param_morph />
- </param>
+ wearable="skin"
+ edit_group="skin_facedetail"
+ edit_group_order="4"
+ name="Rosy Complexion"
+ label_min="Less Rosy"
+ label_max="More Rosy"
+ value_min="0"
+ value_max="1"
+ camera_distance=".3"
+ camera_elevation=".07">
+ <param_color>
+ <value
+ color="198, 71, 71, 0" />
- <param
- id="755"
- group="0"
- name="Hair_Taper_Front"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="13"
- label="Taper Front"
- label_min="Wide Front"
- label_max="Narrow Front"
- value_min="-1.5"
- value_max="1.5"
- value_default="0.05"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_morph />
+ <value
+ color="198, 71, 71, 255" />
+ </param_color>
</param>
+ </layer>
+
+ <layer
+ name="lips">
+ <texture
+ tga_file="lips_mask.tga"
+ file_is_mask="true" />
<param
- id="782"
- group="1"
- clothing_morph="true"
- name="Hair_Pigtails_Short"
- wearable="hair"
- edit_group="hair_style"
+ id="117"
+ group="0"
+ wearable="skin"
+ edit_group="skin_facedetail"
+ edit_group_order="5"
+ name="Lip Pinkness"
+ label_min="Darker"
+ label_max="Pinker"
value_min="0"
- value_max="1">
- <param_morph />
+ value_max="1"
+ camera_distance=".25">
+ <param_color>
+ <value
+ color="220, 115, 115, 0" />
+
+ <value
+ color="220, 115, 115, 128" />
+ </param_color>
</param>
+ </layer>
+ <layer
+ name="wrinkles_shading"
+ render_pass="bump"
+ fixed_color="0,0,0,100">
<param
- id="783"
+ id="118"
group="1"
- clothing_morph="true"
- name="Hair_Pigtails_Med"
- wearable="hair"
- edit_group="hair_style"
+ wearable="skin"
+ name="Wrinkles"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ tga_file="bump_face_wrinkles.tga"
+ skip_if_zero="true"
+ domain="0.3" />
</param>
+ </layer>
- <param
- id="790"
- group="1"
- clothing_morph="true"
- name="Hair_Pigtails_Medlong"
- wearable="hair"
- edit_group="hair_style"
- value_min="0"
- value_max="1">
- <param_morph />
+ <!--<layer
+ name="wrinkles_highlights"
+ fixed_color="255,255,255,64">
+ <param
+ id="128"
+ group="1"
+ name="Wrinkles"
+ value_min="0"
+ value_max="1">
+ <param_alpha
+ tga_file="head_wrinkles_highlights_alpha.tga"
+ skip_if_zero="true"
+ domain="0.3" />
+ </param>
+ </layer>-->
+ <layer
+ name="freckles"
+ fixed_color="120,47,20,128">
+ <param
+ id="165"
+ group="0"
+ wearable="skin"
+ edit_group="skin_facedetail"
+ edit_group_order="2"
+ name="Freckles"
+ label_min="Less"
+ label_max="More"
+ value_min="0"
+ value_max="1"
+ camera_distance=".3"
+camera_elevation=".07">
+ <param_alpha
+ tga_file="freckles_alpha.tga"
+ skip_if_zero="true"
+domain="0.5" />
</param>
+ </layer>
+ <layer
+name="eyebrowsbump"
+render_pass="bump">
+ <texture
+ tga_file="head_hair.tga"
+ file_is_mask="false" />
<param
- id="784"
+ id="1000"
group="1"
- clothing_morph="true"
- name="Hair_Pigtails_Long"
wearable="hair"
- edit_group="hair_style"
+ edit_group="driven"
+ name="Eyebrow Size Bump"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ tga_file="eyebrows_alpha.tga"
+ domain="0.1" />
</param>
<param
- id="786"
+ id="1002"
group="1"
- name="Hair_Ponytail_Short"
wearable="hair"
- edit_group="hair_style"
+ edit_group="driven"
+ name="Eyebrow Density Bump"
value_min="0"
value_max="1">
- <param_morph />
+ <param_color>
+ <value
+ color="255,255,255,0" />
+
+ <value
+ color="255,255,255,255" />
+ </param_color>
</param>
+ </layer>
+
+ <layer
+ name="eyebrows"
+ global_color="hair_color">
+ <texture
+ tga_file="head_hair.tga"
+ file_is_mask="false" />
<param
- id="787"
+ id="1001"
group="1"
- name="Hair_Ponytail_Med"
wearable="hair"
- edit_group="hair_style"
+ edit_group="hair_eyebrows"
+ name="Eyebrow Size"
+ show_simple="true"
value_min="0"
- value_max="1">
- <param_morph />
+ value_max="1"
+ value_default="0.5">
+ <param_alpha
+ tga_file="eyebrows_alpha.tga"
+ domain="0.1" />
</param>
<param
- id="788"
+ id="1003"
group="1"
- name="Hair_Ponytail_Long"
- clothing_morph="true"
wearable="hair"
- edit_group="hair_style"
+ edit_group="driven"
+ name="Eyebrow Density"
value_min="0"
value_max="1">
- <param_morph />
- </param>
-
-<!-- #end morph targets -->
- </mesh>
-
- <mesh
- type="hairMesh"
- lod="1"
- file_name="avatar_hair_1.llm"
- min_pixel_width="160"
- reference="avatar_hair.llm">
- </mesh>
-
- <mesh
- type="hairMesh"
- lod="2"
- file_name="avatar_hair_2.llm"
- min_pixel_width="80"
- reference="avatar_hair.llm">
- </mesh>
-
- <mesh
- type="hairMesh"
- lod="3"
- file_name="avatar_hair_3.llm"
- min_pixel_width="40"
- reference="avatar_hair.llm">
- </mesh>
-
- <mesh
- type="hairMesh"
- lod="4"
- file_name="avatar_hair_4.llm"
- min_pixel_width="20"
- reference="avatar_hair.llm">
- </mesh>
-
- <mesh
- type="hairMesh"
- lod="5"
- file_name="avatar_hair_5.llm"
- min_pixel_width="0"
- reference="avatar_hair.llm">
- </mesh>
-
- <mesh
- type="headMesh"
- lod="0"
- file_name="avatar_head.llm"
- min_pixel_width="320">
-<!--
- begin morph targets
- #############
- tweakable morphs
- #############
- -->
- <param
- id="1"
- group="0"
- name="Big_Brow"
- label="Brow Size"
- wearable="shape"
- edit_group="shape_head"
- edit_group_order="7"
- label_min="Small"
- label_max="Large"
- value_min="-.3"
- value_max="2"
- camera_elevation=".1"
- camera_distance=".4"
- camera_angle="45">
- <param_morph />
- </param>
+ <param_color
+ operation="multiply">
+ <value
+ color="255,255,255,0" />
- <param
- id="2"
- group="0"
- name="Nose_Big_Out"
- label="Nose Size"
- wearable="shape"
- edit_group="shape_nose"
- edit_group_order="1"
- label_min="Small"
- label_max="Large"
- show_simple="true"
- value_min="-0.8"
- value_max="2.5"
- camera_elevation=".1"
- camera_distance=".35"
- camera_angle="50">
- <param_morph />
- </param>
-
- <param
- id="4"
- group="0"
- name="Broad_Nostrils"
- label="Nostril Width"
- wearable="shape"
- edit_group="shape_nose"
- edit_group_order="3"
- label_min="Narrow"
- label_max="Broad"
- value_min="-.5"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".3"
- camera_angle="-20">
- <param_morph />
- </param>
-
- <param
- id="759"
- group="0"
- name="Low_Septum_Nose"
- label="Nostril Division"
- wearable="shape"
- edit_group="shape_nose"
- edit_group_order="3.5"
- label_min="High"
- label_max="Low"
- value_min="-1"
- value_max="1.5"
- value_default="0.5"
- camera_elevation=".1"
- camera_distance=".3"
- camera_angle="-20">
- <param_morph />
+ <value
+ color="255,255,255,255" />
+ </param_color>
</param>
+ </layer>
+ <layer
+ name="lipstick">
<param
- id="517"
+ id="700"
group="0"
- name="Wide_Nose"
- label="Nose Width"
- wearable="shape"
- edit_group="shape_nose"
+ wearable="skin"
+ edit_group="skin_makeup"
edit_group_order="2"
- label_min="Narrow"
- label_max="Wide"
- show_simple="true"
- value_min="-.5"
+ name="Lipstick Color"
+ label_min="Pink"
+ label_max="Black"
+ value_min="0"
value_max="1"
- camera_elevation=".1"
- camera_distance=".3"
- camera_angle="-20">
- <param_morph />
- </param>
+ value_default=".25"
+ camera_distance=".25">
+ <param_color>
+ <value
+ color="245,161,177,200" />
- <param
- id="5"
- group="0"
- name="Cleft_Chin"
- label="Chin Cleft"
- wearable="shape"
- edit_group="shape_chin"
- edit_group_order="6"
- label_min="Round"
- label_max="Cleft"
- value_min="-.1"
- value_max="1"
- camera_elevation="0"
- camera_distance=".28"
- camera_angle="-20">
- <param_morph />
- </param>
+ <value
+ color="216,37,67,200" />
- <param
- id="6"
- group="0"
- name="Bulbous_Nose_Tip"
- label="Nose Tip Shape"
- wearable="shape"
- edit_group="shape_nose"
- edit_group_order="8"
- label_min="Pointy"
- label_max="Bulbous"
- value_min="-.3"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".35"
- camera_angle="15">
- <param_morph />
- </param>
+ <value
+ color="178,48,76,200" />
- <param
- id="7"
- group="0"
- name="Weak_Chin"
- label="Chin Angle"
- wearable="shape"
- edit_group="shape_chin"
- edit_group_order="1"
- label_min="Chin Out"
- label_max="Chin In"
- value_min="-.5"
- value_max=".5"
- camera_elevation=".1"
- camera_distance=".4"
- camera_angle="45">
- <param_morph />
- </param>
+ <value
+ color="68,0,11,200" />
- <param
- id="8"
- group="0"
- name="Double_Chin"
- label="Chin-Neck"
- wearable="shape"
- edit_group="shape_chin"
- edit_group_order="8"
- label_min="Tight Chin"
- label_max="Double Chin"
- value_min="-.5"
- value_max="1.5"
- camera_elevation="-.1"
- camera_distance=".3"
- camera_angle="60">
- <param_morph />
- </param>
+ <value
+ color="252,207,184,200" />
- <param
- id="10"
- group="0"
- name="Sunken_Cheeks"
- label="Lower Cheeks"
- wearable="shape"
- edit_group="shape_head"
- edit_group_order="9"
- label_min="Well-Fed"
- label_max="Sunken"
- show_simple="true"
- value_min="-1.5"
- value_max="3"
- camera_elevation=".1"
- camera_distance=".4"
- camera_angle="5">
- <param_morph />
- </param>
+ <value
+ color="241,136,106,200" />
- <param
- id="11"
- group="0"
- name="Noble_Nose_Bridge"
- label="Upper Bridge"
- wearable="shape"
- edit_group="shape_nose"
- edit_group_order="5"
- label_min="Low"
- label_max="High"
- value_min="-.5"
- value_max="1.5"
- camera_elevation=".1"
- camera_distance=".35"
- camera_angle="70">
- <param_morph />
- </param>
+ <value
+ color="208,110,85,200" />
- <param
- id="758"
- group="0"
- name="Lower_Bridge_Nose"
- label="Lower Bridge"
- wearable="shape"
- edit_group="shape_nose"
- edit_group_order="5.5"
- label_min="Low"
- label_max="High"
- value_min="-1.5"
- value_max="1.5"
- camera_elevation=".1"
- camera_distance=".35"
- camera_angle="70">
- <param_morph />
- </param>
+ <value
+ color="106,28,18,200" />
- <param
- id="12"
- group="0"
- name="Jowls"
- wearable="shape"
- edit_group="shape_chin"
- edit_group_order="5"
- label_min="Less"
- label_max="More"
- value_min="-.5"
- value_max="2.5"
- camera_elevation=".1"
- camera_distance=".4"
- camera_angle="0">
- <param_morph />
+ <value
+ color="58,26,49,200" />
+
+ <value
+ color="14,14,14,200" />
+ </param_color>
</param>
<param
- id="13"
+ id="701"
group="0"
- name="Cleft_Chin_Upper"
- label="Upper Chin Cleft"
- wearable="shape"
- edit_group="shape_chin"
- edit_group_order="7"
- label_min="Round"
- label_max="Cleft"
+ wearable="skin"
+ edit_group="skin_makeup"
+ edit_group_order="1"
+ name="Lipstick"
+ label_min="No Lipstick"
+ label_max="More Lipstick"
value_min="0"
- value_max="1.5"
- camera_elevation="0"
- camera_distance=".28"
- camera_angle="-20">
- <param_morph />
+ value_max=".9"
+ value_default="0.0"
+ camera_distance=".25">
+ <param_alpha
+ tga_file="lipstick_alpha.tga"
+ skip_if_zero="true"
+ domain="0.05" />
</param>
+ </layer>
+ <layer
+ name="lipgloss"
+ fixed_color="255,255,255,190">
<param
- id="14"
+ id="702"
+ name="Lipgloss"
+ label_min="No Lipgloss"
+ label_max="Glossy"
+ wearable="skin"
+ edit_group="skin_makeup"
+ edit_group_order="3"
group="0"
- name="High_Cheek_Bones"
- label="Cheek Bones"
- wearable="shape"
- edit_group="shape_head"
- edit_group_order="10"
- label_min="Low"
- label_max="High"
- value_min="-.5"
+ value_min="0"
value_max="1"
- camera_elevation=".1"
- camera_distance=".3"
- camera_angle="-20">
- <param_morph />
+ camera_distance=".25">
+ <param_alpha
+ tga_file="lipgloss_alpha.tga"
+ skip_if_zero="true"
+ domain="0.2" />
</param>
+ </layer>
+ <layer
+ name="blush">
<param
- id="15"
+ id="704"
group="0"
- name="Ears_Out"
- label="Ear Angle"
- wearable="shape"
- edit_group="shape_ears"
- edit_group_order="2"
- label_min="In"
- label_max="Out"
- value_min="-.5"
- value_max="1.5"
- camera_elevation=".1"
- camera_distance=".3"
- camera_angle="-20">
- <param_morph />
- </param>
-
-<!--Pointy eyebrows became a driver/driven param with new max value for backwards compatibility between 1.0 and 1.1-->
- <param
- id="870"
- group="1"
- name="Pointy_Eyebrows"
- label="Eyebrow Points"
- wearable="hair"
- edit_group="hair_eyebrows"
+ wearable="skin"
+ edit_group="skin_makeup"
edit_group_order="4"
- label_min="Smooth"
- label_max="Pointy"
- value_min="-.5"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".3">
- <param_morph />
+ name="Blush"
+ label_min="No Blush"
+ label_max="More Blush"
+ value_min="0"
+ value_max=".9"
+ value_default="0"
+ camera_distance=".3"
+ camera_elevation=".07"
+ camera_angle="20">
+ <param_alpha
+ tga_file="blush_alpha.tga"
+ skip_if_zero="true"
+ domain="0.3" />
</param>
<param
- id="17"
+ id="705"
group="0"
- name="Square_Jaw"
- label="Jaw Shape"
- wearable="shape"
- edit_group="shape_chin"
- edit_group_order="2"
- label_min="Pointy"
- label_max="Square"
- value_min="-.5"
+ wearable="skin"
+ edit_group="skin_makeup"
+ edit_group_order="5"
+ name="Blush Color"
+ label_min="Pink"
+ label_max="Orange"
+ value_min="0"
value_max="1"
+ value_default=".5"
camera_distance=".3"
- camera_elevation=".04"
- camera_angle="-20">
- <param_morph />
- </param>
+ camera_elevation=".07"
+ camera_angle="20">
+ <param_color>
+ <value
+ color="253,162,193,200" />
- <param
- id="18"
- group="0"
- name="Puffy_Upper_Cheeks"
- label="Upper Cheeks"
- wearable="shape"
- edit_group="shape_head"
- edit_group_order="8"
- label_min="Thin"
- label_max="Puffy"
- value_min="-1.5"
- value_max="2.5"
- camera_elevation=".1"
- camera_distance=".3"
- camera_angle="-20">
- <param_morph />
- </param>
+ <value
+ color="247,131,152,200" />
- <param
- id="19"
- group="0"
- name="Upturned_Nose_Tip"
- label="Nose Tip Angle"
- wearable="shape"
- edit_group="shape_nose"
- edit_group_order="7"
- label_min="Downturned"
- label_max="Upturned"
- value_min="-1.5"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".35"
- camera_angle="15">
- <param_morph />
- </param>
+ <value
+ color="213,122,140,200" />
- <param
- id="20"
- group="0"
- name="Bulbous_Nose"
- label="Nose Thickness"
- wearable="shape"
- edit_group="shape_nose"
- edit_group_order="4"
- label_min="Thin Nose"
- label_max="Bulbous Nose"
- show_simple="true"
- value_min="-.5"
- value_max="1.5"
- camera_elevation=".1"
- camera_distance=".3">
- <param_morph />
- </param>
+ <value
+ color="253,152,144,200" />
- <param
- id="21"
- group="0"
- name="Upper_Eyelid_Fold"
- label="Upper Eyelid Fold"
- wearable="shape"
- edit_group="shape_eyes"
- edit_group_order="5"
- label_min="Uncreased"
- label_max="Creased"
- value_min="-0.2"
- value_max="1.3"
- camera_elevation=".1"
- camera_distance=".35">
- <param_morph />
+ <value
+ color="236,138,103,200" />
+
+ <value
+ color="195,128,122,200" />
+
+ <value
+ color="148,103,100,200" />
+
+ <value
+ color="168,95,62,200" />
+ </param_color>
</param>
<param
- id="22"
+ id="711"
group="0"
- name="Attached_Earlobes"
- label="Attached Earlobes"
- wearable="shape"
- edit_group="shape_ears"
- edit_group_order="3"
- label_min="Unattached"
- label_max="Attached"
+ wearable="skin"
+ edit_group="skin_makeup"
+ edit_group_order="6"
+ name="Blush Opacity"
+ label_min="Clear"
+ label_max="Opaque"
value_min="0"
value_max="1"
- camera_elevation=".1"
+ value_default=".5"
camera_distance=".3"
- camera_angle="45">
- <param_morph />
- </param>
+ camera_elevation=".07"
+ camera_angle="20">
+ <param_color
+ operation="multiply">
+ <value
+ color="255,255,255,0" />
- <param
- id="23"
- group="0"
- name="Baggy_Eyes"
- label="Eye Bags"
- wearable="shape"
- edit_group="shape_eyes"
- edit_group_order="6"
- label_min="Smooth"
- label_max="Baggy"
- value_min="-.5"
- value_max="1.5"
- camera_elevation=".1"
- camera_distance=".35">
- <param_morph />
+ <value
+ color="255,255,255,255" />
+ </param_color>
</param>
+ </layer>
+ <layer
+ name="Outer Eye Shadow">
<param
- id="765"
+ id="708"
group="0"
- name="Puffy_Lower_Lids"
- label="Puffy Eyelids"
- wearable="shape"
- edit_group="shape_eyes"
- edit_group_order="6.1"
- label_min="Flat"
- label_max="Puffy"
- value_min="-.3"
- value_max="2.5"
- camera_elevation=".1"
- camera_distance=".35">
- <param_morph />
- </param>
+ wearable="skin"
+ edit_group="skin_makeup"
+ edit_group_order="11"
+ name="Out Shdw Color"
+ label_min="Light"
+ label_max="Dark"
+ value_min="0"
+ value_max="1"
+ camera_distance=".3"
+ camera_elevation=".14">
+ <param_color>
+ <value
+ color="252,247,246,255" />
- <param
- id="24"
- group="0"
- name="Wide_Eyes"
- label="Eye Opening"
- wearable="shape"
- edit_group="shape_eyes"
- edit_group_order="1.1"
- label_min="Narrow"
- label_max="Wide"
- value_min="-1.5"
- value_max="2"
- show_simple="true"
- camera_elevation=".1"
- camera_distance=".35">
- <param_morph />
- </param>
+ <value
+ color="255,206,206,255" />
- <param
- id="25"
- group="0"
- name="Wide_Lip_Cleft"
- label="Lip Cleft"
- wearable="shape"
- edit_group="shape_mouth"
- edit_group_order="6"
- label_min="Narrow"
- label_max="Wide"
- value_min="-.8"
- value_max="1.5"
- camera_elevation="0"
- camera_distance=".28">
- <param_morph />
- </param>
+ <value
+ color="233,135,149,255" />
- <param
- id="764"
- group="0"
- name="Lip_Cleft_Deep"
- label="Lip Cleft Depth"
- wearable="shape"
- edit_group="shape_mouth"
- edit_group_order="5.8"
- label_min="Shallow"
- label_max="Deep"
- value_min="-.5"
- value_max="1.2"
- camera_elevation="0"
- camera_distance=".28">
- <param_morph />
- </param>
+ <value
+ color="220,168,192,255" />
- <param
- id="26"
- group="1"
- wearable="shape"
- name="Lips_Thin"
- edit_group="driven"
- value_min="0"
- value_max=".7">
- <param_morph />
- </param>
+ <value
+ color="228,203,232,255" />
- <param
- id="27"
- group="0"
- name="Wide_Nose_Bridge"
- label="Bridge Width"
- wearable="shape"
- edit_group="shape_nose"
- edit_group_order="6"
- label_min="Narrow"
- label_max="Wide"
- value_min="-1.3"
- value_max="1.2"
- camera_elevation=".1"
- camera_distance=".3"
- camera_angle="-20">
- <param_morph />
- </param>
+ <value
+ color="255,234,195,255" />
- <param
- id="28"
- group="1"
- name="Lips_Fat"
- wearable="shape"
- edit_group="driven"
- value_min="0"
- value_max="2">
- <param_morph />
- </param>
+ <value
+ color="230,157,101,255" />
- <param
- id="29"
- group="1"
- name="Wide_Upper_Lip"
- wearable="shape"
- edit_group="driven"
- value_min="-.7"
- value_max="1.3">
- <param_morph />
- </param>
+ <value
+ color="255,147,86,255" />
- <param
- id="30"
- group="1"
- name="Wide_Lower_Lip"
- wearable="shape"
- edit_group="driven"
- value_min="-.7"
- value_max="1.3">
- <param_morph />
- </param>
+ <value
+ color="228,110,89,255" />
-<!--Arced eyebrows became a driver/driven param with new max value for backwards compatibility between 1.0 and 1.1-->
- <param
- id="872"
- group="1"
- name="Arced_Eyebrows"
- label="Eyebrow Arc"
- wearable="hair"
- edit_group="hair_eyebrows"
- edit_group_order="3"
- label_min="Flat"
- label_max="Arced"
- value_min="0"
- value_max="1">
- <param_morph />
- </param>
+ <value
+ color="228,150,120,255" />
-<!--Lower eyebrows became a driver/driven param with new min value for backwards compatibility between 1.0 and 1.1-->
- <param
- id="871"
- group="1"
- name="Lower_Eyebrows"
- label="Eyebrow Height"
- show_simple="true"
- wearable="hair"
- edit_group="hair_eyebrows"
- edit_group_order="2.5"
- label_min="Higher"
- label_max="Lower"
- value_min="-2"
- value_max="2">
- <param_morph />
+ <value
+ color="223,227,213,255" />
+
+ <value
+ color="96,116,87,255" />
+
+ <value
+ color="88,143,107,255" />
+
+ <value
+ color="194,231,223,255" />
+
+ <value
+ color="207,227,234,255" />
+
+ <value
+ color="41,171,212,255" />
+
+ <value
+ color="180,137,130,255" />
+
+ <value
+ color="173,125,105,255" />
+
+ <value
+ color="144,95,98,255" />
+
+ <value
+ color="115,70,77,255" />
+
+ <value
+ color="155,78,47,255" />
+
+ <value
+ color="239,239,239,255" />
+
+ <value
+ color="194,194,194,255" />
+
+ <value
+ color="120,120,120,255" />
+
+ <value
+ color="10,10,10,255" />
+ </param_color>
</param>
<param
- id="35"
+ id="706"
group="0"
- name="Big_Ears"
- label="Ear Size"
- wearable="shape"
- edit_group="shape_ears"
- edit_group_order="1"
- label_min="Small"
- label_max="Large"
- value_min="-1"
- value_max="2"
- camera_elevation=".1"
+ wearable="skin"
+ edit_group="skin_makeup"
+ edit_group_order="12"
+ name="Out Shdw Opacity"
+ label_min="Clear"
+ label_max="Opaque"
+ value_min=".2"
+ value_max="1"
+ value_default=".6"
camera_distance=".3"
- camera_angle="45">
- <param_morph />
+ camera_elevation=".14">
+ <param_color
+ operation="multiply">
+ <value
+ color="255,255,255,0" />
+
+ <value
+ color="255,255,255,255" />
+ </param_color>
</param>
<param
- id="796"
+ id="707"
group="0"
- name="Pointy_Ears"
- label="Ear Tips"
- wearable="shape"
- edit_group="shape_ears"
- edit_group_order="4"
- label_min="Flat"
- label_max="Pointy"
- value_min="-.4"
- value_max="3"
- camera_elevation=".1"
+ wearable="skin"
+ edit_group="skin_makeup"
+ edit_group_order="10"
+ name="Outer Shadow"
+ label_min="No Eyeshadow"
+ label_max="More Eyeshadow"
+ value_min="0"
+ value_max=".7"
camera_distance=".3"
- camera_angle="45">
- <param_morph />
+ camera_elevation=".14">
+ <param_alpha
+ tga_file="eyeshadow_outer_alpha.tga"
+ skip_if_zero="true"
+ domain="0.05" />
</param>
+ </layer>
+ <layer
+ name="Inner Eye Shadow">
<param
- id="185"
+ id="712"
group="0"
- name="Deep_Chin"
- label="Chin Depth"
- wearable="shape"
- edit_group="shape_chin"
- edit_group_order="3"
- label_min="Shallow"
- label_max="Deep"
- value_min="-1"
+ wearable="skin"
+ edit_group="skin_makeup"
+ edit_group_order="8"
+ name="In Shdw Color"
+ label_min="Light"
+ label_max="Dark"
+ value_min="0"
value_max="1"
- camera_elevation=".1"
- camera_distance=".4"
- camera_angle="30">
- <param_morph />
- </param>
+ camera_distance=".3"
+ camera_elevation=".14">
+ <param_color>
+ <value
+ color="252,247,246,255" />
- <param
- id="186"
- group="1"
- name="Egg_Head"
- label="Egg Head"
- wearable="shape"
- edit_group="shape_head"
- label_min="Chin Heavy"
- label_max="Forehead Heavy"
- value_min="-1.3"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_morph />
- </param>
+ <value
+ color="255,206,206,255" />
- <param
- id="187"
- group="1"
- name="Squash_Stretch_Head"
- label="Squash/Stretch Head"
- wearable="shape"
- edit_group="shape_head"
- label_min="Squash Head"
- label_max="Stretch Head"
- value_min="-.5"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_morph>
- <volume_morph
- name="HEAD"
- scale="-0.008 -0.006 0.015"/>
- </param_morph>
- </param>
+ <value
+ color="233,135,149,255" />
- <param
- id="188"
- group="1"
- name="Square_Head"
- wearable="shape"
- label_min="Less Square"
- label_max="More Square"
- value_min="0"
- value_max=".7"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_morph />
- </param>
+ <value
+ color="220,168,192,255" />
- <param
- id="189"
- group="1"
- wearable="shape"
- name="Round_Head"
- label_min="Less Round"
- label_max="More Round"
- value_min="0"
- value_max="1"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_morph />
- </param>
+ <value
+ color="228,203,232,255" />
- <param
- id="194"
- group="1"
- name="Eye_Spread"
- wearable="shape"
- edit_group="shape_eyes"
- label_min="Eyes Together"
- label_max="Eyes Spread"
- value_min="-2"
- value_max="2">
- <param_morph />
- </param>
+ <value
+ color="255,234,195,255" />
- <param
- id="400"
- sex="male"
- group="1"
- name="Displace_Hair_Facial"
- label="Hair Thickess"
- wearable="hair"
- edit_group="hair_facial"
- label_min="Cropped Hair"
- label_max="Bushy Hair"
- value_min="0"
- value_max="2">
- <param_morph />
- </param>
+ <value
+ color="230,157,101,255" />
- <param
- id="506"
- group="0"
- name="Mouth_Height"
- wearable="shape"
- label="Mouth Position"
- show_simple="true"
- edit_group="shape_mouth"
- edit_group_order="4"
- label_min="High"
- label_max="Low"
- value_min="-2"
- value_max="2"
- camera_distance=".3"
- camera_elevation=".04">
- <param_morph />
- </param>
+ <value
+ color="255,147,86,255" />
- <param
- id="633"
- group="1"
- name="Fat_Head"
- label="Fat Head"
- wearable="shape"
- edit_group="shape_body"
- label_min="Skinny"
- label_max="Fat"
- value_min="0"
- value_max="1"
- camera_elevation=".3">
- <param_morph/>
- </param>
+ <value
+ color="228,110,89,255" />
- <param
- id="630"
- group="1"
- name="Forehead_Round"
- label="Round Forehead"
- wearable="shape"
- label_min="Less"
- label_max="More"
- value_min="0"
- value_max="1">
- <param_morph />
- </param>
+ <value
+ color="228,150,120,255" />
- <param
- id="631"
- group="1"
- name="Forehead_Slant"
- label="Slanted Forehead"
- wearable="shape"
- label_min="Less"
- label_max="More"
- value_min="0"
- value_max="1">
- <param_morph />
- </param>
+ <value
+ color="223,227,213,255" />
- <param
- id="650"
- group="0"
- name="Eyelid_Corner_Up"
- label="Outer Eye Corner"
- wearable="shape"
- edit_group="shape_eyes"
- edit_group_order="4"
- label_min="Corner Down"
- label_max="Corner Up"
- value_min="-1.3"
- value_max="1.2"
- camera_elevation=".1"
- camera_distance=".30">
- <param_morph />
- </param>
+ <value
+ color="96,116,87,255" />
- <param
- id="880"
- group="0"
- name="Eyelid_Inner_Corner_Up"
- label="Inner Eye Corner"
- wearable="shape"
- edit_group="shape_eyes"
- edit_group_order="4.2"
- label_min="Corner Down"
- label_max="Corner Up"
- value_min="-1.3"
- value_max="1.2"
- camera_elevation=".1"
- camera_distance=".30">
- <param_morph />
- </param>
-
- <param
- id="653"
- group="0"
- name="Tall_Lips"
- wearable="shape"
- label="Lip Fullness"
- show_simple="true"
- edit_group="shape_mouth"
- edit_group_order="2"
- label_min="Less Full"
- label_max="More Full"
- value_min="-1"
- value_max="2"
- camera_distance=".3"
- camera_elevation=".04">
- <param_morph />
+ <value
+ color="88,143,107,255" />
+
+ <value
+ color="194,231,223,255" />
+
+ <value
+ color="207,227,234,255" />
+
+ <value
+ color="41,171,212,255" />
+
+ <value
+ color="180,137,130,255" />
+
+ <value
+ color="173,125,105,255" />
+
+ <value
+ color="144,95,98,255" />
+
+ <value
+ color="115,70,77,255" />
+
+ <value
+ color="155,78,47,255" />
+
+ <value
+ color="239,239,239,255" />
+
+ <value
+ color="194,194,194,255" />
+
+ <value
+ color="120,120,120,255" />
+
+ <value
+ color="10,10,10,255" />
+ </param_color>
</param>
<param
- id="656"
+ id="713"
group="0"
- name="Crooked_Nose"
- wearable="shape"
- label="Crooked Nose"
- edit_group="shape_nose"
+ wearable="skin"
+ edit_group="skin_makeup"
edit_group_order="9"
- label_min="Nose Left"
- label_max="Nose Right"
- value_min="-2"
- value_max="2"
+ name="In Shdw Opacity"
+ label_min="Clear"
+ label_max="Opaque"
+ value_min=".2"
+ value_max="1"
+ value_default=".7"
camera_distance=".3"
- camera_elevation=".04"
- camera_angle="-20">
- <param_morph />
- </param>
+ camera_elevation=".14">
+ <param_color
+ operation="multiply">
+ <value
+ color="255,255,255,0" />
- <param
- id="657"
- group="1"
- name="Smile_Mouth"
- wearable="shape"
- label="Mouth Corner"
- edit_group="shape_mouth"
- label_min="Corner Normal"
- label_max="Corner Up"
- value_min="0"
- value_max="1.4"
- camera_distance=".3"
- camera_elevation=".04">
- <param_morph />
+ <value
+ color="255,255,255,255" />
+ </param_color>
</param>
<param
- id="658"
- group="1"
- name="Frown_Mouth"
- wearable="shape"
- label="Mouth Corner"
- edit_group="shape_mouth"
- label_min="Corner Normal"
- label_max="Corner Down"
+ id="709"
+ group="0"
+ wearable="skin"
+ edit_group="skin_makeup"
+ edit_group_order="7"
+ name="Inner Shadow"
+ label_min="No Eyeshadow"
+ label_max="More Eyeshadow"
value_min="0"
- value_max="1.2"
+ value_max="1"
+ value_default="0"
camera_distance=".3"
- camera_elevation=".04">
- <param_morph />
+ camera_elevation=".14">
+ <param_alpha
+ tga_file="eyeshadow_inner_alpha.tga"
+ skip_if_zero="true"
+ domain="0.2" />
</param>
+ </layer>
+ <layer
+ name="eyeliner"
+ fixed_color="0,0,0,200">
<param
- id="797"
- group="1"
- name="Fat_Upper_Lip"
- wearable="shape"
- label="Fat Upper Lip"
- edit_group="shape_mouth"
- label_min="Normal Upper"
- label_max="Fat Upper"
+ id="703"
+ group="0"
+ wearable="skin"
+ edit_group="skin_makeup"
+ edit_group_order="13"
+ name="Eyeliner"
+ label_min="No Eyeliner"
+ label_max="Full Eyeliner"
value_min="0"
- value_max="1.5"
+ value_max="1"
+ value_default="0.0"
camera_distance=".3"
- camera_elevation=".04">
- <param_morph />
+ camera_elevation=".14">
+ <param_alpha
+ tga_file="eyeliner_alpha.tga"
+ skip_if_zero="true"
+ domain="0.1" />
</param>
<param
- id="798"
- group="1"
- name="Fat_Lower_Lip"
- wearable="shape"
- label="Fat Lower Lip"
- edit_group="shape_mouth"
- label_min="Normal Lower"
- label_max="Fat Lower"
+ id="714"
+ group="0"
+ wearable="skin"
+ edit_group="skin_makeup"
+ edit_group_order="14"
+ name="Eyeliner Color"
+ label_min="Dark Green"
+ label_max="Black"
value_min="0"
- value_max="1.5"
+ value_max="1"
camera_distance=".3"
- camera_elevation=".04">
- <param_morph />
- </param>
+ camera_elevation=".14">
+ <param_color>
+ <value
+ color="24,98,40,250" />
- <param
- id="660"
- group="1"
- name="Shear_Head"
- wearable="shape"
- label="Shear Face"
- edit_group="shape_head"
- label_min="Shear Left"
- label_max="Shear Right"
- value_min="-2"
- value_max="2"
- value_default="0"
- camera_distance=".5"
- camera_elevation=".04">
- <param_morph />
- </param>
+ <!-- dark green -->
+ <value
+ color="9,100,127,250" />
- <param
- id="770"
- group="1"
- name="Elongate_Head"
- wearable="shape"
- label="Shear Face"
- edit_group="shape_head"
- label_min="Flat Head"
- label_max="Long Head"
- value_min="-1"
- value_max="1"
- value_default="0"
- camera_distance=".5"
- camera_elevation=".04">
- <param_morph>
- <volume_morph
- name="HEAD"
- scale="0.02 0.0 0.0"/>
- </param_morph>
- </param>
+ <!-- lt.aqua blue -->
+ <value
+ color="61,93,134,250" />
- <param
- id="663"
- group="0"
- name="Shift_Mouth"
- wearable="shape"
- label="Shift Mouth"
- edit_group="shape_mouth"
- edit_group_order="7"
- label_min="Shift Left"
- label_max="Shift Right"
- value_min="-2"
- value_max="2"
- value_default="0"
- camera_distance=".35"
- camera_elevation=".04"
- camera_angle="-20">
- <param_morph />
- </param>
+ <!-- aqua -->
+ <value
+ color="70,29,27,250" />
- <param
- id="664"
- group="0"
- name="Pop_Eye"
- wearable="shape"
- label="Eye Pop"
- edit_group="shape_eyes"
- edit_group_order="8"
- label_min="Pop Right Eye"
- label_max="Pop Left Eye"
- value_min="-1.3"
- value_max="1.3"
- value_default="0"
- camera_elevation=".1"
- camera_distance=".35">
- <param_morph />
- </param>
+ <!-- dark brown -->
+ <value
+ color="115,75,65,250" />
- <param
- id="760"
- group="0"
- name="Jaw_Angle"
- wearable="shape"
- label="Jaw Angle"
- edit_group="shape_chin"
- edit_group_order="3.5"
- label_min="Low Jaw"
- label_max="High Jaw"
- value_min="-1.2"
- value_max="2"
- value_default="0"
- camera_distance=".5"
- camera_elevation=".04"
- camera_angle="70">
- <param_morph />
- </param>
+ <!-- lt. brown blue -->
+ <value
+ color="100,100,100,250" />
- <param
- id="665"
- group="0"
- name="Jaw_Jut"
- wearable="shape"
- label="Jaw Jut"
- edit_group="shape_chin"
- edit_group_order="4"
- label_min="Overbite"
- label_max="Underbite"
- value_min="-2"
- value_max="2"
- value_default="0"
- camera_distance=".5"
- camera_elevation=".04"
- camera_angle="70">
- <param_morph />
- </param>
+ <!-- grey -->
+ <value
+ color="91,80,74,250" />
- <param
- id="686"
- group="1"
- name="Head_Eyes_Big"
- wearable="shape"
- label="Eye Size"
- edit_group="shape_eyes"
- label_min="Beady Eyes"
- label_max="Anime Eyes"
- show_simple="true"
- value_min="-2"
- value_max="2"
- value_default="0">
- <param_morph />
- </param>
+ <!-- grey/brown -->
+ <value
+ color="112,42,76,250" />
- <param
- id="767"
- group="1"
- name="Bug_Eyed_Head"
- wearable="shape"
- label="Eye Depth"
- edit_group="shape_eyes"
- edit_group_order="4.5"
- label_min="Sunken Eyes"
- label_max="Bug Eyes"
- value_min="-2"
- value_max="2"
- value_default="0">
- <param_morph />
- </param>
+ <!-- plum -->
+ <value
+ color="14,14,14,250" />
-<!--
- #Fat_Lips = Fat_Lips 34 1 0 1
- #Wide_Lips = Wide_Lips 35 1 0 1
- #Wide_Nose = Wide_Nose 36 1 0 1
- -->
-<!--
- ##############
- # Facial Expression morphs
- ##############
- -->
- <param
- id="300"
- group="1"
- name="Express_Closed_Mouth"
- value_default="1"
- value_min="0"
- value_max="1">
- <param_morph />
+ <!-- black -->
+ </param_color>
</param>
+ </layer>
- <param
- id="301"
- group="1"
- name="Express_Tongue_Out"
- value_min="0"
- value_max="1">
- <param_morph />
- </param>
+ <layer
+ name="facialhair bump"
+ render_pass="bump">
+ <texture
+ tga_file="head_hair.tga"
+ file_is_mask="false" />
<param
- id="302"
+ id="1004"
+ sex="male"
group="1"
- name="Express_Surprise_Emote"
+ wearable="hair"
+ edit_group="driven"
+ name="Sideburns bump"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ tga_file="facehair_sideburns_alpha.tga"
+ skip_if_zero="true"
+ domain="0.05" />
</param>
<param
- id="303"
+ id="1006"
+ sex="male"
group="1"
- name="Express_Wink_Emote"
+ wearable="hair"
+ edit_group="driven"
+ name="Moustache bump"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ tga_file="facehair_moustache_alpha.tga"
+ skip_if_zero="true"
+ domain="0.05" />
</param>
<param
- id="304"
+ id="1008"
+ sex="male"
group="1"
- name="Express_Embarrassed_Emote"
+ wearable="hair"
+ edit_group="driven"
+ name="Soulpatch bump"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ tga_file="facehair_soulpatch_alpha.tga"
+ skip_if_zero="true"
+ domain="0.1" />
</param>
<param
- id="305"
+ id="1010"
+ sex="male"
group="1"
- name="Express_Shrug_Emote"
+ edit_group="driven"
+ wearable="hair"
+ name="Chin Curtains bump"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ tga_file="facehair_chincurtains_alpha.tga"
+ skip_if_zero="true"
+ domain="0.03" />
</param>
<param
- id="306"
+ id="1012"
group="1"
- name="Express_Kiss"
+ sex="male"
+ wearable="hair"
+ edit_group="driven"
+ name="5 O'Clock Shadow bump"
value_min="0"
value_max="1">
- <param_morph />
- </param>
+ <param_color>
+ <value
+ color="255,255,255,255" />
- <param
- id="307"
- group="1"
- name="Express_Bored_Emote"
- value_min="0"
- value_max="1">
- <param_morph />
+ <value
+ color="255,255,255,0" />
+ </param_color>
</param>
+ </layer>
- <param
- id="308"
- group="1"
- name="Express_Repulsed_Emote"
- value_min="0"
- value_max="1">
- <param_morph />
- </param>
+ <layer
+ name="facialhair"
+ global_color="hair_color">
- <param
- id="309"
- group="1"
- name="Express_Disdain"
- value_min="0"
- value_max="1">
- <param_morph />
- </param>
+ <texture
+ tga_file="head_hair.tga"
+ file_is_mask="false" />
<param
- id="310"
+ id="1005"
+ sex="male"
group="1"
- name="Express_Afraid_Emote"
+ wearable="hair"
+ edit_group="driven"
+ name="Sideburns"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ tga_file="facehair_sideburns_alpha.tga"
+ skip_if_zero="true"
+ domain="0.05" />
</param>
<param
- id="311"
+ id="1007"
+ sex="male"
group="1"
- name="Express_Worry_Emote"
+ wearable="hair"
+ edit_group="driven"
+ name="Moustache"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ tga_file="facehair_moustache_alpha.tga"
+ skip_if_zero="true"
+ domain="0.05" />
</param>
<param
- id="312"
+ id="1009"
+ sex="male"
group="1"
- name="Express_Cry_Emote"
+ wearable="hair"
+ edit_group="driven"
+ name="Soulpatch"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ tga_file="facehair_soulpatch_alpha.tga"
+ skip_if_zero="true"
+ domain="0.1" />
</param>
<param
- id="313"
+ id="1011"
+ sex="male"
group="1"
- name="Express_Sad_Emote"
+ wearable="hair"
+ edit_group="driven"
+ name="Chin Curtains"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ tga_file="facehair_chincurtains_alpha.tga"
+ skip_if_zero="true"
+ domain="0.03" />
</param>
<param
- id="314"
+ id="751"
group="1"
- name="Express_Anger_Emote"
+ wearable="hair"
+ sex="male"
+ edit_group="hair_facial"
+ name="5 O'Clock Shadow"
+ label_min="Dense hair"
+ label_max="Shadow hair"
value_min="0"
- value_max="1">
- <param_morph />
- </param>
+ value_max="1"
+ value_default="0.7"
+ camera_elevation=".1"
+ camera_distance=".3">
+ <param_color
+ operation="multiply">
+ <value
+ color="255,255,255,255" />
- <param
- id="315"
- group="1"
- name="Express_Frown"
- value_min="0"
- value_max="1">
- <param_morph />
+ <value
+ color="255,255,255,30" />
+ </param_color>
</param>
+ </layer>
- <param
- id="316"
- group="1"
- name="Express_Laugh_Emote"
- value_min="0"
- value_max="1">
- <param_morph />
- </param>
+ <layer
+ name="head_bodypaint">
+ <texture
+ local_texture="head_bodypaint" />
+ </layer>
+ <layer
+ name="eyelash alpha"
+ visibility_mask="TRUE">
+ <texture
+ tga_file="head_alpha.tga"
+ file_is_mask="TRUE" />
+ </layer>
+ <layer
+ name="head alpha"
+ visibility_mask="TRUE">
+ <texture
+ local_texture="head_alpha" />
+ </layer>
+ <layer
+ name="head_tattoo">
+ <texture
+ local_texture="head_tattoo" />
+ </layer>
+
+
+ </layer_set>
+
+ <!-- =========================================================== -->
+ <layer_set
+ body_region="upper_body"
+ width="512"
+ height="512">
+ <layer
+ name="base_upperbody bump"
+ render_pass="bump"
+ fixed_color="128,128,128,255">
+ </layer>
+ <layer
+ name="upperbody bump definition"
+ render_pass="bump">
+ <texture
+ tga_file="bump_upperbody_base.tga"
+ file_is_mask="FALSE"/>
<param
- id="317"
+ id="874"
group="1"
- name="Express_Toothsmile"
+ wearable="skin"
+ edit_group="driven"
+ edit_group_order="20"
+ name="Bump upperdef"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ domain="0" />
</param>
+ </layer>
+
+ <layer
+ name="base"
+ global_color="skin_color">
+ <texture
+ tga_file="body_skingrain.tga" />
+ </layer>
+
+ <layer
+ name="nipples">
+ <texture
+ tga_file="upperbody_color.tga" />
+ </layer>
+
+ <layer
+ name="shadow">
+ <texture
+ tga_file="upperbody_shading_alpha.tga"
+ file_is_mask="TRUE" />
<param
- id="318"
+ id="125"
group="1"
- name="Express_Smile"
+ name="Shading"
+ wearable="skin"
value_min="0"
value_max="1">
- <param_morph />
+ <param_color>
+ <value
+ color="0, 0, 0, 0" />
+
+ <value
+ color="0, 0, 0, 128" />
+ </param_color>
</param>
+ </layer>
+
+ <layer
+ name="highlight">
+ <texture
+ tga_file="upperbody_highlights_alpha.tga"
+ file_is_mask="TRUE" />
<param
- id="632"
+ id="126"
group="1"
- name="Express_Open_Mouth"
+ wearable="skin"
+ name="Shading"
value_min="0"
value_max="1">
- <param_morph />
+ <param_color>
+ <value
+ color="255, 255, 255, 0" />
+
+ <value
+ color="255, 255, 255, 64" />
+ </param_color>
</param>
+ </layer>
-<!--
- ##############
- # Lipsync morphs
- ##############
- -->
+ <layer
+ name="upper_bodypaint">
+ <texture
+ local_texture="upper_bodypaint" />
+ </layer>
+ <layer
+ name="freckles upper"
+ fixed_color="120,47,20,128">
<param
- id="70"
+ id="776"
group="1"
- name="Lipsync_Aah"
+ name="freckles upper"
+ wearable="skin"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ tga_file="upperbodyfreckles_alpha.tga"
+ skip_if_zero="true"
+ domain="0.6" />
</param>
+ </layer>
+
+ <layer
+ name="upper_tattoo">
+ <texture
+ local_texture="upper_tattoo" />
+ </layer>
+
+
+ <layer
+ name="upper_undershirt bump"
+ render_pass="bump"
+ fixed_color="128,128,128,255">
+ <texture
+ local_texture="upper_undershirt"
+ local_texture_alpha_only="true" />
<param
- id="71"
+ id="1043"
group="1"
- name="Lipsync_Ooh"
- value_min="0"
- value_max="1">
- <param_morph />
+ wearable="undershirt"
+ edit_group="driven"
+ name="Sleeve Length bump"
+ value_min=".01"
+ value_max="1"
+ value_default=".4">
+ <param_alpha
+ tga_file="shirt_sleeve_alpha.tga"
+ multiply_blend="false"
+ domain="0.01" />
</param>
-<!--
- ##############
- # other morphs (not user controlled)
- ##############
- -->
<param
- id="40"
+ id="1045"
group="1"
- name="Male_Head"
+ wearable="undershirt"
+ edit_group="undershirt"
+ edit_group_order="2"
+ name="Bottom bump"
value_min="0"
- value_max="1">
- <param_morph />
+ value_max="1"
+ value_default=".8">
+ <param_alpha
+ tga_file="shirt_bottom_alpha.tga"
+ multiply_blend="true"
+ domain="0.05" />
</param>
<param
- id="41"
+ id="1047"
group="1"
- name="Old"
+ wearable="undershirt"
+ edit_group="driven"
+ name="Collar Front bump"
value_min="0"
- value_max="1">
- <param_morph />
+ value_max="1"
+ value_default=".8">
+ <param_alpha
+ tga_file="shirt_collar_alpha.tga"
+ multiply_blend="true"
+ domain="0.05" />
</param>
-<!--
- ##############
- # animatable morphs
- ##############
- -->
<param
- id="51"
+ id="1049"
group="1"
- name="Furrowed_Eyebrows"
+ wearable="undershirt"
+ edit_group="driven"
+ name="Collar Back bump"
value_min="0"
- value_max="1">
- <param_morph />
+ value_max="1"
+ value_default=".8">
+ <param_alpha
+ tga_file="shirt_collar_back_alpha.tga"
+ multiply_blend="true"
+ domain="0.05" />
</param>
+ </layer>
+
+ <layer
+ name="upper_undershirt">
+ <texture
+ local_texture="upper_undershirt" />
<param
- id="53"
- group="1"
- name="Surprised_Eyebrows"
+ id="821"
+ group="0"
+ wearable="undershirt"
+ edit_group="colorpicker"
+ name="undershirt_red"
value_min="0"
- value_max="1">
- <param_morph />
+ value_max="1"
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
+
+ <value
+ color="255, 0, 0, 255" />
+ </param_color>
</param>
<param
- id="54"
- group="1"
- name="Worried_Eyebrows"
+ id="822"
+ group="0"
+ wearable="undershirt"
+ edit_group="colorpicker"
+ name="undershirt_green"
value_min="0"
- value_max="1">
- <param_morph />
+ value_max="1"
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
+
+ <value
+ color="0, 255, 0, 255" />
+ </param_color>
</param>
<param
- id="55"
- group="1"
- name="Frown_Mouth"
+ id="823"
+ group="0"
+ wearable="undershirt"
+ edit_group="colorpicker"
+ name="undershirt_blue"
value_min="0"
- value_max="1">
- <param_morph />
+ value_max="1"
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
+
+ <value
+ color="0, 0, 255, 255" />
+ </param_color>
</param>
<param
- id="57"
+ id="1042"
group="1"
- name="Smile_Mouth"
- value_min="0"
- value_max="1">
- <param_morph />
+ wearable="undershirt"
+ edit_group="driven"
+ name="Sleeve Length"
+ value_min=".01"
+ value_max="1"
+ value_default=".4">
+ <param_alpha
+ tga_file="shirt_sleeve_alpha.tga"
+ multiply_blend="false"
+ domain="0.01" />
</param>
<param
- id="58"
+ id="1044"
group="1"
- name="Blink_Left"
+ wearable="undershirt"
+ edit_group="driven"
+ name="Bottom"
value_min="0"
- value_max="1">
- <param_morph />
+ value_max="1"
+ value_default=".8">
+ <param_alpha
+ tga_file="shirt_bottom_alpha.tga"
+ multiply_blend="true"
+ domain="0.05" />
</param>
<param
- id="59"
+ id="1046"
group="1"
- name="Blink_Right"
+ wearable="undershirt"
+ edit_group="driven"
+ name="Collar Front"
value_min="0"
- value_max="1">
- <param_morph />
- </param>
-
-<!--
- #end morph targets
- -->
- </mesh>
-
- <mesh
- type="headMesh"
- lod="1"
- file_name="avatar_head_1.llm"
- min_pixel_width="160"
- reference="avatar_head.llm">
- </mesh>
-
- <mesh
- type="headMesh"
- lod="2"
- file_name="avatar_head_2.llm"
- min_pixel_width="80"
- reference="avatar_head.llm">
- </mesh>
-
- <mesh
- type="headMesh"
- lod="3"
- file_name="avatar_head_3.llm"
- min_pixel_width="40"
- reference="avatar_head.llm">
- </mesh>
-
- <mesh
- type="headMesh"
- lod="4"
- file_name="avatar_head_4.llm"
- min_pixel_width="0"
- reference="avatar_head.llm">
- </mesh>
-
- <mesh
- type="eyelashMesh"
- lod="0"
- file_name="avatar_eyelashes.llm"
- min_pixel_width="320">
- <param
- shared="1"
- id="660"
- group="1"
- name="Shear_Head"
- wearable="shape"
- label="Shear Face"
- edit_group="shape_head"
- label_min="Shear Left"
- label_max="Shear Right"
- value_min="-2"
- value_max="2"
- value_default="0"
- camera_distance=".5"
- camera_elevation=".04">
- <param_morph />
+ value_max="1"
+ value_default=".8">
+ <param_alpha
+ tga_file="shirt_collar_alpha.tga"
+ multiply_blend="true"
+ domain="0.05" />
</param>
<param
- shared="1"
- id="770"
+ id="1048"
group="1"
- name="Elongate_Head"
- wearable="shape"
- label="Shear Face"
- edit_group="shape_head"
- label_min="Flat Head"
- label_max="Long Head"
- value_min="-1"
+ wearable="undershirt"
+ edit_group="driven"
+ name="Collar Back"
+ label_min="Low"
+ label_max="High"
+ value_min="0"
value_max="1"
- value_default="0"
- camera_distance=".5"
- camera_elevation=".04">
- <param_morph />
+ value_default=".8">
+ <param_alpha
+ tga_file="shirt_collar_back_alpha.tga"
+ multiply_blend="true"
+ domain="0.05" />
</param>
+ </layer>
+ <layer
+ name="Nail Polish">
<param
- shared="1"
- id="664"
+ id="710"
group="0"
- name="Pop_Eye"
- wearable="shape"
- label="Eye Pop"
- edit_group="shape_eyes"
- edit_group_order="8"
- label_min="Pop Right Eye"
- label_max="Pop Left Eye"
- value_min="-2"
- value_max="2"
- value_default="0"
- camera_distance=".5"
- camera_elevation=".04"
- camera_angle="-20">
- <param_morph />
+ wearable="skin"
+ edit_group="skin_makeup"
+ edit_group_order="15"
+ name="Nail Polish"
+ label_min="No Polish"
+ label_max="Painted Nails"
+ value_min="0"
+ value_max="1"
+ value_default="0.0"
+ camera_distance="1.6"
+ camera_elevation="-.4"
+ camera_angle="70">
+ <param_alpha
+ tga_file="nailpolish_alpha.tga"
+ skip_if_zero="true"
+ domain="0.1" />
</param>
<param
- shared="1"
- id="21"
+ id="715"
group="0"
- name="Upper_Eyelid_Fold"
- label="Upper Eyelid Fold"
- wearable="shape"
- edit_group="shape_eyes"
- label_min="Uncreased"
- label_max="Creased"
- value_min="-0.2"
- value_max="1.3"
- camera_elevation=".1"
- camera_distance=".35">
- <param_morph />
- </param>
+ wearable="skin"
+ edit_group="skin_makeup"
+ edit_group_order="16"
+ name="Nail Polish Color"
+ label_min="Pink"
+ label_max="Black"
+ value_min="0"
+ value_max="1"
+ camera_distance="1.6"
+ camera_elevation="-.4"
+ camera_angle="70">
+ <param_color>
+ <value
+ color="255,187,200,255" />
- <param
- shared="1"
- id="24"
- group="0"
- name="Wide_Eyes"
- label="Eye Opening"
- wearable="shape"
- edit_group="shape_eyes"
- label_min="Narrow"
- label_max="Wide"
- show_simple="true"
- value_min="-1.5"
- value_max="2"
- camera_elevation=".1"
- camera_distance=".3">
- <param_morph />
+ <value
+ color="194,102,127,255" />
+
+ <value
+ color="227,34,99,255" />
+
+ <value
+ color="168,41,60,255" />
+
+ <value
+ color="97,28,59,255" />
+
+ <value
+ color="234,115,93,255" />
+
+ <value
+ color="142,58,47,255" />
+
+ <value
+ color="114,30,46,255" />
+
+ <value
+ color="14,14,14,255" />
+ </param_color>
</param>
+ </layer>
+
+ <layer
+ name="upper_gloves bump"
+ render_pass="bump"
+ fixed_color="128,128,128,255">
+ <texture
+ local_texture="upper_gloves"
+ local_texture_alpha_only="true" />
<param
- shared="1"
- id="186"
+ id="1059"
group="1"
- name="Egg_Head"
- label="Egg Head"
- wearable="shape"
- edit_group="shape_head"
- label_min="Chin Heavy"
- label_max="Forehead Heavy"
- value_min="-1.3"
+ wearable="gloves"
+ edit_group="driven"
+ name="Glove Length bump"
+ value_min=".01"
value_max="1"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_morph />
+ value_default=".8">
+ <param_alpha
+ tga_file="glove_length_alpha.tga"
+ domain="0.01" />
</param>
<param
- shared="1"
- id="187"
+ id="1061"
group="1"
- name="Squash_Stretch_Head"
- label="Squash/Stretch Head"
- wearable="shape"
- edit_group="shape_head"
- label_min="Squash Head"
- label_max="Stretch Head"
- value_min="-.5"
+ wearable="gloves"
+ edit_group="driven"
+ name="Glove Fingers bump"
+ value_min=".01"
value_max="1"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_morph />
+ value_default="1">
+ <param_alpha
+ tga_file="gloves_fingers_alpha.tga"
+ multiply_blend="true"
+ domain="0.01" />
</param>
+ </layer>
- <param
- shared="1"
- id="194"
- group="1"
- name="Eye_Spread"
- edit_group="shape_eyes"
- label_min="Eyes Together"
- label_max="Eyes Spread"
- value_min="-2"
- value_max="2">
- <param_morph />
- </param>
+ <layer
+ name="upper_gloves">
+ <texture
+ local_texture="upper_gloves" />
<param
- id="518"
+ id="827"
group="0"
- name="Eyelashes_Long"
- wearable="shape"
- label="Eyelash Length"
- edit_group="shape_eyes"
- edit_group_order="7"
- label_min="Short"
- label_max="Long"
- value_min="-.3"
- value_max="1.5"
- camera_elevation=".1"
- camera_distance=".30"
- camera_angle="-20">
- <param_morph />
+ wearable="gloves"
+ edit_group="colorpicker"
+ name="gloves_red"
+ value_min="0"
+ value_max="1"
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
+
+ <value
+ color="255, 0, 0, 255" />
+ </param_color>
</param>
<param
- shared="1"
- id="650"
+ id="829"
group="0"
- name="Eyelid_Corner_Up"
- label="Outer Eye Corner"
- wearable="shape"
- edit_group="shape_eyes"
- label_min="Corner Down"
- label_max="Corner Up"
- value_min="-1.3"
- value_max="1.2"
- camera_elevation=".1"
- camera_distance=".3">
- <param_morph />
+ wearable="gloves"
+ edit_group="colorpicker"
+ name="gloves_green"
+ value_min="0"
+ value_max="1"
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
+
+ <value
+ color="0, 255, 0, 255" />
+ </param_color>
</param>
-
+
<param
- shared="1"
- id="880"
+ id="830"
group="0"
- name="Eyelid_Inner_Corner_Up"
- label="Inner Eye Corner"
- wearable="shape"
- edit_group="shape_eyes"
- label_min="Corner Down"
- label_max="Corner Up"
- value_min="-1.3"
- value_max="1.2"
- camera_elevation=".1"
- camera_distance=".3">
- <param_morph />
- </param>
+ wearable="gloves"
+ edit_group="colorpicker"
+ name="gloves_blue"
+ value_min="0"
+ value_max="1"
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
- <param
- shared="1"
- id="686"
- group="1"
- name="Head_Eyes_Big"
- wearable="shape"
- label="Eye Size"
- edit_group="shape_eyes"
- label_min="Beady Eyes"
- label_max="Anime Eyes"
- value_min="-2"
- value_max="2"
- show_simple="true"
- value_default="0">
- <param_morph />
+ <value
+ color="0, 0, 255, 255" />
+ </param_color>
</param>
<param
- shared="1"
- id="767"
+ id="1058"
group="1"
- name="Bug_Eyed_Head"
- wearable="shape"
- label="Eye Depth"
- edit_group="shape_eyes"
- edit_group_order="4.5"
- label_min="Sunken Eyes"
- label_max="Bug Eyes"
- value_min="-2"
- value_max="2"
- value_default="0">
- <param_morph />
+ wearable="gloves"
+ edit_group="driven"
+ name="Glove Length"
+ value_min=".01"
+ value_max="1"
+ value_default=".8">
+ <param_alpha
+ tga_file="glove_length_alpha.tga"
+ domain="0.01" />
</param>
-<!--
- ##############
- # Facial Expression morphs
- ##############
- -->
<param
- shared="1"
- id="301"
+ id="1060"
group="1"
- name="Express_Tongue_Out"
- value_min="0"
- value_max="1">
- <param_morph />
+ wearable="gloves"
+ edit_group="driven"
+ name="Glove Fingers"
+ value_min=".01"
+ value_max="1"
+ value_default="1">
+ <param_alpha
+ tga_file="gloves_fingers_alpha.tga"
+ multiply_blend="true"
+ domain="0.01" />
</param>
+ </layer>
- <param
- shared="1"
- id="302"
- group="1"
- name="Express_Surprise_Emote"
- value_min="0"
- value_max="1">
- <param_morph />
- </param>
+ <layer
+ name="upper_clothes_shadow">
+ <texture
+ local_texture="upper_shirt" />
<param
- shared="1"
- id="303"
+ id="899"
group="1"
- name="Express_Wink_Emote"
+ edit_group="driven"
+ wearable="shirt"
+ name="Upper Clothes Shading"
value_min="0"
- value_max="1">
- <param_morph />
- </param>
+ value_max="1"
+ value_default="0">
+ <param_color>
+ <value
+ color="0, 0, 0, 0" />
- <param
- shared="1"
- id="304"
- group="1"
- name="Express_Embarrassed_Emote"
- value_min="0"
- value_max="1">
- <param_morph />
+ <value
+ color="0, 0, 0, 80" />
+ </param_color>
</param>
<param
- shared="1"
- id="305"
+ id="900"
group="1"
- name="Express_Shrug_Emote"
- value_min="0"
- value_max="1">
- <param_morph />
+ wearable="shirt"
+ edit_group="driven"
+ name="Sleeve Length Shadow"
+ value_min="0.02"
+ value_max=".87"
+ value_default="0.02">
+ <param_alpha
+ multiply_blend="false"
+ tga_file="shirt_sleeve_alpha.tga"
+ skip_if_zero="true"
+ domain="0.03" />
</param>
<param
- shared="1"
- id="306"
+ id="901"
group="1"
- name="Express_Kiss"
- value_min="0"
+ wearable="shirt"
+ edit_group="driven"
+ name="Shirt Shadow Bottom"
+ value_min="0.02"
value_max="1">
- <param_morph />
+ <param_alpha
+ multiply_blend="true"
+ tga_file="shirt_bottom_alpha.tga"
+ skip_if_zero="true"
+ domain="0.05" />
</param>
<param
- shared="1"
- id="307"
+ id="902"
group="1"
- name="Express_Bored_Emote"
- value_min="0"
+ wearable="shirt"
+ edit_group="driven"
+ name="Collar Front Shadow Height"
+ value_min="0.02"
value_max="1">
- <param_morph />
+ <param_alpha
+ multiply_blend="true"
+ tga_file="shirt_collar_alpha.tga"
+ skip_if_zero="true"
+ domain="0.02" />
</param>
<param
- shared="1"
- id="308"
+ id="903"
group="1"
- name="Express_Repulsed_Emote"
- value_min="0"
+ wearable="shirt"
+ edit_group="driven"
+ name="Collar Back Shadow Height"
+ value_min="0.02"
value_max="1">
- <param_morph />
+ <param_alpha
+ multiply_blend="true"
+ tga_file="shirt_collar_back_alpha.tga"
+ skip_if_zero="true"
+ domain="0.02" />
</param>
+ </layer>
- <param
- shared="1"
- id="309"
- group="1"
- name="Express_Disdain"
- value_min="0"
- value_max="1">
- <param_morph />
- </param>
+ <layer
+ name="upper_shirt base bump"
+ render_pass="bump"
+ fixed_color="128,128,128,255">
+ <texture
+ local_texture="upper_shirt"
+ local_texture_alpha_only="true" />
<param
- shared="1"
- id="310"
+ id="1029"
group="1"
- name="Express_Afraid_Emote"
+ wearable="shirt"
+ edit_group="driven"
+ name="Sleeve Length Cloth"
value_min="0"
- value_max="1">
- <param_morph />
+ value_max="0.85">
+ <param_alpha
+ multiply_blend="false"
+ tga_file="shirt_sleeve_alpha.tga"
+ domain="0.01" />
</param>
<param
- shared="1"
- id="312"
+ id="1030"
group="1"
- name="Express_Cry_Emote"
+ wearable="shirt"
+ edit_group="driven"
+ name="Shirt Bottom Cloth"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ multiply_blend="true"
+ tga_file="shirt_bottom_alpha.tga"
+ domain="0.05" />
</param>
<param
- shared="1"
- id="313"
+ id="1031"
group="1"
- name="Express_Sad_Emote"
+ wearable="shirt"
+ edit_group="driven"
+ name="Collar Front Height Cloth"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ multiply_blend="true"
+ tga_file="shirt_collar_alpha.tga"
+ domain="0.05" />
</param>
<param
- shared="1"
- id="314"
+ id="1032"
group="1"
- name="Express_Anger_Emote"
+ wearable="shirt"
+ edit_group="driven"
+ name="Collar Back Height Cloth"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ multiply_blend="true"
+ tga_file="shirt_collar_back_alpha.tga"
+ domain="0.05" />
</param>
+ </layer>
- <param
- shared="1"
- id="315"
- group="1"
- name="Express_Frown"
- value_min="0"
- value_max="1">
- <param_morph />
- </param>
+ <layer
+ name="upper_clothes bump"
+ render_pass="bump">
+ <texture
+ tga_file="bump_shirt_wrinkles.tga" />
- <param
- shared="1"
- id="316"
- group="1"
- name="Express_Laugh_Emote"
- value_min="0"
- value_max="1">
- <param_morph />
- </param>
+ <texture
+ local_texture="upper_shirt"
+ local_texture_alpha_only="true" />
<param
- shared="1"
- id="317"
- group="1"
- name="Express_Toothsmile"
+ id="868"
+ group="0"
+ wearable="shirt"
+ edit_group="shirt"
+ edit_group_order="8"
+ name="Shirt Wrinkles"
value_min="0"
- value_max="1">
- <param_morph />
+ value_max="1"
+ value_default="0">
+ <param_color>
+ <value
+ color="255, 255, 255, 0" />
+
+ <value
+ color="255, 255, 255, 255" />
+ </param_color>
</param>
<param
- shared="1"
- id="318"
+ id="1013"
group="1"
- name="Express_Smile"
+ wearable="shirt"
+ edit_group="driven"
+ name="Sleeve Length Cloth"
value_min="0"
- value_max="1">
- <param_morph />
+ value_max="0.85">
+ <param_alpha
+ multiply_blend="false"
+ tga_file="shirt_sleeve_alpha.tga"
+ domain="0.01" />
</param>
-<!--
- ##############
- # other morphs (not user controlled)
- ##############
- -->
<param
- shared="1"
- id="41"
+ id="1014"
group="1"
- name="Old"
+ wearable="shirt"
+ edit_group="driven"
+ name="Shirt Bottom Cloth"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ multiply_blend="true"
+ tga_file="shirt_bottom_alpha.tga"
+ domain="0.05" />
</param>
-<!--
- ##############
- # animatable morphs
- ##############
- -->
<param
- shared="1"
- id="58"
+ id="1015"
group="1"
- name="Blink_Left"
+ wearable="shirt"
+ edit_group="driven"
+ name="Collar Front Height Cloth"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ multiply_blend="true"
+ tga_file="shirt_collar_alpha.tga"
+ domain="0.05" />
</param>
<param
- shared="1"
- id="59"
- group="1"
- name="Blink_Right"
- value_min="0"
- value_max="1">
- <param_morph />
- </param>
- </mesh>
-
-<!--
- #headMesh2 =
- #headMesh3 =
- -->
- <mesh
- type="upperBodyMesh"
- lod="0"
- file_name="avatar_upper_body.llm"
- min_pixel_width="320">
-<!--
- #begin morph targets
- #############
- # tweakable morphs
- #############
- -->
- <param
- id="104"
+ id="1016"
group="1"
- name="Big_Belly_Torso"
+ wearable="shirt"
+ edit_group="driven"
+ name="Collar Back Height Cloth"
value_min="0"
value_max="1">
- <param_morph>
- <volume_morph
- name="BELLY"
- scale="0.075 0.04 0.03"
- pos="0.07 0 -0.07"/>
- </param_morph>
+ <param_alpha
+ multiply_blend="true"
+ tga_file="shirt_collar_back_alpha.tga"
+ domain="0.05" />
</param>
+ </layer>
+
+ <layer
+ name="upper_clothes">
+ <texture
+ local_texture="upper_shirt" />
<param
- id="626"
- sex="female"
- group="1"
- name="Big_Chest"
- label="Chest Size"
- wearable="shape"
- edit_group="shape_torso"
- label_min="Small"
- label_max="Large"
+ id="803"
+ group="0"
+ wearable="shirt"
+ edit_group="colorpicker"
+ name="shirt_red"
value_min="0"
value_max="1"
- camera_elevation=".1"
- camera_distance="1"
- camera_angle="15">
- <param_morph />
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
+
+ <value
+ color="255, 0, 0, 255" />
+ </param_color>
</param>
<param
- id="627"
- sex="female"
- group="1"
- name="Small_Chest"
- label="Chest Size"
- wearable="shape"
- edit_group="shape_torso"
- label_min="Large"
- label_max="Small"
+ id="804"
+ group="0"
+ wearable="shirt"
+ edit_group="colorpicker"
+ name="shirt_green"
value_min="0"
value_max="1"
- camera_elevation="0"
- camera_distance=".28">
- <param_morph />
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
+
+ <value
+ color="0, 255, 0, 255" />
+ </param_color>
</param>
<param
- id="843"
- sex="female"
- group="1"
- name="No_Chest"
- label="Chest Size"
- wearable="shape"
- edit_group="shape_torso"
- label_min="Some"
- label_max="None"
+ id="805"
+ group="0"
+ wearable="shirt"
+ edit_group="colorpicker"
+ name="shirt_blue"
value_min="0"
value_max="1"
- camera_elevation="0"
- camera_distance=".28">
- <param_morph />
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
+
+ <value
+ color="0, 0, 255, 255" />
+ </param_color>
</param>
<param
- id="106"
- group="1"
- name="Muscular_Torso"
- label="Torso Muscles"
- show_simple="true"
- wearable="shape"
- edit_group="shape_torso"
- label_min="Regular"
- label_max="Muscular"
- value_min="0"
- value_max="1.4"
- camera_elevation=".3"
- camera_distance="1.2">
- <param_morph>
- <volume_morph
- name="L_CLAVICLE"
- scale="0.02 0.0 0.005"
- pos="0.0 0 0.005"/>
- <volume_morph
- name="L_UPPER_ARM"
- scale="0.015 0.0 0.005"
- pos="0.015 0 0"/>
- <volume_morph
- name="L_LOWER_ARM"
- scale="0.005 0.0 0.005"
- pos="0.005 0 0"/>
- <volume_morph
- name="R_CLAVICLE"
- scale="0.02 0.0 0.005"
- pos="0.0 0 0.005"/>
- <volume_morph
- name="R_UPPER_ARM"
- scale="0.015 0.0 0.005"
- pos="0.015 0 0"/>
- <volume_morph
- name="R_LOWER_ARM"
- scale="0.005 0.0 0.005"
- pos="0.005 0 0"/>
- </param_morph>
- </param>
-
- <param
- id="648"
- group="1"
- sex="female"
- name="Scrawny_Torso"
- label="Torso Muscles"
- show_simple="true"
- wearable="shape"
- edit_group="shape_torso"
- label_min="Regular"
- label_max="Scrawny"
- value_min="0"
- value_max="1.3"
- camera_elevation=".3"
- camera_distance="1.2">
- <param_morph>
- <volume_morph
- name="BELLY"
- scale="0.0 -0.01 0.0"
- pos="0.0 0.0 0"/>
- <volume_morph
- name="CHEST"
- scale="-0.01 -0.01 0.0"
- pos="0.01 0.0 0"/>
- <volume_morph
- name="L_CLAVICLE"
- scale="0.0 -0.03 -0.005"
- pos="0.0 0 -0.005"/>
- <volume_morph
- name="L_UPPER_ARM"
- scale="-0.01 -0.01 -0.02"
- pos="0 0 0"/>
- <volume_morph
- name="L_LOWER_ARM"
- scale="-0.005 0.0 -0.01"
- pos="-0.005 0 0"/>
- <volume_morph
- name="R_CLAVICLE"
- scale="0.0 -0.03 -0.005"
- pos="0.0 0 -0.005"/>
- <volume_morph
- name="R_UPPER_ARM"
- scale="-0.01 -0.01 -0.02"
- pos="0 0 0"/>
- <volume_morph
- name="R_LOWER_ARM"
- scale="-0.005 0.0 -0.01"
- pos="-0.005 0 0"/>
- </param_morph>
- </param>
-
- <param
- id="677"
- group="1"
- sex="male"
- name="Scrawny_Torso_Male"
- label="Torso Scrawny"
- wearable="shape"
- edit_group="shape_torso"
- label_min="Regular"
- label_max="Scrawny"
- value_min="0"
- value_max="1.3"
- camera_elevation=".3"
- camera_distance="1.2">
- <param_morph>
- <volume_morph
- name="BELLY"
- scale="-0.01 -0.01 0.0"
- pos="0.01 0.0 0"/>
- <volume_morph
- name="CHEST"
- scale="-0.02 -0.02 0.0"
- pos="0.01 0.0 0"/>
- <volume_morph
- name="L_CLAVICLE"
- scale="0.0 -0.03 -0.005"
- pos="0.0 0 -0.005"/>
- <volume_morph
- name="L_UPPER_ARM"
- scale="-0.01 -0.01 -0.02"
- pos="0 0 0"/>
- <volume_morph
- name="L_LOWER_ARM"
- scale="-0.005 0.0 -0.01"
- pos="-0.005 0 0"/>
- <volume_morph
- name="R_CLAVICLE"
- scale="0.0 -0.03 -0.005"
- pos="0.0 0 -0.005"/>
- <volume_morph
- name="R_UPPER_ARM"
- scale="-0.01 -0.01 -0.02"
- pos="0 0 0"/>
- <volume_morph
- name="R_LOWER_ARM"
- scale="-0.005 0.0 -0.01"
- pos="-0.005 0 0"/>
- </param_morph>
- </param>
-
- <param
- id="634"
+ id="600"
group="1"
- name="Fat_Torso"
- label="Fat Torso"
- wearable="shape"
- edit_group="shape_body"
- label_min="skinny"
- label_max="fat"
+ wearable="shirt"
+ edit_group="driven"
+ name="Sleeve Length Cloth"
value_min="0"
- value_max="1"
- camera_elevation=".3">
- <param_morph>
- <volume_morph
- name="CHEST"
- scale="0.02 0.03 0.03"
- pos="0 0 -0.03"/>
- <volume_morph
- name="BELLY"
- scale="0.09 0.08 0.07"
- pos="0 0 -0.05"/>
- <volume_morph
- name="L_CLAVICLE"
- scale="0.0 0.0 0.015"/>
- <volume_morph
- name="L_UPPER_ARM"
- scale="0.02 0.0 0.02"
- pos="0.0 0.0 -0.02"/>
- <volume_morph
- name="L_LOWER_ARM"
- scale="0.01 0.0 0.01"
- pos="0.0 0.0 -0.01"/>
- <volume_morph
- name="R_CLAVICLE"
- scale="0.0 0.0 0.015"/>
- <volume_morph
- name="R_UPPER_ARM"
- scale="0.02 0.0 0.02"
- pos="0.0 0.0 -0.02"/>
- <volume_morph
- name="R_LOWER_ARM"
- scale="0.01 0.0 0.01"
- pos="0.0 0.0 -0.01"/>
- <volume_morph
- name="NECK"
- scale="0.015 0.01 0.0"/>
- <volume_morph
- name="HEAD"
- scale="0.0 0.0 0.01"
- pos="0 0 -0.01"/>
- </param_morph>
-
- </param>
-
- <param
- id="507"
- group="0"
- sex="female"
- name="Breast_Gravity"
- label="Breast Buoyancy"
- wearable="shape"
- edit_group="shape_torso"
- edit_group_order="7"
- label_min="Less Gravity"
- label_max="More Gravity"
- value_default="0"
- value_min="-1.5"
- value_max="2"
- camera_elevation=".3"
- camera_distance=".8">
- <param_morph />
+ value_max="0.85"
+ value_default=".7">
+ <param_alpha
+ multiply_blend="false"
+ tga_file="shirt_sleeve_alpha.tga"
+ domain="0.01" />
</param>
<param
- id="628"
+ id="601"
group="1"
- name="Displace_Loose_Upperbody"
- label="Shirt Fit"
wearable="shirt"
edit_group="driven"
- clothing_morph="true"
+ name="Shirt Bottom Cloth"
value_min="0"
value_max="1"
- value_default="0">
- <param_morph />
+ value_default=".8">
+ <param_alpha
+ multiply_blend="true"
+ tga_file="shirt_bottom_alpha.tga"
+ domain="0.05" />
</param>
<param
- id="840"
- group="0"
- name="Shirtsleeve_flair"
- label="Sleeve Looseness"
- show_simple="true"
+ id="602"
+ group="1"
wearable="shirt"
- edit_group="shirt"
- edit_group_order="6"
- clothing_morph="true"
- label_min="Tight Sleeves"
- label_max="Loose Sleeves"
+ edit_group="driven"
+ name="Collar Front Height Cloth"
value_min="0"
- value_max="1.5"
- camera_distance="1.8"
- camera_angle="30"
- camera_elevation="-.3">
- <param_morph />
+ value_max="1"
+ value_default=".8">
+ <param_alpha
+ multiply_blend="true"
+ tga_file="shirt_collar_alpha.tga"
+ domain="0.05" />
</param>
<param
- id="855"
+ id="778"
group="1"
- name="Love_Handles"
- value_default="0"
- value_min="-1"
- value_max="2">
- <param_morph>
- <volume_morph
- name="BELLY"
- scale="0.0 0.02 0.0"/>
- </param_morph>
- </param>
-
- <param
- id="684"
- group="0"
- sex="female"
- name="Breast_Female_Cleavage"
- label="Breast Cleavage"
- wearable="shape"
- edit_group="shape_torso"
- edit_group_order="8"
- label_min="Separate"
- label_max="Join"
- value_default="0"
- value_min="-.3"
- value_max="1.3"
- camera_elevation=".3"
- camera_distance=".8">
- <param_morph />
+ wearable="shirt"
+ edit_group="driven"
+ name="Collar Back Height Cloth"
+ value_min="0"
+ value_max="1"
+ value_default=".8">
+ <param_alpha
+ multiply_blend="true"
+ tga_file="shirt_collar_back_alpha.tga"
+ domain="0.05" />
</param>
+ </layer>
- <param
- id="685"
- group="0"
- sex="male"
- name="Chest_Male_No_Pecs"
- label="Pectorals"
- wearable="shape"
- edit_group="shape_torso"
- edit_group_order="5"
- label_min="Big Pectorals"
- label_max="Sunken Chest"
- value_default="0"
- value_min="-.5"
- value_max="1.1"
- camera_elevation=".3"
- camera_distance="1.2">
- <param_morph />
- </param>
+ <layer
+ name="upper_jacket base bump"
+ render_pass="bump"
+ fixed_color="128,128,128,255">
+ <texture
+ local_texture="upper_jacket"
+ local_texture_alpha_only="true" />
-<!-- ############# #
- other morphs (not user controlled)
- ############# -->
<param
- id="100"
+ id="1039"
group="1"
- name="Male_Torso"
- label_min="Male_Torso"
- value_min="0"
- value_max="1">
- <param_morph>
- <volume_morph
- name="CHEST"
- scale="0.03 0.04 0.02"
- pos="-0.03 0 -0.01"/>
- <volume_morph
- name="BELLY"
- scale="0.03 0.03 0.0"
- pos="-0.03 0 0.02"/>
- <volume_morph
- name="L_CLAVICLE"
- scale="0.02 0.0 0.01"
- pos="-0.02 0 0"/>
- <volume_morph
- name="L_UPPER_ARM"
- scale="0.01 0.0 0.01"
- pos="0.0 0.0 -0.01"/>
- <volume_morph
- name="L_LOWER_ARM"
- scale="0.005 0.0 0.005"
- pos="0.0 0.0 -0.005"/>
- <volume_morph
- name="R_CLAVICLE"
- scale="0.02 0.0 0.01"
- pos="-0.02 0 0"/>
- <volume_morph
- name="R_UPPER_ARM"
- scale="0.01 0.0 0.01"
- pos="0.0 0.0 -0.01"/>
- <volume_morph
- name="R_LOWER_ARM"
- scale="0.005 0.0 0.005"
- pos="0.0 0.0 -0.005"/>
- <volume_morph
- name="NECK"
- scale="0.015 0.01 0.0"/>
- <volume_morph
- name="HEAD"
- scale="0.0 0.0 0.01"
- pos="0 0 -0.01"/>
- </param_morph>
- </param>
-
-<!--
- ##############
- # animatable morphs
- ##############
- -->
- <param
- id="101"
- group="1"
- name="Hands_Relaxed"
+ wearable="jacket"
+ edit_group="driven"
+ edit_group_order="1"
+ name="Jacket Sleeve Length bump"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ multiply_blend="false"
+ tga_file="shirt_sleeve_alpha.tga"
+ domain="0.01" />
</param>
<param
- id="102"
+ id="1040"
group="1"
- name="Hands_Point"
+ wearable="jacket"
+ edit_group="driven"
+ name="Jacket Collar Front bump"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ multiply_blend="true"
+ tga_file="shirt_collar_alpha.tga"
+ domain="0.05" />
</param>
<param
- id="103"
+ id="1041"
group="1"
- name="Hands_Fist"
+ wearable="jacket"
+ edit_group="driven"
+ edit_group_order="3.5"
+ name="Jacket Collar Back bump"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ multiply_blend="true"
+ tga_file="shirt_collar_back_alpha.tga"
+ domain="0.05" />
</param>
<param
- id="666"
+ id="1037"
group="1"
- name="Hands_Relaxed_L"
+ wearable="jacket"
+ edit_group="driven"
+ name="jacket bottom length upper bump"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ multiply_blend="true"
+ tga_file="jacket_length_upper_alpha.tga"
+ domain="0.01" />
</param>
<param
- id="667"
+ id="1038"
group="1"
- name="Hands_Point_L"
+ wearable="jacket"
+ edit_group="driven"
+ name="jacket open upper bump"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ multiply_blend="true"
+ tga_file="jacket_open_upper_alpha.tga"
+ domain="0.01" />
</param>
+ </layer>
- <param
- id="668"
- group="1"
- name="Hands_Fist_L"
- value_min="0"
- value_max="1">
- <param_morph />
- </param>
+ <layer
+ name="upper_jacket bump"
+ render_pass="bump">
+ <texture
+ tga_file="bump_shirt_wrinkles.tga" />
- <param
- id="669"
- group="1"
- name="Hands_Relaxed_R"
- value_min="0"
- value_max="1">
- <param_morph />
- </param>
+ <texture
+ local_texture="upper_jacket"
+ local_texture_alpha_only="true" />
+
<param
- id="670"
- group="1"
- name="Hands_Point_R"
- value_min="0"
- value_max="1">
- <param_morph />
+ id="875"
+ group="1"
+ wearable="jacket"
+ name="jacket upper Wrinkles"
+ value_min="0"
+ value_max="1"
+ value_default="0">
+ <param_color>
+ <value
+ color="255, 255, 255, 0" />
+
+ <value
+ color="255, 255, 255, 255" />
+ </param_color>
</param>
<param
- id="671"
+ id="1019"
group="1"
- name="Hands_Fist_R"
+ wearable="jacket"
+ edit_group="driven"
+ edit_group_order="1"
+ name="Jacket Sleeve Length bump"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ multiply_blend="false"
+ tga_file="shirt_sleeve_alpha.tga"
+ domain="0.01" />
</param>
<param
- id="672"
+ id="1021"
group="1"
- name="Hands_Typing"
+ wearable="jacket"
+ edit_group="driven"
+ name="Jacket Collar Front bump"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ multiply_blend="true"
+ tga_file="shirt_collar_alpha.tga"
+ domain="0.05" />
</param>
<param
- id="766"
+ id="1023"
group="1"
- name="Hands_Salute_R"
+ wearable="jacket"
+ edit_group="driven"
+ edit_group_order="3.5"
+ name="Jacket Collar Back bump"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ multiply_blend="true"
+ tga_file="shirt_collar_back_alpha.tga"
+ domain="0.05" />
</param>
<param
- id="791"
+ id="1025"
group="1"
- name="Hands_Peace_R"
+ wearable="jacket"
+ edit_group="driven"
+ name="jacket bottom length upper bump"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ multiply_blend="true"
+ tga_file="jacket_length_upper_alpha.tga"
+ domain="0.01" />
</param>
<param
- id="792"
+ id="1026"
group="1"
- name="Hands_Spread_R"
+ wearable="jacket"
+ edit_group="driven"
+ name="jacket open upper bump"
value_min="0"
value_max="1">
- <param_morph />
+ <param_alpha
+ multiply_blend="true"
+ tga_file="jacket_open_upper_alpha.tga"
+ domain="0.01" />
</param>
+ </layer>
-<!--
- #end morph targets
- -->
- </mesh>
-
- <mesh
- type="upperBodyMesh"
- lod="1"
- file_name="avatar_upper_body_1.llm"
- min_pixel_width="160"
- reference="avatar_upper_body.llm">
- </mesh>
-
- <mesh
- type="upperBodyMesh"
- lod="2"
- file_name="avatar_upper_body_2.llm"
- min_pixel_width="80"
- reference="avatar_upper_body.llm">
- </mesh>
-
- <mesh
- type="upperBodyMesh"
- lod="3"
- file_name="avatar_upper_body_3.llm"
- min_pixel_width="40"
- reference="avatar_upper_body.llm">
- </mesh>
-
- <mesh
- type="upperBodyMesh"
- lod="4"
- file_name="avatar_upper_body_4.llm"
- min_pixel_width="0"
- reference="avatar_upper_body.llm">
- </mesh>
-
-<!--
- #upperBodyMesh2 =
- #upperBodyMesh3 =
- -->
- <mesh
- type="lowerBodyMesh"
- lod="0"
- file_name="avatar_lower_body.llm"
- min_pixel_width="320">
-<!--
- #begin morph targets
- #############
- # tweakable morphs
- #############
- -->
- <param
- id="156"
- group="1"
- name="Big_Belly_Legs"
- value_min="0"
- value_max="1">
- <param_morph />
- </param>
+ <layer
+ name="upper_jacket">
+ <texture
+ local_texture="upper_jacket" />
<param
- id="151"
+ id="831"
group="1"
- name="Big_Butt_Legs"
- label="Butt Size"
- wearable="shape"
- edit_group="shape_legs"
- label_min="Regular"
- label_max="Large"
+ edit_group="colorpicker_driven"
+ wearable="jacket"
+ name="upper_jacket_red"
value_min="0"
- value_max="1">
- <param_morph>
- <volume_morph
- name="PELVIS"
- scale="0.03 0.0 0.02"
- pos="-0.03 0 -0.025"/>
- </param_morph>
- </param>
+ value_max="1"
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
- <param
- id="794"
- group="1"
- name="Small_Butt"
- label="Butt Size"
- wearable="shape"
- edit_group="shape_legs"
- label_min="Regular"
- label_max="Small"
- value_min="0"
- value_max="1">
- <param_morph>
- <volume_morph
- name="PELVIS"
- scale="-0.01 0.0 0.0"
- pos="0.01 0 0.0"/>
- </param_morph>
+ <value
+ color="255, 0, 0, 255" />
+ </param_color>
</param>
<param
- id="152"
- group="1"
- name="Muscular_Legs"
- label="Leg Muscles"
- show_simple="true"
- wearable="shape"
- edit_group="shape_legs"
- label_min="Regular Muscles"
- label_max="More Muscles"
- value_min="0"
- value_max="1.5"
- camera_distance="1.3"
- camera_elevation="-.5">
- <param_morph>
- <volume_morph
- name="L_UPPER_LEG"
- scale="0.015 0.015 0.0"
- pos="0.0 0 0.0"/>
- <volume_morph
- name="L_LOWER_LEG"
- scale="0.01 0.01 0.0"
- pos="0.0 0 0.0"/>
- <volume_morph
- name="R_UPPER_LEG"
- scale="0.015 0.015 0.0"
- pos="0.0 0 0.0"/>
- <volume_morph
- name="R_LOWER_LEG"
- scale="0.01 0.01 0.0"
- pos="0.0 0 0.0"/>
- </param_morph>
- </param>
-
- <param
- id="651"
+ id="832"
group="1"
- name="Scrawny_Legs"
- label="Scrawny Leg"
- wearable="shape"
- edit_group="shape_legs"
- label_min="Regular Muscles"
- label_max="Less Muscles"
- value_min="0"
- value_max="1.5"
- camera_distance="1.3"
- camera_elevation="-.5">
- <param_morph>
- <volume_morph
- name="L_UPPER_LEG"
- scale="-0.03 -0.03 0.0"
- pos="0.0 0 0.0"/>
- <volume_morph
- name="L_LOWER_LEG"
- scale="-0.015 -0.015 0.0"
- pos="0.0 0 0.0"/>
- <volume_morph
- name="R_UPPER_LEG"
- scale="-0.03 -0.03 0.0"
- pos="0.0 0 0.0"/>
- <volume_morph
- name="R_LOWER_LEG"
- scale="-0.015 -0.015 0.0"
- pos="0.0 0 0.0"/>
- </param_morph>
- </param>
-
- <param
- id="853"
- group="1"
- name="Bowed_Legs"
- label="Knee Angle"
- wearable="shape"
- value_min="-1"
- value_max="1">
- <param_morph>
- <volume_morph
- name="L_UPPER_LEG"
- pos="0.0 0.03 0.0"/>
- <volume_morph
- name="L_LOWER_LEG"
- pos="0.0 0.03 0.0"/>
- <volume_morph
- name="R_UPPER_LEG"
- pos="0.0 -0.03 0.0"/>
- <volume_morph
- name="R_LOWER_LEG"
- pos="0.0 -0.03 0.0"/>
- </param_morph>
- </param>
-
- <param
- id="500"
- group="1"
- name="Shoe_Heel_Height"
- label="Heel Height"
- wearable="shoes"
- edit_group="shoes"
- label_min="Low Heels"
- label_max="High Heels"
+ edit_group="colorpicker_driven"
+ wearable="jacket"
+ name="upper_jacket_green"
value_min="0"
value_max="1"
- camera_distance="1.5"
- camera_elevation="-.5">
- <param_morph />
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
+
+ <value
+ color="0, 255, 0, 255" />
+ </param_color>
</param>
<param
- id="501"
+ id="833"
group="1"
- name="Shoe_Platform_Height"
- label="Platform Height"
- wearable="shoes"
- edit_group="shoes"
- label_min="Low Platforms"
- label_max="High Platforms"
+ edit_group="colorpicker_driven"
+ wearable="jacket"
+ name="upper_jacket_blue"
value_min="0"
value_max="1"
- camera_distance="1.5"
- camera_elevation="-.5">
- <param_morph />
- </param>
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
- <param
- id="508"
- group="0"
- name="Shoe_Platform_Width"
- label="Platform Width"
- wearable="shoes"
- edit_group="shoes"
- edit_group_order="7"
- label_min="Narrow"
- label_max="Wide"
- value_min="-1"
- value_max="2"
- camera_angle="15"
- camera_distance="1.5"
- camera_elevation="-1">
- <param_morph />
+ <value
+ color="0, 0, 255, 255" />
+ </param_color>
</param>
<param
- id="509"
+ id="1020"
group="1"
- name="Shoe_Heel_Point"
- label="Heel Shape"
- wearable="shoes"
- edit_group="shoes"
- label_min="Default Heels"
- label_max="Pointy Heels"
- value_min="0"
- value_max="1"
- camera_distance="1.3"
- camera_elevation="-.5">
- <param_morph />
+ edit_group="driven"
+ wearable="jacket"
+ name="jacket Sleeve Length" value_min="0"
+ value_max="1">
+ <param_alpha
+ multiply_blend="false"
+ tga_file="shirt_sleeve_alpha.tga"
+ domain="0.01" />
</param>
<param
- id="510"
+ id="1022"
group="1"
- name="Shoe_Heel_Thick"
- label="Heel Shape"
- wearable="shoes"
- edit_group="shoes"
- label_min="default Heels"
- label_max="Thick Heels"
+ wearable="jacket"
+ edit_group="driven"
+ name="jacket Collar Front"
value_min="0"
- value_max="1"
- camera_distance="1.3"
- camera_elevation="-.5">
- <param_morph />
+ value_max="1">
+ <param_alpha
+ multiply_blend="true"
+ tga_file="shirt_collar_alpha.tga"
+ domain="0.05" />
</param>
<param
- id="511"
+ id="1024"
group="1"
- name="Shoe_Toe_Point"
- label="Toe Shape"
- wearable="shoes"
- edit_group="shoes"
- label_min="Default Toe"
- label_max="Pointy Toe"
+ wearable="jacket"
+ edit_group="driven"
+ edit_group_order="3.5"
+ name="jacket Collar Back"
value_min="0"
- value_max="1"
- camera_distance="1.3"
- camera_elevation="-.5">
- <param_morph />
+ value_max="1">
+ <param_alpha
+ multiply_blend="true"
+ tga_file="shirt_collar_back_alpha.tga"
+ domain="0.05" />
</param>
<param
- id="512"
+ id="620"
group="1"
- name="Shoe_Toe_Square"
- label="Toe Shape"
- wearable="shoes"
- edit_group="shoes"
- label_min="Default Toe"
- label_max="Square Toe"
+ wearable="jacket"
+ edit_group="jacket"
+ name="bottom length upper"
+ label_min="hi cut"
+ label_max="low cut"
value_min="0"
value_max="1"
- camera_distance="1.5"
- camera_elevation="-.5">
- <param_morph />
- </param>
-
- <param
- id="654"
- group="0"
- name="Shoe_Toe_Thick"
- label="Toe Thickness"
- wearable="shoes"
- edit_group="shoes"
- edit_group_order="5"
- label_min="Flat Toe"
- label_max="Thick Toe"
- value_min="0"
- value_max="2"
- camera_angle="15"
- camera_distance="1.5"
- camera_elevation="-1">
- <param_morph />
+ value_default=".8"
+ camera_distance="1.2"
+ camera_angle="30"
+ camera_elevation=".2">
+ <param_alpha
+ multiply_blend="true"
+ tga_file="jacket_length_upper_alpha.tga"
+ domain="0.01" />
</param>
<param
- id="515"
- group="0"
- name="Foot_Size"
- label="Foot Size"
- wearable="shape"
- edit_group="shape_legs"
- edit_group_order="6"
- label_min="Small"
- label_max="Big"
- value_min="-1"
- value_max="3"
- camera_angle="45"
- camera_distance="1.1"
- camera_elevation="-1">
- <param_morph>
- <volume_morph
- name="L_FOOT"
- scale="0.02 0.01 0.0"
- pos="0.01 0 0"/>
- <volume_morph
- name="R_FOOT"
- scale="0.02 0.01 0.0"
- pos="0.01 0 0"/>
- </param_morph>
- </param>
-
- <param
- id="516"
+ id="622"
group="1"
- name="Displace_Loose_Lowerbody"
- label="Pants Fit"
- wearable="pants"
- edit_group="driven"
- clothing_morph="true"
+ wearable="jacket"
+ edit_group="jacket"
+ name="open upper"
+ label_min="closed"
+ label_max="open"
value_min="0"
value_max="1"
- value_default="0">
- <param_morph />
- </param>
-
- <param
- id="625"
- group="0"
- name="Leg_Pantflair"
- label="Cuff Flare"
- show_simple="true"
- wearable="pants"
- edit_group="pants"
- edit_group_order="3"
- clothing_morph="true"
- label_min="Tight Cuffs"
- label_max="Flared Cuffs"
- value_min="0"
- value_max="1.5"
- camera_distance="1.8"
+ value_default=".8"
+ camera_distance="1.2"
camera_angle="30"
- camera_elevation="-.3">
- <param_morph />
+ camera_elevation=".2">
+ <param_alpha
+ multiply_blend="true"
+ tga_file="jacket_open_upper_alpha.tga"
+ domain="0.01" />
</param>
+ </layer>
+
+ <layer
+ name="upper alpha"
+ visibility_mask="TRUE">
+ <texture
+ local_texture="upper_alpha" />
+ </layer>
+
+ </layer_set>
+
+ <!-- =========================================================== -->
+ <layer_set
+ body_region="lower_body"
+ width="512"
+ height="512">
+ <layer
+ name="lower body bump base"
+ fixed_color = "128,128,128,255"
+ render_pass="bump">
+ </layer>
+ <layer
+ name="base_lowerbody bump"
+ render_pass="bump">
+ <texture
+ tga_file="bump_lowerbody_base.tga"
+ file_is_mask="FALSE" />
<param
- id="793"
+ id="878"
group="1"
- name="Leg_Longcuffs"
- label="Longcuffs"
- wearable="pants"
+ wearable="skin"
edit_group="driven"
- clothing_morph="true"
+ edit_group_order="20"
+ name="Bump upperdef"
value_min="0"
- value_max="3"
- value_default="0">
- <param_morph />
+ value_max="1">
+ <param_alpha
+ domain="0" />
</param>
+ </layer>
- <param
- id="638"
- group="0"
- name="Low_Crotch"
- label="Pants Crotch"
- wearable="pants"
- clothing_morph="true"
- edit_group="pants"
- edit_group_order="4"
- label_min="High and Tight"
- label_max="Low and Loose"
- value_min="0"
- value_max="1.3"
- camera_distance="1.2"
- camera_angle="-20"
- camera_elevation="-.3">
- <param_morph />
- </param>
+ <layer
+ name="base"
+ global_color="skin_color">
+ <texture
+ tga_file="body_skingrain.tga" />
+ </layer>
+
+ <layer
+ name="shadow">
+ <texture
+ tga_file="lowerbody_shading_alpha.tga"
+ file_is_mask="TRUE" />
<param
- id="635"
+ id="160"
group="1"
- name="Fat_Legs"
- label="Fat Torso"
- wearable="shape"
- edit_group="shape_body"
- label_min="skinny"
- label_max="fat"
+ name="Shading"
+ wearable="pants"
+ cross_wearable="true"
value_min="0"
value_max="1">
- <param_morph>
- <volume_morph
- name="PELVIS"
- scale="0.03 0.06 0.0"/>
- <volume_morph
- name="R_UPPER_LEG"
- scale="0.02 0.02 0.0"
- pos="0.0 -0.02 0.0"/>
- <volume_morph
- name="R_LOWER_LEG"
- scale="0.01 0.01 0.0"/>
- <volume_morph
- name="L_UPPER_LEG"
- scale="0.02 0.02 0.0"
- pos="0.0 0.02 0.0"/>
- <volume_morph
- name="L_LOWER_LEG"
- scale="0.01 0.01 0.0"/>
- </param_morph>
- </param>
-
- <param
- id="854"
- group="1"
- name="Saddlebags"
- value_min="-.5"
- value_max="3">
- <param_morph>
- <volume_morph
- name="PELVIS"
- scale="0.0 0.025 0.0"/>
- </param_morph>
+ <param_color>
+ <value
+ color="0, 0, 0, 0" />
+ <value
+ color="0, 0, 0, 128" />
+ </param_color>
</param>
+ </layer>
- <param
- id="879"
- group="0"
- sex="male"
- name="Male_Package"
- label="Package"
- wearable="shape"
- edit_group="shape_legs"
- edit_group_order="4.6"
- label_min="Coin Purse"
- label_max="Duffle Bag"
- value_default="0"
- value_min="-.5"
- value_max="2"
- camera_angle="60"
- camera_distance=".6">
- <param_morph />
- </param>
+ <layer
+ name="highlight">
+ <texture
+ tga_file="lowerbody_highlights_alpha.tga"
+ file_is_mask="TRUE" />
-<!--
- #############
- # other morphs (not user controlled)
- #############
- -->
<param
- id="153"
+ id="161"
group="1"
- name="Male_Legs"
+ name="Shading"
+ wearable="skin"
value_min="0"
value_max="1">
- <param_morph />
- </param>
-
-<!--
- #end morph targets
- -->
- </mesh>
-
- <mesh
- type="lowerBodyMesh"
- lod="1"
- file_name="avatar_lower_body_1.llm"
- min_pixel_width="160"
- reference="avatar_lower_body.llm">
- </mesh>
-
- <mesh
- type="lowerBodyMesh"
- lod="2"
- file_name="avatar_lower_body_2.llm"
- min_pixel_width="80"
- reference="avatar_lower_body.llm">
- </mesh>
-
- <mesh
- type="lowerBodyMesh"
- lod="3"
- file_name="avatar_lower_body_3.llm"
- min_pixel_width="40"
- reference="avatar_lower_body.llm">
- </mesh>
-
- <mesh
- type="lowerBodyMesh"
- lod="4"
- file_name="avatar_lower_body_4.llm"
- min_pixel_width="0"
- reference="avatar_lower_body.llm">
- </mesh>
-
-<!--
- #lowerBodyMesh2 =
- #lowerBodyMesh3 =
- -->
-<!--
- #eyeLidLeftMesh =
- -->
- <mesh
- type="eyeBallLeftMesh"
- lod="0"
- file_name="avatar_eye.llm"
- min_pixel_width="320">
-<!-- begin morph_params -->
- <param
- id="679"
- group="1"
- name="Eyeball_Size"
- label="Eyeball Size"
- wearable="shape"
- edit_group="shape_eyes"
- label_min="small eye"
- label_max="big eye"
- value_min="-.25"
- value_max=".10">
- <param_morph />
- </param>
+ <param_color>
+ <value
+ color="255, 255, 255, 0" />
- <param
- id="687"
- group="1"
- name="Eyeball_Size"
- label="Big Eyeball"
- wearable="shape"
- edit_group="shape_eyes"
- label_min="small eye"
- label_max="big eye"
- value_min="-.25"
- value_max=".25">
- <param_morph />
- </param>
- </mesh>
-
- <mesh
- type="eyeBallLeftMesh"
- lod="1"
- file_name="avatar_eye_1.llm"
- min_pixel_width="80">
-<!-- begin morph_params -->
- <param
- id="694"
- group="1"
- name="Eyeball_Size"
- label="Eyeball Size"
- wearable="shape"
- edit_group="shape_eyes"
- label_min="small eye"
- label_max="big eye"
- value_min="-.25"
- value_max=".10">
- <param_morph />
- </param>
-
- <param
- id="695"
- group="1"
- name="Eyeball_Size"
- label="Big Eyeball"
- wearable="shape"
- edit_group="shape_eyes"
- label_min="small eye"
- label_max="big eye"
- value_min="-.25"
- value_max=".25">
- <param_morph />
- </param>
- </mesh>
-
-<!--
- #eyeLidRightMesh =
- -->
- <mesh
- type="eyeBallRightMesh"
- lod="0"
- file_name="avatar_eye.llm"
- min_pixel_width="320">
-<!-- begin morph_params -->
- <param
- id="680"
- group="1"
- name="Eyeball_Size"
- label="Eyeball Size"
- wearable="shape"
- label_min="small eye"
- label_max="big eye"
- value_min="-.25"
- value_max=".10">
- <param_morph />
+ <value
+ color="255, 255, 255, 64" />
+ </param_color>
</param>
+ </layer>
- <param
- id="688"
- group="1"
- name="Eyeball_Size"
- label="Big Eyeball"
- wearable="shape"
- label_min="small eye"
- label_max="big eye"
- value_min="-.25"
- value_max=".25">
- <param_morph />
- </param>
- </mesh>
-
- <mesh
- type="eyeBallRightMesh"
- lod="1"
- file_name="avatar_eye_1.llm"
- min_pixel_width="80">
-<!-- begin morph_params -->
- <param
- id="681"
- group="1"
- name="Eyeball_Size"
- label="Eyeball Size"
- wearable="shape"
- edit_group="shape_eyes"
- label_min="small eye"
- label_max="big eye"
- value_min="-.25"
- value_max=".10">
- <param_morph />
- </param>
+ <layer
+ name="toenails">
+ <texture
+ tga_file="lowerbody_color.tga" />
+ </layer>
- <param
- id="691"
- group="1"
- name="Eyeball_Size"
- label="Big Eyeball"
- wearable="shape"
- edit_group="shape_eyes"
- label_min="small eye"
- label_max="big eye"
- value_min="-.25"
- value_max=".25">
- <param_morph />
- </param>
- </mesh>
+ <layer
+ name="lower_bodypaint">
+ <texture
+ local_texture="lower_bodypaint" />
+ </layer>
- <mesh
- type="skirtMesh"
- lod="0"
- file_name="avatar_skirt.llm"
- min_pixel_width="320">
+ <layer
+ name="freckles lower"
+ fixed_color="120,47,20,128">
<param
- id="845"
+ id="777"
group="1"
- name="skirt_poofy"
- label="poofy skirt"
- clothing_morph="true"
- wearable="skirt"
- edit_group="skirt"
- label_min="less poofy"
- label_max="more poofy"
+ name="freckles lower"
+ wearable="skin"
value_min="0"
- value_max="1.5">
- <param_morph />
+ value_max="1">
+ <param_alpha
+ tga_file="bodyfreckles_alpha.tga"
+ skip_if_zero="true"
+ domain="0.6" />
</param>
+ </layer>
+
+ <layer
+ name="lower_tattoo">
+ <texture
+ local_texture="lower_tattoo" />
+ </layer>
+
+ <layer
+ name="lower_underpants bump"
+ render_pass="bump"
+ fixed_color="128,128,128,255">
+ <texture
+ local_texture="lower_underpants"
+ local_texture_alpha_only="true" />
<param
- id="846"
+ id="1055"
group="1"
- name="skirt_loose"
- label="loose skirt"
- clothing_morph="true"
- wearable="skirt"
- edit_group="skirt"
- label_min="form fitting"
- label_max="loose"
+ wearable="underpants"
+ edit_group="underpants"
+ name="Pants Length"
value_min="0"
- value_max="1">
- <param_morph />
+ value_max="1"
+ value_default=".3">
+ <param_alpha
+ tga_file="pants_length_alpha.tga"
+ domain="0.01" />
</param>
<param
- id="866"
+ id="1057"
group="1"
- name="skirt_tight"
- label="tight skirt"
- clothing_morph="true"
- wearable="skirt"
- edit_group="skirt"
- label_min="form fitting"
- label_max="loose"
+ wearable="underpants"
+ edit_group="underpants"
+ name="Pants Waist"
value_min="0"
- value_max="1">
- <param_morph />
+ value_max="1"
+ value_default=".8">
+ <param_alpha
+ tga_file="pants_waist_alpha.tga"
+ domain="0.05" />
</param>
+ </layer>
+
+ <layer
+ name="lower_underpants">
+ <texture
+ local_texture="lower_underpants" />
<param
- id="867"
- group="1"
- name="skirt_smallbutt"
- label="tight skirt"
- clothing_morph="false"
- wearable="skirt"
- edit_group="skirt"
- label_min="form fitting"
- label_max="loose"
+ id="824"
+ group="0"
+ wearable="underpants"
+ edit_group="colorpicker"
+ name="underpants_red"
value_min="0"
- value_max="1">
- <param_morph />
+ value_max="1"
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
+
+ <value
+ color="255, 0, 0, 255" />
+ </param_color>
</param>
<param
- id="848"
+ id="825"
group="0"
- name="skirt_bustle"
- label="bustle skirt"
- clothing_morph="true"
- wearable="skirt"
- edit_group_order="3"
- edit_group="skirt"
- label_min="no bustle"
- label_max="more bustle"
+ wearable="underpants"
+ edit_group="colorpicker"
+ name="underpants_green"
value_min="0"
- value_max="2"
- value_default=".2"
- camera_angle="100"
- camera_distance="1.3"
- camera_elevation="-.5">
- <param_morph />
+ value_max="1"
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
+
+ <value
+ color="0, 255, 0, 255" />
+ </param_color>
</param>
<param
- id="847"
- group="1"
- name="skirt_bowlegs"
- label="legs skirt"
- wearable="skirt"
- value_min="-1"
+ id="826"
+ group="0"
+ wearable="underpants"
+ edit_group="colorpicker"
+ name="underpants_blue"
+ value_min="0"
value_max="1"
- value_default="0">
- <param_morph />
- </param>
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
- <param
- id="852"
- group="1"
- name="skirt_bigbutt"
- label="bigbutt skirt"
- label_min="less"
- label_max="more"
- value_min="0"
- value_max="1">
- <param_morph />
+ <value
+ color="0, 0, 255, 255" />
+ </param_color>
</param>
<param
- id="849"
+ id="1054"
group="1"
- name="skirt_belly"
- label="big belly skirt"
+ wearable="underpants"
+ edit_group="driven"
+ name="Pants Length"
value_min="0"
- value_max="1">
- <param_morph />
+ value_max="1"
+ value_default=".3"
+ camera_distance="1.2"
+ camera_angle="30"
+ camera_elevation="-.3">
+ <param_alpha
+ tga_file="pants_length_alpha.tga"
+ domain="0.01" />
</param>
<param
- id="850"
+ id="1056"
group="1"
- name="skirt_saddlebags"
- value_min="-.5"
- value_max="3">
- <param_morph />
+ wearable="underpants"
+ edit_group="driven"
+ name="Pants Waist"
+ value_min="0"
+ value_max="1"
+ value_default=".8">
+ <param_alpha
+ tga_file="pants_waist_alpha.tga"
+ domain="0.05" />
</param>
+ </layer>
+
+ <layer
+ name="lower_socks bump"
+ render_pass="bump"
+ fixed_color="128,128,128,255">
+ <texture
+ local_texture="lower_socks"
+ local_texture_alpha_only="true" />
<param
- id="851"
+ id="1051"
group="1"
- name="skirt_chubby"
- label_min="less"
- label_max="more"
+ wearable="socks"
+ edit_group="driven"
+ name="Socks Length bump"
value_min="0"
value_max="1"
- value_default="0">
- <param_morph />
+ value_default="0.35">
+ <param_alpha
+ tga_file="shoe_height_alpha.tga"
+ domain="0.01" />
</param>
+ </layer>
- <param
- id="856"
- group="1"
- name="skirt_lovehandles"
- label_min="less"
- label_max="more"
- value_min="-1"
- value_max="2"
- value_default="0">
- <param_morph />
- </param>
+ <layer
+ name="lower_socks">
+ <texture
+ local_texture="lower_socks" />
-<!--
- #############
- # other morphs (not user controlled)
- #############
- -->
<param
- id="857"
- group="1"
- name="skirt_male"
- value_min="0"
- value_max="1">
- <param_morph />
- </param>
- </mesh>
-
- <mesh
- type="skirtMesh"
- lod="1"
- file_name="avatar_skirt_1.llm"
- min_pixel_width="160"
- reference="avatar_skirt.llm">
- </mesh>
-
- <mesh
- type="skirtMesh"
- lod="2"
- file_name="avatar_skirt_2.llm"
- min_pixel_width="80"
- reference="avatar_skirt.llm">
- </mesh>
-
- <mesh
- type="skirtMesh"
- lod="3"
- file_name="avatar_skirt_3.llm"
- min_pixel_width="40"
- reference="avatar_skirt.llm">
- </mesh>
-
- <mesh
- type="skirtMesh"
- lod="4"
- file_name="avatar_skirt_4.llm"
- min_pixel_width="0"
- reference="avatar_skirt.llm">
- </mesh>
-
-<!-- =========================================================== -->
- <global_color
- name="skin_color">
- <param
- id="111"
+ id="818"
group="0"
- wearable="skin"
- edit_group="skin_color"
- edit_group_order="1"
- name="Pigment"
- show_simple="true"
- label_min="Light"
- label_max="Dark"
+ wearable="socks"
+ edit_group="colorpicker"
+ name="socks_red"
value_min="0"
value_max="1"
- value_default=".5">
- <param_color>
- <value
- color="252, 215, 200, 255" />
-
- <value
- color="240, 177, 112, 255" />
-
- <value
- color="90, 40, 16, 255" />
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
- <value
- color="29, 9, 6, 255" />
- </param_color>
+ <value
+ color="255, 0, 0, 255" />
+ </param_color>
</param>
<param
- id="110"
+ id="819"
group="0"
- wearable="skin"
- edit_group="skin_color"
- edit_group_order="2"
- name="Red Skin"
- label="Ruddiness"
- label_min="Pale"
- label_max="Ruddy"
+ wearable="socks"
+ edit_group="colorpicker"
+ name="socks_green"
value_min="0"
- value_max="0.1">
- <param_color
- operation="blend">
- <value
- color="218, 41, 37, 255" />
- </param_color>
+ value_max="1"
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
+
+ <value
+ color="0, 255, 0, 255" />
+ </param_color>
</param>
<param
- id="108"
+ id="820"
group="0"
- wearable="skin"
- edit_group="skin_color"
- edit_group_order="3"
- name="Rainbow Color"
- show_simple="true"
- label_min="None"
- label_max="Wild"
+ wearable="socks"
+ edit_group="colorpicker"
+ name="socks_blue"
value_min="0"
value_max="1"
- camera_elevation=".1"
- camera_distance=".5">
- <param_color>
- <value
- color=" 0, 0, 0, 255" />
-
- <value
- color="255, 0, 255, 255" />
-
- <value
- color="255, 0, 0, 255" />
-
- <value
- color="255, 255, 0, 255" />
-
- <value
- color=" 0, 255, 0, 255" />
-
- <value
- color=" 0, 255, 255, 255" />
-
- <value
- color=" 0, 0, 255, 255" />
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
- <value
- color="255, 0, 255, 255" />
- </param_color>
+ <value
+ color="0, 0, 255, 255" />
+ </param_color>
</param>
- </global_color>
-<!-- =========================================================== -->
- <global_color
- name="hair_color">
<param
- id="114"
- group="0"
- wearable="hair"
- edit_group="hair_color"
- edit_group_order="3"
- name="Blonde Hair"
- show_simple="true"
- label_min="Black"
- label_max="Blonde"
+ id="1050"
+ group="1"
+ wearable="socks"
+ edit_group="driven"
+ name="Socks Length bump"
value_min="0"
value_max="1"
- value_default=".5"
- camera_elevation=".1"
- camera_distance=".5">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="22, 6, 6, 255" />
-
- <value
- color="29, 9, 6, 255" />
-
- <value
- color="45, 21, 11, 255" />
-
- <value
- color="78, 39, 11, 255" />
-
- <value
- color="90, 53, 16, 255" />
-
- <value
- color="136, 92, 21, 255" />
-
- <value
- color="150, 106, 33, 255" />
-
- <value
- color="198, 156, 74, 255" />
-
- <value
- color="233, 192, 103, 255" />
-
- <value
- color="238, 205, 136, 255" />
- </param_color>
+ value_default="0.35">
+ <param_alpha
+ tga_file="shoe_height_alpha.tga"
+ domain="0.01" />
</param>
+ </layer>
+
+ <layer
+ name="lower_shoes bump"
+ render_pass="bump"
+ fixed_color="128,128,128,255">
+ <texture
+ local_texture="lower_shoes"
+ local_texture_alpha_only="true" />
<param
- id="113"
- group="0"
- wearable="hair"
- edit_group="hair_color"
- edit_group_order="4"
- name="Red Hair"
- show_simple="true"
- label_min="No Red"
- label_max="Very Red"
+ id="1053"
+ group="1"
+ wearable="shoes"
+ edit_group="driven"
+ name="Shoe Height bump"
value_min="0"
value_max="1"
- camera_elevation=".1"
- camera_distance=".5">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="118, 47, 19, 255" />
- </param_color>
+ value_default="0.1">
+ <param_alpha
+ tga_file="shoe_height_alpha.tga"
+ domain="0.01" />
</param>
+ </layer>
+
+ <layer
+ name="lower_shoes">
+ <texture
+ local_texture="lower_shoes" />
<param
- id="115"
+ id="812"
group="0"
- wearable="hair"
- edit_group="hair_color"
- edit_group_order="1"
- name="White Hair"
- show_simple="true"
- label_min="No White"
- label_max="All White"
+ wearable="shoes"
+ edit_group="colorpicker"
+ name="shoes_red"
value_min="0"
value_max="1"
- camera_elevation=".1"
- camera_distance=".5">
- <param_color>
- <value
- color="0, 0, 0, 255" />
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
- <value
- color="255, 255, 255, 255" />
- </param_color>
+ <value
+ color="255, 0, 0, 255" />
+ </param_color>
</param>
<param
- id="112"
+ id="813"
group="0"
- wearable="hair"
- edit_group="hair_color"
- edit_group_order="2"
- name="Rainbow Color"
- show_simple="true"
- label_min="None"
- label_max="Wild"
+ wearable="shoes"
+ edit_group="colorpicker"
+ name="shoes_green"
value_min="0"
value_max="1"
- camera_elevation=".1"
- camera_distance=".5">
- <param_color>
- <value
- color=" 0, 0, 0, 255" />
-
- <value
- color="255, 0, 255, 255" />
-
- <value
- color="255, 0, 0, 255" />
-
- <value
- color="255, 255, 0, 255" />
-
- <value
- color=" 0, 255, 0, 255" />
-
- <value
- color=" 0, 255, 255, 255" />
-
- <value
- color=" 0, 0, 255, 255" />
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
- <value
- color="255, 0, 255, 255" />
- </param_color>
+ <value
+ color="0, 255, 0, 255" />
+ </param_color>
</param>
- </global_color>
-<!-- =========================================================== -->
- <global_color
- name="eye_color">
<param
- id="99"
+ id="817"
group="0"
- wearable="eyes"
- edit_group="eyes"
- edit_group_order="1"
- name="Eye Color"
- show_simple="true"
- label_min="Natural"
- label_max="Unnatural"
+ wearable="shoes"
+ edit_group="colorpicker"
+ name="shoes_blue"
value_min="0"
value_max="1"
- value_default="0"
- camera_elevation=".1"
- camera_distance=".3">
-<!-- default to natural brown eyes-->
- <param_color>
- <value
- color="50, 25, 5, 255" />
-
-<!-- natural dark brown eyes-->
- <value
- color="109, 55, 15, 255" />
-
-<!-- natural brown eyes-->
- <value
- color="150, 93, 49, 255" />
-
-<!-- natural light brown eyes-->
- <value
- color="152, 118, 25, 255" />
-
-<!--natural hazel eyes-->
- <value
- color="95, 179, 107, 255" />
-
-<!--natural green eyes-->
- <value
- color="87, 192, 191, 255" />
-
-<!--natural aqua eyes-->
- <value
- color="95, 172, 179, 255" />
-
-<!--natural blue eyes-->
- <value
- color="128, 128, 128, 255" />
-
-<!--natural grey eyes-->
- <value
- color="0, 0, 0, 255" />
-
-<!--black eyes-->
- <value
- color="255, 255, 0, 255" />
-
-<!--bright yellow eyes-->
- <value
- color=" 0, 255, 0, 255" />
-
-<!-- bright green eyes-->
- <value
- color=" 0, 255, 255, 255" />
-
-<!-- bright cyan eyes-->
- <value
- color=" 0, 0, 255, 255" />
-
-<!--bright blue eyes-->
- <value
- color="255, 0, 255, 255" />
-
-<!-- bright violet eyes-->
- <value
- color="255, 0, 0, 255" />
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
-<!--bright red eyes-->
- </param_color>
+ <value
+ color="0, 0, 255, 255" />
+ </param_color>
</param>
<param
- id="98"
- group="0"
- wearable="eyes"
- edit_group="eyes"
- edit_group_order="2"
- name="Eye Lightness"
- show_simple="true"
- label_min="Darker"
- label_max="Lighter"
+ id="1052"
+ group="1"
+ wearable="shoes"
+ edit_group="driven"
+ name="Shoe Height"
value_min="0"
value_max="1"
- camera_elevation=".1"
- camera_distance=".3">
- <param_color>
- <value
- color="0, 0, 0, 0" />
-
- <value
- color="255, 255, 255, 255" />
- </param_color>
+ value_default="0.1">
+ <param_alpha
+ tga_file="shoe_height_alpha.tga"
+ domain="0.01" />
</param>
- </global_color>
+ </layer>
-<!-- =========================================================== -->
- <layer_set
- body_region="hair"
- width="512"
- height="512"
- clear_alpha="false">
<layer
- name="base"
- global_color="hair_color"
- write_all_channels="true">
+ name="lower_clothes_shadow">
<texture
- local_texture="hair_grain" />
- </layer>
- </layer_set>
- <!-- =========================================================== -->
-
- <layer_set
- body_region="head"
- width="512"
- height="512"
- clear_alpha="false"
- alpha_tga_file="head_alpha.tga">
- <layer
- name="head bump base"
- fixed_color = "128,128,128,255"
- render_pass="bump">
- </layer>
-
- <layer
- name="head bump definition"
- render_pass="bump">
-
- <texture
- tga_file="bump_head_base.tga"
- file_is_mask="FALSE"/>
-
- <param
- id="873"
- group="1"
- wearable="skin"
- edit_group="driven"
- edit_group_order="12"
- name="Bump base"
- value_min="0"
- value_max="1">
- <param_alpha
- domain="0" />
- </param>
- </layer>
-
- <layer
- name="base"
- global_color="skin_color">
- <texture
- tga_file="head_skingrain.tga" />
- </layer>
-
- <layer
- name="headcolor">
- <texture
- tga_file="head_color.tga" />
- </layer>
-
- <layer
- name="shadow">
- <texture
- tga_file="head_shading_alpha.tga"
- file_is_mask="TRUE" />
-
- <param
- id="158"
- group="1"
- wearable="skin"
- name="Shading"
- value_min="0"
- value_max="1">
- <param_color>
- <value
- color="0, 0, 0, 0" />
-
- <value
- color="0, 0, 0, 128" />
- </param_color>
- </param>
- </layer>
-
- <layer
- name="highlight">
- <texture
- tga_file="head_highlights_alpha.tga"
- file_is_mask="TRUE" />
-
-
- <param
- id="159"
- group="1"
- name="Shading"
- wearable="skin"
- value_min="0"
- value_max="1">
- <param_color>
- <value
- color="255, 255, 255, 0" />
-
-
- <value
- color="255, 255, 255, 64" />
- </param_color>
- </param>
- </layer>
- <layer
- name="rosyface">
- <texture
- tga_file="rosyface_alpha.tga"
- file_is_mask="true" />
-
- <param
- id="116"
- group="0"
- wearable="skin"
- edit_group="skin_facedetail"
- edit_group_order="4"
- name="Rosy Complexion"
- label_min="Less Rosy"
- label_max="More Rosy"
- value_min="0"
- value_max="1"
- camera_distance=".3"
- camera_elevation=".07">
- <param_color>
- <value
- color="198, 71, 71, 0" />
-
- <value
- color="198, 71, 71, 255" />
- </param_color>
- </param>
- </layer>
-
- <layer
- name="lips">
- <texture
- tga_file="lips_mask.tga"
- file_is_mask="true" />
-
- <param
- id="117"
- group="0"
- wearable="skin"
- edit_group="skin_facedetail"
- edit_group_order="5"
- name="Lip Pinkness"
- label_min="Darker"
- label_max="Pinker"
- value_min="0"
- value_max="1"
- camera_distance=".25">
- <param_color>
- <value
- color="220, 115, 115, 0" />
-
- <value
- color="220, 115, 115, 128" />
- </param_color>
- </param>
- </layer>
-
- <layer
- name="wrinkles_shading"
- render_pass="bump"
- fixed_color="0,0,0,100">
- <param
- id="118"
- group="1"
- wearable="skin"
- name="Wrinkles"
- value_min="0"
- value_max="1">
- <param_alpha
- tga_file="bump_face_wrinkles.tga"
- skip_if_zero="true"
- domain="0.3" />
- </param>
- </layer>
-
-<!--<layer
- name="wrinkles_highlights"
- fixed_color="255,255,255,64">
- <param
- id="128"
- group="1"
- name="Wrinkles"
- value_min="0"
- value_max="1">
- <param_alpha
- tga_file="head_wrinkles_highlights_alpha.tga"
- skip_if_zero="true"
- domain="0.3" />
- </param>
- </layer>-->
- <layer
- name="freckles"
- fixed_color="120,47,20,128">
- <param
- id="165"
- group="0"
- wearable="skin"
- edit_group="skin_facedetail"
- edit_group_order="2"
- name="Freckles"
- label_min="Less"
- label_max="More"
- value_min="0"
- value_max="1"
- camera_distance=".3"
- camera_elevation=".07">
- <param_alpha
- tga_file="freckles_alpha.tga"
- skip_if_zero="true"
- domain="0.5" />
- </param>
- </layer>
- <layer
- name="eyebrowsbump"
- render_pass="bump">
- <texture
- tga_file="head_hair.tga"
- file_is_mask="false" />
-
- <param
- id="1000"
- group="1"
- wearable="hair"
- edit_group="driven"
- name="Eyebrow Size Bump"
- value_min="0"
- value_max="1">
- <param_alpha
- tga_file="eyebrows_alpha.tga"
- domain="0.1" />
- </param>
-
- <param
- id="1002"
- group="1"
- wearable="hair"
- edit_group="driven"
- name="Eyebrow Density Bump"
- value_min="0"
- value_max="1">
- <param_color>
- <value
- color="255,255,255,0" />
-
- <value
- color="255,255,255,255" />
- </param_color>
- </param>
- </layer>
-
- <layer
- name="eyebrows"
- global_color="hair_color">
- <texture
- tga_file="head_hair.tga"
- file_is_mask="false" />
-
- <param
- id="1001"
- group="1"
- wearable="hair"
- edit_group="hair_eyebrows"
- name="Eyebrow Size"
- show_simple="true"
- value_min="0"
- value_max="1"
- value_default="0.5">
- <param_alpha
- tga_file="eyebrows_alpha.tga"
- domain="0.1" />
- </param>
-
- <param
- id="1003"
- group="1"
- edit_group="driven"
- name="Eyebrow Density"
- value_min="0"
- value_max="1">
- <param_color
- operation="multiply">
- <value
- color="255,255,255,0" />
-
- <value
- color="255,255,255,255" />
- </param_color>
- </param>
- </layer>
-
- <layer
- name="lipstick">
- <param
- id="700"
- group="0"
- wearable="skin"
- edit_group="skin_makeup"
- edit_group_order="2"
- name="Lipstick Color"
- label_min="Pink"
- label_max="Black"
- value_min="0"
- value_max="1"
- value_default=".25"
- camera_distance=".25">
- <param_color>
- <value
- color="245,161,177,200" />
-
- <value
- color="216,37,67,200" />
-
- <value
- color="178,48,76,200" />
-
- <value
- color="68,0,11,200" />
-
- <value
- color="252,207,184,200" />
-
- <value
- color="241,136,106,200" />
-
- <value
- color="208,110,85,200" />
-
- <value
- color="106,28,18,200" />
-
- <value
- color="58,26,49,200" />
-
- <value
- color="14,14,14,200" />
- </param_color>
- </param>
-
- <param
- id="701"
- group="0"
- wearable="skin"
- edit_group="skin_makeup"
- edit_group_order="1"
- name="Lipstick"
- label_min="No Lipstick"
- label_max="More Lipstick"
- value_min="0"
- value_max=".9"
- value_default="0.0"
- camera_distance=".25">
- <param_alpha
- tga_file="lipstick_alpha.tga"
- skip_if_zero="true"
- domain="0.05" />
- </param>
- </layer>
-
- <layer
- name="lipgloss"
- fixed_color="255,255,255,190">
- <param
- id="702"
- name="Lipgloss"
- label_min="No Lipgloss"
- label_max="Glossy"
- wearable="skin"
- edit_group="skin_makeup"
- edit_group_order="3"
- group="0"
- value_min="0"
- value_max="1"
- camera_distance=".25">
- <param_alpha
- tga_file="lipgloss_alpha.tga"
- skip_if_zero="true"
- domain="0.2" />
- </param>
- </layer>
-
- <layer
- name="blush">
- <param
- id="704"
- group="0"
- wearable="skin"
- edit_group="skin_makeup"
- edit_group_order="4"
- name="Blush"
- label_min="No Blush"
- label_max="More Blush"
- value_min="0"
- value_max=".9"
- value_default="0"
- camera_distance=".3"
- camera_elevation=".07"
- camera_angle="20">
- <param_alpha
- tga_file="blush_alpha.tga"
- skip_if_zero="true"
- domain="0.3" />
- </param>
-
- <param
- id="705"
- group="0"
- wearable="skin"
- edit_group="skin_makeup"
- edit_group_order="5"
- name="Blush Color"
- label_min="Pink"
- label_max="Orange"
- value_min="0"
- value_max="1"
- value_default=".5"
- camera_distance=".3"
- camera_elevation=".07"
- camera_angle="20">
- <param_color>
- <value
- color="253,162,193,200" />
-
- <value
- color="247,131,152,200" />
-
- <value
- color="213,122,140,200" />
-
- <value
- color="253,152,144,200" />
-
- <value
- color="236,138,103,200" />
-
- <value
- color="195,128,122,200" />
-
- <value
- color="148,103,100,200" />
-
- <value
- color="168,95,62,200" />
- </param_color>
- </param>
-
- <param
- id="711"
- group="0"
- wearable="skin"
- edit_group="skin_makeup"
- edit_group_order="6"
- name="Blush Opacity"
- label_min="Clear"
- label_max="Opaque"
- value_min="0"
- value_max="1"
- value_default=".5"
- camera_distance=".3"
- camera_elevation=".07"
- camera_angle="20">
- <param_color
- operation="multiply">
- <value
- color="255,255,255,0" />
-
- <value
- color="255,255,255,255" />
- </param_color>
- </param>
- </layer>
-
- <layer
- name="Outer Eye Shadow">
- <param
- id="708"
- group="0"
- wearable="skin"
- edit_group="skin_makeup"
- edit_group_order="11"
- name="Out Shdw Color"
- label_min="Light"
- label_max="Dark"
- value_min="0"
- value_max="1"
- camera_distance=".3"
- camera_elevation=".14">
- <param_color>
- <value
- color="252,247,246,255" />
-
- <value
- color="255,206,206,255" />
-
- <value
- color="233,135,149,255" />
-
- <value
- color="220,168,192,255" />
-
- <value
- color="228,203,232,255" />
-
- <value
- color="255,234,195,255" />
-
- <value
- color="230,157,101,255" />
-
- <value
- color="255,147,86,255" />
-
- <value
- color="228,110,89,255" />
-
- <value
- color="228,150,120,255" />
-
- <value
- color="223,227,213,255" />
-
- <value
- color="96,116,87,255" />
-
- <value
- color="88,143,107,255" />
-
- <value
- color="194,231,223,255" />
-
- <value
- color="207,227,234,255" />
-
- <value
- color="41,171,212,255" />
-
- <value
- color="180,137,130,255" />
-
- <value
- color="173,125,105,255" />
-
- <value
- color="144,95,98,255" />
-
- <value
- color="115,70,77,255" />
-
- <value
- color="155,78,47,255" />
-
- <value
- color="239,239,239,255" />
-
- <value
- color="194,194,194,255" />
-
- <value
- color="120,120,120,255" />
-
- <value
- color="10,10,10,255" />
- </param_color>
- </param>
-
- <param
- id="706"
- group="0"
- wearable="skin"
- edit_group="skin_makeup"
- edit_group_order="12"
- name="Out Shdw Opacity"
- label_min="Clear"
- label_max="Opaque"
- value_min=".2"
- value_max="1"
- value_default=".6"
- camera_distance=".3"
- camera_elevation=".14">
- <param_color
- operation="multiply">
- <value
- color="255,255,255,0" />
-
- <value
- color="255,255,255,255" />
- </param_color>
- </param>
-
- <param
- id="707"
- group="0"
- wearable="skin"
- edit_group="skin_makeup"
- edit_group_order="10"
- name="Outer Shadow"
- label_min="No Eyeshadow"
- label_max="More Eyeshadow"
- value_min="0"
- value_max=".7"
- camera_distance=".3"
- camera_elevation=".14">
- <param_alpha
- tga_file="eyeshadow_outer_alpha.tga"
- skip_if_zero="true"
- domain="0.05" />
- </param>
- </layer>
-
- <layer
- name="Inner Eye Shadow">
- <param
- id="712"
- group="0"
- wearable="skin"
- edit_group="skin_makeup"
- edit_group_order="8"
- name="In Shdw Color"
- label_min="Light"
- label_max="Dark"
- value_min="0"
- value_max="1"
- camera_distance=".3"
- camera_elevation=".14">
- <param_color>
- <value
- color="252,247,246,255" />
-
- <value
- color="255,206,206,255" />
-
- <value
- color="233,135,149,255" />
-
- <value
- color="220,168,192,255" />
-
- <value
- color="228,203,232,255" />
-
- <value
- color="255,234,195,255" />
-
- <value
- color="230,157,101,255" />
-
- <value
- color="255,147,86,255" />
-
- <value
- color="228,110,89,255" />
-
- <value
- color="228,150,120,255" />
-
- <value
- color="223,227,213,255" />
-
- <value
- color="96,116,87,255" />
-
- <value
- color="88,143,107,255" />
-
- <value
- color="194,231,223,255" />
-
- <value
- color="207,227,234,255" />
-
- <value
- color="41,171,212,255" />
-
- <value
- color="180,137,130,255" />
-
- <value
- color="173,125,105,255" />
-
- <value
- color="144,95,98,255" />
-
- <value
- color="115,70,77,255" />
-
- <value
- color="155,78,47,255" />
-
- <value
- color="239,239,239,255" />
-
- <value
- color="194,194,194,255" />
-
- <value
- color="120,120,120,255" />
-
- <value
- color="10,10,10,255" />
- </param_color>
- </param>
-
- <param
- id="713"
- group="0"
- wearable="skin"
- edit_group="skin_makeup"
- edit_group_order="9"
- name="In Shdw Opacity"
- label_min="Clear"
- label_max="Opaque"
- value_min=".2"
- value_max="1"
- value_default=".7"
- camera_distance=".3"
- camera_elevation=".14">
- <param_color
- operation="multiply">
- <value
- color="255,255,255,0" />
-
- <value
- color="255,255,255,255" />
- </param_color>
- </param>
-
- <param
- id="709"
- group="0"
- wearable="skin"
- edit_group="skin_makeup"
- edit_group_order="7"
- name="Inner Shadow"
- label_min="No Eyeshadow"
- label_max="More Eyeshadow"
- value_min="0"
- value_max="1"
- value_default="0"
- camera_distance=".3"
- camera_elevation=".14">
- <param_alpha
- tga_file="eyeshadow_inner_alpha.tga"
- skip_if_zero="true"
- domain="0.2" />
- </param>
- </layer>
-
- <layer
- name="eyeliner"
- fixed_color="0,0,0,200">
- <param
- id="703"
- group="0"
- wearable="skin"
- edit_group="skin_makeup"
- edit_group_order="13"
- name="Eyeliner"
- label_min="No Eyeliner"
- label_max="Full Eyeliner"
- value_min="0"
- value_max="1"
- value_default="0.0"
- camera_distance=".3"
- camera_elevation=".14">
- <param_alpha
- tga_file="eyeliner_alpha.tga"
- skip_if_zero="true"
- domain="0.1" />
- </param>
-
- <param
- id="714"
- group="0"
- wearable="skin"
- edit_group="skin_makeup"
- edit_group_order="14"
- name="Eyeliner Color"
- label_min="Dark Green"
- label_max="Black"
- value_min="0"
- value_max="1"
- camera_distance=".3"
- camera_elevation=".14">
- <param_color>
- <value
- color="24,98,40,250" />
-
-<!-- dark green -->
- <value
- color="9,100,127,250" />
-
-<!-- lt.aqua blue -->
- <value
- color="61,93,134,250" />
-
-<!-- aqua -->
- <value
- color="70,29,27,250" />
-
-<!-- dark brown -->
- <value
- color="115,75,65,250" />
-
-<!-- lt. brown blue -->
- <value
- color="100,100,100,250" />
-
-<!-- grey -->
- <value
- color="91,80,74,250" />
-
-<!-- grey/brown -->
- <value
- color="112,42,76,250" />
-
-<!-- plum -->
- <value
- color="14,14,14,250" />
-
-<!-- black -->
- </param_color>
- </param>
- </layer>
-
- <layer
- name="facialhair bump"
- render_pass="bump">
- <texture
- tga_file="head_hair.tga"
- file_is_mask="false" />
-
- <param
- id="1004"
- sex="male"
- group="1"
- wearable="hair"
- edit_group="driven"
- name="Sideburns bump"
- value_min="0"
- value_max="1">
- <param_alpha
- tga_file="facehair_sideburns_alpha.tga"
- skip_if_zero="true"
- domain="0.05" />
- </param>
-
- <param
- id="1006"
- sex="male"
- group="1"
- wearable="hair"
- edit_group="driven"
- name="Moustache bump"
- value_min="0"
- value_max="1">
- <param_alpha
- tga_file="facehair_moustache_alpha.tga"
- skip_if_zero="true"
- domain="0.05" />
- </param>
-
- <param
- id="1008"
- sex="male"
- group="1"
- wearable="hair"
- edit_group="driven"
- name="Soulpatch bump"
- value_min="0"
- value_max="1">
- <param_alpha
- tga_file="facehair_soulpatch_alpha.tga"
- skip_if_zero="true"
- domain="0.1" />
- </param>
-
- <param
- id="1010"
- sex="male"
- group="1"
- edit_group="driven"
- wearable="hair"
- name="Chin Curtains bump"
- value_min="0"
- value_max="1">
- <param_alpha
- tga_file="facehair_chincurtains_alpha.tga"
- skip_if_zero="true"
- domain="0.03" />
- </param>
-
- <param
- id="1012"
- group="1"
- sex="male"
- wearable="hair"
- edit_group="driven"
- name="5 O'Clock Shadow bump"
- value_min="0"
- value_max="1">
- <param_color>
- <value
- color="255,255,255,255" />
-
- <value
- color="255,255,255,0" />
- </param_color>
- </param>
- </layer>
-
- <layer
- name="facialhair"
- global_color="hair_color">
- <morph_mask
- morph_name="Displace_Hair_Facial" />
-
- <texture
- tga_file="head_hair.tga"
- file_is_mask="false" />
-
- <param
- id="1005"
- sex="male"
- group="1"
- edit_group="driven"
- name="Sideburns"
- value_min="0"
- value_max="1">
- <param_alpha
- tga_file="facehair_sideburns_alpha.tga"
- skip_if_zero="true"
- domain="0.05" />
- </param>
-
- <param
- id="1007"
- sex="male"
- group="1"
- edit_group="driven"
- name="Moustache"
- value_min="0"
- value_max="1">
- <param_alpha
- tga_file="facehair_moustache_alpha.tga"
- skip_if_zero="true"
- domain="0.05" />
- </param>
-
- <param
- id="1009"
- sex="male"
- group="1"
- edit_group="driven"
- name="Soulpatch"
- value_min="0"
- value_max="1">
- <param_alpha
- tga_file="facehair_soulpatch_alpha.tga"
- skip_if_zero="true"
- domain="0.1" />
- </param>
-
- <param
- id="1011"
- sex="male"
- group="1"
- edit_group="driven"
- name="Chin Curtains"
- value_min="0"
- value_max="1">
- <param_alpha
- tga_file="facehair_chincurtains_alpha.tga"
- skip_if_zero="true"
- domain="0.03" />
- </param>
-
- <param
- id="751"
- group="1"
- wearable="hair"
- sex="male"
- edit_group="hair_facial"
- name="5 O'Clock Shadow"
- label_min="Dense hair"
- label_max="Shadow hair"
- value_min="0"
- value_max="1"
- value_default="0.7"
- camera_elevation=".1"
- camera_distance=".3">
- <param_color
- operation="multiply">
- <value
- color="255,255,255,255" />
-
- <value
- color="255,255,255,30" />
- </param_color>
- </param>
- </layer>
-
- <layer
- name="head_bodypaint">
- <texture
- local_texture="head_bodypaint" />
- </layer>
- </layer_set>
-
-<!-- =========================================================== -->
- <layer_set
- body_region="upper_body"
- width="512"
- height="512">
- <layer
- name="base_upperbody bump"
- render_pass="bump"
- fixed_color="128,128,128,255">
- </layer>
- <layer
- name="upperbody bump definition"
- render_pass="bump">
- <texture
- tga_file="bump_upperbody_base.tga"
- file_is_mask="FALSE"/>
-
- <param
- id="874"
- group="1"
- wearable="skin"
- edit_group="driven"
- edit_group_order="20"
- name="Bump upperdef"
- value_min="0"
- value_max="1">
- <param_alpha
- domain="0" />
- </param>
- </layer>
-
- <layer
- name="base"
- global_color="skin_color">
- <texture
- tga_file="body_skingrain.tga" />
- </layer>
-
- <layer
- name="nipples">
- <texture
- tga_file="upperbody_color.tga" />
- </layer>
-
- <layer
- name="shadow">
- <texture
- tga_file="upperbody_shading_alpha.tga"
- file_is_mask="TRUE" />
-
- <param
- id="125"
- group="1"
- name="Shading"
- wearable="skin"
- value_min="0"
- value_max="1">
- <param_color>
- <value
- color="0, 0, 0, 0" />
-
- <value
- color="0, 0, 0, 128" />
- </param_color>
- </param>
- </layer>
-
- <layer
- name="highlight">
- <texture
- tga_file="upperbody_highlights_alpha.tga"
- file_is_mask="TRUE" />
-
- <param
- id="126"
- group="1"
- wearable="skin"
- name="Shading"
- value_min="0"
- value_max="1">
- <param_color>
- <value
- color="255, 255, 255, 0" />
-
- <value
- color="255, 255, 255, 64" />
- </param_color>
- </param>
- </layer>
-
- <layer
- name="upper_bodypaint">
- <texture
- local_texture="upper_bodypaint" />
- </layer>
-
- <layer
- name="freckles upper"
- fixed_color="120,47,20,128">
- <param
- id="776"
- group="1"
- name="freckles upper"
- wearable="skin"
- value_min="0"
- value_max="1">
- <param_alpha
- tga_file="upperbodyfreckles_alpha.tga"
- skip_if_zero="true"
- domain="0.6" />
- </param>
- </layer>
-
- <layer
- name="upper_undershirt bump"
- render_pass="bump"
- fixed_color="128,128,128,255">
- <texture
- local_texture="upper_undershirt"
- local_texture_alpha_only="true" />
-
- <param
- id="1043"
- group="1"
- wearable="undershirt"
- edit_group="driven"
- name="Sleeve Length bump"
- value_min=".01"
- value_max="1"
- value_default=".4">
- <param_alpha
- tga_file="shirt_sleeve_alpha.tga"
- multiply_blend="false"
- domain="0.01" />
- </param>
-
- <param
- id="1045"
- group="1"
- wearable="undershirt"
- edit_group="undershirt"
- edit_group_order="2"
- name="Bottom bump"
- value_min="0"
- value_max="1"
- value_default=".8">
- <param_alpha
- tga_file="shirt_bottom_alpha.tga"
- multiply_blend="true"
- domain="0.05" />
- </param>
-
- <param
- id="1047"
- group="1"
- wearable="undershirt"
- edit_group="driven"
- name="Collar Front bump"
- value_min="0"
- value_max="1"
- value_default=".8">
- <param_alpha
- tga_file="shirt_collar_alpha.tga"
- multiply_blend="true"
- domain="0.05" />
- </param>
-
- <param
- id="1049"
- group="1"
- wearable="undershirt"
- edit_group="driven"
- name="Collar Back bump"
- value_min="0"
- value_max="1"
- value_default=".8">
- <param_alpha
- tga_file="shirt_collar_back_alpha.tga"
- multiply_blend="true"
- domain="0.05" />
- </param>
- </layer>
-
- <layer
- name="upper_undershirt">
- <texture
- local_texture="upper_undershirt" />
-
- <param
- id="821"
- group="0"
- wearable="undershirt"
- edit_group="colorpicker"
- name="undershirt_red"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="255, 0, 0, 255" />
- </param_color>
- </param>
-
- <param
- id="822"
- group="0"
- wearable="undershirt"
- edit_group="colorpicker"
- name="undershirt_green"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="0, 255, 0, 255" />
- </param_color>
- </param>
-
- <param
- id="823"
- group="0"
- wearable="undershirt"
- edit_group="colorpicker"
- name="undershirt_blue"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="0, 0, 255, 255" />
- </param_color>
- </param>
-
- <param
- id="1042"
- group="1"
- wearable="undershirt"
- edit_group="driven"
- name="Sleeve Length"
- value_min=".01"
- value_max="1"
- value_default=".4">
- <param_alpha
- tga_file="shirt_sleeve_alpha.tga"
- multiply_blend="false"
- domain="0.01" />
- </param>
-
- <param
- id="1044"
- group="1"
- wearable="undershirt"
- edit_group="driven"
- name="Bottom"
- value_min="0"
- value_max="1"
- value_default=".8">
- <param_alpha
- tga_file="shirt_bottom_alpha.tga"
- multiply_blend="true"
- domain="0.05" />
- </param>
-
- <param
- id="1046"
- group="1"
- wearable="undershirt"
- edit_group="driven"
- name="Collar Front"
- value_min="0"
- value_max="1"
- value_default=".8">
- <param_alpha
- tga_file="shirt_collar_alpha.tga"
- multiply_blend="true"
- domain="0.05" />
- </param>
-
- <param
- id="1048"
- group="1"
- wearable="undershirt"
- edit_group="driven"
- name="Collar Back"
- label_min="Low"
- label_max="High"
- value_min="0"
- value_max="1"
- value_default=".8">
- <param_alpha
- tga_file="shirt_collar_back_alpha.tga"
- multiply_blend="true"
- domain="0.05" />
- </param>
- </layer>
-
- <layer
- name="Nail Polish">
- <param
- id="710"
- group="0"
- wearable="skin"
- edit_group="skin_makeup"
- edit_group_order="15"
- name="Nail Polish"
- label_min="No Polish"
- label_max="Painted Nails"
- value_min="0"
- value_max="1"
- value_default="0.0"
- camera_distance="1.6"
- camera_elevation="-.4"
- camera_angle="70">
- <param_alpha
- tga_file="nailpolish_alpha.tga"
- skip_if_zero="true"
- domain="0.1" />
- </param>
-
- <param
- id="715"
- group="0"
- wearable="skin"
- edit_group="skin_makeup"
- edit_group_order="16"
- name="Nail Polish Color"
- label_min="Pink"
- label_max="Black"
- value_min="0"
- value_max="1"
- camera_distance="1.6"
- camera_elevation="-.4"
- camera_angle="70">
- <param_color>
- <value
- color="255,187,200,255" />
-
- <value
- color="194,102,127,255" />
-
- <value
- color="227,34,99,255" />
-
- <value
- color="168,41,60,255" />
-
- <value
- color="97,28,59,255" />
-
- <value
- color="234,115,93,255" />
-
- <value
- color="142,58,47,255" />
-
- <value
- color="114,30,46,255" />
-
- <value
- color="14,14,14,255" />
- </param_color>
- </param>
- </layer>
-
- <layer
- name="upper_gloves bump"
- render_pass="bump"
- fixed_color="128,128,128,255">
- <texture
- local_texture="upper_gloves"
- local_texture_alpha_only="true" />
-
- <param
- id="1059"
- group="1"
- wearable="gloves"
- edit_group="driven"
- name="Glove Length bump"
- value_min=".01"
- value_max="1"
- value_default=".8">
- <param_alpha
- tga_file="glove_length_alpha.tga"
- domain="0.01" />
- </param>
-
- <param
- id="1061"
- group="1"
- wearable="gloves"
- edit_group="driven"
- name="Glove Fingers bump"
- value_min=".01"
- value_max="1"
- value_default="1">
- <param_alpha
- tga_file="gloves_fingers_alpha.tga"
- multiply_blend="true"
- domain="0.01" />
- </param>
- </layer>
-
- <layer
- name="upper_gloves">
- <texture
- local_texture="upper_gloves" />
-
- <param
- id="827"
- group="0"
- wearable="gloves"
- edit_group="colorpicker"
- name="gloves_red"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="255, 0, 0, 255" />
- </param_color>
- </param>
-
- <param
- id="829"
- group="0"
- wearable="gloves"
- edit_group="colorpicker"
- name="gloves_green"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="0, 255, 0, 255" />
- </param_color>
- </param>
-
- <param
- id="830"
- group="0"
- wearable="gloves"
- edit_group="colorpicker"
- name="gloves_blue"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="0, 0, 255, 255" />
- </param_color>
- </param>
-
- <param
- id="1058"
- group="1"
- wearable="gloves"
- edit_group="driven"
- name="Glove Length"
- value_min=".01"
- value_max="1"
- value_default=".8">
- <param_alpha
- tga_file="glove_length_alpha.tga"
- domain="0.01" />
- </param>
-
- <param
- id="1060"
- group="1"
- wearable="gloves"
- edit_group="driven"
- name="Glove Fingers"
- value_min=".01"
- value_max="1"
- value_default="1">
- <param_alpha
- tga_file="gloves_fingers_alpha.tga"
- multiply_blend="true"
- domain="0.01" />
- </param>
- </layer>
-
- <layer
- name="upper_clothes_shadow">
- <texture
- local_texture="upper_shirt" />
-
- <param
- id="899"
- group="1"
- edit_group="driven"
- wearable="shirt"
- name="Upper Clothes Shading"
- value_min="0"
- value_max="1"
- value_default="0">
- <param_color>
- <value
- color="0, 0, 0, 0" />
-
- <value
- color="0, 0, 0, 80" />
- </param_color>
- </param>
-
- <param
- id="900"
- group="1"
- wearable="shirt"
- edit_group="driven"
- name="Sleeve Length Shadow"
- value_min="0.02"
- value_max=".87"
- value_default="0.02">
- <param_alpha
- multiply_blend="false"
- tga_file="shirt_sleeve_alpha.tga"
- skip_if_zero="true"
- domain="0.03" />
- </param>
-
- <param
- id="901"
- group="1"
- wearable="shirt"
- edit_group="driven"
- name="Shirt Shadow Bottom"
- value_min="0.02"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="shirt_bottom_alpha.tga"
- skip_if_zero="true"
- domain="0.05" />
- </param>
-
- <param
- id="902"
- group="1"
- wearable="shirt"
- edit_group="driven"
- name="Collar Front Shadow Height"
- value_min="0.02"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="shirt_collar_alpha.tga"
- skip_if_zero="true"
- domain="0.02" />
- </param>
-
- <param
- id="903"
- group="1"
- wearable="shirt"
- edit_group="driven"
- name="Collar Back Shadow Height"
- value_min="0.02"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="shirt_collar_back_alpha.tga"
- skip_if_zero="true"
- domain="0.02" />
- </param>
- </layer>
-
- <layer
- name="upper_shirt base bump"
- render_pass="bump"
- fixed_color="128,128,128,255">
- <texture
- local_texture="upper_shirt"
- local_texture_alpha_only="true" />
-
- <param
- id="1029"
- group="1"
- wearable="shirt"
- edit_group="driven"
- name="Sleeve Length Cloth"
- value_min="0"
- value_max="0.85">
- <param_alpha
- multiply_blend="false"
- tga_file="shirt_sleeve_alpha.tga"
- domain="0.01" />
- </param>
-
- <param
- id="1030"
- group="1"
- wearable="shirt"
- edit_group="driven"
- name="Shirt Bottom Cloth"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="shirt_bottom_alpha.tga"
- domain="0.05" />
- </param>
-
- <param
- id="1031"
- group="1"
- wearable="shirt"
- edit_group="driven"
- name="Collar Front Height Cloth"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="shirt_collar_alpha.tga"
- domain="0.05" />
- </param>
-
- <param
- id="1032"
- group="1"
- wearable="shirt"
- edit_group="driven"
- name="Collar Back Height Cloth"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="shirt_collar_back_alpha.tga"
- domain="0.05" />
- </param>
- </layer>
-
- <layer
- name="upper_clothes bump"
- render_pass="bump">
- <texture
- tga_file="bump_shirt_wrinkles.tga" />
-
- <texture
- local_texture="upper_shirt"
- local_texture_alpha_only="true" />
-
- <param
- id="868"
- group="0"
- wearable="shirt"
- edit_group="shirt"
- edit_group_order="8"
- name="Shirt Wrinkles"
- value_min="0"
- value_max="1"
- value_default="0">
- <param_color>
- <value
- color="255, 255, 255, 0" />
-
- <value
- color="255, 255, 255, 255" />
- </param_color>
- </param>
-
- <param
- id="1013"
- group="1"
- wearable="shirt"
- edit_group="driven"
- name="Sleeve Length Cloth"
- value_min="0"
- value_max="0.85">
- <param_alpha
- multiply_blend="false"
- tga_file="shirt_sleeve_alpha.tga"
- domain="0.01" />
- </param>
-
- <param
- id="1014"
- group="1"
- wearable="shirt"
- edit_group="driven"
- name="Shirt Bottom Cloth"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="shirt_bottom_alpha.tga"
- domain="0.05" />
- </param>
-
- <param
- id="1015"
- group="1"
- wearable="shirt"
- edit_group="driven"
- name="Collar Front Height Cloth"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="shirt_collar_alpha.tga"
- domain="0.05" />
- </param>
-
- <param
- id="1016"
- group="1"
- wearable="shirt"
- edit_group="driven"
- name="Collar Back Height Cloth"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="shirt_collar_back_alpha.tga"
- domain="0.05" />
- </param>
- </layer>
-
- <layer
- name="upper_clothes">
- <texture
- local_texture="upper_shirt" />
-
- <morph_mask
- morph_name="Displace_Loose_Upperbody" />
-
- <morph_mask
- morph_name="Shirtsleeve_flair" />
-
- <param
- id="803"
- group="0"
- wearable="shirt"
- edit_group="colorpicker"
- name="shirt_red"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="255, 0, 0, 255" />
- </param_color>
- </param>
-
- <param
- id="804"
- group="0"
- wearable="shirt"
- edit_group="colorpicker"
- name="shirt_green"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="0, 255, 0, 255" />
- </param_color>
- </param>
-
- <param
- id="805"
- group="0"
- wearable="shirt"
- edit_group="colorpicker"
- name="shirt_blue"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="0, 0, 255, 255" />
- </param_color>
- </param>
-
- <param
- id="600"
- group="1"
- wearable="shirt"
- edit_group="driven"
- name="Sleeve Length Cloth"
- value_min="0"
- value_max="0.85"
- value_default=".7">
- <param_alpha
- multiply_blend="false"
- tga_file="shirt_sleeve_alpha.tga"
- domain="0.01" />
- </param>
-
- <param
- id="601"
- group="1"
- wearable="shirt"
- edit_group="driven"
- name="Shirt Bottom Cloth"
- value_min="0"
- value_max="1"
- value_default=".8">
- <param_alpha
- multiply_blend="true"
- tga_file="shirt_bottom_alpha.tga"
- domain="0.05" />
- </param>
-
- <param
- id="602"
- group="1"
- wearable="shirt"
- edit_group="driven"
- name="Collar Front Height Cloth"
- value_min="0"
- value_max="1"
- value_default=".8">
- <param_alpha
- multiply_blend="true"
- tga_file="shirt_collar_alpha.tga"
- domain="0.05" />
- </param>
-
- <param
- id="778"
- group="1"
- wearable="shirt"
- edit_group="driven"
- name="Collar Back Height Cloth"
- value_min="0"
- value_max="1"
- value_default=".8">
- <param_alpha
- multiply_blend="true"
- tga_file="shirt_collar_back_alpha.tga"
- domain="0.05" />
- </param>
- </layer>
-
- <layer
- name="upper_jacket base bump"
- render_pass="bump"
- fixed_color="128,128,128,255">
- <texture
- local_texture="upper_jacket"
- local_texture_alpha_only="true" />
-
- <param
- id="1039"
- group="1"
- wearable="jacket"
- edit_group="driven"
- edit_group_order="1"
- name="Jacket Sleeve Length bump"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="false"
- tga_file="shirt_sleeve_alpha.tga"
- domain="0.01" />
- </param>
-
- <param
- id="1040"
- group="1"
- wearable="jacket"
- edit_group="driven"
- name="Jacket Collar Front bump"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="shirt_collar_alpha.tga"
- domain="0.05" />
- </param>
-
- <param
- id="1041"
- group="1"
- wearable="jacket"
- edit_group="driven"
- edit_group_order="3.5"
- name="Jacket Collar Back bump"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="shirt_collar_back_alpha.tga"
- domain="0.05" />
- </param>
-
- <param
- id="1037"
- group="1"
- wearable="jacket"
- edit_group="driven"
- name="jacket bottom length upper bump"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="jacket_length_upper_alpha.tga"
- domain="0.01" />
- </param>
-
- <param
- id="1038"
- group="1"
- wearable="jacket"
- edit_group="driven"
- name="jacket open upper bump"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="jacket_open_upper_alpha.tga"
- domain="0.01" />
- </param>
- </layer>
-
- <layer
- name="upper_jacket bump"
- render_pass="bump">
- <texture
- tga_file="bump_shirt_wrinkles.tga" />
-
- <texture
- local_texture="upper_jacket"
- local_texture_alpha_only="true" />
-
- <param
- id="875"
- group="1"
- wearable="jacket"
- name="jacket upper Wrinkles"
- value_min="0"
- value_max="1"
- value_default="0">
- <param_color>
- <value
- color="255, 255, 255, 0" />
-
- <value
- color="255, 255, 255, 255" />
- </param_color>
- </param>
-
- <param
- id="1019"
- group="1"
- wearable="jacket"
- edit_group="driven"
- edit_group_order="1"
- name="Jacket Sleeve Length bump"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="false"
- tga_file="shirt_sleeve_alpha.tga"
- domain="0.01" />
- </param>
-
- <param
- id="1021"
- group="1"
- wearable="jacket"
- edit_group="driven"
- name="Jacket Collar Front bump"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="shirt_collar_alpha.tga"
- domain="0.05" />
- </param>
-
- <param
- id="1023"
- group="1"
- wearable="jacket"
- edit_group="driven"
- edit_group_order="3.5"
- name="Jacket Collar Back bump"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="shirt_collar_back_alpha.tga"
- domain="0.05" />
- </param>
-
- <param
- id="1025"
- group="1"
- wearable="jacket"
- edit_group="driven"
- name="jacket bottom length upper bump"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="jacket_length_upper_alpha.tga"
- domain="0.01" />
- </param>
-
- <param
- id="1026"
- group="1"
- wearable="jacket"
- edit_group="driven"
- name="jacket open upper bump"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="jacket_open_upper_alpha.tga"
- domain="0.01" />
- </param>
- </layer>
-
- <layer
- name="upper_jacket">
- <texture
- local_texture="upper_jacket" />
-
- <param
- id="831"
- group="1"
- edit_group="colorpicker_driven"
- wearable="jacket"
- name="upper_jacket_red"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="255, 0, 0, 255" />
- </param_color>
- </param>
-
- <param
- id="832"
- group="1"
- edit_group="colorpicker_driven"
- wearable="jacket"
- name="upper_jacket_green"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="0, 255, 0, 255" />
- </param_color>
- </param>
-
- <param
- id="833"
- group="1"
- edit_group="colorpicker_driven"
- wearable="jacket"
- name="upper_jacket_blue"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="0, 0, 255, 255" />
- </param_color>
- </param>
-
- <param
- id="1020"
- group="1"
- edit_group="driven"
- name="jacket Sleeve Length"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="false"
- tga_file="shirt_sleeve_alpha.tga"
- domain="0.01" />
- </param>
-
- <param
- id="1022"
- group="1"
- edit_group="driven"
- name="jacket Collar Front"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="shirt_collar_alpha.tga"
- domain="0.05" />
- </param>
-
- <param
- id="1024"
- group="1"
- edit_group="driven"
- edit_group_order="3.5"
- name="jacket Collar Back"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="shirt_collar_back_alpha.tga"
- domain="0.05" />
- </param>
-
- <param
- id="620"
- group="1"
- wearable="jacket"
- edit_group="jacket"
- name="bottom length upper"
- label_min="hi cut"
- label_max="low cut"
- value_min="0"
- value_max="1"
- value_default=".8"
- camera_distance="1.2"
- camera_angle="30"
- camera_elevation=".2">
- <param_alpha
- multiply_blend="true"
- tga_file="jacket_length_upper_alpha.tga"
- domain="0.01" />
- </param>
-
- <param
- id="622"
- group="1"
- wearable="jacket"
- edit_group="jacket"
- name="open upper"
- label_min="closed"
- label_max="open"
- value_min="0"
- value_max="1"
- value_default=".8"
- camera_distance="1.2"
- camera_angle="30"
- camera_elevation=".2">
- <param_alpha
- multiply_blend="true"
- tga_file="jacket_open_upper_alpha.tga"
- domain="0.01" />
- </param>
- </layer>
- </layer_set>
-
-<!-- =========================================================== -->
- <layer_set
- body_region="lower_body"
- width="512"
- height="512">
- <layer
- name="lower body bump base"
- fixed_color = "128,128,128,255"
- render_pass="bump">
- </layer>
- <layer
- name="base_lowerbody bump"
- render_pass="bump">
- <texture
- tga_file="bump_lowerbody_base.tga"
- file_is_mask="FALSE" />
-
- <param
- id="878"
- group="1"
- wearable="skin"
- edit_group="driven"
- edit_group_order="20"
- name="Bump upperdef"
- value_min="0"
- value_max="1">
- <param_alpha
- domain="0" />
- </param>
- </layer>
-
- <layer
- name="base"
- global_color="skin_color">
- <texture
- tga_file="body_skingrain.tga" />
- </layer>
-
- <layer
- name="shadow">
- <texture
- tga_file="lowerbody_shading_alpha.tga"
- file_is_mask="TRUE" />
-
- <param
- id="160"
- group="1"
- name="Shading"
- wearable="pants"
- value_min="0"
- value_max="1">
- <param_color>
- <value
- color="0, 0, 0, 0" />
-
- <value
- color="0, 0, 0, 128" />
- </param_color>
- </param>
- </layer>
-
- <layer
- name="highlight">
- <texture
- tga_file="lowerbody_highlights_alpha.tga"
- file_is_mask="TRUE" />
-
- <param
- id="161"
- group="1"
- name="Shading"
- wearable="skin"
- value_min="0"
- value_max="1">
- <param_color>
- <value
- color="255, 255, 255, 0" />
-
- <value
- color="255, 255, 255, 64" />
- </param_color>
- </param>
- </layer>
-
- <layer
- name="toenails">
- <texture
- tga_file="lowerbody_color.tga" />
- </layer>
-
- <layer
- name="lower_bodypaint">
- <texture
- local_texture="lower_bodypaint" />
- </layer>
+ local_texture="lower_pants" />
- <layer
- name="freckles lower"
- fixed_color="120,47,20,128">
- <param
- id="777"
- group="1"
- name="freckles lower"
- wearable="skin"
- value_min="0"
- value_max="1">
- <param_alpha
- tga_file="bodyfreckles_alpha.tga"
- skip_if_zero="true"
- domain="0.6" />
- </param>
- </layer>
-
- <layer
- name="lower_underpants bump"
- render_pass="bump"
- fixed_color="128,128,128,255">
- <texture
- local_texture="lower_underpants"
- local_texture_alpha_only="true" />
-
- <param
- id="1055"
- group="1"
- wearable="underpants"
- edit_group="underpants"
- name="Pants Length"
- value_min="0"
- value_max="1"
- value_default=".3">
- <param_alpha
- tga_file="pants_length_alpha.tga"
- domain="0.01" />
- </param>
-
- <param
- id="1057"
- group="1"
- wearable="underpants"
- edit_group="underpants"
- name="Pants Waist"
- value_min="0"
- value_max="1"
- value_default=".8">
- <param_alpha
- tga_file="pants_waist_alpha.tga"
- domain="0.05" />
- </param>
- </layer>
-
- <layer
- name="lower_underpants">
- <texture
- local_texture="lower_underpants" />
-
- <param
- id="824"
- group="0"
- wearable="underpants"
- edit_group="colorpicker"
- name="underpants_red"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="255, 0, 0, 255" />
- </param_color>
- </param>
-
- <param
- id="825"
- group="0"
- wearable="underpants"
- edit_group="colorpicker"
- name="underpants_green"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="0, 255, 0, 255" />
- </param_color>
- </param>
-
- <param
- id="826"
- group="0"
- wearable="underpants"
- edit_group="colorpicker"
- name="underpants_blue"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="0, 0, 255, 255" />
- </param_color>
- </param>
-
- <param
- id="1054"
- group="1"
- wearable="underpants"
- edit_group="driven"
- name="Pants Length"
- value_min="0"
- value_max="1"
- value_default=".3"
- camera_distance="1.2"
- camera_angle="30"
- camera_elevation="-.3">
- <param_alpha
- tga_file="pants_length_alpha.tga"
- domain="0.01" />
- </param>
-
- <param
- id="1056"
- group="1"
- wearable="underpants"
- edit_group="driven"
- name="Pants Waist"
- value_min="0"
- value_max="1"
- value_default=".8">
- <param_alpha
- tga_file="pants_waist_alpha.tga"
- domain="0.05" />
- </param>
- </layer>
-
- <layer
- name="lower_socks bump"
- render_pass="bump"
- fixed_color="128,128,128,255">
- <texture
- local_texture="lower_socks"
- local_texture_alpha_only="true" />
-
- <param
- id="1051"
- group="1"
- wearable="socks"
- edit_group="driven"
- name="Socks Length bump"
- value_min="0"
- value_max="1"
- value_default="0.35">
- <param_alpha
- tga_file="shoe_height_alpha.tga"
- domain="0.01" />
- </param>
- </layer>
-
- <layer
- name="lower_socks">
- <texture
- local_texture="lower_socks" />
-
- <param
- id="818"
- group="0"
- wearable="socks"
- edit_group="colorpicker"
- name="socks_red"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="255, 0, 0, 255" />
- </param_color>
- </param>
-
- <param
- id="819"
- group="0"
- wearable="socks"
- edit_group="colorpicker"
- name="socks_green"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="0, 255, 0, 255" />
- </param_color>
- </param>
-
- <param
- id="820"
- group="0"
- wearable="socks"
- edit_group="colorpicker"
- name="socks_blue"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="0, 0, 255, 255" />
- </param_color>
- </param>
-
- <param
- id="1050"
- group="1"
- wearable="socks"
- edit_group="driven"
- name="Socks Length bump"
- value_min="0"
- value_max="1"
- value_default="0.35">
- <param_alpha
- tga_file="shoe_height_alpha.tga"
- domain="0.01" />
- </param>
- </layer>
-
- <layer
- name="lower_shoes bump"
- render_pass="bump"
- fixed_color="128,128,128,255">
- <texture
- local_texture="lower_shoes"
- local_texture_alpha_only="true" />
-
- <param
- id="1053"
- group="1"
- wearable="shoes"
- edit_group="driven"
- name="Shoe Height bump"
- value_min="0"
- value_max="1"
- value_default="0.1">
- <param_alpha
- tga_file="shoe_height_alpha.tga"
- domain="0.01" />
- </param>
- </layer>
-
- <layer
- name="lower_shoes">
- <texture
- local_texture="lower_shoes" />
-
- <param
- id="812"
- group="0"
- wearable="shoes"
- edit_group="colorpicker"
- name="shoes_red"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="255, 0, 0, 255" />
- </param_color>
- </param>
-
- <param
- id="813"
- group="0"
- wearable="shoes"
- edit_group="colorpicker"
- name="shoes_green"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="0, 255, 0, 255" />
- </param_color>
- </param>
-
- <param
- id="817"
- group="0"
- wearable="shoes"
- edit_group="colorpicker"
- name="shoes_blue"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="0, 0, 255, 255" />
- </param_color>
- </param>
-
- <param
- id="1052"
- group="1"
- wearable="shoes"
- edit_group="driven"
- name="Shoe Height"
- value_min="0"
- value_max="1"
- value_default="0.1">
- <param_alpha
- tga_file="shoe_height_alpha.tga"
- domain="0.01" />
- </param>
- </layer>
-
- <layer
- name="lower_clothes_shadow">
- <texture
- local_texture="lower_pants" />
-
- <param
- id="913"
- group="1"
- edit_group="driven"
- wearable="pants"
- name="Lower Clothes Shading"
- value_min="0"
- value_max="1"
- value_default="0">
- <param_color>
- <value
- color="0, 0, 0, 0" />
-
- <value
- color="0, 0, 0, 80" />
- </param_color>
- </param>
-
- <param
- id="914"
- group="1"
- edit_group="driven"
- wearable="pants"
- name="Waist Height Shadow"
- value_min="0.02"
- value_max="1">
- <param_alpha
- tga_file="pants_waist_alpha.tga"
- skip_if_zero="true"
- domain="0.04" />
- </param>
-
- <param
- id="915"
- group="1"
- edit_group="driven"
- wearable="pants"
- name="Pants Length Shadow"
- value_min="0.02"
- value_max="1">
- <param_alpha
- tga_file="pants_length_alpha.tga"
- skip_if_zero="true"
- domain="0.03" />
- </param>
- </layer>
-
- <layer
- name="lower_pants base bump"
- render_pass="bump"
- fixed_color="128,128,128,255">
- <texture
- local_texture="lower_pants"
- local_texture_alpha_only="true" />
-
- <param
- id="1035"
- group="1"
- edit_group="driven"
- wearable="pants"
- name="Waist Height Cloth"
- value_min="0"
- value_max="1">
- <param_alpha
- tga_file="pants_waist_alpha.tga"
- domain="0.05" />
- </param>
-
- <param
- id="1036"
- group="1"
- edit_group="driven"
- wearable="pants"
- name="Pants Length Cloth"
- value_min="0"
- value_max="1">
- <param_alpha
- tga_file="pants_length_alpha.tga"
- domain="0.01" />
- </param>
- </layer>
-
- <layer
- name="lower_pants bump"
- render_pass="bump">
- <texture
- tga_file="bump_pants_wrinkles.tga" />
-
- <texture
- local_texture="lower_pants"
- local_texture_alpha_only="true" />
-
- <param
- id="869"
- group="0"
- wearable="pants"
- edit_group="pants"
- edit_group_order="6"
- name="Pants Wrinkles"
- value_min="0"
- value_max="1"
- value_default="0">
- <param_color>
- <value
- color="255, 255, 255, 0" />
-
- <value
- color="255, 255, 255, 255" />
- </param_color>
- </param>
-
- <param
- id="1017"
- group="1"
- edit_group="driven"
- wearable="pants"
- name="Waist Height Cloth"
- value_min="0"
- value_max="1">
- <param_alpha
- tga_file="pants_waist_alpha.tga"
- domain="0.05" />
- </param>
-
- <param
- id="1018"
- group="1"
- edit_group="driven"
- wearable="pants"
- name="Pants Length Cloth"
- value_min="0"
- value_max="1">
- <param_alpha
- tga_file="pants_length_alpha.tga"
- domain="0.01" />
- </param>
- </layer>
-
- <layer
- name="lower_pants">
- <texture
- local_texture="lower_pants" />
-
- <morph_mask
- morph_name="Displace_Loose_Lowerbody" />
-
- <morph_mask
- morph_name="Leg_Pantflair" />
-
- <morph_mask
- morph_name="Low_Crotch" />
-
- <morph_mask
- morph_name="Leg_Longcuffs" />
-
- <param
- id="806"
- group="0"
- wearable="pants"
- edit_group="colorpicker"
- name="pants_red"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="255, 0, 0, 255" />
- </param_color>
- </param>
-
- <param
- id="807"
- group="0"
- wearable="pants"
- edit_group="colorpicker"
- name="pants_green"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="0, 255, 0, 255" />
- </param_color>
- </param>
-
- <param
- id="808"
- group="0"
- wearable="pants"
- edit_group="colorpicker"
- name="pants_blue"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="0, 0, 255, 255" />
- </param_color>
- </param>
-
- <param
- id="614"
- group="1"
- edit_group="driven"
- wearable="pants"
- name="Waist Height Cloth"
- value_min="0"
- value_max="1"
- value_default=".8">
- <param_alpha
- tga_file="pants_waist_alpha.tga"
- domain="0.05" />
- </param>
-
- <param
- id="615"
- group="1"
- edit_group="driven"
- wearable="pants"
- name="Pants Length Cloth"
- value_min="0"
- value_max="1"
- value_default=".8">
- <param_alpha
- tga_file="pants_length_alpha.tga"
- domain="0.01" />
- </param>
- </layer>
-
- <layer
- name="lower_jacket base bump"
- render_pass="bump"
- fixed_color="128,128,128,255">
- <texture
- local_texture="lower_jacket"
- local_texture_alpha_only="true" />
-
- <param
- id="1033"
- group="1"
- wearable="jacket"
- edit_group="driven"
- name="jacket bottom length lower bump"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="false"
- tga_file="jacket_length_lower_alpha.tga"
- domain="0.01" />
- </param>
-
- <param
- id="1034"
- group="1"
- wearable="jacket"
- edit_group="driven"
- name="jacket open lower bump"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="jacket_open_lower_alpha.tga"
- domain="0.01" />
- </param>
- </layer>
-
- <layer
- name="lower_jacket bump"
- render_pass="bump">
- <texture
- tga_file="bump_pants_wrinkles.tga" />
-
- <texture
- local_texture="lower_jacket"
- local_texture_alpha_only="true" />
-
- <param
- id="876"
- group="1"
- wearable="jacket"
- name="jacket upper Wrinkles"
- value_min="0"
- value_max="1"
- value_default="0">
- <param_color>
- <value
- color="255, 255, 255, 0" />
-
- <value
- color="255, 255, 255, 255" />
- </param_color>
- </param>
-
- <param
- id="1027"
- group="1"
- wearable="jacket"
- edit_group="driven"
- name="jacket bottom length lower bump"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="false"
- tga_file="jacket_length_lower_alpha.tga"
- domain="0.01" />
- </param>
-
- <param
- id="1028"
- group="1"
- wearable="jacket"
- edit_group="driven"
- name="jacket open lower bump"
- value_min="0"
- value_max="1">
- <param_alpha
- multiply_blend="true"
- tga_file="jacket_open_lower_alpha.tga"
- domain="0.01" />
- </param>
- </layer>
-
- <layer
- name="lower_jacket">
- <texture
- local_texture="lower_jacket" />
-
- <param
- id="809"
- group="1"
- edit_group="colorpicker_driven"
- wearable="jacket"
- name="lower_jacket_red"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="255, 0, 0, 255" />
- </param_color>
- </param>
-
- <param
- id="810"
- group="1"
- edit_group="colorpicker_driven"
- wearable="jacket"
- name="lower_jacket_green"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="0, 255, 0, 255" />
- </param_color>
- </param>
-
- <param
- id="811"
- group="1"
- edit_group="colorpicker_driven"
- wearable="jacket"
- name="lower_jacket_blue"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="0, 0, 255, 255" />
- </param_color>
- </param>
-
- <param
- id="621"
- group="1"
- wearable="jacket"
- edit_group="jacket"
- name="bottom length lower"
- label_min="hi cut"
- label_max="low cut"
- value_min="0"
- value_max="1"
- value_default=".8"
- camera_distance="1.2"
- camera_angle="30"
- camera_elevation=".2">
- <param_alpha
- multiply_blend="false"
- tga_file="jacket_length_lower_alpha.tga"
- domain="0.01" />
- </param>
-
- <param
- id="623"
- group="1"
- wearable="jacket"
- edit_group="jacket"
- name="open lower"
- label_min="open"
- label_max="closed"
- value_min="0"
- value_max="1"
- value_default=".8"
- camera_distance="1.2"
- camera_angle="30"
- camera_elevation=".2">
- <param_alpha
- multiply_blend="true"
- tga_file="jacket_open_lower_alpha.tga"
- domain="0.01" />
- </param>
- </layer>
- </layer_set>
-
-<!-- =========================================================== -->
- <layer_set
- body_region="eyes"
- width="128"
- height="128">
- <layer
- name="whites">
- <texture
- tga_file="eyewhite.tga" />
- </layer>
-
- <layer
- name="iris"
- global_color="eye_color">
- <texture
- local_texture="eyes_iris" />
- </layer>
- </layer_set>
-
-<!-- =========================================================== -->
- <layer_set
- body_region="skirt"
- width="512"
- height="512"
- clear_alpha="false">
- <layer
- name="skirt_fabric"
- write_all_channels="true">
- <texture
- local_texture="skirt" />
-
- <param
- id="921"
- group="0"
- wearable="skirt"
- edit_group="colorpicker"
- name="skirt_red"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="255, 0, 0, 255" />
- </param_color>
- </param>
-
- <param
- id="922"
- group="0"
- wearable="skirt"
- edit_group="colorpicker"
- name="skirt_green"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="0, 255, 0, 255" />
- </param_color>
- </param>
-
- <param
- id="923"
- group="0"
- wearable="skirt"
- edit_group="colorpicker"
- name="skirt_blue"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_color>
- <value
- color="0, 0, 0, 255" />
-
- <value
- color="0, 0, 255, 255" />
- </param_color>
- </param>
- </layer>
-
- <layer
- name="skirt_fabric_alpha">
- <param
- id="858"
- group="0"
- wearable="skirt"
- edit_group="skirt"
- edit_group_order="1"
- name="Skirt Length"
- show_simple="true"
- label_min="Short"
- label_max="Long"
- value_min=".01"
- value_max="1"
- value_default=".4"
- simple_percent_min="40"
- simple_percent_max="100"
- camera_distance="1.3"
- camera_elevation="-.5"
- camera_angle="30">
- <param_alpha
- tga_file="skirt_length_alpha.tga"
- domain="0"
- multiply_blend="true" />
- </param>
-
- <param
- id="859"
- group="0"
- wearable="skirt"
- edit_group="skirt"
- edit_group_order="4"
- name="Slit Front"
- label_min="Open Front"
- label_max="Closed Front"
- value_min="0"
- value_max="1"
- value_default="1"
- camera_distance="1.3"
- camera_elevation="-.5"
- camera_angle="30">
- <param_alpha
- tga_file="skirt_slit_front_alpha.tga"
- multiply_blend="true"
- domain="0" />
- </param>
-
- <param
- id="860"
- group="0"
- wearable="skirt"
- edit_group="skirt"
- edit_group_order="5"
- name="Slit Back"
- label_min="Open Back"
- label_max="Closed Back"
- value_min="0"
- value_max="1"
- value_default="1"
- camera_distance="1.3"
- camera_elevation="-.5"
- camera_angle="160">
- <param_alpha
- tga_file="skirt_slit_back_alpha.tga"
- multiply_blend="true"
- domain="0" />
- </param>
-
- <param
- id="861"
- group="0"
- wearable="skirt"
- edit_group="skirt"
- edit_group_order="6"
- name="Slit Left"
- label_min="Open Left"
- label_max="Closed Left"
- value_min="0"
- value_max="1"
- value_default="1"
- camera_distance="1.3"
- camera_elevation="-.5"
- camera_angle="30">
- <param_alpha
- tga_file="skirt_slit_left_alpha.tga"
- multiply_blend="true"
- domain="0" />
- </param>
-
- <param
- id="862"
- group="0"
- wearable="skirt"
- edit_group="skirt"
- edit_group_order="7"
- name="Slit Right"
- label_min="Open Right"
- label_max="Closed Right"
- value_min="0"
- value_max="1"
- value_default="1"
- camera_distance="1.3"
- camera_elevation="-.5"
- camera_angle="-30">
- <param_alpha
- tga_file="skirt_slit_right_alpha.tga"
- multiply_blend="true"
- domain="0" />
- </param>
- </layer>
- </layer_set>
-
-<!-- =========================================================== -->
- <driver_parameters>
- <param
- id="828"
- group="0"
- name="Loose Upper Clothing"
- label="Shirt Fit"
- show_simple="true"
- wearable="shirt"
- edit_group="shirt"
- edit_group_order="4"
- label_min="Tight Shirt"
- label_max="Loose Shirt"
+ <param
+ id="913"
+ group="1"
+ edit_group="driven"
+ wearable="pants"
+ name="Lower Clothes Shading"
value_min="0"
value_max="1"
- camera_distance="1.2"
- camera_angle="30"
- camera_elevation=".2">
- <param_driver>
- <driven
- id="628" />
+ value_default="0">
+ <param_color>
+ <value
+ color="0, 0, 0, 0" />
- <driven
- id="899"
- min1="0.1"
- max1="0.5"
- max2="1"
- min2="1" />
- </param_driver>
+ <value
+ color="0, 0, 0, 80" />
+ </param_color>
</param>
<param
- id="816"
- group="0"
- name="Loose Lower Clothing"
- label="Pants Fit"
- show_simple="true"
+ id="914"
+ group="1"
+ edit_group="driven"
wearable="pants"
- edit_group="pants"
- edit_group_order="2.5"
- label_min="Tight Pants"
- label_max="Loose Pants"
- value_min="0"
- value_max="1"
- camera_distance="1.8"
- camera_angle="30"
- camera_elevation="-.3">
- <param_driver>
- <driven
- id="516" />
+ name="Waist Height Shadow"
+ value_min="0.02"
+ value_max="1">
+ <param_alpha
+ tga_file="pants_waist_alpha.tga"
+ skip_if_zero="true"
+ domain="0.04" />
+ </param>
- <driven
- id="913"
- min1="0.1"
- max1="0.5"
- max2="1"
- min2="1" />
- </param_driver>
+ <param
+ id="915"
+ group="1"
+ edit_group="driven"
+ wearable="pants"
+ name="Pants Length Shadow"
+ value_min="0.02"
+ value_max="1">
+ <param_alpha
+ tga_file="pants_length_alpha.tga"
+ skip_if_zero="true"
+ domain="0.03" />
</param>
+ </layer>
+
+ <layer
+ name="lower_pants base bump"
+ render_pass="bump"
+ fixed_color="128,128,128,255">
+ <texture
+ local_texture="lower_pants"
+ local_texture_alpha_only="true" />
<param
- id="814"
- group="0"
+ id="1035"
+ group="1"
+ edit_group="driven"
wearable="pants"
- edit_group="pants"
- edit_group_order="2"
- name="Waist Height"
- label_min="Low"
- label_max="High"
+ name="Waist Height Cloth"
value_min="0"
- value_max="1"
- value_default="1"
- camera_distance="1.2"
- camera_angle="30"
- camera_elevation="-.3">
- <param_driver>
- <driven
- id="614" />
+ value_max="1">
+ <param_alpha
+ tga_file="pants_waist_alpha.tga"
+ domain="0.05" />
+ </param>
- <driven
- id="1017" />
+ <param
+ id="1036"
+ group="1"
+ edit_group="driven"
+ wearable="pants"
+ name="Pants Length Cloth"
+ value_min="0"
+ value_max="1">
+ <param_alpha
+ tga_file="pants_length_alpha.tga"
+ domain="0.01" />
+ </param>
+ </layer>
- <driven
- id="1033" />
+ <layer
+ name="lower_pants bump"
+ render_pass="bump">
+ <texture
+ tga_file="bump_pants_wrinkles.tga" />
- <driven
- id="914"
- min1="0"
- max1=".98"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
+ <texture
+ local_texture="lower_pants"
+ local_texture_alpha_only="true" />
<param
- id="815"
+ id="869"
group="0"
wearable="pants"
edit_group="pants"
- edit_group_order="1"
- name="Pants Length"
- show_simple="true"
- label_min="Short"
- label_max="Long"
- value_min="0"
- value_max="1"
- value_default=".8"
- simple_percent_min="20"
- simple_percent_max="100"
- camera_distance="1.8"
- camera_angle="30"
- camera_elevation="-.3">
- <param_driver>
- <driven
- id="615"
- min1="0"
- max1=".9"
- max2="1"
- min2="1" />
-
- <driven
- id="1018"
- min1="0"
- max1=".9"
- max2="1"
- min2="1" />
-
- <driven
- id="1036"
- min1="0"
- max1=".9"
- max2="1"
- min2="1" />
-
- <driven
- id="793"
- min1=".9"
- max1="1"
- max2="1"
- min2="1" />
-
- <driven
- id="915"
- min1="0"
- max1=".882"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
-
- <param
- id="800"
- group="0"
- wearable="shirt"
- edit_group="shirt"
- edit_group_order="1"
- name="Sleeve Length"
- show_simple="true"
- label_min="Short"
- label_max="Long"
+ edit_group_order="6"
+ name="Pants Wrinkles"
value_min="0"
value_max="1"
- value_default=".89"
- simple_percent_min="15"
- simple_percent_max="100"
- camera_distance="1.2"
- camera_angle="30"
- camera_elevation=".2">
- <param_driver>
- <driven
- id="600" />
-
- <driven
- id="1013" />
-
- <driven
- id="1029" />
+ value_default="0">
+ <param_color>
+ <value
+ color="255, 255, 255, 0" />
- <driven
- id="900"
- min1="0"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
+ <value
+ color="255, 255, 255, 255" />
+ </param_color>
</param>
<param
- id="801"
- group="0"
- wearable="shirt"
- edit_group="shirt"
- edit_group_order="2"
- name="Shirt Bottom"
- label_min="Short"
- label_max="Long"
+ id="1017"
+ group="1"
+ edit_group="driven"
+ wearable="pants"
+ name="Waist Height Cloth"
value_min="0"
- value_max="1"
- value_default="1"
- camera_distance="1.2"
- camera_angle="30"
- camera_elevation=".2">
- <param_driver>
- <driven
- id="601" />
-
- <driven
- id="1014" />
-
- <driven
- id="1030" />
+ value_max="1">
+ <param_alpha
+ tga_file="pants_waist_alpha.tga"
+ domain="0.05" />
+ </param>
- <driven
- id="901"
- min1="0"
- max1=".98"
- max2="1"
- min2="1" />
- </param_driver>
+ <param
+ id="1018"
+ group="1"
+ edit_group="driven"
+ wearable="pants"
+ name="Pants Length Cloth"
+ value_min="0"
+ value_max="1">
+ <param_alpha
+ tga_file="pants_length_alpha.tga"
+ domain="0.01" />
</param>
+ </layer>
+
+ <layer
+ name="lower_pants">
+ <texture
+ local_texture="lower_pants" />
<param
- id="802"
+ id="806"
group="0"
- wearable="shirt"
- edit_group="shirt"
- edit_group_order="3"
- name="Collar Front"
- show_simple="true"
- label_min="Low"
- label_max="High"
+ wearable="pants"
+ edit_group="colorpicker"
+ name="pants_red"
value_min="0"
value_max="1"
- value_default=".78"
- simple_percent_min="40"
- simple_percent_max="100"
- camera_distance="1.2"
- camera_angle="15"
- camera_elevation=".2">
- <param_driver>
- <driven
- id="602" />
-
- <driven
- id="1015" />
-
- <driven
- id="1031" />
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
- <driven
- id="902"
- min1="0"
- max1=".98"
- max2="1"
- min2="1" />
- </param_driver>
+ <value
+ color="255, 0, 0, 255" />
+ </param_color>
</param>
<param
- id="781"
+ id="807"
group="0"
- wearable="shirt"
- edit_group="shirt"
- edit_group_order="3.1"
- name="Collar Back"
- label_min="Low"
- label_max="High"
+ wearable="pants"
+ edit_group="colorpicker"
+ name="pants_green"
value_min="0"
value_max="1"
- value_default=".78"
- camera_distance="1.2"
- camera_angle="195"
- camera_elevation=".2">
- <param_driver>
- <driven
- id="778" />
-
- <driven
- id="1016" />
-
- <driven
- id="1032" />
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
- <driven
- id="903"
- min1="0"
- max1=".98"
- max2="1"
- min2="1" />
- </param_driver>
+ <value
+ color="0, 255, 0, 255" />
+ </param_color>
</param>
<param
- id="150"
+ id="808"
group="0"
- wearable="skin"
- edit_group="skin_bodydetail"
- name="Body Definition"
- label_min="Less"
- label_max="More"
+ wearable="pants"
+ edit_group="colorpicker"
+ name="pants_blue"
value_min="0"
value_max="1"
- value_default="0"
- camera_distance="1.4"
- camera_elevation="-.2">
- <param_driver>
- <driven
- id="125" />
-
- <driven
- id="126" />
-
- <driven
- id="160" />
-
- <driven
- id="161" />
-
- <driven
- id="874" />
-
- <driven
- id="878" />
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
- </param_driver>
+ <value
+ color="0, 0, 255, 255" />
+ </param_color>
</param>
<param
- id="775"
- group="0"
- wearable="skin"
- edit_group="skin_bodydetail"
- name="Body Freckles"
- label_min="Less Freckles"
- label_max="More Freckles"
+ id="614"
+ group="1"
+ edit_group="driven"
+ wearable="pants"
+ name="Waist Height Cloth"
value_min="0"
value_max="1"
- value_default="0"
- camera_distance="1.4"
- camera_elevation="-.2">
- <param_driver>
- <driven
- id="776" />
-
- <driven
- id="777" />
- </param_driver>
+ value_default=".8">
+ <param_alpha
+ tga_file="pants_waist_alpha.tga"
+ domain="0.05" />
</param>
<param
- id="162"
- group="0"
- wearable="skin"
- edit_group="skin_facedetail"
- edit_group_order="1"
- name="Facial Definition"
- label_min="Less"
- label_max="More"
+ id="615"
+ group="1"
+ edit_group="driven"
+ wearable="pants"
+ name="Pants Length Cloth"
value_min="0"
value_max="1"
- camera_distance=".3"
- camera_elevation=".07"
- value_default="0">
- <param_driver>
- <driven
- id="158" />
+ value_default=".8">
+ <param_alpha
+ tga_file="pants_length_alpha.tga"
+ domain="0.01" />
+ </param>
+ </layer>
- <driven
- id="159" />
+ <layer
+ name="lower_jacket base bump"
+ render_pass="bump"
+ fixed_color="128,128,128,255">
+ <texture
+ local_texture="lower_jacket"
+ local_texture_alpha_only="true" />
- <driven
- id="873" />
- </param_driver>
+ <param
+ id="1033"
+ group="1"
+ wearable="jacket"
+ edit_group="driven"
+ cross_wearable="true"
+ name="jacket bottom length lower bump"
+ value_min="0"
+ value_max="1">
+ <param_alpha
+ multiply_blend="false"
+ tga_file="jacket_length_lower_alpha.tga"
+ domain="0.01" />
</param>
<param
- id="163"
- group="0"
- wearable="skin"
- edit_group="skin_facedetail"
- edit_group_order="3"
- name="wrinkles"
- label_min="Less"
- label_max="More"
+ id="1034"
+ group="1"
+ wearable="jacket"
+ edit_group="driven"
+ name="jacket open lower bump"
value_min="0"
- value_max="1"
- camera_distance=".3"
- camera_elevation=".07"
- value_default="0">
- <param_driver>
-<!--<driven
- id="128" />-->
- <driven
- id="118" />
- </param_driver>
+ value_max="1">
+ <param_alpha
+ multiply_blend="true"
+ tga_file="jacket_open_lower_alpha.tga"
+ domain="0.01" />
</param>
+ </layer>
+
+ <layer
+ name="lower_jacket bump"
+ render_pass="bump">
+ <texture
+ tga_file="bump_pants_wrinkles.tga" />
+
+ <texture
+ local_texture="lower_jacket"
+ local_texture_alpha_only="true" />
+
<param
- id="505"
- group="0"
- wearable="shape"
- edit_group="shape_mouth"
- edit_group_order="3"
- name="Lip Thickness"
- label_min="Thin Lips"
- label_max="Fat Lips"
+ id="876"
+ group="1"
+ wearable="jacket"
+ name="jacket upper Wrinkles"
value_min="0"
value_max="1"
- value_default=".5"
- camera_distance=".3"
- camera_elevation=".04"
- camera_angle="20">
- <param_driver>
- <driven
- id="26"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
+ value_default="0">
+ <param_color>
+ <value
+ color="255, 255, 255, 0" />
- <driven
- id="28"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
+ <value
+ color="255, 255, 255, 255" />
+ </param_color>
</param>
<param
- id="799"
- group="0"
- wearable="shape"
- edit_group="shape_mouth"
- edit_group_order="3.2"
- name="Lip Ratio"
- label="Lip Ratio"
- show_simple="true"
- label_min="More Upper Lip"
- label_max="More Lower Lip"
+ id="1027"
+ group="1"
+ wearable="jacket"
+ edit_group="driven"
+ name="jacket bottom length lower bump"
value_min="0"
- value_max="1"
- value_default=".5"
- camera_distance=".3"
- camera_elevation=".04"
- camera_angle="20">
- <param_driver>
- <driven
- id="797"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
-
- <driven
- id="798"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
+ value_max="1">
+ <param_alpha
+ multiply_blend="false"
+ tga_file="jacket_length_lower_alpha.tga"
+ domain="0.01" />
</param>
<param
- id="155"
- group="0"
- wearable="shape"
- edit_group="shape_mouth"
- edit_group_order="1"
- name="Lip Width"
- label="Lip Width"
- label_min="Narrow Lips"
- label_max="Wide Lips"
- show_simple="true"
- value_min="-0.9"
- value_max="1.3"
- camera_distance=".3"
- camera_elevation=".04"
- value_default="0">
- <param_driver>
- <driven
- id="29" />
-
- <driven
- id="30" />
- </param_driver>
+ id="1028"
+ group="1"
+ wearable="jacket"
+ edit_group="driven"
+ name="jacket open lower bump"
+ value_min="0"
+ value_max="1">
+ <param_alpha
+ multiply_blend="true"
+ tga_file="jacket_open_lower_alpha.tga"
+ domain="0.01" />
</param>
+ </layer>
+
+ <layer
+ name="lower_jacket">
+ <texture
+ local_texture="lower_jacket" />
<param
- id="196"
- group="0"
- wearable="shape"
- edit_group="shape_eyes"
- edit_group_order="2"
- name="Eye Spacing"
- label="Eye Spacing"
- label_min="Close Set Eyes"
- label_max="Far Set Eyes"
- show_simple="true"
- value_min="-2"
+ id="809"
+ group="1"
+ edit_group="colorpicker_driven"
+ wearable="jacket"
+ name="lower_jacket_red"
+ value_min="0"
value_max="1"
- value_default="0"
- camera_elevation=".1"
- camera_distance=".35"
- camera_angle="5">
- <param_driver>
- <driven
- id="194" />
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
- <driven
- id="195" />
- </param_driver>
+ <value
+ color="255, 0, 0, 255" />
+ </param_color>
</param>
<param
- id="769"
- group="0"
- wearable="shape"
- edit_group="shape_eyes"
- edit_group_order="4.5"
- name="Eye Depth"
- label_min="Sunken Eyes"
- label_max="Bugged Eyes"
+ id="810"
+ group="1"
+ edit_group="colorpicker_driven"
+ wearable="jacket"
+ name="lower_jacket_green"
value_min="0"
value_max="1"
- value_default=".5"
- camera_elevation=".1"
- camera_distance=".3"
- camera_angle="75">
- <param_driver>
- <driven
- id="767" />
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
- <driven
- id="768" />
- </param_driver>
+ <value
+ color="0, 255, 0, 255" />
+ </param_color>
</param>
<param
- id="198"
- group="0"
- wearable="shoes"
- edit_group="shoes"
- edit_group_order="2"
- name="Heel Height"
- label_min="Low Heels"
- label_max="High Heels"
+ id="811"
+ group="1"
+ edit_group="colorpicker_driven"
+ wearable="jacket"
+ name="lower_jacket_blue"
value_min="0"
value_max="1"
- value_default="0"
- camera_angle="45"
- camera_distance=".8"
- camera_elevation="-1">
- <param_driver>
- <driven
- id="197" />
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
- <driven
- id="500" />
- </param_driver>
+ <value
+ color="0, 0, 255, 255" />
+ </param_color>
</param>
<param
- id="513"
- group="0"
- wearable="shoes"
- edit_group="shoes"
- edit_group_order="3"
- name="Heel Shape"
- label_min="Pointy Heels"
- label_max="Thick Heels"
- value_min="0"
- value_max="1"
- value_default=".5"
- camera_angle="45"
- camera_distance="1.5"
- camera_elevation="-1">
- <param_driver>
- <driven
- id="509"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
-
- <driven
- id="510"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
-
- <param
- id="514"
- group="0"
- wearable="shoes"
- edit_group="shoes"
- edit_group_order="4"
- name="Toe Shape"
- label_min="Pointy"
- label_max="Square"
- value_min="0"
- value_max="1"
- value_default=".5"
- camera_angle="5"
- camera_distance=".8"
- camera_elevation="-.8">
- <param_driver>
- <driven
- id="511"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
-
- <driven
- id="512"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
-
- <param
- id="503"
- group="0"
- wearable="shoes"
- edit_group="shoes"
- edit_group_order="6"
- name="Platform Height"
- label_min="Low Platforms"
- label_max="High Platforms"
+ id="621"
+ group="1"
+ wearable="jacket"
+ edit_group="jacket"
+ name="bottom length lower"
+ label_min="hi cut"
+ label_max="low cut"
value_min="0"
value_max="1"
- value_default="0"
- camera_angle="45"
- camera_distance=".5"
- camera_elevation="-1">
- <param_driver>
- <driven
- id="501" />
-
- <driven
- id="502" />
- </param_driver>
+ value_default=".8"
+ camera_distance="1.2"
+ camera_angle="30"
+ camera_elevation=".2">
+ <param_alpha
+ multiply_blend="false"
+ tga_file="jacket_length_lower_alpha.tga"
+ domain="0.01" />
</param>
<param
- id="193"
- group="0"
- wearable="shape"
- edit_group="shape_head"
- edit_group_order="3"
- name="Head Shape"
- label="Head Shape"
- label_min="More Square"
- label_max="More Round"
- show_simple="true"
- value_min="0"
- value_max="1"
- value_default=".5"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_driver>
- <driven
- id="188"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
-
- <driven
- id="642"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
-
- <driven
- id="189"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
-
- <driven
- id="643"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
-
- <param
- id="157"
- group="0"
- wearable="shape"
- edit_group="shape_torso"
- edit_group_order="13"
- name="Belly Size"
- label_min="Small"
- label_max="Big"
+ id="623"
+ group="1"
+ wearable="jacket"
+ edit_group="jacket"
+ name="open lower"
+ label_min="open"
+ label_max="closed"
value_min="0"
value_max="1"
- value_default="0"
- camera_distance="1.4"
+ value_default=".8"
+ camera_distance="1.2"
camera_angle="30"
camera_elevation=".2">
- <param_driver>
- <driven
- id="104" />
+ <param_alpha
+ multiply_blend="true"
+ tga_file="jacket_open_lower_alpha.tga"
+ domain="0.01" />
+ </param>
+ </layer>
- <driven
- id="156" />
+ <layer
+ name="lower alpha"
+ visibility_mask="TRUE">
+ <texture
+ local_texture="lower_alpha" />
+ </layer>
- <driven
- id="849" />
- </param_driver>
- </param>
+ </layer_set>
- <param
- id="637"
- group="0"
- wearable="shape"
- edit_group="shape_body"
- edit_group_order="3"
- name="Body Fat"
- label_min="Less Body Fat"
- label_max="More Body Fat"
- value_min="0"
- value_max="1"
- value_default="0"
- camera_distance="1.8">
- <param_driver>
- <driven
- id="633" />
+ <!-- =========================================================== -->
+ <layer_set
+ body_region="eyes"
+ width="128"
+ height="128">
+ <layer
+ name="whites">
+ <texture
+ tga_file="eyewhite.tga" />
+ </layer>
- <driven
- id="634" />
+ <layer
+ name="iris"
+ global_color="eye_color">
+ <texture
+ local_texture="eyes_iris" />
+ </layer>
- <driven
- id="635" />
+ <layer
+ name="eyes alpha"
+ visibility_mask="TRUE">
+ <texture
+ local_texture="eyes_alpha" />
+ </layer>
- <driven
- id="851" />
- </param_driver>
- </param>
+ </layer_set>
+
+ <!-- =========================================================== -->
+ <layer_set
+ body_region="skirt"
+ width="512"
+ height="512"
+ clear_alpha="false">
+ <layer
+ name="skirt_fabric"
+ write_all_channels="true">
+ <texture
+ local_texture="skirt" />
<param
- id="130"
+ id="921"
group="0"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="8"
- name="Front Fringe"
- label_min="Short"
- label_max="Long"
+ wearable="skirt"
+ edit_group="colorpicker"
+ name="skirt_red"
value_min="0"
value_max="1"
- value_default=".45"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_driver>
- <driven
- id="144"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
- <driven
- id="145"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
+ <value
+ color="255, 0, 0, 255" />
+ </param_color>
</param>
<param
- id="131"
+ id="922"
group="0"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="9"
- name="Side Fringe"
- label_min="Short"
- label_max="Long"
- value_min="0"
- value_max="1"
- value_default=".5"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="90">
- <param_driver>
- <driven
- id="146"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
-
- <driven
- id="147"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
-
- <param
- id="132"
- group="0"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="10"
- name="Back Fringe"
- label_min="Short"
- label_max="Long"
+ wearable="skirt"
+ edit_group="colorpicker"
+ name="skirt_green"
value_min="0"
value_max="1"
- value_default=".39"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="160">
- <param_driver>
- <driven
- id="148"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
- <driven
- id="149"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
+ <value
+ color="0, 255, 0, 255" />
+ </param_color>
</param>
<param
- id="133"
+ id="923"
group="0"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="2"
- name="Hair Front"
- label_min="Short"
- label_max="Long"
+ wearable="skirt"
+ edit_group="colorpicker"
+ name="skirt_blue"
value_min="0"
value_max="1"
- value_default=".25"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_driver>
- <driven
- id="172"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
+ value_default="1">
+ <param_color>
+ <value
+ color="0, 0, 0, 255" />
- <driven
- id="171"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
+ <value
+ color="0, 0, 255, 255" />
+ </param_color>
</param>
+ </layer>
+ <layer
+ name="skirt_fabric_alpha">
<param
- id="134"
- group="0"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="3"
- name="Hair Sides"
- label_min="Short"
- label_max="Long"
- value_min="0"
- value_max="1"
- value_default=".5"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="90">
- <param_driver>
- <driven
- id="174"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
-
- <driven
- id="173"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
-
- <param
- id="135"
+ id="858"
group="0"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="4"
- name="Hair Back"
- show_simple="true"
+ wearable="skirt"
+ edit_group="skirt"
+ edit_group_order="1"
+ name="Skirt Length"
+ show_simple="true"
label_min="Short"
label_max="Long"
- value_min="0"
+ value_min=".01"
value_max="1"
- value_default=".55"
- camera_elevation="-.1"
- camera_distance=".8"
- camera_angle="160">
- <param_driver>
- <driven
- id="176"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
-
- <driven
- id="175"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
+ value_default=".4"
+ simple_percent_min="40"
+ simple_percent_max="100"
+ camera_distance="1.3"
+ camera_elevation="-.5"
+ camera_angle="30">
+ <param_alpha
+ tga_file="skirt_length_alpha.tga"
+ domain="0"
+ multiply_blend="true" />
</param>
<param
- id="136"
+ id="859"
group="0"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="11.5"
- name="Hair Sweep"
- label_min="Sweep Forward"
- label_max="Sweep Back"
- value_min="0"
- value_max="1"
- value_default=".5"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="90">
- <param_driver>
- <driven
- id="179"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
-
- <driven
- id="178"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
-
- <param
- id="137"
- group="0"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="16"
- name="Hair Tilt"
- label_min="Left"
- label_max="Right"
- value_min="0"
- value_max="1"
- value_default=".5"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="0">
- <param_driver>
- <driven
- id="190"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
-
- <driven
- id="191"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
-
- <param
- id="608"
- group="0"
- wearable="jacket"
- edit_group="jacket"
- edit_group_order="2"
- name="bottom length lower"
- label="Jacket Length"
- label_min="Short"
- label_max="Long"
+ wearable="skirt"
+ edit_group="skirt"
+ edit_group_order="4"
+ name="Slit Front"
+ label_min="Open Front"
+ label_max="Closed Front"
value_min="0"
value_max="1"
- value_default=".8"
- camera_distance="1.4"
- camera_angle="30"
- camera_elevation=".2">
- <param_driver>
- <driven
- id="620" />
-
- <driven
- id="1025" />
-
- <driven
- id="1037" />
-
- <driven
- id="621" />
-
- <driven
- id="1027" />
-
- <driven
- id="1033" />
- </param_driver>
+ value_default="1"
+ camera_distance="1.3"
+ camera_elevation="-.5"
+ camera_angle="30">
+ <param_alpha
+ tga_file="skirt_slit_front_alpha.tga"
+ multiply_blend="true"
+ domain="0" />
</param>
<param
- id="609"
+ id="860"
group="0"
- wearable="jacket"
- edit_group="jacket"
- edit_group_order="4"
- name="open jacket"
- label="Open Front"
- label_min="Open"
- label_max="Closed"
+ wearable="skirt"
+ edit_group="skirt"
+ edit_group_order="5"
+ name="Slit Back"
+ label_min="Open Back"
+ label_max="Closed Back"
value_min="0"
value_max="1"
- value_default=".2"
- camera_distance="1.4"
- camera_angle="30"
- camera_elevation=".2">
- <param_driver>
- <driven
- id="622" />
-
- <driven
- id="1026" />
-
- <driven
- id="1038" />
-
- <driven
- id="623" />
-
- <driven
- id="1028" />
-
- <driven
- id="1034" />
- </param_driver>
+ value_default="1"
+ camera_distance="1.3"
+ camera_elevation="-.5"
+ camera_angle="160">
+ <param_alpha
+ tga_file="skirt_slit_back_alpha.tga"
+ multiply_blend="true"
+ domain="0" />
</param>
<param
- id="105"
+ id="861"
group="0"
- sex="female"
- wearable="shape"
- edit_group="shape_torso"
+ wearable="skirt"
+ edit_group="skirt"
edit_group_order="6"
- name="Breast Size"
- label_min="Small"
- label_max="Large"
+ name="Slit Left"
+ label_min="Open Left"
+ label_max="Closed Left"
value_min="0"
value_max="1"
- value_default=".5"
- camera_elevation=".3"
- camera_distance="1.2"
+ value_default="1"
+ camera_distance="1.3"
+ camera_elevation="-.5"
camera_angle="30">
- <param_driver>
- <driven
- id="843"
- min1="0"
- max1="0"
- max2="0"
- min2=".01" />
-
- <driven
- id="627"
- min1="0"
- max1="0.01"
- max2="0.01"
- min2=".5" />
-
- <driven
- id="626"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
-
- <param
- id="629"
- group="0"
- wearable="shape"
- edit_group="shape_head"
- edit_group_order="6"
- name="Forehead Angle"
- label_min="More Vertical"
- label_max="More Sloped"
- value_min="0"
- value_max="1"
- value_default=".5"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="70">
- <param_driver>
- <driven
- id="630"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
-
- <driven
- id="644"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
-
- <driven
- id="631"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
-
- <driven
- id="645"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
-
- <param
- id="646"
- group="0"
- name="Egg_Head"
- label="Egg Head"
- wearable="shape"
- edit_group="shape_head"
- edit_group_order="4"
- label_min="Chin Heavy"
- label_max="Forehead Heavy"
- show_simple="true"
- value_min="-1.3"
- value_max="1"
- value_default="0"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_driver>
- <driven
- id="640" />
-
- <driven
- id="186" />
- </param_driver>
+ <param_alpha
+ tga_file="skirt_slit_left_alpha.tga"
+ multiply_blend="true"
+ domain="0" />
</param>
<param
- id="647"
- group="0"
- name="Squash_Stretch_Head"
- label="Head Stretch"
- wearable="shape"
- edit_group="shape_head"
- edit_group_order="2"
- show_simple="true"
- label_min="Squash Head"
- label_max="Stretch Head"
- value_min="-0.5"
- value_max="1"
- value_default="0"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_driver>
- <driven
- id="641" />
-
- <driven
- id="187" />
- </param_driver>
- </param>
-
- <param
- id="649"
- group="0"
- sex="female"
- wearable="shape"
- edit_group="shape_torso"
- edit_group_order="1.1"
- name="Torso Muscles"
- label="Torso Muscles"
- show_simple="true"
- label_min="Less Muscular"
- label_max="More Muscular"
- value_min="0"
- value_max="1"
- value_default=".5"
- camera_elevation=".1"
- camera_distance="1"
- camera_angle="15">
- <param_driver>
- <driven
- id="648"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
-
- <driven
- id="106"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
-
- <param
- id="678"
- group="0"
- sex="male"
- wearable="shape"
- edit_group="shape_torso"
- edit_group_order="1"
- name="Torso Muscles"
- show_simple="true"
- label_min="Less Muscular"
- label_max="More Muscular"
- value_min="0"
- value_max="1"
- value_default=".5"
- camera_elevation=".1"
- camera_distance="1.2"
- camera_angle="0">
- <param_driver>
- <driven
- id="677"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
-
- <driven
- id="106"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
-
- <param
- id="652"
+ id="862"
group="0"
- wearable="shape"
- edit_group="shape_legs"
- edit_group_order="1"
- name="Leg Muscles"
- label_min="Less Muscular"
- label_max="More Muscular"
- show_simple="true"
+ wearable="skirt"
+ edit_group="skirt"
+ edit_group_order="7"
+ name="Slit Right"
+ label_min="Open Right"
+ label_max="Closed Right"
value_min="0"
value_max="1"
- value_default=".5"
+ value_default="1"
camera_distance="1.3"
camera_elevation="-.5"
- camera_angle="15">
- <param_driver>
- <driven
- id="651"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
-
- <driven
- id="152"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
-
- <param
- id="80"
- name="male"
- group="0"
- edit_group="dummy"
- wearable="shape"
- value_min="0"
- value_max="1">
- <param_driver>
- <driven
- id="32" />
+ camera_angle="-30">
+ <param_alpha
+ tga_file="skirt_slit_right_alpha.tga"
+ multiply_blend="true"
+ domain="0" />
+ </param>
+ </layer>
- <driven
- id="153" />
+ </layer_set>
- <driven
- id="40" />
+ <!-- =========================================================== -->
+ <driver_parameters>
+ <param
+ id="828"
+ group="0"
+ name="Loose Upper Clothing"
+ label="Shirt Fit"
+ show_simple="true"
+ wearable="shirt"
+ edit_group="shirt"
+ edit_group_order="4"
+ label_min="Tight Shirt"
+ label_max="Loose Shirt"
+ value_min="0"
+ value_max="1"
+ camera_distance="1.2"
+ camera_angle="30"
+ camera_elevation=".2">
+ <param_driver>
+ <driven
+ id="628" />
+
+ <driven
+ id="899"
+ min1="0.1"
+ max1="0.5"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="100" />
+ <param
+ id="816"
+ group="0"
+ name="Loose Lower Clothing"
+ label="Pants Fit"
+ show_simple="true"
+ wearable="pants"
+ edit_group="pants"
+ edit_group_order="2.5"
+ label_min="Tight Pants"
+ label_max="Loose Pants"
+ value_min="0"
+ value_max="1"
+ camera_distance="1.8"
+ camera_angle="30"
+ camera_elevation="-.3">
+ <param_driver>
+ <driven
+ id="516" />
+
+ <driven
+ id="913"
+ min1="0.1"
+ max1="0.5"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="857" />
- </param_driver>
- </param>
+ <param
+ id="814"
+ group="0"
+ wearable="pants"
+ edit_group="pants"
+ edit_group_order="2"
+ name="Waist Height"
+ label_min="Low"
+ label_max="High"
+ value_min="0"
+ value_max="1"
+ value_default="1"
+ camera_distance="1.2"
+ camera_angle="30"
+ camera_elevation="-.3">
+ <param_driver>
+ <driven
+ id="614" />
+
+ <driven
+ id="1017" />
+
+ <driven
+ id="1035" />
+
+ <driven
+ id="914"
+ min1="0"
+ max1=".98"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <param
- id="659"
- group="0"
- wearable="shape"
- edit_group="shape_mouth"
- edit_group_order="5"
- name="Mouth Corner"
- label_min="Corner Down"
- label_max="Corner Up"
- value_min="0"
- value_max="1"
- value_default=".5"
- camera_elevation="0"
- camera_distance=".28">
- <param_driver>
- <driven
- id="658"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
-
- <driven
- id="657"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
-
- <param
- id="662"
- group="0"
- wearable="shape"
- edit_group="shape_head"
- edit_group_order="5"
- name="Face Shear"
- label_min="Shear Right Up"
- label_max="Shear Left Up"
- value_min="0"
- value_max="1"
- value_default=".5"
- camera_elevation=".1"
- camera_distance=".5">
- <param_driver>
- <driven
- id="660" />
+ <param
+ id="815"
+ group="0"
+ wearable="pants"
+ edit_group="pants"
+ edit_group_order="1"
+ name="Pants Length"
+ show_simple="true"
+ label_min="Short"
+ label_max="Long"
+ value_min="0"
+ value_max="1"
+ value_default=".8"
+ simple_percent_min="20"
+ simple_percent_max="100"
+ camera_distance="1.8"
+ camera_angle="30"
+ camera_elevation="-.3">
+ <param_driver>
+ <driven
+ id="615"
+ min1="0"
+ max1=".9"
+ max2="1"
+ min2="1" />
+
+ <driven
+ id="1018"
+ min1="0"
+ max1=".9"
+ max2="1"
+ min2="1" />
+
+ <driven
+ id="1036"
+ min1="0"
+ max1=".9"
+ max2="1"
+ min2="1" />
+
+ <driven
+ id="793"
+ min1=".9"
+ max1="1"
+ max2="1"
+ min2="1" />
+
+ <driven
+ id="915"
+ min1="0"
+ max1=".882"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="661" />
+ <param
+ id="800"
+ group="0"
+ wearable="shirt"
+ edit_group="shirt"
+ edit_group_order="1"
+ name="Sleeve Length"
+ show_simple="true"
+ label_min="Short"
+ label_max="Long"
+ value_min="0"
+ value_max="1"
+ value_default=".89"
+ simple_percent_min="15"
+ simple_percent_max="100"
+ camera_distance="1.2"
+ camera_angle="30"
+ camera_elevation=".2">
+ <param_driver>
+ <driven
+ id="600" />
+
+ <driven
+ id="1013" />
+
+ <driven
+ id="1029" />
+
+ <driven
+ id="900"
+ min1="0"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="774" />
- </param_driver>
- </param>
+ <param
+ id="801"
+ group="0"
+ wearable="shirt"
+ edit_group="shirt"
+ edit_group_order="2"
+ name="Shirt Bottom"
+ label_min="Short"
+ label_max="Long"
+ value_min="0"
+ value_max="1"
+ value_default="1"
+ camera_distance="1.2"
+ camera_angle="30"
+ camera_elevation=".2">
+ <param_driver>
+ <driven
+ id="601" />
+
+ <driven
+ id="1014" />
+
+ <driven
+ id="1030" />
+
+ <driven
+ id="901"
+ min1="0"
+ max1=".98"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <param
- id="773"
- group="0"
- wearable="shape"
- edit_group="shape_head"
- edit_group_order="4.5"
- name="Head Length"
- label_min="Flat Head"
- label_max="Long Head"
- value_min="0"
- value_max="1"
- value_default=".5"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="75">
- <param_driver>
- <driven
- id="770" />
+ <param
+ id="802"
+ group="0"
+ wearable="shirt"
+ edit_group="shirt"
+ edit_group_order="3"
+ name="Collar Front"
+ show_simple="true"
+ label_min="Low"
+ label_max="High"
+ value_min="0"
+ value_max="1"
+ value_default=".78"
+ simple_percent_min="40"
+ simple_percent_max="100"
+ camera_distance="1.2"
+ camera_angle="15"
+ camera_elevation=".2">
+ <param_driver>
+ <driven
+ id="602" />
+
+ <driven
+ id="1015" />
+
+ <driven
+ id="1031" />
+
+ <driven
+ id="902"
+ min1="0"
+ max1=".98"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="771" />
+ <param
+ id="781"
+ group="0"
+ wearable="shirt"
+ edit_group="shirt"
+ edit_group_order="3.1"
+ name="Collar Back"
+ label_min="Low"
+ label_max="High"
+ value_min="0"
+ value_max="1"
+ value_default=".78"
+ camera_distance="1.2"
+ camera_angle="195"
+ camera_elevation=".2">
+ <param_driver>
+ <driven
+ id="778" />
+
+ <driven
+ id="1016" />
+
+ <driven
+ id="1032" />
+
+ <driven
+ id="903"
+ min1="0"
+ max1=".98"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="772" />
- </param_driver>
- </param>
+ <param
+ id="150"
+ group="0"
+ wearable="skin"
+ edit_group="skin_bodydetail"
+ name="Body Definition"
+ label_min="Less"
+ label_max="More"
+ value_min="0"
+ value_max="1"
+ value_default="0"
+ camera_distance="1.4"
+ camera_elevation="-.2">
+ <param_driver>
+ <driven
+ id="125" />
+
+ <driven
+ id="126" />
+
+ <driven
+ id="160" />
+
+ <driven
+ id="161" />
+
+ <driven
+ id="874" />
+
+ <driven
+ id="878" />
+
+ </param_driver>
+ </param>
- <param
- id="682"
- group="0"
- wearable="shape"
- edit_group="shape_head"
- edit_group_order="1"
- name="Head Size"
- label="Head Size"
- label_min="Small Head"
- label_max="Big Head"
- show_simple="true"
- value_min="0"
- value_max="1"
- value_default=".5"
- camera_elevation=".1"
- camera_distance=".5">
- <param_driver>
- <driven
- id="679" />
+ <param
+ id="775"
+ group="0"
+ wearable="skin"
+ edit_group="skin_bodydetail"
+ name="Body Freckles"
+ label_min="Less Freckles"
+ label_max="More Freckles"
+ value_min="0"
+ value_max="1"
+ value_default="0"
+ camera_distance="1.4"
+ camera_elevation="-.2">
+ <param_driver>
+ <driven
+ id="776" />
+
+ <driven
+ id="777" />
+ </param_driver>
+ </param>
- <driven
- id="694" />
+ <param
+ id="162"
+ group="0"
+ wearable="skin"
+ edit_group="skin_facedetail"
+ edit_group_order="1"
+ name="Facial Definition"
+ label_min="Less"
+ label_max="More"
+ value_min="0"
+ value_max="1"
+ camera_distance=".3"
+ camera_elevation=".07"
+ value_default="0">
+ <param_driver>
+ <driven
+ id="158" />
+
+ <driven
+ id="159" />
+
+ <driven
+ id="873" />
+ </param_driver>
+ </param>
- <driven
- id="680" />
+ <param
+ id="163"
+ group="0"
+ wearable="skin"
+ edit_group="skin_facedetail"
+ edit_group_order="3"
+ name="Wrinkles"
+ label_min="Less"
+ label_max="More"
+ value_min="0"
+ value_max="1"
+ camera_distance=".3"
+ camera_elevation=".07"
+ value_default="0">
+ <param_driver>
+ <!--<driven
+ id="128" />-->
+ <driven
+ id="118" />
+ </param_driver>
+ </param>
- <driven
- id="681" />
+ <param
+ id="505"
+ group="0"
+ wearable="shape"
+ edit_group="shape_mouth"
+ edit_group_order="3"
+ name="Lip Thickness"
+ label_min="Thin Lips"
+ label_max="Fat Lips"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_distance=".3"
+ camera_elevation=".04"
+ camera_angle="20">
+ <param_driver>
+ <driven
+ id="26"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="28"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="655" />
- </param_driver>
- </param>
+ <param
+ id="799"
+ group="0"
+ wearable="shape"
+ edit_group="shape_mouth"
+ edit_group_order="3.2"
+ name="Lip Ratio"
+ label="Lip Ratio"
+ show_simple="true"
+ label_min="More Upper Lip"
+ label_max="More Lower Lip"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_distance=".3"
+ camera_elevation=".04"
+ camera_angle="20">
+ <param_driver>
+ <driven
+ id="797"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="798"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <param
- id="690"
- group="0"
- wearable="shape"
- edit_group="shape_eyes"
- edit_group_order="1"
- name="Eye Size"
- label="Eye Size"
- label_min="Beady Eyes"
- label_max="Anime Eyes"
- value_min="0"
- value_max="1"
- value_default=".5"
- show_simple="true"
- camera_elevation=".1"
- camera_distance=".35">
- <param_driver>
- <driven
- id="686" />
+ <param
+ id="155"
+ group="0"
+ wearable="shape"
+ edit_group="shape_mouth"
+ edit_group_order="1"
+ name="Lip Width"
+ label="Lip Width"
+ label_min="Narrow Lips"
+ label_max="Wide Lips"
+ show_simple="true"
+ value_min="-0.9"
+ value_max="1.3"
+ camera_distance=".3"
+ camera_elevation=".04"
+ value_default="0">
+ <param_driver>
+ <driven
+ id="29" />
+
+ <driven
+ id="30" />
+ </param_driver>
+ </param>
- <driven
- id="687" />
+ <param
+ id="196"
+ group="0"
+ wearable="shape"
+ edit_group="shape_eyes"
+ edit_group_order="2"
+ name="Eye Spacing"
+ label="Eye Spacing"
+ label_min="Close Set Eyes"
+ label_max="Far Set Eyes"
+ show_simple="true"
+ value_min="-2"
+ value_max="1"
+ value_default="0"
+ camera_elevation=".1"
+ camera_distance=".35"
+ camera_angle="5">
+ <param_driver>
+ <driven
+ id="194" />
+
+ <driven
+ id="195" />
+ </param_driver>
+ </param>
- <driven
- id="695" />
+ <param
+ id="769"
+ group="0"
+ wearable="shape"
+ edit_group="shape_eyes"
+ edit_group_order="4.5"
+ name="Eye Depth"
+ label_min="Sunken Eyes"
+ label_max="Bugged Eyes"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_elevation=".1"
+ camera_distance=".3"
+ camera_angle="75">
+ <param_driver>
+ <driven
+ id="767" />
+
+ <driven
+ id="768" />
+ </param_driver>
+ </param>
- <driven
- id="688" />
+ <param
+ id="198"
+ group="0"
+ wearable="shoes"
+ edit_group="shoes"
+ edit_group_order="2"
+ name="Heel Height"
+ label_min="Low Heels"
+ label_max="High Heels"
+ value_min="0"
+ value_max="1"
+ value_default="0"
+ camera_angle="45"
+ camera_distance=".8"
+ camera_elevation="-1">
+ <param_driver>
+ <driven
+ id="197" />
+
+ <driven
+ id="500" />
+ </param_driver>
+ </param>
- <driven
- id="691" />
+ <param
+ id="513"
+ group="0"
+ wearable="shoes"
+ edit_group="shoes"
+ edit_group_order="3"
+ name="Heel Shape"
+ label_min="Pointy Heels"
+ label_max="Thick Heels"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_angle="45"
+ camera_distance="1.5"
+ camera_elevation="-1">
+ <param_driver>
+ <driven
+ id="509"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="510"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="689" />
- </param_driver>
- </param>
+ <param
+ id="514"
+ group="0"
+ wearable="shoes"
+ edit_group="shoes"
+ edit_group_order="4"
+ name="Toe Shape"
+ label_min="Pointy"
+ label_max="Square"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_angle="5"
+ camera_distance=".8"
+ camera_elevation="-.8">
+ <param_driver>
+ <driven
+ id="511"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="512"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <param
- id="752"
- group="0"
- sex="male"
- wearable="hair"
- edit_group="hair_facial"
- edit_group_order="1"
- name="Hair Thickness"
- label_min="5 O'Clock Shadow"
- label_max="Bushy Hair"
- value_min="0"
- value_max="1"
- value_default=".5"
- camera_elevation="0"
- camera_distance=".28">
- <param_driver>
- <driven
- id="751"
- min1="0"
- max1="0"
- max2="0"
- min2=".2" />
-
- <driven
- id="1012"
- min1="0"
- max1="0"
- max2=".2"
- min2=".6" />
-
- <driven
- id="400"
- min1=".2"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
-
- <param
- id="763"
- group="0"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="1"
- name="Hair Volume"
- show_simple="true"
- label_min="Less Volume"
- label_max="More Volume"
- value_min="0"
- value_max="1"
- value_default=".55"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="20">
- <param_driver>
- <driven
- id="761"
- min1="0"
- max1="0"
- max2="0"
- min2=".5" />
+ <param
+ id="503"
+ group="0"
+ wearable="shoes"
+ edit_group="shoes"
+ edit_group_order="6"
+ name="Platform Height"
+ label_min="Low Platforms"
+ label_max="High Platforms"
+ value_min="0"
+ value_max="1"
+ value_default="0"
+ camera_angle="45"
+ camera_distance=".5"
+ camera_elevation="-1">
+ <param_driver>
+ <driven
+ id="501" />
+
+ <driven
+ id="502" />
+ </param_driver>
+ </param>
- <driven
- id="180"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
+ <param
+ id="193"
+ group="0"
+ wearable="shape"
+ edit_group="shape_head"
+ edit_group_order="3"
+ name="Head Shape"
+ label="Head Shape"
+ label_min="More Square"
+ label_max="More Round"
+ show_simple="true"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_driver>
+ <driven
+ id="188"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="642"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="189"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+
+ <driven
+ id="643"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <param
- id="834"
- group="0"
- wearable="jacket"
- edit_group="colorpicker"
- name="jacket_red"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_driver>
- <driven
- id="809"
- min1="0"
- max1="1"
- max2="1"
- min2="1" />
+ <param
+ id="157"
+ group="0"
+ wearable="shape"
+ edit_group="shape_torso"
+ edit_group_order="13"
+ name="Belly Size"
+ label_min="Small"
+ label_max="Big"
+ value_min="0"
+ value_max="1"
+ value_default="0"
+ camera_distance="1.4"
+ camera_angle="30"
+ camera_elevation=".2">
+ <param_driver>
+ <driven
+ id="104" />
+
+ <driven
+ id="156" />
+
+ <driven
+ id="849" />
+ </param_driver>
+ </param>
- <driven
- id="831"
- min1="0"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
+ <param
+ id="637"
+ group="0"
+ wearable="shape"
+ edit_group="shape_body"
+ edit_group_order="3"
+ name="Body Fat"
+ label_min="Less Body Fat"
+ label_max="More Body Fat"
+ value_min="0"
+ value_max="1"
+ value_default="0"
+ camera_distance="1.8">
+ <param_driver>
+ <driven
+ id="633" />
+
+ <driven
+ id="634" />
+
+ <driven
+ id="635" />
+
+ <driven
+ id="851" />
+ </param_driver>
+ </param>
- <param
- id="835"
- group="0"
- wearable="jacket"
- edit_group="colorpicker"
- name="jacket_green"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_driver>
- <driven
- id="810"
- min1="0"
- max1="1"
- max2="1"
- min2="1" />
+ <param
+ id="130"
+ group="0"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="8"
+ name="Front Fringe"
+ label_min="Short"
+ label_max="Long"
+ value_min="0"
+ value_max="1"
+ value_default=".45"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_driver>
+ <driven
+ id="144"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="145"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="832"
- min1="0"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
+ <param
+ id="131"
+ group="0"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="9"
+ name="Side Fringe"
+ label_min="Short"
+ label_max="Long"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="90">
+ <param_driver>
+ <driven
+ id="146"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="147"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <param
- id="836"
- group="0"
- wearable="jacket"
- edit_group="colorpicker"
- name="jacket_blue"
- value_min="0"
- value_max="1"
- value_default="1">
- <param_driver>
- <driven
- id="811"
- min1="0"
- max1="1"
- max2="1"
- min2="1" />
+ <param
+ id="132"
+ group="0"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="10"
+ name="Back Fringe"
+ label_min="Short"
+ label_max="Long"
+ value_min="0"
+ value_max="1"
+ value_default=".39"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="160">
+ <param_driver>
+ <driven
+ id="148"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="149"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="833"
- min1="0"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
+ <param
+ id="133"
+ group="0"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="2"
+ name="Hair Front"
+ label_min="Short"
+ label_max="Long"
+ value_min="0"
+ value_max="1"
+ value_default=".25"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_driver>
+ <driven
+ id="172"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="171"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <param
- id="785"
- group="0"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="14.6"
- name="Pigtails"
- show_simple="true"
- label_min="Short Pigtails"
- label_max="Long Pigtails"
- value_min="0"
- value_max="1"
- value_default="0"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="15">
- <param_driver>
- <driven
- id="782"
- min1="0"
- max1=".10"
- max2=".10"
- min2=".5" />
-
- <driven
- id="783"
- min1=".10"
- max1=".5"
- max2=".5"
- min2=".75" />
-
- <driven
- id="790"
- min1=".5"
- max1=".75"
- max2=".75"
- min2="1" />
-
- <driven
- id="784"
- min1=".75"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
-
- <param
- id="789"
- group="0"
- wearable="hair"
- edit_group="hair_style"
- edit_group_order="14.7"
- name="Ponytail"
- label_min="Short Ponytail"
- label_max="Long Ponytail"
- value_min="0"
- value_max="1"
- value_default="0"
- camera_elevation=".1"
- camera_distance=".5"
- camera_angle="180">
- <param_driver>
- <driven
- id="786"
- min1="0"
- max1=".10"
- max2=".10"
- min2=".66" />
-
- <driven
- id="787"
- min1=".10"
- max1=".66"
- max2=".66"
- min2="1" />
-
- <driven
- id="788"
- min1=".66"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
-
- <param
- id="795"
- group="0"
- name="Butt Size"
- label="Butt Size"
- wearable="shape"
- edit_group="shape_legs"
- edit_group_order="4"
- label_min="Flat Butt"
- label_max="Big Butt"
- value_min="0"
- value_max="1"
- value_default=".25"
- camera_angle="180"
- camera_distance=".6">
- <param_driver>
- <driven
- id="867"
- min1="0"
- max1="0"
- max2="0"
- min2=".3" />
-
- <driven
- id="794"
- min1="0"
- max1="0"
- max2="0"
- min2=".3" />
-
- <driven
- id="151"
- min1=".3"
- max1="1"
- max2="1"
- min2="1" />
-
- <driven
- id="852"
- min1=".3"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
-
- <param
- id="841"
- group="0"
- name="Bowed_Legs"
- label="Knee Angle"
- wearable="shape"
- edit_group_order="5.5"
- edit_group="shape_legs"
- label_min="Knock Kneed"
- label_max="Bow Legged"
- value_min="-1"
- value_max="1"
- value_default="0"
- camera_distance="1.3"
- camera_elevation="-.5">
- <param_driver>
- <driven
- id="853" />
+ <param
+ id="134"
+ group="0"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="3"
+ name="Hair Sides"
+ label_min="Short"
+ label_max="Long"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="90">
+ <param_driver>
+ <driven
+ id="174"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="173"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="847" />
- </param_driver>
- </param>
+ <param
+ id="135"
+ group="0"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="4"
+ name="Hair Back"
+ show_simple="true"
+ label_min="Short"
+ label_max="Long"
+ value_min="0"
+ value_max="1"
+ value_default=".55"
+ camera_elevation="-.1"
+ camera_distance=".8"
+ camera_angle="160">
+ <param_driver>
+ <driven
+ id="176"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="175"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <param
- id="753"
- group="0"
- name="Saddlebags"
- label="Saddle Bags"
- wearable="shape"
- edit_group="shape_legs"
- edit_group_order="5"
- label_min="Less Saddle"
- label_max="More Saddle"
- value_min="-0.5"
- value_max="3"
- value_default="0"
- camera_angle="0"
- camera_distance="1.2">
- <param_driver>
- <driven
- id="850" />
+ <param
+ id="136"
+ group="0"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="11.5"
+ name="Hair Sweep"
+ label_min="Sweep Forward"
+ label_max="Sweep Back"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="90">
+ <param_driver>
+ <driven
+ id="179"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="178"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="854" />
- </param_driver>
- </param>
+ <param
+ id="137"
+ group="0"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="16"
+ name="Hair Tilt"
+ label_min="Left"
+ label_max="Right"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="0">
+ <param_driver>
+ <driven
+ id="190"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="191"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <param
- id="676"
- group="0"
- name="Love_Handles"
- label="Love Handles"
- wearable="shape"
- edit_group="shape_torso"
- edit_group_order="12"
- label_min="Less Love"
- label_max="More Love"
- value_min="-1"
- value_max="2"
- value_default="0"
- camera_elevation=".3"
- camera_distance=".9">
- <param_driver>
- <driven
- id="855" />
+ <param
+ id="608"
+ group="0"
+ wearable="jacket"
+ edit_group="jacket"
+ edit_group_order="2"
+ name="bottom length lower"
+ label="Jacket Length"
+ label_min="Short"
+ label_max="Long"
+ value_min="0"
+ value_max="1"
+ value_default=".8"
+ camera_distance="1.4"
+ camera_angle="30"
+ camera_elevation=".2">
+ <param_driver>
+ <driven
+ id="620" />
+
+ <driven
+ id="1025" />
+
+ <driven
+ id="1037" />
+
+ <driven
+ id="621" />
+
+ <driven
+ id="1027" />
+
+ <driven
+ id="1033" />
+ </param_driver>
+ </param>
- <driven
- id="856" />
- </param_driver>
- </param>
+ <param
+ id="609"
+ group="0"
+ wearable="jacket"
+ edit_group="jacket"
+ edit_group_order="4"
+ name="open jacket"
+ label="Open Front"
+ label_min="Open"
+ label_max="Closed"
+ value_min="0"
+ value_max="1"
+ value_default=".2"
+ camera_distance="1.4"
+ camera_angle="30"
+ camera_elevation=".2">
+ <param_driver>
+ <driven
+ id="622" />
+
+ <driven
+ id="1026" />
+
+ <driven
+ id="1038" />
+
+ <driven
+ id="623" />
+
+ <driven
+ id="1028" />
+
+ <driven
+ id="1034" />
+ </param_driver>
+ </param>
- <param
- id="863"
- group="0"
- name="skirt_looseness"
- label="Skirt Fit"
- show_simple="true"
- clothing_morph="true"
- wearable="skirt"
- edit_group_order="2"
- edit_group="skirt"
- label_min="Tight Skirt"
- label_max="Poofy Skirt"
- value_min="0"
- value_max="1"
- value_default=".333"
- camera_distance="1.3"
- camera_elevation="-.5">
- <param_driver>
- <driven
- id="866"
- min1="0"
- max1="0"
- max2="0"
- min2=".2" />
-
- <driven
- id="846"
- min1="0"
- max1=".5"
- max2=".5"
- min2="1" />
-
- <driven
- id="845"
- min1=".5"
- max1="1"
- max2="1"
- min2="1" />
- </param_driver>
- </param>
-
- <param
- id="119"
- group="0"
- wearable="hair"
- edit_group="hair_eyebrows"
- edit_group_order="1"
- name="Eyebrow Size"
- show_simple="true"
- label_min="Thin Eyebrows"
- label_max="Bushy Eyebrows"
- value_min="0"
- value_max="1"
- value_default="0.5"
- camera_elevation=".1"
- camera_distance=".3">
- <param_driver>
- <driven
- id="1000" />
+ <param
+ id="105"
+ group="0"
+ sex="female"
+ wearable="shape"
+ edit_group="shape_torso"
+ edit_group_order="6"
+ name="Breast Size"
+ label_min="Small"
+ label_max="Large"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_elevation=".3"
+ camera_distance="1.2"
+ camera_angle="30">
+ <param_driver>
+ <driven
+ id="843"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".01" />
+
+ <driven
+ id="627"
+ min1="0"
+ max1="0.01"
+ max2="0.01"
+ min2=".5" />
+
+ <driven
+ id="626"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="1001" />
- </param_driver>
- </param>
+ <param
+ id="629"
+ group="0"
+ wearable="shape"
+ edit_group="shape_head"
+ edit_group_order="6"
+ name="Forehead Angle"
+ label_min="More Vertical"
+ label_max="More Sloped"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="70">
+ <param_driver>
+ <driven
+ id="630"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="644"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="631"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+
+ <driven
+ id="645"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <param
- id="750"
- group="0"
- wearable="hair"
- edit_group="hair_eyebrows"
- edit_group_order="2"
- name="Eyebrow Density"
- label_min="Sparse"
- label_max="Dense"
- value_min="0"
- value_max="1"
- value_default="0.7"
- camera_elevation=".1"
- camera_distance=".3">
- <param_driver>
- <driven
- id="1002" />
+ <param
+ id="646"
+ group="0"
+ name="Egg_Head"
+ label="Egg Head"
+ wearable="shape"
+ edit_group="shape_head"
+ edit_group_order="4"
+ label_min="Chin Heavy"
+ label_max="Forehead Heavy"
+ show_simple="true"
+ value_min="-1.3"
+ value_max="1"
+ value_default="0"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_driver>
+ <driven
+ id="640" />
+
+ <driven
+ id="186" />
+ </param_driver>
+ </param>
- <driven
- id="1003" />
- </param_driver>
- </param>
+ <param
+ id="647"
+ group="0"
+ name="Squash_Stretch_Head"
+ label="Head Stretch"
+ wearable="shape"
+ edit_group="shape_head"
+ edit_group_order="2"
+ show_simple="true"
+ label_min="Squash Head"
+ label_max="Stretch Head"
+ value_min="-0.5"
+ value_max="1"
+ value_default="0"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_driver>
+ <driven
+ id="641" />
+
+ <driven
+ id="187" />
+ </param_driver>
+ </param>
- <param
- id="166"
- sex="male"
- group="0"
- wearable="hair"
- edit_group="hair_facial"
- edit_group_order="2"
- name="Sideburns"
- show_simple="true"
- label_min="Short Sideburns"
- label_max="Mutton Chops"
- value_min="0"
- value_max="1"
- value_default="0.0"
- camera_elevation=".1"
- camera_distance=".3"
- camera_angle="30">
- <param_driver>
- <driven
- id="1004" />
+ <param
+ id="649"
+ group="0"
+ sex="female"
+ wearable="shape"
+ edit_group="shape_torso"
+ edit_group_order="1.1"
+ name="Torso Muscles"
+ label="Torso Muscles"
+ show_simple="true"
+ label_min="Less Muscular"
+ label_max="More Muscular"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_elevation=".1"
+ camera_distance="1"
+ camera_angle="15">
+ <param_driver>
+ <driven
+ id="648"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="106"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="1005" />
- </param_driver>
- </param>
+ <param
+ id="678"
+ group="0"
+ sex="male"
+ wearable="shape"
+ edit_group="shape_torso"
+ edit_group_order="1"
+ name="Torso Muscles"
+ show_simple="true"
+ label_min="Less Muscular"
+ label_max="More Muscular"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_elevation=".1"
+ camera_distance="1.2"
+ camera_angle="0">
+ <param_driver>
+ <driven
+ id="677"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="106"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <param
- id="167"
- sex="male"
- group="0"
- wearable="hair"
- edit_group="hair_facial"
- edit_group_order="3"
- name="Moustache"
- show_simple="true"
- label_min="Chaplin"
- label_max="Handlebars"
- value_min="0"
- value_max="1"
- value_default="0.0"
- camera_elevation=".1"
- camera_distance=".3"
- camera_angle="30">
- <param_driver>
- <driven
- id="1006" />
+ <param
+ id="652"
+ group="0"
+ wearable="shape"
+ edit_group="shape_legs"
+ edit_group_order="1"
+ name="Leg Muscles"
+ label_min="Less Muscular"
+ label_max="More Muscular"
+ show_simple="true"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_distance="1.3"
+ camera_elevation="-.5"
+ camera_angle="15">
+ <param_driver>
+ <driven
+ id="651"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="152"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="1007" />
- </param_driver>
- </param>
+ <param
+ id="80"
+ name="male"
+ group="0"
+ edit_group="dummy"
+ wearable="shape"
+ value_min="0"
+ value_max="1">
+ <param_driver>
+ <driven
+ id="32" />
+
+ <driven
+ id="153" />
+
+ <driven
+ id="40" />
+
+ <driven
+ id="100" />
+
+ <driven
+ id="857" />
+ </param_driver>
+ </param>
- <param
- id="168"
- sex="male"
- group="0"
- wearable="hair"
- edit_group="hair_facial"
- edit_group_order="5"
- name="Soulpatch"
- show_simple="true"
- label_min="Less soul"
- label_max="More soul"
- value_min="0"
- value_max="1"
- value_default="0.0"
- camera_elevation="-.1"
- camera_distance=".3"
- camera_angle="0">
- <param_driver>
- <driven
- id="1008" />
+ <param
+ id="659"
+ group="0"
+ wearable="shape"
+ edit_group="shape_mouth"
+ edit_group_order="5"
+ name="Mouth Corner"
+ label_min="Corner Down"
+ label_max="Corner Up"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_elevation="0"
+ camera_distance=".28">
+ <param_driver>
+ <driven
+ id="658"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="657"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="1009" />
- </param_driver>
- </param>
+ <param
+ id="662"
+ group="0"
+ wearable="shape"
+ edit_group="shape_head"
+ edit_group_order="5"
+ name="Face Shear"
+ label_min="Shear Right Up"
+ label_max="Shear Left Up"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_elevation=".1"
+ camera_distance=".5">
+ <param_driver>
+ <driven
+ id="660" />
+
+ <driven
+ id="661" />
+
+ <driven
+ id="774" />
+ </param_driver>
+ </param>
- <param
- id="169"
- sex="male"
- group="0"
- wearable="hair"
- edit_group="hair_facial"
- edit_group_order="4"
- name="Chin Curtains"
- show_simple="true"
- label_min="Less Curtains"
- label_max="More Curtains"
- value_min="0"
- value_max="1"
- value_default="0.0"
- camera_elevation="-.1"
- camera_distance=".3"
- camera_angle="45">
- <param_driver>
- <driven
- id="1010" />
+ <param
+ id="773"
+ group="0"
+ wearable="shape"
+ edit_group="shape_head"
+ edit_group_order="4.5"
+ name="Head Length"
+ label_min="Flat Head"
+ label_max="Long Head"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="75">
+ <param_driver>
+ <driven
+ id="770" />
+
+ <driven
+ id="771" />
+
+ <driven
+ id="772" />
+ </param_driver>
+ </param>
- <driven
- id="1011" />
- </param_driver>
- </param>
+ <param
+ id="682"
+ group="0"
+ wearable="shape"
+ edit_group="shape_head"
+ edit_group_order="1"
+ name="Head Size"
+ label="Head Size"
+ label_min="Small Head"
+ label_max="Big Head"
+ show_simple="true"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_elevation=".1"
+ camera_distance=".5">
+ <param_driver>
+ <driven
+ id="679" />
+
+ <driven
+ id="694" />
+
+ <driven
+ id="680" />
+
+ <driven
+ id="681" />
+
+ <driven
+ id="655" />
+ </param_driver>
+ </param>
- <param
- id="606"
- group="0"
- wearable="jacket"
- edit_group="jacket"
- edit_group_order="1"
- name="Sleeve Length"
- label_min="Short"
- label_max="Long"
- value_min="0"
- value_max="1"
- value_default=".8"
- camera_distance="1.2"
- camera_angle="30"
- camera_elevation=".2">
- <param_driver>
- <driven
- id="1019" />
+ <param
+ id="690"
+ group="0"
+ wearable="shape"
+ edit_group="shape_eyes"
+ edit_group_order="1"
+ name="Eye Size"
+ label="Eye Size"
+ label_min="Beady Eyes"
+ label_max="Anime Eyes"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ show_simple="true"
+ camera_elevation=".1"
+ camera_distance=".35">
+ <param_driver>
+ <driven
+ id="686" />
+
+ <driven
+ id="687" />
+
+ <driven
+ id="695" />
+
+ <driven
+ id="688" />
+
+ <driven
+ id="691" />
+
+ <driven
+ id="689" />
+ </param_driver>
+ </param>
- <driven
- id="1039" />
+ <param
+ id="752"
+ group="0"
+ sex="male"
+ wearable="hair"
+ edit_group="hair_facial"
+ edit_group_order="1"
+ name="Hair Thickness"
+ label_min="5 O'Clock Shadow"
+ label_max="Bushy Hair"
+ value_min="0"
+ value_max="1"
+ value_default=".5"
+ camera_elevation="0"
+ camera_distance=".28">
+ <param_driver>
+ <driven
+ id="751"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".2" />
+
+ <driven
+ id="1012"
+ min1="0"
+ max1="0"
+ max2=".2"
+ min2=".6" />
+
+ <driven
+ id="400"
+ min1=".2"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="1020" />
- </param_driver>
- </param>
+ <param
+ id="763"
+ group="0"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="1"
+ name="Hair Volume"
+ show_simple="true"
+ label_min="Less Volume"
+ label_max="More Volume"
+ value_min="0"
+ value_max="1"
+ value_default=".55"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ <param_driver>
+ <driven
+ id="761"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".5" />
+
+ <driven
+ id="180"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <param
- id="607"
- group="0"
- wearable="jacket"
- edit_group="jacket"
- edit_group_order="3"
- name="Collar Front"
- label_min="Low"
- label_max="High"
- value_min="0"
- value_max="1"
- value_default=".8"
- camera_distance="1.2"
- camera_angle="15"
- camera_elevation=".2">
- <param_driver>
- <driven
- id="1021" />
+ <param
+ id="834"
+ group="0"
+ wearable="jacket"
+ edit_group="colorpicker"
+ name="jacket_red"
+ value_min="0"
+ value_max="1"
+ value_default="1">
+ <param_driver>
+ <driven
+ id="809"
+ min1="0"
+ max1="1"
+ max2="1"
+ min2="1" />
+
+ <driven
+ id="831"
+ min1="0"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="1040" />
+ <param
+ id="835"
+ group="0"
+ wearable="jacket"
+ edit_group="colorpicker"
+ name="jacket_green"
+ value_min="0"
+ value_max="1"
+ value_default="1">
+ <param_driver>
+ <driven
+ id="810"
+ min1="0"
+ max1="1"
+ max2="1"
+ min2="1" />
+
+ <driven
+ id="832"
+ min1="0"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="1022" />
- </param_driver>
- </param>
+ <param
+ id="836"
+ group="0"
+ wearable="jacket"
+ edit_group="colorpicker"
+ name="jacket_blue"
+ value_min="0"
+ value_max="1"
+ value_default="1">
+ <param_driver>
+ <driven
+ id="811"
+ min1="0"
+ max1="1"
+ max2="1"
+ min2="1" />
+
+ <driven
+ id="833"
+ min1="0"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <param
- id="780"
- group="0"
- wearable="jacket"
- edit_group="jacket"
- edit_group_order="3.5"
- name="Collar Back"
- label_min="Low"
- label_max="High"
- value_min="0"
- value_max="1"
- value_default=".8"
- camera_distance="1.2"
- camera_angle="195"
- camera_elevation=".2">
- <param_driver>
- <driven
- id="1023" />
+ <param
+ id="785"
+ group="0"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="14.6"
+ name="Pigtails"
+ show_simple="true"
+ label_min="Short Pigtails"
+ label_max="Long Pigtails"
+ value_min="0"
+ value_max="1"
+ value_default="0"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="15">
+ <param_driver>
+ <driven
+ id="782"
+ min1="0"
+ max1=".10"
+ max2=".10"
+ min2=".5" />
+
+ <driven
+ id="783"
+ min1=".10"
+ max1=".5"
+ max2=".5"
+ min2=".75" />
+
+ <driven
+ id="790"
+ min1=".5"
+ max1=".75"
+ max2=".75"
+ min2="1" />
+
+ <driven
+ id="784"
+ min1=".75"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="1041" />
+ <param
+ id="789"
+ group="0"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="14.7"
+ name="Ponytail"
+ label_min="Short Ponytail"
+ label_max="Long Ponytail"
+ value_min="0"
+ value_max="1"
+ value_default="0"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="180">
+ <param_driver>
+ <driven
+ id="786"
+ min1="0"
+ max1=".10"
+ max2=".10"
+ min2=".66" />
+
+ <driven
+ id="787"
+ min1=".10"
+ max1=".66"
+ max2=".66"
+ min2="1" />
+
+ <driven
+ id="788"
+ min1=".66"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <driven
- id="1024" />
- </param_driver>
- </param>
+ <param
+ id="795"
+ group="0"
+ name="Butt Size"
+ label="Butt Size"
+ wearable="shape"
+ edit_group="shape_legs"
+ edit_group_order="4"
+ label_min="Flat Butt"
+ label_max="Big Butt"
+ value_min="0"
+ value_max="1"
+ value_default=".25"
+ camera_angle="180"
+ camera_distance=".6">
+ <param_driver>
+ <driven
+ id="867"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".3" />
+
+ <driven
+ id="794"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".3" />
+
+ <driven
+ id="151"
+ min1=".3"
+ max1="1"
+ max2="1"
+ min2="1" />
+
+ <driven
+ id="852"
+ min1=".3"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <param
- id="603"
- group="0"
- wearable="undershirt"
- edit_group="undershirt"
- edit_group_order="1"
- name="Sleeve Length"
- label_min="Short"
- label_max="Long"
- value_min=".01"
- value_max="1"
- value_default=".4"
- camera_distance="1.2"
- camera_angle="30"
- camera_elevation=".2">
- <param_driver>
- <driven
- id="1042" />
+ <param
+ id="841"
+ group="0"
+ name="Bowed_Legs"
+ label="Knee Angle"
+ wearable="shape"
+ edit_group_order="5.5"
+ edit_group="shape_legs"
+ label_min="Knock Kneed"
+ label_max="Bow Legged"
+ value_min="-1"
+ value_max="1"
+ value_default="0"
+ camera_distance="1.3"
+ camera_elevation="-.5">
+ <param_driver>
+ <driven
+ id="853" />
+
+ <driven
+ id="847" />
+ </param_driver>
+ </param>
- <driven
- id="1043" />
- </param_driver>
- </param>
+ <param
+ id="753"
+ group="0"
+ name="Saddlebags"
+ label="Saddle Bags"
+ wearable="shape"
+ edit_group="shape_legs"
+ edit_group_order="5"
+ label_min="Less Saddle"
+ label_max="More Saddle"
+ value_min="-0.5"
+ value_max="3"
+ value_default="0"
+ camera_angle="0"
+ camera_distance="1.2">
+ <param_driver>
+ <driven
+ id="850" />
+
+ <driven
+ id="854" />
+ </param_driver>
+ </param>
- <param
- id="604"
- group="0"
- wearable="undershirt"
- edit_group="undershirt"
- edit_group_order="2"
- name="Bottom"
- label_min="Short"
- label_max="Long"
- value_min="0"
- value_max="1"
- value_default=".85"
- camera_distance="1.2"
- camera_angle="30"
- camera_elevation=".2">
- <param_driver>
- <driven
- id="1044" />
+ <param
+ id="676"
+ group="0"
+ name="Love_Handles"
+ label="Love Handles"
+ wearable="shape"
+ edit_group="shape_torso"
+ edit_group_order="12"
+ label_min="Less Love"
+ label_max="More Love"
+ value_min="-1"
+ value_max="2"
+ value_default="0"
+ camera_elevation=".3"
+ camera_distance=".9">
+ <param_driver>
+ <driven
+ id="855" />
+
+ <driven
+ id="856" />
+ </param_driver>
+ </param>
- <driven
- id="1045" />
- </param_driver>
- </param>
+ <param
+ id="863"
+ group="0"
+ name="skirt_looseness"
+ label="Skirt Fit"
+ show_simple="true"
+ clothing_morph="true"
+ wearable="skirt"
+ edit_group_order="2"
+ edit_group="skirt"
+ label_min="Tight Skirt"
+ label_max="Poofy Skirt"
+ value_min="0"
+ value_max="1"
+ value_default=".333"
+ camera_distance="1.3"
+ camera_elevation="-.5">
+ <param_driver>
+ <driven
+ id="866"
+ min1="0"
+ max1="0"
+ max2="0"
+ min2=".2" />
+
+ <driven
+ id="846"
+ min1="0"
+ max1=".5"
+ max2=".5"
+ min2="1" />
+
+ <driven
+ id="845"
+ min1=".5"
+ max1="1"
+ max2="1"
+ min2="1" />
+ </param_driver>
+ </param>
- <param
- id="605"
- group="0"
- wearable="undershirt"
- edit_group="undershirt"
- edit_group_order="3"
- name="Collar Front"
- label_min="Low"
- label_max="High"
- value_min="0"
- value_max="1"
- value_default=".84"
- camera_distance=".8"
- camera_angle="15"
- camera_elevation=".2">
- <param_driver>
- <driven
- id="1046" />
+ <param
+ id="119"
+ group="0"
+ wearable="hair"
+ edit_group="hair_eyebrows"
+ edit_group_order="1"
+ name="Eyebrow Size"
+ show_simple="true"
+ label_min="Thin Eyebrows"
+ label_max="Bushy Eyebrows"
+ value_min="0"
+ value_max="1"
+ value_default="0.5"
+ camera_elevation=".1"
+ camera_distance=".3">
+ <param_driver>
+ <driven
+ id="1000" />
+
+ <driven
+ id="1001" />
+ </param_driver>
+ </param>
- <driven
- id="1047" />
- </param_driver>
- </param>
+ <param
+ id="750"
+ group="0"
+ wearable="hair"
+ edit_group="hair_eyebrows"
+ edit_group_order="2"
+ name="Eyebrow Density"
+ label_min="Sparse"
+ label_max="Dense"
+ value_min="0"
+ value_max="1"
+ value_default="0.7"
+ camera_elevation=".1"
+ camera_distance=".3">
+ <param_driver>
+ <driven
+ id="1002" />
+
+ <driven
+ id="1003" />
+ </param_driver>
+ </param>
- <param
- id="779"
- group="0"
- wearable="undershirt"
- edit_group="undershirt"
- edit_group_order="4"
- name="Collar Back"
- label_min="Low"
- label_max="High"
- value_min="0"
- value_max="1"
- value_default=".84"
- camera_distance=".8"
- camera_angle="195"
- camera_elevation=".2">
- <param_driver>
- <driven
- id="1048" />
+ <param
+ id="166"
+ sex="male"
+ group="0"
+ wearable="hair"
+ edit_group="hair_facial"
+ edit_group_order="2"
+ name="Sideburns"
+ show_simple="true"
+ label_min="Short Sideburns"
+ label_max="Mutton Chops"
+ value_min="0"
+ value_max="1"
+ value_default="0.0"
+ camera_elevation=".1"
+ camera_distance=".3"
+ camera_angle="30">
+ <param_driver>
+ <driven
+ id="1004" />
+
+ <driven
+ id="1005" />
+ </param_driver>
+ </param>
- <driven
- id="1049" />
- </param_driver>
- </param>
+ <param
+ id="167"
+ sex="male"
+ group="0"
+ wearable="hair"
+ edit_group="hair_facial"
+ edit_group_order="3"
+ name="Moustache"
+ show_simple="true"
+ label_min="Chaplin"
+ label_max="Handlebars"
+ value_min="0"
+ value_max="1"
+ value_default="0.0"
+ camera_elevation=".1"
+ camera_distance=".3"
+ camera_angle="30">
+ <param_driver>
+ <driven
+ id="1006" />
+
+ <driven
+ id="1007" />
+ </param_driver>
+ </param>
- <param
- id="617"
- group="0"
- wearable="socks"
- edit_group="socks"
- name="Socks Length"
- label_min="Short"
- label_max="Long"
- value_min="0"
- value_max="1"
- value_default="0.35"
- camera_distance=".95"
- camera_angle="30"
- camera_elevation="-.75">
- <param_driver>
- <driven
- id="1050" />
+ <param
+ id="168"
+ sex="male"
+ group="0"
+ wearable="hair"
+ edit_group="hair_facial"
+ edit_group_order="5"
+ name="Soulpatch"
+ show_simple="true"
+ label_min="Less soul"
+ label_max="More soul"
+ value_min="0"
+ value_max="1"
+ value_default="0.0"
+ camera_elevation="-.1"
+ camera_distance=".3"
+ camera_angle="0">
+ <param_driver>
+ <driven
+ id="1008" />
+
+ <driven
+ id="1009" />
+ </param_driver>
+ </param>
- <driven
- id="1051" />
- </param_driver>
- </param>
+ <param
+ id="169"
+ sex="male"
+ group="0"
+ wearable="hair"
+ edit_group="hair_facial"
+ edit_group_order="4"
+ name="Chin Curtains"
+ show_simple="true"
+ label_min="Less Curtains"
+ label_max="More Curtains"
+ value_min="0"
+ value_max="1"
+ value_default="0.0"
+ camera_elevation="-.1"
+ camera_distance=".3"
+ camera_angle="45">
+ <param_driver>
+ <driven
+ id="1010" />
+
+ <driven
+ id="1011" />
+ </param_driver>
+ </param>
- <param
- id="616"
- group="0"
- wearable="shoes"
- edit_group="shoes"
- edit_group_order="1"
- name="Shoe Height"
- label_min="Short"
- label_max="Tall"
- value_min="0"
- value_max="1"
- value_default="0.1"
- camera_distance="1.2"
- camera_angle="30"
- camera_elevation="-.75">
- <param_driver>
- <driven
- id="1052" />
+ <param
+ id="606"
+ group="0"
+ wearable="jacket"
+ edit_group="jacket"
+ edit_group_order="1"
+ name="Sleeve Length"
+ label_min="Short"
+ label_max="Long"
+ value_min="0"
+ value_max="1"
+ value_default=".8"
+ camera_distance="1.2"
+ camera_angle="30"
+ camera_elevation=".2">
+ <param_driver>
+ <driven
+ id="1019" />
+
+ <driven
+ id="1039" />
+
+ <driven
+ id="1020" />
+ </param_driver>
+ </param>
- <driven
- id="1053" />
- </param_driver>
- </param>
+ <param
+ id="607"
+ group="0"
+ wearable="jacket"
+ edit_group="jacket"
+ edit_group_order="3"
+ name="Collar Front"
+ label_min="Low"
+ label_max="High"
+ value_min="0"
+ value_max="1"
+ value_default=".8"
+ camera_distance="1.2"
+ camera_angle="15"
+ camera_elevation=".2">
+ <param_driver>
+ <driven
+ id="1021" />
+
+ <driven
+ id="1040" />
+
+ <driven
+ id="1022" />
+ </param_driver>
+ </param>
- <param
- id="619"
- group="0"
- wearable="underpants"
- edit_group="underpants"
- name="Pants Length"
- label_min="Short"
- label_max="Long"
- value_min="0"
- value_max="1"
- value_default=".3"
- camera_distance="1.2"
- camera_angle="30"
- camera_elevation="-.3">
- <param_driver>
- <driven
- id="1054" />
+ <param
+ id="780"
+ group="0"
+ wearable="jacket"
+ edit_group="jacket"
+ edit_group_order="3.5"
+ name="Collar Back"
+ label_min="Low"
+ label_max="High"
+ value_min="0"
+ value_max="1"
+ value_default=".8"
+ camera_distance="1.2"
+ camera_angle="195"
+ camera_elevation=".2">
+ <param_driver>
+ <driven
+ id="1023" />
+
+ <driven
+ id="1041" />
+
+ <driven
+ id="1024" />
+ </param_driver>
+ </param>
- <driven
- id="1055" />
- </param_driver>
- </param>
+ <param
+ id="603"
+ group="0"
+ wearable="undershirt"
+ edit_group="undershirt"
+ edit_group_order="1"
+ name="Sleeve Length"
+ label_min="Short"
+ label_max="Long"
+ value_min=".01"
+ value_max="1"
+ value_default=".4"
+ camera_distance="1.2"
+ camera_angle="30"
+ camera_elevation=".2">
+ <param_driver>
+ <driven
+ id="1042" />
+
+ <driven
+ id="1043" />
+ </param_driver>
+ </param>
- <param
- id="624"
- group="0"
- wearable="underpants"
- edit_group="underpants"
- name="Pants Waist"
- label_min="Low"
- label_max="High"
- value_min="0"
- value_max="1"
- value_default=".8"
- camera_distance="1.2"
- camera_angle="30"
- camera_elevation="-.3">
- <param_driver>
- <driven
- id="1056" />
+ <param
+ id="604"
+ group="0"
+ wearable="undershirt"
+ edit_group="undershirt"
+ edit_group_order="2"
+ name="Bottom"
+ label_min="Short"
+ label_max="Long"
+ value_min="0"
+ value_max="1"
+ value_default=".85"
+ camera_distance="1.2"
+ camera_angle="30"
+ camera_elevation=".2">
+ <param_driver>
+ <driven
+ id="1044" />
+
+ <driven
+ id="1045" />
+ </param_driver>
+ </param>
- <driven
- id="1057" />
- </param_driver>
- </param>
+ <param
+ id="605"
+ group="0"
+ wearable="undershirt"
+ edit_group="undershirt"
+ edit_group_order="3"
+ name="Collar Front"
+ label_min="Low"
+ label_max="High"
+ value_min="0"
+ value_max="1"
+ value_default=".84"
+ camera_distance=".8"
+ camera_angle="15"
+ camera_elevation=".2">
+ <param_driver>
+ <driven
+ id="1046" />
+
+ <driven
+ id="1047" />
+ </param_driver>
+ </param>
- <param
- id="93"
- group="0"
- wearable="gloves"
- edit_group="gloves"
- name="Glove Length"
- label_min="Short"
- label_max="Long"
- value_min=".01"
- value_max="1"
- value_default=".8"
- camera_distance="1.2"
- camera_angle="30"
- camera_elevation=".2">
- <param_driver>
- <driven
- id="1058" />
+ <param
+ id="779"
+ group="0"
+ wearable="undershirt"
+ edit_group="undershirt"
+ edit_group_order="4"
+ name="Collar Back"
+ label_min="Low"
+ label_max="High"
+ value_min="0"
+ value_max="1"
+ value_default=".84"
+ camera_distance=".8"
+ camera_angle="195"
+ camera_elevation=".2">
+ <param_driver>
+ <driven
+ id="1048" />
+
+ <driven
+ id="1049" />
+ </param_driver>
+ </param>
- <driven
- id="1059" />
- </param_driver>
- </param>
+ <param
+ id="617"
+ group="0"
+ wearable="socks"
+ edit_group="socks"
+ name="Socks Length"
+ label_min="Short"
+ label_max="Long"
+ value_min="0"
+ value_max="1"
+ value_default="0.35"
+ camera_distance=".95"
+ camera_angle="30"
+ camera_elevation="-.75">
+ <param_driver>
+ <driven
+ id="1050" />
+
+ <driven
+ id="1051" />
+ </param_driver>
+ </param>
- <param
- id="844"
- group="0"
- wearable="gloves"
- edit_group="gloves"
- name="Glove Fingers"
- label_min="Fingerless"
- label_max="Fingers"
- value_min=".01"
- value_max="1"
- value_default="1"
- camera_distance="1.2"
- camera_angle="30"
- camera_elevation=".2">
- <param_driver>
- <driven
- id="1060" />
+ <param
+ id="616"
+ group="0"
+ wearable="shoes"
+ edit_group="shoes"
+ edit_group_order="1"
+ name="Shoe Height"
+ label_min="Short"
+ label_max="Tall"
+ value_min="0"
+ value_max="1"
+ value_default="0.1"
+ camera_distance="1.2"
+ camera_angle="30"
+ camera_elevation="-.75">
+ <param_driver>
+ <driven
+ id="1052" />
+
+ <driven
+ id="1053" />
+ </param_driver>
+ </param>
- <driven
- id="1061" />
- </param_driver>
- </param>
+ <param
+ id="619"
+ group="0"
+ wearable="underpants"
+ edit_group="underpants"
+ name="Pants Length"
+ label_min="Short"
+ label_max="Long"
+ value_min="0"
+ value_max="1"
+ value_default=".3"
+ camera_distance="1.2"
+ camera_angle="30"
+ camera_elevation="-.3">
+ <param_driver>
+ <driven
+ id="1054" />
+
+ <driven
+ id="1055" />
+ </param_driver>
+ </param>
-<!--Pointy eyebrows became a driver/driven param with new max value for backwards compatibility between 1.0 and 1.1-->
- <param
- id="16"
- group="0"
- name="Pointy_Eyebrows"
- label="Eyebrow Points"
- wearable="hair"
- edit_group="hair_eyebrows"
- edit_group_order="4"
- label_min="Smooth"
- label_max="Pointy"
- value_min="-.5"
- value_max="3"
- camera_elevation=".1"
- camera_distance=".3">
- <param_driver>
- <driven
- id="870" />
- </param_driver>
- </param>
+ <param
+ id="624"
+ group="0"
+ wearable="underpants"
+ edit_group="underpants"
+ name="Pants Waist"
+ label_min="Low"
+ label_max="High"
+ value_min="0"
+ value_max="1"
+ value_default=".8"
+ camera_distance="1.2"
+ camera_angle="30"
+ camera_elevation="-.3">
+ <param_driver>
+ <driven
+ id="1056" />
+
+ <driven
+ id="1057" />
+ </param_driver>
+ </param>
-<!--Lower eyebrows became a driver/driven param with new min value for backwards compatibility between 1.0 and 1.1-->
- <param
- id="757"
- group="0"
- name="Lower_Eyebrows"
- label="Eyebrow Height"
- show_simple="true"
- wearable="hair"
- edit_group="hair_eyebrows"
- edit_group_order="2.5"
- label_min="Higher"
- label_max="Lower"
- value_min="-4"
- value_max="2"
- value_default="-1"
- camera_elevation=".1"
- camera_distance=".3">
- <param_driver>
- <driven
- id="871" />
- </param_driver>
- </param>
+ <param
+ id="93"
+ group="0"
+ wearable="gloves"
+ edit_group="gloves"
+ name="Glove Length"
+ label_min="Short"
+ label_max="Long"
+ value_min=".01"
+ value_max="1"
+ value_default=".8"
+ camera_distance="1.2"
+ camera_angle="30"
+ camera_elevation=".2">
+ <param_driver>
+ <driven
+ id="1058" />
+
+ <driven
+ id="1059" />
+ </param_driver>
+ </param>
-<!--Arced eyebrows became a driver/driven param with new max value for backwards compatibility between 1.0 and 1.1-->
- <param
- id="31"
- group="0"
- name="Arced_Eyebrows"
- label="Eyebrow Arc"
- wearable="hair"
- edit_group="hair_eyebrows"
- edit_group_order="3"
- label_min="Flat"
- label_max="Arced"
- value_min="0"
- value_max="2"
- value_default=".5"
- camera_elevation=".1"
- camera_distance=".3">
- <param_driver>
- <driven
- id="872" />
- </param_driver>
- </param>
+ <param
+ id="844"
+ group="0"
+ wearable="gloves"
+ edit_group="gloves"
+ name="Glove Fingers"
+ label_min="Fingerless"
+ label_max="Fingers"
+ value_min=".01"
+ value_max="1"
+ value_default="1"
+ camera_distance="1.2"
+ camera_angle="30"
+ camera_elevation=".2">
+ <param_driver>
+ <driven
+ id="1060" />
+
+ <driven
+ id="1061" />
+ </param_driver>
+ </param>
+
+ <!--Pointy eyebrows became a driver/driven param with new max value for backwards compatibility between 1.0 and 1.1-->
+ <param
+ id="16"
+ group="0"
+ name="Pointy_Eyebrows"
+ label="Eyebrow Points"
+ wearable="hair"
+ edit_group="hair_eyebrows"
+ edit_group_order="4"
+ label_min="Smooth"
+ label_max="Pointy"
+ value_min="-.5"
+ value_max="3"
+ camera_elevation=".1"
+ camera_distance=".3">
+ <param_driver>
+ <driven
+ id="870" />
+ </param_driver>
+ </param>
+
+ <!--Lower eyebrows became a driver/driven param with new min value for backwards compatibility between 1.0 and 1.1-->
+ <param
+ id="757"
+ group="0"
+ name="Lower_Eyebrows"
+ label="Eyebrow Height"
+ show_simple="true"
+ wearable="hair"
+ edit_group="hair_eyebrows"
+ edit_group_order="2.5"
+ label_min="Higher"
+ label_max="Lower"
+ value_min="-4"
+ value_max="2"
+ value_default="-1"
+ camera_elevation=".1"
+ camera_distance=".3">
+ <param_driver>
+ <driven
+ id="871" />
+ </param_driver>
+ </param>
+
+ <!--Arced eyebrows became a driver/driven param with new max value for backwards compatibility between 1.0 and 1.1-->
+ <param
+ id="31"
+ group="0"
+ name="Arced_Eyebrows"
+ label="Eyebrow Arc"
+ wearable="hair"
+ edit_group="hair_eyebrows"
+ edit_group_order="3"
+ label_min="Flat"
+ label_max="Arced"
+ value_min="0"
+ value_max="2"
+ value_default=".5"
+ camera_elevation=".1"
+ camera_distance=".3">
+ <param_driver>
+ <driven
+ id="872" />
+ </param_driver>
+ </param>
- <param
- id="877"
- group="0"
- name="Jacket Wrinkles"
- label="Jacket Wrinkles"
- wearable="jacket"
- edit_group="jacket"
- edit_group_order="20"
- label_min="No Wrinkles"
- label_max="Wrinkles"
- value_min="0"
- value_max="1"
- value_default="0"
- camera_elevation=".1"
- camera_distance=".3">
- <param_driver>
- <driven
- id="875" />
+
+ <param
+ id="877"
+ group="0"
+ name="Jacket Wrinkles"
+ label="Jacket Wrinkles"
+ wearable="jacket"
+ edit_group="jacket"
+ edit_group_order="20"
+ label_min="No Wrinkles"
+ label_max="Wrinkles"
+ value_min="0"
+ value_max="1"
+ value_default="0"
+ camera_elevation=".1"
+ camera_distance=".3">
+ <param_driver>
+ <driven
+ id="875" />
- <driven
- id="876" />
- </param_driver>
- </param>
+
+ <driven
+ id="876" />
+ </param_driver>
+ </param>
- </driver_parameters>
+
+ </driver_parameters>
+
+ <morph_masks>
+ <mask
+ morph_name="Displace_Hair_Facial"
+ body_region="head"
+ layer="facialhair" />
+ <mask
+ morph_name="Displace_Loose_Upperbody"
+ body_region="upper_body"
+ layer="upper_clothes" />
+ <mask
+ morph_name="Shirtsleeve_flair"
+ body_region="upper_body"
+ layer="upper_clothes" />
+ <mask
+ morph_name="Displace_Loose_Lowerbody"
+ body_region="lower_body"
+ layer="lower_pants" />
+ <mask
+ morph_name="Leg_Pantflair"
+ body_region="lower_body"
+ layer="lower_pants" />
+ <mask
+ morph_name="Low_Crotch"
+ body_region="lower_body"
+ layer="lower_pants" />
+ <mask
+ morph_name="Leg_Longcuffs"
+ body_region="lower_body"
+ layer="lower_pants" />
+ </morph_masks>
</linden_avatar>
diff --git a/indra/newview/character/avatar_lower_body.llm b/indra/newview/character/avatar_lower_body.llm
new file mode 100644
index 0000000000..0420899739
--- /dev/null
+++ b/indra/newview/character/avatar_lower_body.llm
Binary files differ
diff --git a/indra/newview/character/avatar_lower_body_1.llm b/indra/newview/character/avatar_lower_body_1.llm
new file mode 100644
index 0000000000..1394eb848b
--- /dev/null
+++ b/indra/newview/character/avatar_lower_body_1.llm
Binary files differ
diff --git a/indra/newview/character/avatar_lower_body_2.llm b/indra/newview/character/avatar_lower_body_2.llm
new file mode 100644
index 0000000000..0da9c1249e
--- /dev/null
+++ b/indra/newview/character/avatar_lower_body_2.llm
Binary files differ
diff --git a/indra/newview/character/avatar_lower_body_3.llm b/indra/newview/character/avatar_lower_body_3.llm
new file mode 100644
index 0000000000..f3c49a1568
--- /dev/null
+++ b/indra/newview/character/avatar_lower_body_3.llm
Binary files differ
diff --git a/indra/newview/character/avatar_lower_body_4.llm b/indra/newview/character/avatar_lower_body_4.llm
new file mode 100644
index 0000000000..e71721063e
--- /dev/null
+++ b/indra/newview/character/avatar_lower_body_4.llm
Binary files differ
diff --git a/indra/newview/character/avatar_skirt.llm b/indra/newview/character/avatar_skirt.llm
new file mode 100644
index 0000000000..08ce3d1700
--- /dev/null
+++ b/indra/newview/character/avatar_skirt.llm
Binary files differ
diff --git a/indra/newview/character/avatar_skirt_1.llm b/indra/newview/character/avatar_skirt_1.llm
new file mode 100644
index 0000000000..88076c321f
--- /dev/null
+++ b/indra/newview/character/avatar_skirt_1.llm
Binary files differ
diff --git a/indra/newview/character/avatar_skirt_2.llm b/indra/newview/character/avatar_skirt_2.llm
new file mode 100644
index 0000000000..73b3effbc6
--- /dev/null
+++ b/indra/newview/character/avatar_skirt_2.llm
Binary files differ
diff --git a/indra/newview/character/avatar_skirt_3.llm b/indra/newview/character/avatar_skirt_3.llm
new file mode 100644
index 0000000000..ded546fdea
--- /dev/null
+++ b/indra/newview/character/avatar_skirt_3.llm
Binary files differ
diff --git a/indra/newview/character/avatar_skirt_4.llm b/indra/newview/character/avatar_skirt_4.llm
new file mode 100644
index 0000000000..b9d5cb945e
--- /dev/null
+++ b/indra/newview/character/avatar_skirt_4.llm
Binary files differ
diff --git a/indra/newview/character/avatar_upper_body.llm b/indra/newview/character/avatar_upper_body.llm
new file mode 100644
index 0000000000..da7d990540
--- /dev/null
+++ b/indra/newview/character/avatar_upper_body.llm
Binary files differ
diff --git a/indra/newview/character/avatar_upper_body_1.llm b/indra/newview/character/avatar_upper_body_1.llm
new file mode 100644
index 0000000000..31e104cc20
--- /dev/null
+++ b/indra/newview/character/avatar_upper_body_1.llm
Binary files differ
diff --git a/indra/newview/character/avatar_upper_body_2.llm b/indra/newview/character/avatar_upper_body_2.llm
new file mode 100644
index 0000000000..c1f4199b9c
--- /dev/null
+++ b/indra/newview/character/avatar_upper_body_2.llm
Binary files differ
diff --git a/indra/newview/character/avatar_upper_body_3.llm b/indra/newview/character/avatar_upper_body_3.llm
new file mode 100644
index 0000000000..9e89ed8b3e
--- /dev/null
+++ b/indra/newview/character/avatar_upper_body_3.llm
Binary files differ
diff --git a/indra/newview/character/avatar_upper_body_4.llm b/indra/newview/character/avatar_upper_body_4.llm
new file mode 100644
index 0000000000..ec836d1dc3
--- /dev/null
+++ b/indra/newview/character/avatar_upper_body_4.llm
Binary files differ
diff --git a/indra/newview/character/blush_alpha.tga b/indra/newview/character/blush_alpha.tga
new file mode 100644
index 0000000000..05be7e7e3d
--- /dev/null
+++ b/indra/newview/character/blush_alpha.tga
Binary files differ
diff --git a/indra/newview/character/body_skingrain.tga b/indra/newview/character/body_skingrain.tga
new file mode 100644
index 0000000000..7264baac14
--- /dev/null
+++ b/indra/newview/character/body_skingrain.tga
Binary files differ
diff --git a/indra/newview/character/bodyfreckles_alpha.tga b/indra/newview/character/bodyfreckles_alpha.tga
new file mode 100644
index 0000000000..d30ab3d122
--- /dev/null
+++ b/indra/newview/character/bodyfreckles_alpha.tga
Binary files differ
diff --git a/indra/newview/character/bump_face_wrinkles.tga b/indra/newview/character/bump_face_wrinkles.tga
new file mode 100644
index 0000000000..54bf7a55be
--- /dev/null
+++ b/indra/newview/character/bump_face_wrinkles.tga
Binary files differ
diff --git a/indra/newview/character/bump_head_base.tga b/indra/newview/character/bump_head_base.tga
new file mode 100644
index 0000000000..fa3568573a
--- /dev/null
+++ b/indra/newview/character/bump_head_base.tga
Binary files differ
diff --git a/indra/newview/character/bump_lowerbody_base.tga b/indra/newview/character/bump_lowerbody_base.tga
new file mode 100644
index 0000000000..498ea3c721
--- /dev/null
+++ b/indra/newview/character/bump_lowerbody_base.tga
Binary files differ
diff --git a/indra/newview/character/bump_pants_wrinkles.tga b/indra/newview/character/bump_pants_wrinkles.tga
new file mode 100644
index 0000000000..cca72415e8
--- /dev/null
+++ b/indra/newview/character/bump_pants_wrinkles.tga
Binary files differ
diff --git a/indra/newview/character/bump_shirt_wrinkles.tga b/indra/newview/character/bump_shirt_wrinkles.tga
new file mode 100644
index 0000000000..9e0d757a48
--- /dev/null
+++ b/indra/newview/character/bump_shirt_wrinkles.tga
Binary files differ
diff --git a/indra/newview/character/bump_upperbody_base.tga b/indra/newview/character/bump_upperbody_base.tga
new file mode 100644
index 0000000000..e57d6352e6
--- /dev/null
+++ b/indra/newview/character/bump_upperbody_base.tga
Binary files differ
diff --git a/indra/newview/character/checkerboard.tga b/indra/newview/character/checkerboard.tga
new file mode 100644
index 0000000000..1950d7403d
--- /dev/null
+++ b/indra/newview/character/checkerboard.tga
Binary files differ
diff --git a/indra/newview/character/eyebrows_alpha.tga b/indra/newview/character/eyebrows_alpha.tga
new file mode 100644
index 0000000000..c363e482e1
--- /dev/null
+++ b/indra/newview/character/eyebrows_alpha.tga
Binary files differ
diff --git a/indra/newview/character/eyeliner_alpha.tga b/indra/newview/character/eyeliner_alpha.tga
new file mode 100644
index 0000000000..1611eb3355
--- /dev/null
+++ b/indra/newview/character/eyeliner_alpha.tga
Binary files differ
diff --git a/indra/newview/character/eyeshadow_inner_alpha.tga b/indra/newview/character/eyeshadow_inner_alpha.tga
new file mode 100644
index 0000000000..37d7919395
--- /dev/null
+++ b/indra/newview/character/eyeshadow_inner_alpha.tga
Binary files differ
diff --git a/indra/newview/character/eyeshadow_outer_alpha.tga b/indra/newview/character/eyeshadow_outer_alpha.tga
new file mode 100644
index 0000000000..00eef9d9f7
--- /dev/null
+++ b/indra/newview/character/eyeshadow_outer_alpha.tga
Binary files differ
diff --git a/indra/newview/character/eyewhite.tga b/indra/newview/character/eyewhite.tga
new file mode 100644
index 0000000000..a720496988
--- /dev/null
+++ b/indra/newview/character/eyewhite.tga
Binary files differ
diff --git a/indra/newview/character/facehair_chincurtains_alpha.tga b/indra/newview/character/facehair_chincurtains_alpha.tga
new file mode 100644
index 0000000000..b10397063c
--- /dev/null
+++ b/indra/newview/character/facehair_chincurtains_alpha.tga
Binary files differ
diff --git a/indra/newview/character/facehair_moustache_alpha.tga b/indra/newview/character/facehair_moustache_alpha.tga
new file mode 100644
index 0000000000..4068c4f2b1
--- /dev/null
+++ b/indra/newview/character/facehair_moustache_alpha.tga
Binary files differ
diff --git a/indra/newview/character/facehair_sideburns_alpha.tga b/indra/newview/character/facehair_sideburns_alpha.tga
new file mode 100644
index 0000000000..acddc2d9bd
--- /dev/null
+++ b/indra/newview/character/facehair_sideburns_alpha.tga
Binary files differ
diff --git a/indra/newview/character/facehair_soulpatch_alpha.tga b/indra/newview/character/facehair_soulpatch_alpha.tga
new file mode 100644
index 0000000000..687091a29f
--- /dev/null
+++ b/indra/newview/character/facehair_soulpatch_alpha.tga
Binary files differ
diff --git a/indra/newview/character/freckles_alpha.tga b/indra/newview/character/freckles_alpha.tga
new file mode 100644
index 0000000000..a9a4ec0735
--- /dev/null
+++ b/indra/newview/character/freckles_alpha.tga
Binary files differ
diff --git a/indra/newview/character/glove_length_alpha.tga b/indra/newview/character/glove_length_alpha.tga
new file mode 100644
index 0000000000..db89ad57e7
--- /dev/null
+++ b/indra/newview/character/glove_length_alpha.tga
Binary files differ
diff --git a/indra/newview/character/gloves_fingers_alpha.tga b/indra/newview/character/gloves_fingers_alpha.tga
new file mode 100644
index 0000000000..dba2eec277
--- /dev/null
+++ b/indra/newview/character/gloves_fingers_alpha.tga
Binary files differ
diff --git a/indra/newview/character/head_alpha.tga b/indra/newview/character/head_alpha.tga
new file mode 100644
index 0000000000..8164525353
--- /dev/null
+++ b/indra/newview/character/head_alpha.tga
Binary files differ
diff --git a/indra/newview/character/head_color.tga b/indra/newview/character/head_color.tga
new file mode 100644
index 0000000000..74b1b3078b
--- /dev/null
+++ b/indra/newview/character/head_color.tga
Binary files differ
diff --git a/indra/newview/character/head_hair.tga b/indra/newview/character/head_hair.tga
new file mode 100644
index 0000000000..5321f35204
--- /dev/null
+++ b/indra/newview/character/head_hair.tga
Binary files differ
diff --git a/indra/newview/character/head_highlights_alpha.tga b/indra/newview/character/head_highlights_alpha.tga
new file mode 100644
index 0000000000..8dc5239f97
--- /dev/null
+++ b/indra/newview/character/head_highlights_alpha.tga
Binary files differ
diff --git a/indra/newview/character/head_shading_alpha.tga b/indra/newview/character/head_shading_alpha.tga
new file mode 100644
index 0000000000..e8ea490109
--- /dev/null
+++ b/indra/newview/character/head_shading_alpha.tga
Binary files differ
diff --git a/indra/newview/character/head_skingrain.tga b/indra/newview/character/head_skingrain.tga
new file mode 100644
index 0000000000..b42dee0809
--- /dev/null
+++ b/indra/newview/character/head_skingrain.tga
Binary files differ
diff --git a/indra/newview/character/invisible_head.tga b/indra/newview/character/invisible_head.tga
new file mode 100755
index 0000000000..2673a237d5
--- /dev/null
+++ b/indra/newview/character/invisible_head.tga
Binary files differ
diff --git a/indra/newview/character/jacket_length_lower_alpha.tga b/indra/newview/character/jacket_length_lower_alpha.tga
new file mode 100644
index 0000000000..722bc192a8
--- /dev/null
+++ b/indra/newview/character/jacket_length_lower_alpha.tga
Binary files differ
diff --git a/indra/newview/character/jacket_length_upper_alpha.tga b/indra/newview/character/jacket_length_upper_alpha.tga
new file mode 100644
index 0000000000..e9db7e7b1f
--- /dev/null
+++ b/indra/newview/character/jacket_length_upper_alpha.tga
Binary files differ
diff --git a/indra/newview/character/jacket_open_lower_alpha.tga b/indra/newview/character/jacket_open_lower_alpha.tga
new file mode 100644
index 0000000000..db0c2fb0e3
--- /dev/null
+++ b/indra/newview/character/jacket_open_lower_alpha.tga
Binary files differ
diff --git a/indra/newview/character/jacket_open_upper_alpha.tga b/indra/newview/character/jacket_open_upper_alpha.tga
new file mode 100644
index 0000000000..71b8a0b805
--- /dev/null
+++ b/indra/newview/character/jacket_open_upper_alpha.tga
Binary files differ
diff --git a/indra/newview/character/lipgloss_alpha.tga b/indra/newview/character/lipgloss_alpha.tga
new file mode 100644
index 0000000000..78ceecaf85
--- /dev/null
+++ b/indra/newview/character/lipgloss_alpha.tga
Binary files differ
diff --git a/indra/newview/character/lips_mask.tga b/indra/newview/character/lips_mask.tga
new file mode 100644
index 0000000000..ae1401c006
--- /dev/null
+++ b/indra/newview/character/lips_mask.tga
Binary files differ
diff --git a/indra/newview/character/lipstick_alpha.tga b/indra/newview/character/lipstick_alpha.tga
new file mode 100644
index 0000000000..2795f1bd40
--- /dev/null
+++ b/indra/newview/character/lipstick_alpha.tga
Binary files differ
diff --git a/indra/newview/character/lowerbody_color.tga b/indra/newview/character/lowerbody_color.tga
new file mode 100644
index 0000000000..a63aa12fca
--- /dev/null
+++ b/indra/newview/character/lowerbody_color.tga
Binary files differ
diff --git a/indra/newview/character/lowerbody_highlights_alpha.tga b/indra/newview/character/lowerbody_highlights_alpha.tga
new file mode 100644
index 0000000000..ae3413ac8b
--- /dev/null
+++ b/indra/newview/character/lowerbody_highlights_alpha.tga
Binary files differ
diff --git a/indra/newview/character/lowerbody_shading_alpha.tga b/indra/newview/character/lowerbody_shading_alpha.tga
new file mode 100644
index 0000000000..0242663a7d
--- /dev/null
+++ b/indra/newview/character/lowerbody_shading_alpha.tga
Binary files differ
diff --git a/indra/newview/character/nailpolish_alpha.tga b/indra/newview/character/nailpolish_alpha.tga
new file mode 100644
index 0000000000..91af762902
--- /dev/null
+++ b/indra/newview/character/nailpolish_alpha.tga
Binary files differ
diff --git a/indra/newview/character/pants_length_alpha.tga b/indra/newview/character/pants_length_alpha.tga
new file mode 100644
index 0000000000..3c4f21c0f2
--- /dev/null
+++ b/indra/newview/character/pants_length_alpha.tga
Binary files differ
diff --git a/indra/newview/character/pants_waist_alpha.tga b/indra/newview/character/pants_waist_alpha.tga
new file mode 100644
index 0000000000..35658c0896
--- /dev/null
+++ b/indra/newview/character/pants_waist_alpha.tga
Binary files differ
diff --git a/indra/newview/character/rosyface_alpha.tga b/indra/newview/character/rosyface_alpha.tga
new file mode 100644
index 0000000000..a0c8513da2
--- /dev/null
+++ b/indra/newview/character/rosyface_alpha.tga
Binary files differ
diff --git a/indra/newview/character/rouge_alpha.tga b/indra/newview/character/rouge_alpha.tga
new file mode 100644
index 0000000000..a0c8513da2
--- /dev/null
+++ b/indra/newview/character/rouge_alpha.tga
Binary files differ
diff --git a/indra/newview/character/shirt_bottom_alpha.tga b/indra/newview/character/shirt_bottom_alpha.tga
new file mode 100644
index 0000000000..7cce03dbe0
--- /dev/null
+++ b/indra/newview/character/shirt_bottom_alpha.tga
Binary files differ
diff --git a/indra/newview/character/shirt_collar_alpha.tga b/indra/newview/character/shirt_collar_alpha.tga
new file mode 100644
index 0000000000..f55f635473
--- /dev/null
+++ b/indra/newview/character/shirt_collar_alpha.tga
Binary files differ
diff --git a/indra/newview/character/shirt_collar_back_alpha.tga b/indra/newview/character/shirt_collar_back_alpha.tga
new file mode 100644
index 0000000000..43a6453107
--- /dev/null
+++ b/indra/newview/character/shirt_collar_back_alpha.tga
Binary files differ
diff --git a/indra/newview/character/shirt_sleeve_alpha.tga b/indra/newview/character/shirt_sleeve_alpha.tga
new file mode 100644
index 0000000000..e3b18f4fc6
--- /dev/null
+++ b/indra/newview/character/shirt_sleeve_alpha.tga
Binary files differ
diff --git a/indra/newview/character/shoe_height_alpha.tga b/indra/newview/character/shoe_height_alpha.tga
new file mode 100644
index 0000000000..d08dd750f3
--- /dev/null
+++ b/indra/newview/character/shoe_height_alpha.tga
Binary files differ
diff --git a/indra/newview/character/skirt_length_alpha.tga b/indra/newview/character/skirt_length_alpha.tga
new file mode 100644
index 0000000000..c86799469d
--- /dev/null
+++ b/indra/newview/character/skirt_length_alpha.tga
Binary files differ
diff --git a/indra/newview/character/skirt_slit_back_alpha.tga b/indra/newview/character/skirt_slit_back_alpha.tga
new file mode 100644
index 0000000000..0e49688b14
--- /dev/null
+++ b/indra/newview/character/skirt_slit_back_alpha.tga
Binary files differ
diff --git a/indra/newview/character/skirt_slit_front_alpha.tga b/indra/newview/character/skirt_slit_front_alpha.tga
new file mode 100644
index 0000000000..888bbf71a1
--- /dev/null
+++ b/indra/newview/character/skirt_slit_front_alpha.tga
Binary files differ
diff --git a/indra/newview/character/skirt_slit_left_alpha.tga b/indra/newview/character/skirt_slit_left_alpha.tga
new file mode 100644
index 0000000000..210feac1ea
--- /dev/null
+++ b/indra/newview/character/skirt_slit_left_alpha.tga
Binary files differ
diff --git a/indra/newview/character/skirt_slit_right_alpha.tga b/indra/newview/character/skirt_slit_right_alpha.tga
new file mode 100644
index 0000000000..ce11c64bf6
--- /dev/null
+++ b/indra/newview/character/skirt_slit_right_alpha.tga
Binary files differ
diff --git a/indra/newview/character/underpants_trial_female.tga b/indra/newview/character/underpants_trial_female.tga
new file mode 100644
index 0000000000..96bf732351
--- /dev/null
+++ b/indra/newview/character/underpants_trial_female.tga
Binary files differ
diff --git a/indra/newview/character/underpants_trial_male.tga b/indra/newview/character/underpants_trial_male.tga
new file mode 100644
index 0000000000..095695ca1c
--- /dev/null
+++ b/indra/newview/character/underpants_trial_male.tga
Binary files differ
diff --git a/indra/newview/character/undershirt_trial_female.tga b/indra/newview/character/undershirt_trial_female.tga
new file mode 100644
index 0000000000..e17a309531
--- /dev/null
+++ b/indra/newview/character/undershirt_trial_female.tga
Binary files differ
diff --git a/indra/newview/character/upperbody_color.tga b/indra/newview/character/upperbody_color.tga
new file mode 100644
index 0000000000..85fcc41142
--- /dev/null
+++ b/indra/newview/character/upperbody_color.tga
Binary files differ
diff --git a/indra/newview/character/upperbody_highlights_alpha.tga b/indra/newview/character/upperbody_highlights_alpha.tga
new file mode 100644
index 0000000000..2d8102b583
--- /dev/null
+++ b/indra/newview/character/upperbody_highlights_alpha.tga
Binary files differ
diff --git a/indra/newview/character/upperbody_shading_alpha.tga b/indra/newview/character/upperbody_shading_alpha.tga
new file mode 100644
index 0000000000..b420506b3e
--- /dev/null
+++ b/indra/newview/character/upperbody_shading_alpha.tga
Binary files differ
diff --git a/indra/newview/character/upperbodyfreckles_alpha.tga b/indra/newview/character/upperbodyfreckles_alpha.tga
new file mode 100644
index 0000000000..76c7ce8849
--- /dev/null
+++ b/indra/newview/character/upperbodyfreckles_alpha.tga
Binary files differ
diff --git a/indra/newview/cursors_mac/UI_CURSOR_TOOLBUY.tif b/indra/newview/cursors_mac/UI_CURSOR_TOOLBUY.tif
deleted file mode 100644
index 39d89987aa..0000000000
--- a/indra/newview/cursors_mac/UI_CURSOR_TOOLBUY.tif
+++ /dev/null
Binary files differ
diff --git a/indra/newview/cursors_mac/UI_CURSOR_TOOLOPEN.tif b/indra/newview/cursors_mac/UI_CURSOR_TOOLOPEN.tif
deleted file mode 100644
index 864c8dee7a..0000000000
--- a/indra/newview/cursors_mac/UI_CURSOR_TOOLOPEN.tif
+++ /dev/null
Binary files differ
diff --git a/indra/newview/cursors_mac/UI_CURSOR_TOOLSIT.tif b/indra/newview/cursors_mac/UI_CURSOR_TOOLSIT.tif
deleted file mode 100644
index d6d835a90b..0000000000
--- a/indra/newview/cursors_mac/UI_CURSOR_TOOLSIT.tif
+++ /dev/null
Binary files differ
diff --git a/indra/newview/da.lproj/language.txt b/indra/newview/da.lproj/language.txt
new file mode 100644
index 0000000000..316d25d903
--- /dev/null
+++ b/indra/newview/da.lproj/language.txt
@@ -0,0 +1 @@
+da \ No newline at end of file
diff --git a/indra/newview/es.lproj/language.txt b/indra/newview/es.lproj/language.txt
new file mode 100644
index 0000000000..6c4381495c
--- /dev/null
+++ b/indra/newview/es.lproj/language.txt
@@ -0,0 +1 @@
+es \ No newline at end of file
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index 05bdf64b42..4029bf95a0 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -1,4 +1,4 @@
-version 19
+version 21
// NOTE: This is mostly identical to featuretable_mac.txt with a few differences
// Should be combined into one table
@@ -28,6 +28,7 @@ RenderAvatarCloth 1 1
RenderAvatarLODFactor 1 1.0
RenderAvatarVP 1 1
RenderCubeMap 1 1
+RenderDelayVBUpdate 1 0
RenderFarClip 1 256
RenderFlexTimeFactor 1 1.0
RenderFogRatio 1 4.0
@@ -260,51 +261,63 @@ UseOcclusion 0 0
list Intel_830M
RenderTerrainDetail 1 0
RenderVBOEnable 1 0
+RenderUseImpostors 0 0
list Intel_845G
RenderTerrainDetail 1 0
RenderVBOEnable 1 0
+RenderUseImpostors 0 0
list Intel_855GM
RenderTerrainDetail 1 0
RenderVBOEnable 1 0
+RenderUseImpostors 0 0
list Intel_865G
RenderTerrainDetail 1 0
RenderVBOEnable 1 0
+RenderUseImpostors 0 0
list Intel_900
RenderTerrainDetail 1 0
RenderVBOEnable 1 0
+RenderUseImpostors 0 0
list Intel_915GM
RenderTerrainDetail 1 0
RenderVBOEnable 1 0
+RenderUseImpostors 0 0
list Intel_915G
RenderTerrainDetail 1 0
RenderVBOEnable 1 0
+RenderUseImpostors 0 0
list Intel_945GM
RenderTerrainDetail 1 0
RenderVBOEnable 1 0
+RenderUseImpostors 0 0
list Intel_945G
RenderTerrainDetail 1 0
RenderVBOEnable 1 0
+RenderUseImpostors 0 0
list Intel_950
RenderTerrainDetail 1 0
RenderVBOEnable 1 0
+RenderUseImpostors 0 0
list Intel_965
RenderTerrainDetail 1 0
RenderVBOEnable 1 0
UseOcclusion 0 0
+RenderUseImpostors 0 0
list Intel_G33
RenderTerrainDetail 1 0
RenderVBOEnable 1 0
+RenderUseImpostors 0 0
list Intel_G45
WindLightUseAtmosShaders 0 0
diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt
index 09105b8d88..61a8e51c50 100644
--- a/indra/newview/featuretable_linux.txt
+++ b/indra/newview/featuretable_linux.txt
@@ -1,4 +1,4 @@
-version 19
+version 21
// NOTE: This is mostly identical to featuretable_mac.txt with a few differences
// Should be combined into one table
@@ -28,6 +28,7 @@ RenderAvatarCloth 1 1
RenderAvatarLODFactor 1 1.0
RenderAvatarVP 1 1
RenderCubeMap 1 1
+RenderDelayVBUpdate 1 0
RenderFarClip 1 256
RenderFlexTimeFactor 1 1.0
RenderFogRatio 1 4.0
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index fd2496d8ad..12d47a904c 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -1,4 +1,4 @@
-version 19
+version 21
// NOTE: This is mostly identical to featuretable_mac.txt with a few differences
// Should be combined into one table
@@ -28,6 +28,7 @@ RenderAvatarCloth 0 0
RenderAvatarLODFactor 1 1.0
RenderAvatarVP 1 0
RenderCubeMap 1 1
+RenderDelayVBUpdate 1 0
RenderFarClip 1 256
RenderFlexTimeFactor 1 1.0
RenderFogRatio 1 4.0
diff --git a/indra/newview/fonts/DejaVuSans-Bold.ttf b/indra/newview/fonts/DejaVuSans-Bold.ttf
new file mode 100644
index 0000000000..ec1a2ebaf2
--- /dev/null
+++ b/indra/newview/fonts/DejaVuSans-Bold.ttf
Binary files differ
diff --git a/indra/newview/fonts/DejaVuSans-BoldOblique.ttf b/indra/newview/fonts/DejaVuSans-BoldOblique.ttf
new file mode 100644
index 0000000000..1a5576460d
--- /dev/null
+++ b/indra/newview/fonts/DejaVuSans-BoldOblique.ttf
Binary files differ
diff --git a/indra/newview/fonts/DejaVuSans-Oblique.ttf b/indra/newview/fonts/DejaVuSans-Oblique.ttf
new file mode 100644
index 0000000000..becc549927
--- /dev/null
+++ b/indra/newview/fonts/DejaVuSans-Oblique.ttf
Binary files differ
diff --git a/indra/newview/fonts/DejaVuSans.ttf b/indra/newview/fonts/DejaVuSans.ttf
new file mode 100644
index 0000000000..c1b19d8705
--- /dev/null
+++ b/indra/newview/fonts/DejaVuSans.ttf
Binary files differ
diff --git a/indra/newview/fonts/DejaVuSansMono.ttf b/indra/newview/fonts/DejaVuSansMono.ttf
index 19d188832b..6bc854ddae 100644
--- a/indra/newview/fonts/DejaVuSansMono.ttf
+++ b/indra/newview/fonts/DejaVuSansMono.ttf
Binary files differ
diff --git a/indra/newview/fr.lproj/language.txt b/indra/newview/fr.lproj/language.txt
new file mode 100644
index 0000000000..717280ac26
--- /dev/null
+++ b/indra/newview/fr.lproj/language.txt
@@ -0,0 +1 @@
+fr \ No newline at end of file
diff --git a/indra/newview/gpu_table.txt b/indra/newview/gpu_table.txt
index 56de9c610a..cc8f6780e3 100644
--- a/indra/newview/gpu_table.txt
+++ b/indra/newview/gpu_table.txt
@@ -70,8 +70,8 @@ ATI M72 .*ATI.*M72.* 1 1
ATI M76 .*ATI.*M76.* 3 1
ATI Mobility Radeon 7xxx .*ATI.*Mobility.*Radeon 7.* 0 1
ATI Mobility Radeon 8xxx .*ATI.*Mobility.*Radeon 8.* 0 1
-ATI Mobility Radeon 9800 .*ATI.*Mobility.*98.* 1 1
-ATI Mobility Radeon 9700 .*ATI.*Mobility.*97.* 1 1
+ATI Mobility Radeon 9800 .*ATI.*Mobility.*98.* 0 1
+ATI Mobility Radeon 9700 .*ATI.*Mobility.*97.* 0 1
ATI Mobility Radeon 9600 .*ATI.*Mobility.*96.* 0 1
ATI Mobility Radeon HD 2300 .*ATI.*Mobility.*HD.*23.* 1 1
ATI Mobility Radeon HD 2400 .*ATI.*Mobility.*HD.*24.* 1 1
@@ -157,12 +157,16 @@ Intel Bear Lake .*Intel.*Bear Lake.* 0 0
Intel Broadwater .*Intel.*Broadwater.* 0 0
Intel Brookdale .*Intel.*Brookdale.* 0 0
Intel Cantiga .*Intel.*Cantiga.* 0 0
-Intel Eaglelake .*Intel.*Eaglelake.* 0 0
+Intel Eaglelake .*Intel.*Eaglelake.* 0 1
Intel Montara .*Intel.*Montara.* 0 0
Intel Springdale .*Intel.*Springdale.* 0 0
Matrox .*Matrox.* 0 0
Mesa .*Mesa.* 0 0
+NVIDIA GT 120 .*NVIDIA.*GeForce.*GT.*12.* 2 1
+NVIDIA GT 130 .*NVIDIA.*GeForce.*GT.*13.* 3 1
+NVIDIA GTS 250 .*NVIDIA.*GeForce.*GTS.*25.* 3 1
NVIDIA GTX 260 .*NVIDIA.*GeForce.*GTX.*26.* 3 1
+NVIDIA GTX 270 .*NVIDIA.*GeForce.*GTX.*27.* 3 1
NVIDIA GTX 280 .*NVIDIA.*GeForce.*GTX.*28.* 3 1
NVIDIA GTX 290 .*NVIDIA.*GeForce.*GTX.*29.* 3 1
NVIDIA C51 .*NVIDIA.*C51.* 0 1
@@ -263,7 +267,6 @@ NVIDIA Quadro FX 4500 .*Quadro.*FX.*4500.* 3 1
NVIDIA Quadro FX .*Quadro FX.* 1 1
NVIDIA Quadro NVS .*Quadro NVS.* 0 1
NVIDIA RIVA TNT .*RIVA TNT.* 0 0
-NVIDIA PCI .*NVIDIA.*/PCI/SSE2 0 0
S3 .*S3 Graphics.* 0 0
SiS SiS.* 0 0
Trident Trident.* 0 0
diff --git a/indra/newview/hu.lproj/language.txt b/indra/newview/hu.lproj/language.txt
new file mode 100644
index 0000000000..6c604cf2a9
--- /dev/null
+++ b/indra/newview/hu.lproj/language.txt
@@ -0,0 +1 @@
+hu \ No newline at end of file
diff --git a/indra/newview/installers/darwin/firstlook-dmg/_DS_Store b/indra/newview/installers/darwin/firstlook-dmg/_DS_Store
index 6c5a3f3452..9d9fd897e7 100644
--- a/indra/newview/installers/darwin/firstlook-dmg/_DS_Store
+++ b/indra/newview/installers/darwin/firstlook-dmg/_DS_Store
Binary files differ
diff --git a/indra/newview/installers/darwin/fix_application_icon_position.sh b/indra/newview/installers/darwin/fix_application_icon_position.sh
new file mode 100644
index 0000000000..a0b72a89f2
--- /dev/null
+++ b/indra/newview/installers/darwin/fix_application_icon_position.sh
@@ -0,0 +1,14 @@
+# just run this script each time after you change the installer's name to fix the icon misalignment
+#!/bin/bash
+cp -r ./../../../build-darwin-i386/newview/*.dmg ~/Desktop/TempBuild.dmg
+hdid ~/Desktop/TempBuild.dmg
+open -a finder /Volumes/Second\ Life\ Installer
+osascript dmg-cleanup.applescript
+cp /Volumes/Second\ Life\ Installer/.DS_Store ~/Desktop/_DS_Store
+chflags nohidden ~/Desktop/_DS_Store
+cp ~/Desktop/_DS_Store ./firstlook-dmg/_DS_Store
+cp ~/Desktop/_DS_Store ./publicnightly-dmg/_DS_Store
+cp ~/Desktop/_DS_Store ./release-dmg/_DS_Store
+cp ~/Desktop/_DS_Store ./releasecandidate-dmg/_DS_Store
+umount /Volumes/Second\ Life\ Installer/
+rm ~/Desktop/_DS_Store ~/Desktop/TempBuild.dmg
diff --git a/indra/newview/installers/darwin/publicnightly-dmg/_DS_Store b/indra/newview/installers/darwin/publicnightly-dmg/_DS_Store
index 6a91b38d6d..9d9fd897e7 100644
--- a/indra/newview/installers/darwin/publicnightly-dmg/_DS_Store
+++ b/indra/newview/installers/darwin/publicnightly-dmg/_DS_Store
Binary files differ
diff --git a/indra/newview/installers/darwin/release-dmg/_DS_Store b/indra/newview/installers/darwin/release-dmg/_DS_Store
index 2c179b11a4..9d9fd897e7 100644
--- a/indra/newview/installers/darwin/release-dmg/_DS_Store
+++ b/indra/newview/installers/darwin/release-dmg/_DS_Store
Binary files differ
diff --git a/indra/newview/installers/darwin/releasecandidate-dmg/_DS_Store b/indra/newview/installers/darwin/releasecandidate-dmg/_DS_Store
index a8b757372e..9d9fd897e7 100644
--- a/indra/newview/installers/darwin/releasecandidate-dmg/_DS_Store
+++ b/indra/newview/installers/darwin/releasecandidate-dmg/_DS_Store
Binary files differ
diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi
index 87218008bd..a7322749ca 100644
--- a/indra/newview/installers/windows/installer_template.nsi
+++ b/indra/newview/installers/windows/installer_template.nsi
@@ -498,7 +498,8 @@ RMDir "$INSTDIR"
IfFileExists "$INSTDIR" FOLDERFOUND NOFOLDER
FOLDERFOUND:
- MessageBox MB_YESNO $(DeleteProgramFilesMB) IDNO NOFOLDER
+ ; Silent uninstall always removes all files (/SD IDYES)
+ MessageBox MB_YESNO $(DeleteProgramFilesMB) /SD IDYES IDNO NOFOLDER
RMDir /r "$INSTDIR"
NOFOLDER:
@@ -757,7 +758,7 @@ CreateShortCut "$SMPROGRAMS\$INSTSHORTCUT\$INSTSHORTCUT.lnk" \
WriteINIStr "$SMPROGRAMS\$INSTSHORTCUT\SL Create Account.url" \
"InternetShortcut" "URL" \
- "http://www.secondlife.com/registration/"
+ "http://join.secondlife.com/"
WriteINIStr "$SMPROGRAMS\$INSTSHORTCUT\SL Your Account.url" \
"InternetShortcut" "URL" \
"http://www.secondlife.com/account/"
diff --git a/indra/newview/installers/windows/lang_fr.nsi b/indra/newview/installers/windows/lang_fr.nsi
index d23615de91..008c240ed7 100644
--- a/indra/newview/installers/windows/lang_fr.nsi
+++ b/indra/newview/installers/windows/lang_fr.nsi
Binary files differ
diff --git a/indra/newview/installers/windows/lang_it.nsi b/indra/newview/installers/windows/lang_it.nsi
index 1208ec4eb8..eccd965a92 100644
--- a/indra/newview/installers/windows/lang_it.nsi
+++ b/indra/newview/installers/windows/lang_it.nsi
Binary files differ
diff --git a/indra/newview/it.lproj/language.txt b/indra/newview/it.lproj/language.txt
new file mode 100644
index 0000000000..c91971434c
--- /dev/null
+++ b/indra/newview/it.lproj/language.txt
@@ -0,0 +1 @@
+it \ No newline at end of file
diff --git a/indra/newview/licenses-mac.txt b/indra/newview/licenses-mac.txt
index d488c7487e..1324fa1a86 100644
--- a/indra/newview/licenses-mac.txt
+++ b/indra/newview/licenses-mac.txt
@@ -315,6 +315,515 @@ This product includes cryptographic software written by Eric Young
Hudson (tjh@cryptsoft.com).
+===========
+Pth License
+===========
+ ____ _ _
+ | _ \| |_| |__ ``Ian Fleming was a UNIX fan!
+ | |_) | __| '_ \ How do I know? Well, James Bond
+ | __/| |_| | | | had the (license to kill) number 007,
+ |_| \__|_| |_| i.e., he could execute anyone!''
+
+ GNU Pth - The GNU Portable Threads
+
+ LICENSE
+ =======
+
+ 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; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ For some people, it is not clear, what is the real intention of the
+ author by using the GNU Lesser General Public License (LGPL) as the
+ distribution license for GNU Pth. This is, because the LGPL and the
+ GPL can be (and are often) interpreted very differently and some
+ interpretations seem to be not compatible with others. So an explicit
+ clarification for the use of the LGPL for GNU Pth from the authors
+ point of view might be useful.
+
+ The author places this library under the LGPL to make sure that it
+ can be used both commercially and non-commercially provided that
+ modifications to the code base are always donated back to the official
+ code base under the same license conditions. Please keep in mind that
+ especially using this library in code not staying under the GPL or
+ the LGPL _is_ allowed and that any taint or license creap into code
+ that uses the library is not the authors intention. It is just the
+ case that _including_ this library into the source tree of other
+ applications is a little bit more inconvinient because of the LGPL.
+ But it has to be this way for good reasons. And keep in mind that
+ inconvinient doesn't mean not allowed or even impossible.
+
+ Even if you want to use this library in some BSD-style licensed
+ packages, this _is_ possible as long as you are a little bit
+ carefully. Usually this means you have to make sure that the code is
+ still clearly separated into the source tree and that modifications to
+ this source area are done under the conditions of the LGPL. Read below
+ for more details on the conditions. Contact the author if you have
+ more questions.
+
+ The license text of the GNU Lesser General Public License follows:
+ __________________________________________________________________________
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
=======================
Original SSLeay License
diff --git a/indra/newview/linux_tools/client-readme-voice.txt b/indra/newview/linux_tools/client-readme-voice.txt
index 23a42f484b..bfefdf3471 100644
--- a/indra/newview/linux_tools/client-readme-voice.txt
+++ b/indra/newview/linux_tools/client-readme-voice.txt
@@ -4,36 +4,31 @@ Second Life - Linux Voice Support README
WHAT IS IT?
-=-=-=-=-=-
-Linux Voice Support is a new feature in testing which allows users
-of the Linux Second Life client to participate in voice-chat with other
-residents and groups inside Second Life, with an appropriate
-headset/microphone.
-
-Linux Voice Support is currently EXPERIMENTAL and is known to still
-have some compatibility issues.
+Linux Voice Support is a feature in testing which allows users of the Linux
+Second Life client to participate in voice-chat with other residents and
+groups inside Second Life, with an appropriate headset/microphone.
REQUIREMENTS
-=-=-=-=-=-=
* A headset/microphone supported by your chosen version of Linux
-* The ALSA sound system (you probably already have this -
- i.e. the alsa-base and alsa-utils packages on Ubuntu)
+* At this time, the PulseAudio audio system is recommended; this software
+ is already part of most modern (2009+) Linux desktop systems. Alternatively,
+ the ALSA audio system may be used on systems installed from around
+ 2007 onwards (again this is likely already installed on your system).
+
+TESTING YOUR SETTINGS
+-=-=-=-=-=-=-=-=-=-=-
-Success with Linux Voice support has been reported on the following
-systems:
-* Ubuntu 6.06 (Dapper) with Intel ICH5/CMI9761A+ audio chipset
-* Ubuntu 6.06 (Dapper) with SigmaTel STAC2997 audio chipset
-* Ubuntu 6.06 (Dapper) with Creative EMU10K1 audio chipset
-* Ubuntu 7.04 (Feisty) with USB Plantronics headset
-* Ubuntu 7.04 (Feisty) with Intel HDA audio chipset
-* Fedora Core 6 with (unknown) audio chipset
-* Ubuntu 8.04 (Hardy) with (unknown) audio chipset
+* The Second Life region 'Voice Echo Canyon' is a great place for testing
+your hardware settings and quality - it will 'echo' your voice back to you
+when you speak.
KNOWN PROBLEMS
-=-=-=-=-=-=-=
-* The 'Input Level' meter in the Voice Chat Device Settings dialog
- does not respond to audio input.
+* Compatibility with old ALSA-based audio systems (such as Ubuntu Dapper
+ from 2006) is poor.
TROUBLESHOOTING
-=-=-=-=-=-=-=-
@@ -41,12 +36,11 @@ TROUBLESHOOTING
PROBLEM 1: I don't see a white dot over the head of my avatar or other
Voice-using avatars.
SOLUTION:
-a. Ensure that 'Enable voice chat' is enabled in the Voice Chat
- preferences window and that you are in a voice-enabled area (you
- will see a blue headphone icon in the SL menu-bar).
+a. Ensure that 'Enable voice' is enabled in the 'Sound' section of the
+ Preferences window, and that you are in a voice-enabled area.
b. If the above does not help, exit Second Life and ensure that any
remaining 'SLVoice' processes (as reported by 'ps', 'top' or similar)
- are killed.
+ are killed before restarting.
PROBLEM 2: I have a white dot over my head but I never see (or hear!) anyone
except myself listed in the Active Speakers dialog when I'm sure that other
@@ -65,12 +59,13 @@ c. Update to the latest version of ALSA manually. For a guide, see the
PROBLEM 3: I can hear other people, but they cannot hear me.
SOLUTION:
-a. Ensure that you have the 'Talk' button activated while you are trying to
- speak.
+a. Ensure that you have the 'Speak' button (at the bottom of the Second Life
+ window) activated while you are trying to speak.
b. Ensure that your microphone jack is inserted into the correct socket of your
sound card, where appropriate.
-c. Use your system mixer-setting program or the 'alsamixer' program to ensure
- that microphone input is set as the active input source and is not muted.
+c. Use your system mixer-setting program (such as the PulseAudio 'volume
+ control' applet or the ALSA 'alsamixer' program) to ensure that microphone
+ input is set as the active input source and is not muted.
d. Verify that audio input works in other applications, i.e. Audacity
PROBLEM 4: Other people just hear bursts of loud noise when I speak.
diff --git a/indra/newview/linux_tools/client-readme.txt b/indra/newview/linux_tools/client-readme.txt
index 99c973f7ea..92d321d8c0 100644
--- a/indra/newview/linux_tools/client-readme.txt
+++ b/indra/newview/linux_tools/client-readme.txt
@@ -55,10 +55,13 @@ Minimum requirements:
is required. If you are running a 64-bit Linux distribution then
you will need its 32-bit compatibility environment installed, but
this configuration is not currently supported.
+ * PulseAudio or ALSA Linux system sound software. A recent PulseAudio
+ is the recommended configuration; see README-linux-voice.txt for more
+ information.
* Video/Graphics Card:
o nVidia GeForce 2, GeForce 4mx, or better (recommend one of the
following: 6700, 6800, 7600, 7800, 7900, 8400, 8500, 8600,
- 8800, Go 7400, Go 7600, Go 7800, Go 7900)
+ 8800, Go 7400, Go 7600, Go 7800, Go 7900, +)
o OR ATI Radeon 8500, 9250, or better
(nVidia cards are recommended for the Linux client)
@@ -75,8 +78,9 @@ Life Linux client is very similar to that for Windows, as detailed at:
3. INSTALLING & RUNNING
-=-=-=-=-=-=-=-=-=-=-=-
-The Second Life Linux client entirely runs out of the directory you have
-unpacked it into - no installation step is required.
+The Second Life Linux client can entirely run from the directory you have
+unpacked it into - no installation step is required. If you wish to
+perform a separate installation step anyway, you may run './install.sh'
Run ./secondlife from the installation directory to start Second Life.
@@ -96,10 +100,7 @@ you wish.
4. KNOWN ISSUES
-=-=-=-=-=-=-=-
-* UPDATING - when the client detects that a new version of Second Life
- is available, it will ask you if you wish to download the new version.
- This option is not implemented; to upgrade, you should manually download a
- new version from the Second Life web site, <http://www.secondlife.com/>.
+* No significant known issues at this time.
5. TROUBLESHOOTING
diff --git a/indra/newview/linux_tools/handle_secondlifeprotocol.sh b/indra/newview/linux_tools/handle_secondlifeprotocol.sh
index 7ff86d1b93..203012132e 100755
--- a/indra/newview/linux_tools/handle_secondlifeprotocol.sh
+++ b/indra/newview/linux_tools/handle_secondlifeprotocol.sh
@@ -11,7 +11,7 @@ if [ -z "$URL" ]; then
fi
RUN_PATH=`dirname "$0" || echo .`
-cd "${RUN_PATH}"
+cd "${RUN_PATH}/.."
exec ./secondlife -url \'"${URL}"\'
diff --git a/indra/newview/linux_tools/install.sh b/indra/newview/linux_tools/install.sh
new file mode 100755
index 0000000000..c94510267a
--- /dev/null
+++ b/indra/newview/linux_tools/install.sh
@@ -0,0 +1,106 @@
+#!/bin/bash
+
+# Install the Second Life Viewer. This script can install the viewer both
+# system-wide and for an individual user.
+
+VT102_STYLE_NORMAL='\E[0m'
+VT102_COLOR_RED='\E[31m'
+
+SCRIPTSRC=`readlink -f "$0" || echo "$0"`
+RUN_PATH=`dirname "${SCRIPTSRC}" || echo .`
+tarball_path=${RUN_PATH}
+
+function prompt()
+{
+ local prompt=$1
+ local input
+
+ echo -n "$prompt"
+
+ while read input; do
+ case $input in
+ [Yy]* )
+ return 1
+ ;;
+ [Nn]* )
+ return 0
+ ;;
+ * )
+ echo "Please enter yes or no."
+ echo -n "$prompt"
+ esac
+ done
+}
+
+function die()
+{
+ warn $1
+ exit 1
+}
+
+function warn()
+{
+ echo -n -e $VT102_COLOR_RED
+ echo $1
+ echo -n -e $VT102_STYLE_NORMAL
+}
+
+function homedir_install()
+{
+ warn "You are not running as a privileged user, so you will only be able"
+ warn "to install the Second Life Viewer in your home directory. If you"
+ warn "would like to install the Second Life Viewer system-wide, please run"
+ warn "this script as the root user, or with the 'sudo' command."
+ echo
+
+ prompt "Proceed with the installation? [Y/N]: "
+ if [[ $? == 0 ]]; then
+ exit 0
+ fi
+
+ install_to_prefix "$HOME/.secondlife-install"
+ $HOME/.secondlife-install/etc/refresh_desktop_app_entry.sh
+}
+
+function root_install()
+{
+ local default_prefix="/opt/secondlife-install"
+
+ echo -n "Enter the desired installation directory [${default_prefix}]: ";
+ read
+ if [[ "$REPLY" = "" ]] ; then
+ local install_prefix=$default_prefix
+ else
+ local install_prefix=$REPLY
+ fi
+
+ install_to_prefix "$install_prefix"
+
+ mkdir -p /usr/local/share/applications
+ ${install_prefix}/etc/refresh_desktop_app_entry.sh
+}
+
+function install_to_prefix()
+{
+ test -e "$1" && backup_previous_installation "$1"
+ mkdir -p "$1" || die "Failed to create installation directory!"
+
+ echo " - Installing to $1"
+
+ cp -a "${tarball_path}"/* "$1/" || die "Failed to complete the installation!"
+}
+
+function backup_previous_installation()
+{
+ local backup_dir="$1".backup-$(date -I)
+ echo " - Backing up previous installation to $backup_dir"
+
+ mv "$1" "$backup_dir" || die "Failed to create backup of existing installation!"
+}
+
+
+if [ "$UID" == "0" ]; then
+ root_install
+else
+ homedir_install
+fi
diff --git a/indra/newview/linux_tools/refresh_desktop_app_entry.sh b/indra/newview/linux_tools/refresh_desktop_app_entry.sh
new file mode 100755
index 0000000000..d2b2a732d5
--- /dev/null
+++ b/indra/newview/linux_tools/refresh_desktop_app_entry.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+SCRIPTSRC=`readlink -f "$0" || echo "$0"`
+RUN_PATH=`dirname "${SCRIPTSRC}" || echo .`
+
+install_prefix=${RUN_PATH}/..
+
+function install_desktop_entry()
+{
+ local installation_prefix="$1"
+ local desktop_entries_dir="$2"
+
+ local desktop_entry="\
+[Desktop Entry]\n\
+Name=Second Life\n\
+Comment=Client for the On-line Virtual World, Second Life\n\
+Exec=${installation_prefix}/secondlife\n\
+Icon=${installation_prefix}/secondlife_icon.png\n\
+Terminal=false\n\
+Type=Application\n\
+Categories=Application;Network;\n\
+StartupNotify=true\n\
+X-Desktop-File-Install-Version=3.0"
+
+ echo " - Installing menu entries in ${desktop_entries_dir}"
+ mkdir -vp "${desktop_entries_dir}"
+ echo -e $desktop_entry > "${desktop_entries_dir}/secondlife-viewer.desktop" || "Failed to install application menu!"
+}
+
+if [ "$UID" == "0" ]; then
+ # system-wide
+ install_desktop_entry "$install_prefix" /usr/local/share/applications
+else
+ # user-specific
+ install_desktop_entry "$install_prefix" "$HOME/.local/share/applications"
+fi
diff --git a/indra/newview/linux_tools/register_secondlifeprotocol.sh b/indra/newview/linux_tools/register_secondlifeprotocol.sh
index 4ab96f97d6..16e73cb854 100755
--- a/indra/newview/linux_tools/register_secondlifeprotocol.sh
+++ b/indra/newview/linux_tools/register_secondlifeprotocol.sh
@@ -7,10 +7,10 @@
HANDLER="$1"
RUN_PATH=`dirname "$0" || echo .`
-cd "${RUN_PATH}"
+cd "${RUN_PATH}/.."
if [ -z "$HANDLER" ]; then
- HANDLER=`pwd`/handle_secondlifeprotocol.sh
+ HANDLER=`pwd`/etc/handle_secondlifeprotocol.sh
fi
# Register handler for GNOME-aware apps
@@ -22,13 +22,12 @@ else
fi
# Register handler for KDE-aware apps
-if [ -z "$KDEHOME" ]; then
- KDEHOME=~/.kde
-fi
-LLKDEPROTDIR=${KDEHOME}/share/services
-if [ -d "$LLKDEPROTDIR" ]; then
- LLKDEPROTFILE=${LLKDEPROTDIR}/secondlife.protocol
- cat > ${LLKDEPROTFILE} <<EOF || echo Warning: Did not register secondlife:// handler with KDE: Could not write ${LLKDEPROTFILE}
+for LLKDECONFIG in kde-config kde4-config; do
+ if [ `which $LLKDECONFIG` ]; then
+ LLKDEPROTODIR=`$LLKDECONFIG --path services | cut -d ':' -f 1`
+ if [ -d "$LLKDEPROTODIR" ]; then
+ LLKDEPROTOFILE=${LLKDEPROTODIR}/secondlife.protocol
+ cat > ${LLKDEPROTOFILE} <<EOF || echo Warning: Did not register secondlife:// handler with KDE: Could not write ${LLKDEPROTOFILE}
[Protocol]
exec=${HANDLER} '%u'
protocol=secondlife
@@ -41,6 +40,9 @@ writing=false
makedir=false
deleting=false
EOF
-else
- echo Warning: Did not register secondlife:// handler with KDE: Directory $LLKDEPROTDIR does not exist.
-fi
+ else
+ echo Warning: Did not register secondlife:// handler with KDE: Directory $LLKDEPROTODIR does not exist.
+ fi
+ fi
+done
+
diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh
index e188abe5d2..f84102e1fb 100755
--- a/indra/newview/linux_tools/wrapper.sh
+++ b/indra/newview/linux_tools/wrapper.sh
@@ -91,12 +91,14 @@ echo "Running from ${RUN_PATH}"
cd "${RUN_PATH}"
# Re-register the secondlife:// protocol handler every launch, for now.
-./register_secondlifeprotocol.sh
+./etc/register_secondlifeprotocol.sh
+
+# Re-register the application with the desktop system every launch, for now.
+./etc/refresh_desktop_app_entry.sh
+
## Before we mess with LD_LIBRARY_PATH, save the old one to restore for
## subprocesses that care.
-if [ "${LD_LIBRARY_PATH+isset}" = "isset" ]; then
- export SAVED_LD_LIBRARY_PATH="${LD_LIBRARY_PATH}"
-fi
+export SAVED_LD_LIBRARY_PATH="${LD_LIBRARY_PATH}"
if [ -n "$LL_TCMALLOC" ]; then
tcmalloc_libs='/usr/lib/libtcmalloc.so.0 /usr/lib/libstacktrace.so.0 /lib/libpthread.so.0'
@@ -116,9 +118,9 @@ if [ -n "$LL_TCMALLOC" ]; then
fi
fi
-export SL_ENV='LD_LIBRARY_PATH="`pwd`"/lib:"`pwd`"/app_settings/mozilla-runtime-linux-i686:"${LD_LIBRARY_PATH}"'
+export SL_ENV='LD_LIBRARY_PATH="`pwd`"/lib:"${LD_LIBRARY_PATH}"'
export SL_CMD='$LL_WRAPPER bin/do-not-directly-run-secondlife-bin'
-export SL_OPT="`cat gridargs.dat` $@"
+export SL_OPT="`cat etc/gridargs.dat` $@"
# Run the program
eval ${SL_ENV} ${SL_CMD} ${SL_OPT} || LL_RUN_ERR=runerr
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 98526c8a57..da0e9238d6 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -31,114 +31,63 @@
*/
#include "llviewerprecompiledheaders.h"
-
-#include "stdtypes.h"
-#include "stdenums.h"
-
#include "llagent.h"
-#include "llcamera.h"
-#include "llcoordframe.h"
-#include "indra_constants.h"
-#include "llmath.h"
-#include "llcriticaldamp.h"
-#include "llfocusmgr.h"
-#include "llglheaders.h"
-#include "llparcel.h"
-#include "llpermissions.h"
-#include "llregionhandle.h"
-#include "m3math.h"
-#include "m4math.h"
-#include "message.h"
-#include "llquaternion.h"
-#include "v3math.h"
-#include "v4math.h"
-#include "llsmoothstep.h"
-#include "llsdutil.h"
-//#include "vmath.h"
+#include "pipeline.h"
-#include "imageids.h"
-#include "llbox.h"
-#include "llbutton.h"
+#include "llagentlistener.h"
+#include "llagentwearables.h"
+#include "llagentui.h"
+#include "llanimationstates.h"
+#include "llbottomtray.h"
#include "llcallingcard.h"
-#include "llchatbar.h"
+#include "llchannelmanager.h"
#include "llconsole.h"
-#include "lldrawable.h"
-#include "llface.h"
-#include "llfirstuse.h"
-#include "llfloater.h"
-#include "llfloateractivespeakers.h"
-#include "llfloateravatarinfo.h"
-#include "llfloaterbuildoptions.h"
+//#include "llfirstuse.h"
#include "llfloatercamera.h"
-#include "llfloaterchat.h"
#include "llfloatercustomize.h"
-#include "llfloaterdirectory.h"
-#include "llfloatergroupinfo.h"
-#include "llfloatergroups.h"
-#include "llfloaterland.h"
-#include "llfloatermap.h"
-#include "llfloatermute.h"
-#include "llfloatersnapshot.h"
+#include "llfloaterreg.h"
#include "llfloatertools.h"
-#include "llfloaterworldmap.h"
+#include "llgroupactions.h"
#include "llgroupmgr.h"
#include "llhomelocationresponder.h"
-#include "llhudeffectlookat.h"
#include "llhudmanager.h"
-#include "llinventorymodel.h"
-#include "llinventoryview.h"
#include "lljoystickbutton.h"
-#include "llmenugl.h"
#include "llmorphview.h"
#include "llmoveview.h"
-#include "llnotify.h"
-#include "llquantize.h"
+#include "llnavigationbar.h" // to show/hide navigation bar when changing mouse look state
+#include "llnearbychatbar.h"
+#include "llnotificationsutil.h"
+#include "llparcel.h"
#include "llsdutil.h"
-#include "llselectmgr.h"
+#include "llsidetray.h"
#include "llsky.h"
-#include "llrendersphere.h"
+#include "llsmoothstep.h"
#include "llstatusbar.h"
-#include "llstartup.h"
-#include "llimview.h"
+#include "llteleportflags.h"
#include "lltool.h"
-#include "lltoolcomp.h"
-#include "lltoolfocus.h"
-#include "lltoolgrab.h"
#include "lltoolmgr.h"
-#include "lltoolpie.h"
-#include "lltoolview.h"
-#include "llui.h" // for make_ui_sound
-#include "llurldispatcher.h"
-#include "llviewercamera.h"
-#include "llviewerinventory.h"
-#include "llviewermenu.h"
-#include "llviewernetwork.h"
+#include "lltrans.h"
+#include "llviewercontrol.h"
+#include "llviewerdisplay.h"
+#include "llviewerjoystick.h"
+#include "llviewermediafocus.h"
#include "llviewerobjectlist.h"
#include "llviewerparcelmgr.h"
-#include "llviewerparceloverlay.h"
-#include "llviewerregion.h"
#include "llviewerstats.h"
-#include "llviewerwindow.h"
-#include "llviewerdisplay.h"
-#include "llvoavatar.h"
-#include "llvoground.h"
-#include "llvosky.h"
-#include "llwearable.h"
-#include "llwearablelist.h"
+#include "llvoavatarself.h"
+#include "llwindow.h"
#include "llworld.h"
#include "llworldmap.h"
-#include "pipeline.h"
-#include "roles_constants.h"
-#include "llviewercontrol.h"
-#include "llappviewer.h"
-#include "llviewerjoystick.h"
-#include "llfollowcam.h"
using namespace LLVOAvatarDefines;
extern LLMenuBarGL* gMenuBarView;
+const BOOL ANIMATE = TRUE;
+const U8 AGENT_STATE_TYPING = 0x04;
+const U8 AGENT_STATE_EDITING = 0x10;
+
//drone wandering constants
const F32 MAX_WANDER_TIME = 20.f; // seconds
const F32 MAX_HEADING_HALF_ERROR = 0.2f; // radians
@@ -214,7 +163,7 @@ const F64 CHAT_AGE_FAST_RATE = 3.0;
// The agent instance.
LLAgent gAgent;
-//
+//--------------------------------------------------------------------
// Statics
//
@@ -240,6 +189,19 @@ void LLAgentFriendObserver::changed(U32 mask)
}
}
+bool handleSlowMotionAnimation(const LLSD& newvalue)
+{
+ if (newvalue.asBoolean())
+ {
+ gAgent.getAvatarObject()->setAnimTimeFactor(0.2f);
+ }
+ else
+ {
+ gAgent.getAvatarObject()->setAnimTimeFactor(1.0f);
+ }
+ return true;
+}
+
// ************************************************************
// Enabled this definition to compile a 'hacked' viewer that
// locally believes the end user has godlike powers.
@@ -262,19 +224,13 @@ LLAgent::LLAgent() :
mHideGroupTitle(FALSE),
mGroupID(),
- mMapOriginX(0.F),
- mMapOriginY(0.F),
- mMapWidth(0),
- mMapHeight(0),
-
mLookAt(NULL),
mPointAt(NULL),
mHUDTargetZoom(1.f),
mHUDCurZoom(1.f),
mInitialized(FALSE),
- mNumPendingQueries(0),
- mActiveCacheQueries(NULL),
+ mListener(),
mForceMouselook(FALSE),
mDoubleTapRunTimer(),
@@ -302,6 +258,8 @@ LLAgent::LLAgent() :
mLastCameraMode( CAMERA_MODE_THIRD_PERSON ),
mViewsPushed(FALSE),
+ mCameraPreset(CAMERA_PRESET_REAR_VIEW),
+
mCustomAnim(FALSE),
mShowAvatar(TRUE),
mCameraAnimating( FALSE ),
@@ -315,7 +273,6 @@ LLAgent::LLAgent() :
mCameraFocusOffset(),
mCameraFOVDefault(DEFAULT_FIELD_OF_VIEW),
- mCameraOffsetDefault(),
mCameraCollidePlane(),
mCurrentCameraDistance(2.f), // meters, set in init()
@@ -348,7 +305,7 @@ LLAgent::LLAgent() :
mLeftKey(0),
mUpKey(0),
mYawKey(0.f),
- mPitchKey(0),
+ mPitchKey(0.f),
mOrbitLeftKey(0.f),
mOrbitRightKey(0.f),
@@ -382,7 +339,7 @@ LLAgent::LLAgent() :
mAutoPilotFinishedCallback(NULL),
mAutoPilotCallbackData(NULL),
- mEffectColor(0.f, 1.f, 1.f, 1.f),
+ mEffectColor(LLColor4(0.f, 1.f, 1.f, 1.f)),
mHaveHomePosition(FALSE),
mHomeRegionHandle( 0 ),
@@ -393,25 +350,17 @@ LLAgent::LLAgent() :
mFirstLogin(FALSE),
mGenderChosen(FALSE),
- mAgentWearablesUpdateSerialNum(0),
- mWearablesLoaded(FALSE),
- mTextureCacheQueryID(0),
mAppearanceSerialNum(0)
{
- U32 i;
- for (i = 0; i < TOTAL_CONTROLS; i++)
+ for (U32 i = 0; i < TOTAL_CONTROLS; i++)
{
mControlsTakenCount[i] = 0;
mControlsTakenPassedOnCount[i] = 0;
}
- mActiveCacheQueries = new S32[BAKED_NUM_INDICES];
- for (i = 0; i < (U32)BAKED_NUM_INDICES; i++)
- {
- mActiveCacheQueries[i] = 0;
- }
-
mFollowCam.setMaxCameraDistantFromSubject( MAX_CAMERA_DISTANCE_FROM_AGENT );
+
+ mListener.reset(new LLAgentListener(*this));
}
// Requires gSavedSettings to be initialized.
@@ -420,6 +369,9 @@ LLAgent::LLAgent() :
//-----------------------------------------------------------------------------
void LLAgent::init()
{
+ gSavedSettings.declareBOOL("SlowMotionAnimation", FALSE, "Declared in code", FALSE);
+ gSavedSettings.getControl("SlowMotionAnimation")->getSignal()->connect(boost::bind(&handleSlowMotionAnimation, _2));
+
mDrawDistance = gSavedSettings.getF32("RenderFarClip");
// *Note: this is where LLViewerCamera::getInstance() used to be constructed.
@@ -428,22 +380,33 @@ void LLAgent::init()
// Leave at 0.1 meters until we have real near clip management
LLViewerCamera::getInstance()->setNear(0.1f);
LLViewerCamera::getInstance()->setFar(mDrawDistance); // if you want to change camera settings, do so in camera.h
- LLViewerCamera::getInstance()->setAspect( gViewerWindow->getDisplayAspectRatio() ); // default, overridden in LLViewerWindow::reshape
+ LLViewerCamera::getInstance()->setAspect( gViewerWindow->getWorldViewAspectRatio() ); // default, overridden in LLViewerWindow::reshape
LLViewerCamera::getInstance()->setViewHeightInPixels(768); // default, overridden in LLViewerWindow::reshape
setFlying( gSavedSettings.getBOOL("FlyingAtExit") );
mCameraFocusOffsetTarget = LLVector4(gSavedSettings.getVector3("CameraOffsetBuild"));
- mCameraOffsetDefault = gSavedSettings.getVector3("CameraOffsetDefault");
+
+ mCameraPreset = (ECameraPreset) gSavedSettings.getU32("CameraPreset");
+
+ mCameraOffsetInitial[CAMERA_PRESET_REAR_VIEW] = gSavedSettings.getVector3("CameraOffsetRearView");
+ mCameraOffsetInitial[CAMERA_PRESET_FRONT_VIEW] = gSavedSettings.getVector3("CameraOffsetFrontView");
+ mCameraOffsetInitial[CAMERA_PRESET_GROUP_VIEW] = gSavedSettings.getVector3("CameraOffsetGroupView");
+
+ mFocusOffsetInitial[CAMERA_PRESET_REAR_VIEW] = gSavedSettings.getVector3d("FocusOffsetRearView");
+ mFocusOffsetInitial[CAMERA_PRESET_FRONT_VIEW] = gSavedSettings.getVector3d("FocusOffsetFrontView");
+ mFocusOffsetInitial[CAMERA_PRESET_GROUP_VIEW] = gSavedSettings.getVector3d("FocusOffsetGroupView");
+
mCameraCollidePlane.clearVec();
- mCurrentCameraDistance = mCameraOffsetDefault.magVec() * gSavedSettings.getF32("CameraOffsetScale");
+ mCurrentCameraDistance = getCameraOffsetInitial().magVec() * gSavedSettings.getF32("CameraOffsetScale");
mTargetCameraDistance = mCurrentCameraDistance;
mCameraZoomFraction = 1.f;
mTrackFocusObject = gSavedSettings.getBOOL("TrackFocusObject");
-// LLDebugVarMessageBox::show("Camera Lag", &CAMERA_FOCUS_HALF_LIFE, 0.5f, 0.01f);
+ mEffectColor = LLUIColorTable::instance().getColor("EffectColor");
- mEffectColor = gSavedSettings.getColor4("EffectColor");
+ gSavedSettings.getControl("PreferredMaturity")->getValidateSignal()->connect(boost::bind(&LLAgent::validateMaturity, this, _2));
+ gSavedSettings.getControl("PreferredMaturity")->getSignal()->connect(boost::bind(&LLAgent::handleMaturity, this, _2));
mInitialized = TRUE;
}
@@ -454,7 +417,9 @@ void LLAgent::init()
void LLAgent::cleanup()
{
setSitCamera(LLUUID::null);
+
mAvatarObject = NULL;
+
if(mLookAt)
{
mLookAt->markDead() ;
@@ -476,9 +441,6 @@ LLAgent::~LLAgent()
{
cleanup();
- delete [] mActiveCacheQueries;
- mActiveCacheQueries = NULL;
-
// *Note: this is where LLViewerCamera::getInstance() used to be deleted.
}
@@ -527,12 +489,16 @@ void LLAgent::resetView(BOOL reset_camera, BOOL change_camera)
LLViewerJoystick::getInstance()->moveAvatar(true);
}
- gFloaterTools->close();
+ //Camera Tool is needed for Free Camera Control Mode
+ if (!LLFloaterCamera::inFreeCameraMode())
+ {
+ LLFloaterReg::hideInstance("build");
+
+ // Switch back to basic toolset
+ LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
+ }
gViewerWindow->showCursor();
-
- // Switch back to basic toolset
- LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
}
@@ -548,6 +514,8 @@ void LLAgent::resetView(BOOL reset_camera, BOOL change_camera)
}
setFocusOnAvatar(TRUE, ANIMATE);
+
+ mCameraFOVZoomFactor = 0.f;
}
mHUDTargetZoom = 1.f;
@@ -734,15 +702,15 @@ void LLAgent::moveYaw(F32 mag, bool reset_view)
//-----------------------------------------------------------------------------
// movePitch()
//-----------------------------------------------------------------------------
-void LLAgent::movePitch(S32 direction)
+void LLAgent::movePitch(F32 mag)
{
- setKey(direction, mPitchKey);
+ mPitchKey = mag;
- if (direction > 0)
+ if (mag > 0)
{
- setControlFlags(AGENT_CONTROL_PITCH_POS );
+ setControlFlags(AGENT_CONTROL_PITCH_POS);
}
- else if (direction < 0)
+ else if (mag < 0)
{
setControlFlags(AGENT_CONTROL_PITCH_NEG);
}
@@ -769,6 +737,10 @@ BOOL LLAgent::canFly()
return parcel->getAllowFly();
}
+BOOL LLAgent::getFlying() const
+{
+ return mControlFlags & AGENT_CONTROL_FLY;
+}
//-----------------------------------------------------------------------------
// setFlying()
@@ -777,13 +749,18 @@ void LLAgent::setFlying(BOOL fly)
{
if (mAvatarObject.notNull())
{
- if(mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_STANDUP) != mAvatarObject->mSignaledAnimations.end())
+ // *HACK: Don't allow to start the flying mode if we got ANIM_AGENT_STANDUP signal
+ // because in this case we won't get a signal to start avatar flying animation and
+ // it will be walking with flying mode "ON" indication. However we allow to switch
+ // the flying mode off if we get ANIM_AGENT_STANDUP signal. See process_avatar_animation().
+ // See EXT-2781.
+ if(fly && mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_STANDUP) != mAvatarObject->mSignaledAnimations.end())
{
return;
}
// don't allow taking off while sitting
- if (fly && mAvatarObject->mIsSitting)
+ if (fly && mAvatarObject->isSitting())
{
return;
}
@@ -805,13 +782,16 @@ void LLAgent::setFlying(BOOL fly)
LLViewerStats::getInstance()->incStat(LLViewerStats::ST_FLY_COUNT);
}
setControlFlags(AGENT_CONTROL_FLY);
- gSavedSettings.setBOOL("FlyBtnState", TRUE);
}
else
{
clearControlFlags(AGENT_CONTROL_FLY);
- gSavedSettings.setBOOL("FlyBtnState", FALSE);
}
+
+
+ // Update Movement Controls according to Fly mode
+ LLFloaterMove::setFlyingMode(fly);
+
mbFlagsDirty = TRUE;
}
@@ -820,12 +800,29 @@ void LLAgent::setFlying(BOOL fly)
//-----------------------------------------------------------------------------
// toggleFlying()
//-----------------------------------------------------------------------------
+// static
void LLAgent::toggleFlying()
{
- BOOL fly = !(mControlFlags & AGENT_CONTROL_FLY);
+ BOOL fly = !gAgent.getFlying();
- setFlying( fly );
- resetView();
+ gAgent.setFlying( fly );
+ gAgent.resetView();
+}
+
+// static
+bool LLAgent::enableFlying()
+{
+ BOOL sitting = FALSE;
+ if (gAgent.getAvatarObject())
+ {
+ sitting = gAgent.getAvatarObject()->isSitting();
+ }
+ return !sitting;
+}
+
+void LLAgent::standUp()
+{
+ setControlFlags(AGENT_CONTROL_STAND_UP);
}
@@ -902,6 +899,8 @@ void LLAgent::setRegion(LLViewerRegion *regionp)
mRegionsVisited.insert(handle);
LLSelectMgr::getInstance()->updateSelectionCenter();
+
+ LLFloaterMove::sUpdateFlyingStatus();
}
@@ -914,7 +913,7 @@ LLViewerRegion *LLAgent::getRegion() const
}
-const LLHost& LLAgent::getRegionHost() const
+LLHost LLAgent::getRegionHost() const
{
if (mRegionp)
{
@@ -927,25 +926,6 @@ const LLHost& LLAgent::getRegionHost() const
}
//-----------------------------------------------------------------------------
-// getSLURL()
-// returns empty() if getRegion() == NULL
-//-----------------------------------------------------------------------------
-std::string LLAgent::getSLURL() const
-{
- std::string slurl;
- LLViewerRegion *regionp = getRegion();
- if (regionp)
- {
- LLVector3d agentPos = getPositionGlobal();
- S32 x = llround( (F32)fmod( agentPos.mdV[VX], (F64)REGION_WIDTH_METERS ) );
- S32 y = llround( (F32)fmod( agentPos.mdV[VY], (F64)REGION_WIDTH_METERS ) );
- S32 z = llround( (F32)agentPos.mdV[VZ] );
- slurl = LLURLDispatcher::buildSLURL(regionp->getName(), x, y, z);
- }
- return slurl;
-}
-
-//-----------------------------------------------------------------------------
// inPrelude()
//-----------------------------------------------------------------------------
BOOL LLAgent::inPrelude()
@@ -1258,7 +1238,7 @@ F32 LLAgent::clampPitchToLimits(F32 angle)
F32 angle_from_skyward = acos( mFrameAgent.getAtAxis() * skyward );
- if (mAvatarObject.notNull() && mAvatarObject->mIsSitting)
+ if (mAvatarObject.notNull() && mAvatarObject->isSitting())
{
look_down_limit = 130.f * DEG_TO_RAD;
}
@@ -1317,14 +1297,19 @@ LLQuaternion LLAgent::getQuat() const
//-----------------------------------------------------------------------------
LLVector3 LLAgent::calcFocusOffset(LLViewerObject *object, LLVector3 original_focus_point, S32 x, S32 y)
{
- // calculate offset based on view direction
- BOOL is_avatar = object->isAvatar();
- // since the animation system allows the avatars facing and position to deviate from its nominal LLViewerObject/LLDrawable transform
- // calculate the focus-specific orientation for avatars based off the pelvis joint
- // NOTE: pelvis no longer good candidate, removed. DEV-30589
LLMatrix4 obj_matrix = object->getRenderMatrix();
LLQuaternion obj_rot = object->getRenderRotation();
LLVector3 obj_pos = object->getRenderPosition();
+
+ BOOL is_avatar = object->isAvatar();
+ // if is avatar - don't do any funk heuristics to position the focal point
+ // see DEV-30589
+ if (is_avatar)
+ {
+ return original_focus_point - obj_pos;
+ }
+
+
LLQuaternion inv_obj_rot = ~obj_rot; // get inverse of rotation
LLVector3 object_extents = object->getScale();
// make sure they object extents are non-zero
@@ -1883,7 +1868,7 @@ void LLAgent::cameraOrbitIn(const F32 meters)
{
if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON)
{
- F32 camera_offset_dist = llmax(0.001f, mCameraOffsetDefault.magVec() * gSavedSettings.getF32("CameraOffsetScale"));
+ F32 camera_offset_dist = llmax(0.001f, getCameraOffsetInitial().magVec() * gSavedSettings.getF32("CameraOffsetScale"));
mCameraZoomFraction = (mTargetCameraDistance - meters) / camera_offset_dist;
@@ -2117,8 +2102,7 @@ void LLAgent::setAFK()
gAwayTimer.start();
if (gAFKMenu)
{
- //*TODO:Translate
- gAFKMenu->setLabel(std::string("Set Not Away"));
+ gAFKMenu->setLabel(LLTrans::getString("AvatarSetNotAway"));
}
}
}
@@ -2141,8 +2125,7 @@ void LLAgent::clearAFK()
clearControlFlags(AGENT_CONTROL_AWAY);
if (gAFKMenu)
{
- //*TODO:Translate
- gAFKMenu->setLabel(std::string("Set Away"));
+ gAFKMenu->setLabel(LLTrans::getString("AvatarSetAway"));
}
}
}
@@ -2164,10 +2147,9 @@ void LLAgent::setBusy()
mIsBusy = TRUE;
if (gBusyMenu)
{
- //*TODO:Translate
- gBusyMenu->setLabel(std::string("Set Not Busy"));
+ gBusyMenu->setLabel(LLTrans::getString("AvatarSetNotBusy"));
}
- LLFloaterMute::getInstance()->updateButtons();
+ LLNotificationsUI::LLChannelManager::getInstance()->muteAllChannels(true);
}
//-----------------------------------------------------------------------------
@@ -2179,10 +2161,9 @@ void LLAgent::clearBusy()
sendAnimationRequest(ANIM_AGENT_BUSY, ANIM_REQUEST_STOP);
if (gBusyMenu)
{
- //*TODO:Translate
- gBusyMenu->setLabel(std::string("Set Busy"));
+ gBusyMenu->setLabel(LLTrans::getString("AvatarSetBusy"));
}
- LLFloaterMute::getInstance()->updateButtons();
+ LLNotificationsUI::LLChannelManager::getInstance()->muteAllChannels(false);
}
//-----------------------------------------------------------------------------
@@ -2331,11 +2312,11 @@ void LLAgent::stopAutoPilot(BOOL user_cancel)
if (user_cancel && !mAutoPilotBehaviorName.empty())
{
if (mAutoPilotBehaviorName == "Sit")
- LLNotifications::instance().add("CancelledSit");
+ LLNotificationsUtil::add("CancelledSit");
else if (mAutoPilotBehaviorName == "Attach")
- LLNotifications::instance().add("CancelledAttach");
+ LLNotificationsUtil::add("CancelledAttach");
else
- LLNotifications::instance().add("Cancelled");
+ LLNotificationsUtil::add("Cancelled");
}
}
}
@@ -2505,13 +2486,11 @@ void LLAgent::autoPilot(F32 *delta_yaw)
void LLAgent::propagate(const F32 dt)
{
// Update UI based on agent motion
- LLFloaterMove *floater_move = LLFloaterMove::getInstance();
+ LLFloaterMove *floater_move = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview");
if (floater_move)
{
floater_move->mForwardButton ->setToggleState( mAtKey > 0 || mWalkKey > 0 );
floater_move->mBackwardButton ->setToggleState( mAtKey < 0 || mWalkKey < 0 );
- floater_move->mSlideLeftButton ->setToggleState( mLeftKey > 0 );
- floater_move->mSlideRightButton->setToggleState( mLeftKey < 0 );
floater_move->mTurnLeftButton ->setToggleState( mYawKey > 0.f );
floater_move->mTurnRightButton ->setToggleState( mYawKey < 0.f );
floater_move->mMoveUpButton ->setToggleState( mUpKey > 0 );
@@ -2520,10 +2499,10 @@ void LLAgent::propagate(const F32 dt)
// handle rotation based on keyboard levels
const F32 YAW_RATE = 90.f * DEG_TO_RAD; // radians per second
- yaw( YAW_RATE * mYawKey * dt );
+ yaw(YAW_RATE * mYawKey * dt);
const F32 PITCH_RATE = 90.f * DEG_TO_RAD; // radians per second
- pitch(PITCH_RATE * (F32) mPitchKey * dt);
+ pitch(PITCH_RATE * mPitchKey * dt);
// handle auto-land behavior
if (mAvatarObject.notNull())
@@ -2548,7 +2527,7 @@ void LLAgent::propagate(const F32 dt)
mLeftKey = 0;
mUpKey = 0;
mYawKey = 0.f;
- mPitchKey = 0;
+ mPitchKey = 0.f;
}
//-----------------------------------------------------------------------------
@@ -2596,7 +2575,7 @@ void LLAgent::updateLookAt(const S32 mouse_x, const S32 mouse_y)
else
{
// *FIX: rotate mframeagent by sit object's rotation?
- LLQuaternion look_rotation = mAvatarObject->mIsSitting ? mAvatarObject->getRenderRotation() : mFrameAgent.getQuaternion(); // use camera's current rotation
+ LLQuaternion look_rotation = mAvatarObject->isSitting() ? mAvatarObject->getRenderRotation() : mFrameAgent.getQuaternion(); // use camera's current rotation
LLVector3 look_offset = LLVector3(2.f, 0.f, 0.f) * look_rotation * av_inv_rot;
setLookAt(LOOKAT_TARGET_IDLE, mAvatarObject, look_offset);
}
@@ -2625,9 +2604,9 @@ void LLAgent::updateLookAt(const S32 mouse_x, const S32 mouse_y)
{
// range from -.5 to .5
F32 x_from_center =
- ((F32) mouse_x / (F32) gViewerWindow->getWindowWidth() ) - 0.5f;
+ ((F32) mouse_x / (F32) gViewerWindow->getWindowWidthScaled() ) - 0.5f;
F32 y_from_center =
- ((F32) mouse_y / (F32) gViewerWindow->getWindowHeight() ) - 0.5f;
+ ((F32) mouse_y / (F32) gViewerWindow->getWindowHeightScaled() ) - 0.5f;
frameCamera.yaw( - x_from_center * gSavedSettings.getF32("YawFromMousePosition") * DEG_TO_RAD);
frameCamera.pitch( - y_from_center * gSavedSettings.getF32("PitchFromMousePosition") * DEG_TO_RAD);
@@ -2662,7 +2641,7 @@ std::ostream& operator<<(std::ostream &s, const LLAgent &agent)
//-----------------------------------------------------------------------------
// setAvatarObject()
//-----------------------------------------------------------------------------
-void LLAgent::setAvatarObject(LLVOAvatar *avatar)
+void LLAgent::setAvatarObject(LLVOAvatarSelf *avatar)
{
mAvatarObject = avatar;
@@ -2689,8 +2668,6 @@ void LLAgent::setAvatarObject(LLVOAvatar *avatar)
{
mPointAt->setSourceObject(avatar);
}
-
- sendAgentWearablesRequest();
}
// TRUE if your own avatar needs to be rendered. Usually only
@@ -2741,7 +2718,7 @@ void LLAgent::startTyping()
{
sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_START);
}
- gChatBar->sendChatFromViewer("", CHAT_TYPE_START, FALSE);
+ LLNearbyChatBar::getInstance()->sendChatFromViewer("", CHAT_TYPE_START, FALSE);
}
//-----------------------------------------------------------------------------
@@ -2753,7 +2730,7 @@ void LLAgent::stopTyping()
{
clearRenderState(AGENT_STATE_TYPING);
sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_STOP);
- gChatBar->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE);
+ LLNearbyChatBar::getInstance()->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE);
}
}
@@ -2807,13 +2784,6 @@ U8 LLAgent::getRenderState()
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
-static const LLFloaterView::skip_list_t& get_skip_list()
-{
- static LLFloaterView::skip_list_t skip_list;
- skip_list.insert(LLFloaterMap::getInstance());
- return skip_list;
-}
-
//-----------------------------------------------------------------------------
// endAnimationUpdateUI()
//-----------------------------------------------------------------------------
@@ -2832,17 +2802,39 @@ void LLAgent::endAnimationUpdateUI()
gViewerWindow->showCursor();
// show menus
gMenuBarView->setVisible(TRUE);
+ LLNavigationBar::getInstance()->setVisible(TRUE);
gStatusBar->setVisibleForMouselook(true);
+ LLBottomTray::getInstance()->setVisible(TRUE);
+ LLBottomTray::getInstance()->onMouselookModeOut();
+
+ LLSideTray::getInstance()->getButtonsPanel()->setVisible(TRUE);
+ LLSideTray::getInstance()->updateSidetrayVisibility();
+
+ LLPanelStandStopFlying::getInstance()->setVisible(TRUE);
+
LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
+ LLFloaterCamera::onLeavingMouseLook();
+
// Only pop if we have pushed...
if (TRUE == mViewsPushed)
{
+#if 0 // Use this once all floaters are registered
+ LLFloaterReg::restoreVisibleInstances();
+#else // Use this for now
+ LLFloaterView::skip_list_t skip_list;
+ if (LLFloaterReg::findInstance("mini_map"))
+ {
+ skip_list.insert(LLFloaterReg::findInstance("mini_map"));
+ }
+
+ gFloaterView->popVisibleAll(skip_list);
+#endif
mViewsPushed = FALSE;
- gFloaterView->popVisibleAll(get_skip_list());
}
+
gAgent.setLookAt(LOOKAT_TARGET_CLEAR);
if( gMorphView )
{
@@ -2884,13 +2876,6 @@ void LLAgent::endAnimationUpdateUI()
LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
- // HACK: If we're quitting, and we were in customize avatar, don't
- // let the mini-map go visible again. JC
- if (!LLAppViewer::instance()->quitRequested())
- {
- LLFloaterMap::getInstance()->popVisible();
- }
-
if( gMorphView )
{
gMorphView->setVisible( FALSE );
@@ -2917,8 +2902,17 @@ void LLAgent::endAnimationUpdateUI()
{
// hide menus
gMenuBarView->setVisible(FALSE);
+ LLNavigationBar::getInstance()->setVisible(FALSE);
gStatusBar->setVisibleForMouselook(false);
+ LLBottomTray::getInstance()->onMouselookModeIn();
+ LLBottomTray::getInstance()->setVisible(FALSE);
+
+ LLSideTray::getInstance()->getButtonsPanel()->setVisible(FALSE);
+ LLSideTray::getInstance()->updateSidetrayVisibility();
+
+ LLPanelStandStopFlying::getInstance()->setVisible(FALSE);
+
// clear out camera lag effect
mCameraLag.clearVec();
@@ -2929,14 +2923,23 @@ void LLAgent::endAnimationUpdateUI()
mViewsPushed = TRUE;
- gFloaterView->pushVisibleAll(FALSE, get_skip_list());
+ // hide all floaters except the mini map
+
+#if 0 // Use this once all floaters are registered
+ std::set<std::string> exceptions;
+ exceptions.insert("mini_map");
+ LLFloaterReg::hideVisibleInstances(exceptions);
+#else // Use this for now
+ LLFloaterView::skip_list_t skip_list;
+ skip_list.insert(LLFloaterReg::findInstance("mini_map"));
+ gFloaterView->pushVisibleAll(FALSE, skip_list);
+#endif
if( gMorphView )
{
gMorphView->setVisible(FALSE);
}
- gIMMgr->setFloaterOpen( FALSE );
gConsole->setVisible( TRUE );
if (mAvatarObject.notNull())
@@ -2985,15 +2988,6 @@ void LLAgent::endAnimationUpdateUI()
{
LLToolMgr::getInstance()->setCurrentToolset(gFaceEditToolset);
- LLFloaterMap::getInstance()->pushVisible(FALSE);
- /*
- LLView *view;
- for (view = gFloaterView->getFirstChild(); view; view = gFloaterView->getNextChild())
- {
- view->pushVisible(FALSE);
- }
- */
-
if( gMorphView )
{
gMorphView->setVisible( TRUE );
@@ -3035,7 +3029,7 @@ void LLAgent::updateCamera()
validateFocusObject();
if (mAvatarObject.notNull() &&
- mAvatarObject->mIsSitting &&
+ mAvatarObject->isSitting() &&
camera_mode == CAMERA_MODE_MOUSELOOK)
{
//Ventrella
@@ -3066,21 +3060,21 @@ void LLAgent::updateCamera()
}
// Update UI with our camera inputs
- LLFloaterCamera::getInstance()->mRotate->setToggleState(
+ LLFloaterCamera* camera_floater = LLFloaterReg::findTypedInstance<LLFloaterCamera>("camera");
+ if (camera_floater)
+ {
+ camera_floater->mRotate->setToggleState(
mOrbitRightKey > 0.f, // left
mOrbitUpKey > 0.f, // top
mOrbitLeftKey > 0.f, // right
mOrbitDownKey > 0.f); // bottom
- LLFloaterCamera::getInstance()->mZoom->setToggleState(
- mOrbitInKey > 0.f, // top
- mOrbitOutKey > 0.f); // bottom
-
- LLFloaterCamera::getInstance()->mTrack->setToggleState(
+ camera_floater->mTrack->setToggleState(
mPanLeftKey > 0.f, // left
mPanUpKey > 0.f, // top
mPanRightKey > 0.f, // right
mPanDownKey > 0.f); // bottom
+ }
// Handle camera movement based on keyboard.
const F32 ORBIT_OVER_RATE = 90.f * DEG_TO_RAD; // radians per second
@@ -3156,7 +3150,7 @@ void LLAgent::updateCamera()
// (2) focus, and (3) upvector. They can then be queried elsewhere in llAgent.
//--------------------------------------------------------------------------------
// *TODO: use combined rotation of frameagent and sit object
- LLQuaternion avatarRotationForFollowCam = mAvatarObject->mIsSitting ? mAvatarObject->getRenderRotation() : mFrameAgent.getQuaternion();
+ LLQuaternion avatarRotationForFollowCam = mAvatarObject->isSitting() ? mAvatarObject->getRenderRotation() : mFrameAgent.getQuaternion();
LLFollowCamParams* current_cam = LLFollowCamMgr::getActiveFollowCamParams();
if (current_cam)
@@ -3164,6 +3158,7 @@ void LLAgent::updateCamera()
mFollowCam.copyParams(*current_cam);
mFollowCam.setSubjectPositionAndRotation( mAvatarObject->getRenderPosition(), avatarRotationForFollowCam );
mFollowCam.update();
+ LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true);
}
else
{
@@ -3336,7 +3331,7 @@ void LLAgent::updateCamera()
}
mLastPositionGlobal = global_pos;
- if (LLVOAvatar::sVisibleInFirstPerson && mAvatarObject.notNull() && !mAvatarObject->mIsSitting && cameraMouselook())
+ if (LLVOAvatar::sVisibleInFirstPerson && mAvatarObject.notNull() && !mAvatarObject->isSitting() && cameraMouselook())
{
LLVector3 head_pos = mAvatarObject->mHeadp->getWorldPosition() +
LLVector3(0.08f, 0.f, 0.05f) * mAvatarObject->mHeadp->getWorldRotation() +
@@ -3373,13 +3368,18 @@ void LLAgent::updateCamera()
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
- LLViewerObject *attached_object = attachment->getObject();
- if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull())
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- // clear any existing "early" movements of attachment
- attached_object->mDrawable->clearState(LLDrawable::EARLY_MOVE);
- gPipeline.updateMoveNormalAsync(attached_object->mDrawable);
- attached_object->updateText();
+ LLViewerObject *attached_object = (*attachment_iter);
+ if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull())
+ {
+ // clear any existing "early" movements of attachment
+ attached_object->mDrawable->clearState(LLDrawable::EARLY_MOVE);
+ gPipeline.updateMoveNormalAsync(attached_object->mDrawable);
+ attached_object->updateText();
+ }
}
}
@@ -3421,11 +3421,11 @@ F32 LLAgent::calcCustomizeAvatarUIOffset( const LLVector3d& camera_pos_global )
const LLRect& rect = gFloaterCustomize->getRect();
// Move the camera so that the avatar isn't covered up by this floater.
- F32 fraction_of_fov = 0.5f - (0.5f * (1.f - llmin(1.f, ((F32)rect.getWidth() / (F32)gViewerWindow->getWindowWidth()))));
+ F32 fraction_of_fov = 0.5f - (0.5f * (1.f - llmin(1.f, ((F32)rect.getWidth() / (F32)gViewerWindow->getWindowWidthScaled()))));
F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect(); // radians
F32 offset = tan(apparent_angle);
- if( rect.mLeft < (gViewerWindow->getWindowWidth() - rect.mRight) )
+ if( rect.mLeft < (gViewerWindow->getWindowWidthScaled() - rect.mRight) )
{
// Move the avatar to the right (camera to the left)
ui_offset = offset;
@@ -3516,7 +3516,7 @@ LLVector3d LLAgent::calcFocusPositionTargetGlobal()
}
return mFocusTargetGlobal;
}
- else if (mSitCameraEnabled && mAvatarObject.notNull() && mAvatarObject->mIsSitting && mSitCameraReferenceObject.notNull())
+ else if (mSitCameraEnabled && mAvatarObject.notNull() && mAvatarObject->isSitting() && mSitCameraReferenceObject.notNull())
{
// sit camera
LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition();
@@ -3535,7 +3535,6 @@ LLVector3d LLAgent::calcThirdPersonFocusOffset()
{
// ...offset from avatar
LLVector3d focus_offset;
- focus_offset.setVec(gSavedSettings.getVector3("FocusOffsetDefault"));
LLQuaternion agent_rot = mFrameAgent.getQuaternion();
if (!mAvatarObject.isNull() && mAvatarObject->getParent())
@@ -3543,7 +3542,7 @@ LLVector3d LLAgent::calcThirdPersonFocusOffset()
agent_rot *= ((LLViewerObject*)(mAvatarObject->getParent()))->getRenderRotation();
}
- focus_offset = focus_offset * agent_rot;
+ focus_offset = mFocusOffsetInitial[mCameraPreset] * agent_rot;
return focus_offset;
}
@@ -3589,7 +3588,7 @@ F32 LLAgent::calcCameraFOVZoomFactor()
{
return 0.f;
}
- else if (mFocusObject.notNull() && !mFocusObject->isAvatar())
+ else if (mFocusObject.notNull() && !mFocusObject->isAvatar() && !mFocusOnAvatar)
{
// don't FOV zoom on mostly transparent objects
LLVector3 focus_offset = mFocusObjectOffset;
@@ -3620,7 +3619,6 @@ LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit)
LLVector3d frame_center_global = mAvatarObject.isNull() ? getPositionGlobal()
: getPosGlobalFromAgent(mAvatarObject->mRoot.getWorldPosition());
- LLVector3 upAxis = getUpAxis();
BOOL isConstrained = FALSE;
LLVector3d head_offset;
head_offset.setVec(mThirdPersonHeadOffset);
@@ -3640,7 +3638,7 @@ LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit)
return LLVector3d::zero;
}
head_offset.clearVec();
- if (mAvatarObject->mIsSitting && mAvatarObject->getParent())
+ if (mAvatarObject->isSitting() && mAvatarObject->getParent())
{
mAvatarObject->updateHeadOffset();
head_offset.mdV[VX] = mAvatarObject->mHeadOffset.mV[VX];
@@ -3654,7 +3652,7 @@ LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit)
else
{
head_offset.mdV[VZ] = mAvatarObject->mHeadOffset.mV[VZ];
- if (mAvatarObject->mIsSitting)
+ if (mAvatarObject->isSitting())
{
head_offset.mdV[VZ] += 0.1;
}
@@ -3670,7 +3668,7 @@ LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit)
if (mSitCameraEnabled
&& mAvatarObject.notNull()
- && mAvatarObject->mIsSitting
+ && mAvatarObject->isSitting()
&& mSitCameraReferenceObject.notNull())
{
// sit camera
@@ -3683,7 +3681,7 @@ LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit)
}
else
{
- local_camera_offset = mCameraZoomFraction * mCameraOffsetDefault * gSavedSettings.getF32("CameraOffsetScale");
+ local_camera_offset = mCameraZoomFraction * getCameraOffsetInitial() * gSavedSettings.getF32("CameraOffsetScale");
// are we sitting down?
if (mAvatarObject.notNull() && mAvatarObject->getParent())
@@ -3702,7 +3700,7 @@ LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit)
local_camera_offset = mFrameAgent.rotateToAbsolute( local_camera_offset );
}
- if (!mCameraCollidePlane.isExactlyZero() && (mAvatarObject.isNull() || !mAvatarObject->mIsSitting))
+ if (!mCameraCollidePlane.isExactlyZero() && (mAvatarObject.isNull() || !mAvatarObject->isSitting()))
{
LLVector3 plane_normal;
plane_normal.setVec(mCameraCollidePlane.mV);
@@ -3880,6 +3878,12 @@ LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit)
}
+LLVector3 LLAgent::getCameraOffsetInitial()
+{
+ return mCameraOffsetInitial[mCameraPreset];
+}
+
+
//-----------------------------------------------------------------------------
// handleScrollWheel()
//-----------------------------------------------------------------------------
@@ -3914,10 +3918,12 @@ void LLAgent::handleScrollWheel(S32 clicks)
}
else if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON)
{
- F32 current_zoom_fraction = mTargetCameraDistance / (mCameraOffsetDefault.magVec() * gSavedSettings.getF32("CameraOffsetScale"));
+ F32 camera_offset_initial_mag = getCameraOffsetInitial().magVec();
+
+ F32 current_zoom_fraction = mTargetCameraDistance / (camera_offset_initial_mag * gSavedSettings.getF32("CameraOffsetScale"));
current_zoom_fraction *= 1.f - pow(ROOT_ROOT_TWO, clicks);
- cameraOrbitIn(current_zoom_fraction * mCameraOffsetDefault.magVec() * gSavedSettings.getF32("CameraOffsetScale"));
+ cameraOrbitIn(current_zoom_fraction * camera_offset_initial_mag * gSavedSettings.getF32("CameraOffsetScale"));
}
else
{
@@ -3985,11 +3991,6 @@ void LLAgent::changeCameraToMouselook(BOOL animate)
LLToolMgr::getInstance()->setCurrentToolset(gMouselookToolset);
- gSavedSettings.setBOOL("FirstPersonBtnState", FALSE);
- gSavedSettings.setBOOL("MouselookBtnState", TRUE);
- gSavedSettings.setBOOL("ThirdPersonBtnState", FALSE);
- gSavedSettings.setBOOL("BuildBtnState", FALSE);
-
if (mAvatarObject.notNull())
{
mAvatarObject->stopMotion( ANIM_AGENT_BODY_NOISE );
@@ -4085,11 +4086,6 @@ void LLAgent::changeCameraToFollow(BOOL animate)
mAvatarObject->startMotion( ANIM_AGENT_BREATHE_ROT );
}
- gSavedSettings.setBOOL("FirstPersonBtnState", FALSE);
- gSavedSettings.setBOOL("MouselookBtnState", FALSE);
- gSavedSettings.setBOOL("ThirdPersonBtnState", TRUE);
- gSavedSettings.setBOOL("BuildBtnState", FALSE);
-
// unpause avatar animation
mPauseRequest = NULL;
@@ -4128,7 +4124,7 @@ void LLAgent::changeCameraToThirdPerson(BOOL animate)
if (mAvatarObject.notNull())
{
- if (!mAvatarObject->mIsSitting)
+ if (!mAvatarObject->isSitting())
{
mAvatarObject->mPelvisp->setPosition(LLVector3::zero);
}
@@ -4136,11 +4132,6 @@ void LLAgent::changeCameraToThirdPerson(BOOL animate)
mAvatarObject->startMotion( ANIM_AGENT_BREATHE_ROT );
}
- gSavedSettings.setBOOL("FirstPersonBtnState", FALSE);
- gSavedSettings.setBOOL("MouselookBtnState", FALSE);
- gSavedSettings.setBOOL("ThirdPersonBtnState", TRUE);
- gSavedSettings.setBOOL("BuildBtnState", FALSE);
-
LLVector3 at_axis;
// unpause avatar animation
@@ -4210,7 +4201,7 @@ void LLAgent::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL camera_ani
return;
}
- setControlFlags(AGENT_CONTROL_STAND_UP); // force stand up
+ standUp(); // force stand up
gViewerWindow->getWindow()->resetBusyCount();
if (gFaceEditToolset)
@@ -4218,11 +4209,6 @@ void LLAgent::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL camera_ani
LLToolMgr::getInstance()->setCurrentToolset(gFaceEditToolset);
}
- gSavedSettings.setBOOL("FirstPersonBtnState", FALSE);
- gSavedSettings.setBOOL("MouselookBtnState", FALSE);
- gSavedSettings.setBOOL("ThirdPersonBtnState", FALSE);
- gSavedSettings.setBOOL("BuildBtnState", FALSE);
-
if (camera_animate)
{
startCameraAnimation();
@@ -4248,14 +4234,14 @@ void LLAgent::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL camera_ani
gFocusMgr.setKeyboardFocus( NULL );
gFocusMgr.setMouseCapture( NULL );
- LLVOAvatar::onCustomizeStart();
+ LLVOAvatarSelf::onCustomizeStart();
}
if (mAvatarObject.notNull())
{
if(avatar_animate)
{
- // Remove any pitch from the avatar
+ // Remove any pitch from the avatar
LLVector3 at = mFrameAgent.getAtAxis();
at.mV[VZ] = 0.f;
at.normalize();
@@ -4290,6 +4276,20 @@ void LLAgent::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL camera_ani
}
+void LLAgent::switchCameraPreset(ECameraPreset preset)
+{
+ //zoom is supposed to be reset for the front and group views
+ mCameraZoomFraction = 1.f;
+
+ //focusing on avatar in that case means following him on movements
+ mFocusOnAvatar = TRUE;
+
+ mCameraPreset = preset;
+
+ gSavedSettings.setU32("CameraPreset", mCameraPreset);
+}
+
+
//
// Focus point management
//
@@ -4674,109 +4674,128 @@ void LLAgent::lookAtLastChat()
const F32 SIT_POINT_EXTENTS = 0.2f;
+LLSD ll_sdmap_from_vector3(const LLVector3& vec)
+{
+ LLSD ret;
+ ret["X"] = vec.mV[VX];
+ ret["Y"] = vec.mV[VY];
+ ret["Z"] = vec.mV[VZ];
+ return ret;
+}
+
+LLVector3 ll_vector3_from_sdmap(const LLSD& sd)
+{
+ LLVector3 ret;
+ ret.mV[VX] = F32(sd["X"].asReal());
+ ret.mV[VY] = F32(sd["Y"].asReal());
+ ret.mV[VZ] = F32(sd["Z"].asReal());
+ return ret;
+}
+
void LLAgent::setStartPosition( U32 location_id )
{
- LLViewerObject *object;
+ LLViewerObject *object;
- if ( !(gAgentID == LLUUID::null) )
- {
+ if (gAgentID == LLUUID::null)
+ {
+ return;
+ }
// we've got an ID for an agent viewerobject
object = gObjectList.findObject(gAgentID);
- if (object)
+ if (! object)
{
- // we've got the viewer object
- // Sometimes the agent can be velocity interpolated off of
- // this simulator. Clamp it to the region the agent is
- // in, a little bit in on each side.
- const F32 INSET = 0.5f; //meters
- const F32 REGION_WIDTH = LLWorld::getInstance()->getRegionWidthInMeters();
-
- LLVector3 agent_pos = getPositionAgent();
- LLVector3 agent_look_at = mFrameAgent.getAtAxis();
-
- if (mAvatarObject.notNull())
- {
- // the z height is at the agent's feet
- agent_pos.mV[VZ] -= 0.5f * mAvatarObject->mBodySize.mV[VZ];
- }
-
- agent_pos.mV[VX] = llclamp( agent_pos.mV[VX], INSET, REGION_WIDTH - INSET );
- agent_pos.mV[VY] = llclamp( agent_pos.mV[VY], INSET, REGION_WIDTH - INSET );
-
- // Don't let them go below ground, or too high.
- agent_pos.mV[VZ] = llclamp( agent_pos.mV[VZ],
- mRegionp->getLandHeightRegion( agent_pos ),
- LLWorld::getInstance()->getRegionMaxHeight() );
- // Send the CapReq
-
- LLSD body;
-
- std::string url = gAgent.getRegion()->getCapability("HomeLocation");
- std::ostringstream strBuffer;
- if( url.empty() )
- {
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_SetStartLocationRequest);
- msg->nextBlockFast( _PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, getID());
- msg->addUUIDFast(_PREHASH_SessionID, getSessionID());
- msg->nextBlockFast( _PREHASH_StartLocationData);
- // corrected by sim
- msg->addStringFast(_PREHASH_SimName, "");
- msg->addU32Fast(_PREHASH_LocationID, location_id);
- msg->addVector3Fast(_PREHASH_LocationPos, agent_pos);
- msg->addVector3Fast(_PREHASH_LocationLookAt,mFrameAgent.getAtAxis());
-
- // Reliable only helps when setting home location. Last
- // location is sent on quit, and we don't have time to ack
- // the packets.
- msg->sendReliable(mRegionp->getHost());
-
- const U32 HOME_INDEX = 1;
- if( HOME_INDEX == location_id )
- {
- setHomePosRegion( mRegionp->getHandle(), getPositionAgent() );
- }
- }
- else
- {
- strBuffer << location_id;
- body["HomeLocation"]["LocationId"] = strBuffer.str();
-
- strBuffer.str("");
- strBuffer << agent_pos.mV[VX];
- body["HomeLocation"]["LocationPos"]["X"] = strBuffer.str();
-
- strBuffer.str("");
- strBuffer << agent_pos.mV[VY];
- body["HomeLocation"]["LocationPos"]["Y"] = strBuffer.str();
-
- strBuffer.str("");
- strBuffer << agent_pos.mV[VZ];
- body["HomeLocation"]["LocationPos"]["Z"] = strBuffer.str();
-
- strBuffer.str("");
- strBuffer << agent_look_at.mV[VX];
- body["HomeLocation"]["LocationLookAt"]["X"] = strBuffer.str();
-
- strBuffer.str("");
- strBuffer << agent_look_at.mV[VY];
- body["HomeLocation"]["LocationLookAt"]["Y"] = strBuffer.str();
-
- strBuffer.str("");
- strBuffer << agent_look_at.mV[VZ];
- body["HomeLocation"]["LocationLookAt"]["Z"] = strBuffer.str();
-
- LLHTTPClient::post( url, body, new LLHomeLocationResponder() );
- }
+ llinfos << "setStartPosition - Can't find agent viewerobject id " << gAgentID << llendl;
+ return;
+ }
+ // we've got the viewer object
+ // Sometimes the agent can be velocity interpolated off of
+ // this simulator. Clamp it to the region the agent is
+ // in, a little bit in on each side.
+ const F32 INSET = 0.5f; //meters
+ const F32 REGION_WIDTH = LLWorld::getInstance()->getRegionWidthInMeters();
+
+ LLVector3 agent_pos = getPositionAgent();
+
+ if (mAvatarObject.notNull())
+ {
+ // the z height is at the agent's feet
+ agent_pos.mV[VZ] -= 0.5f * mAvatarObject->mBodySize.mV[VZ];
}
- else
+
+ agent_pos.mV[VX] = llclamp( agent_pos.mV[VX], INSET, REGION_WIDTH - INSET );
+ agent_pos.mV[VY] = llclamp( agent_pos.mV[VY], INSET, REGION_WIDTH - INSET );
+
+ // Don't let them go below ground, or too high.
+ agent_pos.mV[VZ] = llclamp( agent_pos.mV[VZ],
+ mRegionp->getLandHeightRegion( agent_pos ),
+ LLWorld::getInstance()->getRegionMaxHeight() );
+ // Send the CapReq
+ LLSD request;
+ LLSD body;
+ LLSD homeLocation;
+
+ homeLocation["LocationId"] = LLSD::Integer(location_id);
+ homeLocation["LocationPos"] = ll_sdmap_from_vector3(agent_pos);
+ homeLocation["LocationLookAt"] = ll_sdmap_from_vector3(mFrameAgent.getAtAxis());
+
+ body["HomeLocation"] = homeLocation;
+
+ // This awkward idiom warrants explanation.
+ // For starters, LLSDMessage::ResponderAdapter is ONLY for testing the new
+ // LLSDMessage functionality with a pre-existing LLHTTPClient::Responder.
+ // In new code, define your reply/error methods on the same class as the
+ // sending method, bind them to local LLEventPump objects and pass those
+ // LLEventPump names in the request LLSD object.
+ // When testing old code, the new LLHomeLocationResponder object
+ // is referenced by an LLHTTPClient::ResponderPtr, so when the
+ // ResponderAdapter is deleted, the LLHomeLocationResponder will be too.
+ // We must trust that the underlying LLHTTPClient code will eventually
+ // fire either the reply callback or the error callback; either will cause
+ // the ResponderAdapter to delete itself.
+ LLSDMessage::ResponderAdapter*
+ adapter(new LLSDMessage::ResponderAdapter(new LLHomeLocationResponder()));
+
+ request["message"] = "HomeLocation";
+ request["payload"] = body;
+ request["reply"] = adapter->getReplyName();
+ request["error"] = adapter->getErrorName();
+
+ gAgent.getRegion()->getCapAPI().post(request);
+
+ const U32 HOME_INDEX = 1;
+ if( HOME_INDEX == location_id )
{
- llinfos << "setStartPosition - Can't find agent viewerobject id " << gAgentID << llendl;
+ setHomePosRegion( mRegionp->getHandle(), getPositionAgent() );
}
- }
}
+struct HomeLocationMapper: public LLCapabilityListener::CapabilityMapper
+{
+ // No reply message expected
+ HomeLocationMapper(): LLCapabilityListener::CapabilityMapper("HomeLocation") {}
+ virtual void buildMessage(LLMessageSystem* msg,
+ const LLUUID& agentID,
+ const LLUUID& sessionID,
+ const std::string& capabilityName,
+ const LLSD& payload) const
+ {
+ msg->newMessageFast(_PREHASH_SetStartLocationRequest);
+ msg->nextBlockFast( _PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, agentID);
+ msg->addUUIDFast(_PREHASH_SessionID, sessionID);
+ msg->nextBlockFast( _PREHASH_StartLocationData);
+ // corrected by sim
+ msg->addStringFast(_PREHASH_SimName, "");
+ msg->addU32Fast(_PREHASH_LocationID, payload["HomeLocation"]["LocationId"].asInteger());
+ msg->addVector3Fast(_PREHASH_LocationPos,
+ ll_vector3_from_sdmap(payload["HomeLocation"]["LocationPos"]));
+ msg->addVector3Fast(_PREHASH_LocationLookAt,
+ ll_vector3_from_sdmap(payload["HomeLocation"]["LocationLookAt"]));
+ }
+};
+// Need an instance of this class so it will self-register
+static HomeLocationMapper homeLocationMapper;
+
void LLAgent::requestStopMotion( LLMotion* motion )
{
// Notify all avatars that a motion has stopped.
@@ -4914,6 +4933,9 @@ int LLAgent::convertTextToMaturity(char text)
bool LLAgent::sendMaturityPreferenceToServer(int preferredMaturity)
{
+ if (!getRegion())
+ return false;
+
// Update agent access preference on the server
std::string url = getRegion()->getCapability("UpdateAgentInformation");
if (!url.empty())
@@ -4973,15 +4995,19 @@ const LLAgentAccess& LLAgent::getAgentAccess()
return mAgentAccess;
}
+bool LLAgent::validateMaturity(const LLSD& newvalue)
+{
+ return mAgentAccess.canSetMaturity(newvalue.asInteger());
+}
-void LLAgent::buildFullname(std::string& name) const
+void LLAgent::handleMaturity(const LLSD& newvalue)
{
- if (mAvatarObject.notNull())
- {
- name = mAvatarObject->getFullname();
- }
+ sendMaturityPreferenceToServer(newvalue.asInteger());
}
+//----------------------------------------------------------------------------
+
+//*TODO remove, is not used anywhere as of August 20, 2009
void LLAgent::buildFullnameAndTitle(std::string& name) const
{
if (isGroupMember())
@@ -5135,52 +5161,9 @@ BOOL LLAgent::setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOO
return FALSE;
}
-// utility to build a location string
-void LLAgent::buildLocationString(std::string& str)
+BOOL LLAgent::canJoinGroups() const
{
- const LLVector3& agent_pos_region = getPositionAgent();
- S32 pos_x = S32(agent_pos_region.mV[VX]);
- S32 pos_y = S32(agent_pos_region.mV[VY]);
- S32 pos_z = S32(agent_pos_region.mV[VZ]);
-
- // Round the numbers based on the velocity
- LLVector3 agent_velocity = getVelocity();
- F32 velocity_mag_sq = agent_velocity.magVecSquared();
-
- const F32 FLY_CUTOFF = 6.f; // meters/sec
- const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF;
- const F32 WALK_CUTOFF = 1.5f; // meters/sec
- const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF;
-
- if (velocity_mag_sq > FLY_CUTOFF_SQ)
- {
- pos_x -= pos_x % 4;
- pos_y -= pos_y % 4;
- }
- else if (velocity_mag_sq > WALK_CUTOFF_SQ)
- {
- pos_x -= pos_x % 2;
- pos_y -= pos_y % 2;
- }
-
- // create a defult name and description for the landmark
- std::string buffer;
- if( LLViewerParcelMgr::getInstance()->getAgentParcelName().empty() )
- {
- // the parcel doesn't have a name
- buffer = llformat("%.32s (%d, %d, %d)",
- getRegion()->getName().c_str(),
- pos_x, pos_y, pos_z);
- }
- else
- {
- // the parcel has a name, so include it in the landmark name
- buffer = llformat("%.32s, %.32s (%d, %d, %d)",
- LLViewerParcelMgr::getInstance()->getAgentParcelName().c_str(),
- getRegion()->getName().c_str(),
- pos_x, pos_y, pos_z);
- }
- str = buffer;
+ return mGroups.count() < MAX_AGENT_GROUPS;
}
LLQuaternion LLAgent::getHeadRotation()
@@ -5344,30 +5327,6 @@ BOOL LLAgent::allowOperation(PermissionBit op,
return perm.allowOperationBy(op, agent_proxy, group_proxy);
}
-
-void LLAgent::getName(std::string& name)
-{
- name.clear();
-
- if (mAvatarObject.notNull())
- {
- LLNameValue *first_nv = mAvatarObject->getNVPair("FirstName");
- LLNameValue *last_nv = mAvatarObject->getNVPair("LastName");
- if (first_nv && last_nv)
- {
- name = first_nv->printData() + " " + last_nv->printData();
- }
- else
- {
- llwarns << "Agent is missing FirstName and/or LastName nv pair." << llendl;
- }
- }
- else
- {
- name = gSavedSettings.getString("FirstName") + " " + gSavedSettings.getString("LastName");
- }
-}
-
const LLColor4 &LLAgent::getEffectColor()
{
return mEffectColor;
@@ -5383,24 +5342,48 @@ void LLAgent::initOriginGlobal(const LLVector3d &origin_global)
mAgentOriginGlobal = origin_global;
}
-void update_group_floaters(const LLUUID& group_id)
-{
- LLFloaterGroupInfo::refreshGroup(group_id);
+BOOL LLAgent::leftButtonGrabbed() const
+{
+ return (!cameraMouselook() && mControlsTakenCount[CONTROL_LBUTTON_DOWN_INDEX] > 0)
+ || (cameraMouselook() && mControlsTakenCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0)
+ || (!cameraMouselook() && mControlsTakenPassedOnCount[CONTROL_LBUTTON_DOWN_INDEX] > 0)
+ || (cameraMouselook() && mControlsTakenPassedOnCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0);
+}
- // update avatar info
- LLFloaterAvatarInfo* fa = LLFloaterAvatarInfo::getInstance(gAgent.getID());
- if(fa)
- {
- fa->resetGroupList();
- }
+BOOL LLAgent::rotateGrabbed() const
+{
+ return (mControlsTakenCount[CONTROL_YAW_POS_INDEX] > 0)
+ || (mControlsTakenCount[CONTROL_YAW_NEG_INDEX] > 0);
+}
- if (gIMMgr)
- {
- // update the talk view
- gIMMgr->refresh();
- }
+BOOL LLAgent::forwardGrabbed() const
+{
+ return (mControlsTakenCount[CONTROL_AT_POS_INDEX] > 0);
+}
+
+BOOL LLAgent::backwardGrabbed() const
+{
+ return (mControlsTakenCount[CONTROL_AT_NEG_INDEX] > 0);
+}
- gAgent.fireEvent(new LLEvent(&gAgent, "new group"), "");
+BOOL LLAgent::upGrabbed() const
+{
+ return (mControlsTakenCount[CONTROL_UP_POS_INDEX] > 0);
+}
+
+BOOL LLAgent::downGrabbed() const
+{
+ return (mControlsTakenCount[CONTROL_UP_NEG_INDEX] > 0);
+}
+
+void update_group_floaters(const LLUUID& group_id)
+{
+
+ LLGroupActions::refresh(group_id);
+ //*TODO Implement group update for Profile View
+ // still actual as of July 31, 2009 (DZ)
+
+ gAgent.fireEvent(new LLOldEvents::LLEvent(&gAgent, "new group"), "");
}
// static
@@ -5438,9 +5421,7 @@ void LLAgent::processAgentDropGroup(LLMessageSystem *msg, void **)
LLGroupMgr::getInstance()->clearGroupData(group_id);
// close the floater for this group, if any.
- LLFloaterGroupInfo::closeGroup(group_id);
- // refresh the group panel of the search window, if necessary.
- LLFloaterDirectory::refreshGroup(group_id);
+ LLGroupActions::closeGroup(group_id);
}
else
{
@@ -5461,7 +5442,7 @@ class LLAgentDropGroupViewerNode : public LLHTTPNode
!input.has("body") )
{
//what to do with badly formed message?
- response->status(400);
+ response->statusUnknownError(400);
response->result(LLSD("Invalid message parameters"));
}
@@ -5517,10 +5498,7 @@ class LLAgentDropGroupViewerNode : public LLHTTPNode
LLGroupMgr::getInstance()->clearGroupData(group_id);
// close the floater for this group, if any.
- LLFloaterGroupInfo::closeGroup(group_id);
- // refresh the group panel of the search window,
- //if necessary.
- LLFloaterDirectory::refreshGroup(group_id);
+ LLGroupActions::closeGroup(group_id);
}
else
{
@@ -5534,7 +5512,7 @@ class LLAgentDropGroupViewerNode : public LLHTTPNode
else
{
//what to do with badly formed message?
- response->status(400);
+ response->statusUnknownError(400);
response->result(LLSD("Invalid message parameters"));
}
}
@@ -5721,10 +5699,10 @@ void LLAgent::processScriptControlChange(LLMessageSystem *msg, void **)
}
// Any control taken? If so, might be first time.
- if (total_count > 0)
- {
- LLFirstUse::useOverrideKeys();
- }
+ //if (total_count > 0)
+ //{
+ //LLFirstUse::useOverrideKeys();
+ //}
}
else
{
@@ -5828,9 +5806,9 @@ void LLAgent::processControlRelease(LLMessageSystem *msg, void **)
//static
void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void **user_data)
{
- gAgent.mNumPendingQueries--;
+ gAgentQueryManager.mNumPendingQueries--;
- LLVOAvatar* avatarp = gAgent.getAvatarObject();
+ LLVOAvatarSelf* avatarp = gAgent.getAvatarObject();
if (!avatarp || avatarp->isDead())
{
llwarns << "No avatar for user in cached texture update!" << llendl;
@@ -5860,12 +5838,12 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void *
if (texture_id.notNull()
&& (S32)texture_index < BAKED_NUM_INDICES
- && gAgent.mActiveCacheQueries[ texture_index ] == query_id)
+ && gAgentQueryManager.mActiveCacheQueries[texture_index] == query_id)
{
//llinfos << "Received cached texture " << (U32)texture_index << ": " << texture_id << llendl;
- avatarp->setCachedBakedTexture(getTextureIndex((EBakedTextureIndex)texture_index), texture_id);
+ avatarp->setCachedBakedTexture(LLVOAvatarDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)texture_index), texture_id);
//avatarp->setTETexture( LLVOAvatar::sBakedTextureIndices[texture_index], texture_id );
- gAgent.mActiveCacheQueries[ texture_index ] = 0;
+ gAgentQueryManager.mActiveCacheQueries[texture_index] = 0;
num_results++;
}
}
@@ -5874,7 +5852,7 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void *
avatarp->updateMeshTextures();
- if (gAgent.mNumPendingQueries == 0)
+ if (gAgentQueryManager.mNumPendingQueries == 0)
{
// RN: not sure why composites are disabled at this point
avatarp->setCompositeUpdatesEnabled(TRUE);
@@ -5884,8 +5862,7 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void *
BOOL LLAgent::anyControlGrabbed() const
{
- U32 i;
- for (i = 0; i < TOTAL_CONTROLS; i++)
+ for (U32 i = 0; i < TOTAL_CONTROLS; i++)
{
if (gAgent.mControlsTakenCount[i] > 0)
return TRUE;
@@ -5977,13 +5954,14 @@ bool LLAgent::teleportCore(bool is_local)
// process_teleport_location_reply
// close the map and find panels so we can see our destination
- LLFloaterWorldMap::hide(NULL);
- LLFloaterDirectory::hide(NULL);
+ LLFloaterReg::hideInstance("world_map");
+ LLFloaterReg::hideInstance("search");
// hide land floater too - it'll be out of date
- LLFloaterLand::hideInstance();
-
+ LLFloaterReg::hideInstance("about_land");
+
LLViewerParcelMgr::getInstance()->deselectLand();
+ LLViewerMediaFocus::getInstance()->clearFocus();
// Close all pie menus, deselect land, etc.
// Don't change the camera until we know teleport succeeded. JC
@@ -6099,17 +6077,16 @@ void LLAgent::teleportCancel()
void LLAgent::teleportViaLocation(const LLVector3d& pos_global)
{
LLViewerRegion* regionp = getRegion();
- LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global);
+ U64 handle = to_region_handle(pos_global);
+ LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle);
if(regionp && info)
{
- U32 x_pos;
- U32 y_pos;
- from_region_handle(info->mHandle, &x_pos, &y_pos);
+ LLVector3d region_origin = info->getGlobalOrigin();
LLVector3 pos_local(
- (F32)(pos_global.mdV[VX] - x_pos),
- (F32)(pos_global.mdV[VY] - y_pos),
+ (F32)(pos_global.mdV[VX] - region_origin.mdV[VX]),
+ (F32)(pos_global.mdV[VY] - region_origin.mdV[VY]),
(F32)(pos_global.mdV[VZ]));
- teleportRequest(info->mHandle, pos_local);
+ teleportRequest(handle, pos_local);
}
else if(regionp &&
teleportCore(regionp->getHandle() == to_region_handle_global((F32)pos_global.mdV[VX], (F32)pos_global.mdV[VY])))
@@ -6143,12 +6120,17 @@ void LLAgent::setTeleportState(ETeleportState state)
mTeleportState = state;
if (mTeleportState > TELEPORT_NONE && gSavedSettings.getBOOL("FreezeTime"))
{
- LLFloaterSnapshot::hide(0);
+ LLFloaterReg::hideInstance("snapshot");
}
if (mTeleportState == TELEPORT_MOVING)
{
// We're outa here. Save "back" slurl.
- mTeleportSourceSLURL = getSLURL();
+ mTeleportSourceSLURL = LLAgentUI::buildSLURL();
+ }
+ else if(mTeleportState == TELEPORT_ARRIVING)
+ {
+ // Let the interested parties know we've teleported.
+ LLViewerParcelMgr::getInstance()->onTeleportFinished(false, getPositionGlobal());
}
}
@@ -6277,878 +6259,6 @@ void LLAgent::requestLeaveGodMode()
sendReliableMessage();
}
-// wearables
-LLAgent::createStandardWearablesAllDoneCallback::~createStandardWearablesAllDoneCallback()
-{
- gAgent.createStandardWearablesAllDone();
-}
-
-LLAgent::sendAgentWearablesUpdateCallback::~sendAgentWearablesUpdateCallback()
-{
- gAgent.sendAgentWearablesUpdate();
-}
-
-LLAgent::addWearableToAgentInventoryCallback::addWearableToAgentInventoryCallback(
- LLPointer<LLRefCount> cb, S32 index, LLWearable* wearable, U32 todo) :
- mIndex(index),
- mWearable(wearable),
- mTodo(todo),
- mCB(cb)
-{
-}
-
-void LLAgent::addWearableToAgentInventoryCallback::fire(const LLUUID& inv_item)
-{
- if (inv_item.isNull())
- return;
-
- gAgent.addWearabletoAgentInventoryDone(mIndex, inv_item, mWearable);
-
- if (mTodo & CALL_UPDATE)
- {
- gAgent.sendAgentWearablesUpdate();
- }
- if (mTodo & CALL_RECOVERDONE)
- {
- gAgent.recoverMissingWearableDone();
- }
- /*
- * Do this for every one in the loop
- */
- if (mTodo & CALL_CREATESTANDARDDONE)
- {
- gAgent.createStandardWearablesDone(mIndex);
- }
- if (mTodo & CALL_MAKENEWOUTFITDONE)
- {
- gAgent.makeNewOutfitDone(mIndex);
- }
-}
-
-void LLAgent::addWearabletoAgentInventoryDone(
- S32 index,
- const LLUUID& item_id,
- LLWearable* wearable)
-{
- if (item_id.isNull())
- return;
-
- LLUUID old_item_id = mWearableEntry[index].mItemID;
- mWearableEntry[index].mItemID = item_id;
- mWearableEntry[index].mWearable = wearable;
- if (old_item_id.notNull())
- gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id);
- gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
- LLViewerInventoryItem* item = gInventory.getItem(item_id);
- if(item && wearable)
- {
- // We're changing the asset id, so we both need to set it
- // locally via setAssetUUID() and via setTransactionID() which
- // will be decoded on the server. JC
- item->setAssetUUID(wearable->getID());
- item->setTransactionID(wearable->getTransactionID());
- gInventory.addChangedMask(LLInventoryObserver::INTERNAL, item_id);
- item->updateServer(FALSE);
- }
- gInventory.notifyObservers();
-}
-
-void LLAgent::sendAgentWearablesUpdate()
-{
- // First make sure that we have inventory items for each wearable
- S32 i;
- for(i=0; i < WT_COUNT; ++i)
- {
- LLWearable* wearable = mWearableEntry[ i ].mWearable;
- if (wearable)
- {
- if( mWearableEntry[ i ].mItemID.isNull() )
- {
- LLPointer<LLInventoryCallback> cb =
- new addWearableToAgentInventoryCallback(
- LLPointer<LLRefCount>(NULL),
- i,
- wearable,
- addWearableToAgentInventoryCallback::CALL_NONE);
- addWearableToAgentInventory(cb, wearable);
- }
- else
- {
- gInventory.addChangedMask( LLInventoryObserver::LABEL,
- mWearableEntry[i].mItemID );
- }
- }
- }
-
- // Then make sure the inventory is in sync with the avatar.
- gInventory.notifyObservers();
-
- // Send the AgentIsNowWearing
- gMessageSystem->newMessageFast(_PREHASH_AgentIsNowWearing);
-
- gMessageSystem->nextBlockFast(_PREHASH_AgentData);
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, getID());
- gMessageSystem->addUUIDFast(_PREHASH_SessionID, getSessionID());
-
- lldebugs << "sendAgentWearablesUpdate()" << llendl;
- for(i=0; i < WT_COUNT; ++i)
- {
- gMessageSystem->nextBlockFast(_PREHASH_WearableData);
-
- U8 type_u8 = (U8)i;
- gMessageSystem->addU8Fast(_PREHASH_WearableType, type_u8 );
-
- LLWearable* wearable = mWearableEntry[ i ].mWearable;
- if( wearable )
- {
- //llinfos << "Sending wearable " << wearable->getName() << llendl;
- gMessageSystem->addUUIDFast(_PREHASH_ItemID, mWearableEntry[ i ].mItemID );
- }
- else
- {
- //llinfos << "Not wearing wearable type " << LLWearable::typeToTypeName((EWearableType)i) << llendl;
- gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID::null );
- }
-
- lldebugs << " " << LLWearable::typeToTypeLabel((EWearableType)i) << ": " << (wearable ? wearable->getID() : LLUUID::null) << llendl;
- }
- gAgent.sendReliableMessage();
-}
-
-void LLAgent::saveWearable( EWearableType type, BOOL send_update )
-{
- LLWearable* old_wearable = mWearableEntry[(S32)type].mWearable;
- if( old_wearable && (old_wearable->isDirty() || old_wearable->isOldVersion()) )
- {
- LLWearable* new_wearable = gWearableList.createCopyFromAvatar( old_wearable );
- mWearableEntry[(S32)type].mWearable = new_wearable;
-
- LLInventoryItem* item = gInventory.getItem(mWearableEntry[(S32)type].mItemID);
- if( item )
- {
- // Update existing inventory item
- LLPointer<LLViewerInventoryItem> template_item =
- new LLViewerInventoryItem(item->getUUID(),
- item->getParentUUID(),
- item->getPermissions(),
- new_wearable->getID(),
- new_wearable->getAssetType(),
- item->getInventoryType(),
- item->getName(),
- item->getDescription(),
- item->getSaleInfo(),
- item->getFlags(),
- item->getCreationDate());
- template_item->setTransactionID(new_wearable->getTransactionID());
- template_item->updateServer(FALSE);
- gInventory.updateItem(template_item);
- }
- else
- {
- // Add a new inventory item (shouldn't ever happen here)
- U32 todo = addWearableToAgentInventoryCallback::CALL_NONE;
- if (send_update)
- {
- todo |= addWearableToAgentInventoryCallback::CALL_UPDATE;
- }
- LLPointer<LLInventoryCallback> cb =
- new addWearableToAgentInventoryCallback(
- LLPointer<LLRefCount>(NULL),
- (S32)type,
- new_wearable,
- todo);
- addWearableToAgentInventory(cb, new_wearable);
- return;
- }
-
- getAvatarObject()->wearableUpdated( type );
-
- if( send_update )
- {
- sendAgentWearablesUpdate();
- }
- }
-}
-
-void LLAgent::saveWearableAs(
- EWearableType type,
- const std::string& new_name,
- BOOL save_in_lost_and_found)
-{
- if(!isWearableCopyable(type))
- {
- llwarns << "LLAgent::saveWearableAs() not copyable." << llendl;
- return;
- }
- LLWearable* old_wearable = getWearable(type);
- if(!old_wearable)
- {
- llwarns << "LLAgent::saveWearableAs() no old wearable." << llendl;
- return;
- }
- LLInventoryItem* item = gInventory.getItem(mWearableEntry[type].mItemID);
- if(!item)
- {
- llwarns << "LLAgent::saveWearableAs() no inventory item." << llendl;
- return;
- }
- std::string trunc_name(new_name);
- LLStringUtil::truncate(trunc_name, DB_INV_ITEM_NAME_STR_LEN);
- LLWearable* new_wearable = gWearableList.createCopyFromAvatar(
- old_wearable,
- trunc_name);
- LLPointer<LLInventoryCallback> cb =
- new addWearableToAgentInventoryCallback(
- LLPointer<LLRefCount>(NULL),
- type,
- new_wearable,
- addWearableToAgentInventoryCallback::CALL_UPDATE);
- LLUUID category_id;
- if (save_in_lost_and_found)
- {
- category_id = gInventory.findCategoryUUIDForType(
- LLAssetType::AT_LOST_AND_FOUND);
- }
- else
- {
- // put in same folder as original
- category_id = item->getParentUUID();
- }
-
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- category_id,
- new_name,
- cb);
-
-/*
- LLWearable* old_wearable = getWearable( type );
- if( old_wearable )
- {
- std::string old_name = old_wearable->getName();
- old_wearable->setName( new_name );
- LLWearable* new_wearable = gWearableList.createCopyFromAvatar( old_wearable );
- old_wearable->setName( old_name );
-
- LLUUID category_id;
- LLInventoryItem* item = gInventory.getItem( mWearableEntry[ type ].mItemID );
- if( item )
- {
- new_wearable->setPermissions(item->getPermissions());
- if (save_in_lost_and_found)
- {
- category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
- }
- else
- {
- // put in same folder as original
- category_id = item->getParentUUID();
- }
- LLInventoryView* view = LLInventoryView::getActiveInventory();
- if(view)
- {
- view->getPanel()->setSelection(item->getUUID(), TAKE_FOCUS_NO);
- }
- }
-
- mWearableEntry[ type ].mWearable = new_wearable;
- LLPointer<LLInventoryCallback> cb =
- new addWearableToAgentInventoryCallback(
- LLPointer<LLRefCount>(NULL),
- type,
- addWearableToAgentInventoryCallback::CALL_UPDATE);
- addWearableToAgentInventory(cb, new_wearable, category_id);
- }
-*/
-}
-
-void LLAgent::revertWearable( EWearableType type )
-{
- LLWearable* wearable = mWearableEntry[(S32)type].mWearable;
- if( wearable )
- {
- wearable->writeToAvatar( TRUE );
- }
- sendAgentSetAppearance();
-}
-
-void LLAgent::revertAllWearables()
-{
- for( S32 i=0; i < WT_COUNT; i++ )
- {
- revertWearable( (EWearableType)i );
- }
-}
-
-void LLAgent::saveAllWearables()
-{
- //if(!gInventory.isLoaded())
- //{
- // return;
- //}
-
- for( S32 i=0; i < WT_COUNT; i++ )
- {
- saveWearable( (EWearableType)i, FALSE );
- }
- sendAgentWearablesUpdate();
-}
-
-// Called when the user changes the name of a wearable inventory item that is currenlty being worn.
-void LLAgent::setWearableName( const LLUUID& item_id, const std::string& new_name )
-{
- for( S32 i=0; i < WT_COUNT; i++ )
- {
- if( mWearableEntry[i].mItemID == item_id )
- {
- LLWearable* old_wearable = mWearableEntry[i].mWearable;
- llassert( old_wearable );
-
- std::string old_name = old_wearable->getName();
- old_wearable->setName( new_name );
- LLWearable* new_wearable = gWearableList.createCopy( old_wearable );
- LLInventoryItem* item = gInventory.getItem(item_id);
- if(item)
- {
- new_wearable->setPermissions(item->getPermissions());
- }
- old_wearable->setName( old_name );
-
- mWearableEntry[i].mWearable = new_wearable;
- sendAgentWearablesUpdate();
- break;
- }
- }
-}
-
-
-BOOL LLAgent::isWearableModifiable(EWearableType type)
-{
- LLUUID item_id = getWearableItem(type);
- if(!item_id.isNull())
- {
- LLInventoryItem* item = gInventory.getItem(item_id);
- if(item && item->getPermissions().allowModifyBy(gAgent.getID(),
- gAgent.getGroupID()))
- {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-BOOL LLAgent::isWearableCopyable(EWearableType type)
-{
- LLUUID item_id = getWearableItem(type);
- if(!item_id.isNull())
- {
- LLInventoryItem* item = gInventory.getItem(item_id);
- if(item && item->getPermissions().allowCopyBy(gAgent.getID(),
- gAgent.getGroupID()))
- {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-U32 LLAgent::getWearablePermMask(EWearableType type)
-{
- LLUUID item_id = getWearableItem(type);
- if(!item_id.isNull())
- {
- LLInventoryItem* item = gInventory.getItem(item_id);
- if(item)
- {
- return item->getPermissions().getMaskOwner();
- }
- }
- return PERM_NONE;
-}
-
-LLInventoryItem* LLAgent::getWearableInventoryItem(EWearableType type)
-{
- LLUUID item_id = getWearableItem(type);
- LLInventoryItem* item = NULL;
- if(item_id.notNull())
- {
- item = gInventory.getItem(item_id);
- }
- return item;
-}
-
-LLWearable* LLAgent::getWearableFromWearableItem( const LLUUID& item_id )
-{
- for( S32 i=0; i < WT_COUNT; i++ )
- {
- if( mWearableEntry[i].mItemID == item_id )
- {
- return mWearableEntry[i].mWearable;
- }
- }
- return NULL;
-}
-
-
-void LLAgent::sendAgentWearablesRequest()
-{
- gMessageSystem->newMessageFast(_PREHASH_AgentWearablesRequest);
- gMessageSystem->nextBlockFast(_PREHASH_AgentData);
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
- gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
- sendReliableMessage();
-}
-
-// Used to enable/disable menu items.
-// static
-BOOL LLAgent::selfHasWearable( void* userdata )
-{
- EWearableType type = (EWearableType)(intptr_t)userdata;
- return gAgent.getWearable( type ) != NULL;
-}
-
-BOOL LLAgent::isWearingItem( const LLUUID& item_id )
-{
- return (getWearableFromWearableItem( item_id ) != NULL);
-}
-
-// static
-void LLAgent::processAgentInitialWearablesUpdate( LLMessageSystem* mesgsys, void** user_data )
-{
- // We should only receive this message a single time. Ignore subsequent AgentWearablesUpdates
- // that may result from AgentWearablesRequest having been sent more than once.
- static bool first = true;
- if (!first) return;
- first = false;
-
- LLUUID agent_id;
- gMessageSystem->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
-
- LLVOAvatar* avatar = gAgent.getAvatarObject();
- if( avatar && (agent_id == avatar->getID()) )
- {
- gMessageSystem->getU32Fast(_PREHASH_AgentData, _PREHASH_SerialNum, gAgent.mAgentWearablesUpdateSerialNum );
-
- S32 num_wearables = gMessageSystem->getNumberOfBlocksFast(_PREHASH_WearableData);
- if( num_wearables < 4 )
- {
- // Transitional state. Avatars should always have at least their body parts (hair, eyes, shape and skin).
- // The fact that they don't have any here (only a dummy is sent) implies that this account existed
- // before we had wearables, or that the database has gotten messed up.
- return;
- }
-
- //lldebugs << "processAgentInitialWearablesUpdate()" << llendl;
- // Add wearables
- LLUUID asset_id_array[ WT_COUNT ];
- S32 i;
- for( i=0; i < num_wearables; i++ )
- {
- U8 type_u8 = 0;
- gMessageSystem->getU8Fast(_PREHASH_WearableData, _PREHASH_WearableType, type_u8, i );
- if( type_u8 >= WT_COUNT )
- {
- continue;
- }
- EWearableType type = (EWearableType) type_u8;
-
- LLUUID item_id;
- gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_ItemID, item_id, i );
-
- LLUUID asset_id;
- gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_AssetID, asset_id, i );
- if( asset_id.isNull() )
- {
- LLWearable::removeFromAvatar( type, FALSE );
- }
- else
- {
- LLAssetType::EType asset_type = LLWearable::typeToAssetType( type );
- if( asset_type == LLAssetType::AT_NONE )
- {
- continue;
- }
-
- gAgent.mWearableEntry[type].mItemID = item_id;
- asset_id_array[type] = asset_id;
- }
-
- lldebugs << " " << LLWearable::typeToTypeLabel(type) << llendl;
- }
-
- // now that we have the asset ids...request the wearable assets
- for( i = 0; i < WT_COUNT; i++ )
- {
- if( !gAgent.mWearableEntry[i].mItemID.isNull() )
- {
- gWearableList.getAsset(
- asset_id_array[i],
- LLStringUtil::null,
- LLWearable::typeToAssetType( (EWearableType) i ),
- LLAgent::onInitialWearableAssetArrived, (void*)(intptr_t)i );
- }
- }
- }
-}
-
-// A single wearable that the avatar was wearing on start-up has arrived from the database.
-// static
-void LLAgent::onInitialWearableAssetArrived( LLWearable* wearable, void* userdata )
-{
- EWearableType type = (EWearableType)(intptr_t)userdata;
-
- LLVOAvatar* avatar = gAgent.getAvatarObject();
- if( !avatar )
- {
- return;
- }
-
- if( wearable )
- {
- llassert( type == wearable->getType() );
- gAgent.mWearableEntry[ type ].mWearable = wearable;
-
- // disable composites if initial textures are baked
- avatar->setupComposites();
- gAgent.queryWearableCache();
-
- wearable->writeToAvatar( FALSE );
- avatar->setCompositeUpdatesEnabled(TRUE);
- gInventory.addChangedMask( LLInventoryObserver::LABEL, gAgent.mWearableEntry[type].mItemID );
- }
- else
- {
- // Somehow the asset doesn't exist in the database.
- gAgent.recoverMissingWearable( type );
- }
-
- gInventory.notifyObservers();
-
- // Have all the wearables that the avatar was wearing at log-in arrived?
- if( !gAgent.mWearablesLoaded )
- {
- gAgent.mWearablesLoaded = TRUE;
- for( S32 i = 0; i < WT_COUNT; i++ )
- {
- if( !gAgent.mWearableEntry[i].mItemID.isNull() && !gAgent.mWearableEntry[i].mWearable )
- {
- gAgent.mWearablesLoaded = FALSE;
- break;
- }
- }
- }
-
- if( gAgent.mWearablesLoaded )
- {
- // Make sure that the server's idea of the avatar's wearables actually match the wearables.
- gAgent.sendAgentSetAppearance();
-
- // Check to see if there are any baked textures that we hadn't uploaded before we logged off last time.
- // If there are any, schedule them to be uploaded as soon as the layer textures they depend on arrive.
- if( !gAgent.cameraCustomizeAvatar() )
- {
- avatar->requestLayerSetUploads();
- }
- }
-}
-
-// Normally, all wearables referred to "AgentWearablesUpdate" will correspond to actual assets in the
-// database. If for some reason, we can't load one of those assets, we can try to reconstruct it so that
-// the user isn't left without a shape, for example. (We can do that only after the inventory has loaded.)
-void LLAgent::recoverMissingWearable( EWearableType type )
-{
- // Try to recover by replacing missing wearable with a new one.
- LLNotifications::instance().add("ReplacedMissingWearable");
- lldebugs << "Wearable " << LLWearable::typeToTypeLabel( type ) << " could not be downloaded. Replaced inventory item with default wearable." << llendl;
- LLWearable* new_wearable = gWearableList.createNewWearable(type);
-
- S32 type_s32 = (S32) type;
- mWearableEntry[type_s32].mWearable = new_wearable;
- new_wearable->writeToAvatar( TRUE );
-
- // Add a new one in the lost and found folder.
- // (We used to overwrite the "not found" one, but that could potentially
- // destory content.) JC
- LLUUID lost_and_found_id =
- gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
- LLPointer<LLInventoryCallback> cb =
- new addWearableToAgentInventoryCallback(
- LLPointer<LLRefCount>(NULL),
- type_s32,
- new_wearable,
- addWearableToAgentInventoryCallback::CALL_RECOVERDONE);
- addWearableToAgentInventory( cb, new_wearable, lost_and_found_id, TRUE);
-}
-
-void LLAgent::recoverMissingWearableDone()
-{
- // Have all the wearables that the avatar was wearing at log-in arrived or been fabricated?
- mWearablesLoaded = TRUE;
- for( S32 i = 0; i < WT_COUNT; i++ )
- {
- if( !mWearableEntry[i].mItemID.isNull() && !mWearableEntry[i].mWearable )
- {
- mWearablesLoaded = FALSE;
- break;
- }
- }
-
- if( mWearablesLoaded )
- {
- // Make sure that the server's idea of the avatar's wearables actually match the wearables.
- sendAgentSetAppearance();
- }
- else
- {
- gInventory.addChangedMask( LLInventoryObserver::LABEL, LLUUID::null );
- gInventory.notifyObservers();
- }
-}
-
-void LLAgent::createStandardWearables(BOOL female)
-{
- llwarns << "Creating Standard " << (female ? "female" : "male" )
- << " Wearables" << llendl;
-
- if (mAvatarObject.isNull())
- {
- return;
- }
-
- if(female) mAvatarObject->setSex(SEX_FEMALE);
- else mAvatarObject->setSex(SEX_MALE);
-
- BOOL create[WT_COUNT] =
- {
- TRUE, //WT_SHAPE
- TRUE, //WT_SKIN
- TRUE, //WT_HAIR
- TRUE, //WT_EYES
- TRUE, //WT_SHIRT
- TRUE, //WT_PANTS
- TRUE, //WT_SHOES
- TRUE, //WT_SOCKS
- FALSE, //WT_JACKET
- FALSE, //WT_GLOVES
- TRUE, //WT_UNDERSHIRT
- TRUE, //WT_UNDERPANTS
- FALSE //WT_SKIRT
- };
-
- for( S32 i=0; i < WT_COUNT; i++ )
- {
- bool once = false;
- LLPointer<LLRefCount> donecb = NULL;
- if( create[i] )
- {
- if (!once)
- {
- once = true;
- donecb = new createStandardWearablesAllDoneCallback;
- }
- llassert( mWearableEntry[i].mWearable == NULL );
- LLWearable* wearable = gWearableList.createNewWearable((EWearableType)i);
- mWearableEntry[i].mWearable = wearable;
- // no need to update here...
- LLPointer<LLInventoryCallback> cb =
- new addWearableToAgentInventoryCallback(
- donecb,
- i,
- wearable,
- addWearableToAgentInventoryCallback::CALL_CREATESTANDARDDONE);
- addWearableToAgentInventory(cb, wearable, LLUUID::null, FALSE);
- }
- }
-}
-void LLAgent::createStandardWearablesDone(S32 index)
-{
- LLWearable* wearable = mWearableEntry[index].mWearable;
-
- if (wearable)
- {
- wearable->writeToAvatar(TRUE);
- }
-}
-
-void LLAgent::createStandardWearablesAllDone()
-{
- // ... because sendAgentWearablesUpdate will notify inventory
- // observers.
- mWearablesLoaded = TRUE;
- sendAgentWearablesUpdate();
- sendAgentSetAppearance();
-
- // Treat this as the first texture entry message, if none received yet
- mAvatarObject->onFirstTEMessageReceived();
-}
-
-void LLAgent::makeNewOutfit(
- const std::string& new_folder_name,
- const LLDynamicArray<S32>& wearables_to_include,
- const LLDynamicArray<S32>& attachments_to_include,
- BOOL rename_clothing)
-{
- if (mAvatarObject.isNull())
- {
- return;
- }
-
- // First, make a folder in the Clothes directory.
- LLUUID folder_id = gInventory.createNewCategory(
- gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING),
- LLAssetType::AT_NONE,
- new_folder_name);
-
- bool found_first_item = false;
-
- ///////////////////
- // Wearables
-
- if( wearables_to_include.count() )
- {
- // Then, iterate though each of the wearables and save copies of them in the folder.
- S32 i;
- S32 count = wearables_to_include.count();
- LLDynamicArray<LLUUID> delete_items;
- LLPointer<LLRefCount> cbdone = NULL;
- for( i = 0; i < count; ++i )
- {
- S32 index = wearables_to_include[i];
- LLWearable* old_wearable = mWearableEntry[ index ].mWearable;
- if( old_wearable )
- {
- std::string new_name;
- LLWearable* new_wearable;
- new_wearable = gWearableList.createCopy(old_wearable);
- if (rename_clothing)
- {
- new_name = new_folder_name;
- new_name.append(" ");
- new_name.append(old_wearable->getTypeLabel());
- LLStringUtil::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN);
- new_wearable->setName(new_name);
- }
-
- LLViewerInventoryItem* item = gInventory.getItem(mWearableEntry[index].mItemID);
- S32 todo = addWearableToAgentInventoryCallback::CALL_NONE;
- if (!found_first_item)
- {
- found_first_item = true;
- /* set the focus to the first item */
- todo |= addWearableToAgentInventoryCallback::CALL_MAKENEWOUTFITDONE;
- /* send the agent wearables update when done */
- cbdone = new sendAgentWearablesUpdateCallback;
- }
- LLPointer<LLInventoryCallback> cb =
- new addWearableToAgentInventoryCallback(
- cbdone,
- index,
- new_wearable,
- todo);
- if (isWearableCopyable((EWearableType)index))
- {
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- folder_id,
- new_name,
- cb);
- }
- else
- {
- move_inventory_item(
- gAgent.getID(),
- gAgent.getSessionID(),
- item->getUUID(),
- folder_id,
- new_name,
- cb);
- }
- }
- }
- gInventory.notifyObservers();
- }
-
-
- ///////////////////
- // Attachments
-
- if( attachments_to_include.count() )
- {
- BOOL msg_started = FALSE;
- LLMessageSystem* msg = gMessageSystem;
- for( S32 i = 0; i < attachments_to_include.count(); i++ )
- {
- S32 attachment_pt = attachments_to_include[i];
- LLViewerJointAttachment* attachment = get_if_there(mAvatarObject->mAttachmentPoints, attachment_pt, (LLViewerJointAttachment*)NULL );
- if(!attachment) continue;
- LLViewerObject* attached_object = attachment->getObject();
- if(!attached_object) continue;
- const LLUUID& item_id = attachment->getItemID();
- if(item_id.isNull()) continue;
- LLInventoryItem* item = gInventory.getItem(item_id);
- if(!item) continue;
- if(!msg_started)
- {
- msg_started = TRUE;
- msg->newMessage("CreateNewOutfitAttachments");
- msg->nextBlock("AgentData");
- msg->addUUID("AgentID", getID());
- msg->addUUID("SessionID", getSessionID());
- msg->nextBlock("HeaderData");
- msg->addUUID("NewFolderID", folder_id);
- }
- msg->nextBlock("ObjectData");
- msg->addUUID("OldItemID", item_id);
- msg->addUUID("OldFolderID", item->getParentUUID());
- }
-
- if( msg_started )
- {
- sendReliableMessage();
- }
-
- }
-}
-
-void LLAgent::makeNewOutfitDone(S32 index)
-{
- LLUUID first_item_id = mWearableEntry[index].mItemID;
- // Open the inventory and select the first item we added.
- if( first_item_id.notNull() )
- {
- LLInventoryView* view = LLInventoryView::getActiveInventory();
- if(view)
- {
- view->getPanel()->setSelection(first_item_id, TAKE_FOCUS_NO);
- }
- }
-}
-
-
-void LLAgent::addWearableToAgentInventory(
- LLPointer<LLInventoryCallback> cb,
- LLWearable* wearable,
- const LLUUID& category_id,
- BOOL notify)
-{
- create_inventory_item(
- gAgent.getID(),
- gAgent.getSessionID(),
- category_id,
- wearable->getTransactionID(),
- wearable->getName(),
- wearable->getDescription(),
- wearable->getAssetType(),
- LLInventoryType::IT_WEARABLE,
- wearable->getType(),
- wearable->getPermissions().getMaskNextOwner(),
- cb);
-}
-
//-----------------------------------------------------------------------------
// sendAgentSetAppearance()
//-----------------------------------------------------------------------------
@@ -7156,7 +6266,7 @@ void LLAgent::sendAgentSetAppearance()
{
if (mAvatarObject.isNull()) return;
- if (mNumPendingQueries > 0 && !gAgent.cameraCustomizeAvatar())
+ if (gAgentQueryManager.mNumPendingQueries > 0 && !gAgent.cameraCustomizeAvatar())
{
return;
}
@@ -7186,11 +6296,11 @@ void LLAgent::sendAgentSetAppearance()
// is texture data current relative to wearables?
// KLW - TAT this will probably need to check the local queue.
- BOOL textures_current = !mAvatarObject->hasPendingBakedUploads() && mWearablesLoaded;
+ BOOL textures_current = mAvatarObject->areTexturesCurrent();
for(U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++ )
{
- const ETextureIndex texture_index = getTextureIndex((EBakedTextureIndex)baked_index);
+ const ETextureIndex texture_index = LLVOAvatarDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)baked_index);
// if we're not wearing a skirt, we don't need the texture to be baked
if (texture_index == TEX_SKIRT_BAKED && !mAvatarObject->isWearingWearableType(WT_SKIRT))
@@ -7198,8 +6308,8 @@ void LLAgent::sendAgentSetAppearance()
continue;
}
- // IMG_DEFAULT_AVATAR means not baked
- if (!mAvatarObject->isTextureDefined(texture_index))
+ // IMG_DEFAULT_AVATAR means not baked. 0 index should be ignored for baked textures
+ if (!mAvatarObject->isTextureDefined(texture_index, 0))
{
textures_current = FALSE;
break;
@@ -7212,31 +6322,32 @@ void LLAgent::sendAgentSetAppearance()
llinfos << "TAT: Sending cached texture data" << llendl;
for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
{
- const LLVOAvatarDictionary::WearableDictionaryEntry *wearable_dict = LLVOAvatarDictionary::getInstance()->getWearable((EBakedTextureIndex)baked_index);
+ const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index);
LLUUID hash;
- for (U8 i=0; i < wearable_dict->mWearablesVec.size(); i++)
+ for (U8 i=0; i < baked_dict->mWearables.size(); i++)
{
// EWearableType wearable_type = gBakedWearableMap[baked_index][wearable_num];
- const EWearableType wearable_type = wearable_dict->mWearablesVec[i];
- const LLWearable* wearable = getWearable(wearable_type);
+ const EWearableType wearable_type = baked_dict->mWearables[i];
+ // MULTI-WEARABLE: fixed to 0th - extend to everything once messaging works.
+ const LLWearable* wearable = gAgentWearables.getWearable(wearable_type,0);
if (wearable)
{
- hash ^= wearable->getID();
+ hash ^= wearable->getAssetID();
}
}
if (hash.notNull())
{
- hash ^= wearable_dict->mHashID;
+ hash ^= baked_dict->mWearablesHashID;
}
- const ETextureIndex texture_index = getTextureIndex((EBakedTextureIndex)baked_index);
+ const ETextureIndex texture_index = LLVOAvatarDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)baked_index);
msg->nextBlockFast(_PREHASH_WearableData);
msg->addUUIDFast(_PREHASH_CacheID, hash);
msg->addU8Fast(_PREHASH_TextureIndex, (U8)texture_index);
}
msg->nextBlockFast(_PREHASH_ObjectData);
- mAvatarObject->packTEMessage( gMessageSystem );
+ mAvatarObject->sendAppearanceMessage( gMessageSystem );
}
else
{
@@ -7273,456 +6384,20 @@ void LLAgent::sendAgentDataUpdateRequest()
{
gMessageSystem->newMessageFast(_PREHASH_AgentDataUpdateRequest);
gMessageSystem->nextBlockFast(_PREHASH_AgentData);
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
sendReliableMessage();
}
-void LLAgent::removeWearable( EWearableType type )
-{
- LLWearable* old_wearable = mWearableEntry[ type ].mWearable;
-
- if ( (gAgent.isTeen())
- && (type == WT_UNDERSHIRT || type == WT_UNDERPANTS))
- {
- // Can't take off underclothing in simple UI mode or on PG accounts
- return;
- }
-
- if( old_wearable )
- {
- if( old_wearable->isDirty() )
- {
- LLSD payload;
- payload["wearable_type"] = (S32)type;
- // Bring up view-modal dialog: Save changes? Yes, No, Cancel
- LLNotifications::instance().add("WearableSave", LLSD(), payload, &LLAgent::onRemoveWearableDialog);
- return;
- }
- else
- {
- removeWearableFinal( type );
- }
- }
-}
-
-// static
-bool LLAgent::onRemoveWearableDialog(const LLSD& notification, const LLSD& response )
-{
- S32 option = LLNotification::getSelectedOption(notification, response);
- EWearableType type = (EWearableType)notification["payload"]["wearable_type"].asInteger();
- switch( option )
- {
- case 0: // "Save"
- gAgent.saveWearable( type );
- gAgent.removeWearableFinal( type );
- break;
-
- case 1: // "Don't Save"
- gAgent.removeWearableFinal( type );
- break;
-
- case 2: // "Cancel"
- break;
-
- default:
- llassert(0);
- break;
- }
- return false;
-}
-
-// Called by removeWearable() and onRemoveWearableDialog() to actually do the removal.
-void LLAgent::removeWearableFinal( EWearableType type )
-{
- LLWearable* old_wearable = mWearableEntry[ type ].mWearable;
-
- gInventory.addChangedMask( LLInventoryObserver::LABEL, mWearableEntry[type].mItemID );
-
- mWearableEntry[ type ].mWearable = NULL;
- mWearableEntry[ type ].mItemID.setNull();
-
- queryWearableCache();
-
- if( old_wearable )
- {
- old_wearable->removeFromAvatar( TRUE );
- }
-
- // Update the server
- sendAgentWearablesUpdate();
- sendAgentSetAppearance();
- gInventory.notifyObservers();
-}
-
-void LLAgent::copyWearableToInventory( EWearableType type )
+void LLAgent::sendAgentUserInfoRequest()
{
- LLWearable* wearable = mWearableEntry[ type ].mWearable;
- if( wearable )
- {
- // Save the old wearable if it has changed.
- if( wearable->isDirty() )
- {
- wearable = gWearableList.createCopyFromAvatar( wearable );
- mWearableEntry[ type ].mWearable = wearable;
- }
-
- // Make a new entry in the inventory. (Put it in the same folder as the original item if possible.)
- LLUUID category_id;
- LLInventoryItem* item = gInventory.getItem( mWearableEntry[ type ].mItemID );
- if( item )
- {
- category_id = item->getParentUUID();
- wearable->setPermissions(item->getPermissions());
- }
- LLPointer<LLInventoryCallback> cb =
- new addWearableToAgentInventoryCallback(
- LLPointer<LLRefCount>(NULL),
- type,
- wearable);
- addWearableToAgentInventory(cb, wearable, category_id);
- }
-}
-
-
-// A little struct to let setWearable() communicate more than one value with onSetWearableDialog().
-struct LLSetWearableData
-{
- LLSetWearableData( const LLUUID& new_item_id, LLWearable* new_wearable ) :
- mNewItemID( new_item_id ), mNewWearable( new_wearable ) {}
- LLUUID mNewItemID;
- LLWearable* mNewWearable;
-};
-
-BOOL LLAgent::needsReplacement(EWearableType wearableType, S32 remove)
-{
- return TRUE;
- /*if (remove) return TRUE;
-
- return getWearable(wearableType) ? TRUE : FALSE;*/
-}
-
-// Assumes existing wearables are not dirty.
-void LLAgent::setWearableOutfit(
- const LLInventoryItem::item_array_t& items,
- const LLDynamicArray< LLWearable* >& wearables,
- BOOL remove )
-{
- lldebugs << "setWearableOutfit() start" << llendl;
-
- BOOL wearables_to_remove[WT_COUNT];
- wearables_to_remove[WT_SHAPE] = FALSE;
- wearables_to_remove[WT_SKIN] = FALSE;
- wearables_to_remove[WT_HAIR] = FALSE;
- wearables_to_remove[WT_EYES] = FALSE;
- wearables_to_remove[WT_SHIRT] = remove;
- wearables_to_remove[WT_PANTS] = remove;
- wearables_to_remove[WT_SHOES] = remove;
- wearables_to_remove[WT_SOCKS] = remove;
- wearables_to_remove[WT_JACKET] = remove;
- wearables_to_remove[WT_GLOVES] = remove;
- wearables_to_remove[WT_UNDERSHIRT] = (!gAgent.isTeen()) & remove;
- wearables_to_remove[WT_UNDERPANTS] = (!gAgent.isTeen()) & remove;
- wearables_to_remove[WT_SKIRT] = remove;
-
- S32 count = wearables.count();
- llassert( items.count() == count );
-
- S32 i;
- for( i = 0; i < count; i++ )
- {
- LLWearable* new_wearable = wearables[i];
- LLPointer<LLInventoryItem> new_item = items[i];
-
- EWearableType type = new_wearable->getType();
- wearables_to_remove[type] = FALSE;
-
- LLWearable* old_wearable = mWearableEntry[ type ].mWearable;
- if( old_wearable )
- {
- const LLUUID& old_item_id = mWearableEntry[ type ].mItemID;
- if( (old_wearable->getID() == new_wearable->getID()) &&
- (old_item_id == new_item->getUUID()) )
- {
- lldebugs << "No change to wearable asset and item: " << LLWearable::typeToTypeName( type ) << llendl;
- continue;
- }
-
- gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id);
-
- // Assumes existing wearables are not dirty.
- if( old_wearable->isDirty() )
- {
- llassert(0);
- continue;
- }
- }
-
- mWearableEntry[ type ].mItemID = new_item->getUUID();
- mWearableEntry[ type ].mWearable = new_wearable;
- }
-
- std::vector<LLWearable*> wearables_being_removed;
-
- for( i = 0; i < WT_COUNT; i++ )
- {
- if( wearables_to_remove[i] )
- {
- wearables_being_removed.push_back(mWearableEntry[ i ].mWearable);
- mWearableEntry[ i ].mWearable = NULL;
-
- gInventory.addChangedMask(LLInventoryObserver::LABEL, mWearableEntry[ i ].mItemID);
- mWearableEntry[ i ].mItemID.setNull();
- }
- }
-
- gInventory.notifyObservers();
-
- queryWearableCache();
-
- std::vector<LLWearable*>::iterator wearable_iter;
-
- for( wearable_iter = wearables_being_removed.begin();
- wearable_iter != wearables_being_removed.end();
- ++wearable_iter)
- {
- LLWearable* wearablep = *wearable_iter;
- if (wearablep)
- {
- wearablep->removeFromAvatar( TRUE );
- }
- }
-
- for( i = 0; i < count; i++ )
- {
- wearables[i]->writeToAvatar( TRUE );
- }
-
- // Start rendering & update the server
- mWearablesLoaded = TRUE;
- sendAgentWearablesUpdate();
- sendAgentSetAppearance();
-
- lldebugs << "setWearableOutfit() end" << llendl;
-}
-
-
-// User has picked "wear on avatar" from a menu.
-void LLAgent::setWearable( LLInventoryItem* new_item, LLWearable* new_wearable )
-{
- EWearableType type = new_wearable->getType();
-
- LLWearable* old_wearable = mWearableEntry[ type ].mWearable;
- if( old_wearable )
- {
- const LLUUID& old_item_id = mWearableEntry[ type ].mItemID;
- if( (old_wearable->getID() == new_wearable->getID()) &&
- (old_item_id == new_item->getUUID()) )
- {
- lldebugs << "No change to wearable asset and item: " << LLWearable::typeToTypeName( type ) << llendl;
- return;
- }
-
- if( old_wearable->isDirty() )
- {
- // Bring up modal dialog: Save changes? Yes, No, Cancel
- LLSD payload;
- payload["item_id"] = new_item->getUUID();
- LLNotifications::instance().add( "WearableSave", LLSD(), payload, boost::bind(LLAgent::onSetWearableDialog, _1, _2, new_wearable));
- return;
- }
- }
-
- setWearableFinal( new_item, new_wearable );
-}
-
-// static
-bool LLAgent::onSetWearableDialog( const LLSD& notification, const LLSD& response, LLWearable* wearable )
-{
- S32 option = LLNotification::getSelectedOption(notification, response);
- LLInventoryItem* new_item = gInventory.getItem( notification["payload"]["item_id"].asUUID());
- if( !new_item )
- {
- delete wearable;
- return false;
- }
-
- switch( option )
- {
- case 0: // "Save"
- gAgent.saveWearable( wearable->getType() );
- gAgent.setWearableFinal( new_item, wearable );
- break;
-
- case 1: // "Don't Save"
- gAgent.setWearableFinal( new_item, wearable );
- break;
-
- case 2: // "Cancel"
- break;
-
- default:
- llassert(0);
- break;
- }
-
- delete wearable;
- return false;
-}
-
-// Called from setWearable() and onSetWearableDialog() to actually set the wearable.
-void LLAgent::setWearableFinal( LLInventoryItem* new_item, LLWearable* new_wearable )
-{
- EWearableType type = new_wearable->getType();
-
- // Replace the old wearable with a new one.
- llassert( new_item->getAssetUUID() == new_wearable->getID() );
- LLUUID old_item_id = mWearableEntry[ type ].mItemID;
- mWearableEntry[ type ].mItemID = new_item->getUUID();
- mWearableEntry[ type ].mWearable = new_wearable;
-
- if (old_item_id.notNull())
- {
- gInventory.addChangedMask( LLInventoryObserver::LABEL, old_item_id );
- gInventory.notifyObservers();
- }
-
- //llinfos << "LLVOAvatar::setWearable()" << llendl;
- queryWearableCache();
- new_wearable->writeToAvatar( TRUE );
-
- // Update the server
- sendAgentWearablesUpdate();
- sendAgentSetAppearance();
-}
-
-void LLAgent::queryWearableCache()
-{
- if (!mWearablesLoaded)
- {
- return;
- }
-
- // Look up affected baked textures.
- // If they exist:
- // disallow updates for affected layersets (until dataserver responds with cache request.)
- // If cache miss, turn updates back on and invalidate composite.
- // If cache hit, modify baked texture entries.
- //
- // Cache requests contain list of hashes for each baked texture entry.
- // Response is list of valid baked texture assets. (same message)
-
- gMessageSystem->newMessageFast(_PREHASH_AgentCachedTexture);
+ if(getID().isNull())
+ return; // not logged in
+ gMessageSystem->newMessageFast(_PREHASH_UserInfoRequest);
gMessageSystem->nextBlockFast(_PREHASH_AgentData);
gMessageSystem->addUUIDFast(_PREHASH_AgentID, getID());
gMessageSystem->addUUIDFast(_PREHASH_SessionID, getSessionID());
- gMessageSystem->addS32Fast(_PREHASH_SerialNum, mTextureCacheQueryID);
-
- S32 num_queries = 0;
- for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++ )
- {
- const LLVOAvatarDictionary::WearableDictionaryEntry *wearable_dict = LLVOAvatarDictionary::getInstance()->getWearable((EBakedTextureIndex)baked_index);
- LLUUID hash;
- for (U8 i=0; i < wearable_dict->mWearablesVec.size(); i++)
- {
- // EWearableType wearable_type = gBakedWearableMap[baked_index][wearable_num];
- const EWearableType wearable_type = wearable_dict->mWearablesVec[i];
- const LLWearable* wearable = getWearable(wearable_type);
- if (wearable)
- {
- hash ^= wearable->getID();
- }
- }
- if (hash.notNull())
- {
- hash ^= wearable_dict->mHashID;
- num_queries++;
- // *NOTE: make sure at least one request gets packed
-
- //llinfos << "Requesting texture for hash " << hash << " in baked texture slot " << baked_index << llendl;
- gMessageSystem->nextBlockFast(_PREHASH_WearableData);
- gMessageSystem->addUUIDFast(_PREHASH_ID, hash);
- gMessageSystem->addU8Fast(_PREHASH_TextureIndex, (U8)baked_index);
- }
-
- mActiveCacheQueries[ baked_index ] = mTextureCacheQueryID;
- }
-
- llinfos << "Requesting texture cache entry for " << num_queries << " baked textures" << llendl;
- gMessageSystem->sendReliable(getRegion()->getHost());
- mNumPendingQueries++;
- mTextureCacheQueryID++;
-}
-
-// User has picked "remove from avatar" from a menu.
-// static
-void LLAgent::userRemoveWearable( void* userdata )
-{
- EWearableType type = (EWearableType)(intptr_t)userdata;
-
- if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR ) ) //&&
- //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) )
- {
- gAgent.removeWearable( type );
- }
-}
-
-void LLAgent::userRemoveAllClothes( void* userdata )
-{
- // We have to do this up front to avoid having to deal with the case of multiple wearables being dirty.
- if( gFloaterCustomize )
- {
- gFloaterCustomize->askToSaveIfDirty( LLAgent::userRemoveAllClothesStep2, NULL );
- }
- else
- {
- LLAgent::userRemoveAllClothesStep2( TRUE, NULL );
- }
-}
-
-void LLAgent::userRemoveAllClothesStep2( BOOL proceed, void* userdata )
-{
- if( proceed )
- {
- gAgent.removeWearable( WT_SHIRT );
- gAgent.removeWearable( WT_PANTS );
- gAgent.removeWearable( WT_SHOES );
- gAgent.removeWearable( WT_SOCKS );
- gAgent.removeWearable( WT_JACKET );
- gAgent.removeWearable( WT_GLOVES );
- gAgent.removeWearable( WT_UNDERSHIRT );
- gAgent.removeWearable( WT_UNDERPANTS );
- gAgent.removeWearable( WT_SKIRT );
- }
-}
-
-void LLAgent::userRemoveAllAttachments( void* userdata )
-{
- LLVOAvatar* avatarp = gAgent.getAvatarObject();
- if(!avatarp)
- {
- llwarns << "No avatar found." << llendl;
- return;
- }
-
- gMessageSystem->newMessage("ObjectDetach");
- gMessageSystem->nextBlockFast(_PREHASH_AgentData);
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
- gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-
- for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
- iter != avatarp->mAttachmentPoints.end(); )
- {
- LLVOAvatar::attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- LLViewerObject* objectp = attachment->getObject();
- if (objectp)
- {
- gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
- gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, objectp->getLocalID());
- }
- }
- gMessageSystem->sendReliable( gAgent.getRegionHost() );
+ sendReliableMessage();
}
void LLAgent::observeFriends()
@@ -7787,4 +6462,45 @@ void LLAgent::parseTeleportMessages(const std::string& xml_filename)
}//end for (all message sets in xml file)
}
+void LLAgent::sendAgentUpdateUserInfo(bool im_via_email, const std::string& directory_visibility )
+{
+ gMessageSystem->newMessageFast(_PREHASH_UpdateUserInfo);
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, getID());
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, getSessionID());
+ gMessageSystem->nextBlockFast(_PREHASH_UserData);
+ gMessageSystem->addBOOLFast(_PREHASH_IMViaEMail, im_via_email);
+ gMessageSystem->addString("DirectoryVisibility", directory_visibility);
+ gAgent.sendReliableMessage();
+}
+
+// static
+void LLAgent::dumpGroupInfo()
+{
+ llinfos << "group " << gAgent.mGroupName << llendl;
+ llinfos << "ID " << gAgent.mGroupID << llendl;
+ llinfos << "powers " << gAgent.mGroupPowers << llendl;
+ llinfos << "title " << gAgent.mGroupTitle << llendl;
+ //llinfos << "insig " << gAgent.mGroupInsigniaID << llendl;
+}
+
+/********************************************************************************/
+LLAgentQueryManager gAgentQueryManager;
+
+LLAgentQueryManager::LLAgentQueryManager() :
+ mWearablesCacheQueryID(0),
+ mNumPendingQueries(0),
+ mUpdateSerialNum(0)
+{
+ for (U32 i = 0; i < BAKED_NUM_INDICES; i++)
+ {
+ mActiveCacheQueries[i] = 0;
+ }
+}
+
+LLAgentQueryManager::~LLAgentQueryManager()
+{
+}
+
// EOF
+
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 226c78e631..beede7fbe3 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -33,63 +33,25 @@
#ifndef LL_LLAGENT_H
#define LL_LLAGENT_H
-#include <set>
-
#include "indra_constants.h"
-#include "llmath.h"
-#include "llcontrol.h"
-#include "llcoordframe.h"
-#include "llevent.h"
+#include "llevent.h" // LLObservable base class
#include "llagentaccess.h"
#include "llagentconstants.h"
-#include "llanimationstates.h"
-#include "lldbstrings.h"
-#include "llhudeffectlookat.h"
-#include "llhudeffectpointat.h"
-#include "llmemory.h"
-#include "llstring.h"
-#include "lluuid.h"
-#include "m3math.h"
-#include "m4math.h"
-#include "llquaternion.h"
-#include "lltimer.h"
-#include "v3dmath.h"
-#include "v3math.h"
-#include "v4color.h"
-#include "v4math.h"
-//#include "vmath.h"
-#include "stdenums.h"
-#include "llwearable.h"
-#include "llcharacter.h"
-#include "llinventory.h"
-#include "llviewerinventory.h"
-#include "llagentdata.h"
-
-// Ventrella
-#include "llfollowcam.h"
-// end Ventrella
-
-const U8 AGENT_STATE_TYPING = 0x04; // Typing indication
-const U8 AGENT_STATE_EDITING = 0x10; // Set when agent has objects selected
-
-const BOOL ANIMATE = TRUE;
-
-typedef enum e_camera_modes
-{
- CAMERA_MODE_THIRD_PERSON,
- CAMERA_MODE_MOUSELOOK,
- CAMERA_MODE_CUSTOMIZE_AVATAR,
- CAMERA_MODE_FOLLOW
-} ECameraMode;
-
-typedef enum e_anim_request
-{
- ANIM_REQUEST_START,
- ANIM_REQUEST_STOP
-} EAnimRequest;
+#include "llagentdata.h" // gAgentID, gAgentSessionID
+#include "llcharacter.h" // LLAnimPauseRequest
+#include "llfollowcam.h" // Ventrella
+#include "llhudeffectlookat.h" // EPointAtType
+#include "llhudeffectpointat.h" // ELookAtType
+#include "llpointer.h"
+#include "lluicolor.h"
+#include "llvoavatardefines.h"
+
+extern const BOOL ANIMATE;
+extern const U8 AGENT_STATE_TYPING; // Typing indication
+extern const U8 AGENT_STATE_EDITING; // Set when agent has objects selected
class LLChat;
-class LLVOAvatar;
+class LLVOAvatarSelf;
class LLViewerRegion;
class LLMotion;
class LLToolset;
@@ -98,6 +60,38 @@ class LLPermissions;
class LLHost;
class LLFriendObserver;
class LLPickInfo;
+class LLViewerObject;
+class LLAgentDropGroupViewerNode;
+
+//--------------------------------------------------------------------
+// Types
+//--------------------------------------------------------------------
+enum ECameraMode
+{
+ CAMERA_MODE_THIRD_PERSON,
+ CAMERA_MODE_MOUSELOOK,
+ CAMERA_MODE_CUSTOMIZE_AVATAR,
+ CAMERA_MODE_FOLLOW
+};
+
+/** Camera Presets for CAMERA_MODE_THIRD_PERSON */
+enum ECameraPreset
+{
+ /** Default preset, what the Third Person Mode actually was */
+ CAMERA_PRESET_REAR_VIEW,
+
+ /** "Looking at the Avatar from the front" */
+ CAMERA_PRESET_FRONT_VIEW,
+
+ /** "Above and to the left, over the shoulder, pulled back a little on the zoom" */
+ CAMERA_PRESET_GROUP_VIEW
+};
+
+enum EAnimRequest
+{
+ ANIM_REQUEST_START,
+ ANIM_REQUEST_STOP
+};
struct LLGroupData
{
@@ -110,478 +104,484 @@ struct LLGroupData
std::string mName;
};
-inline bool operator==(const LLGroupData &a, const LLGroupData &b)
-{
- return (a.mID == b.mID);
-}
-
-// forward declarations
-
-//
+class LLAgentListener;
-class LLAgent : public LLObservable
+//------------------------------------------------------------------------
+// LLAgent
+//------------------------------------------------------------------------
+class LLAgent : public LLOldEvents::LLObservable
{
LOG_CLASS(LLAgent);
-
+
public:
- // When the agent hasn't typed anything for this duration, it leaves the
- // typing state (for both chat and IM).
- static const F32 TYPING_TIMEOUT_SECS;
+ friend class LLAgentDropGroupViewerNode;
- LLAgent();
- ~LLAgent();
+/********************************************************************************
+ ** **
+ ** INITIALIZATION
+ **/
+ //--------------------------------------------------------------------
+ // Constructors / Destructors
+ //--------------------------------------------------------------------
+public:
+ LLAgent();
+ virtual ~LLAgent();
void init();
void cleanup();
+ void setAvatarObject(LLVOAvatarSelf *avatar);
- //
- // MANIPULATORS
- //
- // TODO: Put all non-const functions here.
-
- // Called whenever the agent moves. Puts camera back in default position,
- // deselects items, etc.
- void resetView(BOOL reset_camera = TRUE, BOOL change_camera = FALSE);
-
- // Called on camera movement, to allow the camera to be unlocked from the
- // default position behind the avatar.
- void unlockView();
-
- void onAppFocusGained();
-
- void sendMessage(); // Send message to this agent's region.
- void sendReliableMessage();
-
- LLVector3d calcCameraPositionTargetGlobal(BOOL *hit_limit = NULL); // Calculate the camera position target
- LLVector3d calcFocusPositionTargetGlobal();
- LLVector3d calcThirdPersonFocusOffset();
- // target for this mode
- LLVector3d getCameraPositionGlobal() const;
- const LLVector3 &getCameraPositionAgent() const;
- F32 calcCameraFOVZoomFactor();
- F32 getCameraMinOffGround(); // minimum height off ground for this mode, meters
- void endAnimationUpdateUI();
- void setKey(const S32 direction, S32 &key); // sets key to +1 for +direction, -1 for -direction
- void handleScrollWheel(S32 clicks); // mousewheel driven zoom
-
- void setAvatarObject(LLVOAvatar *avatar);
-
- // rendering state bitmask helpers
- void startTyping();
- void stopTyping();
- void setRenderState(U8 newstate);
- void clearRenderState(U8 clearstate);
- U8 getRenderState();
-
- // Set the home data
- void setRegion(LLViewerRegion *regionp);
- LLViewerRegion *getRegion() const;
- const LLHost& getRegionHost() const;
- std::string getSLURL() const;
-
- void updateAgentPosition(const F32 dt, const F32 yaw, const S32 mouse_x, const S32 mouse_y); // call once per frame to update position, angles radians
- void updateLookAt(const S32 mouse_x, const S32 mouse_y);
-
-
- void updateCamera(); // call once per frame to update camera location/orientation
- void resetCamera(); // slam camera into its default position
- void setupSitCamera();
- void setCameraCollidePlane(const LLVector4 &plane) { mCameraCollidePlane = plane; }
-
- void changeCameraToDefault();
- void changeCameraToMouselook(BOOL animate = TRUE);
- void changeCameraToThirdPerson(BOOL animate = TRUE);
- void changeCameraToCustomizeAvatar(BOOL avatar_animate = TRUE, BOOL camera_animate = TRUE); // trigger transition animation
- // Ventrella
- void changeCameraToFollow(BOOL animate = TRUE);
- //end Ventrella
-
- void setFocusGlobal(const LLPickInfo& pick);
- void setFocusGlobal(const LLVector3d &focus, const LLUUID &object_id = LLUUID::null);
- void setFocusOnAvatar(BOOL focus, BOOL animate);
- void setCameraPosAndFocusGlobal(const LLVector3d& pos, const LLVector3d& focus, const LLUUID &object_id);
- void setSitCamera(const LLUUID &object_id, const LLVector3 &camera_pos = LLVector3::zero, const LLVector3 &camera_focus = LLVector3::zero);
- void clearFocusObject();
- void setFocusObject(LLViewerObject* object);
- void setObjectTracking(BOOL track) { mTrackFocusObject = track; }
-// void setLookingAtAvatar(BOOL looking);
-
- void heardChat(const LLUUID& id);
- void lookAtLastChat();
- F32 getTypingTime() { return mTypingTimer.getElapsedTimeF32(); }
-
- void setAFK();
- void clearAFK();
- BOOL getAFK() const;
-
- void setAlwaysRun() { mbAlwaysRun = true; }
- void clearAlwaysRun() { mbAlwaysRun = false; }
-
- void setRunning() { mbRunning = true; }
- void clearRunning() { mbRunning = false; }
-
- void setBusy();
- void clearBusy();
- BOOL getBusy() const;
-
- void setAdminOverride(BOOL b);
- void setGodLevel(U8 god_level);
- void setFirstLogin(BOOL b) { mFirstLogin = b; }
- void setGenderChosen(BOOL b) { mGenderChosen = b; }
-
- // update internal datastructures and update the server with the
- // new contribution level. Returns true if the group id was found
- // and contribution could be set.
- BOOL setGroupContribution(const LLUUID& group_id, S32 contribution);
- BOOL setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOOL list_in_profile);
- void setHideGroupTitle(BOOL hide) { mHideGroupTitle = hide; }
-
- //
- // ACCESSORS
- //
- // TODO: Put all read functions here, make them const
+ //--------------------------------------------------------------------
+ // Login
+ //--------------------------------------------------------------------
+public:
+ void onAppFocusGained();
+ void setFirstLogin(BOOL b) { mFirstLogin = b; }
+ // Return TRUE if the database reported this login as the first for this particular user.
+ BOOL isFirstLogin() const { return mFirstLogin; }
+public:
+ BOOL mInitialized;
+ BOOL mFirstLogin;
+ std::string mMOTD; // Message of the day
+private:
+ boost::shared_ptr<LLAgentListener> mListener;
+ //--------------------------------------------------------------------
+ // Session
+ //--------------------------------------------------------------------
+public:
const LLUUID& getID() const { return gAgentID; }
const LLUUID& getSessionID() const { return gAgentSessionID; }
-
+ // Note: NEVER send this value in the clear or over any weakly
+ // encrypted channel (such as simple XOR masking). If you are unsure
+ // ask Aaron or MarkL.
const LLUUID& getSecureSessionID() const { return mSecureSessionID; }
- // Note: NEVER send this value in the clear or over any weakly
- // encrypted channel (such as simple XOR masking). If you are unsure
- // ask Aaron or MarkL.
-
- BOOL isGodlike() const;
- U8 getGodLevel() const;
- // note: this is a prime candidate for pulling out into a Maturity class
- // rather than just expose the preference setting, we're going to actually
- // expose what the client code cares about -- what the user should see
- // based on a combination of the is* and prefers* flags, combined with God bit.
- bool wantsPGOnly() const;
- bool canAccessMature() const;
- bool canAccessAdult() const;
- bool canAccessMaturityInRegion( U64 region_handle ) const;
- bool canAccessMaturityAtGlobal( LLVector3d pos_global ) const;
- bool prefersPG() const;
- bool prefersMature() const;
- bool prefersAdult() const;
- bool isTeen() const;
- bool isMature() const;
- bool isAdult() const;
- void setTeen(bool teen);
- void setMaturity(char text);
- static int convertTextToMaturity(char text);
- bool sendMaturityPreferenceToServer(int preferredMaturity);
-
- const LLAgentAccess& getAgentAccess();
-
- // This function can go away after the AO transition (see llstartup.cpp)
- void setAOTransition();
+public:
+ LLUUID mSecureSessionID; // Secure token for this login session
- BOOL isGroupTitleHidden() const { return mHideGroupTitle; }
- BOOL isGroupMember() const { return !mGroupID.isNull(); } // This is only used for building titles!
- const LLUUID &getGroupID() const { return mGroupID; }
- ECameraMode getCameraMode() const { return mCameraMode; }
- BOOL getFocusOnAvatar() const { return mFocusOnAvatar; }
- LLPointer<LLViewerObject>& getFocusObject() { return mFocusObject; }
- F32 getFocusObjectDist() const { return mFocusObjectDist; }
- BOOL inPrelude();
- BOOL canManageEstate() const;
- BOOL getAdminOverride() const;
-
- LLUUID getLastChatter() const { return mLastChatterID; }
- bool getAlwaysRun() const { return mbAlwaysRun; }
- bool getRunning() const { return mbRunning; }
+/** Initialization
+ ** **
+ *******************************************************************************/
- const LLUUID& getInventoryRootID() const { return mInventoryRootID; }
+/********************************************************************************
+ ** **
+ ** IDENTITY
+ **/
- void buildFullname(std::string &name) const;
+ //--------------------------------------------------------------------
+ // Name
+ //--------------------------------------------------------------------
+public:
+ //*TODO remove, is not used as of August 20, 2009
void buildFullnameAndTitle(std::string &name) const;
- // Check against all groups in the entire agent group list.
- BOOL isInGroup(const LLUUID& group_id) const;
- BOOL hasPowerInGroup(const LLUUID& group_id, U64 power) const;
- // Check for power in just the active group.
- BOOL hasPowerInActiveGroup(const U64 power) const;
- U64 getPowerInGroup(const LLUUID& group_id) const;
-
- // Get group information by group_id. if not in group, data is
- // left unchanged and method returns FALSE. otherwise, values are
- // copied and returns TRUE.
- BOOL getGroupData(const LLUUID& group_id, LLGroupData& data) const;
- // Get just the agent's contribution to the given group.
- S32 getGroupContribution(const LLUUID& group_id) const;
-
- // return TRUE if the database reported this login as the first
- // for this particular user.
- BOOL isFirstLogin() const { return mFirstLogin; }
-
+ //--------------------------------------------------------------------
+ // Gender
+ //--------------------------------------------------------------------
+public:
// On the very first login, gender isn't chosen until the user clicks
// in a dialog. We don't render the avatar until they choose.
- BOOL isGenderChosen() const { return mGenderChosen; }
-
- // utility to build a location string
- void buildLocationString(std::string& str);
-
- LLQuaternion getHeadRotation();
- LLVOAvatar *getAvatarObject() const { return mAvatarObject; }
-
- BOOL needsRenderAvatar(); // TRUE when camera mode is such that your own avatar should draw
- // Not const because timers can't be accessed in const-fashion.
- BOOL needsRenderHead();
- BOOL cameraThirdPerson() const { return (mCameraMode == CAMERA_MODE_THIRD_PERSON && mLastCameraMode == CAMERA_MODE_THIRD_PERSON); }
- BOOL cameraMouselook() const { return (mCameraMode == CAMERA_MODE_MOUSELOOK && mLastCameraMode == CAMERA_MODE_MOUSELOOK); }
- BOOL cameraCustomizeAvatar() const { return (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR /*&& !mCameraAnimating*/); }
- BOOL cameraFollow() const { return (mCameraMode == CAMERA_MODE_FOLLOW && mLastCameraMode == CAMERA_MODE_FOLLOW); }
+ BOOL isGenderChosen() const { return mGenderChosen; }
+ void setGenderChosen(BOOL b) { mGenderChosen = b; }
+private:
+ BOOL mGenderChosen;
- LLVector3 getPosAgentFromGlobal(const LLVector3d &pos_global) const;
- LLVector3d getPosGlobalFromAgent(const LLVector3 &pos_agent) const;
+/** Identity
+ ** **
+ *******************************************************************************/
- // Get the data members
- const LLVector3& getAtAxis() const { return mFrameAgent.getAtAxis(); } // direction avatar is looking, not camera
- const LLVector3& getUpAxis() const { return mFrameAgent.getUpAxis(); } // direction avatar is looking, not camera
- const LLVector3& getLeftAxis() const { return mFrameAgent.getLeftAxis(); } // direction avatar is looking, not camera
+/********************************************************************************
+ ** **
+ ** GENERAL ACCESSORS
+ **/
- LLCoordFrame getFrameAgent() const { return mFrameAgent; }
- LLVector3 getVelocity() const;
- F32 getVelocityZ() const { return getVelocity().mV[VZ]; } // a hack
+public:
+ LLVOAvatarSelf* getAvatarObject() const { return mAvatarObject; }
+private:
+ LLPointer<LLVOAvatarSelf> mAvatarObject; // NULL until avatar object sent down from simulator
- const LLVector3d &getPositionGlobal() const;
- const LLVector3 &getPositionAgent();
- S32 getRegionsVisited() const;
- F64 getDistanceTraveled() const;
+/** General Accessors
+ ** **
+ *******************************************************************************/
- const LLVector3d &getFocusGlobal() const { return mFocusGlobal; }
- const LLVector3d &getFocusTargetGlobal() const { return mFocusTargetGlobal; }
+/********************************************************************************
+ ** **
+ ** POSITION
+ **/
- BOOL getJump() const { return mbJump; }
- BOOL getAutoPilot() const { return mAutoPilot; }
- LLVector3d getAutoPilotTargetGlobal() const { return mAutoPilotTargetGlobal; }
+ //--------------------------------------------------------------------
+ // Position
+ //--------------------------------------------------------------------
+public:
+ LLVector3 getPosAgentFromGlobal(const LLVector3d &pos_global) const;
+ LLVector3d getPosGlobalFromAgent(const LLVector3 &pos_agent) const;
+ const LLVector3d &getPositionGlobal() const;
+ const LLVector3 &getPositionAgent();
+ // Call once per frame to update position, angles (radians).
+ void updateAgentPosition(const F32 dt, const F32 yaw, const S32 mouse_x, const S32 mouse_y);
+ void setPositionAgent(const LLVector3 &center);
+protected:
+ void propagate(const F32 dt); // ! BUG ! Should roll into updateAgentPosition
+private:
+ mutable LLVector3d mPositionGlobal;
- LLQuaternion getQuat() const; // returns the quat that represents the rotation
- // of the agent in the absolute frame
-// BOOL getLookingAtAvatar() const;
+ //--------------------------------------------------------------------
+ // Velocity
+ //--------------------------------------------------------------------
+public:
+ LLVector3 getVelocity() const;
+ F32 getVelocityZ() const { return getVelocity().mV[VZ]; } // ! HACK !
+
+ //--------------------------------------------------------------------
+ // Coordinate System
+ //--------------------------------------------------------------------
+public:
+ LLCoordFrame getFrameAgent() const { return mFrameAgent; }
+ void initOriginGlobal(const LLVector3d &origin_global); // Only to be used in ONE place
+ void resetAxes();
+ void resetAxes(const LLVector3 &look_at); // Makes reasonable left and up
+ // The following three get*Axis functions return direction avatar is looking, not camera.
+ const LLVector3& getAtAxis() const { return mFrameAgent.getAtAxis(); }
+ const LLVector3& getUpAxis() const { return mFrameAgent.getUpAxis(); }
+ const LLVector3& getLeftAxis() const { return mFrameAgent.getLeftAxis(); }
+ LLQuaternion getQuat() const; // Returns the quat that represents the rotation of the agent in the absolute frame
+private:
+ LLVector3d mAgentOriginGlobal; // Origin of agent coords from global coords
+ LLCoordFrame mFrameAgent; // Agent position and view, agent-region coordinates
- void getName(std::string& name);
- const LLColor4 &getEffectColor();
- void setEffectColor(const LLColor4 &color);
- //
- // UTILITIES
- //
+ //--------------------------------------------------------------------
+ // Home
+ //--------------------------------------------------------------------
+public:
+ void setStartPosition(U32 location_id); // Marks current location as start, sends information to servers
+ void setHomePosRegion(const U64& region_handle, const LLVector3& pos_region);
+ BOOL getHomePosGlobal(LLVector3d* pos_global);
+private:
+ BOOL mHaveHomePosition;
+ U64 mHomeRegionHandle;
+ LLVector3 mHomePosRegion;
- // Set the physics data
- void slamLookAt(const LLVector3 &look_at);
+ //--------------------------------------------------------------------
+ // Region
+ //--------------------------------------------------------------------
+public:
+ void setRegion(LLViewerRegion *regionp);
+ LLViewerRegion *getRegion() const;
+ LLHost getRegionHost() const;
+ BOOL inPrelude();
+private:
+ LLViewerRegion *mRegionp;
- void setPositionAgent(const LLVector3 &center);
+ //--------------------------------------------------------------------
+ // History
+ //--------------------------------------------------------------------
+public:
+ S32 getRegionsVisited() const;
+ F64 getDistanceTraveled() const;
+private:
+ std::set<U64> mRegionsVisited; // Stat - what distinct regions has the avatar been to?
+ F64 mDistanceTraveled; // Stat - how far has the avatar moved?
+ LLVector3d mLastPositionGlobal; // Used to calculate travel distance
+
+/** Position
+ ** **
+ *******************************************************************************/
- void resetAxes();
- void resetAxes(const LLVector3 &look_at); // makes reasonable left and up
+/********************************************************************************
+ ** **
+ ** ACTIONS
+ **/
- // Move the avatar's frame
- void rotate(F32 angle, const LLVector3 &axis);
- void rotate(F32 angle, F32 x, F32 y, F32 z);
- void rotate(const LLMatrix3 &matrix);
- void rotate(const LLQuaternion &quaternion);
- void pitch(F32 angle);
- void roll(F32 angle);
- void yaw(F32 angle);
- LLVector3 getReferenceUpVector();
- F32 clampPitchToLimits(F32 angle);
+ //--------------------------------------------------------------------
+ // Fidget
+ //--------------------------------------------------------------------
+ // Trigger random fidget animations
+public:
+ void fidget();
+ static void stopFidget();
+private:
+ LLFrameTimer mFidgetTimer;
+ LLFrameTimer mFocusObjectFadeTimer;
+ F32 mNextFidgetTime;
+ S32 mCurrentFidget;
- void setThirdPersonHeadOffset(LLVector3 offset) { mThirdPersonHeadOffset = offset; }
- // Flight management
- BOOL getFlying() const { return mControlFlags & AGENT_CONTROL_FLY; }
+ //--------------------------------------------------------------------
+ // Fly
+ //--------------------------------------------------------------------
+public:
+ BOOL getFlying() const;
void setFlying(BOOL fly);
- void toggleFlying();
-
- // Does this parcel allow you to fly?
- BOOL canFly();
-
- // Animation functions
- void stopCurrentAnimations();
- void requestStopMotion( LLMotion* motion );
- void onAnimStop(const LLUUID& id);
+ static void toggleFlying();
+ static bool enableFlying();
+ BOOL canFly(); // Does this parcel allow you to fly?
+
+ //--------------------------------------------------------------------
+ // Chat
+ //--------------------------------------------------------------------
+public:
+ void heardChat(const LLUUID& id);
+ void lookAtLastChat();
+ F32 getTypingTime() { return mTypingTimer.getElapsedTimeF32(); }
+ LLUUID getLastChatter() const { return mLastChatterID; }
+ F32 getNearChatRadius() { return mNearChatRadius; }
+protected:
+ void ageChat(); // Helper function to prematurely age chat when agent is moving
+private:
+ LLFrameTimer mChatTimer;
+ LLUUID mLastChatterID;
+ F32 mNearChatRadius;
+
+ //--------------------------------------------------------------------
+ // Typing
+ //--------------------------------------------------------------------
+public:
+ void startTyping();
+ void stopTyping();
+public:
+ // When the agent hasn't typed anything for this duration, it leaves the
+ // typing state (for both chat and IM).
+ static const F32 TYPING_TIMEOUT_SECS;
+private:
+ LLFrameTimer mTypingTimer;
- void sendAnimationRequests(LLDynamicArray<LLUUID> &anim_ids, EAnimRequest request);
- void sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request);
+ //--------------------------------------------------------------------
+ // AFK
+ //--------------------------------------------------------------------
+public:
+ void setAFK();
+ void clearAFK();
+ BOOL getAFK() const;
- LLVector3 calcFocusOffset(LLViewerObject *object, LLVector3 pos_agent, S32 x, S32 y);
- BOOL calcCameraMinDistance(F32 &obj_min_distance);
+ //--------------------------------------------------------------------
+ // Run
+ //--------------------------------------------------------------------
+public:
+ enum EDoubleTapRunMode
+ {
+ DOUBLETAP_NONE,
+ DOUBLETAP_FORWARD,
+ DOUBLETAP_BACKWARD,
+ DOUBLETAP_SLIDELEFT,
+ DOUBLETAP_SLIDERIGHT
+ };
- void startCameraAnimation();
- void stopCameraAnimation();
+ void setAlwaysRun() { mbAlwaysRun = true; }
+ void clearAlwaysRun() { mbAlwaysRun = false; }
+ void setRunning() { mbRunning = true; }
+ void clearRunning() { mbRunning = false; }
+ void sendWalkRun(bool running);
+ bool getAlwaysRun() const { return mbAlwaysRun; }
+ bool getRunning() const { return mbRunning; }
+public:
+ LLFrameTimer mDoubleTapRunTimer;
+ EDoubleTapRunMode mDoubleTapRunMode;
+private:
+ bool mbAlwaysRun; // Should the avatar run by default rather than walk?
+ bool mbRunning; // Is the avatar trying to run right now?
- void cameraZoomIn(const F32 factor); // zoom in by fraction of current distance
- void cameraOrbitAround(const F32 radians); // rotate camera CCW radians about build focus point
- void cameraOrbitOver(const F32 radians); // rotate camera forward radians over build focus point
- void cameraOrbitIn(const F32 meters); // move camera in toward build focus point
+ //--------------------------------------------------------------------
+ // Sit and stand
+ //--------------------------------------------------------------------
+public:
+ void standUp();
- F32 getCameraZoomFraction(); // get camera zoom as fraction of minimum and maximum zoom
- void setCameraZoomFraction(F32 fraction); // set camera zoom as fraction of minimum and maximum zoom
+ //--------------------------------------------------------------------
+ // Busy
+ //--------------------------------------------------------------------
+public:
+ void setBusy();
+ void clearBusy();
+ BOOL getBusy() const;
+private:
+ BOOL mIsBusy;
- void cameraPanIn(const F32 meters);
- void cameraPanLeft(const F32 meters);
- void cameraPanUp(const F32 meters);
+ //--------------------------------------------------------------------
+ // Jump
+ //--------------------------------------------------------------------
+public:
+ BOOL getJump() const { return mbJump; }
+private:
+ BOOL mbJump;
- void updateFocusOffset();
- void validateFocusObject();
+ //--------------------------------------------------------------------
+ // Grab
+ //--------------------------------------------------------------------
+public:
+ BOOL leftButtonGrabbed() const;
+ BOOL rotateGrabbed() const;
+ BOOL forwardGrabbed() const;
+ BOOL backwardGrabbed() const;
+ BOOL upGrabbed() const;
+ BOOL downGrabbed() const;
- void setUsingFollowCam( bool using_follow_cam);
+ //--------------------------------------------------------------------
+ // Controls
+ //--------------------------------------------------------------------
+public:
+ U32 getControlFlags();
+ void setControlFlags(U32 mask); // Performs bitwise mControlFlags |= mask
+ void clearControlFlags(U32 mask); // Performs bitwise mControlFlags &= ~mask
+ BOOL controlFlagsDirty() const;
+ void enableControlFlagReset();
+ void resetControlFlags();
+ BOOL anyControlGrabbed() const; // True iff a script has taken over a control
+ BOOL isControlGrabbed(S32 control_index) const;
+ // Send message to simulator to force grabbed controls to be
+ // released, in case of a poorly written script.
+ void forceReleaseControls();
+private:
+ S32 mControlsTakenCount[TOTAL_CONTROLS];
+ S32 mControlsTakenPassedOnCount[TOTAL_CONTROLS];
+ U32 mControlFlags; // Replacement for the mFooKey's
+ BOOL mbFlagsDirty;
+ BOOL mbFlagsNeedReset; // ! HACK ! For preventing incorrect flags sent when crossing region boundaries
- F32 calcCustomizeAvatarUIOffset( const LLVector3d& camera_pos_global );
-
- // marks current location as start, sends information to servers
- void setStartPosition(U32 location_id);
+ //--------------------------------------------------------------------
+ // Animations
+ //--------------------------------------------------------------------
+public:
+ void stopCurrentAnimations();
+ void requestStopMotion(LLMotion* motion);
+ void onAnimStop(const LLUUID& id);
+ void sendAnimationRequests(LLDynamicArray<LLUUID> &anim_ids, EAnimRequest request);
+ void sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request);
+ void endAnimationUpdateUI();
+private:
+ LLFrameTimer mAnimationTimer; // Seconds that transition animation has been active
+ F32 mAnimationDuration; // In seconds
+ BOOL mCustomAnim; // Current animation is ANIM_AGENT_CUSTOMIZE ?
+ LLAnimPauseRequest mPauseRequest;
+ BOOL mViewsPushed; // Keep track of whether or not we have pushed views
+
+/** Animation
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** MOVEMENT
+ **/
+
+ //--------------------------------------------------------------------
+ // Keys
+ //--------------------------------------------------------------------
+public:
+ void setKey(const S32 direction, S32 &key); // Sets key to +1 for +direction, -1 for -direction
+private:
+ S32 mAtKey; // Either 1, 0, or -1. Indicates that movement key is pressed
+ S32 mWalkKey; // Like AtKey, but causes less forward thrust
+ S32 mLeftKey;
+ S32 mUpKey;
+ F32 mYawKey;
+ F32 mPitchKey;
- // Movement from user input. All set the appropriate animation flags.
+ //--------------------------------------------------------------------
+ // Movement from user input
+ //--------------------------------------------------------------------
+ // All set the appropriate animation flags.
// All turn off autopilot and make sure the camera is behind the avatar.
- // direction is either positive, zero, or negative
+ // Direction is either positive, zero, or negative
+public:
void moveAt(S32 direction, bool reset_view = true);
void moveAtNudge(S32 direction);
void moveLeft(S32 direction);
void moveLeftNudge(S32 direction);
void moveUp(S32 direction);
void moveYaw(F32 mag, bool reset_view = true);
- void movePitch(S32 direction);
-
- void setOrbitLeftKey(F32 mag) { mOrbitLeftKey = mag; }
- void setOrbitRightKey(F32 mag) { mOrbitRightKey = mag; }
- void setOrbitUpKey(F32 mag) { mOrbitUpKey = mag; }
- void setOrbitDownKey(F32 mag) { mOrbitDownKey = mag; }
- void setOrbitInKey(F32 mag) { mOrbitInKey = mag; }
- void setOrbitOutKey(F32 mag) { mOrbitOutKey = mag; }
-
- void setPanLeftKey(F32 mag) { mPanLeftKey = mag; }
- void setPanRightKey(F32 mag) { mPanRightKey = mag; }
- void setPanUpKey(F32 mag) { mPanUpKey = mag; }
- void setPanDownKey(F32 mag) { mPanDownKey = mag; }
- void setPanInKey(F32 mag) { mPanInKey = mag; }
- void setPanOutKey(F32 mag) { mPanOutKey = mag; }
+ void movePitch(F32 mag);
- U32 getControlFlags();
- void setControlFlags(U32 mask); // performs bitwise mControlFlags |= mask
- void clearControlFlags(U32 mask); // performs bitwise mControlFlags &= ~mask
- BOOL controlFlagsDirty() const;
- void enableControlFlagReset();
- void resetControlFlags();
-
- void propagate(const F32 dt); // BUG: should roll into updateAgentPosition
+ //--------------------------------------------------------------------
+ // Orbit
+ //--------------------------------------------------------------------
+public:
+ void setOrbitLeftKey(F32 mag) { mOrbitLeftKey = mag; }
+ void setOrbitRightKey(F32 mag) { mOrbitRightKey = mag; }
+ void setOrbitUpKey(F32 mag) { mOrbitUpKey = mag; }
+ void setOrbitDownKey(F32 mag) { mOrbitDownKey = mag; }
+ void setOrbitInKey(F32 mag) { mOrbitInKey = mag; }
+ void setOrbitOutKey(F32 mag) { mOrbitOutKey = mag; }
+private:
+ F32 mOrbitLeftKey;
+ F32 mOrbitRightKey;
+ F32 mOrbitUpKey;
+ F32 mOrbitDownKey;
+ F32 mOrbitInKey;
+ F32 mOrbitOutKey;
+
+ //--------------------------------------------------------------------
+ // Pan
+ //--------------------------------------------------------------------
+public:
+ void setPanLeftKey(F32 mag) { mPanLeftKey = mag; }
+ void setPanRightKey(F32 mag) { mPanRightKey = mag; }
+ void setPanUpKey(F32 mag) { mPanUpKey = mag; }
+ void setPanDownKey(F32 mag) { mPanDownKey = mag; }
+ void setPanInKey(F32 mag) { mPanInKey = mag; }
+ void setPanOutKey(F32 mag) { mPanOutKey = mag; }
+private:
+ F32 mPanUpKey;
+ F32 mPanDownKey;
+ F32 mPanLeftKey;
+ F32 mPanRightKey;
+ F32 mPanInKey;
+ F32 mPanOutKey;
- void startAutoPilotGlobal(const LLVector3d &pos_global, const std::string& behavior_name = std::string(), const LLQuaternion *target_rotation = NULL,
- void (*finish_callback)(BOOL, void *) = NULL, void *callback_data = NULL, F32 stop_distance = 0.f, F32 rotation_threshold = 0.03f);
+ //--------------------------------------------------------------------
+ // Move the avatar's frame
+ //--------------------------------------------------------------------
+public:
+ void rotate(F32 angle, const LLVector3 &axis);
+ void rotate(F32 angle, F32 x, F32 y, F32 z);
+ void rotate(const LLMatrix3 &matrix);
+ void rotate(const LLQuaternion &quaternion);
+ void pitch(F32 angle);
+ void roll(F32 angle);
+ void yaw(F32 angle);
+ LLVector3 getReferenceUpVector();
+ F32 clampPitchToLimits(F32 angle);
+ //--------------------------------------------------------------------
+ // Autopilot
+ //--------------------------------------------------------------------
+public:
+ BOOL getAutoPilot() const { return mAutoPilot; }
+ LLVector3d getAutoPilotTargetGlobal() const { return mAutoPilotTargetGlobal; }
+ void startAutoPilotGlobal(const LLVector3d &pos_global,
+ const std::string& behavior_name = std::string(),
+ const LLQuaternion *target_rotation = NULL,
+ void (*finish_callback)(BOOL, void *) = NULL, void *callback_data = NULL,
+ F32 stop_distance = 0.f, F32 rotation_threshold = 0.03f);
void startFollowPilot(const LLUUID &leader_id);
void stopAutoPilot(BOOL user_cancel = FALSE);
void setAutoPilotGlobal(const LLVector3d &pos_global);
- void autoPilot(F32 *delta_yaw); // autopilot walking action, angles in radians
+ void autoPilot(F32 *delta_yaw); // Autopilot walking action, angles in radians
void renderAutoPilotTarget();
+private:
+ BOOL mAutoPilot;
+ BOOL mAutoPilotFlyOnStop;
+ LLVector3d mAutoPilotTargetGlobal;
+ F32 mAutoPilotStopDistance;
+ BOOL mAutoPilotUseRotation;
+ LLVector3 mAutoPilotTargetFacing;
+ F32 mAutoPilotTargetDist;
+ S32 mAutoPilotNoProgressFrameCount;
+ F32 mAutoPilotRotationThreshold;
+ std::string mAutoPilotBehaviorName;
+ void (*mAutoPilotFinishedCallback)(BOOL, void *);
+ void* mAutoPilotCallbackData;
+ LLUUID mLeaderID;
+
+/** Movement
+ ** **
+ *******************************************************************************/
- //
- // teportation methods
- //
-
- // go to a named location home
- void teleportRequest(
- const U64& region_handle,
- const LLVector3& pos_local);
-
- // teleport to a landmark
- void teleportViaLandmark(const LLUUID& landmark_id);
-
- // go home
- void teleportHome() { teleportViaLandmark(LLUUID::null); }
-
- // to an invited location
- void teleportViaLure(const LLUUID& lure_id, BOOL godlike);
-
- // to a global location - this will probably need to be
- // deprecated.
- void teleportViaLocation(const LLVector3d& pos_global);
-
- // cancel the teleport, may or may not be allowed by server
- void teleportCancel();
-
- void setTargetVelocity(const LLVector3 &vel);
- const LLVector3 &getTargetVelocity() const;
-
- const std::string getTeleportSourceSLURL() const { return mTeleportSourceSLURL; }
-
-
- // Setting the ability for this avatar to proxy for another avatar.
- //static void processAddModifyAbility(LLMessageSystem* msg, void**);
- //static void processGrantedProxies(LLMessageSystem* msg, void**);
- //static void processRemoveModifyAbility(LLMessageSystem* msg, void**);
- //BOOL isProxyFor(const LLUUID& agent_id);// *FIX should be const
-
- static void processAgentDataUpdate(LLMessageSystem *msg, void **);
- static void processAgentGroupDataUpdate(LLMessageSystem *msg, void **);
- static void processAgentDropGroup(LLMessageSystem *msg, void **);
- static void processScriptControlChange(LLMessageSystem *msg, void **);
- static void processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void **user_data);
- //static void processControlTake(LLMessageSystem *msg, void **);
- //static void processControlRelease(LLMessageSystem *msg, void **);
-
- // This method checks to see if this agent can modify an object
- // based on the permissions and the agent's proxy status.
- BOOL isGrantedProxy(const LLPermissions& perm);
-
- BOOL allowOperation(PermissionBit op,
- const LLPermissions& perm,
- U64 group_proxy_power = 0,
- U8 god_minimum = GOD_MAINTENANCE);
-
- friend std::ostream& operator<<(std::ostream &s, const LLAgent &sphere);
-
- void initOriginGlobal(const LLVector3d &origin_global); // Only to be used in ONE place! - djs 08/07/02
-
- BOOL leftButtonGrabbed() const { return ( (!cameraMouselook() && mControlsTakenCount[CONTROL_LBUTTON_DOWN_INDEX] > 0)
- ||(cameraMouselook() && mControlsTakenCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0)
- ||(!cameraMouselook() && mControlsTakenPassedOnCount[CONTROL_LBUTTON_DOWN_INDEX] > 0)
- ||(cameraMouselook() && mControlsTakenPassedOnCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0)); }
- BOOL rotateGrabbed() const { return ( (mControlsTakenCount[CONTROL_YAW_POS_INDEX] > 0)
- ||(mControlsTakenCount[CONTROL_YAW_NEG_INDEX] > 0)); }
- BOOL forwardGrabbed() const { return ( (mControlsTakenCount[CONTROL_AT_POS_INDEX] > 0)); }
- BOOL backwardGrabbed() const { return ( (mControlsTakenCount[CONTROL_AT_NEG_INDEX] > 0)); }
- BOOL upGrabbed() const { return ( (mControlsTakenCount[CONTROL_UP_POS_INDEX] > 0)); }
- BOOL downGrabbed() const { return ( (mControlsTakenCount[CONTROL_UP_NEG_INDEX] > 0)); }
-
- // True iff a script has taken over a control.
- BOOL anyControlGrabbed() const;
-
- BOOL isControlGrabbed(S32 control_index) const;
-
- // Send message to simulator to force grabbed controls to be
- // released, in case of a poorly written script.
- void forceReleaseControls();
-
- BOOL sitCameraEnabled() { return mSitCameraEnabled; }
-
- F32 getCurrentCameraBuildOffset() { return (F32)mCameraFocusOffset.length(); }
-
- // look at behavior
- BOOL setLookAt(ELookAtType target_type, LLViewerObject *object = NULL, LLVector3 position = LLVector3::zero);
- ELookAtType getLookAtType();
-
- // point at behavior
- BOOL setPointAt(EPointAtType target_type, LLViewerObject *object = NULL, LLVector3 position = LLVector3::zero);
- EPointAtType getPointAtType();
-
- void setHomePosRegion( const U64& region_handle, const LLVector3& pos_region );
- BOOL getHomePosGlobal( LLVector3d* pos_global );
- void setCameraAnimating( BOOL b ) { mCameraAnimating = b; }
- BOOL getCameraAnimating( ) { return mCameraAnimating; }
- void setAnimationDuration( F32 seconds ) { mAnimationDuration = seconds; }
-
- F32 getNearChatRadius() { return mNearChatRadius; }
-
- enum EDoubleTapRunMode
- {
- DOUBLETAP_NONE,
- DOUBLETAP_FORWARD,
- DOUBLETAP_BACKWARD,
- DOUBLETAP_SLIDELEFT,
- DOUBLETAP_SLIDERIGHT
- };
+/********************************************************************************
+ ** **
+ ** TELEPORT
+ **/
+public:
enum ETeleportState
{
TELEPORT_NONE = 0, // No teleport in progress
@@ -592,376 +592,508 @@ public:
TELEPORT_ARRIVING = 5 // Make the user wait while content "pre-caches"
};
- ETeleportState getTeleportState() const { return mTeleportState; }
- void setTeleportState( ETeleportState state );
- const std::string& getTeleportMessage() const { return mTeleportMessage; }
- void setTeleportMessage(const std::string& message)
- {
- mTeleportMessage = message;
- }
-
- // trigger random fidget animations
- void fidget();
-
- void requestEnterGodMode();
- void requestLeaveGodMode();
-
- void sendAgentSetAppearance();
+public:
+ static void parseTeleportMessages(const std::string& xml_filename);
+ const std::string getTeleportSourceSLURL() const { return mTeleportSourceSLURL; }
+public:
+ // ! TODO ! Define ERROR and PROGRESS enums here instead of exposing the mappings.
+ static std::map<std::string, std::string> sTeleportErrorMessages;
+ static std::map<std::string, std::string> sTeleportProgressMessages;
+private:
+ std::string mTeleportSourceSLURL; // SLURL where last TP began
- void sendAgentDataUpdateRequest();
+ //--------------------------------------------------------------------
+ // Teleport Actions
+ //--------------------------------------------------------------------
+public:
+ void teleportRequest(const U64& region_handle,
+ const LLVector3& pos_local); // Go to a named location home
+ void teleportViaLandmark(const LLUUID& landmark_id); // Teleport to a landmark
+ void teleportHome() { teleportViaLandmark(LLUUID::null); } // Go home
+ void teleportViaLure(const LLUUID& lure_id, BOOL godlike); // To an invited location
+ void teleportViaLocation(const LLVector3d& pos_global); // To a global location - this will probably need to be deprecated
+ void teleportCancel(); // May or may not be allowed by server
+protected:
+ bool teleportCore(bool is_local = false); // Stuff for all teleports; returns true if the teleport can proceed
- // Ventrella
- LLFollowCam mFollowCam;
- // end Ventrella
+ //--------------------------------------------------------------------
+ // Teleport State
+ //--------------------------------------------------------------------
+public:
+ ETeleportState getTeleportState() const { return mTeleportState; }
+ void setTeleportState(ETeleportState state);
+private:
+ ETeleportState mTeleportState;
//--------------------------------------------------------------------
- // Wearables
+ // Teleport Message
//--------------------------------------------------------------------
- void setWearable( LLInventoryItem* new_item, LLWearable* wearable );
- static bool onSetWearableDialog( const LLSD& notification, const LLSD& response, LLWearable* wearable );
- void setWearableFinal( LLInventoryItem* new_item, LLWearable* new_wearable );
- void setWearableOutfit( const LLInventoryItem::item_array_t& items, const LLDynamicArray< LLWearable* >& wearables, BOOL remove );
- void queryWearableCache();
+public:
+ const std::string& getTeleportMessage() const { return mTeleportMessage; }
+ void setTeleportMessage(const std::string& message) { mTeleportMessage = message; }
+private:
+ std::string mTeleportMessage;
+
+/** Teleport
+ ** **
+ *******************************************************************************/
- BOOL isWearableModifiable(EWearableType type);
- BOOL isWearableCopyable(EWearableType type);
- BOOL needsReplacement(EWearableType wearableType, S32 remove);
- U32 getWearablePermMask(EWearableType type);
+/********************************************************************************
+ ** **
+ ** CAMERA
+ **/
- LLInventoryItem* getWearableInventoryItem(EWearableType type);
+ //--------------------------------------------------------------------
+ // Mode
+ //--------------------------------------------------------------------
+public:
+ void changeCameraToDefault();
+ void changeCameraToMouselook(BOOL animate = TRUE);
+ void changeCameraToThirdPerson(BOOL animate = TRUE);
+ void changeCameraToCustomizeAvatar(BOOL avatar_animate = TRUE, BOOL camera_animate = TRUE); // Trigger transition animation
+ void changeCameraToFollow(BOOL animate = TRUE); // Ventrella
+ BOOL cameraThirdPerson() const { return (mCameraMode == CAMERA_MODE_THIRD_PERSON && mLastCameraMode == CAMERA_MODE_THIRD_PERSON); }
+ BOOL cameraMouselook() const { return (mCameraMode == CAMERA_MODE_MOUSELOOK && mLastCameraMode == CAMERA_MODE_MOUSELOOK); }
+ BOOL cameraCustomizeAvatar() const { return (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR /*&& !mCameraAnimating*/); }
+ BOOL cameraFollow() const { return (mCameraMode == CAMERA_MODE_FOLLOW && mLastCameraMode == CAMERA_MODE_FOLLOW); }
+ ECameraMode getCameraMode() const { return mCameraMode; }
+ void updateCamera(); // Call once per frame to update camera location/orientation
+ void resetCamera(); // Slam camera into its default position
+private:
+ ECameraMode mCameraMode; // Target mode after transition animation is done
+ ECameraMode mLastCameraMode;
- LLWearable* getWearable( EWearableType type ) { return (type < WT_COUNT) ? mWearableEntry[ type ].mWearable : NULL; }
- BOOL isWearingItem( const LLUUID& item_id );
- LLWearable* getWearableFromWearableItem( const LLUUID& item_id );
- const LLUUID& getWearableItem( EWearableType type ) { return (type < WT_COUNT) ? mWearableEntry[ type ].mItemID : LLUUID::null; }
+ //--------------------------------------------------------------------
+ // Preset
+ //--------------------------------------------------------------------
+public:
+ void switchCameraPreset(ECameraPreset preset);
- static EWearableType getTEWearableType( S32 te );
- static LLUUID getDefaultTEImageID( S32 te );
-
- void copyWearableToInventory( EWearableType type );
-
- void makeNewOutfit(
- const std::string& new_folder_name,
- const LLDynamicArray<S32>& wearables_to_include,
- const LLDynamicArray<S32>& attachments_to_include,
- BOOL rename_clothing);
- void makeNewOutfitDone(S32 index);
-
- void removeWearable( EWearableType type );
- static bool onRemoveWearableDialog(const LLSD& notification, const LLSD& response );
- void removeWearableFinal( EWearableType type );
-
- void sendAgentWearablesUpdate();
-
- /**
- * @brief Only public because of addWearableToAgentInventoryCallback.
- *
- * NOTE: Do not call this method unless you are the inventory callback.
- * NOTE: This can suffer from race conditions when working on the
- * same values for index.
- * @param index The index in mWearableEntry.
- * @param item_id The inventory item id of the new wearable to wear.
- * @param wearable The actual wearable data.
- */
- void addWearabletoAgentInventoryDone(
- S32 index,
- const LLUUID& item_id,
- LLWearable* wearable);
-
- void saveWearableAs( EWearableType type, const std::string& new_name, BOOL save_in_lost_and_found );
- void saveWearable( EWearableType type, BOOL send_update = TRUE );
- void saveAllWearables();
+private:
- void revertWearable( EWearableType type );
- void revertAllWearables();
+ /** Determines default camera offset depending on the current camera preset */
+ LLVector3 getCameraOffsetInitial();
- void setWearableName( const LLUUID& item_id, const std::string& new_name );
- void createStandardWearables(BOOL female);
- void createStandardWearablesDone(S32 index);
- void createStandardWearablesAllDone();
+ /** Camera preset in Third Person Mode */
+ ECameraPreset mCameraPreset;
- BOOL areWearablesLoaded() { return mWearablesLoaded; }
+ /** Initial camera offsets */
+ std::map<ECameraPreset, LLVector3> mCameraOffsetInitial;
- void sendWalkRun(bool running);
-
- void observeFriends();
- void friendsChanged();
-
- // statics
- static void stopFidget();
- static void processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data);
- static void userRemoveWearable( void* userdata ); // userdata is EWearableType
- static void userRemoveAllClothes( void* userdata ); // userdata is NULL
- static void userRemoveAllClothesStep2(BOOL proceed, void* userdata ); // userdata is NULL
- static void userRemoveAllAttachments( void* userdata); // userdata is NULL
- static BOOL selfHasWearable( void* userdata ); // userdata is EWearableType
-
- //debug methods
- static void clearVisualParams(void *);
+ /** Initial focus offsets */
+ std::map<ECameraPreset, LLVector3d> mFocusOffsetInitial;
-protected:
- // stuff to do for any sort of teleport. Returns true if the
- // teleport can proceed.
- bool teleportCore(bool is_local = false);
- // helper function to prematurely age chat when agent is moving
- void ageChat();
+ //--------------------------------------------------------------------
+ // Position
+ //--------------------------------------------------------------------
+public:
+ LLVector3d getCameraPositionGlobal() const;
+ const LLVector3 &getCameraPositionAgent() const;
+ LLVector3d calcCameraPositionTargetGlobal(BOOL *hit_limit = NULL); // Calculate the camera position target
+ F32 getCameraMinOffGround(); // Minimum height off ground for this mode, meters
+ void setCameraCollidePlane(const LLVector4 &plane) { mCameraCollidePlane = plane; }
+ BOOL calcCameraMinDistance(F32 &obj_min_distance);
+ F32 calcCustomizeAvatarUIOffset(const LLVector3d& camera_pos_global);
+ F32 getCurrentCameraBuildOffset() { return (F32)mCameraFocusOffset.length(); }
+private:
+ F32 mCurrentCameraDistance; // Current camera offset from avatar
+ F32 mTargetCameraDistance; // Target camera offset from avatar
+ F32 mCameraFOVZoomFactor; // Amount of fov zoom applied to camera when zeroing in on an object
+ F32 mCameraCurrentFOVZoomFactor; // Interpolated fov zoom
+ F32 mCameraFOVDefault; // Default field of view that is basis for FOV zoom effect
+ LLVector4 mCameraCollidePlane; // Colliding plane for camera
+ F32 mCameraZoomFraction; // Mousewheel driven fraction of zoom
+ LLVector3 mCameraPositionAgent; // Camera position in agent coordinates
+ LLVector3 mCameraVirtualPositionAgent; // Camera virtual position (target) before performing FOV zoom
+ LLVector3d mCameraSmoothingLastPositionGlobal;
+ LLVector3d mCameraSmoothingLastPositionAgent;
+ BOOL mCameraSmoothingStop;
+ LLVector3 mCameraLag; // Third person camera lag
+ LLVector3 mCameraUpVector; // Camera's up direction in world coordinates (determines the 'roll' of the view)
- // internal wearable functions
- void sendAgentWearablesRequest();
- static void onInitialWearableAssetArrived(LLWearable* wearable, void* userdata);
- void recoverMissingWearable(EWearableType type);
- void recoverMissingWearableDone();
- void addWearableToAgentInventory(LLPointer<LLInventoryCallback> cb,
- LLWearable* wearable, const LLUUID& category_id = LLUUID::null,
- BOOL notify = TRUE);
+ //--------------------------------------------------------------------
+ // Follow
+ //--------------------------------------------------------------------
public:
- // TODO: Make these private!
- LLUUID mSecureSessionID; // secure token for this login session
+ void setUsingFollowCam(bool using_follow_cam);
+private:
+ LLFollowCam mFollowCam; // Ventrella
- F32 mDrawDistance;
+ //--------------------------------------------------------------------
+ // Sit
+ //--------------------------------------------------------------------
+public:
+ void setupSitCamera();
+ BOOL sitCameraEnabled() { return mSitCameraEnabled; }
+ void setSitCamera(const LLUUID &object_id,
+ const LLVector3 &camera_pos = LLVector3::zero, const LLVector3 &camera_focus = LLVector3::zero);
+private:
+ LLPointer<LLViewerObject> mSitCameraReferenceObject; // Object to which camera is related when sitting
+ BOOL mSitCameraEnabled; // Use provided camera information when sitting?
+ LLVector3 mSitCameraPos; // Root relative camera pos when sitting
+ LLVector3 mSitCameraFocus; // Root relative camera target when sitting
- U64 mGroupPowers;
- BOOL mHideGroupTitle;
- std::string mGroupTitle; // honorific, like "Sir"
- std::string mGroupName;
- LLUUID mGroupID;
- //LLUUID mGroupInsigniaID;
- LLUUID mInventoryRootID;
- LLUUID mMapID;
- F64 mMapOriginX; // Global x coord of mMapID's bottom left corner.
- F64 mMapOriginY; // Global y coord of mMapID's bottom left corner.
- S32 mMapWidth; // Width of map in meters
- S32 mMapHeight; // Height of map in meters
- std::string mMOTD; // message of the day
+ //--------------------------------------------------------------------
+ // Animation
+ //--------------------------------------------------------------------
+public:
+ void setCameraAnimating(BOOL b) { mCameraAnimating = b; }
+ BOOL getCameraAnimating() { return mCameraAnimating; }
+ void setAnimationDuration(F32 seconds) { mAnimationDuration = seconds; }
+ void startCameraAnimation();
+ void stopCameraAnimation();
+private:
+ BOOL mCameraAnimating; // Camera is transitioning from one mode to another
+ LLVector3d mAnimationCameraStartGlobal; // Camera start position, global coords
+ LLVector3d mAnimationFocusStartGlobal; // Camera focus point, global coords
+ //--------------------------------------------------------------------
+ // Focus
+ //--------------------------------------------------------------------
+public:
+ LLVector3d calcFocusPositionTargetGlobal();
+ LLVector3 calcFocusOffset(LLViewerObject *object, LLVector3 pos_agent, S32 x, S32 y);
+ BOOL getFocusOnAvatar() const { return mFocusOnAvatar; }
+ LLPointer<LLViewerObject>& getFocusObject() { return mFocusObject; }
+ F32 getFocusObjectDist() const { return mFocusObjectDist; }
+ void updateFocusOffset();
+ void validateFocusObject();
+ void setFocusGlobal(const LLPickInfo& pick);
+ void setFocusGlobal(const LLVector3d &focus, const LLUUID &object_id = LLUUID::null);
+ void setFocusOnAvatar(BOOL focus, BOOL animate);
+ void setCameraPosAndFocusGlobal(const LLVector3d& pos, const LLVector3d& focus, const LLUUID &object_id);
+ void clearFocusObject();
+ void setFocusObject(LLViewerObject* object);
+ void setObjectTracking(BOOL track) { mTrackFocusObject = track; }
+ const LLVector3d &getFocusGlobal() const { return mFocusGlobal; }
+ const LLVector3d &getFocusTargetGlobal() const { return mFocusTargetGlobal; }
+private:
+ LLVector3d mCameraFocusOffset; // Offset from focus point in build mode
+ LLVector3d mCameraFocusOffsetTarget; // Target towards which we are lerping the camera's focus offset
+ BOOL mFocusOnAvatar;
+ LLVector3d mFocusGlobal;
+ LLVector3d mFocusTargetGlobal;
+ LLPointer<LLViewerObject> mFocusObject;
+ F32 mFocusObjectDist;
+ LLVector3 mFocusObjectOffset;
+ F32 mFocusDotRadius; // Meters
+ BOOL mTrackFocusObject;
+ F32 mUIOffset;
+
+ //--------------------------------------------------------------------
+ // Lookat / Pointat
+ //--------------------------------------------------------------------
+public:
+ void updateLookAt(const S32 mouse_x, const S32 mouse_y);
+ BOOL setLookAt(ELookAtType target_type, LLViewerObject *object = NULL, LLVector3 position = LLVector3::zero);
+ ELookAtType getLookAtType();
+ void slamLookAt(const LLVector3 &look_at); // Set the physics data
+ BOOL setPointAt(EPointAtType target_type, LLViewerObject *object = NULL, LLVector3 position = LLVector3::zero);
+ EPointAtType getPointAtType();
+public:
LLPointer<LLHUDEffectLookAt> mLookAt;
LLPointer<LLHUDEffectPointAt> mPointAt;
- LLDynamicArray<LLGroupData> mGroups;
+ //--------------------------------------------------------------------
+ // Third person
+ //--------------------------------------------------------------------
+public:
+ LLVector3d calcThirdPersonFocusOffset();
+ void setThirdPersonHeadOffset(LLVector3 offset) { mThirdPersonHeadOffset = offset; }
+private:
+ LLVector3 mThirdPersonHeadOffset; // Head offset for third person camera position
- F32 mHUDTargetZoom; // target zoom level for HUD objects (used when editing)
- F32 mHUDCurZoom; // current animated zoom level for HUD objects
+ //--------------------------------------------------------------------
+ // Orbit
+ //--------------------------------------------------------------------
+public:
+ void cameraOrbitAround(const F32 radians); // Rotate camera CCW radians about build focus point
+ void cameraOrbitOver(const F32 radians); // Rotate camera forward radians over build focus point
+ void cameraOrbitIn(const F32 meters); // Move camera in toward build focus point
- BOOL mInitialized;
+ //--------------------------------------------------------------------
+ // Zoom
+ //--------------------------------------------------------------------
+public:
+ void handleScrollWheel(S32 clicks); // Mousewheel driven zoom
+ void cameraZoomIn(const F32 factor); // Zoom in by fraction of current distance
+ F32 getCameraZoomFraction(); // Get camera zoom as fraction of minimum and maximum zoom
+ void setCameraZoomFraction(F32 fraction); // Set camera zoom as fraction of minimum and maximum zoom
+ F32 calcCameraFOVZoomFactor();
- S32 mNumPendingQueries;
- S32* mActiveCacheQueries;
+ //--------------------------------------------------------------------
+ // Pan
+ //--------------------------------------------------------------------
+public:
+ void cameraPanIn(const F32 meters);
+ void cameraPanLeft(const F32 meters);
+ void cameraPanUp(const F32 meters);
+
+ //--------------------------------------------------------------------
+ // View
+ //--------------------------------------------------------------------
+public:
+ // Called whenever the agent moves. Puts camera back in default position, deselects items, etc.
+ void resetView(BOOL reset_camera = TRUE, BOOL change_camera = FALSE);
+ // Called on camera movement. Unlocks camera from the default position behind the avatar.
+ void unlockView();
+ //--------------------------------------------------------------------
+ // Mouselook
+ //--------------------------------------------------------------------
+public:
+ BOOL getForceMouselook() const { return mForceMouselook; }
+ void setForceMouselook(BOOL mouselook) { mForceMouselook = mouselook; }
+private:
BOOL mForceMouselook;
+
+ //--------------------------------------------------------------------
+ // HUD
+ //--------------------------------------------------------------------
+public:
+ const LLColor4 &getEffectColor();
+ void setEffectColor(const LLColor4 &color);
+public:
+ F32 mHUDTargetZoom; // Target zoom level for HUD objects (used when editing)
+ F32 mHUDCurZoom; // Current animated zoom level for HUD objects
+private:
+ LLUIColor mEffectColor;
- static void parseTeleportMessages(const std::string& xml_filename);
- //we should really define ERROR and PROGRESS enums here
- //but I don't really feel like doing that, so I am just going
- //to expose the mappings....yup
- static std::map<std::string, std::string> sTeleportErrorMessages;
- static std::map<std::string, std::string> sTeleportProgressMessages;
+/** Camera
+ ** **
+ *******************************************************************************/
- LLFrameTimer mDoubleTapRunTimer;
- EDoubleTapRunMode mDoubleTapRunMode;
+/********************************************************************************
+ ** **
+ ** ACCESS
+ **/
+public:
+ // Checks if agent can modify an object based on the permissions and the agent's proxy status.
+ BOOL isGrantedProxy(const LLPermissions& perm);
+ BOOL allowOperation(PermissionBit op,
+ const LLPermissions& perm,
+ U64 group_proxy_power = 0,
+ U8 god_minimum = GOD_MAINTENANCE);
+ const LLAgentAccess& getAgentAccess();
+ BOOL canManageEstate() const;
+ BOOL getAdminOverride() const;
+ // ! BACKWARDS COMPATIBILITY ! This function can go away after the AO transition (see llstartup.cpp).
+ void setAOTransition();
private:
- bool mbAlwaysRun; // should the avatar run by default rather than walk
- bool mbRunning; // is the avatar trying to run right now
-
- LLAgentAccess mAgentAccess;
+ LLAgentAccess mAgentAccess;
- ETeleportState mTeleportState;
- std::string mTeleportMessage;
-
- S32 mControlsTakenCount[TOTAL_CONTROLS];
- S32 mControlsTakenPassedOnCount[TOTAL_CONTROLS];
-
- LLViewerRegion *mRegionp;
- LLVector3d mAgentOriginGlobal; // Origin of agent coords from global coords
- mutable LLVector3d mPositionGlobal;
+ //--------------------------------------------------------------------
+ // God
+ //--------------------------------------------------------------------
+public:
+ BOOL isGodlike() const;
+ U8 getGodLevel() const;
+ void setAdminOverride(BOOL b);
+ void setGodLevel(U8 god_level);
+ void requestEnterGodMode();
+ void requestLeaveGodMode();
- std::string mTeleportSourceSLURL; // SLURL where last TP began.
+ //--------------------------------------------------------------------
+ // Maturity
+ //--------------------------------------------------------------------
+public:
+ // Note: this is a prime candidate for pulling out into a Maturity class.
+ // Rather than just expose the preference setting, we're going to actually
+ // expose what the client code cares about -- what the user should see
+ // based on a combination of the is* and prefers* flags, combined with god bit.
+ bool wantsPGOnly() const;
+ bool canAccessMature() const;
+ bool canAccessAdult() const;
+ bool canAccessMaturityInRegion( U64 region_handle ) const;
+ bool canAccessMaturityAtGlobal( LLVector3d pos_global ) const;
+ bool prefersPG() const;
+ bool prefersMature() const;
+ bool prefersAdult() const;
+ bool isTeen() const;
+ bool isMature() const;
+ bool isAdult() const;
+ void setTeen(bool teen);
+ void setMaturity(char text);
+ static int convertTextToMaturity(char text);
+ bool sendMaturityPreferenceToServer(int preferredMaturity); // ! "U8" instead of "int"?
+
+ // Maturity callbacks for PreferredMaturity control variable
+ void handleMaturity(const LLSD& newvalue);
+ bool validateMaturity(const LLSD& newvalue);
+
+
+/** Access
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** RENDERING
+ **/
- std::set<U64> mRegionsVisited; // stat - what distinct regions has the avatar been to?
- F64 mDistanceTraveled; // stat - how far has the avatar moved?
- LLVector3d mLastPositionGlobal; // Used to calculate travel distance
+public:
+ LLQuaternion getHeadRotation();
+ BOOL needsRenderAvatar(); // TRUE when camera mode is such that your own avatar should draw
+ BOOL needsRenderHead();
+public:
+ F32 mDrawDistance;
+private:
+ BOOL mShowAvatar; // Should we render the avatar?
+ U32 mAppearanceSerialNum;
+
+ //--------------------------------------------------------------------
+ // Rendering state bitmap helpers
+ //--------------------------------------------------------------------
+public:
+ void setRenderState(U8 newstate);
+ void clearRenderState(U8 clearstate);
+ U8 getRenderState();
+private:
+ U8 mRenderState; // Current behavior state of agent
- LLPointer<LLVOAvatar> mAvatarObject; // NULL until avatar object sent down from simulator
+/** Rendering
+ ** **
+ *******************************************************************************/
- U8 mRenderState; // Current behavior state of agent
- LLFrameTimer mTypingTimer;
+/********************************************************************************
+ ** **
+ ** GROUPS
+ **/
- ECameraMode mCameraMode; // target mode after transition animation is done
- ECameraMode mLastCameraMode;
- BOOL mViewsPushed; // keep track of whether or not we have pushed views.
-
- BOOL mCustomAnim ; //current animation is ANIM_AGENT_CUSTOMIZE ?
- BOOL mShowAvatar; // should we render the avatar?
- BOOL mCameraAnimating; // camera is transitioning from one mode to another
- LLVector3d mAnimationCameraStartGlobal; // camera start position, global coords
- LLVector3d mAnimationFocusStartGlobal; // camera focus point, global coords
- LLFrameTimer mAnimationTimer; // seconds that transition animation has been active
- F32 mAnimationDuration; // seconds
- F32 mCameraFOVZoomFactor; // amount of fov zoom applied to camera when zeroing in on an object
- F32 mCameraCurrentFOVZoomFactor; // interpolated fov zoom
- F32 mCameraFOVDefault; // default field of view that is basis for FOV zoom effect
- LLVector3d mCameraFocusOffset; // offset from focus point in build mode
- LLVector3d mCameraFocusOffsetTarget; // target towards which we are lerping the camera's focus offset
- LLVector3 mCameraOffsetDefault; // default third-person camera offset
- LLVector4 mCameraCollidePlane; // colliding plane for camera
- F32 mCurrentCameraDistance; // current camera offset from avatar
- F32 mTargetCameraDistance; // target camera offset from avatar
- F32 mCameraZoomFraction; // mousewheel driven fraction of zoom
- LLVector3 mCameraLag; // third person camera lag
- LLVector3 mThirdPersonHeadOffset; // head offset for third person camera position
- LLVector3 mCameraPositionAgent; // camera position in agent coordinates
- LLVector3 mCameraVirtualPositionAgent; // camera virtual position (target) before performing FOV zoom
- BOOL mSitCameraEnabled; // use provided camera information when sitting?
- LLVector3 mSitCameraPos; // root relative camera pos when sitting
- LLVector3 mSitCameraFocus; // root relative camera target when sitting
- LLVector3d mCameraSmoothingLastPositionGlobal;
- LLVector3d mCameraSmoothingLastPositionAgent;
- BOOL mCameraSmoothingStop;
+public:
+ const LLUUID &getGroupID() const { return mGroupID; }
+ // Get group information by group_id, or FALSE if not in group.
+ BOOL getGroupData(const LLUUID& group_id, LLGroupData& data) const;
+ // Get just the agent's contribution to the given group.
+ S32 getGroupContribution(const LLUUID& group_id) const;
+ // Update internal datastructures and update the server.
+ BOOL setGroupContribution(const LLUUID& group_id, S32 contribution);
+ BOOL setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOOL list_in_profile);
+ const std::string &getGroupName() const { return mGroupName; }
+ BOOL canJoinGroups() const;
+private:
+ std::string mGroupName;
+ LLUUID mGroupID;
- LLVector3 mCameraUpVector; // camera's up direction in world coordinates (determines the 'roll' of the view)
+ //--------------------------------------------------------------------
+ // Group Membership
+ //--------------------------------------------------------------------
+public:
+ // Checks against all groups in the entire agent group list.
+ BOOL isInGroup(const LLUUID& group_id) const;
+protected:
+ // Only used for building titles.
+ BOOL isGroupMember() const { return !mGroupID.isNull(); }
+public:
+ LLDynamicArray<LLGroupData> mGroups;
- LLPointer<LLViewerObject> mSitCameraReferenceObject; // object to which camera is related when sitting
+ //--------------------------------------------------------------------
+ // Group Title
+ //--------------------------------------------------------------------
+public:
+ void setHideGroupTitle(BOOL hide) { mHideGroupTitle = hide; }
+ BOOL isGroupTitleHidden() const { return mHideGroupTitle; }
+private:
+ std::string mGroupTitle; // Honorific, like "Sir"
+ BOOL mHideGroupTitle;
- BOOL mFocusOnAvatar;
- LLVector3d mFocusGlobal;
- LLVector3d mFocusTargetGlobal;
- LLPointer<LLViewerObject> mFocusObject;
- F32 mFocusObjectDist;
- LLVector3 mFocusObjectOffset;
- F32 mFocusDotRadius; // meters
- BOOL mTrackFocusObject;
- F32 mUIOffset;
+ //--------------------------------------------------------------------
+ // Group Powers
+ //--------------------------------------------------------------------
+public:
+ BOOL hasPowerInGroup(const LLUUID& group_id, U64 power) const;
+ BOOL hasPowerInActiveGroup(const U64 power) const;
+ U64 getPowerInGroup(const LLUUID& group_id) const;
+ U64 mGroupPowers;
- LLCoordFrame mFrameAgent; // Agent position and view, agent-region coordinates
+ //--------------------------------------------------------------------
+ // Friends
+ //--------------------------------------------------------------------
+public:
+ void observeFriends();
+ void friendsChanged();
+private:
+ LLFriendObserver* mFriendObserver;
+ std::set<LLUUID> mProxyForAgents;
- BOOL mIsBusy;
+/** Groups
+ ** **
+ *******************************************************************************/
- S32 mAtKey; // Either 1, 0, or -1... indicates that movement-key is pressed
- S32 mWalkKey; // like AtKey, but causes less forward thrust
- S32 mLeftKey;
- S32 mUpKey;
- F32 mYawKey;
- S32 mPitchKey;
+/********************************************************************************
+ ** **
+ ** MESSAGING
+ **/
- F32 mOrbitLeftKey;
- F32 mOrbitRightKey;
- F32 mOrbitUpKey;
- F32 mOrbitDownKey;
- F32 mOrbitInKey;
- F32 mOrbitOutKey;
+ //--------------------------------------------------------------------
+ // Send
+ //--------------------------------------------------------------------
+public:
+ void sendMessage(); // Send message to this agent's region
+ void sendReliableMessage();
+ void sendAgentSetAppearance();
+ void sendAgentDataUpdateRequest();
+ void sendAgentUserInfoRequest();
+ // IM to Email and Online visibility
+ void sendAgentUpdateUserInfo(bool im_to_email, const std::string& directory_visibility);
- F32 mPanUpKey;
- F32 mPanDownKey;
- F32 mPanLeftKey;
- F32 mPanRightKey;
- F32 mPanInKey;
- F32 mPanOutKey;
+ //--------------------------------------------------------------------
+ // Receive
+ //--------------------------------------------------------------------
+public:
+ static void processAgentDataUpdate(LLMessageSystem *msg, void **);
+ static void processAgentGroupDataUpdate(LLMessageSystem *msg, void **);
+ static void processAgentDropGroup(LLMessageSystem *msg, void **);
+ static void processScriptControlChange(LLMessageSystem *msg, void **);
+ static void processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void **user_data);
+
+/** Messaging
+ ** **
+ *******************************************************************************/
- U32 mControlFlags; // replacement for the mFooKey's
- BOOL mbFlagsDirty;
- BOOL mbFlagsNeedReset; // HACK for preventing incorrect flags sent when crossing region boundaries
+/********************************************************************************
+ ** **
+ ** DEBUGGING
+ **/
- BOOL mbJump;
+public:
+ static void dumpGroupInfo();
+ static void clearVisualParams(void *);
+ friend std::ostream& operator<<(std::ostream &s, const LLAgent &sphere);
- BOOL mAutoPilot;
- BOOL mAutoPilotFlyOnStop;
- LLVector3d mAutoPilotTargetGlobal;
- F32 mAutoPilotStopDistance;
- BOOL mAutoPilotUseRotation;
- LLVector3 mAutoPilotTargetFacing;
- F32 mAutoPilotTargetDist;
- S32 mAutoPilotNoProgressFrameCount;
- F32 mAutoPilotRotationThreshold;
- std::string mAutoPilotBehaviorName;
- void (*mAutoPilotFinishedCallback)(BOOL, void *);
- void* mAutoPilotCallbackData;
- LLUUID mLeaderID;
+/** Debugging
+ ** **
+ *******************************************************************************/
- std::set<LLUUID> mProxyForAgents;
+};
- LLColor4 mEffectColor;
+extern LLAgent gAgent;
- BOOL mHaveHomePosition;
- U64 mHomeRegionHandle;
- LLVector3 mHomePosRegion;
- LLFrameTimer mChatTimer;
- LLUUID mLastChatterID;
- F32 mNearChatRadius;
+inline bool operator==(const LLGroupData &a, const LLGroupData &b)
+{
+ return (a.mID == b.mID);
+}
- LLFrameTimer mFidgetTimer;
- LLFrameTimer mFocusObjectFadeTimer;
- F32 mNextFidgetTime;
- S32 mCurrentFidget;
- BOOL mFirstLogin;
- BOOL mGenderChosen;
+class LLAgentQueryManager
+{
+ friend class LLAgent;
+ friend class LLAgentWearables;
- //--------------------------------------------------------------------
- // Wearables
- //--------------------------------------------------------------------
- struct LLWearableEntry
- {
- LLWearableEntry() : mItemID( LLUUID::null ), mWearable( NULL ) {}
-
- LLUUID mItemID; // ID of the inventory item in the agent's inventory.
- LLWearable* mWearable;
- };
- LLWearableEntry mWearableEntry[ WT_COUNT ];
- U32 mAgentWearablesUpdateSerialNum;
- BOOL mWearablesLoaded;
- S32 mTextureCacheQueryID;
- U32 mAppearanceSerialNum;
- LLAnimPauseRequest mPauseRequest;
-
- class createStandardWearablesAllDoneCallback : public LLRefCount
- {
- protected:
- ~createStandardWearablesAllDoneCallback();
- };
- class sendAgentWearablesUpdateCallback : public LLRefCount
- {
- protected:
- ~sendAgentWearablesUpdateCallback();
- };
-
- class addWearableToAgentInventoryCallback : public LLInventoryCallback
- {
- public:
- enum {
- CALL_NONE = 0,
- CALL_UPDATE = 1,
- CALL_RECOVERDONE = 2,
- CALL_CREATESTANDARDDONE = 4,
- CALL_MAKENEWOUTFITDONE = 8
- } EType;
-
- /**
- * @brief Construct a callback for dealing with the wearables.
- *
- * Would like to pass the agent in here, but we can't safely
- * count on it being around later. Just use gAgent directly.
- * @param cb callback to execute on completion (??? unused ???)
- * @param index Index for the wearable in the agent
- * @param wearable The wearable data.
- * @param todo Bitmask of actions to take on completion.
- */
- addWearableToAgentInventoryCallback(
- LLPointer<LLRefCount> cb,
- S32 index,
- LLWearable* wearable,
- U32 todo = CALL_NONE);
- virtual void fire(const LLUUID& inv_item);
-
- private:
- S32 mIndex;
- LLWearable* mWearable;
- U32 mTodo;
- LLPointer<LLRefCount> mCB;
- };
-
- LLFriendObserver* mFriendObserver;
+public:
+ LLAgentQueryManager();
+ virtual ~LLAgentQueryManager();
+
+ BOOL hasNoPendingQueries() const { return getNumPendingQueries() == 0; }
+ S32 getNumPendingQueries() const { return mNumPendingQueries; }
+private:
+ S32 mNumPendingQueries;
+ S32 mWearablesCacheQueryID;
+ U32 mUpdateSerialNum;
+ S32 mActiveCacheQueries[LLVOAvatarDefines::BAKED_NUM_INDICES];
};
-extern LLAgent gAgent;
+extern LLAgentQueryManager gAgentQueryManager;
#endif
diff --git a/indra/newview/llagentaccess.cpp b/indra/newview/llagentaccess.cpp
index a4fbc04855..eb978eb6c1 100644
--- a/indra/newview/llagentaccess.cpp
+++ b/indra/newview/llagentaccess.cpp
@@ -3,16 +3,39 @@
* @brief LLAgentAccess class implementation - manages maturity and godmode info
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
* Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llagentaccess.h"
#include "indra_constants.h"
-#include "llcontrolgroupreader.h"
+#include "llcontrol.h"
-LLAgentAccess::LLAgentAccess(LLControlGroupReader& savedSettings) :
+LLAgentAccess::LLAgentAccess(LLControlGroup& savedSettings) :
mSavedSettings(savedSettings),
mAccess(SIM_ACCESS_PG),
mAdminOverride(false),
@@ -140,6 +163,20 @@ int LLAgentAccess::convertTextToMaturity(char text)
void LLAgentAccess::setMaturity(char text)
{
mAccess = LLAgentAccess::convertTextToMaturity(text);
+ U32 preferred_access = mSavedSettings.getU32("PreferredMaturity");
+ while (!canSetMaturity(preferred_access))
+ {
+ if (preferred_access == SIM_ACCESS_ADULT)
+ {
+ preferred_access = SIM_ACCESS_MATURE;
+ }
+ else
+ {
+ // Mature or invalid access gets set to PG
+ preferred_access = SIM_ACCESS_PG;
+ }
+ }
+ mSavedSettings.setU32("PreferredMaturity", preferred_access);
}
void LLAgentAccess::setTransition()
@@ -152,3 +189,14 @@ bool LLAgentAccess::isInTransition() const
return mAOTransition;
}
+bool LLAgentAccess::canSetMaturity(S32 maturity)
+{
+ if (isGodlike()) // Gods can always set their Maturity level
+ return true;
+ if (isAdult()) // Adults can always set their Maturity level
+ return true;
+ if (maturity == SIM_ACCESS_PG || (maturity == SIM_ACCESS_MATURE && isMature()))
+ return true;
+ else
+ return false;
+}
diff --git a/indra/newview/llagentaccess.h b/indra/newview/llagentaccess.h
index dec0d76cc9..93d2f0a371 100644
--- a/indra/newview/llagentaccess.h
+++ b/indra/newview/llagentaccess.h
@@ -3,7 +3,30 @@
* @brief LLAgentAccess class implementation - manages maturity and godmode info
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
* Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
@@ -13,12 +36,12 @@
#include "stdtypes.h"
// forward declaration so that we don't have to include the whole class
-class LLControlGroupReader;
+class LLControlGroup;
class LLAgentAccess
{
public:
- LLAgentAccess(LLControlGroupReader& savedSettings);
+ LLAgentAccess(LLControlGroup& savedSettings);
bool getAdminOverride() const;
void setAdminOverride(bool b);
@@ -48,6 +71,7 @@ public:
void setTransition(); // sets the transition bit, which defaults to false
bool isInTransition() const;
+ bool canSetMaturity(S32 maturity);
private:
U8 mAccess; // SIM_ACCESS_MATURE etc
@@ -61,9 +85,7 @@ private:
// all of the code that depends on it.
bool mAOTransition;
- // we want this to be const but the getters for it aren't, so we're
- // overriding it for now
- /* const */ LLControlGroupReader& mSavedSettings;
+ LLControlGroup& mSavedSettings;
};
#endif // LL_LLAGENTACCESS_H
diff --git a/indra/newview/llagentlanguage.h b/indra/newview/llagentlanguage.h
index 6bc7250c6e..45348a1e50 100644
--- a/indra/newview/llagentlanguage.h
+++ b/indra/newview/llagentlanguage.h
@@ -33,10 +33,10 @@
#ifndef LL_LLAGENTLANGUAGE_H
#define LL_LLAGENTLANGUAGE_H
-#include "llmemory.h" // LLSingleton<>
+#include "llsingleton.h" // LLSingleton<>
#include "llevent.h"
-class LLAgentLanguage: public LLSingleton<LLAgentLanguage>, public LLSimpleListener
+class LLAgentLanguage: public LLSingleton<LLAgentLanguage>, public LLOldEvents::LLSimpleListener
{
public:
LLAgentLanguage();
diff --git a/indra/newview/llagentlistener.cpp b/indra/newview/llagentlistener.cpp
new file mode 100644
index 0000000000..b3ed7c353e
--- /dev/null
+++ b/indra/newview/llagentlistener.cpp
@@ -0,0 +1,86 @@
+/**
+ * @file llagentlistener.cpp
+ * @author Brad Kittenbrink
+ * @date 2009-07-10
+ * @brief Implementation for llagentlistener.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llagentlistener.h"
+
+#include "llagent.h"
+#include "llcommandhandler.h"
+#include "llslurl.h"
+#include "llurldispatcher.h"
+#include "llviewerobject.h"
+#include "llviewerobjectlist.h"
+#include "llviewerregion.h"
+
+LLAgentListener::LLAgentListener(LLAgent &agent)
+ : LLEventAPI("LLAgent",
+ "LLAgent listener to (e.g.) teleport, sit, stand, etc."),
+ mAgent(agent)
+{
+ add("requestTeleport",
+ "Teleport: [\"regionname\"], [\"x\"], [\"y\"], [\"z\"]\n"
+ "If [\"skip_confirmation\"] is true, use LLURLDispatcher rather than LLCommandDispatcher.",
+ &LLAgentListener::requestTeleport);
+ add("requestSit",
+ "Ask to sit on the object specified in [\"obj_uuid\"]",
+ &LLAgentListener::requestSit);
+ add("requestStand",
+ "Ask to stand up",
+ &LLAgentListener::requestStand);
+}
+
+void LLAgentListener::requestTeleport(LLSD const & event_data) const
+{
+ if(event_data["skip_confirmation"].asBoolean())
+ {
+ LLSD params(LLSD::emptyArray());
+ params.append(event_data["regionname"]);
+ params.append(event_data["x"]);
+ params.append(event_data["y"]);
+ params.append(event_data["z"]);
+ LLCommandDispatcher::dispatch("teleport", params, LLSD(), NULL, true);
+ // *TODO - lookup other LLCommandHandlers for "agent", "classified", "event", "group", "floater", "parcel", "login", login_refresh", "balance", "chat"
+ // should we just compose LLCommandHandler and LLDispatchListener?
+ }
+ else
+ {
+ std::string url = LLSLURL::buildSLURL(event_data["regionname"], event_data["x"], event_data["y"], event_data["z"]);
+ LLURLDispatcher::dispatch(url, NULL, false);
+ }
+}
+
+void LLAgentListener::requestSit(LLSD const & event_data) const
+{
+ //mAgent.getAvatarObject()->sitOnObject();
+ // shamelessly ripped from llviewermenu.cpp:handle_sit_or_stand()
+ // *TODO - find a permanent place to share this code properly.
+ LLViewerObject *object = gObjectList.findObject(event_data["obj_uuid"]);
+
+ if (object && object->getPCode() == LL_PCODE_VOLUME)
+ {
+ gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit);
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, mAgent.getID());
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, mAgent.getSessionID());
+ gMessageSystem->nextBlockFast(_PREHASH_TargetObject);
+ gMessageSystem->addUUIDFast(_PREHASH_TargetID, object->mID);
+ gMessageSystem->addVector3Fast(_PREHASH_Offset, LLVector3(0,0,0));
+
+ object->getRegion()->sendReliableMessage();
+ }
+}
+
+void LLAgentListener::requestStand(LLSD const & event_data) const
+{
+ mAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
+}
+
diff --git a/indra/newview/llagentlistener.h b/indra/newview/llagentlistener.h
new file mode 100644
index 0000000000..eed6922b3e
--- /dev/null
+++ b/indra/newview/llagentlistener.h
@@ -0,0 +1,36 @@
+/**
+ * @file llagentlistener.h
+ * @author Brad Kittenbrink
+ * @date 2009-07-09
+ * @brief Event API for subset of LLViewerControl methods
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+
+#ifndef LL_LLAGENTLISTENER_H
+#define LL_LLAGENTLISTENER_H
+
+#include "lleventapi.h"
+
+class LLAgent;
+class LLSD;
+
+class LLAgentListener : public LLEventAPI
+{
+public:
+ LLAgentListener(LLAgent &agent);
+
+private:
+ void requestTeleport(LLSD const & event_data) const;
+ void requestSit(LLSD const & event_data) const;
+ void requestStand(LLSD const & event_data) const;
+
+private:
+ LLAgent & mAgent;
+};
+
+#endif // LL_LLAGENTLISTENER_H
+
diff --git a/indra/newview/llagentpicksinfo.cpp b/indra/newview/llagentpicksinfo.cpp
new file mode 100644
index 0000000000..3c8d0dac42
--- /dev/null
+++ b/indra/newview/llagentpicksinfo.cpp
@@ -0,0 +1,131 @@
+/**
+ * @file llagentpicksinfo.cpp
+ * @brief LLAgentPicksInfo class implementation
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llagentpicksinfo.h"
+
+#include "llagent.h"
+#include "llavatarconstants.h"
+#include "llavatarpropertiesprocessor.h"
+
+class LLAgentPicksInfo::LLAgentPicksObserver : public LLAvatarPropertiesObserver
+{
+public:
+ LLAgentPicksObserver()
+ {
+ LLAvatarPropertiesProcessor::getInstance()->addObserver(gAgent.getID(), this);
+ }
+
+ ~LLAgentPicksObserver()
+ {
+ if (LLAvatarPropertiesProcessor::instanceExists())
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(gAgent.getID(), this);
+ }
+
+ void sendAgentPicksRequest()
+ {
+ LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(gAgent.getID());
+ }
+
+ typedef boost::function<void(LLAvatarPicks*)> server_respond_callback_t;
+
+ void setServerRespondCallback(const server_respond_callback_t& cb)
+ {
+ mServerRespondCallback = cb;
+ }
+
+ virtual void processProperties(void* data, EAvatarProcessorType type)
+ {
+ if(APT_PICKS == type)
+ {
+ LLAvatarPicks* picks = static_cast<LLAvatarPicks*>(data);
+ if(picks && gAgent.getID() == picks->target_id)
+ {
+ if(mServerRespondCallback)
+ {
+ mServerRespondCallback(picks);
+ }
+ }
+ }
+ }
+
+private:
+
+ server_respond_callback_t mServerRespondCallback;
+};
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLAgentPicksInfo::LLAgentPicksInfo()
+ : mAgentPicksObserver(NULL)
+ , mMaxNumberOfPicks(MAX_AVATAR_PICKS)
+ // Disable Pick creation until we get number of Picks from server - in case
+ // avatar has maximum number of Picks.
+ , mNumberOfPicks(mMaxNumberOfPicks)
+{
+}
+
+LLAgentPicksInfo::~LLAgentPicksInfo()
+{
+ delete mAgentPicksObserver;
+}
+
+void LLAgentPicksInfo::requestNumberOfPicks()
+{
+ if(!mAgentPicksObserver)
+ {
+ mAgentPicksObserver = new LLAgentPicksObserver();
+
+ mAgentPicksObserver->setServerRespondCallback(boost::bind(
+ &LLAgentPicksInfo::onServerRespond, this, _1));
+ }
+
+ mAgentPicksObserver->sendAgentPicksRequest();
+}
+
+bool LLAgentPicksInfo::isPickLimitReached()
+{
+ return getNumberOfPicks() >= getMaxNumberOfPicks();
+}
+
+void LLAgentPicksInfo::onServerRespond(LLAvatarPicks* picks)
+{
+ if(!picks)
+ {
+ llerrs << "Unexpected value" << llendl;
+ return;
+ }
+
+ setNumberOfPicks(picks->picks_list.size());
+}
diff --git a/indra/newview/llagentpicksinfo.h b/indra/newview/llagentpicksinfo.h
new file mode 100644
index 0000000000..0e30f2c5a0
--- /dev/null
+++ b/indra/newview/llagentpicksinfo.h
@@ -0,0 +1,106 @@
+/**
+ * @file llagentpicksinfo.h
+ * @brief LLAgentPicksInfo class header file
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLAGENTPICKS_H
+#define LL_LLAGENTPICKS_H
+
+#include "llsingleton.h"
+
+struct LLAvatarPicks;
+
+/**
+ * Class that provides information about Agent Picks
+ */
+class LLAgentPicksInfo : public LLSingleton<LLAgentPicksInfo>
+{
+ class LLAgentPicksObserver;
+
+public:
+
+ LLAgentPicksInfo();
+
+ virtual ~LLAgentPicksInfo();
+
+ /**
+ * Requests number of picks from server.
+ *
+ * Number of Picks is requested from server, thus it is not available immediately.
+ */
+ void requestNumberOfPicks();
+
+ /**
+ * Returns number of Picks.
+ */
+ S32 getNumberOfPicks() { return mNumberOfPicks; }
+
+ /**
+ * Returns maximum number of Picks.
+ */
+ S32 getMaxNumberOfPicks() { return mMaxNumberOfPicks; }
+
+ /**
+ * Returns TRUE if Agent has maximum allowed number of Picks.
+ */
+ bool isPickLimitReached();
+
+ /**
+ * After creating or deleting a Pick we can assume operation on server will be
+ * completed successfully. Incrementing/decrementing number of picks makes new number
+ * of picks available immediately. Actual number of picks will be updated when we receive
+ * response from server.
+ */
+ void incrementNumberOfPicks() { ++mNumberOfPicks; }
+
+ void decrementNumberOfPicks() { --mNumberOfPicks; }
+
+private:
+
+ void onServerRespond(LLAvatarPicks* picks);
+
+ /**
+ * Sets number of Picks.
+ */
+ void setNumberOfPicks(S32 number) { mNumberOfPicks = number; }
+
+ /**
+ * Sets maximum number of Picks.
+ */
+ void setMaxNumberOfPicks(S32 max_picks) { mMaxNumberOfPicks = max_picks; }
+
+private:
+
+ LLAgentPicksObserver* mAgentPicksObserver;
+ S32 mMaxNumberOfPicks;
+ S32 mNumberOfPicks;
+};
+
+#endif //LL_LLAGENTPICKS_H
diff --git a/indra/newview/llagentpilot.cpp b/indra/newview/llagentpilot.cpp
index 035c9426a1..8ffb97d8fc 100644
--- a/indra/newview/llagentpilot.cpp
+++ b/indra/newview/llagentpilot.cpp
@@ -38,13 +38,13 @@
#include "llagentpilot.h"
#include "llagent.h"
-#include "llframestats.h"
#include "llappviewer.h"
#include "llviewercontrol.h"
LLAgentPilot gAgentPilot;
BOOL LLAgentPilot::sLoop = TRUE;
+BOOL LLAgentPilot::sReplaySession = FALSE;
LLAgentPilot::LLAgentPilot() :
mNumRuns(-1),
@@ -177,6 +177,11 @@ void LLAgentPilot::stopPlayback()
mTimer.reset();
gAgent.stopAutoPilot();
}
+
+ if (sReplaySession)
+ {
+ LLAppViewer::instance()->forceQuit();
+ }
}
void LLAgentPilot::updateTarget()
@@ -198,7 +203,6 @@ void LLAgentPilot::updateTarget()
{
llinfos << "At start, beginning playback" << llendl;
mTimer.reset();
- LLFrameStats::startLogging(NULL);
mStarted = TRUE;
}
}
@@ -215,7 +219,6 @@ void LLAgentPilot::updateTarget()
else
{
stopPlayback();
- LLFrameStats::stopLogging(NULL);
mNumRuns--;
if (sLoop)
{
diff --git a/indra/newview/llagentpilot.h b/indra/newview/llagentpilot.h
index 0ad4772f68..dc034398a7 100644
--- a/indra/newview/llagentpilot.h
+++ b/indra/newview/llagentpilot.h
@@ -70,6 +70,7 @@ public:
static void startPlayback(void *);
static void stopPlayback(void *);
static BOOL sLoop;
+ static BOOL sReplaySession;
S32 mNumRuns;
BOOL mQuitAfterRuns;
diff --git a/indra/newview/llagentui.cpp b/indra/newview/llagentui.cpp
new file mode 100644
index 0000000000..7404fe5bc4
--- /dev/null
+++ b/indra/newview/llagentui.cpp
@@ -0,0 +1,200 @@
+/**
+ * @file llagentui.cpp
+ * @brief Utility methods to process agent's data as slurl's etc. before displaying
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llagentui.h"
+
+// Library includes
+#include "llparcel.h"
+
+// Viewer includes
+#include "llagent.h"
+#include "llviewercontrol.h"
+#include "llviewerregion.h"
+#include "llviewerparcelmgr.h"
+#include "llvoavatarself.h"
+#include "llslurl.h"
+
+//static
+void LLAgentUI::buildName(std::string& name)
+{
+ name.clear();
+
+ LLVOAvatarSelf* avatar_object = gAgent.getAvatarObject();
+ if (avatar_object)
+ {
+ LLNameValue *first_nv = avatar_object->getNVPair("FirstName");
+ LLNameValue *last_nv = avatar_object->getNVPair("LastName");
+ if (first_nv && last_nv)
+ {
+ name = first_nv->printData() + " " + last_nv->printData();
+ }
+ else
+ {
+ llwarns << "Agent is missing FirstName and/or LastName nv pair." << llendl;
+ }
+ }
+ else
+ {
+ name = gSavedSettings.getString("FirstName") + " " + gSavedSettings.getString("LastName");
+ }
+}
+
+//static
+void LLAgentUI::buildFullname(std::string& name)
+{
+ if (gAgent.getAvatarObject()) name = gAgent.getAvatarObject()->getFullname();
+}
+
+//static
+std::string LLAgentUI::buildSLURL(const bool escaped /*= true*/)
+{
+ std::string slurl;
+ LLViewerRegion *regionp = gAgent.getRegion();
+ if (regionp)
+ {
+ LLVector3d agentPos = gAgent.getPositionGlobal();
+ slurl = LLSLURL::buildSLURLfromPosGlobal(regionp->getName(), agentPos, escaped);
+ }
+ return slurl;
+}
+
+//static
+BOOL LLAgentUI::checkAgentDistance(const LLVector3& pole, F32 radius)
+{
+ F32 delta_x = gAgent.getPositionAgent().mV[VX] - pole.mV[VX];
+ F32 delta_y = gAgent.getPositionAgent().mV[VY] - pole.mV[VY];
+
+ return sqrt( delta_x* delta_x + delta_y* delta_y ) < radius;
+}
+BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt,const LLVector3& agent_pos_region)
+{
+ LLViewerRegion* region = gAgent.getRegion();
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+
+ if (!region || !parcel) return FALSE;
+
+ S32 pos_x = S32(agent_pos_region.mV[VX]);
+ S32 pos_y = S32(agent_pos_region.mV[VY]);
+ S32 pos_z = S32(agent_pos_region.mV[VZ]);
+
+ // Round the numbers based on the velocity
+ F32 velocity_mag_sq = gAgent.getVelocity().magVecSquared();
+
+ const F32 FLY_CUTOFF = 6.f; // meters/sec
+ const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF;
+ const F32 WALK_CUTOFF = 1.5f; // meters/sec
+ const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF;
+
+ if (velocity_mag_sq > FLY_CUTOFF_SQ)
+ {
+ pos_x -= pos_x % 4;
+ pos_y -= pos_y % 4;
+ }
+ else if (velocity_mag_sq > WALK_CUTOFF_SQ)
+ {
+ pos_x -= pos_x % 2;
+ pos_y -= pos_y % 2;
+ }
+
+ // create a default name and description for the landmark
+ std::string parcel_name = LLViewerParcelMgr::getInstance()->getAgentParcelName();
+ std::string region_name = region->getName();
+ std::string sim_access_string = region->getSimAccessString();
+ std::string buffer;
+ if( parcel_name.empty() )
+ {
+ // the parcel doesn't have a name
+ switch (fmt)
+ {
+ case LOCATION_FORMAT_LANDMARK:
+ buffer = llformat("%.100s", region_name.c_str());
+ break;
+ case LOCATION_FORMAT_NORMAL:
+ buffer = llformat("%s", region_name.c_str());
+ break;
+ case LOCATION_FORMAT_NO_COORDS:
+ buffer = llformat("%s%s%s",
+ region_name.c_str(),
+ sim_access_string.empty() ? "" : " - ",
+ sim_access_string.c_str());
+ break;
+ case LOCATION_FORMAT_NO_MATURITY:
+ case LOCATION_FORMAT_FULL:
+ buffer = llformat("%s (%d, %d, %d)",
+ region_name.c_str(),
+ pos_x, pos_y, pos_z);
+ break;
+ }
+ }
+ else
+ {
+ // the parcel has a name, so include it in the landmark name
+ switch (fmt)
+ {
+ case LOCATION_FORMAT_LANDMARK:
+ buffer = llformat("%.100s", parcel_name.c_str());
+ break;
+ case LOCATION_FORMAT_NORMAL:
+ buffer = llformat("%s, %s", parcel_name.c_str(), region_name.c_str());
+ break;
+ case LOCATION_FORMAT_NO_MATURITY:
+ buffer = llformat("%s, %s (%d, %d, %d)",
+ parcel_name.c_str(),
+ region_name.c_str(),
+ pos_x, pos_y, pos_z);
+ break;
+ case LOCATION_FORMAT_NO_COORDS:
+ buffer = llformat("%s, %s%s%s",
+ parcel_name.c_str(),
+ region_name.c_str(),
+ sim_access_string.empty() ? "" : " - ",
+ sim_access_string.c_str());
+ break;
+ case LOCATION_FORMAT_FULL:
+ buffer = llformat("%s, %s (%d, %d, %d)%s%s",
+ parcel_name.c_str(),
+ region_name.c_str(),
+ pos_x, pos_y, pos_z,
+ sim_access_string.empty() ? "" : " - ",
+ sim_access_string.c_str());
+ break;
+ }
+ }
+ str = buffer;
+ return TRUE;
+}
+BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt)
+{
+ return buildLocationString(str,fmt, gAgent.getPositionAgent());
+}
diff --git a/indra/newview/llagentui.h b/indra/newview/llagentui.h
new file mode 100644
index 0000000000..3478793e38
--- /dev/null
+++ b/indra/newview/llagentui.h
@@ -0,0 +1,63 @@
+/**
+ * @file llagentui.h
+ * @brief Utility methods to process agent's data as slurl's etc. before displaying
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLAGENTUI_H
+#define LLAGENTUI_H
+
+class LLAgentUI
+{
+public:
+ enum ELocationFormat
+ {
+ LOCATION_FORMAT_NORMAL, // Parcel
+ LOCATION_FORMAT_LANDMARK, // Parcel, Region
+ LOCATION_FORMAT_NO_MATURITY, // Parcel, Region (x, y, z)
+ LOCATION_FORMAT_NO_COORDS, // Parcel, Region - Maturity
+ LOCATION_FORMAT_FULL, // Parcel, Region (x, y, z) - Maturity
+ };
+
+ static void buildName(std::string& name);
+ static void buildFullname(std::string &name);
+
+ static std::string buildSLURL(const bool escaped = true);
+ //build location string using the current position of gAgent.
+ static BOOL buildLocationString(std::string& str, ELocationFormat fmt = LOCATION_FORMAT_LANDMARK);
+ //build location string using a region position of the avatar.
+ static BOOL buildLocationString(std::string& str, ELocationFormat fmt,const LLVector3& agent_pos_region);
+ /**
+ * @brief Check whether the agent is in neighborhood of the pole Within same region
+ * @return true if the agent is in neighborhood.
+ */
+ static BOOL checkAgentDistance(const LLVector3& local_pole, F32 radius);
+};
+
+#endif //LLAGENTUI_H
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
new file mode 100644
index 0000000000..c21cdf9508
--- /dev/null
+++ b/indra/newview/llagentwearables.cpp
@@ -0,0 +1,2575 @@
+/**
+ * @file llagentwearables.cpp
+ * @brief LLAgentWearables class implementation
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llagent.h"
+#include "llagentwearables.h"
+
+#include "llcallbacklist.h"
+#include "llfloatercustomize.h"
+#include "llinventorybridge.h"
+#include "llinventoryobserver.h"
+#include "llinventorypanel.h"
+#include "llnotificationsutil.h"
+#include "llviewerregion.h"
+#include "llvoavatarself.h"
+#include "llwearable.h"
+#include "llwearablelist.h"
+#include "llgesturemgr.h"
+#include "llappearancemgr.h"
+#include "lltexlayer.h"
+#include "llsidetray.h"
+#include "llpaneloutfitsinventory.h"
+#include "llfolderview.h"
+#include "llaccordionctrltab.h"
+
+#include <boost/scoped_ptr.hpp>
+
+#define USE_CURRENT_OUTFIT_FOLDER
+
+//--------------------------------------------------------------------
+// Classes for fetching initial wearables data
+//--------------------------------------------------------------------
+// Outfit folder fetching callback structure.
+class LLInitialWearablesFetch : public LLInventoryFetchDescendentsObserver
+{
+public:
+ LLInitialWearablesFetch() {}
+ ~LLInitialWearablesFetch();
+ virtual void done();
+
+ struct InitialWearableData
+ {
+ EWearableType mType;
+ LLUUID mItemID;
+ LLUUID mAssetID;
+ InitialWearableData(EWearableType type, LLUUID& itemID, LLUUID& assetID) :
+ mType(type),
+ mItemID(itemID),
+ mAssetID(assetID)
+ {}
+ };
+
+ typedef std::vector<InitialWearableData> initial_wearable_data_vec_t;
+ initial_wearable_data_vec_t mCOFInitialWearables; // Wearables from the Current Outfit Folder
+ initial_wearable_data_vec_t mAgentInitialWearables; // Wearables from the old agent wearables msg
+
+protected:
+ void processWearablesMessage();
+ void processContents();
+};
+
+class LLLibraryOutfitsFetch : public LLInventoryFetchDescendentsObserver
+{
+public:
+ enum ELibraryOutfitFetchStep {
+ LOFS_FOLDER = 0,
+ LOFS_OUTFITS,
+ LOFS_LIBRARY,
+ LOFS_IMPORTED,
+ LOFS_CONTENTS
+ };
+ LLLibraryOutfitsFetch() : mCurrFetchStep(LOFS_FOLDER), mOutfitsPopulated(false)
+ {
+ mMyOutfitsID = LLUUID::null;
+ mClothingID = LLUUID::null;
+ mLibraryClothingID = LLUUID::null;
+ mImportedClothingID = LLUUID::null;
+ mImportedClothingName = "Imported Library Clothing";
+ }
+ ~LLLibraryOutfitsFetch() {}
+ virtual void done();
+ void doneIdle();
+ LLUUID mMyOutfitsID;
+ void importedFolderFetch();
+protected:
+ void folderDone(void);
+ void outfitsDone(void);
+ void libraryDone(void);
+ void importedFolderDone(void);
+ void contentsDone(void);
+ enum ELibraryOutfitFetchStep mCurrFetchStep;
+ typedef std::vector< std::pair< LLUUID, std::string > > cloth_folder_vec_t;
+ cloth_folder_vec_t mLibraryClothingFolders;
+ cloth_folder_vec_t mImportedClothingFolders;
+ bool mOutfitsPopulated;
+ LLUUID mClothingID;
+ LLUUID mLibraryClothingID;
+ LLUUID mImportedClothingID;
+ std::string mImportedClothingName;
+};
+
+LLAgentWearables gAgentWearables;
+
+BOOL LLAgentWearables::mInitialWearablesUpdateReceived = FALSE;
+
+using namespace LLVOAvatarDefines;
+
+// HACK: For EXT-3923: Pants item shows in inventory with skin icon and messes with "current look"
+// Some db items are corrupted, have inventory flags = 0, implying wearable type = shape, even though
+// wearable type stored in asset is some other value.
+// Calling this function whenever a wearable is added to increase visibility if this problem
+// turns up in other inventories.
+void checkWearableAgainstInventory(LLWearable *wearable)
+{
+ if (wearable->getItemID().isNull())
+ return;
+
+ // Check for wearable type consistent with inventory item wearable type.
+ LLViewerInventoryItem *item = gInventory.getItem(wearable->getItemID());
+ if (item)
+ {
+ if (!item->isWearableType())
+ {
+ llwarns << "wearable associated with non-wearable item" << llendl;
+ }
+ if (item->getWearableType() != wearable->getType())
+ {
+ llwarns << "type mismatch: wearable " << wearable->getName()
+ << " has type " << wearable->getType()
+ << " but inventory item " << item->getName()
+ << " has type " << item->getWearableType() << llendl;
+ }
+ }
+ else
+ {
+ llwarns << "wearable inventory item not found" << wearable->getName()
+ << " itemID " << wearable->getItemID().asString() << llendl;
+ }
+}
+
+void LLAgentWearables::dump()
+{
+ llinfos << "LLAgentWearablesDump" << llendl;
+ for (S32 i = 0; i < WT_COUNT; i++)
+ {
+ U32 count = getWearableCount((EWearableType)i);
+ llinfos << "Type: " << i << " count " << count << llendl;
+ for (U32 j=0; j<count; j++)
+ {
+ LLWearable* wearable = getWearable((EWearableType)i,j);
+ if (wearable == NULL)
+ {
+ llinfos << " " << j << " NULL wearable" << llendl;
+ }
+ llinfos << " " << j << " Name " << wearable->getName()
+ << " description " << wearable->getDescription() << llendl;
+
+ }
+ }
+ llinfos << "Total items awaiting wearable update " << mItemsAwaitingWearableUpdate.size() << llendl;
+ for (std::set<LLUUID>::iterator it = mItemsAwaitingWearableUpdate.begin();
+ it != mItemsAwaitingWearableUpdate.end();
+ ++it)
+ {
+ llinfos << (*it).asString() << llendl;
+ }
+}
+
+// MULTI-WEARABLE: debugging
+struct LLAgentDumper
+{
+ LLAgentDumper(std::string name):
+ mName(name)
+ {
+ llinfos << llendl;
+ llinfos << "LLAgentDumper " << mName << llendl;
+ gAgentWearables.dump();
+ }
+
+ ~LLAgentDumper()
+ {
+ llinfos << llendl;
+ llinfos << "~LLAgentDumper " << mName << llendl;
+ gAgentWearables.dump();
+ }
+
+ std::string mName;
+};
+
+LLAgentWearables::LLAgentWearables() :
+ mWearablesLoaded(FALSE),
+ mAvatarObject(NULL)
+{
+}
+
+LLAgentWearables::~LLAgentWearables()
+{
+ cleanup();
+}
+
+void LLAgentWearables::cleanup()
+{
+ mAvatarObject = NULL;
+}
+
+void LLAgentWearables::setAvatarObject(LLVOAvatarSelf *avatar)
+{
+ mAvatarObject = avatar;
+ if (avatar)
+ {
+ sendAgentWearablesRequest();
+ }
+}
+
+// wearables
+LLAgentWearables::createStandardWearablesAllDoneCallback::~createStandardWearablesAllDoneCallback()
+{
+ gAgentWearables.createStandardWearablesAllDone();
+}
+
+LLAgentWearables::sendAgentWearablesUpdateCallback::~sendAgentWearablesUpdateCallback()
+{
+ gAgentWearables.sendAgentWearablesUpdate();
+}
+
+/**
+ * @brief Construct a callback for dealing with the wearables.
+ *
+ * Would like to pass the agent in here, but we can't safely
+ * count on it being around later. Just use gAgent directly.
+ * @param cb callback to execute on completion (??? unused ???)
+ * @param type Type for the wearable in the agent
+ * @param wearable The wearable data.
+ * @param todo Bitmask of actions to take on completion.
+ */
+LLAgentWearables::addWearableToAgentInventoryCallback::addWearableToAgentInventoryCallback(
+ LLPointer<LLRefCount> cb, S32 type, U32 index, LLWearable* wearable, U32 todo) :
+ mType(type),
+ mIndex(index),
+ mWearable(wearable),
+ mTodo(todo),
+ mCB(cb)
+{
+}
+
+void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& inv_item)
+{
+ if (inv_item.isNull())
+ return;
+
+ gAgentWearables.addWearabletoAgentInventoryDone(mType, mIndex, inv_item, mWearable);
+
+ if (mTodo & CALL_UPDATE)
+ {
+ gAgentWearables.sendAgentWearablesUpdate();
+ }
+ if (mTodo & CALL_RECOVERDONE)
+ {
+ gAgentWearables.recoverMissingWearableDone();
+ }
+ /*
+ * Do this for every one in the loop
+ */
+ if (mTodo & CALL_CREATESTANDARDDONE)
+ {
+ gAgentWearables.createStandardWearablesDone(mType, mIndex);
+ }
+ if (mTodo & CALL_MAKENEWOUTFITDONE)
+ {
+ gAgentWearables.makeNewOutfitDone(mType, mIndex);
+ }
+}
+
+void LLAgentWearables::addWearabletoAgentInventoryDone(const S32 type,
+ const U32 index,
+ const LLUUID& item_id,
+ LLWearable* wearable)
+{
+ if (item_id.isNull())
+ return;
+
+ LLUUID old_item_id = getWearableItemID((EWearableType)type,index);
+ if (wearable)
+ {
+ wearable->setItemID(item_id);
+ }
+
+ if (old_item_id.notNull())
+ {
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id);
+ setWearable((EWearableType)type,index,wearable);
+ }
+ else
+ {
+ pushWearable((EWearableType)type,wearable);
+ }
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
+ LLViewerInventoryItem* item = gInventory.getItem(item_id);
+ if (item && wearable)
+ {
+ // We're changing the asset id, so we both need to set it
+ // locally via setAssetUUID() and via setTransactionID() which
+ // will be decoded on the server. JC
+ item->setAssetUUID(wearable->getAssetID());
+ item->setTransactionID(wearable->getTransactionID());
+ gInventory.addChangedMask(LLInventoryObserver::INTERNAL, item_id);
+ item->updateServer(FALSE);
+ }
+ gInventory.notifyObservers();
+}
+
+void LLAgentWearables::sendAgentWearablesUpdate()
+{
+ // MULTI-WEARABLE: call i "type" or something.
+ // First make sure that we have inventory items for each wearable
+ for (S32 type=0; type < WT_COUNT; ++type)
+ {
+ for (U32 j=0; j < getWearableCount((EWearableType)type); ++j)
+ {
+ LLWearable* wearable = getWearable((EWearableType)type,j);
+ if (wearable)
+ {
+ if (wearable->getItemID().isNull())
+ {
+ LLPointer<LLInventoryCallback> cb =
+ new addWearableToAgentInventoryCallback(
+ LLPointer<LLRefCount>(NULL),
+ type,
+ j,
+ wearable,
+ addWearableToAgentInventoryCallback::CALL_NONE);
+ addWearableToAgentInventory(cb, wearable);
+ }
+ else
+ {
+ gInventory.addChangedMask(LLInventoryObserver::LABEL,
+ wearable->getItemID());
+ }
+ }
+ }
+ }
+
+ // Then make sure the inventory is in sync with the avatar.
+ gInventory.notifyObservers();
+
+ // Send the AgentIsNowWearing
+ gMessageSystem->newMessageFast(_PREHASH_AgentIsNowWearing);
+
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+
+ lldebugs << "sendAgentWearablesUpdate()" << llendl;
+ // MULTI-WEARABLE: update for multi-wearables after server-side support is in.
+ for (S32 type=0; type < WT_COUNT; ++type)
+ {
+ gMessageSystem->nextBlockFast(_PREHASH_WearableData);
+
+ U8 type_u8 = (U8)type;
+ gMessageSystem->addU8Fast(_PREHASH_WearableType, type_u8);
+
+ // MULTI-WEARABLE: TODO: hacked index to 0, needs to loop over all once messages support this.
+ LLWearable* wearable = getWearable((EWearableType)type, 0);
+ if (wearable)
+ {
+ //llinfos << "Sending wearable " << wearable->getName() << llendl;
+ LLUUID item_id = wearable->getItemID();
+ const LLViewerInventoryItem *item = gInventory.getItem(item_id);
+ if (item && item->getIsLinkType())
+ {
+ // Get the itemID that this item points to. i.e. make sure
+ // we are storing baseitems, not their links, in the database.
+ item_id = item->getLinkedUUID();
+ }
+ gMessageSystem->addUUIDFast(_PREHASH_ItemID, item_id);
+ }
+ else
+ {
+ //llinfos << "Not wearing wearable type " << LLWearableDictionary::getInstance()->getWearable((EWearableType)i) << llendl;
+ gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID::null);
+ }
+
+ lldebugs << " " << LLWearableDictionary::getTypeLabel((EWearableType)type) << ": " << (wearable ? wearable->getAssetID() : LLUUID::null) << llendl;
+ }
+ gAgent.sendReliableMessage();
+}
+
+void LLAgentWearables::saveWearable(const EWearableType type, const U32 index, BOOL send_update)
+{
+ LLWearable* old_wearable = getWearable(type, index);
+ if (old_wearable && (old_wearable->isDirty() || old_wearable->isOldVersion()))
+ {
+ LLUUID old_item_id = old_wearable->getItemID();
+ LLWearable* new_wearable = LLWearableList::instance().createCopy(old_wearable);
+ new_wearable->setItemID(old_item_id); // should this be in LLWearable::copyDataFrom()?
+ setWearable(type,index,new_wearable);
+
+ LLInventoryItem* item = gInventory.getItem(old_item_id);
+ if (item)
+ {
+ // Update existing inventory item
+ LLPointer<LLViewerInventoryItem> template_item =
+ new LLViewerInventoryItem(item->getUUID(),
+ item->getParentUUID(),
+ item->getPermissions(),
+ new_wearable->getAssetID(),
+ new_wearable->getAssetType(),
+ item->getInventoryType(),
+ item->getName(),
+ item->getDescription(),
+ item->getSaleInfo(),
+ item->getFlags(),
+ item->getCreationDate());
+ template_item->setTransactionID(new_wearable->getTransactionID());
+ template_item->updateServer(FALSE);
+ gInventory.updateItem(template_item);
+ }
+ else
+ {
+ // Add a new inventory item (shouldn't ever happen here)
+ U32 todo = addWearableToAgentInventoryCallback::CALL_NONE;
+ if (send_update)
+ {
+ todo |= addWearableToAgentInventoryCallback::CALL_UPDATE;
+ }
+ LLPointer<LLInventoryCallback> cb =
+ new addWearableToAgentInventoryCallback(
+ LLPointer<LLRefCount>(NULL),
+ (S32)type,
+ index,
+ new_wearable,
+ todo);
+ addWearableToAgentInventory(cb, new_wearable);
+ return;
+ }
+
+ gAgent.getAvatarObject()->wearableUpdated( type, TRUE );
+
+ if (send_update)
+ {
+ sendAgentWearablesUpdate();
+ }
+ }
+}
+
+void LLAgentWearables::saveWearableAs(const EWearableType type,
+ const U32 index,
+ const std::string& new_name,
+ BOOL save_in_lost_and_found)
+{
+ if (!isWearableCopyable(type, index))
+ {
+ llwarns << "LLAgent::saveWearableAs() not copyable." << llendl;
+ return;
+ }
+ LLWearable* old_wearable = getWearable(type, index);
+ if (!old_wearable)
+ {
+ llwarns << "LLAgent::saveWearableAs() no old wearable." << llendl;
+ return;
+ }
+
+ LLInventoryItem* item = gInventory.getItem(getWearableItemID(type,index));
+ if (!item)
+ {
+ llwarns << "LLAgent::saveWearableAs() no inventory item." << llendl;
+ return;
+ }
+ std::string trunc_name(new_name);
+ LLStringUtil::truncate(trunc_name, DB_INV_ITEM_NAME_STR_LEN);
+ LLWearable* new_wearable = LLWearableList::instance().createCopy(
+ old_wearable,
+ trunc_name);
+ LLPointer<LLInventoryCallback> cb =
+ new addWearableToAgentInventoryCallback(
+ LLPointer<LLRefCount>(NULL),
+ type,
+ index,
+ new_wearable,
+ addWearableToAgentInventoryCallback::CALL_UPDATE);
+ LLUUID category_id;
+ if (save_in_lost_and_found)
+ {
+ category_id = gInventory.findCategoryUUIDForType(
+ LLFolderType::FT_LOST_AND_FOUND);
+ }
+ else
+ {
+ // put in same folder as original
+ category_id = item->getParentUUID();
+ }
+
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ category_id,
+ new_name,
+ cb);
+}
+
+void LLAgentWearables::revertWearable(const EWearableType type, const U32 index)
+{
+ LLWearable* wearable = getWearable(type, index);
+ wearable->revertValues();
+
+ gAgent.sendAgentSetAppearance();
+}
+
+void LLAgentWearables::saveAllWearables()
+{
+ //if (!gInventory.isLoaded())
+ //{
+ // return;
+ //}
+
+ for (S32 i=0; i < WT_COUNT; i++)
+ {
+ for (U32 j=0; j < getWearableCount((EWearableType)i); j++)
+ saveWearable((EWearableType)i, j, FALSE);
+ }
+ sendAgentWearablesUpdate();
+}
+
+// Called when the user changes the name of a wearable inventory item that is currently being worn.
+void LLAgentWearables::setWearableName(const LLUUID& item_id, const std::string& new_name)
+{
+ for (S32 i=0; i < WT_COUNT; i++)
+ {
+ for (U32 j=0; j < getWearableCount((EWearableType)i); j++)
+ {
+ LLUUID curr_item_id = getWearableItemID((EWearableType)i,j);
+ if (curr_item_id == item_id)
+ {
+ LLWearable* old_wearable = getWearable((EWearableType)i,j);
+ llassert(old_wearable);
+
+ std::string old_name = old_wearable->getName();
+ old_wearable->setName(new_name);
+ LLWearable* new_wearable = LLWearableList::instance().createCopy(old_wearable);
+ new_wearable->setItemID(item_id);
+ LLInventoryItem* item = gInventory.getItem(item_id);
+ if (item)
+ {
+ new_wearable->setPermissions(item->getPermissions());
+ }
+ old_wearable->setName(old_name);
+
+ setWearable((EWearableType)i,j,new_wearable);
+ sendAgentWearablesUpdate();
+ break;
+ }
+ }
+ }
+}
+
+
+BOOL LLAgentWearables::isWearableModifiable(EWearableType type, U32 index) const
+{
+ LLUUID item_id = getWearableItemID(type, index);
+ if (!item_id.isNull())
+ {
+ LLInventoryItem* item = gInventory.getItem(item_id);
+ if (item && item->getPermissions().allowModifyBy(gAgent.getID(),
+ gAgent.getGroupID()))
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+BOOL LLAgentWearables::isWearableCopyable(EWearableType type, U32 index) const
+{
+ LLUUID item_id = getWearableItemID(type, index);
+ if (!item_id.isNull())
+ {
+ LLInventoryItem* item = gInventory.getItem(item_id);
+ if (item && item->getPermissions().allowCopyBy(gAgent.getID(),
+ gAgent.getGroupID()))
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*
+ U32 LLAgentWearables::getWearablePermMask(EWearableType type)
+ {
+ LLUUID item_id = getWearableItemID(type);
+ if (!item_id.isNull())
+ {
+ LLInventoryItem* item = gInventory.getItem(item_id);
+ if (item)
+ {
+ return item->getPermissions().getMaskOwner();
+ }
+ }
+ return PERM_NONE;
+ }
+*/
+
+LLInventoryItem* LLAgentWearables::getWearableInventoryItem(EWearableType type, U32 index)
+{
+ LLUUID item_id = getWearableItemID(type,index);
+ LLInventoryItem* item = NULL;
+ if (item_id.notNull())
+ {
+ item = gInventory.getItem(item_id);
+ }
+ return item;
+}
+
+const LLWearable* LLAgentWearables::getWearableFromItemID(const LLUUID& item_id) const
+{
+ for (S32 i=0; i < WT_COUNT; i++)
+ {
+ for (U32 j=0; j < getWearableCount((EWearableType)i); j++)
+ {
+ const LLWearable * curr_wearable = getWearable((EWearableType)i, j);
+ if (curr_wearable && (curr_wearable->getItemID() == item_id))
+ {
+ return curr_wearable;
+ }
+ }
+ }
+ return NULL;
+}
+
+const LLWearable* LLAgentWearables::getWearableFromAssetID(const LLUUID& asset_id) const
+{
+ for (S32 i=0; i < WT_COUNT; i++)
+ {
+ for (U32 j=0; j < getWearableCount((EWearableType)i); j++)
+ {
+ const LLWearable * curr_wearable = getWearable((EWearableType)i, j);
+ if (curr_wearable && (curr_wearable->getAssetID() == asset_id))
+ {
+ return curr_wearable;
+ }
+ }
+ }
+ return NULL;
+}
+
+void LLAgentWearables::sendAgentWearablesRequest()
+{
+ gMessageSystem->newMessageFast(_PREHASH_AgentWearablesRequest);
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ gAgent.sendReliableMessage();
+}
+
+// static
+BOOL LLAgentWearables::selfHasWearable(EWearableType type)
+{
+ return (gAgentWearables.getWearableCount(type) > 0);
+}
+
+LLWearable* LLAgentWearables::getWearable(const EWearableType type, U32 index)
+{
+ wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type);
+ if (wearable_iter == mWearableDatas.end())
+ {
+ return NULL;
+ }
+ wearableentry_vec_t& wearable_vec = wearable_iter->second;
+ if (index>=wearable_vec.size())
+ {
+ return NULL;
+ }
+ else
+ {
+ return wearable_vec[index];
+ }
+}
+
+void LLAgentWearables::setWearable(const EWearableType type, U32 index, LLWearable *wearable)
+{
+
+ LLWearable *old_wearable = getWearable(type,index);
+ if (!old_wearable)
+ {
+ pushWearable(type,wearable);
+ return;
+ }
+
+ wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type);
+ if (wearable_iter == mWearableDatas.end())
+ {
+ llwarns << "invalid type, type " << type << " index " << index << llendl;
+ return;
+ }
+ wearableentry_vec_t& wearable_vec = wearable_iter->second;
+ if (index>=wearable_vec.size())
+ {
+ llwarns << "invalid index, type " << type << " index " << index << llendl;
+ }
+ else
+ {
+ wearable_vec[index] = wearable;
+ old_wearable->setLabelUpdated();
+ wearableUpdated(wearable);
+ checkWearableAgainstInventory(wearable);
+ }
+}
+
+U32 LLAgentWearables::pushWearable(const EWearableType type, LLWearable *wearable)
+{
+ if (wearable == NULL)
+ {
+ // no null wearables please!
+ llwarns << "Null wearable sent for type " << type << llendl;
+ return MAX_WEARABLES_PER_TYPE;
+ }
+ if (type < WT_COUNT || mWearableDatas[type].size() < MAX_WEARABLES_PER_TYPE)
+ {
+ mWearableDatas[type].push_back(wearable);
+ wearableUpdated(wearable);
+ checkWearableAgainstInventory(wearable);
+ return mWearableDatas[type].size()-1;
+ }
+ return MAX_WEARABLES_PER_TYPE;
+}
+
+void LLAgentWearables::wearableUpdated(LLWearable *wearable)
+{
+ mAvatarObject->wearableUpdated(wearable->getType(), TRUE);
+ wearable->refreshName();
+ wearable->setLabelUpdated();
+
+ // Hack pt 2. If the wearable we just loaded has definition version 24,
+ // then force a re-save of this wearable after slamming the version number to 22.
+ // This number was incorrectly incremented for internal builds before release, and
+ // this fix will ensure that the affected wearables are re-saved with the right version number.
+ // the versions themselves are compatible. This code can be removed before release.
+ if( wearable->getDefinitionVersion() == 24 )
+ {
+ wearable->setDefinitionVersion(22);
+ U32 index = getWearableIndex(wearable);
+ llinfos << "forcing werable type " << wearable->getType() << " to version 22 from 24" << llendl;
+ saveWearable(wearable->getType(),index,TRUE);
+ }
+
+}
+
+void LLAgentWearables::popWearable(LLWearable *wearable)
+{
+ if (wearable == NULL)
+ {
+ // nothing to do here. move along.
+ return;
+ }
+
+ U32 index = getWearableIndex(wearable);
+ EWearableType type = wearable->getType();
+
+ if (index < MAX_WEARABLES_PER_TYPE && index < getWearableCount(type))
+ {
+ popWearable(type, index);
+ }
+}
+
+void LLAgentWearables::popWearable(const EWearableType type, U32 index)
+{
+ LLWearable *wearable = getWearable(type, index);
+ if (wearable)
+ {
+ mWearableDatas[type].erase(mWearableDatas[type].begin() + index);
+ mAvatarObject->wearableUpdated(wearable->getType(), TRUE);
+ wearable->setLabelUpdated();
+ }
+}
+
+U32 LLAgentWearables::getWearableIndex(LLWearable *wearable)
+{
+ if (wearable == NULL)
+ {
+ return MAX_WEARABLES_PER_TYPE;
+ }
+
+ const EWearableType type = wearable->getType();
+ wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type);
+ if (wearable_iter == mWearableDatas.end())
+ {
+ llwarns << "tried to get wearable index with an invalid type!" << llendl;
+ return MAX_WEARABLES_PER_TYPE;
+ }
+ const wearableentry_vec_t& wearable_vec = wearable_iter->second;
+ for(U32 index = 0; index < wearable_vec.size(); index++)
+ {
+ if (wearable_vec[index] == wearable)
+ {
+ return index;
+ }
+ }
+
+ return MAX_WEARABLES_PER_TYPE;
+}
+
+const LLWearable* LLAgentWearables::getWearable(const EWearableType type, U32 index) const
+{
+ wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type);
+ if (wearable_iter == mWearableDatas.end())
+ {
+ return NULL;
+ }
+ const wearableentry_vec_t& wearable_vec = wearable_iter->second;
+ if (index>=wearable_vec.size())
+ {
+ return NULL;
+ }
+ else
+ {
+ return wearable_vec[index];
+ }
+}
+
+LLWearable* LLAgentWearables::getTopWearable(const EWearableType type)
+{
+ U32 count = getWearableCount(type);
+ if ( count == 0)
+ {
+ return NULL;
+ }
+
+ return getWearable(type, count-1);
+}
+
+U32 LLAgentWearables::getWearableCount(const EWearableType type) const
+{
+ wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type);
+ if (wearable_iter == mWearableDatas.end())
+ {
+ return 0;
+ }
+ const wearableentry_vec_t& wearable_vec = wearable_iter->second;
+ return wearable_vec.size();
+}
+
+U32 LLAgentWearables::getWearableCount(const U32 tex_index) const
+{
+ const EWearableType wearable_type = LLVOAvatarDictionary::getTEWearableType((LLVOAvatarDefines::ETextureIndex)tex_index);
+ return getWearableCount(wearable_type);
+}
+
+
+BOOL LLAgentWearables::itemUpdatePending(const LLUUID& item_id) const
+{
+ return mItemsAwaitingWearableUpdate.find(item_id) != mItemsAwaitingWearableUpdate.end();
+}
+
+U32 LLAgentWearables::itemUpdatePendingCount() const
+{
+ return mItemsAwaitingWearableUpdate.size();
+}
+
+const LLUUID LLAgentWearables::getWearableItemID(EWearableType type, U32 index) const
+{
+ const LLWearable *wearable = getWearable(type,index);
+ if (wearable)
+ return wearable->getItemID();
+ else
+ return LLUUID();
+}
+
+const LLUUID LLAgentWearables::getWearableAssetID(EWearableType type, U32 index) const
+{
+ const LLWearable *wearable = getWearable(type,index);
+ if (wearable)
+ return wearable->getAssetID();
+ else
+ return LLUUID();
+}
+
+BOOL LLAgentWearables::isWearingItem(const LLUUID& item_id) const
+{
+ const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id);
+ if (getWearableFromItemID(base_item_id) != NULL)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// MULTI-WEARABLE: update for multiple
+// static
+// ! BACKWARDS COMPATIBILITY ! When we stop supporting viewer1.23, we can assume
+// that viewers have a Current Outfit Folder and won't need this message, and thus
+// we can remove/ignore this whole function.
+void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data)
+{
+ // We should only receive this message a single time. Ignore subsequent AgentWearablesUpdates
+ // that may result from AgentWearablesRequest having been sent more than once.
+ if (mInitialWearablesUpdateReceived)
+ return;
+ mInitialWearablesUpdateReceived = true;
+
+ // If this is the very first time the user has logged into viewer2+ (from a legacy viewer, or new account)
+ // then auto-populate outfits from the library into the My Outfits folder.
+ if (LLInventoryModel::getIsFirstTimeInViewer2() || gSavedSettings.getBOOL("MyOutfitsAutofill"))
+ {
+ gAgentWearables.populateMyOutfitsFolder();
+ }
+
+ LLUUID agent_id;
+ gMessageSystem->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
+
+ LLVOAvatar* avatar = gAgent.getAvatarObject();
+ if (avatar && (agent_id == avatar->getID()))
+ {
+ gMessageSystem->getU32Fast(_PREHASH_AgentData, _PREHASH_SerialNum, gAgentQueryManager.mUpdateSerialNum);
+
+ const S32 NUM_BODY_PARTS = 4;
+ S32 num_wearables = gMessageSystem->getNumberOfBlocksFast(_PREHASH_WearableData);
+ if (num_wearables < NUM_BODY_PARTS)
+ {
+ // Transitional state. Avatars should always have at least their body parts (hair, eyes, shape and skin).
+ // The fact that they don't have any here (only a dummy is sent) implies that either:
+ // 1. This account existed before we had wearables
+ // 2. The database has gotten messed up
+ // 3. This is the account's first login (i.e. the wearables haven't been generated yet).
+ return;
+ }
+
+ // Get the UUID of the current outfit folder (will be created if it doesn't exist)
+ const LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
+
+ LLInitialWearablesFetch* outfit = new LLInitialWearablesFetch();
+
+ //lldebugs << "processAgentInitialWearablesUpdate()" << llendl;
+ // Add wearables
+ // MULTI-WEARABLE: TODO: update once messages change. Currently use results to populate the zeroth element.
+ gAgentWearables.mItemsAwaitingWearableUpdate.clear();
+ for (S32 i=0; i < num_wearables; i++)
+ {
+ // Parse initial wearables data from message system
+ U8 type_u8 = 0;
+ gMessageSystem->getU8Fast(_PREHASH_WearableData, _PREHASH_WearableType, type_u8, i);
+ if (type_u8 >= WT_COUNT)
+ {
+ continue;
+ }
+ const EWearableType type = (EWearableType) type_u8;
+
+ LLUUID item_id;
+ gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_ItemID, item_id, i);
+
+ LLUUID asset_id;
+ gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_AssetID, asset_id, i);
+ if (asset_id.isNull())
+ {
+ LLWearable::removeFromAvatar(type, FALSE);
+ }
+ else
+ {
+ LLAssetType::EType asset_type = LLWearableDictionary::getAssetType(type);
+ if (asset_type == LLAssetType::AT_NONE)
+ {
+ continue;
+ }
+
+ // MULTI-WEARABLE: TODO: update once messages change. Currently use results to populate the zeroth element.
+
+ // Store initial wearables data until we know whether we have the current outfit folder or need to use the data.
+ LLInitialWearablesFetch::InitialWearableData wearable_data(type, item_id, asset_id); // MULTI-WEARABLE: update
+ outfit->mAgentInitialWearables.push_back(wearable_data);
+
+ }
+
+ lldebugs << " " << LLWearableDictionary::getTypeLabel(type) << llendl;
+ }
+
+ // Get the complete information on the items in the inventory and set up an observer
+ // that will trigger when the complete information is fetched.
+ LLInventoryFetchDescendentsObserver::folder_ref_t folders;
+ folders.push_back(current_outfit_id);
+ outfit->fetchDescendents(folders);
+ if(outfit->isEverythingComplete())
+ {
+ // everything is already here - call done.
+ outfit->done();
+ }
+ else
+ {
+ // it's all on it's way - add an observer, and the inventory
+ // will call done for us when everything is here.
+ gInventory.addObserver(outfit);
+ }
+
+ }
+}
+
+// A single wearable that the avatar was wearing on start-up has arrived from the database.
+// static
+void LLAgentWearables::onInitialWearableAssetArrived(LLWearable* wearable, void* userdata)
+{
+ boost::scoped_ptr<LLInitialWearablesFetch::InitialWearableData> wear_data((LLInitialWearablesFetch::InitialWearableData*)userdata);
+ const EWearableType type = wear_data->mType;
+ U32 index = 0;
+
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if (!avatar)
+ {
+ return;
+ }
+
+ if (wearable)
+ {
+ llassert(type == wearable->getType());
+ wearable->setItemID(wear_data->mItemID);
+ index = gAgentWearables.pushWearable(type, wearable);
+ gAgentWearables.mItemsAwaitingWearableUpdate.erase(wear_data->mItemID);
+
+ // disable composites if initial textures are baked
+ avatar->setupComposites();
+
+ avatar->setCompositeUpdatesEnabled(TRUE);
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, wearable->getItemID());
+ }
+ else
+ {
+ // Somehow the asset doesn't exist in the database.
+ gAgentWearables.recoverMissingWearable(type,index);
+ }
+
+ gInventory.notifyObservers();
+
+ // Have all the wearables that the avatar was wearing at log-in arrived?
+ // MULTI-WEARABLE: update when multiple wearables can arrive per type.
+
+ gAgentWearables.updateWearablesLoaded();
+ if (gAgentWearables.areWearablesLoaded())
+ {
+
+ // Can't query cache until all wearables have arrived, so calling this earlier is a no-op.
+ gAgentWearables.queryWearableCache();
+
+ // Make sure that the server's idea of the avatar's wearables actually match the wearables.
+ gAgent.sendAgentSetAppearance();
+
+ // Check to see if there are any baked textures that we hadn't uploaded before we logged off last time.
+ // If there are any, schedule them to be uploaded as soon as the layer textures they depend on arrive.
+ if (gAgent.cameraCustomizeAvatar())
+ {
+ avatar->requestLayerSetUploads();
+ }
+ }
+}
+
+// Normally, all wearables referred to "AgentWearablesUpdate" will correspond to actual assets in the
+// database. If for some reason, we can't load one of those assets, we can try to reconstruct it so that
+// the user isn't left without a shape, for example. (We can do that only after the inventory has loaded.)
+void LLAgentWearables::recoverMissingWearable(const EWearableType type, U32 index)
+{
+ // Try to recover by replacing missing wearable with a new one.
+ LLNotificationsUtil::add("ReplacedMissingWearable");
+ lldebugs << "Wearable " << LLWearableDictionary::getTypeLabel(type) << " could not be downloaded. Replaced inventory item with default wearable." << llendl;
+ LLWearable* new_wearable = LLWearableList::instance().createNewWearable(type);
+
+ S32 type_s32 = (S32) type;
+ setWearable(type,index,new_wearable);
+ //new_wearable->writeToAvatar(TRUE);
+
+ // Add a new one in the lost and found folder.
+ // (We used to overwrite the "not found" one, but that could potentially
+ // destory content.) JC
+ const LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
+ LLPointer<LLInventoryCallback> cb =
+ new addWearableToAgentInventoryCallback(
+ LLPointer<LLRefCount>(NULL),
+ type_s32,
+ index,
+ new_wearable,
+ addWearableToAgentInventoryCallback::CALL_RECOVERDONE);
+ addWearableToAgentInventory(cb, new_wearable, lost_and_found_id, TRUE);
+}
+
+void LLAgentWearables::recoverMissingWearableDone()
+{
+ // Have all the wearables that the avatar was wearing at log-in arrived or been fabricated?
+ updateWearablesLoaded();
+ if (areWearablesLoaded())
+ {
+ // Make sure that the server's idea of the avatar's wearables actually match the wearables.
+ gAgent.sendAgentSetAppearance();
+ }
+ else
+ {
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, LLUUID::null);
+ gInventory.notifyObservers();
+ }
+}
+
+void LLAgentWearables::addLocalTextureObject(const EWearableType wearable_type, const LLVOAvatarDefines::ETextureIndex texture_type, U32 wearable_index)
+{
+ LLWearable* wearable = getWearable((EWearableType)wearable_type, wearable_index);
+ if (!wearable)
+ {
+ llerrs << "Tried to add local texture object to invalid wearable with type " << wearable_type << " and index " << wearable_index << llendl;
+ }
+ LLLocalTextureObject* lto = new LLLocalTextureObject();
+ wearable->setLocalTextureObject(texture_type, lto);
+}
+
+void LLAgentWearables::createStandardWearables(BOOL female)
+{
+ llwarns << "Creating Standard " << (female ? "female" : "male")
+ << " Wearables" << llendl;
+
+ if (mAvatarObject.isNull())
+ {
+ return;
+ }
+
+ mAvatarObject->setSex(female ? SEX_FEMALE : SEX_MALE);
+
+ const BOOL create[WT_COUNT] =
+ {
+ TRUE, //WT_SHAPE
+ TRUE, //WT_SKIN
+ TRUE, //WT_HAIR
+ TRUE, //WT_EYES
+ TRUE, //WT_SHIRT
+ TRUE, //WT_PANTS
+ TRUE, //WT_SHOES
+ TRUE, //WT_SOCKS
+ FALSE, //WT_JACKET
+ FALSE, //WT_GLOVES
+ TRUE, //WT_UNDERSHIRT
+ TRUE, //WT_UNDERPANTS
+ FALSE //WT_SKIRT
+ };
+
+ for (S32 i=0; i < WT_COUNT; i++)
+ {
+ bool once = false;
+ LLPointer<LLRefCount> donecb = NULL;
+ if (create[i])
+ {
+ if (!once)
+ {
+ once = true;
+ donecb = new createStandardWearablesAllDoneCallback;
+ }
+ llassert(getWearableCount((EWearableType)i) == 0);
+ LLWearable* wearable = LLWearableList::instance().createNewWearable((EWearableType)i);
+ U32 index = pushWearable((EWearableType)i,wearable);
+ // no need to update here...
+ LLPointer<LLInventoryCallback> cb =
+ new addWearableToAgentInventoryCallback(
+ donecb,
+ i,
+ index,
+ wearable,
+ addWearableToAgentInventoryCallback::CALL_CREATESTANDARDDONE);
+ addWearableToAgentInventory(cb, wearable, LLUUID::null, FALSE);
+ }
+ }
+}
+
+void LLAgentWearables::createStandardWearablesDone(S32 type, U32 index)
+{
+ if (mAvatarObject)
+ {
+ mAvatarObject->updateVisualParams();
+ }
+}
+
+void LLAgentWearables::createStandardWearablesAllDone()
+{
+ // ... because sendAgentWearablesUpdate will notify inventory
+ // observers.
+ mWearablesLoaded = TRUE;
+ checkWearablesLoaded();
+
+ updateServer();
+
+ // Treat this as the first texture entry message, if none received yet
+ mAvatarObject->onFirstTEMessageReceived();
+}
+
+// MULTI-WEARABLE: Properly handle multiwearables later.
+void LLAgentWearables::getAllWearablesArray(LLDynamicArray<S32>& wearables)
+{
+ for( S32 i = 0; i < WT_COUNT; ++i )
+ {
+ if (getWearableCount((EWearableType) i) != 0)
+ {
+ wearables.push_back(i);
+ }
+ }
+}
+
+// Note: wearables_to_include should be a list of EWearableType types
+// attachments_to_include should be a list of attachment points
+void LLAgentWearables::makeNewOutfit(const std::string& new_folder_name,
+ const LLDynamicArray<S32>& wearables_to_include,
+ const LLDynamicArray<S32>& attachments_to_include,
+ BOOL rename_clothing)
+{
+ if (mAvatarObject.isNull())
+ {
+ return;
+ }
+
+ // First, make a folder in the Clothes directory.
+ LLUUID folder_id = gInventory.createNewCategory(
+ gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING),
+ LLFolderType::FT_NONE,
+ new_folder_name);
+
+ bool found_first_item = false;
+
+ ///////////////////
+ // Wearables
+
+ if (wearables_to_include.count())
+ {
+ // Then, iterate though each of the wearables and save copies of them in the folder.
+ S32 i;
+ S32 count = wearables_to_include.count();
+ LLDynamicArray<LLUUID> delete_items;
+ LLPointer<LLRefCount> cbdone = NULL;
+ for (i = 0; i < count; ++i)
+ {
+ const S32 type = wearables_to_include[i];
+ for (U32 j=0; j<getWearableCount((EWearableType)i); j++)
+ {
+ LLWearable* old_wearable = getWearable((EWearableType)type, j);
+ if (old_wearable)
+ {
+ std::string new_name;
+ LLWearable* new_wearable;
+ new_wearable = LLWearableList::instance().createCopy(old_wearable);
+ if (rename_clothing)
+ {
+ new_name = new_folder_name;
+ new_name.append(" ");
+ new_name.append(old_wearable->getTypeLabel());
+ LLStringUtil::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN);
+ new_wearable->setName(new_name);
+ }
+
+ LLViewerInventoryItem* item = gInventory.getItem(getWearableItemID((EWearableType)type,j));
+ S32 todo = addWearableToAgentInventoryCallback::CALL_NONE;
+ if (!found_first_item)
+ {
+ found_first_item = true;
+ /* set the focus to the first item */
+ todo |= addWearableToAgentInventoryCallback::CALL_MAKENEWOUTFITDONE;
+ /* send the agent wearables update when done */
+ cbdone = new sendAgentWearablesUpdateCallback;
+ }
+ LLPointer<LLInventoryCallback> cb =
+ new addWearableToAgentInventoryCallback(
+ cbdone,
+ type,
+ j,
+ new_wearable,
+ todo);
+ if (isWearableCopyable((EWearableType)type, j))
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ folder_id,
+ new_name,
+ cb);
+ }
+ else
+ {
+ move_inventory_item(
+ gAgent.getID(),
+ gAgent.getSessionID(),
+ item->getUUID(),
+ folder_id,
+ new_name,
+ cb);
+ }
+ }
+ }
+ }
+ gInventory.notifyObservers();
+ }
+
+
+ ///////////////////
+ // Attachments
+
+ if (attachments_to_include.count())
+ {
+ BOOL msg_started = FALSE;
+ LLMessageSystem* msg = gMessageSystem;
+ for (S32 i = 0; i < attachments_to_include.count(); i++)
+ {
+ S32 attachment_pt = attachments_to_include[i];
+ LLViewerJointAttachment* attachment = get_if_there(mAvatarObject->mAttachmentPoints, attachment_pt, (LLViewerJointAttachment*)NULL);
+ if (!attachment) continue;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject *attached_object = (*attachment_iter);
+ if(!attached_object) continue;
+ const LLUUID& item_id = (*attachment_iter)->getItemID();
+ if(item_id.isNull()) continue;
+ LLInventoryItem* item = gInventory.getItem(item_id);
+ if(!item) continue;
+ if(!msg_started)
+ {
+ msg_started = TRUE;
+ msg->newMessage("CreateNewOutfitAttachments");
+ msg->nextBlock("AgentData");
+ msg->addUUID("AgentID", gAgent.getID());
+ msg->addUUID("SessionID", gAgent.getSessionID());
+ msg->nextBlock("HeaderData");
+ msg->addUUID("NewFolderID", folder_id);
+ }
+ msg->nextBlock("ObjectData");
+ msg->addUUID("OldItemID", item_id);
+ msg->addUUID("OldFolderID", item->getParentUUID());
+ }
+ }
+
+ if (msg_started)
+ {
+ gAgent.sendReliableMessage();
+ }
+
+ }
+}
+
+class LLShowCreatedOutfit: public LLInventoryCallback
+{
+public:
+ LLShowCreatedOutfit(LLUUID& folder_id):
+ mFolderID(folder_id)
+ {
+ }
+
+ virtual ~LLShowCreatedOutfit()
+ {
+ LLSD key;
+ LLSideTray::getInstance()->showPanel("panel_outfits_inventory", key);
+ LLPanelOutfitsInventory *outfit_panel =
+ dynamic_cast<LLPanelOutfitsInventory*>(LLSideTray::getInstance()->getPanel("panel_outfits_inventory"));
+ if (outfit_panel)
+ {
+ outfit_panel->getRootFolder()->clearSelection();
+ outfit_panel->getRootFolder()->setSelectionByID(mFolderID, TRUE);
+ }
+ LLAccordionCtrlTab* tab_outfits = outfit_panel ? outfit_panel->findChild<LLAccordionCtrlTab>("tab_outfits") : 0;
+ if (tab_outfits && !tab_outfits->getDisplayChildren())
+ {
+ tab_outfits->changeOpenClose(tab_outfits->getDisplayChildren());
+ }
+
+ LLAppearanceManager::instance().updateIsDirty();
+ LLAppearanceManager::instance().updatePanelOutfitName("");
+ }
+
+ virtual void fire(const LLUUID&)
+ {
+ }
+
+private:
+ LLUUID mFolderID;
+};
+
+LLUUID LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name)
+{
+ if (mAvatarObject.isNull())
+ {
+ return LLUUID::null;
+ }
+
+ // First, make a folder in the My Outfits directory.
+ const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
+ LLUUID folder_id = gInventory.createNewCategory(
+ parent_id,
+ LLFolderType::FT_OUTFIT,
+ new_folder_name);
+
+ LLPointer<LLInventoryCallback> cb = new LLShowCreatedOutfit(folder_id);
+ LLAppearanceManager::instance().shallowCopyCategory(LLAppearanceManager::instance().getCOF(),folder_id, cb);
+ LLAppearanceManager::instance().createBaseOutfitLink(folder_id, cb);
+
+ return folder_id;
+}
+
+void LLAgentWearables::makeNewOutfitDone(S32 type, U32 index)
+{
+ LLUUID first_item_id = getWearableItemID((EWearableType)type, index);
+ // Open the inventory and select the first item we added.
+ if (first_item_id.notNull())
+ {
+ LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel();
+ if (active_panel)
+ {
+ active_panel->setSelection(first_item_id, TAKE_FOCUS_NO);
+ }
+ }
+}
+
+
+void LLAgentWearables::addWearableToAgentInventory(LLPointer<LLInventoryCallback> cb,
+ LLWearable* wearable,
+ const LLUUID& category_id,
+ BOOL notify)
+{
+ create_inventory_item(gAgent.getID(),
+ gAgent.getSessionID(),
+ category_id,
+ wearable->getTransactionID(),
+ wearable->getName(),
+ wearable->getDescription(),
+ wearable->getAssetType(),
+ LLInventoryType::IT_WEARABLE,
+ wearable->getType(),
+ wearable->getPermissions().getMaskNextOwner(),
+ cb);
+}
+
+void LLAgentWearables::removeWearable(const EWearableType type, bool do_remove_all, U32 index)
+{
+ if (gAgent.isTeen() &&
+ (type == WT_UNDERSHIRT || type == WT_UNDERPANTS))
+ {
+ // Can't take off underclothing in simple UI mode or on PG accounts
+ // TODO: enable the removing of a single undershirt/underpants if multiple are worn. - Nyx
+ return;
+ }
+ if (getWearableCount(type) == 0)
+ {
+ // no wearables to remove
+ return;
+ }
+
+ if (do_remove_all)
+ {
+ removeWearableFinal(type, do_remove_all, index);
+ }
+ else
+ {
+ LLWearable* old_wearable = getWearable(type,index);
+
+ if (old_wearable)
+ {
+ if (old_wearable->isDirty())
+ {
+ LLSD payload;
+ payload["wearable_type"] = (S32)type;
+ // Bring up view-modal dialog: Save changes? Yes, No, Cancel
+ LLNotificationsUtil::add("WearableSave", LLSD(), payload, &LLAgentWearables::onRemoveWearableDialog);
+ return;
+ }
+ else
+ {
+ removeWearableFinal(type, do_remove_all, index);
+ }
+ }
+ }
+}
+
+
+// MULTI_WEARABLE: assuming one wearable per type.
+// MULTI_WEARABLE: hardwiring 0th elt for now - notification needs to change.
+// static
+bool LLAgentWearables::onRemoveWearableDialog(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ EWearableType type = (EWearableType)notification["payload"]["wearable_type"].asInteger();
+ switch(option)
+ {
+ case 0: // "Save"
+ gAgentWearables.saveWearable(type, 0);
+ gAgentWearables.removeWearableFinal(type, false, 0);
+ break;
+
+ case 1: // "Don't Save"
+ gAgentWearables.removeWearableFinal(type, false, 0);
+ break;
+
+ case 2: // "Cancel"
+ break;
+
+ default:
+ llassert(0);
+ break;
+ }
+ return false;
+}
+
+// Called by removeWearable() and onRemoveWearableDialog() to actually do the removal.
+void LLAgentWearables::removeWearableFinal(const EWearableType type, bool do_remove_all, U32 index)
+{
+ //LLAgentDumper dumper("removeWearable");
+ if (do_remove_all)
+ {
+ S32 max_entry = mWearableDatas[type].size()-1;
+ for (S32 i=max_entry; i>=0; i--)
+ {
+ LLWearable* old_wearable = getWearable(type,i);
+ //queryWearableCache(); // moved below
+ if (old_wearable)
+ {
+ popWearable(old_wearable);
+ old_wearable->removeFromAvatar(TRUE);
+ }
+ }
+ mWearableDatas[type].clear();
+ }
+ else
+ {
+ LLWearable* old_wearable = getWearable(type, index);
+ //queryWearableCache(); // moved below
+
+ if (old_wearable)
+ {
+ popWearable(old_wearable);
+ old_wearable->removeFromAvatar(TRUE);
+ }
+ }
+
+ queryWearableCache();
+
+ // Update the server
+ updateServer();
+ gInventory.notifyObservers();
+}
+
+// Assumes existing wearables are not dirty.
+// MULTI_WEARABLE: assumes one wearable per type.
+void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& items,
+ const LLDynamicArray< LLWearable* >& wearables,
+ BOOL remove)
+{
+ lldebugs << "setWearableOutfit() start" << llendl;
+
+ BOOL wearables_to_remove[WT_COUNT];
+ wearables_to_remove[WT_SHAPE] = FALSE;
+ wearables_to_remove[WT_SKIN] = FALSE;
+ wearables_to_remove[WT_HAIR] = FALSE;
+ wearables_to_remove[WT_EYES] = FALSE;
+ wearables_to_remove[WT_SHIRT] = remove;
+ wearables_to_remove[WT_PANTS] = remove;
+ wearables_to_remove[WT_SHOES] = remove;
+ wearables_to_remove[WT_SOCKS] = remove;
+ wearables_to_remove[WT_JACKET] = remove;
+ wearables_to_remove[WT_GLOVES] = remove;
+ wearables_to_remove[WT_UNDERSHIRT] = (!gAgent.isTeen()) & remove;
+ wearables_to_remove[WT_UNDERPANTS] = (!gAgent.isTeen()) & remove;
+ wearables_to_remove[WT_SKIRT] = remove;
+ wearables_to_remove[WT_ALPHA] = remove;
+ wearables_to_remove[WT_TATTOO] = remove;
+
+
+ S32 count = wearables.count();
+ llassert(items.count() == count);
+
+ S32 i;
+ for (i = 0; i < count; i++)
+ {
+ LLWearable* new_wearable = wearables[i];
+ LLPointer<LLInventoryItem> new_item = items[i];
+
+ const EWearableType type = new_wearable->getType();
+ wearables_to_remove[type] = FALSE;
+
+ // MULTI_WEARABLE: using 0th
+ LLWearable* old_wearable = getWearable(type, 0);
+ if (old_wearable)
+ {
+ const LLUUID& old_item_id = getWearableItemID(type, 0);
+ if ((old_wearable->getAssetID() == new_wearable->getAssetID()) &&
+ (old_item_id == new_item->getUUID()))
+ {
+ lldebugs << "No change to wearable asset and item: " << LLWearableDictionary::getInstance()->getWearableEntry(type) << llendl;
+ continue;
+ }
+
+ // Assumes existing wearables are not dirty.
+ if (old_wearable->isDirty())
+ {
+ llassert(0);
+ continue;
+ }
+ }
+
+ if (new_wearable)
+ new_wearable->setItemID(new_item->getUUID());
+ setWearable(type,0,new_wearable);
+ }
+
+ std::vector<LLWearable*> wearables_being_removed;
+
+ for (i = 0; i < WT_COUNT; i++)
+ {
+ if (wearables_to_remove[i])
+ {
+ // MULTI_WEARABLE: assuming 0th
+ LLWearable* wearable = getWearable((EWearableType)i, 0);
+ const LLUUID &item_id = getWearableItemID((EWearableType)i,0);
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
+ if (wearable)
+ {
+ wearables_being_removed.push_back(wearable);
+ }
+ removeWearable((EWearableType)i,true,0);
+ }
+ }
+
+ gInventory.notifyObservers();
+
+
+ std::vector<LLWearable*>::iterator wearable_iter;
+
+ for (wearable_iter = wearables_being_removed.begin();
+ wearable_iter != wearables_being_removed.end();
+ ++wearable_iter)
+ {
+ LLWearable* wearablep = *wearable_iter;
+ if (wearablep)
+ {
+ wearablep->removeFromAvatar(TRUE);
+ }
+ }
+
+ if (mAvatarObject)
+ {
+ mAvatarObject->updateVisualParams();
+ }
+
+ // Start rendering & update the server
+ mWearablesLoaded = TRUE;
+ checkWearablesLoaded();
+ queryWearableCache();
+ updateServer();
+
+ lldebugs << "setWearableOutfit() end" << llendl;
+}
+
+
+// User has picked "wear on avatar" from a menu.
+void LLAgentWearables::setWearableItem(LLInventoryItem* new_item, LLWearable* new_wearable, bool do_append)
+{
+ //LLAgentDumper dumper("setWearableItem");
+ if (isWearingItem(new_item->getUUID()))
+ {
+ llwarns << "wearable " << new_item->getUUID() << " is already worn" << llendl;
+ return;
+ }
+
+ const EWearableType type = new_wearable->getType();
+
+ if (!do_append)
+ {
+ // Remove old wearable, if any
+ // MULTI_WEARABLE: hardwired to 0
+ LLWearable* old_wearable = getWearable(type,0);
+ if (old_wearable)
+ {
+ const LLUUID& old_item_id = old_wearable->getItemID();
+ if ((old_wearable->getAssetID() == new_wearable->getAssetID()) &&
+ (old_item_id == new_item->getUUID()))
+ {
+ lldebugs << "No change to wearable asset and item: " << LLWearableDictionary::getInstance()->getWearableEntry(type) << llendl;
+ return;
+ }
+
+ if (old_wearable->isDirty())
+ {
+ // Bring up modal dialog: Save changes? Yes, No, Cancel
+ LLSD payload;
+ payload["item_id"] = new_item->getUUID();
+ LLNotificationsUtil::add("WearableSave", LLSD(), payload, boost::bind(onSetWearableDialog, _1, _2, new_wearable));
+ return;
+ }
+ }
+ }
+
+ setWearableFinal(new_item, new_wearable, do_append);
+}
+
+// static
+bool LLAgentWearables::onSetWearableDialog(const LLSD& notification, const LLSD& response, LLWearable* wearable)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ LLInventoryItem* new_item = gInventory.getItem(notification["payload"]["item_id"].asUUID());
+ if (!new_item)
+ {
+ delete wearable;
+ return false;
+ }
+
+ switch(option)
+ {
+ case 0: // "Save"
+// MULTI_WEARABLE: assuming 0th
+ gAgentWearables.saveWearable(wearable->getType(),0);
+ gAgentWearables.setWearableFinal(new_item, wearable);
+ break;
+
+ case 1: // "Don't Save"
+ gAgentWearables.setWearableFinal(new_item, wearable);
+ break;
+
+ case 2: // "Cancel"
+ break;
+
+ default:
+ llassert(0);
+ break;
+ }
+
+ delete wearable;
+ return false;
+}
+
+// Called from setWearableItem() and onSetWearableDialog() to actually set the wearable.
+// MULTI_WEARABLE: unify code after null objects are gone.
+void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLWearable* new_wearable, bool do_append)
+{
+ const EWearableType type = new_wearable->getType();
+
+ if (do_append && getWearableItemID(type,0).notNull())
+ {
+ new_wearable->setItemID(new_item->getUUID());
+ mWearableDatas[type].push_back(new_wearable);
+ llinfos << "Added additional wearable for type " << type
+ << " size is now " << mWearableDatas[type].size() << llendl;
+ checkWearableAgainstInventory(new_wearable);
+ }
+ else
+ {
+ // Replace the old wearable with a new one.
+ llassert(new_item->getAssetUUID() == new_wearable->getAssetID());
+
+ LLWearable *old_wearable = getWearable(type,0);
+ LLUUID old_item_id;
+ if (old_wearable)
+ {
+ old_item_id = old_wearable->getItemID();
+ }
+ new_wearable->setItemID(new_item->getUUID());
+ setWearable(type,0,new_wearable);
+
+ if (old_item_id.notNull())
+ {
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id);
+ gInventory.notifyObservers();
+ }
+ llinfos << "Replaced current element 0 for type " << type
+ << " size is now " << mWearableDatas[type].size() << llendl;
+ }
+
+ //llinfos << "LLVOAvatar::setWearableItem()" << llendl;
+ queryWearableCache();
+ //new_wearable->writeToAvatar(TRUE);
+
+ updateServer();
+}
+
+void LLAgentWearables::queryWearableCache()
+{
+ if (!areWearablesLoaded())
+ {
+ return;
+ }
+
+ // Look up affected baked textures.
+ // If they exist:
+ // disallow updates for affected layersets (until dataserver responds with cache request.)
+ // If cache miss, turn updates back on and invalidate composite.
+ // If cache hit, modify baked texture entries.
+ //
+ // Cache requests contain list of hashes for each baked texture entry.
+ // Response is list of valid baked texture assets. (same message)
+
+ gMessageSystem->newMessageFast(_PREHASH_AgentCachedTexture);
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ gMessageSystem->addS32Fast(_PREHASH_SerialNum, gAgentQueryManager.mWearablesCacheQueryID);
+
+ S32 num_queries = 0;
+ for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
+ {
+ const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index);
+ LLUUID hash;
+ for (U8 i=0; i < baked_dict->mWearables.size(); i++)
+ {
+ const EWearableType baked_type = baked_dict->mWearables[i];
+ // MULTI_WEARABLE: not order-dependent
+ const U32 num_wearables = getWearableCount(baked_type);
+ for (U32 index = 0; index < num_wearables; ++index)
+ {
+ const LLWearable* wearable = getWearable(baked_type,index);
+ if (wearable)
+ {
+ hash ^= wearable->getAssetID();
+ }
+ }
+ }
+ if (hash.notNull())
+ {
+ hash ^= baked_dict->mWearablesHashID;
+ num_queries++;
+ // *NOTE: make sure at least one request gets packed
+
+ //llinfos << "Requesting texture for hash " << hash << " in baked texture slot " << baked_index << llendl;
+ gMessageSystem->nextBlockFast(_PREHASH_WearableData);
+ gMessageSystem->addUUIDFast(_PREHASH_ID, hash);
+ gMessageSystem->addU8Fast(_PREHASH_TextureIndex, (U8)baked_index);
+ }
+
+ gAgentQueryManager.mActiveCacheQueries[baked_index] = gAgentQueryManager.mWearablesCacheQueryID;
+ }
+
+ llinfos << "Requesting texture cache entry for " << num_queries << " baked textures" << llendl;
+ gMessageSystem->sendReliable(gAgent.getRegion()->getHost());
+ gAgentQueryManager.mNumPendingQueries++;
+ gAgentQueryManager.mWearablesCacheQueryID++;
+}
+
+// MULTI_WEARABLE: need a way to specify by wearable rather than by type.
+// User has picked "remove from avatar" from a menu.
+// static
+void LLAgentWearables::userRemoveWearable(EWearableType& type)
+{
+ if (!(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR)) //&&
+ //!((!gAgent.isTeen()) && (type==WT_UNDERPANTS || type==WT_UNDERSHIRT)))
+ {
+ // MULTI_WEARABLE: fixed to 0th for now.
+ gAgentWearables.removeWearable(type,false,0);
+ }
+}
+
+// static
+void LLAgentWearables::userRemoveAllClothes()
+{
+ // We have to do this up front to avoid having to deal with the case of multiple wearables being dirty.
+ if (gFloaterCustomize)
+ {
+ gFloaterCustomize->askToSaveIfDirty(userRemoveAllClothesStep2);
+ }
+ else
+ {
+ userRemoveAllClothesStep2(TRUE);
+ }
+}
+
+// static
+void LLAgentWearables::userRemoveAllClothesStep2(BOOL proceed)
+{
+ if (proceed)
+ {
+ gAgentWearables.removeWearable(WT_SHIRT,true,0);
+ gAgentWearables.removeWearable(WT_PANTS,true,0);
+ gAgentWearables.removeWearable(WT_SHOES,true,0);
+ gAgentWearables.removeWearable(WT_SOCKS,true,0);
+ gAgentWearables.removeWearable(WT_JACKET,true,0);
+ gAgentWearables.removeWearable(WT_GLOVES,true,0);
+ gAgentWearables.removeWearable(WT_UNDERSHIRT,true,0);
+ gAgentWearables.removeWearable(WT_UNDERPANTS,true,0);
+ gAgentWearables.removeWearable(WT_SKIRT,true,0);
+ gAgentWearables.removeWearable(WT_ALPHA,true,0);
+ gAgentWearables.removeWearable(WT_TATTOO,true,0);
+ }
+}
+
+// Combines userRemoveAllAttachments() and userAttachMultipleAttachments() logic to
+// get attachments into desired state with minimal number of adds/removes.
+void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj_item_array)
+{
+ // Possible cases:
+ // already wearing but not in request set -> take off.
+ // already wearing and in request set -> leave alone.
+ // not wearing and in request set -> put on.
+
+ LLVOAvatar* avatarp = gAgent.getAvatarObject();
+ if (!avatarp)
+ {
+ llwarns << "No avatar found." << llendl;
+ return;
+ }
+
+ std::set<LLUUID> requested_item_ids;
+ std::set<LLUUID> current_item_ids;
+ for (S32 i=0; i<obj_item_array.count(); i++)
+ requested_item_ids.insert(obj_item_array[i].get()->getLinkedUUID());
+
+ // Build up list of objects to be removed and items currently attached.
+ llvo_vec_t objects_to_remove;
+ for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
+ iter != avatarp->mAttachmentPoints.end();)
+ {
+ LLVOAvatar::attachment_map_t::iterator curiter = iter++;
+ LLViewerJointAttachment* attachment = curiter->second;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject *objectp = (*attachment_iter);
+ if (objectp)
+ {
+ LLUUID object_item_id = objectp->getItemID();
+ if (requested_item_ids.find(object_item_id) != requested_item_ids.end())
+ {
+ // Object currently worn, was requested.
+ // Flag as currently worn so we won't have to add it again.
+ current_item_ids.insert(object_item_id);
+ }
+ else
+ {
+ // object currently worn, not requested.
+ objects_to_remove.push_back(objectp);
+ }
+ }
+ }
+ }
+
+ LLInventoryModel::item_array_t items_to_add;
+ for (LLInventoryModel::item_array_t::iterator it = obj_item_array.begin();
+ it != obj_item_array.end();
+ ++it)
+ {
+ LLUUID linked_id = (*it).get()->getLinkedUUID();
+ if (current_item_ids.find(linked_id) != current_item_ids.end())
+ {
+ // Requested attachment is already worn.
+ }
+ else
+ {
+ // Requested attachment is not worn yet.
+ items_to_add.push_back(*it);
+ }
+ }
+ // S32 remove_count = objects_to_remove.size();
+ // S32 add_count = items_to_add.size();
+ // llinfos << "remove " << remove_count << " add " << add_count << llendl;
+
+ // Remove everything in objects_to_remove
+ userRemoveMultipleAttachments(objects_to_remove);
+
+ // Add everything in items_to_add
+ userAttachMultipleAttachments(items_to_add);
+}
+
+void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remove)
+{
+ LLVOAvatar* avatarp = gAgent.getAvatarObject();
+ if (!avatarp)
+ {
+ llwarns << "No avatar found." << llendl;
+ return;
+ }
+
+ if (objects_to_remove.empty())
+ return;
+
+ gMessageSystem->newMessage("ObjectDetach");
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+
+ for (llvo_vec_t::iterator it = objects_to_remove.begin();
+ it != objects_to_remove.end();
+ ++it)
+ {
+ LLViewerObject *objectp = *it;
+ gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
+ gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, objectp->getLocalID());
+ }
+ gMessageSystem->sendReliable(gAgent.getRegionHost());
+}
+
+void LLAgentWearables::userRemoveAllAttachments()
+{
+ LLVOAvatar* avatarp = gAgent.getAvatarObject();
+ if (!avatarp)
+ {
+ llwarns << "No avatar found." << llendl;
+ return;
+ }
+
+ llvo_vec_t objects_to_remove;
+
+ for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
+ iter != avatarp->mAttachmentPoints.end();)
+ {
+ LLVOAvatar::attachment_map_t::iterator curiter = iter++;
+ LLViewerJointAttachment* attachment = curiter->second;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject *attached_object = (*attachment_iter);
+ if (attached_object)
+ {
+ objects_to_remove.push_back(attached_object);
+ }
+ }
+ }
+ userRemoveMultipleAttachments(objects_to_remove);
+}
+
+void LLAgentWearables::userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array)
+{
+ // Build a compound message to send all the objects that need to be rezzed.
+ S32 obj_count = obj_item_array.count();
+
+ // Limit number of packets to send
+ const S32 MAX_PACKETS_TO_SEND = 10;
+ const S32 OBJECTS_PER_PACKET = 4;
+ const S32 MAX_OBJECTS_TO_SEND = MAX_PACKETS_TO_SEND * OBJECTS_PER_PACKET;
+ if( obj_count > MAX_OBJECTS_TO_SEND )
+ {
+ obj_count = MAX_OBJECTS_TO_SEND;
+ }
+
+ // Create an id to keep the parts of the compound message together
+ LLUUID compound_msg_id;
+ compound_msg_id.generate();
+ LLMessageSystem* msg = gMessageSystem;
+
+ for(S32 i = 0; i < obj_count; ++i)
+ {
+ if( 0 == (i % OBJECTS_PER_PACKET) )
+ {
+ // Start a new message chunk
+ msg->newMessageFast(_PREHASH_RezMultipleAttachmentsFromInv);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_HeaderData);
+ msg->addUUIDFast(_PREHASH_CompoundMsgID, compound_msg_id );
+ msg->addU8Fast(_PREHASH_TotalObjects, obj_count );
+ msg->addBOOLFast(_PREHASH_FirstDetachAll, false );
+ }
+
+ const LLInventoryItem* item = obj_item_array.get(i).get();
+ msg->nextBlockFast(_PREHASH_ObjectData );
+ msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID());
+ msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner());
+ msg->addU8Fast(_PREHASH_AttachmentPt, 0 ); // Wear at the previous or default attachment point
+ pack_permissions_slam(msg, item->getFlags(), item->getPermissions());
+ msg->addStringFast(_PREHASH_Name, item->getName());
+ msg->addStringFast(_PREHASH_Description, item->getDescription());
+
+ if( (i+1 == obj_count) || ((OBJECTS_PER_PACKET-1) == (i % OBJECTS_PER_PACKET)) )
+ {
+ // End of message chunk
+ msg->sendReliable( gAgent.getRegion()->getHost() );
+ }
+ }
+}
+
+void LLAgentWearables::checkWearablesLoaded() const
+{
+#ifdef SHOW_ASSERT
+ U32 item_pend_count = itemUpdatePendingCount();
+ if (mWearablesLoaded)
+ {
+ llassert(item_pend_count==0);
+ }
+#endif
+}
+
+BOOL LLAgentWearables::areWearablesLoaded() const
+{
+ checkWearablesLoaded();
+ return mWearablesLoaded;
+}
+
+// MULTI-WEARABLE: update for multiple indices.
+void LLAgentWearables::updateWearablesLoaded()
+{
+ mWearablesLoaded = (itemUpdatePendingCount()==0);
+}
+
+bool LLAgentWearables::canWearableBeRemoved(const LLWearable* wearable) const
+{
+ if (!wearable) return false;
+
+ EWearableType type = wearable->getType();
+ // Make sure the user always has at least one shape, skin, eyes, and hair type currently worn.
+ return !(((type == WT_SHAPE) || (type == WT_SKIN) || (type == WT_HAIR) || (type == WT_EYES))
+ && (getWearableCount(type) <= 1) );
+}
+void LLAgentWearables::animateAllWearableParams(F32 delta, BOOL upload_bake)
+{
+ for( S32 type = 0; type < WT_COUNT; ++type )
+ {
+ for (S32 count = 0; count < (S32)getWearableCount((EWearableType)type); ++count)
+ {
+ LLWearable *wearable = getWearable((EWearableType)type,count);
+ wearable->animateParams(delta, upload_bake);
+ }
+ }
+}
+
+void LLAgentWearables::updateServer()
+{
+ sendAgentWearablesUpdate();
+ gAgent.sendAgentSetAppearance();
+}
+
+void LLAgentWearables::populateMyOutfitsFolder(void)
+{
+ LLLibraryOutfitsFetch* outfits = new LLLibraryOutfitsFetch();
+
+ // Get the complete information on the items in the inventory and
+ // setup an observer that will wait for that to happen.
+ LLInventoryFetchDescendentsObserver::folder_ref_t folders;
+ outfits->mMyOutfitsID = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
+
+ folders.push_back(outfits->mMyOutfitsID);
+ gInventory.addObserver(outfits);
+ outfits->fetchDescendents(folders);
+ if (outfits->isEverythingComplete())
+ {
+ outfits->done();
+ }
+}
+
+void LLLibraryOutfitsFetch::done()
+{
+ // Delay this until idle() routine, since it's a heavy operation and
+ // we also can't have it run within notifyObservers.
+ doOnIdle(boost::bind(&LLLibraryOutfitsFetch::doneIdle,this));
+ gInventory.removeObserver(this); // Prevent doOnIdle from being added twice.
+}
+
+void LLLibraryOutfitsFetch::doneIdle()
+{
+ gInventory.addObserver(this); // Add this back in since it was taken out during ::done()
+
+ switch (mCurrFetchStep)
+ {
+ case LOFS_FOLDER:
+ folderDone();
+ mCurrFetchStep = LOFS_OUTFITS;
+ break;
+ case LOFS_OUTFITS:
+ outfitsDone();
+ mCurrFetchStep = LOFS_LIBRARY;
+ break;
+ case LOFS_LIBRARY:
+ libraryDone();
+ mCurrFetchStep = LOFS_IMPORTED;
+ break;
+ case LOFS_IMPORTED:
+ importedFolderDone();
+ mCurrFetchStep = LOFS_CONTENTS;
+ break;
+ case LOFS_CONTENTS:
+ contentsDone();
+ break;
+ default:
+ llwarns << "Got invalid state for outfit fetch: " << mCurrFetchStep << llendl;
+ mOutfitsPopulated = TRUE;
+ break;
+ }
+
+ // We're completely done. Cleanup.
+ if (mOutfitsPopulated)
+ {
+ gInventory.removeObserver(this);
+ delete this;
+ return;
+ }
+}
+
+void LLLibraryOutfitsFetch::folderDone(void)
+{
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t wearable_array;
+ gInventory.collectDescendents(mMyOutfitsID, cat_array, wearable_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+
+ // Early out if we already have items in My Outfits.
+ if (cat_array.count() > 0 || wearable_array.count() > 0)
+ {
+ mOutfitsPopulated = true;
+ return;
+ }
+
+ mClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
+ mLibraryClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING, false, true);
+
+ mCompleteFolders.clear();
+
+ // Get the complete information on the items in the inventory.
+ LLInventoryFetchDescendentsObserver::folder_ref_t folders;
+ folders.push_back(mClothingID);
+ folders.push_back(mLibraryClothingID);
+ fetchDescendents(folders);
+ if (isEverythingComplete())
+ {
+ done();
+ }
+}
+
+void LLLibraryOutfitsFetch::outfitsDone(void)
+{
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t wearable_array;
+ LLInventoryFetchDescendentsObserver::folder_ref_t folders;
+
+ // Collect the contents of the Library's Clothing folder
+ gInventory.collectDescendents(mLibraryClothingID, cat_array, wearable_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+
+ llassert(cat_array.count() > 0);
+ for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin();
+ iter != cat_array.end();
+ ++iter)
+ {
+ const LLViewerInventoryCategory *cat = iter->get();
+
+ // Get the names and id's of every outfit in the library, except for ruth and other "misc" outfits.
+ if (cat->getName() != "More Outfits" && cat->getName() != "Ruth")
+ {
+ // Get the name of every outfit in the library
+ folders.push_back(cat->getUUID());
+ mLibraryClothingFolders.push_back(std::make_pair(cat->getUUID(), cat->getName()));
+ }
+ }
+
+ // Collect the contents of your Inventory Clothing folder
+ cat_array.clear();
+ wearable_array.clear();
+ gInventory.collectDescendents(mClothingID, cat_array, wearable_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+
+ // Check if you already have an "Imported Library Clothing" folder
+ for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin();
+ iter != cat_array.end();
+ ++iter)
+ {
+ const LLViewerInventoryCategory *cat = iter->get();
+ if (cat->getName() == mImportedClothingName)
+ {
+ mImportedClothingID = cat->getUUID();
+ }
+ }
+
+ mCompleteFolders.clear();
+
+ fetchDescendents(folders);
+ if (isEverythingComplete())
+ {
+ done();
+ }
+}
+
+class LLLibraryOutfitsCopyDone: public LLInventoryCallback
+{
+public:
+ LLLibraryOutfitsCopyDone(LLLibraryOutfitsFetch * fetcher):
+ mFireCount(0), mLibraryOutfitsFetcher(fetcher)
+ {
+ }
+
+ virtual ~LLLibraryOutfitsCopyDone()
+ {
+ if (mLibraryOutfitsFetcher)
+ {
+ gInventory.addObserver(mLibraryOutfitsFetcher);
+ mLibraryOutfitsFetcher->done();
+ }
+ }
+
+ /* virtual */ void fire(const LLUUID& inv_item)
+ {
+ mFireCount++;
+ }
+private:
+ U32 mFireCount;
+ LLLibraryOutfitsFetch * mLibraryOutfitsFetcher;
+};
+
+void LLLibraryOutfitsFetch::libraryDone(void)
+{
+ // Copy the clothing folders from the library into the imported clothing folder if necessary.
+ if (mImportedClothingID == LLUUID::null)
+ {
+ gInventory.removeObserver(this);
+ LLPointer<LLInventoryCallback> copy_waiter = new LLLibraryOutfitsCopyDone(this);
+ mImportedClothingID = gInventory.createNewCategory(mClothingID,
+ LLFolderType::FT_NONE,
+ mImportedClothingName);
+
+ for (cloth_folder_vec_t::const_iterator iter = mLibraryClothingFolders.begin();
+ iter != mLibraryClothingFolders.end();
+ ++iter)
+ {
+ LLUUID folder_id = gInventory.createNewCategory(mImportedClothingID,
+ LLFolderType::FT_NONE,
+ iter->second);
+ LLAppearanceManager::getInstance()->shallowCopyCategory(iter->first, folder_id, copy_waiter);
+ }
+ }
+ else
+ {
+ // Skip straight to fetching the contents of the imported folder
+ importedFolderFetch();
+ }
+}
+
+void LLLibraryOutfitsFetch::importedFolderFetch(void)
+{
+ // Fetch the contents of the Imported Clothing Folder
+ LLInventoryFetchDescendentsObserver::folder_ref_t folders;
+ folders.push_back(mImportedClothingID);
+
+ mCompleteFolders.clear();
+
+ fetchDescendents(folders);
+ if (isEverythingComplete())
+ {
+ done();
+ }
+}
+
+void LLLibraryOutfitsFetch::importedFolderDone(void)
+{
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t wearable_array;
+ LLInventoryFetchDescendentsObserver::folder_ref_t folders;
+
+ // Collect the contents of the Imported Clothing folder
+ gInventory.collectDescendents(mImportedClothingID, cat_array, wearable_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+
+ for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin();
+ iter != cat_array.end();
+ ++iter)
+ {
+ const LLViewerInventoryCategory *cat = iter->get();
+
+ // Get the name of every imported outfit
+ folders.push_back(cat->getUUID());
+ mImportedClothingFolders.push_back(std::make_pair(cat->getUUID(), cat->getName()));
+ }
+
+ mCompleteFolders.clear();
+ fetchDescendents(folders);
+ if (isEverythingComplete())
+ {
+ done();
+ }
+}
+
+void LLLibraryOutfitsFetch::contentsDone(void)
+{
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t wearable_array;
+
+ for (cloth_folder_vec_t::const_iterator folder_iter = mImportedClothingFolders.begin();
+ folder_iter != mImportedClothingFolders.end();
+ ++folder_iter)
+ {
+ // First, make a folder in the My Outfits directory.
+ LLUUID new_outfit_folder_id = gInventory.createNewCategory(mMyOutfitsID, LLFolderType::FT_OUTFIT, folder_iter->second);
+
+ cat_array.clear();
+ wearable_array.clear();
+ // Collect the contents of each imported clothing folder, so we can create new outfit links for it
+ gInventory.collectDescendents(folder_iter->first, cat_array, wearable_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+
+ for (LLInventoryModel::item_array_t::const_iterator wearable_iter = wearable_array.begin();
+ wearable_iter != wearable_array.end();
+ ++wearable_iter)
+ {
+ const LLViewerInventoryItem *item = wearable_iter->get();
+ link_inventory_item(gAgent.getID(),
+ item->getLinkedUUID(),
+ new_outfit_folder_id,
+ item->getName(),
+ LLAssetType::AT_LINK,
+ NULL);
+ }
+ }
+
+ mOutfitsPopulated = true;
+}
+
+//--------------------------------------------------------------------
+// InitialWearablesFetch
+//
+// This grabs contents from the COF and processes them.
+// The processing is handled in idle(), i.e. outside of done(),
+// to avoid gInventory.notifyObservers recursion.
+//--------------------------------------------------------------------
+
+LLInitialWearablesFetch::~LLInitialWearablesFetch()
+{
+}
+
+// virtual
+void LLInitialWearablesFetch::done()
+{
+ // Delay processing the actual results of this so it's not handled within
+ // gInventory.notifyObservers. The results will be handled in the next
+ // idle tick instead.
+ gInventory.removeObserver(this);
+ doOnIdle(boost::bind(&LLInitialWearablesFetch::processContents,this));
+}
+
+void LLInitialWearablesFetch::processContents()
+{
+ // Fetch the wearable items from the Current Outfit Folder
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t wearable_array;
+ LLFindWearables is_wearable;
+ gInventory.collectDescendentsIf(mCompleteFolders.front(), cat_array, wearable_array,
+ LLInventoryModel::EXCLUDE_TRASH, is_wearable);
+
+ LLAppearanceManager::instance().setAttachmentInvLinkEnable(true);
+ if (wearable_array.count() > 0)
+ {
+ LLAppearanceManager::instance().updateAppearanceFromCOF();
+ }
+ else
+ {
+ // if we're constructing the COF from the wearables message, we don't have a proper outfit link
+ LLAppearanceManager::instance().setOutfitDirty(true);
+ processWearablesMessage();
+ }
+ delete this;
+}
+
+class LLFetchAndLinkObserver: public LLInventoryFetchObserver
+{
+public:
+ LLFetchAndLinkObserver(LLInventoryFetchObserver::item_ref_t& ids):
+ m_ids(ids),
+ LLInventoryFetchObserver(true)
+ {
+ }
+ ~LLFetchAndLinkObserver()
+ {
+ }
+ virtual void done()
+ {
+ gInventory.removeObserver(this);
+ // Link to all fetched items in COF.
+ for (LLInventoryFetchObserver::item_ref_t::iterator it = m_ids.begin();
+ it != m_ids.end();
+ ++it)
+ {
+ LLUUID id = *it;
+ LLViewerInventoryItem *item = gInventory.getItem(*it);
+ if (!item)
+ {
+ llwarns << "fetch failed!" << llendl;
+ continue;
+ }
+ link_inventory_item(gAgent.getID(), item->getLinkedUUID(), LLAppearanceManager::instance().getCOF(), item->getName(),
+ LLAssetType::AT_LINK, LLPointer<LLInventoryCallback>(NULL));
+ }
+ }
+private:
+ LLInventoryFetchObserver::item_ref_t m_ids;
+};
+
+void LLInitialWearablesFetch::processWearablesMessage()
+{
+ if (!mAgentInitialWearables.empty()) // We have an empty current outfit folder, use the message data instead.
+ {
+ const LLUUID current_outfit_id = LLAppearanceManager::instance().getCOF();
+ LLInventoryFetchObserver::item_ref_t ids;
+ for (U8 i = 0; i < mAgentInitialWearables.size(); ++i)
+ {
+ // Populate the current outfit folder with links to the wearables passed in the message
+ InitialWearableData *wearable_data = new InitialWearableData(mAgentInitialWearables[i]); // This will be deleted in the callback.
+
+ if (wearable_data->mAssetID.notNull())
+ {
+#ifdef USE_CURRENT_OUTFIT_FOLDER
+ ids.push_back(wearable_data->mItemID);
+#endif
+ // Fetch the wearables
+ LLWearableList::instance().getAsset(wearable_data->mAssetID,
+ LLStringUtil::null,
+ LLWearableDictionary::getAssetType(wearable_data->mType),
+ LLAgentWearables::onInitialWearableAssetArrived, (void*)(wearable_data));
+ }
+ else
+ {
+ llinfos << "Invalid wearable, type " << wearable_data->mType << " itemID "
+ << wearable_data->mItemID << " assetID " << wearable_data->mAssetID << llendl;
+ }
+ }
+
+ // Add all current attachments to the requested items as well.
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if( avatar )
+ {
+ for (LLVOAvatar::attachment_map_t::const_iterator iter = avatar->mAttachmentPoints.begin();
+ iter != avatar->mAttachmentPoints.end(); ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+ if (!attachment) continue;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject* attached_object = (*attachment_iter);
+ if (!attached_object) continue;
+ const LLUUID& item_id = attached_object->getItemID();
+ if (item_id.isNull()) continue;
+ ids.push_back(item_id);
+ }
+ }
+ }
+
+ // Need to fetch the inventory items for ids, then create links to them after they arrive.
+ LLFetchAndLinkObserver *fetcher = new LLFetchAndLinkObserver(ids);
+ fetcher->fetchItems(ids);
+ // If no items to be fetched, done will never be triggered.
+ // TODO: Change LLInventoryFetchObserver::fetchItems to trigger done() on this condition.
+ if (fetcher->isEverythingComplete())
+ {
+ fetcher->done();
+ }
+ else
+ {
+ gInventory.addObserver(fetcher);
+ }
+ }
+ else
+ {
+ LL_WARNS("Wearables") << "No current outfit folder items found and no initial wearables fallback message received." << LL_ENDL;
+ }
+}
+
+
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
new file mode 100644
index 0000000000..b4f58674af
--- /dev/null
+++ b/indra/newview/llagentwearables.h
@@ -0,0 +1,276 @@
+/**
+ * @file llagentwearables.h
+ * @brief LLAgentWearables class header file
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLAGENTWEARABLES_H
+#define LL_LLAGENTWEARABLES_H
+
+#include "llmemory.h"
+#include "lluuid.h"
+#include "llinventory.h"
+#include "llinventorymodel.h"
+#include "llviewerinventory.h"
+#include "llvoavatardefines.h"
+
+class LLInventoryItem;
+class LLVOAvatarSelf;
+class LLWearable;
+class LLInitialWearablesFetch;
+class LLViewerObject;
+class LLTexLayerTemplate;
+
+class LLAgentWearables
+{
+ //--------------------------------------------------------------------
+ // Constructors / destructors / Initializers
+ //--------------------------------------------------------------------
+public:
+ friend class LLInitialWearablesFetch;
+
+ LLAgentWearables();
+ virtual ~LLAgentWearables();
+ void setAvatarObject(LLVOAvatarSelf *avatar);
+ void createStandardWearables(BOOL female);
+ void cleanup();
+ void dump();
+protected:
+ // MULTI-WEARABLE: assuming one per type. Type is called index - rename.
+ void createStandardWearablesDone(S32 type, U32 index/* = 0*/);
+ void createStandardWearablesAllDone();
+
+ //--------------------------------------------------------------------
+ // Queries
+ //--------------------------------------------------------------------
+public:
+ BOOL isWearingItem(const LLUUID& item_id) const;
+ BOOL isWearableModifiable(EWearableType type, U32 index /*= 0*/) const;
+ BOOL isWearableCopyable(EWearableType type, U32 index /*= 0*/) const;
+ BOOL areWearablesLoaded() const;
+ void updateWearablesLoaded();
+ void checkWearablesLoaded() const;
+
+ // Note: False for shape, skin, eyes, and hair, unless you have MORE than 1.
+ bool canWearableBeRemoved(const LLWearable* wearable) const;
+
+ void animateAllWearableParams(F32 delta, BOOL upload_bake);
+
+ //--------------------------------------------------------------------
+ // Accessors
+ //--------------------------------------------------------------------
+public:
+ const LLUUID getWearableItemID(EWearableType type, U32 index /*= 0*/) const;
+ const LLUUID getWearableAssetID(EWearableType type, U32 index /*= 0*/) const;
+ const LLWearable* getWearableFromItemID(const LLUUID& item_id) const;
+ const LLWearable* getWearableFromAssetID(const LLUUID& asset_id) const;
+ LLInventoryItem* getWearableInventoryItem(EWearableType type, U32 index /*= 0*/);
+ // MULTI-WEARABLE: assuming one per type.
+ static BOOL selfHasWearable(EWearableType type);
+ LLWearable* getWearable(const EWearableType type, U32 index /*= 0*/);
+ const LLWearable* getWearable(const EWearableType type, U32 index /*= 0*/) const;
+ LLWearable* getTopWearable(const EWearableType type);
+ U32 getWearableCount(const EWearableType type) const;
+ U32 getWearableCount(const U32 tex_index) const;
+
+ //--------------------------------------------------------------------
+ // Setters
+ //--------------------------------------------------------------------
+
+private:
+ // Low-level data structure setter - public access is via setWearableItem, etc.
+ void setWearable(const EWearableType type, U32 index, LLWearable *wearable);
+ U32 pushWearable(const EWearableType type, LLWearable *wearable);
+ void wearableUpdated(LLWearable *wearable);
+ void popWearable(LLWearable *wearable);
+ void popWearable(const EWearableType type, U32 index);
+
+public:
+ void setWearableItem(LLInventoryItem* new_item, LLWearable* wearable, bool do_append = false);
+ void setWearableOutfit(const LLInventoryItem::item_array_t& items, const LLDynamicArray< LLWearable* >& wearables, BOOL remove);
+ void setWearableName(const LLUUID& item_id, const std::string& new_name);
+ void addLocalTextureObject(const EWearableType wearable_type, const LLVOAvatarDefines::ETextureIndex texture_type, U32 wearable_index);
+ U32 getWearableIndex(LLWearable *wearable);
+
+protected:
+ void setWearableFinal(LLInventoryItem* new_item, LLWearable* new_wearable, bool do_append = false);
+ static bool onSetWearableDialog(const LLSD& notification, const LLSD& response, LLWearable* wearable);
+
+ void addWearableToAgentInventory(LLPointer<LLInventoryCallback> cb,
+ LLWearable* wearable,
+ const LLUUID& category_id = LLUUID::null,
+ BOOL notify = TRUE);
+ void addWearabletoAgentInventoryDone(const S32 type,
+ const U32 index,
+ const LLUUID& item_id,
+ LLWearable* wearable);
+ void recoverMissingWearable(const EWearableType type, U32 index /*= 0*/);
+ void recoverMissingWearableDone();
+
+ //--------------------------------------------------------------------
+ // Removing wearables
+ //--------------------------------------------------------------------
+public:
+ void removeWearable(const EWearableType type, bool do_remove_all /*= false*/, U32 index /*= 0*/);
+private:
+ void removeWearableFinal(const EWearableType type, bool do_remove_all /*= false*/, U32 index /*= 0*/);
+protected:
+ static bool onRemoveWearableDialog(const LLSD& notification, const LLSD& response);
+ static void userRemoveAllClothesStep2(BOOL proceed); // userdata is NULL
+
+ //--------------------------------------------------------------------
+ // Server Communication
+ //--------------------------------------------------------------------
+public:
+ // Processes the initial wearables update message (if necessary, since the outfit folder makes it redundant)
+ static void processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data);
+protected:
+ void sendAgentWearablesUpdate();
+ void sendAgentWearablesRequest();
+ void queryWearableCache();
+ void updateServer();
+ static void onInitialWearableAssetArrived(LLWearable* wearable, void* userdata);
+
+ //--------------------------------------------------------------------
+ // Outfits
+ //--------------------------------------------------------------------
+public:
+ void getAllWearablesArray(LLDynamicArray<S32>& wearables);
+
+ // Note: wearables_to_include should be a list of EWearableType types
+ // attachments_to_include should be a list of attachment points
+ void makeNewOutfit(const std::string& new_folder_name,
+ const LLDynamicArray<S32>& wearables_to_include,
+ const LLDynamicArray<S32>& attachments_to_include,
+ BOOL rename_clothing);
+
+ LLUUID makeNewOutfitLinks(const std::string& new_folder_name);
+
+ // Should only be called if we *know* we've never done so before, since users may
+ // not want the Library outfits to stay in their quick outfit selector and can delete them.
+ void populateMyOutfitsFolder(void);
+
+private:
+ void makeNewOutfitDone(S32 type, U32 index);
+
+ //--------------------------------------------------------------------
+ // Save Wearables
+ //--------------------------------------------------------------------
+public:
+ // MULTI-WEARABLE: assumes one per type.
+ void saveWearableAs(const EWearableType type, const U32 index, const std::string& new_name, BOOL save_in_lost_and_found);
+ void saveWearable(const EWearableType type, const U32 index, BOOL send_update = TRUE);
+ void saveAllWearables();
+ void revertWearable(const EWearableType type, const U32 index);
+
+ //--------------------------------------------------------------------
+ // Static UI hooks
+ //--------------------------------------------------------------------
+public:
+ // MULTI-WEARABLE: assuming one wearable per type. Need upstream changes.
+ static void userRemoveWearable(EWearableType& type);
+ static void userRemoveAllClothes();
+
+ typedef std::vector<LLViewerObject*> llvo_vec_t;
+
+ static void userUpdateAttachments(LLInventoryModel::item_array_t& obj_item_array);
+ static void userRemoveMultipleAttachments(llvo_vec_t& llvo_array);
+ static void userRemoveAllAttachments();
+ static void userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array);
+
+ BOOL itemUpdatePending(const LLUUID& item_id) const;
+ U32 itemUpdatePendingCount() const;
+
+ //--------------------------------------------------------------------
+ // Member variables
+ //--------------------------------------------------------------------
+private:
+ typedef std::vector<LLWearable*> wearableentry_vec_t; // all wearables of a certain type (EG all shirts)
+ typedef std::map<EWearableType, wearableentry_vec_t> wearableentry_map_t; // wearable "categories" arranged by wearable type
+ wearableentry_map_t mWearableDatas;
+
+ static BOOL mInitialWearablesUpdateReceived;
+ BOOL mWearablesLoaded;
+ std::set<LLUUID> mItemsAwaitingWearableUpdate;
+ LLPointer<LLVOAvatarSelf> mAvatarObject; // NULL until avatar object sent down from simulator
+
+ //--------------------------------------------------------------------------------
+ // Support classes
+ //--------------------------------------------------------------------------------
+private:
+ class createStandardWearablesAllDoneCallback : public LLRefCount
+ {
+ protected:
+ ~createStandardWearablesAllDoneCallback();
+ };
+ class sendAgentWearablesUpdateCallback : public LLRefCount
+ {
+ protected:
+ ~sendAgentWearablesUpdateCallback();
+ };
+
+ class addWearableToAgentInventoryCallback : public LLInventoryCallback
+ {
+ public:
+ enum EType
+ {
+ CALL_NONE = 0,
+ CALL_UPDATE = 1,
+ CALL_RECOVERDONE = 2,
+ CALL_CREATESTANDARDDONE = 4,
+ CALL_MAKENEWOUTFITDONE = 8
+ };
+
+ // MULTI-WEARABLE: index is an EWearableType - more confusing usage.
+ // MULTI-WEARABLE: need to have type and index args both?
+ addWearableToAgentInventoryCallback(LLPointer<LLRefCount> cb,
+ S32 type,
+ U32 index,
+ LLWearable* wearable,
+ U32 todo = CALL_NONE);
+ virtual void fire(const LLUUID& inv_item);
+ private:
+ S32 mType;
+ U32 mIndex;
+ LLWearable* mWearable;
+ U32 mTodo;
+ LLPointer<LLRefCount> mCB;
+ };
+
+ static const U32 MAX_WEARABLES_PER_TYPE = 1;
+
+}; // LLAgentWearables
+
+extern LLAgentWearables gAgentWearables;
+
+//--------------------------------------------------------------------
+// Types
+//--------------------------------------------------------------------
+
+#endif // LL_AGENTWEARABLES_H
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
new file mode 100644
index 0000000000..03180b6a9d
--- /dev/null
+++ b/indra/newview/llappearancemgr.cpp
@@ -0,0 +1,1333 @@
+/**
+ * @file llappearancemgr.cpp
+ * @brief Manager for initiating appearance changes on the viewer
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llagent.h"
+#include "llagentwearables.h"
+#include "llappearancemgr.h"
+#include "llfloatercustomize.h"
+#include "llgesturemgr.h"
+#include "llinventorybridge.h"
+#include "llinventoryobserver.h"
+#include "llnotificationsutil.h"
+#include "llsidepanelappearance.h"
+#include "llsidetray.h"
+#include "llvoavatar.h"
+#include "llvoavatarself.h"
+#include "llviewerregion.h"
+#include "llwearablelist.h"
+
+class LLWearInventoryCategoryCallback : public LLInventoryCallback
+{
+public:
+ LLWearInventoryCategoryCallback(const LLUUID& cat_id, bool append)
+ {
+ mCatID = cat_id;
+ mAppend = append;
+ }
+ void fire(const LLUUID& item_id)
+ {
+ /*
+ * Do nothing. We only care about the destructor
+ *
+ * The reason for this is that this callback is used in a hack where the
+ * same callback is given to dozens of items, and the destructor is called
+ * after the last item has fired the event and dereferenced it -- if all
+ * the events actually fire!
+ */
+ }
+
+protected:
+ ~LLWearInventoryCategoryCallback()
+ {
+ // Is the destructor called by ordinary dereference, or because the app's shutting down?
+ // If the inventory callback manager goes away, we're shutting down, no longer want the callback.
+ if( LLInventoryCallbackManager::is_instantiated() )
+ {
+ LLAppearanceManager::instance().wearInventoryCategoryOnAvatar(gInventory.getCategory(mCatID), mAppend);
+ }
+ else
+ {
+ llwarns << "Dropping unhandled LLWearInventoryCategoryCallback" << llendl;
+ }
+ }
+
+private:
+ LLUUID mCatID;
+ bool mAppend;
+};
+
+class LLOutfitObserver : public LLInventoryFetchObserver
+{
+public:
+ LLOutfitObserver(const LLUUID& cat_id, bool copy_items, bool append) :
+ mCatID(cat_id),
+ mCopyItems(copy_items),
+ mAppend(append)
+ {}
+ ~LLOutfitObserver() {}
+ virtual void done();
+ void doWearCategory();
+
+protected:
+ LLUUID mCatID;
+ bool mCopyItems;
+ bool mAppend;
+};
+
+void LLOutfitObserver::done()
+{
+ gInventory.removeObserver(this);
+ doOnIdle(boost::bind(&LLOutfitObserver::doWearCategory,this));
+}
+
+void LLOutfitObserver::doWearCategory()
+{
+ // We now have an outfit ready to be copied to agent inventory. Do
+ // it, and wear that outfit normally.
+ if(mCopyItems)
+ {
+ LLInventoryCategory* cat = gInventory.getCategory(mCatID);
+ std::string name;
+ if(!cat)
+ {
+ // should never happen.
+ name = "New Outfit";
+ }
+ else
+ {
+ name = cat->getName();
+ }
+ LLViewerInventoryItem* item = NULL;
+ item_ref_t::iterator it = mComplete.begin();
+ item_ref_t::iterator end = mComplete.end();
+ LLUUID pid;
+ for(; it < end; ++it)
+ {
+ item = (LLViewerInventoryItem*)gInventory.getItem(*it);
+ if(item)
+ {
+ if(LLInventoryType::IT_GESTURE == item->getInventoryType())
+ {
+ pid = gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE);
+ }
+ else
+ {
+ pid = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
+ }
+ break;
+ }
+ }
+ if(pid.isNull())
+ {
+ pid = gInventory.getRootFolderID();
+ }
+
+ LLUUID cat_id = gInventory.createNewCategory(
+ pid,
+ LLFolderType::FT_NONE,
+ name);
+ mCatID = cat_id;
+ LLPointer<LLInventoryCallback> cb = new LLWearInventoryCategoryCallback(mCatID, mAppend);
+ it = mComplete.begin();
+ for(; it < end; ++it)
+ {
+ item = (LLViewerInventoryItem*)gInventory.getItem(*it);
+ if(item)
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ cat_id,
+ std::string(),
+ cb);
+ }
+ }
+ // BAP fixes a lag in display of created dir.
+ gInventory.notifyObservers();
+ }
+ else
+ {
+ // Wear the inventory category.
+ LLAppearanceManager::instance().wearInventoryCategoryOnAvatar(gInventory.getCategory(mCatID), mAppend);
+ }
+ delete this;
+}
+
+class LLOutfitFetch : public LLInventoryFetchDescendentsObserver
+{
+public:
+ LLOutfitFetch(bool copy_items, bool append) : mCopyItems(copy_items), mAppend(append) {}
+ ~LLOutfitFetch() {}
+ virtual void done();
+protected:
+ bool mCopyItems;
+ bool mAppend;
+};
+
+void LLOutfitFetch::done()
+{
+ // What we do here is get the complete information on the items in
+ // the library, and set up an observer that will wait for that to
+ // happen.
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ gInventory.collectDescendents(mCompleteFolders.front(),
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+ S32 count = item_array.count();
+ if(!count)
+ {
+ llwarns << "Nothing fetched in category " << mCompleteFolders.front()
+ << llendl;
+ //dec_busy_count();
+ gInventory.removeObserver(this);
+ delete this;
+ return;
+ }
+
+ LLOutfitObserver* outfit_observer = new LLOutfitObserver(mCompleteFolders.front(), mCopyItems, mAppend);
+ LLInventoryFetchObserver::item_ref_t ids;
+ for(S32 i = 0; i < count; ++i)
+ {
+ ids.push_back(item_array.get(i)->getUUID());
+ }
+
+ // clean up, and remove this as an observer since the call to the
+ // outfit could notify observers and throw us into an infinite
+ // loop.
+ //dec_busy_count();
+ gInventory.removeObserver(this);
+
+ // increment busy count and either tell the inventory to check &
+ // call done, or add this object to the inventory for observation.
+ //inc_busy_count();
+
+ // do the fetch
+ outfit_observer->fetchItems(ids);
+ if(outfit_observer->isEverythingComplete())
+ {
+ // everything is already here - call done.
+ outfit_observer->done();
+ }
+ else
+ {
+ // it's all on it's way - add an observer, and the inventory
+ // will call done for us when everything is here.
+ gInventory.addObserver(outfit_observer);
+ }
+ delete this;
+}
+
+class LLUpdateAppearanceOnDestroy: public LLInventoryCallback
+{
+public:
+ LLUpdateAppearanceOnDestroy():
+ mFireCount(0)
+ {
+ }
+
+ virtual ~LLUpdateAppearanceOnDestroy()
+ {
+ LLAppearanceManager::instance().updateAppearanceFromCOF();
+ }
+
+ /* virtual */ void fire(const LLUUID& inv_item)
+ {
+ mFireCount++;
+ }
+private:
+ U32 mFireCount;
+};
+
+struct LLFoundData
+{
+ LLFoundData() {}
+ LLFoundData(const LLUUID& item_id,
+ const LLUUID& asset_id,
+ const std::string& name,
+ LLAssetType::EType asset_type) :
+ mItemID(item_id),
+ mAssetID(asset_id),
+ mName(name),
+ mAssetType(asset_type),
+ mWearable( NULL ) {}
+
+ LLUUID mItemID;
+ LLUUID mAssetID;
+ std::string mName;
+ LLAssetType::EType mAssetType;
+ LLWearable* mWearable;
+};
+
+
+class LLWearableHoldingPattern
+{
+public:
+ LLWearableHoldingPattern();
+ ~LLWearableHoldingPattern();
+
+ bool pollCompletion();
+ bool isDone();
+ bool isTimedOut();
+
+ typedef std::list<LLFoundData> found_list_t;
+ found_list_t mFoundList;
+ LLInventoryModel::item_array_t mObjItems;
+ LLInventoryModel::item_array_t mGestItems;
+ S32 mResolved;
+ LLTimer mWaitTime;
+};
+
+LLWearableHoldingPattern::LLWearableHoldingPattern():
+ mResolved(0)
+{
+}
+
+LLWearableHoldingPattern::~LLWearableHoldingPattern()
+{
+}
+
+bool LLWearableHoldingPattern::isDone()
+{
+ if (mResolved >= (S32)mFoundList.size())
+ return true; // have everything we were waiting for
+ else if (isTimedOut())
+ {
+ llwarns << "Exceeded max wait time, updating appearance based on what has arrived" << llendl;
+ return true;
+ }
+ return false;
+
+}
+
+bool LLWearableHoldingPattern::isTimedOut()
+{
+ static F32 max_wait_time = 15.0; // give up if wearable fetches haven't completed in max_wait_time seconds.
+ return mWaitTime.getElapsedTimeF32() > max_wait_time;
+}
+
+bool LLWearableHoldingPattern::pollCompletion()
+{
+ bool done = isDone();
+ llinfos << "polling, done status: " << done << " elapsed " << mWaitTime.getElapsedTimeF32() << llendl;
+ if (done)
+ {
+ // Activate all gestures in this folder
+ if (mGestItems.count() > 0)
+ {
+ llinfos << "Activating " << mGestItems.count() << " gestures" << llendl;
+
+ LLGestureManager::instance().activateGestures(mGestItems);
+
+ // Update the inventory item labels to reflect the fact
+ // they are active.
+ LLViewerInventoryCategory* catp =
+ gInventory.getCategory(LLAppearanceManager::instance().getCOF());
+
+ if (catp)
+ {
+ gInventory.updateCategory(catp);
+ gInventory.notifyObservers();
+ }
+ }
+
+ // Update wearables.
+ llinfos << "Updating agent wearables with " << mResolved << " wearable items " << llendl;
+ LLAppearanceManager::instance().updateAgentWearables(this, false);
+
+ // Update attachments to match those requested.
+ LLVOAvatar* avatar = gAgent.getAvatarObject();
+ if( avatar )
+ {
+ llinfos << "Updating " << mObjItems.count() << " attachments" << llendl;
+ LLAgentWearables::userUpdateAttachments(mObjItems);
+ }
+
+ delete this;
+ }
+ return done;
+}
+
+static void removeDuplicateItems(LLInventoryModel::item_array_t& items)
+{
+ LLInventoryModel::item_array_t new_items;
+ std::set<LLUUID> items_seen;
+ std::deque<LLViewerInventoryItem*> tmp_list;
+ // Traverse from the front and keep the first of each item
+ // encountered, so we actually keep the *last* of each duplicate
+ // item. This is needed to give the right priority when adding
+ // duplicate items to an existing outfit.
+ for (S32 i=items.count()-1; i>=0; i--)
+ {
+ LLViewerInventoryItem *item = items.get(i);
+ LLUUID item_id = item->getLinkedUUID();
+ if (items_seen.find(item_id)!=items_seen.end())
+ continue;
+ items_seen.insert(item_id);
+ tmp_list.push_front(item);
+ }
+ for (std::deque<LLViewerInventoryItem*>::iterator it = tmp_list.begin();
+ it != tmp_list.end();
+ ++it)
+ {
+ new_items.put(*it);
+ }
+ items = new_items;
+}
+
+static void onWearableAssetFetch(LLWearable* wearable, void* data)
+{
+ LLWearableHoldingPattern* holder = (LLWearableHoldingPattern*)data;
+
+ if(wearable)
+ {
+ for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->mFoundList.begin();
+ iter != holder->mFoundList.end(); ++iter)
+ {
+ LLFoundData& data = *iter;
+ if(wearable->getAssetID() == data.mAssetID)
+ {
+ data.mWearable = wearable;
+ break;
+ }
+ }
+ }
+ holder->mResolved += 1;
+}
+
+const LLUUID LLAppearanceManager::getCOF() const
+{
+ return gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
+}
+
+
+const LLViewerInventoryItem* LLAppearanceManager::getBaseOutfitLink()
+{
+ const LLUUID& current_outfit_cat = getCOF();
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ // Can't search on FT_OUTFIT since links to categories return FT_CATEGORY for type since they don't
+ // return preferred type.
+ LLIsType is_category( LLAssetType::AT_CATEGORY );
+ gInventory.collectDescendentsIf(current_outfit_cat,
+ cat_array,
+ item_array,
+ false,
+ is_category,
+ false);
+ for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin();
+ iter != item_array.end();
+ iter++)
+ {
+ const LLViewerInventoryItem *item = (*iter);
+ const LLViewerInventoryCategory *cat = item->getLinkedCategory();
+ if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT)
+ {
+ return item;
+ }
+ }
+ return NULL;
+}
+
+bool LLAppearanceManager::getBaseOutfitName(std::string& name)
+{
+ const LLViewerInventoryItem* outfit_link = getBaseOutfitLink();
+ if(outfit_link)
+ {
+ const LLViewerInventoryCategory *cat = outfit_link->getLinkedCategory();
+ if (cat)
+ {
+ name = cat->getName();
+ return true;
+ }
+ }
+ return false;
+}
+
+// Update appearance from outfit folder.
+void LLAppearanceManager::changeOutfit(bool proceed, const LLUUID& category, bool append)
+{
+ if (!proceed)
+ return;
+ LLAppearanceManager::instance().updateCOF(category,append);
+}
+
+void LLAppearanceManager::shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
+ LLPointer<LLInventoryCallback> cb)
+{
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ gInventory.collectDescendents(src_id, cats, items,
+ LLInventoryModel::EXCLUDE_TRASH);
+ for (S32 i = 0; i < items.count(); ++i)
+ {
+ const LLViewerInventoryItem* item = items.get(i).get();
+ if (item->getActualType() == LLAssetType::AT_LINK)
+ {
+ link_inventory_item(gAgent.getID(),
+ item->getLinkedUUID(),
+ dst_id,
+ item->getName(),
+ LLAssetType::AT_LINK, cb);
+ }
+ else if (item->getActualType() == LLAssetType::AT_LINK_FOLDER)
+ {
+ LLViewerInventoryCategory *catp = item->getLinkedCategory();
+ // Skip copying outfit links.
+ if (catp && catp->getPreferredType() != LLFolderType::FT_OUTFIT)
+ {
+ link_inventory_item(gAgent.getID(),
+ item->getLinkedUUID(),
+ dst_id,
+ item->getName(),
+ LLAssetType::AT_LINK_FOLDER, cb);
+ }
+ }
+ else
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ dst_id,
+ item->getName(),
+ cb);
+ }
+ }
+}
+
+void LLAppearanceManager::purgeBaseOutfitLink(const LLUUID& category)
+{
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ gInventory.collectDescendents(category, cats, items,
+ LLInventoryModel::EXCLUDE_TRASH);
+ for (S32 i = 0; i < items.count(); ++i)
+ {
+ LLViewerInventoryItem *item = items.get(i);
+ if (item->getActualType() != LLAssetType::AT_LINK_FOLDER)
+ continue;
+ if (item->getIsLinkType())
+ {
+ LLViewerInventoryCategory* catp = item->getLinkedCategory();
+ if(catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT)
+ {
+ gInventory.purgeObject(item->getUUID());
+ }
+ }
+ }
+}
+
+void LLAppearanceManager::purgeCategory(const LLUUID& category, bool keep_outfit_links)
+{
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ gInventory.collectDescendents(category, cats, items,
+ LLInventoryModel::EXCLUDE_TRASH);
+ for (S32 i = 0; i < items.count(); ++i)
+ {
+ LLViewerInventoryItem *item = items.get(i);
+ if (keep_outfit_links && (item->getActualType() == LLAssetType::AT_LINK_FOLDER))
+ continue;
+ if (item->getIsLinkType())
+ {
+ gInventory.purgeObject(item->getUUID());
+ }
+ }
+}
+
+// Keep the last N wearables of each type. For viewer 2.0, N is 1 for
+// both body parts and clothing items.
+void LLAppearanceManager::filterWearableItems(
+ LLInventoryModel::item_array_t& items, S32 max_per_type)
+{
+ // Divvy items into arrays by wearable type.
+ std::vector<LLInventoryModel::item_array_t> items_by_type(WT_COUNT);
+ for (S32 i=0; i<items.count(); i++)
+ {
+ LLViewerInventoryItem *item = items.get(i);
+ // Ignore non-wearables.
+ if (!item->isWearableType())
+ continue;
+ EWearableType type = item->getWearableType();
+ items_by_type[type].push_back(item);
+ }
+
+ // rebuild items list, retaining the last max_per_type of each array
+ items.clear();
+ for (S32 i=0; i<WT_COUNT; i++)
+ {
+ S32 size = items_by_type[i].size();
+ if (size <= 0)
+ continue;
+ S32 start_index = llmax(0,size-max_per_type);
+ for (S32 j = start_index; j<size; j++)
+ {
+ items.push_back(items_by_type[i][j]);
+ }
+ }
+}
+
+// Create links to all listed items.
+void LLAppearanceManager::linkAll(const LLUUID& category,
+ LLInventoryModel::item_array_t& items,
+ LLPointer<LLInventoryCallback> cb)
+{
+ for (S32 i=0; i<items.count(); i++)
+ {
+ const LLInventoryItem* item = items.get(i).get();
+ link_inventory_item(gAgent.getID(),
+ item->getLinkedUUID(),
+ category,
+ item->getName(),
+ LLAssetType::AT_LINK,
+ cb);
+ }
+}
+
+void LLAppearanceManager::updateCOF(const LLUUID& category, bool append)
+{
+ const LLUUID cof = getCOF();
+
+ // Deactivate currently active gestures in the COF, if replacing outfit
+ if (!append)
+ {
+ LLInventoryModel::item_array_t gest_items;
+ getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE, false);
+ for(S32 i = 0; i < gest_items.count(); ++i)
+ {
+ LLViewerInventoryItem *gest_item = gest_items.get(i);
+ if ( LLGestureManager::instance().isGestureActive( gest_item->getLinkedUUID()) )
+ {
+ LLGestureManager::instance().deactivateGesture( gest_item->getLinkedUUID() );
+ }
+ }
+ }
+
+ // Collect and filter descendents to determine new COF contents.
+
+ // - Body parts: always include COF contents as a fallback in case any
+ // required parts are missing.
+ LLInventoryModel::item_array_t body_items;
+ getDescendentsOfAssetType(cof, body_items, LLAssetType::AT_BODYPART, false);
+ getDescendentsOfAssetType(category, body_items, LLAssetType::AT_BODYPART, false);
+ // Reduce body items to max of one per type.
+ removeDuplicateItems(body_items);
+ filterWearableItems(body_items, 1);
+
+ // - Wearables: include COF contents only if appending.
+ LLInventoryModel::item_array_t wear_items;
+ if (append)
+ getDescendentsOfAssetType(cof, wear_items, LLAssetType::AT_CLOTHING, false);
+ getDescendentsOfAssetType(category, wear_items, LLAssetType::AT_CLOTHING, false);
+ // Reduce wearables to max of one per type.
+ removeDuplicateItems(wear_items);
+ filterWearableItems(wear_items, 1);
+
+ // - Attachments: include COF contents only if appending.
+ LLInventoryModel::item_array_t obj_items;
+ if (append)
+ getDescendentsOfAssetType(cof, obj_items, LLAssetType::AT_OBJECT, false);
+ getDescendentsOfAssetType(category, obj_items, LLAssetType::AT_OBJECT, false);
+ removeDuplicateItems(obj_items);
+
+ // - Gestures: include COF contents only if appending.
+ LLInventoryModel::item_array_t gest_items;
+ if (append)
+ getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE, false);
+ getDescendentsOfAssetType(category, gest_items, LLAssetType::AT_GESTURE, false);
+ removeDuplicateItems(gest_items);
+
+ // Remove current COF contents.
+ bool keep_outfit_links = append;
+ purgeCategory(cof, keep_outfit_links);
+ gInventory.notifyObservers();
+
+ // Create links to new COF contents.
+ LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy;
+
+ linkAll(cof, body_items, link_waiter);
+ linkAll(cof, wear_items, link_waiter);
+ linkAll(cof, obj_items, link_waiter);
+ linkAll(cof, gest_items, link_waiter);
+
+ // Add link to outfit if category is an outfit.
+ if (!append)
+ {
+ createBaseOutfitLink(category, link_waiter);
+ }
+}
+
+void LLAppearanceManager::updatePanelOutfitName(const std::string& name)
+{
+ LLSidepanelAppearance* panel_appearance =
+ dynamic_cast<LLSidepanelAppearance *>(LLSideTray::getInstance()->getPanel("sidepanel_appearance"));
+ if (panel_appearance)
+ {
+ panel_appearance->refreshCurrentOutfitName(name);
+ }
+}
+
+void LLAppearanceManager::createBaseOutfitLink(const LLUUID& category, LLPointer<LLInventoryCallback> link_waiter)
+{
+ const LLUUID cof = getCOF();
+ LLViewerInventoryCategory* catp = gInventory.getCategory(category);
+ std::string new_outfit_name = "";
+
+ purgeBaseOutfitLink(cof);
+
+ if (catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT)
+ {
+ link_inventory_item(gAgent.getID(), category, cof, catp->getName(),
+ LLAssetType::AT_LINK_FOLDER, link_waiter);
+ new_outfit_name = catp->getName();
+ }
+
+ updatePanelOutfitName(new_outfit_name);
+}
+
+void LLAppearanceManager::updateAgentWearables(LLWearableHoldingPattern* holder, bool append)
+{
+ lldebugs << "updateAgentWearables()" << llendl;
+ LLInventoryItem::item_array_t items;
+ LLDynamicArray< LLWearable* > wearables;
+
+ // For each wearable type, find the first instance in the category
+ // that we recursed through.
+ for( S32 i = 0; i < WT_COUNT; i++ )
+ {
+ for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->mFoundList.begin();
+ iter != holder->mFoundList.end(); ++iter)
+ {
+ LLFoundData& data = *iter;
+ LLWearable* wearable = data.mWearable;
+ if( wearable && ((S32)wearable->getType() == i) )
+ {
+ LLViewerInventoryItem* item;
+ item = (LLViewerInventoryItem*)gInventory.getItem(data.mItemID);
+ if( item && (item->getAssetUUID() == wearable->getAssetID()) )
+ {
+ items.put(item);
+ wearables.put(wearable);
+ }
+ break;
+ }
+ }
+ }
+
+ if(wearables.count() > 0)
+ {
+ gAgentWearables.setWearableOutfit(items, wearables, !append);
+ }
+
+// dec_busy_count();
+}
+
+void LLAppearanceManager::updateAppearanceFromCOF()
+{
+ // update dirty flag to see if the state of the COF matches
+ // the saved outfit stored as a folder link
+ updateIsDirty();
+
+ dumpCat(getCOF(),"COF, start");
+
+ bool follow_folder_links = true;
+ LLUUID current_outfit_id = getCOF();
+
+ // Find all the wearables that are in the COF's subtree.
+ lldebugs << "LLAppearanceManager::updateFromCOF()" << llendl;
+ LLInventoryModel::item_array_t wear_items;
+ LLInventoryModel::item_array_t obj_items;
+ LLInventoryModel::item_array_t gest_items;
+ getUserDescendents(current_outfit_id, wear_items, obj_items, gest_items, follow_folder_links);
+
+ if(!wear_items.count())
+ {
+ LLNotificationsUtil::add("CouldNotPutOnOutfit");
+ return;
+ }
+
+ LLWearableHoldingPattern* holder = new LLWearableHoldingPattern;
+
+ holder->mObjItems = obj_items;
+ holder->mGestItems = gest_items;
+
+ // Note: can't do normal iteration, because if all the
+ // wearables can be resolved immediately, then the
+ // callback will be called (and this object deleted)
+ // before the final getNextData().
+ LLDynamicArray<LLFoundData> found_container;
+ for(S32 i = 0; i < wear_items.count(); ++i)
+ {
+ LLViewerInventoryItem *item = wear_items.get(i);
+ LLViewerInventoryItem *linked_item = item ? item->getLinkedItem() : NULL;
+ if (item && linked_item)
+ {
+ LLFoundData found(linked_item->getUUID(),
+ linked_item->getAssetUUID(),
+ linked_item->getName(),
+ linked_item->getType());
+ holder->mFoundList.push_front(found);
+ found_container.put(found);
+ }
+ else
+ {
+ if (!item)
+ {
+ llwarns << "attempt to wear a null item " << llendl;
+ }
+ else if (!linked_item)
+ {
+ llwarns << "attempt to wear a broken link " << item->getName() << llendl;
+ }
+ }
+ }
+
+ for(S32 i = 0; i < found_container.count(); ++i)
+ {
+ LLFoundData& found = found_container.get(i);
+
+ // Fetch the wearables about to be worn.
+ LLWearableList::instance().getAsset(found.mAssetID,
+ found.mName,
+ found.mAssetType,
+ onWearableAssetFetch,
+ (void*)holder);
+
+ }
+
+ if (!holder->pollCompletion())
+ {
+ doOnIdleRepeating(boost::bind(&LLWearableHoldingPattern::pollCompletion,holder));
+ }
+
+}
+
+void LLAppearanceManager::getDescendentsOfAssetType(const LLUUID& category,
+ LLInventoryModel::item_array_t& items,
+ LLAssetType::EType type,
+ bool follow_folder_links)
+{
+ LLInventoryModel::cat_array_t cats;
+ LLIsType is_of_type(type);
+ gInventory.collectDescendentsIf(category,
+ cats,
+ items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_of_type,
+ follow_folder_links);
+}
+
+void LLAppearanceManager::getUserDescendents(const LLUUID& category,
+ LLInventoryModel::item_array_t& wear_items,
+ LLInventoryModel::item_array_t& obj_items,
+ LLInventoryModel::item_array_t& gest_items,
+ bool follow_folder_links)
+{
+ LLInventoryModel::cat_array_t wear_cats;
+ LLFindWearables is_wearable;
+ gInventory.collectDescendentsIf(category,
+ wear_cats,
+ wear_items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_wearable,
+ follow_folder_links);
+
+ LLInventoryModel::cat_array_t obj_cats;
+ LLIsType is_object( LLAssetType::AT_OBJECT );
+ gInventory.collectDescendentsIf(category,
+ obj_cats,
+ obj_items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_object,
+ follow_folder_links);
+
+ // Find all gestures in this folder
+ LLInventoryModel::cat_array_t gest_cats;
+ LLIsType is_gesture( LLAssetType::AT_GESTURE );
+ gInventory.collectDescendentsIf(category,
+ gest_cats,
+ gest_items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_gesture,
+ follow_folder_links);
+}
+
+void LLAppearanceManager::wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append)
+{
+ if(!category) return;
+
+ lldebugs << "wearInventoryCategory( " << category->getName()
+ << " )" << llendl;
+ // What we do here is get the complete information on the items in
+ // the inventory, and set up an observer that will wait for that to
+ // happen.
+ LLOutfitFetch* outfit_fetcher = new LLOutfitFetch(copy, append);
+ LLInventoryFetchDescendentsObserver::folder_ref_t folders;
+ folders.push_back(category->getUUID());
+ outfit_fetcher->fetchDescendents(folders);
+ //inc_busy_count();
+ if(outfit_fetcher->isEverythingComplete())
+ {
+ // everything is already here - call done.
+ outfit_fetcher->done();
+ }
+ else
+ {
+ // it's all on it's way - add an observer, and the inventory
+ // will call done for us when everything is here.
+ gInventory.addObserver(outfit_fetcher);
+ }
+}
+
+// *NOTE: hack to get from avatar inventory to avatar
+void LLAppearanceManager::wearInventoryCategoryOnAvatar( LLInventoryCategory* category, bool append )
+{
+ // Avoid unintentionally overwriting old wearables. We have to do
+ // this up front to avoid having to deal with the case of multiple
+ // wearables being dirty.
+ if(!category) return;
+ lldebugs << "wearInventoryCategoryOnAvatar( " << category->getName()
+ << " )" << llendl;
+
+ if( gFloaterCustomize )
+ {
+ gFloaterCustomize->askToSaveIfDirty(boost::bind(&LLAppearanceManager::changeOutfit,
+ &LLAppearanceManager::instance(),
+ _1, category->getUUID(), append));
+ }
+ else
+ {
+ LLAppearanceManager::changeOutfit(TRUE, category->getUUID(), append);
+ }
+}
+
+void LLAppearanceManager::wearOutfitByName(const std::string& name)
+{
+ llinfos << "Wearing category " << name << llendl;
+ //inc_busy_count();
+
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ LLNameCategoryCollector has_name(name);
+ gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ has_name);
+ bool copy_items = false;
+ LLInventoryCategory* cat = NULL;
+ if (cat_array.count() > 0)
+ {
+ // Just wear the first one that matches
+ cat = cat_array.get(0);
+ }
+ else
+ {
+ gInventory.collectDescendentsIf(LLUUID::null,
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ has_name);
+ if(cat_array.count() > 0)
+ {
+ cat = cat_array.get(0);
+ copy_items = true;
+ }
+ }
+
+ if(cat)
+ {
+ LLAppearanceManager::wearInventoryCategory(cat, copy_items, false);
+ }
+ else
+ {
+ llwarns << "Couldn't find outfit " <<name<< " in wearOutfitByName()"
+ << llendl;
+ }
+
+ //dec_busy_count();
+}
+
+bool areMatchingWearables(const LLViewerInventoryItem *a, const LLViewerInventoryItem *b)
+{
+ return (a->isWearableType() && b->isWearableType() &&
+ (a->getWearableType() == b->getWearableType()));
+}
+
+class LLDeferredCOFLinkObserver: public LLInventoryObserver
+{
+public:
+ LLDeferredCOFLinkObserver(const LLUUID& item_id, bool do_update):
+ mItemID(item_id),
+ mDoUpdate(do_update)
+ {
+ }
+
+ ~LLDeferredCOFLinkObserver()
+ {
+ }
+
+ /* virtual */ void changed(U32 mask)
+ {
+ const LLInventoryItem *item = gInventory.getItem(mItemID);
+ if (item)
+ {
+ gInventory.removeObserver(this);
+ LLAppearanceManager::instance().addCOFItemLink(item,mDoUpdate);
+ delete this;
+ }
+ }
+
+private:
+ const LLUUID mItemID;
+ bool mDoUpdate;
+};
+
+
+void LLAppearanceManager::addCOFItemLink(const LLUUID &item_id, bool do_update )
+{
+ const LLInventoryItem *item = gInventory.getItem(item_id);
+ if (!item)
+ {
+ LLDeferredCOFLinkObserver *observer = new LLDeferredCOFLinkObserver(item_id, do_update);
+ gInventory.addObserver(observer);
+ }
+ else
+ {
+ addCOFItemLink(item, do_update);
+ }
+}
+
+void LLAppearanceManager::addCOFItemLink(const LLInventoryItem *item, bool do_update )
+{
+ const LLViewerInventoryItem *vitem = dynamic_cast<const LLViewerInventoryItem*>(item);
+ if (!vitem)
+ {
+ llwarns << "not an llviewerinventoryitem, failed" << llendl;
+ return;
+ }
+
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, vitem->getLinkedUUID());
+
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ gInventory.collectDescendents(LLAppearanceManager::getCOF(),
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+ bool linked_already = false;
+ for (S32 i=0; i<item_array.count(); i++)
+ {
+ // Are these links to the same object?
+ const LLViewerInventoryItem* inv_item = item_array.get(i).get();
+ if (inv_item->getLinkedUUID() == vitem->getLinkedUUID())
+ {
+ linked_already = true;
+ }
+ // Are these links to different items of the same wearable
+ // type? If so, new item will replace old.
+ // MULTI-WEARABLES: revisit if more than one per type is allowed.
+ else if (areMatchingWearables(vitem,inv_item))
+ {
+ gAgentWearables.removeWearable(inv_item->getWearableType(),true,0);
+ if (inv_item->getIsLinkType())
+ {
+ gInventory.purgeObject(inv_item->getUUID());
+ }
+ }
+ }
+ if (linked_already)
+ {
+ if (do_update)
+ {
+ LLAppearanceManager::updateAppearanceFromCOF();
+ }
+ return;
+ }
+ else
+ {
+ LLPointer<LLInventoryCallback> cb = do_update ? new ModifiedCOFCallback : 0;
+ link_inventory_item( gAgent.getID(),
+ vitem->getLinkedUUID(),
+ getCOF(),
+ vitem->getName(),
+ LLAssetType::AT_LINK,
+ cb);
+ }
+ return;
+}
+
+void LLAppearanceManager::addEnsembleLink( LLInventoryCategory* cat, bool do_update )
+{
+#if SUPPORT_ENSEMBLES
+ // BAP add check for already in COF.
+ LLPointer<LLInventoryCallback> cb = do_update ? new ModifiedCOFCallback : 0;
+ link_inventory_item( gAgent.getID(),
+ cat->getLinkedUUID(),
+ getCOF(),
+ cat->getName(),
+ LLAssetType::AT_LINK_FOLDER,
+ cb);
+#endif
+}
+
+void LLAppearanceManager::removeCOFItemLinks(const LLUUID& item_id, bool do_update)
+{
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
+
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ gInventory.collectDescendents(LLAppearanceManager::getCOF(),
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+ for (S32 i=0; i<item_array.count(); i++)
+ {
+ const LLInventoryItem* item = item_array.get(i).get();
+ if (item->getIsLinkType() && item->getLinkedUUID() == item_id)
+ {
+ gInventory.purgeObject(item->getUUID());
+ }
+ }
+ if (do_update)
+ {
+ LLAppearanceManager::updateAppearanceFromCOF();
+ }
+}
+
+void LLAppearanceManager::updateIsDirty()
+{
+ LLUUID cof = getCOF();
+ LLUUID base_outfit;
+
+ // find base outfit link
+ const LLViewerInventoryItem* base_outfit_item = getBaseOutfitLink();
+ LLViewerInventoryCategory* catp = NULL;
+ if (base_outfit_item && base_outfit_item->getIsLinkType())
+ {
+ catp = base_outfit_item->getLinkedCategory();
+ }
+ if(catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT)
+ {
+ base_outfit = catp->getUUID();
+ }
+
+ if(base_outfit.isNull())
+ {
+ // no outfit link found, display "unsaved outfit"
+ mOutfitIsDirty = true;
+ }
+ else
+ {
+ LLInventoryModel::cat_array_t cof_cats;
+ LLInventoryModel::item_array_t cof_items;
+ gInventory.collectDescendents(cof, cof_cats, cof_items,
+ LLInventoryModel::EXCLUDE_TRASH);
+
+ LLInventoryModel::cat_array_t outfit_cats;
+ LLInventoryModel::item_array_t outfit_items;
+ gInventory.collectDescendents(base_outfit, outfit_cats, outfit_items,
+ LLInventoryModel::EXCLUDE_TRASH);
+
+ if(outfit_items.count() != cof_items.count() -1)
+ {
+ // Current outfit folder should have one more item than the outfit folder.
+ // this one item is the link back to the outfit folder itself.
+ mOutfitIsDirty = true;
+ }
+ else
+ {
+ typedef std::set<LLUUID> item_set_t;
+ item_set_t cof_set;
+ item_set_t outfit_set;
+
+ // sort COF items by UUID
+ for (S32 i = 0; i < cof_items.count(); ++i)
+ {
+ LLViewerInventoryItem *item = cof_items.get(i);
+ // don't add the base outfit link to the list of objects we're comparing
+ if(item != base_outfit_item)
+ {
+ cof_set.insert(item->getLinkedUUID());
+ }
+ }
+
+ // sort outfit folder by UUID
+ for (S32 i = 0; i < outfit_items.count(); ++i)
+ {
+ LLViewerInventoryItem *item = outfit_items.get(i);
+ outfit_set.insert(item->getLinkedUUID());
+ }
+
+ mOutfitIsDirty = (outfit_set != cof_set);
+ }
+ }
+}
+
+//#define DUMP_CAT_VERBOSE
+
+void LLAppearanceManager::dumpCat(const LLUUID& cat_id, const std::string& msg)
+{
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ gInventory.collectDescendents(cat_id, cats, items, LLInventoryModel::EXCLUDE_TRASH);
+
+#ifdef DUMP_CAT_VERBOSE
+ llinfos << llendl;
+ llinfos << str << llendl;
+ S32 hitcount = 0;
+ for(S32 i=0; i<items.count(); i++)
+ {
+ LLViewerInventoryItem *item = items.get(i);
+ if (item)
+ hitcount++;
+ llinfos << i <<" "<< item->getName() <<llendl;
+ }
+#endif
+ llinfos << msg << " count " << items.count() << llendl;
+}
+
+void LLAppearanceManager::dumpItemArray(const LLInventoryModel::item_array_t& items,
+ const std::string& msg)
+{
+ llinfos << msg << llendl;
+ for (S32 i=0; i<items.count(); i++)
+ {
+ LLViewerInventoryItem *item = items.get(i);
+ llinfos << i <<" " << item->getName() << llendl;
+ }
+ llinfos << llendl;
+}
+
+LLAppearanceManager::LLAppearanceManager():
+ mAttachmentInvLinkEnabled(false),
+ mOutfitIsDirty(false)
+{
+}
+
+LLAppearanceManager::~LLAppearanceManager()
+{
+}
+
+void LLAppearanceManager::setAttachmentInvLinkEnable(bool val)
+{
+ llinfos << "setAttachmentInvLinkEnable => " << (int) val << llendl;
+ mAttachmentInvLinkEnabled = val;
+}
+
+void dumpAttachmentSet(const std::set<LLUUID>& atts, const std::string& msg)
+{
+ llinfos << msg << llendl;
+ for (std::set<LLUUID>::const_iterator it = atts.begin();
+ it != atts.end();
+ ++it)
+ {
+ LLUUID item_id = *it;
+ LLViewerInventoryItem *item = gInventory.getItem(item_id);
+ if (item)
+ llinfos << "atts " << item->getName() << llendl;
+ else
+ llinfos << "atts " << "UNKNOWN[" << item_id.asString() << "]" << llendl;
+ }
+ llinfos << llendl;
+}
+
+void LLAppearanceManager::registerAttachment(const LLUUID& item_id)
+{
+ mRegisteredAttachments.insert(item_id);
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
+ //dumpAttachmentSet(mRegisteredAttachments,"after register:");
+
+ if (mAttachmentInvLinkEnabled)
+ {
+ LLAppearanceManager::addCOFItemLink(item_id, false); // Add COF link for item.
+ }
+ else
+ {
+ //llinfos << "no link changes, inv link not enabled" << llendl;
+ }
+}
+
+void LLAppearanceManager::unregisterAttachment(const LLUUID& item_id)
+{
+ mRegisteredAttachments.erase(item_id);
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
+
+ //dumpAttachmentSet(mRegisteredAttachments,"after unregister:");
+
+ if (mAttachmentInvLinkEnabled)
+ {
+ //LLAppearanceManager::dumpCat(LLAppearanceManager::getCOF(),"Removing attachment link:");
+ LLAppearanceManager::removeCOFItemLinks(item_id, false);
+ }
+ else
+ {
+ //llinfos << "no link changes, inv link not enabled" << llendl;
+ }
+}
+
+void LLAppearanceManager::linkRegisteredAttachments()
+{
+ for (std::set<LLUUID>::iterator it = mRegisteredAttachments.begin();
+ it != mRegisteredAttachments.end();
+ ++it)
+ {
+ LLUUID item_id = *it;
+ addCOFItemLink(item_id, false);
+ }
+ mRegisteredAttachments.clear();
+}
+
+BOOL LLAppearanceManager::getIsInCOF(const LLUUID& obj_id) const
+{
+ return gInventory.isObjectDescendentOf(obj_id, getCOF());
+}
+
+BOOL LLAppearanceManager::getIsProtectedCOFItem(const LLUUID& obj_id) const
+{
+ if (!getIsInCOF(obj_id)) return FALSE;
+ const LLInventoryObject *obj = gInventory.getObject(obj_id);
+ if (!obj) return FALSE;
+
+ // Can't delete bodyparts, since this would be equivalent to removing the item.
+ if (obj->getType() == LLAssetType::AT_BODYPART) return TRUE;
+
+ // Can't delete the folder link, since this is saved for bookkeeping.
+ if (obj->getActualType() == LLAssetType::AT_LINK_FOLDER) return TRUE;
+
+ return FALSE;
+}
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
new file mode 100644
index 0000000000..dd50b482cf
--- /dev/null
+++ b/indra/newview/llappearancemgr.h
@@ -0,0 +1,215 @@
+/**
+ * @file llappearancemgr.h
+ * @brief Manager for initiating appearance changes on the viewer
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLAPPEARANCEMGR_H
+#define LL_LLAPPEARANCEMGR_H
+
+#include "llsingleton.h"
+#include "llinventorymodel.h"
+#include "llviewerinventory.h"
+#include "llcallbacklist.h"
+
+class LLWearable;
+class LLWearableHoldingPattern;
+
+class LLAppearanceManager: public LLSingleton<LLAppearanceManager>
+{
+ friend class LLSingleton<LLAppearanceManager>;
+
+public:
+ void updateAppearanceFromCOF();
+ bool needToSaveCOF();
+ void updateCOF(const LLUUID& category, bool append = false);
+ void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append);
+ void wearInventoryCategoryOnAvatar(LLInventoryCategory* category, bool append);
+ void wearOutfitByName(const std::string& name);
+ void changeOutfit(bool proceed, const LLUUID& category, bool append);
+
+ // Copy all items in a category.
+ void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
+ LLPointer<LLInventoryCallback> cb);
+
+ // Find the Current Outfit folder.
+ const LLUUID getCOF() const;
+
+ // Finds the folder link to the currently worn outfit
+ const LLViewerInventoryItem *getBaseOutfitLink();
+ bool getBaseOutfitName(std::string &name);
+
+ // Update the displayed outfit name in UI.
+ void updatePanelOutfitName(const std::string& name);
+
+ void createBaseOutfitLink(const LLUUID& category, LLPointer<LLInventoryCallback> link_waiter);
+
+ void updateAgentWearables(LLWearableHoldingPattern* holder, bool append);
+
+ // For debugging - could be moved elsewhere.
+ void dumpCat(const LLUUID& cat_id, const std::string& msg);
+ void dumpItemArray(const LLInventoryModel::item_array_t& items, const std::string& msg);
+
+ // Attachment link management
+ void unregisterAttachment(const LLUUID& item_id);
+ void registerAttachment(const LLUUID& item_id);
+ void setAttachmentInvLinkEnable(bool val);
+ void linkRegisteredAttachments();
+
+ // utility function for bulk linking.
+ void linkAll(const LLUUID& category,
+ LLInventoryModel::item_array_t& items,
+ LLPointer<LLInventoryCallback> cb);
+
+ // Add COF link to individual item.
+ void addCOFItemLink(const LLUUID& item_id, bool do_update = true);
+ void addCOFItemLink(const LLInventoryItem *item, bool do_update = true);
+
+ // Remove COF entries
+ void removeCOFItemLinks(const LLUUID& item_id, bool do_update = true);
+
+ // Add COF link to ensemble folder.
+ void addEnsembleLink(LLInventoryCategory* item, bool do_update = true);
+
+ //has the current outfit changed since it was loaded?
+ bool isOutfitDirty() { return mOutfitIsDirty; }
+
+ // set false if you just loaded the outfit, true otherwise
+ void setOutfitDirty(bool isDirty) { mOutfitIsDirty = isDirty; }
+
+ // manually compare ouftit folder link to COF to see if outfit has changed.
+ // should only be necessary to do on initial login.
+ void updateIsDirty();
+
+protected:
+ LLAppearanceManager();
+ ~LLAppearanceManager();
+
+private:
+
+ void filterWearableItems(LLInventoryModel::item_array_t& items, S32 max_per_type);
+
+ void getDescendentsOfAssetType(const LLUUID& category,
+ LLInventoryModel::item_array_t& items,
+ LLAssetType::EType type,
+ bool follow_folder_links);
+
+ void getUserDescendents(const LLUUID& category,
+ LLInventoryModel::item_array_t& wear_items,
+ LLInventoryModel::item_array_t& obj_items,
+ LLInventoryModel::item_array_t& gest_items,
+ bool follow_folder_links);
+
+ void purgeCategory(const LLUUID& category, bool keep_outfit_links);
+ void purgeBaseOutfitLink(const LLUUID& category);
+
+ std::set<LLUUID> mRegisteredAttachments;
+ bool mAttachmentInvLinkEnabled;
+ bool mOutfitIsDirty;
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // Item-specific convenience functions
+public:
+ // Is this in the COF?
+ BOOL getIsInCOF(const LLUUID& obj_id) const;
+ // Is this in the COF and can the user delete it from the COF?
+ BOOL getIsProtectedCOFItem(const LLUUID& obj_id) const;
+};
+
+#define SUPPORT_ENSEMBLES 0
+
+// Shim class and template function to allow arbitrary boost::bind
+// expressions to be run as one-time idle callbacks.
+template <typename T>
+class OnIdleCallback
+{
+public:
+ OnIdleCallback(T callable):
+ mCallable(callable)
+ {
+ }
+ static void onIdle(void *data)
+ {
+ gIdleCallbacks.deleteFunction(onIdle, data);
+ OnIdleCallback<T>* self = reinterpret_cast<OnIdleCallback<T>*>(data);
+ self->call();
+ delete self;
+ }
+ void call()
+ {
+ mCallable();
+ }
+private:
+ T mCallable;
+};
+
+template <typename T>
+void doOnIdle(T callable)
+{
+ OnIdleCallback<T>* cb_functor = new OnIdleCallback<T>(callable);
+ gIdleCallbacks.addFunction(&OnIdleCallback<T>::onIdle,cb_functor);
+}
+
+// Shim class and template function to allow arbitrary boost::bind
+// expressions to be run as recurring idle callbacks.
+template <typename T>
+class OnIdleCallbackRepeating
+{
+public:
+ OnIdleCallbackRepeating(T callable):
+ mCallable(callable)
+ {
+ }
+ // Will keep getting called until the callable returns false.
+ static void onIdle(void *data)
+ {
+ OnIdleCallbackRepeating<T>* self = reinterpret_cast<OnIdleCallbackRepeating<T>*>(data);
+ bool done = self->call();
+ if (done)
+ {
+ gIdleCallbacks.deleteFunction(onIdle, data);
+ delete self;
+ }
+ }
+ bool call()
+ {
+ return mCallable();
+ }
+private:
+ T mCallable;
+};
+
+template <typename T>
+void doOnIdleRepeating(T callable)
+{
+ OnIdleCallbackRepeating<T>* cb_functor = new OnIdleCallbackRepeating<T>(callable);
+ gIdleCallbacks.addFunction(&OnIdleCallbackRepeating<T>::onIdle,cb_functor);
+}
+
+#endif
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 0c34d018a2..0e248ff88b 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -30,67 +30,94 @@
* $/LicenseInfo$
*/
-
#include "llviewerprecompiledheaders.h"
+
#include "llappviewer.h"
-#include "llprimitive.h"
-#include "llversionviewer.h"
+// Viewer includes
+#include "llversioninfo.h"
#include "llfeaturemanager.h"
#include "lluictrlfactory.h"
#include "lltexteditor.h"
-#include "llalertdialog.h"
#include "llerrorcontrol.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llgroupmgr.h"
#include "llagent.h"
+#include "llagentwearables.h"
#include "llwindow.h"
#include "llviewerstats.h"
#include "llmd5.h"
#include "llpumpio.h"
-#include "llimpanel.h"
#include "llmimetypes.h"
+#include "llslurl.h"
#include "llstartup.h"
#include "llfocusmgr.h"
#include "llviewerjoystick.h"
-#include "llfloaterjoystick.h"
+#include "llallocator.h"
#include "llares.h"
#include "llcurl.h"
-#include "llfloatersnapshot.h"
+#include "lltexturestats.h"
+#include "lltexturestats.h"
#include "llviewerwindow.h"
#include "llviewerdisplay.h"
#include "llviewermedia.h"
+#include "llviewerparcelmedia.h"
+#include "llviewermediafocus.h"
#include "llviewermessage.h"
#include "llviewerobjectlist.h"
#include "llworldmap.h"
#include "llmutelist.h"
+#include "llviewerhelp.h"
+#include "lluicolortable.h"
#include "llurldispatcher.h"
#include "llurlhistory.h"
-#include "llfirstuse.h"
+//#include "llfirstuse.h"
#include "llrender.h"
+#include "llteleporthistory.h"
+#include "lllocationhistory.h"
+#include "llfasttimerview.h"
+#include "llvoicechannel.h"
+#include "llsidetray.h"
+
#include "llweb.h"
#include "llsecondlifeurls.h"
+// Linden library includes
+#include "llimagej2c.h"
+#include "llmemory.h"
+#include "llprimitive.h"
+#include "llurlaction.h"
+#include "llvfile.h"
+#include "llvfsthread.h"
+#include "llvolumemgr.h"
+#include "llxfermanager.h"
+
+#include "llnotificationmanager.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+
+// Third party library includes
#include <boost/bind.hpp>
#if LL_WINDOWS
#include "llwindebug.h"
-#endif
-
-#if LL_WINDOWS
# include <share.h> // For _SH_DENYWR in initMarkerFile
#else
# include <sys/file.h> // For initMarkerFile support
#endif
-#include "llnotify.h"
+#include "llapr.h"
+#include "apr_dso.h"
+#include <boost/lexical_cast.hpp>
+
#include "llviewerkeyboard.h"
#include "lllfsthread.h"
#include "llworkerthread.h"
#include "lltexturecache.h"
#include "lltexturefetch.h"
#include "llimageworker.h"
+#include "llevents.h"
// The files below handle dependencies from cleanup.
#include "llkeyframemotion.h"
@@ -100,11 +127,12 @@
#include "llassetstorage.h"
#include "llpolymesh.h"
#include "llcachename.h"
-#include "audioengine.h"
+#include "llaudioengine.h"
+#include "llstreamingaudio.h"
#include "llviewermenu.h"
#include "llselectmgr.h"
#include "lltrans.h"
-#include "lluitrans.h"
+#include "lltransutil.h"
#include "lltracker.h"
#include "llviewerparcelmgr.h"
#include "llworldmapview.h"
@@ -115,9 +143,7 @@
#include "lldebugview.h"
#include "llconsole.h"
#include "llcontainerview.h"
-#include "llfloaterstats.h"
-#include "llhoverview.h"
-#include "llfloatermemleak.h"
+#include "lltooltip.h"
#include "llsdserialize.h"
@@ -138,12 +164,16 @@
#include "llvoavatar.h"
#include "llfolderview.h"
#include "lltoolbar.h"
-#include "llframestats.h"
#include "llagentpilot.h"
-#include "llsrv.h"
#include "llvovolume.h"
#include "llflexibleobject.h"
#include "llvosurfacepatch.h"
+#include "llviewerfloaterreg.h"
+#include "llcommandlineparser.h"
+#include "llfloatermemleak.h"
+#include "llfloaterreg.h"
+#include "llfloatersnapshot.h"
+#include "llfloaterinventory.h"
// includes for idle() idleShutdown()
#include "llviewercontrol.h"
@@ -159,11 +189,7 @@
#include "llimview.h"
#include "llviewerthrottle.h"
#include "llparcel.h"
-
-
-#include "llinventoryview.h"
-
-#include "llcommandlineparser.h"
+#include "llavatariconctrl.h"
// *FIX: These extern globals should be cleaned up.
// The globals either represent state/config/resource-storage of either
@@ -176,14 +202,22 @@
//----------------------------------------------------------------------------
// llviewernetwork.h
#include "llviewernetwork.h"
+// define a self-registering event API object
+#include "llappviewerlistener.h"
+#if (LL_LINUX || LL_SOLARIS) && LL_GTK
+#include "glib.h"
+#endif // (LL_LINUX || LL_SOLARIS) && LL_GTK
-////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor
-//
-#if LL_WINDOWS && LL_LCD_COMPILE
- #include "lllcd.h"
+#if LL_MSVC
+// disable boost::lexical_cast warning
+#pragma warning (disable:4702)
#endif
+static LLAppViewerListener sAppViewerListener(LLAppViewer::instance);
+
+////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor
+//
//----------------------------------------------------------------------------
// viewer.cpp - these are only used in viewer, should be easily moved.
@@ -202,13 +236,9 @@ const F32 DEFAULT_AFK_TIMEOUT = 5.f * 60.f; // time with no input before user fl
F32 gSimLastTime; // Used in LLAppViewer::init and send_stats()
F32 gSimFrames;
-BOOL gAllowTapTapHoldRun = TRUE;
BOOL gShowObjectUpdates = FALSE;
BOOL gUseQuickTime = TRUE;
-BOOL gAcceptTOS = FALSE;
-BOOL gAcceptCriticalMessage = FALSE;
-
eLastExecEvent gLastExecEvent = LAST_EXEC_NORMAL;
LLSD gDebugInfo;
@@ -217,8 +247,6 @@ U32 gFrameCount = 0;
U32 gForegroundFrameCount = 0; // number of frames that app window was in foreground
LLPumpIO* gServicePump = NULL;
-BOOL gPacificDaylightTime = FALSE;
-
U64 gFrameTime = 0;
F32 gFrameTimeSeconds = 0.f;
F32 gFrameIntervalSeconds = 0.f;
@@ -234,14 +262,8 @@ LLTimer gLogoutTimer;
static const F32 LOGOUT_REQUEST_TIME = 6.f; // this will be cut short by the LogoutReply msg.
F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME;
-LLUUID gInventoryLibraryOwner;
-LLUUID gInventoryLibraryRoot;
-
BOOL gDisconnected = FALSE;
-// Map scale in pixels per region
-F32 gMapScale = 128.f;
-
// used to restore texture state after a mode switch
LLFrameTimer gRestoreGLTimer;
BOOL gRestoreGL = FALSE;
@@ -284,11 +306,23 @@ static std::string gLaunchFileOnQuit;
const char* const VIEWER_WINDOW_CLASSNAME = "Second Life";
//----------------------------------------------------------------------------
+
+// List of entries from strings.xml to always replace
+static std::set<std::string> default_trans_args;
+void init_default_trans_args()
+{
+ default_trans_args.insert("SECOND_LIFE"); // World
+ default_trans_args.insert("APP_NAME");
+ default_trans_args.insert("CAPITALIZED_APP_NAME");
+ default_trans_args.insert("SECOND_LIFE_GRID");
+ default_trans_args.insert("SUPPORT_SITE");
+}
+
+//----------------------------------------------------------------------------
// File scope definitons
const char *VFS_DATA_FILE_BASE = "data.db2.x.";
const char *VFS_INDEX_FILE_BASE = "index.db2.x.";
-static std::string gSecondLife;
static std::string gWindowTitle;
std::string gLoginPage;
@@ -300,7 +334,7 @@ LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ;
void idle_afk_check()
{
// check idle timers
- if (gSavedSettings.getBOOL("AllowIdleAFK") && (gAwayTriggerTimer.getElapsedTimeF32() > gSavedSettings.getF32("AFKTimeout")))
+ if (gSavedSettings.getS32("AFKTimeout") && (gAwayTriggerTimer.getElapsedTimeF32() > gSavedSettings.getS32("AFKTimeout")))
{
gAgent.setAFK();
}
@@ -359,13 +393,11 @@ bool handleCrashSubmitBehaviorChanged(const LLSD& newvalue)
static void settings_to_globals()
{
LLBUTTON_H_PAD = gSavedSettings.getS32("ButtonHPad");
- LLBUTTON_V_PAD = gSavedSettings.getS32("ButtonVPad");
BTN_HEIGHT_SMALL = gSavedSettings.getS32("ButtonHeightSmall");
BTN_HEIGHT = gSavedSettings.getS32("ButtonHeight");
MENU_BAR_HEIGHT = gSavedSettings.getS32("MenuBarHeight");
MENU_BAR_WIDTH = gSavedSettings.getS32("MenuBarWidth");
- STATUS_BAR_HEIGHT = gSavedSettings.getS32("StatusBarHeight");
LLCOMBOBOX_HEIGHT = BTN_HEIGHT - 2;
LLCOMBOBOX_WIDTH = 128;
@@ -387,16 +419,13 @@ static void settings_to_globals()
LLSelectMgr::sRenderHiddenSelections = gSavedSettings.getBOOL("RenderHiddenSelections");
LLSelectMgr::sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius");
- gFrameStats.setTrackStats(gSavedSettings.getBOOL("StatsSessionTrackFrameStats"));
gAgentPilot.mNumRuns = gSavedSettings.getS32("StatsNumRuns");
gAgentPilot.mQuitAfterRuns = gSavedSettings.getBOOL("StatsQuitAfterRuns");
- gAgent.mHideGroupTitle = gSavedSettings.getBOOL("RenderHideGroupTitle");
+ gAgent.setHideGroupTitle(gSavedSettings.getBOOL("RenderHideGroupTitle"));
gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc");
- gAllowTapTapHoldRun = gSavedSettings.getBOOL("AllowTapTapHoldRun");
gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates");
- gMapScale = gSavedSettings.getF32("MapScale");
- LLHoverView::sShowHoverTips = gSavedSettings.getBOOL("ShowHoverTips");
+ LLWorldMapView::sMapScale = gSavedSettings.getF32("MapScale");
LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap");
}
@@ -407,9 +436,9 @@ static void settings_modify()
LLVOAvatar::sUseImpostors = gSavedSettings.getBOOL("RenderUseImpostors");
LLVOSurfacePatch::sLODFactor = gSavedSettings.getF32("RenderTerrainLODFactor");
LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4]
- gDebugGL = gSavedSettings.getBOOL("RenderDebugGL");
+ gDebugGL = gSavedSettings.getBOOL("RenderDebugGL") || gDebugSession;
gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline");
-
+ gAuditTexture = gSavedSettings.getBOOL("AuditTexture");
#if LL_VECTORIZE
if (gSysCPU.hasAltivec())
{
@@ -445,6 +474,38 @@ static void settings_modify()
#endif
}
+class LLFastTimerLogThread : public LLThread
+{
+public:
+ std::string mFile;
+
+ LLFastTimerLogThread() : LLThread("fast timer log")
+ {
+ if(LLFastTimer::sLog)
+ {
+ mFile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance.slp");
+ }
+ if(LLFastTimer::sMetricLog)
+ {
+ mFile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric.slp");
+ }
+ }
+
+ void run()
+ {
+ std::ofstream os(mFile.c_str());
+
+ while (!LLAppViewer::instance()->isQuitting())
+ {
+ LLFastTimer::writeLog(os);
+ os.flush();
+ ms_sleep(32);
+ }
+
+ os.close();
+ }
+};
+
void LLAppViewer::initGridChoice()
{
// Load up the initial grid choice from:
@@ -496,11 +557,9 @@ bool LLAppViewer::sendURLToOtherInstance(const std::string& url)
LLAppViewer* LLAppViewer::sInstance = NULL;
const std::string LLAppViewer::sGlobalSettingsName = "Global";
-const std::string LLAppViewer::sPerAccountSettingsName = "PerAccount";
-const std::string LLAppViewer::sCrashSettingsName = "CrashSettings";
LLTextureCache* LLAppViewer::sTextureCache = NULL;
-LLWorkerThread* LLAppViewer::sImageDecodeThread = NULL;
+LLImageDecodeThread* LLAppViewer::sImageDecodeThread = NULL;
LLTextureFetch* LLAppViewer::sTextureFetch = NULL;
LLAppViewer::LLAppViewer() :
@@ -512,11 +571,15 @@ LLAppViewer::LLAppViewer() :
mPurgeOnExit(false),
mSecondInstance(false),
mSavedFinalSnapshot(false),
+ mForceGraphicsDetail(false),
mQuitRequested(false),
mLogoutRequestSent(false),
mYieldTime(-1),
mMainloopTimeout(NULL),
- mAgentRegionLastAlive(false)
+ mAgentRegionLastAlive(false),
+ mRandomizeFramerate(LLCachedControl<bool>(gSavedSettings,"Randomize Framerate", FALSE)),
+ mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)),
+ mFastTimerLogThread(NULL)
{
if(NULL != sInstance)
{
@@ -544,7 +607,8 @@ bool LLAppViewer::init()
// into the log files during normal startup until AFTER
// we run the "program crashed last time" error handler below.
//
-
+ LLFastTimer::reset();
+
// Need to do this initialization before we do anything else, since anything
// that touches files should really go through the lldir API
gDirUtilp->initAppDirs("SecondLife");
@@ -557,9 +621,26 @@ bool LLAppViewer::init()
//
// OK to write stuff to logs now, we've now crash reported if necessary
//
- if (!initConfiguration())
+
+ init_default_trans_args();
+
+ if (!initConfiguration())
return false;
+ // Although initLogging() is the right place to mess with
+ // setFatalFunction(), we can't query gSavedSettings until after
+ // initConfiguration().
+ S32 rc(gSavedSettings.getS32("QAModeTermCode"));
+ if (rc >= 0)
+ {
+ // QAModeTermCode set, terminate with that rc on LL_ERRS. Use _exit()
+ // rather than exit() because normal cleanup depends too much on
+ // successful startup!
+ LLError::setFatalFunction(boost::bind(_exit, rc));
+ }
+
+ mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling"));
+
// *NOTE:Mani - LLCurl::initClass is not thread safe.
// Called before threads are created.
LLCurl::initClass();
@@ -569,12 +650,9 @@ bool LLAppViewer::init()
writeSystemInfo();
// Build a string representing the current version number.
- gCurrentVersion = llformat("%s %d.%d.%d.%d",
- gSavedSettings.getString("VersionChannelName").c_str(),
- LL_VERSION_MAJOR,
- LL_VERSION_MINOR,
- LL_VERSION_PATCH,
- LL_VERSION_BUILD );
+ gCurrentVersion = llformat("%s %s",
+ gSavedSettings.getString("VersionChannelName").c_str(),
+ LLVersionInfo::getVersion().c_str());
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
@@ -582,6 +660,9 @@ bool LLAppViewer::init()
//////////////////////////////////////////////////////////////////////////////
// *FIX: The following code isn't grouped into functions yet.
+ // Statistics / debug timer initialization
+ init_statistics();
+
//
// Various introspection concerning the libs we're using - particularly
// the libs involved in getting to a full login screen.
@@ -592,6 +673,11 @@ bool LLAppViewer::init()
// Get the single value from the crash settings file, if it exists
std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE);
gCrashSettings.loadFromFile(crash_settings_filename);
+ if(gSavedSettings.getBOOL("IgnoreAllNotifications"))
+ {
+ gCrashSettings.setS32(CRASH_BEHAVIOR_SETTING, CRASH_BEHAVIOR_ALWAYS_SEND);
+ gCrashSettings.saveToFile(crash_settings_filename, FALSE);
+ }
/////////////////////////////////////////////////
// OS-specific login dialogs
@@ -604,42 +690,52 @@ bool LLAppViewer::init()
mNumSessions++;
gSavedSettings.setS32("NumSessions", mNumSessions);
- gSavedSettings.setString("HelpLastVisitedURL",gSavedSettings.getString("HelpHomeURL"));
-
if (gSavedSettings.getBOOL("VerboseLogs"))
{
LLError::setPrintLocation(true);
}
- // Load art UUID information, don't require these strings to be declared in code.
- std::string colors_base_filename = gDirUtilp->findSkinnedFilename("colors_base.xml");
- LL_DEBUGS("InitInfo") << "Loading base colors from " << colors_base_filename << LL_ENDL;
- gColors.loadFromFileLegacy(colors_base_filename, FALSE, TYPE_COL4U);
-
- // Load overrides from user colors file
- std::string user_colors_filename = gDirUtilp->findSkinnedFilename("colors.xml");
- LL_DEBUGS("InitInfo") << "Loading user colors from " << user_colors_filename << LL_ENDL;
- if (gColors.loadFromFileLegacy(user_colors_filename, FALSE, TYPE_COL4U) == 0)
- {
- LL_DEBUGS("InitInfo") << "Cannot load user colors from " << user_colors_filename << LL_ENDL;
- }
-
// Widget construction depends on LLUI being initialized
- LLUI::initClass(&gSavedSettings,
- &gSavedSettings,
- &gColors,
+ LLUI::settings_map_t settings_map;
+ settings_map["config"] = &gSavedSettings;
+ settings_map["ignores"] = &gWarningSettings;
+ settings_map["floater"] = &gSavedSettings; // *TODO: New settings file
+ settings_map["account"] = &gSavedPerAccountSettings;
+
+ LLUI::initClass(settings_map,
LLUIImageList::getInstance(),
ui_audio_callback,
&LLUI::sGLScaleFactor);
- LLWeb::initClass(); // do this after LLUI
+
+ // Setup paths and LLTrans after LLUI::initClass has been called
+ LLUI::setupPaths();
+ LLTransUtil::parseStrings("strings.xml", default_trans_args);
+ LLTransUtil::parseLanguageStrings("language_settings.xml");
+
+ // LLKeyboard relies on LLUI to know what some accelerator keys are called.
+ LLKeyboard::setStringTranslatorFunc( LLTrans::getKeyboardString );
- LLTextEditor::setURLCallbacks(&LLWeb::loadURL,
- &LLURLDispatcher::dispatchFromTextEditor,
- &LLURLDispatcher::dispatchFromTextEditor);
+ LLWeb::initClass(); // do this after LLUI
- LLUICtrlFactory::getInstance()->setupPaths(); // update paths with correct language set
+ // Provide the text fields with callbacks for opening Urls
+ LLUrlAction::setOpenURLCallback(&LLWeb::loadURL);
+ LLUrlAction::setOpenURLInternalCallback(&LLWeb::loadURLInternal);
+ LLUrlAction::setOpenURLExternalCallback(&LLWeb::loadURLExternal);
+ LLUrlAction::setExecuteSLURLCallback(&LLURLDispatcher::dispatchFromTextEditor);
+
+ // Let code in llui access the viewer help floater
+ LLUI::sHelpImpl = LLViewerHelp::getInstance();
+
+ // Load translations for tooltips
+ LLFloater::initClass();
/////////////////////////////////////////////////
+
+ LLToolMgr::getInstance(); // Initialize tool manager if not already instantiated
+
+ LLViewerFloaterReg::registerFloaters();
+
+ /////////////////////////////////////////////////
//
// Load settings files
//
@@ -651,7 +747,15 @@ bool LLAppViewer::init()
LLViewerJointMesh::updateVectorize();
// load MIME type -> media impl mappings
- LLMIMETypes::parseMIMETypes( std::string("mime_types.xml") );
+ std::string mime_types_name;
+#if LL_DARWIN
+ mime_types_name = "mime_types_mac.xml";
+#elif LL_LINUX
+ mime_types_name = "mime_types_linux.xml";
+#else
+ mime_types_name = "mime_types.xml";
+#endif
+ LLMIMETypes::parseMIMETypes( mime_types_name );
// Copy settings to globals. *TODO: Remove or move to appropriage class initializers
settings_to_globals();
@@ -691,36 +795,20 @@ bool LLAppViewer::init()
if (!initCache())
{
std::ostringstream msg;
- msg <<
- gSecondLife << " is unable to access a file that it needs.\n"
- "\n"
- "This can be because you somehow have multiple copies running, "
- "or your system incorrectly thinks a file is open. "
- "If this message persists, restart your computer and try again. "
- "If it continues to persist, you may need to completely uninstall " <<
- gSecondLife << " and reinstall it.";
- OSMessageBox(
- msg.str(),
- LLStringUtil::null,
- OSMB_OK);
+ msg << LLTrans::getString("MBUnableToAccessFile");
+ OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK);
return 1;
}
//
// Initialize the window
//
+ gGLActive = TRUE;
initWindow();
// call all self-registered classes
LLInitClassList::instance().fireCallbacks();
- #if LL_LCD_COMPILE
- // start up an LCD window on a logitech keyboard, if there is one
- HINSTANCE hInstance = GetModuleHandle(NULL);
- gLcdScreen = new LLLCD(hInstance);
- CreateLCDDebugWindows();
-#endif
-
LLFolderViewItem::initClass(); // SJB: Needs to happen after initWindow(), not sure why but related to fonts
gGLManager.getGLInfo(gDebugInfo);
@@ -788,7 +876,7 @@ bool LLAppViewer::init()
if (LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_UNKNOWN)
{
- LLNotifications::instance().add("UnknownGPU");
+ LLNotificationsUtil::add("UnknownGPU");
}
if(unsupported)
@@ -797,7 +885,7 @@ bool LLAppViewer::init()
|| gSavedSettings.getBOOL("WarnUnsupportedHardware"))
{
args["MINSPECS"] = minSpecs;
- LLNotifications::instance().add("UnsupportedHardware", args );
+ LLNotificationsUtil::add("UnsupportedHardware", args );
}
}
@@ -813,14 +901,31 @@ bool LLAppViewer::init()
gSimFrames = (F32)gFrameCount;
LLViewerJoystick::getInstance()->init(false);
-
+ gGLActive = FALSE;
+ if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0)
+ {
+ loadEventHostModule(gSavedSettings.getS32("QAModeEventHostPort"));
+ }
+
+ LLViewerMedia::initClass();
+
return true;
}
+static LLFastTimer::DeclareTimer FTM_MESSAGES("System Messages");
+static LLFastTimer::DeclareTimer FTM_SLEEP("Sleep");
+static LLFastTimer::DeclareTimer FTM_TEXTURE_CACHE("Texture Cache");
+static LLFastTimer::DeclareTimer FTM_DECODE("Image Decode");
+static LLFastTimer::DeclareTimer FTM_VFS("VFS Thread");
+static LLFastTimer::DeclareTimer FTM_LFS("LFS Thread");
+static LLFastTimer::DeclareTimer FTM_PAUSE_THREADS("Pause Threads");
+static LLFastTimer::DeclareTimer FTM_IDLE("Idle");
+static LLFastTimer::DeclareTimer FTM_PUMP("Pump");
+
bool LLAppViewer::mainLoop()
{
+ LLMemType mt1(LLMemType::MTYPE_MAIN);
mMainloopTimeout = new LLWatchdogTimeout();
- // *FIX:Mani - Make this a setting, once new settings exist in this branch.
//-------------------------------------------
// Run main loop until time to quit
@@ -830,36 +935,45 @@ bool LLAppViewer::mainLoop()
gServicePump = new LLPumpIO(gAPRPoolp);
LLHTTPClient::setPump(*gServicePump);
LLCurl::setCAFile(gDirUtilp->getCAFile());
+ LLCurl::setSSLVerify(! gSavedSettings.getBOOL("NoVerifySSLCert"));
// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
LLVoiceChannel::initClass();
LLVoiceClient::init(gServicePump);
-
- LLMemType mt1(LLMemType::MTYPE_MAIN);
+
LLTimer frameTimer,idleTimer;
LLTimer debugTime;
LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
joystick->setNeedsReset(true);
-
+
+ LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
+ // As we do not (yet) send data on the mainloop LLEventPump that varies
+ // with each frame, no need to instantiate a new LLSD event object each
+ // time. Obviously, if that changes, just instantiate the LLSD at the
+ // point of posting.
+ LLSD newFrame;
+
// Handle messages
while (!LLApp::isExiting())
{
- LLFastTimer::reset(); // Should be outside of any timer instances
+ LLFastTimer::nextFrame(); // Should be outside of any timer instances
+
try
{
- LLFastTimer t(LLFastTimer::FTM_FRAME);
pingMainloopTimeout("Main:MiscNativeWindowEvents");
-
+
+ if (gViewerWindow)
{
- LLFastTimer t2(LLFastTimer::FTM_MESSAGES);
+ LLFastTimer t2(FTM_MESSAGES);
gViewerWindow->mWindow->processMiscNativeEvents();
}
-
+
pingMainloopTimeout("Main:GatherInput");
+ if (gViewerWindow)
{
- LLFastTimer t2(LLFastTimer::FTM_MESSAGES);
+ LLFastTimer t2(FTM_MESSAGES);
if (!restoreErrorTrap())
{
llwarns << " Someone took over my signal/exception handler (post messagehandling)!" << llendl;
@@ -877,11 +991,16 @@ bool LLAppViewer::mainLoop()
#endif
//memory leaking simulation
- if(LLFloaterMemLeak::getInstance())
+ LLFloaterMemLeak* mem_leak_instance =
+ LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
+ if(mem_leak_instance)
{
- LLFloaterMemLeak::getInstance()->idle() ;
+ mem_leak_instance->idle() ;
}
+ // canonical per-frame event
+ mainloop.post(newFrame);
+
if (!LLApp::isExiting())
{
pingMainloopTimeout("Main:JoystickKeyboard");
@@ -896,6 +1015,7 @@ bool LLAppViewer::mainLoop()
&& !gViewerWindow->getShowProgress()
&& !gFocusMgr.focusLocked())
{
+ LLMemType mjk(LLMemType::MTYPE_JOY_KEY);
joystick->scanJoystick();
gKeyboard->scanKeyboard();
}
@@ -904,13 +1024,14 @@ bool LLAppViewer::mainLoop()
{
pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
- LLFastTimer t3(LLFastTimer::FTM_IDLE);
+ LLFastTimer t3(FTM_IDLE);
idle();
if (gAres != NULL && gAres->isInitialized())
{
+ LLMemType mt_ip(LLMemType::MTYPE_IDLE_PUMP);
pingMainloopTimeout("Main:ServicePump");
- LLFastTimer t4(LLFastTimer::FTM_PUMP);
+ LLFastTimer t4(FTM_PUMP);
gAres->process();
// this pump is necessary to make the login screen show up
gServicePump->pump();
@@ -932,16 +1053,11 @@ bool LLAppViewer::mainLoop()
if (!LLApp::isExiting())
{
pingMainloopTimeout("Main:Display");
+ gGLActive = TRUE;
display();
-
pingMainloopTimeout("Main:Snapshot");
LLFloaterSnapshot::update(); // take snapshots
-
-#if LL_LCD_COMPILE
- // update LCD Screen
- pingMainloopTimeout("Main:LCD");
- gLcdScreen->UpdateDisplay();
-#endif
+ gGLActive = FALSE;
}
}
@@ -952,7 +1068,8 @@ bool LLAppViewer::mainLoop()
// Sleep and run background threads
{
- LLFastTimer t2(LLFastTimer::FTM_SLEEP);
+ LLMemType mt_sleep(LLMemType::MTYPE_SLEEP);
+ LLFastTimer t2(FTM_SLEEP);
bool run_multiple_threads = gSavedSettings.getBOOL("RunMultipleThreads");
// yield some time to the os based on command line option
@@ -963,7 +1080,7 @@ bool LLAppViewer::mainLoop()
// yield cooperatively when not running as foreground window
if ( gNoRender
- || !gViewerWindow->mWindow->getVisible()
+ || (gViewerWindow && !gViewerWindow->mWindow->getVisible())
|| !gFocusMgr.getAppHasFocus())
{
// Sleep if we're not rendering, or the window is minimized.
@@ -979,12 +1096,12 @@ bool LLAppViewer::mainLoop()
}
}
- if (gRandomizeFramerate)
+ if (mRandomizeFramerate)
{
ms_sleep(rand() % 200);
}
- if (gPeriodicSlowFrame
+ if (mPeriodicSlowFrame
&& (gFrameCount % 10 == 0))
{
llinfos << "Periodic slow frame - sleeping 500 ms" << llendl;
@@ -1000,11 +1117,28 @@ bool LLAppViewer::mainLoop()
{
S32 work_pending = 0;
S32 io_pending = 0;
- work_pending += LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread
- work_pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
- work_pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
- io_pending += LLVFSThread::updateClass(1);
- io_pending += LLLFSThread::updateClass(1);
+ {
+ LLFastTimer ftm(FTM_TEXTURE_CACHE);
+ work_pending += LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread
+ }
+ {
+ LLFastTimer ftm(FTM_DECODE);
+ work_pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
+ }
+ {
+ LLFastTimer ftm(FTM_DECODE);
+ work_pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
+ }
+
+ {
+ LLFastTimer ftm(FTM_VFS);
+ io_pending += LLVFSThread::updateClass(1);
+ }
+ {
+ LLFastTimer ftm(FTM_LFS);
+ io_pending += LLLFSThread::updateClass(1);
+ }
+
if (io_pending > 1000)
{
ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up
@@ -1030,6 +1164,8 @@ bool LLAppViewer::mainLoop()
// if (LLThread::processorCount()==1) //pause() should only be required when on a single processor client...
if (run_multiple_threads == FALSE)
{
+ LLFastTimer ftm(FTM_PAUSE_THREADS);
+
LLAppViewer::getTextureCache()->pause();
LLAppViewer::getImageDecodeThread()->pause();
// LLAppViewer::getTextureFetch()->pause(); // Don't pause the fetch (IO) thread
@@ -1046,9 +1182,11 @@ bool LLAppViewer::mainLoop()
catch(std::bad_alloc)
{
//stop memory leaking simulation
- if(LLFloaterMemLeak::getInstance())
+ LLFloaterMemLeak* mem_leak_instance =
+ LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
+ if(mem_leak_instance)
{
- LLFloaterMemLeak::getInstance()->stop() ;
+ mem_leak_instance->stop() ;
llwarns << "Bad memory allocation in LLAppViewer::mainLoop()!" << llendl ;
}
else
@@ -1073,9 +1211,11 @@ bool LLAppViewer::mainLoop()
llwarns << "Bad memory allocation when saveFinalSnapshot() is called!" << llendl ;
//stop memory leaking simulation
- if(LLFloaterMemLeak::getInstance())
+ LLFloaterMemLeak* mem_leak_instance =
+ LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
+ if(mem_leak_instance)
{
- LLFloaterMemLeak::getInstance()->stop() ;
+ mem_leak_instance->stop() ;
}
}
}
@@ -1091,6 +1231,21 @@ bool LLAppViewer::mainLoop()
bool LLAppViewer::cleanup()
{
+ // workaround for DEV-35406 crash on shutdown
+ LLEventPumps::instance().reset();
+
+ // *TODO - generalize this and move DSO wrangling to a helper class -brad
+ std::set<struct apr_dso_handle_t *>::const_iterator i;
+ for(i = mPlugins.begin(); i != mPlugins.end(); ++i)
+ {
+ int (*ll_plugin_stop_func)(void) = NULL;
+ apr_status_t rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_stop_func, *i, "ll_plugin_stop");
+ ll_plugin_stop_func();
+
+ rv = apr_dso_unload(*i);
+ }
+ mPlugins.clear();
+
//----------------------------------------------
//this test code will be removed after the test
//test manual call stack tracer
@@ -1155,6 +1310,14 @@ bool LLAppViewer::cleanup()
if (gAudiop)
{
+ // shut down the streaming audio sub-subsystem first, in case it relies on not outliving the general audio subsystem.
+
+ LLStreamingAudioInterface *sai = gAudiop->getStreamingAudioImpl();
+ delete sai;
+ gAudiop->setStreamingAudioImpl(NULL);
+
+ // shut down the audio subsystem
+
bool want_longname = false;
if (gAudiop->getDriverName(want_longname) == "FMOD")
{
@@ -1207,29 +1370,50 @@ bool LLAppViewer::cleanup()
llinfos << "Waiting for pending IO to finish: " << pending << llendflush;
ms_sleep(100);
}
- llinfos << "Shutting down." << llendflush;
+ llinfos << "Shutting down Views" << llendflush;
// Destroy the UI
- gViewerWindow->shutdownViews();
+ if( gViewerWindow)
+ gViewerWindow->shutdownViews();
+ llinfos << "Cleaning up Inventory" << llendflush;
+
+ // Cleanup Inventory after the UI since it will delete any remaining observers
+ // (Deleted observers should have already removed themselves)
+ gInventory.cleanupInventory();
+
+ llinfos << "Cleaning up Selections" << llendflush;
+
// Clean up selection managers after UI is destroyed, as UI may be observing them.
// Clean up before GL is shut down because we might be holding on to objects with texture references
LLSelectMgr::cleanupGlobals();
+
+ llinfos << "Shutting down OpenGL" << llendflush;
// Shut down OpenGL
- gViewerWindow->shutdownGL();
+ if( gViewerWindow)
+ {
+ gViewerWindow->shutdownGL();
- // Destroy window, and make sure we're not fullscreen
- // This may generate window reshape and activation events.
- // Therefore must do this before destroying the message system.
- delete gViewerWindow;
- gViewerWindow = NULL;
- llinfos << "ViewerWindow deleted" << llendflush;
+ // Destroy window, and make sure we're not fullscreen
+ // This may generate window reshape and activation events.
+ // Therefore must do this before destroying the message system.
+ delete gViewerWindow;
+ gViewerWindow = NULL;
+ llinfos << "ViewerWindow deleted" << llendflush;
+ }
+ llinfos << "Cleaning up Keyboard & Joystick" << llendflush;
+
// viewer UI relies on keyboard so keep it aound until viewer UI isa gone
delete gKeyboard;
gKeyboard = NULL;
+ // Turn off Space Navigator and similar devices
+ LLViewerJoystick::getInstance()->terminate();
+
+ llinfos << "Cleaning up Objects" << llendflush;
+
LLViewerObject::cleanupVOClasses();
LLWaterParamManager::cleanupClass();
@@ -1245,12 +1429,6 @@ bool LLAppViewer::cleanup()
// gDXHardware.cleanup();
//#endif // LL_WINDOWS
-#if LL_LCD_COMPILE
- // shut down the LCD window on a logitech keyboard, if there is one
- delete gLcdScreen;
- gLcdScreen = NULL;
-#endif
-
LLVolumeMgr* volume_manager = LLPrimitive::getVolumeManager();
if (!volume_manager->cleanup())
{
@@ -1258,6 +1436,8 @@ bool LLAppViewer::cleanup()
}
LLPrimitive::cleanupVolumeManager();
+ llinfos << "Additional Cleanup..." << llendflush;
+
LLViewerParcelMgr::cleanupGlobals();
// *Note: this is where gViewerStats used to be deleted.
@@ -1277,9 +1457,11 @@ bool LLAppViewer::cleanup()
// Also after shutting down the messaging system since it has VFS dependencies
//
+ llinfos << "Cleaning up VFS" << llendflush;
LLVFile::cleanupClass();
- llinfos << "VFS cleaned up" << llendflush;
+ llinfos << "Saving Data" << llendflush;
+
// Quitting with "Remember Password" turned off should always stomp your
// saved password, whether or not you successfully logged in. JC
if (!gSavedSettings.getBOOL("RememberPassword"))
@@ -1292,20 +1474,28 @@ bool LLAppViewer::cleanup()
// Must do this after all panels have been deleted because panels that have persistent rects
// save their rects on delete.
- gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
+ gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
+
+ LLUIColorTable::instance().saveUserSettings();
- // PerAccountSettingsFile should be empty if no use has been logged on.
+ // PerAccountSettingsFile should be empty if no user has been logged on.
// *FIX:Mani This should get really saved in a "logoff" mode.
- gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE);
- llinfos << "Saved settings" << llendflush;
+ if (gSavedSettings.getString("PerAccountSettingsFile").empty())
+ {
+ llinfos << "Not saving per-account settings; don't know the account name yet." << llendl;
+ }
+ else
+ {
+ gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE);
+ llinfos << "Saved settings" << llendflush;
+ }
std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE);
// save all settings, even if equals defaults
gCrashSettings.saveToFile(crash_settings_filename, FALSE);
- gSavedSettings.cleanup();
- gColors.cleanup();
- gCrashSettings.cleanup();
+ std::string warnings_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Warnings"));
+ gWarningSettings.saveToFile(warnings_settings_filename, TRUE);
// Save URL history file
LLURLHistory::saveFile("url_history.xml");
@@ -1324,6 +1514,12 @@ bool LLAppViewer::cleanup()
writeDebugInfo();
+ LLLocationHistory::getInstance()->save();
+
+ LLAvatarIconIDCache::getInstance()->save();
+
+ llinfos << "Shutting down Threads" << llendflush;
+
// Let threads finish
LLTimer idleTimer;
idleTimer.reset();
@@ -1349,18 +1545,45 @@ bool LLAppViewer::cleanup()
sTextureCache->shutdown();
sTextureFetch->shutdown();
sImageDecodeThread->shutdown();
+
delete sTextureCache;
sTextureCache = NULL;
delete sTextureFetch;
sTextureFetch = NULL;
delete sImageDecodeThread;
sImageDecodeThread = NULL;
+ delete mFastTimerLogThread;
+ mFastTimerLogThread = NULL;
+
+ if (LLFastTimerView::sAnalyzePerformance)
+ {
+ llinfos << "Analyzing performance" << llendl;
+
+ if(LLFastTimer::sLog)
+ {
+ LLFastTimerView::doAnalysis(
+ gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance_baseline.slp"),
+ gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance.slp"),
+ gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance_report.csv"));
+ }
+ if(LLFastTimer::sMetricLog)
+ {
+ LLFastTimerView::doAnalysis(
+ gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric_baseline.slp"),
+ gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric.slp"),
+ gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric_report.csv"));
+ }
+ }
+ LLMetricPerformanceTester::cleanClass() ;
+
+ llinfos << "Cleaning up Media and Textures" << llendflush;
//Note:
- //LLViewerMedia::cleanupClass() has to be put before gImageList.shutdown()
+ //LLViewerMedia::cleanupClass() has to be put before gTextureList.shutdown()
//because some new image might be generated during cleaning up media. --bao
LLViewerMedia::cleanupClass();
- gImageList.shutdown(); // shutdown again in case a callback added something
+ LLViewerParcelMedia::cleanupClass();
+ gTextureList.shutdown(); // shutdown again in case a callback added something
LLUIImageList::getInstance()->cleanUp();
// This should eventually be done in LLAppViewer
@@ -1368,28 +1591,31 @@ bool LLAppViewer::cleanup()
LLVFSThread::cleanupClass();
LLLFSThread::cleanupClass();
- llinfos << "VFS Thread finished" << llendflush;
-
#ifndef LL_RELEASE_FOR_DOWNLOAD
llinfos << "Auditing VFS" << llendl;
gVFS->audit();
#endif
+ llinfos << "Misc Cleanup" << llendflush;
+
// For safety, the LLVFS has to be deleted *after* LLVFSThread. This should be cleaned up.
// (LLVFS doesn't know about LLVFSThread so can't kill pending requests) -Steve
delete gStaticVFS;
gStaticVFS = NULL;
delete gVFS;
gVFS = NULL;
+
+ gSavedSettings.cleanup();
+ LLUIColorTable::instance().clear();
+ gCrashSettings.cleanup();
LLWatchdog::getInstance()->cleanup();
+ llinfos << "Shutting down message system" << llendflush;
end_messaging_system();
- llinfos << "Message system deleted." << llendflush;
// *NOTE:Mani - The following call is not thread safe.
LLCurl::cleanupClass();
- llinfos << "LLCurl cleaned up." << llendflush;
// If we're exiting to launch an URL, do that here so the screen
// is at the right resolution before we launch IE.
@@ -1408,7 +1634,9 @@ bool LLAppViewer::cleanup()
llinfos << "File launched." << llendflush;
}
- llinfos << "Goodbye" << llendflush;
+ ll_close_fail_log();
+
+ llinfos << "Goodbye!" << llendflush;
// return 0;
return true;
@@ -1449,14 +1677,21 @@ bool LLAppViewer::initThreads()
LLWatchdog::getInstance()->init(watchdog_killer_callback);
}
- LLVFSThread::initClass(enable_threads && true);
- LLLFSThread::initClass(enable_threads && true);
+ LLVFSThread::initClass(enable_threads && false);
+ LLLFSThread::initClass(enable_threads && false);
// Image decoding
- LLAppViewer::sImageDecodeThread = new LLWorkerThread("ImageDecode", enable_threads && true);
+ LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true);
LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true);
- LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), enable_threads && false);
- LLImage::initClass(LLAppViewer::getImageDecodeThread());
+ LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), sImageDecodeThread, enable_threads && false);
+ LLImage::initClass();
+
+ if (LLFastTimer::sLog || LLFastTimer::sMetricLog)
+ {
+ LLFastTimer::sLogLock = new LLMutex(NULL);
+ mFastTimerLogThread = new LLFastTimerLogThread();
+ mFastTimerLogThread->start();
+ }
// *FIX: no error handling here!
return true;
@@ -1465,7 +1700,7 @@ bool LLAppViewer::initThreads()
void errorCallback(const std::string &error_string)
{
#ifndef LL_RELEASE_FOR_DOWNLOAD
- OSMessageBox(error_string, "Fatal Error", OSMB_OK);
+ OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK);
#endif
//Set the ErrorActivated global so we know to create a marker file
@@ -1482,7 +1717,7 @@ bool LLAppViewer::initLogging()
LLError::initForApplication(
gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
LLError::setFatalFunction(errorCallback);
-
+
// Remove the last ".old" log file.
std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
"SecondLife.old");
@@ -1533,7 +1768,7 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
llinfos << "Attempting to load settings for the group " << settings_group
<< " - from location " << location_key << llendl;
- if(gSettings.find(settings_group) == gSettings.end())
+ if(!LLControlGroup::getInstance(settings_group))
{
llwarns << "No matching settings group for name " << settings_group << llendl;
continue;
@@ -1547,10 +1782,10 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
std::string custom_name_setting = file.get("NameFromSetting");
// *NOTE: Regardless of the group currently being lodaed,
// this setting is always read from the Global settings.
- if(gSettings[sGlobalSettingsName]->controlExists(custom_name_setting))
+ if(LLControlGroup::getInstance(sGlobalSettingsName)->controlExists(custom_name_setting))
{
std::string file_name =
- gSettings[sGlobalSettingsName]->getString(custom_name_setting);
+ LLControlGroup::getInstance(sGlobalSettingsName)->getString(custom_name_setting);
full_settings_path = file_name;
}
}
@@ -1567,7 +1802,7 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
requirement = file.get("Requirement").asInteger();
}
- if(!gSettings[settings_group]->loadFromFile(full_settings_path, set_defaults))
+ if(!LLControlGroup::getInstance(settings_group)->loadFromFile(full_settings_path, set_defaults))
{
if(requirement == 1)
{
@@ -1607,17 +1842,17 @@ std::string LLAppViewer::getSettingsFilename(const std::string& location_key,
return std::string();
}
+void LLAppViewer::loadColorSettings()
+{
+ LLUIColorTable::instance().loadFromSettings();
+}
+
bool LLAppViewer::initConfiguration()
{
- //Set up internal pointers
- gSettings[sGlobalSettingsName] = &gSavedSettings;
- gSettings[sPerAccountSettingsName] = &gSavedPerAccountSettings;
- gSettings[sCrashSettingsName] = &gCrashSettings;
-
//Load settings files list
std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml");
- LLControlGroup settings_control;
- llinfos << "Loading settings file list" << settings_file_list << llendl;
+ LLControlGroup settings_control("SettingsFiles");
+ llinfos << "Loading settings file list " << settings_file_list << llendl;
if (0 == settings_control.loadFromFile(settings_file_list))
{
llerrs << "Cannot load default configuration file " << settings_file_list << llendl;
@@ -1640,26 +1875,34 @@ bool LLAppViewer::initConfiguration()
if(!loadSettingsFromDirectory("Default", set_defaults))
{
std::ostringstream msg;
- msg << "Second Life could not load its default settings file. \n"
- << "The installation may be corrupted. \n";
-
- OSMessageBox(
- msg.str(),
- LLStringUtil::null,
- OSMB_OK);
-
+ msg << "Unable to load default settings file. The installation may be corrupted.";
+ OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK);
return false;
}
-
- // - set procedural settings
+
+ LLUI::setupPaths(); // setup paths for LLTrans based on settings files only
+ LLTransUtil::parseStrings("strings.xml", default_trans_args);
+ LLTransUtil::parseLanguageStrings("language_settings.xml");
+ // - set procedural settings
+ // Note: can't use LL_PATH_PER_SL_ACCOUNT for any of these since we haven't logged in yet
gSavedSettings.setString("ClientSettingsFile",
gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Global")));
- gSavedSettings.setString("VersionChannelName", LL_CHANNEL);
+ gSavedSettings.setString("VersionChannelName", LLVersionInfo::getChannel());
#ifndef LL_RELEASE_FOR_DOWNLOAD
- gSavedSettings.setBOOL("ShowConsoleWindow", TRUE);
- gSavedSettings.setBOOL("AllowMultipleViewers", TRUE);
+ // provide developer build only overrides for these control variables that are not
+ // persisted to settings.xml
+ LLControlVariable* c = gSavedSettings.getControl("ShowConsoleWindow");
+ if (c)
+ {
+ c->setValue(true, false);
+ }
+ c = gSavedSettings.getControl("AllowMultipleViewers");
+ if (c)
+ {
+ c->setValue(true, false);
+ }
#endif
//*FIX:Mani - Set default to disabling watchdog mainloop
@@ -1674,56 +1917,47 @@ bool LLAppViewer::initConfiguration()
gSavedSettings.setBOOL("WatchdogEnabled", FALSE);
#endif
- gCrashSettings.getControl(CRASH_BEHAVIOR_SETTING)->getSignal()->connect(boost::bind(&handleCrashSubmitBehaviorChanged, _1));
+ gCrashSettings.getControl(CRASH_BEHAVIOR_SETTING)->getSignal()->connect(boost::bind(&handleCrashSubmitBehaviorChanged, _2));
// These are warnings that appear on the first experience of that condition.
// They are already set in the settings_default.xml file, but still need to be added to LLFirstUse
// for disable/reset ability
- LLFirstUse::addConfigVariable("FirstBalanceIncrease");
- LLFirstUse::addConfigVariable("FirstBalanceDecrease");
- LLFirstUse::addConfigVariable("FirstSit");
- LLFirstUse::addConfigVariable("FirstMap");
- LLFirstUse::addConfigVariable("FirstGoTo");
- LLFirstUse::addConfigVariable("FirstBuild");
- LLFirstUse::addConfigVariable("FirstLeftClickNoHit");
- LLFirstUse::addConfigVariable("FirstTeleport");
- LLFirstUse::addConfigVariable("FirstOverrideKeys");
- LLFirstUse::addConfigVariable("FirstAttach");
- LLFirstUse::addConfigVariable("FirstAppearance");
- LLFirstUse::addConfigVariable("FirstInventory");
- LLFirstUse::addConfigVariable("FirstSandbox");
- LLFirstUse::addConfigVariable("FirstFlexible");
- LLFirstUse::addConfigVariable("FirstDebugMenus");
- LLFirstUse::addConfigVariable("FirstStreamingMusic");
- LLFirstUse::addConfigVariable("FirstStreamingVideo");
- LLFirstUse::addConfigVariable("FirstSculptedPrim");
- LLFirstUse::addConfigVariable("FirstVoice");
- LLFirstUse::addConfigVariable("FirstMedia");
+// LLFirstUse::addConfigVariable("FirstBalanceIncrease");
+// LLFirstUse::addConfigVariable("FirstBalanceDecrease");
+// LLFirstUse::addConfigVariable("FirstSit");
+// LLFirstUse::addConfigVariable("FirstMap");
+// LLFirstUse::addConfigVariable("FirstGoTo");
+// LLFirstUse::addConfigVariable("FirstBuild");
+// LLFirstUse::addConfigVariable("FirstLeftClickNoHit");
+// LLFirstUse::addConfigVariable("FirstTeleport");
+// LLFirstUse::addConfigVariable("FirstOverrideKeys");
+// LLFirstUse::addConfigVariable("FirstAttach");
+// LLFirstUse::addConfigVariable("FirstAppearance");
+// LLFirstUse::addConfigVariable("FirstInventory");
+// LLFirstUse::addConfigVariable("FirstSandbox");
+// LLFirstUse::addConfigVariable("FirstFlexible");
+// LLFirstUse::addConfigVariable("FirstDebugMenus");
+// LLFirstUse::addConfigVariable("FirstStreamingMedia");
+// LLFirstUse::addConfigVariable("FirstSculptedPrim");
+// LLFirstUse::addConfigVariable("FirstVoice");
+// LLFirstUse::addConfigVariable("FirstMedia");
// - read command line settings.
LLControlGroupCLP clp;
std::string cmd_line_config = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,
"cmd_line.xml");
+
clp.configure(cmd_line_config, &gSavedSettings);
if(!initParseCommandLine(clp))
{
- llwarns
- << "Error parsing command line options. Command Line options ignored."
- << llendl;
-
+ llwarns << "Error parsing command line options. Command Line options ignored." << llendl;
+
llinfos << "Command line usage:\n" << clp << llendl;
std::ostringstream msg;
- msg << "Second Life found an error parsing the command line. \n"
- << "Please see: http://wiki.secondlife.com/wiki/Client_parameters \n"
- << "Error: " << clp.getErrorMessage();
-
- OSMessageBox(
- msg.str(),
- LLStringUtil::null,
- OSMB_OK);
-
+ msg << LLTrans::getString("MBCmdLineError") << clp.getErrorMessage();
+ OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK);
return false;
}
@@ -1743,7 +1977,6 @@ bool LLAppViewer::initConfiguration()
// - load overrides from user_settings
loadSettingsFromDirectory("User");
-
// - apply command line settings
clp.notify();
@@ -1757,7 +1990,7 @@ bool LLAppViewer::initConfiguration()
if(clp.hasOption("help"))
{
std::ostringstream msg;
- msg << "Command line usage:\n" << clp;
+ msg << LLTrans::getString("MBCmdLineUsg") << "\n" << clp;
llinfos << msg.str() << llendl;
OSMessageBox(
@@ -1768,36 +2001,6 @@ bool LLAppViewer::initConfiguration()
return false;
}
- //////////////////////////
- // Apply settings...
- if(clp.hasOption("setdefault"))
- {
- //const LLCommandLineParser::token_vector_t& setdefault = clp.getOption("setdefault");
- //if(0x1 & setdefault.size())
- //{
- // llwarns << "Invalid '--setdefault' parameter count." << llendl;
- //}
- //else
- //{
- // LLCommandLineParser::token_vector_t::const_iterator itr = setdefault.begin();
- // for(; itr != setdefault.end(); ++itr)
- // {
- // const std::string& name = *itr;
- // const std::string& value = *(++itr);
- // LLControlVariable* c = gSettings[sGlobalSettingsName]->getControl(name);
- // if(c)
- // {
- // c->setDefault(value);
- // }
- // else
- // {
- // llwarns << "'--setdefault' specified with unknown setting: '"
- // << name << "'." << llendl;
- // }
- // }
- //}
- }
-
if(clp.hasOption("set"))
{
const LLCommandLineParser::token_vector_t& set_values = clp.getOption("set");
@@ -1812,7 +2015,7 @@ bool LLAppViewer::initConfiguration()
{
const std::string& name = *itr;
const std::string& value = *(++itr);
- LLControlVariable* c = gSettings[sGlobalSettingsName]->getControl(name);
+ LLControlVariable* c = LLControlGroup::getInstance(sGlobalSettingsName)->getControl(name);
if(c)
{
c->setValue(value, false);
@@ -1834,6 +2037,73 @@ bool LLAppViewer::initConfiguration()
gCrashOnStartup = TRUE;
}
+ if (clp.hasOption("logperformance"))
+ {
+ LLFastTimer::sLog = TRUE;
+ }
+
+ if(clp.hasOption("logmetrics"))
+ {
+ LLFastTimer::sMetricLog = TRUE ;
+ }
+
+ if (clp.hasOption("graphicslevel"))
+ {
+ const LLCommandLineParser::token_vector_t& value = clp.getOption("graphicslevel");
+ if(value.size() != 1)
+ {
+ llwarns << "Usage: -graphicslevel <0-3>" << llendl;
+ }
+ else
+ {
+ std::string detail = value.front();
+ mForceGraphicsDetail = TRUE;
+
+ switch (detail.c_str()[0])
+ {
+ case '0':
+ gSavedSettings.setU32("RenderQualityPerformance", 0);
+ break;
+ case '1':
+ gSavedSettings.setU32("RenderQualityPerformance", 1);
+ break;
+ case '2':
+ gSavedSettings.setU32("RenderQualityPerformance", 2);
+ break;
+ case '3':
+ gSavedSettings.setU32("RenderQualityPerformance", 3);
+ break;
+ default:
+ mForceGraphicsDetail = FALSE;
+ llwarns << "Usage: -graphicslevel <0-3>" << llendl;
+ break;
+ }
+ }
+ }
+
+ if (clp.hasOption("analyzeperformance"))
+ {
+ LLFastTimerView::sAnalyzePerformance = TRUE;
+ }
+
+ if (clp.hasOption("replaysession"))
+ {
+ LLAgentPilot::sReplaySession = TRUE;
+ }
+
+ if (clp.hasOption("nonotifications"))
+ {
+ gSavedSettings.setBOOL("IgnoreAllNotifications", TRUE);
+ }
+
+ if (clp.hasOption("debugsession"))
+ {
+ gDebugSession = TRUE;
+ gDebugGL = TRUE;
+
+ ll_init_fail_log(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "test_failures.log"));
+ }
+
// Handle slurl use. NOTE: Don't let SL-55321 reappear.
// *FIX: This init code should be made more robust to prevent
@@ -1854,7 +2124,7 @@ bool LLAppViewer::initConfiguration()
if(clp.hasOption("url"))
{
std::string slurl = clp.getOption("url")[0];
- if (LLURLDispatcher::isSLURLCommand(slurl))
+ if (LLSLURL::isSLURLCommand(slurl))
{
LLStartUp::sSLURLCommand = slurl;
}
@@ -1866,9 +2136,9 @@ bool LLAppViewer::initConfiguration()
else if(clp.hasOption("slurl"))
{
std::string slurl = clp.getOption("slurl")[0];
- if(LLURLDispatcher::isSLURL(slurl))
+ if(LLSLURL::isSLURL(slurl))
{
- if (LLURLDispatcher::isSLURLCommand(slurl))
+ if (LLSLURL::isSLURLCommand(slurl))
{
LLStartUp::sSLURLCommand = slurl;
}
@@ -1882,13 +2152,12 @@ bool LLAppViewer::initConfiguration()
const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent");
if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString())
{
- gDirUtilp->setSkinFolder(skinfolder->getValue().asString());
+ // hack to force the skin to default.
+ //gDirUtilp->setSkinFolder(skinfolder->getValue().asString());
+ gDirUtilp->setSkinFolder("default");
}
mYieldTime = gSavedSettings.getS32("YieldTime");
-
- // XUI:translate
- gSecondLife = "Second Life";
// Read skin/branding settings if specified.
//if (! gDirUtilp->getSkinDir().empty() )
@@ -1905,7 +2174,7 @@ bool LLAppViewer::initConfiguration()
#if LL_DARWIN
// Initialize apple menubar and various callbacks
- init_apple_menu(gSecondLife.c_str());
+ init_apple_menu(LLTrans::getString("APP_NAME").c_str());
#if __ppc__
// If the CPU doesn't have Altivec (i.e. it's not at least a G4), don't go any further.
@@ -1913,7 +2182,7 @@ bool LLAppViewer::initConfiguration()
if(!gSysCPU.hasAltivec())
{
std::ostringstream msg;
- msg << gSecondLife << " requires a processor with AltiVec (G4 or later).";
+ msg << LLTrans::getString("MBRequiresAltiVec");
OSMessageBox(
msg.str(),
LLStringUtil::null,
@@ -1928,7 +2197,7 @@ bool LLAppViewer::initConfiguration()
// Display splash screen. Must be after above check for previous
// crash as this dialog is always frontmost.
std::ostringstream splash_msg;
- splash_msg << "Loading " << gSecondLife << "...";
+ splash_msg << "Loading " << LLTrans::getString("SECOND_LIFE") << "...";
LLSplashScreen::show();
LLSplashScreen::update(splash_msg.str());
@@ -1944,12 +2213,11 @@ bool LLAppViewer::initConfiguration()
//
// Set the name of the window
//
-#if LL_RELEASE_FOR_DOWNLOAD
- gWindowTitle = gSecondLife;
-#elif LL_DEBUG
- gWindowTitle = gSecondLife + std::string(" [DEBUG] ") + gArgs;
+ gWindowTitle = LLTrans::getString("APP_NAME");
+#if LL_DEBUG
+ gWindowTitle += std::string(" [DEBUG] ") + gArgs;
#else
- gWindowTitle = gSecondLife + std::string(" ") + gArgs;
+ gWindowTitle += std::string(" ") + gArgs;
#endif
LLStringUtil::truncate(gWindowTitle, 255);
@@ -1986,11 +2254,7 @@ bool LLAppViewer::initConfiguration()
if (mSecondInstance)
{
std::ostringstream msg;
- msg <<
- gSecondLife << " is already running.\n"
- "\n"
- "Check your task bar for a minimized copy of the program.\n"
- "If this message persists, restart your computer.",
+ msg << LLTrans::getString("MBAlreadyRunning");
OSMessageBox(
msg.str(),
LLStringUtil::null,
@@ -2035,6 +2299,8 @@ bool LLAppViewer::initConfiguration()
gLastRunVersion = gSavedSettings.getString("LastRunVersion");
+ loadColorSettings();
+
return true; // Config was successful.
}
@@ -2042,7 +2308,7 @@ bool LLAppViewer::initConfiguration()
void LLAppViewer::checkForCrash(void)
{
-#if 1 //*REMOVE:Mani LL_SEND_CRASH_REPORTS
+#if LL_SEND_CRASH_REPORTS
//*NOTE:Mani The current state of the crash handler has the MacOSX
// sending all crash reports as freezes, in order to let
// the MacOSX CrashRepoter generate stacks before spawning the
@@ -2052,23 +2318,32 @@ void LLAppViewer::checkForCrash(void)
#if LL_DARWIN
if(gLastExecEvent != LAST_EXEC_NORMAL)
#else
- if (gLastExecEvent == LAST_EXEC_FROZE || gLastExecEvent == LAST_EXEC_OTHER_CRASH)
+ if (gLastExecEvent == LAST_EXEC_FROZE)
#endif
{
llinfos << "Last execution froze, requesting to send crash report." << llendl;
//
// Pop up a freeze or crash warning dialog
//
- std::ostringstream msg;
- msg << gSecondLife
- << " appears to have frozen or crashed on the previous run.\n"
- << "Would you like to send a crash report?";
- std::string alert;
- alert = gSecondLife;
- alert += " Alert";
- S32 choice = OSMessageBox(msg.str(),
+ S32 choice;
+ if(gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING) == CRASH_BEHAVIOR_ASK)
+ {
+ std::ostringstream msg;
+ msg << LLTrans::getString("MBFrozenCrashed");
+ std::string alert = LLTrans::getString("APP_NAME") + " " + LLTrans::getString("MBAlert");
+ choice = OSMessageBox(msg.str(),
alert,
OSMB_YESNO);
+ }
+ else if(gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING) == CRASH_BEHAVIOR_NEVER_SEND)
+ {
+ choice = OSBTN_NO;
+ }
+ else
+ {
+ choice = OSBTN_YES;
+ }
+
if (OSBTN_YES == choice)
{
llinfos << "Sending crash report." << llendl;
@@ -2102,11 +2377,13 @@ bool LLAppViewer::initWindow()
gSavedSettings.getS32("WindowX"), gSavedSettings.getS32("WindowY"),
gSavedSettings.getS32("WindowWidth"), gSavedSettings.getS32("WindowHeight"),
FALSE, ignorePixelDepth);
+
+ LLNotificationsUI::LLNotificationManager::getInstance();
- if (gSavedSettings.getBOOL("FullScreen"))
+ if (gSavedSettings.getBOOL("WindowFullScreen"))
{
+ // request to go full screen... which will be delayed until login
gViewerWindow->toggleFullscreen(FALSE);
- // request to go full screen... which will be delayed until login
}
if (gSavedSettings.getBOOL("WindowMaximized"))
@@ -2121,6 +2398,11 @@ bool LLAppViewer::initWindow()
// Initialize GL stuff
//
+ if (mForceGraphicsDetail)
+ {
+ LLFeatureManager::getInstance()->setGraphicsLevel(gSavedSettings.getU32("RenderQualityPerformance"), false);
+ }
+
// Set this flag in case we crash while initializing GL
gSavedSettings.setBOOL("RenderInitError", TRUE);
gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
@@ -2141,9 +2423,6 @@ bool LLAppViewer::initWindow()
LLUI::sWindow = gViewerWindow->getWindow();
- LLTrans::parseStrings("strings.xml");
- LLUITrans::parseStrings("ui_strings.xml");
-
// Show watch cursor
gViewerWindow->setCursor(UI_CURSOR_WAIT);
@@ -2170,17 +2449,10 @@ void LLAppViewer::cleanupSavedSettings()
{
gSavedSettings.setBOOL("MouseSun", FALSE);
- gSavedSettings.setBOOL("FlyBtnState", FALSE);
-
- gSavedSettings.setBOOL("FirstPersonBtnState", FALSE);
- gSavedSettings.setBOOL("ThirdPersonBtnState", TRUE);
- gSavedSettings.setBOOL("BuildBtnState", FALSE);
-
gSavedSettings.setBOOL("UseEnergy", TRUE); // force toggle to turn off, since sends message to simulator
gSavedSettings.setBOOL("DebugWindowProc", gDebugWindowProc);
- gSavedSettings.setBOOL("AllowTapTapHoldRun", gAllowTapTapHoldRun);
gSavedSettings.setBOOL("ShowObjectUpdates", gShowObjectUpdates);
if (!gNoRender)
@@ -2206,8 +2478,7 @@ void LLAppViewer::cleanupSavedSettings()
}
}
- gSavedSettings.setF32("MapScale", gMapScale );
- gSavedSettings.setBOOL("ShowHoverTips", LLHoverView::sShowHoverTips);
+ gSavedSettings.setF32("MapScale", LLWorldMapView::sMapScale );
// Some things are cached in LLAgent.
if (gAgent.mInitialized)
@@ -2227,10 +2498,10 @@ void LLAppViewer::writeSystemInfo()
gDebugInfo["SLLog"] = LLError::logFileName();
gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName");
- gDebugInfo["ClientInfo"]["MajorVersion"] = LL_VERSION_MAJOR;
- gDebugInfo["ClientInfo"]["MinorVersion"] = LL_VERSION_MINOR;
- gDebugInfo["ClientInfo"]["PatchVersion"] = LL_VERSION_PATCH;
- gDebugInfo["ClientInfo"]["BuildVersion"] = LL_VERSION_BUILD;
+ gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor();
+ gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor();
+ gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::getPatch();
+ gDebugInfo["ClientInfo"]["BuildVersion"] = LLVersionInfo::getBuild();
gDebugInfo["CAFilename"] = gDirUtilp->getCAFile();
@@ -2263,9 +2534,8 @@ void LLAppViewer::writeSystemInfo()
gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)true;
// Dump some debugging info
- LL_INFOS("SystemInfo") << gSecondLife
- << " version " << LL_VERSION_MAJOR << "." << LL_VERSION_MINOR << "." << LL_VERSION_PATCH
- << LL_ENDL;
+ LL_INFOS("SystemInfo") << LLTrans::getString("APP_NAME")
+ << " version " << LLVersionInfo::getShortVersion() << LL_ENDL;
// Dump the local time and time zone
time_t now;
@@ -2319,10 +2589,10 @@ void LLAppViewer::handleViewerCrash()
//to check against no matter what
gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName");
- gDebugInfo["ClientInfo"]["MajorVersion"] = LL_VERSION_MAJOR;
- gDebugInfo["ClientInfo"]["MinorVersion"] = LL_VERSION_MINOR;
- gDebugInfo["ClientInfo"]["PatchVersion"] = LL_VERSION_PATCH;
- gDebugInfo["ClientInfo"]["BuildVersion"] = LL_VERSION_BUILD;
+ gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor();
+ gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor();
+ gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::getPatch();
+ gDebugInfo["ClientInfo"]["BuildVersion"] = LLVersionInfo::getBuild();
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
if ( parcel && parcel->getMusicURL()[0])
@@ -2341,7 +2611,9 @@ void LLAppViewer::handleViewerCrash()
gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath();
gDebugInfo["SessionLength"] = F32(LLFrameTimer::getElapsedSeconds());
gDebugInfo["StartupState"] = LLStartUp::getStartupStateString();
- gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer) getCurrentRSS() >> 10;
+ gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer) LLMemory::getCurrentRSS() >> 10;
+ gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin();
+ gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall");
if(gLogoutInProgress)
{
@@ -2531,7 +2803,7 @@ void LLAppViewer::initMarkerFile()
// Create the marker file for this execution & lock it
apr_status_t s;
- s = mMarkerFile.open(mMarkerFileName, LL_APR_W, gAPRPoolp);
+ s = mMarkerFile.open(mMarkerFileName, LL_APR_W, TRUE);
if (s == APR_SUCCESS && mMarkerFile.getFileHandle())
{
@@ -2599,6 +2871,8 @@ void LLAppViewer::requestQuit()
gFloaterView->closeAllChildren(true);
}
+ LLSideTray::getInstance()->notifyChildren(LLSD().with("request","quit"));
+
send_stats();
gLogoutTimer.reset();
@@ -2607,7 +2881,7 @@ void LLAppViewer::requestQuit()
static bool finish_quit(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0)
{
@@ -2619,7 +2893,7 @@ static LLNotificationFunctorRegistration finish_quit_reg("ConfirmQuit", finish_q
void LLAppViewer::userQuit()
{
- LLNotifications::instance().add("ConfirmQuit");
+ LLNotificationsUtil::add("ConfirmQuit");
}
static bool finish_early_exit(const LLSD& notification, const LLSD& response)
@@ -2632,7 +2906,7 @@ void LLAppViewer::earlyExit(const std::string& name, const LLSD& substitutions)
{
llwarns << "app_early_exit: " << name << llendl;
gDoDisconnect = TRUE;
- LLNotifications::instance().add(name, substitutions, LLSD(), finish_early_exit);
+ LLNotificationsUtil::add(name, substitutions, LLSD(), finish_early_exit);
}
void LLAppViewer::forceExit(S32 arg)
@@ -2750,12 +3024,14 @@ bool LLAppViewer::initCache()
gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation"));
purgeCache(); // purge old cache
gSavedSettings.setString("CacheLocation", new_cache_location);
+ gSavedSettings.setString("CacheLocationTopFolder", gDirUtilp->getBaseFileName(new_cache_location));
}
if (!gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation")))
{
LL_WARNS("AppCache") << "Unable to set cache location" << LL_ENDL;
gSavedSettings.setString("CacheLocation", "");
+ gSavedSettings.setString("CacheLocationTopFolder", "");
}
if (mPurgeCache)
@@ -2935,12 +3211,12 @@ void LLAppViewer::purgeCache()
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask);
}
-const std::string& LLAppViewer::getSecondLifeTitle() const
+std::string LLAppViewer::getSecondLifeTitle() const
{
- return gSecondLife;
+ return LLTrans::getString("APP_NAME");
}
-const std::string& LLAppViewer::getWindowTitle() const
+std::string LLAppViewer::getWindowTitle() const
{
return gWindowTitle;
}
@@ -2948,7 +3224,7 @@ const std::string& LLAppViewer::getWindowTitle() const
// Callback from a dialog indicating user was logged out.
bool finish_disconnect(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (1 == option)
{
@@ -2974,7 +3250,7 @@ void LLAppViewer::forceDisconnect(const std::string& mesg)
return;
}
- // Translate the message if possible
+ // *TODO: Translate the message if possible
std::string big_reason = LLAgent::sTeleportErrorMessages[mesg];
if ( big_reason.size() == 0 )
{
@@ -2988,12 +3264,12 @@ void LLAppViewer::forceDisconnect(const std::string& mesg)
{
// Tell users what happened
args["ERROR_MESSAGE"] = big_reason;
- LLNotifications::instance().add("ErrorMessage", args, LLSD(), &finish_forced_disconnect);
+ LLNotificationsUtil::add("ErrorMessage", args, LLSD(), &finish_forced_disconnect);
}
else
{
args["MESSAGE"] = big_reason;
- LLNotifications::instance().add("YouHaveBeenLoggedOut", args, LLSD(), &finish_disconnect );
+ LLNotificationsUtil::add("YouHaveBeenLoggedOut", args, LLSD(), &finish_disconnect );
}
}
@@ -3046,7 +3322,7 @@ void LLAppViewer::saveFinalSnapshot()
snap_filename += gDirUtilp->getDirDelimiter();
snap_filename += SCREEN_LAST_FILENAME;
// use full pixel dimensions of viewer window (not post-scale dimensions)
- gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight(), FALSE, TRUE);
+ gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw(), FALSE, TRUE);
mSavedFinalSnapshot = TRUE;
}
}
@@ -3102,6 +3378,15 @@ public:
}
};
+static LLFastTimer::DeclareTimer FTM_AUDIO_UPDATE("Update Audio");
+static LLFastTimer::DeclareTimer FTM_CLEANUP("Cleanup");
+static LLFastTimer::DeclareTimer FTM_IDLE_CB("Idle Callbacks");
+static LLFastTimer::DeclareTimer FTM_LOD_UPDATE("Update LOD");
+static LLFastTimer::DeclareTimer FTM_OBJECTLIST_UPDATE("Update Objectlist");
+static LLFastTimer::DeclareTimer FTM_REGION_UPDATE("Update Region");
+static LLFastTimer::DeclareTimer FTM_WORLD_UPDATE("Update World");
+static LLFastTimer::DeclareTimer FTM_NETWORK("Network");
+
///////////////////////////////////////////////////////
// idle()
//
@@ -3110,6 +3395,7 @@ public:
///////////////////////////////////////////////////////
void LLAppViewer::idle()
{
+ LLMemType mt_idle(LLMemType::MTYPE_IDLE);
pingMainloopTimeout("Main:Idle");
// Update frame timers
@@ -3153,14 +3439,16 @@ void LLAppViewer::idle()
//
// Special case idle if still starting up
//
-
if (LLStartUp::getStartupState() < STATE_STARTED)
{
// Skip rest if idle startup returns false (essentially, no world yet)
+ gGLActive = TRUE;
if (!idle_startup())
{
+ gGLActive = FALSE;
return;
}
+ gGLActive = FALSE;
}
@@ -3168,7 +3456,7 @@ void LLAppViewer::idle()
if (!gDisconnected)
{
- LLFastTimer t(LLFastTimer::FTM_NETWORK);
+ LLFastTimer t(FTM_NETWORK);
// Update spaceserver timeinfo
LLWorld::getInstance()->setSpaceTimeUSec(LLWorld::getInstance()->getSpaceTimeUSec() + (U32)(dt_raw * SEC_TO_MICROSEC));
@@ -3193,7 +3481,7 @@ void LLAppViewer::idle()
// When appropriate, update agent location to the simulator.
F32 agent_update_time = agent_update_timer.getElapsedTimeF32();
BOOL flags_changed = gAgent.controlFlagsDirty() || (last_control_flags != gAgent.getControlFlags());
-
+
if (flags_changed || (agent_update_time > (1.0f / (F32) AGENT_UPDATES_PER_SECOND)))
{
// Send avatar and camera info
@@ -3208,7 +3496,6 @@ void LLAppViewer::idle()
// Manage statistics
//
//
-
{
// Initialize the viewer_stats_timer with an already elapsed time
// of SEND_STATS_PERIOD so that the initial stats report will
@@ -3246,12 +3533,11 @@ void LLAppViewer::idle()
gObjectList.mNumUnknownUpdates = 0;
}
}
- gFrameStats.addFrameData();
}
-
+
if (!gDisconnected)
{
- LLFastTimer t(LLFastTimer::FTM_NETWORK);
+ LLFastTimer t(FTM_NETWORK);
////////////////////////////////////////////////
//
@@ -3261,12 +3547,8 @@ void LLAppViewer::idle()
// floating throughout the various object lists.
//
- gFrameStats.start(LLFrameStats::IDLE_NETWORK);
- stop_glerror();
idleNetwork();
- stop_glerror();
-
- gFrameStats.start(LLFrameStats::AGENT_MISC);
+
// Check for away from keyboard, kick idle agents.
idle_afk_check();
@@ -3282,12 +3564,13 @@ void LLAppViewer::idle()
//
{
-// LLFastTimer t(LLFastTimer::FTM_IDLE_CB);
+// LLFastTimer t(FTM_IDLE_CB);
// Do event notifications if necessary. Yes, we may want to move this elsewhere.
gEventNotifier.update();
gIdleCallbacks.callFunctions();
+ gInventory.idleNotifyObservers();
}
if (gDisconnected)
@@ -3295,7 +3578,7 @@ void LLAppViewer::idle()
return;
}
- gViewerWindow->handlePerFrameHover();
+ gViewerWindow->updateUI();
///////////////////////////////////////
// Agent and camera movement
@@ -3311,14 +3594,13 @@ void LLAppViewer::idle()
{
// Handle pending gesture processing
- gGestureManager.update();
+ LLGestureManager::instance().update();
gAgent.updateAgentPosition(gFrameDTClamped, yaw, current_mouse.mX, current_mouse.mY);
}
{
- LLFastTimer t(LLFastTimer::FTM_OBJECTLIST_UPDATE); // Actually "object update"
- gFrameStats.start(LLFrameStats::OBJECT_UPDATE);
+ LLFastTimer t(FTM_OBJECTLIST_UPDATE); // Actually "object update"
if (!(logoutRequestSent() && hasSavedFinalSnapshot()))
{
@@ -3333,8 +3615,7 @@ void LLAppViewer::idle()
//
{
- LLFastTimer t(LLFastTimer::FTM_CLEANUP);
- gFrameStats.start(LLFrameStats::CLEAN_DEAD);
+ LLFastTimer t(FTM_CLEANUP);
gObjectList.cleanDeadObjects();
LLDrawable::cleanupDeadDrawables();
}
@@ -3353,21 +3634,18 @@ void LLAppViewer::idle()
//
{
- gFrameStats.start(LLFrameStats::UPDATE_EFFECTS);
LLSelectMgr::getInstance()->updateEffects();
LLHUDManager::getInstance()->cleanupEffects();
LLHUDManager::getInstance()->sendEffects();
}
- stop_glerror();
-
////////////////////////////////////////
//
// Unpack layer data that we've received
//
{
- LLFastTimer t(LLFastTimer::FTM_NETWORK);
+ LLFastTimer t(FTM_NETWORK);
gVLManager.unpackData();
}
@@ -3379,7 +3657,7 @@ void LLAppViewer::idle()
LLWorld::getInstance()->updateVisibilities();
{
const F32 max_region_update_time = .001f; // 1ms
- LLFastTimer t(LLFastTimer::FTM_REGION_UPDATE);
+ LLFastTimer t(FTM_REGION_UPDATE);
LLWorld::getInstance()->updateRegions(max_region_update_time);
}
@@ -3416,7 +3694,6 @@ void LLAppViewer::idle()
gWindVec.setVec(0.0f, 0.0f, 0.0f);
}
}
- stop_glerror();
//////////////////////////////////////
//
@@ -3426,14 +3703,11 @@ void LLAppViewer::idle()
if (!gNoRender)
{
- LLFastTimer t(LLFastTimer::FTM_WORLD_UPDATE);
- gFrameStats.start(LLFrameStats::UPDATE_MOVE);
+ LLFastTimer t(FTM_WORLD_UPDATE);
gPipeline.updateMove();
- gFrameStats.start(LLFrameStats::UPDATE_PARTICLES);
LLWorld::getInstance()->updateParticles();
}
- stop_glerror();
if (LLViewerJoystick::getInstance()->getOverrideCamera())
{
@@ -3449,15 +3723,17 @@ void LLAppViewer::idle()
gAgent.updateCamera();
}
+ // update media focus
+ LLViewerMediaFocus::getInstance()->update();
+
// objects and camera should be in sync, do LOD calculations now
{
- LLFastTimer t(LLFastTimer::FTM_LOD_UPDATE);
+ LLFastTimer t(FTM_LOD_UPDATE);
gObjectList.updateApparentAngles(gAgent);
}
{
- gFrameStats.start(LLFrameStats::AUDIO);
- LLFastTimer t(LLFastTimer::FTM_AUDIO_UPDATE);
+ LLFastTimer t(FTM_AUDIO_UPDATE);
if (gAudiop)
{
@@ -3476,10 +3752,9 @@ void LLAppViewer::idle()
// forcibly quit if it has taken too long
if (mQuitRequested)
{
+ gGLActive = TRUE;
idleShutdown();
}
-
- stop_glerror();
}
void LLAppViewer::idleShutdown()
@@ -3503,6 +3778,24 @@ void LLAppViewer::idleShutdown()
return;
}
+ if (LLSideTray::getInstance()->notifyChildren(LLSD().with("request","wait_quit")))
+ {
+ return;
+ }
+
+
+
+ // ProductEngine: Try moving this code to where we shut down sTextureCache in cleanup()
+ // *TODO: ugly
+ static bool saved_teleport_history = false;
+ if (!saved_teleport_history)
+ {
+ saved_teleport_history = true;
+ LLTeleportHistory::getInstance()->dump();
+ LLLocationHistory::getInstance()->save(); // *TODO: find a better place for doing this
+ return;
+ }
+
static bool saved_snapshot = false;
if (!saved_snapshot)
{
@@ -3597,8 +3890,11 @@ void LLAppViewer::sendLogoutRequest()
static F32 CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
#endif
+static LLFastTimer::DeclareTimer FTM_IDLE_NETWORK("Network");
+
void LLAppViewer::idleNetwork()
{
+ LLMemType mt_in(LLMemType::MTYPE_IDLE_NETWORK);
pingMainloopTimeout("idleNetwork");
LLError::LLCallStacks::clear() ;
llpushcallstacks ;
@@ -3608,17 +3904,17 @@ void LLAppViewer::idleNetwork()
if (!gSavedSettings.getBOOL("SpeedTest"))
{
- LLFastTimer t(LLFastTimer::FTM_IDLE_NETWORK); // decode
+ LLFastTimer t(FTM_IDLE_NETWORK); // decode
// deal with any queued name requests and replies.
gCacheName->processPending();
llpushcallstacks ;
LLTimer check_message_timer;
// Read all available packets from network
- stop_glerror();
const S64 frame_count = gFrameCount; // U32->S64
F32 total_time = 0.0f;
- while (gMessageSystem->checkAllMessages(frame_count, gServicePump))
+
+ while (gMessageSystem->checkAllMessages(frame_count, gServicePump))
{
if (gDoDisconnect)
{
@@ -3627,8 +3923,7 @@ void LLAppViewer::idleNetwork()
// server going down, so this is OK.
break;
}
- stop_glerror();
-
+
total_decoded++;
gPacketsIn++;
@@ -3647,6 +3942,7 @@ void LLAppViewer::idleNetwork()
break;
#endif
}
+
// Handle per-frame message system processing.
gMessageSystem->processAcks();
@@ -3667,9 +3963,7 @@ void LLAppViewer::idleNetwork()
// we want to clear the control after sending out all necessary agent updates
gAgent.resetControlFlags();
- stop_glerror();
-
-
+
// Decode enqueued messages...
S32 remaining_possible_decodes = MESSAGE_MAX_PER_FRAME - total_decoded;
@@ -3685,7 +3979,7 @@ void LLAppViewer::idleNetwork()
}
}
llpushcallstacks ;
- gObjectList.mNumNewObjectsStat.addValue(gObjectList.mNumNewObjects);
+ LLViewerStats::getInstance()->mNumNewObjectsStat.addValue(gObjectList.mNumNewObjects);
// Retransmit unacknowledged packets.
gXferManager->retransmitUnackedPackets();
@@ -3726,7 +4020,6 @@ void LLAppViewer::disconnectViewer()
llinfos << "Disconnecting viewer!" << llendl;
// Dump our frame statistics
- gFrameStats.dump();
// Remember if we were flying
gSavedSettings.setBOOL("FlyingAtExit", gAgent.getFlying() );
@@ -3738,35 +4031,6 @@ void LLAppViewer::disconnectViewer()
{
gFloaterView->restoreAll();
}
-
-
- std::list<LLFloater*> floaters_to_close;
- for(LLView::child_list_const_iter_t it = gFloaterView->getChildList()->begin();
- it != gFloaterView->getChildList()->end();
- ++it)
- {
- // The following names are defined in the
- // floater_image_preview.xml
- // floater_sound_preview.xml
- // floater_animation_preview.xml
- // files.
- LLFloater* fl = static_cast<LLFloater*>(*it);
- if(fl
- && (fl->getName() == "Image Preview"
- || fl->getName() == "Sound Preview"
- || fl->getName() == "Animation Preview"
- ))
- {
- floaters_to_close.push_back(fl);
- }
- }
-
- while(!floaters_to_close.empty())
- {
- LLFloater* fl = floaters_to_close.front();
- floaters_to_close.pop_front();
- fl->close();
- }
}
if (LLSelectMgr::getInstance())
@@ -3774,20 +4038,22 @@ void LLAppViewer::disconnectViewer()
LLSelectMgr::getInstance()->deselectAll();
}
- if (!gNoRender)
+ // save inventory if appropriate
+ gInventory.cache(gInventory.getRootFolderID(), gAgent.getID());
+ if (gInventory.getLibraryRootFolderID().notNull()
+ && gInventory.getLibraryOwnerID().notNull())
{
- // save inventory if appropriate
- gInventory.cache(gAgent.getInventoryRootID(), gAgent.getID());
- if(gInventoryLibraryRoot.notNull() && gInventoryLibraryOwner.notNull())
- {
- gInventory.cache(gInventoryLibraryRoot, gInventoryLibraryOwner);
- }
+ gInventory.cache(
+ gInventory.getLibraryRootFolderID(),
+ gInventory.getLibraryOwnerID());
}
saveNameCache();
// close inventory interface, close all windows
- LLInventoryView::cleanup();
+ LLFloaterInventory::cleanup();
+
+ gAgentWearables.cleanup();
// Also writes cached agent settings to gSavedSettings
gAgent.cleanup();
@@ -3823,7 +4089,7 @@ void LLAppViewer::forceErrorBadMemoryAccess()
return;
}
-void LLAppViewer::forceErrorInifiniteLoop()
+void LLAppViewer::forceErrorInfiniteLoop()
{
while(true)
{
@@ -3909,10 +4175,10 @@ void LLAppViewer::handleLoginComplete()
// Store some data to DebugInfo in case of a freeze.
gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName");
- gDebugInfo["ClientInfo"]["MajorVersion"] = LL_VERSION_MAJOR;
- gDebugInfo["ClientInfo"]["MinorVersion"] = LL_VERSION_MINOR;
- gDebugInfo["ClientInfo"]["PatchVersion"] = LL_VERSION_PATCH;
- gDebugInfo["ClientInfo"]["BuildVersion"] = LL_VERSION_BUILD;
+ gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor();
+ gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor();
+ gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::getPatch();
+ gDebugInfo["ClientInfo"]["BuildVersion"] = LLVersionInfo::getBuild();
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
if ( parcel && parcel->getMusicURL()[0])
@@ -3939,5 +4205,203 @@ void LLAppViewer::handleLoginComplete()
{
gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState();
}
+
+ mOnLoginCompleted();
+
writeDebugInfo();
}
+
+// *TODO - generalize this and move DSO wrangling to a helper class -brad
+void LLAppViewer::loadEventHostModule(S32 listen_port)
+{
+ std::string dso_name =
+#if LL_WINDOWS
+ "lleventhost.dll";
+#elif LL_DARWIN
+ "liblleventhost.dylib";
+#else
+ "liblleventhost.so";
+#endif
+
+ std::string dso_path = gDirUtilp->findFile(dso_name,
+ gDirUtilp->getAppRODataDir(),
+ gDirUtilp->getExecutableDir());
+
+ if(dso_path == "")
+ {
+ llerrs << "QAModeEventHost requested but module \"" << dso_name << "\" not found!" << llendl;
+ return;
+ }
+
+ apr_dso_handle_t * eventhost_dso_handle = NULL;
+ apr_pool_t * eventhost_dso_memory_pool = NULL;
+
+ //attempt to load the shared library
+ apr_pool_create(&eventhost_dso_memory_pool, NULL);
+ apr_status_t rv = apr_dso_load(&eventhost_dso_handle,
+ dso_path.c_str(),
+ eventhost_dso_memory_pool);
+ ll_apr_assert_status(rv);
+ llassert_always(eventhost_dso_handle != NULL);
+
+ int (*ll_plugin_start_func)(LLSD const &) = NULL;
+ rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_start_func, eventhost_dso_handle, "ll_plugin_start");
+
+ ll_apr_assert_status(rv);
+ llassert_always(ll_plugin_start_func != NULL);
+
+ LLSD args;
+ args["listen_port"] = listen_port;
+
+ int status = ll_plugin_start_func(args);
+
+ if(status != 0)
+ {
+ llerrs << "problem loading eventhost plugin, status: " << status << llendl;
+ }
+
+ mPlugins.insert(eventhost_dso_handle);
+}
+
+void LLAppViewer::launchUpdater()
+{
+ LLSD query_map = LLSD::emptyMap();
+ // *TODO place os string in a global constant
+#if LL_WINDOWS
+ query_map["os"] = "win";
+#elif LL_DARWIN
+ query_map["os"] = "mac";
+#elif LL_LINUX
+ query_map["os"] = "lnx";
+#elif LL_SOLARIS
+ query_map["os"] = "sol";
+#endif
+ // *TODO change userserver to be grid on both viewer and sim, since
+ // userserver no longer exists.
+ query_map["userserver"] = LLViewerLogin::getInstance()->getGridLabel();
+ query_map["channel"] = gSavedSettings.getString("VersionChannelName");
+ // *TODO constantize this guy
+ // *NOTE: This URL is also used in win_setup/lldownloader.cpp
+ LLURI update_url = LLURI::buildHTTP("secondlife.com", 80, "update.php", query_map);
+
+ if(LLAppViewer::sUpdaterInfo)
+ {
+ delete LLAppViewer::sUpdaterInfo;
+ }
+ LLAppViewer::sUpdaterInfo = new LLAppViewer::LLUpdaterInfo() ;
+
+ // if a sim name was passed in via command line parameter (typically through a SLURL)
+ if ( LLURLSimString::sInstance.mSimString.length() )
+ {
+ // record the location to start at next time
+ gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString );
+ };
+
+#if LL_WINDOWS
+ LLAppViewer::sUpdaterInfo->mUpdateExePath = gDirUtilp->getTempFilename();
+ if (LLAppViewer::sUpdaterInfo->mUpdateExePath.empty())
+ {
+ delete LLAppViewer::sUpdaterInfo ;
+ LLAppViewer::sUpdaterInfo = NULL ;
+
+ // We're hosed, bail
+ LL_WARNS("AppInit") << "LLDir::getTempFilename() failed" << LL_ENDL;
+ return;
+ }
+
+ LLAppViewer::sUpdaterInfo->mUpdateExePath += ".exe";
+
+ std::string updater_source = gDirUtilp->getAppRODataDir();
+ updater_source += gDirUtilp->getDirDelimiter();
+ updater_source += "updater.exe";
+
+ LL_DEBUGS("AppInit") << "Calling CopyFile source: " << updater_source
+ << " dest: " << LLAppViewer::sUpdaterInfo->mUpdateExePath
+ << LL_ENDL;
+
+
+ if (!CopyFileA(updater_source.c_str(), LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), FALSE))
+ {
+ delete LLAppViewer::sUpdaterInfo ;
+ LLAppViewer::sUpdaterInfo = NULL ;
+
+ LL_WARNS("AppInit") << "Unable to copy the updater!" << LL_ENDL;
+
+ return;
+ }
+
+ LLAppViewer::sUpdaterInfo->mParams << "-url \"" << update_url.asString() << "\"";
+
+ LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << " " << LLAppViewer::sUpdaterInfo->mParams.str() << LL_ENDL;
+
+ //Explicitly remove the marker file, otherwise we pass the lock onto the child process and things get weird.
+ LLAppViewer::instance()->removeMarkerFile(); // In case updater fails
+
+ // *NOTE:Mani The updater is spawned as the last thing before the WinMain exit.
+ // see LLAppViewerWin32.cpp
+
+#elif LL_DARWIN
+ LLAppViewer::sUpdaterInfo->mUpdateExePath = "'";
+ LLAppViewer::sUpdaterInfo->mUpdateExePath += gDirUtilp->getAppRODataDir();
+ LLAppViewer::sUpdaterInfo->mUpdateExePath += "/mac-updater.app/Contents/MacOS/mac-updater' -url \"";
+ LLAppViewer::sUpdaterInfo->mUpdateExePath += update_url.asString();
+ LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" -name \"";
+ LLAppViewer::sUpdaterInfo->mUpdateExePath += LLAppViewer::instance()->getSecondLifeTitle();
+ LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" &";
+
+ LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL;
+
+ // Run the auto-updater.
+ system(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str()); /* Flawfinder: ignore */
+
+#elif (LL_LINUX || LL_SOLARIS) && LL_GTK
+ // we tell the updater where to find the xml containing string
+ // translations which it can use for its own UI
+ std::string xml_strings_file = "strings.xml";
+ std::vector<std::string> xui_path_vec = LLUI::getXUIPaths();
+ std::string xml_search_paths;
+ std::vector<std::string>::const_iterator iter;
+ // build comma-delimited list of xml paths to pass to updater
+ for (iter = xui_path_vec.begin(); iter != xui_path_vec.end(); )
+ {
+ std::string this_skin_dir = gDirUtilp->getDefaultSkinDir()
+ + gDirUtilp->getDirDelimiter()
+ + (*iter);
+ llinfos << "Got a XUI path: " << this_skin_dir << llendl;
+ xml_search_paths.append(this_skin_dir);
+ ++iter;
+ if (iter != xui_path_vec.end())
+ xml_search_paths.append(","); // comma-delimit
+ }
+ // build the overall command-line to run the updater correctly
+ LLAppViewer::sUpdaterInfo->mUpdateExePath =
+ gDirUtilp->getExecutableDir() + "/" + "linux-updater.bin" +
+ " --url \"" + update_url.asString() + "\"" +
+ " --name \"" + LLAppViewer::instance()->getSecondLifeTitle() + "\"" +
+ " --dest \"" + gDirUtilp->getAppRODataDir() + "\"" +
+ " --stringsdir \"" + xml_search_paths + "\"" +
+ " --stringsfile \"" + xml_strings_file + "\"";
+
+ LL_INFOS("AppInit") << "Calling updater: "
+ << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL;
+
+ // *TODO: we could use the gdk equivalent to ensure the updater
+ // gets started on the same screen.
+ GError *error = NULL;
+ if (!g_spawn_command_line_async(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), &error))
+ {
+ llerrs << "Failed to launch updater: "
+ << error->message
+ << llendl;
+ }
+ if (error) {
+ g_error_free(error);
+ }
+#else
+ OSMessageBox(LLTrans::getString("MBNoAutoUpdate"), LLStringUtil::null, OSMB_OK);
+#endif
+
+ // *REMOVE:Mani - Saving for reference...
+ // LLAppViewer::instance()->forceQuit();
+}
+
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index a3b84759f5..40e74061b5 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -33,12 +33,21 @@
#ifndef LL_LLAPPVIEWER_H
#define LL_LLAPPVIEWER_H
+#include "llallocator.h"
+#include "llcontrol.h"
+#include "llsys.h" // for LLOSInfo
+
+class LLCommandLineParser;
+class LLFrameTimer;
+class LLPumpIO;
class LLTextureCache;
-class LLWorkerThread;
+class LLImageDecodeThread;
class LLTextureFetch;
class LLWatchdogTimeout;
class LLCommandLineParser;
+struct apr_dso_handle_t;
+
class LLAppViewer : public LLApp
{
public:
@@ -89,15 +98,15 @@ public:
// Thread accessors
static LLTextureCache* getTextureCache() { return sTextureCache; }
- static LLWorkerThread* getImageDecodeThread() { return sImageDecodeThread; }
+ static LLImageDecodeThread* getImageDecodeThread() { return sImageDecodeThread; }
static LLTextureFetch* getTextureFetch() { return sTextureFetch; }
const std::string& getSerialNumber() { return mSerialNumber; }
bool getPurgeCache() const { return mPurgeCache; }
- const std::string& getSecondLifeTitle() const; // The Second Life title.
- const std::string& getWindowTitle() const; // The window display name.
+ std::string getSecondLifeTitle() const; // The Second Life title.
+ std::string getWindowTitle() const; // The window display name.
void forceDisconnect(const std::string& msg); // Force disconnection, with a message to the user.
void badNetworkHandler(); // Cause a crash state due to bad network packet.
@@ -115,18 +124,17 @@ public:
virtual void forceErrorLLError();
virtual void forceErrorBreakpoint();
virtual void forceErrorBadMemoryAccess();
- virtual void forceErrorInifiniteLoop();
+ virtual void forceErrorInfiniteLoop();
virtual void forceErrorSoftwareException();
virtual void forceErrorDriverCrash();
- // *NOTE: There are currently 3 settings files:
- // "Global", "PerAccount" and "CrashSettings"
// The list is found in app_settings/settings_files.xml
// but since they are used explicitly in code,
// the follow consts should also do the trick.
static const std::string sGlobalSettingsName;
- static const std::string sPerAccountSettingsName;
- static const std::string sCrashSettingsName;
+
+ LLCachedControl<bool> mRandomizeFramerate;
+ LLCachedControl<bool> mPeriodicSlowFrame;
// Load settings from the location specified by loction_key.
// Key availale and rules for loading, are specified in
@@ -136,6 +144,7 @@ public:
std::string getSettingsFilename(const std::string& location_key,
const std::string& file);
+ void loadColorSettings();
// For thread debugging.
// llstartup needs to control init.
@@ -150,6 +159,15 @@ public:
// *NOTE:Mani Fix this for login abstraction!!
void handleLoginComplete();
+ LLAllocator & getAllocator() { return mAlloc; }
+
+ // On LoginCompleted callback
+ typedef boost::signals2::signal<void (void)> login_completed_signal_t;
+ login_completed_signal_t mOnLoginCompleted;
+ boost::signals2::connection setOnLoginCompletedCallback( const login_completed_signal_t::slot_type& cb ) { return mOnLoginCompleted.connect(cb); }
+
+ void purgeCache(); // Clear the local cache.
+
protected:
virtual bool initWindow(); // Initialize the viewer's window.
virtual bool initLogging(); // Initialize log files, logging system, return false on failure.
@@ -171,7 +189,7 @@ private:
void initGridChoice();
bool initCache(); // Initialize local client cache.
- void purgeCache(); // Clear the local cache.
+
// We have switched locations of both Mac and Windows cache, make sure
// files migrate and old cache is cleared out.
@@ -192,6 +210,8 @@ private:
void sendLogoutRequest();
void disconnectViewer();
+ void loadEventHostModule(S32 listen_port);
+
// *FIX: the app viewer class should be some sort of singleton, no?
// Perhaps its child class is the singleton and this should be an abstract base.
static LLAppViewer* sInstance;
@@ -210,7 +230,7 @@ private:
// Thread objects.
static LLTextureCache* sTextureCache;
- static LLWorkerThread* sImageDecodeThread;
+ static LLImageDecodeThread* sImageDecodeThread;
static LLTextureFetch* sTextureFetch;
S32 mNumSessions;
@@ -221,6 +241,8 @@ private:
bool mSavedFinalSnapshot;
+ bool mForceGraphicsDetail;
+
bool mQuitRequested; // User wants to quit, may have modified documents open.
bool mLogoutRequestSent; // Disconnect message sent to simulator, no longer safe to send messages to the sim.
S32 mYieldTime;
@@ -228,10 +250,15 @@ private:
LLWatchdogTimeout* mMainloopTimeout;
+ LLThread* mFastTimerLogThread;
// for tracking viewer<->region circuit death
bool mAgentRegionLastAlive;
LLUUID mAgentRegionLastID;
+ LLAllocator mAlloc;
+
+ std::set<struct apr_dso_handle_t*> mPlugins;
+
public:
//some information for updater
typedef struct
@@ -240,6 +267,8 @@ public:
std::ostringstream mParams;
}LLUpdaterInfo ;
static LLUpdaterInfo *sUpdaterInfo ;
+
+ void launchUpdater();
};
// consts from viewer.h
@@ -251,14 +280,8 @@ const S32 AGENT_UPDATES_PER_SECOND = 10;
// "// llstartup" indicates that llstartup is the only client for this global.
extern LLSD gDebugInfo;
-
-extern BOOL gAllowTapTapHoldRun;
extern BOOL gShowObjectUpdates;
-extern BOOL gAcceptTOS;
-extern BOOL gAcceptCriticalMessage;
-
-
typedef enum
{
LAST_EXEC_NORMAL = 0,
@@ -276,10 +299,6 @@ extern U32 gForegroundFrameCount;
extern LLPumpIO* gServicePump;
-// Is the Pacific time zone (aka server time zone)
-// currently in daylight savings time?
-extern BOOL gPacificDaylightTime;
-
extern U64 gFrameTime; // The timestamp of the most-recently-processed frame
extern F32 gFrameTimeSeconds; // Loses msec precision after ~4.5 hours...
extern F32 gFrameIntervalSeconds; // Elapsed time between current and previous gFrameTimeSeconds
@@ -297,14 +316,8 @@ extern LLTimer gLogoutTimer;
extern F32 gSimLastTime;
extern F32 gSimFrames;
-extern LLUUID gInventoryLibraryOwner;
-extern LLUUID gInventoryLibraryRoot;
-
extern BOOL gDisconnected;
-// Map scale in pixels per region
-extern F32 gMapScale;
-
extern LLFrameTimer gRestoreGLTimer;
extern BOOL gRestoreGL;
extern BOOL gUseWireframe;
@@ -312,6 +325,7 @@ extern BOOL gUseWireframe;
// VFS globals - gVFS is for general use
// gStaticVFS is read-only and is shipped w/ the viewer
// it has pre-cache data like the UI .TGAs
+class LLVFS;
extern LLVFS *gStaticVFS;
extern LLMemoryInfo gSysMemory;
diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp
index d02e86a557..d34bcb4a68 100644
--- a/indra/newview/llappviewerlinux.cpp
+++ b/indra/newview/llappviewerlinux.cpp
@@ -188,7 +188,7 @@ static inline BOOL do_basic_glibc_backtrace()
for (i = 0; i < size; i++)
{
// the format of the StraceFile is very specific, to allow (kludgy) machine-parsing
- fprintf(StraceFile, "%-3d ", i);
+ fprintf(StraceFile, "%-3lu ", (unsigned long)i);
fprintf(StraceFile, "%-32s\t", "unknown");
fprintf(StraceFile, "%p ", stackarray[i]);
fprintf(StraceFile, "%s\n", strings[i]);
@@ -263,7 +263,7 @@ static inline BOOL do_elfio_glibc_backtrace()
for (btpos = 0; btpos < btsize; ++btpos)
{
// the format of the StraceFile is very specific, to allow (kludgy) machine-parsing
- fprintf(StraceFile, "%-3d ", btpos);
+ fprintf(StraceFile, "%-3ld ", (long)btpos);
int symidx;
for (symidx = 0; symidx < nSymNo; ++symidx)
{
@@ -354,7 +354,7 @@ bool LLAppViewerLinux::init()
bool LLAppViewerLinux::restoreErrorTrap()
{
- // *NOTE:Mani there is a case for implementing this or the mac.
+ // *NOTE:Mani there is a case for implementing this on the mac.
// Linux doesn't need it to my knowledge.
return true;
}
@@ -451,7 +451,7 @@ gboolean viewer_app_api_GoSLURL(ViewerAppAPI *obj, gchar *slurl, gboolean **succ
llinfos << "Was asked to go to slurl: " << slurl << llendl;
std::string url = slurl;
- LLWebBrowserCtrl* web = NULL;
+ LLMediaCtrl* web = NULL;
const bool trusted_browser = false;
if (LLURLDispatcher::dispatch(url, web, trusted_browser))
{
@@ -553,7 +553,7 @@ void LLAppViewerLinux::handleSyncCrashTrace()
void LLAppViewerLinux::handleCrashReporting(bool reportFreeze)
{
- std::string cmd =gDirUtilp->getAppRODataDir();
+ std::string cmd =gDirUtilp->getExecutableDir();
cmd += gDirUtilp->getDirDelimiter();
#if LL_LINUX
cmd += "linux-crash-logger.bin";
@@ -727,8 +727,26 @@ std::string LLAppViewerLinux::generateSerialNumber()
{
char serial_md5[MD5HEX_STR_SIZE];
serial_md5[0] = 0;
+ std::string best;
+ std::string uuiddir("/dev/disk/by-uuid/");
- // TODO
+ // trawl /dev/disk/by-uuid looking for a good-looking UUID to grab
+ std::string this_name;
+ BOOL wrap = FALSE;
+ while (gDirUtilp->getNextFileInDir(uuiddir, "*", this_name, wrap))
+ {
+ if (this_name.length() > best.length() ||
+ (this_name.length() == best.length() &&
+ this_name > best))
+ {
+ // longest (and secondarily alphabetically last) so far
+ best = this_name;
+ }
+ }
+
+ // we don't return the actual serial number, just a hash of it.
+ LLMD5 md5( reinterpret_cast<const unsigned char*>(best.c_str()) );
+ md5.hex_digest(serial_md5);
return serial_md5;
}
diff --git a/indra/newview/llappviewerlinux.h b/indra/newview/llappviewerlinux.h
index 365fcfeb6b..230c0dc24b 100644
--- a/indra/newview/llappviewerlinux.h
+++ b/indra/newview/llappviewerlinux.h
@@ -33,9 +33,12 @@
#ifndef LL_LLAPPVIEWERLINUX_H
#define LL_LLAPPVIEWERLINUX_H
-#if LL_DBUS_ENABLED
extern "C" {
# include <glib.h>
+}
+
+#if LL_DBUS_ENABLED
+extern "C" {
# include <glib-object.h>
# include <dbus/dbus-glib.h>
}
diff --git a/indra/newview/llappviewerlinux_api_dbus.cpp b/indra/newview/llappviewerlinux_api_dbus.cpp
index ee160d0151..da67493e67 100644
--- a/indra/newview/llappviewerlinux_api_dbus.cpp
+++ b/indra/newview/llappviewerlinux_api_dbus.cpp
@@ -41,9 +41,9 @@ extern "C" {
#include "apr_dso.h"
}
-#define DEBUGMSG(...) lldebugs << llformat(__VA_ARGS__) << llendl
-#define INFOMSG(...) llinfos << llformat(__VA_ARGS__) << llendl
-#define WARNMSG(...) llwarns << llformat(__VA_ARGS__) << llendl
+#define DEBUGMSG(...) do { lldebugs << llformat(__VA_ARGS__) << llendl; } while(0)
+#define INFOMSG(...) do { llinfos << llformat(__VA_ARGS__) << llendl; } while(0)
+#define WARNMSG(...) do { llwarns << llformat(__VA_ARGS__) << llendl; } while(0)
#define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) RTN (*ll##DBUSSYM)(__VA_ARGS__) = NULL
#include "llappviewerlinux_api_dbus_syms_raw.inc"
diff --git a/indra/newview/llappviewerlistener.cpp b/indra/newview/llappviewerlistener.cpp
new file mode 100644
index 0000000000..adb5f43c1a
--- /dev/null
+++ b/indra/newview/llappviewerlistener.cpp
@@ -0,0 +1,44 @@
+/**
+ * @file llappviewerlistener.cpp
+ * @author Nat Goodspeed
+ * @date 2009-06-23
+ * @brief Implementation for llappviewerlistener.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "llviewerprecompiledheaders.h"
+// associated header
+#include "llappviewerlistener.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llappviewer.h"
+
+LLAppViewerListener::LLAppViewerListener(const LLAppViewerGetter& getter):
+ LLEventAPI("LLAppViewer",
+ "LLAppViewer listener to (e.g.) request shutdown"),
+ mAppViewerGetter(getter)
+{
+ // add() every method we want to be able to invoke via this event API.
+ add("requestQuit",
+ "Ask to quit nicely",
+ &LLAppViewerListener::requestQuit);
+ add("forceQuit",
+ "Quit abruptly",
+ &LLAppViewerListener::forceQuit);
+}
+
+void LLAppViewerListener::requestQuit(const LLSD& event)
+{
+ mAppViewerGetter()->requestQuit();
+}
+
+void LLAppViewerListener::forceQuit(const LLSD& event)
+{
+ mAppViewerGetter()->forceQuit();
+}
diff --git a/indra/newview/llappviewerlistener.h b/indra/newview/llappviewerlistener.h
new file mode 100644
index 0000000000..deedcbc179
--- /dev/null
+++ b/indra/newview/llappviewerlistener.h
@@ -0,0 +1,36 @@
+/**
+ * @file llappviewerlistener.h
+ * @author Nat Goodspeed
+ * @date 2009-06-18
+ * @brief Wrap subset of LLAppViewer API in event API
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLAPPVIEWERLISTENER_H)
+#define LL_LLAPPVIEWERLISTENER_H
+
+#include "lleventapi.h"
+#include <boost/function.hpp>
+
+class LLAppViewer;
+class LLSD;
+
+/// Listen on an LLEventPump with specified name for LLAppViewer request events.
+class LLAppViewerListener: public LLEventAPI
+{
+public:
+ typedef boost::function<LLAppViewer*(void)> LLAppViewerGetter;
+ /// Bind the LLAppViewer instance to use (e.g. LLAppViewer::instance()).
+ LLAppViewerListener(const LLAppViewerGetter& getter);
+
+private:
+ void requestQuit(const LLSD& event);
+ void forceQuit(const LLSD& event);
+
+ LLAppViewerGetter mAppViewerGetter;
+};
+
+#endif /* ! defined(LL_LLAPPVIEWERLISTENER_H) */
diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp
index 7c2e341bed..1282e437f2 100644
--- a/indra/newview/llappviewermacosx.cpp
+++ b/indra/newview/llappviewermacosx.cpp
@@ -50,7 +50,7 @@
#include <Carbon/Carbon.h>
#include "lldir.h"
#include <signal.h>
-class LLWebBrowserCtrl; // for LLURLDispatcher
+class LLMediaCtrl; // for LLURLDispatcher
namespace
{
@@ -135,31 +135,6 @@ bool LLAppViewerMacOSX::init()
return LLAppViewer::init();
}
-bool LLAppViewerMacOSX::initLogging()
-{
- // Remove the crash stack log from previous executions.
- // Since we've started logging a new instance of the app, we can assume
- // The old crash stack is invalid for the next crash report.
- char path[MAX_PATH];
- FSRef folder;
- if(FSFindFolder(kUserDomain, kLogsFolderType, false, &folder) == noErr)
- {
- // folder is an FSRef to ~/Library/Logs/
- if(FSRefMakePath(&folder, (UInt8*)&path, sizeof(path)) == noErr)
- {
- std::string pathname = std::string(path) + std::string("/CrashReporter/");
- std::string mask = "Second Life*";
- std::string file_name;
- while(gDirUtilp->getNextFileInDir(pathname, mask, file_name, false))
- {
- LLFile::remove(pathname + file_name);
- }
- }
- }
-
- return LLAppViewer::initLogging();
-}
-
// MacOSX may add and addition command line arguement for the process serial number.
// The option takes a form like '-psn_0_12345'. The following method should be able to recognize
// and either ignore or return a pair of values for the option.
@@ -184,15 +159,7 @@ bool LLAppViewerMacOSX::initParseCommandLine(LLCommandLineParser& clp)
clp.addOptionDesc("psn", NULL, 1, "MacOSX process serial number");
clp.setCustomParser(parse_psn);
- // First parse the command line, not often used on the mac.
- if(clp.parseCommandLine(gArgC, gArgV) == false)
- {
- return false;
- }
-
- // Now read in the args from arguments txt.
- // Succesive calls to clp.parse... will NOT override earlier
- // options.
+ // First read in the args from arguments txt.
const char* filename = "arguments.txt";
llifstream ifs(filename, llifstream::binary);
if (!ifs.is_open())
@@ -205,7 +172,14 @@ bool LLAppViewerMacOSX::initParseCommandLine(LLCommandLineParser& clp)
{
return false;
}
-
+
+ // Then parse the user's command line, so that any --url arg can appear last
+ // Succesive calls to clp.parse... will NOT override earlier options.
+ if(clp.parseCommandLine(gArgC, gArgV) == false)
+ {
+ return false;
+ }
+
// Get the user's preferred language string based on the Mac OS localization mechanism.
// To add a new localization:
// go to the "Resources" section of the project
@@ -213,7 +187,7 @@ bool LLAppViewerMacOSX::initParseCommandLine(LLCommandLineParser& clp)
// in the "General" tab, click the "Add Localization" button
// create a new localization for the language you're adding
// set the contents of the new localization of the file to the string corresponding to our localization
- // (i.e. "en-us", "ja", etc. Use the existing ones as a guide.)
+ // (i.e. "en", "ja", etc. Use the existing ones as a guide.)
CFURLRef url = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("language"), CFSTR("txt"), NULL);
char path[MAX_PATH];
if(CFURLGetFileSystemRepresentation(url, false, (UInt8 *)path, sizeof(path)))
@@ -416,6 +390,28 @@ void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze)
{
_exit(1);
}
+
+ // TODO:palmer REMOVE THIS VERY SOON. THIS WILL NOT BE IN VIEWER 2.0
+ // Remove the crash stack log from previous executions.
+ // Since we've started logging a new instance of the app, we can assume
+ // The old crash stack is invalid for the next crash report.
+ char path[MAX_PATH];
+ FSRef folder;
+ if(FSFindFolder(kUserDomain, kLogsFolderType, false, &folder) == noErr)
+ {
+ // folder is an FSRef to ~/Library/Logs/
+ if(FSRefMakePath(&folder, (UInt8*)&path, sizeof(path)) == noErr)
+ {
+ std::string pathname = std::string(path) + std::string("/CrashReporter/");
+ std::string mask = "Second Life*";
+ std::string file_name;
+ while(gDirUtilp->getNextFileInDir(pathname, mask, file_name, false))
+ {
+ LLFile::remove(pathname + file_name);
+ }
+ }
+ }
+
}
std::string LLAppViewerMacOSX::generateSerialNumber()
@@ -479,7 +475,7 @@ OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn)
url.replace(0, prefix.length(), "secondlife:///app/");
}
- LLWebBrowserCtrl* web = NULL;
+ LLMediaCtrl* web = NULL;
const bool trusted_browser = false;
LLURLDispatcher::dispatch(url, web, trusted_browser);
}
diff --git a/indra/newview/llappviewermacosx.h b/indra/newview/llappviewermacosx.h
index 0928916a57..bc841fc3a7 100644
--- a/indra/newview/llappviewermacosx.h
+++ b/indra/newview/llappviewermacosx.h
@@ -55,7 +55,6 @@ protected:
virtual void handleSyncCrashTrace();
std::string generateSerialNumber();
- virtual bool initLogging();
virtual bool initParseCommandLine(LLCommandLineParser& clp);
};
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 16928923bf..12cff32780 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -64,6 +64,7 @@
#include "llfindlocale.h"
#include "llcommandlineparser.h"
+#include "lltrans.h"
// *FIX:Mani - This hack is to fix a linker issue with libndofdev.lib
// The lib was compiled under VS2005 - in VS2003 we need to remap assert
@@ -84,7 +85,7 @@ LONG WINAPI viewer_windows_exception_handler(struct _EXCEPTION_POINTERS *excepti
{
// *NOTE:Mani - this code is stolen from LLApp, where its never actually used.
//OSMessageBox("Attach Debugger Now", "Error", OSMB_OK);
- // Translate the signals/exceptions into cross-platform stuff
+ // *TODO: Translate the signals/exceptions into cross-platform stuff
// Windows implementation
_tprintf( _T("Entering Windows Exception Handler...\n") );
llinfos << "Entering Windows Exception Handler..." << llendl;
@@ -159,9 +160,31 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
int nCmdShow)
{
LLMemType mt1(LLMemType::MTYPE_STARTUP);
+
+ const S32 MAX_HEAPS = 255;
+ DWORD heap_enable_lfh_error[MAX_HEAPS];
+ S32 num_heaps = 0;
#if WINDOWS_CRT_MEM_CHECKS && !INCLUDE_VLD
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); // dump memory leaks on exit
+#elif 1
+ // Experimental - enable the low fragmentation heap
+ // This results in a 2-3x improvement in opening a new Inventory window (which uses a large numebr of allocations)
+ // Note: This won't work when running from the debugger unless the _NO_DEBUG_HEAP environment variable is set to 1
+
+ _CrtSetDbgFlag(0); // default, just making explicit
+
+ ULONG ulEnableLFH = 2;
+ HANDLE* hHeaps = new HANDLE[MAX_HEAPS];
+ num_heaps = GetProcessHeaps(MAX_HEAPS, hHeaps);
+ for(S32 i = 0; i < num_heaps; i++)
+ {
+ bool success = HeapSetInformation(hHeaps[i], HeapCompatibilityInformation, &ulEnableLFH, sizeof(ulEnableLFH));
+ if (success)
+ heap_enable_lfh_error[i] = 0;
+ else
+ heap_enable_lfh_error[i] = GetLastError();
+ }
#endif
// *FIX: global
@@ -183,8 +206,21 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
llwarns << "Application init failed." << llendl;
return -1;
}
-
- // Run the application main loop
+
+ // Have to wait until after logging is initialized to display LFH info
+ if (num_heaps > 0)
+ {
+ llinfos << "Attempted to enable LFH for " << num_heaps << " heaps." << llendl;
+ for(S32 i = 0; i < num_heaps; i++)
+ {
+ if (heap_enable_lfh_error[i])
+ {
+ llinfos << " Failed to enable LFH for heap: " << i << " Error: " << heap_enable_lfh_error[i] << llendl;
+ }
+ }
+ }
+
+ // Run the application main loop
if(!LLApp::isQuitting())
{
viewer_app_ptr->mainLoop();
@@ -209,6 +245,8 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
}
#endif
+ gGLActive = TRUE;
+
viewer_app_ptr->cleanup();
#if WINDOWS_CRT_MEM_CHECKS
@@ -409,33 +447,24 @@ bool LLAppViewerWin32::initHardwareTest()
// but vram.
vram_only = TRUE;
- LLSplashScreen::update("Detecting hardware...");
+ LLSplashScreen::update(LLTrans::getString("StartupDetectingHardware"));
LL_DEBUGS("AppInit") << "Attempting to poll DirectX for hardware info" << LL_ENDL;
gDXHardware.setWriteDebugFunc(write_debug_dx);
BOOL probe_ok = gDXHardware.getInfo(vram_only);
if (!probe_ok
- && gSavedSettings.getWarning("AboutDirectX9"))
+ && gWarningSettings.getBOOL("AboutDirectX9"))
{
LL_WARNS("AppInit") << "DirectX probe failed, alerting user." << LL_ENDL;
// Warn them that runnin without DirectX 9 will
// not allow us to tell them about driver issues
std::ostringstream msg;
- msg <<
- LLAppViewer::instance()->getSecondLifeTitle() << " is unable to detect DirectX 9.0b or greater.\n"
- "\n" <<
- LLAppViewer::instance()->getSecondLifeTitle() << " uses DirectX to detect hardware and/or\n"
- "outdated drivers that can cause stability problems,\n"
- "poor performance and crashes. While you can run\n" <<
- LLAppViewer::instance()->getSecondLifeTitle() << " without it, we highly recommend running\n"
- "with DirectX 9.0b\n"
- "\n"
- "Do you wish to continue?\n";
+ msg << LLTrans::getString ("MBNoDirectX");
S32 button = OSMessageBox(
msg.str(),
- "Warning",
+ LLTrans::getString("MBWarning"),
OSMB_YESNO);
if (OSBTN_NO== button)
{
@@ -443,7 +472,7 @@ bool LLAppViewerWin32::initHardwareTest()
LLWeb::loadURLExternal(DIRECTX_9_URL);
return false;
}
- gSavedSettings.setWarning("AboutDirectX9", FALSE);
+ gWarningSettings.setBOOL("AboutDirectX9", FALSE);
}
LL_DEBUGS("AppInit") << "Done polling DirectX for hardware info" << LL_ENDL;
@@ -452,7 +481,7 @@ bool LLAppViewerWin32::initHardwareTest()
// Disable so debugger can work
std::ostringstream splash_msg;
- splash_msg << "Loading " << LLAppViewer::instance()->getSecondLifeTitle() << "...";
+ splash_msg << LLTrans::getString("StartupLoading") << " " << LLAppViewer::instance()->getSecondLifeTitle() << "...";
LLSplashScreen::update(splash_msg.str());
}
diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp
index 4fca9b1f19..a2322e28b4 100644
--- a/indra/newview/llassetuploadresponders.cpp
+++ b/indra/newview/llassetuploadresponders.cpp
@@ -39,9 +39,8 @@
#include "llcompilequeue.h"
#include "llfloaterbuycurrency.h"
#include "llfilepicker.h"
-#include "llnotify.h"
-#include "llinventorymodel.h"
-#include "llinventoryview.h"
+#include "llinventoryobserver.h"
+#include "llinventorypanel.h"
#include "llpermissionsflags.h"
#include "llpreviewnotecard.h"
#include "llpreviewscript.h"
@@ -58,10 +57,14 @@
#include "lltexlayer.h"
// library includes
+#include "lldir.h"
#include "lleconomy.h"
+#include "llfloaterreg.h"
#include "llfocusmgr.h"
+#include "llnotificationsutil.h"
#include "llscrolllistctrl.h"
#include "llsdserialize.h"
+#include "llvfs.h"
// When uploading multiple files, don't display any of them when uploading more than this number.
static const S32 FILE_COUNT_DISPLAY_THRESHOLD = 5;
@@ -116,14 +119,14 @@ void LLAssetUploadResponder::error(U32 statusNum, const std::string& reason)
args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
args["REASON"] = "Error in upload request. Please visit "
"http://secondlife.com/support for help fixing this problem.";
- LLNotifications::instance().add("CannotUploadReason", args);
+ LLNotificationsUtil::add("CannotUploadReason", args);
break;
case 500:
default:
args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
args["REASON"] = "The server is experiencing unexpected "
"difficulties.";
- LLNotifications::instance().add("CannotUploadReason", args);
+ LLNotificationsUtil::add("CannotUploadReason", args);
break;
}
LLUploadDialog::modalUploadFinished();
@@ -185,7 +188,7 @@ void LLAssetUploadResponder::uploadFailure(const LLSD& content)
LLSD args;
args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
args["REASON"] = content["message"].asString();
- LLNotifications::instance().add("CannotUploadReason", args);
+ LLNotificationsUtil::add("CannotUploadReason", args);
}
}
@@ -228,7 +231,7 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content)
LLSD args;
args["AMOUNT"] = llformat("%d", expected_upload_cost);
- LLNotifications::instance().add("UploadPayment", args);
+ LLNotificationsUtil::add("UploadPayment", args);
}
// Actually add the upload to viewer inventory
@@ -282,19 +285,19 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content)
// Show the preview panel for textures and sounds to let
// user know that the image (or snapshot) arrived intact.
- LLInventoryView* view = LLInventoryView::getActiveInventory();
- if(view)
+ LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel();
+ if (active_panel)
{
- LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus();
- view->getPanel()->setSelection(content["new_inventory_item"].asUUID(), TAKE_FOCUS_NO);
+ active_panel->setSelection(content["new_inventory_item"].asUUID(), TAKE_FOCUS_NO);
if((LLAssetType::AT_TEXTURE == asset_type || LLAssetType::AT_SOUND == asset_type)
&& LLFilePicker::instance().getFileCount() <= FILE_COUNT_DISPLAY_THRESHOLD)
{
- view->getPanel()->openSelected();
+ active_panel->openSelected();
}
- //LLInventoryView::dumpSelectionInformation((void*)view);
+ //LLFloaterInventory::dumpSelectionInformation((void*)view);
// restore keyboard focus
- gFocusMgr.setKeyboardFocus(focus_ctrl);
+ LLFocusableElement* focus = gFocusMgr.getKeyboardFocus();
+ gFocusMgr.setKeyboardFocus(focus);
}
}
else
@@ -329,7 +332,7 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content)
LLAssetStorage::LLStoreAssetCallback callback = NULL;
void *userdata = NULL;
upload_new_resource(next_file, asset_name, asset_name,
- 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE,
+ 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
next_owner_perms, group_perms,
everyone_perms, display_name,
callback, expected_upload_cost, userdata);
@@ -337,11 +340,11 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content)
}
LLSendTexLayerResponder::LLSendTexLayerResponder(const LLSD& post_data,
- const LLUUID& vfile_id,
- LLAssetType::EType asset_type,
- LLBakedUploadData * baked_upload_data)
- : LLAssetUploadResponder(post_data, vfile_id, asset_type),
- mBakedUploadData(baked_upload_data)
+ const LLUUID& vfile_id,
+ LLAssetType::EType asset_type,
+ LLBakedUploadData * baked_upload_data) :
+ LLAssetUploadResponder(post_data, vfile_id, asset_type),
+ mBakedUploadData(baked_upload_data)
{
}
@@ -364,7 +367,7 @@ void LLSendTexLayerResponder::uploadComplete(const LLSD& content)
std::string result = content["state"];
LLUUID new_id = content["new_asset"];
- llinfos << "LLSendTexLayerResponder::result from capabilities: " << result << llendl;
+ llinfos << "result: " << result << "new_id:" << new_id << llendl;
if (result == "complete"
&& mBakedUploadData != NULL)
{ // Invoke
@@ -378,6 +381,14 @@ void LLSendTexLayerResponder::uploadComplete(const LLSD& content)
}
}
+void LLSendTexLayerResponder::error(U32 statusNum, const std::string& reason)
+{
+ llinfos << "status: " << statusNum << " reason: " << reason << llendl;
+
+ // Invoke the original callback with an error result
+ LLTexLayerSetBuffer::onTextureUploadComplete(LLUUID(), (void*) mBakedUploadData, -1, LL_EXSTAT_NONE);
+ mBakedUploadData = NULL; // deleted in onTextureUploadComplete()
+}
LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(const LLSD& post_data,
const LLUUID& vfile_id,
@@ -419,72 +430,68 @@ void LLUpdateAgentInventoryResponder::uploadComplete(const LLSD& content)
LLInventoryType::EType inventory_type = new_item->getInventoryType();
switch(inventory_type)
{
- case LLInventoryType::IT_NOTECARD:
- {
-
- // Update the UI with the new asset.
- LLPreviewNotecard* nc;
- nc = (LLPreviewNotecard*)LLPreview::find(new_item->getUUID());
- if(nc)
- {
- // *HACK: we have to delete the asset in the VFS so
- // that the viewer will redownload it. This is only
- // really necessary if the asset had to be modified by
- // the uploader, so this can be optimized away in some
- // cases. A better design is to have a new uuid if the
- // script actually changed the asset.
- if(nc->hasEmbeddedInventory())
- {
- gVFS->removeFile(
- content["new_asset"].asUUID(),
- LLAssetType::AT_NOTECARD);
- }
- nc->refreshFromInventory();
- }
- }
- break;
- case LLInventoryType::IT_LSL:
- {
- // Find our window and close it if requested.
- LLPreviewLSL* preview = (LLPreviewLSL*)LLPreview::find(item_id);
- if (preview)
- {
- // Bytecode save completed
- if (content["compiled"])
- {
- preview->callbackLSLCompileSucceeded();
- }
- else
- {
- preview->callbackLSLCompileFailed(content["errors"]);
- }
- }
- }
- break;
-
- case LLInventoryType::IT_GESTURE:
- {
- // If this gesture is active, then we need to update the in-memory
- // active map with the new pointer.
- if (gGestureManager.isGestureActive(item_id))
- {
- LLUUID asset_id = new_item->getAssetUUID();
- gGestureManager.replaceGesture(item_id, asset_id);
- gInventory.notifyObservers();
- }
-
- //gesture will have a new asset_id
- LLPreviewGesture* previewp = (LLPreviewGesture*)LLPreview::find(item_id);
- if(previewp)
- {
- previewp->onUpdateSucceeded();
- }
+ case LLInventoryType::IT_NOTECARD:
+ {
+ // Update the UI with the new asset.
+ LLPreviewNotecard* nc = LLFloaterReg::findTypedInstance<LLPreviewNotecard>("preview_notecard", LLSD(item_id));
+ if(nc)
+ {
+ // *HACK: we have to delete the asset in the VFS so
+ // that the viewer will redownload it. This is only
+ // really necessary if the asset had to be modified by
+ // the uploader, so this can be optimized away in some
+ // cases. A better design is to have a new uuid if the
+ // script actually changed the asset.
+ if(nc->hasEmbeddedInventory())
+ {
+ gVFS->removeFile(content["new_asset"].asUUID(), LLAssetType::AT_NOTECARD);
+ }
+ nc->refreshFromInventory(new_item->getUUID());
+ }
+ break;
+ }
+ case LLInventoryType::IT_LSL:
+ {
+ // Find our window and close it if requested.
+ LLPreviewLSL* preview = LLFloaterReg::findTypedInstance<LLPreviewLSL>("preview_script", LLSD(item_id));
+ if (preview)
+ {
+ // Bytecode save completed
+ if (content["compiled"])
+ {
+ preview->callbackLSLCompileSucceeded();
+ }
+ else
+ {
+ preview->callbackLSLCompileFailed(content["errors"]);
+ }
+ }
+ break;
+ }
+
+ case LLInventoryType::IT_GESTURE:
+ {
+ // If this gesture is active, then we need to update the in-memory
+ // active map with the new pointer.
+ if (LLGestureManager::instance().isGestureActive(item_id))
+ {
+ LLUUID asset_id = new_item->getAssetUUID();
+ LLGestureManager::instance().replaceGesture(item_id, asset_id);
+ gInventory.notifyObservers();
+ }
+
+ //gesture will have a new asset_id
+ LLPreviewGesture* previewp = LLFloaterReg::findTypedInstance<LLPreviewGesture>("preview_gesture", LLSD(item_id));
+ if(previewp)
+ {
+ previewp->onUpdateSucceeded();
+ }
- }
- break;
- case LLInventoryType::IT_WEARABLE:
- default:
- break;
+ break;
+ }
+ case LLInventoryType::IT_WEARABLE:
+ default:
+ break;
}
}
@@ -522,64 +529,57 @@ void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content)
switch(mAssetType)
{
- case LLAssetType::AT_NOTECARD:
- {
-
- // Update the UI with the new asset.
- LLPreviewNotecard* nc;
- nc = (LLPreviewNotecard*)LLPreview::find(item_id);
- if(nc)
- {
- // *HACK: we have to delete the asset in the VFS so
- // that the viewer will redownload it. This is only
- // really necessary if the asset had to be modified by
- // the uploader, so this can be optimized away in some
- // cases. A better design is to have a new uuid if the
- // script actually changed the asset.
- if(nc->hasEmbeddedInventory())
- {
- gVFS->removeFile(
- content["new_asset"].asUUID(),
- LLAssetType::AT_NOTECARD);
- }
-
- nc->refreshFromInventory();
- }
- }
- break;
- case LLAssetType::AT_LSL_TEXT:
- {
- if(mQueueId.notNull())
- {
- LLFloaterCompileQueue* queue =
- (LLFloaterCompileQueue*) LLFloaterScriptQueue::findInstance(mQueueId);
- if(NULL != queue)
- {
- queue->removeItemByItemID(item_id);
- }
- }
- else
- {
- LLLiveLSLEditor* preview = LLLiveLSLEditor::find(item_id, task_id);
- if (preview)
- {
- // Bytecode save completed
- if (content["compiled"])
- {
- preview->callbackLSLCompileSucceeded(
- task_id,
- item_id,
- mPostData["is_script_running"]);
- }
- else
- {
- preview->callbackLSLCompileFailed(content["errors"]);
- }
- }
- }
- }
- break;
- default:
+ case LLAssetType::AT_NOTECARD:
+ {
+ // Update the UI with the new asset.
+ LLPreviewNotecard* nc = LLFloaterReg::findTypedInstance<LLPreviewNotecard>("preview_notecard", LLSD(item_id));
+ if(nc)
+ {
+ // *HACK: we have to delete the asset in the VFS so
+ // that the viewer will redownload it. This is only
+ // really necessary if the asset had to be modified by
+ // the uploader, so this can be optimized away in some
+ // cases. A better design is to have a new uuid if the
+ // script actually changed the asset.
+ if(nc->hasEmbeddedInventory())
+ {
+ gVFS->removeFile(content["new_asset"].asUUID(),
+ LLAssetType::AT_NOTECARD);
+ }
+ nc->setAssetId(content["new_asset"].asUUID());
+ nc->refreshFromInventory();
+ }
+ break;
+ }
+ case LLAssetType::AT_LSL_TEXT:
+ {
+ if(mQueueId.notNull())
+ {
+ LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", mQueueId);
+ if(NULL != queue)
+ {
+ queue->removeItemByItemID(item_id);
+ }
+ }
+ else
+ {
+ LLLiveLSLEditor* preview = LLFloaterReg::findTypedInstance<LLLiveLSLEditor>("preview_scriptedit", LLSD(item_id));
+ if (preview)
+ {
+ // Bytecode save completed
+ if (content["compiled"])
+ {
+ preview->callbackLSLCompileSucceeded(task_id, item_id, mPostData["is_script_running"]);
+ }
+ else
+ {
+ preview->callbackLSLCompileFailed(content["errors"]);
+ }
+ }
+ }
+ break;
+ }
+ default:
break;
}
}
diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h
index 9ab571ae99..e656351305 100644
--- a/indra/newview/llassetuploadresponders.h
+++ b/indra/newview/llassetuploadresponders.h
@@ -47,6 +47,7 @@ public:
const std::string& file_name,
LLAssetType::EType asset_type);
~LLAssetUploadResponder();
+
virtual void error(U32 statusNum, const std::string& reason);
virtual void result(const LLSD& content);
virtual void uploadUpload(const LLSD& content);
@@ -83,6 +84,7 @@ public:
~LLSendTexLayerResponder();
virtual void uploadComplete(const LLSD& content);
+ virtual void error(U32 statusNum, const std::string& reason);
LLBakedUploadData * mBakedUploadData;
};
diff --git a/indra/newview/llaudiosourcevo.h b/indra/newview/llaudiosourcevo.h
index e7bb2837a4..4b70f8bc20 100644
--- a/indra/newview/llaudiosourcevo.h
+++ b/indra/newview/llaudiosourcevo.h
@@ -34,7 +34,7 @@
#ifndef LL_LLAUDIOSOURCEVO_H
#define LL_LLAUDIOSOURCEVO_H
-#include "audioengine.h"
+#include "llaudioengine.h"
#include "llviewerobject.h"
class LLViewerObject;
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
new file mode 100644
index 0000000000..bb14c41cec
--- /dev/null
+++ b/indra/newview/llavataractions.cpp
@@ -0,0 +1,611 @@
+/**
+ * @file llavataractions.cpp
+ * @brief Friend-related actions (add, remove, offer teleport, etc)
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llavataractions.h"
+
+#include "llsd.h"
+#include "lldarray.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+
+#include "roles_constants.h" // for GP_MEMBER_INVITE
+
+#include "llagent.h"
+#include "llappviewer.h" // for gLastVersionChannel
+#include "llcachename.h"
+#include "llcallingcard.h" // for LLAvatarTracker
+#include "llfloatergroupinvite.h"
+#include "llfloatergroups.h"
+#include "llfloaterreg.h"
+#include "llfloaterpay.h"
+#include "llinventorymodel.h" // for gInventory.findCategoryUUIDForType
+#include "llimview.h" // for gIMMgr
+#include "llmutelist.h"
+#include "llrecentpeople.h"
+#include "llsidetray.h"
+#include "lltrans.h"
+#include "llviewerobjectlist.h"
+#include "llviewermessage.h" // for handle_lure
+#include "llviewerregion.h"
+#include "llimfloater.h"
+#include "lltrans.h"
+#include "llcallingcard.h"
+
+// static
+void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::string& name)
+{
+ if(id == gAgentID)
+ {
+ LLNotificationsUtil::add("AddSelfFriend");
+ return;
+ }
+
+ LLSD args;
+ args["NAME"] = name;
+ LLSD payload;
+ payload["id"] = id;
+ payload["name"] = name;
+ // Look for server versions like: Second Life Server 1.24.4.95600
+ if (gLastVersionChannel.find(" 1.24.") != std::string::npos)
+ {
+ // Old and busted server version, doesn't support friend
+ // requests with messages.
+ LLNotificationsUtil::add("AddFriend", args, payload, &callbackAddFriend);
+ }
+ else
+ {
+ LLNotificationsUtil::add("AddFriendWithMessage", args, payload, &callbackAddFriendWithMessage);
+ }
+
+ // add friend to recent people list
+ LLRecentPeople::instance().add(id);
+}
+
+// static
+void LLAvatarActions::requestFriendshipDialog(const LLUUID& id)
+{
+ if(id.isNull())
+ {
+ return;
+ }
+
+ std::string full_name;
+ gCacheName->getFullName(id, full_name);
+ requestFriendshipDialog(id, full_name);
+}
+
+// static
+void LLAvatarActions::removeFriendDialog(const LLUUID& id)
+{
+ if (id.isNull())
+ return;
+
+ std::vector<LLUUID> ids;
+ ids.push_back(id);
+ removeFriendsDialog(ids);
+}
+
+// static
+void LLAvatarActions::removeFriendsDialog(const std::vector<LLUUID>& ids)
+{
+ if(ids.size() == 0)
+ return;
+
+ LLSD args;
+ std::string msgType;
+ if(ids.size() == 1)
+ {
+ LLUUID agent_id = ids[0];
+ std::string first, last;
+ if(gCacheName->getName(agent_id, first, last))
+ {
+ args["FIRST_NAME"] = first;
+ args["LAST_NAME"] = last;
+ }
+
+ msgType = "RemoveFromFriends";
+ }
+ else
+ {
+ msgType = "RemoveMultipleFromFriends";
+ }
+
+ LLSD payload;
+ for (std::vector<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); ++it)
+ {
+ payload["ids"].append(*it);
+ }
+
+ LLNotificationsUtil::add(msgType,
+ args,
+ payload,
+ &handleRemove);
+}
+
+// static
+void LLAvatarActions::offerTeleport(const LLUUID& invitee)
+{
+ if (invitee.isNull())
+ return;
+
+ LLDynamicArray<LLUUID> ids;
+ ids.push_back(invitee);
+ offerTeleport(ids);
+}
+
+// static
+void LLAvatarActions::offerTeleport(const std::vector<LLUUID>& ids)
+{
+ if (ids.size() == 0)
+ return;
+
+ handle_lure(ids);
+}
+
+// static
+void LLAvatarActions::startIM(const LLUUID& id)
+{
+ if (id.isNull())
+ return;
+
+ std::string name;
+ gCacheName->getFullName(id, name);
+ LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id);
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
+ make_ui_sound("UISndStartIM");
+}
+
+// static
+void LLAvatarActions::endIM(const LLUUID& id)
+{
+ if (id.isNull())
+ return;
+
+ LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL, id);
+ if (session_id != LLUUID::null)
+ {
+ gIMMgr->leaveSession(session_id);
+ }
+}
+
+// static
+void LLAvatarActions::startCall(const LLUUID& id)
+{
+ if (id.isNull())
+ {
+ return;
+ }
+
+ std::string name;
+ gCacheName->getFullName(id, name);
+ LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id, true);
+ if (session_id != LLUUID::null)
+ {
+ gIMMgr->startCall(session_id);
+ }
+ make_ui_sound("UISndStartIM");
+}
+
+// static
+void LLAvatarActions::startAdhocCall(const std::vector<LLUUID>& ids)
+{
+ if (ids.size() == 0)
+ {
+ return;
+ }
+
+ // convert vector into LLDynamicArray for addSession
+ LLDynamicArray<LLUUID> id_array;
+ for (std::vector<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); ++it)
+ {
+ id_array.push_back(*it);
+ }
+
+ // create the new ad hoc voice session
+ const std::string title = LLTrans::getString("conference-title");
+ LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START,
+ ids[0], id_array, true);
+ if (session_id == LLUUID::null)
+ {
+ return;
+ }
+
+ gIMMgr->autoStartCallOnStartup(session_id);
+
+ make_ui_sound("UISndStartIM");
+}
+
+// static
+bool LLAvatarActions::isCalling(const LLUUID &id)
+{
+ if (id.isNull())
+ {
+ return false;
+ }
+
+ LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL, id);
+ return (LLIMModel::getInstance()->findIMSession(session_id) != NULL);
+}
+
+//static
+bool LLAvatarActions::canCall()
+{
+ return LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking();
+}
+
+// static
+void LLAvatarActions::startConference(const std::vector<LLUUID>& ids)
+{
+ // *HACK: Copy into dynamic array
+ LLDynamicArray<LLUUID> id_array;
+ for (std::vector<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); ++it)
+ {
+ id_array.push_back(*it);
+ }
+ const std::string title = LLTrans::getString("conference-title");
+ LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, ids[0], id_array);
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
+ make_ui_sound("UISndStartIM");
+}
+
+// static
+void LLAvatarActions::showProfile(const LLUUID& id)
+{
+ if (id.notNull())
+ {
+ LLSD params;
+ params["id"] = id;
+ params["open_tab_name"] = "panel_profile";
+
+ //Show own profile
+ if(gAgent.getID() == id)
+ {
+ LLSideTray::getInstance()->showPanel("panel_me", params);
+ }
+ //Show other user profile
+ else
+ {
+ LLSideTray::getInstance()->showPanel("panel_profile_view", params);
+ }
+ }
+}
+
+// static
+void LLAvatarActions::pay(const LLUUID& id)
+{
+ LLNotification::Params params("BusyModePay");
+ params.functor.function(boost::bind(&LLAvatarActions::handlePay, _1, _2, id));
+
+ if (gAgent.getBusy())
+ {
+ // warn users of being in busy mode during a transaction
+ LLNotifications::instance().add(params);
+ }
+ else
+ {
+ LLNotifications::instance().forceResponse(params, 1);
+ }
+}
+
+// static
+void LLAvatarActions::kick(const LLUUID& id)
+{
+ LLSD payload;
+ payload["avatar_id"] = id;
+ LLNotifications::instance().add("KickUser", LLSD(), payload, handleKick);
+}
+
+// static
+void LLAvatarActions::freeze(const LLUUID& id)
+{
+ LLSD payload;
+ payload["avatar_id"] = id;
+ LLNotifications::instance().add("FreezeUser", LLSD(), payload, handleFreeze);
+}
+
+// static
+void LLAvatarActions::unfreeze(const LLUUID& id)
+{
+ LLSD payload;
+ payload["avatar_id"] = id;
+ LLNotifications::instance().add("UnFreezeUser", LLSD(), payload, handleUnfreeze);
+}
+
+//static
+void LLAvatarActions::csr(const LLUUID& id, std::string name)
+{
+ if (name.empty()) return;
+
+ std::string url = "http://csr.lindenlab.com/agent/";
+
+ // slow and stupid, but it's late
+ S32 len = name.length();
+ for (S32 i = 0; i < len; i++)
+ {
+ if (name[i] == ' ')
+ {
+ url += "%20";
+ }
+ else
+ {
+ url += name[i];
+ }
+ }
+
+ LLWeb::loadURL(url);
+}
+
+//static
+void LLAvatarActions::share(const LLUUID& id)
+{
+ LLSD key;
+ LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
+
+
+ LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL,id);
+
+ if (!gIMMgr->hasSession(session_id))
+ {
+ startIM(id);
+ }
+
+ if (gIMMgr->hasSession(session_id))
+ {
+ // we should always get here, but check to verify anyways
+ LLIMModel::getInstance()->addMessage(session_id, SYSTEM_FROM, LLUUID::null, LLTrans::getString("share_alert"), false);
+ }
+}
+
+// static
+void LLAvatarActions::toggleBlock(const LLUUID& id)
+{
+ std::string name;
+
+ gCacheName->getFullName(id, name);
+ LLMute mute(id, name, LLMute::AGENT);
+
+ if (LLMuteList::getInstance()->isMuted(mute.mID, mute.mName))
+ {
+ LLMuteList::getInstance()->remove(mute);
+ }
+ else
+ {
+ LLMuteList::getInstance()->add(mute);
+ }
+}
+
+void LLAvatarActions::inviteToGroup(const LLUUID& id)
+{
+ LLFloaterGroupPicker* widget = LLFloaterReg::showTypedInstance<LLFloaterGroupPicker>("group_picker", LLSD(id));
+ if (widget)
+ {
+ widget->center();
+ widget->setPowersMask(GP_MEMBER_INVITE);
+ widget->removeNoneOption();
+ widget->setSelectGroupCallback(boost::bind(callback_invite_to_group, _1, id));
+ }
+}
+
+//== private methods ========================================================================================
+
+// static
+bool LLAvatarActions::handleRemove(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+ const LLSD& ids = notification["payload"]["ids"];
+ for (LLSD::array_const_iterator itr = ids.beginArray(); itr != ids.endArray(); ++itr)
+ {
+ LLUUID id = itr->asUUID();
+ const LLRelationship* ip = LLAvatarTracker::instance().getBuddyInfo(id);
+ if (ip)
+ {
+ switch (option)
+ {
+ case 0: // YES
+ if( ip->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS))
+ {
+ LLAvatarTracker::instance().empower(id, FALSE);
+ LLAvatarTracker::instance().notifyObservers();
+ }
+ LLAvatarTracker::instance().terminateBuddy(id);
+ LLAvatarTracker::instance().notifyObservers();
+ break;
+
+ case 1: // NO
+ default:
+ llinfos << "No removal performed." << llendl;
+ break;
+ }
+ }
+ }
+ return false;
+}
+
+// static
+bool LLAvatarActions::handlePay(const LLSD& notification, const LLSD& response, LLUUID avatar_id)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option == 0)
+ {
+ gAgent.clearBusy();
+ }
+
+ LLFloaterPayUtil::payDirectly(&give_money, avatar_id, /*is_group=*/false);
+ return false;
+}
+
+// static
+void LLAvatarActions::callback_invite_to_group(LLUUID group_id, LLUUID id)
+{
+ std::vector<LLUUID> agent_ids;
+ agent_ids.push_back(id);
+
+ LLFloaterGroupInvite::showForGroup(group_id, &agent_ids);
+}
+
+
+// static
+bool LLAvatarActions::callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option == 0)
+ {
+ requestFriendship(notification["payload"]["id"].asUUID(),
+ notification["payload"]["name"].asString(),
+ response["message"].asString());
+ }
+ return false;
+}
+
+// static
+bool LLAvatarActions::handleKick(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
+ if (option == 0)
+ {
+ LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
+ LLMessageSystem* msg = gMessageSystem;
+
+ msg->newMessageFast(_PREHASH_GodKickUser);
+ msg->nextBlockFast(_PREHASH_UserInfo);
+ msg->addUUIDFast(_PREHASH_GodID, gAgent.getID() );
+ msg->addUUIDFast(_PREHASH_GodSessionID, gAgent.getSessionID());
+ msg->addUUIDFast(_PREHASH_AgentID, avatar_id );
+ msg->addU32("KickFlags", KICK_FLAGS_DEFAULT );
+ msg->addStringFast(_PREHASH_Reason, response["message"].asString() );
+ gAgent.sendReliableMessage();
+ }
+ return false;
+}
+bool LLAvatarActions::handleFreeze(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
+ if (option == 0)
+ {
+ LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
+ LLMessageSystem* msg = gMessageSystem;
+
+ msg->newMessageFast(_PREHASH_GodKickUser);
+ msg->nextBlockFast(_PREHASH_UserInfo);
+ msg->addUUIDFast(_PREHASH_GodID, gAgent.getID() );
+ msg->addUUIDFast(_PREHASH_GodSessionID, gAgent.getSessionID());
+ msg->addUUIDFast(_PREHASH_AgentID, avatar_id );
+ msg->addU32("KickFlags", KICK_FLAGS_FREEZE );
+ msg->addStringFast(_PREHASH_Reason, response["message"].asString() );
+ gAgent.sendReliableMessage();
+ }
+ return false;
+}
+bool LLAvatarActions::handleUnfreeze(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ std::string text = response["message"].asString();
+ if (option == 0)
+ {
+ LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
+ LLMessageSystem* msg = gMessageSystem;
+
+ msg->newMessageFast(_PREHASH_GodKickUser);
+ msg->nextBlockFast(_PREHASH_UserInfo);
+ msg->addUUIDFast(_PREHASH_GodID, gAgent.getID() );
+ msg->addUUIDFast(_PREHASH_GodSessionID, gAgent.getSessionID());
+ msg->addUUIDFast(_PREHASH_AgentID, avatar_id );
+ msg->addU32("KickFlags", KICK_FLAGS_UNFREEZE );
+ msg->addStringFast(_PREHASH_Reason, text );
+ gAgent.sendReliableMessage();
+ }
+ return false;
+}
+// static
+bool LLAvatarActions::callbackAddFriend(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option == 0)
+ {
+ // Servers older than 1.25 require the text of the message to be the
+ // calling card folder ID for the offering user. JC
+ LLUUID calling_card_folder_id =
+ gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD);
+ std::string message = calling_card_folder_id.asString();
+ requestFriendship(notification["payload"]["id"].asUUID(),
+ notification["payload"]["name"].asString(),
+ message);
+ }
+ return false;
+}
+
+// static
+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);
+ send_improved_im(target_id,
+ target_name,
+ message,
+ IM_ONLINE,
+ IM_FRIENDSHIP_OFFERED,
+ calling_card_folder_id);
+
+ LLSD args;
+ args["TO_NAME"] = target_name;
+
+ LLSD payload;
+ payload["from_id"] = target_id;
+ payload["SESSION_NAME"] = target_name;
+ payload["SUPPRESS_TOAST"] = true;
+ LLNotificationsUtil::add("FriendshipOffered", args, payload);
+}
+
+//static
+bool LLAvatarActions::isFriend(const LLUUID& id)
+{
+ return ( NULL != LLAvatarTracker::instance().getBuddyInfo(id) );
+}
+
+// static
+bool LLAvatarActions::isBlocked(const LLUUID& id)
+{
+ std::string name;
+ gCacheName->getFullName(id, name);
+ return LLMuteList::getInstance()->isMuted(id, name);
+}
diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h
new file mode 100644
index 0000000000..ebfd40b796
--- /dev/null
+++ b/indra/newview/llavataractions.h
@@ -0,0 +1,176 @@
+/**
+ * @file llavataractions.h
+ * @brief Friend-related actions (add, remove, offer teleport, etc)
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLAVATARACTIONS_H
+#define LL_LLAVATARACTIONS_H
+
+#include "lldarray.h"
+#include "llsd.h"
+#include "lluuid.h"
+
+#include <string>
+#include <vector>
+
+/**
+ * Friend-related actions (add, remove, offer teleport, etc)
+ */
+class LLAvatarActions
+{
+public:
+ /**
+ * Show a dialog explaining what friendship entails, then request friendship.
+ */
+ static void requestFriendshipDialog(const LLUUID& id, const std::string& name);
+
+ /**
+ * Show a dialog explaining what friendship entails, then request friendship.
+ */
+ static void requestFriendshipDialog(const LLUUID& id);
+
+ /**
+ * Show a friend removal dialog.
+ */
+ static void removeFriendDialog(const LLUUID& id);
+ static void removeFriendsDialog(const std::vector<LLUUID>& ids);
+
+ /**
+ * Show teleport offer dialog.
+ */
+ static void offerTeleport(const LLUUID& invitee);
+ static void offerTeleport(const std::vector<LLUUID>& ids);
+
+ /**
+ * Start instant messaging session.
+ */
+ static void startIM(const LLUUID& id);
+
+ /**
+ * End instant messaging session.
+ */
+ static void endIM(const LLUUID& id);
+
+ /**
+ * Start an avatar-to-avatar voice call with another user
+ */
+ static void startCall(const LLUUID& id);
+
+ /**
+ * Start an ad-hoc conference voice call with multiple users
+ */
+ static void startAdhocCall(const std::vector<LLUUID>& ids);
+
+ /**
+ * Start conference chat with the given avatars.
+ */
+ static void startConference(const std::vector<LLUUID>& ids);
+
+ /**
+ * Show avatar profile.
+ */
+ static void showProfile(const LLUUID& id);
+
+ /**
+ * Give money to the avatar.
+ */
+ static void pay(const LLUUID& id);
+
+ /**
+ * Share items with the avatar.
+ */
+ static void share(const LLUUID& id);
+
+ /**
+ * Block/unblock the avatar.
+ */
+ static void toggleBlock(const LLUUID& id);
+
+ /**
+ * Return true if avatar with "id" is a friend
+ */
+ static bool isFriend(const LLUUID& id);
+
+ /**
+ * @return true if the avatar is blocked
+ */
+ static bool isBlocked(const LLUUID& id);
+
+ /**
+ * Return true if the avatar is in a P2P voice call with a given user
+ */
+ static bool isCalling(const LLUUID &id);
+
+ /**
+ * @return true if call to the resident can be made
+ */
+
+ static bool canCall();
+ /**
+ * Invite avatar to a group.
+ */
+ static void inviteToGroup(const LLUUID& id);
+
+ /**
+ * Kick avatar off grid
+ */
+ static void kick(const LLUUID& id);
+
+ /**
+ * Freeze avatar
+ */
+ static void freeze(const LLUUID& id);
+
+ /**
+ * Unfreeze avatar
+ */
+ static void unfreeze(const LLUUID& id);
+
+ /**
+ * Open csr page for avatar
+ */
+ static void csr(const LLUUID& id, std::string name);
+
+
+private:
+ static bool callbackAddFriend(const LLSD& notification, const LLSD& response);
+ static bool callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response);
+ static bool handleRemove(const LLSD& notification, const LLSD& response);
+ static bool handlePay(const LLSD& notification, const LLSD& response, LLUUID avatar_id);
+ static bool handleKick(const LLSD& notification, const LLSD& response);
+ static bool handleFreeze(const LLSD& notification, const LLSD& response);
+ static bool handleUnfreeze(const LLSD& notification, const LLSD& response);
+ static void callback_invite_to_group(LLUUID group_id, LLUUID id);
+
+ // Just request friendship, no dialog.
+ static void requestFriendship(const LLUUID& target_id, const std::string& target_name, const std::string& message);
+};
+
+#endif // LL_LLAVATARACTIONS_H
diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp
new file mode 100644
index 0000000000..87b8d807c4
--- /dev/null
+++ b/indra/newview/llavatariconctrl.cpp
@@ -0,0 +1,310 @@
+/**
+ * @file llavatariconctrl.cpp
+ * @brief LLAvatarIconCtrl class implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llavatariconctrl.h"
+
+#include "llagent.h"
+#include "llavatarconstants.h"
+#include "llcallingcard.h" // for LLAvatarTracker
+#include "llavataractions.h"
+#include "llmenugl.h"
+#include "lluictrlfactory.h"
+
+#include "llcachename.h"
+#include "llagentdata.h"
+#include "llimfloater.h"
+
+#define MENU_ITEM_VIEW_PROFILE 0
+#define MENU_ITEM_SEND_IM 1
+
+static LLDefaultChildRegistry::Register<LLAvatarIconCtrl> r("avatar_icon");
+
+bool LLAvatarIconIDCache::LLAvatarIconIDCacheItem::expired()
+{
+ const F64 SEC_PER_DAY_PLUS_HOUR = (24.0 + 1.0) * 60.0 * 60.0;
+ F64 delta = LLDate::now().secondsSinceEpoch() - cached_time.secondsSinceEpoch();
+ if (delta > SEC_PER_DAY_PLUS_HOUR)
+ return true;
+ return false;
+}
+
+void LLAvatarIconIDCache::load ()
+{
+ llinfos << "Loading avatar icon id cache." << llendl;
+
+ // build filename for each user
+ std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, mFilename);
+ llifstream file(resolved_filename);
+
+ if (!file.is_open())
+ return;
+
+ // add each line in the file to the list
+ int uuid_len = UUID_STR_LENGTH-1;
+ std::string line;
+ while (std::getline(file, line))
+ {
+ LLUUID avatar_id;
+ LLUUID icon_id;
+ LLDate date;
+
+ std::string avatar_id_str = line.substr(0,uuid_len);
+ std::string icon_id_str = line.substr(uuid_len,uuid_len);
+
+ std::string date_str = line.substr(uuid_len*2, line.length()-uuid_len*2);
+
+ if(!avatar_id.set(avatar_id_str) || !icon_id.set(icon_id_str) || !date.fromString(date_str))
+ continue;
+
+ LLAvatarIconIDCacheItem item = {icon_id,date};
+ mCache[avatar_id] = item;
+ }
+
+ file.close();
+
+}
+
+void LLAvatarIconIDCache::save ()
+{
+ std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, mFilename);
+
+ // open a file for writing
+ llofstream file (resolved_filename);
+ if (!file.is_open())
+ {
+ llwarns << "can't open avatar icons cache file\"" << mFilename << "\" for writing" << llendl;
+ return;
+ }
+
+ for(std::map<LLUUID,LLAvatarIconIDCacheItem>::iterator it = mCache.begin();it!=mCache.end();++it)
+ {
+ if(!it->second.expired())
+ {
+ file << it->first << it->second.icon_id << it->second.cached_time << std::endl;
+ }
+ }
+
+ file.close();
+}
+
+LLUUID* LLAvatarIconIDCache::get (const LLUUID& avatar_id)
+{
+ std::map<LLUUID,LLAvatarIconIDCacheItem>::iterator it = mCache.find(avatar_id);
+ if(it==mCache.end())
+ return 0;
+ if(it->second.expired())
+ return 0;
+ return &it->second.icon_id;
+}
+
+void LLAvatarIconIDCache::add (const LLUUID& avatar_id,const LLUUID& icon_id)
+{
+ LLAvatarIconIDCacheItem item = {icon_id,LLDate::now()};
+ mCache[avatar_id] = item;
+}
+
+void LLAvatarIconIDCache::remove (const LLUUID& avatar_id)
+{
+ mCache.erase(avatar_id);
+}
+
+
+LLAvatarIconCtrl::Params::Params()
+: avatar_id("avatar_id"),
+ draw_tooltip("draw_tooltip", true),
+ default_icon_name("default_icon_name")
+{
+ name = "avatar_icon";
+}
+
+
+LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p)
+: LLIconCtrl(p),
+ mDrawTooltip(p.draw_tooltip),
+ mDefaultIconName(p.default_icon_name)
+{
+ mPriority = LLViewerFetchedTexture::BOOST_ICON;
+
+ LLRect rect = p.rect;
+ mDrawWidth = llmax(32, rect.getWidth()) ;
+ mDrawHeight = llmax(32, rect.getHeight()) ;
+
+ static LLUICachedControl<S32> llavatariconctrl_symbol_hpad("UIAvatariconctrlSymbolHPad", 2);
+ static LLUICachedControl<S32> llavatariconctrl_symbol_vpad("UIAvatariconctrlSymbolVPad", 2);
+ static LLUICachedControl<S32> llavatariconctrl_symbol_size("UIAvatariconctrlSymbolSize", 5);
+ static LLUICachedControl<std::string> llavatariconctrl_symbol_pos("UIAvatariconctrlSymbolPosition", "BottomRight");
+
+ // BottomRight is the default position
+ S32 left = rect.getWidth() - llavatariconctrl_symbol_size - llavatariconctrl_symbol_hpad;
+ S32 bottom = llavatariconctrl_symbol_vpad;
+
+ if ("BottomLeft" == (std::string)llavatariconctrl_symbol_pos)
+ {
+ left = llavatariconctrl_symbol_hpad;
+ bottom = llavatariconctrl_symbol_vpad;
+ }
+ else if ("TopLeft" == (std::string)llavatariconctrl_symbol_pos)
+ {
+ left = llavatariconctrl_symbol_hpad;
+ bottom = rect.getHeight() - llavatariconctrl_symbol_size - llavatariconctrl_symbol_vpad;
+ }
+ else if ("TopRight" == (std::string)llavatariconctrl_symbol_pos)
+ {
+ left = rect.getWidth() - llavatariconctrl_symbol_size - llavatariconctrl_symbol_hpad;
+ bottom = rect.getHeight() - llavatariconctrl_symbol_size - llavatariconctrl_symbol_vpad;
+ }
+
+ rect.setOriginAndSize(left, bottom, llavatariconctrl_symbol_size, llavatariconctrl_symbol_size);
+
+ if (p.avatar_id.isProvided())
+ {
+ LLSD value(p.avatar_id);
+ setValue(value);
+ }
+ else
+ {
+ LLIconCtrl::setValue(mDefaultIconName);
+ }
+}
+
+LLAvatarIconCtrl::~LLAvatarIconCtrl()
+{
+ if (mAvatarId.notNull())
+ {
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(mAvatarId, this);
+ // Name callbacks will be automatically disconnected since LLUICtrl is trackable
+ }
+}
+
+//virtual
+void LLAvatarIconCtrl::setValue(const LLSD& value)
+{
+ if (value.isUUID())
+ {
+ LLAvatarPropertiesProcessor* app =
+ LLAvatarPropertiesProcessor::getInstance();
+ if (mAvatarId.notNull())
+ {
+ app->removeObserver(mAvatarId, this);
+ }
+
+ if (mAvatarId != value.asUUID())
+ {
+ mAvatarId = value.asUUID();
+
+ // *BUG: This will return stale icons if a user changes their
+ // profile picture. However, otherwise we send too many upstream
+ // AvatarPropertiesRequest messages.
+
+ // to get fresh avatar icon use
+ // LLAvatarIconIDCache::getInstance()->remove(avatar_id);
+
+ // Check if cache already contains image_id for that avatar
+ if (!updateFromCache())
+ {
+ LLIconCtrl::setValue(mDefaultIconName);
+ app->addObserver(mAvatarId, this);
+ app->sendAvatarPropertiesRequest(mAvatarId);
+ }
+ }
+ }
+ else
+ {
+ LLIconCtrl::setValue(value);
+ }
+
+ gCacheName->get(mAvatarId, FALSE, boost::bind(&LLAvatarIconCtrl::nameUpdatedCallback, this, _1, _2, _3, _4));
+}
+
+bool LLAvatarIconCtrl::updateFromCache()
+{
+ LLUUID* icon_id_ptr = LLAvatarIconIDCache::getInstance()->get(mAvatarId);
+ if(!icon_id_ptr)
+ return false;
+
+ const LLUUID& icon_id = *icon_id_ptr;
+
+ // Update the avatar
+ if (icon_id.notNull())
+ {
+ LLIconCtrl::setValue(icon_id);
+ }
+ else
+ {
+ LLIconCtrl::setValue(mDefaultIconName);
+ }
+
+ return true;
+}
+
+//virtual
+void LLAvatarIconCtrl::processProperties(void* data, EAvatarProcessorType type)
+{
+ if (APT_PROPERTIES == type)
+ {
+ LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data);
+ if (avatar_data)
+ {
+ if (avatar_data->avatar_id != mAvatarId)
+ {
+ return;
+ }
+
+ LLAvatarIconIDCache::getInstance()->add(mAvatarId,avatar_data->image_id);
+ updateFromCache();
+ }
+ }
+}
+
+void LLAvatarIconCtrl::nameUpdatedCallback(
+ const LLUUID& id,
+ const std::string& first,
+ const std::string& last,
+ BOOL is_group)
+{
+ if (id == mAvatarId)
+ {
+ mFirstName = first;
+ mLastName = last;
+
+ if (mDrawTooltip)
+ {
+ setToolTip(mFirstName + " " + mLastName);
+ }
+ else
+ {
+ setToolTip(std::string(""));
+ }
+ }
+}
diff --git a/indra/newview/llavatariconctrl.h b/indra/newview/llavatariconctrl.h
new file mode 100644
index 0000000000..38616b7852
--- /dev/null
+++ b/indra/newview/llavatariconctrl.h
@@ -0,0 +1,115 @@
+/**
+ * @file llavatariconctrl.h
+ * @brief LLAvatarIconCtrl base class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLAVATARICONCTRL_H
+#define LL_LLAVATARICONCTRL_H
+
+#include "lliconctrl.h"
+#include "llavatarpropertiesprocessor.h"
+#include "llviewermenu.h"
+
+class LLAvatarIconIDCache: public LLSingleton<LLAvatarIconIDCache>
+{
+public:
+ struct LLAvatarIconIDCacheItem
+ {
+ LLUUID icon_id;
+ LLDate cached_time;
+
+ bool expired();
+ };
+
+ LLAvatarIconIDCache():mFilename("avatar_icons_cache.txt")
+ {
+ }
+
+ void load ();
+ void save ();
+
+ LLUUID* get (const LLUUID& id);
+ void add (const LLUUID& avatar_id,const LLUUID& icon_id);
+
+ void remove (const LLUUID& id);
+protected:
+
+
+ std::string mFilename;
+ std::map<LLUUID,LLAvatarIconIDCacheItem> mCache;//we cache only LLUID and time
+};
+
+class LLAvatarIconCtrl
+: public LLIconCtrl, public LLAvatarPropertiesObserver
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLIconCtrl::Params>
+ {
+ Optional <LLUUID> avatar_id;
+ Optional <bool> draw_tooltip;
+ Optional <std::string> default_icon_name;
+ Params();
+ };
+
+protected:
+ LLAvatarIconCtrl(const Params&);
+ friend class LLUICtrlFactory;
+
+public:
+ virtual ~LLAvatarIconCtrl();
+
+ virtual void setValue(const LLSD& value);
+
+ // LLAvatarPropertiesProcessor observer trigger
+ virtual void processProperties(void* data, EAvatarProcessorType type);
+
+ void nameUpdatedCallback(
+ const LLUUID& id,
+ const std::string& first,
+ const std::string& last,
+ BOOL is_group);
+
+ const LLUUID& getAvatarId() const { return mAvatarId; }
+ const std::string& getFirstName() const { return mFirstName; }
+ const std::string& getLastName() const { return mLastName; }
+
+ void setDrawTooltip(bool value) { mDrawTooltip = value;}
+
+protected:
+ LLUUID mAvatarId;
+ std::string mFirstName;
+ std::string mLastName;
+ bool mDrawTooltip;
+ std::string mDefaultIconName;
+
+ bool updateFromCache();
+};
+
+#endif // LL_LLAVATARICONCTRL_H
diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp
new file mode 100644
index 0000000000..6784e6693b
--- /dev/null
+++ b/indra/newview/llavatarlist.cpp
@@ -0,0 +1,452 @@
+/**
+ * @file llavatarlist.h
+ * @brief Generic avatar list
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llavatarlist.h"
+#include "llagentdata.h" // for comparator
+
+// newview
+#include "llcallingcard.h" // for LLAvatarTracker
+#include "llcachename.h"
+#include "llrecentpeople.h"
+#include "llvoiceclient.h"
+#include "llviewercontrol.h" // for gSavedSettings
+
+static LLDefaultChildRegistry::Register<LLAvatarList> r("avatar_list");
+
+// Last interaction time update period.
+static const F32 LIT_UPDATE_PERIOD = 5;
+
+// Maximum number of avatars that can be added to a list in one pass.
+// Used to limit time spent for avatar list update per frame.
+static const unsigned ADD_LIMIT = 50;
+
+bool LLAvatarList::contains(const LLUUID& id)
+{
+ const uuid_vector_t& ids = getIDs();
+ return std::find(ids.begin(), ids.end(), id) != ids.end();
+}
+
+void LLAvatarList::toggleIcons()
+{
+ // Save the new value for new items to use.
+ mShowIcons = !mShowIcons;
+ gSavedSettings.setBOOL(mIconParamName, mShowIcons);
+
+ // Show/hide icons for all existing items.
+ std::vector<LLPanel*> items;
+ getItems(items);
+ for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
+ {
+ static_cast<LLAvatarListItem*>(*it)->setAvatarIconVisible(mShowIcons);
+ }
+}
+
+void LLAvatarList::setSpeakingIndicatorsVisible(bool visible)
+{
+ // Save the new value for new items to use.
+ mShowSpeakingIndicator = visible;
+
+ // Show/hide icons for all existing items.
+ std::vector<LLPanel*> items;
+ getItems(items);
+ for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
+ {
+ static_cast<LLAvatarListItem*>(*it)->showSpeakingIndicator(mShowSpeakingIndicator);
+ }
+}
+
+static bool findInsensitive(std::string haystack, const std::string& needle_upper)
+{
+ LLStringUtil::toUpper(haystack);
+ return haystack.find(needle_upper) != std::string::npos;
+}
+
+
+//comparators
+static const LLAvatarItemNameComparator NAME_COMPARATOR;
+static const LLFlatListView::ItemReverseComparator REVERSE_NAME_COMPARATOR(NAME_COMPARATOR);
+
+LLAvatarList::Params::Params()
+: ignore_online_status("ignore_online_status", false)
+, show_last_interaction_time("show_last_interaction_time", false)
+, show_info_btn("show_info_btn", true)
+, show_profile_btn("show_profile_btn", true)
+, show_speaking_indicator("show_speaking_indicator", true)
+{
+}
+
+LLAvatarList::LLAvatarList(const Params& p)
+: LLFlatListView(p)
+, mIgnoreOnlineStatus(p.ignore_online_status)
+, mShowLastInteractionTime(p.show_last_interaction_time)
+, mContextMenu(NULL)
+, mDirty(true) // to force initial update
+, mLITUpdateTimer(NULL)
+, mShowIcons(true)
+, mShowInfoBtn(p.show_info_btn)
+, mShowProfileBtn(p.show_profile_btn)
+, mShowSpeakingIndicator(p.show_speaking_indicator)
+{
+ setCommitOnSelectionChange(true);
+
+ // Set default sort order.
+ setComparator(&NAME_COMPARATOR);
+
+ if (mShowLastInteractionTime)
+ {
+ mLITUpdateTimer = new LLTimer();
+ mLITUpdateTimer->setTimerExpirySec(0); // zero to force initial update
+ mLITUpdateTimer->start();
+ }
+}
+
+LLAvatarList::~LLAvatarList()
+{
+ delete mLITUpdateTimer;
+}
+
+void LLAvatarList::setShowIcons(std::string param_name)
+{
+ mIconParamName= param_name;
+ mShowIcons = gSavedSettings.getBOOL(mIconParamName);
+}
+
+// virtual
+void LLAvatarList::draw()
+{
+ // *NOTE dzaporozhan
+ // Call refresh() after draw() to avoid flickering of avatar list items.
+
+ LLFlatListView::draw();
+
+ if (mDirty)
+ refresh();
+
+ if (mShowLastInteractionTime && mLITUpdateTimer->hasExpired())
+ {
+ updateLastInteractionTimes();
+ mLITUpdateTimer->setTimerExpirySec(LIT_UPDATE_PERIOD); // restart the timer
+ }
+}
+
+//virtual
+void LLAvatarList::clear()
+{
+ getIDs().clear();
+ setDirty(true);
+ LLFlatListView::clear();
+}
+
+void LLAvatarList::setNameFilter(const std::string& filter)
+{
+ if (mNameFilter != filter)
+ {
+ mNameFilter = filter;
+ setDirty();
+ }
+}
+
+void LLAvatarList::sortByName()
+{
+ setComparator(&NAME_COMPARATOR);
+ sort();
+}
+
+//////////////////////////////////////////////////////////////////////////
+// PROTECTED SECTION
+//////////////////////////////////////////////////////////////////////////
+
+void LLAvatarList::refresh()
+{
+ bool have_names = TRUE;
+ bool add_limit_exceeded = false;
+ bool modified = false;
+ bool have_filter = !mNameFilter.empty();
+
+ // Save selection.
+ std::vector<LLUUID> selected_ids;
+ getSelectedUUIDs(selected_ids);
+ LLUUID current_id = getSelectedUUID();
+
+ // Determine what to add and what to remove.
+ std::vector<LLUUID> added, removed;
+ LLAvatarList::computeDifference(getIDs(), added, removed);
+
+ // Handle added items.
+ unsigned nadded = 0;
+ for (std::vector<LLUUID>::const_iterator it=added.begin(); it != added.end(); it++)
+ {
+ std::string name;
+ const LLUUID& buddy_id = *it;
+ have_names &= (bool)gCacheName->getFullName(buddy_id, name);
+ if (!have_filter || findInsensitive(name, mNameFilter))
+ {
+ if (nadded >= ADD_LIMIT)
+ {
+ add_limit_exceeded = true;
+ break;
+ }
+ else
+ {
+ addNewItem(buddy_id, name, LLAvatarTracker::instance().isBuddyOnline(buddy_id));
+ modified = true;
+ nadded++;
+ }
+ }
+ }
+
+ // Handle removed items.
+ for (std::vector<LLUUID>::const_iterator it=removed.begin(); it != removed.end(); it++)
+ {
+ removeItemByUUID(*it);
+ modified = true;
+ }
+
+ // Handle filter.
+ if (have_filter)
+ {
+ std::vector<LLSD> cur_values;
+ getValues(cur_values);
+
+ for (std::vector<LLSD>::const_iterator it=cur_values.begin(); it != cur_values.end(); it++)
+ {
+ std::string name;
+ const LLUUID& buddy_id = it->asUUID();
+ have_names &= (bool)gCacheName->getFullName(buddy_id, name);
+ if (!findInsensitive(name, mNameFilter))
+ {
+ removeItemByUUID(buddy_id);
+ modified = true;
+ }
+ }
+ }
+
+ // Changed item in place, need to request sort and update columns
+ // because we might have changed data in a column on which the user
+ // has already sorted. JC
+ sort();
+
+ // re-select items
+ // selectMultiple(selected_ids); // TODO: implement in LLFlatListView if need
+ selectItemByUUID(current_id);
+
+ // If the name filter is specified and the names are incomplete,
+ // we need to re-update when the names are complete so that
+ // the filter can be applied correctly.
+ //
+ // Otherwise, if we have no filter then no need to update again
+ // because the items will update their names.
+ bool dirty = add_limit_exceeded || (have_filter && !have_names);
+ setDirty(dirty);
+
+ // Refreshed all items.
+ if(!dirty)
+ {
+ // Highlight items matching the filter.
+ std::vector<LLPanel*> items;
+ getItems(items);
+ for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
+ {
+ static_cast<LLAvatarListItem*>(*it)->setHighlight(mNameFilter);
+ }
+
+ // Send refresh_complete signal.
+ std::vector<LLSD> cur_values;
+ getValues(cur_values);
+ mRefreshCompleteSignal(this, LLSD((S32)cur_values.size()));
+ }
+
+ // Commit if we've added/removed items.
+ if (modified)
+ onCommit();
+}
+
+bool LLAvatarList::filterHasMatches()
+{
+ uuid_vector_t values = getIDs();
+
+ for (uuid_vector_t::const_iterator it=values.begin(); it != values.end(); it++)
+ {
+ std::string name;
+ const LLUUID& buddy_id = *it;
+ BOOL have_name = gCacheName->getFullName(buddy_id, name);
+
+ // If name has not been loaded yet we consider it as a match.
+ // When the name will be loaded the filter will be applied again(in refresh()).
+
+ if (have_name && !findInsensitive(name, mNameFilter))
+ {
+ continue;
+ }
+
+ return true;
+ }
+ return false;
+}
+
+boost::signals2::connection LLAvatarList::setRefreshCompleteCallback(const commit_signal_t::slot_type& cb)
+{
+ return mRefreshCompleteSignal.connect(cb);
+}
+
+boost::signals2::connection LLAvatarList::setItemDoubleClickCallback(const mouse_signal_t::slot_type& cb)
+{
+ return mItemDoubleClickSignal.connect(cb);
+}
+
+void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_online, EAddPosition pos)
+{
+ LLAvatarListItem* item = new LLAvatarListItem();
+ item->setName(name);
+ item->setAvatarId(id, mIgnoreOnlineStatus);
+ item->setOnline(mIgnoreOnlineStatus ? true : is_online);
+ item->showLastInteractionTime(mShowLastInteractionTime);
+
+ item->setAvatarIconVisible(mShowIcons);
+ item->setShowInfoBtn(mShowInfoBtn);
+ item->setShowProfileBtn(mShowProfileBtn);
+ item->showSpeakingIndicator(mShowSpeakingIndicator);
+
+ item->setDoubleClickCallback(boost::bind(&LLAvatarList::onItemDoucleClicked, this, _1, _2, _3, _4));
+
+ addItem(item, id, pos);
+}
+
+// virtual
+BOOL LLAvatarList::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask);
+ if ( mContextMenu )
+ {
+ std::vector<LLUUID> selected_uuids;
+ getSelectedUUIDs(selected_uuids);
+ mContextMenu->show(this, selected_uuids, x, y);
+ }
+ return handled;
+}
+
+void LLAvatarList::computeDifference(
+ const std::vector<LLUUID>& vnew_unsorted,
+ std::vector<LLUUID>& vadded,
+ std::vector<LLUUID>& vremoved)
+{
+ std::vector<LLUUID> vcur;
+ std::vector<LLUUID> vnew = vnew_unsorted;
+
+ // Convert LLSDs to LLUUIDs.
+ {
+ std::vector<LLSD> vcur_values;
+ getValues(vcur_values);
+
+ for (size_t i=0; i<vcur_values.size(); i++)
+ vcur.push_back(vcur_values[i].asUUID());
+ }
+
+ std::sort(vcur.begin(), vcur.end());
+ std::sort(vnew.begin(), vnew.end());
+
+ std::vector<LLUUID>::iterator it;
+ size_t maxsize = llmax(vcur.size(), vnew.size());
+ vadded.resize(maxsize);
+ vremoved.resize(maxsize);
+
+ // what to remove
+ it = set_difference(vcur.begin(), vcur.end(), vnew.begin(), vnew.end(), vremoved.begin());
+ vremoved.erase(it, vremoved.end());
+
+ // what to add
+ it = set_difference(vnew.begin(), vnew.end(), vcur.begin(), vcur.end(), vadded.begin());
+ vadded.erase(it, vadded.end());
+}
+
+// Refresh shown time of our last interaction with all listed avatars.
+void LLAvatarList::updateLastInteractionTimes()
+{
+ S32 now = (S32) LLDate::now().secondsSinceEpoch();
+ std::vector<LLPanel*> items;
+ getItems(items);
+
+ for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
+ {
+ // *TODO: error handling
+ LLAvatarListItem* item = static_cast<LLAvatarListItem*>(*it);
+ S32 secs_since = now - (S32) LLRecentPeople::instance().getDate(item->getAvatarId()).secondsSinceEpoch();
+ if (secs_since >= 0)
+ item->setLastInteractionTime(secs_since);
+ }
+}
+
+void LLAvatarList::onItemDoucleClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask)
+{
+ mItemDoubleClickSignal(ctrl, x, y, mask);
+}
+
+bool LLAvatarItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const
+{
+ const LLAvatarListItem* avatar_item1 = dynamic_cast<const LLAvatarListItem*>(item1);
+ const LLAvatarListItem* avatar_item2 = dynamic_cast<const LLAvatarListItem*>(item2);
+
+ if (!avatar_item1 || !avatar_item2)
+ {
+ llerror("item1 and item2 cannot be null", 0);
+ return true;
+ }
+
+ return doCompare(avatar_item1, avatar_item2);
+}
+
+bool LLAvatarItemNameComparator::doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const
+{
+ std::string name1 = avatar_item1->getAvatarName();
+ std::string name2 = avatar_item2->getAvatarName();
+
+ LLStringUtil::toUpper(name1);
+ LLStringUtil::toUpper(name2);
+
+ return name1 < name2;
+}
+bool LLAvatarItemAgentOnTopComparator::doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const
+{
+ //keep agent on top, if first is agent,
+ //then we need to return true to elevate this id, otherwise false.
+ if(avatar_item1->getAvatarId() == gAgentID)
+ {
+ return true;
+ }
+ else if (avatar_item2->getAvatarId() == gAgentID)
+ {
+ return false;
+ }
+ return LLAvatarItemNameComparator::doCompare(avatar_item1,avatar_item2);
+}
diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h
new file mode 100644
index 0000000000..a58a562378
--- /dev/null
+++ b/indra/newview/llavatarlist.h
@@ -0,0 +1,175 @@
+/**
+ * @file llavatarlist.h
+ * @brief Generic avatar list
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLAVATARLIST_H
+#define LL_LLAVATARLIST_H
+
+#include "llflatlistview.h"
+
+#include "llavatarlistitem.h"
+
+class LLTimer;
+
+/**
+ * Generic list of avatars.
+ *
+ * Updates itself when it's dirty, using optional name filter.
+ * To initiate update, modify the UUID list and call setDirty().
+ *
+ * @see getIDs()
+ * @see setDirty()
+ * @see setNameFilter()
+ */
+class LLAvatarList : public LLFlatListView
+{
+ LOG_CLASS(LLAvatarList);
+public:
+ typedef std::vector<LLUUID> uuid_vector_t;
+
+ struct Params : public LLInitParam::Block<Params, LLFlatListView::Params>
+ {
+ Optional<bool> ignore_online_status; // show all items as online
+ Optional<bool> show_last_interaction_time; // show most recent interaction time. *HACK: move this to a derived class
+ Optional<bool> show_info_btn;
+ Optional<bool> show_profile_btn;
+ Optional<bool> show_speaking_indicator;
+ Params();
+ };
+
+ LLAvatarList(const Params&);
+ virtual ~LLAvatarList();
+
+ virtual void draw(); // from LLView
+
+ virtual void clear();
+
+ void setNameFilter(const std::string& filter);
+ void setDirty(bool val = true) { mDirty = val; }
+ uuid_vector_t& getIDs() { return mIDs; }
+ bool contains(const LLUUID& id);
+
+ void setContextMenu(LLAvatarListItem::ContextMenu* menu) { mContextMenu = menu; }
+
+ void toggleIcons();
+ void setSpeakingIndicatorsVisible(bool visible);
+ void sortByName();
+ void setShowIcons(std::string param_name);
+ bool getIconsVisible() const { return mShowIcons; }
+ const std::string getIconParamName() const{return mIconParamName;}
+ virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+
+ // Return true if filter has at least one match.
+ bool filterHasMatches();
+
+ boost::signals2::connection setRefreshCompleteCallback(const commit_signal_t::slot_type& cb);
+
+ boost::signals2::connection setItemDoubleClickCallback(const mouse_signal_t::slot_type& cb);
+
+protected:
+ void refresh();
+
+ void addNewItem(const LLUUID& id, const std::string& name, BOOL is_online, EAddPosition pos = ADD_BOTTOM);
+ void computeDifference(
+ const std::vector<LLUUID>& vnew,
+ std::vector<LLUUID>& vadded,
+ std::vector<LLUUID>& vremoved);
+ void updateLastInteractionTimes();
+ void onItemDoucleClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask);
+
+private:
+
+ bool mIgnoreOnlineStatus;
+ bool mShowLastInteractionTime;
+ bool mDirty;
+ bool mShowIcons;
+ bool mShowInfoBtn;
+ bool mShowProfileBtn;
+ bool mShowSpeakingIndicator;
+
+ LLTimer* mLITUpdateTimer; // last interaction time update timer
+ std::string mIconParamName;
+ std::string mNameFilter;
+ uuid_vector_t mIDs;
+
+ LLAvatarListItem::ContextMenu* mContextMenu;
+
+ commit_signal_t mRefreshCompleteSignal;
+ mouse_signal_t mItemDoubleClickSignal;
+};
+
+/** Abstract comparator for avatar items */
+class LLAvatarItemComparator : public LLFlatListView::ItemComparator
+{
+ LOG_CLASS(LLAvatarItemComparator);
+
+public:
+ LLAvatarItemComparator() {};
+ virtual ~LLAvatarItemComparator() {};
+
+ virtual bool compare(const LLPanel* item1, const LLPanel* item2) const;
+
+protected:
+
+ /**
+ * Returns true if avatar_item1 < avatar_item2, false otherwise
+ * Implement this method in your particular comparator.
+ * In Linux a compiler failed to build it using the name "compare", so it was renamed to doCompare
+ */
+ virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const = 0;
+};
+
+
+class LLAvatarItemNameComparator : public LLAvatarItemComparator
+{
+ LOG_CLASS(LLAvatarItemNameComparator);
+
+public:
+ LLAvatarItemNameComparator() {};
+ virtual ~LLAvatarItemNameComparator() {};
+
+protected:
+ virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const;
+};
+
+class LLAvatarItemAgentOnTopComparator : public LLAvatarItemNameComparator
+{
+ LOG_CLASS(LLAvatarItemAgentOnTopComparator);
+
+public:
+ LLAvatarItemAgentOnTopComparator() {};
+ virtual ~LLAvatarItemAgentOnTopComparator() {};
+
+protected:
+ virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const;
+};
+
+#endif // LL_LLAVATARLIST_H
diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp
new file mode 100644
index 0000000000..2bcd097717
--- /dev/null
+++ b/indra/newview/llavatarlistitem.cpp
@@ -0,0 +1,569 @@
+/**
+ * @file llavatarlistitem.cpp
+ * @avatar list item source file
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llavataractions.h"
+#include "llavatarlistitem.h"
+
+#include "llfloaterreg.h"
+#include "llagent.h"
+#include "lloutputmonitorctrl.h"
+#include "llavatariconctrl.h"
+#include "lltextutil.h"
+#include "llbutton.h"
+
+bool LLAvatarListItem::sStaticInitialized = false;
+S32 LLAvatarListItem::sLeftPadding = 0;
+S32 LLAvatarListItem::sRightNamePadding = 0;
+S32 LLAvatarListItem::sChildrenWidths[LLAvatarListItem::ALIC_COUNT];
+
+
+LLAvatarListItem::LLAvatarListItem(bool not_from_ui_factory/* = true*/)
+: LLPanel(),
+ mAvatarIcon(NULL),
+ mAvatarName(NULL),
+ mLastInteractionTime(NULL),
+ mSpeakingIndicator(NULL),
+ mInfoBtn(NULL),
+ mProfileBtn(NULL),
+ mOnlineStatus(E_UNKNOWN),
+ mShowInfoBtn(true),
+ mShowProfileBtn(true)
+{
+ if (not_from_ui_factory)
+ {
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_avatar_list_item.xml");
+ }
+ // *NOTE: mantipov: do not use any member here. They can be uninitialized here in case instance
+ // is created from the UICtrlFactory
+}
+
+LLAvatarListItem::~LLAvatarListItem()
+{
+ if (mAvatarId.notNull())
+ LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarId, this);
+}
+
+BOOL LLAvatarListItem::postBuild()
+{
+ mAvatarIcon = getChild<LLAvatarIconCtrl>("avatar_icon");
+ mAvatarName = getChild<LLTextBox>("avatar_name");
+ mLastInteractionTime = getChild<LLTextBox>("last_interaction");
+
+ mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicator");
+ mInfoBtn = getChild<LLButton>("info_btn");
+ mProfileBtn = getChild<LLButton>("profile_btn");
+
+ mInfoBtn->setVisible(false);
+ mInfoBtn->setClickedCallback(boost::bind(&LLAvatarListItem::onInfoBtnClick, this));
+
+ mProfileBtn->setVisible(false);
+ mProfileBtn->setClickedCallback(boost::bind(&LLAvatarListItem::onProfileBtnClick, this));
+
+ if (!sStaticInitialized)
+ {
+ // Remember children widths including their padding from the next sibling,
+ // so that we can hide and show them again later.
+ initChildrenWidths(this);
+
+ sStaticInitialized = true;
+ }
+
+ return TRUE;
+}
+
+S32 LLAvatarListItem::notifyParent(const LLSD& info)
+{
+ if (info.has("visibility_changed"))
+ {
+ updateChildren();
+ }
+ return 0;
+}
+
+void LLAvatarListItem::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+ childSetVisible("hovered_icon", true);
+ mInfoBtn->setVisible(mShowInfoBtn);
+ mProfileBtn->setVisible(mShowProfileBtn);
+
+ LLPanel::onMouseEnter(x, y, mask);
+
+ updateChildren();
+}
+
+void LLAvatarListItem::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ childSetVisible("hovered_icon", false);
+ mInfoBtn->setVisible(false);
+ mProfileBtn->setVisible(false);
+
+ LLPanel::onMouseLeave(x, y, mask);
+
+ updateChildren();
+}
+
+// virtual, called by LLAvatarTracker
+void LLAvatarListItem::changed(U32 mask)
+{
+ // no need to check mAvatarId for null in this case
+ setOnline(LLAvatarTracker::instance().isBuddyOnline(mAvatarId));
+}
+
+void LLAvatarListItem::setOnline(bool online)
+{
+ // *FIX: setName() overrides font style set by setOnline(). Not an issue ATM.
+
+ if (mOnlineStatus != E_UNKNOWN && (bool) mOnlineStatus == online)
+ return;
+
+ mOnlineStatus = (EOnlineStatus) online;
+
+ // Change avatar name font style depending on the new online status.
+ setState(online ? IS_ONLINE : IS_OFFLINE);
+}
+
+void LLAvatarListItem::setName(const std::string& name)
+{
+ setNameInternal(name, mHighlihtSubstring);
+}
+
+void LLAvatarListItem::setHighlight(const std::string& highlight)
+{
+ setNameInternal(mAvatarName->getText(), mHighlihtSubstring = highlight);
+}
+
+void LLAvatarListItem::setState(EItemState item_style)
+{
+ item_style_map_t& item_styles_params_map = getItemStylesParams();
+
+ mAvatarNameStyle = item_styles_params_map[item_style];
+
+ // *NOTE: You cannot set the style on a text box anymore, you must
+ // rebuild the text. This will cause problems if the text contains
+ // hyperlinks, as their styles will be wrong.
+ setNameInternal(mAvatarName->getText(), mHighlihtSubstring);
+
+ icon_color_map_t& item_icon_color_map = getItemIconColorMap();
+ mAvatarIcon->setColor(item_icon_color_map[item_style]);
+}
+
+void LLAvatarListItem::setAvatarId(const LLUUID& id, bool ignore_status_changes)
+{
+ if (mAvatarId.notNull())
+ LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarId, this);
+
+ mAvatarId = id;
+ mAvatarIcon->setValue(id);
+ mSpeakingIndicator->setSpeakerId(id);
+
+ // We'll be notified on avatar online status changes
+ if (!ignore_status_changes && mAvatarId.notNull())
+ LLAvatarTracker::instance().addParticularFriendObserver(mAvatarId, this);
+
+ // Set avatar name.
+ gCacheName->get(id, FALSE, boost::bind(&LLAvatarListItem::onNameCache, this, _2, _3));
+}
+
+void LLAvatarListItem::showLastInteractionTime(bool show)
+{
+ if (show)
+ return;
+
+ mLastInteractionTime->setVisible(false);
+ updateChildren();
+}
+
+void LLAvatarListItem::setLastInteractionTime(U32 secs_since)
+{
+ mLastInteractionTime->setValue(formatSeconds(secs_since));
+}
+
+void LLAvatarListItem::setShowInfoBtn(bool show)
+{
+ // Already done? Then do nothing.
+ if(mShowInfoBtn == show)
+ return;
+ mShowInfoBtn = show;
+}
+
+void LLAvatarListItem::setShowProfileBtn(bool show)
+{
+ // Already done? Then do nothing.
+ if(mShowProfileBtn == show)
+ return;
+ mShowProfileBtn = show;
+}
+
+void LLAvatarListItem::showSpeakingIndicator(bool visible)
+{
+ // Already done? Then do nothing.
+ if (mSpeakingIndicator->getVisible() == (BOOL)visible)
+ return;
+// Disabled to not contradict with SpeakingIndicatorManager functionality. EXT-3976
+// probably this method should be totally removed.
+// mSpeakingIndicator->setVisible(visible);
+// updateChildren();
+}
+
+void LLAvatarListItem::setAvatarIconVisible(bool visible)
+{
+ // Already done? Then do nothing.
+ if (mAvatarIcon->getVisible() == (BOOL)visible)
+ return;
+
+ // Show/hide avatar icon.
+ mAvatarIcon->setVisible(visible);
+ updateChildren();
+}
+
+void LLAvatarListItem::onInfoBtnClick()
+{
+ LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", mAvatarId));
+}
+
+void LLAvatarListItem::onProfileBtnClick()
+{
+ LLAvatarActions::showProfile(mAvatarId);
+}
+
+BOOL LLAvatarListItem::handleDoubleClick(S32 x, S32 y, MASK mask)
+{
+ if(mInfoBtn->getRect().pointInRect(x, y))
+ {
+ onInfoBtnClick();
+ return TRUE;
+ }
+ if(mProfileBtn->getRect().pointInRect(x, y))
+ {
+ onProfileBtnClick();
+ return TRUE;
+ }
+ return LLPanel::handleDoubleClick(x, y, mask);
+}
+
+void LLAvatarListItem::setValue( const LLSD& value )
+{
+ if (!value.isMap()) return;;
+ if (!value.has("selected")) return;
+ childSetVisible("selected_icon", value["selected"]);
+}
+
+const LLUUID& LLAvatarListItem::getAvatarId() const
+{
+ return mAvatarId;
+}
+
+const std::string LLAvatarListItem::getAvatarName() const
+{
+ return mAvatarName->getValue();
+}
+
+//== PRIVATE SECITON ==========================================================
+
+void LLAvatarListItem::setNameInternal(const std::string& name, const std::string& highlight)
+{
+ LLTextUtil::textboxSetHighlightedVal(mAvatarName, mAvatarNameStyle, name, highlight);
+ mAvatarName->setToolTip(name);
+}
+
+void LLAvatarListItem::onNameCache(const std::string& first_name, const std::string& last_name)
+{
+ std::string name = first_name + " " + last_name;
+ setName(name);
+}
+
+// Convert given number of seconds to a string like "23 minutes", "15 hours" or "3 years",
+// taking i18n into account. The format string to use is taken from the panel XML.
+std::string LLAvatarListItem::formatSeconds(U32 secs)
+{
+ static const U32 LL_ALI_MIN = 60;
+ static const U32 LL_ALI_HOUR = LL_ALI_MIN * 60;
+ static const U32 LL_ALI_DAY = LL_ALI_HOUR * 24;
+ static const U32 LL_ALI_WEEK = LL_ALI_DAY * 7;
+ static const U32 LL_ALI_MONTH = LL_ALI_DAY * 30;
+ static const U32 LL_ALI_YEAR = LL_ALI_DAY * 365;
+
+ std::string fmt;
+ U32 count = 0;
+
+ if (secs >= LL_ALI_YEAR)
+ {
+ fmt = "FormatYears"; count = secs / LL_ALI_YEAR;
+ }
+ else if (secs >= LL_ALI_MONTH)
+ {
+ fmt = "FormatMonths"; count = secs / LL_ALI_MONTH;
+ }
+ else if (secs >= LL_ALI_WEEK)
+ {
+ fmt = "FormatWeeks"; count = secs / LL_ALI_WEEK;
+ }
+ else if (secs >= LL_ALI_DAY)
+ {
+ fmt = "FormatDays"; count = secs / LL_ALI_DAY;
+ }
+ else if (secs >= LL_ALI_HOUR)
+ {
+ fmt = "FormatHours"; count = secs / LL_ALI_HOUR;
+ }
+ else if (secs >= LL_ALI_MIN)
+ {
+ fmt = "FormatMinutes"; count = secs / LL_ALI_MIN;
+ }
+ else
+ {
+ fmt = "FormatSeconds"; count = secs;
+ }
+
+ LLStringUtil::format_map_t args;
+ args["[COUNT]"] = llformat("%u", count);
+ return getString(fmt, args);
+}
+
+// static
+LLAvatarListItem::item_style_map_t& LLAvatarListItem::getItemStylesParams()
+{
+ static item_style_map_t item_styles_params_map;
+ if (!item_styles_params_map.empty()) return item_styles_params_map;
+
+ LLPanel::Params params = LLUICtrlFactory::getDefaultParams<LLPanel>();
+ LLPanel* params_panel = LLUICtrlFactory::create<LLPanel>(params);
+
+ BOOL sucsess = LLUICtrlFactory::instance().buildPanel(params_panel, "panel_avatar_list_item_params.xml");
+
+ if (sucsess)
+ {
+
+ item_styles_params_map.insert(
+ std::make_pair(IS_DEFAULT,
+ params_panel->getChild<LLTextBox>("default_style")->getDefaultStyle()));
+
+ item_styles_params_map.insert(
+ std::make_pair(IS_VOICE_INVITED,
+ params_panel->getChild<LLTextBox>("voice_call_invited_style")->getDefaultStyle()));
+
+ item_styles_params_map.insert(
+ std::make_pair(IS_VOICE_JOINED,
+ params_panel->getChild<LLTextBox>("voice_call_joined_style")->getDefaultStyle()));
+
+ item_styles_params_map.insert(
+ std::make_pair(IS_VOICE_LEFT,
+ params_panel->getChild<LLTextBox>("voice_call_left_style")->getDefaultStyle()));
+
+ item_styles_params_map.insert(
+ std::make_pair(IS_ONLINE,
+ params_panel->getChild<LLTextBox>("online_style")->getDefaultStyle()));
+
+ item_styles_params_map.insert(
+ std::make_pair(IS_OFFLINE,
+ params_panel->getChild<LLTextBox>("offline_style")->getDefaultStyle()));
+ }
+ else
+ {
+ item_styles_params_map.insert(std::make_pair(IS_DEFAULT, LLStyle::Params()));
+ item_styles_params_map.insert(std::make_pair(IS_VOICE_INVITED, LLStyle::Params()));
+ item_styles_params_map.insert(std::make_pair(IS_VOICE_JOINED, LLStyle::Params()));
+ item_styles_params_map.insert(std::make_pair(IS_VOICE_LEFT, LLStyle::Params()));
+ item_styles_params_map.insert(std::make_pair(IS_ONLINE, LLStyle::Params()));
+ item_styles_params_map.insert(std::make_pair(IS_OFFLINE, LLStyle::Params()));
+ }
+ if (params_panel) params_panel->die();
+
+ return item_styles_params_map;
+}
+
+// static
+LLAvatarListItem::icon_color_map_t& LLAvatarListItem::getItemIconColorMap()
+{
+ static icon_color_map_t item_icon_color_map;
+ if (!item_icon_color_map.empty()) return item_icon_color_map;
+
+ item_icon_color_map.insert(
+ std::make_pair(IS_DEFAULT,
+ LLUIColorTable::instance().getColor("AvatarListItemIconDefaultColor", LLColor4::white)));
+
+ item_icon_color_map.insert(
+ std::make_pair(IS_VOICE_INVITED,
+ LLUIColorTable::instance().getColor("AvatarListItemIconVoiceInvitedColor", LLColor4::white)));
+
+ item_icon_color_map.insert(
+ std::make_pair(IS_VOICE_JOINED,
+ LLUIColorTable::instance().getColor("AvatarListItemIconVoiceJoinedColor", LLColor4::white)));
+
+ item_icon_color_map.insert(
+ std::make_pair(IS_VOICE_LEFT,
+ LLUIColorTable::instance().getColor("AvatarListItemIconVoiceLeftColor", LLColor4::white)));
+
+ item_icon_color_map.insert(
+ std::make_pair(IS_ONLINE,
+ LLUIColorTable::instance().getColor("AvatarListItemIconOnlineColor", LLColor4::white)));
+
+ item_icon_color_map.insert(
+ std::make_pair(IS_OFFLINE,
+ LLUIColorTable::instance().getColor("AvatarListItemIconOfflineColor", LLColor4::white)));
+
+ return item_icon_color_map;
+}
+
+// static
+void LLAvatarListItem::initChildrenWidths(LLAvatarListItem* avatar_item)
+{
+ //speaking indicator width + padding
+ S32 speaking_indicator_width = avatar_item->getRect().getWidth() - avatar_item->mSpeakingIndicator->getRect().mLeft;
+
+ //profile btn width + padding
+ S32 profile_btn_width = avatar_item->mSpeakingIndicator->getRect().mLeft - avatar_item->mProfileBtn->getRect().mLeft;
+
+ //info btn width + padding
+ S32 info_btn_width = avatar_item->mProfileBtn->getRect().mLeft - avatar_item->mInfoBtn->getRect().mLeft;
+
+ // last interaction time textbox width + padding
+ S32 last_interaction_time_width = avatar_item->mInfoBtn->getRect().mLeft - avatar_item->mLastInteractionTime->getRect().mLeft;
+
+ // icon width + padding
+ S32 icon_width = avatar_item->mAvatarName->getRect().mLeft - avatar_item->mAvatarIcon->getRect().mLeft;
+
+ sLeftPadding = avatar_item->mAvatarIcon->getRect().mLeft;
+ sRightNamePadding = avatar_item->mLastInteractionTime->getRect().mLeft - avatar_item->mAvatarName->getRect().mRight;
+
+ S32 index = ALIC_COUNT;
+ sChildrenWidths[--index] = icon_width;
+ sChildrenWidths[--index] = 0; // for avatar name we don't need its width, it will be calculated as "left available space"
+ sChildrenWidths[--index] = last_interaction_time_width;
+ sChildrenWidths[--index] = info_btn_width;
+ sChildrenWidths[--index] = profile_btn_width;
+ sChildrenWidths[--index] = speaking_indicator_width;
+}
+
+void LLAvatarListItem::updateChildren()
+{
+ LL_DEBUGS("AvatarItemReshape") << LL_ENDL;
+ LL_DEBUGS("AvatarItemReshape") << "Updating for: " << getAvatarName() << LL_ENDL;
+
+ S32 name_new_width = getRect().getWidth();
+ S32 ctrl_new_left = name_new_width;
+ S32 name_new_left = sLeftPadding;
+
+ // iterate through all children and set them into correct position depend on each child visibility
+ // assume that child indexes are in back order: the first in Enum is the last (right) in the item
+ // iterate & set child views starting from right to left
+ for (S32 i = 0; i < ALIC_COUNT; ++i)
+ {
+ // skip "name" textbox, it will be processed out of loop later
+ if (ALIC_NAME == i) continue;
+
+ LLView* control = getItemChildView((EAvatarListItemChildIndex)i);
+
+ LL_DEBUGS("AvatarItemReshape") << "Processing control: " << control->getName() << LL_ENDL;
+ // skip invisible views
+ if (!control->getVisible()) continue;
+
+ S32 ctrl_width = sChildrenWidths[i]; // including space between current & left controls
+
+ // decrease available for
+ name_new_width -= ctrl_width;
+ LL_DEBUGS("AvatarItemReshape") << "width: " << ctrl_width << ", name_new_width: " << name_new_width << LL_ENDL;
+
+ LLRect control_rect = control->getRect();
+ LL_DEBUGS("AvatarItemReshape") << "rect before: " << control_rect << LL_ENDL;
+
+ if (ALIC_ICON == i)
+ {
+ // assume that this is the last iteration,
+ // so it is not necessary to save "ctrl_new_left" value calculated on previous iterations
+ ctrl_new_left = sLeftPadding;
+ name_new_left = ctrl_new_left + ctrl_width;
+ }
+ else
+ {
+ ctrl_new_left -= ctrl_width;
+ }
+
+ LL_DEBUGS("AvatarItemReshape") << "ctrl_new_left: " << ctrl_new_left << LL_ENDL;
+
+ control_rect.setLeftTopAndSize(
+ ctrl_new_left,
+ control_rect.mTop,
+ control_rect.getWidth(),
+ control_rect.getHeight());
+
+ LL_DEBUGS("AvatarItemReshape") << "rect after: " << control_rect << LL_ENDL;
+ control->setShape(control_rect);
+ }
+
+ // set size and position of the "name" child
+ LLView* name_view = getItemChildView(ALIC_NAME);
+ LLRect name_view_rect = name_view->getRect();
+ LL_DEBUGS("AvatarItemReshape") << "name rect before: " << name_view_rect << LL_ENDL;
+
+ // apply paddings
+ name_new_width -= sLeftPadding;
+ name_new_width -= sRightNamePadding;
+
+ name_view_rect.setLeftTopAndSize(
+ name_new_left,
+ name_view_rect.mTop,
+ name_new_width,
+ name_view_rect.getHeight());
+
+ name_view->setShape(name_view_rect);
+
+ LL_DEBUGS("AvatarItemReshape") << "name rect after: " << name_view_rect << LL_ENDL;
+}
+
+LLView* LLAvatarListItem::getItemChildView(EAvatarListItemChildIndex child_view_index)
+{
+ LLView* child_view = mAvatarName;
+ if (child_view_index < 0 || ALIC_COUNT <= child_view_index)
+ {
+ LL_WARNS("AvatarItemReshape") << "Child view index is out of range: " << child_view_index << LL_ENDL;
+ return child_view;
+ }
+ switch (child_view_index)
+ {
+ case ALIC_ICON: child_view = mAvatarIcon; break;
+ case ALIC_NAME: child_view = mAvatarName; break;
+ case ALIC_INTERACTION_TIME: child_view = mLastInteractionTime; break;
+ case ALIC_SPEAKER_INDICATOR: child_view = mSpeakingIndicator; break;
+ case ALIC_INFO_BUTTON: child_view = mInfoBtn; break;
+ case ALIC_PROFILE_BUTTON: child_view = mProfileBtn; break;
+ default:
+ LL_WARNS("AvatarItemReshape") << "Unexpected child view index is passed: " << child_view_index << LL_ENDL;
+ }
+
+ return child_view;
+}
+
+// EOF
diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h
new file mode 100644
index 0000000000..61c0a8660e
--- /dev/null
+++ b/indra/newview/llavatarlistitem.h
@@ -0,0 +1,201 @@
+/**
+ * @file llavatarlistitem.h
+ * @avatar list item header file
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLAVATARLISTITEM_H
+#define LL_LLAVATARLISTITEM_H
+
+#include "llpanel.h"
+#include "lloutputmonitorctrl.h"
+#include "llbutton.h"
+#include "lltextbox.h"
+#include "llstyle.h"
+
+#include "llcallingcard.h" // for LLFriendObserver
+
+class LLAvatarIconCtrl;
+
+class LLAvatarListItem : public LLPanel, public LLFriendObserver
+{
+public:
+ typedef enum e_item_state_type {
+ IS_DEFAULT,
+ IS_VOICE_INVITED,
+ IS_VOICE_JOINED,
+ IS_VOICE_LEFT,
+ IS_ONLINE,
+ IS_OFFLINE,
+ } EItemState;
+
+ class ContextMenu
+ {
+ public:
+ virtual void show(LLView* spawning_view, const std::vector<LLUUID>& selected_uuids, S32 x, S32 y) = 0;
+ };
+
+ /**
+ * Creates an instance of LLAvatarListItem.
+ *
+ * It is not registered with LLDefaultChildRegistry. It is built via LLUICtrlFactory::buildPanel
+ * or via registered LLCallbackMap depend on passed parameter.
+ *
+ * @param not_from_ui_factory if true instance will be build with LLUICtrlFactory::buildPanel
+ * otherwise it should be registered via LLCallbackMap before creating.
+ */
+ LLAvatarListItem(bool not_from_ui_factory = true);
+ virtual ~LLAvatarListItem();
+
+ virtual BOOL postBuild();
+
+ /**
+ * Processes notification from speaker indicator to update children when indicator's visibility is changed.
+ */
+ virtual S32 notifyParent(const LLSD& info);
+ virtual void onMouseLeave(S32 x, S32 y, MASK mask);
+ virtual void onMouseEnter(S32 x, S32 y, MASK mask);
+ virtual void setValue(const LLSD& value);
+ virtual void changed(U32 mask); // from LLFriendObserver
+
+ void setOnline(bool online);
+ void setName(const std::string& name);
+ void setHighlight(const std::string& highlight);
+ void setState(EItemState item_style);
+ void setAvatarId(const LLUUID& id, bool ignore_status_changes = false);
+ void setLastInteractionTime(U32 secs_since);
+ //Show/hide profile/info btn, translating speaker indicator and avatar name coordinates accordingly
+ void setShowProfileBtn(bool show);
+ void setShowInfoBtn(bool show);
+ void showSpeakingIndicator(bool show);
+ void showLastInteractionTime(bool show);
+ void setAvatarIconVisible(bool visible);
+
+ const LLUUID& getAvatarId() const;
+ const std::string getAvatarName() const;
+
+ void onInfoBtnClick();
+ void onProfileBtnClick();
+
+ /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
+
+protected:
+ /**
+ * Contains indicator to show voice activity.
+ */
+ LLOutputMonitorCtrl* mSpeakingIndicator;
+
+ LLAvatarIconCtrl* mAvatarIcon;
+
+private:
+
+ typedef enum e_online_status {
+ E_OFFLINE,
+ E_ONLINE,
+ E_UNKNOWN,
+ } EOnlineStatus;
+
+ /**
+ * Enumeration of item elements in order from right to left.
+ *
+ * updateChildren() assumes that indexes are in the such order to process avatar icon easier.
+ *
+ * @see updateChildren()
+ */
+ typedef enum e_avatar_item_child {
+ ALIC_SPEAKER_INDICATOR,
+ ALIC_PROFILE_BUTTON,
+ ALIC_INFO_BUTTON,
+ ALIC_INTERACTION_TIME,
+ ALIC_NAME,
+ ALIC_ICON,
+ ALIC_COUNT,
+ } EAvatarListItemChildIndex;
+
+ void setNameInternal(const std::string& name, const std::string& highlight);
+ void onNameCache(const std::string& first_name, const std::string& last_name);
+
+ std::string formatSeconds(U32 secs);
+
+ typedef std::map<EItemState, LLStyle::Params> item_style_map_t;
+ static item_style_map_t& getItemStylesParams();
+
+ typedef std::map<EItemState, LLColor4> icon_color_map_t;
+ static icon_color_map_t& getItemIconColorMap();
+
+ /**
+ * Initializes widths of all children to use them while changing visibility of any of them.
+ *
+ * @see updateChildren()
+ */
+ static void initChildrenWidths(LLAvatarListItem* self);
+
+ /**
+ * Updates position and rectangle of visible children to fit all available item's width.
+ */
+ void updateChildren();
+
+ /**
+ * Gets child view specified by index.
+ *
+ * This method implemented via switch by all EAvatarListItemChildIndex values.
+ * It is used to not store children in array or vector to avoid of increasing memory usage.
+ */
+ LLView* getItemChildView(EAvatarListItemChildIndex child_index);
+
+ LLTextBox* mAvatarName;
+ LLTextBox* mLastInteractionTime;
+ LLStyle::Params mAvatarNameStyle;
+
+ LLButton* mInfoBtn;
+ LLButton* mProfileBtn;
+
+ LLUUID mAvatarId;
+ std::string mHighlihtSubstring; // substring to highlight
+ EOnlineStatus mOnlineStatus;
+ //Flag indicating that info/profile button shouldn't be shown at all.
+ //Speaker indicator and avatar name coords are translated accordingly
+ bool mShowInfoBtn;
+ bool mShowProfileBtn;
+
+ static bool sStaticInitialized; // this variable is introduced to improve code readability
+ static S32 sLeftPadding; // padding to first left visible child (icon or name)
+ static S32 sRightNamePadding; // right padding from name to next visible child
+
+ /**
+ * Contains widths of each child specified by EAvatarListItemChildIndex
+ * including padding to the next right one.
+ *
+ * @see initChildrenWidths()
+ */
+ static S32 sChildrenWidths[ALIC_COUNT];
+
+};
+
+#endif //LL_LLAVATARLISTITEM_H
diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp
new file mode 100644
index 0000000000..33e5046f50
--- /dev/null
+++ b/indra/newview/llavatarpropertiesprocessor.cpp
@@ -0,0 +1,651 @@
+/**
+ * @file llavatarpropertiesprocessor.cpp
+ * @brief LLAvatarPropertiesProcessor class implementation
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llavatarpropertiesprocessor.h"
+
+// Viewer includes
+#include "llagent.h"
+#include "llagentpicksinfo.h"
+#include "llviewergenericmessage.h"
+
+// Linden library includes
+#include "llavatarconstants.h" // AVATAR_TRANSACTED, etc.
+#include "lldate.h"
+#include "lltrans.h"
+#include "llui.h" // LLUI::getLanguage()
+#include "message.h"
+
+LLAvatarPropertiesProcessor::LLAvatarPropertiesProcessor()
+{
+}
+
+LLAvatarPropertiesProcessor::~LLAvatarPropertiesProcessor()
+{
+}
+
+void LLAvatarPropertiesProcessor::addObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer)
+{
+ // Check if that observer is already in mObservers for that avatar_id
+ observer_multimap_t::iterator it;
+
+ // IAN BUG this should update the observer's UUID if this is a dupe - sent to PE
+ it = mObservers.find(avatar_id);
+ while (it != mObservers.end())
+ {
+ if (it->second == observer)
+ {
+ return;
+ }
+ else
+ {
+ ++it;
+ }
+ }
+
+ mObservers.insert(std::pair<LLUUID, LLAvatarPropertiesObserver*>(avatar_id, observer));
+}
+
+void LLAvatarPropertiesProcessor::removeObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer)
+{
+ if (!observer)
+ {
+ return;
+ }
+
+ observer_multimap_t::iterator it;
+ it = mObservers.find(avatar_id);
+ while (it != mObservers.end())
+ {
+ if (it->second == observer)
+ {
+ mObservers.erase(it);
+ break;
+ }
+ else
+ {
+ ++it;
+ }
+ }
+}
+
+
+void LLAvatarPropertiesProcessor::sendGenericRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string method)
+{
+ // 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);
+}
+
+void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequest(const LLUUID& avatar_id)
+{
+ 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);
+
+ 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::sendAvatarPicksRequest(const LLUUID& avatar_id)
+{
+ sendGenericRequest(avatar_id, APT_PICKS, "avatarpicksrequest");
+}
+
+void LLAvatarPropertiesProcessor::sendAvatarNotesRequest(const LLUUID& avatar_id)
+{
+ sendGenericRequest(avatar_id, APT_NOTES, "avatarnotesrequest");
+}
+
+void LLAvatarPropertiesProcessor::sendAvatarGroupsRequest(const LLUUID& avatar_id)
+{
+ sendGenericRequest(avatar_id, APT_GROUPS, "avatargroupsrequest");
+}
+
+void LLAvatarPropertiesProcessor::sendAvatarTexturesRequest(const LLUUID& avatar_id)
+{
+ sendGenericRequest(avatar_id, APT_TEXTURES, "avatartexturesrequest");
+ // No response expected.
+ removePendingRequest(avatar_id, APT_TEXTURES);
+}
+
+void LLAvatarPropertiesProcessor::sendAvatarClassifiedsRequest(const LLUUID& avatar_id)
+{
+ sendGenericRequest(avatar_id, APT_CLASSIFIEDS, "avatarclassifiedsrequest");
+}
+
+void LLAvatarPropertiesProcessor::sendAvatarPropertiesUpdate(const LLAvatarData* avatar_props)
+{
+ llinfos << "Sending avatarinfo update" << llendl;
+
+ // This value is required by sendAvatarPropertiesUpdate method.
+ //A profile should never be mature. (From the original code)
+ BOOL mature = FALSE;
+
+ LLMessageSystem *msg = gMessageSystem;
+
+ msg->newMessageFast(_PREHASH_AvatarPropertiesUpdate);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast( _PREHASH_AgentID, gAgent.getID() );
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
+ msg->nextBlockFast(_PREHASH_PropertiesData);
+
+ msg->addUUIDFast( _PREHASH_ImageID, avatar_props->image_id);
+ msg->addUUIDFast( _PREHASH_FLImageID, avatar_props->fl_image_id);
+ msg->addStringFast( _PREHASH_AboutText, avatar_props->about_text);
+ msg->addStringFast( _PREHASH_FLAboutText, avatar_props->fl_about_text);
+
+ msg->addBOOL(_PREHASH_AllowPublish, avatar_props->allow_publish);
+ msg->addBOOL(_PREHASH_MaturePublish, mature);
+ msg->addString(_PREHASH_ProfileURL, avatar_props->profile_url);
+ gAgent.sendReliableMessage();
+}
+
+
+
+//static
+std::string LLAvatarPropertiesProcessor::accountType(const LLAvatarData* avatar_data)
+{
+ // If you have a special account, like M Linden ("El Jefe!")
+ // return an untranslated "special" string
+ if (!avatar_data->caption_text.empty())
+ {
+ return avatar_data->caption_text;
+ }
+ const char* const ACCT_TYPE[] = {
+ "AcctTypeResident",
+ "AcctTypeTrial",
+ "AcctTypeCharterMember",
+ "AcctTypeEmployee"
+ };
+ U8 caption_max = (U8)LL_ARRAY_SIZE(ACCT_TYPE)-1;
+ U8 caption_index = llclamp(avatar_data->caption_index, (U8)0, caption_max);
+ return LLTrans::getString(ACCT_TYPE[caption_index]);
+}
+
+//static
+std::string LLAvatarPropertiesProcessor::paymentInfo(const LLAvatarData* avatar_data)
+{
+ // Special accounts like M Linden don't have payment info revealed.
+ if (!avatar_data->caption_text.empty()) return "";
+
+ // Linden employees don't have payment info revealed
+ const S32 LINDEN_EMPLOYEE_INDEX = 3;
+ if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX) return "";
+
+ BOOL transacted = (avatar_data->flags & AVATAR_TRANSACTED);
+ BOOL identified = (avatar_data->flags & AVATAR_IDENTIFIED);
+ // Not currently getting set in dataserver/lldataavatar.cpp for privacy considerations
+ //BOOL age_verified = (avatar_data->flags & AVATAR_AGEVERIFIED);
+
+ const char* payment_text;
+ if(transacted)
+ {
+ payment_text = "PaymentInfoUsed";
+ }
+ else if (identified)
+ {
+ payment_text = "PaymentInfoOnFile";
+ }
+ else
+ {
+ payment_text = "NoPaymentInfoOnFile";
+ }
+ return LLTrans::getString(payment_text);
+}
+
+void LLAvatarPropertiesProcessor::processAvatarPropertiesReply(LLMessageSystem* msg, void**)
+{
+ LLAvatarData avatar_data;
+
+ msg->getUUIDFast( _PREHASH_AgentData, _PREHASH_AgentID, avatar_data.agent_id);
+ msg->getUUIDFast( _PREHASH_AgentData, _PREHASH_AvatarID, avatar_data.avatar_id);
+ msg->getUUIDFast( _PREHASH_PropertiesData, _PREHASH_ImageID, avatar_data.image_id);
+ msg->getUUIDFast( _PREHASH_PropertiesData, _PREHASH_FLImageID, avatar_data.fl_image_id);
+ msg->getUUIDFast( _PREHASH_PropertiesData, _PREHASH_PartnerID, avatar_data.partner_id);
+ msg->getStringFast( _PREHASH_PropertiesData, _PREHASH_AboutText, avatar_data.about_text);
+ msg->getStringFast( _PREHASH_PropertiesData, _PREHASH_FLAboutText, avatar_data.fl_about_text);
+ msg->getStringFast( _PREHASH_PropertiesData, _PREHASH_BornOn, avatar_data.born_on);
+ msg->getString( _PREHASH_PropertiesData, _PREHASH_ProfileURL, avatar_data.profile_url);
+ msg->getU32Fast( _PREHASH_PropertiesData, _PREHASH_Flags, avatar_data.flags);
+
+
+ avatar_data.caption_index = 0;
+
+ S32 charter_member_size = 0;
+ charter_member_size = msg->getSize(_PREHASH_PropertiesData, _PREHASH_CharterMember);
+ if(1 == charter_member_size)
+ {
+ msg->getBinaryData(_PREHASH_PropertiesData, _PREHASH_CharterMember, &avatar_data.caption_index, 1);
+ }
+ else if(1 < charter_member_size)
+ {
+ msg->getString(_PREHASH_PropertiesData, _PREHASH_CharterMember, avatar_data.caption_text);
+ }
+ LLAvatarPropertiesProcessor* self = getInstance();
+ // Request processed, no longer pending
+ self->removePendingRequest(avatar_data.avatar_id, APT_PROPERTIES);
+ self->notifyObservers(avatar_data.avatar_id,&avatar_data,APT_PROPERTIES);
+}
+
+void LLAvatarPropertiesProcessor::processAvatarInterestsReply(LLMessageSystem* msg, void**)
+{
+/*
+ AvatarInterestsReply is automatically sent by the server in response to the
+ AvatarPropertiesRequest sent when the panel is opened (in addition to the AvatarPropertiesReply message).
+ If the interests panel is no longer part of the design (?) we should just register the message
+ to a handler function that does nothing.
+ 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
+*/
+}
+
+void LLAvatarPropertiesProcessor::processAvatarClassifiedsReply(LLMessageSystem* msg, void**)
+{
+ LLAvatarClassifieds classifieds;
+
+ msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, classifieds.agent_id);
+ msg->getUUID(_PREHASH_AgentData, _PREHASH_TargetID, classifieds.target_id);
+
+ S32 block_count = msg->getNumberOfBlocks(_PREHASH_Data);
+
+ for(int n = 0; n < block_count; ++n)
+ {
+ LLAvatarClassifieds::classified_data data;
+
+ msg->getUUID(_PREHASH_Data, _PREHASH_ClassifiedID, data.classified_id, n);
+ msg->getString(_PREHASH_Data, _PREHASH_Name, data.name, n);
+
+ classifieds.classifieds_list.push_back(data);
+ }
+
+ LLAvatarPropertiesProcessor* self = getInstance();
+ // Request processed, no longer pending
+ self->removePendingRequest(classifieds.target_id, APT_CLASSIFIEDS);
+ self->notifyObservers(classifieds.target_id,&classifieds,APT_CLASSIFIEDS);
+}
+
+void LLAvatarPropertiesProcessor::processClassifiedInfoReply(LLMessageSystem* msg, void**)
+{
+ LLAvatarClassifiedInfo c_info;
+
+ msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, c_info.agent_id);
+
+ msg->getUUID(_PREHASH_Data, _PREHASH_ClassifiedID, c_info.classified_id);
+ msg->getUUID(_PREHASH_Data, _PREHASH_CreatorID, c_info.creator_id);
+ msg->getU32(_PREHASH_Data, _PREHASH_CreationDate, c_info.creation_date);
+ msg->getU32(_PREHASH_Data, _PREHASH_ExpirationDate, c_info.expiration_date);
+ msg->getU32(_PREHASH_Data, _PREHASH_Category, c_info.category);
+ msg->getString(_PREHASH_Data, _PREHASH_Name, c_info.name);
+ msg->getString(_PREHASH_Data, _PREHASH_Desc, c_info.description);
+ msg->getUUID(_PREHASH_Data, _PREHASH_ParcelID, c_info.parcel_id);
+ msg->getU32(_PREHASH_Data, _PREHASH_ParentEstate, c_info.parent_estate);
+ msg->getUUID(_PREHASH_Data, _PREHASH_SnapshotID, c_info.snapshot_id);
+ msg->getString(_PREHASH_Data, _PREHASH_SimName, c_info.sim_name);
+ msg->getVector3d(_PREHASH_Data, _PREHASH_PosGlobal, c_info.pos_global);
+ msg->getString(_PREHASH_Data, _PREHASH_ParcelName, c_info.parcel_name);
+ msg->getU8(_PREHASH_Data, _PREHASH_ClassifiedFlags, c_info.flags);
+ msg->getS32(_PREHASH_Data, _PREHASH_PriceForListing, c_info.price_for_listing);
+
+ LLAvatarPropertiesProcessor* self = getInstance();
+ // Request processed, no longer pending
+ self->removePendingRequest(c_info.creator_id, APT_CLASSIFIED_INFO);
+ self->notifyObservers(c_info.creator_id, &c_info, APT_CLASSIFIED_INFO);
+}
+
+
+void LLAvatarPropertiesProcessor::processAvatarNotesReply(LLMessageSystem* msg, void**)
+{
+ LLAvatarNotes avatar_notes;
+
+ msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, avatar_notes.agent_id);
+ msg->getUUID(_PREHASH_Data, _PREHASH_TargetID, avatar_notes.target_id);
+ msg->getString(_PREHASH_Data, _PREHASH_Notes, avatar_notes.notes);
+
+ LLAvatarPropertiesProcessor* self = getInstance();
+ // Request processed, no longer pending
+ self->removePendingRequest(avatar_notes.target_id, APT_NOTES);
+ self->notifyObservers(avatar_notes.target_id,&avatar_notes,APT_NOTES);
+}
+
+void LLAvatarPropertiesProcessor::processAvatarPicksReply(LLMessageSystem* msg, void**)
+{
+ LLAvatarPicks avatar_picks;
+ msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, avatar_picks.target_id);
+ msg->getUUID(_PREHASH_AgentData, _PREHASH_TargetID, avatar_picks.target_id);
+
+ S32 block_count = msg->getNumberOfBlocks(_PREHASH_Data);
+ for (int block = 0; block < block_count; ++block)
+ {
+ LLUUID pick_id;
+ std::string pick_name;
+
+ msg->getUUID(_PREHASH_Data, _PREHASH_PickID, pick_id, block);
+ msg->getString(_PREHASH_Data, _PREHASH_PickName, pick_name, block);
+
+ avatar_picks.picks_list.push_back(std::make_pair(pick_id,pick_name));
+ }
+ LLAvatarPropertiesProcessor* self = getInstance();
+ // Request processed, no longer pending
+ self->removePendingRequest(avatar_picks.target_id, APT_PICKS);
+ self->notifyObservers(avatar_picks.target_id,&avatar_picks,APT_PICKS);
+}
+
+void LLAvatarPropertiesProcessor::processPickInfoReply(LLMessageSystem* msg, void**)
+{
+ LLPickData pick_data;
+
+ // Extract the agent id and verify the message is for this
+ // client.
+ msg->getUUID(_PREHASH_AgentData, _PREHASH_AgentID, pick_data.agent_id );
+ msg->getUUID(_PREHASH_Data, _PREHASH_PickID, pick_data.pick_id);
+ msg->getUUID(_PREHASH_Data, _PREHASH_CreatorID, pick_data.creator_id);
+
+ // ** top_pick should be deleted, not being used anymore - angela
+ msg->getBOOL(_PREHASH_Data, _PREHASH_TopPick, pick_data.top_pick);
+ msg->getUUID(_PREHASH_Data, _PREHASH_ParcelID, pick_data.parcel_id);
+ msg->getString(_PREHASH_Data, _PREHASH_Name, pick_data.name);
+ msg->getString(_PREHASH_Data, _PREHASH_Desc, pick_data.desc);
+ msg->getUUID(_PREHASH_Data, _PREHASH_SnapshotID, pick_data.snapshot_id);
+
+ msg->getString(_PREHASH_Data, _PREHASH_User, pick_data.user_name);
+ msg->getString(_PREHASH_Data, _PREHASH_OriginalName, pick_data.original_name);
+ msg->getString(_PREHASH_Data, _PREHASH_SimName, pick_data.sim_name);
+ msg->getVector3d(_PREHASH_Data, _PREHASH_PosGlobal, pick_data.pos_global);
+
+ msg->getS32(_PREHASH_Data, _PREHASH_SortOrder, pick_data.sort_order);
+ msg->getBOOL(_PREHASH_Data, _PREHASH_Enabled, pick_data.enabled);
+
+ LLAvatarPropertiesProcessor* self = getInstance();
+ // don't need to remove pending request as we don't track pick info
+ self->notifyObservers(pick_data.creator_id, &pick_data, APT_PICK_INFO);
+}
+
+void LLAvatarPropertiesProcessor::processAvatarGroupsReply(LLMessageSystem* msg, void**)
+{
+ LLAvatarGroups avatar_groups;
+ msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, avatar_groups.agent_id );
+ msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AvatarID, avatar_groups.avatar_id );
+
+ S32 group_count = msg->getNumberOfBlocksFast(_PREHASH_GroupData);
+ for(S32 i = 0; i < group_count; ++i)
+ {
+ LLAvatarGroups::LLGroupData group_data;
+
+ msg->getU64( _PREHASH_GroupData, _PREHASH_GroupPowers, group_data.group_powers, i );
+ msg->getStringFast(_PREHASH_GroupData, _PREHASH_GroupTitle, group_data.group_title, i );
+ msg->getUUIDFast( _PREHASH_GroupData, _PREHASH_GroupID, group_data.group_id, i);
+ msg->getStringFast(_PREHASH_GroupData, _PREHASH_GroupName, group_data.group_name, i );
+ msg->getUUIDFast( _PREHASH_GroupData, _PREHASH_GroupInsigniaID, group_data.group_insignia_id, i );
+
+ avatar_groups.group_list.push_back(group_data);
+ }
+
+ LLAvatarPropertiesProcessor* self = getInstance();
+ self->removePendingRequest(avatar_groups.avatar_id, APT_GROUPS);
+ self->notifyObservers(avatar_groups.avatar_id,&avatar_groups,APT_GROUPS);
+}
+
+void LLAvatarPropertiesProcessor::notifyObservers(const LLUUID& id,void* data, EAvatarProcessorType type)
+{
+ // Copy the map (because observers may delete themselves when updated?)
+ LLAvatarPropertiesProcessor::observer_multimap_t observers = mObservers;
+
+ observer_multimap_t::iterator oi = observers.begin();
+ observer_multimap_t::iterator end = observers.end();
+ for (; oi != end; ++oi)
+ {
+ // only notify observers for the same agent, or if the observer
+ // didn't know the agent ID and passed a NULL id.
+ const LLUUID &agent_id = oi->first;
+ if (agent_id == id || agent_id.isNull())
+ {
+ oi->second->processProperties(data,type);
+ }
+ }
+}
+
+void LLAvatarPropertiesProcessor::sendFriendRights(const LLUUID& avatar_id, S32 rights)
+{
+ if(!avatar_id.isNull())
+ {
+ LLMessageSystem* msg = gMessageSystem;
+
+ // setup message header
+ msg->newMessageFast(_PREHASH_GrantUserRights);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUID(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
+
+ msg->nextBlockFast(_PREHASH_Rights);
+ msg->addUUID(_PREHASH_AgentRelated, avatar_id);
+ msg->addS32(_PREHASH_RelatedRights, rights);
+
+ gAgent.sendReliableMessage();
+ }
+}
+
+void LLAvatarPropertiesProcessor::sendNotes(const LLUUID& avatar_id, const std::string notes)
+{
+ if(!avatar_id.isNull())
+ {
+ LLMessageSystem* msg = gMessageSystem;
+
+ // setup message header
+ msg->newMessageFast(_PREHASH_AvatarNotesUpdate);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUID(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
+
+ msg->nextBlockFast(_PREHASH_Data);
+ msg->addUUID(_PREHASH_TargetID, avatar_id);
+ msg->addString(_PREHASH_Notes, notes);
+
+ gAgent.sendReliableMessage();
+ }
+}
+
+
+void LLAvatarPropertiesProcessor::sendPickDelete( const LLUUID& pick_id )
+{
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessage(_PREHASH_PickDelete);
+ msg->nextBlock(_PREHASH_AgentData);
+ msg->addUUID(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlock(_PREHASH_Data);
+ msg->addUUID(_PREHASH_PickID, pick_id);
+ gAgent.sendReliableMessage();
+
+ LLAgentPicksInfo::getInstance()->requestNumberOfPicks();
+ LLAgentPicksInfo::getInstance()->decrementNumberOfPicks();
+}
+
+void LLAvatarPropertiesProcessor::sendClassifiedDelete(const LLUUID& classified_id)
+{
+ LLMessageSystem* msg = gMessageSystem;
+
+ msg->newMessage(_PREHASH_ClassifiedDelete);
+
+ msg->nextBlock(_PREHASH_AgentData);
+ msg->addUUID(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
+
+ msg->nextBlock(_PREHASH_Data);
+ msg->addUUID(_PREHASH_ClassifiedID, classified_id);
+
+ gAgent.sendReliableMessage();
+}
+
+void LLAvatarPropertiesProcessor::sendPickInfoUpdate(const LLPickData* new_pick)
+{
+ if (!new_pick) return;
+
+ LLMessageSystem* msg = gMessageSystem;
+
+ msg->newMessage(_PREHASH_PickInfoUpdate);
+ msg->nextBlock(_PREHASH_AgentData);
+ msg->addUUID(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
+
+ msg->nextBlock(_PREHASH_Data);
+ msg->addUUID(_PREHASH_PickID, new_pick->pick_id);
+ msg->addUUID(_PREHASH_CreatorID, new_pick->creator_id);
+
+ //legacy var need to be deleted
+ msg->addBOOL(_PREHASH_TopPick, FALSE);
+
+ // fills in on simulator if null
+ msg->addUUID(_PREHASH_ParcelID, new_pick->parcel_id);
+ msg->addString(_PREHASH_Name, new_pick->name);
+ msg->addString(_PREHASH_Desc, new_pick->desc);
+ msg->addUUID(_PREHASH_SnapshotID, new_pick->snapshot_id);
+ msg->addVector3d(_PREHASH_PosGlobal, new_pick->pos_global);
+
+ // Only top picks have a sort order
+ msg->addS32(_PREHASH_SortOrder, 0);
+
+ msg->addBOOL(_PREHASH_Enabled, new_pick->enabled);
+ gAgent.sendReliableMessage();
+
+ LLAgentPicksInfo::getInstance()->requestNumberOfPicks();
+}
+
+void LLAvatarPropertiesProcessor::sendClassifiedInfoUpdate(const LLAvatarClassifiedInfo* c_data)
+{
+ if(!c_data)
+ {
+ return;
+ }
+
+ LLMessageSystem* msg = gMessageSystem;
+
+ msg->newMessage(_PREHASH_ClassifiedInfoUpdate);
+
+ msg->nextBlock(_PREHASH_AgentData);
+ msg->addUUID(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
+
+ msg->nextBlock(_PREHASH_Data);
+ msg->addUUID(_PREHASH_ClassifiedID, c_data->classified_id);
+ msg->addU32(_PREHASH_Category, c_data->category);
+ msg->addString(_PREHASH_Name, c_data->name);
+ msg->addString(_PREHASH_Desc, c_data->description);
+ msg->addUUID(_PREHASH_ParcelID, c_data->parcel_id);
+ msg->addU32(_PREHASH_ParentEstate, 0);
+ msg->addUUID(_PREHASH_SnapshotID, c_data->snapshot_id);
+ msg->addVector3d(_PREHASH_PosGlobal, c_data->pos_global);
+ msg->addU8(_PREHASH_ClassifiedFlags, c_data->flags);
+ msg->addS32(_PREHASH_PriceForListing, c_data->price_for_listing);
+
+ gAgent.sendReliableMessage();
+}
+
+void LLAvatarPropertiesProcessor::sendPickInfoRequest(const LLUUID& creator_id, const LLUUID& pick_id)
+{
+ // Must ask for a pick based on the creator id because
+ // the pick database is distributed to the inventory cluster. JC
+ std::vector<std::string> request_params;
+ request_params.push_back(creator_id.asString() );
+ request_params.push_back(pick_id.asString() );
+ send_generic_message("pickinforequest", request_params);
+}
+
+void LLAvatarPropertiesProcessor::sendClassifiedInfoRequest(const LLUUID& classified_id)
+{
+ LLMessageSystem* msg = gMessageSystem;
+
+ msg->newMessage(_PREHASH_ClassifiedInfoRequest);
+ msg->nextBlock(_PREHASH_AgentData);
+
+ msg->addUUID(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
+
+ msg->nextBlock(_PREHASH_Data);
+ msg->addUUID(_PREHASH_ClassifiedID, classified_id);
+
+ gAgent.sendReliableMessage();
+}
+
+bool LLAvatarPropertiesProcessor::isPendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type)
+{
+ timestamp_map_t::key_type key = std::make_pair(avatar_id, type);
+ timestamp_map_t::iterator it = mRequestTimestamps.find(key);
+
+ // Is this a new request?
+ if (it == mRequestTimestamps.end()) return false;
+
+ // We found a request, check if it has timed out
+ U32 now = time(NULL);
+ const U32 REQUEST_EXPIRE_SECS = 5;
+ U32 expires = it->second + REQUEST_EXPIRE_SECS;
+
+ // Request is still pending if it hasn't expired yet
+ // *NOTE: Expired requests will accumulate in this map, but they are rare,
+ // the data is small, and they will be updated if the same data is
+ // re-requested
+ return (now < expires);
+}
+
+void LLAvatarPropertiesProcessor::addPendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type)
+{
+ timestamp_map_t::key_type key = std::make_pair(avatar_id, type);
+ U32 now = time(NULL);
+ // Add or update existing (expired) request
+ mRequestTimestamps[ key ] = now;
+}
+
+void LLAvatarPropertiesProcessor::removePendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type)
+{
+ timestamp_map_t::key_type key = std::make_pair(avatar_id, type);
+ mRequestTimestamps.erase(key);
+}
diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h
new file mode 100644
index 0000000000..716c1b8065
--- /dev/null
+++ b/indra/newview/llavatarpropertiesprocessor.h
@@ -0,0 +1,284 @@
+/**
+ * @file llavatarpropertiesprocessor.h
+ * @brief LLAvatatIconCtrl base class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLAVATARPROPERTIESPROCESSOR_H
+#define LL_LLAVATARPROPERTIESPROCESSOR_H
+
+#include "lluuid.h"
+#include "llsingleton.h"
+#include "v3dmath.h" // LLVector3d
+#include <list>
+#include <map>
+
+/*
+*TODO Vadim: This needs some refactoring:
+- Remove EAvatarProcessorType in favor of separate observers, derived from a common parent (to get rid of void*).
+*/
+
+class LLMessageSystem;
+
+enum EAvatarProcessorType
+{
+ APT_PROPERTIES,
+ APT_NOTES,
+ APT_GROUPS,
+ APT_PICKS,
+ APT_PICK_INFO,
+ APT_TEXTURES,
+ APT_CLASSIFIEDS,
+ APT_CLASSIFIED_INFO
+};
+
+struct LLAvatarData
+{
+ LLUUID agent_id;
+ LLUUID avatar_id; //target id
+ LLUUID image_id;
+ LLUUID fl_image_id;
+ LLUUID partner_id;
+ std::string about_text;
+ std::string fl_about_text;
+ std::string born_on;
+ std::string profile_url;
+ U8 caption_index;
+ std::string caption_text;
+ U32 flags;
+ BOOL allow_publish;
+};
+
+struct LLAvatarPicks
+{
+ LLUUID agent_id;
+ LLUUID target_id; //target id
+
+ typedef std::pair<LLUUID,std::string> pick_data_t;
+ typedef std::list< pick_data_t> picks_list_t;
+ picks_list_t picks_list;
+};
+
+struct LLPickData
+{
+ LLUUID agent_id;
+ LLUUID pick_id;
+ LLUUID creator_id;
+ BOOL top_pick;
+ LLUUID parcel_id;
+ std::string name;
+ std::string desc;
+ LLUUID snapshot_id;
+ LLVector3d pos_global;
+ S32 sort_order;
+ BOOL enabled;
+
+ //used only in read requests
+ std::string user_name;
+ std::string original_name;
+ std::string sim_name;
+
+ //used only in write (update) requests
+ LLUUID session_id;
+
+};
+
+struct LLAvatarNotes
+{
+ LLUUID agent_id;
+ LLUUID target_id; //target id
+ std::string notes;
+};
+
+struct LLAvatarGroups
+{
+ LLUUID agent_id;
+ LLUUID avatar_id; //target id
+ BOOL list_in_profile;
+
+ struct LLGroupData;
+ typedef std::list<LLGroupData> group_list_t;
+
+ group_list_t group_list;
+
+ struct LLGroupData
+ {
+ U64 group_powers;
+ BOOL accept_notices;
+ std::string group_title;
+ LLUUID group_id;
+ std::string group_name;
+ LLUUID group_insignia_id;
+ };
+};
+
+struct LLAvatarClassifieds
+{
+ LLUUID agent_id;
+ LLUUID target_id;
+
+ struct classified_data;
+ typedef std::list<classified_data> classifieds_list_t;
+
+ classifieds_list_t classifieds_list;
+
+ struct classified_data
+ {
+ LLUUID classified_id;
+ std::string name;
+ };
+};
+
+struct LLAvatarClassifiedInfo
+{
+ LLUUID agent_id;
+ LLUUID classified_id;
+ LLUUID creator_id;
+ U32 creation_date;
+ U32 expiration_date;
+ U32 category;
+ std::string name;
+ std::string description;
+ LLUUID parcel_id;
+ U32 parent_estate;
+ LLUUID snapshot_id;
+ std::string sim_name;
+ LLVector3d pos_global;
+ std::string parcel_name;
+ U8 flags;
+ S32 price_for_listing;
+};
+
+class LLAvatarPropertiesObserver
+{
+public:
+ virtual ~LLAvatarPropertiesObserver() {}
+ virtual void processProperties(void* data, EAvatarProcessorType type) = 0;
+};
+
+class LLAvatarPropertiesProcessor
+ : public LLSingleton<LLAvatarPropertiesProcessor>
+{
+public:
+
+ LLAvatarPropertiesProcessor();
+ virtual ~LLAvatarPropertiesProcessor();
+
+ void addObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer);
+
+ void removeObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer);
+
+ // Request various types of avatar data. Duplicate requests will be
+ // suppressed while waiting for a response from the network.
+ void sendAvatarPropertiesRequest(const LLUUID& avatar_id);
+ void sendAvatarPicksRequest(const LLUUID& avatar_id);
+ void sendAvatarNotesRequest(const LLUUID& avatar_id);
+ void sendAvatarGroupsRequest(const LLUUID& avatar_id);
+ void sendAvatarTexturesRequest(const LLUUID& avatar_id);
+ void sendAvatarClassifiedsRequest(const LLUUID& avatar_id);
+
+ // Duplicate pick info requests are not suppressed.
+ void sendPickInfoRequest(const LLUUID& creator_id, const LLUUID& pick_id);
+
+ void sendClassifiedInfoRequest(const LLUUID& classified_id);
+
+ void sendAvatarPropertiesUpdate(const LLAvatarData* avatar_props);
+
+ void sendPickInfoUpdate(const LLPickData* new_pick);
+
+ void sendClassifiedInfoUpdate(const LLAvatarClassifiedInfo* c_data);
+
+ void sendFriendRights(const LLUUID& avatar_id, S32 rights);
+
+ void sendNotes(const LLUUID& avatar_id, const std::string notes);
+
+ void sendPickDelete(const LLUUID& pick_id);
+
+ void sendClassifiedDelete(const LLUUID& classified_id);
+
+ // 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);
+
+ // Returns translated, human readable string for payment info, such
+ // as "Payment Info on File" or "Payment Info Used".
+ // Used for profiles, inspectors.
+ static std::string paymentInfo(const LLAvatarData* avatar_data);
+
+ static void processAvatarPropertiesReply(LLMessageSystem* msg, void**);
+
+ static void processAvatarInterestsReply(LLMessageSystem* msg, void**);
+
+ static void processAvatarClassifiedsReply(LLMessageSystem* msg, void**);
+
+ static void processClassifiedInfoReply(LLMessageSystem* msg, void**);
+
+ static void processAvatarGroupsReply(LLMessageSystem* msg, void**);
+
+ static void processAvatarNotesReply(LLMessageSystem* msg, void**);
+
+ static void processAvatarPicksReply(LLMessageSystem* msg, void**);
+
+ static void processPickInfoReply(LLMessageSystem* msg, void**);
+
+protected:
+
+ void sendGenericRequest(const LLUUID& avatar_id, EAvatarProcessorType type, const std::string method);
+
+ void notifyObservers(const LLUUID& id,void* data, EAvatarProcessorType type);
+
+ // Is there a pending, not timed out, request for this avatar's data?
+ // Use this to suppress duplicate requests for data when a request is
+ // pending.
+ bool isPendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type);
+
+ // Call this when a request has been sent
+ void addPendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type);
+
+ // Call this when the reply to the request is received
+ void removePendingRequest(const LLUUID& avatar_id, EAvatarProcessorType type);
+
+ typedef void* (*processor_method_t)(LLMessageSystem*);
+ static processor_method_t getProcessor(EAvatarProcessorType type);
+
+protected:
+
+ typedef std::multimap<LLUUID, LLAvatarPropertiesObserver*> observer_multimap_t;
+
+ observer_multimap_t mObservers;
+
+ // Keep track of pending requests for data by avatar id and type.
+ // Maintain a timestamp for each request so a request that receives no reply
+ // does not block future requests forever.
+ // Map avatar_id+request_type -> U32 timestamp in seconds
+ typedef std::map< std::pair<LLUUID, EAvatarProcessorType>, U32> timestamp_map_t;
+ timestamp_map_t mRequestTimestamps;
+};
+
+#endif // LL_LLAVATARPROPERTIESPROCESSOR_H
diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp
new file mode 100644
index 0000000000..bd68d52868
--- /dev/null
+++ b/indra/newview/llbottomtray.cpp
@@ -0,0 +1,1122 @@
+/**
+ * @file llbottomtray.cpp
+ * @brief LLBottomTray class implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#define LLBOTTOMTRAY_CPP
+#include "llbottomtray.h"
+
+#include "llagent.h"
+#include "llchiclet.h"
+#include "llfloaterreg.h"
+#include "llflyoutbutton.h"
+#include "llimfloater.h" // for LLIMFloater
+#include "lllayoutstack.h"
+#include "llnearbychatbar.h"
+#include "llnotificationsutil.h"
+#include "llspeakbutton.h"
+#include "llsplitbutton.h"
+#include "llsyswellwindow.h"
+#include "llfloatercamera.h"
+#include "lltexteditor.h"
+#include "llnotifications.h"
+
+// Build time optimization, generate extern template once in .cpp file
+template class LLBottomTray* LLSingleton<class LLBottomTray>::getInstance();
+
+namespace
+{
+ const std::string& PANEL_CHICLET_NAME = "chiclet_list_panel";
+ const std::string& PANEL_CHATBAR_NAME = "chat_bar";
+ const std::string& PANEL_MOVEMENT_NAME = "movement_panel";
+ const std::string& PANEL_CAMERA_NAME = "cam_panel";
+ const std::string& PANEL_GESTURE_NAME = "gesture_panel";
+}
+
+LLBottomTray::LLBottomTray(const LLSD&)
+: mChicletPanel(NULL),
+ mSpeakPanel(NULL),
+ mSpeakBtn(NULL),
+ mNearbyChatBar(NULL),
+ mToolbarStack(NULL)
+, mMovementButton(NULL)
+, mResizeState(RS_NORESIZE)
+, mBottomTrayContextMenu(NULL)
+, mMovementPanel(NULL)
+, mCamPanel(NULL)
+, mSnapshotPanel(NULL)
+, mGesturePanel(NULL)
+, mCamButton(NULL)
+{
+ // Firstly add ourself to IMSession observers, so we catch session events
+ // before chiclets do that.
+ LLIMMgr::getInstance()->addSessionObserver(this);
+
+ mFactoryMap["chat_bar"] = LLCallbackMap(LLBottomTray::createNearbyChatBar, NULL);
+
+ LLUICtrlFactory::getInstance()->buildPanel(this,"panel_bottomtray.xml");
+
+ mChicletPanel = getChild<LLChicletPanel>("chiclet_list");
+
+ mChicletPanel->setChicletClickedCallback(boost::bind(&LLBottomTray::onChicletClick,this,_1));
+
+ LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("CameraPresets.ChangeView", boost::bind(&LLFloaterCamera::onClickCameraPresets, _2));
+
+ //this is to fix a crash that occurs because LLBottomTray is a singleton
+ //and thus is deleted at the end of the viewers lifetime, but to be cleanly
+ //destroyed LLBottomTray requires some subsystems that are long gone
+ //LLUI::getRootView()->addChild(this);
+
+ initStateProcessedObjectMap();
+
+ // Necessary for focus movement among child controls
+ setFocusRoot(TRUE);
+}
+
+LLBottomTray::~LLBottomTray()
+{
+ if (!LLSingleton<LLIMMgr>::destroyed())
+ {
+ LLIMMgr::getInstance()->removeSessionObserver(this);
+ }
+}
+
+void LLBottomTray::onChicletClick(LLUICtrl* ctrl)
+{
+ LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(ctrl);
+ if (chiclet)
+ {
+ // Until you can type into an IM Window and have a conversation,
+ // still show the old communicate window
+ //LLFloaterReg::showInstance("communicate", chiclet->getSessionId());
+
+ // Show after comm window so it is frontmost (and hence will not
+ // auto-hide)
+
+// this logic has been moved to LLIMChiclet::handleMouseDown
+// LLIMFloater::show(chiclet->getSessionId());
+// chiclet->setCounter(0);
+ }
+}
+
+// *TODO Vadim: why void* ?
+void* LLBottomTray::createNearbyChatBar(void* userdata)
+{
+ return new LLNearbyChatBar();
+}
+
+LLIMChiclet* LLBottomTray::createIMChiclet(const LLUUID& session_id)
+{
+ LLIMChiclet::EType im_chiclet_type = LLIMChiclet::getIMSessionType(session_id);
+
+ switch (im_chiclet_type)
+ {
+ case LLIMChiclet::TYPE_IM:
+ return getChicletPanel()->createChiclet<LLIMP2PChiclet>(session_id);
+ case LLIMChiclet::TYPE_GROUP:
+ return getChicletPanel()->createChiclet<LLIMGroupChiclet>(session_id);
+ case LLIMChiclet::TYPE_AD_HOC:
+ return getChicletPanel()->createChiclet<LLAdHocChiclet>(session_id);
+ case LLIMChiclet::TYPE_UNKNOWN:
+ break;
+ }
+
+ return NULL;
+}
+
+//virtual
+void LLBottomTray::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id)
+{
+ if (!getChicletPanel()) return;
+
+ LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id);
+ if (!session) return;
+
+ // no need to spawn chiclets for participants in P2P calls called through Avaline
+ if (session->isP2P() && session->isOtherParticipantAvaline()) return;
+
+ if (getChicletPanel()->findChiclet<LLChiclet>(session_id)) return;
+
+ LLIMChiclet* chiclet = createIMChiclet(session_id);
+ if(chiclet)
+ {
+ chiclet->setIMSessionName(name);
+ chiclet->setOtherParticipantId(other_participant_id);
+
+ LLIMFloater::onIMChicletCreated(session_id);
+
+ }
+ else
+ {
+ llerrs << "Could not create chiclet" << llendl;
+ }
+}
+
+//virtual
+void LLBottomTray::sessionRemoved(const LLUUID& session_id)
+{
+ if(getChicletPanel())
+ {
+ // IM floater should be closed when session removed and associated chiclet closed
+ LLIMFloater* iMfloater = LLFloaterReg::findTypedInstance<LLIMFloater>(
+ "impanel", session_id);
+ if (iMfloater != NULL)
+ {
+ iMfloater->closeFloater();
+ }
+
+ getChicletPanel()->removeChiclet(session_id);
+ }
+}
+
+void LLBottomTray::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id)
+{
+ //this is only needed in case of outgoing ad-hoc/group chat sessions
+ LLChicletPanel* chiclet_panel = getChicletPanel();
+ if (chiclet_panel)
+ {
+ //it should be ad-hoc im chiclet or group im chiclet
+ LLChiclet* chiclet = chiclet_panel->findChiclet<LLChiclet>(old_session_id);
+ if (chiclet) chiclet->setSessionId(new_session_id);
+ }
+}
+
+S32 LLBottomTray::getTotalUnreadIMCount()
+{
+ return getChicletPanel()->getTotalUnreadIMCount();
+}
+
+// virtual
+void LLBottomTray::onChange(EStatusType status, const std::string &channelURI, bool proximal)
+{
+ // Time it takes to connect to voice channel might be pretty long,
+ // so don't expect user login or STATUS_VOICE_ENABLED to be followed by STATUS_JOINED.
+ BOOL enable = FALSE;
+
+ switch (status)
+ {
+ // Do not add STATUS_VOICE_ENABLED because voice chat is
+ // inactive until STATUS_JOINED
+ case STATUS_JOINED:
+ enable = TRUE;
+ break;
+ default:
+ enable = FALSE;
+ break;
+ }
+
+ mSpeakBtn->setEnabled(enable);
+}
+
+//virtual
+void LLBottomTray::onFocusLost()
+{
+ if (gAgent.cameraMouselook())
+ {
+ setVisible(FALSE);
+ }
+}
+
+void LLBottomTray::savePanelsShape()
+{
+ mSavedShapeList.clear();
+ for (child_list_const_iter_t
+ child_it = mToolbarStack->beginChild(),
+ child_it_end = mToolbarStack->endChild();
+ child_it != child_it_end; ++child_it)
+ {
+ mSavedShapeList.push_back( (*child_it)->getRect() );
+ }
+}
+
+void LLBottomTray::restorePanelsShape()
+{
+ if (mSavedShapeList.size() != mToolbarStack->getChildCount())
+ return;
+ int i = 0;
+ for (child_list_const_iter_t
+ child_it = mToolbarStack->beginChild(),
+ child_it_end = mToolbarStack->endChild();
+ child_it != child_it_end; ++child_it)
+ {
+ (*child_it)->setShape(mSavedShapeList[i++]);
+ }
+}
+
+void LLBottomTray::onMouselookModeOut()
+{
+ // Apply the saved settings when we are not in mouselook mode, see EXT-3988.
+ {
+ setTrayButtonVisibleIfPossible (RS_BUTTON_GESTURES, gSavedSettings.getBOOL("ShowGestureButton"), false);
+ setTrayButtonVisibleIfPossible (RS_BUTTON_MOVEMENT, gSavedSettings.getBOOL("ShowMoveButton"), false);
+ setTrayButtonVisibleIfPossible (RS_BUTTON_CAMERA, gSavedSettings.getBOOL("ShowCameraButton"), false);
+ setTrayButtonVisibleIfPossible (RS_BUTTON_SNAPSHOT, gSavedSettings.getBOOL("ShowSnapshotButton"),false);
+ }
+ // HACK: To avoid usage the LLLayoutStack logic of resizing, we force the updateLayout
+ // and then restore children saved shapes. See EXT-4309.
+ BOOL saved_anim = mToolbarStack->getAnimate();
+ mToolbarStack->updatePanelAutoResize(PANEL_CHATBAR_NAME, FALSE);
+ // Disable animation to prevent layout updating in several frames.
+ mToolbarStack->setAnimate(FALSE);
+ // Force the updating of layout to reset panels collapse factor.
+ mToolbarStack->updateLayout();
+ // Restore animate state.
+ mToolbarStack->setAnimate(saved_anim);
+ // Restore saved shapes.
+ restorePanelsShape();
+}
+
+void LLBottomTray::onMouselookModeIn()
+{
+ savePanelsShape();
+ mToolbarStack->updatePanelAutoResize(PANEL_CHATBAR_NAME, TRUE);
+}
+
+//virtual
+// setVisible used instead of onVisibilityChange, since LLAgent calls it on entering/leaving mouselook mode.
+// If bottom tray is already visible in mouselook mode, then onVisibilityChange will not be called from setVisible(true),
+void LLBottomTray::setVisible(BOOL visible)
+{
+ LLPanel::setVisible(visible);
+
+ // *NOTE: we must check mToolbarStack against NULL because setVisible is called from the
+ // LLPanel::initFromParams BEFORE postBuild is called and child controls are not exist yet
+ if (NULL != mToolbarStack)
+ {
+ BOOL visibility = gAgent.cameraMouselook() ? false : true;
+
+ for ( child_list_const_iter_t child_it = mToolbarStack->getChildList()->begin();
+ child_it != mToolbarStack->getChildList()->end(); child_it++)
+ {
+ LLView* viewp = *child_it;
+ std::string name = viewp->getName();
+
+ // Chat bar and gesture button are shown even in mouselook mode.
+ // But the move, camera and snapshot buttons shouldn't be displayed. See EXT-3988.
+ if ("chat_bar" == name || "gesture_panel" == name || (visibility && ("movement_panel" == name || "cam_panel" == name || "snapshot_panel" == name)))
+ continue;
+ else
+ {
+ viewp->setVisible(visibility);
+ }
+ }
+ }
+
+ if(visible)
+ gFloaterView->setSnapOffsetBottom(getRect().getHeight());
+ else
+ gFloaterView->setSnapOffsetBottom(0);
+}
+
+void LLBottomTray::showBottomTrayContextMenu(S32 x, S32 y, MASK mask)
+{
+ // We should show BottomTrayContextMenu in last turn
+ if (mBottomTrayContextMenu && !LLMenuGL::sMenuContainer->getVisibleMenu())
+ {
+ //there are no other context menu (IM chiclet etc ), so we can show BottomTrayContextMenu
+
+ updateContextMenu(x, y, mask);
+ mBottomTrayContextMenu->buildDrawLabels();
+ mBottomTrayContextMenu->updateParent(LLMenuGL::sMenuContainer);
+ LLMenuGL::showPopup(this, mBottomTrayContextMenu, x, y);
+
+ }
+}
+
+void LLBottomTray::updateContextMenu(S32 x, S32 y, MASK mask)
+{
+ LLUICtrl* edit_box = mNearbyChatBar->getChild<LLUICtrl>("chat_box");
+
+ S32 local_x = x - mNearbyChatBar->getRect().mLeft - edit_box->getRect().mLeft;
+ S32 local_y = y - mNearbyChatBar->getRect().mBottom - edit_box->getRect().mBottom;
+
+ bool in_edit_box = edit_box->pointInView(local_x, local_y);
+
+ LLMenuItemGL* menu_item;
+ menu_item = mBottomTrayContextMenu->findChild<LLMenuItemGL>("NearbyChatBar_Cut");
+ if(menu_item)
+ menu_item->setVisible(in_edit_box);
+ menu_item = mBottomTrayContextMenu->findChild<LLMenuItemGL>("NearbyChatBar_Copy");
+ if(menu_item)
+ menu_item->setVisible(in_edit_box);
+ menu_item = mBottomTrayContextMenu->findChild<LLMenuItemGL>("NearbyChatBar_Paste");
+ if(menu_item)
+ menu_item->setVisible(in_edit_box);
+ menu_item = mBottomTrayContextMenu->findChild<LLMenuItemGL>("NearbyChatBar_Delete");
+ if(menu_item)
+ menu_item->setVisible(in_edit_box);
+ menu_item = mBottomTrayContextMenu->findChild<LLMenuItemGL>("NearbyChatBar_Select_All");
+ if(menu_item)
+ menu_item->setVisible(in_edit_box);
+}
+
+void LLBottomTray::showGestureButton(BOOL visible)
+{
+ setTrayButtonVisibleIfPossible(RS_BUTTON_GESTURES, visible);
+}
+
+void LLBottomTray::showMoveButton(BOOL visible)
+{
+ setTrayButtonVisibleIfPossible(RS_BUTTON_MOVEMENT, visible);
+}
+
+void LLBottomTray::showCameraButton(BOOL visible)
+{
+ setTrayButtonVisibleIfPossible(RS_BUTTON_CAMERA, visible);
+}
+
+void LLBottomTray::showSnapshotButton(BOOL visible)
+{
+ setTrayButtonVisibleIfPossible(RS_BUTTON_SNAPSHOT, visible);
+}
+
+BOOL LLBottomTray::postBuild()
+{
+
+ LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("NearbyChatBar.Action", boost::bind(&LLBottomTray::onContextMenuItemClicked, this, _2));
+ LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("NearbyChatBar.EnableMenuItem", boost::bind(&LLBottomTray::onContextMenuItemEnabled, this, _2));
+
+ mBottomTrayContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_bottomtray.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ gMenuHolder->addChild(mBottomTrayContextMenu);
+
+
+ mNearbyChatBar = getChild<LLNearbyChatBar>("chat_bar");
+ mToolbarStack = getChild<LLLayoutStack>("toolbar_stack");
+ mMovementPanel = getChild<LLPanel>("movement_panel");
+ mMovementButton = mMovementPanel->getChild<LLButton>("movement_btn");
+ mGesturePanel = getChild<LLPanel>("gesture_panel");
+ mCamPanel = getChild<LLPanel>("cam_panel");
+ mCamButton = mCamPanel->getChild<LLButton>("camera_btn");
+ mSnapshotPanel = getChild<LLPanel>("snapshot_panel");
+ setRightMouseDownCallback(boost::bind(&LLBottomTray::showBottomTrayContextMenu,this, _2, _3,_4));
+
+ mSpeakPanel = getChild<LLPanel>("speak_panel");
+ mSpeakBtn = getChild<LLSpeakButton>("talk");
+
+ // Speak button should be initially disabled because
+ // it takes some time between logging in to world and connecting to voice channel.
+ mSpeakBtn->setEnabled(FALSE);
+
+ // Localization tool doesn't understand custom buttons like <talk_button>
+ mSpeakBtn->setSpeakToolTip( getString("SpeakBtnToolTip") );
+ mSpeakBtn->setShowToolTip( getString("VoiceControlBtnToolTip") );
+
+ // Registering Chat Bar to receive Voice client status change notifications.
+ gVoiceClient->addObserver(this);
+
+ mObjectDefaultWidthMap[RS_BUTTON_GESTURES] = mGesturePanel->getRect().getWidth();
+ mObjectDefaultWidthMap[RS_BUTTON_MOVEMENT] = mMovementPanel->getRect().getWidth();
+ mObjectDefaultWidthMap[RS_BUTTON_CAMERA] = mCamPanel->getRect().getWidth();
+ mObjectDefaultWidthMap[RS_BUTTON_SPEAK] = mSpeakPanel->getRect().getWidth();
+
+ return TRUE;
+}
+
+bool LLBottomTray::onContextMenuItemEnabled(const LLSD& userdata)
+{
+ std::string item = userdata.asString();
+ LLLineEditor* edit_box = mNearbyChatBar->findChild<LLLineEditor>("chat_box");
+
+ if (item == "can_cut")
+ {
+ return edit_box->canCut();
+ }
+ else if (item == "can_copy")
+ {
+ return edit_box->canCopy();
+ }
+ else if (item == "can_paste")
+ {
+ return edit_box->canPaste();
+ }
+ else if (item == "can_delete")
+ {
+ return edit_box->canDoDelete();
+ }
+ else if (item == "can_select_all")
+ {
+ return edit_box->canSelectAll() && (edit_box->getLength()>0);
+ }
+ return true;
+}
+
+
+void LLBottomTray::onContextMenuItemClicked(const LLSD& userdata)
+{
+ std::string item = userdata.asString();
+ LLLineEditor* edit_box = mNearbyChatBar->findChild<LLLineEditor>("chat_box");
+
+ if (item == "cut")
+ {
+ edit_box->cut();
+ }
+ else if (item == "copy")
+ {
+ edit_box->copy();
+ }
+ else if (item == "paste")
+ {
+ edit_box->paste();
+ }
+ else if (item == "delete")
+ {
+ edit_box->doDelete();
+ }
+ else if (item == "select_all")
+ {
+ edit_box->selectAll();
+ }
+}
+
+void LLBottomTray::log(LLView* panel, const std::string& descr)
+{
+ if (NULL == panel) return;
+ LLView* layout = panel->getParent();
+ lldebugs << descr << ": "
+ << "panel: " << panel->getName()
+ << ", rect: " << panel->getRect()
+
+
+ << "layout: " << layout->getName()
+ << ", rect: " << layout->getRect()
+ << llendl
+ ;
+}
+
+void LLBottomTray::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ static S32 debug_calling_number = 0;
+ lldebugs << "**************************************** " << ++debug_calling_number << llendl;
+
+ S32 current_width = getRect().getWidth();
+ S32 delta_width = width - current_width;
+ lldebugs << "Reshaping: "
+ << ", width: " << width
+ << ", cur width: " << current_width
+ << ", delta_width: " << delta_width
+ << ", called_from_parent: " << called_from_parent
+ << llendl;
+
+ if (mNearbyChatBar) log(mNearbyChatBar, "before");
+ if (mChicletPanel) log(mChicletPanel, "before");
+
+ // stores width size on which bottom tray is less than width required by its children. EXT-991
+ static S32 extra_shrink_width = 0;
+ bool should_be_reshaped = true;
+
+ if (mChicletPanel && mToolbarStack && mNearbyChatBar)
+ {
+ mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, TRUE);
+
+ // bottom tray is narrowed
+ if (delta_width < 0)
+ {
+ if (extra_shrink_width > 0)
+ {
+ // is world rect was extra shrunk and decreasing again only update this value
+ // to delta_width negative
+ extra_shrink_width -= delta_width; // use "-=" because delta_width is negative
+ should_be_reshaped = false;
+ }
+ else
+ {
+ extra_shrink_width = processWidthDecreased(delta_width);
+
+ // increase new width to extra_shrink_width value to not reshape less than bottom tray minimum
+ width += extra_shrink_width;
+ }
+ }
+ // bottom tray is widen
+ else
+ {
+ if (extra_shrink_width > delta_width)
+ {
+ // Less than minimum width is more than increasing (delta_width)
+ // only reduce it value and make no reshape
+ extra_shrink_width -= delta_width;
+ should_be_reshaped = false;
+ }
+ else
+ {
+ if (extra_shrink_width > 0)
+ {
+ // If we have some extra shrink width let's reduce delta_width & width
+ delta_width -= extra_shrink_width;
+ width -= extra_shrink_width;
+ extra_shrink_width = 0;
+ }
+ processWidthIncreased(delta_width);
+ }
+ }
+ }
+
+ if (should_be_reshaped)
+ {
+ lldebugs << "Reshape all children with width: " << width << llendl;
+ LLPanel::reshape(width, height, called_from_parent);
+ }
+
+ if (mNearbyChatBar) log(mNearbyChatBar, "after");
+ if (mChicletPanel) log(mChicletPanel, "after");
+}
+
+S32 LLBottomTray::processWidthDecreased(S32 delta_width)
+{
+ bool still_should_be_processed = true;
+
+ const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth();
+ const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth();
+
+ if (chiclet_panel_width > chiclet_panel_min_width)
+ {
+ // we have some space to decrease chiclet panel
+ S32 panel_delta_min = chiclet_panel_width - chiclet_panel_min_width;
+
+ S32 delta_panel = llmin(-delta_width, panel_delta_min);
+
+ lldebugs << "delta_width: " << delta_width
+ << ", panel_delta_min: " << panel_delta_min
+ << ", delta_panel: " << delta_panel
+ << llendl;
+
+ // is chiclet panel width enough to process resizing?
+ delta_width += panel_delta_min;
+
+ still_should_be_processed = delta_width < 0;
+
+ mChicletPanel->getParent()->reshape(mChicletPanel->getParent()->getRect().getWidth() - delta_panel, mChicletPanel->getParent()->getRect().getHeight());
+ log(mChicletPanel, "after processing panel decreasing via chiclet panel");
+
+ lldebugs << "RS_CHICLET_PANEL"
+ << ", delta_width: " << delta_width
+ << llendl;
+ }
+
+ const S32 chatbar_panel_width = mNearbyChatBar->getRect().getWidth();
+ const S32 chatbar_panel_min_width = mNearbyChatBar->getMinWidth();
+ if (still_should_be_processed && chatbar_panel_width > chatbar_panel_min_width)
+ {
+ // we have some space to decrease chatbar panel
+ S32 panel_delta_min = chatbar_panel_width - chatbar_panel_min_width;
+
+ S32 delta_panel = llmin(-delta_width, panel_delta_min);
+
+ // whether chatbar panel width is enough to process resizing?
+ delta_width += panel_delta_min;
+
+ still_should_be_processed = delta_width < 0;
+
+ mNearbyChatBar->reshape(mNearbyChatBar->getRect().getWidth() - delta_panel, mNearbyChatBar->getRect().getHeight());
+
+ log(mChicletPanel, "after processing panel decreasing via nearby chatbar panel");
+
+ lldebugs << "RS_CHATBAR_INPUT"
+ << ", delta_panel: " << delta_panel
+ << ", delta_width: " << delta_width
+ << llendl;
+ }
+
+ S32 extra_shrink_width = 0;
+ S32 buttons_freed_width = 0;
+ if (still_should_be_processed)
+ {
+ processShrinkButtons(&delta_width, &buttons_freed_width);
+
+ if (delta_width < 0)
+ {
+ processHideButton(RS_BUTTON_SNAPSHOT, &delta_width, &buttons_freed_width);
+ }
+
+ if (delta_width < 0)
+ {
+ processHideButton(RS_BUTTON_CAMERA, &delta_width, &buttons_freed_width);
+ }
+
+ if (delta_width < 0)
+ {
+ processHideButton(RS_BUTTON_MOVEMENT, &delta_width, &buttons_freed_width);
+ }
+
+ if (delta_width < 0)
+ {
+ processHideButton(RS_BUTTON_GESTURES, &delta_width, &buttons_freed_width);
+ }
+
+ if (delta_width < 0)
+ {
+ extra_shrink_width = -delta_width;
+ llwarns << "There is no enough width to reshape all children: "
+ << extra_shrink_width << llendl;
+ }
+
+ if (buttons_freed_width > 0)
+ {
+ log(mNearbyChatBar, "before applying compensative width");
+ mNearbyChatBar->reshape(mNearbyChatBar->getRect().getWidth() + buttons_freed_width, mNearbyChatBar->getRect().getHeight() );
+ log(mNearbyChatBar, "after applying compensative width");
+ lldebugs << buttons_freed_width << llendl;
+ }
+ }
+
+ return extra_shrink_width;
+}
+
+void LLBottomTray::processWidthIncreased(S32 delta_width)
+{
+ if (delta_width <= 0) return;
+
+ const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth();
+ const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth();
+
+ const S32 chatbar_panel_width = mNearbyChatBar->getRect().getWidth();
+ const S32 chatbar_panel_min_width = mNearbyChatBar->getMinWidth();
+ const S32 chatbar_panel_max_width = mNearbyChatBar->getMaxWidth();
+
+ const S32 chatbar_available_shrink_width = chatbar_panel_width - chatbar_panel_min_width;
+ const S32 available_width_chiclet = chiclet_panel_width - chiclet_panel_min_width;
+
+ // how many room we have to show hidden buttons
+ S32 total_available_width = delta_width + chatbar_available_shrink_width + available_width_chiclet;
+
+ lldebugs << "Processing extending, available width:"
+ << ", chatbar - " << chatbar_available_shrink_width
+ << ", chiclets - " << available_width_chiclet
+ << ", total - " << total_available_width
+ << llendl;
+
+ S32 available_width = total_available_width;
+ if (available_width > 0)
+ {
+ processShowButton(RS_BUTTON_GESTURES, &available_width);
+ }
+
+ if (available_width > 0)
+ {
+ processShowButton(RS_BUTTON_MOVEMENT, &available_width);
+ }
+
+ if (available_width > 0)
+ {
+ processShowButton(RS_BUTTON_CAMERA, &available_width);
+ }
+
+ if (available_width > 0)
+ {
+ processShowButton(RS_BUTTON_SNAPSHOT, &available_width);
+ }
+
+ processExtendButtons(&available_width);
+
+ // if we have to show/extend some buttons but resized delta width is not enough...
+ S32 processed_width = total_available_width - available_width;
+ if (processed_width > delta_width)
+ {
+ // ... let's shrink nearby chat & chiclet panels
+ S32 required_to_process_width = processed_width;
+
+ // 1. use delta width of resizing
+ required_to_process_width -= delta_width;
+
+ // 2. use width available via decreasing of nearby chat panel
+ S32 chatbar_shrink_width = required_to_process_width;
+ if (chatbar_available_shrink_width < chatbar_shrink_width)
+ {
+ chatbar_shrink_width = chatbar_available_shrink_width;
+ }
+
+ log(mNearbyChatBar, "increase width: before applying compensative width");
+ mNearbyChatBar->reshape(mNearbyChatBar->getRect().getWidth() - chatbar_shrink_width, mNearbyChatBar->getRect().getHeight() );
+ if (mNearbyChatBar) log(mNearbyChatBar, "after applying compensative width");
+ lldebugs << chatbar_shrink_width << llendl;
+
+ // 3. use width available via decreasing of chiclet panel
+ required_to_process_width -= chatbar_shrink_width;
+
+ if (required_to_process_width > 0)
+ {
+ mChicletPanel->getParent()->reshape(mChicletPanel->getParent()->getRect().getWidth() - required_to_process_width, mChicletPanel->getParent()->getRect().getHeight());
+ log(mChicletPanel, "after applying compensative width for chiclets: ");
+ lldebugs << required_to_process_width << llendl;
+ }
+
+ }
+
+ // shown buttons take some space, rest should be processed by nearby chatbar & chiclet panels
+ delta_width -= processed_width;
+
+
+ // how many space can nearby chatbar take?
+ S32 chatbar_panel_width_ = mNearbyChatBar->getRect().getWidth();
+ if (delta_width > 0 && chatbar_panel_width_ < chatbar_panel_max_width)
+ {
+ S32 delta_panel_max = chatbar_panel_max_width - chatbar_panel_width_;
+ S32 delta_panel = llmin(delta_width, delta_panel_max);
+ lldebugs << "Unprocesed delta width: " << delta_width
+ << ", can be applied to chatbar: " << delta_panel_max
+ << ", will be applied: " << delta_panel
+ << llendl;
+
+ delta_width -= delta_panel_max;
+ mNearbyChatBar->reshape(chatbar_panel_width_ + delta_panel, mNearbyChatBar->getRect().getHeight());
+ log(mNearbyChatBar, "applied unprocessed delta width");
+ }
+}
+
+bool LLBottomTray::processShowButton(EResizeState shown_object_type, S32* available_width)
+{
+ lldebugs << "Trying to show object type: " << shown_object_type << llendl;
+
+ LLPanel* panel = mStateProcessedObjectMap[shown_object_type];
+ if (NULL == panel)
+ {
+ lldebugs << "There is no object to process for state: " << shown_object_type << llendl;
+ return false;
+ }
+ bool can_be_shown = canButtonBeShown(shown_object_type);
+ if (can_be_shown)
+ {
+ //validate if we have enough room to show this button
+ const S32 required_width = panel->getRect().getWidth();
+ can_be_shown = *available_width >= required_width;
+ if (can_be_shown)
+ {
+ *available_width -= required_width;
+
+ setTrayButtonVisible(shown_object_type, true);
+
+ lldebugs << "processed object type: " << shown_object_type
+ << ", rest available width: " << *available_width
+ << llendl;
+ mResizeState &= ~shown_object_type;
+ }
+ }
+ return can_be_shown;
+}
+
+void LLBottomTray::processHideButton(EResizeState processed_object_type, S32* required_width, S32* buttons_freed_width)
+{
+ lldebugs << "Trying to hide object type: " << processed_object_type << llendl;
+
+ LLPanel* panel = mStateProcessedObjectMap[processed_object_type];
+ if (NULL == panel)
+ {
+ lldebugs << "There is no object to process for state: " << processed_object_type << llendl;
+ return;
+ }
+
+ if (panel->getVisible())
+ {
+ *required_width += panel->getRect().getWidth();
+
+ if (*required_width > 0)
+ {
+ *buttons_freed_width += *required_width;
+ }
+
+ setTrayButtonVisible(processed_object_type, false);
+
+ mResizeState |= processed_object_type;
+
+ lldebugs << "processing object type: " << processed_object_type
+ << ", buttons_freed_width: " << *buttons_freed_width
+ << llendl;
+ }
+}
+
+void LLBottomTray::processShrinkButtons(S32* required_width, S32* buttons_freed_width)
+{
+ processShrinkButton(RS_BUTTON_CAMERA, required_width);
+
+ if (*required_width < 0)
+ {
+ processShrinkButton(RS_BUTTON_MOVEMENT, required_width);
+ }
+ if (*required_width < 0)
+ {
+ processShrinkButton(RS_BUTTON_GESTURES, required_width);
+ }
+ if (*required_width < 0)
+ {
+
+ S32 panel_min_width = 0;
+ std::string panel_name = mSpeakPanel->getName();
+ bool success = mToolbarStack->getPanelMinSize(panel_name, &panel_min_width, NULL);
+ if (!success)
+ {
+ lldebugs << "Panel was not found to get its min width: " << panel_name << llendl;
+ }
+ else
+ {
+ //
+ mSpeakBtn->setLabelVisible(false);
+ S32 panel_width = mSpeakPanel->getRect().getWidth();
+ S32 possible_shrink_width = panel_width - panel_min_width;
+
+ if (possible_shrink_width > 0)
+ {
+ mSpeakPanel->reshape(panel_width - possible_shrink_width, mSpeakPanel->getRect().getHeight());
+
+ *required_width += possible_shrink_width;
+
+ if (*required_width > 0)
+ {
+ *buttons_freed_width += *required_width;
+ }
+
+ lldebugs << "Shrunk panel: " << panel_name
+ << ", shrunk width: " << possible_shrink_width
+ << ", rest width to process: " << *required_width
+ << llendl;
+ }
+ }
+ }
+}
+
+void LLBottomTray::processShrinkButton(EResizeState processed_object_type, S32* required_width)
+{
+ LLPanel* panel = mStateProcessedObjectMap[processed_object_type];
+ if (NULL == panel)
+ {
+ lldebugs << "There is no object to process for type: " << processed_object_type << llendl;
+ return;
+ }
+
+ if (panel->getVisible())
+ {
+ S32 panel_width = panel->getRect().getWidth();
+ S32 panel_min_width = 0;
+ std::string panel_name = panel->getName();
+ bool success = mToolbarStack->getPanelMinSize(panel_name, &panel_min_width, NULL);
+ S32 possible_shrink_width = panel_width - panel_min_width;
+
+ if (!success)
+ {
+ lldebugs << "Panel was not found to get its min width: " << panel_name << llendl;
+ }
+ // we have some space to free by shrinking the button
+ else if (possible_shrink_width > 0)
+ {
+ // let calculate real width to shrink
+
+ // 1. apply all possible width
+ *required_width += possible_shrink_width;
+
+ // 2. it it is too much...
+ if (*required_width > 0)
+ {
+ // reduce applied shrunk width to the excessive value.
+ possible_shrink_width -= *required_width;
+ *required_width = 0;
+ }
+ panel->reshape(panel_width - possible_shrink_width, panel->getRect().getHeight());
+
+ lldebugs << "Shrunk panel: " << panel_name
+ << ", shrunk width: " << possible_shrink_width
+ << ", rest width to process: " << *required_width
+ << llendl;
+ }
+ }
+}
+
+
+void LLBottomTray::processExtendButtons(S32* available_width)
+{
+ // do not allow extending any buttons if we have some buttons hidden
+ if (mResizeState & RS_BUTTONS_CAN_BE_HIDDEN) return;
+
+ processExtendButton(RS_BUTTON_GESTURES, available_width);
+
+ if (*available_width > 0)
+ {
+ processExtendButton(RS_BUTTON_CAMERA, available_width);
+ }
+ if (*available_width > 0)
+ {
+ processExtendButton(RS_BUTTON_MOVEMENT, available_width);
+ }
+ if (*available_width > 0)
+ {
+ S32 panel_max_width = mObjectDefaultWidthMap[RS_BUTTON_SPEAK];
+ S32 panel_width = mSpeakPanel->getRect().getWidth();
+ S32 possible_extend_width = panel_max_width - panel_width;
+ if (possible_extend_width > 0 && possible_extend_width <= *available_width)
+ {
+ mSpeakBtn->setLabelVisible(true);
+ mSpeakPanel->reshape(panel_max_width, mSpeakPanel->getRect().getHeight());
+ log(mSpeakBtn, "speak button is extended");
+
+ *available_width -= possible_extend_width;
+
+ lldebugs << "Extending panel: " << mSpeakPanel->getName()
+ << ", extended width: " << possible_extend_width
+ << ", rest width to process: " << *available_width
+ << llendl;
+ }
+ }
+}
+
+void LLBottomTray::processExtendButton(EResizeState processed_object_type, S32* available_width)
+{
+ LLPanel* panel = mStateProcessedObjectMap[processed_object_type];
+ if (NULL == panel)
+ {
+ lldebugs << "There is no object to process for type: " << processed_object_type << llendl;
+ return;
+ }
+
+ if (!panel->getVisible()) return;
+
+ S32 panel_max_width = mObjectDefaultWidthMap[processed_object_type];
+ S32 panel_width = panel->getRect().getWidth();
+ S32 possible_extend_width = panel_max_width - panel_width;
+
+ if (possible_extend_width > 0)
+ {
+ // let calculate real width to extend
+
+ // 1. apply all possible width
+ *available_width -= possible_extend_width;
+
+ // 2. it it is too much...
+ if (*available_width < 0)
+ {
+ // reduce applied extended width to the excessive value.
+ possible_extend_width += *available_width;
+ *available_width = 0;
+ }
+ panel->reshape(panel_width + possible_extend_width, panel->getRect().getHeight());
+
+ lldebugs << "Extending panel: " << panel->getName()
+ << ", extended width: " << possible_extend_width
+ << ", rest width to process: " << *available_width
+ << llendl;
+ }
+}
+
+bool LLBottomTray::canButtonBeShown(EResizeState processed_object_type) const
+{
+ bool can_be_shown = mResizeState & processed_object_type;
+ if (can_be_shown)
+ {
+ static MASK MOVEMENT_PREVIOUS_BUTTONS_MASK = RS_BUTTON_GESTURES;
+ static MASK CAMERA_PREVIOUS_BUTTONS_MASK = RS_BUTTON_GESTURES | RS_BUTTON_MOVEMENT;
+ static MASK SNAPSHOT_PREVIOUS_BUTTONS_MASK = RS_BUTTON_GESTURES | RS_BUTTON_MOVEMENT | RS_BUTTON_CAMERA;
+
+ switch(processed_object_type)
+ {
+ case RS_BUTTON_GESTURES: // Gestures should be shown first
+ break;
+ case RS_BUTTON_MOVEMENT: // Move only if gesture is shown
+ can_be_shown = !(MOVEMENT_PREVIOUS_BUTTONS_MASK & mResizeState);
+ break;
+ case RS_BUTTON_CAMERA:
+ can_be_shown = !(CAMERA_PREVIOUS_BUTTONS_MASK & mResizeState);
+ break;
+ case RS_BUTTON_SNAPSHOT:
+ can_be_shown = !(SNAPSHOT_PREVIOUS_BUTTONS_MASK & mResizeState);
+ break;
+ default: // nothing to do here
+ break;
+ }
+ }
+ return can_be_shown;
+}
+
+void LLBottomTray::initStateProcessedObjectMap()
+{
+ mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_GESTURES, mGesturePanel));
+ mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_MOVEMENT, mMovementPanel));
+ mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_CAMERA, mCamPanel));
+ mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_SNAPSHOT, mSnapshotPanel));
+}
+
+void LLBottomTray::setTrayButtonVisible(EResizeState shown_object_type, bool visible)
+{
+ LLPanel* panel = mStateProcessedObjectMap[shown_object_type];
+ if (NULL == panel)
+ {
+ lldebugs << "There is no object to show for state: " << shown_object_type << llendl;
+ return;
+ }
+
+ panel->setVisible(visible);
+}
+
+void LLBottomTray::setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible, bool raise_notification)
+{
+ bool can_be_set = true;
+
+ if (visible)
+ {
+ LLPanel* panel = mStateProcessedObjectMap[shown_object_type];
+ if (NULL == panel)
+ {
+ lldebugs << "There is no object to process for state: " << shown_object_type << llendl;
+ return;
+ }
+
+ const S32 chatbar_panel_width = mNearbyChatBar->getRect().getWidth();
+ const S32 chatbar_panel_min_width = mNearbyChatBar->getMinWidth();
+
+ const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth();
+ const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth();
+
+ const S32 available_width = (chatbar_panel_width - chatbar_panel_min_width)
+ + (chiclet_panel_width - chiclet_panel_min_width);
+
+ const S32 required_width = panel->getRect().getWidth();
+ can_be_set = available_width >= required_width;
+ }
+
+ if (can_be_set)
+ {
+ setTrayButtonVisible(shown_object_type, visible);
+
+ // if we hide the button mark it NOT to show while future bottom tray extending
+ if (!visible)
+ {
+ mResizeState &= ~shown_object_type;
+ }
+ }
+ else
+ {
+ // mark this button to show it while future bottom tray extending
+ mResizeState |= shown_object_type;
+ if ( raise_notification )
+ LLNotificationsUtil::add("BottomTrayButtonCanNotBeShown",
+ LLSD(),
+ LLSD(),
+ LLNotificationFunctorRegistry::instance().DONOTHING);
+ }
+}
+
+//EOF
diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h
new file mode 100644
index 0000000000..562ee56912
--- /dev/null
+++ b/indra/newview/llbottomtray.h
@@ -0,0 +1,219 @@
+/**
+* @file llbottomtray.h
+* @brief LLBottomTray class header file
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#ifndef LL_LLBOTTOMPANEL_H
+#define LL_LLBOTTOMPANEL_H
+
+#include "llmenugl.h"
+
+#include "llpanel.h"
+#include "llimview.h"
+#include "llcombobox.h"
+
+class LLChicletPanel;
+class LLLineEditor;
+class LLLayoutStack;
+class LLNotificationChiclet;
+class LLSpeakButton;
+class LLNearbyChatBar;
+class LLIMChiclet;
+
+// Build time optimization, generate once in .cpp file
+#ifndef LLBOTTOMTRAY_CPP
+extern template class LLBottomTray* LLSingleton<class LLBottomTray>::getInstance();
+#endif
+
+class LLBottomTray
+ : public LLSingleton<LLBottomTray>
+ , public LLPanel
+ , public LLIMSessionObserver
+ , public LLVoiceClientStatusObserver
+{
+ LOG_CLASS(LLBottomTray);
+ friend class LLSingleton<LLBottomTray>;
+public:
+ ~LLBottomTray();
+
+ BOOL postBuild();
+
+ LLChicletPanel* getChicletPanel() {return mChicletPanel;}
+ LLNearbyChatBar* getNearbyChatBar() {return mNearbyChatBar;}
+
+ void onCommitGesture(LLUICtrl* ctrl);
+
+ // LLIMSessionObserver observe triggers
+ virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id);
+ virtual void sessionRemoved(const LLUUID& session_id);
+ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id);
+
+ S32 getTotalUnreadIMCount();
+
+ virtual void reshape(S32 width, S32 height, BOOL called_from_parent);
+
+ virtual void onFocusLost();
+ virtual void setVisible(BOOL visible);
+
+ // Implements LLVoiceClientStatusObserver::onChange() to enable the speak
+ // button when voice is available
+ /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
+
+ void showBottomTrayContextMenu(S32 x, S32 y, MASK mask);
+
+ void showGestureButton(BOOL visible);
+ void showMoveButton(BOOL visible);
+ void showCameraButton(BOOL visible);
+ void showSnapshotButton(BOOL visible);
+
+ void onMouselookModeIn();
+ void onMouselookModeOut();
+
+ /**
+ * Creates IM Chiclet based on session type (IM chat or Group chat)
+ */
+ LLIMChiclet* createIMChiclet(const LLUUID& session_id);
+
+private:
+ typedef enum e_resize_status_type
+ {
+ RS_NORESIZE = 0x0000
+ , RS_CHICLET_PANEL = 0x0001
+ , RS_CHATBAR_INPUT = 0x0002
+ , RS_BUTTON_SNAPSHOT = 0x0004
+ , RS_BUTTON_CAMERA = 0x0008
+ , RS_BUTTON_MOVEMENT = 0x0010
+ , RS_BUTTON_GESTURES = 0x0020
+ , RS_BUTTON_SPEAK = 0x0040
+
+ /**
+ * Specifies buttons which can be hidden when bottom tray is shrunk.
+ * They are: Gestures, Movement (Move), Camera (View), Snapshot
+ */
+ , RS_BUTTONS_CAN_BE_HIDDEN = RS_BUTTON_SNAPSHOT | RS_BUTTON_CAMERA | RS_BUTTON_MOVEMENT | RS_BUTTON_GESTURES
+ }EResizeState;
+
+ S32 processWidthDecreased(S32 delta_width);
+ void processWidthIncreased(S32 delta_width);
+ void log(LLView* panel, const std::string& descr);
+ bool processShowButton(EResizeState shown_object_type, S32* available_width);
+ void processHideButton(EResizeState processed_object_type, S32* required_width, S32* buttons_freed_width);
+
+ /**
+ * Shrinks shown buttons to reduce total taken space.
+ *
+ * @param - required_width - width which buttons can use to be shrunk. It is a negative value.
+ * It is increased on the value processed by buttons.
+ */
+ void processShrinkButtons(S32* required_width, S32* buttons_freed_width);
+ void processShrinkButton(EResizeState processed_object_type, S32* required_width);
+
+ /**
+ * Extends shown buttons to increase total taken space.
+ *
+ * @param - available_width - width which buttons can use to be extended. It is a positive value.
+ * It is decreased on the value processed by buttons.
+ */
+ void processExtendButtons(S32* available_width);
+ void processExtendButton(EResizeState processed_object_type, S32* available_width);
+
+ /**
+ * Determines if specified by type object can be shown. It should be hidden by shrink before.
+ *
+ * Processes buttons a such way to show buttons in constant order:
+ * - Gestures, Move, View, Snapshot
+ */
+ bool canButtonBeShown(EResizeState processed_object_type) const;
+ void initStateProcessedObjectMap();
+
+ /**
+ * Sets passed visibility to object specified by resize type.
+ */
+ void setTrayButtonVisible(EResizeState shown_object_type, bool visible);
+
+ /**
+ * Sets passed visibility to object specified by resize type if it is possible.
+ *
+ * If it is impossible to show required button due to there is no enough room in bottom tray
+ * it will no be shown. Is called via context menu commands.
+ * In this case Alert Dialog will be shown to notify user about that.
+ *
+ * Method also stores resize state to be processed while future bottom tray extending:
+ * - if hidden while resizing button should be hidden it will not be shown while extending;
+ * - if hidden via context menu button should be shown but there is no enough room for now
+ * it will be shown while extending.
+ */
+ void setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible, bool raise_notification = true);
+
+ /**
+ * Save and restore children shapes.
+ * Used to avoid the LLLayoutStack resizing logic between mouse look mode switching.
+ */
+ void savePanelsShape();
+ void restorePanelsShape();
+
+ MASK mResizeState;
+
+ typedef std::map<EResizeState, LLPanel*> state_object_map_t;
+ state_object_map_t mStateProcessedObjectMap;
+
+ typedef std::map<EResizeState, S32> state_object_width_map_t;
+ state_object_width_map_t mObjectDefaultWidthMap;
+
+ typedef std::vector<LLRect> shape_list_t;
+ shape_list_t mSavedShapeList;
+
+protected:
+
+ LLBottomTray(const LLSD& key = LLSD());
+
+ void onChicletClick(LLUICtrl* ctrl);
+
+ static void* createNearbyChatBar(void* userdata);
+
+ void updateContextMenu(S32 x, S32 y, MASK mask);
+ void onContextMenuItemClicked(const LLSD& userdata);
+ bool onContextMenuItemEnabled(const LLSD& userdata);
+
+ LLChicletPanel* mChicletPanel;
+ LLPanel* mSpeakPanel;
+ LLSpeakButton* mSpeakBtn;
+ LLNearbyChatBar* mNearbyChatBar;
+ LLLayoutStack* mToolbarStack;
+ LLMenuGL* mBottomTrayContextMenu;
+ LLPanel* mMovementPanel;
+ LLPanel* mCamPanel;
+ LLPanel* mSnapshotPanel;
+ LLPanel* mGesturePanel;
+ LLButton* mCamButton;
+ LLButton* mMovementButton;
+};
+
+#endif // LL_LLBOTTOMPANEL_H
diff --git a/indra/newview/llbreadcrumbview.cpp b/indra/newview/llbreadcrumbview.cpp
new file mode 100644
index 0000000000..342994ee30
--- /dev/null
+++ b/indra/newview/llbreadcrumbview.cpp
@@ -0,0 +1,37 @@
+/**
+ * @file llbreadcrumbview.cpp
+ * @brief UI widget for displaying position in a folder hierarchy and allowing
+ * the user to click on a location in the hierarchy.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "llviewerprecompiledheaders.h"
+
+#include "llbreadcrumbview.h"
+
+// TODO
diff --git a/indra/newview/llbreadcrumbview.h b/indra/newview/llbreadcrumbview.h
new file mode 100644
index 0000000000..ca6fbe7fb2
--- /dev/null
+++ b/indra/newview/llbreadcrumbview.h
@@ -0,0 +1,36 @@
+/**
+ * @file llbreadcrumbview.h
+ * @brief UI widget for displaying position in a folder hierarchy and allowing
+ * the user to click on a location in the hierarchy.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef LLBREADCRUMBVIEW_H
+#define LLBREADCRUMBVIEW_H
+
+#endif // LLBREADCRUMBVIEW_H
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
new file mode 100644
index 0000000000..d9df537e03
--- /dev/null
+++ b/indra/newview/llcallfloater.cpp
@@ -0,0 +1,744 @@
+/**
+ * @file llcallfloater.cpp
+ * @author Mike Antipov
+ * @brief Voice Control Panel in a Voice Chats (P2P, Group, Nearby...).
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llnotificationsutil.h"
+#include "lltrans.h"
+
+#include "llcallfloater.h"
+
+#include "llagent.h"
+#include "llagentdata.h" // for gAgentID
+#include "llavatariconctrl.h"
+#include "llavatarlist.h"
+#include "llbottomtray.h"
+#include "lldraghandle.h"
+#include "llimfloater.h"
+#include "llfloaterreg.h"
+#include "llparticipantlist.h"
+#include "llspeakers.h"
+#include "lltextutil.h"
+#include "lltransientfloatermgr.h"
+#include "llviewerwindow.h"
+#include "llvoicechannel.h"
+
+static void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids);
+void reshape_floater(LLCallFloater* floater, S32 delta_height);
+
+class LLNonAvatarCaller : public LLAvatarListItem
+{
+public:
+ LLNonAvatarCaller() : LLAvatarListItem(false)
+ {
+
+ }
+ BOOL 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;
+ }
+
+ void setName(const std::string& name)
+ {
+ const std::string& formatted_phone = LLTextUtil::formatPhoneNumber(name);
+ LLAvatarListItem::setName(formatted_phone);
+ }
+
+ void setSpeakerId(const LLUUID& id) { mSpeakingIndicator->setSpeakerId(id); }
+};
+
+
+static void* create_non_avatar_caller(void*)
+{
+ return new LLNonAvatarCaller;
+}
+
+LLVoiceChannel* LLCallFloater::sCurrentVoiceCanel = NULL;
+
+LLCallFloater::LLCallFloater(const LLSD& key)
+: LLTransientDockableFloater(NULL, false, key)
+, mSpeakerManager(NULL)
+, mParticipants(NULL)
+, mAvatarList(NULL)
+, mNonAvatarCaller(NULL)
+, mVoiceType(VC_LOCAL_CHAT)
+, mAgentPanel(NULL)
+, mSpeakingIndicator(NULL)
+, mIsModeratorMutedVoice(false)
+, mInitParticipantsVoiceState(false)
+{
+ static LLUICachedControl<S32> voice_left_remove_delay ("VoiceParticipantLeftRemoveDelay", 10);
+ mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLCallFloater::removeVoiceLeftParticipant, this, _1), voice_left_remove_delay);
+
+ mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL);
+ LLVoiceClient::getInstance()->addObserver(this);
+ LLTransientFloaterMgr::getInstance()->addControlView(this);
+}
+
+LLCallFloater::~LLCallFloater()
+{
+ resetVoiceRemoveTimers();
+ delete mSpeakerDelayRemover;
+
+ delete mParticipants;
+ mParticipants = NULL;
+
+ mAvatarListRefreshConnection.disconnect();
+ mVoiceChannelStateChangeConnection.disconnect();
+
+ // Don't use LLVoiceClient::getInstance() here
+ // singleton MAY have already been destroyed.
+ if(gVoiceClient)
+ {
+ gVoiceClient->removeObserver(this);
+ }
+ LLTransientFloaterMgr::getInstance()->removeControlView(this);
+}
+
+// virtual
+BOOL LLCallFloater::postBuild()
+{
+ LLTransientDockableFloater::postBuild();
+ mAvatarList = getChild<LLAvatarList>("speakers_list");
+ mAvatarListRefreshConnection = mAvatarList->setRefreshCompleteCallback(boost::bind(&LLCallFloater::onAvatarListRefreshed, this));
+
+ childSetAction("leave_call_btn", boost::bind(&LLCallFloater::leaveCall, this));
+
+ mNonAvatarCaller = getChild<LLNonAvatarCaller>("non_avatar_caller");
+ mNonAvatarCaller->setVisible(FALSE);
+
+ LLView *anchor_panel = LLBottomTray::getInstance()->getChild<LLView>("speak_flyout_btn");
+
+ setDockControl(new LLDockControl(
+ anchor_panel, this,
+ getDockTongue(), LLDockControl::TOP));
+
+ initAgentData();
+
+
+ connectToChannel(LLVoiceChannel::getCurrentVoiceChannel());
+
+ setIsChrome(true);
+ //chrome="true" hides floater caption
+ if (mDragHandle)
+ mDragHandle->setTitleVisible(TRUE);
+
+ return TRUE;
+}
+
+// virtual
+void LLCallFloater::onOpen(const LLSD& /*key*/)
+{
+}
+
+// virtual
+void LLCallFloater::draw()
+{
+ // we have to refresh participants to display ones not in voice as disabled.
+ // It should be done only when she joins or leaves voice chat.
+ // But seems that LLVoiceClientParticipantObserver is not enough to satisfy this requirement.
+ // *TODO: mantipov: remove from draw()
+
+ // NOTE: it looks like calling onChange() here is not necessary,
+ // but sometime it is not called properly from the observable object.
+ // Seems this is a problem somewhere in Voice Client (LLVoiceClient::participantAddedEvent)
+// onChange();
+
+ bool is_moderator_muted = gVoiceClient->getIsModeratorMuted(gAgentID);
+
+ if (mIsModeratorMutedVoice != is_moderator_muted)
+ {
+ setModeratorMutedVoice(is_moderator_muted);
+ }
+
+ // Need to resort the participant list if it's in sort by recent speaker order.
+ if (mParticipants)
+ mParticipants->updateRecentSpeakersOrder();
+
+ LLTransientDockableFloater::draw();
+}
+
+// virtual
+void LLCallFloater::onChange()
+{
+ if (NULL == mParticipants) return;
+
+ updateParticipantsVoiceState();
+
+ // Add newly joined participants.
+ std::vector<LLUUID> speakers_uuids;
+ get_voice_participants_uuids(speakers_uuids);
+ for (std::vector<LLUUID>::const_iterator it = speakers_uuids.begin(); it != speakers_uuids.end(); it++)
+ {
+ mParticipants->addAvatarIDExceptAgent(*it);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// PRIVATE SECTION
+//////////////////////////////////////////////////////////////////////////
+
+void LLCallFloater::leaveCall()
+{
+ LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
+ if (voice_channel)
+ {
+ voice_channel->deactivate();
+ }
+}
+
+void LLCallFloater::updateSession()
+{
+ LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
+ if (voice_channel)
+ {
+ lldebugs << "Current voice channel: " << voice_channel->getSessionID() << llendl;
+
+ if (mSpeakerManager && voice_channel->getSessionID() == mSpeakerManager->getSessionID())
+ {
+ lldebugs << "Speaker manager is already set for session: " << voice_channel->getSessionID() << llendl;
+ return;
+ }
+ else
+ {
+ mSpeakerManager = NULL;
+ }
+ }
+
+ const LLUUID& session_id = voice_channel->getSessionID();
+ lldebugs << "Set speaker manager for session: " << session_id << llendl;
+
+ LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id);
+ if (im_session)
+ {
+ mSpeakerManager = LLIMModel::getInstance()->getSpeakerManager(session_id);
+ switch (im_session->mType)
+ {
+ case IM_NOTHING_SPECIAL:
+ case IM_SESSION_P2P_INVITE:
+ mVoiceType = VC_PEER_TO_PEER;
+
+ if (!im_session->mOtherParticipantIsAvatar)
+ {
+ mVoiceType = VC_PEER_TO_PEER_AVALINE;
+ }
+ break;
+ case IM_SESSION_CONFERENCE_START:
+ case IM_SESSION_GROUP_START:
+ case IM_SESSION_INVITE:
+ if (gAgent.isInGroup(session_id))
+ {
+ mVoiceType = VC_GROUP_CHAT;
+ }
+ else
+ {
+ mVoiceType = VC_AD_HOC_CHAT;
+ }
+ break;
+ default:
+ llwarning("Failed to determine voice call IM type", 0);
+ mVoiceType = VC_GROUP_CHAT;
+ break;
+ }
+ }
+
+ if (NULL == mSpeakerManager)
+ {
+ // by default let show nearby chat participants
+ mSpeakerManager = LLLocalSpeakerMgr::getInstance();
+ lldebugs << "Set DEFAULT speaker manager" << llendl;
+ mVoiceType = VC_LOCAL_CHAT;
+ }
+
+ updateTitle();
+
+ //hide "Leave Call" button for nearby chat
+ bool is_local_chat = mVoiceType == VC_LOCAL_CHAT;
+ childSetVisible("leave_call_btn_panel", !is_local_chat);
+
+ refreshParticipantList();
+ updateAgentModeratorState();
+
+ //show floater for voice calls
+ if (!is_local_chat)
+ {
+ LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+ bool show_me = !(im_floater && im_floater->getVisible());
+ if (show_me)
+ {
+ setVisible(true);
+ }
+ }
+}
+
+void LLCallFloater::refreshParticipantList()
+{
+ bool non_avatar_caller = VC_PEER_TO_PEER_AVALINE == mVoiceType;
+
+ if (non_avatar_caller)
+ {
+ LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSpeakerManager->getSessionID());
+ mNonAvatarCaller->setSpeakerId(session->mOtherParticipantID);
+ mNonAvatarCaller->setName(session->mName);
+ }
+
+ mNonAvatarCaller->setVisible(non_avatar_caller);
+ mAvatarList->setVisible(!non_avatar_caller);
+
+ if (!non_avatar_caller)
+ {
+ mParticipants = new LLParticipantList(mSpeakerManager, mAvatarList, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT);
+ mParticipants->setValidateSpeakerCallback(boost::bind(&LLCallFloater::validateSpeaker, this, _1));
+
+ if (LLLocalSpeakerMgr::getInstance() == mSpeakerManager)
+ {
+ mAvatarList->setNoItemsCommentText(getString("no_one_near"));
+ }
+
+ // we have to made delayed initialization of voice state of participant list.
+ // it will be performed after first LLAvatarList refreshing in the onAvatarListRefreshed().
+ mInitParticipantsVoiceState = true;
+ }
+}
+
+void LLCallFloater::onAvatarListRefreshed()
+{
+ if (mInitParticipantsVoiceState)
+ {
+ initParticipantsVoiceState();
+ mInitParticipantsVoiceState = false;
+ }
+ else
+ {
+ updateParticipantsVoiceState();
+ }
+}
+
+// static
+void LLCallFloater::sOnCurrentChannelChanged(const LLUUID& /*session_id*/)
+{
+ LLVoiceChannel* channel = LLVoiceChannel::getCurrentVoiceChannel();
+
+ // *NOTE: if signal was sent for voice channel with LLVoiceChannel::STATE_NO_CHANNEL_INFO
+ // it sill be sent for the same channel again (when state is changed).
+ // So, lets ignore this call.
+ if (channel == sCurrentVoiceCanel) return;
+
+ LLCallFloater* call_floater = LLFloaterReg::getTypedInstance<LLCallFloater>("voice_controls");
+
+ call_floater->connectToChannel(channel);
+}
+
+void LLCallFloater::updateTitle()
+{
+ LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
+ std::string title;
+ switch (mVoiceType)
+ {
+ case VC_LOCAL_CHAT:
+ title = getString("title_nearby");
+ break;
+ case VC_PEER_TO_PEER:
+ case VC_PEER_TO_PEER_AVALINE:
+ {
+ title = voice_channel->getSessionName();
+
+ if (VC_PEER_TO_PEER_AVALINE == mVoiceType)
+ {
+ title = LLTextUtil::formatPhoneNumber(title);
+ }
+
+ LLStringUtil::format_map_t args;
+ args["[NAME]"] = title;
+ title = getString("title_peer_2_peer", args);
+ }
+ break;
+ case VC_AD_HOC_CHAT:
+ title = getString("title_adhoc");
+ break;
+ case VC_GROUP_CHAT:
+ {
+ LLStringUtil::format_map_t args;
+ args["[GROUP]"] = voice_channel->getSessionName();
+ title = getString("title_group", args);
+ }
+ break;
+ }
+
+ setTitle(title);
+}
+
+void LLCallFloater::initAgentData()
+{
+ mAgentPanel = getChild<LLPanel> ("my_panel");
+
+ if ( mAgentPanel )
+ {
+ mAgentPanel->childSetValue("user_icon", gAgentID);
+
+ std::string name;
+ gCacheName->getFullName(gAgentID, name);
+ mAgentPanel->childSetValue("user_text", name);
+
+ mSpeakingIndicator = mAgentPanel->getChild<LLOutputMonitorCtrl>("speaking_indicator");
+ mSpeakingIndicator->setSpeakerId(gAgentID);
+ }
+}
+
+void LLCallFloater::setModeratorMutedVoice(bool moderator_muted)
+{
+ mIsModeratorMutedVoice = moderator_muted;
+
+ if (moderator_muted)
+ {
+ LLNotificationsUtil::add("VoiceIsMutedByModerator");
+ }
+ mSpeakingIndicator->setIsMuted(moderator_muted);
+}
+
+void LLCallFloater::updateAgentModeratorState()
+{
+ std::string name;
+ gCacheName->getFullName(gAgentID, name);
+
+ if(gAgent.isInGroup(mSpeakerManager->getSessionID()))
+ {
+ // This method can be called when LLVoiceChannel.mState == STATE_NO_CHANNEL_INFO
+ // in this case there are no any speakers yet.
+ if (mSpeakerManager->findSpeaker(gAgentID))
+ {
+ // Agent is Moderator
+ if (mSpeakerManager->findSpeaker(gAgentID)->mIsModerator)
+
+ {
+ const std::string moderator_indicator(LLTrans::getString("IM_moderator_label"));
+ name += " " + moderator_indicator;
+ }
+ }
+ }
+ mAgentPanel->childSetValue("user_text", name);
+}
+
+static void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids)
+{
+ // Get a list of participants from VoiceClient
+ LLVoiceClient::participantMap *voice_map = gVoiceClient->getParticipantList();
+ if (voice_map)
+ {
+ for (LLVoiceClient::participantMap::const_iterator iter = voice_map->begin();
+ iter != voice_map->end(); ++iter)
+ {
+ LLUUID id = (*iter).second->mAvatarID;
+ speakers_uuids.push_back(id);
+ }
+ }
+}
+
+void LLCallFloater::initParticipantsVoiceState()
+{
+ // Set initial status for each participant in the list.
+ std::vector<LLPanel*> items;
+ mAvatarList->getItems(items);
+ std::vector<LLPanel*>::const_iterator
+ it = items.begin(),
+ it_end = items.end();
+
+
+ std::vector<LLUUID> speakers_uuids;
+ get_voice_participants_uuids(speakers_uuids);
+
+ for(; it != it_end; ++it)
+ {
+ LLAvatarListItem *item = dynamic_cast<LLAvatarListItem*>(*it);
+
+ if (!item) continue;
+
+ LLUUID speaker_id = item->getAvatarId();
+
+ std::vector<LLUUID>::const_iterator speaker_iter = std::find(speakers_uuids.begin(), speakers_uuids.end(), speaker_id);
+
+ // If an avatarID assigned to a panel is found in a speakers list
+ // obtained from VoiceClient we assign the JOINED status to the owner
+ // of this avatarID.
+ if (speaker_iter != speakers_uuids.end())
+ {
+ setState(item, STATE_JOINED);
+ }
+ else
+ {
+ LLPointer<LLSpeaker> speakerp = mSpeakerManager->findSpeaker(speaker_id);
+ // If someone has already left the call before, we create his
+ // avatar row panel with HAS_LEFT status and remove it after
+ // the timeout, otherwise we create a panel with INVITED status
+ if (speakerp.notNull() && speakerp.get()->mHasLeftCurrentCall)
+ {
+ setState(item, STATE_LEFT);
+ }
+ else
+ {
+ setState(item, STATE_INVITED);
+ }
+ }
+ }
+}
+
+void LLCallFloater::updateParticipantsVoiceState()
+{
+ std::vector<LLUUID> speakers_list;
+
+ // Get a list of participants from VoiceClient
+ std::vector<LLUUID> speakers_uuids;
+ get_voice_participants_uuids(speakers_uuids);
+
+ // Updating the status for each participant already in list.
+ std::vector<LLPanel*> items;
+ mAvatarList->getItems(items);
+ std::vector<LLPanel*>::const_iterator
+ it = items.begin(),
+ it_end = items.end();
+
+ for(; it != it_end; ++it)
+ {
+ LLAvatarListItem *item = dynamic_cast<LLAvatarListItem*>(*it);
+ if (!item) continue;
+
+ const LLUUID participant_id = item->getAvatarId();
+ bool found = false;
+
+ std::vector<LLUUID>::iterator speakers_iter = std::find(speakers_uuids.begin(), speakers_uuids.end(), participant_id);
+
+ lldebugs << "processing speaker: " << item->getAvatarName() << ", " << item->getAvatarId() << llendl;
+
+ // If an avatarID assigned to a panel is found in a speakers list
+ // obtained from VoiceClient we assign the JOINED status to the owner
+ // of this avatarID.
+ if (speakers_iter != speakers_uuids.end())
+ {
+ setState(item, STATE_JOINED);
+
+ LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(participant_id);
+ if (speaker.isNull())
+ continue;
+ speaker->mHasLeftCurrentCall = FALSE;
+
+ speakers_uuids.erase(speakers_iter);
+ found = true;
+ }
+
+ if (!found)
+ {
+ // If an avatarID is not found in a speakers list from VoiceClient and
+ // a panel with this ID has a JOINED status this means that this person
+ // HAS LEFT the call.
+ if ((getState(participant_id) == STATE_JOINED))
+ {
+ setState(item, STATE_LEFT);
+
+ LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(item->getAvatarId());
+ if (speaker.isNull())
+ {
+ continue;
+ }
+
+ speaker->mHasLeftCurrentCall = TRUE;
+ }
+ // If an avatarID is not found in a speakers list from VoiceClient and
+ // a panel with this ID has a LEFT status this means that this person
+ // HAS ENTERED session but it is not in voice chat yet. So, set INVITED status
+ else if ((getState(participant_id) != STATE_LEFT))
+ {
+ setState(item, STATE_INVITED);
+ }
+ else
+ {
+ llwarns << "Unsupported (" << getState(participant_id) << ") state: " << item->getAvatarName() << llendl;
+ }
+ }
+ }
+}
+
+void LLCallFloater::setState(LLAvatarListItem* item, ESpeakerState state)
+{
+ // *HACK: mantipov: sometimes such situation is possible while switching to voice channel:
+/*
+ - voice channel is switched to the one user is joining
+ - participant list is initialized with voice states: agent is in voice
+ - than such log messages were found (with agent UUID)
+ - LLVivoxProtocolParser::process_impl: parsing: <Response requestId="22" action="Session.MediaDisconnect.1"><ReturnCode>0</ReturnCode><Results><StatusCode>0</StatusCode><StatusString /></Results><InputXml><Request requestId="22" action="Session.MediaDisconnect.1"><SessionGroupHandle>9</SessionGroupHandle><SessionHandle>12</SessionHandle><Media>Audio</Media></Request></InputXml></Response>
+ - LLVoiceClient::sessionState::removeParticipant: participant "sip:x2pwNkMbpR_mK4rtB_awASA==@bhr.vivox.com" (da9c0d90-c6e9-47f9-8ae2-bb41fdac0048) removed.
+ - and than while updating participants voice states agent is marked as HAS LEFT
+ - next updating of LLVoiceClient state makes agent JOINED
+ So, lets skip HAS LEFT state for agent's avatar
+*/
+ if (STATE_LEFT == state && item->getAvatarId() == gAgentID) return;
+
+ setState(item->getAvatarId(), state);
+
+ switch (state)
+ {
+ case STATE_INVITED:
+ item->setState(LLAvatarListItem::IS_VOICE_INVITED);
+ break;
+ case STATE_JOINED:
+ removeVoiceRemoveTimer(item->getAvatarId());
+ item->setState(LLAvatarListItem::IS_VOICE_JOINED);
+ break;
+ case STATE_LEFT:
+ {
+ setVoiceRemoveTimer(item->getAvatarId());
+ item->setState(LLAvatarListItem::IS_VOICE_LEFT);
+ }
+ break;
+ default:
+ llwarns << "Unrecognized avatar panel state (" << state << ")" << llendl;
+ break;
+ }
+}
+
+void LLCallFloater::setVoiceRemoveTimer(const LLUUID& voice_speaker_id)
+{
+ mSpeakerDelayRemover->setActionTimer(voice_speaker_id);
+}
+
+bool LLCallFloater::removeVoiceLeftParticipant(const LLUUID& voice_speaker_id)
+{
+ LLAvatarList::uuid_vector_t& speaker_uuids = mAvatarList->getIDs();
+ LLAvatarList::uuid_vector_t::iterator pos = std::find(speaker_uuids.begin(), speaker_uuids.end(), voice_speaker_id);
+ if(pos != speaker_uuids.end())
+ {
+ speaker_uuids.erase(pos);
+ mAvatarList->setDirty();
+ }
+
+ return false;
+}
+
+
+void LLCallFloater::resetVoiceRemoveTimers()
+{
+ mSpeakerDelayRemover->removeAllTimers();
+}
+
+void LLCallFloater::removeVoiceRemoveTimer(const LLUUID& voice_speaker_id)
+{
+ mSpeakerDelayRemover->unsetActionTimer(voice_speaker_id);
+}
+
+bool LLCallFloater::validateSpeaker(const LLUUID& speaker_id)
+{
+ bool is_valid = true;
+ switch (mVoiceType)
+ {
+ case VC_LOCAL_CHAT:
+ {
+ // A nearby chat speaker is considered valid it it's known to LLVoiceClient (i.e. has enabled voice).
+ std::vector<LLUUID> speakers;
+ get_voice_participants_uuids(speakers);
+ is_valid = std::find(speakers.begin(), speakers.end(), speaker_id) != speakers.end();
+ }
+ break;
+ case VC_GROUP_CHAT:
+ // if participant had left this call before do not allow add her again. See EXT-4216.
+ // but if she Join she will be added into the list from the LLCallFloater::onChange()
+ is_valid = STATE_LEFT != getState(speaker_id);
+ break;
+ default:
+ // do nothing. required for Linux build
+ break;
+ }
+
+ return is_valid;
+}
+
+void LLCallFloater::connectToChannel(LLVoiceChannel* channel)
+{
+ mVoiceChannelStateChangeConnection.disconnect();
+
+ sCurrentVoiceCanel = channel;
+
+ mVoiceChannelStateChangeConnection = sCurrentVoiceCanel->setStateChangedCallback(boost::bind(&LLCallFloater::onVoiceChannelStateChanged, this, _1, _2));
+
+ updateState(channel->getState());
+}
+
+void LLCallFloater::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)
+{
+ updateState(new_state);
+}
+
+void LLCallFloater::updateState(const LLVoiceChannel::EState& new_state)
+{
+ LL_DEBUGS("Voice") << "Updating state: " << new_state << ", session name: " << sCurrentVoiceCanel->getSessionName() << LL_ENDL;
+ if (LLVoiceChannel::STATE_CONNECTED == new_state)
+ {
+ updateSession();
+ }
+ else
+ {
+ reset();
+ }
+}
+
+void LLCallFloater::reset()
+{
+ // lets forget states from the previous session
+ // for timers...
+ resetVoiceRemoveTimers();
+
+ // ...and for speaker state
+ mSpeakerStateMap.clear();
+
+ delete mParticipants;
+ mParticipants = NULL;
+ mAvatarList->clear();
+
+ // update floater to show Loading while waiting for data.
+ mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData"));
+ mAvatarList->setVisible(TRUE);
+ mNonAvatarCaller->setVisible(FALSE);
+
+ mSpeakerManager = NULL;
+}
+
+//EOF
diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h
new file mode 100644
index 0000000000..eded3a426b
--- /dev/null
+++ b/indra/newview/llcallfloater.h
@@ -0,0 +1,264 @@
+/**
+ * @file llcallfloater.h
+ * @author Mike Antipov
+ * @brief Voice Control Panel in a Voice Chats (P2P, Group, Nearby...).
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLCALLFLOATER_H
+#define LL_LLCALLFLOATER_H
+
+#include "lltransientdockablefloater.h"
+#include "llvoicechannel.h"
+#include "llvoiceclient.h"
+
+class LLAvatarList;
+class LLAvatarListItem;
+class LLNonAvatarCaller;
+class LLOutputMonitorCtrl;
+class LLParticipantList;
+class LLSpeakerMgr;
+class LLSpeakersDelayActionsStorage;
+
+/**
+ * The Voice Control Panel is an ambient window summoned by clicking the flyout chevron on the Speak button.
+ * It can be torn-off and freely positioned onscreen.
+ *
+ * When the Resident is engaged in Nearby Voice Chat, the Voice Control Panel provides control over
+ * the Resident's own microphone input volume, the audible volume of each of the other participants,
+ * the Resident's own Voice Morphing settings (if she has subscribed to enable the feature), and Voice Recording.
+ *
+ * When the Resident is engaged in any chat except Nearby Chat, the Voice Control Panel also provides an
+ * 'Leave Call' button to allow the Resident to leave that voice channel.
+ */
+class LLCallFloater : public LLTransientDockableFloater, LLVoiceClientParticipantObserver
+{
+public:
+
+ LOG_CLASS(LLCallFloater);
+
+ LLCallFloater(const LLSD& key);
+ ~LLCallFloater();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ void draw();
+
+ /**
+ * Is called by LLVoiceClient::notifyParticipantObservers when voice participant list is changed.
+ *
+ * Refreshes list to display participants not in voice as disabled.
+ */
+ /*virtual*/ void onChange();
+
+ static void sOnCurrentChannelChanged(const LLUUID& session_id);
+
+private:
+ typedef enum e_voice_controls_type
+ {
+ VC_LOCAL_CHAT,
+ VC_GROUP_CHAT,
+ VC_AD_HOC_CHAT,
+ VC_PEER_TO_PEER,
+ VC_PEER_TO_PEER_AVALINE
+ }EVoiceControls;
+
+ typedef enum e_speaker_state
+ {
+ STATE_UNKNOWN,
+ STATE_INVITED,
+ STATE_JOINED,
+ STATE_LEFT,
+ } ESpeakerState;
+
+ typedef std::map<LLUUID, ESpeakerState> speaker_state_map_t;
+
+ void leaveCall();
+
+ /**
+ * Updates mSpeakerManager and list according to current Voice Channel
+ *
+ * It compares mSpeakerManager & current Voice Channel session IDs.
+ * If they are different gets Speaker manager related to current channel and updates channel participant list.
+ */
+ void updateSession();
+
+ /**
+ * Refreshes participant list according to current Voice Channel
+ */
+ void refreshParticipantList();
+
+ /**
+ * Handles event on avatar list is refreshed after it was marked dirty.
+ *
+ * It sets initial participants voice states (once after the first refreshing)
+ * and updates voice states each time anybody is joined/left voice chat in session.
+ */
+ void onAvatarListRefreshed();
+
+
+ void updateTitle();
+ void initAgentData();
+ void setModeratorMutedVoice(bool moderator_muted);
+ void updateAgentModeratorState();
+
+ /**
+ * Sets initial participants voice states in avatar list (Invited, Joined, Has Left).
+ *
+ * @see refreshParticipantList()
+ * @see onAvatarListRefreshed()
+ * @see mInitParticipantsVoiceState
+ */
+ void initParticipantsVoiceState();
+
+ /**
+ * Updates participants voice states in avatar list (Invited, Joined, Has Left).
+ *
+ * @see onAvatarListRefreshed()
+ * @see onChanged()
+ */
+ void updateParticipantsVoiceState();
+
+ void setState(LLAvatarListItem* item, ESpeakerState state);
+ void setState(const LLUUID& speaker_id, ESpeakerState state)
+ {
+ lldebugs << "Storing state: " << speaker_id << ", " << state << llendl;
+ mSpeakerStateMap[speaker_id] = state;
+ }
+
+ ESpeakerState getState(const LLUUID& speaker_id)
+ {
+ lldebugs << "Getting state: " << speaker_id << ", " << mSpeakerStateMap[speaker_id] << llendl;
+
+ return mSpeakerStateMap[speaker_id];
+ }
+
+ /**
+ * Instantiates new LLAvatarListItemRemoveTimer and adds it into the map if it is not already created.
+ *
+ * @param voice_speaker_id LLUUID of Avatar List item to be removed from the list when timer expires.
+ */
+ void setVoiceRemoveTimer(const LLUUID& voice_speaker_id);
+
+ /**
+ * Removes specified by UUID Avatar List item.
+ *
+ * @param voice_speaker_id LLUUID of Avatar List item to be removed from the list.
+ */
+ bool removeVoiceLeftParticipant(const LLUUID& voice_speaker_id);
+
+ /**
+ * Deletes all timers from the list to prevent started timers from ticking after destruction
+ * and after switching on another voice channel.
+ */
+ void resetVoiceRemoveTimers();
+
+ /**
+ * Removes specified by UUID timer from the map.
+ *
+ * @param voice_speaker_id LLUUID of Avatar List item whose timer should be removed from the map.
+ */
+ void removeVoiceRemoveTimer(const LLUUID& voice_speaker_id);
+
+ /**
+ * Called by LLParticipantList before adding a speaker to the participant list.
+ *
+ * If false is returned, the speaker will not be added to the list.
+ *
+ * @param speaker_id Speaker to validate.
+ * @return true if this is a valid speaker, false otherwise.
+ */
+ bool validateSpeaker(const LLUUID& speaker_id);
+
+ /**
+ * Connects to passed channel to be updated according to channel's voice states.
+ */
+ void connectToChannel(LLVoiceChannel* channel);
+
+ /**
+ * Callback to process changing of voice channel's states.
+ */
+ void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state);
+
+ /**
+ * Updates floater according to passed channel's voice state.
+ */
+ void updateState(const LLVoiceChannel::EState& new_state);
+
+ /**
+ * Resets floater to be ready to show voice participants.
+ *
+ * Clears all data from the latest voice session.
+ */
+ void reset();
+
+private:
+ speaker_state_map_t mSpeakerStateMap;
+ LLSpeakerMgr* mSpeakerManager;
+ LLParticipantList* mParticipants;
+ LLAvatarList* mAvatarList;
+ LLNonAvatarCaller* mNonAvatarCaller;
+ EVoiceControls mVoiceType;
+ LLPanel* mAgentPanel;
+ LLOutputMonitorCtrl* mSpeakingIndicator;
+ bool mIsModeratorMutedVoice;
+
+ /**
+ * Flag indicated that participants voice states should be initialized.
+ *
+ * It is used due to Avatar List has delayed refreshing after it content is changed.
+ * Real initializing is performed when Avatar List is first time refreshed.
+ *
+ * @see onAvatarListRefreshed()
+ * @see initParticipantsVoiceState()
+ */
+ bool mInitParticipantsVoiceState;
+
+ boost::signals2::connection mAvatarListRefreshConnection;
+
+
+ /**
+ * time out speakers when they are not part of current session
+ */
+ LLSpeakersDelayActionsStorage* mSpeakerDelayRemover;
+
+ /**
+ * Stores reference to current voice channel.
+ *
+ * Is used to ignore voice channel changed callback for the same channel.
+ *
+ * @see sOnCurrentChannelChanged()
+ */
+ static LLVoiceChannel* sCurrentVoiceCanel;
+ boost::signals2::connection mVoiceChannelStateChangeConnection;
+};
+
+
+#endif //LL_LLCALLFLOATER_H
+
diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp
index db28c7ad38..d988770f90 100644
--- a/indra/newview/llcallingcard.cpp
+++ b/indra/newview/llcallingcard.cpp
@@ -51,9 +51,10 @@
#include "llagent.h"
#include "llbutton.h"
-//#include "llinventory.h"
+#include "llinventoryobserver.h"
#include "llinventorymodel.h"
-#include "llnotify.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
#include "llresmgr.h"
#include "llimview.h"
#include "llviewercontrol.h"
@@ -61,8 +62,6 @@
#include "llviewerobjectlist.h"
#include "llviewerwindow.h"
#include "llvoavatar.h"
-#include "llimview.h"
-#include "llimpanel.h"
///----------------------------------------------------------------------------
/// Local function declarations, constants, enums, and typedefs
@@ -95,29 +94,8 @@ const F32 OFFLINE_SECONDS = FIND_FREQUENCY + 8.0f;
// static
LLAvatarTracker LLAvatarTracker::sInstance;
-/*
-class LLAvatarTrackerInventoryObserver : public LLInventoryObserver
-{
-public:
- LLAvatarTrackerInventoryObserver(LLAvatarTracker* at) :
- mAT(at) {}
- virtual ~LLAvatarTrackerInventoryObserver() {}
- virtual void changed(U32 mask);
-protected:
- LLAvatarTracker* mAT;
-};
-*/
-/*
-void LLAvatarTrackerInventoryObserver::changed(U32 mask)
-{
- // if there's a calling card change, just do it.
- if((mask & LLInventoryObserver::CALLING_CARD) != 0)
- {
- mAT->inventoryChanged();
- }
-}
-*/
+
///----------------------------------------------------------------------------
/// Class LLAvatarTracker
@@ -281,7 +259,7 @@ S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds)
++new_buddy_count;
mBuddyInfo[agent_id] = (*itr).second;
gCacheName->getName(agent_id, first, last);
- mModifyMask |= LLFriendObserver::ADD;
+ addChangedMask(LLFriendObserver::ADD, agent_id);
lldebugs << "Added buddy " << agent_id
<< ", " << (mBuddyInfo[agent_id]->isOnline() ? "Online" : "Offline")
<< ", TO: " << mBuddyInfo[agent_id]->getRightsGrantedTo()
@@ -329,7 +307,8 @@ void LLAvatarTracker::terminateBuddy(const LLUUID& id)
msg->nextBlock("ExBlock");
msg->addUUID("OtherID", id);
gAgent.sendReliableMessage();
- mModifyMask |= LLFriendObserver::REMOVE;
+
+ addChangedMask(LLFriendObserver::REMOVE, id);
delete buddy;
}
@@ -340,6 +319,12 @@ const LLRelationship* LLAvatarTracker::getBuddyInfo(const LLUUID& id) const
return get_ptr_in_map(mBuddyInfo, id);
}
+bool LLAvatarTracker::isBuddy(const LLUUID& id) const
+{
+ LLRelationship* info = get_ptr_in_map(mBuddyInfo, id);
+ return (info != NULL);
+}
+
// online status
void LLAvatarTracker::setBuddyOnline(const LLUUID& id, bool is_online)
{
@@ -347,7 +332,7 @@ void LLAvatarTracker::setBuddyOnline(const LLUUID& id, bool is_online)
if(info)
{
info->online(is_online);
- mModifyMask |= LLFriendObserver::ONLINE;
+ addChangedMask(LLFriendObserver::ONLINE, id);
lldebugs << "Set buddy " << id << (is_online ? " Online" : " Offline") << llendl;
}
else
@@ -502,7 +487,61 @@ void LLAvatarTracker::notifyObservers()
{
(*it)->changed(mModifyMask);
}
+
+ for (changed_buddy_t::iterator it = mChangedBuddyIDs.begin(); it != mChangedBuddyIDs.end(); it++)
+ {
+ notifyParticularFriendObservers(*it);
+ }
+
mModifyMask = LLFriendObserver::NONE;
+ mChangedBuddyIDs.clear();
+}
+
+void LLAvatarTracker::addParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer)
+{
+ if (buddy_id.notNull() && observer)
+ mParticularFriendObserverMap[buddy_id].insert(observer);
+}
+
+void LLAvatarTracker::removeParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer)
+{
+ if (buddy_id.isNull() || !observer)
+ return;
+
+ observer_map_t::iterator obs_it = mParticularFriendObserverMap.find(buddy_id);
+ if(obs_it == mParticularFriendObserverMap.end())
+ return;
+
+ obs_it->second.erase(observer);
+
+ // purge empty sets from the map
+ if (obs_it->second.size() == 0)
+ mParticularFriendObserverMap.erase(obs_it);
+}
+
+void LLAvatarTracker::notifyParticularFriendObservers(const LLUUID& buddy_id)
+{
+ observer_map_t::iterator obs_it = mParticularFriendObserverMap.find(buddy_id);
+ if(obs_it == mParticularFriendObserverMap.end())
+ return;
+
+ // Notify observers interested in buddy_id.
+ observer_set_t& obs = obs_it->second;
+ for (observer_set_t::iterator ob_it = obs.begin(); ob_it != obs.end(); ob_it++)
+ {
+ (*ob_it)->changed(mModifyMask);
+ }
+}
+
+// store flag for change
+// and id of object change applies to
+void LLAvatarTracker::addChangedMask(U32 mask, const LLUUID& referent)
+{
+ mModifyMask |= mask;
+ if (referent.notNull())
+ {
+ mChangedBuddyIDs.insert(referent);
+ }
}
void LLAvatarTracker::applyFunctor(LLRelationshipFunctor& f)
@@ -592,28 +631,29 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg)
{
if((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS)
{
- std::string first, last;
+ std::string name;
LLSD args;
- if(gCacheName->getName(agent_id, first, last))
+ if(gCacheName->getFullName(agent_id, name))
{
- args["FIRST_NAME"] = first;
- args["LAST_NAME"] = last;
+ args["NAME"] = name;
}
+ LLSD payload;
+ payload["from_id"] = agent_id;
if(LLRelationship::GRANT_MODIFY_OBJECTS & new_rights)
{
- LLNotifications::instance().add("GrantedModifyRights",args);
+ LLNotificationsUtil::add("GrantedModifyRights",args, payload);
}
else
{
- LLNotifications::instance().add("RevokedModifyRights",args);
+ LLNotificationsUtil::add("RevokedModifyRights",args, payload);
}
}
(mBuddyInfo[agent_id])->setRightsFrom(new_rights);
}
}
}
- mModifyMask |= LLFriendObserver::POWERS;
+ addChangedMask(LLFriendObserver::POWERS, agent_id);
notifyObservers();
}
@@ -675,17 +715,12 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
if(notify)
{
// Popup a notify box with online status of this agent
- LLNotificationPtr notification = LLNotifications::instance().add(online ? "FriendOnline" : "FriendOffline", args);
+ LLNotificationPtr notification = LLNotificationsUtil::add(online ? "FriendOnline" : "FriendOffline", args);
// If there's an open IM session with this agent, send a notification there too.
LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, agent_id);
- LLFloaterIMPanel *floater = gIMMgr->findFloaterBySession(session_id);
- if (floater)
- {
- std::string notifyMsg = notification->getMessage();
- if (!notifyMsg.empty())
- floater->addHistoryLine(notifyMsg,gSavedSettings.getColor4("SystemChatColor"));
- }
+ std::string notify_msg = notification->getMessage();
+ LLIMModel::instance().proccessOnlineOfflineNotification(session_id, notify_msg);
}
mModifyMask |= LLFriendObserver::ONLINE;
@@ -706,7 +741,7 @@ void LLAvatarTracker::formFriendship(const LLUUID& id)
//visible online to each other.
buddy_info = new LLRelationship(LLRelationship::GRANT_ONLINE_STATUS,LLRelationship::GRANT_ONLINE_STATUS, false);
at.mBuddyInfo[id] = buddy_info;
- at.mModifyMask |= LLFriendObserver::ADD;
+ at.addChangedMask(LLFriendObserver::ADD, id);
at.notifyObservers();
}
}
@@ -722,7 +757,7 @@ void LLAvatarTracker::processTerminateFriendship(LLMessageSystem* msg, void**)
LLRelationship* buddy = get_ptr_in_map(at.mBuddyInfo, id);
if(!buddy) return;
at.mBuddyInfo.erase(id);
- at.mModifyMask |= LLFriendObserver::REMOVE;
+ at.addChangedMask(LLFriendObserver::REMOVE, id);
delete buddy;
at.notifyObservers();
}
diff --git a/indra/newview/llcallingcard.h b/indra/newview/llcallingcard.h
index 85a1ab6e1e..47b0dcb903 100644
--- a/indra/newview/llcallingcard.h
+++ b/indra/newview/llcallingcard.h
@@ -45,6 +45,7 @@
//class LLInventoryObserver;
class LLMessageSystem;
class LLTrackingData;
+
class LLFriendObserver
{
public:
@@ -125,6 +126,9 @@ public:
// get full info
const LLRelationship* getBuddyInfo(const LLUUID& id) const;
+ // Is this person a friend/buddy/calling card holder?
+ bool isBuddy(const LLUUID& id) const;
+
// online status
void setBuddyOnline(const LLUUID& id, bool is_online);
bool isBuddyOnline(const LLUUID& id) const;
@@ -147,6 +151,23 @@ public:
void removeObserver(LLFriendObserver* observer);
void notifyObservers();
+ // Observers interested in updates of a particular avatar.
+ // On destruction these observers are NOT deleted.
+ void addParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer);
+ void removeParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer);
+ void notifyParticularFriendObservers(const LLUUID& buddy_id);
+
+ /**
+ * Stores flag for change and id of object change applies to
+ *
+ * This allows outsiders to tell the AvatarTracker if something has
+ * been changed 'under the hood',
+ * and next notification will have exact avatar IDs have been changed.
+ */
+ void addChangedMask(U32 mask, const LLUUID& referent);
+
+ const std::set<LLUUID>& getChangedIDs() { return mChangedBuddyIDs; }
+
// Apply the functor to every buddy. Do not actually modify the
// buddy list in the functor or bad things will happen.
void applyFunctor(LLRelationshipFunctor& f);
@@ -179,9 +200,16 @@ protected:
buddy_map_t mBuddyInfo;
+ typedef std::set<LLUUID> changed_buddy_t;
+ changed_buddy_t mChangedBuddyIDs;
+
typedef std::vector<LLFriendObserver*> observer_list_t;
observer_list_t mObservers;
+ typedef std::set<LLFriendObserver*> observer_set_t;
+ typedef std::map<LLUUID, observer_set_t> observer_map_t;
+ observer_map_t mParticularFriendObserverMap;
+
private:
// do not implement
LLAvatarTracker(const LLAvatarTracker&);
diff --git a/indra/newview/llcapabilitylistener.cpp b/indra/newview/llcapabilitylistener.cpp
new file mode 100644
index 0000000000..ed9613c1bc
--- /dev/null
+++ b/indra/newview/llcapabilitylistener.cpp
@@ -0,0 +1,208 @@
+/**
+ * @file llcapabilitylistener.cpp
+ * @author Nat Goodspeed
+ * @date 2009-01-07
+ * @brief Implementation for llcapabilitylistener.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "llviewerprecompiledheaders.h"
+// associated header
+#include "llcapabilitylistener.h"
+// STL headers
+#include <map>
+// std headers
+// external library headers
+#include <boost/bind.hpp>
+// other Linden headers
+#include "stringize.h"
+#include "llcapabilityprovider.h"
+#include "message.h"
+
+class LLCapabilityListener::CapabilityMappers: public LLSingleton<LLCapabilityListener::CapabilityMappers>
+{
+public:
+ void registerMapper(const LLCapabilityListener::CapabilityMapper*);
+ void unregisterMapper(const LLCapabilityListener::CapabilityMapper*);
+ const LLCapabilityListener::CapabilityMapper* find(const std::string& cap) const;
+
+ struct DupCapMapper: public std::runtime_error
+ {
+ DupCapMapper(const std::string& what):
+ std::runtime_error(std::string("DupCapMapper: ") + what)
+ {}
+ };
+
+private:
+ friend class LLSingleton<LLCapabilityListener::CapabilityMappers>;
+ CapabilityMappers();
+
+ typedef std::map<std::string, const LLCapabilityListener::CapabilityMapper*> CapabilityMap;
+ CapabilityMap mMap;
+};
+
+LLCapabilityListener::LLCapabilityListener(const std::string& name,
+ LLMessageSystem* messageSystem,
+ const LLCapabilityProvider& provider,
+ const LLUUID& agentID,
+ const LLUUID& sessionID):
+ mEventPump(name),
+ mMessageSystem(messageSystem),
+ mProvider(provider),
+ mAgentID(agentID),
+ mSessionID(sessionID)
+{
+ mEventPump.listen("self", boost::bind(&LLCapabilityListener::capListener, this, _1));
+}
+
+bool LLCapabilityListener::capListener(const LLSD& request)
+{
+ // Extract what we want from the request object. We do it all up front
+ // partly to document what we expect.
+ LLSD::String cap(request["message"]);
+ LLSD payload(request["payload"]);
+ LLSD::String reply(request["reply"]);
+ LLSD::String error(request["error"]);
+ LLSD::Real timeout(request["timeout"]);
+ // If the LLSD doesn't even have a "message" key, we doubt it was intended
+ // for this listener.
+ if (cap.empty())
+ {
+ LL_ERRS("capListener") << "capability request event without 'message' key to '"
+ << getCapAPI().getName()
+ << "' on region\n" << mProvider.getDescription()
+ << LL_ENDL;
+ return false; // in case fatal-error function isn't
+ }
+ // Establish default timeout. This test relies on LLSD::asReal() returning
+ // exactly 0.0 for an undef value.
+ if (! timeout)
+ {
+ timeout = HTTP_REQUEST_EXPIRY_SECS;
+ }
+ // Look up the url for the requested capability name.
+ std::string url = mProvider.getCapability(cap);
+ if (! url.empty())
+ {
+ // This capability is supported by the region to which we're talking.
+ LLHTTPClient::post(url, payload,
+ new LLSDMessage::EventResponder(LLEventPumps::instance(),
+ request,
+ mProvider.getDescription(),
+ cap, reply, error),
+ LLSD(), // headers
+ timeout);
+ }
+ else
+ {
+ // Capability not supported -- do we have a registered mapper?
+ const CapabilityMapper* mapper = CapabilityMappers::instance().find(cap);
+ if (! mapper) // capability neither supported nor mapped
+ {
+ LL_ERRS("capListener") << "unsupported capability '" << cap << "' request to '"
+ << getCapAPI().getName() << "' on region\n"
+ << mProvider.getDescription()
+ << LL_ENDL;
+ }
+ else if (! mapper->getReplyName().empty()) // mapper expects reply support
+ {
+ LL_ERRS("capListener") << "Mapper for capability '" << cap
+ << "' requires unimplemented support for reply message '"
+ << mapper->getReplyName()
+ << "' on '" << getCapAPI().getName() << "' on region\n"
+ << mProvider.getDescription()
+ << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS("capListener") << "fallback invoked for capability '" << cap
+ << "' request to '" << getCapAPI().getName()
+ << "' on region\n" << mProvider.getDescription()
+ << LL_ENDL;
+ mapper->buildMessage(mMessageSystem, mAgentID, mSessionID, cap, payload);
+ mMessageSystem->sendReliable(mProvider.getHost());
+ }
+ }
+ return false;
+}
+
+LLCapabilityListener::CapabilityMapper::CapabilityMapper(const std::string& cap, const std::string& reply):
+ mCapName(cap),
+ mReplyName(reply)
+{
+ LLCapabilityListener::CapabilityMappers::instance().registerMapper(this);
+}
+
+LLCapabilityListener::CapabilityMapper::~CapabilityMapper()
+{
+ LLCapabilityListener::CapabilityMappers::instance().unregisterMapper(this);
+}
+
+LLSD LLCapabilityListener::CapabilityMapper::readResponse(LLMessageSystem* messageSystem) const
+{
+ return LLSD();
+}
+
+LLCapabilityListener::CapabilityMappers::CapabilityMappers() {}
+
+void LLCapabilityListener::CapabilityMappers::registerMapper(const LLCapabilityListener::CapabilityMapper* mapper)
+{
+ // Try to insert a new map entry by which we can look up the passed mapper
+ // instance.
+ std::pair<CapabilityMap::iterator, bool> inserted =
+ mMap.insert(CapabilityMap::value_type(mapper->getCapName(), mapper));
+ // If we already have a mapper for that name, insert() merely located the
+ // existing iterator and returned false. It is a coding error to try to
+ // register more than one mapper for the same capability name.
+ if (! inserted.second)
+ {
+ throw DupCapMapper(std::string("Duplicate capability name ") + mapper->getCapName());
+ }
+}
+
+void LLCapabilityListener::CapabilityMappers::unregisterMapper(const LLCapabilityListener::CapabilityMapper* mapper)
+{
+ CapabilityMap::iterator found = mMap.find(mapper->getCapName());
+ if (found != mMap.end())
+ {
+ mMap.erase(found);
+ }
+}
+
+const LLCapabilityListener::CapabilityMapper*
+LLCapabilityListener::CapabilityMappers::find(const std::string& cap) const
+{
+ CapabilityMap::const_iterator found = mMap.find(cap);
+ if (found != mMap.end())
+ {
+ return found->second;
+ }
+ return NULL;
+}
diff --git a/indra/newview/llcapabilitylistener.h b/indra/newview/llcapabilitylistener.h
new file mode 100644
index 0000000000..be51cf1b8c
--- /dev/null
+++ b/indra/newview/llcapabilitylistener.h
@@ -0,0 +1,137 @@
+/**
+ * @file llcapabilitylistener.h
+ * @author Nat Goodspeed
+ * @date 2009-01-07
+ * @brief Provide an event-based API for capability requests
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLCAPABILITYLISTENER_H)
+#define LL_LLCAPABILITYLISTENER_H
+
+#include "llevents.h" // LLEventPump
+#include "llsdmessage.h" // LLSDMessage::ArgError
+#include "llerror.h" // LOG_CLASS()
+
+class LLCapabilityProvider;
+class LLMessageSystem;
+class LLSD;
+
+class LLCapabilityListener
+{
+ LOG_CLASS(LLCapabilityListener);
+public:
+ LLCapabilityListener(const std::string& name, LLMessageSystem* messageSystem,
+ const LLCapabilityProvider& provider,
+ const LLUUID& agentID, const LLUUID& sessionID);
+
+ /// Capability-request exception
+ typedef LLSDMessage::ArgError ArgError;
+ /// Get LLEventPump on which we listen for capability requests
+ /// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities)
+ LLEventPump& getCapAPI() { return mEventPump; }
+
+ /**
+ * Base class for mapping an as-yet-undeployed capability name to a (pair
+ * of) LLMessageSystem message(s). To map a capability name to such
+ * messages, derive a subclass of CapabilityMapper and declare a static
+ * instance in a translation unit known to be loaded. The mapping is not
+ * region-specific. If an LLViewerRegion's capListener() receives a
+ * request for a supported capability, it will use the capability's URL.
+ * If not, it will look for an applicable CapabilityMapper subclass
+ * instance.
+ */
+ class CapabilityMapper
+ {
+ public:
+ /**
+ * Base-class constructor. Typically your subclass constructor will
+ * pass these parameters as literals.
+ * @param cap the capability name handled by this (subclass) instance
+ * @param reply the name of the response LLMessageSystem message. Omit
+ * if the LLMessageSystem message you intend to send doesn't prompt a
+ * reply message, or if you already handle that message in some other
+ * way.
+ */
+ CapabilityMapper(const std::string& cap, const std::string& reply = "");
+ virtual ~CapabilityMapper();
+ /// query the capability name
+ std::string getCapName() const { return mCapName; }
+ /// query the reply message name
+ std::string getReplyName() const { return mReplyName; }
+ /**
+ * Override this method to build the LLMessageSystem message we should
+ * send instead of the requested capability message. DO NOT send that
+ * message: that will be handled by the caller.
+ */
+ virtual void buildMessage(LLMessageSystem* messageSystem,
+ const LLUUID& agentID,
+ const LLUUID& sessionID,
+ const std::string& capabilityName,
+ const LLSD& payload) const = 0;
+ /**
+ * Override this method if you pass a non-empty @a reply
+ * LLMessageSystem message name to the constructor: that is, if you
+ * expect to receive an LLMessageSystem message in response to the
+ * message you constructed in buildMessage(). If you don't pass a @a
+ * reply message name, you need not override this method as it won't
+ * be called.
+ *
+ * Using LLMessageSystem message-reading operations, your
+ * readResponse() override should construct and return an LLSD object
+ * of the form you expect to receive from the real implementation of
+ * the capability you intend to invoke, when it finally goes live.
+ */
+ virtual LLSD readResponse(LLMessageSystem* messageSystem) const;
+
+ private:
+ const std::string mCapName;
+ const std::string mReplyName;
+ };
+
+private:
+ /// Bind the LLCapabilityProvider passed to our ctor
+ const LLCapabilityProvider& mProvider;
+
+ /// Post an event to this LLEventPump to invoke a capability message on
+ /// the bound LLCapabilityProvider's server
+ /// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities)
+ LLEventStream mEventPump;
+
+ LLMessageSystem* mMessageSystem;
+ LLUUID mAgentID, mSessionID;
+
+ /// listener to process capability requests
+ bool capListener(const LLSD&);
+
+ /// helper class for capListener()
+ class CapabilityMappers;
+};
+
+#endif /* ! defined(LL_LLCAPABILITYLISTENER_H) */
diff --git a/indra/newview/llcapabilityprovider.h b/indra/newview/llcapabilityprovider.h
new file mode 100644
index 0000000000..3d07904775
--- /dev/null
+++ b/indra/newview/llcapabilityprovider.h
@@ -0,0 +1,62 @@
+/**
+ * @file llcapabilityprovider.h
+ * @author Nat Goodspeed
+ * @date 2009-01-07
+ * @brief Interface by which to reference (e.g.) LLViewerRegion to obtain a
+ * capability.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLCAPABILITYPROVIDER_H)
+#define LL_LLCAPABILITYPROVIDER_H
+
+#include "llhost.h"
+#include <string>
+
+/// Interface for obtaining a capability URL, given a capability name
+class LLCapabilityProvider
+{
+public:
+ virtual ~LLCapabilityProvider() {}
+ /**
+ * Get a capability URL, given a capability name. Returns empty string if
+ * no such capability is defined on this provider.
+ */
+ virtual std::string getCapability(const std::string& name) const = 0;
+ /**
+ * Get host to which to send that capability request.
+ */
+ virtual LLHost getHost() const = 0;
+ /**
+ * Describe this LLCapabilityProvider for logging etc.
+ */
+ virtual std::string getDescription() const = 0;
+};
+
+#endif /* ! defined(LL_LLCAPABILITYPROVIDER_H) */
diff --git a/indra/newview/llcaphttpsender.cpp b/indra/newview/llcaphttpsender.cpp
index 1127f43424..b44e1f11fa 100644
--- a/indra/newview/llcaphttpsender.cpp
+++ b/indra/newview/llcaphttpsender.cpp
@@ -32,9 +32,10 @@
#include "llviewerprecompiledheaders.h"
-#include "linden_common.h"
#include "llcaphttpsender.h"
+#include "llhost.h"
+
LLCapHTTPSender::LLCapHTTPSender(const std::string& cap) :
mCap(cap)
{
diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp
new file mode 100644
index 0000000000..769387c26c
--- /dev/null
+++ b/indra/newview/llchannelmanager.cpp
@@ -0,0 +1,240 @@
+/**
+ * @file llchannelmanager.cpp
+ * @brief This class rules screen notification channels.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#include "llchannelmanager.h"
+
+#include "llappviewer.h"
+#include "llviewercontrol.h"
+#include "llviewerwindow.h"
+#include "llrootview.h"
+#include "llsyswellwindow.h"
+#include "llfloaterreg.h"
+
+#include <algorithm>
+
+using namespace LLNotificationsUI;
+
+//--------------------------------------------------------------------------
+LLChannelManager::LLChannelManager()
+{
+ LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLChannelManager::onLoginCompleted, this));
+ mChannelList.clear();
+ mStartUpChannel = NULL;
+
+ if(!gViewerWindow)
+ {
+ llerrs << "LLChannelManager::LLChannelManager() - viwer window is not initialized yet" << llendl;
+ }
+}
+
+//--------------------------------------------------------------------------
+LLChannelManager::~LLChannelManager()
+{
+ for(std::vector<ChannelElem>::iterator it = mChannelList.begin(); it != mChannelList.end(); ++it)
+ {
+ delete (*it).channel;
+ }
+
+ mChannelList.clear();
+}
+
+//--------------------------------------------------------------------------
+LLScreenChannel* LLChannelManager::createNotificationChannel()
+{
+ // creating params for a channel
+ LLChannelManager::Params p;
+ p.id = LLUUID(gSavedSettings.getString("NotificationChannelUUID"));
+ p.channel_align = CA_RIGHT;
+
+ // Getting a Channel for our notifications
+ return dynamic_cast<LLScreenChannel*> (LLChannelManager::getInstance()->getChannel(p));
+}
+
+//--------------------------------------------------------------------------
+void LLChannelManager::onLoginCompleted()
+{
+ S32 away_notifications = 0;
+
+ // calc a number of all offline notifications
+ for(std::vector<ChannelElem>::iterator it = mChannelList.begin(); it != mChannelList.end(); ++it)
+ {
+ // don't calc notifications for Nearby Chat
+ if((*it).channel->getChannelID() == LLUUID(gSavedSettings.getString("NearByChatChannelUUID")))
+ {
+ continue;
+ }
+
+ // don't calc notifications for channels that always show their notifications
+ if(!(*it).channel->getDisplayToastsAlways())
+ {
+ away_notifications +=(*it).channel->getNumberOfHiddenToasts();
+ }
+ }
+
+ away_notifications += gIMMgr->getNumberOfUnreadIM();
+
+ if(!away_notifications)
+ {
+ onStartUpToastClose();
+ return;
+ }
+
+ // create a channel for the StartUp Toast
+ LLChannelManager::Params p;
+ p.id = LLUUID(gSavedSettings.getString("StartUpChannelUUID"));
+ p.channel_align = CA_RIGHT;
+ mStartUpChannel = createChannel(p);
+
+ if(!mStartUpChannel)
+ {
+ onStartUpToastClose();
+ return;
+ }
+
+ gViewerWindow->getRootView()->addChild(mStartUpChannel);
+
+ // init channel's position and size
+ S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin");
+ S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
+ mStartUpChannel->init(channel_right_bound - channel_width, channel_right_bound);
+ mStartUpChannel->setMouseDownCallback(boost::bind(&LLNotificationWellWindow::onStartUpToastClick, LLNotificationWellWindow::getInstance(), _2, _3, _4));
+
+ mStartUpChannel->setCommitCallback(boost::bind(&LLChannelManager::onStartUpToastClose, this));
+ mStartUpChannel->createStartUpToast(away_notifications, gSavedSettings.getS32("StartUpToastLifeTime"));
+}
+
+//--------------------------------------------------------------------------
+void LLChannelManager::onStartUpToastClose()
+{
+ if(mStartUpChannel)
+ {
+ mStartUpChannel->setVisible(FALSE);
+ mStartUpChannel->closeStartUpToast();
+ removeChannelByID(LLUUID(gSavedSettings.getString("StartUpChannelUUID")));
+ mStartUpChannel = NULL;
+ }
+
+ // set StartUp Toast Flag to allow all other channels to show incoming toasts
+ LLScreenChannel::setStartUpToastShown();
+}
+
+//--------------------------------------------------------------------------
+
+LLScreenChannelBase* LLChannelManager::addChannel(LLScreenChannelBase* channel)
+{
+ if(!channel)
+ return 0;
+
+ ChannelElem new_elem;
+ new_elem.id = channel->getChannelID();
+ new_elem.channel = channel;
+
+ mChannelList.push_back(new_elem);
+
+ return channel;
+}
+
+LLScreenChannel* LLChannelManager::createChannel(LLChannelManager::Params& p)
+{
+ LLScreenChannel* new_channel = new LLScreenChannel(p.id);
+
+ if(!new_channel)
+ {
+ llerrs << "LLChannelManager::getChannel(LLChannelManager::Params& p) - can't create a channel!" << llendl;
+ }
+ else
+ {
+ new_channel->setToastAlignment(p.toast_align);
+ new_channel->setChannelAlignment(p.channel_align);
+ new_channel->setDisplayToastsAlways(p.display_toasts_always);
+
+ addChannel(new_channel);
+ }
+ return new_channel;
+}
+
+LLScreenChannelBase* LLChannelManager::getChannel(LLChannelManager::Params& p)
+{
+ LLScreenChannelBase* new_channel = findChannelByID(p.id);
+
+ if(new_channel)
+ return new_channel;
+
+ return createChannel(p);
+
+}
+
+//--------------------------------------------------------------------------
+LLScreenChannelBase* LLChannelManager::findChannelByID(const LLUUID id)
+{
+ std::vector<ChannelElem>::iterator it = find(mChannelList.begin(), mChannelList.end(), id);
+ if(it != mChannelList.end())
+ {
+ return (*it).channel;
+ }
+
+ return NULL;
+}
+
+//--------------------------------------------------------------------------
+void LLChannelManager::removeChannelByID(const LLUUID id)
+{
+ std::vector<ChannelElem>::iterator it = find(mChannelList.begin(), mChannelList.end(), id);
+ if(it != mChannelList.end())
+ {
+ mChannelList.erase(it);
+ }
+}
+
+//--------------------------------------------------------------------------
+void LLChannelManager::muteAllChannels(bool mute)
+{
+ for (std::vector<ChannelElem>::iterator it = mChannelList.begin();
+ it != mChannelList.end(); it++)
+ {
+ it->channel->setShowToasts(!mute);
+ }
+}
+
+void LLChannelManager::killToastsFromChannel(const LLUUID& channel_id, const LLScreenChannel::Matcher& matcher)
+{
+ LLScreenChannel
+ * screen_channel =
+ dynamic_cast<LLScreenChannel*> (findChannelByID(channel_id));
+ if (screen_channel != NULL)
+ {
+ screen_channel->killMatchedToasts(matcher);
+ }
+}
+
diff --git a/indra/newview/llchannelmanager.h b/indra/newview/llchannelmanager.h
new file mode 100644
index 0000000000..c2be39122f
--- /dev/null
+++ b/indra/newview/llchannelmanager.h
@@ -0,0 +1,127 @@
+/**
+ * @file llchannelmanager.h
+ * @brief This class rules screen notification channels.
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLCHANNELMANAGER_H
+#define LL_LLCHANNELMANAGER_H
+
+
+#include "llscreenchannel.h"
+
+#include "lluuid.h"
+
+#include <map>
+#include <boost/shared_ptr.hpp>
+
+namespace LLNotificationsUI
+{
+/**
+ * Manager for screen channels.
+ * Responsible for instantiating and retrieving screen channels.
+ */
+class LLChannelManager : public LLSingleton<LLChannelManager>
+{
+public:
+ struct Params
+ {
+ LLUUID id;
+ bool display_toasts_always;
+ EToastAlignment toast_align;
+ EChannelAlignment channel_align;
+
+ Params(): id(LLUUID("")), display_toasts_always(false), toast_align(NA_BOTTOM), channel_align(CA_LEFT)
+ {}
+ };
+
+ struct ChannelElem
+ {
+ LLUUID id;
+ LLScreenChannelBase* channel;
+
+ ChannelElem() : id(LLUUID("")), channel(NULL) { }
+
+ ChannelElem(const ChannelElem &elem)
+ {
+ id = elem.id;
+ channel = elem.channel;
+ }
+
+ bool operator == (const LLUUID &id_op) const
+ {
+ return (id == id_op);
+ }
+ };
+
+ LLChannelManager();
+ virtual ~LLChannelManager();
+
+ // On LoginCompleted - show StartUp toast
+ void onLoginCompleted();
+ // removes a channel intended for the startup toast and allows other channels to show their toasts
+ void onStartUpToastClose();
+
+ // creates a new ScreenChannel according to the given parameters or returns existing if present
+ LLScreenChannelBase* getChannel(LLChannelManager::Params& p);
+
+ LLScreenChannelBase* addChannel(LLScreenChannelBase* channel);
+
+ // returns a channel by its ID
+ LLScreenChannelBase* findChannelByID(const LLUUID id);
+
+ // creator of the Notification channel, that is used in more than one handler
+ LLScreenChannel* createNotificationChannel();
+
+ // remove channel methods
+ void removeChannelByID(const LLUUID id);
+
+ /**
+ * Manages toasts showing for all channels.
+ *
+ * @param mute Flag to disable/enable toasts showing.
+ */
+ void muteAllChannels(bool mute);
+
+ /**
+ * Kills matched toasts from specified toast screen channel.
+ */
+ void killToastsFromChannel(const LLUUID& channel_id, const LLScreenChannel::Matcher& matcher);
+
+private:
+
+ LLScreenChannel* createChannel(LLChannelManager::Params& p);
+
+ LLScreenChannel* mStartUpChannel;
+ std::vector<ChannelElem> mChannelList;
+};
+
+}
+#endif
+
diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp
index 2395f3c5ae..b32a955038 100644
--- a/indra/newview/llchatbar.cpp
+++ b/indra/newview/llchatbar.cpp
@@ -48,7 +48,6 @@
#include "llcombobox.h"
#include "llcommandhandler.h" // secondlife:///app/chat/ support
#include "llviewercontrol.h"
-#include "llfloaterchat.h"
#include "llgesturemgr.h"
#include "llkeyboard.h"
#include "lllineeditor.h"
@@ -67,7 +66,7 @@
#include "llui.h"
#include "llviewermenu.h"
#include "lluictrlfactory.h"
-
+#include "llbottomtray.h"
//
// Globals
@@ -76,11 +75,6 @@ const F32 AGENT_TYPING_TIMEOUT = 5.f; // seconds
LLChatBar *gChatBar = NULL;
-// legacy calllback glue
-void toggleChatHistory(void* user_data);
-void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel);
-
-
class LLChatBarGestureObserver : public LLGestureManagerObserver
{
public:
@@ -92,12 +86,14 @@ private:
};
+extern void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel);
+
//
// Functions
//
LLChatBar::LLChatBar()
-: LLPanel(LLStringUtil::null, LLRect(), BORDER_NO),
+: LLPanel(),
mInputEditor(NULL),
mGestureLabelTimer(),
mLastSpecialChatChannel(0),
@@ -106,16 +102,12 @@ LLChatBar::LLChatBar()
mObserver(NULL)
{
setIsChrome(TRUE);
-
- #if !LL_RELEASE_FOR_DOWNLOAD
- childDisplayNotFound();
-#endif
}
LLChatBar::~LLChatBar()
{
- gGestureManager.removeObserver(mObserver);
+ LLGestureManager::instance().removeObserver(mObserver);
delete mObserver;
mObserver = NULL;
// LLView destructor cleans up children
@@ -123,34 +115,25 @@ LLChatBar::~LLChatBar()
BOOL LLChatBar::postBuild()
{
- childSetAction("History", toggleChatHistory, this);
- childSetCommitCallback("Say", onClickSay, this);
+ getChild<LLUICtrl>("Say")->setCommitCallback(boost::bind(&LLChatBar::onClickSay, this, _1));
+ // * NOTE: mantipov: getChild with default parameters returns dummy widget.
+ // Seems this class will be completle removed
// attempt to bind to an existing combo box named gesture
- setGestureCombo(getChild<LLComboBox>( "Gesture"));
-
- LLButton * sayp = getChild<LLButton>("Say");
- if(sayp)
- {
- setDefaultBtn(sayp);
- }
+ setGestureCombo(findChild<LLComboBox>( "Gesture"));
mInputEditor = getChild<LLLineEditor>("Chat Editor");
- if (mInputEditor)
- {
- mInputEditor->setCallbackUserData(this);
- mInputEditor->setKeystrokeCallback(&onInputEditorKeystroke);
- mInputEditor->setFocusLostCallback(&onInputEditorFocusLost, this);
- mInputEditor->setFocusReceivedCallback( &onInputEditorGainFocus, this );
- mInputEditor->setCommitOnFocusLost( FALSE );
- mInputEditor->setRevertOnEsc( FALSE );
- mInputEditor->setIgnoreTab(TRUE);
- mInputEditor->setPassDelete(TRUE);
- mInputEditor->setReplaceNewlinesWithSpaces(FALSE);
-
- mInputEditor->setMaxTextLength(1023);
- mInputEditor->setEnableLineHistory(TRUE);
- }
+ mInputEditor->setKeystrokeCallback(&onInputEditorKeystroke, this);
+ mInputEditor->setFocusLostCallback(boost::bind(&LLChatBar::onInputEditorFocusLost));
+ mInputEditor->setFocusReceivedCallback(boost::bind(&LLChatBar::onInputEditorGainFocus));
+ mInputEditor->setCommitOnFocusLost( FALSE );
+ mInputEditor->setRevertOnEsc( FALSE );
+ mInputEditor->setIgnoreTab(TRUE);
+ mInputEditor->setPassDelete(TRUE);
+ mInputEditor->setReplaceNewlinesWithSpaces(FALSE);
+
+ mInputEditor->setMaxTextLength(1023);
+ mInputEditor->setEnableLineHistory(TRUE);
mIsBuilt = TRUE;
@@ -209,10 +192,7 @@ void LLChatBar::refresh()
gAgent.stopTyping();
}
- childSetValue("History", LLFloaterChat::instanceVisible(LLSD()));
-
childSetEnabled("Say", mInputEditor->getText().size() > 0);
- childSetEnabled("Shout", mInputEditor->getText().size() > 0);
}
@@ -229,8 +209,9 @@ void LLChatBar::refreshGestures()
// collect list of unique gestures
std::map <std::string, BOOL> unique;
- LLGestureManager::item_map_t::iterator it;
- for (it = gGestureManager.mActive.begin(); it != gGestureManager.mActive.end(); ++it)
+ LLGestureManager::item_map_t::const_iterator it;
+ const LLGestureManager::item_map_t& active_gestures = LLGestureManager::instance().getActiveGestures();
+ for (it = active_gestures.begin(); it != active_gestures.end(); ++it)
{
LLMultiGesture* gesture = (*it).second;
if (gesture)
@@ -311,12 +292,11 @@ void LLChatBar::setGestureCombo(LLComboBox* combo)
mGestureCombo = combo;
if (mGestureCombo)
{
- mGestureCombo->setCommitCallback(onCommitGesture);
- mGestureCombo->setCallbackUserData(this);
+ mGestureCombo->setCommitCallback(boost::bind(&LLChatBar::onCommitGesture, this, _1));
// now register observer since we have a place to put the results
mObserver = new LLChatBarGestureObserver(this);
- gGestureManager.addObserver(mObserver);
+ LLGestureManager::instance().addObserver(mObserver);
// refresh list from current active gestures
refreshGestures();
@@ -397,7 +377,7 @@ void LLChatBar::sendChat( EChatType type )
if (0 == channel)
{
// discard returned "found" boolean
- gGestureManager.triggerAndReviseString(utf8text, &utf8_revised_text);
+ LLGestureManager::instance().triggerAndReviseString(utf8text, &utf8_revised_text);
}
else
{
@@ -434,17 +414,26 @@ void LLChatBar::sendChat( EChatType type )
// static
void LLChatBar::startChat(const char* line)
{
- gChatBar->setVisible(TRUE);
- gChatBar->setKeyboardFocus(TRUE);
- gSavedSettings.setBOOL("ChatVisible", TRUE);
-
- if (line && gChatBar->mInputEditor)
- {
- std::string line_string(line);
- gChatBar->mInputEditor->setText(line_string);
- }
- // always move cursor to end so users don't obliterate chat when accidentally hitting WASD
- gChatBar->mInputEditor->setCursorToEnd();
+ //TODO* remove DUMMY chat
+ //if(gBottomTray && gBottomTray->getChatBox())
+ //{
+ // gBottomTray->setVisible(TRUE);
+ // gBottomTray->getChatBox()->setFocus(TRUE);
+ //}
+
+ // *TODO Vadim: Why was this code commented out?
+
+// gChatBar->setVisible(TRUE);
+// gChatBar->setKeyboardFocus(TRUE);
+// gSavedSettings.setBOOL("ChatVisible", TRUE);
+//
+// if (line && gChatBar->mInputEditor)
+// {
+// std::string line_string(line);
+// gChatBar->mInputEditor->setText(line_string);
+// }
+// // always move cursor to end so users don't obliterate chat when accidentally hitting WASD
+// gChatBar->mInputEditor->setCursorToEnd();
}
@@ -452,21 +441,29 @@ void LLChatBar::startChat(const char* line)
// static
void LLChatBar::stopChat()
{
- // In simple UI mode, we never release focus from the chat bar
- gChatBar->setKeyboardFocus(FALSE);
-
- // If we typed a movement key and pressed return during the
- // same frame, the keyboard handlers will see the key as having
- // gone down this frame and try to move the avatar.
- gKeyboard->resetKeys();
- gKeyboard->resetMaskKeys();
-
- // stop typing animation
- gAgent.stopTyping();
-
- // hide chat bar so it doesn't grab focus back
- gChatBar->setVisible(FALSE);
- gSavedSettings.setBOOL("ChatVisible", FALSE);
+ //TODO* remove DUMMY chat
+ //if(gBottomTray && gBottomTray->getChatBox())
+ ///{
+ // gBottomTray->getChatBox()->setFocus(FALSE);
+ //}
+
+ // *TODO Vadim: Why was this code commented out?
+
+// // In simple UI mode, we never release focus from the chat bar
+// gChatBar->setKeyboardFocus(FALSE);
+//
+// // If we typed a movement key and pressed return during the
+// // same frame, the keyboard handlers will see the key as having
+// // gone down this frame and try to move the avatar.
+// gKeyboard->resetKeys();
+// gKeyboard->resetMaskKeys();
+//
+// // stop typing animation
+// gAgent.stopTyping();
+//
+// // hide chat bar so it doesn't grab focus back
+// gChatBar->setVisible(FALSE);
+// gSavedSettings.setBOOL("ChatVisible", FALSE);
}
// static
@@ -519,7 +516,7 @@ void LLChatBar::onInputEditorKeystroke( LLLineEditor* caller, void* userdata )
std::string utf8_trigger = wstring_to_utf8str(raw_text);
std::string utf8_out_str(utf8_trigger);
- if (gGestureManager.matchPrefix(utf8_trigger, &utf8_out_str))
+ if (LLGestureManager::instance().matchPrefix(utf8_trigger, &utf8_out_str))
{
if (self->mInputEditor)
{
@@ -541,32 +538,31 @@ void LLChatBar::onInputEditorKeystroke( LLLineEditor* caller, void* userdata )
}
// static
-void LLChatBar::onInputEditorFocusLost( LLFocusableElement* caller, void* userdata)
+void LLChatBar::onInputEditorFocusLost()
{
// stop typing animation
gAgent.stopTyping();
}
// static
-void LLChatBar::onInputEditorGainFocus( LLFocusableElement* caller, void* userdata )
+void LLChatBar::onInputEditorGainFocus()
{
- LLFloaterChat::setHistoryCursorAndScrollToEnd();
+ //LLFloaterChat::setHistoryCursorAndScrollToEnd();
}
-// static
-void LLChatBar::onClickSay( LLUICtrl* ctrl, void* userdata )
+void LLChatBar::onClickSay( LLUICtrl* ctrl )
{
+ std::string cmd = ctrl->getValue().asString();
e_chat_type chat_type = CHAT_TYPE_NORMAL;
- if (ctrl->getValue().asString() == "shout")
+ if (cmd == "shout")
{
chat_type = CHAT_TYPE_SHOUT;
}
- else if (ctrl->getValue().asString() == "whisper")
+ else if (cmd == "whisper")
{
chat_type = CHAT_TYPE_WHISPER;
}
- LLChatBar* self = (LLChatBar*) userdata;
- self->sendChat(chat_type);
+ sendChat(chat_type);
}
void LLChatBar::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate)
@@ -622,7 +618,7 @@ void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL
send_chat_from_viewer(utf8_out_text, type, channel);
}
-
+/*
void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel)
{
LLMessageSystem* msg = gMessageSystem;
@@ -639,13 +635,11 @@ void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32
LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT);
}
+*/
-
-// static
-void LLChatBar::onCommitGesture(LLUICtrl* ctrl, void* data)
+void LLChatBar::onCommitGesture(LLUICtrl* ctrl)
{
- LLChatBar* self = (LLChatBar*)data;
- LLCtrlListInterface* gestures = self->mGestureCombo ? self->mGestureCombo->getListInterface() : NULL;
+ LLCtrlListInterface* gestures = mGestureCombo ? mGestureCombo->getListInterface() : NULL;
if (gestures)
{
S32 index = gestures->getFirstSelectedIndex();
@@ -659,38 +653,32 @@ void LLChatBar::onCommitGesture(LLUICtrl* ctrl, void* data)
// substitution and logging.
std::string text(trigger);
std::string revised_text;
- gGestureManager.triggerAndReviseString(text, &revised_text);
+ LLGestureManager::instance().triggerAndReviseString(text, &revised_text);
revised_text = utf8str_trim(revised_text);
if (!revised_text.empty())
{
// Don't play nodding animation
- self->sendChatFromViewer(revised_text, CHAT_TYPE_NORMAL, FALSE);
+ sendChatFromViewer(revised_text, CHAT_TYPE_NORMAL, FALSE);
}
}
- self->mGestureLabelTimer.start();
- if (self->mGestureCombo != NULL)
+ mGestureLabelTimer.start();
+ if (mGestureCombo != NULL)
{
// free focus back to chat bar
- self->mGestureCombo->setFocus(FALSE);
+ mGestureCombo->setFocus(FALSE);
}
}
-void toggleChatHistory(void* user_data)
-{
- LLFloaterChat::toggleInstance(LLSD());
-}
-
-
class LLChatHandler : public LLCommandHandler
{
public:
// not allowed from outside the app
- LLChatHandler() : LLCommandHandler("chat", true) { }
+ LLChatHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { }
// Your code here
bool handle(const LLSD& tokens, const LLSD& query_map,
- LLWebBrowserCtrl* web)
+ LLMediaCtrl* web)
{
if (tokens.size() < 2) return false;
S32 channel = tokens[0].asInteger();
@@ -701,4 +689,4 @@ public:
};
// Creating the object registers with the dispatcher.
-LLChatHandler gChatHandler;
+//LLChatHandler gChatHandler;
diff --git a/indra/newview/llchatbar.h b/indra/newview/llchatbar.h
index 56a98a78f9..86aa3ebd2a 100644
--- a/indra/newview/llchatbar.h
+++ b/indra/newview/llchatbar.h
@@ -45,6 +45,7 @@ class LLFrameTimer;
class LLChatBarGestureObserver;
class LLComboBox;
+
class LLChatBar
: public LLPanel
{
@@ -82,14 +83,14 @@ public:
LLWString stripChannelNumber(const LLWString &mesg, S32* channel);
// callbacks
- static void onClickSay( LLUICtrl*, void* userdata );
+ void onClickSay(LLUICtrl* ctrl);
static void onTabClick( void* userdata );
static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata);
- static void onInputEditorFocusLost(LLFocusableElement* caller,void* userdata);
- static void onInputEditorGainFocus(LLFocusableElement* caller,void* userdata);
+ static void onInputEditorFocusLost();
+ static void onInputEditorGainFocus();
- static void onCommitGesture(LLUICtrl* ctrl, void* data);
+ void onCommitGesture(LLUICtrl* ctrl);
static void startChat(const char* line);
static void stopChat();
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
new file mode 100644
index 0000000000..d6a7edee5b
--- /dev/null
+++ b/indra/newview/llchathistory.cpp
@@ -0,0 +1,620 @@
+/**
+ * @file llchathistory.cpp
+ * @brief LLTextEditor base class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llinstantmessage.h"
+
+#include "llchathistory.h"
+#include "llpanel.h"
+#include "lluictrlfactory.h"
+#include "llscrollcontainer.h"
+#include "llavatariconctrl.h"
+#include "llcallingcard.h" //for LLAvatarTracker
+#include "llagentdata.h"
+#include "llavataractions.h"
+#include "lltrans.h"
+#include "llfloaterreg.h"
+#include "llmutelist.h"
+#include "llstylemap.h"
+#include "lllayoutstack.h"
+#include "llagent.h"
+
+#include "llsidetray.h"//for blocked objects panel
+
+static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history");
+
+const static std::string NEW_LINE(rawstr_to_utf8("\n"));
+
+class LLChatHistoryHeader: public LLPanel
+{
+public:
+ static LLChatHistoryHeader* createInstance(const std::string& file_name)
+ {
+ LLChatHistoryHeader* pInstance = new LLChatHistoryHeader;
+ LLUICtrlFactory::getInstance()->buildPanel(pInstance, file_name);
+ return pInstance;
+ }
+
+ BOOL handleMouseUp(S32 x, S32 y, MASK mask)
+ {
+ return LLPanel::handleMouseUp(x,y,mask);
+ }
+
+ void onObjectIconContextMenuItemClicked(const LLSD& userdata)
+ {
+ std::string level = userdata.asString();
+
+ if (level == "profile")
+ {
+ LLSD params;
+ params["object_id"] = getAvatarId();
+
+ LLFloaterReg::showInstance("inspect_object", params);
+ }
+ else if (level == "block")
+ {
+ LLMuteList::getInstance()->add(LLMute(getAvatarId(), mFrom, LLMute::OBJECT));
+
+ LLSideTray::getInstance()->showPanel("panel_block_list_sidetray", LLSD().with("blocked_to_select", getAvatarId()));
+ }
+ }
+
+ void onAvatarIconContextMenuItemClicked(const LLSD& userdata)
+ {
+ std::string level = userdata.asString();
+
+ if (level == "profile")
+ {
+ LLAvatarActions::showProfile(getAvatarId());
+ }
+ else if (level == "im")
+ {
+ LLAvatarActions::startIM(getAvatarId());
+ }
+ else if (level == "add")
+ {
+ std::string name;
+ name.assign(getFirstName());
+ name.append(" ");
+ name.append(getLastName());
+
+ LLAvatarActions::requestFriendshipDialog(getAvatarId(), name);
+ }
+ else if (level == "remove")
+ {
+ LLAvatarActions::removeFriendDialog(getAvatarId());
+ }
+ }
+
+ BOOL postBuild()
+ {
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+
+ registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2));
+ registrar.add("ObjectIcon.Action", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemClicked, this, _2));
+
+ LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mPopupMenuHandleAvatar = menu->getHandle();
+
+ menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_object_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mPopupMenuHandleObject = menu->getHandle();
+
+ setDoubleClickCallback(boost::bind(&LLChatHistoryHeader::onHeaderPanelClick, this, _2, _3, _4));
+
+ return LLPanel::postBuild();
+ }
+
+ bool pointInChild(const std::string& name,S32 x,S32 y)
+ {
+ LLUICtrl* child = findChild<LLUICtrl>(name);
+ if(!child)
+ return false;
+
+ LLView* parent = child->getParent();
+ if(parent!=this)
+ {
+ x-=parent->getRect().mLeft;
+ y-=parent->getRect().mBottom;
+ }
+
+ S32 local_x = x - child->getRect().mLeft ;
+ S32 local_y = y - child->getRect().mBottom ;
+ return child->pointInView(local_x, local_y);
+ }
+
+ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask)
+ {
+ if(pointInChild("avatar_icon",x,y) || pointInChild("user_name",x,y))
+ {
+ showContextMenu(x,y);
+ return TRUE;
+ }
+
+ return LLPanel::handleRightMouseDown(x,y,mask);
+ }
+
+ void onHeaderPanelClick(S32 x, S32 y, MASK mask)
+ {
+ if (mSourceType == CHAT_SOURCE_OBJECT)
+ {
+ LLFloaterReg::showInstance("inspect_object", LLSD().with("object_id", mAvatarID));
+ }
+ else if (mSourceType == CHAT_SOURCE_AGENT)
+ {
+ LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", mAvatarID));
+ }
+ //if chat source is system, you may add "else" here to define behaviour.
+ }
+
+ const LLUUID& getAvatarId () const { return mAvatarID;}
+ const std::string& getFirstName() const { return mFirstName; }
+ const std::string& getLastName () const { return mLastName; }
+
+ void setup(const LLChat& chat,const LLStyle::Params& style_params)
+ {
+ mAvatarID = chat.mFromID;
+ mSourceType = chat.mSourceType;
+ gCacheName->get(mAvatarID, FALSE, boost::bind(&LLChatHistoryHeader::nameUpdatedCallback, this, _1, _2, _3, _4));
+ if(chat.mFromID.isNull())
+ {
+ mSourceType = CHAT_SOURCE_SYSTEM;
+ }
+
+ LLTextEditor* userName = getChild<LLTextEditor>("user_name");
+
+ userName->setReadOnlyColor(style_params.readonly_color());
+ userName->setColor(style_params.color());
+
+ if(!chat.mFromName.empty())
+ {
+ userName->setValue(chat.mFromName);
+ mFrom = chat.mFromName;
+ }
+ else
+ {
+ std::string SL = LLTrans::getString("SECOND_LIFE");
+ userName->setValue(SL);
+ }
+
+ mMinUserNameWidth = style_params.font()->getWidth(userName->getWText().c_str()) + PADDING;
+
+ setTimeField(chat);
+
+ LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon");
+
+ if(mSourceType != CHAT_SOURCE_AGENT)
+ icon->setDrawTooltip(false);
+
+ if(!chat.mFromID.isNull())
+ {
+ icon->setValue(chat.mFromID);
+ }
+ else if (userName->getValue().asString()==LLTrans::getString("SECOND_LIFE"))
+ {
+ icon->setValue(LLSD("SL_Logo"));
+ }
+
+ }
+
+ /*virtual*/ void draw()
+ {
+ LLTextEditor* user_name = getChild<LLTextEditor>("user_name");
+ LLTextBox* time_box = getChild<LLTextBox>("time_box");
+
+ LLRect user_name_rect = user_name->getRect();
+ S32 user_name_width = user_name_rect.getWidth();
+ S32 time_box_width = time_box->getRect().getWidth();
+
+ if (time_box->getVisible() && user_name_width <= mMinUserNameWidth)
+ {
+ time_box->setVisible(FALSE);
+
+ user_name_rect.mRight += time_box_width;
+ user_name->reshape(user_name_rect.getWidth(), user_name_rect.getHeight());
+ user_name->setRect(user_name_rect);
+ }
+
+ if (!time_box->getVisible() && user_name_width > mMinUserNameWidth + time_box_width)
+ {
+ user_name_rect.mRight -= time_box_width;
+ user_name->reshape(user_name_rect.getWidth(), user_name_rect.getHeight());
+ user_name->setRect(user_name_rect);
+
+ time_box->setVisible(TRUE);
+ }
+
+ LLPanel::draw();
+ }
+
+ void nameUpdatedCallback(const LLUUID& id,const std::string& first,const std::string& last,BOOL is_group)
+ {
+ if (id != mAvatarID)
+ return;
+ mFirstName = first;
+ mLastName = last;
+ }
+protected:
+ static const S32 PADDING = 20;
+
+ void showContextMenu(S32 x,S32 y)
+ {
+ if(mSourceType == CHAT_SOURCE_SYSTEM)
+ showSystemContextMenu(x,y);
+ if(mSourceType == CHAT_SOURCE_AGENT)
+ showAvatarContextMenu(x,y);
+ if(mSourceType == CHAT_SOURCE_OBJECT)
+ showObjectContextMenu(x,y);
+ }
+
+ void showSystemContextMenu(S32 x,S32 y)
+ {
+ }
+
+ void showObjectContextMenu(S32 x,S32 y)
+ {
+ LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandleObject.get();
+ if(menu)
+ LLMenuGL::showPopup(this, menu, x, y);
+ }
+
+ void showAvatarContextMenu(S32 x,S32 y)
+ {
+ LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandleAvatar.get();
+
+ if(menu)
+ {
+ bool is_friend = LLAvatarTracker::instance().getBuddyInfo(mAvatarID) != NULL;
+
+ menu->setItemEnabled("Add Friend", !is_friend);
+ menu->setItemEnabled("Remove Friend", is_friend);
+
+ if(gAgentID == mAvatarID)
+ {
+ menu->setItemEnabled("Add Friend", false);
+ menu->setItemEnabled("Send IM", false);
+ menu->setItemEnabled("Remove Friend", false);
+ }
+
+ menu->buildDrawLabels();
+ menu->updateParent(LLMenuGL::sMenuContainer);
+ LLMenuGL::showPopup(this, menu, x, y);
+ }
+ }
+
+private:
+ void setTimeField(const LLChat& chat)
+ {
+ LLTextBox* time_box = getChild<LLTextBox>("time_box");
+
+ LLRect rect_before = time_box->getRect();
+
+ time_box->setValue(chat.mTimeStr);
+
+ // set necessary textbox width to fit all text
+ time_box->reshapeToFitText();
+ LLRect rect_after = time_box->getRect();
+
+ // move rect to the left to correct position...
+ S32 delta_pos_x = rect_before.getWidth() - rect_after.getWidth();
+ S32 delta_pos_y = rect_before.getHeight() - rect_after.getHeight();
+ time_box->translate(delta_pos_x, delta_pos_y);
+
+ //... & change width of the name control
+ LLView* user_name = getChild<LLView>("user_name");
+ const LLRect& user_rect = user_name->getRect();
+ user_name->reshape(user_rect.getWidth() + delta_pos_x, user_rect.getHeight());
+ }
+
+protected:
+ LLHandle<LLView> mPopupMenuHandleAvatar;
+ LLHandle<LLView> mPopupMenuHandleObject;
+
+ LLUUID mAvatarID;
+ EChatSourceType mSourceType;
+ std::string mFirstName;
+ std::string mLastName;
+ std::string mFrom;
+
+ S32 mMinUserNameWidth;
+};
+
+
+LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)
+: LLUICtrl(p),
+ mMessageHeaderFilename(p.message_header),
+ mMessageSeparatorFilename(p.message_separator),
+ mLeftTextPad(p.left_text_pad),
+ mRightTextPad(p.right_text_pad),
+ mLeftWidgetPad(p.left_widget_pad),
+ mRightWidgetPad(p.right_widget_pad),
+ mTopSeparatorPad(p.top_separator_pad),
+ mBottomSeparatorPad(p.bottom_separator_pad),
+ mTopHeaderPad(p.top_header_pad),
+ mBottomHeaderPad(p.bottom_header_pad)
+{
+ LLTextEditor::Params editor_params(p);
+ editor_params.rect = getLocalRect();
+ editor_params.follows.flags = FOLLOWS_ALL;
+ editor_params.enabled = false; // read only
+ mEditor = LLUICtrlFactory::create<LLTextEditor>(editor_params, this);
+}
+
+LLChatHistory::~LLChatHistory()
+{
+ this->clear();
+}
+
+void LLChatHistory::initFromParams(const LLChatHistory::Params& p)
+{
+ static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+
+ LLRect stack_rect = getLocalRect();
+ stack_rect.mRight -= scrollbar_size;
+ LLLayoutStack::Params layout_p;
+ layout_p.rect = stack_rect;
+ layout_p.follows.flags = FOLLOWS_ALL;
+ layout_p.orientation = "vertical";
+ layout_p.mouse_opaque = false;
+
+ LLLayoutStack* stackp = LLUICtrlFactory::create<LLLayoutStack>(layout_p, this);
+
+ const S32 NEW_TEXT_NOTICE_HEIGHT = 20;
+
+ LLPanel::Params panel_p;
+ panel_p.name = "spacer";
+ panel_p.background_visible = false;
+ panel_p.has_border = false;
+ panel_p.mouse_opaque = false;
+ stackp->addPanel(LLUICtrlFactory::create<LLPanel>(panel_p), 0, 30, true, false, LLLayoutStack::ANIMATE);
+
+ panel_p.name = "new_text_notice_holder";
+ LLRect new_text_notice_rect = getLocalRect();
+ new_text_notice_rect.mTop = new_text_notice_rect.mBottom + NEW_TEXT_NOTICE_HEIGHT;
+ panel_p.rect = new_text_notice_rect;
+ panel_p.background_opaque = true;
+ panel_p.background_visible = true;
+ panel_p.visible = false;
+ mMoreChatPanel = LLUICtrlFactory::create<LLPanel>(panel_p);
+
+ LLTextBox::Params text_p(p.more_chat_text);
+ text_p.rect = mMoreChatPanel->getLocalRect();
+ text_p.follows.flags = FOLLOWS_ALL;
+ text_p.name = "more_chat_text";
+ mMoreChatText = LLUICtrlFactory::create<LLTextBox>(text_p, mMoreChatPanel);
+ mMoreChatText->setClickedCallback(boost::bind(&LLChatHistory::onClickMoreText, this));
+
+ stackp->addPanel(mMoreChatPanel, 0, 0, false, false, LLLayoutStack::ANIMATE);
+}
+
+
+/*void LLChatHistory::updateTextRect()
+{
+ static LLUICachedControl<S32> texteditor_border ("UITextEditorBorder", 0);
+
+ LLRect old_text_rect = mVisibleTextRect;
+ mVisibleTextRect = mScroller->getContentWindowRect();
+ mVisibleTextRect.stretch(-texteditor_border);
+ mVisibleTextRect.mLeft += mLeftTextPad;
+ mVisibleTextRect.mRight -= mRightTextPad;
+ if (mVisibleTextRect != old_text_rect)
+ {
+ needsReflow();
+ }
+}*/
+
+LLView* LLChatHistory::getSeparator()
+{
+ LLPanel* separator = LLUICtrlFactory::getInstance()->createFromFile<LLPanel>(mMessageSeparatorFilename, NULL, LLPanel::child_registry_t::instance());
+ return separator;
+}
+
+LLView* LLChatHistory::getHeader(const LLChat& chat,const LLStyle::Params& style_params)
+{
+ LLChatHistoryHeader* header = LLChatHistoryHeader::createInstance(mMessageHeaderFilename);
+ header->setup(chat,style_params);
+ return header;
+}
+
+void LLChatHistory::onClickMoreText()
+{
+ mEditor->endOfDoc();
+}
+
+void LLChatHistory::clear()
+{
+ mLastFromName.clear();
+ mEditor->clear();
+ mLastFromID = LLUUID::null;
+}
+
+void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_chat_history, const LLStyle::Params& input_append_params)
+{
+ if (!mEditor->scrolledToEnd() && chat.mFromID != gAgent.getID() && !chat.mFromName.empty())
+ {
+ mUnreadChatSources.insert(chat.mFromName);
+ mMoreChatPanel->setVisible(TRUE);
+ std::string chatters;
+ for (unread_chat_source_t::iterator it = mUnreadChatSources.begin();
+ it != mUnreadChatSources.end();)
+ {
+ chatters += *it;
+ if (++it != mUnreadChatSources.end())
+ {
+ chatters += ",";
+ }
+ }
+ LLStringUtil::format_map_t args;
+ args["SOURCES"] = chatters;
+
+ if (mUnreadChatSources.size() == 1)
+ {
+ mMoreChatText->setValue(LLTrans::getString("unread_chat_single", args));
+ }
+ else
+ {
+ mMoreChatText->setValue(LLTrans::getString("unread_chat_multiple", args));
+ }
+ S32 height = mMoreChatText->getTextPixelHeight() + 5;
+ mMoreChatPanel->reshape(mMoreChatPanel->getRect().getWidth(), height);
+ }
+
+ LLColor4 txt_color = LLUIColorTable::instance().getColor("White");
+ LLViewerChat::getChatColor(chat,txt_color);
+ LLFontGL* fontp = LLViewerChat::getChatFont();
+ std::string font_name = LLFontGL::nameFromFont(fontp);
+ std::string font_size = LLFontGL::sizeFromFont(fontp);
+ LLStyle::Params style_params;
+ style_params.color(txt_color);
+ style_params.readonly_color(txt_color);
+ style_params.font.name(font_name);
+ style_params.font.size(font_size);
+ style_params.font.style(input_append_params.font.style);
+
+ std::string prefix = chat.mText.substr(0, 4);
+
+ //IRC styled /me messages.
+ bool irc_me = prefix == "/me " || prefix == "/me'";
+
+ // Delimiter after a name in header copy/past and in plain text mode
+ std::string delimiter = (chat.mChatType != CHAT_TYPE_SHOUT && chat.mChatType != CHAT_TYPE_WHISPER)
+ ? ": "
+ : " ";
+
+ // Don't add any delimiter after name in irc styled messages
+ if (irc_me || chat.mChatStyle == CHAT_STYLE_IRC)
+ {
+ delimiter = LLStringUtil::null;
+ style_params.font.style = "ITALIC";
+ }
+
+ if (use_plain_text_chat_history)
+ {
+ mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getText().size() != 0, style_params);
+
+ if (utf8str_trim(chat.mFromName).size() != 0)
+ {
+ // Don't hotlink any messages from the system (e.g. "Second Life:"), so just add those in plain text.
+ if ( chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() )
+ {
+ LLStyle::Params link_params(style_params);
+ link_params.fillFrom(LLStyleMap::instance().lookupAgent(chat.mFromID));
+ // Convert the name to a hotlink and add to message.
+ mEditor->appendText(chat.mFromName + delimiter, false, link_params);
+ }
+ else
+ {
+ mEditor->appendText(chat.mFromName + delimiter, false, style_params);
+ }
+ }
+ }
+ else
+ {
+ LLView* view = NULL;
+ LLInlineViewSegment::Params p;
+ p.force_newline = true;
+ p.left_pad = mLeftWidgetPad;
+ p.right_pad = mRightWidgetPad;
+
+ LLDate new_message_time = LLDate::now();
+
+ if (mLastFromName == chat.mFromName
+ && mLastFromID == chat.mFromID
+ && mLastMessageTime.notNull()
+ && (new_message_time.secondsSinceEpoch() - mLastMessageTime.secondsSinceEpoch()) < 60.0
+ && mLastMessageTimeStr.size() == chat.mTimeStr.size()) //*HACK to distinguish between current and previous chat session's histories
+ {
+ view = getSeparator();
+ p.top_pad = mTopSeparatorPad;
+ p.bottom_pad = mBottomSeparatorPad;
+ }
+ else
+ {
+ view = getHeader(chat, style_params);
+ if (mEditor->getText().size() == 0)
+ p.top_pad = 0;
+ else
+ p.top_pad = mTopHeaderPad;
+ p.bottom_pad = mBottomHeaderPad;
+
+ }
+ p.view = view;
+
+ //Prepare the rect for the view
+ LLRect target_rect = mEditor->getDocumentView()->getRect();
+ // squeeze down the widget by subtracting padding off left and right
+ target_rect.mLeft += mLeftWidgetPad + mEditor->getHPad();
+ target_rect.mRight -= mRightWidgetPad;
+ view->reshape(target_rect.getWidth(), view->getRect().getHeight());
+ view->setOrigin(target_rect.mLeft, view->getRect().mBottom);
+
+ std::string widget_associated_text = "\n[" + chat.mTimeStr + "] ";
+ if (utf8str_trim(chat.mFromName).size() != 0 && chat.mFromName != SYSTEM_FROM)
+ widget_associated_text += chat.mFromName + delimiter;
+
+ mEditor->appendWidget(p, widget_associated_text, false);
+ mLastFromName = chat.mFromName;
+ mLastFromID = chat.mFromID;
+ mLastMessageTime = new_message_time;
+ mLastMessageTimeStr = chat.mTimeStr;
+ }
+
+ std::string message = irc_me ? chat.mText.substr(3) : chat.mText;
+ mEditor->appendText(message, FALSE, style_params);
+ mEditor->blockUndo();
+
+ // automatically scroll to end when receiving chat from myself
+ if (chat.mFromID == gAgentID)
+ {
+ mEditor->setCursorAndScrollToEnd();
+ }
+}
+
+void LLChatHistory::draw()
+{
+ if (mEditor->scrolledToEnd())
+ {
+ mUnreadChatSources.clear();
+ mMoreChatPanel->setVisible(FALSE);
+ }
+
+ LLUICtrl::draw();
+}
+
+void LLChatHistory::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ bool is_scrolled_to_end = mEditor->scrolledToEnd();
+ LLUICtrl::reshape( width, height, called_from_parent );
+ // update scroll
+ if (is_scrolled_to_end)
+ mEditor->setCursorAndScrollToEnd();
+}
diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h
new file mode 100644
index 0000000000..c2c60e60cf
--- /dev/null
+++ b/indra/newview/llchathistory.h
@@ -0,0 +1,150 @@
+/**
+ * @file llchathistory.h
+ * @brief LLTextEditor base class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLCHATHISTORY_H_
+#define LLCHATHISTORY_H_
+
+#include "lltexteditor.h"
+#include "lltextbox.h"
+#include "llviewerchat.h"
+
+//Chat log widget allowing addition of a message as a widget
+class LLChatHistory : public LLUICtrl
+{
+ public:
+ struct Params : public LLInitParam::Block<Params, LLTextEditor::Params>
+ {
+ //Message header filename
+ Optional<std::string> message_header;
+ //Message separator filename
+ Optional<std::string> message_separator;
+ //Text left padding from the scroll rect
+ Optional<S32> left_text_pad;
+ //Text right padding from the scroll rect
+ Optional<S32> right_text_pad;
+ //Widget left padding from the scroll rect
+ Optional<S32> left_widget_pad;
+ //Widget right padding from the scroll rect
+ Optional<S32> right_widget_pad;
+ //Separator top padding
+ Optional<S32> top_separator_pad;
+ //Separator bottom padding
+ Optional<S32> bottom_separator_pad;
+ //Header top padding
+ Optional<S32> top_header_pad;
+ //Header bottom padding
+ Optional<S32> bottom_header_pad;
+
+ Optional<LLTextBox::Params> more_chat_text;
+
+ Params()
+ : message_header("message_header"),
+ message_separator("message_separator"),
+ left_text_pad("left_text_pad"),
+ right_text_pad("right_text_pad"),
+ left_widget_pad("left_widget_pad"),
+ right_widget_pad("right_widget_pad"),
+ top_separator_pad("top_separator_pad"),
+ bottom_separator_pad("bottom_separator_pad"),
+ top_header_pad("top_header_pad"),
+ bottom_header_pad("bottom_header_pad"),
+ more_chat_text("more_chat_text")
+ {}
+
+ };
+ protected:
+ LLChatHistory(const Params&);
+ friend class LLUICtrlFactory;
+
+ /*virtual*/ void draw();
+ /**
+ * Redefinition of LLTextEditor::updateTextRect() to considerate text
+ * left/right padding params.
+ */
+ //virtual void updateTextRect();
+ /**
+ * Builds a message separator.
+ * @return pointer to LLView separator object.
+ */
+ LLView* getSeparator();
+ /**
+ * Builds a message header.
+ * @return pointer to LLView header object.
+ */
+ LLView* getHeader(const LLChat& chat,const LLStyle::Params& style_params);
+
+ void onClickMoreText();
+
+ public:
+ ~LLChatHistory();
+
+ void initFromParams(const Params&);
+
+ /**
+ * Appends a widget message.
+ * If last user appended message, concurs with current user,
+ * separator is added before the message, otherwise header is added.
+ * @param chat - base chat message.
+ * @param use_plain_text_chat_history - whether to add message as plain text.
+ * @param input_append_params - font style.
+ */
+ void appendMessage(const LLChat& chat, const bool use_plain_text_chat_history = false, const LLStyle::Params& input_append_params = LLStyle::Params());
+ /*virtual*/ void clear();
+ /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+ private:
+ std::string mLastFromName;
+ LLUUID mLastFromID;
+ LLDate mLastMessageTime;
+ std::string mLastMessageTimeStr;
+
+ std::string mMessageHeaderFilename;
+ std::string mMessageSeparatorFilename;
+
+ S32 mLeftTextPad;
+ S32 mRightTextPad;
+
+ S32 mLeftWidgetPad;
+ S32 mRightWidgetPad;
+
+ S32 mTopSeparatorPad;
+ S32 mBottomSeparatorPad;
+ S32 mTopHeaderPad;
+ S32 mBottomHeaderPad;
+
+ LLPanel* mMoreChatPanel;
+ LLTextBox* mMoreChatText;
+ LLTextEditor* mEditor;
+ typedef std::set<std::string> unread_chat_source_t;
+ unread_chat_source_t mUnreadChatSources;
+};
+#endif /* LLCHATHISTORY_H_ */
diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp
new file mode 100644
index 0000000000..f7f7ee83af
--- /dev/null
+++ b/indra/newview/llchatitemscontainerctrl.cpp
@@ -0,0 +1,327 @@
+/**
+ * @file llchatitemscontainer.cpp
+ * @brief chat history scrolling panel implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llchatitemscontainerctrl.h"
+#include "lltextbox.h"
+
+#include "llchatmsgbox.h"
+#include "llavatariconctrl.h"
+#include "llfloaterreg.h"
+#include "lllocalcliprect.h"
+#include "lltrans.h"
+
+#include "llviewercontrol.h"
+#include "llagentdata.h"
+
+static const S32 msg_left_offset = 10;
+static const S32 msg_right_offset = 10;
+static const S32 msg_height_pad = 5;
+
+//*******************************************************************************************************************
+//LLNearbyChatToastPanel
+//*******************************************************************************************************************
+
+LLNearbyChatToastPanel* LLNearbyChatToastPanel::createInstance()
+{
+ LLNearbyChatToastPanel* item = new LLNearbyChatToastPanel();
+ LLUICtrlFactory::getInstance()->buildPanel(item, "panel_chat_item.xml");
+ item->setFollows(FOLLOWS_NONE);
+ return item;
+}
+
+void LLNearbyChatToastPanel::reshape (S32 width, S32 height, BOOL called_from_parent )
+{
+ LLPanel::reshape(width, height,called_from_parent);
+
+ LLUICtrl* msg_text = getChild<LLUICtrl>("msg_text", false);
+ LLUICtrl* icon = getChild<LLUICtrl>("avatar_icon", false);
+
+ LLRect msg_text_rect = msg_text->getRect();
+ LLRect avatar_rect = icon->getRect();
+
+ avatar_rect.setLeftTopAndSize(2,height-2,avatar_rect.getWidth(),avatar_rect.getHeight());
+ icon->setRect(avatar_rect);
+
+
+ msg_text_rect.setLeftTopAndSize( avatar_rect.mRight + msg_left_offset,
+ height - msg_height_pad,
+ width - avatar_rect.mRight - msg_left_offset - msg_right_offset,
+ height - 2*msg_height_pad);
+ msg_text->reshape( msg_text_rect.getWidth(), msg_text_rect.getHeight(), 1);
+ msg_text->setRect(msg_text_rect);
+}
+
+BOOL LLNearbyChatToastPanel::postBuild()
+{
+ return LLPanel::postBuild();
+}
+
+void LLNearbyChatToastPanel::addMessage(LLSD& notification)
+{
+ std::string messageText = notification["message"].asString(); // UTF-8 line of text
+
+ LLChatMsgBox* msg_text = getChild<LLChatMsgBox>("msg_text", false);
+
+ std::string color_name = notification["text_color"].asString();
+
+ LLColor4 textColor = LLUIColorTable::instance().getColor(color_name);
+ textColor.mV[VALPHA] =notification["color_alpha"].asReal();
+
+ S32 font_size = notification["font_size"].asInteger();
+
+ LLFontGL* messageFont;
+ switch(font_size)
+ {
+ case 0: messageFont = LLFontGL::getFontSansSerifSmall(); break;
+ default:
+ case 1: messageFont = LLFontGL::getFontSansSerif(); break;
+ case 2: messageFont = LLFontGL::getFontSansSerifBig(); break;
+ }
+
+ //append text
+ {
+ LLStyle::Params style_params;
+ style_params.color(textColor);
+ std::string font_name = LLFontGL::nameFromFont(messageFont);
+ std::string font_style_size = LLFontGL::sizeFromFont(messageFont);
+ style_params.font.name(font_name);
+ style_params.font.size(font_style_size);
+
+ int chat_type = notification["chat_type"].asInteger();
+
+ if(notification["chat_style"].asInteger()== CHAT_STYLE_IRC)
+ {
+ style_params.font.style = "ITALIC";
+ }
+ else if( chat_type == CHAT_TYPE_SHOUT)
+ {
+ style_params.font.style = "BOLD";
+ }
+ else if( chat_type == CHAT_TYPE_WHISPER)
+ {
+ style_params.font.style = "ITALIC";
+ }
+ msg_text->appendText(messageText, TRUE, style_params);
+ }
+
+ snapToMessageHeight();
+
+}
+
+void LLNearbyChatToastPanel::init(LLSD& notification)
+{
+ std::string messageText = notification["message"].asString(); // UTF-8 line of text
+ std::string fromName = notification["from"].asString(); // agent or object name
+ mFromID = notification["from_id"].asUUID(); // agent id or object id
+
+ int sType = notification["source"].asInteger();
+ mSourceType = (EChatSourceType)sType;
+
+ std::string color_name = notification["text_color"].asString();
+
+ LLColor4 textColor = LLUIColorTable::instance().getColor(color_name);
+ textColor.mV[VALPHA] =notification["color_alpha"].asReal();
+
+ S32 font_size = notification["font_size"].asInteger();
+
+ LLFontGL* messageFont;
+ switch(font_size)
+ {
+ case 0: messageFont = LLFontGL::getFontSansSerifSmall(); break;
+ default:
+ case 1: messageFont = LLFontGL::getFontSansSerif(); break;
+ case 2: messageFont = LLFontGL::getFontSansSerifBig(); break;
+ }
+
+ LLChatMsgBox* msg_text = getChild<LLChatMsgBox>("msg_text", false);
+
+ msg_text->setText(std::string(""));
+
+ if ( notification["chat_style"].asInteger() != CHAT_STYLE_IRC )
+ {
+ std::string str_sender;
+
+ str_sender = fromName;
+
+ str_sender+=" ";
+
+ //append user name
+ {
+ LLStyle::Params style_params_name;
+
+ LLColor4 userNameColor = LLUIColorTable::instance().getColor("ChatToastAgentNameColor");
+
+ style_params_name.color(userNameColor);
+
+ std::string font_name = LLFontGL::nameFromFont(messageFont);
+ std::string font_style_size = LLFontGL::sizeFromFont(messageFont);
+ style_params_name.font.name(font_name);
+ style_params_name.font.size(font_style_size);
+
+ msg_text->appendText(str_sender, FALSE, style_params_name);
+
+ }
+ }
+
+ //append text
+ {
+ LLStyle::Params style_params;
+ style_params.color(textColor);
+ std::string font_name = LLFontGL::nameFromFont(messageFont);
+ std::string font_style_size = LLFontGL::sizeFromFont(messageFont);
+ style_params.font.name(font_name);
+ style_params.font.size(font_style_size);
+
+ int chat_type = notification["chat_type"].asInteger();
+
+ if(notification["chat_style"].asInteger()== CHAT_STYLE_IRC)
+ {
+ style_params.font.style = "ITALIC";
+ }
+ else if( chat_type == CHAT_TYPE_SHOUT)
+ {
+ style_params.font.style = "BOLD";
+ }
+ else if( chat_type == CHAT_TYPE_WHISPER)
+ {
+ style_params.font.style = "ITALIC";
+ }
+ msg_text->appendText(messageText, FALSE, style_params);
+ }
+
+
+ snapToMessageHeight();
+
+ mIsDirty = true;//will set Avatar Icon in draw
+}
+
+void LLNearbyChatToastPanel::snapToMessageHeight ()
+{
+ LLChatMsgBox* text_box = getChild<LLChatMsgBox>("msg_text", false);
+ S32 new_height = llmax (text_box->getTextPixelHeight() + 2*text_box->getVPad() + 2*msg_height_pad, 25);
+
+ LLRect panel_rect = getRect();
+
+ panel_rect.setLeftTopAndSize( panel_rect.mLeft, panel_rect.mTop, panel_rect.getWidth(), new_height);
+
+ reshape( getRect().getWidth(), getRect().getHeight(), 1);
+
+ setRect(panel_rect);
+
+}
+
+void LLNearbyChatToastPanel::onMouseLeave (S32 x, S32 y, MASK mask)
+{
+
+}
+void LLNearbyChatToastPanel::onMouseEnter (S32 x, S32 y, MASK mask)
+{
+ if(mSourceType != CHAT_SOURCE_AGENT)
+ return;
+}
+
+BOOL LLNearbyChatToastPanel::handleMouseDown (S32 x, S32 y, MASK mask)
+{
+ return LLPanel::handleMouseDown(x,y,mask);
+}
+
+BOOL LLNearbyChatToastPanel::handleMouseUp (S32 x, S32 y, MASK mask)
+{
+ if(mSourceType != CHAT_SOURCE_AGENT)
+ return LLPanel::handleMouseUp(x,y,mask);
+
+ LLChatMsgBox* text_box = getChild<LLChatMsgBox>("msg_text", false);
+ S32 local_x = x - text_box->getRect().mLeft;
+ S32 local_y = y - text_box->getRect().mBottom;
+
+ //if text_box process mouse up (ussually this is click on url) - we didn't show nearby_chat.
+ if (text_box->pointInView(local_x, local_y) )
+ {
+ if (text_box->handleMouseUp(local_x,local_y,mask) == TRUE)
+ return TRUE;
+ else
+ {
+ LLFloaterReg::showInstance("nearby_chat",LLSD());
+ return FALSE;
+ }
+ }
+
+ LLFloaterReg::showInstance("nearby_chat",LLSD());
+ return LLPanel::handleMouseUp(x,y,mask);
+}
+
+void LLNearbyChatToastPanel::setHeaderVisibility(EShowItemHeader e)
+{
+ LLUICtrl* icon = getChild<LLUICtrl>("avatar_icon", false);
+ if(icon)
+ icon->setVisible(e == CHATITEMHEADER_SHOW_ONLY_ICON || e==CHATITEMHEADER_SHOW_BOTH);
+
+}
+
+bool LLNearbyChatToastPanel::canAddText ()
+{
+ LLChatMsgBox* msg_text = findChild<LLChatMsgBox>("msg_text");
+ if(!msg_text)
+ return false;
+ return msg_text->getLineCount()<10;
+}
+
+BOOL LLNearbyChatToastPanel::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ LLUICtrl* avatar_icon = getChild<LLUICtrl>("avatar_icon", false);
+
+ S32 local_x = x - avatar_icon->getRect().mLeft;
+ S32 local_y = y - avatar_icon->getRect().mBottom;
+
+ //eat message for avatar icon if msg was from object
+ if(avatar_icon->pointInView(local_x, local_y) && mSourceType != CHAT_SOURCE_AGENT)
+ return TRUE;
+ return LLPanel::handleRightMouseDown(x,y,mask);
+}
+void LLNearbyChatToastPanel::draw()
+{
+ if(mIsDirty)
+ {
+ LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon", false);
+ if(icon)
+ {
+ icon->setDrawTooltip(mSourceType == CHAT_SOURCE_AGENT);
+ icon->setValue(mFromID);
+ }
+ mIsDirty = false;
+ }
+ LLToastPanelBase::draw();
+}
+
+
diff --git a/indra/newview/llchatitemscontainerctrl.h b/indra/newview/llchatitemscontainerctrl.h
new file mode 100644
index 0000000000..f4b8655054
--- /dev/null
+++ b/indra/newview/llchatitemscontainerctrl.h
@@ -0,0 +1,98 @@
+/**
+ * @file llchatitemscontainer.h
+ * @brief chat history scrolling panel implementation
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLCHATITEMSCONTAINER_H_
+#define LL_LLCHATITEMSCONTAINER_H_
+
+#include "llpanel.h"
+#include "llscrollbar.h"
+#include "string"
+#include "llviewerchat.h"
+#include "lltoastpanel.h"
+
+typedef enum e_show_item_header
+{
+ CHATITEMHEADER_SHOW_ONLY_NAME = 0,
+ CHATITEMHEADER_SHOW_ONLY_ICON = 1,
+ CHATITEMHEADER_SHOW_BOTH
+} EShowItemHeader;
+
+class LLNearbyChatToastPanel: public LLToastPanelBase
+{
+protected:
+ LLNearbyChatToastPanel():mIsDirty(false){};
+public:
+
+
+ ~LLNearbyChatToastPanel(){}
+
+ static LLNearbyChatToastPanel* createInstance();
+
+ const LLUUID& getFromID() const { return mFromID;}
+
+ //void addText (const std::string& message , const LLStyle::Params& input_params = LLStyle::Params());
+ //void setMessage (const LLChat& msg);
+ void snapToMessageHeight ();
+
+ bool canAddText ();
+
+ void onMouseLeave (S32 x, S32 y, MASK mask);
+ void onMouseEnter (S32 x, S32 y, MASK mask);
+ BOOL handleMouseDown (S32 x, S32 y, MASK mask);
+ BOOL handleMouseUp (S32 x, S32 y, MASK mask);
+
+ virtual BOOL postBuild();
+
+ void reshape (S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+ void setHeaderVisibility(EShowItemHeader e);
+ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+
+ virtual void init(LLSD& data);
+ virtual void addMessage(LLSD& data);
+
+ virtual void draw();
+
+ const LLUUID& messageID() const { return mFromID;}
+private:
+ LLUUID mFromID; // agent id or object id
+ EChatSourceType mSourceType;
+
+
+
+ bool mIsDirty;
+};
+
+
+#endif
+
+
diff --git a/indra/newview/llchatmsgbox.cpp b/indra/newview/llchatmsgbox.cpp
new file mode 100644
index 0000000000..bb0ec2db27
--- /dev/null
+++ b/indra/newview/llchatmsgbox.cpp
@@ -0,0 +1,98 @@
+/**
+ * @file llchatmsgbox.cpp
+ * @author Martin Reddy
+ * @brief chat history text box, able to show array of strings with separator
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llchatmsgbox.h"
+#include "llwindow.h"
+
+
+static LLDefaultChildRegistry::Register<LLChatMsgBox> r("text_chat");
+
+class ChatSeparator : public LLTextSegment
+{
+public:
+ ChatSeparator(S32 start, S32 end)
+ : LLTextSegment(start, end),
+ mEditor(NULL)
+ {}
+
+ /*virtual*/ void linkToDocument(class LLTextBase* editor)
+ {
+ mEditor = editor;
+ }
+
+ /*virtual*/ void unlinkFromDocument(class LLTextBase* editor)
+ {
+ mEditor = NULL;
+ }
+
+ /*virtual*/ S32 getWidth(S32 first_char, S32 num_chars) const
+ {
+ return mEditor->getDocumentView()->getRect().getWidth();
+ }
+
+ /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
+ {
+ gl_line_2d(draw_rect.mLeft + 5, draw_rect.getCenterY(), draw_rect.mRight - 5, draw_rect.getCenterY(), LLColor4::grey);
+ return draw_rect.getWidth();
+ }
+
+private:
+ LLTextBase* mEditor;
+};
+
+
+LLChatMsgBox::Params::Params() :
+ block_spacing("block_spacing", 10)
+{
+ line_spacing.pixels = 4;
+}
+
+LLChatMsgBox::LLChatMsgBox(const Params& p) :
+ LLTextBox(p),
+ mBlockSpacing(p.block_spacing)
+{}
+
+void LLChatMsgBox::addText( const LLStringExplicit& text , const LLStyle::Params& input_params )
+{
+ S32 length = getLength();
+ // if there is existing text, add a separator
+ if (length > 0)
+ {
+ // chat separator exists right before the null terminator
+ insertSegment(new ChatSeparator(length - 1, length - 1));
+ }
+ // prepend newline only if there is some existing text
+ appendText(text, length > 0, input_params);
+}
diff --git a/indra/newview/llchatmsgbox.h b/indra/newview/llchatmsgbox.h
new file mode 100644
index 0000000000..9e16616729
--- /dev/null
+++ b/indra/newview/llchatmsgbox.h
@@ -0,0 +1,71 @@
+/**
+ * @file llchatmsgbox.h
+ * @author Martin Reddy
+ * @brief chat history text box, able to show array of strings with separator
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLCHATMSGBOX_H
+#define LL_LLCHATMSGBOX_H
+
+#include "lltextbox.h"
+#include "lluictrl.h"
+#include "v4color.h"
+#include "llstring.h"
+
+///
+/// LLChatMsgBox provides a text box with support for multiple blocks
+/// of text that can be added incrementally. Each block of text is
+/// visual separated from the previous block (e.g., with a horizontal
+/// line).
+///
+class LLChatMsgBox :
+ public LLTextBox
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLTextBox::Params>
+ {
+ Optional<S32> block_spacing;
+
+ Params();
+ };
+
+protected:
+ LLChatMsgBox(const Params&);
+ friend class LLUICtrlFactory;
+
+public:
+ void addText(const LLStringExplicit &text, const LLStyle::Params& input_params = LLStyle::Params());
+
+private:
+ S32 mBlockSpacing;
+};
+
+#endif
+
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
new file mode 100644
index 0000000000..f1de4e2982
--- /dev/null
+++ b/indra/newview/llchiclet.cpp
@@ -0,0 +1,1984 @@
+/**
+ * @file llchiclet.cpp
+ * @brief LLChiclet class implementation
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h" // must be first include
+#include "llchiclet.h"
+
+#include "llagent.h"
+#include "llavataractions.h"
+#include "llbottomtray.h"
+#include "llgroupactions.h"
+#include "lliconctrl.h"
+#include "llimfloater.h"
+#include "llimview.h"
+#include "llfloaterreg.h"
+#include "lllocalcliprect.h"
+#include "llmenugl.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+#include "lloutputmonitorctrl.h"
+#include "llscriptfloater.h"
+#include "llspeakers.h"
+#include "lltextbox.h"
+#include "llvoiceclient.h"
+#include "llgroupmgr.h"
+#include "llnotificationmanager.h"
+#include "lltransientfloatermgr.h"
+#include "llsyswellwindow.h"
+
+static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel");
+static LLDefaultChildRegistry::Register<LLIMWellChiclet> t2_0("chiclet_im_well");
+static LLDefaultChildRegistry::Register<LLNotificationChiclet> t2("chiclet_notification");
+static LLDefaultChildRegistry::Register<LLIMP2PChiclet> t3("chiclet_im_p2p");
+static LLDefaultChildRegistry::Register<LLIMGroupChiclet> t4("chiclet_im_group");
+static LLDefaultChildRegistry::Register<LLAdHocChiclet> t5("chiclet_im_adhoc");
+static LLDefaultChildRegistry::Register<LLScriptChiclet> t6("chiclet_script");
+static LLDefaultChildRegistry::Register<LLInvOfferChiclet> t7("chiclet_offer");
+
+boost::signals2::signal<LLChiclet* (const LLUUID&),
+ LLIMChiclet::CollectChicletCombiner<std::list<LLChiclet*> > >
+ LLIMChiclet::sFindChicletsSignal;
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+/**
+ * Updates the Well's 'Lit' state to flash it when "new messages" are come.
+ *
+ * It gets callback which will be called 2*N times with passed period. See EXT-3147
+ */
+class LLSysWellChiclet::FlashToLitTimer : public LLEventTimer
+{
+public:
+ typedef boost::function<void()> callback_t;
+
+ /**
+ * Constructor.
+ *
+ * @param count - how many times callback should be called (twice to not change original state)
+ * @param period - how frequently callback should be called
+ * @param cb - callback to be called each tick
+ */
+ FlashToLitTimer(S32 count, F32 period, callback_t cb)
+ : LLEventTimer(period)
+ , mCallback(cb)
+ , mFlashCount(2 * count)
+ , mCurrentFlashCount(0)
+ {
+ mEventTimer.stop();
+ }
+
+ BOOL tick()
+ {
+ mCallback();
+
+ if (++mCurrentFlashCount == mFlashCount) mEventTimer.stop();
+ return FALSE;
+ }
+
+ void flash()
+ {
+ mCurrentFlashCount = 0;
+ mEventTimer.start();
+ }
+
+ void stopFlashing()
+ {
+ mEventTimer.stop();
+ }
+
+private:
+ callback_t mCallback;
+
+ /**
+ * How many times Well will blink.
+ */
+ S32 mFlashCount;
+ S32 mCurrentFlashCount;
+};
+
+LLSysWellChiclet::Params::Params()
+: button("button")
+, unread_notifications("unread_notifications")
+, max_displayed_count("max_displayed_count", 99)
+, flash_to_lit_count("flash_to_lit_count", 3)
+, flash_period("flash_period", 0.5F)
+{
+ button.name("button");
+ button.tab_stop(FALSE);
+ button.label(LLStringUtil::null);
+}
+
+LLSysWellChiclet::LLSysWellChiclet(const Params& p)
+: LLChiclet(p)
+, mButton(NULL)
+, mCounter(0)
+, mMaxDisplayedCount(p.max_displayed_count)
+, mIsNewMessagesState(false)
+, mFlashToLitTimer(NULL)
+, mContextMenu(NULL)
+{
+ LLButton::Params button_params = p.button;
+ mButton = LLUICtrlFactory::create<LLButton>(button_params);
+ addChild(mButton);
+
+ mFlashToLitTimer = new FlashToLitTimer(p.flash_to_lit_count, p.flash_period, boost::bind(&LLSysWellChiclet::changeLitState, this));
+}
+
+LLSysWellChiclet::~LLSysWellChiclet()
+{
+ delete mFlashToLitTimer;
+}
+
+void LLSysWellChiclet::setCounter(S32 counter)
+{
+ // do nothing if the same counter is coming. EXT-3678.
+ if (counter == mCounter) return;
+
+ // note same code in LLChicletNotificationCounterCtrl::setCounter(S32 counter)
+ std::string s_count;
+ if(counter != 0)
+ {
+ static std::string more_messages_exist("+");
+ std::string more_messages(counter > mMaxDisplayedCount ? more_messages_exist : "");
+ s_count = llformat("%d%s"
+ , llmin(counter, mMaxDisplayedCount)
+ , more_messages.c_str()
+ );
+ }
+
+ mButton->setLabel(s_count);
+
+ setNewMessagesState(counter > mCounter);
+
+ // we have to flash to 'Lit' state each time new unread message is coming.
+ if (counter > mCounter)
+ {
+ mFlashToLitTimer->flash();
+ }
+ else if (counter == 0)
+ {
+ // if notification is resolved while well is flashing it can leave in the 'Lit' state
+ // when flashing finishes itself. Let break flashing here.
+ mFlashToLitTimer->stopFlashing();
+ }
+
+ mCounter = counter;
+}
+
+boost::signals2::connection LLSysWellChiclet::setClickCallback(
+ const commit_callback_t& cb)
+{
+ return mButton->setClickedCallback(cb);
+}
+
+void LLSysWellChiclet::setToggleState(BOOL toggled) {
+ mButton->setToggleState(toggled);
+}
+
+void LLSysWellChiclet::changeLitState()
+{
+ setNewMessagesState(!mIsNewMessagesState);
+}
+
+void LLSysWellChiclet::setNewMessagesState(bool new_messages)
+{
+ /*
+ Emulate 4 states of button by background images, see detains in EXT-3147
+ xml attribute Description
+ image_unselected "Unlit" - there are no new messages
+ image_selected "Unlit" + "Selected" - there are no new messages and the Well is open
+ image_pressed "Lit" - there are new messages
+ image_pressed_selected "Lit" + "Selected" - there are new messages and the Well is open
+ */
+ mButton->setForcePressedState(new_messages);
+
+ mIsNewMessagesState = new_messages;
+}
+
+void LLSysWellChiclet::updateWidget(bool is_window_empty)
+{
+ mButton->setEnabled(!is_window_empty);
+}
+// virtual
+BOOL LLSysWellChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ if(!mContextMenu)
+ {
+ createMenu();
+ }
+ if (mContextMenu)
+ {
+ mContextMenu->show(x, y);
+ LLMenuGL::showPopup(this, mContextMenu, x, y);
+ }
+ return TRUE;
+}
+
+/************************************************************************/
+/* LLIMWellChiclet implementation */
+/************************************************************************/
+LLIMWellChiclet::LLIMWellChiclet(const Params& p)
+: LLSysWellChiclet(p)
+{
+ LLIMModel::instance().addNewMsgCallback(boost::bind(&LLIMWellChiclet::messageCountChanged, this, _1));
+ LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(&LLIMWellChiclet::messageCountChanged, this, _1));
+
+ LLIMMgr::getInstance()->addSessionObserver(this);
+
+ LLIMWellWindow::getInstance()->setSysWellChiclet(this);
+}
+
+LLIMWellChiclet::~LLIMWellChiclet()
+{
+ LLIMMgr::getInstance()->removeSessionObserver(this);
+}
+
+void LLIMWellChiclet::onMenuItemClicked(const LLSD& user_data)
+{
+ std::string action = user_data.asString();
+ if("close all" == action)
+ {
+ LLIMWellWindow::getInstance()->closeAll();
+ }
+}
+
+bool LLIMWellChiclet::enableMenuItem(const LLSD& user_data)
+{
+ std::string item = user_data.asString();
+ if (item == "can close all")
+ {
+ return !LLIMWellWindow::getInstance()->isWindowEmpty();
+ }
+ return true;
+}
+
+void LLIMWellChiclet::createMenu()
+{
+ if(mContextMenu)
+ {
+ llwarns << "Menu already exists" << llendl;
+ return;
+ }
+
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("IMWellChicletMenu.Action",
+ boost::bind(&LLIMWellChiclet::onMenuItemClicked, this, _2));
+
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+ enable_registrar.add("IMWellChicletMenu.EnableItem",
+ boost::bind(&LLIMWellChiclet::enableMenuItem, this, _2));
+
+ mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>
+ ("menu_im_well_button.xml",
+ LLMenuGL::sMenuContainer,
+ LLViewerMenuHolderGL::child_registry_t::instance());
+}
+
+void LLIMWellChiclet::messageCountChanged(const LLSD& session_data)
+{
+ setCounter(LLBottomTray::getInstance()->getTotalUnreadIMCount());
+}
+
+/************************************************************************/
+/* LLNotificationChiclet implementation */
+/************************************************************************/
+LLNotificationChiclet::LLNotificationChiclet(const Params& p)
+: LLSysWellChiclet(p)
+, mUreadSystemNotifications(0)
+{
+ // connect counter handlers to the signals
+ connectCounterUpdatersToSignal("notify");
+ connectCounterUpdatersToSignal("groupnotify");
+ connectCounterUpdatersToSignal("offer");
+
+ // ensure that notification well window exists, to synchronously
+ // handle toast add/delete events.
+ LLNotificationWellWindow::getInstance()->setSysWellChiclet(this);
+}
+
+void LLNotificationChiclet::connectCounterUpdatersToSignal(const std::string& notification_type)
+{
+ LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance();
+ LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type);
+ if(n_handler)
+ {
+ n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this));
+ n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::decUreadSystemNotifications, this));
+ }
+}
+
+void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data)
+{
+ std::string action = user_data.asString();
+ if("close all" == action)
+ {
+ LLNotificationWellWindow::getInstance()->closeAll();
+ }
+}
+
+bool LLNotificationChiclet::enableMenuItem(const LLSD& user_data)
+{
+ std::string item = user_data.asString();
+ if (item == "can close all")
+ {
+ return mUreadSystemNotifications != 0;
+ }
+ return true;
+}
+
+void LLNotificationChiclet::createMenu()
+{
+ if(mContextMenu)
+ {
+ llwarns << "Menu already exists" << llendl;
+ return;
+ }
+
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("NotificationWellChicletMenu.Action",
+ boost::bind(&LLNotificationChiclet::onMenuItemClicked, this, _2));
+
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+ enable_registrar.add("NotificationWellChicletMenu.EnableItem",
+ boost::bind(&LLNotificationChiclet::enableMenuItem, this, _2));
+
+ mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>
+ ("menu_notification_well_button.xml",
+ LLMenuGL::sMenuContainer,
+ LLViewerMenuHolderGL::child_registry_t::instance());
+}
+
+/*virtual*/
+void LLNotificationChiclet::setCounter(S32 counter)
+{
+ LLSysWellChiclet::setCounter(counter);
+ updateWidget(getCounter() == 0);
+
+}
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLChiclet::Params::Params()
+ : show_counter("show_counter", true)
+ , enable_counter("enable_counter", false)
+{
+}
+
+LLChiclet::LLChiclet(const Params& p)
+: LLUICtrl(p)
+, mSessionId(LLUUID::null)
+, mShowCounter(p.show_counter)
+{
+
+}
+
+LLChiclet::~LLChiclet()
+{
+
+}
+
+boost::signals2::connection LLChiclet::setLeftButtonClickCallback(
+ const commit_callback_t& cb)
+{
+ return setCommitCallback(cb);
+}
+
+BOOL LLChiclet::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ onCommit();
+ childrenHandleMouseDown(x,y,mask);
+ return TRUE;
+}
+
+boost::signals2::connection LLChiclet::setChicletSizeChangedCallback(
+ const chiclet_size_changed_callback_t& cb)
+{
+ return mChicletSizeChangedSignal.connect(cb);
+}
+
+void LLChiclet::onChicletSizeChanged()
+{
+ mChicletSizeChangedSignal(this, getValue());
+}
+
+LLSD LLChiclet::getValue() const
+{
+ return LLSD(getSessionId());
+}
+
+void LLChiclet::setValue(const LLSD& value)
+{
+ if(value.isUUID())
+ setSessionId(value.asUUID());
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p)
+: LLChiclet(p)
+, mShowSpeaker(false)
+, mDefaultWidth(p.rect().getWidth())
+, mNewMessagesIcon(NULL)
+, mSpeakerCtrl(NULL)
+, mCounterCtrl(NULL)
+, mChicletButton(NULL)
+{
+ enableCounterControl(p.enable_counter);
+}
+
+void LLIMChiclet::setShowSpeaker(bool show)
+{
+ bool needs_resize = getShowSpeaker() != show;
+ if(needs_resize)
+ {
+ mShowSpeaker = show;
+ toggleSpeakerControl();
+ }
+}
+
+void LLIMChiclet::enableCounterControl(bool enable)
+{
+ mCounterEnabled = enable;
+ if(!enable)
+ {
+ LLChiclet::setShowCounter(false);
+ }
+}
+
+void LLIMChiclet::setShowCounter(bool show)
+{
+ if(!mCounterEnabled)
+ {
+ return;
+ }
+
+ bool needs_resize = getShowCounter() != show;
+ if(needs_resize)
+ {
+ LLChiclet::setShowCounter(show);
+ toggleCounterControl();
+ }
+}
+
+void LLIMChiclet::initSpeakerControl()
+{
+ // virtual
+}
+
+void LLIMChiclet::setRequiredWidth()
+{
+ bool show_speaker = getShowSpeaker();
+ bool show_counter = getShowCounter();
+ S32 required_width = mDefaultWidth;
+
+ if (show_counter)
+ {
+ required_width += mCounterCtrl->getRect().getWidth();
+ }
+ if (show_speaker)
+ {
+ required_width += mSpeakerCtrl->getRect().getWidth();
+ }
+
+ reshape(required_width, getRect().getHeight());
+
+ onChicletSizeChanged();
+}
+
+void LLIMChiclet::toggleSpeakerControl()
+{
+ if(getShowSpeaker())
+ {
+ // move speaker to the right of chiclet icon
+ LLRect speaker_rc = mSpeakerCtrl->getRect();
+ speaker_rc.setLeftTopAndSize(mDefaultWidth, speaker_rc.mTop, speaker_rc.getWidth(), speaker_rc.getHeight());
+ mSpeakerCtrl->setRect(speaker_rc);
+
+ if(getShowCounter())
+ {
+ // move speaker to the right of counter
+ mSpeakerCtrl->translate(mCounterCtrl->getRect().getWidth(), 0);
+ }
+
+ initSpeakerControl();
+ }
+
+ setRequiredWidth();
+ mSpeakerCtrl->setVisible(getShowSpeaker());
+}
+
+void LLIMChiclet::setCounter(S32 counter)
+{
+ if (mCounterCtrl->getCounter() == counter)
+ {
+ return;
+ }
+
+ mCounterCtrl->setCounter(counter);
+ setShowCounter(counter);
+ setShowNewMessagesIcon(counter);
+}
+
+void LLIMChiclet::toggleCounterControl()
+{
+ setRequiredWidth();
+ mCounterCtrl->setVisible(getShowCounter());
+}
+
+void LLIMChiclet::setShowNewMessagesIcon(bool show)
+{
+ if(mNewMessagesIcon)
+ {
+ mNewMessagesIcon->setVisible(show);
+ }
+ setRequiredWidth();
+}
+
+bool LLIMChiclet::getShowNewMessagesIcon()
+{
+ return mNewMessagesIcon->getVisible();
+}
+
+void LLIMChiclet::onMouseDown()
+{
+ LLIMFloater::toggle(getSessionId());
+ setCounter(0);
+}
+
+void LLIMChiclet::setToggleState(bool toggle)
+{
+ mChicletButton->setToggleState(toggle);
+}
+
+BOOL LLIMChiclet::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ onMouseDown();
+ return LLChiclet::handleMouseDown(x, y, mask);
+}
+
+void LLIMChiclet::draw()
+{
+ LLUICtrl::draw();
+}
+
+// static
+LLIMChiclet::EType LLIMChiclet::getIMSessionType(const LLUUID& session_id)
+{
+ EType type = TYPE_UNKNOWN;
+
+ if(session_id.isNull())
+ return type;
+
+ EInstantMessage im_type = LLIMModel::getInstance()->getType(session_id);
+ if (IM_COUNT == im_type)
+ {
+ llassert_always(0 && "IM session not found"); // should never happen
+ return type;
+ }
+
+ switch(im_type)
+ {
+ case IM_NOTHING_SPECIAL:
+ case IM_SESSION_P2P_INVITE:
+ type = TYPE_IM;
+ break;
+ case IM_SESSION_GROUP_START:
+ case IM_SESSION_INVITE:
+ if (gAgent.isInGroup(session_id))
+ {
+ type = TYPE_GROUP;
+ }
+ else
+ {
+ type = TYPE_AD_HOC;
+ }
+ break;
+ case IM_SESSION_CONFERENCE_START:
+ type = TYPE_AD_HOC;
+ default:
+ break;
+ }
+
+ return type;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLIMP2PChiclet::Params::Params()
+: avatar_icon("avatar_icon")
+, chiclet_button("chiclet_button")
+, unread_notifications("unread_notifications")
+, speaker("speaker")
+, new_message_icon("new_message_icon")
+, show_speaker("show_speaker")
+{
+}
+
+LLIMP2PChiclet::LLIMP2PChiclet(const Params& p)
+: LLIMChiclet(p)
+, mChicletIconCtrl(NULL)
+, mPopupMenu(NULL)
+{
+ LLButton::Params button_params = p.chiclet_button;
+ mChicletButton = LLUICtrlFactory::create<LLButton>(button_params);
+ addChild(mChicletButton);
+
+ LLIconCtrl::Params new_msg_params = p.new_message_icon;
+ mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params);
+ addChild(mNewMessagesIcon);
+
+ LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon;
+ mChicletIconCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params);
+ addChild(mChicletIconCtrl);
+
+ LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications;
+ mCounterCtrl = LLUICtrlFactory::create<LLChicletNotificationCounterCtrl>(unread_params);
+ addChild(mCounterCtrl);
+
+ setCounter(getCounter());
+ setShowCounter(getShowCounter());
+
+ LLChicletSpeakerCtrl::Params speaker_params = p.speaker;
+ mSpeakerCtrl = LLUICtrlFactory::create<LLChicletSpeakerCtrl>(speaker_params);
+ addChild(mSpeakerCtrl);
+
+ sendChildToFront(mNewMessagesIcon);
+ setShowSpeaker(p.show_speaker);
+}
+
+void LLIMP2PChiclet::initSpeakerControl()
+{
+ mSpeakerCtrl->setSpeakerId(getOtherParticipantId());
+}
+
+void LLIMP2PChiclet::setOtherParticipantId(const LLUUID& other_participant_id)
+{
+ LLIMChiclet::setOtherParticipantId(other_participant_id);
+ mChicletIconCtrl->setValue(getOtherParticipantId());
+}
+
+void LLIMP2PChiclet::updateMenuItems()
+{
+ if(!mPopupMenu)
+ return;
+ if(getSessionId().isNull())
+ return;
+
+ LLIMFloater* open_im_floater = LLIMFloater::findInstance(getSessionId());
+ bool open_window_exists = open_im_floater && open_im_floater->getVisible();
+ mPopupMenu->getChild<LLUICtrl>("Send IM")->setEnabled(!open_window_exists);
+
+ bool is_friend = LLAvatarActions::isFriend(getOtherParticipantId());
+ mPopupMenu->getChild<LLUICtrl>("Add Friend")->setEnabled(!is_friend);
+}
+
+BOOL LLIMP2PChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ if(!mPopupMenu)
+ {
+ createPopupMenu();
+ }
+
+ if (mPopupMenu)
+ {
+ updateMenuItems();
+ mPopupMenu->arrangeAndClear();
+ LLMenuGL::showPopup(this, mPopupMenu, x, y);
+ }
+
+ return TRUE;
+}
+
+void LLIMP2PChiclet::createPopupMenu()
+{
+ if(mPopupMenu)
+ {
+ llwarns << "Menu already exists" << llendl;
+ return;
+ }
+ if(getSessionId().isNull())
+ {
+ return;
+ }
+
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("IMChicletMenu.Action", boost::bind(&LLIMP2PChiclet::onMenuItemClicked, this, _2));
+
+ mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>
+ ("menu_imchiclet_p2p.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+}
+
+void LLIMP2PChiclet::onMenuItemClicked(const LLSD& user_data)
+{
+ std::string level = user_data.asString();
+ LLUUID other_participant_id = getOtherParticipantId();
+
+ if("profile" == level)
+ {
+ LLAvatarActions::showProfile(other_participant_id);
+ }
+ else if("im" == level)
+ {
+ LLAvatarActions::startIM(other_participant_id);
+ }
+ else if("add" == level)
+ {
+ LLAvatarActions::requestFriendshipDialog(other_participant_id);
+ }
+ else if("end" == level)
+ {
+ LLAvatarActions::endIM(other_participant_id);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLAdHocChiclet::Params::Params()
+: avatar_icon("avatar_icon")
+, chiclet_button("chiclet_button")
+, unread_notifications("unread_notifications")
+, speaker("speaker")
+, new_message_icon("new_message_icon")
+, show_speaker("show_speaker")
+, avatar_icon_color("avatar_icon_color", LLColor4::green)
+{
+}
+
+LLAdHocChiclet::LLAdHocChiclet(const Params& p)
+: LLIMChiclet(p)
+, mChicletIconCtrl(NULL)
+, mPopupMenu(NULL)
+{
+ LLButton::Params button_params = p.chiclet_button;
+ mChicletButton = LLUICtrlFactory::create<LLButton>(button_params);
+ addChild(mChicletButton);
+
+ LLIconCtrl::Params new_msg_params = p.new_message_icon;
+ mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params);
+ addChild(mNewMessagesIcon);
+
+ LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon;
+ mChicletIconCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params);
+ //Make the avatar modified
+ mChicletIconCtrl->setColor(p.avatar_icon_color);
+ addChild(mChicletIconCtrl);
+
+ LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications;
+ mCounterCtrl = LLUICtrlFactory::create<LLChicletNotificationCounterCtrl>(unread_params);
+ addChild(mCounterCtrl);
+
+ setCounter(getCounter());
+ setShowCounter(getShowCounter());
+
+ LLChicletSpeakerCtrl::Params speaker_params = p.speaker;
+ mSpeakerCtrl = LLUICtrlFactory::create<LLChicletSpeakerCtrl>(speaker_params);
+ addChild(mSpeakerCtrl);
+
+ sendChildToFront(mNewMessagesIcon);
+ setShowSpeaker(p.show_speaker);
+}
+
+void LLAdHocChiclet::setSessionId(const LLUUID& session_id)
+{
+ LLChiclet::setSessionId(session_id);
+ LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id);
+ mChicletIconCtrl->setValue(im_session->mOtherParticipantID);
+}
+
+void LLAdHocChiclet::draw()
+{
+ switchToCurrentSpeaker();
+ LLIMChiclet::draw();
+}
+
+void LLAdHocChiclet::initSpeakerControl()
+{
+ switchToCurrentSpeaker();
+}
+
+void LLAdHocChiclet::switchToCurrentSpeaker()
+{
+ LLUUID speaker_id;
+ LLSpeakerMgr::speaker_list_t speaker_list;
+
+ LLIMModel::getInstance()->findIMSession(getSessionId())->mSpeakers->getSpeakerList(&speaker_list, FALSE);
+ for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i)
+ {
+ LLPointer<LLSpeaker> s = *i;
+ if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING)
+ {
+ speaker_id = s->mID;
+ break;
+ }
+ }
+
+ mSpeakerCtrl->setSpeakerId(speaker_id);
+}
+
+void LLAdHocChiclet::createPopupMenu()
+{
+ if(mPopupMenu)
+ {
+ llwarns << "Menu already exists" << llendl;
+ return;
+ }
+ if(getSessionId().isNull())
+ {
+ return;
+ }
+
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("IMChicletMenu.Action", boost::bind(&LLAdHocChiclet::onMenuItemClicked, this, _2));
+
+ mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>
+ ("menu_imchiclet_adhoc.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+}
+
+void LLAdHocChiclet::onMenuItemClicked(const LLSD& user_data)
+{
+ std::string level = user_data.asString();
+ LLUUID group_id = getSessionId();
+
+ if("end" == level)
+ {
+ LLGroupActions::endIM(group_id);
+ }
+}
+
+BOOL LLAdHocChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ if(!mPopupMenu)
+ {
+ createPopupMenu();
+ }
+
+ if (mPopupMenu)
+ {
+ mPopupMenu->arrangeAndClear();
+ LLMenuGL::showPopup(this, mPopupMenu, x, y);
+ }
+
+ return TRUE;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLIMGroupChiclet::Params::Params()
+: group_icon("group_icon")
+, chiclet_button("chiclet_button")
+, unread_notifications("unread_notifications")
+, speaker("speaker")
+, new_message_icon("new_message_icon")
+, show_speaker("show_speaker")
+{
+}
+
+LLIMGroupChiclet::LLIMGroupChiclet(const Params& p)
+: LLIMChiclet(p)
+, LLGroupMgrObserver(LLUUID::null)
+, mChicletIconCtrl(NULL)
+, mPopupMenu(NULL)
+{
+ LLButton::Params button_params = p.chiclet_button;
+ mChicletButton = LLUICtrlFactory::create<LLButton>(button_params);
+ addChild(mChicletButton);
+
+ LLIconCtrl::Params new_msg_params = p.new_message_icon;
+ mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params);
+ addChild(mNewMessagesIcon);
+
+ LLChicletGroupIconCtrl::Params avatar_params = p.group_icon;
+ mChicletIconCtrl = LLUICtrlFactory::create<LLChicletGroupIconCtrl>(avatar_params);
+ addChild(mChicletIconCtrl);
+
+ LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications;
+ mCounterCtrl = LLUICtrlFactory::create<LLChicletNotificationCounterCtrl>(unread_params);
+ addChild(mCounterCtrl);
+
+ setCounter(getCounter());
+ setShowCounter(getShowCounter());
+
+ LLChicletSpeakerCtrl::Params speaker_params = p.speaker;
+ mSpeakerCtrl = LLUICtrlFactory::create<LLChicletSpeakerCtrl>(speaker_params);
+ addChild(mSpeakerCtrl);
+
+ sendChildToFront(mNewMessagesIcon);
+ setShowSpeaker(p.show_speaker);
+}
+
+LLIMGroupChiclet::~LLIMGroupChiclet()
+{
+ LLGroupMgr::getInstance()->removeObserver(this);
+}
+
+void LLIMGroupChiclet::draw()
+{
+ switchToCurrentSpeaker();
+ LLIMChiclet::draw();
+}
+
+void LLIMGroupChiclet::initSpeakerControl()
+{
+ switchToCurrentSpeaker();
+}
+
+void LLIMGroupChiclet::switchToCurrentSpeaker()
+{
+ LLUUID speaker_id;
+ LLSpeakerMgr::speaker_list_t speaker_list;
+
+ LLIMModel::getInstance()->findIMSession(getSessionId())->mSpeakers->getSpeakerList(&speaker_list, FALSE);
+ for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i)
+ {
+ LLPointer<LLSpeaker> s = *i;
+ if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING)
+ {
+ speaker_id = s->mID;
+ break;
+ }
+ }
+
+ mSpeakerCtrl->setSpeakerId(speaker_id);
+}
+
+void LLIMGroupChiclet::setSessionId(const LLUUID& session_id)
+{
+ LLChiclet::setSessionId(session_id);
+
+ LLGroupMgr* grp_mgr = LLGroupMgr::getInstance();
+ LLGroupMgrGroupData* group_data = grp_mgr->getGroupData(session_id);
+ if (group_data && group_data->mInsigniaID.notNull())
+ {
+ mChicletIconCtrl->setValue(group_data->mInsigniaID);
+ }
+ else
+ {
+ if(getSessionId() != mID)
+ {
+ grp_mgr->removeObserver(this);
+ mID = getSessionId();
+ grp_mgr->addObserver(this);
+ }
+ grp_mgr->sendGroupPropertiesRequest(session_id);
+ }
+}
+
+void LLIMGroupChiclet::changed(LLGroupChange gc)
+{
+ if (GC_PROPERTIES == gc)
+ {
+ LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(getSessionId());
+ if (group_data)
+ {
+ mChicletIconCtrl->setValue(group_data->mInsigniaID);
+ }
+ }
+}
+
+void LLIMGroupChiclet::updateMenuItems()
+{
+ if(!mPopupMenu)
+ return;
+ if(getSessionId().isNull())
+ return;
+
+ LLIMFloater* open_im_floater = LLIMFloater::findInstance(getSessionId());
+ bool open_window_exists = open_im_floater && open_im_floater->getVisible();
+ mPopupMenu->getChild<LLUICtrl>("Chat")->setEnabled(!open_window_exists);
+}
+
+BOOL LLIMGroupChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ if(!mPopupMenu)
+ {
+ createPopupMenu();
+ }
+
+ if (mPopupMenu)
+ {
+ updateMenuItems();
+ mPopupMenu->arrangeAndClear();
+ LLMenuGL::showPopup(this, mPopupMenu, x, y);
+ }
+
+ return TRUE;
+}
+
+void LLIMGroupChiclet::createPopupMenu()
+{
+ if(mPopupMenu)
+ {
+ llwarns << "Menu already exists" << llendl;
+ return;
+ }
+ if(getSessionId().isNull())
+ {
+ return;
+ }
+
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("IMChicletMenu.Action", boost::bind(&LLIMGroupChiclet::onMenuItemClicked, this, _2));
+
+ mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>
+ ("menu_imchiclet_group.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+}
+
+void LLIMGroupChiclet::onMenuItemClicked(const LLSD& user_data)
+{
+ std::string level = user_data.asString();
+ LLUUID group_id = getSessionId();
+
+ if("group chat" == level)
+ {
+ LLGroupActions::startIM(group_id);
+ }
+ else if("info" == level)
+ {
+ LLGroupActions::show(group_id);
+ }
+ else if("end" == level)
+ {
+ LLGroupActions::endIM(group_id);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLChicletPanel::Params::Params()
+: chiclet_padding("chiclet_padding")
+, scrolling_offset("scrolling_offset")
+, scroll_button_hpad("scroll_button_hpad")
+, scroll_ratio("scroll_ratio")
+, min_width("min_width")
+{
+};
+
+LLChicletPanel::LLChicletPanel(const Params&p)
+: LLPanel(p)
+, mScrollArea(NULL)
+, mLeftScrollButton(NULL)
+, mRightScrollButton(NULL)
+, mChicletPadding(p.chiclet_padding)
+, mScrollingOffset(p.scrolling_offset)
+, mScrollButtonHPad(p.scroll_button_hpad)
+, mScrollRatio(p.scroll_ratio)
+, mMinWidth(p.min_width)
+, mShowControls(true)
+{
+ LLPanel::Params panel_params;
+ panel_params.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT);
+ mScrollArea = LLUICtrlFactory::create<LLPanel>(panel_params,this);
+
+ // important for Show/Hide Camera and Move controls menu in bottom tray to work properly
+ mScrollArea->setMouseOpaque(false);
+
+ addChild(mScrollArea);
+}
+
+LLChicletPanel::~LLChicletPanel()
+{
+ LLTransientFloaterMgr::getInstance()->removeControlView(mLeftScrollButton);
+ LLTransientFloaterMgr::getInstance()->removeControlView(mRightScrollButton);
+
+}
+
+void im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){
+
+ LLUUID session_id = data["session_id"].asUUID();
+ S32 unread = data["participant_unread"].asInteger();
+
+ LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+ if (im_floater && im_floater->getVisible())
+ {
+ unread = 0;
+ }
+
+ std::list<LLChiclet*> chiclets = LLIMChiclet::sFindChicletsSignal(session_id);
+ std::list<LLChiclet *>::iterator iter;
+ for (iter = chiclets.begin(); iter != chiclets.end(); iter++) {
+ LLChiclet* chiclet = *iter;
+ if (chiclet != NULL)
+ {
+ chiclet->setCounter(unread);
+ }
+ else
+ {
+ llwarns << "Unable to set counter for chiclet " << session_id << llendl;
+ }
+ }
+}
+
+void object_chiclet_callback(const LLSD& data)
+{
+ LLUUID object_id = data["object_id"];
+ bool new_message = data["new_message"];
+
+ std::list<LLChiclet*> chiclets = LLIMChiclet::sFindChicletsSignal(object_id);
+ std::list<LLChiclet *>::iterator iter;
+ for (iter = chiclets.begin(); iter != chiclets.end(); iter++)
+ {
+ LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*iter);
+ if (chiclet != NULL)
+ {
+ if(data.has("unread"))
+ {
+ chiclet->setCounter(data["unread"]);
+ }
+ chiclet->setShowNewMessagesIcon(new_message);
+ }
+ }
+}
+
+BOOL LLChicletPanel::postBuild()
+{
+ LLPanel::postBuild();
+ LLIMModel::instance().addNewMsgCallback(boost::bind(im_chiclet_callback, this, _1));
+ LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(im_chiclet_callback, this, _1));
+ LLScriptFloaterManager::getInstance()->addNewObjectCallback(boost::bind(object_chiclet_callback, _1));
+ LLScriptFloaterManager::getInstance()->addToggleObjectFloaterCallback(boost::bind(object_chiclet_callback, _1));
+ LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLChicletPanel::findChiclet<LLChiclet>, this, _1));
+ LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLChicletPanel::onCurrentVoiceChannelChanged, this, _1));
+
+ mLeftScrollButton=getChild<LLButton>("chicklet_left_scroll_button");
+ LLTransientFloaterMgr::getInstance()->addControlView(mLeftScrollButton);
+ mLeftScrollButton->setMouseDownCallback(boost::bind(&LLChicletPanel::onLeftScrollClick,this));
+ mLeftScrollButton->setHeldDownCallback(boost::bind(&LLChicletPanel::onLeftScrollHeldDown,this));
+ mLeftScrollButton->setEnabled(false);
+
+ mRightScrollButton=getChild<LLButton>("chicklet_right_scroll_button");
+ LLTransientFloaterMgr::getInstance()->addControlView(mRightScrollButton);
+ mRightScrollButton->setMouseDownCallback(boost::bind(&LLChicletPanel::onRightScrollClick,this));
+ mRightScrollButton->setHeldDownCallback(boost::bind(&LLChicletPanel::onRightScrollHeldDown,this));
+ mRightScrollButton->setEnabled(false);
+
+ return TRUE;
+}
+
+void LLChicletPanel::onCurrentVoiceChannelChanged(const LLUUID& session_id)
+{
+ static LLUUID s_previous_active_voice_session_id;
+
+ std::list<LLChiclet*> chiclets = LLIMChiclet::sFindChicletsSignal(session_id);
+
+ for(std::list<LLChiclet *>::iterator it = chiclets.begin(); it != chiclets.end(); ++it)
+ {
+ LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*it);
+ if(chiclet)
+ {
+ chiclet->setShowSpeaker(true);
+ }
+ }
+
+ if(!s_previous_active_voice_session_id.isNull() && s_previous_active_voice_session_id != session_id)
+ {
+ chiclets = LLIMChiclet::sFindChicletsSignal(s_previous_active_voice_session_id);
+
+ for(std::list<LLChiclet *>::iterator it = chiclets.begin(); it != chiclets.end(); ++it)
+ {
+ LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*it);
+ if(chiclet)
+ {
+ chiclet->setShowSpeaker(false);
+ }
+ }
+ }
+
+ s_previous_active_voice_session_id = session_id;
+}
+
+bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index)
+{
+ if(mScrollArea->addChild(chiclet))
+ {
+ // chiclets should be aligned to right edge of scroll panel
+ S32 left_shift = 0;
+
+ if (!canScrollLeft())
+ {
+ // init left shift for the first chiclet in the list...
+ if (mChicletList.empty())
+ {
+ // ...start from the right border of the scroll area for the first added chiclet
+ left_shift = mScrollArea->getRect().getWidth();
+ }
+ else
+ {
+ // ... start from the left border of the first chiclet minus padding
+ left_shift = getChiclet(0)->getRect().mLeft - getChicletPadding();
+ }
+
+ // take into account width of the being added chiclet
+ left_shift -= chiclet->getRequiredRect().getWidth();
+
+ // if we overflow the scroll area we do not need to shift chiclets
+ if (left_shift < 0)
+ {
+ left_shift = 0;
+ }
+ }
+
+ mChicletList.insert(mChicletList.begin() + index, chiclet);
+
+ // shift first chiclet to place it in correct position.
+ // rest ones will be placed in arrange()
+ if (!canScrollLeft())
+ {
+ getChiclet(0)->translate(left_shift - getChiclet(0)->getRect().mLeft, 0);
+ }
+
+ chiclet->setLeftButtonClickCallback(boost::bind(&LLChicletPanel::onChicletClick, this, _1, _2));
+ chiclet->setChicletSizeChangedCallback(boost::bind(&LLChicletPanel::onChicletSizeChanged, this, _1, index));
+
+ arrange();
+ LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, chiclet);
+
+ return true;
+ }
+
+ return false;
+}
+
+void LLChicletPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param)
+{
+ arrange();
+}
+
+void LLChicletPanel::onChicletClick(LLUICtrl*ctrl,const LLSD&param)
+{
+ if (mCommitSignal)
+ {
+ (*mCommitSignal)(ctrl,param);
+ }
+}
+
+void LLChicletPanel::removeChiclet(chiclet_list_t::iterator it)
+{
+ LLChiclet* chiclet = *it;
+ mScrollArea->removeChild(chiclet);
+ mChicletList.erase(it);
+
+ arrange();
+ LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, chiclet);
+ chiclet->die();
+}
+
+void LLChicletPanel::removeChiclet(S32 index)
+{
+ if(index >= 0 && index < getChicletCount())
+ {
+ removeChiclet(mChicletList.begin() + index);
+ }
+}
+
+S32 LLChicletPanel::getChicletIndex(const LLChiclet* chiclet)
+{
+ if(mChicletList.empty())
+ return -1;
+
+ S32 size = getChicletCount();
+ for(int n = 0; n < size; ++n)
+ {
+ if(chiclet == mChicletList[n])
+ return n;
+ }
+
+ return -1;
+}
+
+void LLChicletPanel::removeChiclet(LLChiclet*chiclet)
+{
+ chiclet_list_t::iterator it = mChicletList.begin();
+ for( ; mChicletList.end() != it; ++it)
+ {
+ LLChiclet* temp = *it;
+ if(temp == chiclet)
+ {
+ removeChiclet(it);
+ return;
+ }
+ }
+}
+
+void LLChicletPanel::removeChiclet(const LLUUID& im_session_id)
+{
+ chiclet_list_t::iterator it = mChicletList.begin();
+ for( ; mChicletList.end() != it; ++it)
+ {
+ LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*it);
+
+ if(chiclet->getSessionId() == im_session_id)
+ {
+ removeChiclet(it);
+ return;
+ }
+ }
+}
+
+void LLChicletPanel::removeAll()
+{
+ S32 size = getChicletCount();
+ for(S32 n = 0; n < size; ++n)
+ {
+ mScrollArea->removeChild(mChicletList[n]);
+ }
+
+ mChicletList.erase(mChicletList.begin(), mChicletList.end());
+
+ showScrollButtonsIfNeeded();
+}
+
+void LLChicletPanel::scrollToChiclet(const LLChiclet* chiclet)
+{
+ const LLRect& rect = chiclet->getRect();
+
+ if (rect.mLeft < 0)
+ {
+ scroll(llabs(rect.mLeft));
+ showScrollButtonsIfNeeded();
+ }
+ else
+ {
+ S32 scrollWidth = mScrollArea->getRect().getWidth();
+
+ if (rect.mRight > scrollWidth)
+ {
+ scroll(-llabs(rect.mRight - scrollWidth));
+ showScrollButtonsIfNeeded();
+ }
+ }
+}
+
+void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent )
+{
+ LLPanel::reshape(width,height,called_from_parent);
+
+ //Needed once- to avoid error at first call of reshape() before postBuild()
+ if(!mLeftScrollButton||!mRightScrollButton)
+ return;
+
+ LLRect scroll_button_rect = mLeftScrollButton->getRect();
+ mLeftScrollButton->setRect(LLRect(0,scroll_button_rect.mTop,scroll_button_rect.getWidth(),
+ scroll_button_rect.mBottom));
+ scroll_button_rect = mRightScrollButton->getRect();
+ mRightScrollButton->setRect(LLRect(width - scroll_button_rect.getWidth(),scroll_button_rect.mTop,
+ width, scroll_button_rect.mBottom));
+
+
+ bool need_show_scroll = needShowScroll();
+ if(need_show_scroll)
+ {
+ mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + mScrollButtonHPad,
+ height, width - scroll_button_rect.getWidth() - mScrollButtonHPad, 0));
+ }
+ else
+ {
+ mScrollArea->setRect(LLRect(0,height, width, 0));
+ }
+
+ mShowControls = width >= mMinWidth;
+
+ mScrollArea->setVisible(mShowControls);
+
+ trimChiclets();
+ showScrollButtonsIfNeeded();
+
+}
+
+S32 LLChicletPanel::notifyParent(const LLSD& info)
+{
+ if(info.has("notification"))
+ {
+ std::string str_notification = info["notification"];
+ if(str_notification == "size_changes")
+ {
+ arrange();
+ return 1;
+ }
+ }
+ return LLPanel::notifyParent(info);
+}
+
+void LLChicletPanel::setChicletToggleState(const LLUUID& session_id, bool toggle)
+{
+ if(session_id.isNull())
+ {
+ llwarns << "Null Session ID" << llendl;
+ }
+
+ // toggle off all chiclets, except specified
+ S32 size = getChicletCount();
+ for(int n = 0; n < size; ++n)
+ {
+ LLIMChiclet* chiclet = getChiclet<LLIMChiclet>(n);
+ if(chiclet && chiclet->getSessionId() != session_id)
+ {
+ chiclet->setToggleState(false);
+ }
+ }
+
+ // toggle specified chiclet
+ LLIMChiclet* chiclet = findChiclet<LLIMChiclet>(session_id);
+ if(chiclet)
+ {
+ chiclet->setToggleState(toggle);
+ }
+}
+
+void LLChicletPanel::arrange()
+{
+ if(mChicletList.empty())
+ return;
+
+ //initial arrange of chicklets positions
+ S32 chiclet_left = getChiclet(0)->getRect().mLeft;
+ S32 size = getChicletCount();
+ for( int n = 0; n < size; ++n)
+ {
+ LLChiclet* chiclet = getChiclet(n);
+
+ S32 chiclet_width = chiclet->getRequiredRect().getWidth();
+ LLRect rect = chiclet->getRect();
+ rect.set(chiclet_left, rect.mTop, chiclet_left + chiclet_width, rect.mBottom);
+
+ chiclet->setRect(rect);
+
+ chiclet_left += chiclet_width + getChicletPadding();
+ }
+
+ //reset size and pos on mScrollArea
+ LLRect rect = getRect();
+ LLRect scroll_button_rect = mLeftScrollButton->getRect();
+
+ bool need_show_scroll = needShowScroll();
+ if(need_show_scroll)
+ {
+ mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + mScrollButtonHPad,
+ rect.getHeight(), rect.getWidth() - scroll_button_rect.getWidth() - mScrollButtonHPad, 0));
+ }
+ else
+ {
+ mScrollArea->setRect(LLRect(0,rect.getHeight(), rect.getWidth(), 0));
+ }
+
+ trimChiclets();
+ showScrollButtonsIfNeeded();
+}
+
+void LLChicletPanel::trimChiclets()
+{
+ // trim right
+ if(!mChicletList.empty())
+ {
+ S32 last_chiclet_right = (*mChicletList.rbegin())->getRect().mRight;
+ S32 first_chiclet_left = getChiclet(0)->getRect().mLeft;
+ S32 scroll_width = mScrollArea->getRect().getWidth();
+ if(last_chiclet_right < scroll_width || first_chiclet_left > 0)
+ {
+ shiftChiclets(scroll_width - last_chiclet_right);
+ }
+ }
+}
+
+bool LLChicletPanel::needShowScroll()
+{
+ if(mChicletList.empty())
+ return false;
+
+ S32 chicklet_width = (*mChicletList.rbegin())->getRect().mRight - (*mChicletList.begin())->getRect().mLeft;
+
+ return chicklet_width>getRect().getWidth();
+}
+
+
+void LLChicletPanel::showScrollButtonsIfNeeded()
+{
+ bool can_scroll_left = canScrollLeft();
+ bool can_scroll_right = canScrollRight();
+
+ mLeftScrollButton->setEnabled(can_scroll_left);
+ mRightScrollButton->setEnabled(can_scroll_right);
+
+ bool show_scroll_buttons = (can_scroll_left || can_scroll_right) && mShowControls;
+
+ mLeftScrollButton->setVisible(show_scroll_buttons);
+ mRightScrollButton->setVisible(show_scroll_buttons);
+}
+
+void LLChicletPanel::draw()
+{
+ child_list_const_iter_t it = getChildList()->begin();
+ for( ; getChildList()->end() != it; ++it)
+ {
+ LLView* child = *it;
+ if(child == dynamic_cast<LLView*>(mScrollArea))
+ {
+ LLLocalClipRect clip(mScrollArea->getRect());
+ drawChild(mScrollArea);
+ }
+ else
+ {
+ drawChild(child);
+ }
+ }
+}
+
+bool LLChicletPanel::canScrollRight()
+{
+ if(mChicletList.empty())
+ return false;
+
+ S32 scroll_width = mScrollArea->getRect().getWidth();
+ S32 last_chiclet_right = (*mChicletList.rbegin())->getRect().mRight;
+
+ if(last_chiclet_right > scroll_width)
+ return true;
+
+ return false;
+}
+
+bool LLChicletPanel::canScrollLeft()
+{
+ if(mChicletList.empty())
+ return false;
+
+ return getChiclet(0)->getRect().mLeft < 0;
+}
+
+void LLChicletPanel::scroll(S32 offset)
+{
+ shiftChiclets(offset);
+}
+
+void LLChicletPanel::shiftChiclets(S32 offset, S32 start_index /* = 0 */)
+{
+ if(start_index < 0 || start_index >= getChicletCount())
+ {
+ return;
+ }
+
+ chiclet_list_t::const_iterator it = mChicletList.begin() + start_index;
+ for(;mChicletList.end() != it; ++it)
+ {
+ LLChiclet* chiclet = *it;
+ chiclet->translate(offset,0);
+ }
+}
+
+void LLChicletPanel::scrollLeft()
+{
+ if(canScrollLeft())
+ {
+ S32 offset = getScrollingOffset();
+ LLRect first_chiclet_rect = getChiclet(0)->getRect();
+
+ // shift chiclets in case first chiclet is partially visible
+ if(first_chiclet_rect.mLeft < 0 && first_chiclet_rect.mRight > 0)
+ {
+ offset = llabs(first_chiclet_rect.mLeft);
+ }
+
+ scroll(offset);
+
+ showScrollButtonsIfNeeded();
+ }
+}
+
+void LLChicletPanel::scrollRight()
+{
+ if(canScrollRight())
+ {
+ S32 offset = - getScrollingOffset();
+
+ S32 last_chiclet_right = (*mChicletList.rbegin())->getRect().mRight;
+ S32 scroll_rect_width = mScrollArea->getRect().getWidth();
+ // if after scrolling, the last chiclet will not be aligned to
+ // scroll area right side - align it.
+ if( last_chiclet_right + offset < scroll_rect_width )
+ {
+ offset = scroll_rect_width - last_chiclet_right;
+ }
+
+ scroll(offset);
+
+ showScrollButtonsIfNeeded();
+ }
+}
+
+void LLChicletPanel::onLeftScrollClick()
+{
+ scrollLeft();
+}
+
+void LLChicletPanel::onRightScrollClick()
+{
+ scrollRight();
+}
+
+void LLChicletPanel::onLeftScrollHeldDown()
+{
+ S32 offset = mScrollingOffset;
+ mScrollingOffset = mScrollingOffset / mScrollRatio;
+ scrollLeft();
+ mScrollingOffset = offset;
+}
+
+void LLChicletPanel::onRightScrollHeldDown()
+{
+ S32 offset = mScrollingOffset;
+ mScrollingOffset = mScrollingOffset / mScrollRatio;
+ scrollRight();
+ mScrollingOffset = offset;
+}
+
+boost::signals2::connection LLChicletPanel::setChicletClickedCallback(
+ const commit_callback_t& cb)
+{
+ return setCommitCallback(cb);
+}
+
+BOOL LLChicletPanel::handleScrollWheel(S32 x, S32 y, S32 clicks)
+{
+ if(clicks > 0)
+ {
+ scrollRight();
+ }
+ else
+ {
+ scrollLeft();
+ }
+ return TRUE;
+}
+
+bool LLChicletPanel::isAnyIMFloaterDoked()
+{
+ bool res = false;
+ for (chiclet_list_t::iterator it = mChicletList.begin(); it
+ != mChicletList.end(); it++)
+ {
+ LLIMFloater* im_floater = LLFloaterReg::findTypedInstance<LLIMFloater>(
+ "impanel", (*it)->getSessionId());
+ if (im_floater != NULL && im_floater->getVisible()
+ && !im_floater->isMinimized() && im_floater->isDocked())
+ {
+ res = true;
+ break;
+ }
+ }
+
+ return res;
+}
+
+S32 LLChicletPanel::getTotalUnreadIMCount()
+{
+ S32 count = 0;
+ chiclet_list_t::const_iterator it = mChicletList.begin();
+ for( ; mChicletList.end() != it; ++it)
+ {
+ LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*it);
+ if(chiclet)
+ {
+ count += chiclet->getCounter();
+ }
+ }
+ return count;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+LLChicletNotificationCounterCtrl::Params::Params()
+: max_displayed_count("max_displayed_count", 99)
+{
+}
+
+LLChicletNotificationCounterCtrl::LLChicletNotificationCounterCtrl(const Params& p)
+ : LLTextBox(p)
+ , mCounter(0)
+ , mInitialWidth(0)
+ , mMaxDisplayedCount(p.max_displayed_count)
+{
+ mInitialWidth = getRect().getWidth();
+}
+
+void LLChicletNotificationCounterCtrl::setCounter(S32 counter)
+{
+ mCounter = counter;
+
+ // note same code in LLSysWellChiclet::setCounter(S32 counter)
+ std::string s_count;
+ if(counter != 0)
+ {
+ static std::string more_messages_exist("+");
+ std::string more_messages(counter > mMaxDisplayedCount ? more_messages_exist : "");
+ s_count = llformat("%d%s"
+ , llmin(counter, mMaxDisplayedCount)
+ , more_messages.c_str()
+ );
+ }
+
+ if(mCounter != 0)
+ {
+ setText(s_count);
+ }
+ else
+ {
+ setText(std::string(""));
+ }
+}
+
+LLRect LLChicletNotificationCounterCtrl::getRequiredRect()
+{
+ LLRect rc;
+ S32 text_width = getTextPixelWidth();
+
+ rc.mRight = rc.mLeft + llmax(text_width, mInitialWidth);
+
+ return rc;
+}
+
+void LLChicletNotificationCounterCtrl::setValue(const LLSD& value)
+{
+ if(value.isInteger())
+ setCounter(value.asInteger());
+}
+
+LLSD LLChicletNotificationCounterCtrl::getValue() const
+{
+ return LLSD(getCounter());
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLChicletAvatarIconCtrl::LLChicletAvatarIconCtrl(const Params& p)
+ : LLAvatarIconCtrl(p)
+{
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLChicletGroupIconCtrl::LLChicletGroupIconCtrl(const Params& p)
+: LLIconCtrl(p)
+, mDefaultIcon(p.default_icon)
+{
+ setValue(LLUUID::null);
+}
+
+void LLChicletGroupIconCtrl::setValue(const LLSD& value )
+{
+ if(value.asUUID().isNull())
+ {
+ LLIconCtrl::setValue(mDefaultIcon);
+ }
+ else
+ {
+ LLIconCtrl::setValue(value);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLChicletInvOfferIconCtrl::LLChicletInvOfferIconCtrl(const Params& p)
+: LLChicletAvatarIconCtrl(p)
+ , mDefaultIcon(p.default_icon)
+{
+}
+
+void LLChicletInvOfferIconCtrl::setValue(const LLSD& value )
+{
+ if(value.asUUID().isNull())
+ {
+ LLIconCtrl::setValue(mDefaultIcon);
+ }
+ else
+ {
+ LLChicletAvatarIconCtrl::setValue(value);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLChicletSpeakerCtrl::LLChicletSpeakerCtrl(const Params&p)
+ : LLOutputMonitorCtrl(p)
+{
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLScriptChiclet::Params::Params()
+ : icon("icon")
+ , chiclet_button("chiclet_button")
+ , new_message_icon("new_message_icon")
+{
+}
+
+LLScriptChiclet::LLScriptChiclet(const Params&p)
+ : LLIMChiclet(p)
+ , mChicletIconCtrl(NULL)
+{
+ LLButton::Params button_params = p.chiclet_button;
+ mChicletButton = LLUICtrlFactory::create<LLButton>(button_params);
+ addChild(mChicletButton);
+
+ LLIconCtrl::Params new_msg_params = p.new_message_icon;
+ mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params);
+ addChild(mNewMessagesIcon);
+
+ LLIconCtrl::Params icon_params = p.icon;
+ mChicletIconCtrl = LLUICtrlFactory::create<LLIconCtrl>(icon_params);
+ addChild(mChicletIconCtrl);
+
+ sendChildToFront(mNewMessagesIcon);
+}
+
+void LLScriptChiclet::setSessionId(const LLUUID& session_id)
+{
+ setShowNewMessagesIcon( getSessionId() != session_id );
+
+ LLIMChiclet::setSessionId(session_id);
+ LLUUID notification_id = LLScriptFloaterManager::getInstance()->findNotificationId(session_id);
+ LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id);
+ if(notification)
+ {
+ setToolTip(notification->getSubstitutions()["TITLE"].asString());
+ }
+}
+
+void LLScriptChiclet::setCounter(S32 counter)
+{
+ setShowNewMessagesIcon( counter > 0 );
+}
+
+void LLScriptChiclet::onMouseDown()
+{
+ LLScriptFloaterManager::getInstance()->toggleScriptFloater(getSessionId());
+}
+
+BOOL LLScriptChiclet::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ onMouseDown();
+ return LLChiclet::handleMouseDown(x, y, mask);
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+static const std::string INVENTORY_USER_OFFER ("UserGiveItem");
+
+LLInvOfferChiclet::Params::Params()
+ : icon("icon")
+ , chiclet_button("chiclet_button")
+ , new_message_icon("new_message_icon")
+{
+}
+
+LLInvOfferChiclet::LLInvOfferChiclet(const Params&p)
+ : LLIMChiclet(p)
+ , mChicletIconCtrl(NULL)
+{
+ LLButton::Params button_params = p.chiclet_button;
+ mChicletButton = LLUICtrlFactory::create<LLButton>(button_params);
+ addChild(mChicletButton);
+
+ LLIconCtrl::Params new_msg_params = p.new_message_icon;
+ mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params);
+ addChild(mNewMessagesIcon);
+
+ LLChicletInvOfferIconCtrl::Params icon_params = p.icon;
+ mChicletIconCtrl = LLUICtrlFactory::create<LLChicletInvOfferIconCtrl>(icon_params);
+ addChild(mChicletIconCtrl);
+
+ sendChildToFront(mNewMessagesIcon);
+}
+
+void LLInvOfferChiclet::setSessionId(const LLUUID& session_id)
+{
+ setShowNewMessagesIcon( getSessionId() != session_id );
+
+ LLIMChiclet::setSessionId(session_id);
+ LLUUID notification_id = LLScriptFloaterManager::getInstance()->findNotificationId(session_id);
+ LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id);
+ if(notification)
+ {
+ setToolTip(notification->getSubstitutions()["TITLE"].asString());
+ }
+
+ if ( notification && notification->getName() == INVENTORY_USER_OFFER )
+ {
+ mChicletIconCtrl->setValue(notification->getPayload()["from_id"]);
+ }
+ else
+ {
+ mChicletIconCtrl->setValue(LLUUID::null);
+ }
+}
+
+void LLInvOfferChiclet::setCounter(S32 counter)
+{
+ setShowNewMessagesIcon( counter > 0 );
+}
+
+void LLInvOfferChiclet::onMouseDown()
+{
+ LLScriptFloaterManager::instance().toggleScriptFloater(getSessionId());
+}
+
+BOOL LLInvOfferChiclet::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ onMouseDown();
+ return LLChiclet::handleMouseDown(x, y, mask);
+}
+
+// EOF
diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h
new file mode 100644
index 0000000000..bb4846aa57
--- /dev/null
+++ b/indra/newview/llchiclet.h
@@ -0,0 +1,1269 @@
+/**
+ * @file llchiclet.h
+ * @brief LLChiclet class header file
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLCHICLET_H
+#define LL_LLCHICLET_H
+
+#include "llavatariconctrl.h"
+#include "llbutton.h"
+#include "llpanel.h"
+#include "lltextbox.h"
+#include "lloutputmonitorctrl.h"
+#include "llgroupmgr.h"
+#include "llimview.h"
+
+class LLMenuGL;
+class LLIMFloater;
+
+/**
+ * Class for displaying amount of messages/notifications(unread).
+ */
+class LLChicletNotificationCounterCtrl : public LLTextBox
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLTextBox::Params>
+ {
+ /**
+ * Contains maximum displayed count of unread messages. Default value is 9.
+ *
+ * If count is less than "max_unread_count" will be displayed as is.
+ * Otherwise 9+ will be shown (for default value).
+ */
+ Optional<S32> max_displayed_count;
+
+ Params();
+ };
+
+ /**
+ * Sets number of notifications
+ */
+ virtual void setCounter(S32 counter);
+
+ /**
+ * Returns number of notifications
+ */
+ virtual S32 getCounter() const { return mCounter; }
+
+ /**
+ * Returns width, required to display amount of notifications in text form.
+ * Width is the only valid value.
+ */
+ /*virtual*/ LLRect getRequiredRect();
+
+ /**
+ * Sets number of notifications using LLSD
+ */
+ /*virtual*/ void setValue(const LLSD& value);
+
+ /**
+ * Returns number of notifications wrapped in LLSD
+ */
+ /*virtual*/ LLSD getValue() const;
+
+protected:
+
+ LLChicletNotificationCounterCtrl(const Params& p);
+ friend class LLUICtrlFactory;
+
+private:
+
+ S32 mCounter;
+ S32 mInitialWidth;
+ S32 mMaxDisplayedCount;
+};
+
+/**
+ * Class for displaying avatar's icon in P2P chiclet.
+ */
+class LLChicletAvatarIconCtrl : public LLAvatarIconCtrl
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLAvatarIconCtrl::Params>
+ {
+ Params()
+ {
+ draw_tooltip(FALSE);
+ mouse_opaque(FALSE);
+ default_icon_name("Generic_Person");
+ };
+ };
+
+protected:
+
+ LLChicletAvatarIconCtrl(const Params& p);
+ friend class LLUICtrlFactory;
+};
+
+/**
+ * Class for displaying group's icon in Group chiclet.
+ */
+class LLChicletGroupIconCtrl : public LLIconCtrl
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLIconCtrl::Params>
+ {
+ Optional<std::string> default_icon;
+
+ Params()
+ : default_icon("default_icon", "Generic_Group")
+ {
+ };
+ };
+
+ /**
+ * Sets icon, if value is LLUUID::null - default icon will be set.
+ */
+ virtual void setValue(const LLSD& value );
+
+protected:
+
+ LLChicletGroupIconCtrl(const Params& p);
+ friend class LLUICtrlFactory;
+
+ std::string mDefaultIcon;
+};
+
+/**
+ * Class for displaying icon in inventory offer chiclet.
+ */
+class LLChicletInvOfferIconCtrl : public LLChicletAvatarIconCtrl
+{
+public:
+
+ struct Params :
+ public LLInitParam::Block<Params, LLChicletAvatarIconCtrl::Params>
+ {
+ Optional<std::string> default_icon;
+
+ Params()
+ : default_icon("default_icon", "Generic_Object_Small")
+ {
+ avatar_id = LLUUID::null;
+ };
+ };
+
+ /**
+ * Sets icon, if value is LLUUID::null - default icon will be set.
+ */
+ virtual void setValue(const LLSD& value );
+
+protected:
+
+ LLChicletInvOfferIconCtrl(const Params& p);
+ friend class LLUICtrlFactory;
+
+private:
+ std::string mDefaultIcon;
+};
+
+/**
+ * Class for displaying of speaker's voice indicator
+ */
+class LLChicletSpeakerCtrl : public LLOutputMonitorCtrl
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLOutputMonitorCtrl::Params>
+ {
+ Params(){};
+ };
+protected:
+
+ LLChicletSpeakerCtrl(const Params&p);
+ friend class LLUICtrlFactory;
+};
+
+/**
+ * Base class for all chiclets.
+ */
+class LLChiclet : public LLUICtrl
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<bool> show_counter,
+ enable_counter;
+
+ Params();
+ };
+
+ /*virtual*/ ~LLChiclet();
+
+ /**
+ * Associates chat session id with chiclet.
+ */
+ virtual void setSessionId(const LLUUID& session_id) { mSessionId = session_id; }
+
+ /**
+ * Returns associated chat session.
+ */
+ virtual const LLUUID& getSessionId() const { return mSessionId; }
+
+ /**
+ * Sets number of unread notifications.
+ */
+ virtual void setCounter(S32 counter) = 0;
+
+ /**
+ * Returns number of unread notifications.
+ */
+ virtual S32 getCounter() = 0;
+
+ /**
+ * Sets show counter state.
+ */
+ virtual void setShowCounter(bool show) { mShowCounter = show; }
+
+ /**
+ * Returns show counter state.
+ */
+ virtual bool getShowCounter() {return mShowCounter;};
+
+ /**
+ * Connects chiclet clicked event with callback.
+ */
+ /*virtual*/ boost::signals2::connection setLeftButtonClickCallback(
+ const commit_callback_t& cb);
+
+ typedef boost::function<void (LLChiclet* ctrl, const LLSD& param)>
+ chiclet_size_changed_callback_t;
+
+ /**
+ * Connects chiclets size changed event with callback.
+ */
+ virtual boost::signals2::connection setChicletSizeChangedCallback(
+ const chiclet_size_changed_callback_t& cb);
+
+ /**
+ * Sets IM Session id using LLSD
+ */
+ /*virtual*/ LLSD getValue() const;
+
+ /**
+ * Returns IM Session id using LLSD
+ */
+ /*virtual*/ void setValue(const LLSD& value);
+
+protected:
+
+ friend class LLUICtrlFactory;
+ LLChiclet(const Params& p);
+
+ /**
+ * Notifies subscribers about click on chiclet.
+ */
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+
+ /**
+ * Notifies subscribers about chiclet size changed event.
+ */
+ virtual void onChicletSizeChanged();
+
+private:
+
+ LLUUID mSessionId;
+
+ bool mShowCounter;
+
+ typedef boost::signals2::signal<void (LLChiclet* ctrl, const LLSD& param)>
+ chiclet_size_changed_signal_t;
+
+ chiclet_size_changed_signal_t mChicletSizeChangedSignal;
+};
+
+
+/**
+ * Base class for Instant Message chiclets.
+ * IMChiclet displays icon, number of unread messages(optional)
+ * and voice chat status(optional).
+ */
+class LLIMChiclet : public LLChiclet
+{
+public:
+ enum EType {
+ TYPE_UNKNOWN,
+ TYPE_IM,
+ TYPE_GROUP,
+ TYPE_AD_HOC
+ };
+ struct Params : public LLInitParam::Block<Params, LLChiclet::Params>
+ {
+ Params(){}
+ };
+
+
+ virtual ~LLIMChiclet() {};
+
+ /**
+ * Sets IM session name. This name will be displayed in chiclet tooltip.
+ */
+ virtual void setIMSessionName(const std::string& name) { setToolTip(name); }
+
+ /**
+ * Sets id of person/group user is chatting with.
+ * Session id should be set before calling this
+ */
+ virtual void setOtherParticipantId(const LLUUID& other_participant_id) { mOtherParticipantId = other_participant_id; }
+
+ /**
+ * Gets id of person/group user is chatting with.
+ */
+ virtual LLUUID getOtherParticipantId() { return mOtherParticipantId; }
+
+ /**
+ * Init Speaker Control with speaker's ID
+ */
+ virtual void initSpeakerControl();
+
+ /**
+ * set status (Shows/Hide) for voice control.
+ */
+ virtual void setShowSpeaker(bool show);
+
+ /**
+ * Returns voice chat status control visibility.
+ */
+ virtual bool getShowSpeaker() {return mShowSpeaker;};
+
+ /**
+ * Shows/Hides for voice control for a chiclet.
+ */
+ virtual void toggleSpeakerControl();
+
+ /**
+ * Sets number of unread messages. Will update chiclet's width if number text
+ * exceeds size of counter and notify it's parent about size change.
+ */
+ virtual void setCounter(S32);
+
+ /**
+ * Enables/disables the counter control for a chiclet.
+ */
+ virtual void enableCounterControl(bool enable);
+
+ /**
+ * Sets show counter state.
+ */
+ virtual void setShowCounter(bool show);
+
+ /**
+ * Shows/Hides for counter control for a chiclet.
+ */
+ virtual void toggleCounterControl();
+
+ /**
+ * Sets required width for a chiclet according to visible controls.
+ */
+ virtual void setRequiredWidth();
+
+ /**
+ * Shows/hides overlay icon concerning new unread messages.
+ */
+ virtual void setShowNewMessagesIcon(bool show);
+
+ /**
+ * Returns visibility of overlay icon concerning new unread messages.
+ */
+ virtual bool getShowNewMessagesIcon();
+
+ virtual void draw();
+
+ /**
+ * Determine whether given ID refers to a group or an IM chat session.
+ *
+ * This is used when we need to chose what IM chiclet (P2P/group)
+ * class to instantiate.
+ *
+ * @param session_id session ID.
+ * @return TYPE_GROUP in case of group chat session,
+ * TYPE_IM in case of P2P session,
+ * TYPE_UNKNOWN otherwise.
+ */
+ static EType getIMSessionType(const LLUUID& session_id);
+
+ /**
+ * The action taken on mouse down event.
+ *
+ * Made public so that it can be triggered from outside
+ * (more specifically, from the Active IM window).
+ */
+ virtual void onMouseDown();
+
+ virtual void setToggleState(bool toggle);
+
+protected:
+
+ LLIMChiclet(const LLIMChiclet::Params& p);
+
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+
+protected:
+
+ bool mShowSpeaker;
+ bool mCounterEnabled;
+ /* initial width of chiclet, should not include counter or speaker width */
+ S32 mDefaultWidth;
+
+ LLIconCtrl* mNewMessagesIcon;
+ LLChicletNotificationCounterCtrl* mCounterCtrl;
+ LLChicletSpeakerCtrl* mSpeakerCtrl;
+ LLButton* mChicletButton;
+
+ /** the id of another participant, either an avatar id or a group id*/
+ LLUUID mOtherParticipantId;
+
+ template<typename Container>
+ struct CollectChicletCombiner {
+ typedef Container result_type;
+
+ template<typename InputIterator>
+ Container operator()(InputIterator first, InputIterator last) const {
+ Container c = Container();
+ for (InputIterator iter = first; iter != last; iter++) {
+ if (*iter != NULL) {
+ c.push_back(*iter);
+ }
+ }
+ return c;
+ }
+ };
+
+public:
+ static boost::signals2::signal<LLChiclet* (const LLUUID&),
+ CollectChicletCombiner<std::list<LLChiclet*> > >
+ sFindChicletsSignal;
+};
+
+/**
+ * Implements P2P chiclet.
+ */
+class LLIMP2PChiclet : public LLIMChiclet
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLIMChiclet::Params>
+ {
+ Optional<LLButton::Params> chiclet_button;
+
+ Optional<LLChicletAvatarIconCtrl::Params> avatar_icon;
+
+ Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications;
+
+ Optional<LLChicletSpeakerCtrl::Params> speaker;
+
+ Optional<LLIconCtrl::Params> new_message_icon;
+
+ Optional<bool> show_speaker;
+
+ Params();
+ };
+
+ /* virtual */ void setOtherParticipantId(const LLUUID& other_participant_id);
+
+ /**
+ * Init Speaker Control with speaker's ID
+ */
+ /*virtual*/ void initSpeakerControl();
+
+ /**
+ * Returns number of unread messages.
+ */
+ /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); }
+
+protected:
+ LLIMP2PChiclet(const Params& p);
+ friend class LLUICtrlFactory;
+
+ /**
+ * Creates chiclet popup menu. Will create P2P or Group IM Chat menu
+ * based on other participant's id.
+ */
+ virtual void createPopupMenu();
+
+ /**
+ * Processes clicks on chiclet popup menu.
+ */
+ virtual void onMenuItemClicked(const LLSD& user_data);
+
+ /**
+ * Displays popup menu.
+ */
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+
+ /**
+ * Enables/disables menus based on relationship with other participant.
+ * Enables/disables "show session" menu item depending on visible IM floater existence.
+ */
+ virtual void updateMenuItems();
+
+private:
+
+ LLChicletAvatarIconCtrl* mChicletIconCtrl;
+ LLMenuGL* mPopupMenu;
+};
+
+/**
+ * Implements AD-HOC chiclet.
+ */
+class LLAdHocChiclet : public LLIMChiclet
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLIMChiclet::Params>
+ {
+ Optional<LLButton::Params> chiclet_button;
+
+ Optional<LLChicletAvatarIconCtrl::Params> avatar_icon;
+
+ Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications;
+
+ Optional<LLChicletSpeakerCtrl::Params> speaker;
+
+ Optional<LLIconCtrl::Params> new_message_icon;
+
+ Optional<bool> show_speaker;
+
+ Optional<LLColor4> avatar_icon_color;
+
+ Params();
+ };
+
+ /**
+ * Sets session id.
+ * Session ID for group chat is actually Group ID.
+ */
+ /*virtual*/ void setSessionId(const LLUUID& session_id);
+
+ /**
+ * Keep Speaker Control with actual speaker's ID
+ */
+ /*virtual*/ void draw();
+
+ /**
+ * Init Speaker Control with speaker's ID
+ */
+ /*virtual*/ void initSpeakerControl();
+
+ /**
+ * Returns number of unread messages.
+ */
+ /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); }
+
+protected:
+ LLAdHocChiclet(const Params& p);
+ friend class LLUICtrlFactory;
+
+ /**
+ * Creates chiclet popup menu. Will create AdHoc Chat menu
+ * based on other participant's id.
+ */
+ virtual void createPopupMenu();
+
+ /**
+ * Processes clicks on chiclet popup menu.
+ */
+ virtual void onMenuItemClicked(const LLSD& user_data);
+
+ /**
+ * Displays popup menu.
+ */
+ virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+
+ /**
+ * Finds a current speaker and resets the SpeakerControl with speaker's ID
+ */
+ /*virtual*/ void switchToCurrentSpeaker();
+
+private:
+
+ LLChicletAvatarIconCtrl* mChicletIconCtrl;
+ LLMenuGL* mPopupMenu;
+};
+
+/**
+ * Chiclet for script floaters.
+ */
+class LLScriptChiclet : public LLIMChiclet
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLIMChiclet::Params>
+ {
+ Optional<LLButton::Params> chiclet_button;
+
+ Optional<LLIconCtrl::Params> icon;
+
+ Optional<LLIconCtrl::Params> new_message_icon;
+
+ Params();
+ };
+
+ /*virtual*/ void setSessionId(const LLUUID& session_id);
+
+ /*virtual*/ void setCounter(S32 counter);
+
+ /*virtual*/ S32 getCounter() { return 0; }
+
+ /**
+ * Toggle script floater
+ */
+ /*virtual*/ void onMouseDown();
+
+ /**
+ * Override default handler
+ */
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+
+protected:
+
+ LLScriptChiclet(const Params&);
+ friend class LLUICtrlFactory;
+
+private:
+
+ LLIconCtrl* mChicletIconCtrl;
+};
+
+/**
+ * Chiclet for inventory offer script floaters.
+ */
+class LLInvOfferChiclet: public LLIMChiclet
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLIMChiclet::Params>
+ {
+ Optional<LLButton::Params> chiclet_button;
+
+ Optional<LLChicletInvOfferIconCtrl::Params> icon;
+
+ Optional<LLIconCtrl::Params> new_message_icon;
+
+ Params();
+ };
+
+ /*virtual*/ void setSessionId(const LLUUID& session_id);
+
+ /*virtual*/ void setCounter(S32 counter);
+
+ /*virtual*/ S32 getCounter() { return 0; }
+
+ /**
+ * Toggle script floater
+ */
+ /*virtual*/ void onMouseDown();
+
+ /**
+ * Override default handler
+ */
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+
+
+protected:
+ LLInvOfferChiclet(const Params&);
+ friend class LLUICtrlFactory;
+
+private:
+ LLChicletInvOfferIconCtrl* mChicletIconCtrl;
+};
+
+/**
+ * Implements Group chat chiclet.
+ */
+class LLIMGroupChiclet : public LLIMChiclet, public LLGroupMgrObserver
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLIMChiclet::Params>
+ {
+ Optional<LLButton::Params> chiclet_button;
+
+ Optional<LLChicletGroupIconCtrl::Params> group_icon;
+
+ Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications;
+
+ Optional<LLChicletSpeakerCtrl::Params> speaker;
+
+ Optional<LLIconCtrl::Params> new_message_icon;
+
+ Optional<bool> show_speaker;
+
+ Params();
+ };
+
+ /**
+ * Sets session id.
+ * Session ID for group chat is actually Group ID.
+ */
+ /*virtual*/ void setSessionId(const LLUUID& session_id);
+
+ /**
+ * Keep Speaker Control with actual speaker's ID
+ */
+ /*virtual*/ void draw();
+
+ /**
+ * Callback for LLGroupMgrObserver, we get this when group data is available or changed.
+ * Sets group icon.
+ */
+ /*virtual*/ void changed(LLGroupChange gc);
+
+ /**
+ * Init Speaker Control with speaker's ID
+ */
+ /*virtual*/ void initSpeakerControl();
+
+ /**
+ * Returns number of unread messages.
+ */
+ /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); }
+
+ ~LLIMGroupChiclet();
+
+protected:
+ LLIMGroupChiclet(const Params& p);
+ friend class LLUICtrlFactory;
+
+ /**
+ * Finds a current speaker and resets the SpeakerControl with speaker's ID
+ */
+ /*virtual*/ void switchToCurrentSpeaker();
+
+ /**
+ * Creates chiclet popup menu. Will create P2P or Group IM Chat menu
+ * based on other participant's id.
+ */
+ virtual void createPopupMenu();
+
+ /**
+ * Processes clicks on chiclet popup menu.
+ */
+ virtual void onMenuItemClicked(const LLSD& user_data);
+
+ /**
+ * Enables/disables "show session" menu item depending on visible IM floater existence.
+ */
+ virtual void updateMenuItems();
+
+ /**
+ * Displays popup menu.
+ */
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+
+private:
+
+ LLChicletGroupIconCtrl* mChicletIconCtrl;
+ LLMenuGL* mPopupMenu;
+};
+
+/**
+ * Implements notification chiclet. Used to display total amount of unread messages
+ * across all IM sessions, total amount of system notifications. See EXT-3147 for details
+ */
+class LLSysWellChiclet : public LLChiclet
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLChiclet::Params>
+ {
+ Optional<LLButton::Params> button;
+
+ Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications;
+
+ /**
+ * Contains maximum displayed count of unread messages. Default value is 9.
+ *
+ * If count is less than "max_unread_count" will be displayed as is.
+ * Otherwise 9+ will be shown (for default value).
+ */
+ Optional<S32> max_displayed_count;
+
+ /**
+ * How many time chiclet should flash before set "Lit" state. Default value is 3.
+ */
+ Optional<S32> flash_to_lit_count;
+
+ /**
+ * Period of flashing while setting "Lit" state, in seconds. Default value is 0.5.
+ */
+ Optional<F32> flash_period;
+
+ Params();
+ };
+
+ /*virtual*/ void setCounter(S32 counter);
+
+ // *TODO: mantipov: seems getCounter is not necessary for LLNotificationChiclet
+ // but inherited interface requires it to implement.
+ // Probably it can be safe removed.
+ /*virtual*/S32 getCounter() { return mCounter; }
+
+ boost::signals2::connection setClickCallback(const commit_callback_t& cb);
+
+ /*virtual*/ ~LLSysWellChiclet();
+
+ void setToggleState(BOOL toggled);
+
+ void setNewMessagesState(bool new_messages);
+ //this method should change a widget according to state of the SysWellWindow
+ virtual void updateWidget(bool is_window_empty);
+
+protected:
+
+ LLSysWellChiclet(const Params& p);
+ friend class LLUICtrlFactory;
+
+ /**
+ * Change Well 'Lit' state from 'Lit' to 'Unlit' and vice-versa.
+ *
+ * There is an assumption that it will be called 2*N times to do not change its start state.
+ * @see FlashToLitTimer
+ */
+ void changeLitState();
+
+ /**
+ * Displays menu.
+ */
+ virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+
+ virtual void createMenu() = 0;
+
+protected:
+ class FlashToLitTimer;
+ LLButton* mButton;
+ S32 mCounter;
+ S32 mMaxDisplayedCount;
+ bool mIsNewMessagesState;
+
+ FlashToLitTimer* mFlashToLitTimer;
+ LLContextMenu* mContextMenu;
+};
+
+/**
+ * Class represented a chiclet for IM Well Icon.
+ *
+ * It displays a count of unread messages from other participants in all IM sessions.
+ */
+class LLIMWellChiclet : public LLSysWellChiclet, LLIMSessionObserver
+{
+ friend class LLUICtrlFactory;
+public:
+ virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) {}
+ virtual void sessionRemoved(const LLUUID& session_id) { messageCountChanged(LLSD()); }
+ virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) {}
+
+ ~LLIMWellChiclet();
+protected:
+ LLIMWellChiclet(const Params& p);
+
+ /**
+ * Processes clicks on chiclet popup menu.
+ */
+ virtual void onMenuItemClicked(const LLSD& user_data);
+
+ /**
+ * Enables chiclet menu items.
+ */
+ bool enableMenuItem(const LLSD& user_data);
+
+ /**
+ * Creates menu.
+ */
+ /*virtual*/ void createMenu();
+
+ /**
+ * Handles changes in a session (message was added, messages were read, etc.)
+ *
+ * It get total count of unread messages from a LLIMMgr in all opened sessions and display it.
+ *
+ * @param[in] session_data contains session related data, is not used now
+ * ["session_id"] - id of an appropriate session
+ * ["participant_unread"] - count of unread messages from "real" participants.
+ *
+ * @see LLIMMgr::getNumberOfUnreadParticipantMessages()
+ */
+ void messageCountChanged(const LLSD& session_data);
+};
+
+class LLNotificationChiclet : public LLSysWellChiclet
+{
+ friend class LLUICtrlFactory;
+protected:
+ LLNotificationChiclet(const Params& p);
+
+ /**
+ * Processes clicks on chiclet menu.
+ */
+ void onMenuItemClicked(const LLSD& user_data);
+
+ /**
+ * Enables chiclet menu items.
+ */
+ bool enableMenuItem(const LLSD& user_data);
+
+ /**
+ * Creates menu.
+ */
+ /*virtual*/ void createMenu();
+
+ // connect counter updaters to the corresponding signals
+ void connectCounterUpdatersToSignal(const std::string& notification_type);
+
+ // methods for updating a number of unread System notifications
+ void incUreadSystemNotifications() { setCounter(++mUreadSystemNotifications); }
+ void decUreadSystemNotifications() { setCounter(--mUreadSystemNotifications); }
+ /*virtual*/ void setCounter(S32 counter);
+ S32 mUreadSystemNotifications;
+};
+
+/**
+ * Storage class for all IM chiclets. Provides mechanism to display,
+ * scroll, create, remove chiclets.
+ */
+class LLChicletPanel : public LLPanel
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ Optional<S32> chiclet_padding,
+ scrolling_offset,
+ scroll_button_hpad,
+ scroll_ratio;
+
+ Optional<S32> min_width;
+
+ Params();
+ };
+
+ virtual ~LLChicletPanel();
+
+ /**
+ * Creates chiclet and adds it to chiclet list at specified index.
+ */
+ template<class T> T* createChiclet(const LLUUID& session_id, S32 index);
+
+ /**
+ * Creates chiclet and adds it to chiclet list at right.
+ */
+ template<class T> T* createChiclet(const LLUUID& session_id);
+
+ /**
+ * Returns pointer to chiclet of specified type at specified index.
+ */
+ template<class T> T* getChiclet(S32 index);
+
+ /**
+ * Returns pointer to LLChiclet at specified index.
+ */
+ LLChiclet* getChiclet(S32 index) { return getChiclet<LLChiclet>(index); }
+
+ /**
+ * Searches a chiclet using IM session id.
+ */
+ template<class T> T* findChiclet(const LLUUID& im_session_id);
+
+ /**
+ * Returns number of hosted chiclets.
+ */
+ S32 getChicletCount() {return mChicletList.size();};
+
+ /**
+ * Returns index of chiclet in list.
+ */
+ S32 getChicletIndex(const LLChiclet* chiclet);
+
+ /**
+ * Removes chiclet by index.
+ */
+ void removeChiclet(S32 index);
+
+ /**
+ * Removes chiclet by pointer.
+ */
+ void removeChiclet(LLChiclet* chiclet);
+
+ /**
+ * Removes chiclet by IM session id.
+ */
+ void removeChiclet(const LLUUID& im_session_id);
+
+ /**
+ * Removes all chiclets.
+ */
+ void removeAll();
+
+ /**
+ * Scrolls the panel to the specified chiclet
+ */
+ void scrollToChiclet(const LLChiclet* chiclet);
+
+ boost::signals2::connection setChicletClickedCallback(
+ const commit_callback_t& cb);
+
+ /*virtual*/ BOOL postBuild();
+
+ /**
+ * Handler for the Voice Client's signal. Finds a corresponding chiclet and toggles its SpeakerControl
+ */
+ void onCurrentVoiceChannelChanged(const LLUUID& session_id);
+
+ /**
+ * Reshapes controls and rearranges chiclets if needed.
+ */
+ /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE );
+
+ /*virtual*/ void draw();
+
+ S32 getMinWidth() const { return mMinWidth; }
+
+ S32 getTotalUnreadIMCount();
+
+ S32 notifyParent(const LLSD& info);
+
+ /**
+ * Toggle chiclet by session id ON and toggle OFF all other chiclets.
+ */
+ void setChicletToggleState(const LLUUID& session_id, bool toggle);
+
+protected:
+ LLChicletPanel(const Params&p);
+ friend class LLUICtrlFactory;
+
+ /**
+ * Adds chiclet to list and rearranges all chiclets.
+ * They should be right aligned, most recent right. See EXT-1293
+ *
+ * It calculates position of the first chiclet in the list. Other chiclets are placed in arrange().
+ *
+ * @see arrange()
+ */
+ bool addChiclet(LLChiclet*, S32 index);
+
+ /**
+ * Arranges chiclets to have them in correct positions.
+ *
+ * Method bases on assumption that first chiclet has correct rect and starts from the its position.
+ *
+ * @see addChiclet()
+ */
+ void arrange();
+
+ /**
+ * Returns true if chiclets can be scrolled right.
+ */
+ bool canScrollRight();
+
+ /**
+ * Returns true if we need to show scroll buttons
+ */
+ bool needShowScroll();
+
+ /**
+ * Returns true if chiclets can be scrolled left.
+ */
+ bool canScrollLeft();
+
+ /**
+ * Shows or hides chiclet scroll buttons if chiclets can or can not be scrolled.
+ */
+ void showScrollButtonsIfNeeded();
+
+ /**
+ * Shifts chiclets left or right.
+ */
+ void shiftChiclets(S32 offset, S32 start_index = 0);
+
+ /**
+ * Removes gaps between first chiclet and scroll area left side,
+ * last chiclet and scroll area right side.
+ */
+ void trimChiclets();
+
+ /**
+ * Scrolls chiclets to right or left.
+ */
+ void scroll(S32 offset);
+
+ /**
+ * Verifies that chiclets can be scrolled left, then calls scroll()
+ */
+ void scrollLeft();
+
+ /**
+ * Verifies that chiclets can be scrolled right, then calls scroll()
+ */
+ void scrollRight();
+
+ /**
+ * Callback for left scroll button clicked
+ */
+ void onLeftScrollClick();
+
+ /**
+ * Callback for right scroll button clicked
+ */
+ void onRightScrollClick();
+
+ /**
+ * Callback for right scroll button held down event
+ */
+ void onLeftScrollHeldDown();
+
+ /**
+ * Callback for left scroll button held down event
+ */
+ void onRightScrollHeldDown();
+
+ /**
+ * Callback for mouse wheel scrolled, calls scrollRight() or scrollLeft()
+ */
+ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+
+ /**
+ * Notifies subscribers about click on chiclet.
+ * Do not place any code here, instead subscribe on event (see setChicletClickedCallback).
+ */
+ void onChicletClick(LLUICtrl*ctrl,const LLSD&param);
+
+ /**
+ * Callback for chiclet size changed event, rearranges chiclets.
+ */
+ void onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param);
+
+ typedef std::vector<LLChiclet*> chiclet_list_t;
+
+ /**
+ * Removes chiclet from scroll area and chiclet list.
+ */
+ void removeChiclet(chiclet_list_t::iterator it);
+
+ S32 getChicletPadding() { return mChicletPadding; }
+
+ S32 getScrollingOffset() { return mScrollingOffset; }
+
+ bool isAnyIMFloaterDoked();
+
+protected:
+
+ chiclet_list_t mChicletList;
+ LLButton* mLeftScrollButton;
+ LLButton* mRightScrollButton;
+ LLPanel* mScrollArea;
+
+ S32 mChicletPadding;
+ S32 mScrollingOffset;
+ S32 mScrollButtonHPad;
+ S32 mScrollRatio;
+ S32 mMinWidth;
+ bool mShowControls;
+ static const S32 s_scroll_ratio;
+};
+
+template<class T>
+T* LLChicletPanel::createChiclet(const LLUUID& session_id, S32 index)
+{
+ typename T::Params params;
+ T* chiclet = LLUICtrlFactory::create<T>(params);
+ if(!chiclet)
+ {
+ llwarns << "Could not create chiclet" << llendl;
+ return NULL;
+ }
+ if(!addChiclet(chiclet, index))
+ {
+ delete chiclet;
+ llwarns << "Could not add chiclet to chiclet panel" << llendl;
+ return NULL;
+ }
+
+ if (!isAnyIMFloaterDoked())
+ {
+ scrollToChiclet(chiclet);
+ }
+
+ chiclet->setSessionId(session_id);
+
+ return chiclet;
+}
+
+template<class T>
+T* LLChicletPanel::createChiclet(const LLUUID& session_id)
+{
+ return createChiclet<T>(session_id, mChicletList.size());
+}
+
+template<class T>
+T* LLChicletPanel::findChiclet(const LLUUID& im_session_id)
+{
+ if(im_session_id.isNull())
+ {
+ return NULL;
+ }
+
+ chiclet_list_t::const_iterator it = mChicletList.begin();
+ for( ; mChicletList.end() != it; ++it)
+ {
+ LLChiclet* chiclet = *it;
+
+ if(chiclet->getSessionId() == im_session_id)
+ {
+ T* result = dynamic_cast<T*>(chiclet);
+ if(!result && chiclet)
+ {
+ llwarns << "Found chiclet but of wrong type " << llendl;
+ }
+ return result;
+ }
+ }
+ return NULL;
+}
+
+template<class T> T* LLChicletPanel::getChiclet(S32 index)
+{
+ if(index < 0 || index >= getChicletCount())
+ {
+ return NULL;
+ }
+
+ LLChiclet* chiclet = mChicletList[index];
+ T*result = dynamic_cast<T*>(chiclet);
+ if(!result && chiclet)
+ {
+ llwarns << "Found chiclet but of wrong type " << llendl;
+ }
+ return result;
+}
+
+#endif // LL_LLCHICLET_H
diff --git a/indra/newview/llclassifiedinfo.cpp b/indra/newview/llclassifiedinfo.cpp
index 5cf1579d0e..5fcafbeca6 100644
--- a/indra/newview/llclassifiedinfo.cpp
+++ b/indra/newview/llclassifiedinfo.cpp
@@ -38,35 +38,19 @@
LLClassifiedInfo::cat_map LLClassifiedInfo::sCategories;
// static
-void LLClassifiedInfo::loadCategories(LLUserAuth::options_t classified_options)
+void LLClassifiedInfo::loadCategories(const LLSD& options)
{
- LLUserAuth::options_t::iterator resp_it;
- for (resp_it = classified_options.begin();
- resp_it != classified_options.end();
- ++resp_it)
+ for(LLSD::array_const_iterator resp_it = options.beginArray(),
+ end = options.endArray(); resp_it != end; ++resp_it)
{
- const LLUserAuth::response_t& response = *resp_it;
-
- LLUserAuth::response_t::const_iterator option_it;
-
- S32 cat_id = 0;
- option_it = response.find("category_id");
- if (option_it != response.end())
+ LLSD name = (*resp_it)["category_name"];
+ if(name.isDefined())
{
- cat_id = atoi(option_it->second.c_str());
+ LLSD id = (*resp_it)["category_id"];
+ if(id.isDefined())
+ {
+ LLClassifiedInfo::sCategories[id.asInteger()] = name.asString();
+ }
}
- else
- {
- continue;
- }
-
- // Add the category id/name pair
- option_it = response.find("category_name");
- if (option_it != response.end())
- {
- LLClassifiedInfo::sCategories[cat_id] = option_it->second;
- }
-
}
-
}
diff --git a/indra/newview/llclassifiedinfo.h b/indra/newview/llclassifiedinfo.h
index cc5a6bf28f..37134c7e5b 100644
--- a/indra/newview/llclassifiedinfo.h
+++ b/indra/newview/llclassifiedinfo.h
@@ -37,7 +37,6 @@
#include "v3dmath.h"
#include "lluuid.h"
-#include "lluserauth.h"
class LLMessageSystem;
@@ -46,7 +45,7 @@ class LLClassifiedInfo
public:
LLClassifiedInfo() {}
- static void loadCategories(LLUserAuth::options_t event_options);
+ static void loadCategories(const LLSD& options);
typedef std::map<U32, std::string> cat_map;
static cat_map sCategories;
diff --git a/indra/newview/llclassifiedstatsresponder.cpp b/indra/newview/llclassifiedstatsresponder.cpp
index a218e2b4e5..ecd1879090 100644
--- a/indra/newview/llclassifiedstatsresponder.cpp
+++ b/indra/newview/llclassifiedstatsresponder.cpp
@@ -33,7 +33,6 @@
#include "llviewerprecompiledheaders.h"
-#include "llagent.h"
#include "llclassifiedstatsresponder.h"
#include "llpanelclassified.h"
diff --git a/indra/newview/llclassifiedstatsresponder.h b/indra/newview/llclassifiedstatsresponder.h
index c4591df8de..9c52ed5ae1 100644
--- a/indra/newview/llclassifiedstatsresponder.h
+++ b/indra/newview/llclassifiedstatsresponder.h
@@ -44,6 +44,7 @@ public:
//If we get back a normal response, handle it here
virtual void result(const LLSD& content);
//If we get back an error (not found, etc...), handle it here
+
virtual void error(U32 status, const std::string& reason);
protected:
diff --git a/indra/newview/llcloud.cpp b/indra/newview/llcloud.cpp
index 0099817de4..af6f4e3286 100644
--- a/indra/newview/llcloud.cpp
+++ b/indra/newview/llcloud.cpp
@@ -37,6 +37,7 @@
#include "v3math.h"
#include "v4math.h"
#include "llquaternion.h"
+#include "llrand.h"
#include "v4color.h"
#include "llwind.h"
diff --git a/indra/newview/llcloud.h b/indra/newview/llcloud.h
index f4ae03b689..155bf4eae9 100644
--- a/indra/newview/llcloud.h
+++ b/indra/newview/llcloud.h
@@ -72,7 +72,7 @@
#include "v3dmath.h"
#include "v4math.h"
#include "v4color.h"
-#include "llmemory.h"
+#include "llpointer.h"
#include "lldarray.h"
#include "llframetimer.h"
diff --git a/indra/newview/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp
index 5f8d9ed27b..dc6847f236 100644
--- a/indra/newview/llcolorswatch.cpp
+++ b/indra/newview/llcolorswatch.cpp
@@ -37,74 +37,69 @@
// Linden library includes
#include "v4color.h"
+#include "llwindow.h" // setCursor()
// Project includes
#include "llui.h"
#include "llrender.h"
#include "lluiconstants.h"
-#include "llviewerwindow.h"
#include "llviewercontrol.h"
#include "llbutton.h"
#include "lltextbox.h"
#include "llfloatercolorpicker.h"
#include "llviewborder.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llfocusmgr.h"
-static LLRegisterWidget<LLColorSwatchCtrl> r("color_swatch");
+static LLDefaultChildRegistry::Register<LLColorSwatchCtrl> r("color_swatch");
-LLColorSwatchCtrl::LLColorSwatchCtrl(const std::string& name, const LLRect& rect, const LLColor4& color,
- void (*commit_callback)(LLUICtrl* ctrl, void* userdata),
- void* userdata )
-: LLUICtrl(name, rect, TRUE, commit_callback, userdata, FOLLOWS_LEFT | FOLLOWS_TOP),
- mValid( TRUE ),
- mColor( color ),
- mBorderColor( gColors.getColor("DefaultHighlightLight") ),
- mCanApplyImmediately(FALSE),
- mOnCancelCallback(NULL),
- mOnSelectCallback(NULL)
+LLColorSwatchCtrl::Params::Params()
+: color("color", LLColor4::white),
+ can_apply_immediately("can_apply_immediately", false),
+ alpha_background_image("alpha_background_image"),
+ border_color("border_color"),
+ label_width("label_width", -1),
+ caption_text("caption_text"),
+ border("border")
{
- mCaption = new LLTextBox( name,
- LLRect( 0, BTN_HEIGHT_SMALL, getRect().getWidth(), 0 ),
- name,
- LLFontGL::getFontSansSerifSmall() );
- mCaption->setFollows( FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM );
- addChild( mCaption );
-
- // Scalable UI made this off-by-one, I don't know why. JC
- LLRect border_rect(0, getRect().getHeight()-1, getRect().getWidth()-1, 0);
- border_rect.mBottom += BTN_HEIGHT_SMALL;
- mBorder = new LLViewBorder(std::string("border"), border_rect, LLViewBorder::BEVEL_IN);
- addChild(mBorder);
-
- mAlphaGradientImage = LLUI::getUIImage("color_swatch_alpha.tga");
+ name = "colorswatch";
}
-LLColorSwatchCtrl::LLColorSwatchCtrl(const std::string& name, const LLRect& rect, const std::string& label, const LLColor4& color,
- void (*commit_callback)(LLUICtrl* ctrl, void* userdata),
- void* userdata )
-: LLUICtrl(name, rect, TRUE, commit_callback, userdata, FOLLOWS_LEFT | FOLLOWS_TOP),
+LLColorSwatchCtrl::LLColorSwatchCtrl(const Params& p)
+: LLUICtrl(p),
mValid( TRUE ),
- mColor( color ),
- mBorderColor( gColors.getColor("DefaultHighlightLight") ),
- mCanApplyImmediately(FALSE),
- mOnCancelCallback(NULL),
- mOnSelectCallback(NULL)
-{
- mCaption = new LLTextBox( label,
- LLRect( 0, BTN_HEIGHT_SMALL, getRect().getWidth(), 0 ),
- label,
- LLFontGL::getFontSansSerifSmall() );
- mCaption->setFollows( FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM );
+ mColor(p.color),
+ mCanApplyImmediately(p.can_apply_immediately),
+ mAlphaGradientImage(p.alpha_background_image),
+ mOnCancelCallback(p.cancel_callback()),
+ mOnSelectCallback(p.select_callback()),
+ mBorderColor(p.border_color()),
+ mLabelWidth(p.label_width)
+{
+ LLTextBox::Params tp = p.caption_text;
+ // label_width is specified, not -1
+ if(mLabelWidth!= -1)
+ {
+ tp.rect(LLRect( 0, BTN_HEIGHT_SMALL, mLabelWidth, 0 ));
+ }
+ else
+ {
+ tp.rect(LLRect( 0, BTN_HEIGHT_SMALL, getRect().getWidth(), 0 ));
+ }
+
+ tp.initial_value(p.label());
+ mCaption = LLUICtrlFactory::create<LLTextBox>(tp);
addChild( mCaption );
- // Scalable UI made this off-by-one, I don't know why. JC
- LLRect border_rect(0, getRect().getHeight()-1, getRect().getWidth()-1, 0);
+ LLRect border_rect = getLocalRect();
+ border_rect.mTop -= 1;
+ border_rect.mRight -=1;
border_rect.mBottom += BTN_HEIGHT_SMALL;
- mBorder = new LLViewBorder(std::string("border"), border_rect, LLViewBorder::BEVEL_IN);
- addChild(mBorder);
- mAlphaGradientImage = LLUI::getUIImage("color_swatch_alpha.tga");
+ LLViewBorder::Params params = p.border;
+ params.rect(border_rect);
+ mBorder = LLUICtrlFactory::create<LLViewBorder> (params);
+ addChild(mBorder);
}
LLColorSwatchCtrl::~LLColorSwatchCtrl ()
@@ -114,9 +109,8 @@ LLColorSwatchCtrl::~LLColorSwatchCtrl ()
if (pickerp)
{
pickerp->cancelSelection();
- pickerp->close();
+ pickerp->closeFloater();
}
- mAlphaGradientImage = NULL;
}
BOOL LLColorSwatchCtrl::handleDoubleClick(S32 x, S32 y, MASK mask)
@@ -203,10 +197,11 @@ BOOL LLColorSwatchCtrl::handleMouseUp(S32 x, S32 y, MASK mask)
// assumes GL state is set for 2D
void LLColorSwatchCtrl::draw()
{
+ F32 alpha = getDrawContext().mAlpha;
mBorder->setKeyboardFocusHighlight(hasFocus());
// Draw border
LLRect border( 0, getRect().getHeight(), getRect().getWidth(), BTN_HEIGHT_SMALL );
- gl_rect_2d( border, mBorderColor, FALSE );
+ gl_rect_2d( border, mBorderColor.get(), FALSE );
LLRect interior = border;
interior.stretch( -1 );
@@ -233,20 +228,21 @@ void LLColorSwatchCtrl::draw()
{
if (!mFallbackImageName.empty())
{
- LLPointer<LLViewerImage> fallback_image = gImageList.getImageFromFile(mFallbackImageName);
+ LLPointer<LLViewerFetchedTexture> fallback_image = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, TRUE,
+ LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
if( fallback_image->getComponents() == 4 )
{
gl_rect_2d_checkerboard( interior );
}
- gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), fallback_image);
+ gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), fallback_image, LLColor4::white % alpha);
fallback_image->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) );
}
else
{
// Draw grey and an X
- gl_rect_2d(interior, LLColor4::grey, TRUE);
+ gl_rect_2d(interior, LLColor4::grey % alpha, TRUE);
- gl_draw_x(interior, LLColor4::black);
+ gl_draw_x(interior, LLColor4::black % alpha);
}
}
@@ -264,7 +260,7 @@ void LLColorSwatchCtrl::setEnabled( BOOL enabled )
if (pickerp)
{
pickerp->cancelSelection();
- pickerp->close();
+ pickerp->closeFloater();
}
}
}
@@ -295,11 +291,11 @@ void LLColorSwatchCtrl::onColorChanged ( void* data, EColorPickOp pick_op )
if (pick_op == COLOR_CANCEL && subject->mOnCancelCallback)
{
- subject->mOnCancelCallback(subject, subject->mCallbackUserData);
+ subject->mOnCancelCallback( subject, LLSD());
}
else if (pick_op == COLOR_SELECT && subject->mOnSelectCallback)
{
- subject->mOnSelectCallback(subject, subject->mCallbackUserData);
+ subject->mOnSelectCallback( subject, LLSD() );
}
else
{
@@ -310,6 +306,21 @@ void LLColorSwatchCtrl::onColorChanged ( void* data, EColorPickOp pick_op )
}
}
+// This is called when the main floatercustomize panel is closed.
+// Since this class has pointers up to its parents, we need to cleanup
+// this class first in order to avoid a crash.
+void LLColorSwatchCtrl::onParentFloaterClosed()
+{
+ LLFloaterColorPicker* pickerp = (LLFloaterColorPicker*)mPickerHandle.get();
+ if (pickerp)
+ {
+ pickerp->setSwatch(NULL);
+ pickerp->closeFloater();
+ }
+
+ mPickerHandle.markDead();
+}
+
void LLColorSwatchCtrl::setValid(BOOL valid )
{
mValid = valid;
@@ -327,7 +338,7 @@ void LLColorSwatchCtrl::showPicker(BOOL take_focus)
if (!pickerp)
{
pickerp = new LLFloaterColorPicker(this, mCanApplyImmediately);
- gFloaterView->getParentFloater(this)->addDependentFloater(pickerp);
+ //gFloaterView->getParentFloater(this)->addDependentFloater(pickerp);
mPickerHandle = pickerp->getHandle();
}
@@ -343,59 +354,3 @@ void LLColorSwatchCtrl::showPicker(BOOL take_focus)
}
}
-// virtual
-LLXMLNodePtr LLColorSwatchCtrl::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLUICtrl::getXML();
-
- node->createChild("color", TRUE)->setFloatValue(4, mColor.mV);
-
- node->createChild("border_color", TRUE)->setFloatValue(4, mBorderColor.mV);
-
- if (mCaption)
- {
- node->createChild("label", TRUE)->setStringValue(mCaption->getText());
- }
-
- node->createChild("can_apply_immediately", TRUE)->setBoolValue(mCanApplyImmediately);
-
- return node;
-}
-
-LLView* LLColorSwatchCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("colorswatch");
- node->getAttributeString("name", name);
-
- std::string label;
- node->getAttributeString("label", label);
-
- LLColor4 color(1.f, 1.f, 1.f, 1.f);
- node->getAttributeColor("initial_color", color);
-
- LLRect rect;
- createRect(node, rect, parent, LLRect());
-
- BOOL can_apply_immediately = FALSE;
- node->getAttributeBOOL("can_apply_immediately", can_apply_immediately);
-
- LLUICtrlCallback callback = NULL;
-
- if (label.empty())
- {
- label.assign(node->getValue());
- }
-
- LLColorSwatchCtrl* color_swatch = new LLColorSwatchCtrl(
- name,
- rect,
- label,
- color,
- callback,
- NULL );
-
- color_swatch->setCanApplyImmediately(can_apply_immediately);
- color_swatch->initFromXML(node, parent);
-
- return color_swatch;
-}
diff --git a/indra/newview/llcolorswatch.h b/indra/newview/llcolorswatch.h
index 0dd021f51f..4bb7d837cb 100644
--- a/indra/newview/llcolorswatch.h
+++ b/indra/newview/llcolorswatch.h
@@ -36,7 +36,8 @@
#include "lluictrl.h"
#include "v4color.h"
#include "llfloater.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
+#include "lltextbox.h"
//
// Classes
@@ -44,7 +45,7 @@
class LLColor4;
class LLTextBox;
class LLFloaterColorPicker;
-class LLViewerImage;
+class LLViewerTexture;
class LLColorSwatchCtrl
: public LLUICtrl
@@ -57,53 +58,66 @@ public:
COLOR_CANCEL
} EColorPickOp;
- LLColorSwatchCtrl(const std::string& name, const LLRect& rect, const LLColor4& color,
- void (*on_commit_callback)(LLUICtrl* ctrl, void* userdata),
- void* callback_userdata);
- LLColorSwatchCtrl(const std::string& name, const LLRect& rect, const std::string& label, const LLColor4& color,
- void (*on_commit_callback)(LLUICtrl* ctrl, void* userdata),
- void* callback_userdata);
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<LLColor4> color;
+ Optional<bool> can_apply_immediately;
+ Optional<LLUIImage*> alpha_background_image;
+ Optional<commit_callback_t> cancel_callback;
+ Optional<commit_callback_t> select_callback;
+ Optional<LLUIColor> border_color;
+ Optional<S32> label_width;
+
+ Optional<LLTextBox::Params> caption_text;
+ Optional<LLViewBorder::Params> border;
+ Params();
+ };
+protected:
+ LLColorSwatchCtrl(const Params& p);
+ friend class LLUICtrlFactory;
+public:
~LLColorSwatchCtrl ();
- virtual void setValue(const LLSD& value);
+ /*virtual*/ void setValue(const LLSD& value);
- virtual LLSD getValue() const { return mColor.getValue(); }
+ /*virtual*/ LLSD getValue() const { return mColor.getValue(); }
const LLColor4& get() { return mColor; }
void set(const LLColor4& color, BOOL update_picker = FALSE, BOOL from_event = FALSE);
void setOriginal(const LLColor4& color);
void setValid(BOOL valid);
void setLabel(const std::string& label);
+ void setLabelWidth(S32 label_width) {mLabelWidth =label_width;}
void setCanApplyImmediately(BOOL apply) { mCanApplyImmediately = apply; }
- void setOnCancelCallback(LLUICtrlCallback cb) { mOnCancelCallback = cb; }
- void setOnSelectCallback(LLUICtrlCallback cb) { mOnSelectCallback = cb; }
+ void setOnCancelCallback(commit_callback_t cb) { mOnCancelCallback = cb; }
+ void setOnSelectCallback(commit_callback_t cb) { mOnSelectCallback = cb; }
void setFallbackImageName(const std::string& name) { mFallbackImageName = name; }
void showPicker(BOOL take_focus);
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleDoubleClick(S32 x,S32 y,MASK mask);
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual BOOL handleUnicodeCharHere(llwchar uni_char);
- virtual void draw();
- virtual void setEnabled( BOOL enabled );
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleDoubleClick(S32 x,S32 y,MASK mask);
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char);
+ /*virtual*/ void draw();
+ /*virtual*/ void setEnabled( BOOL enabled );
static void onColorChanged ( void* data, EColorPickOp pick_op = COLOR_CHANGE );
+ void onParentFloaterClosed();
protected:
BOOL mValid;
LLColor4 mColor;
- LLColor4 mBorderColor;
+ LLUIColor mBorderColor;
LLTextBox* mCaption;
LLHandle<LLFloater> mPickerHandle;
LLViewBorder* mBorder;
BOOL mCanApplyImmediately;
- LLUICtrlCallback mOnCancelCallback;
- LLUICtrlCallback mOnSelectCallback;
+ commit_callback_t mOnCancelCallback;
+ commit_callback_t mOnSelectCallback;
+ S32 mLabelWidth;
LLPointer<LLUIImage> mAlphaGradientImage;
std::string mFallbackImageName;
diff --git a/indra/newview/llcommanddispatcherlistener.cpp b/indra/newview/llcommanddispatcherlistener.cpp
new file mode 100644
index 0000000000..91baeaf989
--- /dev/null
+++ b/indra/newview/llcommanddispatcherlistener.cpp
@@ -0,0 +1,60 @@
+/**
+ * @file llcommanddispatcherlistener.cpp
+ * @author Nat Goodspeed
+ * @date 2009-12-10
+ * @brief Implementation for llcommanddispatcherlistener.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "llviewerprecompiledheaders.h"
+// associated header
+#include "llcommanddispatcherlistener.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llcommandhandler.h"
+
+LLCommandDispatcherListener::LLCommandDispatcherListener(/* LLCommandDispatcher* instance */):
+ LLEventAPI("LLCommandDispatcher", "Access to LLCommandHandler commands") /* ,
+ mDispatcher(instance) */
+{
+ add("dispatch",
+ "Execute a command registered as an LLCommandHandler,\n"
+ "passing any required parameters:\n"
+ "[\"cmd\"] string command name\n"
+ "[\"params\"] array of parameters, as if from components of URL path\n"
+ "[\"query\"] map of parameters, as if from ?key1=val&key2=val\n"
+ "[\"trusted\"] boolean indicating trusted browser [default true]",
+ &LLCommandDispatcherListener::dispatch);
+ add("enumerate",
+ "Post to [\"reply\"] a map of registered LLCommandHandler instances, containing\n"
+ "name key and (e.g.) untrusted flag",
+ &LLCommandDispatcherListener::enumerate,
+ LLSD().with("reply", LLSD()));
+}
+
+void LLCommandDispatcherListener::dispatch(const LLSD& params) const
+{
+ // For most purposes, we expect callers to want to be trusted.
+ bool trusted_browser = true;
+ if (params.has("trusted"))
+ {
+ // But for testing, allow a caller to specify untrusted.
+ trusted_browser = params["trusted"].asBoolean();
+ }
+ LLCommandDispatcher::dispatch(params["cmd"], params["params"], params["query"], NULL,
+ trusted_browser);
+}
+
+void LLCommandDispatcherListener::enumerate(const LLSD& params) const
+{
+ LLReqID reqID(params);
+ LLSD response(LLCommandDispatcher::enumerate());
+ reqID.stamp(response);
+ LLEventPumps::instance().obtain(params["reply"]).post(response);
+}
diff --git a/indra/newview/llcommanddispatcherlistener.h b/indra/newview/llcommanddispatcherlistener.h
new file mode 100644
index 0000000000..9bcddebcc1
--- /dev/null
+++ b/indra/newview/llcommanddispatcherlistener.h
@@ -0,0 +1,31 @@
+/**
+ * @file llcommanddispatcherlistener.h
+ * @author Nat Goodspeed
+ * @date 2009-12-10
+ * @brief LLEventAPI for LLCommandDispatcher
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLCOMMANDDISPATCHERLISTENER_H)
+#define LL_LLCOMMANDDISPATCHERLISTENER_H
+
+#include "lleventapi.h"
+class LLCommandDispatcher;
+class LLSD;
+
+class LLCommandDispatcherListener: public LLEventAPI
+{
+public:
+ LLCommandDispatcherListener(/* LLCommandDispatcher* instance */); // all static members
+
+private:
+ void dispatch(const LLSD& params) const;
+ void enumerate(const LLSD& params) const;
+
+ //LLCommandDispatcher* mDispatcher;
+};
+
+#endif /* ! defined(LL_LLCOMMANDDISPATCHERLISTENER_H) */
diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp
index 422c94ade5..dc506a1692 100644
--- a/indra/newview/llcommandhandler.cpp
+++ b/indra/newview/llcommandhandler.cpp
@@ -34,16 +34,23 @@
#include "llviewerprecompiledheaders.h"
#include "llcommandhandler.h"
+#include "llnotificationsutil.h"
+#include "llcommanddispatcherlistener.h"
+#include "stringize.h"
// system includes
#include <boost/tokenizer.hpp>
+#define THROTTLE_PERIOD 15 // required secs between throttled commands
+
+static LLCommandDispatcherListener sCommandDispatcherListener;
+
//---------------------------------------------------------------------------
// Underlying registry for command handlers, not directly accessible.
//---------------------------------------------------------------------------
struct LLCommandHandlerInfo
{
- bool mRequireTrustedBrowser;
+ LLCommandHandler::EUntrustedAccess mUntrustedBrowserAccess;
LLCommandHandler* mHandler; // safe, all of these are static objects
};
@@ -51,14 +58,17 @@ class LLCommandHandlerRegistry
{
public:
static LLCommandHandlerRegistry& instance();
- void add(const char* cmd, bool require_trusted_browser, LLCommandHandler* handler);
+ void add(const char* cmd,
+ LLCommandHandler::EUntrustedAccess untrusted_access,
+ LLCommandHandler* handler);
bool dispatch(const std::string& cmd,
const LLSD& params,
const LLSD& query_map,
- LLWebBrowserCtrl* web,
+ LLMediaCtrl* web,
bool trusted_browser);
private:
+ friend LLSD LLCommandDispatcher::enumerate();
std::map<std::string, LLCommandHandlerInfo> mMap;
};
@@ -72,10 +82,12 @@ LLCommandHandlerRegistry& LLCommandHandlerRegistry::instance()
return instance;
}
-void LLCommandHandlerRegistry::add(const char* cmd, bool require_trusted_browser, LLCommandHandler* handler)
+void LLCommandHandlerRegistry::add(const char* cmd,
+ LLCommandHandler::EUntrustedAccess untrusted_access,
+ LLCommandHandler* handler)
{
LLCommandHandlerInfo info;
- info.mRequireTrustedBrowser = require_trusted_browser;
+ info.mUntrustedBrowserAccess = untrusted_access;
info.mHandler = handler;
mMap[cmd] = info;
@@ -84,18 +96,52 @@ void LLCommandHandlerRegistry::add(const char* cmd, bool require_trusted_browser
bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
const LLSD& params,
const LLSD& query_map,
- LLWebBrowserCtrl* web,
+ LLMediaCtrl* web,
bool trusted_browser)
{
+ static bool slurl_blocked = false;
+ static bool slurl_throttled = false;
+ static F64 last_throttle_time = 0.0;
+ F64 cur_time = 0.0;
std::map<std::string, LLCommandHandlerInfo>::iterator it = mMap.find(cmd);
if (it == mMap.end()) return false;
const LLCommandHandlerInfo& info = it->second;
- if (!trusted_browser && info.mRequireTrustedBrowser)
+ if (!trusted_browser)
{
- // block request from external browser, but report as
- // "handled" because it was well formatted.
- LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL;
- return true;
+ switch (info.mUntrustedBrowserAccess)
+ {
+ case LLCommandHandler::UNTRUSTED_ALLOW:
+ // fall through and let the command be handled
+ break;
+
+ case LLCommandHandler::UNTRUSTED_BLOCK:
+ // block request from external browser, but report as
+ // "handled" because it was well formatted.
+ LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL;
+ if (! slurl_blocked)
+ {
+ LLNotificationsUtil::add("BlockedSLURL");
+ slurl_blocked = true;
+ }
+ return true;
+
+ case LLCommandHandler::UNTRUSTED_THROTTLE:
+ cur_time = LLTimer::getElapsedSeconds();
+ if (cur_time < last_throttle_time + THROTTLE_PERIOD)
+ {
+ // block request from external browser if it happened
+ // within THROTTLE_PERIOD secs of the last command
+ LL_WARNS_ONCE("SLURL") << "Throttled SLURL command from untrusted browser" << LL_ENDL;
+ if (! slurl_throttled)
+ {
+ LLNotificationsUtil::add("ThrottledSLURL");
+ slurl_throttled = true;
+ }
+ return true;
+ }
+ last_throttle_time = cur_time;
+ break;
+ }
}
if (!info.mHandler) return false;
return info.mHandler->handle(params, query_map, web);
@@ -106,10 +152,9 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
//---------------------------------------------------------------------------
LLCommandHandler::LLCommandHandler(const char* cmd,
- bool require_trusted_browser)
+ EUntrustedAccess untrusted_access)
{
- LLCommandHandlerRegistry::instance().add(
- cmd, require_trusted_browser, this);
+ LLCommandHandlerRegistry::instance().add(cmd, untrusted_access, this);
}
LLCommandHandler::~LLCommandHandler()
@@ -126,9 +171,62 @@ LLCommandHandler::~LLCommandHandler()
bool LLCommandDispatcher::dispatch(const std::string& cmd,
const LLSD& params,
const LLSD& query_map,
- LLWebBrowserCtrl* web,
+ LLMediaCtrl* web,
bool trusted_browser)
{
return LLCommandHandlerRegistry::instance().dispatch(
cmd, params, query_map, web, trusted_browser);
}
+
+static std::string lookup(LLCommandHandler::EUntrustedAccess value);
+
+LLSD LLCommandDispatcher::enumerate()
+{
+ LLSD response;
+ LLCommandHandlerRegistry& registry(LLCommandHandlerRegistry::instance());
+ for (std::map<std::string, LLCommandHandlerInfo>::const_iterator chi(registry.mMap.begin()),
+ chend(registry.mMap.end());
+ chi != chend; ++chi)
+ {
+ LLSD info;
+ info["untrusted"] = chi->second.mUntrustedBrowserAccess;
+ info["untrusted_str"] = lookup(chi->second.mUntrustedBrowserAccess);
+ response[chi->first] = info;
+ }
+ return response;
+}
+
+/*------------------------------ lookup stuff ------------------------------*/
+struct symbol_info
+{
+ const char* name;
+ LLCommandHandler::EUntrustedAccess value;
+};
+
+#define ent(SYMBOL) \
+ { \
+ #SYMBOL + 28, /* skip "LLCommandHandler::UNTRUSTED_" prefix */ \
+ SYMBOL \
+ }
+
+symbol_info symbols[] =
+{
+ ent(LLCommandHandler::UNTRUSTED_ALLOW), // allow commands from untrusted browsers
+ ent(LLCommandHandler::UNTRUSTED_BLOCK), // ignore commands from untrusted browsers
+ ent(LLCommandHandler::UNTRUSTED_THROTTLE) // allow untrusted, but only a few per min.
+};
+
+#undef ent
+
+static std::string lookup(LLCommandHandler::EUntrustedAccess value)
+{
+ for (symbol_info *sii(symbols), *siend(symbols + (sizeof(symbols)/sizeof(symbols[0])));
+ sii != siend; ++sii)
+ {
+ if (sii->value == value)
+ {
+ return sii->name;
+ }
+ }
+ return STRINGIZE("UNTRUSTED_" << value);
+}
diff --git a/indra/newview/llcommandhandler.h b/indra/newview/llcommandhandler.h
index ab4c2cc488..a1d4c880f5 100644
--- a/indra/newview/llcommandhandler.h
+++ b/indra/newview/llcommandhandler.h
@@ -34,6 +34,8 @@
#ifndef LLCOMMANDHANDLER_H
#define LLCOMMANDHANDLER_H
+#include "llsd.h"
+
/* Example: secondlife:///app/foo/<uuid>
Command "foo" that takes one parameter, a UUID.
@@ -43,11 +45,11 @@ public:
// Inform the system you handle commands starting
// with "foo" and they are only allowed from
// "trusted" (pointed at Linden content) browsers
- LLFooHandler() : LLCommandHandler("foo", true) { }
+ LLFooHandler() : LLCommandHandler("foo", UNTRUSTED_BLOCK) { }
// Your code here
bool handle(const LLSD& tokens, const LLSD& query_map,
- LLWebBrowserCtrl* web)
+ LLMediaCtrl* web)
{
if (tokens.size() < 1) return false;
LLUUID id( tokens[0] );
@@ -60,22 +62,29 @@ LLFooHandler gFooHandler;
*/
-class LLWebBrowserCtrl;
+class LLMediaCtrl;
class LLCommandHandler
{
public:
- LLCommandHandler(const char* command, bool allow_from_untrusted_browser);
+ enum EUntrustedAccess
+ {
+ UNTRUSTED_ALLOW, // allow commands from untrusted browsers
+ UNTRUSTED_BLOCK, // ignore commands from untrusted browsers
+ UNTRUSTED_THROTTLE // allow untrusted, but only a few per min.
+ };
+
+ LLCommandHandler(const char* command, EUntrustedAccess untrusted_access);
// Automatically registers object to get called when
// command is executed. All commands can be processed
- // in links from LLWebBrowserCtrl, but some (like teleport)
+ // in links from LLMediaCtrl, but some (like teleport)
// should not be allowed from outside the app.
virtual ~LLCommandHandler();
virtual bool handle(const LLSD& params,
const LLSD& query_map,
- LLWebBrowserCtrl* web) = 0;
+ LLMediaCtrl* web) = 0;
// For URL secondlife:///app/foo/bar/baz?cat=1&dog=2
// @params - array of "bar", "baz", possibly empty
// @query_map - map of "cat" -> 1, "dog" -> 2, possibly empty
@@ -91,11 +100,14 @@ public:
static bool dispatch(const std::string& cmd,
const LLSD& params,
const LLSD& query_map,
- LLWebBrowserCtrl* web,
+ LLMediaCtrl* web,
bool trusted_browser);
// Execute a command registered via the above mechanism,
// passing string parameters.
// Returns true if command was found and executed correctly.
+ /// Return an LLSD::Map of registered LLCommandHandlers and associated
+ /// info (e.g. EUntrustedAccess).
+ static LLSD enumerate();
};
#endif
diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp
index 689033a07b..47f1b7c9f5 100644
--- a/indra/newview/llcompilequeue.cpp
+++ b/indra/newview/llcompilequeue.cpp
@@ -46,6 +46,7 @@
#include "llassetuploadqueue.h"
#include "llassetuploadresponders.h"
#include "llchat.h"
+#include "llfloaterreg.h"
#include "llviewerwindow.h"
#include "llviewerobject.h"
#include "llviewerobjectlist.h"
@@ -55,28 +56,24 @@
#include "llviewerobject.h"
#include "llviewerregion.h"
#include "llresmgr.h"
+
#include "llbutton.h"
#include "lldir.h"
-#include "llfloaterchat.h"
+#include "llnotificationsutil.h"
#include "llviewerstats.h"
+#include "llvfile.h"
#include "lluictrlfactory.h"
+#include "lltrans.h"
#include "llselectmgr.h"
+// *TODO: This should be separated into the script queue, and the floater views of that queue.
+// There should only be one floater class that can view any queue type
+
///----------------------------------------------------------------------------
/// Local function declarations, constants, enums, and typedefs
///----------------------------------------------------------------------------
-// *TODO:Translate
-const std::string COMPILE_QUEUE_TITLE("Recompilation Progress");
-const std::string COMPILE_START_STRING("recompile");
-const std::string RESET_QUEUE_TITLE("Reset Progress");
-const std::string RESET_START_STRING("reset");
-const std::string RUN_QUEUE_TITLE("Set Running Progress");
-const std::string RUN_START_STRING("set running");
-const std::string NOT_RUN_QUEUE_TITLE("Set Not Running Progress");
-const std::string NOT_RUN_START_STRING("set not running");
-
struct LLScriptQueueData
{
LLUUID mQueueID;
@@ -92,54 +89,26 @@ struct LLScriptQueueData
/// Class LLFloaterScriptQueue
///----------------------------------------------------------------------------
-// static
-LLMap<LLUUID, LLFloaterScriptQueue*> LLFloaterScriptQueue::sInstances;
-
-
// Default constructor
-LLFloaterScriptQueue::LLFloaterScriptQueue(const std::string& name,
- const LLRect& rect,
- const std::string& title,
- const std::string& start_string) :
- LLFloater(name, rect, title,
- RESIZE_YES, DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT,
- DRAG_ON_TOP, MINIMIZE_YES, CLOSE_YES)
+LLFloaterScriptQueue::LLFloaterScriptQueue(const LLSD& key) :
+ LLFloater(key),
+ mDone(FALSE)
{
- mID.generate();
-
- LLUICtrlFactory::getInstance()->buildFloater(this,"floater_script_queue.xml");
-
- childSetAction("close",onCloseBtn,this);
- childSetEnabled("close",FALSE);
-
- setTitle(title);
-
- LLRect curRect = getRect();
- translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop);
-
- mStartString = start_string;
- mDone = FALSE;
- sInstances.addData(mID, this);
+ //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this,"floater_script_queue.xml", FALSE);
}
// Destroys the object
LLFloaterScriptQueue::~LLFloaterScriptQueue()
{
- sInstances.removeData(mID);
}
-// find an instance by ID. Return NULL if it does not exist.
-// static
-LLFloaterScriptQueue* LLFloaterScriptQueue::findInstance(const LLUUID& id)
+BOOL LLFloaterScriptQueue::postBuild()
{
- if(sInstances.checkData(id))
- {
- return sInstances.getData(id);
- }
- return NULL;
+ childSetAction("close",onCloseBtn,this);
+ childSetEnabled("close",FALSE);
+ return TRUE;
}
-
// This is the callback method for the viewer object currently being
// worked on.
// NOT static, virtual!
@@ -185,7 +154,7 @@ void LLFloaterScriptQueue::inventoryChanged(LLViewerObject* viewer_object,
void LLFloaterScriptQueue::onCloseBtn(void* user_data)
{
LLFloaterScriptQueue* self = (LLFloaterScriptQueue*)user_data;
- self->close();
+ self->closeFloater();
}
void LLFloaterScriptQueue::addObject(const LLUUID& id)
@@ -210,10 +179,12 @@ BOOL LLFloaterScriptQueue::start()
n_objects = selectHandle->getRootObjectCount();
}
- buffer = llformat("Starting %s of %d items.", mStartString.c_str(), n_objects); // *TODO: Translate
+ LLStringUtil::format_map_t args;
+ args["[START]"] = mStartString;
+ args["[COUNT]"] = llformat ("%d", mObjectIDs.count());
+ buffer = getString ("Starting", args);
- LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
- list->addCommentText(buffer);
+ getChild<LLScrollListCtrl>("queue output")->setCommentText(buffer);
return nextObject();
}
@@ -245,12 +216,8 @@ BOOL LLFloaterScriptQueue::nextObject()
} while((mObjectIDs.count() > 0) && !successful_start);
if(isDone() && !mDone)
{
-
- LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
-
mDone = TRUE;
- std::string buffer = "Done."; // *TODO: Translate
- list->addCommentText(buffer);
+ getChild<LLScrollListCtrl>("queue output")->setCommentText(getString("Done"));
childSetEnabled("close",TRUE);
}
return successful_start;
@@ -275,7 +242,7 @@ BOOL LLFloaterScriptQueue::popNext()
{
llinfos << "LLFloaterScriptQueue::popNext() requesting inv for "
<< mCurrentObjectID << llendl;
- LLUUID* id = new LLUUID(mID);
+ LLUUID* id = new LLUUID(getKey().asUUID());
registerVOInventoryListener(obj,id);
requestVOInventory();
rv = TRUE;
@@ -289,64 +256,48 @@ BOOL LLFloaterScriptQueue::popNext()
/// Class LLFloaterCompileQueue
///----------------------------------------------------------------------------
-// static
-LLFloaterCompileQueue* LLFloaterCompileQueue::create(BOOL mono)
+class LLCompileFloaterUploadQueueSupplier : public LLAssetUploadQueueSupplier
{
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- LLRect rect = gSavedSettings.getRect("CompileOutputRect");
- rect.translate(left - rect.mLeft, top - rect.mTop);
- LLFloaterCompileQueue* new_queue = new LLFloaterCompileQueue("queue", rect);
+public:
- class LLCompileFloaterUploadQueueSupplier : public LLAssetUploadQueueSupplier
+ LLCompileFloaterUploadQueueSupplier(const LLUUID& queue_id) :
+ mQueueId(queue_id)
{
- public:
-
- LLCompileFloaterUploadQueueSupplier(const LLUUID& queue_id) :
- mQueueId(queue_id)
- {
- }
+ }
- virtual LLAssetUploadQueue* get() const
+ virtual LLAssetUploadQueue* get() const
+ {
+ LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", LLSD(mQueueId));
+ if(NULL == queue)
{
- LLFloaterCompileQueue* queue =
- (LLFloaterCompileQueue*) LLFloaterScriptQueue::findInstance(mQueueId);
-
- if(NULL == queue)
- {
- return NULL;
- }
-
- return queue->mUploadQueue;
+ return NULL;
}
+ return queue->getUploadQueue();
+ }
- virtual void log(std::string message) const
+ virtual void log(std::string message) const
+ {
+ LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", LLSD(mQueueId));
+ if(NULL == queue)
{
- LLFloaterCompileQueue* queue =
- (LLFloaterCompileQueue*) LLFloaterScriptQueue::findInstance(mQueueId);
-
- if(NULL == queue)
- {
- return;
- }
-
- LLScrollListCtrl* list = queue->getChild<LLScrollListCtrl>("queue output");
- list->addCommentText(message.c_str());
+ return;
}
+
+ queue->getChild<LLScrollListCtrl>("queue output")->setCommentText(message);
+ }
- private:
- LLUUID mQueueId;
- };
-
- new_queue->mUploadQueue = new LLAssetUploadQueue(new LLCompileFloaterUploadQueueSupplier(new_queue->getID()));
- new_queue->mMono = mono;
- new_queue->open();
- return new_queue;
-}
+private:
+ LLUUID mQueueId;
+};
-LLFloaterCompileQueue::LLFloaterCompileQueue(const std::string& name, const LLRect& rect)
-: LLFloaterScriptQueue(name, rect, COMPILE_QUEUE_TITLE, COMPILE_START_STRING)
-{ }
+LLFloaterCompileQueue::LLFloaterCompileQueue(const LLSD& key)
+ : LLFloaterScriptQueue(key)
+{
+ setTitle(LLTrans::getString("CompileQueueTitle"));
+ setStartString(LLTrans::getString("CompileQueueStart"));
+
+ mUploadQueue = new LLAssetUploadQueue(new LLCompileFloaterUploadQueueSupplier(key.asUUID()));
+}
LLFloaterCompileQueue::~LLFloaterCompileQueue()
{
@@ -391,7 +342,7 @@ void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object,
for(iter = asset_item_map.begin(); iter != asset_item_map.end(); iter++)
{
LLInventoryItem *itemp = iter->second;
- LLScriptQueueData* datap = new LLScriptQueueData(getID(),
+ LLScriptQueueData* datap = new LLScriptQueueData(getKey().asUUID(),
itemp->getName(),
viewer_object->getID(),
itemp->getUUID());
@@ -419,9 +370,12 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
{
llinfos << "LLFloaterCompileQueue::scriptArrived()" << llendl;
LLScriptQueueData* data = (LLScriptQueueData*)user_data;
- if(!data) return;
- LLFloaterCompileQueue* queue = static_cast<LLFloaterCompileQueue*>
- (LLFloaterScriptQueue::findInstance(data->mQueueID));
+ if(!data)
+ {
+ return;
+ }
+ LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", data->mQueueID);
+
std::string buffer;
if(queue && (0 == status))
{
@@ -447,13 +401,13 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
file.read(script_data, script_size);
queue->mUploadQueue->queue(filename, data->mTaskId,
- data->mItemId, is_running, queue->mMono, queue->getID(),
- script_data, script_size, data->mScriptName);
+ data->mItemId, is_running, queue->mMono, queue->getKey().asUUID(),
+ script_data, script_size, data->mScriptName);
}
else
{
// It's now in the file, now compile it.
- buffer = std::string("Downloaded, now compiling: ") + data->mScriptName; // *TODO: Translate
+ buffer = LLTrans::getString("CompileQueueDownloadedCompiling") + (": ") + data->mScriptName;
// Write script to local file for compilation.
LLFILE *fp = LLFile::fopen(filename, "wb"); /*Flawfinder: ignore*/
@@ -492,19 +446,25 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status )
{
- LLChat chat(std::string("Script not found on server.")); // *TODO: Translate
- LLFloaterChat::addChat(chat);
- buffer = std::string("Problem downloading: ") + data->mScriptName; // *TODO: Translate
+ //TODO* CHAT: how to show this?
+ //LLSD args;
+ //args["MESSAGE"] = LLTrans::getString("CompileQueueScriptNotFound);
+ //LLNotificationsUtil::add("SystemMessage", args);
+
+ buffer = LLTrans::getString("CompileQueueProblemDownloading") + (": ") + data->mScriptName;
}
else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
{
- LLChat chat(std::string("Insufficient permissions to download a script.")); // *TODO: Translate
- LLFloaterChat::addChat(chat);
- buffer = std::string("Insufficient permissions for: ") + data->mScriptName; // *TODO: Translate
+ //TODO* CHAT: how to show this?
+ //LLSD args;
+ //args["MESSAGE"] = LLTrans::getString("CompileQueueScriptNotFound);
+ //LLNotificationsUtil::add("SystemMessage", args);
+
+ buffer = LLTrans::getString("CompileQueueInsufficientPermFor") + (": ") + data->mScriptName;
}
else
{
- buffer = std::string("Unknown failure to download ") + data->mScriptName; // *TODO: Translate
+ buffer = LLTrans::getString("CompileQueueUnknownFailure") + (" ") + data->mScriptName;
}
llwarns << "Problem downloading script asset." << llendl;
@@ -512,8 +472,7 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
}
if(queue && (buffer.size() > 0))
{
- LLScrollListCtrl* list = queue->getChild<LLScrollListCtrl>("queue output");
- list->addCommentText(buffer);
+ queue->getChild<LLScrollListCtrl>("queue output")->setCommentText(buffer);
}
delete data;
}
@@ -527,7 +486,7 @@ void LLFloaterCompileQueue::onSaveTextComplete(const LLUUID& asset_id, void* use
llwarns << "Unable to save text for script." << llendl;
LLSD args;
args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
- LLNotifications::instance().add("CompileQueueSaveText", args);
+ LLNotificationsUtil::add("CompileQueueSaveText", args);
}
}
@@ -536,8 +495,7 @@ void LLFloaterCompileQueue::onSaveBytecodeComplete(const LLUUID& asset_id, void*
{
llinfos << "LLFloaterCompileQueue::onSaveBytecodeComplete()" << llendl;
LLCompileQueueData* data = (LLCompileQueueData*)user_data;
- LLFloaterCompileQueue* queue = static_cast<LLFloaterCompileQueue*>
- (LLFloaterScriptQueue::findInstance(data->mQueueID));
+ LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", data->mQueueID);
if(queue && (0 == status) && data)
{
queue->saveItemByItemID(data->mItemId);
@@ -548,7 +506,7 @@ void LLFloaterCompileQueue::onSaveBytecodeComplete(const LLUUID& asset_id, void*
llwarns << "Unable to save bytecode for script." << llendl;
LLSD args;
args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
- LLNotifications::instance().add("CompileQueueSaveBytecode", args);
+ LLNotificationsUtil::add("CompileQueueSaveBytecode", args);
}
delete data;
data = NULL;
@@ -587,7 +545,7 @@ void LLFloaterCompileQueue::compile(const std::string& filename,
llinfos << "compile successful." << llendl;
// Save LSL bytecode
- LLCompileQueueData* data = new LLCompileQueueData(mID, item_id);
+ LLCompileQueueData* data = new LLCompileQueueData(getKey().asUUID(), item_id);
gAssetStorage->storeAssetData(dst_filename, new_asset_id,
LLAssetType::AT_LSL_BYTECODE,
&LLFloaterCompileQueue::onSaveBytecodeComplete,
@@ -656,23 +614,13 @@ void LLFloaterCompileQueue::saveItemByItemID(const LLUUID& asset_id)
/// Class LLFloaterResetQueue
///----------------------------------------------------------------------------
-// static
-LLFloaterResetQueue* LLFloaterResetQueue::create()
+LLFloaterResetQueue::LLFloaterResetQueue(const LLSD& key)
+ : LLFloaterScriptQueue(key)
{
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- LLRect rect = gSavedSettings.getRect("CompileOutputRect");
- rect.translate(left - rect.mLeft, top - rect.mTop);
- LLFloaterResetQueue* new_queue = new LLFloaterResetQueue("queue", rect);
- gFloaterView->addChild(new_queue);
- new_queue->open();
- return new_queue;
+ setTitle(LLTrans::getString("ResetQueueTitle"));
+ setStartString(LLTrans::getString("ResetQueueStart"));
}
-LLFloaterResetQueue::LLFloaterResetQueue(const std::string& name, const LLRect& rect)
-: LLFloaterScriptQueue(name, rect, RESET_QUEUE_TITLE, RESET_START_STRING)
-{ }
-
LLFloaterResetQueue::~LLFloaterResetQueue()
{
}
@@ -695,10 +643,9 @@ void LLFloaterResetQueue::handleInventory(LLViewerObject* viewer_obj,
if (object)
{
LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it));
- LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
std::string buffer;
- buffer = std::string("Resetting: ") + item->getName(); // *TODO: Translate
- list->addCommentText(buffer);
+ buffer = getString("Resetting") + (": ") + item->getName();
+ getChild<LLScrollListCtrl>("queue output")->setCommentText(buffer);
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_ScriptReset);
msg->nextBlockFast(_PREHASH_AgentData);
@@ -719,22 +666,13 @@ void LLFloaterResetQueue::handleInventory(LLViewerObject* viewer_obj,
/// Class LLFloaterRunQueue
///----------------------------------------------------------------------------
-// static
-LLFloaterRunQueue* LLFloaterRunQueue::create()
+LLFloaterRunQueue::LLFloaterRunQueue(const LLSD& key)
+ : LLFloaterScriptQueue(key)
{
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- LLRect rect = gSavedSettings.getRect("CompileOutputRect");
- rect.translate(left - rect.mLeft, top - rect.mTop);
- LLFloaterRunQueue* new_queue = new LLFloaterRunQueue("queue", rect);
- new_queue->open(); /*Flawfinder: ignore*/
- return new_queue;
+ setTitle(LLTrans::getString("RunQueueTitle"));
+ setStartString(LLTrans::getString("RunQueueStart"));
}
-LLFloaterRunQueue::LLFloaterRunQueue(const std::string& name, const LLRect& rect)
-: LLFloaterScriptQueue(name, rect, RUN_QUEUE_TITLE, RUN_START_STRING)
-{ }
-
LLFloaterRunQueue::~LLFloaterRunQueue()
{
}
@@ -759,8 +697,8 @@ void LLFloaterRunQueue::handleInventory(LLViewerObject* viewer_obj,
LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it));
LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
std::string buffer;
- buffer = std::string("Running: ") + item->getName(); // *TODO: Translate
- list->addCommentText(buffer);
+ buffer = getString("Running") + (": ") + item->getName();
+ list->setCommentText(buffer);
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_SetScriptRunning);
@@ -783,22 +721,13 @@ void LLFloaterRunQueue::handleInventory(LLViewerObject* viewer_obj,
/// Class LLFloaterNotRunQueue
///----------------------------------------------------------------------------
-// static
-LLFloaterNotRunQueue* LLFloaterNotRunQueue::create()
+LLFloaterNotRunQueue::LLFloaterNotRunQueue(const LLSD& key)
+ : LLFloaterScriptQueue(key)
{
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- LLRect rect = gSavedSettings.getRect("CompileOutputRect");
- rect.translate(left - rect.mLeft, top - rect.mTop);
- LLFloaterNotRunQueue* new_queue = new LLFloaterNotRunQueue("queue", rect);
- new_queue->open(); /*Flawfinder: ignore*/
- return new_queue;
+ setTitle(LLTrans::getString("NotRunQueueTitle"));
+ setStartString(LLTrans::getString("NotRunQueueStart"));
}
-LLFloaterNotRunQueue::LLFloaterNotRunQueue(const std::string& name, const LLRect& rect)
-: LLFloaterScriptQueue(name, rect, NOT_RUN_QUEUE_TITLE, NOT_RUN_START_STRING)
-{ }
-
LLFloaterNotRunQueue::~LLFloaterNotRunQueue()
{
}
@@ -823,8 +752,8 @@ void LLFloaterNotRunQueue::handleInventory(LLViewerObject* viewer_obj,
LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it));
LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
std::string buffer;
- buffer = std::string("Not running: ") +item->getName(); // *TODO: Translate
- list->addCommentText(buffer);
+ buffer = getString("NotRunning") + (": ") +item->getName();
+ list->setCommentText(buffer);
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_SetScriptRunning);
diff --git a/indra/newview/llcompilequeue.h b/indra/newview/llcompilequeue.h
index 51240423ba..063d573239 100644
--- a/indra/newview/llcompilequeue.h
+++ b/indra/newview/llcompilequeue.h
@@ -59,20 +59,20 @@
class LLFloaterScriptQueue : public LLFloater, public LLVOInventoryListener
{
public:
+ LLFloaterScriptQueue(const LLSD& key);
+ virtual ~LLFloaterScriptQueue();
+
+ /*virtual*/ BOOL postBuild();
+
+ void setMono(bool mono) { mMono = mono; }
+
// addObject() accepts an object id.
void addObject(const LLUUID& id);
// start() returns TRUE if the queue has started, otherwise FALSE.
BOOL start();
-
- // find an instance by ID. Return NULL if it does not exist.
- static LLFloaterScriptQueue* findInstance(const LLUUID& id);
-
+
protected:
- LLFloaterScriptQueue(const std::string& name, const LLRect& rect,
- const std::string& title, const std::string& start_string);
- virtual ~LLFloaterScriptQueue();
-
// This is the callback method for the viewer object currently
// being worked on.
/*virtual*/ void inventoryChanged(LLViewerObject* obj,
@@ -94,8 +94,7 @@ protected:
BOOL nextObject();
BOOL popNext();
- // Get this instances ID.
- const LLUUID& getID() const { return mID; }
+ void setStartString(const std::string& s) { mStartString = s; }
protected:
// UI
@@ -107,10 +106,8 @@ protected:
LLUUID mCurrentObjectID;
BOOL mDone;
- LLUUID mID;
- static LLMap<LLUUID, LLFloaterScriptQueue*> sInstances;
-
std::string mStartString;
+ BOOL mMono;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -131,20 +128,19 @@ class LLAssetUploadQueue;
class LLFloaterCompileQueue : public LLFloaterScriptQueue
{
+ friend class LLFloaterReg;
public:
- // Use this method to create a compile queue. Once created, it
- // will be responsible for it's own destruction.
- static LLFloaterCompileQueue* create(BOOL mono);
-
static void onSaveBytecodeComplete(const LLUUID& asset_id,
void* user_data,
S32 status);
// remove any object in mScriptScripts with the matching uuid.
void removeItemByItemID(const LLUUID& item_id);
+
+ LLAssetUploadQueue* getUploadQueue() { return mUploadQueue; }
protected:
- LLFloaterCompileQueue(const std::string& name, const LLRect& rect);
+ LLFloaterCompileQueue(const LLSD& key);
virtual ~LLFloaterCompileQueue();
// This is called by inventoryChanged
@@ -173,12 +169,11 @@ protected:
// find InventoryItem given item id.
const LLInventoryItem* findItemByItemID(const LLUUID& item_id) const;
-
+
protected:
LLViewerInventoryItem::item_array_t mCurrentScripts;
private:
- BOOL mMono; // Compile to mono.
LLAssetUploadQueue* mUploadQueue;
};
@@ -190,20 +185,14 @@ private:
class LLFloaterResetQueue : public LLFloaterScriptQueue
{
-public:
- // Use this method to create a reset queue. Once created, it
- // will be responsible for it's own destruction.
- static LLFloaterResetQueue* create();
-
+ friend class LLFloaterReg;
protected:
- LLFloaterResetQueue(const std::string& name, const LLRect& rect);
+ LLFloaterResetQueue(const LLSD& key);
virtual ~LLFloaterResetQueue();
// This is called by inventoryChanged
virtual void handleInventory(LLViewerObject* viewer_obj,
InventoryObjectList* inv);
-
-protected:
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -214,20 +203,14 @@ protected:
class LLFloaterRunQueue : public LLFloaterScriptQueue
{
-public:
- // Use this method to create a run queue. Once created, it
- // will be responsible for it's own destruction.
- static LLFloaterRunQueue* create();
-
+ friend class LLFloaterReg;
protected:
- LLFloaterRunQueue(const std::string& name, const LLRect& rect);
+ LLFloaterRunQueue(const LLSD& key);
virtual ~LLFloaterRunQueue();
// This is called by inventoryChanged
virtual void handleInventory(LLViewerObject* viewer_obj,
InventoryObjectList* inv);
-
-protected:
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -238,20 +221,14 @@ protected:
class LLFloaterNotRunQueue : public LLFloaterScriptQueue
{
-public:
- // Use this method to create a not run queue. Once created, it
- // will be responsible for it's own destruction.
- static LLFloaterNotRunQueue* create();
-
+ friend class LLFloaterReg;
protected:
- LLFloaterNotRunQueue(const std::string& name, const LLRect& rect);
+ LLFloaterNotRunQueue(const LLSD& key);
virtual ~LLFloaterNotRunQueue();
// This is called by inventoryChanged
virtual void handleInventory(LLViewerObject* viewer_obj,
InventoryObjectList* inv);
-
-protected:
};
#endif // LL_LLCOMPILEQUEUE_H
diff --git a/indra/newview/llconfirmationmanager.cpp b/indra/newview/llconfirmationmanager.cpp
index 00ffff79a8..4b73339957 100644
--- a/indra/newview/llconfirmationmanager.cpp
+++ b/indra/newview/llconfirmationmanager.cpp
@@ -37,9 +37,9 @@
#include "lluictrlfactory.h"
// viewer includes
-#include "llviewerwindow.h"
-#include "lllineeditor.h"
+#include "llnotificationsutil.h"
#include "llstring.h"
+#include "llxmlnode.h"
LLConfirmationManager::ListenerBase::~ListenerBase()
{
@@ -48,7 +48,7 @@ LLConfirmationManager::ListenerBase::~ListenerBase()
static bool onConfirmAlert(const LLSD& notification, const LLSD& response, LLConfirmationManager::ListenerBase* listener)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0)
{
listener->confirmed("");
@@ -61,7 +61,7 @@ static bool onConfirmAlert(const LLSD& notification, const LLSD& response, LLCon
static bool onConfirmAlertPassword(const LLSD& notification, const LLSD& response, LLConfirmationManager::ListenerBase* listener)
{
std::string text = response["message"].asString();
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0)
{
@@ -83,11 +83,11 @@ void LLConfirmationManager::confirm(Type type,
switch (type)
{
case TYPE_CLICK:
- LLNotifications::instance().add("ConfirmPurchase", args, LLSD(), boost::bind(onConfirmAlert, _1, _2, listener));
+ LLNotificationsUtil::add("ConfirmPurchase", args, LLSD(), boost::bind(onConfirmAlert, _1, _2, listener));
break;
case TYPE_PASSWORD:
- LLNotifications::instance().add("ConfirmPurchasePassword", args, LLSD(), boost::bind(onConfirmAlertPassword, _1, _2, listener));
+ LLNotificationsUtil::add("ConfirmPurchasePassword", args, LLSD(), boost::bind(onConfirmAlertPassword, _1, _2, listener));
break;
case TYPE_NONE:
default:
diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp
index 86821249a0..00c05445e1 100644
--- a/indra/newview/llcurrencyuimanager.cpp
+++ b/indra/newview/llcurrencyuimanager.cpp
@@ -35,6 +35,8 @@
#include "lluictrlfactory.h"
#include "lltextbox.h"
#include "lllineeditor.h"
+#include "llviewercontrol.h"
+#include "llversioninfo.h"
#include "llcurrencyuimanager.h"
@@ -46,6 +48,7 @@
#include "llviewchildren.h"
#include "llxmlrpctransaction.h"
#include "llviewernetwork.h"
+#include "llpanel.h"
const F64 CURRENCY_ESTIMATE_FREQUENCY = 2.0;
@@ -73,8 +76,16 @@ public:
bool mUserEnteredCurrencyBuy;
// from website
- bool mSiteCurrencyEstimated;
- S32 mSiteCurrencyEstimatedCost;
+
+ // pre-viewer 2.0, the server returned estimates as an
+ // integer US cents value, e.g., "1000" for $10.00
+ // post-viewer 2.0, the server may also return estimates
+ // as a string with currency embedded, e.g., "10.00 Euros"
+ bool mUSDCurrencyEstimated;
+ S32 mUSDCurrencyEstimatedCost;
+ bool mLocalCurrencyEstimated;
+ std::string mLocalCurrencyEstimatedCost;
+ bool mSupportsInternationalBilling;
std::string mSiteConfirm;
bool mBought;
@@ -98,6 +109,10 @@ public:
void startCurrencyBuy(const std::string& password);
void finishCurrencyBuy();
+
+ void clearEstimate();
+ bool hasEstimate() const;
+ std::string getLocalEstimate() const;
void startTransaction(TransactionType type,
const char* method, LLXMLRPCValue params);
@@ -123,12 +138,12 @@ LLCurrencyUIManager::Impl::Impl(LLPanel& dialog)
mError(false),
mUserCurrencyBuy(2000), // note, this is a default, real value set in llfloaterbuycurrency.cpp
mUserEnteredCurrencyBuy(false),
- mSiteCurrencyEstimated(false),
- mSiteCurrencyEstimatedCost(0),
+ mSupportsInternationalBilling(false),
mBought(false),
mTransactionType(TransactionNone), mTransaction(0),
mCurrencyChanged(false)
{
+ clearEstimate();
}
LLCurrencyUIManager::Impl::~Impl()
@@ -138,14 +153,13 @@ LLCurrencyUIManager::Impl::~Impl()
void LLCurrencyUIManager::Impl::updateCurrencyInfo()
{
- mSiteCurrencyEstimated = false;
- mSiteCurrencyEstimatedCost = 0;
+ clearEstimate();
mBought = false;
mCurrencyChanged = false;
if (mUserCurrencyBuy == 0)
{
- mSiteCurrencyEstimated = true;
+ mLocalCurrencyEstimated = true;
return;
}
@@ -155,6 +169,11 @@ void LLCurrencyUIManager::Impl::updateCurrencyInfo()
"secureSessionId",
gAgent.getSecureSessionID().asString());
keywordArgs.appendInt("currencyBuy", mUserCurrencyBuy);
+ keywordArgs.appendString("viewerChannel", gSavedSettings.getString("VersionChannelName"));
+ keywordArgs.appendInt("viewerMajorVersion", LLVersionInfo::getMajor());
+ keywordArgs.appendInt("viewerMinorVersion", LLVersionInfo::getMinor());
+ keywordArgs.appendInt("viewerPatchVersion", LLVersionInfo::getPatch());
+ keywordArgs.appendInt("viewerBuildVersion", LLVersionInfo::getBuild());
LLXMLRPCValue params = LLXMLRPCValue::createArray();
params.append(keywordArgs);
@@ -177,9 +196,22 @@ void LLCurrencyUIManager::Impl::finishCurrencyInfo()
}
LLXMLRPCValue currency = result["currency"];
- mSiteCurrencyEstimated = true;
- mSiteCurrencyEstimatedCost = currency["estimatedCost"].asInt();
-
+
+ // old XML-RPC server: estimatedCost = value in US cents
+ mUSDCurrencyEstimated = currency["estimatedCost"].isValid();
+ if (mUSDCurrencyEstimated)
+ {
+ mUSDCurrencyEstimatedCost = currency["estimatedCost"].asInt();
+ }
+
+ // newer XML-RPC server: estimatedLocalCost = local currency string
+ mLocalCurrencyEstimated = currency["estimatedLocalCost"].isValid();
+ if (mLocalCurrencyEstimated)
+ {
+ mLocalCurrencyEstimatedCost = currency["estimatedLocalCost"].asString();
+ mSupportsInternationalBilling = true;
+ }
+
S32 newCurrencyBuy = currency["currencyBuy"].asInt();
if (newCurrencyBuy != mUserCurrencyBuy)
{
@@ -192,27 +224,38 @@ void LLCurrencyUIManager::Impl::finishCurrencyInfo()
void LLCurrencyUIManager::Impl::startCurrencyBuy(const std::string& password)
{
- mSiteCurrencyEstimated = false;
- mSiteCurrencyEstimatedCost = 0;
- mCurrencyChanged = false;
-
LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct();
keywordArgs.appendString("agentId", gAgent.getID().asString());
keywordArgs.appendString(
"secureSessionId",
gAgent.getSecureSessionID().asString());
keywordArgs.appendInt("currencyBuy", mUserCurrencyBuy);
- keywordArgs.appendInt("estimatedCost", mSiteCurrencyEstimatedCost);
+ if (mUSDCurrencyEstimated)
+ {
+ keywordArgs.appendInt("estimatedCost", mUSDCurrencyEstimatedCost);
+ }
+ if (mLocalCurrencyEstimated)
+ {
+ keywordArgs.appendString("estimatedLocalCost", mLocalCurrencyEstimatedCost);
+ }
keywordArgs.appendString("confirm", mSiteConfirm);
if (!password.empty())
{
keywordArgs.appendString("password", password);
}
-
+ keywordArgs.appendString("viewerChannel", gSavedSettings.getString("VersionChannelName"));
+ keywordArgs.appendInt("viewerMajorVersion", LLVersionInfo::getMajor());
+ keywordArgs.appendInt("viewerMinorVersion", LLVersionInfo::getMinor());
+ keywordArgs.appendInt("viewerPatchVersion", LLVersionInfo::getPatch());
+ keywordArgs.appendInt("viewerBuildVersion", LLVersionInfo::getBuild());
+
LLXMLRPCValue params = LLXMLRPCValue::createArray();
params.append(keywordArgs);
startTransaction(TransactionBuy, "buyCurrency", params);
+
+ clearEstimate();
+ mCurrencyChanged = false;
}
void LLCurrencyUIManager::Impl::finishCurrencyBuy()
@@ -257,6 +300,34 @@ void LLCurrencyUIManager::Impl::startTransaction(TransactionType type,
clearError();
}
+void LLCurrencyUIManager::Impl::clearEstimate()
+{
+ mUSDCurrencyEstimated = false;
+ mUSDCurrencyEstimatedCost = 0;
+ mLocalCurrencyEstimated = false;
+ mLocalCurrencyEstimatedCost = "0";
+}
+
+bool LLCurrencyUIManager::Impl::hasEstimate() const
+{
+ return (mUSDCurrencyEstimated || mLocalCurrencyEstimated);
+}
+
+std::string LLCurrencyUIManager::Impl::getLocalEstimate() const
+{
+ if (mLocalCurrencyEstimated)
+ {
+ // we have the new-style local currency string
+ return mLocalCurrencyEstimatedCost;
+ }
+ if (mUSDCurrencyEstimated)
+ {
+ // we have the old-style USD-specific value
+ return "US$ " + llformat("%#.2f", mUSDCurrencyEstimatedCost / 100.0);
+ }
+ return "";
+}
+
bool LLCurrencyUIManager::Impl::checkTransaction()
{
if (!mTransaction)
@@ -329,8 +400,8 @@ void LLCurrencyUIManager::Impl::currencyKey(S32 value)
mUserCurrencyBuy = value;
- if (mSiteCurrencyEstimated) {
- mSiteCurrencyEstimated = false;
+ if (hasEstimate()) {
+ clearEstimate();
//cannot just simply refresh the whole UI, as the edit field will
// get reset and the cursor will change...
@@ -356,8 +427,7 @@ void LLCurrencyUIManager::Impl::prepare()
if (lindenAmount)
{
lindenAmount->setPrevalidate(LLLineEditor::prevalidateNonNegativeS32);
- lindenAmount->setKeystrokeCallback(onCurrencyKey);
- lindenAmount->setCallbackUserData(this);
+ lindenAmount->setKeystrokeCallback(onCurrencyKey, this);
}
}
@@ -394,8 +464,11 @@ void LLCurrencyUIManager::Impl::updateUI()
}
}
- mPanel.childSetTextArg("currency_est", "[USD]", llformat("%#.2f", mSiteCurrencyEstimatedCost / 100.0));
- mPanel.childSetVisible("currency_est", mSiteCurrencyEstimated && mUserCurrencyBuy > 0);
+ mPanel.childSetTextArg("currency_est", "[LOCALAMOUNT]", getLocalEstimate());
+ mPanel.childSetVisible("currency_est", hasEstimate() && mUserCurrencyBuy > 0);
+
+ mPanel.childSetVisible("currency_links", mSupportsInternationalBilling);
+ mPanel.childSetVisible("exchange_rate_note", mSupportsInternationalBilling);
if (mPanel.childIsEnabled("buy_btn")
||mPanel.childIsVisible("currency_est")
@@ -436,18 +509,32 @@ void LLCurrencyUIManager::setZeroMessage(const std::string& message)
impl.mZeroMessage = message;
}
-void LLCurrencyUIManager::setEstimate(int amount)
+void LLCurrencyUIManager::setUSDEstimate(int amount)
+{
+ impl.mUSDCurrencyEstimatedCost = amount;
+ impl.mUSDCurrencyEstimated = true;
+ impl.updateUI();
+
+ impl.mCurrencyChanged = false;
+}
+
+int LLCurrencyUIManager::getUSDEstimate()
+{
+ return impl.mUSDCurrencyEstimated ? impl.mUSDCurrencyEstimatedCost : 0;
+}
+
+void LLCurrencyUIManager::setLocalEstimate(const std::string &amount)
{
- impl.mSiteCurrencyEstimatedCost = amount;
- impl.mSiteCurrencyEstimated = true;
+ impl.mLocalCurrencyEstimatedCost = amount;
+ impl.mLocalCurrencyEstimated = true;
impl.updateUI();
impl.mCurrencyChanged = false;
}
-int LLCurrencyUIManager::getEstimate()
+std::string LLCurrencyUIManager::getLocalEstimate() const
{
- return impl.mSiteCurrencyEstimated ? impl.mSiteCurrencyEstimatedCost : 0;
+ return impl.getLocalEstimate();
}
void LLCurrencyUIManager::prepare()
@@ -478,7 +565,7 @@ void LLCurrencyUIManager::buy(const std::string& buy_msg)
LLUIString msg = buy_msg;
msg.setArg("[LINDENS]", llformat("%d", impl.mUserCurrencyBuy));
- msg.setArg("[USD]", llformat("%#.2f", impl.mSiteCurrencyEstimatedCost / 100.0));
+ msg.setArg("[LOCALAMOUNT]", getLocalEstimate());
LLConfirmationManager::confirm(impl.mSiteConfirm,
msg,
impl,
@@ -499,7 +586,7 @@ bool LLCurrencyUIManager::canCancel()
bool LLCurrencyUIManager::canBuy()
{
return impl.mTransactionType == Impl::TransactionNone
- && impl.mSiteCurrencyEstimated
+ && impl.hasEstimate()
&& impl.mUserCurrencyBuy > 0;
}
diff --git a/indra/newview/llcurrencyuimanager.h b/indra/newview/llcurrencyuimanager.h
index 93427aed7f..dfe027098d 100644
--- a/indra/newview/llcurrencyuimanager.h
+++ b/indra/newview/llcurrencyuimanager.h
@@ -57,11 +57,16 @@ public:
void setZeroMessage(const std::string& message);
// sets the gray message to show when zero
- void setEstimate(int);
- int getEstimate();
+ void setUSDEstimate(int); // deprecated in 2.0
+ int getUSDEstimate(); // deprecated in 2.0
// the amount in US$ * 100 (in otherwords, in cents)
// use set when you get this information from elsewhere
+ void setLocalEstimate(const std::string &local_est);
+ std::string getLocalEstimate() const;
+ // the estimated cost in the user's local currency
+ // for example, "US$ 10.00" or "10.00 Euros"
+
void prepare();
// call once after dialog is built, from postBuild()
void updateUI(bool show = true);
diff --git a/indra/newview/lldateutil.cpp b/indra/newview/lldateutil.cpp
new file mode 100644
index 0000000000..abb2fdeb9a
--- /dev/null
+++ b/indra/newview/lldateutil.cpp
@@ -0,0 +1,161 @@
+/**
+* @file lldateutil.cpp
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lldateutil.h"
+
+// Linden libraries
+#include "lltrans.h"
+#include "llui.h"
+
+static S32 DAYS_PER_MONTH_NOLEAP[] =
+ { 31, 28, 21, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+static S32 DAYS_PER_MONTH_LEAP[] =
+ { 31, 29, 21, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+static S32 days_from_month(S32 year, S32 month)
+{
+ llassert_always(1 <= month);
+ llassert_always(month <= 12);
+
+ if (year % 4 == 0
+ && year % 100 != 0)
+ {
+ // leap year
+ return DAYS_PER_MONTH_LEAP[month - 1];
+ }
+ else
+ {
+ return DAYS_PER_MONTH_NOLEAP[month - 1];
+ }
+}
+
+std::string LLDateUtil::ageFromDate(const std::string& date_string,
+ const LLDate& now)
+{
+ S32 born_month, born_day, born_year;
+ S32 matched = sscanf(date_string.c_str(), "%d/%d/%d", &born_month, &born_day, &born_year);
+ if (matched != 3) return "???";
+ LLDate born_date;
+ born_date.fromYMDHMS(born_year, born_month, born_day);
+ F64 born_date_secs_since_epoch = born_date.secondsSinceEpoch();
+ // Correct for the fact that account creation dates are in Pacific time,
+ // == UTC - 8
+ born_date_secs_since_epoch += 8.0 * 60.0 * 60.0;
+ born_date.secondsSinceEpoch(born_date_secs_since_epoch);
+ // explode out to month/day/year again
+ born_date.split(&born_year, &born_month, &born_day);
+
+ S32 now_year, now_month, now_day;
+ now.split(&now_year, &now_month, &now_day);
+
+ // Do grade-school subtraction, from right-to-left, borrowing from the left
+ // when things go negative
+ S32 age_days = (now_day - born_day);
+ if (age_days < 0)
+ {
+ now_month -= 1;
+ if (now_month == 0)
+ {
+ now_year -= 1;
+ now_month = 12;
+ }
+ age_days += days_from_month(now_year, now_month);
+ }
+ S32 age_months = (now_month - born_month);
+ if (age_months < 0)
+ {
+ now_year -= 1;
+ age_months += 12;
+ }
+ S32 age_years = (now_year - born_year);
+
+ // Noun pluralization depends on language
+ std::string lang = LLUI::getLanguage();
+
+ // Try for age in round number of years
+ LLStringUtil::format_map_t args;
+
+ if (age_months > 0 || age_years > 0)
+ {
+ args["[AGEYEARS]"] =
+ LLTrans::getCountString(lang, "AgeYears", age_years);
+ args["[AGEMONTHS]"] =
+ LLTrans::getCountString(lang, "AgeMonths", age_months);
+
+ // We want to display times like:
+ // 2 year 2 months
+ // 2 years (implicitly 0 months)
+ // 11 months
+ if (age_years > 0)
+ {
+ if (age_months > 0)
+ {
+ return LLTrans::getString("YearsMonthsOld", args);
+ }
+ else
+ {
+ return LLTrans::getString("YearsOld", args);
+ }
+ }
+ else // age_years == 0
+ {
+ return LLTrans::getString("MonthsOld", args);
+ }
+ }
+ // you're 0 months old, display in weeks or days
+
+ // Now for age in weeks
+ S32 age_weeks = age_days / 7;
+ age_days = age_days % 7;
+ if (age_weeks > 0)
+ {
+ args["[AGEWEEKS]"] =
+ LLTrans::getCountString(lang, "AgeWeeks", age_weeks);
+ return LLTrans::getString("WeeksOld", args);
+ }
+
+ // Down to days now
+ if (age_days > 0)
+ {
+ args["[AGEDAYS]"] =
+ LLTrans::getCountString(lang, "AgeDays", age_days);
+ return LLTrans::getString("DaysOld", args);
+ }
+
+ return LLTrans::getString("TodayOld");
+}
+
+std::string LLDateUtil::ageFromDate(const std::string& date_string)
+{
+ return ageFromDate(date_string, LLDate::now());
+}
diff --git a/indra/newview/lldateutil.h b/indra/newview/lldateutil.h
new file mode 100644
index 0000000000..041be07f12
--- /dev/null
+++ b/indra/newview/lldateutil.h
@@ -0,0 +1,49 @@
+/**
+* @file lldateutil.h
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#ifndef LLDATEUTIL_H
+#define LLDATEUTIL_H
+
+class LLDate;
+
+namespace LLDateUtil
+{
+ // Convert a date provided by the server (MM/DD/YYYY) into a localized,
+ // human-readable age (1 year, 2 months) using translation strings.
+ // Pass LLDate::now() for now.
+ // Used for avatar inspectors and profiles.
+ std::string ageFromDate(const std::string& date_string, const LLDate& now);
+
+ // Calls the above with LLDate::now()
+ std::string ageFromDate(const std::string& date_string);
+}
+
+#endif
diff --git a/indra/newview/lldebugmessagebox.cpp b/indra/newview/lldebugmessagebox.cpp
index 4188ecc0e2..7814e94dfd 100644
--- a/indra/newview/lldebugmessagebox.cpp
+++ b/indra/newview/lldebugmessagebox.cpp
@@ -50,32 +50,69 @@
std::map<std::string, LLDebugVarMessageBox*> LLDebugVarMessageBox::sInstances;
LLDebugVarMessageBox::LLDebugVarMessageBox(const std::string& title, EDebugVarType var_type, void *var) :
- LLFloater(std::string("msg box"), LLRect(10,160,400,10), title),
+ LLFloater(LLSD()),
mVarType(var_type), mVarData(var), mAnimate(FALSE)
{
+ setRect(LLRect(10,160,400,10));
+
+ LLSliderCtrl::Params slider_p;
+ slider_p.label(title);
+ slider_p.label_width(70);
+ slider_p.text_width(40);
+ slider_p.can_edit_text(true);
+ slider_p.show_text(true);
+
+ mSlider1 = NULL;
+ mSlider2 = NULL;
+ mSlider3 = NULL;
+
switch(var_type)
{
case VAR_TYPE_F32:
- mSlider1 = new LLSliderCtrl(std::string("slider 1"), LLRect(20,130,190,110), title, NULL, 70, 130, TRUE, TRUE, FALSE, NULL, NULL, *((F32*)var), -100.f, 100.f, 0.1f, LLStringUtil::null);
- mSlider1->setPrecision(3);
+ slider_p.name("slider 1");
+ slider_p.rect(LLRect(20,130,190,110));
+ slider_p.initial_value(*((F32*)var));
+ slider_p.min_value(-100.f);
+ slider_p.max_value(100.f);
+ slider_p.increment(0.1f);
+ slider_p.decimal_digits(3);
+ mSlider1 = LLUICtrlFactory::create<LLSliderCtrl>(slider_p);
addChild(mSlider1);
- mSlider2 = NULL;
- mSlider3 = NULL;
break;
case VAR_TYPE_S32:
- mSlider1 = new LLSliderCtrl(std::string("slider 1"), LLRect(20,100,190,80), title, NULL, 70, 130, TRUE, TRUE, FALSE, NULL, NULL, (F32)*((S32*)var), -255.f, 255.f, 1.f, LLStringUtil::null);
- mSlider1->setPrecision(0);
+ slider_p.name("slider 1");
+ slider_p.rect(LLRect(20,100,190,80));
+ slider_p.initial_value((F32)*((S32*)var));
+ slider_p.min_value(-255.f);
+ slider_p.max_value(255.f);
+ slider_p.increment(1.f);
+ slider_p.decimal_digits(0);
+ mSlider1 = LLUICtrlFactory::create<LLSliderCtrl>(slider_p);
addChild(mSlider1);
- mSlider2 = NULL;
- mSlider3 = NULL;
break;
case VAR_TYPE_VEC3:
- mSlider1 = new LLSliderCtrl(std::string("slider 1"), LLRect(20,130,190,110), std::string("x: "), NULL, 70, 130, TRUE, TRUE, FALSE, NULL, NULL, ((LLVector3*)var)->mV[VX], -100.f, 100.f, 0.1f, LLStringUtil::null);
- mSlider1->setPrecision(3);
- mSlider2 = new LLSliderCtrl(std::string("slider 2"), LLRect(20,100,190,80), std::string("y: "), NULL, 70, 130, TRUE, TRUE, FALSE, NULL, NULL, ((LLVector3*)var)->mV[VY], -100.f, 100.f, 0.1f, LLStringUtil::null);
- mSlider2->setPrecision(3);
- mSlider3 = new LLSliderCtrl(std::string("slider 3"), LLRect(20,70,190,50), std::string("z: "), NULL, 70, 130, TRUE, TRUE, FALSE, NULL, NULL, ((LLVector3*)var)->mV[VZ], -100.f, 100.f, 0.1f, LLStringUtil::null);
- mSlider3->setPrecision(3);
+ slider_p.name("slider 1");
+ slider_p.label("x: ");
+ slider_p.rect(LLRect(20,130,190,110));
+ slider_p.initial_value(((LLVector3*)var)->mV[VX]);
+ slider_p.min_value(-100.f);
+ slider_p.max_value(100.f);
+ slider_p.increment(0.1f);
+ slider_p.decimal_digits(3);
+ mSlider1 = LLUICtrlFactory::create<LLSliderCtrl>(slider_p);
+
+ slider_p.name("slider 2");
+ slider_p.label("y: ");
+ slider_p.rect(LLRect(20,100,190,80));
+ slider_p.initial_value(((LLVector3*)var)->mV[VY]);
+ mSlider2 = LLUICtrlFactory::create<LLSliderCtrl>(slider_p);
+
+ slider_p.name("slider 3");
+ slider_p.label("z: ");
+ slider_p.rect(LLRect(20,70,190,50));
+ slider_p.initial_value(((LLVector3*)var)->mV[VZ]);
+ mSlider2 = LLUICtrlFactory::create<LLSliderCtrl>(slider_p);
+
addChild(mSlider1);
addChild(mSlider2);
addChild(mSlider3);
@@ -85,10 +122,19 @@ LLDebugVarMessageBox::LLDebugVarMessageBox(const std::string& title, EDebugVarTy
break;
}
- mAnimateButton = new LLButton(std::string("Animate"), LLRect(20, 45, 180, 25), LLStringUtil::null, onAnimateClicked, this);
+ LLButton::Params p;
+ p.name(std::string("Animate"));
+ p.label(std::string("Animate"));
+ p.rect(LLRect(20, 45, 180, 25));
+ p.click_callback.function(boost::bind(&LLDebugVarMessageBox::onAnimateClicked, this, _2));
+ mAnimateButton = LLUICtrlFactory::create<LLButton>(p);
addChild(mAnimateButton);
- mText = new LLTextBox(std::string("value"), LLRect(20,20,190,0));
+ LLTextBox::Params params;
+ params.name("value");
+ params.initial_value(params.name());
+ params.rect(LLRect(20,20,190,0));
+ mText = LLUICtrlFactory::create<LLTextBox> (params);
addChild(mText);
//disable hitting enter closes dialog
@@ -112,8 +158,7 @@ void LLDebugVarMessageBox::show(const std::string& title, F32 *var, F32 max_valu
{
box->mSlider1->setValue(*var);
}
- box->mSlider1->setCommitCallback(slider_changed);
- box->mSlider1->setCallbackUserData(box);
+ box->mSlider1->setCommitCallback(boost::bind(&LLDebugVarMessageBox::sliderChanged, box, _2));
#endif
}
@@ -129,8 +174,7 @@ void LLDebugVarMessageBox::show(const std::string& title, S32 *var, S32 max_valu
{
box->mSlider1->setValue((F32)*var);
}
- box->mSlider1->setCommitCallback(slider_changed);
- box->mSlider1->setCallbackUserData(box);
+ box->mSlider1->setCommitCallback(boost::bind(&LLDebugVarMessageBox::sliderChanged, box, _2));
#endif
}
@@ -142,20 +186,17 @@ void LLDebugVarMessageBox::show(const std::string& title, LLVector3 *var, LLVect
box->mSlider1->setMaxValue(max_value.mV[VX]);
box->mSlider1->setMinValue(-max_value.mV[VX]);
box->mSlider1->setIncrement(increment.mV[VX]);
- box->mSlider1->setCommitCallback(slider_changed);
- box->mSlider1->setCallbackUserData(box);
+ box->mSlider1->setCommitCallback(boost::bind(&LLDebugVarMessageBox::sliderChanged, box, _2));
box->mSlider2->setMaxValue(max_value.mV[VX]);
box->mSlider2->setMinValue(-max_value.mV[VX]);
box->mSlider2->setIncrement(increment.mV[VX]);
- box->mSlider2->setCommitCallback(slider_changed);
- box->mSlider2->setCallbackUserData(box);
+ box->mSlider2->setCommitCallback(boost::bind(&LLDebugVarMessageBox::sliderChanged, box, _2));
box->mSlider3->setMaxValue(max_value.mV[VX]);
box->mSlider3->setMinValue(-max_value.mV[VX]);
box->mSlider3->setIncrement(increment.mV[VX]);
- box->mSlider3->setCommitCallback(slider_changed);
- box->mSlider3->setCallbackUserData(box);
+ box->mSlider3->setCommitCallback(boost::bind(&LLDebugVarMessageBox::sliderChanged, box, _2));
#endif
}
@@ -170,50 +211,44 @@ LLDebugVarMessageBox* LLDebugVarMessageBox::show(const std::string& title, EDebu
sInstances[title_string] = box;
gFloaterView->addChild(box);
box->reshape(200,150);
- box->open(); /*Flawfinder: ignore*/
+ box->openFloater();
box->mTitle = title_string;
}
return box;
}
-void LLDebugVarMessageBox::slider_changed(LLUICtrl* ctrl, void* user_data)
+void LLDebugVarMessageBox::sliderChanged(const LLSD& data)
{
- LLDebugVarMessageBox *msg_box = (LLDebugVarMessageBox*)user_data;
- if (!msg_box || !msg_box->mVarData) return;
+ if (!mVarData)
+ return;
- switch(msg_box->mVarType)
+ switch(mVarType)
{
case VAR_TYPE_F32:
- *((F32*)msg_box->mVarData) = (F32)msg_box->mSlider1->getValue().asReal();
+ *((F32*)mVarData) = (F32)mSlider1->getValue().asReal();
break;
case VAR_TYPE_S32:
- *((S32*)msg_box->mVarData) = (S32)msg_box->mSlider1->getValue().asInteger();
+ *((S32*)mVarData) = (S32)mSlider1->getValue().asInteger();
break;
case VAR_TYPE_VEC3:
{
- LLVector3* vec_p = (LLVector3*)msg_box->mVarData;
- vec_p->setVec((F32)msg_box->mSlider1->getValue().asReal(),
- (F32)msg_box->mSlider2->getValue().asReal(),
- (F32)msg_box->mSlider3->getValue().asReal());
+ LLVector3* vec_p = (LLVector3*)mVarData;
+ vec_p->setVec((F32)mSlider1->getValue().asReal(),
+ (F32)mSlider2->getValue().asReal(),
+ (F32)mSlider3->getValue().asReal());
break;
}
default:
- llwarns << "Unhandled var type " << msg_box->mVarType << llendl;
+ llwarns << "Unhandled var type " << mVarType << llendl;
break;
}
}
-void LLDebugVarMessageBox::onAnimateClicked(void* user_data)
-{
- LLDebugVarMessageBox* msg_boxp = (LLDebugVarMessageBox*)user_data;
- msg_boxp->mAnimate = !msg_boxp->mAnimate;
- msg_boxp->mAnimateButton->setToggleState(msg_boxp->mAnimate);
-}
-
-void LLDebugVarMessageBox::onClose(bool app_quitting)
+void LLDebugVarMessageBox::onAnimateClicked(const LLSD& data)
{
- setVisible(FALSE);
+ mAnimate = !mAnimate;
+ mAnimateButton->setToggleState(mAnimate);
}
void LLDebugVarMessageBox::draw()
@@ -245,16 +280,16 @@ void LLDebugVarMessageBox::draw()
{
F32 animated_val = clamp_rescale(fmodf((F32)LLFrameTimer::getElapsedSeconds() / 5.f, 1.f), 0.f, 1.f, 0.f, mSlider1->getMaxValue());
mSlider1->setValue(animated_val);
- slider_changed(mSlider1, this);
+ sliderChanged(LLSD());
if (mSlider2)
{
mSlider2->setValue(animated_val);
- slider_changed(mSlider2, this);
+ sliderChanged(LLSD());
}
if (mSlider3)
{
mSlider3->setValue(animated_val);
- slider_changed(mSlider3, this);
+ sliderChanged(LLSD());
}
}
}
diff --git a/indra/newview/lldebugmessagebox.h b/indra/newview/lldebugmessagebox.h
index 07062218ac..0def0ee7af 100644
--- a/indra/newview/lldebugmessagebox.h
+++ b/indra/newview/lldebugmessagebox.h
@@ -66,8 +66,8 @@ protected:
~LLDebugVarMessageBox();
static LLDebugVarMessageBox* show(const std::string& title, EDebugVarType var_type, void *var);
- static void slider_changed(LLUICtrl* ctrl, void* user_data);
- static void onAnimateClicked(void* user_data);
+ void sliderChanged(const LLSD& data);
+ void onAnimateClicked(const LLSD& data);
public:
static void show(const std::string& title, F32 *var, F32 max_value = 100.f, F32 increment = 0.1f);
@@ -76,7 +76,6 @@ public:
static void show(const std::string& title, LLVector3 *var, LLVector3 max_value = LLVector3(100.f, 100.f, 100.f), LLVector3 increment = LLVector3(0.1f, 0.1f, 0.1f));
//static void show(const std::string& title, LLVector4 *var, LLVector4 max_value = LLVector4(100.f, 100.f, 100.f, 100.f), LLVector4 increment = LLVector4(0.1f, 0.1f, 0.1f, 0.1f));
- virtual void onClose(bool app_quitting);
virtual void draw();
protected:
diff --git a/indra/newview/lldebugview.cpp b/indra/newview/lldebugview.cpp
index 40f5202067..169a963d0d 100644
--- a/indra/newview/lldebugview.cpp
+++ b/indra/newview/lldebugview.cpp
@@ -35,17 +35,17 @@
#include "lldebugview.h"
// library includes
-#include "llframestatview.h"
#include "llfasttimerview.h"
#include "llmemoryview.h"
#include "llconsole.h"
#include "lltextureview.h"
#include "llresmgr.h"
#include "imageids.h"
-#include "llvelocitybar.h"
+#include "llviewercontrol.h"
#include "llviewerwindow.h"
-#include "llfloaterstats.h"
-
+#include "llappviewer.h"
+#include "llmemoryview.h"
+#include "llviewertexture.h"
//
// Globals
//
@@ -55,58 +55,80 @@ LLDebugView* gDebugView = NULL;
//
// Methods
//
+static LLDefaultChildRegistry::Register<LLDebugView> r("debug_view");
-LLDebugView::LLDebugView(const std::string& name, const LLRect &rect)
-: LLView(name, rect, FALSE)
+LLDebugView::LLDebugView(const LLDebugView::Params& p)
+: LLView(p)
+{}
+
+void LLDebugView::init()
{
LLRect r;
+ LLRect rect = getLocalRect();
r.set(10, rect.getHeight() - 100, rect.getWidth()/2, 100);
- mDebugConsolep = new LLConsole("debug console", 20, r, -1, 0.f );
- mDebugConsolep->setFollowsBottom();
- mDebugConsolep->setFollowsLeft();
- mDebugConsolep->setVisible( FALSE );
+ LLConsole::Params cp;
+ cp.name("debug console");
+ cp.max_lines(20);
+ cp.rect(r);
+ cp.font(LLFontGL::getFontMonospace());
+ cp.follows.flags(FOLLOWS_BOTTOM | FOLLOWS_LEFT);
+ cp.visible(false);
+ mDebugConsolep = LLUICtrlFactory::create<LLConsole>(cp);
addChild(mDebugConsolep);
r.set(150 - 25, rect.getHeight() - 50, rect.getWidth()/2 - 25, rect.getHeight() - 450);
- mFrameStatView = new LLFrameStatView("frame stat", r);
- mFrameStatView->setFollowsTop();
- mFrameStatView->setFollowsLeft();
- mFrameStatView->setVisible(FALSE); // start invisible
- addChild(mFrameStatView);
-
- r.set(25, rect.getHeight() - 50, (S32) (gViewerWindow->getVirtualWindowRect().getWidth() * 0.75f),
- (S32) (gViewerWindow->getVirtualWindowRect().getHeight() * 0.75f));
- mFastTimerView = new LLFastTimerView("fast timers", r);
+
+ r.setLeftTopAndSize(25, rect.getHeight() - 50, (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f),
+ (S32) (gViewerWindow->getWindowRectScaled().getHeight() * 0.75f));
+ mFastTimerView = new LLFastTimerView(r);
mFastTimerView->setFollowsTop();
mFastTimerView->setFollowsLeft();
mFastTimerView->setVisible(FALSE); // start invisible
addChild(mFastTimerView);
- r.set(25, rect.getHeight() - 50, rect.getWidth()/2, rect.getHeight() - 450);
- mMemoryView = new LLMemoryView("memory", r);
- mMemoryView->setFollowsTop();
- mMemoryView->setFollowsLeft();
- mMemoryView->setVisible(FALSE); // start invisible
+ r.setLeftTopAndSize(25, rect.getHeight() - 50, (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f),
+ (S32) (gViewerWindow->getWindowRectScaled().getHeight() * 0.75f));
+ LLMemoryView::Params mp;
+ mp.name("memory");
+ mp.rect(r);
+ mp.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT);
+ mp.visible(false);
+ mMemoryView = LLUICtrlFactory::create<LLMemoryView>(mp);
addChild(mMemoryView);
r.set(150, rect.getHeight() - 50, 820, 100);
- gTextureView = new LLTextureView("gTextureView", r);
- gTextureView->setRect(r);
- gTextureView->setFollowsBottom();
- gTextureView->setFollowsLeft();
+ LLTextureView::Params tvp;
+ tvp.name("gTextureView");
+ tvp.rect(r);
+ tvp.follows.flags(FOLLOWS_BOTTOM|FOLLOWS_LEFT);
+ tvp.visible(false);
+ gTextureView = LLUICtrlFactory::create<LLTextureView>(tvp);
addChild(gTextureView);
//gTextureView->reshape(r.getWidth(), r.getHeight(), TRUE);
- const S32 VELOCITY_LEFT = 10; // 370;
- const S32 VELOCITY_WIDTH = 500;
- const S32 VELOCITY_TOP = 140;
- const S32 VELOCITY_HEIGHT = 45;
- r.setLeftTopAndSize( VELOCITY_LEFT, VELOCITY_TOP, VELOCITY_WIDTH, VELOCITY_HEIGHT );
- gVelocityBar = new LLVelocityBar("Velocity Bar", r);
- gVelocityBar->setFollowsBottom();
- gVelocityBar->setFollowsLeft();
- addChild(gVelocityBar);
+ if(gAuditTexture)
+ {
+ r.set(150, rect.getHeight() - 50, 900 + LLImageGL::sTextureLoadedCounter.size() * 30, 100);
+ LLTextureSizeView::Params tsv ;
+ tsv.name("gTextureSizeView");
+ tsv.rect(r);
+ tsv.follows.flags(FOLLOWS_BOTTOM|FOLLOWS_LEFT);
+ tsv.visible(false);
+ gTextureSizeView = LLUICtrlFactory::create<LLTextureSizeView>(tsv);
+ addChild(gTextureSizeView);
+ gTextureSizeView->setType(LLTextureSizeView::TEXTURE_MEM_OVER_SIZE) ;
+
+ r.set(150, rect.getHeight() - 50, 900 + LLViewerTexture::getTotalNumOfCategories() * 30, 100);
+ LLTextureSizeView::Params tcv ;
+ tcv.name("gTextureCategoryView");
+ tcv.rect(r);
+ tcv.follows.flags(FOLLOWS_BOTTOM|FOLLOWS_LEFT);
+ tcv.visible(false);
+ gTextureCategoryView = LLUICtrlFactory::create<LLTextureSizeView>(tcv);
+ gTextureCategoryView->setType(LLTextureSizeView::TEXTURE_MEM_OVER_CATEGORY);
+ addChild(gTextureCategoryView);
+ }
}
@@ -115,5 +137,7 @@ LLDebugView::~LLDebugView()
// These have already been deleted. Fix the globals appropriately.
gDebugView = NULL;
gTextureView = NULL;
+ gTextureSizeView = NULL;
+ gTextureCategoryView = NULL;
}
diff --git a/indra/newview/lldebugview.h b/indra/newview/lldebugview.h
index 189efd3a3f..b17cdb43cd 100644
--- a/indra/newview/lldebugview.h
+++ b/indra/newview/lldebugview.h
@@ -40,9 +40,7 @@
// declarations
class LLButton;
-class LLToolView;
class LLStatusPanel;
-class LLFrameStatView;
class LLFastTimerView;
class LLMemoryView;
class LLConsole;
@@ -52,10 +50,20 @@ class LLFloaterStats;
class LLDebugView : public LLView
{
public:
- LLDebugView(const std::string& name, const LLRect &rect);
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
+ {
+ Params()
+ {
+ mouse_opaque = false;
+ }
+ };
+ LLDebugView(const Params&);
~LLDebugView();
- LLFrameStatView* mFrameStatView;
+ void init();
+
+ void setStatsVisible(BOOL visible);
+
LLFastTimerView* mFastTimerView;
LLMemoryView* mMemoryView;
LLConsole* mDebugConsolep;
diff --git a/indra/newview/lldelayedgestureerror.cpp b/indra/newview/lldelayedgestureerror.cpp
index 1af94b3503..ead377deb0 100644
--- a/indra/newview/lldelayedgestureerror.cpp
+++ b/indra/newview/lldelayedgestureerror.cpp
@@ -33,8 +33,9 @@
#include "llviewerprecompiledheaders.h"
#include "lldelayedgestureerror.h"
+
#include <list>
-#include "llnotify.h"
+#include "llnotificationsutil.h"
#include "llcallbacklist.h"
#include "llinventory.h"
#include "llviewerinventory.h"
@@ -119,7 +120,7 @@ bool LLDelayedGestureError::doDialog(const LLErrorEntry &ent, bool uuid_ok)
}
- LLNotifications::instance().add(ent.mNotifyName, args);
+ LLNotificationsUtil::add(ent.mNotifyName, args);
return true;
}
diff --git a/indra/newview/lldirpicker.cpp b/indra/newview/lldirpicker.cpp
index 8b0ed39eb0..a720dc46b5 100644
--- a/indra/newview/lldirpicker.cpp
+++ b/indra/newview/lldirpicker.cpp
@@ -40,6 +40,7 @@
#include "lldir.h"
#include "llframetimer.h"
#include "lltrans.h"
+#include "llwindow.h" // beforeDialog()
#if LL_LINUX || LL_SOLARIS
# include "llfilepicker.h"
diff --git a/indra/newview/lldndbutton.cpp b/indra/newview/lldndbutton.cpp
new file mode 100644
index 0000000000..22f2bb1d16
--- /dev/null
+++ b/indra/newview/lldndbutton.cpp
@@ -0,0 +1,60 @@
+/**
+ * @file lldndbutton.cpp
+ * @brief Implementation of the drag-n-drop button.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lldndbutton.h"
+
+
+static LLDefaultChildRegistry::Register<LLDragAndDropButton> r("dnd_button");
+
+LLDragAndDropButton::Params::Params()
+{
+
+}
+
+LLDragAndDropButton::LLDragAndDropButton(Params& params)
+: LLButton(params)
+{
+
+}
+
+BOOL LLDragAndDropButton::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg)
+{
+ if (mDragDropHandler)
+ {
+ return mDragDropHandler(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+ }
+ return false;
+}
+
+// EOF
diff --git a/indra/newview/lldndbutton.h b/indra/newview/lldndbutton.h
new file mode 100644
index 0000000000..c888268187
--- /dev/null
+++ b/indra/newview/lldndbutton.h
@@ -0,0 +1,89 @@
+/**
+ * @file lldndbutton.h
+ * @brief Declaration of the drag-n-drop button.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLDNDBUTTON_H
+#define LL_LLDNDBUTTON_H
+
+#include "llbutton.h"
+
+/**
+ * Class representing a button which can handle Drag-And-Drop event.
+ *
+ * LLDragAndDropButton does not contain any logic to handle Drag-And-Drop itself.
+ * Instead it provides drag_drop_handler_t which can be set to the button.
+ * Then each Drag-And-Drop will be delegated to this handler without any pre/post processing.
+ *
+ * All xml parameters are the same as LLButton has.
+ *
+ * @see LLLandmarksPanel for example of usage of this class.
+ */
+class LLDragAndDropButton : public LLButton
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLButton::Params>
+ {
+ Params();
+ };
+
+ LLDragAndDropButton(Params& params);
+
+ typedef boost::function<bool (
+ S32 /*x*/, S32 /*y*/, MASK /*mask*/, BOOL /*drop*/,
+ EDragAndDropType /*cargo_type*/,
+ void* /*cargo_data*/,
+ EAcceptance* /*accept*/,
+ std::string& /*tooltip_msg*/)> drag_drop_handler_t;
+
+
+ /**
+ * Sets a handler which should process Drag-And-Drop.
+ */
+ void setDragAndDropHandler(drag_drop_handler_t handler) { mDragDropHandler = handler; }
+
+
+ /**
+ * Process Drag-And-Drop by delegating the event to drag_drop_handler_t.
+ *
+ * @return BOOL - value returned by drag_drop_handler_t if it is set, FALSE otherwise.
+ */
+ /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg);
+
+private:
+ drag_drop_handler_t mDragDropHandler;
+};
+
+
+#endif // LL_LLDNDBUTTON_H
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 9f4afc9f17..d60330024a 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -60,6 +60,9 @@ const F32 MAX_INTERPOLATE_DISTANCE_SQUARED = 10.f * 10.f;
const F32 OBJECT_DAMPING_TIME_CONSTANT = 0.06f;
const F32 MIN_SHADOW_CASTER_RADIUS = 2.0f;
+static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound");
+
+
////////////////////////
//
// Inline implementations.
@@ -86,7 +89,7 @@ LLDynamicArrayPtr<LLPointer<LLDrawable> > LLDrawable::sDeadList;
void LLDrawable::incrementVisible()
{
sCurVisible++;
- sCurPixelAngle = (F32) gViewerWindow->getWindowDisplayHeight()/LLViewerCamera::getInstance()->getView();
+ sCurPixelAngle = (F32) gViewerWindow->getWindowHeightRaw()/LLViewerCamera::getInstance()->getView();
}
void LLDrawable::init()
{
@@ -102,7 +105,7 @@ void LLDrawable::init()
mVObjp = NULL;
// mFaces
mSpatialGroupp = NULL;
- mVisible = 0;
+ mVisible = sCurVisible - 2;//invisible for the current frame and the last frame.
mRadius = 0.f;
mGeneration = -1;
@@ -188,7 +191,7 @@ BOOL LLDrawable::isLight() const
void LLDrawable::cleanupReferences()
{
- LLFastTimer t(LLFastTimer::FTM_PIPELINE);
+ LLFastTimer t(FTM_PIPELINE);
std::for_each(mFaces.begin(), mFaces.end(), DeletePointer());
mFaces.clear();
@@ -229,7 +232,7 @@ S32 LLDrawable::findReferences(LLDrawable *drawablep)
return count;
}
-LLFace* LLDrawable::addFace(LLFacePool *poolp, LLViewerImage *texturep)
+LLFace* LLDrawable::addFace(LLFacePool *poolp, LLViewerTexture *texturep)
{
LLMemType mt(LLMemType::MTYPE_DRAWABLE);
@@ -253,7 +256,7 @@ LLFace* LLDrawable::addFace(LLFacePool *poolp, LLViewerImage *texturep)
return face;
}
-LLFace* LLDrawable::addFace(const LLTextureEntry *te, LLViewerImage *texturep)
+LLFace* LLDrawable::addFace(const LLTextureEntry *te, LLViewerTexture *texturep)
{
LLMemType mt(LLMemType::MTYPE_DRAWABLE);
@@ -275,7 +278,7 @@ LLFace* LLDrawable::addFace(const LLTextureEntry *te, LLViewerImage *texturep)
}
-void LLDrawable::setNumFaces(const S32 newFaces, LLFacePool *poolp, LLViewerImage *texturep)
+void LLDrawable::setNumFaces(const S32 newFaces, LLFacePool *poolp, LLViewerTexture *texturep)
{
if (newFaces == (S32)mFaces.size())
{
@@ -298,7 +301,7 @@ void LLDrawable::setNumFaces(const S32 newFaces, LLFacePool *poolp, LLViewerImag
llassert_always(mFaces.size() == newFaces);
}
-void LLDrawable::setNumFacesFast(const S32 newFaces, LLFacePool *poolp, LLViewerImage *texturep)
+void LLDrawable::setNumFacesFast(const S32 newFaces, LLFacePool *poolp, LLViewerTexture *texturep)
{
if (newFaces <= (S32)mFaces.size() && newFaces >= (S32)mFaces.size()/2)
{
@@ -673,8 +676,13 @@ BOOL LLDrawable::updateMoveDamped()
return done_moving;
}
-void LLDrawable::updateDistance(LLCamera& camera)
+void LLDrawable::updateDistance(LLCamera& camera, bool force_update)
{
+ if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD)
+ {
+ llerrs << "WTF?" << llendl;
+ }
+
//switch LOD with the spatial group to avoid artifacts
//LLSpatialGroup* sg = getSpatialGroup();
@@ -692,19 +700,22 @@ void LLDrawable::updateDistance(LLCamera& camera)
pos += volume->getRegion()->getOriginAgent();
}
- for (S32 i = 0; i < getNumFaces(); i++)
+ if (isState(LLDrawable::HAS_ALPHA))
{
- LLFace* facep = getFace(i);
- if (facep->getPoolType() == LLDrawPool::POOL_ALPHA)
+ for (S32 i = 0; i < getNumFaces(); i++)
{
- LLVector3 box = (facep->mExtents[1] - facep->mExtents[0]) * 0.25f;
- LLVector3 v = (facep->mCenterLocal-camera.getOrigin());
- LLVector3 at = camera.getAtAxis();
- for (U32 j = 0; j < 3; j++)
+ LLFace* facep = getFace(i);
+ if (force_update || facep->getPoolType() == LLDrawPool::POOL_ALPHA)
{
- v.mV[j] -= box.mV[j] * at.mV[j];
+ LLVector3 box = (facep->mExtents[1] - facep->mExtents[0]) * 0.25f;
+ LLVector3 v = (facep->mCenterLocal-camera.getOrigin());
+ const LLVector3& at = camera.getAtAxis();
+ for (U32 j = 0; j < 3; j++)
+ {
+ v.mV[j] -= box.mV[j] * at.mV[j];
+ }
+ facep->mDistance = v * camera.getAtAxis();
}
- facep->mDistance = v * camera.getAtAxis();
}
}
}
@@ -736,11 +747,7 @@ void LLDrawable::updateTexture()
if (getVOVolume())
{
- if (!isActive())
- {
- //gPipeline.markMoved(this);
- }
- else
+ if (isActive())
{
if (isRoot())
{
@@ -953,6 +960,30 @@ LLSpatialPartition* LLDrawable::getSpatialPartition()
return retval;
}
+const S32 MIN_VIS_FRAME_RANGE = 2 ; //two frames:the current one and the last one.
+//static
+S32 LLDrawable::getMinVisFrameRange()
+{
+ return MIN_VIS_FRAME_RANGE ;
+}
+
+BOOL LLDrawable::isRecentlyVisible() const
+{
+ //currently visible or visible in the previous frame.
+ BOOL vis = isVisible() || (sCurVisible - mVisible < MIN_VIS_FRAME_RANGE) ;
+
+ if(!vis)
+ {
+ LLSpatialGroup* group = getSpatialGroup();
+ if (group && group->isRecentlyVisible())
+ {
+ mVisible = sCurVisible;
+ vis = TRUE ;
+ }
+ }
+
+ return vis ;
+}
BOOL LLDrawable::isVisible() const
{
@@ -1003,8 +1034,8 @@ BOOL LLDrawable::isVisible() const
// Spatial Partition Bridging Drawable
//=======================================
-LLSpatialBridge::LLSpatialBridge(LLDrawable* root, U32 data_mask)
-: LLSpatialPartition(data_mask, FALSE)
+LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask)
+: LLSpatialPartition(data_mask, render_by_group, FALSE)
{
mDrawable = root;
root->setSpatialBridge(this);
@@ -1037,7 +1068,7 @@ void LLSpatialBridge::updateSpatialExtents()
LLSpatialGroup* root = (LLSpatialGroup*) mOctree->getListener(0);
{
- LLFastTimer ftm(LLFastTimer::FTM_CULL_REBOUND);
+ LLFastTimer ftm(FTM_CULL_REBOUND);
root->rebound();
}
@@ -1242,7 +1273,9 @@ void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector<LLDrawable*>*
(camera_in.AABBInFrustumNoFarClip(center, size) &&
AABBSphereIntersect(mExtents[0], mExtents[1], camera_in.getOrigin(), camera_in.mFrustumCornerDist)))
{
- if (!LLPipeline::sImpostorRender && LLPipeline::calcPixelArea(center, size, camera_in) < FORCE_INVISIBLE_AREA)
+ if (!LLPipeline::sImpostorRender &&
+ !LLPipeline::sShadowRender &&
+ LLPipeline::calcPixelArea(center, size, camera_in) < FORCE_INVISIBLE_AREA)
{
return;
}
@@ -1273,7 +1306,7 @@ void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector<LLDrawable*>*
}
}
-void LLSpatialBridge::updateDistance(LLCamera& camera_in)
+void LLSpatialBridge::updateDistance(LLCamera& camera_in, bool force_update)
{
if (mDrawable == NULL)
{
@@ -1281,12 +1314,25 @@ void LLSpatialBridge::updateDistance(LLCamera& camera_in)
return;
}
- LLCamera camera = transformCamera(camera_in);
-
- mDrawable->updateDistance(camera);
-
if (mDrawable->getVObj())
{
+ if (mDrawable->getVObj()->isAttachment())
+ {
+ LLDrawable* parent = mDrawable->getParent();
+ if (parent && parent->getVObj())
+ {
+ LLVOAvatar* av = parent->getVObj()->asAvatar();
+ if (av && av->isImpostor())
+ {
+ return;
+ }
+ }
+ }
+
+ LLCamera camera = transformCamera(camera_in);
+
+ mDrawable->updateDistance(camera, force_update);
+
LLViewerObject::const_child_list_t& child_list = mDrawable->getVObj()->getChildren();
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
iter != child_list.end(); iter++)
@@ -1300,7 +1346,7 @@ void LLSpatialBridge::updateDistance(LLCamera& camera_in)
if (!drawable->isAvatar())
{
- drawable->updateDistance(camera);
+ drawable->updateDistance(camera, force_update);
}
}
}
@@ -1428,9 +1474,8 @@ void LLDrawable::updateFaceSize(S32 idx)
}
LLBridgePartition::LLBridgePartition()
-: LLSpatialPartition(0, TRUE)
+: LLSpatialPartition(0, FALSE, 0)
{
- mRenderByGroup = FALSE;
mDrawableType = LLPipeline::RENDER_TYPE_AVATAR;
mPartitionType = LLViewerRegion::PARTITION_BRIDGE;
mLODPeriod = 16;
diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h
index f5a66a3a78..5a10b688da 100644
--- a/indra/newview/lldrawable.h
+++ b/indra/newview/lldrawable.h
@@ -46,7 +46,6 @@
#include "llmemtype.h"
#include "llprimitive.h"
#include "lldarray.h"
-#include "llstat.h"
#include "llviewerobject.h"
#include "llrect.h"
#include "llappviewer.h" // for gFrameTimeSeconds
@@ -59,12 +58,11 @@ class LLSpatialGroup;
class LLSpatialBridge;
class LLSpatialPartition;
class LLVOVolume;
-class LLViewerImage;
+class LLViewerTexture;
// Can have multiple silhouettes for each object
const U32 SILHOUETTE_HIGHLIGHT = 0;
-
// All data for new renderer goes into this class.
class LLDrawable : public LLRefCount
{
@@ -80,7 +78,8 @@ public:
BOOL isLight() const;
- BOOL isVisible() const;
+ BOOL isVisible() const;
+ BOOL isRecentlyVisible() const;
virtual void setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* results = NULL, BOOL for_select = FALSE);
@@ -126,11 +125,11 @@ public:
inline S32 getNumFaces() const;
//void removeFace(const S32 i); // SJB: Avoid using this, it's slow
- LLFace* addFace(LLFacePool *poolp, LLViewerImage *texturep);
- LLFace* addFace(const LLTextureEntry *te, LLViewerImage *texturep);
+ LLFace* addFace(LLFacePool *poolp, LLViewerTexture *texturep);
+ LLFace* addFace(const LLTextureEntry *te, LLViewerTexture *texturep);
void deleteFaces(S32 offset, S32 count);
- void setNumFaces(const S32 numFaces, LLFacePool *poolp, LLViewerImage *texturep);
- void setNumFacesFast(const S32 numFaces, LLFacePool *poolp, LLViewerImage *texturep);
+ void setNumFaces(const S32 numFaces, LLFacePool *poolp, LLViewerTexture *texturep);
+ void setNumFacesFast(const S32 numFaces, LLFacePool *poolp, LLViewerTexture *texturep);
void mergeFaces(LLDrawable* src);
void init();
@@ -151,7 +150,7 @@ public:
void updateTexture();
void updateMaterial();
- virtual void updateDistance(LLCamera& camera);
+ virtual void updateDistance(LLCamera& camera, bool force_update);
BOOL updateGeometry(BOOL priority);
void updateFaceSize(S32 idx);
@@ -266,7 +265,8 @@ public:
BUILT = 0x08000000,
FORCE_INVISIBLE = 0x10000000, // stay invis until CLEAR_INVISIBLE is set (set of orphaned)
CLEAR_INVISIBLE = 0x20000000, // clear FORCE_INVISIBLE next draw frame
- REBUILD_SHADOW = 0x40000000
+ REBUILD_SHADOW = 0x40000000,
+ HAS_ALPHA = 0x80000000,
} EDrawableFlags;
LLXformMatrix mXform;
@@ -279,7 +279,8 @@ public:
S32 mQuietCount;
static S32 getCurrentFrame() { return sCurVisible; }
-
+ static S32 getMinVisFrameRange();
+
void setSpatialBridge(LLSpatialBridge* bridge) { mSpatialBridge = (LLDrawable*) bridge; }
LLSpatialBridge* getSpatialBridge() { return (LLSpatialBridge*) (LLDrawable*) mSpatialBridge; }
@@ -301,7 +302,7 @@ private:
LLVector3d mPositionGroup;
F64 mBinRadius;
S32 mGeneration;
-
+
LLVector3 mCurrentScale;
static U32 sCurVisible; // Counter for what value of mVisible means currently visible
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index 9f05ce3c46..95ddacb722 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -60,7 +60,7 @@ S32 LLDrawPool::sNumDrawPools = 0;
//=============================
// Draw Pool Implementation
//=============================
-LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerImage *tex0)
+LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerTexture *tex0)
{
LLDrawPool *poolp = NULL;
switch (type)
@@ -129,7 +129,7 @@ LLDrawPool::~LLDrawPool()
}
-LLViewerImage *LLDrawPool::getDebugTexture()
+LLViewerTexture *LLDrawPool::getDebugTexture()
{
return NULL;
}
@@ -244,7 +244,7 @@ void LLFacePool::destroy()
}
}
-void LLFacePool::dirtyTextures(const std::set<LLViewerImage*>& textures)
+void LLFacePool::dirtyTextures(const std::set<LLViewerFetchedTexture*>& textures)
{
}
@@ -279,7 +279,7 @@ S32 LLFacePool::drawLoopSetTex(face_array_t& face_list, S32 stage)
iter != face_list.end(); iter++)
{
LLFace *facep = *iter;
- gGL.getTexUnit(stage)->bind(facep->getTexture());
+ gGL.getTexUnit(stage)->bind(facep->getTexture(), TRUE) ;
gGL.getTexUnit(0)->activate();
res += facep->renderIndexed();
}
@@ -295,13 +295,6 @@ void LLFacePool::drawLoop()
}
}
-void LLFacePool::renderFaceSelected(LLFace *facep,
- LLImageGL *image,
- const LLColor4 &color,
- const S32 index_offset, const S32 index_count)
-{
-}
-
void LLFacePool::enqueue(LLFace* facep)
{
mDrawFace.push_back(facep);
@@ -330,7 +323,7 @@ void LLFacePool::resetDrawOrders()
mDrawFace.resize(0);
}
-LLViewerImage *LLFacePool::getTexture()
+LLViewerTexture *LLFacePool::getTexture()
{
return NULL;
}
@@ -449,6 +442,7 @@ void LLRenderPass::renderTexture(U32 type, U32 mask)
void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture)
{
+ llpushcallstacks ;
for (LLCullResult::drawinfo_list_t::iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i)
{
LLDrawInfo* pparams = *i;
@@ -481,14 +475,13 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
{
if (params.mTexture.notNull())
{
- gGL.getTexUnit(0)->bind(params.mTexture.get());
+ gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ;
if (params.mTextureMatrix)
{
glMatrixMode(GL_TEXTURE);
glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
gPipeline.mTextureMatrixOps++;
}
- params.mTexture->addTextureStats(params.mVSize);
}
else
{
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index 87c3ccaffe..67870c10e9 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -39,8 +39,8 @@
#include "llvertexbuffer.h"
class LLFace;
-class LLImageGL;
-class LLViewerImage;
+class LLViewerTexture;
+class LLViewerFetchedTexture;
class LLSpatialGroup;
class LLDrawInfo;
@@ -61,12 +61,17 @@ public:
POOL_GRASS,
POOL_FULLBRIGHT,
POOL_BUMP,
- POOL_INVISIBLE,
+ POOL_INVISIBLE, // see below *
POOL_AVATAR,
POOL_WATER,
POOL_GLOW,
POOL_ALPHA,
NUM_POOL_TYPES,
+ // * invisiprims work by rendering to the depth buffer but not the color buffer, occluding anything rendered after them
+ // - and the LLDrawPool types enum controls what order things are rendered in
+ // - so, it has absolute control over what invisprims block
+ // ...invisiprims being rendered in pool_invisible
+ // ...shiny/bump mapped objects in rendered in POOL_BUMP
};
LLDrawPool(const U32 type);
@@ -77,7 +82,7 @@ public:
S32 getId() const { return mId; }
U32 getType() const { return mType; }
- virtual LLViewerImage *getDebugTexture();
+ virtual LLViewerTexture *getDebugTexture();
virtual void beginRenderPass( S32 pass );
virtual void endRenderPass( S32 pass );
virtual S32 getNumPasses();
@@ -103,9 +108,9 @@ public:
virtual BOOL verify() const { return TRUE; } // Verify that all data in the draw pool is correct!
virtual S32 getVertexShaderLevel() const { return mVertexShaderLevel; }
- static LLDrawPool* createPool(const U32 type, LLViewerImage *tex0 = NULL);
+ static LLDrawPool* createPool(const U32 type, LLViewerTexture *tex0 = NULL);
virtual LLDrawPool *instancePool() = 0; // Create an empty new instance of the pool.
- virtual LLViewerImage* getTexture() = 0;
+ virtual LLViewerTexture* getTexture() = 0;
virtual BOOL isFacePool() { return FALSE; }
virtual void resetDrawOrders() = 0;
@@ -139,8 +144,8 @@ public:
LLRenderPass(const U32 type);
virtual ~LLRenderPass();
/*virtual*/ LLDrawPool* instancePool();
- /*virtual*/ LLViewerImage* getDebugTexture() { return NULL; }
- LLViewerImage* getTexture() { return NULL; }
+ /*virtual*/ LLViewerTexture* getDebugTexture() { return NULL; }
+ LLViewerTexture* getTexture() { return NULL; }
BOOL isDead() { return FALSE; }
void resetDrawOrders() { }
@@ -169,11 +174,9 @@ public:
virtual void renderForSelect() = 0;
BOOL isDead() { return mReferences.empty(); }
- virtual void renderFaceSelected(LLFace *facep, LLImageGL *image, const LLColor4 &color,
- const S32 index_offset = 0, const S32 index_count = 0);
-
- virtual LLViewerImage *getTexture();
- virtual void dirtyTextures(const std::set<LLViewerImage*>& textures);
+
+ virtual LLViewerTexture *getTexture();
+ virtual void dirtyTextures(const std::set<LLViewerFetchedTexture*>& textures);
virtual void enqueue(LLFace *face);
virtual BOOL addFace(LLFace *face);
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 7e470bd01f..6d77361414 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -42,11 +42,10 @@
#include "llcubemap.h"
#include "llsky.h"
-#include "llagent.h"
#include "lldrawable.h"
#include "llface.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h" // For debugging
+#include "llviewertexturelist.h" // For debugging
#include "llviewerobjectlist.h" // For debugging
#include "llviewerwindow.h"
#include "pipeline.h"
@@ -88,22 +87,23 @@ void LLDrawPoolAlpha::beginDeferredPass(S32 pass)
void LLDrawPoolAlpha::endDeferredPass(S32 pass)
{
- gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.4f);
+
+}
+
+void LLDrawPoolAlpha::renderDeferred(S32 pass)
+{
+ gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f);
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS);
+ LLFastTimer t(FTM_RENDER_GRASS);
gDeferredTreeProgram.bind();
LLGLEnable test(GL_ALPHA_TEST);
//render alpha masked objects
LLRenderPass::renderTexture(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask());
+ gDeferredTreeProgram.unbind();
}
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
}
-void LLDrawPoolAlpha::renderDeferred(S32 pass)
-{
-
-}
-
S32 LLDrawPoolAlpha::getNumPostDeferredPasses()
{
@@ -112,7 +112,7 @@ S32 LLDrawPoolAlpha::getNumPostDeferredPasses()
void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA);
+ LLFastTimer t(FTM_RENDER_ALPHA);
simple_shader = &gDeferredAlphaProgram;
fullbright_shader = &gDeferredFullbrightProgram;
@@ -139,7 +139,7 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass)
void LLDrawPoolAlpha::beginRenderPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA);
+ LLFastTimer t(FTM_RENDER_ALPHA);
if (LLPipeline::sUnderWaterRender)
{
@@ -163,7 +163,7 @@ void LLDrawPoolAlpha::beginRenderPass(S32 pass)
void LLDrawPoolAlpha::endRenderPass( S32 pass )
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA);
+ LLFastTimer t(FTM_RENDER_ALPHA);
LLRenderPass::endRenderPass(pass);
if(gPipeline.canUseWindLightShaders())
@@ -174,7 +174,7 @@ void LLDrawPoolAlpha::endRenderPass( S32 pass )
void LLDrawPoolAlpha::render(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA);
+ LLFastTimer t(FTM_RENDER_ALPHA);
LLGLSPipelineAlpha gls_pipeline_alpha;
@@ -218,8 +218,8 @@ void LLDrawPoolAlpha::render(S32 pass)
}
gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
glColor4f(1,0,0,1);
- LLViewerImage::sSmokeImagep->addTextureStats(1024.f*1024.f);
- gGL.getTexUnit(0)->bind(LLViewerImage::sSmokeImagep.get());
+ LLViewerFetchedTexture::sSmokeImagep->addTextureStats(1024.f*1024.f);
+ gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sSmokeImagep, TRUE) ;
renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX |
LLVertexBuffer::MAP_TEXCOORD0);
}
@@ -261,6 +261,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
{
BOOL initialized_lighting = FALSE;
BOOL light_enabled = TRUE;
+ S32 diffuse_channel = 0;
+
//BOOL is_particle = FALSE;
BOOL use_shaders = (LLPipeline::sUnderWaterRender && gPipeline.canUseVertexShaders())
|| gPipeline.canUseWindLightShadersOnObjects();
@@ -291,19 +293,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
LLRenderPass::applyModelMatrix(params);
- if (params.mTexture.notNull())
- {
- gGL.getTexUnit(0)->activate();
- gGL.getTexUnit(0)->bind(params.mTexture.get());
- params.mTexture->addTextureStats(params.mVSize);
- if (params.mTextureMatrix)
- {
- glMatrixMode(GL_TEXTURE);
- glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
- gPipeline.mTextureMatrixOps++;
- }
- }
-
if (params.mFullbright)
{
// Turn off lighting if it hasn't already been so.
@@ -344,11 +333,13 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
if (deferred_render && current_shader != NULL)
{
gPipeline.unbindDeferredShader(*current_shader);
+ diffuse_channel = 0;
}
current_shader = target_shader;
if (deferred_render)
{
gPipeline.bindDeferredShader(*current_shader);
+ diffuse_channel = current_shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
}
else
{
@@ -357,11 +348,12 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
}
else if (!use_shaders && current_shader != NULL)
{
- LLGLSLShader::bindNoShader();
if (deferred_render)
{
gPipeline.unbindDeferredShader(*current_shader);
+ diffuse_channel = 0;
}
+ LLGLSLShader::bindNoShader();
current_shader = NULL;
}
@@ -369,6 +361,24 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
{
params.mGroup->rebuildMesh();
}
+
+
+ if (params.mTexture.notNull())
+ {
+ gGL.getTexUnit(diffuse_channel)->bind(params.mTexture.get());
+ if(params.mTexture.notNull())
+ {
+ params.mTexture->addTextureStats(params.mVSize);
+ }
+ if (params.mTextureMatrix)
+ {
+ gGL.getTexUnit(0)->activate();
+ glMatrixMode(GL_TEXTURE);
+ glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
+ gPipeline.mTextureMatrixOps++;
+ }
+ }
+
params.mVertexBuffer->setBuffer(mask);
params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
gPipeline.addTrianglesDrawn(params.mCount/3);
@@ -383,6 +393,15 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
}
}
+ if (deferred_render && current_shader != NULL)
+ {
+ gPipeline.unbindDeferredShader(*current_shader);
+ LLVertexBuffer::unbind();
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+ }
+
if (!light_enabled)
{
gPipeline.enableLightsDynamic();
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 80c7d73e6a..546b60f286 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -38,7 +38,6 @@
#include "llvoavatar.h"
#include "m3math.h"
-#include "llagent.h"
#include "lldrawable.h"
#include "llface.h"
#include "llsky.h"
@@ -89,17 +88,17 @@ S32 AVATAR_OFFSET_TEX0 = 32;
S32 AVATAR_OFFSET_TEX1 = 40;
S32 AVATAR_VERTEX_BYTES = 48;
-
BOOL gAvatarEmbossBumpMap = FALSE;
static BOOL sRenderingSkinned = FALSE;
S32 normal_channel = -1;
S32 specular_channel = -1;
+S32 diffuse_channel = -1;
+
+static LLFastTimer::DeclareTimer FTM_SHADOW_AVATAR("Avatar Shadow");
-LLDrawPoolAvatar::LLDrawPoolAvatar() :
-LLFacePool(POOL_AVATAR)
+LLDrawPoolAvatar::LLDrawPoolAvatar() :
+ LLFacePool(POOL_AVATAR)
{
- //LLDebugVarMessageBox::show("acceleration", &CLOTHING_ACCEL_FORCE_FACTOR, 10.f, 0.1f);
- //LLDebugVarMessageBox::show("gravity", &CLOTHING_GRAVITY_EFFECT, 10.f, 0.1f);
}
//-----------------------------------------------------------------------------
@@ -110,7 +109,6 @@ LLDrawPool *LLDrawPoolAvatar::instancePool()
return new LLDrawPoolAvatar();
}
-BOOL gRenderAvatar = TRUE;
S32 LLDrawPoolAvatar::getVertexShaderLevel() const
{
@@ -157,7 +155,7 @@ S32 LLDrawPoolAvatar::getNumDeferredPasses()
void LLDrawPoolAvatar::beginDeferredPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS);
+ LLFastTimer t(FTM_RENDER_CHARACTERS);
if (LLPipeline::sImpostorRender)
{
@@ -181,7 +179,7 @@ void LLDrawPoolAvatar::beginDeferredPass(S32 pass)
void LLDrawPoolAvatar::endDeferredPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS);
+ LLFastTimer t(FTM_RENDER_CHARACTERS);
if (LLPipeline::sImpostorRender)
{
@@ -251,7 +249,7 @@ S32 LLDrawPoolAvatar::getNumShadowPasses()
void LLDrawPoolAvatar::beginShadowPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_SHADOW_AVATAR);
+ LLFastTimer t(FTM_SHADOW_AVATAR);
sVertexProgram = &gDeferredAvatarShadowProgram;
if (sShaderLevel > 0)
@@ -273,7 +271,7 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass)
void LLDrawPoolAvatar::endShadowPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_SHADOW_AVATAR);
+ LLFastTimer t(FTM_SHADOW_AVATAR);
if (sShaderLevel > 0)
{
@@ -287,11 +285,7 @@ void LLDrawPoolAvatar::endShadowPass(S32 pass)
void LLDrawPoolAvatar::renderShadow(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_SHADOW_AVATAR);
- if (!gRenderAvatar)
- {
- return;
- }
+ LLFastTimer t(FTM_SHADOW_AVATAR);
if (mDrawFace.empty())
{
@@ -327,7 +321,7 @@ S32 LLDrawPoolAvatar::getNumPasses()
void LLDrawPoolAvatar::render(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS);
+ LLFastTimer t(FTM_RENDER_CHARACTERS);
if (LLPipeline::sImpostorRender)
{
renderAvatars(NULL, 2);
@@ -339,7 +333,7 @@ void LLDrawPoolAvatar::render(S32 pass)
void LLDrawPoolAvatar::beginRenderPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS);
+ LLFastTimer t(FTM_RENDER_CHARACTERS);
//reset vertex buffer mappings
LLVertexBuffer::unbind();
@@ -365,7 +359,7 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass)
void LLDrawPoolAvatar::endRenderPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS);
+ LLFastTimer t(FTM_RENDER_CHARACTERS);
if (LLPipeline::sImpostorRender)
{
@@ -395,6 +389,7 @@ void LLDrawPoolAvatar::beginFootShadow()
}
gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
+ diffuse_channel = 0;
}
void LLDrawPoolAvatar::endFootShadow()
@@ -447,7 +442,8 @@ void LLDrawPoolAvatar::beginDeferredImpostor()
normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL);
specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP);
-
+ diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+
sVertexProgram->bind();
}
@@ -456,6 +452,7 @@ void LLDrawPoolAvatar::endDeferredImpostor()
sShaderLevel = mVertexShaderLevel;
sVertexProgram->disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL);
sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP);
+ sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
sVertexProgram->unbind();
gGL.getTexUnit(0)->activate();
}
@@ -609,13 +606,6 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
return;
}
-
-
- if (!gRenderAvatar)
- {
- return;
- }
-
if (mDrawFace.empty() && !single_avatar)
{
return;
@@ -647,7 +637,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (pass==1 && (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) || LLViewerPartSim::getMaxPartCount() <= 0))
{
// debug code to draw a sphere in place of avatar
- gGL.getTexUnit(0)->bind(LLViewerImage::sWhiteImagep.get());
+ gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
gGL.setColorMask(true, true);
LLVector3 pos = avatarp->getPositionAgent();
gGL.color4f(1.0f, 1.0f, 1.0f, 0.7f);
@@ -699,7 +689,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
avatarp->mImpostor.bindTexture(1, specular_channel);
}
}
- avatarp->renderImpostor();
+ avatarp->renderImpostor(LLColor4U(255,255,255,255), diffuse_channel);
}
else if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS) && !LLPipeline::sRenderDeferred)
{
@@ -761,10 +751,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
//-----------------------------------------------------------------------------
void LLDrawPoolAvatar::renderForSelect()
{
- if (!gRenderAvatar)
- {
- return;
- }
+
if (mDrawFace.empty())
{
@@ -836,7 +823,7 @@ void LLDrawPoolAvatar::renderForSelect()
//-----------------------------------------------------------------------------
// getDebugTexture()
//-----------------------------------------------------------------------------
-LLViewerImage *LLDrawPoolAvatar::getDebugTexture()
+LLViewerTexture *LLDrawPoolAvatar::getDebugTexture()
{
if (mReferences.empty())
{
diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h
index 1e2630e1fb..6a2b7fc218 100644
--- a/indra/newview/lldrawpoolavatar.h
+++ b/indra/newview/lldrawpoolavatar.h
@@ -105,7 +105,7 @@ public:
void endDeferredRigid();
void endDeferredSkinned();
- /*virtual*/ LLViewerImage *getDebugTexture();
+ /*virtual*/ LLViewerTexture *getDebugTexture();
/*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display
void renderAvatars(LLVOAvatar *single_avatar, S32 pass = -1); // renders only one avatar if single_avatar is not null.
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index b11dcc1608..03a8b108e2 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -37,21 +37,19 @@
#include "llstl.h"
#include "llviewercontrol.h"
#include "lldir.h"
-#include "llimagegl.h"
#include "m3math.h"
#include "m4math.h"
#include "v4math.h"
#include "llglheaders.h"
#include "llrender.h"
-#include "llagent.h"
#include "llcubemap.h"
#include "lldrawable.h"
#include "llface.h"
#include "llsky.h"
#include "lltextureentry.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "pipeline.h"
#include "llspatialpartition.h"
#include "llviewershadermgr.h"
@@ -75,6 +73,7 @@ const U32 VERTEX_MASK_BUMP = LLVertexBuffer::MAP_VERTEX |LLVertexBuffer::MAP_TEX
U32 LLDrawPoolBump::sVertexMask = VERTEX_MASK_SHINY;
+
static LLGLSLShader* shader = NULL;
static S32 cube_channel = -1;
static S32 diffuse_channel = -1;
@@ -127,9 +126,9 @@ void LLStandardBumpmap::restoreGL()
{
// *NOTE: This buffer size is hard coded into scanf() below.
char label[2048] = ""; /* Flawfinder: ignore */
- char bump_file[2048] = ""; /* Flawfinder: ignore */
+ char bump_image_id[2048] = ""; /* Flawfinder: ignore */
fields_read = fscanf( /* Flawfinder: ignore */
- file, "\n%2047s %2047s", label, bump_file);
+ file, "\n%2047s %2047s", label, bump_image_id);
if( EOF == fields_read )
{
break;
@@ -140,12 +139,13 @@ void LLStandardBumpmap::restoreGL()
return;
}
-// llinfos << "Loading bumpmap: " << bump_file << " from viewerart" << llendl;
+// llinfos << "Loading bumpmap: " << bump_image_id << " from viewerart" << llendl;
gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mLabel = label;
gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage =
- gImageList.getImageFromFile(bump_file,
+ LLViewerTextureManager::getFetchedTexture(LLUUID(bump_image_id),
TRUE,
- FALSE,
+ LLViewerTexture::BOOST_NONE,
+ LLViewerTexture::LOD_TEXTURE,
0,
0);
gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setLoadedCallback(LLBumpImageList::onSourceStandardLoaded, 0, TRUE, FALSE, NULL );
@@ -220,7 +220,7 @@ S32 LLDrawPoolBump::getNumPasses()
void LLDrawPoolBump::beginRenderPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP);
+ LLFastTimer t(FTM_RENDER_BUMP);
switch( pass )
{
case 0:
@@ -247,7 +247,7 @@ void LLDrawPoolBump::beginRenderPass(S32 pass)
void LLDrawPoolBump::render(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP);
+ LLFastTimer t(FTM_RENDER_BUMP);
if (!gPipeline.hasRenderType(LLDrawPool::POOL_SIMPLE))
{
@@ -280,7 +280,7 @@ void LLDrawPoolBump::render(S32 pass)
void LLDrawPoolBump::endRenderPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP);
+ LLFastTimer t(FTM_RENDER_BUMP);
switch( pass )
{
case 0:
@@ -308,9 +308,9 @@ void LLDrawPoolBump::endRenderPass(S32 pass)
//static
void LLDrawPoolBump::beginShiny(bool invisible)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY);
- if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)||
- invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))
+ LLFastTimer t(FTM_RENDER_SHINY);
+ if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))||
+ (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)))
{
return;
}
@@ -383,9 +383,9 @@ void LLDrawPoolBump::beginShiny(bool invisible)
void LLDrawPoolBump::renderShiny(bool invisible)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY);
- if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)||
- invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))
+ LLFastTimer t(FTM_RENDER_SHINY);
+ if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))||
+ (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)))
{
return;
}
@@ -410,9 +410,9 @@ void LLDrawPoolBump::renderShiny(bool invisible)
void LLDrawPoolBump::endShiny(bool invisible)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY);
- if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)||
- invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))
+ LLFastTimer t(FTM_RENDER_SHINY);
+ if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))||
+ (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)))
{
return;
}
@@ -450,7 +450,7 @@ void LLDrawPoolBump::endShiny(bool invisible)
void LLDrawPoolBump::beginFullbrightShiny()
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY);
+ LLFastTimer t(FTM_RENDER_SHINY);
if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY))
{
return;
@@ -499,7 +499,7 @@ void LLDrawPoolBump::beginFullbrightShiny()
void LLDrawPoolBump::renderFullbrightShiny()
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY);
+ LLFastTimer t(FTM_RENDER_SHINY);
if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY))
{
return;
@@ -514,7 +514,7 @@ void LLDrawPoolBump::renderFullbrightShiny()
void LLDrawPoolBump::endFullbrightShiny()
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY);
+ LLFastTimer t(FTM_RENDER_SHINY);
if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY))
{
return;
@@ -569,22 +569,25 @@ void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL
// static
BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel)
{
- LLImageGL* bump = NULL;
+ LLViewerTexture* bump = NULL;
U8 bump_code = params.mBump;
- LLViewerImage* tex = params.mTexture;
+
+ //Note: texture atlas does not support bump texture now.
+ LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(params.mTexture) ;
+ if(!tex)
+ {
+ //if the texture is not a fetched texture
+ return FALSE;
+ }
switch( bump_code )
{
- case BE_NO_BUMP:
- bump = NULL;
+ case BE_NO_BUMP:
break;
case BE_BRIGHTNESS:
case BE_DARKNESS:
- if( tex )
- {
- bump = gBumpImageList.getBrightnessDarknessImage( tex, bump_code );
- }
+ bump = gBumpImageList.getBrightnessDarknessImage( tex, bump_code );
break;
default:
@@ -623,7 +626,7 @@ void LLDrawPoolBump::beginBump()
}
sVertexMask = VERTEX_MASK_BUMP;
- LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP);
+ LLFastTimer t(FTM_RENDER_BUMP);
// Optional second pass: emboss bump map
stop_glerror();
@@ -667,7 +670,7 @@ void LLDrawPoolBump::renderBump()
return;
}
- LLFastTimer ftm(LLFastTimer::FTM_RENDER_BUMP);
+ LLFastTimer ftm(FTM_RENDER_BUMP);
LLGLDisable fog(GL_FOG);
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_LEQUAL);
LLGLEnable blend(GL_BLEND);
@@ -704,7 +707,7 @@ void LLDrawPoolBump::beginDeferredPass(S32 pass)
{
return;
}
- LLFastTimer ftm(LLFastTimer::FTM_RENDER_BUMP);
+ LLFastTimer ftm(FTM_RENDER_BUMP);
mShiny = TRUE;
gDeferredBumpProgram.bind();
diffuse_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
@@ -719,7 +722,7 @@ void LLDrawPoolBump::endDeferredPass(S32 pass)
{
return;
}
- LLFastTimer ftm(LLFastTimer::FTM_RENDER_BUMP);
+ LLFastTimer ftm(FTM_RENDER_BUMP);
mShiny = FALSE;
gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::BUMP_MAP);
@@ -733,7 +736,7 @@ void LLDrawPoolBump::renderDeferred(S32 pass)
{
return;
}
- LLFastTimer ftm(LLFastTimer::FTM_RENDER_BUMP);
+ LLFastTimer ftm(FTM_RENDER_BUMP);
U32 type = LLRenderPass::PASS_BUMP;
LLCullResult::drawinfo_list_t::iterator begin = gPipeline.beginRenderMap(type);
@@ -812,7 +815,7 @@ LLBumpImageList::~LLBumpImageList()
void LLBumpImageList::addTextureStats(U8 bump, const LLUUID& base_image_id, F32 virtual_size)
{
bump &= TEM_BUMP_MASK;
- LLViewerImage* bump_image = gStandardBumpmapList[bump].mImage;
+ LLViewerFetchedTexture* bump_image = gStandardBumpmapList[bump].mImage;
if( bump_image )
{
bump_image->addTextureStats(virtual_size);
@@ -826,11 +829,11 @@ void LLBumpImageList::updateImages()
for (bump_image_map_t::iterator iter = mBrightnessEntries.begin(); iter != mBrightnessEntries.end(); )
{
bump_image_map_t::iterator curiter = iter++;
- LLImageGL* image = curiter->second;
+ LLViewerTexture* image = curiter->second;
if( image )
{
BOOL destroy = TRUE;
- if( image->getHasGLTexture())
+ if( image->hasGLTexture())
{
if( image->getBoundRecently() )
{
@@ -853,11 +856,11 @@ void LLBumpImageList::updateImages()
for (bump_image_map_t::iterator iter = mDarknessEntries.begin(); iter != mDarknessEntries.end(); )
{
bump_image_map_t::iterator curiter = iter++;
- LLImageGL* image = curiter->second;
+ LLViewerTexture* image = curiter->second;
if( image )
{
BOOL destroy = TRUE;
- if( image->getHasGLTexture())
+ if( image->hasGLTexture())
{
if( image->getBoundRecently() )
{
@@ -881,16 +884,16 @@ void LLBumpImageList::updateImages()
// Note: the caller SHOULD NOT keep the pointer that this function returns. It may be updated as more data arrives.
-LLImageGL* LLBumpImageList::getBrightnessDarknessImage(LLViewerImage* src_image, U8 bump_code )
+LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedTexture* src_image, U8 bump_code )
{
llassert( (bump_code == BE_BRIGHTNESS) || (bump_code == BE_DARKNESS) );
- LLImageGL* bump = NULL;
+ LLViewerTexture* bump = NULL;
const F32 BRIGHTNESS_DARKNESS_PIXEL_AREA_THRESHOLD = 1000;
- if( src_image->mMaxVirtualSize > BRIGHTNESS_DARKNESS_PIXEL_AREA_THRESHOLD )
+ if( src_image->getMaxVirtualSize() > BRIGHTNESS_DARKNESS_PIXEL_AREA_THRESHOLD )
{
bump_image_map_t* entries_list = NULL;
- void (*callback_func)( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) = NULL;
+ void (*callback_func)( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) = NULL;
switch( bump_code )
{
@@ -917,14 +920,8 @@ LLImageGL* LLBumpImageList::getBrightnessDarknessImage(LLViewerImage* src_image,
LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,1);
raw->clear(0x77, 0x77, 0x77, 0xFF);
- //------------------------------
- bump = new LLImageGL( raw, TRUE);
- //immediately assign bump to a global smart pointer in case some local smart pointer
- //accidently releases it.
- (*entries_list)[src_image->getID()] = bump;
- //------------------------------
-
- bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA);
+ (*entries_list)[src_image->getID()] = LLViewerTextureManager::getLocalTexture( raw.get(), TRUE);
+ (*entries_list)[src_image->getID()]->setExplicitFormat(GL_ALPHA8, GL_ALPHA);
// Note: this may create an LLImageGL immediately
src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()) );
@@ -940,7 +937,7 @@ LLImageGL* LLBumpImageList::getBrightnessDarknessImage(LLViewerImage* src_image,
// static
-void LLBumpImageList::onSourceBrightnessLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
+void LLBumpImageList::onSourceBrightnessLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
{
LLUUID* source_asset_id = (LLUUID*)userdata;
LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_BRIGHTNESS );
@@ -951,7 +948,7 @@ void LLBumpImageList::onSourceBrightnessLoaded( BOOL success, LLViewerImage *src
}
// static
-void LLBumpImageList::onSourceDarknessLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
+void LLBumpImageList::onSourceDarknessLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
{
LLUUID* source_asset_id = (LLUUID*)userdata;
LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_DARKNESS );
@@ -961,14 +958,14 @@ void LLBumpImageList::onSourceDarknessLoaded( BOOL success, LLViewerImage *src_v
}
}
-void LLBumpImageList::onSourceStandardLoaded( BOOL success, LLViewerImage* src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata)
+void LLBumpImageList::onSourceStandardLoaded( BOOL success, LLViewerFetchedTexture* src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata)
{
if (success && LLPipeline::sRenderDeferred)
{
LLPointer<LLImageRaw> nrm_image = new LLImageRaw(src->getWidth(), src->getHeight(), 4);
generateNormalMapFromAlpha(src, nrm_image);
src_vi->setExplicitFormat(GL_RGBA, GL_RGBA);
- src_vi->createGLTexture(0, nrm_image);
+ src_vi->createGLTexture(src_vi->getDiscardLevel(), nrm_image);
}
}
@@ -1028,7 +1025,7 @@ void LLBumpImageList::generateNormalMapFromAlpha(LLImageRaw* src, LLImageRaw* nr
}
// static
-void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump_code )
+void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump_code )
{
if( success )
{
@@ -1147,7 +1144,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerImage *src_vi, LLIma
//---------------------------------------------------
//immediately assign bump to a global smart pointer in case some local smart pointer
//accidently releases it.
- LLPointer<LLImageGL> bump = new LLImageGL( TRUE);
+ LLPointer<LLViewerTexture> bump = LLViewerTextureManager::getLocalTexture( TRUE);
if (!LLPipeline::sRenderDeferred)
{
@@ -1220,8 +1217,8 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
{
if (params.mTexture.notNull())
{
- gGL.getTexUnit(diffuse_channel)->bind(params.mTexture.get());
- params.mTexture->addTextureStats(params.mVSize);
+ gGL.getTexUnit(diffuse_channel)->bind(params.mTexture) ;
+ params.mTexture->addTextureStats(params.mVSize);
}
else
{
@@ -1255,7 +1252,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
void LLDrawPoolInvisible::render(S32 pass)
{ //render invisiprims
- LLFastTimer t(LLFastTimer::FTM_RENDER_INVISIBLE);
+ LLFastTimer t(FTM_RENDER_INVISIBLE);
U32 invisi_mask = LLVertexBuffer::MAP_VERTEX;
glStencilMask(0);
@@ -1284,7 +1281,7 @@ void LLDrawPoolInvisible::endDeferredPass( S32 pass )
void LLDrawPoolInvisible::renderDeferred( S32 pass )
{ //render invisiprims; this doesn't work becaue it also blocks all the post-deferred stuff
- LLFastTimer t(LLFastTimer::FTM_RENDER_INVISIBLE);
+ LLFastTimer t(FTM_RENDER_INVISIBLE);
U32 invisi_mask = LLVertexBuffer::MAP_VERTEX;
glStencilMask(0);
diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h
index 34c1e9c29f..bf940cf1e4 100644
--- a/indra/newview/lldrawpoolbump.h
+++ b/indra/newview/lldrawpoolbump.h
@@ -41,6 +41,7 @@
class LLImageRaw;
class LLSpatialGroup;
class LLDrawInfo;
+class LLViewerFetchedTexture;
class LLDrawPoolBump : public LLRenderPass
{
@@ -110,7 +111,7 @@ public:
LLStandardBumpmap( const std::string& label ) : mLabel(label) {}
std::string mLabel;
- LLPointer<LLViewerImage> mImage;
+ LLPointer<LLViewerFetchedTexture> mImage;
static U32 sStandardBumpmapCount; // Number of valid values in gStandardBumpmapList[]
@@ -140,21 +141,20 @@ public:
void updateImages();
- LLImageGL* getBrightnessDarknessImage(LLViewerImage* src_image, U8 bump_code);
-// LLImageGL* getTestImage();
+ LLViewerTexture* getBrightnessDarknessImage(LLViewerFetchedTexture* src_image, U8 bump_code);
void addTextureStats(U8 bump, const LLUUID& base_image_id, F32 virtual_size);
- static void onSourceBrightnessLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata );
- static void onSourceDarknessLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata );
- static void onSourceStandardLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata );
+ static void onSourceBrightnessLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata );
+ static void onSourceDarknessLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata );
+ static void onSourceStandardLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata );
static void generateNormalMapFromAlpha(LLImageRaw* src, LLImageRaw* nrm_image);
private:
- static void onSourceLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump );
+ static void onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump );
private:
- typedef std::map<LLUUID, LLPointer<LLImageGL> > bump_image_map_t;
+ typedef std::map<LLUUID, LLPointer<LLViewerTexture> > bump_image_map_t;
bump_image_map_t mBrightnessEntries;
bump_image_map_t mDarknessEntries;
};
diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp
index 1fdf87f6d2..ca7a1b47c2 100644
--- a/indra/newview/lldrawpoolsimple.cpp
+++ b/indra/newview/lldrawpoolsimple.cpp
@@ -35,7 +35,6 @@
#include "lldrawpoolsimple.h"
#include "llviewercamera.h"
-#include "llagent.h"
#include "lldrawable.h"
#include "llface.h"
#include "llsky.h"
@@ -48,9 +47,12 @@
static LLGLSLShader* simple_shader = NULL;
static LLGLSLShader* fullbright_shader = NULL;
+static LLFastTimer::DeclareTimer FTM_RENDER_SIMPLE_DEFERRED("Deferred Simple");
+static LLFastTimer::DeclareTimer FTM_RENDER_GRASS_DEFERRED("Deferred Grass");
+
void LLDrawPoolGlow::render(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_GLOW);
+ LLFastTimer t(FTM_RENDER_GLOW);
LLGLEnable blend(GL_BLEND);
LLGLDisable test(GL_ALPHA_TEST);
gGL.setSceneBlendType(LLRender::BT_ADD);
@@ -98,7 +100,7 @@ void LLDrawPoolSimple::prerender()
void LLDrawPoolSimple::beginRenderPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE);
+ LLFastTimer t(FTM_RENDER_SIMPLE);
if (LLPipeline::sUnderWaterRender)
{
@@ -125,7 +127,7 @@ void LLDrawPoolSimple::beginRenderPass(S32 pass)
void LLDrawPoolSimple::endRenderPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE);
+ LLFastTimer t(FTM_RENDER_SIMPLE);
LLRenderPass::endRenderPass(pass);
if (mVertexShaderLevel > 0){
@@ -140,7 +142,7 @@ void LLDrawPoolSimple::render(S32 pass)
LLGLDisable alpha_test(GL_ALPHA_TEST);
{ //render simple
- LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE);
+ LLFastTimer t(FTM_RENDER_SIMPLE);
gPipeline.enableLightsDynamic();
renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask());
@@ -157,13 +159,13 @@ void LLDrawPoolSimple::render(S32 pass)
void LLDrawPoolSimple::beginDeferredPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE);
+ LLFastTimer t(FTM_RENDER_SIMPLE_DEFERRED);
gDeferredDiffuseProgram.bind();
}
void LLDrawPoolSimple::endDeferredPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE);
+ LLFastTimer t(FTM_RENDER_SIMPLE_DEFERRED);
LLRenderPass::endRenderPass(pass);
gDeferredDiffuseProgram.unbind();
@@ -175,7 +177,7 @@ void LLDrawPoolSimple::renderDeferred(S32 pass)
LLGLDisable alpha_test(GL_ALPHA_TEST);
{ //render simple
- LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE);
+ LLFastTimer t(FTM_RENDER_SIMPLE_DEFERRED);
renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask());
}
}
@@ -195,7 +197,7 @@ void LLDrawPoolGrass::prerender()
void LLDrawPoolGrass::beginRenderPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS);
+ LLFastTimer t(FTM_RENDER_GRASS);
if (LLPipeline::sUnderWaterRender)
{
@@ -222,7 +224,7 @@ void LLDrawPoolGrass::beginRenderPass(S32 pass)
void LLDrawPoolGrass::endRenderPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS);
+ LLFastTimer t(FTM_RENDER_GRASS);
LLRenderPass::endRenderPass(pass);
if (mVertexShaderLevel > 0)
@@ -237,7 +239,7 @@ void LLDrawPoolGrass::render(S32 pass)
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS);
+ LLFastTimer t(FTM_RENDER_GRASS);
LLGLEnable test(GL_ALPHA_TEST);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
//render grass
@@ -259,10 +261,10 @@ void LLDrawPoolGrass::endDeferredPass(S32 pass)
void LLDrawPoolGrass::renderDeferred(S32 pass)
{
- gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
+ gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f);
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS);
+ LLFastTimer t(FTM_RENDER_GRASS_DEFERRED);
gDeferredTreeProgram.bind();
LLGLEnable test(GL_ALPHA_TEST);
//render grass
@@ -286,7 +288,7 @@ void LLDrawPoolFullbright::prerender()
void LLDrawPoolFullbright::beginRenderPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT);
+ LLFastTimer t(FTM_RENDER_FULLBRIGHT);
if (LLPipeline::sUnderWaterRender)
{
@@ -300,7 +302,7 @@ void LLDrawPoolFullbright::beginRenderPass(S32 pass)
void LLDrawPoolFullbright::endRenderPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT);
+ LLFastTimer t(FTM_RENDER_FULLBRIGHT);
LLRenderPass::endRenderPass(pass);
if (mVertexShaderLevel > 0)
@@ -311,7 +313,7 @@ void LLDrawPoolFullbright::endRenderPass(S32 pass)
void LLDrawPoolFullbright::render(S32 pass)
{ //render fullbright
- LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT);
+ LLFastTimer t(FTM_RENDER_FULLBRIGHT);
if (mVertexShaderLevel > 0)
{
fullbright_shader->bind();
diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp
index 7f21adcc94..8428be194f 100644
--- a/indra/newview/lldrawpoolsky.cpp
+++ b/indra/newview/lldrawpoolsky.cpp
@@ -41,9 +41,8 @@
#include "llface.h"
#include "llsky.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewerregion.h"
-#include "llviewerwindow.h"
#include "llvosky.h"
#include "llworld.h" // To get water height
#include "pipeline.h"
@@ -61,8 +60,8 @@ LLDrawPool *LLDrawPoolSky::instancePool()
void LLDrawPoolSky::prerender()
{
- mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT);
-// gSky.mVOSkyp->updateGeometry(gSky.mVOSkyp->mDrawable);
+ mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT);
+ gSky.mVOSkyp->updateGeometry(gSky.mVOSkyp->mDrawable);
}
void LLDrawPoolSky::render(S32 pass)
@@ -97,7 +96,6 @@ void LLDrawPoolSky::render(S32 pass)
}
- LLVOSky *voskyp = gSky.mVOSkyp;
LLGLSPipelineSkyBox gls_skybox;
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
@@ -120,43 +118,9 @@ void LLDrawPoolSky::render(S32 pass)
{
renderSkyCubeFace(i);
}
-
- LLFace *hbfaces[3];
- hbfaces[0] = NULL;
- hbfaces[1] = NULL;
- hbfaces[2] = NULL;
- for (S32 curr_face = 0; curr_face < face_count; curr_face++)
- {
- LLFace* facep = mDrawFace[curr_face];
- if (voskyp->isSameFace(LLVOSky::FACE_SUN, facep))
- {
- hbfaces[0] = facep;
- }
- if (voskyp->isSameFace(LLVOSky::FACE_MOON, facep))
- {
- hbfaces[1] = facep;
- }
- if (voskyp->isSameFace(LLVOSky::FACE_BLOOM, facep))
- {
- hbfaces[2] = facep;
- }
- }
LLGLEnable blend(GL_BLEND);
- if (hbfaces[2])
- {
- // renderSunHalo(hbfaces[2]);
- }
- if (hbfaces[0])
- {
- // renderHeavenlyBody(0, hbfaces[0]);
- }
- if (hbfaces[1])
- {
- // renderHeavenlyBody(1, hbfaces[1]);
- }
-
glPopMatrix();
}
@@ -181,35 +145,6 @@ void LLDrawPoolSky::renderSkyCubeFace(U8 side)
}
}
-void LLDrawPoolSky::renderHeavenlyBody(U8 hb, LLFace* face)
-{
- if ( !mHB[hb]->getDraw() ) return;
- if (! face->getGeomCount()) return;
-
- LLImageGL* tex = face->getTexture();
- gGL.getTexUnit(0)->bind(tex);
- LLColor4 color(mHB[hb]->getInterpColor());
- LLOverrideFaceColor override(this, color);
- face->renderIndexed();
-}
-
-
-
-void LLDrawPoolSky::renderSunHalo(LLFace* face)
-{
- if (! mHB[0]->getDraw()) return;
- if (! face->getGeomCount()) return;
-
- LLImageGL* tex = face->getTexture();
- gGL.getTexUnit(0)->bind(tex);
- LLColor4 color(mHB[0]->getInterpColor());
- color.mV[3] = llclamp(mHB[0]->getHaloBrighness(), 0.f, 1.f);
-
- LLOverrideFaceColor override(this, color);
- face->renderIndexed();
-}
-
-
void LLDrawPoolSky::renderForSelect()
{
}
diff --git a/indra/newview/lldrawpoolsky.h b/indra/newview/lldrawpoolsky.h
index f35b114730..8595d73aee 100644
--- a/indra/newview/lldrawpoolsky.h
+++ b/indra/newview/lldrawpoolsky.h
@@ -36,14 +36,12 @@
#include "lldrawpool.h"
class LLSkyTex;
-class LLHeavenBody;
class LLGLSLShader;
class LLDrawPoolSky : public LLFacePool
{
private:
LLSkyTex *mSkyTex;
- LLHeavenBody *mHB[2]; // Sun and Moon
LLGLSLShader *mShader;
public:
@@ -69,8 +67,6 @@ public:
/*virtual*/ void renderForSelect();
/*virtual*/ void endRenderPass(S32 pass);
void setSkyTex(LLSkyTex* const st) { mSkyTex = st; }
- void setSun(LLHeavenBody* sun_flag) { mHB[0] = sun_flag; }
- void setMoon(LLHeavenBody* moon) { mHB[1] = moon; }
void renderSkyCubeFace(U8 side);
void renderHeavenlyBody(U8 hb, LLFace* face);
diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp
index 2c644b0fd5..9dc22cddcd 100644
--- a/indra/newview/lldrawpoolterrain.cpp
+++ b/indra/newview/lldrawpoolterrain.cpp
@@ -49,7 +49,7 @@
#include "llviewerparceloverlay.h"
#include "llvosurfacepatch.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h" // To get alpha gradients
+#include "llviewertexturelist.h" // To get alpha gradients
#include "llworld.h"
#include "pipeline.h"
#include "llviewershadermgr.h"
@@ -61,31 +61,37 @@ int DebugDetailMap = 0;
S32 LLDrawPoolTerrain::sDetailMode = 1;
F32 LLDrawPoolTerrain::sDetailScale = DETAIL_SCALE;
static LLGLSLShader* sShader = NULL;
+static LLFastTimer::DeclareTimer FTM_SHADOW_TERRAIN("Terrain Shadow");
-LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerImage *texturep) :
+
+LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) :
LLFacePool(POOL_TERRAIN),
mTexturep(texturep)
{
// Hack!
sDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainScale");
sDetailMode = gSavedSettings.getS32("RenderTerrainDetail");
- mAlphaRampImagep = gImageList.getImageFromFile("alpha_gradient.tga",
- TRUE, TRUE, GL_ALPHA8, GL_ALPHA,
+ mAlphaRampImagep = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient.tga",
+ TRUE, LLViewerTexture::BOOST_UI,
+ LLViewerTexture::FETCHED_TEXTURE,
+ GL_ALPHA8, GL_ALPHA,
LLUUID("e97cf410-8e61-7005-ec06-629eba4cd1fb"));
- gGL.getTexUnit(0)->bind(mAlphaRampImagep.get());
+ //gGL.getTexUnit(0)->bind(mAlphaRampImagep.get());
mAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
- m2DAlphaRampImagep = gImageList.getImageFromFile("alpha_gradient_2d.j2c",
- TRUE, TRUE, GL_ALPHA8, GL_ALPHA,
+ m2DAlphaRampImagep = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient_2d.j2c",
+ TRUE, LLViewerTexture::BOOST_UI,
+ LLViewerTexture::FETCHED_TEXTURE,
+ GL_ALPHA8, GL_ALPHA,
LLUUID("38b86f85-2575-52a9-a531-23108d8da837"));
- gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get());
+ //gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get());
m2DAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
- mTexturep->setBoostLevel(LLViewerImage::BOOST_TERRAIN);
+ mTexturep->setBoostLevel(LLViewerTexture::BOOST_TERRAIN);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ //gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
LLDrawPoolTerrain::~LLDrawPoolTerrain()
@@ -127,7 +133,7 @@ void LLDrawPoolTerrain::prerender()
void LLDrawPoolTerrain::beginRenderPass( S32 pass )
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_TERRAIN);
+ LLFastTimer t(FTM_RENDER_TERRAIN);
LLFacePool::beginRenderPass(pass);
sShader = LLPipeline::sUnderWaterRender ?
@@ -142,7 +148,7 @@ void LLDrawPoolTerrain::beginRenderPass( S32 pass )
void LLDrawPoolTerrain::endRenderPass( S32 pass )
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_TERRAIN);
+ LLFastTimer t(FTM_RENDER_TERRAIN);
LLFacePool::endRenderPass(pass);
if (mVertexShaderLevel > 1 && sShader->mShaderLevel > 0) {
@@ -158,7 +164,7 @@ S32 LLDrawPoolTerrain::getDetailMode()
void LLDrawPoolTerrain::render(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_TERRAIN);
+ LLFastTimer t(FTM_RENDER_TERRAIN);
if (mDrawFace.empty())
{
@@ -170,7 +176,7 @@ void LLDrawPoolTerrain::render(S32 pass)
LLVLComposition *compp = regionp->getComposition();
for (S32 i = 0; i < 4; i++)
{
- compp->mDetailTextures[i]->setBoostLevel(LLViewerImage::BOOST_TERRAIN);
+ compp->mDetailTextures[i]->setBoostLevel(LLViewerTexture::BOOST_TERRAIN);
compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area
}
@@ -231,7 +237,7 @@ void LLDrawPoolTerrain::render(S32 pass)
void LLDrawPoolTerrain::beginDeferredPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_TERRAIN);
+ LLFastTimer t(FTM_RENDER_TERRAIN);
LLFacePool::beginRenderPass(pass);
sShader = &gDeferredTerrainProgram;
@@ -241,14 +247,14 @@ void LLDrawPoolTerrain::beginDeferredPass(S32 pass)
void LLDrawPoolTerrain::endDeferredPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_TERRAIN);
+ LLFastTimer t(FTM_RENDER_TERRAIN);
LLFacePool::endRenderPass(pass);
sShader->unbind();
}
void LLDrawPoolTerrain::renderDeferred(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_TERRAIN);
+ LLFastTimer t(FTM_RENDER_TERRAIN);
if (mDrawFace.empty())
{
return;
@@ -258,7 +264,7 @@ void LLDrawPoolTerrain::renderDeferred(S32 pass)
void LLDrawPoolTerrain::beginShadowPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_SHADOW_TERRAIN);
+ LLFastTimer t(FTM_SHADOW_TERRAIN);
LLFacePool::beginRenderPass(pass);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gDeferredShadowProgram.bind();
@@ -266,14 +272,14 @@ void LLDrawPoolTerrain::beginShadowPass(S32 pass)
void LLDrawPoolTerrain::endShadowPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_SHADOW_TERRAIN);
+ LLFastTimer t(FTM_SHADOW_TERRAIN);
LLFacePool::endRenderPass(pass);
gDeferredShadowProgram.unbind();
}
void LLDrawPoolTerrain::renderShadow(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_SHADOW_TERRAIN);
+ LLFastTimer t(FTM_SHADOW_TERRAIN);
if (mDrawFace.empty())
{
return;
@@ -289,10 +295,10 @@ void LLDrawPoolTerrain::renderFullShader()
// Hack! Get the region that this draw pool is rendering from!
LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
LLVLComposition *compp = regionp->getComposition();
- LLViewerImage *detail_texture0p = compp->mDetailTextures[0];
- LLViewerImage *detail_texture1p = compp->mDetailTextures[1];
- LLViewerImage *detail_texture2p = compp->mDetailTextures[2];
- LLViewerImage *detail_texture3p = compp->mDetailTextures[3];
+ LLViewerTexture *detail_texture0p = compp->mDetailTextures[0];
+ LLViewerTexture *detail_texture1p = compp->mDetailTextures[1];
+ LLViewerTexture *detail_texture2p = compp->mDetailTextures[2];
+ LLViewerTexture *detail_texture3p = compp->mDetailTextures[3];
LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal();
F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale;
@@ -363,7 +369,7 @@ void LLDrawPoolTerrain::renderFullShader()
// Alpha Ramp
//
S32 alpha_ramp = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_ALPHARAMP);
- gGL.getTexUnit(alpha_ramp)->bind(m2DAlphaRampImagep.get());
+ gGL.getTexUnit(alpha_ramp)->bind(m2DAlphaRampImagep);
// GL_BLEND disabled by default
drawLoop();
@@ -429,10 +435,10 @@ void LLDrawPoolTerrain::renderFull4TU()
// Hack! Get the region that this draw pool is rendering from!
LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
LLVLComposition *compp = regionp->getComposition();
- LLViewerImage *detail_texture0p = compp->mDetailTextures[0];
- LLViewerImage *detail_texture1p = compp->mDetailTextures[1];
- LLViewerImage *detail_texture2p = compp->mDetailTextures[2];
- LLViewerImage *detail_texture3p = compp->mDetailTextures[3];
+ LLViewerTexture *detail_texture0p = compp->mDetailTextures[0];
+ LLViewerTexture *detail_texture1p = compp->mDetailTextures[1];
+ LLViewerTexture *detail_texture2p = compp->mDetailTextures[2];
+ LLViewerTexture *detail_texture3p = compp->mDetailTextures[3];
LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal();
F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale;
@@ -527,7 +533,7 @@ void LLDrawPoolTerrain::renderFull4TU()
//
// Stage 1: Generate alpha ramp for detail2/detail3 transition
//
- gGL.getTexUnit(1)->bind(m2DAlphaRampImagep.get());
+ gGL.getTexUnit(1)->bind(m2DAlphaRampImagep);
gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(1)->activate();
@@ -559,7 +565,7 @@ void LLDrawPoolTerrain::renderFull4TU()
//
// Stage 3: Generate alpha ramp for detail1/detail2 transition
//
- gGL.getTexUnit(3)->bind(m2DAlphaRampImagep.get());
+ gGL.getTexUnit(3)->bind(m2DAlphaRampImagep);
gGL.getTexUnit(3)->enable(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(3)->activate();
@@ -630,10 +636,10 @@ void LLDrawPoolTerrain::renderFull2TU()
// Hack! Get the region that this draw pool is rendering from!
LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
LLVLComposition *compp = regionp->getComposition();
- LLViewerImage *detail_texture0p = compp->mDetailTextures[0];
- LLViewerImage *detail_texture1p = compp->mDetailTextures[1];
- LLViewerImage *detail_texture2p = compp->mDetailTextures[2];
- LLViewerImage *detail_texture3p = compp->mDetailTextures[3];
+ LLViewerTexture *detail_texture0p = compp->mDetailTextures[0];
+ LLViewerTexture *detail_texture1p = compp->mDetailTextures[1];
+ LLViewerTexture *detail_texture2p = compp->mDetailTextures[2];
+ LLViewerTexture *detail_texture3p = compp->mDetailTextures[3];
LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal();
F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale;
@@ -671,7 +677,7 @@ void LLDrawPoolTerrain::renderFull2TU()
//
// Stage 0: Generate alpha ramp for detail0/detail1 transition
//
- gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get());
+ gGL.getTexUnit(0)->bind(m2DAlphaRampImagep);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
@@ -709,7 +715,7 @@ void LLDrawPoolTerrain::renderFull2TU()
//
// Stage 0: Generate alpha ramp for detail1/detail2 transition
//
- gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get());
+ gGL.getTexUnit(0)->bind(m2DAlphaRampImagep);
// Set the texture matrix
glMatrixMode(GL_TEXTURE);
@@ -749,7 +755,7 @@ void LLDrawPoolTerrain::renderFull2TU()
// Stage 0: Generate alpha ramp for detail2/detail3 transition
//
gGL.getTexUnit(0)->activate();
- gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get());
+ gGL.getTexUnit(0)->bind(m2DAlphaRampImagep);
// Set the texture matrix
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
@@ -822,7 +828,7 @@ void LLDrawPoolTerrain::renderSimple()
gGL.getTexUnit(0)->activate();
gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
- gGL.getTexUnit(0)->bind(mTexturep.get());
+ gGL.getTexUnit(0)->bind(mTexturep);
LLVector3 origin_agent = mDrawFace[0]->getDrawable()->getVObj()->getRegion()->getOriginAgent();
F32 tscale = 1.f/256.f;
@@ -872,7 +878,7 @@ void LLDrawPoolTerrain::renderOwnership()
LLSurface *surfacep = surface_patchp->getSurface();
LLViewerRegion *regionp = surfacep->getRegion();
LLViewerParcelOverlay *overlayp = regionp->getParcelOverlay();
- LLImageGL *texturep = overlayp->getTexture();
+ LLViewerTexture *texturep = overlayp->getTexture();
gGL.getTexUnit(0)->bind(texturep);
@@ -920,9 +926,10 @@ void LLDrawPoolTerrain::renderForSelect()
}
}
-void LLDrawPoolTerrain::dirtyTextures(const std::set<LLViewerImage*>& textures)
+void LLDrawPoolTerrain::dirtyTextures(const std::set<LLViewerFetchedTexture*>& textures)
{
- if (textures.find(mTexturep) != textures.end())
+ LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(mTexturep) ;
+ if (tex && textures.find(tex) != textures.end())
{
for (std::vector<LLFace*>::iterator iter = mReferences.begin();
iter != mReferences.end(); iter++)
@@ -933,12 +940,12 @@ void LLDrawPoolTerrain::dirtyTextures(const std::set<LLViewerImage*>& textures)
}
}
-LLViewerImage *LLDrawPoolTerrain::getTexture()
+LLViewerTexture *LLDrawPoolTerrain::getTexture()
{
return mTexturep;
}
-LLViewerImage *LLDrawPoolTerrain::getDebugTexture()
+LLViewerTexture *LLDrawPoolTerrain::getDebugTexture()
{
return mTexturep;
}
diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h
index 19d09e2feb..2e2a36d533 100644
--- a/indra/newview/lldrawpoolterrain.h
+++ b/indra/newview/lldrawpoolterrain.h
@@ -37,7 +37,7 @@
class LLDrawPoolTerrain : public LLFacePool
{
- LLPointer<LLViewerImage> mTexturep;
+ LLPointer<LLViewerTexture> mTexturep;
public:
enum
{
@@ -53,7 +53,7 @@ public:
virtual U32 getVertexDataMask();
static S32 getDetailMode();
- LLDrawPoolTerrain(LLViewerImage *texturep);
+ LLDrawPoolTerrain(LLViewerTexture *texturep);
virtual ~LLDrawPoolTerrain();
/*virtual*/ LLDrawPool *instancePool();
@@ -73,14 +73,14 @@ public:
/*virtual*/ void beginRenderPass( S32 pass );
/*virtual*/ void endRenderPass( S32 pass );
/*virtual*/ void renderForSelect();
- /*virtual*/ void dirtyTextures(const std::set<LLViewerImage*>& textures);
- /*virtual*/ LLViewerImage *getTexture();
- /*virtual*/ LLViewerImage *getDebugTexture();
+ /*virtual*/ void dirtyTextures(const std::set<LLViewerFetchedTexture*>& textures);
+ /*virtual*/ LLViewerTexture *getTexture();
+ /*virtual*/ LLViewerTexture *getDebugTexture();
/*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display
- LLPointer<LLViewerImage> mAlphaRampImagep;
- LLPointer<LLViewerImage> m2DAlphaRampImagep;
- LLPointer<LLViewerImage> mAlphaNoiseImagep;
+ LLPointer<LLViewerTexture> mAlphaRampImagep;
+ LLPointer<LLViewerTexture> m2DAlphaRampImagep;
+ LLPointer<LLViewerTexture> mAlphaNoiseImagep;
static S32 sDetailMode;
static F32 sDetailScale; // meters per texture
diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp
index 2f2b07232a..5521fb05a8 100644
--- a/indra/newview/lldrawpooltree.cpp
+++ b/indra/newview/lldrawpooltree.cpp
@@ -37,7 +37,6 @@
#include "lldrawable.h"
#include "llface.h"
#include "llsky.h"
-#include "llviewerwindow.h"
#include "llvotree.h"
#include "pipeline.h"
#include "llviewercamera.h"
@@ -47,12 +46,12 @@
S32 LLDrawPoolTree::sDiffTex = 0;
static LLGLSLShader* shader = NULL;
+static LLFastTimer::DeclareTimer FTM_SHADOW_TREE("Tree Shadow");
-LLDrawPoolTree::LLDrawPoolTree(LLViewerImage *texturep) :
+LLDrawPoolTree::LLDrawPoolTree(LLViewerTexture *texturep) :
LLFacePool(POOL_TREE),
mTexturep(texturep)
{
- gGL.getTexUnit(0)->bind(mTexturep.get());
mTexturep->setAddressMode(LLTexUnit::TAM_WRAP);
}
@@ -68,7 +67,7 @@ void LLDrawPoolTree::prerender()
void LLDrawPoolTree::beginRenderPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_TREES);
+ LLFastTimer t(FTM_RENDER_TREES);
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
if (LLPipeline::sUnderWaterRender)
@@ -92,7 +91,7 @@ void LLDrawPoolTree::beginRenderPass(S32 pass)
void LLDrawPoolTree::render(S32 pass)
{
- LLFastTimer t(LLPipeline::sShadowRender ? LLFastTimer::FTM_SHADOW_TREE : LLFastTimer::FTM_RENDER_TREES);
+ LLFastTimer t(LLPipeline::sShadowRender ? FTM_SHADOW_TREE : FTM_RENDER_TREES);
if (mDrawFace.empty())
{
@@ -123,7 +122,7 @@ void LLDrawPoolTree::render(S32 pass)
void LLDrawPoolTree::endRenderPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_TREES);
+ LLFastTimer t(FTM_RENDER_TREES);
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
if (gPipeline.canUseWindLightShadersOnObjects())
@@ -137,8 +136,8 @@ void LLDrawPoolTree::endRenderPass(S32 pass)
//============================================
void LLDrawPoolTree::beginDeferredPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_TREES);
- gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
+ LLFastTimer t(FTM_RENDER_TREES);
+ gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f);
shader = &gDeferredTreeProgram;
shader->bind();
@@ -151,7 +150,7 @@ void LLDrawPoolTree::renderDeferred(S32 pass)
void LLDrawPoolTree::endDeferredPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_TREES);
+ LLFastTimer t(FTM_RENDER_TREES);
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
shader->unbind();
@@ -162,8 +161,11 @@ void LLDrawPoolTree::endDeferredPass(S32 pass)
//============================================
void LLDrawPoolTree::beginShadowPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_SHADOW_TREE);
+ LLFastTimer t(FTM_SHADOW_TREE);
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
+ glPolygonOffset(gSavedSettings.getF32("RenderDeferredTreeShadowOffset"),
+ gSavedSettings.getF32("RenderDeferredTreeShadowBias"));
+
gDeferredShadowProgram.bind();
}
@@ -174,9 +176,13 @@ void LLDrawPoolTree::renderShadow(S32 pass)
void LLDrawPoolTree::endShadowPass(S32 pass)
{
- LLFastTimer t(LLFastTimer::FTM_SHADOW_TREE);
+ LLFastTimer t(FTM_SHADOW_TREE);
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
- gDeferredShadowProgram.unbind();
+
+ glPolygonOffset(gSavedSettings.getF32("RenderDeferredSpotShadowOffset"),
+ gSavedSettings.getF32("RenderDeferredSpotShadowBias"));
+
+ //gDeferredShadowProgram.unbind();
}
@@ -247,7 +253,7 @@ void LLDrawPoolTree::renderTree(BOOL selecting)
LLGLState normalize(GL_NORMALIZE, TRUE);
// Bind the texture for this tree.
- gGL.getTexUnit(sDiffTex)->bind(mTexturep.get());
+ gGL.getTexUnit(sDiffTex)->bind(mTexturep.get(), TRUE);
U32 indices_drawn = 0;
@@ -377,12 +383,12 @@ BOOL LLDrawPoolTree::verify() const
return TRUE;
}
-LLViewerImage *LLDrawPoolTree::getTexture()
+LLViewerTexture *LLDrawPoolTree::getTexture()
{
return mTexturep;
}
-LLViewerImage *LLDrawPoolTree::getDebugTexture()
+LLViewerTexture *LLDrawPoolTree::getDebugTexture()
{
return mTexturep;
}
diff --git a/indra/newview/lldrawpooltree.h b/indra/newview/lldrawpooltree.h
index 80c4fdfffe..bc7711d4e8 100644
--- a/indra/newview/lldrawpooltree.h
+++ b/indra/newview/lldrawpooltree.h
@@ -37,7 +37,7 @@
class LLDrawPoolTree : public LLFacePool
{
- LLPointer<LLViewerImage> mTexturep;
+ LLPointer<LLViewerTexture> mTexturep;
public:
enum
{
@@ -48,7 +48,7 @@ public:
virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
- LLDrawPoolTree(LLViewerImage *texturep);
+ LLDrawPoolTree(LLViewerTexture *texturep);
/*virtual*/ LLDrawPool *instancePool();
@@ -70,8 +70,8 @@ public:
/*virtual*/ S32 getNumPasses() { return 1; }
/*virtual*/ void renderForSelect();
/*virtual*/ BOOL verify() const;
- /*virtual*/ LLViewerImage *getTexture();
- /*virtual*/ LLViewerImage *getDebugTexture();
+ /*virtual*/ LLViewerTexture *getTexture();
+ /*virtual*/ LLViewerTexture *getDebugTexture();
/*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display
static S32 sDiffTex;
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index ce3425dd9e..107de934df 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -45,8 +45,7 @@
#include "lldrawable.h"
#include "llface.h"
#include "llsky.h"
-#include "llviewercamera.h" // to get OGL_TO_CFR_ROTATION
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewerregion.h"
#include "llvosky.h"
#include "llvowater.h"
@@ -70,17 +69,17 @@ LLVector3 LLDrawPoolWater::sLightDir;
LLDrawPoolWater::LLDrawPoolWater() :
LLFacePool(POOL_WATER)
{
- mHBTex[0] = gImageList.getImage(gSunTextureID, TRUE, TRUE);
- gGL.getTexUnit(0)->bind(mHBTex[0].get());
+ mHBTex[0] = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLViewerTexture::BOOST_UI);
+ gGL.getTexUnit(0)->bind(mHBTex[0]) ;
mHBTex[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
- mHBTex[1] = gImageList.getImage(gMoonTextureID, TRUE, TRUE);
- gGL.getTexUnit(0)->bind(mHBTex[1].get());
+ mHBTex[1] = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLViewerTexture::BOOST_UI);
+ gGL.getTexUnit(0)->bind(mHBTex[1]);
mHBTex[1]->setAddressMode(LLTexUnit::TAM_CLAMP);
- mWaterImagep = gImageList.getImage(WATER_TEST);
+ mWaterImagep = LLViewerTextureManager::getFetchedTexture(WATER_TEST);
mWaterImagep->setNoDelete() ;
- mWaterNormp = gImageList.getImage(DEFAULT_WATER_NORMAL);
+ mWaterNormp = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL);
mWaterNormp->setNoDelete() ;
restoreGL();
@@ -137,9 +136,22 @@ void LLDrawPoolWater::endPostDeferredPass(S32 pass)
deferred_render = FALSE;
}
+//===============================
+//DEFERRED IMPLEMENTATION
+//===============================
+void LLDrawPoolWater::renderDeferred(S32 pass)
+{
+ LLFastTimer t(FTM_RENDER_WATER);
+ deferred_render = TRUE;
+ shade();
+ deferred_render = FALSE;
+}
+
+//=========================================
+
void LLDrawPoolWater::render(S32 pass)
{
- LLFastTimer ftm(LLFastTimer::FTM_RENDER_WATER);
+ LLFastTimer ftm(FTM_RENDER_WATER);
if (mDrawFace.empty() || LLDrawable::getCurrentFrame() <= 1)
{
return;
@@ -185,7 +197,7 @@ void LLDrawPoolWater::render(S32 pass)
mWaterImagep->addTextureStats(1024.f*1024.f);
gGL.getTexUnit(1)->activate();
gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE);
- gGL.getTexUnit(1)->bind(mWaterImagep.get());
+ gGL.getTexUnit(1)->bind(mWaterImagep) ;
LLVector3 camera_up = LLViewerCamera::getInstance()->getUpAxis();
F32 up_dot = camera_up * LLVector3::z_axis;
@@ -330,7 +342,7 @@ void LLDrawPoolWater::renderReflection(LLFace* face)
LLGLSNoFog noFog;
- gGL.getTexUnit(0)->bind(mHBTex[dr].get());
+ gGL.getTexUnit(0)->bind(mHBTex[dr]);
LLOverrideFaceColor override(this, face->getFaceColor().mV);
face->renderIndexed();
@@ -338,7 +350,10 @@ void LLDrawPoolWater::renderReflection(LLFace* face)
void LLDrawPoolWater::shade()
{
- gGL.setColorMask(true, true);
+ if (!deferred_render)
+ {
+ gGL.setColorMask(true, true);
+ }
LLVOSky *voskyp = gSky.mVOSkyp;
@@ -354,7 +369,7 @@ void LLDrawPoolWater::shade()
LLVector3 light_dir;
LLColor3 light_color;
- if (gSky.getSunDirection().mV[2] > NIGHTTIME_ELEVATION_COS)
+ if (gSky.getSunDirection().mV[2] > LLSky::NIGHTTIME_ELEVATION_COS)
{
light_dir = gSky.getSunDirection();
light_dir.normVec();
@@ -401,6 +416,15 @@ void LLDrawPoolWater::shade()
shader = &gWaterProgram;
}
+ if (deferred_render)
+ {
+ gPipeline.bindDeferredShader(*shader);
+ }
+ else
+ {
+ shader->bind();
+ }
+
sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f;
S32 reftex = shader->enableTexture(LLViewerShaderMgr::WATER_REFTEX);
@@ -420,11 +444,11 @@ void LLDrawPoolWater::shade()
// change mWaterNormp if needed
if (mWaterNormp->getID() != param_mgr->getNormalMapID())
{
- mWaterNormp = gImageList.getImage(param_mgr->getNormalMapID());
+ mWaterNormp = LLViewerTextureManager::getFetchedTexture(param_mgr->getNormalMapID());
}
mWaterNormp->addTextureStats(1024.f*1024.f);
- gGL.getTexUnit(bumpTex)->bind(mWaterNormp.get());
+ gGL.getTexUnit(bumpTex)->bind(mWaterNormp) ;
if (gSavedSettings.getBOOL("RenderWaterMipNormal"))
{
mWaterNormp->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
@@ -436,15 +460,6 @@ void LLDrawPoolWater::shade()
S32 screentex = shader->enableTexture(LLViewerShaderMgr::WATER_SCREENTEX);
- if (deferred_render)
- {
- gPipeline.bindDeferredShader(*shader);
- }
- else
- {
- shader->bind();
- }
-
if (screentex > -1)
{
shader->uniform4fv(LLViewerShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV);
@@ -548,8 +563,15 @@ void LLDrawPoolWater::shade()
{ //smash background faces to far clip plane
if (water->getIsEdgePatch())
{
- LLGLClampToFarClip far_clip(glh_get_current_projection());
- face->renderIndexed();
+ if (deferred_render)
+ {
+ face->renderIndexed();
+ }
+ else
+ {
+ LLGLClampToFarClip far_clip(glh_get_current_projection());
+ face->renderIndexed();
+ }
}
else
{
@@ -578,7 +600,10 @@ void LLDrawPoolWater::shade()
gGL.getTexUnit(0)->activate();
gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
- gGL.setColorMask(true, false);
+ if (!deferred_render)
+ {
+ gGL.setColorMask(true, false);
+ }
}
@@ -588,20 +613,9 @@ void LLDrawPoolWater::renderForSelect()
return;
}
-
-void LLDrawPoolWater::renderFaceSelected(LLFace *facep,
- LLImageGL *image,
- const LLColor4 &color,
- const S32 index_offset, const S32 index_count)
-{
- // Can't select water
- return;
-}
-
-
-LLViewerImage *LLDrawPoolWater::getDebugTexture()
+LLViewerTexture *LLDrawPoolWater::getDebugTexture()
{
- return LLViewerImage::sSmokeImagep;
+ return LLViewerFetchedTexture::sSmokeImagep;
}
LLColor3 LLDrawPoolWater::getDebugColor() const
diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h
index 6351041140..68a8172dd0 100644
--- a/indra/newview/lldrawpoolwater.h
+++ b/indra/newview/lldrawpoolwater.h
@@ -43,9 +43,9 @@ class LLWaterSurface;
class LLDrawPoolWater: public LLFacePool
{
protected:
- LLPointer<LLViewerImage> mHBTex[2];
- LLPointer<LLViewerImage> mWaterImagep;
- LLPointer<LLViewerImage> mWaterNormp;
+ LLPointer<LLViewerTexture> mHBTex[2];
+ LLPointer<LLViewerTexture> mWaterImagep;
+ LLPointer<LLViewerTexture> mWaterNormp;
const LLWaterSurface *mWaterSurface;
public:
@@ -71,19 +71,19 @@ public:
/*virtual*/ LLDrawPool *instancePool();
static void restoreGL();
- /*virtual*/ S32 getNumPostDeferredPasses() { return getNumPasses(); }
+ /*virtual*/ S32 getNumPostDeferredPasses() { return 0; } //getNumPasses(); }
/*virtual*/ void beginPostDeferredPass(S32 pass);
/*virtual*/ void endPostDeferredPass(S32 pass);
/*virtual*/ void renderPostDeferred(S32 pass) { render(pass); }
+ /*virtual*/ S32 getNumDeferredPasses() { return 1; }
+ /*virtual*/ void renderDeferred(S32 pass = 0);
/*virtual*/ S32 getNumPasses();
/*virtual*/ void render(S32 pass = 0);
- /*virtual*/ void renderFaceSelected(LLFace *facep, LLImageGL *image, const LLColor4 &color,
- const S32 index_offset = 0, const S32 index_count = 0);
/*virtual*/ void prerender();
/*virtual*/ void renderForSelect();
- /*virtual*/ LLViewerImage *getDebugTexture();
+ /*virtual*/ LLViewerTexture *getDebugTexture();
/*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display
void renderReflection(LLFace* face);
diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp
index 6ff65c7ed0..c7cd77cb65 100644
--- a/indra/newview/lldrawpoolwlsky.cpp
+++ b/indra/newview/lldrawpoolwlsky.cpp
@@ -42,12 +42,11 @@
#include "llwlparammanager.h"
#include "llsky.h"
#include "llvowlsky.h"
-#include "llagent.h"
#include "llviewerregion.h"
#include "llface.h"
#include "llrender.h"
-LLPointer<LLImageGL> LLDrawPoolWLSky::sCloudNoiseTexture = NULL;
+LLPointer<LLViewerTexture> LLDrawPoolWLSky::sCloudNoiseTexture = NULL;
LLPointer<LLImageRaw> LLDrawPoolWLSky::sCloudNoiseRawImage = NULL;
@@ -71,7 +70,7 @@ LLDrawPoolWLSky::LLDrawPoolWLSky(void) :
cloudNoiseFile->decode(sCloudNoiseRawImage, 0.0f);
- LLImageGL::create(sCloudNoiseTexture, sCloudNoiseRawImage, TRUE);
+ sCloudNoiseTexture = LLViewerTextureManager::getLocalTexture(sCloudNoiseRawImage.get(), TRUE);
LLWLParamManager::instance()->propagateParameters();
}
@@ -83,7 +82,7 @@ LLDrawPoolWLSky::~LLDrawPoolWLSky()
sCloudNoiseRawImage = NULL;
}
-LLViewerImage *LLDrawPoolWLSky::getDebugTexture()
+LLViewerTexture *LLDrawPoolWLSky::getDebugTexture()
{
return NULL;
}
@@ -160,15 +159,10 @@ void LLDrawPoolWLSky::renderStars(void) const
// *NOTE: have to have bound the cloud noise texture already since register
// combiners blending below requires something to be bound
// and we might as well only bind once.
- //gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
gPipeline.disableLights();
-
- if (!LLPipeline::sReflectionRender)
- {
- glPointSize(2.f);
- }
-
+
// *NOTE: we divide by two here and GL_ALPHA_SCALE by two below to avoid
// clamping and allow the star_alpha param to brighten the stars.
bool error;
@@ -176,16 +170,20 @@ void LLDrawPoolWLSky::renderStars(void) const
star_alpha.mV[3] = LLWLParamManager::instance()->mCurParams.getFloat("star_brightness", error) / 2.f;
llassert_always(!error);
+ gGL.getTexUnit(0)->bind(gSky.mVOSkyp->getBloomTex());
+
+ gGL.pushMatrix();
+ glRotatef(gFrameTimeSeconds*0.01f, 0.f, 0.f, 1.f);
// gl_FragColor.rgb = gl_Color.rgb;
// gl_FragColor.a = gl_Color.a * star_alpha.a;
- gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR);
- gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT_X2, LLTexUnit::TBS_PREV_ALPHA, LLTexUnit::TBS_CONST_ALPHA);
+ gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_VERT_COLOR);
+ gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT_X2, LLTexUnit::TBS_CONST_ALPHA, LLTexUnit::TBS_TEX_ALPHA);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, star_alpha.mV);
gSky.mVOWLSkyp->drawStars();
- glPointSize(1.f);
-
+ gGL.popMatrix();
+
// and disable the combiner states
gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
}
@@ -224,7 +222,7 @@ void LLDrawPoolWLSky::renderHeavenlyBodies()
LLFace * face = gSky.mVOSkyp->mFace[LLVOSky::FACE_SUN];
if (gSky.mVOSkyp->getSun().getDraw() && face->getGeomCount())
{
- LLImageGL * tex = face->getTexture();
+ LLViewerTexture * tex = face->getTexture();
gGL.getTexUnit(0)->bind(tex);
LLColor4 color(gSky.mVOSkyp->getSun().getInterpColor());
LLFacePool::LLOverrideFaceColor color_override(this, color);
@@ -239,8 +237,7 @@ void LLDrawPoolWLSky::renderHeavenlyBodies()
// *NOTE: even though we already bound this texture above for the
// stars register combiners, we bind again here for defensive reasons,
// since LLImageGL::bind detects that it's a noop, and optimizes it out.
- LLImageGL * tex = face->getTexture();
- gGL.getTexUnit(0)->bind(tex);
+ gGL.getTexUnit(0)->bind(face->getTexture());
LLColor4 color(gSky.mVOSkyp->getMoon().getInterpColor());
F32 a = gSky.mVOSkyp->getMoon().getDirection().mV[2];
if (a > 0.f)
@@ -261,7 +258,7 @@ void LLDrawPoolWLSky::render(S32 pass)
{
return;
}
- LLFastTimer ftm(LLFastTimer::FTM_RENDER_WL_SKY);
+ LLFastTimer ftm(FTM_RENDER_WL_SKY);
const F32 camHeightLocal = LLWLParamManager::instance()->getDomeOffset() * LLWLParamManager::instance()->getDomeRadius();
@@ -280,9 +277,8 @@ void LLDrawPoolWLSky::render(S32 pass)
// *NOTE: have to bind a texture here since register combiners blending in
// renderStars() requires something to be bound and we might as well only
- // bind the moon's texture once.
- LLImageGL * tex = gSky.mVOSkyp->mFace[LLVOSky::FACE_MOON]->getTexture();
- gGL.getTexUnit(0)->bind(tex);
+ // bind the moon's texture once.
+ gGL.getTexUnit(0)->bind(gSky.mVOSkyp->mFace[LLVOSky::FACE_MOON]->getTexture());
renderHeavenlyBodies();
@@ -306,7 +302,7 @@ LLDrawPoolWLSky *LLDrawPoolWLSky::instancePool()
return new LLDrawPoolWLSky();
}
-LLViewerImage* LLDrawPoolWLSky::getTexture()
+LLViewerTexture* LLDrawPoolWLSky::getTexture()
{
return NULL;
}
@@ -324,5 +320,5 @@ void LLDrawPoolWLSky::cleanupGL()
//static
void LLDrawPoolWLSky::restoreGL()
{
- LLImageGL::create(sCloudNoiseTexture, sCloudNoiseRawImage, TRUE);
+ sCloudNoiseTexture = LLViewerTextureManager::getLocalTexture(sCloudNoiseRawImage.get(), TRUE);
}
diff --git a/indra/newview/lldrawpoolwlsky.h b/indra/newview/lldrawpoolwlsky.h
index c7a1f3fe27..9059f6382f 100644
--- a/indra/newview/lldrawpoolwlsky.h
+++ b/indra/newview/lldrawpoolwlsky.h
@@ -43,7 +43,7 @@ public:
static const U32 SKY_VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX |
LLVertexBuffer::MAP_TEXCOORD0;
static const U32 STAR_VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX |
- LLVertexBuffer::MAP_COLOR;
+ LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD0;
LLDrawPoolWLSky(void);
/*virtual*/ ~LLDrawPoolWLSky();
@@ -55,7 +55,7 @@ public:
/*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); }
/*virtual*/ void renderPostDeferred(S32 pass) { render(pass); }
- /*virtual*/ LLViewerImage *getDebugTexture();
+ /*virtual*/ LLViewerTexture *getDebugTexture();
/*virtual*/ void beginRenderPass( S32 pass );
/*virtual*/ void endRenderPass( S32 pass );
/*virtual*/ S32 getNumPasses() { return 1; }
@@ -65,11 +65,11 @@ public:
/*virtual*/ BOOL verify() const { return TRUE; } // Verify that all data in the draw pool is correct!
/*virtual*/ S32 getVertexShaderLevel() const { return mVertexShaderLevel; }
- //static LLDrawPool* createPool(const U32 type, LLViewerImage *tex0 = NULL);
+ //static LLDrawPool* createPool(const U32 type, LLViewerTexture *tex0 = NULL);
// Create an empty new instance of the pool.
/*virtual*/ LLDrawPoolWLSky *instancePool(); ///< covariant override
- /*virtual*/ LLViewerImage* getTexture();
+ /*virtual*/ LLViewerTexture* getTexture();
/*virtual*/ BOOL isFacePool() { return FALSE; }
/*virtual*/ void resetDrawOrders();
@@ -83,7 +83,7 @@ private:
void renderHeavenlyBodies();
private:
- static LLPointer<LLImageGL> sCloudNoiseTexture;
+ static LLPointer<LLViewerTexture> sCloudNoiseTexture;
static LLPointer<LLImageRaw> sCloudNoiseRawImage;
};
diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp
index 55b3ab796e..3961afe9af 100644
--- a/indra/newview/lldriverparam.cpp
+++ b/indra/newview/lldriverparam.cpp
@@ -36,6 +36,9 @@
#include "llfasttimer.h"
#include "llvoavatar.h"
+#include "llvoavatarself.h"
+#include "llagent.h"
+#include "llwearable.h"
//-----------------------------------------------------------------------------
// LLDriverParamInfo
@@ -100,12 +103,70 @@ BOOL LLDriverParamInfo::parseXml(LLXmlTreeNode* node)
return TRUE;
}
+//virtual
+void LLDriverParamInfo::toStream(std::ostream &out)
+{
+ LLViewerVisualParamInfo::toStream(out);
+ out << "driver" << "\t";
+ out << mDrivenInfoList.size() << "\t";
+ for (entry_info_list_t::iterator iter = mDrivenInfoList.begin(); iter != mDrivenInfoList.end(); iter++)
+ {
+ LLDrivenEntryInfo driven = *iter;
+ out << driven.mDrivenID << "\t";
+ }
+
+ out << std::endl;
+
+ LLVOAvatarSelf *avatar = gAgent.getAvatarObject();
+ if(avatar)
+ {
+ for (entry_info_list_t::iterator iter = mDrivenInfoList.begin(); iter != mDrivenInfoList.end(); iter++)
+ {
+ LLDrivenEntryInfo driven = *iter;
+ LLViewerVisualParam *param = (LLViewerVisualParam*)avatar->getVisualParam(driven.mDrivenID);
+ if (param)
+ {
+ param->getInfo()->toStream(out);
+ if (param->getWearableType() != mWearableType)
+ {
+ if(param->getCrossWearable())
+ {
+ out << "cross-wearable" << "\t";
+ }
+ else
+ {
+ out << "ERROR!" << "\t";
+ }
+ }
+ else
+ {
+ out << "valid" << "\t";
+ }
+ }
+ else
+ {
+ llwarns << "could not get parameter " << driven.mDrivenID << " from avatar " << avatar << " for driver parameter " << getID() << llendl;
+ }
+ out << std::endl;
+ }
+ }
+}
+
//-----------------------------------------------------------------------------
// LLDriverParam
//-----------------------------------------------------------------------------
-LLDriverParam::LLDriverParam(LLVOAvatar *avatarp)
- : mCurrentDistortionParam( NULL ), mAvatarp(avatarp)
+LLDriverParam::LLDriverParam(LLVOAvatar *avatarp) :
+ mCurrentDistortionParam( NULL ),
+ mAvatarp(avatarp),
+ mWearablep(NULL)
+{
+}
+
+LLDriverParam::LLDriverParam(LLWearable *wearablep) :
+ mCurrentDistortionParam( NULL ),
+ mAvatarp(NULL),
+ mWearablep(wearablep)
{
}
@@ -122,27 +183,48 @@ BOOL LLDriverParam::setInfo(LLDriverParamInfo *info)
mID = info->mID;
setWeight(getDefaultWeight(), FALSE );
-
- LLDriverParamInfo::entry_info_list_t::iterator iter;
- mDriven.reserve(getInfo()->mDrivenInfoList.size());
- for (iter = getInfo()->mDrivenInfoList.begin(); iter != getInfo()->mDrivenInfoList.end(); iter++)
+
+ return TRUE;
+}
+
+void LLDriverParam::setWearable(LLWearable *wearablep)
+{
+ if (wearablep)
{
- LLDrivenEntryInfo *driven_info = &(*iter);
- S32 driven_id = driven_info->mDrivenID;
- LLViewerVisualParam* param = (LLViewerVisualParam*)mAvatarp->getVisualParam( driven_id );
- if (param)
+ mWearablep = wearablep;
+ mAvatarp = NULL;
+ }
+}
+
+void LLDriverParam::setAvatar(LLVOAvatar *avatarp)
+{
+ if (avatarp)
+ {
+ mWearablep = NULL;
+ mAvatarp = avatarp;
+ }
+}
+
+/*virtual*/ LLViewerVisualParam* LLDriverParam::cloneParam(LLWearable* wearable) const
+{
+ LLDriverParam *new_param;
+ if (wearable)
+ {
+ new_param = new LLDriverParam(wearable);
+ }
+ else
+ {
+ if (mWearablep)
{
- mDriven.push_back(LLDrivenEntry( param, driven_info ));
+ new_param = new LLDriverParam(mWearablep);
}
else
{
- llerrs << "<driven> Unable to resolve driven parameter: " << driven_id << llendl;
- mInfo = NULL;
- return FALSE;
+ new_param = new LLDriverParam(mAvatarp);
}
}
-
- return TRUE;
+ *new_param = *this;
+ return new_param;
}
#if 0 // obsolete
@@ -160,7 +242,7 @@ BOOL LLDriverParam::parseData(LLXmlTreeNode* node)
}
#endif
-void LLDriverParam::setWeight(F32 weight, BOOL set_by_user)
+void LLDriverParam::setWeight(F32 weight, BOOL upload_bake)
{
F32 min_weight = getMinWeight();
F32 max_weight = getMaxWeight();
@@ -218,8 +300,8 @@ void LLDriverParam::setWeight(F32 weight, BOOL set_by_user)
{
driven_weight = driven_min;
}
-
- driven->mParam->setWeight( driven_weight, set_by_user );
+
+ setDrivenWeight(driven,driven_weight,upload_bake);
continue;
}
else
@@ -243,13 +325,13 @@ void LLDriverParam::setWeight(F32 weight, BOOL set_by_user)
driven_weight = driven_min;
}
- driven->mParam->setWeight( driven_weight, set_by_user );
+ setDrivenWeight(driven,driven_weight,upload_bake);
continue;
}
}
driven_weight = getDrivenWeight(driven, mCurWeight);
- driven->mParam->setWeight( driven_weight, set_by_user );
+ setDrivenWeight(driven,driven_weight,upload_bake);
}
}
@@ -373,9 +455,9 @@ const LLVector3* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_
//-----------------------------------------------------------------------------
// setAnimationTarget()
//-----------------------------------------------------------------------------
-void LLDriverParam::setAnimationTarget( F32 target_value, BOOL set_by_user )
+void LLDriverParam::setAnimationTarget( F32 target_value, BOOL upload_bake )
{
- LLVisualParam::setAnimationTarget(target_value, set_by_user);
+ LLVisualParam::setAnimationTarget(target_value, upload_bake);
for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
{
@@ -384,16 +466,16 @@ void LLDriverParam::setAnimationTarget( F32 target_value, BOOL set_by_user )
// this isn't normally necessary, as driver params handle interpolation of their driven params
// but texture params need to know to assume their final value at beginning of interpolation
- driven->mParam->setAnimationTarget(driven_weight, set_by_user);
+ driven->mParam->setAnimationTarget(driven_weight, upload_bake);
}
}
//-----------------------------------------------------------------------------
// stopAnimating()
//-----------------------------------------------------------------------------
-void LLDriverParam::stopAnimating(BOOL set_by_user)
+void LLDriverParam::stopAnimating(BOOL upload_bake)
{
- LLVisualParam::stopAnimating(set_by_user);
+ LLVisualParam::stopAnimating(upload_bake);
for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
{
@@ -402,6 +484,50 @@ void LLDriverParam::stopAnimating(BOOL set_by_user)
}
}
+/*virtual*/
+BOOL LLDriverParam::linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params)
+{
+ BOOL success = TRUE;
+ LLDriverParamInfo::entry_info_list_t::iterator iter;
+ for (iter = getInfo()->mDrivenInfoList.begin(); iter != getInfo()->mDrivenInfoList.end(); ++iter)
+ {
+ LLDrivenEntryInfo *driven_info = &(*iter);
+ S32 driven_id = driven_info->mDrivenID;
+
+ // check for already existing links. Do not overwrite.
+ BOOL found = FALSE;
+ for (entry_list_t::iterator driven_iter = mDriven.begin(); driven_iter != mDriven.end() && !found; ++driven_iter)
+ {
+ if (driven_iter->mInfo->mDrivenID == driven_id)
+ {
+ found = TRUE;
+ }
+ }
+
+ if (!found)
+ {
+ LLViewerVisualParam* param = (LLViewerVisualParam*)mapper(driven_id);
+ bool push = param && (!only_cross_params || param->getCrossWearable());
+ if (push)
+ {
+ mDriven.push_back(LLDrivenEntry( param, driven_info ));
+ }
+ else
+ {
+ success = FALSE;
+ }
+ }
+ }
+
+ return success;
+}
+
+void LLDriverParam::resetDrivenParams()
+{
+ mDriven.clear();
+ mDriven.reserve(getInfo()->mDrivenInfoList.size());
+}
+
//-----------------------------------------------------------------------------
// getDrivenWeight()
//-----------------------------------------------------------------------------
@@ -458,3 +584,19 @@ F32 LLDriverParam::getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight
return driven_weight;
}
+
+void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake)
+{
+ LLVOAvatarSelf *avatar_self = gAgent.getAvatarObject();
+ if(mWearablep &&
+ driven->mParam->getCrossWearable() &&
+ mWearablep->isOnTop())
+ {
+ // call setWeight through LLVOAvatarSelf so other wearables can be updated with the correct values
+ avatar_self->setVisualParamWeight( (LLVisualParam*)driven->mParam, driven_weight, upload_bake );
+ }
+ else
+ {
+ driven->mParam->setWeight( driven_weight, upload_bake );
+ }
+}
diff --git a/indra/newview/lldriverparam.h b/indra/newview/lldriverparam.h
index 7bc0c15448..4e2daf5ba7 100644
--- a/indra/newview/lldriverparam.h
+++ b/indra/newview/lldriverparam.h
@@ -36,6 +36,7 @@
#include "llviewervisualparam.h"
class LLVOAvatar;
+class LLWearable;
//-----------------------------------------------------------------------------
@@ -69,6 +70,8 @@ public:
/*virtual*/ BOOL parseXml(LLXmlTreeNode* node);
+ /*virtual*/ void toStream(std::ostream &out);
+
protected:
typedef std::deque<LLDrivenEntryInfo> entry_info_list_t;
entry_info_list_t mDrivenInfoList;
@@ -80,6 +83,7 @@ class LLDriverParam : public LLViewerVisualParam
{
public:
LLDriverParam(LLVOAvatar *avatarp);
+ LLDriverParam(LLWearable *wearablep);
~LLDriverParam();
// Special: These functions are overridden by child classes
@@ -87,12 +91,19 @@ public:
// This sets mInfo and calls initialization functions
BOOL setInfo(LLDriverParamInfo *info);
+ void setWearable(LLWearable *wearablep);
+ void setAvatar(LLVOAvatar *avatarp);
+
+ /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const;
+
// LLVisualParam Virtual functions
///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
/*virtual*/ void apply( ESex sex ) {} // apply is called separately for each driven param.
- /*virtual*/ void setWeight(F32 weight, BOOL set_by_user);
- /*virtual*/ void setAnimationTarget( F32 target_value, BOOL set_by_user );
- /*virtual*/ void stopAnimating(BOOL set_by_user);
+ /*virtual*/ void setWeight(F32 weight, BOOL upload_bake);
+ /*virtual*/ void setAnimationTarget( F32 target_value, BOOL upload_bake );
+ /*virtual*/ void stopAnimating(BOOL upload_bake);
+ /*virtual*/ BOOL linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params);
+ /*virtual*/ void resetDrivenParams();
// LLViewerVisualParam Virtual functions
/*virtual*/ F32 getTotalDistortion();
@@ -103,6 +114,7 @@ public:
/*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh);
protected:
F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight);
+ void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake);
LLVector3 mDefaultVec; // temp holder
@@ -111,6 +123,7 @@ protected:
LLViewerVisualParam* mCurrentDistortionParam;
// Backlink only; don't make this an LLPointer.
LLVOAvatar* mAvatarp;
+ LLWearable* mWearablep;
};
#endif // LL_LLDRIVERPARAM_H
diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp
index 62fcf60e7f..c7c79401a0 100644
--- a/indra/newview/lldynamictexture.cpp
+++ b/indra/newview/lldynamictexture.cpp
@@ -1,6 +1,6 @@
/**
* @file lldynamictexture.cpp
- * @brief Implementation of LLDynamicTexture class
+ * @brief Implementation of LLViewerDynamicTexture class
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
@@ -33,28 +33,29 @@
#include "llviewerprecompiledheaders.h"
#include "lldynamictexture.h"
+
+// Linden library includes
#include "llglheaders.h"
+#include "llwindow.h" // getPosition()
+
+// Viewer includes
#include "llviewerwindow.h"
#include "llviewercamera.h"
#include "llviewercontrol.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
#include "llvertexbuffer.h"
#include "llviewerdisplay.h"
#include "llrender.h"
// static
-LLDynamicTexture::instance_list_t LLDynamicTexture::sInstances[ LLDynamicTexture::ORDER_COUNT ];
-S32 LLDynamicTexture::sNumRenders = 0;
+LLViewerDynamicTexture::instance_list_t LLViewerDynamicTexture::sInstances[ LLViewerDynamicTexture::ORDER_COUNT ];
+S32 LLViewerDynamicTexture::sNumRenders = 0;
//-----------------------------------------------------------------------------
-// LLDynamicTexture()
+// LLViewerDynamicTexture()
//-----------------------------------------------------------------------------
-LLDynamicTexture::LLDynamicTexture(S32 width, S32 height, S32 components, EOrder order, BOOL clamp) :
- mWidth(width),
- mHeight(height),
- mComponents(components),
- mTexture(NULL),
- mLastBindTime(0),
+LLViewerDynamicTexture::LLViewerDynamicTexture(S32 width, S32 height, S32 components, EOrder order, BOOL clamp) :
+ LLViewerTexture(width, height, components, FALSE),
mClamp(clamp)
{
llassert((1 <= components) && (components <= 4));
@@ -62,64 +63,56 @@ LLDynamicTexture::LLDynamicTexture(S32 width, S32 height, S32 components, EOrder
generateGLTexture();
llassert( 0 <= order && order < ORDER_COUNT );
- LLDynamicTexture::sInstances[ order ].insert(this);
+ LLViewerDynamicTexture::sInstances[ order ].insert(this);
}
//-----------------------------------------------------------------------------
-// LLDynamicTexture()
+// LLViewerDynamicTexture()
//-----------------------------------------------------------------------------
-LLDynamicTexture::~LLDynamicTexture()
+LLViewerDynamicTexture::~LLViewerDynamicTexture()
{
- releaseGLTexture();
for( S32 order = 0; order < ORDER_COUNT; order++ )
{
- LLDynamicTexture::sInstances[order].erase(this); // will fail in all but one case.
+ LLViewerDynamicTexture::sInstances[order].erase(this); // will fail in all but one case.
}
}
-//-----------------------------------------------------------------------------
-// releaseGLTexture()
-//-----------------------------------------------------------------------------
-void LLDynamicTexture::releaseGLTexture()
+//virtual
+S8 LLViewerDynamicTexture::getType() const
{
- if (mTexture.notNull())
- {
-// llinfos << "RELEASING " << (mWidth*mHeight*mComponents)/1024 << "K" << llendl;
- mTexture = NULL;
- }
+ return LLViewerTexture::DYNAMIC_TEXTURE ;
}
//-----------------------------------------------------------------------------
// generateGLTexture()
//-----------------------------------------------------------------------------
-void LLDynamicTexture::generateGLTexture()
+void LLViewerDynamicTexture::generateGLTexture()
{
+ LLViewerTexture::generateGLTexture() ;
generateGLTexture(-1, 0, 0, FALSE);
}
-void LLDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes)
+void LLViewerDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes)
{
if (mComponents < 1 || mComponents > 4)
{
llerrs << "Bad number of components in dynamic texture: " << mComponents << llendl;
}
- releaseGLTexture();
- LLPointer<LLImageRaw> raw_image = new LLImageRaw(mWidth, mHeight, mComponents);
- mTexture = new LLViewerImage(mWidth, mHeight, mComponents, FALSE);
+
+ LLPointer<LLImageRaw> raw_image = new LLImageRaw(mFullWidth, mFullHeight, mComponents);
if (internal_format >= 0)
{
- mTexture->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes);
+ setExplicitFormat(internal_format, primary_format, type_format, swap_bytes);
}
-// llinfos << "ALLOCATING " << (mWidth*mHeight*mComponents)/1024 << "K" << llendl;
- mTexture->createGLTexture(0, raw_image);
- mTexture->setAddressMode((mClamp) ? LLTexUnit::TAM_CLAMP : LLTexUnit::TAM_WRAP);
- mTexture->setGLTextureCreated(false);
+ createGLTexture(0, raw_image, 0, TRUE, LLViewerTexture::DYNAMIC_TEX);
+ setAddressMode((mClamp) ? LLTexUnit::TAM_CLAMP : LLTexUnit::TAM_WRAP);
+ mGLTexturep->setGLTextureCreated(false);
}
//-----------------------------------------------------------------------------
// render()
//-----------------------------------------------------------------------------
-BOOL LLDynamicTexture::render()
+BOOL LLViewerDynamicTexture::render()
{
return FALSE;
}
@@ -127,13 +120,13 @@ BOOL LLDynamicTexture::render()
//-----------------------------------------------------------------------------
// preRender()
//-----------------------------------------------------------------------------
-void LLDynamicTexture::preRender(BOOL clear_depth)
+void LLViewerDynamicTexture::preRender(BOOL clear_depth)
{
{
// force rendering to on-screen portion of frame buffer
LLCoordScreen window_pos;
gViewerWindow->getWindow()->getPosition( &window_pos );
- mOrigin.set(0, gViewerWindow->getWindowDisplayHeight() - mHeight); // top left corner
+ mOrigin.set(0, gViewerWindow->getWindowHeightRaw() - mFullHeight); // top left corner
if (window_pos.mX < 0)
{
@@ -148,13 +141,14 @@ void LLDynamicTexture::preRender(BOOL clear_depth)
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
// Set up camera
- mCamera.setOrigin(*LLViewerCamera::getInstance());
- mCamera.setAxes(*LLViewerCamera::getInstance());
- mCamera.setAspect(LLViewerCamera::getInstance()->getAspect());
- mCamera.setView(LLViewerCamera::getInstance()->getView());
- mCamera.setNear(LLViewerCamera::getInstance()->getNear());
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
+ mCamera.setOrigin(*camera);
+ mCamera.setAxes(*camera);
+ mCamera.setAspect(camera->getAspect());
+ mCamera.setView(camera->getView());
+ mCamera.setNear(camera->getNear());
- glViewport(mOrigin.mX, mOrigin.mY, mWidth, mHeight);
+ glViewport(mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight);
if (clear_depth)
{
glClear(GL_DEPTH_BUFFER_BIT);
@@ -164,24 +158,29 @@ void LLDynamicTexture::preRender(BOOL clear_depth)
//-----------------------------------------------------------------------------
// postRender()
//-----------------------------------------------------------------------------
-void LLDynamicTexture::postRender(BOOL success)
+void LLViewerDynamicTexture::postRender(BOOL success)
{
{
if (success)
{
- success = mTexture->setSubImageFromFrameBuffer(0, 0, mOrigin.mX, mOrigin.mY, mWidth, mHeight);
+ if(mGLTexturep.isNull())
+ {
+ generateGLTexture() ;
+ }
+ success = mGLTexturep->setSubImageFromFrameBuffer(0, 0, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight);
}
}
// restore viewport
- gViewerWindow->setupViewport();
+ gViewerWindow->setup2DViewport();
// restore camera
- LLViewerCamera::getInstance()->setOrigin(mCamera);
- LLViewerCamera::getInstance()->setAxes(mCamera);
- LLViewerCamera::getInstance()->setAspect(mCamera.getAspect());
- LLViewerCamera::getInstance()->setView(mCamera.getView());
- LLViewerCamera::getInstance()->setNear(mCamera.getNear());
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
+ camera->setOrigin(mCamera);
+ camera->setAxes(mCamera);
+ camera->setAspect(mCamera.getAspect());
+ camera->setView(mCamera.getView());
+ camera->setNear(mCamera.getNear());
}
//-----------------------------------------------------------------------------
@@ -189,7 +188,7 @@ void LLDynamicTexture::postRender(BOOL success)
// updateDynamicTextures()
// Calls update on each dynamic texture. Calls each group in order: "first," then "middle," then "last."
//-----------------------------------------------------------------------------
-BOOL LLDynamicTexture::updateAllInstances()
+BOOL LLViewerDynamicTexture::updateAllInstances()
{
sNumRenders = 0;
if (gGLManager.mIsDisabled)
@@ -201,10 +200,10 @@ BOOL LLDynamicTexture::updateAllInstances()
BOOL ret = FALSE ;
for( S32 order = 0; order < ORDER_COUNT; order++ )
{
- for (instance_list_t::iterator iter = LLDynamicTexture::sInstances[order].begin();
- iter != LLDynamicTexture::sInstances[order].end(); ++iter)
+ for (instance_list_t::iterator iter = LLViewerDynamicTexture::sInstances[order].begin();
+ iter != LLViewerDynamicTexture::sInstances[order].end(); ++iter)
{
- LLDynamicTexture *dynamicTexture = *iter;
+ LLViewerDynamicTexture *dynamicTexture = *iter;
if (dynamicTexture->needsRender())
{
glClear(GL_DEPTH_BUFFER_BIT);
@@ -231,30 +230,18 @@ BOOL LLDynamicTexture::updateAllInstances()
return ret;
}
-//virtual
-void LLDynamicTexture::restoreGLTexture()
-{
- generateGLTexture() ;
-}
-
-//virtual
-void LLDynamicTexture::destroyGLTexture()
-{
- releaseGLTexture() ;
-}
-
//-----------------------------------------------------------------------------
// static
// destroyGL()
//-----------------------------------------------------------------------------
-void LLDynamicTexture::destroyGL()
+void LLViewerDynamicTexture::destroyGL()
{
for( S32 order = 0; order < ORDER_COUNT; order++ )
{
- for (instance_list_t::iterator iter = LLDynamicTexture::sInstances[order].begin();
- iter != LLDynamicTexture::sInstances[order].end(); ++iter)
+ for (instance_list_t::iterator iter = LLViewerDynamicTexture::sInstances[order].begin();
+ iter != LLViewerDynamicTexture::sInstances[order].end(); ++iter)
{
- LLDynamicTexture *dynamicTexture = *iter;
+ LLViewerDynamicTexture *dynamicTexture = *iter;
dynamicTexture->destroyGLTexture() ;
}
}
@@ -264,7 +251,7 @@ void LLDynamicTexture::destroyGL()
// static
// restoreGL()
//-----------------------------------------------------------------------------
-void LLDynamicTexture::restoreGL()
+void LLViewerDynamicTexture::restoreGL()
{
if (gGLManager.mIsDisabled)
{
@@ -273,10 +260,10 @@ void LLDynamicTexture::restoreGL()
for( S32 order = 0; order < ORDER_COUNT; order++ )
{
- for (instance_list_t::iterator iter = LLDynamicTexture::sInstances[order].begin();
- iter != LLDynamicTexture::sInstances[order].end(); ++iter)
+ for (instance_list_t::iterator iter = LLViewerDynamicTexture::sInstances[order].begin();
+ iter != LLViewerDynamicTexture::sInstances[order].end(); ++iter)
{
- LLDynamicTexture *dynamicTexture = *iter;
+ LLViewerDynamicTexture *dynamicTexture = *iter;
dynamicTexture->restoreGLTexture() ;
}
}
diff --git a/indra/newview/lldynamictexture.h b/indra/newview/lldynamictexture.h
index 5a20eaef9b..2a944eaada 100644
--- a/indra/newview/lldynamictexture.h
+++ b/indra/newview/lldynamictexture.h
@@ -1,6 +1,6 @@
/**
* @file lldynamictexture.h
- * @brief Implementation of LLDynamicTexture class
+ * @brief Implementation of LLViewerDynamicTexture class
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
@@ -33,61 +33,55 @@
#ifndef LL_LLDYNAMICTEXTURE_H
#define LL_LLDYNAMICTEXTURE_H
+#include "llcamera.h"
#include "llgl.h"
#include "llcoord.h"
-#include "llimagegl.h"
+#include "llviewertexture.h"
+#include "llcamera.h"
-class LLDynamicTexture
+class LLViewerDynamicTexture : public LLViewerTexture
{
+protected:
+ /*virtual*/ ~LLViewerDynamicTexture();
+
public:
enum EOrder { ORDER_FIRST = 0, ORDER_MIDDLE = 1, ORDER_LAST = 2, ORDER_RESET = 3, ORDER_COUNT = 4 };
- LLDynamicTexture(S32 width,
+ LLViewerDynamicTexture(S32 width,
S32 height,
S32 components, // = 4,
EOrder order, // = ORDER_MIDDLE,
BOOL clamp);
- virtual ~LLDynamicTexture();
+
+ /*virtual*/ S8 getType() const ;
S32 getOriginX() { return mOrigin.mX; }
S32 getOriginY() { return mOrigin.mY; }
- S32 getWidth() { return mWidth; }
- S32 getHeight() { return mHeight; }
- S32 getComponents() { return mComponents; }
- S32 getSize() { return mWidth * mHeight * mComponents; }
+
+ S32 getSize() { return mFullWidth * mFullHeight * mComponents; }
virtual BOOL needsRender() { return TRUE; }
virtual void preRender(BOOL clear_depth = TRUE);
virtual BOOL render();
virtual void postRender(BOOL success);
- virtual void restoreGLTexture() ;
- virtual void destroyGLTexture() ;
-
- LLImageGL* getTexture(void) const { return mTexture; }
+ virtual void restoreGLTexture() {}
+ virtual void destroyGLTexture() {}
static BOOL updateAllInstances();
-
- static void destroyGL();
- static void restoreGL();
-
+ static void destroyGL() ;
+ static void restoreGL() ;
protected:
- void releaseGLTexture();
void generateGLTexture();
void generateGLTexture(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes = FALSE);
protected:
- S32 mWidth;
- S32 mHeight;
- S32 mComponents;
- LLPointer<LLImageGL> mTexture;
- F32 mLastBindTime;
BOOL mClamp;
LLCoordGL mOrigin;
-
LLCamera mCamera;
- typedef std::set<LLDynamicTexture*> instance_list_t;
- static instance_list_t sInstances[ LLDynamicTexture::ORDER_COUNT ];
+
+ typedef std::set<LLViewerDynamicTexture*> instance_list_t;
+ static instance_list_t sInstances[ LLViewerDynamicTexture::ORDER_COUNT ];
static S32 sNumRenders;
};
diff --git a/indra/newview/llemote.cpp b/indra/newview/llemote.cpp
index bacf3daf5a..c83846215e 100644
--- a/indra/newview/llemote.cpp
+++ b/indra/newview/llemote.cpp
@@ -39,7 +39,6 @@
#include "llcharacter.h"
#include "m3math.h"
#include "llvoavatar.h"
-#include "llagent.h"
//-----------------------------------------------------------------------------
// Constants
diff --git a/indra/newview/lleventinfo.cpp b/indra/newview/lleventinfo.cpp
index d4175b6c84..aabd7ed997 100644
--- a/indra/newview/lleventinfo.cpp
+++ b/indra/newview/lleventinfo.cpp
@@ -33,7 +33,6 @@
#include "llviewerprecompiledheaders.h"
#include "lleventinfo.h"
-#include "llappviewer.h" // for gPacificDaylightTime
#include "lluuid.h"
#include "message.h"
@@ -87,35 +86,19 @@ void LLEventInfo::unpack(LLMessageSystem *msg)
}
// static
-void LLEventInfo::loadCategories(LLUserAuth::options_t event_options)
+void LLEventInfo::loadCategories(const LLSD& options)
{
- LLUserAuth::options_t::iterator resp_it;
- for (resp_it = event_options.begin();
- resp_it != event_options.end();
- ++resp_it)
+ for(LLSD::array_const_iterator resp_it = options.beginArray(),
+ end = options.endArray(); resp_it != end; ++resp_it)
{
- const LLUserAuth::response_t& response = *resp_it;
-
- LLUserAuth::response_t::const_iterator option_it;
-
- S32 cat_id = 0;
- option_it = response.find("category_id");
- if (option_it != response.end())
+ LLSD name = (*resp_it)["category_name"];
+ if(name.isDefined())
{
- cat_id = atoi(option_it->second.c_str());
+ LLSD id = (*resp_it)["category_id"];
+ if(id.isDefined())
+ {
+ LLEventInfo::sCategories[id.asInteger()] = name.asString();
+ }
}
- else
- {
- continue;
- }
-
- // Add the category id/name pair
- option_it = response.find("category_name");
- if (option_it != response.end())
- {
- LLEventInfo::sCategories[cat_id] = option_it->second;
- }
-
}
-
}
diff --git a/indra/newview/lleventinfo.h b/indra/newview/lleventinfo.h
index 880517a9f4..493c659983 100644
--- a/indra/newview/lleventinfo.h
+++ b/indra/newview/lleventinfo.h
@@ -37,7 +37,6 @@
#include "v3dmath.h"
#include "lluuid.h"
-#include "lluserauth.h"
class LLMessageSystem;
@@ -48,7 +47,7 @@ public:
void unpack(LLMessageSystem *msg);
- static void loadCategories(LLUserAuth::options_t event_options);
+ static void loadCategories(const LLSD& options);
public:
std::string mName;
diff --git a/indra/newview/lleventnotifier.cpp b/indra/newview/lleventnotifier.cpp
index e7403c2903..edfb9dc864 100644
--- a/indra/newview/lleventnotifier.cpp
+++ b/indra/newview/lleventnotifier.cpp
@@ -34,11 +34,11 @@
#include "lleventnotifier.h"
+#include "llnotificationsutil.h"
#include "message.h"
-#include "llnotify.h"
#include "lleventinfo.h"
-#include "llfloaterdirectory.h"
+#include "llfloaterreg.h"
#include "llfloaterworldmap.h"
#include "llagent.h"
@@ -81,7 +81,7 @@ void LLEventNotifier::update()
LLSD args;
args["NAME"] = np->getEventName();
args["DATE"] = np->getEventDateStr();
- LLNotifications::instance().add("EventNotification", args, LLSD(),
+ LLNotificationsUtil::add("EventNotification", args, LLSD(),
boost::bind(&LLEventNotification::handleResponse, np, _1, _2));
mEventNotifications.erase(iter++);
}
@@ -94,18 +94,16 @@ void LLEventNotifier::update()
}
}
-void LLEventNotifier::load(const LLUserAuth::options_t& event_options)
+void LLEventNotifier::load(const LLSD& event_options)
{
- LLUserAuth::options_t::const_iterator resp_it;
- for (resp_it = event_options.begin();
- resp_it != event_options.end();
- ++resp_it)
+ for(LLSD::array_const_iterator resp_it = event_options.beginArray(),
+ end = event_options.endArray(); resp_it != end; ++resp_it)
{
- const LLUserAuth::response_t& response = *resp_it;
+ LLSD response = *resp_it;
LLEventNotification *new_enp = new LLEventNotification();
- if (!new_enp->load(response))
+ if(!new_enp->load(response))
{
delete new_enp;
continue;
@@ -187,16 +185,18 @@ LLEventNotification::~LLEventNotification()
bool LLEventNotification::handleResponse(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
switch (option)
{
case 0:
- gAgent.teleportViaLocation(getEventPosGlobal());
- gFloaterWorldMap->trackLocation(getEventPosGlobal());
- break;
+ {
+ gAgent.teleportViaLocation(getEventPosGlobal());
+ LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance();
+ if(floater_world_map) floater_world_map->trackLocation(getEventPosGlobal());
+ break;
+ }
case 1:
- gDisplayEventHack = TRUE;
- LLFloaterDirectory::showEvents(getEventID());
+ LLFloaterReg::showInstance("search", LLSD().with("category", "events").with("id", S32(getEventID())));
break;
case 2:
break;
@@ -206,49 +206,46 @@ bool LLEventNotification::handleResponse(const LLSD& notification, const LLSD& r
return false;
}
-BOOL LLEventNotification::load(const LLUserAuth::response_t &response)
+BOOL LLEventNotification::load(const LLSD& response)
{
-
- LLUserAuth::response_t::const_iterator option_it;
BOOL event_ok = TRUE;
- option_it = response.find("event_id");
- if (option_it != response.end())
+ LLSD option = response.get("event_id");
+ if (option.isDefined())
{
- mEventID = atoi(option_it->second.c_str());
+ mEventID = option.asInteger();
}
else
{
event_ok = FALSE;
}
- option_it = response.find("event_name");
- if (option_it != response.end())
+ option = response.get("event_name");
+ if (option.isDefined())
{
- llinfos << "Event: " << option_it->second << llendl;
- mEventName = option_it->second;
+ llinfos << "Event: " << option.asString() << llendl;
+ mEventName = option.asString();
}
else
{
event_ok = FALSE;
}
-
- option_it = response.find("event_date");
- if (option_it != response.end())
+ option = response.get("event_date");
+ if (option.isDefined())
{
- llinfos << "EventDate: " << option_it->second << llendl;
- mEventDateStr = option_it->second;
+ llinfos << "EventDate: " << option.asString() << llendl;
+ mEventDateStr = option.asString();
}
else
{
event_ok = FALSE;
}
- option_it = response.find("event_date_ut");
- if (option_it != response.end())
+ option = response.get("event_date_ut");
+ if (option.isDefined())
{
- llinfos << "EventDate: " << option_it->second << llendl;
- mEventDate = strtoul(option_it->second.c_str(), NULL, 10);
+ llinfos << "EventDate: " << option.asString() << llendl;
+ mEventDate = strtoul(option.asString().c_str(), NULL, 10);
}
else
{
@@ -260,44 +257,44 @@ BOOL LLEventNotification::load(const LLUserAuth::response_t &response)
S32 x_region = 0;
S32 y_region = 0;
- option_it = response.find("grid_x");
- if (option_it != response.end())
+ option = response.get("grid_x");
+ if (option.isDefined())
{
- llinfos << "GridX: " << option_it->second << llendl;
- grid_x= atoi(option_it->second.c_str());
+ llinfos << "GridX: " << option.asInteger() << llendl;
+ grid_x= option.asInteger();
}
else
{
event_ok = FALSE;
}
- option_it = response.find("grid_y");
- if (option_it != response.end())
+ option = response.get("grid_y");
+ if (option.isDefined())
{
- llinfos << "GridY: " << option_it->second << llendl;
- grid_y = atoi(option_it->second.c_str());
+ llinfos << "GridY: " << option.asInteger() << llendl;
+ grid_y = option.asInteger();
}
else
{
event_ok = FALSE;
}
- option_it = response.find("x_region");
- if (option_it != response.end())
+ option = response.get("x_region");
+ if (option.isDefined())
{
- llinfos << "RegionX: " << option_it->second << llendl;
- x_region = atoi(option_it->second.c_str());
+ llinfos << "RegionX: " << option.asInteger() << llendl;
+ x_region = option.asInteger();
}
else
{
event_ok = FALSE;
}
- option_it = response.find("y_region");
- if (option_it != response.end())
+ option = response.get("y_region");
+ if (option.isDefined())
{
- llinfos << "RegionY: " << option_it->second << llendl;
- y_region = atoi(option_it->second.c_str());
+ llinfos << "RegionY: " << option.asInteger() << llendl;
+ y_region = option.asInteger();
}
else
{
diff --git a/indra/newview/lleventnotifier.h b/indra/newview/lleventnotifier.h
index feb734948c..6fdde87646 100644
--- a/indra/newview/lleventnotifier.h
+++ b/indra/newview/lleventnotifier.h
@@ -34,7 +34,6 @@
#define LL_LLEVENTNOTIFIER_H
#include "llframetimer.h"
-#include "lluserauth.h"
#include "v3dmath.h"
class LLEventInfo;
@@ -49,7 +48,7 @@ public:
void update(); // Notify the user of the event if it's coming up
- void load(const LLUserAuth::options_t& event_options); // In the format that it comes in from LLUserAuth
+ void load(const LLSD& event_options); // In the format that it comes in from login
void add(LLEventInfo &event_info); // Add a new notification for an event
void remove(U32 event_id);
@@ -69,7 +68,7 @@ public:
LLEventNotification();
virtual ~LLEventNotification();
- BOOL load(const LLUserAuth::response_t &en); // In the format it comes in from LLUserAuth
+ BOOL load(const LLSD& en); // In the format it comes in from login
BOOL load(const LLEventInfo &event_info); // From existing event_info on the viewer.
//void setEventID(const U32 event_id);
//void setEventName(std::string &event_name);
diff --git a/indra/newview/lleventpoll.h b/indra/newview/lleventpoll.h
index 12e4b49d57..f2465a361e 100644
--- a/indra/newview/lleventpoll.h
+++ b/indra/newview/lleventpoll.h
@@ -35,6 +35,9 @@
#include "llhttpclient.h"
+class LLHost;
+
+
class LLEventPoll
///< implements the viewer side of server-to-viewer pushed events.
{
diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp
new file mode 100644
index 0000000000..9f6412c0ab
--- /dev/null
+++ b/indra/newview/llexpandabletextbox.cpp
@@ -0,0 +1,442 @@
+/**
+ * @file llexpandabletextbox.cpp
+ * @brief LLExpandableTextBox and related class implementations
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llexpandabletextbox.h"
+
+#include "llscrollcontainer.h"
+#include "llwindow.h"
+
+static LLDefaultChildRegistry::Register<LLExpandableTextBox> t1("expandable_text");
+
+class LLExpanderSegment : public LLTextSegment
+{
+public:
+ LLExpanderSegment(const LLStyleSP& style, S32 start, S32 end, const std::string& more_text, LLTextBase& editor )
+ : LLTextSegment(start, end),
+ mEditor(editor),
+ mStyle(style),
+ mExpanderLabel(more_text)
+ {}
+
+ /*virtual*/ bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const
+ {
+ // more label always spans width of text box
+ if (num_chars == 0)
+ {
+ width = 0;
+ height = 0;
+ }
+ else
+ {
+ width = mEditor.getDocumentView()->getRect().getWidth() - mEditor.getHPad();
+ height = llceil(mStyle->getFont()->getLineHeight());
+ }
+ return true;
+ }
+ /*virtual*/ S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const
+ {
+ return start_offset;
+ }
+ /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const
+ {
+ // require full line to ourselves
+ if (line_offset == 0)
+ {
+ // print all our text
+ return getEnd() - getStart();
+ }
+ else
+ {
+ // wait for next line
+ return 0;
+ }
+ }
+ /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
+ {
+ F32 right_x;
+ mStyle->getFont()->renderUTF8(mExpanderLabel, start,
+ draw_rect.mRight, draw_rect.mTop,
+ mStyle->getColor(),
+ LLFontGL::RIGHT, LLFontGL::TOP,
+ 0,
+ mStyle->getShadowType(),
+ end - start, draw_rect.getWidth(),
+ &right_x,
+ mEditor.getUseEllipses());
+ return right_x;
+ }
+ /*virtual*/ bool canEdit() const { return false; }
+ // eat handleMouseDown event so we get the mouseup event
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask) { return TRUE; }
+ /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask) { mEditor.onCommit(); return TRUE; }
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask)
+ {
+ LLUI::getWindow()->setCursor(UI_CURSOR_HAND);
+ return TRUE;
+ }
+private:
+ LLTextBase& mEditor;
+ LLStyleSP mStyle;
+ std::string mExpanderLabel;
+};
+
+LLExpandableTextBox::LLTextBoxEx::Params::Params()
+: more_label("more_label")
+{
+}
+
+LLExpandableTextBox::LLTextBoxEx::LLTextBoxEx(const Params& p)
+: LLTextBox(p),
+ mExpanderLabel(p.more_label),
+ mExpanderVisible(false)
+{
+ setIsChrome(TRUE);
+
+}
+
+void LLExpandableTextBox::LLTextBoxEx::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ hideExpandText();
+ LLTextBox::reshape(width, height, called_from_parent);
+
+ if (getTextPixelHeight() > getRect().getHeight())
+ {
+ showExpandText();
+ }
+}
+
+void LLExpandableTextBox::LLTextBoxEx::setText(const LLStringExplicit& text,const LLStyle::Params& input_params)
+{
+ // LLTextBox::setText will obliterate the expander segment, so make sure
+ // we generate it again by clearing mExpanderVisible
+ mExpanderVisible = false;
+ LLTextBox::setText(text, input_params);
+
+ // text contents have changed, segments are cleared out
+ // so hide the expander and determine if we need it
+ //mExpanderVisible = false;
+ if (getTextPixelHeight() > getRect().getHeight())
+ {
+ showExpandText();
+ }
+ else
+ {
+ hideExpandText();
+ }
+}
+
+
+void LLExpandableTextBox::LLTextBoxEx::showExpandText()
+{
+ if (!mExpanderVisible)
+ {
+ // make sure we're scrolled to top when collapsing
+ if (mScroller)
+ {
+ mScroller->goToTop();
+ }
+ // get fully visible lines
+ std::pair<S32, S32> visible_lines = getVisibleLines(true);
+ S32 last_line = visible_lines.second - 1;
+
+ LLStyle::Params expander_style = getDefaultStyle();
+ expander_style.font.name(LLFontGL::nameFromFont(expander_style.font));
+ expander_style.font.style = "UNDERLINE";
+ expander_style.color = LLUIColorTable::instance().getColor("HTMLLinkColor");
+ LLExpanderSegment* expanderp = new LLExpanderSegment(new LLStyle(expander_style), getLineStart(last_line), getLength() + 1, mExpanderLabel, *this);
+ insertSegment(expanderp);
+ mExpanderVisible = true;
+ }
+
+}
+
+//NOTE: obliterates existing styles (including hyperlinks)
+void LLExpandableTextBox::LLTextBoxEx::hideExpandText()
+{
+ if (mExpanderVisible)
+ {
+ // this will overwrite the expander segment and all text styling with a single style
+ LLNormalTextSegment* segmentp = new LLNormalTextSegment(
+ new LLStyle(getDefaultStyle()), 0, getLength() + 1, *this);
+ insertSegment(segmentp);
+
+ mExpanderVisible = false;
+ }
+}
+
+S32 LLExpandableTextBox::LLTextBoxEx::getVerticalTextDelta()
+{
+ S32 text_height = getTextPixelHeight();
+ S32 textbox_height = getRect().getHeight();
+
+ return text_height - textbox_height;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLExpandableTextBox::Params::Params()
+: textbox("textbox"),
+ scroll("scroll"),
+ max_height("max_height", 0),
+ bg_visible("bg_visible", false),
+ expanded_bg_visible("expanded_bg_visible", true),
+ bg_color("bg_color", LLColor4::black),
+ expanded_bg_color("expanded_bg_color", LLColor4::black)
+{
+}
+
+LLExpandableTextBox::LLExpandableTextBox(const Params& p)
+: LLUICtrl(p),
+ mMaxHeight(p.max_height),
+ mBGVisible(p.bg_visible),
+ mExpandedBGVisible(p.expanded_bg_visible),
+ mBGColor(p.bg_color),
+ mExpandedBGColor(p.expanded_bg_color),
+ mExpanded(false)
+{
+ LLRect rc = getLocalRect();
+
+ LLScrollContainer::Params scroll_params = p.scroll;
+ scroll_params.rect(rc);
+ mScroll = LLUICtrlFactory::create<LLScrollContainer>(scroll_params);
+ addChild(mScroll);
+
+ LLTextBoxEx::Params textbox_params = p.textbox;
+ textbox_params.rect(rc);
+ mTextBox = LLUICtrlFactory::create<LLTextBoxEx>(textbox_params);
+ mScroll->addChild(mTextBox);
+
+ updateTextBoxRect();
+
+ mTextBox->setCommitCallback(boost::bind(&LLExpandableTextBox::onExpandClicked, this));
+}
+
+void LLExpandableTextBox::draw()
+{
+ if(mBGVisible && !mExpanded)
+ {
+ gl_rect_2d(getLocalRect(), mBGColor.get(), TRUE);
+ }
+ if(mExpandedBGVisible && mExpanded)
+ {
+ gl_rect_2d(getLocalRect(), mExpandedBGColor.get(), TRUE);
+ }
+
+ collapseIfPosChanged();
+
+ LLUICtrl::draw();
+}
+
+void LLExpandableTextBox::collapseIfPosChanged()
+{
+ if(mExpanded)
+ {
+ LLView* parentp = getParent();
+ LLRect parent_rect = parentp->getRect();
+ parentp->localRectToOtherView(parent_rect, &parent_rect, getRootView());
+
+ if(parent_rect.mLeft != mParentRect.mLeft
+ || parent_rect.mTop != mParentRect.mTop)
+ {
+ collapseTextBox();
+ }
+ }
+}
+
+void LLExpandableTextBox::onExpandClicked()
+{
+ expandTextBox();
+}
+
+void LLExpandableTextBox::updateTextBoxRect()
+{
+ LLRect rc = getLocalRect();
+
+ rc.mLeft += mScroll->getBorderWidth();
+ rc.mRight -= mScroll->getBorderWidth();
+ rc.mTop -= mScroll->getBorderWidth();
+ rc.mBottom += mScroll->getBorderWidth();
+
+ mTextBox->reshape(rc.getWidth(), rc.getHeight());
+ mTextBox->setRect(rc);
+}
+
+S32 LLExpandableTextBox::recalculateTextDelta(S32 text_delta)
+{
+ LLRect expanded_rect = getLocalRect();
+ LLView* root_view = getRootView();
+ LLRect window_rect = root_view->getRect();
+
+ LLRect expanded_screen_rect;
+ localRectToOtherView(expanded_rect, &expanded_screen_rect, root_view);
+
+ // don't allow expanded text box bottom go off screen
+ if(expanded_screen_rect.mBottom - text_delta < window_rect.mBottom)
+ {
+ text_delta = expanded_screen_rect.mBottom - window_rect.mBottom;
+ }
+ // show scroll bar if max_height is valid
+ // and expanded size is greater that max_height
+ else if(mMaxHeight > 0 && expanded_rect.getHeight() + text_delta > mMaxHeight)
+ {
+ text_delta = mMaxHeight - expanded_rect.getHeight();
+ }
+
+ return text_delta;
+}
+
+void LLExpandableTextBox::expandTextBox()
+{
+ // hide "more" link, and show full text contents
+ mTextBox->hideExpandText();
+
+ // *HACK dz
+ // hideExpandText brakes text styles (replaces hyper-links with plain text), see ticket EXT-3290
+ // Set text again to make text box re-apply styles.
+ // *TODO Find proper solution to fix this issue.
+ // Maybe add removeSegment to LLTextBase
+ mTextBox->setTextBase(mText);
+
+ S32 text_delta = mTextBox->getVerticalTextDelta();
+ text_delta += mTextBox->getVPad() * 2;
+ text_delta += mScroll->getBorderWidth() * 2;
+ // no need to expand
+ if(text_delta <= 0)
+ {
+ return;
+ }
+
+ saveCollapsedState();
+
+ LLRect expanded_rect = getLocalRect();
+ LLRect expanded_screen_rect;
+
+ S32 updated_text_delta = recalculateTextDelta(text_delta);
+ // actual expand
+ expanded_rect.mBottom -= updated_text_delta;
+
+ LLRect text_box_rect = mTextBox->getRect();
+
+ // check if we need to show scrollbar
+ if(text_delta != updated_text_delta)
+ {
+ static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+
+ // disable horizontal scrollbar
+ text_box_rect.mRight -= scrollbar_size;
+
+ // text box size has changed - redo text wrap
+ // Should be handled automatically in reshape() below. JC
+ //mTextBox->setWrappedText(mText, text_box_rect.getWidth());
+
+ // recalculate text delta since text wrap changed text height
+ text_delta = mTextBox->getVerticalTextDelta() + mTextBox->getVPad() * 2;
+ }
+
+ // expand text
+ text_box_rect.mBottom -= text_delta;
+ mTextBox->reshape(text_box_rect.getWidth(), text_box_rect.getHeight());
+ mTextBox->setRect(text_box_rect);
+
+ // expand text box
+ localRectToOtherView(expanded_rect, &expanded_screen_rect, getParent());
+ reshape(expanded_screen_rect.getWidth(), expanded_screen_rect.getHeight(), FALSE);
+ setRect(expanded_screen_rect);
+
+ setFocus(TRUE);
+ // this lets us receive top_lost event(needed to collapse text box)
+ // it also draws text box above all other ui elements
+ gFocusMgr.setTopCtrl(this);
+
+ mExpanded = true;
+}
+
+void LLExpandableTextBox::collapseTextBox()
+{
+ if(!mExpanded)
+ {
+ return;
+ }
+
+ mExpanded = false;
+
+ reshape(mCollapsedRect.getWidth(), mCollapsedRect.getHeight(), FALSE);
+ setRect(mCollapsedRect);
+
+ updateTextBoxRect();
+
+ if(gFocusMgr.getTopCtrl() == this)
+ {
+ gFocusMgr.setTopCtrl(NULL);
+ }
+}
+
+void LLExpandableTextBox::onFocusLost()
+{
+ collapseTextBox();
+
+ LLUICtrl::onFocusLost();
+}
+
+void LLExpandableTextBox::onTopLost()
+{
+ collapseTextBox();
+
+ LLUICtrl::onTopLost();
+}
+
+void LLExpandableTextBox::setValue(const LLSD& value)
+{
+ collapseTextBox();
+ mText = value.asString();
+ mTextBox->setValue(value);
+}
+
+void LLExpandableTextBox::setText(const std::string& str)
+{
+ collapseTextBox();
+ mText = str;
+ mTextBox->setText(str);
+}
+
+void LLExpandableTextBox::saveCollapsedState()
+{
+ mCollapsedRect = getRect();
+
+ mParentRect = getParent()->getRect();
+ // convert parent rect to screen coordinates,
+ // this will allow to track parent's position change
+ getParent()->localRectToOtherView(mParentRect, &mParentRect, getRootView());
+}
diff --git a/indra/newview/llexpandabletextbox.h b/indra/newview/llexpandabletextbox.h
new file mode 100644
index 0000000000..2b4f9e527c
--- /dev/null
+++ b/indra/newview/llexpandabletextbox.h
@@ -0,0 +1,205 @@
+/**
+ * @file llexpandabletextbox.h
+ * @brief LLExpandableTextBox and related class definitions
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLEXPANDABLETEXTBOX_H
+#define LL_LLEXPANDABLETEXTBOX_H
+
+#include "lltextbox.h"
+#include "llscrollcontainer.h"
+
+/**
+ * LLExpandableTextBox is a text box control that will show "More" link at end of text
+ * if text doesn't fit into text box. After pressing "More" the text box will expand to show
+ * all text. If text is still too big, a scroll bar will appear inside expanded text box.
+ */
+class LLExpandableTextBox : public LLUICtrl
+{
+protected:
+
+ /**
+ * Extended text box. "More" link will appear at end of text if
+ * text is too long to fit into text box size.
+ */
+ class LLTextBoxEx : public LLTextBox
+ {
+ public:
+ struct Params : public LLInitParam::Block<Params, LLTextBox::Params>
+ {
+ Mandatory<std::string> more_label;
+ Params();
+ };
+
+ // adds or removes "More" link as needed
+ /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+ /*virtual*/ void setText(const LLStringExplicit& text, const LLStyle::Params& input_params = LLStyle::Params());
+ void setTextBase(const std::string& text) { LLTextBase::setText(text); }
+
+ /**
+ * Returns difference between text box height and text height.
+ * Value is positive if text height is greater than text box height.
+ */
+ virtual S32 getVerticalTextDelta();
+
+ /**
+ * Shows "More" link
+ */
+ void showExpandText();
+
+ /**
+ * Hides "More" link
+ */
+ void hideExpandText();
+
+ protected:
+
+ LLTextBoxEx(const Params& p);
+ friend class LLUICtrlFactory;
+
+ private:
+ std::string mExpanderLabel;
+
+ bool mExpanderVisible;
+ };
+
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<LLTextBoxEx::Params> textbox;
+
+ Optional<LLScrollContainer::Params> scroll;
+
+ Optional<S32> max_height;
+
+ Optional<bool> bg_visible,
+ expanded_bg_visible;
+
+ Optional<LLUIColor> bg_color,
+ expanded_bg_color;
+
+ Params();
+ };
+
+ /**
+ * Sets text
+ */
+ virtual void setText(const std::string& str);
+
+ /**
+ * Returns text
+ */
+ virtual std::string getText() const { return mText; }
+
+ /**
+ * Sets text
+ */
+ /*virtual*/ void setValue(const LLSD& value);
+
+ /**
+ * Returns text
+ */
+ /*virtual*/ LLSD getValue() const { return mText; }
+
+ /**
+ * Collapses text box on focus_lost event
+ */
+ /*virtual*/ void onFocusLost();
+
+ /**
+ * Collapses text box on top_lost event
+ */
+ /*virtual*/ void onTopLost();
+
+ /**
+ * Draws text box, collapses text box if its expanded and its parent's position changed
+ */
+ /*virtual*/ void draw();
+
+protected:
+
+ LLExpandableTextBox(const Params& p);
+ friend class LLUICtrlFactory;
+
+ /**
+ * Expands text box.
+ * A scroll bar will appear if expanded height is greater than max_height
+ */
+ virtual void expandTextBox();
+
+ /**
+ * Collapses text box.
+ */
+ virtual void collapseTextBox();
+
+ /**
+ * Collapses text box if it is expanded and its parent's position changed
+ */
+ virtual void collapseIfPosChanged();
+
+ /**
+ * Updates text box rect to avoid horizontal scroll bar
+ */
+ virtual void updateTextBoxRect();
+
+ /**
+ * User clicked on "More" link - expand text box
+ */
+ virtual void onExpandClicked();
+
+ /**
+ * Saves collapsed text box's states(rect, parent rect...)
+ */
+ virtual void saveCollapsedState();
+
+ /**
+ * Recalculate text delta considering min_height and window rect.
+ */
+ virtual S32 recalculateTextDelta(S32 text_delta);
+
+protected:
+
+ std::string mText;
+ LLTextBoxEx* mTextBox;
+ LLScrollContainer* mScroll;
+
+ S32 mMaxHeight;
+ LLRect mCollapsedRect;
+ bool mExpanded;
+ LLRect mParentRect;
+
+ bool mBGVisible;
+ bool mExpandedBGVisible;
+ LLUIColor mBGColor;
+ LLUIColor mExpandedBGColor;
+};
+
+#endif //LL_LLEXPANDABLETEXTBOX_H
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 3dfe6a2820..eef774426a 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -47,11 +47,12 @@
#include "lllightconstants.h"
#include "llsky.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llvosky.h"
#include "llvovolume.h"
#include "pipeline.h"
#include "llviewerregion.h"
+#include "llviewerwindow.h"
#define LL_MAX_INDICES_COUNT 1000000
@@ -174,11 +175,22 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
mLastGeomIndex = mGeomIndex;
mLastIndicesCount = mIndicesCount;
mLastIndicesIndex = mIndicesIndex;
+
+ mImportanceToCamera = 0.f ;
+ mBoundingSphereRadius = 0.0f ;
+
+ mAtlasInfop = NULL ;
+ mUsingAtlas = FALSE ;
}
void LLFace::destroy()
{
+ if(mTexture.notNull())
+ {
+ mTexture->removeFace(this) ;
+ }
+
if (mDrawPoolp)
{
mDrawPoolp->removeFace(this);
@@ -196,12 +208,14 @@ void LLFace::destroy()
if (group)
{
group->dirtyGeom();
+ gPipeline.markRebuild(group, TRUE);
}
}
}
-
+
setDrawInfo(NULL);
+ removeAtlas();
mDrawablep = NULL;
mVObjp = NULL;
}
@@ -217,7 +231,7 @@ void LLFace::setWorldMatrix(const LLMatrix4 &mat)
llerrs << "Faces on this drawable are not independently modifiable\n" << llendl;
}
-void LLFace::setPool(LLFacePool* new_pool, LLViewerImage *texturep)
+void LLFace::setPool(LLFacePool* new_pool, LLViewerTexture *texturep)
{
LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
@@ -247,9 +261,53 @@ void LLFace::setPool(LLFacePool* new_pool, LLViewerImage *texturep)
}
mDrawPoolp = new_pool;
}
- mTexture = texturep;
+
+ setTexture(texturep) ;
+}
+
+void LLFace::setTexture(LLViewerTexture* tex)
+{
+ if(mTexture == tex)
+ {
+ return ;
+ }
+
+ if(mTexture.notNull())
+ {
+ mTexture->removeFace(this) ;
+ removeAtlas() ;
+ }
+
+ if(tex)
+ {
+ tex->addFace(this) ;
+ }
+
+ mTexture = tex ;
+}
+
+void LLFace::dirtyTexture()
+{
+ gPipeline.markTextured(getDrawable());
}
+void LLFace::switchTexture(LLViewerTexture* new_texture)
+{
+ if(mTexture == new_texture)
+ {
+ return ;
+ }
+
+ if(!new_texture)
+ {
+ llerrs << "Can not switch to a null texture." << llendl ;
+ }
+ new_texture->addTextureStats(mTexture->getMaxVirtualSize()) ;
+
+ getViewerObject()->changeTEImage(mTEOffset, new_texture) ;
+ setTexture(new_texture) ;
+ dirtyTexture();
+}
void LLFace::setTEOffset(const S32 te_offset)
{
@@ -422,10 +480,17 @@ void LLFace::renderForSelect(U32 data_mask)
}
}
-void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color)
+void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)
{
- if(mDrawablep.isNull() || mVertexBuffer.isNull() || mDrawablep->getSpatialGroup() == NULL ||
- mDrawablep->getSpatialGroup()->isState(LLSpatialGroup::GEOM_DIRTY))
+ if (mDrawablep->getSpatialGroup() == NULL)
+ {
+ return;
+ }
+
+ mDrawablep->getSpatialGroup()->rebuildGeom();
+ mDrawablep->getSpatialGroup()->rebuildMesh();
+
+ if(mDrawablep.isNull() || mVertexBuffer.isNull())
{
return;
}
@@ -444,17 +509,10 @@ void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color)
glMultMatrixf((GLfloat*)mDrawablep->getRegion()->mRenderMatrix.mMatrix);
}
- setFaceColor(color);
- renderSetColor();
-
+ glColor4fv(color.mV);
mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0);
-#if !LL_RELEASE_FOR_DOWNLOAD
- LLGLState::checkClientArrays("", LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0);
-#endif
mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex);
- unsetFaceColor();
- unsetFaceColor();
gGL.popMatrix();
}
}
@@ -463,8 +521,8 @@ void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color)
/* removed in lieu of raycast uv detection
void LLFace::renderSelectedUV()
{
- LLViewerImage* red_blue_imagep = gImageList.getImageFromFile("uv_test1.j2c", TRUE, TRUE);
- LLViewerImage* green_imagep = gImageList.getImageFromFile("uv_test2.tga", TRUE, TRUE);
+ LLViewerTexture* red_blue_imagep = LLViewerTextureManager::getFetchedTextureFromFile("uv_test1.j2c", TRUE, LLViewerTexture::BOOST_UI);
+ LLViewerTexture* green_imagep = LLViewerTextureManager::getFetchedTextureFromFile("uv_test2.tga", TRUE, LLViewerTexture::BOOST_UI);
LLGLSUVSelect object_select;
@@ -698,7 +756,9 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
}
mCenterLocal = (newMin+newMax)*0.5f;
-
+ LLVector3 tmp = (newMin - newMax) ;
+ mBoundingSphereRadius = tmp.length() * 0.5f ;
+
updateCenterAgent();
}
@@ -804,6 +864,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
const LLMatrix4& mat_vert, const LLMatrix3& mat_normal,
const U16 &index_offset)
{
+ llpushcallstacks ;
const LLVolumeFace &vf = volume.getVolumeFace(f);
S32 num_vertices = (S32)vf.mVertices.size();
S32 num_indices = (S32)vf.mIndices.size();
@@ -812,7 +873,15 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
{
if (num_indices + (S32) mIndicesIndex > mVertexBuffer->getNumIndices())
{
- llwarns << "Index buffer overflow!" << llendl;
+ llwarns << "Index buffer overflow!" << llendl;
+ llwarns << "Indices Count: " << mIndicesCount
+ << " VF Num Indices: " << num_indices
+ << " Indices Index: " << mIndicesIndex
+ << " VB Num Indices: " << mVertexBuffer->getNumIndices() << llendl;
+ llwarns << "Last Indices Count: " << mLastIndicesCount
+ << " Last Indices Index: " << mLastIndicesIndex
+ << " Face Index: " << f
+ << " Pool Type: " << mPoolType << llendl;
return FALSE;
}
@@ -865,6 +934,13 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
{
mVertexBuffer->getBinormalStrider(binormals, mGeomIndex);
}
+
+ F32 tcoord_xoffset = 0.f ;
+ F32 tcoord_yoffset = 0.f ;
+ F32 tcoord_xscale = 1.f ;
+ F32 tcoord_yscale = 1.f ;
+ BOOL in_atlas = FALSE ;
+
if (rebuild_tcoord)
{
mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex);
@@ -872,6 +948,18 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
{
mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex);
}
+
+ in_atlas = isAtlasInUse() ;
+ if(in_atlas)
+ {
+ const LLVector2* tmp = getTexCoordOffset() ;
+ tcoord_xoffset = tmp->mV[0] ;
+ tcoord_yoffset = tmp->mV[1] ;
+
+ tmp = getTexCoordScale() ;
+ tcoord_xscale = tmp->mV[0] ;
+ tcoord_yscale = tmp->mV[1] ;
+ }
}
if (rebuild_color)
{
@@ -959,7 +1047,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
0.75f
};
- if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || LLPipeline::sRenderBump && tep->getShiny()))
+ if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || (LLPipeline::sRenderBump && tep->getShiny())))
{
color.mV[3] = U8 (alpha[tep->getShiny()] * 255);
}
@@ -998,7 +1086,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
break;
case BE_BRIGHTNESS:
case BE_DARKNESS:
- if( mTexture.notNull() && mTexture->getHasGLTexture())
+ if( mTexture.notNull() && mTexture->hasGLTexture())
{
// Offset by approximately one texel
S32 cur_discard = mTexture->getDiscardLevel();
@@ -1081,6 +1169,93 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
}
+ if(in_atlas)
+ {
+ //
+ //manually calculate tex-coord per vertex for varying address modes.
+ //should be removed if shader can handle this.
+ //
+
+ S32 int_part = 0 ;
+ switch(mTexture->getAddressMode())
+ {
+ case LLTexUnit::TAM_CLAMP:
+ if(tc.mV[0] < 0.f)
+ {
+ tc.mV[0] = 0.f ;
+ }
+ else if(tc.mV[0] > 1.f)
+ {
+ tc.mV[0] = 1.f;
+ }
+
+ if(tc.mV[1] < 0.f)
+ {
+ tc.mV[1] = 0.f ;
+ }
+ else if(tc.mV[1] > 1.f)
+ {
+ tc.mV[1] = 1.f;
+ }
+ break;
+ case LLTexUnit::TAM_MIRROR:
+ if(tc.mV[0] < 0.f)
+ {
+ tc.mV[0] = -tc.mV[0] ;
+ }
+ int_part = (S32)tc.mV[0] ;
+ if(int_part & 1) //odd number
+ {
+ tc.mV[0] = int_part + 1 - tc.mV[0] ;
+ }
+ else //even number
+ {
+ tc.mV[0] -= int_part ;
+ }
+
+ if(tc.mV[1] < 0.f)
+ {
+ tc.mV[1] = -tc.mV[1] ;
+ }
+ int_part = (S32)tc.mV[1] ;
+ if(int_part & 1) //odd number
+ {
+ tc.mV[1] = int_part + 1 - tc.mV[1] ;
+ }
+ else //even number
+ {
+ tc.mV[1] -= int_part ;
+ }
+ break;
+ case LLTexUnit::TAM_WRAP:
+ if(tc.mV[0] > 1.f)
+ tc.mV[0] -= (S32)(tc.mV[0] - 0.00001f) ;
+ else if(tc.mV[0] < -1.f)
+ tc.mV[0] -= (S32)(tc.mV[0] + 0.00001f) ;
+
+ if(tc.mV[1] > 1.f)
+ tc.mV[1] -= (S32)(tc.mV[1] - 0.00001f) ;
+ else if(tc.mV[1] < -1.f)
+ tc.mV[1] -= (S32)(tc.mV[1] + 0.00001f) ;
+
+ if(tc.mV[0] < 0.f)
+ {
+ tc.mV[0] = 1.0f + tc.mV[0] ;
+ }
+ if(tc.mV[1] < 0.f)
+ {
+ tc.mV[1] = 1.0f + tc.mV[1] ;
+ }
+ break;
+ default:
+ break;
+ }
+
+ tc.mV[0] = tcoord_xoffset + tcoord_xscale * tc.mV[0] ;
+ tc.mV[1] = tcoord_yoffset + tcoord_yscale * tc.mV[1] ;
+ }
+
+
*tex_coords++ = tc;
if (bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1))
@@ -1147,9 +1322,171 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
return TRUE;
}
+const F32 LEAST_IMPORTANCE = 0.05f ;
+const F32 LEAST_IMPORTANCE_FOR_LARGE_IMAGE = 0.3f ;
+
+F32 LLFace::getTextureVirtualSize()
+{
+ F32 radius;
+ F32 cos_angle_to_view_dir;
+ mPixelArea = calcPixelArea(cos_angle_to_view_dir, radius);
+
+ if (mPixelArea <= 0)
+ {
+ return 0.f;
+ }
+
+ //get area of circle in texture space
+ LLVector2 tdim = mTexExtents[1] - mTexExtents[0];
+ F32 texel_area = (tdim * 0.5f).lengthSquared()*3.14159f;
+ if (texel_area <= 0)
+ {
+ // Probably animated, use default
+ texel_area = 1.f;
+ }
+
+ //apply texel area to face area to get accurate ratio
+ //face_area /= llclamp(texel_area, 1.f/64.f, 16.f);
+ F32 face_area = mPixelArea / llclamp(texel_area, 0.015625f, 128.f);
+
+ if(face_area > LLViewerTexture::sMaxSmallImageSize)
+ {
+ if(mImportanceToCamera < LEAST_IMPORTANCE) //if the face is not important, do not load hi-res.
+ {
+ static const F32 MAX_LEAST_IMPORTANCE_IMAGE_SIZE = 128.0f * 128.0f ;
+ face_area = llmin(face_area * 0.5f, MAX_LEAST_IMPORTANCE_IMAGE_SIZE) ;
+ }
+ else if(face_area > LLViewerTexture::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping.
+ {
+ if(mImportanceToCamera < LEAST_IMPORTANCE_FOR_LARGE_IMAGE)//if the face is not important, do not load hi-res.
+ {
+ face_area = LLViewerTexture::sMinLargeImageSize ;
+ }
+ else if(mTexture.notNull() && mTexture->isLargeImage())
+ {
+ face_area *= adjustPartialOverlapPixelArea(cos_angle_to_view_dir, radius );
+ }
+ }
+ }
+
+ return face_area;
+}
+
+F32 LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius)
+{
+ //get area of circle around face
+ LLVector3 center = getPositionAgent();
+ LLVector3 size = (mExtents[1] - mExtents[0]) * 0.5f;
+
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
+ LLVector3 lookAt = center - camera->getOrigin();
+ F32 dist = lookAt.normVec() ;
+
+ //get area of circle around node
+ F32 app_angle = atanf(size.length()/dist);
+ radius = app_angle*LLDrawable::sCurPixelAngle;
+ F32 face_area = radius*radius * 3.14159f;
+
+ if(dist < mBoundingSphereRadius) //camera is very close
+ {
+ cos_angle_to_view_dir = 1.0f ;
+ mImportanceToCamera = 1.0f ;
+ }
+ else
+ {
+ cos_angle_to_view_dir = lookAt * camera->getXAxis() ;
+ mImportanceToCamera = LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist) ;
+ }
+
+ return face_area ;
+}
+
+//the projection of the face partially overlaps with the screen
+F32 LLFace::adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius )
+{
+ F32 screen_radius = (F32)llmax(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()) ;
+ F32 center_angle = acosf(cos_angle_to_view_dir) ;
+ F32 d = center_angle * LLDrawable::sCurPixelAngle ;
+
+ if(d + radius > screen_radius + 5.f)
+ {
+ //----------------------------------------------
+ //calculate the intersection area of two circles
+ //F32 radius_square = radius * radius ;
+ //F32 d_square = d * d ;
+ //F32 screen_radius_square = screen_radius * screen_radius ;
+ //face_area =
+ // radius_square * acosf((d_square + radius_square - screen_radius_square)/(2 * d * radius)) +
+ // screen_radius_square * acosf((d_square + screen_radius_square - radius_square)/(2 * d * screen_radius)) -
+ // 0.5f * sqrtf((-d + radius + screen_radius) * (d + radius - screen_radius) * (d - radius + screen_radius) * (d + radius + screen_radius)) ;
+ //----------------------------------------------
+
+ //the above calculation is too expensive
+ //the below is a good estimation: bounding box of the bounding sphere:
+ F32 alpha = 0.5f * (radius + screen_radius - d) / radius ;
+ alpha = llclamp(alpha, 0.f, 1.f) ;
+ return alpha * alpha ;
+ }
+ return 1.0f ;
+}
+
+const S8 FACE_IMPORTANCE_LEVEL = 4 ;
+const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL][2] = //{distance, importance_weight}
+ {{16.1f, 1.0f}, {32.1f, 0.5f}, {48.1f, 0.2f}, {96.1f, 0.05f} } ;
+const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[FACE_IMPORTANCE_LEVEL][2] = //{cos(angle), importance_weight}
+ {{0.985f /*cos(10 degrees)*/, 1.0f}, {0.94f /*cos(20 degrees)*/, 0.8f}, {0.866f /*cos(30 degrees)*/, 0.64f}, {0.0f, 0.36f}} ;
+
+//static
+F32 LLFace::calcImportanceToCamera(F32 cos_angle_to_view_dir, F32 dist)
+{
+ F32 importance = 0.f ;
+
+ if(cos_angle_to_view_dir > LLViewerCamera::getInstance()->getCosHalfFov() &&
+ dist < FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL - 1][0])
+ {
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
+ F32 camera_moving_speed = camera->getAverageSpeed() ;
+ F32 camera_angular_speed = camera->getAverageAngularSpeed();
+
+ if(camera_moving_speed > 10.0f || camera_angular_speed > 1.0f)
+ {
+ //if camera moves or rotates too fast, ignore the importance factor
+ return 0.f ;
+ }
+
+ //F32 camera_relative_speed = camera_moving_speed * (lookAt * LLViewerCamera::getInstance()->getVelocityDir()) ;
+
+ S32 i = 0 ;
+ for(i = 0; i < FACE_IMPORTANCE_LEVEL && dist > FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][0]; ++i);
+ i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ;
+ F32 dist_factor = FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][1] ;
+
+ for(i = 0; i < FACE_IMPORTANCE_LEVEL && cos_angle_to_view_dir < FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][0] ; ++i) ;
+ i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ;
+ importance = dist_factor * FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][1] ;
+ }
+
+ return importance ;
+}
+
BOOL LLFace::verify(const U32* indices_array) const
{
BOOL ok = TRUE;
+
+ if( mVertexBuffer.isNull() )
+ {
+ if( mGeomCount )
+ {
+ // This happens before teleports as faces are torn down.
+ // Stop the crash in DEV-31893 with a null pointer check,
+ // but present this info.
+ // To clean up the log, the geometry could be cleared, or the
+ // face could otherwise be marked for no ::verify.
+ llinfos << "Face with no vertex buffer and " << mGeomCount << " mGeomCount" << llendl;
+ }
+ return TRUE;
+ }
+
// First, check whether the face data fits within the pool's range.
if ((mGeomIndex + mGeomCount) > mVertexBuffer->getNumVerts())
{
@@ -1320,3 +1657,156 @@ LLVector3 LLFace::getPositionAgent() const
return mCenterLocal * getRenderMatrix();
}
}
+
+//
+//atlas
+//
+void LLFace::removeAtlas()
+{
+ setAtlasInUse(FALSE) ;
+ mAtlasInfop = NULL ;
+}
+
+const LLTextureAtlas* LLFace::getAtlas()const
+{
+ if(mAtlasInfop)
+ {
+ return mAtlasInfop->getAtlas() ;
+ }
+ return NULL ;
+}
+
+const LLVector2* LLFace::getTexCoordOffset()const
+{
+ if(isAtlasInUse())
+ {
+ return mAtlasInfop->getTexCoordOffset() ;
+ }
+ return NULL ;
+}
+const LLVector2* LLFace::getTexCoordScale() const
+{
+ if(isAtlasInUse())
+ {
+ return mAtlasInfop->getTexCoordScale() ;
+ }
+ return NULL ;
+}
+
+BOOL LLFace::isAtlasInUse()const
+{
+ return mUsingAtlas ;
+}
+
+BOOL LLFace::canUseAtlas()const
+{
+ //no drawable or no spatial group, do not use atlas
+ if(!mDrawablep || !mDrawablep->getSpatialGroup())
+ {
+ return FALSE ;
+ }
+
+ //if bump face, do not use atlas
+ if(getTextureEntry() && getTextureEntry()->getBumpmap())
+ {
+ return FALSE ;
+ }
+
+ //if animated texture, do not use atlas
+ if(isState(TEXTURE_ANIM))
+ {
+ return FALSE ;
+ }
+
+ return TRUE ;
+}
+
+void LLFace::setAtlasInUse(BOOL flag)
+{
+ //no valid atlas to use.
+ if(flag && (!mAtlasInfop || !mAtlasInfop->isValid()))
+ {
+ flag = FALSE ;
+ }
+
+ if(!flag && !mUsingAtlas)
+ {
+ return ;
+ }
+
+ //
+ //at this stage (flag || mUsingAtlas) is always true.
+ //
+
+ //rebuild the tex coords
+ if(mDrawablep)
+ {
+ gPipeline.markRebuild(mDrawablep, LLDrawable::REBUILD_TCOORD);
+ mUsingAtlas = flag ;
+ }
+ else
+ {
+ mUsingAtlas = FALSE ;
+ }
+}
+
+LLTextureAtlasSlot* LLFace::getAtlasInfo()
+{
+ return mAtlasInfop ;
+}
+
+void LLFace::setAtlasInfo(LLTextureAtlasSlot* atlasp)
+{
+ if(mAtlasInfop != atlasp)
+ {
+ if(mAtlasInfop)
+ {
+ //llerrs << "Atlas slot changed!" << llendl ;
+ }
+ mAtlasInfop = atlasp ;
+ }
+}
+
+LLViewerTexture* LLFace::getTexture() const
+{
+ if(isAtlasInUse())
+ {
+ return (LLViewerTexture*)mAtlasInfop->getAtlas() ;
+ }
+
+ return mTexture ;
+}
+
+//switch to atlas or switch back to gl texture
+//return TRUE if using atlas.
+BOOL LLFace::switchTexture()
+{
+ //no valid atlas or texture
+ if(!mAtlasInfop || !mAtlasInfop->isValid() || !mTexture)
+ {
+ return FALSE ;
+ }
+
+ if(mTexture->getTexelsInAtlas() >= (U32)mVSize ||
+ mTexture->getTexelsInAtlas() >= mTexture->getTexelsInGLTexture())
+ {
+ //switch to use atlas
+ //atlas resolution is qualified, use it.
+ if(!mUsingAtlas)
+ {
+ setAtlasInUse(TRUE) ;
+ }
+ }
+ else //if atlas not qualified.
+ {
+ //switch back to GL texture
+ if(mUsingAtlas && mTexture->isGLTextureCreated() &&
+ mTexture->getDiscardLevel() < mTexture->getDiscardLevelInAtlas())
+ {
+ setAtlasInUse(FALSE) ;
+ }
+ }
+
+ return mUsingAtlas ;
+}
+
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index 4a551ff261..e12b64a2f2 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -45,17 +45,18 @@
#include "xform.h"
#include "lldarrayptr.h"
#include "llvertexbuffer.h"
-#include "llviewerimage.h"
-#include "llstat.h"
+#include "llviewertexture.h"
#include "lldrawable.h"
+#include "lltextureatlasmanager.h"
class LLFacePool;
class LLVolume;
-class LLViewerImage;
+class LLViewerTexture;
class LLTextureEntry;
class LLVertexProgram;
-class LLViewerImage;
+class LLViewerTexture;
class LLGeometryManager;
+class LLTextureAtlasSlot;
const F32 MIN_ALPHA_SIZE = 1024.f;
const F32 MIN_TEX_ANIM_SIZE = 512.f;
@@ -87,8 +88,9 @@ public:
U16 getGeomCount() const { return mGeomCount; } // vertex count for this face
U16 getGeomIndex() const { return mGeomIndex; } // index into draw pool
U16 getGeomStart() const { return mGeomIndex; } // index into draw pool
- LLViewerImage* getTexture() const { return mTexture; }
- void setTexture(LLViewerImage* tex) { mTexture = tex; }
+ void setTexture(LLViewerTexture* tex) ;
+ void switchTexture(LLViewerTexture* new_texture);
+ void dirtyTexture();
LLXformMatrix* getXform() const { return mXform; }
BOOL hasGeometry() const { return mGeomCount > 0; }
LLVector3 getPositionAgent() const;
@@ -103,6 +105,9 @@ public:
F32 getVirtualSize() const { return mVSize; }
F32 getPixelArea() const { return mPixelArea; }
+ S32 getIndexInTex() const {return mIndexInTex ;}
+ void setIndexInTex(S32 index) { mIndexInTex = index ;}
+
void renderSetColor() const;
S32 renderElements(const U16 *index_array) const;
S32 renderIndexed ();
@@ -120,10 +125,10 @@ public:
LLVertexBuffer* getVertexBuffer() const { return mVertexBuffer; }
void setPoolType(U32 type) { mPoolType = type; }
S32 getTEOffset() { return mTEOffset; }
- LLViewerImage* getTexture() { return mTexture; }
+ LLViewerTexture* getTexture() const;
void setViewerObject(LLViewerObject* object);
- void setPool(LLFacePool *pool, LLViewerImage *texturep);
+ void setPool(LLFacePool *pool, LLViewerTexture *texturep);
void setDrawable(LLDrawable *drawable);
void setTEOffset(const S32 te_offset);
@@ -172,7 +177,7 @@ public:
void renderSelectedUV();
void renderForSelect(U32 data_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0);
- void renderSelected(LLImageGL *image, const LLColor4 &color);
+ void renderSelected(LLViewerTexture *image, const LLColor4 &color);
F32 getKey() const { return mDistance; }
@@ -186,7 +191,26 @@ public:
void setIndicesIndex(S32 idx) { mIndicesIndex = idx; }
void setDrawInfo(LLDrawInfo* draw_info);
-protected:
+ F32 getTextureVirtualSize() ;
+ F32 getImportanceToCamera()const {return mImportanceToCamera ;}
+
+ //for atlas
+ LLTextureAtlasSlot* getAtlasInfo() ;
+ void setAtlasInUse(BOOL flag);
+ void setAtlasInfo(LLTextureAtlasSlot* atlasp);
+ BOOL isAtlasInUse()const;
+ BOOL canUseAtlas() const;
+ const LLVector2* getTexCoordScale() const ;
+ const LLVector2* getTexCoordOffset()const;
+ const LLTextureAtlas* getAtlas()const ;
+ void removeAtlas() ;
+ BOOL switchTexture() ;
+
+private:
+ F32 adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius );
+ F32 calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) ;
+public:
+ static F32 calcImportanceToCamera(F32 to_view_dir, F32 dist);
public:
@@ -202,7 +226,7 @@ public:
LLMatrix4* mTextureMatrix;
LLDrawInfo* mDrawInfo;
-protected:
+private:
friend class LLGeometryManager;
friend class LLVolumeGeometryManager;
@@ -215,6 +239,7 @@ protected:
U16 mGeomIndex; // index into draw pool
U32 mIndicesCount;
U32 mIndicesIndex; // index into draw pool for indices (yeah, I know!)
+ S32 mIndexInTex ;
//previous rebuild's geometry info
U16 mLastGeomCount;
@@ -223,7 +248,7 @@ protected:
U32 mLastIndicesIndex;
LLXformMatrix* mXform;
- LLPointer<LLViewerImage> mTexture;
+ LLPointer<LLViewerTexture> mTexture;
LLPointer<LLDrawable> mDrawablep;
LLPointer<LLViewerObject> mVObjp;
S32 mTEOffset;
@@ -231,6 +256,17 @@ protected:
S32 mReferenceIndex;
F32 mVSize;
F32 mPixelArea;
+
+ //importance factor, in the range [0, 1.0].
+ //1.0: the most important.
+ //based on the distance from the face to the view point and the angle from the face center to the view direction.
+ F32 mImportanceToCamera ;
+ F32 mBoundingSphereRadius ;
+
+
+ //atlas
+ LLPointer<LLTextureAtlasSlot> mAtlasInfop ;
+ BOOL mUsingAtlas ;
protected:
static BOOL sSafeRenderSelect;
@@ -259,7 +295,7 @@ public:
const LLTextureEntry* lte = lhs->getTextureEntry();
const LLTextureEntry* rte = rhs->getTextureEntry();
- if (lhs->getTexture() != rhs->getTexture())
+ if(lhs->getTexture() != rhs->getTexture())
{
return lhs->getTexture() < rhs->getTexture();
}
diff --git a/indra/newview/llface.inl b/indra/newview/llface.inl
index 38f38f5466..176c73e38e 100644
--- a/indra/newview/llface.inl
+++ b/indra/newview/llface.inl
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
- * Copyright (c) 2001-2007, Linden Research, Inc.
+ * Copyright (c) 2001-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -12,12 +12,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index c9037d0fbb..4fa97e789b 100644
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -32,304 +32,129 @@
#include "llviewerprecompiledheaders.h"
-#include "indra_constants.h"
#include "llfasttimerview.h"
+
#include "llviewerwindow.h"
#include "llrect.h"
#include "llerror.h"
#include "llgl.h"
#include "llrender.h"
+#include "lllocalcliprect.h"
#include "llmath.h"
#include "llfontgl.h"
+#include "llsdserialize.h"
+#include "lltooltip.h"
#include "llappviewer.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llui.h"
#include "llviewercontrol.h"
#include "llstat.h"
#include "llfasttimer.h"
-
+#include "lltreeiterators.h"
+#include "llmetricperformancetester.h"
//////////////////////////////////////////////////////////////////////////////
static const S32 MAX_VISIBLE_HISTORY = 10;
static const S32 LINE_GRAPH_HEIGHT = 240;
-struct ft_display_info {
- int timer;
- const char *desc;
- const LLColor4 *color;
- S32 disabled; // initialized to 0
- int level; // calculated based on desc
- int parent; // calculated
-};
-
-static const LLColor4 red0(0.5f, 0.0f, 0.0f, 1.0f);
-static const LLColor4 green0(0.0f, 0.5f, 0.0f, 1.0f);
-static const LLColor4 blue0(0.0f, 0.0f, 0.5f, 1.0f);
-static const LLColor4 blue7(0.0f, 0.0f, 0.5f, 1.0f);
-
-static const LLColor4 green7(0.6f, 1.0f, 0.4f, 1.0f);
-static const LLColor4 green8(0.4f, 1.0f, 0.6f, 1.0f);
-static const LLColor4 green9(0.6f, 1.0f, 0.6f, 1.0f);
-
-// green(6), blue, yellow, orange, pink(2), cyan
-// red (5) magenta (4)
-static struct ft_display_info ft_display_table[] =
-{
- { LLFastTimer::FTM_FRAME, "Frame", &LLColor4::white, 0 },
- { LLFastTimer::FTM_MESSAGES, " System Messages", &LLColor4::grey1, 1 },
- { LLFastTimer::FTM_MOUSEHANDLER, " Mouse", &LLColor4::grey1, 0 },
- { LLFastTimer::FTM_KEYHANDLER, " Keyboard", &LLColor4::grey1, 0 },
- { LLFastTimer::FTM_SLEEP, " Sleep", &LLColor4::grey2, 0 },
- { LLFastTimer::FTM_IDLE, " Idle", &blue0, 0 },
- { LLFastTimer::FTM_PUMP, " Pump", &LLColor4::magenta2, 1 },
- { LLFastTimer::FTM_CURL, " Curl", &LLColor4::magenta3, 0 },
- { LLFastTimer::FTM_INVENTORY, " Inventory Update", &LLColor4::purple6, 1 },
- { LLFastTimer::FTM_AUTO_SELECT, " Open and Select", &LLColor4::red, 0 },
- { LLFastTimer::FTM_FILTER, " Filter", &LLColor4::red2, 0 },
- { LLFastTimer::FTM_ARRANGE, " Arrange", &LLColor4::red3, 0 },
- { LLFastTimer::FTM_REFRESH, " Refresh", &LLColor4::red4, 0 },
- { LLFastTimer::FTM_SORT, " Sort", &LLColor4::red5, 0 },
- { LLFastTimer::FTM_RESET_DRAWORDER, " ResetDrawOrder", &LLColor4::pink1, 0 },
- { LLFastTimer::FTM_WORLD_UPDATE, " World Update", &LLColor4::blue1, 1 },
- { LLFastTimer::FTM_UPDATE_MOVE, " Move Objects", &LLColor4::pink2, 0 },
- { LLFastTimer::FTM_OCTREE_BALANCE, " Octree Balance", &LLColor4::red3, 0 },
- { LLFastTimer::FTM_SIMULATE_PARTICLES, " Particle Sim", &LLColor4::blue4, 0 },
- { LLFastTimer::FTM_OBJECTLIST_UPDATE, " Object Update", &LLColor4::purple1, 1 },
- { LLFastTimer::FTM_AVATAR_UPDATE, " Avatars", &LLColor4::purple2, 0 },
- { LLFastTimer::FTM_JOINT_UPDATE, " Joints", &LLColor4::purple3, 0 },
- { LLFastTimer::FTM_ATTACHMENT_UPDATE, " Attachments", &LLColor4::purple4, 0 },
- { LLFastTimer::FTM_UPDATE_ANIMATION, " Animation", &LLColor4::purple5, 0 },
- { LLFastTimer::FTM_FLEXIBLE_UPDATE, " Flex Update", &LLColor4::pink2, 0 },
- { LLFastTimer::FTM_LOD_UPDATE, " LOD Update", &LLColor4::magenta1, 0 },
- { LLFastTimer::FTM_REGION_UPDATE, " Region Update", &LLColor4::cyan2, 0 },
- { LLFastTimer::FTM_NETWORK, " Network", &LLColor4::orange1, 1 },
- { LLFastTimer::FTM_IDLE_NETWORK, " Decode Msgs", &LLColor4::orange2, 0 },
- { LLFastTimer::FTM_PROCESS_MESSAGES, " Process Msgs", &LLColor4::orange3, 0 },
- { LLFastTimer::FTM_PROCESS_OBJECTS, " Object Updates",&LLColor4::orange4, 0 },
- { LLFastTimer::FTM_CREATE_OBJECT, " Create Obj", &LLColor4::orange5, 0 },
-// { LLFastTimer::FTM_LOAD_AVATAR, " Load Avatar", &LLColor4::pink2, 0 },
- { LLFastTimer::FTM_PROCESS_IMAGES, " Image Updates",&LLColor4::orange6, 0 },
- { LLFastTimer::FTM_PIPELINE, " Pipeline", &LLColor4::magenta4, 0 },
- { LLFastTimer::FTM_CLEANUP, " Cleanup", &LLColor4::cyan3, 0 },
- { LLFastTimer::FTM_AUDIO_UPDATE, " Audio Update", &LLColor4::yellow3, 0 },
- { LLFastTimer::FTM_VFILE_WAIT, " VFile Wait", &LLColor4::cyan6, 0 },
-// { LLFastTimer::FTM_IDLE_CB, " Callbacks", &LLColor4::pink1, 0 },
- { LLFastTimer::FTM_RENDER, " Render", &green0, 1 },
- { LLFastTimer::FTM_PICK, " Pick", &LLColor4::purple, 1 },
- { LLFastTimer::FTM_HUD_EFFECTS, " HUD Effects", &LLColor4::orange1, 0 },
- { LLFastTimer::FTM_HUD_UPDATE, " HUD Update", &LLColor4::orange2, 0 },
- { LLFastTimer::FTM_UPDATE_SKY, " Sky Update", &LLColor4::cyan1, 0 },
- { LLFastTimer::FTM_UPDATE_TEXTURES, " Textures", &LLColor4::pink2, 0 },
- { LLFastTimer::FTM_GEO_UPDATE, " Geo Update", &LLColor4::blue3, 1 },
- { LLFastTimer::FTM_UPDATE_PRIMITIVES, " Volumes", &LLColor4::blue4, 0 },
- { LLFastTimer::FTM_GEN_VOLUME, " Gen Volume", &LLColor4::yellow3, 0 },
- { LLFastTimer::FTM_GEN_FLEX, " Flexible", &LLColor4::yellow4, 0 },
- { LLFastTimer::FTM_GEN_TRIANGLES, " Triangles", &LLColor4::yellow5, 0 },
- { LLFastTimer::FTM_UPDATE_AVATAR, " Avatar", &LLColor4::yellow1, 0 },
- { LLFastTimer::FTM_UPDATE_TREE, " Tree", &LLColor4::yellow2, 0 },
- { LLFastTimer::FTM_UPDATE_TERRAIN, " Terrain", &LLColor4::yellow6, 0 },
- { LLFastTimer::FTM_UPDATE_CLOUDS, " Clouds", &LLColor4::yellow7, 0 },
- { LLFastTimer::FTM_UPDATE_GRASS, " Grass", &LLColor4::yellow8, 0 },
- { LLFastTimer::FTM_UPDATE_WATER, " Water", &LLColor4::yellow9, 0 },
- { LLFastTimer::FTM_GEO_LIGHT, " Lighting", &LLColor4::yellow1, 0 },
- { LLFastTimer::FTM_GEO_SHADOW, " Shadow", &LLColor4::black, 0 },
- { LLFastTimer::FTM_UPDATE_PARTICLES, " Particles", &LLColor4::blue5, 0 },
- { LLFastTimer::FTM_GEO_RESERVE, " Reserve", &LLColor4::blue6, 0 },
- { LLFastTimer::FTM_UPDATE_LIGHTS, " Lights", &LLColor4::yellow2, 0 },
- { LLFastTimer::FTM_GEO_SKY, " Sky", &LLColor4::yellow3, 0 },
- { LLFastTimer::FTM_UPDATE_WLPARAM, " Windlight Param",&LLColor4::magenta2, 0 },
- { LLFastTimer::FTM_CULL, " Object Cull", &LLColor4::blue2, 1 },
- { LLFastTimer::FTM_CULL_REBOUND, " Rebound", &LLColor4::blue3, 0 },
- { LLFastTimer::FTM_FRUSTUM_CULL, " Frustum Cull", &LLColor4::blue4, 0 },
- { LLFastTimer::FTM_OCCLUSION_READBACK, " Occlusion Read", &LLColor4::red2, 0 },
- { LLFastTimer::FTM_IMAGE_UPDATE, " Image Update", &LLColor4::yellow4, 1 },
- { LLFastTimer::FTM_IMAGE_CREATE, " Image CreateGL",&LLColor4::yellow5, 0 },
- { LLFastTimer::FTM_IMAGE_DECODE, " Image Decode", &LLColor4::yellow6, 0 },
- { LLFastTimer::FTM_IMAGE_MARK_DIRTY, " Dirty Textures",&LLColor4::red1, 0 },
- { LLFastTimer::FTM_STATESORT, " State Sort", &LLColor4::orange1, 1 },
- { LLFastTimer::FTM_STATESORT_DRAWABLE, " Drawable", &LLColor4::orange2, 0 },
- { LLFastTimer::FTM_STATESORT_POSTSORT, " Post Sort", &LLColor4::orange3, 0 },
- { LLFastTimer::FTM_REBUILD_OCCLUSION_VB," Occlusion", &LLColor4::cyan5, 0 },
- { LLFastTimer::FTM_REBUILD_VBO, " VBO Rebuild", &LLColor4::red4, 0 },
- { LLFastTimer::FTM_REBUILD_VOLUME_VB, " Volume", &LLColor4::blue1, 0 },
-// { LLFastTimer::FTM_REBUILD_NONE_VB, " Unknown", &LLColor4::cyan5, 0 },
-// { LLFastTimer::FTM_REBUILD_BRIDGE_VB, " Bridge", &LLColor4::blue2, 0 },
-// { LLFastTimer::FTM_REBUILD_HUD_VB, " HUD", &LLColor4::blue3, 0 },
- { LLFastTimer::FTM_REBUILD_TERRAIN_VB, " Terrain", &LLColor4::blue4, 0 },
-// { LLFastTimer::FTM_REBUILD_WATER_VB, " Water", &LLColor4::blue5, 0 },
-// { LLFastTimer::FTM_REBUILD_TREE_VB, " Tree", &LLColor4::cyan1, 0 },
- { LLFastTimer::FTM_REBUILD_PARTICLE_VB, " Particle", &LLColor4::cyan2, 0 },
-// { LLFastTimer::FTM_REBUILD_CLOUD_VB, " Cloud", &LLColor4::cyan3, 0 },
- { LLFastTimer::FTM_REBUILD_GRASS_VB, " Grass", &LLColor4::cyan4, 0 },
- { LLFastTimer::FTM_SHADOW_RENDER, " Shadow", &LLColor4::green5, 1 },
- { LLFastTimer::FTM_SHADOW_SIMPLE, " Simple", &LLColor4::yellow2, 1 },
- { LLFastTimer::FTM_SHADOW_ALPHA, " Alpha", &LLColor4::yellow6, 1 },
- { LLFastTimer::FTM_SHADOW_TERRAIN, " Terrain", &LLColor4::green6, 1 },
- { LLFastTimer::FTM_SHADOW_AVATAR, " Avatar", &LLColor4::yellow1, 1 },
- { LLFastTimer::FTM_SHADOW_TREE, " Tree", &LLColor4::yellow8, 1 },
- { LLFastTimer::FTM_RENDER_GEOMETRY, " Geometry", &LLColor4::green2, 1 },
- { LLFastTimer::FTM_POOLS, " Pools", &LLColor4::green3, 1 },
- { LLFastTimer::FTM_POOLRENDER, " RenderPool", &LLColor4::green4, 1 },
- { LLFastTimer::FTM_RENDER_TERRAIN, " Terrain", &LLColor4::green6, 0 },
- { LLFastTimer::FTM_RENDER_CHARACTERS, " Avatars", &LLColor4::yellow1, 0 },
- { LLFastTimer::FTM_RENDER_SIMPLE, " Simple", &LLColor4::yellow2, 0 },
- { LLFastTimer::FTM_RENDER_FULLBRIGHT, " Fullbright", &LLColor4::yellow5, 0 },
- { LLFastTimer::FTM_RENDER_GLOW, " Glow", &LLColor4::orange1, 0 },
- { LLFastTimer::FTM_RENDER_GRASS, " Grass", &LLColor4::yellow6, 0 },
- { LLFastTimer::FTM_RENDER_INVISIBLE, " Invisible", &LLColor4::red2, 0 },
- { LLFastTimer::FTM_RENDER_SHINY, " Shiny", &LLColor4::yellow3, 0 },
- { LLFastTimer::FTM_RENDER_BUMP, " Bump", &LLColor4::yellow4, 0 },
- { LLFastTimer::FTM_RENDER_TREES, " Trees", &LLColor4::yellow8, 0 },
- { LLFastTimer::FTM_RENDER_OCCLUSION, " Occlusion", &LLColor4::red1, 0 },
- { LLFastTimer::FTM_RENDER_CLOUDS, " Clouds", &LLColor4::yellow5, 0 },
- { LLFastTimer::FTM_RENDER_ALPHA, " Alpha", &LLColor4::yellow6, 0 },
- { LLFastTimer::FTM_RENDER_HUD, " HUD", &LLColor4::yellow7, 0 },
- { LLFastTimer::FTM_RENDER_WATER, " Water", &LLColor4::yellow9, 0 },
- { LLFastTimer::FTM_RENDER_WL_SKY, " WL Sky", &LLColor4::blue3, 0 },
- { LLFastTimer::FTM_RENDER_FAKE_VBO_UPDATE," Fake VBO update", &LLColor4::red2, 0 },
- { LLFastTimer::FTM_RENDER_BLOOM, " Bloom", &LLColor4::blue4, 0 },
- { LLFastTimer::FTM_RENDER_BLOOM_FBO, " First FBO", &LLColor4::blue, 0 },
- { LLFastTimer::FTM_RENDER_UI, " UI", &LLColor4::cyan4, 1 },
- { LLFastTimer::FTM_RENDER_TIMER, " Timers", &LLColor4::cyan5, 1, 0 },
- { LLFastTimer::FTM_RENDER_FONTS, " Fonts", &LLColor4::pink1, 0 },
- { LLFastTimer::FTM_SWAP, " Swap", &LLColor4::pink2, 0 },
- { LLFastTimer::FTM_CLIENT_COPY, " Client Copy", &LLColor4::red1, 1},
-
-#if 0 || !LL_RELEASE_FOR_DOWNLOAD
- { LLFastTimer::FTM_TEMP1, " Temp1", &LLColor4::red1, 0 },
- { LLFastTimer::FTM_TEMP2, " Temp2", &LLColor4::magenta1, 0 },
- { LLFastTimer::FTM_TEMP3, " Temp3", &LLColor4::red2, 0 },
- { LLFastTimer::FTM_TEMP4, " Temp4", &LLColor4::magenta2, 0 },
- { LLFastTimer::FTM_TEMP5, " Temp5", &LLColor4::red3, 0 },
- { LLFastTimer::FTM_TEMP6, " Temp6", &LLColor4::magenta3, 0 },
- { LLFastTimer::FTM_TEMP7, " Temp7", &LLColor4::red4, 0 },
- { LLFastTimer::FTM_TEMP8, " Temp8", &LLColor4::magenta4, 0 },
-#endif
-
- { LLFastTimer::FTM_OTHER, " Other", &red0 }
-};
-static int ft_display_didcalc = 0;
-static const int FTV_DISPLAY_NUM = LL_ARRAY_SIZE(ft_display_table);
+//static const int FTV_DISPLAY_NUM = (sizeof(ft_display_table)/sizeof(ft_display_table[0]));
+static S32 FTV_NUM_TIMERS;
+const S32 FTV_MAX_DEPTH = 8;
-S32 ft_display_idx[FTV_DISPLAY_NUM]; // line of table entry for display purposes (for collapse)
+std::vector<LLFastTimer::NamedTimer*> ft_display_idx; // line of table entry for display purposes (for collapse)
-LLFastTimerView::LLFastTimerView(const std::string& name, const LLRect& rect)
- : LLFloater(name, rect, std::string("Fast Timers"))
+typedef LLTreeDFSIter<LLFastTimer::NamedTimer, LLFastTimer::NamedTimer::child_const_iter> timer_tree_iterator_t;
+
+BOOL LLFastTimerView::sAnalyzePerformance = FALSE;
+
+static timer_tree_iterator_t begin_timer_tree(LLFastTimer::NamedTimer& id)
+{
+ return timer_tree_iterator_t(&id,
+ boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::beginChildren), _1),
+ boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::endChildren), _1));
+}
+
+static timer_tree_iterator_t end_timer_tree()
+{
+ return timer_tree_iterator_t();
+}
+
+LLFastTimerView::LLFastTimerView(const LLRect& rect)
+: LLFloater(LLSD()),
+ mHoverTimer(NULL)
{
+ setRect(rect);
setVisible(FALSE);
mDisplayMode = 0;
mAvgCountTotal = 0;
mMaxCountTotal = 0;
- mDisplayCenter = 1;
+ mDisplayCenter = ALIGN_CENTER;
mDisplayCalls = 0;
mDisplayHz = 0;
mScrollIndex = 0;
- mHoverIndex = -1;
+ mHoverID = NULL;
mHoverBarIndex = -1;
- mBarStart = new S32[(MAX_VISIBLE_HISTORY + 1) * FTV_DISPLAY_NUM];
- memset(mBarStart, 0, (MAX_VISIBLE_HISTORY + 1) * FTV_DISPLAY_NUM * sizeof(S32));
- mBarEnd = new S32[(MAX_VISIBLE_HISTORY + 1) * FTV_DISPLAY_NUM];
- memset(mBarEnd, 0, (MAX_VISIBLE_HISTORY + 1) * FTV_DISPLAY_NUM * sizeof(S32));
- mSubtractHidden = 0;
+ FTV_NUM_TIMERS = LLFastTimer::NamedTimer::instanceCount();
mPrintStats = -1;
-
- // One-time setup
- if (!ft_display_didcalc)
- {
- int pidx[FTV_DISPLAY_NUM];
- int pdisabled[FTV_DISPLAY_NUM];
- for (S32 i=0; i < FTV_DISPLAY_NUM; i++)
- {
- int level = 0;
- const char *text = ft_display_table[i].desc;
- while(text[0] == ' ')
- {
- text++;
- level++;
- }
- llassert(level < FTV_DISPLAY_NUM);
- ft_display_table[i].desc = text;
- ft_display_table[i].level = level;
- if (level > 0)
- {
- ft_display_table[i].parent = pidx[level-1];
- if (pdisabled[level-1])
- {
- ft_display_table[i].disabled = 3;
- }
- }
- else
- {
- ft_display_table[i].parent = -1;
- }
- ft_display_idx[i] = i;
- pidx[level] = i;
- pdisabled[level] = ft_display_table[i].disabled;
- }
- ft_display_didcalc = 1;
- }
+ mAverageCyclesPerTimer = 0;
}
-LLFastTimerView::~LLFastTimerView()
-{
- delete[] mBarStart;
- delete[] mBarEnd;
-}
BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
- if (mBarRect.pointInRect(x, y))
+ if (mHoverTimer )
+ {
+ // right click collapses timers
+ if (!mHoverTimer->getCollapsed())
+ {
+ mHoverTimer->setCollapsed(true);
+ }
+ else if (mHoverTimer->getParent())
+ {
+ mHoverTimer->getParent()->setCollapsed(true);
+ }
+ }
+ else if (mBarRect.pointInRect(x, y))
{
S32 bar_idx = MAX_VISIBLE_HISTORY - ((y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) / mBarRect.getHeight());
bar_idx = llclamp(bar_idx, 0, MAX_VISIBLE_HISTORY);
mPrintStats = bar_idx;
-// return TRUE; // for now, pass all mouse events through
}
return FALSE;
}
-S32 LLFastTimerView::getLegendIndex(S32 y)
+LLFastTimer::NamedTimer* LLFastTimerView::getLegendID(S32 y)
{
S32 idx = (getRect().getHeight() - y) / ((S32) LLFontGL::getFontMonospace()->getLineHeight()+2) - 5;
- if (idx >= 0 && idx < FTV_DISPLAY_NUM)
+
+ if (idx >= 0 && idx < (S32)ft_display_idx.size())
{
return ft_display_idx[idx];
}
- return -1;
+ return NULL;
}
BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask)
{
if (x < mBarRect.mLeft)
{
- S32 legend_index = getLegendIndex(y);
- if (legend_index >= 0 && legend_index < FTV_DISPLAY_NUM)
+ LLFastTimer::NamedTimer* idp = getLegendID(y);
+ if (idp)
{
- S32 disabled = ft_display_table[legend_index].disabled;
- if (++disabled > 2)
- disabled = 0;
- ft_display_table[legend_index].disabled = disabled;
- S32 level = ft_display_table[legend_index].level;
-
- // propagate enable/disable to all children
- legend_index++;
- while (legend_index < FTV_DISPLAY_NUM && ft_display_table[legend_index].level > level)
- {
- ft_display_table[legend_index].disabled = disabled ? 3 : 0;
- legend_index++;
- }
+ idp->setCollapsed(!idp->getCollapsed());
}
}
+ else if (mHoverTimer)
+ {
+ //left click drills down by expanding timers
+ mHoverTimer->setCollapsed(false);
+ }
else if (mask & MASK_ALT)
{
- if (mask & MASK_SHIFT)
- {
- mSubtractHidden = !mSubtractHidden;
- }
- else if (mask & MASK_CONTROL)
+ if (mask & MASK_CONTROL)
{
mDisplayHz = !mDisplayHz;
}
@@ -345,8 +170,7 @@ BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask)
}
else if (mask & MASK_CONTROL)
{
- if (++mDisplayCenter > 2)
- mDisplayCenter = 0;
+ mDisplayCenter = (ChildAlignment)((mDisplayCenter + 1) % ALIGN_COUNT);
}
else
{
@@ -367,13 +191,15 @@ BOOL LLFastTimerView::handleMouseUp(S32 x, S32 y, MASK mask)
return FALSE;
}
-
BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask)
{
+ mHoverTimer = NULL;
+ mHoverID = NULL;
+
if(LLFastTimer::sPauseHistory && mBarRect.pointInRect(x, y))
{
- mHoverIndex = -1;
- mHoverBarIndex = MAX_VISIBLE_HISTORY - ((y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) / mBarRect.getHeight());
+ mHoverBarIndex = llmin(LLFastTimer::getCurFrameIndex() - 1,
+ MAX_VISIBLE_HISTORY - ((y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) / mBarRect.getHeight()));
if (mHoverBarIndex == 0)
{
return TRUE;
@@ -382,22 +208,73 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask)
{
mHoverBarIndex = 0;
}
- for (S32 i = 0; i < FTV_DISPLAY_NUM; i++)
+
+ S32 i = 0;
+ for(timer_tree_iterator_t it = begin_timer_tree(LLFastTimer::NamedTimer::getRootNamedTimer());
+ it != end_timer_tree();
+ ++it, ++i)
{
- if (x > mBarStart[mHoverBarIndex * FTV_DISPLAY_NUM + i] &&
- x < mBarEnd[mHoverBarIndex * FTV_DISPLAY_NUM + i] &&
- ft_display_table[i].disabled <= 1)
+ // is mouse over bar for this timer?
+ if (x > mBarStart[mHoverBarIndex][i] &&
+ x < mBarEnd[mHoverBarIndex][i])
+ {
+ mHoverID = (*it);
+ mHoverTimer = (*it);
+ mToolTipRect.set(mBarStart[mHoverBarIndex][i],
+ mBarRect.mBottom + llround(((F32)(MAX_VISIBLE_HISTORY - mHoverBarIndex + 1)) * ((F32)mBarRect.getHeight() / ((F32)MAX_VISIBLE_HISTORY + 2.f))),
+ mBarEnd[mHoverBarIndex][i],
+ mBarRect.mBottom + llround((F32)(MAX_VISIBLE_HISTORY - mHoverBarIndex) * ((F32)mBarRect.getHeight() / ((F32)MAX_VISIBLE_HISTORY + 2.f))));
+ }
+
+ if ((*it)->getCollapsed())
{
- mHoverIndex = i;
+ it.skipDescendants();
}
}
}
else if (x < mBarRect.mLeft)
{
- S32 legend_index = getLegendIndex(y);
- if (legend_index >= 0 && legend_index < FTV_DISPLAY_NUM)
+ LLFastTimer::NamedTimer* timer_id = getLegendID(y);
+ if (timer_id)
+ {
+ mHoverID = timer_id;
+ }
+ }
+
+ return FALSE;
+}
+
+
+BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, MASK mask)
+{
+ if(LLFastTimer::sPauseHistory && mBarRect.pointInRect(x, y))
+ {
+ // tooltips for timer bars
+ if (mHoverTimer)
+ {
+ LLRect screen_rect;
+ localRectToScreen(mToolTipRect, &screen_rect);
+
+ LLToolTipMgr::instance().show(LLToolTip::Params()
+ .message(mHoverTimer->getToolTip(LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex - mHoverBarIndex))
+ .sticky_rect(screen_rect)
+ .delay_time(0.f));
+
+ return TRUE;
+ }
+ }
+ else
+ {
+ // tooltips for timer legend
+ if (x < mBarRect.mLeft)
{
- mHoverIndex = legend_index;
+ LLFastTimer::NamedTimer* idp = getLegendID(y);
+ if (idp)
+ {
+ LLToolTipMgr::instance().show(idp->getToolTip());
+
+ return TRUE;
+ }
}
}
@@ -408,13 +285,18 @@ BOOL LLFastTimerView::handleScrollWheel(S32 x, S32 y, S32 clicks)
{
LLFastTimer::sPauseHistory = TRUE;
mScrollIndex = llclamp(mScrollIndex - clicks,
- 0, llmin(LLFastTimer::sLastFrameIndex, (S32)LLFastTimer::FTM_HISTORY_NUM-MAX_VISIBLE_HISTORY));
+ 0,
+ llmin(LLFastTimer::getLastFrameIndex(), (S32)LLFastTimer::NamedTimer::HISTORY_NUM - MAX_VISIBLE_HISTORY));
return TRUE;
}
+static LLFastTimer::DeclareTimer FTM_RENDER_TIMER("Timers", true);
+
+static std::map<LLFastTimer::NamedTimer*, LLColor4> sTimerColors;
+
void LLFastTimerView::draw()
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_TIMER);
+ LLFastTimer t(FTM_RENDER_TIMER);
std::string tdesc;
@@ -422,62 +304,31 @@ void LLFastTimerView::draw()
F64 iclock_freq = 1000.0 / clock_freq;
S32 margin = 10;
- S32 height = (S32) (gViewerWindow->getVirtualWindowRect().getHeight()*0.75f);
- S32 width = (S32) (gViewerWindow->getVirtualWindowRect().getWidth() * 0.75f);
+ S32 height = (S32) (gViewerWindow->getWindowRectScaled().getHeight()*0.75f);
+ S32 width = (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f);
- // HACK: casting away const. Should use setRect or some helper function instead.
- const_cast<LLRect&>(getRect()).setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height);
+ LLRect new_rect;
+ new_rect.setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height);
+ setRect(new_rect);
S32 left, top, right, bottom;
S32 x, y, barw, barh, dx, dy;
S32 texth, textw;
- LLPointer<LLUIImage> box_imagep = LLUI::getUIImage("rounded_square.tga");
+ LLPointer<LLUIImage> box_imagep = LLUI::getUIImage("Rounded_Square");
- // Make sure all timers are accounted for
- // Set 'FTM_OTHER' to unaccounted ticks last frame
- {
- S32 display_timer[LLFastTimer::FTM_NUM_TYPES];
- S32 hidx = LLFastTimer::sLastFrameIndex % LLFastTimer::FTM_HISTORY_NUM;
- for (S32 i=0; i < LLFastTimer::FTM_NUM_TYPES; i++)
- {
- display_timer[i] = 0;
- }
- for (S32 i=0; i < FTV_DISPLAY_NUM; i++)
- {
- S32 tidx = ft_display_table[i].timer;
- display_timer[tidx] = 1;
- }
- LLFastTimer::sCountHistory[hidx][LLFastTimer::FTM_OTHER] = 0;
- LLFastTimer::sCallHistory[hidx][LLFastTimer::FTM_OTHER] = 0;
- for (S32 tidx = 0; tidx < LLFastTimer::FTM_NUM_TYPES; tidx++)
- {
- U64 counts = LLFastTimer::sCountHistory[hidx][tidx];
- if (counts > 0 && display_timer[tidx] == 0)
- {
- LLFastTimer::sCountHistory[hidx][LLFastTimer::FTM_OTHER] += counts;
- LLFastTimer::sCallHistory[hidx][LLFastTimer::FTM_OTHER] += 1;
- }
- }
- LLFastTimer::sCountAverage[LLFastTimer::FTM_OTHER] = 0;
- LLFastTimer::sCallAverage[LLFastTimer::FTM_OTHER] = 0;
- for (S32 h = 0; h < LLFastTimer::FTM_HISTORY_NUM; h++)
- {
- LLFastTimer::sCountAverage[LLFastTimer::FTM_OTHER] += LLFastTimer::sCountHistory[h][LLFastTimer::FTM_OTHER];
- LLFastTimer::sCallAverage[LLFastTimer::FTM_OTHER] += LLFastTimer::sCallHistory[h][LLFastTimer::FTM_OTHER];
- }
- LLFastTimer::sCountAverage[LLFastTimer::FTM_OTHER] /= LLFastTimer::FTM_HISTORY_NUM;
- LLFastTimer::sCallAverage[LLFastTimer::FTM_OTHER] /= LLFastTimer::FTM_HISTORY_NUM;
- }
-
// Draw the window background
- {
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f));
- }
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f));
S32 xleft = margin;
S32 ytop = margin;
+ mAverageCyclesPerTimer = LLFastTimer::sTimerCalls == 0
+ ? 0
+ : llround(lerp((F32)mAverageCyclesPerTimer, (F32)(LLFastTimer::sTimerCycles / (U64)LLFastTimer::sTimerCalls), 0.1f));
+ LLFastTimer::sTimerCycles = 0;
+ LLFastTimer::sTimerCalls = 0;
+
// Draw some help
{
@@ -485,6 +336,10 @@ void LLFastTimerView::draw()
y = height - ytop;
texth = (S32)LLFontGL::getFontMonospace()->getLineHeight();
+#if TIME_FAST_TIMERS
+ tdesc = llformat("Cycles per timer call: %d", mAverageCyclesPerTimer);
+ LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
+#else
char modedesc[][32] = {
"2 x Average ",
"Max ",
@@ -499,7 +354,6 @@ void LLFastTimerView::draw()
tdesc = llformat("Full bar = %s [Click to pause/reset] [SHIFT-Click to toggle]",modedesc[mDisplayMode]);
LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
-
textw = LLFontGL::getFontMonospace()->getWidth(tdesc);
x = xleft, y -= (texth + 2);
@@ -509,151 +363,139 @@ void LLFastTimerView::draw()
LLFontGL::getFontMonospace()->renderUTF8(std::string("[Right-Click log selected] [ALT-Click toggle counts] [ALT-SHIFT-Click sub hidden]"),
0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
+#endif
y -= (texth + 2);
}
- // Calc the total ticks
- S32 histmax = llmin(LLFastTimer::sLastFrameIndex+1, MAX_VISIBLE_HISTORY);
- U64 ticks_sum[LLFastTimer::FTM_HISTORY_NUM+1][FTV_DISPLAY_NUM];
- for (S32 j=-1; j<LLFastTimer::FTM_HISTORY_NUM; j++)
- {
- S32 hidx;
- if (j >= 0)
- hidx = (LLFastTimer::sLastFrameIndex+j) % LLFastTimer::FTM_HISTORY_NUM;
- else
- hidx = -1;
-
- // calculate tick info by adding child ticks to parents
- for (S32 i=0; i < FTV_DISPLAY_NUM; i++)
- {
- if (mSubtractHidden && ft_display_table[i].disabled > 1)
- {
- continue;
- }
- // Get ticks
- S32 tidx = ft_display_table[i].timer;
- if (hidx >= 0)
- ticks_sum[j+1][i] = LLFastTimer::sCountHistory[hidx][tidx];
- else
- ticks_sum[j+1][i] = LLFastTimer::sCountAverage[tidx];
- S32 pidx = ft_display_table[i].parent;
- // Add ticks to parents
- while (pidx >= 0)
- {
- ticks_sum[j+1][pidx] += ticks_sum[j+1][i];
- pidx = ft_display_table[pidx].parent;
- }
- }
- }
+ S32 histmax = llmin(LLFastTimer::getLastFrameIndex()+1, MAX_VISIBLE_HISTORY);
// Draw the legend
-
- S32 legendwidth = 0;
xleft = margin;
ytop = y;
y -= (texth + 2);
- S32 cur_line = 0;
- S32 display_line[FTV_DISPLAY_NUM];
- for (S32 i=0; i<FTV_DISPLAY_NUM; i++)
+ sTimerColors[&LLFastTimer::NamedTimer::getRootNamedTimer()] = LLColor4::grey;
+
+ F32 hue = 0.f;
+
+ for (timer_tree_iterator_t it = begin_timer_tree(LLFastTimer::NamedTimer::getRootNamedTimer());
+ it != timer_tree_iterator_t();
+ ++it)
{
- S32 disabled = ft_display_table[i].disabled;
- if (disabled == 3)
- {
- continue; // skip row
- }
- display_line[i] = cur_line;
- ft_display_idx[cur_line] = i;
- cur_line++;
- S32 level = ft_display_table[i].level;
- S32 parent = ft_display_table[i].parent;
-
- x = xleft;
+ LLFastTimer::NamedTimer* idp = (*it);
- left = x; right = x + texth;
- top = y; bottom = y - texth;
- S32 scale_offset = 0;
- if (i == mHoverIndex)
- {
- scale_offset = llfloor(sinf(mHighlightTimer.getElapsedTimeF32() * 6.f) * 2.f);
- }
- gl_rect_2d(left - scale_offset, top + scale_offset, right + scale_offset, bottom - scale_offset, *ft_display_table[i].color);
+ const F32 HUE_INCREMENT = 0.23f;
+ hue = fmodf(hue + HUE_INCREMENT, 1.f);
+ // saturation increases with depth
+ F32 saturation = clamp_rescale((F32)idp->getDepth(), 0.f, 3.f, 0.f, 1.f);
+ // lightness alternates with depth
+ F32 lightness = idp->getDepth() % 2 ? 0.5f : 0.6f;
- int tidx = ft_display_table[i].timer;
- F32 ms = 0;
- S32 calls = 0;
- if (mHoverBarIndex > 0 && mHoverIndex >= 0)
- {
- S32 hidx = (LLFastTimer::sLastFrameIndex + (mHoverBarIndex - 1) - mScrollIndex) % LLFastTimer::FTM_HISTORY_NUM;
- S32 bidx = LLFastTimer::FTM_HISTORY_NUM - mScrollIndex - mHoverBarIndex;
- U64 ticks = ticks_sum[bidx+1][i]; // : LLFastTimer::sCountHistory[hidx][tidx];
- ms = (F32)((F64)ticks * iclock_freq);
- calls = (S32)LLFastTimer::sCallHistory[hidx][tidx];
- }
- else
- {
- U64 ticks = ticks_sum[0][i];
- ms = (F32)((F64)ticks * iclock_freq);
- calls = (S32)LLFastTimer::sCallAverage[tidx];
- }
- if (mDisplayCalls)
- {
- tdesc = llformat("%s (%d)",ft_display_table[i].desc,calls);
- }
- else
- {
- tdesc = llformat("%s [%.1f]",ft_display_table[i].desc,ms);
- }
- dx = (texth+4) + level*8;
+ LLColor4 child_color;
+ child_color.setHSL(hue, saturation, lightness);
- LLColor4 color = disabled > 1 ? LLColor4::grey : LLColor4::white;
- if (level > 0)
+ sTimerColors[idp] = child_color;
+ }
+
+ const S32 LEGEND_WIDTH = 220;
+ {
+ LLLocalClipRect clip(LLRect(margin, y, LEGEND_WIDTH, margin));
+ S32 cur_line = 0;
+ ft_display_idx.clear();
+ std::map<LLFastTimer::NamedTimer*, S32> display_line;
+ for (timer_tree_iterator_t it = begin_timer_tree(LLFastTimer::NamedTimer::getRootNamedTimer());
+ it != timer_tree_iterator_t();
+ ++it)
{
- S32 line_start_y = (top + bottom) / 2;
- S32 line_end_y = line_start_y + ((texth + 2) * (display_line[i] - display_line[parent])) - (texth / 2);
- gl_line_2d(x + dx - 8, line_start_y, x + dx, line_start_y, color);
- S32 line_x = x + (texth + 4) + ((level - 1) * 8);
- gl_line_2d(line_x, line_start_y, line_x, line_end_y, color);
- if (disabled == 1)
+ LLFastTimer::NamedTimer* idp = (*it);
+ display_line[idp] = cur_line;
+ ft_display_idx.push_back(idp);
+ cur_line++;
+
+ x = xleft;
+
+ left = x; right = x + texth;
+ top = y; bottom = y - texth;
+ S32 scale_offset = 0;
+ if (idp == mHoverID)
{
- gl_line_2d(line_x+4, line_start_y-3, line_x+4, line_start_y+4, color);
+ scale_offset = llfloor(sinf(mHighlightTimer.getElapsedTimeF32() * 6.f) * 2.f);
}
- }
+ gl_rect_2d(left - scale_offset, top + scale_offset, right + scale_offset, bottom - scale_offset, sTimerColors[idp]);
- x += dx;
- BOOL is_child_of_hover_item = (i == mHoverIndex);
- S32 next_parent = ft_display_table[i].parent;
- while(!is_child_of_hover_item && next_parent >= 0)
- {
- is_child_of_hover_item = (mHoverIndex == next_parent);
- next_parent = ft_display_table[next_parent].parent;
- }
+ F32 ms = 0;
+ S32 calls = 0;
+ if (mHoverBarIndex > 0 && mHoverID)
+ {
+ S32 hidx = LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex - mHoverBarIndex;
+ U64 ticks = idp->getHistoricalCount(hidx);
+ ms = (F32)((F64)ticks * iclock_freq);
+ calls = (S32)idp->getHistoricalCalls(hidx);
+ }
+ else
+ {
+ U64 ticks = idp->getCountAverage();
+ ms = (F32)((F64)ticks * iclock_freq);
+ calls = (S32)idp->getCallAverage();
+ }
- if (is_child_of_hover_item)
- {
- LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, color, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::BOLD);
- }
- else
- {
- LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, color, LLFontGL::LEFT, LLFontGL::TOP);
- }
- y -= (texth + 2);
+ if (mDisplayCalls)
+ {
+ tdesc = llformat("%s (%d)",idp->getName().c_str(),calls);
+ }
+ else
+ {
+ tdesc = llformat("%s [%.1f]",idp->getName().c_str(),ms);
+ }
+ dx = (texth+4) + idp->getDepth()*8;
- textw = dx + LLFontGL::getFontMonospace()->getWidth(std::string(ft_display_table[i].desc)) + 40;
- if (textw > legendwidth)
- legendwidth = textw;
- }
- for (S32 i=cur_line; i<FTV_DISPLAY_NUM; i++)
- {
- ft_display_idx[i] = -1;
+ LLColor4 color = LLColor4::white;
+ if (idp->getDepth() > 0)
+ {
+ S32 line_start_y = (top + bottom) / 2;
+ S32 line_end_y = line_start_y + ((texth + 2) * (cur_line - display_line[idp->getParent()])) - texth;
+ gl_line_2d(x + dx - 8, line_start_y, x + dx, line_start_y, color);
+ S32 line_x = x + (texth + 4) + ((idp->getDepth() - 1) * 8);
+ gl_line_2d(line_x, line_start_y, line_x, line_end_y, color);
+ if (idp->getCollapsed() && !idp->getChildren().empty())
+ {
+ gl_line_2d(line_x+4, line_start_y-3, line_x+4, line_start_y+4, color);
+ }
+ }
+
+ x += dx;
+ BOOL is_child_of_hover_item = (idp == mHoverID);
+ LLFastTimer::NamedTimer* next_parent = idp->getParent();
+ while(!is_child_of_hover_item && next_parent)
+ {
+ is_child_of_hover_item = (mHoverID == next_parent);
+ next_parent = next_parent->getParent();
+ }
+
+ LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0,
+ x, y,
+ color,
+ LLFontGL::LEFT, LLFontGL::TOP,
+ is_child_of_hover_item ? LLFontGL::BOLD : LLFontGL::NORMAL);
+
+ y -= (texth + 2);
+
+ textw = dx + LLFontGL::getFontMonospace()->getWidth(idp->getName()) + 40;
+
+ if (idp->getCollapsed())
+ {
+ it.skipDescendants();
+ }
+ }
}
- xleft += legendwidth + 8;
+
+ xleft += LEGEND_WIDTH + 8;
// ytop = ytop;
// update rectangle that includes timer bars
mBarRect.mLeft = xleft;
- mBarRect.mRight = getRect().mRight - xleft;
+ mBarRect.mRight = getRect().getWidth();
mBarRect.mTop = ytop - ((S32)LLFontGL::getFontMonospace()->getLineHeight() + 4);
mBarRect.mBottom = margin + LINE_GRAPH_HEIGHT;
@@ -665,25 +507,18 @@ void LLFastTimerView::draw()
barw = width - xleft - margin;
// Draw the history bars
- if (LLFastTimer::sLastFrameIndex >= 0)
+ if (LLFastTimer::getLastFrameIndex() >= 0)
{
+ LLLocalClipRect clip(LLRect(xleft, ytop, getRect().getWidth() - margin, margin));
+
U64 totalticks;
if (!LLFastTimer::sPauseHistory)
{
- U64 ticks = 0;
- int hidx = (LLFastTimer::sLastFrameIndex - mScrollIndex) % LLFastTimer::FTM_HISTORY_NUM;
- for (S32 i=0; i<FTV_DISPLAY_NUM; i++)
- {
- if (mSubtractHidden && ft_display_table[i].disabled > 1)
- {
- continue;
- }
- int tidx = ft_display_table[i].timer;
- ticks += LLFastTimer::sCountHistory[hidx][tidx];
- }
- if (LLFastTimer::sCurFrameIndex >= 10)
+ U64 ticks = LLFastTimer::NamedTimer::getRootNamedTimer().getHistoricalCount(mScrollIndex);
+
+ if (LLFastTimer::getCurFrameIndex() >= 10)
{
- U64 framec = LLFastTimer::sCurFrameIndex;
+ U64 framec = LLFastTimer::getCurFrameIndex();
U64 avg = (U64)mAvgCountTotal;
mAvgCountTotal = (avg*framec + ticks) / (framec + 1);
if (ticks > mMaxCountTotal)
@@ -691,11 +526,13 @@ void LLFastTimerView::draw()
mMaxCountTotal = ticks;
}
}
-#if 1
+
if (ticks < mAvgCountTotal/100 || ticks > mAvgCountTotal*100)
- LLFastTimer::sResetHistory = 1;
-#endif
- if (LLFastTimer::sCurFrameIndex < 10 || LLFastTimer::sResetHistory)
+ {
+ LLFastTimer::sResetHistory = true;
+ }
+
+ if (LLFastTimer::getCurFrameIndex() < 10 || LLFastTimer::sResetHistory)
{
mAvgCountTotal = ticks;
mMaxCountTotal = ticks;
@@ -716,16 +553,8 @@ void LLFastTimerView::draw()
totalticks = 0;
for (S32 j=0; j<histmax; j++)
{
- U64 ticks = 0;
- for (S32 i=0; i<FTV_DISPLAY_NUM; i++)
- {
- if (mSubtractHidden && ft_display_table[i].disabled > 1)
- {
- continue;
- }
- int tidx = ft_display_table[i].timer;
- ticks += LLFastTimer::sCountHistory[j][tidx];
- }
+ U64 ticks = LLFastTimer::NamedTimer::getRootNamedTimer().getHistoricalCount(j);
+
if (ticks > totalticks)
totalticks = ticks;
}
@@ -798,18 +627,23 @@ void LLFastTimerView::draw()
gl_rect_2d(graph_rect, FALSE);
}
+ mBarStart.clear();
+ mBarEnd.clear();
+
// Draw bars for each history entry
// Special: -1 = show running average
gGL.getTexUnit(0)->bind(box_imagep->getImage());
for (S32 j=-1; j<histmax && y > LINE_GRAPH_HEIGHT; j++)
{
- int sublevel_dx[FTV_DISPLAY_NUM+1];
- int sublevel_left[FTV_DISPLAY_NUM+1];
- int sublevel_right[FTV_DISPLAY_NUM+1];
+ mBarStart.push_back(std::vector<S32>());
+ mBarEnd.push_back(std::vector<S32>());
+ int sublevel_dx[FTV_MAX_DEPTH];
+ int sublevel_left[FTV_MAX_DEPTH];
+ int sublevel_right[FTV_MAX_DEPTH];
S32 tidx;
if (j >= 0)
{
- tidx = LLFastTimer::FTM_HISTORY_NUM - j - 1 - mScrollIndex;
+ tidx = LLFastTimer::NamedTimer::HISTORY_NUM - j - 1 - mScrollIndex;
}
else
{
@@ -819,88 +653,75 @@ void LLFastTimerView::draw()
x = xleft;
// draw the bars for each stat
- int xpos[FTV_DISPLAY_NUM+1];
- int deltax[FTV_DISPLAY_NUM+1];
- xpos[0] = xleft;
+ std::vector<S32> xpos;
+ std::vector<S32> deltax;
+ xpos.push_back(xleft);
+
+ LLFastTimer::NamedTimer* prev_id = NULL;
- for (S32 i = 0; i < FTV_DISPLAY_NUM; i++)
+ S32 i = 0;
+ for(timer_tree_iterator_t it = begin_timer_tree(LLFastTimer::NamedTimer::getRootNamedTimer());
+ it != end_timer_tree();
+ ++it, ++i)
{
- if (ft_display_table[i].disabled > 1)
- {
- continue;
- }
-
- F32 frac = (F32)ticks_sum[tidx+1][i] / (F32)totalticks;
+ LLFastTimer::NamedTimer* idp = (*it);
+ F32 frac = tidx == -1
+ ? (F32)idp->getCountAverage() / (F32)totalticks
+ : (F32)idp->getHistoricalCount(tidx) / (F32)totalticks;
dx = llround(frac * (F32)barw);
- deltax[i] = dx;
-
- int level = ft_display_table[i].level;
- int parent = ft_display_table[i].parent;
- llassert(level < FTV_DISPLAY_NUM);
- llassert(parent < FTV_DISPLAY_NUM);
+ S32 prev_delta_x = deltax.empty() ? 0 : deltax.back();
+ deltax.push_back(dx);
- left = xpos[level];
+ int level = idp->getDepth() - 1;
- S32 prev_idx = i - 1;
- while (prev_idx > 0)
+ while ((S32)xpos.size() > level + 1)
{
- if (ft_display_table[prev_idx].disabled <= 1)
- {
- break;
- }
- prev_idx--;
+ xpos.pop_back();
}
- S32 next_idx = i + 1;
- while (next_idx < FTV_DISPLAY_NUM)
- {
- if (ft_display_table[next_idx].disabled <= 1)
- {
- break;
- }
- next_idx++;
- }
-
+ left = xpos.back();
+
if (level == 0)
- {
+ {
sublevel_left[level] = xleft;
sublevel_dx[level] = dx;
sublevel_right[level] = sublevel_left[level] + sublevel_dx[level];
- }
- else if (i==0 || ft_display_table[prev_idx].level < level)
+ }
+ else if (prev_id && prev_id->getDepth() < idp->getDepth())
{
- // If we are the first entry at a new sublevel block, calc the
- // total width of this sublevel and modify left to align block.
- U64 sublevelticks = ticks_sum[tidx+1][i];
- for (S32 k=i+1; k<FTV_DISPLAY_NUM; k++)
- {
- if (ft_display_table[k].level < level)
- break;
- if (ft_display_table[k].disabled <= 1 && ft_display_table[k].level == level)
- sublevelticks += ticks_sum[tidx+1][k];
- }
- F32 subfrac = (F32)sublevelticks / (F32)totalticks;
+ U64 sublevelticks = 0;
+
+ for (LLFastTimer::NamedTimer::child_const_iter it = prev_id->beginChildren();
+ it != prev_id->endChildren();
+ ++it)
+ {
+ sublevelticks += (tidx == -1)
+ ? (*it)->getCountAverage()
+ : (*it)->getHistoricalCount(tidx);
+ }
+
+ F32 subfrac = (F32)sublevelticks / (F32)totalticks;
sublevel_dx[level] = (int)(subfrac * (F32)barw + .5f);
- if (mDisplayCenter == 1) // center aligned
+ if (mDisplayCenter == ALIGN_CENTER)
{
- left += (deltax[parent] - sublevel_dx[level])/2;
+ left += (prev_delta_x - sublevel_dx[level])/2;
}
- else if (mDisplayCenter == 2) // right aligned
+ else if (mDisplayCenter == ALIGN_RIGHT)
{
- left += (deltax[parent] - sublevel_dx[level]);
- }
+ left += (prev_delta_x - sublevel_dx[level]);
+ }
sublevel_left[level] = left;
sublevel_right[level] = sublevel_left[level] + sublevel_dx[level];
}
right = left + dx;
- xpos[level] = right;
- xpos[level+1] = left;
+ xpos.back() = right;
+ xpos.push_back(left);
- mBarStart[(j + 1) * FTV_DISPLAY_NUM + i] = left;
- mBarEnd[(j + 1) * FTV_DISPLAY_NUM + i] = right;
+ mBarStart.back().push_back(left);
+ mBarEnd.back().push_back(right);
top = y;
bottom = y - barh;
@@ -908,23 +729,23 @@ void LLFastTimerView::draw()
if (right > left)
{
//U32 rounded_edges = 0;
- LLColor4 color = *ft_display_table[i].color;
+ LLColor4 color = sTimerColors[idp];//*ft_display_table[i].color;
S32 scale_offset = 0;
- BOOL is_child_of_hover_item = (i == mHoverIndex);
- S32 next_parent = ft_display_table[i].parent;
- while(!is_child_of_hover_item && next_parent >= 0)
+ BOOL is_child_of_hover_item = (idp == mHoverID);
+ LLFastTimer::NamedTimer* next_parent = idp->getParent();
+ while(!is_child_of_hover_item && next_parent)
{
- is_child_of_hover_item = (mHoverIndex == next_parent);
- next_parent = ft_display_table[next_parent].parent;
+ is_child_of_hover_item = (mHoverID == next_parent);
+ next_parent = next_parent->getParent();
}
- if (i == mHoverIndex)
+ if (idp == mHoverID)
{
scale_offset = llfloor(sinf(mHighlightTimer.getElapsedTimeF32() * 6.f) * 3.f);
//color = lerp(color, LLColor4::black, -0.4f);
}
- else if (mHoverIndex >= 0 && !is_child_of_hover_item)
+ else if (mHoverID != NULL && !is_child_of_hover_item)
{
color = lerp(color, LLColor4::grey, 0.8f);
}
@@ -935,7 +756,13 @@ void LLFastTimerView::draw()
gl_segmented_rect_2d_fragment_tex(sublevel_left[level], top - level + scale_offset, sublevel_right[level], bottom + level - scale_offset, box_imagep->getTextureWidth(), box_imagep->getTextureHeight(), 16, start_fragment, end_fragment);
}
-
+
+ if ((*it)->getCollapsed())
+ {
+ it.skipDescendants();
+ }
+
+ prev_id = idp;
}
y -= (barh + dy);
if (j < 0)
@@ -970,10 +797,10 @@ void LLFastTimerView::draw()
//highlight visible range
{
- S32 first_frame = LLFastTimer::FTM_HISTORY_NUM - mScrollIndex;
+ S32 first_frame = LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex;
S32 last_frame = first_frame - MAX_VISIBLE_HISTORY;
- F32 frame_delta = ((F32) (graph_rect.getWidth()))/(LLFastTimer::FTM_HISTORY_NUM-1);
+ F32 frame_delta = ((F32) (graph_rect.getWidth()))/(LLFastTimer::NamedTimer::HISTORY_NUM-1);
F32 right = (F32) graph_rect.mLeft + frame_delta*first_frame;
F32 left = (F32) graph_rect.mLeft + frame_delta*last_frame;
@@ -996,28 +823,27 @@ void LLFastTimerView::draw()
}
U64 cur_max = 0;
- for (S32 idx = 0; idx < FTV_DISPLAY_NUM; ++idx)
+ for(timer_tree_iterator_t it = begin_timer_tree(LLFastTimer::NamedTimer::getRootNamedTimer());
+ it != end_timer_tree();
+ ++it)
{
- if (ft_display_table[idx].disabled > 1)
- { //skip disabled timers
- continue;
- }
+ LLFastTimer::NamedTimer* idp = (*it);
//fatten highlighted timer
- if (mHoverIndex == idx)
+ if (mHoverID == idp)
{
gGL.flush();
glLineWidth(3);
}
- const F32 * col = ft_display_table[idx].color->mV;
+ const F32 * col = sTimerColors[idp].mV;// ft_display_table[idx].color->mV;
F32 alpha = 1.f;
- if (mHoverIndex >= 0 &&
- idx != mHoverIndex)
+ if (mHoverID != NULL &&
+ idp != mHoverID)
{ //fade out non-hihglighted timers
- if (ft_display_table[idx].parent != mHoverIndex)
+ if (idp->getParent() != mHoverID)
{
alpha = alpha_interp;
}
@@ -1025,9 +851,9 @@ void LLFastTimerView::draw()
gGL.color4f(col[0], col[1], col[2], alpha);
gGL.begin(LLRender::LINE_STRIP);
- for (U32 j = 0; j < LLFastTimer::FTM_HISTORY_NUM; j++)
+ for (U32 j = 0; j < LLFastTimer::NamedTimer::HISTORY_NUM; j++)
{
- U64 ticks = ticks_sum[j+1][idx];
+ U64 ticks = idp->getHistoricalCount(j);
if (mDisplayHz)
{
@@ -1037,26 +863,31 @@ void LLFastTimerView::draw()
}
else if (mDisplayCalls)
{
- S32 tidx = ft_display_table[idx].timer;
- S32 hidx = (LLFastTimer::sLastFrameIndex + j) % LLFastTimer::FTM_HISTORY_NUM;
- ticks = (S32)LLFastTimer::sCallHistory[hidx][tidx];
+ ticks = (S32)idp->getHistoricalCalls(j);
}
if (alpha == 1.f)
- { //normalize to highlighted timer
+ {
+ //normalize to highlighted timer
cur_max = llmax(cur_max, ticks);
}
- F32 x = graph_rect.mLeft + ((F32) (graph_rect.getWidth()))/(LLFastTimer::FTM_HISTORY_NUM-1)*j;
+ F32 x = graph_rect.mLeft + ((F32) (graph_rect.getWidth()))/(LLFastTimer::NamedTimer::HISTORY_NUM-1)*j;
F32 y = graph_rect.mBottom + (F32) graph_rect.getHeight()/max_ticks*ticks;
gGL.vertex2f(x,y);
}
gGL.end();
- if (mHoverIndex == idx)
+ if (mHoverID == idp)
{
gGL.flush();
glLineWidth(1);
}
+
+ if (idp->getCollapsed())
+ {
+ //skip hidden timers
+ it.skipDescendants();
+ }
}
//interpolate towards new maximum
@@ -1068,12 +899,16 @@ void LLFastTimerView::draw()
alpha_interp = alpha_interp + (alpha_target-alpha_interp) * dt;
- if (mHoverIndex >= 0)
+ if (mHoverID != NULL)
{
x = (graph_rect.mRight + graph_rect.mLeft)/2;
y = graph_rect.mBottom + 8;
- LLFontGL::getFontMonospace()->renderUTF8(std::string(ft_display_table[mHoverIndex].desc), 0, x, y, LLColor4::white,
+ LLFontGL::getFontMonospace()->renderUTF8(
+ mHoverID->getName(),
+ 0,
+ x, y,
+ LLColor4::white,
LLFontGL::LEFT, LLFontGL::BOTTOM);
}
}
@@ -1083,87 +918,278 @@ void LLFastTimerView::draw()
if (mPrintStats >= 0)
{
std::string legend_stat;
- S32 stat_num;
- S32 first = 1;
- for (stat_num = 0; stat_num < FTV_DISPLAY_NUM; stat_num++)
+ bool first = true;
+ for(timer_tree_iterator_t it = begin_timer_tree(LLFastTimer::NamedTimer::getRootNamedTimer());
+ it != end_timer_tree();
+ ++it)
{
- if (ft_display_table[stat_num].disabled > 1)
- continue;
+ LLFastTimer::NamedTimer* idp = (*it);
+
if (!first)
+ {
legend_stat += ", ";
- first=0;
- legend_stat += ft_display_table[stat_num].desc;
+ }
+ first = true;
+ legend_stat += idp->getName();
+
+ if (idp->getCollapsed())
+ {
+ it.skipDescendants();
+ }
}
llinfos << legend_stat << llendl;
std::string timer_stat;
- first = 1;
- for (stat_num = 0; stat_num < FTV_DISPLAY_NUM; stat_num++)
+ first = true;
+ for(timer_tree_iterator_t it = begin_timer_tree(LLFastTimer::NamedTimer::getRootNamedTimer());
+ it != end_timer_tree();
+ ++it)
{
- S32 disabled = ft_display_table[stat_num].disabled;
- if (disabled > 1)
- continue;
+ LLFastTimer::NamedTimer* idp = (*it);
+
if (!first)
+ {
timer_stat += ", ";
- first=0;
+ }
+ first = false;
+
U64 ticks;
- S32 tidx = ft_display_table[stat_num].timer;
if (mPrintStats > 0)
{
- S32 hidx = (LLFastTimer::sLastFrameIndex+(mPrintStats-1)-mScrollIndex) % LLFastTimer::FTM_HISTORY_NUM;
- ticks = disabled >= 1 ? ticks_sum[mPrintStats][stat_num] : LLFastTimer::sCountHistory[hidx][tidx];
+ S32 hidx = (mPrintStats - 1) - mScrollIndex;
+ ticks = idp->getHistoricalCount(hidx);
}
else
{
- ticks = disabled >= 1 ? ticks_sum[0][stat_num] : LLFastTimer::sCountAverage[tidx];
+ ticks = idp->getCountAverage();
}
F32 ms = (F32)((F64)ticks * iclock_freq);
timer_stat += llformat("%.1f",ms);
+
+ if (idp->getCollapsed())
+ {
+ it.skipDescendants();
+ }
}
llinfos << timer_stat << llendl;
mPrintStats = -1;
}
- mHoverIndex = -1;
+ mHoverID = NULL;
mHoverBarIndex = -1;
LLView::draw();
}
-F64 LLFastTimerView::getTime(LLFastTimer::EFastTimerType tidx)
+F64 LLFastTimerView::getTime(const std::string& name)
{
- // Find table index
- S32 i;
- for (i=0; i<FTV_DISPLAY_NUM; i++)
+ const LLFastTimer::NamedTimer* timerp = LLFastTimer::getTimerByName(name);
+ if (timerp)
+ {
+ return (F64)timerp->getCountAverage() / (F64)LLFastTimer::countsPerSecond();
+ }
+ return 0.0;
+}
+
+//static
+LLSD LLFastTimerView::analyzePerformanceLogDefault(std::istream& is)
+{
+ LLSD ret;
+
+ LLSD cur;
+
+ LLSD::Real total_time = 0.0;
+ LLSD::Integer total_frames = 0;
+
+ while (!is.eof() && LLSDSerialize::fromXML(cur, is))
{
- if (tidx == ft_display_table[i].timer)
+ for (LLSD::map_iterator iter = cur.beginMap(); iter != cur.endMap(); ++iter)
{
- break;
+ std::string label = iter->first;
+
+ F64 time = iter->second["Time"].asReal();
+
+ // Skip the total figure
+ if(label.compare("Total") != 0)
+ {
+ total_time += time;
+ }
+
+ if (time > 0.0)
+ {
+ ret[label]["TotalTime"] = ret[label]["TotalTime"].asReal() + time;
+ ret[label]["MaxTime"] = llmax(time, ret[label]["MaxTime"].asReal());
+
+ if (ret[label]["MinTime"].asReal() == 0)
+ {
+ ret[label]["MinTime"] = time;
+ }
+ else
+ {
+ ret[label]["MinTime"] = llmin(ret[label]["MinTime"].asReal(), time);
+ }
+
+ LLSD::Integer samples = iter->second["Calls"].asInteger();
+
+ ret[label]["Samples"] = ret[label]["Samples"].asInteger() + samples;
+ ret[label]["MaxSamples"] = llmax(ret[label]["MaxSamples"].asInteger(), samples);
+
+ if (ret[label]["MinSamples"].asInteger() == 0)
+ {
+ ret[label]["MinSamples"] = samples;
+ }
+ else
+ {
+ ret[label]["MinSamples"] = llmin(ret[label]["MinSamples"].asInteger(), samples);
+ }
+ }
}
+ total_frames++;
}
+
+ ret["SessionTime"] = total_time;
+ ret["FrameCount"] = total_frames;
+
+ return ret;
+
+}
+
+//static
+void LLFastTimerView::doAnalysisDefault(std::string baseline, std::string target, std::string output)
+{
+
+ //analyze baseline
+ std::ifstream base_is(baseline.c_str());
+ LLSD base = analyzePerformanceLogDefault(base_is);
+ base_is.close();
+
+ //analyze current
+ std::ifstream target_is(target.c_str());
+ LLSD current = analyzePerformanceLogDefault(target_is);
+ target_is.close();
+
+ //output comparision
+ std::ofstream os(output.c_str());
- if (i == FTV_DISPLAY_NUM)
+ LLSD::Real session_time = current["SessionTime"].asReal();
+
+ os << "Label, % Change, % of Session, Cur Min, Cur Max, Cur Mean, Cur Total, Cur Samples, Base Min, Base Max, Base Mean, Base Total, Base Samples\n";
+ for (LLSD::map_iterator iter = base.beginMap(); iter != base.endMap(); ++iter)
{
- // walked off the end of ft_display_table without finding
- // the desired timer type
- llwarns << "Timer type " << tidx << " not known." << llendl;
- return F64(0.0);
+ LLSD::String label = iter->first;
+
+ if (current[label]["Samples"].asInteger() == 0 ||
+ base[label]["Samples"].asInteger() == 0)
+ {
+ //cannot compare
+ continue;
+ }
+ LLSD::Real a = base[label]["TotalTime"].asReal() / base[label]["Samples"].asReal();
+ LLSD::Real b = current[label]["TotalTime"].asReal() / base[label]["Samples"].asReal();
+
+ LLSD::Real diff = b-a;
+
+ LLSD::Real perc = diff/a * 100;
+
+ os << llformat("%s, %.2f, %.4f, %.4f, %.4f, %.4f, %.4f, %d, %.4f, %.4f, %.4f, %.4f, %d\n",
+ label.c_str(),
+ (F32) perc,
+ (F32) (current[label]["TotalTime"].asReal()/session_time * 100.0),
+ (F32) current[label]["MinTime"].asReal(),
+ (F32) current[label]["MaxTime"].asReal(),
+ (F32) b,
+ (F32) current[label]["TotalTime"].asReal(),
+ current[label]["Samples"].asInteger(),
+ (F32) base[label]["MinTime"].asReal(),
+ (F32) base[label]["MaxTime"].asReal(),
+ (F32) a,
+ (F32) base[label]["TotalTime"].asReal(),
+ base[label]["Samples"].asInteger());
}
- S32 table_idx = i;
- // Add child ticks to parent
- U64 ticks = LLFastTimer::sCountAverage[tidx];
- S32 level = ft_display_table[table_idx].level;
- for (i=table_idx+1; i<FTV_DISPLAY_NUM; i++)
+ os.flush();
+ os.close();
+}
+
+//-------------------------
+//static
+LLSD LLFastTimerView::analyzeMetricPerformanceLog(std::istream& is)
+{
+ LLSD ret;
+ LLSD cur;
+
+ while (!is.eof() && LLSDSerialize::fromXML(cur, is))
{
- if (ft_display_table[i].level <= level)
+ for (LLSD::map_iterator iter = cur.beginMap(); iter != cur.endMap(); ++iter)
{
- break;
+ std::string label = iter->first;
+
+ LLMetricPerformanceTester* tester = LLMetricPerformanceTester::getTester(iter->second["Name"].asString()) ;
+ if(tester)
+ {
+ ret[label]["Name"] = iter->second["Name"] ;
+
+ S32 num_of_strings = tester->getNumOfMetricStrings() ;
+ for(S32 index = 0 ; index < num_of_strings ; index++)
+ {
+ ret[label][ tester->getMetricString(index) ] = iter->second[ tester->getMetricString(index) ] ;
+ }
+ }
}
- ticks += LLFastTimer::sCountAverage[ft_display_table[i].timer];
+ }
+
+ return ret;
+}
+
+//static
+void LLFastTimerView::doAnalysisMetrics(std::string baseline, std::string target, std::string output)
+{
+ if(!LLMetricPerformanceTester::hasMetricPerformanceTesters())
+ {
+ return ;
+ }
+
+ //analyze baseline
+ std::ifstream base_is(baseline.c_str());
+ LLSD base = analyzeMetricPerformanceLog(base_is);
+ base_is.close();
+
+ //analyze current
+ std::ifstream target_is(target.c_str());
+ LLSD current = analyzeMetricPerformanceLog(target_is);
+ target_is.close();
+
+ //output comparision
+ std::ofstream os(output.c_str());
+
+ os << "Label, Metric, Base(B), Target(T), Diff(T-B), Percentage(100*T/B)\n";
+ for(LLMetricPerformanceTester::name_tester_map_t::iterator iter = LLMetricPerformanceTester::sTesterMap.begin() ;
+ iter != LLMetricPerformanceTester::sTesterMap.end() ; ++iter)
+ {
+ LLMetricPerformanceTester* tester = ((LLMetricPerformanceTester*)iter->second) ;
+ tester->analyzePerformance(&os, &base, &current) ;
+ }
+
+ os.flush();
+ os.close();
+}
+
+//static
+void LLFastTimerView::doAnalysis(std::string baseline, std::string target, std::string output)
+{
+ if(LLFastTimer::sLog)
+ {
+ doAnalysisDefault(baseline, target, output) ;
+ return ;
}
- return (F64)ticks / (F64)LLFastTimer::countsPerSecond();
+ if(LLFastTimer::sMetricLog)
+ {
+ doAnalysisMetrics(baseline, target, output) ;
+ return ;
+ }
}
+
+
diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h
index 86fc194610..f5c8f23818 100644
--- a/indra/newview/llfasttimerview.h
+++ b/indra/newview/llfasttimerview.h
@@ -34,40 +34,64 @@
#define LL_LLFASTTIMERVIEW_H
#include "llfloater.h"
-#include "llframetimer.h"
+#include "llfasttimer.h"
class LLFastTimerView : public LLFloater
{
public:
- LLFastTimerView(const std::string& name, const LLRect& rect);
- virtual ~LLFastTimerView();
+ LLFastTimerView(const LLRect& rect);
+
+ static BOOL sAnalyzePerformance;
+
+ static void doAnalysis(std::string baseline, std::string target, std::string output);
+
+private:
+ static void doAnalysisDefault(std::string baseline, std::string target, std::string output) ;
+ static void doAnalysisMetrics(std::string baseline, std::string target, std::string output) ;
+ static LLSD analyzeMetricPerformanceLog(std::istream& is) ;
+ static LLSD analyzePerformanceLogDefault(std::istream& is) ;
+
+public:
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
virtual void draw();
- S32 getLegendIndex(S32 y);
- F64 getTime(LLFastTimer::EFastTimerType tidx);
+ LLFastTimer::NamedTimer* getLegendID(S32 y);
+ F64 getTime(const std::string& name);
private:
- S32* mBarStart;
- S32* mBarEnd;
+ typedef std::vector<std::vector<S32> > bar_positions_t;
+ bar_positions_t mBarStart;
+ bar_positions_t mBarEnd;
S32 mDisplayMode;
- S32 mDisplayCenter;
+
+ typedef enum child_alignment
+ {
+ ALIGN_LEFT,
+ ALIGN_CENTER,
+ ALIGN_RIGHT,
+ ALIGN_COUNT
+ } ChildAlignment;
+
+ ChildAlignment mDisplayCenter;
S32 mDisplayCalls;
S32 mDisplayHz;
U64 mAvgCountTotal;
U64 mMaxCountTotal;
LLRect mBarRect;
S32 mScrollIndex;
- S32 mHoverIndex;
+ LLFastTimer::NamedTimer* mHoverID;
+ LLFastTimer::NamedTimer* mHoverTimer;
+ LLRect mToolTipRect;
S32 mHoverBarIndex;
LLFrameTimer mHighlightTimer;
- S32 mSubtractHidden;
S32 mPrintStats;
+ S32 mAverageCyclesPerTimer;
};
#endif
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
new file mode 100644
index 0000000000..0e42ff09d8
--- /dev/null
+++ b/indra/newview/llfavoritesbar.cpp
@@ -0,0 +1,1228 @@
+/**
+ * @file llfavoritesbar.cpp
+ * @brief LLFavoritesBarCtrl class implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfavoritesbar.h"
+
+#include "llbutton.h"
+#include "llfloaterreg.h"
+#include "llfocusmgr.h"
+#include "llinventory.h"
+#include "lllandmarkactions.h"
+#include "lltrans.h"
+#include "lluictrlfactory.h"
+#include "llmenugl.h"
+#include "lltooltip.h"
+
+#include "llagent.h"
+#include "llclipboard.h"
+#include "llinventoryclipboard.h"
+#include "llinventorybridge.h"
+#include "llinventorymodel.h"
+#include "llfloaterworldmap.h"
+#include "lllandmarkactions.h"
+#include "llnotificationsutil.h"
+#include "llsidetray.h"
+#include "lltoggleablemenu.h"
+#include "llviewerinventory.h"
+#include "llviewermenu.h"
+#include "llviewermenu.h"
+#include "lltooldraganddrop.h"
+
+static LLDefaultChildRegistry::Register<LLFavoritesBarCtrl> r("favorites_bar");
+
+const S32 DROP_DOWN_MENU_WIDTH = 250;
+
+/**
+ * Helper for LLFavoriteLandmarkButton and LLFavoriteLandmarkMenuItem.
+ * Performing requests for SLURL for given Landmark ID
+ */
+class LLLandmarkInfoGetter
+{
+public:
+ LLLandmarkInfoGetter()
+ : mLandmarkID(LLUUID::null),
+ mName("(Loading...)"),
+ mPosX(0),
+ mPosY(0),
+ mPosZ(0),
+ mLoaded(false)
+ {}
+
+ void setLandmarkID(const LLUUID& id) { mLandmarkID = id; }
+ const LLUUID& getLandmarkId() const { return mLandmarkID; }
+
+ const std::string& getName()
+ {
+ if(!mLoaded)
+ requestNameAndPos();
+
+ return mName;
+ }
+
+ S32 getPosX()
+ {
+ if (!mLoaded)
+ requestNameAndPos();
+ return mPosX;
+ }
+
+ S32 getPosY()
+ {
+ if (!mLoaded)
+ requestNameAndPos();
+ return mPosY;
+ }
+
+ S32 getPosZ()
+ {
+ if (!mLoaded)
+ requestNameAndPos();
+ return mPosZ;
+ }
+
+private:
+ /**
+ * Requests landmark data from server.
+ */
+ void requestNameAndPos()
+ {
+ if (mLandmarkID.isNull())
+ return;
+
+ LLVector3d g_pos;
+ if(LLLandmarkActions::getLandmarkGlobalPos(mLandmarkID, g_pos))
+ {
+ LLLandmarkActions::getRegionNameAndCoordsFromPosGlobal(g_pos,
+ boost::bind(&LLLandmarkInfoGetter::landmarkNameCallback, this, _1, _2, _3, _4));
+ }
+ }
+
+ void landmarkNameCallback(const std::string& name, S32 x, S32 y, S32 z)
+ {
+ mPosX = x;
+ mPosY = y;
+ mPosZ = z;
+ mName = name;
+ mLoaded = true;
+ }
+
+ LLUUID mLandmarkID;
+ std::string mName;
+ S32 mPosX;
+ S32 mPosY;
+ S32 mPosZ;
+ bool mLoaded;
+};
+
+/**
+ * This class is needed to override LLButton default handleToolTip function and
+ * show SLURL as button tooltip.
+ * *NOTE: dzaporozhan: This is a workaround. We could set tooltips for buttons
+ * in createButtons function but landmark data is not available when Favorites Bar is
+ * created. Thats why we are requesting landmark data after
+ */
+class LLFavoriteLandmarkButton : public LLButton
+{
+public:
+
+ BOOL handleToolTip(S32 x, S32 y, MASK mask)
+ {
+ std::string region_name = mLandmarkInfoGetter.getName();
+
+ if (!region_name.empty())
+ {
+ LLToolTip::Params params;
+ std::string extra_message = llformat("%s (%d, %d, %d)", region_name.c_str(),
+ mLandmarkInfoGetter.getPosX(), mLandmarkInfoGetter.getPosY(), mLandmarkInfoGetter.getPosZ());
+
+ params.message = llformat("%s\n%s", getLabelSelected().c_str(), extra_message.c_str());
+
+ LLRect rect = calcScreenRect();
+ LLFontGL* standart_font = LLFontGL::getFontSansSerif();
+ if(standart_font)
+ {
+ S32 w = llmax((S32)(standart_font->getWidthF32(getLabelSelected())+0.5),(S32)(standart_font->getWidthF32(extra_message)+0.5));
+ rect.mRight = rect.mLeft + w;
+ params.max_width = w;
+ }
+
+ params.sticky_rect = rect;
+
+ LLToolTipMgr::instance().show(params);
+ }
+ return TRUE;
+ }
+
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask)
+ {
+ LLFavoritesBarCtrl* fb = dynamic_cast<LLFavoritesBarCtrl*>(getParent());
+
+ if (fb)
+ {
+ fb->handleHover(x, y, mask);
+ }
+
+ return LLButton::handleHover(x, y, mask);
+ }
+
+ void setLandmarkID(const LLUUID& id){ mLandmarkInfoGetter.setLandmarkID(id); }
+ const LLUUID& getLandmarkId() const { return mLandmarkInfoGetter.getLandmarkId(); }
+
+ void onMouseEnter(S32 x, S32 y, MASK mask)
+ {
+ if (LLToolDragAndDrop::getInstance()->hasMouseCapture())
+ {
+ LLUICtrl::onMouseEnter(x, y, mask);
+ }
+ else
+ {
+ LLButton::onMouseEnter(x, y, mask);
+ }
+ }
+
+protected:
+ LLFavoriteLandmarkButton(const LLButton::Params& p) : LLButton(p) {}
+ friend class LLUICtrlFactory;
+
+private:
+ LLLandmarkInfoGetter mLandmarkInfoGetter;
+};
+
+/**
+ * This class is needed to override LLMenuItemCallGL default handleToolTip function and
+ * show SLURL as button tooltip.
+ * *NOTE: dzaporozhan: This is a workaround. We could set tooltips for buttons
+ * in showDropDownMenu function but landmark data is not available when Favorites Bar is
+ * created. Thats why we are requesting landmark data after
+ */
+class LLFavoriteLandmarkMenuItem : public LLMenuItemCallGL
+{
+public:
+ BOOL handleToolTip(S32 x, S32 y, MASK mask)
+ {
+ std::string region_name = mLandmarkInfoGetter.getName();
+ if (!region_name.empty())
+ {
+ LLToolTip::Params params;
+ params.message = llformat("%s\n%s (%d, %d)", getLabel().c_str(), region_name.c_str(), mLandmarkInfoGetter.getPosX(), mLandmarkInfoGetter.getPosY());
+ params.sticky_rect = calcScreenRect();
+ LLToolTipMgr::instance().show(params);
+ }
+ return TRUE;
+ }
+
+ void setLandmarkID(const LLUUID& id){ mLandmarkInfoGetter.setLandmarkID(id); }
+
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask)
+ {
+ if (mMouseDownSignal)
+ (*mMouseDownSignal)(this, x, y, mask);
+ return LLMenuItemCallGL::handleMouseDown(x, y, mask);
+ }
+
+ virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask)
+ {
+ if (mMouseUpSignal)
+ (*mMouseUpSignal)(this, x, y, mask);
+ return LLMenuItemCallGL::handleMouseUp(x, y, mask);
+ }
+
+ virtual BOOL handleHover(S32 x, S32 y, MASK mask)
+ {
+ if (fb)
+ {
+ fb->handleHover(x, y, mask);
+ }
+
+ return TRUE;
+ }
+
+ void initFavoritesBarPointer(LLFavoritesBarCtrl* fb) { this->fb = fb; }
+
+protected:
+
+ LLFavoriteLandmarkMenuItem(const LLMenuItemCallGL::Params& p) : LLMenuItemCallGL(p) {}
+ friend class LLUICtrlFactory;
+
+private:
+ LLLandmarkInfoGetter mLandmarkInfoGetter;
+ LLFavoritesBarCtrl* fb;
+};
+
+/**
+ * This class was introduced just for fixing the following issue:
+ * EXT-836 Nav bar: Favorites overflow menu passes left-mouse click through.
+ * We must explicitly handle drag and drop event by returning TRUE
+ * because otherwise LLToolDragAndDrop will initiate drag and drop operation
+ * with the world.
+ */
+class LLFavoriteLandmarkToggleableMenu : public LLToggleableMenu
+{
+public:
+ virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg)
+ {
+ *accept = ACCEPT_NO;
+ return TRUE;
+ }
+
+protected:
+ LLFavoriteLandmarkToggleableMenu(const LLToggleableMenu::Params& p):
+ LLToggleableMenu(p)
+ {
+ }
+
+ friend class LLUICtrlFactory;
+};
+
+/**
+ * This class is needed to update an item being copied to the favorites folder
+ * with a sort field value (required to save favorites bar's tabs order).
+ * See method handleNewFavoriteDragAndDrop for more details on how this class is used.
+ */
+class LLItemCopiedCallback : public LLInventoryCallback
+{
+public:
+ LLItemCopiedCallback(S32 sortField): mSortField(sortField) {}
+
+ virtual void fire(const LLUUID& inv_item)
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(inv_item);
+
+ if (item)
+ {
+ item->setSortField(mSortField);
+ item->setComplete(TRUE);
+ item->updateServer(FALSE);
+
+ gInventory.updateItem(item);
+ gInventory.notifyObservers();
+ }
+
+ LLView::getWindow()->setCursor(UI_CURSOR_ARROW);
+ }
+
+private:
+ S32 mSortField;
+};
+
+// updateButtons's helper
+struct LLFavoritesSort
+{
+ // Sorting by creation date and name
+ // TODO - made it customizible using gSavedSettings
+ bool operator()(const LLViewerInventoryItem* const& a, const LLViewerInventoryItem* const& b)
+ {
+ S32 sortField1 = a->getSortField();
+ S32 sortField2 = b->getSortField();
+
+ if (!(sortField1 < 0 && sortField2 < 0))
+ {
+ return sortField2 > sortField1;
+ }
+
+ time_t first_create = a->getCreationDate();
+ time_t second_create = b->getCreationDate();
+ if (first_create == second_create)
+ {
+ return (LLStringUtil::compareDict(a->getName(), b->getName()) < 0);
+ }
+ else
+ {
+ return (first_create > second_create);
+ }
+ }
+};
+
+LLFavoritesBarCtrl::Params::Params()
+: image_drag_indication("image_drag_indication"),
+ chevron_button("chevron_button")
+{
+}
+
+LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p)
+: LLUICtrl(p),
+ mFont(p.font.isProvided() ? p.font() : LLFontGL::getFontSansSerifSmall()),
+ mPopupMenuHandle(),
+ mInventoryItemsPopupMenuHandle(),
+ mImageDragIndication(p.image_drag_indication),
+ mShowDragMarker(FALSE),
+ mLandingTab(NULL),
+ mLastTab(NULL),
+ mTabsHighlightEnabled(TRUE)
+ , mUpdateDropDownItems(true)
+{
+ // Register callback for menus with current registrar (will be parent panel's registrar)
+ LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Favorites.DoToSelected",
+ boost::bind(&LLFavoritesBarCtrl::doToSelected, this, _2));
+
+ // Add this if we need to selectively enable items
+ LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Favorites.EnableSelected",
+ boost::bind(&LLFavoritesBarCtrl::enableSelected, this, _2));
+
+ gInventory.addObserver(this);
+
+ //make chevron button
+ LLButton::Params chevron_button_params(p.chevron_button);
+ chevron_button_params.click_callback.function(boost::bind(&LLFavoritesBarCtrl::showDropDownMenu, this));
+ mChevronButton = LLUICtrlFactory::create<LLButton> (chevron_button_params);
+ addChild(mChevronButton);
+}
+
+LLFavoritesBarCtrl::~LLFavoritesBarCtrl()
+{
+ gInventory.removeObserver(this);
+
+ LLView::deleteViewByHandle(mPopupMenuHandle);
+ LLView::deleteViewByHandle(mInventoryItemsPopupMenuHandle);
+}
+
+BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg)
+{
+ *accept = ACCEPT_NO;
+
+ switch (cargo_type)
+ {
+
+ case DAD_LANDMARK:
+ {
+ /*
+ * add a callback to the end drag event.
+ * the callback will disconnet itself immediately after execution
+ * this is done because LLToolDragAndDrop is a common tool so it shouldn't
+ * be overloaded with redundant callbacks.
+ */
+ if (!mEndDragConnection.connected())
+ {
+ mEndDragConnection = LLToolDragAndDrop::getInstance()->setEndDragCallback(boost::bind(&LLFavoritesBarCtrl::onEndDrag, this));
+ }
+
+ // Copy the item into the favorites folder (if it's not already there).
+ LLInventoryItem *item = (LLInventoryItem *)cargo_data;
+
+ if (LLFavoriteLandmarkButton* dest = dynamic_cast<LLFavoriteLandmarkButton*>(findChildByLocalCoords(x, y)))
+ {
+ setLandingTab(dest);
+ }
+ /*
+ * the condition dest == NULL can be satisfied not only in the case
+ * of dragging to the right from the last tab of the favbar. there is a
+ * small gap between each tab. if the user drags something exactly there
+ * then mLandingTab will be set to NULL and the dragged item will be pushed
+ * to the end of the favorites bar. this is incorrect behavior. that's why
+ * we need an additional check which excludes the case described previously
+ * making sure that the mouse pointer is beyond the last tab.
+ */
+ else if (mLastTab && x >= mLastTab->getRect().mRight)
+ {
+ setLandingTab(NULL);
+ }
+
+ // check if we are dragging an existing item from the favorites bar
+ if (item && mDragItemId == item->getUUID())
+ {
+ *accept = ACCEPT_YES_SINGLE;
+
+ showDragMarker(TRUE);
+
+ if (drop)
+ {
+ handleExistingFavoriteDragAndDrop(x, y);
+ showDragMarker(FALSE);
+ }
+ }
+ else
+ {
+ const LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+ if (item->getParentUUID() == favorites_id)
+ {
+ llwarns << "Attemt to copy a favorite item into the same folder." << llendl;
+ break;
+ }
+
+ *accept = ACCEPT_YES_COPY_MULTI;
+
+ showDragMarker(TRUE);
+
+ if (drop)
+ {
+ if (mItems.empty())
+ {
+ setLandingTab(NULL);
+ }
+ handleNewFavoriteDragAndDrop(item, favorites_id, x, y);
+ showDragMarker(FALSE);
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+void LLFavoritesBarCtrl::handleExistingFavoriteDragAndDrop(S32 x, S32 y)
+{
+ LLFavoriteLandmarkButton* dest = dynamic_cast<LLFavoriteLandmarkButton*>(mLandingTab);
+
+ // there is no need to handle if an item was dragged onto itself
+ if (dest && dest->getLandmarkId() == mDragItemId)
+ {
+ return;
+ }
+
+ if (dest)
+ {
+ LLInventoryModel::updateItemsOrder(mItems, mDragItemId, dest->getLandmarkId());
+ }
+ else
+ {
+ mItems.push_back(gInventory.getItem(mDragItemId));
+ }
+
+ gInventory.saveItemsOrder(mItems);
+
+ LLToggleableMenu* menu = (LLToggleableMenu*) mPopupMenuHandle.get();
+
+ if (menu && menu->getVisible())
+ {
+ menu->setVisible(FALSE);
+ showDropDownMenu();
+ }
+}
+
+void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, const LLUUID& favorites_id, S32 x, S32 y)
+{
+ LLFavoriteLandmarkButton* dest = dynamic_cast<LLFavoriteLandmarkButton*>(mLandingTab);
+
+ // there is no need to handle if an item was dragged onto itself
+ if (dest && dest->getLandmarkId() == mDragItemId)
+ {
+ return;
+ }
+
+ LLPointer<LLViewerInventoryItem> viewer_item = new LLViewerInventoryItem(item);
+
+ if (dest)
+ {
+ insertBeforeItem(mItems, dest->getLandmarkId(), viewer_item);
+ }
+ else
+ {
+ mItems.push_back(viewer_item);
+ }
+
+ int sortField = 0;
+ LLPointer<LLItemCopiedCallback> cb;
+
+ // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field
+ for (LLInventoryModel::item_array_t::iterator i = mItems.begin(); i != mItems.end(); ++i)
+ {
+ LLViewerInventoryItem* currItem = *i;
+
+ if (currItem->getUUID() == item->getUUID())
+ {
+ cb = new LLItemCopiedCallback(++sortField);
+ }
+ else
+ {
+ currItem->setSortField(++sortField);
+ currItem->setComplete(TRUE);
+ currItem->updateServer(FALSE);
+
+ gInventory.updateItem(currItem);
+ }
+ }
+
+ LLToolDragAndDrop* tool_dad = LLToolDragAndDrop::getInstance();
+ if (tool_dad->getSource() == LLToolDragAndDrop::SOURCE_NOTECARD)
+ {
+ viewer_item->setType(LLAssetType::AT_LANDMARK);
+ copy_inventory_from_notecard(tool_dad->getObjectID(), tool_dad->getSourceID(), viewer_item.get(), gInventoryCallbacks.registerCB(cb));
+ }
+ else
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ favorites_id,
+ std::string(),
+ cb);
+ }
+
+ llinfos << "Copied inventory item #" << item->getUUID() << " to favorites." << llendl;
+}
+
+//virtual
+void LLFavoritesBarCtrl::changed(U32 mask)
+{
+ if (mFavoriteFolderId.isNull())
+ {
+ mFavoriteFolderId = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+
+ if (mFavoriteFolderId.notNull())
+ {
+ gInventory.fetchDescendentsOf(mFavoriteFolderId);
+ }
+ }
+ else
+ {
+ updateButtons();
+ }
+}
+
+//virtual
+void LLFavoritesBarCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ LLUICtrl::reshape(width, height, called_from_parent);
+ updateButtons();
+}
+
+void LLFavoritesBarCtrl::draw()
+{
+ LLUICtrl::draw();
+
+ if (mShowDragMarker)
+ {
+ S32 w = mImageDragIndication->getWidth() / 2;
+ S32 h = mImageDragIndication->getHeight() / 2;
+
+ if (mLandingTab)
+ {
+ // mouse pointer hovers over an existing tab
+ LLRect rect = mLandingTab->getRect();
+ mImageDragIndication->draw(rect.mLeft - w/2, rect.getHeight(), w, h);
+ }
+ else if (mLastTab)
+ {
+ // mouse pointer hovers over the favbar empty space (right to the last tab)
+ LLRect rect = mLastTab->getRect();
+ mImageDragIndication->draw(rect.mRight, rect.getHeight(), w, h);
+ }
+ }
+}
+
+LLXMLNodePtr LLFavoritesBarCtrl::getButtonXMLNode()
+{
+ LLXMLNodePtr buttonXMLNode = NULL;
+ bool success = LLUICtrlFactory::getLayeredXMLNode("favorites_bar_button.xml", buttonXMLNode);
+ if (!success)
+ {
+ llwarns << "Failed to create Favorites Bar button from favorites_bar_button.xml" << llendl;
+ buttonXMLNode = NULL;
+ }
+ return buttonXMLNode;
+}
+
+void LLFavoritesBarCtrl::updateButtons()
+{
+ mItems.clear();
+
+ if (!collectFavoriteItems(mItems))
+ {
+ return;
+ }
+
+ static LLXMLNodePtr buttonXMLNode = getButtonXMLNode();
+ if (buttonXMLNode.isNull())
+ {
+ return;
+ }
+
+ const child_list_t* childs = getChildList();
+ child_list_const_iter_t child_it = childs->begin();
+ int first_changed_item_index = 0;
+ int rightest_point = getRect().mRight - mChevronButton->getRect().getWidth();
+ //lets find first changed button
+ while (child_it != childs->end() && first_changed_item_index < mItems.count())
+ {
+ LLFavoriteLandmarkButton* button = dynamic_cast<LLFavoriteLandmarkButton*> (*child_it);
+ if (button)
+ {
+ const LLViewerInventoryItem *item = mItems[first_changed_item_index].get();
+ if (item)
+ {
+ // an child's order and mItems should be same
+ if (button->getLandmarkId() != item->getUUID() // sort order has been changed
+ || button->getLabelSelected() != item->getDisplayName() // favorite's name has been changed
+ || button->getRect().mRight < rightest_point) // favbar's width has been changed
+ {
+ break;
+ }
+ }
+ first_changed_item_index++;
+ }
+ child_it++;
+ }
+ // now first_changed_item_index should contains a number of button that need to change
+
+ if (first_changed_item_index <= mItems.count())
+ {
+ // Rebuild the buttons only
+ // child_list_t is a linked list, so safe to erase from the middle if we pre-incrament the iterator
+
+ while (child_it != childs->end())
+ {
+ //lets remove other landmarks button and rebuild it
+ child_list_const_iter_t cur_it = child_it++;
+ LLFavoriteLandmarkButton* button =
+ dynamic_cast<LLFavoriteLandmarkButton*> (*cur_it);
+ if (button)
+ {
+ removeChild(button);
+ delete button;
+ }
+ }
+ // we have to remove ChevronButton to make sure that the last item will be LandmarkButton to get the right aligning
+ if (mChevronButton->getParent() == this)
+ {
+ removeChild(mChevronButton);
+ }
+ int last_right_edge = 0;
+ if (getChildList()->size() > 0)
+ {
+ last_right_edge = getChildList()->back()->getRect().mRight;
+ }
+ //last_right_edge is saving coordinates
+ LLButton* last_new_button = NULL;
+ int j = first_changed_item_index;
+ for (; j < mItems.count(); j++)
+ {
+ last_new_button = createButton(mItems[j], buttonXMLNode, last_right_edge);
+ if (!last_new_button)
+ {
+ break;
+ }
+ sendChildToBack(last_new_button);
+ last_right_edge = last_new_button->getRect().mRight;
+
+ mLastTab = last_new_button;
+ }
+ mFirstDropDownItem = j;
+ // Chevron button
+ if (mFirstDropDownItem < mItems.count())
+ {
+ // if updateButton had been called it means:
+ //or there are some new favorites, or width had been changed
+ // so if we need to display chevron button, we must update dropdown items too.
+ mUpdateDropDownItems = true;
+ S32 buttonHGap = 2; // default value
+ buttonXMLNode->getAttributeS32("left", buttonHGap);
+ LLRect rect;
+ // Chevron button should stay right aligned
+ rect.setOriginAndSize(getRect().mRight - mChevronButton->getRect().getWidth() - buttonHGap, 0,
+ mChevronButton->getRect().getWidth(),
+ mChevronButton->getRect().getHeight());
+
+ addChild(mChevronButton);
+ mChevronButton->setRect(rect);
+ mChevronButton->setVisible(TRUE);
+ }
+ }
+ else
+ {
+ mUpdateDropDownItems = false;
+ }
+}
+
+LLButton* LLFavoritesBarCtrl::createButton(const LLPointer<LLViewerInventoryItem> item, LLXMLNodePtr &buttonXMLNode, S32 x_offset)
+{
+ S32 def_button_width = 120;
+ buttonXMLNode->getAttributeS32("width", def_button_width);
+ S32 button_x_delta = 2; // default value
+ buttonXMLNode->getAttributeS32("left", button_x_delta);
+ S32 curr_x = x_offset;
+
+ /**
+ * WORKAROUND:
+ * there are some problem with displaying of fonts in buttons.
+ * Empty space (or ...) is displaying instead of last symbols, even though the width of the button is enough.
+ * Problem will gone, if we stretch out the button. For that reason I have to put additional 20 pixels.
+ */
+ int requred_width = mFont->getWidth(item->getDisplayName()) + 20;
+ int width = requred_width > def_button_width? def_button_width : requred_width;
+ LLFavoriteLandmarkButton* fav_btn = NULL;
+
+ // do we have a place for next button + double buttonHGap + mChevronButton ?
+ if(curr_x + width + 2*button_x_delta + mChevronButton->getRect().getWidth() > getRect().mRight )
+ {
+ return NULL;
+ }
+ fav_btn = LLUICtrlFactory::defaultBuilder<LLFavoriteLandmarkButton>(buttonXMLNode, this, NULL);
+ if (NULL == fav_btn)
+ {
+ llwarns << "Unable to create LLFavoriteLandmarkButton widget: " << item->getName() << llendl;
+ return NULL;
+ }
+
+ LLRect butt_rect (fav_btn->getRect());
+ fav_btn->setLandmarkID(item->getUUID());
+ butt_rect.setOriginAndSize(curr_x + button_x_delta, fav_btn->getRect().mBottom, width, fav_btn->getRect().getHeight());
+
+ fav_btn->setRect(butt_rect);
+ // change only left and save bottom
+ fav_btn->setFont(mFont);
+ fav_btn->setName(item->getName());
+ fav_btn->setLabel(item->getName());
+ fav_btn->setToolTip(item->getName());
+ fav_btn->setCommitCallback(boost::bind(&LLFavoritesBarCtrl::onButtonClick, this, item->getUUID()));
+ fav_btn->setRightMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonRightClick, this, item->getUUID(), _1, _2, _3,_4 ));
+
+ fav_btn->LLUICtrl::setMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseDown, this, item->getUUID(), _1, _2, _3, _4));
+ fav_btn->LLUICtrl::setMouseUpCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseUp, this, item->getUUID(), _1, _2, _3, _4));
+
+ return fav_btn;
+}
+
+
+BOOL LLFavoritesBarCtrl::postBuild()
+{
+ // make the popup menu available
+ LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_favorites.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if (!menu)
+ {
+ menu = LLUICtrlFactory::getDefaultWidget<LLMenuGL>("inventory_menu");
+ }
+ menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor"));
+ mInventoryItemsPopupMenuHandle = menu->getHandle();
+
+ return TRUE;
+}
+
+BOOL LLFavoritesBarCtrl::collectFavoriteItems(LLInventoryModel::item_array_t &items)
+{
+ if (mFavoriteFolderId.isNull())
+ return FALSE;
+
+ LLInventoryModel::cat_array_t cats;
+
+ LLIsType is_type(LLAssetType::AT_LANDMARK);
+ gInventory.collectDescendentsIf(mFavoriteFolderId, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type);
+
+ std::sort(items.begin(), items.end(), LLFavoritesSort());
+
+ if (needToSaveItemsOrder(items))
+ {
+ S32 sortField = 0;
+ for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
+ {
+ (*i)->setSortField(++sortField);
+ }
+ }
+
+ return TRUE;
+}
+
+void LLFavoritesBarCtrl::showDropDownMenu()
+{
+ if (mPopupMenuHandle.isDead())
+ {
+ LLToggleableMenu::Params menu_p;
+ menu_p.name("favorites menu");
+ menu_p.can_tear_off(false);
+ menu_p.visible(false);
+ menu_p.scrollable(true);
+ menu_p.max_scrollable_items = 10;
+ menu_p.preferred_width = DROP_DOWN_MENU_WIDTH;
+
+ LLToggleableMenu* menu = LLUICtrlFactory::create<LLFavoriteLandmarkToggleableMenu>(menu_p);
+ mPopupMenuHandle = menu->getHandle();
+ }
+
+ LLToggleableMenu* menu = (LLToggleableMenu*)mPopupMenuHandle.get();
+
+ if (menu)
+ {
+ if (!menu->toggleVisibility())
+ return;
+
+ U32 max_width = llmin(DROP_DOWN_MENU_WIDTH, getRect().getWidth());
+ if (mUpdateDropDownItems)
+ {
+ menu->empty();
+
+ U32 widest_item = 0;
+
+ for (S32 i = mFirstDropDownItem; i < mItems.count(); i++)
+ {
+ LLViewerInventoryItem* item = mItems.get(i);
+ const std::string& item_name = item->getName();
+
+ LLFavoriteLandmarkMenuItem::Params item_params;
+ item_params.name(item_name);
+ item_params.label(item_name);
+
+ item_params.on_click.function(boost::bind(
+ &LLFavoritesBarCtrl::onButtonClick, this,
+ item->getUUID()));
+ LLFavoriteLandmarkMenuItem *menu_item = LLUICtrlFactory::create<LLFavoriteLandmarkMenuItem>(item_params);
+ menu_item->initFavoritesBarPointer(this);
+ menu_item->setRightMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonRightClick, this, item->getUUID(), _1, _2, _3, _4));
+ menu_item->LLUICtrl::setMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseDown, this, item->getUUID(), _1, _2, _3, _4));
+ menu_item->LLUICtrl::setMouseUpCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseUp, this, item->getUUID(), _1, _2, _3, _4));
+ menu_item->setLandmarkID(item->getUUID());
+
+ // Check whether item name wider than menu
+ if (menu_item->getNominalWidth() > max_width)
+ {
+ S32 chars_total = item_name.length();
+ S32 chars_fitted = 1;
+ menu_item->setLabel(LLStringExplicit(""));
+ S32 label_space = max_width - menu_item->getFont()->getWidth("...") -
+ menu_item->getNominalWidth();// This returns width of menu item with empty label (pad pixels)
+
+ while (chars_fitted < chars_total
+ && menu_item->getFont()->getWidth(item_name, 0, chars_fitted) < label_space)
+ {
+ chars_fitted++;
+ }
+ chars_fitted--; // Rolling back one char, that doesn't fit
+
+ menu_item->setLabel(item_name.substr(0, chars_fitted)
+ + "...");
+ }
+ widest_item = llmax(widest_item, menu_item->getNominalWidth());
+
+ menu->addChild(menu_item);
+ }
+ mUpdateDropDownItems = false;
+ }
+
+ menu->buildDrawLabels();
+ menu->updateParent(LLMenuGL::sMenuContainer);
+
+ menu->setButtonRect(mChevronButton->getRect(), this);
+
+ LLMenuGL::showPopup(this, menu, getRect().getWidth() - max_width, 0);
+ }
+}
+
+void LLFavoritesBarCtrl::onButtonClick(LLUUID item_id)
+{
+ // We only have one Inventory, gInventory. Some day this should be better abstracted.
+ LLInvFVBridgeAction::doAction(item_id,&gInventory);
+}
+
+void LLFavoritesBarCtrl::onButtonRightClick( LLUUID item_id,LLView* fav_button,S32 x,S32 y,MASK mask)
+{
+ mSelectedItemID = item_id;
+
+ LLMenuGL* menu = (LLMenuGL*)mInventoryItemsPopupMenuHandle.get();
+ if (!menu)
+ {
+ return;
+ }
+
+ // Release mouse capture so hover events go to the popup menu
+ // because this is happening during a mouse down.
+ gFocusMgr.setMouseCapture(NULL);
+
+ menu->updateParent(LLMenuGL::sMenuContainer);
+ LLMenuGL::showPopup(fav_button, menu, x, y);
+}
+
+BOOL LLFavoritesBarCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = childrenHandleRightMouseDown( x, y, mask) != NULL;
+ if(!handled && !gMenuHolder->hasVisibleMenu())
+ {
+ show_navbar_context_menu(this,x,y);
+ handled = true;
+ }
+
+ return handled;
+}
+void copy_slurl_to_clipboard_cb(std::string& slurl)
+{
+ gClipboard.copyFromString(utf8str_to_wstring(slurl));
+
+ LLSD args;
+ args["SLURL"] = slurl;
+ LLNotificationsUtil::add("CopySLURL", args);
+}
+
+
+bool LLFavoritesBarCtrl::enableSelected(const LLSD& userdata)
+{
+ std::string param = userdata.asString();
+
+ if (param == std::string("can_paste"))
+ {
+ return isClipboardPasteable();
+ }
+
+ return false;
+}
+
+void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata)
+{
+ std::string action = userdata.asString();
+ llinfos << "Action = " << action << " Item = " << mSelectedItemID.asString() << llendl;
+
+ LLViewerInventoryItem* item = gInventory.getItem(mSelectedItemID);
+ if (!item)
+ return;
+
+ if (action == "open")
+ {
+ onButtonClick(item->getUUID());
+ }
+ else if (action == "about")
+ {
+ LLSD key;
+ key["type"] = "landmark";
+ key["id"] = mSelectedItemID;
+
+ LLSideTray::getInstance()->showPanel("panel_places", key);
+ }
+ else if (action == "copy_slurl")
+ {
+ LLVector3d posGlobal;
+ LLLandmarkActions::getLandmarkGlobalPos(mSelectedItemID, posGlobal);
+
+ if (!posGlobal.isExactlyZero())
+ {
+ LLLandmarkActions::getSLURLfromPosGlobal(posGlobal, copy_slurl_to_clipboard_cb);
+ }
+ }
+ else if (action == "show_on_map")
+ {
+ LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
+
+ LLVector3d posGlobal;
+ LLLandmarkActions::getLandmarkGlobalPos(mSelectedItemID, posGlobal);
+
+ if (!posGlobal.isExactlyZero() && worldmap_instance)
+ {
+ worldmap_instance->trackLocation(posGlobal);
+ LLFloaterReg::showInstance("world_map", "center");
+ }
+ }
+ else if (action == "cut")
+ {
+ }
+ else if (action == "copy")
+ {
+ LLInventoryClipboard::instance().store(mSelectedItemID);
+ }
+ else if (action == "paste")
+ {
+ pastFromClipboard();
+ }
+ else if (action == "delete")
+ {
+ gInventory.removeItem(mSelectedItemID);
+ }
+}
+
+BOOL LLFavoritesBarCtrl::isClipboardPasteable() const
+{
+ if (!LLInventoryClipboard::instance().hasContents())
+ {
+ return FALSE;
+ }
+
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ for(S32 i = 0; i < count; i++)
+ {
+ const LLUUID &item_id = objects.get(i);
+
+ // Can't paste folders
+ const LLInventoryCategory *cat = gInventory.getCategory(item_id);
+ if (cat)
+ {
+ return FALSE;
+ }
+
+ const LLInventoryItem *item = gInventory.getItem(item_id);
+ if (item && LLAssetType::AT_LANDMARK != item->getType())
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+void LLFavoritesBarCtrl::pastFromClipboard() const
+{
+ LLInventoryModel* model = &gInventory;
+ if(model && isClipboardPasteable())
+ {
+ LLInventoryItem* item = NULL;
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ LLUUID parent_id(mFavoriteFolderId);
+ for(S32 i = 0; i < count; i++)
+ {
+ item = model->getItem(objects.get(i));
+ if (item)
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ parent_id,
+ std::string(),
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ }
+ }
+}
+
+void LLFavoritesBarCtrl::onButtonMouseDown(LLUUID id, LLUICtrl* ctrl, S32 x, S32 y, MASK mask)
+{
+ mDragItemId = id;
+ mStartDrag = TRUE;
+
+ S32 screenX, screenY;
+ localPointToScreen(x, y, &screenX, &screenY);
+
+ LLToolDragAndDrop::getInstance()->setDragStart(screenX, screenY);
+}
+
+void LLFavoritesBarCtrl::onButtonMouseUp(LLUUID id, LLUICtrl* ctrl, S32 x, S32 y, MASK mask)
+{
+ mStartDrag = FALSE;
+ mDragItemId = LLUUID::null;
+}
+
+void LLFavoritesBarCtrl::onEndDrag()
+{
+ mEndDragConnection.disconnect();
+
+ showDragMarker(FALSE);
+ mDragItemId = LLUUID::null;
+ LLView::getWindow()->setCursor(UI_CURSOR_ARROW);
+}
+
+BOOL LLFavoritesBarCtrl::handleHover(S32 x, S32 y, MASK mask)
+{
+ if (mDragItemId != LLUUID::null && mStartDrag)
+ {
+ S32 screenX, screenY;
+ localPointToScreen(x, y, &screenX, &screenY);
+
+ if(LLToolDragAndDrop::getInstance()->isOverThreshold(screenX, screenY))
+ {
+ LLToolDragAndDrop::getInstance()->beginDrag(
+ DAD_LANDMARK, mDragItemId,
+ LLToolDragAndDrop::SOURCE_LIBRARY);
+
+ mStartDrag = FALSE;
+
+ return LLToolDragAndDrop::getInstance()->handleHover(x, y, mask);
+ }
+ }
+
+ return TRUE;
+}
+
+LLUICtrl* LLFavoritesBarCtrl::findChildByLocalCoords(S32 x, S32 y)
+{
+ LLUICtrl* ctrl = 0;
+ S32 screenX, screenY;
+ const child_list_t* list = getChildList();
+
+ localPointToScreen(x, y, &screenX, &screenY);
+
+ // look for a child which contains the point (screenX, screenY) in it's rectangle
+ for (child_list_const_iter_t i = list->begin(); i != list->end(); ++i)
+ {
+ LLRect rect;
+ localRectToScreen((*i)->getRect(), &rect);
+
+ if (rect.pointInRect(screenX, screenY))
+ {
+ ctrl = dynamic_cast<LLUICtrl*>(*i);
+ break;
+ }
+ }
+
+ return ctrl;
+}
+
+BOOL LLFavoritesBarCtrl::needToSaveItemsOrder(const LLInventoryModel::item_array_t& items)
+{
+ BOOL result = FALSE;
+
+ // if there is an item without sort order field set, we need to save items order
+ for (LLInventoryModel::item_array_t::const_iterator i = items.begin(); i != items.end(); ++i)
+ {
+ if ((*i)->getSortField() < 0)
+ {
+ result = TRUE;
+ break;
+ }
+ }
+
+ return result;
+}
+
+LLInventoryModel::item_array_t::iterator LLFavoritesBarCtrl::findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id)
+{
+ LLInventoryModel::item_array_t::iterator result = items.end();
+
+ for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
+ {
+ if ((*i)->getUUID() == id)
+ {
+ result = i;
+ break;
+ }
+ }
+
+ return result;
+}
+
+void LLFavoritesBarCtrl::insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, LLViewerInventoryItem* insertedItem)
+{
+ LLViewerInventoryItem* beforeItem = gInventory.getItem(beforeItemId);
+
+ items.insert(findItemByUUID(items, beforeItem->getUUID()), insertedItem);
+}
+
+// EOF
diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h
new file mode 100644
index 0000000000..40dd551eef
--- /dev/null
+++ b/indra/newview/llfavoritesbar.h
@@ -0,0 +1,153 @@
+/**
+ * @file llfavoritesbar.h
+ * @brief LLFavoritesBarCtrl base class
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFAVORITESBARCTRL_H
+#define LL_LLFAVORITESBARCTRL_H
+
+#include "llbutton.h"
+#include "lluictrl.h"
+
+#include "llinventoryobserver.h"
+#include "llinventorymodel.h"
+
+class LLFavoritesBarCtrl : public LLUICtrl, public LLInventoryObserver
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<LLUIImage*> image_drag_indication;
+ Optional<LLButton::Params> chevron_button;
+ Params();
+ };
+
+protected:
+ LLFavoritesBarCtrl(const Params&);
+ friend class LLUICtrlFactory;
+public:
+ virtual ~LLFavoritesBarCtrl();
+
+ /*virtual*/ BOOL postBuild();
+
+ /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg);
+
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ // LLInventoryObserver observer trigger
+ virtual void changed(U32 mask);
+ virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+ virtual void draw();
+
+ void showDragMarker(BOOL show) { mShowDragMarker = show; }
+ void setLandingTab(LLUICtrl* tab) { mLandingTab = tab; }
+
+protected:
+ void updateButtons();
+ LLButton* createButton(const LLPointer<LLViewerInventoryItem> item, LLXMLNodePtr &root, S32 x_offset );
+ LLXMLNodePtr getButtonXMLNode();
+ BOOL collectFavoriteItems(LLInventoryModel::item_array_t &items);
+
+ void onButtonClick(LLUUID id);
+ void onButtonRightClick(LLUUID id,LLView* button,S32 x,S32 y,MASK mask);
+
+ void onButtonMouseDown(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask);
+ void onOverflowMenuItemMouseDown(LLUUID id, LLUICtrl* item, S32 x, S32 y, MASK mask);
+ void onButtonMouseUp(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask);
+
+ void onEndDrag();
+
+ bool enableSelected(const LLSD& userdata);
+ void doToSelected(const LLSD& userdata);
+ BOOL isClipboardPasteable() const;
+ void pastFromClipboard() const;
+
+ void showDropDownMenu();
+
+ LLHandle<LLView> mPopupMenuHandle;
+ LLHandle<LLView> mInventoryItemsPopupMenuHandle;
+
+ LLUUID mFavoriteFolderId;
+ const LLFontGL *mFont;
+ S32 mFirstDropDownItem;
+ bool mUpdateDropDownItems;
+
+ LLUUID mSelectedItemID;
+
+ LLUIImage* mImageDragIndication;
+
+private:
+ /*
+ * Helper function to make code more readable. It handles all drag and drop
+ * operations of the existing favorites items on the favorites bar.
+ */
+ void handleExistingFavoriteDragAndDrop(S32 x, S32 y);
+
+ /*
+ * Helper function to make code more readable. It handles all drag and drop
+ * operations of the new landmark to the favorites bar.
+ */
+ void handleNewFavoriteDragAndDrop(LLInventoryItem *item, const LLUUID& favorites_id, S32 x, S32 y);
+
+ // finds a control under the specified LOCAL point
+ LLUICtrl* findChildByLocalCoords(S32 x, S32 y);
+
+ // checks if the current order of the favorites items must be saved
+ BOOL needToSaveItemsOrder(const LLInventoryModel::item_array_t& items);
+
+ /**
+ * inserts an item identified by insertedItemId BEFORE an item identified by beforeItemId.
+ * this function assumes that an item identified by insertedItemId doesn't exist in items array.
+ */
+ void insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, LLViewerInventoryItem* insertedItem);
+
+ // finds an item by it's UUID in the items array
+ LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id);
+
+ BOOL mShowDragMarker;
+ LLUICtrl* mLandingTab;
+ LLUICtrl* mLastTab;
+ LLButton* mChevronButton;
+
+ LLUUID mDragItemId;
+ BOOL mStartDrag;
+ LLInventoryModel::item_array_t mItems;
+
+ BOOL mTabsHighlightEnabled;
+
+ boost::signals2::connection mEndDragConnection;
+};
+
+
+#endif // LL_LLFAVORITESBARCTRL_H
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index 35613b7c34..fb724f30e0 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -44,10 +44,11 @@
#include "llgl.h"
#include "llsecondlifeurls.h"
+#include "llappviewer.h"
#include "llviewercontrol.h"
#include "llworld.h"
#include "lldrawpoolterrain.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llwindow.h"
#include "llui.h"
#include "llcontrol.h"
@@ -58,11 +59,6 @@
#include "lldxhardware.h"
#endif
-//
-// externs
-//
-extern LLMemoryInfo gSysMemory;
-extern LLCPUInfo gSysCPU;
#if LL_DARWIN
const char FEATURE_TABLE_FILENAME[] = "featuretable_mac.txt";
@@ -434,7 +430,6 @@ void LLFeatureManager::applyRecommendedSettings()
setGraphicsLevel(level, false);
gSavedSettings.setU32("RenderQualityPerformance", level);
- gSavedSettings.setBOOL("RenderCustomSettings", FALSE);
// now apply the tweaks to draw distance
// these are double negatives, because feature masks only work by
diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h
index 537bf0c6a4..383963a41d 100644
--- a/indra/newview/llfeaturemanager.h
+++ b/indra/newview/llfeaturemanager.h
@@ -35,6 +35,7 @@
#include "stdtypes.h"
+#include "llsingleton.h"
#include "llstring.h"
#include <map>
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 8f5882615f..028e1cc098 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -39,6 +39,7 @@
#include "lldir.h"
#include "llframetimer.h"
#include "lltrans.h"
+#include "llwindow.h" // beforeDialog()
#if LL_SDL
#include "llwindowsdl.h" // for some X/GTK utils to help with filepickers
@@ -818,6 +819,13 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter)
reset();
mNavOptions.optionFlags &= ~kNavAllowMultipleFiles;
+
+ if(filter == FFLOAD_ALL) // allow application bundles etc. to be traversed; important for DEV-16869, but generally useful
+ {
+ // mNavOptions.optionFlags |= kNavAllowOpenPackages;
+ mNavOptions.optionFlags |= kNavSupportPackages;
+ }
+
// Modal, so pause agent
send_agent_pause();
{
diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h
index ab2455620f..7ecbc3db60 100644
--- a/indra/newview/llfilepicker.h
+++ b/indra/newview/llfilepicker.h
@@ -64,11 +64,6 @@ extern "C" {
#if LL_GTK
# include "gtk/gtk.h"
#endif // LL_GTK
-
-// also mostly for Linux, for some X11-specific filepicker usability tweaks
-#if LL_X11
-#include "SDL/SDL_syswm.h"
-#endif
}
class LLFilePicker
diff --git a/indra/newview/llfirstuse.cpp b/indra/newview/llfirstuse.cpp
index 9ee24d6d83..b3fdf60b11 100644
--- a/indra/newview/llfirstuse.cpp
+++ b/indra/newview/llfirstuse.cpp
@@ -36,23 +36,22 @@
// library includes
#include "indra_constants.h"
+#include "llnotificationsutil.h"
// viewer includes
#include "llagent.h" // for gAgent.inPrelude()
-#include "llnotify.h"
#include "llviewercontrol.h"
#include "llui.h"
#include "llappviewer.h"
#include "lltracker.h"
+/*
// static
std::set<std::string> LLFirstUse::sConfigVariables;
// static
void LLFirstUse::addConfigVariable(const std::string& var)
{
- //Don't add the warning, now that we're storing the default in the settings_default.xml file
- //gSavedSettings.addWarning(var);
sConfigVariables.insert(var);
}
@@ -63,7 +62,7 @@ void LLFirstUse::disableFirstUse()
for (std::set<std::string>::iterator iter = sConfigVariables.begin();
iter != sConfigVariables.end(); ++iter)
{
- gSavedSettings.setWarning(*iter, FALSE);
+ gWarningSettings.setBOOL(*iter, FALSE);
}
}
@@ -74,21 +73,22 @@ void LLFirstUse::resetFirstUse()
for (std::set<std::string>::iterator iter = sConfigVariables.begin();
iter != sConfigVariables.end(); ++iter)
{
- gSavedSettings.setWarning(*iter, TRUE);
+ gWarningSettings.setBOOL(*iter, TRUE);
}
}
-
+*/
+/*
// Called whenever the viewer detects that your balance went up
void LLFirstUse::useBalanceIncrease(S32 delta)
{
- if (gSavedSettings.getWarning("FirstBalanceIncrease"))
+ if (gWarningSettings.getBOOL("FirstBalanceIncrease"))
{
- gSavedSettings.setWarning("FirstBalanceIncrease", FALSE);
+ gWarningSettings.setBOOL("FirstBalanceIncrease", FALSE);
LLSD args;
args["AMOUNT"] = llformat("%d",delta);
- LLNotifications::instance().add("FirstBalanceIncrease", args);
+ LLNotificationsUtil::add("FirstBalanceIncrease", args);
}
}
@@ -96,13 +96,13 @@ void LLFirstUse::useBalanceIncrease(S32 delta)
// Called whenever the viewer detects your balance went down
void LLFirstUse::useBalanceDecrease(S32 delta)
{
- if (gSavedSettings.getWarning("FirstBalanceDecrease"))
+ if (gWarningSettings.getBOOL("FirstBalanceDecrease"))
{
- gSavedSettings.setWarning("FirstBalanceDecrease", FALSE);
+ gWarningSettings.setBOOL("FirstBalanceDecrease", FALSE);
LLSD args;
args["AMOUNT"] = llformat("%d",-delta);
- LLNotifications::instance().add("FirstBalanceDecrease", args);
+ LLNotificationsUtil::add("FirstBalanceDecrease", args);
}
}
@@ -112,22 +112,22 @@ void LLFirstUse::useSit()
{
// Our orientation island uses sitting to teach vehicle driving
// so just never show this message. JC
- //if (gSavedSettings.getWarning("FirstSit"))
+ //if (gWarningSettings.getBOOL("FirstSit"))
//{
- // gSavedSettings.setWarning("FirstSit", FALSE);
+ // gWarningSettings.setBOOL("FirstSit", FALSE);
//
- // LLNotifications::instance().add("FirstSit");
+ // LLNotificationsUtil::add("FirstSit");
//}
}
// static
void LLFirstUse::useMap()
{
- if (gSavedSettings.getWarning("FirstMap"))
+ if (gWarningSettings.getBOOL("FirstMap"))
{
- gSavedSettings.setWarning("FirstMap", FALSE);
+ gWarningSettings.setBOOL("FirstMap", FALSE);
- LLNotifications::instance().add("FirstMap");
+ LLNotificationsUtil::add("FirstMap");
}
}
@@ -140,40 +140,43 @@ void LLFirstUse::useGoTo()
// static
void LLFirstUse::useBuild()
{
- if (gSavedSettings.getWarning("FirstBuild"))
+ if (gWarningSettings.getBOOL("FirstBuild"))
{
- gSavedSettings.setWarning("FirstBuild", FALSE);
+ gWarningSettings.setBOOL("FirstBuild", FALSE);
- LLNotifications::instance().add("FirstBuild");
+ LLNotificationsUtil::add("FirstBuild");
}
}
-
+
+ */
+/*
// static
void LLFirstUse::useLeftClickNoHit()
{
- if (gSavedSettings.getWarning("FirstLeftClickNoHit"))
+ if (gWarningSettings.getBOOL("FirstLeftClickNoHit"))
{
- gSavedSettings.setWarning("FirstLeftClickNoHit", FALSE);
+ gWarningSettings.setBOOL("FirstLeftClickNoHit", FALSE);
- LLNotifications::instance().add("FirstLeftClickNoHit");
+ LLNotificationsUtil::add("FirstLeftClickNoHit");
}
}
-
+*/
+/*
// static
void LLFirstUse::useTeleport()
{
- if (gSavedSettings.getWarning("FirstTeleport"))
+ if (gWarningSettings.getBOOL("FirstTeleport"))
{
LLVector3d teleportDestination = LLTracker::getTrackedPositionGlobal();
if(teleportDestination != LLVector3d::zero)
{
- gSavedSettings.setWarning("FirstTeleport", FALSE);
+ gWarningSettings.setBOOL("FirstTeleport", FALSE);
- LLNotifications::instance().add("FirstTeleport");
+ LLNotificationsUtil::add("FirstTeleport");
}
}
}
-
+*/
// static
void LLFirstUse::useOverrideKeys()
{
@@ -181,15 +184,15 @@ void LLFirstUse::useOverrideKeys()
// so don't show this message until you get off OI. JC
if (!gAgent.inPrelude())
{
- if (gSavedSettings.getWarning("FirstOverrideKeys"))
+ if (gWarningSettings.getBOOL("FirstOverrideKeys"))
{
- gSavedSettings.setWarning("FirstOverrideKeys", FALSE);
+ gWarningSettings.setBOOL("FirstOverrideKeys", FALSE);
- LLNotifications::instance().add("FirstOverrideKeys");
+ LLNotificationsUtil::add("FirstOverrideKeys");
}
}
}
-
+/*
// static
void LLFirstUse::useAttach()
{
@@ -199,70 +202,71 @@ void LLFirstUse::useAttach()
// static
void LLFirstUse::useAppearance()
{
- if (gSavedSettings.getWarning("FirstAppearance"))
+ if (gWarningSettings.getBOOL("FirstAppearance"))
{
- gSavedSettings.setWarning("FirstAppearance", FALSE);
+ gWarningSettings.setBOOL("FirstAppearance", FALSE);
- LLNotifications::instance().add("FirstAppearance");
+ LLNotificationsUtil::add("FirstAppearance");
}
}
// static
void LLFirstUse::useInventory()
{
- if (gSavedSettings.getWarning("FirstInventory"))
+ if (gWarningSettings.getBOOL("FirstInventory"))
{
- gSavedSettings.setWarning("FirstInventory", FALSE);
+ gWarningSettings.setBOOL("FirstInventory", FALSE);
- LLNotifications::instance().add("FirstInventory");
+ LLNotificationsUtil::add("FirstInventory");
}
}
+*/
// static
void LLFirstUse::useSandbox()
{
- if (gSavedSettings.getWarning("FirstSandbox"))
+ if (gWarningSettings.getBOOL("FirstSandbox"))
{
- gSavedSettings.setWarning("FirstSandbox", FALSE);
+ gWarningSettings.setBOOL("FirstSandbox", FALSE);
LLSD args;
args["HOURS"] = llformat("%d",SANDBOX_CLEAN_FREQ);
args["TIME"] = llformat("%d",SANDBOX_FIRST_CLEAN_HOUR);
- LLNotifications::instance().add("FirstSandbox", args);
+ LLNotificationsUtil::add("FirstSandbox", args);
}
}
-
+/*
// static
void LLFirstUse::useFlexible()
{
- if (gSavedSettings.getWarning("FirstFlexible"))
+ if (gWarningSettings.getBOOL("FirstFlexible"))
{
- gSavedSettings.setWarning("FirstFlexible", FALSE);
+ gWarningSettings.setBOOL("FirstFlexible", FALSE);
- LLNotifications::instance().add("FirstFlexible");
+ LLNotificationsUtil::add("FirstFlexible");
}
}
// static
void LLFirstUse::useDebugMenus()
{
- if (gSavedSettings.getWarning("FirstDebugMenus"))
+ if (gWarningSettings.getBOOL("FirstDebugMenus"))
{
- gSavedSettings.setWarning("FirstDebugMenus", FALSE);
+ gWarningSettings.setBOOL("FirstDebugMenus", FALSE);
- LLNotifications::instance().add("FirstDebugMenus");
+ LLNotificationsUtil::add("FirstDebugMenus");
}
}
// static
void LLFirstUse::useSculptedPrim()
{
- if (gSavedSettings.getWarning("FirstSculptedPrim"))
+ if (gWarningSettings.getBOOL("FirstSculptedPrim"))
{
- gSavedSettings.setWarning("FirstSculptedPrim", FALSE);
+ gWarningSettings.setBOOL("FirstSculptedPrim", FALSE);
- LLNotifications::instance().add("FirstSculptedPrim");
+ LLNotificationsUtil::add("FirstSculptedPrim");
}
}
@@ -270,10 +274,13 @@ void LLFirstUse::useSculptedPrim()
// static
void LLFirstUse::useMedia()
{
- if (gSavedSettings.getWarning("FirstMedia"))
+ if (gWarningSettings.getBOOL("FirstMedia"))
{
- gSavedSettings.setWarning("FirstMedia", FALSE);
+ gWarningSettings.setBOOL("FirstMedia", FALSE);
- LLNotifications::instance().add("FirstMedia");
+ // Popup removed as a short-term fix for EXT-1643.
+ // Ultimately, the plan is to kill all First Use dialogs
+ //LLNotificationsUtil::add("FirstMedia");
}
}
+*/
diff --git a/indra/newview/llfirstuse.h b/indra/newview/llfirstuse.h
index bb64cdd2c6..3c7551f6cb 100644
--- a/indra/newview/llfirstuse.h
+++ b/indra/newview/llfirstuse.h
@@ -79,6 +79,7 @@ object or from inventory.
class LLFirstUse
{
public:
+/*
// Add a config variable to be reset on resetFirstUse()
static void addConfigVariable(const std::string& var);
@@ -95,13 +96,18 @@ public:
static void useMap();
static void useGoTo();
static void useBuild();
- static void useLeftClickNoHit();
+// static void useLeftClickNoHit();
static void useTeleport();
+*/
static void useOverrideKeys();
+/*
static void useAttach();
static void useAppearance();
static void useInventory();
+ */
static void useSandbox();
+
+/*
static void useFlexible();
static void useDebugMenus();
static void useSculptedPrim();
@@ -109,6 +115,7 @@ public:
protected:
static std::set<std::string> sConfigVariables;
+*/
};
#endif
diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp
index 8f2c6d538b..fc8790c172 100644
--- a/indra/newview/llflexibleobject.cpp
+++ b/indra/newview/llflexibleobject.cpp
@@ -39,11 +39,10 @@
#include "llglheaders.h"
#include "llrendersphere.h"
#include "llviewerobject.h"
-#include "llimagegl.h"
#include "llagent.h"
#include "llsky.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewercontrol.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
@@ -262,6 +261,7 @@ void LLVolumeImplFlexible::onSetVolume(const LLVolumeParams &volume_params, cons
// updated every time step. In the future, perhaps there could be an
// optimization similar to what Havok does for objects that are stationary.
//---------------------------------------------------------------------------------
+static LLFastTimer::DeclareTimer FTM_FLEXIBLE_UPDATE("Update Flexies");
BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
{
if (mVO->mDrawable.isNull())
@@ -280,7 +280,7 @@ BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F6
parent->mDrawable->mQuietCount = 0;
}
- LLFastTimer ftm(LLFastTimer::FTM_FLEXIBLE_UPDATE);
+ LLFastTimer ftm(FTM_FLEXIBLE_UPDATE);
S32 new_res = mAttributes->getSimulateLOD();
@@ -704,7 +704,7 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable)
}
if (volume->mLODChanged || volume->mFaceMappingChanged ||
- volume->mVolumeChanged)
+ volume->mVolumeChanged || drawable->isState(LLDrawable::REBUILD_MATERIAL))
{
volume->regenFaces();
volume->mDrawable->setState(LLDrawable::REBUILD_VOLUME);
diff --git a/indra/newview/llflexibleobject.h b/indra/newview/llflexibleobject.h
index 895701da3a..811ae24df2 100644
--- a/indra/newview/llflexibleobject.h
+++ b/indra/newview/llflexibleobject.h
@@ -43,7 +43,6 @@
#ifndef LL_LLFLEXIBLEOBJECT_H
#define LL_LLFLEXIBLEOBJECT_H
-#include "llmemory.h"
#include "llprimitive.h"
#include "llvovolume.h"
#include "llwind.h"
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index 810799d27c..ef69f39ad2 100644
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -35,274 +35,304 @@
#include "llfloaterabout.h"
-#include "llsys.h"
-#include "llgl.h"
-#include "llui.h" // for tr()
-#include "v3dmath.h"
-
-#include "llcurl.h"
-#include "llimagej2c.h"
-#include "audioengine.h"
-
+// Viewer includes
+#include "llagent.h"
+#include "llappviewer.h"
+#include "llsecondlifeurls.h"
+#include "llvoiceclient.h"
+#include "lluictrlfactory.h"
#include "llviewertexteditor.h"
#include "llviewercontrol.h"
-#include "llagent.h"
#include "llviewerstats.h"
#include "llviewerregion.h"
-#include "llversionviewer.h"
-#include "llviewerbuild.h"
-#include "lluictrlfactory.h"
-#include "lluri.h"
+#include "llversioninfo.h"
#include "llweb.h"
-#include "llsecondlifeurls.h"
-#include "lltrans.h"
-#include "llappviewer.h"
+
+// Linden library includes
+#include "llaudioengine.h"
+#include "llbutton.h"
+#include "llcurl.h"
#include "llglheaders.h"
-#include "llmediamanager.h"
+#include "llfloater.h"
+#include "llfloaterreg.h"
+#include "llimagej2c.h"
+#include "llsys.h"
+#include "lltrans.h"
+#include "lluri.h"
+#include "v3dmath.h"
#include "llwindow.h"
+#include "stringize.h"
+#include "llsdutil_math.h"
+#include "lleventapi.h"
#if LL_WINDOWS
#include "lldxhardware.h"
#endif
-extern LLCPUInfo gSysCPU;
extern LLMemoryInfo gSysMemory;
extern U32 gPacketsIn;
-///----------------------------------------------------------------------------
-/// Local function declarations, constants, enums, and typedefs
-///----------------------------------------------------------------------------
-
-LLFloaterAbout* LLFloaterAbout::sInstance = NULL;
-
static std::string get_viewer_release_notes_url();
+
///----------------------------------------------------------------------------
/// Class LLFloaterAbout
///----------------------------------------------------------------------------
+class LLFloaterAbout
+ : public LLFloater
+{
+ friend class LLFloaterReg;
+private:
+ LLFloaterAbout(const LLSD& key);
+ virtual ~LLFloaterAbout();
+
+public:
+ /*virtual*/ BOOL postBuild();
+
+ /// Obtain the data used to fill out the contents string. This is
+ /// separated so that we can programmatically access the same info.
+ static LLSD getInfo();
+ void onClickCopyToClipboard();
+};
+
// Default constructor
-LLFloaterAbout::LLFloaterAbout()
-: LLFloater(std::string("floater_about"), std::string("FloaterAboutRect"), LLStringUtil::null)
+LLFloaterAbout::LLFloaterAbout(const LLSD& key)
+: LLFloater(key)
{
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_about.xml");
+ //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_about.xml");
+
+}
- // Support for changing product name.
- std::string title("About ");
- title += LLAppViewer::instance()->getSecondLifeTitle();
- setTitle(title);
+// Destroys the object
+LLFloaterAbout::~LLFloaterAbout()
+{
+}
+BOOL LLFloaterAbout::postBuild()
+{
+ center();
LLViewerTextEditor *support_widget =
getChild<LLViewerTextEditor>("support_editor", true);
LLViewerTextEditor *credits_widget =
getChild<LLViewerTextEditor>("credits_editor", true);
+ getChild<LLUICtrl>("copy_btn")->setCommitCallback(
+ boost::bind(&LLFloaterAbout::onClickCopyToClipboard, this));
+
+#if LL_WINDOWS
+ getWindow()->incBusyCount();
+ getWindow()->setCursor(UI_CURSOR_ARROW);
+#endif
+ LLSD info(getInfo());
+#if LL_WINDOWS
+ getWindow()->decBusyCount();
+ getWindow()->setCursor(UI_CURSOR_ARROW);
+#endif
+
+ std::ostringstream support;
+
+ // Render the LLSD from getInfo() as a format_map_t
+ LLStringUtil::format_map_t args;
+ // For reasons I don't yet understand, [ReleaseNotes] is not part of the
+ // default substitution strings whereas [APP_NAME] is. But it works to
+ // simply copy it into these specific args.
+ args["ReleaseNotes"] = LLTrans::getString("ReleaseNotes");
+ for (LLSD::map_const_iterator ii(info.beginMap()), iend(info.endMap());
+ ii != iend; ++ii)
+ {
+ if (! ii->second.isArray())
+ {
+ // Scalar value
+ if (ii->second.isUndefined())
+ {
+ args[ii->first] = getString("none");
+ }
+ else
+ {
+ // don't forget to render value asString()
+ args[ii->first] = ii->second.asString();
+ }
+ }
+ else
+ {
+ // array value: build KEY_0, KEY_1 etc. entries
+ for (LLSD::Integer n(0), size(ii->second.size()); n < size; ++n)
+ {
+ args[STRINGIZE(ii->first << '_' << n)] = ii->second[n].asString();
+ }
+ }
+ }
- if (!support_widget || !credits_widget)
+ // Now build the various pieces
+ support << getString("AboutHeader", args);
+ if (info.has("REGION"))
+ {
+ support << "\n\n" << getString("AboutPosition", args);
+ }
+ support << "\n\n" << getString("AboutSystem", args);
+ support << "\n";
+ if (info.has("GRAPHICS_DRIVER_VERSION"))
+ {
+ support << "\n" << getString("AboutDriver", args);
+ }
+ support << "\n" << getString("AboutLibs", args);
+ if (info.has("COMPILER"))
{
- return;
+ support << "\n" << getString("AboutCompiler", args);
+ }
+ if (info.has("PACKETS_IN"))
+ {
+ support << '\n' << getString("AboutTraffic", args);
}
- // For some reason, adding style doesn't work unless this is true.
- support_widget->setParseHTML(TRUE);
+ support_widget->appendText(support.str(),
+ FALSE,
+ LLStyle::Params()
+ .color(LLUIColorTable::instance().getColor("TextFgReadOnlyColor")));
+ support_widget->blockUndo();
- // Text styles for release notes hyperlinks
- LLStyleSP viewer_link_style(new LLStyle);
- viewer_link_style->setVisible(true);
- viewer_link_style->setFontName(LLStringUtil::null);
- viewer_link_style->setLinkHREF(get_viewer_release_notes_url());
- viewer_link_style->setColor(gSavedSettings.getColor4("HTMLLinkColor"));
+ // Fix views
+ support_widget->setEnabled(FALSE);
+ support_widget->startOfDoc();
- // Version string
- std::string version = LLAppViewer::instance()->getSecondLifeTitle()
- + llformat(" %d.%d.%d (%d) %s %s (%s)\n",
- LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH, LL_VIEWER_BUILD,
- __DATE__, __TIME__,
- gSavedSettings.getString("VersionChannelName").c_str());
- support_widget->appendColoredText(version, FALSE, FALSE, gColors.getColor("TextFgReadOnlyColor"));
- support_widget->appendStyledText(LLTrans::getString("ReleaseNotes"), false, false, viewer_link_style);
+ credits_widget->setEnabled(FALSE);
+ credits_widget->startOfDoc();
- std::string support;
- support.append("\n\n");
+ return TRUE;
+}
-#if LL_MSVC
- support.append(llformat("Built with MSVC version %d\n\n", _MSC_VER));
-#endif
+// static
+LLSD LLFloaterAbout::getInfo()
+{
+ // The point of having one method build an LLSD info block and the other
+ // construct the user-visible About string is to ensure that the same info
+ // is available to a getInfo() caller as to the user opening
+ // LLFloaterAbout.
+ LLSD info;
+ LLSD version;
+ version.append(LLVersionInfo::getMajor());
+ version.append(LLVersionInfo::getMinor());
+ version.append(LLVersionInfo::getPatch());
+ version.append(LLVersionInfo::getBuild());
+ info["VIEWER_VERSION"] = version;
+ info["VIEWER_VERSION_STR"] = LLVersionInfo::getVersion();
+ info["BUILD_DATE"] = __DATE__;
+ info["BUILD_TIME"] = __TIME__;
+ info["CHANNEL"] = gSavedSettings.getString("VersionChannelName");
+
+ info["VIEWER_RELEASE_NOTES_URL"] = get_viewer_release_notes_url();
-#if LL_GNUC
- support.append(llformat("Built with GCC version %d\n\n", GCC_VERSION));
+#if LL_MSVC
+ info["COMPILER"] = "MSVC";
+ info["COMPILER_VERSION"] = _MSC_VER;
+#elif LL_GNUC
+ info["COMPILER"] = "GCC";
+ info["COMPILER_VERSION"] = GCC_VERSION;
#endif
// Position
LLViewerRegion* region = gAgent.getRegion();
if (region)
{
- LLStyleSP server_link_style(new LLStyle);
- server_link_style->setVisible(true);
- server_link_style->setFontName(LLStringUtil::null);
- server_link_style->setLinkHREF(region->getCapability("ServerReleaseNotes"));
- server_link_style->setColor(gSavedSettings.getColor4("HTMLLinkColor"));
-
const LLVector3d &pos = gAgent.getPositionGlobal();
- LLUIString pos_text = getString("you_are_at");
- pos_text.setArg("[POSITION]",
- llformat("%.1f, %.1f, %.1f ", pos.mdV[VX], pos.mdV[VY], pos.mdV[VZ]));
- support.append(pos_text);
-
- std::string region_text = llformat("in %s located at ",
- gAgent.getRegion()->getName().c_str());
- support.append(region_text);
-
- std::string buffer;
- buffer = gAgent.getRegion()->getHost().getHostName();
- support.append(buffer);
- support.append(" (");
- buffer = gAgent.getRegion()->getHost().getString();
- support.append(buffer);
- support.append(")\n");
- support.append(gLastVersionChannel);
- support.append("\n");
-
- support_widget->appendColoredText(support, FALSE, FALSE, gColors.getColor("TextFgReadOnlyColor"));
- support_widget->appendStyledText(LLTrans::getString("ReleaseNotes"), false, false, server_link_style);
-
- support = "\n\n";
+ info["POSITION"] = ll_sd_from_vector3d(pos);
+ info["REGION"] = gAgent.getRegion()->getName();
+ info["HOSTNAME"] = gAgent.getRegion()->getHost().getHostName();
+ info["HOSTIP"] = gAgent.getRegion()->getHost().getString();
+ info["SERVER_VERSION"] = gLastVersionChannel;
+ info["SERVER_RELEASE_NOTES_URL"] = LLWeb::escapeURL(region->getCapability("ServerReleaseNotes"));
}
- // *NOTE: Do not translate text like GPU, Graphics Card, etc -
- // Most PC users that know what these mean will be used to the english versions,
- // and this info sometimes gets sent to support
-
// CPU
- support.append("CPU: ");
- support.append( gSysCPU.getCPUString() );
- support.append("\n");
-
- U32 memory = gSysMemory.getPhysicalMemoryKB() / 1024;
+ info["CPU"] = gSysCPU.getCPUString();
+ info["MEMORY_MB"] = LLSD::Integer(gSysMemory.getPhysicalMemoryKB() / 1024);
// Moved hack adjustment to Windows memory size into llsys.cpp
-
- std::string mem_text = llformat("Memory: %u MB\n", memory );
- support.append(mem_text);
-
- support.append("OS Version: ");
- support.append( LLAppViewer::instance()->getOSInfo().getOSString() );
- support.append("\n");
-
- support.append("Graphics Card Vendor: ");
- support.append( (const char*) glGetString(GL_VENDOR) );
- support.append("\n");
-
- support.append("Graphics Card: ");
- support.append( (const char*) glGetString(GL_RENDERER) );
- support.append("\n");
+ info["OS_VERSION"] = LLAppViewer::instance()->getOSInfo().getOSString();
+ info["GRAPHICS_CARD_VENDOR"] = (const char*)(glGetString(GL_VENDOR));
+ info["GRAPHICS_CARD"] = (const char*)(glGetString(GL_RENDERER));
#if LL_WINDOWS
- getWindow()->incBusyCount();
- getWindow()->setCursor(UI_CURSOR_ARROW);
- support.append("Windows Graphics Driver Version: ");
LLSD driver_info = gDXHardware.getDisplayInfo();
if (driver_info.has("DriverVersion"))
{
- support.append(driver_info["DriverVersion"]);
+ info["GRAPHICS_DRIVER_VERSION"] = driver_info["DriverVersion"];
}
- support.append("\n");
- getWindow()->decBusyCount();
- getWindow()->setCursor(UI_CURSOR_ARROW);
#endif
- support.append("OpenGL Version: ");
- support.append( (const char*) glGetString(GL_VERSION) );
- support.append("\n");
-
- support.append("\n");
-
- support.append("libcurl Version: ");
- support.append( LLCurl::getVersionString() );
- support.append("\n");
-
- support.append("J2C Decoder Version: ");
- support.append( LLImageJ2C::getEngineInfo() );
- support.append("\n");
-
- support.append("Audio Driver Version: ");
+ info["OPENGL_VERSION"] = (const char*)(glGetString(GL_VERSION));
+ info["LIBCURL_VERSION"] = LLCurl::getVersionString();
+ info["J2C_VERSION"] = LLImageJ2C::getEngineInfo();
bool want_fullname = true;
- support.append( gAudiop ? gAudiop->getDriverName(want_fullname) : "(none)" );
- support.append("\n");
+ info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : LLSD();
+ info["VIVOX_VERSION"] = gVoiceClient ? gVoiceClient->getAPIVersion() : LLTrans::getString("NotConnected");
- LLMediaManager *mgr = LLMediaManager::getInstance();
- if (mgr)
- {
- LLMediaBase *media_source = mgr->createSourceFromMimeType("http", "text/html");
- if (media_source)
- {
- support.append("LLMozLib Version: ");
- support.append(media_source->getVersion());
- support.append("\n");
- mgr->destroySource(media_source);
- }
- }
+ // TODO: Implement media plugin version query
+ info["QT_WEBKIT_VERSION"] = "4.6 (version number hard-coded)";
if (gPacketsIn > 0)
{
- std::string packet_loss = llformat("Packets Lost: %.0f/%.0f (%.1f%%)",
- LLViewerStats::getInstance()->mPacketsLostStat.getCurrent(),
- F32(gPacketsIn),
- 100.f*LLViewerStats::getInstance()->mPacketsLostStat.getCurrent() / F32(gPacketsIn) );
- support.append(packet_loss);
- support.append("\n");
+ info["PACKETS_LOST"] = LLViewerStats::getInstance()->mPacketsLostStat.getCurrent();
+ info["PACKETS_IN"] = F32(gPacketsIn);
+ info["PACKETS_PCT"] = 100.f*info["PACKETS_LOST"].asReal() / info["PACKETS_IN"].asReal();
}
- support_widget->appendColoredText(support, FALSE, FALSE, gColors.getColor("TextFgReadOnlyColor"));
-
- // Fix views
- support_widget->setCursorPos(0);
- support_widget->setEnabled(FALSE);
- support_widget->setTakesFocus(TRUE);
- support_widget->setHandleEditKeysDirectly(TRUE);
-
- credits_widget->setCursorPos(0);
- credits_widget->setEnabled(FALSE);
- credits_widget->setTakesFocus(TRUE);
- credits_widget->setHandleEditKeysDirectly(TRUE);
-
- center();
-
- sInstance = this;
+ return info;
}
-// Destroys the object
-LLFloaterAbout::~LLFloaterAbout()
+static std::string get_viewer_release_notes_url()
{
- sInstance = NULL;
+ LLSD query;
+ query["channel"] = gSavedSettings.getString("VersionChannelName");
+ query["version"] = LLVersionInfo::getVersion();
+
+ std::ostringstream url;
+ url << LLTrans::getString("RELEASE_NOTES_BASE_URL") << LLURI::mapToQueryString(query);
+
+ return LLWeb::escapeURL(url.str());
}
-// static
-void LLFloaterAbout::show(void*)
+class LLFloaterAboutListener: public LLEventAPI
{
- if (!sInstance)
+public:
+ LLFloaterAboutListener():
+ LLEventAPI("LLFloaterAbout",
+ "LLFloaterAbout listener to retrieve About box info")
{
- sInstance = new LLFloaterAbout();
+ add("getInfo",
+ "Request an LLSD::Map containing information used to populate About box",
+ &LLFloaterAboutListener::getInfo,
+ LLSD().with("reply", LLSD()));
}
- sInstance->open(); /*Flawfinder: ignore*/
-}
+private:
+ void getInfo(const LLSD& request) const
+ {
+ LLReqID reqid(request);
+ LLSD reply(LLFloaterAbout::getInfo());
+ reqid.stamp(reply);
+ LLEventPumps::instance().obtain(request["reply"]).post(reply);
+ }
+};
+static LLFloaterAboutListener floaterAboutListener;
-static std::string get_viewer_release_notes_url()
+void LLFloaterAbout::onClickCopyToClipboard()
{
- std::ostringstream version;
- version << LL_VERSION_MAJOR << "."
- << LL_VERSION_MINOR << "."
- << LL_VERSION_PATCH << "."
- << LL_VERSION_BUILD;
-
- LLSD query;
- query["channel"] = gSavedSettings.getString("VersionChannelName");
- query["version"] = version.str();
+ LLViewerTextEditor *support_widget =
+ getChild<LLViewerTextEditor>("support_editor", true);
+ support_widget->selectAll();
+ support_widget->copy();
+ support_widget->deselect();
+}
- std::ostringstream url;
- url << RELEASE_NOTES_BASE_URL << LLURI::mapToQueryString(query);
+///----------------------------------------------------------------------------
+/// LLFloaterAboutUtil
+///----------------------------------------------------------------------------
+void LLFloaterAboutUtil::registerFloater()
+{
+ LLFloaterReg::add("sl_about", "floater_about.xml",
+ &LLFloaterReg::build<LLFloaterAbout>);
- return url.str();
}
diff --git a/indra/newview/llfloaterabout.h b/indra/newview/llfloaterabout.h
index 7564b8e41c..1092282ae2 100644
--- a/indra/newview/llfloaterabout.h
+++ b/indra/newview/llfloaterabout.h
@@ -33,20 +33,9 @@
#ifndef LL_LLFLOATERABOUT_H
#define LL_LLFLOATERABOUT_H
-#include "llfloater.h"
-
-class LLFloaterAbout
-: public LLFloater
+namespace LLFloaterAboutUtil
{
-public:
- LLFloaterAbout();
- virtual ~LLFloaterAbout();
-
- static void show(void*);
-
-private:
- static LLFloaterAbout* sInstance;
-};
-
+ void registerFloater();
+}
#endif // LL_LLFLOATERABOUT_H
diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp
index 162456b8ce..60f150bd96 100644
--- a/indra/newview/llfloateranimpreview.cpp
+++ b/indra/newview/llfloateranimpreview.cpp
@@ -37,11 +37,14 @@
#include "llbvhloader.h"
#include "lldatapacker.h"
#include "lldir.h"
+#include "lleconomy.h"
+#include "llnotificationsutil.h"
#include "llvfile.h"
#include "llapr.h"
#include "llstring.h"
#include "llagent.h"
+#include "llanimationstates.h"
#include "llbbox.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
@@ -66,8 +69,7 @@
#include "llvoavatar.h"
#include "pipeline.h"
#include "lluictrlfactory.h"
-
-S32 LLFloaterAnimPreview::sUploadAmount = 10;
+#include "lltrans.h"
const S32 PREVIEW_BORDER_WIDTH = 2;
const S32 PREVIEW_RESIZE_HANDLE_SIZE = S32(RESIZE_HANDLE_WIDTH * OO_SQRT2) + PREVIEW_BORDER_WIDTH;
@@ -82,6 +84,40 @@ const F32 MAX_CAMERA_ZOOM = 10.f;
const F32 BASE_ANIM_TIME_OFFSET = 5.f;
+std::string STATUS[] =
+{
+ "E_ST_OK",
+ "E_ST_EOF",
+ "E_ST_NO_CONSTRAINT",
+ "E_ST_NO_FILE",
+"E_ST_NO_HIER",
+"E_ST_NO_JOINT",
+"E_ST_NO_NAME",
+"E_ST_NO_OFFSET",
+"E_ST_NO_CHANNELS",
+"E_ST_NO_ROTATION",
+"E_ST_NO_AXIS",
+"E_ST_NO_MOTION",
+"E_ST_NO_FRAMES",
+"E_ST_NO_FRAME_TIME",
+"E_ST_NO_POS",
+"E_ST_NO_ROT",
+"E_ST_NO_XLT_FILE",
+"E_ST_NO_XLT_HEADER",
+"E_ST_NO_XLT_NAME",
+"E_ST_NO_XLT_IGNORE",
+"E_ST_NO_XLT_RELATIVE",
+"E_ST_NO_XLT_OUTNAME",
+"E_ST_NO_XLT_MATRIX",
+"E_ST_NO_XLT_MERGECHILD",
+"E_ST_NO_XLT_MERGEPARENT",
+"E_ST_NO_XLT_PRIORITY",
+"E_ST_NO_XLT_LOOP",
+"E_ST_NO_XLT_EASEIN",
+"E_ST_NO_XLT_EASEOUT",
+"E_ST_NO_XLT_HAND",
+"E_ST_NO_XLT_EMOTE",
+};
//-----------------------------------------------------------------------------
// LLFloaterAnimPreview()
//-----------------------------------------------------------------------------
@@ -131,9 +167,9 @@ void LLFloaterAnimPreview::setAnimCallbacks()
childSetCommitCallback("priority", onCommitPriority, this);
childSetCommitCallback("loop_check", onCommitLoop, this);
childSetCommitCallback("loop_in_point", onCommitLoopIn, this);
- childSetValidate("loop_in_point", validateLoopIn);
+ childSetValidate("loop_in_point", boost::bind(&LLFloaterAnimPreview::validateLoopIn, this, _1));
childSetCommitCallback("loop_out_point", onCommitLoopOut, this);
- childSetValidate("loop_out_point", validateLoopOut);
+ childSetValidate("loop_out_point", boost::bind(&LLFloaterAnimPreview::validateLoopOut, this, _1));
childSetCommitCallback("hand_pose_combo", onCommitHandPose, this);
@@ -141,9 +177,9 @@ void LLFloaterAnimPreview::setAnimCallbacks()
childSetValue("emote_combo", "[None]");
childSetCommitCallback("ease_in_time", onCommitEaseIn, this);
- childSetValidate("ease_in_time", validateEaseIn);
+ childSetValidate("ease_in_time", boost::bind(&LLFloaterAnimPreview::validateEaseIn, this, _1));
childSetCommitCallback("ease_out_time", onCommitEaseOut, this);
- childSetValidate("ease_out_time", validateEaseOut);
+ childSetValidate("ease_out_time", boost::bind(&LLFloaterAnimPreview::validateEaseOut, this, _1));
}
//-----------------------------------------------------------------------------
@@ -151,7 +187,6 @@ void LLFloaterAnimPreview::setAnimCallbacks()
//-----------------------------------------------------------------------------
BOOL LLFloaterAnimPreview::postBuild()
{
- LLRect r;
LLKeyframeMotion* motionp = NULL;
LLBVHLoader* loaderp = NULL;
@@ -162,7 +197,6 @@ BOOL LLFloaterAnimPreview::postBuild()
childSetCommitCallback("name_form", onCommitName, this);
- childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d",sUploadAmount));
childSetAction("ok_btn", onBtnOK, this);
setDefaultBtn();
@@ -172,63 +206,19 @@ BOOL LLFloaterAnimPreview::postBuild()
PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD);
mPreviewImageRect.set(0.f, 1.f, 1.f, 0.f);
- S32 y = mPreviewRect.mTop + BTN_HEIGHT;
- S32 btn_left = PREVIEW_HPAD;
-
- r.set( btn_left, y, btn_left + 32, y - BTN_HEIGHT );
mPlayButton = getChild<LLButton>( "play_btn");
- if (!mPlayButton)
- {
- mPlayButton = new LLButton(std::string("play_btn"), LLRect(0,0,0,0));
- }
- mPlayButton->setClickedCallback(onBtnPlay);
- mPlayButton->setCallbackUserData(this);
-
- mPlayButton->setImages(std::string("button_anim_play.tga"),
- std::string("button_anim_play_selected.tga"));
- mPlayButton->setDisabledImages(LLStringUtil::null,LLStringUtil::null);
-
- mPlayButton->setScaleImage(TRUE);
+ mPlayButton->setClickedCallback(onBtnPlay, this);
+ mPlayButton->setVisible(true);
+ mPauseButton = getChild<LLButton>( "pause_btn");
+ mPauseButton->setClickedCallback(onBtnPause, this);
+ mPauseButton->setVisible(false);
+
mStopButton = getChild<LLButton>( "stop_btn");
- if (!mStopButton)
- {
- mStopButton = new LLButton(std::string("stop_btn"), LLRect(0,0,0,0));
- }
- mStopButton->setClickedCallback(onBtnStop);
- mStopButton->setCallbackUserData(this);
-
- mStopButton->setImages(std::string("button_anim_stop.tga"),
- std::string("button_anim_stop_selected.tga"));
- mStopButton->setDisabledImages(LLStringUtil::null,LLStringUtil::null);
-
- mStopButton->setScaleImage(TRUE);
-
- r.set(r.mRight + PREVIEW_HPAD, y, getRect().getWidth() - PREVIEW_HPAD, y - BTN_HEIGHT);
- //childSetCommitCallback("playback_slider", onSliderMove, this);
+ mStopButton->setClickedCallback(onBtnStop, this);
childHide("bad_animation_text");
- //childSetCommitCallback("preview_base_anim", onCommitBaseAnim, this);
- //childSetValue("preview_base_anim", "Standing");
-
- //childSetCommitCallback("priority", onCommitPriority, this);
- //childSetCommitCallback("loop_check", onCommitLoop, this);
- //childSetCommitCallback("loop_in_point", onCommitLoopIn, this);
- //childSetValidate("loop_in_point", validateLoopIn);
- //childSetCommitCallback("loop_out_point", onCommitLoopOut, this);
- //childSetValidate("loop_out_point", validateLoopOut);
-
- //childSetCommitCallback("hand_pose_combo", onCommitHandPose, this);
-
- //childSetCommitCallback("emote_combo", onCommitEmote, this);
- //childSetValue("emote_combo", "[None]");
-
- //childSetCommitCallback("ease_in_time", onCommitEaseIn, this);
- //childSetValidate("ease_in_time", validateEaseIn);
- //childSetCommitCallback("ease_out_time", onCommitEaseOut, this);
- //childSetValidate("ease_out_time", validateEaseOut);
-
std::string exten = gDirUtilp->getExtension(mFilename);
if (exten == "bvh")
{
@@ -254,7 +244,19 @@ BOOL LLFloaterAnimPreview::postBuild()
{
file_buffer[file_size] = '\0';
llinfos << "Loading BVH file " << mFilename << llendl;
- loaderp = new LLBVHLoader(file_buffer);
+ ELoadStatus load_status = E_ST_OK;
+ S32 line_number = 0;
+ loaderp = new LLBVHLoader(file_buffer, load_status, line_number);
+ std::string status = getString(STATUS[load_status]);
+
+ if(load_status == E_ST_NO_XLT_FILE)
+ {
+ llwarns << "NOTE: No translation table found." << llendl;
+ }
+ else
+ {
+ llwarns << "ERROR: [line: " << line_number << "] " << status << llendl;
+ }
}
infile.close() ;
@@ -309,8 +311,9 @@ BOOL LLFloaterAnimPreview::postBuild()
motionp->setName(childGetValue("name_form").asString());
mAnimPreview->getDummyAvatar()->startMotion(mMotionID);
- childSetMinValue("playback_slider", 0.0);
- childSetMaxValue("playback_slider", 1.0);
+
+ getChild<LLSlider>("playback_slider")->setMinValue(0.0);
+ getChild<LLSlider>("playback_slider")->setMaxValue(1.0);
childSetValue("loop_check", LLSD(motionp->getLoop()));
childSetValue("loop_in_point", LLSD(motionp->getLoopIn() / motionp->getDuration() * 100.f));
@@ -327,7 +330,6 @@ BOOL LLFloaterAnimPreview::postBuild()
}
else
{
- delete mAnimPreview;
mAnimPreview = NULL;
mMotionID.setNull();
childSetValue("bad_animation_text", getString("failed_to_initialize"));
@@ -347,7 +349,7 @@ BOOL LLFloaterAnimPreview::postBuild()
else
{
LLUIString out_str = getString("failed_file_read");
- out_str.setArg("[STATUS]", loaderp->getStatus()); // *TODO:Translate
+ out_str.setArg("[STATUS]", getString(STATUS[loaderp->getStatus()]));
childSetValue("bad_animation_text", out_str.getString());
}
}
@@ -369,7 +371,6 @@ BOOL LLFloaterAnimPreview::postBuild()
//-----------------------------------------------------------------------------
LLFloaterAnimPreview::~LLFloaterAnimPreview()
{
- delete mAnimPreview;
mAnimPreview = NULL;
setEnabled(FALSE);
@@ -389,7 +390,7 @@ void LLFloaterAnimPreview::draw()
{
gGL.color3f(1.f, 1.f, 1.f);
- gGL.getTexUnit(0)->bind(mAnimPreview->getTexture());
+ gGL.getTexUnit(0)->bind(mAnimPreview);
gGL.begin( LLRender::QUADS );
{
@@ -431,8 +432,8 @@ void LLFloaterAnimPreview::resetMotion()
LLUUID base_id = mIDList[childGetValue("preview_base_anim").asString()];
avatarp->deactivateAllMotions();
- avatarp->startMotion(base_id, BASE_ANIM_TIME_OFFSET);
avatarp->startMotion(mMotionID, 0.0f);
+ avatarp->startMotion(base_id, BASE_ANIM_TIME_OFFSET);
childSetValue("playback_slider", 0.0f);
// Set pose
@@ -510,7 +511,7 @@ BOOL LLFloaterAnimPreview::handleHover(S32 x, S32 y, MASK mask)
mAnimPreview->requestUpdate();
- LLUI::setCursorPositionLocal(this, mLastMouseX, mLastMouseY);
+ LLUI::setMousePositionLocal(this, mLastMouseX, mLastMouseY);
}
if (!mPreviewRect.pointInRect(x, y) || !mAnimPreview)
@@ -564,19 +565,35 @@ void LLFloaterAnimPreview::onBtnPlay(void* user_data)
if (previewp->mMotionID.notNull() && previewp->mAnimPreview)
{
LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
-
+
if(!avatarp->isMotionActive(previewp->mMotionID))
{
previewp->resetMotion();
previewp->mPauseRequest = NULL;
}
- else
+ else if (avatarp->areAnimationsPaused())
+ {
+ previewp->mPauseRequest = NULL;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// onBtnPause()
+//-----------------------------------------------------------------------------
+void LLFloaterAnimPreview::onBtnPause(void* user_data)
+{
+ LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)user_data;
+ if (!previewp->getEnabled())
+ return;
+
+ if (previewp->mMotionID.notNull() && previewp->mAnimPreview)
+ {
+ LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
+
+ if(avatarp->isMotionActive(previewp->mMotionID))
{
- if (avatarp->areAnimationsPaused())
- {
- previewp->mPauseRequest = NULL;
- }
- else
+ if (!avatarp->areAnimationsPaused())
{
previewp->mPauseRequest = avatarp->requestPause();
}
@@ -643,10 +660,10 @@ void LLFloaterAnimPreview::onCommitBaseAnim(LLUICtrl* ctrl, void* data)
BOOL paused = avatarp->areAnimationsPaused();
// stop all other possible base motions
- avatarp->stopMotion(ANIM_AGENT_STAND, TRUE);
- avatarp->stopMotion(ANIM_AGENT_WALK, TRUE);
- avatarp->stopMotion(ANIM_AGENT_SIT, TRUE);
- avatarp->stopMotion(ANIM_AGENT_HOVER, TRUE);
+ avatarp->stopMotion(previewp->mIDList["Standing"], TRUE);
+ avatarp->stopMotion(previewp->mIDList["Walking"], TRUE);
+ avatarp->stopMotion(previewp->mIDList["Sitting"], TRUE);
+ avatarp->stopMotion(previewp->mIDList["Flying"], TRUE);
previewp->resetMotion();
@@ -736,7 +753,7 @@ void LLFloaterAnimPreview::onCommitName(LLUICtrl* ctrl, void* data)
motionp->setName(previewp->childGetValue("name_form").asString());
}
- LLFloaterNameDesc::doCommit(ctrl, data);
+ previewp->doCommit();
}
//-----------------------------------------------------------------------------
@@ -813,57 +830,53 @@ void LLFloaterAnimPreview::onCommitEaseOut(LLUICtrl* ctrl, void* data)
//-----------------------------------------------------------------------------
// validateEaseIn()
//-----------------------------------------------------------------------------
-BOOL LLFloaterAnimPreview::validateEaseIn(LLUICtrl* spin, void* data)
+bool LLFloaterAnimPreview::validateEaseIn(const LLSD& data)
{
- LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
- if (!previewp->getEnabled())
- return FALSE;
+ if (!getEnabled())
+ return false;
- LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
- LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID);
+ LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar();
+ LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(mMotionID);
if (!motionp->getLoop())
{
- F32 new_ease_in = llclamp((F32)previewp->childGetValue("ease_in_time").asReal(), 0.f, motionp->getDuration() - motionp->getEaseOutDuration());
- previewp->childSetValue("ease_in_time", LLSD(new_ease_in));
+ F32 new_ease_in = llclamp((F32)childGetValue("ease_in_time").asReal(), 0.f, motionp->getDuration() - motionp->getEaseOutDuration());
+ childSetValue("ease_in_time", LLSD(new_ease_in));
}
- return TRUE;
+ return true;
}
//-----------------------------------------------------------------------------
// validateEaseOut()
//-----------------------------------------------------------------------------
-BOOL LLFloaterAnimPreview::validateEaseOut(LLUICtrl* spin, void* data)
+bool LLFloaterAnimPreview::validateEaseOut(const LLSD& data)
{
- LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
+ if (!getEnabled())
+ return false;
- if (!previewp->getEnabled())
- return FALSE;
-
- LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
- LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID);
+ LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar();
+ LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(mMotionID);
if (!motionp->getLoop())
{
- F32 new_ease_out = llclamp((F32)previewp->childGetValue("ease_out_time").asReal(), 0.f, motionp->getDuration() - motionp->getEaseInDuration());
- previewp->childSetValue("ease_out_time", LLSD(new_ease_out));
+ F32 new_ease_out = llclamp((F32)childGetValue("ease_out_time").asReal(), 0.f, motionp->getDuration() - motionp->getEaseInDuration());
+ childSetValue("ease_out_time", LLSD(new_ease_out));
}
- return TRUE;
+ return true;
}
//-----------------------------------------------------------------------------
// validateLoopIn()
//-----------------------------------------------------------------------------
-BOOL LLFloaterAnimPreview::validateLoopIn(LLUICtrl* ctrl, void* data)
+bool LLFloaterAnimPreview::validateLoopIn(const LLSD& data)
{
- LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
- if (!previewp->getEnabled())
- return FALSE;
+ if (!getEnabled())
+ return false;
- F32 loop_in_value = (F32)previewp->childGetValue("loop_in_point").asReal();
- F32 loop_out_value = (F32)previewp->childGetValue("loop_out_point").asReal();
+ F32 loop_in_value = (F32)childGetValue("loop_in_point").asReal();
+ F32 loop_out_value = (F32)childGetValue("loop_out_point").asReal();
if (loop_in_value < 0.f)
{
@@ -878,21 +891,20 @@ BOOL LLFloaterAnimPreview::validateLoopIn(LLUICtrl* ctrl, void* data)
loop_in_value = loop_out_value;
}
- previewp->childSetValue("loop_in_point", LLSD(loop_in_value));
- return TRUE;
+ childSetValue("loop_in_point", LLSD(loop_in_value));
+ return true;
}
//-----------------------------------------------------------------------------
// validateLoopOut()
//-----------------------------------------------------------------------------
-BOOL LLFloaterAnimPreview::validateLoopOut(LLUICtrl* spin, void* data)
+bool LLFloaterAnimPreview::validateLoopOut(const LLSD& data)
{
- LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
- if (!previewp->getEnabled())
- return FALSE;
+ if (!getEnabled())
+ return false;
- F32 loop_out_value = (F32)previewp->childGetValue("loop_out_point").asReal();
- F32 loop_in_value = (F32)previewp->childGetValue("loop_in_point").asReal();
+ F32 loop_out_value = (F32)childGetValue("loop_out_point").asReal();
+ F32 loop_in_value = (F32)childGetValue("loop_in_point").asReal();
if (loop_out_value < 0.f)
{
@@ -907,8 +919,8 @@ BOOL LLFloaterAnimPreview::validateLoopOut(LLUICtrl* spin, void* data)
loop_out_value = loop_in_value;
}
- previewp->childSetValue("loop_out_point", LLSD(loop_out_value));
- return TRUE;
+ childSetValue("loop_out_point", LLSD(loop_out_value));
+ return true;
}
@@ -917,9 +929,12 @@ BOOL LLFloaterAnimPreview::validateLoopOut(LLUICtrl* spin, void* data)
//-----------------------------------------------------------------------------
void LLFloaterAnimPreview::refresh()
{
+ // Are we showing the play button (default) or the pause button?
+ bool show_play = true;
if (!mAnimPreview)
{
childShow("bad_animation_text");
+ // play button visible but disabled
mPlayButton->setEnabled(FALSE);
mStopButton->setEnabled(FALSE);
childDisable("ok_btn");
@@ -927,42 +942,35 @@ void LLFloaterAnimPreview::refresh()
else
{
childHide("bad_animation_text");
+ // re-enabled in case previous animation was bad
mPlayButton->setEnabled(TRUE);
+ mStopButton->setEnabled(TRUE);
LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar();
if (avatarp->isMotionActive(mMotionID))
{
mStopButton->setEnabled(TRUE);
LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(mMotionID);
- if (avatarp->areAnimationsPaused())
- {
-
- mPlayButton->setImages(std::string("button_anim_play.tga"),
- std::string("button_anim_play_selected.tga"));
-
- }
- else
+ if (!avatarp->areAnimationsPaused())
{
+ // animation is playing
if (motionp)
{
F32 fraction_complete = motionp->getLastUpdateTime() / motionp->getDuration();
childSetValue("playback_slider", fraction_complete);
}
- mPlayButton->setImages(std::string("button_anim_pause.tga"),
- std::string("button_anim_pause_selected.tga"));
-
+ show_play = false;
}
}
else
{
+ // Motion just finished playing
mPauseRequest = avatarp->requestPause();
- mPlayButton->setImages(std::string("button_anim_play.tga"),
- std::string("button_anim_play_selected.tga"));
-
- mStopButton->setEnabled(TRUE); // stop also resets, leave enabled.
}
childEnable("ok_btn");
mAnimPreview->requestUpdate();
}
+ mPlayButton->setVisible(show_play);
+ mPauseButton->setVisible(!show_play);
}
//-----------------------------------------------------------------------------
@@ -992,14 +1000,14 @@ void LLFloaterAnimPreview::onBtnOK(void* userdata)
std::string name = floaterp->childGetValue("name_form").asString();
std::string desc = floaterp->childGetValue("description_form").asString();
LLAssetStorage::LLStoreAssetCallback callback = NULL;
- S32 expected_upload_cost = sUploadAmount;
+ S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
void *userdata = NULL;
upload_new_resource(floaterp->mTransactionID, // tid
LLAssetType::AT_ANIMATION,
name,
desc,
0,
- LLAssetType::AT_NONE,
+ LLFolderType::FT_NONE,
LLInventoryType::IT_ANIMATION,
LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(),
name,
@@ -1008,7 +1016,7 @@ void LLFloaterAnimPreview::onBtnOK(void* userdata)
else
{
llwarns << "Failure writing animation data." << llendl;
- LLNotifications::instance().add("WriteAnimationFail");
+ LLNotificationsUtil::add("WriteAnimationFail");
}
}
@@ -1018,13 +1026,13 @@ void LLFloaterAnimPreview::onBtnOK(void* userdata)
LLKeyframeDataCache::removeKeyframeData(floaterp->mMotionID);
}
- floaterp->close(false);
+ floaterp->closeFloater(false);
}
//-----------------------------------------------------------------------------
// LLPreviewAnimation
//-----------------------------------------------------------------------------
-LLPreviewAnimation::LLPreviewAnimation(S32 width, S32 height) : LLDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE)
+LLPreviewAnimation::LLPreviewAnimation(S32 width, S32 height) : LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE)
{
mNeedsUpdate = TRUE;
mCameraDistance = PREVIEW_CAMERA_DISTANCE;
@@ -1070,7 +1078,7 @@ BOOL LLPreviewAnimation::render()
glMatrixMode(GL_PROJECTION);
gGL.pushMatrix();
glLoadIdentity();
- glOrtho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f);
+ glOrtho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
gGL.pushMatrix();
@@ -1080,7 +1088,7 @@ BOOL LLPreviewAnimation::render()
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.color4f(0.15f, 0.2f, 0.3f, 1.f);
- gl_rect_2d_simple( mWidth, mHeight );
+ gl_rect_2d_simple( mFullWidth, mFullHeight );
glMatrixMode(GL_PROJECTION);
gGL.popMatrix();
@@ -1102,7 +1110,7 @@ BOOL LLPreviewAnimation::render()
target_pos + (mCameraOffset * av_rot) ); // point of interest
LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom);
- LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mWidth, mHeight, FALSE);
+ LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE);
mCameraRelPos = LLViewerCamera::getInstance()->getOrigin() - avatarp->mHeadp->getWorldPosition();
diff --git a/indra/newview/llfloateranimpreview.h b/indra/newview/llfloateranimpreview.h
index 639c9277cd..dd2c0b809a 100644
--- a/indra/newview/llfloateranimpreview.h
+++ b/indra/newview/llfloateranimpreview.h
@@ -33,6 +33,7 @@
#ifndef LL_LLFLOATERANIMPREVIEW_H
#define LL_LLFLOATERANIMPREVIEW_H
+#include "llassettype.h"
#include "llfloaternamedesc.h"
#include "lldynamictexture.h"
#include "llcharacter.h"
@@ -41,12 +42,14 @@
class LLVOAvatar;
class LLViewerJointMesh;
-class LLPreviewAnimation : public LLDynamicTexture
+class LLPreviewAnimation : public LLViewerDynamicTexture
{
-public:
- LLPreviewAnimation(S32 width, S32 height);
+protected:
virtual ~LLPreviewAnimation();
+public:
+ LLPreviewAnimation(S32 width, S32 height);
+
BOOL render();
void requestUpdate();
void rotate(F32 yaw_radians, F32 pitch_radians);
@@ -85,23 +88,23 @@ public:
void refresh();
static void onBtnPlay(void*);
+ static void onBtnPause(void*);
static void onBtnStop(void*);
- static void setUploadAmount(S32 amount) { sUploadAmount = amount; }
static void onSliderMove(LLUICtrl*, void*);
static void onCommitBaseAnim(LLUICtrl*, void*);
static void onCommitLoop(LLUICtrl*, void*);
static void onCommitLoopIn(LLUICtrl*, void*);
static void onCommitLoopOut(LLUICtrl*, void*);
- static BOOL validateLoopIn(LLUICtrl*, void*);
- static BOOL validateLoopOut(LLUICtrl*, void*);
+ bool validateLoopIn(const LLSD& data);
+ bool validateLoopOut(const LLSD& data);
static void onCommitName(LLUICtrl*, void*);
static void onCommitHandPose(LLUICtrl*, void*);
static void onCommitEmote(LLUICtrl*, void*);
static void onCommitPriority(LLUICtrl*, void*);
static void onCommitEaseIn(LLUICtrl*, void*);
static void onCommitEaseOut(LLUICtrl*, void*);
- static BOOL validateEaseIn(LLUICtrl*, void*);
- static BOOL validateEaseOut(LLUICtrl*, void*);
+ bool validateEaseIn(const LLSD& data);
+ bool validateEaseOut(const LLSD& data);
static void onBtnOK(void*);
static void onSaveComplete(const LLUUID& asset_uuid,
LLAssetType::EType type,
@@ -114,10 +117,11 @@ protected:
void draw();
void resetMotion();
- LLPreviewAnimation* mAnimPreview;
+ LLPointer< LLPreviewAnimation > mAnimPreview;
S32 mLastMouseX;
S32 mLastMouseY;
LLButton* mPlayButton;
+ LLButton* mPauseButton;
LLButton* mStopButton;
LLRect mPreviewRect;
LLRectf mPreviewImageRect;
@@ -127,8 +131,6 @@ protected:
LLAnimPauseRequest mPauseRequest;
std::map<std::string, LLUUID> mIDList;
-
- static S32 sUploadAmount;
};
#endif // LL_LLFLOATERANIMPREVIEW_H
diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp
index 747431fb19..698ccec9c1 100644
--- a/indra/newview/llfloaterauction.cpp
+++ b/indra/newview/llfloaterauction.cpp
@@ -33,20 +33,23 @@
#include "llviewerprecompiledheaders.h"
#include "llfloaterauction.h"
+#include "llfloaterregioninfo.h"
-#include "lldir.h"
#include "llgl.h"
#include "llimagej2c.h"
#include "llimagetga.h"
#include "llparcel.h"
#include "llvfile.h"
#include "llvfs.h"
+#include "llwindow.h"
+#include "message.h"
#include "llagent.h"
#include "llcombobox.h"
-#include "llnotify.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
#include "llsavedsettingsglue.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
#include "lluictrlfactory.h"
@@ -55,6 +58,8 @@
#include "llviewercontrol.h"
#include "llui.h"
#include "llrender.h"
+#include "llsdutil.h"
+#include "llsdutil_math.h"
///----------------------------------------------------------------------------
/// Local function declarations, constants, enums, and typedefs
@@ -69,45 +74,37 @@ void auction_tga_upload_done(const LLUUID& asset_id,
/// Class llfloaterauction
///----------------------------------------------------------------------------
-LLFloaterAuction* LLFloaterAuction::sInstance = NULL;
-
// Default constructor
-LLFloaterAuction::LLFloaterAuction() :
- LLFloater(std::string("floater_auction")),
+LLFloaterAuction::LLFloaterAuction(const LLSD& key)
+ : LLFloater(key),
mParcelID(-1)
{
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_auction.xml");
-
- childSetValue("fence_check",
- LLSD( gSavedSettings.getBOOL("AuctionShowFence") ) );
- childSetCommitCallback("fence_check",
- LLSavedSettingsGlue::setBOOL, (void*)"AuctionShowFence");
-
- childSetAction("snapshot_btn", onClickSnapshot, this);
- childSetAction("ok_btn", onClickOK, this);
+// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_auction.xml");
+ mCommitCallbackRegistrar.add("ClickSnapshot", boost::bind(&LLFloaterAuction::onClickSnapshot, this));
+ mCommitCallbackRegistrar.add("ClickSellToAnyone", boost::bind(&LLFloaterAuction::onClickSellToAnyone, this));
+ mCommitCallbackRegistrar.add("ClickStartAuction", boost::bind(&LLFloaterAuction::onClickStartAuction, this));
+ mCommitCallbackRegistrar.add("ClickResetParcel", boost::bind(&LLFloaterAuction::onClickResetParcel, this));
}
// Destroys the object
LLFloaterAuction::~LLFloaterAuction()
{
- sInstance = NULL;
}
-// static
-void LLFloaterAuction::show()
+BOOL LLFloaterAuction::postBuild()
{
- if(!sInstance)
- {
- sInstance = new LLFloaterAuction();
- sInstance->center();
- sInstance->setFocus(TRUE);
- }
- sInstance->initialize();
- sInstance->open(); /*Flawfinder: ignore*/
+ return TRUE;
+}
+
+void LLFloaterAuction::onOpen(const LLSD& key)
+{
+ initialize();
}
void LLFloaterAuction::initialize()
{
+ mParcelUpdateCapUrl.clear();
+
mParcelp = LLViewerParcelMgr::getInstance()->getParcelSelection();
LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
LLParcel* parcelp = mParcelp->getParcel();
@@ -115,10 +112,23 @@ void LLFloaterAuction::initialize()
{
mParcelHost = region->getHost();
mParcelID = parcelp->getLocalID();
+ mParcelUpdateCapUrl = region->getCapability("ParcelPropertiesUpdate");
childSetText("parcel_text", parcelp->getName());
childEnable("snapshot_btn");
- childEnable("ok_btn");
+ childEnable("reset_parcel_btn");
+ childEnable("start_auction_btn");
+
+ LLPanelEstateInfo* panel = LLFloaterRegionInfo::getPanelEstate();
+ if (panel)
+ { // Only enable "Sell to Anyone" on Teen grid or if we don't know the ID yet
+ U32 estate_id = panel->getEstateID();
+ childSetEnabled("sell_to_anyone_btn", (estate_id == ESTATE_TEEN || estate_id == 0));
+ }
+ else
+ { // Don't have the panel up, so don't know if we're on the teen grid or not. Default to enabling it
+ childEnable("sell_to_anyone_btn");
+ }
}
else
{
@@ -133,8 +143,11 @@ void LLFloaterAuction::initialize()
}
mParcelID = -1;
childSetEnabled("snapshot_btn", false);
- childSetEnabled("ok_btn", false);
+ childSetEnabled("reset_parcel_btn", false);
+ childSetEnabled("sell_to_anyone_btn", false);
+ childSetEnabled("start_auction_btn", false);
}
+
mImageID.setNull();
mImage = NULL;
}
@@ -176,8 +189,8 @@ void LLFloaterAuction::onClickSnapshot(void* data)
gForceRenderLandFence = self->childGetValue("fence_check").asBoolean();
BOOL success = gViewerWindow->rawSnapshot(raw,
- gViewerWindow->getWindowWidth(),
- gViewerWindow->getWindowHeight(),
+ gViewerWindow->getWindowWidthScaled(),
+ gViewerWindow->getWindowHeightScaled(),
TRUE, FALSE,
FALSE, FALSE);
gForceRenderLandFence = FALSE;
@@ -197,7 +210,7 @@ void LLFloaterAuction::onClickSnapshot(void* data)
tga->encode(raw);
LLVFile::writeFile(tga->getData(), tga->getDataSize(), gVFS, self->mImageID, LLAssetType::AT_IMAGE_TGA);
- raw->biasedScaleToPowerOfTwo(LLViewerImage::MAX_IMAGE_SIZE_DEFAULT);
+ raw->biasedScaleToPowerOfTwo(LLViewerTexture::MAX_IMAGE_SIZE_DEFAULT);
llinfos << "Writing J2C..." << llendl;
@@ -205,7 +218,7 @@ void LLFloaterAuction::onClickSnapshot(void* data)
j2c->encode(raw, 0.0f);
LLVFile::writeFile(j2c->getData(), j2c->getDataSize(), gVFS, self->mImageID, LLAssetType::AT_TEXTURE);
- self->mImage = new LLImageGL((LLImageRaw*)raw, FALSE);
+ self->mImage = LLViewerTextureManager::getLocalTexture((LLImageRaw*)raw, FALSE);
gGL.getTexUnit(0)->bind(self->mImage);
self->mImage->setAddressMode(LLTexUnit::TAM_CLAMP);
}
@@ -216,7 +229,7 @@ void LLFloaterAuction::onClickSnapshot(void* data)
}
// static
-void LLFloaterAuction::onClickOK(void* data)
+void LLFloaterAuction::onClickStartAuction(void* data)
{
LLFloaterAuction* self = (LLFloaterAuction*)(data);
@@ -239,7 +252,7 @@ void LLFloaterAuction::onClickOK(void* data)
FALSE);
self->getWindow()->incBusyCount();
- LLNotifications::instance().add("UploadingAuctionSnapshot");
+ LLNotificationsUtil::add("UploadingAuctionSnapshot");
}
LLMessageSystem* msg = gMessageSystem;
@@ -255,11 +268,264 @@ void LLFloaterAuction::onClickOK(void* data)
msg->sendReliable(self->mParcelHost);
// clean up floater, and get out
- self->mImageID.setNull();
- self->mImage = NULL;
- self->mParcelID = -1;
- self->mParcelHost.invalidate();
- self->close();
+ self->cleanupAndClose();
+}
+
+
+void LLFloaterAuction::cleanupAndClose()
+{
+ mImageID.setNull();
+ mImage = NULL;
+ mParcelID = -1;
+ mParcelHost.invalidate();
+ closeFloater();
+}
+
+
+
+// static glue
+void LLFloaterAuction::onClickResetParcel(void* data)
+{
+ LLFloaterAuction* self = (LLFloaterAuction*)(data);
+ if (self)
+ {
+ self->doResetParcel();
+ }
+}
+
+
+// Reset all the values for the parcel in preparation for a sale
+void LLFloaterAuction::doResetParcel()
+{
+ LLParcel* parcelp = mParcelp->getParcel();
+ LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
+
+ if (parcelp
+ && region
+ && !mParcelUpdateCapUrl.empty())
+ {
+ LLSD body;
+ std::string empty;
+
+ // request new properties update from simulator
+ U32 message_flags = 0x01;
+ body["flags"] = ll_sd_from_U32(message_flags);
+
+ // Set all the default parcel properties for auction
+ body["local_id"] = parcelp->getLocalID();
+
+ U32 parcel_flags = PF_ALLOW_LANDMARK |
+ PF_ALLOW_FLY |
+ PF_CREATE_GROUP_OBJECTS |
+ PF_ALLOW_ALL_OBJECT_ENTRY |
+ PF_ALLOW_GROUP_OBJECT_ENTRY |
+ PF_ALLOW_GROUP_SCRIPTS |
+ PF_RESTRICT_PUSHOBJECT |
+ PF_SOUND_LOCAL |
+ PF_ALLOW_VOICE_CHAT |
+ PF_USE_ESTATE_VOICE_CHAN;
+
+ body["parcel_flags"] = ll_sd_from_U32(parcel_flags);
+
+ // Build a parcel name like "Ahern (128,128) PG 4032m"
+ std::ostringstream parcel_name;
+ LLVector3 center_point( parcelp->getCenterpoint() );
+ center_point.snap(0); // Get rid of fractions
+ parcel_name << region->getName()
+ << " ("
+ << (S32) center_point.mV[VX]
+ << ","
+ << (S32) center_point.mV[VY]
+ << ") "
+ << region->getSimAccessString()
+ << " "
+ << parcelp->getArea()
+ << "m";
+
+ std::string new_name(parcel_name.str().c_str());
+ body["name"] = new_name;
+ childSetText("parcel_text", new_name); // Set name in dialog as well, since it won't get updated otherwise
+
+ body["sale_price"] = (S32) 0;
+ body["description"] = empty;
+ body["music_url"] = empty;
+ body["media_url"] = empty;
+ body["media_desc"] = empty;
+ body["media_type"] = std::string("none/none");
+ body["media_width"] = (S32) 0;
+ body["media_height"] = (S32) 0;
+ body["auto_scale"] = (S32) 0;
+ body["media_loop"] = (S32) 0;
+ body["obscure_media"] = (S32) 0;
+ body["obscure_music"] = (S32) 0;
+ body["media_id"] = LLUUID::null;
+ body["group_id"] = MAINTENANCE_GROUP_ID; // Use maintenance group
+ body["pass_price"] = (S32) 10; // Defaults to $10
+ body["pass_hours"] = 0.0f;
+ body["category"] = (U8) LLParcel::C_NONE;
+ body["auth_buyer_id"] = LLUUID::null;
+ body["snapshot_id"] = LLUUID::null;
+ body["user_location"] = ll_sd_from_vector3( LLVector3::zero );
+ body["user_look_at"] = ll_sd_from_vector3( LLVector3::zero );
+ body["landing_type"] = (U8) LLParcel::L_DIRECT;
+
+ llinfos << "Sending parcel update to reset for auction via capability to: "
+ << mParcelUpdateCapUrl << llendl;
+ LLHTTPClient::post(mParcelUpdateCapUrl, body, new LLHTTPClient::Responder());
+
+ // Send a message to clear the object return time
+ LLMessageSystem *msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_ParcelSetOtherCleanTime);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_ParcelData);
+ msg->addS32Fast(_PREHASH_LocalID, parcelp->getLocalID());
+ msg->addS32Fast(_PREHASH_OtherCleanTime, 5); // 5 minute object auto-return
+
+ msg->sendReliable(region->getHost());
+
+ // Clear the access lists
+ clearParcelAccessLists(parcelp, region);
+ }
+}
+
+
+
+void LLFloaterAuction::clearParcelAccessLists(LLParcel* parcel, LLViewerRegion* region)
+{
+ if (!region || !parcel) return;
+
+ LLUUID transactionUUID;
+ transactionUUID.generate();
+
+ LLMessageSystem* msg = gMessageSystem;
+
+ // Clear access list
+ // parcel->mAccessList.clear();
+
+ msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
+ msg->nextBlockFast(_PREHASH_Data);
+ msg->addU32Fast(_PREHASH_Flags, AL_ACCESS);
+ msg->addS32(_PREHASH_LocalID, parcel->getLocalID() );
+ msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
+ msg->addS32Fast(_PREHASH_SequenceID, 1); // sequence_id
+ msg->addS32Fast(_PREHASH_Sections, 0); // num_sections
+
+ // pack an empty block since there will be no data
+ msg->nextBlockFast(_PREHASH_List);
+ msg->addUUIDFast(_PREHASH_ID, LLUUID::null );
+ msg->addS32Fast(_PREHASH_Time, 0 );
+ msg->addU32Fast(_PREHASH_Flags, 0 );
+
+ msg->sendReliable( region->getHost() );
+
+ // Send message for empty ban list
+ //parcel->mBanList.clear();
+ msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
+ msg->nextBlockFast(_PREHASH_Data);
+ msg->addU32Fast(_PREHASH_Flags, AL_BAN);
+ msg->addS32(_PREHASH_LocalID, parcel->getLocalID() );
+ msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
+ msg->addS32Fast(_PREHASH_SequenceID, 1); // sequence_id
+ msg->addS32Fast(_PREHASH_Sections, 0); // num_sections
+
+ // pack an empty block since there will be no data
+ msg->nextBlockFast(_PREHASH_List);
+ msg->addUUIDFast(_PREHASH_ID, LLUUID::null );
+ msg->addS32Fast(_PREHASH_Time, 0 );
+ msg->addU32Fast(_PREHASH_Flags, 0 );
+
+ msg->sendReliable( region->getHost() );
+}
+
+
+
+// static - 'Sell to Anyone' clicked, throw up a confirmation dialog
+void LLFloaterAuction::onClickSellToAnyone(void* data)
+{
+ LLFloaterAuction* self = (LLFloaterAuction*)(data);
+ if (self)
+ {
+ LLParcel* parcelp = self->mParcelp->getParcel();
+
+ // Do a confirmation
+ S32 sale_price = parcelp->getArea(); // Selling for L$1 per meter
+ S32 area = parcelp->getArea();
+
+ LLSD args;
+ args["LAND_SIZE"] = llformat("%d", area);
+ args["SALE_PRICE"] = llformat("%d", sale_price);
+ args["NAME"] = "Anyone";
+
+ LLNotification::Params params("ConfirmLandSaleChange"); // Re-use existing dialog
+ params.substitutions(args)
+ .functor.function(boost::bind(&LLFloaterAuction::onSellToAnyoneConfirmed, self, _1, _2));
+
+ params.name("ConfirmLandSaleToAnyoneChange");
+
+ // ask away
+ LLNotifications::instance().add(params);
+ }
+}
+
+
+// Sell confirmation clicked
+bool LLFloaterAuction::onSellToAnyoneConfirmed(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option == 0)
+ {
+ doSellToAnyone();
+ }
+
+ return false;
+}
+
+
+
+// Reset all the values for the parcel in preparation for a sale
+void LLFloaterAuction::doSellToAnyone()
+{
+ LLParcel* parcelp = mParcelp->getParcel();
+ LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
+
+ if (parcelp
+ && region
+ && !mParcelUpdateCapUrl.empty())
+ {
+ LLSD body;
+ std::string empty;
+
+ // request new properties update from simulator
+ U32 message_flags = 0x01;
+ body["flags"] = ll_sd_from_U32(message_flags);
+
+ // Set all the default parcel properties for auction
+ body["local_id"] = parcelp->getLocalID();
+
+ // Set 'for sale' flag
+ U32 parcel_flags = parcelp->getParcelFlags() | PF_FOR_SALE;
+ // Ensure objects not included
+ parcel_flags &= ~PF_FOR_SALE_OBJECTS;
+ body["parcel_flags"] = ll_sd_from_U32(parcel_flags);
+
+ body["sale_price"] = parcelp->getArea(); // Sell for L$1 per square meter
+ body["auth_buyer_id"] = LLUUID::null; // To anyone
+
+ llinfos << "Sending parcel update to sell to anyone for L$1 via capability to: "
+ << mParcelUpdateCapUrl << llendl;
+ LLHTTPClient::post(mParcelUpdateCapUrl, body, new LLHTTPClient::Responder());
+
+ // clean up floater, and get out
+ cleanupAndClose();
+ }
}
@@ -278,13 +544,13 @@ void auction_tga_upload_done(const LLUUID& asset_id, void* user_data, S32 status
if (0 == status)
{
- LLNotifications::instance().add("UploadWebSnapshotDone");
+ LLNotificationsUtil::add("UploadWebSnapshotDone");
}
else
{
LLSD args;
args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
- LLNotifications::instance().add("UploadAuctionSnapshotFail", args);
+ LLNotificationsUtil::add("UploadAuctionSnapshotFail", args);
}
}
@@ -299,12 +565,12 @@ void auction_j2c_upload_done(const LLUUID& asset_id, void* user_data, S32 status
if (0 == status)
{
- LLNotifications::instance().add("UploadSnapshotDone");
+ LLNotificationsUtil::add("UploadSnapshotDone");
}
else
{
LLSD args;
args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
- LLNotifications::instance().add("UploadAuctionSnapshotFail", args);
+ LLNotificationsUtil::add("UploadAuctionSnapshotFail", args);
}
}
diff --git a/indra/newview/llfloaterauction.h b/indra/newview/llfloaterauction.h
index e13bce01e1..c599af782d 100644
--- a/indra/newview/llfloaterauction.h
+++ b/indra/newview/llfloaterauction.h
@@ -36,8 +36,8 @@
#include "llfloater.h"
#include "lluuid.h"
-#include "llmemory.h"
-#include "llviewerimage.h"
+#include "llpointer.h"
+#include "llviewertexture.h"
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLFloaterAuction
@@ -45,34 +45,47 @@
// Class which holds the functionality to start auctions.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLParcelSelection;
+class LLParcel;
+class LLViewerRegion;
class LLFloaterAuction : public LLFloater
{
+ friend class LLFloaterReg;
public:
// LLFloater interface
- /*virtual*/ void onClose(bool app_quitting) { setVisible(FALSE); }
+ /*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ void draw();
- // LLFloaterAuction interface
- static void show();
-
private:
- LLFloaterAuction();
+
+ LLFloaterAuction(const LLSD& key);
~LLFloaterAuction();
+
void initialize();
static void onClickSnapshot(void* data);
- static void onClickOK(void* data);
+ static void onClickResetParcel(void* data);
+ static void onClickSellToAnyone(void* data); // Sell to anyone clicked
+ bool onSellToAnyoneConfirmed(const LLSD& notification, const LLSD& response); // Sell confirmation clicked
+ static void onClickStartAuction(void* data);
- static LLFloaterAuction* sInstance;
+ /*virtual*/ BOOL postBuild();
+
+ void doResetParcel();
+ void doSellToAnyone();
+ void clearParcelAccessLists( LLParcel* parcel, LLViewerRegion* region );
+ void cleanupAndClose();
private:
+
LLTransactionID mTransactionID;
LLAssetID mImageID;
- LLPointer<LLImageGL> mImage;
+ LLPointer<LLViewerTexture> mImage;
LLSafeHandle<LLParcelSelection> mParcelp;
S32 mParcelID;
LLHost mParcelHost;
+
+ std::string mParcelUpdateCapUrl; // "ParcelPropertiesUpdate" capability
};
diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp
index e382fefece..a0b2de85f0 100644
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -33,89 +33,85 @@
#include "llfloateravatarpicker.h"
-#include "message.h"
-
+// Viewer includes
#include "llagent.h"
-#include "llbutton.h"
+#include "llcallingcard.h"
#include "llfocusmgr.h"
-#include "llinventoryview.h"
-#include "llinventorymodel.h"
-#include "lllineeditor.h"
-#include "llscrolllistctrl.h"
-#include "lltextbox.h"
-#include "lluictrlfactory.h"
+#include "llfloaterreg.h"
#include "llviewercontrol.h"
#include "llworld.h"
-const S32 MIN_WIDTH = 200;
-const S32 MIN_HEIGHT = 340;
-const LLRect FLOATER_RECT(0, 380, 240, 0);
-const std::string FLOATER_TITLE = "Choose Resident";
-
-// static
-LLFloaterAvatarPicker* LLFloaterAvatarPicker::sInstance = NULL;
-
+// Linden libraries
+#include "llbutton.h"
+#include "lllineeditor.h"
+#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "llscrolllistcell.h"
+#include "lltabcontainer.h"
+#include "lluictrlfactory.h"
+#include "message.h"
-LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(callback_t callback,
- void* userdata,
+LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback,
BOOL allow_multiple,
BOOL closeOnSelect)
{
- // TODO: This class should not be a singleton as it's used in multiple places
- // and therefore can't be used simultaneously. -MG
- if (!sInstance)
- {
- sInstance = new LLFloaterAvatarPicker();
- sInstance->mCallback = callback;
- sInstance->mCallbackUserdata = userdata;
- sInstance->mCloseOnSelect = FALSE;
-
- sInstance->open(); /* Flawfinder: ignore */
- sInstance->center();
- sInstance->setAllowMultiple(allow_multiple);
- }
- else
+ // *TODO: Use a key to allow this not to be an effective singleton
+ LLFloaterAvatarPicker* floater =
+ LLFloaterReg::showTypedInstance<LLFloaterAvatarPicker>("avatar_picker");
+
+ floater->mSelectionCallback = callback;
+ floater->setAllowMultiple(allow_multiple);
+ floater->mNearMeListComplete = FALSE;
+ floater->mCloseOnSelect = closeOnSelect;
+
+ if (!closeOnSelect)
{
- sInstance->open(); /*Flawfinder: ignore*/
- sInstance->mCallback = callback;
- sInstance->mCallbackUserdata = userdata;
- sInstance->setAllowMultiple(allow_multiple);
+ // Use Select/Close
+ std::string select_string = floater->getString("Select");
+ std::string close_string = floater->getString("Close");
+ floater->getChild<LLButton>("ok_btn")->setLabel(select_string);
+ floater->getChild<LLButton>("cancel_btn")->setLabel(close_string);
}
-
- sInstance->mNearMeListComplete = FALSE;
- sInstance->mCloseOnSelect = closeOnSelect;
- return sInstance;
+
+ return floater;
}
// Default constructor
-LLFloaterAvatarPicker::LLFloaterAvatarPicker() :
- LLFloater(std::string("avatarpicker"), FLOATER_RECT, FLOATER_TITLE, TRUE, MIN_WIDTH, MIN_HEIGHT),
- mResultsReturned(FALSE),
- mCallback(NULL),
- mCallbackUserdata(NULL)
+LLFloaterAvatarPicker::LLFloaterAvatarPicker(const LLSD& key)
+ : LLFloater(key),
+ mNumResultsReturned(0),
+ mNearMeListComplete(FALSE),
+ mCloseOnSelect(FALSE)
{
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_avatar_picker.xml", NULL);
+// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_avatar_picker.xml");
+ mCommitCallbackRegistrar.add("Refresh.FriendList", boost::bind(&LLFloaterAvatarPicker::populateFriend, this));
}
BOOL LLFloaterAvatarPicker::postBuild()
{
- childSetKeystrokeCallback("Edit", editKeystroke, this);
+ getChild<LLLineEditor>("Edit")->setKeystrokeCallback( boost::bind(&LLFloaterAvatarPicker::editKeystroke, this, _1, _2),NULL);
- childSetAction("Find", onBtnFind, this);
+ childSetAction("Find", boost::bind(&LLFloaterAvatarPicker::onBtnFind, this));
childDisable("Find");
- childSetAction("Refresh", onBtnRefresh, this);
- childSetCommitCallback("near_me_range", onRangeAdjust, this);
-
- childSetDoubleClickCallback("SearchResults", onBtnSelect);
- childSetDoubleClickCallback("NearMe", onBtnSelect);
- childSetCommitCallback("SearchResults", onList, this);
- childSetCommitCallback("NearMe", onList, this);
+ childSetAction("Refresh", boost::bind(&LLFloaterAvatarPicker::onBtnRefresh, this));
+ getChild<LLUICtrl>("near_me_range")->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onRangeAdjust, this));
+
+ LLScrollListCtrl* searchresults = getChild<LLScrollListCtrl>("SearchResults");
+ searchresults->setDoubleClickCallback( boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this));
+ searchresults->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onList, this));
childDisable("SearchResults");
+
+ LLScrollListCtrl* nearme = getChild<LLScrollListCtrl>("NearMe");
+ nearme->setDoubleClickCallback(boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this));
+ nearme->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onList, this));
- childSetAction("Select", onBtnSelect, this);
- childDisable("Select");
+ LLScrollListCtrl* friends = getChild<LLScrollListCtrl>("Friends");
+ friends->setDoubleClickCallback(boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this));
+ getChild<LLUICtrl>("Friends")->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onList, this));
- childSetAction("Cancel", onBtnClose, this);
+ childSetAction("ok_btn", boost::bind(&LLFloaterAvatarPicker::onBtnSelect, this));
+ childDisable("ok_btn");
+ childSetAction("cancel_btn", boost::bind(&LLFloaterAvatarPicker::onBtnClose, this));
childSetFocus("Edit");
@@ -126,47 +122,39 @@ BOOL LLFloaterAvatarPicker::postBuild()
search_panel->setDefaultBtn("Find");
}
- getChild<LLScrollListCtrl>("SearchResults")->addCommentText(getString("no_results"));
-
- LLInventoryPanel* inventory_panel = getChild<LLInventoryPanel>("InventoryPanel");
- inventory_panel->setFilterTypes(0x1 << LLInventoryType::IT_CALLINGCARD);
- inventory_panel->setFollowsAll();
- inventory_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
- inventory_panel->openDefaultFolderForType(LLAssetType::AT_CALLINGCARD);
- inventory_panel->setSelectCallback(LLFloaterAvatarPicker::onCallingCardSelectionChange, this);
+ getChild<LLScrollListCtrl>("SearchResults")->setCommentText(getString("no_results"));
- childSetTabChangeCallback("ResidentChooserTabs", "SearchPanel", onTabChanged, this);
- childSetTabChangeCallback("ResidentChooserTabs", "CallingCardsPanel", onTabChanged, this);
- childSetTabChangeCallback("ResidentChooserTabs", "NearMePanel", onTabChanged, this);
+ getChild<LLTabContainer>("ResidentChooserTabs")->setCommitCallback(
+ boost::bind(&LLFloaterAvatarPicker::onTabChanged, this));
setAllowMultiple(FALSE);
+
+ center();
+
+ populateFriend();
return TRUE;
}
-void LLFloaterAvatarPicker::onTabChanged(void* userdata, bool from_click)
+void LLFloaterAvatarPicker::setOkBtnEnableCb(validate_callback_t cb)
{
- LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata;
- if (!self)
- {
- return;
- }
-
- self->childSetEnabled("Select", self->visibleItemsSelected());
+ mOkButtonValidateSignal.connect(cb);
+}
+
+void LLFloaterAvatarPicker::onTabChanged()
+{
+ childSetEnabled("ok_btn", isSelectBtnEnabled());
}
// Destroys the object
LLFloaterAvatarPicker::~LLFloaterAvatarPicker()
{
gFocusMgr.releaseFocusIfNeeded( this );
-
- sInstance = NULL;
}
-void LLFloaterAvatarPicker::onBtnFind(void* userdata)
+void LLFloaterAvatarPicker::onBtnFind()
{
- LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata;
- if(self) self->find();
+ find();
}
static void getSelectedAvatarData(const LLScrollListCtrl* from, std::vector<std::string>& avatar_names, std::vector<LLUUID>& avatar_ids)
@@ -183,118 +171,73 @@ static void getSelectedAvatarData(const LLScrollListCtrl* from, std::vector<std:
}
}
-void LLFloaterAvatarPicker::onBtnSelect(void* userdata)
+void LLFloaterAvatarPicker::onBtnSelect()
{
- LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata;
- if(self->mCallback)
- {
- LLPanel* active_panel = self->childGetVisibleTab("ResidentChooserTabs");
+ // If select btn not enabled then do not callback
+ if (!isSelectBtnEnabled())
+ return;
- if(active_panel == self->getChild<LLPanel>("CallingCardsPanel"))
+ if(mSelectionCallback)
+ {
+ std::string acvtive_panel_name;
+ LLScrollListCtrl* list = NULL;
+ LLPanel* active_panel = childGetVisibleTab("ResidentChooserTabs");
+ if(active_panel)
{
- self->mCallback(self->mSelectedInventoryAvatarNames, self->mSelectedInventoryAvatarIDs, self->mCallbackUserdata);
+ acvtive_panel_name = active_panel->getName();
}
- else if(active_panel == self->getChild<LLPanel>("SearchPanel"))
+ if(acvtive_panel_name == "SearchPanel")
{
- std::vector<std::string> avatar_names;
- std::vector<LLUUID> avatar_ids;
- getSelectedAvatarData(self->getChild<LLScrollListCtrl>("SearchResults"), avatar_names, avatar_ids);
- self->mCallback(avatar_names, avatar_ids, self->mCallbackUserdata);
+ list = getChild<LLScrollListCtrl>("SearchResults");
}
- else if(active_panel == self->getChild<LLPanel>("NearMePanel"))
+ else if(acvtive_panel_name == "NearMePanel")
+ {
+ list = getChild<LLScrollListCtrl>("NearMe");
+ }
+ else if (acvtive_panel_name == "FriendsPanel")
+ {
+ list = getChild<LLScrollListCtrl>("Friends");
+ }
+
+ if(list)
{
std::vector<std::string> avatar_names;
std::vector<LLUUID> avatar_ids;
- getSelectedAvatarData(self->getChild<LLScrollListCtrl>("NearMe"), avatar_names, avatar_ids);
- self->mCallback(avatar_names, avatar_ids, self->mCallbackUserdata);
+ getSelectedAvatarData(list, avatar_names, avatar_ids);
+ mSelectionCallback(avatar_names, avatar_ids);
}
}
- self->getChild<LLInventoryPanel>("InventoryPanel")->setSelection(LLUUID::null, FALSE);
- self->getChild<LLScrollListCtrl>("SearchResults")->deselectAllItems(TRUE);
- self->getChild<LLScrollListCtrl>("NearMe")->deselectAllItems(TRUE);
- if(self->mCloseOnSelect)
+ getChild<LLScrollListCtrl>("SearchResults")->deselectAllItems(TRUE);
+ getChild<LLScrollListCtrl>("NearMe")->deselectAllItems(TRUE);
+ getChild<LLScrollListCtrl>("Friends")->deselectAllItems(TRUE);
+ if(mCloseOnSelect)
{
- self->mCloseOnSelect = FALSE;
- self->close();
+ mCloseOnSelect = FALSE;
+ closeFloater();
}
}
-void LLFloaterAvatarPicker::onBtnRefresh(void* userdata)
+void LLFloaterAvatarPicker::onBtnRefresh()
{
- LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata;
- if (!self)
- {
- return;
- }
-
- self->getChild<LLScrollListCtrl>("NearMe")->deleteAllItems();
- self->getChild<LLScrollListCtrl>("NearMe")->addCommentText(self->getString("searching"));
- self->mNearMeListComplete = FALSE;
+ getChild<LLScrollListCtrl>("NearMe")->deleteAllItems();
+ getChild<LLScrollListCtrl>("NearMe")->setCommentText(getString("searching"));
+ mNearMeListComplete = FALSE;
}
-void LLFloaterAvatarPicker::onBtnClose(void* userdata)
+void LLFloaterAvatarPicker::onBtnClose()
{
- LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata;
- if(self) self->close();
+ closeFloater();
}
-void LLFloaterAvatarPicker::onRangeAdjust(LLUICtrl* source, void* data)
+void LLFloaterAvatarPicker::onRangeAdjust()
{
- LLFloaterAvatarPicker::onBtnRefresh(data);
+ onBtnRefresh();
}
-void LLFloaterAvatarPicker::onList(LLUICtrl* ctrl, void* userdata)
+void LLFloaterAvatarPicker::onList()
{
- LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata;
- if (self)
- {
- self->childSetEnabled("Select", self->visibleItemsSelected());
- }
-}
-
-// static callback for inventory picker (select from calling cards)
-void LLFloaterAvatarPicker::onCallingCardSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action, void* data)
-{
- LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)data;
- if (self)
- {
- self->doCallingCardSelectionChange( items, user_action, data );
- }
-}
-
-// Callback for inventory picker (select from calling cards)
-void LLFloaterAvatarPicker::doCallingCardSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action, void* data)
-{
- bool panel_active = (childGetVisibleTab("ResidentChooserTabs") == getChild<LLPanel>("CallingCardsPanel"));
-
- mSelectedInventoryAvatarIDs.clear();
- mSelectedInventoryAvatarNames.clear();
-
- if (panel_active)
- {
- childSetEnabled("Select", FALSE);
- }
-
- std::deque<LLFolderViewItem*>::const_iterator item_it;
- for (item_it = items.begin(); item_it != items.end(); ++item_it)
- {
- LLFolderViewEventListener* listenerp = (*item_it)->getListener();
- if (listenerp->getInventoryType() == LLInventoryType::IT_CALLINGCARD)
- {
- LLInventoryItem* item = gInventory.getItem(listenerp->getUUID());
- if (item)
- {
- mSelectedInventoryAvatarIDs.push_back(item->getCreatorUUID());
- mSelectedInventoryAvatarNames.push_back(listenerp->getName());
- }
- }
- }
-
- if (panel_active)
- {
- childSetEnabled("Select", visibleItemsSelected());
- }
+ childSetEnabled("ok_btn", isSelectBtnEnabled());
}
void LLFloaterAvatarPicker::populateNearMe()
@@ -329,15 +272,15 @@ void LLFloaterAvatarPicker::populateNearMe()
if (empty)
{
childDisable("NearMe");
- childDisable("Select");
- near_me_scroller->addCommentText(getString("no_one_near"));
+ childDisable("ok_btn");
+ near_me_scroller->setCommentText(getString("no_one_near"));
}
else
{
childEnable("NearMe");
- childEnable("Select");
+ childEnable("ok_btn");
near_me_scroller->selectFirstItem();
- onList(near_me_scroller, this);
+ onList();
near_me_scroller->setFocus(TRUE);
}
@@ -347,6 +290,26 @@ void LLFloaterAvatarPicker::populateNearMe()
}
}
+void LLFloaterAvatarPicker::populateFriend()
+{
+ LLScrollListCtrl* friends_scroller = getChild<LLScrollListCtrl>("Friends");
+ friends_scroller->deleteAllItems();
+ LLCollectAllBuddies collector;
+ LLAvatarTracker::instance().applyFunctor(collector);
+ LLCollectAllBuddies::buddy_map_t::iterator it;
+
+
+ for(it = collector.mOnline.begin(); it!=collector.mOnline.end(); it++)
+ {
+ friends_scroller->addStringUUIDItem(it->first, it->second);
+ }
+ for(it = collector.mOffline.begin(); it!=collector.mOffline.end(); it++)
+ {
+ friends_scroller->addStringUUIDItem(it->first, it->second);
+ }
+ friends_scroller->sortByColumnIndex(0, TRUE);
+}
+
void LLFloaterAvatarPicker::draw()
{
LLFloater::draw();
@@ -364,20 +327,20 @@ BOOL LLFloaterAvatarPicker::visibleItemsSelected() const
{
return getChild<LLScrollListCtrl>("SearchResults")->getFirstSelectedIndex() >= 0;
}
- else if(active_panel == getChild<LLPanel>("CallingCardsPanel"))
- {
- return mSelectedInventoryAvatarIDs.size() > 0;
- }
else if(active_panel == getChild<LLPanel>("NearMePanel"))
{
return getChild<LLScrollListCtrl>("NearMe")->getFirstSelectedIndex() >= 0;
}
+ else if(active_panel == getChild<LLPanel>("FriendsPanel"))
+ {
+ return getChild<LLScrollListCtrl>("Friends")->getFirstSelectedIndex() >= 0;
+ }
return FALSE;
}
void LLFloaterAvatarPicker::find()
{
- const std::string& text = childGetValue("Edit").asString();
+ std::string text = childGetValue("Edit").asString();
mQueryID.generate();
@@ -394,17 +357,17 @@ void LLFloaterAvatarPicker::find()
gAgent.sendReliableMessage();
getChild<LLScrollListCtrl>("SearchResults")->deleteAllItems();
- getChild<LLScrollListCtrl>("SearchResults")->addCommentText(getString("searching"));
+ getChild<LLScrollListCtrl>("SearchResults")->setCommentText(getString("searching"));
- childSetEnabled("Select", FALSE);
- mResultsReturned = FALSE;
+ childSetEnabled("ok_btn", FALSE);
+ mNumResultsReturned = 0;
}
void LLFloaterAvatarPicker::setAllowMultiple(BOOL allow_multiple)
{
getChild<LLScrollListCtrl>("SearchResults")->setAllowMultipleSelection(allow_multiple);
- getChild<LLInventoryPanel>("InventoryPanel")->setAllowMultiSelect(allow_multiple);
getChild<LLScrollListCtrl>("NearMe")->setAllowMultipleSelection(allow_multiple);
+ getChild<LLScrollListCtrl>("Friends")->setAllowMultipleSelection(allow_multiple);
}
// static
@@ -421,23 +384,22 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void*
// Not for us
if (agent_id != gAgent.getID()) return;
-
- // Dialog already closed
- LLFloaterAvatarPicker *self = sInstance;
- if (!self) return;
+
+ LLFloaterAvatarPicker* floater = LLFloaterReg::findTypedInstance<LLFloaterAvatarPicker>("avatar_picker");
// these are not results from our last request
- if (query_id != self->mQueryID)
+ if (query_id != floater->mQueryID)
{
return;
}
- LLScrollListCtrl* search_results = self->getChild<LLScrollListCtrl>("SearchResults");
+ LLScrollListCtrl* search_results = floater->getChild<LLScrollListCtrl>("SearchResults");
// clear "Searching" label on first results
- search_results->deleteAllItems();
-
- self->mResultsReturned = TRUE;
+ if (floater->mNumResultsReturned++ == 0)
+ {
+ search_results->deleteAllItems();
+ }
BOOL found_one = FALSE;
S32 num_new_rows = msg->getNumberOfBlocks("Data");
@@ -451,10 +413,10 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void*
if (avatar_id.isNull())
{
LLStringUtil::format_map_t map;
- map["[TEXT]"] = self->childGetText("Edit");
- avatar_name = self->getString("not_found", map);
+ map["[TEXT]"] = floater->childGetText("Edit");
+ avatar_name = floater->getString("not_found", map);
search_results->setEnabled(FALSE);
- self->childDisable("Select");
+ floater->childDisable("ok_btn");
}
else
{
@@ -470,9 +432,9 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void*
if (found_one)
{
- self->childEnable("Select");
+ floater->childEnable("ok_btn");
search_results->selectFirstItem();
- self->onList(search_results, self);
+ floater->onList();
search_results->setFocus(TRUE);
}
}
@@ -480,8 +442,7 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void*
//static
void LLFloaterAvatarPicker::editKeystroke(LLLineEditor* caller, void* user_data)
{
- LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)user_data;
- self->childSetEnabled("Find", caller->getText().size() >= 3);
+ childSetEnabled("Find", caller->getText().size() >= 3);
}
// virtual
@@ -491,19 +452,59 @@ BOOL LLFloaterAvatarPicker::handleKeyHere(KEY key, MASK mask)
{
if (childHasFocus("Edit"))
{
- onBtnFind(this);
+ onBtnFind();
}
else
{
- onBtnSelect(this);
+ onBtnSelect();
}
return TRUE;
}
else if (key == KEY_ESCAPE && mask == MASK_NONE)
{
- close();
+ closeFloater();
return TRUE;
}
return LLFloater::handleKeyHere(key, mask);
}
+
+bool LLFloaterAvatarPicker::isSelectBtnEnabled()
+{
+ bool ret_val = visibleItemsSelected();
+
+ if ( ret_val && mOkButtonValidateSignal.num_slots() )
+ {
+ std::string acvtive_panel_name;
+ LLScrollListCtrl* list = NULL;
+ LLPanel* active_panel = childGetVisibleTab("ResidentChooserTabs");
+
+ if(active_panel)
+ {
+ acvtive_panel_name = active_panel->getName();
+ }
+
+ if(acvtive_panel_name == "SearchPanel")
+ {
+ list = getChild<LLScrollListCtrl>("SearchResults");
+ }
+ else if(acvtive_panel_name == "NearMePanel")
+ {
+ list = getChild<LLScrollListCtrl>("NearMe");
+ }
+ else if (acvtive_panel_name == "FriendsPanel")
+ {
+ list = getChild<LLScrollListCtrl>("Friends");
+ }
+
+ if(list)
+ {
+ std::vector<LLUUID> avatar_ids;
+ std::vector<std::string> avatar_names;
+ getSelectedAvatarData(list, avatar_names, avatar_ids);
+ return mOkButtonValidateSignal(avatar_ids);
+ }
+ }
+
+ return ret_val;
+}
diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h
index 56bc387bce..e35466cec8 100644
--- a/indra/newview/llfloateravatarpicker.h
+++ b/indra/newview/llfloateravatarpicker.h
@@ -37,37 +37,42 @@
#include <vector>
-
class LLFloaterAvatarPicker : public LLFloater
{
public:
- // Call this to select an avatar.
+ typedef boost::signals2::signal<bool(const std::vector<LLUUID>&), boost_boolean_combiner> validate_signal_t;
+ typedef validate_signal_t::slot_type validate_callback_t;
+
// The callback function will be called with an avatar name and UUID.
- typedef void(*callback_t)(const std::vector<std::string>&, const std::vector<LLUUID>&, void*);
- static LLFloaterAvatarPicker* show(callback_t callback,
- void* userdata,
+ typedef boost::function<void (const std::vector<std::string>&, const std::vector<LLUUID>&)> select_callback_t;
+ // Call this to select an avatar.
+ static LLFloaterAvatarPicker* show(select_callback_t callback,
BOOL allow_multiple = FALSE,
BOOL closeOnSelect = FALSE);
+
+ LLFloaterAvatarPicker(const LLSD& key);
+ virtual ~LLFloaterAvatarPicker();
+
virtual BOOL postBuild();
+ void setOkBtnEnableCb(validate_callback_t cb);
+
static void processAvatarPickerReply(class LLMessageSystem* msg, void**);
private:
+ void editKeystroke(class LLLineEditor* caller, void* user_data);
- static void editKeystroke(class LLLineEditor* caller, void* user_data);
-
- static void onBtnFind(void* userdata);
- static void onBtnSelect(void* userdata);
- static void onBtnRefresh(void* userdata);
- static void onRangeAdjust(LLUICtrl* source, void* data);
- static void onBtnClose(void* userdata);
- static void onList(class LLUICtrl* ctrl, void* userdata);
- static void onTabChanged(void* userdata, bool from_click);
-
- void doCallingCardSelectionChange(const std::deque<class LLFolderViewItem*> &items, BOOL user_action, void* data);
- static void onCallingCardSelectionChange(const std::deque<class LLFolderViewItem*> &items, BOOL user_action, void* data);
+ void onBtnFind();
+ void onBtnSelect();
+ void onBtnRefresh();
+ void onRangeAdjust();
+ void onBtnClose();
+ void onList();
+ void onTabChanged();
+ bool isSelectBtnEnabled();
void populateNearMe();
+ void populateFriend();
BOOL visibleItemsSelected() const; // Returns true if any items in the current tab are selected.
void find();
@@ -76,21 +81,13 @@ private:
virtual void draw();
virtual BOOL handleKeyHere(KEY key, MASK mask);
- std::vector<LLUUID> mSelectedInventoryAvatarIDs;
- std::vector<std::string> mSelectedInventoryAvatarNames;
LLUUID mQueryID;
- BOOL mResultsReturned;
+ int mNumResultsReturned;
BOOL mNearMeListComplete;
BOOL mCloseOnSelect;
- void (*mCallback)(const std::vector<std::string>& name, const std::vector<LLUUID>& id, void* userdata);
- void* mCallbackUserdata;
-
- static LLFloaterAvatarPicker* sInstance;
-
- // do not call these directly
- LLFloaterAvatarPicker();
- virtual ~LLFloaterAvatarPicker();
+ validate_signal_t mOkButtonValidateSignal;
+ select_callback_t mSelectionCallback;
};
#endif
diff --git a/indra/newview/llfloateravatartextures.cpp b/indra/newview/llfloateravatartextures.cpp
index e81b5d7fce..8c7899af3e 100644
--- a/indra/newview/llfloateravatartextures.cpp
+++ b/indra/newview/llfloateravatartextures.cpp
@@ -39,35 +39,21 @@
#include "lluictrlfactory.h"
#include "llviewerobjectlist.h"
#include "llvoavatar.h"
+#include "llagentwearables.h"
using namespace LLVOAvatarDefines;
-LLFloaterAvatarTextures::LLFloaterAvatarTextures(const LLUUID& id) :
- LLFloater(std::string("avatar_texture_debug")),
- mID(id)
+LLFloaterAvatarTextures::LLFloaterAvatarTextures(const LLSD& id)
+ : LLFloater(id),
+ mID(id.asUUID())
{
+// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_avatar_textures.xml");
}
LLFloaterAvatarTextures::~LLFloaterAvatarTextures()
{
}
-LLFloaterAvatarTextures* LLFloaterAvatarTextures::show(const LLUUID &id)
-{
-
- LLFloaterAvatarTextures* floaterp = new LLFloaterAvatarTextures(id);
-
- // Builds and adds to gFloaterView
- LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_avatar_textures.xml");
-
- gFloaterView->addChild(floaterp);
- floaterp->open(); /*Flawfinder: ignore*/
-
- gFloaterView->adjustToFitScreen(floaterp, FALSE);
-
- return floaterp;
-}
-
BOOL LLFloaterAvatarTextures::postBuild()
{
for (U32 i=0; i < TEX_NUM_INDICES; i++)
@@ -94,7 +80,26 @@ static void update_texture_ctrl(LLVOAvatar* avatarp,
LLTextureCtrl* ctrl,
ETextureIndex te)
{
- LLUUID id = avatarp->getTE(te)->getID();
+ LLUUID id = IMG_DEFAULT_AVATAR;
+ const LLVOAvatarDictionary::TextureEntry* tex_entry = LLVOAvatarDictionary::getInstance()->getTexture(te);
+ if (tex_entry->mIsLocalTexture)
+ {
+ const EWearableType wearable_type = tex_entry->mWearableType;
+ LLWearable *wearable = gAgentWearables.getWearable(wearable_type, 0);
+ if (wearable)
+ {
+ LLLocalTextureObject *lto = wearable->getLocalTextureObject(te);
+ if (lto)
+ {
+ id = lto->getID();
+ }
+ }
+ }
+ else
+ {
+ id = avatarp->getTE(te)->getID();
+ }
+ //id = avatarp->getTE(te)->getID();
if (id == IMG_DEFAULT_AVATAR)
{
ctrl->setImageAssetID(LLUUID::null);
@@ -142,7 +147,7 @@ void LLFloaterAvatarTextures::refresh()
}
else
{
- setTitle(mTitle + ": INVALID AVATAR (" + mID.asString() + ")");
+ setTitle(mTitle + ": " + getString("InvalidAvatar") + " (" + mID.asString() + ")");
}
}
@@ -167,7 +172,32 @@ void LLFloaterAvatarTextures::onClickDump(void* data)
const LLTextureEntry* te = avatarp->getTE(i);
if (!te) continue;
- llinfos << "Avatar TE " << i << " id " << te->getID() << llendl;
+ if (LLVOAvatar::isIndexLocalTexture((ETextureIndex)i))
+ {
+ LLUUID id = IMG_DEFAULT_AVATAR;
+ EWearableType wearable_type = LLVOAvatarDictionary::getInstance()->getTEWearableType((ETextureIndex)i);
+ LLWearable *wearable = gAgentWearables.getWearable(wearable_type, 0);
+ if (wearable)
+ {
+ LLLocalTextureObject *lto = wearable->getLocalTextureObject(i);
+ if (lto)
+ {
+ id = lto->getID();
+ }
+ }
+ if (id != IMG_DEFAULT_AVATAR)
+ {
+ llinfos << "Avatar TE " << i << " id " << id << llendl;
+ }
+ else
+ {
+ llinfos << "Avatar TE " << i << " id " << "<DEFAULT>" << llendl;
+ }
+ }
+ else
+ {
+ llinfos << "Avatar TE " << i << " id " << te->getID() << llendl;
+ }
}
#endif
}
diff --git a/indra/newview/llfloateravatartextures.h b/indra/newview/llfloateravatartextures.h
index 4138edeb4d..e27484d26f 100644
--- a/indra/newview/llfloateravatartextures.h
+++ b/indra/newview/llfloateravatartextures.h
@@ -43,7 +43,7 @@ class LLTextureCtrl;
class LLFloaterAvatarTextures : public LLFloater
{
public:
- LLFloaterAvatarTextures(const LLUUID& id);
+ LLFloaterAvatarTextures(const LLSD& id);
virtual ~LLFloaterAvatarTextures();
/*virtual*/ BOOL postBuild();
@@ -51,8 +51,6 @@ public:
void refresh();
- static LLFloaterAvatarTextures* show(const LLUUID& id);
-
private:
static void onClickDump(void*);
diff --git a/indra/newview/llfloaterbeacons.cpp b/indra/newview/llfloaterbeacons.cpp
index 5476b35dc8..13a7888f60 100644
--- a/indra/newview/llfloaterbeacons.cpp
+++ b/indra/newview/llfloaterbeacons.cpp
@@ -40,8 +40,9 @@
LLFloaterBeacons::LLFloaterBeacons(const LLSD& seed)
+: LLFloater(seed)
{
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_beacons.xml");
+// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_beacons.xml");
// Initialize pipeline states from saved settings.
// OK to do at floater constructor time because beacons do not display unless the floater is open
@@ -55,44 +56,21 @@ LLFloaterBeacons::LLFloaterBeacons(const LLSD& seed)
LLPipeline::setRenderParticleBeacons( gSavedSettings.getBOOL("particlesbeacon"));
LLPipeline::setRenderHighlights( gSavedSettings.getBOOL("renderhighlights"));
LLPipeline::setRenderBeacons( gSavedSettings.getBOOL("renderbeacons"));
+ mCommitCallbackRegistrar.add("Beacons.UICheck", boost::bind(&LLFloaterBeacons::onClickUICheck, this,_1));
}
BOOL LLFloaterBeacons::postBuild()
{
- childSetCommitCallback("touch_only", onClickUICheck, this);
- childSetCommitCallback("scripted", onClickUICheck, this);
- childSetCommitCallback("physical", onClickUICheck, this);
- childSetCommitCallback("sounds", onClickUICheck, this);
- childSetCommitCallback("particles", onClickUICheck, this);
- childSetCommitCallback("highlights", onClickUICheck, this);
- childSetCommitCallback("beacons", onClickUICheck, this);
return TRUE;
}
-// Needed to make the floater visibility toggle the beacons.
-// Too bad we can't just add control_name="BeaconAlwaysOn" to the XML.
-void LLFloaterBeacons::open()
-{
- LLFloater::open();
- gSavedSettings.setBOOL( "BeaconAlwaysOn", TRUE);
-}
-void LLFloaterBeacons::close(bool app_quitting)
-{
- LLFloater::close(app_quitting);
- if(!app_quitting)
- {
- gSavedSettings.setBOOL( "BeaconAlwaysOn", FALSE);
- }
-}
-
// Callback attached to each check box control to both affect their main purpose
// and to implement the couple screwy interdependency rules that some have.
-//static
-void LLFloaterBeacons::onClickUICheck(LLUICtrl *ctrl, void* data)
+
+void LLFloaterBeacons::onClickUICheck(LLUICtrl *ctrl)
{
LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
std::string name = check->getName();
- LLFloaterBeacons* view = (LLFloaterBeacons*)data;
if( name == "touch_only")
{
LLPipeline::toggleRenderScriptedTouchBeacons(NULL);
@@ -102,8 +80,8 @@ void LLFloaterBeacons::onClickUICheck(LLUICtrl *ctrl, void* data)
LLPipeline::getRenderScriptedBeacons(NULL) )
{
LLPipeline::setRenderScriptedBeacons(FALSE);
- view->getChild<LLCheckBoxCtrl>("scripted")->setControlValue(LLSD(FALSE));
- view->getChild<LLCheckBoxCtrl>("touch_only")->setControlValue(LLSD(TRUE)); // just to be sure it's in sync with llpipeline
+ getChild<LLCheckBoxCtrl>("scripted")->setControlValue(LLSD(FALSE));
+ getChild<LLCheckBoxCtrl>("touch_only")->setControlValue(LLSD(TRUE)); // just to be sure it's in sync with llpipeline
}
}
else if(name == "scripted")
@@ -115,8 +93,8 @@ void LLFloaterBeacons::onClickUICheck(LLUICtrl *ctrl, void* data)
LLPipeline::getRenderScriptedBeacons(NULL) )
{
LLPipeline::setRenderScriptedTouchBeacons(FALSE);
- view->getChild<LLCheckBoxCtrl>("touch_only")->setControlValue(LLSD(FALSE));
- view->getChild<LLCheckBoxCtrl>("scripted")->setControlValue(LLSD(TRUE)); // just to be sure it's in sync with llpipeline
+ getChild<LLCheckBoxCtrl>("touch_only")->setControlValue(LLSD(FALSE));
+ getChild<LLCheckBoxCtrl>("scripted")->setControlValue(LLSD(TRUE)); // just to be sure it's in sync with llpipeline
}
}
else if(name == "physical") LLPipeline::setRenderPhysicalBeacons(check->get());
@@ -131,8 +109,8 @@ void LLFloaterBeacons::onClickUICheck(LLUICtrl *ctrl, void* data)
!LLPipeline::getRenderHighlights(NULL) )
{
LLPipeline::setRenderBeacons(TRUE);
- view->getChild<LLCheckBoxCtrl>("beacons")->setControlValue(LLSD(TRUE));
- view->getChild<LLCheckBoxCtrl>("highlights")->setControlValue(LLSD(FALSE)); // just to be sure it's in sync with llpipeline
+ getChild<LLCheckBoxCtrl>("beacons")->setControlValue(LLSD(TRUE));
+ getChild<LLCheckBoxCtrl>("highlights")->setControlValue(LLSD(FALSE)); // just to be sure it's in sync with llpipeline
}
}
else if(name == "beacons")
@@ -144,8 +122,8 @@ void LLFloaterBeacons::onClickUICheck(LLUICtrl *ctrl, void* data)
!LLPipeline::getRenderHighlights(NULL) )
{
LLPipeline::setRenderHighlights(TRUE);
- view->getChild<LLCheckBoxCtrl>("highlights")->setControlValue(LLSD(TRUE));
- view->getChild<LLCheckBoxCtrl>("beacons")->setControlValue(LLSD(FALSE)); // just to be sure it's in sync with llpipeline
+ getChild<LLCheckBoxCtrl>("highlights")->setControlValue(LLSD(TRUE));
+ getChild<LLCheckBoxCtrl>("beacons")->setControlValue(LLSD(FALSE)); // just to be sure it's in sync with llpipeline
}
}
}
diff --git a/indra/newview/llfloaterbeacons.h b/indra/newview/llfloaterbeacons.h
index c12bdd7261..c175cb3ef4 100644
--- a/indra/newview/llfloaterbeacons.h
+++ b/indra/newview/llfloaterbeacons.h
@@ -36,22 +36,20 @@
#include "llfloater.h"
-class LLFloaterBeacons : public LLFloater, public LLFloaterSingleton<LLFloaterBeacons>
+class LLFloaterBeacons : public LLFloater
{
- friend class LLUISingleton<LLFloaterBeacons, VisibilityPolicy<LLFloater> >;
+ friend class LLFloaterReg;
public:
+
/*virtual*/ BOOL postBuild();
// Needed to make the floater visibility toggle the beacons.
// Too bad we can't just add control_name="BeaconAlwaysOn" to the XML.
- /*virtual*/ void open();
- /*virtual*/ void close(bool app_quitting);
+ void onClickUICheck(LLUICtrl *ctrl);
private:
LLFloaterBeacons(const LLSD& seed);
-
- static void onClickUICheck(LLUICtrl *ctrl, void* data);
};
#endif
diff --git a/indra/newview/llfloaterbuildoptions.cpp b/indra/newview/llfloaterbuildoptions.cpp
index 3cd35db19c..30e9428df9 100644
--- a/indra/newview/llfloaterbuildoptions.cpp
+++ b/indra/newview/llfloaterbuildoptions.cpp
@@ -40,58 +40,16 @@
#include "llfloaterbuildoptions.h"
#include "lluictrlfactory.h"
-// library includes
-#include "llfontgl.h"
-#include "llcheckboxctrl.h"
-#include "llspinctrl.h"
-#include "llsliderctrl.h"
-
-// newview includes
-#include "llresmgr.h"
-#include "llviewercontrol.h"
-
-//
-// Globals
-//
-LLFloaterBuildOptions *LLFloaterBuildOptions::sInstance = NULL;
-
//
// Methods
//
-LLFloaterBuildOptions::LLFloaterBuildOptions( )
-: LLFloater(std::string("build options floater"))
+LLFloaterBuildOptions::LLFloaterBuildOptions(const LLSD& key)
+ : LLFloater(key)
{
- sInstance = this;
+ //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_build_options.xml");
}
LLFloaterBuildOptions::~LLFloaterBuildOptions()
{
- sInstance = NULL;
-}
-
-// static
-void LLFloaterBuildOptions::show(void*)
-{
- if (sInstance)
- {
- sInstance->open(); /*Flawfinder: ignore*/
- }
- else
- {
- LLFloaterBuildOptions* floater = new LLFloaterBuildOptions();
-
- LLUICtrlFactory::getInstance()->buildFloater(floater, "floater_build_options.xml");
- floater->open(); /*Flawfinder: ignore*/
- }
}
-LLFloaterBuildOptions* LLFloaterBuildOptions::getInstance()
-{
- return sInstance;
-}
-
-// static
-BOOL LLFloaterBuildOptions::visible(void*)
-{
- return (sInstance != NULL);
-}
diff --git a/indra/newview/llfloaterbuildoptions.h b/indra/newview/llfloaterbuildoptions.h
index e030b063d9..43cbb201c2 100644
--- a/indra/newview/llfloaterbuildoptions.h
+++ b/indra/newview/llfloaterbuildoptions.h
@@ -42,19 +42,12 @@
class LLFloaterBuildOptions
-: public LLFloater
+ : public LLFloater
{
-protected:
- LLFloaterBuildOptions();
+ friend class LLFloaterReg;
+private:
+ LLFloaterBuildOptions(const LLSD& key);
~LLFloaterBuildOptions();
-
-public:
- static void show(void*);
- static LLFloaterBuildOptions* getInstance();
- static BOOL visible(void*);
-
-protected:
- static LLFloaterBuildOptions* sInstance;
};
#endif
diff --git a/indra/newview/llfloaterbulkpermission.cpp b/indra/newview/llfloaterbulkpermission.cpp
index d4e1e98125..5c3a54e34b 100644
--- a/indra/newview/llfloaterbulkpermission.cpp
+++ b/indra/newview/llfloaterbulkpermission.cpp
@@ -48,25 +48,30 @@
#include "llresmgr.h"
#include "llbutton.h"
#include "lldir.h"
-#include "llfloaterchat.h"
#include "llviewerstats.h"
#include "lluictrlfactory.h"
#include "llselectmgr.h"
+#include "llcheckboxctrl.h"
#include "roles_constants.h" // for GP_OBJECT_MANIPULATE
-LLFloaterBulkPermission::LLFloaterBulkPermission(const LLSD& seed) : mDone(FALSE)
+LLFloaterBulkPermission::LLFloaterBulkPermission(const LLSD& seed)
+: LLFloater(seed),
+ mDone(FALSE)
{
mID.generate();
- LLUICtrlFactory::getInstance()->buildFloater(this,"floater_bulk_perms.xml");
- childSetEnabled("next_owner_transfer", gSavedSettings.getBOOL("BulkChangeNextOwnerCopy"));
- childSetAction("help", onHelpBtn, this);
- childSetAction("apply", onApplyBtn, this);
- childSetAction("close", onCloseBtn, this);
- childSetAction("check_all", onCheckAll, this);
- childSetAction("check_none", onUncheckAll, this);
- childSetCommitCallback("next_owner_copy", &onCommitCopy, this);
+// LLUICtrlFactory::getInstance()->buildFloater(this,"floater_bulk_perms.xml");
+ mCommitCallbackRegistrar.add("BulkPermission.Apply", boost::bind(&LLFloaterBulkPermission::onApplyBtn, this));
+ mCommitCallbackRegistrar.add("BulkPermission.Close", boost::bind(&LLFloaterBulkPermission::onCloseBtn, this));
+ mCommitCallbackRegistrar.add("BulkPermission.CheckAll", boost::bind(&LLFloaterBulkPermission::onCheckAll, this));
+ mCommitCallbackRegistrar.add("BulkPermission.UncheckAll", boost::bind(&LLFloaterBulkPermission::onUncheckAll, this));
+ mCommitCallbackRegistrar.add("BulkPermission.CommitCopy", boost::bind(&LLFloaterBulkPermission::onCommitCopy, this));
+}
+
+BOOL LLFloaterBulkPermission::postBuild()
+{
+ return TRUE;
}
void LLFloaterBulkPermission::doApply()
@@ -93,7 +98,7 @@ void LLFloaterBulkPermission::doApply()
LLSelectMgr::getInstance()->getSelection()->applyToNodes(&gatherer);
if(mObjectIDs.empty())
{
- list->addCommentText(getString("nothing_to_modify_text"));
+ list->setCommentText(getString("nothing_to_modify_text"));
}
else
{
@@ -144,41 +149,33 @@ void LLFloaterBulkPermission::inventoryChanged(LLViewerObject* viewer_object,
}
}
-void LLFloaterBulkPermission::onApplyBtn(void* user_data)
-{
- LLFloaterBulkPermission* self = static_cast<LLFloaterBulkPermission*>(user_data);
- self->doApply();
-}
-
-void LLFloaterBulkPermission::onHelpBtn(void* user_data)
+void LLFloaterBulkPermission::onApplyBtn()
{
- LLNotifications::instance().add("HelpBulkPermission");
+ doApply();
}
-void LLFloaterBulkPermission::onCloseBtn(void* user_data)
+void LLFloaterBulkPermission::onCloseBtn()
{
- LLFloaterBulkPermission* self = static_cast<LLFloaterBulkPermission*>(user_data);
- self->onClose(false);
+ closeFloater();
}
//static
-void LLFloaterBulkPermission::onCommitCopy(LLUICtrl* ctrl, void* data)
+void LLFloaterBulkPermission::onCommitCopy()
{
- LLFloaterBulkPermission* self = static_cast<LLFloaterBulkPermission*>(data);
// Implements fair use
BOOL copyable = gSavedSettings.getBOOL("BulkChangeNextOwnerCopy");
if(!copyable)
{
gSavedSettings.setBOOL("BulkChangeNextOwnerTransfer", TRUE);
}
- LLCheckBoxCtrl* xfer = self->getChild<LLCheckBoxCtrl>("next_owner_transfer");
+ LLCheckBoxCtrl* xfer =getChild<LLCheckBoxCtrl>("next_owner_transfer");
xfer->setEnabled(copyable);
}
BOOL LLFloaterBulkPermission::start()
{
// note: number of top-level objects to modify is mObjectIDs.count().
- getChild<LLScrollListCtrl>("queue output")->addCommentText(getString("start_text"));
+ getChild<LLScrollListCtrl>("queue output")->setCommentText(getString("start_text"));
return nextObject();
}
@@ -201,7 +198,7 @@ BOOL LLFloaterBulkPermission::nextObject()
if(isDone() && !mDone)
{
- getChild<LLScrollListCtrl>("queue output")->addCommentText(getString("done_text"));
+ getChild<LLScrollListCtrl>("queue output")->setCommentText(getString("done_text"));
mDone = TRUE;
}
return successful_start;
@@ -244,7 +241,6 @@ void LLFloaterBulkPermission::doCheckUncheckAll(BOOL check)
gSavedSettings.setBOOL("BulkChangeIncludeBodyParts" , check);
gSavedSettings.setBOOL("BulkChangeIncludeClothing" , check);
gSavedSettings.setBOOL("BulkChangeIncludeGestures" , check);
- gSavedSettings.setBOOL("BulkChangeIncludeLandmarks" , check);
gSavedSettings.setBOOL("BulkChangeIncludeNotecards" , check);
gSavedSettings.setBOOL("BulkChangeIncludeObjects" , check);
gSavedSettings.setBOOL("BulkChangeIncludeScripts" , check);
@@ -267,7 +263,6 @@ void LLFloaterBulkPermission::handleInventory(LLViewerObject* viewer_obj, Invent
( asstype == LLAssetType::AT_BODYPART && gSavedSettings.getBOOL("BulkChangeIncludeBodyParts" )) ||
( asstype == LLAssetType::AT_CLOTHING && gSavedSettings.getBOOL("BulkChangeIncludeClothing" )) ||
( asstype == LLAssetType::AT_GESTURE && gSavedSettings.getBOOL("BulkChangeIncludeGestures" )) ||
- ( asstype == LLAssetType::AT_LANDMARK && gSavedSettings.getBOOL("BulkChangeIncludeLandmarks" )) ||
( asstype == LLAssetType::AT_NOTECARD && gSavedSettings.getBOOL("BulkChangeIncludeNotecards" )) ||
( asstype == LLAssetType::AT_OBJECT && gSavedSettings.getBOOL("BulkChangeIncludeObjects" )) ||
( asstype == LLAssetType::AT_LSL_TEXT && gSavedSettings.getBOOL("BulkChangeIncludeScripts" )) ||
@@ -317,7 +312,7 @@ void LLFloaterBulkPermission::handleInventory(LLViewerObject* viewer_obj, Invent
status_text.setArg("[STATUS]", "");
}
- list->addCommentText(status_text.getString());
+ list->setCommentText(status_text.getString());
//TODO if we are an object inside an object we should check a recuse flag and if set
//open the inventory of the object and recurse - Michelle2 Zenovka
diff --git a/indra/newview/llfloaterbulkpermission.h b/indra/newview/llfloaterbulkpermission.h
index a26b5b4f79..31f4f5c3e1 100644
--- a/indra/newview/llfloaterbulkpermission.h
+++ b/indra/newview/llfloaterbulkpermission.h
@@ -46,13 +46,16 @@
#include "llviewerinventory.h"
-class LLFloaterBulkPermission : public LLFloater, public LLVOInventoryListener, public LLFloaterSingleton<LLFloaterBulkPermission>
+class LLFloaterBulkPermission : public LLFloater, public LLVOInventoryListener
{
+ friend class LLFloaterReg;
public:
- LLFloaterBulkPermission(const LLSD& seed);
+ BOOL postBuild();
private:
+
+ LLFloaterBulkPermission(const LLSD& seed);
virtual ~LLFloaterBulkPermission() {}
BOOL start(); // returns TRUE if the queue has started, otherwise FALSE.
@@ -76,12 +79,11 @@ private:
U8 key,
bool is_new);
- static void onHelpBtn(void* user_data);
- static void onCloseBtn(void* user_data);
- static void onApplyBtn(void* user_data);
- static void onCommitCopy(LLUICtrl* ctrl, void* data);
- static void onCheckAll( void* user_data) { ((LLFloaterBulkPermission*)user_data)->doCheckUncheckAll(TRUE); }
- static void onUncheckAll(void* user_data) { ((LLFloaterBulkPermission*)user_data)->doCheckUncheckAll(FALSE); }
+ void onCloseBtn();
+ void onApplyBtn();
+ void onCommitCopy();
+ void onCheckAll() { doCheckUncheckAll(TRUE); }
+ void onUncheckAll() { doCheckUncheckAll(FALSE); }
// returns true if this is done
BOOL isDone() const { return (mCurrentObjectID.isNull() || (mObjectIDs.count() == 0)); }
diff --git a/indra/newview/llfloaterbump.cpp b/indra/newview/llfloaterbump.cpp
index 96e51c2fa2..e925796526 100644
--- a/indra/newview/llfloaterbump.cpp
+++ b/indra/newview/llfloaterbump.cpp
@@ -33,59 +33,44 @@
#include "llviewerprecompiledheaders.h"
-#include "llfloaterbump.h"
+#include "llsd.h"
+#include "mean_collision_data.h"
+#include "llfloaterbump.h"
#include "llscrolllistctrl.h"
-
#include "lluictrlfactory.h"
#include "llviewermessage.h"
-#include "llappviewer.h" // gPacificDaylightTime
-
-///----------------------------------------------------------------------------
-/// Local function declarations, constants, enums, and typedefs
-///----------------------------------------------------------------------------
-LLFloaterBump* LLFloaterBump::sInstance = NULL;
///----------------------------------------------------------------------------
/// Class LLFloaterBump
///----------------------------------------------------------------------------
+extern BOOL gNoRender;
// Default constructor
-LLFloaterBump::LLFloaterBump()
-: LLFloater()
+LLFloaterBump::LLFloaterBump(const LLSD& key)
+: LLFloater(key)
{
- sInstance = this;
-
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_bumps.xml");
+ if(gNoRender) return;
+ //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_bumps.xml");
}
// Destroys the object
LLFloaterBump::~LLFloaterBump()
{
- sInstance = NULL;
}
-// static
-void LLFloaterBump::show(void *contents)
+// virtual
+void LLFloaterBump::onOpen(const LLSD& key)
{
- if (gNoRender)
- {
+ LLScrollListCtrl* list = getChild<LLScrollListCtrl>("bump_list");
+ if (!list)
return;
- }
-
- if (!sInstance)
- {
- sInstance = new LLFloaterBump();
- }
-
- LLScrollListCtrl* list = sInstance->getChild<LLScrollListCtrl>("bump_list");
- if (!list) return;
list->deleteAllItems();
if (gMeanCollisionList.empty())
{
- std::string none_detected = sInstance->getString("none_detected");
+ std::string none_detected = getString("none_detected");
LLSD row;
row["columns"][0]["value"] = none_detected;
row["columns"][0]["font"] = "SansSerifBold";
@@ -97,33 +82,23 @@ void LLFloaterBump::show(void *contents)
iter != gMeanCollisionList.end(); ++iter)
{
LLMeanCollisionData *mcd = *iter;
- LLFloaterBump::add(list, mcd);
+ add(list, mcd);
}
}
-
- sInstance->open(); /*Flawfinder: ignore*/
}
void LLFloaterBump::add(LLScrollListCtrl* list, LLMeanCollisionData* mcd)
{
- if (!sInstance)
- {
- new LLFloaterBump();
- }
-
if (mcd->mFirstName.empty() || list->getItemCount() >= 20)
{
return;
}
- // There's only one internal tm buffer.
- struct tm* timep;
-
- // Convert to Pacific, based on server's opinion of whether
- // it's daylight savings time there.
- timep = utc_to_pacific_time(mcd->mTime, gPacificDaylightTime);
-
- std::string time = llformat("[%d:%02d]", timep->tm_hour, timep->tm_min);
+ std::string timeStr = getString ("timeStr");
+ LLSD substitution;
+
+ substitution["datetime"] = (S32) mcd->mTime;
+ LLStringUtil::format (timeStr, substitution);
std::string action;
switch(mcd->mType)
@@ -150,8 +125,8 @@ void LLFloaterBump::add(LLScrollListCtrl* list, LLMeanCollisionData* mcd)
}
// All above action strings are in XML file
- LLUIString text = sInstance->getString(action);
- text.setArg("[TIME]", time);
+ LLUIString text = getString(action);
+ text.setArg("[TIME]", timeStr);
text.setArg("[FIRST]", mcd->mFirstName);
text.setArg("[LAST]", mcd->mLastName);
diff --git a/indra/newview/llfloaterbump.h b/indra/newview/llfloaterbump.h
index eb15671d41..1f2cb6d6ab 100644
--- a/indra/newview/llfloaterbump.h
+++ b/indra/newview/llfloaterbump.h
@@ -42,16 +42,17 @@ class LLScrollListCtrl;
class LLFloaterBump
: public LLFloater
{
-public:
- static void show(void *);
+ friend class LLFloaterReg;
+protected:
+ void add(LLScrollListCtrl* list, LLMeanCollisionData *mcd);
-private:
- LLFloaterBump();
- virtual ~LLFloaterBump();
- static void add(LLScrollListCtrl* list, LLMeanCollisionData *mcd);
+public:
+ /*virtual*/ void onOpen(const LLSD& key);
private:
- static LLFloaterBump* sInstance;
+
+ LLFloaterBump(const LLSD& key);
+ virtual ~LLFloaterBump();
};
#endif
diff --git a/indra/newview/llfloaterbuy.cpp b/indra/newview/llfloaterbuy.cpp
index a33cabc749..fba557c656 100644
--- a/indra/newview/llfloaterbuy.cpp
+++ b/indra/newview/llfloaterbuy.cpp
@@ -41,34 +41,46 @@
#include "llfloaterbuy.h"
#include "llagent.h" // for agent id
-#include "llalertdialog.h"
#include "llinventorymodel.h" // for gInventory
-#include "llinventoryview.h" // for get_item_icon
+#include "llfloaterreg.h"
+#include "llfloaterinventory.h" // for get_item_icon
+#include "llinventoryfunctions.h"
+#include "llnotificationsutil.h"
#include "llselectmgr.h"
#include "llscrolllistctrl.h"
#include "llviewerobject.h"
#include "lluictrlfactory.h"
#include "llviewerwindow.h"
+#include "lltrans.h"
-LLFloaterBuy* LLFloaterBuy::sInstance = NULL;
-
-LLFloaterBuy::LLFloaterBuy()
-: LLFloater(std::string("floater_buy_object"), std::string("FloaterBuyRect"), LLStringUtil::null)
+LLFloaterBuy::LLFloaterBuy(const LLSD& key)
+: LLFloater(key)
{
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_buy_object.xml");
+// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_buy_object.xml");
+}
+BOOL LLFloaterBuy::postBuild()
+{
childDisable("object_list");
childDisable("item_list");
- childSetAction("cancel_btn", onClickCancel, this);
- childSetAction("buy_btn", onClickBuy, this);
+ getChild<LLUICtrl>("cancel_btn")->setCommitCallback( boost::bind(&LLFloaterBuy::onClickCancel, this));
+ getChild<LLUICtrl>("buy_btn")->setCommitCallback( boost::bind(&LLFloaterBuy::onClickBuy, this));
setDefaultBtn("cancel_btn"); // to avoid accidental buy (SL-43130)
+
+ // Always center the dialog. User can change the size,
+ // but purchases are important and should be center screen.
+ // This also avoids problems where the user resizes the application window
+ // mid-session and the saved rect is off-center.
+ center();
+
+ return TRUE;
}
LLFloaterBuy::~LLFloaterBuy()
{
- sInstance = NULL;
+ mObjectSelection = NULL;
}
void LLFloaterBuy::reset()
@@ -87,61 +99,48 @@ void LLFloaterBuy::show(const LLSaleInfo& sale_info)
if (selection->getRootObjectCount() != 1)
{
- LLNotifications::instance().add("BuyOneObjectOnly");
+ LLNotificationsUtil::add("BuyOneObjectOnly");
return;
}
-
- // Create a new instance only if one doesn't exist
- if (sInstance)
- {
- // Clean up the lists...
- sInstance->reset();
- }
- else
- {
- sInstance = new LLFloaterBuy();
- }
- sInstance->open(); /*Flawfinder: ignore*/
- sInstance->setFocus(TRUE);
- sInstance->mSaleInfo = sale_info;
- sInstance->mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
-
- // Always center the dialog. User can change the size,
- // but purchases are important and should be center screen.
- // This also avoids problems where the user resizes the application window
- // mid-session and the saved rect is off-center.
- sInstance->center();
-
+ LLFloaterBuy* floater = LLFloaterReg::showTypedInstance<LLFloaterBuy>("buy_object");
+ if (!floater)
+ return;
+
+ // Clean up the lists...
+ floater->reset();
+ floater->mSaleInfo = sale_info;
+ floater->mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
+
LLSelectNode* node = selection->getFirstRootNode();
if (!node)
return;
-
+
// Set title based on sale type
LLUIString title;
switch (sale_info.getSaleType())
{
case LLSaleInfo::FS_ORIGINAL:
- title = sInstance->getString("title_buy_text");
+ title = floater->getString("title_buy_text");
break;
case LLSaleInfo::FS_COPY:
default:
- title = sInstance->getString("title_buy_copy_text");
+ title = floater->getString("title_buy_copy_text");
break;
}
title.setArg("[NAME]", node->mName);
- sInstance->setTitle(title);
+ floater->setTitle(title);
LLUUID owner_id;
std::string owner_name;
BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name);
if (!owners_identical)
{
- LLNotifications::instance().add("BuyObjectOneOwner");
+ LLNotificationsUtil::add("BuyObjectOneOwner");
return;
}
- LLCtrlListInterface *object_list = sInstance->childGetListInterface("object_list");
+ LLCtrlListInterface *object_list = floater->childGetListInterface("object_list");
if (!object_list)
{
return;
@@ -166,15 +165,15 @@ void LLFloaterBuy::show(const LLSaleInfo& sale_info)
std::string text = node->mName;
if (!(next_owner_mask & PERM_COPY))
{
- text.append(sInstance->getString("no_copy_text"));
+ text.append(floater->getString("no_copy_text"));
}
if (!(next_owner_mask & PERM_MODIFY))
{
- text.append(sInstance->getString("no_modify_text"));
+ text.append(floater->getString("no_modify_text"));
}
if (!(next_owner_mask & PERM_TRANSFER))
{
- text.append(sInstance->getString("no_transfer_text"));
+ text.append(floater->getString("no_transfer_text"));
}
row["columns"][1]["column"] = "text";
@@ -184,15 +183,15 @@ void LLFloaterBuy::show(const LLSaleInfo& sale_info)
// Add after columns added so appropriate heights are correct.
object_list->addElement(row);
- sInstance->childSetTextArg("buy_text", "[AMOUNT]", llformat("%d", sale_info.getSalePrice()));
- sInstance->childSetTextArg("buy_text", "[NAME]", owner_name);
+ floater->childSetTextArg("buy_text", "[AMOUNT]", llformat("%d", sale_info.getSalePrice()));
+ floater->childSetTextArg("buy_text", "[NAME]", owner_name);
// Must do this after the floater is created, because
// sometimes the inventory is already there and
// the callback is called immediately.
LLViewerObject* obj = selection->getFirstRootObject();
- sInstance->registerVOInventoryListener(obj,NULL);
- sInstance->requestVOInventory();
+ floater->registerVOInventoryListener(obj,NULL);
+ floater->requestVOInventory();
}
void LLFloaterBuy::inventoryChanged(LLViewerObject* obj,
@@ -231,10 +230,6 @@ void LLFloaterBuy::inventoryChanged(LLViewerObject* obj,
if (obj->getType() == LLAssetType::AT_CATEGORY)
continue;
- // Skip root folders, so we know we have inventory items only
- if (obj->getType() == LLAssetType::AT_ROOT_CATEGORY)
- continue;
-
// Skip the mysterious blank InventoryObject
if (obj->getType() == LLAssetType::AT_NONE)
continue;
@@ -270,15 +265,15 @@ void LLFloaterBuy::inventoryChanged(LLViewerObject* obj,
std::string text = obj->getName();
if (!(next_owner_mask & PERM_COPY))
{
- text.append(" (no copy)");
+ text.append(LLTrans::getString("no_copy"));
}
if (!(next_owner_mask & PERM_MODIFY))
{
- text.append(" (no modify)");
+ text.append(LLTrans::getString("no_modify"));
}
if (!(next_owner_mask & PERM_TRANSFER))
{
- text.append(" (no transfer)");
+ text.append(LLTrans::getString("no_transfer"));
}
row["columns"][1]["column"] = "text";
@@ -290,41 +285,28 @@ void LLFloaterBuy::inventoryChanged(LLViewerObject* obj,
removeVOInventoryListener();
}
-
-// static
-void LLFloaterBuy::onClickBuy(void*)
+void LLFloaterBuy::onClickBuy()
{
- if (!sInstance)
- {
- llinfos << "LLFloaterBuy::onClickBuy no sInstance!" << llendl;
- return;
- }
-
// Put the items where we put new folders.
LLUUID category_id;
- category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT);
+ category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
// *NOTE: doesn't work for multiple object buy, which UI does not
// currently support sale info is used for verification only, if
// it doesn't match region info then sale is canceled.
- LLSelectMgr::getInstance()->sendBuy(gAgent.getID(), category_id, sInstance->mSaleInfo );
+ LLSelectMgr::getInstance()->sendBuy(gAgent.getID(), category_id, mSaleInfo );
- sInstance->close();
+ closeFloater();
}
-// static
-void LLFloaterBuy::onClickCancel(void*)
+void LLFloaterBuy::onClickCancel()
{
- if (sInstance)
- {
- sInstance->close();
- }
+ closeFloater();
}
+// virtual
void LLFloaterBuy::onClose(bool app_quitting)
{
- // drop reference to current selection so selection goes away
- mObjectSelection = NULL;
- LLFloater::onClose(app_quitting);
+ mObjectSelection.clear();
}
diff --git a/indra/newview/llfloaterbuy.h b/indra/newview/llfloaterbuy.h
index 7473e6c855..ab38e082dc 100644
--- a/indra/newview/llfloaterbuy.h
+++ b/indra/newview/llfloaterbuy.h
@@ -52,13 +52,15 @@ class LLFloaterBuy
: public LLFloater, public LLVOInventoryListener
{
public:
+ LLFloaterBuy(const LLSD& key);
+ ~LLFloaterBuy();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onClose(bool app_quitting);
+
static void show(const LLSaleInfo& sale_info);
protected:
- LLFloaterBuy();
- ~LLFloaterBuy();
-
- /*virtual*/ void onClose(bool app_quitting);
void reset();
void requestObjectInventories();
@@ -67,12 +69,10 @@ protected:
S32 serial_num,
void* data);
- static void onClickBuy(void*);
- static void onClickCancel(void*);
+ void onClickBuy();
+ void onClickCancel();
private:
- static LLFloaterBuy* sInstance;
-
LLSafeHandle<LLObjectSelection> mObjectSelection;
LLSaleInfo mSaleInfo;
};
diff --git a/indra/newview/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp
index 95a8caac53..0daef27af2 100644
--- a/indra/newview/llfloaterbuycontents.cpp
+++ b/indra/newview/llfloaterbuycontents.cpp
@@ -43,10 +43,12 @@
#include "llcachename.h"
#include "llagent.h" // for agent id
-#include "llalertdialog.h"
#include "llcheckboxctrl.h"
+#include "llinventoryfunctions.h"
#include "llinventorymodel.h" // for gInventory
-#include "llinventoryview.h" // for get_item_icon
+#include "llfloaterreg.h"
+#include "llfloaterinventory.h" // for get_item_icon
+#include "llnotificationsutil.h"
#include "llselectmgr.h"
#include "llscrolllistctrl.h"
#include "llviewerobject.h"
@@ -54,26 +56,35 @@
#include "lluictrlfactory.h"
#include "llviewerwindow.h"
-LLFloaterBuyContents* LLFloaterBuyContents::sInstance = NULL;
+LLFloaterBuyContents::LLFloaterBuyContents(const LLSD& key)
+: LLFloater(key)
+{
+// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_buy_contents.xml");
+}
-LLFloaterBuyContents::LLFloaterBuyContents()
-: LLFloater(std::string("floater_buy_contents"), std::string("FloaterBuyContentsRect"), LLStringUtil::null)
+BOOL LLFloaterBuyContents::postBuild()
{
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_buy_contents.xml");
- childSetAction("cancel_btn", onClickCancel, this);
- childSetAction("buy_btn", onClickBuy, this);
+ getChild<LLUICtrl>("cancel_btn")->setCommitCallback( boost::bind(&LLFloaterBuyContents::onClickCancel, this));
+ getChild<LLUICtrl>("buy_btn")->setCommitCallback( boost::bind(&LLFloaterBuyContents::onClickBuy, this));
childDisable("item_list");
childDisable("buy_btn");
childDisable("wear_check");
setDefaultBtn("cancel_btn"); // to avoid accidental buy (SL-43130)
+
+ // Always center the dialog. User can change the size,
+ // but purchases are important and should be center screen.
+ // This also avoids problems where the user resizes the application window
+ // mid-session and the saved rect is off-center.
+ center();
+
+ return TRUE;
}
LLFloaterBuyContents::~LLFloaterBuyContents()
{
- sInstance = NULL;
}
@@ -84,41 +95,30 @@ void LLFloaterBuyContents::show(const LLSaleInfo& sale_info)
if (selection->getRootObjectCount() != 1)
{
- LLNotifications::instance().add("BuyContentsOneOnly");
+ LLNotificationsUtil::add("BuyContentsOneOnly");
return;
}
+
+ LLFloaterBuyContents* floater = LLFloaterReg::showTypedInstance<LLFloaterBuyContents>("buy_object_contents");
+ if (!floater)
+ return;
+
+ LLScrollListCtrl* list = floater->getChild<LLScrollListCtrl>("item_list");
+ if (list)
+ list->deleteAllItems();
- // Create a new instance only if needed
- if (sInstance)
- {
- LLScrollListCtrl* list = sInstance->getChild<LLScrollListCtrl>("item_list");
- if (list) list->deleteAllItems();
- }
- else
- {
- sInstance = new LLFloaterBuyContents();
- }
-
- sInstance->open(); /*Flawfinder: ignore*/
- sInstance->setFocus(TRUE);
- sInstance->mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
-
- // Always center the dialog. User can change the size,
- // but purchases are important and should be center screen.
- // This also avoids problems where the user resizes the application window
- // mid-session and the saved rect is off-center.
- sInstance->center();
+ floater->mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
LLUUID owner_id;
std::string owner_name;
BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name);
if (!owners_identical)
{
- LLNotifications::instance().add("BuyContentsOneOwner");
+ LLNotificationsUtil::add("BuyContentsOneOwner");
return;
}
- sInstance->mSaleInfo = sale_info;
+ floater->mSaleInfo = sale_info;
// Update the display
LLSelectNode* node = selection->getFirstRootNode();
@@ -128,16 +128,16 @@ void LLFloaterBuyContents::show(const LLSaleInfo& sale_info)
gCacheName->getGroupName(owner_id, owner_name);
}
- sInstance->childSetTextArg("contains_text", "[NAME]", node->mName);
- sInstance->childSetTextArg("buy_text", "[AMOUNT]", llformat("%d", sale_info.getSalePrice()));
- sInstance->childSetTextArg("buy_text", "[NAME]", owner_name);
+ floater->childSetTextArg("contains_text", "[NAME]", node->mName);
+ floater->childSetTextArg("buy_text", "[AMOUNT]", llformat("%d", sale_info.getSalePrice()));
+ floater->childSetTextArg("buy_text", "[NAME]", owner_name);
// Must do this after the floater is created, because
// sometimes the inventory is already there and
// the callback is called immediately.
LLViewerObject* obj = selection->getFirstRootObject();
- sInstance->registerVOInventoryListener(obj,NULL);
- sInstance->requestVOInventory();
+ floater->registerVOInventoryListener(obj,NULL);
+ floater->requestVOInventory();
}
@@ -187,10 +187,6 @@ void LLFloaterBuyContents::inventoryChanged(LLViewerObject* obj,
if (asset_type == LLAssetType::AT_CATEGORY)
continue;
- // Skip root folders, so we know we have inventory items only
- if (asset_type == LLAssetType::AT_ROOT_CATEGORY)
- continue;
-
LLInventoryItem* inv_item = (LLInventoryItem*)((LLInventoryObject*)(*it));
inv_type = inv_item->getInventoryType();
@@ -267,39 +263,36 @@ void LLFloaterBuyContents::inventoryChanged(LLViewerObject* obj,
}
-// static
-void LLFloaterBuyContents::onClickBuy(void*)
+void LLFloaterBuyContents::onClickBuy()
{
// Make sure this wasn't selected through other mechanisms
// (ie, being the default button and pressing enter.
- if(!sInstance->childIsEnabled("buy_btn"))
+ if(!childIsEnabled("buy_btn"))
{
// We shouldn't be enabled. Just close.
- sInstance->close();
+ closeFloater();
return;
}
// We may want to wear this item
- if (sInstance->childGetValue("wear_check"))
+ if (childGetValue("wear_check"))
{
- LLInventoryView::sWearNewClothing = TRUE;
+ LLInventoryState::sWearNewClothing = TRUE;
}
// Put the items where we put new folders.
LLUUID category_id;
- category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CATEGORY);
+ category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_ROOT_INVENTORY);
// *NOTE: doesn't work for multiple object buy, which UI does not
// currently support sale info is used for verification only, if
// it doesn't match region info then sale is canceled.
- LLSelectMgr::getInstance()->sendBuy(gAgent.getID(), category_id, sInstance->mSaleInfo);
+ LLSelectMgr::getInstance()->sendBuy(gAgent.getID(), category_id, mSaleInfo);
- sInstance->close();
+ closeFloater();
}
-
-// static
-void LLFloaterBuyContents::onClickCancel(void*)
+void LLFloaterBuyContents::onClickCancel()
{
- sInstance->close();
+ closeFloater();
}
diff --git a/indra/newview/llfloaterbuycontents.h b/indra/newview/llfloaterbuycontents.h
index 908ff134e6..8045a46c9f 100644
--- a/indra/newview/llfloaterbuycontents.h
+++ b/indra/newview/llfloaterbuycontents.h
@@ -52,22 +52,21 @@ class LLFloaterBuyContents
public:
static void show(const LLSaleInfo& sale_info);
-protected:
- LLFloaterBuyContents();
+ LLFloaterBuyContents(const LLSD& key);
~LLFloaterBuyContents();
-
+ /*virtual*/ BOOL postBuild();
+
+protected:
void requestObjectInventories();
/*virtual*/ void inventoryChanged(LLViewerObject* obj,
InventoryObjectList* inv,
S32 serial_num,
void* data);
-
- static void onClickBuy(void*);
- static void onClickCancel(void*);
+
+ void onClickBuy();
+ void onClickCancel();
protected:
- static LLFloaterBuyContents* sInstance;
-
LLSafeHandle<LLObjectSelection> mObjectSelection;
LLSaleInfo mSaleInfo;
};
diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index cfbc5da761..1642e6725e 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -37,6 +37,8 @@
// viewer includes
#include "llcurrencyuimanager.h"
#include "llfloater.h"
+#include "llfloaterreg.h"
+#include "llnotificationsutil.h"
#include "llstatusbar.h"
#include "lltextbox.h"
#include "llviewchildren.h"
@@ -53,12 +55,7 @@ class LLFloaterBuyCurrencyUI
: public LLFloater
{
public:
- static LLFloaterBuyCurrencyUI* soleInstance(bool createIfNeeded);
-
-private:
- static LLFloaterBuyCurrencyUI* sInstance;
-
- LLFloaterBuyCurrencyUI();
+ LLFloaterBuyCurrencyUI(const LLSD& key);
virtual ~LLFloaterBuyCurrencyUI();
@@ -80,32 +77,18 @@ public:
virtual void draw();
virtual BOOL canClose();
- virtual void onClose(bool app_quitting);
- static void onClickBuy(void* data);
- static void onClickCancel(void* data);
- static void onClickErrorWeb(void* data);
+ void onClickBuy();
+ void onClickCancel();
+ void onClickErrorWeb();
};
-
-// static
-LLFloaterBuyCurrencyUI* LLFloaterBuyCurrencyUI::sInstance = NULL;
-
-// static
-LLFloaterBuyCurrencyUI* LLFloaterBuyCurrencyUI::soleInstance(bool createIfNeeded)
+LLFloater* LLFloaterBuyCurrency::buildFloater(const LLSD& key)
{
- if (!sInstance && createIfNeeded)
- {
- sInstance = new LLFloaterBuyCurrencyUI();
-
- LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_buy_currency.xml");
- sInstance->center();
- }
-
- return sInstance;
+ LLFloaterBuyCurrencyUI* floater = new LLFloaterBuyCurrencyUI(key);
+ return floater;
}
-
#if LL_WINDOWS
// passing 'this' during construction generates a warning. The callee
// only uses the pointer to hold a reference to 'this' which is
@@ -113,8 +96,8 @@ LLFloaterBuyCurrencyUI* LLFloaterBuyCurrencyUI::soleInstance(bool createIfNeeded
// warning so that we can compile without generating a warning.
#pragma warning(disable : 4355)
#endif
-LLFloaterBuyCurrencyUI::LLFloaterBuyCurrencyUI()
-: LLFloater(std::string("Buy Currency")),
+LLFloaterBuyCurrencyUI::LLFloaterBuyCurrencyUI(const LLSD& key)
+: LLFloater(key),
mChildren(*this),
mManager(*this)
{
@@ -122,10 +105,6 @@ LLFloaterBuyCurrencyUI::LLFloaterBuyCurrencyUI()
LLFloaterBuyCurrencyUI::~LLFloaterBuyCurrencyUI()
{
- if (sInstance == this)
- {
- sInstance = NULL;
- }
}
@@ -157,10 +136,12 @@ BOOL LLFloaterBuyCurrencyUI::postBuild()
{
mManager.prepare();
- childSetAction("buy_btn", onClickBuy, this);
- childSetAction("cancel_btn", onClickCancel, this);
- childSetAction("error_web", onClickErrorWeb, this);
-
+ getChild<LLUICtrl>("buy_btn")->setCommitCallback( boost::bind(&LLFloaterBuyCurrencyUI::onClickBuy, this));
+ getChild<LLUICtrl>("cancel_btn")->setCommitCallback( boost::bind(&LLFloaterBuyCurrencyUI::onClickCancel, this));
+ getChild<LLUICtrl>("error_web")->setCommitCallback( boost::bind(&LLFloaterBuyCurrencyUI::onClickErrorWeb, this));
+
+ center();
+
updateUI();
return TRUE;
@@ -172,13 +153,17 @@ void LLFloaterBuyCurrencyUI::draw()
{
if (mManager.bought())
{
- close();
+ LLNotificationsUtil::add("BuyLindenDollarSuccess");
+ closeFloater();
return;
}
updateUI();
}
+ // disable the Buy button when we are not able to buy
+ childSetEnabled("buy_btn", mManager.canBuy());
+
LLFloater::draw();
}
@@ -187,70 +172,58 @@ BOOL LLFloaterBuyCurrencyUI::canClose()
return mManager.canCancel();
}
-void LLFloaterBuyCurrencyUI::onClose(bool app_quitting)
-{
- LLFloater::onClose(app_quitting);
- destroy();
-}
-
void LLFloaterBuyCurrencyUI::updateUI()
{
bool hasError = mManager.hasError();
mManager.updateUI(!hasError && !mManager.buying());
- // section zero: title area
- {
- childSetVisible("info_buying", false);
- childSetVisible("info_cannot_buy", false);
- childSetVisible("info_need_more", false);
- if (hasError)
- {
- childSetVisible("info_cannot_buy", true);
- }
- else if (mHasTarget)
- {
- childSetVisible("info_need_more", true);
- }
- else
- {
- childSetVisible("info_buying", true);
- }
- }
-
- // error section
+ // hide most widgets - we'll turn them on as needed next
+ childHide("info_buying");
+ childHide("info_cannot_buy");
+ childHide("info_need_more");
+ childHide("purchase_warning_repurchase");
+ childHide("purchase_warning_notenough");
+ childHide("contacting");
+ childHide("buy_action");
+
if (hasError)
{
- mChildren.setBadge(std::string("step_error"), LLViewChildren::BADGE_ERROR);
-
- LLTextBox* message = getChild<LLTextBox>("error_message");
- if (message)
+ // display an error from the server
+ childHide("normal_background");
+ childShow("error_background");
+ childShow("info_cannot_buy");
+ childShow("cannot_buy_message");
+ childHide("balance_label");
+ childHide("balance_amount");
+ childHide("buying_label");
+ childHide("buying_amount");
+ childHide("total_label");
+ childHide("total_amount");
+
+ LLTextBox* message = getChild<LLTextBox>("cannot_buy_message");
+ if (message)
{
- message->setVisible(true);
- message->setWrappedText(mManager.errorMessage());
+ message->setText(mManager.errorMessage());
}
childSetVisible("error_web", !mManager.errorURI().empty());
- if (!mManager.errorURI().empty())
- {
- childHide("getting_data");
- }
}
else
{
- childHide("step_error");
- childHide("error_message");
+ // display the main Buy L$ interface
+ childShow("normal_background");
+ childHide("error_background");
+ childHide("cannot_buy_message");
childHide("error_web");
- }
-
-
- // currency
- childSetVisible("contacting", false);
- childSetVisible("buy_action", false);
- childSetVisible("buy_action_unknown", false);
-
- if (!hasError)
- {
- mChildren.setBadge(std::string("step_1"), LLViewChildren::BADGE_NOTE);
+
+ if (mHasTarget)
+ {
+ childShow("info_need_more");
+ }
+ else
+ {
+ childShow("info_buying");
+ }
if (mManager.buying())
{
@@ -264,10 +237,6 @@ void LLFloaterBuyCurrencyUI::updateUI()
childSetTextArg("buy_action", "[NAME]", mTargetName);
childSetTextArg("buy_action", "[PRICE]", llformat("%d",mTargetPrice));
}
- else
- {
- childSetVisible("buy_action_unknown", true);
- }
}
S32 balance = gStatusBar->getBalance();
@@ -285,8 +254,6 @@ void LLFloaterBuyCurrencyUI::updateUI()
childShow("total_amount");
childSetTextArg("total_amount", "[AMT]", llformat("%d", total));
- childSetVisible("purchase_warning_repurchase", false);
- childSetVisible("purchase_warning_notenough", false);
if (mHasTarget)
{
if (total >= mTargetPrice)
@@ -299,78 +266,41 @@ void LLFloaterBuyCurrencyUI::updateUI()
}
}
}
- else
- {
- childHide("step_1");
- childHide("balance_label");
- childHide("balance_amount");
- childHide("buying_label");
- childHide("buying_amount");
- childHide("total_label");
- childHide("total_amount");
- childHide("purchase_warning_repurchase");
- childHide("purchase_warning_notenough");
- }
-
- childSetEnabled("buy_btn", mManager.canBuy());
- if (!mManager.canBuy() && !childIsVisible("error_web"))
- {
- childShow("getting_data");
- }
+ childSetVisible("getting_data", !mManager.canBuy() && !hasError);
}
-// static
-void LLFloaterBuyCurrencyUI::onClickBuy(void* data)
+void LLFloaterBuyCurrencyUI::onClickBuy()
{
- LLFloaterBuyCurrencyUI* self = LLFloaterBuyCurrencyUI::soleInstance(false);
- if (self)
- {
- self->mManager.buy(self->getString("buy_currency"));
- self->updateUI();
- // JC: updateUI() doesn't get called again until progress is made
- // with transaction processing, so the "Purchase" button would be
- // left enabled for some time. Pre-emptively disable.
- self->childSetEnabled("buy_btn", false);
- }
+ mManager.buy(getString("buy_currency"));
+ updateUI();
}
-// static
-void LLFloaterBuyCurrencyUI::onClickCancel(void* data)
+void LLFloaterBuyCurrencyUI::onClickCancel()
{
- LLFloaterBuyCurrencyUI* self = LLFloaterBuyCurrencyUI::soleInstance(false);
- if (self)
- {
- self->close();
- }
+ closeFloater();
}
-// static
-void LLFloaterBuyCurrencyUI::onClickErrorWeb(void* data)
+void LLFloaterBuyCurrencyUI::onClickErrorWeb()
{
- LLFloaterBuyCurrencyUI* self = LLFloaterBuyCurrencyUI::soleInstance(false);
- if (self)
- {
- LLWeb::loadURLExternal(self->mManager.errorURI());
- self->close();
- }
+ LLWeb::loadURLExternal(mManager.errorURI());
+ closeFloater();
}
// static
void LLFloaterBuyCurrency::buyCurrency()
{
- LLFloaterBuyCurrencyUI* ui = LLFloaterBuyCurrencyUI::soleInstance(true);
+ LLFloaterBuyCurrencyUI* ui = LLFloaterReg::showTypedInstance<LLFloaterBuyCurrencyUI>("buy_currency");
ui->noTarget();
ui->updateUI();
- ui->open();
}
+// static
void LLFloaterBuyCurrency::buyCurrency(const std::string& name, S32 price)
{
- LLFloaterBuyCurrencyUI* ui = LLFloaterBuyCurrencyUI::soleInstance(true);
+ LLFloaterBuyCurrencyUI* ui = LLFloaterReg::showTypedInstance<LLFloaterBuyCurrencyUI>("buy_currency");
ui->target(name, price);
ui->updateUI();
- ui->open();
}
diff --git a/indra/newview/llfloaterbuycurrency.h b/indra/newview/llfloaterbuycurrency.h
index 756acd2f0c..9b3f9b43d0 100644
--- a/indra/newview/llfloaterbuycurrency.h
+++ b/indra/newview/llfloaterbuycurrency.h
@@ -35,6 +35,8 @@
#include "stdtypes.h"
+class LLFloater;
+
class LLFloaterBuyCurrency
{
public:
@@ -46,6 +48,8 @@ public:
"Uploading costs"
a space and the price will be appended
*/
+
+ static LLFloater* buildFloater(const LLSD& key);
};
diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp
index 29506e21d5..9b88923e7e 100644
--- a/indra/newview/llfloaterbuyland.cpp
+++ b/indra/newview/llfloaterbuyland.cpp
@@ -43,12 +43,14 @@
#include "llconfirmationmanager.h"
#include "llcurrencyuimanager.h"
#include "llfloater.h"
+#include "llfloaterreg.h"
#include "llfloatertools.h"
#include "llframetimer.h"
#include "lliconctrl.h"
#include "lllineeditor.h"
-#include "llnotify.h"
+#include "llnotificationsutil.h"
#include "llparcel.h"
+#include "llslurl.h"
#include "llstatusbar.h"
#include "lltextbox.h"
#include "lltexturectrl.h"
@@ -70,15 +72,29 @@
const F32 GROUP_LAND_BONUS_FACTOR = 1.1f;
const F64 CURRENCY_ESTIMATE_FREQUENCY = 0.5;
// how long of a pause in typing a currency buy amount before an
- // esimate is fetched from the server
+ // estimate is fetched from the server
class LLFloaterBuyLandUI
: public LLFloater
{
-private:
- LLFloaterBuyLandUI();
+public:
+ LLFloaterBuyLandUI(const LLSD& key);
virtual ~LLFloaterBuyLandUI();
-
+
+ /*virtual*/ void onClose(bool app_quitting);
+
+private:
+ class SelectionObserver : public LLParcelObserver
+ {
+ public:
+ SelectionObserver(LLFloaterBuyLandUI* floater) : mFloater(floater) {}
+ virtual void changed();
+ private:
+ LLFloaterBuyLandUI* mFloater;
+ };
+
+private:
+ SelectionObserver mParcelSelectionObserver;
LLViewerRegion* mRegion;
LLParcelSelectionHandle mParcel;
bool mIsClaim;
@@ -144,11 +160,7 @@ private:
LLViewerParcelMgr::ParcelBuyInfo* mParcelBuyInfo;
- static LLFloaterBuyLandUI* sInstance;
-
public:
- static LLFloaterBuyLandUI* soleInstance(bool createIfNeeded);
-
void setForGroup(bool is_for_group);
void setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel);
@@ -156,10 +168,10 @@ public:
void updateParcelInfo();
void updateCovenantInfo();
static void onChangeAgreeCovenant(LLUICtrl* ctrl, void* user_data);
- void updateCovenantText(const std::string& string, const LLUUID &asset_id);
- void updateEstateName(const std::string& name);
- void updateLastModified(const std::string& text);
- void updateEstateOwnerName(const std::string& name);
+ void updateFloaterCovenantText(const std::string& string, const LLUUID &asset_id);
+ void updateFloaterEstateName(const std::string& name);
+ void updateFloaterLastModified(const std::string& text);
+ void updateFloaterEstateOwnerName(const std::string& name);
void updateWebSiteInfo();
void finishWebSiteInfo();
@@ -168,10 +180,15 @@ public:
void sendBuyLand();
void updateNames();
+ // Name cache callback
+ void updateGroupName(const LLUUID& id,
+ const std::string& first_name,
+ const std::string& last_name,
+ BOOL is_group);
void refreshUI();
- void startTransaction(TransactionType type, LLXMLRPCValue params);
+ void startTransaction(TransactionType type, const LLXMLRPCValue& params);
bool checkTransaction();
void tellUserError(const std::string& message, const std::string& uri);
@@ -181,138 +198,85 @@ public:
void startBuyPreConfirm();
void startBuyPostConfirm(const std::string& password);
- static void onClickBuy(void* data);
- static void onClickCancel(void* data);
- static void onClickErrorWeb(void* data);
+ void onClickBuy();
+ void onClickCancel();
+ void onClickErrorWeb();
virtual void draw();
virtual BOOL canClose();
- virtual void onClose(bool app_quitting);
- /*virtual*/ void setMinimized(BOOL b);
+
+ void onVisibilityChange ( const LLSD& new_visibility );
-private:
- class SelectionObserver : public LLParcelObserver
- {
- public:
- virtual void changed();
- };
};
-static void cacheNameUpdateRefreshesBuyLand(const LLUUID&,
- const std::string&, const std::string&, BOOL, void* data)
-{
- LLFloaterBuyLandUI* ui = LLFloaterBuyLandUI::soleInstance(false);
- if (ui)
- {
- ui->updateNames();
- }
-}
-
// static
void LLFloaterBuyLand::buyLand(
LLViewerRegion* region, LLParcelSelectionHandle parcel, bool is_for_group)
{
if(is_for_group && !gAgent.hasPowerInActiveGroup(GP_LAND_DEED))
{
- LLNotifications::instance().add("OnlyOfficerCanBuyLand");
+ LLNotificationsUtil::add("OnlyOfficerCanBuyLand");
return;
}
- LLFloaterBuyLandUI* ui = LLFloaterBuyLandUI::soleInstance(true);
- ui->setForGroup(is_for_group);
- ui->setParcel(region, parcel);
- ui->open(); /*Flawfinder: ignore*/
+ LLFloaterBuyLandUI* ui = LLFloaterReg::showTypedInstance<LLFloaterBuyLandUI>("buy_land");
+ if (ui)
+ {
+ ui->setForGroup(is_for_group);
+ ui->setParcel(region, parcel);
+ }
}
// static
void LLFloaterBuyLand::updateCovenantText(const std::string& string, const LLUUID &asset_id)
{
- LLFloaterBuyLandUI* floater = LLFloaterBuyLandUI::soleInstance(FALSE);
+ LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance<LLFloaterBuyLandUI>("buy_land");
if (floater)
{
- floater->updateCovenantText(string, asset_id);
+ floater->updateFloaterCovenantText(string, asset_id);
}
}
// static
void LLFloaterBuyLand::updateEstateName(const std::string& name)
{
- LLFloaterBuyLandUI* floater = LLFloaterBuyLandUI::soleInstance(FALSE);
+ LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance<LLFloaterBuyLandUI>("buy_land");
if (floater)
{
- floater->updateEstateName(name);
+ floater->updateFloaterEstateName(name);
}
}
// static
void LLFloaterBuyLand::updateLastModified(const std::string& text)
{
- LLFloaterBuyLandUI* floater = LLFloaterBuyLandUI::soleInstance(FALSE);
+ LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance<LLFloaterBuyLandUI>("buy_land");
if (floater)
{
- floater->updateLastModified(text);
+ floater->updateFloaterLastModified(text);
}
}
// static
void LLFloaterBuyLand::updateEstateOwnerName(const std::string& name)
{
- LLFloaterBuyLandUI* floater = LLFloaterBuyLandUI::soleInstance(FALSE);
- if (floater)
- {
- floater->updateEstateOwnerName(name);
- }
-}
-
-// static
-BOOL LLFloaterBuyLand::isOpen()
-{
- LLFloaterBuyLandUI* floater = LLFloaterBuyLandUI::soleInstance(FALSE);
+ LLFloaterBuyLandUI* floater = LLFloaterReg::findTypedInstance<LLFloaterBuyLandUI>("buy_land");
if (floater)
{
- return floater->getVisible();
+ floater->updateFloaterEstateOwnerName(name);
}
- return FALSE;
}
// static
-LLFloaterBuyLandUI* LLFloaterBuyLandUI::sInstance = NULL;
-
-// static
-LLFloaterBuyLandUI* LLFloaterBuyLandUI::soleInstance(bool createIfNeeded)
+LLFloater* LLFloaterBuyLand::buildFloater(const LLSD& key)
{
-#if !LL_RELEASE_FOR_DOWNLOAD
- if (createIfNeeded)
- {
- delete sInstance;
- sInstance = NULL;
- }
-#endif
- if (!sInstance && createIfNeeded)
- {
- sInstance = new LLFloaterBuyLandUI();
-
- LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_buy_land.xml");
- sInstance->center();
-
- static bool observingCacheName = false;
- if (!observingCacheName)
- {
- gCacheName->addObserver(cacheNameUpdateRefreshesBuyLand);
- observingCacheName = true;
- }
-
- static SelectionObserver* parcelSelectionObserver = NULL;
- if (!parcelSelectionObserver)
- {
- parcelSelectionObserver = new SelectionObserver;
- LLViewerParcelMgr::getInstance()->addObserver(parcelSelectionObserver);
- }
- }
-
- return sInstance;
+ LLFloaterBuyLandUI* floater = new LLFloaterBuyLandUI(key);
+ return floater;
}
+//----------------------------------------------------------------------------
+// LLFloaterBuyLandUI
+//----------------------------------------------------------------------------
#if LL_WINDOWS
// passing 'this' during construction generates a warning. The callee
@@ -321,42 +285,48 @@ LLFloaterBuyLandUI* LLFloaterBuyLandUI::soleInstance(bool createIfNeeded)
// warning so that we can compile without generating a warning.
#pragma warning(disable : 4355)
#endif
-LLFloaterBuyLandUI::LLFloaterBuyLandUI()
-: LLFloater(std::string("Buy Land")),
+LLFloaterBuyLandUI::LLFloaterBuyLandUI(const LLSD& key)
+: LLFloater(LLSD()),
+ mParcelSelectionObserver(this),
mParcel(0),
mBought(false),
mParcelValid(false), mSiteValid(false),
mChildren(*this), mCurrency(*this), mTransaction(0),
mParcelBuyInfo(0)
{
+ LLViewerParcelMgr::getInstance()->addObserver(&mParcelSelectionObserver);
+
+// LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_buy_land.xml");
}
LLFloaterBuyLandUI::~LLFloaterBuyLandUI()
{
+ LLViewerParcelMgr::getInstance()->removeObserver(&mParcelSelectionObserver);
+ LLViewerParcelMgr::getInstance()->deleteParcelBuy(&mParcelBuyInfo);
+
delete mTransaction;
+}
- LLViewerParcelMgr::getInstance()->deleteParcelBuy(mParcelBuyInfo);
-
- if (sInstance == this)
- {
- sInstance = NULL;
- }
+// virtual
+void LLFloaterBuyLandUI::onClose(bool app_quitting)
+{
+ // This object holds onto observer, transactions, and parcel state.
+ // Despite being single_instance, destroy it to call destructors and clean
+ // everything up.
+ setVisible(FALSE);
+ destroy();
}
void LLFloaterBuyLandUI::SelectionObserver::changed()
{
- LLFloaterBuyLandUI* ui = LLFloaterBuyLandUI::soleInstance(false);
- if (ui)
+ if (LLViewerParcelMgr::getInstance()->selectionEmpty())
{
- if (LLViewerParcelMgr::getInstance()->selectionEmpty())
- {
- ui->close();
- }
- else {
- ui->setParcel(
- LLViewerParcelMgr::getInstance()->getSelectionRegion(),
- LLViewerParcelMgr::getInstance()->getParcelSelection());
- }
+ mFloater->closeFloater();
+ }
+ else
+ {
+ mFloater->setParcel(LLViewerParcelMgr::getInstance()->getSelectionRegion(),
+ LLViewerParcelMgr::getInstance()->getParcelSelection());
}
}
@@ -523,10 +493,14 @@ void LLFloaterBuyLandUI::updateCovenantInfo()
LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
if(!region) return;
+ U8 sim_access = region->getSimAccess();
+ std::string rating = LLViewerRegion::accessToString(sim_access);
+
LLTextBox* region_name = getChild<LLTextBox>("region_name_text");
if (region_name)
{
- region_name->setText(region->getName());
+ std::string region_name_txt = region->getName() + " ("+rating +")";
+ region_name->setText(region_name_txt);
}
LLTextBox* region_type = getChild<LLTextBox>("region_type_text");
@@ -566,8 +540,7 @@ void LLFloaterBuyLandUI::updateCovenantInfo()
{
check->set(false);
check->setEnabled(true);
- check->setCallbackUserData(this);
- check->setCommitCallback(onChangeAgreeCovenant);
+ check->setCommitCallback(onChangeAgreeCovenant, this);
}
LLTextBox* box = getChild<LLTextBox>("covenant_text");
@@ -595,51 +568,44 @@ void LLFloaterBuyLandUI::onChangeAgreeCovenant(LLUICtrl* ctrl, void* user_data)
}
}
-void LLFloaterBuyLandUI::updateCovenantText(const std::string &string, const LLUUID& asset_id)
+void LLFloaterBuyLandUI::updateFloaterCovenantText(const std::string &string, const LLUUID& asset_id)
{
LLViewerTextEditor* editor = getChild<LLViewerTextEditor>("covenant_editor");
- if (editor)
- {
- editor->setHandleEditKeysDirectly(FALSE);
- editor->setText(string);
+ editor->setText(string);
- LLCheckBoxCtrl* check = getChild<LLCheckBoxCtrl>("agree_covenant");
- LLTextBox* box = getChild<LLTextBox>("covenant_text");
- if(check && box)
- {
- if (asset_id.isNull())
- {
- check->set(true);
- check->setEnabled(false);
- refreshUI();
+ LLCheckBoxCtrl* check = getChild<LLCheckBoxCtrl>("agree_covenant");
+ LLTextBox* box = getChild<LLTextBox>("covenant_text");
+ if (asset_id.isNull())
+ {
+ check->set(true);
+ check->setEnabled(false);
+ refreshUI();
- // remove the line stating that you must agree
- box->setVisible(FALSE);
- }
- else
- {
- check->setEnabled(true);
+ // remove the line stating that you must agree
+ box->setVisible(FALSE);
+ }
+ else
+ {
+ check->setEnabled(true);
- // remove the line stating that you must agree
- box->setVisible(TRUE);
- }
- }
+ // remove the line stating that you must agree
+ box->setVisible(TRUE);
}
}
-void LLFloaterBuyLandUI::updateEstateName(const std::string& name)
+void LLFloaterBuyLandUI::updateFloaterEstateName(const std::string& name)
{
LLTextBox* box = getChild<LLTextBox>("estate_name_text");
if (box) box->setText(name);
}
-void LLFloaterBuyLandUI::updateLastModified(const std::string& text)
+void LLFloaterBuyLandUI::updateFloaterLastModified(const std::string& text)
{
LLTextBox* editor = getChild<LLTextBox>("covenant_timestamp_text");
if (editor) editor->setText(text);
}
-void LLFloaterBuyLandUI::updateEstateOwnerName(const std::string& name)
+void LLFloaterBuyLandUI::updateFloaterEstateOwnerName(const std::string& name)
{
LLTextBox* box = getChild<LLTextBox>("estate_owner_text");
if (box) box->setText(name);
@@ -723,7 +689,14 @@ void LLFloaterBuyLandUI::finishWebSiteInfo()
mSiteLandUseAction = landUse["action"].asString();
LLXMLRPCValue currency = result["currency"];
- mCurrency.setEstimate(currency["estimatedCost"].asInt());
+ if (currency["estimatedCost"].isValid())
+ {
+ mCurrency.setUSDEstimate(currency["estimatedCost"].asInt());
+ }
+ if (currency["estimatedLocalCost"].isValid())
+ {
+ mCurrency.setLocalEstimate(currency["estimatedLocalCost"].asString());
+ }
mSiteConfirm = result["confirm"].asString();
}
@@ -771,7 +744,8 @@ void LLFloaterBuyLandUI::runWebSitePrep(const std::string& password)
keywordArgs.appendInt("billableArea",
mIsForGroup ? 0 : mParcelBillableArea);
keywordArgs.appendInt("currencyBuy", mCurrency.getAmount());
- keywordArgs.appendInt("estimatedCost", mCurrency.getEstimate());
+ keywordArgs.appendInt("estimatedCost", mCurrency.getUSDEstimate());
+ keywordArgs.appendString("estimatedLocalCost", mCurrency.getLocalEstimate());
keywordArgs.appendString("confirm", mSiteConfirm);
if (!password.empty())
{
@@ -806,7 +780,7 @@ void LLFloaterBuyLandUI::sendBuyLand()
if (mParcelBuyInfo)
{
LLViewerParcelMgr::getInstance()->sendParcelBuy(mParcelBuyInfo);
- LLViewerParcelMgr::getInstance()->deleteParcelBuy(mParcelBuyInfo);
+ LLViewerParcelMgr::getInstance()->deleteParcelBuy(&mParcelBuyInfo);
mBought = true;
}
}
@@ -827,17 +801,32 @@ void LLFloaterBuyLandUI::updateNames()
}
else if (parcelp->getIsGroupOwned())
{
- gCacheName->getGroupName(parcelp->getGroupID(), mParcelSellerName);
+ gCacheName->get(parcelp->getGroupID(), TRUE,
+ boost::bind(&LLFloaterBuyLandUI::updateGroupName, this,
+ _1, _2, _3, _4));
}
else
{
- gCacheName->getFullName(parcelp->getOwnerID(), mParcelSellerName);
+ mParcelSellerName =
+ LLSLURL::buildCommand("agent", parcelp->getOwnerID(), "inspect");
}
}
+void LLFloaterBuyLandUI::updateGroupName(const LLUUID& id,
+ const std::string& first_name,
+ const std::string& last_name,
+ BOOL is_group)
+{
+ LLParcel* parcelp = mParcel->getParcel();
+ if (parcelp
+ && parcelp->getGroupID() == id)
+ {
+ // request is current
+ mParcelSellerName = first_name;
+ }
+}
-void LLFloaterBuyLandUI::startTransaction(TransactionType type,
- LLXMLRPCValue params)
+void LLFloaterBuyLandUI::startTransaction(TransactionType type, const LLXMLRPCValue& params)
{
delete mTransaction;
mTransaction = NULL;
@@ -918,11 +907,15 @@ void LLFloaterBuyLandUI::tellUserError(
// virtual
BOOL LLFloaterBuyLandUI::postBuild()
{
+ setVisibleCallback(boost::bind(&LLFloaterBuyLandUI::onVisibilityChange, this, _2));
+
mCurrency.prepare();
- childSetAction("buy_btn", onClickBuy, this);
- childSetAction("cancel_btn", onClickCancel, this);
- childSetAction("error_web", onClickErrorWeb, this);
+ getChild<LLUICtrl>("buy_btn")->setCommitCallback( boost::bind(&LLFloaterBuyLandUI::onClickBuy, this));
+ getChild<LLUICtrl>("cancel_btn")->setCommitCallback( boost::bind(&LLFloaterBuyLandUI::onClickCancel, this));
+ getChild<LLUICtrl>("error_web")->setCommitCallback( boost::bind(&LLFloaterBuyLandUI::onClickErrorWeb, this));
+
+ center();
return TRUE;
}
@@ -963,7 +956,7 @@ void LLFloaterBuyLandUI::draw()
if (mBought)
{
- close();
+ closeFloater();
}
else if (needsUpdate)
{
@@ -983,29 +976,19 @@ BOOL LLFloaterBuyLandUI::canClose()
if (!can_close)
{
// explain to user why they can't do this, see DEV-9605
- LLNotifications::instance().add("CannotCloseFloaterBuyLand");
+ LLNotificationsUtil::add("CannotCloseFloaterBuyLand");
}
return can_close;
}
-// virtual
-void LLFloaterBuyLandUI::setMinimized(BOOL minimize)
+void LLFloaterBuyLandUI::onVisibilityChange ( const LLSD& new_visibility )
{
- bool restored = (isMinimized() && !minimize);
- LLFloater::setMinimized(minimize);
- if (restored)
+ if (new_visibility.asBoolean())
{
refreshUI();
}
}
-void LLFloaterBuyLandUI::onClose(bool app_quitting)
-{
- LLFloater::onClose(app_quitting);
- destroy();
-}
-
-
void LLFloaterBuyLandUI::refreshUI()
{
// section zero: title area
@@ -1082,9 +1065,7 @@ void LLFloaterBuyLandUI::refreshUI()
if (message)
{
message->setVisible(true);
- message->setWrappedText(
- !mCanBuy ? mCannotBuyReason : "(waiting for data)"
- );
+ message->setValue(LLSD(!mCanBuy ? mCannotBuyReason : "(waiting for data)"));
}
childSetVisible("error_web",
@@ -1155,7 +1136,7 @@ void LLFloaterBuyLandUI::refreshUI()
if (mIsForGroup)
{
LLStringUtil::format_map_t string_args;
- string_args["[GROUP]"] = std::string(gAgent.mGroupName);
+ string_args["[GROUP]"] = std::string(gAgent.getGroupName());
message += getString("insufficient_land_credits", string_args);
@@ -1169,7 +1150,7 @@ void LLFloaterBuyLandUI::refreshUI()
if (!mParcelValid)
{
- message += "(no parcel selected)";
+ message += getString("no_parcel_selected");
}
else if (mParcelBillableArea == mParcelActualArea)
{
@@ -1194,7 +1175,7 @@ void LLFloaterBuyLandUI::refreshUI()
}
}
- childSetWrappedText("land_use_reason", message);
+ childSetValue("land_use_reason", message);
childShow("step_2");
childShow("land_use_action");
@@ -1225,12 +1206,10 @@ void LLFloaterBuyLandUI::refreshUI()
? LLViewChildren::BADGE_NOTE
: LLViewChildren::BADGE_OK);
- childSetText("purchase_action",
- llformat(
- "Pay L$ %d to %s for this land",
- mParcelPrice,
- mParcelSellerName.c_str()
- ));
+ LLStringUtil::format_map_t string_args;
+ string_args["[AMOUNT]"] = llformat("%d", mParcelPrice);
+ string_args["[SELLER]"] = mParcelSellerName;
+ childSetText("purchase_action", getString("pay_to_for_land", string_args));
childSetVisible("purchase_action", mParcelValid);
std::string reasonString;
@@ -1250,7 +1229,7 @@ void LLFloaterBuyLandUI::refreshUI()
childSetText("currency_reason", getString("not_enough_lindens", string_args));
- childSetTextArg("currency_est", "[AMOUNT2]", llformat("%#.2f", mCurrency.getEstimate() / 100.0));
+ childSetTextArg("currency_est", "[LOCAL_AMOUNT]", mCurrency.getLocalEstimate());
}
if (willHaveEnough)
@@ -1330,7 +1309,7 @@ void LLFloaterBuyLandUI::startBuyPreConfirm()
{
LLStringUtil::format_map_t string_args;
string_args["[AMOUNT]"] = llformat("%d", mCurrency.getAmount());
- string_args["[AMOUNT2]"] = llformat("%#.2f", mCurrency.getEstimate() / 100.0);
+ string_args["[LOCAL_AMOUNT]"] = mCurrency.getLocalEstimate();
action += getString("buy_for_US", string_args);
}
@@ -1357,26 +1336,20 @@ void LLFloaterBuyLandUI::startBuyPostConfirm(const std::string& password)
}
-// static
-void LLFloaterBuyLandUI::onClickBuy(void* data)
+void LLFloaterBuyLandUI::onClickBuy()
{
- LLFloaterBuyLandUI* self = (LLFloaterBuyLandUI*)data;
- self->startBuyPreConfirm();
+ startBuyPreConfirm();
}
-// static
-void LLFloaterBuyLandUI::onClickCancel(void* data)
+void LLFloaterBuyLandUI::onClickCancel()
{
- LLFloaterBuyLandUI* self = (LLFloaterBuyLandUI*)data;
- self->close();
+ closeFloater();
}
-// static
-void LLFloaterBuyLandUI::onClickErrorWeb(void* data)
+void LLFloaterBuyLandUI::onClickErrorWeb()
{
- LLFloaterBuyLandUI* self = (LLFloaterBuyLandUI*)data;
- LLWeb::loadURLExternal(self->mCannotBuyURI);
- self->close();
+ LLWeb::loadURLExternal(mCannotBuyURI);
+ closeFloater();
}
diff --git a/indra/newview/llfloaterbuyland.h b/indra/newview/llfloaterbuyland.h
index 82e59a0bcc..00d44035ae 100644
--- a/indra/newview/llfloaterbuyland.h
+++ b/indra/newview/llfloaterbuyland.h
@@ -33,8 +33,8 @@
#ifndef LL_LLFLOATERBUYLAND_H
#define LL_LLFLOATERBUYLAND_H
+class LLFloater;
class LLViewerRegion;
-class LLViewerTextEditor;
class LLParcelSelection;
class LLFloaterBuyLand
@@ -47,7 +47,8 @@ public:
static void updateEstateName(const std::string& name);
static void updateLastModified(const std::string& text);
static void updateEstateOwnerName(const std::string& name);
- static BOOL isOpen();
+
+ static LLFloater* buildFloater(const LLSD& key);
};
#endif
diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp
index 7a4e5147fe..9496e94780 100644
--- a/indra/newview/llfloatercamera.cpp
+++ b/indra/newview/llfloatercamera.cpp
@@ -35,87 +35,384 @@
#include "llfloatercamera.h"
// Library includes
-#include "lluictrlfactory.h"
+#include "llfloaterreg.h"
// Viewer includes
#include "lljoystickbutton.h"
#include "llviewercontrol.h"
+#include "llviewercamera.h"
+#include "llbottomtray.h"
+#include "llagent.h"
+#include "lltoolmgr.h"
+#include "lltoolfocus.h"
+#include "llslider.h"
// Constants
const F32 CAMERA_BUTTON_DELAY = 0.0f;
+#define ORBIT "cam_rotate_stick"
+#define PAN "cam_track_stick"
+#define ZOOM "zoom"
+#define PRESETS "camera_presets"
+#define CONTROLS "controls"
+
+// Zoom the camera in and out
+class LLPanelCameraZoom
+: public LLPanel
+{
+ LOG_CLASS(LLPanelCameraZoom);
+public:
+ LLPanelCameraZoom();
+
+ /* virtual */ BOOL postBuild();
+ /* virtual */ void onOpen(const LLSD& key);
+
+protected:
+ void onZoomPlusHeldDown();
+ void onZoomMinusHeldDown();
+ void onSliderValueChanged();
+
+private:
+ F32 mSavedSliderVal;
+ LLButton* mPlusBtn;
+ LLButton* mMinusBtn;
+ LLSlider* mSlider;
+};
+
+static LLRegisterPanelClassWrapper<LLPanelCameraZoom> t_camera_zoom_panel("camera_zoom_panel");
+
+//-------------------------------------------------------------------------------
+// LLPanelCameraZoom
+//-------------------------------------------------------------------------------
+
+LLPanelCameraZoom::LLPanelCameraZoom()
+: mPlusBtn( NULL ),
+ mMinusBtn( NULL ),
+ mSlider( NULL ),
+ mSavedSliderVal(0.f)
+{
+ mCommitCallbackRegistrar.add("Zoom.minus", boost::bind(&LLPanelCameraZoom::onZoomPlusHeldDown, this));
+ mCommitCallbackRegistrar.add("Zoom.plus", boost::bind(&LLPanelCameraZoom::onZoomMinusHeldDown, this));
+ mCommitCallbackRegistrar.add("Slider.value_changed", boost::bind(&LLPanelCameraZoom::onSliderValueChanged, this));
+}
+
+BOOL LLPanelCameraZoom::postBuild()
+{
+ mPlusBtn = getChild <LLButton> ("zoom_plus_btn");
+ mMinusBtn = getChild <LLButton> ("zoom_minus_btn");
+ mSlider = getChild <LLSlider> ("zoom_slider");
+ mSlider->setMinValue(.0f);
+ mSlider->setMaxValue(8.f);
+ return LLPanel::postBuild();
+}
+
+void LLPanelCameraZoom::onOpen(const LLSD& key)
+{
+ LLVector3d to_focus = gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin()) - gAgent.calcFocusPositionTargetGlobal();
+ mSavedSliderVal = 8.f - (F32)to_focus.magVec(); // maximum minus current
+ mSlider->setValue( mSavedSliderVal );
+}
+
+void LLPanelCameraZoom::onZoomPlusHeldDown()
+{
+ F32 val = mSlider->getValueF32();
+ F32 inc = mSlider->getIncrement();
+ mSlider->setValue(val - inc);
+ // commit only if value changed
+ if (val != mSlider->getValueF32())
+ mSlider->onCommit();
+}
+
+void LLPanelCameraZoom::onZoomMinusHeldDown()
+{
+ F32 val = mSlider->getValueF32();
+ F32 inc = mSlider->getIncrement();
+ mSlider->setValue(val + inc);
+ // commit only if value changed
+ if (val != mSlider->getValueF32())
+ mSlider->onCommit();
+}
+
+void LLPanelCameraZoom::onSliderValueChanged()
+{
+ F32 val = mSlider->getValueF32();
+ F32 rate = val - mSavedSliderVal;
+
+ gAgent.unlockView();
+ gAgent.cameraOrbitIn(rate);
+
+ mSavedSliderVal = val;
+}
+
+void activate_camera_tool()
+{
+ LLToolMgr::getInstance()->setTransientTool(LLToolCamera::getInstance());
+};
+
//
// Member functions
//
+/*static*/ bool LLFloaterCamera::inFreeCameraMode()
+{
+ LLFloaterCamera* floater_camera = LLFloaterCamera::findInstance();
+ if (floater_camera && floater_camera->mCurrMode == CAMERA_CTRL_MODE_FREE_CAMERA && gAgent.getCameraMode() != CAMERA_MODE_MOUSELOOK)
+ {
+ return true;
+ }
+ return false;
+}
+
+bool LLFloaterCamera::inAvatarViewMode()
+{
+ return mCurrMode == CAMERA_CTRL_MODE_AVATAR_VIEW;
+}
+
+void LLFloaterCamera::resetCameraMode()
+{
+ LLFloaterCamera* floater_camera = LLFloaterCamera::findInstance();
+ if (!floater_camera) return;
+ floater_camera->switchMode(CAMERA_CTRL_MODE_ORBIT);
+}
+
+void LLFloaterCamera::update()
+{
+ ECameraControlMode mode = determineMode();
+ if (mode != mCurrMode) setMode(mode);
+}
+
+
+void LLFloaterCamera::toPrevMode()
+{
+ switchMode(mPrevMode);
+}
+
+/*static*/ void LLFloaterCamera::onLeavingMouseLook()
+{
+ LLFloaterCamera* floater_camera = LLFloaterCamera::findInstance();
+ if (floater_camera && floater_camera->inFreeCameraMode())
+ {
+ activate_camera_tool();
+ }
+}
+
+LLFloaterCamera* LLFloaterCamera::findInstance()
+{
+ return LLFloaterReg::findTypedInstance<LLFloaterCamera>("camera");
+}
+
+void LLFloaterCamera::onOpen(const LLSD& key)
+{
+ LLButton *anchor_panel = LLBottomTray::getInstance()->getChild<LLButton>("camera_btn");
+
+ setDockControl(new LLDockControl(
+ anchor_panel, this,
+ getDockTongue(), LLDockControl::TOP));
+
+ mZoom->onOpen(key);
+
+ // Returns to previous mode, see EXT-2727(View tool should remember state).
+ // In case floater was just hidden and it isn't reset the mode
+ // just update state to current one. Else go to previous.
+ if ( !mClosed )
+ updateState();
+ else
+ toPrevMode();
+ mClosed = FALSE;
+}
+
+void LLFloaterCamera::onClose(bool app_quitting)
+{
+ //We don't care of camera mode if app is quitting
+ if(app_quitting)
+ return;
+ // When mCurrMode is in CAMERA_CTRL_MODE_ORBIT
+ // switchMode won't modify mPrevMode, so force it here.
+ // It is needed to correctly return to previous mode on open, see EXT-2727.
+ if (mCurrMode == CAMERA_CTRL_MODE_ORBIT)
+ mPrevMode = CAMERA_CTRL_MODE_ORBIT;
+
+ // HACK: Should always close as docked to prevent toggleInstance without calling onOpen.
+ if ( !isDocked() )
+ setDocked(true);
+ switchMode(CAMERA_CTRL_MODE_ORBIT);
+ mClosed = TRUE;
+}
+
LLFloaterCamera::LLFloaterCamera(const LLSD& val)
-: LLFloater("camera floater") // uses "FloaterCameraRect3"
+: LLTransientDockableFloater(NULL, true, val),
+ mClosed(FALSE),
+ mCurrMode(CAMERA_CTRL_MODE_ORBIT),
+ mPrevMode(CAMERA_CTRL_MODE_ORBIT)
+{
+}
+
+// virtual
+BOOL LLFloaterCamera::postBuild()
{
setIsChrome(TRUE);
+
+ mRotate = getChild<LLJoystickCameraRotate>(ORBIT);
+ mZoom = getChild<LLPanelCameraZoom>(ZOOM);
+ mTrack = getChild<LLJoystickCameraTrack>(PAN);
+
+ assignButton2Mode(CAMERA_CTRL_MODE_ORBIT, "orbit_btn");
+ assignButton2Mode(CAMERA_CTRL_MODE_PAN, "pan_btn");
+ assignButton2Mode(CAMERA_CTRL_MODE_FREE_CAMERA, "freecamera_btn");
+ assignButton2Mode(CAMERA_CTRL_MODE_AVATAR_VIEW, "avatarview_btn");
+
+ update();
+
+ return LLDockableFloater::postBuild();
+}
+
+ECameraControlMode LLFloaterCamera::determineMode()
+{
+ LLTool* curr_tool = LLToolMgr::getInstance()->getCurrentTool();
+ if (curr_tool == LLToolCamera::getInstance())
+ {
+ return CAMERA_CTRL_MODE_FREE_CAMERA;
+ }
+
+ if (gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK)
+ {
+ return CAMERA_CTRL_MODE_AVATAR_VIEW;
+ }
+
+ return CAMERA_CTRL_MODE_ORBIT;
+}
+
+
+void clear_camera_tool()
+{
+ LLToolMgr* tool_mgr = LLToolMgr::getInstance();
+ if (tool_mgr->usingTransientTool() &&
+ tool_mgr->getCurrentTool() == LLToolCamera::getInstance())
+ {
+ tool_mgr->clearTransientTool();
+ }
+}
+
+
+void LLFloaterCamera::setMode(ECameraControlMode mode)
+{
+ if (mode != mCurrMode)
+ {
+ mPrevMode = mCurrMode;
+ mCurrMode = mode;
+ }
- // For now, only used for size and tooltip strings
- const BOOL DONT_OPEN = FALSE;
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_camera.xml", NULL, DONT_OPEN);
-
- S32 top = getRect().getHeight();
- S32 bottom = 0;
- S32 left = 16;
-
- const S32 ROTATE_WIDTH = 64;
- mRotate = new LLJoystickCameraRotate(std::string("cam rotate stick"),
- LLRect( left, top, left + ROTATE_WIDTH, bottom ),
- std::string("cam_rotate_out.tga"),
- std::string("cam_rotate_in.tga") );
- mRotate->setFollows(FOLLOWS_TOP | FOLLOWS_LEFT);
- mRotate->setHeldDownDelay(CAMERA_BUTTON_DELAY);
- mRotate->setToolTip( getString("rotate_tooltip") );
- mRotate->setSoundFlags(MOUSE_DOWN | MOUSE_UP);
- addChild(mRotate);
-
- left += ROTATE_WIDTH;
-
- const S32 ZOOM_WIDTH = 16;
- mZoom = new LLJoystickCameraZoom(
- std::string("zoom"),
- LLRect( left, top, left + ZOOM_WIDTH, bottom ),
- std::string("cam_zoom_out.tga"),
- std::string("cam_zoom_plus_in.tga"),
- std::string("cam_zoom_minus_in.tga"));
- mZoom->setFollows(FOLLOWS_TOP | FOLLOWS_LEFT);
- mZoom->setHeldDownDelay(CAMERA_BUTTON_DELAY);
- mZoom->setToolTip( getString("zoom_tooltip") );
- mZoom->setSoundFlags(MOUSE_DOWN | MOUSE_UP);
- addChild(mZoom);
-
- left += ZOOM_WIDTH;
-
- const S32 TRACK_WIDTH = 64;
- mTrack = new LLJoystickCameraTrack(std::string("cam track stick"),
- LLRect( left, top, left + TRACK_WIDTH, bottom ),
- std::string("cam_tracking_out.tga"),
- std::string("cam_tracking_in.tga"));
- mTrack->setFollows(FOLLOWS_TOP | FOLLOWS_LEFT);
- mTrack->setHeldDownDelay(CAMERA_BUTTON_DELAY);
- mTrack->setToolTip( getString("move_tooltip") );
- mTrack->setSoundFlags(MOUSE_DOWN | MOUSE_UP);
- addChild(mTrack);
+ updateState();
}
-// virtual
-void LLFloaterCamera::onOpen()
+void LLFloaterCamera::switchMode(ECameraControlMode mode)
+{
+ setMode(mode);
+
+ switch (mode)
+ {
+ case CAMERA_CTRL_MODE_ORBIT:
+ clear_camera_tool();
+ break;
+
+ case CAMERA_CTRL_MODE_PAN:
+ clear_camera_tool();
+ break;
+
+ case CAMERA_CTRL_MODE_FREE_CAMERA:
+ activate_camera_tool();
+ break;
+
+ case CAMERA_CTRL_MODE_AVATAR_VIEW:
+ break;
+
+ default:
+ //normally we won't occur here
+ llassert_always(FALSE);
+ }
+}
+
+
+void LLFloaterCamera::onClickBtn(ECameraControlMode mode)
{
- LLFloater::onOpen();
+ // check for a click on active button
+ if (mCurrMode == mode) mMode2Button[mode]->setToggleState(TRUE);
- gSavedSettings.setBOOL("ShowCameraControls", TRUE);
+ switchMode(mode);
+
}
-// virtual
-void LLFloaterCamera::onClose(bool app_quitting)
+void LLFloaterCamera::assignButton2Mode(ECameraControlMode mode, const std::string& button_name)
{
- LLFloater::onClose(app_quitting);
+ LLButton* button = getChild<LLButton>(button_name);
- if (!app_quitting)
+ button->setClickedCallback(boost::bind(&LLFloaterCamera::onClickBtn, this, mode));
+ mMode2Button[mode] = button;
+}
+
+void LLFloaterCamera::updateState()
+{
+ //updating buttons
+ std::map<ECameraControlMode, LLButton*>::const_iterator iter = mMode2Button.begin();
+ for (; iter != mMode2Button.end(); ++iter)
{
- gSavedSettings.setBOOL("ShowCameraControls", FALSE);
+ iter->second->setToggleState(iter->first == mCurrMode);
}
+
+ childSetVisible(ORBIT, CAMERA_CTRL_MODE_ORBIT == mCurrMode);
+ childSetVisible(PAN, CAMERA_CTRL_MODE_PAN == mCurrMode);
+ childSetVisible(ZOOM, CAMERA_CTRL_MODE_AVATAR_VIEW != mCurrMode);
+ childSetVisible(PRESETS, CAMERA_CTRL_MODE_AVATAR_VIEW == mCurrMode);
+
+ //hiding or showing the panel with controls by reshaping the floater
+ bool showControls = CAMERA_CTRL_MODE_FREE_CAMERA != mCurrMode;
+ if (showControls == childIsVisible(CONTROLS)) return;
+
+ childSetVisible(CONTROLS, showControls);
+
+ LLRect rect = getRect();
+ LLRect controls_rect;
+ if (childGetRect(CONTROLS, controls_rect))
+ {
+ S32 floater_header_size = getHeaderHeight();
+ S32 height = controls_rect.getHeight() - floater_header_size;
+ S32 newHeight = rect.getHeight();
+
+ if (showControls)
+ {
+ newHeight += height;
+ }
+ else
+ {
+ newHeight -= height;
+ }
+
+ rect.setOriginAndSize(rect.mLeft, rect.mBottom, rect.getWidth(), newHeight);
+ reshape(rect.getWidth(), rect.getHeight());
+ setRect(rect);
+
+ }
+}
+
+void LLFloaterCamera::onClickCameraPresets(const LLSD& param)
+{
+ std::string name = param.asString();
+
+ if ("rear_view" == name)
+ {
+ gAgent.switchCameraPreset(CAMERA_PRESET_REAR_VIEW);
+ }
+ else if ("group_view" == name)
+ {
+ gAgent.switchCameraPreset(CAMERA_PRESET_GROUP_VIEW);
+ }
+ else if ("front_view" == name)
+ {
+ gAgent.switchCameraPreset(CAMERA_PRESET_FRONT_VIEW);
+ }
+ else if ("mouselook_view" == name)
+ {
+ gAgent.changeCameraToMouselook();
+ }
+
}
diff --git a/indra/newview/llfloatercamera.h b/indra/newview/llfloatercamera.h
index 6862db7068..45d5e9a845 100644
--- a/indra/newview/llfloatercamera.h
+++ b/indra/newview/llfloatercamera.h
@@ -33,29 +33,85 @@
#ifndef LLFLOATERCAMERA_H
#define LLFLOATERCAMERA_H
-#include "llfloater.h"
+#include "lltransientdockablefloater.h"
class LLJoystickCameraRotate;
class LLJoystickCameraZoom;
class LLJoystickCameraTrack;
+class LLFloaterReg;
+class LLPanelCameraZoom;
+
+enum ECameraControlMode
+{
+ CAMERA_CTRL_MODE_ORBIT,
+ CAMERA_CTRL_MODE_PAN,
+ CAMERA_CTRL_MODE_FREE_CAMERA,
+ CAMERA_CTRL_MODE_AVATAR_VIEW
+};
class LLFloaterCamera
- : public LLFloater,
- public LLFloaterSingleton<LLFloaterCamera>
+ : public LLTransientDockableFloater
{
- friend class LLUISingleton<LLFloaterCamera, VisibilityPolicy<LLFloater> >;
+ friend class LLFloaterReg;
+public:
+
+ /* whether in free camera mode */
+ static bool inFreeCameraMode();
+ /* callback for camera presets changing */
+ static void onClickCameraPresets(const LLSD& param);
+
+ static void onLeavingMouseLook();
+
+ /** resets current camera mode to orbit mode */
+ static void resetCameraMode();
+
+ /* determines actual mode and updates ui */
+ void update();
+
+ virtual void onOpen(const LLSD& key);
+ virtual void onClose(bool app_quitting);
+
+ LLJoystickCameraRotate* mRotate;
+ LLPanelCameraZoom* mZoom;
+ LLJoystickCameraTrack* mTrack;
+
private:
+
LLFloaterCamera(const LLSD& val);
~LLFloaterCamera() {};
+
+ /* return instance if it exists - created by LLFloaterReg */
+ static LLFloaterCamera* findInstance();
+
+ /*virtual*/ BOOL postBuild();
+
+ ECameraControlMode determineMode();
+
+ /* whether in avatar view (first person) mode */
+ bool inAvatarViewMode();
+
+ /* resets to the previous mode */
+ void toPrevMode();
+
+ /* sets a new mode and performs related actions */
+ void switchMode(ECameraControlMode mode);
+
+ /* sets a new mode preserving previous one and updates ui*/
+ void setMode(ECameraControlMode mode);
+
+ /* updates the state (UI) according to the current mode */
+ void updateState();
+
+ void onClickBtn(ECameraControlMode mode);
+ void assignButton2Mode(ECameraControlMode mode, const std::string& button_name);
- /*virtual*/ void onOpen();
- /*virtual*/ void onClose(bool app_quitting);
-
-public:
- LLJoystickCameraRotate* mRotate;
- LLJoystickCameraZoom* mZoom;
- LLJoystickCameraTrack* mTrack;
+
+ BOOL mClosed;
+ ECameraControlMode mPrevMode;
+ ECameraControlMode mCurrMode;
+ std::map<ECameraControlMode, LLButton*> mMode2Button;
+
};
#endif
diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp
index ea529d1883..cdb9b8edb8 100644
--- a/indra/newview/llfloaterchat.cpp
+++ b/indra/newview/llfloaterchat.cpp
@@ -37,30 +37,25 @@
#include "llviewerprecompiledheaders.h"
-#include "llfloaterchat.h"
-#include "llfloateractivespeakers.h"
-#include "llfloaterscriptdebug.h"
-
-#include "llchat.h"
-#include "llfontgl.h"
-#include "llrect.h"
-#include "llerror.h"
-#include "llstring.h"
-#include "message.h"
-
// project include
#include "llagent.h"
+#include "llappviewer.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#include "llconsole.h"
+#include "llfloateractivespeakers.h"
#include "llfloaterchatterbox.h"
-#include "llfloatermute.h"
+#include "llfloaterreg.h"
+#include "llfloaterscriptdebug.h"
#include "llkeyboard.h"
//#include "lllineeditor.h"
#include "llmutelist.h"
//#include "llresizehandle.h"
#include "llchatbar.h"
+#include "llrecentpeople.h"
+#include "llpanelblockedlist.h"
+#include "llslurl.h"
#include "llstatusbar.h"
#include "llviewertexteditor.h"
#include "llviewergesture.h" // for triggering gestures
@@ -68,24 +63,28 @@
#include "llviewerwindow.h"
#include "llviewercontrol.h"
#include "lluictrlfactory.h"
-#include "llchatbar.h"
#include "lllogchat.h"
#include "lltexteditor.h"
#include "lltextparser.h"
-#include "llfloaterhtml.h"
#include "llweb.h"
#include "llstylemap.h"
-// Used for LCD display
-extern void AddNewIMToLCD(const std::string &newLine);
-extern void AddNewChatToLCD(const std::string &newLine);
+// linden library includes
+#include "llaudioengine.h"
+#include "llchat.h"
+#include "llfontgl.h"
+#include "llrect.h"
+#include "llerror.h"
+#include "llstring.h"
+#include "llwindow.h"
+#include "message.h"
+
//
// Constants
//
const F32 INSTANT_MSG_SIZE = 8.0f;
const F32 CHAT_MSG_SIZE = 8.0f;
-const LLColor4 MUTED_MSG_COLOR(0.5f, 0.5f, 0.5f, 1.f);
-const S32 MAX_CHATTER_COUNT = 16;
+
//
// Global statics
@@ -96,20 +95,13 @@ LLColor4 get_text_color(const LLChat& chat);
// Member Functions
//
LLFloaterChat::LLFloaterChat(const LLSD& seed)
-: LLFloater(std::string("chat floater"), std::string("FloaterChatRect"), LLStringUtil::null,
- RESIZE_YES, 440, 100, DRAG_ON_TOP, MINIMIZE_NO, CLOSE_YES),
- mPanel(NULL)
+ : LLFloater(seed),
+ mPanel(NULL)
{
mFactoryMap["chat_panel"] = LLCallbackMap(createChatPanel, NULL);
mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, NULL);
- // do not automatically open singleton floaters (as result of getInstance())
- BOOL no_open = FALSE;
- LLUICtrlFactory::getInstance()->buildFloater(this,"floater_chat_history.xml",&getFactoryMap(),no_open);
+ //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this,"floater_chat_history.xml");
- childSetCommitCallback("show mutes",onClickToggleShowMute,this); //show mutes
- childSetVisible("Chat History Editor with mute",FALSE);
- childSetAction("toggle_active_speakers_btn", onClickToggleActiveSpeakers, this);
- setDefaultBtn("Chat");
}
LLFloaterChat::~LLFloaterChat()
@@ -117,20 +109,13 @@ LLFloaterChat::~LLFloaterChat()
// Children all cleaned up by default view destructor.
}
-void LLFloaterChat::setVisible(BOOL visible)
-{
- LLFloater::setVisible( visible );
-
- gSavedSettings.setBOOL("ShowChatHistory", visible);
-}
-
void LLFloaterChat::draw()
{
// enable say and shout only when text available
childSetValue("toggle_active_speakers_btn", childIsVisible("active_speakers_panel"));
- LLChatBar* chat_barp = getChild<LLChatBar>("chat_panel", TRUE);
+ LLChatBar* chat_barp = findChild<LLChatBar>("chat_panel", TRUE);
if (chat_barp)
{
chat_barp->refresh();
@@ -142,49 +127,24 @@ void LLFloaterChat::draw()
BOOL LLFloaterChat::postBuild()
{
+ // Hide the chat overlay when our history is visible.
+ setVisibleCallback(boost::bind(&LLFloaterChat::updateConsoleVisibility, this));
+
mPanel = (LLPanelActiveSpeakers*)getChild<LLPanel>("active_speakers_panel");
- LLChatBar* chat_barp = getChild<LLChatBar>("chat_panel", TRUE);
- if (chat_barp)
- {
- chat_barp->setGestureCombo(getChild<LLComboBox>( "Gesture"));
- }
- return TRUE;
-}
+ childSetCommitCallback("show mutes",onClickToggleShowMute,this); //show mutes
+ childSetVisible("Chat History Editor with mute",FALSE);
+ childSetAction("toggle_active_speakers_btn", onClickToggleActiveSpeakers, this);
-// public virtual
-void LLFloaterChat::onClose(bool app_quitting)
-{
- if (!app_quitting)
- {
- gSavedSettings.setBOOL("ShowChatHistory", FALSE);
- }
- setVisible(FALSE);
+ return TRUE;
}
-void LLFloaterChat::onVisibilityChange(BOOL new_visibility)
+void LLFloaterChat::updateConsoleVisibility()
{
- // Hide the chat overlay when our history is visible.
- updateConsoleVisibility();
-
- // stop chat history tab from flashing when it appears
- if (new_visibility)
+ if(gDisconnected)
{
- LLFloaterChatterBox::getInstance()->setFloaterFlashing(this, FALSE);
+ return;
}
-
- LLFloater::onVisibilityChange(new_visibility);
-}
-
-void LLFloaterChat::setMinimized(BOOL minimized)
-{
- LLFloater::setMinimized(minimized);
- updateConsoleVisibility();
-}
-
-
-void LLFloaterChat::updateConsoleVisibility()
-{
// determine whether we should show console due to not being visible
gConsole->setVisible( !isInVisibleChain() // are we not in part of UI being drawn?
|| isMinimized() // are we minimized?
@@ -206,7 +166,7 @@ void add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4&
if (chat.mSourceType == CHAT_SOURCE_AGENT &&
chat.mFromID != LLUUID::null)
{
- chat.mURL = llformat("secondlife:///app/agent/%s/about",chat.mFromID.asString().c_str());
+ chat.mURL = LLSLURL::buildCommand("agent", chat.mFromID, "inspect");
}
// If the chat line has an associated url, link it up to the name.
@@ -215,29 +175,27 @@ void add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4&
{
std::string start_line = line.substr(0, chat.mFromName.length() + 1);
line = line.substr(chat.mFromName.length() + 1);
- const LLStyleSP &sourceStyle = LLStyleMap::instance().lookup(chat.mFromID,chat.mURL);
- edit->appendStyledText(start_line, false, prepend_newline, sourceStyle);
+ edit->appendText(start_line, prepend_newline, LLStyleMap::instance().lookup(chat.mFromID,chat.mURL));
+ edit->blockUndo();
prepend_newline = false;
}
- edit->appendColoredText(line, false, prepend_newline, color);
+ edit->appendText(line, prepend_newline, LLStyle::Params().color(color));
+ edit->blockUndo();
}
-void log_chat_text(const LLChat& chat)
-{
- std::string histstr;
- if (gSavedPerAccountSettings.getBOOL("LogChatTimestamp"))
- histstr = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate")) + chat.mText;
- else
- histstr = chat.mText;
-
- LLLogChat::saveHistory(std::string("chat"),histstr);
-}
// static
void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file)
{
- if ( gSavedPerAccountSettings.getBOOL("LogChat") && log_to_file)
+ if (log_to_file && (gSavedPerAccountSettings.getBOOL("LogChat")))
{
- log_chat_text(chat);
+ if (chat.mChatType != CHAT_TYPE_WHISPER && chat.mChatType != CHAT_TYPE_SHOUT)
+ {
+ LLLogChat::saveHistory("chat", chat.mFromName, chat.mFromID, chat.mText);
+ }
+ else
+ {
+ LLLogChat::saveHistory("chat", "", chat.mFromID, chat.mFromName + " " + chat.mText);
+ }
}
LLColor4 color = get_text_color(chat);
@@ -246,27 +204,23 @@ void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file)
if (chat.mChatType == CHAT_TYPE_DEBUG_MSG)
{
- LLFloaterScriptDebug::addScriptLine(chat.mText,
- chat.mFromName,
- color,
- chat.mFromID);
- if (!gSavedSettings.getBOOL("ScriptErrorsAsChat"))
+ if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE)
+ return;
+ if (gSavedSettings.getS32("ShowScriptErrorsLocation") == 1)
{
+ LLFloaterScriptDebug::addScriptLine(chat.mText,
+ chat.mFromName,
+ color,
+ chat.mFromID);
return;
}
}
// could flash the chat button in the status bar here. JC
- LLFloaterChat* chat_floater = LLFloaterChat::getInstance(LLSD());
+ LLFloaterChat* chat_floater = LLFloaterChat::getInstance();
LLViewerTextEditor* history_editor = chat_floater->getChild<LLViewerTextEditor>("Chat History Editor");
LLViewerTextEditor* history_editor_with_mute = chat_floater->getChild<LLViewerTextEditor>("Chat History Editor with mute");
- history_editor->setParseHTML(TRUE);
- history_editor_with_mute->setParseHTML(TRUE);
-
- history_editor->setParseHighlights(TRUE);
- history_editor_with_mute->setParseHighlights(TRUE);
-
if (!chat.mMuted)
{
add_timestamped_line(history_editor, chat, color);
@@ -295,8 +249,8 @@ void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file)
// static
void LLFloaterChat::setHistoryCursorAndScrollToEnd()
{
- LLViewerTextEditor* history_editor = LLFloaterChat::getInstance(LLSD())->getChild<LLViewerTextEditor>("Chat History Editor");
- LLViewerTextEditor* history_editor_with_mute = LLFloaterChat::getInstance(LLSD())->getChild<LLViewerTextEditor>("Chat History Editor with mute");
+ LLViewerTextEditor* history_editor = LLFloaterChat::getInstance()->getChild<LLViewerTextEditor>("Chat History Editor");
+ LLViewerTextEditor* history_editor_with_mute = LLFloaterChat::getInstance()->getChild<LLViewerTextEditor>("Chat History Editor with mute");
if (history_editor)
{
@@ -324,8 +278,7 @@ void LLFloaterChat::onClickMute(void *data)
LLMute mute(id);
mute.setFromDisplayName(name);
LLMuteList::getInstance()->add(mute);
-
- LLFloaterMute::showInstance();
+ LLPanelBlockedList::showPanelAndSelect(mute.mID);
}
//static
@@ -358,60 +311,59 @@ void LLFloaterChat::onClickToggleShowMute(LLUICtrl* caller, void *data)
}
// Put a line of chat in all the right places
-void LLFloaterChat::addChat(const LLChat& chat,
- BOOL from_instant_message,
- BOOL local_agent)
+void LLFloaterChat::addChat(const LLChat& chat, BOOL local_agent)
{
- LLColor4 text_color = get_text_color(chat);
+ triggerAlerts(chat.mText);
- BOOL invisible_script_debug_chat =
- chat.mChatType == CHAT_TYPE_DEBUG_MSG
- && !gSavedSettings.getBOOL("ScriptErrorsAsChat");
+ // Add the sender to the list of people with which we've recently interacted.
+ // this is not the best place to add _all_ messages to recent list
+ // comment this for now, may remove later on code cleanup
+ //if(chat.mSourceType == CHAT_SOURCE_AGENT && chat.mFromID.notNull())
+ // LLRecentPeople::instance().add(chat.mFromID);
+
+ addChatHistory(chat, true);
+}
-#if LL_LCD_COMPILE
- // add into LCD displays
- if (!invisible_script_debug_chat)
- {
- if (!from_instant_message)
- {
- AddNewChatToLCD(chat.mText);
- }
- else
- {
- AddNewIMToLCD(chat.mText);
- }
- }
-#endif
- if (!invisible_script_debug_chat
- && !chat.mMuted
- && gConsole
- && !local_agent)
+// Moved from lltextparser.cpp to break llui/llaudio library dependency.
+//static
+void LLFloaterChat::triggerAlerts(const std::string& text)
+{
+ LLTextParser* parser = LLTextParser::getInstance();
+// bool spoken=FALSE;
+ for (S32 i=0;i<parser->mHighlights.size();i++)
{
- F32 size = CHAT_MSG_SIZE;
- if (chat.mSourceType == CHAT_SOURCE_SYSTEM)
+ LLSD& highlight = parser->mHighlights[i];
+ if (parser->findPattern(text,highlight) >= 0 )
{
- text_color = gSavedSettings.getColor("SystemChatColor");
- }
- else if(from_instant_message)
- {
- text_color = gSavedSettings.getColor("IMChatColor");
- size = INSTANT_MSG_SIZE;
- }
- // We display anything if it's not an IM. If it's an IM, check pref...
- if ( !from_instant_message || gSavedSettings.getBOOL("IMInChatConsole") )
- {
- gConsole->addLine(chat.mText, size, text_color);
+ if(gAudiop)
+ {
+ if ((std::string)highlight["sound_lluuid"] != LLUUID::null.asString())
+ {
+ gAudiop->triggerSound(highlight["sound_lluuid"].asUUID(),
+ gAgent.getID(),
+ 1.f,
+ LLAudioEngine::AUDIO_TYPE_UI,
+ gAgent.getPositionGlobal() );
+ }
+/*
+ if (!spoken)
+ {
+ LLTextToSpeech* text_to_speech = NULL;
+ text_to_speech = LLTextToSpeech::getInstance();
+ spoken = text_to_speech->speak((LLString)highlight["voice"],text);
+ }
+ */
+ }
+ if (highlight["flash"])
+ {
+ LLWindow* viewer_window = gViewerWindow->getWindow();
+ if (viewer_window && viewer_window->getMinimized())
+ {
+ viewer_window->flashIcon(5.f);
+ }
+ }
}
}
-
- if(from_instant_message && gSavedPerAccountSettings.getBOOL("LogChatIM"))
- log_chat_text(chat);
-
- LLTextParser* highlight = LLTextParser::getInstance();
- highlight->triggerAlerts(gAgent.getID(), gAgent.getPositionGlobal(), chat.mText, gViewerWindow->getWindow());
-
- if(!from_instant_message)
- addChatHistory(chat);
}
LLColor4 get_text_color(const LLChat& chat)
@@ -427,37 +379,37 @@ LLColor4 get_text_color(const LLChat& chat)
switch(chat.mSourceType)
{
case CHAT_SOURCE_SYSTEM:
- text_color = gSavedSettings.getColor4("SystemChatColor");
+ text_color = LLUIColorTable::instance().getColor("SystemChatColor");
break;
case CHAT_SOURCE_AGENT:
if (chat.mFromID.isNull())
{
- text_color = gSavedSettings.getColor4("SystemChatColor");
+ text_color = LLUIColorTable::instance().getColor("SystemChatColor");
}
else
{
if(gAgent.getID() == chat.mFromID)
{
- text_color = gSavedSettings.getColor4("UserChatColor");
+ text_color = LLUIColorTable::instance().getColor("UserChatColor");
}
else
{
- text_color = gSavedSettings.getColor4("AgentChatColor");
+ text_color = LLUIColorTable::instance().getColor("AgentChatColor");
}
}
break;
case CHAT_SOURCE_OBJECT:
if (chat.mChatType == CHAT_TYPE_DEBUG_MSG)
{
- text_color = gSavedSettings.getColor4("ScriptErrorColor");
+ text_color = LLUIColorTable::instance().getColor("ScriptErrorColor");
}
else if ( chat.mChatType == CHAT_TYPE_OWNER )
{
- text_color = gSavedSettings.getColor4("llOwnerSayChatColor");
+ text_color = LLUIColorTable::instance().getColor("llOwnerSayChatColor");
}
else
{
- text_color = gSavedSettings.getColor4("ObjectChatColor");
+ text_color = LLUIColorTable::instance().getColor("ObjectChatColor");
}
break;
default:
@@ -482,11 +434,11 @@ LLColor4 get_text_color(const LLChat& chat)
//static
void LLFloaterChat::loadHistory()
{
- LLLogChat::loadHistory(std::string("chat"), &chatFromLogFile, (void *)LLFloaterChat::getInstance(LLSD()));
+ LLLogChat::loadHistory(std::string("chat"), &chatFromLogFile, (void *)LLFloaterChat::getInstance());
}
//static
-void LLFloaterChat::chatFromLogFile(LLLogChat::ELogLineType type , std::string line, void* userdata)
+void LLFloaterChat::chatFromLogFile(LLLogChat::ELogLineType type , const LLSD& line, void* userdata)
{
switch (type)
{
@@ -495,9 +447,11 @@ void LLFloaterChat::chatFromLogFile(LLLogChat::ELogLineType type , std::string l
// *TODO: nice message from XML file here
break;
case LLLogChat::LOG_LINE:
+ case LLLogChat::LOG_LLSD:
{
LLChat chat;
- chat.mText = line;
+ chat.mText = line["message"].asString();
+ get_text_color(chat);
addChatHistory(chat, FALSE);
}
break;
@@ -528,27 +482,9 @@ void LLFloaterChat::onClickToggleActiveSpeakers(void* userdata)
self->childSetVisible("active_speakers_panel", !self->childIsVisible("active_speakers_panel"));
}
-//static
-bool LLFloaterChat::visible(LLFloater* instance, const LLSD& key)
-{
- return VisibilityPolicy<LLFloater>::visible(instance, key);
-}
-
-//static
-void LLFloaterChat::show(LLFloater* instance, const LLSD& key)
-{
- VisibilityPolicy<LLFloater>::show(instance, key);
-}
-
-//static
-void LLFloaterChat::hide(LLFloater* instance, const LLSD& key)
-{
- if(instance->getHost())
- {
- LLFloaterChatterBox::hideInstance();
- }
- else
- {
- VisibilityPolicy<LLFloater>::hide(instance, key);
- }
-}
+//static
+ LLFloaterChat* LLFloaterChat::getInstance()
+ {
+ return LLFloaterReg::getTypedInstance<LLFloaterChat>("chat", LLSD()) ;
+
+ }
diff --git a/indra/newview/llfloaterchat.h b/indra/newview/llfloaterchat.h
index b5393866b8..4437a0a5c2 100644
--- a/indra/newview/llfloaterchat.h
+++ b/indra/newview/llfloaterchat.h
@@ -40,54 +40,43 @@
#include "llfloater.h"
#include "lllogchat.h"
-class LLButton;
+
class LLChat;
-class LLComboBox;
-class LLLineEditor;
-class LLViewerTextEditor;
-class LLMessageSystem;
-class LLUUID;
-class LLCheckBoxCtrl;
class LLPanelActiveSpeakers;
class LLLogChat;
-class LLFloaterChat
- : public LLFloater, public LLUISingleton<LLFloaterChat, LLFloaterChat>
+class LLFloaterChat : public LLFloater
{
public:
LLFloaterChat(const LLSD& seed);
~LLFloaterChat();
- virtual void setVisible( BOOL b );
virtual void draw();
virtual BOOL postBuild();
- virtual void onClose(bool app_quitting);
- virtual void onVisibilityChange(BOOL cur_visibility);
- virtual void setMinimized(BOOL);
+
void updateConsoleVisibility();
static void setHistoryCursorAndScrollToEnd();
-
+
+ // *TODO:Skinning - move these to LLChat (or LLViewerChat?)
// Add chat to console and history list.
// Color based on source, type, distance.
- static void addChat(const LLChat& chat, BOOL from_im = FALSE, BOOL local_agent = FALSE);
-
+ static void addChat(const LLChat& chat, BOOL local_agent = FALSE);
// Add chat to history alone.
static void addChatHistory(const LLChat& chat, bool log_to_file = true);
+ static void triggerAlerts(const std::string& text);
+
static void onClickMute(void *data);
static void onClickToggleShowMute(LLUICtrl* caller, void *data);
static void onClickToggleActiveSpeakers(void* userdata);
- static void chatFromLogFile(LLLogChat::ELogLineType type,std::string line, void* userdata);
+ static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& line, void* userdata);
static void loadHistory();
static void* createSpeakersPanel(void* data);
static void* createChatPanel(void* data);
-
- // visibility policy for LLUISingleton
- static bool visible(LLFloater* instance, const LLSD& key);
- static void show(LLFloater* instance, const LLSD& key);
- static void hide(LLFloater* instance, const LLSD& key);
-
+
+ static LLFloaterChat* getInstance(); // *TODO:Skinning Deprecate
+
LLPanelActiveSpeakers* mPanel;
BOOL mScrolledToEnd;
};
diff --git a/indra/newview/llfloaterchatterbox.cpp b/indra/newview/llfloaterchatterbox.cpp
index 0fa1aa15e6..84b423399e 100644
--- a/indra/newview/llfloaterchatterbox.cpp
+++ b/indra/newview/llfloaterchatterbox.cpp
@@ -35,26 +35,26 @@
#include "llviewerprecompiledheaders.h"
+#include "llfloaterreg.h"
#include "llfloaterchatterbox.h"
#include "lluictrlfactory.h"
-#include "llfloaterchat.h"
#include "llfloaterfriends.h"
#include "llfloatergroups.h"
#include "llviewercontrol.h"
-#include "llimview.h"
+#include "llvoicechannel.h"
#include "llimpanel.h"
+#include "llimview.h"
//
// LLFloaterMyFriends
//
LLFloaterMyFriends::LLFloaterMyFriends(const LLSD& seed)
+ : LLFloater(seed)
{
mFactoryMap["friends_panel"] = LLCallbackMap(LLFloaterMyFriends::createFriendsPanel, NULL);
mFactoryMap["groups_panel"] = LLCallbackMap(LLFloaterMyFriends::createGroupsPanel, NULL);
- // do not automatically open singleton floaters (as result of getInstance())
- BOOL no_open = FALSE;
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_my_friends.xml", &getFactoryMap(), no_open);
+ //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_my_friends.xml");
}
LLFloaterMyFriends::~LLFloaterMyFriends()
@@ -63,15 +63,19 @@ LLFloaterMyFriends::~LLFloaterMyFriends()
BOOL LLFloaterMyFriends::postBuild()
{
- mTabs = getChild<LLTabContainer>("friends_and_groups");
-
return TRUE;
}
-
-void LLFloaterMyFriends::onClose(bool app_quitting)
+void LLFloaterMyFriends::onOpen(const LLSD& key)
{
- setVisible(FALSE);
+ if (key.asString() == "friends")
+ {
+ childShowTab("friends_and_groups", "friends_panel");
+ }
+ else if (key.asString() == "groups")
+ {
+ childShowTab("friends_and_groups", "groups_panel");
+ }
}
//static
@@ -86,47 +90,51 @@ void* LLFloaterMyFriends::createGroupsPanel(void* data)
return new LLPanelGroups();
}
+//static
+LLFloaterMyFriends* LLFloaterMyFriends::getInstance()
+{
+ return LLFloaterReg::getTypedInstance<LLFloaterMyFriends>("contacts", "friends") ;
+}
+
//
// LLFloaterChatterBox
//
-LLFloaterChatterBox::LLFloaterChatterBox(const LLSD& seed) :
+LLFloaterChatterBox::LLFloaterChatterBox(const LLSD& seed)
+: LLMultiFloater(seed),
mActiveVoiceFloater(NULL)
{
mAutoResize = FALSE;
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_chatterbox.xml", NULL, FALSE);
+ //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_chatterbox.xml", FALSE);
+}
+
+LLFloaterChatterBox::~LLFloaterChatterBox()
+{
+}
+
+BOOL LLFloaterChatterBox::postBuild()
+{
+ setVisibleCallback(boost::bind(&LLFloaterChatterBox::onVisibilityChange, this, _2));
+
if (gSavedSettings.getBOOL("ContactsTornOff"))
{
- LLFloaterMyFriends* floater_contacts = LLFloaterMyFriends::getInstance(0);
- // add then remove to set up relationship for re-attach
- addFloater(floater_contacts, FALSE);
- removeFloater(floater_contacts);
- // reparent to floater view
- gFloaterView->addChild(floater_contacts);
+ LLFloaterMyFriends* floater_contacts = LLFloaterMyFriends::getInstance();
+ if(floater_contacts)
+ {
+ // add then remove to set up relationship for re-attach
+ addFloater(floater_contacts, FALSE);
+ removeFloater(floater_contacts);
+ // reparent to floater view
+ gFloaterView->addChild(floater_contacts);
+ }
}
else
{
- addFloater(LLFloaterMyFriends::getInstance(0), TRUE);
+ addFloater(LLFloaterMyFriends::getInstance(), TRUE);
}
- if (gSavedSettings.getBOOL("ChatHistoryTornOff"))
- {
- LLFloaterChat* floater_chat = LLFloaterChat::getInstance();
- // add then remove to set up relationship for re-attach
- addFloater(floater_chat, FALSE);
- removeFloater(floater_chat);
- // reparent to floater view
- gFloaterView->addChild(floater_chat);
- }
- else
- {
- addFloater(LLFloaterChat::getInstance(LLSD()), FALSE);
- }
mTabContainer->lockTabs();
-}
-
-LLFloaterChatterBox::~LLFloaterChatterBox()
-{
+ return TRUE;
}
BOOL LLFloaterChatterBox::handleKeyHere(KEY key, MASK mask)
@@ -139,13 +147,13 @@ BOOL LLFloaterChatterBox::handleKeyHere(KEY key, MASK mask)
{
if (floater->isCloseable())
{
- floater->close();
+ floater->closeFloater();
}
else
{
// close chatterbox window if frontmost tab is reserved, non-closeable tab
// such as contacts or near me
- close();
+ closeFloater();
}
}
return TRUE;
@@ -200,26 +208,30 @@ void LLFloaterChatterBox::draw()
LLMultiFloater::draw();
}
-void LLFloaterChatterBox::onOpen()
-{
- gSavedSettings.setBOOL("ShowCommunicate", TRUE);
-}
-
-void LLFloaterChatterBox::onClose(bool app_quitting)
+void LLFloaterChatterBox::onOpen(const LLSD& key)
{
- setVisible(FALSE);
- gSavedSettings.setBOOL("ShowCommunicate", FALSE);
+ //*TODO:Skinning show the session id associated with key
+ if (key.asString() == "local")
+ {
+ }
+ else if (key.isDefined())
+ {
+ LLFloaterIMPanel* impanel = gIMMgr->findFloaterBySession(key.asUUID());
+ if (impanel)
+ {
+ impanel->openFloater();
+ }
+ }
}
-void LLFloaterChatterBox::setMinimized(BOOL minimized)
+void LLFloaterChatterBox::onVisibilityChange ( const LLSD& new_visibility )
{
- LLFloater::setMinimized(minimized);
- // HACK: potentially need to toggle console
- LLFloaterChat::getInstance()->updateConsoleVisibility();
}
void LLFloaterChatterBox::removeFloater(LLFloater* floaterp)
{
+ if(!floaterp) return;
+
if (floaterp->getName() == "chat floater")
{
// only my friends floater now locked
@@ -241,10 +253,16 @@ void LLFloaterChatterBox::addFloater(LLFloater* floaterp,
BOOL select_added_floater,
LLTabContainer::eInsertionPoint insertion_point)
{
+ if(!floaterp) return;
+
S32 num_locked_tabs = mTabContainer->getNumLockedTabs();
// already here
- if (floaterp->getHost() == this) return;
+ if (floaterp->getHost() == this)
+ {
+ openFloater(floaterp->getKey());
+ return;
+ }
// make sure my friends and chat history both locked when re-attaching chat history
if (floaterp->getName() == "chat floater")
@@ -281,6 +299,7 @@ void LLFloaterChatterBox::addFloater(LLFloater* floaterp,
else
{
LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point);
+ // openFloater(floaterp->getKey());
}
// make sure active voice icon shows up for new tab
@@ -290,6 +309,12 @@ void LLFloaterChatterBox::addFloater(LLFloater* floaterp,
}
}
+//static
+LLFloaterChatterBox* LLFloaterChatterBox::getInstance()
+{
+ return LLFloaterReg::getTypedInstance<LLFloaterChatterBox>("communicate", LLSD()) ;
+}
+
//static
LLFloater* LLFloaterChatterBox::getCurrentVoiceFloater()
{
@@ -299,12 +324,12 @@ LLFloater* LLFloaterChatterBox::getCurrentVoiceFloater()
}
if (LLVoiceChannelProximal::getInstance() == LLVoiceChannel::getCurrentVoiceChannel())
{
- // show near me tab if in proximal channel
- return LLFloaterChat::getInstance(LLSD());
+ return NULL;
}
else
{
- LLFloaterChatterBox* floater = LLFloaterChatterBox::getInstance(LLSD());
+ LLFloaterChatterBox* floater = LLFloaterChatterBox::getInstance();
+ if(!floater) return NULL;
// iterator over all IM tabs (skip friends and near me)
for (S32 i = 0; i < floater->getFloaterCount(); i++)
{
@@ -313,7 +338,8 @@ LLFloater* LLFloaterChatterBox::getCurrentVoiceFloater()
{
// only LLFloaterIMPanels are called "im_floater"
LLFloaterIMPanel* im_floaterp = (LLFloaterIMPanel*)panelp;
- if (im_floaterp->getVoiceChannel() == LLVoiceChannel::getCurrentVoiceChannel())
+ LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(im_floaterp->getSessionID());
+ if (voice_channel == LLVoiceChannel::getCurrentVoiceChannel())
{
return im_floaterp;
}
diff --git a/indra/newview/llfloaterchatterbox.h b/indra/newview/llfloaterchatterbox.h
index 3adbd14370..ab44281d81 100644
--- a/indra/newview/llfloaterchatterbox.h
+++ b/indra/newview/llfloaterchatterbox.h
@@ -36,131 +36,51 @@
#define LL_LLFLOATERCHATTERBOX_H
#include "llfloater.h"
+#include "llmultifloater.h"
#include "llstring.h"
-#include "llimview.h"
#include "llimpanel.h"
class LLTabContainer;
-class LLFloaterChatterBox : public LLMultiFloater, public LLUISingleton<LLFloaterChatterBox, LLFloaterChatterBox>
+class LLFloaterChatterBox : public LLMultiFloater
{
public:
LLFloaterChatterBox(const LLSD& seed);
virtual ~LLFloaterChatterBox();
-
+
+ /*virtual*/ BOOL postBuild();
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
/*virtual*/ void draw();
- /*virtual*/ void onOpen();
- /*virtual*/ void onClose(bool app_quitting);
- /*virtual*/ void setMinimized(BOOL minimized);
+ /*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ void removeFloater(LLFloater* floaterp);
/*virtual*/ void addFloater(LLFloater* floaterp,
BOOL select_added_floater,
LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END);
+ static LLFloaterChatterBox* getInstance(); // *TODO:Skinning Deprecate
static LLFloater* getCurrentVoiceFloater();
- // visibility policy for LLUISingleton
- static bool visible(LLFloater* instance, const LLSD& key)
- {
- LLFloater* floater_to_check = ((LLFloaterChatterBox*)instance)->getFloater(key);
-
- if (floater_to_check)
- {
- return floater_to_check->isInVisibleChain();
- }
-
- // otherwise use default visibility rule for chatterbox
- return VisibilityPolicy<LLFloater>::visible(instance, key);
- }
-
- static void show(LLFloater* instance, const LLSD& key)
- {
- LLFloater* floater_to_show = ((LLFloaterChatterBox*)instance)->getFloater(key);
- VisibilityPolicy<LLFloater>::show(instance, key);
-
- if (floater_to_show)
- {
- floater_to_show->open();
- }
- }
-
- static void hide(LLFloater* instance, const LLSD& key)
- {
- VisibilityPolicy<LLFloater>::hide(instance, key);
- }
-
-private:
- LLFloater* getFloater(const LLSD& key)
- {
- LLFloater* floater = NULL;
-
- //try to show requested session
- LLUUID session_id = key.asUUID();
- if (session_id.notNull())
- {
- floater = LLIMMgr::getInstance()->findFloaterBySession(session_id);
- }
-
- // if TRUE, show tab for active voice channel, otherwise, just show last tab
- if (key.asBoolean())
- {
- floater = getCurrentVoiceFloater();
- }
-
- return floater;
- }
-
protected:
+ void onVisibilityChange ( const LLSD& new_visibility );
+
LLFloater* mActiveVoiceFloater;
};
-class LLFloaterMyFriends : public LLFloater, public LLUISingleton<LLFloaterMyFriends, LLFloaterMyFriends>
+class LLFloaterMyFriends : public LLFloater
{
public:
LLFloaterMyFriends(const LLSD& seed);
virtual ~LLFloaterMyFriends();
- virtual BOOL postBuild();
-
- void onClose(bool app_quitting);
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+ static LLFloaterMyFriends* getInstance(); // *TODO:Skinning Deprecate
+
static void* createFriendsPanel(void* data);
static void* createGroupsPanel(void* data);
-
- // visibility policy for LLUISingleton
- static bool visible(LLFloater* instance, const LLSD& key)
- {
- LLFloaterMyFriends* floaterp = (LLFloaterMyFriends*)instance;
- return floaterp->isInVisibleChain() && floaterp->mTabs->getCurrentPanelIndex() == key.asInteger();
- }
-
- static void show(LLFloater* instance, const LLSD& key)
- {
- VisibilityPolicy<LLFloater>::show(instance, key);
- // garbage values in id will be interpreted as 0, or the friends tab
- ((LLFloaterMyFriends*)instance)->mTabs->selectTab(key);
- }
-
- static void hide(LLFloater* instance, const LLSD& key)
- {
- if (visible(instance, key))
- {
- if(instance->getHost())
- {
- LLFloaterChatterBox::hideInstance();
- }
- else
- {
- VisibilityPolicy<LLFloater>::hide(instance, key);
- }
- }
- }
-
-protected:
- LLTabContainer* mTabs;
};
#endif // LL_LLFLOATERCHATTERBOX_H
diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp
index f82d692dd3..73b79d8e13 100644
--- a/indra/newview/llfloatercolorpicker.cpp
+++ b/indra/newview/llfloatercolorpicker.cpp
@@ -32,11 +32,15 @@
#include "llviewerprecompiledheaders.h"
-#include <sstream>
-#include <iomanip>
-
#include "llfloatercolorpicker.h"
+// Viewer project includes
+#include "lltoolmgr.h"
+#include "lltoolpipette.h"
+#include "llviewercontrol.h"
+#include "llworld.h"
+
+// Linden library includes
#include "llfontgl.h"
#include "llsys.h"
#include "llgl.h"
@@ -47,23 +51,22 @@
#include "lllineeditor.h"
#include "v4coloru.h"
#include "llbutton.h"
-#include "llviewercontrol.h"
#include "lluictrlfactory.h"
-#include "llviewerwindow.h"
#include "llgl.h"
-#include "llmemory.h"
+#include "llpointer.h"
#include "llimage.h"
#include "llmousehandler.h"
-#include "llimagegl.h"
#include "llglheaders.h"
#include "llcheckboxctrl.h"
-#include "llworld.h"
#include "lltextbox.h"
#include "lluiconstants.h"
#include "llfocusmgr.h"
-#include "lltoolmgr.h"
-#include "lltoolpipette.h"
#include "lldraghandle.h"
+#include "llwindow.h"
+
+// System includes
+#include <sstream>
+#include <iomanip>
const F32 CONTEXT_CONE_IN_ALPHA = 0.0f;
const F32 CONTEXT_CONE_OUT_ALPHA = 1.f;
@@ -75,11 +78,8 @@ const F32 CONTEXT_FADE_TIME = 0.08f;
//
//////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-// default ctor
-LLFloaterColorPicker::
-LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show_apply_immediate )
- : LLFloater (std::string("Color Picker Floater")),
+LLFloaterColorPicker::LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show_apply_immediate )
+ : LLFloater(LLSD()),
mComponents ( 3 ),
mMouseDownInLumRegion ( FALSE ),
mMouseDownInHueRegion ( FALSE ),
@@ -113,6 +113,9 @@ LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show_apply_immediate )
mCanApplyImmediately ( show_apply_immediate ),
mContextConeOpacity ( 0.f )
{
+ // build the majority of the gui using the factory builder
+ LLUICtrlFactory::getInstance()->buildFloater ( this, "floater_color_picker.xml", NULL );
+
// create user interface for this picker
createUI ();
@@ -123,10 +126,7 @@ LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show_apply_immediate )
}
}
-//////////////////////////////////////////////////////////////////////////////
-// dtor
-LLFloaterColorPicker::
-~LLFloaterColorPicker()
+LLFloaterColorPicker::~LLFloaterColorPicker()
{
// destroy the UI we created
destroyUI ();
@@ -134,14 +134,8 @@ LLFloaterColorPicker::
//////////////////////////////////////////////////////////////////////////////
//
-void
-LLFloaterColorPicker::
-createUI ()
+void LLFloaterColorPicker::createUI ()
{
- // build the majority of the gui using the factory builder
- LLUICtrlFactory::getInstance()->buildFloater ( this, "floater_color_picker.xml" );
- setVisible ( FALSE );
-
// create RGB type area (not really RGB but it's got R,G & B in it.,..
LLPointer<LLImageRaw> raw = new LLImageRaw ( mRGBViewerImageWidth, mRGBViewerImageHeight, mComponents );
@@ -165,7 +159,7 @@ createUI ()
* ( bits + x + y * linesize + 2 ) = ( U8 )( bVal * 255.0f );
}
}
- mRGBImage = new LLImageGL ( (LLImageRaw*)raw, FALSE );
+ mRGBImage = LLViewerTextureManager::getLocalTexture( (LLImageRaw*)raw, FALSE );
gGL.getTexUnit(0)->bind(mRGBImage);
mRGBImage->setAddressMode(LLTexUnit::TAM_CLAMP);
@@ -177,19 +171,17 @@ createUI ()
// argh!
const std::string s ( codec.str () );
- mPalette.push_back ( new LLColor4 ( gSavedSettings.getColor4 ( s ) ) );
+ mPalette.push_back ( new LLColor4 ( LLUIColorTable::instance().getColor ( s ) ) );
}
}
//////////////////////////////////////////////////////////////////////////////
//
-void
-LLFloaterColorPicker::
-showUI ()
+void LLFloaterColorPicker::showUI ()
{
setVisible ( TRUE );
setFocus ( TRUE );
- open(); /*Flawfinder: ignore*/
+ openFloater(getKey());
// HACK: if system color picker is required - close the SL one we made and use default system dialog
if ( gSavedSettings.getBOOL ( "UseDefaultColorPicker" ) )
@@ -203,7 +195,7 @@ showUI ()
{
LLColor4 curCol = swatch->get ();
send_agent_pause();
- gViewerWindow->getWindow ()->dialog_color_picker ( &curCol [ 0 ], &curCol [ 1 ], &curCol [ 2 ] );
+ getWindow()->dialogColorPicker( &curCol [ 0 ], &curCol [ 1 ], &curCol [ 2 ] );
send_agent_resume();
setOrigRgb ( curCol [ 0 ], curCol [ 1 ], curCol [ 2 ] );
@@ -212,36 +204,30 @@ showUI ()
LLColorSwatchCtrl::onColorChanged ( swatch, LLColorSwatchCtrl::COLOR_CHANGE );
}
- close();
+ closeFloater();
}
}
//////////////////////////////////////////////////////////////////////////////
// called after the dialog is rendered
-BOOL
-LLFloaterColorPicker::
-postBuild()
+BOOL LLFloaterColorPicker::postBuild()
{
mCancelBtn = getChild<LLButton>( "cancel_btn" );
- mCancelBtn->setClickedCallback ( onClickCancel );
- mCancelBtn->setCallbackUserData ( this );
+ mCancelBtn->setClickedCallback ( onClickCancel, this );
mSelectBtn = getChild<LLButton>( "select_btn");
- mSelectBtn->setClickedCallback ( onClickSelect );
- mSelectBtn->setCallbackUserData ( this );
+ mSelectBtn->setClickedCallback ( onClickSelect, this );
mSelectBtn->setFocus ( TRUE );
mPipetteBtn = getChild<LLButton>("color_pipette" );
mPipetteBtn->setImages(std::string("eye_button_inactive.tga"), std::string("eye_button_active.tga"));
- mPipetteBtn->setClickedCallback( onClickPipette );
- mPipetteBtn->setCallbackUserData ( this );
+ mPipetteBtn->setCommitCallback( boost::bind(&LLFloaterColorPicker::onClickPipette, this ));
mApplyImmediateCheck = getChild<LLCheckBoxCtrl>("apply_immediate");
mApplyImmediateCheck->set(gSavedSettings.getBOOL("ApplyColorImmediately"));
- mApplyImmediateCheck->setCommitCallback(onImmediateCheck);
- mApplyImmediateCheck->setCallbackUserData(this);
+ mApplyImmediateCheck->setCommitCallback(onImmediateCheck, this);
childSetCommitCallback("rspin", onTextCommit, (void*)this );
childSetCommitCallback("gspin", onTextCommit, (void*)this );
@@ -250,18 +236,15 @@ postBuild()
childSetCommitCallback("sspin", onTextCommit, (void*)this );
childSetCommitCallback("lspin", onTextCommit, (void*)this );
+ LLToolPipette::getInstance()->setToolSelectCallback(boost::bind(&LLFloaterColorPicker::onColorSelect, this, _1));
+
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////
//
-void
-LLFloaterColorPicker::
-initUI ( F32 rValIn, F32 gValIn, F32 bValIn )
+void LLFloaterColorPicker::initUI ( F32 rValIn, F32 gValIn, F32 bValIn )
{
- // start catching lose-focus events from entry widgets
- enableTextCallbacks ( TRUE );
-
// under some circumstances, we get rogue values that can be calmed by clamping...
rValIn = llclamp ( rValIn, 0.0f, 1.0f );
gValIn = llclamp ( gValIn, 0.0f, 1.0f );
@@ -279,9 +262,7 @@ initUI ( F32 rValIn, F32 gValIn, F32 bValIn )
//////////////////////////////////////////////////////////////////////////////
//
-void
-LLFloaterColorPicker::
-destroyUI ()
+void LLFloaterColorPicker::destroyUI ()
{
// shut down pipette tool if active
stopUsingPipette();
@@ -305,9 +286,7 @@ destroyUI ()
//////////////////////////////////////////////////////////////////////////////
//
-F32
-LLFloaterColorPicker::
-hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn )
+F32 LLFloaterColorPicker::hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn )
{
if ( valHUeIn < 0.0f ) valHUeIn += 1.0f;
if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f;
@@ -319,9 +298,7 @@ hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn )
//////////////////////////////////////////////////////////////////////////////
//
-void
-LLFloaterColorPicker::
-hslToRgb ( F32 hValIn, F32 sValIn, F32 lValIn, F32& rValOut, F32& gValOut, F32& bValOut )
+void LLFloaterColorPicker::hslToRgb ( F32 hValIn, F32 sValIn, F32 lValIn, F32& rValOut, F32& gValOut, F32& bValOut )
{
if ( sValIn < 0.00001f )
{
@@ -349,9 +326,7 @@ hslToRgb ( F32 hValIn, F32 sValIn, F32 lValIn, F32& rValOut, F32& gValOut, F32&
//////////////////////////////////////////////////////////////////////////////
// mutator for original RGB value
-void
-LLFloaterColorPicker::
-setOrigRgb ( F32 origRIn, F32 origGIn, F32 origBIn )
+void LLFloaterColorPicker::setOrigRgb ( F32 origRIn, F32 origGIn, F32 origBIn )
{
origR = origRIn;
origG = origGIn;
@@ -360,9 +335,7 @@ setOrigRgb ( F32 origRIn, F32 origGIn, F32 origBIn )
//////////////////////////////////////////////////////////////////////////////
// accessor for original RGB value
-void
-LLFloaterColorPicker::
-getOrigRgb ( F32& origROut, F32& origGOut, F32& origBOut )
+void LLFloaterColorPicker::getOrigRgb ( F32& origROut, F32& origGOut, F32& origBOut )
{
origROut = origR;
origGOut = origG;
@@ -371,9 +344,7 @@ getOrigRgb ( F32& origROut, F32& origGOut, F32& origBOut )
//////////////////////////////////////////////////////////////////////////////
// mutator for current RGB value
-void
-LLFloaterColorPicker::
-setCurRgb ( F32 curRIn, F32 curGIn, F32 curBIn )
+void LLFloaterColorPicker::setCurRgb ( F32 curRIn, F32 curGIn, F32 curBIn )
{
// save current RGB
curR = curRIn;
@@ -383,19 +354,13 @@ setCurRgb ( F32 curRIn, F32 curGIn, F32 curBIn )
// update corresponding HSL values and
LLColor3(curRIn, curGIn, curBIn).calcHSL(&curH, &curS, &curL);
- // color changed so update text fields (fixes SL-16968)
- // HACK: turn off the call back wilst we update the text or we recurse ourselves into oblivion
- // CP: this was required when I first wrote the code but this may not be necessary anymore - leaving it there just in case
- enableTextCallbacks( FALSE );
+ // color changed so update text fields
updateTextEntry();
- enableTextCallbacks( TRUE );
}
//////////////////////////////////////////////////////////////////////////////
// accessor for current RGB value
-void
-LLFloaterColorPicker::
-getCurRgb ( F32& curROut, F32& curGOut, F32& curBOut )
+void LLFloaterColorPicker::getCurRgb ( F32& curROut, F32& curGOut, F32& curBOut )
{
curROut = curR;
curGOut = curG;
@@ -404,9 +369,7 @@ getCurRgb ( F32& curROut, F32& curGOut, F32& curBOut )
//////////////////////////////////////////////////////////////////////////////
// mutator for current HSL value
-void
-LLFloaterColorPicker::
-setCurHsl ( F32 curHIn, F32 curSIn, F32 curLIn )
+void LLFloaterColorPicker::setCurHsl ( F32 curHIn, F32 curSIn, F32 curLIn )
{
// save current HSL
curH = curHIn;
@@ -419,9 +382,7 @@ setCurHsl ( F32 curHIn, F32 curSIn, F32 curLIn )
//////////////////////////////////////////////////////////////////////////////
// accessor for current HSL value
-void
-LLFloaterColorPicker::
-getCurHsl ( F32& curHOut, F32& curSOut, F32& curLOut )
+void LLFloaterColorPicker::getCurHsl ( F32& curHOut, F32& curSOut, F32& curLOut )
{
curHOut = curH;
curSOut = curS;
@@ -430,9 +391,7 @@ getCurHsl ( F32& curHOut, F32& curSOut, F32& curLOut )
//////////////////////////////////////////////////////////////////////////////
// called when 'cancel' clicked
-void
-LLFloaterColorPicker::
-onClickCancel ( void* data )
+void LLFloaterColorPicker::onClickCancel ( void* data )
{
if (data)
{
@@ -441,16 +400,14 @@ onClickCancel ( void* data )
if ( self )
{
self->cancelSelection ();
- self->close();
+ self->closeFloater();
}
}
}
//////////////////////////////////////////////////////////////////////////////
// called when 'select' clicked
-void
-LLFloaterColorPicker::
-onClickSelect ( void* data )
+void LLFloaterColorPicker::onClickSelect ( void* data )
{
if (data)
{
@@ -460,36 +417,28 @@ onClickSelect ( void* data )
{
// apply to selection
LLColorSwatchCtrl::onColorChanged ( self->getSwatch (), LLColorSwatchCtrl::COLOR_SELECT );
- self->close();
+ self->closeFloater();
}
}
}
-void LLFloaterColorPicker::onClickPipette( void* data )
+void LLFloaterColorPicker::onClickPipette( )
{
- LLFloaterColorPicker* self = ( LLFloaterColorPicker* )data;
-
- if ( self)
+ BOOL pipette_active = mPipetteBtn->getToggleState();
+ pipette_active = !pipette_active;
+ if (pipette_active)
{
- BOOL pipette_active = self->mPipetteBtn->getToggleState();
- pipette_active = !pipette_active;
- if (pipette_active)
- {
- LLToolPipette::getInstance()->setSelectCallback(onColorSelect, self);
- LLToolMgr::getInstance()->setTransientTool(LLToolPipette::getInstance());
- }
- else
- {
- LLToolMgr::getInstance()->clearTransientTool();
- }
+ LLToolMgr::getInstance()->setTransientTool(LLToolPipette::getInstance());
+ }
+ else
+ {
+ LLToolMgr::getInstance()->clearTransientTool();
}
}
//////////////////////////////////////////////////////////////////////////////
// called when 'text is committed' - i,e. focus moves from a text field
-void
-LLFloaterColorPicker::
-onTextCommit ( LLUICtrl* ctrl, void* data )
+void LLFloaterColorPicker::onTextCommit ( LLUICtrl* ctrl, void* data )
{
if ( data )
{
@@ -515,16 +464,12 @@ void LLFloaterColorPicker::onImmediateCheck( LLUICtrl* ctrl, void* data)
}
}
-void LLFloaterColorPicker::onColorSelect( const LLTextureEntry& te, void *data )
+void LLFloaterColorPicker::onColorSelect( const LLTextureEntry& te )
{
- LLFloaterColorPicker* self = (LLFloaterColorPicker*)data;
- if (self)
+ setCurRgb(te.getColor().mV[VRED], te.getColor().mV[VGREEN], te.getColor().mV[VBLUE]);
+ if (mApplyImmediateCheck->get())
{
- self->setCurRgb(te.getColor().mV[VRED], te.getColor().mV[VGREEN], te.getColor().mV[VBLUE]);
- if (self->mApplyImmediateCheck->get())
- {
- LLColorSwatchCtrl::onColorChanged ( self->getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
- }
+ LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
}
}
@@ -616,7 +561,7 @@ void LLFloaterColorPicker::draw()
// create rgb area outline
gl_rect_2d ( mRGBViewerImageLeft,
mRGBViewerImageTop - mRGBViewerImageHeight,
- mRGBViewerImageLeft + mRGBViewerImageWidth,
+ mRGBViewerImageLeft + mRGBViewerImageWidth + 1,
mRGBViewerImageTop,
LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ),
FALSE );
@@ -646,7 +591,7 @@ void LLFloaterColorPicker::draw()
// draw luminance slider outline
gl_rect_2d ( mLumRegionLeft,
mLumRegionTop - mLumRegionHeight,
- mLumRegionLeft + mLumRegionWidth,
+ mLumRegionLeft + mLumRegionWidth + 1,
mLumRegionTop,
LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ),
FALSE );
@@ -662,7 +607,7 @@ void LLFloaterColorPicker::draw()
// draw selected color swatch outline
gl_rect_2d ( mSwatchRegionLeft,
mSwatchRegionTop - mSwatchRegionHeight,
- mSwatchRegionLeft + mSwatchRegionWidth,
+ mSwatchRegionLeft + mSwatchRegionWidth + 1,
mSwatchRegionTop,
LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ),
FALSE );
@@ -673,9 +618,7 @@ void LLFloaterColorPicker::draw()
//////////////////////////////////////////////////////////////////////////////
// find a complimentary color to the one passed in that can be used to highlight
-const LLColor4&
-LLFloaterColorPicker::
-getComplimentaryColor ( const LLColor4& backgroundColor )
+const LLColor4& LLFloaterColorPicker::getComplimentaryColor ( const LLColor4& backgroundColor )
{
// going to base calculation on luminance
F32 hVal, sVal, lVal;
@@ -695,9 +638,7 @@ getComplimentaryColor ( const LLColor4& backgroundColor )
//////////////////////////////////////////////////////////////////////////////
// draw color palette
-void
-LLFloaterColorPicker::
-drawPalette ()
+void LLFloaterColorPicker::drawPalette ()
{
S32 curEntry = 0;
@@ -748,9 +689,7 @@ drawPalette ()
//////////////////////////////////////////////////////////////////////////////
// update text entry values for RGB/HSL (can't be done in ::draw () since this overwrites input
-void
-LLFloaterColorPicker::
-updateTextEntry ()
+void LLFloaterColorPicker::updateTextEntry ()
{
// set values in spinners
childSetValue("rspin", ( getCurR () * 255.0f ) );
@@ -762,37 +701,8 @@ updateTextEntry ()
}
//////////////////////////////////////////////////////////////////////////////
-// turns on or off text entry commit call backs
-void
-LLFloaterColorPicker::
-enableTextCallbacks ( BOOL stateIn )
-{
- if ( stateIn )
- {
- childSetCommitCallback("rspin", onTextCommit, (void*)this );
- childSetCommitCallback("gspin", onTextCommit, (void*)this );
- childSetCommitCallback("bspin", onTextCommit, (void*)this );
- childSetCommitCallback("hspin", onTextCommit, (void*)this );
- childSetCommitCallback("sspin", onTextCommit, (void*)this );
- childSetCommitCallback("lspin", onTextCommit, (void*)this );
- }
- else
- {
- childSetCommitCallback("rspin", 0, (void*)this );
- childSetCommitCallback("gspin", 0, (void*)this );
- childSetCommitCallback("bspin", 0, (void*)this );
- childSetCommitCallback("hspin", 0, (void*)this );
- childSetCommitCallback("sspin", 0, (void*)this );
- childSetCommitCallback("lspin", 0, (void*)this );
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////////
//
-void
-LLFloaterColorPicker::
-onTextEntryChanged ( LLUICtrl* ctrl )
+void LLFloaterColorPicker::onTextEntryChanged ( LLUICtrl* ctrl )
{
// value in RGB boxes changed
std::string name = ctrl->getName();
@@ -821,10 +731,7 @@ onTextEntryChanged ( LLUICtrl* ctrl )
// update current RGB (and implicitly HSL)
setCurRgb ( rVal, gVal, bVal );
- // HACK: turn off the call back wilst we update the text or we recurse ourselves into oblivion
- enableTextCallbacks ( FALSE );
updateTextEntry ();
- enableTextCallbacks ( TRUE );
}
else
// value in HSL boxes changed
@@ -847,10 +754,7 @@ onTextEntryChanged ( LLUICtrl* ctrl )
// update current HSL (and implicitly RGB)
setCurHsl ( hVal, sVal, lVal );
- // HACK: turn off the call back wilst we update the text or we recurse ourselves into oblivion
- enableTextCallbacks ( FALSE );
updateTextEntry ();
- enableTextCallbacks ( TRUE );
}
if (mApplyImmediateCheck->get())
@@ -861,9 +765,7 @@ onTextEntryChanged ( LLUICtrl* ctrl )
//////////////////////////////////////////////////////////////////////////////
//
-BOOL
-LLFloaterColorPicker::
-updateRgbHslFromPoint ( S32 xPosIn, S32 yPosIn )
+BOOL LLFloaterColorPicker::updateRgbHslFromPoint ( S32 xPosIn, S32 yPosIn )
{
if ( xPosIn >= mRGBViewerImageLeft &&
xPosIn <= mRGBViewerImageLeft + mRGBViewerImageWidth &&
@@ -899,9 +801,7 @@ updateRgbHslFromPoint ( S32 xPosIn, S32 yPosIn )
//////////////////////////////////////////////////////////////////////////////
//
-BOOL
-LLFloaterColorPicker::
-handleMouseDown ( S32 x, S32 y, MASK mask )
+BOOL LLFloaterColorPicker::handleMouseDown ( S32 x, S32 y, MASK mask )
{
// make it the frontmost
gFloaterView->bringToFront(this);
@@ -987,10 +887,7 @@ handleMouseDown ( S32 x, S32 y, MASK mask )
LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
}
- // HACK: turn off the call back wilst we update the text or we recurse ourselves into oblivion
- enableTextCallbacks ( FALSE );
updateTextEntry ();
- enableTextCallbacks ( TRUE );
}
return TRUE;
@@ -1003,9 +900,7 @@ handleMouseDown ( S32 x, S32 y, MASK mask )
//////////////////////////////////////////////////////////////////////////////
//
-BOOL
-LLFloaterColorPicker::
-handleHover ( S32 x, S32 y, MASK mask )
+BOOL LLFloaterColorPicker::handleHover ( S32 x, S32 y, MASK mask )
{
// if we're the front most window
if ( isFrontmost () )
@@ -1071,19 +966,9 @@ handleHover ( S32 x, S32 y, MASK mask )
return LLFloater::handleHover ( x, y, mask );
}
-void LLFloaterColorPicker::onClose(bool app_quitting)
-{
- //RN: this is consistent with texture picker in that closing the window leaves the current selection
- // to change this to "close to cancel", uncomment the following line
- //cancelSelection();
- LLFloater::onClose(app_quitting);
-}
-
//////////////////////////////////////////////////////////////////////////////
// reverts state once mouse button is released
-BOOL
-LLFloaterColorPicker::
-handleMouseUp ( S32 x, S32 y, MASK mask )
+BOOL LLFloaterColorPicker::handleMouseUp ( S32 x, S32 y, MASK mask )
{
getWindow()->setCursor ( UI_CURSOR_ARROW );
@@ -1130,7 +1015,7 @@ handleMouseUp ( S32 x, S32 y, MASK mask )
std::ostringstream codec;
codec << "ColorPaletteEntry" << std::setfill ( '0' ) << std::setw ( 2 ) << curEntry + 1;
const std::string s ( codec.str () );
- gSavedSettings.setColor4( s, *mPalette [ curEntry ] );
+ LLUIColorTable::instance().setColor(s, *mPalette [ curEntry ] );
}
}
@@ -1158,16 +1043,11 @@ handleMouseUp ( S32 x, S32 y, MASK mask )
//////////////////////////////////////////////////////////////////////////////
// cancel current color selection, revert to original and close picker
-void
-LLFloaterColorPicker::
-cancelSelection ()
+void LLFloaterColorPicker::cancelSelection ()
{
// restore the previous color selection
setCurRgb ( getOrigR (), getOrigG (), getOrigB () );
- // we're going away and when we do and the entry widgets lose focus, they do bad things so turn them off
- enableTextCallbacks ( FALSE );
-
// update in world item with original color via current swatch
LLColorSwatchCtrl::onColorChanged( getSwatch(), LLColorSwatchCtrl::COLOR_CANCEL );
diff --git a/indra/newview/llfloatercolorpicker.h b/indra/newview/llfloatercolorpicker.h
index 7c8d36a7c7..0bbbe2051c 100644
--- a/indra/newview/llfloatercolorpicker.h
+++ b/indra/newview/llfloatercolorpicker.h
@@ -36,7 +36,7 @@
#include <vector>
#include "llfloater.h"
-#include "llmemory.h"
+#include "llpointer.h"
#include "llcolorswatch.h"
#include "llspinctrl.h"
#include "lltextureentry.h"
@@ -61,7 +61,6 @@ class LLFloaterColorPicker
virtual BOOL handleMouseUp ( S32 x, S32 y, MASK mask );
virtual BOOL handleHover ( S32 x, S32 y, MASK mask );
virtual void onMouseCaptureLost();
- virtual void onClose(bool app_quitting);
// implicit methods
void createUI ();
@@ -70,6 +69,7 @@ class LLFloaterColorPicker
void destroyUI ();
void cancelSelection ();
LLColorSwatchCtrl* getSwatch () { return mSwatch; };
+ void setSwatch( LLColorSwatchCtrl* swatch) { mSwatch = swatch; }
// mutator / accessor for original RGB value
void setOrigRgb ( F32 origRIn, F32 origGIn, F32 origBIn );
@@ -123,14 +123,11 @@ class LLFloaterColorPicker
// callbacks
static void onClickCancel ( void* data );
static void onClickSelect ( void* data );
- static void onClickPipette ( void* data );
+ void onClickPipette ( );
static void onTextCommit ( LLUICtrl* ctrl, void* data );
static void onImmediateCheck ( LLUICtrl* ctrl, void* data );
- static void onColorSelect( const LLTextureEntry& te, void *data );
+ void onColorSelect( const LLTextureEntry& te );
private:
- // turns on or off text entry commit call backs
- void enableTextCallbacks ( BOOL stateIn );
-
// draws color selection palette
void drawPalette ();
@@ -179,7 +176,7 @@ class LLFloaterColorPicker
const S32 mPaletteRegionHeight;
// image used to compose color grid
- LLPointer<LLImageGL> mRGBImage;
+ LLPointer<LLViewerTexture> mRGBImage;
// current swatch in use
LLColorSwatchCtrl* mSwatch;
diff --git a/indra/newview/llfloaterdaycycle.cpp b/indra/newview/llfloaterdaycycle.cpp
index 58876a8dec..48d552022f 100644
--- a/indra/newview/llfloaterdaycycle.cpp
+++ b/indra/newview/llfloaterdaycycle.cpp
@@ -59,19 +59,23 @@
#include "llfloaterwindlight.h"
-LLFloaterDayCycle* LLFloaterDayCycle::sDayCycle = NULL;
std::map<std::string, LLWLSkyKey> LLFloaterDayCycle::sSliderToKey;
const F32 LLFloaterDayCycle::sHoursPerDay = 24.0f;
-LLFloaterDayCycle::LLFloaterDayCycle() : LLFloater(std::string("Day Cycle Floater"))
+LLFloaterDayCycle::LLFloaterDayCycle(const LLSD& key)
+: LLFloater(key)
+{
+ //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_day_cycle_options.xml");
+}
+
+BOOL LLFloaterDayCycle::postBuild()
{
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_day_cycle_options.xml");
-
// add the combo boxes
LLComboBox* keyCombo = getChild<LLComboBox>("WLKeyPresets");
if(keyCombo != NULL)
{
+ keyCombo->removeall();
std::map<std::string, LLWLParamSet>::iterator mIt =
LLWLParamManager::instance()->mParamList.begin();
for(; mIt != LLWLParamManager::instance()->mParamList.end(); mIt++)
@@ -90,48 +94,38 @@ LLFloaterDayCycle::LLFloaterDayCycle() : LLFloater(std::string("Day Cycle Floate
// load it up
initCallbacks();
-}
-LLFloaterDayCycle::~LLFloaterDayCycle()
-{
-}
-
-void LLFloaterDayCycle::onClickHelp(void* data)
-{
- LLFloaterDayCycle* self = LLFloaterDayCycle::instance();
-
- std::string xml_alert = *(std::string *) data;
- LLNotifications::instance().add(self->contextualNotification(xml_alert));
+ syncMenu();
+ syncSliderTrack();
+
+ return TRUE;
}
-void LLFloaterDayCycle::initHelpBtn(const std::string& name, const std::string& xml_alert)
+LLFloaterDayCycle::~LLFloaterDayCycle()
{
- childSetAction(name, onClickHelp, new std::string(xml_alert));
}
void LLFloaterDayCycle::initCallbacks(void)
{
- initHelpBtn("WLDayCycleHelp", "HelpDayCycle");
-
// WL Day Cycle
- childSetCommitCallback("WLTimeSlider", onTimeSliderMoved, NULL);
- childSetCommitCallback("WLDayCycleKeys", onKeyTimeMoved, NULL);
- childSetCommitCallback("WLCurKeyHour", onKeyTimeChanged, NULL);
- childSetCommitCallback("WLCurKeyMin", onKeyTimeChanged, NULL);
- childSetCommitCallback("WLKeyPresets", onKeyPresetChanged, NULL);
-
- childSetCommitCallback("WLLengthOfDayHour", onTimeRateChanged, NULL);
- childSetCommitCallback("WLLengthOfDayMin", onTimeRateChanged, NULL);
- childSetCommitCallback("WLLengthOfDaySec", onTimeRateChanged, NULL);
- childSetAction("WLUseLindenTime", onUseLindenTime, NULL);
- childSetAction("WLAnimSky", onRunAnimSky, NULL);
- childSetAction("WLStopAnimSky", onStopAnimSky, NULL);
-
- childSetAction("WLLoadDayCycle", onLoadDayCycle, NULL);
- childSetAction("WLSaveDayCycle", onSaveDayCycle, NULL);
-
- childSetAction("WLAddKey", onAddKey, NULL);
- childSetAction("WLDeleteKey", onDeleteKey, NULL);
+ getChild<LLUICtrl>("WLTimeSlider")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onTimeSliderMoved, this, _1));
+ getChild<LLUICtrl>("WLDayCycleKeys")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onKeyTimeMoved, this, _1));
+ getChild<LLUICtrl>("WLCurKeyHour")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onKeyTimeChanged, this, _1));
+ getChild<LLUICtrl>("WLCurKeyMin")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onKeyTimeChanged, this, _1));
+ getChild<LLUICtrl>("WLKeyPresets")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onKeyPresetChanged, this, _1));
+
+ getChild<LLUICtrl>("WLLengthOfDayHour")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onTimeRateChanged, this, _1));
+ getChild<LLUICtrl>("WLLengthOfDayMin")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onTimeRateChanged, this, _1));
+ getChild<LLUICtrl>("WLLengthOfDaySec")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onTimeRateChanged, this, _1));
+ getChild<LLUICtrl>("WLUseLindenTime")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onUseLindenTime, this, _1));
+ getChild<LLUICtrl>("WLAnimSky")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onRunAnimSky, this, _1));
+ getChild<LLUICtrl>("WLStopAnimSky")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onStopAnimSky, this, _1));
+
+ getChild<LLUICtrl>("WLLoadDayCycle")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onLoadDayCycle, this, _1));
+ getChild<LLUICtrl>("WLSaveDayCycle")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onSaveDayCycle, this, _1));
+
+ getChild<LLUICtrl>("WLAddKey")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onAddKey, this, _1));
+ getChild<LLUICtrl>("WLDeleteKey")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onDeleteKey, this, _1));
}
void LLFloaterDayCycle::syncMenu()
@@ -139,12 +133,12 @@ void LLFloaterDayCycle::syncMenu()
// std::map<std::string, LLVector4> & currentParams = LLWLParamManager::instance()->mCurParams.mParamValues;
// set time
- LLMultiSliderCtrl* sldr = LLFloaterDayCycle::sDayCycle->getChild<LLMultiSliderCtrl>("WLTimeSlider");
+ LLMultiSliderCtrl* sldr = getChild<LLMultiSliderCtrl>("WLTimeSlider");
sldr->setCurSliderValue((F32)LLWLParamManager::instance()->mAnimator.getDayTime() * sHoursPerDay);
- LLSpinCtrl* secSpin = sDayCycle->getChild<LLSpinCtrl>("WLLengthOfDaySec");
- LLSpinCtrl* minSpin = sDayCycle->getChild<LLSpinCtrl>("WLLengthOfDayMin");
- LLSpinCtrl* hourSpin = sDayCycle->getChild<LLSpinCtrl>("WLLengthOfDayHour");
+ LLSpinCtrl* secSpin = getChild<LLSpinCtrl>("WLLengthOfDaySec");
+ LLSpinCtrl* minSpin = getChild<LLSpinCtrl>("WLLengthOfDayMin");
+ LLSpinCtrl* hourSpin = getChild<LLSpinCtrl>("WLLengthOfDayHour");
F32 curRate;
F32 hours, min, sec;
@@ -164,18 +158,18 @@ void LLFloaterDayCycle::syncMenu()
// turn off Use Estate Time button if it's already being used
if( LLWLParamManager::instance()->mAnimator.mUseLindenTime == true)
{
- LLFloaterDayCycle::sDayCycle->childDisable("WLUseLindenTime");
+ childDisable("WLUseLindenTime");
}
else
{
- LLFloaterDayCycle::sDayCycle->childEnable("WLUseLindenTime");
+ childEnable("WLUseLindenTime");
}
}
void LLFloaterDayCycle::syncSliderTrack()
{
// clear the slider
- LLMultiSliderCtrl* kSldr = sDayCycle->getChild<LLMultiSliderCtrl>("WLDayCycleKeys");
+ LLMultiSliderCtrl* kSldr = getChild<LLMultiSliderCtrl>("WLDayCycleKeys");
kSldr->clear();
sSliderToKey.clear();
@@ -198,12 +192,12 @@ void LLFloaterDayCycle::syncTrack()
}
LLMultiSliderCtrl* sldr;
- sldr = sDayCycle->getChild<LLMultiSliderCtrl>(
+ sldr = getChild<LLMultiSliderCtrl>(
"WLDayCycleKeys");
llassert_always(sSliderToKey.size() == sldr->getValue().size());
LLMultiSliderCtrl* tSldr;
- tSldr = sDayCycle->getChild<LLMultiSliderCtrl>(
+ tSldr = getChild<LLMultiSliderCtrl>(
"WLTimeSlider");
// create a new animation track
@@ -225,50 +219,7 @@ void LLFloaterDayCycle::syncTrack()
LLWLParamManager::instance()->mCurParams);
}
-// static
-LLFloaterDayCycle* LLFloaterDayCycle::instance()
-{
- if (!sDayCycle)
- {
- sDayCycle = new LLFloaterDayCycle();
- sDayCycle->open();
- sDayCycle->setFocus(TRUE);
- }
- return sDayCycle;
-}
-
-bool LLFloaterDayCycle::isOpen()
-{
- if (sDayCycle != NULL)
- {
- return true;
- }
- return false;
-}
-
-void LLFloaterDayCycle::show()
-{
- LLFloaterDayCycle* dayCycle = instance();
- dayCycle->syncMenu();
- syncSliderTrack();
-
- // comment in if you want the menu to rebuild each time
- //LLUICtrlFactory::getInstance()->buildFloater(dayCycle, "floater_day_cycle_options.xml");
- //dayCycle->initCallbacks();
-
- dayCycle->open();
-}
-
-// virtual
-void LLFloaterDayCycle::onClose(bool app_quitting)
-{
- if (sDayCycle)
- {
- sDayCycle->setVisible(FALSE);
- }
-}
-
-void LLFloaterDayCycle::onRunAnimSky(void* userData)
+void LLFloaterDayCycle::onRunAnimSky(LLUICtrl* ctrl)
{
// if no keys, do nothing
if(sSliderToKey.size() == 0)
@@ -277,11 +228,11 @@ void LLFloaterDayCycle::onRunAnimSky(void* userData)
}
LLMultiSliderCtrl* sldr;
- sldr = sDayCycle->getChild<LLMultiSliderCtrl>("WLDayCycleKeys");
+ sldr = getChild<LLMultiSliderCtrl>("WLDayCycleKeys");
llassert_always(sSliderToKey.size() == sldr->getValue().size());
LLMultiSliderCtrl* tSldr;
- tSldr = sDayCycle->getChild<LLMultiSliderCtrl>("WLTimeSlider");
+ tSldr = getChild<LLMultiSliderCtrl>("WLTimeSlider");
// turn off linden time
LLWLParamManager::instance()->mAnimator.mUseLindenTime = false;
@@ -293,7 +244,7 @@ void LLFloaterDayCycle::onRunAnimSky(void* userData)
llassert_always(LLWLParamManager::instance()->mAnimator.mTimeTrack.size() == sldr->getValue().size());
}
-void LLFloaterDayCycle::onStopAnimSky(void* userData)
+void LLFloaterDayCycle::onStopAnimSky(LLUICtrl* ctrl)
{
// if no keys, do nothing
if(sSliderToKey.size() == 0) {
@@ -305,17 +256,16 @@ void LLFloaterDayCycle::onStopAnimSky(void* userData)
LLWLParamManager::instance()->mAnimator.mUseLindenTime = false;
}
-void LLFloaterDayCycle::onUseLindenTime(void* userData)
+void LLFloaterDayCycle::onUseLindenTime(LLUICtrl* ctrl)
{
- LLFloaterWindLight* wl = LLFloaterWindLight::instance();
- LLComboBox* box = wl->getChild<LLComboBox>("WLPresetsCombo");
+ LLComboBox* box = getChild<LLComboBox>("WLPresetsCombo");
box->selectByValue("");
LLWLParamManager::instance()->mAnimator.mIsRunning = true;
LLWLParamManager::instance()->mAnimator.mUseLindenTime = true;
}
-void LLFloaterDayCycle::onLoadDayCycle(void* userData)
+void LLFloaterDayCycle::onLoadDayCycle(LLUICtrl* ctrl)
{
LLWLParamManager::instance()->mDay.loadDayCycle("Default.xml");
@@ -325,7 +275,7 @@ void LLFloaterDayCycle::onLoadDayCycle(void* userData)
// set the param manager's track to the new one
LLMultiSliderCtrl* tSldr;
- tSldr = sDayCycle->getChild<LLMultiSliderCtrl>(
+ tSldr = getChild<LLMultiSliderCtrl>(
"WLTimeSlider");
LLWLParamManager::instance()->resetAnimator(
tSldr->getCurSliderValue() / sHoursPerDay, false);
@@ -335,15 +285,15 @@ void LLFloaterDayCycle::onLoadDayCycle(void* userData)
LLWLParamManager::instance()->mCurParams);
}
-void LLFloaterDayCycle::onSaveDayCycle(void* userData)
+void LLFloaterDayCycle::onSaveDayCycle(LLUICtrl* ctrl)
{
LLWLParamManager::instance()->mDay.saveDayCycle("Default.xml");
}
-void LLFloaterDayCycle::onTimeSliderMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterDayCycle::onTimeSliderMoved(LLUICtrl* ctrl)
{
- LLMultiSliderCtrl* sldr = sDayCycle->getChild<LLMultiSliderCtrl>(
+ LLMultiSliderCtrl* sldr = getChild<LLMultiSliderCtrl>(
"WLTimeSlider");
/// get the slider value
@@ -359,12 +309,12 @@ void LLFloaterDayCycle::onTimeSliderMoved(LLUICtrl* ctrl, void* userData)
LLWLParamManager::instance()->mCurParams);
}
-void LLFloaterDayCycle::onKeyTimeMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterDayCycle::onKeyTimeMoved(LLUICtrl* ctrl)
{
- LLComboBox* comboBox = sDayCycle->getChild<LLComboBox>("WLKeyPresets");
- LLMultiSliderCtrl* sldr = sDayCycle->getChild<LLMultiSliderCtrl>("WLDayCycleKeys");
- LLSpinCtrl* hourSpin = sDayCycle->getChild<LLSpinCtrl>("WLCurKeyHour");
- LLSpinCtrl* minSpin = sDayCycle->getChild<LLSpinCtrl>("WLCurKeyMin");
+ LLComboBox* comboBox = getChild<LLComboBox>("WLKeyPresets");
+ LLMultiSliderCtrl* sldr = getChild<LLMultiSliderCtrl>("WLDayCycleKeys");
+ LLSpinCtrl* hourSpin = getChild<LLSpinCtrl>("WLCurKeyHour");
+ LLSpinCtrl* minSpin = getChild<LLSpinCtrl>("WLCurKeyMin");
if(sldr->getValue().size() == 0) {
return;
@@ -402,18 +352,18 @@ void LLFloaterDayCycle::onKeyTimeMoved(LLUICtrl* ctrl, void* userData)
}
-void LLFloaterDayCycle::onKeyTimeChanged(LLUICtrl* ctrl, void* userData)
+void LLFloaterDayCycle::onKeyTimeChanged(LLUICtrl* ctrl)
{
// if no keys, skipped
if(sSliderToKey.size() == 0) {
return;
}
- LLMultiSliderCtrl* sldr = sDayCycle->getChild<LLMultiSliderCtrl>(
+ LLMultiSliderCtrl* sldr = getChild<LLMultiSliderCtrl>(
"WLDayCycleKeys");
- LLSpinCtrl* hourSpin = sDayCycle->getChild<LLSpinCtrl>(
+ LLSpinCtrl* hourSpin = getChild<LLSpinCtrl>(
"WLCurKeyHour");
- LLSpinCtrl* minSpin = sDayCycle->getChild<LLSpinCtrl>(
+ LLSpinCtrl* minSpin = getChild<LLSpinCtrl>(
"WLCurKeyMin");
F32 hour = hourSpin->get();
@@ -431,12 +381,12 @@ void LLFloaterDayCycle::onKeyTimeChanged(LLUICtrl* ctrl, void* userData)
syncTrack();
}
-void LLFloaterDayCycle::onKeyPresetChanged(LLUICtrl* ctrl, void* userData)
+void LLFloaterDayCycle::onKeyPresetChanged(LLUICtrl* ctrl)
{
// get the time
- LLComboBox* comboBox = sDayCycle->getChild<LLComboBox>(
+ LLComboBox* comboBox = getChild<LLComboBox>(
"WLKeyPresets");
- LLMultiSliderCtrl* sldr = sDayCycle->getChild<LLMultiSliderCtrl>(
+ LLMultiSliderCtrl* sldr = getChild<LLMultiSliderCtrl>(
"WLDayCycleKeys");
// do nothing if no sliders
@@ -458,16 +408,16 @@ void LLFloaterDayCycle::onKeyPresetChanged(LLUICtrl* ctrl, void* userData)
syncTrack();
}
-void LLFloaterDayCycle::onTimeRateChanged(LLUICtrl* ctrl, void* userData)
+void LLFloaterDayCycle::onTimeRateChanged(LLUICtrl* ctrl)
{
// get the time
- LLSpinCtrl* secSpin = sDayCycle->getChild<LLSpinCtrl>(
+ LLSpinCtrl* secSpin = getChild<LLSpinCtrl>(
"WLLengthOfDaySec");
- LLSpinCtrl* minSpin = sDayCycle->getChild<LLSpinCtrl>(
+ LLSpinCtrl* minSpin = getChild<LLSpinCtrl>(
"WLLengthOfDayMin");
- LLSpinCtrl* hourSpin = sDayCycle->getChild<LLSpinCtrl>(
+ LLSpinCtrl* hourSpin = getChild<LLSpinCtrl>(
"WLLengthOfDayHour");
F32 hour;
@@ -486,13 +436,13 @@ void LLFloaterDayCycle::onTimeRateChanged(LLUICtrl* ctrl, void* userData)
syncTrack();
}
-void LLFloaterDayCycle::onAddKey(void* userData)
+void LLFloaterDayCycle::onAddKey(LLUICtrl* ctrl)
{
- LLComboBox* comboBox = sDayCycle->getChild<LLComboBox>(
+ LLComboBox* comboBox = getChild<LLComboBox>(
"WLKeyPresets");
- LLMultiSliderCtrl* kSldr = sDayCycle->getChild<LLMultiSliderCtrl>(
+ LLMultiSliderCtrl* kSldr = getChild<LLMultiSliderCtrl>(
"WLDayCycleKeys");
- LLMultiSliderCtrl* tSldr = sDayCycle->getChild<LLMultiSliderCtrl>(
+ LLMultiSliderCtrl* tSldr = getChild<LLMultiSliderCtrl>(
"WLTimeSlider");
llassert_always(sSliderToKey.size() == kSldr->getValue().size());
@@ -508,7 +458,7 @@ void LLFloaterDayCycle::onAddKey(void* userData)
void LLFloaterDayCycle::addSliderKey(F32 time, const std::string & presetName)
{
- LLMultiSliderCtrl* kSldr = sDayCycle->getChild<LLMultiSliderCtrl>(
+ LLMultiSliderCtrl* kSldr = getChild<LLMultiSliderCtrl>(
"WLDayCycleKeys");
// make a slider
@@ -533,7 +483,7 @@ void LLFloaterDayCycle::addSliderKey(F32 time, const std::string & presetName)
void LLFloaterDayCycle::deletePreset(std::string& presetName)
{
- LLMultiSliderCtrl* sldr = sDayCycle->getChild<LLMultiSliderCtrl>("WLDayCycleKeys");
+ LLMultiSliderCtrl* sldr = getChild<LLMultiSliderCtrl>("WLDayCycleKeys");
/// delete any reference
std::map<std::string, LLWLSkyKey>::iterator curr_preset, next_preset;
@@ -549,15 +499,15 @@ void LLFloaterDayCycle::deletePreset(std::string& presetName)
}
}
-void LLFloaterDayCycle::onDeleteKey(void* userData)
+void LLFloaterDayCycle::onDeleteKey(LLUICtrl* ctrl)
{
if(sSliderToKey.size() == 0) {
return;
}
- LLComboBox* comboBox = sDayCycle->getChild<LLComboBox>(
+ LLComboBox* comboBox = getChild<LLComboBox>(
"WLKeyPresets");
- LLMultiSliderCtrl* sldr = sDayCycle->getChild<LLMultiSliderCtrl>("WLDayCycleKeys");
+ LLMultiSliderCtrl* sldr = getChild<LLMultiSliderCtrl>("WLDayCycleKeys");
// delete from map
const std::string& sldrName = sldr->getCurSlider();
@@ -574,8 +524,8 @@ void LLFloaterDayCycle::onDeleteKey(void* userData)
comboBox->selectByValue(sSliderToKey[name].presetName);
F32 time = sSliderToKey[name].time;
- LLSpinCtrl* hourSpin = sDayCycle->getChild<LLSpinCtrl>("WLCurKeyHour");
- LLSpinCtrl* minSpin = sDayCycle->getChild<LLSpinCtrl>("WLCurKeyMin");
+ LLSpinCtrl* hourSpin = getChild<LLSpinCtrl>("WLCurKeyHour");
+ LLSpinCtrl* minSpin = getChild<LLSpinCtrl>("WLCurKeyMin");
// now set the spinners
F32 hour = (F32)((S32)time);
diff --git a/indra/newview/llfloaterdaycycle.h b/indra/newview/llfloaterdaycycle.h
index d230035545..c250902b65 100644
--- a/indra/newview/llfloaterdaycycle.h
+++ b/indra/newview/llfloaterdaycycle.h
@@ -56,87 +56,66 @@ class LLFloaterDayCycle : public LLFloater
{
public:
- LLFloaterDayCycle();
+ LLFloaterDayCycle(const LLSD& key);
virtual ~LLFloaterDayCycle();
-
- /// help button stuff
- static void onClickHelp(void* data);
- void initHelpBtn(const std::string& name, const std::string& xml_alert);
+ /*virtual*/ BOOL postBuild();
/// initialize all
void initCallbacks(void);
- /// one and one instance only
- static LLFloaterDayCycle* instance();
-
/// on time slider moved
- static void onTimeSliderMoved(LLUICtrl* ctrl, void* userData);
+ void onTimeSliderMoved(LLUICtrl* ctrl);
/// what happens when you move the key frame
- static void onKeyTimeMoved(LLUICtrl* ctrl, void* userData);
+ void onKeyTimeMoved(LLUICtrl* ctrl);
/// what happens when you change the key frame's time
- static void onKeyTimeChanged(LLUICtrl* ctrl, void* userData);
+ void onKeyTimeChanged(LLUICtrl* ctrl);
/// if you change the combo box, change the frame
- static void onKeyPresetChanged(LLUICtrl* ctrl, void* userData);
+ void onKeyPresetChanged(LLUICtrl* ctrl);
/// run this when user says to run the sky animation
- static void onRunAnimSky(void* userData);
+ void onRunAnimSky(LLUICtrl* ctrl);
/// run this when user says to stop the sky animation
- static void onStopAnimSky(void* userData);
+ void onStopAnimSky(LLUICtrl* ctrl);
/// if you change the combo box, change the frame
- static void onTimeRateChanged(LLUICtrl* ctrl, void* userData);
+ void onTimeRateChanged(LLUICtrl* ctrl);
/// add a new key on slider
- static void onAddKey(void* userData);
+ void onAddKey(LLUICtrl* ctrl);
/// delete any and all reference to a preset
void deletePreset(std::string& presetName);
/// delete a key frame
- static void onDeleteKey(void* userData);
+ void onDeleteKey(LLUICtrl* ctrl);
/// button to load day
- static void onLoadDayCycle(void* userData);
+ void onLoadDayCycle(LLUICtrl* ctrl);
/// button to save day
- static void onSaveDayCycle(void* userData);
+ void onSaveDayCycle(LLUICtrl* ctrl);
/// toggle for Linden time
- static void onUseLindenTime(void* userData);
-
-
- //// menu management
-
- /// show off our menu
- static void show();
-
- /// return if the menu exists or not
- static bool isOpen();
-
- /// stuff to do on exit
- virtual void onClose(bool app_quitting);
+ void onUseLindenTime(LLUICtrl* ctrl);
/// sync up sliders with day cycle structure
- static void syncMenu();
+ void syncMenu();
// makes sure key slider has what's in day cycle
- static void syncSliderTrack();
+ void syncSliderTrack();
/// makes sure day cycle data structure has what's in menu
- static void syncTrack();
+ void syncTrack();
/// add a slider to the track
- static void addSliderKey(F32 time, const std::string& presetName);
+ void addSliderKey(F32 time, const std::string& presetName);
private:
- // one instance on the inside
- static LLFloaterDayCycle* sDayCycle;
-
// map of sliders to parameters
static std::map<std::string, LLWLSkyKey> sSliderToKey;
diff --git a/indra/newview/llfloaterenvsettings.cpp b/indra/newview/llfloaterenvsettings.cpp
index 661c3988c0..2fffa6eece 100644
--- a/indra/newview/llfloaterenvsettings.cpp
+++ b/indra/newview/llfloaterenvsettings.cpp
@@ -34,6 +34,7 @@
#include "llfloaterenvsettings.h"
+#include "llfloaterreg.h"
#include "llfloaterwindlight.h"
#include "llfloaterwater.h"
#include "lluictrlfactory.h"
@@ -52,59 +53,53 @@
#include <sstream>
-LLFloaterEnvSettings* LLFloaterEnvSettings::sEnvSettings = NULL;
-
-LLFloaterEnvSettings::LLFloaterEnvSettings() : LLFloater(std::string("Environment Settings Floater"))
+LLFloaterEnvSettings::LLFloaterEnvSettings(const LLSD& key)
+ : LLFloater(key)
{
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_env_settings.xml");
-
- // load it up
- initCallbacks();
+ //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_env_settings.xml");
}
-
+// virtual
LLFloaterEnvSettings::~LLFloaterEnvSettings()
{
}
-
-void LLFloaterEnvSettings::onClickHelp(void* data)
-{
- LLFloaterEnvSettings* self = (LLFloaterEnvSettings*)data;
- LLNotifications::instance().add(self->contextualNotification("EnvSettingsHelpButton"));
+// virtual
+BOOL LLFloaterEnvSettings::postBuild()
+{
+ // load it up
+ initCallbacks();
+ syncMenu();
+ return TRUE;
}
void LLFloaterEnvSettings::initCallbacks(void)
{
// our three sliders
- childSetCommitCallback("EnvTimeSlider", onChangeDayTime, NULL);
- childSetCommitCallback("EnvCloudSlider", onChangeCloudCoverage, NULL);
- childSetCommitCallback("EnvWaterFogSlider", onChangeWaterFogDensity,
- &LLWaterParamManager::instance()->mFogDensity);
+ getChild<LLUICtrl>("EnvTimeSlider")->setCommitCallback(boost::bind(&LLFloaterEnvSettings::onChangeDayTime, this, _1));
+ getChild<LLUICtrl>("EnvCloudSlider")->setCommitCallback(boost::bind(&LLFloaterEnvSettings::onChangeCloudCoverage, this, _1));
+ getChild<LLUICtrl>("EnvWaterFogSlider")->setCommitCallback(boost::bind(&LLFloaterEnvSettings::onChangeWaterFogDensity, this, _1, &LLWaterParamManager::instance()->mFogDensity));
// color picker
- childSetCommitCallback("EnvWaterColor", onChangeWaterColor,
- &LLWaterParamManager::instance()->mFogColor);
+ getChild<LLUICtrl>("EnvWaterColor")->setCommitCallback(boost::bind(&LLFloaterEnvSettings::onChangeWaterColor, this, _1, &LLWaterParamManager::instance()->mFogColor));
// WL Top
- childSetAction("EnvAdvancedSkyButton", onOpenAdvancedSky, NULL);
- childSetAction("EnvAdvancedWaterButton", onOpenAdvancedWater, NULL);
- childSetAction("EnvUseEstateTimeButton", onUseEstateTime, NULL);
- childSetAction("EnvSettingsHelpButton", onClickHelp, this);
+ getChild<LLUICtrl>("EnvAdvancedSkyButton")->setCommitCallback(boost::bind(&LLFloaterEnvSettings::onOpenAdvancedSky, this));
+ getChild<LLUICtrl>("EnvAdvancedWaterButton")->setCommitCallback(boost::bind(&LLFloaterEnvSettings::onOpenAdvancedWater, this));
+ getChild<LLUICtrl>("EnvUseEstateTimeButton")->setCommitCallback(boost::bind(&LLFloaterEnvSettings::onUseEstateTime, this));
}
-
// menu maintenance functions
void LLFloaterEnvSettings::syncMenu()
{
LLSliderCtrl* sldr;
- sldr = sEnvSettings->getChild<LLSliderCtrl>("EnvTimeSlider");
+ sldr = getChild<LLSliderCtrl>("EnvTimeSlider");
// sync the clock
F32 val = (F32)LLWLParamManager::instance()->mAnimator.getDayTime();
std::string timeStr = timeToString(val);
LLTextBox* textBox;
- textBox = sEnvSettings->getChild<LLTextBox>("EnvTimeText");
+ textBox = getChild<LLTextBox>("EnvTimeText");
textBox->setValue(timeStr);
@@ -123,7 +118,7 @@ void LLFloaterEnvSettings::syncMenu()
LLWaterParamManager * param_mgr = LLWaterParamManager::instance();
// sync water params
LLColor4 col = param_mgr->getFogColor();
- LLColorSwatchCtrl* colCtrl = sEnvSettings->getChild<LLColorSwatchCtrl>("EnvWaterColor");
+ LLColorSwatchCtrl* colCtrl = getChild<LLColorSwatchCtrl>("EnvWaterColor");
col.mV[3] = 1.0f;
colCtrl->set(col);
@@ -167,53 +162,9 @@ void LLFloaterEnvSettings::syncMenu()
}
}
-
-// static instance of it
-LLFloaterEnvSettings* LLFloaterEnvSettings::instance()
+void LLFloaterEnvSettings::onChangeDayTime(LLUICtrl* ctrl)
{
- if (!sEnvSettings)
- {
- sEnvSettings = new LLFloaterEnvSettings();
- sEnvSettings->open();
- sEnvSettings->setFocus(TRUE);
- }
- return sEnvSettings;
-}
-void LLFloaterEnvSettings::show()
-{
- LLFloaterEnvSettings* envSettings = instance();
- envSettings->syncMenu();
-
- // comment in if you want the menu to rebuild each time
- //LLUICtrlFactory::getInstance()->buildFloater(envSettings, "floater_env_settings.xml");
- //envSettings->initCallbacks();
-
- envSettings->open();
-}
-
-bool LLFloaterEnvSettings::isOpen()
-{
- if (sEnvSettings != NULL)
- {
- return true;
- }
- return false;
-}
-
-// virtual
-void LLFloaterEnvSettings::onClose(bool app_quitting)
-{
- if (sEnvSettings)
- {
- sEnvSettings->setVisible(FALSE);
- }
-}
-
-
-void LLFloaterEnvSettings::onChangeDayTime(LLUICtrl* ctrl, void* userData)
-{
- LLSliderCtrl* sldr;
- sldr = sEnvSettings->getChild<LLSliderCtrl>("EnvTimeSlider");
+ LLSliderCtrl* sldr = static_cast<LLSliderCtrl*>(ctrl);
// deactivate animator
LLWLParamManager::instance()->mAnimator.mIsRunning = false;
@@ -230,10 +181,9 @@ void LLFloaterEnvSettings::onChangeDayTime(LLUICtrl* ctrl, void* userData)
LLWLParamManager::instance()->mCurParams);
}
-void LLFloaterEnvSettings::onChangeCloudCoverage(LLUICtrl* ctrl, void* userData)
+void LLFloaterEnvSettings::onChangeCloudCoverage(LLUICtrl* ctrl)
{
- LLSliderCtrl* sldr;
- sldr = sEnvSettings->getChild<LLSliderCtrl>("EnvCloudSlider");
+ LLSliderCtrl* sldr = static_cast<LLSliderCtrl*>(ctrl);
// deactivate animator
//LLWLParamManager::instance()->mAnimator.mIsRunning = false;
@@ -243,17 +193,10 @@ void LLFloaterEnvSettings::onChangeCloudCoverage(LLUICtrl* ctrl, void* userData)
LLWLParamManager::instance()->mCurParams.set("cloud_shadow", val);
}
-void LLFloaterEnvSettings::onChangeWaterFogDensity(LLUICtrl* ctrl, void* userData)
+void LLFloaterEnvSettings::onChangeWaterFogDensity(LLUICtrl* ctrl, WaterExpFloatControl* expFloatControl)
{
LLSliderCtrl* sldr;
- sldr = sEnvSettings->getChild<LLSliderCtrl>("EnvWaterFogSlider");
-
- if(NULL == userData)
- {
- return;
- }
-
- WaterExpFloatControl * expFloatControl = static_cast<WaterExpFloatControl *>(userData);
+ sldr = getChild<LLSliderCtrl>("EnvWaterFogSlider");
F32 val = sldr->getValueF32();
expFloatControl->mExp = val;
@@ -263,10 +206,9 @@ void LLFloaterEnvSettings::onChangeWaterFogDensity(LLUICtrl* ctrl, void* userDat
LLWaterParamManager::instance()->propagateParameters();
}
-void LLFloaterEnvSettings::onChangeWaterColor(LLUICtrl* ctrl, void* userData)
+void LLFloaterEnvSettings::onChangeWaterColor(LLUICtrl* ctrl, WaterColorControl* colorControl)
{
LLColorSwatchCtrl* swatch = static_cast<LLColorSwatchCtrl*>(ctrl);
- WaterColorControl * colorControl = static_cast<WaterColorControl *>(userData);
*colorControl = swatch->get();
colorControl->update(LLWaterParamManager::instance()->mCurParams);
@@ -274,23 +216,22 @@ void LLFloaterEnvSettings::onChangeWaterColor(LLUICtrl* ctrl, void* userData)
}
-void LLFloaterEnvSettings::onOpenAdvancedSky(void* userData)
+void LLFloaterEnvSettings::onOpenAdvancedSky()
{
- LLFloaterWindLight::show();
+ LLFloaterReg::showInstance("env_windlight");
}
-void LLFloaterEnvSettings::onOpenAdvancedWater(void* userData)
+void LLFloaterEnvSettings::onOpenAdvancedWater()
{
- LLFloaterWater::show();
+ LLFloaterReg::showInstance("env_water");
}
-void LLFloaterEnvSettings::onUseEstateTime(void* userData)
+void LLFloaterEnvSettings::onUseEstateTime()
{
- if(LLFloaterWindLight::isOpen())
+ LLFloaterWindLight* wl = LLFloaterReg::findTypedInstance<LLFloaterWindLight>("env_windlight");
+ if(wl)
{
- // select the blank value in
- LLFloaterWindLight* wl = LLFloaterWindLight::instance();
LLComboBox* box = wl->getChild<LLComboBox>("WLPresetsCombo");
box->selectByValue("");
}
@@ -303,7 +244,6 @@ std::string LLFloaterEnvSettings::timeToString(F32 curTime)
{
S32 hours;
S32 min;
- bool isPM = false;
// get hours and minutes
hours = (S32) (24.0 * curTime);
@@ -317,46 +257,19 @@ std::string LLFloaterEnvSettings::timeToString(F32 curTime)
min = 0;
}
- // set for PM
- if(hours >= 12 && hours < 24)
- {
- isPM = true;
- }
+ std::string newTime = getString("timeStr");
+ struct tm * timeT;
+ time_t secT = time(0);
+ timeT = gmtime (&secT);
- // convert to non-military notation
- if(hours >= 24)
- {
- hours = 12;
- }
- else if(hours > 12)
- {
- hours -= 12;
- }
- else if(hours == 0)
- {
- hours = 12;
- }
+ timeT->tm_hour = hours;
+ timeT->tm_min = min;
+ secT = mktime (timeT);
+ secT -= LLStringOps::getLocalTimeOffset ();
- // make the string
- std::stringstream newTime;
- newTime << hours << ":";
-
- // double 0
- if(min < 10)
- {
- newTime << 0;
- }
-
- // finish it
- newTime << min << " ";
- if(isPM)
- {
- newTime << "PM";
- }
- else
- {
- newTime << "AM";
- }
+ LLSD substitution;
+ substitution["datetime"] = (S32) secT;
- return newTime.str();
+ LLStringUtil::format (newTime, substitution);
+ return newTime;
}
diff --git a/indra/newview/llfloaterenvsettings.h b/indra/newview/llfloaterenvsettings.h
index 4cdf6036c6..02bc502120 100644
--- a/indra/newview/llfloaterenvsettings.h
+++ b/indra/newview/llfloaterenvsettings.h
@@ -39,59 +39,43 @@
#include "llfloater.h"
+struct WaterColorControl;
+struct WaterExpFloatControl;
/// Menuing system for all of windlight's functionality
class LLFloaterEnvSettings : public LLFloater
{
public:
- LLFloaterEnvSettings();
- virtual ~LLFloaterEnvSettings();
-
+ LLFloaterEnvSettings(const LLSD& key);
+ /*virtual*/ ~LLFloaterEnvSettings();
+ /*virtual*/ BOOL postBuild();
/// initialize all the callbacks for the menu
void initCallbacks(void);
- /// one and one instance only
- static LLFloaterEnvSettings* instance();
-
- /// callback for the menus help button
- static void onClickHelp(void* data);
-
/// handle if time of day is changed
- static void onChangeDayTime(LLUICtrl* ctrl, void* userData);
+ void onChangeDayTime(LLUICtrl* ctrl);
/// handle if cloud coverage is changed
- static void onChangeCloudCoverage(LLUICtrl* ctrl, void* userData);
+ void onChangeCloudCoverage(LLUICtrl* ctrl);
/// handle change in water fog density
- static void onChangeWaterFogDensity(LLUICtrl* ctrl, void* userData);
-
- /// handle change in under water fog density
- static void onChangeUnderWaterFogMod(LLUICtrl* ctrl, void* userData);
+ void onChangeWaterFogDensity(LLUICtrl* ctrl, WaterExpFloatControl* expFloatControl);
/// handle change in water fog color
- static void onChangeWaterColor(LLUICtrl* ctrl, void* userData);
+ void onChangeWaterColor(LLUICtrl* ctrl, WaterColorControl* colorControl);
/// open the advanced sky settings menu
- static void onOpenAdvancedSky(void* userData);
+ void onOpenAdvancedSky();
/// open the advanced water settings menu
- static void onOpenAdvancedWater(void* userData);
+ void onOpenAdvancedWater();
/// sync time with the server
- static void onUseEstateTime(void* userData);
+ void onUseEstateTime();
//// menu management
- /// show off our menu
- static void show();
-
- /// return if the menu exists or not
- static bool isOpen();
-
- /// stuff to do on exit
- virtual void onClose(bool app_quitting);
-
/// sync up sliders with parameters
void syncMenu();
@@ -99,8 +83,6 @@ public:
std::string timeToString(F32 curTime);
private:
- // one instance on the inside
- static LLFloaterEnvSettings* sEnvSettings;
};
diff --git a/indra/newview/llfloaterevent.cpp b/indra/newview/llfloaterevent.cpp
deleted file mode 100644
index 485c13c7b6..0000000000
--- a/indra/newview/llfloaterevent.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/**
- * @file llfloaterevent.cpp
- * @brief Event information as shown in a floating window from
- * secondlife:// command handler.
- *
- * $LicenseInfo:firstyear=2007&license=viewergpl$
- *
- * Copyright (c) 2007-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llfloaterevent.h"
-
-// viewer project includes
-#include "llcommandhandler.h"
-#include "llpanelevent.h"
-
-// linden library includes
-#include "lluuid.h"
-#include "lluictrlfactory.h"
-
-////////////////////////////////////////////////////////////////////////////
-// LLFloaterEventInfo
-
-//-----------------------------------------------------------------------------
-// Globals
-//-----------------------------------------------------------------------------
-
-LLMap< U32, LLFloaterEventInfo* > gEventInfoInstances;
-
-class LLEventHandler : public LLCommandHandler
-{
-public:
- // requires trusted browser to trigger
- LLEventHandler() : LLCommandHandler("event", true) { }
- bool handle(const LLSD& tokens, const LLSD& query_map,
- LLWebBrowserCtrl* web)
- {
- if (tokens.size() < 2)
- {
- return false;
- }
- U32 event_id = tokens[0].asInteger();
- if (tokens[1].asString() == "about")
- {
- LLFloaterEventInfo::show(event_id);
- return true;
- }
- return false;
- }
-};
-LLEventHandler gEventHandler;
-
-LLFloaterEventInfo::LLFloaterEventInfo(const std::string& name, const U32 event_id)
-: LLFloater(name),
- mEventID( event_id )
-{
-
- mFactoryMap["event_details_panel"] = LLCallbackMap(LLFloaterEventInfo::createEventDetail, this);
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_preview_event.xml", &getFactoryMap());
- gEventInfoInstances.addData(event_id, this);
-}
-
-LLFloaterEventInfo::~LLFloaterEventInfo()
-{
- // child views automatically deleted
- gEventInfoInstances.removeData(mEventID);
-}
-
-void LLFloaterEventInfo::displayEventInfo(const U32 event_id)
-{
- mPanelEventp->setEventID(event_id);
- this->setFrontmost(true);
-}
-
-// static
-void* LLFloaterEventInfo::createEventDetail(void* userdata)
-{
- LLFloaterEventInfo *self = (LLFloaterEventInfo*)userdata;
- self->mPanelEventp = new LLPanelEvent();
- LLUICtrlFactory::getInstance()->buildPanel(self->mPanelEventp, "panel_event.xml");
-
- return self->mPanelEventp;
-}
-
-// static
-LLFloaterEventInfo* LLFloaterEventInfo::show(const U32 event_id)
-{
- LLFloaterEventInfo *floater;
- if (gEventInfoInstances.checkData(event_id))
- {
- // ...bring that window to front
- floater = gEventInfoInstances.getData(event_id);
- floater->open(); /*Flawfinder: ignore*/
- floater->setFrontmost(true);
- }
- else
- {
- floater = new LLFloaterEventInfo("eventinfo", event_id );
- floater->center();
- floater->open(); /*Flawfinder: ignore*/
- floater->displayEventInfo(event_id);
- floater->setFrontmost(true);
- }
-
- return floater;
-}
diff --git a/indra/newview/llfloaterfonttest.cpp b/indra/newview/llfloaterfonttest.cpp
index 4bb1d9605d..413992910e 100644
--- a/indra/newview/llfloaterfonttest.cpp
+++ b/indra/newview/llfloaterfonttest.cpp
@@ -5,7 +5,7 @@
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2008 Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -13,12 +13,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
@@ -41,25 +42,11 @@
#include "lluictrlfactory.h"
-LLFloaterFontTest* LLFloaterFontTest::sInstance = NULL;
-
-LLFloaterFontTest::LLFloaterFontTest()
- : LLFloater(std::string("floater_font_test"), LLRect(0,500,700,0), std::string("Font Test"))
+LLFloaterFontTest::LLFloaterFontTest(const LLSD& key)
+ : LLFloater("floater_font_test")
{
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_font_test.xml");
}
LLFloaterFontTest::~LLFloaterFontTest()
{
- sInstance = NULL;
-}
-
-// static
-void LLFloaterFontTest::show(void *unused)
-{
- if (!sInstance)
- sInstance = new LLFloaterFontTest();
-
- sInstance->open(); /*Flawfinder: ignore*/
- sInstance->setFocus(TRUE);
}
diff --git a/indra/newview/llfloaterfonttest.h b/indra/newview/llfloaterfonttest.h
index 45ff890423..4406a9f36a 100644
--- a/indra/newview/llfloaterfonttest.h
+++ b/indra/newview/llfloaterfonttest.h
@@ -5,7 +5,7 @@
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2008, Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -13,12 +13,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
@@ -38,14 +39,10 @@
class LLFloaterFontTest:
public LLFloater
{
-public:
- static void show(void* unused);
-
+ friend class LLFloaterReg;
private:
- LLFloaterFontTest();
+ LLFloaterFontTest(const LLSD& key);
~LLFloaterFontTest();
-
- static LLFloaterFontTest* sInstance;
};
#endif
diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp
index 014a631a53..ccc5cab85a 100644
--- a/indra/newview/llfloaterfriends.cpp
+++ b/indra/newview/llfloaterfriends.cpp
@@ -46,12 +46,14 @@
#include "llfloateravatarpicker.h"
#include "llviewerwindow.h"
#include "llbutton.h"
-#include "llfloateravatarinfo.h"
+#include "llavataractions.h"
#include "llinventorymodel.h"
#include "llnamelistctrl.h"
-#include "llnotify.h"
+#include "llnotificationsutil.h"
#include "llresmgr.h"
-#include "llimview.h"
+#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "llscrolllistcell.h"
#include "lluictrlfactory.h"
#include "llmenucommands.h"
#include "llviewercontrol.h"
@@ -60,6 +62,8 @@
#include "lltextbox.h"
#include "llvoiceclient.h"
+// *TODO: Move more common stuff to LLAvatarActions?
+
//Maximum number of people you can select to do an operation on at once.
#define MAX_FRIEND_SELECT 20
#define DEFAULT_PERIOD 5.0
@@ -148,7 +152,7 @@ void LLPanelFriends::updateFriends(U32 changed_mask)
// if the maximum amount of friends are selected
mShowMaxSelectWarning = false;
- LLDynamicArray<LLUUID> selected_friends = getSelectedIDs();
+ std::vector<LLUUID> selected_friends = getSelectedIDs();
if(changed_mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE))
{
refreshNames(changed_mask);
@@ -173,7 +177,7 @@ void LLPanelFriends::updateFriends(U32 changed_mask)
// but we don't really care here, because refreshUI() will
// clean up the interface.
friends_list->setCurrentByID(selected_id);
- for(LLDynamicArray<LLUUID>::iterator itr = selected_friends.begin(); itr != selected_friends.end(); ++itr)
+ for(std::vector<LLUUID>::iterator itr = selected_friends.begin(); itr != selected_friends.end(); ++itr)
{
friends_list->setSelectedByValue(*itr, true);
}
@@ -188,10 +192,11 @@ BOOL LLPanelFriends::postBuild()
{
mFriendsList = getChild<LLScrollListCtrl>("friend_list");
mFriendsList->setMaxSelectable(MAX_FRIEND_SELECT);
- mFriendsList->setMaximumSelectCallback(onMaximumSelect);
+ mFriendsList->setMaximumSelectCallback(boost::bind(&LLPanelFriends::onMaximumSelect));
mFriendsList->setCommitOnSelectionChange(TRUE);
+ mFriendsList->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
childSetCommitCallback("friend_list", onSelectName, this);
- childSetDoubleClickCallback("friend_list", onClickIM);
+ getChild<LLScrollListCtrl>("friend_list")->setDoubleClickCallback(onClickIM, this);
U32 changed_mask = LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE;
refreshNames(changed_mask);
@@ -232,8 +237,8 @@ BOOL LLPanelFriends::addFriend(const LLUUID& agent_id)
LLSD& friend_column = element["columns"][LIST_FRIEND_NAME];
friend_column["column"] = "friend_name";
friend_column["value"] = fullname;
- friend_column["font"] = "SANSSERIF";
- friend_column["font-style"] = "NORMAL";
+ friend_column["font"]["name"] = "SANSSERIF";
+ friend_column["font"]["style"] = "NORMAL";
LLSD& online_status_column = element["columns"][LIST_ONLINE_STATUS];
online_status_column["column"] = "icon_online_status";
@@ -241,12 +246,12 @@ BOOL LLPanelFriends::addFriend(const LLUUID& agent_id)
if (isOnline)
{
- friend_column["font-style"] = "BOLD";
+ friend_column["font"]["style"] = "BOLD";
online_status_column["value"] = "icon_avatar_online.tga";
}
else if(isOnlineSIP)
{
- friend_column["font-style"] = "BOLD";
+ friend_column["font"]["style"] = "BOLD";
online_status_column["value"] = ONLINE_SIP_ICON_NAME;
}
@@ -325,31 +330,14 @@ BOOL LLPanelFriends::updateFriendItem(const LLUUID& agent_id, const LLRelationsh
void LLPanelFriends::refreshRightsChangeList()
{
- LLDynamicArray<LLUUID> friends = getSelectedIDs();
+ std::vector<LLUUID> friends = getSelectedIDs();
S32 num_selected = friends.size();
bool can_offer_teleport = num_selected >= 1;
bool selected_friends_online = true;
- LLTextBox* processing_label = getChild<LLTextBox>("process_rights_label");
-
- if(!mAllowRightsChange)
- {
- if(processing_label)
- {
- processing_label->setVisible(true);
- // ignore selection for now
- friends.clear();
- num_selected = 0;
- }
- }
- else if(processing_label)
- {
- processing_label->setVisible(false);
- }
-
const LLRelationship* friend_status = NULL;
- for(LLDynamicArray<LLUUID>::iterator itr = friends.begin(); itr != friends.end(); ++itr)
+ for(std::vector<LLUUID>::iterator itr = friends.begin(); itr != friends.end(); ++itr)
{
friend_status = LLAvatarTracker::instance().getBuddyInfo(*itr);
if (friend_status)
@@ -391,7 +379,7 @@ struct SortFriendsByID
void LLPanelFriends::refreshNames(U32 changed_mask)
{
- LLDynamicArray<LLUUID> selected_ids = getSelectedIDs();
+ std::vector<LLUUID> selected_ids = getSelectedIDs();
S32 pos = mFriendsList->getScrollPos();
// get all buddies we know about
@@ -417,7 +405,7 @@ void LLPanelFriends::refreshNames(U32 changed_mask)
// Changed item in place, need to request sort and update columns
// because we might have changed data in a column on which the user
// has already sorted. JC
- mFriendsList->sortItems();
+ mFriendsList->updateSort();
// re-select items
mFriendsList->selectMultiple(selected_ids);
@@ -499,17 +487,8 @@ void LLPanelFriends::refreshUI()
single_selected = TRUE;
if(num_selected > 1)
{
- childSetText("friend_name_label", getString("Multiple"));
multiple_selected = TRUE;
}
- else
- {
- childSetText("friend_name_label", mFriendsList->getFirstSelected()->getColumn(LIST_FRIEND_NAME)->getValue().asString() + "...");
- }
- }
- else
- {
- childSetText("friend_name_label", LLStringUtil::null);
}
@@ -521,15 +500,15 @@ void LLPanelFriends::refreshUI()
//(single_selected will always be true in this situations)
childSetEnabled("remove_btn", single_selected);
childSetEnabled("im_btn", single_selected);
- childSetEnabled("friend_rights", single_selected);
+// childSetEnabled("friend_rights", single_selected);
refreshRightsChangeList();
}
-LLDynamicArray<LLUUID> LLPanelFriends::getSelectedIDs()
+std::vector<LLUUID> LLPanelFriends::getSelectedIDs()
{
LLUUID selected_id;
- LLDynamicArray<LLUUID> friend_ids;
+ std::vector<LLUUID> friend_ids;
std::vector<LLScrollListItem*> selected = mFriendsList->getAllSelected();
for(std::vector<LLScrollListItem*>::iterator itr = selected.begin(); itr != selected.end(); ++itr)
{
@@ -552,11 +531,11 @@ void LLPanelFriends::onSelectName(LLUICtrl* ctrl, void* user_data)
}
//static
-void LLPanelFriends::onMaximumSelect(void* user_data)
+void LLPanelFriends::onMaximumSelect()
{
LLSD args;
args["MAX_SELECT"] = llformat("%d", MAX_FRIEND_SELECT);
- LLNotifications::instance().add("MaxListSelectMessage", args);
+ LLNotificationsUtil::add("MaxListSelectMessage", args);
};
// static
@@ -564,14 +543,11 @@ void LLPanelFriends::onClickProfile(void* user_data)
{
LLPanelFriends* panelp = (LLPanelFriends*)user_data;
- //llinfos << "LLPanelFriends::onClickProfile()" << llendl;
- LLDynamicArray<LLUUID> ids = panelp->getSelectedIDs();
+ std::vector<LLUUID> ids = panelp->getSelectedIDs();
if(ids.size() > 0)
{
LLUUID agent_id = ids[0];
- BOOL online;
- online = LLAvatarTracker::instance().isBuddyOnline(agent_id);
- LLFloaterAvatarInfo::showFromFriend(agent_id, online);
+ LLAvatarActions::showProfile(agent_id);
}
}
@@ -580,108 +556,27 @@ void LLPanelFriends::onClickIM(void* user_data)
{
LLPanelFriends* panelp = (LLPanelFriends*)user_data;
- //llinfos << "LLPanelFriends::onClickIM()" << llendl;
- LLDynamicArray<LLUUID> ids = panelp->getSelectedIDs();
+ std::vector<LLUUID> ids = panelp->getSelectedIDs();
if(ids.size() > 0)
{
if(ids.size() == 1)
{
- LLUUID agent_id = ids[0];
- const LLRelationship* info = LLAvatarTracker::instance().getBuddyInfo(agent_id);
- std::string fullname;
- if(info && gCacheName->getFullName(agent_id, fullname))
- {
- gIMMgr->setFloaterOpen(TRUE);
- gIMMgr->addSession(fullname, IM_NOTHING_SPECIAL, agent_id);
- }
+ LLAvatarActions::startIM(ids[0]);
}
else
{
- gIMMgr->setFloaterOpen(TRUE);
- gIMMgr->addSession("Friends Conference", IM_SESSION_CONFERENCE_START, ids[0], ids);
+ LLAvatarActions::startConference(ids);
}
- make_ui_sound("UISndStartIM");
}
}
// static
-void LLPanelFriends::requestFriendship(const LLUUID& target_id, const std::string& target_name, const std::string& message)
-{
- LLUUID calling_card_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD);
- send_improved_im(target_id,
- target_name,
- message,
- IM_ONLINE,
- IM_FRIENDSHIP_OFFERED,
- calling_card_folder_id);
-}
-
-// static
-bool LLPanelFriends::callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotification::getSelectedOption(notification, response);
- if (option == 0)
- {
- requestFriendship(notification["payload"]["id"].asUUID(),
- notification["payload"]["name"].asString(),
- response["message"].asString());
- }
- return false;
-}
-
-bool LLPanelFriends::callbackAddFriend(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotification::getSelectedOption(notification, response);
- if (option == 0)
- {
- // Servers older than 1.25 require the text of the message to be the
- // calling card folder ID for the offering user. JC
- LLUUID calling_card_folder_id =
- gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD);
- std::string message = calling_card_folder_id.asString();
- requestFriendship(notification["payload"]["id"].asUUID(),
- notification["payload"]["name"].asString(),
- message);
- }
- return false;
-}
-
-// static
void LLPanelFriends::onPickAvatar(const std::vector<std::string>& names,
- const std::vector<LLUUID>& ids,
- void* )
+ const std::vector<LLUUID>& ids)
{
if (names.empty()) return;
if (ids.empty()) return;
- requestFriendshipDialog(ids[0], names[0]);
-}
-
-// static
-void LLPanelFriends::requestFriendshipDialog(const LLUUID& id,
- const std::string& name)
-{
- if(id == gAgentID)
- {
- LLNotifications::instance().add("AddSelfFriend");
- return;
- }
-
- LLSD args;
- args["NAME"] = name;
- LLSD payload;
- payload["id"] = id;
- payload["name"] = name;
- // Look for server versions like: Second Life Server 1.24.4.95600
- if (gLastVersionChannel.find(" 1.24.") != std::string::npos)
- {
- // Old and busted server version, doesn't support friend
- // requests with messages.
- LLNotifications::instance().add("AddFriend", args, payload, &callbackAddFriend);
- }
- else
- {
- LLNotifications::instance().add("AddFriendWithMessage", args, payload, &callbackAddFriendWithMessage);
- }
+ LLAvatarActions::requestFriendshipDialog(ids[0], names[0]);
}
// static
@@ -689,7 +584,7 @@ void LLPanelFriends::onClickAddFriend(void* user_data)
{
LLPanelFriends* panelp = (LLPanelFriends*)user_data;
LLFloater* root_floater = gFloaterView->getParentFloater(panelp);
- LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(onPickAvatar, user_data, FALSE, TRUE);
+ LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelFriends::onPickAvatar, _1,_2), FALSE, TRUE);
if (root_floater)
{
root_floater->addDependentFloater(picker);
@@ -700,53 +595,14 @@ void LLPanelFriends::onClickAddFriend(void* user_data)
void LLPanelFriends::onClickRemove(void* user_data)
{
LLPanelFriends* panelp = (LLPanelFriends*)user_data;
-
- //llinfos << "LLPanelFriends::onClickRemove()" << llendl;
- LLDynamicArray<LLUUID> ids = panelp->getSelectedIDs();
- LLSD args;
- if(ids.size() > 0)
- {
- std::string msgType = "RemoveFromFriends";
- if(ids.size() == 1)
- {
- LLUUID agent_id = ids[0];
- std::string first, last;
- if(gCacheName->getName(agent_id, first, last))
- {
- args["FIRST_NAME"] = first;
- args["LAST_NAME"] = last;
- }
- }
- else
- {
- msgType = "RemoveMultipleFromFriends";
- }
- LLSD payload;
-
- for (LLDynamicArray<LLUUID>::iterator it = ids.begin();
- it != ids.end();
- ++it)
- {
- payload["ids"].append(*it);
- }
-
- LLNotifications::instance().add(msgType,
- args,
- payload,
- &handleRemove);
- }
+ LLAvatarActions::removeFriendsDialog(panelp->getSelectedIDs());
}
// static
void LLPanelFriends::onClickOfferTeleport(void* user_data)
{
LLPanelFriends* panelp = (LLPanelFriends*)user_data;
-
- LLDynamicArray<LLUUID> ids = panelp->getSelectedIDs();
- if(ids.size() > 0)
- {
- handle_lure(ids);
- }
+ LLAvatarActions::offerTeleport(panelp->getSelectedIDs());
}
// static
@@ -754,10 +610,10 @@ void LLPanelFriends::onClickPay(void* user_data)
{
LLPanelFriends* panelp = (LLPanelFriends*)user_data;
- LLDynamicArray<LLUUID> ids = panelp->getSelectedIDs();
+ std::vector<LLUUID> ids = panelp->getSelectedIDs();
if(ids.size() == 1)
{
- handle_pay_by_id(ids[0]);
+ LLAvatarActions::pay(ids[0]);
}
}
@@ -782,14 +638,14 @@ void LLPanelFriends::confirmModifyRights(rights_map_t& ids, EGrantRevoke command
}
if (command == GRANT)
{
- LLNotifications::instance().add("GrantModifyRights",
+ LLNotificationsUtil::add("GrantModifyRights",
args,
LLSD(),
boost::bind(&LLPanelFriends::modifyRightsConfirmation, this, _1, _2, rights));
}
else
{
- LLNotifications::instance().add("RevokeModifyRights",
+ LLNotificationsUtil::add("RevokeModifyRights",
args,
LLSD(),
boost::bind(&LLPanelFriends::modifyRightsConfirmation, this, _1, _2, rights));
@@ -799,14 +655,14 @@ void LLPanelFriends::confirmModifyRights(rights_map_t& ids, EGrantRevoke command
{
if (command == GRANT)
{
- LLNotifications::instance().add("GrantModifyRightsMultiple",
+ LLNotificationsUtil::add("GrantModifyRightsMultiple",
args,
LLSD(),
boost::bind(&LLPanelFriends::modifyRightsConfirmation, this, _1, _2, rights));
}
else
{
- LLNotifications::instance().add("RevokeModifyRightsMultiple",
+ LLNotificationsUtil::add("RevokeModifyRightsMultiple",
args,
LLSD(),
boost::bind(&LLPanelFriends::modifyRightsConfirmation, this, _1, _2, rights));
@@ -817,7 +673,7 @@ void LLPanelFriends::confirmModifyRights(rights_map_t& ids, EGrantRevoke command
bool LLPanelFriends::modifyRightsConfirmation(const LLSD& notification, const LLSD& response, rights_map_t* rights)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if(0 == option)
{
sendRightsGrant(*rights);
@@ -955,42 +811,3 @@ void LLPanelFriends::sendRightsGrant(rights_map_t& ids)
mNumRightsChanged = ids.size();
gAgent.sendReliableMessage();
}
-
-
-
-// static
-bool LLPanelFriends::handleRemove(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotification::getSelectedOption(notification, response);
-
- const LLSD& ids = notification["payload"]["ids"];
- for(LLSD::array_const_iterator itr = ids.beginArray(); itr != ids.endArray(); ++itr)
- {
- LLUUID id = itr->asUUID();
- const LLRelationship* ip = LLAvatarTracker::instance().getBuddyInfo(id);
- if(ip)
- {
- switch(option)
- {
- case 0: // YES
- if( ip->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS))
- {
- LLAvatarTracker::instance().empower(id, FALSE);
- LLAvatarTracker::instance().notifyObservers();
- }
- LLAvatarTracker::instance().terminateBuddy(id);
- LLAvatarTracker::instance().notifyObservers();
- gInventory.addChangedMask(LLInventoryObserver::LABEL | LLInventoryObserver::CALLING_CARD, LLUUID::null);
- gInventory.notifyObservers();
- break;
-
- case 1: // NO
- default:
- llinfos << "No removal performed." << llendl;
- break;
- }
- }
-
- }
- return false;
-}
diff --git a/indra/newview/llfloaterfriends.h b/indra/newview/llfloaterfriends.h
index a5c94ee485..0042da48d3 100644
--- a/indra/newview/llfloaterfriends.h
+++ b/indra/newview/llfloaterfriends.h
@@ -74,14 +74,8 @@ public:
virtual BOOL postBuild();
- // Show a dialog explaining what friendship entails, then request
- // friendship. JC
- static void requestFriendshipDialog(const LLUUID& target_id,
- const std::string& target_name);
-
- // Just request friendship, no dialog.
- static void requestFriendship(const LLUUID& target_id,
- const std::string& target_name, const std::string& message);
+ // *HACK Made public to remove friends from LLAvatarIconCtrl context menu
+ static bool handleRemove(const LLSD& notification, const LLSD& response);
private:
@@ -115,15 +109,15 @@ private:
void confirmModifyRights(rights_map_t& ids, EGrantRevoke command);
void sendRightsGrant(rights_map_t& ids);
- // return LLUUID::null if nothing is selected
- LLDynamicArray<LLUUID> getSelectedIDs();
+ // return empty vector if nothing is selected
+ std::vector<LLUUID> getSelectedIDs();
// callback methods
static void onSelectName(LLUICtrl* ctrl, void* user_data);
static bool callbackAddFriend(const LLSD& notification, const LLSD& response);
static bool callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response);
- static void onPickAvatar(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* user_data);
- static void onMaximumSelect(void* user_data);
+ static void onPickAvatar(const std::vector<std::string>& names, const std::vector<LLUUID>& ids);
+ static void onMaximumSelect();
static void onClickIM(void* user_data);
static void onClickProfile(void* user_data);
@@ -135,7 +129,6 @@ private:
static void onClickModifyStatus(LLUICtrl* ctrl, void* user_data);
- static bool handleRemove(const LLSD& notification, const LLSD& response);
bool modifyRightsConfirmation(const LLSD& notification, const LLSD& response, rights_map_t* rights);
private:
diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp
index 6d39d75663..de65c6f876 100644
--- a/indra/newview/llfloatergesture.cpp
+++ b/indra/newview/llfloatergesture.cpp
@@ -34,36 +34,26 @@
#include "llfloatergesture.h"
-#include "lldir.h"
#include "llinventory.h"
-#include "llmultigesture.h"
+#include "llinventorybridge.h"
+#include "llinventorymodel.h"
+#include "llinventoryclipboard.h"
#include "llagent.h"
-#include "llviewerwindow.h"
-#include "llbutton.h"
-#include "llcombobox.h"
+#include "llappearancemgr.h"
+#include "llclipboard.h"
#include "llgesturemgr.h"
-#include "llinventorymodel.h"
-#include "llinventoryview.h"
#include "llkeyboard.h"
-#include "lllineeditor.h"
+#include "llmenugl.h"
+#include "llmultigesture.h"
#include "llpreviewgesture.h"
-#include "llresizehandle.h"
-#include "llscrollbar.h"
-#include "llscrollcontainer.h"
#include "llscrolllistctrl.h"
-#include "lltextbox.h"
-#include "lluictrlfactory.h"
+#include "lltrans.h"
#include "llviewergesture.h"
-#include "llviewerimagelist.h"
+#include "llviewermenu.h"
#include "llviewerinventory.h"
-#include "llvoavatar.h"
#include "llviewercontrol.h"
-// static
-LLFloaterGesture* LLFloaterGesture::sInstance = NULL;
-LLFloaterGestureObserver* LLFloaterGesture::sObserver = NULL;
-
BOOL item_name_precedes( LLInventoryItem* a, LLInventoryItem* b )
{
return LLStringUtil::precedesDict( a->getName(), b->getName() );
@@ -72,35 +62,113 @@ BOOL item_name_precedes( LLInventoryItem* a, LLInventoryItem* b )
class LLFloaterGestureObserver : public LLGestureManagerObserver
{
public:
- LLFloaterGestureObserver() {}
+ LLFloaterGestureObserver(LLFloaterGesture* floater) : mFloater(floater) {}
virtual ~LLFloaterGestureObserver() {}
- virtual void changed() { LLFloaterGesture::refreshAll(); }
+ virtual void changed() { mFloater->refreshAll(); }
+
+private:
+ LLFloaterGesture* mFloater;
+};
+//-----------------------------
+// GestureCallback
+//-----------------------------
+
+class GestureShowCallback : public LLInventoryCallback
+{
+public:
+ void fire(const LLUUID &inv_item)
+ {
+ LLPreviewGesture::show(inv_item, LLUUID::null);
+ }
+};
+
+class GestureCopiedCallback : public LLInventoryCallback
+{
+private:
+ LLFloaterGesture* mFloater;
+
+public:
+ GestureCopiedCallback(LLFloaterGesture* floater): mFloater(floater)
+ {}
+ void fire(const LLUUID &inv_item)
+ {
+ if(mFloater)
+ {
+ mFloater->addGesture(inv_item,NULL,mFloater->getChild<LLScrollListCtrl>("gesture_list"));
+ }
+ }
};
//---------------------------------------------------------------------------
// LLFloaterGesture
//---------------------------------------------------------------------------
-LLFloaterGesture::LLFloaterGesture()
-: LLFloater(std::string("Gesture Floater"))
+LLFloaterGesture::LLFloaterGesture(const LLSD& key)
+ : LLFloater(key)
{
- sInstance = this;
+ mObserver = new LLFloaterGestureObserver(this);
+ LLGestureManager::instance().addObserver(mObserver);
+
+ mCommitCallbackRegistrar.add("Gesture.Action.ToogleActiveState", 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));
- sObserver = new LLFloaterGestureObserver;
- gGestureManager.addObserver(sObserver);
+ mEnableCallbackRegistrar.add("Gesture.EnableAction", boost::bind(&LLFloaterGesture::isActionEnabled, this, _2));
}
-// virtual
-LLFloaterGesture::~LLFloaterGesture()
+void LLFloaterGesture::done()
{
- gGestureManager.removeObserver(sObserver);
- delete sObserver;
- sObserver = NULL;
+ //this method can be called twice: for GestureFolder and once after loading all sudir of GestureFolder
+ if (gInventory.isCategoryComplete(mGestureFolderID))
+ {
+ LL_DEBUGS("Gesture")<< "mGestureFolderID loaded" << LL_ENDL;
+ // we load only gesture folder without childred.
+ LLInventoryModel::cat_array_t* categories;
+ LLInventoryModel::item_array_t* items;
+ LLInventoryFetchDescendentsObserver::folder_ref_t unloaded_folders;
+ LL_DEBUGS("Gesture")<< "Get subdirs of Gesture Folder...." << LL_ENDL;
+ gInventory.getDirectDescendentsOf(mGestureFolderID, categories, items);
+ if (categories->empty())
+ {
+ gInventory.removeObserver(this);
+ LL_INFOS("Gesture")<< "Gesture dos NOT contains sub-directories."<< LL_ENDL;
+ return;
+ }
+ LL_DEBUGS("Gesture")<< "There are " << categories->size() << " Folders "<< LL_ENDL;
+ for (LLInventoryModel::cat_array_t::iterator it = categories->begin(); it != categories->end(); it++)
+ {
+ if (!gInventory.isCategoryComplete(it->get()->getUUID()))
+ {
+ unloaded_folders.push_back(it->get()->getUUID());
+ LL_DEBUGS("Gesture")<< it->get()->getName()<< " Folder added to fetchlist"<< LL_ENDL;
+ }
- sInstance = NULL;
+ }
+ if (!unloaded_folders.empty())
+ {
+ LL_DEBUGS("Gesture")<< "Fetching subdirectories....." << LL_ENDL;
+ fetchDescendents(unloaded_folders);
+ }
+ else
+ {
+ LL_DEBUGS("Gesture")<< "All Gesture subdirectories have been loaded."<< LL_ENDL;
+ gInventory.removeObserver(this);
+ buildGestureList();
+ }
+ }
+ else
+ {
+ LL_WARNS("Gesture")<< "Gesture list was NOT loaded"<< LL_ENDL;
+ }
+}
- // Custom saving rectangle, since load must be done
- // after postBuild.
- gSavedSettings.setRect("FloaterGestureRect2", getRect());
+// virtual
+LLFloaterGesture::~LLFloaterGesture()
+{
+ LLGestureManager::instance().removeObserver(mObserver);
+ delete mObserver;
+ mObserver = NULL;
+ gInventory.removeObserver(this);
}
// virtual
@@ -108,320 +176,447 @@ BOOL LLFloaterGesture::postBuild()
{
std::string label;
- // Translate title
label = getTitle();
setTitle(label);
+ mGestureList = getChild<LLScrollListCtrl>("gesture_list");
+ mGestureList->setCommitCallback(boost::bind(&LLFloaterGesture::onCommitList, this));
+ mGestureList->setDoubleClickCallback(boost::bind(&LLFloaterGesture::onClickPlay, this));
- childSetCommitCallback("gesture_list", onCommitList, this);
- childSetDoubleClickCallback("gesture_list", onClickPlay);
-
- childSetAction("inventory_btn", onClickInventory, this);
-
- childSetAction("edit_btn", onClickEdit, this);
+ getChild<LLUICtrl>("edit_btn")->setCommitCallback(boost::bind(&LLFloaterGesture::onClickEdit, this));
- childSetAction("play_btn", onClickPlay, this);
- childSetAction("stop_btn", onClickPlay, this);
-
- childSetAction("new_gesture_btn", onClickNew, this);
+ getChild<LLUICtrl>("play_btn")->setCommitCallback(boost::bind(&LLFloaterGesture::onClickPlay, this));
+ getChild<LLUICtrl>("stop_btn")->setCommitCallback(boost::bind(&LLFloaterGesture::onClickPlay, this));
+ getChild<LLButton>("activate_btn")->setClickedCallback(boost::bind(&LLFloaterGesture::onActivateBtnClick, this));
+
+ getChild<LLUICtrl>("new_gesture_btn")->setCommitCallback(boost::bind(&LLFloaterGesture::onClickNew, this));
+ getChild<LLButton>("del_btn")->setClickedCallback(boost::bind(&LLFloaterGesture::onDeleteSelected, this));
childSetVisible("play_btn", true);
childSetVisible("stop_btn", false);
setDefaultBtn("play_btn");
+ mGestureFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE, false);
- return TRUE;
-}
-
-
-// static
-void LLFloaterGesture::show()
-{
- if (sInstance)
- {
- sInstance->open(); /*Flawfinder: ignore*/
- return;
- }
-
- LLFloaterGesture *self = new LLFloaterGesture();
-
- // Builds and adds to gFloaterView
- LLUICtrlFactory::getInstance()->buildFloater(self, "floater_gesture.xml");
+ folder_ref_t folders;
+ folders.push_back(mGestureFolderID);
+ //perform loading Gesture directory anyway to make sure that all subdirectory are loaded too. See method done() for details.
+ gInventory.addObserver(this);
+ fetchDescendents(folders);
- // Fix up rectangle
- LLRect rect = gSavedSettings.getRect("FloaterGestureRect2");
- self->reshape(rect.getWidth(), rect.getHeight());
- self->setRect(rect);
-
- self->buildGestureList();
-
- self->childSetFocus("gesture_list");
+ buildGestureList();
+
+ mGestureList->setFocus(TRUE);
- LLCtrlListInterface *list = self->childGetListInterface("gesture_list");
- if (list)
+ if (mGestureList)
{
const BOOL ascending = TRUE;
- list->sortByColumn(std::string("name"), ascending);
- list->selectFirstItem();
+ mGestureList->sortByColumn(std::string("name"), ascending);
+ mGestureList->selectFirstItem();
}
- self->mSelectedID = LLUUID::null;
-
// Update button labels
- onCommitList(NULL, self);
- self->open(); /*Flawfinder: ignore*/
+ onCommitList();
+
+ return TRUE;
}
-// static
-void LLFloaterGesture::toggleVisibility()
+
+void LLFloaterGesture::refreshAll()
{
- if(sInstance && sInstance->getVisible())
+ buildGestureList();
+
+ if (!mGestureList) return;
+
+ if (mSelectedID.isNull())
{
- sInstance->close();
+ mGestureList->selectFirstItem();
}
else
{
- show();
+ if (! mGestureList->setCurrentByID(mSelectedID))
+ {
+ mGestureList->selectFirstItem();
+ }
}
+
+ // Update button labels
+ onCommitList();
}
-// static
-void LLFloaterGesture::refreshAll()
+void LLFloaterGesture::buildGestureList()
{
- if (sInstance)
+ S32 scroll_pos = mGestureList->getScrollPos();
+ std::vector<LLUUID> selected_items;
+ getSelectedIds(selected_items);
+ LL_DEBUGS("Gesture")<< "Rebuilding gesture list "<< LL_ENDL;
+ mGestureList->deleteAllItems();
+
+ LLGestureManager::item_map_t::const_iterator it;
+ const LLGestureManager::item_map_t& active_gestures = LLGestureManager::instance().getActiveGestures();
+ for (it = active_gestures.begin(); it != active_gestures.end(); ++it)
{
- sInstance->buildGestureList();
-
- LLCtrlListInterface *list = sInstance->childGetListInterface("gesture_list");
- if (!list) return;
+ addGesture(it->first,it->second, mGestureList);
+ }
+ if (gInventory.isCategoryComplete(mGestureFolderID))
+ {
+ LLIsType is_gesture(LLAssetType::AT_GESTURE);
+ LLInventoryModel::cat_array_t categories;
+ LLInventoryModel::item_array_t items;
+ gInventory.collectDescendentsIf(mGestureFolderID, categories, items,
+ LLInventoryModel::EXCLUDE_TRASH, is_gesture);
- if (sInstance->mSelectedID.isNull())
- {
- list->selectFirstItem();
- }
- else
+ for (LLInventoryModel::item_array_t::iterator it = items.begin(); it!= items.end(); ++it)
{
- if (! list->setCurrentByID(sInstance->mSelectedID))
+ LLInventoryItem* item = it->get();
+ if (active_gestures.find(item->getUUID()) == active_gestures.end())
{
- list->selectFirstItem();
+ // if gesture wasn't loaded yet, we can display only name
+ addGesture(item->getUUID(), NULL, mGestureList);
}
}
+ }
- // Update button labels
- onCommitList(NULL, sInstance);
+ // attempt to preserve scroll position through re-builds
+ // since we do re-build whenever something gets dirty
+ for(std::vector<LLUUID>::iterator it = selected_items.begin(); it != selected_items.end(); it++)
+ {
+ mGestureList->selectByID(*it);
}
+ mGestureList->setScrollPos(scroll_pos);
}
-void LLFloaterGesture::buildGestureList()
+void LLFloaterGesture::addGesture(const LLUUID& item_id , LLMultiGesture* gesture,LLCtrlListInterface * list )
{
- LLCtrlListInterface *list = childGetListInterface("gesture_list");
- LLCtrlScrollInterface *scroll = childGetScrollInterface("gesture_list");
+ // Note: Can have NULL item if inventory hasn't arrived yet.
+ static std::string item_name = getString("loading");
+ LLInventoryItem* item = gInventory.getItem(item_id);
+ if (item)
+ {
+ item_name = item->getName();
+ }
- if (! (list && scroll)) return;
+ static std::string font_style = "NORMAL";
+ // If gesture is playing, bold it
- // attempt to preserve scroll position through re-builds
- // since we do re-build any time anything dirties
- S32 current_scroll_pos = scroll->getScrollPos();
-
- list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ LLSD element;
+ element["id"] = item_id;
- LLGestureManager::item_map_t::iterator it;
- for (it = gGestureManager.mActive.begin(); it != gGestureManager.mActive.end(); ++it)
+ if (gesture)
{
- const LLUUID& item_id = (*it).first;
- LLMultiGesture* gesture = (*it).second;
-
- // Note: Can have NULL item if inventory hasn't arrived yet.
- std::string item_name = "Loading...";
- LLInventoryItem* item = gInventory.getItem(item_id);
- if (item)
+ if (gesture->mPlaying)
{
- item_name = item->getName();
+ font_style = "BOLD";
}
+ item_name = gesture->mName;
+ element["columns"][0]["column"] = "trigger";
+ element["columns"][0]["value"] = gesture->mTrigger;
+ element["columns"][0]["font"]["name"] = "SANSSERIF";
+ element["columns"][0]["font"]["style"] = font_style;
- std::string font_style = "NORMAL";
- // If gesture is playing, bold it
-
- LLSD element;
- element["id"] = item_id;
+ std::string key_string = LLKeyboard::stringFromKey(gesture->mKey);
+ std::string buffer;
- if (gesture)
+ if (gesture->mKey == KEY_NONE)
{
- if (gesture->mPlaying)
- {
- font_style = "BOLD";
- }
+ buffer = "---";
+ key_string = "~~~"; // alphabetize to end
+ }
+ else
+ {
+ buffer = LLKeyboard::stringFromAccelerator(gesture->mMask,
+ gesture->mKey);
+ }
- element["columns"][0]["column"] = "trigger";
- element["columns"][0]["value"] = gesture->mTrigger;
- element["columns"][0]["font"] = "SANSSERIF";
- element["columns"][0]["font-style"] = font_style;
+ element["columns"][1]["column"] = "shortcut";
+ element["columns"][1]["value"] = buffer;
+ element["columns"][1]["font"]["name"] = "SANSSERIF";
+ element["columns"][1]["font"]["style"] = font_style;
- std::string key_string = LLKeyboard::stringFromKey(gesture->mKey);
- std::string buffer;
+ // hidden column for sorting
+ element["columns"][2]["column"] = "key";
+ element["columns"][2]["value"] = key_string;
+ element["columns"][2]["font"]["name"] = "SANSSERIF";
+ element["columns"][2]["font"]["style"] = font_style;
- {
- if (gesture->mKey == KEY_NONE)
- {
- buffer = "---";
- key_string = "~~~"; // alphabetize to end
- }
- else
- {
- if (gesture->mMask & MASK_CONTROL) buffer.append("Ctrl-");
- if (gesture->mMask & MASK_ALT) buffer.append("Alt-");
- if (gesture->mMask & MASK_SHIFT) buffer.append("Shift-");
- if ((gesture->mMask & (MASK_CONTROL|MASK_ALT|MASK_SHIFT)) &&
- (key_string[0] == '-' || key_string[0] == '='))
- {
- buffer.append(" ");
- }
- buffer.append(key_string);
- }
- }
- element["columns"][1]["column"] = "shortcut";
- element["columns"][1]["value"] = buffer;
- element["columns"][1]["font"] = "SANSSERIF";
- element["columns"][1]["font-style"] = font_style;
-
- // hidden column for sorting
- element["columns"][2]["column"] = "key";
- element["columns"][2]["value"] = key_string;
- element["columns"][2]["font"] = "SANSSERIF";
- element["columns"][2]["font-style"] = font_style;
-
- // Only add "playing" if we've got the name, less confusing. JC
- if (item && gesture->mPlaying)
- {
- item_name += " (Playing)";
- }
- element["columns"][3]["column"] = "name";
- element["columns"][3]["value"] = item_name;
- element["columns"][3]["font"] = "SANSSERIF";
- element["columns"][3]["font-style"] = font_style;
- }
- else
+ // Only add "playing" if we've got the name, less confusing. JC
+ if (item && gesture->mPlaying)
{
- element["columns"][0]["column"] = "trigger";
- element["columns"][0]["value"] = "";
- element["columns"][0]["font"] = "SANSSERIF";
- element["columns"][0]["font-style"] = font_style;
- element["columns"][0]["column"] = "trigger";
- element["columns"][0]["value"] = "---";
- element["columns"][0]["font"] = "SANSSERIF";
- element["columns"][0]["font-style"] = font_style;
- element["columns"][2]["column"] = "key";
- element["columns"][2]["value"] = "~~~";
- element["columns"][2]["font"] = "SANSSERIF";
- element["columns"][2]["font-style"] = font_style;
- element["columns"][3]["column"] = "name";
- element["columns"][3]["value"] = item_name;
- element["columns"][3]["font"] = "SANSSERIF";
- element["columns"][3]["font-style"] = font_style;
+ item_name += " " + getString("playing");
}
- list->addElement(element, ADD_BOTTOM);
+ element["columns"][3]["column"] = "name";
+ element["columns"][3]["value"] = item_name;
+ element["columns"][3]["font"]["name"] = "SANSSERIF";
+ element["columns"][3]["font"]["style"] = font_style;
}
-
- scroll->setScrollPos(current_scroll_pos);
+ else
+ {
+ element["columns"][0]["column"] = "trigger";
+ element["columns"][0]["value"] = "";
+ element["columns"][0]["font"]["name"] = "SANSSERIF";
+ element["columns"][0]["font"]["style"] = font_style;
+ element["columns"][0]["column"] = "trigger";
+ element["columns"][0]["value"] = "---";
+ element["columns"][0]["font"]["name"] = "SANSSERIF";
+ element["columns"][0]["font"]["style"] = font_style;
+ element["columns"][2]["column"] = "key";
+ element["columns"][2]["value"] = "~~~";
+ element["columns"][2]["font"]["name"] = "SANSSERIF";
+ element["columns"][2]["font"]["style"] = font_style;
+ element["columns"][3]["column"] = "name";
+ element["columns"][3]["value"] = item_name;
+ element["columns"][3]["font"]["name"] = "SANSSERIF";
+ element["columns"][3]["font"]["style"] = font_style;
+ }
+ list->addElement(element, ADD_BOTTOM);
}
-// static
-void LLFloaterGesture::onClickInventory(void* data)
+void LLFloaterGesture::getSelectedIds(std::vector<LLUUID>& ids)
{
- LLFloaterGesture* self = (LLFloaterGesture*)data;
-
- LLCtrlListInterface *list = self->childGetListInterface("gesture_list");
- if (!list) return;
- const LLUUID& item_id = list->getCurrentID();
-
- LLInventoryView* inv = LLInventoryView::showAgentInventory();
- if (!inv) return;
- inv->getPanel()->setSelection(item_id, TRUE);
+ std::vector<LLScrollListItem*> items = mGestureList->getAllSelected();
+ for(std::vector<LLScrollListItem*>::const_iterator it = items.begin(); it != items.end(); it++)
+ {
+ ids.push_back((*it)->getUUID());
+ }
}
-// static
-void LLFloaterGesture::onClickPlay(void* data)
+bool LLFloaterGesture::isActionEnabled(const LLSD& command)
{
- LLFloaterGesture* self = (LLFloaterGesture*)data;
-
- LLCtrlListInterface *list = self->childGetListInterface("gesture_list");
- if (!list) return;
- const LLUUID& item_id = list->getCurrentID();
-
- if (gGestureManager.isGesturePlaying(item_id))
+ // paste copy_uuid edit_gesture
+ std::string command_name = command.asString();
+ if("paste" == command_name)
{
- gGestureManager.stopGesture(item_id);
+ if(!LLInventoryClipboard::instance().hasContents())
+ return false;
+
+ LLDynamicArray<LLUUID> ids;
+ LLInventoryClipboard::instance().retrieve(ids);
+ for(LLDynamicArray<LLUUID>::iterator it = ids.begin(); it != ids.end(); it++)
+ {
+ LLInventoryItem* item = gInventory.getItem(*it);
+
+ if(item && item->getInventoryType() == LLInventoryType::IT_GESTURE)
+ {
+ return true;
+ }
+ }
+ return false;
}
- else
+ else if("copy_uuid" == command_name || "edit_gesture" == command_name
+ || "inspect" == command_name)
{
- gGestureManager.playGesture(item_id);
+ return mGestureList->getAllSelected().size() == 1;
}
+ return true;
}
-class GestureShowCallback : public LLInventoryCallback
+void LLFloaterGesture::onClickPlay()
{
-public:
- GestureShowCallback(std::string &title)
+ const LLUUID& item_id = mGestureList->getCurrentID();
+ if(item_id.isNull()) return;
+
+ LL_DEBUGS("Gesture")<<" Trying to play gesture id: "<< item_id <<LL_ENDL;
+ if(!LLGestureManager::instance().isGestureActive(item_id))
{
- mTitle = title;
+ // we need to inform server about gesture activating to be consistent with LLPreviewGesture and LLGestureComboList.
+ BOOL inform_server = TRUE;
+ BOOL deactivate_similar = FALSE;
+ LLGestureManager::instance().setGestureLoadedCallback(item_id, boost::bind(&LLFloaterGesture::playGesture, this, item_id));
+ LLGestureManager::instance().activateGestureWithAsset(item_id, gInventory.getItem(item_id)->getAssetUUID(), inform_server, deactivate_similar);
+ LL_DEBUGS("Gesture")<< "Activating gesture with inventory ID: " << item_id <<LL_ENDL;
}
- void fire(const LLUUID &inv_item)
+ else
{
- LLPreviewGesture::show(mTitle, inv_item, LLUUID::null);
+ playGesture(item_id);
}
-private:
- std::string mTitle;
-};
+}
-// static
-void LLFloaterGesture::onClickNew(void* data)
+void LLFloaterGesture::onClickNew()
{
- std::string title("Gesture: ");
- title.append("New Gesture");
- LLPointer<LLInventoryCallback> cb = new GestureShowCallback(title);
+ LLPointer<LLInventoryCallback> cb = new GestureShowCallback();
create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
LLUUID::null, LLTransactionID::tnull, "New Gesture", "", LLAssetType::AT_GESTURE,
LLInventoryType::IT_GESTURE, NOT_WEARABLE, PERM_MOVE | PERM_TRANSFER, cb);
}
+void LLFloaterGesture::onActivateBtnClick()
+{
+ std::vector<LLUUID> ids;
+ getSelectedIds(ids);
+ if(ids.empty())
+ return;
+
+ LLGestureManager* gm = LLGestureManager::getInstance();
+ std::vector<LLUUID>::const_iterator it = ids.begin();
+ BOOL first_gesture_state = gm->isGestureActive(*it);
+ BOOL is_mixed = FALSE;
+ while( ++it != ids.end() )
+ {
+ if(first_gesture_state != gm->isGestureActive(*it))
+ {
+ is_mixed = TRUE;
+ break;
+ }
+ }
+ for(std::vector<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); it++)
+ {
+ if(is_mixed)
+ {
+ gm->activateGesture(*it);
+ }
+ else
+ {
+ if(first_gesture_state)
+ {
+ gm->deactivateGesture(*it);
+ }
+ else
+ {
+ gm->activateGesture(*it);
+ }
+ }
+ }
+}
-// static
-void LLFloaterGesture::onClickEdit(void* data)
+void LLFloaterGesture::onCopyPasteAction(const LLSD& command)
{
- LLFloaterGesture* self = (LLFloaterGesture*)data;
+ std::string command_name = command.asString();
+ // since we select this comman inventory item had already arrived .
+ if("copy_gesture" == command_name)
+ {
+ std::vector<LLUUID> ids;
+ getSelectedIds(ids);
+ // make sure that clopboard is empty
+ LLInventoryClipboard::instance().reset();
+ for(std::vector<LLUUID>::iterator it = ids.begin(); it != ids.end(); it++)
+ {
+ LLInventoryItem* item = gInventory.getItem(*it);
+ if(item && item->getInventoryType() == LLInventoryType::IT_GESTURE)
+ {
+ LLInventoryClipboard::instance().add(item->getUUID());
+ }
+ }
+ }
+ else if ("paste" == command_name)
+ {
+ LLInventoryClipboard& clipbord = LLInventoryClipboard::instance();
+ LLDynamicArray<LLUUID> ids;
+ clipbord.retrieve(ids);
+ if(ids.empty() || !gInventory.isCategoryComplete(mGestureFolderID))
+ return;
+ LLInventoryCategory* gesture_dir = gInventory.getCategory(mGestureFolderID);
+ LLPointer<GestureCopiedCallback> cb = new GestureCopiedCallback(this);
+
+ for(LLDynamicArray<LLUUID>::iterator it = ids.begin(); it != ids.end(); it++)
+ {
+ LLInventoryItem* item = gInventory.getItem(*it);
+ LLStringUtil::format_map_t string_args;
+ string_args["[COPY_NAME]"] = item->getName();
+ if(item && item->getInventoryType() == LLInventoryType::IT_GESTURE)
+ {
+ LL_DEBUGS("Gesture")<< "Copying gesture " << item->getName() << " "<< item->getUUID() << " into "
+ << gesture_dir->getName() << " "<< gesture_dir->getUUID() << LL_ENDL;
+ copy_inventory_item(gAgent.getID(), item->getPermissions().getOwner(), item->getUUID(),
+ gesture_dir->getUUID(), getString("copy_name", string_args), cb);
+ }
+ }
+ clipbord.reset();
+ }
+ else if ("copy_uuid" == command_name)
+ {
+ gClipboard.copyFromString(utf8str_to_wstring(mGestureList->getCurrentID().asString()), mGestureList->getCurrentID());
+ }
+}
- LLCtrlListInterface *list = self->childGetListInterface("gesture_list");
- if (!list) return;
- const LLUUID& item_id = list->getCurrentID();
+void LLFloaterGesture::onClickEdit()
+{
+ const LLUUID& item_id = mGestureList->getCurrentID();
LLInventoryItem* item = gInventory.getItem(item_id);
if (!item) return;
- std::string title("Gesture: ");
- title.append(item->getName());
-
- LLPreviewGesture* previewp = LLPreviewGesture::show(title, item_id, LLUUID::null);
+ LLPreviewGesture* previewp = LLPreviewGesture::show(item_id, LLUUID::null);
if (!previewp->getHost())
{
- previewp->setRect(gFloaterView->findNeighboringPosition(self, previewp));
+ previewp->setRect(gFloaterView->findNeighboringPosition(this, previewp));
}
}
-// static
-void LLFloaterGesture::onCommitList(LLUICtrl* ctrl, void* data)
+void LLFloaterGesture::onCommitList()
{
- LLFloaterGesture* self = (LLFloaterGesture*)data;
+ const LLUUID& item_id = mGestureList->getCurrentID();
- const LLUUID& item_id = self->childGetValue("gesture_list").asUUID();
+ mSelectedID = item_id;
+ if (LLGestureManager::instance().isGesturePlaying(item_id))
+ {
+ childSetVisible("play_btn", false);
+ childSetVisible("stop_btn", true);
+ }
+ else
+ {
+ childSetVisible("play_btn", true);
+ childSetVisible("stop_btn", false);
+ }
+}
+
+void LLFloaterGesture::onDeleteSelected()
+{
+ std::vector<LLUUID> ids;
+ getSelectedIds(ids);
+ if(ids.empty())
+ return;
+
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ LLGestureManager* gm = LLGestureManager::getInstance();
+ for(std::vector<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); it++)
+ {
+ const LLUUID& selected_item = *it;
+ LLInventoryItem* inv_item = gInventory.getItem(selected_item);
+ if (inv_item && inv_item->getInventoryType() == LLInventoryType::IT_GESTURE)
+ {
+ if(gm->isGestureActive(selected_item))
+ {
+ gm->deactivateGesture(selected_item);
+ }
+ LLInventoryModel::update_list_t update;
+ LLInventoryModel::LLCategoryUpdate old_folder(inv_item->getParentUUID(), -1);
+ update.push_back(old_folder);
+ LLInventoryModel::LLCategoryUpdate new_folder(trash_id, 1);
+ update.push_back(new_folder);
+ gInventory.accountForUpdate(update);
+
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(inv_item);
+ new_item->setParent(trash_id);
+ // no need to restamp it though it's a move into trash because
+ // it's a brand new item already.
+ new_item->updateParentOnServer(FALSE);
+ gInventory.updateItem(new_item);
+ }
+ }
+ gInventory.notifyObservers();
+ buildGestureList();
+}
+
+void LLFloaterGesture::addToCurrentOutFit()
+{
+ std::vector<LLUUID> ids;
+ getSelectedIds(ids);
+ LLAppearanceManager* am = LLAppearanceManager::getInstance();
+ for(std::vector<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); it++)
+ {
+ am->addCOFItemLink(*it);
+ }
+}
+
+void LLFloaterGesture::playGesture(LLUUID item_id)
+{
+ LL_DEBUGS("Gesture")<<"Playing gesture "<< item_id<<LL_ENDL;
- self->mSelectedID = item_id;
- if (gGestureManager.isGesturePlaying(item_id))
+ if (LLGestureManager::instance().isGesturePlaying(item_id))
{
- self->childSetVisible("play_btn", false);
- self->childSetVisible("stop_btn", true);
+ LLGestureManager::instance().stopGesture(item_id);
}
else
{
- self->childSetVisible("play_btn", true);
- self->childSetVisible("stop_btn", false);
+ LLGestureManager::instance().playGesture(item_id);
}
}
diff --git a/indra/newview/llfloatergesture.h b/indra/newview/llfloatergesture.h
index 4e11a10e61..629d77b949 100644
--- a/indra/newview/llfloatergesture.h
+++ b/indra/newview/llfloatergesture.h
@@ -36,12 +36,12 @@
#ifndef LL_LLFLOATERGESTURE_H
#define LL_LLFLOATERGESTURE_H
+#include <vector>
#include "llfloater.h"
+#include "llinventoryobserver.h"
-#include "lldarray.h"
-
-class LLScrollableContainerView;
+class LLScrollContainer;
class LLView;
class LLButton;
class LLLineEditor;
@@ -51,37 +51,62 @@ class LLGestureOptions;
class LLScrollListCtrl;
class LLFloaterGestureObserver;
class LLFloaterGestureInventoryObserver;
+class LLMultiGesture;
+class LLMenuGL;
class LLFloaterGesture
-: public LLFloater
+: public LLFloater, LLInventoryFetchDescendentsObserver
{
+ LOG_CLASS(LLFloaterGesture);
public:
- LLFloaterGesture();
+ LLFloaterGesture(const LLSD& key);
virtual ~LLFloaterGesture();
virtual BOOL postBuild();
-
- static void show();
- static void toggleVisibility();
- static void refreshAll();
+ virtual void done ();
+ void refreshAll();
+ /**
+ * @brief Add new scrolllistitem into gesture_list.
+ * @param item_id inventory id of gesture
+ * @param gesture can be NULL , if item was not loaded yet
+ */
+ void addGesture(const LLUUID& item_id, LLMultiGesture* gesture, LLCtrlListInterface * list);
protected:
// Reads from the gesture manager's list of active gestures
// and puts them in this list.
void buildGestureList();
+ void playGesture(LLUUID item_id);
+private:
+ void addToCurrentOutFit();
+ /**
+ * @brief This method is using to collect selected items.
+ * In some places gesture_list can be rebuilt by gestureObservers during iterating data from LLScrollListCtrl::getAllSelected().
+ * Therefore we have to copy these items to avoid viewer crash.
+ * @see LLFloaterGesture::onActivateBtnClick
+ */
+ void getSelectedIds(std::vector<LLUUID>& ids);
+ bool isActionEnabled(const LLSD& command);
+ /**
+ * @brief Activation rules:
+ * According to Gesture Spec:
+ * 1. If all selected gestures are active: set to inactive
+ * 2. If all selected gestures are inactive: set to active
+ * 3. If selected gestures are in a mixed state: set all to active
+ */
+ void onActivateBtnClick();
+ void onClickEdit();
+ void onClickPlay();
+ void onClickNew();
+ void onCommitList();
+ void onCopyPasteAction(const LLSD& command);
+ void onDeleteSelected();
- static void onClickInventory(void* data);
- static void onClickEdit(void* data);
- static void onClickPlay(void* data);
- static void onClickNew(void* data);
- static void onCommitList(LLUICtrl* ctrl, void* data);
-
-protected:
LLUUID mSelectedID;
+ LLUUID mGestureFolderID;
+ LLScrollListCtrl* mGestureList;
- static LLFloaterGesture* sInstance;
- static LLFloaterGestureObserver* sObserver;
- static LLFloaterGestureInventoryObserver* sInventoryObserver;
+ LLFloaterGestureObserver* mObserver;
};
diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp
index 4959a2913e..c2b0bd18fa 100644
--- a/indra/newview/llfloatergodtools.cpp
+++ b/indra/newview/llfloatergodtools.cpp
@@ -39,17 +39,18 @@
#include "llframetimer.h"
#include "llgl.h"
#include "llhost.h"
+#include "llnotificationsutil.h"
#include "llregionflags.h"
#include "llstring.h"
#include "message.h"
#include "llagent.h"
-#include "llalertdialog.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#include "lldraghandle.h"
#include "llfloater.h"
+#include "llfloaterreg.h"
#include "llfocusmgr.h"
#include "llfloatertopobjects.h"
#include "lllineeditor.h"
@@ -67,42 +68,44 @@
#include "llviewerwindow.h"
#include "llworld.h"
#include "llfloateravatarpicker.h"
-#include "llnotify.h"
#include "llxfermanager.h"
#include "llvlcomposition.h"
#include "llsurface.h"
#include "llviewercontrol.h"
#include "lluictrlfactory.h"
+#include "lltrans.h"
#include "lltransfertargetfile.h"
#include "lltransfersourcefile.h"
const F32 SECONDS_BETWEEN_UPDATE_REQUESTS = 5.0f;
-static LLFloaterGodTools* sGodTools = NULL;
-
//*****************************************************************************
// LLFloaterGodTools
//*****************************************************************************
-// static
-LLFloaterGodTools* LLFloaterGodTools::instance()
+void LLFloaterGodTools::onOpen(const LLSD& key)
{
- if (!sGodTools)
+ center();
+ setFocus(TRUE);
+// LLPanel *panel = childGetVisibleTab("GodTools Tabs");
+// if (panel)
+// panel->setFocus(TRUE);
+ if (mPanelObjectTools)
+ mPanelObjectTools->setTargetAvatar(LLUUID::null);
+
+ if (gAgent.getRegionHost() != mCurrentHost)
{
- sGodTools = new LLFloaterGodTools();
- sGodTools->open(); /*Flawfinder: ignore*/
- sGodTools->center();
- sGodTools->setFocus(TRUE);
+ // we're in a new region
+ sendRegionInfoRequest();
}
- return sGodTools;
}
// static
void LLFloaterGodTools::refreshAll()
{
- LLFloaterGodTools* god_tools = instance();
+ LLFloaterGodTools* god_tools = LLFloaterReg::getTypedInstance<LLFloaterGodTools>("god_tools");
if (god_tools)
{
if (gAgent.getRegionHost() != god_tools->mCurrentHost)
@@ -115,39 +118,36 @@ void LLFloaterGodTools::refreshAll()
-LLFloaterGodTools::LLFloaterGodTools()
-: LLFloater(std::string("godtools floater")),
+LLFloaterGodTools::LLFloaterGodTools(const LLSD& key)
+: LLFloater(key),
mCurrentHost(LLHost::invalid),
mUpdateTimer()
{
- LLCallbackMap::map_t factory_map;
- factory_map["grid"] = LLCallbackMap(createPanelGrid, this);
- factory_map["region"] = LLCallbackMap(createPanelRegion, this);
- factory_map["objects"] = LLCallbackMap(createPanelObjects, this);
- factory_map["request"] = LLCallbackMap(createPanelRequest, this);
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_god_tools.xml", &factory_map);
+ mFactoryMap["grid"] = LLCallbackMap(createPanelGrid, this);
+ mFactoryMap["region"] = LLCallbackMap(createPanelRegion, this);
+ mFactoryMap["objects"] = LLCallbackMap(createPanelObjects, this);
+ mFactoryMap["request"] = LLCallbackMap(createPanelRequest, this);
+// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_god_tools.xml");
- childSetTabChangeCallback("GodTools Tabs", "grid", onTabChanged, this);
- childSetTabChangeCallback("GodTools Tabs", "region", onTabChanged, this);
- childSetTabChangeCallback("GodTools Tabs", "objects", onTabChanged, this);
- childSetTabChangeCallback("GodTools Tabs", "request", onTabChanged, this);
+}
+BOOL LLFloaterGodTools::postBuild()
+{
sendRegionInfoRequest();
-
childShowTab("GodTools Tabs", "region");
+ return TRUE;
}
-
// static
void* LLFloaterGodTools::createPanelGrid(void *userdata)
{
- return new LLPanelGridTools("grid");
+ return new LLPanelGridTools();
}
// static
void* LLFloaterGodTools::createPanelRegion(void *userdata)
{
LLFloaterGodTools* self = (LLFloaterGodTools*)userdata;
- self->mPanelRegionTools = new LLPanelRegionTools("region");
+ self->mPanelRegionTools = new LLPanelRegionTools();
return self->mPanelRegionTools;
}
@@ -155,14 +155,14 @@ void* LLFloaterGodTools::createPanelRegion(void *userdata)
void* LLFloaterGodTools::createPanelObjects(void *userdata)
{
LLFloaterGodTools* self = (LLFloaterGodTools*)userdata;
- self->mPanelObjectTools = new LLPanelObjectTools("objects");
+ self->mPanelObjectTools = new LLPanelObjectTools();
return self->mPanelObjectTools;
}
// static
void* LLFloaterGodTools::createPanelRequest(void *userdata)
{
- return new LLPanelRequestTools("region");
+ return new LLPanelRequestTools();
}
LLFloaterGodTools::~LLFloaterGodTools()
@@ -170,6 +170,7 @@ LLFloaterGodTools::~LLFloaterGodTools()
// children automatically deleted
}
+
U32 LLFloaterGodTools::computeRegionFlags() const
{
U32 flags = gAgent.getRegion()->getRegionFlags();
@@ -184,15 +185,6 @@ void LLFloaterGodTools::updatePopup(LLCoordGL center, MASK mask)
}
// virtual
-void LLFloaterGodTools::onClose(bool app_quitting)
-{
- if (sGodTools)
- {
- sGodTools->setVisible(FALSE);
- }
-}
-
-// virtual
void LLFloaterGodTools::draw()
{
if (mCurrentHost == LLHost::invalid)
@@ -209,42 +201,15 @@ void LLFloaterGodTools::draw()
LLFloater::draw();
}
-// static
-void LLFloaterGodTools::show(void *)
-{
- LLFloaterGodTools* god_tools = instance();
- god_tools->open();
- LLPanel *panel = god_tools->childGetVisibleTab("GodTools Tabs");
- if (panel) panel->setFocus(TRUE);
- if (god_tools->mPanelObjectTools) god_tools->mPanelObjectTools->setTargetAvatar(LLUUID::null);
-
- if (gAgent.getRegionHost() != god_tools->mCurrentHost)
- {
- // we're in a new region
- god_tools->sendRegionInfoRequest();
- }
-}
-
void LLFloaterGodTools::showPanel(const std::string& panel_name)
{
childShowTab("GodTools Tabs", panel_name);
- open(); /*Flawfinder: ignore*/
+ openFloater();
LLPanel *panel = childGetVisibleTab("GodTools Tabs");
- if (panel) panel->setFocus(TRUE);
-}
-
-
-// static
-void LLFloaterGodTools::onTabChanged(void* data, bool from_click)
-{
- LLPanel* panel = (LLPanel*)data;
if (panel)
- {
panel->setFocus(TRUE);
- }
}
-
// static
void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg)
{
@@ -297,16 +262,19 @@ void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg)
regionp->setWaterHeight(water_height);
regionp->setBillableFactor(billable_factor);
}
+
+ LLFloaterGodTools* god_tools = LLFloaterReg::getTypedInstance<LLFloaterGodTools>("god_tools");
+ if (!god_tools) return;
// push values to god tools, if available
- if (sGodTools
- && sGodTools->mPanelRegionTools
- && sGodTools->mPanelObjectTools
- && msg
- && gAgent.isGodlike())
+ if ( gAgent.isGodlike()
+ && LLFloaterReg::instanceVisible("god_tools")
+ && god_tools->mPanelRegionTools
+ && god_tools->mPanelObjectTools
+ && msg )
{
- LLPanelRegionTools* rtool = sGodTools->mPanelRegionTools;
- sGodTools->mCurrentHost = host;
+ LLPanelRegionTools* rtool = god_tools->mPanelRegionTools;
+ god_tools->mCurrentHost = host;
// store locally
rtool->setSimName(sim_name);
@@ -319,7 +287,7 @@ void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg)
rtool->setRedirectGridY(redirect_grid_y);
rtool->enableAllWidgets();
- LLPanelObjectTools *otool = sGodTools->mPanelObjectTools;
+ LLPanelObjectTools *otool = god_tools->mPanelObjectTools;
otool->setCheckFlags(region_flags);
otool->enableAllWidgets();
@@ -362,14 +330,17 @@ void LLFloaterGodTools::sendRegionInfoRequest()
void LLFloaterGodTools::sendGodUpdateRegionInfo()
{
+ LLFloaterGodTools* god_tools = LLFloaterReg::getTypedInstance<LLFloaterGodTools>("god_tools");
+ if (!god_tools) return;
+
LLViewerRegion *regionp = gAgent.getRegion();
if (gAgent.isGodlike()
- && sGodTools->mPanelRegionTools
+ && god_tools->mPanelRegionTools
&& regionp
&& gAgent.getRegionHost() == mCurrentHost)
{
LLMessageSystem *msg = gMessageSystem;
- LLPanelRegionTools *rtool = sGodTools->mPanelRegionTools;
+ LLPanelRegionTools *rtool = god_tools->mPanelRegionTools;
msg->newMessage("GodUpdateRegionInfo");
msg->nextBlockFast(_PREHASH_AgentData);
@@ -426,61 +397,34 @@ const F32 PRICE_PER_METER_MIN = 0.f;
const F32 PRICE_PER_METER_MAX = 100.f;
-LLPanelRegionTools::LLPanelRegionTools(const std::string& title)
-: LLPanel(title)
+LLPanelRegionTools::LLPanelRegionTools()
+: LLPanel()
{
+ mCommitCallbackRegistrar.add("RegionTools.ChangeAnything", boost::bind(&LLPanelRegionTools::onChangeAnything, this));
+ mCommitCallbackRegistrar.add("RegionTools.ChangePrelude", boost::bind(&LLPanelRegionTools::onChangePrelude, this));
+ mCommitCallbackRegistrar.add("RegionTools.BakeTerrain", boost::bind(&LLPanelRegionTools::onBakeTerrain, this));
+ mCommitCallbackRegistrar.add("RegionTools.RevertTerrain", boost::bind(&LLPanelRegionTools::onRevertTerrain, this));
+ mCommitCallbackRegistrar.add("RegionTools.SwapTerrain", boost::bind(&LLPanelRegionTools::onSwapTerrain, this));
+ mCommitCallbackRegistrar.add("RegionTools.Refresh", boost::bind(&LLPanelRegionTools::onRefresh, this));
+ mCommitCallbackRegistrar.add("RegionTools.ApplyChanges", boost::bind(&LLPanelRegionTools::onApplyChanges, this));
+ mCommitCallbackRegistrar.add("RegionTools.SelectRegion", boost::bind(&LLPanelRegionTools::onSelectRegion, this));
+ mCommitCallbackRegistrar.add("RegionTools.SaveState", boost::bind(&LLPanelRegionTools::onSaveState, this));
}
BOOL LLPanelRegionTools::postBuild()
{
- childSetCommitCallback("region name", onChangeAnything, this);
- childSetKeystrokeCallback("region name", onChangeSimName, this);
- childSetPrevalidate("region name", &LLLineEditor::prevalidatePrintableNotPipe);
-
- childSetCommitCallback("check prelude", onChangePrelude, this);
- childSetCommitCallback("check fixed sun", onChangeAnything, this);
- childSetCommitCallback("check reset home", onChangeAnything, this);
- childSetCommitCallback("check visible", onChangeAnything, this);
- childSetCommitCallback("check damage", onChangeAnything, this);
- childSetCommitCallback("block dwell", onChangeAnything, this);
- childSetCommitCallback("block terraform", onChangeAnything, this);
- childSetCommitCallback("allow transfer", onChangeAnything, this);
- childSetCommitCallback("is sandbox", onChangeAnything, this);
-
- childSetAction("Bake Terrain", onBakeTerrain, this);
- childSetAction("Revert Terrain", onRevertTerrain, this);
- childSetAction("Swap Terrain", onSwapTerrain, this);
-
- childSetCommitCallback("estate", onChangeAnything, this);
+ getChild<LLLineEditor>("region name")->setKeystrokeCallback(onChangeSimName, this);
+ childSetPrevalidate("region name", &LLLineEditor::prevalidateASCIIPrintableNoPipe);
childSetPrevalidate("estate", &LLLineEditor::prevalidatePositiveS32);
-
- childSetCommitCallback("parentestate", onChangeAnything, this);
childSetPrevalidate("parentestate", &LLLineEditor::prevalidatePositiveS32);
childDisable("parentestate");
-
- childSetCommitCallback("gridposx", onChangeAnything, this);
childSetPrevalidate("gridposx", &LLLineEditor::prevalidatePositiveS32);
childDisable("gridposx");
-
- childSetCommitCallback("gridposy", onChangeAnything, this);
childSetPrevalidate("gridposy", &LLLineEditor::prevalidatePositiveS32);
childDisable("gridposy");
-
- childSetCommitCallback("redirectx", onChangeAnything, this);
+
childSetPrevalidate("redirectx", &LLLineEditor::prevalidatePositiveS32);
-
- childSetCommitCallback("redirecty", onChangeAnything, this);
childSetPrevalidate("redirecty", &LLLineEditor::prevalidatePositiveS32);
-
- childSetCommitCallback("billable factor", onChangeAnything, this);
-
- childSetCommitCallback("land cost", onChangeAnything, this);
-
- childSetAction("Refresh", onRefresh, this);
- childSetAction("Apply", onApplyChanges, this);
-
- childSetAction("Select Region", onSelectRegion, this);
- childSetAction("Autosave now", onSaveState, this);
return TRUE;
}
@@ -567,8 +511,6 @@ void LLPanelRegionTools::enableAllWidgets()
childEnable("Autosave now");
}
-
-// static
void LLPanelRegionTools::onSaveState(void* userdata)
{
if (gAgent.isGodlike())
@@ -765,92 +707,81 @@ void LLPanelRegionTools::setPricePerMeter(S32 price)
childSetValue("land cost", price);
}
-// static
-void LLPanelRegionTools::onChangeAnything(LLUICtrl* ctrl, void* userdata)
+void LLPanelRegionTools::onChangeAnything()
{
- if (sGodTools
- && userdata
- && gAgent.isGodlike())
+ if (gAgent.isGodlike())
{
- LLPanelRegionTools* region_tools = (LLPanelRegionTools*) userdata;
- region_tools->childEnable("Apply");
+ childEnable("Apply");
}
}
-// static
-void LLPanelRegionTools::onChangePrelude(LLUICtrl* ctrl, void* data)
+void LLPanelRegionTools::onChangePrelude()
{
// checking prelude auto-checks fixed sun
- LLPanelRegionTools* self = (LLPanelRegionTools*)data;
- if (self->childGetValue("check prelude").asBoolean())
+ if (childGetValue("check prelude").asBoolean())
{
- self->childSetValue("check fixed sun", TRUE);
- self->childSetValue("check reset home", TRUE);
+ childSetValue("check fixed sun", TRUE);
+ childSetValue("check reset home", TRUE);
+ onChangeAnything();
}
// pass on to default onChange handler
- onChangeAnything(ctrl, data);
+
}
// static
void LLPanelRegionTools::onChangeSimName(LLLineEditor* caller, void* userdata )
{
- if (sGodTools
- && userdata
- && gAgent.isGodlike())
+ if (userdata && gAgent.isGodlike())
{
LLPanelRegionTools* region_tools = (LLPanelRegionTools*) userdata;
region_tools->childEnable("Apply");
}
}
-//static
-void LLPanelRegionTools::onRefresh(void* userdata)
+
+void LLPanelRegionTools::onRefresh()
{
+ LLFloaterGodTools* god_tools = LLFloaterReg::getTypedInstance<LLFloaterGodTools>("god_tools");
+ if(!god_tools) return;
LLViewerRegion *region = gAgent.getRegion();
- if (region
- && sGodTools
- && gAgent.isGodlike())
+ if (region && gAgent.isGodlike())
{
- sGodTools->sendRegionInfoRequest();
+ god_tools->sendRegionInfoRequest();
+ //LLFloaterGodTools::getInstance()->sendRegionInfoRequest();
+ //LLFloaterReg::getTypedInstance<LLFloaterGodTools>("god_tools")->sendRegionInfoRequest();
}
}
-// static
-void LLPanelRegionTools::onApplyChanges(void* userdata)
+void LLPanelRegionTools::onApplyChanges()
{
+ LLFloaterGodTools* god_tools = LLFloaterReg::getTypedInstance<LLFloaterGodTools>("god_tools");
+ if(!god_tools) return;
LLViewerRegion *region = gAgent.getRegion();
- if (region
- && sGodTools
- && userdata
- && gAgent.isGodlike())
+ if (region && gAgent.isGodlike())
{
- LLPanelRegionTools* region_tools = (LLPanelRegionTools*) userdata;
-
- region_tools->childDisable("Apply");
- sGodTools->sendGodUpdateRegionInfo();
+ childDisable("Apply");
+ god_tools->sendGodUpdateRegionInfo();
+ //LLFloaterReg::getTypedInstance<LLFloaterGodTools>("god_tools")->sendGodUpdateRegionInfo();
}
}
-// static
-void LLPanelRegionTools::onBakeTerrain(void *userdata)
+void LLPanelRegionTools::onBakeTerrain()
{
LLPanelRequestTools::sendRequest("terrain", "bake", gAgent.getRegionHost());
}
-// static
-void LLPanelRegionTools::onRevertTerrain(void *userdata)
+void LLPanelRegionTools::onRevertTerrain()
{
LLPanelRequestTools::sendRequest("terrain", "revert", gAgent.getRegionHost());
}
-// static
-void LLPanelRegionTools::onSwapTerrain(void *userdata)
+
+void LLPanelRegionTools::onSwapTerrain()
{
LLPanelRequestTools::sendRequest("terrain", "swap", gAgent.getRegionHost());
}
-// static
-void LLPanelRegionTools::onSelectRegion(void* userdata)
+void LLPanelRegionTools::onSelectRegion()
{
llinfos << "LLPanelRegionTools::onSelectRegion" << llendl;
@@ -890,12 +821,13 @@ void LLPanelRegionTools::onSelectRegion(void* userdata)
// LEFT R2 RIGHT
const F32 HOURS_TO_RADIANS = (2.f*F_PI)/24.f;
-const char FLOATER_GRID_ADMIN_TITLE[] = "Grid Administration";
-LLPanelGridTools::LLPanelGridTools(const std::string& name) :
- LLPanel(name)
+LLPanelGridTools::LLPanelGridTools() :
+ LLPanel()
{
+ mCommitCallbackRegistrar.add("GridTools.KickAll", boost::bind(&LLPanelGridTools::onClickKickAll, this));
+ mCommitCallbackRegistrar.add("GridTools.FlushMapVisibilityCaches", boost::bind(&LLPanelGridTools::onClickFlushMapVisibilityCaches, this));
}
// Destroys the object
@@ -905,9 +837,6 @@ LLPanelGridTools::~LLPanelGridTools()
BOOL LLPanelGridTools::postBuild()
{
- childSetAction("Kick all users", onClickKickAll, this);
- childSetAction("Flush This Region's Map Visibility Caches", onClickFlushMapVisibilityCaches, this);
-
return TRUE;
}
@@ -915,25 +844,19 @@ void LLPanelGridTools::refresh()
{
}
-
-// static
-void LLPanelGridTools::onClickKickAll(void* userdata)
+void LLPanelGridTools::onClickKickAll()
{
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- LLRect rect(left, top, left+400, top-300);
-
- LLNotifications::instance().add("KickAllUsers", LLSD(), LLSD(), LLPanelGridTools::confirmKick);
+ LLNotificationsUtil::add("KickAllUsers", LLSD(), LLSD(), LLPanelGridTools::confirmKick);
}
bool LLPanelGridTools::confirmKick(const LLSD& notification, const LLSD& response)
{
- if (LLNotification::getSelectedOption(notification, response) == 0)
+ if (LLNotificationsUtil::getSelectedOption(notification, response) == 0)
{
LLSD payload;
payload["kick_message"] = response["message"].asString();
- LLNotifications::instance().add("ConfirmKick", LLSD(), payload, LLPanelGridTools::finishKick);
+ LLNotificationsUtil::add("ConfirmKick", LLSD(), payload, LLPanelGridTools::finishKick);
}
return false;
}
@@ -942,7 +865,7 @@ bool LLPanelGridTools::confirmKick(const LLSD& notification, const LLSD& respons
// static
bool LLPanelGridTools::finishKick(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0)
@@ -961,17 +884,15 @@ bool LLPanelGridTools::finishKick(const LLSD& notification, const LLSD& response
return false;
}
-
-// static
-void LLPanelGridTools::onClickFlushMapVisibilityCaches(void* data)
+void LLPanelGridTools::onClickFlushMapVisibilityCaches()
{
- LLNotifications::instance().add("FlushMapVisibilityCaches", LLSD(), LLSD(), flushMapVisibilityCachesConfirm);
+ LLNotificationsUtil::add("FlushMapVisibilityCaches", LLSD(), LLSD(), flushMapVisibilityCachesConfirm);
}
// static
bool LLPanelGridTools::flushMapVisibilityCachesConfirm(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option != 0) return false;
// HACK: Send this as an EstateOwnerRequest so it gets routed
@@ -1017,9 +938,19 @@ bool LLPanelGridTools::flushMapVisibilityCachesConfirm(const LLSD& notification,
// LEFT RIGHT
// Default constructor
-LLPanelObjectTools::LLPanelObjectTools(const std::string& title)
-: LLPanel(title), mTargetAvatar()
+LLPanelObjectTools::LLPanelObjectTools()
+ : LLPanel(),
+ mTargetAvatar()
{
+ mCommitCallbackRegistrar.add("ObjectTools.ChangeAnything", boost::bind(&LLPanelObjectTools::onChangeAnything, this));
+ mCommitCallbackRegistrar.add("ObjectTools.DeletePublicOwnedBy", boost::bind(&LLPanelObjectTools::onClickDeletePublicOwnedBy, this));
+ mCommitCallbackRegistrar.add("ObjectTools.DeleteAllScriptedOwnedBy", boost::bind(&LLPanelObjectTools::onClickDeleteAllScriptedOwnedBy, this));
+ mCommitCallbackRegistrar.add("ObjectTools.DeleteAllOwnedBy", boost::bind(&LLPanelObjectTools::onClickDeleteAllOwnedBy, this));
+ mCommitCallbackRegistrar.add("ObjectTools.ApplyChanges", boost::bind(&LLPanelObjectTools::onApplyChanges, this));
+ mCommitCallbackRegistrar.add("ObjectTools.Set", boost::bind(&LLPanelObjectTools::onClickSet, this));
+ mCommitCallbackRegistrar.add("ObjectTools.GetTopColliders", boost::bind(&LLPanelObjectTools::onGetTopColliders, this));
+ mCommitCallbackRegistrar.add("ObjectTools.GetTopScripts", boost::bind(&LLPanelObjectTools::onGetTopScripts, this));
+ mCommitCallbackRegistrar.add("ObjectTools.GetScriptDigest", boost::bind(&LLPanelObjectTools::onGetScriptDigest, this));
}
// Destroys the object
@@ -1030,22 +961,6 @@ LLPanelObjectTools::~LLPanelObjectTools()
BOOL LLPanelObjectTools::postBuild()
{
- childSetCommitCallback("disable scripts", onChangeAnything, this);
- childSetCommitCallback("disable collisions", onChangeAnything, this);
- childSetCommitCallback("disable physics", onChangeAnything, this);
-
- childSetAction("Apply", onApplyChanges, this);
-
- childSetAction("Set Target", onClickSet, this);
-
- childSetAction("Delete Target's Scripted Objects On Others Land", onClickDeletePublicOwnedBy, this);
- childSetAction("Delete Target's Scripted Objects On *Any* Land", onClickDeleteAllScriptedOwnedBy, this);
- childSetAction("Delete *ALL* Of Target's Objects", onClickDeleteAllOwnedBy, this);
-
- childSetAction("Get Top Colliders", onGetTopColliders, this);
- childSetAction("Get Top Scripts", onGetTopScripts, this);
- childSetAction("Scripts digest", onGetScriptDigest, this);
-
return TRUE;
}
@@ -1054,7 +969,7 @@ void LLPanelObjectTools::setTargetAvatar(const LLUUID &target_id)
mTargetAvatar = target_id;
if (target_id.isNull())
{
- childSetValue("target_avatar_name", "(no target)");
+ childSetValue("target_avatar_name", getString("no_target"));
}
}
@@ -1134,35 +1049,35 @@ void LLPanelObjectTools::enableAllWidgets()
}
-// static
-void LLPanelObjectTools::onGetTopColliders(void* userdata)
+void LLPanelObjectTools::onGetTopColliders()
{
- if (sGodTools
- && gAgent.isGodlike())
+ LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance<LLFloaterTopObjects>("top_objects");
+ if(!instance) return;
+
+ if (gAgent.isGodlike())
{
- LLFloaterTopObjects::show();
+ LLFloaterReg::showInstance("top_objects");
LLFloaterTopObjects::setMode(STAT_REPORT_TOP_COLLIDERS);
- LLFloaterTopObjects::onRefresh(NULL);
+ instance->onRefresh();
}
}
-// static
-void LLPanelObjectTools::onGetTopScripts(void* userdata)
+void LLPanelObjectTools::onGetTopScripts()
{
- if (sGodTools
- && gAgent.isGodlike())
+ LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance<LLFloaterTopObjects>("top_objects");
+ if(!instance) return;
+
+ if (gAgent.isGodlike())
{
- LLFloaterTopObjects::show();
+ LLFloaterReg::showInstance("top_objects");
LLFloaterTopObjects::setMode(STAT_REPORT_TOP_SCRIPTS);
- LLFloaterTopObjects::onRefresh(NULL);
+ instance->onRefresh();
}
}
-// static
-void LLPanelObjectTools::onGetScriptDigest(void* userdata)
+void LLPanelObjectTools::onGetScriptDigest()
{
- if (sGodTools
- && gAgent.isGodlike())
+ if (gAgent.isGodlike())
{
// get the list of scripts and number of occurences of each
// (useful for finding self-replicating objects)
@@ -1170,66 +1085,62 @@ void LLPanelObjectTools::onGetScriptDigest(void* userdata)
}
}
-void LLPanelObjectTools::onClickDeletePublicOwnedBy(void* userdata)
+void LLPanelObjectTools::onClickDeletePublicOwnedBy()
{
// Bring up view-modal dialog
- LLPanelObjectTools* panelp = (LLPanelObjectTools*)userdata;
- if (!panelp->mTargetAvatar.isNull())
+
+ if (!mTargetAvatar.isNull())
{
- panelp->mSimWideDeletesFlags =
+ mSimWideDeletesFlags =
SWD_SCRIPTED_ONLY | SWD_OTHERS_LAND_ONLY;
LLSD args;
- args["AVATAR_NAME"] = panelp->childGetValue("target_avatar_name").asString();
+ args["AVATAR_NAME"] = childGetValue("target_avatar_name").asString();
LLSD payload;
- payload["avatar_id"] = panelp->mTargetAvatar;
- payload["flags"] = (S32)panelp->mSimWideDeletesFlags;
+ payload["avatar_id"] = mTargetAvatar;
+ payload["flags"] = (S32)mSimWideDeletesFlags;
- LLNotifications::instance().add( "GodDeleteAllScriptedPublicObjectsByUser",
+ LLNotificationsUtil::add( "GodDeleteAllScriptedPublicObjectsByUser",
args,
payload,
callbackSimWideDeletes);
}
}
-// static
-void LLPanelObjectTools::onClickDeleteAllScriptedOwnedBy(void* userdata)
+void LLPanelObjectTools::onClickDeleteAllScriptedOwnedBy()
{
// Bring up view-modal dialog
- LLPanelObjectTools* panelp = (LLPanelObjectTools*)userdata;
- if (!panelp->mTargetAvatar.isNull())
+ if (!mTargetAvatar.isNull())
{
- panelp->mSimWideDeletesFlags = SWD_SCRIPTED_ONLY;
+ mSimWideDeletesFlags = SWD_SCRIPTED_ONLY;
LLSD args;
- args["AVATAR_NAME"] = panelp->childGetValue("target_avatar_name").asString();
+ args["AVATAR_NAME"] = childGetValue("target_avatar_name").asString();
LLSD payload;
- payload["avatar_id"] = panelp->mTargetAvatar;
- payload["flags"] = (S32)panelp->mSimWideDeletesFlags;
+ payload["avatar_id"] = mTargetAvatar;
+ payload["flags"] = (S32)mSimWideDeletesFlags;
- LLNotifications::instance().add( "GodDeleteAllScriptedObjectsByUser",
+ LLNotificationsUtil::add( "GodDeleteAllScriptedObjectsByUser",
args,
payload,
callbackSimWideDeletes);
}
}
-// static
-void LLPanelObjectTools::onClickDeleteAllOwnedBy(void* userdata)
+void LLPanelObjectTools::onClickDeleteAllOwnedBy()
{
// Bring up view-modal dialog
- LLPanelObjectTools* panelp = (LLPanelObjectTools*)userdata;
- if (!panelp->mTargetAvatar.isNull())
+ if (!mTargetAvatar.isNull())
{
- panelp->mSimWideDeletesFlags = 0;
+ mSimWideDeletesFlags = 0;
LLSD args;
- args["AVATAR_NAME"] = panelp->childGetValue("target_avatar_name").asString();
+ args["AVATAR_NAME"] = childGetValue("target_avatar_name").asString();
LLSD payload;
- payload["avatar_id"] = panelp->mTargetAvatar;
- payload["flags"] = (S32)panelp->mSimWideDeletesFlags;
+ payload["avatar_id"] = mTargetAvatar;
+ payload["flags"] = (S32)mSimWideDeletesFlags;
- LLNotifications::instance().add( "GodDeleteAllObjectsByUser",
+ LLNotificationsUtil::add( "GodDeleteAllObjectsByUser",
args,
payload,
callbackSimWideDeletes);
@@ -1239,7 +1150,7 @@ void LLPanelObjectTools::onClickDeleteAllOwnedBy(void* userdata)
// static
bool LLPanelObjectTools::callbackSimWideDeletes( const LLSD& notification, const LLSD& response )
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0)
{
if (!notification["payload"]["avatar_id"].asUUID().isNull())
@@ -1251,11 +1162,10 @@ bool LLPanelObjectTools::callbackSimWideDeletes( const LLSD& notification, const
return false;
}
-void LLPanelObjectTools::onClickSet(void* data)
+void LLPanelObjectTools::onClickSet()
{
- LLPanelObjectTools* panelp = (LLPanelObjectTools*) data;
// grandparent is a floater, which can have a dependent
- gFloaterView->getParentFloater(panelp)->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarID, data));
+ gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLPanelObjectTools::callbackAvatarID, this, _1,_2)));
}
void LLPanelObjectTools::onClickSetBySelection(void* data)
@@ -1272,47 +1182,40 @@ void LLPanelObjectTools::onClickSetBySelection(void* data)
LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name);
panelp->mTargetAvatar = owner_id;
- std::string name = "Object " + node->mName + " owned by " + owner_name;
+ LLStringUtil::format_map_t args;
+ args["[OBJECT]"] = node->mName;
+ args["[OWNER]"] = owner_name;
+ std::string name = LLTrans::getString("GodToolsObjectOwnedBy", args);
panelp->childSetValue("target_avatar_name", name);
}
-// static
-void LLPanelObjectTools::callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data)
+void LLPanelObjectTools::callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids)
{
- LLPanelObjectTools* object_tools = (LLPanelObjectTools*) data;
if (ids.empty() || names.empty()) return;
- object_tools->mTargetAvatar = ids[0];
- object_tools->childSetValue("target_avatar_name", names[0]);
- object_tools->refresh();
+ mTargetAvatar = ids[0];
+ childSetValue("target_avatar_name", names[0]);
+ refresh();
}
-
-// static
-void LLPanelObjectTools::onChangeAnything(LLUICtrl* ctrl, void* userdata)
+void LLPanelObjectTools::onChangeAnything()
{
- if (sGodTools
- && userdata
- && gAgent.isGodlike())
+ if (gAgent.isGodlike())
{
- LLPanelObjectTools* object_tools = (LLPanelObjectTools*) userdata;
- object_tools->childEnable("Apply");
+ childEnable("Apply");
}
}
-// static
-void LLPanelObjectTools::onApplyChanges(void* userdata)
+void LLPanelObjectTools::onApplyChanges()
{
+ LLFloaterGodTools* god_tools = LLFloaterReg::getTypedInstance<LLFloaterGodTools>("god_tools");
+ if(!god_tools) return;
LLViewerRegion *region = gAgent.getRegion();
- if (region
- && sGodTools
- && userdata
- && gAgent.isGodlike())
+ if (region && gAgent.isGodlike())
{
- LLPanelObjectTools* object_tools = (LLPanelObjectTools*) userdata;
// TODO -- implement this
-
- object_tools->childDisable("Apply");
- sGodTools->sendGodUpdateRegionInfo();
+ childDisable("Apply");
+ god_tools->sendGodUpdateRegionInfo();
+ //LLFloaterReg::getTypedInstance<LLFloaterGodTools>("god_tools")->sendGodUpdateRegionInfo();
}
}
@@ -1324,9 +1227,10 @@ void LLPanelObjectTools::onApplyChanges(void* userdata)
const std::string SELECTION = "Selection";
const std::string AGENT_REGION = "Agent Region";
-LLPanelRequestTools::LLPanelRequestTools(const std::string& name):
- LLPanel(name)
+LLPanelRequestTools::LLPanelRequestTools():
+ LLPanel()
{
+ mCommitCallbackRegistrar.add("GodTools.Request", boost::bind(&LLPanelRequestTools::onClickRequest, this));
}
LLPanelRequestTools::~LLPanelRequestTools()
@@ -1335,8 +1239,6 @@ LLPanelRequestTools::~LLPanelRequestTools()
BOOL LLPanelRequestTools::postBuild()
{
- childSetAction("Make Request", onClickRequest, this);
-
refresh();
return TRUE;
@@ -1348,9 +1250,13 @@ void LLPanelRequestTools::refresh()
LLCtrlListInterface *list = childGetListInterface("destination");
if (!list) return;
- list->operateOnAll(LLCtrlListInterface::OP_DELETE);
- list->addSimpleElement(SELECTION);
- list->addSimpleElement(AGENT_REGION);
+ S32 last_item = list->getItemCount();
+
+ if (last_item >=3)
+ {
+ list->selectItemRange(2,last_item);
+ list->operateOnSelection(LLCtrlListInterface::OP_DELETE);
+ }
for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
{
@@ -1367,7 +1273,7 @@ void LLPanelRequestTools::refresh()
}
else
{
- list->selectByValue(SELECTION);
+ list->operateOnSelection(LLCtrlListInterface::OP_DESELECT);
}
}
@@ -1393,21 +1299,19 @@ void LLPanelRequestTools::sendRequest(const std::string& request,
msg->sendReliable(host);
}
-// static
-void LLPanelRequestTools::onClickRequest(void* data)
+void LLPanelRequestTools::onClickRequest()
{
- LLPanelRequestTools* self = (LLPanelRequestTools*)data;
- const std::string dest = self->childGetValue("destination").asString();
+ const std::string dest = childGetValue("destination").asString();
if(dest == SELECTION)
{
- std::string req = self->childGetValue("request");
+ std::string req =childGetValue("request");
req = req.substr(0, req.find_first_of(" "));
- std::string param = self->childGetValue("parameter");
+ std::string param = childGetValue("parameter");
LLSelectMgr::getInstance()->sendGodlikeRequest(req, param);
}
else if(dest == AGENT_REGION)
{
- self->sendRequest(gAgent.getRegionHost());
+ sendRequest(gAgent.getRegionHost());
}
else
{
@@ -1419,7 +1323,7 @@ void LLPanelRequestTools::onClickRequest(void* data)
if(dest == regionp->getName())
{
// found it
- self->sendRequest(regionp->getHost());
+ sendRequest(regionp->getHost());
}
}
}
@@ -1427,7 +1331,7 @@ void LLPanelRequestTools::onClickRequest(void* data)
void terrain_download_done(void** data, S32 status, LLExtStat ext_status)
{
- LLNotifications::instance().add("TerrainDownloaded");
+ LLNotificationsUtil::add("TerrainDownloaded");
}
diff --git a/indra/newview/llfloatergodtools.h b/indra/newview/llfloatergodtools.h
index 75813ca886..ef5ce02749 100644
--- a/indra/newview/llfloatergodtools.h
+++ b/indra/newview/llfloatergodtools.h
@@ -57,12 +57,11 @@ class LLTextBox;
class LLMessageSystem;
class LLFloaterGodTools
-: public LLFloater
+ : public LLFloater
{
+ friend class LLFloaterReg;
public:
- static LLFloaterGodTools* instance();
-
enum EGodPanel
{
PANEL_GRID,
@@ -72,9 +71,6 @@ public:
PANEL_COUNT
};
- static void show(void *);
- static void hide(void *);
-
static void* createPanelGrid(void *userdata);
static void* createPanelRegion(void *userdata);
static void* createPanelObjects(void *userdata);
@@ -84,7 +80,7 @@ public:
void showPanel(const std::string& panel_name);
- virtual void onClose(bool app_quitting);
+ virtual void onOpen(const LLSD& key);
virtual void draw();
@@ -101,21 +97,21 @@ public:
// Send possibly changed values to simulator.
void sendGodUpdateRegionInfo();
- static void onTabChanged(void *data, bool from_click);
-
+private:
+
+ LLFloaterGodTools(const LLSD& key);
+ ~LLFloaterGodTools();
+
protected:
U32 computeRegionFlags() const;
protected:
- LLFloaterGodTools();
- ~LLFloaterGodTools();
+ /*virtual*/ BOOL postBuild();
// When the floater is going away, reset any options that need to be
// cleared.
void resetToolState();
- static LLFloaterGodTools* sInstance;
-
public:
LLPanelRegionTools *mPanelRegionTools;
LLPanelObjectTools *mPanelObjectTools;
@@ -133,23 +129,24 @@ class LLPanelRegionTools
: public LLPanel
{
public:
- LLPanelRegionTools(const std::string& name);
+ LLPanelRegionTools();
/*virtual*/ ~LLPanelRegionTools();
BOOL postBuild();
/*virtual*/ void refresh();
- static void onSaveState(void* data);
- static void onChangeAnything(LLUICtrl* ctrl, void* userdata);
- static void onChangePrelude(LLUICtrl* ctrl, void* data);
+ static void onSaveState(void* userdata);
static void onChangeSimName(LLLineEditor* caller, void* userdata);
- static void onApplyChanges(void* userdata);
- static void onBakeTerrain(void *userdata);
- static void onRevertTerrain(void *userdata);
- static void onSwapTerrain(void *userdata);
- static void onSelectRegion(void *userdata);
- static void onRefresh(void* userdata);
+
+ void onChangeAnything();
+ void onChangePrelude();
+ void onApplyChanges();
+ void onBakeTerrain();
+ void onRevertTerrain();
+ void onSwapTerrain();
+ void onSelectRegion();
+ void onRefresh();
// set internal checkboxes/spinners/combos
const std::string getSimName() const;
@@ -194,18 +191,18 @@ class LLPanelGridTools
: public LLPanel
{
public:
- LLPanelGridTools(const std::string& name);
+ LLPanelGridTools();
virtual ~LLPanelGridTools();
BOOL postBuild();
void refresh();
- static void onClickKickAll(void *data);
+ void onClickKickAll();
static bool confirmKick(const LLSD& notification, const LLSD& response);
static bool finishKick(const LLSD& notification, const LLSD& response);
static void onDragSunPhase(LLUICtrl *ctrl, void *userdata);
- static void onClickFlushMapVisibilityCaches(void* data);
+ void onClickFlushMapVisibilityCaches();
static bool flushMapVisibilityCachesConfirm(const LLSD& notification, const LLSD& response);
protected:
@@ -221,7 +218,7 @@ class LLPanelObjectTools
: public LLPanel
{
public:
- LLPanelObjectTools(const std::string& name);
+ LLPanelObjectTools();
/*virtual*/ ~LLPanelObjectTools();
BOOL postBuild();
@@ -234,17 +231,17 @@ public:
void enableAllWidgets();
void setCheckFlags(U32 flags);
- static void onChangeAnything(LLUICtrl* ctrl, void* data);
- static void onApplyChanges(void* data);
- static void onClickSet(void* data);
- static void callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data);
- static void onClickDeletePublicOwnedBy(void* data);
- static void onClickDeleteAllScriptedOwnedBy(void* data);
- static void onClickDeleteAllOwnedBy(void* data);
+ void onChangeAnything();
+ void onApplyChanges();
+ void onClickSet();
+ void callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids);
+ void onClickDeletePublicOwnedBy();
+ void onClickDeleteAllScriptedOwnedBy();
+ void onClickDeleteAllOwnedBy();
static bool callbackSimWideDeletes(const LLSD& notification, const LLSD& response);
- static void onGetTopColliders(void* data);
- static void onGetTopScripts(void* data);
- static void onGetScriptDigest(void* data);
+ void onGetTopColliders();
+ void onGetTopScripts();
+ void onGetScriptDigest();
static void onClickSetBySelection(void* data);
protected:
@@ -262,7 +259,7 @@ protected:
class LLPanelRequestTools : public LLPanel
{
public:
- LLPanelRequestTools(const std::string& name);
+ LLPanelRequestTools();
/*virtual*/ ~LLPanelRequestTools();
BOOL postBuild();
@@ -274,7 +271,7 @@ public:
const LLHost& host);
protected:
- static void onClickRequest(void *data);
+ void onClickRequest();
void sendRequest(const LLHost& host);
};
diff --git a/indra/newview/llfloatergroupinvite.cpp b/indra/newview/llfloatergroupinvite.cpp
index 08a6269a04..bf484c6343 100644
--- a/indra/newview/llfloatergroupinvite.cpp
+++ b/indra/newview/llfloatergroupinvite.cpp
@@ -34,9 +34,8 @@
#include "llfloatergroupinvite.h"
#include "llpanelgroupinvite.h"
-
-const char FLOATER_TITLE[] = "Group Invitation";
-const LLRect FGI_RECT(0, 380, 210, 0);
+#include "lltrans.h"
+#include "lldraghandle.h"
class LLFloaterGroupInvite::impl
{
@@ -73,25 +72,26 @@ void LLFloaterGroupInvite::impl::closeFloater(void* data)
{
LLFloaterGroupInvite* floaterp = (LLFloaterGroupInvite*) data;
- if ( floaterp ) floaterp->close();
+ if ( floaterp ) floaterp->closeFloater();
}
//-----------------------------------------------------------------------------
// Implementation
//-----------------------------------------------------------------------------
-LLFloaterGroupInvite::LLFloaterGroupInvite(const std::string& name,
- const LLRect &rect,
- const std::string& title,
- const LLUUID& group_id)
-: LLFloater(name, rect, title)
+LLFloaterGroupInvite::LLFloaterGroupInvite(const LLUUID& group_id)
+: LLFloater(group_id)
{
- LLRect contents(getRect());
- contents.mTop -= LLFLOATER_HEADER_SIZE;
+ S32 floater_header_size = getHeaderHeight();
+ LLRect contents;
mImpl = new impl(group_id);
- mImpl->mInvitePanelp = new LLPanelGroupInvite("Group Invite Panel",
- group_id);
+ mImpl->mInvitePanelp = new LLPanelGroupInvite(group_id);
+
+ contents = mImpl->mInvitePanelp->getRect();
+ contents.mTop -= floater_header_size;
+
+ setTitle (mImpl->mInvitePanelp->getString("GroupInvitation"));
mImpl->mInvitePanelp->setCloseCallback(impl::closeFloater, this);
@@ -114,6 +114,10 @@ LLFloaterGroupInvite::~LLFloaterGroupInvite()
// static
void LLFloaterGroupInvite::showForGroup(const LLUUID& group_id, std::vector<LLUUID> *agent_ids)
{
+ const LLFloater::Params& floater_params = LLFloater::getDefaultParams();
+ S32 floater_header_size = floater_params.header_height;
+ LLRect contents;
+
// Make sure group_id isn't null
if (group_id.isNull())
{
@@ -127,10 +131,12 @@ void LLFloaterGroupInvite::showForGroup(const LLUUID& group_id, std::vector<LLUU
(LLFloaterGroupInvite*)NULL);
if (!fgi)
{
- fgi = new LLFloaterGroupInvite("groupinfo",
- FGI_RECT,
- FLOATER_TITLE,
- group_id);
+ fgi = new LLFloaterGroupInvite(group_id);
+ contents = fgi->mImpl->mInvitePanelp->getRect();
+ contents.mTop += floater_header_size;
+ fgi->setRect(contents);
+ fgi->getDragHandle()->setRect(contents);
+ fgi->getDragHandle()->setTitle(fgi->mImpl->mInvitePanelp->getString("GroupInvitation"));
impl::sInstances[group_id] = fgi;
@@ -143,6 +149,6 @@ void LLFloaterGroupInvite::showForGroup(const LLUUID& group_id, std::vector<LLUU
}
fgi->center();
- fgi->open(); /*Flawfinder: ignore*/
+ fgi->openFloater();
fgi->mImpl->mInvitePanelp->update();
}
diff --git a/indra/newview/llfloatergroupinvite.h b/indra/newview/llfloatergroupinvite.h
index d1485ead91..b3f5d75ac1 100644
--- a/indra/newview/llfloatergroupinvite.h
+++ b/indra/newview/llfloatergroupinvite.h
@@ -46,10 +46,7 @@ public:
static void showForGroup(const LLUUID &group_id, std::vector<LLUUID> *agent_ids = NULL);
protected:
- LLFloaterGroupInvite(const std::string& name,
- const LLRect &rect,
- const std::string& title,
- const LLUUID& group_id = LLUUID::null);
+ LLFloaterGroupInvite(const LLUUID& group_id = LLUUID::null);
class impl;
impl* mImpl;
diff --git a/indra/newview/llfloatergroups.cpp b/indra/newview/llfloatergroups.cpp
index 8cd7297447..c71764c2e5 100644
--- a/indra/newview/llfloatergroups.cpp
+++ b/indra/newview/llfloatergroups.cpp
@@ -41,24 +41,17 @@
#include "llfloatergroups.h"
-#include "message.h"
#include "roles_constants.h"
#include "llagent.h"
#include "llbutton.h"
-#include "llfloatergroupinfo.h"
-#include "llfloaterdirectory.h"
-#include "llfocusmgr.h"
-#include "llalertdialog.h"
-#include "llselectmgr.h"
+#include "llgroupactions.h"
#include "llscrolllistctrl.h"
#include "lltextbox.h"
#include "lluictrlfactory.h"
-#include "llviewerwindow.h"
-#include "llimview.h"
+#include "lltrans.h"
-// static
-std::map<const LLUUID, LLFloaterGroupPicker*> LLFloaterGroupPicker::sInstances;
+using namespace LLOldEvents;
// helper functions
void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id, U64 powers_mask = GP_ALL_POWERS);
@@ -67,56 +60,35 @@ void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id, U64 pow
/// Class LLFloaterGroupPicker
///----------------------------------------------------------------------------
-// static
-LLFloaterGroupPicker* LLFloaterGroupPicker::findInstance(const LLSD& seed)
+LLFloaterGroupPicker::LLFloaterGroupPicker(const LLSD& seed)
+: LLFloater(seed),
+ mPowersMask(GP_ALL_POWERS),
+ mID(seed.asUUID())
{
- instance_map_t::iterator found_it = sInstances.find(seed.asUUID());
- if (found_it != sInstances.end())
- {
- return found_it->second;
- }
- return NULL;
-}
-
-// static
-LLFloaterGroupPicker* LLFloaterGroupPicker::createInstance(const LLSD &seed)
-{
- LLFloaterGroupPicker* pickerp = new LLFloaterGroupPicker(seed);
- LLUICtrlFactory::getInstance()->buildFloater(pickerp, "floater_choose_group.xml");
- return pickerp;
-}
-
-LLFloaterGroupPicker::LLFloaterGroupPicker(const LLSD& seed) :
- mSelectCallback(NULL),
- mCallbackUserdata(NULL),
- mPowersMask(GP_ALL_POWERS)
-{
- mID = seed.asUUID();
- sInstances.insert(std::make_pair(mID, this));
+// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_choose_group.xml");
}
LLFloaterGroupPicker::~LLFloaterGroupPicker()
{
- sInstances.erase(mID);
-}
-
-void LLFloaterGroupPicker::setSelectCallback(void (*callback)(LLUUID, void*),
- void* userdata)
-{
- mSelectCallback = callback;
- mCallbackUserdata = userdata;
}
void LLFloaterGroupPicker::setPowersMask(U64 powers_mask)
{
mPowersMask = powers_mask;
- postBuild();
+ init_group_list(getChild<LLScrollListCtrl>("group list"), gAgent.getGroupID(), mPowersMask);
}
BOOL LLFloaterGroupPicker::postBuild()
{
- init_group_list(getChild<LLScrollListCtrl>("group list"), gAgent.getGroupID(), mPowersMask);
+ LLScrollListCtrl* list_ctrl = getChild<LLScrollListCtrl>("group list");
+ if (list_ctrl)
+ {
+ init_group_list(list_ctrl, gAgent.getGroupID(), mPowersMask);
+ list_ctrl->setDoubleClickCallback(onBtnOK, this);
+ list_ctrl->setContextMenu(LLScrollListCtrl::MENU_GROUP);
+ }
+
childSetAction("OK", onBtnOK, this);
@@ -124,14 +96,25 @@ BOOL LLFloaterGroupPicker::postBuild()
setDefaultBtn("OK");
- childSetDoubleClickCallback("group list", onBtnOK);
- childSetUserData("group list", this);
-
childEnable("OK");
return TRUE;
}
+void LLFloaterGroupPicker::removeNoneOption()
+{
+ // Remove group "none" from list. Group "none" is added in init_group_list().
+ // Some UI elements use group "none", we need to manually delete it here.
+ // Group "none" ID is LLUUID:null.
+ LLCtrlListInterface* group_list = getChild<LLScrollListCtrl>("group list")->getListInterface();
+ if(group_list)
+ {
+ group_list->selectByValue(LLUUID::null);
+ group_list->operateOnSelection(LLCtrlListInterface::OP_DELETE);
+ }
+}
+
+
void LLFloaterGroupPicker::onBtnOK(void* userdata)
{
LLFloaterGroupPicker* self = (LLFloaterGroupPicker*)userdata;
@@ -141,7 +124,7 @@ void LLFloaterGroupPicker::onBtnOK(void* userdata)
void LLFloaterGroupPicker::onBtnCancel(void* userdata)
{
LLFloaterGroupPicker* self = (LLFloaterGroupPicker*)userdata;
- if(self) self->close();
+ if(self) self->closeFloater();
}
@@ -153,12 +136,9 @@ void LLFloaterGroupPicker::ok()
{
group_id = group_list->getCurrentID();
}
- if(mSelectCallback)
- {
- mSelectCallback(group_id, mCallbackUserdata);
- }
+ mGroupSelectSignal(group_id);
- close();
+ closeFloater();
}
///----------------------------------------------------------------------------
@@ -211,7 +191,13 @@ BOOL LLPanelGroups::postBuild()
childSetTextArg("groupcount", "[COUNT]", llformat("%d",gAgent.mGroups.count()));
childSetTextArg("groupcount", "[MAX]", llformat("%d",MAX_AGENT_GROUPS));
- init_group_list(getChild<LLScrollListCtrl>("group list"), gAgent.getGroupID());
+ LLScrollListCtrl *list = getChild<LLScrollListCtrl>("group list");
+ if (list)
+ {
+ init_group_list(list, gAgent.getGroupID());
+ list->setDoubleClickCallback(onBtnIM, this);
+ list->setContextMenu(LLScrollListCtrl::MENU_GROUP);
+ }
childSetAction("Activate", onBtnActivate, this);
@@ -227,9 +213,6 @@ BOOL LLPanelGroups::postBuild()
setDefaultBtn("IM");
- childSetDoubleClickCallback("group list", onBtnIM);
- childSetUserData("group list", this);
-
reset();
return TRUE;
@@ -264,14 +247,7 @@ void LLPanelGroups::enableButtons()
childDisable("IM");
childDisable("Leave");
}
- if(gAgent.mGroups.count() < MAX_AGENT_GROUPS)
- {
- childEnable("Create");
- }
- else
- {
- childDisable("Create");
- }
+ childSetEnabled("Create", gAgent.canJoinGroups());
}
@@ -313,113 +289,54 @@ void LLPanelGroups::onBtnSearch(void* userdata)
void LLPanelGroups::create()
{
- llinfos << "LLPanelGroups::create" << llendl;
- LLFloaterGroupInfo::showCreateGroup(NULL);
+ LLGroupActions::createGroup();
}
void LLPanelGroups::activate()
{
- llinfos << "LLPanelGroups::activate" << llendl;
LLCtrlListInterface *group_list = childGetListInterface("group list");
LLUUID group_id;
if (group_list)
{
group_id = group_list->getCurrentID();
}
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_ActivateGroup);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->addUUIDFast(_PREHASH_GroupID, group_id);
- gAgent.sendReliableMessage();
+ LLGroupActions::activate(group_id);
}
void LLPanelGroups::info()
{
- llinfos << "LLPanelGroups::info" << llendl;
LLCtrlListInterface *group_list = childGetListInterface("group list");
LLUUID group_id;
if (group_list && (group_id = group_list->getCurrentID()).notNull())
{
- LLFloaterGroupInfo::showFromUUID(group_id);
+ LLGroupActions::show(group_id);
}
}
void LLPanelGroups::startIM()
{
- //llinfos << "LLPanelFriends::onClickIM()" << llendl;
LLCtrlListInterface *group_list = childGetListInterface("group list");
LLUUID group_id;
if (group_list && (group_id = group_list->getCurrentID()).notNull())
{
- LLGroupData group_data;
- if (gAgent.getGroupData(group_id, group_data))
- {
- gIMMgr->setFloaterOpen(TRUE);
- gIMMgr->addSession(
- group_data.mName,
- IM_SESSION_GROUP_START,
- group_id);
- make_ui_sound("UISndStartIM");
- }
- else
- {
- // this should never happen, as starting a group IM session
- // relies on you belonging to the group and hence having the group data
- make_ui_sound("UISndInvalidOp");
- }
+ LLGroupActions::startIM(group_id);
}
}
void LLPanelGroups::leave()
{
- llinfos << "LLPanelGroups::leave" << llendl;
LLCtrlListInterface *group_list = childGetListInterface("group list");
LLUUID group_id;
if (group_list && (group_id = group_list->getCurrentID()).notNull())
{
- S32 count = gAgent.mGroups.count();
- S32 i;
- for(i = 0; i < count; ++i)
- {
- if(gAgent.mGroups.get(i).mID == group_id)
- break;
- }
- if(i < count)
- {
- LLSD args;
- args["GROUP"] = gAgent.mGroups.get(i).mName;
- LLSD payload;
- payload["group_id"] = group_id;
- LLNotifications::instance().add("GroupLeaveConfirmMember", args, payload, callbackLeaveGroup);
- }
+ LLGroupActions::leave(group_id);
}
}
void LLPanelGroups::search()
{
- LLFloaterDirectory::showGroups();
-}
-
-// static
-bool LLPanelGroups::callbackLeaveGroup(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotification::getSelectedOption(notification, response);
- LLUUID group_id = notification["payload"]["group_id"].asUUID();
- if(option == 0)
- {
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_LeaveGroupRequest);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_GroupData);
- msg->addUUIDFast(_PREHASH_GroupID, group_id);
- gAgent.sendReliableMessage();
- }
- return false;
+ LLGroupActions::search();
}
void LLPanelGroups::onGroupList(LLUICtrl* ctrl, void* userdata)
@@ -453,8 +370,8 @@ void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id, U64 pow
element["id"] = id;
element["columns"][0]["column"] = "name";
element["columns"][0]["value"] = group_datap->mName;
- element["columns"][0]["font"] = "SANSSERIF";
- element["columns"][0]["font-style"] = style;
+ element["columns"][0]["font"]["name"] = "SANSSERIF";
+ element["columns"][0]["font"]["style"] = style;
group_list->addElement(element, ADD_SORTED);
}
@@ -470,9 +387,9 @@ void init_group_list(LLScrollListCtrl* ctrl, const LLUUID& highlight_id, U64 pow
LLSD element;
element["id"] = LLUUID::null;
element["columns"][0]["column"] = "name";
- element["columns"][0]["value"] = "none"; // *TODO: Translate
- element["columns"][0]["font"] = "SANSSERIF";
- element["columns"][0]["font-style"] = style;
+ element["columns"][0]["value"] = LLTrans::getString("GroupsNone");
+ element["columns"][0]["font"]["name"] = "SANSSERIF";
+ element["columns"][0]["font"]["style"] = style;
group_list->addElement(element, ADD_TOP);
}
diff --git a/indra/newview/llfloatergroups.h b/indra/newview/llfloatergroups.h
index da1c4e23dd..ce3a470a23 100644
--- a/indra/newview/llfloatergroups.h
+++ b/indra/newview/llfloatergroups.h
@@ -47,6 +47,8 @@
#include "lluuid.h"
#include "llfloater.h"
#include <map>
+#include <boost/function.hpp>
+#include <boost/signals2.hpp>
class LLUICtrl;
class LLTextBox;
@@ -54,13 +56,15 @@ class LLScrollListCtrl;
class LLButton;
class LLFloaterGroupPicker;
-class LLFloaterGroupPicker : public LLFloater, public LLUIFactory<LLFloaterGroupPicker, LLFloaterGroupPicker, VisibilityPolicy<LLFloater> >
+class LLFloaterGroupPicker : public LLFloater
{
- friend class LLUIFactory<LLFloaterGroupPicker>;
public:
+ LLFloaterGroupPicker(const LLSD& seed);
~LLFloaterGroupPicker();
- void setSelectCallback( void (*callback)(LLUUID, void*),
- void* userdata);
+
+ // Note: Don't return connection; use boost::bind + boost::signals2::trackable to disconnect slots
+ typedef boost::signals2::signal<void (LLUUID id)> signal_t;
+ void setSelectGroupCallback(const signal_t::slot_type& cb) { mGroupSelectSignal.connect(cb); }
void setPowersMask(U64 powers_mask);
BOOL postBuild();
@@ -68,8 +72,10 @@ public:
static LLFloaterGroupPicker* findInstance(const LLSD& seed);
static LLFloaterGroupPicker* createInstance(const LLSD& seed);
+ // for cases like inviting avatar to group we don't want the none option
+ void removeNoneOption();
+
protected:
- LLFloaterGroupPicker(const LLSD& seed);
void ok();
static void onBtnOK(void* userdata);
static void onBtnCancel(void* userdata);
@@ -77,21 +83,20 @@ protected:
protected:
LLUUID mID;
U64 mPowersMask;
- void (*mSelectCallback)(LLUUID id, void* userdata);
- void* mCallbackUserdata;
+ signal_t mGroupSelectSignal;
typedef std::map<const LLUUID, LLFloaterGroupPicker*> instance_map_t;
static instance_map_t sInstances;
};
-class LLPanelGroups : public LLPanel, public LLSimpleListener
+class LLPanelGroups : public LLPanel, public LLOldEvents::LLSimpleListener
{
public:
LLPanelGroups();
virtual ~LLPanelGroups();
//LLEventListener
- /*virtual*/ bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata);
+ /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
// clear the group list, and get a fresh set of info.
void reset();
diff --git a/indra/newview/llfloaterhandler.cpp b/indra/newview/llfloaterhandler.cpp
index f4c7e43a7d..e50a09ed86 100644
--- a/indra/newview/llfloaterhandler.cpp
+++ b/indra/newview/llfloaterhandler.cpp
@@ -31,7 +31,7 @@
#include "llfloaterhandler.h"
#include "llfloater.h"
-#include "llwebbrowserctrl.h"
+#include "llmediactrl.h"
// register with dispatch via global object
LLFloaterHandler gFloaterHandler;
@@ -54,7 +54,7 @@ LLFloater* get_parent_floater(LLView* view)
}
-bool LLFloaterHandler::handle(const LLSD &params, const LLSD &query_map, LLWebBrowserCtrl *web)
+bool LLFloaterHandler::handle(const LLSD &params, const LLSD &query_map, LLMediaCtrl *web)
{
if (params.size() < 2) return false;
LLFloater* floater = NULL;
@@ -70,7 +70,7 @@ bool LLFloaterHandler::handle(const LLSD &params, const LLSD &query_map, LLWebBr
{
if (floater)
{
- floater->close();
+ floater->closeFloater();
return true;
}
}
diff --git a/indra/newview/llfloaterhandler.h b/indra/newview/llfloaterhandler.h
index b08f1f35b4..cd9d8b5377 100644
--- a/indra/newview/llfloaterhandler.h
+++ b/indra/newview/llfloaterhandler.h
@@ -38,8 +38,8 @@ class LLFloaterHandler
: public LLCommandHandler
{
public:
- LLFloaterHandler() : LLCommandHandler("floater", true) { }
- bool handle(const LLSD& params, const LLSD& query_map, LLWebBrowserCtrl* web);
+ LLFloaterHandler() : LLCommandHandler("floater", UNTRUSTED_BLOCK) { }
+ bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web);
};
#endif
diff --git a/indra/newview/llfloaterhardwaresettings.cpp b/indra/newview/llfloaterhardwaresettings.cpp
index 7886e394a3..31b494b590 100644
--- a/indra/newview/llfloaterhardwaresettings.cpp
+++ b/indra/newview/llfloaterhardwaresettings.cpp
@@ -33,39 +33,32 @@
#include "llviewerprecompiledheaders.h"
#include "llfloaterhardwaresettings.h"
+
+// Viewer includes
#include "llfloaterpreference.h"
#include "llviewerwindow.h"
#include "llviewercontrol.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llfeaturemanager.h"
#include "llstartup.h"
+#include "pipeline.h"
+// Linden library includes
#include "llradiogroup.h"
#include "lluictrlfactory.h"
+#include "llwindow.h"
+#include "llsliderctrl.h"
-#include "llimagegl.h"
-#include "pipeline.h"
-
-LLFloaterHardwareSettings* LLFloaterHardwareSettings::sHardwareSettings = NULL;
-
-LLFloaterHardwareSettings::LLFloaterHardwareSettings() : LLFloater(std::string("Hardware Settings Floater"))
+LLFloaterHardwareSettings::LLFloaterHardwareSettings(const LLSD& key)
+ : LLFloater(key)
{
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_hardware_settings.xml");
-
- // load it up
- initCallbacks();
+ //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_hardware_settings.xml");
}
LLFloaterHardwareSettings::~LLFloaterHardwareSettings()
{
}
-void LLFloaterHardwareSettings::onClickHelp(void* data)
-{
- const char* xml_alert = "HardwareSettingsHelpButton";
- LLNotifications::instance().add(xml_alert);
-}
-
void LLFloaterHardwareSettings::initCallbacks(void)
{
}
@@ -90,10 +83,10 @@ void LLFloaterHardwareSettings::refresh()
void LLFloaterHardwareSettings::refreshEnabledState()
{
- S32 min_tex_mem = LLViewerImageList::getMinVideoRamSetting();
- S32 max_tex_mem = LLViewerImageList::getMaxVideoRamSetting();
- childSetMinValue("GrapicsCardTextureMemory", min_tex_mem);
- childSetMaxValue("GrapicsCardTextureMemory", max_tex_mem);
+ S32 min_tex_mem = LLViewerTextureList::getMinVideoRamSetting();
+ S32 max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting();
+ getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMinValue(min_tex_mem);
+ getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMaxValue(max_tex_mem);
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") ||
!gGLManager.mHasVertexBufferObject)
@@ -108,48 +101,6 @@ void LLFloaterHardwareSettings::refreshEnabledState()
}
-// static instance of it
-LLFloaterHardwareSettings* LLFloaterHardwareSettings::instance()
-{
- if (!sHardwareSettings)
- {
- sHardwareSettings = new LLFloaterHardwareSettings();
- sHardwareSettings->close();
- }
- return sHardwareSettings;
-}
-void LLFloaterHardwareSettings::show()
-{
- LLFloaterHardwareSettings* hardSettings = instance();
- hardSettings->refresh();
- hardSettings->center();
-
- // comment in if you want the menu to rebuild each time
- //LLUICtrlFactory::getInstance()->buildFloater(hardSettings, "floater_hardware_settings.xml");
- //hardSettings->initCallbacks();
-
- hardSettings->open();
-}
-
-bool LLFloaterHardwareSettings::isOpen()
-{
- if (sHardwareSettings != NULL)
- {
- return true;
- }
- return false;
-}
-
-// virtual
-void LLFloaterHardwareSettings::onClose(bool app_quitting)
-{
- if (sHardwareSettings)
- {
- sHardwareSettings->setVisible(FALSE);
- }
-}
-
-
//============================================================================
BOOL LLFloaterHardwareSettings::postBuild()
@@ -157,7 +108,10 @@ BOOL LLFloaterHardwareSettings::postBuild()
childSetAction("OK", onBtnOK, this);
refresh();
+ center();
+ // load it up
+ initCallbacks();
return TRUE;
}
@@ -203,7 +157,7 @@ void LLFloaterHardwareSettings::cancel()
gSavedSettings.setF32("RenderFogRatio", mFogRatio);
gSavedSettings.setBOOL("ProbeHardwareOnStartup", mProbeHardwareOnStartup );
- close();
+ closeFloater();
}
// static
@@ -211,6 +165,7 @@ void LLFloaterHardwareSettings::onBtnOK( void* userdata )
{
LLFloaterHardwareSettings *fp =(LLFloaterHardwareSettings *)userdata;
fp->apply();
- fp->close(false);
+ fp->closeFloater(false);
}
+
diff --git a/indra/newview/llfloaterhardwaresettings.h b/indra/newview/llfloaterhardwaresettings.h
index 04a33f69dc..ef0b0c905e 100644
--- a/indra/newview/llfloaterhardwaresettings.h
+++ b/indra/newview/llfloaterhardwaresettings.h
@@ -35,29 +35,21 @@
#include "llfloater.h"
-class LLSliderCtrl;
-
/// Menuing system for all of windlight's functionality
class LLFloaterHardwareSettings : public LLFloater
{
- friend class LLPreferenceCore;
+ friend class LLFloaterPreference;
public:
- LLFloaterHardwareSettings();
- virtual ~LLFloaterHardwareSettings();
+ LLFloaterHardwareSettings(const LLSD& key);
+ /*virtual*/ ~LLFloaterHardwareSettings();
- virtual BOOL postBuild();
+ /*virtual*/ BOOL postBuild();
/// initialize all the callbacks for the menu
void initCallbacks(void);
- /// one and one instance only
- static LLFloaterHardwareSettings* instance();
-
- /// callback for the menus help button
- static void onClickHelp(void* data);
-
/// OK button
static void onBtnOK( void* userdata );
@@ -69,9 +61,6 @@ public:
/// return if the menu exists or not
static bool isOpen();
- /// stuff to do on exit
- virtual void onClose(bool app_quitting);
-
/// sync up menu with parameters
void refresh();
@@ -85,8 +74,6 @@ public:
void refreshEnabledState();
protected:
- LLSliderCtrl* mCtrlVideoCardMem;
-
BOOL mUseVBO;
BOOL mUseAniso;
U32 mFSAASamples;
@@ -96,8 +83,6 @@ protected:
BOOL mProbeHardwareOnStartup;
private:
- // one instance on the inside
- static LLFloaterHardwareSettings* sHardwareSettings;
};
#endif
diff --git a/indra/newview/llfloaterhelpbrowser.cpp b/indra/newview/llfloaterhelpbrowser.cpp
new file mode 100644
index 0000000000..2e0ae3265e
--- /dev/null
+++ b/indra/newview/llfloaterhelpbrowser.cpp
@@ -0,0 +1,141 @@
+/**
+ * @file llfloaterhelpbrowser.cpp
+ * @brief HTML Help floater - uses embedded web browser control
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ *
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterhelpbrowser.h"
+
+#include "llfloaterreg.h"
+#include "llpluginclassmedia.h"
+#include "llmediactrl.h"
+#include "llviewerwindow.h"
+#include "llviewercontrol.h"
+#include "llweb.h"
+#include "llui.h"
+
+#include "llurlhistory.h"
+#include "llmediactrl.h"
+#include "llviewermedia.h"
+
+
+LLFloaterHelpBrowser::LLFloaterHelpBrowser(const LLSD& key)
+ : LLFloater(key)
+{
+}
+
+BOOL LLFloaterHelpBrowser::postBuild()
+{
+ mBrowser = getChild<LLMediaCtrl>("browser");
+ mBrowser->addObserver(this);
+
+ childSetAction("open_browser", onClickOpenWebBrowser, this);
+
+ buildURLHistory();
+ return TRUE;
+}
+
+void LLFloaterHelpBrowser::buildURLHistory()
+{
+ // Get all of the entries in the "browser" collection
+ LLSD browser_history = LLURLHistory::getURLHistory("browser");
+
+ // initialize URL history in the plugin
+ LLPluginClassMedia *plugin = mBrowser->getMediaPlugin();
+ if (plugin)
+ {
+ plugin->initializeUrlHistory(browser_history);
+ }
+}
+
+//virtual
+void LLFloaterHelpBrowser::onClose(bool app_quitting)
+{
+ // really really destroy the help browser when it's closed, it'll be recreated.
+ destroy(); // really destroy this dialog on closure, it's relatively heavyweight.
+}
+
+void LLFloaterHelpBrowser::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
+{
+ if(event == MEDIA_EVENT_LOCATION_CHANGED)
+ {
+ setCurrentURL(self->getLocation());
+ }
+ else if(event == MEDIA_EVENT_NAVIGATE_COMPLETE)
+ {
+ // nothing yet
+ }
+}
+
+void LLFloaterHelpBrowser::setCurrentURL(const std::string& url)
+{
+ mCurrentURL = url;
+
+ // redirects will navigate momentarily to about:blank, don't add to history
+ if (mCurrentURL != "about:blank")
+ {
+ // Serialize url history
+ LLURLHistory::removeURL("browser", mCurrentURL);
+ LLURLHistory::addURL("browser", mCurrentURL);
+ }
+}
+
+//static
+void LLFloaterHelpBrowser::onClickClose(void* user_data)
+{
+ LLFloaterHelpBrowser* self = (LLFloaterHelpBrowser*)user_data;
+
+ self->closeFloater();
+}
+
+//static
+void LLFloaterHelpBrowser::onClickOpenWebBrowser(void* user_data)
+{
+ LLFloaterHelpBrowser* self = (LLFloaterHelpBrowser*)user_data;
+
+ std::string url = self->mCurrentURL.empty() ?
+ self->mBrowser->getHomePageUrl() :
+ self->mCurrentURL;
+ LLWeb::loadURLExternal(url);
+}
+
+void LLFloaterHelpBrowser::openMedia(const std::string& media_url)
+{
+ mBrowser->setHomePageUrl(media_url);
+ //mBrowser->navigateTo("data:text/html;charset=utf-8,I'd really love to be going to:<br><b>" + media_url + "</b>"); // tofu HACK for debugging =:)
+ mBrowser->navigateTo(media_url);
+ setCurrentURL(media_url);
+}
+
+void LLFloaterHelpBrowser::navigateToLocalPage( const std::string& subdir, const std::string& filename_in )
+{
+ mBrowser->navigateToLocalPage(subdir, filename_in);
+}
diff --git a/indra/newview/llfloaterhelpbrowser.h b/indra/newview/llfloaterhelpbrowser.h
new file mode 100644
index 0000000000..b66a67c4d6
--- /dev/null
+++ b/indra/newview/llfloaterhelpbrowser.h
@@ -0,0 +1,72 @@
+/**
+ * @file llfloatermediabrowser.h
+ * @brief HTML Help floater - uses embedded web browser control
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ *
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATERHELPBROWSER_H
+#define LL_LLFLOATERHELPBROWSER_H
+
+#include "llfloater.h"
+#include "llmediactrl.h"
+
+
+class LLMediaCtrl;
+
+class LLFloaterHelpBrowser :
+ public LLFloater,
+ public LLViewerMediaObserver
+{
+ public:
+ LLFloaterHelpBrowser(const LLSD& key);
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onClose(bool app_quitting);
+
+ // inherited from LLViewerMediaObserver
+ /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
+
+ void openMedia(const std::string& media_url);
+
+ void navigateToLocalPage( const std::string& subdir, const std::string& filename_in );
+
+ private:
+ void buildURLHistory();
+ void setCurrentURL(const std::string& url);
+
+ static void onClickClose(void* user_data);
+ static void onClickOpenWebBrowser(void* user_data);
+
+ private:
+ LLMediaCtrl* mBrowser;
+ std::string mCurrentURL;
+};
+
+#endif // LL_LLFLOATERHELPBROWSER_H
+
diff --git a/indra/newview/llfloaterhud.cpp b/indra/newview/llfloaterhud.cpp
index 9810bf1009..d2ee3e44c5 100644
--- a/indra/newview/llfloaterhud.cpp
+++ b/indra/newview/llfloaterhud.cpp
@@ -36,14 +36,12 @@
// Viewer libs
#include "llviewercontrol.h"
-#include "llwebbrowserctrl.h"
-#include "llalertdialog.h"
+#include "llmediactrl.h"
// Linden libs
+#include "llnotificationsutil.h"
#include "lluictrlfactory.h"
-// statics
-LLFloaterHUD* LLFloaterHUD::sInstance = 0;
///----------------------------------------------------------------------------
/// Class LLFloaterHUD
@@ -51,12 +49,18 @@ LLFloaterHUD* LLFloaterHUD::sInstance = 0;
#define super LLFloater /* superclass */
// Default constructor
-LLFloaterHUD::LLFloaterHUD()
-: LLFloater(std::string("floater_hud")),
+LLFloaterHUD::LLFloaterHUD(const LLSD& key)
+: LLFloater(key),
mWebBrowser(0)
{
- // Create floater from its XML definition
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_hud.xml");
+ // do not build the floater if there the url is empty
+ if (gSavedSettings.getString("TutorialURL") == "")
+ {
+ LLNotificationsUtil::add("TutorialNotFound");
+ return;
+ }
+
+ //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_hud.xml");
// Don't grab the focus as it will impede performing in-world actions
// while using the HUD
@@ -68,79 +72,32 @@ LLFloaterHUD::LLFloaterHUD()
// Opaque background since we never get the focus
setBackgroundOpaque(TRUE);
+}
- // Position floater based on saved location
- LLRect saved_position_rect = gSavedSettings.getRect("FloaterHUDRect2");
- reshape(saved_position_rect.getWidth(), saved_position_rect.getHeight(), FALSE);
- setRect(saved_position_rect);
-
- mWebBrowser = getChild<LLWebBrowserCtrl>("floater_hud_browser" );
+BOOL LLFloaterHUD::postBuild()
+{
+ mWebBrowser = getChild<LLMediaCtrl>("floater_hud_browser" );
if (mWebBrowser)
{
// Open links in internal browser
mWebBrowser->setOpenInExternalBrowser(false);
-
+
// This is a "chrome" floater, so we don't want anything to
// take focus (as the user needs to be able to walk with
// arrow keys during tutorial).
mWebBrowser->setTakeFocusOnClick(false);
-
+
std::string language = LLUI::getLanguage();
std::string base_url = gSavedSettings.getString("TutorialURL");
-
+
std::string url = base_url + language + "/";
mWebBrowser->navigateTo(url);
}
-
- // Remember the one instance
- sInstance = this;
-}
-
-// Get the instance
-LLFloaterHUD* LLFloaterHUD::getInstance()
-{
- if (!sInstance)
- {
- new LLFloaterHUD();
- }
- return sInstance;
+
+ return TRUE;
}
// Destructor
LLFloaterHUD::~LLFloaterHUD()
{
- // Save floater position
- gSavedSettings.setRect("FloaterHUDRect2", getRect() );
-
- // Clear out the one instance if it's ours
- if (sInstance == this)
- {
- sInstance = NULL;
- }
-}
-
-// Show the HUD
-void LLFloaterHUD::showHUD()
-{
- // do not build the floater if there the url is empty
- if (gSavedSettings.getString("TutorialURL") == "")
- {
- LLNotifications::instance().add("TutorialNotFound");
- return;
- }
-
- // Create the instance if necessary
- LLFloaterHUD* hud = getInstance();
- hud->open();
- hud->setFrontmost(FALSE);
-}
-
-// Save our visibility state on close in case the user accidentally
-// quit the application while the tutorial was visible.
-// virtual
-void LLFloaterHUD::onClose(bool app_quitting)
-{
- bool stay_visible = app_quitting;
- gSavedSettings.setBOOL("ShowTutorial", stay_visible);
- destroy();
}
diff --git a/indra/newview/llfloaterhud.h b/indra/newview/llfloaterhud.h
index 2d58685b58..23ff82362a 100644
--- a/indra/newview/llfloaterhud.h
+++ b/indra/newview/llfloaterhud.h
@@ -35,26 +35,22 @@
#include "llfloater.h"
-class LLWebBrowserCtrl;
+class LLMediaCtrl;
class LLFloaterHUD : public LLFloater
{
+ friend class LLFloaterReg;
public:
- static LLFloaterHUD* getInstance(); ///< get instance creating if necessary
-
- static void showHUD(); ///< show the HUD
-
- // Save our visibility state during close
- /*virtual*/ void onClose(bool app_quitting);
+ BOOL postBuild();
+
private:
// Handles its own construction and destruction, so private.
- LLFloaterHUD();
+ LLFloaterHUD(const LLSD& key);
/*virtual*/ ~LLFloaterHUD();
private:
- LLWebBrowserCtrl* mWebBrowser; ///< the actual web browser control
- static LLFloaterHUD* sInstance;
+ LLMediaCtrl* mWebBrowser; ///< the actual web browser control
};
#endif // LL_LLFLOATERHUD_H
diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp
index d39824ee05..61568df12e 100644
--- a/indra/newview/llfloaterimagepreview.cpp
+++ b/indra/newview/llfloaterimagepreview.cpp
@@ -56,12 +56,9 @@
#include "llvoavatar.h"
#include "pipeline.h"
#include "lluictrlfactory.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llstring.h"
-//static
-S32 LLFloaterImagePreview::sUploadAmount = 10;
-
const S32 PREVIEW_BORDER_WIDTH = 2;
const S32 PREVIEW_RESIZE_HANDLE_SIZE = S32(RESIZE_HANDLE_WIDTH * OO_SQRT2) + PREVIEW_BORDER_WIDTH;
const S32 PREVIEW_HPAD = PREVIEW_RESIZE_HANDLE_SIZE;
@@ -93,9 +90,7 @@ BOOL LLFloaterImagePreview::postBuild()
{
return FALSE;
}
-
- childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d",sUploadAmount));
-
+
LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo");
if (iface)
{
@@ -130,7 +125,9 @@ BOOL LLFloaterImagePreview::postBuild()
childDisable("clothing_type_combo");
childDisable("ok_btn");
}
-
+
+ getChild<LLUICtrl>("ok_btn")->setCommitCallback(boost::bind(&LLFloaterNameDesc::onBtnOK, this));
+
return TRUE;
}
@@ -142,9 +139,6 @@ LLFloaterImagePreview::~LLFloaterImagePreview()
clearAllPreviewTextures();
mRawImagep = NULL;
- delete mAvatarPreview;
- delete mSculptedPreview;
-
mImagep = NULL ;
}
@@ -214,13 +208,16 @@ void LLFloaterImagePreview::onPreviewTypeCommit(LLUICtrl* ctrl, void* userdata)
//-----------------------------------------------------------------------------
void LLFloaterImagePreview::clearAllPreviewTextures()
{
- mAvatarPreview->clearPreviewTexture("mHairMesh0");
- mAvatarPreview->clearPreviewTexture("mUpperBodyMesh0");
- mAvatarPreview->clearPreviewTexture("mLowerBodyMesh0");
- mAvatarPreview->clearPreviewTexture("mHeadMesh0");
- mAvatarPreview->clearPreviewTexture("mUpperBodyMesh0");
- mAvatarPreview->clearPreviewTexture("mLowerBodyMesh0");
- mAvatarPreview->clearPreviewTexture("mSkirtMesh0");
+ if (mAvatarPreview)
+ {
+ mAvatarPreview->clearPreviewTexture("mHairMesh0");
+ mAvatarPreview->clearPreviewTexture("mUpperBodyMesh0");
+ mAvatarPreview->clearPreviewTexture("mLowerBodyMesh0");
+ mAvatarPreview->clearPreviewTexture("mHeadMesh0");
+ mAvatarPreview->clearPreviewTexture("mUpperBodyMesh0");
+ mAvatarPreview->clearPreviewTexture("mLowerBodyMesh0");
+ mAvatarPreview->clearPreviewTexture("mSkirtMesh0");
+ }
}
//-----------------------------------------------------------------------------
@@ -249,7 +246,7 @@ void LLFloaterImagePreview::draw()
}
else
{
- mImagep = new LLImageGL(mRawImagep, FALSE) ;
+ mImagep = LLViewerTextureManager::getLocalTexture(mRawImagep.get(), FALSE) ;
gGL.getTexUnit(0)->unbind(mImagep->getTarget()) ;
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mImagep->getTexName());
@@ -291,11 +288,11 @@ void LLFloaterImagePreview::draw()
if (selected == 9)
{
- gGL.getTexUnit(0)->bind(mSculptedPreview->getTexture());
+ gGL.getTexUnit(0)->bind(mSculptedPreview);
}
else
{
- gGL.getTexUnit(0)->bind(mAvatarPreview->getTexture());
+ gGL.getTexUnit(0)->bind(mAvatarPreview);
}
gGL.begin( LLRender::QUADS );
@@ -550,7 +547,7 @@ BOOL LLFloaterImagePreview::handleHover(S32 x, S32 y, MASK mask)
mSculptedPreview->refresh();
}
- LLUI::setCursorPositionLocal(this, mLastMouseX, mLastMouseY);
+ LLUI::setMousePositionLocal(this, mLastMouseX, mLastMouseY);
}
if (!mPreviewRect.pointInRect(x, y) || !mAvatarPreview || !mSculptedPreview)
@@ -603,7 +600,7 @@ void LLFloaterImagePreview::onMouseCaptureLostImagePreview(LLMouseHandler* handl
//-----------------------------------------------------------------------------
// LLImagePreviewAvatar
//-----------------------------------------------------------------------------
-LLImagePreviewAvatar::LLImagePreviewAvatar(S32 width, S32 height) : LLDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE)
+LLImagePreviewAvatar::LLImagePreviewAvatar(S32 width, S32 height) : LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE)
{
mNeedsUpdate = TRUE;
mTargetJoint = NULL;
@@ -614,6 +611,7 @@ LLImagePreviewAvatar::LLImagePreviewAvatar(S32 width, S32 height) : LLDynamicTex
mCameraZoom = 1.f;
mDummyAvatar = (LLVOAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR, gAgent.getRegion());
+ mDummyAvatar->initInstance();
mDummyAvatar->createDrawable(&gPipeline);
mDummyAvatar->mIsDummy = TRUE;
mDummyAvatar->mSpecialRenderMode = 2;
@@ -671,11 +669,14 @@ void LLImagePreviewAvatar::setPreviewTarget(const std::string& joint_name, const
//-----------------------------------------------------------------------------
void LLImagePreviewAvatar::clearPreviewTexture(const std::string& mesh_name)
{
- LLViewerJointMesh *mesh = (LLViewerJointMesh*)mDummyAvatar->mRoot.findJoint(mesh_name);
- // clear out existing test mesh
- if (mesh)
+ if (mDummyAvatar)
{
- mesh->setTestTexture(0);
+ LLViewerJointMesh *mesh = (LLViewerJointMesh*)mDummyAvatar->mRoot.findJoint(mesh_name);
+ // clear out existing test mesh
+ if (mesh)
+ {
+ mesh->setTestTexture(0);
+ }
}
}
@@ -690,7 +691,7 @@ BOOL LLImagePreviewAvatar::render()
glMatrixMode(GL_PROJECTION);
gGL.pushMatrix();
glLoadIdentity();
- glOrtho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f);
+ glOrtho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
gGL.pushMatrix();
@@ -699,7 +700,7 @@ BOOL LLImagePreviewAvatar::render()
LLGLSUIDefault def;
gGL.color4f(0.15f, 0.2f, 0.3f, 1.f);
- gl_rect_2d_simple( mWidth, mHeight );
+ gl_rect_2d_simple( mFullWidth, mFullHeight );
glMatrixMode(GL_PROJECTION);
gGL.popMatrix();
@@ -721,9 +722,9 @@ BOOL LLImagePreviewAvatar::render()
stop_glerror();
- LLViewerCamera::getInstance()->setAspect((F32)mWidth / mHeight);
+ LLViewerCamera::getInstance()->setAspect((F32)mFullWidth / mFullHeight);
LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom);
- LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mWidth, mHeight, FALSE);
+ LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE);
LLVertexBuffer::unbind();
avatarp->updateLOD();
@@ -781,7 +782,7 @@ void LLImagePreviewAvatar::pan(F32 right, F32 up)
// LLImagePreviewSculpted
//-----------------------------------------------------------------------------
-LLImagePreviewSculpted::LLImagePreviewSculpted(S32 width, S32 height) : LLDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE)
+LLImagePreviewSculpted::LLImagePreviewSculpted(S32 width, S32 height) : LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE)
{
mNeedsUpdate = TRUE;
mCameraDistance = 0.f;
@@ -796,27 +797,11 @@ LLImagePreviewSculpted::LLImagePreviewSculpted(S32 width, S32 height) : LLDynami
F32 const HIGHEST_LOD = 4.0f;
mVolume = new LLVolume(volume_params, HIGHEST_LOD);
-
- /*
- mDummyAvatar = new LLVOAvatar(LLUUID::null, LL_PCODE_LEGACY_AVATAR, gAgent.getRegion());
- mDummyAvatar->createDrawable(&gPipeline);
- mDummyAvatar->mIsDummy = TRUE;
- mDummyAvatar->mSpecialRenderMode = 2;
- mDummyAvatar->setPositionAgent(LLVector3::zero);
- mDummyAvatar->slamPosition();
- mDummyAvatar->updateJointLODs();
- mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable);
- gPipeline.markVisible(mDummyAvatar->mDrawable, *LLViewerCamera::getInstance());
- mTextureName = 0;
- */
}
LLImagePreviewSculpted::~LLImagePreviewSculpted()
{
- /*
- mDummyAvatar->markDead();
- */
}
@@ -880,7 +865,7 @@ BOOL LLImagePreviewSculpted::render()
glMatrixMode(GL_PROJECTION);
gGL.pushMatrix();
glLoadIdentity();
- glOrtho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f);
+ glOrtho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
gGL.pushMatrix();
@@ -888,7 +873,7 @@ BOOL LLImagePreviewSculpted::render()
gGL.color4f(0.15f, 0.2f, 0.3f, 1.f);
- gl_rect_2d_simple( mWidth, mHeight );
+ gl_rect_2d_simple( mFullWidth, mFullHeight );
glMatrixMode(GL_PROJECTION);
gGL.popMatrix();
@@ -911,9 +896,9 @@ BOOL LLImagePreviewSculpted::render()
stop_glerror();
- LLViewerCamera::getInstance()->setAspect((F32) mWidth / mHeight);
+ LLViewerCamera::getInstance()->setAspect((F32) mFullWidth / mFullHeight);
LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom);
- LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mWidth, mHeight, FALSE);
+ LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE);
const LLVolumeFace &vf = mVolume->getVolumeFace(0);
U32 num_indices = vf.mIndices.size();
diff --git a/indra/newview/llfloaterimagepreview.h b/indra/newview/llfloaterimagepreview.h
index 6a4de3d3cc..4a12543650 100644
--- a/indra/newview/llfloaterimagepreview.h
+++ b/indra/newview/llfloaterimagepreview.h
@@ -35,6 +35,7 @@
#include "llfloaternamedesc.h"
#include "lldynamictexture.h"
+#include "llpointer.h"
#include "llquaternion.h"
class LLComboBox;
@@ -43,13 +44,16 @@ class LLViewerJointMesh;
class LLVOAvatar;
class LLTextBox;
class LLVertexBuffer;
+class LLVolume;
-class LLImagePreviewSculpted : public LLDynamicTexture
+class LLImagePreviewSculpted : public LLViewerDynamicTexture
{
- public:
- LLImagePreviewSculpted(S32 width, S32 height);
+protected:
virtual ~LLImagePreviewSculpted();
+ public:
+ LLImagePreviewSculpted(S32 width, S32 height);
+
void setPreviewTarget(LLImageRaw *imagep, F32 distance);
void setTexture(U32 name) { mTextureName = name; }
@@ -73,12 +77,14 @@ class LLImagePreviewSculpted : public LLDynamicTexture
};
-class LLImagePreviewAvatar : public LLDynamicTexture
+class LLImagePreviewAvatar : public LLViewerDynamicTexture
{
-public:
- LLImagePreviewAvatar(S32 width, S32 height);
+protected:
virtual ~LLImagePreviewAvatar();
+public:
+ LLImagePreviewAvatar(S32 width, S32 height);
+
void setPreviewTarget(const std::string& joint_name, const std::string& mesh_name, LLImageRaw* imagep, F32 distance, BOOL male);
void setTexture(U32 name) { mTextureName = name; }
void clearPreviewTexture(const std::string& mesh_name);
@@ -117,7 +123,6 @@ public:
BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
static void onMouseCaptureLostImagePreview(LLMouseHandler*);
- static void setUploadAmount(S32 amount) { sUploadAmount = amount; }
void clearAllPreviewTextures();
@@ -127,15 +132,14 @@ protected:
bool loadImage(const std::string& filename);
LLPointer<LLImageRaw> mRawImagep;
- LLImagePreviewAvatar* mAvatarPreview;
- LLImagePreviewSculpted* mSculptedPreview;
+ LLPointer<LLImagePreviewAvatar> mAvatarPreview;
+ LLPointer<LLImagePreviewSculpted> mSculptedPreview;
S32 mLastMouseX;
S32 mLastMouseY;
LLRect mPreviewRect;
LLRectf mPreviewImageRect;
- LLPointer<LLImageGL> mImagep ;
+ LLPointer<LLViewerTexture> mImagep ;
- static S32 sUploadAmount;
};
#endif // LL_LLFLOATERIMAGEPREVIEW_H
diff --git a/indra/newview/llfloaterinspect.cpp b/indra/newview/llfloaterinspect.cpp
index de8a094fa9..13ca7638c5 100644
--- a/indra/newview/llfloaterinspect.cpp
+++ b/indra/newview/llfloaterinspect.cpp
@@ -31,11 +31,15 @@
*/
#include "llviewerprecompiledheaders.h"
-#include "llfloateravatarinfo.h"
+
#include "llfloaterinspect.h"
+
+#include "llfloaterreg.h"
#include "llfloatertools.h"
+#include "llavataractions.h"
#include "llcachename.h"
#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
#include "llselectmgr.h"
#include "lltoolcomp.h"
#include "lltoolmgr.h"
@@ -43,19 +47,33 @@
#include "llviewerobject.h"
#include "lluictrlfactory.h"
-LLFloaterInspect* LLFloaterInspect::sInstance = NULL;
+//LLFloaterInspect* LLFloaterInspect::sInstance = NULL;
-LLFloaterInspect::LLFloaterInspect(void) :
- LLFloater(std::string("Inspect Object")),
+LLFloaterInspect::LLFloaterInspect(const LLSD& key)
+ : LLFloater(key),
mDirty(FALSE)
{
- sInstance = this;
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inspect.xml");
+ //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inspect.xml");
+ mCommitCallbackRegistrar.add("Inspect.OwnerProfile", boost::bind(&LLFloaterInspect::onClickOwnerProfile, this));
+ mCommitCallbackRegistrar.add("Inspect.CreatorProfile", boost::bind(&LLFloaterInspect::onClickCreatorProfile, this));
+ mCommitCallbackRegistrar.add("Inspect.SelectObject", boost::bind(&LLFloaterInspect::onSelectObject, this));
+}
+
+BOOL LLFloaterInspect::postBuild()
+{
+ mObjectList = getChild<LLScrollListCtrl>("object_list");
+// childSetAction("button owner",onClickOwnerProfile, this);
+// childSetAction("button creator",onClickCreatorProfile, this);
+// childSetCommitCallback("object_list", onSelectObject, NULL);
+
+ refresh();
+
+ return TRUE;
}
LLFloaterInspect::~LLFloaterInspect(void)
{
- if(!gFloaterTools->getVisible())
+ if(!LLFloaterReg::instanceVisible("build"))
{
if(LLToolMgr::getInstance()->getBaseTool() == LLToolCompInspect::getInstance())
{
@@ -66,44 +84,26 @@ LLFloaterInspect::~LLFloaterInspect(void)
}
else
{
- gFloaterTools->setFocus(TRUE);
+ LLFloaterReg::showInstance("build", LLSD(), TRUE);
}
- sInstance = NULL;
+ //sInstance = NULL;
}
-BOOL LLFloaterInspect::isVisible()
+void LLFloaterInspect::onOpen(const LLSD& key)
{
- return (!!sInstance);
-}
-
-void LLFloaterInspect::show(void* ignored)
-{
- // setForceSelection ensures that the pie menu does not deselect things when it
- // looses the focus (this can happen with "select own objects only" enabled
- // VWR-1471
BOOL forcesel = LLSelectMgr::getInstance()->setForceSelection(TRUE);
-
- if (!sInstance) // first use
- {
- sInstance = new LLFloaterInspect;
- }
-
- sInstance->open();
LLToolMgr::getInstance()->setTransientTool(LLToolCompInspect::getInstance());
LLSelectMgr::getInstance()->setForceSelection(forcesel); // restore previouis value
-
- sInstance->mObjectSelection = LLSelectMgr::getInstance()->getSelection();
- sInstance->refresh();
+ mObjectSelection = LLSelectMgr::getInstance()->getSelection();
+ refresh();
}
-
-void LLFloaterInspect::onClickCreatorProfile(void* ctrl)
+void LLFloaterInspect::onClickCreatorProfile()
{
- if(sInstance->mObjectList->getAllSelected().size() == 0)
+ if(mObjectList->getAllSelected().size() == 0)
{
return;
}
- LLScrollListItem* first_selected =
- sInstance->mObjectList->getFirstSelected();
+ LLScrollListItem* first_selected =mObjectList->getFirstSelected();
if (first_selected)
{
@@ -116,19 +116,18 @@ void LLFloaterInspect::onClickCreatorProfile(void* ctrl)
return (obj_id == node->getObject()->getID());
}
} func(first_selected->getUUID());
- LLSelectNode* node = sInstance->mObjectSelection->getFirstNode(&func);
+ LLSelectNode* node = mObjectSelection->getFirstNode(&func);
if(node)
{
- LLFloaterAvatarInfo::showFromDirectory(node->mPermissions->getCreator());
+ LLAvatarActions::showProfile(node->mPermissions->getCreator());
}
}
}
-void LLFloaterInspect::onClickOwnerProfile(void* ctrl)
+void LLFloaterInspect::onClickOwnerProfile()
{
- if(sInstance->mObjectList->getAllSelected().size() == 0) return;
- LLScrollListItem* first_selected =
- sInstance->mObjectList->getFirstSelected();
+ if(mObjectList->getAllSelected().size() == 0) return;
+ LLScrollListItem* first_selected =mObjectList->getFirstSelected();
if (first_selected)
{
@@ -142,46 +141,34 @@ void LLFloaterInspect::onClickOwnerProfile(void* ctrl)
return (obj_id == node->getObject()->getID());
}
} func(selected_id);
- LLSelectNode* node = sInstance->mObjectSelection->getFirstNode(&func);
+ LLSelectNode* node = mObjectSelection->getFirstNode(&func);
if(node)
{
const LLUUID& owner_id = node->mPermissions->getOwner();
- LLFloaterAvatarInfo::showFromDirectory(owner_id);
+ LLAvatarActions::showProfile(owner_id);
}
}
}
-BOOL LLFloaterInspect::postBuild()
-{
- mObjectList = getChild<LLScrollListCtrl>("object_list");
- childSetAction("button owner",onClickOwnerProfile, this);
- childSetAction("button creator",onClickCreatorProfile, this);
- childSetCommitCallback("object_list", onSelectObject);
- return TRUE;
-}
-
-void LLFloaterInspect::onSelectObject(LLUICtrl* ctrl, void* user_data)
+void LLFloaterInspect::onSelectObject()
{
if(LLFloaterInspect::getSelectedUUID() != LLUUID::null)
{
- sInstance->childSetEnabled("button owner", true);
- sInstance->childSetEnabled("button creator", true);
+ childSetEnabled("button owner", true);
+ childSetEnabled("button creator", true);
}
}
LLUUID LLFloaterInspect::getSelectedUUID()
{
- if(sInstance)
+ if(mObjectList->getAllSelected().size() > 0)
{
- if(sInstance->mObjectList->getAllSelected().size() > 0)
+ LLScrollListItem* first_selected =mObjectList->getFirstSelected();
+ if (first_selected)
{
- LLScrollListItem* first_selected =
- sInstance->mObjectList->getFirstSelected();
- if (first_selected)
- {
- return first_selected->getUUID();
- }
+ return first_selected->getUUID();
}
+
}
return LLUUID::null;
}
@@ -212,7 +199,6 @@ void LLFloaterInspect::refresh()
{
LLSelectNode* obj = *iter;
LLSD row;
- char time[MAX_STRING];
std::string owner_name, creator_name;
if (obj->mCreationDate == 0)
@@ -221,8 +207,11 @@ void LLFloaterInspect::refresh()
}
time_t timestamp = (time_t) (obj->mCreationDate/1000000);
- LLStringUtil::copy(time, ctime(&timestamp), MAX_STRING);
- time[24] = '\0';
+ std::string timeStr = getString("timeStamp");
+ LLSD substitution;
+ substitution["datetime"] = (S32) timestamp;
+ LLStringUtil::format (timeStr, substitution);
+
gCacheName->getFullName(obj->mPermissions->getOwner(), owner_name);
gCacheName->getFullName(obj->mPermissions->getCreator(), creator_name);
row["id"] = obj->getObject()->getID();
@@ -246,7 +235,7 @@ void LLFloaterInspect::refresh()
row["columns"][2]["value"] = creator_name;
row["columns"][3]["column"] = "creation_date";
row["columns"][3]["type"] = "text";
- row["columns"][3]["value"] = time;
+ row["columns"][3]["value"] = timeStr;
mObjectList->addElement(row, ADD_TOP);
}
if(selected_index > -1 && mObjectList->getItemIndex(selected_uuid) == selected_index)
@@ -257,7 +246,7 @@ void LLFloaterInspect::refresh()
{
mObjectList->selectNthItem(0);
}
- onSelectObject(this, NULL);
+ onSelectObject();
mObjectList->setScrollPos(pos);
}
@@ -269,10 +258,7 @@ void LLFloaterInspect::onFocusReceived()
void LLFloaterInspect::dirty()
{
- if(sInstance)
- {
- sInstance->setDirty();
- }
+ setDirty();
}
void LLFloaterInspect::draw()
diff --git a/indra/newview/llfloaterinspect.h b/indra/newview/llfloaterinspect.h
index 57bba6864f..ce9485ee74 100644
--- a/indra/newview/llfloaterinspect.h
+++ b/indra/newview/llfloaterinspect.h
@@ -44,29 +44,33 @@ class LLUICtrl;
class LLFloaterInspect : public LLFloater
{
+ friend class LLFloaterReg;
public:
- virtual ~LLFloaterInspect(void);
- static void show(void* ignored = NULL);
+
+// static void show(void* ignored = NULL);
+ void onOpen(const LLSD& key);
virtual BOOL postBuild();
- static void dirty();
- static LLUUID getSelectedUUID();
+ void dirty();
+ LLUUID getSelectedUUID();
virtual void draw();
virtual void refresh();
- static BOOL isVisible();
+// static BOOL isVisible();
virtual void onFocusReceived();
- static void onClickCreatorProfile(void* ctrl);
- static void onClickOwnerProfile(void* ctrl);
- static void onSelectObject(LLUICtrl* ctrl, void* user_data);
+ void onClickCreatorProfile();
+ void onClickOwnerProfile();
+ void onSelectObject();
LLScrollListCtrl* mObjectList;
protected:
// protected members
- LLFloaterInspect();
void setDirty() { mDirty = TRUE; }
bool mDirty;
private:
+
+ LLFloaterInspect(const LLSD& key);
+ virtual ~LLFloaterInspect(void);
// static data
- static LLFloaterInspect* sInstance;
+// static LLFloaterInspect* sInstance;
LLSafeHandle<LLObjectSelection> mObjectSelection;
};
diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp
new file mode 100644
index 0000000000..e62e2c99a7
--- /dev/null
+++ b/indra/newview/llfloaterinventory.cpp
@@ -0,0 +1,139 @@
+/**
+ * @file llfloaterinventory.cpp
+ * @brief Implementation of the inventory view and associated stuff.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterinventory.h"
+
+#include "llagent.h"
+//#include "llfirstuse.h"
+#include "llfloaterreg.h"
+#include "llinventorymodel.h"
+#include "llpanelmaininventory.h"
+#include "llresmgr.h"
+#include "llviewerfoldertype.h"
+
+///----------------------------------------------------------------------------
+/// LLFloaterInventory
+///----------------------------------------------------------------------------
+
+LLFloaterInventory::LLFloaterInventory(const LLSD& key)
+ : LLFloater(key)
+{
+}
+
+LLFloaterInventory::~LLFloaterInventory()
+{
+}
+
+BOOL LLFloaterInventory::postBuild()
+{
+ mPanelMainInventory = getChild<LLPanelMainInventory>("Inventory Panel");
+ return TRUE;
+}
+
+
+void LLFloaterInventory::draw()
+{
+ updateTitle();
+ LLFloater::draw();
+}
+
+void LLFloaterInventory::updateTitle()
+{
+ LLLocale locale(LLLocale::USER_LOCALE);
+ std::string item_count_string;
+ LLResMgr::getInstance()->getIntegerString(item_count_string, gInventory.getItemCount());
+
+ LLStringUtil::format_map_t string_args;
+ string_args["[ITEM_COUNT]"] = item_count_string;
+ string_args["[FILTER]"] = mPanelMainInventory->getFilterText();
+
+ if (LLInventoryModel::backgroundFetchActive())
+ {
+ setTitle(getString("TitleFetching", string_args));
+ }
+ else if (LLInventoryModel::isEverythingFetched())
+ {
+ setTitle(getString("TitleCompleted", string_args));
+ }
+ else
+ {
+ setTitle(getString("Title"));
+ }
+}
+
+void LLFloaterInventory::changed(U32 mask)
+{
+ updateTitle();
+}
+
+LLInventoryPanel* LLFloaterInventory::getPanel()
+{
+ if (mPanelMainInventory)
+ return mPanelMainInventory->getPanel();
+ return NULL;
+}
+
+// static
+LLFloaterInventory* LLFloaterInventory::showAgentInventory()
+{
+ // Hack to generate semi-unique key for each inventory floater.
+ static S32 instance_num = 0;
+ instance_num = (instance_num + 1) % S32_MAX;
+
+ LLFloaterInventory* iv = NULL;
+ if (!gAgent.cameraMouselook())
+ {
+ iv = LLFloaterReg::showTypedInstance<LLFloaterInventory>("inventory", LLSD(instance_num));
+ }
+ return iv;
+}
+
+// static
+void LLFloaterInventory::cleanup()
+{
+ LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory");
+ for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end();)
+ {
+ LLFloaterInventory* iv = dynamic_cast<LLFloaterInventory*>(*iter++);
+ if (iv)
+ {
+ iv->destroy();
+ }
+ }
+}
+
+void LLFloaterInventory::onOpen(const LLSD& key)
+{
+ //LLFirstUse::useInventory();
+}
diff --git a/indra/newview/llfloaterinventory.h b/indra/newview/llfloaterinventory.h
new file mode 100644
index 0000000000..b661c391a7
--- /dev/null
+++ b/indra/newview/llfloaterinventory.h
@@ -0,0 +1,80 @@
+/**
+ * @file llfloaterinventory.h
+ * @brief LLFloaterInventory, LLInventoryFolder, and LLInventoryItem
+ * class definition
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATERINVENTORY_H
+#define LL_LLFLOATERINVENTORY_H
+
+#include "llfloater.h"
+#include "llfoldertype.h"
+
+class LLInventoryPanel;
+class LLPanelMainInventory;
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLFloaterInventory
+//
+// This deals with the buttons and views used to navigate as
+// well as controlling the behavior of the overall object.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLFloaterInventory : public LLFloater
+{
+public:
+ LLFloaterInventory(const LLSD& key);
+ ~LLFloaterInventory();
+
+ BOOL postBuild();
+
+ // This method makes sure that an inventory view exists, is
+ // visible, and has focus. The view chosen is returned.
+ static LLFloaterInventory* showAgentInventory();
+
+ // Final cleanup, destroy all open inventory views.
+ static void cleanup();
+
+ // Inherited functionality
+ /*virtual*/ void changed(U32 mask);
+ /*virtual*/ void draw();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ LLInventoryPanel* getPanel();
+protected:
+ void updateTitle();
+private:
+ LLPanelMainInventory* mPanelMainInventory;
+};
+
+#endif // LL_LLFLOATERINVENTORY_H
+
+
+
diff --git a/indra/newview/llfloaterjoystick.cpp b/indra/newview/llfloaterjoystick.cpp
index e5811671ed..06fe2a84c8 100644
--- a/indra/newview/llfloaterjoystick.cpp
+++ b/indra/newview/llfloaterjoystick.cpp
@@ -48,10 +48,10 @@
#include "llcheckboxctrl.h"
LLFloaterJoystick::LLFloaterJoystick(const LLSD& data)
- : LLFloater("floater_joystick")
+ : LLFloater(data)
{
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_joystick.xml");
- center();
+ //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_joystick.xml");
+
}
void LLFloaterJoystick::draw()
@@ -68,14 +68,15 @@ void LLFloaterJoystick::draw()
{
F32 value = joystick->getJoystickAxis(i);
mAxisStats[i]->addValue(value * gFrameIntervalSeconds);
-
- if (mAxisStatsBar[i]->mMinBar > value)
- {
- mAxisStatsBar[i]->mMinBar = value;
- }
- if (mAxisStatsBar[i]->mMaxBar < value)
+ if (mAxisStatsBar[i])
{
- mAxisStatsBar[i]->mMaxBar = value;
+ F32 minbar, maxbar;
+ mAxisStatsBar[i]->getRange(minbar, maxbar);
+ if (llabs(value) > maxbar)
+ {
+ F32 range = llabs(value);
+ mAxisStatsBar[i]->setRange(-range, range, range * 0.25f, range * 0.5f);
+ }
}
}
@@ -84,37 +85,20 @@ void LLFloaterJoystick::draw()
BOOL LLFloaterJoystick::postBuild()
{
- F32 range = gSavedSettings.getBOOL("Cursor3D") ? 1024.f : 2.f;
- LLUIString axis = getString("Axis");
- LLUIString joystick = getString("JoystickMonitor");
-
- // use this child to get relative positioning info; we'll place the
- // joystick monitor on its right, vertically aligned to it.
- LLView* child = getChild<LLView>("FlycamAxisScale1");
- LLRect rect;
-
- if (child)
- {
- LLRect r = child->getRect();
- LLRect f = getRect();
- rect = LLRect(350, r.mTop, r.mRight + 200, 0);
- }
-
- mAxisStatsView = new LLStatView("axis values", joystick, "", rect);
- mAxisStatsView->setDisplayChildren(TRUE);
+ center();
+ F32 range = gSavedSettings.getBOOL("Cursor3D") ? 128.f : 2.f;
for (U32 i = 0; i < 6; i++)
{
- axis.setArg("[NUM]", llformat("%d", i));
mAxisStats[i] = new LLStat(4);
- mAxisStatsBar[i] = mAxisStatsView->addStat(axis, mAxisStats[i]);
- mAxisStatsBar[i]->mMinBar = -range;
- mAxisStatsBar[i]->mMaxBar = range;
- mAxisStatsBar[i]->mLabelSpacing = range * 0.5f;
- mAxisStatsBar[i]->mTickSpacing = range * 0.25f;
+ std::string axisname = llformat("axis%d", i);
+ mAxisStatsBar[i] = getChild<LLStatBar>(axisname);
+ if (mAxisStatsBar[i])
+ {
+ mAxisStatsBar[i]->setStat(mAxisStats[i]);
+ mAxisStatsBar[i]->setRange(-range, range, range * 0.25f, range * 0.5f);
+ }
}
-
- addChild(mAxisStatsView);
mCheckJoystickEnabled = getChild<LLCheckBoxCtrl>("enable_joystick");
childSetCommitCallback("enable_joystick",onCommitJoystickEnabled,this);
@@ -310,7 +294,7 @@ void LLFloaterJoystick::onClickCancel(void *joy_panel)
if (self)
{
self->cancel();
- self->close();
+ self->closeFloater();
}
}
}
@@ -323,7 +307,7 @@ void LLFloaterJoystick::onClickOK(void *joy_panel)
if (self)
{
- self->close();
+ self->closeFloater();
}
}
}
diff --git a/indra/newview/llfloaterjoystick.h b/indra/newview/llfloaterjoystick.h
index 3ce647e5bb..f3559c28e9 100644
--- a/indra/newview/llfloaterjoystick.h
+++ b/indra/newview/llfloaterjoystick.h
@@ -38,11 +38,11 @@
class LLCheckBoxCtrl;
-class LLFloaterJoystick : public LLFloater, public LLFloaterSingleton<LLFloaterJoystick >
+class LLFloaterJoystick : public LLFloater
{
+ friend class LLFloaterReg;
+
public:
- LLFloaterJoystick(const LLSD& data);
- virtual ~LLFloaterJoystick();
virtual BOOL postBuild();
virtual void refresh();
@@ -52,6 +52,10 @@ public:
static void setSNDefaults();
private:
+
+ LLFloaterJoystick(const LLSD& data);
+ virtual ~LLFloaterJoystick();
+
static void onCommitJoystickEnabled(LLUICtrl*, void*);
static void onClickRestoreSNDefaults(void*);
static void onClickCancel(void*);
@@ -84,9 +88,8 @@ private:
LLCheckBoxCtrl *mCheckFlycamEnabled;
// stats view
- LLStatView* mAxisStatsView;
- LLStat* mAxisStats[6];
- LLStatBar* mAxisStatsBar[6];
+ LLStat* mAxisStats[6];
+ LLStatBar* mAxisStatsBar[6];
};
#endif
diff --git a/indra/newview/llfloaterlagmeter.cpp b/indra/newview/llfloaterlagmeter.cpp
index 91471ca2d0..3753dcaaa8 100644
--- a/indra/newview/llfloaterlagmeter.cpp
+++ b/indra/newview/llfloaterlagmeter.cpp
@@ -36,7 +36,7 @@
#include "lluictrlfactory.h"
#include "llviewerstats.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
#include "llviewercontrol.h"
#include "llappviewer.h"
@@ -51,14 +51,24 @@ const std::string LAG_WARNING_IMAGE_NAME = "lag_status_warning.tga";
const std::string LAG_GOOD_IMAGE_NAME = "lag_status_good.tga";
LLFloaterLagMeter::LLFloaterLagMeter(const LLSD& key)
- : LLFloater(std::string("floater_lagmeter"))
+ : LLFloater(key)
{
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_lagmeter.xml");
+// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_lagmeter.xml");
+ mCommitCallbackRegistrar.add("LagMeter.ClickShrink", boost::bind(&LLFloaterLagMeter::onClickShrink, this));
+}
+BOOL LLFloaterLagMeter::postBuild()
+{
// Don't let this window take keyboard focus -- it's confusing to
// lose arrow-key driving when testing lag.
setIsChrome(TRUE);
-
+
+ // were we shrunk last time?
+ if (gSavedSettings.getBOOL("LagMeterShrunk"))
+ {
+ onClickShrink();
+ }
+
mClientButton = getChild<LLButton>("client_lagmeter");
mClientText = getChild<LLTextBox>("client_text");
mClientCause = getChild<LLTextBox>("client_lag_cause");
@@ -93,7 +103,7 @@ LLFloaterLagMeter::LLFloaterLagMeter(const LLSD& key)
config_string = getString("server_single_process_max_time_ms", mStringArgs);
mServerSingleProcessMaxTime = (float)atof( config_string.c_str() );
- mShrunk = false;
+// mShrunk = false;
config_string = getString("max_width_px", mStringArgs);
mMaxWidth = atoi( config_string.c_str() );
config_string = getString("min_width_px", mStringArgs);
@@ -111,23 +121,18 @@ LLFloaterLagMeter::LLFloaterLagMeter(const LLSD& key)
mStringArgs["[SERVER_FRAME_RATE_CRITICAL]"] = getString("server_frame_rate_critical_fps");
mStringArgs["[SERVER_FRAME_RATE_WARNING]"] = getString("server_frame_rate_warning_fps");
- childSetAction("minimize", onClickShrink, this);
+// childSetAction("minimize", onClickShrink, this);
- // were we shrunk last time?
- if (gSavedSettings.getBOOL("LagMeterShrunk"))
- {
- onClickShrink(this);
- }
+ return TRUE;
}
-
LLFloaterLagMeter::~LLFloaterLagMeter()
{
// save shrunk status for next time
- gSavedSettings.setBOOL("LagMeterShrunk", mShrunk);
+// gSavedSettings.setBOOL("LagMeterShrunk", mShrunk);
// expand so we save the large window rectangle
- if (mShrunk)
+ if (gSavedSettings.getBOOL("LagMeterShrunk"))
{
- onClickShrink(this);
+ onClickShrink();
}
}
@@ -147,25 +152,25 @@ void LLFloaterLagMeter::determineClient()
if (!gFocusMgr.getAppHasFocus())
{
- mClientButton->setImageUnselected(LAG_GOOD_IMAGE_NAME);
+ mClientButton->setImageUnselected(LLUI::getUIImage(LAG_GOOD_IMAGE_NAME));
mClientText->setText( getString("client_frame_time_window_bg_msg", mStringArgs) );
mClientCause->setText( LLStringUtil::null );
}
else if(client_frame_time >= mClientFrameTimeCritical)
{
- mClientButton->setImageUnselected(LAG_CRITICAL_IMAGE_NAME);
+ mClientButton->setImageUnselected(LLUI::getUIImage(LAG_CRITICAL_IMAGE_NAME));
mClientText->setText( getString("client_frame_time_critical_msg", mStringArgs) );
find_cause = true;
}
else if(client_frame_time >= mClientFrameTimeWarning)
{
- mClientButton->setImageUnselected(LAG_WARNING_IMAGE_NAME);
+ mClientButton->setImageUnselected(LLUI::getUIImage(LAG_WARNING_IMAGE_NAME));
mClientText->setText( getString("client_frame_time_warning_msg", mStringArgs) );
find_cause = true;
}
else
{
- mClientButton->setImageUnselected(LAG_GOOD_IMAGE_NAME);
+ mClientButton->setImageUnselected(LLUI::getUIImage(LAG_GOOD_IMAGE_NAME));
mClientText->setText( getString("client_frame_time_normal_msg", mStringArgs) );
mClientCause->setText( LLStringUtil::null );
}
@@ -180,7 +185,7 @@ void LLFloaterLagMeter::determineClient()
{
mClientCause->setText( getString("client_texture_loading_cause_msg", mStringArgs) );
}
- else if((LLViewerImage::sBoundTextureMemory >> 20) > LLViewerImage::sMaxBoundTextureMem)
+ else if((BYTES_TO_MEGA_BYTES(LLViewerTexture::sBoundTextureMemoryInBytes)) > LLViewerTexture::sMaxBoundTextureMemInMegaBytes)
{
mClientCause->setText( getString("client_texture_memory_cause_msg", mStringArgs) );
}
@@ -206,13 +211,13 @@ void LLFloaterLagMeter::determineNetwork()
if(packet_loss >= mNetworkPacketLossCritical)
{
- mNetworkButton->setImageUnselected(LAG_CRITICAL_IMAGE_NAME);
+ mNetworkButton->setImageUnselected(LLUI::getUIImage(LAG_CRITICAL_IMAGE_NAME));
mNetworkText->setText( getString("network_packet_loss_critical_msg", mStringArgs) );
find_cause_loss = true;
}
else if(ping_time >= mNetworkPingCritical)
{
- mNetworkButton->setImageUnselected(LAG_CRITICAL_IMAGE_NAME);
+ mNetworkButton->setImageUnselected(LLUI::getUIImage(LAG_CRITICAL_IMAGE_NAME));
if (client_frame_time_ms < mNetworkPingCritical)
{
mNetworkText->setText( getString("network_ping_critical_msg", mStringArgs) );
@@ -221,13 +226,13 @@ void LLFloaterLagMeter::determineNetwork()
}
else if(packet_loss >= mNetworkPacketLossWarning)
{
- mNetworkButton->setImageUnselected(LAG_WARNING_IMAGE_NAME);
+ mNetworkButton->setImageUnselected(LLUI::getUIImage(LAG_WARNING_IMAGE_NAME));
mNetworkText->setText( getString("network_packet_loss_warning_msg", mStringArgs) );
find_cause_loss = true;
}
else if(ping_time >= mNetworkPingWarning)
{
- mNetworkButton->setImageUnselected(LAG_WARNING_IMAGE_NAME);
+ mNetworkButton->setImageUnselected(LLUI::getUIImage(LAG_WARNING_IMAGE_NAME));
if (client_frame_time_ms < mNetworkPingWarning)
{
mNetworkText->setText( getString("network_ping_warning_msg", mStringArgs) );
@@ -236,7 +241,7 @@ void LLFloaterLagMeter::determineNetwork()
}
else
{
- mNetworkButton->setImageUnselected(LAG_GOOD_IMAGE_NAME);
+ mNetworkButton->setImageUnselected(LLUI::getUIImage(LAG_GOOD_IMAGE_NAME));
mNetworkText->setText( getString("network_performance_normal_msg", mStringArgs) );
}
@@ -261,19 +266,19 @@ void LLFloaterLagMeter::determineServer()
if(sim_frame_time >= mServerFrameTimeCritical)
{
- mServerButton->setImageUnselected(LAG_CRITICAL_IMAGE_NAME);
+ mServerButton->setImageUnselected(LLUI::getUIImage(LAG_CRITICAL_IMAGE_NAME));
mServerText->setText( getString("server_frame_time_critical_msg", mStringArgs) );
find_cause = true;
}
else if(sim_frame_time >= mServerFrameTimeWarning)
{
- mServerButton->setImageUnselected(LAG_WARNING_IMAGE_NAME);
+ mServerButton->setImageUnselected(LLUI::getUIImage(LAG_WARNING_IMAGE_NAME));
mServerText->setText( getString("server_frame_time_warning_msg", mStringArgs) );
find_cause = true;
}
else
{
- mServerButton->setImageUnselected(LAG_GOOD_IMAGE_NAME);
+ mServerButton->setImageUnselected(LLUI::getUIImage(LAG_GOOD_IMAGE_NAME));
mServerText->setText( getString("server_frame_time_normal_msg", mStringArgs) );
mServerCause->setText( LLStringUtil::null );
}
@@ -307,58 +312,61 @@ void LLFloaterLagMeter::determineServer()
}
}
-//static
-void LLFloaterLagMeter::onClickShrink(void * data)
+
+void LLFloaterLagMeter::onClickShrink() // toggle "LagMeterShrunk"
{
- LLFloaterLagMeter * self = (LLFloaterLagMeter*)data;
+// LLFloaterLagMeter * self = (LLFloaterLagMeter*)data;
+
+ LLButton * button = getChild<LLButton>("minimize");
+ S32 delta_width = mMaxWidth -mMinWidth;
+ LLRect r = getRect();
+ bool shrunk = gSavedSettings.getBOOL("LagMeterShrunk");
- LLButton * button = self->getChild<LLButton>("minimize");
- S32 delta_width = self->mMaxWidth - self->mMinWidth;
- LLRect r = self->getRect();
- if(self->mShrunk)
+ if(shrunk)
{
- self->setTitle( self->getString("max_title_msg", self->mStringArgs) );
+ setTitle(getString("max_title_msg", mStringArgs) );
// make left edge appear to expand
r.translate(-delta_width, 0);
- self->setRect(r);
- self->reshape(self->mMaxWidth, self->getRect().getHeight());
+ setRect(r);
+ reshape(mMaxWidth, getRect().getHeight());
- self->childSetText("client", self->getString("client_text_msg", self->mStringArgs) + ":");
- self->childSetText("network", self->getString("network_text_msg", self->mStringArgs) + ":");
- self->childSetText("server", self->getString("server_text_msg", self->mStringArgs) + ":");
+ childSetText("client", getString("client_text_msg", mStringArgs) + ":");
+ childSetText("network", getString("network_text_msg",mStringArgs) + ":");
+ childSetText("server", getString("server_text_msg", mStringArgs) + ":");
// usually "<<"
- button->setLabel( self->getString("smaller_label", self->mStringArgs) );
+ button->setLabel( getString("smaller_label", mStringArgs) );
}
else
{
- self->setTitle( self->getString("min_title_msg", self->mStringArgs) );
+ setTitle( getString("min_title_msg", mStringArgs) );
// make left edge appear to collapse
r.translate(delta_width, 0);
- self->setRect(r);
- self->reshape(self->mMinWidth, self->getRect().getHeight());
+ setRect(r);
+ reshape(mMinWidth, getRect().getHeight());
- self->childSetText("client", self->getString("client_text_msg", self->mStringArgs) );
- self->childSetText("network", self->getString("network_text_msg", self->mStringArgs) );
- self->childSetText("server", self->getString("server_text_msg", self->mStringArgs) );
+ childSetText("client", getString("client_text_msg", mStringArgs) );
+ childSetText("network",getString("network_text_msg",mStringArgs) );
+ childSetText("server", getString("server_text_msg", mStringArgs) );
// usually ">>"
- button->setLabel( self->getString("bigger_label", self->mStringArgs) );
+ button->setLabel( getString("bigger_label", mStringArgs) );
}
// Don't put keyboard focus on the button
button->setFocus(FALSE);
- self->mClientText->setVisible(self->mShrunk);
- self->mClientCause->setVisible(self->mShrunk);
- self->childSetVisible("client_help", self->mShrunk);
+// self->mClientText->setVisible(self->mShrunk);
+// self->mClientCause->setVisible(self->mShrunk);
+// self->childSetVisible("client_help", self->mShrunk);
- self->mNetworkText->setVisible(self->mShrunk);
- self->mNetworkCause->setVisible(self->mShrunk);
- self->childSetVisible("network_help", self->mShrunk);
+// self->mNetworkText->setVisible(self->mShrunk);
+// self->mNetworkCause->setVisible(self->mShrunk);
+// self->childSetVisible("network_help", self->mShrunk);
- self->mServerText->setVisible(self->mShrunk);
- self->mServerCause->setVisible(self->mShrunk);
- self->childSetVisible("server_help", self->mShrunk);
+// self->mServerText->setVisible(self->mShrunk);
+// self->mServerCause->setVisible(self->mShrunk);
+// self->childSetVisible("server_help", self->mShrunk);
- self->mShrunk = !self->mShrunk;
+// self->mShrunk = !self->mShrunk;
+ gSavedSettings.setBOOL("LagMeterShrunk", !gSavedSettings.getBOOL("LagMeterShrunk"));
}
diff --git a/indra/newview/llfloaterlagmeter.h b/indra/newview/llfloaterlagmeter.h
index d9cea18305..592630636a 100644
--- a/indra/newview/llfloaterlagmeter.h
+++ b/indra/newview/llfloaterlagmeter.h
@@ -35,22 +35,24 @@
#include "llfloater.h"
-class LLFloaterLagMeter : public LLFloater, public LLFloaterSingleton<LLFloaterLagMeter>
+class LLTextBox;
+
+class LLFloaterLagMeter : public LLFloater
{
- friend class LLUISingleton<LLFloaterLagMeter, VisibilityPolicy<LLFloater> >;
+ friend class LLFloaterReg;
public:
/*virtual*/ void draw();
-
+ /*virtual*/ BOOL postBuild();
private:
+
LLFloaterLagMeter(const LLSD& key);
/*virtual*/ ~LLFloaterLagMeter();
-
void determineClient();
void determineNetwork();
void determineServer();
- static void onClickShrink(void * data);
+ void onClickShrink();
bool mShrunk;
S32 mMaxWidth, mMinWidth;
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 94a834502f..42c961a956 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -39,34 +39,38 @@
#include "llcachename.h"
#include "llfocusmgr.h"
+#include "llnotificationsutil.h"
#include "llparcel.h"
#include "message.h"
#include "lluserauth.h"
#include "llagent.h"
-#include "llfloateravatarpicker.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
-#include "llradiogroup.h"
#include "llcombobox.h"
+#include "llfloaterreg.h"
+#include "llfloateravatarpicker.h"
#include "llfloaterauction.h"
-#include "llfloateravatarinfo.h"
#include "llfloatergroups.h"
-#include "llfloatergroupinfo.h"
+#include "llfloaterscriptlimits.h"
+#include "llavataractions.h"
#include "lllineeditor.h"
#include "llnamelistctrl.h"
-#include "llnotify.h"
+#include "llpanellandaudio.h"
#include "llpanellandmedia.h"
#include "llradiogroup.h"
#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "llscrolllistcell.h"
#include "llselectmgr.h"
+#include "llslurl.h"
#include "llspinctrl.h"
#include "lltabcontainer.h"
#include "lltextbox.h"
#include "lltexturectrl.h"
#include "lluiconstants.h"
#include "lluictrlfactory.h"
-#include "llviewerimagelist.h" // LLUIImageList
+#include "llviewertexturelist.h" // LLUIImageList
#include "llviewermessage.h"
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
@@ -75,6 +79,9 @@
#include "llviewerwindow.h"
#include "llviewercontrol.h"
#include "roles_constants.h"
+#include "lltrans.h"
+
+#include "llgroupactions.h"
static std::string OWNER_ONLINE = "0";
static std::string OWNER_OFFLINE = "1";
@@ -99,7 +106,7 @@ public:
// LLFloaterLand
//---------------------------------------------------------------------------
-void send_parcel_select_objects(S32 parcel_local_id, S32 return_type,
+void send_parcel_select_objects(S32 parcel_local_id, U32 return_type,
uuid_list_t* return_ids = NULL)
{
LLMessageSystem *msg = gMessageSystem;
@@ -117,7 +124,7 @@ void send_parcel_select_objects(S32 parcel_local_id, S32 return_type,
msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID());
msg->nextBlockFast(_PREHASH_ParcelData);
msg->addS32Fast(_PREHASH_LocalID, parcel_local_id);
- msg->addS32Fast(_PREHASH_ReturnType, return_type);
+ msg->addU32Fast(_PREHASH_ReturnType, return_type);
// Throw all return ids into the packet.
// TODO: Check for too many ids.
@@ -142,27 +149,58 @@ void send_parcel_select_objects(S32 parcel_local_id, S32 return_type,
msg->sendReliable(region->getHost());
}
+LLParcel* LLFloaterLand::getCurrentSelectedParcel()
+{
+ return mParcel->getParcel();
+};
//static
LLPanelLandObjects* LLFloaterLand::getCurrentPanelLandObjects()
{
- return LLFloaterLand::getInstance()->mPanelObjects;
+ LLFloaterLand* land_instance = LLFloaterReg::getTypedInstance<LLFloaterLand>("about_land");
+ if(land_instance)
+ {
+ return land_instance->mPanelObjects;
+ }
+ else
+ {
+ return NULL;
+ }
}
//static
LLPanelLandCovenant* LLFloaterLand::getCurrentPanelLandCovenant()
{
- return LLFloaterLand::getInstance()->mPanelCovenant;
+ LLFloaterLand* land_instance = LLFloaterReg::getTypedInstance<LLFloaterLand>("about_land");
+ if(land_instance)
+ {
+ return land_instance->mPanelCovenant;
+ }
+ else
+ {
+ return NULL;
+ }
}
// static
void LLFloaterLand::refreshAll()
{
- LLFloaterLand::getInstance()->refresh();
+ LLFloaterLand* land_instance = LLFloaterReg::getTypedInstance<LLFloaterLand>("about_land");
+ if(land_instance)
+ {
+ land_instance->refresh();
+ }
}
-void LLFloaterLand::onOpen()
+void LLFloaterLand::onOpen(const LLSD& key)
{
+ // moved from triggering show instance in llviwermenu.cpp
+
+ if (LLViewerParcelMgr::getInstance()->selectionEmpty())
+ {
+ LLViewerParcelMgr::getInstance()->selectParcelAt(gAgent.getPositionGlobal());
+ }
+
// Done automatically when the selected parcel's properties arrive
// (and hence we have the local id).
// LLViewerParcelMgr::getInstance()->sendParcelAccessListRequest(AL_ACCESS | AL_BAN | AL_RENTER);
@@ -174,45 +212,40 @@ void LLFloaterLand::onOpen()
refresh();
}
-
-// virtual
-void LLFloaterLand::onClose(bool app_quitting)
+void LLFloaterLand::onVisibilityChange(const LLSD& visible)
{
- LLViewerParcelMgr::getInstance()->removeObserver( sObserver );
- delete sObserver;
- sObserver = NULL;
-
- // Might have been showing owned objects
- LLSelectMgr::getInstance()->unhighlightAll();
-
- // Save which panel we had open
- sLastTab = mTabLand->getCurrentPanelIndex();
+ if (!visible.asBoolean())
+ {
+ // Might have been showing owned objects
+ LLSelectMgr::getInstance()->unhighlightAll();
- destroy();
+ // Save which panel we had open
+ sLastTab = mTabLand->getCurrentPanelIndex();
+ }
}
LLFloaterLand::LLFloaterLand(const LLSD& seed)
-: LLFloater(std::string("floaterland"), std::string("FloaterLandRect5"), std::string("About Land"))
+: LLFloater(seed)
{
- LLCallbackMap::map_t factory_map;
- factory_map["land_general_panel"] = LLCallbackMap(createPanelLandGeneral, this);
+ mFactoryMap["land_general_panel"] = LLCallbackMap(createPanelLandGeneral, this);
+ mFactoryMap["land_covenant_panel"] = LLCallbackMap(createPanelLandCovenant, this);
+ mFactoryMap["land_objects_panel"] = LLCallbackMap(createPanelLandObjects, this);
+ mFactoryMap["land_options_panel"] = LLCallbackMap(createPanelLandOptions, this);
+ mFactoryMap["land_audio_panel"] = LLCallbackMap(createPanelLandAudio, this);
+ mFactoryMap["land_media_panel"] = LLCallbackMap(createPanelLandMedia, this);
+ mFactoryMap["land_access_panel"] = LLCallbackMap(createPanelLandAccess, this);
-
- factory_map["land_covenant_panel"] = LLCallbackMap(createPanelLandCovenant, this);
- factory_map["land_objects_panel"] = LLCallbackMap(createPanelLandObjects, this);
- factory_map["land_options_panel"] = LLCallbackMap(createPanelLandOptions, this);
- factory_map["land_media_panel"] = LLCallbackMap(createPanelLandMedia, this);
- factory_map["land_access_panel"] = LLCallbackMap(createPanelLandAccess, this);
-
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_about_land.xml", &factory_map, false);
+ //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_about_land.xml", false);
sObserver = new LLParcelSelectionObserver();
LLViewerParcelMgr::getInstance()->addObserver( sObserver );
}
BOOL LLFloaterLand::postBuild()
-{
+{
+ setVisibleCallback(boost::bind(&LLFloaterLand::onVisibilityChange, this, _2));
+
LLTabContainer* tab = getChild<LLTabContainer>("landtab");
mTabLand = (LLTabContainer*) tab;
@@ -229,6 +262,9 @@ BOOL LLFloaterLand::postBuild()
// virtual
LLFloaterLand::~LLFloaterLand()
{
+ LLViewerParcelMgr::getInstance()->removeObserver( sObserver );
+ delete sObserver;
+ sObserver = NULL;
}
// public
@@ -237,8 +273,10 @@ void LLFloaterLand::refresh()
mPanelGeneral->refresh();
mPanelObjects->refresh();
mPanelOptions->refresh();
+ mPanelAudio->refresh();
mPanelMedia->refresh();
mPanelAccess->refresh();
+ mPanelCovenant->refresh();
}
@@ -276,6 +314,14 @@ void* LLFloaterLand::createPanelLandOptions(void* data)
}
// static
+void* LLFloaterLand::createPanelLandAudio(void* data)
+{
+ LLFloaterLand* self = (LLFloaterLand*)data;
+ self->mPanelAudio = new LLPanelLandAudio(self->mParcel);
+ return self->mPanelAudio;
+}
+
+// static
void* LLFloaterLand::createPanelLandMedia(void* data)
{
LLFloaterLand* self = (LLFloaterLand*)data;
@@ -297,7 +343,7 @@ void* LLFloaterLand::createPanelLandAccess(void* data)
LLPanelLandGeneral::LLPanelLandGeneral(LLParcelSelectionHandle& parcel)
-: LLPanel(std::string("land_general_panel")),
+: LLPanel(),
mUncheckedSell(FALSE),
mParcel(parcel)
{
@@ -306,16 +352,15 @@ LLPanelLandGeneral::LLPanelLandGeneral(LLParcelSelectionHandle& parcel)
BOOL LLPanelLandGeneral::postBuild()
{
mEditName = getChild<LLLineEditor>("Name");
- mEditName->setCommitCallback(onCommitAny);
- childSetPrevalidate("Name", LLLineEditor::prevalidatePrintableNotPipe);
- childSetUserData("Name", this);
+ mEditName->setCommitCallback(onCommitAny, this);
+ childSetPrevalidate("Name", LLLineEditor::prevalidateASCIIPrintableNoPipe);
mEditDesc = getChild<LLTextEditor>("Description");
mEditDesc->setCommitOnFocusLost(TRUE);
- mEditDesc->setCommitCallback(onCommitAny);
- childSetPrevalidate("Description", LLLineEditor::prevalidatePrintableNotPipe);
- childSetUserData("Description", this);
-
+ mEditDesc->setCommitCallback(onCommitAny, this);
+ // No prevalidate function - historically the prevalidate function was broken,
+ // allowing residents to put in characters like U+2661 WHITE HEART SUIT, so
+ // preserve that ability.
mTextSalePending = getChild<LLTextBox>("SalePending");
mTextOwnerLabel = getChild<LLTextBox>("Owner:");
@@ -333,7 +378,7 @@ BOOL LLPanelLandGeneral::postBuild()
mBtnSetGroup = getChild<LLButton>("Set...");
- mBtnSetGroup->setClickedCallback(onClickSetGroup, this);
+ mBtnSetGroup->setCommitCallback(boost::bind(&LLPanelLandGeneral::onClickSetGroup, this));
mCheckDeedToGroup = getChild<LLCheckBoxCtrl>( "check deed");
@@ -382,6 +427,9 @@ BOOL LLPanelLandGeneral::postBuild()
mBtnBuyLand = getChild<LLButton>("Buy Land...");
mBtnBuyLand->setClickedCallback(onClickBuyLand, (void*)&BUY_PERSONAL_LAND);
+ mBtnScriptLimits = getChild<LLButton>("Scripts...");
+ mBtnScriptLimits->setClickedCallback(onClickScriptLimits, this);
+
mBtnBuyGroupLand = getChild<LLButton>("Buy For Group...");
mBtnBuyGroupLand->setClickedCallback(onClickBuyLand, (void*)&BUY_GROUP_LAND);
@@ -396,7 +444,7 @@ BOOL LLPanelLandGeneral::postBuild()
mBtnReclaimLand->setClickedCallback(onClickReclaim, NULL);
mBtnStartAuction = getChild<LLButton>("Linden Sale...");
- mBtnStartAuction->setClickedCallback(onClickStartAuction, NULL);
+ mBtnStartAuction->setClickedCallback(onClickStartAuction, this);
return TRUE;
}
@@ -469,6 +517,7 @@ void LLPanelLandGeneral::refresh()
mTextDwell->setText(LLStringUtil::null);
mBtnBuyLand->setEnabled(FALSE);
+ mBtnScriptLimits->setEnabled(FALSE);
mBtnBuyGroupLand->setEnabled(FALSE);
mBtnReleaseLand->setEnabled(FALSE);
mBtnReclaimLand->setEnabled(FALSE);
@@ -676,6 +725,8 @@ void LLPanelLandGeneral::refresh()
mBtnBuyLand->setEnabled(
LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, false));
+ mBtnScriptLimits->setEnabled(true);
+// LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, false));
mBtnBuyGroupLand->setEnabled(
LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, true));
@@ -706,6 +757,7 @@ void LLPanelLandGeneral::refreshNames()
if (!parcel)
{
mTextOwner->setText(LLStringUtil::null);
+ mTextGroup->setText(LLStringUtil::null);
return;
}
@@ -717,7 +769,7 @@ void LLPanelLandGeneral::refreshNames()
else
{
// Figure out the owner's name
- gCacheName->getFullName(parcel->getOwnerID(), owner);
+ owner = LLSLURL::buildCommand("agent", parcel->getOwnerID(), "inspect");
}
if(LLParcel::OS_LEASE_PENDING == parcel->getOwnershipStatus())
@@ -727,9 +779,9 @@ void LLPanelLandGeneral::refreshNames()
mTextOwner->setText(owner);
std::string group;
- if(!parcel->getGroupID().isNull())
+ if (!parcel->getGroupID().isNull())
{
- gCacheName->getGroupName(parcel->getGroupID(), group);
+ group = LLSLURL::buildCommand("group", parcel->getGroupID(), "inspect");
}
mTextGroup->setText(group);
@@ -737,7 +789,7 @@ void LLPanelLandGeneral::refreshNames()
if(auth_buyer_id.notNull())
{
std::string name;
- gCacheName->getFullName(auth_buyer_id, name);
+ name = LLSLURL::buildCommand("agent", auth_buyer_id, "inspect");
mSaleInfoForSale2->setTextArg("[BUYER]", name);
}
else
@@ -750,26 +802,23 @@ void LLPanelLandGeneral::refreshNames()
// virtual
void LLPanelLandGeneral::draw()
{
- refreshNames();
LLPanel::draw();
}
-// static
-void LLPanelLandGeneral::onClickSetGroup(void* userdata)
+void LLPanelLandGeneral::onClickSetGroup()
{
- LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)userdata;
- LLFloaterGroupPicker* fg;
-
- LLFloater* parent_floater = gFloaterView->getParentFloater(panelp);
+ LLFloater* parent_floater = gFloaterView->getParentFloater(this);
- fg = LLFloaterGroupPicker::showInstance(LLSD(gAgent.getID()));
- fg->setSelectCallback( cbGroupID, userdata );
-
- if (parent_floater)
+ LLFloaterGroupPicker* fg = LLFloaterReg::showTypedInstance<LLFloaterGroupPicker>("group_picker", LLSD(gAgent.getID()));
+ if (fg)
{
- LLRect new_rect = gFloaterView->findNeighboringPosition(parent_floater, fg);
- fg->setOrigin(new_rect.mLeft, new_rect.mBottom);
- parent_floater->addDependentFloater(fg);
+ fg->setSelectGroupCallback( boost::bind(&LLPanelLandGeneral::setGroup, this, _1 ));
+ if (parent_floater)
+ {
+ LLRect new_rect = gFloaterView->findNeighboringPosition(parent_floater, fg);
+ fg->setOrigin(new_rect.mLeft, new_rect.mBottom);
+ parent_floater->addDependentFloater(fg);
+ }
}
}
@@ -783,22 +832,15 @@ void LLPanelLandGeneral::onClickProfile(void* data)
if (parcel->getIsGroupOwned())
{
const LLUUID& group_id = parcel->getGroupID();
- LLFloaterGroupInfo::showFromUUID(group_id);
+ LLGroupActions::show(group_id);
}
else
{
const LLUUID& avatar_id = parcel->getOwnerID();
- LLFloaterAvatarInfo::showFromObject(avatar_id);
+ LLAvatarActions::showProfile(avatar_id);
}
}
-// static
-void LLPanelLandGeneral::cbGroupID(LLUUID group_id, void* userdata)
-{
- LLPanelLandGeneral* self = (LLPanelLandGeneral*)userdata;
- self->setGroup(group_id);
-}
-
// public
void LLPanelLandGeneral::setGroup(const LLUUID& group_id)
{
@@ -824,6 +866,17 @@ void LLPanelLandGeneral::onClickBuyLand(void* data)
LLViewerParcelMgr::getInstance()->startBuyLand(*for_group);
}
+// static
+void LLPanelLandGeneral::onClickScriptLimits(void* data)
+{
+ LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data;
+ LLParcel* parcel = panelp->mParcel->getParcel();
+ if(parcel != NULL)
+ {
+ LLFloaterReg::showInstance("script_limits");
+ }
+}
+
BOOL LLPanelLandGeneral::enableDeedToGroup(void* data)
{
LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data;
@@ -884,7 +937,7 @@ void LLPanelLandGeneral::onClickBuyPass(void* data)
args["PARCEL_NAME"] = parcel_name;
args["TIME"] = time;
- LLNotifications::instance().add("LandBuyPass", args, LLSD(), cbBuyPass);
+ LLNotificationsUtil::add("LandBuyPass", args, LLSD(), cbBuyPass);
}
// static
@@ -896,11 +949,12 @@ void LLPanelLandGeneral::onClickStartAuction(void* data)
{
if(parcelp->getForSale())
{
- LLNotifications::instance().add("CannotStartAuctionAlreadyForSale");
+ LLNotificationsUtil::add("CannotStartAuctionAlreadyForSale");
}
else
{
- LLFloaterAuction::show();
+ //LLFloaterAuction::showInstance();
+ LLFloaterReg::showInstance("auction");
}
}
}
@@ -908,7 +962,7 @@ void LLPanelLandGeneral::onClickStartAuction(void* data)
// static
bool LLPanelLandGeneral::cbBuyPass(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
// User clicked OK
@@ -974,7 +1028,8 @@ void LLPanelLandGeneral::onClickStopSellLand(void* data)
// LLPanelLandObjects
//---------------------------------------------------------------------------
LLPanelLandObjects::LLPanelLandObjects(LLParcelSelectionHandle& parcel)
-: LLPanel(std::string("land_objects_panel")), mParcel(parcel)
+ : LLPanel(),
+ mParcel(parcel)
{
}
@@ -1013,11 +1068,9 @@ BOOL LLPanelLandObjects::postBuild()
mSelectedObjects = getChild<LLTextBox>("selected_objects_text");
mCleanOtherObjectsTime = getChild<LLLineEditor>("clean other time");
- mCleanOtherObjectsTime->setFocusLostCallback(onLostFocus, this);
- mCleanOtherObjectsTime->setCommitCallback(onCommitClean);
-
+ mCleanOtherObjectsTime->setFocusLostCallback(boost::bind(onLostFocus, _1, this));
+ mCleanOtherObjectsTime->setCommitCallback(onCommitClean, this);
childSetPrevalidate("clean other time", LLLineEditor::prevalidateNonNegativeS32);
- childSetUserData("clean other time", this);
mBtnRefresh = getChild<LLButton>("Refresh List");
mBtnRefresh->setClickedCallback(onClickRefresh, this);
@@ -1025,14 +1078,15 @@ BOOL LLPanelLandObjects::postBuild()
mBtnReturnOwnerList = getChild<LLButton>("Return objects...");
mBtnReturnOwnerList->setClickedCallback(onClickReturnOwnerList, this);
- mIconAvatarOnline = LLUIImageList::getInstance()->getUIImage("icon_avatar_online.tga");
- mIconAvatarOffline = LLUIImageList::getInstance()->getUIImage("icon_avatar_offline.tga");
- mIconGroup = LLUIImageList::getInstance()->getUIImage("icon_group.tga");
+ mIconAvatarOnline = LLUIImageList::getInstance()->getUIImage("icon_avatar_online.tga", 0);
+ mIconAvatarOffline = LLUIImageList::getInstance()->getUIImage("icon_avatar_offline.tga", 0);
+ mIconGroup = LLUIImageList::getInstance()->getUIImage("icon_group.tga", 0);
mOwnerList = getChild<LLNameListCtrl>("owner list");
mOwnerList->sortByColumnIndex(3, FALSE);
childSetCommitCallback("owner list", onCommitList, this);
- mOwnerList->setDoubleClickCallback(onDoubleClickOwner);
+ mOwnerList->setDoubleClickCallback(onDoubleClickOwner, this);
+ mOwnerList->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
return TRUE;
}
@@ -1064,11 +1118,11 @@ void LLPanelLandObjects::onDoubleClickOwner(void *userdata)
BOOL is_group = cell->getValue().asString() == OWNER_GROUP;
if (is_group)
{
- LLFloaterGroupInfo::showFromUUID(owner_id);
+ LLGroupActions::show(owner_id);
}
else
{
- LLFloaterAvatarInfo::showFromDirectory(owner_id);
+ LLAvatarActions::showProfile(owner_id);
}
}
}
@@ -1254,7 +1308,7 @@ void send_return_objects_message(S32 parcel_local_id, S32 return_type,
bool LLPanelLandObjects::callbackReturnOwnerObjects(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLParcel *parcel = mParcel->getParcel();
if (0 == option)
{
@@ -1264,7 +1318,7 @@ bool LLPanelLandObjects::callbackReturnOwnerObjects(const LLSD& notification, co
LLSD args;
if (owner_id == gAgentID)
{
- LLNotifications::instance().add("OwnedObjectsReturned");
+ LLNotificationsUtil::add("OwnedObjectsReturned");
}
else
{
@@ -1272,7 +1326,7 @@ bool LLPanelLandObjects::callbackReturnOwnerObjects(const LLSD& notification, co
gCacheName->getName(owner_id, first, last);
args["FIRST"] = first;
args["LAST"] = last;
- LLNotifications::instance().add("OtherObjectsReturned", args);
+ LLNotificationsUtil::add("OtherObjectsReturned", args);
}
send_return_objects_message(parcel->getLocalID(), RT_OWNER);
}
@@ -1286,7 +1340,7 @@ bool LLPanelLandObjects::callbackReturnOwnerObjects(const LLSD& notification, co
bool LLPanelLandObjects::callbackReturnGroupObjects(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLParcel *parcel = mParcel->getParcel();
if (0 == option)
{
@@ -1296,7 +1350,7 @@ bool LLPanelLandObjects::callbackReturnGroupObjects(const LLSD& notification, co
gCacheName->getGroupName(parcel->getGroupID(), group_name);
LLSD args;
args["GROUPNAME"] = group_name;
- LLNotifications::instance().add("GroupObjectsReturned", args);
+ LLNotificationsUtil::add("GroupObjectsReturned", args);
send_return_objects_message(parcel->getLocalID(), RT_GROUP);
}
}
@@ -1308,13 +1362,13 @@ bool LLPanelLandObjects::callbackReturnGroupObjects(const LLSD& notification, co
bool LLPanelLandObjects::callbackReturnOtherObjects(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLParcel *parcel = mParcel->getParcel();
if (0 == option)
{
if (parcel)
{
- LLNotifications::instance().add("UnOwnedObjectsReturned");
+ LLNotificationsUtil::add("UnOwnedObjectsReturned");
send_return_objects_message(parcel->getLocalID(), RT_OTHER);
}
}
@@ -1326,7 +1380,7 @@ bool LLPanelLandObjects::callbackReturnOtherObjects(const LLSD& notification, co
bool LLPanelLandObjects::callbackReturnOwnerList(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLParcel *parcel = mParcel->getParcel();
if (0 == option)
{
@@ -1340,12 +1394,12 @@ bool LLPanelLandObjects::callbackReturnOwnerList(const LLSD& notification, const
if (mSelectedIsGroup)
{
args["GROUPNAME"] = mSelectedName;
- LLNotifications::instance().add("GroupObjectsReturned", args);
+ LLNotificationsUtil::add("GroupObjectsReturned", args);
}
else
{
args["NAME"] = mSelectedName;
- LLNotifications::instance().add("OtherObjectsReturned2", args);
+ LLNotificationsUtil::add("OtherObjectsReturned2", args);
}
send_return_objects_message(parcel->getLocalID(), RT_LIST, &(mSelectedOwners));
@@ -1382,11 +1436,11 @@ void LLPanelLandObjects::onClickReturnOwnerList(void* userdata)
args["N"] = llformat("%d",self->mSelectedCount);
if (self->mSelectedIsGroup)
{
- LLNotifications::instance().add("ReturnObjectsDeededToGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerList, self, _1, _2));
+ LLNotificationsUtil::add("ReturnObjectsDeededToGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerList, self, _1, _2));
}
else
{
- LLNotifications::instance().add("ReturnObjectsOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerList, self, _1, _2));
+ LLNotificationsUtil::add("ReturnObjectsOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerList, self, _1, _2));
}
}
@@ -1406,7 +1460,7 @@ void LLPanelLandObjects::onClickRefresh(void* userdata)
// ready the list for results
self->mOwnerList->deleteAllItems();
- self->mOwnerList->addCommentText(std::string("Searching...")); // *TODO: Translate
+ self->mOwnerList->setCommentText(LLTrans::getString("Searching"));
self->mOwnerList->setEnabled(FALSE);
self->mFirstReply = TRUE;
@@ -1468,39 +1522,36 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo
continue;
}
- LLScrollListItem *row = new LLScrollListItem( TRUE, NULL, owner_id);
+ LLNameListCtrl::NameItem item_params;
+ item_params.value = owner_id;
+ item_params.target = is_group_owned ? LLNameListCtrl::GROUP : LLNameListCtrl::INDIVIDUAL;
+
if (is_group_owned)
{
- row->addColumn(self->mIconGroup);
- row->addColumn(OWNER_GROUP, FONT);
+ item_params.columns.add().type("icon").value(self->mIconGroup->getName()).column("type");
+ item_params.columns.add().value(OWNER_GROUP).font(FONT).column("online_status");
}
else if (is_online)
{
- row->addColumn(self->mIconAvatarOnline);
- row->addColumn(OWNER_ONLINE, FONT);
+ item_params.columns.add().type("icon").value(self->mIconAvatarOnline->getName()).column("type");
+ item_params.columns.add().value(OWNER_ONLINE).font(FONT).column("online_status");
}
else // offline
{
- row->addColumn(self->mIconAvatarOffline);
- row->addColumn(OWNER_OFFLINE, FONT);
+ item_params.columns.add().type("icon").value(self->mIconAvatarOffline->getName()).column("type");
+ item_params.columns.add().value(OWNER_OFFLINE).font(FONT).column("online_status");
}
+
// Placeholder for name.
- row->addColumn(LLStringUtil::null, FONT);
+ std::string name;
+ gCacheName->getFullName(owner_id, name);
+ item_params.columns.add().value(name).font(FONT).column("name");
object_count_str = llformat("%d", object_count);
- row->addColumn(object_count_str, FONT);
-
- row->addColumn(formatted_time((time_t)most_recent_time), FONT);
+ item_params.columns.add().value(object_count_str).font(FONT).column("count");
+ item_params.columns.add().value(LLDate((time_t)most_recent_time)).font(FONT).column("mostrecent").type("date");
-
- if (is_group_owned)
- {
- self->mOwnerList->addGroupNameItem(row, ADD_BOTTOM);
- }
- else
- {
- self->mOwnerList->addNameItem(row, ADD_BOTTOM);
- }
+ self->mOwnerList->addRow(item_params);
lldebugs << "object owner " << owner_id << " (" << (is_group_owned ? "group" : "agent")
<< ") owns " << object_count << " objects." << llendl;
@@ -1508,7 +1559,7 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo
// check for no results
if (0 == self->mOwnerList->getItemCount())
{
- self->mOwnerList->addCommentText(std::string("None found.")); // *TODO: Translate
+ self->mOwnerList->setCommentText(LLTrans::getString("NoneFound"));
}
else
{
@@ -1599,14 +1650,14 @@ void LLPanelLandObjects::onClickReturnOwnerObjects(void* userdata)
if (owner_id == gAgent.getID())
{
- LLNotifications::instance().add("ReturnObjectsOwnedBySelf", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerObjects, panelp, _1, _2));
+ LLNotificationsUtil::add("ReturnObjectsOwnedBySelf", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerObjects, panelp, _1, _2));
}
else
{
std::string name;
gCacheName->getFullName(owner_id, name);
args["NAME"] = name;
- LLNotifications::instance().add("ReturnObjectsOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerObjects, panelp, _1, _2));
+ LLNotificationsUtil::add("ReturnObjectsOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerObjects, panelp, _1, _2));
}
}
@@ -1627,7 +1678,7 @@ void LLPanelLandObjects::onClickReturnGroupObjects(void* userdata)
args["N"] = llformat("%d", parcel->getGroupPrimCount());
// create and show confirmation textbox
- LLNotifications::instance().add("ReturnObjectsDeededToGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnGroupObjects, panelp, _1, _2));
+ LLNotificationsUtil::add("ReturnObjectsDeededToGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnGroupObjects, panelp, _1, _2));
}
// static
@@ -1652,7 +1703,7 @@ void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata)
gCacheName->getGroupName(parcel->getGroupID(), group_name);
args["NAME"] = group_name;
- LLNotifications::instance().add("ReturnObjectsNotOwnedByGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, panelp, _1, _2));
+ LLNotificationsUtil::add("ReturnObjectsNotOwnedByGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, panelp, _1, _2));
}
else
{
@@ -1660,7 +1711,7 @@ void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata)
if (owner_id == gAgent.getID())
{
- LLNotifications::instance().add("ReturnObjectsNotOwnedBySelf", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, panelp, _1, _2));
+ LLNotificationsUtil::add("ReturnObjectsNotOwnedBySelf", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, panelp, _1, _2));
}
else
{
@@ -1668,7 +1719,7 @@ void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata)
gCacheName->getFullName(owner_id, name);
args["NAME"] = name;
- LLNotifications::instance().add("ReturnObjectsNotOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, panelp, _1, _2));
+ LLNotificationsUtil::add("ReturnObjectsNotOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, panelp, _1, _2));
}
}
}
@@ -1699,7 +1750,7 @@ void LLPanelLandObjects::onCommitClean(LLUICtrl *caller, void* user_data)
//---------------------------------------------------------------------------
LLPanelLandOptions::LLPanelLandOptions(LLParcelSelectionHandle& parcel)
-: LLPanel(std::string("land_options_panel")),
+: LLPanel(),
mCheckEditObjects(NULL),
mCheckEditGroupObjects(NULL),
mCheckAllObjectEntry(NULL),
@@ -1709,7 +1760,6 @@ LLPanelLandOptions::LLPanelLandOptions(LLParcelSelectionHandle& parcel)
mCheckFly(NULL),
mCheckGroupScripts(NULL),
mCheckOtherScripts(NULL),
- mCheckLandmark(NULL),
mCheckShowDirectory(NULL),
mCategoryCombo(NULL),
mLandingTypeCombo(NULL),
@@ -1719,7 +1769,6 @@ LLPanelLandOptions::LLPanelLandOptions(LLParcelSelectionHandle& parcel)
mClearBtn(NULL),
mMatureCtrl(NULL),
mPushRestrictionCtrl(NULL),
- mPublishHelpButton(NULL),
mParcel(parcel)
{
}
@@ -1743,10 +1792,6 @@ BOOL LLPanelLandOptions::postBuild()
childSetCommitCallback("edit land check", onCommitAny, this);
- mCheckLandmark = getChild<LLCheckBoxCtrl>( "check landmark");
- childSetCommitCallback("check landmark", onCommitAny, this);
-
-
mCheckGroupScripts = getChild<LLCheckBoxCtrl>( "check group scripts");
childSetCommitCallback("check group scripts", onCommitAny, this);
@@ -1792,14 +1837,9 @@ BOOL LLPanelLandOptions::postBuild()
mMatureCtrl = getChild<LLCheckBoxCtrl>( "MatureCheck");
childSetCommitCallback("MatureCheck", onCommitAny, this);
- mPublishHelpButton = getChild<LLButton>("?");
- mPublishHelpButton->setClickedCallback(onClickPublishHelp, this);
-
if (gAgent.wantsPGOnly())
{
// Disable these buttons if they are PG (Teen) users
- mPublishHelpButton->setVisible(FALSE);
- mPublishHelpButton->setEnabled(FALSE);
mMatureCtrl->setVisible(FALSE);
mMatureCtrl->setEnabled(FALSE);
}
@@ -1808,8 +1848,7 @@ BOOL LLPanelLandOptions::postBuild()
mSnapshotCtrl = getChild<LLTextureCtrl>("snapshot_ctrl");
if (mSnapshotCtrl)
{
- mSnapshotCtrl->setCommitCallback( onCommitAny );
- mSnapshotCtrl->setCallbackUserData( this );
+ mSnapshotCtrl->setCommitCallback( onCommitAny, this );
mSnapshotCtrl->setAllowNoTexture ( TRUE );
mSnapshotCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
mSnapshotCtrl->setNonImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
@@ -1873,9 +1912,6 @@ void LLPanelLandOptions::refresh()
mCheckFly ->set(FALSE);
mCheckFly ->setEnabled(FALSE);
- mCheckLandmark ->set(FALSE);
- mCheckLandmark ->setEnabled(FALSE);
-
mCheckGroupScripts ->set(FALSE);
mCheckGroupScripts ->setEnabled(FALSE);
@@ -1896,7 +1932,6 @@ void LLPanelLandOptions::refresh()
mClearBtn->setEnabled(FALSE);
mMatureCtrl->setEnabled(FALSE);
- mPublishHelpButton->setEnabled(FALSE);
}
else
{
@@ -1926,9 +1961,6 @@ void LLPanelLandOptions::refresh()
mCheckFly ->set( parcel->getAllowFly() );
mCheckFly ->setEnabled( can_change_options );
- mCheckLandmark ->set( parcel->getAllowLandmark() );
- mCheckLandmark ->setEnabled( can_change_options );
-
mCheckGroupScripts ->set( parcel->getAllowGroupScripts() || parcel->getAllowOtherScripts());
mCheckGroupScripts ->setEnabled( can_change_options && !parcel->getAllowOtherScripts());
@@ -1975,13 +2007,9 @@ void LLPanelLandOptions::refresh()
mSetBtn->setEnabled( can_change_landing_point );
mClearBtn->setEnabled( can_change_landing_point );
- mPublishHelpButton->setEnabled( can_change_identity );
-
if (gAgent.wantsPGOnly())
{
// Disable these buttons if they are PG (Teen) users
- mPublishHelpButton->setVisible(FALSE);
- mPublishHelpButton->setEnabled(FALSE);
mMatureCtrl->setVisible(FALSE);
mMatureCtrl->setEnabled(FALSE);
}
@@ -2143,7 +2171,7 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata)
BOOL allow_terraform = self->mCheckEditLand->get();
BOOL allow_damage = !self->mCheckSafe->get();
BOOL allow_fly = self->mCheckFly->get();
- BOOL allow_landmark = self->mCheckLandmark->get();
+ BOOL allow_landmark = TRUE; // cannot restrict landmark creation
BOOL allow_group_scripts = self->mCheckGroupScripts->get() || self->mCheckOtherScripts->get();
BOOL allow_other_scripts = self->mCheckOtherScripts->get();
BOOL allow_publish = FALSE;
@@ -2160,7 +2188,7 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata)
if (!allow_other_scripts && region && region->getAllowDamage())
{
- LLNotifications::instance().add("UnableToDisableOutsideScripts");
+ LLNotificationsUtil::add("UnableToDisableOutsideScripts");
return;
}
@@ -2204,7 +2232,7 @@ void LLPanelLandOptions::onClickSet(void* userdata)
if (agent_parcel->getLocalID() != selected_parcel->getLocalID())
{
- LLNotifications::instance().add("MustBeInParcel");
+ LLNotificationsUtil::add("MustBeInParcel");
return;
}
@@ -2234,35 +2262,14 @@ void LLPanelLandOptions::onClickClear(void* userdata)
self->refresh();
}
-// static
-void LLPanelLandOptions::onClickPublishHelp(void*)
-{
- LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
- LLParcel *parcel = LLViewerParcelMgr::getInstance()->getFloatingParcelSelection()->getParcel();
- llassert(region); // Region should never be null.
-
- bool can_change_identity = region && parcel ?
- LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_LAND_CHANGE_IDENTITY) &&
- ! (region->getRegionFlags() & REGION_FLAGS_BLOCK_PARCEL_SEARCH) : false;
-
- if(! can_change_identity)
- {
- LLNotifications::instance().add("ClickPublishHelpLandDisabled");
- }
- else
- {
- LLNotifications::instance().add("ClickPublishHelpLand");
- }
-}
-
-
//---------------------------------------------------------------------------
// LLPanelLandAccess
//---------------------------------------------------------------------------
LLPanelLandAccess::LLPanelLandAccess(LLParcelSelectionHandle& parcel)
-: LLPanel(std::string("land_access_panel")), mParcel(parcel)
+ : LLPanel(),
+ mParcel(parcel)
{
}
@@ -2278,18 +2285,24 @@ BOOL LLPanelLandAccess::postBuild()
childSetCommitCallback("PriceSpin", onCommitAny, this);
childSetCommitCallback("HoursSpin", onCommitAny, this);
- childSetAction("add_allowed", onClickAddAccess, this);
+ childSetAction("add_allowed", boost::bind(&LLPanelLandAccess::onClickAddAccess, this));
childSetAction("remove_allowed", onClickRemoveAccess, this);
- childSetAction("add_banned", onClickAddBanned, this);
+ childSetAction("add_banned", boost::bind(&LLPanelLandAccess::onClickAddBanned, this));
childSetAction("remove_banned", onClickRemoveBanned, this);
mListAccess = getChild<LLNameListCtrl>("AccessList");
if (mListAccess)
+ {
mListAccess->sortByColumnIndex(0, TRUE); // ascending
+ mListAccess->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
+ }
mListBanned = getChild<LLNameListCtrl>("BannedList");
if (mListBanned)
+ {
mListBanned->sortByColumnIndex(0, TRUE); // ascending
+ mListBanned->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
+ }
return TRUE;
}
@@ -2301,13 +2314,15 @@ LLPanelLandAccess::~LLPanelLandAccess()
void LLPanelLandAccess::refresh()
{
+ LLFloater* parent_floater = gFloaterView->getParentFloater(this);
+
if (mListAccess)
mListAccess->deleteAllItems();
if (mListBanned)
mListBanned->deleteAllItems();
LLParcel *parcel = mParcel->getParcel();
-
+
// Display options
if (parcel)
{
@@ -2328,7 +2343,6 @@ void LLPanelLandAccess::refresh()
childSetToolTipArg("AccessList", "[LISTED]", llformat("%d",count));
childSetToolTipArg("AccessList", "[MAX]", llformat("%d",PARCEL_MAX_ACCESS_LIST));
- // *TODO: Translate
for (access_map_const_iterator cit = parcel->mAccessList.begin();
cit != parcel->mAccessList.end(); ++cit)
{
@@ -2336,25 +2350,28 @@ void LLPanelLandAccess::refresh()
std::string suffix;
if (entry.mTime != 0)
{
+ LLStringUtil::format_map_t args;
S32 now = time(NULL);
S32 seconds = entry.mTime - now;
if (seconds < 0) seconds = 0;
suffix.assign(" (");
if (seconds >= 120)
{
- std::string buf = llformat("%d minutes", (seconds/60));
+ args["[MINUTES]"] = llformat("%d", (seconds/60));
+ std::string buf = parent_floater->getString ("Minutes", args);
suffix.append(buf);
}
else if (seconds >= 60)
{
- suffix.append("1 minute");
+ suffix.append("1 " + parent_floater->getString("Minute"));
}
else
{
- std::string buf = llformat("%d seconds", seconds);
+ args["[SECONDS]"] = llformat("%d", seconds);
+ std::string buf = parent_floater->getString ("Seconds", args);
suffix.append(buf);
}
- suffix.append(" remaining)");
+ suffix.append(" " + parent_floater->getString("Remaining") + ")");
}
if (mListAccess)
mListAccess->addNameItem(entry.mID, ADD_SORTED, TRUE, suffix);
@@ -2375,45 +2392,66 @@ void LLPanelLandAccess::refresh()
std::string suffix;
if (entry.mTime != 0)
{
+ LLStringUtil::format_map_t args;
S32 now = time(NULL);
S32 seconds = entry.mTime - now;
if (seconds < 0) seconds = 0;
suffix.assign(" (");
if (seconds >= 120)
{
- std::string buf = llformat("%d minutes", (seconds/60));
+ args["[MINUTES]"] = llformat("%d", (seconds/60));
+ std::string buf = parent_floater->getString ("Minutes", args);
suffix.append(buf);
}
else if (seconds >= 60)
{
- suffix.append("1 minute");
+ suffix.append("1 " + parent_floater->getString("Minute"));
}
else
{
- std::string buf = llformat("%d seconds", seconds);
+ args["[SECONDS]"] = llformat("%d", seconds);
+ std::string buf = parent_floater->getString ("Seconds", args);
suffix.append(buf);
}
- suffix.append(" remaining)");
+ suffix.append(" " + parent_floater->getString("Remaining") + ")");
}
mListBanned->addNameItem(entry.mID, ADD_SORTED, TRUE, suffix);
}
}
+
+ LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
+ if(region)
+ {
+ std::string region_access = "(";
+ region_access += region->getSimAccessString();
+ region_access += ")";
+ childSetLabelArg( "public_access", "[MATURITY]", region_access );
+ }
+ else
+ {
+ childSetLabelArg( "public_access", "[MATURITY]", std::string() );
+ }
+
if(parcel->getRegionDenyAnonymousOverride())
{
childSetValue("limit_payment", TRUE);
+ childSetLabelArg( "limit_payment", "[ESTATE_PAYMENT_LIMIT]", getString("access_estate_defined") );
}
else
{
childSetValue("limit_payment", (parcel->getParcelFlag(PF_DENY_ANONYMOUS)));
+ childSetLabelArg( "limit_payment", "[ESTATE_PAYMENT_LIMIT]", std::string() );
}
if(parcel->getRegionDenyAgeUnverifiedOverride())
{
childSetValue("limit_age_verified", TRUE);
+ childSetLabelArg( "limit_age_verified", "[ESTATE_AGE_LIMIT]", getString("access_estate_defined") );
}
else
{
childSetValue("limit_age_verified", (parcel->getParcelFlag(PF_DENY_AGEUNVERIFIED)));
+ childSetLabelArg( "limit_age_verified", "[ESTATE_AGE_LIMIT]", std::string() );
}
BOOL use_pass = parcel->getParcelFlag(PF_USE_PASS_LIST);
@@ -2657,29 +2695,22 @@ void LLPanelLandAccess::onCommitAny(LLUICtrl *ctrl, void *userdata)
self->refresh();
}
-// static
-void LLPanelLandAccess::onClickAddAccess(void* data)
+void LLPanelLandAccess::onClickAddAccess()
{
- LLPanelLandAccess* panelp = (LLPanelLandAccess*)data;
- if (panelp)
- {
- gFloaterView->getParentFloater(panelp)->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarCBAccess, data) );
- }
+ gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLPanelLandAccess::callbackAvatarCBAccess, this, _1,_2)) );
}
-// static
-void LLPanelLandAccess::callbackAvatarCBAccess(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* userdata)
+void LLPanelLandAccess::callbackAvatarCBAccess(const std::vector<std::string>& names, const std::vector<LLUUID>& ids)
{
- LLPanelLandAccess* panelp = (LLPanelLandAccess*)userdata;
if (!names.empty() && !ids.empty())
{
LLUUID id = ids[0];
- LLParcel* parcel = panelp->mParcel->getParcel();
+ LLParcel* parcel = mParcel->getParcel();
if (parcel)
{
parcel->addToAccessList(id, 0);
LLViewerParcelMgr::getInstance()->sendParcelAccessListUpdate(AL_ACCESS);
- panelp->refresh();
+ refresh();
}
}
}
@@ -2708,25 +2739,23 @@ void LLPanelLandAccess::onClickRemoveAccess(void* data)
}
// static
-void LLPanelLandAccess::onClickAddBanned(void* data)
+void LLPanelLandAccess::onClickAddBanned()
{
- LLPanelLandAccess* panelp = (LLPanelLandAccess*)data;
- gFloaterView->getParentFloater(panelp)->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarCBBanned, data) );
+ gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLPanelLandAccess::callbackAvatarCBBanned, this, _1,_2)));
}
// static
-void LLPanelLandAccess::callbackAvatarCBBanned(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* userdata)
+void LLPanelLandAccess::callbackAvatarCBBanned(const std::vector<std::string>& names, const std::vector<LLUUID>& ids)
{
- LLPanelLandAccess* panelp = (LLPanelLandAccess*)userdata;
if (!names.empty() && !ids.empty())
{
LLUUID id = ids[0];
- LLParcel* parcel = panelp->mParcel->getParcel();
+ LLParcel* parcel = mParcel->getParcel();
if (parcel)
{
parcel->addToBanList(id, 0);
LLViewerParcelMgr::getInstance()->sendParcelAccessListUpdate(AL_BAN);
- panelp->refresh();
+ refresh();
}
}
}
@@ -2758,7 +2787,8 @@ void LLPanelLandAccess::onClickRemoveBanned(void* data)
// LLPanelLandCovenant
//---------------------------------------------------------------------------
LLPanelLandCovenant::LLPanelLandCovenant(LLParcelSelectionHandle& parcel)
-: LLPanel(std::string("land_covenant_panel")), mParcel(parcel)
+ : LLPanel(),
+ mParcel(parcel)
{
}
@@ -2766,12 +2796,6 @@ LLPanelLandCovenant::~LLPanelLandCovenant()
{
}
-BOOL LLPanelLandCovenant::postBuild()
-{
- refresh();
- return TRUE;
-}
-
// virtual
void LLPanelLandCovenant::refresh()
{
@@ -2838,11 +2862,7 @@ void LLPanelLandCovenant::updateCovenantText(const std::string &string)
if (self)
{
LLViewerTextEditor* editor = self->getChild<LLViewerTextEditor>("covenant_editor");
- if (editor)
- {
- editor->setHandleEditKeysDirectly(TRUE);
- editor->setText(string);
- }
+ editor->setText(string);
}
}
diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h
index 4c3de65d71..a4785e8f5b 100644
--- a/indra/newview/llfloaterland.h
+++ b/indra/newview/llfloaterland.h
@@ -38,8 +38,9 @@
#include <vector>
#include "llfloater.h"
-//#include "llviewerimagelist.h"
-#include "llmemory.h" // LLPointer<>
+#include "llpointer.h" // LLPointer<>
+//#include "llviewertexturelist.h"
+#include "llsafehandle.h"
typedef std::set<LLUUID, lluuid_less> uuid_list_t;
const F32 CACHE_REFRESH_TIME = 2.5f;
@@ -58,39 +59,43 @@ class LLTextBox;
class LLTextEditor;
class LLTextureCtrl;
class LLUIImage;
-class LLViewerTextEditor;
class LLParcelSelection;
class LLPanelLandGeneral;
class LLPanelLandObjects;
class LLPanelLandOptions;
+class LLPanelLandAudio;
class LLPanelLandMedia;
class LLPanelLandAccess;
class LLPanelLandBan;
class LLPanelLandRenters;
class LLPanelLandCovenant;
+class LLParcel;
class LLFloaterLand
-: public LLFloater, public LLFloaterSingleton<LLFloaterLand>
+: public LLFloater
{
- friend class LLUISingleton<LLFloaterLand, VisibilityPolicy<LLFloater> >;
+ friend class LLFloaterReg;
public:
static void refreshAll();
static LLPanelLandObjects* getCurrentPanelLandObjects();
static LLPanelLandCovenant* getCurrentPanelLandCovenant();
-
- // Destroys itself on close.
- virtual void onClose(bool app_quitting);
- virtual void onOpen();
+
+ LLParcel* getCurrentSelectedParcel();
+
+ virtual void onOpen(const LLSD& key);
virtual BOOL postBuild();
-protected:
-
+private:
// Does its own instance management, so clients not allowed
// to allocate or destroy.
LLFloaterLand(const LLSD& seed);
virtual ~LLFloaterLand();
+
+ void onVisibilityChange(const LLSD& visible);
+
+protected:
/*virtual*/ void refresh();
@@ -98,6 +103,7 @@ protected:
static void* createPanelLandCovenant(void* data);
static void* createPanelLandObjects(void* data);
static void* createPanelLandOptions(void* data);
+ static void* createPanelLandAudio(void* data);
static void* createPanelLandMedia(void* data);
static void* createPanelLandAccess(void* data);
static void* createPanelLandBan(void* data);
@@ -111,6 +117,7 @@ protected:
LLPanelLandGeneral* mPanelGeneral;
LLPanelLandObjects* mPanelObjects;
LLPanelLandOptions* mPanelOptions;
+ LLPanelLandAudio* mPanelAudio;
LLPanelLandMedia* mPanelMedia;
LLPanelLandAccess* mPanelAccess;
LLPanelLandCovenant* mPanelCovenant;
@@ -138,11 +145,11 @@ public:
void setGroup(const LLUUID& group_id);
static void onClickProfile(void*);
- static void onClickSetGroup(void*);
- static void cbGroupID(LLUUID group_id, void* userdata);
+ void onClickSetGroup();
static BOOL enableDeedToGroup(void*);
static void onClickDeed(void*);
static void onClickBuyLand(void* data);
+ static void onClickScriptLimits(void* data);
static void onClickRelease(void*);
static void onClickReclaim(void*);
static void onClickBuyPass(void* deselect_when_done);
@@ -212,6 +219,7 @@ protected:
LLTextBox* mTextDwell;
LLButton* mBtnBuyLand;
+ LLButton* mBtnScriptLimits;
LLButton* mBtnBuyGroupLand;
// these buttons share the same location, but
@@ -317,7 +325,6 @@ private:
static void onCommitAny(LLUICtrl* ctrl, void *userdata);
static void onClickSet(void* userdata);
static void onClickClear(void* userdata);
- static void onClickPublishHelp(void*);
private:
LLCheckBoxCtrl* mCheckEditObjects;
@@ -329,7 +336,6 @@ private:
LLCheckBoxCtrl* mCheckFly;
LLCheckBoxCtrl* mCheckGroupScripts;
LLCheckBoxCtrl* mCheckOtherScripts;
- LLCheckBoxCtrl* mCheckLandmark;
LLCheckBoxCtrl* mCheckShowDirectory;
LLComboBox* mCategoryCombo;
@@ -343,7 +349,6 @@ private:
LLCheckBoxCtrl *mMatureCtrl;
LLCheckBoxCtrl *mPushRestrictionCtrl;
- LLButton *mPublishHelpButton;
LLSafeHandle<LLParcelSelection>& mParcel;
};
@@ -362,14 +367,15 @@ public:
static void onCommitPublicAccess(LLUICtrl* ctrl, void *userdata);
static void onCommitAny(LLUICtrl* ctrl, void *userdata);
- static void onClickAddAccess(void*);
- static void callbackAvatarCBAccess(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* userdata);
static void onClickRemoveAccess(void*);
- static void onClickAddBanned(void*);
- static void callbackAvatarCBBanned(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* userdata);
static void onClickRemoveBanned(void*);
virtual BOOL postBuild();
+
+ void onClickAddAccess();
+ void onClickAddBanned();
+ void callbackAvatarCBBanned(const std::vector<std::string>& names, const std::vector<LLUUID>& ids);
+ void callbackAvatarCBAccess(const std::vector<std::string>& names, const std::vector<LLUUID>& ids);
protected:
LLNameListCtrl* mListAccess;
@@ -385,7 +391,6 @@ class LLPanelLandCovenant
public:
LLPanelLandCovenant(LLSafeHandle<LLParcelSelection>& parcelp);
virtual ~LLPanelLandCovenant();
- virtual BOOL postBuild();
void refresh();
static void updateCovenantText(const std::string& string);
static void updateEstateName(const std::string& name);
diff --git a/indra/newview/llfloaterlandholdings.cpp b/indra/newview/llfloaterlandholdings.cpp
index bd1186b151..19552ca9c9 100644
--- a/indra/newview/llfloaterlandholdings.cpp
+++ b/indra/newview/llfloaterlandholdings.cpp
@@ -41,58 +41,32 @@
#include "message.h"
#include "llagent.h"
-#include "llbutton.h"
-#include "llfloatergroupinfo.h"
+#include "llfloaterreg.h"
#include "llfloaterworldmap.h"
#include "llproductinforequest.h"
#include "llscrolllistctrl.h"
#include "llstatusbar.h"
#include "lltextbox.h"
+#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "llscrolllistcell.h"
#include "lltrans.h"
#include "lluiconstants.h"
#include "llviewermessage.h"
#include "lluictrlfactory.h"
-// statics
-LLFloaterLandHoldings* LLFloaterLandHoldings::sInstance = NULL;
-
-
-// static
-void LLFloaterLandHoldings::show(void*)
-{
- LLFloaterLandHoldings* floater = new LLFloaterLandHoldings();
- LLUICtrlFactory::getInstance()->buildFloater(floater, "floater_land_holdings.xml");
- floater->center();
-
- // query_id null is known to be us
- const LLUUID& query_id = LLUUID::null;
-
- // look only for parcels we own
- U32 query_flags = DFQ_AGENT_OWNED;
-
- send_places_query(query_id,
- LLUUID::null,
- "",
- query_flags,
- LLParcel::C_ANY,
- "");
-
- // TODO: request updated L$ balance?
- floater->open(); /* Flawfinder: ignore */
-}
-
+#include "llgroupactions.h"
// protected
-LLFloaterLandHoldings::LLFloaterLandHoldings()
-: LLFloater(std::string("land holdings floater")),
+LLFloaterLandHoldings::LLFloaterLandHoldings(const LLSD& key)
+: LLFloater(key),
mActualArea(0),
mBillableArea(0),
mFirstPacketReceived(FALSE),
mSortColumn(""),
mSortAscending(TRUE)
{
- // Instance management.
- sInstance = this;
+// LLUICtrlFactory::getInstance()->buildFloater(floater, "floater_land_holdings.xml");
}
BOOL LLFloaterLandHoldings::postBuild()
@@ -101,8 +75,7 @@ BOOL LLFloaterLandHoldings::postBuild()
childSetAction("Show on Map", onClickMap, this);
// Grant list
- childSetDoubleClickCallback("grant list", onGrantList);
- childSetUserData("grant list", this);
+ getChild<LLScrollListCtrl>("grant list")->setDoubleClickCallback(onGrantList, this);
LLCtrlListInterface *list = childGetListInterface("grant list");
if (!list) return TRUE;
@@ -126,7 +99,9 @@ BOOL LLFloaterLandHoldings::postBuild()
list->addElement(element, ADD_SORTED);
}
-
+
+ center();
+
return TRUE;
}
@@ -134,9 +109,23 @@ BOOL LLFloaterLandHoldings::postBuild()
// protected
LLFloaterLandHoldings::~LLFloaterLandHoldings()
{
- sInstance = NULL;
}
+void LLFloaterLandHoldings::onOpen(const LLSD& key)
+{
+ // query_id null is known to be us
+ const LLUUID& query_id = LLUUID::null;
+
+ // look only for parcels we own
+ U32 query_flags = DFQ_AGENT_OWNED;
+
+ send_places_query(query_id,
+ LLUUID::null,
+ "",
+ query_flags,
+ LLParcel::C_ANY,
+ "");
+}
void LLFloaterLandHoldings::draw()
{
@@ -166,7 +155,7 @@ void LLFloaterLandHoldings::refresh()
// static
void LLFloaterLandHoldings::processPlacesReply(LLMessageSystem* msg, void**)
{
- LLFloaterLandHoldings* self = sInstance;
+ LLFloaterLandHoldings* self = LLFloaterReg::findTypedInstance<LLFloaterLandHoldings>("land_holdings");
// Is this packet from an old, closed window?
if (!self)
@@ -222,50 +211,53 @@ void LLFloaterLandHoldings::processPlacesReply(LLMessageSystem* msg, void**)
land_type = LLTrans::getString("land_type_unknown");
}
- self->mActualArea += actual_area;
- self->mBillableArea += billable_area;
-
- S32 region_x = llround(global_x) % REGION_WIDTH_UNITS;
- S32 region_y = llround(global_y) % REGION_WIDTH_UNITS;
-
- std::string location;
- location = llformat("%s (%d, %d)", sim_name.c_str(), region_x, region_y);
-
- std::string area;
- if(billable_area == actual_area)
+ if(owner_id.notNull())
{
- area = llformat("%d", billable_area);
+ self->mActualArea += actual_area;
+ self->mBillableArea += billable_area;
+
+ S32 region_x = llround(global_x) % REGION_WIDTH_UNITS;
+ S32 region_y = llround(global_y) % REGION_WIDTH_UNITS;
+
+ std::string location;
+ location = llformat("%s (%d, %d)", sim_name.c_str(), region_x, region_y);
+
+ std::string area;
+ if(billable_area == actual_area)
+ {
+ area = llformat("%d", billable_area);
+ }
+ else
+ {
+ area = llformat("%d / %d", billable_area, actual_area);
+ }
+
+ std::string hidden;
+ hidden = llformat("%f %f", global_x, global_y);
+
+ LLSD element;
+ element["columns"][0]["column"] = "name";
+ element["columns"][0]["value"] = name;
+ element["columns"][0]["font"] = "SANSSERIF";
+
+ element["columns"][1]["column"] = "location";
+ element["columns"][1]["value"] = location;
+ element["columns"][1]["font"] = "SANSSERIF";
+
+ element["columns"][2]["column"] = "area";
+ element["columns"][2]["value"] = area;
+ element["columns"][2]["font"] = "SANSSERIF";
+
+ element["columns"][3]["column"] = "type";
+ element["columns"][3]["value"] = land_type;
+ element["columns"][3]["font"] = "SANSSERIF";
+
+ // hidden is always last column
+ element["columns"][4]["column"] = "hidden";
+ element["columns"][4]["value"] = hidden;
+
+ list->addElement(element);
}
- else
- {
- area = llformat("%d / %d", billable_area, actual_area);
- }
-
- std::string hidden;
- hidden = llformat("%f %f", global_x, global_y);
-
- LLSD element;
- element["columns"][0]["column"] = "name";
- element["columns"][0]["value"] = name;
- element["columns"][0]["font"] = "SANSSERIF";
-
- element["columns"][1]["column"] = "location";
- element["columns"][1]["value"] = location;
- element["columns"][1]["font"] = "SANSSERIF";
-
- element["columns"][2]["column"] = "area";
- element["columns"][2]["value"] = area;
- element["columns"][2]["font"] = "SANSSERIF";
-
- element["columns"][3]["column"] = "type";
- element["columns"][3]["value"] = land_type;
- element["columns"][3]["font"] = "SANSSERIF";
-
- // hidden is always last column
- element["columns"][4]["column"] = "hidden";
- element["columns"][4]["value"] = hidden;
-
- list->addElement(element);
}
self->refreshAggregates();
@@ -290,16 +282,17 @@ void LLFloaterLandHoldings::buttonCore(S32 which)
F64 global_z = gAgent.getPositionGlobal().mdV[VZ];
LLVector3d pos_global(global_x, global_y, global_z);
+ LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance();
switch(which)
{
case 0:
gAgent.teleportViaLocation(pos_global);
- gFloaterWorldMap->trackLocation(pos_global);
+ if(floater_world_map) floater_world_map->trackLocation(pos_global);
break;
case 1:
- gFloaterWorldMap->trackLocation(pos_global);
- LLFloaterWorldMap::show(NULL, TRUE);
+ if(floater_world_map) floater_world_map->trackLocation(pos_global);
+ LLFloaterReg::showInstance("world_map", "center");
break;
default:
break;
@@ -311,7 +304,7 @@ void LLFloaterLandHoldings::onClickTeleport(void* data)
{
LLFloaterLandHoldings* self = (LLFloaterLandHoldings*)data;
self->buttonCore(0);
- self->close();
+ self->closeFloater();
}
@@ -331,7 +324,7 @@ void LLFloaterLandHoldings::onGrantList(void* data)
LLUUID group_id = list->getCurrentID();
if (group_id.notNull())
{
- LLFloaterGroupInfo::showFromUUID(group_id);
+ LLGroupActions::show(group_id);
}
}
diff --git a/indra/newview/llfloaterlandholdings.h b/indra/newview/llfloaterlandholdings.h
index def77cf2a8..471ddf7f44 100644
--- a/indra/newview/llfloaterlandholdings.h
+++ b/indra/newview/llfloaterlandholdings.h
@@ -44,10 +44,11 @@ class LLFloaterLandHoldings
: public LLFloater
{
public:
- BOOL postBuild();
-
- static void show(void*);
-
+ LLFloaterLandHoldings(const LLSD& key);
+ virtual ~LLFloaterLandHoldings();
+
+ virtual BOOL postBuild();
+ virtual void onOpen(const LLSD& key);
virtual void draw();
void refresh();
@@ -63,14 +64,9 @@ public:
static void onGrantList(void* data);
protected:
- LLFloaterLandHoldings();
- virtual ~LLFloaterLandHoldings();
-
void refreshAggregates();
protected:
- static LLFloaterLandHoldings* sInstance;
-
// Sum up as packets arrive the total holdings
S32 mActualArea;
S32 mBillableArea;
diff --git a/indra/newview/llfloatermap.cpp b/indra/newview/llfloatermap.cpp
index 3b1e4c7ac7..d18f127f85 100644
--- a/indra/newview/llfloatermap.cpp
+++ b/indra/newview/llfloatermap.cpp
@@ -32,94 +32,218 @@
#include "llviewerprecompiledheaders.h"
+// self include
#include "llfloatermap.h"
+// Library includes
+#include "llfloaterreg.h"
+#include "llfontgl.h"
+#include "llglheaders.h"
+
+// Viewer includes
#include "llagent.h"
-#include "llcolorscheme.h"
#include "llviewercontrol.h"
-#include "lldraghandle.h"
#include "llnetmap.h"
-#include "llregionhandle.h"
-#include "llresizebar.h"
-#include "lluictrlfactory.h"
-
-LLFloaterMap::LLFloaterMap(const LLSD& key)
- :
- LLFloater(std::string("minimap")),
- mPanelMap(NULL)
+#include "lltracker.h"
+#include "llviewercamera.h"
+#include "lldraghandle.h"
+#include "lltextbox.h"
+#include "llviewermenu.h"
+
+//
+// Constants
+//
+const F32 MAP_MINOR_DIR_THRESHOLD = 0.08f;
+
+//
+// Member functions
+//
+
+LLFloaterMap::LLFloaterMap(const LLSD& key)
+ : LLFloater(key),
+ mPopupMenu(NULL),
+ mTextBoxEast(NULL),
+ mTextBoxNorth(NULL),
+ mTextBoxWest(NULL),
+ mTextBoxSouth(NULL),
+ mTextBoxSouthEast(NULL),
+ mTextBoxNorthEast(NULL),
+ mTextBoxNorthWest(NULL),
+ mTextBoxSouthWest(NULL),
+ mMap(NULL)
{
- LLCallbackMap::map_t factory_map;
- factory_map["mini_mapview"] = LLCallbackMap(createPanelMiniMap, this);
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_mini_map.xml", &factory_map, FALSE);
+ //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_map.xml", FALSE);
}
-
-// static
-void* LLFloaterMap::createPanelMiniMap(void* data)
+LLFloaterMap::~LLFloaterMap()
{
- LLFloaterMap* self = (LLFloaterMap*)data;
- self->mPanelMap = new LLNetMap("Mapview");
- return self->mPanelMap;
}
BOOL LLFloaterMap::postBuild()
{
- // Send the drag handle to the back, but make sure close stays on top
+ mMap = getChild<LLNetMap>("Net Map");
+ mMap->setScale(gSavedSettings.getF32("MiniMapScale"));
+ 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");
+
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+
+ registrar.add("Minimap.Zoom", boost::bind(&LLFloaterMap::handleZoom, this, _2));
+ registrar.add("Minimap.Tracker", boost::bind(&LLFloaterMap::handleStopTracking, this, _2));
+
+ mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_mini_map.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if (mPopupMenu && !LLTracker::isTracking(0))
+ {
+ mPopupMenu->setItemEnabled ("Stop Tracking", false);
+ }
+
+ updateMinorDirections();
+
+ // Get the drag handle all the way in back
sendChildToBack(getDragHandle());
- sendChildToFront(getChild<LLButton>("llfloater_close_btn"));
+
setIsChrome(TRUE);
+
+ // keep onscreen
+ gFloaterView->adjustToFitScreen(this, FALSE);
+
return TRUE;
}
-
-LLFloaterMap::~LLFloaterMap()
+BOOL LLFloaterMap::handleDoubleClick( S32 x, S32 y, MASK mask )
{
+ LLFloaterReg::showInstance("world_map");
+ return TRUE;
}
+BOOL LLFloaterMap::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ if (mPopupMenu)
+ {
+ mPopupMenu->buildDrawLabels();
+ mPopupMenu->updateParent(LLMenuGL::sMenuContainer);
+ LLMenuGL::showPopup(this, mPopupMenu, x, y);
+ }
+ return TRUE;
+}
-// virtual
-void LLFloaterMap::onOpen()
+void LLFloaterMap::setDirectionPos( LLTextBox* text_box, F32 rotation )
{
- gFloaterView->adjustToFitScreen(this, FALSE);
+ // Rotation is in radians.
+ // Rotation of 0 means x = 1, y = 0 on the unit circle.
- gSavedSettings.setBOOL("ShowMiniMap", TRUE);
-}
+ F32 map_half_height = (F32)(getRect().getHeight() / 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;
-// virtual
-void LLFloaterMap::onClose(bool app_quitting)
-{
- LLFloater::setVisible(FALSE);
+ text_box->setOrigin(
+ llround(map_half_width - text_half_width + radius * cos( rotation )),
+ llround(map_half_height - text_half_height + radius * sin( rotation )) );
+}
- if (!app_quitting)
+void LLFloaterMap::updateMinorDirections()
+{
+ if (mTextBoxNorthEast == NULL)
{
- gSavedSettings.setBOOL("ShowMiniMap", FALSE);
+ return;
}
-}
-BOOL LLFloaterMap::canClose()
-{
- return !LLApp::isExiting();
-}
+ // Hide minor directions if they cover too much of the map
+ bool show_minors = mTextBoxNorthEast->getRect().getHeight() < MAP_MINOR_DIR_THRESHOLD *
+ llmin(getRect().getWidth(), getRect().getHeight());
+ mTextBoxNorthEast->setVisible(show_minors);
+ mTextBoxNorthWest->setVisible(show_minors);
+ mTextBoxSouthWest->setVisible(show_minors);
+ mTextBoxSouthEast->setVisible(show_minors);
+}
// virtual
void LLFloaterMap::draw()
{
+ F32 rotation = 0;
+
+ static LLUICachedControl<bool> rotate_map("MiniMapRotate", true);
+ if( rotate_map )
+ {
+ // rotate subsequent draws to agent rotation
+ rotation = atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] );
+ }
+
+ setDirectionPos( mTextBoxEast, rotation );
+ setDirectionPos( mTextBoxNorth, rotation + F_PI_BY_TWO );
+ setDirectionPos( mTextBoxWest, rotation + F_PI );
+ setDirectionPos( mTextBoxSouth, rotation + F_PI + F_PI_BY_TWO );
+
+ setDirectionPos( mTextBoxNorthEast, rotation + F_PI_BY_TWO / 2);
+ setDirectionPos( mTextBoxNorthWest, rotation + F_PI_BY_TWO + F_PI_BY_TWO / 2);
+ setDirectionPos( mTextBoxSouthWest, rotation + F_PI + F_PI_BY_TWO / 2);
+ setDirectionPos( mTextBoxSouthEast, rotation + F_PI + F_PI_BY_TWO + F_PI_BY_TWO / 2);
+
// Note: we can't just gAgent.check cameraMouselook() because the transition states are wrong.
if( gAgent.cameraMouselook())
{
setMouseOpaque(FALSE);
getDragHandle()->setMouseOpaque(FALSE);
-
- drawChild(mPanelMap);
}
else
{
setMouseOpaque(TRUE);
getDragHandle()->setMouseOpaque(TRUE);
+ }
+
+ if (LLTracker::isTracking(0))
+ {
+ mPopupMenu->setItemEnabled ("Stop Tracking", true);
+ }
+
+ LLFloater::draw();
+}
+
+void LLFloaterMap::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ LLFloater::reshape(width, height, called_from_parent);
+ updateMinorDirections();
+}
+
+void LLFloaterMap::handleZoom(const LLSD& userdata)
+{
+ std::string level = userdata.asString();
+
+ F32 scale = 0.0f;
+ 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)
+ {
+ gSavedSettings.setF32("MiniMapScale", scale );
+ mMap->setScale(scale);
+ }
+}
- LLFloater::draw();
+void LLFloaterMap::handleStopTracking (const LLSD& userdata)
+{
+ if (mPopupMenu)
+ {
+ mPopupMenu->setItemEnabled ("Stop Tracking", false);
+ LLTracker::stopTracking ((void*)LLTracker::isTracking(NULL));
}
}
diff --git a/indra/newview/llfloatermap.h b/indra/newview/llfloatermap.h
index ec2db27f7a..6c9138c6a7 100644
--- a/indra/newview/llfloatermap.h
+++ b/indra/newview/llfloatermap.h
@@ -35,28 +35,44 @@
#include "llfloater.h"
+class LLMenuGL;
class LLNetMap;
+class LLTextBox;
-class LLFloaterMap :
- public LLFloater,
- public LLFloaterSingleton<LLFloaterMap>
+//
+// Classes
+//
+class LLFloaterMap : public LLFloater
{
- friend class LLUISingleton<LLFloaterMap, VisibilityPolicy<LLFloater> >;
public:
+ LLFloaterMap(const LLSD& key);
virtual ~LLFloaterMap();
-
- static void* createPanelMiniMap(void* data);
-
- BOOL postBuild();
-
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ BOOL handleDoubleClick( S32 x, S32 y, MASK mask );
+ /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
+ /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
/*virtual*/ void draw();
- /*virtual*/ void onOpen();
- /*virtual*/ void onClose(bool app_quitting);
- /*virtual*/ BOOL canClose();
-
+
private:
- LLFloaterMap(const LLSD& key = LLSD());
- LLNetMap* mPanelMap;
+ void handleZoom(const LLSD& userdata);
+ void handleStopTracking (const LLSD& userdata);
+ void setDirectionPos( LLTextBox* text_box, F32 rotation );
+ void updateMinorDirections();
+
+ LLMenuGL* mPopupMenu;
+
+ LLTextBox* mTextBoxEast;
+ LLTextBox* mTextBoxNorth;
+ LLTextBox* mTextBoxWest;
+ LLTextBox* mTextBoxSouth;
+
+ LLTextBox* mTextBoxSouthEast;
+ LLTextBox* mTextBoxNorthEast;
+ LLTextBox* mTextBoxNorthWest;
+ LLTextBox* mTextBoxSouthWest;
+
+ LLNetMap* mMap;
};
#endif // LL_LLFLOATERMAP_H
diff --git a/indra/newview/llfloatermediabrowser.cpp b/indra/newview/llfloatermediabrowser.cpp
new file mode 100644
index 0000000000..5673550fbe
--- /dev/null
+++ b/indra/newview/llfloatermediabrowser.cpp
@@ -0,0 +1,336 @@
+/**
+ * @file llfloatermediabrowser.cpp
+ * @brief media browser floater - uses embedded media browser control
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ *
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloatermediabrowser.h"
+
+#include "llfloaterreg.h"
+#include "llparcel.h"
+#include "llpluginclassmedia.h"
+#include "lluictrlfactory.h"
+#include "llmediactrl.h"
+#include "llviewerwindow.h"
+#include "llviewercontrol.h"
+#include "llviewerparcelmgr.h"
+#include "llweb.h"
+#include "llui.h"
+#include "roles_constants.h"
+
+#include "llurlhistory.h"
+#include "llmediactrl.h"
+#include "llviewermedia.h"
+#include "llviewerparcelmedia.h"
+#include "llcombobox.h"
+
+
+// TEMP
+#include "llsdutil.h"
+
+LLFloaterMediaBrowser::LLFloaterMediaBrowser(const LLSD& key)
+ : LLFloater(key)
+{
+// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_media_browser.xml");
+
+}
+
+void LLFloaterMediaBrowser::draw()
+{
+ childSetEnabled("go", !mAddressCombo->getValue().asString().empty());
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ if(parcel)
+ {
+ childSetVisible("parcel_owner_controls", LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_LAND_CHANGE_MEDIA));
+ childSetEnabled("assign", !mAddressCombo->getValue().asString().empty());
+ }
+ bool show_time_controls = false;
+ bool media_playing = false;
+ if(mBrowser)
+ {
+ LLPluginClassMedia* media_plugin = mBrowser->getMediaPlugin();
+ if(media_plugin)
+ {
+ show_time_controls = media_plugin->pluginSupportsMediaTime();
+ media_playing = media_plugin->getStatus() == LLPluginClassMediaOwner::MEDIA_PLAYING;
+ }
+ }
+ childSetVisible("rewind", show_time_controls);
+ childSetVisible("play", show_time_controls && ! media_playing);
+ childSetVisible("pause", show_time_controls && media_playing);
+ childSetVisible("stop", show_time_controls);
+ childSetVisible("seek", show_time_controls);
+
+ childSetEnabled("play", ! media_playing);
+ childSetEnabled("stop", media_playing);
+
+ childSetEnabled("back", mBrowser->canNavigateBack());
+ childSetEnabled("forward", mBrowser->canNavigateForward());
+
+ LLFloater::draw();
+}
+
+BOOL LLFloaterMediaBrowser::postBuild()
+{
+ mBrowser = getChild<LLMediaCtrl>("browser");
+ mBrowser->addObserver(this);
+
+ mAddressCombo = getChild<LLComboBox>("address");
+ mAddressCombo->setCommitCallback(onEnterAddress, this);
+
+ childSetAction("back", onClickBack, this);
+ childSetAction("forward", onClickForward, this);
+ childSetAction("reload", onClickRefresh, this);
+ childSetAction("rewind", onClickRewind, this);
+ childSetAction("play", onClickPlay, this);
+ childSetAction("stop", onClickStop, this);
+ childSetAction("pause", onClickPlay, this);
+ childSetAction("seek", onClickSeek, this);
+ childSetAction("go", onClickGo, this);
+ childSetAction("close", onClickClose, this);
+ childSetAction("open_browser", onClickOpenWebBrowser, this);
+ childSetAction("assign", onClickAssign, this);
+
+ buildURLHistory();
+ return TRUE;
+}
+
+void LLFloaterMediaBrowser::buildURLHistory()
+{
+ LLCtrlListInterface* url_list = childGetListInterface("address");
+ if (url_list)
+ {
+ url_list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ }
+
+ // Get all of the entries in the "browser" collection
+ LLSD browser_history = LLURLHistory::getURLHistory("browser");
+
+ LLSD::array_iterator iter_history =
+ browser_history.beginArray();
+ LLSD::array_iterator end_history =
+ browser_history.endArray();
+ for(; iter_history != end_history; ++iter_history)
+ {
+ std::string url = (*iter_history).asString();
+ if(! url.empty())
+ url_list->addSimpleElement(url);
+ }
+
+ // initialize URL history in the plugin
+ if(mBrowser && mBrowser->getMediaPlugin())
+ {
+ mBrowser->getMediaPlugin()->initializeUrlHistory(browser_history);
+ }
+}
+
+std::string LLFloaterMediaBrowser::getSupportURL()
+{
+ return getString("support_page_url");
+}
+
+//virtual
+void LLFloaterMediaBrowser::onClose(bool app_quitting)
+{
+ //setVisible(FALSE);
+ destroy();
+}
+
+void LLFloaterMediaBrowser::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
+{
+ if(event == MEDIA_EVENT_LOCATION_CHANGED)
+ {
+ setCurrentURL(self->getLocation());
+ }
+ else if(event == MEDIA_EVENT_NAVIGATE_COMPLETE)
+ {
+ // This is the event these flags are sent with.
+ childSetEnabled("back", self->getHistoryBackAvailable());
+ childSetEnabled("forward", self->getHistoryForwardAvailable());
+ }
+}
+void LLFloaterMediaBrowser::setCurrentURL(const std::string& url)
+{
+ mCurrentURL = url;
+
+ // redirects will navigate momentarily to about:blank, don't add to history
+ if (mCurrentURL != "about:blank")
+ {
+ mAddressCombo->remove(mCurrentURL);
+ mAddressCombo->add(mCurrentURL, ADD_SORTED);
+ mAddressCombo->selectByValue(mCurrentURL);
+
+ // Serialize url history
+ LLURLHistory::removeURL("browser", mCurrentURL);
+ LLURLHistory::addURL("browser", mCurrentURL);
+ }
+ childSetEnabled("back", mBrowser->canNavigateBack());
+ childSetEnabled("forward", mBrowser->canNavigateForward());
+ childSetEnabled("reload", TRUE);
+}
+
+void LLFloaterMediaBrowser::onOpen(const LLSD& media_url)
+{
+ LLFloater::onOpen(media_url);
+ openMedia(media_url.asString());
+}
+
+//static
+void LLFloaterMediaBrowser::onEnterAddress(LLUICtrl* ctrl, void* user_data)
+{
+ LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data;
+ self->mBrowser->navigateTo(self->mAddressCombo->getValue().asString());
+}
+
+//static
+void LLFloaterMediaBrowser::onClickRefresh(void* user_data)
+{
+ LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data;
+
+ self->mAddressCombo->remove(0);
+ self->mBrowser->navigateTo(self->mCurrentURL);
+}
+
+//static
+void LLFloaterMediaBrowser::onClickForward(void* user_data)
+{
+ LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data;
+
+ self->mBrowser->navigateForward();
+}
+
+//static
+void LLFloaterMediaBrowser::onClickBack(void* user_data)
+{
+ LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data;
+
+ self->mBrowser->navigateBack();
+}
+
+//static
+void LLFloaterMediaBrowser::onClickGo(void* user_data)
+{
+ LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data;
+
+ self->mBrowser->navigateTo(self->mAddressCombo->getValue().asString());
+}
+
+//static
+void LLFloaterMediaBrowser::onClickClose(void* user_data)
+{
+ LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data;
+
+ self->closeFloater();
+}
+
+//static
+void LLFloaterMediaBrowser::onClickOpenWebBrowser(void* user_data)
+{
+ LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data;
+
+ std::string url = self->mCurrentURL.empty() ?
+ self->mBrowser->getHomePageUrl() :
+ self->mCurrentURL;
+ LLWeb::loadURLExternal(url);
+}
+
+void LLFloaterMediaBrowser::onClickAssign(void* user_data)
+{
+ LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data;
+
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ if (!parcel)
+ {
+ return;
+ }
+ std::string media_url = self->mAddressCombo->getValue().asString();
+ LLStringUtil::trim(media_url);
+
+ if(parcel->getMediaType() != "text/html")
+ {
+ parcel->setMediaURL(media_url);
+ parcel->setMediaCurrentURL(media_url);
+ parcel->setMediaType(std::string("text/html"));
+ LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel, true );
+ LLViewerParcelMedia::sendMediaNavigateMessage(media_url);
+ LLViewerParcelMedia::stop();
+ // LLViewerParcelMedia::update( parcel );
+ }
+ LLViewerParcelMedia::sendMediaNavigateMessage(media_url);
+}
+//static
+void LLFloaterMediaBrowser::onClickRewind(void* user_data)
+{
+ LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data;
+
+ if(self->mBrowser->getMediaPlugin())
+ self->mBrowser->getMediaPlugin()->start(-2.0f);
+}
+//static
+void LLFloaterMediaBrowser::onClickPlay(void* user_data)
+{
+ LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data;
+
+ LLPluginClassMedia* plugin = self->mBrowser->getMediaPlugin();
+ if(plugin)
+ {
+ if(plugin->getStatus() == LLPluginClassMediaOwner::MEDIA_PLAYING)
+ {
+ plugin->pause();
+ }
+ else
+ {
+ plugin->start();
+ }
+ }
+}
+//static
+void LLFloaterMediaBrowser::onClickStop(void* user_data)
+{
+ LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data;
+
+ if(self->mBrowser->getMediaPlugin())
+ self->mBrowser->getMediaPlugin()->stop();
+}
+//static
+void LLFloaterMediaBrowser::onClickSeek(void* user_data)
+{
+ LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data;
+
+ if(self->mBrowser->getMediaPlugin())
+ self->mBrowser->getMediaPlugin()->start(2.0f);
+}
+void LLFloaterMediaBrowser::openMedia(const std::string& media_url)
+{
+ mBrowser->setHomePageUrl(media_url);
+ mBrowser->navigateTo(media_url);
+ setCurrentURL(media_url);
+}
diff --git a/indra/newview/llfloatermediabrowser.h b/indra/newview/llfloatermediabrowser.h
new file mode 100644
index 0000000000..c315f9e797
--- /dev/null
+++ b/indra/newview/llfloatermediabrowser.h
@@ -0,0 +1,83 @@
+/**
+ * @file llfloatermediabrowser.h
+ * @brief media browser floater - uses embedded media browser control
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ *
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATERMEDIABROWSER_H
+#define LL_LLFLOATERMEDIABROWSER_H
+
+#include "llfloater.h"
+#include "llmediactrl.h"
+
+
+class LLComboBox;
+class LLMediaCtrl;
+
+class LLFloaterMediaBrowser :
+ public LLFloater,
+ public LLViewerMediaObserver
+{
+public:
+ LLFloaterMediaBrowser(const LLSD& key);
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onClose(bool app_quitting);
+ /*virtual*/ void draw();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ // inherited from LLViewerMediaObserver
+ /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
+
+ void openMedia(const std::string& media_url);
+ void buildURLHistory();
+ std::string getSupportURL();
+ void setCurrentURL(const std::string& url);
+
+ static void onEnterAddress(LLUICtrl* ctrl, void* user_data);
+ static void onClickRefresh(void* user_data);
+ static void onClickBack(void* user_data);
+ static void onClickForward(void* user_data);
+ static void onClickGo(void* user_data);
+ static void onClickClose(void* user_data);
+ static void onClickOpenWebBrowser(void* user_data);
+ static void onClickAssign(void* user_data);
+ static void onClickRewind(void* user_data);
+ static void onClickPlay(void* user_data);
+ static void onClickStop(void* user_data);
+ static void onClickSeek(void* user_data);
+
+private:
+ LLMediaCtrl* mBrowser;
+ LLComboBox* mAddressCombo;
+ std::string mCurrentURL;
+};
+
+#endif // LL_LLFLOATERMEDIABROWSER_H
+
diff --git a/indra/newview/llfloatermediasettings.cpp b/indra/newview/llfloatermediasettings.cpp
new file mode 100644
index 0000000000..976af121ae
--- /dev/null
+++ b/indra/newview/llfloatermediasettings.cpp
@@ -0,0 +1,308 @@
+/**
+ * @file llfloatermediasettings.cpp
+ * @brief Tabbed dialog for media settings - class implementation
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterreg.h"
+#include "llfloatermediasettings.h"
+#include "llpanelmediasettingsgeneral.h"
+#include "llpanelmediasettingssecurity.h"
+#include "llpanelmediasettingspermissions.h"
+#include "llviewercontrol.h"
+#include "lluictrlfactory.h"
+#include "llbutton.h"
+#include "llselectmgr.h"
+#include "llsdutil.h"
+
+LLFloaterMediaSettings* LLFloaterMediaSettings::sInstance = NULL;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+LLFloaterMediaSettings::LLFloaterMediaSettings(const LLSD& key)
+ : LLFloater(key),
+ mTabContainer(NULL),
+ mPanelMediaSettingsGeneral(NULL),
+ mPanelMediaSettingsSecurity(NULL),
+ mPanelMediaSettingsPermissions(NULL),
+ mWaitingToClose( false ),
+ mIdenticalHasMediaInfo( true ),
+ mMultipleMedia(false),
+ mMultipleValidMedia(false)
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+LLFloaterMediaSettings::~LLFloaterMediaSettings()
+{
+ if ( mPanelMediaSettingsGeneral )
+ {
+ delete mPanelMediaSettingsGeneral;
+ mPanelMediaSettingsGeneral = NULL;
+ }
+
+ if ( mPanelMediaSettingsSecurity )
+ {
+ delete mPanelMediaSettingsSecurity;
+ mPanelMediaSettingsSecurity = NULL;
+ }
+
+ if ( mPanelMediaSettingsPermissions )
+ {
+ delete mPanelMediaSettingsPermissions;
+ mPanelMediaSettingsPermissions = NULL;
+ }
+
+ sInstance = NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLFloaterMediaSettings::postBuild()
+{
+ mApplyBtn = getChild<LLButton>("Apply");
+ mApplyBtn->setClickedCallback(onBtnApply, this);
+
+ mCancelBtn = getChild<LLButton>("Cancel");
+ mCancelBtn->setClickedCallback(onBtnCancel, this);
+
+ mOKBtn = getChild<LLButton>("OK");
+ mOKBtn->setClickedCallback(onBtnOK, this);
+
+ mTabContainer = getChild<LLTabContainer>( "tab_container" );
+
+ mPanelMediaSettingsGeneral = new LLPanelMediaSettingsGeneral();
+ mTabContainer->addTabPanel(
+ LLTabContainer::TabPanelParams().
+ panel(mPanelMediaSettingsGeneral));
+ mPanelMediaSettingsGeneral->setParent( this );
+
+ // note that "permissions" tab is really "Controls" tab - refs to 'perms' and
+ // 'permissions' not changed to 'controls' since we don't want to change
+ // shared files in server code and keeping everything the same seemed best.
+ mPanelMediaSettingsPermissions = new LLPanelMediaSettingsPermissions();
+ mTabContainer->addTabPanel(
+ LLTabContainer::TabPanelParams().
+ panel(mPanelMediaSettingsPermissions));
+
+ mPanelMediaSettingsSecurity = new LLPanelMediaSettingsSecurity();
+ mTabContainer->addTabPanel(
+ LLTabContainer::TabPanelParams().
+ panel(mPanelMediaSettingsSecurity));
+ mPanelMediaSettingsSecurity->setParent( this );
+
+ // restore the last tab viewed from persistance variable storage
+ if (!mTabContainer->selectTab(gSavedSettings.getS32("LastMediaSettingsTab")))
+ {
+ mTabContainer->selectFirstTab();
+ };
+
+ sInstance = this;
+
+ return TRUE;
+}
+
+//static
+LLFloaterMediaSettings* LLFloaterMediaSettings::getInstance()
+{
+ if ( !sInstance )
+ {
+ sInstance = (LLFloaterReg::getTypedInstance<LLFloaterMediaSettings>("media_settings"));
+ }
+
+ return sInstance;
+}
+
+//static
+void LLFloaterMediaSettings::apply()
+{
+ if (sInstance->haveValuesChanged())
+ {
+ LLSD settings;
+ sInstance->mPanelMediaSettingsGeneral->preApply();
+ sInstance->mPanelMediaSettingsGeneral->getValues( settings );
+ sInstance->mPanelMediaSettingsSecurity->preApply();
+ sInstance->mPanelMediaSettingsSecurity->getValues( settings );
+ sInstance->mPanelMediaSettingsPermissions->preApply();
+ sInstance->mPanelMediaSettingsPermissions->getValues( settings );
+ LLSelectMgr::getInstance()->selectionSetMedia( LLTextureEntry::MF_HAS_MEDIA );
+ LLSelectMgr::getInstance()->selectionSetMediaData(settings);
+ sInstance->mPanelMediaSettingsGeneral->postApply();
+ sInstance->mPanelMediaSettingsSecurity->postApply();
+ sInstance->mPanelMediaSettingsPermissions->postApply();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void LLFloaterMediaSettings::onClose(bool app_quitting)
+{
+ if(mPanelMediaSettingsGeneral)
+ {
+ mPanelMediaSettingsGeneral->onClose(app_quitting);
+ }
+ LLFloaterReg::hideInstance("whitelist_entry");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//static
+void LLFloaterMediaSettings::initValues( const LLSD& media_settings, bool editable )
+{
+ sInstance->clearValues(editable);
+ // update all panels with values from simulator
+ sInstance->mPanelMediaSettingsGeneral->
+ initValues( sInstance->mPanelMediaSettingsGeneral, media_settings, editable );
+
+ sInstance->mPanelMediaSettingsSecurity->
+ initValues( sInstance->mPanelMediaSettingsSecurity, media_settings, editable );
+
+ sInstance->mPanelMediaSettingsPermissions->
+ initValues( sInstance->mPanelMediaSettingsPermissions, media_settings, editable );
+
+ // Squirrel away initial values
+ sInstance->mInitialValues.clear();
+ sInstance->mPanelMediaSettingsGeneral->getValues( sInstance->mInitialValues );
+ sInstance->mPanelMediaSettingsSecurity->getValues( sInstance->mInitialValues );
+ sInstance->mPanelMediaSettingsPermissions->getValues( sInstance->mInitialValues );
+
+ sInstance->mApplyBtn->setEnabled(editable);
+ sInstance->mOKBtn->setEnabled(editable);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLFloaterMediaSettings::commitFields()
+{
+ if (hasFocus())
+ {
+ LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
+ if (cur_focus->acceptsTextInput())
+ {
+ cur_focus->onCommit();
+ };
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//static
+void LLFloaterMediaSettings::clearValues( bool editable)
+{
+ // clean up all panels before updating
+ sInstance->mPanelMediaSettingsGeneral ->clearValues(sInstance->mPanelMediaSettingsGeneral, editable);
+ sInstance->mPanelMediaSettingsSecurity ->clearValues(sInstance->mPanelMediaSettingsSecurity, editable);
+ sInstance->mPanelMediaSettingsPermissions->clearValues(sInstance->mPanelMediaSettingsPermissions, editable);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLFloaterMediaSettings::onBtnOK( void* userdata )
+{
+ sInstance->commitFields();
+
+ sInstance->apply();
+
+ sInstance->closeFloater();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLFloaterMediaSettings::onBtnApply( void* userdata )
+{
+ sInstance->commitFields();
+
+ sInstance->apply();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLFloaterMediaSettings::onBtnCancel( void* userdata )
+{
+ sInstance->closeFloater();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLFloaterMediaSettings::onTabChanged(void* user_data, bool from_click)
+{
+ LLTabContainer* self = (LLTabContainer*)user_data;
+ gSavedSettings.setS32("LastMediaSettingsTab", self->getCurrentPanelIndex());
+}
+////////////////////////////////////////////////////////////////////////////////
+//
+const std::string LLFloaterMediaSettings::getHomeUrl()
+{
+ if ( mPanelMediaSettingsGeneral )
+ return mPanelMediaSettingsGeneral->getHomeUrl();
+ else
+ return std::string( "" );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+void LLFloaterMediaSettings::draw()
+{
+ if (NULL != mApplyBtn)
+ {
+ // Set the enabled state of the "Apply" button if values changed
+ mApplyBtn->setEnabled( haveValuesChanged() );
+ }
+
+ LLFloater::draw();
+}
+
+
+//private
+bool LLFloaterMediaSettings::haveValuesChanged() const
+{
+ bool values_changed = false;
+ // *NOTE: The code below is very inefficient. Better to do this
+ // only when data change.
+ // Every frame, check to see what the values are. If they are not
+ // the same as the initial media data, enable the OK/Apply buttons
+ LLSD settings;
+ sInstance->mPanelMediaSettingsGeneral->getValues( settings );
+ sInstance->mPanelMediaSettingsSecurity->getValues( settings );
+ sInstance->mPanelMediaSettingsPermissions->getValues( settings );
+ LLSD::map_const_iterator iter = settings.beginMap();
+ LLSD::map_const_iterator end = settings.endMap();
+ for ( ; iter != end; ++iter )
+ {
+ const std::string &current_key = iter->first;
+ const LLSD &current_value = iter->second;
+ if ( ! llsd_equals(current_value, mInitialValues[current_key]))
+ {
+ values_changed = true;
+ break;
+ }
+ }
+ return values_changed;
+}
+
diff --git a/indra/newview/llfloatermediasettings.h b/indra/newview/llfloatermediasettings.h
new file mode 100644
index 0000000000..cdfd5aa8ae
--- /dev/null
+++ b/indra/newview/llfloatermediasettings.h
@@ -0,0 +1,94 @@
+/**
+ * @file llfloatermediasettings.cpp
+ * @brief Tabbed dialog for media settings - class definition
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATERMEDIASETTINGS_H
+#define LL_LLFLOATERMEDIASETTINGS_H
+
+#include "llfloater.h"
+#include "lltabcontainer.h"
+
+class LLPanelMediaSettingsGeneral;
+class LLPanelMediaSettingsSecurity;
+class LLPanelMediaSettingsPermissions;
+
+class LLFloaterMediaSettings :
+ public LLFloater
+{
+public:
+ LLFloaterMediaSettings(const LLSD& key);
+ ~LLFloaterMediaSettings();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onClose(bool app_quitting);
+
+ static LLFloaterMediaSettings* getInstance();
+ static void apply();
+ static void initValues( const LLSD& media_settings , bool editable);
+ static void clearValues( bool editable);
+
+ LLPanelMediaSettingsSecurity* getPanelSecurity(){return mPanelMediaSettingsSecurity;};
+ const std::string getHomeUrl();
+ //bool passesWhiteList( const std::string& test_url );
+
+ virtual void draw();
+
+ bool mIdenticalHasMediaInfo;
+ bool mMultipleMedia;
+ bool mMultipleValidMedia;
+
+protected:
+ LLButton *mOKBtn;
+ LLButton *mCancelBtn;
+ LLButton *mApplyBtn;
+
+ LLTabContainer *mTabContainer;
+ LLPanelMediaSettingsGeneral* mPanelMediaSettingsGeneral;
+ LLPanelMediaSettingsSecurity* mPanelMediaSettingsSecurity;
+ LLPanelMediaSettingsPermissions* mPanelMediaSettingsPermissions;
+
+ static void onBtnOK(void*);
+ static void onBtnCancel(void*);
+ static void onBtnApply(void*);
+ static void onTabChanged(void* user_data, bool from_click);
+ void commitFields();
+
+ static LLFloaterMediaSettings* sInstance;
+
+private:
+
+ bool haveValuesChanged() const;
+
+ LLSD mInitialValues;
+ bool mWaitingToClose;
+};
+
+#endif // LL_LLFLOATERMEDIASETTINGS_H
diff --git a/indra/newview/llfloatermemleak.cpp b/indra/newview/llfloatermemleak.cpp
index df51918e35..529bd68e03 100644
--- a/indra/newview/llfloatermemleak.cpp
+++ b/indra/newview/llfloatermemleak.cpp
@@ -42,24 +42,56 @@
#include "llmath.h"
#include "llviewerwindow.h"
-LLFloaterMemLeak* LLFloaterMemLeak::sInstance = NULL;
U32 LLFloaterMemLeak::sMemLeakingSpeed = 0 ; //bytes leaked per frame
U32 LLFloaterMemLeak::sMaxLeakedMem = 0 ; //maximum allowed leaked memory
U32 LLFloaterMemLeak::sTotalLeaked = 0 ;
S32 LLFloaterMemLeak::sStatus = LLFloaterMemLeak::STOP ;
BOOL LLFloaterMemLeak::sbAllocationFailed = FALSE ;
-LLFloaterMemLeak::LLFloaterMemLeak() : LLFloater("Memory Leaking Simulation Floater")
+LLFloaterMemLeak::LLFloaterMemLeak(const LLSD& key)
+ : LLFloater(key)
{
+ setTitle("Memory Leaking Simulation Floater");
+ mCommitCallbackRegistrar.add("MemLeak.ChangeLeakingSpeed", boost::bind(&LLFloaterMemLeak::onChangeLeakingSpeed, this));
+ mCommitCallbackRegistrar.add("MemLeak.ChangeMaxMemLeaking", boost::bind(&LLFloaterMemLeak::onChangeMaxMemLeaking, this));
+ mCommitCallbackRegistrar.add("MemLeak.Start", boost::bind(&LLFloaterMemLeak::onClickStart, this));
+ mCommitCallbackRegistrar.add("MemLeak.Stop", boost::bind(&LLFloaterMemLeak::onClickStop, this));
+ mCommitCallbackRegistrar.add("MemLeak.Release", boost::bind(&LLFloaterMemLeak::onClickRelease, this));
+ mCommitCallbackRegistrar.add("MemLeak.Close", boost::bind(&LLFloaterMemLeak::onClickClose, this));
}
+//----------------------------------------------
+BOOL LLFloaterMemLeak::postBuild(void)
+{
+ F32 a, b ;
+ a = childGetValue("leak_speed").asReal();
+ if(a > (F32)(0xFFFFFFFF))
+ {
+ sMemLeakingSpeed = 0xFFFFFFFF ;
+ }
+ else
+ {
+ sMemLeakingSpeed = (U32)a ;
+ }
+ b = childGetValue("max_leak").asReal();
+ if(b > (F32)0xFFF)
+ {
+ sMaxLeakedMem = 0xFFFFFFFF ;
+ }
+ else
+ {
+ sMaxLeakedMem = ((U32)b) << 20 ;
+ }
+
+ sbAllocationFailed = FALSE ;
+ return TRUE ;
+}
LLFloaterMemLeak::~LLFloaterMemLeak()
{
release() ;
sMemLeakingSpeed = 0 ; //bytes leaked per frame
sMaxLeakedMem = 0 ; //maximum allowed leaked memory
- sInstance = NULL ;
}
void LLFloaterMemLeak::release()
@@ -115,79 +147,56 @@ void LLFloaterMemLeak::idle()
}
//----------------------
-void LLFloaterMemLeak::onChangeLeakingSpeed(LLUICtrl* ctrl, void* userData)
+void LLFloaterMemLeak::onChangeLeakingSpeed()
{
- LLFloaterMemLeak *mem_leak = (LLFloaterMemLeak *)userData;
- if (mem_leak)
- {
- F32 tmp ;
- tmp = mem_leak->childGetValue("leak_speed").asReal();
+ F32 tmp ;
+ tmp =childGetValue("leak_speed").asReal();
- if(tmp > (F32)0xFFFFFFFF)
- {
- sMemLeakingSpeed = 0xFFFFFFFF ;
- }
- else
- {
- sMemLeakingSpeed = (U32)tmp ;
- }
+ if(tmp > (F32)0xFFFFFFFF)
+ {
+ sMemLeakingSpeed = 0xFFFFFFFF ;
}
+ else
+ {
+ sMemLeakingSpeed = (U32)tmp ;
+ }
+
}
-void LLFloaterMemLeak::onChangeMaxMemLeaking(LLUICtrl* ctrl, void* userData)
+void LLFloaterMemLeak::onChangeMaxMemLeaking()
{
- LLFloaterMemLeak *mem_leak = (LLFloaterMemLeak *)userData;
- if (mem_leak)
+
+ F32 tmp ;
+ tmp =childGetValue("max_leak").asReal();
+ if(tmp > (F32)0xFFF)
{
- F32 tmp ;
- tmp = mem_leak->childGetValue("max_leak").asReal();
- if(tmp > (F32)0xFFF)
- {
- sMaxLeakedMem = 0xFFFFFFFF ;
- }
- else
- {
- sMaxLeakedMem = ((U32)tmp) << 20 ;
- }
+ sMaxLeakedMem = 0xFFFFFFFF ;
}
+ else
+ {
+ sMaxLeakedMem = ((U32)tmp) << 20 ;
+ }
+
}
-void LLFloaterMemLeak::onClickStart(void* userData)
+void LLFloaterMemLeak::onClickStart()
{
sStatus = START ;
}
-void LLFloaterMemLeak::onClickStop(void* userData)
+void LLFloaterMemLeak::onClickStop()
{
sStatus = STOP ;
}
-void LLFloaterMemLeak::onClickRelease(void* userData)
+void LLFloaterMemLeak::onClickRelease()
{
sStatus = RELEASE ;
}
-void LLFloaterMemLeak::onClickClose(void* userData)
-{
- if (sInstance)
- {
- sInstance->setVisible(FALSE);
- }
-}
-
-//----------------------------------------------
-
-BOOL LLFloaterMemLeak::postBuild(void)
+void LLFloaterMemLeak::onClickClose()
{
- childSetCommitCallback("leak_speed", onChangeLeakingSpeed, this);
- childSetCommitCallback("max_leak", onChangeMaxMemLeaking, this);
-
- childSetAction("start_btn", onClickStart, this);
- childSetAction("stop_btn", onClickStop, this);
- childSetAction("release_btn", onClickRelease, this);
- childSetAction("close_btn", onClickClose, this);
-
- return TRUE ;
+ setVisible(FALSE);
}
void LLFloaterMemLeak::draw()
@@ -217,50 +226,3 @@ void LLFloaterMemLeak::draw()
LLFloater::draw();
}
-
-// static instance of it
-LLFloaterMemLeak* LLFloaterMemLeak::instance()
-{
- if (!sInstance)
- {
- sInstance = new LLFloaterMemLeak();
- LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_mem_leaking.xml", NULL, FALSE);
-
- if(sInstance)
- {
- F32 a, b ;
- a = sInstance->childGetValue("leak_speed").asReal();
- if(a > (F32)(0xFFFFFFFF))
- {
- sMemLeakingSpeed = 0xFFFFFFFF ;
- }
- else
- {
- sMemLeakingSpeed = (U32)a ;
- }
- b = sInstance->childGetValue("max_leak").asReal();
- if(b > (F32)0xFFF)
- {
- sMaxLeakedMem = 0xFFFFFFFF ;
- }
- else
- {
- sMaxLeakedMem = ((U32)b) << 20 ;
- }
-
- sbAllocationFailed = FALSE ;
- }
- }
- return sInstance ;
-}
-
-void LLFloaterMemLeak::show(void*)
-{
- instance()->open();
-}
-
-LLFloaterMemLeak* LLFloaterMemLeak::getInstance()
-{
- return sInstance ;
-}
-
diff --git a/indra/newview/llfloatermemleak.h b/indra/newview/llfloatermemleak.h
index 7d9d5f9c5f..763af943ba 100644
--- a/indra/newview/llfloatermemleak.h
+++ b/indra/newview/llfloatermemleak.h
@@ -37,34 +37,28 @@
class LLFloaterMemLeak : public LLFloater
{
+ friend class LLFloaterReg;
public:
- LLFloaterMemLeak();
- virtual ~LLFloaterMemLeak();
-
/// initialize all the callbacks for the menu
- //void initCallbacks(void);
+
virtual BOOL postBuild() ;
virtual void draw() ;
-
- /// one and one instance only
- static LLFloaterMemLeak* instance();
- static void onChangeLeakingSpeed(LLUICtrl* ctrl, void* userData);
- static void onChangeMaxMemLeaking(LLUICtrl* ctrl, void* userData);
- static void onClickStart(void* userData);
- static void onClickStop(void* userData);
- static void onClickRelease(void* userData);
- static void onClickClose(void* userData);
-
- /// show off our menu
- static void show(void*);
+ void onChangeLeakingSpeed();
+ void onChangeMaxMemLeaking();
+ void onClickStart();
+ void onClickStop();
+ void onClickRelease();
+ void onClickClose();
public:
- static LLFloaterMemLeak* getInstance() ;
void idle() ;
void stop() ;
private:
+
+ LLFloaterMemLeak(const LLSD& key);
+ virtual ~LLFloaterMemLeak();
void release() ;
private:
@@ -75,9 +69,6 @@ private:
START
} ;
- // one instance on the inside
- static LLFloaterMemLeak* sInstance;
-
static U32 sMemLeakingSpeed ; //bytes leaked per frame
static U32 sMaxLeakedMem ; //maximum allowed leaked memory
static U32 sTotalLeaked ;
diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp
index acfcfab445..810761e034 100644
--- a/indra/newview/llfloaternamedesc.cpp
+++ b/indra/newview/llfloaternamedesc.cpp
@@ -41,6 +41,7 @@
#include "llbutton.h"
#include "llviewerwindow.h"
#include "llfocusmgr.h"
+#include "llrootview.h"
#include "llradiogroup.h"
#include "lldbstrings.h"
#include "lldir.h"
@@ -68,14 +69,12 @@ const S32 PREF_BUTTON_HEIGHT = 16;
//-----------------------------------------------------------------------------
// LLFloaterNameDesc()
//-----------------------------------------------------------------------------
-LLFloaterNameDesc::LLFloaterNameDesc(const std::string& filename )
- : LLFloater(std::string("Name/Description Floater"))
+LLFloaterNameDesc::LLFloaterNameDesc(const LLSD& filename )
+ : LLFloater(filename),
+ mIsAudio(FALSE)
{
- mFilenameAndPath = filename;
- mFilename = gDirUtilp->getBaseFileName(filename, false);
- // SL-5521 Maintain capitalization of filename when making the inventory item. JC
- //LLStringUtil::toLower(mFilename);
- mIsAudio = FALSE;
+ mFilenameAndPath = filename.asString();
+ mFilename = gDirUtilp->getBaseFileName(mFilenameAndPath, false);
}
//-----------------------------------------------------------------------------
@@ -91,11 +90,6 @@ BOOL LLFloaterNameDesc::postBuild()
LLStringUtil::stripNonprintable(asset_name);
LLStringUtil::trim(asset_name);
- std::string exten = gDirUtilp->getExtension(asset_name);
- if (exten == "wav")
- {
- mIsAudio = TRUE;
- }
asset_name = gDirUtilp->getBaseFileName(asset_name, true); // no extsntion
setTitle(mFilename);
@@ -110,37 +104,37 @@ BOOL LLFloaterNameDesc::postBuild()
r.setLeftTopAndSize( PREVIEW_HPAD, y, line_width, PREVIEW_LINE_HEIGHT );
- childSetCommitCallback("name_form", doCommit, this);
+ getChild<LLUICtrl>("name_form")->setCommitCallback(boost::bind(&LLFloaterNameDesc::doCommit, this));
childSetValue("name_form", LLSD(asset_name));
LLLineEditor *NameEditor = getChild<LLLineEditor>("name_form");
if (NameEditor)
{
NameEditor->setMaxTextLength(DB_INV_ITEM_NAME_STR_LEN);
- NameEditor->setPrevalidate(&LLLineEditor::prevalidatePrintableNotPipe);
+ NameEditor->setPrevalidate(&LLLineEditor::prevalidateASCIIPrintableNoPipe);
}
y -= llfloor(PREVIEW_LINE_HEIGHT * 1.2f);
y -= PREVIEW_LINE_HEIGHT;
r.setLeftTopAndSize( PREVIEW_HPAD, y, line_width, PREVIEW_LINE_HEIGHT );
- childSetCommitCallback("description_form", doCommit, this);
+ getChild<LLUICtrl>("description_form")->setCommitCallback(boost::bind(&LLFloaterNameDesc::doCommit, this));
LLLineEditor *DescEditor = getChild<LLLineEditor>("description_form");
if (DescEditor)
{
DescEditor->setMaxTextLength(DB_INV_ITEM_DESC_STR_LEN);
- DescEditor->setPrevalidate(&LLLineEditor::prevalidatePrintableNotPipe);
+ DescEditor->setPrevalidate(&LLLineEditor::prevalidateASCIIPrintableNoPipe);
}
y -= llfloor(PREVIEW_LINE_HEIGHT * 1.2f);
// Cancel button
- childSetAction("cancel_btn", onBtnCancel, this);
+ getChild<LLUICtrl>("cancel_btn")->setCommitCallback(boost::bind(&LLFloaterNameDesc::onBtnCancel, this));
- // OK button
- childSetAction("ok_btn", onBtnOK, this);
+ childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload() ));
+
setDefaultBtn("ok_btn");
-
+
return TRUE;
}
@@ -160,45 +154,59 @@ void LLFloaterNameDesc::onCommit()
{
}
-// static
//-----------------------------------------------------------------------------
// onCommit()
//-----------------------------------------------------------------------------
-void LLFloaterNameDesc::doCommit( class LLUICtrl *, void* userdata )
+void LLFloaterNameDesc::doCommit()
{
- LLFloaterNameDesc* self = (LLFloaterNameDesc*) userdata;
- self->onCommit();
+ onCommit();
}
-// static
//-----------------------------------------------------------------------------
// onBtnOK()
//-----------------------------------------------------------------------------
-void LLFloaterNameDesc::onBtnOK( void* userdata )
+void LLFloaterNameDesc::onBtnOK( )
{
- LLFloaterNameDesc *fp =(LLFloaterNameDesc *)userdata;
-
- fp->childDisable("ok_btn"); // don't allow inadvertent extra uploads
+ childDisable("ok_btn"); // don't allow inadvertent extra uploads
LLAssetStorage::LLStoreAssetCallback callback = NULL;
S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); // kinda hack - assumes that unsubclassed LLFloaterNameDesc is only used for uploading chargeable assets, which it is right now (it's only used unsubclassed for the sound upload dialog, and THAT should be a subclass).
void *nruserdata = NULL;
std::string display_name = LLStringUtil::null;
- upload_new_resource(fp->mFilenameAndPath, // file
- fp->childGetValue("name_form").asString(),
- fp->childGetValue("description_form").asString(),
- 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE,
+ upload_new_resource(mFilenameAndPath, // file
+ childGetValue("name_form").asString(),
+ childGetValue("description_form").asString(),
+ 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(),
display_name, callback, expected_upload_cost, nruserdata);
- fp->close(false);
+ closeFloater(false);
}
-// static
//-----------------------------------------------------------------------------
// onBtnCancel()
//-----------------------------------------------------------------------------
-void LLFloaterNameDesc::onBtnCancel( void* userdata )
+void LLFloaterNameDesc::onBtnCancel()
{
- LLFloaterNameDesc *fp =(LLFloaterNameDesc *)userdata;
- fp->close(false);
+ closeFloater(false);
+}
+
+
+//-----------------------------------------------------------------------------
+// LLFloaterSoundPreview()
+//-----------------------------------------------------------------------------
+
+LLFloaterSoundPreview::LLFloaterSoundPreview(const LLSD& filename )
+ : LLFloaterNameDesc(filename)
+{
+ mIsAudio = TRUE;
+}
+
+BOOL LLFloaterSoundPreview::postBuild()
+{
+ if (!LLFloaterNameDesc::postBuild())
+ {
+ return FALSE;
+ }
+ getChild<LLUICtrl>("ok_btn")->setCommitCallback(boost::bind(&LLFloaterNameDesc::onBtnOK, this));
+ return TRUE;
}
diff --git a/indra/newview/llfloaternamedesc.h b/indra/newview/llfloaternamedesc.h
index 6aa19eba40..2cc7f1101d 100644
--- a/indra/newview/llfloaternamedesc.h
+++ b/indra/newview/llfloaternamedesc.h
@@ -44,11 +44,14 @@ class LLRadioGroup;
class LLFloaterNameDesc : public LLFloater
{
public:
- LLFloaterNameDesc(const std::string& filename);
+ LLFloaterNameDesc(const LLSD& filename);
virtual ~LLFloaterNameDesc();
virtual BOOL postBuild();
-
- static void doCommit(class LLUICtrl *, void* userdata);
+
+ void onBtnOK();
+ void onBtnCancel();
+ void doCommit();
+
protected:
virtual void onCommit();
@@ -57,9 +60,13 @@ protected:
std::string mFilenameAndPath;
std::string mFilename;
-
- static void onBtnOK(void*);
- static void onBtnCancel(void*);
};
+class LLFloaterSoundPreview : public LLFloaterNameDesc
+{
+public:
+ LLFloaterSoundPreview(const LLSD& filename );
+ virtual BOOL postBuild();
+};
+
#endif // LL_LLFLOATERNAMEDESC_H
diff --git a/indra/newview/llfloaternotificationsconsole.cpp b/indra/newview/llfloaternotificationsconsole.cpp
index e6250063f7..90db8988b2 100644
--- a/indra/newview/llfloaternotificationsconsole.cpp
+++ b/indra/newview/llfloaternotificationsconsole.cpp
@@ -36,9 +36,9 @@
#include "lluictrlfactory.h"
#include "llbutton.h"
#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
#include "llpanel.h"
#include "llcombobox.h"
-#include "llviewertexteditor.h"
const S32 NOTIFICATION_PANEL_HEADER_HEIGHT = 20;
const S32 HEADER_PADDING = 38;
@@ -59,11 +59,12 @@ private:
};
LLNotificationChannelPanel::LLNotificationChannelPanel(const std::string& channel_name)
- : LLPanel(channel_name)
+ : LLPanel()
{
mChannelPtr = LLNotifications::instance().getChannel(channel_name);
mChannelRejectsPtr = LLNotificationChannelPtr(
- LLNotificationChannel::buildChannel(channel_name + "rejects", mChannelPtr->getParentChannelName(), !boost::bind(mChannelPtr->getFilter(), _1)));
+ LLNotificationChannel::buildChannel(channel_name + "rejects", mChannelPtr->getParentChannelName(),
+ !boost::bind(mChannelPtr->getFilter(), _1)));
LLUICtrlFactory::instance().buildPanel(this, "panel_notifications_channel.xml");
}
@@ -77,13 +78,11 @@ BOOL LLNotificationChannelPanel::postBuild()
mChannelRejectsPtr->connectChanged(boost::bind(&LLNotificationChannelPanel::update, this, _1, false));
LLScrollListCtrl* scroll = getChild<LLScrollListCtrl>("notifications_list");
- scroll->setDoubleClickCallback(onClickNotification);
- scroll->setCallbackUserData(this);
-
+ scroll->setDoubleClickCallback(onClickNotification, this);
+ scroll->setRect(LLRect( getRect().mLeft, getRect().mTop, getRect().mRight, 0));
scroll = getChild<LLScrollListCtrl>("notification_rejects_list");
- scroll->setDoubleClickCallback(onClickNotificationReject);
- scroll->setCallbackUserData(this);
-
+ scroll->setDoubleClickCallback(onClickNotificationReject, this);
+ scroll->setRect(LLRect( getRect().mLeft, getRect().mTop, getRect().mRight, 0));
return TRUE;
}
@@ -161,17 +160,13 @@ bool LLNotificationChannelPanel::update(const LLSD& payload, bool passed_filter)
// LLFloaterNotificationConsole
//
LLFloaterNotificationConsole::LLFloaterNotificationConsole(const LLSD& key)
+: LLFloater(key)
{
- LLUICtrlFactory::instance().buildFloater(this, "floater_notifications_console.xml");
-}
+ mCommitCallbackRegistrar.add("ClickAdd", boost::bind(&LLFloaterNotificationConsole::onClickAdd, this));
-void LLFloaterNotificationConsole::onClose(bool app_quitting)
-{
- setVisible(FALSE);
- //destroy();
+ //LLUICtrlFactory::instance().buildFloater(this, "floater_notifications_console.xml");
}
-
BOOL LLFloaterNotificationConsole::postBuild()
{
// these are in the order of processing
@@ -186,7 +181,7 @@ BOOL LLFloaterNotificationConsole::postBuild()
addChannel("Notifications");
addChannel("NotificationTips");
- getChild<LLButton>("add_notification")->setClickedCallback(onClickAdd, this);
+// getChild<LLButton>("add_notification")->setClickedCallback(onClickAdd, this);
LLComboBox* notifications = getChild<LLComboBox>("notification_types");
LLNotifications::TemplateNames names = LLNotifications::instance().getTemplateNames();
@@ -216,12 +211,9 @@ void LLFloaterNotificationConsole::addChannel(const std::string& name, bool open
void LLFloaterNotificationConsole::removeChannel(const std::string& name)
{
- LLPanel* panelp = getChild<LLPanel>(name, TRUE, FALSE);
- if (panelp)
- {
- getChildRef<LLLayoutStack>("notification_channels").removePanel(panelp);
- delete panelp;
- }
+ LLPanel* panelp = getChild<LLPanel>(name);
+ getChildRef<LLLayoutStack>("notification_channels").removePanel(panelp);
+ delete panelp;
updateResizeLimits();
}
@@ -229,33 +221,36 @@ void LLFloaterNotificationConsole::removeChannel(const std::string& name)
//static
void LLFloaterNotificationConsole::updateResizeLimits()
{
+ const LLFloater::Params& floater_params = LLFloater::getDefaultParams();
+ S32 floater_header_size = floater_params.header_height;
+
LLLayoutStack& stack = getChildRef<LLLayoutStack>("notification_channels");
- setResizeLimits(getMinWidth(), LLFLOATER_HEADER_SIZE + HEADER_PADDING + ((NOTIFICATION_PANEL_HEADER_HEIGHT + 3) * stack.getNumPanels()));
+ setResizeLimits(getMinWidth(), floater_header_size + HEADER_PADDING + ((NOTIFICATION_PANEL_HEADER_HEIGHT + 3) * stack.getNumPanels()));
}
-void LLFloaterNotificationConsole::onClickAdd(void* user_data)
+void LLFloaterNotificationConsole::onClickAdd()
{
- LLFloaterNotificationConsole* floater = (LLFloaterNotificationConsole*)user_data;
-
- std::string message_name = floater->getChild<LLComboBox>("notification_types")->getValue().asString();
+ std::string message_name = getChild<LLComboBox>("notification_types")->getValue().asString();
if (!message_name.empty())
{
- LLNotifications::instance().add(message_name, LLSD());
+ LLNotifications::instance().add(message_name, LLSD(), LLSD());
}
}
//=============== LLFloaterNotification ================
-LLFloaterNotification::LLFloaterNotification(LLNotification* note) : mNote(note)
+LLFloaterNotification::LLFloaterNotification(LLNotification* note)
+: LLFloater(LLSD()),
+ mNote(note)
{
- LLUICtrlFactory::instance().buildFloater(this, "floater_notification.xml");
+ LLUICtrlFactory::instance().buildFloater(this, "floater_notification.xml", NULL);
}
BOOL LLFloaterNotification::postBuild()
{
setTitle(mNote->getName());
- getChild<LLViewerTextEditor>("payload")->setText(mNote->getMessage());
+ getChild<LLUICtrl>("payload")->setValue(mNote->getMessage());
LLComboBox* responses_combo = getChild<LLComboBox>("response");
LLCtrlListInterface* response_list = responses_combo->getListInterface();
@@ -265,8 +260,7 @@ BOOL LLFloaterNotification::postBuild()
return TRUE;
}
- responses_combo->setCommitCallback(onCommitResponse);
- responses_combo->setCallbackUserData(this);
+ responses_combo->setCommitCallback(onCommitResponse, this);
LLSD form_sd = form->asLLSD();
diff --git a/indra/newview/llfloaternotificationsconsole.h b/indra/newview/llfloaternotificationsconsole.h
index 1a436b8bfe..a05d559eb4 100644
--- a/indra/newview/llfloaternotificationsconsole.h
+++ b/indra/newview/llfloaternotificationsconsole.h
@@ -34,18 +34,20 @@
#define LL_LLFLOATER_NOTIFICATIONS_CONSOLE_H
#include "llfloater.h"
-#include "llnotifications.h"
+#include "lllayoutstack.h"
+//#include "llnotificationsutil.h"
+
+class LLNotification;
class LLFloaterNotificationConsole :
- public LLFloater,
- public LLFloaterSingleton<LLFloaterNotificationConsole>
+ public LLFloater
{
+ friend class LLFloaterReg;
+
public:
- LLFloaterNotificationConsole(const LLSD& key);
// LLPanel
BOOL postBuild();
- void onClose(bool app_quitting);
void addChannel(const std::string& type, bool open = false);
void updateResizeLimits(LLLayoutStack &stack);
@@ -54,7 +56,8 @@ public:
void updateResizeLimits();
private:
- static void onClickAdd(void* user_data);
+ LLFloaterNotificationConsole(const LLSD& key);
+ void onClickAdd();
};
@@ -69,7 +72,6 @@ public:
// LLPanel
BOOL postBuild();
void respond();
- void onClose(bool app_quitting) { setVisible(FALSE); }
private:
static void onCommitResponse(LLUICtrl* ctrl, void* data) { ((LLFloaterNotification*)data)->respond(); }
diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp
index f4984df6d9..ec50ed596c 100644
--- a/indra/newview/llfloateropenobject.cpp
+++ b/indra/newview/llfloateropenobject.cpp
@@ -32,7 +32,7 @@
/*
* Shows the contents of an object.
- * A floater wrapper for llpanelinventory
+ * A floater wrapper for LLPanelObjectInventory
*/
#include "llviewerprecompiledheaders.h"
@@ -41,13 +41,15 @@
#include "llcachename.h"
#include "llbutton.h"
+#include "llnotificationsutil.h"
#include "lltextbox.h"
-#include "llagent.h" // for agent id
-#include "llalertdialog.h"
-#include "llinventoryview.h"
+#include "llinventorybridge.h"
+#include "llfloaterinventory.h"
#include "llinventorymodel.h"
-#include "llpanelinventory.h"
+#include "llinventorypanel.h"
+#include "llpanelobjectinventory.h"
+#include "llfloaterreg.h"
#include "llselectmgr.h"
#include "lluiconstants.h"
#include "llviewerobject.h"
@@ -55,50 +57,97 @@
#include "llviewerwindow.h"
-LLFloaterOpenObject* LLFloaterOpenObject::sInstance = NULL;
-
-LLFloaterOpenObject::LLFloaterOpenObject()
-: LLFloater(std::string("object_contents")),
- mPanelInventory(NULL),
+LLFloaterOpenObject::LLFloaterOpenObject(const LLSD& key)
+: LLFloater(key),
+ mPanelInventoryObject(NULL),
mDirty(TRUE)
{
- LLCallbackMap::map_t factory_map;
- factory_map["object_contents"] = LLCallbackMap(createPanelInventory, this);
- LLUICtrlFactory::getInstance()->buildFloater(this,"floater_openobject.xml",&factory_map);
+// LLUICtrlFactory::getInstance()->buildFloater(this,"floater_openobject.xml");
+ mCommitCallbackRegistrar.add("OpenObject.MoveToInventory", boost::bind(&LLFloaterOpenObject::onClickMoveToInventory, this));
+ mCommitCallbackRegistrar.add("OpenObject.MoveAndWear", boost::bind(&LLFloaterOpenObject::onClickMoveAndWear, this));
+}
+
+LLFloaterOpenObject::~LLFloaterOpenObject()
+{
+// sInstance = NULL;
+}
- childSetAction("copy_to_inventory_button", onClickMoveToInventory, this);
- childSetAction("copy_and_wear_button", onClickMoveAndWear, this);
+// virtual
+BOOL LLFloaterOpenObject::postBuild()
+{
childSetTextArg("object_name", "[DESC]", std::string("Object") ); // *Note: probably do not want to translate this
+ mPanelInventoryObject = getChild<LLPanelObjectInventory>("object_contents");
+
+ refresh();
+ return TRUE;
}
-LLFloaterOpenObject::~LLFloaterOpenObject()
+void LLFloaterOpenObject::onOpen(const LLSD& key)
{
- sInstance = NULL;
+ LLObjectSelectionHandle object_selection = LLSelectMgr::getInstance()->getSelection();
+ if (object_selection->getRootObjectCount() != 1)
+ {
+ LLNotificationsUtil::add("UnableToViewContentsMoreThanOne");
+ closeFloater();
+ return;
+ }
+ if(!(object_selection->getPrimaryObject()))
+ {
+ closeFloater();
+ return;
+ }
+ mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
+ refresh();
}
void LLFloaterOpenObject::refresh()
{
- mPanelInventory->refresh();
+ mPanelInventoryObject->refresh();
- std::string name;
- BOOL enabled;
+ std::string name = "";
+
+ // Enable the copy || copy & wear buttons only if we have something we can copy or copy & wear (respectively).
+ bool copy_enabled = false;
+ bool wear_enabled = false;
LLSelectNode* node = mObjectSelection->getFirstRootNode();
- if (node)
+ if (node)
{
name = node->mName;
- enabled = TRUE;
- }
- else
- {
- name = "";
- enabled = FALSE;
+ copy_enabled = true;
+
+ LLViewerObject* object = node->getObject();
+ if (object)
+ {
+ // this folder is coming from an object, as there is only one folder in an object, the root,
+ // we need to collect the entire contents and handle them as a group
+ InventoryObjectList inventory_objects;
+ object->getInventoryContents(inventory_objects);
+
+ if (!inventory_objects.empty())
+ {
+ for (InventoryObjectList::iterator it = inventory_objects.begin();
+ it != inventory_objects.end();
+ ++it)
+ {
+ LLInventoryItem* item = static_cast<LLInventoryItem*> ((LLInventoryObject*)(*it));
+ LLInventoryType::EType type = item->getInventoryType();
+ if (type == LLInventoryType::IT_OBJECT
+ || type == LLInventoryType::IT_ATTACHMENT
+ || type == LLInventoryType::IT_WEARABLE
+ || type == LLInventoryType::IT_GESTURE)
+ {
+ wear_enabled = true;
+ break;
+ }
+ }
+ }
+ }
}
childSetTextArg("object_name", "[DESC]", name);
-
- childSetEnabled("copy_to_inventory_button", enabled);
- childSetEnabled("copy_and_wear_button", enabled);
+ childSetEnabled("copy_to_inventory_button", copy_enabled);
+ childSetEnabled("copy_and_wear_button", wear_enabled);
}
@@ -112,41 +161,18 @@ void LLFloaterOpenObject::draw()
LLFloater::draw();
}
-// static
void LLFloaterOpenObject::dirty()
{
- if (sInstance) sInstance->mDirty = TRUE;
+ mDirty = TRUE;
}
-// static
-void LLFloaterOpenObject::show()
-{
- LLObjectSelectionHandle object_selection = LLSelectMgr::getInstance()->getSelection();
- if (object_selection->getRootObjectCount() != 1)
- {
- LLNotifications::instance().add("UnableToViewContentsMoreThanOne");
- return;
- }
-
- // Create a new instance only if needed
- if (!sInstance)
- {
- sInstance = new LLFloaterOpenObject();
- sInstance->center();
- }
-
- sInstance->open(); /* Flawfinder: ignore */
- sInstance->setFocus(TRUE);
-
- sInstance->mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
-}
void LLFloaterOpenObject::moveToInventory(bool wear)
{
if (mObjectSelection->getRootObjectCount() != 1)
{
- LLNotifications::instance().add("OnlyCopyContentsOfSingleItem");
+ LLNotificationsUtil::add("OnlyCopyContentsOfSingleItem");
return;
}
@@ -163,14 +189,14 @@ void LLFloaterOpenObject::moveToInventory(bool wear)
if (wear)
{
parent_category_id = gInventory.findCategoryUUIDForType(
- LLAssetType::AT_CLOTHING);
+ LLFolderType::FT_CLOTHING);
}
else
{
- parent_category_id = gAgent.getInventoryRootID();
+ parent_category_id = gInventory.getRootFolderID();
}
LLUUID category_id = gInventory.createNewCategory(parent_category_id,
- LLAssetType::AT_NONE,
+ LLFolderType::FT_NONE,
name);
LLCatAndWear* data = new LLCatAndWear;
@@ -187,7 +213,7 @@ void LLFloaterOpenObject::moveToInventory(bool wear)
delete data;
data = NULL;
- LLNotifications::instance().add("OpenObjectCannotCopy");
+ LLNotificationsUtil::add("OpenObjectCannotCopy");
}
}
@@ -198,38 +224,25 @@ void LLFloaterOpenObject::callbackMoveInventory(S32 result, void* data)
if (result == 0)
{
- LLInventoryView::showAgentInventory();
- LLInventoryView* view = LLInventoryView::getActiveInventory();
- if (view)
+ LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel();
+ if (active_panel)
{
- view->getPanel()->setSelection(cat->mCatID, TAKE_FOCUS_NO);
+ active_panel->setSelection(cat->mCatID, TAKE_FOCUS_NO);
}
}
delete cat;
}
-
-// static
-void LLFloaterOpenObject::onClickMoveToInventory(void* data)
+void LLFloaterOpenObject::onClickMoveToInventory()
{
- LLFloaterOpenObject* self = (LLFloaterOpenObject*)data;
- self->moveToInventory(false);
- self->close();
+ moveToInventory(false);
+ closeFloater();
}
-// static
-void LLFloaterOpenObject::onClickMoveAndWear(void* data)
+void LLFloaterOpenObject::onClickMoveAndWear()
{
- LLFloaterOpenObject* self = (LLFloaterOpenObject*)data;
- self->moveToInventory(true);
- self->close();
+ moveToInventory(true);
+ closeFloater();
}
-//static
-void* LLFloaterOpenObject::createPanelInventory(void* data)
-{
- LLFloaterOpenObject* floater = (LLFloaterOpenObject*)data;
- floater->mPanelInventory = new LLPanelInventory(std::string("Object Contents"), LLRect());
- return floater->mPanelInventory;
-}
diff --git a/indra/newview/llfloateropenobject.h b/indra/newview/llfloateropenobject.h
index 27653a5c99..10d96b7ea3 100644
--- a/indra/newview/llfloateropenobject.h
+++ b/indra/newview/llfloateropenobject.h
@@ -41,14 +41,15 @@
#include "llfloater.h"
class LLObjectSelection;
-class LLPanelInventory;
+class LLPanelObjectInventory;
class LLFloaterOpenObject
: public LLFloater
{
+ friend class LLFloaterReg;
public:
- static void show();
- static void dirty();
+
+ void dirty();
struct LLCatAndWear
{
@@ -57,23 +58,26 @@ public:
};
protected:
- LLFloaterOpenObject();
- ~LLFloaterOpenObject();
+ /*virtual*/ BOOL postBuild();
void refresh();
void draw();
+ virtual void onOpen(const LLSD& key);
void moveToInventory(bool wear);
- static void onClickMoveToInventory(void* data);
- static void onClickMoveAndWear(void* data);
+ void onClickMoveToInventory();
+ void onClickMoveAndWear();
static void callbackMoveInventory(S32 result, void* data);
- static void* createPanelInventory(void* data);
+private:
+
+ LLFloaterOpenObject(const LLSD& key);
+ ~LLFloaterOpenObject();
+
protected:
- static LLFloaterOpenObject* sInstance;
- LLPanelInventory* mPanelInventory;
+ LLPanelObjectInventory* mPanelInventoryObject;
LLSafeHandle<LLObjectSelection> mObjectSelection;
BOOL mDirty;
};
diff --git a/indra/newview/llfloaterparcel.cpp b/indra/newview/llfloaterparcel.cpp
index 4213150553..e2be784116 100644
--- a/indra/newview/llfloaterparcel.cpp
+++ b/indra/newview/llfloaterparcel.cpp
@@ -35,9 +35,12 @@
#include "llfloaterparcel.h"
+#include "llfloaterreg.h"
+
// viewer project includes
#include "llcommandhandler.h"
#include "llpanelplace.h"
+#include "llsidetray.h"
// linden library includes
#include "lluuid.h"
@@ -47,15 +50,13 @@
// Globals
//-----------------------------------------------------------------------------
-LLMap< const LLUUID, LLFloaterParcelInfo* > gPlaceInfoInstances;
-
class LLParcelHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
- LLParcelHandler() : LLCommandHandler("parcel", true) { }
+ LLParcelHandler() : LLCommandHandler("parcel", UNTRUSTED_THROTTLE) { }
bool handle(const LLSD& params, const LLSD& query_map,
- LLWebBrowserCtrl* web)
+ LLMediaCtrl* web)
{
if (params.size() < 2)
{
@@ -68,8 +69,14 @@ public:
}
if (params[1].asString() == "about")
{
- LLFloaterParcelInfo::show(parcel_id);
- return true;
+ if (parcel_id.notNull())
+ {
+ LLSD key;
+ key["type"] = "remote_place";
+ key["id"] = parcel_id;
+ LLSideTray::getInstance()->showPanel("panel_places", key);
+ return true;
+ }
}
return false;
}
@@ -82,7 +89,7 @@ LLParcelHandler gParcelHandler;
//----------------------------------------------------------------------------
-void* LLFloaterParcelInfo::createPanelPlace(void* data)
+void* LLFloaterParcelInfo::createPanelPlace(void* data)
{
LLFloaterParcelInfo* self = (LLFloaterParcelInfo*)data;
self->mPanelParcelp = new LLPanelPlace(); // allow edit self
@@ -93,54 +100,29 @@ void* LLFloaterParcelInfo::createPanelPlace(void* data)
//----------------------------------------------------------------------------
-LLFloaterParcelInfo::LLFloaterParcelInfo(const std::string& name, const LLUUID &parcel_id)
-: LLFloater(name),
- mParcelID( parcel_id )
+LLFloaterParcelInfo::LLFloaterParcelInfo(const LLSD& parcel_id)
+: LLFloater(parcel_id),
+ mParcelID( parcel_id.asUUID() ),
+ mPanelParcelp(NULL)
{
mFactoryMap["place_details_panel"] = LLCallbackMap(LLFloaterParcelInfo::createPanelPlace, this);
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_preview_url.xml", &getFactoryMap());
- gPlaceInfoInstances.addData(parcel_id, this);
+// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_preview_url.xml");
}
// virtual
LLFloaterParcelInfo::~LLFloaterParcelInfo()
{
- // child views automatically deleted
- gPlaceInfoInstances.removeData(mParcelID);
-
-}
-void LLFloaterParcelInfo::displayParcelInfo(const LLUUID& parcel_id)
-{
- mPanelParcelp->setParcelID(parcel_id);
}
-// static
-LLFloaterParcelInfo* LLFloaterParcelInfo::show(const LLUUID &parcel_id)
+BOOL LLFloaterParcelInfo::postBuild()
{
- if (parcel_id.isNull())
+ if (mPanelParcelp)
{
- return NULL;
+ mPanelParcelp->setParcelID(mParcelID);
}
-
- LLFloaterParcelInfo *floater;
- if (gPlaceInfoInstances.checkData(parcel_id))
- {
- // ...bring that window to front
- floater = gPlaceInfoInstances.getData(parcel_id);
- floater->open(); /*Flawfinder: ignore*/
- floater->setFrontmost(true);
- }
- else
- {
- floater = new LLFloaterParcelInfo("parcelinfo", parcel_id );
- floater->center();
- floater->open(); /*Flawfinder: ignore*/
- floater->displayParcelInfo(parcel_id);
- floater->setFrontmost(true);
- }
-
- return floater;
+ center();
+ return LLFloater::postBuild();
}
diff --git a/indra/newview/llfloaterparcel.h b/indra/newview/llfloaterparcel.h
index 4d698d64ae..386acb3fd5 100644
--- a/indra/newview/llfloaterparcel.h
+++ b/indra/newview/llfloaterparcel.h
@@ -43,13 +43,13 @@ class LLFloaterParcelInfo
public:
static void* createPanelPlace(void* data);
- LLFloaterParcelInfo(const std::string& name, const LLUUID &parcel_id );
+ LLFloaterParcelInfo( const LLSD& parcel_id );
/*virtual*/ ~LLFloaterParcelInfo();
-
+
+ /*virtual*/ BOOL postBuild();
+
void displayParcelInfo(const LLUUID& parcel_id);
- static LLFloaterParcelInfo* show(const LLUUID& parcel_id);
-
private:
LLUUID mParcelID; // for which parcel is this window?
LLPanelPlace* mPanelParcelp;
diff --git a/indra/newview/llfloaterpay.cpp b/indra/newview/llfloaterpay.cpp
new file mode 100644
index 0000000000..c2389e73a0
--- /dev/null
+++ b/indra/newview/llfloaterpay.cpp
@@ -0,0 +1,571 @@
+/**
+ * @file llfloaterpay.cpp
+ * @author Aaron Brashears, Kelly Washington, James Cook
+ * @brief Implementation of the LLFloaterPay class.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterpay.h"
+
+#include "message.h"
+#include "llfloater.h"
+#include "lllslconstants.h" // MAX_PAY_BUTTONS
+#include "lluuid.h"
+
+#include "llagent.h"
+#include "llfloaterreg.h"
+#include "llresmgr.h"
+#include "lltextbox.h"
+#include "lllineeditor.h"
+#include "llmutelist.h"
+#include "llfloaterreporter.h"
+#include "llviewerobject.h"
+#include "llviewerobjectlist.h"
+#include "llviewerregion.h"
+#include "llviewerwindow.h"
+#include "llbutton.h"
+#include "llselectmgr.h"
+#include "lltransactiontypes.h"
+#include "lluictrlfactory.h"
+
+///----------------------------------------------------------------------------
+/// Local function declarations, constants, enums, and typedefs
+///----------------------------------------------------------------------------
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLGiveMoneyInfo
+//
+// A small class used to track callback information
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLFloaterPay;
+
+struct LLGiveMoneyInfo
+{
+ LLFloaterPay* mFloater;
+ S32 mAmount;
+ LLGiveMoneyInfo(LLFloaterPay* floater, S32 amount) :
+ mFloater(floater), mAmount(amount){}
+};
+
+///----------------------------------------------------------------------------
+/// Class LLFloaterPay
+///----------------------------------------------------------------------------
+
+class LLFloaterPay : public LLFloater
+{
+public:
+ LLFloaterPay(const LLSD& key);
+ virtual ~LLFloaterPay();
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onClose(bool app_quitting);
+
+ void setCallback(money_callback callback) { mCallback = callback; }
+
+
+ static void payViaObject(money_callback callback, LLSafeHandle<LLObjectSelection> selection);
+
+ static void payDirectly(money_callback callback,
+ const LLUUID& target_id,
+ bool is_group);
+
+private:
+ static void onCancel(void* data);
+ static void onKeystroke(LLLineEditor* editor, void* data);
+ static void onGive(void* data);
+ void give(S32 amount);
+ static void processPayPriceReply(LLMessageSystem* msg, void **userdata);
+ void onCacheOwnerName(const LLUUID& owner_id,
+ const std::string& firstname,
+ const std::string& lastname,
+ BOOL is_group);
+ void finishPayUI(const LLUUID& target_id, BOOL is_group);
+
+protected:
+ std::vector<LLGiveMoneyInfo*> mCallbackData;
+ money_callback mCallback;
+ LLTextBox* mObjectNameText;
+ LLUUID mTargetUUID;
+ BOOL mTargetIsGroup;
+ BOOL mHaveName;
+
+ LLButton* mQuickPayButton[MAX_PAY_BUTTONS];
+ LLGiveMoneyInfo* mQuickPayInfo[MAX_PAY_BUTTONS];
+
+ LLSafeHandle<LLObjectSelection> mObjectSelection;
+
+ static S32 sLastAmount;
+};
+
+
+S32 LLFloaterPay::sLastAmount = 0;
+const S32 MAX_AMOUNT_LENGTH = 10;
+const S32 FASTPAY_BUTTON_WIDTH = 80;
+
+LLFloaterPay::LLFloaterPay(const LLSD& key)
+ : LLFloater(key),
+ mCallbackData(),
+ mCallback(NULL),
+ mObjectNameText(NULL),
+ mTargetUUID(key.asUUID()),
+ mTargetIsGroup(FALSE)
+{
+}
+
+// Destroys the object
+LLFloaterPay::~LLFloaterPay()
+{
+ std::for_each(mCallbackData.begin(), mCallbackData.end(), DeletePointer());
+ // Name callbacks will be automatically disconnected since LLFloater is trackable
+}
+
+BOOL LLFloaterPay::postBuild()
+{
+ S32 i = 0;
+
+ LLGiveMoneyInfo* info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_0);
+ mCallbackData.push_back(info);
+
+ childSetAction("fastpay 1",&LLFloaterPay::onGive,info);
+ childSetVisible("fastpay 1", FALSE);
+
+ mQuickPayButton[i] = getChild<LLButton>("fastpay 1");
+ mQuickPayInfo[i] = info;
+ ++i;
+
+ info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_1);
+ mCallbackData.push_back(info);
+
+ childSetAction("fastpay 5",&LLFloaterPay::onGive,info);
+ childSetVisible("fastpay 5", FALSE);
+
+ mQuickPayButton[i] = getChild<LLButton>("fastpay 5");
+ mQuickPayInfo[i] = info;
+ ++i;
+
+ info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_2);
+ mCallbackData.push_back(info);
+
+ childSetAction("fastpay 10",&LLFloaterPay::onGive,info);
+ childSetVisible("fastpay 10", FALSE);
+
+ mQuickPayButton[i] = getChild<LLButton>("fastpay 10");
+ mQuickPayInfo[i] = info;
+ ++i;
+
+ info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_3);
+ mCallbackData.push_back(info);
+
+ childSetAction("fastpay 20",&LLFloaterPay::onGive,info);
+ childSetVisible("fastpay 20", FALSE);
+
+ mQuickPayButton[i] = getChild<LLButton>("fastpay 20");
+ mQuickPayInfo[i] = info;
+ ++i;
+
+
+ childSetVisible("amount text", FALSE);
+
+ std::string last_amount;
+ if(sLastAmount > 0)
+ {
+ last_amount = llformat("%d", sLastAmount);
+ }
+
+ childSetVisible("amount", FALSE);
+
+ getChild<LLLineEditor>("amount")->setKeystrokeCallback(&LLFloaterPay::onKeystroke, this);
+ childSetText("amount", last_amount);
+ childSetPrevalidate("amount", LLLineEditor::prevalidateNonNegativeS32);
+
+ info = new LLGiveMoneyInfo(this, 0);
+ mCallbackData.push_back(info);
+
+ childSetAction("pay btn",&LLFloaterPay::onGive,info);
+ setDefaultBtn("pay btn");
+ childSetVisible("pay btn", FALSE);
+ childSetEnabled("pay btn", (sLastAmount > 0));
+
+ childSetAction("cancel btn",&LLFloaterPay::onCancel,this);
+
+ return TRUE;
+}
+
+// virtual
+void LLFloaterPay::onClose(bool app_quitting)
+{
+ // Deselect the objects
+ mObjectSelection = NULL;
+}
+
+// static
+void LLFloaterPay::processPayPriceReply(LLMessageSystem* msg, void **userdata)
+{
+ LLFloaterPay* self = (LLFloaterPay*)userdata;
+ if (self)
+ {
+ S32 price;
+ LLUUID target;
+
+ msg->getUUIDFast(_PREHASH_ObjectData,_PREHASH_ObjectID,target);
+ if (target != self->mTargetUUID)
+ {
+ // This is a message for a different object's pay info
+ return;
+ }
+
+ msg->getS32Fast(_PREHASH_ObjectData,_PREHASH_DefaultPayPrice,price);
+
+ if (PAY_PRICE_HIDE == price)
+ {
+ self->childSetVisible("amount", FALSE);
+ self->childSetVisible("pay btn", FALSE);
+ self->childSetVisible("amount text", FALSE);
+ }
+ else if (PAY_PRICE_DEFAULT == price)
+ {
+ self->childSetVisible("amount", TRUE);
+ self->childSetVisible("pay btn", TRUE);
+ self->childSetVisible("amount text", TRUE);
+ }
+ else
+ {
+ // PAY_PRICE_HIDE and PAY_PRICE_DEFAULT are negative values
+ // So we take the absolute value here after we have checked for those cases
+
+ self->childSetVisible("amount", TRUE);
+ self->childSetVisible("pay btn", TRUE);
+ self->childSetEnabled("pay btn", TRUE);
+ self->childSetVisible("amount text", TRUE);
+
+ self->childSetText("amount", llformat("%d", llabs(price)));
+ }
+
+ S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_ButtonData);
+ S32 i = 0;
+ if (num_blocks > MAX_PAY_BUTTONS) num_blocks = MAX_PAY_BUTTONS;
+
+ S32 max_pay_amount = 0;
+ S32 padding_required = 0;
+
+ for (i=0;i<num_blocks;++i)
+ {
+ S32 pay_button;
+ msg->getS32Fast(_PREHASH_ButtonData,_PREHASH_PayButton,pay_button,i);
+ if (pay_button > 0)
+ {
+ std::string button_str = "L$";
+ button_str += LLResMgr::getInstance()->getMonetaryString( pay_button );
+
+ self->mQuickPayButton[i]->setLabelSelected(button_str);
+ self->mQuickPayButton[i]->setLabelUnselected(button_str);
+ self->mQuickPayButton[i]->setVisible(TRUE);
+ self->mQuickPayInfo[i]->mAmount = pay_button;
+ self->childSetVisible("fastpay text",TRUE);
+
+ if ( pay_button > max_pay_amount )
+ {
+ max_pay_amount = pay_button;
+ }
+ }
+ else
+ {
+ self->mQuickPayButton[i]->setVisible(FALSE);
+ }
+ }
+
+ // build a string containing the maximum value and calc nerw button width from it.
+ std::string balance_str = "L$";
+ balance_str += LLResMgr::getInstance()->getMonetaryString( max_pay_amount );
+ const LLFontGL* font = LLFontGL::getFontSansSerif();
+ S32 new_button_width = font->getWidth( std::string(balance_str));
+ new_button_width += ( 12 + 12 ); // padding
+
+ // dialong is sized for 2 digit pay amounts - larger pay values need to be scaled
+ const S32 threshold = 100000;
+ if ( max_pay_amount >= threshold )
+ {
+ S32 num_digits_threshold = (S32)log10((double)threshold) + 1;
+ S32 num_digits_max = (S32)log10((double)max_pay_amount) + 1;
+
+ // calculate the extra width required by 2 buttons with max amount and some commas
+ padding_required = ( num_digits_max - num_digits_threshold + ( num_digits_max / 3 ) ) * font->getWidth( std::string("0") );
+ };
+
+ // change in button width
+ S32 button_delta = new_button_width - FASTPAY_BUTTON_WIDTH;
+ if ( button_delta < 0 )
+ button_delta = 0;
+
+ // now we know the maximum amount, we can resize all the buttons to be
+ for (i=0;i<num_blocks;++i)
+ {
+ LLRect r;
+ r = self->mQuickPayButton[i]->getRect();
+
+ // RHS button colum needs to move further because LHS changed too
+ if ( i % 2 )
+ {
+ r.setCenterAndSize( r.getCenterX() + ( button_delta * 3 ) / 2 ,
+ r.getCenterY(),
+ r.getWidth() + button_delta,
+ r.getHeight() );
+ }
+ else
+ {
+ r.setCenterAndSize( r.getCenterX() + button_delta / 2,
+ r.getCenterY(),
+ r.getWidth() + button_delta,
+ r.getHeight() );
+ }
+ self->mQuickPayButton[i]->setRect( r );
+ }
+
+ for (i=num_blocks;i<MAX_PAY_BUTTONS;++i)
+ {
+ self->mQuickPayButton[i]->setVisible(FALSE);
+ }
+
+ self->reshape( self->getRect().getWidth() + padding_required, self->getRect().getHeight(), FALSE );
+ }
+ msg->setHandlerFunc("PayPriceReply",NULL,NULL);
+}
+
+// static
+void LLFloaterPay::payViaObject(money_callback callback, LLSafeHandle<LLObjectSelection> selection)
+{
+ // Object that lead to the selection, may be child
+ LLViewerObject* object = selection->getPrimaryObject();
+ if (!object)
+ return;
+
+ LLFloaterPay *floater = LLFloaterReg::showTypedInstance<LLFloaterPay>("pay_object", LLSD(object->getID()));
+ if (!floater)
+ return;
+
+ floater->setCallback(callback);
+ // Hold onto the selection until we close
+ floater->mObjectSelection = selection;
+
+ LLSelectNode* node = selection->getFirstRootNode();
+ if (!node)
+ {
+ //FIXME: notify user object no longer exists
+ floater->closeFloater();
+ return;
+ }
+
+ LLHost target_region = object->getRegion()->getHost();
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_RequestPayPrice);
+ msg->nextBlockFast(_PREHASH_ObjectData);
+ msg->addUUIDFast(_PREHASH_ObjectID, object->getID());
+ msg->sendReliable(target_region);
+ msg->setHandlerFuncFast(_PREHASH_PayPriceReply, processPayPriceReply,(void **)floater);
+
+ LLUUID owner_id;
+ BOOL is_group = FALSE;
+ node->mPermissions->getOwnership(owner_id, is_group);
+
+ floater->childSetText("object_name_text",node->mName);
+
+ floater->finishPayUI(owner_id, is_group);
+}
+
+void LLFloaterPay::payDirectly(money_callback callback,
+ const LLUUID& target_id,
+ bool is_group)
+{
+ LLFloaterPay *floater = LLFloaterReg::showTypedInstance<LLFloaterPay>("pay_resident", LLSD(target_id));
+ if (!floater)
+ return;
+
+ floater->setCallback(callback);
+ floater->mObjectSelection = NULL;
+
+ floater->childSetVisible("amount", TRUE);
+ floater->childSetVisible("pay btn", TRUE);
+ floater->childSetVisible("amount text", TRUE);
+
+ floater->childSetVisible("fastpay text",TRUE);
+ for(S32 i=0;i<MAX_PAY_BUTTONS;++i)
+ {
+ floater->mQuickPayButton[i]->setVisible(TRUE);
+ }
+
+ floater->finishPayUI(target_id, is_group);
+}
+
+void LLFloaterPay::finishPayUI(const LLUUID& target_id, BOOL is_group)
+{
+ gCacheName->get(target_id, is_group, boost::bind(&LLFloaterPay::onCacheOwnerName, this, _1, _2, _3, _4));
+
+ // Make sure the amount field has focus
+
+ childSetFocus("amount", TRUE);
+
+ LLLineEditor* amount = getChild<LLLineEditor>("amount");
+ amount->selectAll();
+ mTargetIsGroup = is_group;
+}
+
+void LLFloaterPay::onCacheOwnerName(const LLUUID& owner_id,
+ const std::string& firstname,
+ const std::string& lastname,
+ BOOL is_group)
+{
+ if (is_group)
+ {
+ setTitle(getString("payee_group"));
+ }
+ else
+ {
+ setTitle(getString("payee_resident"));
+ }
+
+ childSetTextArg("payee_name", "[FIRST]", firstname);
+ childSetTextArg("payee_name", "[LAST]", lastname);
+}
+
+// static
+void LLFloaterPay::onCancel(void* data)
+{
+ LLFloaterPay* self = reinterpret_cast<LLFloaterPay*>(data);
+ if(self)
+ {
+ self->closeFloater();
+ }
+}
+
+// static
+void LLFloaterPay::onKeystroke(LLLineEditor*, void* data)
+{
+ LLFloaterPay* self = reinterpret_cast<LLFloaterPay*>(data);
+ if(self)
+ {
+ // enable the Pay button when amount is non-empty and positive, disable otherwise
+ std::string amtstr = self->childGetText("amount");
+ self->childSetEnabled("pay btn", !amtstr.empty() && atoi(amtstr.c_str()) > 0);
+ }
+}
+
+// static
+void LLFloaterPay::onGive(void* data)
+{
+ LLGiveMoneyInfo* info = reinterpret_cast<LLGiveMoneyInfo*>(data);
+ if(info && info->mFloater)
+ {
+ info->mFloater->give(info->mAmount);
+ info->mFloater->closeFloater();
+ }
+}
+
+void LLFloaterPay::give(S32 amount)
+{
+ if(mCallback)
+ {
+ // if the amount is 0, that menas that we should use the
+ // text field.
+ if(amount == 0)
+ {
+ amount = atoi(childGetText("amount").c_str());
+ }
+ sLastAmount = amount;
+
+ // Try to pay an object.
+ if (mObjectSelection.notNull())
+ {
+ LLViewerObject* dest_object = gObjectList.findObject(mTargetUUID);
+ if(dest_object)
+ {
+ LLViewerRegion* region = dest_object->getRegion();
+ if (region)
+ {
+ // Find the name of the root object
+ LLSelectNode* node = mObjectSelection->getFirstRootNode();
+ std::string object_name;
+ if (node)
+ {
+ object_name = node->mName;
+ }
+ S32 tx_type = TRANS_PAY_OBJECT;
+ if(dest_object->isAvatar()) tx_type = TRANS_GIFT;
+ mCallback(mTargetUUID, region, amount, FALSE, tx_type, object_name);
+ mObjectSelection = NULL;
+
+ // request the object owner in order to check if the owner needs to be unmuted
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_ObjectData);
+ msg->addU32Fast(_PREHASH_RequestFlags, OBJECT_PAY_REQUEST );
+ msg->addUUIDFast(_PREHASH_ObjectID, mTargetUUID);
+ msg->sendReliable( region->getHost() );
+ }
+ }
+ }
+ else
+ {
+ // just transfer the L$
+ mCallback(mTargetUUID, gAgent.getRegion(), amount, mTargetIsGroup, TRANS_GIFT, LLStringUtil::null);
+
+ // check if the payee needs to be unmuted
+ LLMuteList::getInstance()->autoRemove(mTargetUUID, LLMuteList::AR_MONEY);
+ }
+ }
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Namespace LLFloaterPayUtil
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void LLFloaterPayUtil::registerFloater()
+{
+ // Sneaky, use same code but different XML for dialogs
+ LLFloaterReg::add("pay_resident", "floater_pay.xml",
+ &LLFloaterReg::build<LLFloaterPay>);
+ LLFloaterReg::add("pay_object", "floater_pay_object.xml",
+ &LLFloaterReg::build<LLFloaterPay>);
+}
+
+void LLFloaterPayUtil::payViaObject(money_callback callback,
+ LLSafeHandle<LLObjectSelection> selection)
+{
+ LLFloaterPay::payViaObject(callback, selection);
+}
+
+void LLFloaterPayUtil::payDirectly(money_callback callback,
+ const LLUUID& target_id,
+ bool is_group)
+{
+ LLFloaterPay::payDirectly(callback, target_id, is_group);
+}
diff --git a/indra/newview/llfloaterpay.h b/indra/newview/llfloaterpay.h
new file mode 100644
index 0000000000..161ed78acb
--- /dev/null
+++ b/indra/newview/llfloaterpay.h
@@ -0,0 +1,61 @@
+/**
+ * @file llfloaterpay.h
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLFLOATERPAY_H
+#define LLFLOATERPAY_H
+
+#include "llsafehandle.h"
+
+class LLObjectSelection;
+class LLUUID;
+class LLViewerRegion;
+
+typedef void (*money_callback)(const LLUUID&, LLViewerRegion*,S32,BOOL,S32,const std::string&);
+
+namespace LLFloaterPayUtil
+{
+ /// Register with LLFloaterReg
+ void registerFloater();
+
+ /// Pay into an in-world object, which will trigger scripts and eventually
+ /// transfer the L$ to the resident or group that owns the object.
+ /// Objects must be selected. Recipient (primary) object may be a child.
+ void payViaObject(money_callback callback,
+ LLSafeHandle<LLObjectSelection> selection);
+
+ /// Pay an avatar or group directly, not via an object in the world.
+ /// Scripts are not notified, L$ can be direcly transferred.
+ void payDirectly(money_callback callback,
+ const LLUUID& target_id,
+ bool is_group);
+}
+
+#endif // LLFLOATERPAY_H
diff --git a/indra/newview/llfloaterperms.cpp b/indra/newview/llfloaterperms.cpp
index 52fba0aa20..7edc27d4c3 100644
--- a/indra/newview/llfloaterperms.cpp
+++ b/indra/newview/llfloaterperms.cpp
@@ -32,7 +32,6 @@
*/
#include "llviewerprecompiledheaders.h"
-#include "llalertdialog.h"
#include "llcheckboxctrl.h"
#include "llfloaterperms.h"
#include "llviewercontrol.h"
@@ -42,50 +41,45 @@
LLFloaterPerms::LLFloaterPerms(const LLSD& seed)
+: LLFloater(seed)
{
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_perm_prefs.xml");
+ //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_perm_prefs.xml");
+ mCommitCallbackRegistrar.add("Perms.Copy", boost::bind(&LLFloaterPerms::onCommitCopy, this));
+ mCommitCallbackRegistrar.add("Perms.OK", boost::bind(&LLFloaterPerms::onClickOK, this));
+ mCommitCallbackRegistrar.add("Perms.Cancel", boost::bind(&LLFloaterPerms::onClickCancel, this));
+
}
BOOL LLFloaterPerms::postBuild()
{
- childSetEnabled("next_owner_transfer", gSavedSettings.getBOOL("NextOwnerCopy"));
- childSetAction("help", onClickHelp, this);
- childSetAction("ok", onClickOK, this);
- childSetAction("cancel", onClickCancel, this);
- childSetCommitCallback("next_owner_copy", &onCommitCopy, this);
-
+ mCloseSignal.connect(boost::bind(&LLFloaterPerms::cancel, this));
+
refresh();
return TRUE;
}
-//static
-void LLFloaterPerms::onClickOK(void* data)
+void LLFloaterPerms::onClickOK()
{
- LLFloaterPerms* self = static_cast<LLFloaterPerms*>(data);
- self->ok();
- self->close();
+ ok();
+ closeFloater();
}
-//static
-void LLFloaterPerms::onClickCancel(void* data)
+void LLFloaterPerms::onClickCancel()
{
- LLFloaterPerms* self = static_cast<LLFloaterPerms*>(data);
- self->cancel();
- self->close();
+ cancel();
+ closeFloater();
}
-//static
-void LLFloaterPerms::onCommitCopy(LLUICtrl* ctrl, void* data)
+void LLFloaterPerms::onCommitCopy()
{
- LLFloaterPerms* self = static_cast<LLFloaterPerms*>(data);
// Implements fair use
BOOL copyable = gSavedSettings.getBOOL("NextOwnerCopy");
if(!copyable)
{
gSavedSettings.setBOOL("NextOwnerTransfer", TRUE);
}
- LLCheckBoxCtrl* xfer = self->getChild<LLCheckBoxCtrl>("next_owner_transfer");
+ LLCheckBoxCtrl* xfer = getChild<LLCheckBoxCtrl>("next_owner_transfer");
xfer->setEnabled(copyable);
}
@@ -112,14 +106,6 @@ void LLFloaterPerms::refresh()
mNextOwnerTransfer = gSavedSettings.getBOOL("NextOwnerTransfer");
}
-void LLFloaterPerms::onClose(bool app_quitting)
-{
- // Cancel any unsaved changes before closing.
- // Note: when closed due to the OK button this amounts to a no-op.
- cancel();
- LLFloater::onClose(app_quitting);
-}
-
//static
U32 LLFloaterPerms::getGroupPerms(std::string prefix)
{
@@ -151,9 +137,3 @@ U32 LLFloaterPerms::getNextOwnerPerms(std::string prefix)
return flags;
}
-
-//static
-void LLFloaterPerms::onClickHelp(void* data)
-{
- LLNotifications::instance().add("ClickUploadHelpPermissions");
-}
diff --git a/indra/newview/llfloaterperms.h b/indra/newview/llfloaterperms.h
index 805039efe4..2426f43ca7 100644
--- a/indra/newview/llfloaterperms.h
+++ b/indra/newview/llfloaterperms.h
@@ -36,18 +36,17 @@
#include "llfloater.h"
-class LLFloaterPerms : public LLFloater, public LLFloaterSingleton<LLFloaterPerms>
+class LLFloaterPerms : public LLFloater
{
- friend class LLUISingleton<LLFloaterPerms, VisibilityPolicy<LLFloater> >;
+ friend class LLFloaterReg;
public:
- /*virtual*/ void onClose(bool app_quitting = false);
/*virtual*/ BOOL postBuild();
void ok();
void cancel();
- static void onClickOK(void*);
- static void onClickCancel(void*);
- static void onCommitCopy(LLUICtrl* ctrl, void* data);
+ void onClickOK();
+ void onClickCancel();
+ void onCommitCopy();
// Convenience methods to get current permission preference bitfields from saved settings:
static U32 getEveryonePerms(std::string prefix=""); // prefix + "EveryoneCopy"
static U32 getGroupPerms(std::string prefix=""); // prefix + "ShareWithGroup"
@@ -57,9 +56,6 @@ private:
LLFloaterPerms(const LLSD& seed);
void refresh();
- /// callback for the menus help button
- static void onClickHelp(void* data);
-
BOOL // cached values only for implementing cancel.
mShareWithGroup,
mEveryoneCopy,
diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp
index b0ab0f9625..8da44e2035 100644
--- a/indra/newview/llfloaterpostcard.cpp
+++ b/indra/newview/llfloaterpostcard.cpp
@@ -43,8 +43,10 @@
#include "llagent.h"
#include "llui.h"
#include "lllineeditor.h"
-#include "llviewertexteditor.h"
#include "llbutton.h"
+#include "lltexteditor.h"
+#include "llfloaterreg.h"
+#include "llnotificationsutil.h"
#include "llviewercontrol.h"
#include "llviewernetwork.h"
#include "lluictrlfactory.h"
@@ -54,15 +56,15 @@
#include "llstatusbar.h"
#include "llviewerregion.h"
#include "lleconomy.h"
+#include "message.h"
-#include "llgl.h"
-#include "llglheaders.h"
#include "llimagejpeg.h"
#include "llimagej2c.h"
#include "llvfile.h"
#include "llvfs.h"
-
+#include "llviewertexture.h"
#include "llassetuploadresponders.h"
+#include "llagentui.h"
#include <boost/regex.hpp> //boost.regex lib
@@ -70,89 +72,59 @@
/// Local function declarations, constants, enums, and typedefs
///----------------------------------------------------------------------------
-//static
-LLFloaterPostcard::instance_list_t LLFloaterPostcard::sInstances;
-
///----------------------------------------------------------------------------
/// Class LLFloaterPostcard
///----------------------------------------------------------------------------
-LLFloaterPostcard::LLFloaterPostcard(LLImageJPEG* jpeg, LLImageGL *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global)
-: LLFloater(std::string("Postcard Floater")),
- mJPEGImage(jpeg),
- mViewerImage(img),
- mImageScale(img_scale),
- mPosTakenGlobal(pos_taken_global),
+LLFloaterPostcard::LLFloaterPostcard(const LLSD& key)
+: LLFloater(key),
+ mJPEGImage(NULL),
+ mViewerImage(NULL),
mHasFirstMsgFocus(false)
{
- init();
-}
-
-void LLFloaterPostcard::init()
-{
- // pick up the user's up-to-date email address
- if(!gAgent.getID().isNull())
- {
- // we're logged in, so we can get this info.
- gMessageSystem->newMessageFast(_PREHASH_UserInfoRequest);
- gMessageSystem->nextBlockFast(_PREHASH_AgentData);
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- gAgent.sendReliableMessage();
- }
-
- sInstances.insert(this);
+ //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_postcard.xml");
}
// Destroys the object
LLFloaterPostcard::~LLFloaterPostcard()
{
- sInstances.erase(this);
mJPEGImage = NULL; // deletes image
}
BOOL LLFloaterPostcard::postBuild()
{
+ // pick up the user's up-to-date email address
+ gAgent.sendAgentUserInfoRequest();
+
childSetAction("cancel_btn", onClickCancel, this);
childSetAction("send_btn", onClickSend, this);
childDisable("from_form");
std::string name_string;
- gAgent.buildFullname(name_string);
+ LLAgentUI::buildFullname(name_string);
childSetValue("name_form", LLSD(name_string));
- LLTextEditor* MsgField = getChild<LLTextEditor>("msg_form");
- if (MsgField)
- {
- MsgField->setWordWrap(TRUE);
-
- // For the first time a user focusess to .the msg box, all text will be selected.
- MsgField->setFocusChangedCallback(onMsgFormFocusRecieved, this);
- }
+ // For the first time a user focusess to .the msg box, all text will be selected.
+ getChild<LLUICtrl>("msg_form")->setFocusChangedCallback(boost::bind(onMsgFormFocusRecieved, _1, this));
childSetFocus("to_form", TRUE);
return TRUE;
}
-
-
// static
-LLFloaterPostcard* LLFloaterPostcard::showFromSnapshot(LLImageJPEG *jpeg, LLImageGL *img, const LLVector2 &image_scale, const LLVector3d& pos_taken_global)
+LLFloaterPostcard* LLFloaterPostcard::showFromSnapshot(LLImageJPEG *jpeg, LLViewerTexture *img, const LLVector2 &image_scale, const LLVector3d& pos_taken_global)
{
// Take the images from the caller
// It's now our job to clean them up
- LLFloaterPostcard *instance = new LLFloaterPostcard(jpeg, img, image_scale, pos_taken_global);
-
- LLUICtrlFactory::getInstance()->buildFloater(instance, "floater_postcard.xml");
-
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- instance->setOrigin(left, top - instance->getRect().getHeight());
+ LLFloaterPostcard* instance = LLFloaterReg::showTypedInstance<LLFloaterPostcard>("postcard", LLSD(img->getID()));
+
+ instance->mJPEGImage = jpeg;
+ instance->mViewerImage = img;
+ instance->mImageScale = image_scale;
+ instance->mPosTakenGlobal = pos_taken_global;
- instance->open(); /*Flawfinder: ignore*/
-
return instance;
}
@@ -176,11 +148,11 @@ void LLFloaterPostcard::draw()
F32 ratio = (F32)mJPEGImage->getWidth() / (F32)mJPEGImage->getHeight();
if ((F32)rect.getWidth() / (F32)rect.getHeight() >= ratio)
{
- rect.mRight = (S32)((F32)rect.mLeft + ((F32)rect.getHeight() * ratio));
+ rect.mRight = LLRect::tCoordType((F32)rect.mLeft + ((F32)rect.getHeight() * ratio));
}
else
{
- rect.mBottom = (S32)((F32)rect.mTop - ((F32)rect.getWidth() / ratio));
+ rect.mBottom = LLRect::tCoordType((F32)rect.mTop - ((F32)rect.getWidth() / ratio));
}
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
@@ -198,7 +170,7 @@ void LLFloaterPostcard::draw()
rect.mBottom,
rect.getWidth(),
rect.getHeight(),
- mViewerImage,
+ mViewerImage.get(),
LLColor4::white);
}
glMatrixMode(GL_TEXTURE);
@@ -215,7 +187,7 @@ void LLFloaterPostcard::onClickCancel(void* data)
{
LLFloaterPostcard *self = (LLFloaterPostcard *)data;
- self->close(false);
+ self->closeFloater(false);
}
}
@@ -250,20 +222,20 @@ void LLFloaterPostcard::onClickSend(void* data)
if (to.empty() || !boost::regex_match(to, emailFormat))
{
- LLNotifications::instance().add("PromptRecipientEmail");
+ LLNotificationsUtil::add("PromptRecipientEmail");
return;
}
if (from.empty() || !boost::regex_match(from, emailFormat))
{
- LLNotifications::instance().add("PromptSelfEmail");
+ LLNotificationsUtil::add("PromptSelfEmail");
return;
}
std::string subject(self->childGetValue("subject_form").asString());
if(subject.empty() || !self->mHasFirstMsgFocus)
{
- LLNotifications::instance().add("PromptMissingSubjMsg", LLSD(), LLSD(), boost::bind(&LLFloaterPostcard::missingSubjMsgAlertCallback, self, _1, _2));
+ LLNotificationsUtil::add("PromptMissingSubjMsg", LLSD(), LLSD(), boost::bind(&LLFloaterPostcard::missingSubjMsgAlertCallback, self, _1, _2));
return;
}
@@ -273,7 +245,7 @@ void LLFloaterPostcard::onClickSend(void* data)
}
else
{
- LLNotifications::instance().add("ErrorProcessingSnapshot");
+ LLNotificationsUtil::add("ErrorProcessingSnapshot");
}
}
}
@@ -289,7 +261,7 @@ void LLFloaterPostcard::uploadCallback(const LLUUID& asset_id, void *user_data,
{
LLSD args;
args["REASON"] = std::string(LLAssetStorage::getErrorString(result));
- LLNotifications::instance().add("ErrorUploadingPostcard", args);
+ LLNotificationsUtil::add("ErrorUploadingPostcard", args);
}
else
{
@@ -313,16 +285,17 @@ void LLFloaterPostcard::uploadCallback(const LLUUID& asset_id, void *user_data,
gAgent.sendReliableMessage();
}
- self->close();
+ self->closeFloater();
}
// static
void LLFloaterPostcard::updateUserInfo(const std::string& email)
{
- for (instance_list_t::iterator iter = sInstances.begin();
- iter != sInstances.end(); ++iter)
+ LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("postcard");
+ for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin();
+ iter != inst_list.end(); ++iter)
{
- LLFloaterPostcard *instance = *iter;
+ LLFloater* instance = *iter;
const std::string& text = instance->childGetValue("from_form").asString();
if (text.empty())
{
@@ -348,7 +321,7 @@ void LLFloaterPostcard::onMsgFormFocusRecieved(LLFocusableElement* receiver, voi
bool LLFloaterPostcard::missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if(0 == option)
{
// User clicked OK
diff --git a/indra/newview/llfloaterpostcard.h b/indra/newview/llfloaterpostcard.h
index 087649f159..0a44b50779 100644
--- a/indra/newview/llfloaterpostcard.h
+++ b/indra/newview/llfloaterpostcard.h
@@ -36,25 +36,25 @@
#include "llfloater.h"
#include "llcheckboxctrl.h"
-#include "llmemory.h"
-#include "llimagegl.h"
+#include "llpointer.h"
class LLTextEditor;
class LLLineEditor;
class LLButton;
+class LLViewerTexture;
+class LLImageJPEG;
class LLFloaterPostcard
: public LLFloater
{
public:
- LLFloaterPostcard(LLImageJPEG* jpeg, LLImageGL *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global);
+ LLFloaterPostcard(const LLSD& key);
virtual ~LLFloaterPostcard();
- virtual void init();
virtual BOOL postBuild();
virtual void draw();
- static LLFloaterPostcard* showFromSnapshot(LLImageJPEG *jpeg, LLImageGL *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global);
+ static LLFloaterPostcard* showFromSnapshot(LLImageJPEG *jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global);
static void onClickCancel(void* data);
static void onClickSend(void* data);
@@ -70,18 +70,15 @@ public:
void sendPostcard();
-protected:
+private:
LLPointer<LLImageJPEG> mJPEGImage;
- LLPointer<LLImageGL> mViewerImage;
+ LLPointer<LLViewerTexture> mViewerImage;
LLTransactionID mTransactionID;
LLAssetID mAssetID;
LLVector2 mImageScale;
LLVector3d mPosTakenGlobal;
- boolean mHasFirstMsgFocus;
-
- typedef std::set<LLFloaterPostcard*> instance_list_t;
- static instance_list_t sInstances;
+ bool mHasFirstMsgFocus;
};
diff --git a/indra/newview/llfloaterpostprocess.cpp b/indra/newview/llfloaterpostprocess.cpp
index de9b598b1e..87a12d3d66 100644
--- a/indra/newview/llfloaterpostprocess.cpp
+++ b/indra/newview/llfloaterpostprocess.cpp
@@ -36,6 +36,7 @@
#include "llsliderctrl.h"
#include "llcheckboxctrl.h"
+#include "llnotificationsutil.h"
#include "lluictrlfactory.h"
#include "llviewerdisplay.h"
#include "llpostprocess.h"
@@ -44,13 +45,19 @@
#include "llviewerwindow.h"
-LLFloaterPostProcess* LLFloaterPostProcess::sPostProcess = NULL;
-
+LLFloaterPostProcess::LLFloaterPostProcess(const LLSD& key)
+ : LLFloater(key)
+{
+ //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_post_process.xml");
+}
-LLFloaterPostProcess::LLFloaterPostProcess() : LLFloater(std::string("Post-Process Floater"))
+LLFloaterPostProcess::~LLFloaterPostProcess()
{
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_post_process.xml");
+
+}
+BOOL LLFloaterPostProcess::postBuild()
+{
/// Color Filter Callbacks
childSetCommitCallback("ColorFilterToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_color_filter");
//childSetCommitCallback("ColorFilterGamma", &LLFloaterPostProcess::onFloatControlMoved, &(gPostProcess->tweaks.gamma()));
@@ -77,32 +84,14 @@ LLFloaterPostProcess::LLFloaterPostProcess() : LLFloater(std::string("Post-Proce
// Effect loading and saving.
LLComboBox* comboBox = getChild<LLComboBox>("PPEffectsCombo");
- childSetAction("PPLoadEffect", &LLFloaterPostProcess::onLoadEffect, comboBox);
- comboBox->setCommitCallback(onChangeEffectName);
+ getChild<LLComboBox>("PPLoadEffect")->setCommitCallback(boost::bind(&LLFloaterPostProcess::onLoadEffect, this, comboBox));
+ comboBox->setCommitCallback(boost::bind(&LLFloaterPostProcess::onChangeEffectName, this, _1));
LLLineEditor* editBox = getChild<LLLineEditor>("PPEffectNameEditor");
- childSetAction("PPSaveEffect", &LLFloaterPostProcess::onSaveEffect, editBox);
+ getChild<LLComboBox>("PPSaveEffect")->setCommitCallback(boost::bind(&LLFloaterPostProcess::onSaveEffect, this, editBox));
syncMenu();
-
-}
-
-LLFloaterPostProcess::~LLFloaterPostProcess()
-{
-
-
-}
-
-LLFloaterPostProcess* LLFloaterPostProcess::instance()
-{
- // if we don't have our singleton instance, create it
- if (!sPostProcess)
- {
- sPostProcess = new LLFloaterPostProcess();
- sPostProcess->open();
- sPostProcess->setFocus(TRUE);
- }
- return sPostProcess;
+ return TRUE;
}
// Bool Toggle
@@ -155,79 +144,55 @@ void LLFloaterPostProcess::onColorControlIMoved(LLUICtrl* ctrl, void* userData)
gPostProcess->tweaks[floatVariableName][3] = sldrCtrl->getValue();
}
-void LLFloaterPostProcess::onLoadEffect(void* userData)
+void LLFloaterPostProcess::onLoadEffect(LLComboBox* comboBox)
{
- LLComboBox* comboBox = static_cast<LLComboBox*>(userData);
-
LLSD::String effectName(comboBox->getSelectedValue().asString());
gPostProcess->setSelectedEffect(effectName);
- sPostProcess->syncMenu();
+ syncMenu();
}
-void LLFloaterPostProcess::onSaveEffect(void* userData)
+void LLFloaterPostProcess::onSaveEffect(LLLineEditor* editBox)
{
- LLLineEditor* editBox = static_cast<LLLineEditor*>(userData);
-
std::string effectName(editBox->getValue().asString());
if (gPostProcess->mAllEffects.has(effectName))
{
LLSD payload;
payload["effect_name"] = effectName;
- LLNotifications::instance().add("PPSaveEffectAlert", LLSD(), payload, &LLFloaterPostProcess::saveAlertCallback);
+ LLNotificationsUtil::add("PPSaveEffectAlert", LLSD(), payload, boost::bind(&LLFloaterPostProcess::saveAlertCallback, this, _1, _2));
}
else
{
gPostProcess->saveEffect(effectName);
- sPostProcess->syncMenu();
+ syncMenu();
}
}
-void LLFloaterPostProcess::onChangeEffectName(LLUICtrl* ctrl, void * userData)
+void LLFloaterPostProcess::onChangeEffectName(LLUICtrl* ctrl)
{
// get the combo box and name
- LLComboBox * comboBox = static_cast<LLComboBox*>(ctrl);
- LLLineEditor* editBox = sPostProcess->getChild<LLLineEditor>("PPEffectNameEditor");
+ LLLineEditor* editBox = getChild<LLLineEditor>("PPEffectNameEditor");
// set the parameter's new name
- editBox->setValue(comboBox->getSelectedValue());
+ editBox->setValue(ctrl->getValue());
}
bool LLFloaterPostProcess::saveAlertCallback(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
// if they choose save, do it. Otherwise, don't do anything
if (option == 0)
{
gPostProcess->saveEffect(notification["payload"]["effect_name"].asString());
- sPostProcess->syncMenu();
+ syncMenu();
}
return false;
}
-void LLFloaterPostProcess::show()
-{
- // get the instance, make sure the values are synced
- // and open the menu
- LLFloaterPostProcess* postProcess = instance();
- postProcess->syncMenu();
- postProcess->open();
-}
-
-// virtual
-void LLFloaterPostProcess::onClose(bool app_quitting)
-{
- // just set visibility to false, don't get fancy yet
- if (sPostProcess)
- {
- sPostProcess->setVisible(FALSE);
- }
-}
-
void LLFloaterPostProcess::syncMenu()
{
// add the combo boxe contents
diff --git a/indra/newview/llfloaterpostprocess.h b/indra/newview/llfloaterpostprocess.h
index 08a3618c2b..c789adee00 100644
--- a/indra/newview/llfloaterpostprocess.h
+++ b/indra/newview/llfloaterpostprocess.h
@@ -36,6 +36,8 @@
#include "llfloater.h"
class LLButton;
+class LLComboBox;
+class LLLineEditor;
class LLSliderCtrl;
class LLTabContainer;
class LLPanelPermissions;
@@ -51,11 +53,9 @@ class LLFloaterPostProcess : public LLFloater
{
public:
- LLFloaterPostProcess();
+ LLFloaterPostProcess(const LLSD& key);
virtual ~LLFloaterPostProcess();
-
- /// one and one instance only
- static LLFloaterPostProcess* instance();
+ /*virtual*/ BOOL postBuild();
/// post process callbacks
static void onBoolToggle(LLUICtrl* ctrl, void* userData);
@@ -64,18 +64,12 @@ public:
static void onColorControlGMoved(LLUICtrl* ctrl, void* userData);
static void onColorControlBMoved(LLUICtrl* ctrl, void* userData);
static void onColorControlIMoved(LLUICtrl* ctrl, void* userData);
- static void onLoadEffect(void* userData);
- static void onSaveEffect(void* userData);
- static void onChangeEffectName(LLUICtrl* ctrl, void * userData);
+ void onLoadEffect(LLComboBox* comboBox);
+ void onSaveEffect(LLLineEditor* editBox);
+ void onChangeEffectName(LLUICtrl* ctrl);
/// prompts a user when overwriting an effect
- static bool saveAlertCallback(const LLSD& notification, const LLSD& response);
-
- /// show off our menu
- static void show();
-
- /// stuff to do on exit
- virtual void onClose(bool app_quitting);
+ bool saveAlertCallback(const LLSD& notification, const LLSD& response);
/// sync up sliders
void syncMenu();
@@ -84,8 +78,6 @@ public:
void refresh();
*/
public:
-
- static LLFloaterPostProcess* sPostProcess;
};
#endif
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 17a59ccb77..e77c93b5f8 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -40,477 +40,1488 @@
#include "llfloaterpreference.h"
-#include "llbutton.h"
-#include "llcheckboxctrl.h"
-#include "lldir.h"
-#include "llfocusmgr.h"
-#include "llscrollbar.h"
-#include "llspinctrl.h"
#include "message.h"
+#include "llagent.h"
+#include "llavatarconstants.h"
+#include "llcheckboxctrl.h"
+#include "llcolorswatch.h"
+#include "llcombobox.h"
#include "llcommandhandler.h"
+#include "lldirpicker.h"
+#include "llfeaturemanager.h"
+#include "llfocusmgr.h"
+//#include "llfirstuse.h"
+#include "llfloaterreg.h"
#include "llfloaterabout.h"
-#include "llfloaterpreference.h"
-#include "llpanelnetwork.h"
-#include "llpanelaudioprefs.h"
-#include "llpaneldisplay.h"
-#include "llpaneldebug.h"
-#include "llpanelgeneral.h"
-#include "llpanelinput.h"
+#include "llfloaterhardwaresettings.h"
+#include "llfloatervoicedevicesettings.h"
+#include "llimfloater.h"
+#include "llkeyboard.h"
+#include "llmodaldialog.h"
+#include "llnavigationbar.h"
+#include "llnearbychat.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
#include "llpanellogin.h"
-#include "llpanelLCD.h"
-#include "llpanelmsgs.h"
-#include "llpanelweb.h"
-#include "llpanelskins.h"
-#include "llprefschat.h"
-#include "llprefsvoice.h"
-#include "llprefsim.h"
-#include "llresizehandle.h"
-#include "llresmgr.h"
-#include "llassetstorage.h"
-#include "llagent.h"
+#include "llradiogroup.h"
+#include "llsearchcombobox.h"
+#include "llsky.h"
+#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "llsliderctrl.h"
+#include "lltabcontainer.h"
+#include "lltrans.h"
#include "llviewercontrol.h"
-#include "llviewernetwork.h"
-#include "lluictrlfactory.h"
+#include "llviewercamera.h"
#include "llviewerwindow.h"
-#include "llkeyboard.h"
-#include "llscrollcontainer.h"
-#include "llfloaterhardwaresettings.h"
+#include "llviewermessage.h"
+#include "llviewershadermgr.h"
+#include "llvotree.h"
+#include "llvosky.h"
-const S32 PREF_BORDER = 4;
-const S32 PREF_PAD = 5;
-const S32 PREF_BUTTON_WIDTH = 70;
-const S32 PREF_CATEGORY_WIDTH = 150;
+// linden library includes
+#include "llerror.h"
+#include "llfontgl.h"
+#include "llrect.h"
+#include "llstring.h"
-const S32 PREF_FLOATER_MIN_HEIGHT = 2 * SCROLLBAR_SIZE + 2 * LLPANEL_BORDER_WIDTH + 96;
+// project includes
-LLFloaterPreference* LLFloaterPreference::sInstance = NULL;
+#include "llbutton.h"
+#include "llflexibleobject.h"
+#include "lllineeditor.h"
+#include "llresmgr.h"
+#include "llspinctrl.h"
+#include "llstartup.h"
+#include "lltextbox.h"
+#include "llui.h"
+#include "llviewerobjectlist.h"
+#include "llvoavatar.h"
+#include "llvovolume.h"
+#include "llwindow.h"
+#include "llworld.h"
+#include "pipeline.h"
+#include "lluictrlfactory.h"
+#include "llviewermedia.h"
+#include "llpluginclassmedia.h"
+#include "llteleporthistorystorage.h"
+
+const F32 MAX_USER_FAR_CLIP = 512.f;
+const F32 MIN_USER_FAR_CLIP = 64.f;
+const S32 ASPECT_RATIO_STR_LEN = 100;
-class LLPreferencesHandler : public LLCommandHandler
+class LLVoiceSetKeyDialog : public LLModalDialog
{
public:
- // requires trusted browser
- LLPreferencesHandler() : LLCommandHandler("preferences", true) { }
- bool handle(const LLSD& tokens, const LLSD& query_map,
- LLWebBrowserCtrl* web)
- {
- LLFloaterPreference::show(NULL);
- return true;
- }
+ LLVoiceSetKeyDialog(const LLSD& key);
+ ~LLVoiceSetKeyDialog();
+
+ /*virtual*/ BOOL postBuild();
+
+ void setParent(LLFloaterPreference* parent) { mParent = parent; }
+
+ BOOL handleKeyHere(KEY key, MASK mask);
+ static void onCancel(void* user_data);
+
+private:
+ LLFloaterPreference* mParent;
};
-LLPreferencesHandler gPreferencesHandler;
-
+LLVoiceSetKeyDialog::LLVoiceSetKeyDialog(const LLSD& key)
+ : LLModalDialog(key),
+ mParent(NULL)
+{
+// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_select_key.xml", NULL);
+}
-// Must be done at run time, not compile time. JC
-S32 pref_min_width()
+//virtual
+BOOL LLVoiceSetKeyDialog::postBuild()
{
- return
- 2 * PREF_BORDER +
- 2 * PREF_BUTTON_WIDTH +
- PREF_PAD + RESIZE_HANDLE_WIDTH +
- PREF_CATEGORY_WIDTH +
- PREF_PAD;
+ childSetAction("Cancel", onCancel, this);
+ childSetFocus("Cancel");
+
+ gFocusMgr.setKeystrokesOnly(TRUE);
+
+ return TRUE;
}
-S32 pref_min_height()
+LLVoiceSetKeyDialog::~LLVoiceSetKeyDialog()
{
- return
- 2 * PREF_BORDER +
- 3*(BTN_HEIGHT + PREF_PAD) +
- PREF_FLOATER_MIN_HEIGHT;
}
+BOOL LLVoiceSetKeyDialog::handleKeyHere(KEY key, MASK mask)
+{
+ BOOL result = TRUE;
+
+ if(key == 'Q' && mask == MASK_CONTROL)
+ {
+ result = FALSE;
+ }
+ else if (mParent)
+ {
+ mParent->setKey(key);
+ }
+ closeFloater();
+ return result;
+}
-LLPreferenceCore::LLPreferenceCore(LLTabContainer* tab_container, LLButton * default_btn) :
- mTabContainer(tab_container),
- mGeneralPanel(NULL),
- mInputPanel(NULL),
- mNetworkPanel(NULL),
- mDisplayPanel(NULL),
- mAudioPanel(NULL),
- mMsgPanel(NULL),
- mSkinsPanel(NULL),
- mLCDPanel(NULL)
+//static
+void LLVoiceSetKeyDialog::onCancel(void* user_data)
{
- mGeneralPanel = new LLPanelGeneral();
- mTabContainer->addTabPanel(mGeneralPanel, mGeneralPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
- mGeneralPanel->setDefaultBtn(default_btn);
+ LLVoiceSetKeyDialog* self = (LLVoiceSetKeyDialog*)user_data;
+ self->closeFloater();
+}
+
- mInputPanel = new LLPanelInput();
- mTabContainer->addTabPanel(mInputPanel, mInputPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
- mInputPanel->setDefaultBtn(default_btn);
+// global functions
- mNetworkPanel = new LLPanelNetwork();
- mTabContainer->addTabPanel(mNetworkPanel, mNetworkPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
- mNetworkPanel->setDefaultBtn(default_btn);
+// helper functions for getting/freeing the web browser media
+// if creating/destroying these is too slow, we'll need to create
+// a static member and update all our static callbacks
- mWebPanel = new LLPanelWeb();
- mTabContainer->addTabPanel(mWebPanel, mWebPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
- mWebPanel->setDefaultBtn(default_btn);
+void handleNameTagOptionChanged(const LLSD& newvalue);
+viewer_media_t get_web_media();
+bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response);
- mDisplayPanel = new LLPanelDisplay();
- mTabContainer->addTabPanel(mDisplayPanel, mDisplayPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
- mDisplayPanel->setDefaultBtn(default_btn);
+//bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater);
+//bool callback_reset_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater);
- mAudioPanel = new LLPanelAudioPrefs();
- mTabContainer->addTabPanel(mAudioPanel, mAudioPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
- mAudioPanel->setDefaultBtn(default_btn);
+void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator);
- mPrefsChat = new LLPrefsChat();
- mTabContainer->addTabPanel(mPrefsChat->getPanel(), mPrefsChat->getPanel()->getLabel(), FALSE, onTabChanged, mTabContainer);
- mPrefsChat->getPanel()->setDefaultBtn(default_btn);
+viewer_media_t get_web_media()
+{
+ viewer_media_t media_source = LLViewerMedia::newMediaImpl(LLUUID::null);
+ media_source->initializeMedia("text/html");
+ return media_source;
+}
- mPrefsVoice = new LLPrefsVoice();
- mTabContainer->addTabPanel(mPrefsVoice, mPrefsVoice->getLabel(), FALSE, onTabChanged, mTabContainer);
- mPrefsVoice->setDefaultBtn(default_btn);
- mPrefsIM = new LLPrefsIM();
- mTabContainer->addTabPanel(mPrefsIM->getPanel(), mPrefsIM->getPanel()->getLabel(), FALSE, onTabChanged, mTabContainer);
- mPrefsIM->getPanel()->setDefaultBtn(default_btn);
+bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if ( option == 0 ) // YES
+ {
+ // clean web
+ viewer_media_t media_source = get_web_media();
+ if (media_source && media_source->hasMedia())
+ media_source->getMediaPlugin()->clear_cache();
+
+ // clean nav bar history
+ LLNavigationBar::getInstance()->clearHistoryCache();
+
+ // flag client texture cache for clearing next time the client runs
+ gSavedSettings.setBOOL("PurgeCacheOnNextStartup", TRUE);
+ LLNotificationsUtil::add("CacheWillClear");
+
+ LLSearchHistory::getInstance()->clearHistory();
+ LLSearchHistory::getInstance()->save();
+ LLSearchComboBox* search_ctrl = LLNavigationBar::getInstance()->getChild<LLSearchComboBox>("search_combo_box");
+ search_ctrl->clearHistory();
-#if LL_LCD_COMPILE
+ LLTeleportHistoryStorage::getInstance()->purgeItems();
+ LLTeleportHistoryStorage::getInstance()->save();
+ }
+
+ return false;
+}
- // only add this option if we actually have a logitech keyboard / speaker set
- if (gLcdScreen->Enabled())
+void handleNameTagOptionChanged(const LLSD& newvalue)
+{
+ S32 name_tag_option = S32(newvalue);
+ if(name_tag_option==2)
{
- mLCDPanel = new LLPanelLCD();
- mTabContainer->addTabPanel(mLCDPanel, mLCDPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
- mLCDPanel->setDefaultBtn(default_btn);
+ gSavedSettings.setBOOL("SmallAvatarNames", TRUE);
}
+}
-#else
- mLCDPanel = NULL;
-#endif
+/*bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (0 == option && floater )
+ {
+ if ( floater )
+ {
+ floater->setAllIgnored();
+ // LLFirstUse::disableFirstUse();
+ floater->buildPopupLists();
+ }
+ }
+ return false;
+}
- mMsgPanel = new LLPanelMsgs();
- mTabContainer->addTabPanel(mMsgPanel, mMsgPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
- mMsgPanel->setDefaultBtn(default_btn);
-
- mSkinsPanel = new LLPanelSkins();
- mTabContainer->addTabPanel(mSkinsPanel, mSkinsPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
- mSkinsPanel->setDefaultBtn(default_btn);
+bool callback_reset_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if ( 0 == option && floater )
+ {
+ if ( floater )
+ {
+ floater->resetAllIgnored();
+ //LLFirstUse::resetFirstUse();
+ floater->buildPopupLists();
+ }
+ }
+ return false;
+}
+*/
- if (!mTabContainer->selectTab(gSavedSettings.getS32("LastPrefTab")))
+void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator)
+{
+ numerator = 0;
+ denominator = 0;
+ for (F32 test_denominator = 1.f; test_denominator < 30.f; test_denominator += 1.f)
{
- mTabContainer->selectFirstTab();
+ if (fmodf((decimal_val * test_denominator) + 0.01f, 1.f) < 0.02f)
+ {
+ numerator = llround(decimal_val * test_denominator);
+ denominator = llround(test_denominator);
+ break;
+ }
}
}
+// static
+std::string LLFloaterPreference::sSkin = "";
+F32 LLFloaterPreference::sAspectRatio = 0.0;
+//////////////////////////////////////////////
+// LLFloaterPreference
-LLPreferenceCore::~LLPreferenceCore()
+LLFloaterPreference::LLFloaterPreference(const LLSD& key)
+ : LLFloater(key),
+ mGotPersonalInfo(false),
+ mOriginalIMViaEmail(false)
{
- if (mGeneralPanel)
+ //Build Floater is now Called from LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>);
+
+ static bool registered_dialog = false;
+ if (!registered_dialog)
{
- delete mGeneralPanel;
- mGeneralPanel = NULL;
+ LLFloaterReg::add("voice_set_key", "floater_select_key.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLVoiceSetKeyDialog>);
+ registered_dialog = true;
}
- if (mInputPanel)
+
+ mCommitCallbackRegistrar.add("Pref.Apply", boost::bind(&LLFloaterPreference::onBtnApply, this));
+ mCommitCallbackRegistrar.add("Pref.Cancel", boost::bind(&LLFloaterPreference::onBtnCancel, this));
+ mCommitCallbackRegistrar.add("Pref.OK", boost::bind(&LLFloaterPreference::onBtnOK, this));
+
+// mCommitCallbackRegistrar.add("Pref.ClearCache", boost::bind(&LLFloaterPreference::onClickClearCache, this));
+ mCommitCallbackRegistrar.add("Pref.WebClearCache", boost::bind(&LLFloaterPreference::onClickBrowserClearCache, this));
+ mCommitCallbackRegistrar.add("Pref.SetCache", boost::bind(&LLFloaterPreference::onClickSetCache, this));
+ mCommitCallbackRegistrar.add("Pref.ResetCache", boost::bind(&LLFloaterPreference::onClickResetCache, this));
+ mCommitCallbackRegistrar.add("Pref.ClickSkin", boost::bind(&LLFloaterPreference::onClickSkin, this,_1, _2));
+ mCommitCallbackRegistrar.add("Pref.SelectSkin", boost::bind(&LLFloaterPreference::onSelectSkin, this));
+ mCommitCallbackRegistrar.add("Pref.VoiceSetKey", boost::bind(&LLFloaterPreference::onClickSetKey, this));
+ mCommitCallbackRegistrar.add("Pref.VoiceSetMiddleMouse", boost::bind(&LLFloaterPreference::onClickSetMiddleMouse, this));
+// mCommitCallbackRegistrar.add("Pref.ClickSkipDialogs", boost::bind(&LLFloaterPreference::onClickSkipDialogs, this));
+// mCommitCallbackRegistrar.add("Pref.ClickResetDialogs", boost::bind(&LLFloaterPreference::onClickResetDialogs, this));
+ mCommitCallbackRegistrar.add("Pref.ClickEnablePopup", boost::bind(&LLFloaterPreference::onClickEnablePopup, this));
+ mCommitCallbackRegistrar.add("Pref.ClickDisablePopup", boost::bind(&LLFloaterPreference::onClickDisablePopup, this));
+ mCommitCallbackRegistrar.add("Pref.LogPath", boost::bind(&LLFloaterPreference::onClickLogPath, this));
+ mCommitCallbackRegistrar.add("Pref.UpdateMeterText", boost::bind(&LLFloaterPreference::updateMeterText, this, _1));
+ mCommitCallbackRegistrar.add("Pref.HardwareSettings", boost::bind(&LLFloaterPreference::onOpenHardwareSettings, this));
+ mCommitCallbackRegistrar.add("Pref.HardwareDefaults", boost::bind(&LLFloaterPreference::setHardwareDefaults, this));
+ mCommitCallbackRegistrar.add("Pref.VertexShaderEnable", boost::bind(&LLFloaterPreference::onVertexShaderEnable, this));
+ mCommitCallbackRegistrar.add("Pref.WindowedMod", boost::bind(&LLFloaterPreference::onCommitWindowedMode, this));
+ mCommitCallbackRegistrar.add("Pref.UpdateSliderText", boost::bind(&LLFloaterPreference::onUpdateSliderText,this, _1,_2));
+ mCommitCallbackRegistrar.add("Pref.AutoDetectAspect", boost::bind(&LLFloaterPreference::onCommitAutoDetectAspect, this));
+ mCommitCallbackRegistrar.add("Pref.ParcelMediaAutoPlayEnable", boost::bind(&LLFloaterPreference::onCommitParcelMediaAutoPlayEnable, this));
+ mCommitCallbackRegistrar.add("Pref.MediaEnabled", boost::bind(&LLFloaterPreference::onCommitMediaEnabled, this));
+ mCommitCallbackRegistrar.add("Pref.MusicEnabled", boost::bind(&LLFloaterPreference::onCommitMusicEnabled, this));
+ mCommitCallbackRegistrar.add("Pref.onSelectAspectRatio", boost::bind(&LLFloaterPreference::onKeystrokeAspectRatio, this));
+ mCommitCallbackRegistrar.add("Pref.QualityPerformance", boost::bind(&LLFloaterPreference::onChangeQuality, this, _2));
+ mCommitCallbackRegistrar.add("Pref.applyUIColor", boost::bind(&LLFloaterPreference::applyUIColor, this ,_1, _2));
+ mCommitCallbackRegistrar.add("Pref.getUIColor", boost::bind(&LLFloaterPreference::getUIColor, this ,_1, _2));
+
+ sSkin = gSavedSettings.getString("SkinCurrent");
+
+ gSavedSettings.getControl("AvatarNameTagMode")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2));
+}
+
+BOOL LLFloaterPreference::postBuild()
+{
+ gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate, _2));
+
+ gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLNearbyChat::processChatHistoryStyleUpdate, _2));
+
+ LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core");
+ if (!tabcontainer->selectTab(gSavedSettings.getS32("LastPrefTab")))
+ tabcontainer->selectFirstTab();
+ S32 show_avatar_nametag_options = gSavedSettings.getS32("AvatarNameTagMode");
+ handleNameTagOptionChanged(LLSD(show_avatar_nametag_options));
+
+ std::string cache_location = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "");
+ childSetText("cache_location", cache_location);
+
+ return TRUE;
+}
+
+LLFloaterPreference::~LLFloaterPreference()
+{
+ // clean up user data
+ LLComboBox* ctrl_aspect_ratio = getChild<LLComboBox>( "aspect_ratio");
+ LLComboBox* ctrl_window_size = getChild<LLComboBox>("windowsize combo");
+ for (S32 i = 0; i < ctrl_aspect_ratio->getItemCount(); i++)
{
- delete mInputPanel;
- mInputPanel = NULL;
+ ctrl_aspect_ratio->setCurrentByIndex(i);
}
- if (mNetworkPanel)
+ for (S32 i = 0; i < ctrl_window_size->getItemCount(); i++)
{
- delete mNetworkPanel;
- mNetworkPanel = NULL;
+ ctrl_window_size->setCurrentByIndex(i);
}
- if (mDisplayPanel)
+}
+
+void LLFloaterPreference::draw()
+{
+ BOOL has_first_selected = (getChildRef<LLScrollListCtrl>("disabled_popups").getFirstSelected()!=NULL);
+ gSavedSettings.setBOOL("FirstSelectedDisabledPopups", has_first_selected);
+
+ has_first_selected = (getChildRef<LLScrollListCtrl>("enabled_popups").getFirstSelected()!=NULL);
+ gSavedSettings.setBOOL("FirstSelectedEnabledPopups", has_first_selected);
+
+ LLFloater::draw();
+}
+
+void LLFloaterPreference::saveSettings()
+{
+ LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core");
+ child_list_t::const_iterator iter = tabcontainer->getChildList()->begin();
+ child_list_t::const_iterator end = tabcontainer->getChildList()->end();
+ for ( ; iter != end; ++iter)
{
- delete mDisplayPanel;
- mDisplayPanel = NULL;
+ LLView* view = *iter;
+ LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view);
+ if (panel)
+ panel->saveSettings();
}
+}
- if (mAudioPanel)
+void LLFloaterPreference::apply()
+{
+ LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core");
+ if (sSkin != gSavedSettings.getString("SkinCurrent"))
+ {
+ LLNotificationsUtil::add("ChangeSkin");
+ refreshSkin(this);
+ }
+ // Call apply() on all panels that derive from LLPanelPreference
+ for (child_list_t::const_iterator iter = tabcontainer->getChildList()->begin();
+ iter != tabcontainer->getChildList()->end(); ++iter)
+ {
+ LLView* view = *iter;
+ LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view);
+ if (panel)
+ panel->apply();
+ }
+ // hardware menu apply
+ LLFloaterHardwareSettings* hardware_settings = LLFloaterReg::getTypedInstance<LLFloaterHardwareSettings>("prefs_hardware_settings");
+ if (hardware_settings)
+ {
+ hardware_settings->apply();
+ }
+
+ LLFloaterVoiceDeviceSettings* voice_device_settings = LLFloaterReg::findTypedInstance<LLFloaterVoiceDeviceSettings>("pref_voicedevicesettings");
+ if(voice_device_settings)
{
- delete mAudioPanel;
- mAudioPanel = NULL;
+ voice_device_settings->apply();
}
- if (mPrefsChat)
+
+ gViewerWindow->requestResolutionUpdate(); // for UIScaleFactor
+
+ LLSliderCtrl* fov_slider = getChild<LLSliderCtrl>("camera_fov");
+ fov_slider->setMinValue(LLViewerCamera::getInstance()->getMinView());
+ fov_slider->setMaxValue(LLViewerCamera::getInstance()->getMaxView());
+
+ std::string cache_location = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "");
+ childSetText("cache_location", cache_location);
+
+ viewer_media_t media_source = get_web_media();
+ if (media_source && media_source->hasMedia())
{
- delete mPrefsChat;
- mPrefsChat = NULL;
+ media_source->getMediaPlugin()->enable_cookies(childGetValue("cookies_enabled"));
+ if(hasChild("web_proxy_enabled") &&hasChild("web_proxy_editor") && hasChild("web_proxy_port"))
+ {
+ bool proxy_enable = childGetValue("web_proxy_enabled");
+ std::string proxy_address = childGetValue("web_proxy_editor");
+ int proxy_port = childGetValue("web_proxy_port");
+ media_source->getMediaPlugin()->proxy_setup(proxy_enable, proxy_address, proxy_port);
+ }
}
- if (mPrefsIM)
+
+// LLWString busy_response = utf8str_to_wstring(getChild<LLUICtrl>("busy_response")->getValue().asString());
+// LLWStringUtil::replaceTabsWithSpaces(busy_response, 4);
+
+ gSavedSettings.setBOOL("PlainTextChatHistory", childGetValue("plain_text_chat_history").asBoolean());
+
+ if(mGotPersonalInfo)
+ {
+// gSavedSettings.setString("BusyModeResponse2", std::string(wstring_to_utf8str(busy_response)));
+ bool new_im_via_email = childGetValue("send_im_to_email").asBoolean();
+ bool new_hide_online = childGetValue("online_visibility").asBoolean();
+
+ if((new_im_via_email != mOriginalIMViaEmail)
+ ||(new_hide_online != mOriginalHideOnlineStatus))
+ {
+ // This hack is because we are representing several different
+ // possible strings with a single checkbox. Since most users
+ // can only select between 2 values, we represent it as a
+ // checkbox. This breaks down a little bit for liaisons, but
+ // works out in the end.
+ if(new_hide_online != mOriginalHideOnlineStatus)
+ {
+ if(new_hide_online) mDirectoryVisibility = VISIBILITY_HIDDEN;
+ else mDirectoryVisibility = VISIBILITY_DEFAULT;
+ //Update showonline value, otherwise multiple applys won't work
+ mOriginalHideOnlineStatus = new_hide_online;
+ }
+ gAgent.sendAgentUpdateUserInfo(new_im_via_email,mDirectoryVisibility);
+ }
+ }
+
+ applyResolution();
+}
+
+void LLFloaterPreference::cancel()
+{
+ LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core");
+ // Call cancel() on all panels that derive from LLPanelPreference
+ for (child_list_t::const_iterator iter = tabcontainer->getChildList()->begin();
+ iter != tabcontainer->getChildList()->end(); ++iter)
{
- delete mPrefsIM;
- mPrefsIM = NULL;
+ LLView* view = *iter;
+ LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view);
+ if (panel)
+ panel->cancel();
}
- if (mMsgPanel)
+ // hide joystick pref floater
+ LLFloaterReg::hideInstance("pref_joystick");
+
+ // cancel hardware menu
+ LLFloaterHardwareSettings* hardware_settings = LLFloaterReg::getTypedInstance<LLFloaterHardwareSettings>("prefs_hardware_settings");
+ if (hardware_settings)
{
- delete mMsgPanel;
- mMsgPanel = NULL;
+ hardware_settings->cancel();
}
- if (mWebPanel)
+
+ // reverts any changes to current skin
+ gSavedSettings.setString("SkinCurrent", sSkin);
+
+ LLFloaterVoiceDeviceSettings* voice_device_settings = LLFloaterReg::findTypedInstance<LLFloaterVoiceDeviceSettings>("pref_voicedevicesettings");
+ if (voice_device_settings)
{
- delete mWebPanel;
- mWebPanel = NULL;
+ voice_device_settings ->cancel();
}
- if (mSkinsPanel)
+
+ LLFloaterReg::hideInstance("pref_voicedevicesettings");
+
+ gSavedSettings.setF32("FullScreenAspectRatio", sAspectRatio);
+
+}
+
+void LLFloaterPreference::onOpen(const LLSD& key)
+{
+ gAgent.sendAgentUserInfoRequest();
+
+ /////////////////////////// From LLPanelGeneral //////////////////////////
+ // if we have no agent, we can't let them choose anything
+ // if we have an agent, then we only let them choose if they have a choice
+ bool can_choose_maturity =
+ gAgent.getID().notNull() && (gAgent.isMature() || gAgent.isGodlike());
+
+ LLComboBox* maturity_combo = getChild<LLComboBox>("maturity_desired_combobox");
+
+ if (can_choose_maturity)
+ {
+ // if they're not adult or a god, they shouldn't see the adult selection, so delete it
+ if (!gAgent.isAdult() && !gAgent.isGodlike())
+ {
+ // we're going to remove the adult entry from the combo. This obviously depends
+ // on the order of items in the XML file, but there doesn't seem to be a reasonable
+ // way to depend on the field in XML called 'name'.
+ maturity_combo->remove(0);
+ }
+ childSetVisible("maturity_desired_combobox", true);
+ childSetVisible("maturity_desired_textbox", false);
+ }
+ else
{
- delete mSkinsPanel;
- mSkinsPanel = NULL;
+ childSetText("maturity_desired_textbox", maturity_combo->getSelectedItemLabel());
+ childSetVisible("maturity_desired_combobox", false);
}
+
+ // Enabled/disabled popups, might have been changed by user actions
+ // while preferences floater was closed.
+ buildPopupLists();
+ LLPanelLogin::setAlwaysRefresh(true);
+ refresh();
+
+ // Make sure the current state of prefs are saved away when
+ // when the floater is opened. That will make cancel do its
+ // job
+ saveSettings();
}
+void LLFloaterPreference::onVertexShaderEnable()
+{
+ refreshEnabledGraphics();
+}
-void LLPreferenceCore::apply()
+void LLFloaterPreference::setHardwareDefaults()
{
- mGeneralPanel->apply();
- mInputPanel->apply();
- mNetworkPanel->apply();
- mDisplayPanel->apply();
- mAudioPanel->apply();
- mPrefsChat->apply();
- mPrefsVoice->apply();
- mPrefsIM->apply();
- mMsgPanel->apply();
- mSkinsPanel->apply();
+ LLFeatureManager::getInstance()->applyRecommendedSettings();
+ refreshEnabledGraphics();
+}
- // hardware menu apply
- LLFloaterHardwareSettings::instance()->apply();
+//virtual
+void LLFloaterPreference::onClose(bool app_quitting)
+{
+ gSavedSettings.setS32("LastPrefTab", getChild<LLTabContainer>("pref core")->getCurrentPanelIndex());
+ LLPanelLogin::setAlwaysRefresh(false);
+ cancel();
+}
+
+void LLFloaterPreference::onOpenHardwareSettings()
+{
+ LLFloaterReg::showInstance("prefs_hardware_settings");
+}
+// static
+void LLFloaterPreference::onBtnOK()
+{
+ // commit any outstanding text entry
+ if (hasFocus())
+ {
+ LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
+ if (cur_focus->acceptsTextInput())
+ {
+ cur_focus->onCommit();
+ }
+ }
+
+ if (canClose())
+ {
+ saveSettings();
+ apply();
+ closeFloater(false);
- mWebPanel->apply();
-#if LL_LCD_COMPILE
- // only add this option if we actually have a logitech keyboard / speaker set
- if (gLcdScreen->Enabled())
+ LLUIColorTable::instance().saveUserSettings();
+ gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
+ std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE);
+ // save all settings, even if equals defaults
+ gCrashSettings.saveToFile(crash_settings_filename, FALSE);
+ }
+ else
+ {
+ // Show beep, pop up dialog, etc.
+ llinfos << "Can't close preferences!" << llendl;
+ }
+
+ LLPanelLogin::refreshLocation( false );
+}
+
+// static
+void LLFloaterPreference::onBtnApply( )
+{
+ if (hasFocus())
{
- mLCDPanel->apply();
+ LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
+ if (cur_focus->acceptsTextInput())
+ {
+ cur_focus->onCommit();
+ }
}
-#endif
-// mWebPanel->apply();
+ apply();
+ saveSettings();
+
+ LLPanelLogin::refreshLocation( false );
}
+// static
+void LLFloaterPreference::onBtnCancel()
+{
+ if (hasFocus())
+ {
+ LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
+ if (cur_focus->acceptsTextInput())
+ {
+ cur_focus->onCommit();
+ }
+ refresh();
+ }
+ cancel();
+ closeFloater();
+}
-void LLPreferenceCore::cancel()
+// static
+void LLFloaterPreference::updateUserInfo(const std::string& visibility, bool im_via_email, const std::string& email)
{
- mGeneralPanel->cancel();
- mInputPanel->cancel();
- mNetworkPanel->cancel();
- mDisplayPanel->cancel();
- mAudioPanel->cancel();
- mPrefsChat->cancel();
- mPrefsVoice->cancel();
- mPrefsIM->cancel();
- mMsgPanel->cancel();
- mSkinsPanel->cancel();
+ LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
+ if(instance)
+ {
+ instance->setPersonalInfo(visibility, im_via_email, email);
+ }
+}
- // cancel hardware menu
- LLFloaterHardwareSettings::instance()->cancel();
- mWebPanel->cancel();
-#if LL_LCD_COMPILE
- // only add this option if we actually have a logitech keyboard / speaker set
- if (gLcdScreen->Enabled())
+void LLFloaterPreference::refreshEnabledGraphics()
+{
+ LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
+ if(instance)
{
- mLCDPanel->cancel();
+ instance->refreshEnabledState();
+ }
+ LLFloaterHardwareSettings* hardware_settings = LLFloaterReg::getTypedInstance<LLFloaterHardwareSettings>("prefs_hardware_settings");
+ if (hardware_settings)
+ {
+ hardware_settings->refreshEnabledState();
}
-#endif
-// mWebPanel->cancel();
}
-// static
-void LLPreferenceCore::onTabChanged(void* user_data, bool from_click)
+void LLFloaterPreference::updateMeterText(LLUICtrl* ctrl)
{
- LLTabContainer* self = (LLTabContainer*)user_data;
+ // get our UI widgets
+ LLSliderCtrl* slider = (LLSliderCtrl*) ctrl;
+
+ LLTextBox* m1 = getChild<LLTextBox>("DrawDistanceMeterText1");
+ LLTextBox* m2 = getChild<LLTextBox>("DrawDistanceMeterText2");
- gSavedSettings.setS32("LastPrefTab", self->getCurrentPanelIndex());
+ // toggle the two text boxes based on whether we have 1 or two digits
+ F32 val = slider->getValueF32();
+ bool two_digits = val < 100;
+ m1->setVisible(two_digits);
+ m2->setVisible(!two_digits);
}
+void LLFloaterPreference::onClickBrowserClearCache()
+{
+ LLNotificationsUtil::add("ConfirmClearBrowserCache", LLSD(), LLSD(), callback_clear_browser_cache);
+}
-void LLPreferenceCore::setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email)
+void LLFloaterPreference::onClickSetCache()
{
- mPrefsIM->setPersonalInfo(visibility, im_via_email, email);
+ std::string cur_name(gSavedSettings.getString("CacheLocation"));
+// std::string cur_top_folder(gDirUtilp->getBaseFileName(cur_name));
+
+ std::string proposed_name(cur_name);
+
+ LLDirPicker& picker = LLDirPicker::instance();
+ if (! picker.getDir(&proposed_name ) )
+ {
+ return; //Canceled!
+ }
+
+ std::string dir_name = picker.getDirName();
+ if (!dir_name.empty() && dir_name != cur_name)
+ {
+ std::string new_top_folder(gDirUtilp->getBaseFileName(dir_name));
+ LLNotificationsUtil::add("CacheWillBeMoved");
+ gSavedSettings.setString("NewCacheLocation", dir_name);
+ gSavedSettings.setString("NewCacheLocationTopFolder", new_top_folder);
+ }
+ else
+ {
+ std::string cache_location = gDirUtilp->getCacheDir();
+ gSavedSettings.setString("CacheLocation", cache_location);
+ std::string top_folder(gDirUtilp->getBaseFileName(cache_location));
+ gSavedSettings.setString("CacheLocationTopFolder", top_folder);
+ }
}
-void LLPreferenceCore::refreshEnabledGraphics()
+void LLFloaterPreference::onClickResetCache()
{
- LLFloaterHardwareSettings::instance()->refreshEnabledState();
- mDisplayPanel->refreshEnabledState();
+ if (!gSavedSettings.getString("CacheLocation").empty())
+ {
+ gSavedSettings.setString("NewCacheLocation", "");
+ gSavedSettings.setString("NewCacheLocationTopFolder", "");
+ }
+
+ LLNotificationsUtil::add("CacheWillBeMoved");
+ std::string cache_location = gDirUtilp->getCacheDir(true);
+ gSavedSettings.setString("CacheLocation", cache_location);
+ std::string top_folder(gDirUtilp->getBaseFileName(cache_location));
+ gSavedSettings.setString("CacheLocationTopFolder", top_folder);
}
-//////////////////////////////////////////////
-// LLFloaterPreference
+void LLFloaterPreference::onClickSkin(LLUICtrl* ctrl, const LLSD& userdata)
+{
+ gSavedSettings.setString("SkinCurrent", userdata.asString());
+ ctrl->setValue(userdata.asString());
+}
-LLFloaterPreference::LLFloaterPreference()
+void LLFloaterPreference::onSelectSkin()
{
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_preferences.xml");
+ std::string skin_selection = getChild<LLRadioGroup>("skin_selection")->getValue().asString();
+ gSavedSettings.setString("SkinCurrent", skin_selection);
}
-BOOL LLFloaterPreference::postBuild()
+void LLFloaterPreference::refreshSkin(void* data)
+{
+ LLPanel*self = (LLPanel*)data;
+ sSkin = gSavedSettings.getString("SkinCurrent");
+ self->getChild<LLRadioGroup>("skin_selection", true)->setValue(sSkin);
+}
+
+
+void LLFloaterPreference::buildPopupLists()
{
- requires<LLButton>("About...");
- requires<LLButton>("OK");
- requires<LLButton>("Cancel");
- requires<LLButton>("Apply");
- requires<LLTabContainer>("pref core");
+ LLScrollListCtrl& disabled_popups =
+ getChildRef<LLScrollListCtrl>("disabled_popups");
+ LLScrollListCtrl& enabled_popups =
+ getChildRef<LLScrollListCtrl>("enabled_popups");
+
+ disabled_popups.deleteAllItems();
+ enabled_popups.deleteAllItems();
+
+ for (LLNotifications::TemplateMap::const_iterator iter = LLNotifications::instance().templatesBegin();
+ iter != LLNotifications::instance().templatesEnd();
+ ++iter)
+ {
+ LLNotificationTemplatePtr templatep = iter->second;
+ LLNotificationFormPtr formp = templatep->mForm;
+
+ LLNotificationForm::EIgnoreType ignore = formp->getIgnoreType();
+ if (ignore == LLNotificationForm::IGNORE_NO)
+ continue;
+
+ LLSD row;
+ row["columns"][0]["value"] = formp->getIgnoreMessage();
+ row["columns"][0]["font"] = "SANSSERIF_SMALL";
+ row["columns"][0]["width"] = 400;
+
+ LLScrollListItem* item = NULL;
+
+ bool show_popup = LLUI::sSettingGroups["ignores"]->getBOOL(templatep->mName);
+ if (!show_popup)
+ {
+ if (ignore == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
+ {
+ LLSD last_response = LLUI::sSettingGroups["config"]->getLLSD("Default" + templatep->mName);
+ if (!last_response.isUndefined())
+ {
+ for (LLSD::map_const_iterator it = last_response.beginMap();
+ it != last_response.endMap();
+ ++it)
+ {
+ if (it->second.asBoolean())
+ {
+ row["columns"][1]["value"] = formp->getElement(it->first)["ignore"].asString();
+ break;
+ }
+ }
+ }
+ row["columns"][1]["font"] = "SANSSERIF_SMALL";
+ row["columns"][1]["width"] = 360;
+ }
+ item = disabled_popups.addElement(row,
+ ADD_SORTED);
+ }
+ else
+ {
+ item = enabled_popups.addElement(row,
+ ADD_SORTED);
+ }
+
+ if (item)
+ {
+ item->setUserdata((void*)&iter->first);
+ }
+ }
+}
- if (!checkRequirements())
+void LLFloaterPreference::refreshEnabledState()
+{
+ LLCheckBoxCtrl* ctrl_reflections = getChild<LLCheckBoxCtrl>("Reflections");
+ LLRadioGroup* radio_reflection_detail = getChild<LLRadioGroup>("ReflectionDetailRadio");
+
+ // Reflections
+ BOOL reflections = gSavedSettings.getBOOL("VertexShaderEnable")
+ && gGLManager.mHasCubeMap
+ && LLCubeMap::sUseCubeMaps;
+ ctrl_reflections->setEnabled(reflections);
+
+ // Bump & Shiny
+ bool bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump");
+ getChild<LLCheckBoxCtrl>("BumpShiny")->setEnabled(bumpshiny ? TRUE : FALSE);
+
+ radio_reflection_detail->setEnabled(ctrl_reflections->get() && reflections);
+
+ // Avatar Mode
+ // Enable Avatar Shaders
+ LLCheckBoxCtrl* ctrl_avatar_vp = getChild<LLCheckBoxCtrl>("AvatarVertexProgram");
+ // Avatar Render Mode
+ LLCheckBoxCtrl* ctrl_avatar_cloth = getChild<LLCheckBoxCtrl>("AvatarCloth");
+
+ S32 max_avatar_shader = LLViewerShaderMgr::instance()->mMaxAvatarShaderLevel;
+ ctrl_avatar_vp->setEnabled((max_avatar_shader > 0) ? TRUE : FALSE);
+
+ if (gSavedSettings.getBOOL("VertexShaderEnable") == FALSE ||
+ gSavedSettings.getBOOL("RenderAvatarVP") == FALSE)
{
- return FALSE;
+ ctrl_avatar_cloth->setEnabled(false);
+ }
+ else
+ {
+ ctrl_avatar_cloth->setEnabled(true);
}
+
+ // Vertex Shaders
+ // Global Shader Enable
+ LLCheckBoxCtrl* ctrl_shader_enable = getChild<LLCheckBoxCtrl>("BasicShaders");
+ // radio set for terrain detail mode
+ LLRadioGroup* mRadioTerrainDetail = getChild<LLRadioGroup>("TerrainDetailRadio"); // can be linked with control var
- mAboutBtn = getChild<LLButton>("About...");
- mAboutBtn->setClickedCallback(onClickAbout, this);
+ ctrl_shader_enable->setEnabled(LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable"));
- mApplyBtn = getChild<LLButton>("Apply");
- mApplyBtn->setClickedCallback(onBtnApply, this);
-
- mCancelBtn = getChild<LLButton>("Cancel");
- mCancelBtn->setClickedCallback(onBtnCancel, this);
+ BOOL shaders = ctrl_shader_enable->get();
+ if (shaders)
+ {
+ mRadioTerrainDetail->setValue(1);
+ mRadioTerrainDetail->setEnabled(FALSE);
+ }
+ else
+ {
+ mRadioTerrainDetail->setEnabled(TRUE);
+ }
+
+ // WindLight
+ LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders");
+
+ // *HACK just checks to see if we can use shaders...
+ // maybe some cards that use shaders, but don't support windlight
+ ctrl_wind_light->setEnabled(ctrl_shader_enable->getEnabled() && shaders);
+ // now turn off any features that are unavailable
+ disableUnavailableSettings();
+}
- mOKBtn = getChild<LLButton>("OK");
- mOKBtn->setClickedCallback(onBtnOK, this);
-
- mPreferenceCore = new LLPreferenceCore(
- getChild<LLTabContainer>("pref core"),
- getChild<LLButton>("OK")
- );
+void LLFloaterPreference::disableUnavailableSettings()
+{
+ LLCheckBoxCtrl* ctrl_reflections = getChild<LLCheckBoxCtrl>("Reflections");
+ LLCheckBoxCtrl* ctrl_avatar_vp = getChild<LLCheckBoxCtrl>("AvatarVertexProgram");
+ LLCheckBoxCtrl* ctrl_avatar_cloth = getChild<LLCheckBoxCtrl>("AvatarCloth");
+ LLCheckBoxCtrl* ctrl_shader_enable = getChild<LLCheckBoxCtrl>("BasicShaders");
+ LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders");
+ LLCheckBoxCtrl* ctrl_avatar_impostors = getChild<LLCheckBoxCtrl>("AvatarImpostors");
+
+ // if vertex shaders off, disable all shader related products
+ if(!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable"))
+ {
+ ctrl_shader_enable->setEnabled(FALSE);
+ ctrl_shader_enable->setValue(FALSE);
+
+ ctrl_wind_light->setEnabled(FALSE);
+ ctrl_wind_light->setValue(FALSE);
+
+ ctrl_reflections->setEnabled(FALSE);
+ ctrl_reflections->setValue(FALSE);
+
+ ctrl_avatar_vp->setEnabled(FALSE);
+ ctrl_avatar_vp->setValue(FALSE);
+
+ ctrl_avatar_cloth->setEnabled(FALSE);
+ ctrl_avatar_cloth->setValue(FALSE);
+ }
- sInstance = this;
+ // disabled windlight
+ if(!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"))
+ {
+ ctrl_wind_light->setEnabled(FALSE);
+ ctrl_wind_light->setValue(FALSE);
+ }
+
+ // disabled reflections
+ if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderWaterReflections"))
+ {
+ ctrl_reflections->setEnabled(FALSE);
+ ctrl_reflections->setValue(FALSE);
+ }
+
+ // disabled av
+ if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarVP"))
+ {
+ ctrl_avatar_vp->setEnabled(FALSE);
+ ctrl_avatar_vp->setValue(FALSE);
+
+ ctrl_avatar_cloth->setEnabled(FALSE);
+ ctrl_avatar_cloth->setValue(FALSE);
+ }
+ // disabled cloth
+ if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarCloth"))
+ {
+ ctrl_avatar_cloth->setEnabled(FALSE);
+ ctrl_avatar_cloth->setValue(FALSE);
+ }
+ // disabled impostors
+ if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderUseImpostors"))
+ {
+ ctrl_avatar_impostors->setEnabled(FALSE);
+ ctrl_avatar_impostors->setValue(FALSE);
+ }
+}
- return TRUE;
+void LLFloaterPreference::onCommitAutoDetectAspect()
+{
+ BOOL auto_detect = getChild<LLCheckBoxCtrl>("aspect_auto_detect")->get();
+ F32 ratio;
+
+ if (auto_detect)
+ {
+ S32 numerator = 0;
+ S32 denominator = 0;
+
+ // clear any aspect ratio override
+ gViewerWindow->mWindow->setNativeAspectRatio(0.f);
+ fractionFromDecimal(gViewerWindow->mWindow->getNativeAspectRatio(), numerator, denominator);
+
+ std::string aspect;
+ if (numerator != 0)
+ {
+ aspect = llformat("%d:%d", numerator, denominator);
+ }
+ else
+ {
+ aspect = llformat("%.3f", gViewerWindow->mWindow->getNativeAspectRatio());
+ }
+
+ getChild<LLComboBox>( "aspect_ratio")->setLabel(aspect);
+
+ ratio = gViewerWindow->mWindow->getNativeAspectRatio();
+ gSavedSettings.setF32("FullScreenAspectRatio", ratio);
+ }
}
+void LLFloaterPreference::onCommitParcelMediaAutoPlayEnable()
+{
+ BOOL autoplay = getChild<LLCheckBoxCtrl>("autoplay_enabled")->get();
+
+ gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, autoplay);
-LLFloaterPreference::~LLFloaterPreference()
+ lldebugs << "autoplay now = " << int(autoplay) << llendl;
+}
+
+void LLFloaterPreference::onCommitMediaEnabled()
{
- sInstance = NULL;
- delete mPreferenceCore;
+ LLCheckBoxCtrl *media_enabled_ctrl = getChild<LLCheckBoxCtrl>("media_enabled");
+ bool enabled = media_enabled_ctrl->get();
+ gSavedSettings.setBOOL("AudioStreamingMedia", enabled);
}
-void LLFloaterPreference::apply()
+void LLFloaterPreference::onCommitMusicEnabled()
{
- this->mPreferenceCore->apply();
+ LLCheckBoxCtrl *music_enabled_ctrl = getChild<LLCheckBoxCtrl>("music_enabled");
+ bool enabled = music_enabled_ctrl->get();
+ gSavedSettings.setBOOL("AudioStreamingMusic", enabled);
}
+void LLFloaterPreference::refresh()
+{
+ LLPanel::refresh();
+
+ // sliders and their text boxes
+ // mPostProcess = gSavedSettings.getS32("RenderGlowResolutionPow");
+ // slider text boxes
+ updateSliderText(getChild<LLSliderCtrl>("ObjectMeshDetail", true), getChild<LLTextBox>("ObjectMeshDetailText", true));
+ updateSliderText(getChild<LLSliderCtrl>("FlexibleMeshDetail", true), getChild<LLTextBox>("FlexibleMeshDetailText", true));
+ updateSliderText(getChild<LLSliderCtrl>("TreeMeshDetail", true), getChild<LLTextBox>("TreeMeshDetailText", true));
+ updateSliderText(getChild<LLSliderCtrl>("AvatarMeshDetail", true), getChild<LLTextBox>("AvatarMeshDetailText", true));
+ updateSliderText(getChild<LLSliderCtrl>("TerrainMeshDetail", true), getChild<LLTextBox>("TerrainMeshDetailText", true));
+ updateSliderText(getChild<LLSliderCtrl>("RenderPostProcess", true), getChild<LLTextBox>("PostProcessText", true));
+ updateSliderText(getChild<LLSliderCtrl>("SkyMeshDetail", true), getChild<LLTextBox>("SkyMeshDetailText", true));
+
+ refreshEnabledState();
+}
-void LLFloaterPreference::cancel()
+void LLFloaterPreference::onCommitWindowedMode()
{
- this->mPreferenceCore->cancel();
+ refresh();
}
+void LLFloaterPreference::onChangeQuality(const LLSD& data)
+{
+ U32 level = (U32)(data.asReal());
+ LLFeatureManager::getInstance()->setGraphicsLevel(level, true);
+ refreshEnabledGraphics();
+ refresh();
+}
// static
-void LLFloaterPreference::show(void*)
+// DEV-24146 - needs to be removed at a later date. jan-2009
+void LLFloaterPreference::cleanupBadSetting()
{
- if (!sInstance)
+ if (gSavedPerAccountSettings.getString("BusyModeResponse2") == "|TOKEN COPY BusyModeResponse|")
{
- new LLFloaterPreference();
- sInstance->center();
+ llwarns << "cleaning old BusyModeResponse" << llendl;
+ gSavedPerAccountSettings.setString("BusyModeResponse2", gSavedPerAccountSettings.getText("BusyModeResponse"));
}
+}
- sInstance->open(); /* Flawfinder: ignore */
-
- if(!gAgent.getID().isNull())
+void LLFloaterPreference::onClickSetKey()
+{
+ LLVoiceSetKeyDialog* dialog = LLFloaterReg::showTypedInstance<LLVoiceSetKeyDialog>("voice_set_key", LLSD(), TRUE);
+ if (dialog)
{
- // we're logged in, so we can get this info.
- gMessageSystem->newMessageFast(_PREHASH_UserInfoRequest);
- gMessageSystem->nextBlockFast(_PREHASH_AgentData);
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- gAgent.sendReliableMessage();
+ dialog->setParent(this);
}
+}
- LLPanelLogin::setAlwaysRefresh(true);
+void LLFloaterPreference::setKey(KEY key)
+{
+ childSetValue("modifier_combo", LLKeyboard::stringFromKey(key));
+ // update the control right away since we no longer wait for apply
+ getChild<LLUICtrl>("modifier_combo")->onCommit();
}
+void LLFloaterPreference::onClickSetMiddleMouse()
+{
+ childSetValue("modifier_combo", "MiddleMouse");
+ // update the control right away since we no longer wait for apply
+ getChild<LLUICtrl>("modifier_combo")->onCommit();
+}
+/*
+void LLFloaterPreference::onClickSkipDialogs()
+{
+ LLNotificationsUtil::add("SkipShowNextTimeDialogs", LLSD(), LLSD(), boost::bind(&callback_skip_dialogs, _1, _2, this));
+}
-// static
-void LLFloaterPreference::onClickAbout(void*)
+void LLFloaterPreference::onClickResetDialogs()
{
- LLFloaterAbout::show(NULL);
+ LLNotificationsUtil::add("ResetShowNextTimeDialogs", LLSD(), LLSD(), boost::bind(&callback_reset_dialogs, _1, _2, this));
}
+ */
+void LLFloaterPreference::onClickEnablePopup()
+{
+ LLScrollListCtrl& disabled_popups = getChildRef<LLScrollListCtrl>("disabled_popups");
+
+ std::vector<LLScrollListItem*> items = disabled_popups.getAllSelected();
+ std::vector<LLScrollListItem*>::iterator itor;
+ for (itor = items.begin(); itor != items.end(); ++itor)
+ {
+ LLNotificationTemplatePtr templatep = LLNotifications::instance().getTemplate(*(std::string*)((*itor)->getUserdata()));
+ //gSavedSettings.setWarning(templatep->mName, TRUE);
+ std::string notification_name = templatep->mName;
+ LLUI::sSettingGroups["ignores"]->setBOOL(notification_name, TRUE);
+ }
+
+ buildPopupLists();
+}
-// static
-void LLFloaterPreference::onBtnOK( void* userdata )
+void LLFloaterPreference::onClickDisablePopup()
+{
+ LLScrollListCtrl& enabled_popups = getChildRef<LLScrollListCtrl>("enabled_popups");
+
+ std::vector<LLScrollListItem*> items = enabled_popups.getAllSelected();
+ std::vector<LLScrollListItem*>::iterator itor;
+ for (itor = items.begin(); itor != items.end(); ++itor)
+ {
+ LLNotificationTemplatePtr templatep = LLNotifications::instance().getTemplate(*(std::string*)((*itor)->getUserdata()));
+ //gSavedSettings.setWarning(templatep->mName, TRUE);
+ std::string notification_name = templatep->mName;
+ LLUI::sSettingGroups["ignores"]->setBOOL(notification_name, FALSE);
+ }
+
+ buildPopupLists();
+}
+
+void LLFloaterPreference::resetAllIgnored()
{
- LLFloaterPreference *fp =(LLFloaterPreference *)userdata;
- // commit any outstanding text entry
- if (fp->hasFocus())
+ for (LLNotifications::TemplateMap::const_iterator iter = LLNotifications::instance().templatesBegin();
+ iter != LLNotifications::instance().templatesEnd();
+ ++iter)
{
- LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus();
- if (cur_focus->acceptsTextInput())
+ if (iter->second->mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO)
{
- cur_focus->onCommit();
+ LLUI::sSettingGroups["ignores"]->setBOOL(iter->first, TRUE);
}
}
+}
- if (fp->canClose())
+void LLFloaterPreference::setAllIgnored()
+{
+ for (LLNotifications::TemplateMap::const_iterator iter = LLNotifications::instance().templatesBegin();
+ iter != LLNotifications::instance().templatesEnd();
+ ++iter)
{
- fp->apply();
- fp->close(false);
+ if (iter->second->mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO)
+ {
+ LLUI::sSettingGroups["ignores"]->setBOOL(iter->first, FALSE);
+ }
+ }
+}
- gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
-
- std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE);
- // save all settings, even if equals defaults
- gCrashSettings.saveToFile(crash_settings_filename, FALSE);
+void LLFloaterPreference::onClickLogPath()
+{
+ std::string proposed_name(gSavedPerAccountSettings.getString("InstantMessageLogPath"));
+
+ LLDirPicker& picker = LLDirPicker::instance();
+ if (!picker.getDir(&proposed_name ) )
+ {
+ return; //Canceled!
+ }
+ std::string chat_log_dir = picker.getDirName();
+ std::string chat_log_top_folder= gDirUtilp->getBaseFileName(chat_log_dir);
+ gSavedPerAccountSettings.setString("InstantMessageLogPath",chat_log_dir);
+ gSavedPerAccountSettings.setString("InstantMessageLogFolder",chat_log_top_folder);
+}
+
+void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email)
+{
+ mGotPersonalInfo = true;
+ mOriginalIMViaEmail = im_via_email;
+ mDirectoryVisibility = visibility;
+
+ if(visibility == VISIBILITY_DEFAULT)
+ {
+ mOriginalHideOnlineStatus = false;
+ childEnable("online_visibility");
+ }
+ else if(visibility == VISIBILITY_HIDDEN)
+ {
+ mOriginalHideOnlineStatus = true;
+ childEnable("online_visibility");
}
else
{
- // Show beep, pop up dialog, etc.
- llinfos << "Can't close preferences!" << llendl;
+ mOriginalHideOnlineStatus = true;
}
+
+ childEnable("include_im_in_chat_history");
+ childEnable("show_timestamps_check_im");
+ childEnable("friends_online_notify_checkbox");
+
+ childSetValue("online_visibility", mOriginalHideOnlineStatus);
+ childSetLabelArg("online_visibility", "[DIR_VIS]", mDirectoryVisibility);
+ childEnable("send_im_to_email");
+ childSetValue("send_im_to_email", im_via_email);
+ childEnable("plain_text_chat_history");
+ childSetValue("plain_text_chat_history", gSavedSettings.getBOOL("PlainTextChatHistory"));
+ childEnable("log_instant_messages");
+// childEnable("log_chat");
+// childEnable("busy_response");
+// childEnable("log_instant_messages_timestamp");
+// childEnable("log_chat_timestamp");
+ childEnable("log_chat_IM");
+ childEnable("log_date_timestamp");
+
+// childSetText("busy_response", gSavedSettings.getString("BusyModeResponse2"));
+
+ childEnable("log_nearby_chat");
+ childEnable("log_instant_messages");
+ childEnable("show_timestamps_check_im");
+ childEnable("log_path_string");
+ childEnable("log_path_button");
+
+ std::string display_email(email);
+ childSetText("email_address",display_email);
- LLPanelLogin::refreshLocation( false );
}
+void LLFloaterPreference::onUpdateSliderText(LLUICtrl* ctrl, const LLSD& name)
+{
+ std::string ctrl_name = name.asString();
+
+ if((ctrl_name =="" )|| !hasChild(ctrl_name, true))
+ return;
+
+ LLTextBox* text_box = getChild<LLTextBox>(name.asString());
+ LLSliderCtrl* slider = dynamic_cast<LLSliderCtrl*>(ctrl);
+ updateSliderText(slider, text_box);
+}
-// static
-void LLFloaterPreference::onBtnApply( void* userdata )
+void LLFloaterPreference::updateSliderText(LLSliderCtrl* ctrl, LLTextBox* text_box)
{
- LLFloaterPreference *fp =(LLFloaterPreference *)userdata;
- if (fp->hasFocus())
+ if(text_box == NULL || ctrl== NULL)
+ return;
+
+ // get range and points when text should change
+ F32 value = (F32)ctrl->getValue().asReal();
+ F32 min = ctrl->getMinValue();
+ F32 max = ctrl->getMaxValue();
+ F32 range = max - min;
+ llassert(range > 0);
+ F32 midPoint = min + range / 3.0f;
+ F32 highPoint = min + (2.0f * range / 3.0f);
+
+ // choose the right text
+ if(value < midPoint)
{
- LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus();
- if (cur_focus->acceptsTextInput())
+ text_box->setText(LLTrans::getString("GraphicsQualityLow"));
+ }
+ else if (value < highPoint)
+ {
+ text_box->setText(LLTrans::getString("GraphicsQualityMid"));
+ }
+ else
+ {
+ text_box->setText(LLTrans::getString("GraphicsQualityHigh"));
+ }
+}
+
+void LLFloaterPreference::onKeystrokeAspectRatio()
+{
+ getChild<LLCheckBoxCtrl>("aspect_auto_detect")->set(FALSE);
+}
+
+void LLFloaterPreference::applyResolution()
+{
+ LLComboBox* ctrl_aspect_ratio = getChild<LLComboBox>( "aspect_ratio");
+ gGL.flush();
+ char aspect_ratio_text[ASPECT_RATIO_STR_LEN]; /*Flawfinder: ignore*/
+ if (ctrl_aspect_ratio->getCurrentIndex() == -1)
+ {
+ // *Can't pass const char* from c_str() into strtok
+ strncpy(aspect_ratio_text, ctrl_aspect_ratio->getSimple().c_str(), sizeof(aspect_ratio_text) -1); /*Flawfinder: ignore*/
+ aspect_ratio_text[sizeof(aspect_ratio_text) -1] = '\0';
+ char *element = strtok(aspect_ratio_text, ":/\\");
+ if (!element)
{
- cur_focus->onCommit();
+ sAspectRatio = 0.f; // will be clamped later
+ }
+ else
+ {
+ LLLocale locale(LLLocale::USER_LOCALE);
+ sAspectRatio = (F32)atof(element);
+ }
+
+ // look for denominator
+ element = strtok(NULL, ":/\\");
+ if (element)
+ {
+ LLLocale locale(LLLocale::USER_LOCALE);
+
+ F32 denominator = (F32)atof(element);
+ if (denominator != 0.f)
+ {
+ sAspectRatio /= denominator;
+ }
}
}
- fp->apply();
-
- LLPanelLogin::refreshLocation( false );
+ else
+ {
+ sAspectRatio = (F32)ctrl_aspect_ratio->getValue().asReal();
+ }
+
+ // presumably, user entered a non-numeric value if aspect_ratio == 0.f
+ if (sAspectRatio != 0.f)
+ {
+ sAspectRatio = llclamp(sAspectRatio, 0.2f, 5.f);
+ gSavedSettings.setF32("FullScreenAspectRatio", sAspectRatio);
+ }
+
+ // Screen resolution
+ S32 num_resolutions;
+ LLWindow::LLWindowResolution* supported_resolutions =
+ gViewerWindow->getWindow()->getSupportedResolutions(num_resolutions);
+ S32 resIndex = getChild<LLComboBox>("fullscreen combo")->getCurrentIndex();
+ if (resIndex == -1)
+ {
+ // use highest resolution if nothing selected
+ resIndex = num_resolutions - 1;
+ }
+ gSavedSettings.setS32("FullScreenWidth", supported_resolutions[resIndex].mWidth);
+ gSavedSettings.setS32("FullScreenHeight", supported_resolutions[resIndex].mHeight);
+
+ gViewerWindow->requestResolutionUpdate(gSavedSettings.getBOOL("WindowFullScreen"));
+
+ send_agent_update(TRUE);
+
+ // Update enable/disable
+ refresh();
}
-void LLFloaterPreference::onClose(bool app_quitting)
+
+
+void LLFloaterPreference::applyUIColor(LLUICtrl* ctrl, const LLSD& param)
{
- LLPanelLogin::setAlwaysRefresh(false);
- cancel(); // will be a no-op if OK or apply was performed just prior.
- LLFloater::onClose(app_quitting);
+ LLUIColorTable::instance().setColor(param.asString(), LLColor4(ctrl->getValue()));
}
+void LLFloaterPreference::getUIColor(LLUICtrl* ctrl, const LLSD& param)
+{
+ LLColorSwatchCtrl* color_swatch = (LLColorSwatchCtrl*) ctrl;
+ color_swatch->setOriginal(LLUIColorTable::instance().getColor(param.asString()));
+}
-// static
-void LLFloaterPreference::onBtnCancel( void* userdata )
+
+//----------------------------------------------------------------------------
+static LLRegisterPanelClassWrapper<LLPanelPreference> t_places("panel_preference");
+LLPanelPreference::LLPanelPreference()
+: LLPanel()
+{
+ mCommitCallbackRegistrar.add("Pref.setControlFalse", boost::bind(&LLPanelPreference::setControlFalse,this, _2));
+}
+
+//virtual
+BOOL LLPanelPreference::postBuild()
{
- LLFloaterPreference *fp =(LLFloaterPreference *)userdata;
- if (fp->hasFocus())
+
+ ////////////////////// PanelVoice ///////////////////
+ if(hasChild("voice_unavailable"))
{
- LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus();
- if (cur_focus->acceptsTextInput())
+ BOOL voice_disabled = gSavedSettings.getBOOL("CmdLineDisableVoice");
+ childSetVisible("voice_unavailable", voice_disabled);
+ childSetVisible("enable_voice_check", !voice_disabled);
+ }
+
+ //////////////////////PanelSkins ///////////////////
+
+ if (hasChild("skin_selection"))
+ {
+ LLFloaterPreference::refreshSkin(this);
+
+ // if skin is set to a skin that no longer exists (silver) set back to default
+ if (getChild<LLRadioGroup>("skin_selection")->getSelectedIndex() < 0)
{
- cur_focus->onCommit();
+ gSavedSettings.setString("SkinCurrent", "default");
+ LLFloaterPreference::refreshSkin(this);
}
+
+ }
+
+ if(hasChild("online_visibility") && hasChild("send_im_to_email"))
+ {
+ childSetText("email_address",getString("log_in_to_change") );
+// childSetText("busy_response", getString("log_in_to_change"));
}
- fp->close(); // side effect will also cancel any unsaved changes.
+
+
+ if(hasChild("aspect_ratio"))
+ {
+ // We used to set up fullscreen resolution and window size
+ // controls here, see LLFloaterWindowSize::initWindowSizeControls()
+
+ if (gSavedSettings.getBOOL("FullScreenAutoDetectAspectRatio"))
+ {
+ LLFloaterPreference::sAspectRatio = gViewerWindow->getDisplayAspectRatio();
+ }
+ else
+ {
+ LLFloaterPreference::sAspectRatio = gSavedSettings.getF32("FullScreenAspectRatio");
+ }
+
+ getChild<LLComboBox>("aspect_ratio")->setTextEntryCallback(boost::bind(&LLPanelPreference::setControlFalse, this, LLSD("FullScreenAutoDetectAspectRatio") ));
+
+
+ S32 numerator = 0;
+ S32 denominator = 0;
+ fractionFromDecimal(LLFloaterPreference::sAspectRatio, numerator, denominator);
+
+ LLUIString aspect_ratio_text = getString("aspect_ratio_text");
+ if (numerator != 0)
+ {
+ aspect_ratio_text.setArg("[NUM]", llformat("%d", numerator));
+ aspect_ratio_text.setArg("[DEN]", llformat("%d", denominator));
+ }
+ else
+ {
+ aspect_ratio_text = llformat("%.3f", LLFloaterPreference::sAspectRatio);
+ }
+
+ LLComboBox* ctrl_aspect_ratio = getChild<LLComboBox>( "aspect_ratio");
+ //mCtrlAspectRatio->setCommitCallback(onSelectAspectRatio, this);
+ // add default aspect ratios
+ ctrl_aspect_ratio->add(aspect_ratio_text, &LLFloaterPreference::sAspectRatio, ADD_TOP);
+ ctrl_aspect_ratio->setCurrentByIndex(0);
+
+ refresh();
+ }
+
+ //////////////////////PanelPrivacy ///////////////////
+ if (hasChild("media_enabled"))
+ {
+ bool media_enabled = gSavedSettings.getBOOL("AudioStreamingMedia");
+ getChild<LLCheckBoxCtrl>("voice_call_friends_only_check")->setCommitCallback(boost::bind(&showFriendsOnlyWarning, _1, _2));
+ getChild<LLCheckBoxCtrl>("media_enabled")->set(media_enabled);
+ getChild<LLCheckBoxCtrl>("autoplay_enabled")->setEnabled(media_enabled);
+ }
+ if (hasChild("music_enabled"))
+ {
+ getChild<LLCheckBoxCtrl>("music_enabled")->set(gSavedSettings.getBOOL("AudioStreamingMusic"));
+ }
+
+ apply();
+ return true;
}
+void LLPanelPreference::apply()
+{
+ // no-op
+}
-// static
-void LLFloaterPreference::updateUserInfo(const std::string& visibility, bool im_via_email, const std::string& email)
+void LLPanelPreference::saveSettings()
+{
+ // Save the value of all controls in the hierarchy
+ mSavedValues.clear();
+ std::list<LLView*> view_stack;
+ view_stack.push_back(this);
+ while(!view_stack.empty())
+ {
+ // Process view on top of the stack
+ LLView* curview = view_stack.front();
+ view_stack.pop_front();
+
+ LLColorSwatchCtrl* color_swatch = dynamic_cast<LLColorSwatchCtrl *>(curview);
+ if (color_swatch)
+ {
+ mSavedColors[color_swatch->getName()] = color_swatch->get();
+ }
+ else
+ {
+ LLUICtrl* ctrl = dynamic_cast<LLUICtrl*>(curview);
+ if (ctrl)
+ {
+ LLControlVariable* control = ctrl->getControlVariable();
+ if (control)
+ {
+ mSavedValues[control] = control->getValue();
+ }
+ }
+ }
+
+ // Push children onto the end of the work stack
+ for (child_list_t::const_iterator iter = curview->getChildList()->begin();
+ iter != curview->getChildList()->end(); ++iter)
+ {
+ view_stack.push_back(*iter);
+ }
+ }
+}
+
+void LLPanelPreference::showFriendsOnlyWarning(LLUICtrl* checkbox, const LLSD& value)
{
- if(sInstance && sInstance->mPreferenceCore)
+ if (checkbox && checkbox->getValue())
{
- sInstance->mPreferenceCore->setPersonalInfo(visibility, im_via_email, email);
+ LLNotificationsUtil::add("FriendsAndGroupsOnly");
}
}
-void LLFloaterPreference::refreshEnabledGraphics()
+void LLPanelPreference::cancel()
{
- sInstance->mPreferenceCore->refreshEnabledGraphics();
+ for (control_values_map_t::iterator iter = mSavedValues.begin();
+ iter != mSavedValues.end(); ++iter)
+ {
+ LLControlVariable* control = iter->first;
+ LLSD ctrl_value = iter->second;
+ control->set(ctrl_value);
+ }
+
+ for (string_color_map_t::iterator iter = mSavedColors.begin();
+ iter != mSavedColors.end(); ++iter)
+ {
+ LLColorSwatchCtrl* color_swatch = findChild<LLColorSwatchCtrl>(iter->first);
+ if(color_swatch)
+ {
+ color_swatch->set(iter->second);
+ color_swatch->onCommit();
+ }
+ }
+}
+
+void LLPanelPreference::setControlFalse(const LLSD& user_data)
+{
+ std::string control_name = user_data.asString();
+ LLControlVariable* control = findControl(control_name);
+
+ if (control)
+ control->set(LLSD(FALSE));
}
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index f48696ffdb..8778d76a5a 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -40,94 +40,141 @@
#define LL_LLFLOATERPREFERENCE_H
#include "llfloater.h"
-#include "lltabcontainervertical.h"
-class LLPanelGeneral;
-class LLPanelInput;
+class LLPanelPreference;
class LLPanelLCD;
-class LLPanelDisplay;
-class LLPanelAudioPrefs;
class LLPanelDebug;
-class LLPanelNetwork;
-class LLPanelWeb;
class LLMessageSystem;
-class LLPrefsChat;
-class LLPrefsVoice;
-class LLPrefsIM;
-class LLPanelMsgs;
-class LLPanelSkins;
class LLScrollListCtrl;
+class LLSliderCtrl;
+class LLSD;
+class LLTextBox;
-class LLPreferenceCore
-{
-
-public:
- LLPreferenceCore(LLTabContainer* tab_container, LLButton * default_btn);
- ~LLPreferenceCore();
-
- void apply();
- void cancel();
-
- LLTabContainer* getTabContainer() { return mTabContainer; }
+typedef enum
+ {
+ GS_LOW_GRAPHICS,
+ GS_MID_GRAPHICS,
+ GS_HIGH_GRAPHICS,
+ GS_ULTRA_GRAPHICS
+
+ } EGraphicsSettings;
- void setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email);
-
- static void onTabChanged(void* user_data, bool from_click);
-
- // refresh all the graphics preferences menus
- void refreshEnabledGraphics();
-
-private:
- LLTabContainer *mTabContainer;
- LLPanelGeneral *mGeneralPanel;
- LLPanelSkins *mSkinsPanel;
- LLPanelInput *mInputPanel;
- LLPanelNetwork *mNetworkPanel;
- LLPanelDisplay *mDisplayPanel;
- LLPanelAudioPrefs *mAudioPanel;
-// LLPanelDebug *mDebugPanel;
- LLPrefsChat *mPrefsChat;
- LLPrefsVoice *mPrefsVoice;
- LLPrefsIM *mPrefsIM;
- LLPanelWeb *mWebPanel;
- LLPanelMsgs *mMsgPanel;
- LLPanelLCD *mLCDPanel;
-};
// Floater to control preferences (display, audio, bandwidth, general.
class LLFloaterPreference : public LLFloater
{
public:
- LLFloaterPreference();
+ LLFloaterPreference(const LLSD& key);
~LLFloaterPreference();
void apply();
void cancel();
- virtual BOOL postBuild();
- static void show(void*);
+ /*virtual*/ void draw();
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ void onClose(bool app_quitting);
// static data update, called from message handler
static void updateUserInfo(const std::string& visibility, bool im_via_email, const std::string& email);
// refresh all the graphics preferences menus
static void refreshEnabledGraphics();
+
+protected:
+ void onBtnOK();
+ void onBtnCancel();
+ void onBtnApply();
+
+ void onClickBrowserClearCache();
+
+ // if the custom settings box is clicked
+ void onChangeCustom();
+ void updateMeterText(LLUICtrl* ctrl);
+ void onOpenHardwareSettings();
+ /// callback for defaults
+ void setHardwareDefaults();
+ // callback for when client turns on shaders
+ void onVertexShaderEnable();
+
+ // This function squirrels away the current values of the controls so that
+ // cancel() can restore them.
+ void saveSettings();
+
-protected:
- LLPreferenceCore *mPreferenceCore;
+public:
- /*virtual*/ void onClose(bool app_quitting);
+ void onClickSetCache();
+ void onClickResetCache();
+ void onClickSkin(LLUICtrl* ctrl,const LLSD& userdata);
+ void onSelectSkin();
+ void onClickSetKey();
+ void setKey(KEY key);
+ void onClickSetMiddleMouse();
+// void onClickSkipDialogs();
+// void onClickResetDialogs();
+ void onClickEnablePopup();
+ void onClickDisablePopup();
+ void resetAllIgnored();
+ void setAllIgnored();
+ void onClickLogPath();
+ void enableHistory();
+ void setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email);
+ void refreshEnabledState();
+ void disableUnavailableSettings();
+ void onCommitWindowedMode();
+ void refresh(); // Refresh enable/disable
+ // if the quality radio buttons are changed
+ void onChangeQuality(const LLSD& data);
+
+ void updateSliderText(LLSliderCtrl* ctrl, LLTextBox* text_box);
+ void onUpdateSliderText(LLUICtrl* ctrl, const LLSD& name);
+ void onKeystrokeAspectRatio();
+// void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator);
+
+ void onCommitAutoDetectAspect();
+ void onCommitParcelMediaAutoPlayEnable();
+ void onCommitMediaEnabled();
+ void onCommitMusicEnabled();
+ void applyResolution();
+ void applyUIColor(LLUICtrl* ctrl, const LLSD& param);
+ void getUIColor(LLUICtrl* ctrl, const LLSD& param);
+
+ void buildPopupLists();
+ static void refreshSkin(void* data);
+ static void cleanupBadSetting();
+ static F32 sAspectRatio;
+private:
+ static std::string sSkin;
+ bool mGotPersonalInfo;
+ bool mOriginalIMViaEmail;
+
+ bool mOriginalHideOnlineStatus;
+ std::string mDirectoryVisibility;
+};
- LLButton* mAboutBtn;
- LLButton *mOKBtn;
- LLButton *mCancelBtn;
- LLButton *mApplyBtn;
+class LLPanelPreference : public LLPanel
+{
+public:
+ LLPanelPreference();
+ /*virtual*/ BOOL postBuild();
+
+ virtual void apply();
+ virtual void cancel();
+ void setControlFalse(const LLSD& user_data);
+
+ // This function squirrels away the current values of the controls so that
+ // cancel() can restore them.
+ virtual void saveSettings();
+
+private:
+ //for "Only friends and groups can call or IM me"
+ static void showFriendsOnlyWarning(LLUICtrl*, const LLSD&);
- static void onClickAbout(void*);
- static void onBtnOK(void*);
- static void onBtnCancel(void*);
- static void onBtnApply(void*);
+ typedef std::map<LLControlVariable*, LLSD> control_values_map_t;
+ control_values_map_t mSavedValues;
- static LLFloaterPreference* sInstance;
+ typedef std::map<std::string, LLColor4> string_color_map_t;
+ string_color_map_t mSavedColors;
};
#endif // LL_LLPREFERENCEFLOATER_H
diff --git a/indra/newview/llfloaterproperties.cpp b/indra/newview/llfloaterproperties.cpp
index 406d940cf0..ff9002787c 100644
--- a/indra/newview/llfloaterproperties.cpp
+++ b/indra/newview/llfloaterproperties.cpp
@@ -37,25 +37,30 @@
#include <functional>
#include "llcachename.h"
#include "lldbstrings.h"
+#include "llfloaterreg.h"
#include "llinventory.h"
#include "llagent.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
-#include "llfloateravatarinfo.h"
-#include "llfloatergroupinfo.h"
+#include "llavataractions.h"
+#include "llinventoryobserver.h"
#include "llinventorymodel.h"
#include "lllineeditor.h"
+//#include "llspinctrl.h"
#include "llradiogroup.h"
#include "llresmgr.h"
#include "roles_constants.h"
#include "llselectmgr.h"
#include "lltextbox.h"
+#include "lltrans.h"
#include "lluiconstants.h"
#include "llviewerinventory.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "llviewercontrol.h"
+#include "llviewerwindow.h"
+#include "llgroupactions.h"
#include "lluictrlfactory.h"
@@ -73,7 +78,8 @@
class LLPropertiesObserver : public LLInventoryObserver
{
public:
- LLPropertiesObserver()
+ LLPropertiesObserver(LLFloaterProperties* floater)
+ : mFloater(floater)
{
gInventory.addObserver(this);
}
@@ -82,6 +88,8 @@ public:
gInventory.removeObserver(this);
}
virtual void changed(U32 mask);
+private:
+ LLFloaterProperties* mFloater;
};
void LLPropertiesObserver::changed(U32 mask)
@@ -89,7 +97,7 @@ void LLPropertiesObserver::changed(U32 mask)
// if there's a change we're interested in.
if((mask & (LLInventoryObserver::LABEL | LLInventoryObserver::INTERNAL | LLInventoryObserver::REMOVE)) != 0)
{
- LLFloaterProperties::dirtyAll();
+ mFloater->dirty();
}
}
@@ -99,120 +107,63 @@ void LLPropertiesObserver::changed(U32 mask)
/// Class LLFloaterProperties
///----------------------------------------------------------------------------
-// static
-LLFloaterProperties::instance_map LLFloaterProperties::sInstances;
-LLPropertiesObserver* LLFloaterProperties::sPropertiesObserver = NULL;
-S32 LLFloaterProperties::sPropertiesObserverCount = 0;
-
-// static
-LLFloaterProperties* LLFloaterProperties::find(const LLUUID& item_id,
- const LLUUID& object_id)
-{
- // for simplicity's sake, we key the properties window with a
- // single uuid. However, the items are keyed by item and object
- // (obj == null -> agent inventory). So, we xor the two ids, and
- // use that as a lookup key
- instance_map::iterator it = sInstances.find(item_id ^ object_id);
- if(it != sInstances.end())
- {
- return (*it).second;
- }
- return NULL;
-}
-
-// static
-LLFloaterProperties* LLFloaterProperties::show(const LLUUID& item_id,
- const LLUUID& object_id)
+// Default constructor
+LLFloaterProperties::LLFloaterProperties(const LLUUID& item_id)
+ : LLFloater(mItemID),
+ mItemID(item_id),
+ mDirty(TRUE)
{
- LLFloaterProperties* instance = find(item_id, object_id);
- if(instance)
- {
- if (LLFloater::getFloaterHost() && LLFloater::getFloaterHost() != instance->getHost())
- {
- // this properties window is being opened in a new context
- // needs to be rehosted
- LLFloater::getFloaterHost()->addFloater(instance, TRUE);
- }
-
- instance->refresh();
- instance->open(); /* Flawfinder: ignore */
- }
- return instance;
+ mPropertiesObserver = new LLPropertiesObserver(this);
+
+ //LLUICtrlFactory::getInstance()->buildFloater(this,"floater_inventory_item_properties.xml");
}
-void LLFloaterProperties::dirtyAll()
+// Destroys the object
+LLFloaterProperties::~LLFloaterProperties()
{
- // ...this is more clear. Possibly more correct, because the
- // refresh method may delete the object.
- for(instance_map::iterator it = sInstances.begin(); it!=sInstances.end(); )
- {
- (*it++).second->dirty();
- }
+ delete mPropertiesObserver;
+ mPropertiesObserver = NULL;
}
-// Default constructor
-LLFloaterProperties::LLFloaterProperties(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& item_id, const LLUUID& object_id) :
- LLFloater(name, rect, title),
- mItemID(item_id),
- mObjectID(object_id),
- mDirty(TRUE)
+// virtual
+BOOL LLFloaterProperties::postBuild()
{
- LLUICtrlFactory::getInstance()->buildFloater(this,"floater_inventory_item_properties.xml");
-
- if (!sPropertiesObserver)
- {
- sPropertiesObserver = new LLPropertiesObserver;
- }
- sPropertiesObserverCount++;
-
- // add the object to the static structure
- LLUUID key = mItemID ^ mObjectID;
- sInstances.insert(instance_map::value_type(key, this));
// build the UI
// item name & description
- childSetPrevalidate("LabelItemName",&LLLineEditor::prevalidatePrintableNotPipe);
- childSetCommitCallback("LabelItemName",onCommitName,this);
- childSetPrevalidate("LabelItemDesc",&LLLineEditor::prevalidatePrintableNotPipe);
- childSetCommitCallback("LabelItemDesc", onCommitDescription, this);
+ childSetPrevalidate("LabelItemName",&LLLineEditor::prevalidateASCIIPrintableNoPipe);
+ getChild<LLUICtrl>("LabelItemName")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitName,this));
+ childSetPrevalidate("LabelItemDesc",&LLLineEditor::prevalidateASCIIPrintableNoPipe);
+ getChild<LLUICtrl>("LabelItemDesc")->setCommitCallback(boost::bind(&LLFloaterProperties:: onCommitDescription, this));
// Creator information
- childSetAction("BtnCreator",onClickCreator,this);
+ getChild<LLUICtrl>("BtnCreator")->setCommitCallback(boost::bind(&LLFloaterProperties::onClickCreator,this));
// owner information
- childSetAction("BtnOwner",onClickOwner,this);
+ getChild<LLUICtrl>("BtnOwner")->setCommitCallback(boost::bind(&LLFloaterProperties::onClickOwner,this));
// acquired date
// owner permissions
// Permissions debug text
// group permissions
- childSetCommitCallback("CheckShareWithGroup",&onCommitPermissions, this);
+ getChild<LLUICtrl>("CheckShareWithGroup")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitPermissions, this));
// everyone permissions
- childSetCommitCallback("CheckEveryoneCopy",&onCommitPermissions, this);
+ getChild<LLUICtrl>("CheckEveryoneCopy")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitPermissions, this));
// next owner permissions
- childSetCommitCallback("CheckNextOwnerModify",&onCommitPermissions, this);
- childSetCommitCallback("CheckNextOwnerCopy",&onCommitPermissions, this);
- childSetCommitCallback("CheckNextOwnerTransfer",&onCommitPermissions, this);
+ getChild<LLUICtrl>("CheckNextOwnerModify")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitPermissions, this));
+ getChild<LLUICtrl>("CheckNextOwnerCopy")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitPermissions, this));
+ getChild<LLUICtrl>("CheckNextOwnerTransfer")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitPermissions, this));
// Mark for sale or not, and sale info
- childSetCommitCallback("CheckPurchase",&onCommitSaleInfo, this);
- childSetCommitCallback("RadioSaleType",&onCommitSaleType, this);
+ getChild<LLUICtrl>("CheckPurchase")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitSaleInfo, this));
+ getChild<LLUICtrl>("RadioSaleType")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitSaleType, this));
// "Price" label for edit
- childSetCommitCallback("EditPrice",&onCommitSaleInfo, this);
+ getChild<LLUICtrl>("Edit Cost")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitSaleInfo, this));
// The UI has been built, now fill in all the values
refresh();
+
+ return TRUE;
}
-// Destroys the object
-LLFloaterProperties::~LLFloaterProperties()
+// virtual
+void LLFloaterProperties::onOpen(const LLSD& key)
{
- // clean up the static data.
- instance_map::iterator it = sInstances.find(mItemID ^ mObjectID);
- if(it != sInstances.end())
- {
- sInstances.erase(it);
- }
- sPropertiesObserverCount--;
- if (!sPropertiesObserverCount)
- {
- delete sPropertiesObserver;
- sPropertiesObserver = NULL;
- }
+ refresh();
}
void LLFloaterProperties::refresh()
@@ -246,7 +197,7 @@ void LLFloaterProperties::refresh()
"CheckNextOwnerTransfer",
"CheckPurchase",
"RadioSaleType",
- "EditPrice"
+ "Edit Cost"
};
for(size_t t=0; t<LL_ARRAY_SIZE(enableNames); ++t)
{
@@ -287,12 +238,15 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item)
// do not enable the UI for incomplete items.
LLViewerInventoryItem* i = (LLViewerInventoryItem*)item;
BOOL is_complete = i->isComplete();
-
+ const BOOL cannot_restrict_permissions = LLInventoryType::cannotRestrictPermissions(i->getInventoryType());
+ const BOOL is_calling_card = (i->getInventoryType() == LLInventoryType::IT_CALLINGCARD);
const LLPermissions& perm = item->getPermissions();
- BOOL can_agent_manipulate = gAgent.allowOperation(PERM_OWNER, perm,
- GP_OBJECT_MANIPULATE);
- BOOL can_agent_sell = gAgent.allowOperation(PERM_OWNER, perm,
- GP_OBJECT_SET_SALE);
+ const BOOL can_agent_manipulate = gAgent.allowOperation(PERM_OWNER, perm,
+ GP_OBJECT_MANIPULATE);
+ const BOOL can_agent_sell = gAgent.allowOperation(PERM_OWNER, perm,
+ GP_OBJECT_SET_SALE) &&
+ !cannot_restrict_permissions;
+ const BOOL is_link = i->getIsLinkType();
// You need permission to modify the object to modify an inventory
// item in it.
@@ -308,11 +262,11 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item)
// ITEM NAME & DESC //
//////////////////////
BOOL is_modifiable = gAgent.allowOperation(PERM_MODIFY, perm,
- GP_OBJECT_MANIPULATE)
- && is_obj_modify && is_complete;
+ GP_OBJECT_MANIPULATE)
+ && is_obj_modify && is_complete;
childSetEnabled("LabelItemNameTitle",TRUE);
- childSetEnabled("LabelItemName",is_modifiable);
+ childSetEnabled("LabelItemName",is_modifiable && !is_calling_card); // for now, don't allow rename of calling cards
childSetText("LabelItemName",item->getName());
childSetEnabled("LabelItemDescTitle",TRUE);
childSetEnabled("LabelItemDesc",is_modifiable);
@@ -372,8 +326,7 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item)
//////////////////
// ACQUIRE DATE //
//////////////////
-
- // *TODO: Localize / translate this
+
time_t time_utc = item->getCreationDate();
if (0 == time_utc)
{
@@ -381,7 +334,11 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item)
}
else
{
- childSetText("LabelAcquiredDate", std::string(ctime(&time_utc)) );
+ std::string timeStr = getString("acquiredDate");
+ LLSD substitution;
+ substitution["datetime"] = (S32) time_utc;
+ LLStringUtil::format (timeStr, substitution);
+ childSetText ("LabelAcquiredDate", timeStr);
}
///////////////////////
@@ -472,7 +429,12 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item)
/////////////
// Check for ability to change values.
- if (is_obj_modify && can_agent_manipulate)
+ if (is_link || cannot_restrict_permissions)
+ {
+ childSetEnabled("CheckShareWithGroup",FALSE);
+ childSetEnabled("CheckEveryoneCopy",FALSE);
+ }
+ else if (is_obj_modify && can_agent_manipulate)
{
childSetEnabled("CheckShareWithGroup",TRUE);
childSetEnabled("CheckEveryoneCopy",(owner_mask & PERM_COPY) && (owner_mask & PERM_TRANSFER));
@@ -533,13 +495,13 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item)
childSetEnabled("CheckPurchase",is_complete);
childSetEnabled("NextOwnerLabel",TRUE);
- childSetEnabled("CheckNextOwnerModify",base_mask & PERM_MODIFY);
- childSetEnabled("CheckNextOwnerCopy",base_mask & PERM_COPY);
- childSetEnabled("CheckNextOwnerTransfer",next_owner_mask & PERM_COPY);
+ childSetEnabled("CheckNextOwnerModify",(base_mask & PERM_MODIFY) && !cannot_restrict_permissions);
+ childSetEnabled("CheckNextOwnerCopy",(base_mask & PERM_COPY) && !cannot_restrict_permissions);
+ childSetEnabled("CheckNextOwnerTransfer",(next_owner_mask & PERM_COPY) && !cannot_restrict_permissions);
childSetEnabled("RadioSaleType",is_complete && is_for_sale);
childSetEnabled("TextPrice",is_complete && is_for_sale);
- childSetEnabled("EditPrice",is_complete && is_for_sale);
+ childSetEnabled("Edit Cost",is_complete && is_for_sale);
}
else
{
@@ -553,11 +515,13 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item)
childSetEnabled("RadioSaleType",FALSE);
childSetEnabled("TextPrice",FALSE);
- childSetEnabled("EditPrice",FALSE);
+ childSetEnabled("Edit Cost",FALSE);
}
// Set values.
childSetValue("CheckPurchase", is_for_sale);
+ childSetEnabled("combobox sale copy", is_for_sale);
+ childSetEnabled("Edit Cost", is_for_sale);
childSetValue("CheckNextOwnerModify",LLSD(BOOL(next_owner_mask & PERM_MODIFY)));
childSetValue("CheckNextOwnerCopy",LLSD(BOOL(next_owner_mask & PERM_COPY)));
childSetValue("CheckNextOwnerTransfer",LLSD(BOOL(next_owner_mask & PERM_TRANSFER)));
@@ -568,63 +532,50 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item)
radioSaleType->setSelectedIndex((S32)sale_info.getSaleType() - 1);
S32 numerical_price;
numerical_price = sale_info.getSalePrice();
- childSetText("EditPrice",llformat("%d",numerical_price));
+ childSetText("Edit Cost",llformat("%d",numerical_price));
}
else
{
radioSaleType->setSelectedIndex(-1);
- childSetText("EditPrice",llformat("%d",0));
+ childSetText("Edit Cost",llformat("%d",0));
}
}
-// static
-void LLFloaterProperties::onClickCreator(void* data)
+void LLFloaterProperties::onClickCreator()
{
- LLFloaterProperties* self = (LLFloaterProperties*)data;
- if(!self) return;
- LLInventoryItem* item = self->findItem();
+ LLInventoryItem* item = findItem();
if(!item) return;
if(!item->getCreatorUUID().isNull())
{
- LLFloaterAvatarInfo::showFromObject(item->getCreatorUUID());
+ LLAvatarActions::showProfile(item->getCreatorUUID());
}
}
// static
-void LLFloaterProperties::onClickOwner(void* data)
+void LLFloaterProperties::onClickOwner()
{
- LLFloaterProperties* self = (LLFloaterProperties*)data;
- if(!self) return;
- LLInventoryItem* item = self->findItem();
+ LLInventoryItem* item = findItem();
if(!item) return;
if(item->getPermissions().isGroupOwned())
{
- LLFloaterGroupInfo::showFromUUID(item->getPermissions().getGroup());
+ LLGroupActions::show(item->getPermissions().getGroup());
}
else
{
- if(!item->getPermissions().getOwner().isNull())
- {
- LLFloaterAvatarInfo::showFromObject(item->getPermissions().getOwner());
- }
+ LLAvatarActions::showProfile(item->getPermissions().getOwner());
}
}
// static
-void LLFloaterProperties::onCommitName(LLUICtrl* ctrl, void* data)
+void LLFloaterProperties::onCommitName()
{
//llinfos << "LLFloaterProperties::onCommitName()" << llendl;
- LLFloaterProperties* self = (LLFloaterProperties*)data;
- if(!self)
- {
- return;
- }
- LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->findItem();
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem();
if(!item)
{
return;
}
- LLLineEditor* labelItemName = self->getChild<LLLineEditor>("LabelItemName");
+ LLLineEditor* labelItemName = getChild<LLLineEditor>("LabelItemName");
if(labelItemName&&
(item->getName() != labelItemName->getText()) &&
@@ -632,7 +583,7 @@ void LLFloaterProperties::onCommitName(LLUICtrl* ctrl, void* data)
{
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
new_item->rename(labelItemName->getText());
- if(self->mObjectID.isNull())
+ if(mObjectID.isNull())
{
new_item->updateServer(FALSE);
gInventory.updateItem(new_item);
@@ -640,7 +591,7 @@ void LLFloaterProperties::onCommitName(LLUICtrl* ctrl, void* data)
}
else
{
- LLViewerObject* object = gObjectList.findObject(self->mObjectID);
+ LLViewerObject* object = gObjectList.findObject(mObjectID);
if(object)
{
object->updateInventory(
@@ -652,16 +603,13 @@ void LLFloaterProperties::onCommitName(LLUICtrl* ctrl, void* data)
}
}
-// static
-void LLFloaterProperties::onCommitDescription(LLUICtrl* ctrl, void* data)
+void LLFloaterProperties::onCommitDescription()
{
//llinfos << "LLFloaterProperties::onCommitDescription()" << llendl;
- LLFloaterProperties* self = (LLFloaterProperties*)data;
- if(!self) return;
- LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->findItem();
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem();
if(!item) return;
- LLLineEditor* labelItemDesc = self->getChild<LLLineEditor>("LabelItemDesc");
+ LLLineEditor* labelItemDesc = getChild<LLLineEditor>("LabelItemDesc");
if(!labelItemDesc)
{
return;
@@ -672,7 +620,7 @@ void LLFloaterProperties::onCommitDescription(LLUICtrl* ctrl, void* data)
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
new_item->setDescription(labelItemDesc->getText());
- if(self->mObjectID.isNull())
+ if(mObjectID.isNull())
{
new_item->updateServer(FALSE);
gInventory.updateItem(new_item);
@@ -680,7 +628,7 @@ void LLFloaterProperties::onCommitDescription(LLUICtrl* ctrl, void* data)
}
else
{
- LLViewerObject* object = gObjectList.findObject(self->mObjectID);
+ LLViewerObject* object = gObjectList.findObject(mObjectID);
if(object)
{
object->updateInventory(
@@ -693,17 +641,15 @@ void LLFloaterProperties::onCommitDescription(LLUICtrl* ctrl, void* data)
}
// static
-void LLFloaterProperties::onCommitPermissions(LLUICtrl* ctrl, void* data)
+void LLFloaterProperties::onCommitPermissions()
{
//llinfos << "LLFloaterProperties::onCommitPermissions()" << llendl;
- LLFloaterProperties* self = (LLFloaterProperties*)data;
- if(!self) return;
- LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->findItem();
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem();
if(!item) return;
LLPermissions perm(item->getPermissions());
- LLCheckBoxCtrl* CheckShareWithGroup = self->getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
+ LLCheckBoxCtrl* CheckShareWithGroup = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
if(CheckShareWithGroup)
{
@@ -711,26 +657,26 @@ void LLFloaterProperties::onCommitPermissions(LLUICtrl* ctrl, void* data)
CheckShareWithGroup->get(),
PERM_MODIFY | PERM_MOVE | PERM_COPY);
}
- LLCheckBoxCtrl* CheckEveryoneCopy = self->getChild<LLCheckBoxCtrl>("CheckEveryoneCopy");
+ LLCheckBoxCtrl* CheckEveryoneCopy = getChild<LLCheckBoxCtrl>("CheckEveryoneCopy");
if(CheckEveryoneCopy)
{
perm.setEveryoneBits(gAgent.getID(), gAgent.getGroupID(),
CheckEveryoneCopy->get(), PERM_COPY);
}
- LLCheckBoxCtrl* CheckNextOwnerModify = self->getChild<LLCheckBoxCtrl>("CheckNextOwnerModify");
+ LLCheckBoxCtrl* CheckNextOwnerModify = getChild<LLCheckBoxCtrl>("CheckNextOwnerModify");
if(CheckNextOwnerModify)
{
perm.setNextOwnerBits(gAgent.getID(), gAgent.getGroupID(),
CheckNextOwnerModify->get(), PERM_MODIFY);
}
- LLCheckBoxCtrl* CheckNextOwnerCopy = self->getChild<LLCheckBoxCtrl>("CheckNextOwnerCopy");
+ LLCheckBoxCtrl* CheckNextOwnerCopy = getChild<LLCheckBoxCtrl>("CheckNextOwnerCopy");
if(CheckNextOwnerCopy)
{
perm.setNextOwnerBits(gAgent.getID(), gAgent.getGroupID(),
CheckNextOwnerCopy->get(), PERM_COPY);
}
- LLCheckBoxCtrl* CheckNextOwnerTransfer = self->getChild<LLCheckBoxCtrl>("CheckNextOwnerTransfer");
+ LLCheckBoxCtrl* CheckNextOwnerTransfer = getChild<LLCheckBoxCtrl>("CheckNextOwnerTransfer");
if(CheckNextOwnerTransfer)
{
perm.setNextOwnerBits(gAgent.getID(), gAgent.getGroupID(),
@@ -766,7 +712,7 @@ void LLFloaterProperties::onCommitPermissions(LLUICtrl* ctrl, void* data)
flags |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
}
new_item->setFlags(flags);
- if(self->mObjectID.isNull())
+ if(mObjectID.isNull())
{
new_item->updateServer(FALSE);
gInventory.updateItem(new_item);
@@ -774,7 +720,7 @@ void LLFloaterProperties::onCommitPermissions(LLUICtrl* ctrl, void* data)
}
else
{
- LLViewerObject* object = gObjectList.findObject(self->mObjectID);
+ LLViewerObject* object = gObjectList.findObject(mObjectID);
if(object)
{
object->updateInventory(
@@ -787,26 +733,22 @@ void LLFloaterProperties::onCommitPermissions(LLUICtrl* ctrl, void* data)
else
{
// need to make sure we don't just follow the click
- self->refresh();
+ refresh();
}
}
// static
-void LLFloaterProperties::onCommitSaleInfo(LLUICtrl* ctrl, void* data)
+void LLFloaterProperties::onCommitSaleInfo()
{
//llinfos << "LLFloaterProperties::onCommitSaleInfo()" << llendl;
- LLFloaterProperties* self = (LLFloaterProperties*)data;
- if(!self) return;
- self->updateSaleInfo();
+ updateSaleInfo();
}
// static
-void LLFloaterProperties::onCommitSaleType(LLUICtrl* ctrl, void* data)
+void LLFloaterProperties::onCommitSaleType()
{
//llinfos << "LLFloaterProperties::onCommitSaleType()" << llendl;
- LLFloaterProperties* self = (LLFloaterProperties*)data;
- if(!self) return;
- self->updateSaleInfo();
+ updateSaleInfo();
}
void LLFloaterProperties::updateSaleInfo()
@@ -851,13 +793,11 @@ void LLFloaterProperties::updateSaleInfo()
sale_type = LLSaleInfo::FS_ORIGINAL;
}
- LLLineEditor* EditPrice = getChild<LLLineEditor>("EditPrice");
+
S32 price = -1;
- if(EditPrice)
- {
- price = atoi(EditPrice->getText().c_str());
- }
+ price = getChild<LLUICtrl>("Edit Cost")->getValue().asInteger();;
+
// Invalid data - turn off the sale
if (price < 0)
{
@@ -932,13 +872,15 @@ LLInventoryItem* LLFloaterProperties::findItem() const
return item;
}
-void LLFloaterProperties::closeByID(const LLUUID& item_id, const LLUUID &object_id)
+//static
+void LLFloaterProperties::dirtyAll()
{
- LLFloaterProperties* floaterp = find(item_id, object_id);
-
- if (floaterp)
+ LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("properties");
+ for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin();
+ iter != inst_list.end(); ++iter)
{
- floaterp->close();
+ LLFloaterProperties* floater = dynamic_cast<LLFloaterProperties*>(*iter);
+ floater->dirty();
}
}
@@ -946,8 +888,24 @@ void LLFloaterProperties::closeByID(const LLUUID& item_id, const LLUUID &object_
/// LLMultiProperties
///----------------------------------------------------------------------------
-LLMultiProperties::LLMultiProperties(const LLRect &rect) : LLMultiFloater(std::string("Properties"), rect)
+LLMultiProperties::LLMultiProperties()
+ : LLMultiFloater(LLSD())
{
+ // *TODO: There should be a .xml file for this
+ const LLRect& nextrect = LLFloaterReg::getFloaterRect("properties"); // place where the next properties should show up
+ if (nextrect.getWidth() > 0)
+ {
+ setRect(nextrect);
+ }
+ else
+ {
+ // start with a small rect in the top-left corner ; will get resized
+ LLRect rect;
+ rect.setLeftTopAndSize(0, gViewerWindow->getWindowHeightScaled(), 20, 20);
+ setRect(rect);
+ }
+ setTitle(LLTrans::getString("MultiPropertiesTitle"));
+ buildTabContainer();
}
///----------------------------------------------------------------------------
diff --git a/indra/newview/llfloaterproperties.h b/indra/newview/llfloaterproperties.h
index 2f5d97d384..586719a4dc 100644
--- a/indra/newview/llfloaterproperties.h
+++ b/indra/newview/llfloaterproperties.h
@@ -34,7 +34,7 @@
#define LL_LLFLOATERPROPERTIES_H
#include <map>
-#include "llfloater.h"
+#include "llmultifloater.h"
#include "lliconctrl.h"
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -53,30 +53,27 @@ class LLPropertiesObserver;
class LLFloaterProperties : public LLFloater
{
public:
- static LLFloaterProperties* find(const LLUUID& item_id,
- const LLUUID& object_id);
- static LLFloaterProperties* show(const LLUUID& item_id,
- const LLUUID& object_id);
- static void dirtyAll();
-
- static void closeByID(const LLUUID& item_id, const LLUUID& object_id);
-
- LLFloaterProperties(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& item_id, const LLUUID& object_id);
- virtual ~LLFloaterProperties();
+ LLFloaterProperties(const LLUUID& item_id);
+ /*virtual*/ ~LLFloaterProperties();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+ void setObjectID(const LLUUID& object_id) { mObjectID = object_id; }
- // do everything necessary
void dirty() { mDirty = TRUE; }
void refresh();
-
+
+ static void dirtyAll();
+
protected:
// ui callbacks
- static void onClickCreator(void* data);
- static void onClickOwner(void* data);
- static void onCommitName(LLUICtrl* ctrl, void* data);
- static void onCommitDescription(LLUICtrl* ctrl, void* data);
- static void onCommitPermissions(LLUICtrl* ctrl, void* data);
- static void onCommitSaleInfo(LLUICtrl* ctrl, void* data);
- static void onCommitSaleType(LLUICtrl* ctrl, void* data);
+ void onClickCreator();
+ void onClickOwner();
+ void onCommitName();
+ void onCommitDescription();
+ void onCommitPermissions();
+ void onCommitSaleInfo();
+ void onCommitSaleType();
void updateSaleInfo();
LLInventoryItem* findItem() const;
@@ -93,18 +90,15 @@ protected:
// inventory.
LLUUID mObjectID;
- BOOL mDirty;
+ BOOL mDirty;
- typedef std::map<LLUUID, LLFloaterProperties*, lluuid_less> instance_map;
- static instance_map sInstances;
- static LLPropertiesObserver* sPropertiesObserver;
- static S32 sPropertiesObserverCount;
+ LLPropertiesObserver* mPropertiesObserver;
};
class LLMultiProperties : public LLMultiFloater
{
public:
- LLMultiProperties(const LLRect& rect);
+ LLMultiProperties();
};
#endif // LL_LLFLOATERPROPERTIES_H
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 06c1b2c12b..03ff2cc370 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -37,34 +37,37 @@
#include <algorithm>
#include <functional>
-#include "llcachename.h"
#include "lldir.h"
#include "lldispatcher.h"
#include "llglheaders.h"
#include "llregionflags.h"
#include "llstl.h"
+#include "llvfile.h"
+#include "llxfermanager.h"
#include "indra_constants.h"
#include "message.h"
#include "llagent.h"
-#include "llalertdialog.h"
#include "llappviewer.h"
#include "llfloateravatarpicker.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#include "llfilepicker.h"
-#include "llfloaterdaycycle.h"
#include "llfloatergodtools.h" // for send_sim_wide_deletes()
#include "llfloatertopobjects.h" // added to fix SL-32336
#include "llfloatergroups.h"
+#include "llfloaterreg.h"
#include "llfloatertelehub.h"
#include "llfloaterwindlight.h"
#include "llinventorymodel.h"
#include "lllineeditor.h"
-#include "llalertdialog.h"
#include "llnamelistctrl.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+#include "llscrolllistitem.h"
#include "llsliderctrl.h"
+#include "llslurl.h"
#include "llspinctrl.h"
#include "lltabcontainer.h"
#include "lltextbox.h"
@@ -73,15 +76,16 @@
#include "lltrans.h"
#include "llviewercontrol.h"
#include "lluictrlfactory.h"
-#include "llviewerimage.h"
-#include "llviewerimagelist.h"
+#include "llviewerinventory.h"
+#include "llviewertexture.h"
+#include "llviewertexturelist.h"
#include "llviewerregion.h"
#include "llviewerstats.h"
#include "llviewertexteditor.h"
#include "llviewerwindow.h"
#include "llvlcomposition.h"
-
-#define ELAR_ENABLED 0 // Enable when server support is implemented
+#include "lltrans.h"
+#include "llagentui.h"
const S32 TERRAIN_TEXTURE_COUNT = 4;
const S32 CORNER_COUNT = 4;
@@ -161,8 +165,9 @@ bool estate_dispatch_initialized = false;
LLUUID LLFloaterRegionInfo::sRequestInvoice;
LLFloaterRegionInfo::LLFloaterRegionInfo(const LLSD& seed)
+ : LLFloater(seed)
{
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_region_info.xml", NULL, FALSE);
+ //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_region_info.xml", FALSE);
}
BOOL LLFloaterRegionInfo::postBuild()
@@ -173,33 +178,35 @@ BOOL LLFloaterRegionInfo::postBuild()
LLPanelRegionInfo* panel;
panel = new LLPanelRegionGeneralInfo;
mInfoPanels.push_back(panel);
+ panel->getCommitCallbackRegistrar().add("RegionInfo.ManageTelehub", boost::bind(&LLPanelRegionInfo::onClickManageTelehub, panel));
+
LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_region_general.xml");
- mTab->addTabPanel(panel, panel->getLabel(), TRUE);
+ mTab->addTabPanel(LLTabContainer::TabPanelParams().panel(panel).select_tab(true));
panel = new LLPanelRegionDebugInfo;
mInfoPanels.push_back(panel);
LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_region_debug.xml");
- mTab->addTabPanel(panel, panel->getLabel(), FALSE);
+ mTab->addTabPanel(panel);
panel = new LLPanelRegionTextureInfo;
mInfoPanels.push_back(panel);
LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_region_texture.xml");
- mTab->addTabPanel(panel, panel->getLabel(), FALSE);
+ mTab->addTabPanel(panel);
panel = new LLPanelRegionTerrainInfo;
mInfoPanels.push_back(panel);
LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_region_terrain.xml");
- mTab->addTabPanel(panel, panel->getLabel(), FALSE);
+ mTab->addTabPanel(panel);
panel = new LLPanelEstateInfo;
mInfoPanels.push_back(panel);
LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_region_estate.xml");
- mTab->addTabPanel(panel, panel->getLabel(), FALSE);
+ mTab->addTabPanel(panel);
panel = new LLPanelEstateCovenant;
mInfoPanels.push_back(panel);
LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_region_covenant.xml");
- mTab->addTabPanel(panel, panel->getLabel(), FALSE);
+ mTab->addTabPanel(panel);
gMessageSystem->setHandlerFunc(
"EstateOwnerMessage",
@@ -212,22 +219,16 @@ LLFloaterRegionInfo::~LLFloaterRegionInfo()
{
}
-void LLFloaterRegionInfo::onOpen()
+void LLFloaterRegionInfo::onOpen(const LLSD& key)
{
- LLRect rect = gSavedSettings.getRect("FloaterRegionInfo");
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- rect.translate(left,top);
-
refreshFromRegion(gAgent.getRegion());
requestRegionInfo();
- LLFloater::onOpen();
}
// static
void LLFloaterRegionInfo::requestRegionInfo()
{
- LLTabContainer* tab = findInstance()->getChild<LLTabContainer>("region_panels");
+ LLTabContainer* tab = getChild<LLTabContainer>("region_panels");
tab->getChild<LLPanel>("General")->setCtrlsEnabled(FALSE);
tab->getChild<LLPanel>("Debug")->setCtrlsEnabled(FALSE);
@@ -249,7 +250,8 @@ void LLFloaterRegionInfo::requestRegionInfo()
void LLFloaterRegionInfo::processEstateOwnerRequest(LLMessageSystem* msg,void**)
{
static LLDispatcher dispatch;
- if(!findInstance())
+ LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info");
+ if(!floater)
{
return;
}
@@ -259,7 +261,7 @@ void LLFloaterRegionInfo::processEstateOwnerRequest(LLMessageSystem* msg,void**)
LLPanelEstateInfo::initDispatch(dispatch);
}
- LLTabContainer* tab = findInstance()->getChild<LLTabContainer>("region_panels");
+ LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels");
LLPanelEstateInfo* panel = (LLPanelEstateInfo*)tab->getChild<LLPanel>("Estate");
// unpack the message
@@ -285,14 +287,14 @@ void LLFloaterRegionInfo::processEstateOwnerRequest(LLMessageSystem* msg,void**)
void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg)
{
LLPanel* panel;
-
+ LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info");
llinfos << "LLFloaterRegionInfo::processRegionInfo" << llendl;
- if(!findInstance())
+ if(!floater)
{
return;
}
- LLTabContainer* tab = findInstance()->getChild<LLTabContainer>("region_panels");
+ LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels");
LLViewerRegion* region = gAgent.getRegion();
BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate());
@@ -379,13 +381,13 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg)
panel->childSetEnabled("sun_hour_slider", allow_modify && !use_estate_sun);
panel->setCtrlsEnabled(allow_modify);
- getInstance()->refreshFromRegion( gAgent.getRegion() );
+ floater->refreshFromRegion( gAgent.getRegion() );
}
// static
LLPanelEstateInfo* LLFloaterRegionInfo::getPanelEstate()
{
- LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance();
+ LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info");
if (!floater) return NULL;
LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels");
LLPanelEstateInfo* panel = (LLPanelEstateInfo*)tab->getChild<LLPanel>("Estate");
@@ -395,7 +397,7 @@ LLPanelEstateInfo* LLFloaterRegionInfo::getPanelEstate()
// static
LLPanelEstateCovenant* LLFloaterRegionInfo::getPanelCovenant()
{
- LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance();
+ LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info");
if (!floater) return NULL;
LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels");
LLPanelEstateCovenant* panel = (LLPanelEstateCovenant*)tab->getChild<LLPanel>("Covenant");
@@ -404,6 +406,11 @@ LLPanelEstateCovenant* LLFloaterRegionInfo::getPanelCovenant()
void LLFloaterRegionInfo::refreshFromRegion(LLViewerRegion* region)
{
+ if (!region)
+ {
+ return;
+ }
+
// call refresh from region on all panels
std::for_each(
mInfoPanels.begin(),
@@ -436,52 +443,48 @@ void LLFloaterRegionInfo::refresh()
// LLPanelRegionInfo
//
-// static
-void LLPanelRegionInfo::onBtnSet(void* user_data)
+LLPanelRegionInfo::LLPanelRegionInfo()
+ : LLPanel()
{
- LLPanelRegionInfo* panel = (LLPanelRegionInfo*)user_data;
- if(!panel) return;
- if (panel->sendUpdate())
- {
- panel->disableButton("apply_btn");
- }
}
-//static
-void LLPanelRegionInfo::onChangeChildCtrl(LLUICtrl* ctrl, void* user_data)
+void LLPanelRegionInfo::onBtnSet()
{
- if (ctrl)
+ if (sendUpdate())
{
- LLPanelRegionInfo* panel = (LLPanelRegionInfo*) ctrl->getParent();
- panel->updateChild(ctrl);
+ disableButton("apply_btn");
}
}
-// static
+void LLPanelRegionInfo::onChangeChildCtrl(LLUICtrl* ctrl)
+{
+ updateChild(ctrl); // virtual function
+}
+
// Enables the "set" button if it is not already enabled
-void LLPanelRegionInfo::onChangeAnything(LLUICtrl* ctrl, void* user_data)
+void LLPanelRegionInfo::onChangeAnything()
{
- LLPanelRegionInfo* panel = (LLPanelRegionInfo*)user_data;
- if(panel)
- {
- panel->enableButton("apply_btn");
- panel->refresh();
- }
+ enableButton("apply_btn");
+ refresh();
}
// static
// Enables set button on change to line editor
void LLPanelRegionInfo::onChangeText(LLLineEditor* caller, void* user_data)
{
- // reuse the previous method
- onChangeAnything(0, user_data);
+ LLPanelRegionInfo* panel = dynamic_cast<LLPanelRegionInfo*>(caller->getParent());
+ if(panel)
+ {
+ panel->enableButton("apply_btn");
+ panel->refresh();
+ }
}
// virtual
BOOL LLPanelRegionInfo::postBuild()
{
- childSetAction("apply_btn", onBtnSet, this);
+ getChild<LLUICtrl>("apply_btn")->setCommitCallback(boost::bind(&LLPanelRegionInfo::onBtnSet, this));
childDisable("apply_btn");
refresh();
return TRUE;
@@ -544,19 +547,13 @@ void LLPanelRegionInfo::disableButton(const std::string& btn_name)
void LLPanelRegionInfo::initCtrl(const std::string& name)
{
- childSetCommitCallback(name, onChangeAnything, this);
-}
-
-void LLPanelRegionInfo::initHelpBtn(const std::string& name, const std::string& xml_alert)
-{
- childSetAction(name, onClickHelp, new std::string(xml_alert));
+ getChild<LLUICtrl>(name)->setCommitCallback(boost::bind(&LLPanelRegionInfo::onChangeAnything, this));
}
-// static
-void LLPanelRegionInfo::onClickHelp(void* data)
+void LLPanelRegionInfo::onClickManageTelehub()
{
- std::string* xml_alert = (std::string*)data;
- LLNotifications::instance().add(*xml_alert);
+ LLFloaterReg::hideInstance("region_info");
+ LLFloaterReg::showInstance("telehubs");
}
/////////////////////////////////////////////////////////////////////////////
@@ -594,46 +591,30 @@ BOOL LLPanelRegionGeneralInfo::postBuild()
initCtrl("restrict_pushobject");
initCtrl("block_parcel_search_check");
- initHelpBtn("terraform_help", "HelpRegionBlockTerraform");
- initHelpBtn("fly_help", "HelpRegionBlockFly");
- initHelpBtn("damage_help", "HelpRegionAllowDamage");
- initHelpBtn("agent_limit_help", "HelpRegionAgentLimit");
- initHelpBtn("object_bonus_help", "HelpRegionObjectBonus");
- initHelpBtn("access_help", "HelpRegionMaturity");
- initHelpBtn("restrict_pushobject_help", "HelpRegionRestrictPushObject");
- initHelpBtn("land_resell_help", "HelpRegionLandResell");
- initHelpBtn("parcel_changes_help", "HelpParcelChanges");
- initHelpBtn("parcel_search_help", "HelpRegionSearch");
-
- childSetAction("kick_btn", onClickKick, this);
+ childSetAction("kick_btn", boost::bind(&LLPanelRegionGeneralInfo::onClickKick, this));
childSetAction("kick_all_btn", onClickKickAll, this);
childSetAction("im_btn", onClickMessage, this);
- childSetAction("manage_telehub_btn", onClickManageTelehub, this);
+// childSetAction("manage_telehub_btn", onClickManageTelehub, this);
return LLPanelRegionInfo::postBuild();
}
-// static
-void LLPanelRegionGeneralInfo::onClickKick(void* userdata)
+void LLPanelRegionGeneralInfo::onClickKick()
{
llinfos << "LLPanelRegionGeneralInfo::onClickKick" << llendl;
- LLPanelRegionGeneralInfo* panelp = (LLPanelRegionGeneralInfo*)userdata;
// this depends on the grandparent view being a floater
// in order to set up floater dependency
- LLFloater* parent_floater = gFloaterView->getParentFloater(panelp);
- LLFloater* child_floater = LLFloaterAvatarPicker::show(onKickCommit, userdata, FALSE, TRUE);
+ LLFloater* parent_floater = gFloaterView->getParentFloater(this);
+ LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionGeneralInfo::onKickCommit, this, _1,_2), FALSE, TRUE);
parent_floater->addDependentFloater(child_floater);
}
-// static
-void LLPanelRegionGeneralInfo::onKickCommit(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* userdata)
+void LLPanelRegionGeneralInfo::onKickCommit(const std::vector<std::string>& names, const std::vector<LLUUID>& ids)
{
if (names.empty() || ids.empty()) return;
if(ids[0].notNull())
{
- LLPanelRegionGeneralInfo* self = (LLPanelRegionGeneralInfo*)userdata;
- if(!self) return;
strings_t strings;
// [0] = our agent id
// [1] = target agent id
@@ -645,7 +626,7 @@ void LLPanelRegionGeneralInfo::onKickCommit(const std::vector<std::string>& name
strings.push_back(strings_t::value_type(buffer));
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
- self->sendEstateOwnerMessage(gMessageSystem, "teleporthomeuser", invoice, strings);
+ sendEstateOwnerMessage(gMessageSystem, "teleporthomeuser", invoice, strings);
}
}
@@ -653,7 +634,7 @@ void LLPanelRegionGeneralInfo::onKickCommit(const std::vector<std::string>& name
void LLPanelRegionGeneralInfo::onClickKickAll(void* userdata)
{
llinfos << "LLPanelRegionGeneralInfo::onClickKickAll" << llendl;
- LLNotifications::instance().add("KickUsersFromRegion",
+ LLNotificationsUtil::add("KickUsersFromRegion",
LLSD(),
LLSD(),
boost::bind(&LLPanelRegionGeneralInfo::onKickAllCommit, (LLPanelRegionGeneralInfo*)userdata, _1, _2));
@@ -661,7 +642,7 @@ void LLPanelRegionGeneralInfo::onClickKickAll(void* userdata)
bool LLPanelRegionGeneralInfo::onKickAllCommit(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0)
{
strings_t strings;
@@ -681,7 +662,7 @@ bool LLPanelRegionGeneralInfo::onKickAllCommit(const LLSD& notification, const L
void LLPanelRegionGeneralInfo::onClickMessage(void* userdata)
{
llinfos << "LLPanelRegionGeneralInfo::onClickMessage" << llendl;
- LLNotifications::instance().add("MessageRegion",
+ LLNotificationsUtil::add("MessageRegion",
LLSD(),
LLSD(),
boost::bind(&LLPanelRegionGeneralInfo::onMessageCommit, (LLPanelRegionGeneralInfo*)userdata, _1, _2));
@@ -690,7 +671,7 @@ void LLPanelRegionGeneralInfo::onClickMessage(void* userdata)
// static
bool LLPanelRegionGeneralInfo::onMessageCommit(const LLSD& notification, const LLSD& response)
{
- if(LLNotification::getSelectedOption(notification, response) != 0) return false;
+ if(LLNotificationsUtil::getSelectedOption(notification, response) != 0) return false;
std::string text = response["message"].asString();
if (text.empty()) return false;
@@ -708,7 +689,7 @@ bool LLPanelRegionGeneralInfo::onMessageCommit(const LLSD& notification, const L
gAgent.getID().toString(buffer);
strings.push_back(buffer);
std::string name;
- gAgent.buildFullname(name);
+ LLAgentUI::buildFullname(name);
strings.push_back(strings_t::value_type(name));
strings.push_back(strings_t::value_type(text));
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
@@ -716,13 +697,7 @@ bool LLPanelRegionGeneralInfo::onMessageCommit(const LLSD& notification, const L
return false;
}
-// static
-void LLPanelRegionGeneralInfo::onClickManageTelehub(void* data)
-{
- LLFloaterRegionInfo::getInstance()->close();
- LLFloaterTelehub::show();
-}
// setregioninfo
// strings[0] = 'Y' - block terraform, 'N' - not
@@ -799,7 +774,7 @@ BOOL LLPanelRegionGeneralInfo::sendUpdate()
LLViewerRegion* region = gAgent.getRegion();
if (region && (childGetValue("access_combo").asInteger() != region->getSimAccess()) )
{
- LLNotifications::instance().add("RegionMaturityChange");
+ LLNotificationsUtil::add("RegionMaturityChange");
}
return TRUE;
@@ -815,14 +790,7 @@ BOOL LLPanelRegionDebugInfo::postBuild()
initCtrl("disable_collisions_check");
initCtrl("disable_physics_check");
- initHelpBtn("disable_scripts_help", "HelpRegionDisableScripts");
- initHelpBtn("disable_collisions_help", "HelpRegionDisableCollisions");
- initHelpBtn("disable_physics_help", "HelpRegionDisablePhysics");
- initHelpBtn("top_colliders_help", "HelpRegionTopColliders");
- initHelpBtn("top_scripts_help", "HelpRegionTopScripts");
- initHelpBtn("restart_help", "HelpRegionRestart");
-
- childSetAction("choose_avatar_btn", onClickChooseAvatar, this);
+ childSetAction("choose_avatar_btn", boost::bind(&LLPanelRegionDebugInfo::onClickChooseAvatar, this));
childSetAction("return_btn", onClickReturn, this);
childSetAction("top_colliders_btn", onClickTopColliders, this);
childSetAction("top_scripts_btn", onClickTopScripts, this);
@@ -874,19 +842,18 @@ BOOL LLPanelRegionDebugInfo::sendUpdate()
return TRUE;
}
-void LLPanelRegionDebugInfo::onClickChooseAvatar(void* data)
+void LLPanelRegionDebugInfo::onClickChooseAvatar()
{
- LLFloaterAvatarPicker::show(callbackAvatarID, data, FALSE, TRUE);
+ LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionDebugInfo::callbackAvatarID, this, _1, _2), FALSE, TRUE);
}
-// static
-void LLPanelRegionDebugInfo::callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data)
+
+void LLPanelRegionDebugInfo::callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids)
{
- LLPanelRegionDebugInfo* self = (LLPanelRegionDebugInfo*) data;
if (ids.empty() || names.empty()) return;
- self->mTargetAvatar = ids[0];
- self->childSetValue("target_avatar_name", LLSD(names[0]));
- self->refreshFromRegion( gAgent.getRegion() );
+ mTargetAvatar = ids[0];
+ childSetValue("target_avatar_name", LLSD(names[0]));
+ refreshFromRegion( gAgent.getRegion() );
}
// static
@@ -913,13 +880,13 @@ void LLPanelRegionDebugInfo::onClickReturn(void* data)
}
payload["flags"] = int(flags);
payload["return_estate_wide"] = panelp->childGetValue("return_estate_wide").asBoolean();
- LLNotifications::instance().add("EstateObjectReturn", args, payload,
+ LLNotificationsUtil::add("EstateObjectReturn", args, payload,
boost::bind(&LLPanelRegionDebugInfo::callbackReturn, panelp, _1, _2));
}
bool LLPanelRegionDebugInfo::callbackReturn(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option != 0) return false;
LLUUID target_avatar = notification["payload"]["avatar_id"].asUUID();
@@ -955,8 +922,10 @@ void LLPanelRegionDebugInfo::onClickTopColliders(void* data)
strings_t strings;
strings.push_back("1"); // one physics step
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
- LLFloaterTopObjects::show();
- LLFloaterTopObjects::clearList();
+ LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance<LLFloaterTopObjects>("top_objects");
+ if(!instance) return;
+ LLFloaterReg::showInstance("top_objects");
+ instance->clearList();
self->sendEstateOwnerMessage(gMessageSystem, "colliders", invoice, strings);
}
@@ -967,21 +936,23 @@ void LLPanelRegionDebugInfo::onClickTopScripts(void* data)
strings_t strings;
strings.push_back("6"); // top 5 scripts
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
- LLFloaterTopObjects::show();
- LLFloaterTopObjects::clearList();
+ LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance<LLFloaterTopObjects>("top_objects");
+ if(!instance) return;
+ LLFloaterReg::showInstance("top_objects");
+ instance->clearList();
self->sendEstateOwnerMessage(gMessageSystem, "scripts", invoice, strings);
}
// static
void LLPanelRegionDebugInfo::onClickRestart(void* data)
{
- LLNotifications::instance().add("ConfirmRestart", LLSD(), LLSD(),
+ LLNotificationsUtil::add("ConfirmRestart", LLSD(), LLSD(),
boost::bind(&LLPanelRegionDebugInfo::callbackRestart, (LLPanelRegionDebugInfo*)data, _1, _2));
}
bool LLPanelRegionDebugInfo::callbackRestart(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option != 0) return false;
strings_t strings;
@@ -1074,7 +1045,7 @@ BOOL LLPanelRegionTextureInfo::postBuild()
initCtrl(buffer);
}
-// LLButton* btn = new LLButton("dump", LLRect(0, 20, 100, 0), "", onClickDump, this);
+// LLButton* btn = ("dump", LLRect(0, 20, 100, 0), "", onClickDump, this);
// btn->setFollows(FOLLOWS_TOP|FOLLOWS_LEFT);
// addChild(btn);
@@ -1136,11 +1107,11 @@ BOOL LLPanelRegionTextureInfo::validateTextureSizes()
if (!texture_ctrl) continue;
LLUUID image_asset_id = texture_ctrl->getImageAssetID();
- LLViewerImage* img = gImageList.getImage(image_asset_id);
+ LLViewerTexture* img = LLViewerTextureManager::getFetchedTexture(image_asset_id);
S32 components = img->getComponents();
// Must ask for highest resolution version's width. JC
- S32 width = img->getWidth(0);
- S32 height = img->getHeight(0);
+ S32 width = img->getFullWidth();
+ S32 height = img->getFullHeight();
//llinfos << "texture detail " << i << " is " << width << "x" << height << "x" << components << llendl;
@@ -1149,7 +1120,7 @@ BOOL LLPanelRegionTextureInfo::validateTextureSizes()
LLSD args;
args["TEXTURE_NUM"] = i+1;
args["TEXTURE_BIT_DEPTH"] = llformat("%d",components * 8);
- LLNotifications::instance().add("InvalidTerrainBitDepth", args);
+ LLNotificationsUtil::add("InvalidTerrainBitDepth", args);
return FALSE;
}
@@ -1160,7 +1131,7 @@ BOOL LLPanelRegionTextureInfo::validateTextureSizes()
args["TEXTURE_NUM"] = i+1;
args["TEXTURE_SIZE_X"] = width;
args["TEXTURE_SIZE_Y"] = height;
- LLNotifications::instance().add("InvalidTerrainSize", args);
+ LLNotificationsUtil::add("InvalidTerrainSize", args);
return FALSE;
}
@@ -1184,23 +1155,14 @@ BOOL LLPanelRegionTerrainInfo::postBuild()
{
LLPanelRegionInfo::postBuild();
- initHelpBtn("water_height_help", "HelpRegionWaterHeight");
- initHelpBtn("terrain_raise_help", "HelpRegionTerrainRaise");
- initHelpBtn("terrain_lower_help", "HelpRegionTerrainLower");
- initHelpBtn("upload_raw_help", "HelpRegionUploadRaw");
- initHelpBtn("download_raw_help", "HelpRegionDownloadRaw");
- initHelpBtn("use_estate_sun_help", "HelpRegionUseEstateSun");
- initHelpBtn("fixed_sun_help", "HelpRegionFixedSun");
- initHelpBtn("bake_terrain_help", "HelpRegionBakeTerrain");
-
initCtrl("water_height_spin");
initCtrl("terrain_raise_spin");
initCtrl("terrain_lower_spin");
initCtrl("fixed_sun_check");
- childSetCommitCallback("fixed_sun_check", onChangeFixedSun, this);
- childSetCommitCallback("use_estate_sun_check", onChangeUseEstateTime, this);
- childSetCommitCallback("sun_hour_slider", onChangeSunHour, this);
+ getChild<LLUICtrl>("fixed_sun_check")->setCommitCallback(boost::bind(&LLPanelRegionTerrainInfo::onChangeFixedSun, this));
+ getChild<LLUICtrl>("use_estate_sun_check")->setCommitCallback(boost::bind(&LLPanelRegionTerrainInfo::onChangeUseEstateTime, this));
+ getChild<LLUICtrl>("sun_hour_slider")->setCommitCallback(boost::bind(&LLPanelRegionTerrainInfo::onChangeSunHour, this));
childSetAction("download_raw_btn", onClickDownloadRaw, this);
childSetAction("upload_raw_btn", onClickUploadRaw, this);
@@ -1251,7 +1213,7 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate()
// Grab estate information in case the user decided to set the
// region back to estate time. JC
- LLFloaterRegionInfo* floater = LLFloaterRegionInfo::getInstance();
+ LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info");
if (!floater) return true;
LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels");
@@ -1283,39 +1245,29 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate()
return TRUE;
}
-// static
-void LLPanelRegionTerrainInfo::onChangeUseEstateTime(LLUICtrl* ctrl, void* user_data)
+void LLPanelRegionTerrainInfo::onChangeUseEstateTime()
{
- LLPanelRegionTerrainInfo* panel = (LLPanelRegionTerrainInfo*) user_data;
- if (!panel) return;
- BOOL use_estate_sun = panel->childGetValue("use_estate_sun_check").asBoolean();
- panel->childSetEnabled("fixed_sun_check", !use_estate_sun);
- panel->childSetEnabled("sun_hour_slider", !use_estate_sun);
+ BOOL use_estate_sun = childGetValue("use_estate_sun_check").asBoolean();
+ childSetEnabled("fixed_sun_check", !use_estate_sun);
+ childSetEnabled("sun_hour_slider", !use_estate_sun);
if (use_estate_sun)
{
- panel->childSetValue("fixed_sun_check", LLSD(FALSE));
- panel->childSetValue("sun_hour_slider", LLSD(0.f));
+ childSetValue("fixed_sun_check", LLSD(FALSE));
+ childSetValue("sun_hour_slider", LLSD(0.f));
}
- panel->childEnable("apply_btn");
+ childEnable("apply_btn");
}
-// static
-void LLPanelRegionTerrainInfo::onChangeFixedSun(LLUICtrl* ctrl, void* user_data)
+void LLPanelRegionTerrainInfo::onChangeFixedSun()
{
- LLPanelRegionTerrainInfo* panel = (LLPanelRegionTerrainInfo*) user_data;
- if (!panel) return;
// Just enable the apply button. We let the sun-hour slider be enabled
// for both fixed-sun and non-fixed-sun. JC
- panel->childEnable("apply_btn");
+ childEnable("apply_btn");
}
-// static
-void LLPanelRegionTerrainInfo::onChangeSunHour(LLUICtrl* ctrl, void*)
+void LLPanelRegionTerrainInfo::onChangeSunHour()
{
- // can't use userdata to get panel, slider uses it internally
- LLPanelRegionTerrainInfo* panel = (LLPanelRegionTerrainInfo*) ctrl->getParent();
- if (!panel) return;
- panel->childEnable("apply_btn");
+ childEnable("apply_btn");
}
// static
@@ -1357,20 +1309,18 @@ void LLPanelRegionTerrainInfo::onClickUploadRaw(void* data)
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
self->sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings);
- LLNotifications::instance().add("RawUploadStarted");
+ LLNotificationsUtil::add("RawUploadStarted");
}
// static
void LLPanelRegionTerrainInfo::onClickBakeTerrain(void* data)
{
- LLNotifications::instance().add(
- LLNotification::Params("ConfirmBakeTerrain")
- .functor(boost::bind(&LLPanelRegionTerrainInfo::callbackBakeTerrain, (LLPanelRegionTerrainInfo*)data, _1, _2)));
+ LLNotificationsUtil::add("ConfirmBakeTerrain", LLSD(), LLSD(), boost::bind(&LLPanelRegionTerrainInfo::callbackBakeTerrain, (LLPanelRegionTerrainInfo*)data, _1, _2));
}
bool LLPanelRegionTerrainInfo::callbackBakeTerrain(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option != 0) return false;
strings_t strings;
@@ -1410,32 +1360,23 @@ void LLPanelEstateInfo::initDispatch(LLDispatcher& dispatch)
estate_dispatch_initialized = true;
}
-// static
// Disables the sun-hour slider and the use fixed time check if the use global time is check
-void LLPanelEstateInfo::onChangeUseGlobalTime(LLUICtrl* ctrl, void* user_data)
+void LLPanelEstateInfo::onChangeUseGlobalTime()
{
- LLPanelEstateInfo* panel = (LLPanelEstateInfo*) user_data;
- if (panel)
- {
- bool enabled = !panel->childGetValue("use_global_time_check").asBoolean();
- panel->childSetEnabled("sun_hour_slider", enabled);
- panel->childSetEnabled("fixed_sun_check", enabled);
- panel->childSetValue("fixed_sun_check", LLSD(FALSE));
- panel->enableButton("apply_btn");
- }
+ bool enabled = !childGetValue("use_global_time_check").asBoolean();
+ childSetEnabled("sun_hour_slider", enabled);
+ childSetEnabled("fixed_sun_check", enabled);
+ childSetValue("fixed_sun_check", LLSD(FALSE));
+ enableButton("apply_btn");
}
// Enables the sun-hour slider if the fixed-sun checkbox is set
-void LLPanelEstateInfo::onChangeFixedSun(LLUICtrl* ctrl, void* user_data)
+void LLPanelEstateInfo::onChangeFixedSun()
{
- LLPanelEstateInfo* panel = (LLPanelEstateInfo*) user_data;
- if (panel)
- {
- bool enabled = !panel->childGetValue("fixed_sun_check").asBoolean();
- panel->childSetEnabled("use_global_time_check", enabled);
- panel->childSetValue("use_global_time_check", LLSD(FALSE));
- panel->enableButton("apply_btn");
- }
+ bool enabled = !childGetValue("fixed_sun_check").asBoolean();
+ childSetEnabled("use_global_time_check", enabled);
+ childSetValue("use_global_time_check", LLSD(FALSE));
+ enableButton("apply_btn");
}
@@ -1446,12 +1387,12 @@ void LLPanelEstateInfo::onChangeFixedSun(LLUICtrl* ctrl, void* user_data)
//---------------------------------------------------------------------------
void LLPanelEstateInfo::onClickEditSky(void* user_data)
{
- LLFloaterWindLight::show();
+ LLFloaterReg::showInstance("env_windlight");
}
void LLPanelEstateInfo::onClickEditDayCycle(void* user_data)
{
- LLFloaterDayCycle::show();
+ LLFloaterReg::showInstance("env_day_cycle");
}
// static
@@ -1466,7 +1407,7 @@ void LLPanelEstateInfo::onClickAddAllowedAgent(void* user_data)
LLSD args;
args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
- LLNotifications::instance().add("MaxAllowedAgentOnRegion", args);
+ LLNotificationsUtil::add("MaxAllowedAgentOnRegion", args);
return;
}
accessAddCore(ESTATE_ACCESS_ALLOWED_AGENT_ADD, "EstateAllowedAgentAdd");
@@ -1478,22 +1419,20 @@ void LLPanelEstateInfo::onClickRemoveAllowedAgent(void* user_data)
accessRemoveCore(ESTATE_ACCESS_ALLOWED_AGENT_REMOVE, "EstateAllowedAgentRemove", "allowed_avatar_name_list");
}
-// static
-void LLPanelEstateInfo::onClickAddAllowedGroup(void* user_data)
+void LLPanelEstateInfo::onClickAddAllowedGroup()
{
- LLPanelEstateInfo* self = (LLPanelEstateInfo*)user_data;
- LLCtrlListInterface *list = self->childGetListInterface("allowed_group_name_list");
+ LLCtrlListInterface *list = childGetListInterface("allowed_group_name_list");
if (!list) return;
if (list->getItemCount() >= ESTATE_MAX_ACCESS_IDS)
{
LLSD args;
args["MAX_GROUPS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
- LLNotifications::instance().add("MaxAllowedGroupsOnRegion", args);
+ LLNotificationsUtil::add("MaxAllowedGroupsOnRegion", args);
return;
}
LLNotification::Params params("ChangeLindenAccess");
- params.functor(boost::bind(&LLPanelEstateInfo::addAllowedGroup, self, _1, _2));
+ params.functor.function(boost::bind(&LLPanelEstateInfo::addAllowedGroup, this, _1, _2));
if (isLindenEstate())
{
LLNotifications::instance().add(params);
@@ -1506,16 +1445,16 @@ void LLPanelEstateInfo::onClickAddAllowedGroup(void* user_data)
bool LLPanelEstateInfo::addAllowedGroup(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option != 0) return false;
LLFloater* parent_floater = gFloaterView->getParentFloater(this);
- LLFloaterGroupPicker* widget;
- widget = LLFloaterGroupPicker::showInstance(LLSD(gAgent.getID()));
+ LLFloaterGroupPicker* widget = LLFloaterReg::showTypedInstance<LLFloaterGroupPicker>("group_picker", LLSD(gAgent.getID()));
if (widget)
{
- widget->setSelectCallback(addAllowedGroup2, NULL);
+ widget->removeNoneOption();
+ widget->setSelectGroupCallback(boost::bind(&LLPanelEstateInfo::addAllowedGroup2, this, _1));
if (parent_floater)
{
LLRect new_rect = gFloaterView->findNeighboringPosition(parent_floater, widget);
@@ -1543,7 +1482,7 @@ void LLPanelEstateInfo::onClickAddBannedAgent(void* user_data)
{
LLSD args;
args["MAX_BANNED"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
- LLNotifications::instance().add("MaxBannedAgentsOnRegion", args);
+ LLNotificationsUtil::add("MaxBannedAgentsOnRegion", args);
return;
}
accessAddCore(ESTATE_ACCESS_BANNED_AGENT_ADD, "EstateBannedAgentAdd");
@@ -1565,7 +1504,7 @@ void LLPanelEstateInfo::onClickAddEstateManager(void* user_data)
{ // Tell user they can't add more managers
LLSD args;
args["MAX_MANAGER"] = llformat("%d",ESTATE_MAX_MANAGERS);
- LLNotifications::instance().add("MaxManagersOnRegion", args);
+ LLNotificationsUtil::add("MaxManagersOnRegion", args);
}
else
{ // Go pick managers to add
@@ -1588,18 +1527,16 @@ struct LLKickFromEstateInfo
LLUUID mAgentID;
};
-void LLPanelEstateInfo::onClickKickUser(void *user_data)
+void LLPanelEstateInfo::onClickKickUser()
{
- LLPanelEstateInfo* panelp = (LLPanelEstateInfo*)user_data;
-
// this depends on the grandparent view being a floater
// in order to set up floater dependency
- LLFloater* parent_floater = gFloaterView->getParentFloater(panelp);
- LLFloater* child_floater = LLFloaterAvatarPicker::show(LLPanelEstateInfo::onKickUserCommit, user_data, FALSE, TRUE);
+ LLFloater* parent_floater = gFloaterView->getParentFloater(this);
+ LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::onKickUserCommit, this, _1, _2), FALSE, TRUE);
parent_floater->addDependentFloater(child_floater);
}
-void LLPanelEstateInfo::onKickUserCommit(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* userdata)
+void LLPanelEstateInfo::onKickUserCommit(const std::vector<std::string>& names, const std::vector<LLUUID>& ids)
{
if (names.empty() || ids.empty()) return;
@@ -1610,12 +1547,9 @@ void LLPanelEstateInfo::onKickUserCommit(const std::vector<std::string>& names,
return;
}
- LLPanelEstateInfo* self = (LLPanelEstateInfo*)userdata;
- if(!self) return;
-
//keep track of what user they want to kick and other misc info
LLKickFromEstateInfo *kick_info = new LLKickFromEstateInfo();
- kick_info->mEstatePanelp = self;
+ kick_info->mEstatePanelp = this;
kick_info->mAgentID = ids[0];
//Bring up a confirmation dialog
@@ -1623,13 +1557,13 @@ void LLPanelEstateInfo::onKickUserCommit(const std::vector<std::string>& names,
args["EVIL_USER"] = names[0];
LLSD payload;
payload["agent_id"] = ids[0];
- LLNotifications::instance().add("EstateKickUser", args, payload, boost::bind(&LLPanelEstateInfo::kickUserConfirm, self, _1, _2));
+ LLNotificationsUtil::add("EstateKickUser", args, payload, boost::bind(&LLPanelEstateInfo::kickUserConfirm, this, _1, _2));
}
bool LLPanelEstateInfo::kickUserConfirm(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
switch(option)
{
case 0:
@@ -1656,26 +1590,29 @@ bool LLPanelEstateInfo::kickUserConfirm(const LLSD& notification, const LLSD& re
std::string all_estates_text()
{
LLPanelEstateInfo* panel = LLFloaterRegionInfo::getPanelEstate();
- if (!panel) return "(error)";
+ if (!panel) return "(" + LLTrans::getString("RegionInfoError") + ")";
+ LLStringUtil::format_map_t args;
std::string owner = panel->getOwnerName();
LLViewerRegion* region = gAgent.getRegion();
if (gAgent.isGodlike())
{
- return llformat("all estates\nowned by %s", owner.c_str());
+ args["[OWNER]"] = owner.c_str();
+ return LLTrans::getString("RegionInfoAllEstatesOwnedBy", args);
}
else if (region && region->getOwner() == gAgent.getID())
{
- return "all estates you own";
+ return LLTrans::getString("RegionInfoAllEstatesYouOwn");
}
else if (region && region->isEstateManager())
{
- return llformat("all estates that\nyou manage for %s", owner.c_str());
+ args["[OWNER]"] = owner.c_str();
+ return LLTrans::getString("RegionInfoAllEstatesYouManage", args);
}
else
{
- return "(error)";
+ return "(" + LLTrans::getString("RegionInfoError") + ")";
}
}
@@ -1725,8 +1662,7 @@ struct LLEstateAccessChangeInfo
};
// Special case callback for groups, since it has different callback format than names
-// static
-void LLPanelEstateInfo::addAllowedGroup2(LLUUID id, void* user_data)
+void LLPanelEstateInfo::addAllowedGroup2(LLUUID id)
{
LLSD payload;
payload["operation"] = (S32)ESTATE_ACCESS_ALLOWED_GROUP_ADD;
@@ -1739,7 +1675,7 @@ void LLPanelEstateInfo::addAllowedGroup2(LLUUID id, void* user_data)
LLNotification::Params params("EstateAllowedGroupAdd");
params.payload(payload)
.substitutions(args)
- .functor(accessCoreConfirm);
+ .functor.function(accessCoreConfirm);
if (isLindenEstate())
{
LLNotifications::instance().forceResponse(params, 0);
@@ -1760,7 +1696,7 @@ void LLPanelEstateInfo::accessAddCore(U32 operation_flag, const std::string& dia
LLNotification::Params params("ChangeLindenAccess");
params.payload(payload)
- .functor(accessAddCore2);
+ .functor.function(accessAddCore2);
if (isLindenEstate())
{
@@ -1776,7 +1712,7 @@ void LLPanelEstateInfo::accessAddCore(U32 operation_flag, const std::string& dia
// static
bool LLPanelEstateInfo::accessAddCore2(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option != 0)
{
// abort change
@@ -1785,7 +1721,7 @@ bool LLPanelEstateInfo::accessAddCore2(const LLSD& notification, const LLSD& res
LLEstateAccessChangeInfo* change_info = new LLEstateAccessChangeInfo(notification["payload"]);
// avatar picker yes multi-select, yes close-on-select
- LLFloaterAvatarPicker::show(accessAddCore3, (void*)change_info, TRUE, TRUE);
+ LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::accessAddCore3, _1, _2, (void*)change_info), TRUE, TRUE);
return false;
}
@@ -1820,7 +1756,7 @@ void LLPanelEstateInfo::accessAddCore3(const std::vector<std::string>& names, co
args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
args["LIST_TYPE"] = "Allowed Residents";
args["NUM_EXCESS"] = llformat("%d",(ids.size()+currentCount)-ESTATE_MAX_ACCESS_IDS);
- LLNotifications::instance().add("MaxAgentOnRegionBatch", args);
+ LLNotificationsUtil::add("MaxAgentOnRegionBatch", args);
delete change_info;
return;
}
@@ -1836,7 +1772,7 @@ void LLPanelEstateInfo::accessAddCore3(const std::vector<std::string>& names, co
args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
args["LIST_TYPE"] = "Banned Residents";
args["NUM_EXCESS"] = llformat("%d",(ids.size()+currentCount)-ESTATE_MAX_ACCESS_IDS);
- LLNotifications::instance().add("MaxAgentOnRegionBatch", args);
+ LLNotificationsUtil::add("MaxAgentOnRegionBatch", args);
delete change_info;
return;
}
@@ -1848,7 +1784,7 @@ void LLPanelEstateInfo::accessAddCore3(const std::vector<std::string>& names, co
LLNotification::Params params(change_info->mDialogName);
params.substitutions(args)
.payload(change_info->asLLSD())
- .functor(accessCoreConfirm);
+ .functor.function(accessCoreConfirm);
if (isLindenEstate())
{
@@ -1888,7 +1824,7 @@ void LLPanelEstateInfo::accessRemoveCore(U32 operation_flag, const std::string&
LLNotification::Params params("ChangeLindenAccess");
params.payload(payload)
- .functor(accessRemoveCore2);
+ .functor.function(accessRemoveCore2);
if (isLindenEstate())
{
@@ -1905,7 +1841,7 @@ void LLPanelEstateInfo::accessRemoveCore(U32 operation_flag, const std::string&
// static
bool LLPanelEstateInfo::accessRemoveCore2(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option != 0)
{
// abort
@@ -1922,7 +1858,7 @@ bool LLPanelEstateInfo::accessRemoveCore2(const LLSD& notification, const LLSD&
{
LLSD args;
args["ALL_ESTATES"] = all_estates_text();
- LLNotifications::instance().add(notification["payload"]["dialog_name"],
+ LLNotificationsUtil::add(notification["payload"]["dialog_name"],
args,
notification["payload"],
accessCoreConfirm);
@@ -1935,7 +1871,7 @@ bool LLPanelEstateInfo::accessRemoveCore2(const LLSD& notification, const LLSD&
// static
bool LLPanelEstateInfo::accessCoreConfirm(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
const U32 originalFlags = (U32)notification["payload"]["operation"].asInteger();
LLViewerRegion* region = gAgent.getRegion();
@@ -1954,7 +1890,7 @@ bool LLPanelEstateInfo::accessCoreConfirm(const LLSD& notification, const LLSD&
if (((U32)notification["payload"]["operation"].asInteger() & ESTATE_ACCESS_BANNED_AGENT_ADD)
&& region && (region->getOwner() == id))
{
- LLNotifications::instance().add("OwnerCanNotBeDenied");
+ LLNotificationsUtil::add("OwnerCanNotBeDenied");
break;
}
switch(option)
@@ -2050,11 +1986,6 @@ void LLPanelEstateInfo::updateControls(LLViewerRegion* region)
childSetEnabled("remove_banned_avatar_btn", god || owner || manager);
childSetEnabled("message_estate_btn", god || owner || manager);
childSetEnabled("kick_user_from_estate_btn", god || owner || manager);
-#if ELAR_ENABLED
- childSetEnabled("abuse_email_address", god || owner || manager);
-#else
- childSetEnabled("abuse_email_address", false);
-#endif
// estate managers can't add estate managers
childSetEnabled("add_estate_manager_btn", god || owner);
@@ -2120,29 +2051,13 @@ BOOL LLPanelEstateInfo::postBuild()
initCtrl("limit_payment");
initCtrl("limit_age_verified");
initCtrl("voice_chat_check");
- childSetCommitCallback("abuse_email_address", onChangeAnything, this);
- childSetKeystrokeCallback("abuse_email_address", onChangeText, this);
-
- initHelpBtn("estate_manager_help", "HelpEstateEstateManager");
- initHelpBtn("use_global_time_help", "HelpEstateUseGlobalTime");
- initHelpBtn("fixed_sun_help", "HelpEstateFixedSun");
- initHelpBtn("WLEditSkyHelp", "HelpEditSky");
- initHelpBtn("WLEditDayCycleHelp", "HelpEditDayCycle");
-
- initHelpBtn("externally_visible_help", "HelpEstateExternallyVisible");
- initHelpBtn("allow_direct_teleport_help", "HelpEstateAllowDirectTeleport");
- initHelpBtn("allow_resident_help", "HelpEstateAllowResident");
- initHelpBtn("allow_group_help", "HelpEstateAllowGroup");
- initHelpBtn("ban_resident_help", "HelpEstateBanResident");
- initHelpBtn("abuse_email_address_help", "HelpEstateAbuseEmailAddress");
- initHelpBtn("voice_chat_help", "HelpEstateVoiceChat");
// set up the use global time checkbox
- childSetCommitCallback("use_global_time_check", onChangeUseGlobalTime, this);
- childSetCommitCallback("fixed_sun_check", onChangeFixedSun, this);
- childSetCommitCallback("sun_hour_slider", onChangeChildCtrl, this);
-
- childSetCommitCallback("allowed_avatar_name_list", onChangeChildCtrl, this);
+ getChild<LLUICtrl>("use_global_time_check")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeUseGlobalTime, this));
+ getChild<LLUICtrl>("fixed_sun_check")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeFixedSun, this));
+ getChild<LLUICtrl>("sun_hour_slider")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1));
+
+ getChild<LLUICtrl>("allowed_avatar_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1));
LLNameListCtrl *avatar_name_list = getChild<LLNameListCtrl>("allowed_avatar_name_list");
if (avatar_name_list)
{
@@ -2153,7 +2068,7 @@ BOOL LLPanelEstateInfo::postBuild()
childSetAction("add_allowed_avatar_btn", onClickAddAllowedAgent, this);
childSetAction("remove_allowed_avatar_btn", onClickRemoveAllowedAgent, this);
- childSetCommitCallback("allowed_group_name_list", onChangeChildCtrl, this);
+ getChild<LLUICtrl>("allowed_group_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1));
LLNameListCtrl* group_name_list = getChild<LLNameListCtrl>("allowed_group_name_list");
if (group_name_list)
{
@@ -2161,10 +2076,10 @@ BOOL LLPanelEstateInfo::postBuild()
group_name_list->setMaxItemCount(ESTATE_MAX_ACCESS_IDS);
}
- childSetAction("add_allowed_group_btn", onClickAddAllowedGroup, this);
+ getChild<LLUICtrl>("add_allowed_group_btn")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onClickAddAllowedGroup, this));
childSetAction("remove_allowed_group_btn", onClickRemoveAllowedGroup, this);
- childSetCommitCallback("banned_avatar_name_list", onChangeChildCtrl, this);
+ getChild<LLUICtrl>("banned_avatar_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1));
LLNameListCtrl* banned_name_list = getChild<LLNameListCtrl>("banned_avatar_name_list");
if (banned_name_list)
{
@@ -2175,7 +2090,7 @@ BOOL LLPanelEstateInfo::postBuild()
childSetAction("add_banned_avatar_btn", onClickAddBannedAgent, this);
childSetAction("remove_banned_avatar_btn", onClickRemoveBannedAgent, this);
- childSetCommitCallback("estate_manager_name_list", onChangeChildCtrl, this);
+ getChild<LLUICtrl>("estate_manager_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1));
LLNameListCtrl* manager_name_list = getChild<LLNameListCtrl>("estate_manager_name_list");
if (manager_name_list)
{
@@ -2186,7 +2101,7 @@ BOOL LLPanelEstateInfo::postBuild()
childSetAction("add_estate_manager_btn", onClickAddEstateManager, this);
childSetAction("remove_estate_manager_btn", onClickRemoveEstateManager, this);
childSetAction("message_estate_btn", onClickMessageEstate, this);
- childSetAction("kick_user_from_estate_btn", onClickKickUser, this);
+ childSetAction("kick_user_from_estate_btn", boost::bind(&LLPanelEstateInfo::onClickKickUser, this));
childSetAction("WLEditSky", onClickEditSky, this);
childSetAction("WLEditDayCycle", onClickEditDayCycle, this);
@@ -2213,7 +2128,7 @@ BOOL LLPanelEstateInfo::sendUpdate()
llinfos << "LLPanelEsateInfo::sendUpdate()" << llendl;
LLNotification::Params params("ChangeLindenEstate");
- params.functor(boost::bind(&LLPanelEstateInfo::callbackChangeLindenEstate, this, _1, _2));
+ params.functor.function(boost::bind(&LLPanelEstateInfo::callbackChangeLindenEstate, this, _1, _2));
if (getEstateID() <= ESTATE_LAST_LINDEN)
{
@@ -2230,7 +2145,7 @@ BOOL LLPanelEstateInfo::sendUpdate()
bool LLPanelEstateInfo::callbackChangeLindenEstate(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
switch(option)
{
case 0:
@@ -2289,13 +2204,18 @@ void LLPanelEstateInfo::getEstateOwner()
class LLEstateChangeInfoResponder : public LLHTTPClient::Responder
{
public:
- LLEstateChangeInfoResponder(void* userdata) : mpPanel((LLPanelEstateInfo*)userdata) {};
+ LLEstateChangeInfoResponder(LLPanelEstateInfo* panel)
+ {
+ mpPanel = panel->getHandle();
+ }
// if we get a normal response, handle it here
virtual void result(const LLSD& content)
{
// refresh the panel from the database
- mpPanel->refresh();
+ LLPanelEstateInfo* panel = dynamic_cast<LLPanelEstateInfo*>(mpPanel.get());
+ if (panel)
+ panel->refresh();
}
// if we get an error response
@@ -2305,7 +2225,7 @@ public:
<< status << ": " << reason << llendl;
}
private:
- LLPanelEstateInfo* mpPanel;
+ LLHandle<LLPanel> mpPanel;
};
// tries to send estate info using a cap; returns true if it succeeded
@@ -2340,10 +2260,8 @@ bool LLPanelEstateInfo::commitEstateInfoCaps()
}
body["sun_hour"] = sun_hour;
- body["owner_abuse_email"] = childGetValue("abuse_email_address").asString();
-
// we use a responder so that we can re-get the data after committing to the database
- LLHTTPClient::post(url, body, new LLEstateChangeInfoResponder((void*)this));
+ LLHTTPClient::post(url, body, new LLEstateChangeInfoResponder(this));
return true;
}
@@ -2500,16 +2418,6 @@ void LLPanelEstateInfo::setOwnerName(const std::string& name)
childSetValue("estate_owner", LLSD(name));
}
-const std::string LLPanelEstateInfo::getAbuseEmailAddress() const
-{
- return childGetValue("abuse_email_address").asString();
-}
-
-void LLPanelEstateInfo::setAbuseEmailAddress(const std::string& address)
-{
- childSetValue("abuse_email_address", LLSD(address));
-}
-
void LLPanelEstateInfo::setAccessAllowedEnabled(bool enable_agent,
bool enable_group,
bool enable_ban)
@@ -2551,31 +2459,6 @@ void LLPanelEstateInfo::setAccessAllowedEnabled(bool enable_agent,
}
}
-// static
-void LLPanelEstateInfo::callbackCacheName(
- const LLUUID& id,
- const std::string& first,
- const std::string& last,
- BOOL is_group,
- void*)
-{
- LLPanelEstateInfo* self = LLFloaterRegionInfo::getPanelEstate();
- if (!self) return;
-
- std::string name;
-
- if (id.isNull())
- {
- name = "(none)";
- }
- else
- {
- name = first + " " + last;
- }
-
- self->setOwnerName(name);
-}
-
void LLPanelEstateInfo::clearAccessLists()
{
LLNameListCtrl* name_list = getChild<LLNameListCtrl>("allowed_avatar_name_list");
@@ -2639,12 +2522,12 @@ BOOL LLPanelEstateInfo::checkSunHourSlider(LLUICtrl* child_ctrl)
void LLPanelEstateInfo::onClickMessageEstate(void* userdata)
{
llinfos << "LLPanelEstateInfo::onClickMessageEstate" << llendl;
- LLNotifications::instance().add("MessageEstate", LLSD(), LLSD(), boost::bind(&LLPanelEstateInfo::onMessageCommit, (LLPanelEstateInfo*)userdata, _1, _2));
+ LLNotificationsUtil::add("MessageEstate", LLSD(), LLSD(), boost::bind(&LLPanelEstateInfo::onMessageCommit, (LLPanelEstateInfo*)userdata, _1, _2));
}
bool LLPanelEstateInfo::onMessageCommit(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
std::string text = response["message"].asString();
if(option != 0) return false;
if(text.empty()) return false;
@@ -2652,7 +2535,7 @@ bool LLPanelEstateInfo::onMessageCommit(const LLSD& notification, const LLSD& re
strings_t strings;
//integers_t integers;
std::string name;
- gAgent.buildFullname(name);
+ LLAgentUI::buildFullname(name);
strings.push_back(strings_t::value_type(name));
strings.push_back(strings_t::value_type(text));
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
@@ -2734,12 +2617,10 @@ bool LLPanelEstateCovenant::estateUpdate(LLMessageSystem* msg)
// virtual
BOOL LLPanelEstateCovenant::postBuild()
{
- initHelpBtn("covenant_help", "HelpEstateCovenant");
mEstateNameText = getChild<LLTextBox>("estate_name_text");
mEstateOwnerText = getChild<LLTextBox>("estate_owner_text");
mLastModifiedText = getChild<LLTextBox>("covenant_timestamp_text");
mEditor = getChild<LLViewerTextEditor>("covenant_editor");
- if (mEditor) mEditor->setHandleEditKeysDirectly(TRUE);
LLButton* reset_button = getChild<LLButton>("reset_covenant");
reset_button->setEnabled(gAgent.canManageEstate());
reset_button->setClickedCallback(LLPanelEstateCovenant::resetCovenantID, NULL);
@@ -2775,7 +2656,7 @@ BOOL LLPanelEstateCovenant::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop
{
LLSD payload;
payload["item_id"] = item->getUUID();
- LLNotifications::instance().add("EstateChangeCovenant", LLSD(), payload,
+ LLNotificationsUtil::add("EstateChangeCovenant", LLSD(), payload,
LLPanelEstateCovenant::confirmChangeCovenantCallback);
}
break;
@@ -2790,7 +2671,7 @@ BOOL LLPanelEstateCovenant::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop
// static
bool LLPanelEstateCovenant::confirmChangeCovenantCallback(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLInventoryItem* item = gInventory.getItem(notification["payload"]["item_id"].asUUID());
LLPanelEstateCovenant* self = LLFloaterRegionInfo::getPanelCovenant();
@@ -2810,7 +2691,7 @@ bool LLPanelEstateCovenant::confirmChangeCovenantCallback(const LLSD& notificati
// static
void LLPanelEstateCovenant::resetCovenantID(void* userdata)
{
- LLNotifications::instance().add("EstateChangeCovenant", LLSD(), LLSD(), confirmResetCovenantCallback);
+ LLNotificationsUtil::add("EstateChangeCovenant", LLSD(), LLSD(), confirmResetCovenantCallback);
}
// static
@@ -2819,7 +2700,7 @@ bool LLPanelEstateCovenant::confirmResetCovenantCallback(const LLSD& notificatio
LLPanelEstateCovenant* self = LLFloaterRegionInfo::getPanelCovenant();
if (!self) return false;
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
switch(option)
{
case 0:
@@ -2852,7 +2733,7 @@ void LLPanelEstateCovenant::loadInvItem(LLInventoryItem *itemp)
else
{
mAssetStatus = ASSET_LOADED;
- setCovenantTextEditor("There is no Covenant provided for this Estate.");
+ setCovenantTextEditor(LLTrans::getString("RegionNoCovenant"));
sendChangeCovenantID(LLUUID::null);
}
}
@@ -2883,7 +2764,7 @@ void LLPanelEstateCovenant::onLoadComplete(LLVFS *vfs,
if( !panelp->mEditor->importBuffer( &buffer[0], file_length+1 ) )
{
llwarns << "Problem importing estate covenant." << llendl;
- LLNotifications::instance().add("ProblemImportingEstateCovenant");
+ LLNotificationsUtil::add("ProblemImportingEstateCovenant");
}
else
{
@@ -2903,15 +2784,15 @@ void LLPanelEstateCovenant::onLoadComplete(LLVFS *vfs,
if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
LL_ERR_FILE_EMPTY == status)
{
- LLNotifications::instance().add("MissingNotecardAssetID");
+ LLNotificationsUtil::add("MissingNotecardAssetID");
}
else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
{
- LLNotifications::instance().add("NotAllowedToViewNotecard");
+ LLNotificationsUtil::add("NotAllowedToViewNotecard");
}
else
{
- LLNotifications::instance().add("UnableToLoadNotecardAsset");
+ LLNotificationsUtil::add("UnableToLoadNotecardAsset");
}
llwarns << "Problem loading notecard: " << status << llendl;
@@ -2953,7 +2834,7 @@ BOOL LLPanelEstateCovenant::sendUpdate()
return TRUE;
}
-const std::string& LLPanelEstateCovenant::getEstateName() const
+std::string LLPanelEstateCovenant::getEstateName() const
{
return mEstateNameText->getText();
}
@@ -3004,7 +2885,7 @@ void LLPanelEstateCovenant::updateEstateOwnerName(const std::string& name)
}
}
-const std::string& LLPanelEstateCovenant::getOwnerName() const
+std::string LLPanelEstateCovenant::getOwnerName() const
{
return mEstateOwnerText->getText();
}
@@ -3045,25 +2926,14 @@ bool LLDispatchEstateUpdateInfo::operator()(
std::string estate_name = strings[0].c_str(); // preserve c_str() call!
panel->setEstateName(estate_name);
-#if ELAR_ENABLED
- if (strings.size() > 9)
- {
- std::string abuse_email = strings[9].c_str(); // preserve c_str() call!
- panel->setAbuseEmailAddress(abuse_email);
- }
- else
-#endif
- {
- panel->setAbuseEmailAddress(panel->getString("email_unsupported"));
- }
-
LLViewerRegion* regionp = gAgent.getRegion();
LLUUID owner_id(strings[1]);
regionp->setOwner(owner_id);
// Update estate owner name in UI
- const BOOL is_group = FALSE;
- gCacheName->get(owner_id, is_group, LLPanelEstateInfo::callbackCacheName);
+ std::string owner_name =
+ LLSLURL::buildCommand("agent", owner_id, "inspect");
+ panel->setOwnerName(owner_name);
U32 estate_id = strtoul(strings[2].c_str(), NULL, 10);
panel->setEstateID(estate_id);
@@ -3162,9 +3032,10 @@ bool LLDispatchSetEstateAccess::operator()(
totalAllowedAgents += allowed_agent_name_list->getItemCount();
}
- std::string msg = llformat("Allowed residents: (%d, max %d)",
- totalAllowedAgents,
- ESTATE_MAX_ACCESS_IDS);
+ LLStringUtil::format_map_t args;
+ args["[ALLOWEDAGENTS]"] = llformat ("%d", totalAllowedAgents);
+ args["[MAXACCESS]"] = llformat ("%d", ESTATE_MAX_ACCESS_IDS);
+ std::string msg = LLTrans::getString("RegionInfoAllowedResidents", args);
panel->childSetValue("allow_resident_label", LLSD(msg));
if (allowed_agent_name_list)
@@ -3186,9 +3057,10 @@ bool LLDispatchSetEstateAccess::operator()(
LLNameListCtrl* allowed_group_name_list;
allowed_group_name_list = panel->getChild<LLNameListCtrl>("allowed_group_name_list");
- std::string msg = llformat("Allowed groups: (%d, max %d)",
- num_allowed_groups,
- (S32) ESTATE_MAX_GROUP_IDS);
+ LLStringUtil::format_map_t args;
+ args["[ALLOWEDGROUPS]"] = llformat ("%d", num_allowed_groups);
+ args["[MAXACCESS]"] = llformat ("%d", ESTATE_MAX_GROUP_IDS);
+ std::string msg = LLTrans::getString("RegionInfoAllowedGroups", args);
panel->childSetValue("allow_group_label", LLSD(msg));
if (allowed_group_name_list)
diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h
index 806d1f57d6..8d315bdb78 100644
--- a/indra/newview/llfloaterregioninfo.h
+++ b/indra/newview/llfloaterregioninfo.h
@@ -35,9 +35,12 @@
#define LL_LLFLOATERREGIONINFO_H
#include <vector>
+#include "llassettype.h"
#include "llfloater.h"
+#include "llhost.h"
#include "llpanel.h"
+class LLDispatcher;
class LLLineEditor;
class LLMessageSystem;
class LLPanelRegionInfo;
@@ -51,6 +54,7 @@ class LLNameListCtrl;
class LLSliderCtrl;
class LLSpinCtrl;
class LLTextBox;
+class LLVFS;
class LLPanelRegionGeneralInfo;
class LLPanelRegionDebugInfo;
@@ -59,13 +63,13 @@ class LLPanelRegionTerrainInfo;
class LLPanelEstateInfo;
class LLPanelEstateCovenant;
-class LLFloaterRegionInfo : public LLFloater, public LLFloaterSingleton<LLFloaterRegionInfo>
+class LLFloaterRegionInfo : public LLFloater
{
- friend class LLUISingleton<LLFloaterRegionInfo, VisibilityPolicy<LLFloater> >;
+ friend class LLFloaterReg;
public:
- ~LLFloaterRegionInfo();
- /*virtual*/ void onOpen();
+
+ /*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ BOOL postBuild();
static void processEstateOwnerRequest(LLMessageSystem* msg, void**);
@@ -84,10 +88,14 @@ public:
// from LLPanel
virtual void refresh();
- static void requestRegionInfo();
+ void requestRegionInfo();
-protected:
+private:
+
LLFloaterRegionInfo(const LLSD& seed);
+ ~LLFloaterRegionInfo();
+
+protected:
void refreshFromRegion(LLViewerRegion* region);
// member data
@@ -103,10 +111,11 @@ protected:
class LLPanelRegionInfo : public LLPanel
{
public:
- LLPanelRegionInfo() : LLPanel(std::string("Region Info Panel")) {}
- static void onBtnSet(void* user_data);
- static void onChangeChildCtrl(LLUICtrl* ctrl, void* user_data);
- static void onChangeAnything(LLUICtrl* ctrl, void* user_data);
+ LLPanelRegionInfo();
+
+ void onBtnSet();
+ void onChangeChildCtrl(LLUICtrl* ctrl);
+ void onChangeAnything();
static void onChangeText(LLLineEditor* caller, void* user_data);
virtual bool refreshFromRegion(LLViewerRegion* region);
@@ -118,12 +127,10 @@ public:
void enableButton(const std::string& btn_name, BOOL enable = TRUE);
void disableButton(const std::string& btn_name);
+ void onClickManageTelehub();
+
protected:
void initCtrl(const std::string& name);
- void initHelpBtn(const std::string& name, const std::string& xml_alert);
-
- // Callback for all help buttons, data is name of XML alert to show.
- static void onClickHelp(void* data);
// Returns TRUE if update sent and apply button should be
// disabled.
@@ -147,6 +154,7 @@ protected:
class LLPanelRegionGeneralInfo : public LLPanelRegionInfo
{
+
public:
LLPanelRegionGeneralInfo()
: LLPanelRegionInfo() {}
@@ -156,16 +164,16 @@ public:
// LLPanel
virtual BOOL postBuild();
+
protected:
virtual BOOL sendUpdate();
-
- static void onClickKick(void* userdata);
- static void onKickCommit(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* userdata);
+ void onClickKick();
+ void onKickCommit(const std::vector<std::string>& names, const std::vector<LLUUID>& ids);
static void onClickKickAll(void* userdata);
bool onKickAllCommit(const LLSD& notification, const LLSD& response);
static void onClickMessage(void* userdata);
bool onMessageCommit(const LLSD& notification, const LLSD& response);
- static void onClickManageTelehub(void* data);
+
};
/////////////////////////////////////////////////////////////////////////////
@@ -184,8 +192,8 @@ public:
protected:
virtual BOOL sendUpdate();
- static void onClickChooseAvatar(void*);
- static void callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data);
+ void onClickChooseAvatar();
+ void callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids);
static void onClickReturn(void *);
bool callbackReturn(const LLSD& notification, const LLSD& response);
static void onClickTopColliders(void*);
@@ -234,9 +242,9 @@ public:
protected:
virtual BOOL sendUpdate();
- static void onChangeUseEstateTime(LLUICtrl* ctrl, void* user_data);
- static void onChangeFixedSun(LLUICtrl* ctrl, void* user_data);
- static void onChangeSunHour(LLUICtrl* ctrl, void*);
+ void onChangeUseEstateTime();
+ void onChangeFixedSun();
+ void onChangeSunHour();
static void onClickDownloadRaw(void*);
static void onClickUploadRaw(void*);
@@ -251,8 +259,8 @@ class LLPanelEstateInfo : public LLPanelRegionInfo
public:
static void initDispatch(LLDispatcher& dispatch);
- static void onChangeFixedSun(LLUICtrl* ctrl, void* user_data);
- static void onChangeUseGlobalTime(LLUICtrl* ctrl, void* user_data);
+ void onChangeFixedSun();
+ void onChangeUseGlobalTime();
static void onClickEditSky(void* userdata);
static void onClickEditSkyHelp(void* userdata);
@@ -261,17 +269,17 @@ public:
static void onClickAddAllowedAgent(void* user_data);
static void onClickRemoveAllowedAgent(void* user_data);
- static void onClickAddAllowedGroup(void* user_data);
+ void onClickAddAllowedGroup();
static void onClickRemoveAllowedGroup(void* user_data);
static void onClickAddBannedAgent(void* user_data);
static void onClickRemoveBannedAgent(void* user_data);
static void onClickAddEstateManager(void* user_data);
static void onClickRemoveEstateManager(void* user_data);
- static void onClickKickUser(void* userdata);
+ void onClickKickUser();
// Group picker callback is different, can't use core methods below
bool addAllowedGroup(const LLSD& notification, const LLSD& response);
- static void addAllowedGroup2(LLUUID id, void* data);
+ void addAllowedGroup2(LLUUID id);
// Core methods for all above add/remove button clicks
static void accessAddCore(U32 operation_flag, const std::string& dialog_name);
@@ -288,7 +296,7 @@ public:
// Send the actual EstateOwnerRequest "estateaccessdelta" message
static void sendEstateAccessDelta(U32 flags, const LLUUID& agent_id);
- static void onKickUserCommit(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* userdata);
+ void onKickUserCommit(const std::vector<std::string>& names, const std::vector<LLUUID>& ids);
static void onClickMessageEstate(void* data);
bool onMessageCommit(const LLSD& notification, const LLSD& response);
@@ -326,22 +334,10 @@ public:
const std::string getOwnerName() const;
void setOwnerName(const std::string& name);
- const std::string getAbuseEmailAddress() const;
- void setAbuseEmailAddress(const std::string& address);
-
// If visible from mainland, allowed agent and allowed groups
// are ignored, so must disable UI.
void setAccessAllowedEnabled(bool enable_agent, bool enable_group, bool enable_ban);
- // this must have the same function signature as
- // llmessage/llcachename.h:LLCacheNameCallback
- static void callbackCacheName(
- const LLUUID& id,
- const std::string& first,
- const std::string& last,
- BOOL is_group,
- void*);
-
protected:
virtual BOOL sendUpdate();
// confirmation dialog callback
@@ -396,9 +392,9 @@ public:
const LLUUID& getCovenantID() const { return mCovenantID; }
void setCovenantID(const LLUUID& id) { mCovenantID = id; }
- const std::string& getEstateName() const;
+ std::string getEstateName() const;
void setEstateName(const std::string& name);
- const std::string& getOwnerName() const;
+ std::string getOwnerName() const;
void setOwnerName(const std::string& name);
void setCovenantTextEditor(const std::string& text);
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index 412494eeb3..4a1eb51dbe 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -1,6 +1,6 @@
/**
* @file llfloaterreporter.cpp
- * @brief Bug and abuse reports.
+ * @brief Abuse reports.
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
@@ -32,35 +32,32 @@
#include "llviewerprecompiledheaders.h"
-#include <sstream>
-
// self include
#include "llfloaterreporter.h"
+#include <sstream>
+
// linden library includes
#include "llassetstorage.h"
-#include "llcachename.h"
#include "llfontgl.h"
-#include "llgl.h" // for renderer
+#include "llimagej2c.h"
#include "llinventory.h"
+#include "llnotificationsutil.h"
#include "llstring.h"
#include "llsys.h"
-#include "llversionviewer.h"
+#include "llvfile.h"
+#include "llvfs.h"
+#include "mean_collision_data.h"
#include "message.h"
#include "v3math.h"
// viewer project includes
#include "llagent.h"
#include "llbutton.h"
-#include "llcheckboxctrl.h"
-#include "llinventoryview.h"
-#include "lllineeditor.h"
+#include "llfloaterreg.h"
#include "lltexturectrl.h"
#include "llscrolllistctrl.h"
-#include "llimview.h"
-#include "lltextbox.h"
#include "lldispatcher.h"
-#include "llviewertexteditor.h"
#include "llviewerobject.h"
#include "llviewerregion.h"
#include "llcombobox.h"
@@ -72,18 +69,20 @@
#include "lltoolobjpicker.h"
#include "lltoolmgr.h"
#include "llresourcedata.h" // for LLResourceData
+#include "llslurl.h"
#include "llviewerwindow.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llworldmap.h"
#include "llfilepicker.h"
#include "llfloateravatarpicker.h"
#include "lldir.h"
#include "llselectmgr.h"
-#include "llviewerbuild.h"
+#include "llversioninfo.h"
#include "lluictrlfactory.h"
#include "llviewernetwork.h"
#include "llassetuploadresponders.h"
+#include "llagentui.h"
const U32 INCLUDE_SCREENSHOT = 0x01 << 0;
@@ -91,68 +90,41 @@ const U32 INCLUDE_SCREENSHOT = 0x01 << 0;
// Globals
//-----------------------------------------------------------------------------
-// this map keeps track of current reporter instances
-// there can only be one instance of each reporter type
-LLMap< EReportType, LLFloaterReporter* > gReporterInstances;
-
-// keeps track of where email is going to - global to avoid a pile
-// of static/non-static access outside my control
-namespace {
- static BOOL gEmailToEstateOwner = FALSE;
- static BOOL gDialogVisible = FALSE;
-}
-
//-----------------------------------------------------------------------------
// Member functions
//-----------------------------------------------------------------------------
-LLFloaterReporter::LLFloaterReporter(
- const std::string& name,
- const LLRect& rect,
- const std::string& title,
- EReportType report_type)
- :
- LLFloater(name, rect, title),
- mReportType(report_type),
+
+LLFloaterReporter::LLFloaterReporter(const LLSD& key)
+: LLFloater(key),
+ mReportType(COMPLAINT_REPORT),
mObjectID(),
mScreenID(),
mAbuserID(),
+ mOwnerName(),
mDeselectOnClose( FALSE ),
mPicking( FALSE),
mPosition(),
mCopyrightWarningSeen( FALSE ),
mResourceDatap(new LLResourceData())
{
- if (report_type == BUG_REPORT)
- {
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_report_bug.xml");
- }
- else
- {
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_report_abuse.xml");
- }
-
- childSetText("abuse_location_edit", gAgent.getSLURL() );
-
- LLButton* pick_btn = getChild<LLButton>("pick_btn");
- if (pick_btn)
- {
- // XUI: Why aren't these in viewerart.ini?
- pick_btn->setImages( std::string("UIImgFaceUUID"),
- std::string("UIImgFaceSelectedUUID") );
- childSetAction("pick_btn", onClickObjPicker, this);
- }
+ //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_report_abuse.xml");
+}
- if (report_type != BUG_REPORT)
+// static
+void LLFloaterReporter::processRegionInfo(LLMessageSystem* msg)
+{
+ U32 region_flags;
+ msg->getU32("RegionInfo", "RegionFlags", region_flags);
+
+ if ( LLFloaterReg::instanceVisible("reporter") )
{
- // abuser name is selected from a list
- LLLineEditor* le = getChild<LLLineEditor>("abuser_name_edit");
- le->setEnabled( FALSE );
- }
-
- childSetAction("select_abuser", onClickSelectAbuser, this);
-
- childSetAction("send_btn", onClickSend, this);
- childSetAction("cancel_btn", onClickCancel, this);
+ LLNotificationsUtil::add("HelpReportAbuseEmailLL");
+ };
+}
+// virtual
+BOOL LLFloaterReporter::postBuild()
+{
+ childSetText("abuse_location_edit", LLAgentUI::buildSLURL());
enableControls(TRUE);
@@ -161,12 +133,11 @@ LLFloaterReporter::LLFloaterReporter(
LLViewerRegion *regionp = gAgent.getRegion();
if (regionp)
{
+ childSetText("sim_field", regionp->getName());
pos -= regionp->getOriginGlobal();
}
setPosBox(pos);
- gReporterInstances.addData(report_type, this);
-
// Take a screenshot, but don't draw this floater.
setVisible(FALSE);
takeScreenshot();
@@ -175,49 +146,49 @@ LLFloaterReporter::LLFloaterReporter(
// Default text to be blank
childSetText("object_name", LLStringUtil::null);
childSetText("owner_name", LLStringUtil::null);
+ mOwnerName = LLStringUtil::null;
childSetFocus("summary_edit");
mDefaultSummary = childGetText("details_edit");
- gDialogVisible = TRUE;
+ // send a message and ask for information about this region -
+ // result comes back in processRegionInfo(..)
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessage("RequestRegionInfo");
+ msg->nextBlock("AgentData");
+ msg->addUUID("AgentID", gAgent.getID());
+ msg->addUUID("SessionID", gAgent.getSessionID());
+ gAgent.sendReliableMessage();
+
+
+ // abuser name is selected from a list
+ LLUICtrl* le = getChild<LLUICtrl>("abuser_name_edit");
+ le->setEnabled( false );
- // only request details for abuse reports (not BUG reports)
- if (report_type != BUG_REPORT)
- {
- // send a message and ask for information about this region -
- // result comes back in processRegionInfo(..)
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessage("RequestRegionInfo");
- msg->nextBlock("AgentData");
- msg->addUUID("AgentID", gAgent.getID());
- msg->addUUID("SessionID", gAgent.getSessionID());
- gAgent.sendReliableMessage();
- };
-}
+ setPosBox((LLVector3d)mPosition.getValue());
+ LLButton* pick_btn = getChild<LLButton>("pick_btn");
+ pick_btn->setImages(std::string("tool_face.tga"),
+ std::string("tool_face_active.tga") );
+ childSetAction("pick_btn", onClickObjPicker, this);
-// static
-void LLFloaterReporter::processRegionInfo(LLMessageSystem* msg)
-{
- U32 region_flags;
- msg->getU32("RegionInfo", "RegionFlags", region_flags);
- gEmailToEstateOwner = ( region_flags & REGION_FLAGS_ABUSE_EMAIL_TO_ESTATE_OWNER );
+ childSetAction("select_abuser", boost::bind(&LLFloaterReporter::onClickSelectAbuser, this));
- if ( gDialogVisible )
- {
- if ( gEmailToEstateOwner )
- {
- LLNotifications::instance().add("HelpReportAbuseEmailEO");
- }
- else
- LLNotifications::instance().add("HelpReportAbuseEmailLL");
- };
-}
+ childSetAction("send_btn", onClickSend, this);
+ childSetAction("cancel_btn", onClickCancel, this);
+
+ // grab the user's name
+ std::string fullname;
+ LLAgentUI::buildFullname(fullname);
+ childSetText("reporter_field", fullname);
+
+ center();
+ return TRUE;
+}
// virtual
LLFloaterReporter::~LLFloaterReporter()
{
- gReporterInstances.removeData(mReportType);
// child views automatically deleted
mObjectID = LLUUID::null;
@@ -232,24 +203,12 @@ LLFloaterReporter::~LLFloaterReporter()
mMCDList.clear();
delete mResourceDatap;
- gDialogVisible = FALSE;
}
// virtual
void LLFloaterReporter::draw()
{
- // this is set by a static callback sometime after the dialog is created.
- // Only disable screenshot for abuse reports to estate owners - bug reports always
- // allow screenshots to be taken.
- if ( gEmailToEstateOwner && ( mReportType != BUG_REPORT ) )
- {
- childSetValue("screen_check", FALSE );
- childSetEnabled("screen_check", FALSE );
- }
- else
- {
- childSetEnabled("screen_check", TRUE );
- }
+ childSetEnabled("screen_check", TRUE );
LLFloater::draw();
}
@@ -257,11 +216,7 @@ void LLFloaterReporter::draw()
void LLFloaterReporter::enableControls(BOOL enable)
{
childSetEnabled("category_combo", enable);
- // bug reports never include the chat history
- if (mReportType != BUG_REPORT)
- {
- childSetEnabled("chat_check", enable);
- }
+ childSetEnabled("chat_check", enable);
childSetEnabled("screen_check", enable);
childDisable("screenshot");
childSetEnabled("pick_btn", enable);
@@ -322,17 +277,15 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
{
object_owner.append("Unknown");
}
- childSetText("object_name", object_owner);
- childSetText("owner_name", object_owner);
- childSetText("abuser_name_edit", object_owner);
- mAbuserID = object_id;
+
+ setFromAvatar(object_id, object_owner);
}
else
{
// we have to query the simulator for information
// about this object
LLMessageSystem* msg = gMessageSystem;
- U32 request_flags = (mReportType == BUG_REPORT) ? BUG_REPORT_REQUEST : COMPLAINT_REPORT_REQUEST;
+ U32 request_flags = COMPLAINT_REPORT_REQUEST;
msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
@@ -347,31 +300,32 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
}
}
-
-// static
-void LLFloaterReporter::onClickSelectAbuser(void *userdata)
+void LLFloaterReporter::onClickSelectAbuser()
{
- LLFloaterReporter *self = (LLFloaterReporter *)userdata;
-
- gFloaterView->getParentFloater(self)->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarID, userdata, FALSE, TRUE ));
+ gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLFloaterReporter::callbackAvatarID, this, _1, _2), FALSE, TRUE ));
}
-// static
-void LLFloaterReporter::callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data)
+void LLFloaterReporter::callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids)
{
- LLFloaterReporter* self = (LLFloaterReporter*) data;
-
if (ids.empty() || names.empty()) return;
- // this should never be called in a bug report but here for safety.
- if ( self->mReportType != BUG_REPORT )
- {
- self->childSetText("abuser_name_edit", names[0] );
-
- self->mAbuserID = ids[0];
+ childSetText("abuser_name_edit", names[0] );
- self->refresh();
- };
+ mAbuserID = ids[0];
+
+ refresh();
+
+}
+
+void LLFloaterReporter::setFromAvatar(const LLUUID& avatar_id, const std::string& avatar_name)
+{
+ mAbuserID = mObjectID = avatar_id;
+ mOwnerName = avatar_name;
+
+ std::string avatar_link = LLSLURL::buildCommand("agent", mObjectID, "inspect");
+ childSetText("owner_name", avatar_link);
+ childSetText("object_name", avatar_name);
+ childSetText("abuser_name_edit", avatar_name);
}
// static
@@ -386,9 +340,7 @@ void LLFloaterReporter::onClickSend(void *userdata)
if(self->validateReport())
{
- // only show copyright alert for abuse reports
- if ( self->mReportType != BUG_REPORT )
- {
+
const int IP_CONTENT_REMOVAL = 66;
const int IP_PERMISSONS_EXPLOIT = 37;
LLComboBox* combo = self->getChild<LLComboBox>( "category_combo");
@@ -406,7 +358,7 @@ void LLFloaterReporter::onClickSend(void *userdata)
category_value == IP_CONTENT_REMOVAL ||
category_value == IP_PERMISSONS_EXPLOIT)
{
- LLNotifications::instance().add("HelpReportAbuseContainsCopyright");
+ LLNotificationsUtil::add("HelpReportAbuseContainsCopyright");
self->mCopyrightWarningSeen = TRUE;
return;
}
@@ -415,10 +367,10 @@ void LLFloaterReporter::onClickSend(void *userdata)
{
// IP_CONTENT_REMOVAL *always* shows the dialog -
// ergo you can never send that abuse report type.
- LLNotifications::instance().add("HelpReportAbuseContainsCopyright");
+ LLNotificationsUtil::add("HelpReportAbuseContainsCopyright");
return;
}
- }
+
LLUploadDialog::modalUploadDialog("Uploading...\n\nReport");
// *TODO don't upload image if checkbox isn't checked
@@ -427,7 +379,7 @@ void LLFloaterReporter::onClickSend(void *userdata)
if(!url.empty() || !sshot_url.empty())
{
self->sendReportViaCaps(url, sshot_url, self->gatherReport());
- self->close();
+ self->closeFloater();
}
else
{
@@ -442,7 +394,7 @@ void LLFloaterReporter::onClickSend(void *userdata)
{
self->sendReportViaLegacy(self->gatherReport());
LLUploadDialog::modalUploadFinished();
- self->close();
+ self->closeFloater();
}
}
}
@@ -461,7 +413,7 @@ void LLFloaterReporter::onClickCancel(void *userdata)
{
closePickTool(self);
}
- self->close();
+ self->closeFloater();
}
@@ -474,6 +426,7 @@ void LLFloaterReporter::onClickObjPicker(void *userdata)
self->mPicking = TRUE;
self->childSetText("object_name", LLStringUtil::null);
self->childSetText("owner_name", LLStringUtil::null);
+ self->mOwnerName = LLStringUtil::null;
LLButton* pick_btn = self->getChild<LLButton>("pick_btn");
if (pick_btn) pick_btn->setToggleState(TRUE);
}
@@ -497,107 +450,63 @@ void LLFloaterReporter::closePickTool(void *userdata)
// static
void LLFloaterReporter::showFromMenu(EReportType report_type)
{
- if (gReporterInstances.checkData(report_type))
+ if (COMPLAINT_REPORT != report_type)
{
- // ...bring that window to front
- LLFloaterReporter *f = gReporterInstances.getData(report_type);
- f->open(); /* Flawfinder: ignore */
+ llwarns << "Unknown LLViewerReporter type : " << report_type << llendl;
+ return;
}
- else
+
+ LLFloaterReporter* f = LLFloaterReg::showTypedInstance<LLFloaterReporter>("reporter", LLSD());
+ if (f)
{
- LLFloaterReporter *f;
- if (BUG_REPORT == report_type)
- {
- f = LLFloaterReporter::createNewBugReporter();
- }
- else if (COMPLAINT_REPORT == report_type)
- {
- f = LLFloaterReporter::createNewAbuseReporter();
- }
- else
- {
- llwarns << "Unknown LLViewerReporter type : " << report_type << llendl;
- return;
- }
-
- f->center();
-
- if (report_type == BUG_REPORT)
- {
- LLNotifications::instance().add("HelpReportBug");
- }
- else
- {
- // popup for abuse reports is triggered elsewhere
- }
-
- // grab the user's name
- std::string fullname;
- gAgent.buildFullname(fullname);
- f->childSetText("reporter_field", fullname);
+ f->setReportType(report_type);
}
}
-
// static
-void LLFloaterReporter::showFromObject(const LLUUID& object_id)
+void LLFloaterReporter::show(const LLUUID& object_id, const std::string& avatar_name)
{
- LLFloaterReporter* f = createNewAbuseReporter();
- f->center();
- f->setFocus(TRUE);
+ LLFloaterReporter* f = LLFloaterReg::showTypedInstance<LLFloaterReporter>("reporter");
// grab the user's name
std::string fullname;
- gAgent.buildFullname(fullname);
+ LLAgentUI::buildFullname(fullname);
f->childSetText("reporter_field", fullname);
- // Request info for this object
- f->getObjectInfo(object_id);
+ if (avatar_name.empty())
+ // Request info for this object
+ f->getObjectInfo(object_id);
+ else
+ f->setFromAvatar(object_id, avatar_name);
// Need to deselect on close
f->mDeselectOnClose = TRUE;
- f->open(); /* Flawfinder: ignore */
+ f->openFloater();
}
-// static
-LLFloaterReporter* LLFloaterReporter::getReporter(EReportType report_type)
-{
- LLFloaterReporter *self = NULL;
- if (gReporterInstances.checkData(report_type))
- {
- // ...bring that window to front
- self = gReporterInstances.getData(report_type);
- }
- return self;
-}
-
-LLFloaterReporter* LLFloaterReporter::createNewAbuseReporter()
+// static
+void LLFloaterReporter::showFromObject(const LLUUID& object_id)
{
- return new LLFloaterReporter("complaint_reporter",
- LLRect(),
- "Report Abuse",
- COMPLAINT_REPORT);
+ show(object_id);
}
-//static
-LLFloaterReporter* LLFloaterReporter::createNewBugReporter()
+// static
+void LLFloaterReporter::showFromAvatar(const LLUUID& avatar_id, const std::string avatar_name)
{
- return new LLFloaterReporter("bug_reporter",
- LLRect(),
- "Report Bug",
- BUG_REPORT);
+ show(avatar_id, avatar_name);
}
-
-
void LLFloaterReporter::setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id)
{
childSetText("object_name", object_name);
- childSetText("owner_name", owner_name);
+ std::string owner_link =
+ LLSLURL::buildCommand("agent", owner_id, "inspect");
+ childSetText("owner_name", owner_link);
childSetText("abuser_name_edit", owner_name);
mAbuserID = owner_id;
+ mOwnerName = owner_name;
}
@@ -608,55 +517,39 @@ bool LLFloaterReporter::validateReport()
U8 category = (U8)category_sd.asInteger();
if (category == 0)
{
- if ( mReportType != BUG_REPORT )
- {
- LLNotifications::instance().add("HelpReportAbuseSelectCategory");
- }
- else
- {
- LLNotifications::instance().add("HelpReportBugSelectCategory");
- }
+ LLNotificationsUtil::add("HelpReportAbuseSelectCategory");
return false;
}
- if ( mReportType != BUG_REPORT )
+
+ if ( childGetText("abuser_name_edit").empty() )
+ {
+ LLNotificationsUtil::add("HelpReportAbuseAbuserNameEmpty");
+ return false;
+ };
+
+ if ( childGetText("abuse_location_edit").empty() )
{
- if ( childGetText("abuser_name_edit").empty() )
- {
- LLNotifications::instance().add("HelpReportAbuseAbuserNameEmpty");
- return false;
- };
-
- if ( childGetText("abuse_location_edit").empty() )
- {
- LLNotifications::instance().add("HelpReportAbuseAbuserLocationEmpty");
- return false;
- };
+ LLNotificationsUtil::add("HelpReportAbuseAbuserLocationEmpty");
+ return false;
};
+ if ( childGetText("abuse_location_edit").empty() )
+ {
+ LLNotificationsUtil::add("HelpReportAbuseAbuserLocationEmpty");
+ return false;
+ };
+
+
if ( childGetText("summary_edit").empty() )
{
- if ( mReportType != BUG_REPORT )
- {
- LLNotifications::instance().add("HelpReportAbuseSummaryEmpty");
- }
- else
- {
- LLNotifications::instance().add("HelpReportBugSummaryEmpty");
- }
+ LLNotificationsUtil::add("HelpReportAbuseSummaryEmpty");
return false;
};
if ( childGetText("details_edit") == mDefaultSummary )
{
- if ( mReportType != BUG_REPORT )
- {
- LLNotifications::instance().add("HelpReportAbuseDetailsEmpty");
- }
- else
- {
- LLNotifications::instance().add("HelpReportBugDetailsEmpty");
- }
+ LLNotificationsUtil::add("HelpReportAbuseDetailsEmpty");
return false;
};
return true;
@@ -685,72 +578,48 @@ LLSD LLFloaterReporter::gatherReport()
#if LL_WINDOWS
const char* platform = "Win";
- const char* short_platform = "O:W";
#elif LL_DARWIN
const char* platform = "Mac";
- const char* short_platform = "O:M";
#elif LL_LINUX
const char* platform = "Lnx";
- const char* short_platform = "O:L";
#elif LL_SOLARIS
const char* platform = "Sol";
const char* short_platform = "O:S";
#else
const char* platform = "???";
- const char* short_platform = "O:?";
#endif
- if ( mReportType == BUG_REPORT)
- {
- summary << short_platform << " V" << LL_VERSION_MAJOR << "."
- << LL_VERSION_MINOR << "."
- << LL_VERSION_PATCH << "."
- << LL_VIEWER_BUILD
- << " (" << regionp->getName() << ")"
- << "[" << category_name << "] "
- << "\"" << childGetValue("summary_edit").asString() << "\"";
- }
- else
- {
- summary << ""
- << " |" << regionp->getName() << "|" // region reporter is currently in.
- << " (" << childGetText("abuse_location_edit") << ")" // region abuse occured in (freeform text - no LLRegionPicker tool)
- << " [" << category_name << "] " // updated category
- << " {" << childGetText("abuser_name_edit") << "} " // name of abuse entered in report (chosen using LLAvatarPicker)
- << " \"" << childGetValue("summary_edit").asString() << "\""; // summary as entered
- };
+
+ summary << ""
+ << " |" << regionp->getName() << "|" // region reporter is currently in.
+ << " (" << childGetText("abuse_location_edit") << ")" // region abuse occured in (freeform text - no LLRegionPicker tool)
+ << " [" << category_name << "] " // updated category
+ << " {" << childGetText("abuser_name_edit") << "} " // name of abuse entered in report (chosen using LLAvatarPicker)
+ << " \"" << childGetValue("summary_edit").asString() << "\""; // summary as entered
+
std::ostringstream details;
- if (mReportType != BUG_REPORT)
- {
- details << "V" << LL_VERSION_MAJOR << "." // client version moved to body of email for abuse reports
- << LL_VERSION_MINOR << "."
- << LL_VERSION_PATCH << "."
- << LL_VIEWER_BUILD << std::endl << std::endl;
- }
+
+ details << "V" << LLVersionInfo::getVersion() << std::endl << std::endl; // client version moved to body of email for abuse reports
+
std::string object_name = childGetText("object_name");
- std::string owner_name = childGetText("owner_name");
- if (!object_name.empty() && !owner_name.empty())
+ if (!object_name.empty() && !mOwnerName.empty())
{
details << "Object: " << object_name << "\n";
- details << "Owner: " << owner_name << "\n";
+ details << "Owner: " << mOwnerName << "\n";
}
- if ( mReportType != BUG_REPORT )
- {
- details << "Abuser name: " << childGetText("abuser_name_edit") << " \n";
- details << "Abuser location: " << childGetText("abuse_location_edit") << " \n";
- };
+
+ details << "Abuser name: " << childGetText("abuser_name_edit") << " \n";
+ details << "Abuser location: " << childGetText("abuse_location_edit") << " \n";
details << childGetValue("details_edit").asString();
std::string version_string;
version_string = llformat(
- "%d.%d.%d %s %s %s %s",
- LL_VERSION_MAJOR,
- LL_VERSION_MINOR,
- LL_VERSION_PATCH,
+ "%s %s %s %s %s",
+ LLVersionInfo::getShortVersion().c_str(),
platform,
gSysCPU.getFamily().c_str(),
gGLManager.mGLRenderer.c_str(),
@@ -761,17 +630,7 @@ LLSD LLFloaterReporter::gatherReport()
LLUUID screenshot_id = LLUUID::null;
if (childGetValue("screen_check"))
{
- if ( mReportType != BUG_REPORT )
- {
- if ( gEmailToEstateOwner == FALSE )
- {
- screenshot_id = childGetValue("screenshot");
- }
- }
- else
- {
- screenshot_id = childGetValue("screenshot");
- };
+ screenshot_id = childGetValue("screenshot");
};
LLSD report = LLSD::emptyMap();
@@ -883,7 +742,7 @@ void LLFloaterReporter::takeScreenshot()
llwarns << "Unable to take screenshot" << llendl;
return;
}
- LLPointer<LLImageJ2C> upload_data = LLViewerImageList::convertToUploadFile(raw);
+ LLPointer<LLImageJ2C> upload_data = LLViewerTextureList::convertToUploadFile(raw);
// create a resource data
mResourceDatap->mInventoryType = LLInventoryType::IT_NONE;
@@ -891,15 +750,11 @@ void LLFloaterReporter::takeScreenshot()
mResourceDatap->mExpectedUploadCost = 0; // we expect that abuse screenshots are free
mResourceDatap->mAssetInfo.mTransactionID.generate();
mResourceDatap->mAssetInfo.mUuid = mResourceDatap->mAssetInfo.mTransactionID.makeAssetID(gAgent.getSecureSessionID());
- if (BUG_REPORT == mReportType)
- {
- mResourceDatap->mAssetInfo.mType = LLAssetType::AT_TEXTURE;
- mResourceDatap->mPreferredLocation = LLAssetType::EType(-1);
- }
- else if (COMPLAINT_REPORT == mReportType)
+
+ if (COMPLAINT_REPORT == mReportType)
{
mResourceDatap->mAssetInfo.mType = LLAssetType::AT_TEXTURE;
- mResourceDatap->mPreferredLocation = LLAssetType::EType(-2);
+ mResourceDatap->mPreferredLocation = LLFolderType::EType(LLResourceData::INVALID_LOCATION);
}
else
{
@@ -917,17 +772,17 @@ void LLFloaterReporter::takeScreenshot()
mResourceDatap->mAssetInfo.mType);
// store in the image list so it doesn't try to fetch from the server
- LLPointer<LLViewerImage> image_in_list = new LLViewerImage(mResourceDatap->mAssetInfo.mUuid, TRUE);
- image_in_list->createGLTexture(0, raw);
- gImageList.addImage(image_in_list);
-
+ LLPointer<LLViewerFetchedTexture> image_in_list =
+ LLViewerTextureManager::getFetchedTexture(mResourceDatap->mAssetInfo.mUuid, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::FETCHED_TEXTURE);
+ image_in_list->createGLTexture(0, raw, 0, TRUE, LLViewerTexture::OTHER);
+
// the texture picker then uses that texture
LLTexturePicker* texture = getChild<LLTextureCtrl>("screenshot");
if (texture)
{
texture->setImageAssetID(mResourceDatap->mAssetInfo.mUuid);
texture->setDefaultImageAssetID(mResourceDatap->mAssetInfo.mUuid);
- texture->setCaption(std::string("Screenshot"));
+ texture->setCaption(getString("Screenshot"));
}
}
@@ -958,7 +813,7 @@ void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data,
{
LLSD args;
args["REASON"] = std::string(LLAssetStorage::getErrorString(result));
- LLNotifications::instance().add("ErrorUploadingReportScreenshot", args);
+ LLNotificationsUtil::add("ErrorUploadingReportScreenshot", args);
std::string err_msg("There was a problem uploading a report screenshot");
err_msg += " due to the following reason: " + args["REASON"].asString();
@@ -967,11 +822,7 @@ void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data,
}
EReportType report_type = UNKNOWN_REPORT;
- if (data->mPreferredLocation == -1)
- {
- report_type = BUG_REPORT;
- }
- else if (data->mPreferredLocation == -2)
+ if (data->mPreferredLocation == LLResourceData::INVALID_LOCATION)
{
report_type = COMPLAINT_REPORT;
}
@@ -980,13 +831,13 @@ void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data,
llwarns << "Unknown report type : " << data->mPreferredLocation << llendl;
}
- LLFloaterReporter *self = getReporter(report_type);
+ LLFloaterReporter *self = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter");
if (self)
{
self->mScreenID = uuid;
llinfos << "Got screen shot " << uuid << llendl;
self->sendReportViaLegacy(self->gatherReport());
- self->close();
+ self->closeFloater();
}
}
@@ -1001,35 +852,35 @@ void LLFloaterReporter::setPosBox(const LLVector3d &pos)
childSetText("pos_field", pos_string);
}
-void LLFloaterReporter::setDescription(const std::string& description, LLMeanCollisionData *mcd)
-{
- LLFloaterReporter *self = gReporterInstances[COMPLAINT_REPORT];
- if (self)
- {
- self->childSetText("details_edit", 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 = gReporterInstances[COMPLAINT_REPORT];
- if (self)
- {
- LLTextEditor* text = self->getChild<LLTextEditor>("details_edit");
- if (text)
- {
- text->insertText(description);
- }
- if (mcd)
- {
- self->mMCDList.push_back(new LLMeanCollisionData(mcd));
- }
- }
-}
+// void LLFloaterReporter::setDescription(const std::string& description, LLMeanCollisionData *mcd)
+// {
+// LLFloaterReporter *self = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter");
+// if (self)
+// {
+// self->childSetText("details_edit", 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 86bc60559e..7c6473f975 100644
--- a/indra/newview/llfloaterreporter.h
+++ b/indra/newview/llfloaterreporter.h
@@ -1,7 +1,7 @@
/**
* @file llfloaterreporter.h
* @author Andrew Meadows
- * @brief Bug and abuse reports.
+ * @brief Abuse reports.
*
* $LicenseInfo:firstyear=2006&license=viewergpl$
*
@@ -39,7 +39,7 @@
#include "v3math.h"
class LLMessageSystem;
-class LLViewerImage;
+class LLViewerTexture;
class LLInventoryItem;
class LLViewerObject;
class LLAgent;
@@ -48,7 +48,7 @@ class LLMeanCollisionData;
struct LLResourceData;
// these flags are used to label info requests to the server
-const U32 BUG_REPORT_REQUEST = 0x01 << 0;
+//const U32 BUG_REPORT_REQUEST = 0x01 << 0; // DEPRECATED
const U32 COMPLAINT_REPORT_REQUEST = 0x01 << 1;
const U32 OBJECT_PAY_REQUEST = 0x01 << 2;
@@ -73,7 +73,7 @@ enum EReportType
{
NULL_REPORT = 0, // don't use this value anywhere
UNKNOWN_REPORT = 1,
- BUG_REPORT = 2,
+ //BUG_REPORT = 2, // DEPRECATED
COMPLAINT_REPORT = 3,
CS_REQUEST_REPORT = 4
};
@@ -82,39 +82,36 @@ class LLFloaterReporter
: public LLFloater
{
public:
- LLFloaterReporter(const std::string& name,
- const LLRect &rect,
- const std::string& title,
- EReportType = UNKNOWN_REPORT);
+ LLFloaterReporter(const LLSD& key);
/*virtual*/ ~LLFloaterReporter();
-
+ /*virtual*/ BOOL postBuild();
virtual void draw();
-
+
+ void setReportType(EReportType type) { mReportType = type; }
+
// Enables all buttons
static void showFromMenu(EReportType report_type);
static void showFromObject(const LLUUID& object_id);
+ static void showFromAvatar(const LLUUID& avatar_id, const std::string avatar_name);
static void onClickSend (void *userdata);
static void onClickCancel (void *userdata);
static void onClickObjPicker (void *userdata);
- static void onClickSelectAbuser (void *userdata);
+ 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);
- // returns a pointer to reporter of report_type
- static LLFloaterReporter* getReporter(EReportType report_type);
- static LLFloaterReporter* createNewAbuseReporter();
- static LLFloaterReporter* createNewBugReporter();
-
// static
static void processRegionInfo(LLMessageSystem* msg);
void setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id);
private:
+ static void show(const LLUUID& object_id, const std::string& avatar_name = LLStringUtil::null);
+
void takeScreenshot();
void sendReportViaCaps(std::string url);
void uploadImage();
@@ -126,13 +123,16 @@ private:
void setPosBox(const LLVector3d &pos);
void enableControls(BOOL own_avatar);
void getObjectInfo(const LLUUID& object_id);
- static void callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data);
+ void callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids);
+ void setFromAvatar(const LLUUID& avatar_id, const std::string& avatar_name = LLStringUtil::null);
private:
EReportType mReportType;
LLUUID mObjectID;
LLUUID mScreenID;
LLUUID mAbuserID;
+ // Store the real name, not the link, for upstream reporting
+ std::string mOwnerName;
BOOL mDeselectOnClose;
BOOL mPicking;
LLVector3 mPosition;
diff --git a/indra/newview/llfloaterscriptdebug.cpp b/indra/newview/llfloaterscriptdebug.cpp
index bc774e77ac..eeea71cc4c 100644
--- a/indra/newview/llfloaterscriptdebug.cpp
+++ b/indra/newview/llfloaterscriptdebug.cpp
@@ -32,9 +32,10 @@
#include "llviewerprecompiledheaders.h"
-#include "lluictrlfactory.h"
#include "llfloaterscriptdebug.h"
+#include "llfloaterreg.h"
+#include "lluictrlfactory.h"
#include "llfontgl.h"
#include "llrect.h"
#include "llerror.h"
@@ -45,19 +46,20 @@
#include "llviewertexteditor.h"
#include "llviewercontrol.h"
#include "llviewerobjectlist.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
//
// Statics
//
-LLFloaterScriptDebug* LLFloaterScriptDebug::sInstance = NULL;
//
// Member Functions
//
-LLFloaterScriptDebug::LLFloaterScriptDebug() :
- LLMultiFloater()
+LLFloaterScriptDebug::LLFloaterScriptDebug(const LLSD& key)
+ : LLMultiFloater(key)
{
+// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_script_debug.xml");
+
// avoid resizing of the window to match
// the initial size of the tabbed-childs, whenever a tab is opened or closed
mAutoResize = FALSE;
@@ -65,17 +67,11 @@ LLFloaterScriptDebug::LLFloaterScriptDebug() :
LLFloaterScriptDebug::~LLFloaterScriptDebug()
{
- sInstance = NULL;
}
void LLFloaterScriptDebug::show(const LLUUID& object_id)
{
- LLFloater* floaterp = addOutputWindow(object_id);
- if (sInstance)
- {
- sInstance->open(); /* Flawfinder: ignore */
- sInstance->showFloater(floaterp);
- }
+ addOutputWindow(object_id);
}
BOOL LLFloaterScriptDebug::postBuild()
@@ -84,41 +80,22 @@ BOOL LLFloaterScriptDebug::postBuild()
if (mTabContainer)
{
- // *FIX: apparantly fails for tab containers?
-// mTabContainer->requires<LLFloater>("all_scripts");
-// mTabContainer->checkRequirements();
return TRUE;
}
return FALSE;
}
-void* getOutputWindow(void* data)
-{
- return new LLFloaterScriptDebugOutput();
-}
-
LLFloater* LLFloaterScriptDebug::addOutputWindow(const LLUUID &object_id)
{
- if (!sInstance)
- {
- sInstance = new LLFloaterScriptDebug();
- LLCallbackMap::map_t factory_map;
- factory_map["all_scripts"] = LLCallbackMap(getOutputWindow, NULL);
- LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_script_debug.xml", &factory_map);
- sInstance->setVisible(FALSE);
- }
+ LLMultiFloater* host = LLFloaterReg::showTypedInstance<LLMultiFloater>("script_debug", LLSD());
+ if (!host)
+ return NULL;
- LLFloater* floaterp = NULL;
- LLFloater::setFloaterHost(sInstance);
- {
- floaterp = LLFloaterScriptDebugOutput::show(object_id);
- }
+ LLFloater::setFloaterHost(host);
+ LLFloater* floaterp = LLFloaterReg::showInstance("script_debug_output", object_id);
LLFloater::setFloaterHost(NULL);
- // Tabs sometimes overlap resize handle
- sInstance->moveResizeHandlesToFront();
-
return floaterp;
}
@@ -129,7 +106,7 @@ void LLFloaterScriptDebug::addScriptLine(const std::string &utf8mesg, const std:
if (objectp)
{
- objectp->setIcon(gImageList.getImageFromFile("script_error.j2c", TRUE, TRUE));
+ objectp->setIcon(LLViewerTextureManager::getFetchedTextureFromFile("script_error.j2c", TRUE, LLViewerTexture::BOOST_UI));
floater_label = llformat("%s(%.2f, %.2f)", user_name.c_str(), objectp->getPositionRegion().mV[VX], objectp->getPositionRegion().mV[VY]);
}
else
@@ -141,119 +118,56 @@ void LLFloaterScriptDebug::addScriptLine(const std::string &utf8mesg, const std:
addOutputWindow(source_id);
// add to "All" floater
- LLFloaterScriptDebugOutput* floaterp = LLFloaterScriptDebugOutput::getFloaterByID(LLUUID::null);
- floaterp->addLine(utf8mesg, user_name, color);
-
+ LLFloaterScriptDebugOutput* floaterp = LLFloaterReg::getTypedInstance<LLFloaterScriptDebugOutput>("script_debug_output", LLUUID::null);
+ if (floaterp)
+ {
+ floaterp->addLine(utf8mesg, user_name, color);
+ }
+
// add to specific script instance floater
- floaterp = LLFloaterScriptDebugOutput::getFloaterByID(source_id);
- floaterp->addLine(utf8mesg, floater_label, color);
+ floaterp = LLFloaterReg::getTypedInstance<LLFloaterScriptDebugOutput>("script_debug_output", source_id);
+ if (floaterp)
+ {
+ floaterp->addLine(utf8mesg, floater_label, color);
+ }
}
//
// LLFloaterScriptDebugOutput
//
-std::map<LLUUID, LLFloaterScriptDebugOutput*> LLFloaterScriptDebugOutput::sInstanceMap;
-
-LLFloaterScriptDebugOutput::LLFloaterScriptDebugOutput()
-: mObjectID(LLUUID::null)
+LLFloaterScriptDebugOutput::LLFloaterScriptDebugOutput(const LLSD& object_id)
+ : LLFloater(LLSD(object_id)),
+ mObjectID(object_id.asUUID())
{
- sInstanceMap[mObjectID] = this;
+ //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_script_debug_panel.xml");
}
-LLFloaterScriptDebugOutput::LLFloaterScriptDebugOutput(const LLUUID& object_id)
-: LLFloater(std::string("script instance floater"), LLRect(0, 200, 200, 0), std::string("Script"), TRUE), mObjectID(object_id)
+BOOL LLFloaterScriptDebugOutput::postBuild()
{
- S32 y = getRect().getHeight() - LLFLOATER_HEADER_SIZE - LLFLOATER_VPAD;
- S32 x = LLFLOATER_HPAD;
- // History editor
- // Give it a border on the top
- LLRect history_editor_rect(
- x,
- y,
- getRect().getWidth() - LLFLOATER_HPAD,
- LLFLOATER_VPAD );
- mHistoryEditor = new LLViewerTextEditor( std::string("Chat History Editor"),
- history_editor_rect, S32_MAX, LLStringUtil::null, LLFontGL::getFontSansSerif());
- mHistoryEditor->setWordWrap( TRUE );
- mHistoryEditor->setFollowsAll();
- mHistoryEditor->setEnabled( FALSE );
- mHistoryEditor->setTabStop( TRUE ); // We want to be able to cut or copy from the history.
- addChild(mHistoryEditor);
-}
-
-void LLFloaterScriptDebugOutput::initFloater(const std::string& title, BOOL resizable,
- S32 min_width, S32 min_height, BOOL drag_on_left,
- BOOL minimizable, BOOL close_btn)
-{
- LLFloater::initFloater(title, resizable, min_width, min_height, drag_on_left, minimizable, close_btn);
- S32 y = getRect().getHeight() - LLFLOATER_HEADER_SIZE - LLFLOATER_VPAD;
- S32 x = LLFLOATER_HPAD;
- // History editor
- // Give it a border on the top
- LLRect history_editor_rect(
- x,
- y,
- getRect().getWidth() - LLFLOATER_HPAD,
- LLFLOATER_VPAD );
- mHistoryEditor = new LLViewerTextEditor( std::string("Chat History Editor"),
- history_editor_rect, S32_MAX, LLStringUtil::null, LLFontGL::getFontSansSerif());
- mHistoryEditor->setWordWrap( TRUE );
- mHistoryEditor->setFollowsAll();
- mHistoryEditor->setEnabled( FALSE );
- mHistoryEditor->setTabStop( TRUE ); // We want to be able to cut or copy from the history.
- addChild(mHistoryEditor);
+ LLFloater::postBuild();
+ mHistoryEditor = getChild<LLViewerTextEditor>("Chat History Editor");
+ return TRUE;
}
LLFloaterScriptDebugOutput::~LLFloaterScriptDebugOutput()
{
- sInstanceMap.erase(mObjectID);
}
void LLFloaterScriptDebugOutput::addLine(const std::string &utf8mesg, const std::string &user_name, const LLColor4& color)
{
if (mObjectID.isNull())
{
- //setTitle("[All scripts]");
setCanTearOff(FALSE);
setCanClose(FALSE);
}
else
{
setTitle(user_name);
+ setShortTitle(user_name);
}
- mHistoryEditor->appendColoredText(utf8mesg, false, true, color);
-}
-
-//static
-LLFloaterScriptDebugOutput* LLFloaterScriptDebugOutput::show(const LLUUID& object_id)
-{
- LLFloaterScriptDebugOutput* floaterp = NULL;
- instance_map_t::iterator found_it = sInstanceMap.find(object_id);
- if (found_it == sInstanceMap.end())
- {
- floaterp = new LLFloaterScriptDebugOutput(object_id);
- sInstanceMap[object_id] = floaterp;
- floaterp->open(); /* Flawfinder: ignore*/
- }
- else
- {
- floaterp = found_it->second;
- }
-
- return floaterp;
+ mHistoryEditor->appendText(utf8mesg, true, LLStyle::Params().color(color));
+ mHistoryEditor->blockUndo();
}
-//static
-LLFloaterScriptDebugOutput* LLFloaterScriptDebugOutput::getFloaterByID(const LLUUID& object_id)
-{
- LLFloaterScriptDebugOutput* floaterp = NULL;
- instance_map_t::iterator found_it = sInstanceMap.find(object_id);
- if (found_it != sInstanceMap.end())
- {
- floaterp = found_it->second;
- }
-
- return floaterp;
-}
diff --git a/indra/newview/llfloaterscriptdebug.h b/indra/newview/llfloaterscriptdebug.h
index 59c0ba1c8b..ffc60e5554 100644
--- a/indra/newview/llfloaterscriptdebug.h
+++ b/indra/newview/llfloaterscriptdebug.h
@@ -33,7 +33,7 @@
#ifndef LL_LLFLOATERSCRIPTDEBUG_H
#define LL_LLFLOATERSCRIPTDEBUG_H
-#include "llfloater.h"
+#include "llmultifloater.h"
class LLTextEditor;
class LLUUID;
@@ -41,15 +41,13 @@ class LLUUID;
class LLFloaterScriptDebug : public LLMultiFloater
{
public:
+ LLFloaterScriptDebug(const LLSD& key);
virtual ~LLFloaterScriptDebug();
- virtual void onClose(bool app_quitting) { setVisible(FALSE); }
virtual BOOL postBuild();
static void show(const LLUUID& object_id);
static void addScriptLine(const std::string &utf8mesg, const std::string &user_name, const LLColor4& color, const LLUUID& source_id);
protected:
- LLFloaterScriptDebug();
-
static LLFloater* addOutputWindow(const LLUUID& object_id);
protected:
@@ -59,26 +57,17 @@ protected:
class LLFloaterScriptDebugOutput : public LLFloater
{
public:
- LLFloaterScriptDebugOutput();
- LLFloaterScriptDebugOutput(const LLUUID& object_id);
+ LLFloaterScriptDebugOutput(const LLSD& object_id);
~LLFloaterScriptDebugOutput();
- virtual void initFloater(const std::string& title, BOOL resizable,
- S32 min_width, S32 min_height, BOOL drag_on_left,
- BOOL minimizable, BOOL close_btn);
-
void addLine(const std::string &utf8mesg, const std::string &user_name, const LLColor4& color);
- static LLFloaterScriptDebugOutput* show(const LLUUID& object_id);
- static LLFloaterScriptDebugOutput* getFloaterByID(const LLUUID& id);
-
+ virtual BOOL postBuild();
+
protected:
- LLTextEditor* mHistoryEditor;
-
- typedef std::map<LLUUID, LLFloaterScriptDebugOutput*> instance_map_t;
- static instance_map_t sInstanceMap;
+ LLTextEditor* mHistoryEditor;
- LLUUID mObjectID;
+ LLUUID mObjectID;
};
#endif // LL_LLFLOATERSCRIPTDEBUG_H
diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp
new file mode 100644
index 0000000000..0964ad7f91
--- /dev/null
+++ b/indra/newview/llfloaterscriptlimits.cpp
@@ -0,0 +1,1136 @@
+/**
+ * @file llfloaterscriptlimits.cpp
+ * @author Gabriel Lee
+ * @brief Implementation of the region info and controls floater and panels.
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llfloaterscriptlimits.h"
+
+#include "llsdutil.h"
+#include "llsdutil_math.h"
+#include "message.h"
+
+#include "llagent.h"
+#include "llfloateravatarpicker.h"
+#include "llfloaterland.h"
+#include "llfloaterreg.h"
+#include "llregionhandle.h"
+#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "llparcel.h"
+#include "lltabcontainer.h"
+#include "lltracker.h"
+#include "lltrans.h"
+#include "llviewercontrol.h"
+#include "lluictrlfactory.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+#include "llviewerwindow.h"
+
+///----------------------------------------------------------------------------
+/// LLFloaterScriptLimits
+///----------------------------------------------------------------------------
+
+// due to server side bugs the full summary display is not possible
+// until they are fixed this define creates a simple version of the
+// summary which only shows available & correct information
+#define USE_SIMPLE_SUMMARY
+
+const S32 SIZE_OF_ONE_KB = 1024;
+
+LLFloaterScriptLimits::LLFloaterScriptLimits(const LLSD& seed)
+ : LLFloater(seed)
+{
+}
+
+BOOL LLFloaterScriptLimits::postBuild()
+{
+ // a little cheap and cheerful - if there's an about land panel open default to showing parcel info,
+ // otherwise default to showing attachments (avatar appearance)
+ bool selectParcelPanel = false;
+
+ LLFloaterLand* instance = LLFloaterReg::getTypedInstance<LLFloaterLand>("about_land");
+ if(instance)
+ {
+ if(instance->isShown())
+ {
+ selectParcelPanel = true;
+ }
+ }
+
+ mTab = getChild<LLTabContainer>("scriptlimits_panels");
+
+ // contruct the panels
+ LLPanelScriptLimitsRegionMemory* panel_memory;
+ panel_memory = new LLPanelScriptLimitsRegionMemory;
+ mInfoPanels.push_back(panel_memory);
+
+ LLUICtrlFactory::getInstance()->buildPanel(panel_memory, "panel_script_limits_region_memory.xml");
+ mTab->addTabPanel(panel_memory);
+
+ LLPanelScriptLimitsRegionURLs* panel_urls = new LLPanelScriptLimitsRegionURLs;
+ mInfoPanels.push_back(panel_urls);
+ LLUICtrlFactory::getInstance()->buildPanel(panel_urls, "panel_script_limits_region_urls.xml");
+ mTab->addTabPanel(panel_urls);
+
+ LLPanelScriptLimitsAttachment* panel_attachments = new LLPanelScriptLimitsAttachment;
+ mInfoPanels.push_back(panel_attachments);
+ LLUICtrlFactory::getInstance()->buildPanel(panel_attachments, "panel_script_limits_my_avatar.xml");
+ mTab->addTabPanel(panel_attachments);
+
+ if(selectParcelPanel)
+ {
+ mTab->selectTab(0);
+ }
+ else
+ {
+ mTab->selectTab(2);
+ }
+
+ return TRUE;
+}
+
+LLFloaterScriptLimits::~LLFloaterScriptLimits()
+{
+}
+
+// public
+void LLFloaterScriptLimits::refresh()
+{
+ for(info_panels_t::iterator iter = mInfoPanels.begin();
+ iter != mInfoPanels.end(); ++iter)
+ {
+ (*iter)->refresh();
+ }
+}
+
+///----------------------------------------------------------------------------
+// Base class for panels
+///----------------------------------------------------------------------------
+
+LLPanelScriptLimitsInfo::LLPanelScriptLimitsInfo()
+ : LLPanel()
+{
+}
+
+
+// virtual
+BOOL LLPanelScriptLimitsInfo::postBuild()
+{
+ refresh();
+ return TRUE;
+}
+
+// virtual
+void LLPanelScriptLimitsInfo::updateChild(LLUICtrl* child_ctr)
+{
+}
+
+///----------------------------------------------------------------------------
+// Responders
+///----------------------------------------------------------------------------
+
+void fetchScriptLimitsRegionInfoResponder::result(const LLSD& content)
+{
+ // at this point we have an llsd which should contain ether one or two urls to the services we want.
+ // first we look for the details service:
+ if(content.has("ScriptResourceDetails"))
+ {
+ LLHTTPClient::get(content["ScriptResourceDetails"], new fetchScriptLimitsRegionDetailsResponder(mInfo));
+ }
+ else
+ {
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(!instance)
+ {
+ llinfos << "Failed to get llfloaterscriptlimits instance" << llendl;
+ }
+ else
+ {
+
+// temp - only show info if we get details - there's nothing to show if not until the sim gets fixed
+#ifdef USE_SIMPLE_SUMMARY
+
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ std::string msg = LLTrans::getString("ScriptLimitsRequestDontOwnParcel");
+ panel_memory->childSetValue("loading_text", LLSD(msg));
+ LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
+ panel_urls->childSetValue("loading_text", LLSD(msg));
+
+ // intentional early out as we dont want the resource summary if we are using the "simple summary"
+ // and the details are missing
+ return;
+#endif
+ }
+ }
+
+ // then the summary service:
+ if(content.has("ScriptResourceSummary"))
+ {
+ LLHTTPClient::get(content["ScriptResourceSummary"], new fetchScriptLimitsRegionSummaryResponder(mInfo));
+ }
+}
+
+void fetchScriptLimitsRegionInfoResponder::error(U32 status, const std::string& reason)
+{
+ llinfos << "Error from responder " << reason << llendl;
+}
+
+void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content)
+{
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(!instance)
+ {
+ llinfos << "Failed to get llfloaterscriptlimits instance" << llendl;
+ }
+ else
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ panel_memory->setRegionSummary(content);
+ LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
+ panel_urls->setRegionSummary(content);
+ }
+}
+
+void fetchScriptLimitsRegionSummaryResponder::error(U32 status, const std::string& reason)
+{
+ llinfos << "Error from responder " << reason << llendl;
+}
+
+void fetchScriptLimitsRegionDetailsResponder::result(const LLSD& content)
+{
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+
+ if(!instance)
+ {
+ llinfos << "Failed to get llfloaterscriptlimits instance" << llendl;
+ }
+ else
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ panel_memory->setRegionDetails(content);
+
+ LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
+ panel_urls->setRegionDetails(content);
+ }
+}
+
+void fetchScriptLimitsRegionDetailsResponder::error(U32 status, const std::string& reason)
+{
+ llinfos << "Error from responder " << reason << llendl;
+}
+
+void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content)
+{
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+
+ if(!instance)
+ {
+ llinfos << "Failed to get llfloaterscriptlimits instance" << llendl;
+ }
+ else
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsAttachment* panel = (LLPanelScriptLimitsAttachment*)tab->getChild<LLPanel>("script_limits_my_avatar_panel");
+ panel->setAttachmentDetails(content);
+ }
+}
+
+void fetchScriptLimitsAttachmentInfoResponder::error(U32 status, const std::string& reason)
+{
+ llinfos << "Error from responder " << reason << llendl;
+}
+
+///----------------------------------------------------------------------------
+// Memory Panel
+///----------------------------------------------------------------------------
+
+BOOL LLPanelScriptLimitsRegionMemory::getLandScriptResources()
+{
+ LLSD body;
+ std::string url = gAgent.getRegion()->getCapability("LandResources");
+ if (!url.empty())
+ {
+ body["parcel_id"] = mParcelId;
+
+ LLSD info;
+ info["parcel_id"] = mParcelId;
+ LLHTTPClient::post(url, body, new fetchScriptLimitsRegionInfoResponder(info));
+
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+void LLPanelScriptLimitsRegionMemory::processParcelInfo(const LLParcelData& parcel_data)
+{
+ mParcelId = parcel_data.parcel_id;
+
+ if(!getLandScriptResources())
+ {
+ std::string msg_error = LLTrans::getString("ScriptLimitsRequestError");
+ childSetValue("loading_text", LLSD(msg_error));
+ }
+ else
+ {
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
+ childSetValue("loading_text", LLSD(msg_waiting));
+ }
+}
+
+void LLPanelScriptLimitsRegionMemory::setParcelID(const LLUUID& parcel_id)
+{
+ if (!parcel_id.isNull())
+ {
+ LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this);
+ LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id);
+ }
+ else
+ {
+ std::string msg_error = LLTrans::getString("ScriptLimitsRequestError");
+ childSetValue("loading_text", LLSD(msg_error));
+ }
+}
+
+// virtual
+void LLPanelScriptLimitsRegionMemory::setErrorStatus(U32 status, const std::string& reason)
+{
+ llerrs << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl;
+}
+
+// callback from the name cache with an owner name to add to the list
+void LLPanelScriptLimitsRegionMemory::onNameCache(
+ const LLUUID& id,
+ const std::string& first_name,
+ const std::string& last_name)
+{
+ std::string name = first_name + " " + last_name;
+
+ LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
+ std::vector<LLSD>::iterator id_itor;
+ for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor)
+ {
+ LLSD element = *id_itor;
+ if(element["owner_id"].asUUID() == id)
+ {
+ LLScrollListItem* item = list->getItem(element["id"].asUUID());
+
+ if(item)
+ {
+ item->getColumn(2)->setValue(LLSD(name));
+ element["columns"][2]["value"] = name;
+ }
+ }
+ }
+
+ // fill in the url's tab if needed, all urls must have memory so we can do it all here
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
+
+ LLScrollListCtrl *list = panel->getChild<LLScrollListCtrl>("scripts_list");
+ std::vector<LLSD>::iterator id_itor;
+ for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor)
+ {
+ LLSD element = *id_itor;
+ if(element["owner_id"].asUUID() == id)
+ {
+ LLScrollListItem* item = list->getItem(element["id"].asUUID());
+
+ if(item)
+ {
+ item->getColumn(2)->setValue(LLSD(name));
+ element["columns"][2]["value"] = name;
+ }
+ }
+ }
+ }
+}
+
+void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content)
+{
+ LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
+
+ S32 number_parcels = content["parcels"].size();
+
+ LLStringUtil::format_map_t args_parcels;
+ args_parcels["[PARCELS]"] = llformat ("%d", number_parcels);
+ std::string msg_parcels = LLTrans::getString("ScriptLimitsParcelsOwned", args_parcels);
+ childSetValue("parcels_listed", LLSD(msg_parcels));
+
+ S32 total_objects = 0;
+ S32 total_size = 0;
+
+ std::vector<LLUUID> names_requested;
+
+ for(S32 i = 0; i < number_parcels; i++)
+ {
+ std::string parcel_name = content["parcels"][i]["name"].asString();
+ LLUUID parcel_id = content["parcels"][i]["id"].asUUID();
+ S32 number_objects = content["parcels"][i]["objects"].size();
+ for(S32 j = 0; j < number_objects; j++)
+ {
+ S32 size = content["parcels"][i]["objects"][j]["resources"]["memory"].asInteger() / SIZE_OF_ONE_KB;
+ total_size += size;
+
+ std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString();
+ LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID();
+ LLUUID owner_id = content["parcels"][i]["objects"][j]["owner_id"].asUUID();
+
+ std::string owner_buf;
+
+ BOOL name_is_cached = gCacheName->getFullName(owner_id, owner_buf);
+ if(!name_is_cached)
+ {
+ if(std::find(names_requested.begin(), names_requested.end(), owner_id) == names_requested.end())
+ {
+ names_requested.push_back(owner_id);
+ gCacheName->get(owner_id, TRUE,
+ boost::bind(&LLPanelScriptLimitsRegionMemory::onNameCache,
+ this, _1, _2, _3));
+ }
+ }
+
+ LLSD element;
+
+ element["id"] = task_id;
+ element["owner_id"] = owner_id;
+ element["columns"][0]["column"] = "size";
+ element["columns"][0]["value"] = llformat("%d", size);
+ element["columns"][0]["font"] = "SANSSERIF";
+ element["columns"][1]["column"] = "name";
+ element["columns"][1]["value"] = name_buf;
+ element["columns"][1]["font"] = "SANSSERIF";
+ element["columns"][2]["column"] = "owner";
+ element["columns"][2]["value"] = owner_buf;
+ element["columns"][2]["font"] = "SANSSERIF";
+ element["columns"][3]["column"] = "location";
+ element["columns"][3]["value"] = parcel_name;
+ element["columns"][3]["font"] = "SANSSERIF";
+
+ list->addElement(element, ADD_SORTED);
+ mObjectListItems.push_back(element);
+ total_objects++;
+ }
+ }
+
+ mParcelMemoryUsed =total_size;
+ mGotParcelMemoryUsed = TRUE;
+ populateParcelMemoryText();
+}
+
+void LLPanelScriptLimitsRegionMemory::populateParcelMemoryText()
+{
+ if(mGotParcelMemoryUsed && mGotParcelMemoryMax)
+ {
+#ifdef USE_SIMPLE_SUMMARY
+ LLStringUtil::format_map_t args_parcel_memory;
+ args_parcel_memory["[COUNT]"] = llformat ("%d", mParcelMemoryUsed);
+ std::string msg_parcel_memory = LLTrans::getString("ScriptLimitsMemoryUsedSimple", args_parcel_memory);
+ childSetValue("memory_used", LLSD(msg_parcel_memory));
+#else
+ S32 parcel_memory_available = mParcelMemoryMax - mParcelMemoryUsed;
+
+ LLStringUtil::format_map_t args_parcel_memory;
+ args_parcel_memory["[COUNT]"] = llformat ("%d", mParcelMemoryUsed);
+ args_parcel_memory["[MAX]"] = llformat ("%d", mParcelMemoryMax);
+ args_parcel_memory["[AVAILABLE]"] = llformat ("%d", parcel_memory_available);
+ std::string msg_parcel_memory = LLTrans::getString("ScriptLimitsMemoryUsed", args_parcel_memory);
+ childSetValue("memory_used", LLSD(msg_parcel_memory));
+#endif
+
+ childSetValue("loading_text", LLSD(std::string("")));
+ }
+}
+
+void LLPanelScriptLimitsRegionMemory::setRegionSummary(LLSD content)
+{
+ if(content["summary"]["available"][0]["type"].asString() == std::string("memory"))
+ {
+ mParcelMemoryMax = content["summary"]["available"][0]["amount"].asInteger();
+ mGotParcelMemoryMax = TRUE;
+ }
+ else if(content["summary"]["available"][1]["type"].asString() == std::string("memory"))
+ {
+ mParcelMemoryMax = content["summary"]["available"][1]["amount"].asInteger();
+ mGotParcelMemoryMax = TRUE;
+ }
+ else
+ {
+ llinfos << "summary doesn't contain memory info" << llendl;
+ return;
+ }
+/*
+ currently this is broken on the server, so we get this value from the details section
+ and update via populateParcelMemoryText() when both sets of information have been returned
+
+ when the sim is fixed this should be used instead:
+ if(content["summary"]["used"][0]["type"].asString() == std::string("memory"))
+ {
+ mParcelMemoryUsed = content["summary"]["used"][0]["amount"].asInteger();
+ mGotParcelMemoryUsed = TRUE;
+ }
+ else if(content["summary"]["used"][1]["type"].asString() == std::string("memory"))
+ {
+ mParcelMemoryUsed = content["summary"]["used"][1]["amount"].asInteger();
+ mGotParcelMemoryUsed = TRUE;
+ }
+ else
+ {
+ //ERROR!!!
+ return;
+ }*/
+
+ populateParcelMemoryText();
+}
+
+BOOL LLPanelScriptLimitsRegionMemory::postBuild()
+{
+ childSetAction("refresh_list_btn", onClickRefresh, this);
+ childSetAction("highlight_btn", onClickHighlight, this);
+ childSetAction("return_btn", onClickReturn, this);
+
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
+ childSetValue("loading_text", LLSD(msg_waiting));
+
+ return StartRequestChain();
+}
+
+BOOL LLPanelScriptLimitsRegionMemory::StartRequestChain()
+{
+ LLUUID region_id;
+
+ LLFloaterLand* instance = LLFloaterReg::getTypedInstance<LLFloaterLand>("about_land");
+ if(!instance)
+ {
+ //this isnt really an error...
+// llinfos << "Failed to get about land instance" << llendl;
+// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+ childSetValue("loading_text", LLSD(std::string("")));
+ //might have to do parent post build here
+ //if not logic below could use early outs
+ return FALSE;
+ }
+
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
+
+ LLParcel* parcel = instance->getCurrentSelectedParcel();
+ LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
+
+ LLUUID current_region_id = gAgent.getRegion()->getRegionID();
+
+ if ((region) && (parcel))
+ {
+ LLVector3 parcel_center = parcel->getCenterpoint();
+
+ region_id = region->getRegionID();
+
+ if(region_id != current_region_id)
+ {
+ std::string msg_wrong_region = LLTrans::getString("ScriptLimitsRequestWrongRegion");
+ childSetValue("loading_text", LLSD(msg_wrong_region));
+ panel_urls->childSetValue("loading_text", LLSD(msg_wrong_region));
+ return FALSE;
+ }
+
+ LLVector3d pos_global = region->getCenterGlobal();
+
+ LLSD body;
+ std::string url = region->getCapability("RemoteParcelRequest");
+ if (!url.empty())
+ {
+ body["location"] = ll_sd_from_vector3(parcel_center);
+ if (!region_id.isNull())
+ {
+ body["region_id"] = region_id;
+ }
+ if (!pos_global.isExactlyZero())
+ {
+ U64 region_handle = to_region_handle(pos_global);
+ body["region_handle"] = ll_sd_from_U64(region_handle);
+ }
+ LLHTTPClient::post(url, body, new LLRemoteParcelRequestResponder(getObserverHandle()));
+ }
+ else
+ {
+ llwarns << "Can't get parcel info for script information request" << region_id
+ << ". Region: " << region->getName()
+ << " does not support RemoteParcelRequest" << llendl;
+
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+ childSetValue("loading_text", LLSD(msg_waiting));
+ panel_urls->childSetValue("loading_text", LLSD(msg_waiting));
+ }
+ }
+ else
+ {
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+ childSetValue("loading_text", LLSD(msg_waiting));
+ panel_urls->childSetValue("loading_text", LLSD(msg_waiting));
+ }
+
+ return LLPanelScriptLimitsInfo::postBuild();
+}
+
+void LLPanelScriptLimitsRegionMemory::clearList()
+{
+ LLCtrlListInterface *list = childGetListInterface("scripts_list");
+
+ if (list)
+ {
+ list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ }
+
+ mGotParcelMemoryUsed = FALSE;
+ mGotParcelMemoryMax = FALSE;
+
+ LLStringUtil::format_map_t args_parcel_memory;
+ std::string msg_empty_string("");
+ childSetValue("memory_used", LLSD(msg_empty_string));
+ childSetValue("parcels_listed", LLSD(msg_empty_string));
+
+ mObjectListItems.clear();
+}
+
+// static
+void LLPanelScriptLimitsRegionMemory::onClickRefresh(void* userdata)
+{
+ llinfos << "LLPanelRegionGeneralInfo::onClickRefresh" << llendl;
+
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ panel_memory->clearList();
+
+ LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
+ panel_urls->clearList();
+
+ panel_memory->StartRequestChain();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after refresh button clicked" << llendl;
+ return;
+ }
+}
+
+void LLPanelScriptLimitsRegionMemory::showBeacon()
+{
+/* LLScrollListCtrl* list = getChild<LLScrollListCtrl>("scripts_list");
+ if (!list) return;
+
+ LLScrollListItem* first_selected = list->getFirstSelected();
+ if (!first_selected) return;
+
+ std::string name = first_selected->getColumn(1)->getValue().asString();
+ std::string pos_string = first_selected->getColumn(3)->getValue().asString();
+
+ llinfos << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" <<llendl;
+ llinfos << "name = " << name << " pos = " << pos_string << llendl;
+
+ F32 x, y, z;
+ S32 matched = sscanf(pos_string.c_str(), "<%g,%g,%g>", &x, &y, &z);
+ if (matched != 3) return;
+
+ LLVector3 pos_agent(x, y, z);
+ LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent);
+ llinfos << "name = " << name << " pos = " << pos_string << llendl;
+ std::string tooltip("");
+ LLTracker::trackLocation(pos_global, name, tooltip, LLTracker::LOCATION_ITEM);*/
+}
+
+// static
+void LLPanelScriptLimitsRegionMemory::onClickHighlight(void* userdata)
+{
+/* llinfos << "LLPanelRegionGeneralInfo::onClickHighlight" << llendl;
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ panel->showBeacon();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl;
+// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+// panel->childSetValue("loading_text", LLSD(msg_waiting));
+ return;
+ }*/
+}
+
+void LLPanelScriptLimitsRegionMemory::returnObjects()
+{
+/* llinfos << "started" << llendl;
+ LLMessageSystem *msg = gMessageSystem;
+
+ LLViewerRegion* region = gAgent.getRegion();
+ if (!region) return;
+
+ llinfos << "got region" << llendl;
+ LLCtrlListInterface *list = childGetListInterface("scripts_list");
+ if (!list || list->getItemCount() == 0) return;
+
+ llinfos << "got list" << llendl;
+ std::vector<LLUUID>::iterator id_itor;
+
+ bool start_message = true;
+
+ for (id_itor = mObjectListIDs.begin(); id_itor != mObjectListIDs.end(); ++id_itor)
+ {
+ LLUUID task_id = *id_itor;
+ llinfos << task_id << llendl;
+ if (!list->isSelected(task_id))
+ {
+ llinfos << "not selected" << llendl;
+ // Selected only
+ continue;
+ }
+ llinfos << "selected" << llendl;
+ if (start_message)
+ {
+ msg->newMessageFast(_PREHASH_ParcelReturnObjects);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_ParcelData);
+ msg->addS32Fast(_PREHASH_LocalID, -1); // Whole region
+ msg->addS32Fast(_PREHASH_ReturnType, RT_LIST);
+ start_message = false;
+ llinfos << "start message" << llendl;
+ }
+
+ msg->nextBlockFast(_PREHASH_TaskIDs);
+ msg->addUUIDFast(_PREHASH_TaskID, task_id);
+ llinfos << "added id" << llendl;
+
+ if (msg->isSendFullFast(_PREHASH_TaskIDs))
+ {
+ msg->sendReliable(region->getHost());
+ start_message = true;
+ llinfos << "sent 1" << llendl;
+ }
+ }
+
+ if (!start_message)
+ {
+ msg->sendReliable(region->getHost());
+ llinfos << "sent 2" << llendl;
+ }*/
+}
+
+// static
+void LLPanelScriptLimitsRegionMemory::onClickReturn(void* userdata)
+{
+/* llinfos << "LLPanelRegionGeneralInfo::onClickReturn" << llendl;
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ panel->returnObjects();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl;
+// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+// panel->childSetValue("loading_text", LLSD(msg_waiting));
+ return;
+ }*/
+}
+
+///----------------------------------------------------------------------------
+// URLs Panel
+///----------------------------------------------------------------------------
+
+void LLPanelScriptLimitsRegionURLs::setRegionDetails(LLSD content)
+{
+ LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
+
+ S32 number_parcels = content["parcels"].size();
+
+ LLStringUtil::format_map_t args_parcels;
+ args_parcels["[PARCELS]"] = llformat ("%d", number_parcels);
+ std::string msg_parcels = LLTrans::getString("ScriptLimitsParcelsOwned", args_parcels);
+ childSetValue("parcels_listed", LLSD(msg_parcels));
+
+ S32 total_objects = 0;
+ S32 total_size = 0;
+
+ for(S32 i = 0; i < number_parcels; i++)
+ {
+ std::string parcel_name = content["parcels"][i]["name"].asString();
+ llinfos << parcel_name << llendl;
+
+ S32 number_objects = content["parcels"][i]["objects"].size();
+ for(S32 j = 0; j < number_objects; j++)
+ {
+ if(content["parcels"][i]["objects"][j]["resources"].has("urls"))
+ {
+ S32 size = content["parcels"][i]["objects"][j]["resources"]["urls"].asInteger();
+ total_size += size;
+
+ std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString();
+ LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID();
+ LLUUID owner_id = content["parcels"][i]["objects"][j]["owner_id"].asUUID();
+
+ std::string owner_buf;
+ gCacheName->getFullName(owner_id, owner_buf); //dont care if this fails as the memory tab will request and fill the field
+
+ LLSD element;
+
+ element["id"] = task_id;
+ element["columns"][0]["column"] = "urls";
+ element["columns"][0]["value"] = llformat("%d", size);
+ element["columns"][0]["font"] = "SANSSERIF";
+ element["columns"][1]["column"] = "name";
+ element["columns"][1]["value"] = name_buf;
+ element["columns"][1]["font"] = "SANSSERIF";
+ element["columns"][2]["column"] = "owner";
+ element["columns"][2]["value"] = owner_buf;
+ element["columns"][2]["font"] = "SANSSERIF";
+ element["columns"][3]["column"] = "location";
+ element["columns"][3]["value"] = parcel_name;
+ element["columns"][3]["font"] = "SANSSERIF";
+
+ list->addElement(element);
+ mObjectListItems.push_back(element);
+ total_objects++;
+ }
+ }
+ }
+
+ mParcelURLsUsed =total_size;
+ mGotParcelURLsUsed = TRUE;
+ populateParcelURLsText();
+}
+
+void LLPanelScriptLimitsRegionURLs::populateParcelURLsText()
+{
+ if(mGotParcelURLsUsed && mGotParcelURLsMax)
+ {
+
+#ifdef USE_SIMPLE_SUMMARY
+ LLStringUtil::format_map_t args_parcel_urls;
+ args_parcel_urls["[COUNT]"] = llformat ("%d", mParcelURLsUsed);
+ std::string msg_parcel_urls = LLTrans::getString("ScriptLimitsURLsUsedSimple", args_parcel_urls);
+ childSetValue("urls_used", LLSD(msg_parcel_urls));
+#else
+ S32 parcel_urls_available = mParcelURLsMax - mParcelURLsUsed;
+
+ LLStringUtil::format_map_t args_parcel_urls;
+ args_parcel_urls["[COUNT]"] = llformat ("%d", mParcelURLsUsed);
+ args_parcel_urls["[MAX]"] = llformat ("%d", mParcelURLsMax);
+ args_parcel_urls["[AVAILABLE]"] = llformat ("%d", parcel_urls_available);
+ std::string msg_parcel_urls = LLTrans::getString("ScriptLimitsURLsUsed", args_parcel_urls);
+ childSetValue("urls_used", LLSD(msg_parcel_urls));
+#endif
+
+ childSetValue("loading_text", LLSD(std::string("")));
+
+ }
+}
+
+void LLPanelScriptLimitsRegionURLs::setRegionSummary(LLSD content)
+{
+ if(content["summary"]["available"][0]["type"].asString() == std::string("urls"))
+ {
+ mParcelURLsMax = content["summary"]["available"][0]["amount"].asInteger();
+ mGotParcelURLsMax = TRUE;
+ }
+ else if(content["summary"]["available"][1]["type"].asString() == std::string("urls"))
+ {
+ mParcelURLsMax = content["summary"]["available"][1]["amount"].asInteger();
+ mGotParcelURLsMax = TRUE;
+ }
+ else
+ {
+ llinfos << "summary contains no url info" << llendl;
+ return;
+ }
+/*
+ currently this is broken on the server, so we get this value from the details section
+ and update via populateParcelMemoryText() when both sets of information have been returned
+
+ when the sim is fixed this should be used instead:
+ if(content["summary"]["used"][0]["type"].asString() == std::string("urls"))
+ {
+ mParcelURLsUsed = content["summary"]["used"][0]["amount"].asInteger();
+ mGotParcelURLsUsed = TRUE;
+ }
+ else if(content["summary"]["used"][1]["type"].asString() == std::string("urls"))
+ {
+ mParcelURLsUsed = content["summary"]["used"][1]["amount"].asInteger();
+ mGotParcelURLsUsed = TRUE;
+ }
+ else
+ {
+ //ERROR!!!
+ return;
+ }*/
+
+ populateParcelURLsText();
+}
+
+BOOL LLPanelScriptLimitsRegionURLs::postBuild()
+{
+ childSetAction("refresh_list_btn", onClickRefresh, this);
+ childSetAction("highlight_btn", onClickHighlight, this);
+ childSetAction("return_btn", onClickReturn, this);
+
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
+ childSetValue("loading_text", LLSD(msg_waiting));
+ return FALSE;
+}
+
+void LLPanelScriptLimitsRegionURLs::clearList()
+{
+ LLCtrlListInterface *list = childGetListInterface("scripts_list");
+
+ if (list)
+ {
+ list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ }
+
+ mGotParcelURLsUsed = FALSE;
+ mGotParcelURLsMax = FALSE;
+
+ LLStringUtil::format_map_t args_parcel_urls;
+ std::string msg_empty_string("");
+ childSetValue("urls_used", LLSD(msg_empty_string));
+ childSetValue("parcels_listed", LLSD(msg_empty_string));
+
+ mObjectListItems.clear();
+}
+
+// static
+void LLPanelScriptLimitsRegionURLs::onClickRefresh(void* userdata)
+{
+ llinfos << "Refresh clicked" << llendl;
+
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ // use the memory panel to re-request all the info
+ panel_memory->clearList();
+
+ LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
+ // but the urls panel to clear itself
+ panel_urls->clearList();
+
+ panel_memory->StartRequestChain();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after refresh button clicked" << llendl;
+ return;
+ }
+}
+
+// static
+void LLPanelScriptLimitsRegionURLs::onClickHighlight(void* userdata)
+{
+/* llinfos << "Highlight clicked" << llendl;
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ // use the beacon function from the memory panel
+ panel->showBeacon();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl;
+// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+// panel->childSetValue("loading_text", LLSD(msg_waiting));
+ return;
+ }*/
+}
+
+// static
+void LLPanelScriptLimitsRegionURLs::onClickReturn(void* userdata)
+{
+/* llinfos << "Return clicked" << llendl;
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ // use the return function from the memory panel
+ panel->returnObjects();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl;
+// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+// panel->childSetValue("loading_text", LLSD(msg_waiting));
+ return;
+ }*/
+}
+
+///----------------------------------------------------------------------------
+// Attachment Panel
+///----------------------------------------------------------------------------
+
+BOOL LLPanelScriptLimitsAttachment::requestAttachmentDetails()
+{
+ LLSD body;
+ std::string url = gAgent.getRegion()->getCapability("AttachmentResources");
+ if (!url.empty())
+ {
+ LLHTTPClient::get(url, body, new fetchScriptLimitsAttachmentInfoResponder());
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+void LLPanelScriptLimitsAttachment::setAttachmentDetails(LLSD content)
+{
+ LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
+ S32 number_attachments = content["attachments"].size();
+
+ for(int i = 0; i < number_attachments; i++)
+ {
+ std::string humanReadableLocation = "";
+ if(content["attachments"][i].has("location"))
+ {
+ std::string actualLocation = content["attachments"][i]["location"];
+ humanReadableLocation = LLTrans::getString(actualLocation.c_str());
+ }
+
+ S32 number_objects = content["attachments"][i]["objects"].size();
+ for(int j = 0; j < number_objects; j++)
+ {
+ LLUUID task_id = content["attachments"][i]["objects"][j]["id"].asUUID();
+ S32 size = 0;
+ if(content["attachments"][i]["objects"][j]["resources"].has("memory"))
+ {
+ size = content["attachments"][i]["objects"][j]["resources"]["memory"].asInteger() / SIZE_OF_ONE_KB;
+ }
+ S32 urls = 0;
+ if(content["attachments"][i]["objects"][j]["resources"].has("urls"))
+ {
+ urls = content["attachments"][i]["objects"][j]["resources"]["urls"].asInteger();
+ }
+ std::string name = content["attachments"][i]["objects"][j]["name"].asString();
+
+ LLSD element;
+
+ element["id"] = task_id;
+ element["columns"][0]["column"] = "size";
+ element["columns"][0]["value"] = llformat("%d", size);
+ element["columns"][0]["font"] = "SANSSERIF";
+
+ element["columns"][1]["column"] = "urls";
+ element["columns"][1]["value"] = llformat("%d", urls);
+ element["columns"][1]["font"] = "SANSSERIF";
+
+ element["columns"][2]["column"] = "name";
+ element["columns"][2]["value"] = name;
+ element["columns"][2]["font"] = "SANSSERIF";
+
+ element["columns"][3]["column"] = "location";
+ element["columns"][3]["value"] = humanReadableLocation;
+ element["columns"][3]["font"] = "SANSSERIF";
+
+ list->addElement(element);
+ }
+ }
+
+ childSetValue("loading_text", LLSD(std::string("")));
+}
+
+BOOL LLPanelScriptLimitsAttachment::postBuild()
+{
+ childSetAction("refresh_list_btn", onClickRefresh, this);
+
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
+ childSetValue("loading_text", LLSD(msg_waiting));
+ return requestAttachmentDetails();
+}
+
+void LLPanelScriptLimitsAttachment::clearList()
+{
+ LLCtrlListInterface *list = childGetListInterface("scripts_list");
+
+ if (list)
+ {
+ list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ }
+
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
+ childSetValue("loading_text", LLSD(msg_waiting));
+}
+
+// static
+void LLPanelScriptLimitsAttachment::onClickRefresh(void* userdata)
+{
+ llinfos << "Refresh clicked" << llendl;
+
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsAttachment* panel_attachments = (LLPanelScriptLimitsAttachment*)tab->getChild<LLPanel>("script_limits_my_avatar_panel");
+ panel_attachments->clearList();
+ panel_attachments->requestAttachmentDetails();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after refresh button clicked" << llendl;
+ return;
+ }
+}
+
diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h
new file mode 100644
index 0000000000..7e2b536eb6
--- /dev/null
+++ b/indra/newview/llfloaterscriptlimits.h
@@ -0,0 +1,263 @@
+/**
+ * @file llfloaterscriptlimits.h
+ * @author Gabriel Lee
+ * @brief Declaration of the region info and controls floater and panels.
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATERSCRIPTLIMITS_H
+#define LL_LLFLOATERSCRIPTLIMITS_H
+
+#include <vector>
+#include "llfloater.h"
+#include "llhost.h"
+#include "llpanel.h"
+#include "llremoteparcelrequest.h"
+
+class LLPanelScriptLimitsInfo;
+class LLTabContainer;
+
+class LLPanelScriptLimitsRegionMemory;
+
+class LLFloaterScriptLimits : public LLFloater
+{
+ friend class LLFloaterReg;
+public:
+
+ /*virtual*/ BOOL postBuild();
+
+ // from LLPanel
+ virtual void refresh();
+
+private:
+
+ LLFloaterScriptLimits(const LLSD& seed);
+ ~LLFloaterScriptLimits();
+
+protected:
+
+ LLTabContainer* mTab;
+ typedef std::vector<LLPanelScriptLimitsInfo*> info_panels_t;
+ info_panels_t mInfoPanels;
+};
+
+
+// Base class for all script limits information panels.
+class LLPanelScriptLimitsInfo : public LLPanel
+{
+public:
+ LLPanelScriptLimitsInfo();
+
+ virtual BOOL postBuild();
+ virtual void updateChild(LLUICtrl* child_ctrl);
+
+protected:
+ void initCtrl(const std::string& name);
+
+ typedef std::vector<std::string> strings_t;
+
+ LLHost mHost;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// Responders
+/////////////////////////////////////////////////////////////////////////////
+
+class fetchScriptLimitsRegionInfoResponder: public LLHTTPClient::Responder
+{
+ public:
+ fetchScriptLimitsRegionInfoResponder(const LLSD& info) : mInfo(info) {};
+
+ void result(const LLSD& content);
+ void error(U32 status, const std::string& reason);
+ public:
+ protected:
+ LLSD mInfo;
+};
+
+class fetchScriptLimitsRegionSummaryResponder: public LLHTTPClient::Responder
+{
+ public:
+ fetchScriptLimitsRegionSummaryResponder(const LLSD& info) : mInfo(info) {};
+
+ void result(const LLSD& content);
+ void error(U32 status, const std::string& reason);
+ public:
+ protected:
+ LLSD mInfo;
+};
+
+class fetchScriptLimitsRegionDetailsResponder: public LLHTTPClient::Responder
+{
+ public:
+ fetchScriptLimitsRegionDetailsResponder(const LLSD& info) : mInfo(info) {};
+
+ void result(const LLSD& content);
+ void error(U32 status, const std::string& reason);
+ public:
+ protected:
+ LLSD mInfo;
+};
+
+class fetchScriptLimitsAttachmentInfoResponder: public LLHTTPClient::Responder
+{
+ public:
+ fetchScriptLimitsAttachmentInfoResponder() {};
+
+ void result(const LLSD& content);
+ void error(U32 status, const std::string& reason);
+ public:
+ protected:
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// Memory panel
+/////////////////////////////////////////////////////////////////////////////
+
+class LLPanelScriptLimitsRegionMemory : public LLPanelScriptLimitsInfo, LLRemoteParcelInfoObserver
+{
+
+public:
+ LLPanelScriptLimitsRegionMemory()
+ : LLPanelScriptLimitsInfo(), LLRemoteParcelInfoObserver(), mParcelId(LLUUID()), mGotParcelMemoryUsed(FALSE), mGotParcelMemoryMax(FALSE) {};
+ ~LLPanelScriptLimitsRegionMemory()
+ {
+ LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this);
+ };
+
+ // LLPanel
+ virtual BOOL postBuild();
+
+ void setRegionDetails(LLSD content);
+ void setRegionSummary(LLSD content);
+
+ BOOL StartRequestChain();
+
+ void populateParcelMemoryText();
+ BOOL getLandScriptResources();
+ void clearList();
+ void showBeacon();
+ void returnObjects();
+
+private:
+
+ void onNameCache( const LLUUID& id,
+ const std::string& first_name,
+ const std::string& last_name);
+
+ LLUUID mParcelId;
+ BOOL mGotParcelMemoryUsed;
+ BOOL mGotParcelMemoryMax;
+ S32 mParcelMemoryMax;
+ S32 mParcelMemoryUsed;
+
+ std::vector<LLSD> mObjectListItems;
+
+protected:
+
+// LLRemoteParcelInfoObserver interface:
+/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
+/*virtual*/ void setParcelID(const LLUUID& parcel_id);
+/*virtual*/ void setErrorStatus(U32 status, const std::string& reason);
+
+ static void onClickRefresh(void* userdata);
+ static void onClickHighlight(void* userdata);
+ static void onClickReturn(void* userdata);
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// URLs panel
+/////////////////////////////////////////////////////////////////////////////
+
+class LLPanelScriptLimitsRegionURLs : public LLPanelScriptLimitsInfo
+{
+
+public:
+ LLPanelScriptLimitsRegionURLs()
+ : LLPanelScriptLimitsInfo(), mParcelId(LLUUID()), mGotParcelURLsUsed(FALSE), mGotParcelURLsMax(FALSE) {};
+ ~LLPanelScriptLimitsRegionURLs()
+ {
+ };
+
+ // LLPanel
+ virtual BOOL postBuild();
+
+ void setRegionDetails(LLSD content);
+ void setRegionSummary(LLSD content);
+
+ void populateParcelURLsText();
+ void clearList();
+
+private:
+
+ LLUUID mParcelId;
+ BOOL mGotParcelURLsUsed;
+ BOOL mGotParcelURLsMax;
+ S32 mParcelURLsMax;
+ S32 mParcelURLsUsed;
+
+ std::vector<LLSD> mObjectListItems;
+
+protected:
+
+ static void onClickRefresh(void* userdata);
+ static void onClickHighlight(void* userdata);
+ static void onClickReturn(void* userdata);
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// Attachment panel
+/////////////////////////////////////////////////////////////////////////////
+
+class LLPanelScriptLimitsAttachment : public LLPanelScriptLimitsInfo
+{
+
+public:
+ LLPanelScriptLimitsAttachment()
+ : LLPanelScriptLimitsInfo() {};
+ ~LLPanelScriptLimitsAttachment()
+ {
+ };
+
+ // LLPanel
+ virtual BOOL postBuild();
+
+ void setAttachmentDetails(LLSD content);
+
+ BOOL requestAttachmentDetails();
+ void clearList();
+
+private:
+
+protected:
+
+ static void onClickRefresh(void* userdata);
+};
+
+#endif
diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp
new file mode 100644
index 0000000000..a7401fdb6f
--- /dev/null
+++ b/indra/newview/llfloatersearch.cpp
@@ -0,0 +1,221 @@
+/**
+ * @file llfloatersearch.cpp
+ * @author Martin Reddy
+ * @brief Search floater - uses an embedded web browser control
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llcommandhandler.h"
+#include "llfloaterreg.h"
+#include "llfloatersearch.h"
+#include "llmediactrl.h"
+#include "lllogininstance.h"
+#include "lluri.h"
+#include "llagent.h"
+#include "llui.h"
+#include "llviewercontrol.h"
+#include "llweb.h"
+
+// support secondlife:///app/search/{CATEGORY}/{QUERY} SLapps
+class LLSearchHandler : public LLCommandHandler
+{
+public:
+ // requires trusted browser to trigger
+ LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_THROTTLE) { }
+ bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
+ {
+ const size_t parts = tokens.size();
+
+ // get the (optional) category for the search
+ std::string category;
+ if (parts > 0)
+ {
+ category = tokens[0].asString();
+ }
+
+ // get the (optional) search string
+ std::string search_text;
+ if (parts > 1)
+ {
+ search_text = tokens[1].asString();
+ }
+
+ // create the LLSD arguments for the search floater
+ LLSD args;
+ args["category"] = category;
+ args["id"] = LLURI::unescape(search_text);
+
+ // open the search floater and perform the requested search
+ LLFloaterReg::showInstance("search", args);
+ return true;
+ }
+};
+LLSearchHandler gSearchHandler;
+
+LLFloaterSearch::LLFloaterSearch(const LLSD& key) :
+ LLFloater(key),
+ LLViewerMediaObserver(),
+ mBrowser(NULL),
+ mSearchGodLevel(0)
+{
+ // 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["destinations"] = "destinations";
+ mCategoryPaths["classifieds"] = "classifieds";
+}
+
+BOOL LLFloaterSearch::postBuild()
+{
+ mBrowser = getChild<LLMediaCtrl>("browser");
+ if (mBrowser)
+ {
+ mBrowser->addObserver(this);
+ mBrowser->setTrusted(true);
+ }
+
+ return TRUE;
+}
+
+void LLFloaterSearch::onOpen(const LLSD& key)
+{
+ search(key);
+}
+
+void LLFloaterSearch::onClose(bool app_quitting)
+{
+ if (! app_quitting)
+ {
+ // Show the blank home page ready for the next onOpen()
+ mBrowser->navigateHome();
+ }
+}
+
+void LLFloaterSearch::handleMediaEvent(LLPluginClassMedia *self, EMediaEvent event)
+{
+ switch (event)
+ {
+ case MEDIA_EVENT_NAVIGATE_BEGIN:
+ childSetText("status_text", getString("loading_text"));
+ break;
+
+ case MEDIA_EVENT_NAVIGATE_COMPLETE:
+ childSetText("status_text", getString("done_text"));
+ break;
+
+ default:
+ break;
+ }
+}
+
+void LLFloaterSearch::godLevelChanged(U8 godlevel)
+{
+ // search results can change based upon god level - if the user
+ // changes god level, then give them a warning (we don't refresh
+ // the search as this might undo any page navigation or
+ // AJAX-driven changes since the last search).
+ childSetVisible("refresh_search", (godlevel != mSearchGodLevel));
+}
+
+void LLFloaterSearch::search(const LLSD &key)
+{
+ if (! mBrowser)
+ {
+ return;
+ }
+
+ // display the blank home page first, to clear the display of
+ // any previous search results while the new results load.
+ // The home page is set in floater_search.xml as start_url.
+ mBrowser->navigateHome();
+
+ // reset the god level warning as we're sending the latest state
+ childHide("refresh_search");
+ mSearchGodLevel = gAgent.getGodLevel();
+
+ // work out the subdir to use based on the requested category
+ LLSD subs;
+ std::string category = key.has("category") ? key["category"].asString() : "";
+ if (mCategoryPaths.has(category))
+ {
+ subs["CATEGORY"] = mCategoryPaths[category].asString();
+ }
+ else
+ {
+ subs["CATEGORY"] = mCategoryPaths["all"].asString();
+ }
+
+ // add the search query string
+ std::string search_text = key.has("id") ? key["id"].asString() : "";
+ subs["QUERY"] = LLURI::escape(search_text);
+
+ // add the permissions token that login.cgi gave us
+ // We use "search_token", and fallback to "auth_token" if not present.
+ LLSD search_token = LLLoginInstance::getInstance()->getResponse("search_token");
+ if (search_token.asString().empty())
+ {
+ search_token = LLLoginInstance::getInstance()->getResponse("auth_token");
+ }
+ subs["AUTH_TOKEN"] = search_token.asString();
+
+ // add the user's preferred maturity (can be changed via prefs)
+ std::string maturity;
+ if (gAgent.prefersAdult())
+ {
+ maturity = "42"; // PG,Mature,Adult
+ }
+ else if (gAgent.prefersMature())
+ {
+ maturity = "21"; // PG,Mature
+ }
+ else
+ {
+ maturity = "13"; // PG
+ }
+ subs["MATURITY"] = maturity;
+
+ // add the user's god status
+ subs["GODLIKE"] = gAgent.isGodlike() ? "1" : "0";
+
+ // get the search URL and expand all of the substitutions
+ // (also adds things like [LANGUAGE], [VERSION], [OS], etc.)
+ std::string url = gSavedSettings.getString("SearchURL");
+ url = LLWeb::expandURLSubstitutions(url, subs);
+
+ // and load the URL in the web view
+ mBrowser->navigateTo(url);
+}
diff --git a/indra/newview/llfloatersearch.h b/indra/newview/llfloatersearch.h
new file mode 100644
index 0000000000..0a8d9bbe36
--- /dev/null
+++ b/indra/newview/llfloatersearch.h
@@ -0,0 +1,88 @@
+/**
+ * @file llfloatersearch.h
+ * @author Martin Reddy
+ * @brief Search floater - uses an embedded web browser control
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATERSEARCH_H
+#define LL_LLFLOATERSEARCH_H
+
+#include "llfloater.h"
+#include "llviewermediaobserver.h"
+
+#include <string>
+
+class LLMediaCtrl;
+
+///
+/// The search floater allows users to perform all search operations.
+/// All search functionality is now implemented via web services and
+/// so this floater simply embeds a web view and displays the search
+/// web page. The browser control is explicitly marked as "trusted"
+/// so that the user can click on teleport links in search results.
+///
+class LLFloaterSearch :
+ public LLFloater,
+ public LLViewerMediaObserver
+{
+public:
+ LLFloaterSearch(const LLSD& key);
+
+ /// show the search floater with a new search
+ /// see search() for details on the key parameter.
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ /*virtual*/ void onClose(bool app_quitting);
+
+ /// perform a search with the specific search term.
+ /// The key should be a map that can contain the following keys:
+ /// - "id": specifies the text phrase to search for
+ /// - "category": one of "all" (default), "people", "places",
+ /// "events", "groups", "wiki", "destinations", "classifieds"
+ void search(const LLSD &key);
+
+ /// changing godmode can affect the search results that are
+ /// returned by the search website - use this method to tell the
+ /// search floater that the user has changed god level.
+ void godLevelChanged(U8 godlevel);
+
+private:
+ /*virtual*/ BOOL postBuild();
+
+ // inherited from LLViewerMediaObserver
+ /*virtual*/ void handleMediaEvent(LLPluginClassMedia *self, EMediaEvent event);
+
+ LLMediaCtrl *mBrowser;
+ LLSD mCategoryPaths;
+ U8 mSearchGodLevel;
+};
+
+#endif // LL_LLFLOATERSEARCH_H
+
diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp
index 92e070f766..e2b0c4b66f 100644
--- a/indra/newview/llfloatersellland.cpp
+++ b/indra/newview/llfloatersellland.cpp
@@ -34,10 +34,11 @@
#include "llfloatersellland.h"
#include "llfloateravatarpicker.h"
-#include "llfloater.h"
+#include "llfloaterreg.h"
#include "llfloaterland.h"
#include "lllineeditor.h"
-#include "llnotify.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
#include "llparcel.h"
#include "llselectmgr.h"
#include "lltexturectrl.h"
@@ -47,7 +48,7 @@
#include "llviewerwindow.h"
// defined in llfloaterland.cpp
-void send_parcel_select_objects(S32 parcel_local_id, S32 return_type,
+void send_parcel_select_objects(S32 parcel_local_id, U32 return_type,
uuid_list_t* return_ids = NULL);
enum Badge { BADGE_OK, BADGE_NOTE, BADGE_WARN, BADGE_ERROR };
@@ -55,10 +56,22 @@ enum Badge { BADGE_OK, BADGE_NOTE, BADGE_WARN, BADGE_ERROR };
class LLFloaterSellLandUI
: public LLFloater
{
-private:
- LLFloaterSellLandUI();
+public:
+ LLFloaterSellLandUI(const LLSD& key);
virtual ~LLFloaterSellLandUI();
-
+ /*virtual*/ void onClose(bool app_quitting);
+
+private:
+ class SelectionObserver : public LLParcelObserver
+ {
+ public:
+ SelectionObserver(LLFloaterSellLandUI* floater) : mFloater(floater) {}
+ virtual void changed();
+ private:
+ LLFloaterSellLandUI* mFloater;
+ };
+
+private:
LLViewerRegion* mRegion;
LLParcelSelectionHandle mParcelSelection;
bool mParcelIsForSale;
@@ -69,110 +82,81 @@ private:
LLUUID mParcelSnapshot;
LLUUID mAuthorizedBuyer;
bool mParcelSoldWithObjects;
+ SelectionObserver mParcelSelectionObserver;
void updateParcelInfo();
void refreshUI();
void setBadge(const char* id, Badge badge);
- static LLFloaterSellLandUI* sInstance;
-
static void onChangeValue(LLUICtrl *ctrl, void *userdata);
- static void doSelectAgent(void *userdata);
+ void doSelectAgent();
static void doCancel(void *userdata);
static void doSellLand(void *userdata);
bool onConfirmSale(const LLSD& notification, const LLSD& response);
static void doShowObjects(void *userdata);
static bool callbackHighlightTransferable(const LLSD& notification, const LLSD& response);
- static void callbackAvatarPick(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data);
+ void callbackAvatarPick(const std::vector<std::string>& names, const std::vector<LLUUID>& ids);
public:
virtual BOOL postBuild();
- virtual void onClose(bool app_quitting);
- static LLFloaterSellLandUI* soleInstance(bool createIfNeeded);
-
bool setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel);
-
-private:
- class SelectionObserver : public LLParcelObserver
- {
- public:
- virtual void changed();
- };
};
// static
void LLFloaterSellLand::sellLand(
LLViewerRegion* region, LLParcelSelectionHandle parcel)
{
- LLFloaterSellLandUI* ui = LLFloaterSellLandUI::soleInstance(true);
- if (ui->setParcel(region, parcel))
- {
- ui->open(); /* Flawfinder: ignore */
- }
+ LLFloaterSellLandUI* ui = LLFloaterReg::showTypedInstance<LLFloaterSellLandUI>("sell_land");
+ ui->setParcel(region, parcel);
}
// static
-LLFloaterSellLandUI* LLFloaterSellLandUI::sInstance = NULL;
-
-// static
-LLFloaterSellLandUI* LLFloaterSellLandUI::soleInstance(bool createIfNeeded)
+LLFloater* LLFloaterSellLand::buildFloater(const LLSD& key)
{
- if (!sInstance && createIfNeeded)
- {
- sInstance = new LLFloaterSellLandUI();
-
- LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_sell_land.xml");
- sInstance->center();
- }
-
-
- static SelectionObserver* parcelSelectionObserver = NULL;
- if (!parcelSelectionObserver)
- {
- parcelSelectionObserver = new SelectionObserver;
- LLViewerParcelMgr::getInstance()->addObserver(parcelSelectionObserver);
- }
-
- return sInstance;
+ LLFloaterSellLandUI* floater = new LLFloaterSellLandUI(key);
+ return floater;
}
-LLFloaterSellLandUI::LLFloaterSellLandUI()
-: LLFloater(std::string("Sell Land")),
+#if LL_WINDOWS
+// passing 'this' during construction generates a warning. The callee
+// only uses the pointer to hold a reference to 'this' which is
+// already valid, so this call does the correct thing. Disable the
+// warning so that we can compile without generating a warning.
+#pragma warning(disable : 4355)
+#endif
+LLFloaterSellLandUI::LLFloaterSellLandUI(const LLSD& key)
+: LLFloater(key),
+ mParcelSelectionObserver(this),
mRegion(0)
{
+ LLViewerParcelMgr::getInstance()->addObserver(&mParcelSelectionObserver);
}
LLFloaterSellLandUI::~LLFloaterSellLandUI()
{
- if (sInstance == this)
- {
- sInstance = NULL;
- }
+ LLViewerParcelMgr::getInstance()->removeObserver(&mParcelSelectionObserver);
}
-void LLFloaterSellLandUI::SelectionObserver::changed()
+// Because we are single_instance, we are not destroyed on close.
+void LLFloaterSellLandUI::onClose(bool app_quitting)
{
- LLFloaterSellLandUI* ui = LLFloaterSellLandUI::soleInstance(false);
- if (ui)
- {
- if (LLViewerParcelMgr::getInstance()->selectionEmpty())
- {
- ui->close();
- }
- else {
- ui->setParcel(
- LLViewerParcelMgr::getInstance()->getSelectionRegion(),
- LLViewerParcelMgr::getInstance()->getParcelSelection());
- }
- }
+ // Must release parcel selection to allow land to deselect, see EXT-803
+ mParcelSelection = NULL;
}
-void LLFloaterSellLandUI::onClose(bool app_quitting)
+void LLFloaterSellLandUI::SelectionObserver::changed()
{
- LLFloater::onClose(app_quitting);
- destroy();
+ if (LLViewerParcelMgr::getInstance()->selectionEmpty())
+ {
+ mFloater->closeFloater();
+ }
+ else if (mFloater->getVisible()) // only update selection if sell land ui in use
+ {
+ mFloater->setParcel(LLViewerParcelMgr::getInstance()->getSelectionRegion(),
+ LLViewerParcelMgr::getInstance()->getParcelSelection());
+ }
}
BOOL LLFloaterSellLandUI::postBuild()
@@ -181,16 +165,17 @@ BOOL LLFloaterSellLandUI::postBuild()
childSetCommitCallback("price", onChangeValue, this);
childSetPrevalidate("price", LLLineEditor::prevalidateNonNegativeS32);
childSetCommitCallback("sell_objects", onChangeValue, this);
- childSetAction("sell_to_select_agent", doSelectAgent, this);
+ childSetAction("sell_to_select_agent", boost::bind( &LLFloaterSellLandUI::doSelectAgent, this));
childSetAction("cancel_btn", doCancel, this);
childSetAction("sell_btn", doSellLand, this);
childSetAction("show_objects", doShowObjects, this);
+ center();
return TRUE;
}
bool LLFloaterSellLandUI::setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel)
{
- if (!parcel->getParcel()) // || !can_agent_modify_parcel(parcel)) // can_agent_modify_parcel was deprecated by GROUPS
+ if (!parcel->getParcel())
{
return false;
}
@@ -276,10 +261,7 @@ void LLFloaterSellLandUI::refreshUI()
if (!parcelp) return;
LLTextureCtrl* snapshot = getChild<LLTextureCtrl>("info_image");
- if (snapshot)
- {
- snapshot->setImageAssetID(mParcelSnapshot);
- }
+ snapshot->setImageAssetID(mParcelSnapshot);
childSetText("info_parcel", parcelp->getName());
childSetTextArg("info_size", "[AREA]", llformat("%d", mParcelActualArea));
@@ -379,7 +361,7 @@ void LLFloaterSellLandUI::onChangeValue(LLUICtrl *ctrl, void *userdata)
self->mSellToBuyer = true;
if (self->mAuthorizedBuyer.isNull())
{
- doSelectAgent(self);
+ self->doSelectAgent();
}
}
else if (sell_to == "anyone")
@@ -402,37 +384,33 @@ void LLFloaterSellLandUI::onChangeValue(LLUICtrl *ctrl, void *userdata)
self->refreshUI();
}
-// static
-void LLFloaterSellLandUI::doSelectAgent(void *userdata)
+void LLFloaterSellLandUI::doSelectAgent()
{
- LLFloaterSellLandUI* floaterp = (LLFloaterSellLandUI*)userdata;
// grandparent is a floater, in order to set up dependency
- floaterp->addDependentFloater(LLFloaterAvatarPicker::show(callbackAvatarPick, floaterp, FALSE, TRUE));
+ addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLFloaterSellLandUI::callbackAvatarPick, this, _1, _2), FALSE, TRUE));
}
-// static
-void LLFloaterSellLandUI::callbackAvatarPick(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data)
+void LLFloaterSellLandUI::callbackAvatarPick(const std::vector<std::string>& names, const std::vector<LLUUID>& ids)
{
- LLFloaterSellLandUI* floaterp = (LLFloaterSellLandUI*)data;
- LLParcel* parcel = floaterp->mParcelSelection->getParcel();
+ LLParcel* parcel = mParcelSelection->getParcel();
if (names.empty() || ids.empty()) return;
LLUUID id = ids[0];
parcel->setAuthorizedBuyerID(id);
- floaterp->mAuthorizedBuyer = ids[0];
+ mAuthorizedBuyer = ids[0];
- floaterp->childSetText("sell_to_agent", names[0]);
+ childSetText("sell_to_agent", names[0]);
- floaterp->refreshUI();
+ refreshUI();
}
// static
void LLFloaterSellLandUI::doCancel(void *userdata)
{
LLFloaterSellLandUI* self = (LLFloaterSellLandUI*)userdata;
- self->close();
+ self->closeFloater();
}
// static
@@ -444,7 +422,7 @@ void LLFloaterSellLandUI::doShowObjects(void *userdata)
send_parcel_select_objects(parcel->getLocalID(), RT_SELL);
- LLNotifications::instance().add("TransferObjectsHighlighted",
+ LLNotificationsUtil::add("TransferObjectsHighlighted",
LLSD(), LLSD(),
&LLFloaterSellLandUI::callbackHighlightTransferable);
}
@@ -479,7 +457,7 @@ void LLFloaterSellLandUI::doSellLand(void *userdata)
&& (sale_price == 0)
&& sell_to_anyone)
{
- LLNotifications::instance().add("SalePriceRestriction");
+ LLNotificationsUtil::add("SalePriceRestriction");
return;
}
@@ -490,7 +468,7 @@ void LLFloaterSellLandUI::doSellLand(void *userdata)
LLNotification::Params params("ConfirmLandSaleChange");
params.substitutions(args)
- .functor(boost::bind(&LLFloaterSellLandUI::onConfirmSale, self, _1, _2));
+ .functor.function(boost::bind(&LLFloaterSellLandUI::onConfirmSale, self, _1, _2));
if (sell_to_anyone)
{
@@ -512,7 +490,7 @@ void LLFloaterSellLandUI::doSellLand(void *userdata)
bool LLFloaterSellLandUI::onConfirmSale(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option != 0)
{
return false;
@@ -556,6 +534,6 @@ bool LLFloaterSellLandUI::onConfirmSale(const LLSD& notification, const LLSD& re
// Send update to server
LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel );
- close();
+ closeFloater();
return false;
}
diff --git a/indra/newview/llfloatersellland.h b/indra/newview/llfloatersellland.h
index 1b3a33ebb8..1adf08052b 100644
--- a/indra/newview/llfloatersellland.h
+++ b/indra/newview/llfloatersellland.h
@@ -31,8 +31,10 @@
#ifndef LL_LLFLOATERSELLLAND_H
#define LL_LLFLOATERSELLLAND_H
-#include "llmemory.h"
+#include "llsafehandle.h"
+
+class LLFloater;
class LLParcel;
class LLViewerRegion;
class LLParcelSelection;
@@ -42,6 +44,8 @@ class LLFloaterSellLand
public:
static void sellLand(LLViewerRegion* region,
LLSafeHandle<LLParcelSelection> parcel);
+
+ static LLFloater* buildFloater(const LLSD& key);
};
#endif // LL_LLFLOATERSELLLAND_H
diff --git a/indra/newview/llfloatersettingsdebug.cpp b/indra/newview/llfloatersettingsdebug.cpp
index 2677467611..a6ffa5ec09 100644
--- a/indra/newview/llfloatersettingsdebug.cpp
+++ b/indra/newview/llfloatersettingsdebug.cpp
@@ -34,22 +34,26 @@
#include "llfloatersettingsdebug.h"
#include "llfloater.h"
#include "lluictrlfactory.h"
-#include "llfirstuse.h"
+//#include "llfirstuse.h"
#include "llcombobox.h"
#include "llspinctrl.h"
#include "llcolorswatch.h"
#include "llviewercontrol.h"
+#include "lltexteditor.h"
-LLFloaterSettingsDebug* LLFloaterSettingsDebug::sInstance = NULL;
-LLFloaterSettingsDebug::LLFloaterSettingsDebug() : LLFloater(std::string("Configuration Editor"))
+LLFloaterSettingsDebug::LLFloaterSettingsDebug(const LLSD& key)
+: LLFloater(key)
{
+ //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_settings_debug.xml");
+ mCommitCallbackRegistrar.add("SettingSelect", boost::bind(&LLFloaterSettingsDebug::onSettingSelect, this,_1));
+ mCommitCallbackRegistrar.add("CommitSettings", boost::bind(&LLFloaterSettingsDebug::onCommitSettings, this));
+ mCommitCallbackRegistrar.add("ClickDefault", boost::bind(&LLFloaterSettingsDebug::onClickDefault, this));
+
}
LLFloaterSettingsDebug::~LLFloaterSettingsDebug()
-{
- sInstance = NULL;
-}
+{}
BOOL LLFloaterSettingsDebug::postBuild()
{
@@ -68,30 +72,18 @@ BOOL LLFloaterSettingsDebug::postBuild()
}
} func(settings_combo);
- gSavedSettings.applyToAll(&func);
- gSavedPerAccountSettings.applyToAll(&func);
- gColors.applyToAll(&func);
+ std::string key = getKey().asString();
+ if (key == "all" || key == "base")
+ {
+ gSavedSettings.applyToAll(&func);
+ }
+ if (key == "all" || key == "account")
+ {
+ gSavedPerAccountSettings.applyToAll(&func);
+ }
settings_combo->sortByName();
- settings_combo->setCommitCallback(onSettingSelect);
- settings_combo->setCallbackUserData(this);
settings_combo->updateSelection();
-
- childSetCommitCallback("val_spinner_1", onCommitSettings);
- childSetUserData("val_spinner_1", this);
- childSetCommitCallback("val_spinner_2", onCommitSettings);
- childSetUserData("val_spinner_2", this);
- childSetCommitCallback("val_spinner_3", onCommitSettings);
- childSetUserData("val_spinner_3", this);
- childSetCommitCallback("val_spinner_4", onCommitSettings);
- childSetUserData("val_spinner_4", this);
- childSetCommitCallback("val_text", onCommitSettings);
- childSetUserData("val_text", this);
- childSetCommitCallback("boolean_combo", onCommitSettings);
- childSetUserData("boolean_combo", this);
- childSetCommitCallback("color_swatch", onCommitSettings);
- childSetUserData("color_swatch", this);
- childSetAction("default_btn", onClickDefault, this);
mComment = getChild<LLTextEditor>("comment_text");
return TRUE;
}
@@ -105,37 +97,25 @@ void LLFloaterSettingsDebug::draw()
LLFloater::draw();
}
-//static
-void LLFloaterSettingsDebug::show(void*)
-{
- if (sInstance == NULL)
- {
- sInstance = new LLFloaterSettingsDebug();
-
- LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_settings_debug.xml");
- }
-
- sInstance->open(); /* Flawfinder: ignore */
-}
-
//static
-void LLFloaterSettingsDebug::onSettingSelect(LLUICtrl* ctrl, void* user_data)
+void LLFloaterSettingsDebug::onSettingSelect(LLUICtrl* ctrl)
{
- LLFloaterSettingsDebug* floaterp = (LLFloaterSettingsDebug*)user_data;
LLComboBox* combo_box = (LLComboBox*)ctrl;
LLControlVariable* controlp = (LLControlVariable*)combo_box->getCurrentUserdata();
- floaterp->updateControl(controlp);
+ updateControl(controlp);
}
-//static
-void LLFloaterSettingsDebug::onCommitSettings(LLUICtrl* ctrl, void* user_data)
+void LLFloaterSettingsDebug::onCommitSettings()
{
- LLFloaterSettingsDebug* floaterp = (LLFloaterSettingsDebug*)user_data;
-
- LLComboBox* settings_combo = floaterp->getChild<LLComboBox>("settings_combo");
+ LLComboBox* settings_combo = getChild<LLComboBox>("settings_combo");
LLControlVariable* controlp = (LLControlVariable*)settings_combo->getCurrentUserdata();
+ if (!controlp)
+ {
+ return;
+ }
+
LLVector3 vector;
LLVector3d vectord;
LLRect rect;
@@ -147,73 +127,66 @@ void LLFloaterSettingsDebug::onCommitSettings(LLUICtrl* ctrl, void* user_data)
switch(controlp->type())
{
case TYPE_U32:
- controlp->set(floaterp->childGetValue("val_spinner_1"));
+ controlp->set(childGetValue("val_spinner_1"));
break;
case TYPE_S32:
- controlp->set(floaterp->childGetValue("val_spinner_1"));
+ controlp->set(childGetValue("val_spinner_1"));
break;
case TYPE_F32:
- controlp->set(LLSD(floaterp->childGetValue("val_spinner_1").asReal()));
+ controlp->set(LLSD(childGetValue("val_spinner_1").asReal()));
break;
case TYPE_BOOLEAN:
- controlp->set(floaterp->childGetValue("boolean_combo"));
+ controlp->set(childGetValue("boolean_combo"));
break;
case TYPE_STRING:
- controlp->set(LLSD(floaterp->childGetValue("val_text").asString()));
+ controlp->set(LLSD(childGetValue("val_text").asString()));
break;
case TYPE_VEC3:
- vector.mV[VX] = (F32)floaterp->childGetValue("val_spinner_1").asReal();
- vector.mV[VY] = (F32)floaterp->childGetValue("val_spinner_2").asReal();
- vector.mV[VZ] = (F32)floaterp->childGetValue("val_spinner_3").asReal();
+ vector.mV[VX] = (F32)childGetValue("val_spinner_1").asReal();
+ vector.mV[VY] = (F32)childGetValue("val_spinner_2").asReal();
+ vector.mV[VZ] = (F32)childGetValue("val_spinner_3").asReal();
controlp->set(vector.getValue());
break;
case TYPE_VEC3D:
- vectord.mdV[VX] = floaterp->childGetValue("val_spinner_1").asReal();
- vectord.mdV[VY] = floaterp->childGetValue("val_spinner_2").asReal();
- vectord.mdV[VZ] = floaterp->childGetValue("val_spinner_3").asReal();
+ vectord.mdV[VX] = childGetValue("val_spinner_1").asReal();
+ vectord.mdV[VY] = childGetValue("val_spinner_2").asReal();
+ vectord.mdV[VZ] = childGetValue("val_spinner_3").asReal();
controlp->set(vectord.getValue());
break;
case TYPE_RECT:
- rect.mLeft = floaterp->childGetValue("val_spinner_1").asInteger();
- rect.mRight = floaterp->childGetValue("val_spinner_2").asInteger();
- rect.mBottom = floaterp->childGetValue("val_spinner_3").asInteger();
- rect.mTop = floaterp->childGetValue("val_spinner_4").asInteger();
+ rect.mLeft = childGetValue("val_spinner_1").asInteger();
+ rect.mRight = childGetValue("val_spinner_2").asInteger();
+ rect.mBottom = childGetValue("val_spinner_3").asInteger();
+ rect.mTop = childGetValue("val_spinner_4").asInteger();
controlp->set(rect.getValue());
break;
case TYPE_COL4:
- col3.setValue(floaterp->childGetValue("color_swatch"));
- col4 = LLColor4(col3, (F32)floaterp->childGetValue("val_spinner_4").asReal());
+ col3.setValue(childGetValue("val_color_swatch"));
+ col4 = LLColor4(col3, (F32)childGetValue("val_spinner_4").asReal());
controlp->set(col4.getValue());
break;
case TYPE_COL3:
- controlp->set(floaterp->childGetValue("color_swatch"));
+ controlp->set(childGetValue("val_color_swatch"));
//col3.mV[VRED] = (F32)floaterp->childGetValue("val_spinner_1").asC();
//col3.mV[VGREEN] = (F32)floaterp->childGetValue("val_spinner_2").asReal();
//col3.mV[VBLUE] = (F32)floaterp->childGetValue("val_spinner_3").asReal();
//controlp->set(col3.getValue());
break;
- case TYPE_COL4U:
- col3.setValue(floaterp->childGetValue("color_swatch"));
- col4U.setVecScaleClamp(col3);
- col4U.mV[VALPHA] = floaterp->childGetValue("val_spinner_4").asInteger();
- controlp->set(col4U.getValue());
- break;
default:
break;
}
}
// static
-void LLFloaterSettingsDebug::onClickDefault(void* user_data)
+void LLFloaterSettingsDebug::onClickDefault()
{
- LLFloaterSettingsDebug* floaterp = (LLFloaterSettingsDebug*)user_data;
- LLComboBox* settings_combo = floaterp->getChild<LLComboBox>("settings_combo");
+ LLComboBox* settings_combo = getChild<LLComboBox>("settings_combo");
LLControlVariable* controlp = (LLControlVariable*)settings_combo->getCurrentUserdata();
if (controlp)
{
controlp->resetToDefault();
- floaterp->updateControl(controlp);
+ updateControl(controlp);
}
}
@@ -224,7 +197,7 @@ void LLFloaterSettingsDebug::updateControl(LLControlVariable* controlp)
LLSpinCtrl* spinner2 = getChild<LLSpinCtrl>("val_spinner_2");
LLSpinCtrl* spinner3 = getChild<LLSpinCtrl>("val_spinner_3");
LLSpinCtrl* spinner4 = getChild<LLSpinCtrl>("val_spinner_4");
- LLColorSwatchCtrl* color_swatch = getChild<LLColorSwatchCtrl>("color_swatch");
+ LLColorSwatchCtrl* color_swatch = getChild<LLColorSwatchCtrl>("val_color_swatch");
if (!spinner1 || !spinner2 || !spinner3 || !spinner4 || !color_swatch)
{
@@ -464,29 +437,6 @@ void LLFloaterSettingsDebug::updateControl(LLControlVariable* controlp)
color_swatch->setValue(sd);
break;
}
- case TYPE_COL4U:
- {
- LLColor4U clr;
- clr.setValue(sd);
- color_swatch->setVisible(TRUE);
- if(LLColor4(clr) != LLColor4(color_swatch->getValue()))
- {
- color_swatch->set(LLColor4(clr), TRUE, FALSE);
- }
- spinner4->setVisible(TRUE);
- spinner4->setLabel(std::string("Alpha"));
- if(!spinner4->hasFocus())
- {
- spinner4->setPrecision(0);
- spinner4->setValue(clr.mV[VALPHA]);
- }
-
- spinner4->setMinValue(0);
- spinner4->setMaxValue(255);
- spinner4->setIncrement(1.f);
-
- break;
- }
default:
mComment->setText(std::string("unknown"));
break;
diff --git a/indra/newview/llfloatersettingsdebug.h b/indra/newview/llfloatersettingsdebug.h
index e08e6b5d74..65803fbf70 100644
--- a/indra/newview/llfloatersettingsdebug.h
+++ b/indra/newview/llfloatersettingsdebug.h
@@ -35,27 +35,31 @@
#include "llcontrol.h"
#include "llfloater.h"
-#include "lltexteditor.h"
-class LLFloaterSettingsDebug : public LLFloater
+class LLFloaterSettingsDebug
+: public LLFloater
{
+ friend class LLFloaterReg;
+
public:
- LLFloaterSettingsDebug();
- virtual ~LLFloaterSettingsDebug();
virtual BOOL postBuild();
virtual void draw();
void updateControl(LLControlVariable* control);
- static void show(void*);
- static void onSettingSelect(LLUICtrl* ctrl, void* user_data);
- static void onCommitSettings(LLUICtrl* ctrl, void* user_data);
- static void onClickDefault(void* user_data);
+ void onSettingSelect(LLUICtrl* ctrl);
+ void onCommitSettings();
+ void onClickDefault();
+private:
+ // key - selects which settings to show, one of:
+ // "all", "base", "account", "skin"
+ LLFloaterSettingsDebug(const LLSD& key);
+ virtual ~LLFloaterSettingsDebug();
+
protected:
- static LLFloaterSettingsDebug* sInstance;
- LLTextEditor* mComment;
+ class LLTextEditor* mComment;
};
#endif //LLFLOATERDEBUGSETTINGS_H
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index e68d699d03..afb58c9407 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -34,20 +34,13 @@
#include "llfloatersnapshot.h"
-#include "llfontgl.h"
-#include "llsys.h"
-#include "llgl.h"
-#include "llrender.h"
-#include "v3dmath.h"
-#include "llmath.h"
-#include "lldir.h"
-#include "llsdserialize.h"
+#include "llfloaterreg.h"
+// Viewer includes
#include "llagent.h"
#include "llcallbacklist.h"
#include "llcriticaldamp.h"
#include "llui.h"
-#include "llviewertexteditor.h"
#include "llfocusmgr.h"
#include "llbutton.h"
#include "llcombobox.h"
@@ -66,15 +59,28 @@
#include "lltoolfocus.h"
#include "lltoolmgr.h"
#include "llworld.h"
+#include "llagentui.h"
+// Linden library includes
+#include "llfontgl.h"
+#include "llsys.h"
+#include "llrender.h"
+#include "v3dmath.h"
+#include "llmath.h"
+#include "lldir.h"
+#include "llsdserialize.h"
#include "llgl.h"
#include "llglheaders.h"
#include "llimagejpeg.h"
#include "llimagepng.h"
#include "llimagebmp.h"
#include "llimagej2c.h"
+#include "lllocalcliprect.h"
+#include "llnotificationsutil.h"
+#include "llresmgr.h" // LLLocale
#include "llvfile.h"
#include "llvfs.h"
+#include "llwindow.h"
///----------------------------------------------------------------------------
/// Local function declarations, constants, enums, and typedefs
@@ -85,8 +91,6 @@ S32 LLFloaterSnapshot::sUIWinWidth = 215 ;
LLSnapshotFloaterView* gSnapshotFloaterView = NULL;
-LLFloaterSnapshot* LLFloaterSnapshot::sInstance = NULL;
-
const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f;
F32 SHINE_TIME = 0.5f;
@@ -98,6 +102,8 @@ S32 BORDER_WIDTH = 6;
const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512
+static LLDefaultChildRegistry::Register<LLSnapshotFloaterView> r("snapshot_floater_view");
+
///----------------------------------------------------------------------------
/// Class LLSnapshotLivePreview
///----------------------------------------------------------------------------
@@ -112,7 +118,17 @@ public:
};
- LLSnapshotLivePreview(const LLRect& rect);
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
+ {
+ Params()
+ {
+ name = "snapshot_live_preview";
+ mouse_opaque = false;
+ }
+ };
+
+
+ LLSnapshotLivePreview(const LLSnapshotLivePreview::Params& p);
~LLSnapshotLivePreview();
/*virtual*/ void draw();
@@ -128,12 +144,12 @@ public:
LLFloaterSnapshot::ESnapshotFormat getSnapshotFormat() const { return mSnapshotFormat; }
BOOL getSnapshotUpToDate() const { return mSnapshotUpToDate; }
BOOL isSnapshotActive() { return mSnapshotActive; }
- LLImageGL* getThumbnailImage() const { return mThumbnailImage ; }
+ LLViewerTexture* getThumbnailImage() const { return mThumbnailImage ; }
S32 getThumbnailWidth() const { return mThumbnailWidth ; }
S32 getThumbnailHeight() const { return mThumbnailHeight ; }
BOOL getThumbnailLock() const { return mThumbnailUpdateLock ; }
BOOL getThumbnailUpToDate() const { return mThumbnailUpToDate ;}
- LLImageGL* getCurrentImage();
+ LLViewerTexture* getCurrentImage();
F32 getImageAspect();
F32 getAspect() ;
LLRect getImageRect();
@@ -158,7 +174,7 @@ public:
private:
LLColor4 mColor;
- LLPointer<LLImageGL> mViewerImage[2]; //used to represent the scene when the frame is frozen.
+ LLPointer<LLViewerTexture> mViewerImage[2]; //used to represent the scene when the frame is frozen.
LLRect mImageRect[2];
S32 mWidth[2];
S32 mHeight[2];
@@ -166,7 +182,7 @@ private:
S32 mMaxImageSize ;
//thumbnail image
- LLPointer<LLImageGL> mThumbnailImage ;
+ LLPointer<LLViewerTexture> mThumbnailImage ;
S32 mThumbnailWidth ;
S32 mThumbnailHeight ;
LLRect mPreviewRect ;
@@ -200,8 +216,9 @@ public:
};
std::set<LLSnapshotLivePreview*> LLSnapshotLivePreview::sList;
-LLSnapshotLivePreview::LLSnapshotLivePreview (const LLRect& rect) :
- LLView(std::string("snapshot_live_preview"), rect, FALSE),
+
+LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Params& p)
+: LLView(p),
mColor(1.f, 0.f, 0.f, 0.5f),
mCurImageIndex(0),
mPreviewImage(NULL),
@@ -229,10 +246,10 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLRect& rect) :
// gIdleCallbacks.addFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
sList.insert(this);
setFollowsAll();
- mWidth[0] = gViewerWindow->getWindowDisplayWidth();
- mWidth[1] = gViewerWindow->getWindowDisplayWidth();
- mHeight[0] = gViewerWindow->getWindowDisplayHeight();
- mHeight[1] = gViewerWindow->getWindowDisplayHeight();
+ mWidth[0] = gViewerWindow->getWindowWidthRaw();
+ mWidth[1] = gViewerWindow->getWindowWidthRaw();
+ mHeight[0] = gViewerWindow->getWindowHeightRaw();
+ mHeight[1] = gViewerWindow->getWindowHeightRaw();
mImageScaled[0] = FALSE;
mImageScaled[1] = FALSE;
@@ -265,7 +282,7 @@ void LLSnapshotLivePreview::setMaxImageSize(S32 size)
}
}
-LLImageGL* LLSnapshotLivePreview::getCurrentImage()
+LLViewerTexture* LLSnapshotLivePreview::getCurrentImage()
{
return mViewerImage[mCurImageIndex];
}
@@ -472,37 +489,33 @@ void LLSnapshotLivePreview::draw()
}
else if (mShineAnimTimer.getStarted())
{
- //LLDebugVarMessageBox::show("Shine time", &SHINE_TIME, 10.f, 0.1f);
- //LLDebugVarMessageBox::show("Shine width", &SHINE_WIDTH, 2.f, 0.05f);
- //LLDebugVarMessageBox::show("Shine opacity", &SHINE_OPACITY, 1.f, 0.05f);
-
F32 shine_interp = llmin(1.f, mShineAnimTimer.getElapsedTimeF32() / SHINE_TIME);
// draw "shine" effect
LLLocalClipRect clip(getLocalRect());
{
// draw diagonal stripe with gradient that passes over screen
- S32 x1 = gViewerWindow->getWindowWidth() * llround((clamp_rescale(shine_interp, 0.f, 1.f, -1.f - SHINE_WIDTH, 1.f)));
- S32 x2 = x1 + llround(gViewerWindow->getWindowWidth() * SHINE_WIDTH);
- S32 x3 = x2 + llround(gViewerWindow->getWindowWidth() * SHINE_WIDTH);
+ S32 x1 = gViewerWindow->getWindowWidthScaled() * llround((clamp_rescale(shine_interp, 0.f, 1.f, -1.f - SHINE_WIDTH, 1.f)));
+ S32 x2 = x1 + llround(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH);
+ S32 x3 = x2 + llround(gViewerWindow->getWindowWidthScaled() * SHINE_WIDTH);
S32 y1 = 0;
- S32 y2 = gViewerWindow->getWindowHeight();
+ S32 y2 = gViewerWindow->getWindowHeightScaled();
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.begin(LLRender::QUADS);
{
gGL.color4f(1.f, 1.f, 1.f, 0.f);
gGL.vertex2i(x1, y1);
- gGL.vertex2i(x1 + gViewerWindow->getWindowWidth(), y2);
+ gGL.vertex2i(x1 + gViewerWindow->getWindowWidthScaled(), y2);
gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
- gGL.vertex2i(x2 + gViewerWindow->getWindowWidth(), y2);
+ gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2);
gGL.vertex2i(x2, y1);
gGL.color4f(1.f, 1.f, 1.f, SHINE_OPACITY);
gGL.vertex2i(x2, y1);
- gGL.vertex2i(x2 + gViewerWindow->getWindowWidth(), y2);
+ gGL.vertex2i(x2 + gViewerWindow->getWindowWidthScaled(), y2);
gGL.color4f(1.f, 1.f, 1.f, 0.f);
- gGL.vertex2i(x3 + gViewerWindow->getWindowWidth(), y2);
+ gGL.vertex2i(x3 + gViewerWindow->getWindowWidthScaled(), y2);
gGL.vertex2i(x3, y1);
}
gGL.end();
@@ -605,8 +618,8 @@ BOOL LLSnapshotLivePreview::setThumbnailImageSize()
{
return FALSE ;
}
- S32 window_width = gViewerWindow->getWindowDisplayWidth() ;
- S32 window_height = gViewerWindow->getWindowDisplayHeight() ;
+ S32 window_width = gViewerWindow->getWindowWidthRaw() ;
+ S32 window_height = gViewerWindow->getWindowHeightRaw() ;
F32 window_aspect_ratio = ((F32)window_width) / ((F32)window_height);
@@ -714,7 +727,7 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
if(raw)
{
- mThumbnailImage = new LLImageGL(raw, FALSE);
+ mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
mThumbnailUpToDate = TRUE ;
}
@@ -862,8 +875,8 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
scaled->expandToPowerOfTwo(1024, FALSE);
}
- previewp->mViewerImage[previewp->mCurImageIndex] = new LLImageGL(scaled, FALSE);
- LLPointer<LLImageGL> curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex];
+ previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE);
+ LLPointer<LLViewerTexture> curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex];
gGL.getTexUnit(0)->bind(curr_preview_image);
if (previewp->getSnapshotType() != SNAPSHOT_TEXTURE)
{
@@ -959,9 +972,9 @@ void LLSnapshotLivePreview::saveTexture()
{
LLVFile::writeFile(formatted->getData(), formatted->getDataSize(), gVFS, new_asset_id, LLAssetType::AT_TEXTURE);
std::string pos_string;
- gAgent.buildLocationString(pos_string);
+ LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL);
std::string who_took_it;
- gAgent.buildFullname(who_took_it);
+ LLAgentUI::buildFullname(who_took_it);
LLAssetStorage::LLStoreAssetCallback callback = NULL;
S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
void *userdata = NULL;
@@ -970,7 +983,7 @@ void LLSnapshotLivePreview::saveTexture()
"Snapshot : " + pos_string,
"Taken by " + who_took_it + " at " + pos_string,
0,
- LLAssetType::AT_SNAPSHOT_CATEGORY,
+ LLFolderType::FT_SNAPSHOT_CATEGORY,
LLInventoryType::IT_SNAPSHOT,
PERM_ALL, // Note: Snapshots to inventory is a special case of content upload
PERM_NONE, // that ignores the user's premissions preferences and continues to
@@ -981,7 +994,7 @@ void LLSnapshotLivePreview::saveTexture()
}
else
{
- LLNotifications::instance().add("ErrorEncodingSnapshot");
+ LLNotificationsUtil::add("ErrorEncodingSnapshot");
llwarns << "Error encoding snapshot" << llendl;
}
@@ -1053,9 +1066,6 @@ public:
static void updateLayout(LLFloaterSnapshot* floater);
static void updateResolutionTextEntry(LLFloaterSnapshot* floater);
- static LLHandle<LLView> sPreviewHandle;
- static BOOL sAspectRatioCheckOff ;
-
private:
static LLSnapshotLivePreview::ESnapshotType getTypeIndex(LLFloaterSnapshot* floater);
static ESnapshotFormat getFormatIndex(LLFloaterSnapshot* floater);
@@ -1068,18 +1078,14 @@ public:
std::vector<LLAnimPauseRequest> mAvatarPauseHandles;
LLToolset* mLastToolset;
+ LLHandle<LLView> mPreviewHandle;
+ BOOL mAspectRatioCheckOff ;
};
// static
-LLHandle<LLView> LLFloaterSnapshot::Impl::sPreviewHandle;
-
-//static
-BOOL LLFloaterSnapshot::Impl::sAspectRatioCheckOff = FALSE ;
-
-// static
LLSnapshotLivePreview* LLFloaterSnapshot::Impl::getPreviewView(LLFloaterSnapshot *floater)
{
- LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)sPreviewHandle.get();
+ LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)floater->impl.mPreviewHandle.get();
return previewp;
}
@@ -1103,15 +1109,18 @@ LLSnapshotLivePreview::ESnapshotType LLFloaterSnapshot::Impl::getTypeIndex(LLFlo
LLFloaterSnapshot::ESnapshotFormat LLFloaterSnapshot::Impl::getFormatIndex(LLFloaterSnapshot* floater)
{
ESnapshotFormat index = SNAPSHOT_FORMAT_PNG;
- LLSD value = floater->childGetValue("local_format_combo");
- const std::string id = value.asString();
- if (id == "PNG")
- index = SNAPSHOT_FORMAT_PNG;
- else if (id == "JPEG")
- index = SNAPSHOT_FORMAT_JPEG;
- else if (id == "BMP")
- index = SNAPSHOT_FORMAT_BMP;
- return index;
+ if(floater->hasChild("local_format_combo"))
+ {
+ LLComboBox* local_format_combo = floater->findChild<LLComboBox>("local_format_combo");
+ const std::string id = local_format_combo->getSelectedItemLabel();
+ if (id == "PNG")
+ index = SNAPSHOT_FORMAT_PNG;
+ else if (id == "JPEG")
+ index = SNAPSHOT_FORMAT_JPEG;
+ else if (id == "BMP")
+ index = SNAPSHOT_FORMAT_BMP;
+ }
+ return index;
}
@@ -1160,7 +1169,7 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
gSavedSettings.setS32("SnapshotLocalLastResolution", 0);
LLSnapshotLivePreview* previewp = getPreviewView(floaterp);
- previewp->setSize(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight());
+ previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
}
bool use_freeze_frame = floaterp->childGetValue("freeze_frame_check").asBoolean();
@@ -1186,7 +1195,7 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
iter != LLCharacter::sInstances.end(); ++iter)
{
avatarp = *iter;
- sInstance->impl.mAvatarPauseHandles.push_back(avatarp->requestPause());
+ floaterp->impl.mAvatarPauseHandles.push_back(avatarp->requestPause());
}
// freeze everything else
@@ -1194,7 +1203,7 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
if (LLToolMgr::getInstance()->getCurrentToolset() != gCameraToolset)
{
- sInstance->impl.mLastToolset = LLToolMgr::getInstance()->getCurrentToolset();
+ floaterp->impl.mLastToolset = LLToolMgr::getInstance()->getCurrentToolset();
LLToolMgr::getInstance()->setCurrentToolset(gCameraToolset);
}
}
@@ -1209,15 +1218,15 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
}
//RN: thaw all avatars
- sInstance->impl.mAvatarPauseHandles.clear();
+ floaterp->impl.mAvatarPauseHandles.clear();
// thaw everything else
gSavedSettings.setBOOL("FreezeTime", FALSE);
// restore last tool (e.g. pie menu, etc)
- if (sInstance->impl.mLastToolset)
+ if (floaterp->impl.mLastToolset)
{
- LLToolMgr::getInstance()->setCurrentToolset(sInstance->impl.mLastToolset);
+ LLToolMgr::getInstance()->setCurrentToolset(floaterp->impl.mLastToolset);
}
}
}
@@ -1248,7 +1257,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
floater->childSetVisible("upload_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE);
floater->childSetVisible("send_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD);
floater->childSetVisible("save_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL);
- floater->childSetEnabled("keep_aspect_check", shot_type != LLSnapshotLivePreview::SNAPSHOT_TEXTURE && !sAspectRatioCheckOff);
+ floater->childSetEnabled("keep_aspect_check", shot_type != LLSnapshotLivePreview::SNAPSHOT_TEXTURE && !floater->impl.mAspectRatioCheckOff);
floater->childSetEnabled("layer_types", shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL);
BOOL is_advance = gSavedSettings.getBOOL("AdvanceSnapshot");
@@ -1295,7 +1304,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
floater->childSetColor("file_size_label",
shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD
&& got_bytes
- && previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLColor4::red : gColors.getColor( "LabelTextColor" ));
+ && previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" ));
switch(shot_type)
{
@@ -1367,9 +1376,10 @@ void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp,
void LLFloaterSnapshot::Impl::onClickDiscard(void* data)
{
LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
+
if (view)
{
- view->close();
+ view->closeFloater();
}
}
@@ -1415,7 +1425,7 @@ void LLFloaterSnapshot::Impl::onClickKeep(void* data)
if (gSavedSettings.getBOOL("CloseSnapshotOnKeep"))
{
- view->close();
+ view->closeFloater();
}
else
{
@@ -1596,7 +1606,7 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde
if(0 == index) //current window size
{
- sAspectRatioCheckOff = TRUE ;
+ view->impl.mAspectRatioCheckOff = TRUE ;
view->childSetEnabled("keep_aspect_check", FALSE) ;
if(previewp)
@@ -1606,7 +1616,7 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde
}
else if(-1 == index) //custom
{
- sAspectRatioCheckOff = FALSE ;
+ view->impl.mAspectRatioCheckOff = FALSE ;
//if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE != gSavedSettings.getS32("LastSnapshotType"))
{
view->childSetEnabled("keep_aspect_check", TRUE) ;
@@ -1619,7 +1629,7 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde
}
else
{
- sAspectRatioCheckOff = TRUE ;
+ view->impl.mAspectRatioCheckOff = TRUE ;
view->childSetEnabled("keep_aspect_check", FALSE) ;
if(previewp)
@@ -1683,7 +1693,7 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL
if (width == 0 || height == 0)
{
// take resolution from current window size
- previewp->setSize(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight());
+ previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
}
else if (width == -1 || height == -1)
{
@@ -1836,13 +1846,13 @@ BOOL LLFloaterSnapshot::Impl::checkImageSize(LLSnapshotLivePreview* previewp, S3
#endif
if(previewp && previewp->mKeepAspectRatio)
{
- if(gViewerWindow->getWindowDisplayWidth() < 1 || gViewerWindow->getWindowDisplayHeight() < 1)
+ if(gViewerWindow->getWindowWidthRaw() < 1 || gViewerWindow->getWindowHeightRaw() < 1)
{
return FALSE ;
}
//aspect ratio of the current window
- F32 aspect_ratio = (F32)gViewerWindow->getWindowDisplayWidth() / gViewerWindow->getWindowDisplayHeight() ;
+ F32 aspect_ratio = (F32)gViewerWindow->getWindowWidthRaw() / gViewerWindow->getWindowHeightRaw() ;
//change another value proportionally
if(isWidthChanged)
@@ -1955,21 +1965,17 @@ void LLFloaterSnapshot::Impl::onCommitCustomResolution(LLUICtrl *ctrl, void* dat
///----------------------------------------------------------------------------
// Default constructor
-LLFloaterSnapshot::LLFloaterSnapshot()
- : LLFloater(std::string("Snapshot Floater")),
+LLFloaterSnapshot::LLFloaterSnapshot(const LLSD& key)
+ : LLFloater(key),
impl (*(new Impl))
{
+ //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_snapshot.xml", FALSE);
}
// Destroys the object
LLFloaterSnapshot::~LLFloaterSnapshot()
{
- if (sInstance == this)
- {
- LLView::deleteViewByHandle(Impl::sPreviewHandle);
- Impl::sPreviewHandle = LLHandle<LLView>();
- sInstance = NULL;
- }
+ LLView::deleteViewByHandle(impl.mPreviewHandle);
//unfreeze everything else
gSavedSettings.setBOOL("FreezeTime", FALSE);
@@ -2034,16 +2040,24 @@ BOOL LLFloaterSnapshot::postBuild()
childSetCommitCallback("local_size_combo", Impl::onCommitResolution, this);
// create preview window
- LLRect full_screen_rect = sInstance->getRootView()->getRect();
- LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(full_screen_rect);
- sInstance->getRootView()->removeChild(gSnapshotFloaterView);
+ LLRect full_screen_rect = getRootView()->getRect();
+ LLSnapshotLivePreview::Params p;
+ p.rect(full_screen_rect);
+ LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
+ LLView* parent_view = gSnapshotFloaterView->getParent();
+
+ parent_view->removeChild(gSnapshotFloaterView);
// make sure preview is below snapshot floater
- sInstance->getRootView()->addChild(previewp);
- sInstance->getRootView()->addChild(gSnapshotFloaterView);
-
- Impl::sPreviewHandle = previewp->getHandle();
+ parent_view->addChild(previewp);
+ parent_view->addChild(gSnapshotFloaterView);
+
+ //move snapshot floater to special purpose snapshotfloaterview
+ gFloaterView->removeChild(this);
+ gSnapshotFloaterView->addChild(this);
+ impl.mPreviewHandle = previewp->getHandle();
impl.updateControls(this);
+ impl.updateLayout(this);
return TRUE;
}
@@ -2064,8 +2078,10 @@ void LLFloaterSnapshot::draw()
{
if(previewp->getThumbnailImage())
{
+ LLRect thumbnail_rect = getChild<LLUICtrl>("thumbnail_placeholder")->getRect();
+
S32 offset_x = (getRect().getWidth() - previewp->getThumbnailWidth()) / 2 ;
- S32 offset_y = getRect().getHeight() - 205 + (90 - previewp->getThumbnailHeight()) / 2 ;
+ S32 offset_y = thumbnail_rect.mBottom + (thumbnail_rect.getHeight() - previewp->getThumbnailHeight()) / 2 ;
glMatrixMode(GL_MODELVIEW);
gl_draw_scaled_image(offset_x, offset_y,
@@ -2077,54 +2093,32 @@ void LLFloaterSnapshot::draw()
}
}
-void LLFloaterSnapshot::onClose(bool app_quitting)
+void LLFloaterSnapshot::onOpen(const LLSD& key)
{
- gSnapshotFloaterView->setEnabled(FALSE);
- // Set invisible so it doesn't eat tooltips. JC
- gSnapshotFloaterView->setVisible(FALSE);
- destroy();
-}
-
-// static
-void LLFloaterSnapshot::show(void*)
-{
- if (!sInstance)
+ LLSnapshotLivePreview* preview = LLFloaterSnapshot::Impl::getPreviewView(this);
+ if(preview)
{
- sInstance = new LLFloaterSnapshot();
- LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_snapshot.xml", NULL, FALSE);
- //move snapshot floater to special purpose snapshotfloaterview
- gFloaterView->removeChild(sInstance);
- gSnapshotFloaterView->addChild(sInstance);
-
- sInstance->impl.updateLayout(sInstance);
- }
- else // just refresh the snapshot in the existing floater instance (DEV-12255)
- {
- LLSnapshotLivePreview* preview = LLFloaterSnapshot::Impl::getPreviewView(sInstance);
- if(preview)
- {
- preview->updateSnapshot(TRUE);
- }
+ preview->updateSnapshot(TRUE);
}
-
- sInstance->open(); /* Flawfinder: ignore */
- sInstance->focusFirstItem(FALSE);
+ focusFirstItem(FALSE);
gSnapshotFloaterView->setEnabled(TRUE);
gSnapshotFloaterView->setVisible(TRUE);
- gSnapshotFloaterView->adjustToFitScreen(sInstance, FALSE);
+ gSnapshotFloaterView->adjustToFitScreen(this, FALSE);
}
-void LLFloaterSnapshot::hide(void*)
+void LLFloaterSnapshot::onClose(bool app_quitting)
{
- if (sInstance && !sInstance->isDead())
- {
- sInstance->close();
- }
+ getParent()->setMouseOpaque(FALSE);
}
+
//static
void LLFloaterSnapshot::update()
{
+ LLFloaterSnapshot* inst = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot");
+ if (!inst)
+ return;
+
BOOL changed = FALSE;
for (std::set<LLSnapshotLivePreview*>::iterator iter = LLSnapshotLivePreview::sList.begin();
iter != LLSnapshotLivePreview::sList.end(); ++iter)
@@ -2133,7 +2127,7 @@ void LLFloaterSnapshot::update()
}
if(changed)
{
- sInstance->impl.updateControls(sInstance);
+ inst->impl.updateControls(inst);
}
}
@@ -2142,10 +2136,8 @@ void LLFloaterSnapshot::update()
/// Class LLSnapshotFloaterView
///----------------------------------------------------------------------------
-LLSnapshotFloaterView::LLSnapshotFloaterView( const std::string& name, const LLRect& rect ) : LLFloaterView(name, rect)
+LLSnapshotFloaterView::LLSnapshotFloaterView (const Params& p) : LLFloaterView (p)
{
- setMouseOpaque(TRUE);
- setEnabled(FALSE);
}
LLSnapshotFloaterView::~LLSnapshotFloaterView()
diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h
index 14f1872cd1..1333497bd2 100644
--- a/indra/newview/llfloatersnapshot.h
+++ b/indra/newview/llfloatersnapshot.h
@@ -35,10 +35,6 @@
#include "llfloater.h"
-#include "llmemory.h"
-#include "llimagegl.h"
-#include "llcharacter.h"
-
class LLFloaterSnapshot : public LLFloater
{
@@ -50,17 +46,16 @@ public:
SNAPSHOT_FORMAT_BMP
} ESnapshotFormat;
- LLFloaterSnapshot();
+ LLFloaterSnapshot(const LLSD& key);
virtual ~LLFloaterSnapshot();
-
+
/*virtual*/ BOOL postBuild();
/*virtual*/ void draw();
+ /*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ void onClose(bool app_quitting);
-
- static void show(void*);
- static void hide(void*);
+
static void update();
-
+
static S32 getUIWinHeightLong() {return sUIWinHeightLong ;}
static S32 getUIWinHeightShort() {return sUIWinHeightShort ;}
static S32 getUIWinWidth() {return sUIWinWidth ;}
@@ -69,7 +64,6 @@ private:
class Impl;
Impl& impl;
- static LLFloaterSnapshot* sInstance;
static S32 sUIWinHeightLong ;
static S32 sUIWinHeightShort ;
static S32 sUIWinWidth ;
@@ -78,7 +72,16 @@ private:
class LLSnapshotFloaterView : public LLFloaterView
{
public:
- LLSnapshotFloaterView( const std::string& name, const LLRect& rect );
+ struct Params
+ : public LLInitParam::Block<Params, LLFloaterView::Params>
+ {
+ };
+
+protected:
+ LLSnapshotFloaterView (const Params& p);
+ friend class LLUICtrlFactory;
+
+public:
virtual ~LLSnapshotFloaterView();
/*virtual*/ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
diff --git a/indra/newview/llfloatertelehub.cpp b/indra/newview/llfloatertelehub.cpp
index 530bb87983..816181643f 100644
--- a/indra/newview/llfloatertelehub.cpp
+++ b/indra/newview/llfloatertelehub.cpp
@@ -39,6 +39,7 @@
#include "llfontgl.h"
#include "llagent.h"
+#include "llfloaterreg.h"
#include "llfloatertools.h"
#include "llscrolllistctrl.h"
#include "llselectmgr.h"
@@ -48,56 +49,25 @@
#include "llviewerobjectlist.h"
#include "lluictrlfactory.h"
-LLFloaterTelehub* LLFloaterTelehub::sInstance = NULL;
-
-
-// static
-void LLFloaterTelehub::show()
-{
- if (sInstance)
- {
- sInstance->setVisibleAndFrontmost();
- return;
- }
-
- sInstance = new LLFloaterTelehub();
-
- // Show tools floater by selecting translate (select) tool
- LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
- LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompTranslate::getInstance() );
-
- // Find tools floater, glue to bottom
- if (gFloaterTools)
- {
- LLRect tools_rect = gFloaterTools->getRect();
- S32 our_width = sInstance->getRect().getWidth();
- S32 our_height = sInstance->getRect().getHeight();
- LLRect our_rect;
- our_rect.setLeftTopAndSize(tools_rect.mLeft, tools_rect.mBottom, our_width, our_height);
- sInstance->setRect(our_rect);
- }
-
- sInstance->sendTelehubInfoRequest();
-}
-
-LLFloaterTelehub::LLFloaterTelehub()
-: LLFloater(std::string("telehub")),
+LLFloaterTelehub::LLFloaterTelehub(const LLSD& key)
+: LLFloater(key),
mTelehubObjectID(),
mTelehubObjectName(),
mTelehubPos(),
mTelehubRot(),
mNumSpawn(0)
{
- sInstance = this;
+ //LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_telehub.xml");
+}
+BOOL LLFloaterTelehub::postBuild()
+{
gMessageSystem->setHandlerFunc("TelehubInfo", processTelehubInfo);
- LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_telehub.xml");
-
- childSetAction("connect_btn", onClickConnect, this);
- childSetAction("disconnect_btn", onClickDisconnect, this);
- childSetAction("add_spawn_point_btn", onClickAddSpawnPoint, this);
- childSetAction("remove_spawn_point_btn", onClickRemoveSpawnPoint, this);
+ getChild<LLUICtrl>("connect_btn")->setCommitCallback(boost::bind(&LLFloaterTelehub::onClickConnect, this));
+ getChild<LLUICtrl>("disconnect_btn")->setCommitCallback(boost::bind(&LLFloaterTelehub::onClickDisconnect, this));
+ getChild<LLUICtrl>("add_spawn_point_btn")->setCommitCallback(boost::bind(&LLFloaterTelehub::onClickAddSpawnPoint, this));
+ getChild<LLUICtrl>("remove_spawn_point_btn")->setCommitCallback(boost::bind(&LLFloaterTelehub::onClickRemoveSpawnPoint, this));
LLScrollListCtrl* list = getChild<LLScrollListCtrl>("spawn_points_list");
if (list)
@@ -106,13 +76,21 @@ LLFloaterTelehub::LLFloaterTelehub()
list->setAllowKeyboardMovement(FALSE);
}
+ return TRUE;
+}
+void LLFloaterTelehub::onOpen(const LLSD& key)
+{
+ // Show tools floater by selecting translate (select) tool
+ LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
+ LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompTranslate::getInstance() );
+
+ sendTelehubInfoRequest();
+
mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
}
LLFloaterTelehub::~LLFloaterTelehub()
{
- sInstance = NULL;
-
// no longer interested in this message
gMessageSystem->setHandlerFunc("TelehubInfo", NULL);
}
@@ -154,19 +132,22 @@ void LLFloaterTelehub::refresh()
BOOL LLFloaterTelehub::renderBeacons()
{
// only render if we've got a telehub
- return sInstance && sInstance->mTelehubObjectID.notNull();
+ LLFloaterTelehub* floater = LLFloaterReg::findTypedInstance<LLFloaterTelehub>("telehubs");
+ return floater && floater->mTelehubObjectID.notNull();
}
// static
void LLFloaterTelehub::addBeacons()
{
- if (!sInstance) return;
-
+ LLFloaterTelehub* floater = LLFloaterReg::findTypedInstance<LLFloaterTelehub>("telehubs");
+ if (!floater)
+ return;
+
// Find the telehub position, either our cached old position, or
// an updated one based on the actual object position.
- LLVector3 hub_pos_region = sInstance->mTelehubPos;
- LLQuaternion hub_rot = sInstance->mTelehubRot;
- LLViewerObject* obj = gObjectList.findObject(sInstance->mTelehubObjectID);
+ LLVector3 hub_pos_region = floater->mTelehubPos;
+ LLQuaternion hub_rot = floater->mTelehubRot;
+ LLViewerObject* obj = gObjectList.findObject(floater->mTelehubObjectID);
if (obj)
{
hub_pos_region = obj->getPositionRegion();
@@ -175,13 +156,13 @@ void LLFloaterTelehub::addBeacons()
// Draw nice thick 3-pixel lines.
gObjectList.addDebugBeacon(hub_pos_region, "", LLColor4::yellow, LLColor4::white, 4);
- LLScrollListCtrl* list = sInstance->getChild<LLScrollListCtrl>("spawn_points_list");
+ LLScrollListCtrl* list = floater->getChild<LLScrollListCtrl>("spawn_points_list");
if (list)
{
S32 spawn_index = list->getFirstSelectedIndex();
if (spawn_index >= 0)
{
- LLVector3 spawn_pos = hub_pos_region + (sInstance->mSpawnPointPos[spawn_index] * hub_rot);
+ LLVector3 spawn_pos = hub_pos_region + (floater->mSpawnPointPos[spawn_index] * hub_rot);
gObjectList.addDebugBeacon(spawn_pos, "", LLColor4::orange, LLColor4::white, 4);
}
}
@@ -192,32 +173,27 @@ void LLFloaterTelehub::sendTelehubInfoRequest()
LLSelectMgr::getInstance()->sendGodlikeRequest("telehub", "info ui");
}
-// static
-void LLFloaterTelehub::onClickConnect(void* data)
+void LLFloaterTelehub::onClickConnect()
{
LLSelectMgr::getInstance()->sendGodlikeRequest("telehub", "connect");
}
-// static
-void LLFloaterTelehub::onClickDisconnect(void* data)
+void LLFloaterTelehub::onClickDisconnect()
{
LLSelectMgr::getInstance()->sendGodlikeRequest("telehub", "delete");
}
-// static
-void LLFloaterTelehub::onClickAddSpawnPoint(void* data)
+void LLFloaterTelehub::onClickAddSpawnPoint()
{
LLSelectMgr::getInstance()->sendGodlikeRequest("telehub", "spawnpoint add");
LLSelectMgr::getInstance()->deselectAll();
}
-// static
-void LLFloaterTelehub::onClickRemoveSpawnPoint(void* data)
+void LLFloaterTelehub::onClickRemoveSpawnPoint()
{
- if (!sInstance) return;
-
- LLScrollListCtrl* list = sInstance->getChild<LLScrollListCtrl>("spawn_points_list");
- if (!list) return;
+ LLScrollListCtrl* list = getChild<LLScrollListCtrl>("spawn_points_list");
+ if (!list)
+ return;
S32 spawn_index = list->getFirstSelectedIndex();
if (spawn_index < 0) return; // nothing selected
@@ -255,9 +231,10 @@ void LLFloaterTelehub::onClickRemoveSpawnPoint(void* data)
// static
void LLFloaterTelehub::processTelehubInfo(LLMessageSystem* msg, void**)
{
- if (sInstance)
+ LLFloaterTelehub* floater = LLFloaterReg::findTypedInstance<LLFloaterTelehub>("telehubs");
+ if (floater)
{
- sInstance->unpackTelehubInfo(msg);
+ floater->unpackTelehubInfo(msg);
}
}
diff --git a/indra/newview/llfloatertelehub.h b/indra/newview/llfloatertelehub.h
index 28c9d16573..5b654585f1 100644
--- a/indra/newview/llfloatertelehub.h
+++ b/indra/newview/llfloatertelehub.h
@@ -44,25 +44,24 @@ const S32 MAX_SPAWNPOINTS_PER_TELEHUB = 16;
class LLFloaterTelehub : public LLFloater
{
public:
- // Opens the floater on screen.
- static void show();
-
- virtual void draw();
+ LLFloaterTelehub(const LLSD& key);
+ ~LLFloaterTelehub();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ void draw();
+
static BOOL renderBeacons();
static void addBeacons();
-private:
- LLFloaterTelehub();
- ~LLFloaterTelehub();
-
void refresh();
void sendTelehubInfoRequest();
- static void onClickConnect(void* data);
- static void onClickDisconnect(void* data);
- static void onClickAddSpawnPoint(void* data);
- static void onClickRemoveSpawnPoint(void* data);
+ void onClickConnect();
+ void onClickDisconnect();
+ void onClickAddSpawnPoint();
+ void onClickRemoveSpawnPoint();
static void processTelehubInfo(LLMessageSystem* msg, void**);
void unpackTelehubInfo(LLMessageSystem* msg);
diff --git a/indra/newview/llfloatertestinspectors.cpp b/indra/newview/llfloatertestinspectors.cpp
new file mode 100644
index 0000000000..58d5197eaa
--- /dev/null
+++ b/indra/newview/llfloatertestinspectors.cpp
@@ -0,0 +1,119 @@
+/**
+* @file llfloatertestinspectors.cpp
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloatertestinspectors.h"
+
+// Viewer includes
+#include "llstartup.h"
+
+// Linden library includes
+#include "llfloaterreg.h"
+//#include "lluictrlfactory.h"
+
+LLFloaterTestInspectors::LLFloaterTestInspectors(const LLSD& seed)
+: LLFloater(seed)
+{
+ mCommitCallbackRegistrar.add("ShowAvatarInspector",
+ boost::bind(&LLFloaterTestInspectors::showAvatarInspector, this, _1, _2));
+ mCommitCallbackRegistrar.add("ShowObjectInspector",
+ boost::bind(&LLFloaterTestInspectors::showObjectInspector, this, _1, _2));
+}
+
+LLFloaterTestInspectors::~LLFloaterTestInspectors()
+{}
+
+BOOL LLFloaterTestInspectors::postBuild()
+{
+ // Test the dummy widget construction code
+ getChild<LLUICtrl>("intentionally-not-found")->setEnabled(true);
+
+// getChild<LLUICtrl>("avatar_2d_btn")->setCommitCallback(
+// boost::bind(&LLFloaterTestInspectors::onClickAvatar2D, this));
+ getChild<LLUICtrl>("avatar_3d_btn")->setCommitCallback(
+ boost::bind(&LLFloaterTestInspectors::onClickAvatar3D, this));
+ getChild<LLUICtrl>("object_2d_btn")->setCommitCallback(
+ boost::bind(&LLFloaterTestInspectors::onClickObject2D, this));
+ getChild<LLUICtrl>("object_3d_btn")->setCommitCallback(
+ boost::bind(&LLFloaterTestInspectors::onClickObject3D, this));
+ getChild<LLUICtrl>("group_btn")->setCommitCallback(
+ boost::bind(&LLFloaterTestInspectors::onClickGroup, this));
+ getChild<LLUICtrl>("place_btn")->setCommitCallback(
+ boost::bind(&LLFloaterTestInspectors::onClickPlace, this));
+ getChild<LLUICtrl>("event_btn")->setCommitCallback(
+ boost::bind(&LLFloaterTestInspectors::onClickEvent, this));
+
+ return LLFloater::postBuild();
+}
+
+void LLFloaterTestInspectors::showAvatarInspector(LLUICtrl*, const LLSD& avatar_id)
+{
+ LLUUID id; // defaults to null
+ if (LLStartUp::getStartupState() >= STATE_STARTED)
+ {
+ id = avatar_id.asUUID();
+ }
+ // spawns off mouse position automatically
+ LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", id));
+}
+
+void LLFloaterTestInspectors::showObjectInspector(LLUICtrl*, const LLSD& object_id)
+{
+ LLFloaterReg::showInstance("inspect_object", LLSD().with("object_id", object_id));
+}
+
+void LLFloaterTestInspectors::onClickAvatar2D()
+{
+}
+
+void LLFloaterTestInspectors::onClickAvatar3D()
+{
+}
+
+void LLFloaterTestInspectors::onClickObject2D()
+{
+}
+
+void LLFloaterTestInspectors::onClickObject3D()
+{
+}
+
+void LLFloaterTestInspectors::onClickGroup()
+{
+}
+
+void LLFloaterTestInspectors::onClickPlace()
+{
+}
+
+void LLFloaterTestInspectors::onClickEvent()
+{
+}
diff --git a/indra/newview/llfloatertestinspectors.h b/indra/newview/llfloatertestinspectors.h
new file mode 100644
index 0000000000..6555aad4e8
--- /dev/null
+++ b/indra/newview/llfloatertestinspectors.h
@@ -0,0 +1,65 @@
+/**
+* @file llfloatertestinspectors.h
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+#ifndef LLFLOATERTESTINSPECTORS_H
+#define LLFLOATERTESTINSPECTORS_H
+
+#include "llfloater.h"
+
+class LLSD;
+
+class LLFloaterTestInspectors : public LLFloater
+{
+ friend class LLFloaterReg;
+public:
+ // nothing yet
+
+private:
+ // Construction handled by LLFloaterReg
+ LLFloaterTestInspectors(const LLSD& seed);
+ ~LLFloaterTestInspectors();
+
+ /*virtual*/ BOOL postBuild();
+
+ // Button callback to show
+ void showAvatarInspector(LLUICtrl*, const LLSD& avatar_id);
+ void showObjectInspector(LLUICtrl*, const LLSD& avatar_id);
+
+ // Debug function hookups for buttons
+ void onClickAvatar2D();
+ void onClickAvatar3D();
+ void onClickObject2D();
+ void onClickObject3D();
+ void onClickGroup();
+ void onClickPlace();
+ void onClickEvent();
+};
+
+#endif
diff --git a/indra/newview/llfloatertestlistview.cpp b/indra/newview/llfloatertestlistview.cpp
new file mode 100644
index 0000000000..7171449738
--- /dev/null
+++ b/indra/newview/llfloatertestlistview.cpp
@@ -0,0 +1,41 @@
+/**
+* @file llfloatertestlistview.cpp
+* @brief Tests of programmatic manipulation of LLListView widgets
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloatertestlistview.h"
+
+LLFloaterTestListView::LLFloaterTestListView(const LLSD& seed)
+: LLFloater(seed)
+{}
+
+LLFloaterTestListView::~LLFloaterTestListView()
+{}
diff --git a/indra/newview/llfloatertestlistview.h b/indra/newview/llfloatertestlistview.h
new file mode 100644
index 0000000000..0c47c2ee31
--- /dev/null
+++ b/indra/newview/llfloatertestlistview.h
@@ -0,0 +1,49 @@
+/**
+* @file llfloatertestlistview.h
+* @brief Tests of programmatic manipulation of LLListView widgets
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+#ifndef LLFLOATERTESTLISTVIEW_H
+#define LLFLOATERTESTLISTVIEW_H
+
+#include "llfloater.h"
+
+class LLSD;
+
+class LLFloaterTestListView : public LLFloater
+{
+ friend class LLFloaterReg;
+
+private:
+ // Construction handled by LLFloaterReg
+ LLFloaterTestListView(const LLSD& seed);
+ ~LLFloaterTestListView();
+};
+
+#endif
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index a33b49563c..241497aeaf 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -36,24 +36,31 @@
#include "llfontgl.h"
#include "llcoord.h"
-#include "llgl.h"
+//#include "llgl.h"
#include "llagent.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#include "lldraghandle.h"
+#include "llerror.h"
#include "llfloaterbuildoptions.h"
+#include "llfloatermediasettings.h"
#include "llfloateropenobject.h"
+#include "llfloaterreg.h"
#include "llfocusmgr.h"
+#include "llmediaentry.h"
+#include "llmediactrl.h"
#include "llmenugl.h"
+#include "llnotificationsutil.h"
#include "llpanelcontents.h"
#include "llpanelface.h"
#include "llpanelland.h"
-#include "llpanelinventory.h"
+#include "llpanelobjectinventory.h"
#include "llpanelobject.h"
#include "llpanelvolume.h"
#include "llpanelpermissions.h"
+#include "llradiogroup.h"
#include "llresmgr.h"
#include "llselectmgr.h"
#include "llslider.h"
@@ -73,17 +80,20 @@
#include "lltoolpipette.h"
#include "lltoolplacer.h"
#include "lltoolselectland.h"
+#include "lltrans.h"
#include "llui.h"
+#include "llviewercontrol.h"
+#include "llviewerjoystick.h"
+#include "llviewerregion.h"
#include "llviewermenu.h"
#include "llviewerparcelmgr.h"
#include "llviewerwindow.h"
-#include "llviewercontrol.h"
-#include "llviewerjoystick.h"
+#include "llvovolume.h"
#include "lluictrlfactory.h"
// Globals
LLFloaterTools *gFloaterTools = NULL;
-
+bool LLFloaterTools::sShowObjectCost = true;
const std::string PANEL_NAMES[LLFloaterTools::PANEL_COUNT] =
{
@@ -95,41 +105,36 @@ const std::string PANEL_NAMES[LLFloaterTools::PANEL_COUNT] =
};
// Local prototypes
-void commit_select_tool(LLUICtrl *ctrl, void *data);
-void commit_select_component(LLUICtrl *ctrl, void *data);
+void commit_select_component(void *data);
void click_show_more(void*);
void click_popup_info(void*);
void click_popup_done(void*);
void click_popup_minimize(void*);
-void click_popup_grab_drag(LLUICtrl *, void*);
-void click_popup_grab_lift(LLUICtrl *, void*);
-void click_popup_grab_spin(LLUICtrl *, void*);
void click_popup_rotate_left(void*);
void click_popup_rotate_reset(void*);
void click_popup_rotate_right(void*);
-void click_popup_dozer_mode(LLUICtrl *, void *user);
-void commit_slider_dozer_size(LLUICtrl *, void*);
-void commit_slider_dozer_force(LLUICtrl *, void*);
+void commit_slider_dozer_force(LLUICtrl *);
void click_apply_to_selection(void*);
-void commit_radio_zoom(LLUICtrl *, void*);
-void commit_radio_orbit(LLUICtrl *, void*);
-void commit_radio_pan(LLUICtrl *, void*);
-void commit_grid_mode(LLUICtrl *, void*);
-void commit_slider_zoom(LLUICtrl *, void*);
+void commit_radio_group_focus(LLUICtrl* ctrl);
+void commit_radio_group_move(LLUICtrl* ctrl);
+void commit_radio_group_edit(LLUICtrl* ctrl);
+void commit_radio_group_land(LLUICtrl* ctrl);
+void commit_grid_mode(LLUICtrl *);
+void commit_slider_zoom(LLUICtrl *ctrl);
//static
void* LLFloaterTools::createPanelPermissions(void* data)
{
LLFloaterTools* floater = (LLFloaterTools*)data;
- floater->mPanelPermissions = new LLPanelPermissions("General");
+ floater->mPanelPermissions = new LLPanelPermissions();
return floater->mPanelPermissions;
}
//static
void* LLFloaterTools::createPanelObject(void* data)
{
LLFloaterTools* floater = (LLFloaterTools*)data;
- floater->mPanelObject = new LLPanelObject("Object");
+ floater->mPanelObject = new LLPanelObject();
return floater->mPanelObject;
}
@@ -137,7 +142,7 @@ void* LLFloaterTools::createPanelObject(void* data)
void* LLFloaterTools::createPanelVolume(void* data)
{
LLFloaterTools* floater = (LLFloaterTools*)data;
- floater->mPanelVolume = new LLPanelVolume("Features");
+ floater->mPanelVolume = new LLPanelVolume();
return floater->mPanelVolume;
}
@@ -145,7 +150,7 @@ void* LLFloaterTools::createPanelVolume(void* data)
void* LLFloaterTools::createPanelFace(void* data)
{
LLFloaterTools* floater = (LLFloaterTools*)data;
- floater->mPanelFace = new LLPanelFace("Texture");
+ floater->mPanelFace = new LLPanelFace();
return floater->mPanelFace;
}
@@ -153,29 +158,53 @@ void* LLFloaterTools::createPanelFace(void* data)
void* LLFloaterTools::createPanelContents(void* data)
{
LLFloaterTools* floater = (LLFloaterTools*)data;
- floater->mPanelContents = new LLPanelContents("Contents");
+ floater->mPanelContents = new LLPanelContents();
return floater->mPanelContents;
}
//static
-void* LLFloaterTools::createPanelContentsInventory(void* data)
-{
- LLFloaterTools* floater = (LLFloaterTools*)data;
- floater->mPanelContents->mPanelInventory = new LLPanelInventory(std::string("ContentsInventory"), LLRect());
- return floater->mPanelContents->mPanelInventory;
-}
-
-//static
void* LLFloaterTools::createPanelLandInfo(void* data)
{
LLFloaterTools* floater = (LLFloaterTools*)data;
- floater->mPanelLandInfo = new LLPanelLandInfo(std::string("land info panel"));
+ floater->mPanelLandInfo = new LLPanelLandInfo();
return floater->mPanelLandInfo;
}
+static const std::string toolNames[]={
+ "ToolCube",
+ "ToolPrism",
+ "ToolPyramid",
+ "ToolTetrahedron",
+ "ToolCylinder",
+ "ToolHemiCylinder",
+ "ToolCone",
+ "ToolHemiCone",
+ "ToolSphere",
+ "ToolHemiSphere",
+ "ToolTorus",
+ "ToolTube",
+ "ToolRing",
+ "ToolTree",
+ "ToolGrass"};
+LLPCode toolData[]={
+ LL_PCODE_CUBE,
+ LL_PCODE_PRISM,
+ LL_PCODE_PYRAMID,
+ LL_PCODE_TETRAHEDRON,
+ LL_PCODE_CYLINDER,
+ LL_PCODE_CYLINDER_HEMI,
+ LL_PCODE_CONE,
+ LL_PCODE_CONE_HEMI,
+ LL_PCODE_SPHERE,
+ LL_PCODE_SPHERE_HEMI,
+ LL_PCODE_TORUS,
+ LLViewerObject::LL_VO_SQUARE_TORUS,
+ LLViewerObject::LL_VO_TRIANGLE_TORUS,
+ LL_PCODE_LEGACY_TREE,
+ LL_PCODE_LEGACY_GRASS};
+
BOOL LLFloaterTools::postBuild()
-{
-
+{
// Hide until tool selected
setVisible(FALSE);
@@ -186,97 +215,39 @@ BOOL LLFloaterTools::postBuild()
getDragHandle()->setEnabled( !gSavedSettings.getBOOL("ToolboxAutoMove") );
LLRect rect;
- mBtnFocus = getChild<LLButton>("button focus");//btn;
- childSetAction("button focus",LLFloaterTools::setEditTool, (void*)LLToolCamera::getInstance());
- mBtnMove = getChild<LLButton>("button move");
- childSetAction("button move",LLFloaterTools::setEditTool, (void*)LLToolGrab::getInstance());
- mBtnEdit = getChild<LLButton>("button edit");
- childSetAction("button edit",LLFloaterTools::setEditTool, (void*)LLToolCompTranslate::getInstance());
- mBtnCreate = getChild<LLButton>("button create");
- childSetAction("button create",LLFloaterTools::setEditTool, (void*)LLToolCompCreate::getInstance());
- mBtnLand = getChild<LLButton>("button land" );
- childSetAction("button land",LLFloaterTools::setEditTool, (void*)LLToolSelectLand::getInstance());
- mTextStatus = getChild<LLTextBox>("text status");
-
- childSetCommitCallback("slider zoom",commit_slider_zoom,this);
-
- mRadioZoom = getChild<LLCheckBoxCtrl>("radio zoom");
- childSetCommitCallback("radio zoom",commit_radio_zoom,this);
- mRadioOrbit = getChild<LLCheckBoxCtrl>("radio orbit");
- childSetCommitCallback("radio orbit",commit_radio_orbit,this);
- mRadioPan = getChild<LLCheckBoxCtrl>("radio pan");
- childSetCommitCallback("radio pan",commit_radio_pan,this);
-
- mRadioMove = getChild<LLCheckBoxCtrl>("radio move");
- childSetCommitCallback("radio move",click_popup_grab_drag,this);
- mRadioLift = getChild<LLCheckBoxCtrl>("radio lift");
- childSetCommitCallback("radio lift",click_popup_grab_lift,this);
- mRadioSpin = getChild<LLCheckBoxCtrl>("radio spin");
- childSetCommitCallback("radio spin",click_popup_grab_spin,NULL);
- mRadioPosition = getChild<LLCheckBoxCtrl>("radio position");
- childSetCommitCallback("radio position",commit_select_tool,LLToolCompTranslate::getInstance());
- mRadioRotate = getChild<LLCheckBoxCtrl>("radio rotate");
- childSetCommitCallback("radio rotate",commit_select_tool,LLToolCompRotate::getInstance());
- mRadioStretch = getChild<LLCheckBoxCtrl>("radio stretch");
- childSetCommitCallback("radio stretch",commit_select_tool,LLToolCompScale::getInstance());
- mRadioSelectFace = getChild<LLCheckBoxCtrl>("radio select face");
- childSetCommitCallback("radio select face",commit_select_tool,LLToolFace::getInstance());
- mCheckSelectIndividual = getChild<LLCheckBoxCtrl>("checkbox edit linked parts");
+ mBtnFocus = getChild<LLButton>("button focus");//btn;
+ mBtnMove = getChild<LLButton>("button move");
+ mBtnEdit = getChild<LLButton>("button edit");
+ mBtnCreate = getChild<LLButton>("button create");
+ mBtnLand = getChild<LLButton>("button land" );
+ mTextStatus = getChild<LLTextBox>("text status");
+ mRadioGroupFocus = getChild<LLRadioGroup>("focus_radio_group");
+ mRadioGroupMove = getChild<LLRadioGroup>("move_radio_group");
+ mRadioGroupEdit = getChild<LLRadioGroup>("edit_radio_group");
+ mBtnGridOptions = getChild<LLButton>("Options...");
+ mTitleMedia = getChild<LLMediaCtrl>("title_media");
+
+ mCheckSelectIndividual = getChild<LLCheckBoxCtrl>("checkbox edit linked parts");
childSetValue("checkbox edit linked parts",(BOOL)gSavedSettings.getBOOL("EditLinkedParts"));
- childSetCommitCallback("checkbox edit linked parts",commit_select_component,this);
- mCheckSnapToGrid = getChild<LLCheckBoxCtrl>("checkbox snap to grid");
+ mCheckSnapToGrid = getChild<LLCheckBoxCtrl>("checkbox snap to grid");
childSetValue("checkbox snap to grid",(BOOL)gSavedSettings.getBOOL("SnapEnabled"));
- mBtnGridOptions = getChild<LLButton>("Options...");
- childSetAction("Options...",onClickGridOptions, this);
- mCheckStretchUniform = getChild<LLCheckBoxCtrl>("checkbox uniform");
+ mCheckStretchUniform = getChild<LLCheckBoxCtrl>("checkbox uniform");
childSetValue("checkbox uniform",(BOOL)gSavedSettings.getBOOL("ScaleUniform"));
- mCheckStretchTexture = getChild<LLCheckBoxCtrl>("checkbox stretch textures");
+ mCheckStretchTexture = getChild<LLCheckBoxCtrl>("checkbox stretch textures");
childSetValue("checkbox stretch textures",(BOOL)gSavedSettings.getBOOL("ScaleStretchTextures"));
- mTextGridMode = getChild<LLTextBox>("text ruler mode");
- mComboGridMode = getChild<LLComboBox>("combobox grid mode");
- childSetCommitCallback("combobox grid mode",commit_grid_mode, this);
+ mTextGridMode = getChild<LLTextBox>("text ruler mode");
+ mComboGridMode = getChild<LLComboBox>("combobox grid mode");
+
//
// Create Buttons
//
- static const std::string toolNames[]={
- "ToolCube",
- "ToolPrism",
- "ToolPyramid",
- "ToolTetrahedron",
- "ToolCylinder",
- "ToolHemiCylinder",
- "ToolCone",
- "ToolHemiCone",
- "ToolSphere",
- "ToolHemiSphere",
- "ToolTorus",
- "ToolTube",
- "ToolRing",
- "ToolTree",
- "ToolGrass"};
- void* toolData[]={
- &LLToolPlacerPanel::sCube,
- &LLToolPlacerPanel::sPrism,
- &LLToolPlacerPanel::sPyramid,
- &LLToolPlacerPanel::sTetrahedron,
- &LLToolPlacerPanel::sCylinder,
- &LLToolPlacerPanel::sCylinderHemi,
- &LLToolPlacerPanel::sCone,
- &LLToolPlacerPanel::sConeHemi,
- &LLToolPlacerPanel::sSphere,
- &LLToolPlacerPanel::sSphereHemi,
- &LLToolPlacerPanel::sTorus,
- &LLToolPlacerPanel::sSquareTorus,
- &LLToolPlacerPanel::sTriangleTorus,
- &LLToolPlacerPanel::sTree,
- &LLToolPlacerPanel::sGrass};
for(size_t t=0; t<LL_ARRAY_SIZE(toolNames); ++t)
{
LLButton *found = getChild<LLButton>(toolNames[t]);
if(found)
{
- found->setClickedCallback(setObjectType,toolData[t]);
+ found->setClickedCallback(boost::bind(&LLFloaterTools::setObjectType, toolData[t]));
mButtons.push_back( found );
}else{
llwarns << "Tool button not found! DOA Pending." << llendl;
@@ -290,29 +261,12 @@ BOOL LLFloaterTools::postBuild()
childSetValue("checkbox copy centers",(BOOL)gSavedSettings.getBOOL("CreateToolCopyCenters"));
mCheckCopyRotates = getChild<LLCheckBoxCtrl>("checkbox copy rotates");
childSetValue("checkbox copy rotates",(BOOL)gSavedSettings.getBOOL("CreateToolCopyRotates"));
- mRadioSelectLand = getChild<LLCheckBoxCtrl>("radio select land");
- childSetCommitCallback("radio select land",commit_select_tool, LLToolSelectLand::getInstance());
- mRadioDozerFlatten = getChild<LLCheckBoxCtrl>("radio flatten");
- childSetCommitCallback("radio flatten",click_popup_dozer_mode, (void*)0);
- mRadioDozerRaise = getChild<LLCheckBoxCtrl>("radio raise");
- childSetCommitCallback("radio raise",click_popup_dozer_mode, (void*)1);
- mRadioDozerLower = getChild<LLCheckBoxCtrl>("radio lower");
- childSetCommitCallback("radio lower",click_popup_dozer_mode, (void*)2);
- mRadioDozerSmooth = getChild<LLCheckBoxCtrl>("radio smooth");
- childSetCommitCallback("radio smooth",click_popup_dozer_mode, (void*)3);
- mRadioDozerNoise = getChild<LLCheckBoxCtrl>("radio noise");
- childSetCommitCallback("radio noise",click_popup_dozer_mode, (void*)4);
- mRadioDozerRevert = getChild<LLCheckBoxCtrl>("radio revert");
- childSetCommitCallback("radio revert",click_popup_dozer_mode, (void*)5);
- mBtnApplyToSelection = getChild<LLButton>("button apply to selection");
- childSetAction("button apply to selection",click_apply_to_selection, (void*)0);
-
- mSliderDozerSize = getChild<LLSlider>("slider brush size");
- childSetCommitCallback("slider brush size", commit_slider_dozer_size, (void*)0);
+
+ mRadioGroupLand = getChild<LLRadioGroup>("land_radio_group");
+ mBtnApplyToSelection = getChild<LLButton>("button apply to selection");
+ mSliderDozerSize = getChild<LLSlider>("slider brush size");
childSetValue( "slider brush size", gSavedSettings.getF32("LandBrushSize"));
-
- mSliderDozerForce = getChild<LLSlider>("slider force");
- childSetCommitCallback("slider force",commit_slider_dozer_force, (void*)0);
+ mSliderDozerForce = getChild<LLSlider>("slider force");
// the setting stores the actual force multiplier, but the slider is logarithmic, so we convert here
childSetValue( "slider force", log10(gSavedSettings.getF32("LandBrushForce")));
@@ -332,14 +286,16 @@ BOOL LLFloaterTools::postBuild()
mStatusText["grab"] = getString("status_grab");
mStatusText["place"] = getString("status_place");
mStatusText["selectland"] = getString("status_selectland");
+
+ sShowObjectCost = gSavedSettings.getBOOL("ShowObjectRenderingCost");
return TRUE;
}
// Create the popupview with a dummy center. It will be moved into place
// during LLViewerWindow's per-frame hover processing.
-LLFloaterTools::LLFloaterTools()
-: LLFloater(std::string("toolbox floater")),
+LLFloaterTools::LLFloaterTools(const LLSD& key)
+: LLFloater(key),
mBtnFocus(NULL),
mBtnMove(NULL),
mBtnEdit(NULL),
@@ -347,22 +303,15 @@ LLFloaterTools::LLFloaterTools()
mBtnLand(NULL),
mTextStatus(NULL),
- mRadioOrbit(NULL),
- mRadioZoom(NULL),
- mRadioPan(NULL),
+ mRadioGroupFocus(NULL),
+ mRadioGroupMove(NULL),
+ mRadioGroupEdit(NULL),
- mRadioMove(NULL),
- mRadioLift(NULL),
- mRadioSpin(NULL),
-
- mRadioPosition(NULL),
- mRadioRotate(NULL),
- mRadioStretch(NULL),
- mRadioSelectFace(NULL),
mCheckSelectIndividual(NULL),
mCheckSnapToGrid(NULL),
mBtnGridOptions(NULL),
+ mTitleMedia(NULL),
mTextGridMode(NULL),
mComboGridMode(NULL),
mCheckStretchUniform(NULL),
@@ -380,13 +329,7 @@ LLFloaterTools::LLFloaterTools()
mCheckCopySelection(NULL),
mCheckCopyCenters(NULL),
mCheckCopyRotates(NULL),
- mRadioSelectLand(NULL),
- mRadioDozerFlatten(NULL),
- mRadioDozerRaise(NULL),
- mRadioDozerLower(NULL),
- mRadioDozerSmooth(NULL),
- mRadioDozerNoise(NULL),
- mRadioDozerRevert(NULL),
+ mRadioGroupLand(NULL),
mSliderDozerSize(NULL),
mSliderDozerForce(NULL),
mBtnApplyToSelection(NULL),
@@ -400,24 +343,42 @@ LLFloaterTools::LLFloaterTools()
mPanelLandInfo(NULL),
mTabLand(NULL),
- mDirty(TRUE)
+ mDirty(TRUE),
+ mNeedMediaTitle(TRUE)
{
+ gFloaterTools = this;
+
setAutoFocus(FALSE);
- LLCallbackMap::map_t factory_map;
- factory_map["General"] = LLCallbackMap(createPanelPermissions, this);//LLPanelPermissions
- factory_map["Object"] = LLCallbackMap(createPanelObject, this);//LLPanelObject
- factory_map["Features"] = LLCallbackMap(createPanelVolume, this);//LLPanelVolume
- factory_map["Texture"] = LLCallbackMap(createPanelFace, this);//LLPanelFace
- factory_map["Contents"] = LLCallbackMap(createPanelContents, this);//LLPanelContents
- factory_map["ContentsInventory"] = LLCallbackMap(createPanelContentsInventory, this);//LLPanelContents
- factory_map["land info panel"] = LLCallbackMap(createPanelLandInfo, this);//LLPanelLandInfo
+ mFactoryMap["General"] = LLCallbackMap(createPanelPermissions, this);//LLPanelPermissions
+ mFactoryMap["Object"] = LLCallbackMap(createPanelObject, this);//LLPanelObject
+ mFactoryMap["Features"] = LLCallbackMap(createPanelVolume, this);//LLPanelVolume
+ mFactoryMap["Texture"] = LLCallbackMap(createPanelFace, this);//LLPanelFace
+ mFactoryMap["Contents"] = LLCallbackMap(createPanelContents, this);//LLPanelContents
+ mFactoryMap["land info panel"] = LLCallbackMap(createPanelLandInfo, this);//LLPanelLandInfo
+
+ //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this,"floater_tools.xml",FALSE);
+ mCommitCallbackRegistrar.add("BuildTool.setTool", boost::bind(&LLFloaterTools::setTool,this, _2));
+ mCommitCallbackRegistrar.add("BuildTool.commitZoom", boost::bind(&commit_slider_zoom, _1));
+ mCommitCallbackRegistrar.add("BuildTool.commitRadioFocus", boost::bind(&commit_radio_group_focus, _1));
+ mCommitCallbackRegistrar.add("BuildTool.commitRadioMove", boost::bind(&commit_radio_group_move,_1));
+ mCommitCallbackRegistrar.add("BuildTool.commitRadioEdit", boost::bind(&commit_radio_group_edit,_1));
+
+ mCommitCallbackRegistrar.add("BuildTool.selectComponent", boost::bind(&commit_select_component, this));
+ mCommitCallbackRegistrar.add("BuildTool.gridOptions", boost::bind(&LLFloaterTools::onClickGridOptions,this));
+ mCommitCallbackRegistrar.add("BuildTool.applyToSelection", boost::bind(&click_apply_to_selection, this));
+ mCommitCallbackRegistrar.add("BuildTool.gridMode", boost::bind(&commit_grid_mode,_1));
+ 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));
- LLUICtrlFactory::getInstance()->buildFloater(this,"floater_tools.xml",&factory_map,FALSE);
}
LLFloaterTools::~LLFloaterTools()
{
// children automatically deleted
+ gFloaterTools = NULL;
}
void LLFloaterTools::setStatusText(const std::string& text)
@@ -465,11 +426,27 @@ void LLFloaterTools::refresh()
LLResMgr::getInstance()->getIntegerString(prim_count_string, LLSelectMgr::getInstance()->getSelection()->getObjectCount());
childSetTextArg("prim_count", "[COUNT]", prim_count_string);
+ // calculate selection rendering cost
+ if (sShowObjectCost)
+ {
+ std::string prim_cost_string;
+ LLResMgr::getInstance()->getIntegerString(prim_cost_string, calcRenderCost());
+ childSetTextArg("RenderingCost", "[COUNT]", prim_cost_string);
+ }
+
+
+ // disable the object and prim counts if nothing selected
+ bool have_selection = ! LLSelectMgr::getInstance()->getSelection()->isEmpty();
+ childSetEnabled("obj_count", have_selection);
+ childSetEnabled("prim_count", have_selection);
+ childSetEnabled("RenderingCost", have_selection && sShowObjectCost);
+
// Refresh child tabs
mPanelPermissions->refresh();
mPanelObject->refresh();
mPanelVolume->refresh();
mPanelFace->refresh();
+ refreshMedia();
mPanelContents->refresh();
mPanelLandInfo->refresh();
}
@@ -482,6 +459,9 @@ void LLFloaterTools::draw()
mDirty = FALSE;
}
+ // grab media name/title and update the UI widget
+ updateMediaTitle();
+
// mCheckSelectIndividual->set(gSavedSettings.getBOOL("EditLinkedParts"));
LLFloater::draw();
}
@@ -489,7 +469,8 @@ void LLFloaterTools::draw()
void LLFloaterTools::dirty()
{
mDirty = TRUE;
- LLFloaterOpenObject::dirty();
+ LLFloaterOpenObject* instance = LLFloaterReg::findTypedInstance<LLFloaterOpenObject>("openobject");
+ if (instance) instance->dirty();
}
// Clean up any tool state that should not persist when the
@@ -525,26 +506,31 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
mBtnFocus ->setToggleState( focus_visible );
- mRadioZoom ->setVisible( focus_visible );
- mRadioOrbit ->setVisible( focus_visible );
- mRadioPan ->setVisible( focus_visible );
+ mRadioGroupFocus->setVisible( focus_visible );
childSetVisible("slider zoom", focus_visible);
childSetEnabled("slider zoom", gCameraBtnZoom);
- mRadioZoom ->set( !gCameraBtnOrbit &&
- !gCameraBtnPan &&
- !(mask == MASK_ORBIT) &&
- !(mask == (MASK_ORBIT | MASK_ALT)) &&
- !(mask == MASK_PAN) &&
- !(mask == (MASK_PAN | MASK_ALT)) );
-
- mRadioOrbit ->set( gCameraBtnOrbit ||
- (mask == MASK_ORBIT) ||
- (mask == (MASK_ORBIT | MASK_ALT)) );
-
- mRadioPan ->set( gCameraBtnPan ||
- (mask == MASK_PAN) ||
- (mask == (MASK_PAN | MASK_ALT)) );
+ if (!gCameraBtnOrbit &&
+ !gCameraBtnPan &&
+ !(mask == MASK_ORBIT) &&
+ !(mask == (MASK_ORBIT | MASK_ALT)) &&
+ !(mask == MASK_PAN) &&
+ !(mask == (MASK_PAN | MASK_ALT)) )
+ {
+ mRadioGroupFocus->setValue("radio zoom");
+ }
+ else if ( gCameraBtnOrbit ||
+ (mask == MASK_ORBIT) ||
+ (mask == (MASK_ORBIT | MASK_ALT)) )
+ {
+ mRadioGroupFocus->setValue("radio orbit");
+ }
+ else if ( gCameraBtnPan ||
+ (mask == MASK_PAN) ||
+ (mask == (MASK_PAN | MASK_ALT)) )
+ {
+ mRadioGroupFocus->setValue("radio pan");
+ }
// multiply by correction factor because volume sliders go [0, 0.5]
childSetValue( "slider zoom", gAgent.getCameraZoomFraction() * 0.5f);
@@ -555,27 +541,23 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
if (mBtnMove) mBtnMove ->setToggleState( move_visible );
// HACK - highlight buttons for next click
- if (mRadioMove)
+ mRadioGroupMove->setVisible(move_visible);
+ if (!gGrabBtnSpin &&
+ !gGrabBtnVertical &&
+ !(mask == MASK_VERTICAL) &&
+ !(mask == MASK_SPIN) )
{
- mRadioMove ->setVisible( move_visible );
- mRadioMove ->set( !gGrabBtnSpin &&
- !gGrabBtnVertical &&
- !(mask == MASK_VERTICAL) &&
- !(mask == MASK_SPIN) );
+ mRadioGroupMove->setValue("radio move");
}
-
- if (mRadioLift)
+ else if (gGrabBtnVertical ||
+ (mask == MASK_VERTICAL) )
{
- mRadioLift ->setVisible( move_visible );
- mRadioLift ->set( gGrabBtnVertical ||
- (mask == MASK_VERTICAL) );
+ mRadioGroupMove->setValue("radio lift");
}
-
- if (mRadioSpin)
+ else if (gGrabBtnSpin ||
+ (mask == MASK_SPIN) )
{
- mRadioSpin ->setVisible( move_visible );
- mRadioSpin ->set( gGrabBtnSpin ||
- (mask == MASK_SPIN) );
+ mRadioGroupMove->setValue("radio spin");
}
// Edit buttons
@@ -587,15 +569,9 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
tool == LLToolPipette::getInstance();
mBtnEdit ->setToggleState( edit_visible );
-
- mRadioPosition ->setVisible( edit_visible );
- mRadioRotate ->setVisible( edit_visible );
- mRadioStretch ->setVisible( edit_visible );
- if (mRadioSelectFace)
- {
- mRadioSelectFace->setVisible( edit_visible );
- mRadioSelectFace->set( tool == LLToolFace::getInstance() );
- }
+ mRadioGroupEdit->setVisible( edit_visible );
+ bool linked_parts = gSavedSettings.getBOOL("EditLinkedParts");
+ childSetVisible("RenderingCost", !linked_parts && (edit_visible || focus_visible || move_visible) && sShowObjectCost);
if (mCheckSelectIndividual)
{
@@ -603,9 +579,22 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
//mCheckSelectIndividual->set(gSavedSettings.getBOOL("EditLinkedParts"));
}
- mRadioPosition ->set( tool == LLToolCompTranslate::getInstance() );
- mRadioRotate ->set( tool == LLToolCompRotate::getInstance() );
- mRadioStretch ->set( tool == LLToolCompScale::getInstance() );
+ if ( tool == LLToolCompTranslate::getInstance() )
+ {
+ mRadioGroupEdit->setValue("radio position");
+ }
+ else if ( tool == LLToolCompRotate::getInstance() )
+ {
+ mRadioGroupEdit->setValue("radio rotate");
+ }
+ else if ( tool == LLToolCompScale::getInstance() )
+ {
+ mRadioGroupEdit->setValue("radio stretch");
+ }
+ else if ( tool == LLToolFace::getInstance() )
+ {
+ mRadioGroupEdit->setValue("radio select face");
+ }
if (mComboGridMode)
{
@@ -662,15 +651,13 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
else
{
// Highlight the correct placer button
- for( std::vector<LLButton*>::size_type i = 0; i < mButtons.size(); i++ )
+ for( S32 t = 0; t < (S32)mButtons.size(); t++ )
{
LLPCode pcode = LLToolPlacer::getObjectType();
- void *userdata = mButtons[i]->getCallbackUserData();
- LLPCode *cur = (LLPCode*) userdata;
-
- BOOL state = (pcode == *cur);
- mButtons[i]->setToggleState( state );
- mButtons[i]->setVisible( create_visible );
+ LLPCode button_pcode = toolData[t];
+ BOOL state = (pcode == button_pcode);
+ mButtons[t]->setToggleState( state );
+ mButtons[t]->setVisible( create_visible );
}
}
@@ -687,44 +674,39 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
if (mBtnLand) mBtnLand ->setToggleState( land_visible );
- // mRadioEditLand ->set( tool == LLToolBrushLand::getInstance() );
- if (mRadioSelectLand) mRadioSelectLand->set( tool == LLToolSelectLand::getInstance() );
-
- // mRadioEditLand ->setVisible( land_visible );
- if (mRadioSelectLand) mRadioSelectLand->setVisible( land_visible );
-
- S32 dozer_mode = gSavedSettings.getS32("RadioLandBrushAction");
-
- if (mRadioDozerFlatten)
- {
- mRadioDozerFlatten ->set( tool == LLToolBrushLand::getInstance() && dozer_mode == 0);
- mRadioDozerFlatten ->setVisible( land_visible );
- }
- if (mRadioDozerRaise)
- {
- mRadioDozerRaise ->set( tool == LLToolBrushLand::getInstance() && dozer_mode == 1);
- mRadioDozerRaise ->setVisible( land_visible );
- }
- if (mRadioDozerLower)
- {
- mRadioDozerLower ->set( tool == LLToolBrushLand::getInstance() && dozer_mode == 2);
- mRadioDozerLower ->setVisible( land_visible );
- }
- if (mRadioDozerSmooth)
- {
- mRadioDozerSmooth ->set( tool == LLToolBrushLand::getInstance() && dozer_mode == 3);
- mRadioDozerSmooth ->setVisible( land_visible );
- }
- if (mRadioDozerNoise)
+ mRadioGroupLand->setVisible( land_visible );
+ if ( tool == LLToolSelectLand::getInstance() )
{
- mRadioDozerNoise ->set( tool == LLToolBrushLand::getInstance() && dozer_mode == 4);
- mRadioDozerNoise ->setVisible( land_visible );
+ mRadioGroupLand->setValue("radio select land");
}
- if (mRadioDozerRevert)
+ else if ( tool == LLToolBrushLand::getInstance() )
{
- mRadioDozerRevert ->set( tool == LLToolBrushLand::getInstance() && dozer_mode == 5);
- mRadioDozerRevert ->setVisible( land_visible );
+ S32 dozer_mode = gSavedSettings.getS32("RadioLandBrushAction");
+ switch(dozer_mode)
+ {
+ case 0:
+ mRadioGroupLand->setValue("radio flatten");
+ break;
+ case 1:
+ mRadioGroupLand->setValue("radio raise");
+ break;
+ case 2:
+ mRadioGroupLand->setValue("radio lower");
+ break;
+ case 3:
+ mRadioGroupLand->setValue("radio smooth");
+ break;
+ case 4:
+ mRadioGroupLand->setValue("radio noise");
+ break;
+ case 5:
+ mRadioGroupLand->setValue("radio revert");
+ break;
+ default:
+ break;
+ }
}
+
if (mBtnApplyToSelection)
{
mBtnApplyToSelection->setVisible( land_visible );
@@ -757,24 +739,31 @@ BOOL LLFloaterTools::canClose()
}
// virtual
-void LLFloaterTools::onOpen()
+void LLFloaterTools::onOpen(const LLSD& key)
{
mParcelSelection = LLViewerParcelMgr::getInstance()->getFloatingParcelSelection();
mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
- // gMenuBarView->setItemVisible(std::string("Tools"), TRUE);
- // gMenuBarView->arrange();
+ std::string panel = key.asString();
+ if (!panel.empty())
+ {
+ mTab->selectTabByName(panel);
+ }
+
+ //gMenuBarView->setItemVisible("BuildTools", TRUE);
}
// virtual
void LLFloaterTools::onClose(bool app_quitting)
{
- setMinimized(FALSE);
- setVisible(FALSE);
mTab->setVisible(FALSE);
LLViewerJoystick::getInstance()->moveAvatar(false);
+ // destroy media source used to grab media title
+ if( mTitleMedia )
+ mTitleMedia->unloadMediaSource();
+
// Different from handle_reset_view in that it doesn't actually
// move the camera if EditCameraMovement is not set.
gAgent.resetView(gSavedSettings.getBOOL("EditCameraMovement"));
@@ -796,19 +785,12 @@ void LLFloaterTools::onClose(bool app_quitting)
// so manually reset tool to default (pie menu tool)
LLToolMgr::getInstance()->getCurrentToolset()->selectFirstTool();
- // gMenuBarView->setItemVisible(std::string("Tools"), FALSE);
- // gMenuBarView->arrange();
-}
-
-void LLFloaterTools::showPanel(EInfoPanel panel)
-{
- llassert(panel >= 0 && panel < PANEL_COUNT);
- mTab->selectTabByName(PANEL_NAMES[panel]);
+ //gMenuBarView->setItemVisible("BuildTools", FALSE);
+ LLFloaterReg::hideInstance("media_settings");
}
void click_popup_info(void*)
{
-// gBuildView->setPropertiesPanelOpen(TRUE);
}
void click_popup_done(void*)
@@ -816,46 +798,52 @@ void click_popup_done(void*)
handle_reset_view();
}
-void click_popup_grab_drag(LLUICtrl*, void*)
-{
- gGrabBtnVertical = FALSE;
- gGrabBtnSpin = FALSE;
-}
-
-void click_popup_grab_lift(LLUICtrl*, void*)
-{
- gGrabBtnVertical = TRUE;
- gGrabBtnSpin = FALSE;
-}
-
-void click_popup_grab_spin(LLUICtrl*, void*)
-{
- gGrabBtnVertical = FALSE;
- gGrabBtnSpin = TRUE;
-}
-
-void commit_radio_zoom(LLUICtrl *, void*)
-{
- gCameraBtnZoom = TRUE;
- gCameraBtnOrbit = FALSE;
- gCameraBtnPan = FALSE;
-}
-
-void commit_radio_orbit(LLUICtrl *, void*)
+void commit_radio_group_move(LLUICtrl* ctrl)
{
- gCameraBtnZoom = FALSE;
- gCameraBtnOrbit = TRUE;
- gCameraBtnPan = FALSE;
+ LLRadioGroup* group = (LLRadioGroup*)ctrl;
+ std::string selected = group->getValue().asString();
+ if (selected == "radio move")
+ {
+ gGrabBtnVertical = FALSE;
+ gGrabBtnSpin = FALSE;
+ }
+ else if (selected == "radio lift")
+ {
+ gGrabBtnVertical = TRUE;
+ gGrabBtnSpin = FALSE;
+ }
+ else if (selected == "radio spin")
+ {
+ gGrabBtnVertical = FALSE;
+ gGrabBtnSpin = TRUE;
+ }
}
-void commit_radio_pan(LLUICtrl *, void*)
+void commit_radio_group_focus(LLUICtrl* ctrl)
{
- gCameraBtnZoom = FALSE;
- gCameraBtnOrbit = FALSE;
- gCameraBtnPan = TRUE;
+ LLRadioGroup* group = (LLRadioGroup*)ctrl;
+ std::string selected = group->getValue().asString();
+ if (selected == "radio zoom")
+ {
+ gCameraBtnZoom = TRUE;
+ gCameraBtnOrbit = FALSE;
+ gCameraBtnPan = FALSE;
+ }
+ else if (selected == "radio orbit")
+ {
+ gCameraBtnZoom = FALSE;
+ gCameraBtnOrbit = TRUE;
+ gCameraBtnPan = FALSE;
+ }
+ else if (selected == "radio pan")
+ {
+ gCameraBtnZoom = FALSE;
+ gCameraBtnOrbit = FALSE;
+ gCameraBtnPan = TRUE;
+ }
}
-void commit_slider_zoom(LLUICtrl *ctrl, void*)
+void commit_slider_zoom(LLUICtrl *ctrl)
{
// renormalize value, since max "volume" level is 0.5 for some reason
F32 zoom_level = (F32)ctrl->getValue().asReal() * 2.f; // / 0.5f;
@@ -880,43 +868,72 @@ void click_popup_rotate_right(void*)
dialog_refresh_all();
}
-
-void click_popup_dozer_mode(LLUICtrl *, void *user)
-{
- S32 mode = (S32)(intptr_t) user;
- gFloaterTools->setEditTool( LLToolBrushLand::getInstance() );
- gSavedSettings.setS32("RadioLandBrushAction", mode);
-}
-
-void commit_slider_dozer_size(LLUICtrl *ctrl, void*)
-{
- F32 size = (F32)ctrl->getValue().asReal();
- gSavedSettings.setF32("LandBrushSize", size);
-}
-
-void commit_slider_dozer_force(LLUICtrl *ctrl, void*)
+void commit_slider_dozer_force(LLUICtrl *ctrl)
{
// the slider is logarithmic, so we exponentiate to get the actual force multiplier
F32 dozer_force = pow(10.f, (F32)ctrl->getValue().asReal());
gSavedSettings.setF32("LandBrushForce", dozer_force);
}
-
-
-
-void click_apply_to_selection(void* user)
+void click_apply_to_selection(void*)
{
LLToolBrushLand::getInstance()->modifyLandInSelectionGlobal();
}
-void commit_select_tool(LLUICtrl *ctrl, void *data)
+void commit_radio_group_edit(LLUICtrl *ctrl)
{
S32 show_owners = gSavedSettings.getBOOL("ShowParcelOwners");
- gFloaterTools->setEditTool(data);
+
+ LLRadioGroup* group = (LLRadioGroup*)ctrl;
+ std::string selected = group->getValue().asString();
+ if (selected == "radio position")
+ {
+ LLFloaterTools::setEditTool( LLToolCompTranslate::getInstance() );
+ }
+ else if (selected == "radio rotate")
+ {
+ LLFloaterTools::setEditTool( LLToolCompRotate::getInstance() );
+ }
+ else if (selected == "radio stretch")
+ {
+ LLFloaterTools::setEditTool( LLToolCompScale::getInstance() );
+ }
+ else if (selected == "radio select face")
+ {
+ LLFloaterTools::setEditTool( LLToolFace::getInstance() );
+ }
gSavedSettings.setBOOL("ShowParcelOwners", show_owners);
}
-void commit_select_component(LLUICtrl *ctrl, void *data)
+void commit_radio_group_land(LLUICtrl* ctrl)
+{
+ LLRadioGroup* group = (LLRadioGroup*)ctrl;
+ std::string selected = group->getValue().asString();
+ if (selected == "radio select land")
+ {
+ LLFloaterTools::setEditTool( LLToolSelectLand::getInstance() );
+ }
+ else
+ {
+ LLFloaterTools::setEditTool( LLToolBrushLand::getInstance() );
+ S32 dozer_mode = gSavedSettings.getS32("RadioLandBrushAction");
+ if (selected == "radio flatten")
+ dozer_mode = 0;
+ else if (selected == "radio raise")
+ dozer_mode = 1;
+ else if (selected == "radio lower")
+ dozer_mode = 2;
+ else if (selected == "radio smooth")
+ dozer_mode = 3;
+ else if (selected == "radio noise")
+ dozer_mode = 4;
+ else if (selected == "radio revert")
+ dozer_mode = 5;
+ gSavedSettings.setS32("RadioLandBrushAction", dozer_mode);
+ }
+}
+
+void commit_select_component(void *data)
{
LLFloaterTools* floaterp = (LLFloaterTools*)data;
@@ -940,7 +957,7 @@ void commit_select_component(LLUICtrl *ctrl, void *data)
}
}
-void commit_grid_mode(LLUICtrl *ctrl, void *data)
+void commit_grid_mode(LLUICtrl *ctrl)
{
LLComboBox* combo = (LLComboBox*)ctrl;
@@ -948,26 +965,69 @@ void commit_grid_mode(LLUICtrl *ctrl, void *data)
}
// static
-void LLFloaterTools::setObjectType( void* data )
+void LLFloaterTools::setObjectType( LLPCode pcode )
{
- LLPCode pcode = *(LLPCode*) data;
LLToolPlacer::setObjectType( pcode );
gSavedSettings.setBOOL("CreateToolCopySelection", FALSE);
gFocusMgr.setMouseCapture(NULL);
}
-// static
-void LLFloaterTools::onClickGridOptions(void* data)
+
+void LLFloaterTools::onClickGridOptions()
{
- //LLFloaterTools* floaterp = (LLFloaterTools*)data;
- LLFloaterBuildOptions::show(NULL);
+ LLFloaterReg::showInstance("build_options");
// RN: this makes grid options dependent on build tools window
//floaterp->addDependentFloater(LLFloaterBuildOptions::getInstance(), FALSE);
}
+S32 LLFloaterTools::calcRenderCost()
+{
+ S32 cost = 0;
+ std::set<LLUUID> textures;
+
+ for (LLObjectSelection::iterator selection_iter = LLSelectMgr::getInstance()->getSelection()->begin();
+ selection_iter != LLSelectMgr::getInstance()->getSelection()->end();
+ ++selection_iter)
+ {
+ LLSelectNode *select_node = *selection_iter;
+ if (select_node)
+ {
+ LLVOVolume *viewer_volume = (LLVOVolume*)select_node->getObject();
+ if (viewer_volume)
+ {
+ cost += viewer_volume->getRenderCost(textures);
+ cost += textures.size() * LLVOVolume::ARC_TEXTURE_COST;
+ textures.clear();
+ }
+ }
+ }
+
+
+ return cost;
+}
+
+// static
void LLFloaterTools::setEditTool(void* tool_pointer)
{
- select_tool(tool_pointer);
+ LLTool *tool = (LLTool *)tool_pointer;
+ LLToolMgr::getInstance()->getCurrentToolset()->selectTool( tool );
+}
+
+void LLFloaterTools::setTool(const LLSD& user_data)
+{
+ std::string control_name = user_data.asString();
+ if(control_name == "Focus")
+ LLToolMgr::getInstance()->getCurrentToolset()->selectTool((LLTool *) LLToolCamera::getInstance() );
+ else if (control_name == "Move" )
+ LLToolMgr::getInstance()->getCurrentToolset()->selectTool( (LLTool *)LLToolGrab::getInstance() );
+ else if (control_name == "Edit" )
+ LLToolMgr::getInstance()->getCurrentToolset()->selectTool( (LLTool *) LLToolCompTranslate::getInstance());
+ else if (control_name == "Create" )
+ LLToolMgr::getInstance()->getCurrentToolset()->selectTool( (LLTool *) LLToolCompCreate::getInstance());
+ else if (control_name == "Land" )
+ LLToolMgr::getInstance()->getCurrentToolset()->selectTool( (LLTool *) LLToolSelectLand::getInstance());
+ else
+ llwarns<<" no parameter name "<<control_name<<" found!! No Tool selected!!"<< llendl;
}
void LLFloaterTools::onFocusReceived()
@@ -975,3 +1035,822 @@ void LLFloaterTools::onFocusReceived()
LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
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::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()
+ ))
+ {
+ childSetEnabled("Add_Media", FALSE);
+ media_info->clear();
+ clearMediaSettings();
+ return;
+ }
+
+ std::string url = first_object->getRegion()->getCapability("ObjectMedia");
+ bool has_media_capability = (!url.empty());
+
+ if(!has_media_capability)
+ {
+ childSetEnabled("Add_Media", FALSE);
+ LL_WARNS("LLFloaterTools: media") << "Media not enabled (no capability) in this region!" << LL_ENDL;
+ clearMediaSettings();
+ return;
+ }
+
+ bool editable = (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("LLFloaterTools: media")
+ << "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("LLFloaterTools: media")
+// << "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 = "";
+ mNeedMediaTitle = false;
+ // update UI depending on whether "object" (prim or face) has media
+ // and whether or not you are allowed to edit it.
+
+ childSetEnabled("Add_Media", 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();
+
+ // kick off a navigate and flag that we need to update the title
+ navigateToTitleMedia( media_data_get.getHomeURL() );
+ mNeedMediaTitle = true;
+ }
+ // else all faces might be empty.
+ }
+ else // there' re Different Medias' been set on on the faces.
+ {
+ media_title = multi_media_info_str;
+ mNeedMediaTitle = false;
+ }
+
+ childSetEnabled("media_tex", bool_has_media && editable);
+ childSetEnabled( "edit_media", bool_has_media && LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo && editable );
+ childSetEnabled( "delete_media", bool_has_media && editable );
+ childSetEnabled( "add_media", ( ! bool_has_media ) && editable );
+ // TODO: display a list of all media on the face - use 'identical' flag
+ }
+ else // not all face has media but at least one does.
+ {
+ // 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;
+ mNeedMediaTitle = false;
+ }
+ 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();
+
+ // kick off a navigate and flag that we need to update the title
+ navigateToTitleMedia( media_data_get.getHomeURL() );
+ mNeedMediaTitle = true;
+ }
+ }
+
+ childSetEnabled("media_tex", TRUE);
+ childSetEnabled( "edit_media", LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo);
+ childSetEnabled( "delete_media", TRUE);
+ childSetEnabled( "add_media", FALSE );
+ }
+ 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 );
+ if(LLFloaterReg::instanceVisible("media_settings"))
+ {
+ LLFloaterReg::hideInstance("media_settings");
+ }
+ break;
+
+ case 1: // "No"
+ default:
+ break;
+ }
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+void LLFloaterTools::clearMediaSettings()
+{
+ LLFloaterMediaSettings::getInstance();
+ LLFloaterMediaSettings::clearValues(false);
+
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+void LLFloaterTools::navigateToTitleMedia( const std::string url )
+{
+ if ( mTitleMedia )
+ {
+ LLPluginClassMedia* media_plugin = mTitleMedia->getMediaPlugin();
+ if ( media_plugin )
+ {
+ // if it's a movie, we don't want to hear it
+ media_plugin->setVolume( 0 );
+ };
+ mTitleMedia->navigateTo( url );
+ };
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+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();
+ 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();
+ };
+
+ 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
+ value_bool = default_media_data.getAutoScale();
+ 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();;
+ };
+
+ 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 833a8a7b73..e1f3c9b78c 100644
--- a/indra/newview/llfloatertools.h
+++ b/indra/newview/llfloatertools.h
@@ -38,18 +38,20 @@
#include "llparcelselection.h"
class LLButton;
-class LLTextBox;
-class LLTool;
+class LLComboBox;
class LLCheckBoxCtrl;
-class LLTabContainer;
class LLPanelPermissions;
class LLPanelObject;
class LLPanelVolume;
class LLPanelContents;
class LLPanelFace;
class LLPanelLandInfo;
-class LLComboBox;
+class LLRadioGroup;
class LLSlider;
+class LLTabContainer;
+class LLTextBox;
+class LLMediaCtrl;
+class LLTool;
class LLParcelSelection;
class LLObjectSelection;
@@ -65,15 +67,16 @@ public:
static void* createPanelVolume(void* vdata);
static void* createPanelFace(void* vdata);
static void* createPanelContents(void* vdata);
- static void* createPanelContentsInventory(void* vdata);
static void* createPanelLandInfo(void* vdata);
- LLFloaterTools();
+ LLFloaterTools(const LLSD& key);
virtual ~LLFloaterTools();
- virtual void onOpen();
- virtual void onClose(bool app_quitting);
- virtual BOOL canClose();
+ /*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ BOOL canClose();
+ /*virtual*/ void onClose(bool app_quitting);
+ /*virtual*/ void draw();
+ /*virtual*/ void onFocusReceived();
// call this once per frame to handle visibility, rect location,
// button highlights, etc.
@@ -93,24 +96,33 @@ public:
PANEL_COUNT
};
- /*virtual*/ void draw();
-
void dirty();
void showPanel(EInfoPanel panel);
void setStatusText(const std::string& text);
- virtual void onFocusReceived();
static void setEditTool(void* data);
+ void setTool(const LLSD& user_data);
void saveLastTool();
+ void onClickBtnDeleteMedia();
+ void onClickBtnAddMedia();
+ void onClickBtnEditMedia();
+ void clearMediaSettings();
+ void updateMediaTitle();
+ void navigateToTitleMedia( const std::string url );
+ bool selectedMediaEditable();
+
private:
- static void setObjectType( void* data );
-
void refresh();
-
- static void onClickGridOptions(void* data);
+ void refreshMedia();
+ void getMediaState();
+ void updateMediaSettings();
+ 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();
+ S32 calcRenderCost();
public:
-
LLButton *mBtnFocus;
LLButton *mBtnMove;
LLButton *mBtnEdit;
@@ -120,20 +132,13 @@ public:
LLTextBox *mTextStatus;
// Focus buttons
- LLCheckBoxCtrl *mRadioOrbit;
- LLCheckBoxCtrl *mRadioZoom;
- LLCheckBoxCtrl *mRadioPan;
+ LLRadioGroup* mRadioGroupFocus;
// Move buttons
- LLCheckBoxCtrl *mRadioMove;
- LLCheckBoxCtrl *mRadioLift;
- LLCheckBoxCtrl *mRadioSpin;
+ LLRadioGroup* mRadioGroupMove;
// Edit buttons
- LLCheckBoxCtrl *mRadioPosition;
- LLCheckBoxCtrl *mRadioRotate;
- LLCheckBoxCtrl *mRadioStretch;
- LLCheckBoxCtrl *mRadioSelectFace;
+ LLRadioGroup* mRadioGroupEdit;
LLCheckBoxCtrl *mCheckSelectIndividual;
@@ -159,15 +164,7 @@ public:
LLCheckBoxCtrl *mCheckCopyRotates;
// Land buttons
-// LLCheckBoxCtrl *mRadioEditLand;
- LLCheckBoxCtrl *mRadioSelectLand;
-
- LLCheckBoxCtrl *mRadioDozerFlatten;
- LLCheckBoxCtrl *mRadioDozerRaise;
- LLCheckBoxCtrl *mRadioDozerLower;
- LLCheckBoxCtrl *mRadioDozerSmooth;
- LLCheckBoxCtrl *mRadioDozerNoise;
- LLCheckBoxCtrl *mRadioDozerRevert;
+ LLRadioGroup* mRadioGroupLand;
LLSlider *mSliderDozerSize;
LLSlider *mSliderDozerForce;
@@ -188,10 +185,20 @@ public:
LLParcelSelectionHandle mParcelSelection;
LLObjectSelectionHandle mObjectSelection;
+ LLMediaCtrl *mTitleMedia;
+ bool mNeedMediaTitle;
+
private:
BOOL mDirty;
std::map<std::string, std::string> mStatusText;
+
+protected:
+ LLSD mMediaSettings;
+
+public:
+ static bool sShowObjectCost;
+
};
extern LLFloaterTools *gFloaterTools;
diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp
index fa6ba162ec..c930e99bad 100644
--- a/indra/newview/llfloatertopobjects.cpp
+++ b/indra/newview/llfloatertopobjects.cpp
@@ -40,8 +40,12 @@
#include "llagent.h"
#include "llbutton.h"
#include "llfloatergodtools.h"
+#include "llfloaterreg.h"
+#include "llnotificationsutil.h"
#include "llparcel.h"
#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "llscrolllistcell.h"
#include "lllineeditor.h"
#include "lltextbox.h"
#include "lltracker.h"
@@ -51,11 +55,11 @@
#include "lluictrlfactory.h"
#include "llviewerwindow.h"
-LLFloaterTopObjects* LLFloaterTopObjects::sInstance = NULL;
+//LLFloaterTopObjects* LLFloaterTopObjects::sInstance = NULL;
// Globals
// const U32 TIME_STR_LENGTH = 30;
-
+/*
// static
void LLFloaterTopObjects::show()
{
@@ -66,64 +70,53 @@ void LLFloaterTopObjects::show()
}
sInstance = new LLFloaterTopObjects();
- LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_top_objects.xml");
+// LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_top_objects.xml");
sInstance->center();
}
-
-LLFloaterTopObjects::LLFloaterTopObjects()
-: LLFloater(std::string("top_objects")),
+*/
+LLFloaterTopObjects::LLFloaterTopObjects(const LLSD& key)
+: LLFloater(key),
mInitialized(FALSE),
mtotalScore(0.f)
{
- sInstance = this;
+ mCommitCallbackRegistrar.add("TopObjects.ShowBeacon", boost::bind(&LLFloaterTopObjects::onClickShowBeacon, this));
+ mCommitCallbackRegistrar.add("TopObjects.ReturnSelected", boost::bind(&LLFloaterTopObjects::onReturnSelected, this));
+ mCommitCallbackRegistrar.add("TopObjects.ReturnAll", boost::bind(&LLFloaterTopObjects::onReturnAll, this));
+ mCommitCallbackRegistrar.add("TopObjects.DisableSelected", boost::bind(&LLFloaterTopObjects::onDisableSelected, this));
+ mCommitCallbackRegistrar.add("TopObjects.DisableAll", boost::bind(&LLFloaterTopObjects::onDisableAll, this));
+ mCommitCallbackRegistrar.add("TopObjects.Refresh", boost::bind(&LLFloaterTopObjects::onRefresh, this));
+ mCommitCallbackRegistrar.add("TopObjects.GetByObjectName", boost::bind(&LLFloaterTopObjects::onGetByObjectName, this));
+ mCommitCallbackRegistrar.add("TopObjects.GetByOwnerName", boost::bind(&LLFloaterTopObjects::onGetByOwnerName, this));
+ mCommitCallbackRegistrar.add("TopObjects.CommitObjectsList",boost::bind(&LLFloaterTopObjects::onCommitObjectsList, this));
}
LLFloaterTopObjects::~LLFloaterTopObjects()
{
- sInstance = NULL;
}
// virtual
BOOL LLFloaterTopObjects::postBuild()
{
- childSetCommitCallback("objects_list", onCommitObjectsList, this);
- childSetDoubleClickCallback("objects_list", onDoubleClickObjectsList);
- childSetFocus("objects_list");
LLScrollListCtrl *objects_list = getChild<LLScrollListCtrl>("objects_list");
- if (objects_list)
- {
- objects_list->setCommitOnSelectionChange(TRUE);
- }
+ childSetFocus("objects_list");
+ objects_list->setDoubleClickCallback(onDoubleClickObjectsList, this);
+ objects_list->setCommitOnSelectionChange(TRUE);
- childSetAction("show_beacon_btn", onClickShowBeacon, this);
setDefaultBtn("show_beacon_btn");
- childSetAction("return_selected_btn", onReturnSelected, this);
- childSetAction("return_all_btn", onReturnAll, this);
- childSetAction("disable_selected_btn", onDisableSelected, this);
- childSetAction("disable_all_btn", onDisableAll, this);
- childSetAction("refresh_btn", onRefresh, this);
-
-
- childSetAction("filter_object_btn", onGetByObjectNameClicked, this);
- childSetAction("filter_owner_btn", onGetByOwnerNameClicked, this);
-
-
/*
LLLineEditor* line_editor = getChild<LLLineEditor>("owner_name_editor");
if (line_editor)
{
line_editor->setCommitOnFocusLost(FALSE);
- line_editor->setCommitCallback(onGetByOwnerName);
- line_editor->setCallbackUserData(this);
+ line_editor->setCommitCallback(onGetByOwnerName, this);
}
line_editor = getChild<LLLineEditor>("object_name_editor");
if (line_editor)
{
line_editor->setCommitOnFocusLost(FALSE);
- line_editor->setCommitCallback(onGetByObjectName);
- line_editor->setCallbackUserData(this);
+ line_editor->setCommitCallback(onGetByObjectName, this);
}*/
mCurrentMode = STAT_REPORT_TOP_SCRIPTS;
@@ -132,19 +125,29 @@ BOOL LLFloaterTopObjects::postBuild()
return TRUE;
}
+// static
+void LLFloaterTopObjects::setMode(U32 mode)
+{
+ LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance<LLFloaterTopObjects>("top_objects");
+ if(!instance) return;
+ instance->mCurrentMode = mode;
+}
+// static
void LLFloaterTopObjects::handle_land_reply(LLMessageSystem* msg, void** data)
{
+ LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance<LLFloaterTopObjects>("top_objects");
+ if(!instance) return;
// Make sure dialog is on screen
- show();
- sInstance->handleReply(msg, data);
+ LLFloaterReg::showInstance("top_objects");
+ instance->handleReply(msg, data);
//HACK: for some reason sometimes top scripts originally comes back
//with no results even though they're there
- if (!sInstance->mObjectListIDs.size() && !sInstance->mInitialized)
+ if (!instance->mObjectListIDs.size() && !instance->mInitialized)
{
- sInstance->onRefresh(NULL);
- sInstance->mInitialized = TRUE;
+ instance->onRefresh();
+ instance->mInitialized = TRUE;
}
}
@@ -159,7 +162,7 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)
msg->getU32Fast(_PREHASH_RequestData, _PREHASH_ReportType, mCurrentMode);
LLScrollListCtrl *list = getChild<LLScrollListCtrl>("objects_list");
-
+
S32 block_count = msg->getNumberOfBlocks("ReportData");
for (S32 block = 0; block < block_count; ++block)
{
@@ -234,7 +237,7 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)
if (total_count == 0 && list->getItemCount() == 0)
{
- list->addCommentText(getString("none_descriptor"));
+ list->setCommentText(getString("none_descriptor"));
}
else
{
@@ -263,12 +266,9 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)
}
}
-// static
-void LLFloaterTopObjects::onCommitObjectsList(LLUICtrl* ctrl, void* data)
+void LLFloaterTopObjects::onCommitObjectsList()
{
- LLFloaterTopObjects* self = (LLFloaterTopObjects*)data;
-
- self->updateSelectionInfo();
+ updateSelectionInfo();
}
void LLFloaterTopObjects::updateSelectionInfo()
@@ -295,11 +295,9 @@ void LLFloaterTopObjects::onDoubleClickObjectsList(void* data)
}
// static
-void LLFloaterTopObjects::onClickShowBeacon(void* data)
+void LLFloaterTopObjects::onClickShowBeacon()
{
- LLFloaterTopObjects* self = (LLFloaterTopObjects*)data;
- if (!self) return;
- self->showBeacon();
+ showBeacon();
}
void LLFloaterTopObjects::doToObjects(int action, bool all)
@@ -362,76 +360,77 @@ void LLFloaterTopObjects::doToObjects(int action, bool all)
//static
bool LLFloaterTopObjects::callbackReturnAll(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance<LLFloaterTopObjects>("top_objects");
+ if(!instance) return false;
if (option == 0)
{
- sInstance->doToObjects(ACTION_RETURN, true);
+ instance->doToObjects(ACTION_RETURN, true);
}
return false;
}
-void LLFloaterTopObjects::onReturnAll(void* data)
+void LLFloaterTopObjects::onReturnAll()
{
- LLNotifications::instance().add("ReturnAllTopObjects", LLSD(), LLSD(), &callbackReturnAll);
+ LLNotificationsUtil::add("ReturnAllTopObjects", LLSD(), LLSD(), &callbackReturnAll);
}
-void LLFloaterTopObjects::onReturnSelected(void* data)
+void LLFloaterTopObjects::onReturnSelected()
{
- sInstance->doToObjects(ACTION_RETURN, false);
+ doToObjects(ACTION_RETURN, false);
}
//static
bool LLFloaterTopObjects::callbackDisableAll(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance<LLFloaterTopObjects>("top_objects");
+ if(!instance) return false;
if (option == 0)
{
- sInstance->doToObjects(ACTION_DISABLE, true);
+ instance->doToObjects(ACTION_DISABLE, true);
}
return false;
}
-void LLFloaterTopObjects::onDisableAll(void* data)
+void LLFloaterTopObjects::onDisableAll()
{
- LLNotifications::instance().add("DisableAllTopObjects", LLSD(), LLSD(), callbackDisableAll);
+ LLNotificationsUtil::add("DisableAllTopObjects", LLSD(), LLSD(), callbackDisableAll);
}
-void LLFloaterTopObjects::onDisableSelected(void* data)
+void LLFloaterTopObjects::onDisableSelected()
{
- sInstance->doToObjects(ACTION_DISABLE, false);
+ doToObjects(ACTION_DISABLE, false);
}
-//static
+
void LLFloaterTopObjects::clearList()
{
- LLCtrlListInterface *list = sInstance->childGetListInterface("objects_list");
+ LLCtrlListInterface *list = childGetListInterface("objects_list");
if (list)
{
list->operateOnAll(LLCtrlListInterface::OP_DELETE);
}
- sInstance->mObjectListData.clear();
- sInstance->mObjectListIDs.clear();
- sInstance->mtotalScore = 0.f;
+ mObjectListData.clear();
+ mObjectListIDs.clear();
+ mtotalScore = 0.f;
}
-//static
-void LLFloaterTopObjects::onRefresh(void* data)
+
+void LLFloaterTopObjects::onRefresh()
{
U32 mode = STAT_REPORT_TOP_SCRIPTS;
U32 flags = 0;
std::string filter = "";
- if (sInstance)
- {
- mode = sInstance->mCurrentMode;
- flags = sInstance->mFlags;
- filter = sInstance->mFilter;
- sInstance->clearList();
- }
+ mode = mCurrentMode;
+ flags = mFlags;
+ filter = mFilter;
+ clearList();
LLMessageSystem *msg = gMessageSystem;
msg->newMessageFast(_PREHASH_LandStatRequest);
@@ -446,35 +445,26 @@ void LLFloaterTopObjects::onRefresh(void* data)
msg->sendReliable(gAgent.getRegionHost());
- if (sInstance)
- {
- sInstance->mFilter.clear();
- sInstance->mFlags = 0;
- }
+ mFilter.clear();
+ mFlags = 0;
}
-void LLFloaterTopObjects::onGetByObjectName(LLUICtrl* ctrl, void* data)
+void LLFloaterTopObjects::onGetByObjectName()
{
- if (sInstance)
- {
- sInstance->mFlags = STAT_FILTER_BY_OBJECT;
- sInstance->mFilter = sInstance->childGetText("object_name_editor");
- onRefresh(NULL);
- }
+ mFlags = STAT_FILTER_BY_OBJECT;
+ mFilter = childGetText("object_name_editor");
+ onRefresh();
}
-void LLFloaterTopObjects::onGetByOwnerName(LLUICtrl* ctrl, void* data)
+void LLFloaterTopObjects::onGetByOwnerName()
{
- if (sInstance)
- {
- sInstance->mFlags = STAT_FILTER_BY_OWNER;
- sInstance->mFilter = sInstance->childGetText("owner_name_editor");
- onRefresh(NULL);
- }
+ mFlags = STAT_FILTER_BY_OWNER;
+ mFilter = childGetText("owner_name_editor");
+ onRefresh();
}
void LLFloaterTopObjects::showBeacon()
-{
+{
LLScrollListCtrl* list = getChild<LLScrollListCtrl>("objects_list");
if (!list) return;
diff --git a/indra/newview/llfloatertopobjects.h b/indra/newview/llfloatertopobjects.h
index 58cbf5d2ce..ee3c5d3cce 100644
--- a/indra/newview/llfloatertopobjects.h
+++ b/indra/newview/llfloatertopobjects.h
@@ -39,48 +39,49 @@ class LLUICtrl;
class LLFloaterTopObjects : public LLFloater
{
+ friend class LLFloaterReg;
public:
// Opens the floater on screen.
- static void show();
+// static void show();
// Opens the floater if it's not on-screen.
// Juggles the UI based on method = "scripts" or "colliders"
static void handle_land_reply(LLMessageSystem* msg, void** data);
void handleReply(LLMessageSystem* msg, void** data);
- static void clearList();
+ void clearList();
void updateSelectionInfo();
virtual BOOL postBuild();
- static void onRefresh(void* data);
+ void onRefresh();
- static void setMode(U32 mode) { if (sInstance) sInstance->mCurrentMode = mode; }
+ static void setMode(U32 mode);
private:
- LLFloaterTopObjects();
+ LLFloaterTopObjects(const LLSD& key);
~LLFloaterTopObjects();
void initColumns(LLCtrlListInterface *list);
- static void onCommitObjectsList(LLUICtrl* ctrl, void* data);
+ void onCommitObjectsList();
static void onDoubleClickObjectsList(void* data);
- static void onClickShowBeacon(void* data);
+ void onClickShowBeacon();
void doToObjects(int action, bool all);
- static void onReturnAll(void* data);
- static void onReturnSelected(void* data);
- static void onDisableAll(void* data);
- static void onDisableSelected(void* data);
+ void onReturnAll();
+ void onReturnSelected();
+ void onDisableAll();
+ void onDisableSelected();
static bool callbackReturnAll(const LLSD& notification, const LLSD& response);
static bool callbackDisableAll(const LLSD& notification, const LLSD& response);
- static void onGetByOwnerName(LLUICtrl* ctrl, void* data);
- static void onGetByObjectName(LLUICtrl* ctrl, void* data);
+ void onGetByOwnerName();
+ void onGetByObjectName();
- static void onGetByOwnerNameClicked(void* data) { onGetByOwnerName(NULL, data); };
- static void onGetByObjectNameClicked(void* data) { onGetByObjectName(NULL, data); };
+// static void onGetByOwnerNameClicked(void* data) { onGetByOwnerName(NULL, data); };
+// static void onGetByObjectNameClicked(void* data) { onGetByObjectName(NULL, data); };
void showBeacon();
diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp
index 6a392e03fb..69ee8cd547 100644
--- a/indra/newview/llfloatertos.cpp
+++ b/indra/newview/llfloatertos.cpp
@@ -35,55 +35,30 @@
#include "llfloatertos.h"
// viewer includes
-#include "llagent.h"
-#include "llappviewer.h"
-#include "llstartup.h"
#include "llviewerstats.h"
-#include "llviewertexteditor.h"
#include "llviewerwindow.h"
// linden library includes
#include "llbutton.h"
+#include "llevents.h"
#include "llhttpclient.h"
#include "llhttpstatuscodes.h" // for HTTP_FOUND
+#include "llnotificationsutil.h"
#include "llradiogroup.h"
#include "lltextbox.h"
#include "llui.h"
#include "lluictrlfactory.h"
#include "llvfile.h"
#include "message.h"
+#include "llstartup.h" // login_alert_done
-// static
-LLFloaterTOS* LLFloaterTOS::sInstance = NULL;
-
-// static
-LLFloaterTOS* LLFloaterTOS::show(ETOSType type, const std::string & message)
-{
- if( !LLFloaterTOS::sInstance )
- {
- LLFloaterTOS::sInstance = new LLFloaterTOS(type, message);
- }
-
- if (type == TOS_TOS)
- {
- LLUICtrlFactory::getInstance()->buildFloater(LLFloaterTOS::sInstance, "floater_tos.xml");
- }
- else
- {
- LLUICtrlFactory::getInstance()->buildFloater(LLFloaterTOS::sInstance, "floater_critical.xml");
- }
-
- return LLFloaterTOS::sInstance;
-}
-
-
-LLFloaterTOS::LLFloaterTOS(ETOSType type, const std::string & message)
-: LLModalDialog( std::string(" "), 100, 100 ),
- mType(type),
- mMessage(message),
+LLFloaterTOS::LLFloaterTOS(const LLSD& data)
+: LLModalDialog( data["message"].asString() ),
+ mMessage(data["message"].asString()),
mWebBrowserWindowId( 0 ),
- mLoadCompleteCount( 0 )
+ mLoadCompleteCount( 0 ),
+ mReplyPumpName(data["reply_pump"].asString())
{
}
@@ -139,16 +114,14 @@ BOOL LLFloaterTOS::postBuild()
childSetAction("Continue", onContinue, this);
childSetAction("Cancel", onCancel, this);
childSetCommitCallback("agree_chk", updateAgree, this);
-
- if ( mType != TOS_TOS )
+
+ if (hasChild("tos_text"))
{
// this displays the critical message
- LLTextEditor *editor = getChild<LLTextEditor>("tos_text");
- editor->setHandleEditKeysDirectly( TRUE );
- editor->setEnabled( FALSE );
- editor->setWordWrap(TRUE);
- editor->setFocus(TRUE);
- editor->setValue(LLSD(mMessage));
+ LLUICtrl *tos_text = getChild<LLUICtrl>("tos_text");
+ tos_text->setEnabled( FALSE );
+ tos_text->setFocus(TRUE);
+ tos_text->setValue(LLSD(mMessage));
return TRUE;
}
@@ -158,15 +131,13 @@ BOOL LLFloaterTOS::postBuild()
tos_agreement->setEnabled( false );
// hide the SL text widget if we're displaying TOS with using a browser widget.
- LLTextEditor *editor = getChild<LLTextEditor>("tos_text");
+ LLUICtrl *editor = getChild<LLUICtrl>("tos_text");
editor->setVisible( FALSE );
- LLWebBrowserCtrl* web_browser = getChild<LLWebBrowserCtrl>("tos_html");
+ LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("tos_html");
if ( web_browser )
{
- // start to observe it so we see navigate complete events
- web_browser->addObserver( this );
-
+ web_browser->addObserver(this);
gResponsePtr = LLIamHere::build( this );
LLHTTPClient::get( getString( "real_url" ), gResponsePtr );
}
@@ -177,17 +148,14 @@ BOOL LLFloaterTOS::postBuild()
void LLFloaterTOS::setSiteIsAlive( bool alive )
{
// only do this for TOS pages
- if ( mType == TOS_TOS )
+ if (hasChild("tos_html"))
{
- LLWebBrowserCtrl* web_browser = getChild<LLWebBrowserCtrl>("tos_html");
+ LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("tos_html");
// if the contents of the site was retrieved
if ( alive )
{
- if ( web_browser )
- {
- // navigate to the "real" page
- web_browser->navigateTo( getString( "real_url" ) );
- };
+ // navigate to the "real" page
+ web_browser->navigateTo( getString( "real_url" ) );
}
else
{
@@ -195,24 +163,16 @@ void LLFloaterTOS::setSiteIsAlive( bool alive )
// but if the page is unavailable, we need to do this now
LLCheckBoxCtrl* tos_agreement = getChild<LLCheckBoxCtrl>("agree_chk");
tos_agreement->setEnabled( true );
- };
- };
+ }
+ }
}
LLFloaterTOS::~LLFloaterTOS()
{
- // stop obsaerving events
- LLWebBrowserCtrl* web_browser = getChild<LLWebBrowserCtrl>("tos_html");
- if ( web_browser )
- {
- web_browser->remObserver( this );
- };
// tell the responder we're not here anymore
if ( gResponsePtr )
gResponsePtr->setParent( 0 );
-
- LLFloaterTOS::sInstance = NULL;
}
// virtual
@@ -235,26 +195,13 @@ void LLFloaterTOS::onContinue( void* userdata )
{
LLFloaterTOS* self = (LLFloaterTOS*) userdata;
llinfos << "User agrees with TOS." << llendl;
- if (self->mType == TOS_TOS)
- {
- gAcceptTOS = TRUE;
- }
- else
- {
- gAcceptCriticalMessage = TRUE;
- }
- // Testing TOS dialog
- #if ! LL_RELEASE_FOR_DOWNLOAD
- if ( LLStartUp::getStartupState() == STATE_LOGIN_WAIT )
+ if(self->mReplyPumpName != "")
{
- LLStartUp::setStartupState( STATE_LOGIN_SHOW );
+ LLEventPumps::instance().obtain(self->mReplyPumpName).post(LLSD(true));
}
- else
- #endif
- LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT ); // Go back and finish authentication
- self->close(); // destroys this object
+ self->closeFloater(); // destroys this object
}
// static
@@ -262,21 +209,30 @@ void LLFloaterTOS::onCancel( void* userdata )
{
LLFloaterTOS* self = (LLFloaterTOS*) userdata;
llinfos << "User disagrees with TOS." << llendl;
- LLNotifications::instance().add("MustAgreeToLogIn", LLSD(), LLSD(), login_alert_done);
- LLStartUp::setStartupState( STATE_LOGIN_SHOW );
+ LLNotificationsUtil::add("MustAgreeToLogIn", LLSD(), LLSD(), login_alert_done);
+
+ if(self->mReplyPumpName != "")
+ {
+ LLEventPumps::instance().obtain(self->mReplyPumpName).post(LLSD(false));
+ }
+
self->mLoadCompleteCount = 0; // reset counter for next time we come to TOS
- self->close(); // destroys this object
+ self->closeFloater(); // destroys this object
}
//virtual
-void LLFloaterTOS::onNavigateComplete( const EventType& eventIn )
+void LLFloaterTOS::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent event)
{
- // skip past the loading screen navigate complete
- if ( ++mLoadCompleteCount == 2 )
+ if(event == MEDIA_EVENT_NAVIGATE_COMPLETE)
{
- llinfos << "NAVIGATE COMPLETE" << llendl;
- // enable Agree to TOS radio button now that page has loaded
- LLCheckBoxCtrl * tos_agreement = getChild<LLCheckBoxCtrl>("agree_chk");
- tos_agreement->setEnabled( true );
- };
+ // skip past the loading screen navigate complete
+ if ( ++mLoadCompleteCount == 2 )
+ {
+ llinfos << "NAVIGATE COMPLETE" << llendl;
+ // enable Agree to TOS radio button now that page has loaded
+ LLCheckBoxCtrl * tos_agreement = getChild<LLCheckBoxCtrl>("agree_chk");
+ tos_agreement->setEnabled( true );
+ }
+ }
}
+
diff --git a/indra/newview/llfloatertos.h b/indra/newview/llfloatertos.h
index dbec3ff8b6..1d573e8170 100644
--- a/indra/newview/llfloatertos.h
+++ b/indra/newview/llfloatertos.h
@@ -35,7 +35,8 @@
#include "llmodaldialog.h"
#include "llassetstorage.h"
-#include "llwebbrowserctrl.h"
+#include "llmediactrl.h"
+#include <boost/function.hpp>
class LLButton;
class LLRadioGroup;
@@ -45,21 +46,12 @@ class LLUUID;
class LLFloaterTOS :
public LLModalDialog,
- public LLWebBrowserCtrlObserver
+ public LLViewerMediaObserver
{
public:
+ LLFloaterTOS(const LLSD& data);
virtual ~LLFloaterTOS();
- // Types of dialog.
- enum ETOSType
- {
- TOS_TOS = 0,
- TOS_CRITICAL_MESSAGE = 1
- };
-
- // Asset_id is overwritten with LLUUID::null when agree is clicked.
- static LLFloaterTOS* show(ETOSType type, const std::string & message);
-
BOOL postBuild();
virtual void draw();
@@ -70,19 +62,14 @@ public:
void setSiteIsAlive( bool alive );
- virtual void onNavigateComplete( const EventType& eventIn );
+ // inherited from LLViewerMediaObserver
+ /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
private:
- // Asset_id is overwritten with LLUUID::null when agree is clicked.
- LLFloaterTOS(ETOSType type, const std::string & message);
-
-private:
- ETOSType mType;
std::string mMessage;
int mWebBrowserWindowId;
int mLoadCompleteCount;
-
- static LLFloaterTOS* sInstance;
+ std::string mReplyPumpName;
};
#endif // LL_LLFLOATERTOS_H
diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp
new file mode 100644
index 0000000000..1e92ac0b8e
--- /dev/null
+++ b/indra/newview/llfloateruipreview.cpp
@@ -0,0 +1,1884 @@
+/**
+ * @file llfloateruipreview.cpp
+ * @brief Tool for previewing and editing floaters, plus localization tool integration
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Tool for previewing floaters and panels for localization and UI design purposes.
+// See: https://wiki.lindenlab.com/wiki/GUI_Preview_And_Localization_Tools
+// See: https://jira.lindenlab.com/browse/DEV-16869
+
+// *TODO: Translate error messgaes using notifications/alerts.xml
+
+#include "llviewerprecompiledheaders.h" // Precompiled headers
+
+#include "llfloateruipreview.h" // Own header
+
+// Internal utility
+#include "llrender.h"
+#include "llsdutil.h"
+#include "llxmltree.h"
+#include "llviewerwindow.h"
+
+// XUI
+#include "lluictrlfactory.h"
+#include "llcombobox.h"
+#include "llnotificationsutil.h"
+#include "llresizebar.h"
+#include "llscrolllistitem.h"
+#include "llscrolllistctrl.h"
+#include "llfilepicker.h"
+#include "lldraghandle.h"
+#include "lllayoutstack.h"
+#include "lltooltip.h"
+#include "llviewermenu.h"
+#include "llrngwriter.h"
+#include "llfloater.h" // superclass
+#include "llfloaterreg.h"
+#include "llscrollcontainer.h" // scroll container for overlapping elements
+#include "lllivefile.h" // live file poll/stat/reload
+
+// Boost (for linux/unix command-line execv)
+#include <boost/tokenizer.hpp>
+#include <boost/shared_ptr.hpp>
+
+// External utility
+#include <string>
+#include <list>
+#include <map>
+
+#if LL_DARWIN
+#include <CoreFoundation/CFURL.h>
+#endif
+
+// Static initialization
+static const S32 PRIMARY_FLOATER = 1;
+static const S32 SECONDARY_FLOATER = 2;
+
+class LLOverlapPanel;
+static LLDefaultChildRegistry::Register<LLOverlapPanel> register_overlap_panel("overlap_panel");
+
+static std::string get_xui_dir()
+{
+ std::string delim = gDirUtilp->getDirDelimiter();
+ return gDirUtilp->getSkinBaseDir() + delim + "default" + delim + "xui" + delim;
+}
+
+// Forward declarations to avoid header dependencies
+class LLEventTimer;
+class LLColor;
+class LLScrollListCtrl;
+class LLComboBox;
+class LLButton;
+class LLLineEditor;
+class LLXmlTreeNode;
+class LLFloaterUIPreview;
+class LLFadeEventTimer;
+
+class LLLocalizationResetForcer;
+class LLGUIPreviewLiveFile;
+class LLFadeEventTimer;
+class LLPreviewedFloater;
+
+// Implementation of custom overlapping element display panel
+class LLOverlapPanel : public LLPanel
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ Params() {}
+ };
+ LLOverlapPanel(Params p = Params()) : LLPanel(p),
+ mSpacing(10),
+ // mClickedElement(NULL),
+ mLastClickedElement(NULL)
+ {
+ mOriginalWidth = getRect().getWidth();
+ mOriginalHeight = getRect().getHeight();
+ }
+ virtual void draw();
+
+ typedef std::map<LLView*, std::list<LLView*> > OverlapMap;
+ OverlapMap mOverlapMap; // map, of XUI element to a list of XUI elements it overlaps
+
+ // LLView *mClickedElement;
+ LLView *mLastClickedElement;
+ int mOriginalWidth, mOriginalHeight, mSpacing;
+};
+
+
+class LLFloaterUIPreview : public LLFloater
+{
+public:
+ // Setup
+ LLFloaterUIPreview(const LLSD& key);
+ virtual ~LLFloaterUIPreview();
+
+ std::string getLocStr(S32 ID); // fetches the localization string based on what is selected in the drop-down menu
+ void displayFloater(BOOL click, S32 ID, bool save = false); // needs to be public so live file can call it when it finds an update
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onClose(bool app_quitting);
+
+ void refreshList(); // refresh list (empty it out and fill it up from scratch)
+ void addFloaterEntry(const std::string& path); // add a single file's entry to the list of floaters
+
+ static BOOL containerType(LLView* viewp); // check if the element is a container type and tree traverses need to look at its children
+
+public:
+ LLPreviewedFloater* mDisplayedFloater; // the floater which is currently being displayed
+ LLPreviewedFloater* mDisplayedFloater_2; // the floater which is currently being displayed
+ LLGUIPreviewLiveFile* mLiveFile; // live file for checking for updates to the currently-displayed XML file
+ LLOverlapPanel* mOverlapPanel; // custom overlapping elements panel
+ // BOOL mHighlightingDiffs; // bool for whether localization diffs are being highlighted or not
+ BOOL mHighlightingOverlaps; // bool for whether overlapping elements are being highlighted
+
+ // typedef std::map<std::string,std::pair<std::list<std::string>,std::list<std::string> > > DiffMap; // this version copies the lists etc., and thus is bad memory-wise
+ typedef std::list<std::string> StringList;
+ typedef boost::shared_ptr<StringList> StringListPtr;
+ typedef std::map<std::string, std::pair<StringListPtr,StringListPtr> > DiffMap;
+ DiffMap mDiffsMap; // map, of filename to pair of list of changed element paths and list of errors
+
+private:
+ // XUI elements for this floater
+ LLScrollListCtrl* mFileList; // scroll list control for file list
+ LLLineEditor* mEditorPathTextBox; // text field for path to editor executable
+ LLLineEditor* mEditorArgsTextBox; // text field for arguments to editor executable
+ LLLineEditor* mDiffPathTextBox; // text field for path to diff file
+ LLButton* mDisplayFloaterBtn; // button to display primary floater
+ LLButton* mDisplayFloaterBtn_2; // button to display secondary floater
+ LLButton* mEditFloaterBtn; // button to edit floater
+ LLButton* mExecutableBrowseButton; // button to browse for executable
+ LLButton* mCloseOtherButton; // button to close primary displayed floater
+ LLButton* mCloseOtherButton_2; // button to close secondary displayed floater
+ LLButton* mDiffBrowseButton; // button to browse for diff file
+ LLButton* mToggleHighlightButton; // button to toggle highlight of files/elements with diffs
+ LLButton* mToggleOverlapButton; // button to togle overlap panel/highlighting
+ LLComboBox* mLanguageSelection; // combo box for primary language selection
+ LLComboBox* mLanguageSelection_2; // combo box for secondary language selection
+ LLScrollContainer* mOverlapScrollView; // overlapping elements scroll container
+ S32 mLastDisplayedX, mLastDisplayedY; // stored position of last floater so the new one opens up in the same place
+ std::string mDelim; // the OS-specific delimiter character (/ or \) (*TODO: this shouldn't be needed, right?)
+
+ std::string mSavedEditorPath; // stored editor path so closing this floater doesn't reset it
+ std::string mSavedEditorArgs; // stored editor args so closing this floater doesn't reset it
+ std::string mSavedDiffPath; // stored diff file path so closing this floater doesn't reset it
+
+ // Internal functionality
+ static void popupAndPrintWarning(std::string& warning); // pop up a warning
+ std::string getLocalizedDirectory(); // build and return the path to the XUI directory for the currently-selected localization
+ void scanDiffFile(LLXmlTreeNode* file_node); // scan a given XML node for diff entries and highlight them in its associated file
+ void highlightChangedElements(); // look up the list of elements to highlight and highlight them in the current floater
+ void highlightChangedFiles(); // look up the list of changed files to highlight and highlight them in the scroll list
+ void findOverlapsInChildren(LLView* parent); // fill the map below with element overlap information
+ static BOOL overlapIgnorable(LLView* viewp); // check it the element can be ignored for overlap/localization purposes
+
+ // check if two elements overlap using their rectangles
+ // used instead of llrect functions because by adding a few pixels of leeway I can cut down drastically on the number of overlaps
+ BOOL elementOverlap(LLView* view1, LLView* view2);
+
+ // Button/drop-down action listeners (self explanatory)
+ void onClickDisplayFloater(S32 id);
+ void onClickSaveFloater(S32 id);
+ void onClickSaveAll(S32 id);
+ void onClickEditFloater();
+ void onClickBrowseForEditor();
+ void onClickBrowseForDiffs();
+ void onClickToggleDiffHighlighting();
+ void onClickToggleOverlapping();
+ void onClickCloseDisplayedFloater(S32 id);
+ void onLanguageComboSelect(LLUICtrl* ctrl);
+ void onClickExportSchema();
+ void onClickShowRectangles(const LLSD& data);
+};
+
+//----------------------------------------------------------------------------
+// Local class declarations
+// Reset object to ensure that when we change the current language setting for preview purposes,
+// it automatically is reset. Constructed on the stack at the start of the method; the reset
+// occurs as it falls out of scope at the end of the method. See llfloateruipreview.cpp for usage.
+class LLLocalizationResetForcer
+{
+public:
+ LLLocalizationResetForcer(LLFloaterUIPreview* floater, S32 ID);
+ virtual ~LLLocalizationResetForcer();
+
+private:
+ std::string mSavedLocalization; // the localization before we change it
+};
+
+// Implementation of live file
+// When a floater is being previewed, any saved changes to its corresponding
+// file cause the previewed floater to be reloaded
+class LLGUIPreviewLiveFile : public LLLiveFile
+{
+public:
+ LLGUIPreviewLiveFile(std::string path, std::string name, LLFloaterUIPreview* parent);
+ virtual ~LLGUIPreviewLiveFile();
+ LLFloaterUIPreview* mParent;
+ LLFadeEventTimer* mFadeTimer; // timer for fade-to-yellow-and-back effect to warn that file has been reloaded
+ BOOL mFirstFade; // setting this avoids showing the fade reload warning on first load
+ std::string mFileName;
+protected:
+ bool loadFile();
+};
+
+// Implementation of graphical fade in/out (on timer) for when XUI files are updated
+class LLFadeEventTimer : public LLEventTimer
+{
+public:
+ LLFadeEventTimer(F32 refresh, LLGUIPreviewLiveFile* parent);
+ BOOL tick();
+ LLGUIPreviewLiveFile* mParent;
+private:
+ BOOL mFadingOut; // fades in then out; this is toggled in between
+ LLColor4 mOriginalColor; // original color; color is reset to this after fade is coimplete
+};
+
+// Implementation of previewed floater
+// Used to override draw and mouse handler
+class LLPreviewedFloater : public LLFloater
+{
+public:
+ LLPreviewedFloater(LLFloaterUIPreview* floater)
+ : LLFloater(LLSD()),
+ mFloaterUIPreview(floater)
+ {
+ }
+ virtual void draw();
+ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ BOOL handleToolTip(S32 x, S32 y, MASK mask);
+ BOOL selectElement(LLView* parent, int x, int y, int depth); // select element to display its overlappers
+
+ LLFloaterUIPreview* mFloaterUIPreview;
+
+ // draw widget outlines
+ static bool sShowRectangles;
+};
+
+bool LLPreviewedFloater::sShowRectangles = false;
+
+//----------------------------------------------------------------------------
+
+// Localization reset forcer -- ensures that when localization is temporarily changed for previewed floater, it is reset
+// Changes are made here
+LLLocalizationResetForcer::LLLocalizationResetForcer(LLFloaterUIPreview* floater, S32 ID)
+{
+ mSavedLocalization = LLUI::sSettingGroups["config"]->getString("Language"); // save current localization setting
+ LLUI::sSettingGroups["config"]->setString("Language", floater->getLocStr(ID));// hack language to be the one we want to preview floaters in
+ LLUI::setupPaths(); // forcibly reset XUI paths with this new language
+}
+
+// Actually reset in destructor
+// Changes are reversed here
+LLLocalizationResetForcer::~LLLocalizationResetForcer()
+{
+ LLUI::sSettingGroups["config"]->setString("Language", mSavedLocalization); // reset language to what it was before we changed it
+ LLUI::setupPaths(); // forcibly reset XUI paths with this new language
+}
+
+// Live file constructor
+// Needs full path for LLLiveFile but needs just file name for this code, hence the reduntant arguments; easier than separating later
+LLGUIPreviewLiveFile::LLGUIPreviewLiveFile(std::string path, std::string name, LLFloaterUIPreview* parent)
+ : mFileName(name),
+ mParent(parent),
+ mFirstFade(TRUE),
+ mFadeTimer(NULL),
+ LLLiveFile(path, 1.0)
+{}
+
+LLGUIPreviewLiveFile::~LLGUIPreviewLiveFile()
+{
+ mParent->mLiveFile = NULL;
+ if(mFadeTimer)
+ {
+ mFadeTimer->mParent = NULL;
+ // deletes itself; see lltimer.cpp
+ }
+}
+
+// Live file load
+bool LLGUIPreviewLiveFile::loadFile()
+{
+ mParent->displayFloater(FALSE,1); // redisplay the floater
+ if(mFirstFade) // only fade if it wasn't just clicked on; can't use "clicked" BOOL below because of an oddity with setting LLLiveFile initial state
+ {
+ mFirstFade = FALSE;
+ }
+ else
+ {
+ if(mFadeTimer)
+ {
+ mFadeTimer->mParent = NULL;
+ }
+ mFadeTimer = new LLFadeEventTimer(0.05f,this);
+ }
+ return true;
+}
+
+// Initialize fade event timer
+LLFadeEventTimer::LLFadeEventTimer(F32 refresh, LLGUIPreviewLiveFile* parent)
+ : mParent(parent),
+ mFadingOut(TRUE),
+ LLEventTimer(refresh)
+{
+ mOriginalColor = mParent->mParent->mDisplayedFloater->getBackgroundColor();
+}
+
+// Single tick of fade event timer: increment the color
+BOOL LLFadeEventTimer::tick()
+{
+ float diff = 0.04f;
+ if(TRUE == mFadingOut) // set fade for in/out color direction
+ {
+ diff = -diff;
+ }
+
+ if(NULL == mParent) // no more need to tick, so suicide
+ {
+ delete this;
+ return FALSE;
+ }
+
+ // Set up colors
+ LLColor4 bg_color = mParent->mParent->mDisplayedFloater->getBackgroundColor();
+ LLSD colors = bg_color.getValue();
+ LLSD colors_old = colors;
+
+ // Tick colors
+ colors[0] = colors[0].asReal() - diff; if(colors[0].asReal() < mOriginalColor.getValue()[0].asReal()) { colors[0] = colors_old[0]; }
+ colors[1] = colors[1].asReal() - diff; if(colors[1].asReal() < mOriginalColor.getValue()[1].asReal()) { colors[1] = colors_old[1]; }
+ colors[2] = colors[2].asReal() + diff; if(colors[2].asReal() > mOriginalColor.getValue()[2].asReal()) { colors[2] = colors_old[2]; }
+
+ // Clamp and set colors
+ bg_color.setValue(colors);
+ bg_color.clamp(); // make sure we didn't exceed [0,1]
+ mParent->mParent->mDisplayedFloater->setBackgroundColor(bg_color);
+
+ if(bg_color[2] <= 0.0f) // end of fade out, start fading in
+ {
+ mFadingOut = FALSE;
+ }
+
+ return FALSE;
+}
+
+// Constructor
+LLFloaterUIPreview::LLFloaterUIPreview(const LLSD& key)
+ : LLFloater(key),
+ mDisplayedFloater(NULL),
+ mDisplayedFloater_2(NULL),
+ mLiveFile(NULL),
+ // sHighlightingDiffs(FALSE),
+ mHighlightingOverlaps(FALSE),
+ mLastDisplayedX(0),
+ mLastDisplayedY(0)
+{
+ // called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_ui_preview.xml");
+}
+
+// Destructor
+LLFloaterUIPreview::~LLFloaterUIPreview()
+{
+ // spawned floaters are deleted automatically, so we don't need to delete them here
+
+ // save contents of textfields so it can be restored later if the floater is created again this session
+ mSavedEditorPath = mEditorPathTextBox->getText();
+ mSavedEditorArgs = mEditorArgsTextBox->getText();
+ mSavedDiffPath = mDiffPathTextBox->getText();
+
+ // delete live file if it exists
+ if(mLiveFile)
+ {
+ delete mLiveFile;
+ mLiveFile = NULL;
+ }
+}
+
+// Perform post-build setup (defined in superclass)
+BOOL LLFloaterUIPreview::postBuild()
+{
+ LLPanel* main_panel_tmp = getChild<LLPanel>("main_panel"); // get a pointer to the main panel in order to...
+ mFileList = main_panel_tmp->getChild<LLScrollListCtrl>("name_list"); // save pointer to file list
+ // Double-click opens the floater, for convenience
+ mFileList->setDoubleClickCallback(boost::bind(&LLFloaterUIPreview::onClickDisplayFloater, this, PRIMARY_FLOATER));
+
+ // get pointers to buttons and link to callbacks
+ mLanguageSelection = main_panel_tmp->getChild<LLComboBox>("language_select_combo");
+ mLanguageSelection->setCommitCallback(boost::bind(&LLFloaterUIPreview::onLanguageComboSelect, this, mLanguageSelection));
+ mLanguageSelection_2 = main_panel_tmp->getChild<LLComboBox>("language_select_combo_2");
+ mLanguageSelection_2->setCommitCallback(boost::bind(&LLFloaterUIPreview::onLanguageComboSelect, this, mLanguageSelection));
+ LLPanel* editor_panel_tmp = main_panel_tmp->getChild<LLPanel>("editor_panel");
+ mDisplayFloaterBtn = main_panel_tmp->getChild<LLButton>("display_floater");
+ mDisplayFloaterBtn->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickDisplayFloater, this, PRIMARY_FLOATER));
+ mDisplayFloaterBtn_2 = main_panel_tmp->getChild<LLButton>("display_floater_2");
+ mDisplayFloaterBtn_2->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickDisplayFloater, this, SECONDARY_FLOATER));
+ mToggleOverlapButton = main_panel_tmp->getChild<LLButton>("toggle_overlap_panel");
+ mToggleOverlapButton->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickToggleOverlapping, this));
+ mCloseOtherButton = main_panel_tmp->getChild<LLButton>("close_displayed_floater");
+ mCloseOtherButton->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickCloseDisplayedFloater, this, PRIMARY_FLOATER));
+ mCloseOtherButton_2 = main_panel_tmp->getChild<LLButton>("close_displayed_floater_2");
+ mCloseOtherButton_2->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickCloseDisplayedFloater, this, SECONDARY_FLOATER));
+ mEditFloaterBtn = main_panel_tmp->getChild<LLButton>("edit_floater");
+ mEditFloaterBtn->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickEditFloater, this));
+ mExecutableBrowseButton = editor_panel_tmp->getChild<LLButton>("browse_for_executable");
+ LLPanel* vlt_panel_tmp = main_panel_tmp->getChild<LLPanel>("vlt_panel");
+ mExecutableBrowseButton->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickBrowseForEditor, this));
+ mDiffBrowseButton = vlt_panel_tmp->getChild<LLButton>("browse_for_vlt_diffs");
+ mDiffBrowseButton->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickBrowseForDiffs, this));
+ mToggleHighlightButton = vlt_panel_tmp->getChild<LLButton>("toggle_vlt_diff_highlight");
+ mToggleHighlightButton->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickToggleDiffHighlighting, this));
+ main_panel_tmp->getChild<LLButton>("save_floater")->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickSaveFloater, this, PRIMARY_FLOATER));
+ main_panel_tmp->getChild<LLButton>("save_all_floaters")->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickSaveAll, this, PRIMARY_FLOATER));
+
+ getChild<LLButton>("export_schema")->setClickedCallback(boost::bind(&LLFloaterUIPreview::onClickExportSchema, this));
+ getChild<LLUICtrl>("show_rectangles")->setCommitCallback(
+ boost::bind(&LLFloaterUIPreview::onClickShowRectangles, this, _2));
+
+ // get pointers to text fields
+ mEditorPathTextBox = editor_panel_tmp->getChild<LLLineEditor>("executable_path_field");
+ mEditorArgsTextBox = editor_panel_tmp->getChild<LLLineEditor>("executable_args_field");
+ mDiffPathTextBox = vlt_panel_tmp->getChild<LLLineEditor>("vlt_diff_path_field");
+
+ // *HACK: restored saved editor path and args to textfields
+ mEditorPathTextBox->setText(mSavedEditorPath);
+ mEditorArgsTextBox->setText(mSavedEditorArgs);
+ mDiffPathTextBox->setText(mSavedDiffPath);
+
+ // Set up overlap panel
+ mOverlapPanel = getChild<LLOverlapPanel>("overlap_panel");
+
+ childSetVisible("overlap_scroll", mHighlightingOverlaps);
+
+ mDelim = gDirUtilp->getDirDelimiter(); // initialize delimiter to dir sep slash
+
+ // refresh list of available languages (EN will still be default)
+ BOOL found = TRUE;
+ BOOL found_en_us = FALSE;
+ std::string language_directory;
+ std::string xui_dir = get_xui_dir(); // directory containing localizations -- don't forget trailing delim
+ mLanguageSelection->removeall(); // clear out anything temporarily in list from XML
+ while(found) // for every directory
+ {
+ if((found = gDirUtilp->getNextFileInDir(xui_dir, "*", language_directory, FALSE))) // get next directory
+ {
+ std::string full_path = xui_dir + language_directory;
+ if(LLFile::isfile(full_path.c_str())) // if it's not a directory, skip it
+ {
+ continue;
+ }
+
+ if(strncmp("template",language_directory.c_str(),8) && -1 == language_directory.find(".")) // if it's not the template directory or a hidden directory
+ {
+ if(!strncmp("en",language_directory.c_str(),5)) // remember if we've seen en, so we can make it default
+ {
+ found_en_us = TRUE;
+ }
+ else
+ {
+ mLanguageSelection->add(std::string(language_directory)); // add it to the language selection dropdown menu
+ mLanguageSelection_2->add(std::string(language_directory));
+ }
+ }
+ }
+ }
+ if(found_en_us)
+ {
+ mLanguageSelection->add(std::string("en"),ADD_TOP); // make en first item if we found it
+ mLanguageSelection_2->add(std::string("en"),ADD_TOP);
+ }
+ else
+ {
+ std::string warning = std::string("No EN localization found; check your XUI directories!");
+ popupAndPrintWarning(warning);
+ }
+ mLanguageSelection->selectFirstItem(); // select the first item
+ mLanguageSelection_2->selectFirstItem();
+
+ refreshList(); // refresh the list of available floaters
+
+ return TRUE;
+}
+
+// Callback for language combo box selection: refresh current floater when you change languages
+void LLFloaterUIPreview::onLanguageComboSelect(LLUICtrl* ctrl)
+{
+ LLComboBox* caller = dynamic_cast<LLComboBox*>(ctrl);
+ if (!caller)
+ return;
+ if(caller->getName() == std::string("language_select_combo"))
+ {
+ if(mDisplayedFloater)
+ {
+ onClickCloseDisplayedFloater(PRIMARY_FLOATER);
+ displayFloater(TRUE,1);
+ }
+ }
+ else
+ {
+ if(mDisplayedFloater_2)
+ {
+ onClickCloseDisplayedFloater(PRIMARY_FLOATER);
+ displayFloater(TRUE,2); // *TODO: make take an arg
+ }
+ }
+
+}
+
+void LLFloaterUIPreview::onClickExportSchema()
+{
+ //NOTE: schema generation not complete
+ //gViewerWindow->setCursor(UI_CURSOR_WAIT);
+ //std::string template_path = gDirUtilp->getExpandedFilename(LL_PATH_DEFAULT_SKIN, "xui", "schema");
+
+ //typedef LLWidgetTypeRegistry::Registrar::registry_map_t::const_iterator registry_it;
+ //registry_it end_it = LLWidgetTypeRegistry::defaultRegistrar().endItems();
+ //for(registry_it it = LLWidgetTypeRegistry::defaultRegistrar().beginItems();
+ // it != end_it;
+ // ++it)
+ //{
+ // std::string widget_name = it->first;
+ // const LLInitParam::BaseBlock& block =
+ // (*LLDefaultParamBlockRegistry::instance().getValue(*LLWidgetTypeRegistry::instance().getValue(widget_name)))();
+ // LLXMLNodePtr root_nodep = new LLXMLNode();
+ // LLRNGWriter().writeRNG(widget_name, root_nodep, block, "http://www.lindenlab.com/xui");
+
+ // std::string file_name(template_path + gDirUtilp->getDirDelimiter() + widget_name + ".rng");
+
+ // LLFILE* rng_file = LLFile::fopen(file_name.c_str(), "w");
+ // {
+ // LLXMLNode::writeHeaderToFile(rng_file);
+ // const bool use_type_decorations = false;
+ // root_nodep->writeToFile(rng_file, std::string(), use_type_decorations);
+ // }
+ // fclose(rng_file);
+ //}
+ //gViewerWindow->setCursor(UI_CURSOR_ARROW);
+}
+
+void LLFloaterUIPreview::onClickShowRectangles(const LLSD& data)
+{
+ LLPreviewedFloater::sShowRectangles = data.asBoolean();
+}
+
+// Close click handler -- delete my displayed floater if it exists
+void LLFloaterUIPreview::onClose(bool app_quitting)
+{
+ if(!app_quitting && mDisplayedFloater)
+ {
+ onClickCloseDisplayedFloater(PRIMARY_FLOATER);
+ onClickCloseDisplayedFloater(SECONDARY_FLOATER);
+ delete mDisplayedFloater;
+ mDisplayedFloater = NULL;
+ delete mDisplayedFloater_2;
+ mDisplayedFloater_2 = NULL;
+ }
+}
+
+// Error handling (to avoid code repetition)
+// *TODO: this is currently unlocalized. Add to alerts/notifications.xml, someday, maybe.
+void LLFloaterUIPreview::popupAndPrintWarning(std::string& warning)
+{
+ llwarns << warning << llendl;
+ LLSD args;
+ args["MESSAGE"] = warning;
+ LLNotificationsUtil::add("GenericAlert", args);
+}
+
+// Get localization string from drop-down menu
+std::string LLFloaterUIPreview::getLocStr(S32 ID)
+{
+ if(ID == 1)
+ {
+ return mLanguageSelection->getSelectedItemLabel(0);
+ }
+ else
+ {
+ return mLanguageSelection_2->getSelectedItemLabel(0);
+ }
+}
+
+// Get localized directory (build path from data directory to XUI files, substituting localization string in for language)
+std::string LLFloaterUIPreview::getLocalizedDirectory()
+{
+ return get_xui_dir() + (getLocStr(1)) + mDelim; // e.g. "C:/Code/guipreview/indra/newview/skins/xui/en/";
+}
+
+// Refresh the list of floaters by doing a directory traverse for XML XUI floater files
+// Could be used to grab any specific language's list of compatible floaters, but currently it's just used to get all of them
+void LLFloaterUIPreview::refreshList()
+{
+ // Note: the mask doesn't seem to accept regular expressions, so there need to be two directory searches here
+ mFileList->clearRows(); // empty list
+ std::string name;
+ BOOL found = TRUE;
+ while(found) // for every floater file that matches the pattern
+ {
+ if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "floater_*.xml", name, FALSE))) // get next file matching pattern
+ {
+ addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path)
+ }
+ }
+ found = TRUE;
+ while(found) // for every inspector file that matches the pattern
+ {
+ if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "inspect_*.xml", name, FALSE))) // get next file matching pattern
+ {
+ addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path)
+ }
+ }
+ found = TRUE;
+ while(found) // for every menu file that matches the pattern
+ {
+ if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "menu_*.xml", name, FALSE))) // get next file matching pattern
+ {
+ addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path)
+ }
+ }
+ found = TRUE;
+ while(found) // for every panel file that matches the pattern
+ {
+ if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "panel_*.xml", name, FALSE))) // get next file matching pattern
+ {
+ addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path)
+ }
+ }
+
+ found = TRUE;
+ while(found) // for every sidepanel file that matches the pattern
+ {
+ if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "sidepanel_*.xml", name, FALSE))) // get next file matching pattern
+ {
+ addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path)
+ }
+ }
+
+ if(!mFileList->isEmpty()) // if there were any matching files, just select the first one (so we don't have to worry about disabling buttons when no entry is selected)
+ {
+ mFileList->selectFirstItem();
+ }
+}
+
+// Add a single entry to the list of available floaters
+// Note: no deduplification (shouldn't be necessary)
+void LLFloaterUIPreview::addFloaterEntry(const std::string& path)
+{
+ LLUUID* entry_id = new LLUUID(); // create a new UUID
+ entry_id->generate(path);
+ const LLUUID& entry_id_ref = *entry_id; // get a reference to the UUID for the LLSD block
+
+ // fill LLSD column entry: initialize row/col structure
+ LLSD row;
+ row["id"] = entry_id_ref;
+ LLSD& columns = row["columns"];
+
+ // Get name of floater:
+ LLXmlTree xml_tree;
+ std::string full_path = getLocalizedDirectory() + path; // get full path
+ BOOL success = xml_tree.parseFile(full_path.c_str(), TRUE); // parse xml
+ std::string entry_name;
+ std::string entry_title;
+ if(success)
+ {
+ // get root (or error handle)
+ LLXmlTreeNode* root_floater = xml_tree.getRoot();
+ if (!root_floater)
+ {
+ std::string warning = std::string("No root node found in XUI file: ") + path;
+ popupAndPrintWarning(warning);
+ return;
+ }
+
+ // get name
+ root_floater->getAttributeString("name",entry_name);
+ if(std::string("") == entry_name)
+ {
+ entry_name = "Error: unable to load " + std::string(path); // set to error state if load fails
+ }
+
+ // get title
+ root_floater->getAttributeString("title",entry_title); // some don't have a title, and some have title = "(unknown)", so just leave it blank if it fails
+ }
+ else
+ {
+ std::string warning = std::string("Unable to parse XUI file: ") + path; // error handling
+ popupAndPrintWarning(warning);
+ if(mLiveFile)
+ {
+ delete mLiveFile;
+ mLiveFile = NULL;
+ }
+ return;
+ }
+
+ // Fill floater title column
+ columns[0]["column"] = "title_column";
+ columns[0]["type"] = "text";
+ columns[0]["value"] = entry_title;
+
+ // Fill floater path column
+ columns[1]["column"] = "file_column";
+ columns[1]["type"] = "text";
+ columns[1]["value"] = std::string(path);
+
+ // Fill floater name column
+ columns[2]["column"] = "top_level_node_column";
+ columns[2]["type"] = "text";
+ columns[2]["value"] = entry_name;
+
+ mFileList->addElement(row); // actually add to list
+}
+
+// Respond to button click to display/refresh currently-selected floater
+void LLFloaterUIPreview::onClickDisplayFloater(S32 caller_id)
+{
+ displayFloater(TRUE, caller_id);
+}
+
+// Saves the current floater/panel
+void LLFloaterUIPreview::onClickSaveFloater(S32 caller_id)
+{
+ displayFloater(TRUE, caller_id, true);
+}
+
+// Saves all floater/panels
+void LLFloaterUIPreview::onClickSaveAll(S32 caller_id)
+{
+ int listSize = mFileList->getItemCount();
+
+ for (int index = 0; index < listSize; index++)
+ {
+ mFileList->selectNthItem(index);
+ displayFloater(TRUE, caller_id, true);
+ }
+}
+
+// Given path to floater or panel XML file "filename.xml",
+// returns "filename_new.xml"
+static std::string append_new_to_xml_filename(const std::string& path)
+{
+ std::string full_filename = gDirUtilp->findSkinnedFilename(LLUI::getLocalizedSkinPath(), path);
+ std::string::size_type extension_pos = full_filename.rfind(".xml");
+ full_filename.resize(extension_pos);
+ full_filename += "_new.xml";
+ return full_filename;
+}
+
+// Actually display the floater
+// Only set up a new live file if this came from a click (at which point there should be no existing live file), rather than from the live file's update itself;
+// otherwise, we get an infinite loop as the live file keeps recreating itself. That means this function is generally called twice.
+void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save)
+{
+ // Convince UI that we're in a different language (the one selected on the drop-down menu)
+ LLLocalizationResetForcer reset_forcer(this, ID); // save old language in reset forcer object (to be reset upon destruction when it falls out of scope)
+
+ LLPreviewedFloater** floaterp = (ID == 1 ? &(mDisplayedFloater) : &(mDisplayedFloater_2));
+ if(ID == 1)
+ {
+ BOOL floater_already_open = mDisplayedFloater != NULL;
+ if(floater_already_open) // if we are already displaying a floater
+ {
+ mLastDisplayedX = mDisplayedFloater->calcScreenRect().mLeft; // save floater's last known position to put the new one there
+ mLastDisplayedY = mDisplayedFloater->calcScreenRect().mBottom;
+ delete mDisplayedFloater; // delete it (this closes it too)
+ mDisplayedFloater = NULL; // and reset the pointer
+ }
+ }
+ else
+ {
+ if(mDisplayedFloater_2 != NULL)
+ {
+ delete mDisplayedFloater_2;
+ mDisplayedFloater_2 = NULL;
+ }
+ }
+
+ std::string path = mFileList->getSelectedItemLabel(1); // get the path of the currently-selected floater
+ if(std::string("") == path) // if no item is selected
+ {
+ return; // ignore click (this can only happen with empty list; otherwise an item is always selected)
+ }
+
+ *floaterp = new LLPreviewedFloater(this);
+
+ if(!strncmp(path.c_str(),"floater_",8)
+ || !strncmp(path.c_str(), "inspect_", 8)) // if it's a floater
+ {
+ if (save)
+ {
+ LLXMLNodePtr floater_write = new LLXMLNode();
+ LLUICtrlFactory::getInstance()->buildFloater(*floaterp, path, floater_write); // just build it
+
+ if (!floater_write->isNull())
+ {
+ std::string full_filename = append_new_to_xml_filename(path);
+ LLFILE* floater_temp = LLFile::fopen(full_filename.c_str(), "w");
+ LLXMLNode::writeHeaderToFile(floater_temp);
+ const bool use_type_decorations = false;
+ floater_write->writeToFile(floater_temp, std::string(), use_type_decorations);
+ fclose(floater_temp);
+ }
+ }
+ else
+ {
+ LLUICtrlFactory::getInstance()->buildFloater(*floaterp, path, NULL); // just build it
+ (*floaterp)->openFloater((*floaterp)->getKey());
+ (*floaterp)->setCanResize((*floaterp)->isResizable());
+ }
+
+ }
+ else if (!strncmp(path.c_str(),"menu_",5)) // if it's a menu
+ {
+ if (save)
+ {
+ LLXMLNodePtr menu_write = new LLXMLNode();
+ LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(path, gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance(), menu_write);
+
+ if (!menu_write->isNull())
+ {
+ std::string full_filename = append_new_to_xml_filename(path);
+ LLFILE* menu_temp = LLFile::fopen(full_filename.c_str(), "w");
+ LLXMLNode::writeHeaderToFile(menu_temp);
+ const bool use_type_decorations = false;
+ menu_write->writeToFile(menu_temp, std::string(), use_type_decorations);
+ fclose(menu_temp);
+ }
+
+ delete menu;
+ }
+ }
+ else // if it is a panel...
+ {
+ const LLFloater::Params& floater_params = LLFloater::getDefaultParams();
+ S32 floater_header_size = floater_params.header_height;
+
+ LLPanel::Params panel_params;
+ LLPanel* panel = LLUICtrlFactory::create<LLPanel>(panel_params); // create a new panel
+
+ if (save)
+ {
+ LLXMLNodePtr panel_write = new LLXMLNode();
+ LLUICtrlFactory::getInstance()->buildPanel(panel, path, panel_write); // build it
+
+ if (!panel_write->isNull())
+ {
+ std::string full_filename = append_new_to_xml_filename(path);
+ LLFILE* panel_temp = LLFile::fopen(full_filename.c_str(), "w");
+ LLXMLNode::writeHeaderToFile(panel_temp);
+ const bool use_type_decorations = false;
+ panel_write->writeToFile(panel_temp, std::string(), use_type_decorations);
+ fclose(panel_temp);
+ }
+ }
+ else
+ {
+ LLUICtrlFactory::getInstance()->buildPanel(panel, path); // build it
+ LLRect new_size = panel->getRect(); // get its rectangle
+ panel->setOrigin(0,0); // reset its origin point so it's not offset by -left or other XUI attributes
+ (*floaterp)->setTitle(path); // use the file name as its title, since panels have no guaranteed meaningful name attribute
+ panel->setUseBoundingRect(TRUE); // enable the use of its outer bounding rect (normally disabled because it's O(n) on the number of sub-elements)
+ panel->updateBoundingRect(); // update bounding rect
+ LLRect bounding_rect = panel->getBoundingRect(); // get the bounding rect
+ LLRect new_rect = panel->getRect(); // get the panel's rect
+ new_rect.unionWith(bounding_rect); // union them to make sure we get the biggest one possible
+ (*floaterp)->reshape(new_rect.getWidth(), new_rect.getHeight() + floater_header_size); // reshape floater to match the union rect's dimensions
+ panel->reshape(new_rect.getWidth(), new_rect.getHeight()); // reshape panel to match the union rect's dimensions as well (both are needed)
+ (*floaterp)->addChild(panel); // add panel as child
+ (*floaterp)->openFloater(); // open floater (needed?)
+ }
+ }
+
+ if(ID == 1)
+ {
+ (*floaterp)->setOrigin(mLastDisplayedX, mLastDisplayedY);
+ }
+
+ // *HACK: Remove ability to close it; if you close it, its destructor gets called, but we don't know it's null and try to delete it again,
+ // resulting in a double free
+ (*floaterp)->setCanClose(FALSE);
+
+ if(ID == 1)
+ {
+ mCloseOtherButton->setEnabled(TRUE); // enable my floater's close button
+ }
+ else
+ {
+ mCloseOtherButton_2->setEnabled(TRUE);
+ }
+
+ // Add localization to title so user knows whether it's localized or defaulted to en
+ std::string full_path = getLocalizedDirectory() + path;
+ std::string floater_lang = "EN";
+ llstat dummy;
+ if(!LLFile::stat(full_path.c_str(), &dummy)) // if the file does not exist
+ {
+ floater_lang = getLocStr(ID);
+ }
+ std::string new_title = (*floaterp)->getTitle() + std::string(" [") + floater_lang +
+ (ID == 1 ? " - Primary" : " - Secondary") + std::string("]");
+ (*floaterp)->setTitle(new_title);
+
+ (*floaterp)->center();
+ addDependentFloater(*floaterp);
+
+ if(click && ID == 1 && !save)
+ {
+ // set up live file to track it
+ if(mLiveFile)
+ {
+ delete mLiveFile;
+ mLiveFile = NULL;
+ }
+ mLiveFile = new LLGUIPreviewLiveFile(std::string(full_path.c_str()),std::string(path.c_str()),this);
+ mLiveFile->checkAndReload();
+ mLiveFile->addToEventTimer();
+ }
+
+ if(ID == 1)
+ {
+ mToggleOverlapButton->setEnabled(TRUE);
+ }
+
+ if(LLView::sHighlightingDiffs && click && ID == 1)
+ {
+ highlightChangedElements();
+ }
+
+ if(ID == 1)
+ {
+ mOverlapPanel->mOverlapMap.clear();
+ LLView::sPreviewClickedElement = NULL; // stop overlapping elements from drawing
+ mOverlapPanel->mLastClickedElement = NULL;
+ findOverlapsInChildren((LLView*)mDisplayedFloater);
+
+ // highlight and enable them
+ if(mHighlightingOverlaps)
+ {
+ for(LLOverlapPanel::OverlapMap::iterator iter = mOverlapPanel->mOverlapMap.begin(); iter != mOverlapPanel->mOverlapMap.end(); ++iter)
+ {
+ LLView* viewp = iter->first;
+ LLView::sPreviewHighlightedElements.insert(viewp);
+ }
+ }
+ else if(LLView::sHighlightingDiffs)
+ {
+ highlightChangedElements();
+ }
+ }
+
+ // NOTE: language is reset here automatically when the reset forcer object falls out of scope (see header for details)
+}
+
+// Respond to button click to edit currently-selected floater
+void LLFloaterUIPreview::onClickEditFloater()
+{
+ std::string file_name = mFileList->getSelectedItemLabel(1); // get the file name of the currently-selected floater
+ if(std::string("") == file_name) // if no item is selected
+ {
+ return; // ignore click
+ }
+ std::string path = getLocalizedDirectory() + file_name;
+
+ // stat file to see if it exists (some localized versions may not have it there are no diffs, and then we try to open an nonexistent file)
+ llstat dummy;
+ if(LLFile::stat(path.c_str(), &dummy)) // if the file does not exist
+ {
+ std::string warning = "No file for this floater exists in the selected localization. Opening the EN version instead.";
+ popupAndPrintWarning(warning);
+
+ path = get_xui_dir() + mDelim + "en" + mDelim + file_name; // open the en version instead, by default
+ }
+
+ // get executable path
+ const char* exe_path_char;
+ std::string path_in_textfield = mEditorPathTextBox->getText();
+ if(std::string("") != path_in_textfield) // if the text field is not emtpy, use its path
+ {
+ exe_path_char = path_in_textfield.c_str();
+ }
+ else if (!LLUI::sSettingGroups["config"]->getString("XUIEditor").empty())
+ {
+ exe_path_char = LLUI::sSettingGroups["config"]->getString("XUIEditor").c_str();
+ }
+ else // otherwise use the path specified by the environment variable
+ {
+ exe_path_char = getenv("LL_XUI_EDITOR");
+ }
+
+ // error check executable path
+ if(NULL == exe_path_char)
+ {
+ std::string warning = "Select an editor by setting the environment variable LL_XUI_EDITOR or specifying its path in the \"Editor Path\" field.";
+ popupAndPrintWarning(warning);
+ return;
+ }
+ std::string exe_path = exe_path_char; // do this after error check, otherwise internal strlen call fails on bad char*
+
+ // remove any quotes; they're added back in later where necessary
+ int found_at;
+ while((found_at = exe_path.find("\"")) != -1 || (found_at = exe_path.find("'")) != -1)
+ {
+ exe_path.erase(found_at,1);
+ }
+
+ llstat s;
+ if(!LLFile::stat(exe_path.c_str(), &s)) // If the executable exists
+ {
+ // build paths and arguments
+ std::string args;
+ std::string custom_args = mEditorArgsTextBox->getText();
+ int position_of_file = custom_args.find(std::string("%FILE%"), 0); // prepare to replace %FILE% with actual file path
+ std::string first_part_of_args = "";
+ std::string second_part_of_args = "";
+ if(-1 == position_of_file) // default: Executable.exe File.xml
+ {
+ args = std::string("\"") + path + std::string("\""); // execute the command Program.exe "File.xml"
+ }
+ else // use advanced command-line arguments, e.g. "Program.exe -safe File.xml" -windowed for "-safe %FILE% -windowed"
+ {
+ first_part_of_args = custom_args.substr(0,position_of_file); // get part of args before file name
+ second_part_of_args = custom_args.substr(position_of_file+6,custom_args.length()); // get part of args after file name
+ custom_args = first_part_of_args + std::string("\"") + path + std::string("\"") + second_part_of_args; // replace %FILE% with "<file path>" and put back together
+ args = custom_args; // and save in the variable that is actually used
+ }
+
+ // find directory in which executable resides by taking everything after last slash
+ int last_slash_position = exe_path.find_last_of(mDelim);
+ if(-1 == last_slash_position)
+ {
+ std::string warning = std::string("Unable to find a valid path to the specified executable for XUI XML editing: ") + exe_path;
+ popupAndPrintWarning(warning);
+ return;
+ }
+ std::string exe_dir = exe_path.substr(0,last_slash_position); // strip executable off, e.g. get "C:\Program Files\TextPad 5" (with or without trailing slash)
+
+#if LL_WINDOWS
+ PROCESS_INFORMATION pinfo;
+ STARTUPINFOA sinfo;
+ memset(&sinfo, 0, sizeof(sinfo));
+ memset(&pinfo, 0, sizeof(pinfo));
+
+ std::string exe_name = exe_path.substr(last_slash_position+1);
+ args = exe_name + std::string(" ") + args; // and prepend the executable name, so we get 'Program.exe "Arg1"'
+
+ char *args2 = new char[args.size() + 1]; // Windows requires that the second parameter to CreateProcessA be a writable (non-const) string...
+ strcpy(args2, args.c_str());
+
+ if(!CreateProcessA(exe_path.c_str(), args2, NULL, NULL, FALSE, 0, NULL, exe_dir.c_str(), &sinfo, &pinfo))
+ {
+ // DWORD dwErr = GetLastError();
+ std::string warning = "Creating editor process failed!";
+ popupAndPrintWarning(warning);
+ }
+ else
+ {
+ // foo = pinfo.dwProcessId; // get your pid here if you want to use it later on
+ // sGatewayHandle = pinfo.hProcess;
+ CloseHandle(pinfo.hThread); // stops leaks - nothing else
+ }
+
+ delete[] args2;
+#else // if !LL_WINDOWS
+ // This code was copied from the code to run SLVoice, with some modification; should work in UNIX (Mac/Darwin or Linux)
+ {
+ std::vector<std::string> arglist;
+ arglist.push_back(exe_path.c_str());
+
+ // Split the argument string into separate strings for each argument
+ typedef boost::tokenizer< boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep("","\" ", boost::drop_empty_tokens);
+
+ tokenizer tokens(args, sep);
+ tokenizer::iterator token_iter;
+ BOOL inside_quotes = FALSE;
+ BOOL last_was_space = FALSE;
+ for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
+ {
+ if(!strncmp("\"",(*token_iter).c_str(),2))
+ {
+ inside_quotes = !inside_quotes;
+ }
+ else if(!strncmp(" ",(*token_iter).c_str(),2))
+ {
+ if(inside_quotes)
+ {
+ arglist.back().append(std::string(" "));
+ last_was_space = TRUE;
+ }
+ }
+ else
+ {
+ std::string to_push = *token_iter;
+ if(last_was_space)
+ {
+ arglist.back().append(to_push);
+ last_was_space = FALSE;
+ }
+ else
+ {
+ arglist.push_back(to_push);
+ }
+ }
+ }
+
+ // create an argv vector for the child process
+ char **fakeargv = new char*[arglist.size() + 1];
+ int i;
+ for(i=0; i < arglist.size(); i++)
+ fakeargv[i] = const_cast<char*>(arglist[i].c_str());
+
+ fakeargv[i] = NULL;
+
+ fflush(NULL); // flush all buffers before the child inherits them
+ pid_t id = vfork();
+ if(id == 0)
+ {
+ // child
+ execv(exe_path.c_str(), fakeargv);
+
+ // If we reach this point, the exec failed.
+ // Use _exit() instead of exit() per the vfork man page.
+ std::string warning = "Creating editor process failed (vfork/execv)!";
+ popupAndPrintWarning(warning);
+ _exit(0);
+ }
+
+ // parent
+ delete[] fakeargv;
+ // sGatewayPID = id;
+ }
+#endif // LL_WINDOWS
+ }
+ else
+ {
+ std::string warning = "Unable to find path to external XML editor for XUI preview tool";
+ popupAndPrintWarning(warning);
+ }
+}
+
+// Respond to button click to browse for an executable with which to edit XML files
+void LLFloaterUIPreview::onClickBrowseForEditor()
+{
+ // create load dialog box
+ LLFilePicker::ELoadFilter type = (LLFilePicker::ELoadFilter)((intptr_t)((void*)LLFilePicker::FFLOAD_ALL)); // nothing for *.exe so just use all
+ LLFilePicker& picker = LLFilePicker::instance();
+ if (!picker.getOpenFile(type)) // user cancelled -- do nothing
+ {
+ return;
+ }
+
+ // put the selected path into text field
+ const std::string chosen_path = picker.getFirstFile();
+ std::string executable_path = chosen_path;
+#if LL_DARWIN
+ // on Mac, if it's an application bundle, figure out the actual path from the Info.plist file
+ CFStringRef path_cfstr = CFStringCreateWithCString(kCFAllocatorDefault, chosen_path.c_str(), kCFStringEncodingMacRoman); // get path as a CFStringRef
+ CFURLRef path_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path_cfstr, kCFURLPOSIXPathStyle, TRUE); // turn it into a CFURLRef
+ CFBundleRef chosen_bundle = CFBundleCreate(kCFAllocatorDefault, path_url); // get a handle for the bundle
+ if(NULL != chosen_bundle)
+ {
+ CFDictionaryRef bundleInfoDict = CFBundleGetInfoDictionary(chosen_bundle); // get the bundle's dictionary
+ if(NULL != bundleInfoDict)
+ {
+ CFStringRef executable_cfstr = (CFStringRef)CFDictionaryGetValue(bundleInfoDict, CFSTR("CFBundleExecutable")); // get the name of the actual executable (e.g. TextEdit or firefox-bin)
+ int max_file_length = 256; // (max file name length is 255 in OSX)
+ char executable_buf[max_file_length];
+ if(CFStringGetCString(executable_cfstr, executable_buf, max_file_length, kCFStringEncodingMacRoman)) // convert CFStringRef to char*
+ {
+ executable_path += std::string("/Contents/MacOS/") + std::string(executable_buf); // append path to executable directory and then executable name to exec path
+ }
+ else
+ {
+ std::string warning = "Unable to get CString from CFString for executable path";
+ popupAndPrintWarning(warning);
+ }
+ }
+ else
+ {
+ std::string warning = "Unable to get bundle info dictionary from application bundle";
+ popupAndPrintWarning(warning);
+ }
+ }
+ else
+ {
+ if(-1 != executable_path.find(".app")) // only warn if this path actually had ".app" in it, i.e. it probably just wasn'nt an app bundle and that's okay
+ {
+ std::string warning = std::string("Unable to get bundle from path \"") + chosen_path + std::string("\"");
+ popupAndPrintWarning(warning);
+ }
+ }
+
+#endif
+ mEditorPathTextBox->setText(std::string(executable_path)); // copy the path to the executable to the textfield for display and later fetching
+}
+
+// Respond to button click to browse for a VLT-generated diffs file
+void LLFloaterUIPreview::onClickBrowseForDiffs()
+{
+ // create load dialog box
+ LLFilePicker::ELoadFilter type = (LLFilePicker::ELoadFilter)((intptr_t)((void*)LLFilePicker::FFLOAD_XML)); // nothing for *.exe so just use all
+ LLFilePicker& picker = LLFilePicker::instance();
+ if (!picker.getOpenFile(type)) // user cancelled -- do nothing
+ {
+ return;
+ }
+
+ // put the selected path into text field
+ const std::string chosen_path = picker.getFirstFile();
+ mDiffPathTextBox->setText(std::string(chosen_path)); // copy the path to the executable to the textfield for display and later fetching
+ if(LLView::sHighlightingDiffs) // if we're already highlighting, toggle off and then on so we get the data from the new file
+ {
+ onClickToggleDiffHighlighting();
+ onClickToggleDiffHighlighting();
+ }
+}
+
+void LLFloaterUIPreview::onClickToggleDiffHighlighting()
+{
+ if(mHighlightingOverlaps)
+ {
+ onClickToggleOverlapping();
+ mToggleOverlapButton->toggleState();
+ }
+
+ LLView::sPreviewHighlightedElements.clear(); // clear lists first
+ mDiffsMap.clear();
+ mFileList->clearHighlightedItems();
+
+ if(LLView::sHighlightingDiffs) // Turning highlighting off
+ {
+ LLView::sHighlightingDiffs = !sHighlightingDiffs;
+ return;
+ }
+ else // Turning highlighting on
+ {
+ // Get the file and make sure it exists
+ std::string path_in_textfield = mDiffPathTextBox->getText(); // get file path
+ BOOL error = FALSE;
+
+ if(std::string("") == path_in_textfield) // check for blank file
+ {
+ std::string warning = "Unable to highlight differences because no file was provided; fill in the relevant text field";
+ popupAndPrintWarning(warning);
+ error = TRUE;
+ }
+
+ llstat dummy;
+ if(LLFile::stat(path_in_textfield.c_str(), &dummy) && !error) // check if the file exists (empty check is reduntant but useful for the informative error message)
+ {
+ std::string warning = std::string("Unable to highlight differences because an invalid path to a difference file was provided:\"") + path_in_textfield + "\"";
+ popupAndPrintWarning(warning);
+ error = TRUE;
+ }
+
+ // Build a list of changed elements as given by the XML
+ std::list<std::string> changed_element_names;
+ LLXmlTree xml_tree;
+ BOOL success = xml_tree.parseFile(path_in_textfield.c_str(), TRUE);
+
+ if(success && !error)
+ {
+ LLXmlTreeNode* root_floater = xml_tree.getRoot();
+ if(!strncmp("XuiDelta",root_floater->getName().c_str(),9))
+ {
+ for (LLXmlTreeNode* child = root_floater->getFirstChild(); // get the first child first, then below get the next one; otherwise the iterator is invalid (bug or feature in XML code?)
+ child != NULL;
+ child = root_floater->getNextChild()) // get child for next iteration
+ {
+ if(!strncmp("file",child->getName().c_str(),5))
+ {
+ scanDiffFile(child);
+ }
+ else if(!strncmp("error",child->getName().c_str(),6))
+ {
+ std::string error_file, error_message;
+ child->getAttributeString("filename",error_file);
+ child->getAttributeString("message",error_message);
+ if(mDiffsMap.find(error_file) != mDiffsMap.end())
+ {
+ mDiffsMap.insert(std::make_pair(error_file,std::make_pair(StringListPtr(new StringList), StringListPtr(new StringList))));
+ }
+ mDiffsMap[error_file].second->push_back(error_message);
+ }
+ else
+ {
+ std::string warning = std::string("Child was neither a file or an error, but rather the following:\"") + std::string(child->getName()) + "\"";
+ popupAndPrintWarning(warning);
+ error = TRUE;
+ break;
+ }
+ }
+ }
+ else
+ {
+ std::string warning = std::string("Root node not named XuiDelta:\"") + path_in_textfield + "\"";
+ popupAndPrintWarning(warning);
+ error = TRUE;
+ }
+ }
+ else if(!error)
+ {
+ std::string warning = std::string("Unable to create tree from XML:\"") + path_in_textfield + "\"";
+ popupAndPrintWarning(warning);
+ error = TRUE;
+ }
+
+ if(error) // if we encountered an error, reset the button to off
+ {
+ mToggleHighlightButton->setToggleState(FALSE);
+ }
+ else // only toggle if we didn't encounter an error
+ {
+ LLView::sHighlightingDiffs = !sHighlightingDiffs;
+ highlightChangedElements(); // *TODO: this is extraneous, right?
+ highlightChangedFiles(); // *TODO: this is extraneous, right?
+ }
+ }
+}
+
+void LLFloaterUIPreview::scanDiffFile(LLXmlTreeNode* file_node)
+{
+ // Get file name
+ std::string file_name;
+ file_node->getAttributeString("name",file_name);
+ if(std::string("") == file_name)
+ {
+ std::string warning = std::string("Empty file name encountered in differences:\"") + file_name + "\"";
+ popupAndPrintWarning(warning);
+ return;
+ }
+
+ // Get a list of changed elements
+ // Get the first child first, then below get the next one; otherwise the iterator is invalid (bug or feature in XML code?)
+ for (LLXmlTreeNode* child = file_node->getFirstChild(); child != NULL; child = file_node->getNextChild())
+ {
+ if(!strncmp("delta",child->getName().c_str(),6))
+ {
+ std::string id;
+ child->getAttributeString("id",id);
+ if(mDiffsMap.find(file_name) == mDiffsMap.end())
+ {
+ mDiffsMap.insert(std::make_pair(file_name,std::make_pair(StringListPtr(new StringList), StringListPtr(new StringList))));
+ }
+ mDiffsMap[file_name].first->push_back(std::string(id.c_str()));
+ }
+ else
+ {
+ std::string warning = std::string("Child of file was not a delta, but rather the following:\"") + std::string(child->getName()) + "\"";
+ popupAndPrintWarning(warning);
+ return;
+ }
+ }
+}
+
+void LLFloaterUIPreview::highlightChangedElements()
+{
+ if(NULL == mLiveFile)
+ {
+ return;
+ }
+
+ // Process differences first (we want their warnings to be shown underneath other warnings)
+ StringListPtr changed_element_paths;
+ DiffMap::iterator iterExists = mDiffsMap.find(mLiveFile->mFileName);
+ if(iterExists != mDiffsMap.end())
+ {
+ changed_element_paths = mDiffsMap[mLiveFile->mFileName].first; // retrieve list of changed element paths from map
+ }
+
+ for(std::list<std::string>::iterator iter = changed_element_paths->begin(); iter != changed_element_paths->end(); ++iter) // for every changed element path
+ {
+ LLView* element = mDisplayedFloater;
+ if(!strncmp(iter->c_str(),".",1)) // if it's the root floater itself
+ {
+ continue;
+ }
+
+ // Split element hierarchy path on period (*HACK: it's possible that the element name will have a period in it, in which case this won't work. See https://wiki.lindenlab.com/wiki/Viewer_Localization_Tool_Documentation.)
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep(".");
+ tokenizer tokens(*iter, sep);
+ tokenizer::iterator token_iter;
+ BOOL failed = FALSE;
+ for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
+ {
+ element = element->findChild<LLView>(*token_iter,FALSE); // try to find element: don't recur, and don't create if missing
+
+ // if we still didn't find it...
+ if(NULL == element)
+ {
+ llinfos << "Unable to find element in XuiDelta file named \"" << *iter << "\" in file \"" << mLiveFile->mFileName <<
+ "\". The element may no longer exist, the path may be incorrect, or it may not be a non-displayable element (not an LLView) such as a \"string\" type." << llendl;
+ failed = TRUE;
+ break;
+ }
+ }
+
+ if(!failed)
+ {
+ // Now that we have a pointer to the actual element, add it to the list of elements to be highlighted
+ std::set<LLView*>::iterator iter2 = std::find(LLView::sPreviewHighlightedElements.begin(), LLView::sPreviewHighlightedElements.end(), element);
+ if(iter2 == LLView::sPreviewHighlightedElements.end())
+ {
+ LLView::sPreviewHighlightedElements.insert(element);
+ }
+ }
+ }
+
+ // Process errors second, so their warnings show up on top of other warnings
+ StringListPtr error_list;
+ if(iterExists != mDiffsMap.end())
+ {
+ error_list = mDiffsMap[mLiveFile->mFileName].second;
+ }
+ for(std::list<std::string>::iterator iter = error_list->begin(); iter != error_list->end(); ++iter) // for every changed element path
+ {
+ std::string warning = std::string("Error listed among differences. Filename: \"") + mLiveFile->mFileName + "\". Message: \"" + *iter + "\"";
+ popupAndPrintWarning(warning);
+ }
+}
+
+void LLFloaterUIPreview::highlightChangedFiles()
+{
+ for(DiffMap::iterator iter = mDiffsMap.begin(); iter != mDiffsMap.end(); ++iter) // for every file listed in diffs
+ {
+ LLScrollListItem* item = mFileList->getItemByLabel(std::string(iter->first), FALSE, 1);
+ if(item)
+ {
+ item->setHighlighted(TRUE);
+ }
+ }
+}
+
+// Respond to button click to browse for an executable with which to edit XML files
+void LLFloaterUIPreview::onClickCloseDisplayedFloater(S32 caller_id)
+{
+ if(caller_id == PRIMARY_FLOATER)
+ {
+ mCloseOtherButton->setEnabled(FALSE);
+ mToggleOverlapButton->setEnabled(FALSE);
+
+ if(mDisplayedFloater)
+ {
+ mLastDisplayedX = mDisplayedFloater->calcScreenRect().mLeft;
+ mLastDisplayedY = mDisplayedFloater->calcScreenRect().mBottom;
+ delete mDisplayedFloater;
+ mDisplayedFloater = NULL;
+ }
+
+ if(mLiveFile)
+ {
+ delete mLiveFile;
+ mLiveFile = NULL;
+ }
+
+ if(mToggleOverlapButton->getToggleState())
+ {
+ mToggleOverlapButton->toggleState();
+ onClickToggleOverlapping();
+ }
+
+ LLView::sPreviewClickedElement = NULL; // stop overlapping elements panel from drawing
+ mOverlapPanel->mLastClickedElement = NULL;
+ }
+ else
+ {
+ mCloseOtherButton_2->setEnabled(FALSE);
+ delete mDisplayedFloater_2;
+ mDisplayedFloater_2 = NULL;
+ }
+
+}
+
+void append_view_tooltip(LLView* tooltip_view, std::string *tooltip_msg)
+{
+ LLRect rect = tooltip_view->getRect();
+ LLRect parent_rect = tooltip_view->getParent()->getRect();
+ S32 left = rect.mLeft;
+ // invert coordinate system for XUI top-left layout
+ S32 top = parent_rect.getHeight() - rect.mTop;
+ if (!tooltip_msg->empty())
+ {
+ tooltip_msg->append("\n");
+ }
+ std::string msg = llformat("%s %d, %d (%d x %d)",
+ tooltip_view->getName().c_str(),
+ left,
+ top,
+ rect.getWidth(),
+ rect.getHeight() );
+ tooltip_msg->append( msg );
+}
+
+BOOL LLPreviewedFloater::handleToolTip(S32 x, S32 y, MASK mask)
+{
+ if (!sShowRectangles)
+ {
+ return LLFloater::handleToolTip(x, y, mask);
+ }
+
+ S32 screen_x, screen_y;
+ localPointToScreen(x, y, &screen_x, &screen_y);
+ std::string tooltip_msg;
+ LLView* tooltip_view = this;
+ LLView::tree_iterator_t end_it = endTreeDFS();
+ for (LLView::tree_iterator_t it = beginTreeDFS(); it != end_it; ++it)
+ {
+ LLView* viewp = *it;
+ LLRect screen_rect;
+ viewp->localRectToScreen(viewp->getLocalRect(), &screen_rect);
+ if (!(viewp->getVisible()
+ && screen_rect.pointInRect(screen_x, screen_y)))
+ {
+ it.skipDescendants();
+ }
+ // only report xui names for LLUICtrls, not the various container LLViews
+
+ else if (dynamic_cast<LLUICtrl*>(viewp))
+ {
+ // if we are in a new part of the tree (not a descendent of current tooltip_view)
+ // then push the results for tooltip_view and start with a new potential view
+ // NOTE: this emulates visiting only the leaf nodes that meet our criteria
+
+ if (tooltip_view != this
+ && !viewp->hasAncestor(tooltip_view))
+ {
+ append_view_tooltip(tooltip_view, &tooltip_msg);
+ }
+ tooltip_view = viewp;
+ }
+ }
+
+ append_view_tooltip(tooltip_view, &tooltip_msg);
+
+ LLToolTipMgr::instance().show(LLToolTip::Params()
+ .message(tooltip_msg)
+ .max_width(400));
+ return TRUE;
+}
+
+BOOL LLPreviewedFloater::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ selectElement(this,x,y,0);
+ return TRUE;
+}
+
+// *NOTE: In order to hide all of the overlapping elements of the selected element so as to see it in context, here is what you would need to do:
+// -This selectElement call fills the overlap panel as normal. The element which is "selected" here is actually just an intermediate selection step;
+// what you've really selected is a list of elements: the one you clicked on and everything that overlaps it.
+// -The user then selects one of the elements from this list the overlap panel (click handling to the overlap panel would have to be added).
+// This becomes the final selection (as opposed to the intermediate selection that was just made).
+// -Everything else that is currently displayed on the overlap panel should be hidden from view in the previewed floater itself (setVisible(FALSE)).
+// -Subsequent clicks on other elements in the overlap panel (they should still be there) should make other elements the final selection.
+// -On close or on the click of a new button, everything should be shown again and all selection state should be cleared.
+// ~Jacob, 8/08
+BOOL LLPreviewedFloater::selectElement(LLView* parent, int x, int y, int depth)
+{
+ if(getVisible())
+ {
+ BOOL handled = FALSE;
+ if(LLFloaterUIPreview::containerType(parent))
+ {
+ for(child_list_const_iter_t child_it = parent->getChildList()->begin(); child_it != parent->getChildList()->end(); ++child_it)
+ {
+ LLView* child = *child_it;
+ S32 local_x = x - child->getRect().mLeft;
+ S32 local_y = y - child->getRect().mBottom;
+ if (child->pointInView(local_x, local_y) &&
+ child->getVisible() &&
+ selectElement(child, x, y, ++depth))
+ {
+ handled = TRUE;
+ break;
+ }
+ }
+ }
+
+ if(!handled)
+ {
+ LLView::sPreviewClickedElement = parent;
+ }
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+void LLPreviewedFloater::draw()
+{
+ if(NULL != mFloaterUIPreview)
+ {
+ // Set and unset sDrawPreviewHighlights flag so as to avoid using two flags
+ if(mFloaterUIPreview->mHighlightingOverlaps)
+ {
+ LLView::sDrawPreviewHighlights = TRUE;
+ }
+
+ // If we're looking for truncations, draw debug rects for the displayed
+ // floater only.
+ bool old_debug_rects = LLView::sDebugRects;
+ bool old_show_names = LLView::sDebugRectsShowNames;
+ if (sShowRectangles)
+ {
+ LLView::sDebugRects = true;
+ LLView::sDebugRectsShowNames = false;
+ }
+
+ LLFloater::draw();
+
+ LLView::sDebugRects = old_debug_rects;
+ LLView::sDebugRectsShowNames = old_show_names;
+
+ if(mFloaterUIPreview->mHighlightingOverlaps)
+ {
+ LLView::sDrawPreviewHighlights = FALSE;
+ }
+ }
+}
+
+void LLFloaterUIPreview::onClickToggleOverlapping()
+{
+ if(LLView::sHighlightingDiffs)
+ {
+ onClickToggleDiffHighlighting();
+ mToggleHighlightButton->toggleState();
+ }
+ LLView::sPreviewHighlightedElements.clear(); // clear lists first
+
+ S32 width, height;
+ getResizeLimits(&width, &height); // illegal call of non-static member function
+ if(mHighlightingOverlaps)
+ {
+ mHighlightingOverlaps = !mHighlightingOverlaps;
+ // reset list of preview highlighted elements
+ setRect(LLRect(getRect().mLeft,getRect().mTop,getRect().mRight - mOverlapPanel->getRect().getWidth(),getRect().mBottom));
+ setResizeLimits(width - mOverlapPanel->getRect().getWidth(), height);
+ }
+ else
+ {
+ mHighlightingOverlaps = !mHighlightingOverlaps;
+ displayFloater(FALSE,1);
+ setRect(LLRect(getRect().mLeft,getRect().mTop,getRect().mRight + mOverlapPanel->getRect().getWidth(),getRect().mBottom));
+ setResizeLimits(width + mOverlapPanel->getRect().getWidth(), height);
+ }
+ childSetVisible("overlap_scroll", mHighlightingOverlaps);
+}
+
+void LLFloaterUIPreview::findOverlapsInChildren(LLView* parent)
+{
+ if(parent->getChildCount() == 0 || !containerType(parent)) // if it has no children or isn't a container type, skip it
+ {
+ return;
+ }
+
+ // for every child of the parent
+ for(child_list_const_iter_t child_it = parent->getChildList()->begin(); child_it != parent->getChildList()->end(); ++child_it)
+ {
+ LLView* child = *child_it;
+ if(overlapIgnorable(child))
+ {
+ continue;
+ }
+
+ // for every sibling
+ for(child_list_const_iter_t sibling_it = parent->getChildList()->begin(); sibling_it != parent->getChildList()->end(); ++sibling_it) // for each sibling
+ {
+ LLView* sibling = *sibling_it;
+ if(overlapIgnorable(sibling))
+ {
+ continue;
+ }
+
+ // if they overlap... (we don't care if they're visible or enabled -- we want to check those anyway, i.e. hidden tabs that can be later shown)
+ if(sibling != child && elementOverlap(child, sibling))
+ {
+ mOverlapPanel->mOverlapMap[child].push_back(sibling); // add to the map
+ }
+ }
+ findOverlapsInChildren(child); // recur
+ }
+}
+
+// *HACK: don't overlap with the drag handle and various other elements
+// This is using dynamic casts because there is no object-oriented way to tell which elements contain localizable text. These are a few that are ignorable.
+// *NOTE: If a list of elements which have localizable content were created, this function should return false if viewp's class is in that list.
+BOOL LLFloaterUIPreview::overlapIgnorable(LLView* viewp)
+{
+ return NULL != dynamic_cast<LLDragHandle*>(viewp) ||
+ NULL != dynamic_cast<LLViewBorder*>(viewp) ||
+ NULL != dynamic_cast<LLResizeBar*>(viewp);
+}
+
+// *HACK: these are the only two container types as of 8/08, per Richard
+// This is using dynamic casts because there is no object-oriented way to tell which elements are containers.
+BOOL LLFloaterUIPreview::containerType(LLView* viewp)
+{
+ return NULL != dynamic_cast<LLPanel*>(viewp) || NULL != dynamic_cast<LLLayoutStack*>(viewp);
+}
+
+// Check if two llview's rectangles overlap, with some tolerance
+BOOL LLFloaterUIPreview::elementOverlap(LLView* view1, LLView* view2)
+{
+ LLSD rec1 = view1->getRect().getValue();
+ LLSD rec2 = view2->getRect().getValue();
+ int tolerance = 2;
+ return (int)rec1[0] <= (int)rec2[2] - tolerance &&
+ (int)rec2[0] <= (int)rec1[2] - tolerance &&
+ (int)rec1[3] <= (int)rec2[1] - tolerance &&
+ (int)rec2[3] <= (int)rec1[1] - tolerance;
+}
+
+void LLOverlapPanel::draw()
+{
+ static const std::string current_selection_text("Current selection: ");
+ static const std::string overlapper_text("Overlapper: ");
+ LLColor4 text_color = LLColor4::grey;
+ gGL.color4fv(text_color.mV);
+
+ if(!LLView::sPreviewClickedElement)
+ {
+ LLUI::translate(5,getRect().getHeight()-20); // translate to top-5,left-5
+ LLView::sDrawPreviewHighlights = FALSE;
+ LLFontGL::getFontSansSerifSmall()->renderUTF8(current_selection_text, 0, 0, 0, text_color,
+ LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
+ }
+ else
+ {
+ OverlapMap::iterator iterExists = mOverlapMap.find(LLView::sPreviewClickedElement);
+ if(iterExists == mOverlapMap.end())
+ {
+ return;
+ }
+
+ std::list<LLView*> overlappers = mOverlapMap[LLView::sPreviewClickedElement];
+ if(overlappers.size() == 0)
+ {
+ LLUI::translate(5,getRect().getHeight()-20); // translate to top-5,left-5
+ LLView::sDrawPreviewHighlights = FALSE;
+ std::string current_selection = std::string(current_selection_text + LLView::sPreviewClickedElement->getName() + " (no elements overlap)");
+ S32 text_width = LLFontGL::getFontSansSerifSmall()->getWidth(current_selection) + 10;
+ LLFontGL::getFontSansSerifSmall()->renderUTF8(current_selection, 0, 0, 0, text_color,
+ LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
+ // widen panel enough to fit this text
+ LLRect rect = getRect();
+ setRect(LLRect(rect.mLeft,rect.mTop,rect.getWidth() < text_width ? rect.mLeft + text_width : rect.mRight,rect.mTop));
+ return;
+ }
+
+ // recalculate required with and height; otherwise use cached
+ BOOL need_to_recalculate_bounds = FALSE;
+ if(mLastClickedElement == NULL)
+ {
+ need_to_recalculate_bounds = TRUE;
+ }
+
+ if(NULL == mLastClickedElement)
+ {
+ mLastClickedElement = LLView::sPreviewClickedElement;
+ }
+
+ // recalculate bounds for scroll panel
+ if(need_to_recalculate_bounds || LLView::sPreviewClickedElement->getName() != mLastClickedElement->getName())
+ {
+ // reset panel's rectangle to its default width and height (300x600)
+ LLRect panel_rect = getRect();
+ setRect(LLRect(panel_rect.mLeft,panel_rect.mTop,panel_rect.mLeft+getRect().getWidth(),panel_rect.mTop-getRect().getHeight()));
+
+ LLRect rect;
+
+ // change bounds for selected element
+ int height_sum = mLastClickedElement->getRect().getHeight() + mSpacing + 80;
+ rect = getRect();
+ setRect(LLRect(rect.mLeft,rect.mTop,rect.getWidth() > mLastClickedElement->getRect().getWidth() + 5 ? rect.mRight : rect.mLeft + mLastClickedElement->getRect().getWidth() + 5, rect.mBottom));
+
+ // and widen to accomodate text if that's wider
+ std::string display_text = current_selection_text + LLView::sPreviewClickedElement->getName();
+ S32 text_width = LLFontGL::getFontSansSerifSmall()->getWidth(display_text) + 10;
+ rect = getRect();
+ setRect(LLRect(rect.mLeft,rect.mTop,rect.getWidth() < text_width ? rect.mLeft + text_width : rect.mRight,rect.mTop));
+
+ std::list<LLView*> overlappers = mOverlapMap[LLView::sPreviewClickedElement];
+ for(std::list<LLView*>::iterator overlap_it = overlappers.begin(); overlap_it != overlappers.end(); ++overlap_it)
+ {
+ LLView* viewp = *overlap_it;
+ height_sum += viewp->getRect().getHeight() + mSpacing*3;
+
+ // widen panel's rectangle to accommodate widest overlapping element of this floater
+ rect = getRect();
+ setRect(LLRect(rect.mLeft,rect.mTop,rect.getWidth() > viewp->getRect().getWidth() + 5 ? rect.mRight : rect.mLeft + viewp->getRect().getWidth() + 5, rect.mBottom));
+
+ // and widen to accomodate text if that's wider
+ std::string display_text = overlapper_text + viewp->getName();
+ S32 text_width = LLFontGL::getFontSansSerifSmall()->getWidth(display_text) + 10;
+ rect = getRect();
+ setRect(LLRect(rect.mLeft,rect.mTop,rect.getWidth() < text_width ? rect.mLeft + text_width : rect.mRight,rect.mTop));
+ }
+ // change panel's height to accommodate all element heights plus spacing between them
+ rect = getRect();
+ setRect(LLRect(rect.mLeft,rect.mTop,rect.mRight,rect.mTop-height_sum));
+ }
+
+ LLUI::translate(5,getRect().getHeight()-10); // translate to top left
+ LLView::sDrawPreviewHighlights = FALSE;
+
+ // draw currently-selected element at top of overlappers
+ LLUI::translate(0,-mSpacing);
+ LLFontGL::getFontSansSerifSmall()->renderUTF8(current_selection_text + LLView::sPreviewClickedElement->getName(), 0, 0, 0, text_color,
+ LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
+ LLUI::translate(0,-mSpacing-LLView::sPreviewClickedElement->getRect().getHeight()); // skip spacing distance + height
+ LLView::sPreviewClickedElement->draw();
+
+ for(std::list<LLView*>::iterator overlap_it = overlappers.begin(); overlap_it != overlappers.end(); ++overlap_it)
+ {
+ LLView* viewp = *overlap_it;
+
+ // draw separating line
+ LLUI::translate(0,-mSpacing);
+ gl_line_2d(0,0,getRect().getWidth()-10,0,LLColor4(192.0f/255.0f,192.0f/255.0f,192.0f/255.0f));
+
+ // draw name
+ LLUI::translate(0,-mSpacing);
+ LLFontGL::getFontSansSerifSmall()->renderUTF8(overlapper_text + viewp->getName(), 0, 0, 0, text_color,
+ LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
+
+ // draw element
+ LLUI::translate(0,-mSpacing-viewp->getRect().getHeight()); // skip spacing distance + height
+ viewp->draw();
+ }
+ mLastClickedElement = LLView::sPreviewClickedElement;
+ }
+}
+
+void LLFloaterUIPreviewUtil::registerFloater()
+{
+ LLFloaterReg::add("ui_preview", "floater_ui_preview.xml",
+ &LLFloaterReg::build<LLFloaterUIPreview>);
+}
diff --git a/indra/newview/llfloateruipreview.h b/indra/newview/llfloateruipreview.h
new file mode 100644
index 0000000000..2a31b2df59
--- /dev/null
+++ b/indra/newview/llfloateruipreview.h
@@ -0,0 +1,46 @@
+/**
+ * @file llfloateruipreview.h
+ * @brief Tool for previewing and editing floaters
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Tool for previewing floaters and panels for localization and UI design purposes.
+// See: https://wiki.lindenlab.com/wiki/GUI_Preview_And_Localization_Tools
+// See: https://jira.lindenlab.com/browse/DEV-16869
+
+#ifndef LL_LLUIPREVIEW_H
+#define LL_LLUIPREVIEW_H
+
+namespace LLFloaterUIPreviewUtil
+{
+ void registerFloater();
+}
+
+#endif // LL_LLUIPREVIEW_H
+
diff --git a/indra/newview/llfloaterurldisplay.cpp b/indra/newview/llfloaterurldisplay.cpp
index c265c6169a..4b67cbb308 100644
--- a/indra/newview/llfloaterurldisplay.cpp
+++ b/indra/newview/llfloaterurldisplay.cpp
@@ -33,22 +33,23 @@
#include "llviewerprecompiledheaders.h"
+#include "llregionhandle.h"
+#include "v3dmath.h"
+
#include "llfloaterurldisplay.h"
#include "llpanelplace.h"
#include "lluictrlfactory.h"
-#include "v3dmath.h"
-
////////////////////////////////////////////////////////////////////////////
// LLFloaterURLDisplay
LLFloaterURLDisplay::LLFloaterURLDisplay(const LLSD& sd)
+ : LLFloater(sd)
{
mFactoryMap["place_details_panel"] = LLCallbackMap(LLFloaterURLDisplay::createPlaceDetail, this);
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_preview_url.xml", &getFactoryMap());
- this->setVisible(false);
+// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_preview_url.xml");
// If positioned at 0,0 the teleport button is behind the toolbar.
LLRect r = getRect();
diff --git a/indra/newview/llfloaterurldisplay.h b/indra/newview/llfloaterurldisplay.h
index 91c544ae86..22f5a95ad0 100644
--- a/indra/newview/llfloaterurldisplay.h
+++ b/indra/newview/llfloaterurldisplay.h
@@ -40,11 +40,10 @@ class LLPanelPlace;
class LLSD;
class LLUUID;
-class LLFloaterURLDisplay : public LLFloater, public LLFloaterSingleton<LLFloaterURLDisplay>
+class LLFloaterURLDisplay : public LLFloater
{
+ friend class LLFloaterReg;
public:
- LLFloaterURLDisplay(const LLSD& sd);
- virtual ~LLFloaterURLDisplay();
void displayParcelInfo(U64 region_handle, const LLVector3& pos);
void setSnapshotDisplay(const LLUUID& snapshot_id);
@@ -54,6 +53,9 @@ public:
static void* createPlaceDetail(void* userdata);
private:
+ LLFloaterURLDisplay(const LLSD& sd);
+ virtual ~LLFloaterURLDisplay();
+
LLVector3 mRegionPosition;
U64 mRegionHandle;
LLPanelPlace* mPlacePanel;
diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp
index 9d91aa9868..91d0f0e370 100644
--- a/indra/newview/llfloaterurlentry.cpp
+++ b/indra/newview/llfloaterurlentry.cpp
@@ -32,12 +32,15 @@
#include "llviewerprecompiledheaders.h"
+#include "llhttpclient.h"
+
#include "llfloaterurlentry.h"
#include "llpanellandmedia.h"
+#include "llpanelface.h"
-// project includes
#include "llcombobox.h"
+#include "llnotificationsutil.h"
#include "llurlhistory.h"
#include "lluictrlfactory.h"
#include "llwindow.h"
@@ -86,12 +89,22 @@ public:
// LLFloaterURLEntry()
//-----------------------------------------------------------------------------
LLFloaterURLEntry::LLFloaterURLEntry(LLHandle<LLPanel> parent)
- :
- LLFloater(),
- mPanelLandMediaHandle(parent)
+ : LLFloater(LLSD()),
+ mPanelLandMediaHandle(parent)
{
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_url_entry.xml");
+ LLUICtrlFactory::getInstance()->buildFloater(this, "floater_url_entry.xml", NULL);
+}
+
+//-----------------------------------------------------------------------------
+// ~LLFloaterURLEntry()
+//-----------------------------------------------------------------------------
+LLFloaterURLEntry::~LLFloaterURLEntry()
+{
+ sInstance = NULL;
+}
+BOOL LLFloaterURLEntry::postBuild()
+{
mMediaURLEdit = getChild<LLComboBox>("media_entry");
// Cancel button
@@ -99,7 +112,6 @@ LLFloaterURLEntry::LLFloaterURLEntry(LLHandle<LLPanel> parent)
// Cancel button
childSetAction("clear_btn", onBtnClear, this);
-
// clear media list button
LLSD parcel_history = LLURLHistory::getURLHistory("parcel");
bool enable_clear_button = parcel_history.size() > 0 ? true : false;
@@ -111,17 +123,8 @@ LLFloaterURLEntry::LLFloaterURLEntry(LLHandle<LLPanel> parent)
setDefaultBtn("ok_btn");
buildURLHistory();
- sInstance = this;
-}
-
-//-----------------------------------------------------------------------------
-// ~LLFloaterURLEntry()
-//-----------------------------------------------------------------------------
-LLFloaterURLEntry::~LLFloaterURLEntry()
-{
- sInstance = NULL;
+ return TRUE;
}
-
void LLFloaterURLEntry::buildURLHistory()
{
LLCtrlListInterface* url_list = childGetListInterface("media_entry");
@@ -145,43 +148,42 @@ void LLFloaterURLEntry::buildURLHistory()
void LLFloaterURLEntry::headerFetchComplete(U32 status, const std::string& mime_type)
{
- LLPanelLandMedia* panel_media = (LLPanelLandMedia*)mPanelLandMediaHandle.get();
+ LLPanelLandMedia* panel_media = dynamic_cast<LLPanelLandMedia*>(mPanelLandMediaHandle.get());
if (panel_media)
{
// status is ignored for now -- error = "none/none"
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());
+ }
+
+ }
// Decrement the cursor
getWindow()->decBusyCount();
childSetVisible("loading_label", false);
- close();
+ closeFloater();
}
// static
-LLHandle<LLFloater> LLFloaterURLEntry::show(LLHandle<LLPanel> parent)
+LLHandle<LLFloater> LLFloaterURLEntry::show(LLHandle<LLPanel> parent, const std::string media_url)
{
- if (sInstance)
- {
- sInstance->open();
- }
- else
+ if (!sInstance)
{
sInstance = new LLFloaterURLEntry(parent);
}
- sInstance->updateFromLandMediaPanel();
+ sInstance->openFloater();
+ sInstance->addURLToCombobox(media_url);
return sInstance->getHandle();
}
-void LLFloaterURLEntry::updateFromLandMediaPanel()
-{
- LLPanelLandMedia* panel_media = (LLPanelLandMedia*)mPanelLandMediaHandle.get();
- if (panel_media)
- {
- std::string media_url = panel_media->getMediaURL();
- addURLToCombobox(media_url);
- }
-}
+
bool LLFloaterURLEntry::addURLToCombobox(const std::string& media_url)
{
@@ -227,7 +229,7 @@ void LLFloaterURLEntry::onBtnOK( void* userdata )
}
// Discover the MIME type only for "http" scheme.
- if(scheme == "http")
+ if(scheme == "http" || scheme == "https")
{
LLHTTPClient::getHeaderOnly( media_url,
new LLMediaTypeResponder(self->getHandle()));
@@ -254,7 +256,7 @@ void LLFloaterURLEntry::onBtnOK( void* userdata )
void LLFloaterURLEntry::onBtnCancel( void* userdata )
{
LLFloaterURLEntry *self =(LLFloaterURLEntry *)userdata;
- self->close();
+ self->closeFloater();
}
// static
@@ -263,13 +265,13 @@ void LLFloaterURLEntry::onBtnCancel( void* userdata )
//-----------------------------------------------------------------------------
void LLFloaterURLEntry::onBtnClear( void* userdata )
{
- LLNotifications::instance().add( "ConfirmClearMediaUrlList", LLSD(), LLSD(),
+ LLNotificationsUtil::add( "ConfirmClearMediaUrlList", LLSD(), LLSD(),
boost::bind(&LLFloaterURLEntry::callback_clear_url_list, (LLFloaterURLEntry*)userdata, _1, _2) );
}
bool LLFloaterURLEntry::callback_clear_url_list(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if ( option == 0 ) // YES
{
// clear saved list
diff --git a/indra/newview/llfloaterurlentry.h b/indra/newview/llfloaterurlentry.h
index 6d04326cf8..6dd9c8453c 100644
--- a/indra/newview/llfloaterurlentry.h
+++ b/indra/newview/llfloaterurlentry.h
@@ -1,6 +1,6 @@
/**
- * @file llfloaternamedesc.h
- * @brief LLFloaterNameDesc class definition
+ * @file llfloaterurlentry.h
+ * @brief LLFloaterURLEntry class definition
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
@@ -44,10 +44,8 @@ class LLFloaterURLEntry : public LLFloater
public:
// Can only be shown by LLPanelLandMedia, and pushes data back into
// that panel via the handle.
- static LLHandle<LLFloater> show(LLHandle<LLPanel> panel_land_media_handle);
-
- void updateFromLandMediaPanel();
-
+ static LLHandle<LLFloater> show(LLHandle<LLPanel> panel_land_media_handle, const std::string media_url);
+ /*virtual*/ BOOL postBuild();
void headerFetchComplete(U32 status, const std::string& mime_type);
bool addURLToCombobox(const std::string& media_url);
diff --git a/indra/newview/llfloatervoicedevicesettings.cpp b/indra/newview/llfloatervoicedevicesettings.cpp
index 2922628786..638c9f1b8c 100644
--- a/indra/newview/llfloatervoicedevicesettings.cpp
+++ b/indra/newview/llfloatervoicedevicesettings.cpp
@@ -36,22 +36,24 @@
#include "llfloatervoicedevicesettings.h"
// Viewer includes
-#include "llagent.h"
#include "llbutton.h"
#include "llcombobox.h"
#include "llfocusmgr.h"
#include "lliconctrl.h"
-#include "llprefsvoice.h"
#include "llsliderctrl.h"
#include "llviewercontrol.h"
#include "llvoiceclient.h"
-#include "llimpanel.h"
+#include "llvoicechannel.h"
// Library includes (after viewer)
#include "lluictrlfactory.h"
+static LLRegisterPanelClassWrapper<LLPanelVoiceDeviceSettings> t_panel_group_general("panel_voice_device_settings");
+
+
LLPanelVoiceDeviceSettings::LLPanelVoiceDeviceSettings()
+ : LLPanel()
{
mCtrlInputDevices = NULL;
mCtrlOutputDevices = NULL;
@@ -83,40 +85,58 @@ BOOL LLPanelVoiceDeviceSettings::postBuild()
return TRUE;
}
+// virtual
+void LLPanelVoiceDeviceSettings::handleVisibilityChange ( BOOL new_visibility )
+{
+ if (new_visibility)
+ {
+ initialize();
+ }
+ else
+ {
+ cleanup();
+ // when closing this window, turn of visiblity control so that
+ // next time preferences is opened we don't suspend voice
+ gSavedSettings.setBOOL("ShowDeviceSettings", FALSE);
+ }
+}
void LLPanelVoiceDeviceSettings::draw()
{
+ refresh();
+
// let user know that volume indicator is not yet available
bool is_in_tuning_mode = gVoiceClient->inTuningMode();
childSetVisible("wait_text", !is_in_tuning_mode);
LLPanel::draw();
- F32 voice_power = gVoiceClient->tuningGetEnergy();
- S32 discrete_power = 0;
-
- if (!is_in_tuning_mode)
- {
- discrete_power = 0;
- }
- else
- {
- discrete_power = llmin(4, llfloor((voice_power / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 4.f));
- }
-
if (is_in_tuning_mode)
{
- for(S32 power_bar_idx = 0; power_bar_idx < 5; power_bar_idx++)
+ const S32 num_bars = 5;
+ F32 voice_power = gVoiceClient->tuningGetEnergy() / LLVoiceClient::OVERDRIVEN_POWER_LEVEL;
+ S32 discrete_power = llmin(num_bars, llfloor(voice_power * (F32)num_bars + 0.1f));
+
+ for(S32 power_bar_idx = 0; power_bar_idx < num_bars; power_bar_idx++)
{
std::string view_name = llformat("%s%d", "bar", power_bar_idx);
LLView* bar_view = getChild<LLView>(view_name);
if (bar_view)
{
+ gl_rect_2d(bar_view->getRect(), LLColor4::grey, TRUE);
+
+ LLColor4 color;
if (power_bar_idx < discrete_power)
{
- LLColor4 color = (power_bar_idx >= 3) ? gSavedSettings.getColor4("OverdrivenColor") : gSavedSettings.getColor4("SpeakingColor");
- gl_rect_2d(bar_view->getRect(), color, TRUE);
+ color = (power_bar_idx >= 3) ? LLUIColorTable::instance().getColor("OverdrivenColor") : LLUIColorTable::instance().getColor("SpeakingColor");
}
- gl_rect_2d(bar_view->getRect(), LLColor4::grey, FALSE);
+ else
+ {
+ color = LLUIColorTable::instance().getColor("PanelFocusBackgroundColor");
+ }
+
+ LLRect color_rect = bar_view->getRect();
+ color_rect.stretch(-1);
+ gl_rect_2d(color_rect, color, TRUE);
}
}
}
@@ -240,7 +260,7 @@ void LLPanelVoiceDeviceSettings::refresh()
}
}
-void LLPanelVoiceDeviceSettings::onOpen()
+void LLPanelVoiceDeviceSettings::initialize()
{
mInputDevice = gSavedSettings.getString("VoiceInputAudioDevice");
mOutputDevice = gSavedSettings.getString("VoiceOutputAudioDevice");
@@ -255,9 +275,12 @@ void LLPanelVoiceDeviceSettings::onOpen()
LLVoiceChannel::suspend();
}
-void LLPanelVoiceDeviceSettings::onClose(bool app_quitting)
+void LLPanelVoiceDeviceSettings::cleanup()
{
- gVoiceClient->tuningStop();
+ if (gVoiceClient)
+ {
+ gVoiceClient->tuningStop();
+ }
LLVoiceChannel::resume();
}
@@ -284,34 +307,37 @@ void LLPanelVoiceDeviceSettings::onCommitOutputDevice(LLUICtrl* ctrl, void* user
//
LLFloaterVoiceDeviceSettings::LLFloaterVoiceDeviceSettings(const LLSD& seed)
- : LLFloater(std::string("floater_device_settings")),
+ : LLFloater(seed),
mDevicePanel(NULL)
{
mFactoryMap["device_settings"] = LLCallbackMap(createPanelVoiceDeviceSettings, this);
// do not automatically open singleton floaters (as result of getInstance())
- BOOL no_open = FALSE;
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_device_settings.xml", &mFactoryMap, no_open);
+// BOOL no_open = FALSE;
+// Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_device_settings.xml", no_open);
+}
+BOOL LLFloaterVoiceDeviceSettings::postBuild()
+{
center();
+ return TRUE;
}
-void LLFloaterVoiceDeviceSettings::onOpen()
+// virtual
+void LLFloaterVoiceDeviceSettings::onOpen(const LLSD& key)
{
if(mDevicePanel)
{
- mDevicePanel->onOpen();
+ mDevicePanel->initialize();
}
-
- LLFloater::onOpen();
}
-void LLFloaterVoiceDeviceSettings::onClose(bool app_quitting)
+// virtual
+void LLFloaterVoiceDeviceSettings::onClose(bool app_settings)
{
if(mDevicePanel)
{
- mDevicePanel->onClose(app_quitting);
+ mDevicePanel->apply();
+ mDevicePanel->cleanup();
}
-
- setVisible(FALSE);
}
void LLFloaterVoiceDeviceSettings::apply()
diff --git a/indra/newview/llfloatervoicedevicesettings.h b/indra/newview/llfloatervoicedevicesettings.h
index d30a57f161..d67283d0a2 100644
--- a/indra/newview/llfloatervoicedevicesettings.h
+++ b/indra/newview/llfloatervoicedevicesettings.h
@@ -36,8 +36,6 @@
#include "llfloater.h"
-class LLPrefsVoiceLogic;
-
class LLPanelVoiceDeviceSettings : public LLPanel
{
public:
@@ -49,9 +47,11 @@ public:
void apply();
void cancel();
void refresh();
- void onOpen();
- void onClose(bool app_quitting);
+ void initialize();
+ void cleanup();
+ /*virtual*/ void handleVisibilityChange ( BOOL new_visibility );
+
protected:
static void onCommitInputDevice(LLUICtrl* ctrl, void* user_data);
static void onCommitOutputDevice(LLUICtrl* ctrl, void* user_data);
@@ -64,19 +64,25 @@ protected:
BOOL mDevicesUpdated;
};
-class LLFloaterVoiceDeviceSettings : public LLFloater, public LLFloaterSingleton<LLFloaterVoiceDeviceSettings>
+class LLFloaterVoiceDeviceSettings : public LLFloater
{
+ friend class LLFloaterReg;
+
public:
- LLFloaterVoiceDeviceSettings(const LLSD& seed);
- /*virtual*/ void onOpen();
- /*virtual*/ void onClose(bool app_quitting);
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ void onClose(bool app_settings);
/*virtual*/ void draw();
void apply();
void cancel();
-
+private:
+ LLFloaterVoiceDeviceSettings(const LLSD& seed);
+
protected:
static void* createPanelVoiceDeviceSettings(void* user_data);
-
+
+protected:
LLPanelVoiceDeviceSettings* mDevicePanel;
};
diff --git a/indra/newview/llfloaterwater.cpp b/indra/newview/llfloaterwater.cpp
index 730c1393ca..66a1f6701f 100644
--- a/indra/newview/llfloaterwater.cpp
+++ b/indra/newview/llfloaterwater.cpp
@@ -37,6 +37,7 @@
#include "pipeline.h"
#include "llsky.h"
+#include "llfloaterreg.h"
#include "llsliderctrl.h"
#include "llspinctrl.h"
#include "llcolorswatch.h"
@@ -46,6 +47,7 @@
#include "llviewercamera.h"
#include "llcombobox.h"
#include "lllineeditor.h"
+#include "llnotificationsutil.h"
#include "llfloaterdaycycle.h"
#include "llboost.h"
#include "llmultisliderctrl.h"
@@ -62,19 +64,36 @@
#undef max
-LLFloaterWater* LLFloaterWater::sWaterMenu = NULL;
-
std::set<std::string> LLFloaterWater::sDefaultPresets;
-LLFloaterWater::LLFloaterWater() : LLFloater(std::string("water floater"))
+LLFloaterWater::LLFloaterWater(const LLSD& key)
+ : LLFloater(key)
+{
+ //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_water.xml");
+}
+
+LLFloaterWater::~LLFloaterWater()
{
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_water.xml");
+}
+BOOL LLFloaterWater::postBuild()
+{
+
+ std::string def_water = getString("WLDefaultWaterNames");
+
+ // no editing or deleting of the blank string
+ sDefaultPresets.insert("");
+ boost_tokenizer tokens(def_water, boost::char_separator<char>(":"));
+ for (boost_tokenizer::iterator token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
+ {
+ std::string tok(*token_iter);
+ sDefaultPresets.insert(tok);
+ }
// add the combo boxes
LLComboBox* comboBox = getChild<LLComboBox>("WaterPresetsCombo");
if(comboBox != NULL) {
-
+
std::map<std::string, LLWaterParamSet>::iterator mIt =
LLWaterParamManager::instance()->mParamList.begin();
for(; mIt != LLWaterParamManager::instance()->mParamList.end(); mIt++)
@@ -85,110 +104,63 @@ LLFloaterWater::LLFloaterWater() : LLFloater(std::string("water floater"))
// set defaults on combo boxes
comboBox->selectByValue(LLSD("Default"));
}
-
- std::string def_water = getString("WLDefaultWaterNames");
-
- // no editing or deleting of the blank string
- sDefaultPresets.insert("");
- boost_tokenizer tokens(def_water, boost::char_separator<char>(":"));
- for (boost_tokenizer::iterator token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
- {
- std::string tok(*token_iter);
- sDefaultPresets.insert(tok);
- }
-
// load it up
initCallbacks();
+ syncMenu();
+ return TRUE;
}
-
-LLFloaterWater::~LLFloaterWater()
-{
-}
-
void LLFloaterWater::initCallbacks(void) {
- // help buttons
- initHelpBtn("WaterFogColorHelp", "HelpWaterFogColor");
- initHelpBtn("WaterFogDensityHelp", "HelpWaterFogDensity");
- initHelpBtn("WaterUnderWaterFogModHelp", "HelpUnderWaterFogMod");
- initHelpBtn("WaterGlowHelp", "HelpWaterGlow");
- initHelpBtn("WaterNormalScaleHelp", "HelpWaterNormalScale");
- initHelpBtn("WaterFresnelScaleHelp", "HelpWaterFresnelScale");
- initHelpBtn("WaterFresnelOffsetHelp", "HelpWaterFresnelOffset");
-
- initHelpBtn("WaterBlurMultiplierHelp", "HelpWaterBlurMultiplier");
- initHelpBtn("WaterScaleBelowHelp", "HelpWaterScaleBelow");
- initHelpBtn("WaterScaleAboveHelp", "HelpWaterScaleAbove");
-
- initHelpBtn("WaterNormalMapHelp", "HelpWaterNormalMap");
- initHelpBtn("WaterWave1Help", "HelpWaterWave1");
- initHelpBtn("WaterWave2Help", "HelpWaterWave2");
-
LLWaterParamManager * param_mgr = LLWaterParamManager::instance();
- childSetCommitCallback("WaterFogColor", onWaterFogColorMoved, &param_mgr->mFogColor);
+ getChild<LLUICtrl>("WaterFogColor")->setCommitCallback(boost::bind(&LLFloaterWater::onWaterFogColorMoved, this, _1, &param_mgr->mFogColor));
//
- childSetCommitCallback("WaterGlow", onColorControlAMoved, &param_mgr->mFogColor);
+ getChild<LLUICtrl>("WaterGlow")->setCommitCallback(boost::bind(&LLFloaterWater::onColorControlAMoved, this, _1, &param_mgr->mFogColor));
// fog density
- childSetCommitCallback("WaterFogDensity", onExpFloatControlMoved, &param_mgr->mFogDensity);
- childSetCommitCallback("WaterUnderWaterFogMod", onFloatControlMoved, &param_mgr->mUnderWaterFogMod);
+ getChild<LLUICtrl>("WaterFogDensity")->setCommitCallback(boost::bind(&LLFloaterWater::onExpFloatControlMoved, this, _1, &param_mgr->mFogDensity));
+ getChild<LLUICtrl>("WaterUnderWaterFogMod")->setCommitCallback(boost::bind(&LLFloaterWater::onFloatControlMoved, this, _1, &param_mgr->mUnderWaterFogMod));
// blue density
- childSetCommitCallback("WaterNormalScaleX", onVector3ControlXMoved, &param_mgr->mNormalScale);
- childSetCommitCallback("WaterNormalScaleY", onVector3ControlYMoved, &param_mgr->mNormalScale);
- childSetCommitCallback("WaterNormalScaleZ", onVector3ControlZMoved, &param_mgr->mNormalScale);
+ getChild<LLUICtrl>("WaterNormalScaleX")->setCommitCallback(boost::bind(&LLFloaterWater::onVector3ControlXMoved, this, _1, &param_mgr->mNormalScale));
+ getChild<LLUICtrl>("WaterNormalScaleY")->setCommitCallback(boost::bind(&LLFloaterWater::onVector3ControlYMoved, this, _1, &param_mgr->mNormalScale));
+ getChild<LLUICtrl>("WaterNormalScaleZ")->setCommitCallback(boost::bind(&LLFloaterWater::onVector3ControlZMoved, this, _1, &param_mgr->mNormalScale));
// fresnel
- childSetCommitCallback("WaterFresnelScale", onFloatControlMoved, &param_mgr->mFresnelScale);
- childSetCommitCallback("WaterFresnelOffset", onFloatControlMoved, &param_mgr->mFresnelOffset);
+ getChild<LLUICtrl>("WaterFresnelScale")->setCommitCallback(boost::bind(&LLFloaterWater::onFloatControlMoved, this, _1, &param_mgr->mFresnelScale));
+ getChild<LLUICtrl>("WaterFresnelOffset")->setCommitCallback(boost::bind(&LLFloaterWater::onFloatControlMoved, this, _1, &param_mgr->mFresnelOffset));
// scale above/below
- childSetCommitCallback("WaterScaleAbove", onFloatControlMoved, &param_mgr->mScaleAbove);
- childSetCommitCallback("WaterScaleBelow", onFloatControlMoved, &param_mgr->mScaleBelow);
+ getChild<LLUICtrl>("WaterScaleAbove")->setCommitCallback(boost::bind(&LLFloaterWater::onFloatControlMoved, this, _1, &param_mgr->mScaleAbove));
+ getChild<LLUICtrl>("WaterScaleBelow")->setCommitCallback(boost::bind(&LLFloaterWater::onFloatControlMoved, this, _1, &param_mgr->mScaleBelow));
// blur mult
- childSetCommitCallback("WaterBlurMult", onFloatControlMoved, &param_mgr->mBlurMultiplier);
+ getChild<LLUICtrl>("WaterBlurMult")->setCommitCallback(boost::bind(&LLFloaterWater::onFloatControlMoved, this, _1, &param_mgr->mBlurMultiplier));
// Load/save
- LLComboBox* comboBox = getChild<LLComboBox>("WaterPresetsCombo");
-
- //childSetAction("WaterLoadPreset", onLoadPreset, comboBox);
- childSetAction("WaterNewPreset", onNewPreset, comboBox);
- childSetAction("WaterSavePreset", onSavePreset, comboBox);
- childSetAction("WaterDeletePreset", onDeletePreset, comboBox);
+// getChild<LLUICtrl>("WaterLoadPreset")->setCommitCallback(boost::bind(&LLFloaterWater::onLoadPreset, this));
+ getChild<LLUICtrl>("WaterNewPreset")->setCommitCallback(boost::bind(&LLFloaterWater::onNewPreset, this));
+ getChild<LLUICtrl>("WaterSavePreset")->setCommitCallback(boost::bind(&LLFloaterWater::onSavePreset, this));
+ getChild<LLUICtrl>("WaterDeletePreset")->setCommitCallback(boost::bind(&LLFloaterWater::onDeletePreset, this));
// wave direction
- childSetCommitCallback("WaterWave1DirX", onVector2ControlXMoved, &param_mgr->mWave1Dir);
- childSetCommitCallback("WaterWave1DirY", onVector2ControlYMoved, &param_mgr->mWave1Dir);
- childSetCommitCallback("WaterWave2DirX", onVector2ControlXMoved, &param_mgr->mWave2Dir);
- childSetCommitCallback("WaterWave2DirY", onVector2ControlYMoved, &param_mgr->mWave2Dir);
+ getChild<LLUICtrl>("WaterWave1DirX")->setCommitCallback(boost::bind(&LLFloaterWater::onVector2ControlXMoved, this, _1, &param_mgr->mWave1Dir));
+ getChild<LLUICtrl>("WaterWave1DirY")->setCommitCallback(boost::bind(&LLFloaterWater::onVector2ControlYMoved, this, _1, &param_mgr->mWave1Dir));
+ getChild<LLUICtrl>("WaterWave2DirX")->setCommitCallback(boost::bind(&LLFloaterWater::onVector2ControlXMoved, this, _1, &param_mgr->mWave2Dir));
+ getChild<LLUICtrl>("WaterWave2DirY")->setCommitCallback(boost::bind(&LLFloaterWater::onVector2ControlYMoved, this, _1, &param_mgr->mWave2Dir));
- comboBox->setCommitCallback(onChangePresetName);
+ getChild<LLUICtrl>("WaterPresetsCombo")->setCommitCallback(boost::bind(&LLFloaterWater::onChangePresetName, this, _1));
LLTextureCtrl* textCtrl = getChild<LLTextureCtrl>("WaterNormalMap");
textCtrl->setDefaultImageAssetID(DEFAULT_WATER_NORMAL);
- childSetCommitCallback("WaterNormalMap", onNormalMapPicked, NULL);
-}
-
-void LLFloaterWater::onClickHelp(void* data)
-{
- LLFloaterWater* self = LLFloaterWater::instance();
-
- const std::string* xml_alert = (std::string*)data;
- LLNotifications::instance().add(self->contextualNotification(*xml_alert));
-}
-
-void LLFloaterWater::initHelpBtn(const std::string& name, const std::string& xml_alert)
-{
- childSetAction(name, onClickHelp, new std::string(xml_alert));
+ getChild<LLUICtrl>("WaterNormalMap")->setCommitCallback(boost::bind(&LLFloaterWater::onNormalMapPicked, this, _1));
}
bool LLFloaterWater::newPromptCallback(const LLSD& notification, const LLSD& response)
{
std::string text = response["message"].asString();
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if(text == "")
{
@@ -196,7 +168,7 @@ bool LLFloaterWater::newPromptCallback(const LLSD& notification, const LLSD& res
}
if(option == 0) {
- LLComboBox* comboBox = sWaterMenu->getChild<LLComboBox>( "WaterPresetsCombo");
+ LLComboBox* comboBox = getChild<LLComboBox>( "WaterPresetsCombo");
LLWaterParamManager * param_mgr = LLWaterParamManager::instance();
@@ -220,7 +192,7 @@ bool LLFloaterWater::newPromptCallback(const LLSD& notification, const LLSD& res
}
else
{
- LLNotifications::instance().add("ExistsWaterPresetAlert");
+ LLNotificationsUtil::add("ExistsWaterPresetAlert");
}
}
return false;
@@ -240,7 +212,7 @@ void LLFloaterWater::syncMenu()
LLColor4 col = param_mgr->getFogColor();
childSetValue("WaterGlow", col.mV[3]);
col.mV[3] = 1.0f;
- LLColorSwatchCtrl* colCtrl = sWaterMenu->getChild<LLColorSwatchCtrl>("WaterFogColor");
+ LLColorSwatchCtrl* colCtrl = getChild<LLColorSwatchCtrl>("WaterFogColor");
colCtrl->set(col);
@@ -285,56 +257,15 @@ void LLFloaterWater::syncMenu()
childSetValue("WaterWave2DirX", param_mgr->mWave2Dir.mX);
childSetValue("WaterWave2DirY", param_mgr->mWave2Dir.mY);
- LLTextureCtrl* textCtrl = sWaterMenu->getChild<LLTextureCtrl>("WaterNormalMap");
+ LLTextureCtrl* textCtrl = getChild<LLTextureCtrl>("WaterNormalMap");
textCtrl->setImageAssetID(param_mgr->getNormalMapID());
}
-// static
-LLFloaterWater* LLFloaterWater::instance()
-{
- if (!sWaterMenu)
- {
- sWaterMenu = new LLFloaterWater();
- sWaterMenu->open();
- sWaterMenu->setFocus(TRUE);
- }
- return sWaterMenu;
-}
-void LLFloaterWater::show()
-{
- LLFloaterWater* water = instance();
- water->syncMenu();
-
- // comment in if you want the menu to rebuild each time
- //LLUICtrlFactory::getInstance()->buildFloater(water, "floater_water.xml");
- //water->initCallbacks();
-
- water->open();
-}
-
-bool LLFloaterWater::isOpen()
-{
- if (sWaterMenu != NULL) {
- return true;
- }
- return false;
-}
-
-// virtual
-void LLFloaterWater::onClose(bool app_quitting)
-{
- if (sWaterMenu)
- {
- sWaterMenu->setVisible(FALSE);
- }
-}
-
// vector control callbacks
-void LLFloaterWater::onVector3ControlXMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWater::onVector3ControlXMoved(LLUICtrl* ctrl, WaterVector3Control* vectorControl)
{
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- WaterVector3Control * vectorControl = static_cast<WaterVector3Control *>(userData);
vectorControl->mX = sldrCtrl->getValueF32();
@@ -344,10 +275,9 @@ void LLFloaterWater::onVector3ControlXMoved(LLUICtrl* ctrl, void* userData)
}
// vector control callbacks
-void LLFloaterWater::onVector3ControlYMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWater::onVector3ControlYMoved(LLUICtrl* ctrl, WaterVector3Control* vectorControl)
{
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- WaterVector3Control * vectorControl = static_cast<WaterVector3Control *>(userData);
vectorControl->mY = sldrCtrl->getValueF32();
@@ -357,10 +287,9 @@ void LLFloaterWater::onVector3ControlYMoved(LLUICtrl* ctrl, void* userData)
}
// vector control callbacks
-void LLFloaterWater::onVector3ControlZMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWater::onVector3ControlZMoved(LLUICtrl* ctrl, WaterVector3Control* vectorControl)
{
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- WaterVector3Control * vectorControl = static_cast<WaterVector3Control *>(userData);
vectorControl->mZ = sldrCtrl->getValueF32();
@@ -371,10 +300,9 @@ void LLFloaterWater::onVector3ControlZMoved(LLUICtrl* ctrl, void* userData)
// vector control callbacks
-void LLFloaterWater::onVector2ControlXMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWater::onVector2ControlXMoved(LLUICtrl* ctrl, WaterVector2Control* vectorControl)
{
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- WaterVector2Control * vectorControl = static_cast<WaterVector2Control *>(userData);
vectorControl->mX = sldrCtrl->getValueF32();
@@ -384,10 +312,9 @@ void LLFloaterWater::onVector2ControlXMoved(LLUICtrl* ctrl, void* userData)
}
// vector control callbacks
-void LLFloaterWater::onVector2ControlYMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWater::onVector2ControlYMoved(LLUICtrl* ctrl, WaterVector2Control* vectorControl)
{
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- WaterVector2Control * vectorControl = static_cast<WaterVector2Control *>(userData);
vectorControl->mY = sldrCtrl->getValueF32();
@@ -397,10 +324,9 @@ void LLFloaterWater::onVector2ControlYMoved(LLUICtrl* ctrl, void* userData)
}
// color control callbacks
-void LLFloaterWater::onColorControlRMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWater::onColorControlRMoved(LLUICtrl* ctrl, WaterColorControl* colorControl)
{
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- WaterColorControl * colorControl = static_cast<WaterColorControl *>(userData);
colorControl->mR = sldrCtrl->getValueF32();
@@ -413,7 +339,7 @@ void LLFloaterWater::onColorControlRMoved(LLUICtrl* ctrl, void* userData)
std::string name = colorControl->mSliderName;
name.append("I");
- sWaterMenu->childSetValue(name, colorControl->mR);
+ childSetValue(name, colorControl->mR);
}
colorControl->update(LLWaterParamManager::instance()->mCurParams);
@@ -421,10 +347,9 @@ void LLFloaterWater::onColorControlRMoved(LLUICtrl* ctrl, void* userData)
LLWaterParamManager::instance()->propagateParameters();
}
-void LLFloaterWater::onColorControlGMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWater::onColorControlGMoved(LLUICtrl* ctrl, WaterColorControl* colorControl)
{
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- WaterColorControl * colorControl = static_cast<WaterColorControl *>(userData);
colorControl->mG = sldrCtrl->getValueF32();
@@ -437,7 +362,7 @@ void LLFloaterWater::onColorControlGMoved(LLUICtrl* ctrl, void* userData)
std::string name = colorControl->mSliderName;
name.append("I");
- sWaterMenu->childSetValue(name, colorControl->mG);
+ childSetValue(name, colorControl->mG);
}
@@ -446,10 +371,9 @@ void LLFloaterWater::onColorControlGMoved(LLUICtrl* ctrl, void* userData)
LLWaterParamManager::instance()->propagateParameters();
}
-void LLFloaterWater::onColorControlBMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWater::onColorControlBMoved(LLUICtrl* ctrl, WaterColorControl* colorControl)
{
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- WaterColorControl * colorControl = static_cast<WaterColorControl *>(userData);
colorControl->mB = sldrCtrl->getValueF32();
@@ -462,7 +386,7 @@ void LLFloaterWater::onColorControlBMoved(LLUICtrl* ctrl, void* userData)
std::string name = colorControl->mSliderName;
name.append("I");
- sWaterMenu->childSetValue(name, colorControl->mB);
+ childSetValue(name, colorControl->mB);
}
colorControl->update(LLWaterParamManager::instance()->mCurParams);
@@ -470,10 +394,9 @@ void LLFloaterWater::onColorControlBMoved(LLUICtrl* ctrl, void* userData)
LLWaterParamManager::instance()->propagateParameters();
}
-void LLFloaterWater::onColorControlAMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWater::onColorControlAMoved(LLUICtrl* ctrl, WaterColorControl* colorControl)
{
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- WaterColorControl * colorControl = static_cast<WaterColorControl *>(userData);
colorControl->mA = sldrCtrl->getValueF32();
@@ -483,10 +406,9 @@ void LLFloaterWater::onColorControlAMoved(LLUICtrl* ctrl, void* userData)
}
-void LLFloaterWater::onColorControlIMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWater::onColorControlIMoved(LLUICtrl* ctrl, WaterColorControl* colorControl)
{
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- WaterColorControl * colorControl = static_cast<WaterColorControl *>(userData);
colorControl->mI = sldrCtrl->getValueF32();
@@ -533,9 +455,9 @@ void LLFloaterWater::onColorControlIMoved(LLUICtrl* ctrl, void* userData)
}
// set the sliders to the new vals
- sWaterMenu->childSetValue(rName, colorControl->mR);
- sWaterMenu->childSetValue(gName, colorControl->mG);
- sWaterMenu->childSetValue(bName, colorControl->mB);
+ childSetValue(rName, colorControl->mR);
+ childSetValue(gName, colorControl->mG);
+ childSetValue(bName, colorControl->mB);
}
// now update the current parameters and send them to shaders
@@ -543,10 +465,9 @@ void LLFloaterWater::onColorControlIMoved(LLUICtrl* ctrl, void* userData)
LLWaterParamManager::instance()->propagateParameters();
}
-void LLFloaterWater::onExpFloatControlMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWater::onExpFloatControlMoved(LLUICtrl* ctrl, WaterExpFloatControl* expFloatControl)
{
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- WaterExpFloatControl * expFloatControl = static_cast<WaterExpFloatControl *>(userData);
F32 val = sldrCtrl->getValueF32();
expFloatControl->mExp = val;
@@ -556,50 +477,40 @@ void LLFloaterWater::onExpFloatControlMoved(LLUICtrl* ctrl, void* userData)
LLWaterParamManager::instance()->propagateParameters();
}
-void LLFloaterWater::onFloatControlMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWater::onFloatControlMoved(LLUICtrl* ctrl, WaterFloatControl* floatControl)
{
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- WaterFloatControl * floatControl = static_cast<WaterFloatControl *>(userData);
floatControl->mX = sldrCtrl->getValueF32() / floatControl->mMult;
floatControl->update(LLWaterParamManager::instance()->mCurParams);
LLWaterParamManager::instance()->propagateParameters();
}
-void LLFloaterWater::onWaterFogColorMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWater::onWaterFogColorMoved(LLUICtrl* ctrl, WaterColorControl* colorControl)
{
LLColorSwatchCtrl* swatch = static_cast<LLColorSwatchCtrl*>(ctrl);
- WaterColorControl * colorControl = static_cast<WaterColorControl *>(userData);
*colorControl = swatch->get();
colorControl->update(LLWaterParamManager::instance()->mCurParams);
LLWaterParamManager::instance()->propagateParameters();
}
-void LLFloaterWater::onBoolToggle(LLUICtrl* ctrl, void* userData)
-{
- LLCheckBoxCtrl* cbCtrl = static_cast<LLCheckBoxCtrl*>(ctrl);
-
- bool value = cbCtrl->get();
- (*(static_cast<BOOL *>(userData))) = value;
-}
-
-void LLFloaterWater::onNormalMapPicked(LLUICtrl* ctrl, void* userData)
+void LLFloaterWater::onNormalMapPicked(LLUICtrl* ctrl)
{
LLTextureCtrl* textCtrl = static_cast<LLTextureCtrl*>(ctrl);
LLUUID textID = textCtrl->getImageAssetID();
LLWaterParamManager::instance()->setNormalMapID(textID);
}
-void LLFloaterWater::onNewPreset(void* userData)
+void LLFloaterWater::onNewPreset()
{
- LLNotifications::instance().add("NewWaterPreset", LLSD(), LLSD(), newPromptCallback);
+ LLNotificationsUtil::add("NewWaterPreset", LLSD(), LLSD(), boost::bind(&LLFloaterWater::newPromptCallback, this, _1, _2));
}
-void LLFloaterWater::onSavePreset(void* userData)
+void LLFloaterWater::onSavePreset()
{
// get the name
- LLComboBox* comboBox = sWaterMenu->getChild<LLComboBox>("WaterPresetsCombo");
+ LLComboBox* comboBox = getChild<LLComboBox>("WaterPresetsCombo");
// don't save the empty name
if(comboBox->getSelectedItemLabel() == "")
@@ -615,16 +526,16 @@ void LLFloaterWater::onSavePreset(void* userData)
comboBox->getSelectedItemLabel());
if(sIt != sDefaultPresets.end() && !gSavedSettings.getBOOL("WaterEditPresets"))
{
- LLNotifications::instance().add("WLNoEditDefault");
+ LLNotificationsUtil::add("WLNoEditDefault");
return;
}
- LLNotifications::instance().add("WLSavePresetAlert", LLSD(), LLSD(), saveAlertCallback);
+ LLNotificationsUtil::add("WLSavePresetAlert", LLSD(), LLSD(), boost::bind(&LLFloaterWater::saveAlertCallback, this, _1, _2));
}
bool LLFloaterWater::saveAlertCallback(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
// if they choose save, do it. Otherwise, don't do anything
if(option == 0)
{
@@ -640,9 +551,9 @@ bool LLFloaterWater::saveAlertCallback(const LLSD& notification, const LLSD& res
return false;
}
-void LLFloaterWater::onDeletePreset(void* userData)
+void LLFloaterWater::onDeletePreset()
{
- LLComboBox* combo_box = sWaterMenu->getChild<LLComboBox>("WaterPresetsCombo");
+ LLComboBox* combo_box = getChild<LLComboBox>("WaterPresetsCombo");
if(combo_box->getSelectedValue().asString() == "")
{
@@ -651,23 +562,22 @@ void LLFloaterWater::onDeletePreset(void* userData)
LLSD args;
args["SKY"] = combo_box->getSelectedValue().asString();
- LLNotifications::instance().add("WLDeletePresetAlert", args, LLSD(), deleteAlertCallback);
+ LLNotificationsUtil::add("WLDeletePresetAlert", args, LLSD(), boost::bind(&LLFloaterWater::deleteAlertCallback, this, _1, _2));
}
bool LLFloaterWater::deleteAlertCallback(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
// if they choose delete, do it. Otherwise, don't do anything
if(option == 0)
{
- LLComboBox* combo_box = sWaterMenu->getChild<LLComboBox>("WaterPresetsCombo");
- LLFloaterDayCycle* day_cycle = NULL;
+ LLComboBox* combo_box = getChild<LLComboBox>("WaterPresetsCombo");
+ LLFloaterDayCycle* day_cycle = LLFloaterReg::findTypedInstance<LLFloaterDayCycle>("env_day_cycle");
LLComboBox* key_combo = NULL;
LLMultiSliderCtrl* mult_sldr = NULL;
- if(LLFloaterDayCycle::isOpen())
+ if (day_cycle)
{
- day_cycle = LLFloaterDayCycle::instance();
key_combo = day_cycle->getChild<LLComboBox>("WaterKeyPresets");
mult_sldr = day_cycle->getChild<LLMultiSliderCtrl>("WaterDayCycleKeys");
}
@@ -678,7 +588,7 @@ bool LLFloaterWater::deleteAlertCallback(const LLSD& notification, const LLSD& r
std::set<std::string>::iterator sIt = sDefaultPresets.find(name);
if(sIt != sDefaultPresets.end())
{
- LLNotifications::instance().add("WaterNoEditDefault");
+ LLNotificationsUtil::add("WaterNoEditDefault");
return false;
}
@@ -712,17 +622,13 @@ bool LLFloaterWater::deleteAlertCallback(const LLSD& notification, const LLSD& r
}
-void LLFloaterWater::onChangePresetName(LLUICtrl* ctrl, void * userData)
+void LLFloaterWater::onChangePresetName(LLUICtrl* ctrl)
{
- LLComboBox * combo_box = static_cast<LLComboBox*>(ctrl);
-
- if(combo_box->getSimple() == "")
+ std::string data = ctrl->getValue().asString();
+ if(!data.empty())
{
- return;
+ LLWaterParamManager::instance()->loadPreset(data);
+ syncMenu();
}
-
- LLWaterParamManager::instance()->loadPreset(
- combo_box->getSelectedValue().asString());
- sWaterMenu->syncMenu();
}
diff --git a/indra/newview/llfloaterwater.h b/indra/newview/llfloaterwater.h
index 774d5c5a75..0ea2436dbe 100644
--- a/indra/newview/llfloaterwater.h
+++ b/indra/newview/llfloaterwater.h
@@ -42,91 +42,70 @@
#include <vector>
#include "llwlparamset.h"
+struct WaterVector2Control;
+struct WaterVector3Control;
struct WaterColorControl;
-struct WaterloatControl;
-
+struct WaterFloatControl;
+struct WaterExpFloatControl;
/// Menuing system for all of windlight's functionality
class LLFloaterWater : public LLFloater
{
public:
- LLFloaterWater();
+ LLFloaterWater(const LLSD& key);
virtual ~LLFloaterWater();
-
+ /*virtual*/ BOOL postBuild();
/// initialize all
void initCallbacks(void);
- /// one and one instance only
- static LLFloaterWater* instance();
-
- // help button stuff
- static void onClickHelp(void* data);
- void initHelpBtn(const std::string& name, const std::string& xml_alert);
-
- static bool newPromptCallback(const LLSD& notification, const LLSD& response);
+ bool newPromptCallback(const LLSD& notification, const LLSD& response);
/// general purpose callbacks for dealing with color controllers
- static void onColorControlRMoved(LLUICtrl* ctrl, void* userData);
- static void onColorControlGMoved(LLUICtrl* ctrl, void* userData);
- static void onColorControlBMoved(LLUICtrl* ctrl, void* userData);
- static void onColorControlAMoved(LLUICtrl* ctrl, void* userData);
- static void onColorControlIMoved(LLUICtrl* ctrl, void* userData);
-
- static void onVector3ControlXMoved(LLUICtrl* ctrl, void* userData);
- static void onVector3ControlYMoved(LLUICtrl* ctrl, void* userData);
- static void onVector3ControlZMoved(LLUICtrl* ctrl, void* userData);
-
- static void onVector2ControlXMoved(LLUICtrl* ctrl, void* userData);
- static void onVector2ControlYMoved(LLUICtrl* ctrl, void* userData);
-
- static void onFloatControlMoved(LLUICtrl* ctrl, void* userData);
-
- static void onExpFloatControlMoved(LLUICtrl* ctrl, void* userData);
+ void onColorControlRMoved(LLUICtrl* ctrl, WaterColorControl* colorControl);
+ void onColorControlGMoved(LLUICtrl* ctrl, WaterColorControl* colorControl);
+ void onColorControlBMoved(LLUICtrl* ctrl, WaterColorControl* colorControl);
+ void onColorControlAMoved(LLUICtrl* ctrl, WaterColorControl* colorControl);
+ void onColorControlIMoved(LLUICtrl* ctrl, WaterColorControl* colorControl);
+
+ void onVector3ControlXMoved(LLUICtrl* ctrl, WaterVector3Control* vectorControl);
+ void onVector3ControlYMoved(LLUICtrl* ctrl, WaterVector3Control* vectorControl);
+ void onVector3ControlZMoved(LLUICtrl* ctrl, WaterVector3Control* vectorControl);
+
+ void onVector2ControlXMoved(LLUICtrl* ctrl, WaterVector2Control* vectorControl);
+ void onVector2ControlYMoved(LLUICtrl* ctrl, WaterVector2Control* vectorControl);
+
+ void onFloatControlMoved(LLUICtrl* ctrl, WaterFloatControl* floatControl);
- static void onWaterFogColorMoved(LLUICtrl* ctrl, void* userData);
+ void onExpFloatControlMoved(LLUICtrl* ctrl, WaterExpFloatControl* expFloatControl);
- static void onBoolToggle(LLUICtrl* ctrl, void* userData);
+ void onWaterFogColorMoved(LLUICtrl* ctrl, WaterColorControl* colorControl);
/// handle if they choose a new normal map
- static void onNormalMapPicked(LLUICtrl* ctrl, void* userData);
+ void onNormalMapPicked(LLUICtrl* ctrl);
/// when user hits the load preset button
- static void onNewPreset(void* userData);
+ void onNewPreset();
/// when user hits the save preset button
- static void onSavePreset(void* userData);
+ void onSavePreset();
/// prompts a user when overwriting a preset
- static bool saveAlertCallback(const LLSD& notification, const LLSD& response);
+ bool saveAlertCallback(const LLSD& notification, const LLSD& response);
/// when user hits the save preset button
- static void onDeletePreset(void* userData);
+ void onDeletePreset();
/// prompts a user when overwriting a preset
- static bool deleteAlertCallback(const LLSD& notification, const LLSD& response);
+ bool deleteAlertCallback(const LLSD& notification, const LLSD& response);
/// what to do when you change the preset name
- static void onChangePresetName(LLUICtrl* ctrl, void* userData);
-
- //// menu management
-
- /// show off our menu
- static void show();
-
- /// return if the menu exists or not
- static bool isOpen();
-
- /// stuff to do on exit
- virtual void onClose(bool app_quitting);
+ void onChangePresetName(LLUICtrl* ctrl);
/// sync up sliders with parameters
void syncMenu();
private:
- // one instance on the inside
- static LLFloaterWater* sWaterMenu;
-
static std::set<std::string> sDefaultPresets;
};
diff --git a/indra/newview/llfloaterwhitelistentry.cpp b/indra/newview/llfloaterwhitelistentry.cpp
new file mode 100644
index 0000000000..705c8afd00
--- /dev/null
+++ b/indra/newview/llfloaterwhitelistentry.cpp
@@ -0,0 +1,98 @@
+/**
+ * @file llfloaterwhitelistentry.cpp
+ * @brief LLFloaterWhistListEntry class implementation
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterreg.h"
+#include "llfloatermediasettings.h"
+#include "llfloaterwhitelistentry.h"
+#include "llpanelmediasettingssecurity.h"
+#include "lluictrlfactory.h"
+#include "llwindow.h"
+#include "llviewerwindow.h"
+#include "lllineeditor.h"
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+LLFloaterWhiteListEntry::LLFloaterWhiteListEntry( const LLSD& key ) :
+ LLFloater(key)
+{
+// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_whitelist_entry.xml");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+LLFloaterWhiteListEntry::~LLFloaterWhiteListEntry()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLFloaterWhiteListEntry::postBuild()
+{
+ mWhiteListEdit = getChild<LLLineEditor>("whitelist_entry");
+
+ childSetAction("cancel_btn", onBtnCancel, this);
+ childSetAction("ok_btn", onBtnOK, this);
+
+ setDefaultBtn("ok_btn");
+
+ return TRUE;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// static
+void LLFloaterWhiteListEntry::onBtnOK( void* userdata )
+{
+ LLFloaterWhiteListEntry *self =(LLFloaterWhiteListEntry *)userdata;
+
+ LLPanelMediaSettingsSecurity* panel = LLFloaterReg::getTypedInstance<LLFloaterMediaSettings>("media_settings")->getPanelSecurity();
+ if ( panel )
+ {
+ std::string white_list_item = self->mWhiteListEdit->getText();
+
+ panel->addWhiteListEntry( white_list_item );
+ panel->updateWhitelistEnableStatus();
+ };
+
+ self->closeFloater();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// static
+void LLFloaterWhiteListEntry::onBtnCancel( void* userdata )
+{
+ LLFloaterWhiteListEntry *self =(LLFloaterWhiteListEntry *)userdata;
+
+ self->closeFloater();
+}
diff --git a/indra/newview/llfloaterevent.h b/indra/newview/llfloaterwhitelistentry.h
index 8f448b5fa2..8ab5fb78b9 100644
--- a/indra/newview/llfloaterevent.h
+++ b/indra/newview/llfloaterwhitelistentry.h
@@ -1,8 +1,6 @@
-/**
- * @file llfloaterevent.h
- * @brief Event information as shown in a floating window from
- * secondlife:// command handler.
- * Just a wrapper for LLPanelEvent.
+/**
+ * @file llfloaterwhitelistentry.h
+ * @brief LLFloaterWhiteListEntry class definition
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
@@ -32,29 +30,27 @@
* $/LicenseInfo$
*/
-#ifndef LL_LLFLOATEREVENT_H
-#define LL_LLFLOATEREVENT_H
+#ifndef LL_LLFLOATERWHITELISTENTRY_H
+#define LL_LLFLOATERWHITELISTENTRY_H
#include "llfloater.h"
-class LLPanelEvent;
+class LLLineEditor;
-class LLFloaterEventInfo : public LLFloater
+class LLFloaterWhiteListEntry :
+ public LLFloater
{
-public:
- LLFloaterEventInfo(const std::string& name, const U32 event_id );
- /*virtual*/ ~LLFloaterEventInfo();
-
- void displayEventInfo(const U32 event_id);
-
- static LLFloaterEventInfo* show(const U32 event_id);
+ public:
+ LLFloaterWhiteListEntry(const LLSD& key);
+ ~LLFloaterWhiteListEntry();
- static void* createEventDetail(void* userdata);
+ BOOL postBuild();
-private:
- U32 mEventID; // for which event is this window?
- LLPanelEvent* mPanelEventp;
+ private:
+ LLLineEditor* mWhiteListEdit;
+ static void onBtnOK(void*);
+ static void onBtnCancel(void*);
};
-#endif // LL_LLFLOATEREVENT_H
+#endif // LL_LLFLOATERWHITELISTENTRY_H
diff --git a/indra/newview/llfloaterwindlight.cpp b/indra/newview/llfloaterwindlight.cpp
index 98b315795a..ea6fda7303 100644
--- a/indra/newview/llfloaterwindlight.cpp
+++ b/indra/newview/llfloaterwindlight.cpp
@@ -37,9 +37,11 @@
#include "pipeline.h"
#include "llsky.h"
+#include "llfloaterreg.h"
#include "llsliderctrl.h"
#include "llmultislider.h"
#include "llmultisliderctrl.h"
+#include "llnotificationsutil.h"
#include "llspinctrl.h"
#include "llcheckboxctrl.h"
#include "lluictrlfactory.h"
@@ -58,24 +60,44 @@
#include "llwlparamset.h"
#include "llwlparammanager.h"
#include "llpostprocess.h"
+#include "lltabcontainer.h"
-#undef max
-LLFloaterWindLight* LLFloaterWindLight::sWindLight = NULL;
+#undef max
std::set<std::string> LLFloaterWindLight::sDefaultPresets;
static const F32 WL_SUN_AMBIENT_SLIDER_SCALE = 3.0f;
-LLFloaterWindLight::LLFloaterWindLight() : LLFloater(std::string("windlight floater"))
+LLFloaterWindLight::LLFloaterWindLight(const LLSD& key)
+ : LLFloater(key)
{
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_windlight_options.xml");
-
+ //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_windlight_options.xml");
+}
+
+LLFloaterWindLight::~LLFloaterWindLight()
+{
+}
+
+BOOL LLFloaterWindLight::postBuild()
+{
+ // add the list of presets
+ std::string def_days = getString("WLDefaultSkyNames");
+
+ // no editing or deleting of the blank string
+ sDefaultPresets.insert("");
+ boost_tokenizer tokens(def_days, boost::char_separator<char>(":"));
+ for (boost_tokenizer::iterator token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
+ {
+ std::string tok(*token_iter);
+ sDefaultPresets.insert(tok);
+ }
+
// add the combo boxes
LLComboBox* comboBox = getChild<LLComboBox>("WLPresetsCombo");
if(comboBox != NULL) {
-
+
std::map<std::string, LLWLParamSet>::iterator mIt =
LLWLParamManager::instance()->mParamList.begin();
for(; mIt != LLWLParamManager::instance()->mParamList.end(); mIt++)
@@ -89,164 +111,107 @@ LLFloaterWindLight::LLFloaterWindLight() : LLFloater(std::string("windlight floa
// set defaults on combo boxes
comboBox->selectByValue(LLSD("Default"));
}
-
- // add the list of presets
- std::string def_days = getString("WLDefaultSkyNames");
-
- // no editing or deleting of the blank string
- sDefaultPresets.insert("");
- boost_tokenizer tokens(def_days, boost::char_separator<char>(":"));
- for (boost_tokenizer::iterator token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
- {
- std::string tok(*token_iter);
- sDefaultPresets.insert(tok);
- }
-
// load it up
initCallbacks();
-}
-LLFloaterWindLight::~LLFloaterWindLight()
-{
+ syncMenu();
+
+ return TRUE;
}
-
void LLFloaterWindLight::initCallbacks(void) {
- // help buttons
- initHelpBtn("WLBlueHorizonHelp", "HelpBlueHorizon");
- initHelpBtn("WLHazeHorizonHelp", "HelpHazeHorizon");
- initHelpBtn("WLBlueDensityHelp", "HelpBlueDensity");
- initHelpBtn("WLHazeDensityHelp", "HelpHazeDensity");
-
- initHelpBtn("WLDensityMultHelp", "HelpDensityMult");
- initHelpBtn("WLDistanceMultHelp", "HelpDistanceMult");
- initHelpBtn("WLMaxAltitudeHelp", "HelpMaxAltitude");
-
- initHelpBtn("WLSunlightColorHelp", "HelpSunlightColor");
- initHelpBtn("WLAmbientHelp", "HelpSunAmbient");
- initHelpBtn("WLSunGlowHelp", "HelpSunGlow");
- initHelpBtn("WLTimeOfDayHelp", "HelpTimeOfDay");
- initHelpBtn("WLEastAngleHelp", "HelpEastAngle");
-
- initHelpBtn("WLSceneGammaHelp", "HelpSceneGamma");
- initHelpBtn("WLStarBrightnessHelp", "HelpStarBrightness");
-
- initHelpBtn("WLCloudColorHelp", "HelpCloudColor");
- initHelpBtn("WLCloudDetailHelp", "HelpCloudDetail");
- initHelpBtn("WLCloudDensityHelp", "HelpCloudDensity");
- initHelpBtn("WLCloudCoverageHelp", "HelpCloudCoverage");
-
- initHelpBtn("WLCloudScaleHelp", "HelpCloudScale");
- initHelpBtn("WLCloudScrollXHelp", "HelpCloudScrollX");
- initHelpBtn("WLCloudScrollYHelp", "HelpCloudScrollY");
-
- initHelpBtn("WLClassicCloudsHelp", "HelpClassicClouds");
-
LLWLParamManager * param_mgr = LLWLParamManager::instance();
// blue horizon
- childSetCommitCallback("WLBlueHorizonR", onColorControlRMoved, &param_mgr->mBlueHorizon);
- childSetCommitCallback("WLBlueHorizonG", onColorControlGMoved, &param_mgr->mBlueHorizon);
- childSetCommitCallback("WLBlueHorizonB", onColorControlBMoved, &param_mgr->mBlueHorizon);
- childSetCommitCallback("WLBlueHorizonI", onColorControlIMoved, &param_mgr->mBlueHorizon);
+ getChild<LLUICtrl>("WLBlueHorizonR")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlRMoved, this, _1, &param_mgr->mBlueHorizon));
+ getChild<LLUICtrl>("WLBlueHorizonG")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlGMoved, this, _1, &param_mgr->mBlueHorizon));
+ getChild<LLUICtrl>("WLBlueHorizonB")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlBMoved, this, _1, &param_mgr->mBlueHorizon));
+ getChild<LLUICtrl>("WLBlueHorizonI")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlIMoved, this, _1, &param_mgr->mBlueHorizon));
// haze density, horizon, mult, and altitude
- childSetCommitCallback("WLHazeDensity", onColorControlRMoved, &param_mgr->mHazeDensity);
- childSetCommitCallback("WLHazeHorizon", onColorControlRMoved, &param_mgr->mHazeHorizon);
- childSetCommitCallback("WLDensityMult", onFloatControlMoved, &param_mgr->mDensityMult);
- childSetCommitCallback("WLMaxAltitude", onFloatControlMoved, &param_mgr->mMaxAlt);
+ getChild<LLUICtrl>("WLHazeDensity")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlRMoved, this, _1, &param_mgr->mHazeDensity));
+ getChild<LLUICtrl>("WLHazeHorizon")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlRMoved, this, _1, &param_mgr->mHazeHorizon));
+ getChild<LLUICtrl>("WLDensityMult")->setCommitCallback(boost::bind(&LLFloaterWindLight::onFloatControlMoved, this, _1, &param_mgr->mDensityMult));
+ getChild<LLUICtrl>("WLMaxAltitude")->setCommitCallback(boost::bind(&LLFloaterWindLight::onFloatControlMoved, this, _1, &param_mgr->mMaxAlt));
// blue density
- childSetCommitCallback("WLBlueDensityR", onColorControlRMoved, &param_mgr->mBlueDensity);
- childSetCommitCallback("WLBlueDensityG", onColorControlGMoved, &param_mgr->mBlueDensity);
- childSetCommitCallback("WLBlueDensityB", onColorControlBMoved, &param_mgr->mBlueDensity);
- childSetCommitCallback("WLBlueDensityI", onColorControlIMoved, &param_mgr->mBlueDensity);
+ getChild<LLUICtrl>("WLBlueDensityR")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlRMoved, this, _1, &param_mgr->mBlueDensity));
+ getChild<LLUICtrl>("WLBlueDensityG")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlGMoved, this, _1, &param_mgr->mBlueDensity));
+ getChild<LLUICtrl>("WLBlueDensityB")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlBMoved, this, _1, &param_mgr->mBlueDensity));
+ getChild<LLUICtrl>("WLBlueDensityI")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlIMoved, this, _1, &param_mgr->mBlueDensity));
// Lighting
// sunlight
- childSetCommitCallback("WLSunlightR", onColorControlRMoved, &param_mgr->mSunlight);
- childSetCommitCallback("WLSunlightG", onColorControlGMoved, &param_mgr->mSunlight);
- childSetCommitCallback("WLSunlightB", onColorControlBMoved, &param_mgr->mSunlight);
- childSetCommitCallback("WLSunlightI", onColorControlIMoved, &param_mgr->mSunlight);
+ getChild<LLUICtrl>("WLSunlightR")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlRMoved, this, _1, &param_mgr->mSunlight));
+ getChild<LLUICtrl>("WLSunlightG")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlGMoved, this, _1, &param_mgr->mSunlight));
+ getChild<LLUICtrl>("WLSunlightB")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlBMoved, this, _1, &param_mgr->mSunlight));
+ getChild<LLUICtrl>("WLSunlightI")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlIMoved, this, _1, &param_mgr->mSunlight));
// glow
- childSetCommitCallback("WLGlowR", onGlowRMoved, &param_mgr->mGlow);
- childSetCommitCallback("WLGlowB", onGlowBMoved, &param_mgr->mGlow);
+ getChild<LLUICtrl>("WLGlowR")->setCommitCallback(boost::bind(&LLFloaterWindLight::onGlowRMoved, this, _1, &param_mgr->mGlow));
+ getChild<LLUICtrl>("WLGlowB")->setCommitCallback(boost::bind(&LLFloaterWindLight::onGlowBMoved, this, _1, &param_mgr->mGlow));
// ambient
- childSetCommitCallback("WLAmbientR", onColorControlRMoved, &param_mgr->mAmbient);
- childSetCommitCallback("WLAmbientG", onColorControlGMoved, &param_mgr->mAmbient);
- childSetCommitCallback("WLAmbientB", onColorControlBMoved, &param_mgr->mAmbient);
- childSetCommitCallback("WLAmbientI", onColorControlIMoved, &param_mgr->mAmbient);
+ getChild<LLUICtrl>("WLAmbientR")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlRMoved, this, _1, &param_mgr->mAmbient));
+ getChild<LLUICtrl>("WLAmbientG")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlGMoved, this, _1, &param_mgr->mAmbient));
+ getChild<LLUICtrl>("WLAmbientB")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlBMoved, this, _1, &param_mgr->mAmbient));
+ getChild<LLUICtrl>("WLAmbientI")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlIMoved, this, _1, &param_mgr->mAmbient));
// time of day
- childSetCommitCallback("WLSunAngle", onSunMoved, &param_mgr->mLightnorm);
- childSetCommitCallback("WLEastAngle", onSunMoved, &param_mgr->mLightnorm);
+ getChild<LLUICtrl>("WLSunAngle")->setCommitCallback(boost::bind(&LLFloaterWindLight::onSunMoved, this, _1, &param_mgr->mLightnorm));
+ getChild<LLUICtrl>("WLEastAngle")->setCommitCallback(boost::bind(&LLFloaterWindLight::onSunMoved, this, _1, &param_mgr->mLightnorm));
// Clouds
// Cloud Color
- childSetCommitCallback("WLCloudColorR", onColorControlRMoved, &param_mgr->mCloudColor);
- childSetCommitCallback("WLCloudColorG", onColorControlGMoved, &param_mgr->mCloudColor);
- childSetCommitCallback("WLCloudColorB", onColorControlBMoved, &param_mgr->mCloudColor);
- childSetCommitCallback("WLCloudColorI", onColorControlIMoved, &param_mgr->mCloudColor);
+ getChild<LLUICtrl>("WLCloudColorR")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlRMoved, this, _1, &param_mgr->mCloudColor));
+ getChild<LLUICtrl>("WLCloudColorG")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlGMoved, this, _1, &param_mgr->mCloudColor));
+ getChild<LLUICtrl>("WLCloudColorB")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlBMoved, this, _1, &param_mgr->mCloudColor));
+ getChild<LLUICtrl>("WLCloudColorI")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlIMoved, this, _1, &param_mgr->mCloudColor));
// Cloud
- childSetCommitCallback("WLCloudX", onColorControlRMoved, &param_mgr->mCloudMain);
- childSetCommitCallback("WLCloudY", onColorControlGMoved, &param_mgr->mCloudMain);
- childSetCommitCallback("WLCloudDensity", onColorControlBMoved, &param_mgr->mCloudMain);
+ getChild<LLUICtrl>("WLCloudX")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlRMoved, this, _1, &param_mgr->mCloudMain));
+ getChild<LLUICtrl>("WLCloudY")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlGMoved, this, _1, &param_mgr->mCloudMain));
+ getChild<LLUICtrl>("WLCloudDensity")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlBMoved, this, _1, &param_mgr->mCloudMain));
// Cloud Detail
- childSetCommitCallback("WLCloudDetailX", onColorControlRMoved, &param_mgr->mCloudDetail);
- childSetCommitCallback("WLCloudDetailY", onColorControlGMoved, &param_mgr->mCloudDetail);
- childSetCommitCallback("WLCloudDetailDensity", onColorControlBMoved, &param_mgr->mCloudDetail);
+ getChild<LLUICtrl>("WLCloudDetailX")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlRMoved, this, _1, &param_mgr->mCloudDetail));
+ getChild<LLUICtrl>("WLCloudDetailY")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlGMoved, this, _1, &param_mgr->mCloudDetail));
+ getChild<LLUICtrl>("WLCloudDetailDensity")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlBMoved, this, _1, &param_mgr->mCloudDetail));
// Cloud extras
- childSetCommitCallback("WLCloudCoverage", onFloatControlMoved, &param_mgr->mCloudCoverage);
- childSetCommitCallback("WLCloudScale", onFloatControlMoved, &param_mgr->mCloudScale);
- childSetCommitCallback("WLCloudLockX", onCloudScrollXToggled, NULL);
- childSetCommitCallback("WLCloudLockY", onCloudScrollYToggled, NULL);
- childSetCommitCallback("WLCloudScrollX", onCloudScrollXMoved, NULL);
- childSetCommitCallback("WLCloudScrollY", onCloudScrollYMoved, NULL);
- childSetCommitCallback("WLDistanceMult", onFloatControlMoved, &param_mgr->mDistanceMult);
- childSetCommitCallback("DrawClassicClouds", LLSavedSettingsGlue::setBOOL, (void*)"SkyUseClassicClouds");
+ getChild<LLUICtrl>("WLCloudCoverage")->setCommitCallback(boost::bind(&LLFloaterWindLight::onFloatControlMoved, this, _1, &param_mgr->mCloudCoverage));
+ getChild<LLUICtrl>("WLCloudScale")->setCommitCallback(boost::bind(&LLFloaterWindLight::onFloatControlMoved, this, _1, &param_mgr->mCloudScale));
+ getChild<LLUICtrl>("WLCloudLockX")->setCommitCallback(boost::bind(&LLFloaterWindLight::onCloudScrollXToggled, this, _1));
+ getChild<LLUICtrl>("WLCloudLockY")->setCommitCallback(boost::bind(&LLFloaterWindLight::onCloudScrollYToggled, this, _1));
+ getChild<LLUICtrl>("WLCloudScrollX")->setCommitCallback(boost::bind(&LLFloaterWindLight::onCloudScrollXMoved, this, _1));
+ getChild<LLUICtrl>("WLCloudScrollY")->setCommitCallback(boost::bind(&LLFloaterWindLight::onCloudScrollYMoved, this, _1));
+ getChild<LLUICtrl>("WLDistanceMult")->setCommitCallback(boost::bind(&LLFloaterWindLight::onFloatControlMoved, this, _1, &param_mgr->mDistanceMult));
+ getChild<LLUICtrl>("DrawClassicClouds")->setCommitCallback(boost::bind(LLSavedSettingsGlue::setBOOL, _1, "SkyUseClassicClouds"));
// WL Top
- childSetAction("WLDayCycleMenuButton", onOpenDayCycle, NULL);
+ getChild<LLUICtrl>("WLDayCycleMenuButton")->setCommitCallback(boost::bind(&LLFloaterWindLight::onOpenDayCycle, this));
// Load/save
LLComboBox* comboBox = getChild<LLComboBox>("WLPresetsCombo");
//childSetAction("WLLoadPreset", onLoadPreset, comboBox);
- childSetAction("WLNewPreset", onNewPreset, comboBox);
- childSetAction("WLSavePreset", onSavePreset, comboBox);
- childSetAction("WLDeletePreset", onDeletePreset, comboBox);
+ getChild<LLUICtrl>("WLNewPreset")->setCommitCallback(boost::bind(&LLFloaterWindLight::onNewPreset, this));
+ getChild<LLUICtrl>("WLSavePreset")->setCommitCallback(boost::bind(&LLFloaterWindLight::onSavePreset, this));
+ getChild<LLUICtrl>("WLDeletePreset")->setCommitCallback(boost::bind(&LLFloaterWindLight::onDeletePreset, this));
- comboBox->setCommitCallback(onChangePresetName);
+ comboBox->setCommitCallback(boost::bind(&LLFloaterWindLight::onChangePresetName, this, _1));
// Dome
- childSetCommitCallback("WLGamma", onFloatControlMoved, &param_mgr->mWLGamma);
- childSetCommitCallback("WLStarAlpha", onStarAlphaMoved, NULL);
-}
-
-void LLFloaterWindLight::onClickHelp(void* data)
-{
- LLFloaterWindLight* self = LLFloaterWindLight::instance();
-
- const std::string xml_alert = *(std::string*)data;
- LLNotifications::instance().add(self->contextualNotification(xml_alert));
-}
-
-void LLFloaterWindLight::initHelpBtn(const std::string& name, const std::string& xml_alert)
-{
- childSetAction(name, onClickHelp, new std::string(xml_alert));
+ getChild<LLUICtrl>("WLGamma")->setCommitCallback(boost::bind(&LLFloaterWindLight::onFloatControlMoved, this, _1, &param_mgr->mWLGamma));
+ getChild<LLUICtrl>("WLStarAlpha")->setCommitCallback(boost::bind(&LLFloaterWindLight::onStarAlphaMoved, this, _1));
}
bool LLFloaterWindLight::newPromptCallback(const LLSD& notification, const LLSD& response)
{
std::string text = response["message"].asString();
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if(text == "")
{
@@ -254,16 +219,13 @@ bool LLFloaterWindLight::newPromptCallback(const LLSD& notification, const LLSD&
}
if(option == 0) {
- LLComboBox* comboBox = sWindLight->getChild<LLComboBox>(
- "WLPresetsCombo");
+ LLComboBox* comboBox = getChild<LLComboBox>("WLPresetsCombo");
- LLFloaterDayCycle* sDayCycle = NULL;
+ LLFloaterDayCycle* day_cycle = LLFloaterReg::findTypedInstance<LLFloaterDayCycle>("env_day_cycle");
LLComboBox* keyCombo = NULL;
- if(LLFloaterDayCycle::isOpen())
+ if(day_cycle)
{
- sDayCycle = LLFloaterDayCycle::instance();
- keyCombo = sDayCycle->getChild<LLComboBox>(
- "WLKeyPresets");
+ keyCombo = day_cycle->getChild<LLComboBox>("WLKeyPresets");
}
// add the current parameters to the list
@@ -288,7 +250,7 @@ bool LLFloaterWindLight::newPromptCallback(const LLSD& notification, const LLSD&
comboBox->add(LLStringUtil::null);
comboBox->setSelectedByValue(text, true);
- if(LLFloaterDayCycle::isOpen())
+ if(keyCombo)
{
keyCombo->add(text);
keyCombo->sortByName();
@@ -299,7 +261,7 @@ bool LLFloaterWindLight::newPromptCallback(const LLSD& notification, const LLSD&
}
else
{
- LLNotifications::instance().add("ExistsSkyPresetAlert");
+ LLNotificationsUtil::add("ExistsSkyPresetAlert");
}
}
return false;
@@ -435,56 +397,20 @@ void LLFloaterWindLight::syncMenu()
childSetValue("WLGamma", param_mgr->mWLGamma.x);
childSetValue("WLStarAlpha", param_mgr->mCurParams.getStarBrightness());
-}
+ LLTabContainer* tab = getChild<LLTabContainer>("WindLight Tabs");
+ LLPanel* panel = getChild<LLPanel>("Scattering");
-// static
-LLFloaterWindLight* LLFloaterWindLight::instance()
-{
- if (!sWindLight)
- {
- sWindLight = new LLFloaterWindLight();
- sWindLight->open();
- sWindLight->setFocus(TRUE);
- }
- return sWindLight;
-}
-void LLFloaterWindLight::show()
-{
- LLFloaterWindLight* windLight = instance();
- windLight->syncMenu();
-
- // comment in if you want the menu to rebuild each time
- //LLUICtrlFactory::getInstance()->buildFloater(windLight, "floater_windlight_options.xml");
- //windLight->initCallbacks();
-
- windLight->open();
+ tab->enableTabButton(tab->getIndexForPanel(panel), gSavedSettings.getBOOL("RenderDeferredGI"));
}
-bool LLFloaterWindLight::isOpen()
-{
- if (sWindLight != NULL) {
- return true;
- }
- return false;
-}
-
-// virtual
-void LLFloaterWindLight::onClose(bool app_quitting)
-{
- if (sWindLight)
- {
- sWindLight->setVisible(FALSE);
- }
-}
// color control callbacks
-void LLFloaterWindLight::onColorControlRMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWindLight::onColorControlRMoved(LLUICtrl* ctrl, WLColorControl* colorControl)
{
deactivateAnimator();
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- WLColorControl * colorControl = static_cast<WLColorControl *>(userData);
colorControl->r = sldrCtrl->getValueF32();
if(colorControl->isSunOrAmbientColor) {
@@ -502,11 +428,11 @@ void LLFloaterWindLight::onColorControlRMoved(LLUICtrl* ctrl, void* userData)
name.append("I");
if(colorControl->isSunOrAmbientColor) {
- sWindLight->childSetValue(name, colorControl->r / 3);
+ childSetValue(name, colorControl->r / 3);
} else if(colorControl->isBlueHorizonOrDensity) {
- sWindLight->childSetValue(name, colorControl->r / 2);
+ childSetValue(name, colorControl->r / 2);
} else {
- sWindLight->childSetValue(name, colorControl->r);
+ childSetValue(name, colorControl->r);
}
}
@@ -515,12 +441,11 @@ void LLFloaterWindLight::onColorControlRMoved(LLUICtrl* ctrl, void* userData)
LLWLParamManager::instance()->propagateParameters();
}
-void LLFloaterWindLight::onColorControlGMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWindLight::onColorControlGMoved(LLUICtrl* ctrl, WLColorControl* colorControl)
{
deactivateAnimator();
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- WLColorControl * colorControl = static_cast<WLColorControl *>(userData);
colorControl->g = sldrCtrl->getValueF32();
if(colorControl->isSunOrAmbientColor) {
@@ -538,11 +463,11 @@ void LLFloaterWindLight::onColorControlGMoved(LLUICtrl* ctrl, void* userData)
name.append("I");
if(colorControl->isSunOrAmbientColor) {
- sWindLight->childSetValue(name, colorControl->g / 3);
+ childSetValue(name, colorControl->g / 3);
} else if(colorControl->isBlueHorizonOrDensity) {
- sWindLight->childSetValue(name, colorControl->g / 2);
+ childSetValue(name, colorControl->g / 2);
} else {
- sWindLight->childSetValue(name, colorControl->g);
+ childSetValue(name, colorControl->g);
}
}
@@ -551,12 +476,11 @@ void LLFloaterWindLight::onColorControlGMoved(LLUICtrl* ctrl, void* userData)
LLWLParamManager::instance()->propagateParameters();
}
-void LLFloaterWindLight::onColorControlBMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWindLight::onColorControlBMoved(LLUICtrl* ctrl, WLColorControl* colorControl)
{
deactivateAnimator();
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- WLColorControl * colorControl = static_cast<WLColorControl *>(userData);
colorControl->b = sldrCtrl->getValueF32();
if(colorControl->isSunOrAmbientColor) {
@@ -574,11 +498,11 @@ void LLFloaterWindLight::onColorControlBMoved(LLUICtrl* ctrl, void* userData)
name.append("I");
if(colorControl->isSunOrAmbientColor) {
- sWindLight->childSetValue(name, colorControl->b / 3);
+ childSetValue(name, colorControl->b / 3);
} else if(colorControl->isBlueHorizonOrDensity) {
- sWindLight->childSetValue(name, colorControl->b / 2);
+ childSetValue(name, colorControl->b / 2);
} else {
- sWindLight->childSetValue(name, colorControl->b);
+ childSetValue(name, colorControl->b);
}
}
@@ -587,12 +511,11 @@ void LLFloaterWindLight::onColorControlBMoved(LLUICtrl* ctrl, void* userData)
LLWLParamManager::instance()->propagateParameters();
}
-void LLFloaterWindLight::onColorControlIMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWindLight::onColorControlIMoved(LLUICtrl* ctrl, WLColorControl* colorControl)
{
deactivateAnimator();
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- WLColorControl * colorControl = static_cast<WLColorControl *>(userData);
colorControl->i = sldrCtrl->getValueF32();
@@ -649,24 +572,24 @@ void LLFloaterWindLight::onColorControlIMoved(LLUICtrl* ctrl, void* userData)
// divide sun color vals by three
if(colorControl->isSunOrAmbientColor)
{
- sWindLight->childSetValue(rName, colorControl->r/3);
- sWindLight->childSetValue(gName, colorControl->g/3);
- sWindLight->childSetValue(bName, colorControl->b/3);
+ childSetValue(rName, colorControl->r/3);
+ childSetValue(gName, colorControl->g/3);
+ childSetValue(bName, colorControl->b/3);
}
else if(colorControl->isBlueHorizonOrDensity)
{
- sWindLight->childSetValue(rName, colorControl->r/2);
- sWindLight->childSetValue(gName, colorControl->g/2);
- sWindLight->childSetValue(bName, colorControl->b/2);
+ childSetValue(rName, colorControl->r/2);
+ childSetValue(gName, colorControl->g/2);
+ childSetValue(bName, colorControl->b/2);
}
else
{
// set the sliders to the new vals
- sWindLight->childSetValue(rName, colorControl->r);
- sWindLight->childSetValue(gName, colorControl->g);
- sWindLight->childSetValue(bName, colorControl->b);
+ childSetValue(rName, colorControl->r);
+ childSetValue(gName, colorControl->g);
+ childSetValue(bName, colorControl->b);
}
}
@@ -676,12 +599,11 @@ void LLFloaterWindLight::onColorControlIMoved(LLUICtrl* ctrl, void* userData)
}
/// GLOW SPECIFIC CODE
-void LLFloaterWindLight::onGlowRMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWindLight::onGlowRMoved(LLUICtrl* ctrl, WLColorControl* colorControl)
{
deactivateAnimator();
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- WLColorControl * colorControl = static_cast<WLColorControl *>(userData);
// scaled by 20
colorControl->r = (2 - sldrCtrl->getValueF32()) * 20;
@@ -691,12 +613,11 @@ void LLFloaterWindLight::onGlowRMoved(LLUICtrl* ctrl, void* userData)
}
/// \NOTE that we want NEGATIVE (-) B
-void LLFloaterWindLight::onGlowBMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWindLight::onGlowBMoved(LLUICtrl* ctrl, WLColorControl* colorControl)
{
deactivateAnimator();
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- WLColorControl * colorControl = static_cast<WLColorControl *>(userData);
/// \NOTE that we want NEGATIVE (-) B and NOT by 20 as 20 is too big
colorControl->b = -sldrCtrl->getValueF32() * 5;
@@ -705,12 +626,11 @@ void LLFloaterWindLight::onGlowBMoved(LLUICtrl* ctrl, void* userData)
LLWLParamManager::instance()->propagateParameters();
}
-void LLFloaterWindLight::onFloatControlMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWindLight::onFloatControlMoved(LLUICtrl* ctrl, WLFloatControl* floatControl)
{
deactivateAnimator();
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- WLFloatControl * floatControl = static_cast<WLFloatControl *>(userData);
floatControl->x = sldrCtrl->getValueF32() / floatControl->mult;
@@ -718,29 +638,16 @@ void LLFloaterWindLight::onFloatControlMoved(LLUICtrl* ctrl, void* userData)
LLWLParamManager::instance()->propagateParameters();
}
-void LLFloaterWindLight::onBoolToggle(LLUICtrl* ctrl, void* userData)
-{
- deactivateAnimator();
-
- LLCheckBoxCtrl* cbCtrl = static_cast<LLCheckBoxCtrl*>(ctrl);
-
- bool value = cbCtrl->get();
- (*(static_cast<BOOL *>(userData))) = value;
-}
-
-
// Lighting callbacks
// time of day
-void LLFloaterWindLight::onSunMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWindLight::onSunMoved(LLUICtrl* ctrl, WLColorControl* colorControl)
{
deactivateAnimator();
- LLSliderCtrl* sunSldr = sWindLight->getChild<LLSliderCtrl>("WLSunAngle");
- LLSliderCtrl* eastSldr = sWindLight->getChild<LLSliderCtrl>("WLEastAngle");
+ LLSliderCtrl* sunSldr = getChild<LLSliderCtrl>("WLSunAngle");
+ LLSliderCtrl* eastSldr = getChild<LLSliderCtrl>("WLEastAngle");
- WLColorControl * colorControl = static_cast<WLColorControl *>(userData);
-
// get the two angles
LLWLParamManager * param_mgr = LLWLParamManager::instance();
@@ -759,18 +666,7 @@ void LLFloaterWindLight::onSunMoved(LLUICtrl* ctrl, void* userData)
param_mgr->propagateParameters();
}
-void LLFloaterWindLight::onFloatTweakMoved(LLUICtrl* ctrl, void* userData)
-{
- deactivateAnimator();
-
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- F32 * tweak = static_cast<F32 *>(userData);
-
- (*tweak) = sldrCtrl->getValueF32();
- LLWLParamManager::instance()->propagateParameters();
-}
-
-void LLFloaterWindLight::onStarAlphaMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWindLight::onStarAlphaMoved(LLUICtrl* ctrl)
{
deactivateAnimator();
@@ -779,15 +675,15 @@ void LLFloaterWindLight::onStarAlphaMoved(LLUICtrl* ctrl, void* userData)
LLWLParamManager::instance()->mCurParams.setStarBrightness(sldrCtrl->getValueF32());
}
-void LLFloaterWindLight::onNewPreset(void* userData)
+void LLFloaterWindLight::onNewPreset()
{
- LLNotifications::instance().add("NewSkyPreset", LLSD(), LLSD(), newPromptCallback);
+ LLNotificationsUtil::add("NewSkyPreset", LLSD(), LLSD(), boost::bind(&LLFloaterWindLight::newPromptCallback, this, _1, _2));
}
-void LLFloaterWindLight::onSavePreset(void* userData)
+void LLFloaterWindLight::onSavePreset()
{
// get the name
- LLComboBox* comboBox = sWindLight->getChild<LLComboBox>(
+ LLComboBox* comboBox = getChild<LLComboBox>(
"WLPresetsCombo");
// don't save the empty name
@@ -801,19 +697,19 @@ void LLFloaterWindLight::onSavePreset(void* userData)
comboBox->getSelectedItemLabel());
if(sIt != sDefaultPresets.end() && !gSavedSettings.getBOOL("SkyEditPresets"))
{
- LLNotifications::instance().add("WLNoEditDefault");
+ LLNotificationsUtil::add("WLNoEditDefault");
return;
}
LLWLParamManager::instance()->mCurParams.mName =
comboBox->getSelectedItemLabel();
- LLNotifications::instance().add("WLSavePresetAlert", LLSD(), LLSD(), saveAlertCallback);
+ LLNotificationsUtil::add("WLSavePresetAlert", LLSD(), LLSD(), boost::bind(&LLFloaterWindLight::saveAlertCallback, this, _1, _2));
}
bool LLFloaterWindLight::saveAlertCallback(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
// if they choose save, do it. Otherwise, don't do anything
if(option == 0)
{
@@ -827,9 +723,9 @@ bool LLFloaterWindLight::saveAlertCallback(const LLSD& notification, const LLSD&
return false;
}
-void LLFloaterWindLight::onDeletePreset(void* userData)
+void LLFloaterWindLight::onDeletePreset()
{
- LLComboBox* combo_box = sWindLight->getChild<LLComboBox>(
+ LLComboBox* combo_box = getChild<LLComboBox>(
"WLPresetsCombo");
if(combo_box->getSelectedValue().asString() == "")
@@ -839,28 +735,25 @@ void LLFloaterWindLight::onDeletePreset(void* userData)
LLSD args;
args["SKY"] = combo_box->getSelectedValue().asString();
- LLNotifications::instance().add("WLDeletePresetAlert", args, LLSD(),
- boost::bind(&LLFloaterWindLight::deleteAlertCallback, sWindLight, _1, _2));
+ LLNotificationsUtil::add("WLDeletePresetAlert", args, LLSD(),
+ boost::bind(&LLFloaterWindLight::deleteAlertCallback, this, _1, _2));
}
bool LLFloaterWindLight::deleteAlertCallback(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
// if they choose delete, do it. Otherwise, don't do anything
if(option == 0)
{
- LLComboBox* combo_box = getChild<LLComboBox>(
- "WLPresetsCombo");
- LLFloaterDayCycle* day_cycle = NULL;
+ LLComboBox* combo_box = getChild<LLComboBox>("WLPresetsCombo");
+ LLFloaterDayCycle* day_cycle = LLFloaterReg::findTypedInstance<LLFloaterDayCycle>("env_day_cycle");
LLComboBox* key_combo = NULL;
LLMultiSliderCtrl* mult_sldr = NULL;
- if(LLFloaterDayCycle::isOpen())
+ if (day_cycle)
{
- day_cycle = LLFloaterDayCycle::instance();
- key_combo = day_cycle->getChild<LLComboBox>(
- "WLKeyPresets");
+ key_combo = day_cycle->getChild<LLComboBox>("WLKeyPresets");
mult_sldr = day_cycle->getChild<LLMultiSliderCtrl>("WLDayCycleKeys");
}
@@ -870,7 +763,7 @@ bool LLFloaterWindLight::deleteAlertCallback(const LLSD& notification, const LLS
std::set<std::string>::iterator sIt = sDefaultPresets.find(name);
if(sIt != sDefaultPresets.end())
{
- LLNotifications::instance().add("WLNoEditDefault");
+ LLNotificationsUtil::add("WLNoEditDefault");
return false;
}
@@ -903,29 +796,25 @@ bool LLFloaterWindLight::deleteAlertCallback(const LLSD& notification, const LLS
}
-void LLFloaterWindLight::onChangePresetName(LLUICtrl* ctrl, void * userData)
+void LLFloaterWindLight::onChangePresetName(LLUICtrl* ctrl)
{
deactivateAnimator();
- LLComboBox * combo_box = static_cast<LLComboBox*>(ctrl);
-
- if(combo_box->getSimple() == "")
+ std::string data = ctrl->getValue().asString();
+ if(!data.empty())
{
- return;
+ LLWLParamManager::instance()->loadPreset( data);
+ syncMenu();
}
-
- LLWLParamManager::instance()->loadPreset(
- combo_box->getSelectedValue().asString());
- sWindLight->syncMenu();
}
-void LLFloaterWindLight::onOpenDayCycle(void* userData)
+void LLFloaterWindLight::onOpenDayCycle()
{
- LLFloaterDayCycle::show();
+ LLFloaterReg::showInstance("env_day_cycle");
}
// Clouds
-void LLFloaterWindLight::onCloudScrollXMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWindLight::onCloudScrollXMoved(LLUICtrl* ctrl)
{
deactivateAnimator();
@@ -934,7 +823,7 @@ void LLFloaterWindLight::onCloudScrollXMoved(LLUICtrl* ctrl, void* userData)
LLWLParamManager::instance()->mCurParams.setCloudScrollX(sldrCtrl->getValueF32() + 10.0f);
}
-void LLFloaterWindLight::onCloudScrollYMoved(LLUICtrl* ctrl, void* userData)
+void LLFloaterWindLight::onCloudScrollYMoved(LLUICtrl* ctrl)
{
deactivateAnimator();
@@ -944,7 +833,7 @@ void LLFloaterWindLight::onCloudScrollYMoved(LLUICtrl* ctrl, void* userData)
LLWLParamManager::instance()->mCurParams.setCloudScrollY(sldrCtrl->getValueF32() + 10.0f);
}
-void LLFloaterWindLight::onCloudScrollXToggled(LLUICtrl* ctrl, void* userData)
+void LLFloaterWindLight::onCloudScrollXToggled(LLUICtrl* ctrl)
{
deactivateAnimator();
@@ -953,7 +842,7 @@ void LLFloaterWindLight::onCloudScrollXToggled(LLUICtrl* ctrl, void* userData)
bool lock = cbCtrl->get();
LLWLParamManager::instance()->mCurParams.setEnableCloudScrollX(!lock);
- LLSliderCtrl* sldr = sWindLight->getChild<LLSliderCtrl>(
+ LLSliderCtrl* sldr = getChild<LLSliderCtrl>(
"WLCloudScrollX");
if(cbCtrl->get())
@@ -967,7 +856,7 @@ void LLFloaterWindLight::onCloudScrollXToggled(LLUICtrl* ctrl, void* userData)
}
-void LLFloaterWindLight::onCloudScrollYToggled(LLUICtrl* ctrl, void* userData)
+void LLFloaterWindLight::onCloudScrollYToggled(LLUICtrl* ctrl)
{
deactivateAnimator();
@@ -975,7 +864,7 @@ void LLFloaterWindLight::onCloudScrollYToggled(LLUICtrl* ctrl, void* userData)
bool lock = cbCtrl->get();
LLWLParamManager::instance()->mCurParams.setEnableCloudScrollY(!lock);
- LLSliderCtrl* sldr = sWindLight->getChild<LLSliderCtrl>(
+ LLSliderCtrl* sldr = getChild<LLSliderCtrl>(
"WLCloudScrollY");
if(cbCtrl->get())
diff --git a/indra/newview/llfloaterwindlight.h b/indra/newview/llfloaterwindlight.h
index 3447caa923..ed9322c450 100644
--- a/indra/newview/llfloaterwindlight.h
+++ b/indra/newview/llfloaterwindlight.h
@@ -51,80 +51,58 @@ class LLFloaterWindLight : public LLFloater
{
public:
- LLFloaterWindLight();
+ LLFloaterWindLight(const LLSD& key);
virtual ~LLFloaterWindLight();
-
+ /*virtual*/ BOOL postBuild();
/// initialize all
void initCallbacks(void);
- /// one and one instance only
- static LLFloaterWindLight* instance();
-
- // help button stuff
- static void onClickHelp(void* data);
- void initHelpBtn(const std::string& name, const std::string& xml_alert);
-
- static bool newPromptCallback(const LLSD& notification, const LLSD& response);
+ bool newPromptCallback(const LLSD& notification, const LLSD& response);
/// general purpose callbacks for dealing with color controllers
- static void onColorControlRMoved(LLUICtrl* ctrl, void* userData);
- static void onColorControlGMoved(LLUICtrl* ctrl, void* userData);
- static void onColorControlBMoved(LLUICtrl* ctrl, void* userData);
- static void onColorControlIMoved(LLUICtrl* ctrl, void* userData);
- static void onFloatControlMoved(LLUICtrl* ctrl, void* userData);
- static void onBoolToggle(LLUICtrl* ctrl, void* userData);
+ void onColorControlRMoved(LLUICtrl* ctrl, WLColorControl* userData);
+ void onColorControlGMoved(LLUICtrl* ctrl, WLColorControl* userData);
+ void onColorControlBMoved(LLUICtrl* ctrl, WLColorControl* userData);
+ void onColorControlIMoved(LLUICtrl* ctrl, WLColorControl* userData);
+ void onFloatControlMoved(LLUICtrl* ctrl, WLFloatControl* userData);
/// lighting callbacks for glow
- static void onGlowRMoved(LLUICtrl* ctrl, void* userData);
+ void onGlowRMoved(LLUICtrl* ctrl, WLColorControl* userData);
//static void onGlowGMoved(LLUICtrl* ctrl, void* userData);
- static void onGlowBMoved(LLUICtrl* ctrl, void* userData);
+ void onGlowBMoved(LLUICtrl* ctrl, WLColorControl* userData);
/// lighting callbacks for sun
- static void onSunMoved(LLUICtrl* ctrl, void* userData);
-
- /// handle if float is changed
- static void onFloatTweakMoved(LLUICtrl* ctrl, void* userData);
+ void onSunMoved(LLUICtrl* ctrl, WLColorControl* userData);
/// for handling when the star slider is moved to adjust the alpha
- static void onStarAlphaMoved(LLUICtrl* ctrl, void* userData);
+ void onStarAlphaMoved(LLUICtrl* ctrl);
/// when user hits the load preset button
- static void onNewPreset(void* userData);
+ void onNewPreset();
/// when user hits the save preset button
- static void onSavePreset(void* userData);
+ void onSavePreset();
/// prompts a user when overwriting a preset
- static bool saveAlertCallback(const LLSD& notification, const LLSD& response);
+ bool saveAlertCallback(const LLSD& notification, const LLSD& response);
/// when user hits the save preset button
- static void onDeletePreset(void* userData);
+ void onDeletePreset();
/// prompts a user when overwriting a preset
bool deleteAlertCallback(const LLSD& notification, const LLSD& response);
/// what to do when you change the preset name
- static void onChangePresetName(LLUICtrl* ctrl, void* userData);
+ void onChangePresetName(LLUICtrl* ctrl);
/// when user hits the save preset button
- static void onOpenDayCycle(void* userData);
+ void onOpenDayCycle();
/// handle cloud scrolling
- static void onCloudScrollXMoved(LLUICtrl* ctrl, void* userData);
- static void onCloudScrollYMoved(LLUICtrl* ctrl, void* userData);
- static void onCloudScrollXToggled(LLUICtrl* ctrl, void* userData);
- static void onCloudScrollYToggled(LLUICtrl* ctrl, void* userData);
-
- //// menu management
-
- /// show off our menu
- static void show();
-
- /// return if the menu exists or not
- static bool isOpen();
-
- /// stuff to do on exit
- virtual void onClose(bool app_quitting);
+ void onCloudScrollXMoved(LLUICtrl* ctrl);
+ void onCloudScrollYMoved(LLUICtrl* ctrl);
+ void onCloudScrollXToggled(LLUICtrl* ctrl);
+ void onCloudScrollYToggled(LLUICtrl* ctrl);
/// sync up sliders with parameters
void syncMenu();
@@ -133,9 +111,6 @@ public:
static void deactivateAnimator();
private:
- // one instance on the inside
- static LLFloaterWindLight* sWindLight;
-
static std::set<std::string> sDefaultPresets;
};
diff --git a/indra/newview/llfloaterwindowsize.cpp b/indra/newview/llfloaterwindowsize.cpp
new file mode 100644
index 0000000000..5519be6f08
--- /dev/null
+++ b/indra/newview/llfloaterwindowsize.cpp
@@ -0,0 +1,164 @@
+/**
+ * @file llfloaterwindowsize.cpp
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterwindowsize.h"
+
+// Viewer includes
+#include "llviewerwindow.h"
+
+// Linden library includes
+#include "llcombobox.h"
+#include "llfloater.h"
+#include "llfloaterreg.h"
+#include "lluictrl.h"
+
+// System libraries
+#include <boost/regex.hpp>
+
+// Extract from strings of the form "<width> x <height>", e.g. "640 x 480".
+bool extractWindowSizeFromString(const std::string& instr, U32 *width, U32 *height)
+{
+ boost::cmatch what;
+ // matches (any number)(any non-number)(any number)
+ const boost::regex expression("([0-9]+)[^0-9]+([0-9]+)");
+ if (boost::regex_match(instr.c_str(), what, expression))
+ {
+ *width = atoi(what[1].first);
+ *height = atoi(what[2].first);
+ return true;
+ }
+
+ *width = 0;
+ *height = 0;
+ return false;
+}
+
+
+///----------------------------------------------------------------------------
+/// Class LLFloaterWindowSize
+///----------------------------------------------------------------------------
+class LLFloaterWindowSize
+: public LLFloater
+{
+ friend class LLFloaterReg;
+private:
+ LLFloaterWindowSize(const LLSD& key);
+ virtual ~LLFloaterWindowSize();
+
+public:
+ /*virtual*/ BOOL postBuild();
+ void initWindowSizeControls();
+ void onClickSet();
+ void onClickCancel();
+};
+
+
+LLFloaterWindowSize::LLFloaterWindowSize(const LLSD& key)
+: LLFloater(key)
+{
+ //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_window_size.xml");
+}
+
+LLFloaterWindowSize::~LLFloaterWindowSize()
+{
+}
+
+BOOL LLFloaterWindowSize::postBuild()
+{
+ center();
+ initWindowSizeControls();
+ getChild<LLUICtrl>("set_btn")->setCommitCallback(
+ boost::bind(&LLFloaterWindowSize::onClickSet, this));
+ getChild<LLUICtrl>("cancel_btn")->setCommitCallback(
+ boost::bind(&LLFloaterWindowSize::onClickCancel, this));
+ setDefaultBtn("set_btn");
+ return TRUE;
+}
+
+void LLFloaterWindowSize::initWindowSizeControls()
+{
+ LLComboBox* ctrl_window_size = getChild<LLComboBox>("window_size_combo");
+
+ // Look to see if current window size matches existing window sizes, if so then
+ // just set the selection value...
+ const U32 height = gViewerWindow->getWindowHeightRaw();
+ const U32 width = gViewerWindow->getWindowWidthRaw();
+ for (S32 i=0; i < ctrl_window_size->getItemCount(); i++)
+ {
+ U32 height_test = 0;
+ U32 width_test = 0;
+ ctrl_window_size->setCurrentByIndex(i);
+ std::string resolution = ctrl_window_size->getValue().asString();
+ if (extractWindowSizeFromString(resolution, &width_test, &height_test))
+ {
+ if ((height_test == height) && (width_test == width))
+ {
+ return;
+ }
+ }
+ }
+ // ...otherwise, add a new entry with the current window height/width.
+ LLUIString resolution_label = getString("resolution_format");
+ resolution_label.setArg("[RES_X]", llformat("%d", width));
+ resolution_label.setArg("[RES_Y]", llformat("%d", height));
+ ctrl_window_size->add(resolution_label, ADD_TOP);
+ ctrl_window_size->setCurrentByIndex(0);
+}
+
+void LLFloaterWindowSize::onClickSet()
+{
+ LLComboBox* ctrl_window_size = getChild<LLComboBox>("window_size_combo");
+ U32 width = 0;
+ U32 height = 0;
+ std::string resolution = ctrl_window_size->getValue().asString();
+ if (extractWindowSizeFromString(resolution, &width, &height))
+ {
+ LLViewerWindow::movieSize(width, height);
+ }
+ closeFloater();
+}
+
+void LLFloaterWindowSize::onClickCancel()
+{
+ closeFloater();
+}
+
+///----------------------------------------------------------------------------
+/// LLFloaterWindowSizeUtil
+///----------------------------------------------------------------------------
+void LLFloaterWindowSizeUtil::registerFloater()
+{
+ LLFloaterReg::add("window_size", "floater_window_size.xml",
+ &LLFloaterReg::build<LLFloaterWindowSize>);
+
+}
diff --git a/indra/newview/llfloaterwindowsize.h b/indra/newview/llfloaterwindowsize.h
new file mode 100644
index 0000000000..fd9d17323a
--- /dev/null
+++ b/indra/newview/llfloaterwindowsize.h
@@ -0,0 +1,41 @@
+/**
+ * @file llfloaterwindowsize.h
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLFLOATERWINDOWSIZE_H
+#define LLFLOATERWINDOWSIZE_H
+
+// Allow user to set the window size for filming tutorials, machinima, etc
+namespace LLFloaterWindowSizeUtil
+{
+ void registerFloater();
+}
+
+#endif
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index 8326557cf8..f4d4ea3553 100644
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -41,40 +41,54 @@
#include "llfloaterworldmap.h"
#include "llagent.h"
-#include "llviewerwindow.h"
#include "llbutton.h"
#include "llcallingcard.h"
-#include "llcolorscheme.h"
#include "llcombobox.h"
#include "llviewercontrol.h"
+#include "llcommandhandler.h"
#include "lldraghandle.h"
-#include "llfirstuse.h"
+//#include "llfirstuse.h"
+#include "llfloaterreg.h" // getTypedInstance()
#include "llfocusmgr.h"
+#include "llinventorymodel.h"
+#include "llinventoryobserver.h"
#include "lllandmarklist.h"
#include "lllineeditor.h"
-#include "llpreviewlandmark.h"
+#include "llnotificationsutil.h"
#include "llregionhandle.h"
#include "llscrolllistctrl.h"
+#include "llslurl.h"
#include "lltextbox.h"
#include "lltracker.h"
-#include "llurldispatcher.h"
+#include "lltrans.h"
+#include "llviewerinventory.h" // LLViewerInventoryItem
#include "llviewermenu.h"
#include "llviewerregion.h"
#include "llviewerstats.h"
+#include "llviewertexture.h"
#include "llworldmap.h"
+#include "llworldmapmessage.h"
#include "llworldmapview.h"
#include "lluictrlfactory.h"
#include "llappviewer.h"
#include "llmapimagetype.h"
#include "llweb.h"
+#include "llslider.h"
+#include "message.h"
-#include "llglheaders.h"
+#include "llwindow.h" // copyTextToClipboard()
//---------------------------------------------------------------------------
// 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
+// sessions and doesn't prevent the user to pan the world if it was to grow a lot beyond that limit.
+// Currently (01/26/09), this value allows the whole grid to be visible in a 1024x1024 window.
+static const S32 MAX_VISIBLE_REGIONS = 512;
+
enum EPanDirection
{
PAN_UP,
@@ -84,21 +98,44 @@ enum EPanDirection
};
// Values in pixels per region
-static const F32 ZOOM_MIN = -8.f; // initial value, updated by adjustZoomSlider
-static const F32 ZOOM_MAX = 0.f;
-static const F32 ZOOM_INC = 0.2f;
-
-static const F32 SIM_COORD_MIN = 0.f;
-static const F32 SIM_COORD_MAX = 255.f;
-static const F32 SIM_COORD_DEFAULT = 128.f;
-
-static const F64 MAX_FLY_DISTANCE = 363.f; // Diagonal size of one sim.
-static const F64 MAX_FLY_DISTANCE_SQUARED = MAX_FLY_DISTANCE * MAX_FLY_DISTANCE;
+static const F32 ZOOM_MAX = 128.f;
//---------------------------------------------------------------------------
// Globals
//---------------------------------------------------------------------------
+// handle secondlife:///app/worldmap/{NAME}/{COORDS} URLs
+class LLWorldMapHandler : public LLCommandHandler
+{
+public:
+ // requires trusted browser to trigger
+ LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_THROTTLE) { }
+
+ bool handle(const LLSD& params, const LLSD& query_map,
+ LLMediaCtrl* web)
+ {
+ if (params.size() == 0)
+ {
+ // support the secondlife:///app/worldmap SLapp
+ LLFloaterReg::showInstance("world_map", "center");
+ return true;
+ }
+
+ // support the secondlife:///app/worldmap/{LOCATION}/{COORDS} SLapp
+ const std::string region_name = params[0].asString();
+ S32 x = (params.size() > 1) ? params[1].asInteger() : 128;
+ S32 y = (params.size() > 2) ? params[2].asInteger() : 128;
+ S32 z = (params.size() > 3) ? params[3].asInteger() : 0;
+
+ LLFloaterWorldMap::getInstance()->trackURL(region_name, x, y, z);
+ LLFloaterReg::showInstance("world_map", "center");
+
+ return true;
+ }
+};
+LLWorldMapHandler gWorldMapHandler;
+
+
LLFloaterWorldMap* gFloaterWorldMap = NULL;
class LLMapInventoryObserver : public LLInventoryObserver
@@ -148,105 +185,74 @@ const LLUUID LLFloaterWorldMap::sHomeID( "10000000-0000-0000-0000-000000000001"
//---------------------------------------------------------------------------
-LLFloaterWorldMap::LLFloaterWorldMap()
-: LLFloater(std::string("worldmap")),
+LLFloaterWorldMap::LLFloaterWorldMap(const LLSD& key)
+: LLFloater(key),
mInventory(NULL),
mInventoryObserver(NULL),
mFriendObserver(NULL),
- mCompletingRegionName(""),
+ mCompletingRegionName(),
+ mCompletingRegionPos(),
mWaitingForTracker(FALSE),
- mExactMatch(FALSE),
mIsClosing(FALSE),
mSetToUserPosition(TRUE),
mTrackedLocation(0,0,0),
mTrackedStatus(LLTracker::TRACKING_NOTHING)
{
- LLCallbackMap::map_t factory_map;
- factory_map["objects_mapview"] = LLCallbackMap(createWorldMapView, NULL);
- factory_map["terrain_mapview"] = LLCallbackMap(createWorldMapView, NULL);
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_world_map.xml", &factory_map);
+ gFloaterWorldMap = this;
+
+ mFactoryMap["objects_mapview"] = LLCallbackMap(createWorldMapView, NULL);
+
+ //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_world_map.xml", FALSE);
+ mCommitCallbackRegistrar.add("WMap.Location", boost::bind(&LLFloaterWorldMap::onLocationCommit, this));
+ mCommitCallbackRegistrar.add("WMap.AvatarCombo", boost::bind(&LLFloaterWorldMap::onAvatarComboCommit, this));
+ mCommitCallbackRegistrar.add("WMap.Landmark", boost::bind(&LLFloaterWorldMap::onLandmarkComboCommit, this));
+ mCommitCallbackRegistrar.add("WMap.SearchResult", boost::bind(&LLFloaterWorldMap::onCommitSearchResult, this));
+ mCommitCallbackRegistrar.add("WMap.GoHome", boost::bind(&LLFloaterWorldMap::onGoHome, this));
+ mCommitCallbackRegistrar.add("WMap.Teleport", boost::bind(&LLFloaterWorldMap::onClickTeleportBtn, this));
+ mCommitCallbackRegistrar.add("WMap.ShowTarget", boost::bind(&LLFloaterWorldMap::onShowTargetBtn, this));
+ mCommitCallbackRegistrar.add("WMap.ShowAgent", boost::bind(&LLFloaterWorldMap::onShowAgentBtn, this));
+ mCommitCallbackRegistrar.add("WMap.Clear", boost::bind(&LLFloaterWorldMap::onClearBtn, this));
+ mCommitCallbackRegistrar.add("WMap.CopySLURL", boost::bind(&LLFloaterWorldMap::onCopySLURL, this));
}
// static
void* LLFloaterWorldMap::createWorldMapView(void* data)
{
- return new LLWorldMapView(std::string("mapview"), LLRect(0,300,400,0));
+ return new LLWorldMapView();
}
BOOL LLFloaterWorldMap::postBuild()
{
- mTabs = getChild<LLTabContainer>("maptab");
- if (!mTabs) return FALSE;
-
- LLPanel *panel;
-
- panel = mTabs->getChild<LLPanel>("objects_mapview");
- if (panel)
- {
- mTabs->setTabChangeCallback(panel, onCommitBackground);
- mTabs->setTabUserData(panel, this);
- }
- panel = mTabs->getChild<LLPanel>("terrain_mapview");
- if (panel)
- {
- mTabs->setTabChangeCallback(panel, onCommitBackground);
- mTabs->setTabUserData(panel, this);
- }
-
- // The following callback syncs the worlmap tabs with the images.
- // Commented out since it was crashing when LLWorldMap became a singleton.
- // We should be fine without it but override the onOpen method and put it
- // there if it turns out to be needed. -MG
- //
- //onCommitBackground((void*)this, false);
-
- childSetCommitCallback("friend combo", onAvatarComboCommit, this);
+ mPanel = getChild<LLPanel>("objects_mapview");
LLComboBox *avatar_combo = getChild<LLComboBox>("friend combo");
if (avatar_combo)
{
avatar_combo->selectFirstItem();
- avatar_combo->setPrearrangeCallback( onAvatarComboPrearrange );
- avatar_combo->setTextEntryCallback( onComboTextEntry );
+ avatar_combo->setPrearrangeCallback( boost::bind(&LLFloaterWorldMap::onAvatarComboPrearrange, this) );
+ avatar_combo->setTextEntryCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );
}
- childSetAction("DoSearch", onLocationCommit, this);
-
- childSetFocusChangedCallback("location", onLocationFocusChanged, this);
+ getChild<LLScrollListCtrl>("location")->setFocusChangedCallback(boost::bind(&LLFloaterWorldMap::onLocationFocusChanged, this, _1));
LLLineEditor *location_editor = getChild<LLLineEditor>("location");
if (location_editor)
{
- location_editor->setKeystrokeCallback( onSearchTextEntry );
+ location_editor->setKeystrokeCallback( boost::bind(&LLFloaterWorldMap::onSearchTextEntry, this, _1), NULL );
}
- childSetCommitCallback("search_results", onCommitSearchResult, this);
- childSetDoubleClickCallback("search_results", onClickTeleportBtn);
- childSetCommitCallback("spin x", onCommitLocation, this);
- childSetCommitCallback("spin y", onCommitLocation, this);
- childSetCommitCallback("spin z", onCommitLocation, this);
-
- childSetCommitCallback("landmark combo", onLandmarkComboCommit, this);
+ getChild<LLScrollListCtrl>("search_results")->setDoubleClickCallback( boost::bind(&LLFloaterWorldMap::onClickTeleportBtn, this));
LLComboBox *landmark_combo = getChild<LLComboBox>( "landmark combo");
if (landmark_combo)
{
landmark_combo->selectFirstItem();
- landmark_combo->setPrearrangeCallback( onLandmarkComboPrearrange );
- landmark_combo->setTextEntryCallback( onComboTextEntry );
+ landmark_combo->setPrearrangeCallback( boost::bind(&LLFloaterWorldMap::onLandmarkComboPrearrange, this) );
+ landmark_combo->setTextEntryCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );
}
- childSetAction("Go Home", onGoHome, this);
-
- childSetAction("Teleport", onClickTeleportBtn, this);
-
- childSetAction("Show Destination", onShowTargetBtn, this);
- childSetAction("Show My Location", onShowAgentBtn, this);
- childSetAction("Clear", onClearBtn, this);
- childSetAction("copy_slurl", onCopySLURL, this);
-
- mCurZoomVal = log(gMapScale)/log(2.f);
- childSetValue("zoom slider", gMapScale);
+ mCurZoomVal = log(LLWorldMapView::sMapScale)/log(2.f);
+ childSetValue("zoom slider", LLWorldMapView::sMapScale);
setDefaultBtn(NULL);
@@ -259,7 +265,7 @@ BOOL LLFloaterWorldMap::postBuild()
LLFloaterWorldMap::~LLFloaterWorldMap()
{
// All cleaned up by LLView destructor
- mTabs = NULL;
+ mPanel = NULL;
// Inventory deletes all observers on shutdown
mInventory = NULL;
@@ -267,28 +273,34 @@ LLFloaterWorldMap::~LLFloaterWorldMap()
// avatar tracker will delete this for us.
mFriendObserver = NULL;
+
+ gFloaterWorldMap = NULL;
}
+//static
+LLFloaterWorldMap* LLFloaterWorldMap::getInstance()
+{
+ return LLFloaterReg::getTypedInstance<LLFloaterWorldMap>("world_map");
+}
// virtual
void LLFloaterWorldMap::onClose(bool app_quitting)
{
- setVisible(FALSE);
+ // While we're not visible, discard the overlay images we're using
+ LLWorldMap::getInstance()->clearImageRefs();
}
-// static
-void LLFloaterWorldMap::show(void*, BOOL center_on_target)
+// virtual
+void LLFloaterWorldMap::onOpen(const LLSD& key)
{
- BOOL was_visible = gFloaterWorldMap->getVisible();
+ bool center_on_target = (key.asString() == "center");
- gFloaterWorldMap->mIsClosing = FALSE;
- gFloaterWorldMap->open(); /* Flawfinder: ignore */
+ mIsClosing = FALSE;
LLWorldMapView* map_panel;
- map_panel = (LLWorldMapView*)gFloaterWorldMap->mTabs->getCurrentPanel();
+ map_panel = (LLWorldMapView*)gFloaterWorldMap->mPanel;
map_panel->clearLastClick();
- if (!was_visible)
{
// reset pan on show, so it centers on you again
if (!center_on_target)
@@ -297,40 +309,33 @@ void LLFloaterWorldMap::show(void*, BOOL center_on_target)
}
map_panel->updateVisibleBlocks();
- // Reload the agent positions when we show the window
- LLWorldMap::getInstance()->eraseItems();
-
- // Reload any maps that may have changed
- LLWorldMap::getInstance()->clearSimFlags();
-
- const S32 panel_num = gFloaterWorldMap->mTabs->getCurrentPanelIndex();
- const bool request_from_sim = true;
- LLWorldMap::getInstance()->setCurrentLayer(panel_num, request_from_sim);
+ // Reload items as they may have changed
+ LLWorldMap::getInstance()->reloadItems();
// We may already have a bounding box for the regions of the world,
// so use that to adjust the view.
- gFloaterWorldMap->adjustZoomSliderBounds();
+ adjustZoomSliderBounds();
// Could be first show
- LLFirstUse::useMap();
+ //LLFirstUse::useMap();
// Start speculative download of landmarks
- LLUUID landmark_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK);
+ const LLUUID landmark_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
gInventory.startBackgroundFetch(landmark_folder_id);
- gFloaterWorldMap->childSetFocus("location", TRUE);
+ childSetFocus("location", TRUE);
gFocusMgr.triggerFocusFlash();
- gFloaterWorldMap->buildAvatarIDList();
- gFloaterWorldMap->buildLandmarkIDLists();
+ buildAvatarIDList();
+ buildLandmarkIDLists();
// If nothing is being tracked, set flag so the user position will be found
- gFloaterWorldMap->mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING );
+ mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING );
}
if (center_on_target)
{
- gFloaterWorldMap->centerOnTarget(FALSE);
+ centerOnTarget(FALSE);
}
}
@@ -339,52 +344,9 @@ void LLFloaterWorldMap::show(void*, BOOL center_on_target)
// static
void LLFloaterWorldMap::reloadIcons(void*)
{
- LLWorldMap::getInstance()->eraseItems();
-
- LLWorldMap::getInstance()->sendMapLayerRequest();
-}
-
-
-// static
-void LLFloaterWorldMap::toggle(void*)
-{
- BOOL visible = gFloaterWorldMap->getVisible();
-
- if (!visible)
- {
- show(NULL, FALSE);
- }
- else
- {
- gFloaterWorldMap->mIsClosing = TRUE;
- gFloaterWorldMap->close();
- }
-}
-
-
-// static
-void LLFloaterWorldMap::hide(void*)
-{
- gFloaterWorldMap->mIsClosing = TRUE;
- gFloaterWorldMap->close();
-}
-
-
-// virtual
-void LLFloaterWorldMap::setVisible( BOOL visible )
-{
- LLFloater::setVisible( visible );
-
- gSavedSettings.setBOOL( "ShowWorldMap", visible );
-
- if( !visible )
- {
- // While we're not visible, discard the overlay images we're using
- LLWorldMap::getInstance()->clearImageRefs();
- }
+ LLWorldMap::getInstance()->reloadItems();
}
-
// virtual
BOOL LLFloaterWorldMap::handleHover(S32 x, S32 y, MASK mask)
{
@@ -416,18 +378,15 @@ BOOL LLFloaterWorldMap::handleScrollWheel(S32 x, S32 y, S32 clicks)
void LLFloaterWorldMap::reshape( S32 width, S32 height, BOOL called_from_parent )
{
LLFloater::reshape( width, height, called_from_parent );
-
- // Might have changed size of world display area
- // JC: Technically, this is correct, but it makes the slider "pop"
- // if you resize the window, then draw the slider. Just leaving it
- // the way it was when you opened the window seems better.
- // adjustZoomSliderBounds();
}
// virtual
void LLFloaterWorldMap::draw()
{
+ static LLUIColor map_track_color = LLUIColorTable::instance().getColor("MapTrackColor", LLColor4::white);
+ static LLUIColor map_track_disabled_color = LLUIColorTable::instance().getColor("MapTrackDisabledColor", LLColor4::white);
+
// Hide/Show Mature Events controls
childSetVisible("events_mature_icon", gAgent.canAccessMature());
childSetVisible("events_mature_label", gAgent.canAccessMature());
@@ -456,25 +415,25 @@ void LLFloaterWorldMap::draw()
LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus();
if (LLTracker::TRACKING_AVATAR == tracking_status)
{
- childSetColor("avatar_icon", gTrackColor);
+ childSetColor("avatar_icon", map_track_color);
}
else
{
- childSetColor("avatar_icon", gDisabledTrackColor);
+ childSetColor("avatar_icon", map_track_disabled_color);
}
if (LLTracker::TRACKING_LANDMARK == tracking_status)
{
- childSetColor("landmark_icon", gTrackColor);
+ childSetColor("landmark_icon", map_track_color);
}
else
{
- childSetColor("landmark_icon", gDisabledTrackColor);
+ childSetColor("landmark_icon", map_track_disabled_color);
}
if (LLTracker::TRACKING_LOCATION == tracking_status)
{
- childSetColor("location_icon", gTrackColor);
+ childSetColor("location_icon", map_track_color);
}
else
{
@@ -482,13 +441,13 @@ void LLFloaterWorldMap::draw()
{
F64 seconds = LLTimer::getElapsedSeconds();
double value = fmod(seconds, 2);
- value = 0.5 + 0.5*cos(value * 3.14159f);
+ value = 0.5 + 0.5*cos(value * F_PI);
LLColor4 loading_color(0.0, F32(value/2), F32(value), 1.0);
childSetColor("location_icon", loading_color);
}
else
{
- childSetColor("location_icon", gDisabledTrackColor);
+ childSetColor("location_icon", map_track_disabled_color);
}
}
@@ -500,7 +459,7 @@ void LLFloaterWorldMap::draw()
childSetEnabled("Teleport", (BOOL)tracking_status);
// childSetEnabled("Clear", (BOOL)tracking_status);
- childSetEnabled("Show Destination", (BOOL)tracking_status || LLWorldMap::getInstance()->mIsTrackingUnknownLocation);
+ childSetEnabled("Show Destination", (BOOL)tracking_status || LLWorldMap::getInstance()->isTracking());
childSetEnabled("copy_slurl", (mSLURL.size() > 0) );
setMouseOpaque(TRUE);
@@ -520,6 +479,18 @@ void LLFloaterWorldMap::draw()
mCurZoomVal = lerp(mCurZoomVal, (F32)childGetValue("zoom slider").asReal(), interp);
F32 map_scale = 256.f*pow(2.f, mCurZoomVal);
LLWorldMapView::setScale( map_scale );
+
+ // 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();
+ childSetEnabled("people_chk", enable);
+ childSetEnabled("infohub_chk", enable);
+ childSetEnabled("telehub_chk", enable);
+ childSetEnabled("land_for_sale_chk", enable);
+ childSetEnabled("event_chk", enable);
+ childSetEnabled("event_mature_chk", enable);
+ childSetEnabled("event_adult_chk", enable);
LLFloater::draw();
}
@@ -608,14 +579,14 @@ void LLFloaterWorldMap::trackLandmark( const LLUUID& landmark_item_id )
void LLFloaterWorldMap::trackEvent(const LLItemInfo &event_info)
{
mTrackedStatus = LLTracker::TRACKING_LOCATION;
- LLTracker::trackLocation(event_info.mPosGlobal, event_info.mName, event_info.mToolTip, LLTracker::LOCATION_EVENT);
+ LLTracker::trackLocation(event_info.getGlobalPosition(), event_info.getName(), event_info.getToolTip(), LLTracker::LOCATION_EVENT);
setDefaultBtn("Teleport");
}
void LLFloaterWorldMap::trackGenericItem(const LLItemInfo &item)
{
mTrackedStatus = LLTracker::TRACKING_LOCATION;
- LLTracker::trackLocation(item.mPosGlobal, item.mName, item.mToolTip, LLTracker::LOCATION_ITEM);
+ LLTracker::trackLocation(item.getGlobalPosition(), item.getName(), item.getToolTip(), LLTracker::LOCATION_ITEM);
setDefaultBtn("Teleport");
}
@@ -624,29 +595,27 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global)
LLSimInfo* sim_info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global);
if (!sim_info)
{
- LLWorldMap::getInstance()->mIsTrackingUnknownLocation = TRUE;
- LLWorldMap::getInstance()->mInvalidLocation = FALSE;
- LLWorldMap::getInstance()->mUnknownLocation = pos_global;
+ // We haven't found a region for that point yet, leave the tracking to the world map
+ LLWorldMap::getInstance()->setTracking(pos_global);
LLTracker::stopTracking(NULL);
S32 world_x = S32(pos_global.mdV[0] / 256);
S32 world_y = S32(pos_global.mdV[1] / 256);
- LLWorldMap::getInstance()->sendMapBlockRequest(world_x, world_y, world_x, world_y, true);
+ LLWorldMapMessage::getInstance()->sendMapBlockRequest(world_x, world_y, world_x, world_y, true);
setDefaultBtn("");
return;
}
- if (sim_info->mAccess == SIM_ACCESS_DOWN)
+ if (sim_info->isDown())
{
- // Down sim. Show the blue circle of death!
- LLWorldMap::getInstance()->mIsTrackingUnknownLocation = TRUE;
- LLWorldMap::getInstance()->mUnknownLocation = pos_global;
- LLWorldMap::getInstance()->mInvalidLocation = TRUE;
+ // Down region. Show the blue circle of death!
+ // i.e. let the world map that this and tell it it's invalid
+ LLWorldMap::getInstance()->setTracking(pos_global);
+ LLWorldMap::getInstance()->setTrackingInvalid();
LLTracker::stopTracking(NULL);
setDefaultBtn("");
return;
}
- std::string sim_name;
- LLWorldMap::getInstance()->simNameFromPosGlobal( pos_global, sim_name );
+ std::string sim_name = sim_info->getName();
F32 region_x = (F32)fmod( pos_global.mdV[VX], (F64)REGION_WIDTH_METERS );
F32 region_y = (F32)fmod( pos_global.mdV[VY], (F64)REGION_WIDTH_METERS );
std::string full_name = llformat("%s (%d, %d, %d)",
@@ -658,9 +627,7 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global)
std::string tooltip("");
mTrackedStatus = LLTracker::TRACKING_LOCATION;
LLTracker::trackLocation(pos_global, full_name, tooltip);
- LLWorldMap::getInstance()->mIsTrackingUnknownLocation = FALSE;
- LLWorldMap::getInstance()->mIsTrackingDoubleClick = FALSE;
- LLWorldMap::getInstance()->mIsTrackingCommit = FALSE;
+ LLWorldMap::getInstance()->cancelTracking(); // The floater is taking over the tracking
setDefaultBtn("Teleport");
}
@@ -698,12 +665,8 @@ void LLFloaterWorldMap::updateLocation()
S32 agent_y = llround( (F32)fmod( agentPos.mdV[VY], (F64)REGION_WIDTH_METERS ) );
S32 agent_z = llround( (F32)agentPos.mdV[VZ] );
- childSetValue("spin x", LLSD(agent_x) );
- childSetValue("spin y", LLSD(agent_y) );
- childSetValue("spin z", LLSD(agent_z) );
-
// Set the current SLURL
- mSLURL = LLURLDispatcher::buildSLURL(agent_sim_name, agent_x, agent_y, agent_z);
+ mSLURL = LLSLURL::buildSLURL(agent_sim_name, agent_x, agent_y, agent_z);
}
}
@@ -733,14 +696,11 @@ void LLFloaterWorldMap::updateLocation()
F32 region_x = (F32)fmod( pos_global.mdV[VX], (F64)REGION_WIDTH_METERS );
F32 region_y = (F32)fmod( pos_global.mdV[VY], (F64)REGION_WIDTH_METERS );
- childSetValue("spin x", LLSD(region_x) );
- childSetValue("spin y", LLSD(region_y) );
- childSetValue("spin z", LLSD((F32)pos_global.mdV[VZ]) );
// simNameFromPosGlobal can fail, so don't give the user an invalid SLURL
if ( gotSimName )
{
- mSLURL = LLURLDispatcher::buildSLURL(sim_name, llround(region_x), llround(region_y), llround((F32)pos_global.mdV[VZ]));
+ mSLURL = LLSLURL::buildSLURL(sim_name, llround(region_x), llround(region_y), llround((F32)pos_global.mdV[VZ]));
}
else
{ // Empty SLURL will disable the "Copy SLURL to clipboard" button
@@ -767,15 +727,17 @@ void LLFloaterWorldMap::trackURL(const std::string& region_name, S32 x_coord, S3
{
// fill in UI based on URL
gFloaterWorldMap->childSetValue("location", region_name);
- childSetValue("spin x", LLSD((F32)x_coord));
- childSetValue("spin y", LLSD((F32)y_coord));
- childSetValue("spin z", LLSD((F32)z_coord));
+
+ // Save local coords to highlight position after region global
+ // position is returned.
+ gFloaterWorldMap->mCompletingRegionPos.set(
+ (F32)x_coord, (F32)y_coord, (F32)z_coord);
// pass sim name to combo box
gFloaterWorldMap->mCompletingRegionName = region_name;
- LLWorldMap::getInstance()->sendNamedRegionRequest(region_name);
+ LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name);
LLStringUtil::toLower(gFloaterWorldMap->mCompletingRegionName);
- LLWorldMap::getInstance()->mIsTrackingCommit = TRUE;
+ LLWorldMap::getInstance()->setTrackingCommit();
}
}
@@ -842,19 +804,12 @@ void LLFloaterWorldMap::buildAvatarIDList()
// Delete all but the "None" entry
S32 list_size = list->getItemCount();
- while (list_size > 1)
+ if (list_size > 1)
{
- list->selectNthItem(1);
+ list->selectItemRange(1, -1);
list->operateOnSelection(LLCtrlListInterface::OP_DELETE);
- --list_size;
}
- LLSD default_column;
- default_column["name"] = "friend name";
- default_column["label"] = "Friend Name";
- default_column["width"] = 500;
- list->addColumn(default_column);
-
// Get all of the calling cards for avatar that are currently online
LLCollectMappableBuddies collector;
LLAvatarTracker::instance().applyFunctor(collector);
@@ -875,10 +830,7 @@ void LLFloaterWorldMap::buildAvatarIDList()
void LLFloaterWorldMap::buildLandmarkIDLists()
{
LLCtrlListInterface *list = childGetListInterface("landmark combo");
- if (!list)
- {
- return;
- }
+ if (!list) return;
// Delete all but the "None" entry
S32 list_size = list->getItemCount();
@@ -901,7 +853,7 @@ void LLFloaterWorldMap::buildLandmarkIDLists()
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
LLIsType is_landmark(LLAssetType::AT_LANDMARK);
- gInventory.collectDescendentsIf(gAgent.getInventoryRootID(),
+ gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
cats,
items,
LLInventoryModel::EXCLUDE_TRASH,
@@ -919,7 +871,6 @@ void LLFloaterWorldMap::buildLandmarkIDLists()
mLandmarkAssetIDList.put( item->getAssetUUID() );
mLandmarkItemIDList.put( item->getUUID() );
}
- list->sortByColumn(std::string("landmark name"), TRUE);
list->selectFirstItem();
}
@@ -944,21 +895,8 @@ void LLFloaterWorldMap::clearLocationSelection(BOOL clear_ui)
{
list->operateOnAll(LLCtrlListInterface::OP_DELETE);
}
- if (!childHasKeyboardFocus("spin x"))
- {
- childSetValue("spin x", SIM_COORD_DEFAULT);
- }
- if (!childHasKeyboardFocus("spin y"))
- {
- childSetValue("spin y", SIM_COORD_DEFAULT);
- }
- if (!childHasKeyboardFocus("spin z"))
- {
- childSetValue("spin z", 0);
- }
- LLWorldMap::getInstance()->mIsTrackingCommit = FALSE;
+ LLWorldMap::getInstance()->cancelTracking();
mCompletingRegionName = "";
- mExactMatch = FALSE;
}
@@ -993,18 +931,16 @@ void LLFloaterWorldMap::clearAvatarSelection(BOOL clear_ui)
// can see the whole world, plus a little.
void LLFloaterWorldMap::adjustZoomSliderBounds()
{
- // World size in regions
- S32 world_width_regions = LLWorldMap::getInstance()->getWorldWidth() / REGION_WIDTH_UNITS;
- S32 world_height_regions = LLWorldMap::getInstance()->getWorldHeight() / REGION_WIDTH_UNITS;
-
- // Pad the world size a little bit, so we have a nice border on
- // the edge
- world_width_regions++;
- world_height_regions++;
+ // 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
+ // sessions and doesn't prevent the user to pan the world if it was to grow a lot beyond that limit.
+ // Currently (01/26/09), this value allows the whole grid to be visible in a 1024x1024 window.
+ S32 world_width_regions = MAX_VISIBLE_REGIONS;
+ S32 world_height_regions = MAX_VISIBLE_REGIONS;
// Find how much space we have to display the world
LLWorldMapView* map_panel;
- map_panel = (LLWorldMapView*)mTabs->getCurrentPanel();
+ map_panel = (LLWorldMapView*)mPanel;
LLRect view_rect = map_panel->getRect();
// View size in pixels
@@ -1024,10 +960,11 @@ void LLFloaterWorldMap::adjustZoomSliderBounds()
// Make sure the zoom slider can be moved at least a little bit.
// Likewise, less than the increment pixels per region is just silly.
- pixels_per_region = llclamp(pixels_per_region, 1.f, (F32)(pow(2.f, ZOOM_MAX) * 128.f));
+ pixels_per_region = llclamp(pixels_per_region, 1.f, ZOOM_MAX);
F32 min_power = log(pixels_per_region/256.f)/log(2.f);
- childSetMinValue("zoom slider", min_power);
+
+ getChild<LLSlider>("zoom slider")->setMinValue(min_power);
}
@@ -1035,52 +972,26 @@ void LLFloaterWorldMap::adjustZoomSliderBounds()
// User interface widget callbacks
//-------------------------------------------------------------------------
-// static
-void LLFloaterWorldMap::onPanBtn( void* userdata )
-{
- if( !gFloaterWorldMap ) return;
-
- EPanDirection direction = (EPanDirection)(intptr_t)userdata;
-
- S32 pan_x = 0;
- S32 pan_y = 0;
- switch( direction )
- {
- case PAN_UP: pan_y = -1; break;
- case PAN_DOWN: pan_y = 1; break;
- case PAN_LEFT: pan_x = 1; break;
- case PAN_RIGHT: pan_x = -1; break;
- default: llassert(0); return;
- }
-
- LLWorldMapView* map_panel;
- map_panel = (LLWorldMapView*)gFloaterWorldMap->mTabs->getCurrentPanel();
- map_panel->translatePan( pan_x, pan_y );
-}
-
-// static
-void LLFloaterWorldMap::onGoHome(void*)
+void LLFloaterWorldMap::onGoHome()
{
gAgent.teleportHome();
- gFloaterWorldMap->close();
+ closeFloater();
}
-// static
-void LLFloaterWorldMap::onLandmarkComboPrearrange( LLUICtrl* ctrl, void* userdata )
+void LLFloaterWorldMap::onLandmarkComboPrearrange( )
{
- LLFloaterWorldMap* self = gFloaterWorldMap;
- if( !self || self->mIsClosing )
+ if( mIsClosing )
{
return;
}
- LLCtrlListInterface *list = self->childGetListInterface("landmark combo");
+ LLCtrlListInterface *list = childGetListInterface("landmark combo");
if (!list) return;
LLUUID current_choice = list->getCurrentID();
- gFloaterWorldMap->buildLandmarkIDLists();
+ buildLandmarkIDLists();
if( current_choice.isNull() || !list->setCurrentByID( current_choice ) )
{
@@ -1089,7 +1000,7 @@ void LLFloaterWorldMap::onLandmarkComboPrearrange( LLUICtrl* ctrl, void* userdat
}
-void LLFloaterWorldMap::onComboTextEntry( LLLineEditor* ctrl, void* userdata )
+void LLFloaterWorldMap::onComboTextEntry()
{
// Reset the tracking whenever we start typing into any of the search fields,
// so that hitting <enter> does an auto-complete versus teleporting us to the
@@ -1097,24 +1008,21 @@ void LLFloaterWorldMap::onComboTextEntry( LLLineEditor* ctrl, void* userdata )
LLTracker::clearFocus();
}
-// static
-void LLFloaterWorldMap::onSearchTextEntry( LLLineEditor* ctrl, void* userdata )
+void LLFloaterWorldMap::onSearchTextEntry( LLLineEditor* ctrl )
{
- onComboTextEntry(ctrl, userdata);
- updateSearchEnabled(ctrl, userdata);
+ onComboTextEntry();
+ updateSearchEnabled();
}
-// static
-void LLFloaterWorldMap::onLandmarkComboCommit( LLUICtrl* ctrl, void* userdata )
-{
- LLFloaterWorldMap* self = gFloaterWorldMap;
- if( !self || self->mIsClosing )
+void LLFloaterWorldMap::onLandmarkComboCommit()
+{
+ if( mIsClosing )
{
return;
}
- LLCtrlListInterface *list = gFloaterWorldMap->childGetListInterface("landmark combo");
+ LLCtrlListInterface *list = childGetListInterface("landmark combo");
if (!list) return;
LLUUID asset_id;
@@ -1146,23 +1054,22 @@ void LLFloaterWorldMap::onLandmarkComboCommit( LLUICtrl* ctrl, void* userdata )
}
}
- self->trackLandmark( item_id);
- onShowTargetBtn(self);
+ trackLandmark( item_id);
+ onShowTargetBtn();
// Reset to user postion if nothing is tracked
- self->mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING );
+ mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING );
}
// static
-void LLFloaterWorldMap::onAvatarComboPrearrange( LLUICtrl* ctrl, void* userdata )
+void LLFloaterWorldMap::onAvatarComboPrearrange( )
{
- LLFloaterWorldMap* self = gFloaterWorldMap;
- if( !self || self->mIsClosing )
+ if( mIsClosing )
{
return;
}
- LLCtrlListInterface *list = self->childGetListInterface("friend combo");
+ LLCtrlListInterface *list = childGetListInterface("friend combo");
if (!list) return;
LLUUID current_choice;
@@ -1172,7 +1079,7 @@ void LLFloaterWorldMap::onAvatarComboPrearrange( LLUICtrl* ctrl, void* userdata
current_choice = LLAvatarTracker::instance().getAvatarID();
}
- self->buildAvatarIDList();
+ buildAvatarIDList();
if( !list->setCurrentByID( current_choice ) || current_choice.isNull() )
{
@@ -1180,152 +1087,118 @@ void LLFloaterWorldMap::onAvatarComboPrearrange( LLUICtrl* ctrl, void* userdata
}
}
-
-// static
-void LLFloaterWorldMap::onAvatarComboCommit( LLUICtrl* ctrl, void* userdata )
+void LLFloaterWorldMap::onAvatarComboCommit()
{
- LLFloaterWorldMap* self = gFloaterWorldMap;
- if( !self || self->mIsClosing )
+ if( mIsClosing )
{
return;
}
- LLCtrlListInterface *list = gFloaterWorldMap->childGetListInterface("friend combo");
+ LLCtrlListInterface *list = childGetListInterface("friend combo");
if (!list) return;
const LLUUID& new_avatar_id = list->getCurrentID();
if (new_avatar_id.notNull())
{
std::string name;
- LLComboBox* combo = gFloaterWorldMap->getChild<LLComboBox>("friend combo");
+ LLComboBox* combo = getChild<LLComboBox>("friend combo");
if (combo) name = combo->getSimple();
- self->trackAvatar(new_avatar_id, name);
- onShowTargetBtn(self);
+ trackAvatar(new_avatar_id, name);
+ onShowTargetBtn();
}
else
{ // Reset to user postion if nothing is tracked
- self->mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING );
+ mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING );
}
}
-//static
-void LLFloaterWorldMap::onLocationFocusChanged( LLFocusableElement* focus, void* userdata )
+void LLFloaterWorldMap::onLocationFocusChanged( LLFocusableElement* focus )
{
- updateSearchEnabled((LLUICtrl*)focus, userdata);
+ updateSearchEnabled();
}
-// static
-void LLFloaterWorldMap::updateSearchEnabled( LLUICtrl* ctrl, void* userdata )
+void LLFloaterWorldMap::updateSearchEnabled()
{
- LLFloaterWorldMap *self = gFloaterWorldMap;
- if (self->childHasKeyboardFocus("location") &&
- self->childGetValue("location").asString().length() > 0)
+ if (childHasKeyboardFocus("location") &&
+ childGetValue("location").asString().length() > 0)
{
- self->setDefaultBtn("DoSearch");
+ setDefaultBtn("DoSearch");
}
else
{
- self->setDefaultBtn(NULL);
+ setDefaultBtn(NULL);
}
}
-// static
-void LLFloaterWorldMap::onLocationCommit( void* userdata )
+void LLFloaterWorldMap::onLocationCommit()
{
- LLFloaterWorldMap *self = gFloaterWorldMap;
- if( !self || self->mIsClosing )
+ if( mIsClosing )
{
return;
}
- self->clearLocationSelection(FALSE);
- self->mCompletingRegionName = "";
- self->mLastRegionName = "";
+ clearLocationSelection(FALSE);
+ mCompletingRegionName = "";
+ mLastRegionName = "";
- std::string str = self->childGetValue("location").asString();
+ std::string str = childGetValue("location").asString();
// Trim any leading and trailing spaces in the search target
std::string saved_str = str;
LLStringUtil::trim( str );
if ( str != saved_str )
{ // Set the value in the UI if any spaces were removed
- self->childSetValue("location", str);
+ childSetValue("location", str);
}
LLStringUtil::toLower(str);
- gFloaterWorldMap->mCompletingRegionName = str;
- LLWorldMap::getInstance()->mIsTrackingCommit = TRUE;
- self->mExactMatch = FALSE;
+ mCompletingRegionName = str;
+ LLWorldMap::getInstance()->setTrackingCommit();
if (str.length() >= 3)
{
- LLWorldMap::getInstance()->sendNamedRegionRequest(str);
+ LLWorldMapMessage::getInstance()->sendNamedRegionRequest(str);
}
else
{
str += "#";
- LLWorldMap::getInstance()->sendNamedRegionRequest(str);
+ LLWorldMapMessage::getInstance()->sendNamedRegionRequest(str);
}
}
-
-// static
-void LLFloaterWorldMap::onClearBtn(void* data)
+void LLFloaterWorldMap::onClearBtn()
{
- LLFloaterWorldMap* self = (LLFloaterWorldMap*)data;
- self->mTrackedStatus = LLTracker::TRACKING_NOTHING;
+ mTrackedStatus = LLTracker::TRACKING_NOTHING;
LLTracker::stopTracking((void *)(intptr_t)TRUE);
- LLWorldMap::getInstance()->mIsTrackingUnknownLocation = FALSE;
- self->mSLURL = ""; // Clear the SLURL since it's invalid
- self->mSetToUserPosition = TRUE; // Revert back to the current user position
-}
-
-// static
-void LLFloaterWorldMap::onFlyBtn(void* data)
-{
- LLFloaterWorldMap* self = (LLFloaterWorldMap*)data;
- self->fly();
+ LLWorldMap::getInstance()->cancelTracking();
+ mSLURL = ""; // Clear the SLURL since it's invalid
+ mSetToUserPosition = TRUE; // Revert back to the current user position
}
-void LLFloaterWorldMap::onShowTargetBtn(void* data)
+void LLFloaterWorldMap::onShowTargetBtn()
{
- LLFloaterWorldMap* self = (LLFloaterWorldMap*)data;
- self->centerOnTarget(TRUE);
+ centerOnTarget(TRUE);
}
-void LLFloaterWorldMap::onShowAgentBtn(void* data)
+void LLFloaterWorldMap::onShowAgentBtn()
{
LLWorldMapView::setPan( 0, 0, FALSE); // FALSE == animate
-
// Set flag so user's location will be displayed if not tracking anything else
- LLFloaterWorldMap* self = (LLFloaterWorldMap*)data;
- self->mSetToUserPosition = TRUE;
+ mSetToUserPosition = TRUE;
}
-// static
-void LLFloaterWorldMap::onClickTeleportBtn(void* data)
+void LLFloaterWorldMap::onClickTeleportBtn()
{
- LLFloaterWorldMap* self = (LLFloaterWorldMap*)data;
- self->teleport();
+ teleport();
}
-// static
-void LLFloaterWorldMap::onCopySLURL(void* data)
+void LLFloaterWorldMap::onCopySLURL()
{
- LLFloaterWorldMap* self = (LLFloaterWorldMap*)data;
- gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(self->mSLURL));
+ getWindow()->copyTextToClipboard(utf8str_to_wstring(mSLURL));
LLSD args;
- args["SLURL"] = self->mSLURL;
-
- LLNotifications::instance().add("CopySLURL", args);
-}
+ args["SLURL"] = mSLURL;
-void LLFloaterWorldMap::onCheckEvents(LLUICtrl*, void* data)
-{
- LLFloaterWorldMap* self = (LLFloaterWorldMap*)data;
- if(!self) return;
- self->childSetEnabled("event_mature_chk", self->childGetValue("event_chk"));
- self->childSetEnabled("event_adult_chk", self->childGetValue("event_chk"));
+ LLNotificationsUtil::add("CopySLURL", args);
}
// protected
@@ -1349,9 +1222,9 @@ void LLFloaterWorldMap::centerOnTarget(BOOL animate)
pos_global = LLTracker::getTrackedPositionGlobal() - gAgent.getCameraPositionGlobal();
}
}
- else if(LLWorldMap::getInstance()->mIsTrackingUnknownLocation)
+ else if(LLWorldMap::getInstance()->isTracking())
{
- pos_global = LLWorldMap::getInstance()->mUnknownLocation - gAgent.getCameraPositionGlobal();;
+ pos_global = LLWorldMap::getInstance()->getTrackedPositionGlobal() - gAgent.getCameraPositionGlobal();;
}
else
{
@@ -1359,8 +1232,8 @@ void LLFloaterWorldMap::centerOnTarget(BOOL animate)
pos_global.clearVec();
}
- LLWorldMapView::setPan( -llfloor((F32)(pos_global.mdV[VX] * (F64)LLWorldMapView::sPixelsPerMeter)),
- -llfloor((F32)(pos_global.mdV[VY] * (F64)LLWorldMapView::sPixelsPerMeter)),
+ 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);
mWaitingForTracker = FALSE;
}
@@ -1375,7 +1248,7 @@ void LLFloaterWorldMap::fly()
if (!pos_global.isExactlyZero())
{
gAgent.startAutoPilotGlobal( pos_global );
- close();
+ closeFloater();
}
else
{
@@ -1447,24 +1320,6 @@ void LLFloaterWorldMap::teleport()
}
}
-// static
-void LLFloaterWorldMap::onGoToLandmarkDialog( S32 option, void* userdata )
-{
- LLFloaterWorldMap* self = (LLFloaterWorldMap*) userdata;
- switch( option )
- {
- case 0:
- self->teleportToLandmark();
- break;
- case 1:
- self->flyToLandmark();
- break;
- default:
- // nothing
- break;
- }
-}
-
void LLFloaterWorldMap::flyToLandmark()
{
LLVector3d destination_pos_global;
@@ -1536,17 +1391,6 @@ void LLFloaterWorldMap::flyToAvatar()
}
}
-// static
-void LLFloaterWorldMap::onCommitBackground(void* userdata, bool from_click)
-{
- LLFloaterWorldMap* self = (LLFloaterWorldMap*) userdata;
-
- // Find my index
- S32 index = self->mTabs->getCurrentPanelIndex();
-
- LLWorldMap::getInstance()->setCurrentLayer(index);
-}
-
void LLFloaterWorldMap::updateSims(bool found_null_sim)
{
if (mCompletingRegionName == "")
@@ -1557,90 +1401,59 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim)
LLScrollListCtrl *list = getChild<LLScrollListCtrl>("search_results");
list->operateOnAll(LLCtrlListInterface::OP_DELETE);
- LLSD selected_value = list->getSelectedValue();
-
S32 name_length = mCompletingRegionName.length();
- BOOL match_found = FALSE;
+ LLSD match;
+
S32 num_results = 0;
std::map<U64, LLSimInfo*>::const_iterator it;
- for (it = LLWorldMap::getInstance()->mSimInfoMap.begin(); it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it)
+ for (it = LLWorldMap::getInstance()->getRegionMap().begin(); it != LLWorldMap::getInstance()->getRegionMap().end(); ++it)
{
- LLSimInfo* info = (*it).second;
- std::string sim_name = info->mName;
- std::string sim_name_lower = sim_name;
+ LLSimInfo* info = it->second;
+ std::string sim_name_lower = info->getName();
LLStringUtil::toLower(sim_name_lower);
if (sim_name_lower.substr(0, name_length) == mCompletingRegionName)
{
- if (LLWorldMap::getInstance()->mIsTrackingCommit)
+ if (sim_name_lower == mCompletingRegionName)
{
- if (sim_name_lower == mCompletingRegionName)
- {
- selected_value = sim_name;
- match_found = TRUE;
- }
+ match = info->getName();
}
-
+
LLSD value;
- value["id"] = sim_name;
+ value["id"] = info->getName();
value["columns"][0]["column"] = "sim_name";
- value["columns"][0]["value"] = sim_name;
+ value["columns"][0]["value"] = info->getName();
list->addElement(value);
num_results++;
}
}
-
- list->selectByValue(selected_value);
if (found_null_sim)
{
mCompletingRegionName = "";
}
- if (match_found)
- {
- mExactMatch = TRUE;
- childSetFocus("search_results");
- onCommitSearchResult(NULL, this);
- }
- else if (!mExactMatch && num_results > 0)
+ // if match found, highlight it and go
+ if (!match.isUndefined())
{
- list->selectFirstItem(); // select first item by default
+ list->selectByValue(match);
childSetFocus("search_results");
- onCommitSearchResult(NULL, this);
+ onCommitSearchResult();
}
- else if (num_results == 0)
+
+ // if we found nothing, say "none"
+ if (num_results == 0)
{
- list->addCommentText(std::string("None found."));
+ list->setCommentText(LLTrans::getString("worldmap_results_none_found"));
list->operateOnAll(LLCtrlListInterface::OP_DESELECT);
}
}
-// static
-void LLFloaterWorldMap::onCommitLocation(LLUICtrl* ctrl, void* userdata)
-{
- LLFloaterWorldMap* self = (LLFloaterWorldMap*) userdata;
- LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus();
- if ( LLTracker::TRACKING_LOCATION == tracking_status)
- {
- LLVector3d pos_global = LLTracker::getTrackedPositionGlobal();
- F64 local_x = self->childGetValue("spin x");
- F64 local_y = self->childGetValue("spin y");
- F64 local_z = self->childGetValue("spin z");
- pos_global.mdV[VX] += -fmod(pos_global.mdV[VX], 256.0) + local_x;
- pos_global.mdV[VY] += -fmod(pos_global.mdV[VY], 256.0) + local_y;
- pos_global.mdV[VZ] = local_z;
- self->trackLocation(pos_global);
- }
-}
-// static
-void LLFloaterWorldMap::onCommitSearchResult(LLUICtrl*, void* userdata)
+void LLFloaterWorldMap::onCommitSearchResult()
{
- LLFloaterWorldMap* self = (LLFloaterWorldMap*) userdata;
-
- LLCtrlListInterface *list = self->childGetListInterface("search_results");
+ LLCtrlListInterface *list = childGetListInterface("search_results");
if (!list) return;
LLSD selected_value = list->getSelectedValue();
@@ -1652,28 +1465,33 @@ void LLFloaterWorldMap::onCommitSearchResult(LLUICtrl*, void* userdata)
LLStringUtil::toLower(sim_name);
std::map<U64, LLSimInfo*>::const_iterator it;
- for (it = LLWorldMap::getInstance()->mSimInfoMap.begin(); it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it)
+ for (it = LLWorldMap::getInstance()->getRegionMap().begin(); it != LLWorldMap::getInstance()->getRegionMap().end(); ++it)
{
- LLSimInfo* info = (*it).second;
- std::string info_sim_name = info->mName;
- LLStringUtil::toLower(info_sim_name);
+ LLSimInfo* info = it->second;
- if (sim_name == info_sim_name)
+ if (info->isName(sim_name))
{
- LLVector3d pos_global = from_region_handle( info->mHandle );
- F64 local_x = self->childGetValue("spin x");
- F64 local_y = self->childGetValue("spin y");
- F64 local_z = self->childGetValue("spin z");
- pos_global.mdV[VX] += local_x;
- pos_global.mdV[VY] += local_y;
- pos_global.mdV[VZ] = local_z;
-
- self->childSetValue("location", sim_name);
- self->trackLocation(pos_global);
- self->setDefaultBtn("Teleport");
+ LLVector3d pos_global = info->getGlobalOrigin();
+
+ const F64 SIM_COORD_DEFAULT = 128.0;
+ LLVector3 pos_local(SIM_COORD_DEFAULT, SIM_COORD_DEFAULT, 0.0f);
+
+ // Did this value come from a trackURL() request?
+ if (!mCompletingRegionPos.isExactlyZero())
+ {
+ pos_local = mCompletingRegionPos;
+ mCompletingRegionPos.clear();
+ }
+ pos_global.mdV[VX] += (F64)pos_local.mV[VX];
+ pos_global.mdV[VY] += (F64)pos_local.mV[VY];
+ pos_global.mdV[VZ] = (F64)pos_local.mV[VZ];
+
+ childSetValue("location", sim_name);
+ trackLocation(pos_global);
+ setDefaultBtn("Teleport");
break;
}
}
- onShowTargetBtn(self);
+ onShowTargetBtn();
}
diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h
index b0e72f298a..00f5e788fb 100644
--- a/indra/newview/llfloaterworldmap.h
+++ b/indra/newview/llfloaterworldmap.h
@@ -49,29 +49,29 @@ class LLFriendObserver;
class LLInventoryModel;
class LLInventoryObserver;
class LLItemInfo;
+class LLLineEditor;
class LLTabContainer;
-class LLWorldMapView;
class LLFloaterWorldMap : public LLFloater
{
public:
- LLFloaterWorldMap();
+ LLFloaterWorldMap(const LLSD& key);
virtual ~LLFloaterWorldMap();
+ // Prefer this to gFloaterWorldMap
+ static LLFloaterWorldMap* getInstance();
+
static void *createWorldMapView(void* data);
BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ void onClose(bool app_quitting);
- static void show(void*, BOOL center_on_target );
static void reloadIcons(void*);
- static void toggle(void*);
- static void hide(void*);
/*virtual*/ void reshape( S32 width, S32 height, BOOL called_from_parent = TRUE );
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
- /*virtual*/ void setVisible(BOOL visible);
/*virtual*/ void draw();
// methods for dealing with inventory. The observe() method is
@@ -96,7 +96,7 @@ public:
static const LLUUID& getHomeID() { return sHomeID; }
// A z_attenuation of 0.0f collapses the distance into the X-Y plane
- F32 getDistanceToDestination(const LLVector3d& pos_global, F32 z_attenuation = 0.5f) const;
+ F32 getDistanceToDestination(const LLVector3d& pos_global, F32 z_attenuation = 0.5f) const;
void clearLocationSelection(BOOL clear_ui = FALSE);
void clearAvatarSelection(BOOL clear_ui = FALSE);
@@ -112,30 +112,23 @@ public:
// teleport to the tracked item, if there is one
void teleport();
-protected:
- static void onPanBtn( void* userdata );
-
- static void onGoHome(void* data);
-
- static void onLandmarkComboPrearrange( LLUICtrl* ctrl, void* data );
- static void onLandmarkComboCommit( LLUICtrl* ctrl, void* data );
+protected:
+ void onGoHome();
- static void onAvatarComboPrearrange( LLUICtrl* ctrl, void* data );
- static void onAvatarComboCommit( LLUICtrl* ctrl, void* data );
+ void onLandmarkComboPrearrange();
+ void onLandmarkComboCommit();
- static void onCommitBackground(void* data, bool from_click);
+ void onAvatarComboPrearrange();
+ void onAvatarComboCommit();
- static void onComboTextEntry( LLLineEditor* ctrl, void* data );
- static void onSearchTextEntry( LLLineEditor* ctrl, void* data );
+ void onComboTextEntry( );
+ void onSearchTextEntry( LLLineEditor* ctrl );
- static void onClearBtn(void*);
- static void onFlyBtn(void*);
- static void onClickTeleportBtn(void*);
- static void onShowTargetBtn(void*);
- static void onShowAgentBtn(void*);
- static void onCopySLURL(void*);
-
- static void onCheckEvents(LLUICtrl* ctrl, void*);
+ void onClearBtn();
+ void onClickTeleportBtn();
+ void onShowTargetBtn();
+ void onShowAgentBtn();
+ void onCopySLURL();
void centerOnTarget(BOOL animate);
void updateLocation();
@@ -144,7 +137,6 @@ protected:
void fly();
void buildLandmarkIDLists();
- static void onGoToLandmarkDialog(S32 option,void* userdata);
void flyToLandmark();
void teleportToLandmark();
void setLandmarkVisited();
@@ -153,24 +145,22 @@ protected:
void flyToAvatar();
void teleportToAvatar();
- static void updateSearchEnabled( LLUICtrl* ctrl, void* userdata );
- static void onLocationFocusChanged( LLFocusableElement* ctrl, void* userdata );
- static void onLocationCommit( void* userdata );
- static void onCommitLocation( LLUICtrl* ctrl, void* userdata );
- static void onCommitSearchResult( LLUICtrl* ctrl, void* userdata );
+ void updateSearchEnabled();
+ void onLocationFocusChanged( LLFocusableElement* ctrl );
+ void onLocationCommit();
+ void onCommitSearchResult();
void cacheLandmarkPosition();
-protected:
- LLTabContainer* mTabs;
+private:
+ LLPanel* mPanel; // Panel displaying the map
- // Sets gMapScale, in pixels per region
+ // Ties to LLWorldMapView::sMapScale, in pixels per region
F32 mCurZoomVal;
LLFrameTimer mZoomTimer;
LLDynamicArray<LLUUID> mLandmarkAssetIDList;
LLDynamicArray<LLUUID> mLandmarkItemIDList;
- BOOL mHasLandmarkPosition;
static const LLUUID sHomeID;
@@ -179,9 +169,12 @@ protected:
LLFriendObserver* mFriendObserver;
std::string mCompletingRegionName;
+ // Local position from trackURL() request, used to select final
+ // position once region lookup complete.
+ LLVector3 mCompletingRegionPos;
+
std::string mLastRegionName;
BOOL mWaitingForTracker;
- BOOL mExactMatch;
BOOL mIsClosing;
BOOL mSetToUserPosition;
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 97a3bd7c50..b833c611bf 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -34,60 +34,58 @@
#include "llfolderview.h"
-#include <algorithm>
-
-#include "llviewercontrol.h"
-#include "lldbstrings.h"
-#include "llfocusmgr.h"
-#include "llfontgl.h"
-#include "llgl.h"
-#include "llrender.h"
-#include "llinventory.h"
-
#include "llcallbacklist.h"
+#include "llinventorybridge.h"
#include "llinventoryclipboard.h" // *TODO: remove this once hack below gone.
-#include "llinventoryview.h"// hacked in for the bonus context menu items.
+#include "llinventoryfilter.h"
+#include "llinventoryfunctions.h"
+#include "llinventorypanel.h"
+#include "llfoldertype.h"
+#include "llfloaterinventory.h"// hacked in for the bonus context menu items.
#include "llkeyboard.h"
#include "lllineeditor.h"
#include "llmenugl.h"
-#include "llresmgr.h"
+#include "llpanel.h"
#include "llpreview.h"
#include "llscrollcontainer.h" // hack to allow scrolling
#include "lltooldraganddrop.h"
+#include "lltrans.h"
#include "llui.h"
-#include "llviewerimage.h"
-#include "llviewerimagelist.h"
+#include "llviewertexture.h"
+#include "llviewertexturelist.h"
#include "llviewerjointattachment.h"
#include "llviewermenu.h"
#include "lluictrlfactory.h"
+#include "llviewercontrol.h"
+#include "llviewerfoldertype.h"
#include "llviewerwindow.h"
#include "llvoavatar.h"
#include "llfloaterproperties.h"
-// RN: HACK
-// We need these because some of the code below relies on things like
-// gAgent root folder. Remove them once the abstraction leak is fixed.
-#include "llagent.h"
-#include "llappviewer.h"
+// Linden library includes
+#include "lldbstrings.h"
+#include "llfocusmgr.h"
+#include "llfontgl.h"
+#include "llgl.h"
+#include "llrender.h"
+#include "llinventory.h"
+
+// Third-party library includes
+#include <algorithm>
///----------------------------------------------------------------------------
/// Local function declarations, constants, enums, and typedefs
///----------------------------------------------------------------------------
-const S32 LEFT_PAD = 5;
-const S32 LEFT_INDENTATION = 13;
-const S32 ICON_PAD = 2;
-const S32 ICON_WIDTH = 16;
-const S32 TEXT_PAD = 1;
-const S32 ARROW_SIZE = 12;
const S32 RENAME_WIDTH_PAD = 4;
-const S32 RENAME_HEIGHT_PAD = 6;
+const S32 RENAME_HEIGHT_PAD = 1;
const S32 AUTO_OPEN_STACK_DEPTH = 16;
-const S32 MIN_ITEM_WIDTH_VISIBLE = ICON_WIDTH + ICON_PAD + ARROW_SIZE + TEXT_PAD + /*first few characters*/ 40;
+const S32 MIN_ITEM_WIDTH_VISIBLE = LLFolderViewItem::ICON_WIDTH
+ + LLFolderViewItem::ICON_PAD
+ + LLFolderViewItem::ARROW_SIZE
+ + LLFolderViewItem::TEXT_PAD
+ + /*first few characters*/ 40;
const S32 MINIMUM_RENAMER_WIDTH = 80;
-const F32 FOLDER_CLOSE_TIME_CONSTANT = 0.02f;
-const F32 FOLDER_OPEN_TIME_CONSTANT = 0.03f;
-const S32 MAX_FOLDER_ITEM_OVERLAP = 2;
enum {
SIGNAL_NO_KEYBOARD_FOCUS = 1,
@@ -103,2328 +101,6 @@ void properties_selected_items(void* user_data);
void paste_items(void* user_data);
void renamer_focus_lost( LLFocusableElement* handler, void* user_data );
-///----------------------------------------------------------------------------
-/// Class LLFolderViewItem
-///----------------------------------------------------------------------------
-
-// statics
-const LLFontGL* LLFolderViewItem::sFont = NULL;
-const LLFontGL* LLFolderViewItem::sSmallFont = NULL;
-LLColor4 LLFolderViewItem::sFgColor;
-LLColor4 LLFolderViewItem::sHighlightBgColor;
-LLColor4 LLFolderViewItem::sHighlightFgColor;
-LLColor4 LLFolderViewItem::sFilterBGColor;
-LLColor4 LLFolderViewItem::sFilterTextColor;
-LLColor4 LLFolderViewItem::sSuffixColor;
-LLColor4 LLFolderViewItem::sSearchStatusColor;
-LLUIImagePtr LLFolderViewItem::sArrowImage;
-LLUIImagePtr LLFolderViewItem::sBoxImage;
-
-//static
-void LLFolderViewItem::initClass()
-{
- sFont = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL );
- sSmallFont = LLResMgr::getInstance()->getRes( LLFONT_SMALL );
- sFgColor = gColors.getColor( "MenuItemEnabledColor" );
- sHighlightBgColor = gColors.getColor( "MenuItemHighlightBgColor" );
- sHighlightFgColor = gColors.getColor( "MenuItemHighlightFgColor" );
- sFilterBGColor = gColors.getColor( "FilterBackgroundColor" );
- sFilterTextColor = gColors.getColor( "FilterTextColor" );
- sSuffixColor = gColors.getColor( "InventoryItemSuffixColor" );
- sSearchStatusColor = gColors.getColor( "InventorySearchStatusColor" );
- sArrowImage = LLUI::getUIImage("folder_arrow.tga");
- sBoxImage = LLUI::getUIImage("rounded_square.tga");
-}
-
-//static
-void LLFolderViewItem::cleanupClass()
-{
- sArrowImage = NULL;
- sBoxImage = NULL;
-}
-
-// Default constructor
-// NOTE: Optimize this, we call it a *lot* when opening a large inventory
-LLFolderViewItem::LLFolderViewItem( const std::string& name, LLUIImagePtr icon,
- time_t creation_date,
- LLFolderView* root,
- LLFolderViewEventListener* listener ) :
- LLUICtrl( name, LLRect(0, 0, 0, 0), TRUE, NULL, NULL, FOLLOWS_LEFT|FOLLOWS_TOP|FOLLOWS_RIGHT),
- mLabel( name ),
- mLabelWidth(0),
- mCreationDate(creation_date),
- mParentFolder( NULL ),
- mListener( listener ),
- mIsSelected( FALSE ),
- mIsCurSelection( FALSE ),
- mSelectPending(FALSE),
- mLabelStyle( LLFontGL::NORMAL ),
- mIcon(icon),
- mHasVisibleChildren(FALSE),
- mIndentation(0),
- mNumDescendantsSelected(0),
- mFiltered(FALSE),
- mLastFilterGeneration(-1),
- mStringMatchOffset(std::string::npos),
- mControlLabelRotation(0.f),
- mRoot( root ),
- mDragAndDropTarget(FALSE),
- mIsLoading(FALSE)
-{
- refresh(); // possible opt: only call refreshFromListener()
- setTabStop(FALSE);
-}
-
-// Destroys the object
-LLFolderViewItem::~LLFolderViewItem( void )
-{
- delete mListener;
- mListener = NULL;
-}
-
-LLFolderView* LLFolderViewItem::getRoot()
-{
- return mRoot;
-}
-
-// Returns true if this object is a child (or grandchild, etc.) of potential_ancestor.
-BOOL LLFolderViewItem::isDescendantOf( const LLFolderViewFolder* potential_ancestor )
-{
- LLFolderViewItem* root = this;
- while( root->mParentFolder )
- {
- if( root->mParentFolder == potential_ancestor )
- {
- return TRUE;
- }
- root = root->mParentFolder;
- }
- return FALSE;
-}
-
-LLFolderViewItem* LLFolderViewItem::getNextOpenNode(BOOL include_children)
-{
- if (!mParentFolder)
- {
- return NULL;
- }
-
- LLFolderViewItem* itemp = mParentFolder->getNextFromChild( this, include_children );
- while(itemp && !itemp->getVisible())
- {
- LLFolderViewItem* next_itemp = itemp->mParentFolder->getNextFromChild( itemp, include_children );
- if (itemp == next_itemp)
- {
- // hit last item
- return itemp->getVisible() ? itemp : this;
- }
- itemp = next_itemp;
- }
-
- return itemp;
-}
-
-LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children)
-{
- if (!mParentFolder)
- {
- return NULL;
- }
-
- LLFolderViewItem* itemp = mParentFolder->getPreviousFromChild( this, include_children );
- while(itemp && !itemp->getVisible())
- {
- LLFolderViewItem* next_itemp = itemp->mParentFolder->getPreviousFromChild( itemp, include_children );
- if (itemp == next_itemp)
- {
- // hit first item
- return itemp->getVisible() ? itemp : this;
- }
- itemp = next_itemp;
- }
-
- return itemp;
-}
-
-// is this item something we think we should be showing?
-// for example, if we haven't gotten around to filtering it yet, then the answer is yes
-// until we find out otherwise
-BOOL LLFolderViewItem::potentiallyVisible()
-{
- // we haven't been checked against min required filter
- // or we have and we passed
- return getLastFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration() || getFiltered();
-}
-
-BOOL LLFolderViewItem::getFiltered()
-{
- return mFiltered && mLastFilterGeneration >= mRoot->getFilter()->getMinRequiredGeneration();
-}
-
-BOOL LLFolderViewItem::getFiltered(S32 filter_generation)
-{
- return mFiltered && mLastFilterGeneration >= filter_generation;
-}
-
-void LLFolderViewItem::setFiltered(BOOL filtered, S32 filter_generation)
-{
- mFiltered = filtered;
- mLastFilterGeneration = filter_generation;
-}
-
-void LLFolderViewItem::setIcon(LLUIImagePtr icon)
-{
- mIcon = icon;
-}
-
-// refresh information from the listener
-void LLFolderViewItem::refreshFromListener()
-{
- if(mListener)
- {
- mLabel = mListener->getDisplayName();
- setIcon(mListener->getIcon());
- time_t creation_date = mListener->getCreationDate();
- if (mCreationDate != creation_date)
- {
- mCreationDate = mListener->getCreationDate();
- dirtyFilter();
- }
- mLabelStyle = mListener->getLabelStyle();
- mLabelSuffix = mListener->getLabelSuffix();
- }
-}
-
-void LLFolderViewItem::refresh()
-{
- refreshFromListener();
-
- std::string searchable_label(mLabel);
- searchable_label.append(mLabelSuffix);
- LLStringUtil::toUpper(searchable_label);
-
- if (mSearchableLabel.compare(searchable_label))
- {
- mSearchableLabel.assign(searchable_label);
- dirtyFilter();
- // some part of label has changed, so overall width has potentially changed
- if (mParentFolder)
- {
- mParentFolder->requestArrange();
- }
- }
-
- S32 label_width = sFont->getWidth(mLabel);
- if( mLabelSuffix.size() )
- {
- label_width += sFont->getWidth( mLabelSuffix );
- }
-
- mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + label_width;
-}
-
-void LLFolderViewItem::applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor)
-{
- functor(mListener);
-}
-
-// This function is called when items are added or view filters change. It's
-// implemented here but called by derived classes when folding the
-// views.
-void LLFolderViewItem::filterFromRoot( void )
-{
- LLFolderViewItem* root = getRoot();
-
- root->filter(*((LLFolderView*)root)->getFilter());
-}
-
-// This function is called when the folder view is dirty. It's
-// implemented here but called by derived classes when folding the
-// views.
-void LLFolderViewItem::arrangeFromRoot()
-{
- LLFolderViewItem* root = getRoot();
-
- S32 height = 0;
- S32 width = 0;
- root->arrange( &width, &height, 0 );
-}
-
-// This function clears the currently selected item, and records the
-// specified selected item appropriately for display and use in the
-// UI. If open is TRUE, then folders are opened up along the way to
-// the selection.
-void LLFolderViewItem::setSelectionFromRoot(LLFolderViewItem* selection,
- BOOL openitem,
- BOOL take_keyboard_focus)
-{
- getRoot()->setSelection(selection, openitem, take_keyboard_focus);
-}
-
-// helper function to change the selection from the root.
-void LLFolderViewItem::changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected)
-{
- getRoot()->changeSelection(selection, selected);
-}
-
-void LLFolderViewItem::extendSelectionFromRoot(LLFolderViewItem* selection)
-{
- LLDynamicArray<LLFolderViewItem*> selected_items;
-
- getRoot()->extendSelection(selection, NULL, selected_items);
-}
-
-EInventorySortGroup LLFolderViewItem::getSortGroup() const
-{
- return SG_ITEM;
-}
-
-// addToFolder() returns TRUE if it succeeds. FALSE otherwise
-BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* root)
-{
- if (!folder)
- {
- return FALSE;
- }
- mParentFolder = folder;
- root->addItemID(getListener()->getUUID(), this);
- return folder->addItem(this);
-}
-
-
-// Finds width and height of this object and it's children. Also
-// makes sure that this view and it's children are the right size.
-S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation)
-{
- mIndentation = mParentFolder ? mParentFolder->getIndentation() + LEFT_INDENTATION : 0;
- *width = llmax(*width, mLabelWidth + mIndentation);
- *height = getItemHeight();
- return *height;
-}
-
-S32 LLFolderViewItem::getItemHeight()
-{
- S32 icon_height = mIcon->getHeight();
- S32 label_height = llround(sFont->getLineHeight());
- return llmax( icon_height, label_height ) + ICON_PAD;
-}
-
-void LLFolderViewItem::filter( LLInventoryFilter& filter)
-{
- BOOL filtered = mListener && filter.check(this);
-
- // if our visibility will change as a result of this filter, then
- // we need to be rearranged in our parent folder
- if (getVisible() != filtered)
- {
- if (mParentFolder)
- {
- mParentFolder->requestArrange();
- }
- }
-
- setFiltered(filtered, filter.getCurrentGeneration());
- mStringMatchOffset = filter.getStringMatchOffset();
- filter.decrementFilterCount();
-
- if (getRoot()->getDebugFilters())
- {
- mStatusText = llformat("%d", mLastFilterGeneration);
- }
-}
-
-void LLFolderViewItem::dirtyFilter()
-{
- mLastFilterGeneration = -1;
- // bubble up dirty flag all the way to root
- if (getParentFolder())
- {
- getParentFolder()->setCompletedFilterGeneration(-1, TRUE);
- }
-}
-
-// *TODO: This can be optimized a lot by simply recording that it is
-// selected in the appropriate places, and assuming that set selection
-// means 'deselect' for a leaf item. Do this optimization after
-// multiple selection is implemented to make sure it all plays nice
-// together.
-BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus)
-{
- if( selection == this )
- {
- mIsSelected = TRUE;
- if(mListener)
- {
- mListener->selectItem();
- }
- }
- else
- {
- mIsSelected = FALSE;
- }
- return mIsSelected;
-}
-
-BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selected)
-{
- if(selection == this && mIsSelected != selected)
- {
- mIsSelected = selected;
- if(mListener)
- {
- mListener->selectItem();
- }
- return TRUE;
- }
- return FALSE;
-}
-
-void LLFolderViewItem::recursiveDeselect(BOOL deselect_self)
-{
- if (mIsSelected && deselect_self)
- {
- mIsSelected = FALSE;
-
- // update ancestors' count of selected descendents
- LLFolderViewFolder* parent_folder = getParentFolder();
- while(parent_folder)
- {
- parent_folder->mNumDescendantsSelected--;
- parent_folder = parent_folder->getParentFolder();
- }
- }
-}
-
-
-BOOL LLFolderViewItem::isMovable()
-{
- if( mListener )
- {
- return mListener->isItemMovable();
- }
- else
- {
- return TRUE;
- }
-}
-
-BOOL LLFolderViewItem::isRemovable()
-{
- if( mListener )
- {
- return mListener->isItemRemovable();
- }
- else
- {
- return TRUE;
- }
-}
-
-void LLFolderViewItem::destroyView()
-{
- if (mParentFolder)
- {
- // removeView deletes me
- mParentFolder->removeView(this);
- }
-}
-
-// Call through to the viewed object and return true if it can be
-// removed.
-//BOOL LLFolderViewItem::removeRecursively(BOOL single_item)
-BOOL LLFolderViewItem::remove()
-{
- if(!isRemovable())
- {
- return FALSE;
- }
- if(mListener)
- {
- return mListener->removeItem();
- }
- return TRUE;
-}
-
-// Build an appropriate context menu for the item.
-void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- if(mListener)
- {
- mListener->buildContextMenu(menu, flags);
- }
-}
-
-void LLFolderViewItem::openItem( void )
-{
- if( mListener )
- {
- mListener->openItem();
- }
-}
-
-void LLFolderViewItem::preview( void )
-{
- if (mListener)
- {
- mListener->previewItem();
- }
-}
-
-void LLFolderViewItem::rename(const std::string& new_name)
-{
- if( !new_name.empty() )
- {
- mLabel = new_name;
- if( mListener )
- {
- mListener->renameItem(new_name);
-
- if(mParentFolder)
- {
- mParentFolder->resort(this);
- }
- }
- }
-}
-
-const std::string& LLFolderViewItem::getSearchableLabel() const
-{
- return mSearchableLabel;
-}
-
-const std::string& LLFolderViewItem::getName( void ) const
-{
- if(mListener)
- {
- return mListener->getName();
- }
- return mLabel;
-}
-
-// LLView functionality
-BOOL LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask )
-{
- if(!mIsSelected)
- {
- setSelectionFromRoot(this, FALSE);
- }
- make_ui_sound("UISndClick");
- return TRUE;
-}
-
-BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask )
-{
- // No handler needed for focus lost since this class has no
- // state that depends on it.
- gFocusMgr.setMouseCapture( this );
-
- if (!mIsSelected)
- {
- if(mask & MASK_CONTROL)
- {
- changeSelectionFromRoot(this, !mIsSelected);
- }
- else if (mask & MASK_SHIFT)
- {
- extendSelectionFromRoot(this);
- }
- else
- {
- setSelectionFromRoot(this, FALSE);
- }
- make_ui_sound("UISndClick");
- }
- else
- {
- mSelectPending = TRUE;
- }
-
- if( isMovable() )
- {
- S32 screen_x;
- S32 screen_y;
- localPointToScreen(x, y, &screen_x, &screen_y );
- LLToolDragAndDrop::getInstance()->setDragStart( screen_x, screen_y );
- }
- return TRUE;
-}
-
-BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask )
-{
- if( hasMouseCapture() && isMovable() )
- {
- S32 screen_x;
- S32 screen_y;
- localPointToScreen(x, y, &screen_x, &screen_y );
- BOOL can_drag = TRUE;
- if( LLToolDragAndDrop::getInstance()->isOverThreshold( screen_x, screen_y ) )
- {
- LLFolderView* root = getRoot();
-
- if(root->getCurSelectedItem())
- {
- LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_WORLD;
-
- // *TODO: push this into listener and remove
- // dependency on llagent
- if(mListener && gInventory.isObjectDescendentOf(mListener->getUUID(), gAgent.getInventoryRootID()))
- {
- src = LLToolDragAndDrop::SOURCE_AGENT;
- }
- else if (mListener && gInventory.isObjectDescendentOf(mListener->getUUID(), gInventoryLibraryRoot))
- {
- src = LLToolDragAndDrop::SOURCE_LIBRARY;
- }
-
- can_drag = root->startDrag(src);
- if (can_drag)
- {
- // if (mListener) mListener->startDrag();
- // RN: when starting drag and drop, clear out last auto-open
- root->autoOpenTest(NULL);
- root->setShowSelectionContext(TRUE);
-
- // Release keyboard focus, so that if stuff is dropped into the
- // world, pressing the delete key won't blow away the inventory
- // item.
- gFocusMgr.setKeyboardFocus(NULL);
-
- return LLToolDragAndDrop::getInstance()->handleHover( x, y, mask );
- }
- }
- }
-
- if (can_drag)
- {
- gViewerWindow->setCursor(UI_CURSOR_ARROW);
- }
- else
- {
- gViewerWindow->setCursor(UI_CURSOR_NOLOCKED);
- }
- return TRUE;
- }
- else
- {
- getRoot()->setShowSelectionContext(FALSE);
- gViewerWindow->setCursor(UI_CURSOR_ARROW);
- // let parent handle this then...
- return FALSE;
- }
-}
-
-
-BOOL LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask )
-{
- preview();
- return TRUE;
-}
-
-BOOL LLFolderViewItem::handleScrollWheel(S32 x, S32 y, S32 clicks)
-{
- if (getParent())
- {
- return getParent()->handleScrollWheel(x, y, clicks);
- }
- return FALSE;
-}
-
-BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask )
-{
- // if mouse hasn't moved since mouse down...
- if ( pointInView(x, y) && mSelectPending )
- {
- //...then select
- if(mask & MASK_CONTROL)
- {
- changeSelectionFromRoot(this, !mIsSelected);
- }
- else if (mask & MASK_SHIFT)
- {
- extendSelectionFromRoot(this);
- }
- else
- {
- setSelectionFromRoot(this, FALSE);
- }
- }
-
- mSelectPending = FALSE;
-
- if( hasMouseCapture() )
- {
- getRoot()->setShowSelectionContext(FALSE);
- gFocusMgr.setMouseCapture( NULL );
- }
- return TRUE;
-}
-
-BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
- EDragAndDropType cargo_type,
- void* cargo_data,
- EAcceptance* accept,
- std::string& tooltip_msg)
-{
- BOOL accepted = FALSE;
- BOOL handled = FALSE;
- if(mListener)
- {
- accepted = mListener->dragOrDrop(mask,drop,cargo_type,cargo_data);
- handled = accepted;
- if (accepted)
- {
- mDragAndDropTarget = TRUE;
- *accept = ACCEPT_YES_MULTI;
- }
- else
- {
- *accept = ACCEPT_NO;
- }
- }
- if(mParentFolder && !handled)
- {
- handled = mParentFolder->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg);
- }
- if (handled)
- {
- lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewItem" << llendl;
- }
-
- return handled;
-}
-
-
-void LLFolderViewItem::draw()
-{
- bool possibly_has_children = false;
- bool up_to_date = mListener && mListener->isUpToDate();
- if((up_to_date && hasVisibleChildren() ) || // we fetched our children and some of them have passed the filter...
- (!up_to_date && mListener && mListener->hasChildren())) // ...or we know we have children but haven't fetched them (doesn't obey filter)
- {
- possibly_has_children = true;
- }
- if(/*mControlLabel[0] != '\0' && */possibly_has_children)
- {
- if (sArrowImage)
- {
- gl_draw_scaled_rotated_image(mIndentation, getRect().getHeight() - ARROW_SIZE - TEXT_PAD,
- ARROW_SIZE, ARROW_SIZE, mControlLabelRotation, sArrowImage->getImage(), sFgColor);
- }
- }
-
- F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation);
-
- // If we have keyboard focus, draw selection filled
- BOOL show_context = getRoot()->getShowSelectionContext();
- BOOL filled = show_context || (gFocusMgr.getKeyboardFocus() == getRoot());
-
- // always render "current" item, only render other selected items if
- // mShowSingleSelection is FALSE
- if( mIsSelected )
- {
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- LLColor4 bg_color = sHighlightBgColor;
- //const S32 TRAILING_PAD = 5; // It just looks better with this.
- if (!mIsCurSelection)
- {
- // do time-based fade of extra objects
- F32 fade_time = getRoot()->getSelectionFadeElapsedTime();
- if (getRoot()->getShowSingleSelection())
- {
- // fading out
- bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f);
- }
- else
- {
- // fading in
- bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]);
- }
- }
-
- gl_rect_2d(
- 0,
- getRect().getHeight(),
- getRect().getWidth() - 2,
- llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD),
- bg_color, filled);
- if (mIsCurSelection)
- {
- gl_rect_2d(
- 0,
- getRect().getHeight(),
- getRect().getWidth() - 2,
- llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD),
- sHighlightFgColor, FALSE);
- }
- if (getRect().getHeight() > llround(sFont->getLineHeight()) + ICON_PAD + 2)
- {
- gl_rect_2d(
- 0,
- llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD) - 2,
- getRect().getWidth() - 2,
- 2,
- sHighlightFgColor, FALSE);
- if (show_context)
- {
- gl_rect_2d(
- 0,
- llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD) - 2,
- getRect().getWidth() - 2,
- 2,
- sHighlightBgColor, TRUE);
- }
- }
- }
- if (mDragAndDropTarget)
- {
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gl_rect_2d(
- 0,
- getRect().getHeight(),
- getRect().getWidth() - 2,
- llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD),
- sHighlightBgColor, FALSE);
-
- if (getRect().getHeight() > llround(sFont->getLineHeight()) + ICON_PAD + 2)
- {
- gl_rect_2d(
- 0,
- llfloor(getRect().getHeight() - sFont->getLineHeight() - ICON_PAD) - 2,
- getRect().getWidth() - 2,
- 2,
- sHighlightBgColor, FALSE);
- }
- mDragAndDropTarget = FALSE;
- }
-
-
- if(mIcon)
- {
- mIcon->draw(mIndentation + ARROW_SIZE + TEXT_PAD, getRect().getHeight() - mIcon->getHeight());
- }
-
- if (!mLabel.empty())
- {
- // highlight filtered text
- BOOL debug_filters = getRoot()->getDebugFilters();
- LLColor4 color = ( (mIsSelected && filled) ? sHighlightFgColor : sFgColor );
- F32 right_x;
- F32 y = (F32)getRect().getHeight() - sFont->getLineHeight() - (F32)TEXT_PAD;
-
- if (debug_filters)
- {
- if (!getFiltered() && !possibly_has_children)
- {
- color.mV[VALPHA] *= 0.5f;
- }
-
- LLColor4 filter_color = mLastFilterGeneration >= getRoot()->getFilter()->getCurrentGeneration() ? LLColor4(0.5f, 0.8f, 0.5f, 1.f) : LLColor4(0.8f, 0.5f, 0.5f, 1.f);
- sSmallFont->renderUTF8(mStatusText, 0, text_left, y, filter_color,
- LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL,
- S32_MAX, S32_MAX, &right_x, FALSE );
- text_left = right_x;
- }
-
-
- if ( mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime") )
- {
- // *TODO: Translate
- sFont->renderUTF8( std::string("Loading... "), 0, text_left, y, sSearchStatusColor,
- LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle, S32_MAX, S32_MAX, &right_x, FALSE);
- text_left = right_x;
- }
-
- sFont->renderUTF8( mLabel, 0, text_left, y, color,
- LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle,
- S32_MAX, S32_MAX, &right_x, FALSE );
- if (!mLabelSuffix.empty())
- {
- sFont->renderUTF8( mLabelSuffix, 0, right_x, y, sSuffixColor,
- LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle,
- S32_MAX, S32_MAX, &right_x, FALSE );
- }
-
- if (sBoxImage.notNull() && mStringMatchOffset != std::string::npos)
- {
- // don't draw backgrounds for zero-length strings
- S32 filter_string_length = mRoot->getFilterSubString().size();
- if (filter_string_length > 0)
- {
- std::string combined_string = mLabel + mLabelSuffix;
- S32 left = llround(text_left) + sFont->getWidth(combined_string, 0, mStringMatchOffset) - 1;
- S32 right = left + sFont->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2;
- S32 bottom = llfloor(getRect().getHeight() - sFont->getLineHeight() - 3);
- S32 top = getRect().getHeight();
-
- LLRect box_rect(left, top, right, bottom);
- sBoxImage->draw(box_rect, sFilterBGColor);
- F32 match_string_left = text_left + sFont->getWidthF32(combined_string, 0, mStringMatchOffset);
- F32 y = (F32)getRect().getHeight() - sFont->getLineHeight() - (F32)TEXT_PAD;
- sFont->renderUTF8( combined_string, mStringMatchOffset, match_string_left, y,
- sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, mLabelStyle,
- filter_string_length, S32_MAX, &right_x, FALSE );
- }
- }
- }
-
- if( sDebugRects )
- {
- drawDebugRect();
- }
-}
-
-
-///----------------------------------------------------------------------------
-/// Class LLFolderViewFolder
-///----------------------------------------------------------------------------
-
-// Default constructor
-LLFolderViewFolder::LLFolderViewFolder( const std::string& name, LLUIImagePtr icon,
- LLFolderView* root,
- LLFolderViewEventListener* listener ):
- LLFolderViewItem( name, icon, 0, root, listener ), // 0 = no create time
- mIsOpen(FALSE),
- mExpanderHighlighted(FALSE),
- mCurHeight(0.f),
- mTargetHeight(0.f),
- mAutoOpenCountdown(0.f),
- mSubtreeCreationDate(0),
- mAmTrash(LLFolderViewFolder::UNKNOWN),
- mLastArrangeGeneration( -1 ),
- mLastCalculatedWidth(0),
- mCompletedFilterGeneration(-1),
- mMostFilteredDescendantGeneration(-1)
-{
- mType = std::string("(folder)");
-}
-
-// Destroys the object
-LLFolderViewFolder::~LLFolderViewFolder( void )
-{
- // The LLView base class takes care of object destruction. make sure that we
- // don't have mouse or keyboard focus
- gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit()
-}
-
-// addToFolder() returns TRUE if it succeeds. FALSE otherwise
-BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder, LLFolderView* root)
-{
- if (!folder)
- {
- return FALSE;
- }
- mParentFolder = folder;
- root->addItemID(getListener()->getUUID(), this);
- return folder->addFolder(this);
-}
-
-// Finds width and height of this object and it's children. Also
-// makes sure that this view and it's children are the right size.
-S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)
-{
- mHasVisibleChildren = hasFilteredDescendants(filter_generation);
-
- LLInventoryFilter::EFolderShow show_folder_state = getRoot()->getShowFolderState();
-
- // calculate height as a single item (without any children), and reshapes rectangle to match
- LLFolderViewItem::arrange( width, height, filter_generation );
-
- // clamp existing animated height so as to never get smaller than a single item
- mCurHeight = llmax((F32)*height, mCurHeight);
-
- // initialize running height value as height of single item in case we have no children
- *height = getItemHeight();
- F32 running_height = (F32)*height;
- F32 target_height = (F32)*height;
-
- // are my children visible?
- if (needsArrange())
- {
- // set last arrange generation first, in case children are animating
- // and need to be arranged again
- mLastArrangeGeneration = mRoot->getArrangeGeneration();
- if (mIsOpen)
- {
- // Add sizes of children
- S32 parent_item_height = getRect().getHeight();
-
- for(folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit)
- {
- LLFolderViewFolder* folderp = (*fit);
- if (getRoot()->getDebugFilters())
- {
- folderp->setVisible(TRUE);
- }
- else
- {
- folderp->setVisible(show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS || // always show folders?
- (folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter
- }
-
- if (folderp->getVisible())
- {
- S32 child_width = *width;
- S32 child_height = 0;
- S32 child_top = parent_item_height - llround(running_height);
-
- target_height += folderp->arrange( &child_width, &child_height, filter_generation );
-
- running_height += (F32)child_height;
- *width = llmax(*width, child_width);
- folderp->setOrigin( 0, child_top - folderp->getRect().getHeight() );
- }
- }
- for(items_t::iterator iit = mItems.begin();
- iit != mItems.end(); ++iit)
- {
- LLFolderViewItem* itemp = (*iit);
- if (getRoot()->getDebugFilters())
- {
- itemp->setVisible(TRUE);
- }
- else
- {
- itemp->setVisible(itemp->getFiltered(filter_generation));
- }
-
- if (itemp->getVisible())
- {
- S32 child_width = *width;
- S32 child_height = 0;
- S32 child_top = parent_item_height - llround(running_height);
-
- target_height += itemp->arrange( &child_width, &child_height, filter_generation );
- // don't change width, as this item is as wide as its parent folder by construction
- itemp->reshape( itemp->getRect().getWidth(), child_height);
-
- running_height += (F32)child_height;
- *width = llmax(*width, child_width);
- itemp->setOrigin( 0, child_top - itemp->getRect().getHeight() );
- }
- }
- }
-
- mTargetHeight = target_height;
- // cache this width so next time we can just return it
- mLastCalculatedWidth = *width;
- }
- else
- {
- // just use existing width
- *width = mLastCalculatedWidth;
- }
-
- // animate current height towards target height
- if (llabs(mCurHeight - mTargetHeight) > 1.f)
- {
- mCurHeight = lerp(mCurHeight, mTargetHeight, LLCriticalDamp::getInterpolant(mIsOpen ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT));
-
- requestArrange();
-
- // hide child elements that fall out of current animated height
- for (folders_t::iterator iter = mFolders.begin();
- iter != mFolders.end();)
- {
- folders_t::iterator fit = iter++;
- // number of pixels that bottom of folder label is from top of parent folder
- if (getRect().getHeight() - (*fit)->getRect().mTop + (*fit)->getItemHeight()
- > llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP)
- {
- // hide if beyond current folder height
- (*fit)->setVisible(FALSE);
- }
- }
-
- for (items_t::iterator iter = mItems.begin();
- iter != mItems.end();)
- {
- items_t::iterator iit = iter++;
- // number of pixels that bottom of item label is from top of parent folder
- if (getRect().getHeight() - (*iit)->getRect().mBottom
- > llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP)
- {
- (*iit)->setVisible(FALSE);
- }
- }
- }
- else
- {
- mCurHeight = mTargetHeight;
- }
-
- // don't change width as this item is already as wide as its parent folder
- reshape(getRect().getWidth(),llround(mCurHeight));
-
- // pass current height value back to parent
- *height = llround(mCurHeight);
-
- return llround(mTargetHeight);
-}
-
-BOOL LLFolderViewFolder::needsArrange()
-{
- return mLastArrangeGeneration < mRoot->getArrangeGeneration();
-}
-
-void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recurse_up)
-{
- mMostFilteredDescendantGeneration = llmin(mMostFilteredDescendantGeneration, generation);
- mCompletedFilterGeneration = generation;
- // only aggregate up if we are a lower (older) value
- if (recurse_up && mParentFolder && generation < mParentFolder->getCompletedFilterGeneration())
- {
- mParentFolder->setCompletedFilterGeneration(generation, TRUE);
- }
-}
-
-void LLFolderViewFolder::filter( LLInventoryFilter& filter)
-{
- S32 filter_generation = filter.getCurrentGeneration();
- // if failed to pass filter newer than must_pass_generation
- // you will automatically fail this time, so we only
- // check against items that have passed the filter
- S32 must_pass_generation = filter.getMustPassGeneration();
-
- // if we have already been filtered against this generation, skip out
- if (getCompletedFilterGeneration() >= filter_generation)
- {
- return;
- }
-
- // filter folder itself
- if (getLastFilterGeneration() < filter_generation)
- {
- if (getLastFilterGeneration() >= must_pass_generation && // folder has been compared to a valid precursor filter
- !mFiltered) // and did not pass the filter
- {
- // go ahead and flag this folder as done
- mLastFilterGeneration = filter_generation;
- }
- else
- {
- // filter self only on first pass through
- LLFolderViewItem::filter( filter );
- }
- }
-
- if (getRoot()->getDebugFilters())
- {
- mStatusText = llformat("%d", mLastFilterGeneration);
- mStatusText += llformat("(%d)", mCompletedFilterGeneration);
- mStatusText += llformat("+%d", mMostFilteredDescendantGeneration);
- }
-
- // all descendants have been filtered later than must pass generation
- // but none passed
- if(getCompletedFilterGeneration() >= must_pass_generation && !hasFilteredDescendants(must_pass_generation))
- {
- // don't traverse children if we've already filtered them since must_pass_generation
- // and came back with nothing
- return;
- }
-
- // we entered here with at least one filter iteration left
- // check to see if we have any more before continuing on to children
- if (filter.getFilterCount() < 0)
- {
- return;
- }
-
- // when applying a filter, matching folders get their contents downloaded first
- if (filter.isNotDefault() && getFiltered(filter.getMinRequiredGeneration()) && (mListener && !gInventory.isCategoryComplete(mListener->getUUID())))
- {
- gInventory.startBackgroundFetch(mListener->getUUID());
- }
-
- // now query children
- for (folders_t::iterator iter = mFolders.begin();
- iter != mFolders.end();)
- {
- folders_t::iterator fit = iter++;
- // have we run out of iterations this frame?
- if (filter.getFilterCount() < 0)
- {
- break;
- }
-
- // mMostFilteredDescendantGeneration might have been reset
- // in which case we need to update it even for folders that
- // don't need to be filtered anymore
- if ((*fit)->getCompletedFilterGeneration() >= filter_generation)
- {
- // track latest generation to pass any child items
- if ((*fit)->getFiltered() || (*fit)->hasFilteredDescendants(filter.getMinRequiredGeneration()))
- {
- mMostFilteredDescendantGeneration = filter_generation;
- if (mRoot->needsAutoSelect())
- {
- (*fit)->setOpenArrangeRecursively(TRUE);
- }
- }
- // just skip it, it has already been filtered
- continue;
- }
-
- // update this folders filter status (and children)
- (*fit)->filter( filter );
-
- // track latest generation to pass any child items
- if ((*fit)->getFiltered() || (*fit)->hasFilteredDescendants(filter_generation))
- {
- mMostFilteredDescendantGeneration = filter_generation;
- if (mRoot->needsAutoSelect())
- {
- (*fit)->setOpenArrangeRecursively(TRUE);
- }
- }
- }
-
- for (items_t::iterator iter = mItems.begin();
- iter != mItems.end();)
- {
- items_t::iterator iit = iter++;
- if (filter.getFilterCount() < 0)
- {
- break;
- }
- if ((*iit)->getLastFilterGeneration() >= filter_generation)
- {
- if ((*iit)->getFiltered())
- {
- mMostFilteredDescendantGeneration = filter_generation;
- }
- continue;
- }
-
- if ((*iit)->getLastFilterGeneration() >= must_pass_generation &&
- !(*iit)->getFiltered(must_pass_generation))
- {
- // failed to pass an earlier filter that was a subset of the current one
- // go ahead and flag this item as done
- (*iit)->setFiltered(FALSE, filter_generation);
- continue;
- }
-
- (*iit)->filter( filter );
-
- if ((*iit)->getFiltered(filter.getMinRequiredGeneration()))
- {
- mMostFilteredDescendantGeneration = filter_generation;
- }
- }
-
- // if we didn't use all filter iterations
- // that means we filtered all of our descendants
- // instead of exhausting the filter count for this frame
- if (filter.getFilterCount() > 0)
- {
- // flag this folder as having completed filter pass for all descendants
- setCompletedFilterGeneration(filter_generation, FALSE/*dont recurse up to root*/);
- }
-}
-
-void LLFolderViewFolder::setFiltered(BOOL filtered, S32 filter_generation)
-{
- // if this folder is now filtered, but wasn't before
- // (it just passed)
- if (filtered && !mFiltered)
- {
- // reset current height, because last time we drew it
- // it might have had more visible items than now
- mCurHeight = 0.f;
- }
-
- LLFolderViewItem::setFiltered(filtered, filter_generation);
-}
-
-void LLFolderViewFolder::dirtyFilter()
-{
- // we're a folder, so invalidate our completed generation
- setCompletedFilterGeneration(-1, FALSE);
- LLFolderViewItem::dirtyFilter();
-}
-
-BOOL LLFolderViewFolder::hasFilteredDescendants()
-{
- return mMostFilteredDescendantGeneration >= mRoot->getFilter()->getCurrentGeneration();
-}
-
-// Passes selection information on to children and record selection
-// information if necessary.
-BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem,
- BOOL take_keyboard_focus)
-{
- BOOL rv = FALSE;
- if( selection == this )
- {
- mIsSelected = TRUE;
- if(mListener)
- {
- mListener->selectItem();
- }
- rv = TRUE;
- }
- else
- {
- mIsSelected = FALSE;
- rv = FALSE;
- }
- BOOL child_selected = FALSE;
-
- for (folders_t::iterator iter = mFolders.begin();
- iter != mFolders.end();)
- {
- folders_t::iterator fit = iter++;
- if((*fit)->setSelection(selection, openitem, take_keyboard_focus))
- {
- rv = TRUE;
- child_selected = TRUE;
- mNumDescendantsSelected++;
- }
- }
- for (items_t::iterator iter = mItems.begin();
- iter != mItems.end();)
- {
- items_t::iterator iit = iter++;
- if((*iit)->setSelection(selection, openitem, take_keyboard_focus))
- {
- rv = TRUE;
- child_selected = TRUE;
- mNumDescendantsSelected++;
- }
- }
- if(openitem && child_selected)
- {
- setOpenArrangeRecursively(TRUE);
- }
- return rv;
-}
-
-// This method is used to change the selection of an item. If
-// selection is 'this', then note selection as true. Returns TRUE
-// if this or a child is now selected.
-BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection,
- BOOL selected)
-{
- BOOL rv = FALSE;
- if(selection == this)
- {
- mIsSelected = selected;
- if(mListener && selected)
- {
- mListener->selectItem();
- }
- rv = TRUE;
- }
-
- for (folders_t::iterator iter = mFolders.begin();
- iter != mFolders.end();)
- {
- folders_t::iterator fit = iter++;
- if((*fit)->changeSelection(selection, selected))
- {
- if (selected)
- {
- mNumDescendantsSelected++;
- }
- else
- {
- mNumDescendantsSelected--;
- }
- rv = TRUE;
- }
- }
- for (items_t::iterator iter = mItems.begin();
- iter != mItems.end();)
- {
- items_t::iterator iit = iter++;
- if((*iit)->changeSelection(selection, selected))
- {
- if (selected)
- {
- mNumDescendantsSelected++;
- }
- else
- {
- mNumDescendantsSelected--;
- }
- rv = TRUE;
- }
- }
- return rv;
-}
-
-S32 LLFolderViewFolder::extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& selected_items)
-{
- S32 num_selected = 0;
-
- // pass on to child folders first
- for (folders_t::iterator iter = mFolders.begin();
- iter != mFolders.end();)
- {
- folders_t::iterator fit = iter++;
- num_selected += (*fit)->extendSelection(selection, last_selected, selected_items);
- mNumDescendantsSelected += num_selected;
- }
-
- // handle selection of our immediate children...
- BOOL reverse_select = FALSE;
- BOOL found_last_selected = FALSE;
- BOOL found_selection = FALSE;
- LLDynamicArray<LLFolderViewItem*> items_to_select;
- LLFolderViewItem* item;
-
- //...folders first...
- for (folders_t::iterator iter = mFolders.begin();
- iter != mFolders.end();)
- {
- folders_t::iterator fit = iter++;
- item = (*fit);
- if(item == selection)
- {
- found_selection = TRUE;
- }
- else if (item == last_selected)
- {
- found_last_selected = TRUE;
- if (found_selection)
- {
- reverse_select = TRUE;
- }
- }
-
- if (found_selection || found_last_selected)
- {
- // deselect currently selected items so they can be pushed back on queue
- if (item->isSelected())
- {
- item->changeSelection(item, FALSE);
- }
- items_to_select.put(item);
- }
-
- if (found_selection && found_last_selected)
- {
- break;
- }
- }
-
- if (!(found_selection && found_last_selected))
- {
- //,,,then items
- for (items_t::iterator iter = mItems.begin();
- iter != mItems.end();)
- {
- items_t::iterator iit = iter++;
- item = (*iit);
- if(item == selection)
- {
- found_selection = TRUE;
- }
- else if (item == last_selected)
- {
- found_last_selected = TRUE;
- if (found_selection)
- {
- reverse_select = TRUE;
- }
- }
-
- if (found_selection || found_last_selected)
- {
- // deselect currently selected items so they can be pushed back on queue
- if (item->isSelected())
- {
- item->changeSelection(item, FALSE);
- }
- items_to_select.put(item);
- }
-
- if (found_selection && found_last_selected)
- {
- break;
- }
- }
- }
-
- if (found_last_selected && found_selection)
- {
- // we have a complete selection inside this folder
- for (S32 index = reverse_select ? items_to_select.getLength() - 1 : 0;
- reverse_select ? index >= 0 : index < items_to_select.getLength(); reverse_select ? index-- : index++)
- {
- LLFolderViewItem* item = items_to_select[index];
- if (item->changeSelection(item, TRUE))
- {
- selected_items.put(item);
- mNumDescendantsSelected++;
- num_selected++;
- }
- }
- }
- else if (found_selection)
- {
- // last selection was not in this folder....go ahead and select just the new item
- if (selection->changeSelection(selection, TRUE))
- {
- selected_items.put(selection);
- mNumDescendantsSelected++;
- num_selected++;
- }
- }
-
- return num_selected;
-}
-
-void LLFolderViewFolder::recursiveDeselect(BOOL deselect_self)
-{
- // make sure we don't have negative values
- llassert(mNumDescendantsSelected >= 0);
-
- if (mIsSelected && deselect_self)
- {
- mIsSelected = FALSE;
-
- // update ancestors' count of selected descendents
- LLFolderViewFolder* parent_folder = getParentFolder();
- while(parent_folder)
- {
- parent_folder->mNumDescendantsSelected--;
- parent_folder = parent_folder->getParentFolder();
- }
- }
-
- if (0 == mNumDescendantsSelected)
- {
- return;
- }
-
- for (items_t::iterator iter = mItems.begin();
- iter != mItems.end();)
- {
- items_t::iterator iit = iter++;
- LLFolderViewItem* item = (*iit);
- item->recursiveDeselect(TRUE);
- }
-
- for (folders_t::iterator iter = mFolders.begin();
- iter != mFolders.end();)
- {
- folders_t::iterator fit = iter++;
- LLFolderViewFolder* folder = (*fit);
- folder->recursiveDeselect(TRUE);
- }
-
-}
-
-void LLFolderViewFolder::destroyView()
-{
- for (items_t::iterator iter = mItems.begin();
- iter != mItems.end();)
- {
- items_t::iterator iit = iter++;
- LLFolderViewItem* item = (*iit);
- getRoot()->removeItemID(item->getListener()->getUUID());
- }
-
- std::for_each(mItems.begin(), mItems.end(), DeletePointer());
- mItems.clear();
-
- while (!mFolders.empty())
- {
- LLFolderViewFolder *folderp = mFolders.back();
- folderp->destroyView(); // removes entry from mFolders
- }
-
- deleteAllChildren();
-
- if (mParentFolder)
- {
- mParentFolder->removeView(this);
- }
-}
-
-// remove the specified item (and any children) if possible. Return
-// TRUE if the item was deleted.
-BOOL LLFolderViewFolder::removeItem(LLFolderViewItem* item)
-{
- if(item->remove())
- {
- //RN: this seem unneccessary as remove() moves to trash
- //removeView(item);
- return TRUE;
- }
- return FALSE;
-}
-
-// simply remove the view (and any children) Don't bother telling the
-// listeners.
-void LLFolderViewFolder::removeView(LLFolderViewItem* item)
-{
- if (!item || item->getParentFolder() != this)
- {
- return;
- }
- // deselect without traversing hierarchy
- item->recursiveDeselect(TRUE);
- getRoot()->removeFromSelectionList(item);
- extractItem(item);
- delete item;
-}
-
-// extractItem() removes the specified item from the folder, but
-// doesn't delete it.
-void LLFolderViewFolder::extractItem( LLFolderViewItem* item )
-{
- items_t::iterator it = std::find(mItems.begin(), mItems.end(), item);
- if(it == mItems.end())
- {
- // This is an evil downcast. However, it's only doing
- // pointer comparison to find if (which it should be ) the
- // item is in the container, so it's pretty safe.
- LLFolderViewFolder* f = reinterpret_cast<LLFolderViewFolder*>(item);
- folders_t::iterator ft;
- ft = std::find(mFolders.begin(), mFolders.end(), f);
- if(ft != mFolders.end())
- {
- mFolders.erase(ft);
- }
- }
- else
- {
- mItems.erase(it);
- }
- //item has been removed, need to update filter
- dirtyFilter();
- //because an item is going away regardless of filter status, force rearrange
- requestArrange();
- getRoot()->removeItemID(item->getListener()->getUUID());
- removeChild(item);
-}
-
-// This function is called by a child that needs to be resorted.
-// This is only called for renaming an object because it won't work for date
-void LLFolderViewFolder::resort(LLFolderViewItem* item)
-{
- mItems.sort(mSortFunction);
- mFolders.sort(mSortFunction);
-}
-
-bool LLFolderViewFolder::isTrash() const
-{
- if (mAmTrash == LLFolderViewFolder::UNKNOWN)
- {
- mAmTrash = mListener->getUUID() == gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH, false) ? LLFolderViewFolder::TRASH : LLFolderViewFolder::NOT_TRASH;
- }
- return mAmTrash == LLFolderViewFolder::TRASH;
-}
-
-void LLFolderViewFolder::sortBy(U32 order)
-{
- if (!mSortFunction.updateSort(order))
- {
- // No changes.
- return;
- }
-
- // Propegate this change to sub folders
- for (folders_t::iterator iter = mFolders.begin();
- iter != mFolders.end();)
- {
- folders_t::iterator fit = iter++;
- (*fit)->sortBy(order);
- }
-
- mFolders.sort(mSortFunction);
- mItems.sort(mSortFunction);
-
- if (order & LLInventoryFilter::SO_DATE)
- {
- time_t latest = 0;
-
- if (!mItems.empty())
- {
- LLFolderViewItem* item = *(mItems.begin());
- latest = item->getCreationDate();
- }
-
- if (!mFolders.empty())
- {
- LLFolderViewFolder* folder = *(mFolders.begin());
- if (folder->getCreationDate() > latest)
- {
- latest = folder->getCreationDate();
- }
- }
- mSubtreeCreationDate = latest;
- }
-}
-
-void LLFolderViewFolder::setItemSortOrder(U32 ordering)
-{
- if (mSortFunction.updateSort(ordering))
- {
- for (folders_t::iterator iter = mFolders.begin();
- iter != mFolders.end();)
- {
- folders_t::iterator fit = iter++;
- (*fit)->setItemSortOrder(ordering);
- }
-
- mFolders.sort(mSortFunction);
- mItems.sort(mSortFunction);
- }
-}
-
-EInventorySortGroup LLFolderViewFolder::getSortGroup() const
-{
- if (isTrash())
- {
- return SG_TRASH_FOLDER;
- }
-
- // Folders that can't be moved are 'system' folders.
- if( mListener )
- {
- if( !(mListener->isItemMovable()) )
- {
- return SG_SYSTEM_FOLDER;
- }
- }
-
- return SG_NORMAL_FOLDER;
-}
-
-BOOL LLFolderViewFolder::isMovable()
-{
- if( mListener )
- {
- if( !(mListener->isItemMovable()) )
- {
- return FALSE;
- }
-
- for (items_t::iterator iter = mItems.begin();
- iter != mItems.end();)
- {
- items_t::iterator iit = iter++;
- if(!(*iit)->isMovable())
- {
- return FALSE;
- }
- }
-
- for (folders_t::iterator iter = mFolders.begin();
- iter != mFolders.end();)
- {
- folders_t::iterator fit = iter++;
- if(!(*fit)->isMovable())
- {
- return FALSE;
- }
- }
- }
- return TRUE;
-}
-
-
-BOOL LLFolderViewFolder::isRemovable()
-{
- if( mListener )
- {
- if( !(mListener->isItemRemovable()) )
- {
- return FALSE;
- }
-
- for (items_t::iterator iter = mItems.begin();
- iter != mItems.end();)
- {
- items_t::iterator iit = iter++;
- if(!(*iit)->isRemovable())
- {
- return FALSE;
- }
- }
-
- for (folders_t::iterator iter = mFolders.begin();
- iter != mFolders.end();)
- {
- folders_t::iterator fit = iter++;
- if(!(*fit)->isRemovable())
- {
- return FALSE;
- }
- }
- }
- return TRUE;
-}
-
-// this is an internal method used for adding items to folders.
-BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item)
-{
-
- items_t::iterator it = std::lower_bound(
- mItems.begin(),
- mItems.end(),
- item,
- mSortFunction);
- mItems.insert(it,item);
- item->setRect(LLRect(0, 0, getRect().getWidth(), 0));
- item->setVisible(FALSE);
- addChild( item );
- item->dirtyFilter();
- requestArrange();
- return TRUE;
-}
-
-// this is an internal method used for adding items to folders.
-BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder)
-{
- folders_t::iterator it = std::lower_bound(
- mFolders.begin(),
- mFolders.end(),
- folder,
- mSortFunction);
- mFolders.insert(it,folder);
- folder->setOrigin(0, 0);
- folder->reshape(getRect().getWidth(), 0);
- folder->setVisible(FALSE);
- addChild( folder );
- folder->dirtyFilter();
- // rearrange all descendants too, as our indentation level might have changed
- folder->requestArrange(TRUE);
- return TRUE;
-}
-
-void LLFolderViewFolder::requestArrange(BOOL include_descendants)
-{
- mLastArrangeGeneration = -1;
- // flag all items up to root
- if (mParentFolder)
- {
- mParentFolder->requestArrange();
- }
-
- if (include_descendants)
- {
- for (folders_t::iterator iter = mFolders.begin();
- iter != mFolders.end();
- ++iter)
- {
- (*iter)->requestArrange(TRUE);
- }
- }
-}
-
-void LLFolderViewFolder::toggleOpen()
-{
- setOpen(!mIsOpen);
-}
-
-// Force a folder open or closed
-void LLFolderViewFolder::setOpen(BOOL openitem)
-{
- setOpenArrangeRecursively(openitem);
-}
-
-void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse)
-{
- BOOL was_open = mIsOpen;
- mIsOpen = openitem;
- if(!was_open && openitem)
- {
- if(mListener)
- {
- mListener->openItem();
- }
- }
-
- if (recurse == RECURSE_DOWN || recurse == RECURSE_UP_DOWN)
- {
- for (folders_t::iterator iter = mFolders.begin();
- iter != mFolders.end();)
- {
- folders_t::iterator fit = iter++;
- (*fit)->setOpenArrangeRecursively(openitem, RECURSE_DOWN); /* Flawfinder: ignore */
- }
- }
- if (mParentFolder && (recurse == RECURSE_UP || recurse == RECURSE_UP_DOWN))
- {
- mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP);
- }
-
- if (was_open != mIsOpen)
- {
- requestArrange();
- }
-}
-
-BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask,
- BOOL drop,
- EDragAndDropType c_type,
- void* cargo_data,
- EAcceptance* accept,
- std::string& tooltip_msg)
-{
- BOOL accepted = mListener && mListener->dragOrDrop(mask,drop,c_type,cargo_data);
- if (accepted)
- {
- mDragAndDropTarget = TRUE;
- *accept = ACCEPT_YES_MULTI;
- }
- else
- {
- *accept = ACCEPT_NO;
- }
-
- // drag and drop to child item, so clear pending auto-opens
- getRoot()->autoOpenTest(NULL);
-
- return TRUE;
-}
-
-void LLFolderViewFolder::openItem( void )
-{
- toggleOpen();
-}
-
-void LLFolderViewFolder::applyFunctorRecursively(LLFolderViewFunctor& functor)
-{
- functor.doFolder(this);
-
- for (folders_t::iterator iter = mFolders.begin();
- iter != mFolders.end();)
- {
- folders_t::iterator fit = iter++;
- (*fit)->applyFunctorRecursively(functor);
- }
- for (items_t::iterator iter = mItems.begin();
- iter != mItems.end();)
- {
- items_t::iterator iit = iter++;
- functor.doItem((*iit));
- }
-}
-
-void LLFolderViewFolder::applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor)
-{
- functor(mListener);
- for (folders_t::iterator iter = mFolders.begin();
- iter != mFolders.end();)
- {
- folders_t::iterator fit = iter++;
- (*fit)->applyListenerFunctorRecursively(functor);
- }
- for (items_t::iterator iter = mItems.begin();
- iter != mItems.end();)
- {
- items_t::iterator iit = iter++;
- (*iit)->applyListenerFunctorRecursively(functor);
- }
-}
-
-// LLView functionality
-BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask,
- BOOL drop,
- EDragAndDropType cargo_type,
- void* cargo_data,
- EAcceptance* accept,
- std::string& tooltip_msg)
-{
- LLFolderView* root_view = getRoot();
-
- BOOL handled = FALSE;
- if(mIsOpen)
- {
- handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type,
- cargo_data, accept, tooltip_msg) != NULL;
- }
-
- if (!handled)
- {
- BOOL accepted = mListener && mListener->dragOrDrop(mask, drop,cargo_type,cargo_data);
-
- if (accepted)
- {
- mDragAndDropTarget = TRUE;
- *accept = ACCEPT_YES_MULTI;
- }
- else
- {
- *accept = ACCEPT_NO;
- }
-
- if (!drop && accepted)
- {
- root_view->autoOpenTest(this);
- }
-
- lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewFolder" << llendl;
- }
-
- return TRUE;
-}
-
-
-BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask )
-{
- BOOL handled = FALSE;
- // fetch contents of this folder, as context menu can depend on contents
- // still, user would have to open context menu again to see the changes
- gInventory.fetchDescendentsOf(mListener->getUUID());
-
- if( mIsOpen )
- {
- handled = childrenHandleRightMouseDown( x, y, mask ) != NULL;
- }
- if (!handled)
- {
- handled = LLFolderViewItem::handleRightMouseDown( x, y, mask );
- }
- return handled;
-}
-
-
-BOOL LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask)
-{
- BOOL handled = LLView::handleHover(x, y, mask);
-
- if (!handled)
- {
- // this doesn't do child processing
- handled = LLFolderViewItem::handleHover(x, y, mask);
- }
-
- //if(x < LEFT_INDENTATION + mIndentation && x > mIndentation - LEFT_PAD && y > getRect().getHeight() - )
- //{
- // gViewerWindow->setCursor(UI_CURSOR_ARROW);
- // mExpanderHighlighted = TRUE;
- // handled = TRUE;
- //}
- return handled;
-}
-
-BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask )
-{
- BOOL handled = FALSE;
- if( mIsOpen )
- {
- handled = childrenHandleMouseDown(x,y,mask) != NULL;
- }
- if( !handled )
- {
- if(x < LEFT_INDENTATION + mIndentation && x > mIndentation - LEFT_PAD)
- {
- toggleOpen();
- handled = TRUE;
- }
- else
- {
- // do normal selection logic
- handled = LLFolderViewItem::handleMouseDown(x, y, mask);
- }
- }
-
- return handled;
-}
-
-BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask )
-{
- BOOL handled = FALSE;
- if( mIsOpen )
- {
- handled = childrenHandleDoubleClick( x, y, mask ) != NULL;
- }
- if( !handled )
- {
- if(x < LEFT_INDENTATION + mIndentation && x > mIndentation - LEFT_PAD)
- {
- // don't select when user double-clicks plus sign
- // so as not to contradict single-click behavior
- toggleOpen();
- }
- else
- {
- setSelectionFromRoot(this, FALSE);
- toggleOpen();
- }
- handled = TRUE;
- }
- return handled;
-}
-
-void LLFolderViewFolder::draw()
-{
- if (mAutoOpenCountdown != 0.f)
- {
- mControlLabelRotation = mAutoOpenCountdown * -90.f;
- }
- else if (mIsOpen)
- {
- mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLCriticalDamp::getInterpolant(0.04f));
- }
- else
- {
- mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f));
- }
-
- bool possibly_has_children = false;
- bool up_to_date = mListener && mListener->isUpToDate();
- if(!up_to_date && mListener && mListener->hasChildren()) // we know we have children but haven't fetched them (doesn't obey filter)
- {
- possibly_has_children = true;
- }
-
-
- BOOL loading = ( mIsOpen && possibly_has_children && !up_to_date );
-
- if ( loading && !mIsLoading )
- {
- // Measure how long we've been in the loading state
- mTimeSinceRequestStart.reset();
- }
-
- mIsLoading = loading;
-
- LLFolderViewItem::draw();
-
- // draw children if root folder, or any other folder that is open or animating to closed state
- if( getRoot() == this || (mIsOpen || mCurHeight != mTargetHeight ))
- {
- LLView::draw();
- }
-
- mExpanderHighlighted = FALSE;
-}
-
-time_t LLFolderViewFolder::getCreationDate() const
-{
- return llmax<time_t>(mCreationDate, mSubtreeCreationDate);
-}
-
-
-BOOL LLFolderViewFolder::potentiallyVisible()
-{
- // folder should be visible by it's own filter status
- return LLFolderViewItem::potentiallyVisible()
- // or one or more of its descendants have passed the minimum filter requirement
- || hasFilteredDescendants(mRoot->getFilter()->getMinRequiredGeneration())
- // or not all of its descendants have been checked against minimum filter requirement
- || getCompletedFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration();
-}
-
-// this does prefix traversal, as folders are listed above their contents
-LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, BOOL include_children )
-{
- BOOL found_item = FALSE;
-
- LLFolderViewItem* result = NULL;
- // when not starting from a given item, start at beginning
- if(item == NULL)
- {
- found_item = TRUE;
- }
-
- // find current item among children
- folders_t::iterator fit = mFolders.begin();
- folders_t::iterator fend = mFolders.end();
-
- items_t::iterator iit = mItems.begin();
- items_t::iterator iend = mItems.end();
-
- // if not trivially starting at the beginning, we have to find the current item
- if (!found_item)
- {
- // first, look among folders, since they are always above items
- for(; fit != fend; ++fit)
- {
- if(item == (*fit))
- {
- found_item = TRUE;
- // if we are on downwards traversal
- if (include_children && (*fit)->isOpen())
- {
- // look for first descendant
- return (*fit)->getNextFromChild(NULL, TRUE);
- }
- // otherwise advance to next folder
- ++fit;
- include_children = TRUE;
- break;
- }
- }
-
- // didn't find in folders? Check items...
- if (!found_item)
- {
- for(; iit != iend; ++iit)
- {
- if(item == (*iit))
- {
- found_item = TRUE;
- // point to next item
- ++iit;
- break;
- }
- }
- }
- }
-
- if (!found_item)
- {
- // you should never call this method with an item that isn't a child
- // so we should always find something
- llassert(FALSE);
- return NULL;
- }
-
- // at this point, either iit or fit point to a candidate "next" item
- // if both are out of range, we need to punt up to our parent
-
- // now, starting from found folder, continue through folders
- // searching for next visible folder
- while(fit != fend && !(*fit)->getVisible())
- {
- // turn on downwards traversal for next folder
- ++fit;
- }
-
- if (fit != fend)
- {
- result = (*fit);
- }
- else
- {
- // otherwise, scan for next visible item
- while(iit != iend && !(*iit)->getVisible())
- {
- ++iit;
- }
-
- // check to see if we have a valid item
- if (iit != iend)
- {
- result = (*iit);
- }
- }
-
- if( !result && mParentFolder )
- {
- // If there are no siblings or children to go to, recurse up one level in the tree
- // and skip children for this folder, as we've already discounted them
- result = mParentFolder->getNextFromChild(this, FALSE);
- }
-
- return result;
-}
-
-// this does postfix traversal, as folders are listed above their contents
-LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* item, BOOL include_children )
-{
- BOOL found_item = FALSE;
-
- LLFolderViewItem* result = NULL;
- // when not starting from a given item, start at end
- if(item == NULL)
- {
- found_item = TRUE;
- }
-
- // find current item among children
- folders_t::reverse_iterator fit = mFolders.rbegin();
- folders_t::reverse_iterator fend = mFolders.rend();
-
- items_t::reverse_iterator iit = mItems.rbegin();
- items_t::reverse_iterator iend = mItems.rend();
-
- // if not trivially starting at the end, we have to find the current item
- if (!found_item)
- {
- // first, look among items, since they are always below the folders
- for(; iit != iend; ++iit)
- {
- if(item == (*iit))
- {
- found_item = TRUE;
- // point to next item
- ++iit;
- break;
- }
- }
-
- // didn't find in items? Check folders...
- if (!found_item)
- {
- for(; fit != fend; ++fit)
- {
- if(item == (*fit))
- {
- found_item = TRUE;
- // point to next folder
- ++fit;
- break;
- }
- }
- }
- }
-
- if (!found_item)
- {
- // you should never call this method with an item that isn't a child
- // so we should always find something
- llassert(FALSE);
- return NULL;
- }
-
- // at this point, either iit or fit point to a candidate "next" item
- // if both are out of range, we need to punt up to our parent
-
- // now, starting from found item, continue through items
- // searching for next visible item
- while(iit != iend && !(*iit)->getVisible())
- {
- ++iit;
- }
-
- if (iit != iend)
- {
- // we found an appropriate item
- result = (*iit);
- }
- else
- {
- // otherwise, scan for next visible folder
- while(fit != fend && !(*fit)->getVisible())
- {
- ++fit;
- }
-
- // check to see if we have a valid folder
- if (fit != fend)
- {
- // try selecting child element of this folder
- if ((*fit)->isOpen())
- {
- result = (*fit)->getPreviousFromChild(NULL);
- }
- else
- {
- result = (*fit);
- }
- }
- }
-
- if( !result )
- {
- // If there are no siblings or children to go to, recurse up one level in the tree
- // which gets back to this folder, which will only be visited if it is a valid, visible item
- result = this;
- }
-
- return result;
-}
-
//---------------------------------------------------------------------------
@@ -2494,39 +170,34 @@ void LLCloseAllFoldersFunctor::doItem(LLFolderViewItem* item)
///----------------------------------------------------------------------------
// Default constructor
-LLFolderView::LLFolderView( const std::string& name, LLUIImagePtr root_folder_icon,
- const LLRect& rect, const LLUUID& source_id, LLView *parent_view ) :
-#if LL_WINDOWS
-#pragma warning( push )
-#pragma warning( disable : 4355 ) // warning C4355: 'this' : used in base member initializer list
-#endif
- LLFolderViewFolder( name, root_folder_icon, this, NULL ),
-#if LL_WINDOWS
-#pragma warning( pop )
-#endif
+LLFolderView::LLFolderView(const Params& p)
+: LLFolderViewFolder(p),
mScrollContainer( NULL ),
mPopupMenuHandle(),
mAllowMultiSelect(TRUE),
mShowFolderHierarchy(FALSE),
- mSourceID(source_id),
+ mSourceID(p.task_id),
mRenameItem( NULL ),
mNeedsScroll( FALSE ),
- mLastScrollItem( NULL ),
+ mPinningSelectedItem(FALSE),
mNeedsAutoSelect( FALSE ),
mAutoSelectOverride(FALSE),
mNeedsAutoRename(FALSE),
mDebugFilters(FALSE),
mSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME), // This gets overridden by a pref immediately
- mFilter(name),
+ mFilter( new LLInventoryFilter(p.name) ),
mShowSelectionContext(FALSE),
mShowSingleSelection(FALSE),
mArrangeGeneration(0),
- mUserData(NULL),
- mSelectCallback(NULL),
mSignalSelectCallback(0),
mMinWidth(0),
- mDragAndDropThisFrame(FALSE)
+ mDragAndDropThisFrame(FALSE),
+ mCallbackRegistrar(NULL),
+ mParentPanel(p.parent_panel),
+ mUseEllipses(false),
+ mDraggingOverItem(NULL)
{
+ LLRect rect = p.rect;
LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom);
setRect( rect );
reshape(rect.getWidth(), rect.getHeight());
@@ -2535,7 +206,10 @@ LLFolderView::LLFolderView( const std::string& name, LLUIImagePtr root_folder_ic
mAutoOpenCandidate = NULL;
mAutoOpenTimer.stop();
mKeyboardSelection = FALSE;
- mIndentation = -LEFT_INDENTATION; // children start at indentation 0
+ const LLFolderViewItem::Params& item_params =
+ LLUICtrlFactory::getDefaultParams<LLFolderViewItem>();
+ S32 indentation = item_params.folder_indentation();
+ mIndentation = -indentation; // children start at indentation 0
gIdleCallbacks.addFunction(idle, this);
//clear label
@@ -2543,30 +217,29 @@ LLFolderView::LLFolderView( const std::string& name, LLUIImagePtr root_folder_ic
// just make sure the label ("Inventory Folder") never shows up
mLabel = LLStringUtil::null;
- mRenamer = new LLLineEditor(std::string("ren"), getRect(), LLStringUtil::null, sFont,
- DB_INV_ITEM_NAME_STR_LEN,
- &LLFolderView::commitRename,
- NULL,
- NULL,
- this,
- &LLLineEditor::prevalidatePrintableNotPipe);
//mRenamer->setWriteableBgColor(LLColor4::white);
// Escape is handled by reverting the rename, not commiting it (default behavior)
- mRenamer->setCommitOnFocusLost(TRUE);
- mRenamer->setVisible(FALSE);
+ LLLineEditor::Params params;
+ params.name("ren");
+ params.rect(getRect());
+ params.font(getLabelFontForStyle(LLFontGL::NORMAL));
+ params.max_length_bytes(DB_INV_ITEM_NAME_STR_LEN);
+ params.commit_callback.function(boost::bind(&LLFolderView::commitRename, this, _2));
+ params.prevalidate_callback(&LLLineEditor::prevalidateASCIIPrintableNoPipe);
+ params.commit_on_focus_lost(true);
+ params.visible(false);
+ mRenamer = LLUICtrlFactory::create<LLLineEditor> (params);
addChild(mRenamer);
// make the popup menu available
- LLMenuGL* menu = LLUICtrlFactory::getInstance()->buildMenu("menu_inventory.xml", parent_view);
+ LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
if (!menu)
{
- menu = new LLMenuGL(LLStringUtil::null);
+ menu = LLUICtrlFactory::getDefaultWidget<LLMenuGL>("inventory_menu");
}
- menu->setBackgroundColor(gColors.getColor("MenuPopupBgColor"));
- menu->setVisible(FALSE);
+ menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor"));
mPopupMenuHandle = menu->getHandle();
- setTabStop(TRUE);
}
// Destroys the object
@@ -2580,7 +253,6 @@ LLFolderView::~LLFolderView( void )
mScrollContainer = NULL;
mRenameItem = NULL;
mRenamer = NULL;
- gFocusMgr.releaseFocusIfNeeded( this );
if( gEditMenuHandler == this )
{
@@ -2603,6 +275,9 @@ LLFolderView::~LLFolderView( void )
mFolders.clear();
mItemMap.clear();
+
+ delete mFilter;
+ mFilter = NULL;
}
BOOL LLFolderView::canFocusChildren() const
@@ -2622,11 +297,13 @@ void LLFolderView::checkTreeResortForModelChanged()
}
}
+static LLFastTimer::DeclareTimer FTM_SORT("Sort Inventory");
+
void LLFolderView::setSortOrder(U32 order)
{
if (order != mSortOrder)
{
- LLFastTimer t(LLFastTimer::FTM_SORT);
+ LLFastTimer t(FTM_SORT);
mSortOrder = order;
for (folders_t::iterator iter = mFolders.begin();
@@ -2649,7 +326,7 @@ U32 LLFolderView::getSortOrder() const
BOOL LLFolderView::addFolder( LLFolderViewFolder* folder)
{
// enforce sort order of My Inventory followed by Library
- if (folder->getListener()->getUUID() == gInventoryLibraryRoot)
+ if (folder->getListener()->getUUID() == gInventory.getLibraryRootFolderID())
{
mFolders.push_back(folder);
}
@@ -2657,6 +334,7 @@ BOOL LLFolderView::addFolder( LLFolderViewFolder* folder)
{
mFolders.insert(mFolders.begin(), folder);
}
+ folder->setShowLoadStatus(true);
folder->setOrigin(0, 0);
folder->reshape(getRect().getWidth(), 0);
folder->setVisible(FALSE);
@@ -2670,11 +348,12 @@ void LLFolderView::closeAllFolders()
{
// Close all the folders
setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN);
+ arrangeAll();
}
void LLFolderView::openFolder(const std::string& foldername)
{
- LLFolderViewFolder* inv = getChild<LLFolderViewFolder>(foldername);
+ LLFolderViewFolder* inv = findChild<LLFolderViewFolder>(foldername);
if (inv)
{
setSelection(inv, FALSE, FALSE);
@@ -2682,6 +361,16 @@ void LLFolderView::openFolder(const std::string& foldername)
}
}
+void LLFolderView::openTopLevelFolders()
+{
+ for (folders_t::iterator iter = mFolders.begin();
+ iter != mFolders.end();)
+ {
+ folders_t::iterator fit = iter++;
+ (*fit)->setOpen(TRUE);
+ }
+}
+
void LLFolderView::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse)
{
// call base class to do proper recursion
@@ -2690,22 +379,25 @@ void LLFolderView::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse
mIsOpen = TRUE;
}
+static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange");
+
// This view grows and shinks to enclose all of its children items and folders.
S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_generation )
{
- LLFastTimer t2(LLFastTimer::FTM_ARRANGE);
+ LLFastTimer t2(FTM_ARRANGE);
- filter_generation = mFilter.getMinRequiredGeneration();
+ filter_generation = mFilter->getMinRequiredGeneration();
mMinWidth = 0;
mHasVisibleChildren = hasFilteredDescendants(filter_generation);
// arrange always finishes, so optimistically set the arrange generation to the most current
- mLastArrangeGeneration = mRoot->getArrangeGeneration();
+ mLastArrangeGeneration = getRoot()->getArrangeGeneration();
- LLInventoryFilter::EFolderShow show_folder_state = getRoot()->getShowFolderState();
+ LLInventoryFilter::EFolderShow show_folder_state =
+ getRoot()->getFilter()->getShowFolderState();
S32 total_width = LEFT_PAD;
- S32 running_height = mDebugFilters ? llceil(sSmallFont->getLineHeight()) : 0;
+ S32 running_height = mDebugFilters ? llceil(LLFontGL::getFontMonospace()->getLineHeight()) : 0;
S32 target_height = running_height;
S32 parent_item_height = getRect().getHeight();
@@ -2723,7 +415,12 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen
folderp->setVisible(show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS || // always show folders?
(folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter
}
- if (folderp->getVisible())
+
+ // Need to call arrange regardless of visibility, since children's visibility
+ // might need to be changed too (e.g. even though a folder is invisible, its
+ // children also need to be set invisible for state-tracking purposes, e.g.
+ // llfolderviewitem::filter).
+ // if (folderp->getVisible())
{
S32 child_height = 0;
S32 child_width = 0;
@@ -2761,52 +458,62 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen
}
}
- S32 dummy_s32;
- BOOL dummy_bool;
- S32 min_width;
- mScrollContainer->calcVisibleSize( &min_width, &dummy_s32, &dummy_bool, &dummy_bool);
- reshape( llmax(min_width, total_width), running_height );
+ LLRect scroll_rect = mScrollContainer->getContentWindowRect();
+ reshape( llmax(scroll_rect.getWidth(), total_width), running_height );
- S32 new_min_width;
- mScrollContainer->calcVisibleSize( &new_min_width, &dummy_s32, &dummy_bool, &dummy_bool);
- if (new_min_width != min_width)
+ LLRect new_scroll_rect = mScrollContainer->getContentWindowRect();
+ if (new_scroll_rect.getWidth() != scroll_rect.getWidth())
{
- reshape( llmax(min_width, total_width), running_height );
+ reshape( llmax(scroll_rect.getWidth(), total_width), running_height );
}
+ // move item renamer text field to item's new position
+ updateRenamerPosition();
+
mTargetHeight = (F32)target_height;
return llround(mTargetHeight);
}
const std::string LLFolderView::getFilterSubString(BOOL trim)
{
- return mFilter.getFilterSubString(trim);
+ return mFilter->getFilterSubString(trim);
}
+static LLFastTimer::DeclareTimer FTM_FILTER("Filter Inventory");
+
void LLFolderView::filter( LLInventoryFilter& filter )
{
- LLFastTimer t2(LLFastTimer::FTM_FILTER);
+ LLFastTimer t2(FTM_FILTER);
filter.setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000));
if (getCompletedFilterGeneration() < filter.getCurrentGeneration())
{
- mFiltered = FALSE;
+ mPassedFilter = FALSE;
mMinWidth = 0;
LLFolderViewFolder::filter(filter);
}
+ else
+ {
+ mPassedFilter = TRUE;
+ }
}
void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent)
{
- S32 min_width = 0;
- S32 dummy_height;
- BOOL dummy_bool;
+ LLRect scroll_rect;
if (mScrollContainer)
{
- mScrollContainer->calcVisibleSize( &min_width, &dummy_height, &dummy_bool, &dummy_bool);
+ scroll_rect = mScrollContainer->getContentWindowRect();
}
- width = llmax(mMinWidth, min_width);
+ width = llmax(mMinWidth, scroll_rect.getWidth());
+
+ // restrict width with scroll container's width
+ if (mUseEllipses)
+ width = scroll_rect.getWidth();
+
LLView::reshape(width, height, called_from_parent);
+
+ mReshapeSignal(mSelectedItems, FALSE);
}
void LLFolderView::addToSelectionList(LLFolderViewItem* item)
@@ -2864,6 +571,8 @@ LLFolderViewItem* LLFolderView::getCurSelectedItem( void )
BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem,
BOOL take_keyboard_focus)
{
+ mSignalSelectCallback = take_keyboard_focus ? SIGNAL_KEYBOARD_FOCUS : SIGNAL_NO_KEYBOARD_FOCUS;
+
if( selection == this )
{
return FALSE;
@@ -2871,7 +580,7 @@ BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem,
if( selection && take_keyboard_focus)
{
- setFocus(TRUE);
+ mParentPanel->setFocus(TRUE);
}
// clear selection down here because change of keyboard focus can potentially
@@ -2891,11 +600,33 @@ BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem,
llassert(mSelectedItems.size() <= 1);
- mSignalSelectCallback = take_keyboard_focus ? SIGNAL_KEYBOARD_FOCUS : SIGNAL_NO_KEYBOARD_FOCUS;
-
return rv;
}
+void LLFolderView::setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus)
+{
+ LLFolderViewItem* itemp = getItemByID(obj_id);
+ if(itemp && itemp->getListener())
+ {
+ itemp->arrangeAndSet(TRUE, take_keyboard_focus);
+ mSelectThisID.setNull();
+ return;
+ }
+ else
+ {
+ // save the desired item to be selected later (if/when ready)
+ mSelectThisID = obj_id;
+ }
+}
+
+void LLFolderView::updateSelection()
+{
+ if (mSelectThisID.notNull())
+ {
+ setSelectionByID(mSelectThisID, false);
+ }
+}
+
BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected)
{
BOOL rv = FALSE;
@@ -2970,7 +701,7 @@ void LLFolderView::sanitizeSelection()
LLFolderViewItem* original_selected_item = getCurSelectedItem();
// Cache "Show all folders" filter setting
- BOOL show_all_folders = (getRoot()->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS);
+ BOOL show_all_folders = (getRoot()->getFilter()->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS);
std::vector<LLFolderViewItem*> items_to_remove;
selected_items_t::iterator item_iter;
@@ -3021,6 +752,12 @@ void LLFolderView::sanitizeSelection()
}
}
}
+
+ // Don't allow invisible items (such as root folders) to be selected.
+ if (item->getHidden())
+ {
+ items_to_remove.push_back(item);
+ }
}
std::vector<LLFolderViewItem*>::iterator item_it;
@@ -3040,7 +777,7 @@ void LLFolderView::sanitizeSelection()
parent_folder;
parent_folder = parent_folder->getParentFolder())
{
- if (parent_folder->potentiallyVisible())
+ if (parent_folder->potentiallyVisible() && !parent_folder->getHidden())
{
// give initial selection to first ancestor folder that potentially passes the filter
if (!new_selection)
@@ -3060,7 +797,12 @@ void LLFolderView::sanitizeSelection()
else
{
// nothing selected to start with, so pick "My Inventory" as best guess
- new_selection = getItemByID(gAgent.getInventoryRootID());
+ new_selection = getItemByID(gInventory.getRootFolderID());
+ // ... except if it's hidden from the UI.
+ if (new_selection && new_selection->getHidden())
+ {
+ new_selection = NULL;
+ }
}
if (new_selection)
@@ -3077,12 +819,14 @@ void LLFolderView::clearSelection()
recursiveDeselect(FALSE);
mSelectedItems.clear();
}
+ mSelectThisID.setNull();
}
-BOOL LLFolderView::getSelectionList(std::set<LLUUID> &selection)
+BOOL LLFolderView::getSelectionList(std::set<LLUUID> &selection) const
{
- selected_items_t::iterator item_it;
- for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)
+ for (selected_items_t::const_iterator item_it = mSelectedItems.begin();
+ item_it != mSelectedItems.end();
+ ++item_it)
{
selection.insert((*item_it)->getListener()->getUUID());
}
@@ -3113,36 +857,31 @@ BOOL LLFolderView::startDrag(LLToolDragAndDrop::ESource source)
return can_drag;
}
-void LLFolderView::commitRename( LLUICtrl* renamer, void* user_data )
+void LLFolderView::commitRename( const LLSD& data )
{
- LLFolderView* root = reinterpret_cast<LLFolderView*>(user_data);
- if( root )
- {
- root->finishRenamingItem();
- }
+ finishRenamingItem();
}
void LLFolderView::draw()
{
+ static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", LLColor4::white);
if (mDebugFilters)
{
std::string current_filter_string = llformat("Current Filter: %d, Least Filter: %d, Auto-accept Filter: %d",
- mFilter.getCurrentGeneration(), mFilter.getMinRequiredGeneration(), mFilter.getMustPassGeneration());
- sSmallFont->renderUTF8(current_filter_string, 0, 2,
- getRect().getHeight() - sSmallFont->getLineHeight(), LLColor4(0.5f, 0.5f, 0.8f, 1.f),
- LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, S32_MAX, S32_MAX, NULL, FALSE );
+ mFilter->getCurrentGeneration(), mFilter->getMinRequiredGeneration(), mFilter->getMustPassGeneration());
+ LLFontGL::getFontMonospace()->renderUTF8(current_filter_string, 0, 2,
+ getRect().getHeight() - LLFontGL::getFontMonospace()->getLineHeight(), LLColor4(0.5f, 0.5f, 0.8f, 1.f),
+ LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );
}
+ LLFontGL* font = getLabelFontForStyle(mLabelStyle);
+
// if cursor has moved off of me during drag and drop
// close all auto opened folders
if (!mDragAndDropThisFrame)
{
closeAutoOpenedFolders();
}
- if(this == gFocusMgr.getKeyboardFocus() && !getVisible())
- {
- gFocusMgr.setKeyboardFocus( NULL );
- }
// while dragging, update selection rendering to reflect single/multi drag status
if (LLToolDragAndDrop::getInstance()->hasMouseCapture())
@@ -3168,21 +907,22 @@ void LLFolderView::draw()
mSearchString.clear();
}
- if (hasVisibleChildren() || getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS)
+ if (hasVisibleChildren()
+ || mFilter->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS)
{
mStatusText.clear();
}
else
{
- if (gInventory.backgroundFetchActive() || mCompletedFilterGeneration < mFilter.getMinRequiredGeneration())
+ if (gInventory.backgroundFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration())
{
- mStatusText = std::string("Searching..."); // *TODO:translate
- sFont->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, S32_MAX, S32_MAX, NULL, FALSE );
+ mStatusText = LLTrans::getString("Searching");
+ font->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );
}
else
{
- mStatusText = std::string("No matching items found in inventory."); // *TODO:translate
- sFont->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, S32_MAX, S32_MAX, NULL, FALSE );
+ mStatusText = LLTrans::getString(getFilter()->getEmptyLookupMessage());
+ font->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );
}
}
@@ -3202,11 +942,7 @@ void LLFolderView::finishRenamingItem( void )
mRenameItem->rename( mRenamer->getText() );
}
- mRenamer->setCommitOnFocusLost( FALSE );
- mRenamer->setFocus( FALSE );
- mRenamer->setVisible( FALSE );
- mRenamer->setCommitOnFocusLost( TRUE );
- gFocusMgr.setTopCtrl( NULL );
+ gFocusMgr.setTopCtrl( NULL );
if( mRenameItem )
{
@@ -3280,11 +1016,11 @@ void LLFolderView::removeSelectedItems( void )
// change selection on successful delete
if (new_selection)
{
- setSelectionFromRoot(new_selection, new_selection->isOpen(), gFocusMgr.childHasKeyboardFocus(this));
+ setSelectionFromRoot(new_selection, new_selection->isOpen(), mParentPanel->hasFocus());
}
else
{
- setSelectionFromRoot(NULL, gFocusMgr.childHasKeyboardFocus(this));
+ setSelectionFromRoot(NULL, mParentPanel->hasFocus());
}
}
}
@@ -3310,11 +1046,11 @@ void LLFolderView::removeSelectedItems( void )
}
if (new_selection)
{
- setSelectionFromRoot(new_selection, new_selection->isOpen(), gFocusMgr.childHasKeyboardFocus(this));
+ setSelectionFromRoot(new_selection, new_selection->isOpen(), mParentPanel->hasFocus());
}
else
{
- setSelectionFromRoot(NULL, gFocusMgr.childHasKeyboardFocus(this));
+ setSelectionFromRoot(NULL, mParentPanel->hasFocus());
}
for(S32 i = 0; i < count; ++i)
@@ -3347,11 +1083,8 @@ void LLFolderView::openSelectedItems( void )
}
else
{
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- LLMultiPreview* multi_previewp = new LLMultiPreview(LLRect(left, top, left + 300, top - 100));
- gFloaterView->getNewFloaterPosition(&left, &top);
- LLMultiProperties* multi_propertiesp = new LLMultiProperties(LLRect(left, top, left + 300, top - 100));
+ LLMultiPreview* multi_previewp = new LLMultiPreview();
+ LLMultiProperties* multi_propertiesp = new LLMultiProperties();
selected_items_t::iterator item_it;
for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)
@@ -3371,8 +1104,8 @@ void LLFolderView::openSelectedItems( void )
LLFloater::setFloaterHost(NULL);
// *NOTE: LLMulti* will safely auto-delete when open'd
// without any children.
- multi_previewp->open();
- multi_propertiesp->open();
+ multi_previewp->openFloater(LLSD());
+ multi_propertiesp->openFloater(LLSD());
}
}
}
@@ -3389,10 +1122,7 @@ void LLFolderView::propertiesSelectedItems( void )
}
else
{
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
-
- LLMultiProperties* multi_propertiesp = new LLMultiProperties(LLRect(left, top, left + 100, top - 100));
+ LLMultiProperties* multi_propertiesp = new LLMultiProperties();
LLFloater::setFloaterHost(multi_propertiesp);
@@ -3403,11 +1133,21 @@ void LLFolderView::propertiesSelectedItems( void )
}
LLFloater::setFloaterHost(NULL);
- multi_propertiesp->open(); /* Flawfinder: ignore */
+ multi_propertiesp->openFloater(LLSD());
}
}
}
+void LLFolderView::changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type)
+{
+ LLFolderBridge *folder_bridge = LLFolderBridge::sSelf;
+
+ if (!folder_bridge) return;
+ LLViewerInventoryCategory *cat = folder_bridge->getCategory();
+ if (!cat) return;
+ cat->changeType(new_folder_type);
+}
+
void LLFolderView::autoOpenItem( LLFolderViewFolder* item )
{
if (mAutoOpenItems.check() == item || mAutoOpenItems.getDepth() >= (U32)AUTO_OPEN_STACK_DEPTH)
@@ -3429,7 +1169,9 @@ void LLFolderView::autoOpenItem( LLFolderViewFolder* item )
mAutoOpenItems.push(item);
item->setOpen(TRUE);
- scrollToShowItem(item);
+ LLRect content_rect = mScrollContainer->getContentWindowRect();
+ LLRect constraint_rect(0,content_rect.getHeight(), content_rect.getWidth(), 0);
+ scrollToShowItem(item, constraint_rect);
}
void LLFolderView::closeAutoOpenedFolders()
@@ -3520,12 +1262,44 @@ void LLFolderView::copy()
BOOL LLFolderView::canCut() const
{
- return FALSE;
+ if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0)))
+ {
+ return FALSE;
+ }
+
+ for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it)
+ {
+ const LLFolderViewItem* item = *selected_it;
+ const LLFolderViewEventListener* listener = item->getListener();
+
+ // *WARKAROUND: it is too many places where the "isItemRemovable" method should be changed with "const" modifier
+ if (!listener || !(const_cast<LLFolderViewEventListener*>(listener))->isItemRemovable())
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
}
void LLFolderView::cut()
{
- // implement Windows-style cut-and-leave
+ // clear the inventory clipboard
+ LLInventoryClipboard::instance().reset();
+ S32 count = mSelectedItems.size();
+ if(getVisible() && getEnabled() && (count > 0))
+ {
+ LLFolderViewEventListener* listener = NULL;
+ selected_items_t::iterator item_it;
+ for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)
+ {
+ listener = (*item_it)->getListener();
+ if(listener)
+ {
+ listener->cutToClipboard();
+ }
+ }
+ }
+ mSearchString.clear();
}
BOOL LLFolderView::canPaste() const
@@ -3608,47 +1382,20 @@ void LLFolderView::startRenamingSelectedItem( void )
{
mRenameItem = item;
- S32 x = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD - 1 + item->getIndentation();
- S32 y = llfloor(item->getRect().getHeight()-sFont->getLineHeight()-2);
- item->localPointToScreen( x, y, &x, &y );
- screenPointToLocal( x, y, &x, &y );
- mRenamer->setOrigin( x, y );
+ updateRenamerPosition();
- S32 scroller_height = 0;
- S32 scroller_width = gViewerWindow->getWindowWidth();
- BOOL dummy_bool;
- if (mScrollContainer)
- {
- mScrollContainer->calcVisibleSize( &scroller_width, &scroller_height, &dummy_bool, &dummy_bool);
- }
-
- S32 width = llmax(llmin(item->getRect().getWidth() - x, scroller_width - x - getRect().mLeft), MINIMUM_RENAMER_WIDTH);
- S32 height = llfloor(sFont->getLineHeight() + RENAME_HEIGHT_PAD);
- mRenamer->reshape( width, height, TRUE );
mRenamer->setText(item->getName());
mRenamer->selectAll();
mRenamer->setVisible( TRUE );
// set focus will fail unless item is visible
mRenamer->setFocus( TRUE );
- mRenamer->setLostTopCallback(onRenamerLost);
+ mRenamer->setTopLostCallback(boost::bind(onRenamerLost, _1));
+ mRenamer->setFocusLostCallback(boost::bind(onRenamerLost, _1));
gFocusMgr.setTopCtrl( mRenamer );
}
}
-void LLFolderView::setFocus(BOOL focus)
-{
- if (focus)
- {
- if(!hasFocus())
- {
- gEditMenuHandler = this;
- }
- }
-
- LLFolderViewFolder::setFocus(focus);
-}
-
BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )
{
BOOL handled = FALSE;
@@ -3851,7 +1598,7 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )
break;
}
- if (!handled && hasFocus())
+ if (!handled && mParentPanel->hasFocus())
{
if (key == KEY_BACKSPACE)
{
@@ -3940,20 +1687,11 @@ BOOL LLFolderView::handleMouseDown( S32 x, S32 y, MASK mask )
mKeyboardSelection = FALSE;
mSearchString.clear();
- setFocus(TRUE);
+ mParentPanel->setFocus(TRUE);
return LLView::handleMouseDown( x, y, mask );
}
-void LLFolderView::onFocusLost( )
-{
- if( gEditMenuHandler == this )
- {
- gEditMenuHandler = NULL;
- }
- LLUICtrl::onFocusLost();
-}
-
BOOL LLFolderView::search(LLFolderViewItem* first_item, const std::string &search_string, BOOL backward)
{
// get first selected item
@@ -4030,13 +1768,15 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask )
{
// all user operations move keyboard focus to inventory
// this way, we know when to stop auto-updating a search
- setFocus(TRUE);
+ mParentPanel->setFocus(TRUE);
BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL;
S32 count = mSelectedItems.size();
LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
if(handled && (count > 0) && menu)
{
+ if (mCallbackRegistrar)
+ mCallbackRegistrar->pushScope();
//menu->empty();
const LLView::child_list_t *list = menu->getChildList();
@@ -4056,9 +1796,10 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask )
flags = 0x0;
}
- menu->arrange();
menu->updateParent(LLMenuGL::sMenuContainer);
LLMenuGL::showPopup(this, menu, x, y);
+ if (mCallbackRegistrar)
+ mCallbackRegistrar->popScope();
}
else
{
@@ -4086,6 +1827,13 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
BOOL handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data,
accept, tooltip_msg);
+ // When there are no visible children drag and drop is handled
+ // by the folder which is the hierarchy root.
+ if (!handled && !hasVisibleChildren())
+ {
+ handled = mFolders.front()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg);
+ }
+
if (handled)
{
lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderView" << llendl;
@@ -4094,15 +1842,6 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
return handled;
}
-BOOL LLFolderView::handleScrollWheel(S32 x, S32 y, S32 clicks)
-{
- if (mScrollContainer)
- {
- return mScrollContainer->handleScrollWheel(x, y, clicks);
- }
- return FALSE;
-}
-
void LLFolderView::deleteAllChildren()
{
if(mRenamer == gFocusMgr.getTopCtrl())
@@ -4127,49 +1866,41 @@ void LLFolderView::scrollToShowSelection()
// If the parent is scroll containter, scroll it to make the selection
// is maximally visible.
-void LLFolderView::scrollToShowItem(LLFolderViewItem* item)
+void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect)
{
+ if (!mScrollContainer) return;
+
// don't scroll to items when mouse is being used to scroll/drag and drop
if (gFocusMgr.childHasMouseCapture(mScrollContainer))
{
mNeedsScroll = FALSE;
return;
}
- if(item && mScrollContainer)
+
+ // if item exists and is in visible portion of parent folder...
+ if(item)
{
- LLRect local_rect = item->getRect();
+ LLRect local_rect = item->getLocalRect();
LLRect item_scrolled_rect; // item position relative to display area of scroller
+ LLRect visible_doc_rect = mScrollContainer->getVisibleContentRect();
S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight();
- S32 label_height = llround(sFont->getLineHeight());
- // when navigating with keyboard, only move top of folders on screen, otherwise show whole folder
- S32 max_height_to_show = gFocusMgr.childHasKeyboardFocus(this) ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight();
- item->localPointToOtherView(item->getIndentation(), llmax(0, local_rect.getHeight() - max_height_to_show), &item_scrolled_rect.mLeft, &item_scrolled_rect.mBottom, mScrollContainer);
- item->localPointToOtherView(local_rect.getWidth(), local_rect.getHeight(), &item_scrolled_rect.mRight, &item_scrolled_rect.mTop, mScrollContainer);
-
- item_scrolled_rect.mRight = llmin(item_scrolled_rect.mLeft + MIN_ITEM_WIDTH_VISIBLE, item_scrolled_rect.mRight);
- LLCoordGL scroll_offset(-mScrollContainer->getBorderWidth() - item_scrolled_rect.mLeft,
- mScrollContainer->getRect().getHeight() - item_scrolled_rect.mTop - 1);
-
- S32 max_scroll_offset = getVisibleRect().getHeight() - item_scrolled_rect.getHeight();
- if (item != mLastScrollItem || // if we're scrolling to focus on a new item
- // or the item has just appeared on screen and it wasn't onscreen before
- (scroll_offset.mY > 0 && scroll_offset.mY < max_scroll_offset &&
- (mLastScrollOffset.mY < 0 || mLastScrollOffset.mY > max_scroll_offset)))
- {
- // we now have a position on screen that we want to keep stable
- // offset of selection relative to top of visible area
- mLastScrollOffset = scroll_offset;
- mLastScrollItem = item;
- }
+ S32 label_height = llround(getLabelFontForStyle(mLabelStyle)->getLineHeight());
+ // when navigating with keyboard, only move top of opened folder on screen, otherwise show whole folder
+ S32 max_height_to_show = item->isOpen() && mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight();
+
+ // get portion of item that we want to see...
+ LLRect item_local_rect = LLRect(item->getIndentation(),
+ local_rect.getHeight(),
+ llmin(MIN_ITEM_WIDTH_VISIBLE, local_rect.getWidth()),
+ llmax(0, local_rect.getHeight() - max_height_to_show));
+
+ LLRect item_doc_rect;
- mScrollContainer->scrollToShowRect( item_scrolled_rect, mLastScrollOffset );
+ item->localRectToOtherView(item_local_rect, &item_doc_rect, this);
+
+ mScrollContainer->scrollToShowRect( item_doc_rect, constraint_rect );
- // after scrolling, store new offset
- // in case we don't have room to maintain the original position
- LLCoordGL new_item_left_top;
- item->localPointToOtherView(item->getIndentation(), item->getRect().getHeight(), &new_item_left_top.mX, &new_item_left_top.mY, mScrollContainer);
- mLastScrollOffset.set(-mScrollContainer->getBorderWidth() - new_item_left_top.mX, mScrollContainer->getRect().getHeight() - new_item_left_top.mY - 1);
}
}
@@ -4232,11 +1963,118 @@ LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id)
return NULL;
}
+LLFolderViewFolder* LLFolderView::getFolderByID(const LLUUID& id)
+{
+ if (id.isNull())
+ {
+ return this;
+ }
+
+ for (folders_t::iterator iter = mFolders.begin();
+ iter != mFolders.end();
+ ++iter)
+ {
+ LLFolderViewFolder *folder = (*iter);
+ if (folder->getListener()->getUUID() == id)
+ {
+ return folder;
+ }
+ }
+ return NULL;
+}
+
+bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata)
+{
+ std::string action = userdata.asString();
+
+ if ("rename" == action)
+ {
+ startRenamingSelectedItem();
+ return true;
+ }
+ if ("delete" == action)
+ {
+ removeSelectedItems();
+ return true;
+ }
+
+ if ("copy" == action)
+ {
+ LLInventoryClipboard::instance().reset();
+ }
+
+ static const std::string change_folder_string = "change_folder_type_";
+ if (action.length() > change_folder_string.length() &&
+ (action.compare(0,change_folder_string.length(),"change_folder_type_") == 0))
+ {
+ LLFolderType::EType new_folder_type = LLViewerFolderType::lookupTypeFromXUIName(action.substr(change_folder_string.length()));
+ changeType(model, new_folder_type);
+ return true;
+ }
+
+
+ std::set<LLUUID> selected_items;
+ getSelectionList(selected_items);
+
+ LLMultiPreview* multi_previewp = NULL;
+ LLMultiProperties* multi_propertiesp = NULL;
+
+ if (("task_open" == action || "open" == action) && selected_items.size() > 1)
+ {
+ multi_previewp = new LLMultiPreview();
+ gFloaterView->addChild(multi_previewp);
+
+ LLFloater::setFloaterHost(multi_previewp);
+
+ }
+ else if (("task_properties" == action || "properties" == action) && selected_items.size() > 1)
+ {
+ multi_propertiesp = new LLMultiProperties();
+ gFloaterView->addChild(multi_propertiesp);
+
+ LLFloater::setFloaterHost(multi_propertiesp);
+ }
+
+ std::set<LLUUID>::iterator set_iter;
+
+ for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)
+ {
+ LLFolderViewItem* folder_item = getItemByID(*set_iter);
+ if(!folder_item) continue;
+ LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener();
+ if(!bridge) continue;
+
+ bridge->performAction(this, model, action);
+ }
+
+ LLFloater::setFloaterHost(NULL);
+ if (multi_previewp)
+ {
+ multi_previewp->openFloater(LLSD());
+ }
+ else if (multi_propertiesp)
+ {
+ multi_propertiesp->openFloater(LLSD());
+ }
+
+ return true;
+}
+
+static LLFastTimer::DeclareTimer FTM_AUTO_SELECT("Open and Select");
+static LLFastTimer::DeclareTimer FTM_INVENTORY("Inventory");
// Main idle routine
void LLFolderView::doIdle()
{
- LLFastTimer t2(LLFastTimer::FTM_INVENTORY);
+ // If this is associated with the user's inventory, don't do anything
+ // until that inventory is loaded up.
+ const LLInventoryPanel *inventory_panel = dynamic_cast<LLInventoryPanel*>(mParentPanel);
+ if (inventory_panel && !inventory_panel->getIsViewsInitialized())
+ {
+ return;
+ }
+
+ LLFastTimer t2(FTM_INVENTORY);
BOOL debug_filters = gSavedSettings.getBOOL("DebugInventoryFilters");
if (debug_filters != getDebugFilters())
@@ -4245,12 +2083,12 @@ void LLFolderView::doIdle()
arrangeAll();
}
- mFilter.clearModified();
- BOOL filter_modified_and_active = mCompletedFilterGeneration < mFilter.getCurrentGeneration() &&
- mFilter.isNotDefault();
+ mFilter->clearModified();
+ BOOL filter_modified_and_active = mCompletedFilterGeneration < mFilter->getCurrentGeneration() &&
+ mFilter->isNotDefault();
mNeedsAutoSelect = filter_modified_and_active &&
!(gFocusMgr.childHasKeyboardFocus(this) || gFocusMgr.getMouseCapture());
-
+
// filter to determine visiblity before arranging
filterFromRoot();
@@ -4261,7 +2099,7 @@ void LLFolderView::doIdle()
// potentially changed
if (mNeedsAutoSelect)
{
- LLFastTimer t3(LLFastTimer::FTM_AUTO_SELECT);
+ LLFastTimer t3(FTM_AUTO_SELECT);
// select new item only if a filtered item not currently selected
LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back();
if ((!selected_itemp || !selected_itemp->getFiltered()) && !mAutoSelectOverride)
@@ -4273,6 +2111,59 @@ void LLFolderView::doIdle()
scrollToShowSelection();
}
+ // during filtering process, try to pin selected item's location on screen
+ // this will happen when searching your inventory and when new items arrive
+ if (filter_modified_and_active)
+ {
+ // calculate rectangle to pin item to at start of animated rearrange
+ if (!mPinningSelectedItem && !mSelectedItems.empty())
+ {
+ // lets pin it!
+ mPinningSelectedItem = TRUE;
+
+ LLRect visible_content_rect = mScrollContainer->getVisibleContentRect();
+ LLFolderViewItem* selected_item = mSelectedItems.back();
+
+ LLRect item_rect;
+ selected_item->localRectToOtherView(selected_item->getLocalRect(), &item_rect, this);
+ // if item is visible in scrolled region
+ if (visible_content_rect.overlaps(item_rect))
+ {
+ // then attempt to keep it in same place on screen
+ mScrollConstraintRect = item_rect;
+ mScrollConstraintRect.translate(-visible_content_rect.mLeft, -visible_content_rect.mBottom);
+ }
+ else
+ {
+ // otherwise we just want it onscreen somewhere
+ LLRect content_rect = mScrollContainer->getContentWindowRect();
+ mScrollConstraintRect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight());
+ }
+ }
+ }
+ else
+ {
+ // stop pinning selected item after folders stop rearranging
+ if (!needsArrange())
+ {
+ mPinningSelectedItem = FALSE;
+ }
+ }
+
+ LLRect constraint_rect;
+ if (mPinningSelectedItem)
+ {
+ // use last known constraint rect for pinned item
+ constraint_rect = mScrollConstraintRect;
+ }
+ else
+ {
+ // during normal use (page up/page down, etc), just try to fit item on screen
+ LLRect content_rect = mScrollContainer->getContentWindowRect();
+ constraint_rect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight());
+ }
+
+
BOOL is_visible = isInVisibleChain();
if ( is_visible )
@@ -4286,20 +2177,20 @@ void LLFolderView::doIdle()
if (mSelectedItems.size() && mNeedsScroll)
{
- scrollToShowItem(mSelectedItems.back());
+ scrollToShowItem(mSelectedItems.back(), constraint_rect);
// continue scrolling until animated layout change is done
- if (getCompletedFilterGeneration() >= mFilter.getMinRequiredGeneration() &&
- (!needsArrange() || !is_visible))
+ if (!filter_modified_and_active
+ && (!needsArrange() || !is_visible))
{
mNeedsScroll = FALSE;
}
}
- if (mSignalSelectCallback && mSelectCallback)
+ if (mSignalSelectCallback)
{
//RN: we use keyboard focus as a proxy for user-explicit actions
BOOL take_keyboard_focus = (mSignalSelectCallback == SIGNAL_KEYBOARD_FOCUS);
- mSelectCallback(mSelectedItems, take_keyboard_focus, mUserData);
+ mSelectSignal(mSelectedItems, take_keyboard_focus);
}
mSignalSelectCallback = FALSE;
}
@@ -4315,7 +2206,6 @@ void LLFolderView::idle(void* user_data)
}
}
-
void LLFolderView::dumpSelectionInformation()
{
llinfos << "LLFolderView::dumpSelectionInformation()" << llendl;
@@ -4328,706 +2218,115 @@ void LLFolderView::dumpSelectionInformation()
llinfos << "****************************************" << llendl;
}
-///----------------------------------------------------------------------------
-/// Local function definitions
-///----------------------------------------------------------------------------
-bool LLInventorySort::updateSort(U32 order)
+void LLFolderView::updateRenamerPosition()
{
- if (order != mSortOrder)
+ if(mRenameItem)
{
- mSortOrder = order;
- mByDate = (order & LLInventoryFilter::SO_DATE);
- mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP);
- mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME);
- return true;
- }
- return false;
-}
-
-bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b)
-{
- // We sort by name if we aren't sorting by date
- // OR if these are folders and we are sorting folders by name.
- bool by_name = (!mByDate
- || (mFoldersByName
- && (a->getSortGroup() != SG_ITEM)));
-
- if (a->getSortGroup() != b->getSortGroup())
- {
- if (mSystemToTop)
- {
- // Group order is System Folders, Trash, Normal Folders, Items
- return (a->getSortGroup() < b->getSortGroup());
- }
- else if (mByDate)
- {
- // Trash needs to go to the bottom if we are sorting by date
- if ( (a->getSortGroup() == SG_TRASH_FOLDER)
- || (b->getSortGroup() == SG_TRASH_FOLDER))
- {
- return (b->getSortGroup() == SG_TRASH_FOLDER);
- }
- }
- }
+ // See also LLFolderViewItem::draw()
+ S32 x = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mRenameItem->getIndentation();
+ S32 y = mRenameItem->getRect().getHeight() - mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD;
+ mRenameItem->localPointToScreen( x, y, &x, &y );
+ screenPointToLocal( x, y, &x, &y );
+ mRenamer->setOrigin( x, y );
- if (by_name)
- {
- S32 compare = LLStringUtil::compareDict(a->getLabel(), b->getLabel());
- if (0 == compare)
- {
- return (a->getCreationDate() > b->getCreationDate());
- }
- else
- {
- return (compare < 0);
- }
- }
- else
- {
- // BUG: This is very very slow. The getCreationDate() is log n in number
- // of inventory items.
- time_t first_create = a->getCreationDate();
- time_t second_create = b->getCreationDate();
- if (first_create == second_create)
- {
- return (LLStringUtil::compareDict(a->getLabel(), b->getLabel()) < 0);
- }
- else
+ LLRect scroller_rect(0, 0, gViewerWindow->getWindowWidthScaled(), 0);
+ if (mScrollContainer)
{
- return (first_create > second_create);
+ scroller_rect = mScrollContainer->getContentWindowRect();
}
- }
-}
-
-//static
-void LLFolderView::onRenamerLost( LLUICtrl* renamer, void* user_data)
-{
- renamer->setVisible(FALSE);
-}
-
-void delete_selected_item(void* user_data)
-{
- if(user_data)
- {
- LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data);
- fv->removeSelectedItems();
- }
-}
-
-void copy_selected_item(void* user_data)
-{
- if(user_data)
- {
- LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data);
- fv->copy();
- }
-}
-void paste_items(void* user_data)
-{
- if(user_data)
- {
- LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data);
- fv->paste();
- }
-}
-
-void open_selected_items(void* user_data)
-{
- if(user_data)
- {
- LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data);
- fv->openSelectedItems();
- }
-}
-
-void properties_selected_items(void* user_data)
-{
- if(user_data)
- {
- LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data);
- fv->propertiesSelectedItems();
- }
-}
-
-///----------------------------------------------------------------------------
-/// Class LLFolderViewEventListener
-///----------------------------------------------------------------------------
-
-void LLFolderViewEventListener::arrangeAndSet(LLFolderViewItem* focus,
- BOOL set_selection,
- BOOL take_keyboard_focus)
-{
- if(!focus) return;
- LLFolderView* root = focus->getRoot();
- focus->getParentFolder()->requestArrange();
- if(set_selection)
- {
- focus->setSelectionFromRoot(focus, TRUE, take_keyboard_focus);
- if(root)
- {
- root->scrollToShowSelection();
- }
+ S32 width = llmax(llmin(mRenameItem->getRect().getWidth() - x, scroller_rect.getWidth() - x - getRect().mLeft), MINIMUM_RENAMER_WIDTH);
+ S32 height = mRenameItem->getItemHeight() - RENAME_HEIGHT_PAD;
+ mRenamer->reshape( width, height, TRUE );
}
}
///----------------------------------------------------------------------------
-/// Class LLInventoryFilter
+/// Local function definitions
///----------------------------------------------------------------------------
-LLInventoryFilter::LLInventoryFilter(const std::string& name) :
- mName(name),
- mModified(FALSE),
- mNeedTextRebuild(TRUE)
-{
- mFilterOps.mFilterTypes = 0xffffffff;
- mFilterOps.mMinDate = time_min();
- mFilterOps.mMaxDate = time_max();
- mFilterOps.mHoursAgo = 0;
- mFilterOps.mShowFolderState = SHOW_NON_EMPTY_FOLDERS;
- mFilterOps.mPermissions = PERM_NONE;
-
- mOrder = SO_FOLDERS_BY_NAME; // This gets overridden by a pref immediately
-
- mSubStringMatchOffset = 0;
- mFilterSubString.clear();
- mFilterGeneration = 0;
- mMustPassGeneration = S32_MAX;
- mMinRequiredGeneration = 0;
- mFilterCount = 0;
- mNextFilterGeneration = mFilterGeneration + 1;
-
- mLastLogoff = gSavedPerAccountSettings.getU32("LastLogoff");
- mFilterBehavior = FILTER_NONE;
- // copy mFilterOps into mDefaultFilterOps
- markDefault();
-}
-
-LLInventoryFilter::~LLInventoryFilter()
-{
-}
-
-BOOL LLInventoryFilter::check(LLFolderViewItem* item)
+//static
+void LLFolderView::onRenamerLost( LLFocusableElement* renamer)
{
- time_t earliest;
-
- earliest = time_corrected() - mFilterOps.mHoursAgo * 3600;
- if (mFilterOps.mMinDate > time_min() && mFilterOps.mMinDate < earliest)
+ LLUICtrl* uictrl = dynamic_cast<LLUICtrl*>(renamer);
+ if (uictrl)
{
- earliest = mFilterOps.mMinDate;
+ uictrl->setVisible(FALSE);
}
- else if (!mFilterOps.mHoursAgo)
- {
- earliest = 0;
- }
- LLFolderViewEventListener* listener = item->getListener();
- mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos;
- BOOL passed = (0x1 << listener->getInventoryType() & mFilterOps.mFilterTypes || listener->getInventoryType() == LLInventoryType::IT_NONE)
- && (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos)
- && ((listener->getPermissionMask() & mFilterOps.mPermissions) == mFilterOps.mPermissions)
- && (listener->getCreationDate() >= earliest && listener->getCreationDate() <= mFilterOps.mMaxDate);
- return passed;
-}
-
-const std::string LLInventoryFilter::getFilterSubString(BOOL trim)
-{
- return mFilterSubString;
-}
-
-std::string::size_type LLInventoryFilter::getStringMatchOffset() const
-{
- return mSubStringMatchOffset;
-}
-
-// has user modified default filter params?
-BOOL LLInventoryFilter::isNotDefault()
-{
- return mFilterOps.mFilterTypes != mDefaultFilterOps.mFilterTypes
- || mFilterSubString.size()
- || mFilterOps.mPermissions != mDefaultFilterOps.mPermissions
- || mFilterOps.mMinDate != mDefaultFilterOps.mMinDate
- || mFilterOps.mMaxDate != mDefaultFilterOps.mMaxDate
- || mFilterOps.mHoursAgo != mDefaultFilterOps.mHoursAgo;
-}
-
-BOOL LLInventoryFilter::isActive()
-{
- return mFilterOps.mFilterTypes != 0xffffffff
- || mFilterSubString.size()
- || mFilterOps.mPermissions != PERM_NONE
- || mFilterOps.mMinDate != time_min()
- || mFilterOps.mMaxDate != time_max()
- || mFilterOps.mHoursAgo != 0;
-}
-
-BOOL LLInventoryFilter::isModified()
-{
- return mModified;
}
-BOOL LLInventoryFilter::isModifiedAndClear()
+LLInventoryFilter* LLFolderView::getFilter()
{
- BOOL ret = mModified;
- mModified = FALSE;
- return ret;
+ return mFilter;
}
-void LLInventoryFilter::setFilterTypes(U32 types)
+void LLFolderView::setFilterPermMask( PermissionMask filter_perm_mask )
{
- if (mFilterOps.mFilterTypes != types)
- {
- // keep current items only if no type bits getting turned off
- BOOL fewer_bits_set = (mFilterOps.mFilterTypes & ~types);
- BOOL more_bits_set = (~mFilterOps.mFilterTypes & types);
-
- mFilterOps.mFilterTypes = types;
- if (more_bits_set && fewer_bits_set)
- {
- // neither less or more restrive, both simultaneously
- // so we need to filter from scratch
- setModified(FILTER_RESTART);
- }
- else if (more_bits_set)
- {
- // target is only one of all requested types so more type bits == less restrictive
- setModified(FILTER_LESS_RESTRICTIVE);
- }
- else if (fewer_bits_set)
- {
- setModified(FILTER_MORE_RESTRICTIVE);
- }
-
- }
-}
-
-void LLInventoryFilter::setFilterSubString(const std::string& string)
-{
- if (mFilterSubString != string)
- {
- // hitting BACKSPACE, for example
- BOOL less_restrictive = mFilterSubString.size() >= string.size() && !mFilterSubString.substr(0, string.size()).compare(string);
- // appending new characters
- BOOL more_restrictive = mFilterSubString.size() < string.size() && !string.substr(0, mFilterSubString.size()).compare(mFilterSubString);
- mFilterSubString = string;
- LLStringUtil::toUpper(mFilterSubString);
- LLStringUtil::trimHead(mFilterSubString);
-
- if (less_restrictive)
- {
- setModified(FILTER_LESS_RESTRICTIVE);
- }
- else if (more_restrictive)
- {
- setModified(FILTER_MORE_RESTRICTIVE);
- }
- else
- {
- setModified(FILTER_RESTART);
- }
- }
+ mFilter->setFilterPermissions(filter_perm_mask);
}
-void LLInventoryFilter::setFilterPermissions(PermissionMask perms)
+U32 LLFolderView::getFilterObjectTypes() const
{
- if (mFilterOps.mPermissions != perms)
- {
- // keep current items only if no perm bits getting turned off
- BOOL fewer_bits_set = (mFilterOps.mPermissions & ~perms);
- BOOL more_bits_set = (~mFilterOps.mPermissions & perms);
- mFilterOps.mPermissions = perms;
-
- if (more_bits_set && fewer_bits_set)
- {
- setModified(FILTER_RESTART);
- }
- else if (more_bits_set)
- {
- // target must have all requested permission bits, so more bits == more restrictive
- setModified(FILTER_MORE_RESTRICTIVE);
- }
- else if (fewer_bits_set)
- {
- setModified(FILTER_LESS_RESTRICTIVE);
- }
- }
+ return mFilter->getFilterObjectTypes();
}
-void LLInventoryFilter::setDateRange(time_t min_date, time_t max_date)
+PermissionMask LLFolderView::getFilterPermissions() const
{
- mFilterOps.mHoursAgo = 0;
- if (mFilterOps.mMinDate != min_date)
- {
- mFilterOps.mMinDate = min_date;
- setModified();
- }
- if (mFilterOps.mMaxDate != llmax(mFilterOps.mMinDate, max_date))
- {
- mFilterOps.mMaxDate = llmax(mFilterOps.mMinDate, max_date);
- setModified();
- }
+ return mFilter->getFilterPermissions();
}
-void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl)
+BOOL LLFolderView::isFilterModified()
{
- if (sl && !isSinceLogoff())
- {
- setDateRange(mLastLogoff, time_max());
- setModified();
- }
- if (!sl && isSinceLogoff())
- {
- setDateRange(0, time_max());
- setModified();
- }
+ return mFilter->isNotDefault();
}
-BOOL LLInventoryFilter::isSinceLogoff()
+BOOL LLFolderView::getAllowMultiSelect()
{
- return (mFilterOps.mMinDate == (time_t)mLastLogoff) &&
- (mFilterOps.mMaxDate == time_max());
+ return mAllowMultiSelect;
}
-void LLInventoryFilter::setHoursAgo(U32 hours)
-{
- if (mFilterOps.mHoursAgo != hours)
- {
- // *NOTE: need to cache last filter time, in case filter goes stale
- BOOL less_restrictive = (mFilterOps.mMinDate == time_min() && mFilterOps.mMaxDate == time_max() && hours > mFilterOps.mHoursAgo);
- BOOL more_restrictive = (mFilterOps.mMinDate == time_min() && mFilterOps.mMaxDate == time_max() && hours <= mFilterOps.mHoursAgo);
- mFilterOps.mHoursAgo = hours;
- mFilterOps.mMinDate = time_min();
- mFilterOps.mMaxDate = time_max();
- if (less_restrictive)
- {
- setModified(FILTER_LESS_RESTRICTIVE);
- }
- else if (more_restrictive)
- {
- setModified(FILTER_MORE_RESTRICTIVE);
- }
- else
- {
- setModified(FILTER_RESTART);
- }
- }
-}
-void LLInventoryFilter::setShowFolderState(EFolderShow state)
+void delete_selected_item(void* user_data)
{
- if (mFilterOps.mShowFolderState != state)
+ if(user_data)
{
- mFilterOps.mShowFolderState = state;
- if (state == SHOW_NON_EMPTY_FOLDERS)
- {
- // showing fewer folders than before
- setModified(FILTER_MORE_RESTRICTIVE);
- }
- else if (state == SHOW_ALL_FOLDERS)
- {
- // showing same folders as before and then some
- setModified(FILTER_LESS_RESTRICTIVE);
- }
- else
- {
- setModified();
- }
+ LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data);
+ fv->removeSelectedItems();
}
}
-void LLInventoryFilter::setSortOrder(U32 order)
+void copy_selected_item(void* user_data)
{
- if (mOrder != order)
+ if(user_data)
{
- mOrder = order;
- setModified();
+ LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data);
+ fv->copy();
}
}
-void LLInventoryFilter::markDefault()
-{
- mDefaultFilterOps = mFilterOps;
-}
-
-void LLInventoryFilter::resetDefault()
-{
- mFilterOps = mDefaultFilterOps;
- setModified();
-}
-
-void LLInventoryFilter::setModified(EFilterBehavior behavior)
+void paste_items(void* user_data)
{
- mModified = TRUE;
- mNeedTextRebuild = TRUE;
- mFilterGeneration = mNextFilterGeneration++;
-
- if (mFilterBehavior == FILTER_NONE)
- {
- mFilterBehavior = behavior;
- }
- else if (mFilterBehavior != behavior)
- {
- // trying to do both less restrictive and more restrictive filter
- // basically means restart from scratch
- mFilterBehavior = FILTER_RESTART;
- }
-
- if (isNotDefault())
- {
- // if not keeping current filter results, update last valid as well
- switch(mFilterBehavior)
- {
- case FILTER_RESTART:
- mMustPassGeneration = mFilterGeneration;
- mMinRequiredGeneration = mFilterGeneration;
- break;
- case FILTER_LESS_RESTRICTIVE:
- mMustPassGeneration = mFilterGeneration;
- break;
- case FILTER_MORE_RESTRICTIVE:
- mMinRequiredGeneration = mFilterGeneration;
- // must have passed either current filter generation (meaningless, as it hasn't been run yet)
- // or some older generation, so keep the value
- mMustPassGeneration = llmin(mMustPassGeneration, mFilterGeneration);
- break;
- default:
- llerrs << "Bad filter behavior specified" << llendl;
- }
- }
- else
+ if(user_data)
{
- // shortcut disabled filters to show everything immediately
- mMinRequiredGeneration = 0;
- mMustPassGeneration = S32_MAX;
+ LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data);
+ fv->paste();
}
}
-BOOL LLInventoryFilter::isFilterWith(LLInventoryType::EType t)
-{
- return mFilterOps.mFilterTypes & (0x01 << t);
-}
-
-std::string LLInventoryFilter::getFilterText()
+void open_selected_items(void* user_data)
{
- if (!mNeedTextRebuild)
- {
- return mFilterText;
- }
-
- mNeedTextRebuild = FALSE;
- std::string filtered_types;
- std::string not_filtered_types;
- BOOL filtered_by_type = FALSE;
- BOOL filtered_by_all_types = TRUE;
- S32 num_filter_types = 0;
- mFilterText.clear();
-
- if (isFilterWith(LLInventoryType::IT_ANIMATION))
- {
- filtered_types += " Animations,";
- filtered_by_type = TRUE;
- num_filter_types++;
- }
- else
- {
- not_filtered_types += " Animations,";
- filtered_by_all_types = FALSE;
- }
-
- if (isFilterWith(LLInventoryType::IT_CALLINGCARD))
- {
- filtered_types += " Calling Cards,";
- filtered_by_type = TRUE;
- num_filter_types++;
- }
- else
- {
- not_filtered_types += " Calling Cards,";
- filtered_by_all_types = FALSE;
- }
-
- if (isFilterWith(LLInventoryType::IT_WEARABLE))
- {
- filtered_types += " Clothing,";
- filtered_by_type = TRUE;
- num_filter_types++;
- }
- else
- {
- not_filtered_types += " Clothing,";
- filtered_by_all_types = FALSE;
- }
-
- if (isFilterWith(LLInventoryType::IT_GESTURE))
- {
- filtered_types += " Gestures,";
- filtered_by_type = TRUE;
- num_filter_types++;
- }
- else
- {
- not_filtered_types += " Gestures,";
- filtered_by_all_types = FALSE;
- }
-
- if (isFilterWith(LLInventoryType::IT_LANDMARK))
- {
- filtered_types += " Landmarks,";
- filtered_by_type = TRUE;
- num_filter_types++;
- }
- else
- {
- not_filtered_types += " Landmarks,";
- filtered_by_all_types = FALSE;
- }
-
- if (isFilterWith(LLInventoryType::IT_NOTECARD))
- {
- filtered_types += " Notecards,";
- filtered_by_type = TRUE;
- num_filter_types++;
- }
- else
- {
- not_filtered_types += " Notecards,";
- filtered_by_all_types = FALSE;
- }
-
- if (isFilterWith(LLInventoryType::IT_OBJECT) && isFilterWith(LLInventoryType::IT_ATTACHMENT))
- {
- filtered_types += " Objects,";
- filtered_by_type = TRUE;
- num_filter_types++;
- }
- else
- {
- not_filtered_types += " Objects,";
- filtered_by_all_types = FALSE;
- }
-
- if (isFilterWith(LLInventoryType::IT_LSL))
- {
- filtered_types += " Scripts,";
- filtered_by_type = TRUE;
- num_filter_types++;
- }
- else
- {
- not_filtered_types += " Scripts,";
- filtered_by_all_types = FALSE;
- }
-
- if (isFilterWith(LLInventoryType::IT_SOUND))
- {
- filtered_types += " Sounds,";
- filtered_by_type = TRUE;
- num_filter_types++;
- }
- else
- {
- not_filtered_types += " Sounds,";
- filtered_by_all_types = FALSE;
- }
-
- if (isFilterWith(LLInventoryType::IT_TEXTURE))
- {
- filtered_types += " Textures,";
- filtered_by_type = TRUE;
- num_filter_types++;
- }
- else
- {
- not_filtered_types += " Textures,";
- filtered_by_all_types = FALSE;
- }
-
- if (isFilterWith(LLInventoryType::IT_SNAPSHOT))
- {
- filtered_types += " Snapshots,";
- filtered_by_type = TRUE;
- num_filter_types++;
- }
- else
- {
- not_filtered_types += " Snapshots,";
- filtered_by_all_types = FALSE;
- }
-
- if (!gInventory.backgroundFetchActive() && filtered_by_type && !filtered_by_all_types)
- {
- mFilterText += " - ";
- if (num_filter_types < 5)
- {
- mFilterText += filtered_types;
- }
- else
- {
- mFilterText += "No ";
- mFilterText += not_filtered_types;
- }
- // remove the ',' at the end
- mFilterText.erase(mFilterText.size() - 1, 1);
- }
-
- if (isSinceLogoff())
+ if(user_data)
{
- mFilterText += " - Since Logoff";
+ LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data);
+ fv->openSelectedItems();
}
- return mFilterText;
}
-void LLInventoryFilter::toLLSD(LLSD& data)
-{
- data["filter_types"] = (LLSD::Integer)getFilterTypes();
- data["min_date"] = (LLSD::Integer)getMinDate();
- data["max_date"] = (LLSD::Integer)getMaxDate();
- data["hours_ago"] = (LLSD::Integer)getHoursAgo();
- data["show_folder_state"] = (LLSD::Integer)getShowFolderState();
- data["permissions"] = (LLSD::Integer)getFilterPermissions();
- data["substring"] = (LLSD::String)getFilterSubString();
- data["sort_order"] = (LLSD::Integer)getSortOrder();
- data["since_logoff"] = (LLSD::Boolean)isSinceLogoff();
-}
-
-void LLInventoryFilter::fromLLSD(LLSD& data)
+void properties_selected_items(void* user_data)
{
- if(data.has("filter_types"))
- {
- setFilterTypes((U32)data["filter_types"].asInteger());
- }
-
- if(data.has("min_date") && data.has("max_date"))
- {
- setDateRange(data["min_date"].asInteger(), data["max_date"].asInteger());
- }
-
- if(data.has("hours_ago"))
- {
- setHoursAgo((U32)data["hours_ago"].asInteger());
- }
-
- if(data.has("show_folder_state"))
- {
- setShowFolderState((EFolderShow)data["show_folder_state"].asInteger());
- }
-
- if(data.has("permissions"))
- {
- setFilterPermissions((PermissionMask)data["permissions"].asInteger());
- }
-
- if(data.has("substring"))
- {
- setFilterSubString(std::string(data["substring"].asString()));
- }
-
- if(data.has("sort_order"))
- {
- setSortOrder((U32)data["sort_order"].asInteger());
- }
-
- if(data.has("since_logoff"))
+ if(user_data)
{
- setDateRangeLastLogoff((bool)data["since_logoff"].asBoolean());
+ LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data);
+ fv->propertiesSelectedItems();
}
}
diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h
index 3fe3095c58..89e1865e35 100644
--- a/indra/newview/llfolderview.h
+++ b/indra/newview/llfolderview.h
@@ -41,108 +41,27 @@
#ifndef LL_LLFOLDERVIEW_H
#define LL_LLFOLDERVIEW_H
-#include <vector>
-#include <map>
-#include <deque>
+#include "llfolderviewitem.h" // because LLFolderView is-a LLFolderViewFolder
#include "lluictrl.h"
#include "v4color.h"
#include "lldarray.h"
-//#include "llviewermenu.h"
#include "stdenums.h"
-#include "llfontgl.h"
-#include "lleditmenuhandler.h"
-#include "llviewerimage.h"
#include "lldepthstack.h"
+#include "lleditmenuhandler.h"
+#include "llfontgl.h"
#include "lltooldraganddrop.h"
+#include "llviewertexture.h"
-class LLMenuGL;
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLFolderViewEventListener
-//
-// This is an abstract base class that users of the folderview classes
-// would use to catch the useful events emitted from the folder
-// views.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-
+class LLFolderViewEventListener;
+class LLFolderViewFolder;
class LLFolderViewItem;
-class LLFolderView;
class LLInventoryModel;
-class LLScrollableContainerView;
-
-class LLFolderViewEventListener
-{
-public:
- virtual ~LLFolderViewEventListener( void ) {}
- virtual const std::string& getName() const = 0;
- virtual const std::string& getDisplayName() const = 0;
- virtual const LLUUID& getUUID() const = 0;
- virtual time_t getCreationDate() const = 0; // UTC seconds
- virtual PermissionMask getPermissionMask() const = 0;
- virtual LLUIImagePtr getIcon() const = 0;
- virtual LLFontGL::StyleFlags getLabelStyle() const = 0;
- virtual std::string getLabelSuffix() const = 0;
- virtual void openItem( void ) = 0;
- virtual void previewItem( void ) = 0;
- virtual void selectItem(void) = 0;
- virtual void showProperties(void) = 0;
- virtual BOOL isItemRenameable() const = 0;
- virtual BOOL renameItem(const std::string& new_name) = 0;
- virtual BOOL isItemMovable( void ) = 0; // Can be moved to another folder
- virtual BOOL isItemRemovable( void ) = 0; // Can be destroyed
- virtual BOOL removeItem() = 0;
- virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) = 0;
- virtual void move( LLFolderViewEventListener* parent_listener ) = 0;
- virtual BOOL isItemCopyable() const = 0;
- virtual BOOL copyToClipboard() const = 0;
- virtual void cutToClipboard() = 0;
- virtual BOOL isClipboardPasteable() const = 0;
- virtual void pasteFromClipboard() = 0;
- virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0;
- virtual BOOL isUpToDate() const = 0;
- virtual BOOL hasChildren() const = 0;
- virtual LLInventoryType::EType getInventoryType() const = 0;
- virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) {}
-
- // This method should be called when a drag begins. returns TRUE
- // if the drag can begin, otherwise FALSE.
- virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0;
-
- // This method will be called to determine if a drop can be
- // performed, and will set drop to TRUE if a drop is
- // requested. Returns TRUE if a drop is possible/happened,
- // otherwise FALSE.
- virtual BOOL dragOrDrop(MASK mask, BOOL drop,
- EDragAndDropType cargo_type,
- void* cargo_data) = 0;
-
- // This method is called when the object being referenced by the
- // bridge is actually dropped. This allows for cleanup of the old
- // view, reference counting, etc.
-// virtual void dropped() = 0;
-
- // this method accesses the parent and arranges and sets it as
- // specified.
- void arrangeAndSet(LLFolderViewItem* focus, BOOL set_selection,
- BOOL take_keyboard_focus = TRUE);
-};
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLFolderViewListenerFunctor
-//
-// This simple abstract base class can be used to applied to all
-// listeners in a hierarchy.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLFolderViewListenerFunctor
-{
-public:
- virtual ~LLFolderViewListenerFunctor() {}
- virtual void operator()(LLFolderViewEventListener* listener) = 0;
-};
+class LLPanel;
+class LLLineEditor;
+class LLMenuGL;
+class LLScrollContainer;
+class LLUICtrl;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLFolderViewFunctor
@@ -152,10 +71,6 @@ public:
// that only work folders or only work on items, but I'll worry about
// that later when it's determined to be too slow.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLFolderViewItem;
-class LLFolderViewFolder;
-
class LLFolderViewFunctor
{
public:
@@ -164,552 +79,6 @@ public:
virtual void doItem(LLFolderViewItem* item) = 0;
};
-class LLInventoryFilter
-{
-public:
- typedef enum e_folder_show
- {
- SHOW_ALL_FOLDERS,
- SHOW_NON_EMPTY_FOLDERS,
- SHOW_NO_FOLDERS
- } EFolderShow;
-
- typedef enum e_filter_behavior
- {
- FILTER_NONE, // nothing to do, already filtered
- FILTER_RESTART, // restart filtering from scratch
- FILTER_LESS_RESTRICTIVE, // existing filtered items will certainly pass this filter
- FILTER_MORE_RESTRICTIVE // if you didn't pass the previous filter, you definitely won't pass this one
- } EFilterBehavior;
-
- static const U32 SO_DATE = 1;
- static const U32 SO_FOLDERS_BY_NAME = 2;
- static const U32 SO_SYSTEM_FOLDERS_TO_TOP = 4;
-
- LLInventoryFilter(const std::string& name);
- virtual ~LLInventoryFilter();
-
- void setFilterTypes(U32 types);
- U32 getFilterTypes() const { return mFilterOps.mFilterTypes; }
-
- void setFilterSubString(const std::string& string);
- const std::string getFilterSubString(BOOL trim = FALSE);
-
- void setFilterPermissions(PermissionMask perms);
- PermissionMask getFilterPermissions() const { return mFilterOps.mPermissions; }
-
- void setDateRange(time_t min_date, time_t max_date);
- void setDateRangeLastLogoff(BOOL sl);
- time_t getMinDate() const { return mFilterOps.mMinDate; }
- time_t getMaxDate() const { return mFilterOps.mMaxDate; }
-
- void setHoursAgo(U32 hours);
- U32 getHoursAgo() const { return mFilterOps.mHoursAgo; }
-
- void setShowFolderState( EFolderShow state);
- EFolderShow getShowFolderState() { return mFilterOps.mShowFolderState; }
-
- void setSortOrder(U32 order);
- U32 getSortOrder() { return mOrder; }
-
- BOOL check(LLFolderViewItem* item);
- std::string::size_type getStringMatchOffset() const;
- BOOL isActive();
- BOOL isNotDefault();
- BOOL isModified();
- BOOL isModifiedAndClear();
- BOOL isSinceLogoff();
- void clearModified() { mModified = FALSE; mFilterBehavior = FILTER_NONE; }
- const std::string getName() const { return mName; }
- std::string getFilterText();
-
- void setFilterCount(S32 count) { mFilterCount = count; }
- S32 getFilterCount() { return mFilterCount; }
- void decrementFilterCount() { mFilterCount--; }
-
- void markDefault();
- void resetDefault();
-
- BOOL isFilterWith(LLInventoryType::EType t);
-
- S32 getCurrentGeneration() const { return mFilterGeneration; }
- S32 getMinRequiredGeneration() const { return mMinRequiredGeneration; }
- S32 getMustPassGeneration() const { return mMustPassGeneration; }
-
- //RN: this is public to allow system to externally force a global refilter
- void setModified(EFilterBehavior behavior = FILTER_RESTART);
-
- void toLLSD(LLSD& data);
- void fromLLSD(LLSD& data);
-
-protected:
- struct filter_ops
- {
- U32 mFilterTypes;
- time_t mMinDate;
- time_t mMaxDate;
- U32 mHoursAgo;
- EFolderShow mShowFolderState;
- PermissionMask mPermissions;
- };
- filter_ops mFilterOps;
- filter_ops mDefaultFilterOps;
- std::string::size_type mSubStringMatchOffset;
- std::string mFilterSubString;
- U32 mOrder;
- const std::string mName;
- S32 mFilterGeneration;
- S32 mMustPassGeneration;
- S32 mMinRequiredGeneration;
- S32 mFilterCount;
- S32 mNextFilterGeneration;
- EFilterBehavior mFilterBehavior;
-
-private:
- U32 mLastLogoff;
- BOOL mModified;
- BOOL mNeedTextRebuild;
- std::string mFilterText;
-};
-
-// These are grouping of inventory types.
-// Order matters when sorting system folders to the top.
-enum EInventorySortGroup
-{
- SG_SYSTEM_FOLDER,
- SG_TRASH_FOLDER,
- SG_NORMAL_FOLDER,
- SG_ITEM
-};
-
-class LLInventorySort
-{
-public:
- LLInventorySort()
- : mSortOrder(0),
- mByDate(false),
- mSystemToTop(false),
- mFoldersByName(false) { }
-
- // Returns true if order has changed
- bool updateSort(U32 order);
- U32 getSort() { return mSortOrder; }
-
- bool operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b);
-private:
- U32 mSortOrder;
- bool mByDate;
- bool mSystemToTop;
- bool mFoldersByName;
-};
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLFolderViewItem
-//
-// An instance of this class represents a single item in a folder view
-// such as an inventory item or a file.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLFontGL;
-class LLFolderViewFolder;
-class LLFolderView;
-
-class LLFolderViewItem : public LLUICtrl
-{
-protected:
- friend class LLFolderViewEventListener;
-
- static const LLFontGL* sFont;
- static const LLFontGL* sSmallFont;
- static LLColor4 sFgColor;
- static LLColor4 sHighlightBgColor;
- static LLColor4 sHighlightFgColor;
- static LLColor4 sFilterBGColor;
- static LLColor4 sFilterTextColor;
- static LLColor4 sSuffixColor;
- static LLColor4 sSearchStatusColor;
- static LLUIImagePtr sArrowImage;
- static LLUIImagePtr sBoxImage;
-
- std::string mLabel;
- std::string mSearchableLabel;
- std::string mType;
- S32 mLabelWidth;
- time_t mCreationDate;
- LLFolderViewFolder* mParentFolder;
- LLFolderViewEventListener* mListener;
- BOOL mIsSelected;
- BOOL mIsCurSelection;
- BOOL mSelectPending;
- LLFontGL::StyleFlags mLabelStyle;
- std::string mLabelSuffix;
- LLUIImagePtr mIcon;
- std::string mStatusText;
- BOOL mHasVisibleChildren;
- S32 mIndentation;
- S32 mNumDescendantsSelected;
- BOOL mFiltered;
- S32 mLastFilterGeneration;
- std::string::size_type mStringMatchOffset;
- F32 mControlLabelRotation;
- LLFolderView* mRoot;
- BOOL mDragAndDropTarget;
- BOOL mIsLoading;
- LLTimer mTimeSinceRequestStart;
-
- // This function clears the currently selected item, and records
- // the specified selected item appropriately for display and use
- // in the UI. If open is TRUE, then folders are opened up along
- // the way to the selection.
- void setSelectionFromRoot(LLFolderViewItem* selection, BOOL openitem,
- BOOL take_keyboard_focus = TRUE);
-
- // helper function to change the selection from the root.
- void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected);
-
- // helper function to change the selection from the root.
- void extendSelectionFromRoot(LLFolderViewItem* selection);
-
- // this is an internal method used for adding items to folders. A
- // no-op at this leve, but reimplemented in derived classes.
- virtual BOOL addItem(LLFolderViewItem*) { return FALSE; }
- virtual BOOL addFolder(LLFolderViewFolder*) { return FALSE; }
-
-public:
- static void initClass();
- static void cleanupClass();
-
- // This function is called when the folder view is dirty. It's
- // implemented here but called by derived classes when folding the
- // views.
- void arrangeFromRoot();
- void filterFromRoot( void );
-
- // creation_date is in UTC seconds
- LLFolderViewItem( const std::string& name, LLUIImagePtr icon, time_t creation_date, LLFolderView* root, LLFolderViewEventListener* listener );
- virtual ~LLFolderViewItem( void );
-
- // addToFolder() returns TRUE if it succeeds. FALSE otherwise
- enum { ARRANGE = TRUE, DO_NOT_ARRANGE = FALSE };
- virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root);
-
- virtual EInventorySortGroup getSortGroup() const;
-
- // Finds width and height of this object and it's children. Also
- // makes sure that this view and it's children are the right size.
- virtual S32 arrange( S32* width, S32* height, S32 filter_generation );
- virtual S32 getItemHeight();
-
- // applies filters to control visibility of inventory items
- virtual void filter( LLInventoryFilter& filter);
-
- // updates filter serial number and optionally propagated value up to root
- S32 getLastFilterGeneration() { return mLastFilterGeneration; }
-
- virtual void dirtyFilter();
-
- // If the selection is 'this' then note that otherwise
- // ignore. Returns TRUE if this object was affected. If open is
- // TRUE, then folders are opened up along the way to the
- // selection.
- virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem,
- BOOL take_keyboard_focus);
-
- // This method is used to toggle the selection of an item. If
- // selection is 'this', then note selection, and return TRUE.
- virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected);
-
- // this method is used to group select items
- virtual S32 extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items){ return FALSE; }
-
- // this method is used to group select items
- virtual void recursiveDeselect(BOOL deselect_self);
-
- // gets multiple-element selection
- virtual BOOL getSelectionList(std::set<LLUUID> &selection){return TRUE;}
-
- // Returns true is this object and all of its children can be removed (deleted by user)
- virtual BOOL isRemovable();
-
- // Returns true is this object and all of its children can be moved
- virtual BOOL isMovable();
-
- // destroys this item recursively
- virtual void destroyView();
-
- S32 getNumSelectedDescendants() { return mNumDescendantsSelected; }
-
- BOOL isSelected() { return mIsSelected; }
-
- void setIsCurSelection(BOOL select) { mIsCurSelection = select; }
-
- BOOL getIsCurSelection() { return mIsCurSelection; }
-
- BOOL hasVisibleChildren() { return mHasVisibleChildren; }
-
- // Call through to the viewed object and return true if it can be
- // removed. Returns true if it's removed.
- //virtual BOOL removeRecursively(BOOL single_item);
- BOOL remove();
-
- // Build an appropriate context menu for the item. Flags unused.
- void buildContextMenu(LLMenuGL& menu, U32 flags);
-
- // This method returns the actual name of the thing being
- // viewed. This method will ask the viewed object itself.
- const std::string& getName( void ) const;
-
- const std::string& getSearchableLabel( void ) const;
-
- // This method returns the label displayed on the view. This
- // method was primarily added to allow sorting on the folder
- // contents possible before the entire view has been constructed.
- const std::string& getLabel() const { return mLabel; }
-
- // Used for sorting, like getLabel() above.
- virtual time_t getCreationDate() const { return mCreationDate; }
-
- LLFolderViewFolder* getParentFolder( void ) { return mParentFolder; }
- const LLFolderViewFolder* getParentFolder( void ) const { return mParentFolder; }
-
- LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE );
- LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE );
-
- const LLFolderViewEventListener* getListener( void ) const { return mListener; }
- LLFolderViewEventListener* getListener( void ) { return mListener; }
-
- // just rename the object.
- void rename(const std::string& new_name);
-
- // open
- virtual void openItem( void );
- virtual void preview(void);
-
- // Show children (unfortunate that this is called "open")
- virtual void setOpen(BOOL open = TRUE) {};
-
- virtual BOOL isOpen() { return FALSE; }
-
- LLFolderView* getRoot();
- BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor );
- S32 getIndentation() { return mIndentation; }
-
- virtual BOOL potentiallyVisible(); // do we know for a fact that this item has been filtered out?
-
- virtual BOOL getFiltered();
- virtual BOOL getFiltered(S32 filter_generation);
- virtual void setFiltered(BOOL filtered, S32 filter_generation);
-
- // change the icon
- void setIcon(LLUIImagePtr icon);
-
- // refresh information from the object being viewed.
- void refreshFromListener();
- virtual void refresh();
-
- virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor);
-
- // LLView functionality
- virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
- virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );
- virtual BOOL handleHover( S32 x, S32 y, MASK mask );
- virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask );
- virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask );
- virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
-
- // virtual void handleDropped();
- virtual void draw();
- virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
- EDragAndDropType cargo_type,
- void* cargo_data,
- EAcceptance* accept,
- std::string& tooltip_msg);
-};
-
-
-// function used for sorting.
-typedef bool (*sort_order_f)(LLFolderViewItem* a, LLFolderViewItem* b);
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLFolderViewFolder
-//
-// An instance of an LLFolderViewFolder represents a collection of
-// more folders and items. This is used to build the hierarchy of
-// items found in the folder view. :)
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLFolderViewFolder : public LLFolderViewItem
-{
-public:
- typedef enum e_trash
- {
- UNKNOWN, TRASH, NOT_TRASH
- } ETrash;
-
-protected:
- typedef std::list<LLFolderViewItem*> items_t;
- typedef std::list<LLFolderViewFolder*> folders_t;
- items_t mItems;
- folders_t mFolders;
- LLInventorySort mSortFunction;
-
- BOOL mIsOpen;
- BOOL mExpanderHighlighted;
- F32 mCurHeight;
- F32 mTargetHeight;
- F32 mAutoOpenCountdown;
- time_t mSubtreeCreationDate;
- mutable ETrash mAmTrash;
- S32 mLastArrangeGeneration;
- S32 mLastCalculatedWidth;
- S32 mCompletedFilterGeneration;
- S32 mMostFilteredDescendantGeneration;
-public:
- typedef enum e_recurse_type
- {
- RECURSE_NO,
- RECURSE_UP,
- RECURSE_DOWN,
- RECURSE_UP_DOWN
- } ERecurseType;
-
- LLFolderViewFolder( const std::string& name, LLUIImagePtr icon,
- LLFolderView* root,
- LLFolderViewEventListener* listener );
- virtual ~LLFolderViewFolder( void );
-
- virtual BOOL potentiallyVisible();
-
- LLFolderViewItem* getNextFromChild( LLFolderViewItem*, BOOL include_children = TRUE );
- LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE );
-
- // addToFolder() returns TRUE if it succeeds. FALSE otherwise
- virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root);
-
- // Finds width and height of this object and it's children. Also
- // makes sure that this view and it's children are the right size.
- virtual S32 arrange( S32* width, S32* height, S32 filter_generation );
-
- BOOL needsArrange();
-
- // Returns the sort group (system, trash, folder) for this folder.
- virtual EInventorySortGroup getSortGroup() const;
-
- virtual void setCompletedFilterGeneration(S32 generation, BOOL recurse_up);
- virtual S32 getCompletedFilterGeneration() { return mCompletedFilterGeneration; }
-
- BOOL hasFilteredDescendants(S32 filter_generation) { return mMostFilteredDescendantGeneration >= filter_generation; }
- BOOL hasFilteredDescendants();
-
- // applies filters to control visibility of inventory items
- virtual void filter( LLInventoryFilter& filter);
- virtual void setFiltered(BOOL filtered, S32 filter_generation);
- virtual void dirtyFilter();
-
- // Passes selection information on to children and record
- // selection information if necessary. Returns TRUE if this object
- // (or a child) was affected.
- virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem,
- BOOL take_keyboard_focus);
-
- // This method is used to change the selection of an item. If
- // selection is 'this', then note selection as true. Returns TRUE
- // if this or a child is now selected.
- virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected);
-
- // this method is used to group select items
- virtual S32 extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items);
-
- virtual void recursiveDeselect(BOOL deselect_self);
-
- // Returns true is this object and all of its children can be removed.
- virtual BOOL isRemovable();
-
- // Returns true is this object and all of its children can be moved
- virtual BOOL isMovable();
-
- // destroys this folder, and all children
- virtual void destroyView();
-
- // If this folder can be removed, remove all children that can be
- // removed, return TRUE if this is empty after the operation and
- // it's viewed folder object can be removed.
- //virtual BOOL removeRecursively(BOOL single_item);
- //virtual BOOL remove();
-
- // remove the specified item (and any children) if
- // possible. Return TRUE if the item was deleted.
- BOOL removeItem(LLFolderViewItem* item);
-
- // simply remove the view (and any children) Don't bother telling
- // the listeners.
- void removeView(LLFolderViewItem* item);
-
- // extractItem() removes the specified item from the folder, but
- // doesn't delete it.
- void extractItem( LLFolderViewItem* item );
-
- // This function is called by a child that needs to be resorted.
- void resort(LLFolderViewItem* item);
-
- void setItemSortOrder(U32 ordering);
- void sortBy(U32);
- //BOOL (*func)(LLFolderViewItem* a, LLFolderViewItem* b));
-
- void setAutoOpenCountdown(F32 countdown) { mAutoOpenCountdown = countdown; }
-
- // folders can be opened. This will usually be called by internal
- // methods.
- virtual void toggleOpen();
-
- // Force a folder open or closed
- virtual void setOpen(BOOL openitem = TRUE);
-
- // Called when a child is refreshed.
- // don't rearrange child folder contents unless explicitly requested
- virtual void requestArrange(BOOL include_descendants = FALSE);
-
- // internal method which doesn't update the entire view. This
- // method was written because the list iterators destroy the state
- // of other iterations, thus, we can't arrange while iterating
- // through the children (such as when setting which is selected.
- virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse = RECURSE_NO);
-
- // Get the current state of the folder.
- virtual BOOL isOpen() { return mIsOpen; }
-
- // special case if an object is dropped on the child.
- BOOL handleDragAndDropFromChild(MASK mask,
- BOOL drop,
- EDragAndDropType cargo_type,
- void* cargo_data,
- EAcceptance* accept,
- std::string& tooltip_msg);
-
- void applyFunctorRecursively(LLFolderViewFunctor& functor);
- virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor);
-
- virtual void openItem( void );
- virtual BOOL addItem(LLFolderViewItem* item);
- virtual BOOL addFolder( LLFolderViewFolder* folder);
-
- // LLView functionality
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
- virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );
- virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask );
- virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
- EDragAndDropType cargo_type,
- void* cargo_data,
- EAcceptance* accept,
- std::string& tooltip_msg);
- virtual void draw();
-
- time_t getCreationDate() const;
- bool isTrash() const;
-};
-
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLFolderView
@@ -718,42 +87,47 @@ public:
// manages the screen region of the folder view.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLUICtrl;
-class LLLineEditor;
-
-class LLFolderView : public LLFolderViewFolder, LLEditMenuHandler
+class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler
{
public:
- typedef void (*SelectCallback)(const std::deque<LLFolderViewItem*> &items, BOOL user_action, void* data);
-
- static F32 sAutoOpenTime;
-
- LLFolderView( const std::string& name, LLUIImagePtr root_folder_icon, const LLRect& rect,
- const LLUUID& source_id, LLView *parent_view );
+ struct Params : public LLInitParam::Block<Params, LLFolderViewFolder::Params>
+ {
+ Mandatory<LLPanel*> parent_panel;
+ Optional<LLUUID> task_id;
+ };
+ LLFolderView(const Params&);
virtual ~LLFolderView( void );
virtual BOOL canFocusChildren() const;
+ virtual LLFolderView* getRoot() { return this; }
+
// FolderViews default to sort by name. This will change that,
// and resort the items if necessary.
void setSortOrder(U32 order);
void checkTreeResortForModelChanged();
- void setFilterPermMask(PermissionMask filter_perm_mask) { mFilter.setFilterPermissions(filter_perm_mask); }
- void setSelectCallback(SelectCallback callback, void* user_data) { mSelectCallback = callback, mUserData = user_data; }
+ void setFilterPermMask(PermissionMask filter_perm_mask);
void setAllowMultiSelect(BOOL allow) { mAllowMultiSelect = allow; }
-
- LLInventoryFilter* getFilter() { return &mFilter; }
+
+ typedef boost::signals2::signal<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)> signal_t;
+ void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); }
+ void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); }
+
+ // filter is never null
+ LLInventoryFilter* getFilter();
const std::string getFilterSubString(BOOL trim = FALSE);
- U32 getFilterTypes() const { return mFilter.getFilterTypes(); }
- PermissionMask getFilterPermissions() const { return mFilter.getFilterPermissions(); }
- LLInventoryFilter::EFolderShow getShowFolderState() { return mFilter.getShowFolderState(); }
+ U32 getFilterObjectTypes() const;
+ PermissionMask getFilterPermissions() const;
+ // JAMESDEBUG use getFilter()->getShowFolderState();
+ //LLInventoryFilter::EFolderShow getShowFolderState();
U32 getSortOrder() const;
- BOOL isFilterModified() { return mFilter.isNotDefault(); }
- BOOL getAllowMultiSelect() { return mAllowMultiSelect; }
+ BOOL isFilterModified();
+ BOOL getAllowMultiSelect();
// Close all folders in the view
void closeAllFolders();
void openFolder(const std::string& foldername);
+ void openTopLevelFolders();
virtual void toggleOpen() {};
virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse);
@@ -775,14 +149,20 @@ public:
// Record the selected item and pass it down the hierachy.
virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem,
BOOL take_keyboard_focus);
-
+
+ // Used by menu callbacks
+ void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus);
+
+ // Called once a frame to update the selection if mSelectThisID has been set
+ void updateSelection();
+
// This method is used to toggle the selection of an item. Walks
// children, and keeps track of selected objects.
virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected);
virtual S32 extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items);
- virtual BOOL getSelectionList(std::set<LLUUID> &selection);
+ virtual BOOL getSelectionList(std::set<LLUUID> &selection) const;
// make sure if ancestor is selected, descendents are not
void sanitizeSelection();
@@ -792,6 +172,9 @@ public:
BOOL startDrag(LLToolDragAndDrop::ESource source);
void setDragAndDropThisFrame() { mDragAndDropThisFrame = TRUE; }
+ void setDraggingOverItem(LLFolderViewItem* item) { mDraggingOverItem = item; }
+ LLFolderViewItem* getDraggingOverItem() { return mDraggingOverItem; }
+
// deletion functionality
void removeSelectedItems();
@@ -800,6 +183,9 @@ public:
void openSelectedItems( void );
void propertiesSelectedItems( void );
+ // change the folder type
+ void changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type);
+
void autoOpenItem(LLFolderViewFolder* item);
void closeAutoOpenedFolders();
BOOL autoOpenTest(LLFolderViewFolder* item);
@@ -828,9 +214,6 @@ public:
//void dragItemIntoFolder( LLFolderViewItem* moving_item, LLFolderViewFolder* dst_folder, BOOL drop, BOOL* accept );
//void dragFolderIntoFolder( LLFolderViewFolder* moving_folder, LLFolderViewFolder* dst_folder, BOOL drop, BOOL* accept );
- // LLUICtrl Functionality
- /*virtual*/ void setFocus(BOOL focus);
-
// LLView functionality
///*virtual*/ BOOL handleKey( KEY key, MASK mask, BOOL called_from_parent );
/*virtual*/ BOOL handleKeyHere( KEY key, MASK mask );
@@ -845,14 +228,12 @@ public:
EAcceptance* accept,
std::string& tooltip_msg);
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
- /*virtual*/ void onFocusLost();
- virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
virtual void draw();
virtual void deleteAllChildren();
void scrollToShowSelection();
- void scrollToShowItem(LLFolderViewItem* item);
- void setScrollContainer( LLScrollableContainerView* parent ) { mScrollContainer = parent; }
+ void scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect);
+ void setScrollContainer( LLScrollContainer* parent ) { mScrollContainer = parent; }
LLRect getVisibleRect();
BOOL search(LLFolderViewItem* first_item, const std::string &search_string, BOOL backward);
@@ -861,11 +242,16 @@ public:
void setShowSingleSelection(BOOL show);
BOOL getShowSingleSelection() { return mShowSingleSelection; }
F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); }
+ void setUseEllipses(bool use_ellipses) { mUseEllipses = use_ellipses; }
+ bool getUseEllipses() { return mUseEllipses; }
void addItemID(const LLUUID& id, LLFolderViewItem* itemp);
void removeItemID(const LLUUID& id);
LLFolderViewItem* getItemByID(const LLUUID& id);
-
+ LLFolderViewFolder* getFolderByID(const LLUUID& id);
+
+ bool doToSelected(LLInventoryModel* model, const LLSD& userdata);
+
void doIdle(); // Real idle routine
static void idle(void* user_data); // static glue to doIdle()
@@ -873,20 +259,26 @@ public:
BOOL needsAutoRename() { return mNeedsAutoRename; }
void setNeedsAutoRename(BOOL val) { mNeedsAutoRename = val; }
+ void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; }
+
BOOL getDebugFilters() { return mDebugFilters; }
+ LLPanel* getParentPanel() { return mParentPanel; }
// DEBUG only
void dumpSelectionInformation();
+
+private:
+ void updateRenamerPosition();
protected:
- LLScrollableContainerView* mScrollContainer; // NULL if this is not a child of a scroll container.
+ LLScrollContainer* mScrollContainer; // NULL if this is not a child of a scroll container.
- static void commitRename( LLUICtrl* renamer, void* user_data );
- static void onRenamerLost( LLUICtrl* renamer, void* user_data);
+ void commitRename( const LLSD& data );
+ static void onRenamerLost( LLFocusableElement* renamer);
void finishRenamingItem( void );
void closeRenamer( void );
-
+
protected:
LLHandle<LLView> mPopupMenuHandle;
@@ -902,8 +294,8 @@ protected:
LLLineEditor* mRenamer;
BOOL mNeedsScroll;
- LLFolderViewItem* mLastScrollItem;
- LLCoordGL mLastScrollOffset;
+ BOOL mPinningSelectedItem;
+ LLRect mScrollConstraintRect;
BOOL mNeedsAutoSelect;
BOOL mAutoSelectOverride;
BOOL mNeedsAutoRename;
@@ -915,19 +307,38 @@ protected:
LLFrameTimer mAutoOpenTimer;
LLFrameTimer mSearchTimer;
std::string mSearchString;
- LLInventoryFilter mFilter;
+ LLInventoryFilter* mFilter;
BOOL mShowSelectionContext;
BOOL mShowSingleSelection;
LLFrameTimer mMultiSelectionFadeTimer;
S32 mArrangeGeneration;
- void* mUserData;
- SelectCallback mSelectCallback;
+ signal_t mSelectSignal;
+ signal_t mReshapeSignal;
S32 mSignalSelectCallback;
S32 mMinWidth;
std::map<LLUUID, LLFolderViewItem*> mItemMap;
BOOL mDragAndDropThisFrame;
+
+ LLUUID mSelectThisID; // if non null, select this item
+
+ LLPanel* mParentPanel;
+
+ /**
+ * Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll.
+ * NOTE: For now it uses only to cut LLFolderViewItem::mLabel text to be used for Landmarks in Places Panel.
+ */
+ bool mUseEllipses; // See EXT-719
+
+ /**
+ * Contains item under mouse pointer while dragging
+ */
+ LLFolderViewItem* mDraggingOverItem; // See EXT-719
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* mCallbackRegistrar;
+
+public:
+ static F32 sAutoOpenTime;
};
bool sort_item_name(LLFolderViewItem* a, LLFolderViewItem* b);
diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h
new file mode 100644
index 0000000000..d6c4459e6f
--- /dev/null
+++ b/indra/newview/llfoldervieweventlistener.h
@@ -0,0 +1,105 @@
+/**
+ * @file llfoldervieweventlistener.h
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef LLFOLDERVIEWEVENTLISTENER_H
+#define LLFOLDERVIEWEVENTLISTENER_H
+
+#include "lldarray.h" // JAMESDEBUG convert to std::vector
+#include "llfoldertype.h"
+#include "llfontgl.h" // just for StyleFlags enum
+#include "llinventorytype.h"
+#include "llpermissionsflags.h"
+#include "llpointer.h"
+
+
+class LLFolderViewItem;
+class LLFolderView;
+class LLFontGL;
+class LLInventoryModel;
+class LLMenuGL;
+class LLScrollContainer;
+class LLUIImage;
+class LLUUID;
+
+// This is an abstract base class that users of the folderview classes
+// would use to catch the useful events emitted from the folder
+// views.
+class LLFolderViewEventListener
+{
+public:
+ virtual ~LLFolderViewEventListener( void ) {}
+ virtual const std::string& getName() const = 0;
+ virtual const std::string& getDisplayName() const = 0;
+ virtual const LLUUID& getUUID() const = 0;
+ virtual time_t getCreationDate() const = 0; // UTC seconds
+ virtual PermissionMask getPermissionMask() const = 0;
+ virtual LLFolderType::EType getPreferredType() const = 0;
+ virtual LLPointer<LLUIImage> getIcon() const = 0;
+ virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); }
+ virtual LLFontGL::StyleFlags getLabelStyle() const = 0;
+ virtual std::string getLabelSuffix() const = 0;
+ virtual void openItem( void ) = 0;
+ virtual void closeItem( void ) = 0;
+ virtual void previewItem( void ) = 0;
+ virtual void selectItem(void) = 0;
+ virtual void showProperties(void) = 0;
+ virtual BOOL isItemRenameable() const = 0;
+ virtual BOOL renameItem(const std::string& new_name) = 0;
+ virtual BOOL isItemMovable( void ) const = 0; // Can be moved to another folder
+ virtual BOOL isItemRemovable( void ) = 0; // Can be destroyed
+ virtual BOOL removeItem() = 0;
+ virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) = 0;
+ virtual void move( LLFolderViewEventListener* parent_listener ) = 0;
+ virtual BOOL isItemCopyable() const = 0;
+ virtual BOOL copyToClipboard() const = 0;
+ virtual void cutToClipboard() = 0;
+ virtual BOOL isClipboardPasteable() const = 0;
+ virtual void pasteFromClipboard() = 0;
+ virtual void pasteLinkFromClipboard() = 0;
+ virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0;
+ virtual BOOL isUpToDate() const = 0;
+ virtual BOOL hasChildren() const = 0;
+ virtual LLInventoryType::EType getInventoryType() const = 0;
+ virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) = 0;
+
+ // This method should be called when a drag begins. returns TRUE
+ // if the drag can begin, otherwise FALSE.
+ virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0;
+
+ // This method will be called to determine if a drop can be
+ // performed, and will set drop to TRUE if a drop is
+ // requested. Returns TRUE if a drop is possible/happened,
+ // otherwise FALSE.
+ virtual BOOL dragOrDrop(MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data) = 0;
+};
+
+#endif
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
new file mode 100644
index 0000000000..4b48626b22
--- /dev/null
+++ b/indra/newview/llfolderviewitem.cpp
@@ -0,0 +1,2611 @@
+/**
+* @file llfolderviewitem.cpp
+* @brief Items and folders that can appear in a hierarchical folder view
+*
+* $LicenseInfo:firstyear=2001&license=viewergpl$
+*
+* Copyright (c) 2001-2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+#include "llviewerprecompiledheaders.h"
+
+#include "llfolderviewitem.h"
+
+// viewer includes
+#include "llfolderview.h" // Items depend extensively on LLFolderViews
+#include "llfoldervieweventlistener.h"
+#include "llinventorybridge.h" // for LLItemBridge in LLInventorySort::operator()
+#include "llinventoryfilter.h"
+#include "llpanel.h"
+#include "llviewercontrol.h" // gSavedSettings
+#include "llviewerinventory.h"
+#include "llviewerwindow.h" // Argh, only for setCursor()
+
+// linden library includes
+#include "llfocusmgr.h" // gFocusMgr
+#include "lltrans.h"
+
+///----------------------------------------------------------------------------
+/// Class LLFolderViewItem
+///----------------------------------------------------------------------------
+
+static LLDefaultChildRegistry::Register<LLFolderViewItem> r("folder_view_item");
+
+// statics
+std::map<U8, LLFontGL*> LLFolderViewItem::sFonts; // map of styles to fonts
+
+// only integers can be initialized in header
+const F32 LLFolderViewItem::FOLDER_CLOSE_TIME_CONSTANT = 0.02f;
+const F32 LLFolderViewItem::FOLDER_OPEN_TIME_CONSTANT = 0.03f;
+
+const LLColor4U DEFAULT_WHITE(255, 255, 255);
+
+
+//static
+LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style)
+{
+ LLFontGL* rtn = sFonts[style];
+ if (!rtn) // grab label font with this style, lazily
+ {
+ LLFontDescriptor labelfontdesc("SansSerif", "Small", style);
+ rtn = LLFontGL::getFont(labelfontdesc);
+ if (!rtn)
+ {
+ rtn = LLFontGL::getFontDefault();
+ }
+ sFonts[style] = rtn;
+ }
+ return rtn;
+}
+
+//static
+void LLFolderViewItem::initClass()
+{
+}
+
+//static
+void LLFolderViewItem::cleanupClass()
+{
+ sFonts.clear();
+}
+
+
+// NOTE: Optimize this, we call it a *lot* when opening a large inventory
+LLFolderViewItem::Params::Params()
+: icon(),
+ icon_open(),
+ root(),
+ listener(),
+ folder_arrow_image("folder_arrow_image"),
+ folder_indentation("folder_indentation"),
+ selection_image("selection_image"),
+ item_height("item_height"),
+ item_top_pad("item_top_pad"),
+ creation_date()
+{
+ mouse_opaque(true);
+ follows.flags(FOLLOWS_LEFT|FOLLOWS_TOP|FOLLOWS_RIGHT);
+}
+
+// Default constructor
+LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
+: LLView(p),
+ mLabelWidth(0),
+ mLabelWidthDirty(false),
+ mParentFolder( NULL ),
+ mIsSelected( FALSE ),
+ mIsCurSelection( FALSE ),
+ mSelectPending(FALSE),
+ mLabelStyle( LLFontGL::NORMAL ),
+ mHasVisibleChildren(FALSE),
+ mIndentation(0),
+ mItemHeight(p.item_height),
+ mNumDescendantsSelected(0),
+ mPassedFilter(FALSE),
+ mLastFilterGeneration(-1),
+ mStringMatchOffset(std::string::npos),
+ mControlLabelRotation(0.f),
+ mDragAndDropTarget(FALSE),
+ mIsLoading(FALSE),
+ mLabel(p.name),
+ mRoot(p.root),
+ mCreationDate(p.creation_date),
+ mIcon(p.icon),
+ mIconOpen(p.icon_open),
+ mListener(p.listener),
+ mHidden(false),
+ mShowLoadStatus(false)
+{
+ refresh();
+}
+
+// Destroys the object
+LLFolderViewItem::~LLFolderViewItem( void )
+{
+ delete mListener;
+ mListener = NULL;
+}
+
+LLFolderView* LLFolderViewItem::getRoot()
+{
+ return mRoot;
+}
+
+// Returns true if this object is a child (or grandchild, etc.) of potential_ancestor.
+BOOL LLFolderViewItem::isDescendantOf( const LLFolderViewFolder* potential_ancestor )
+{
+ LLFolderViewItem* root = this;
+ while( root->mParentFolder )
+ {
+ if( root->mParentFolder == potential_ancestor )
+ {
+ return TRUE;
+ }
+ root = root->mParentFolder;
+ }
+ return FALSE;
+}
+
+LLFolderViewItem* LLFolderViewItem::getNextOpenNode(BOOL include_children)
+{
+ if (!mParentFolder)
+ {
+ return NULL;
+ }
+
+ LLFolderViewItem* itemp = mParentFolder->getNextFromChild( this, include_children );
+ while(itemp && !itemp->getVisible())
+ {
+ LLFolderViewItem* next_itemp = itemp->mParentFolder->getNextFromChild( itemp, include_children );
+ if (itemp == next_itemp)
+ {
+ // hit last item
+ return itemp->getVisible() ? itemp : this;
+ }
+ itemp = next_itemp;
+ }
+
+ return itemp;
+}
+
+LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children)
+{
+ if (!mParentFolder)
+ {
+ return NULL;
+ }
+
+ LLFolderViewItem* itemp = mParentFolder->getPreviousFromChild( this, include_children );
+
+ // Skip over items that are invisible or are hidden from the UI.
+ while(itemp && (!itemp->getVisible() || itemp->getHidden()))
+ {
+ LLFolderViewItem* next_itemp = itemp->mParentFolder->getPreviousFromChild( itemp, include_children );
+ if (itemp == next_itemp)
+ {
+ // hit first item
+ return itemp->getVisible() ? itemp : this;
+ }
+ itemp = next_itemp;
+ }
+
+ return itemp;
+}
+
+// is this item something we think we should be showing?
+// for example, if we haven't gotten around to filtering it yet, then the answer is yes
+// until we find out otherwise
+BOOL LLFolderViewItem::potentiallyVisible()
+{
+ // we haven't been checked against min required filter
+ // or we have and we passed
+ return getLastFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration() || getFiltered();
+}
+
+BOOL LLFolderViewItem::getFiltered()
+{
+ return mPassedFilter && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration();
+}
+
+BOOL LLFolderViewItem::getFiltered(S32 filter_generation)
+{
+ return mPassedFilter && mLastFilterGeneration >= filter_generation;
+}
+
+void LLFolderViewItem::setFiltered(BOOL filtered, S32 filter_generation)
+{
+ mPassedFilter = filtered;
+ mLastFilterGeneration = filter_generation;
+}
+
+void LLFolderViewItem::setIcon(LLUIImagePtr icon)
+{
+ mIcon = icon;
+}
+
+// refresh information from the listener
+void LLFolderViewItem::refreshFromListener()
+{
+ if(mListener)
+ {
+ mLabel = mListener->getDisplayName();
+ LLFolderType::EType preferred_type = mListener->getPreferredType();
+
+ // *TODO: to be removed when database supports multi language. This is a
+ // temporary attempt to display the inventory folder in the user locale.
+ // mantipov: *NOTE: be sure this code is synchronized with LLFriendCardsManager::findChildFolderUUID
+ // it uses the same way to find localized string
+ if (LLFolderType::lookupIsProtectedType(preferred_type))
+ {
+ LLTrans::findString(mLabel, "InvFolder " + mLabel);
+ };
+
+ setIcon(mListener->getIcon());
+ time_t creation_date = mListener->getCreationDate();
+ if (mCreationDate != creation_date)
+ {
+ mCreationDate = mListener->getCreationDate();
+ dirtyFilter();
+ }
+ mLabelStyle = mListener->getLabelStyle();
+ mLabelSuffix = mListener->getLabelSuffix();
+ }
+}
+
+void LLFolderViewItem::refresh()
+{
+ refreshFromListener();
+
+ std::string searchable_label(mLabel);
+ searchable_label.append(mLabelSuffix);
+ LLStringUtil::toUpper(searchable_label);
+
+ if (mSearchableLabel.compare(searchable_label))
+ {
+ mSearchableLabel.assign(searchable_label);
+ dirtyFilter();
+ // some part of label has changed, so overall width has potentially changed, and sort order too
+ if (mParentFolder)
+ {
+ mParentFolder->requestSort();
+ mParentFolder->requestArrange();
+ }
+ }
+
+ mLabelWidthDirty = true;
+}
+
+void LLFolderViewItem::applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor)
+{
+ functor(mListener);
+}
+
+// This function is called when items are added or view filters change. It's
+// implemented here but called by derived classes when folding the
+// views.
+void LLFolderViewItem::filterFromRoot( void )
+{
+ LLFolderViewItem* root = getRoot();
+
+ root->filter(*((LLFolderView*)root)->getFilter());
+}
+
+// This function is called when the folder view is dirty. It's
+// implemented here but called by derived classes when folding the
+// views.
+void LLFolderViewItem::arrangeFromRoot()
+{
+ LLFolderViewItem* root = getRoot();
+
+ S32 height = 0;
+ S32 width = 0;
+ S32 total_height = root->arrange( &width, &height, 0 );
+
+ LLSD params;
+ params["action"] = "size_changes";
+ params["height"] = total_height;
+ getParent()->notifyParent(params);
+}
+
+// Utility function for LLFolderView
+void LLFolderViewItem::arrangeAndSet(BOOL set_selection,
+ BOOL take_keyboard_focus)
+{
+ LLFolderView* root = getRoot();
+ getParentFolder()->requestArrange();
+ if(set_selection)
+ {
+ setSelectionFromRoot(this, TRUE, take_keyboard_focus);
+ if(root)
+ {
+ root->scrollToShowSelection();
+ }
+ }
+}
+
+// This function clears the currently selected item, and records the
+// specified selected item appropriately for display and use in the
+// UI. If open is TRUE, then folders are opened up along the way to
+// the selection.
+void LLFolderViewItem::setSelectionFromRoot(LLFolderViewItem* selection,
+ BOOL openitem,
+ BOOL take_keyboard_focus)
+{
+ getRoot()->setSelection(selection, openitem, take_keyboard_focus);
+}
+
+// helper function to change the selection from the root.
+void LLFolderViewItem::changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected)
+{
+ getRoot()->changeSelection(selection, selected);
+}
+
+void LLFolderViewItem::extendSelectionFromRoot(LLFolderViewItem* selection)
+{
+ LLDynamicArray<LLFolderViewItem*> selected_items;
+
+ getRoot()->extendSelection(selection, NULL, selected_items);
+}
+
+EInventorySortGroup LLFolderViewItem::getSortGroup() const
+{
+ return SG_ITEM;
+}
+
+// addToFolder() returns TRUE if it succeeds. FALSE otherwise
+BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* root)
+{
+ if (!folder)
+ {
+ return FALSE;
+ }
+ mParentFolder = folder;
+ root->addItemID(getListener()->getUUID(), this);
+ return folder->addItem(this);
+}
+
+
+// Finds width and height of this object and it's children. Also
+// makes sure that this view and it's children are the right size.
+S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation)
+{
+ const Params& p = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>();
+ S32 indentation = p.folder_indentation();
+ // Only indent deeper items in hierarchy
+ mIndentation = (getParentFolder()
+ && getParentFolder()->getParentFolder() )
+ ? mParentFolder->getIndentation() + indentation
+ : 0;
+ if (mLabelWidthDirty)
+ {
+ mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + getLabelFontForStyle(mLabelStyle)->getWidth(mSearchableLabel);
+ mLabelWidthDirty = false;
+ }
+
+ *width = llmax(*width, mLabelWidth + mIndentation);
+
+ // determine if we need to use ellipses to avoid horizontal scroll. EXT-719
+ bool use_ellipses = getRoot()->getUseEllipses();
+ if (use_ellipses)
+ {
+ // limit to set rect to avoid horizontal scrollbar
+ *width = llmin(*width, getRoot()->getRect().getWidth());
+ }
+ *height = getItemHeight();
+ return *height;
+}
+
+S32 LLFolderViewItem::getItemHeight()
+{
+ if (mHidden) return 0;
+
+ //S32 icon_height = mIcon->getHeight();
+ //S32 label_height = llround(getLabelFontForStyle(mLabelStyle)->getLineHeight());
+ //return llmax( icon_height, label_height ) + ICON_PAD;
+ return mItemHeight;
+}
+
+void LLFolderViewItem::filter( LLInventoryFilter& filter)
+{
+ const BOOL previous_passed_filter = mPassedFilter;
+ const BOOL passed_filter = mListener && filter.check(this);
+
+ // If our visibility will change as a result of this filter, then
+ // we need to be rearranged in our parent folder
+ if (mParentFolder)
+ {
+ if (getVisible() != passed_filter)
+ mParentFolder->requestArrange();
+ if (passed_filter != previous_passed_filter)
+ mParentFolder->requestArrange();
+ }
+
+ setFiltered(passed_filter, filter.getCurrentGeneration());
+ mStringMatchOffset = filter.getStringMatchOffset();
+ filter.decrementFilterCount();
+
+ if (getRoot()->getDebugFilters())
+ {
+ mStatusText = llformat("%d", mLastFilterGeneration);
+ }
+}
+
+void LLFolderViewItem::dirtyFilter()
+{
+ mLastFilterGeneration = -1;
+ // bubble up dirty flag all the way to root
+ if (getParentFolder())
+ {
+ getParentFolder()->setCompletedFilterGeneration(-1, TRUE);
+ }
+}
+
+// *TODO: This can be optimized a lot by simply recording that it is
+// selected in the appropriate places, and assuming that set selection
+// means 'deselect' for a leaf item. Do this optimization after
+// multiple selection is implemented to make sure it all plays nice
+// together.
+BOOL LLFolderViewItem::setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus)
+{
+ if( selection == this )
+ {
+ mIsSelected = TRUE;
+ if(mListener)
+ {
+ mListener->selectItem();
+ }
+ }
+ else
+ {
+ mIsSelected = FALSE;
+ }
+ return mIsSelected;
+}
+
+BOOL LLFolderViewItem::changeSelection(LLFolderViewItem* selection, BOOL selected)
+{
+ if(selection == this && mIsSelected != selected)
+ {
+ mIsSelected = selected;
+ if(mListener)
+ {
+ mListener->selectItem();
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void LLFolderViewItem::recursiveDeselect(BOOL deselect_self)
+{
+ if (mIsSelected && deselect_self)
+ {
+ mIsSelected = FALSE;
+
+ // update ancestors' count of selected descendents
+ LLFolderViewFolder* parent_folder = getParentFolder();
+ while(parent_folder)
+ {
+ parent_folder->mNumDescendantsSelected--;
+ parent_folder = parent_folder->getParentFolder();
+ }
+ }
+}
+
+
+BOOL LLFolderViewItem::isMovable()
+{
+ if( mListener )
+ {
+ return mListener->isItemMovable();
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+BOOL LLFolderViewItem::isRemovable()
+{
+ if( mListener )
+ {
+ return mListener->isItemRemovable();
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+void LLFolderViewItem::destroyView()
+{
+ if (mParentFolder)
+ {
+ // removeView deletes me
+ mParentFolder->removeView(this);
+ }
+}
+
+// Call through to the viewed object and return true if it can be
+// removed.
+//BOOL LLFolderViewItem::removeRecursively(BOOL single_item)
+BOOL LLFolderViewItem::remove()
+{
+ if(!isRemovable())
+ {
+ return FALSE;
+ }
+ if(mListener)
+ {
+ return mListener->removeItem();
+ }
+ return TRUE;
+}
+
+// Build an appropriate context menu for the item.
+void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ if(mListener)
+ {
+ mListener->buildContextMenu(menu, flags);
+ }
+}
+
+void LLFolderViewItem::openItem( void )
+{
+ if( mListener )
+ {
+ mListener->openItem();
+ }
+}
+
+void LLFolderViewItem::preview( void )
+{
+ if (mListener)
+ {
+ mListener->previewItem();
+ }
+}
+
+void LLFolderViewItem::rename(const std::string& new_name)
+{
+ if( !new_name.empty() )
+ {
+ if( mListener )
+ {
+ mListener->renameItem(new_name);
+
+ if(mParentFolder)
+ {
+ mParentFolder->requestSort();
+ }
+ }
+ }
+}
+
+const std::string& LLFolderViewItem::getSearchableLabel() const
+{
+ return mSearchableLabel;
+}
+
+LLViewerInventoryItem * LLFolderViewItem::getInventoryItem(void)
+{
+ return gInventory.getItem(getListener()->getUUID());
+}
+
+std::string LLFolderViewItem::getName( void ) const
+{
+ if(mListener)
+ {
+ return mListener->getName();
+ }
+ return mLabel;
+}
+
+// LLView functionality
+BOOL LLFolderViewItem::handleRightMouseDown( S32 x, S32 y, MASK mask )
+{
+ if(!mIsSelected)
+ {
+ setSelectionFromRoot(this, FALSE);
+ }
+ make_ui_sound("UISndClick");
+ return TRUE;
+}
+
+BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask )
+{
+ if (LLView::childrenHandleMouseDown(x, y, mask))
+ {
+ return TRUE;
+ }
+
+ // No handler needed for focus lost since this class has no
+ // state that depends on it.
+ gFocusMgr.setMouseCapture( this );
+
+ if (!mIsSelected)
+ {
+ if(mask & MASK_CONTROL)
+ {
+ changeSelectionFromRoot(this, !mIsSelected);
+ }
+ else if (mask & MASK_SHIFT)
+ {
+ extendSelectionFromRoot(this);
+ }
+ else
+ {
+ setSelectionFromRoot(this, FALSE);
+ }
+ make_ui_sound("UISndClick");
+ }
+ else
+ {
+ mSelectPending = TRUE;
+ }
+
+ if( isMovable() )
+ {
+ S32 screen_x;
+ S32 screen_y;
+ localPointToScreen(x, y, &screen_x, &screen_y );
+ LLToolDragAndDrop::getInstance()->setDragStart( screen_x, screen_y );
+ }
+ return TRUE;
+}
+
+BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask )
+{
+ if( hasMouseCapture() && isMovable() )
+ {
+ S32 screen_x;
+ S32 screen_y;
+ localPointToScreen(x, y, &screen_x, &screen_y );
+ BOOL can_drag = TRUE;
+ if( LLToolDragAndDrop::getInstance()->isOverThreshold( screen_x, screen_y ) )
+ {
+ LLFolderView* root = getRoot();
+
+ if(root->getCurSelectedItem())
+ {
+ LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_WORLD;
+
+ // *TODO: push this into listener and remove
+ // dependency on llagent
+ if (mListener
+ && gInventory.isObjectDescendentOf(mListener->getUUID(), gInventory.getRootFolderID()))
+ {
+ src = LLToolDragAndDrop::SOURCE_AGENT;
+ }
+ else if (mListener
+ && gInventory.isObjectDescendentOf(mListener->getUUID(), gInventory.getLibraryRootFolderID()))
+ {
+ src = LLToolDragAndDrop::SOURCE_LIBRARY;
+ }
+
+ can_drag = root->startDrag(src);
+ if (can_drag)
+ {
+ // if (mListener) mListener->startDrag();
+ // RN: when starting drag and drop, clear out last auto-open
+ root->autoOpenTest(NULL);
+ root->setShowSelectionContext(TRUE);
+
+ // Release keyboard focus, so that if stuff is dropped into the
+ // world, pressing the delete key won't blow away the inventory
+ // item.
+ gFocusMgr.setKeyboardFocus(NULL);
+
+ return LLToolDragAndDrop::getInstance()->handleHover( x, y, mask );
+ }
+ }
+ }
+
+ if (can_drag)
+ {
+ gViewerWindow->setCursor(UI_CURSOR_ARROW);
+ }
+ else
+ {
+ gViewerWindow->setCursor(UI_CURSOR_NOLOCKED);
+ }
+ return TRUE;
+ }
+ else
+ {
+ getRoot()->setShowSelectionContext(FALSE);
+ gViewerWindow->setCursor(UI_CURSOR_ARROW);
+ // let parent handle this then...
+ return FALSE;
+ }
+}
+
+
+BOOL LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask )
+{
+ preview();
+ return TRUE;
+}
+
+BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask )
+{
+ if (LLView::childrenHandleMouseUp(x, y, mask))
+ {
+ return TRUE;
+ }
+
+ // if mouse hasn't moved since mouse down...
+ if ( pointInView(x, y) && mSelectPending )
+ {
+ //...then select
+ if(mask & MASK_CONTROL)
+ {
+ changeSelectionFromRoot(this, !mIsSelected);
+ }
+ else if (mask & MASK_SHIFT)
+ {
+ extendSelectionFromRoot(this);
+ }
+ else
+ {
+ setSelectionFromRoot(this, FALSE);
+ }
+ }
+
+ mSelectPending = FALSE;
+
+ if( hasMouseCapture() )
+ {
+ getRoot()->setShowSelectionContext(FALSE);
+ gFocusMgr.setMouseCapture( NULL );
+ }
+ return TRUE;
+}
+
+BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg)
+{
+ BOOL accepted = FALSE;
+ BOOL handled = FALSE;
+ if(mListener)
+ {
+ accepted = mListener->dragOrDrop(mask,drop,cargo_type,cargo_data);
+ handled = accepted;
+ if (accepted)
+ {
+ mDragAndDropTarget = TRUE;
+ *accept = ACCEPT_YES_MULTI;
+ }
+ else
+ {
+ *accept = ACCEPT_NO;
+ }
+ }
+ if(mParentFolder && !handled)
+ {
+ // store this item to get it in LLFolderBridge::dragItemIntoFolder on drop event.
+ mRoot->setDraggingOverItem(this);
+ handled = mParentFolder->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg);
+ mRoot->setDraggingOverItem(NULL);
+ }
+ if (handled)
+ {
+ lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewItem" << llendl;
+ }
+
+ return handled;
+}
+
+
+void LLFolderViewItem::draw()
+{
+ if (mHidden) return;
+
+ static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE);
+ static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE);
+ static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE);
+ static LLUIColor sFocusOutlineColor =
+ LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE);
+ static LLUIColor sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE);
+ static LLUIColor sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE);
+ static LLUIColor sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemSuffixColor", DEFAULT_WHITE);
+ static LLUIColor sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE);
+
+ const Params& default_params = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>();
+ const S32 TOP_PAD = default_params.item_top_pad;
+
+ bool possibly_has_children = false;
+ bool up_to_date = mListener && mListener->isUpToDate();
+ if((up_to_date && hasVisibleChildren() ) || // we fetched our children and some of them have passed the filter...
+ (!up_to_date && mListener && mListener->hasChildren())) // ...or we know we have children but haven't fetched them (doesn't obey filter)
+ {
+ possibly_has_children = true;
+ }
+ if(/*mControlLabel[0] != '\0' && */possibly_has_children)
+ {
+ LLUIImage* arrow_image = default_params.folder_arrow_image;
+ gl_draw_scaled_rotated_image(
+ mIndentation, getRect().getHeight() - ARROW_SIZE - TEXT_PAD - TOP_PAD,
+ ARROW_SIZE, ARROW_SIZE, mControlLabelRotation, arrow_image->getImage(), sFgColor);
+ }
+
+ // See also LLFolderView::updateRenamerPosition()
+ F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation);
+
+ LLFontGL* font = getLabelFontForStyle(mLabelStyle);
+
+ // If we have keyboard focus, draw selection filled
+ BOOL show_context = getRoot()->getShowSelectionContext();
+ BOOL filled = show_context || (getRoot()->getParentPanel()->hasFocus());
+ const S32 FOCUS_LEFT = 1;
+ S32 focus_top = getRect().getHeight();
+ S32 focus_bottom = getRect().getHeight() - mItemHeight;
+ bool folder_open = (getRect().getHeight() > mItemHeight + 4);
+
+ // always render "current" item, only render other selected items if
+ // mShowSingleSelection is FALSE
+ if( mIsSelected )
+ {
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ LLColor4 bg_color = sHighlightBgColor;
+ if (!mIsCurSelection)
+ {
+ // do time-based fade of extra objects
+ F32 fade_time = getRoot()->getSelectionFadeElapsedTime();
+ if (getRoot()->getShowSingleSelection())
+ {
+ // fading out
+ bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, bg_color.mV[VALPHA], 0.f);
+ }
+ else
+ {
+ // fading in
+ bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]);
+ }
+ }
+
+ gl_rect_2d(
+ FOCUS_LEFT,
+ focus_top,
+ getRect().getWidth() - 2,
+ focus_bottom,
+ bg_color, filled);
+ if (mIsCurSelection)
+ {
+ gl_rect_2d(
+ FOCUS_LEFT,
+ focus_top,
+ getRect().getWidth() - 2,
+ focus_bottom,
+ sFocusOutlineColor, FALSE);
+ }
+ if (folder_open)
+ {
+ gl_rect_2d(
+ FOCUS_LEFT,
+ focus_bottom + 1, // overlap with bottom edge of above rect
+ getRect().getWidth() - 2,
+ 0,
+ sFocusOutlineColor, FALSE);
+ if (show_context)
+ {
+ gl_rect_2d(
+ FOCUS_LEFT,
+ focus_bottom + 1,
+ getRect().getWidth() - 2,
+ 0,
+ sHighlightBgColor, TRUE);
+ }
+ }
+ }
+ if (mDragAndDropTarget)
+ {
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gl_rect_2d(
+ FOCUS_LEFT,
+ focus_top,
+ getRect().getWidth() - 2,
+ focus_bottom,
+ sHighlightBgColor, FALSE);
+ if (folder_open)
+ {
+ gl_rect_2d(
+ FOCUS_LEFT,
+ focus_bottom + 1, // overlap with bottom edge of above rect
+ getRect().getWidth() - 2,
+ 0,
+ sHighlightBgColor, FALSE);
+ }
+ mDragAndDropTarget = FALSE;
+ }
+
+ S32 icon_x = mIndentation + ARROW_SIZE + TEXT_PAD;
+ // First case is used for open folders
+ if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80))
+ {
+ mIconOpen->draw(icon_x, getRect().getHeight() - mIconOpen->getHeight() - TOP_PAD + 1);
+ }
+ else if(mIcon)
+ {
+ mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1);
+ }
+
+ if (!mLabel.empty())
+ {
+ // highlight filtered text
+ BOOL debug_filters = getRoot()->getDebugFilters();
+ LLColor4 color = ( (mIsSelected && filled) ? sHighlightFgColor : sFgColor );
+ F32 right_x;
+ F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD;
+
+ if (debug_filters)
+ {
+ if (!getFiltered() && !possibly_has_children)
+ {
+ color.mV[VALPHA] *= 0.5f;
+ }
+
+ LLColor4 filter_color = mLastFilterGeneration >= getRoot()->getFilter()->getCurrentGeneration() ? LLColor4(0.5f, 0.8f, 0.5f, 1.f) : LLColor4(0.8f, 0.5f, 0.5f, 1.f);
+ LLFontGL::getFontMonospace()->renderUTF8(
+ mStatusText, 0, text_left, y, filter_color,
+ LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
+ S32_MAX, S32_MAX, &right_x, FALSE );
+ text_left = right_x;
+ }
+
+
+ font->renderUTF8( mLabel, 0, text_left, y, color,
+ LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
+ S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE);
+
+// LLViewerInventoryCategory *item = 0;
+// if (getListener())
+// item = gInventory.getCategory(getListener()->getUUID());
+ bool root_is_loading = false;
+ if (getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(),gInventory.getRootFolderID()))
+ {
+ // Descendent of my inventory.
+ root_is_loading = gInventory.myInventoryFetchInProgress();
+ }
+ if (getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(),gInventory.getLibraryRootFolderID()))
+ {
+ // Descendent of library
+ root_is_loading = gInventory.libraryFetchInProgress();
+ }
+
+ if ( (mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime"))
+ || (LLInventoryModel::backgroundFetchActive() && root_is_loading && mShowLoadStatus) )
+ {
+ std::string load_string = " ( " + LLTrans::getString("LoadingData") + " ) ";
+ font->renderUTF8(load_string, 0, right_x, y, sSearchStatusColor,
+ LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, &right_x, FALSE);
+ }
+
+ if (!mLabelSuffix.empty())
+ {
+ font->renderUTF8( mLabelSuffix, 0, right_x, y, sSuffixColor,
+ LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
+ S32_MAX, S32_MAX, &right_x, FALSE );
+ }
+
+ if (mStringMatchOffset != std::string::npos)
+ {
+ // don't draw backgrounds for zero-length strings
+ S32 filter_string_length = getRoot()->getFilterSubString().size();
+ if (filter_string_length > 0)
+ {
+ std::string combined_string = mLabel + mLabelSuffix;
+ S32 left = llround(text_left) + font->getWidth(combined_string, 0, mStringMatchOffset) - 1;
+ S32 right = left + font->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2;
+ S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD);
+ S32 top = getRect().getHeight() - TOP_PAD;
+
+ LLUIImage* box_image = default_params.selection_image;
+ LLRect box_rect(left, top, right, bottom);
+ box_image->draw(box_rect, sFilterBGColor);
+ F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mStringMatchOffset);
+ F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD;
+ font->renderUTF8( combined_string, mStringMatchOffset, match_string_left, yy,
+ sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
+ filter_string_length, S32_MAX, &right_x, FALSE );
+ }
+ }
+ }
+}
+
+
+///----------------------------------------------------------------------------
+/// Class LLFolderViewFolder
+///----------------------------------------------------------------------------
+
+LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ):
+LLFolderViewItem( p ), // 0 = no create time
+mIsOpen(FALSE),
+mExpanderHighlighted(FALSE),
+mCurHeight(0.f),
+mTargetHeight(0.f),
+mAutoOpenCountdown(0.f),
+mSubtreeCreationDate(0),
+mAmTrash(LLFolderViewFolder::UNKNOWN),
+mLastArrangeGeneration( -1 ),
+mLastCalculatedWidth(0),
+mCompletedFilterGeneration(-1),
+mMostFilteredDescendantGeneration(-1),
+mNeedsSort(false)
+{}
+
+// Destroys the object
+LLFolderViewFolder::~LLFolderViewFolder( void )
+{
+ // The LLView base class takes care of object destruction. make sure that we
+ // don't have mouse or keyboard focus
+ gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit()
+}
+
+// addToFolder() returns TRUE if it succeeds. FALSE otherwise
+BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder, LLFolderView* root)
+{
+ if (!folder)
+ {
+ return FALSE;
+ }
+ mParentFolder = folder;
+ root->addItemID(getListener()->getUUID(), this);
+ return folder->addFolder(this);
+}
+
+// Finds width and height of this object and it's children. Also
+// makes sure that this view and it's children are the right size.
+S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)
+{
+ // sort before laying out contents
+ if (mNeedsSort)
+ {
+ mFolders.sort(mSortFunction);
+ mItems.sort(mSortFunction);
+ mNeedsSort = false;
+ }
+
+ mHasVisibleChildren = hasFilteredDescendants(filter_generation);
+
+ LLInventoryFilter::EFolderShow show_folder_state = getRoot()->getFilter()->getShowFolderState();
+
+ // calculate height as a single item (without any children), and reshapes rectangle to match
+ LLFolderViewItem::arrange( width, height, filter_generation );
+
+ // clamp existing animated height so as to never get smaller than a single item
+ mCurHeight = llmax((F32)*height, mCurHeight);
+
+ // initialize running height value as height of single item in case we have no children
+ *height = getItemHeight();
+ F32 running_height = (F32)*height;
+ F32 target_height = (F32)*height;
+
+ // are my children visible?
+ if (needsArrange())
+ {
+ // set last arrange generation first, in case children are animating
+ // and need to be arranged again
+ mLastArrangeGeneration = getRoot()->getArrangeGeneration();
+ if (mIsOpen)
+ {
+ // Add sizes of children
+ S32 parent_item_height = getRect().getHeight();
+
+ for(folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit)
+ {
+ LLFolderViewFolder* folderp = (*fit);
+ if (getRoot()->getDebugFilters())
+ {
+ folderp->setVisible(TRUE);
+ }
+ else
+ {
+ folderp->setVisible(show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS || // always show folders?
+ (folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter
+ }
+
+ if (folderp->getVisible())
+ {
+ S32 child_width = *width;
+ S32 child_height = 0;
+ S32 child_top = parent_item_height - llround(running_height);
+
+ target_height += folderp->arrange( &child_width, &child_height, filter_generation );
+
+ running_height += (F32)child_height;
+ *width = llmax(*width, child_width);
+ folderp->setOrigin( 0, child_top - folderp->getRect().getHeight() );
+ }
+ }
+ for(items_t::iterator iit = mItems.begin();
+ iit != mItems.end(); ++iit)
+ {
+ LLFolderViewItem* itemp = (*iit);
+ if (getRoot()->getDebugFilters())
+ {
+ itemp->setVisible(TRUE);
+ }
+ else
+ {
+ itemp->setVisible(itemp->getFiltered(filter_generation));
+ }
+
+ if (itemp->getVisible())
+ {
+ S32 child_width = *width;
+ S32 child_height = 0;
+ S32 child_top = parent_item_height - llround(running_height);
+
+ target_height += itemp->arrange( &child_width, &child_height, filter_generation );
+ // don't change width, as this item is as wide as its parent folder by construction
+ itemp->reshape( itemp->getRect().getWidth(), child_height);
+
+ running_height += (F32)child_height;
+ *width = llmax(*width, child_width);
+ itemp->setOrigin( 0, child_top - itemp->getRect().getHeight() );
+ }
+ }
+ }
+
+ mTargetHeight = target_height;
+ // cache this width so next time we can just return it
+ mLastCalculatedWidth = *width;
+ }
+ else
+ {
+ // just use existing width
+ *width = mLastCalculatedWidth;
+ }
+
+ // animate current height towards target height
+ if (llabs(mCurHeight - mTargetHeight) > 1.f)
+ {
+ mCurHeight = lerp(mCurHeight, mTargetHeight, LLCriticalDamp::getInterpolant(mIsOpen ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT));
+
+ requestArrange();
+
+ // hide child elements that fall out of current animated height
+ for (folders_t::iterator iter = mFolders.begin();
+ iter != mFolders.end();)
+ {
+ folders_t::iterator fit = iter++;
+ // number of pixels that bottom of folder label is from top of parent folder
+ if (getRect().getHeight() - (*fit)->getRect().mTop + (*fit)->getItemHeight()
+ > llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP)
+ {
+ // hide if beyond current folder height
+ (*fit)->setVisible(FALSE);
+ }
+ }
+
+ for (items_t::iterator iter = mItems.begin();
+ iter != mItems.end();)
+ {
+ items_t::iterator iit = iter++;
+ // number of pixels that bottom of item label is from top of parent folder
+ if (getRect().getHeight() - (*iit)->getRect().mBottom
+ > llround(mCurHeight) + MAX_FOLDER_ITEM_OVERLAP)
+ {
+ (*iit)->setVisible(FALSE);
+ }
+ }
+ }
+ else
+ {
+ mCurHeight = mTargetHeight;
+ }
+
+ // don't change width as this item is already as wide as its parent folder
+ reshape(getRect().getWidth(),llround(mCurHeight));
+
+ // pass current height value back to parent
+ *height = llround(mCurHeight);
+
+ return llround(mTargetHeight);
+}
+
+BOOL LLFolderViewFolder::needsArrange()
+{
+ return mLastArrangeGeneration < getRoot()->getArrangeGeneration();
+}
+
+void LLFolderViewFolder::requestSort()
+{
+ mNeedsSort = true;
+ // whenever item order changes, we need to lay things out again
+ requestArrange();
+}
+
+void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recurse_up)
+{
+ mMostFilteredDescendantGeneration = llmin(mMostFilteredDescendantGeneration, generation);
+ mCompletedFilterGeneration = generation;
+ // only aggregate up if we are a lower (older) value
+ if (recurse_up && mParentFolder && generation < mParentFolder->getCompletedFilterGeneration())
+ {
+ mParentFolder->setCompletedFilterGeneration(generation, TRUE);
+ }
+}
+
+void LLFolderViewFolder::filter( LLInventoryFilter& filter)
+{
+ S32 filter_generation = filter.getCurrentGeneration();
+ // if failed to pass filter newer than must_pass_generation
+ // you will automatically fail this time, so we only
+ // check against items that have passed the filter
+ S32 must_pass_generation = filter.getMustPassGeneration();
+
+ bool autoopen_folders = (filter.hasFilterString());
+
+ // if we have already been filtered against this generation, skip out
+ if (getCompletedFilterGeneration() >= filter_generation)
+ {
+ return;
+ }
+
+ // filter folder itself
+ if (getLastFilterGeneration() < filter_generation)
+ {
+ if (getLastFilterGeneration() >= must_pass_generation && // folder has been compared to a valid precursor filter
+ !mPassedFilter) // and did not pass the filter
+ {
+ // go ahead and flag this folder as done
+ mLastFilterGeneration = filter_generation;
+ }
+ else
+ {
+ // filter self only on first pass through
+ LLFolderViewItem::filter( filter );
+ }
+ if (mHidden)
+ {
+ setOpen();
+ }
+ }
+
+ if (getRoot()->getDebugFilters())
+ {
+ mStatusText = llformat("%d", mLastFilterGeneration);
+ mStatusText += llformat("(%d)", mCompletedFilterGeneration);
+ mStatusText += llformat("+%d", mMostFilteredDescendantGeneration);
+ }
+
+ // all descendants have been filtered later than must pass generation
+ // but none passed
+ if(getCompletedFilterGeneration() >= must_pass_generation && !hasFilteredDescendants(must_pass_generation))
+ {
+ // don't traverse children if we've already filtered them since must_pass_generation
+ // and came back with nothing
+ return;
+ }
+
+ // we entered here with at least one filter iteration left
+ // check to see if we have any more before continuing on to children
+ if (filter.getFilterCount() < 0)
+ {
+ return;
+ }
+
+ // when applying a filter, matching folders get their contents downloaded first
+ if (filter.isNotDefault() && getFiltered(filter.getMinRequiredGeneration()) && (mListener && !gInventory.isCategoryComplete(mListener->getUUID())))
+ {
+ gInventory.startBackgroundFetch(mListener->getUUID());
+ }
+
+ // now query children
+ for (folders_t::iterator iter = mFolders.begin();
+ iter != mFolders.end();
+ ++iter)
+ {
+ LLFolderViewFolder* folder = (*iter);
+ // have we run out of iterations this frame?
+ if (filter.getFilterCount() < 0)
+ {
+ break;
+ }
+
+ // mMostFilteredDescendantGeneration might have been reset
+ // in which case we need to update it even for folders that
+ // don't need to be filtered anymore
+ if (folder->getCompletedFilterGeneration() >= filter_generation)
+ {
+ // track latest generation to pass any child items
+ if (folder->getFiltered() || folder->hasFilteredDescendants(filter.getMinRequiredGeneration()))
+ {
+ mMostFilteredDescendantGeneration = filter_generation;
+ if (getRoot()->needsAutoSelect() && autoopen_folders)
+ {
+ folder->setOpenArrangeRecursively(TRUE);
+ }
+ }
+ // just skip it, it has already been filtered
+ continue;
+ }
+
+ // update this folders filter status (and children)
+ folder->filter( filter );
+
+ // track latest generation to pass any child items
+ if (folder->getFiltered() || folder->hasFilteredDescendants(filter_generation))
+ {
+ mMostFilteredDescendantGeneration = filter_generation;
+ if (getRoot()->needsAutoSelect() && autoopen_folders)
+ {
+ folder->setOpenArrangeRecursively(TRUE);
+ }
+ }
+ }
+
+ for (items_t::iterator iter = mItems.begin();
+ iter != mItems.end();
+ ++iter)
+ {
+ LLFolderViewItem* item = (*iter);
+ if (filter.getFilterCount() < 0)
+ {
+ break;
+ }
+ if (item->getLastFilterGeneration() >= filter_generation)
+ {
+ if (item->getFiltered())
+ {
+ mMostFilteredDescendantGeneration = filter_generation;
+ }
+ continue;
+ }
+
+ if (item->getLastFilterGeneration() >= must_pass_generation &&
+ !item->getFiltered(must_pass_generation))
+ {
+ // failed to pass an earlier filter that was a subset of the current one
+ // go ahead and flag this item as done
+ item->setFiltered(FALSE, filter_generation);
+ continue;
+ }
+
+ item->filter( filter );
+
+ if (item->getFiltered(filter.getMinRequiredGeneration()))
+ {
+ mMostFilteredDescendantGeneration = filter_generation;
+ }
+ }
+
+ // if we didn't use all filter iterations
+ // that means we filtered all of our descendants
+ // instead of exhausting the filter count for this frame
+ if (filter.getFilterCount() > 0)
+ {
+ // flag this folder as having completed filter pass for all descendants
+ setCompletedFilterGeneration(filter_generation, FALSE/*dont recurse up to root*/);
+ }
+}
+
+void LLFolderViewFolder::setFiltered(BOOL filtered, S32 filter_generation)
+{
+ // if this folder is now filtered, but wasn't before
+ // (it just passed)
+ if (filtered && !mPassedFilter)
+ {
+ // reset current height, because last time we drew it
+ // it might have had more visible items than now
+ mCurHeight = 0.f;
+ }
+
+ LLFolderViewItem::setFiltered(filtered, filter_generation);
+}
+
+void LLFolderViewFolder::dirtyFilter()
+{
+ // we're a folder, so invalidate our completed generation
+ setCompletedFilterGeneration(-1, FALSE);
+ LLFolderViewItem::dirtyFilter();
+}
+
+BOOL LLFolderViewFolder::hasFilteredDescendants()
+{
+ return mMostFilteredDescendantGeneration >= getRoot()->getFilter()->getCurrentGeneration();
+}
+
+// Passes selection information on to children and record selection
+// information if necessary.
+BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem,
+ BOOL take_keyboard_focus)
+{
+ BOOL rv = FALSE;
+ if( selection == this )
+ {
+ mIsSelected = TRUE;
+ if(mListener)
+ {
+ mListener->selectItem();
+ }
+ rv = TRUE;
+ }
+ else
+ {
+ mIsSelected = FALSE;
+ rv = FALSE;
+ }
+ BOOL child_selected = FALSE;
+
+ for (folders_t::iterator iter = mFolders.begin();
+ iter != mFolders.end();)
+ {
+ folders_t::iterator fit = iter++;
+ if((*fit)->setSelection(selection, openitem, take_keyboard_focus))
+ {
+ rv = TRUE;
+ child_selected = TRUE;
+ mNumDescendantsSelected++;
+ }
+ }
+ for (items_t::iterator iter = mItems.begin();
+ iter != mItems.end();)
+ {
+ items_t::iterator iit = iter++;
+ if((*iit)->setSelection(selection, openitem, take_keyboard_focus))
+ {
+ rv = TRUE;
+ child_selected = TRUE;
+ mNumDescendantsSelected++;
+ }
+ }
+ if(openitem && child_selected)
+ {
+ setOpenArrangeRecursively(TRUE);
+ }
+ return rv;
+}
+
+// This method is used to change the selection of an item. If
+// selection is 'this', then note selection as true. Returns TRUE
+// if this or a child is now selected.
+BOOL LLFolderViewFolder::changeSelection(LLFolderViewItem* selection,
+ BOOL selected)
+{
+ BOOL rv = FALSE;
+ if(selection == this)
+ {
+ mIsSelected = selected;
+ if(mListener && selected)
+ {
+ mListener->selectItem();
+ }
+ rv = TRUE;
+ }
+
+ for (folders_t::iterator iter = mFolders.begin();
+ iter != mFolders.end();)
+ {
+ folders_t::iterator fit = iter++;
+ if((*fit)->changeSelection(selection, selected))
+ {
+ if (selected)
+ {
+ mNumDescendantsSelected++;
+ }
+ else
+ {
+ mNumDescendantsSelected--;
+ }
+ rv = TRUE;
+ }
+ }
+ for (items_t::iterator iter = mItems.begin();
+ iter != mItems.end();)
+ {
+ items_t::iterator iit = iter++;
+ if((*iit)->changeSelection(selection, selected))
+ {
+ if (selected)
+ {
+ mNumDescendantsSelected++;
+ }
+ else
+ {
+ mNumDescendantsSelected--;
+ }
+ rv = TRUE;
+ }
+ }
+ return rv;
+}
+
+S32 LLFolderViewFolder::extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& selected_items)
+{
+ S32 num_selected = 0;
+
+ // pass on to child folders first
+ for (folders_t::iterator iter = mFolders.begin();
+ iter != mFolders.end();)
+ {
+ folders_t::iterator fit = iter++;
+ num_selected += (*fit)->extendSelection(selection, last_selected, selected_items);
+ mNumDescendantsSelected += num_selected;
+ }
+
+ // handle selection of our immediate children...
+ BOOL reverse_select = FALSE;
+ BOOL found_last_selected = FALSE;
+ BOOL found_selection = FALSE;
+ LLDynamicArray<LLFolderViewItem*> items_to_select;
+ LLFolderViewItem* item;
+
+ //...folders first...
+ for (folders_t::iterator iter = mFolders.begin();
+ iter != mFolders.end();)
+ {
+ folders_t::iterator fit = iter++;
+ item = (*fit);
+ if(item == selection)
+ {
+ found_selection = TRUE;
+ }
+ else if (item == last_selected)
+ {
+ found_last_selected = TRUE;
+ if (found_selection)
+ {
+ reverse_select = TRUE;
+ }
+ }
+
+ if (found_selection || found_last_selected)
+ {
+ // deselect currently selected items so they can be pushed back on queue
+ if (item->isSelected())
+ {
+ item->changeSelection(item, FALSE);
+ }
+ items_to_select.put(item);
+ }
+
+ if (found_selection && found_last_selected)
+ {
+ break;
+ }
+ }
+
+ if (!(found_selection && found_last_selected))
+ {
+ //,,,then items
+ for (items_t::iterator iter = mItems.begin();
+ iter != mItems.end();)
+ {
+ items_t::iterator iit = iter++;
+ item = (*iit);
+ if(item == selection)
+ {
+ found_selection = TRUE;
+ }
+ else if (item == last_selected)
+ {
+ found_last_selected = TRUE;
+ if (found_selection)
+ {
+ reverse_select = TRUE;
+ }
+ }
+
+ if (found_selection || found_last_selected)
+ {
+ // deselect currently selected items so they can be pushed back on queue
+ if (item->isSelected())
+ {
+ item->changeSelection(item, FALSE);
+ }
+ items_to_select.put(item);
+ }
+
+ if (found_selection && found_last_selected)
+ {
+ break;
+ }
+ }
+ }
+
+ if (found_last_selected && found_selection)
+ {
+ // we have a complete selection inside this folder
+ for (S32 index = reverse_select ? items_to_select.getLength() - 1 : 0;
+ reverse_select ? index >= 0 : index < items_to_select.getLength(); reverse_select ? index-- : index++)
+ {
+ LLFolderViewItem* item = items_to_select[index];
+ if (item->changeSelection(item, TRUE))
+ {
+ selected_items.put(item);
+ mNumDescendantsSelected++;
+ num_selected++;
+ }
+ }
+ }
+ else if (found_selection)
+ {
+ // last selection was not in this folder....go ahead and select just the new item
+ if (selection->changeSelection(selection, TRUE))
+ {
+ selected_items.put(selection);
+ mNumDescendantsSelected++;
+ num_selected++;
+ }
+ }
+
+ return num_selected;
+}
+
+void LLFolderViewFolder::recursiveDeselect(BOOL deselect_self)
+{
+ // make sure we don't have negative values
+ llassert(mNumDescendantsSelected >= 0);
+
+ if (mIsSelected && deselect_self)
+ {
+ mIsSelected = FALSE;
+
+ // update ancestors' count of selected descendents
+ LLFolderViewFolder* parent_folder = getParentFolder();
+ while(parent_folder)
+ {
+ parent_folder->mNumDescendantsSelected--;
+ parent_folder = parent_folder->getParentFolder();
+ }
+ }
+
+ if (0 == mNumDescendantsSelected)
+ {
+ return;
+ }
+
+ for (items_t::iterator iter = mItems.begin();
+ iter != mItems.end();)
+ {
+ items_t::iterator iit = iter++;
+ LLFolderViewItem* item = (*iit);
+ item->recursiveDeselect(TRUE);
+ }
+
+ for (folders_t::iterator iter = mFolders.begin();
+ iter != mFolders.end();)
+ {
+ folders_t::iterator fit = iter++;
+ LLFolderViewFolder* folder = (*fit);
+ folder->recursiveDeselect(TRUE);
+ }
+
+}
+
+void LLFolderViewFolder::destroyView()
+{
+ for (items_t::iterator iter = mItems.begin();
+ iter != mItems.end();)
+ {
+ items_t::iterator iit = iter++;
+ LLFolderViewItem* item = (*iit);
+ getRoot()->removeItemID(item->getListener()->getUUID());
+ }
+
+ std::for_each(mItems.begin(), mItems.end(), DeletePointer());
+ mItems.clear();
+
+ while (!mFolders.empty())
+ {
+ LLFolderViewFolder *folderp = mFolders.back();
+ folderp->destroyView(); // removes entry from mFolders
+ }
+
+ deleteAllChildren();
+
+ if (mParentFolder)
+ {
+ mParentFolder->removeView(this);
+ }
+}
+
+// remove the specified item (and any children) if possible. Return
+// TRUE if the item was deleted.
+BOOL LLFolderViewFolder::removeItem(LLFolderViewItem* item)
+{
+ if(item->remove())
+ {
+ //RN: this seem unneccessary as remove() moves to trash
+ //removeView(item);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// simply remove the view (and any children) Don't bother telling the
+// listeners.
+void LLFolderViewFolder::removeView(LLFolderViewItem* item)
+{
+ if (!item || item->getParentFolder() != this)
+ {
+ return;
+ }
+ // deselect without traversing hierarchy
+ item->recursiveDeselect(TRUE);
+ getRoot()->removeFromSelectionList(item);
+ extractItem(item);
+ delete item;
+}
+
+// extractItem() removes the specified item from the folder, but
+// doesn't delete it.
+void LLFolderViewFolder::extractItem( LLFolderViewItem* item )
+{
+ items_t::iterator it = std::find(mItems.begin(), mItems.end(), item);
+ if(it == mItems.end())
+ {
+ // This is an evil downcast. However, it's only doing
+ // pointer comparison to find if (which it should be ) the
+ // item is in the container, so it's pretty safe.
+ LLFolderViewFolder* f = reinterpret_cast<LLFolderViewFolder*>(item);
+ folders_t::iterator ft;
+ ft = std::find(mFolders.begin(), mFolders.end(), f);
+ if(ft != mFolders.end())
+ {
+ mFolders.erase(ft);
+ }
+ }
+ else
+ {
+ mItems.erase(it);
+ }
+ //item has been removed, need to update filter
+ dirtyFilter();
+ //because an item is going away regardless of filter status, force rearrange
+ requestArrange();
+ getRoot()->removeItemID(item->getListener()->getUUID());
+ removeChild(item);
+}
+
+bool LLFolderViewFolder::isTrash() const
+{
+ if (mAmTrash == LLFolderViewFolder::UNKNOWN)
+ {
+ mAmTrash = mListener->getUUID() == gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH, false) ? LLFolderViewFolder::TRASH : LLFolderViewFolder::NOT_TRASH;
+ }
+ return mAmTrash == LLFolderViewFolder::TRASH;
+}
+
+void LLFolderViewFolder::sortBy(U32 order)
+{
+ if (!mSortFunction.updateSort(order))
+ {
+ // No changes.
+ return;
+ }
+
+ // Propegate this change to sub folders
+ for (folders_t::iterator iter = mFolders.begin();
+ iter != mFolders.end();)
+ {
+ folders_t::iterator fit = iter++;
+ (*fit)->sortBy(order);
+ }
+
+ mFolders.sort(mSortFunction);
+ mItems.sort(mSortFunction);
+
+ if (order & LLInventoryFilter::SO_DATE)
+ {
+ time_t latest = 0;
+
+ if (!mItems.empty())
+ {
+ LLFolderViewItem* item = *(mItems.begin());
+ latest = item->getCreationDate();
+ }
+
+ if (!mFolders.empty())
+ {
+ LLFolderViewFolder* folder = *(mFolders.begin());
+ if (folder->getCreationDate() > latest)
+ {
+ latest = folder->getCreationDate();
+ }
+ }
+ mSubtreeCreationDate = latest;
+ }
+}
+
+void LLFolderViewFolder::setItemSortOrder(U32 ordering)
+{
+ if (mSortFunction.updateSort(ordering))
+ {
+ for (folders_t::iterator iter = mFolders.begin();
+ iter != mFolders.end();)
+ {
+ folders_t::iterator fit = iter++;
+ (*fit)->setItemSortOrder(ordering);
+ }
+
+ mFolders.sort(mSortFunction);
+ mItems.sort(mSortFunction);
+ }
+}
+
+EInventorySortGroup LLFolderViewFolder::getSortGroup() const
+{
+ if (isTrash())
+ {
+ return SG_TRASH_FOLDER;
+ }
+
+ // Folders that can't be moved are 'system' folders.
+ if( mListener )
+ {
+ if( !(mListener->isItemMovable()) )
+ {
+ return SG_SYSTEM_FOLDER;
+ }
+ }
+
+ return SG_NORMAL_FOLDER;
+}
+
+BOOL LLFolderViewFolder::isMovable()
+{
+ if( mListener )
+ {
+ if( !(mListener->isItemMovable()) )
+ {
+ return FALSE;
+ }
+
+ for (items_t::iterator iter = mItems.begin();
+ iter != mItems.end();)
+ {
+ items_t::iterator iit = iter++;
+ if(!(*iit)->isMovable())
+ {
+ return FALSE;
+ }
+ }
+
+ for (folders_t::iterator iter = mFolders.begin();
+ iter != mFolders.end();)
+ {
+ folders_t::iterator fit = iter++;
+ if(!(*fit)->isMovable())
+ {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+
+BOOL LLFolderViewFolder::isRemovable()
+{
+ if( mListener )
+ {
+ if( !(mListener->isItemRemovable()) )
+ {
+ return FALSE;
+ }
+
+ for (items_t::iterator iter = mItems.begin();
+ iter != mItems.end();)
+ {
+ items_t::iterator iit = iter++;
+ if(!(*iit)->isRemovable())
+ {
+ return FALSE;
+ }
+ }
+
+ for (folders_t::iterator iter = mFolders.begin();
+ iter != mFolders.end();)
+ {
+ folders_t::iterator fit = iter++;
+ if(!(*fit)->isRemovable())
+ {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+// this is an internal method used for adding items to folders.
+BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item)
+{
+ mItems.push_back(item);
+ item->setRect(LLRect(0, 0, getRect().getWidth(), 0));
+ item->setVisible(FALSE);
+ addChild( item );
+ item->dirtyFilter();
+ requestArrange();
+ requestSort();
+ return TRUE;
+}
+
+// this is an internal method used for adding items to folders.
+BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder)
+{
+ mFolders.push_back(folder);
+ folder->setOrigin(0, 0);
+ folder->reshape(getRect().getWidth(), 0);
+ folder->setVisible(FALSE);
+ addChild( folder );
+ folder->dirtyFilter();
+ // rearrange all descendants too, as our indentation level might have changed
+ folder->requestArrange(TRUE);
+ requestSort();
+ return TRUE;
+}
+
+void LLFolderViewFolder::requestArrange(BOOL include_descendants)
+{
+ mLastArrangeGeneration = -1;
+ // flag all items up to root
+ if (mParentFolder)
+ {
+ mParentFolder->requestArrange();
+ }
+
+ if (include_descendants)
+ {
+ for (folders_t::iterator iter = mFolders.begin();
+ iter != mFolders.end();
+ ++iter)
+ {
+ (*iter)->requestArrange(TRUE);
+ }
+ }
+}
+
+void LLFolderViewFolder::toggleOpen()
+{
+ setOpen(!mIsOpen);
+}
+
+// Force a folder open or closed
+void LLFolderViewFolder::setOpen(BOOL openitem)
+{
+ setOpenArrangeRecursively(openitem);
+}
+
+void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse)
+{
+ BOOL was_open = mIsOpen;
+ mIsOpen = openitem;
+ if (mListener)
+ {
+ if(!was_open && openitem)
+ {
+ mListener->openItem();
+ }
+ else if(was_open && !openitem)
+ {
+ mListener->closeItem();
+ }
+ }
+
+ if (recurse == RECURSE_DOWN || recurse == RECURSE_UP_DOWN)
+ {
+ for (folders_t::iterator iter = mFolders.begin();
+ iter != mFolders.end();)
+ {
+ folders_t::iterator fit = iter++;
+ (*fit)->setOpenArrangeRecursively(openitem, RECURSE_DOWN); /* Flawfinder: ignore */
+ }
+ }
+ if (mParentFolder && (recurse == RECURSE_UP || recurse == RECURSE_UP_DOWN))
+ {
+ mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP);
+ }
+
+ if (was_open != mIsOpen)
+ {
+ requestArrange();
+ }
+}
+
+BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask,
+ BOOL drop,
+ EDragAndDropType c_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg)
+{
+ BOOL accepted = mListener && mListener->dragOrDrop(mask,drop,c_type,cargo_data);
+ if (accepted)
+ {
+ mDragAndDropTarget = TRUE;
+ *accept = ACCEPT_YES_MULTI;
+ }
+ else
+ {
+ *accept = ACCEPT_NO;
+ }
+
+ // drag and drop to child item, so clear pending auto-opens
+ getRoot()->autoOpenTest(NULL);
+
+ return TRUE;
+}
+
+void LLFolderViewFolder::openItem( void )
+{
+ toggleOpen();
+}
+
+void LLFolderViewFolder::applyFunctorToChildren(LLFolderViewFunctor& functor)
+{
+ for (folders_t::iterator iter = mFolders.begin();
+ iter != mFolders.end();)
+ {
+ folders_t::iterator fit = iter++;
+ functor.doItem((*fit));
+ }
+ for (items_t::iterator iter = mItems.begin();
+ iter != mItems.end();)
+ {
+ items_t::iterator iit = iter++;
+ functor.doItem((*iit));
+ }
+}
+
+void LLFolderViewFolder::applyFunctorRecursively(LLFolderViewFunctor& functor)
+{
+ functor.doFolder(this);
+
+ for (folders_t::iterator iter = mFolders.begin();
+ iter != mFolders.end();)
+ {
+ folders_t::iterator fit = iter++;
+ (*fit)->applyFunctorRecursively(functor);
+ }
+ for (items_t::iterator iter = mItems.begin();
+ iter != mItems.end();)
+ {
+ items_t::iterator iit = iter++;
+ functor.doItem((*iit));
+ }
+}
+
+void LLFolderViewFolder::applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor)
+{
+ functor(mListener);
+ for (folders_t::iterator iter = mFolders.begin();
+ iter != mFolders.end();)
+ {
+ folders_t::iterator fit = iter++;
+ (*fit)->applyListenerFunctorRecursively(functor);
+ }
+ for (items_t::iterator iter = mItems.begin();
+ iter != mItems.end();)
+ {
+ items_t::iterator iit = iter++;
+ (*iit)->applyListenerFunctorRecursively(functor);
+ }
+}
+
+// LLView functionality
+BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask,
+ BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg)
+{
+ LLFolderView* root_view = getRoot();
+
+ BOOL handled = FALSE;
+ if(mIsOpen)
+ {
+ handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type,
+ cargo_data, accept, tooltip_msg) != NULL;
+ }
+
+ if (!handled)
+ {
+ BOOL accepted = mListener && mListener->dragOrDrop(mask, drop,cargo_type,cargo_data);
+
+ if (accepted)
+ {
+ mDragAndDropTarget = TRUE;
+ *accept = ACCEPT_YES_MULTI;
+ }
+ else
+ {
+ *accept = ACCEPT_NO;
+ }
+
+ if (!drop && accepted)
+ {
+ root_view->autoOpenTest(this);
+ }
+
+ lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewFolder" << llendl;
+ }
+
+ return TRUE;
+}
+
+
+BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask )
+{
+ BOOL handled = FALSE;
+ // fetch contents of this folder, as context menu can depend on contents
+ // still, user would have to open context menu again to see the changes
+ gInventory.fetchDescendentsOf(mListener->getUUID());
+
+ if( mIsOpen )
+ {
+ handled = childrenHandleRightMouseDown( x, y, mask ) != NULL;
+ }
+ if (!handled)
+ {
+ handled = LLFolderViewItem::handleRightMouseDown( x, y, mask );
+ }
+ return handled;
+}
+
+
+BOOL LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = LLView::handleHover(x, y, mask);
+
+ if (!handled)
+ {
+ // this doesn't do child processing
+ handled = LLFolderViewItem::handleHover(x, y, mask);
+ }
+
+ return handled;
+}
+
+BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask )
+{
+ BOOL handled = FALSE;
+ if( mIsOpen )
+ {
+ handled = childrenHandleMouseDown(x,y,mask) != NULL;
+ }
+ if( !handled )
+ {
+ if(mIndentation < x && x < mIndentation + ARROW_SIZE + TEXT_PAD)
+ {
+ toggleOpen();
+ handled = TRUE;
+ }
+ else
+ {
+ // do normal selection logic
+ handled = LLFolderViewItem::handleMouseDown(x, y, mask);
+ }
+ }
+
+ return handled;
+}
+
+BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask )
+{
+ /* Disable outfit double click to wear
+ const LLUUID &cat_uuid = getListener()->getUUID();
+ const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_uuid);
+ if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT)
+ {
+ getListener()->performAction(NULL, NULL,"replaceoutfit");
+ return TRUE;
+ }
+ */
+
+ BOOL handled = FALSE;
+ if( mIsOpen )
+ {
+ handled = childrenHandleDoubleClick( x, y, mask ) != NULL;
+ }
+ if( !handled )
+ {
+ if(mIndentation < x && x < mIndentation + ARROW_SIZE + TEXT_PAD)
+ {
+ // don't select when user double-clicks plus sign
+ // so as not to contradict single-click behavior
+ toggleOpen();
+ }
+ else
+ {
+ setSelectionFromRoot(this, FALSE);
+ toggleOpen();
+ }
+ handled = TRUE;
+ }
+ return handled;
+}
+
+void LLFolderViewFolder::draw()
+{
+ if (mAutoOpenCountdown != 0.f)
+ {
+ mControlLabelRotation = mAutoOpenCountdown * -90.f;
+ }
+ else if (mIsOpen)
+ {
+ mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLCriticalDamp::getInterpolant(0.04f));
+ }
+ else
+ {
+ mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f));
+ }
+
+ bool possibly_has_children = false;
+ bool up_to_date = mListener && mListener->isUpToDate();
+ if(!up_to_date && mListener && mListener->hasChildren()) // we know we have children but haven't fetched them (doesn't obey filter)
+ {
+ possibly_has_children = true;
+ }
+
+
+ BOOL loading = ( mIsOpen && possibly_has_children && !up_to_date );
+
+ if ( loading && !mIsLoading )
+ {
+ // Measure how long we've been in the loading state
+ mTimeSinceRequestStart.reset();
+ }
+
+ mIsLoading = loading;
+
+ LLFolderViewItem::draw();
+
+ // draw children if root folder, or any other folder that is open or animating to closed state
+ if( getRoot() == this || (mIsOpen || mCurHeight != mTargetHeight ))
+ {
+ LLView::draw();
+ }
+
+ mExpanderHighlighted = FALSE;
+}
+
+time_t LLFolderViewFolder::getCreationDate() const
+{
+ return llmax<time_t>(mCreationDate, mSubtreeCreationDate);
+}
+
+
+BOOL LLFolderViewFolder::potentiallyVisible()
+{
+ // folder should be visible by it's own filter status
+ return LLFolderViewItem::potentiallyVisible()
+ // or one or more of its descendants have passed the minimum filter requirement
+ || hasFilteredDescendants(getRoot()->getFilter()->getMinRequiredGeneration())
+ // or not all of its descendants have been checked against minimum filter requirement
+ || getCompletedFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration();
+}
+
+// this does prefix traversal, as folders are listed above their contents
+LLFolderViewItem* LLFolderViewFolder::getNextFromChild( LLFolderViewItem* item, BOOL include_children )
+{
+ BOOL found_item = FALSE;
+
+ LLFolderViewItem* result = NULL;
+ // when not starting from a given item, start at beginning
+ if(item == NULL)
+ {
+ found_item = TRUE;
+ }
+
+ // find current item among children
+ folders_t::iterator fit = mFolders.begin();
+ folders_t::iterator fend = mFolders.end();
+
+ items_t::iterator iit = mItems.begin();
+ items_t::iterator iend = mItems.end();
+
+ // if not trivially starting at the beginning, we have to find the current item
+ if (!found_item)
+ {
+ // first, look among folders, since they are always above items
+ for(; fit != fend; ++fit)
+ {
+ if(item == (*fit))
+ {
+ found_item = TRUE;
+ // if we are on downwards traversal
+ if (include_children && (*fit)->isOpen())
+ {
+ // look for first descendant
+ return (*fit)->getNextFromChild(NULL, TRUE);
+ }
+ // otherwise advance to next folder
+ ++fit;
+ include_children = TRUE;
+ break;
+ }
+ }
+
+ // didn't find in folders? Check items...
+ if (!found_item)
+ {
+ for(; iit != iend; ++iit)
+ {
+ if(item == (*iit))
+ {
+ found_item = TRUE;
+ // point to next item
+ ++iit;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!found_item)
+ {
+ // you should never call this method with an item that isn't a child
+ // so we should always find something
+ llassert(FALSE);
+ return NULL;
+ }
+
+ // at this point, either iit or fit point to a candidate "next" item
+ // if both are out of range, we need to punt up to our parent
+
+ // now, starting from found folder, continue through folders
+ // searching for next visible folder
+ while(fit != fend && !(*fit)->getVisible())
+ {
+ // turn on downwards traversal for next folder
+ ++fit;
+ }
+
+ if (fit != fend)
+ {
+ result = (*fit);
+ }
+ else
+ {
+ // otherwise, scan for next visible item
+ while(iit != iend && !(*iit)->getVisible())
+ {
+ ++iit;
+ }
+
+ // check to see if we have a valid item
+ if (iit != iend)
+ {
+ result = (*iit);
+ }
+ }
+
+ if( !result && mParentFolder )
+ {
+ // If there are no siblings or children to go to, recurse up one level in the tree
+ // and skip children for this folder, as we've already discounted them
+ result = mParentFolder->getNextFromChild(this, FALSE);
+ }
+
+ return result;
+}
+
+// this does postfix traversal, as folders are listed above their contents
+LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* item, BOOL include_children )
+{
+ BOOL found_item = FALSE;
+
+ LLFolderViewItem* result = NULL;
+ // when not starting from a given item, start at end
+ if(item == NULL)
+ {
+ found_item = TRUE;
+ }
+
+ // find current item among children
+ folders_t::reverse_iterator fit = mFolders.rbegin();
+ folders_t::reverse_iterator fend = mFolders.rend();
+
+ items_t::reverse_iterator iit = mItems.rbegin();
+ items_t::reverse_iterator iend = mItems.rend();
+
+ // if not trivially starting at the end, we have to find the current item
+ if (!found_item)
+ {
+ // first, look among items, since they are always below the folders
+ for(; iit != iend; ++iit)
+ {
+ if(item == (*iit))
+ {
+ found_item = TRUE;
+ // point to next item
+ ++iit;
+ break;
+ }
+ }
+
+ // didn't find in items? Check folders...
+ if (!found_item)
+ {
+ for(; fit != fend; ++fit)
+ {
+ if(item == (*fit))
+ {
+ found_item = TRUE;
+ // point to next folder
+ ++fit;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!found_item)
+ {
+ // you should never call this method with an item that isn't a child
+ // so we should always find something
+ llassert(FALSE);
+ return NULL;
+ }
+
+ // at this point, either iit or fit point to a candidate "next" item
+ // if both are out of range, we need to punt up to our parent
+
+ // now, starting from found item, continue through items
+ // searching for next visible item
+ while(iit != iend && !(*iit)->getVisible())
+ {
+ ++iit;
+ }
+
+ if (iit != iend)
+ {
+ // we found an appropriate item
+ result = (*iit);
+ }
+ else
+ {
+ // otherwise, scan for next visible folder
+ while(fit != fend && !(*fit)->getVisible())
+ {
+ ++fit;
+ }
+
+ // check to see if we have a valid folder
+ if (fit != fend)
+ {
+ // try selecting child element of this folder
+ if ((*fit)->isOpen())
+ {
+ result = (*fit)->getPreviousFromChild(NULL);
+ }
+ else
+ {
+ result = (*fit);
+ }
+ }
+ }
+
+ if( !result )
+ {
+ // If there are no siblings or children to go to, recurse up one level in the tree
+ // which gets back to this folder, which will only be visited if it is a valid, visible item
+ result = this;
+ }
+
+ return result;
+}
+
+
+bool LLInventorySort::updateSort(U32 order)
+{
+ if (order != mSortOrder)
+ {
+ mSortOrder = order;
+ mByDate = (order & LLInventoryFilter::SO_DATE);
+ mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP);
+ mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME);
+ return true;
+ }
+ return false;
+}
+
+bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b)
+{
+ // ignore sort order for landmarks in the Favorites folder.
+ // they should be always sorted as in Favorites bar. See EXT-719
+ if (a->getSortGroup() == SG_ITEM && b->getSortGroup() == SG_ITEM
+ && a->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK
+ && b->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
+ {
+
+ static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+ static const LLUUID& landmarks_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
+
+ LLUUID a_uuid = a->getParentFolder()->getListener()->getUUID();
+ LLUUID b_uuid = b->getParentFolder()->getListener()->getUUID();
+
+ if ((a_uuid == favorites_folder_id && b_uuid == favorites_folder_id) ||
+ (a_uuid == landmarks_folder_id && b_uuid == landmarks_folder_id))
+ {
+ // *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem
+ // or to LLInvFVBridge
+ S32 a_sort = (static_cast<const LLItemBridge*>(a->getListener()))->getItem()->getSortField();
+ S32 b_sort = (static_cast<const LLItemBridge*>(b->getListener()))->getItem()->getSortField();
+ return a_sort < b_sort;
+ }
+ }
+
+ // We sort by name if we aren't sorting by date
+ // OR if these are folders and we are sorting folders by name.
+ bool by_name = (!mByDate
+ || (mFoldersByName
+ && (a->getSortGroup() != SG_ITEM)));
+
+ if (a->getSortGroup() != b->getSortGroup())
+ {
+ if (mSystemToTop)
+ {
+ // Group order is System Folders, Trash, Normal Folders, Items
+ return (a->getSortGroup() < b->getSortGroup());
+ }
+ else if (mByDate)
+ {
+ // Trash needs to go to the bottom if we are sorting by date
+ if ( (a->getSortGroup() == SG_TRASH_FOLDER)
+ || (b->getSortGroup() == SG_TRASH_FOLDER))
+ {
+ return (b->getSortGroup() == SG_TRASH_FOLDER);
+ }
+ }
+ }
+
+ if (by_name)
+ {
+ S32 compare = LLStringUtil::compareDict(a->getLabel(), b->getLabel());
+ if (0 == compare)
+ {
+ return (a->getCreationDate() > b->getCreationDate());
+ }
+ else
+ {
+ return (compare < 0);
+ }
+ }
+ else
+ {
+ // BUG: This is very very slow. The getCreationDate() is log n in number
+ // of inventory items.
+ time_t first_create = a->getCreationDate();
+ time_t second_create = b->getCreationDate();
+ if (first_create == second_create)
+ {
+ return (LLStringUtil::compareDict(a->getLabel(), b->getLabel()) < 0);
+ }
+ else
+ {
+ return (first_create > second_create);
+ }
+ }
+}
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
new file mode 100644
index 0000000000..be8e73a5a9
--- /dev/null
+++ b/indra/newview/llfolderviewitem.h
@@ -0,0 +1,550 @@
+/**
+* @file llfolderviewitem.h
+* @brief Items and folders that can appear in a hierarchical folder view
+*
+* $LicenseInfo:firstyear=2001&license=viewergpl$
+*
+* Copyright (c) 2001-2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+#ifndef LLFOLDERVIEWITEM_H
+#define LLFOLDERVIEWITEM_H
+
+#include "llview.h"
+#include "lldarray.h" // *TODO: Eliminate, forward declare
+
+class LLFontGL;
+class LLFolderView;
+class LLFolderViewEventListener;
+class LLFolderViewFolder;
+class LLFolderViewFunctor;
+class LLFolderViewItem;
+class LLFolderViewListenerFunctor;
+class LLInventoryFilter;
+class LLMenuGL;
+class LLUIImage;
+class LLViewerInventoryItem;
+
+// These are grouping of inventory types.
+// Order matters when sorting system folders to the top.
+enum EInventorySortGroup
+{
+ SG_SYSTEM_FOLDER,
+ SG_TRASH_FOLDER,
+ SG_NORMAL_FOLDER,
+ SG_ITEM
+};
+
+// JAMESDEBUG *TODO: do we really need one sort object per folder?
+// can we just have one of these per LLFolderView ?
+class LLInventorySort
+{
+public:
+ LLInventorySort()
+ : mSortOrder(0),
+ mByDate(false),
+ mSystemToTop(false),
+ mFoldersByName(false) { }
+
+ // Returns true if order has changed
+ bool updateSort(U32 order);
+ U32 getSort() { return mSortOrder; }
+
+ bool operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b);
+private:
+ U32 mSortOrder;
+ bool mByDate;
+ bool mSystemToTop;
+ bool mFoldersByName;
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLFolderViewItem
+//
+// An instance of this class represents a single item in a folder view
+// such as an inventory item or a file.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLFolderViewItem : public LLView
+{
+public:
+ static void initClass();
+ static void cleanupClass();
+
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
+ {
+ Optional<LLUIImage*> icon;
+ Optional<LLUIImage*> icon_open; // used for folders
+ Optional<LLFolderView*> root;
+ Optional<LLFolderViewEventListener*> listener;
+
+ Optional<LLUIImage*> folder_arrow_image;
+ Optional<S32> folder_indentation; // pixels
+ Optional<LLUIImage*> selection_image;
+ Optional<S32> item_height; // pixels
+ Optional<S32> item_top_pad; // pixels
+
+ Optional<S32> creation_date; //UTC seconds
+
+ Params();
+ };
+
+ // layout constants
+ static const S32 LEFT_PAD = 5;
+ // LEFT_INDENTATION is set via folder_indentation above
+ static const S32 ICON_PAD = 2;
+ static const S32 ICON_WIDTH = 16;
+ static const S32 TEXT_PAD = 1;
+ static const S32 ARROW_SIZE = 12;
+ static const S32 MAX_FOLDER_ITEM_OVERLAP = 2;
+ // animation parameters
+ static const F32 FOLDER_CLOSE_TIME_CONSTANT;
+ static const F32 FOLDER_OPEN_TIME_CONSTANT;
+
+ // Mostly for debugging printout purposes.
+ const std::string& getSearchableLabel() { return mSearchableLabel; }
+
+protected:
+ friend class LLUICtrlFactory;
+ friend class LLFolderViewEventListener;
+
+ LLFolderViewItem(const Params& p);
+
+ std::string mLabel;
+ std::string mSearchableLabel;
+ S32 mLabelWidth;
+ bool mLabelWidthDirty;
+ time_t mCreationDate;
+ LLFolderViewFolder* mParentFolder;
+ LLFolderViewEventListener* mListener;
+ BOOL mIsSelected;
+ BOOL mIsCurSelection;
+ BOOL mSelectPending;
+ LLFontGL::StyleFlags mLabelStyle;
+ std::string mLabelSuffix;
+ LLUIImagePtr mIcon;
+ std::string mStatusText;
+ LLUIImagePtr mIconOpen;
+ BOOL mHasVisibleChildren;
+ S32 mIndentation;
+ S32 mItemHeight;
+ S32 mNumDescendantsSelected;
+ BOOL mPassedFilter;
+ S32 mLastFilterGeneration;
+ std::string::size_type mStringMatchOffset;
+ F32 mControlLabelRotation;
+ LLFolderView* mRoot;
+ BOOL mDragAndDropTarget;
+ BOOL mIsLoading;
+ LLTimer mTimeSinceRequestStart;
+ bool mHidden;
+ bool mShowLoadStatus;
+
+ // helper function to change the selection from the root.
+ void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected);
+
+ // helper function to change the selection from the root.
+ void extendSelectionFromRoot(LLFolderViewItem* selection);
+
+ // this is an internal method used for adding items to folders. A
+ // no-op at this leve, but reimplemented in derived classes.
+ virtual BOOL addItem(LLFolderViewItem*) { return FALSE; }
+ virtual BOOL addFolder(LLFolderViewFolder*) { return FALSE; }
+
+ static LLFontGL* getLabelFontForStyle(U8 style);
+
+public:
+ // This function clears the currently selected item, and records
+ // the specified selected item appropriately for display and use
+ // in the UI. If open is TRUE, then folders are opened up along
+ // the way to the selection.
+ void setSelectionFromRoot(LLFolderViewItem* selection, BOOL openitem,
+ BOOL take_keyboard_focus = TRUE);
+
+ // This function is called when the folder view is dirty. It's
+ // implemented here but called by derived classes when folding the
+ // views.
+ void arrangeFromRoot();
+ void filterFromRoot( void );
+
+ void arrangeAndSet(BOOL set_selection, BOOL take_keyboard_focus);
+
+ virtual ~LLFolderViewItem( void );
+
+ // addToFolder() returns TRUE if it succeeds. FALSE otherwise
+ enum { ARRANGE = TRUE, DO_NOT_ARRANGE = FALSE };
+ virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root);
+
+ virtual EInventorySortGroup getSortGroup() const;
+
+ // Finds width and height of this object and it's children. Also
+ // makes sure that this view and it's children are the right size.
+ virtual S32 arrange( S32* width, S32* height, S32 filter_generation );
+ virtual S32 getItemHeight();
+
+ // Hide the folder from the UI, such as if you want to hide the root
+ // folder in an inventory panel.
+ void setHidden(bool hidden) { mHidden = hidden; }
+ bool getHidden() const { return mHidden; }
+
+ // applies filters to control visibility of inventory items
+ virtual void filter( LLInventoryFilter& filter);
+
+ // updates filter serial number and optionally propagated value up to root
+ S32 getLastFilterGeneration() { return mLastFilterGeneration; }
+
+ virtual void dirtyFilter();
+
+ // If the selection is 'this' then note that otherwise
+ // ignore. Returns TRUE if this object was affected. If open is
+ // TRUE, then folders are opened up along the way to the
+ // selection.
+ virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem,
+ BOOL take_keyboard_focus);
+
+ // This method is used to toggle the selection of an item. If
+ // selection is 'this', then note selection, and return TRUE.
+ virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected);
+
+ // this method is used to group select items
+ virtual S32 extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items){ return FALSE; }
+
+ // this method is used to group select items
+ virtual void recursiveDeselect(BOOL deselect_self);
+
+ // gets multiple-element selection
+ virtual BOOL getSelectionList(std::set<LLUUID> &selection) const {return TRUE;}
+
+ // Returns true is this object and all of its children can be removed (deleted by user)
+ virtual BOOL isRemovable();
+
+ // Returns true is this object and all of its children can be moved
+ virtual BOOL isMovable();
+
+ // destroys this item recursively
+ virtual void destroyView();
+
+ S32 getNumSelectedDescendants() { return mNumDescendantsSelected; }
+
+ BOOL isSelected() { return mIsSelected; }
+
+ void setIsCurSelection(BOOL select) { mIsCurSelection = select; }
+
+ BOOL getIsCurSelection() { return mIsCurSelection; }
+
+ BOOL hasVisibleChildren() { return mHasVisibleChildren; }
+
+ void setShowLoadStatus(bool status) { mShowLoadStatus = status; }
+
+ // Call through to the viewed object and return true if it can be
+ // removed. Returns true if it's removed.
+ //virtual BOOL removeRecursively(BOOL single_item);
+ BOOL remove();
+
+ // Build an appropriate context menu for the item. Flags unused.
+ void buildContextMenu(LLMenuGL& menu, U32 flags);
+
+ // This method returns the actual name of the thing being
+ // viewed. This method will ask the viewed object itself.
+ std::string getName( void ) const;
+
+ const std::string& getSearchableLabel( void ) const;
+
+ // This method returns the label displayed on the view. This
+ // method was primarily added to allow sorting on the folder
+ // contents possible before the entire view has been constructed.
+ const std::string& getLabel() const { return mLabel; }
+
+ // Used for sorting, like getLabel() above.
+ virtual time_t getCreationDate() const { return mCreationDate; }
+
+ LLFolderViewFolder* getParentFolder( void ) { return mParentFolder; }
+ const LLFolderViewFolder* getParentFolder( void ) const { return mParentFolder; }
+
+ LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE );
+ LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE );
+
+ const LLFolderViewEventListener* getListener( void ) const { return mListener; }
+ LLFolderViewEventListener* getListener( void ) { return mListener; }
+
+ // Gets the inventory item if it exists (null otherwise)
+ LLViewerInventoryItem * getInventoryItem(void);
+
+ // just rename the object.
+ void rename(const std::string& new_name);
+
+ // open
+ virtual void openItem( void );
+ virtual void preview(void);
+
+ // Show children (unfortunate that this is called "open")
+ virtual void setOpen(BOOL open = TRUE) {};
+
+ virtual BOOL isOpen() const { return FALSE; }
+
+ virtual LLFolderView* getRoot();
+ BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor );
+ S32 getIndentation() { return mIndentation; }
+
+ virtual BOOL potentiallyVisible(); // do we know for a fact that this item has been filtered out?
+
+ virtual BOOL getFiltered();
+ virtual BOOL getFiltered(S32 filter_generation);
+ virtual void setFiltered(BOOL filtered, S32 filter_generation);
+
+ // change the icon
+ void setIcon(LLUIImagePtr icon);
+
+ // refresh information from the object being viewed.
+ void refreshFromListener();
+ virtual void refresh();
+
+ virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor);
+
+ // LLView functionality
+ virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
+ virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );
+ virtual BOOL handleHover( S32 x, S32 y, MASK mask );
+ virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask );
+ virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask );
+
+ // virtual void handleDropped();
+ virtual void draw();
+ virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg);
+
+private:
+ static std::map<U8, LLFontGL*> sFonts; // map of styles to fonts
+};
+
+
+// function used for sorting.
+typedef bool (*sort_order_f)(LLFolderViewItem* a, LLFolderViewItem* b);
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLFolderViewFolder
+//
+// An instance of an LLFolderViewFolder represents a collection of
+// more folders and items. This is used to build the hierarchy of
+// items found in the folder view.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLFolderViewFolder : public LLFolderViewItem
+{
+protected:
+ LLFolderViewFolder( const LLFolderViewItem::Params& );
+ friend class LLUICtrlFactory;
+
+public:
+ typedef enum e_trash
+ {
+ UNKNOWN, TRASH, NOT_TRASH
+ } ETrash;
+
+protected:
+ typedef std::list<LLFolderViewItem*> items_t;
+ typedef std::list<LLFolderViewFolder*> folders_t;
+ items_t mItems;
+ folders_t mFolders;
+ LLInventorySort mSortFunction;
+
+ BOOL mIsOpen;
+ BOOL mExpanderHighlighted;
+ F32 mCurHeight;
+ F32 mTargetHeight;
+ F32 mAutoOpenCountdown;
+ time_t mSubtreeCreationDate;
+ mutable ETrash mAmTrash;
+ S32 mLastArrangeGeneration;
+ S32 mLastCalculatedWidth;
+ S32 mCompletedFilterGeneration;
+ S32 mMostFilteredDescendantGeneration;
+ bool mNeedsSort;
+public:
+ typedef enum e_recurse_type
+ {
+ RECURSE_NO,
+ RECURSE_UP,
+ RECURSE_DOWN,
+ RECURSE_UP_DOWN
+ } ERecurseType;
+
+
+ virtual ~LLFolderViewFolder( void );
+
+ virtual BOOL potentiallyVisible();
+
+ LLFolderViewItem* getNextFromChild( LLFolderViewItem*, BOOL include_children = TRUE );
+ LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE );
+
+ // addToFolder() returns TRUE if it succeeds. FALSE otherwise
+ virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root);
+
+ // Finds width and height of this object and it's children. Also
+ // makes sure that this view and it's children are the right size.
+ virtual S32 arrange( S32* width, S32* height, S32 filter_generation );
+
+ BOOL needsArrange();
+ void requestSort();
+
+ // Returns the sort group (system, trash, folder) for this folder.
+ virtual EInventorySortGroup getSortGroup() const;
+
+ virtual void setCompletedFilterGeneration(S32 generation, BOOL recurse_up);
+ virtual S32 getCompletedFilterGeneration() { return mCompletedFilterGeneration; }
+
+ BOOL hasFilteredDescendants(S32 filter_generation) { return mMostFilteredDescendantGeneration >= filter_generation; }
+ BOOL hasFilteredDescendants();
+
+ // applies filters to control visibility of inventory items
+ virtual void filter( LLInventoryFilter& filter);
+ virtual void setFiltered(BOOL filtered, S32 filter_generation);
+ virtual void dirtyFilter();
+
+ // Passes selection information on to children and record
+ // selection information if necessary. Returns TRUE if this object
+ // (or a child) was affected.
+ virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem,
+ BOOL take_keyboard_focus);
+
+ // This method is used to change the selection of an item. If
+ // selection is 'this', then note selection as true. Returns TRUE
+ // if this or a child is now selected.
+ virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected);
+
+ // this method is used to group select items
+ virtual S32 extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items);
+
+ virtual void recursiveDeselect(BOOL deselect_self);
+
+ // Returns true is this object and all of its children can be removed.
+ virtual BOOL isRemovable();
+
+ // Returns true is this object and all of its children can be moved
+ virtual BOOL isMovable();
+
+ // destroys this folder, and all children
+ virtual void destroyView();
+
+ // If this folder can be removed, remove all children that can be
+ // removed, return TRUE if this is empty after the operation and
+ // it's viewed folder object can be removed.
+ //virtual BOOL removeRecursively(BOOL single_item);
+ //virtual BOOL remove();
+
+ // remove the specified item (and any children) if
+ // possible. Return TRUE if the item was deleted.
+ BOOL removeItem(LLFolderViewItem* item);
+
+ // simply remove the view (and any children) Don't bother telling
+ // the listeners.
+ void removeView(LLFolderViewItem* item);
+
+ // extractItem() removes the specified item from the folder, but
+ // doesn't delete it.
+ void extractItem( LLFolderViewItem* item );
+
+ // This function is called by a child that needs to be resorted.
+ void resort(LLFolderViewItem* item);
+
+ void setItemSortOrder(U32 ordering);
+ void sortBy(U32);
+ //BOOL (*func)(LLFolderViewItem* a, LLFolderViewItem* b));
+
+ void setAutoOpenCountdown(F32 countdown) { mAutoOpenCountdown = countdown; }
+
+ // folders can be opened. This will usually be called by internal
+ // methods.
+ virtual void toggleOpen();
+
+ // Force a folder open or closed
+ virtual void setOpen(BOOL openitem = TRUE);
+
+ // Called when a child is refreshed.
+ // don't rearrange child folder contents unless explicitly requested
+ virtual void requestArrange(BOOL include_descendants = FALSE);
+
+ // internal method which doesn't update the entire view. This
+ // method was written because the list iterators destroy the state
+ // of other iterations, thus, we can't arrange while iterating
+ // through the children (such as when setting which is selected.
+ virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse = RECURSE_NO);
+
+ // Get the current state of the folder.
+ virtual BOOL isOpen() const { return mIsOpen; }
+
+ // special case if an object is dropped on the child.
+ BOOL handleDragAndDropFromChild(MASK mask,
+ BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg);
+
+ void applyFunctorRecursively(LLFolderViewFunctor& functor);
+ virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor);
+
+ // Just apply this functor to the folder's immediate children.
+ void applyFunctorToChildren(LLFolderViewFunctor& functor);
+
+ virtual void openItem( void );
+ virtual BOOL addItem(LLFolderViewItem* item);
+ virtual BOOL addFolder( LLFolderViewFolder* folder);
+
+ // LLView functionality
+ virtual BOOL handleHover(S32 x, S32 y, MASK mask);
+ virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
+ virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );
+ virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask );
+ virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg);
+ virtual void draw();
+
+ time_t getCreationDate() const;
+ bool isTrash() const;
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLFolderViewListenerFunctor
+//
+// This simple abstract base class can be used to applied to all
+// listeners in a hierarchy.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLFolderViewListenerFunctor
+{
+public:
+ virtual ~LLFolderViewListenerFunctor() {}
+ virtual void operator()(LLFolderViewEventListener* listener) = 0;
+};
+
+#endif // LLFOLDERVIEWITEM_H
diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp
new file mode 100644
index 0000000000..ac060cef15
--- /dev/null
+++ b/indra/newview/llfriendcard.cpp
@@ -0,0 +1,609 @@
+/**
+ * @file llfriendcard.cpp
+ * @brief Implementation of classes to process Friends Cards
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llinventory.h"
+#include "llinventoryobserver.h"
+#include "lltrans.h"
+
+#include "llfriendcard.h"
+
+#include "llcallingcard.h" // for LLAvatarTracker
+#include "llviewerinventory.h"
+#include "llinventorymodel.h"
+
+// Constants;
+
+static const std::string INVENTORY_STRING_FRIENDS_SUBFOLDER = "InvFolder Friends";
+static const std::string INVENTORY_STRING_FRIENDS_ALL_SUBFOLDER = "InvFolder All";
+
+// helper functions
+
+// NOTE: Usage of LLTrans::getString(); in next two functions to set localized
+// folders' names is caused by a hack in the LLFolderViewItem::refreshFromListener()
+// method for protected asset types.
+// So, localized names will be got from the strings with "InvFolder LABEL_NAME"
+// in the strings.xml
+inline const std::string get_friend_folder_name()
+{
+ return LLTrans::getString(INVENTORY_STRING_FRIENDS_SUBFOLDER);
+}
+
+inline const std::string get_friend_all_subfolder_name()
+{
+ return LLTrans::getString(INVENTORY_STRING_FRIENDS_ALL_SUBFOLDER);
+}
+
+void move_from_to_arrays(LLInventoryModel::cat_array_t& from, LLInventoryModel::cat_array_t& to)
+{
+ while (from.count() > 0)
+ {
+ to.put(from.get(0));
+ from.remove(0);
+ }
+}
+
+const LLUUID& get_folder_uuid(const LLUUID& parentFolderUUID, LLInventoryCollectFunctor& matchFunctor)
+{
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+
+ gInventory.collectDescendentsIf(parentFolderUUID, cats, items,
+ LLInventoryModel::EXCLUDE_TRASH, matchFunctor);
+
+ S32 cats_count = cats.count();
+
+ if (cats_count > 1)
+ {
+ LL_WARNS("LLFriendCardsManager")
+ << "There is more than one Friend card folder."
+ << "The first folder will be used."
+ << LL_ENDL;
+ }
+
+ return (cats_count >= 1) ? cats.get(0)->getUUID() : LLUUID::null;
+}
+
+/**
+ * Class for fetching initial friend cards data
+ *
+ * Implemented to fix an issue when Inventory folders are in incomplete state.
+ * See EXT-2320, EXT-2061, EXT-1935, EXT-813.
+ * Uses a callback to sync Inventory Friends/All folder with agent's Friends List.
+ */
+class LLInitialFriendCardsFetch : public LLInventoryFetchDescendentsObserver
+{
+public:
+ typedef boost::function<void()> callback_t;
+
+ LLInitialFriendCardsFetch(callback_t cb)
+ : mCheckFolderCallback(cb) {}
+
+ /* virtual */ void done();
+
+private:
+ callback_t mCheckFolderCallback;
+};
+
+void LLInitialFriendCardsFetch::done()
+{
+ // This observer is no longer needed.
+ gInventory.removeObserver(this);
+
+ mCheckFolderCallback();
+
+ delete this;
+}
+
+// LLFriendCardsManager Constructor / Destructor
+LLFriendCardsManager::LLFriendCardsManager()
+{
+ LLAvatarTracker::instance().addObserver(this);
+}
+
+LLFriendCardsManager::~LLFriendCardsManager()
+{
+ LLAvatarTracker::instance().removeObserver(this);
+}
+
+void LLFriendCardsManager::putAvatarData(const LLUUID& avatarID)
+{
+ llinfos << "Store avatar data, avatarID: " << avatarID << llendl;
+ std::pair< avatar_uuid_set_t::iterator, bool > pr;
+ pr = mBuddyIDSet.insert(avatarID);
+ if (pr.second == false)
+ {
+ llwarns << "Trying to add avatar UUID for the stored avatar: "
+ << avatarID
+ << llendl;
+ }
+}
+
+const LLUUID LLFriendCardsManager::extractAvatarID(const LLUUID& avatarID)
+{
+ LLUUID rv;
+ avatar_uuid_set_t::iterator it = mBuddyIDSet.find(avatarID);
+ if (mBuddyIDSet.end() == it)
+ {
+ llwarns << "Call method for non-existent avatar name in the map: " << avatarID << llendl;
+ }
+ else
+ {
+ rv = (*it);
+ mBuddyIDSet.erase(it);
+ }
+ return rv;
+}
+
+bool LLFriendCardsManager::isItemInAnyFriendsList(const LLViewerInventoryItem* item)
+{
+ if (item->getType() != LLAssetType::AT_CALLINGCARD)
+ return false;
+
+ LLInventoryModel::item_array_t items;
+ findMatchedFriendCards(item->getCreatorUUID(), items);
+
+ return items.count() > 0;
+}
+
+
+bool LLFriendCardsManager::isObjDirectDescendentOfCategory(const LLInventoryObject* obj,
+ const LLViewerInventoryCategory* cat) const
+{
+ // we need both params to proceed.
+ if ( !obj || !cat )
+ return false;
+
+ // Need to check that target category is in the Calling Card/Friends folder.
+ // In other case function returns unpredictable result.
+ if ( !isCategoryInFriendFolder(cat) )
+ return false;
+
+ bool result = false;
+
+ LLInventoryModel::item_array_t* items;
+ LLInventoryModel::cat_array_t* cats;
+
+ gInventory.lockDirectDescendentArrays(cat->getUUID(), cats, items);
+ if ( items )
+ {
+ if ( obj->getType() == LLAssetType::AT_CALLINGCARD )
+ {
+ // For CALLINGCARD compare items by creator's id, if they are equal assume
+ // that it is same card and return true. Note: UUID's of compared items
+ // may be not equal. Also, we already know that obj should be type of LLInventoryItem,
+ // but in case inventory database is broken check what dynamic_cast returns.
+ const LLInventoryItem* item = dynamic_cast < const LLInventoryItem* > (obj);
+ if ( item )
+ {
+ LLUUID creator_id = item->getCreatorUUID();
+ LLViewerInventoryItem* cur_item = NULL;
+ for ( S32 i = items->count() - 1; i >= 0; --i )
+ {
+ cur_item = items->get(i);
+ if ( creator_id == cur_item->getCreatorUUID() )
+ {
+ result = true;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ // Else check that items have same type and name.
+ // Note: UUID's of compared items also may be not equal.
+ std::string obj_name = obj->getName();
+ LLViewerInventoryItem* cur_item = NULL;
+ for ( S32 i = items->count() - 1; i >= 0; --i )
+ {
+ cur_item = items->get(i);
+ if ( obj->getType() != cur_item->getType() )
+ continue;
+ if ( obj_name == cur_item->getName() )
+ {
+ result = true;
+ break;
+ }
+ }
+ }
+ }
+ if ( !result && cats )
+ {
+ // There is no direct descendent in items, so check categories.
+ // If target obj and descendent category have same type and name
+ // then return true. Note: UUID's of compared items also may be not equal.
+ std::string obj_name = obj->getName();
+ LLViewerInventoryCategory* cur_cat = NULL;
+ for ( S32 i = cats->count() - 1; i >= 0; --i )
+ {
+ cur_cat = cats->get(i);
+ if ( obj->getType() != cur_cat->getType() )
+ continue;
+ if ( obj_name == cur_cat->getName() )
+ {
+ result = true;
+ break;
+ }
+ }
+ }
+ gInventory.unlockDirectDescendentArrays(cat->getUUID());
+
+ return result;
+}
+
+
+bool LLFriendCardsManager::isCategoryInFriendFolder(const LLViewerInventoryCategory* cat) const
+{
+ if (NULL == cat)
+ return false;
+ return TRUE == gInventory.isObjectDescendentOf(cat->getUUID(), findFriendFolderUUIDImpl());
+}
+
+bool LLFriendCardsManager::isAnyFriendCategory(const LLUUID& catID) const
+{
+ const LLUUID& friendFolderID = findFriendFolderUUIDImpl();
+ if (catID == friendFolderID)
+ return true;
+
+ return TRUE == gInventory.isObjectDescendentOf(catID, friendFolderID);
+}
+
+void LLFriendCardsManager::syncFriendCardsFolders()
+{
+ const LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD);
+
+ fetchAndCheckFolderDescendents(callingCardsFolderID,
+ boost::bind(&LLFriendCardsManager::ensureFriendsFolderExists, this));
+}
+
+void LLFriendCardsManager::collectFriendsLists(folderid_buddies_map_t& folderBuddiesMap) const
+{
+ folderBuddiesMap.clear();
+
+ LLInventoryModel::cat_array_t* listFolders;
+ LLInventoryModel::item_array_t* items;
+
+ // get folders in the Friend folder. Items should be NULL due to Cards should be in lists.
+ gInventory.getDirectDescendentsOf(findFriendFolderUUIDImpl(), listFolders, items);
+
+ if (NULL == listFolders)
+ return;
+
+ LLInventoryModel::cat_array_t::const_iterator itCats; // to iterate Friend Lists (categories)
+ LLInventoryModel::item_array_t::const_iterator itBuddy; // to iterate Buddies in each List
+ LLInventoryModel::cat_array_t* fakeCatsArg;
+ for (itCats = listFolders->begin(); itCats != listFolders->end(); ++itCats)
+ {
+ if (items)
+ items->clear();
+
+ // *HACK: Only Friends/All content will be shown for now
+ // *TODO: Remove this hack, implement sorting if it will be needded by spec.
+ if ((*itCats)->getUUID() != findFriendAllSubfolderUUIDImpl())
+ continue;
+
+ gInventory.getDirectDescendentsOf((*itCats)->getUUID(), fakeCatsArg, items);
+
+ if (NULL == items)
+ continue;
+
+ std::vector<LLUUID> buddyUUIDs;
+ for (itBuddy = items->begin(); itBuddy != items->end(); ++itBuddy)
+ {
+ buddyUUIDs.push_back((*itBuddy)->getCreatorUUID());
+ }
+
+ folderBuddiesMap.insert(make_pair((*itCats)->getUUID(), buddyUUIDs));
+ }
+}
+
+
+/************************************************************************/
+/* Private Methods */
+/************************************************************************/
+const LLUUID& LLFriendCardsManager::findFriendFolderUUIDImpl() const
+{
+ const LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD);
+
+ std::string friendFolderName = get_friend_folder_name();
+
+ return findChildFolderUUID(callingCardsFolderID, friendFolderName);
+}
+
+const LLUUID& LLFriendCardsManager::findFriendAllSubfolderUUIDImpl() const
+{
+ LLUUID friendFolderUUID = findFriendFolderUUIDImpl();
+
+ std::string friendAllSubfolderName = get_friend_all_subfolder_name();
+
+ return findChildFolderUUID(friendFolderUUID, friendAllSubfolderName);
+}
+
+const LLUUID& LLFriendCardsManager::findChildFolderUUID(const LLUUID& parentFolderUUID, const std::string& localizedName) const
+{
+ LLNameCategoryCollector matchFolderFunctor(localizedName);
+
+ return get_folder_uuid(parentFolderUUID, matchFolderFunctor);
+}
+const LLUUID& LLFriendCardsManager::findFriendCardInventoryUUIDImpl(const LLUUID& avatarID)
+{
+ LLUUID friendAllSubfolderUUID = findFriendAllSubfolderUUIDImpl();
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ LLInventoryModel::item_array_t::const_iterator it;
+
+ // it is not necessary to check friendAllSubfolderUUID against NULL. It will be processed by collectDescendents
+ gInventory.collectDescendents(friendAllSubfolderUUID, cats, items, LLInventoryModel::EXCLUDE_TRASH);
+ for (it = items.begin(); it != items.end(); ++it)
+ {
+ if ((*it)->getCreatorUUID() == avatarID)
+ return (*it)->getUUID();
+ }
+
+ return LLUUID::null;
+}
+
+void LLFriendCardsManager::findMatchedFriendCards(const LLUUID& avatarID, LLInventoryModel::item_array_t& items) const
+{
+ LLInventoryModel::cat_array_t cats;
+ LLUUID friendFolderUUID = findFriendFolderUUIDImpl();
+
+
+ LLViewerInventoryCategory* friendFolder = gInventory.getCategory(friendFolderUUID);
+ if (NULL == friendFolder)
+ return;
+
+ LLParticularBuddyCollector matchFunctor(avatarID);
+ LLInventoryModel::cat_array_t subFolders;
+ subFolders.push_back(friendFolder);
+
+ while (subFolders.count() > 0)
+ {
+ LLViewerInventoryCategory* cat = subFolders.get(0);
+ subFolders.remove(0);
+
+ gInventory.collectDescendentsIf(cat->getUUID(), cats, items,
+ LLInventoryModel::EXCLUDE_TRASH, matchFunctor);
+
+ move_from_to_arrays(cats, subFolders);
+ }
+}
+
+void LLFriendCardsManager::fetchAndCheckFolderDescendents(const LLUUID& folder_id, callback_t cb)
+{
+ // This instance will be deleted in LLInitialFriendCardsFetch::done().
+ LLInitialFriendCardsFetch* fetch = new LLInitialFriendCardsFetch(cb);
+
+ LLInventoryFetchDescendentsObserver::folder_ref_t folders;
+ folders.push_back(folder_id);
+
+ fetch->fetchDescendents(folders);
+ if(fetch->isEverythingComplete())
+ {
+ // everything is already here - call done.
+ fetch->done();
+ }
+ else
+ {
+ // it's all on it's way - add an observer, and the inventory
+ // will call done for us when everything is here.
+ gInventory.addObserver(fetch);
+ }
+}
+
+// Make sure LLInventoryModel::buildParentChildMap() has been called before it.
+// This method must be called before any actions with friends list.
+void LLFriendCardsManager::ensureFriendsFolderExists()
+{
+ const LLUUID calling_cards_folder_ID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD);
+
+ // If "Friends" folder exists in "Calling Cards" we should check if "All" sub-folder
+ // exists in "Friends", otherwise we create it.
+ LLUUID friends_folder_ID = findFriendFolderUUIDImpl();
+ if (friends_folder_ID.notNull())
+ {
+ fetchAndCheckFolderDescendents(friends_folder_ID,
+ boost::bind(&LLFriendCardsManager::ensureFriendsAllFolderExists, this));
+ }
+ else
+ {
+ if (!gInventory.isCategoryComplete(calling_cards_folder_ID))
+ {
+ LLViewerInventoryCategory* cat = gInventory.getCategory(calling_cards_folder_ID);
+ std::string cat_name = cat ? cat->getName() : "unknown";
+ llwarns << "Failed to find \"" << cat_name << "\" category descendents in Category Tree." << llendl;
+ }
+
+ friends_folder_ID = gInventory.createNewCategory(calling_cards_folder_ID,
+ LLFolderType::FT_CALLINGCARD, get_friend_folder_name());
+
+ gInventory.createNewCategory(friends_folder_ID,
+ LLFolderType::FT_CALLINGCARD, get_friend_all_subfolder_name());
+
+ // Now when we have all needed folders we can sync their contents with buddies list.
+ syncFriendsFolder();
+ }
+}
+
+// Make sure LLFriendCardsManager::ensureFriendsFolderExists() has been called before it.
+void LLFriendCardsManager::ensureFriendsAllFolderExists()
+{
+ LLUUID friends_all_folder_ID = findFriendAllSubfolderUUIDImpl();
+ if (friends_all_folder_ID.notNull())
+ {
+ fetchAndCheckFolderDescendents(friends_all_folder_ID,
+ boost::bind(&LLFriendCardsManager::syncFriendsFolder, this));
+ }
+ else
+ {
+ LLUUID friends_folder_ID = findFriendFolderUUIDImpl();
+
+ if (!gInventory.isCategoryComplete(friends_folder_ID))
+ {
+ LLViewerInventoryCategory* cat = gInventory.getCategory(friends_folder_ID);
+ std::string cat_name = cat ? cat->getName() : "unknown";
+ llwarns << "Failed to find \"" << cat_name << "\" category descendents in Category Tree." << llendl;
+ }
+
+ friends_all_folder_ID = gInventory.createNewCategory(friends_folder_ID,
+ LLFolderType::FT_CALLINGCARD, get_friend_all_subfolder_name());
+
+ // Now when we have all needed folders we can sync their contents with buddies list.
+ syncFriendsFolder();
+ }
+}
+
+void LLFriendCardsManager::syncFriendsFolder()
+{
+ LLAvatarTracker::buddy_map_t all_buddies;
+ LLAvatarTracker::instance().copyBuddyList(all_buddies);
+
+ // 1. Remove Friend Cards for non-friends
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+
+ gInventory.collectDescendents(findFriendAllSubfolderUUIDImpl(), cats, items, LLInventoryModel::EXCLUDE_TRASH);
+
+ LLInventoryModel::item_array_t::const_iterator it;
+ for (it = items.begin(); it != items.end(); ++it)
+ {
+ lldebugs << "Check if buddy is in list: " << (*it)->getName() << " " << (*it)->getCreatorUUID() << llendl;
+ if (NULL == get_ptr_in_map(all_buddies, (*it)->getCreatorUUID()))
+ {
+ lldebugs << "NONEXISTS, so remove it" << llendl;
+ removeFriendCardFromInventory((*it)->getCreatorUUID());
+ }
+ }
+
+ // 2. Add missing Friend Cards for friends
+ LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin();
+ llinfos << "try to build friends, count: " << all_buddies.size() << llendl;
+ for(; buddy_it != all_buddies.end(); ++buddy_it)
+ {
+ const LLUUID& buddy_id = (*buddy_it).first;
+ addFriendCardToInventory(buddy_id);
+ }
+}
+
+class CreateFriendCardCallback : public LLInventoryCallback
+{
+public:
+ void fire(const LLUUID& inv_item_id)
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(inv_item_id);
+
+ if (item)
+ LLFriendCardsManager::instance().extractAvatarID(item->getCreatorUUID());
+ }
+};
+
+void LLFriendCardsManager::addFriendCardToInventory(const LLUUID& avatarID)
+{
+
+ bool shouldBeAdded = true;
+ std::string name;
+ gCacheName->getFullName(avatarID, name);
+
+ lldebugs << "Processing buddy name: " << name
+ << ", id: " << avatarID
+ << llendl;
+
+ if (shouldBeAdded && findFriendCardInventoryUUIDImpl(avatarID).notNull())
+ {
+ shouldBeAdded = false;
+ lldebugs << "is found in Inventory: " << name << llendl;
+ }
+
+ if (shouldBeAdded && isAvatarDataStored(avatarID))
+ {
+ shouldBeAdded = false;
+ lldebugs << "is found in sentRequests: " << name << llendl;
+ }
+
+ if (shouldBeAdded)
+ {
+ putAvatarData(avatarID);
+ lldebugs << "Sent create_inventory_item for " << avatarID << ", " << name << llendl;
+
+ // TODO: mantipov: Is CreateFriendCardCallback really needed? Probably not
+ LLPointer<LLInventoryCallback> cb = new CreateFriendCardCallback();
+
+ create_inventory_callingcard(avatarID, findFriendAllSubfolderUUIDImpl(), cb);
+ }
+}
+
+void LLFriendCardsManager::removeFriendCardFromInventory(const LLUUID& avatarID)
+{
+ LLInventoryModel::item_array_t items;
+ findMatchedFriendCards(avatarID, items);
+
+ LLInventoryModel::item_array_t::const_iterator it;
+ for (it = items.begin(); it != items.end(); ++ it)
+ {
+ gInventory.removeItem((*it)->getUUID());
+ }
+}
+
+void LLFriendCardsManager::onFriendListUpdate(U32 changed_mask)
+{
+ LLAvatarTracker& at = LLAvatarTracker::instance();
+
+ switch(changed_mask) {
+ case LLFriendObserver::ADD:
+ {
+ const std::set<LLUUID>& changed_items = at.getChangedIDs();
+ std::set<LLUUID>::const_iterator id_it = changed_items.begin();
+ std::set<LLUUID>::const_iterator id_end = changed_items.end();
+ for (;id_it != id_end; ++id_it)
+ {
+ LLFriendCardsManager::instance().addFriendCardToInventory(*id_it);
+ }
+ }
+ break;
+ case LLFriendObserver::REMOVE:
+ {
+ const std::set<LLUUID>& changed_items = at.getChangedIDs();
+ std::set<LLUUID>::const_iterator id_it = changed_items.begin();
+ std::set<LLUUID>::const_iterator id_end = changed_items.end();
+ for (;id_it != id_end; ++id_it)
+ {
+ LLFriendCardsManager::instance().removeFriendCardFromInventory(*id_it);
+ }
+ }
+
+ default:;
+ }
+}
+
+// EOF
diff --git a/indra/newview/llfriendcard.h b/indra/newview/llfriendcard.h
new file mode 100644
index 0000000000..b94d5ec2c0
--- /dev/null
+++ b/indra/newview/llfriendcard.h
@@ -0,0 +1,168 @@
+/**
+ * @file llfriendcard.h
+ * @brief Definition of classes to process Friends Cards
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFRIENDCARD_H
+#define LL_LLFRIENDCARD_H
+
+
+#include "llcallingcard.h"
+#include "llinventorymodel.h" // for LLInventoryModel::item_array_t
+
+class LLViewerInventoryItem;
+
+class LLFriendCardsManager
+ : public LLSingleton<LLFriendCardsManager>
+ , public LLFriendObserver
+{
+ LOG_CLASS(LLFriendCardsManager);
+
+ friend class LLSingleton<LLFriendCardsManager>;
+ friend class CreateFriendCardCallback;
+
+public:
+ typedef std::map<LLUUID, std::vector<LLUUID> > folderid_buddies_map_t;
+
+ // LLFriendObserver implementation
+ void changed(U32 mask)
+ {
+ onFriendListUpdate(mask);
+ }
+
+ /**
+ * Determines if specified Inventory Calling Card exists in any of lists
+ * in the Calling Card/Friends/ folder (Default, or Custom)
+ */
+ bool isItemInAnyFriendsList(const LLViewerInventoryItem* item);
+
+ /**
+ * Checks if specified category is contained in the Calling Card/Friends folder and
+ * determines if specified Inventory Object exists in that category.
+ */
+ bool isObjDirectDescendentOfCategory(const LLInventoryObject* obj, const LLViewerInventoryCategory* cat) const;
+
+ /**
+ * Checks is the specified category is in the Calling Card/Friends folder
+ */
+ bool isCategoryInFriendFolder(const LLViewerInventoryCategory* cat) const;
+
+ /**
+ * Checks is the specified category is a Friend folder or any its subfolder
+ */
+ bool isAnyFriendCategory(const LLUUID& catID) const;
+
+ /**
+ * Checks whether "Friends" and "Friends/All" folders exist in "Calling Cards" category
+ * (creates them otherwise) and fetches their contents to synchronize with Agent's Friends List.
+ */
+ void syncFriendCardsFolders();
+
+ /*!
+ * \brief
+ * Collects folders' IDs with the buddies' IDs in the Inventory Calling Card/Friends folder.
+ *
+ * \param folderBuddiesMap
+ * map into collected data will be put. It will be cleared before adding new data.
+ *
+ * Each item in the out map is a pair where first is an LLViewerInventoryCategory UUID,
+ * second is a vector with UUID of Avatars from this folder.
+ *
+ */
+ void collectFriendsLists(folderid_buddies_map_t& folderBuddiesMap) const;
+
+private:
+ typedef boost::function<void()> callback_t;
+
+ LLFriendCardsManager();
+ ~LLFriendCardsManager();
+
+
+ /**
+ * Stores buddy id to avoid sent create_inventory_callingcard several time for the same Avatar
+ */
+ void putAvatarData(const LLUUID& avatarID);
+
+ /**
+ * Extracts buddy id of Created Friend Card
+ */
+ const LLUUID extractAvatarID(const LLUUID& avatarID);
+
+ bool isAvatarDataStored(const LLUUID& avatarID) const
+ {
+ return (mBuddyIDSet.end() != mBuddyIDSet.find(avatarID));
+ }
+
+ const LLUUID& findChildFolderUUID(const LLUUID& parentFolderUUID, const std::string& localizedName) const;
+ const LLUUID& findFriendFolderUUIDImpl() const;
+ const LLUUID& findFriendAllSubfolderUUIDImpl() const;
+ const LLUUID& findFriendCardInventoryUUIDImpl(const LLUUID& avatarID);
+ void findMatchedFriendCards(const LLUUID& avatarID, LLInventoryModel::item_array_t& items) const;
+
+ void fetchAndCheckFolderDescendents(const LLUUID& folder_id, callback_t cb);
+
+ /**
+ * Checks whether "Calling Cards/Friends" folder exists. If not, creates it with "All"
+ * sub-folder and synchronizes its contents with buddies list.
+ */
+ void ensureFriendsFolderExists();
+
+ /**
+ * Checks whether "Calling Cards/Friends/All" folder exists. If not, creates it and
+ * synchronizes its contents with buddies list.
+ */
+ void ensureFriendsAllFolderExists();
+
+ /**
+ * Synchronizes content of the Calling Card/Friends/All Global Inventory folder with Agent's Friend List
+ */
+ void syncFriendsFolder();
+
+ /**
+ * Adds avatar specified by its UUID into the Calling Card/Friends/All Global Inventory folder
+ */
+ void addFriendCardToInventory(const LLUUID& avatarID);
+
+ /**
+ * Removes an avatar specified by its UUID from the Calling Card/Friends/All Global Inventory folder
+ * and from the all Custom Folders
+ */
+ void removeFriendCardFromInventory(const LLUUID& avatarID);
+
+ void onFriendListUpdate(U32 changed_mask);
+
+
+private:
+ typedef std::set<LLUUID> avatar_uuid_set_t;
+
+ avatar_uuid_set_t mBuddyIDSet;
+};
+
+#endif // LL_LLFRIENDCARD_H
diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp
index 2dbff92ba0..0ba7bdf613 100644
--- a/indra/newview/llgesturemgr.cpp
+++ b/indra/newview/llgesturemgr.cpp
@@ -37,12 +37,12 @@
// system
#include <functional>
#include <algorithm>
-#include <boost/tokenizer.hpp>
// library
#include "lldatapacker.h"
#include "llinventory.h"
#include "llmultigesture.h"
+#include "llnotificationsutil.h"
#include "llstl.h"
#include "llstring.h" // todo: remove
#include "llvfile.h"
@@ -50,19 +50,20 @@
// newview
#include "llagent.h"
-#include "llchatbar.h"
#include "lldelayedgestureerror.h"
#include "llinventorymodel.h"
-#include "llnotify.h"
#include "llviewermessage.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "llviewerstats.h"
-
-LLGestureManager gGestureManager;
+#include "llnearbychatbar.h"
+#include "llappearancemgr.h"
// Longest time, in seconds, to wait for all animations to stop playing
const F32 MAX_WAIT_ANIM_SECS = 30.f;
+// If this gesture is a link, get the base gesture that this link points to,
+// otherwise just return this id.
+static const LLUUID& get_linked_uuid(const LLUUID& item_id);
// Lightweight constructor.
// init() does the heavy lifting.
@@ -71,7 +72,10 @@ LLGestureManager::LLGestureManager()
mPlaying(),
mActive(),
mLoadingCount(0)
-{ }
+{
+ mRetryIfMissing = true;
+ gInventory.addObserver(this);
+}
// We own the data for gestures, so clean them up.
@@ -85,6 +89,7 @@ LLGestureManager::~LLGestureManager()
delete gesture;
gesture = NULL;
}
+ gInventory.removeObserver(this);
}
@@ -93,6 +98,41 @@ void LLGestureManager::init()
// TODO
}
+void LLGestureManager::changed(U32 mask)
+{
+ LLInventoryFetchObserver::changed(mask);
+
+ if (mask & LLInventoryObserver::GESTURE)
+ {
+ // If there was a gesture label changed, update all the names in the
+ // active gestures and then notify observers
+ if (mask & LLInventoryObserver::LABEL)
+ {
+ for(item_map_t::iterator it = mActive.begin(); it != mActive.end(); ++it)
+ {
+ if(it->second)
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(it->first);
+ if(item)
+ {
+ it->second->mName = item->getName();
+ }
+ }
+ }
+ notifyObservers();
+ }
+ // If there was a gesture added or removed notify observers
+ // STRUCTURE denotes that the inventory item has been moved
+ // In the case of deleting gesture, it is moved to the trash
+ else if(mask & LLInventoryObserver::ADD ||
+ mask & LLInventoryObserver::REMOVE ||
+ mask & LLInventoryObserver::STRUCTURE)
+ {
+ notifyObservers();
+ }
+ }
+}
+
// Use this version when you have the item_id but not the asset_id,
// and you KNOW the inventory is loaded.
@@ -205,11 +245,16 @@ struct LLLoadInfo
// If inform_server is true, will send a message upstream to update
// the user_gesture_active table.
+/**
+ * It will load a gesture from remote storage
+ */
void LLGestureManager::activateGestureWithAsset(const LLUUID& item_id,
const LLUUID& asset_id,
BOOL inform_server,
BOOL deactivate_similar)
{
+ const LLUUID& base_item_id = get_linked_uuid(item_id);
+
if( !gAssetStorage )
{
llwarns << "LLGestureManager::activateGestureWithAsset without valid gAssetStorage" << llendl;
@@ -230,13 +275,13 @@ void LLGestureManager::activateGestureWithAsset(const LLUUID& item_id,
// For now, put NULL into the item map. We'll build a gesture
// class object when the asset data arrives.
- mActive[item_id] = NULL;
+ mActive[base_item_id] = NULL;
// Copy the UUID
if (asset_id.notNull())
{
LLLoadInfo* info = new LLLoadInfo;
- info->mItemID = item_id;
+ info->mItemID = base_item_id;
info->mInformServer = inform_server;
info->mDeactivateSimilar = deactivate_similar;
@@ -256,7 +301,8 @@ void LLGestureManager::activateGestureWithAsset(const LLUUID& item_id,
void LLGestureManager::deactivateGesture(const LLUUID& item_id)
{
- item_map_t::iterator it = mActive.find(item_id);
+ const LLUUID& base_item_id = get_linked_uuid(item_id);
+ item_map_t::iterator it = mActive.find(base_item_id);
if (it == mActive.end())
{
llwarns << "deactivateGesture for inactive gesture " << item_id << llendl;
@@ -276,7 +322,7 @@ void LLGestureManager::deactivateGesture(const LLUUID& item_id)
}
mActive.erase(it);
- gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, base_item_id);
// Inform the database of this change
LLMessageSystem* msg = gMessageSystem;
@@ -292,12 +338,15 @@ void LLGestureManager::deactivateGesture(const LLUUID& item_id)
gAgent.sendReliableMessage();
+ LLAppearanceManager::instance().removeCOFItemLinks(base_item_id, false);
+
notifyObservers();
}
void LLGestureManager::deactivateSimilarGestures(LLMultiGesture* in, const LLUUID& in_item_id)
{
+ const LLUUID& base_in_item_id = get_linked_uuid(in_item_id);
std::vector<LLUUID> gest_item_ids;
// Deactivate all gestures that match
@@ -309,7 +358,7 @@ void LLGestureManager::deactivateSimilarGestures(LLMultiGesture* in, const LLUUI
// Don't deactivate the gesture we are looking for duplicates of
// (for replaceGesture)
- if (!gest || item_id == in_item_id)
+ if (!gest || item_id == base_in_item_id)
{
// legal, can have null pointers in list
++it;
@@ -384,14 +433,17 @@ void LLGestureManager::deactivateSimilarGestures(LLMultiGesture* in, const LLUUI
BOOL LLGestureManager::isGestureActive(const LLUUID& item_id)
{
- item_map_t::iterator it = mActive.find(item_id);
+ const LLUUID& base_item_id = get_linked_uuid(item_id);
+ item_map_t::iterator it = mActive.find(base_item_id);
return (it != mActive.end());
}
BOOL LLGestureManager::isGesturePlaying(const LLUUID& item_id)
{
- item_map_t::iterator it = mActive.find(item_id);
+ const LLUUID& base_item_id = get_linked_uuid(item_id);
+
+ item_map_t::iterator it = mActive.find(base_item_id);
if (it == mActive.end()) return FALSE;
LLMultiGesture* gesture = (*it).second;
@@ -400,21 +452,33 @@ BOOL LLGestureManager::isGesturePlaying(const LLUUID& item_id)
return gesture->mPlaying;
}
+BOOL LLGestureManager::isGesturePlaying(LLMultiGesture* gesture)
+{
+ if(!gesture)
+ {
+ return FALSE;
+ }
+
+ return gesture->mPlaying;
+}
+
void LLGestureManager::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_gesture, const LLUUID& asset_id)
{
- item_map_t::iterator it = mActive.find(item_id);
+ const LLUUID& base_item_id = get_linked_uuid(item_id);
+
+ item_map_t::iterator it = mActive.find(base_item_id);
if (it == mActive.end())
{
- llwarns << "replaceGesture for inactive gesture " << item_id << llendl;
+ llwarns << "replaceGesture for inactive gesture " << base_item_id << llendl;
return;
}
LLMultiGesture* old_gesture = (*it).second;
stopGesture(old_gesture);
- mActive.erase(item_id);
+ mActive.erase(base_item_id);
- mActive[item_id] = new_gesture;
+ mActive[base_item_id] = new_gesture;
delete old_gesture;
old_gesture = NULL;
@@ -425,7 +489,7 @@ void LLGestureManager::replaceGesture(const LLUUID& item_id, LLMultiGesture* new
mDeactivateSimilarNames.clear();
LLLoadInfo* info = new LLLoadInfo;
- info->mItemID = item_id;
+ info->mItemID = base_item_id;
info->mInformServer = TRUE;
info->mDeactivateSimilar = FALSE;
@@ -442,16 +506,18 @@ void LLGestureManager::replaceGesture(const LLUUID& item_id, LLMultiGesture* new
void LLGestureManager::replaceGesture(const LLUUID& item_id, const LLUUID& new_asset_id)
{
- item_map_t::iterator it = gGestureManager.mActive.find(item_id);
+ const LLUUID& base_item_id = get_linked_uuid(item_id);
+
+ item_map_t::iterator it = LLGestureManager::instance().mActive.find(base_item_id);
if (it == mActive.end())
{
- llwarns << "replaceGesture for inactive gesture " << item_id << llendl;
+ llwarns << "replaceGesture for inactive gesture " << base_item_id << llendl;
return;
}
// mActive owns this gesture pointer, so clean up memory.
LLMultiGesture* gesture = (*it).second;
- gGestureManager.replaceGesture(item_id, gesture, new_asset_id);
+ LLGestureManager::instance().replaceGesture(base_item_id, gesture, new_asset_id);
}
void LLGestureManager::playGesture(LLMultiGesture* gesture)
@@ -475,7 +541,9 @@ void LLGestureManager::playGesture(LLMultiGesture* gesture)
// Convenience function that looks up the item_id for you.
void LLGestureManager::playGesture(const LLUUID& item_id)
{
- item_map_t::iterator it = mActive.find(item_id);
+ const LLUUID& base_item_id = get_linked_uuid(item_id);
+
+ item_map_t::iterator it = mActive.find(base_item_id);
if (it == mActive.end()) return;
LLMultiGesture* gesture = (*it).second;
@@ -868,9 +936,11 @@ void LLGestureManager::runStep(LLMultiGesture* gesture, LLGestureStep* step)
std::string chat_text = chat_step->mChatText;
// Don't animate the nodding, as this might not blend with
// other playing animations.
+
const BOOL animate = FALSE;
- gChatBar->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate);
+ LLNearbyChatBar::getInstance()->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate);
+
gesture->mCurrentStep++;
break;
}
@@ -918,8 +988,8 @@ void LLGestureManager::onLoadComplete(LLVFS *vfs,
delete info;
info = NULL;
-
- gGestureManager.mLoadingCount--;
+ LLGestureManager& self = LLGestureManager::instance();
+ self.mLoadingCount--;
if (0 == status)
{
@@ -941,22 +1011,36 @@ void LLGestureManager::onLoadComplete(LLVFS *vfs,
{
if (deactivate_similar)
{
- gGestureManager.deactivateSimilarGestures(gesture, item_id);
+ self.deactivateSimilarGestures(gesture, item_id);
// Display deactivation message if this was the last of the bunch.
- if (gGestureManager.mLoadingCount == 0
- && gGestureManager.mDeactivateSimilarNames.length() > 0)
+ if (self.mLoadingCount == 0
+ && self.mDeactivateSimilarNames.length() > 0)
{
// we're done with this set of deactivations
LLSD args;
- args["NAMES"] = gGestureManager.mDeactivateSimilarNames;
- LLNotifications::instance().add("DeactivatedGesturesTrigger", args);
+ args["NAMES"] = self.mDeactivateSimilarNames;
+ LLNotificationsUtil::add("DeactivatedGesturesTrigger", args);
}
}
+ LLViewerInventoryItem* item = gInventory.getItem(item_id);
+ if(item)
+ {
+ gesture->mName = item->getName();
+ }
+ else
+ {
+ // Watch this item and set gesture name when item exists in inventory
+ item_ref_t ids;
+ ids.push_back(item_id);
+ self.fetchItems(ids);
+ }
+ self.mActive[item_id] = gesture;
+
// Everything has been successful. Add to the active list.
- gGestureManager.mActive[item_id] = gesture;
gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
+
if (inform_server)
{
// Inform the database of this change
@@ -974,14 +1058,21 @@ void LLGestureManager::onLoadComplete(LLVFS *vfs,
gAgent.sendReliableMessage();
}
+ callback_map_t::iterator i_cb = self.mCallbackMap.find(item_id);
+
+ if(i_cb != self.mCallbackMap.end())
+ {
+ i_cb->second(gesture);
+ self.mCallbackMap.erase(i_cb);
+ }
- gGestureManager.notifyObservers();
+ self.notifyObservers();
}
else
{
llwarns << "Unable to load gesture" << llendl;
- gGestureManager.mActive.erase(item_id);
+ self.mActive.erase(item_id);
delete gesture;
gesture = NULL;
@@ -1003,7 +1094,7 @@ void LLGestureManager::onLoadComplete(LLVFS *vfs,
llwarns << "Problem loading gesture: " << status << llendl;
- gGestureManager.mActive.erase(item_id);
+ LLGestureManager::instance().mActive.erase(item_id);
}
}
@@ -1050,7 +1141,9 @@ void LLGestureManager::stopGesture(LLMultiGesture* gesture)
void LLGestureManager::stopGesture(const LLUUID& item_id)
{
- item_map_t::iterator it = mActive.find(item_id);
+ const LLUUID& base_item_id = get_linked_uuid(item_id);
+
+ item_map_t::iterator it = mActive.find(base_item_id);
if (it == mActive.end()) return;
LLMultiGesture* gesture = (*it).second;
@@ -1131,3 +1224,36 @@ void LLGestureManager::getItemIDs(std::vector<LLUUID>* ids)
ids->push_back(it->first);
}
}
+
+void LLGestureManager::done()
+{
+ bool notify = false;
+ for(item_map_t::iterator it = mActive.begin(); it != mActive.end(); ++it)
+ {
+ if(it->second && it->second->mName.empty())
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(it->first);
+ if(item)
+ {
+ it->second->mName = item->getName();
+ notify = true;
+ }
+ }
+ }
+ if(notify)
+ {
+ notifyObservers();
+ }
+}
+
+// static
+const LLUUID& get_linked_uuid(const LLUUID &item_id)
+{
+ LLViewerInventoryItem* item = gInventory.getItem(item_id);
+ if (item && item->getIsLinkType())
+ {
+ return item->getLinkedUUID();
+ }
+ return item_id;
+}
+
diff --git a/indra/newview/llgesturemgr.h b/indra/newview/llgesturemgr.h
index f564c17486..3dd184ddc7 100644
--- a/indra/newview/llgesturemgr.h
+++ b/indra/newview/llgesturemgr.h
@@ -38,6 +38,8 @@
#include <vector>
#include "llassetstorage.h" // LLAssetType
+#include "llinventoryobserver.h"
+#include "llsingleton.h"
#include "llviewerinventory.h"
class LLMultiGesture;
@@ -52,9 +54,15 @@ public:
virtual void changed() = 0;
};
-class LLGestureManager
+class LLGestureManager : public LLSingleton<LLGestureManager>, public LLInventoryFetchObserver
{
public:
+
+ typedef boost::function<void (LLMultiGesture* loaded_gesture)> gesture_loaded_callback_t;
+ // Maps inventory item_id to gesture
+ typedef std::map<LLUUID, LLMultiGesture*> item_map_t;
+ typedef std::map<LLUUID, gesture_loaded_callback_t> callback_map_t;
+
LLGestureManager();
~LLGestureManager();
@@ -95,6 +103,9 @@ public:
BOOL isGesturePlaying(const LLUUID& item_id);
+ BOOL isGesturePlaying(LLMultiGesture* gesture);
+
+ const item_map_t& getActiveGestures() const { return mActive; }
// Force a gesture to be played, for example, if it is being
// previewed.
void playGesture(LLMultiGesture* gesture);
@@ -104,7 +115,15 @@ public:
// Also remove from playing list
void stopGesture(LLMultiGesture* gesture);
void stopGesture(const LLUUID& item_id);
-
+ /**
+ * Add cb into callbackMap.
+ * Note:
+ * Manager will call cb after gesture will be loaded and will remove cb automatically.
+ */
+ void setGestureLoadedCallback(LLUUID inv_item_id, gesture_loaded_callback_t cb)
+ {
+ mCallbackMap[inv_item_id] = cb;
+ }
// Trigger the first gesture that matches this key.
// Returns TRUE if it finds a gesture bound to that key.
BOOL triggerGesture(KEY key, MASK mask);
@@ -121,6 +140,9 @@ public:
void removeObserver(LLGestureManagerObserver* observer);
void notifyObservers();
+ // Overriding so we can update active gesture names and notify observers
+ void changed(U32 mask);
+
BOOL matchPrefix(const std::string& in_str, std::string* out_str);
// Copy item ids into the vector
@@ -133,19 +155,16 @@ protected:
// Do a single step in a gesture
void runStep(LLMultiGesture* gesture, LLGestureStep* step);
+ // LLInventoryCompletionObserver trigger
+ void done();
+
// Used by loadGesture
static void onLoadComplete(LLVFS *vfs,
const LLUUID& asset_uuid,
LLAssetType::EType type,
void* user_data, S32 status, LLExtStat ext_status);
-public:
- BOOL mValid;
- std::vector<LLMultiGesture*> mPlaying;
-
- // Maps inventory item_id to gesture
- typedef std::map<LLUUID, LLMultiGesture*> item_map_t;
-
+private:
// Active gestures.
// NOTE: The gesture pointer CAN BE NULL. This means that
// there is a gesture with that item_id, but the asset data
@@ -154,10 +173,11 @@ public:
S32 mLoadingCount;
std::string mDeactivateSimilarNames;
-
+
std::vector<LLGestureManagerObserver*> mObservers;
+ callback_map_t mCallbackMap;
+ std::vector<LLMultiGesture*> mPlaying;
+ BOOL mValid;
};
-extern LLGestureManager gGestureManager;
-
#endif
diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp
index 91beb801ad..750a9d478f 100644
--- a/indra/newview/llglsandbox.cpp
+++ b/indra/newview/llglsandbox.cpp
@@ -49,7 +49,7 @@
#include "lltextureentry.h"
#include "llviewercamera.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "llagent.h"
#include "lltoolmgr.h"
#include "llselectmgr.h"
@@ -58,7 +58,6 @@
#include "llviewerobjectlist.h"
#include "lltoolselectrect.h"
#include "llviewerwindow.h"
-#include "llcompass.h"
#include "llsurface.h"
#include "llwind.h"
#include "llworld.h"
@@ -68,7 +67,10 @@
#include "llresmgr.h"
#include "pipeline.h"
#include "llspatialpartition.h"
-
+
+// Height of the yellow selection highlight posts for land
+const F32 PARCEL_POST_HEIGHT = 0.666f;
+
BOOL LLAgent::setLookAt(ELookAtType target_type, LLViewerObject *object, LLVector3 position)
{
if(object && object->isAttachment())
@@ -162,8 +164,6 @@ void LLAgent::renderAutoPilotTarget()
}
}
-extern BOOL gDebugSelect;
-
// Returns true if you got at least one object
void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask)
{
@@ -338,127 +338,8 @@ void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask)
gViewerWindow->setup3DRender();
}
-
-const F32 COMPASS_SIZE = 64;
-static const F32 COMPASS_RANGE = 0.33f;
-
-void LLCompass::draw()
-{
- glMatrixMode(GL_MODELVIEW);
- gGL.pushMatrix();
-
- S32 width = 32;
- S32 height = 32;
-
- LLGLSUIDefault gls_ui;
-
- gGL.translatef( COMPASS_SIZE/2.f, COMPASS_SIZE/2.f, 0.f);
-
- if (mBkgndTexture)
- {
- gGL.getTexUnit(0)->bind(mBkgndTexture.get());
-
- gGL.color4f(1.0f, 1.0f, 1.0f, 1.0f);
-
- gGL.begin(LLRender::QUADS);
-
- gGL.texCoord2f(1.f, 1.f);
- gGL.vertex2i(width, height);
-
- gGL.texCoord2f(0.f, 1.f);
- gGL.vertex2i(-width, height);
-
- gGL.texCoord2f(0.f, 0.f);
- gGL.vertex2i(-width, -height);
-
- gGL.texCoord2f(1.f, 0.f);
- gGL.vertex2i(width, -height);
-
- gGL.end();
- }
-
- // rotate subsequent draws to agent rotation
- F32 rotation = atan2( gAgent.getFrameAgent().getAtAxis().mV[VX], gAgent.getFrameAgent().getAtAxis().mV[VY] );
- glRotatef( - rotation * RAD_TO_DEG, 0.f, 0.f, -1.f);
-
- if (mTexture)
- {
- gGL.getTexUnit(0)->bind(mTexture.get());
- gGL.color4f(1.0f, 1.0f, 1.0f, 1.0f);
-
- gGL.begin(LLRender::QUADS);
-
- gGL.texCoord2f(1.f, 1.f);
- gGL.vertex2i(width, height);
-
- gGL.texCoord2f(0.f, 1.f);
- gGL.vertex2i(-width, height);
-
- gGL.texCoord2f(0.f, 0.f);
- gGL.vertex2i(-width, -height);
-
- gGL.texCoord2f(1.f, 0.f);
- gGL.vertex2i(width, -height);
-
- gGL.end();
- }
-
- gGL.popMatrix();
-
-}
-
-
-
-void LLHorizontalCompass::draw()
-{
- LLGLSUIDefault gls_ui;
-
- S32 width = getRect().getWidth();
- S32 height = getRect().getHeight();
- S32 half_width = width / 2;
-
- if( mTexture )
- {
- const LLVector3& at_axis = LLViewerCamera::getInstance()->getAtAxis();
- F32 center = atan2( at_axis.mV[VX], at_axis.mV[VY] );
-
- center += F_PI;
- center = llclamp( center, 0.0f, F_TWO_PI ); // probably not necessary...
- center /= F_TWO_PI;
- F32 left = center - COMPASS_RANGE;
- F32 right = center + COMPASS_RANGE;
-
- gGL.getTexUnit(0)->bind(mTexture.get());
- gGL.color4f(1.0f, 1.0f, 1.0f, 1.0f );
- gGL.begin( LLRender::QUADS );
-
- gGL.texCoord2f(right, 1.f);
- gGL.vertex2i(width, height);
-
- gGL.texCoord2f(left, 1.f);
- gGL.vertex2i(0, height);
-
- gGL.texCoord2f(left, 0.f);
- gGL.vertex2i(0, 0);
-
- gGL.texCoord2f(right, 0.f);
- gGL.vertex2i(width, 0);
-
- gGL.end();
- }
-
- // Draw the focus line
- {
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.color4fv( mFocusColor.mV );
- gl_line_2d( half_width, 0, half_width, height );
- }
-}
-
-
const F32 WIND_ALTITUDE = 180.f;
-
void LLWind::renderVectors()
{
// Renders the wind as vectors (used for debug)
@@ -1008,8 +889,6 @@ void LLViewerObjectList::renderObjectBeacons()
return;
}
- //const LLFontGL *font = LLResMgr::getInstance()->getRes(LLFONT_SANSSERIF);
-
LLGLSUIDefault gls_ui;
{
diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp
new file mode 100644
index 0000000000..d6e2bb0445
--- /dev/null
+++ b/indra/newview/llgroupactions.cpp
@@ -0,0 +1,398 @@
+/**
+ * @file llgroupactions.cpp
+ * @brief Group-related actions (join, leave, new, delete, etc)
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llgroupactions.h"
+
+#include "message.h"
+
+#include "llagent.h"
+#include "llcommandhandler.h"
+#include "llfloaterreg.h"
+#include "llgroupmgr.h"
+#include "llimview.h" // for gIMMgr
+#include "llnotificationsutil.h"
+#include "llsidetray.h"
+#include "llstatusbar.h" // can_afford_transaction()
+#include "llimfloater.h"
+
+//
+// Globals
+//
+
+class LLGroupHandler : public LLCommandHandler
+{
+public:
+ // requires trusted browser to trigger
+ LLGroupHandler() : LLCommandHandler("group", UNTRUSTED_THROTTLE) { }
+ bool handle(const LLSD& tokens, const LLSD& query_map,
+ LLMediaCtrl* web)
+ {
+ if (tokens.size() < 1)
+ {
+ return false;
+ }
+
+ if (tokens[0].asString() == "create")
+ {
+ LLGroupActions::createGroup();
+ return true;
+ }
+
+ if (tokens.size() < 2)
+ {
+ return false;
+ }
+
+ if (tokens[0].asString() == "list")
+ {
+ if (tokens[1].asString() == "show")
+ {
+ LLFloaterReg::showInstance("contacts", "groups");
+ return true;
+ }
+ return false;
+ }
+
+ LLUUID group_id;
+ if (!group_id.set(tokens[0], FALSE))
+ {
+ return false;
+ }
+
+ if (tokens[1].asString() == "about")
+ {
+ if (group_id.isNull())
+ return true;
+
+ LLGroupActions::show(group_id);
+
+ return true;
+ }
+ if (tokens[1].asString() == "inspect")
+ {
+ if (group_id.isNull())
+ return true;
+ LLGroupActions::show(group_id);
+ return true;
+ }
+ return false;
+ }
+};
+LLGroupHandler gGroupHandler;
+
+// static
+void LLGroupActions::search()
+{
+ LLFloaterReg::showInstance("search", LLSD().with("category", "groups"));
+}
+
+// static
+void LLGroupActions::startCall(const LLUUID& group_id)
+{
+ // create a new group voice session
+ LLGroupData gdata;
+
+ if (!gAgent.getGroupData(group_id, gdata))
+ {
+ llwarns << "Error getting group data" << llendl;
+ return;
+ }
+
+ LLUUID session_id = gIMMgr->addSession(gdata.mName, IM_SESSION_GROUP_START, group_id, true);
+ if (session_id == LLUUID::null)
+ {
+ llwarns << "Error adding session" << llendl;
+ return;
+ }
+
+ // start the call
+ gIMMgr->autoStartCallOnStartup(session_id);
+
+ make_ui_sound("UISndStartIM");
+}
+
+// static
+void LLGroupActions::join(const LLUUID& group_id)
+{
+ if (!gAgent.canJoinGroups())
+ {
+ LLNotificationsUtil::add("JoinedTooManyGroups");
+ return;
+ }
+
+ LLGroupMgrGroupData* gdatap =
+ LLGroupMgr::getInstance()->getGroupData(group_id);
+
+ if (gdatap)
+ {
+ S32 cost = gdatap->mMembershipFee;
+ LLSD args;
+ args["COST"] = llformat("%d", cost);
+ LLSD payload;
+ payload["group_id"] = group_id;
+
+ if (can_afford_transaction(cost))
+ {
+ LLNotificationsUtil::add("JoinGroupCanAfford", args, payload, onJoinGroup);
+ }
+ else
+ {
+ LLNotificationsUtil::add("JoinGroupCannotAfford", args, payload);
+ }
+ }
+ else
+ {
+ llwarns << "LLGroupMgr::getInstance()->getGroupData(" << group_id
+ << ") was NULL" << llendl;
+ }
+}
+
+// static
+bool LLGroupActions::onJoinGroup(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+ if (option == 1)
+ {
+ // user clicked cancel
+ return false;
+ }
+
+ LLGroupMgr::getInstance()->
+ sendGroupMemberJoin(notification["payload"]["group_id"].asUUID());
+ return false;
+}
+
+// static
+void LLGroupActions::leave(const LLUUID& group_id)
+{
+ if (group_id.isNull())
+ return;
+
+ S32 count = gAgent.mGroups.count();
+ S32 i;
+ for (i = 0; i < count; ++i)
+ {
+ if(gAgent.mGroups.get(i).mID == group_id)
+ break;
+ }
+ if (i < count)
+ {
+ LLSD args;
+ args["GROUP"] = gAgent.mGroups.get(i).mName;
+ LLSD payload;
+ payload["group_id"] = group_id;
+ LLNotificationsUtil::add("GroupLeaveConfirmMember", args, payload, onLeaveGroup);
+ }
+}
+
+// static
+void LLGroupActions::activate(const LLUUID& group_id)
+{
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_ActivateGroup);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addUUIDFast(_PREHASH_GroupID, group_id);
+ gAgent.sendReliableMessage();
+}
+
+static bool isGroupUIVisible()
+{
+ static LLPanel* panel = 0;
+ if(!panel)
+ panel = LLSideTray::getInstance()->findChild<LLPanel>("panel_group_info_sidetray");
+ if(!panel)
+ return false;
+ return panel->isInVisibleChain();
+}
+
+// static
+void LLGroupActions::show(const LLUUID& group_id)
+{
+ if (group_id.isNull())
+ return;
+
+ LLSD params;
+ params["group_id"] = group_id;
+ params["open_tab_name"] = "panel_group_info_sidetray";
+
+ LLSideTray::getInstance()->showPanel("panel_group_info_sidetray", params);
+}
+
+void LLGroupActions::refresh_notices()
+{
+ if(!isGroupUIVisible())
+ return;
+
+ LLSD params;
+ params["group_id"] = LLUUID::null;
+ params["open_tab_name"] = "panel_group_info_sidetray";
+ params["action"] = "refresh_notices";
+
+ LLSideTray::getInstance()->showPanel("panel_group_info_sidetray", params);
+}
+
+//static
+void LLGroupActions::refresh(const LLUUID& group_id)
+{
+ if(!isGroupUIVisible())
+ return;
+
+ LLSD params;
+ params["group_id"] = group_id;
+ params["open_tab_name"] = "panel_group_info_sidetray";
+ params["action"] = "refresh";
+
+ LLSideTray::getInstance()->showPanel("panel_group_info_sidetray", params);
+}
+
+//static
+void LLGroupActions::createGroup()
+{
+ LLSD params;
+ params["group_id"] = LLUUID::null;
+ params["open_tab_name"] = "panel_group_info_sidetray";
+ params["action"] = "create";
+
+ LLSideTray::getInstance()->showPanel("panel_group_info_sidetray", params);
+
+}
+//static
+void LLGroupActions::closeGroup(const LLUUID& group_id)
+{
+ if(!isGroupUIVisible())
+ return;
+
+ LLSD params;
+ params["group_id"] = group_id;
+ params["open_tab_name"] = "panel_group_info_sidetray";
+ params["action"] = "close";
+
+ LLSideTray::getInstance()->showPanel("panel_group_info_sidetray", params);
+}
+
+
+// static
+void LLGroupActions::startIM(const LLUUID& group_id)
+{
+ if (group_id.isNull())
+ return;
+
+ LLGroupData group_data;
+ if (gAgent.getGroupData(group_id, group_data))
+ {
+ LLUUID session_id = gIMMgr->addSession(
+ group_data.mName,
+ IM_SESSION_GROUP_START,
+ group_id);
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
+ make_ui_sound("UISndStartIM");
+ }
+ else
+ {
+ // this should never happen, as starting a group IM session
+ // relies on you belonging to the group and hence having the group data
+ make_ui_sound("UISndInvalidOp");
+ }
+}
+
+// static
+void LLGroupActions::endIM(const LLUUID& group_id)
+{
+ if (group_id.isNull())
+ return;
+
+ LLUUID session_id = gIMMgr->computeSessionID(IM_SESSION_GROUP_START, group_id);
+ if (session_id != LLUUID::null)
+ {
+ gIMMgr->leaveSession(session_id);
+ }
+}
+
+// static
+bool LLGroupActions::isInGroup(const LLUUID& group_id)
+{
+ // *TODO: Move all the LLAgent group stuff into another class, such as
+ // this one.
+ return gAgent.isInGroup(group_id);
+}
+
+// static
+bool LLGroupActions::isAvatarMemberOfGroup(const LLUUID& group_id, const LLUUID& avatar_id)
+{
+ if(group_id.isNull() || avatar_id.isNull())
+ {
+ return false;
+ }
+
+ LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(group_id);
+ if(!group_data)
+ {
+ return false;
+ }
+
+ if(group_data->mMembers.end() == group_data->mMembers.find(avatar_id))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+//-- Private methods ----------------------------------------------------------
+
+// static
+bool LLGroupActions::onLeaveGroup(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ LLUUID group_id = notification["payload"]["group_id"].asUUID();
+ if(option == 0)
+ {
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_LeaveGroupRequest);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_GroupData);
+ msg->addUUIDFast(_PREHASH_GroupID, group_id);
+ gAgent.sendReliableMessage();
+ }
+ return false;
+}
diff --git a/indra/newview/llgroupactions.h b/indra/newview/llgroupactions.h
new file mode 100644
index 0000000000..e99df86cd9
--- /dev/null
+++ b/indra/newview/llgroupactions.h
@@ -0,0 +1,120 @@
+/**
+ * @file llgroupactions.h
+ * @brief Group-related actions (join, leave, new, delete, etc)
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLGROUPACTIONS_H
+#define LL_LLGROUPACTIONS_H
+
+#include "llsd.h"
+#include "lluuid.h"
+
+/**
+ * Group-related actions (join, leave, new, delete, etc)
+ */
+class LLGroupActions
+{
+public:
+ /**
+ * Invokes group search floater.
+ */
+ static void search();
+
+ /// Join a group. Assumes LLGroupMgr has data for that group already.
+ static void join(const LLUUID& group_id);
+
+ /**
+ * Invokes "Leave Group" floater.
+ */
+ static void leave(const LLUUID& group_id);
+
+ /**
+ * Activate group.
+ */
+ static void activate(const LLUUID& group_id);
+
+ /**
+ * Show group information panel.
+ */
+ static void show(const LLUUID& group_id);
+
+ /**
+ * Refresh group information panel.
+ */
+ static void refresh(const LLUUID& group_id);
+
+ /**
+ * Refresh group notices panel.
+ */
+ static void refresh_notices();
+
+ /**
+ * Refresh group information panel.
+ */
+ static void createGroup();
+
+ /**
+ * Close group information panel.
+ */
+ static void closeGroup (const LLUUID& group_id);
+
+ /**
+ * Start group instant messaging session.
+ */
+ static void startIM(const LLUUID& group_id);
+
+ /**
+ * End group instant messaging session.
+ */
+ static void endIM(const LLUUID& group_id);
+
+ /// Returns if the current user is a member of the group
+ static bool isInGroup(const LLUUID& group_id);
+
+ /**
+ * Start a group voice call.
+ */
+ static void startCall(const LLUUID& group_id);
+
+ /**
+ * Returns true if avatar is in group.
+ *
+ * Note that data about group members is loaded from server.
+ * If data has not been loaded yet, function will return inaccurate result.
+ * See LLGroupMgr::sendGroupMembersRequest
+ */
+ static bool isAvatarMemberOfGroup(const LLUUID& group_id, const LLUUID& avatar_id);
+
+private:
+ static bool onJoinGroup(const LLSD& notification, const LLSD& response);
+ static bool onLeaveGroup(const LLSD& notification, const LLSD& response);
+};
+
+#endif // LL_LLGROUPACTIONS_H
diff --git a/indra/newview/llgroupiconctrl.cpp b/indra/newview/llgroupiconctrl.cpp
new file mode 100644
index 0000000000..0b03d49cbc
--- /dev/null
+++ b/indra/newview/llgroupiconctrl.cpp
@@ -0,0 +1,145 @@
+/**
+ * @file llgroupiconctrl.cpp
+ * @brief LLGroupIconCtrl class implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llgroupiconctrl.h"
+
+#include "llagent.h"
+/*
+#include "llavatarconstants.h"
+#include "llcallingcard.h" // for LLAvatarTracker
+#include "llavataractions.h"
+#include "llmenugl.h"
+#include "lluictrlfactory.h"
+
+#include "llcachename.h"
+#include "llagentdata.h"
+#include "llimfloater.h"
+*/
+
+static LLDefaultChildRegistry::Register<LLGroupIconCtrl> g_i("group_icon");
+
+LLGroupIconCtrl::Params::Params()
+: group_id("group_id")
+, draw_tooltip("draw_tooltip", true)
+, default_icon_name("default_icon_name")
+{
+}
+
+
+LLGroupIconCtrl::LLGroupIconCtrl(const LLGroupIconCtrl::Params& p)
+: LLIconCtrl(p)
+, mGroupId(LLUUID::null)
+, mDrawTooltip(p.draw_tooltip)
+, mDefaultIconName(p.default_icon_name)
+{
+ mPriority = LLViewerFetchedTexture::BOOST_ICON;
+
+ if (p.group_id.isProvided())
+ {
+ LLSD value(p.group_id);
+ setValue(value);
+ }
+ else
+ {
+ LLIconCtrl::setValue(mDefaultIconName);
+ }
+}
+
+LLGroupIconCtrl::~LLGroupIconCtrl()
+{
+ LLGroupMgr::getInstance()->removeObserver(this);
+}
+
+void LLGroupIconCtrl::setValue(const LLSD& value)
+{
+ if (value.isUUID())
+ {
+ LLGroupMgr* gm = LLGroupMgr::getInstance();
+ if (mGroupId.notNull())
+ {
+ gm->removeObserver(this);
+ }
+
+ if (mGroupId != value.asUUID())
+ {
+ mGroupId = value.asUUID();
+
+ // Check if cache already contains image_id for that group
+ if (!updateFromCache())
+ {
+ LLIconCtrl::setValue(mDefaultIconName);
+ gm->addObserver(this);
+ gm->sendGroupPropertiesRequest(mGroupId);
+ }
+ }
+ }
+ else
+ {
+ LLIconCtrl::setValue(value);
+ }
+}
+
+void LLGroupIconCtrl::changed(LLGroupChange gc)
+{
+ if (GC_PROPERTIES == gc)
+ {
+ updateFromCache();
+ }
+}
+
+bool LLGroupIconCtrl::updateFromCache()
+{
+ LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mGroupId);
+ if (!group_data) return false;
+
+ if (group_data->mInsigniaID.notNull())
+ {
+ LLIconCtrl::setValue(group_data->mInsigniaID);
+ }
+ else
+ {
+ LLIconCtrl::setValue(mDefaultIconName);
+ }
+
+ if (mDrawTooltip && !group_data->mName.empty())
+ {
+ setToolTip(group_data->mName);
+ }
+ else
+ {
+ setToolTip(LLStringUtil::null);
+ }
+ return true;
+}
+
diff --git a/indra/newview/llgroupiconctrl.h b/indra/newview/llgroupiconctrl.h
new file mode 100644
index 0000000000..7ac2ca0219
--- /dev/null
+++ b/indra/newview/llgroupiconctrl.h
@@ -0,0 +1,92 @@
+/**
+ * @file llgroupiconctrl.h
+ * @brief LLGroupIconCtrl class declaration
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLGROUPICONCTRL_H
+#define LL_LLGROUPICONCTRL_H
+
+#include "lliconctrl.h"
+
+#include "llgroupmgr.h"
+
+/**
+ * Extends IconCtrl to show group icon wherever it is needed.
+ *
+ * It gets icon id by group id from the LLGroupMgr.
+ * If group data is not loaded yet it subscribes as LLGroupMgr observer and requests necessary data.
+ */
+class LLGroupIconCtrl
+ : public LLIconCtrl, public LLGroupMgrObserver
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLIconCtrl::Params>
+ {
+ Optional <LLUUID> group_id;
+ Optional <bool> draw_tooltip;
+ Optional <std::string> default_icon_name;
+ Params();
+ };
+
+protected:
+ LLGroupIconCtrl(const Params&);
+ friend class LLUICtrlFactory;
+
+public:
+ virtual ~LLGroupIconCtrl();
+
+ /**
+ * Determines group icon id by group id and sets it as icon value.
+ *
+ * Icon id is got from the appropriate LLGroupMgrGroupData specified by group UUID.
+ * If necessary it requests necessary data from the LLGroupMgr.
+ *
+ * @params value - if LLUUID - it is processed as group id otherwise base method is called.
+ */
+ virtual void setValue(const LLSD& value);
+
+ // LLGroupMgrObserver observer trigger
+ virtual void changed(LLGroupChange gc);
+
+ const std::string& getGroupName() const { return mGroupName; }
+ void setDrawTooltip(bool value) { mDrawTooltip = value;}
+
+ const LLUUID& getGroupId() const { return mGroupId; }
+
+protected:
+ LLUUID mGroupId;
+ std::string mGroupName;
+ bool mDrawTooltip;
+ std::string mDefaultIconName;
+
+ bool updateFromCache();
+};
+
+#endif // LL_LLGROUPICONCTRL_H
diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp
new file mode 100644
index 0000000000..e01709aa3a
--- /dev/null
+++ b/indra/newview/llgrouplist.cpp
@@ -0,0 +1,431 @@
+/**
+ * @file llgrouplist.cpp
+ * @brief List of the groups the agent belongs to.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llgrouplist.h"
+
+// libs
+#include "llbutton.h"
+#include "lliconctrl.h"
+#include "llmenugl.h"
+#include "lltextbox.h"
+#include "lltrans.h"
+
+// newview
+#include "llagent.h"
+#include "llgroupactions.h"
+#include "llfloaterreg.h"
+#include "lltextutil.h"
+#include "llviewercontrol.h" // for gSavedSettings
+#include "llviewermenu.h" // for gMenuHolder
+#include "llvoiceclient.h"
+
+static LLDefaultChildRegistry::Register<LLGroupList> r("group_list");
+S32 LLGroupListItem::sIconWidth = 0;
+
+class LLGroupComparator : public LLFlatListView::ItemComparator
+{
+public:
+ /** Returns true if item1 < item2, false otherwise */
+ /*virtual*/ bool compare(const LLPanel* item1, const LLPanel* item2) const
+ {
+ std::string name1 = static_cast<const LLGroupListItem*>(item1)->getGroupName();
+ std::string name2 = static_cast<const LLGroupListItem*>(item2)->getGroupName();
+
+ LLStringUtil::toUpper(name1);
+ LLStringUtil::toUpper(name2);
+
+ return name1 < name2;
+ }
+};
+
+static const LLGroupComparator GROUP_COMPARATOR;
+
+LLGroupList::Params::Params()
+{
+
+}
+
+LLGroupList::LLGroupList(const Params& p)
+: LLFlatListView(p)
+ , mDirty(true) // to force initial update
+{
+ // Listen for agent group changes.
+ gAgent.addListener(this, "new group");
+
+ mShowIcons = gSavedSettings.getBOOL("GroupListShowIcons");
+ setCommitOnSelectionChange(true);
+ // TODO: implement context menu
+ // display a context menu appropriate for a list of group names
+// setContextMenu(LLScrollListCtrl::MENU_GROUP);
+
+ // Set default sort order.
+ setComparator(&GROUP_COMPARATOR);
+
+ // Set up context menu.
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+
+ registrar.add("People.Groups.Action", boost::bind(&LLGroupList::onContextMenuItemClick, this, _2));
+ enable_registrar.add("People.Groups.Enable", boost::bind(&LLGroupList::onContextMenuItemEnable, this, _2));
+
+ LLMenuGL* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_groups.xml",
+ gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if(context_menu)
+ mContextMenuHandle = context_menu->getHandle();
+}
+
+LLGroupList::~LLGroupList()
+{
+ gAgent.removeListener(this);
+ LLView::deleteViewByHandle(mContextMenuHandle);
+}
+
+// virtual
+void LLGroupList::draw()
+{
+ if (mDirty)
+ refresh();
+
+ LLFlatListView::draw();
+}
+
+// virtual
+BOOL LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask);
+
+ LLMenuGL* context_menu = (LLMenuGL*)mContextMenuHandle.get();
+ if (context_menu)
+ {
+ context_menu->buildDrawLabels();
+ context_menu->updateParent(LLMenuGL::sMenuContainer);
+ LLMenuGL::showPopup(this, context_menu, x, y);
+ }
+
+ return handled;
+}
+
+void LLGroupList::setNameFilter(const std::string& filter)
+{
+ if (mNameFilter != filter)
+ {
+ mNameFilter = filter;
+ setDirty();
+ }
+}
+
+static bool findInsensitive(std::string haystack, const std::string& needle_upper)
+{
+ LLStringUtil::toUpper(haystack);
+ return haystack.find(needle_upper) != std::string::npos;
+}
+
+void LLGroupList::refresh()
+{
+ const LLUUID& highlight_id = gAgent.getGroupID();
+ S32 count = gAgent.mGroups.count();
+ LLUUID id;
+ bool have_filter = !mNameFilter.empty();
+
+ clear();
+
+ for(S32 i = 0; i < count; ++i)
+ {
+ id = gAgent.mGroups.get(i).mID;
+ const LLGroupData& group_data = gAgent.mGroups.get(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"?).
+ if (!have_filter)
+ {
+ std::string loc_none = LLTrans::getString("GroupsNone");
+ addNewItem(LLUUID::null, loc_none, LLUUID::null, ADD_TOP);
+ }
+
+ selectItemByUUID(highlight_id);
+
+ setDirty(false);
+ onCommit();
+}
+
+void LLGroupList::toggleIcons()
+{
+ // Save the new value for new items to use.
+ mShowIcons = !mShowIcons;
+ gSavedSettings.setBOOL("GroupListShowIcons", mShowIcons);
+
+ // Show/hide icons for all existing items.
+ std::vector<LLPanel*> items;
+ getItems(items);
+ for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
+ {
+ static_cast<LLGroupListItem*>(*it)->setGroupIconVisible(mShowIcons);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// PRIVATE Section
+//////////////////////////////////////////////////////////////////////////
+
+void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos)
+{
+ LLGroupListItem* item = new LLGroupListItem();
+
+ item->setGroupID(id);
+ item->setName(name, mNameFilter);
+ item->setGroupIconID(icon_id);
+
+ item->childSetVisible("info_btn", false);
+ item->childSetVisible("profile_btn", false);
+ item->setGroupIconVisible(mShowIcons);
+
+ addItem(item, id, pos);
+
+// setCommentVisible(false);
+}
+
+// virtual
+bool LLGroupList::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
+{
+ // Why is "new group" sufficient?
+ if (event->desc() == "new group")
+ {
+ setDirty();
+ return true;
+ }
+
+ return false;
+}
+
+bool LLGroupList::onContextMenuItemClick(const LLSD& userdata)
+{
+ std::string action = userdata.asString();
+ LLUUID selected_group = getSelectedUUID();
+
+ if (action == "view_info")
+ {
+ LLGroupActions::show(selected_group);
+ }
+ else if (action == "chat")
+ {
+ LLGroupActions::startIM(selected_group);
+ }
+ else if (action == "call")
+ {
+ LLGroupActions::startCall(selected_group);
+ }
+ else if (action == "activate")
+ {
+ LLGroupActions::activate(selected_group);
+ }
+ else if (action == "leave")
+ {
+ LLGroupActions::leave(selected_group);
+ }
+
+ return true;
+}
+
+bool LLGroupList::onContextMenuItemEnable(const LLSD& userdata)
+{
+ LLUUID selected_group_id = getSelectedUUID();
+ bool real_group_selected = selected_group_id.notNull(); // a "real" (not "none") group is selected
+
+ // each group including "none" can be activated
+ if (userdata.asString() == "activate")
+ return gAgent.getGroupID() != selected_group_id;
+
+ if (userdata.asString() == "call")
+ return LLVoiceClient::voiceEnabled()&&gVoiceClient->voiceWorking();
+
+ return real_group_selected;
+}
+
+/************************************************************************/
+/* LLGroupListItem implementation */
+/************************************************************************/
+
+LLGroupListItem::LLGroupListItem()
+: LLPanel(),
+mGroupIcon(NULL),
+mGroupNameBox(NULL),
+mInfoBtn(NULL),
+mGroupID(LLUUID::null)
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this, "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;
+ }
+}
+
+LLGroupListItem::~LLGroupListItem()
+{
+ LLGroupMgr::getInstance()->removeObserver(this);
+}
+
+//virtual
+BOOL LLGroupListItem::postBuild()
+{
+ mGroupIcon = getChild<LLIconCtrl>("group_icon");
+ mGroupNameBox = getChild<LLTextBox>("group_name");
+
+ mInfoBtn = getChild<LLButton>("info_btn");
+ mInfoBtn->setClickedCallback(boost::bind(&LLGroupListItem::onInfoBtnClick, this));
+
+ childSetAction("profile_btn", boost::bind(&LLGroupListItem::onProfileBtnClick, this));
+
+ return TRUE;
+}
+
+//virtual
+void LLGroupListItem::setValue( const LLSD& value )
+{
+ if (!value.isMap()) return;
+ if (!value.has("selected")) return;
+ childSetVisible("selected_icon", value["selected"]);
+}
+
+void LLGroupListItem::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+ childSetVisible("hovered_icon", true);
+ if (mGroupID.notNull()) // don't show the info button for the "none" group
+ {
+ mInfoBtn->setVisible(true);
+ childSetVisible("profile_btn", true);
+ }
+
+ LLPanel::onMouseEnter(x, y, mask);
+}
+
+void LLGroupListItem::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ childSetVisible("hovered_icon", false);
+ mInfoBtn->setVisible(false);
+ childSetVisible("profile_btn", false);
+
+ LLPanel::onMouseLeave(x, y, mask);
+}
+
+void LLGroupListItem::setName(const std::string& name, const std::string& highlight)
+{
+ mGroupName = name;
+ LLTextUtil::textboxSetHighlightedVal(mGroupNameBox, mGroupNameStyle, name, highlight);
+ mGroupNameBox->setToolTip(name);
+}
+
+void LLGroupListItem::setGroupID(const LLUUID& group_id)
+{
+ LLGroupMgr::getInstance()->removeObserver(this);
+
+ mID = group_id;
+ mGroupID = group_id;
+ setActive(group_id == gAgent.getGroupID());
+
+ LLGroupMgr::getInstance()->addObserver(this);
+}
+
+void LLGroupListItem::setGroupIconID(const LLUUID& group_icon_id)
+{
+ if (group_icon_id.notNull())
+ {
+ mGroupIcon->setValue(group_icon_id);
+ }
+}
+
+void LLGroupListItem::setGroupIconVisible(bool visible)
+{
+ // Already done? Then do nothing.
+ if (mGroupIcon->getVisible() == (BOOL)visible)
+ return;
+
+ // Show/hide the group icon.
+ mGroupIcon->setVisible(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;
+ mGroupNameBox->setRect(name_rect);
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Private Section
+//////////////////////////////////////////////////////////////////////////
+void LLGroupListItem::setActive(bool active)
+{
+ // *BUG: setName() overrides the style params.
+
+ // Active group should be bold.
+ LLFontDescriptor new_desc(mGroupNameBox->getDefaultFont()->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);
+ LLFontGL* new_font = LLFontGL::getFont(new_desc);
+ mGroupNameStyle.font = new_font;
+
+ // *NOTE: You cannot set the style on a text box anymore, you must
+ // rebuild the text. This will cause problems if the text contains
+ // hyperlinks, as their styles will be wrong.
+ mGroupNameBox->setText(mGroupName, mGroupNameStyle);
+}
+
+void LLGroupListItem::onInfoBtnClick()
+{
+ LLFloaterReg::showInstance("inspect_group", LLSD().with("group_id", mGroupID));
+}
+
+void LLGroupListItem::onProfileBtnClick()
+{
+ LLGroupActions::show(mGroupID);
+}
+
+void LLGroupListItem::changed(LLGroupChange gc)
+{
+ LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mID);
+ if(group_data)
+ setGroupIconID(group_data->mInsigniaID);
+}
+
+//EOF
diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h
new file mode 100644
index 0000000000..f7afe0c0b2
--- /dev/null
+++ b/indra/newview/llgrouplist.h
@@ -0,0 +1,124 @@
+/**
+ * @file llgrouplist.h
+ * @brief List of the groups the agent belongs to.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLGROUPLIST_H
+#define LL_LLGROUPLIST_H
+
+#include "llevent.h"
+#include "llflatlistview.h"
+#include "llpanel.h"
+#include "llpointer.h"
+#include "llstyle.h"
+#include "llgroupmgr.h"
+
+/**
+ * Auto-updating list of agent groups.
+ *
+ * Can use optional group name filter.
+ *
+ * @see setNameFilter()
+ */
+class LLGroupList: public LLFlatListView, public LLOldEvents::LLSimpleListener
+{
+ LOG_CLASS(LLGroupList);
+public:
+ struct Params : public LLInitParam::Block<Params, LLFlatListView::Params>
+ {
+ Params();
+ };
+
+ LLGroupList(const Params& p);
+ virtual ~LLGroupList();
+
+ virtual void draw(); // from LLView
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); // from LLView
+
+ void setNameFilter(const std::string& filter);
+ void toggleIcons();
+ bool getIconsVisible() const { return mShowIcons; }
+
+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);
+ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); // called on agent group list changes
+
+ bool onContextMenuItemClick(const LLSD& userdata);
+ bool onContextMenuItemEnable(const LLSD& userdata);
+
+ LLHandle<LLView> mContextMenuHandle;
+
+ bool mShowIcons;
+ bool mDirty;
+ std::string mNameFilter;
+};
+
+class LLButton;
+class LLIconCtrl;
+class LLTextBox;
+
+class LLGroupListItem : public LLPanel
+ , public LLGroupMgrObserver
+{
+public:
+ LLGroupListItem();
+ ~LLGroupListItem();
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void setValue(const LLSD& value);
+ void onMouseEnter(S32 x, S32 y, MASK mask);
+ void onMouseLeave(S32 x, S32 y, MASK mask);
+
+ const LLUUID& getGroupID() const { return mGroupID; }
+ const std::string& getGroupName() const { return mGroupName; }
+
+ void setName(const std::string& name, const std::string& highlight = LLStringUtil::null);
+ void setGroupID(const LLUUID& group_id);
+ void setGroupIconID(const LLUUID& group_icon_id);
+ void setGroupIconVisible(bool visible);
+
+ virtual void changed(LLGroupChange gc);
+private:
+ void setActive(bool active);
+ void onInfoBtnClick();
+ void onProfileBtnClick();
+
+ LLTextBox* mGroupNameBox;
+ LLUUID mGroupID;
+ LLIconCtrl* mGroupIcon;
+ LLButton* mInfoBtn;
+
+ std::string mGroupName;
+ LLStyle::Params mGroupNameStyle;
+
+ static S32 sIconWidth; // icon width + padding
+};
+#endif // LL_LLGROUPLIST_H
diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp
index 003a02c3cd..af58e81ca4 100644
--- a/indra/newview/llgroupmgr.cpp
+++ b/indra/newview/llgroupmgr.cpp
@@ -50,8 +50,9 @@
#include "llstatusbar.h"
#include "lleconomy.h"
#include "llviewerwindow.h"
-#include "llfloaterdirectory.h"
-#include "llfloatergroupinfo.h"
+#include "llpanelgroup.h"
+#include "llgroupactions.h"
+#include "llnotificationsutil.h"
#include "lluictrlfactory.h"
#include <boost/regex.hpp>
@@ -757,7 +758,8 @@ void LLGroupMgr::clearGroupData(const LLUUID& group_id)
void LLGroupMgr::addObserver(LLGroupMgrObserver* observer)
{
- mObservers.insert(std::pair<LLUUID, LLGroupMgrObserver*>(observer->getID(), observer));
+ if( observer->getID() != LLUUID::null )
+ mObservers.insert(std::pair<LLUUID, LLGroupMgrObserver*>(observer->getID(), observer));
}
void LLGroupMgr::removeObserver(LLGroupMgrObserver* observer)
@@ -808,7 +810,7 @@ static void formatDateString(std::string &date_string)
std::string day = result[2];
// ISO 8601 date format
- date_string = llformat("%04s-%02s-%02s", year.c_str(), month.c_str(), day.c_str());
+ date_string = llformat("%02s/%02s/%04s", month.c_str(), day.c_str(), year.c_str());
}
}
@@ -1210,7 +1212,7 @@ void LLGroupMgr::processEjectGroupMemberReply(LLMessageSystem* msg, void ** data
// If we had a failure, the group panel needs to be updated.
if (!success)
{
- LLFloaterGroupInfo::refreshGroup(group_id);
+ LLGroupActions::refresh(group_id);
}
}
@@ -1230,9 +1232,7 @@ void LLGroupMgr::processJoinGroupReply(LLMessageSystem* msg, void ** data)
LLGroupMgr::getInstance()->clearGroupData(group_id);
// refresh the floater for this group, if any.
- LLFloaterGroupInfo::refreshGroup(group_id);
- // refresh the group panel of the search window, if necessary.
- LLFloaterDirectory::refreshGroup(group_id);
+ LLGroupActions::refresh(group_id);
}
}
@@ -1252,9 +1252,7 @@ void LLGroupMgr::processLeaveGroupReply(LLMessageSystem* msg, void ** data)
LLGroupMgr::getInstance()->clearGroupData(group_id);
// close the floater for this group, if any.
- LLFloaterGroupInfo::closeGroup(group_id);
- // refresh the group panel of the search window, if necessary.
- LLFloaterDirectory::refreshGroup(group_id);
+ LLGroupActions::closeGroup(group_id);
}
}
@@ -1288,15 +1286,17 @@ void LLGroupMgr::processCreateGroupReply(LLMessageSystem* msg, void ** data)
gAgent.mGroups.push_back(gd);
- LLFloaterGroupInfo::closeCreateGroup();
- LLFloaterGroupInfo::showFromUUID(group_id,"roles_tab");
+ LLPanelGroup::refreshCreatedGroup(group_id);
+ //FIXME
+ //LLFloaterGroupInfo::closeCreateGroup();
+ //LLFloaterGroupInfo::showFromUUID(group_id,"roles_tab");
}
else
{
- // *TODO:translate
+ // *TODO: Translate
LLSD args;
args["MESSAGE"] = message;
- LLNotifications::instance().add("UnableToCreateGroup", args);
+ LLNotificationsUtil::add("UnableToCreateGroup", args);
}
}
@@ -1322,11 +1322,16 @@ void LLGroupMgr::notifyObservers(LLGroupChange gc)
{
for (group_map_t::iterator gi = mGroups.begin(); gi != mGroups.end(); ++gi)
{
+ LLUUID group_id = gi->first;
if (gi->second->mChanged)
{
+ // Copy the map because observers may remove themselves on update
+ observer_multimap_t observers = mObservers;
+
// find all observers for this group id
- observer_multimap_t::iterator oi = mObservers.find(gi->first);
- for (; oi != mObservers.end(); ++oi)
+ observer_multimap_t::iterator oi = observers.lower_bound(group_id);
+ observer_multimap_t::iterator end = observers.upper_bound(group_id);
+ for (; oi != end; ++oi)
{
oi->second->changed(gc);
}
diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h
index a0604be57e..487fdd4c5b 100644
--- a/indra/newview/llgroupmgr.h
+++ b/indra/newview/llgroupmgr.h
@@ -45,6 +45,7 @@ class LLGroupMgrObserver
{
public:
LLGroupMgrObserver(const LLUUID& id) : mID(id){};
+ LLGroupMgrObserver() : mID(LLUUID::null){};
virtual ~LLGroupMgrObserver(){};
virtual void changed(LLGroupChange gc) = 0;
const LLUUID& getID() { return mID; }
diff --git a/indra/newview/llhomelocationresponder.cpp b/indra/newview/llhomelocationresponder.cpp
index 3ef58e7561..df478a0a04 100644
--- a/indra/newview/llhomelocationresponder.cpp
+++ b/indra/newview/llhomelocationresponder.cpp
@@ -103,7 +103,7 @@ void LLHomeLocationResponder::result( const LLSD& content )
}
}
-void LLHomeLocationResponder::error( const LLSD& content )
+void LLHomeLocationResponder::error( U32 status, const std::string& reason )
{
- llinfos << "received error(" << ll_pretty_print_sd( content ) << ")" << llendl;
+ llinfos << "received error(" << reason << ")" << llendl;
}
diff --git a/indra/newview/llhomelocationresponder.h b/indra/newview/llhomelocationresponder.h
index 1e222cd5b2..3a1d8ebfed 100644
--- a/indra/newview/llhomelocationresponder.h
+++ b/indra/newview/llhomelocationresponder.h
@@ -42,7 +42,7 @@
class LLHomeLocationResponder : public LLHTTPClient::Responder
{
virtual void result( const LLSD& content );
- virtual void error( const LLSD& content );
+ virtual void error( U32 status, const std::string& reason );
};
#endif
diff --git a/indra/newview/llhudeffect.cpp b/indra/newview/llhudeffect.cpp
index c1d46f98d4..bfd62805a1 100644
--- a/indra/newview/llhudeffect.cpp
+++ b/indra/newview/llhudeffect.cpp
@@ -38,7 +38,6 @@
#include "llgl.h"
#include "llagent.h"
#include "llrendersphere.h"
-#include "llimagegl.h"
#include "llviewerobjectlist.h"
#include "lldrawable.h"
diff --git a/indra/newview/llhudeffect.h b/indra/newview/llhudeffect.h
index 954cda7c8d..781e57fa6a 100644
--- a/indra/newview/llhudeffect.h
+++ b/indra/newview/llhudeffect.h
@@ -37,9 +37,6 @@
#include "lluuid.h"
#include "v4coloru.h"
-#include "llinterp.h"
-#include "llframetimer.h"
-#include "llmemory.h"
const F32 LL_HUD_DUR_SHORT = 1.f;
diff --git a/indra/newview/llhudeffectbeam.cpp b/indra/newview/llhudeffectbeam.cpp
index 6cb3bef751..43a8dd1d81 100644
--- a/indra/newview/llhudeffectbeam.cpp
+++ b/indra/newview/llhudeffectbeam.cpp
@@ -43,7 +43,6 @@
#include "llgl.h"
#include "llglheaders.h"
#include "llhudrender.h"
-#include "llimagegl.h"
#include "llrendersphere.h"
#include "llviewercamera.h"
#include "llvoavatar.h"
diff --git a/indra/newview/llhudeffectlookat.cpp b/indra/newview/llhudeffectlookat.cpp
index 3a5bec2be0..07b81ef134 100644
--- a/indra/newview/llhudeffectlookat.cpp
+++ b/indra/newview/llhudeffectlookat.cpp
@@ -421,8 +421,8 @@ BOOL LLHUDEffectLookAt::setLookAt(ELookAtType target_type, LLViewerObject *objec
BOOL lookAtChanged = (target_type != mTargetType) || (object != mTargetObject);
// lookat position has moved a certain amount and we haven't just sent an update
- lookAtChanged = lookAtChanged || (dist_vec(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE) &&
- ((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC));
+ lookAtChanged = lookAtChanged || ((dist_vec(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE) &&
+ ((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC)));
if (lookAtChanged)
{
@@ -610,7 +610,9 @@ bool LLHUDEffectLookAt::calcTargetPosition()
}
LLVOAvatar* source_avatar = (LLVOAvatar*)(LLViewerObject*)mSourceObject;
-
+ if (!source_avatar->isBuilt())
+ return false;
+
if (target_obj && target_obj->mDrawable.notNull())
{
LLQuaternion target_rot;
diff --git a/indra/newview/llhudeffectpointat.h b/indra/newview/llhudeffectpointat.h
index 81db3da1c7..278c69fe2b 100644
--- a/indra/newview/llhudeffectpointat.h
+++ b/indra/newview/llhudeffectpointat.h
@@ -33,6 +33,7 @@
#ifndef LL_LLHUDEFFECTPOINTAT_H
#define LL_LLHUDEFFECTPOINTAT_H
+#include "llframetimer.h"
#include "llhudeffect.h"
class LLViewerObject;
diff --git a/indra/newview/llhudeffecttrail.cpp b/indra/newview/llhudeffecttrail.cpp
index 0ade6810ba..786491211d 100644
--- a/indra/newview/llhudeffecttrail.cpp
+++ b/indra/newview/llhudeffecttrail.cpp
@@ -35,14 +35,13 @@
#include "llhudeffecttrail.h"
#include "llviewercontrol.h"
-#include "llimagegl.h"
#include "message.h"
#include "llagent.h"
#include "llbox.h"
#include "lldrawable.h"
#include "llhudrender.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewerobjectlist.h"
#include "llviewerpartsim.h"
#include "llviewerpartsource.h"
diff --git a/indra/newview/llhudicon.cpp b/indra/newview/llhudicon.cpp
index 3535fe185c..28b0e7356a 100644
--- a/indra/newview/llhudicon.cpp
+++ b/indra/newview/llhudicon.cpp
@@ -40,7 +40,7 @@
#include "llviewerobject.h"
#include "lldrawable.h"
#include "llviewercamera.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
#include "llviewerwindow.h"
//-----------------------------------------------------------------------------
@@ -103,28 +103,29 @@ void LLHUDIcon::renderIcon(BOOL for_select)
// put icon above object, and in front
// RN: don't use drawable radius, it's fricking HUGE
- LLVector3 icon_relative_pos = (LLViewerCamera::getInstance()->getUpAxis() * ~mSourceObject->getRenderRotation());
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
+ LLVector3 icon_relative_pos = (camera->getUpAxis() * ~mSourceObject->getRenderRotation());
icon_relative_pos.abs();
F32 distance_scale = llmin(mSourceObject->getScale().mV[VX] / icon_relative_pos.mV[VX],
mSourceObject->getScale().mV[VY] / icon_relative_pos.mV[VY],
mSourceObject->getScale().mV[VZ] / icon_relative_pos.mV[VZ]);
F32 up_distance = 0.5f * distance_scale;
- LLVector3 icon_position = obj_position + (up_distance * LLViewerCamera::getInstance()->getUpAxis()) * 1.2f;
+ LLVector3 icon_position = obj_position + (up_distance * camera->getUpAxis()) * 1.2f;
LLVector3 icon_to_cam = LLViewerCamera::getInstance()->getOrigin() - icon_position;
icon_to_cam.normVec();
icon_position += icon_to_cam * mSourceObject->mDrawable->getRadius() * 1.1f;
- mDistance = dist_vec(icon_position, LLViewerCamera::getInstance()->getOrigin());
+ mDistance = dist_vec(icon_position, camera->getOrigin());
F32 alpha_factor = for_select ? 1.f : clamp_rescale(mDistance, DIST_START_FADE, DIST_END_FADE, 1.f, 0.f);
LLVector3 x_pixel_vec;
LLVector3 y_pixel_vec;
- LLViewerCamera::getInstance()->getPixelVectors(icon_position, y_pixel_vec, x_pixel_vec);
+ camera->getPixelVectors(icon_position, y_pixel_vec, x_pixel_vec);
F32 scale_factor = 1.f;
if (mAnimTimer.getElapsedTimeF32() < ANIM_TIME)
@@ -144,9 +145,9 @@ void LLHUDIcon::renderIcon(BOOL for_select)
alpha_factor *= clamp_rescale(time_elapsed, MAX_VISIBLE_TIME - FADE_OUT_TIME, MAX_VISIBLE_TIME, 1.f, 0.f);
}
- F32 image_aspect = (F32)mImagep->mFullWidth / (F32)mImagep->mFullHeight;
- LLVector3 x_scale = image_aspect * (F32)gViewerWindow->getWindowHeight() * mScale * scale_factor * x_pixel_vec;
- LLVector3 y_scale = (F32)gViewerWindow->getWindowHeight() * mScale * scale_factor * y_pixel_vec;
+ F32 image_aspect = (F32)mImagep->getFullWidth() / (F32)mImagep->getFullHeight() ;
+ LLVector3 x_scale = image_aspect * (F32)gViewerWindow->getWindowHeightScaled() * mScale * scale_factor * x_pixel_vec;
+ LLVector3 y_scale = (F32)gViewerWindow->getWindowHeightScaled() * mScale * scale_factor * y_pixel_vec;
LLVector3 lower_left = icon_position - (x_scale * 0.5f);
LLVector3 lower_right = icon_position + (x_scale * 0.5f);
@@ -164,7 +165,7 @@ void LLHUDIcon::renderIcon(BOOL for_select)
LLColor4 icon_color = LLColor4::white;
icon_color.mV[VALPHA] = alpha_factor;
gGL.color4fv(icon_color.mV);
- gGL.getTexUnit(0)->bind(mImagep.get());
+ gGL.getTexUnit(0)->bind(mImagep);
}
gGL.begin(LLRender::QUADS);
@@ -181,7 +182,7 @@ void LLHUDIcon::renderIcon(BOOL for_select)
gGL.end();
}
-void LLHUDIcon::setImage(LLViewerImage* imagep)
+void LLHUDIcon::setImage(LLViewerTexture* imagep)
{
mImagep = imagep;
mImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
@@ -226,26 +227,27 @@ BOOL LLHUDIcon::lineSegmentIntersect(const LLVector3& start, const LLVector3& en
// put icon above object, and in front
// RN: don't use drawable radius, it's fricking HUGE
- LLVector3 icon_relative_pos = (LLViewerCamera::getInstance()->getUpAxis() * ~mSourceObject->getRenderRotation());
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
+ LLVector3 icon_relative_pos = (camera->getUpAxis() * ~mSourceObject->getRenderRotation());
icon_relative_pos.abs();
F32 distance_scale = llmin(mSourceObject->getScale().mV[VX] / icon_relative_pos.mV[VX],
mSourceObject->getScale().mV[VY] / icon_relative_pos.mV[VY],
mSourceObject->getScale().mV[VZ] / icon_relative_pos.mV[VZ]);
F32 up_distance = 0.5f * distance_scale;
- LLVector3 icon_position = obj_position + (up_distance * LLViewerCamera::getInstance()->getUpAxis()) * 1.2f;
+ LLVector3 icon_position = obj_position + (up_distance * camera->getUpAxis()) * 1.2f;
LLVector3 icon_to_cam = LLViewerCamera::getInstance()->getOrigin() - icon_position;
icon_to_cam.normVec();
icon_position += icon_to_cam * mSourceObject->mDrawable->getRadius() * 1.1f;
- mDistance = dist_vec(icon_position, LLViewerCamera::getInstance()->getOrigin());
+ mDistance = dist_vec(icon_position, camera->getOrigin());
LLVector3 x_pixel_vec;
LLVector3 y_pixel_vec;
- LLViewerCamera::getInstance()->getPixelVectors(icon_position, y_pixel_vec, x_pixel_vec);
+ camera->getPixelVectors(icon_position, y_pixel_vec, x_pixel_vec);
F32 scale_factor = 1.f;
if (mAnimTimer.getElapsedTimeF32() < ANIM_TIME)
@@ -260,9 +262,9 @@ BOOL LLHUDIcon::lineSegmentIntersect(const LLVector3& start, const LLVector3& en
return FALSE;
}
- F32 image_aspect = (F32)mImagep->mFullWidth / (F32)mImagep->mFullHeight;
- LLVector3 x_scale = image_aspect * (F32)gViewerWindow->getWindowHeight() * mScale * scale_factor * x_pixel_vec;
- LLVector3 y_scale = (F32)gViewerWindow->getWindowHeight() * mScale * scale_factor * y_pixel_vec;
+ F32 image_aspect = (F32)mImagep->getFullWidth() / (F32)mImagep->getFullHeight() ;
+ LLVector3 x_scale = image_aspect * (F32)gViewerWindow->getWindowHeightScaled() * mScale * scale_factor * x_pixel_vec;
+ LLVector3 y_scale = (F32)gViewerWindow->getWindowHeightScaled() * mScale * scale_factor * y_pixel_vec;
LLVector3 lower_left = icon_position - (x_scale * 0.5f);
LLVector3 lower_right = icon_position + (x_scale * 0.5f);
diff --git a/indra/newview/llhudicon.h b/indra/newview/llhudicon.h
index 154e6df518..770e3bbcd0 100644
--- a/indra/newview/llhudicon.h
+++ b/indra/newview/llhudicon.h
@@ -33,7 +33,7 @@
#ifndef LL_LLHUDICON_H
#define LL_LLHUDICON_H
-#include "llmemory.h"
+#include "llpointer.h"
#include "lldarrayptr.h"
#include "llhudobject.h"
@@ -61,7 +61,7 @@ public:
/*virtual*/ void markDead();
/*virtual*/ F32 getDistance() const { return mDistance; }
- void setImage(LLViewerImage* imagep);
+ void setImage(LLViewerTexture* imagep);
void setScale(F32 fraction_of_fov);
void restartLifeTimer() { mLifeTimer.reset(); }
@@ -88,7 +88,7 @@ protected:
void renderIcon(BOOL for_select); // common render code
private:
- LLPointer<LLViewerImage> mImagep;
+ LLPointer<LLViewerTexture> mImagep;
LLFrameTimer mAnimTimer;
LLFrameTimer mLifeTimer;
F32 mDistance;
diff --git a/indra/newview/llhudmanager.cpp b/indra/newview/llhudmanager.cpp
index 955d786187..bdb8dadfb4 100644
--- a/indra/newview/llhudmanager.cpp
+++ b/indra/newview/llhudmanager.cpp
@@ -40,6 +40,7 @@
#include "llagent.h"
#include "llhudeffect.h"
#include "pipeline.h"
+#include "llui.h"
#include "llviewercontrol.h"
#include "llviewerobjectlist.h"
@@ -52,19 +53,20 @@ LLColor4 LLHUDManager::sChildColor;
LLHUDManager::LLHUDManager()
{
- LLHUDManager::sParentColor = gColors.getColor("FocusColor");
+ LLHUDManager::sParentColor = LLUIColorTable::instance().getColor("FocusColor");
// rdw commented out since it's not used. Also removed from colors_base.xml
- //LLHUDManager::sChildColor = gColors.getColor("FocusSecondaryColor");
+ //LLHUDManager::sChildColor =LLUIColorTable::instance().getColor("FocusSecondaryColor");
}
LLHUDManager::~LLHUDManager()
{
}
+static LLFastTimer::DeclareTimer FTM_HUD_EFFECTS("Hud Effects");
void LLHUDManager::updateEffects()
{
- LLFastTimer ftm(LLFastTimer::FTM_HUD_EFFECTS);
+ LLFastTimer ftm(FTM_HUD_EFFECTS);
S32 i;
for (i = 0; i < mHUDEffects.count(); i++)
{
diff --git a/indra/newview/llhudmanager.h b/indra/newview/llhudmanager.h
index 615eb93a27..b2b4ffb559 100644
--- a/indra/newview/llhudmanager.h
+++ b/indra/newview/llhudmanager.h
@@ -36,7 +36,7 @@
// Responsible for managing all HUD elements.
#include "llhudobject.h"
-#include "lldarray.h"
+#include "lldarrayptr.h"
class LLViewerObject;
class LLHUDEffect;
diff --git a/indra/newview/llhudobject.cpp b/indra/newview/llhudobject.cpp
index bdff492948..dc55aba0db 100644
--- a/indra/newview/llhudobject.cpp
+++ b/indra/newview/llhudobject.cpp
@@ -254,10 +254,12 @@ LLHUDEffect *LLHUDObject::addHUDEffect(const U8 type)
return hud_objectp;
}
+static LLFastTimer::DeclareTimer FTM_HUD_UPDATE("Update Hud");
+
// static
void LLHUDObject::updateAll()
{
- LLFastTimer ftm(LLFastTimer::FTM_HUD_UPDATE);
+ LLFastTimer ftm(FTM_HUD_UPDATE);
LLHUDText::updateAll();
LLHUDIcon::updateAll();
sortObjects();
diff --git a/indra/newview/llhudobject.h b/indra/newview/llhudobject.h
index 2cd8abf886..d304ac41af 100644
--- a/indra/newview/llhudobject.h
+++ b/indra/newview/llhudobject.h
@@ -37,7 +37,7 @@
* Base class and manager for in-world 2.5D non-interactive objects
*/
-#include "llmemory.h"
+#include "llpointer.h"
#include "v4color.h"
#include "v3math.h"
diff --git a/indra/newview/llhudrender.cpp b/indra/newview/llhudrender.cpp
index 95b8442ec7..a02dc3355b 100644
--- a/indra/newview/llhudrender.cpp
+++ b/indra/newview/llhudrender.cpp
@@ -40,33 +40,36 @@
#include "v3math.h"
#include "llquaternion.h"
#include "llfontgl.h"
-#include "llimagegl.h"
#include "llglheaders.h"
#include "llviewerwindow.h"
+#include "llui.h"
void hud_render_utf8text(const std::string &str, const LLVector3 &pos_agent,
const LLFontGL &font,
const U8 style,
+ const LLFontGL::ShadowType shadow,
const F32 x_offset, const F32 y_offset,
const LLColor4& color,
const BOOL orthographic)
{
LLWString wstr(utf8str_to_wstring(str));
- hud_render_text(wstr, pos_agent, font, style, x_offset, y_offset, color, orthographic);
+ hud_render_text(wstr, pos_agent, font, style, shadow, x_offset, y_offset, color, orthographic);
}
void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent,
const LLFontGL &font,
const U8 style,
+ const LLFontGL::ShadowType shadow,
const F32 x_offset, const F32 y_offset,
const LLColor4& color,
const BOOL orthographic)
{
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
// Do cheap plane culling
- LLVector3 dir_vec = pos_agent - LLViewerCamera::getInstance()->getOrigin();
+ LLVector3 dir_vec = pos_agent - camera->getOrigin();
dir_vec /= dir_vec.magVec();
- if (wstr.empty() || (!orthographic && dir_vec * LLViewerCamera::getInstance()->getAtAxis() <= 0.f))
+ if (wstr.empty() || (!orthographic && dir_vec * camera->getAtAxis() <= 0.f))
{
return;
}
@@ -75,20 +78,20 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent,
LLVector3 up_axis;
if (orthographic)
{
- right_axis.setVec(0.f, -1.f / gViewerWindow->getWindowHeight(), 0.f);
- up_axis.setVec(0.f, 0.f, 1.f / gViewerWindow->getWindowHeight());
+ right_axis.setVec(0.f, -1.f / gViewerWindow->getWorldViewWidthRaw(), 0.f);
+ up_axis.setVec(0.f, 0.f, 1.f / gViewerWindow->getWorldViewHeightRaw());
}
else
{
- LLViewerCamera::getInstance()->getPixelVectors(pos_agent, up_axis, right_axis);
+ camera->getPixelVectors(pos_agent, up_axis, right_axis);
}
- LLCoordFrame render_frame = *LLViewerCamera::getInstance();
+ LLCoordFrame render_frame = *camera;
LLQuaternion rot;
if (!orthographic)
{
rot = render_frame.getQuaternion();
- rot = rot * LLQuaternion(-F_PI_BY_TWO, LLViewerCamera::getInstance()->getYAxis());
- rot = rot * LLQuaternion(F_PI_BY_TWO, LLViewerCamera::getInstance()->getXAxis());
+ rot = rot * LLQuaternion(-F_PI_BY_TWO, camera->getYAxis());
+ rot = rot * LLQuaternion(F_PI_BY_TWO, camera->getXAxis());
}
else
{
@@ -104,26 +107,36 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent,
//get the render_pos in screen space
F64 winX, winY, winZ;
+ LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw();
+ S32 viewport[4];
+ viewport[0] = world_view_rect.mLeft;
+ viewport[1] = world_view_rect.mBottom;
+ viewport[2] = world_view_rect.getWidth();
+ viewport[3] = world_view_rect.getHeight();
gluProject(render_pos.mV[0], render_pos.mV[1], render_pos.mV[2],
- gGLModelView, gGLProjection, (GLint*) gGLViewport,
+ gGLModelView, gGLProjection, (GLint*) viewport,
&winX, &winY, &winZ);
- //fonts all render orthographically, set up projection
+ //fonts all render orthographically, set up projection``
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
LLUI::pushMatrix();
- gViewerWindow->setup2DRender();
+ gl_state_for_2d(world_view_rect.getWidth(), world_view_rect.getHeight());
+ gViewerWindow->setup3DViewport();
+ //gViewerWindow->setup2DRender();
+ winX -= world_view_rect.mLeft;
+ winY -= world_view_rect.mBottom;
LLUI::loadIdentity();
LLUI::translate((F32) winX*1.0f/LLFontGL::sScaleX, (F32) winY*1.0f/(LLFontGL::sScaleY), -(((F32) winZ*2.f)-1.f));
//glRotatef(angle * RAD_TO_DEG, axis.mV[VX], axis.mV[VY], axis.mV[VZ]);
//glScalef(right_scale, up_scale, 1.f);
F32 right_x;
- font.render(wstr, 0, 0, 0, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, wstr.length(), 1000, &right_x);
+ font.render(wstr, 0, 0, 0, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, shadow, wstr.length(), 1000, &right_x);
LLUI::popMatrix();
glMatrixMode(GL_PROJECTION);
diff --git a/indra/newview/llhudrender.h b/indra/newview/llhudrender.h
index 5ca865737f..93de89f7b0 100644
--- a/indra/newview/llhudrender.h
+++ b/indra/newview/llhudrender.h
@@ -43,6 +43,7 @@ void hud_render_text(const LLWString &wstr,
const LLVector3 &pos_agent,
const LLFontGL &font,
const U8 style,
+ const LLFontGL::ShadowType,
const F32 x_offset,
const F32 y_offset,
const LLColor4& color,
@@ -53,6 +54,7 @@ void hud_render_utf8text(const std::string &str,
const LLVector3 &pos_agent,
const LLFontGL &font,
const U8 style,
+ const LLFontGL::ShadowType,
const F32 x_offset,
const F32 y_offset,
const LLColor4& color,
diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp
index 20140073f4..8ad94b957d 100644
--- a/indra/newview/llhudtext.cpp
+++ b/indra/newview/llhudtext.cpp
@@ -39,16 +39,14 @@
#include "llagent.h"
#include "llviewercontrol.h"
-#include "llchatbar.h"
#include "llcriticaldamp.h"
#include "lldrawable.h"
#include "llfontgl.h"
#include "llglheaders.h"
#include "llhudrender.h"
-#include "llimagegl.h"
#include "llui.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewerobject.h"
#include "llvovolume.h"
#include "llviewerwindow.h"
@@ -113,7 +111,6 @@ LLHUDText::LLHUDText(const U8 type) :
mRadius = 0.1f;
LLPointer<LLHUDText> ptr(this);
sTextObjects.insert(ptr);
- //LLDebugVarMessageBox::show("max width", &HUD_TEXT_MAX_WIDTH, 500.f, 1.f);
}
LLHUDText::~LLHUDText()
@@ -159,8 +156,8 @@ BOOL LLHUDText::lineSegmentIntersect(const LLVector3& start, const LLVector3& en
if (mOnHUDAttachment)
{
- x_pixel_vec = LLVector3::y_axis / (F32)gViewerWindow->getWindowWidth();
- y_pixel_vec = LLVector3::z_axis / (F32)gViewerWindow->getWindowHeight();
+ x_pixel_vec = LLVector3::y_axis / (F32)gViewerWindow->getWindowWidthScaled();
+ y_pixel_vec = LLVector3::z_axis / (F32)gViewerWindow->getWindowHeightScaled();
}
else
{
@@ -290,10 +287,10 @@ void LLHUDText::renderText(BOOL for_select)
mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f));
// *TODO: cache this image
- LLUIImagePtr imagep = LLUI::getUIImage("rounded_square.tga");
+ LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square");
// *TODO: make this a per-text setting
- LLColor4 bg_color = gSavedSettings.getColor4("BackgroundChatColor");
+ LLColor4 bg_color = LLUIColorTable::instance().getColor("BackgroundChatColor");
bg_color.setAlpha(gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor);
const S32 border_height = 16;
@@ -319,8 +316,8 @@ void LLHUDText::renderText(BOOL for_select)
if (mOnHUDAttachment)
{
- x_pixel_vec = LLVector3::y_axis / (F32)gViewerWindow->getWindowWidth();
- y_pixel_vec = LLVector3::z_axis / (F32)gViewerWindow->getWindowHeight();
+ x_pixel_vec = LLVector3::y_axis / (F32)gViewerWindow->getWorldViewWidthRaw();
+ y_pixel_vec = LLVector3::z_axis / (F32)gViewerWindow->getWorldViewHeightRaw();
}
else
{
@@ -354,8 +351,8 @@ void LLHUDText::renderText(BOOL for_select)
//if (mOnHUD)
//{
- // render_position.mV[VY] -= fmodf(render_position.mV[VY], 1.f / (F32)gViewerWindow->getWindowWidth());
- // render_position.mV[VZ] -= fmodf(render_position.mV[VZ], 1.f / (F32)gViewerWindow->getWindowHeight());
+ // render_position.mV[VY] -= fmodf(render_position.mV[VY], 1.f / (F32)gViewerWindow->getWindowWidthScaled());
+ // render_position.mV[VZ] -= fmodf(render_position.mV[VZ], 1.f / (F32)gViewerWindow->getWindowHeightScaled());
//}
//else
//{
@@ -509,7 +506,7 @@ void LLHUDText::renderText(BOOL for_select)
LLColor4 label_color(0.f, 0.f, 0.f, 1.f);
label_color.mV[VALPHA] = alpha_factor;
- hud_render_text(segment_iter->getText(), render_position, *fontp, segment_iter->mStyle, x_offset, y_offset, label_color, mOnHUDAttachment);
+ hud_render_text(segment_iter->getText(), render_position, *fontp, segment_iter->mStyle, LLFontGL::NO_SHADOW, x_offset, y_offset, label_color, mOnHUDAttachment);
}
}
@@ -535,9 +532,10 @@ void LLHUDText::renderText(BOOL for_select)
y_offset -= fontp->getLineHeight();
U8 style = segment_iter->mStyle;
+ LLFontGL::ShadowType shadow = LLFontGL::NO_SHADOW;
if (mDropShadow)
{
- style |= LLFontGL::DROP_SHADOW;
+ shadow = LLFontGL::DROP_SHADOW;
}
F32 x_offset;
@@ -553,7 +551,7 @@ void LLHUDText::renderText(BOOL for_select)
text_color = segment_iter->mColor;
text_color.mV[VALPHA] *= alpha_factor;
- hud_render_text(segment_iter->getText(), render_position, *fontp, style, x_offset, y_offset, text_color, mOnHUDAttachment);
+ hud_render_text(segment_iter->getText(), render_position, *fontp, style, shadow, x_offset, y_offset, text_color, mOnHUDAttachment);
}
}
/// Reset the default color to white. The renderer expects this to be the default.
@@ -608,7 +606,7 @@ void LLHUDText::addLine(const LLWString &wstr, const LLColor4& color, const LLFo
U32 line_length = 0;
do
{
- S32 segment_length = mFontp->maxDrawableChars(iter->substr(line_length).c_str(), mUseBubble ? HUD_TEXT_MAX_WIDTH : HUD_TEXT_MAX_WIDTH_NO_BUBBLE, wline.length(), TRUE);
+ S32 segment_length = mFontp->maxDrawableChars(iter->substr(line_length).c_str(), mUseBubble ? HUD_TEXT_MAX_WIDTH : HUD_TEXT_MAX_WIDTH_NO_BUBBLE, wline.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
mTextSegments.push_back(LLHUDTextSegment(iter->substr(line_length, segment_length), style, color));
line_length += segment_length;
}
@@ -644,7 +642,7 @@ void LLHUDText::setLabel(const LLWString &wlabel)
U32 line_length = 0;
do
{
- S32 segment_length = mFontp->maxDrawableChars(iter->substr(line_length).c_str(), mUseBubble ? HUD_TEXT_MAX_WIDTH : HUD_TEXT_MAX_WIDTH_NO_BUBBLE, wstr.length(), TRUE);
+ S32 segment_length = mFontp->maxDrawableChars(iter->substr(line_length).c_str(), mUseBubble ? HUD_TEXT_MAX_WIDTH : HUD_TEXT_MAX_WIDTH_NO_BUBBLE, wstr.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
mLabelSegments.push_back(LLHUDTextSegment(iter->substr(line_length, segment_length), LLFontGL::NORMAL, mColor));
line_length += segment_length;
}
@@ -797,44 +795,22 @@ LLVector2 LLHUDText::updateScreenPos(LLVector2 &offset)
if (!LLViewerCamera::getInstance()->projectPosAgentToScreen(world_pos, screen_pos, FALSE) && mVisibleOffScreen)
{
// bubble off-screen, so find a spot for it along screen edge
- LLVector2 window_center(gViewerWindow->getWindowDisplayWidth() * 0.5f, gViewerWindow->getWindowDisplayHeight() * 0.5f);
- LLVector2 delta_from_center(screen_pos.mX - window_center.mV[VX],
- screen_pos.mY - window_center.mV[VY]);
- delta_from_center.normVec();
-
- F32 camera_aspect = LLViewerCamera::getInstance()->getAspect();
- F32 delta_aspect = llabs(delta_from_center.mV[VX] / delta_from_center.mV[VY]);
- if (camera_aspect / llmax(delta_aspect, 0.001f) > 1.f)
- {
- // camera has wider aspect ratio than offset vector, so clamp to height
- delta_from_center *= llabs(window_center.mV[VY] / delta_from_center.mV[VY]);
- }
- else
- {
- // camera has narrower aspect ratio than offset vector, so clamp to width
- delta_from_center *= llabs(window_center.mV[VX] / delta_from_center.mV[VX]);
- }
-
- screen_pos_vec = window_center + delta_from_center;
- }
- else
- {
- screen_pos_vec.setVec((F32)screen_pos.mX, (F32)screen_pos.mY);
- }
- S32 bottom = STATUS_BAR_HEIGHT;
- if (gChatBar->getVisible())
- {
- bottom += CHAT_BAR_HEIGHT;
+ LLViewerCamera::getInstance()->projectPosAgentToScreenEdge(world_pos, screen_pos);
}
+ screen_pos_vec.setVec((F32)screen_pos.mX, (F32)screen_pos.mY);
+
+ LLRect world_rect = gViewerWindow->getWorldViewRectScaled();
+ S32 bottom = world_rect.mBottom + STATUS_BAR_HEIGHT;
+
LLVector2 screen_center;
- screen_center.mV[VX] = llclamp((F32)screen_pos_vec.mV[VX], mWidth * 0.5f, (F32)gViewerWindow->getWindowDisplayWidth() - mWidth * 0.5f);
+ screen_center.mV[VX] = llclamp((F32)screen_pos_vec.mV[VX], (F32)world_rect.mLeft + mWidth * 0.5f, (F32)world_rect.mRight - mWidth * 0.5f);
if(mVertAlignment == ALIGN_VERT_TOP)
{
screen_center.mV[VY] = llclamp((F32)screen_pos_vec.mV[VY],
(F32)bottom,
- (F32)gViewerWindow->getWindowDisplayHeight() - mHeight - (F32)MENU_BAR_HEIGHT);
+ (F32)world_rect.mTop - mHeight - (F32)MENU_BAR_HEIGHT);
mSoftScreenRect.setLeftTopAndSize(screen_center.mV[VX] - (mWidth + BUFFER_SIZE) * 0.5f,
screen_center.mV[VY] + (mHeight + BUFFER_SIZE), mWidth + BUFFER_SIZE, mHeight + BUFFER_SIZE);
}
@@ -842,7 +818,7 @@ LLVector2 LLHUDText::updateScreenPos(LLVector2 &offset)
{
screen_center.mV[VY] = llclamp((F32)screen_pos_vec.mV[VY],
(F32)bottom + mHeight * 0.5f,
- (F32)gViewerWindow->getWindowDisplayHeight() - mHeight * 0.5f - (F32)MENU_BAR_HEIGHT);
+ (F32)world_rect.mTop - mHeight * 0.5f - (F32)MENU_BAR_HEIGHT);
mSoftScreenRect.setCenterAndSize(screen_center.mV[VX], screen_center.mV[VY], mWidth + BUFFER_SIZE, mHeight + BUFFER_SIZE);
}
@@ -921,7 +897,7 @@ void LLHUDText::updateAll()
std::sort(sVisibleHUDTextObjects.begin(), sVisibleHUDTextObjects.end(), lltextobject_further_away());
// iterate from front to back, and set LOD based on current screen coverage
- F32 screen_area = (F32)(gViewerWindow->getWindowWidth() * gViewerWindow->getWindowHeight());
+ F32 screen_area = (F32)(gViewerWindow->getWindowWidthScaled() * gViewerWindow->getWindowHeightScaled());
F32 current_screen_area = 0.f;
std::vector<LLPointer<LLHUDText> >::reverse_iterator r_it;
for (r_it = sVisibleTextObjects.rbegin(); r_it != sVisibleTextObjects.rend(); ++r_it)
@@ -981,7 +957,7 @@ void LLHUDText::updateAll()
{
continue;
}
- if (src_textp->mSoftScreenRect.rectInRect(&dst_textp->mSoftScreenRect))
+ if (src_textp->mSoftScreenRect.overlaps(dst_textp->mSoftScreenRect))
{
LLRectf intersect_rect = src_textp->mSoftScreenRect;
intersect_rect.intersectWith(dst_textp->mSoftScreenRect);
@@ -1087,6 +1063,8 @@ void LLHUDText::renderAllHUD()
LLVertexBuffer::unbind();
+ LLVertexBuffer::unbind();
+
LLGLState::checkStates();
LLGLState::checkTextureChannels();
LLGLState::checkClientArrays();
diff --git a/indra/newview/llhudtext.h b/indra/newview/llhudtext.h
index 645cbc2698..dc14a8c764 100644
--- a/indra/newview/llhudtext.h
+++ b/indra/newview/llhudtext.h
@@ -33,7 +33,7 @@
#ifndef LL_LLHUDTEXT_H
#define LL_LLHUDTEXT_H
-#include "llmemory.h"
+#include "llpointer.h"
#include "lldarrayptr.h"
#include "llhudobject.h"
diff --git a/indra/newview/llhudview.cpp b/indra/newview/llhudview.cpp
index 198514ce0c..261d9f1df7 100644
--- a/indra/newview/llhudview.cpp
+++ b/indra/newview/llhudview.cpp
@@ -39,46 +39,37 @@
#include "llcoord.h"
// viewer includes
-#include "llagent.h"
#include "llcallingcard.h"
-#include "llcolorscheme.h"
#include "llviewercontrol.h"
#include "llfloaterworldmap.h"
#include "llworldmapview.h"
#include "lltracker.h"
#include "llviewercamera.h"
#include "llui.h"
+#include "lluictrlfactory.h"
LLHUDView *gHUDView = NULL;
const S32 HUD_ARROW_SIZE = 32;
-LLHUDView::LLHUDView()
-: LLPanel()
-{ }
-LLHUDView::~LLHUDView()
-{ }
-// virtual
-void LLHUDView::draw()
+LLHUDView::LLHUDView(const LLRect& r)
{
- LLTracker::drawHUDArrow();
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_hud.xml");
+ setShape(r, true);
}
-
-// public
-const LLColor4& LLHUDView::colorFromType(S32 type)
+LLHUDView::~LLHUDView()
{
- switch (type)
- {
- case 0:
- return LLColor4::green;
- default:
- return LLColor4::black;
- }
}
+// virtual
+void LLHUDView::draw()
+{
+ LLTracker::drawHUDArrow();
+ LLView::draw();
+}
/*virtual*/
BOOL LLHUDView::handleMouseDown(S32 x, S32 y, MASK mask)
@@ -89,4 +80,3 @@ BOOL LLHUDView::handleMouseDown(S32 x, S32 y, MASK mask)
}
return LLView::handleMouseDown(x, y, mask);
}
-
diff --git a/indra/newview/llhudview.h b/indra/newview/llhudview.h
index 7859e7f8be..0946e2c5c8 100644
--- a/indra/newview/llhudview.h
+++ b/indra/newview/llhudview.h
@@ -42,13 +42,11 @@ class LLHUDView
: public LLPanel
{
public:
- LLHUDView();
+ LLHUDView(const LLRect& rect);
virtual ~LLHUDView();
virtual void draw();
- const LLColor4& colorFromType(S32 type);
-
protected:
/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
};
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
new file mode 100644
index 0000000000..73597e7de3
--- /dev/null
+++ b/indra/newview/llimfloater.cpp
@@ -0,0 +1,1044 @@
+/**
+ * @file llimfloater.cpp
+ * @brief LLIMFloater class definition
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llimfloater.h"
+
+#include "llnotificationsutil.h"
+
+#include "llagent.h"
+#include "llappviewer.h"
+#include "llbutton.h"
+#include "llbottomtray.h"
+#include "llchannelmanager.h"
+#include "llchiclet.h"
+#include "llfloaterreg.h"
+#include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container
+#include "lllayoutstack.h"
+#include "lllineeditor.h"
+#include "lllogchat.h"
+#include "llpanelimcontrolpanel.h"
+#include "llscreenchannel.h"
+#include "llsyswellwindow.h"
+#include "lltrans.h"
+#include "llchathistory.h"
+#include "llviewerwindow.h"
+#include "llvoicechannel.h"
+#include "lltransientfloatermgr.h"
+#include "llinventorymodel.h"
+#include "llrootview.h"
+
+#include "llspeakers.h"
+
+
+LLIMFloater::LLIMFloater(const LLUUID& session_id)
+ : LLTransientDockableFloater(NULL, true, session_id),
+ mControlPanel(NULL),
+ mSessionID(session_id),
+ mLastMessageIndex(-1),
+ mDialog(IM_NOTHING_SPECIAL),
+ mChatHistory(NULL),
+ mInputEditor(NULL),
+ mSavedTitle(),
+ mTypingStart(),
+ mShouldSendTypingState(false),
+ mMeTyping(false),
+ mOtherTyping(false),
+ mTypingTimer(),
+ mTypingTimeoutTimer(),
+ mPositioned(false),
+ mSessionInitialized(false)
+{
+ LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(mSessionID);
+ if (im_session)
+ {
+ mSessionInitialized = im_session->mSessionInitialized;
+
+ mDialog = im_session->mType;
+ switch(mDialog){
+ case IM_NOTHING_SPECIAL:
+ case IM_SESSION_P2P_INVITE:
+ mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this);
+ break;
+ case IM_SESSION_CONFERENCE_START:
+ mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this);
+ break;
+ case IM_SESSION_GROUP_START:
+ mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this);
+ break;
+ case IM_SESSION_INVITE:
+ if (gAgent.isInGroup(mSessionID))
+ {
+ mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this);
+ }
+ else
+ {
+ mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this);
+ }
+ break;
+ default: break;
+ }
+ }
+ setOverlapsScreenChannel(true);
+
+ LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this);
+}
+
+void LLIMFloater::onFocusLost()
+{
+ LLIMModel::getInstance()->resetActiveSessionID();
+
+ LLBottomTray::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, false);
+}
+
+void LLIMFloater::onFocusReceived()
+{
+ LLIMModel::getInstance()->setActiveSessionID(mSessionID);
+
+ // return focus to the input field when active tab in the multitab container is clicked.
+ if (isChatMultiTab() && mInputEditor)
+ {
+ mInputEditor->setFocus(TRUE);
+ }
+
+ LLBottomTray::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, true);
+}
+
+// virtual
+void LLIMFloater::onClose(bool app_quitting)
+{
+ setTyping(false);
+
+ // The source of much argument and design thrashing
+ // Should the window hide or the session close when the X is clicked?
+ //
+ // Last change:
+ // EXT-3516 X Button should end IM session, _ button should hide
+ gIMMgr->leaveSession(mSessionID);
+}
+
+/* static */
+void LLIMFloater::newIMCallback(const LLSD& data){
+
+ if (data["num_unread"].asInteger() > 0 || data["from_id"].asUUID().isNull())
+ {
+ LLUUID session_id = data["session_id"].asUUID();
+
+ LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id);
+ if (floater == NULL) return;
+
+ // update if visible, otherwise will be updated when opened
+ if (floater->getVisible())
+ {
+ floater->updateMessages();
+ }
+ }
+}
+
+void LLIMFloater::onVisibilityChange(const LLSD& new_visibility)
+{
+ bool visible = new_visibility.asBoolean();
+
+ LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID);
+
+ if (visible && voice_channel &&
+ voice_channel->getState() == LLVoiceChannel::STATE_CONNECTED)
+ {
+ LLFloaterReg::showInstance("voice_call", mSessionID);
+ }
+ else
+ {
+ LLFloaterReg::hideInstance("voice_call", mSessionID);
+ }
+}
+
+void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata )
+{
+ LLIMFloater* self = (LLIMFloater*) userdata;
+ self->sendMsg();
+ self->setTyping(false);
+}
+
+void LLIMFloater::sendMsg()
+{
+ if (!gAgent.isGodlike()
+ && (mDialog == IM_NOTHING_SPECIAL)
+ && mOtherParticipantUUID.isNull())
+ {
+ llinfos << "Cannot send IM to everyone unless you're a god." << llendl;
+ return;
+ }
+
+ if (mInputEditor)
+ {
+ LLWString text = mInputEditor->getConvertedText();
+ if(!text.empty())
+ {
+ // Truncate and convert to UTF8 for transport
+ std::string utf8_text = wstring_to_utf8str(text);
+ utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1);
+
+ if (mSessionInitialized)
+ {
+ LLIMModel::sendMessage(utf8_text, mSessionID,
+ mOtherParticipantUUID,mDialog);
+ }
+ else
+ {
+ //queue up the message to send once the session is initialized
+ mQueuedMsgsForInit.append(utf8_text);
+ }
+
+ mInputEditor->setText(LLStringUtil::null);
+
+ updateMessages();
+ }
+ }
+}
+
+
+
+LLIMFloater::~LLIMFloater()
+{
+ LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this);
+}
+
+//virtual
+BOOL LLIMFloater::postBuild()
+{
+ // User-resizable control panels in P2P sessions look ugly (EXT-3470).
+ if (mDialog == IM_NOTHING_SPECIAL || mDialog == IM_SESSION_P2P_INVITE)
+ {
+ getChild<LLLayoutStack>("im_panels")->setPanelUserResize("panel_im_control_panel", FALSE);
+ }
+
+ const LLUUID& other_party_id = LLIMModel::getInstance()->getOtherParticipantID(mSessionID);
+ if (other_party_id.notNull())
+ {
+ mOtherParticipantUUID = other_party_id;
+ }
+
+ mControlPanel->setSessionId(mSessionID);
+ mControlPanel->setVisible(gSavedSettings.getBOOL("IMShowControlPanel"));
+
+ LLButton* slide_left = getChild<LLButton>("slide_left_btn");
+ slide_left->setVisible(mControlPanel->getVisible());
+ slide_left->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this));
+
+ LLButton* slide_right = getChild<LLButton>("slide_right_btn");
+ slide_right->setVisible(!mControlPanel->getVisible());
+ slide_right->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this));
+
+ mInputEditor = getChild<LLLineEditor>("chat_editor");
+ mInputEditor->setMaxTextLength(1023);
+ // enable line history support for instant message bar
+ mInputEditor->setEnableLineHistory(TRUE);
+
+
+ mInputEditor->setFocusReceivedCallback( boost::bind(onInputEditorFocusReceived, _1, this) );
+ mInputEditor->setFocusLostCallback( boost::bind(onInputEditorFocusLost, _1, this) );
+ mInputEditor->setKeystrokeCallback( onInputEditorKeystroke, this );
+ mInputEditor->setCommitOnFocusLost( FALSE );
+ mInputEditor->setRevertOnEsc( FALSE );
+ mInputEditor->setReplaceNewlinesWithSpaces( FALSE );
+
+ std::string session_name(LLIMModel::instance().getName(mSessionID));
+
+ mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + session_name);
+
+ setTitle(session_name);
+
+ childSetCommitCallback("chat_editor", onSendMsg, this);
+
+ mChatHistory = getChild<LLChatHistory>("chat_history");
+
+ setDocked(true);
+
+ mTypingStart = LLTrans::getString("IM_typing_start_string");
+
+ // Disable input editor if session cannot accept text
+ LLIMModel::LLIMSession* im_session =
+ LLIMModel::instance().findIMSession(mSessionID);
+ if( im_session && !im_session->mTextIMPossible )
+ {
+ mInputEditor->setEnabled(FALSE);
+ mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label"));
+ }
+
+ //*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla"
+ //see LLFloaterIMPanel for how it is done (IB)
+
+ if(isChatMultiTab())
+ {
+ return LLFloater::postBuild();
+ }
+ else
+ {
+ return LLDockableFloater::postBuild();
+ }
+}
+
+// virtual
+void LLIMFloater::draw()
+{
+ if ( mMeTyping )
+ {
+ // Time out if user hasn't typed for a while.
+ if ( mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS )
+ {
+ setTyping(false);
+ }
+ }
+
+ LLTransientDockableFloater::draw();
+}
+
+
+// static
+void* LLIMFloater::createPanelIMControl(void* userdata)
+{
+ LLIMFloater *self = (LLIMFloater*)userdata;
+ self->mControlPanel = new LLPanelIMControlPanel();
+ self->mControlPanel->setXMLFilename("panel_im_control_panel.xml");
+ return self->mControlPanel;
+}
+
+
+// static
+void* LLIMFloater::createPanelGroupControl(void* userdata)
+{
+ LLIMFloater *self = (LLIMFloater*)userdata;
+ self->mControlPanel = new LLPanelGroupControlPanel(self->mSessionID);
+ self->mControlPanel->setXMLFilename("panel_group_control_panel.xml");
+ return self->mControlPanel;
+}
+
+// static
+void* LLIMFloater::createPanelAdHocControl(void* userdata)
+{
+ LLIMFloater *self = (LLIMFloater*)userdata;
+ self->mControlPanel = new LLPanelAdHocControlPanel(self->mSessionID);
+ self->mControlPanel->setXMLFilename("panel_adhoc_control_panel.xml");
+ return self->mControlPanel;
+}
+
+void LLIMFloater::onSlide()
+{
+ mControlPanel->setVisible(!mControlPanel->getVisible());
+
+ gSavedSettings.setBOOL("IMShowControlPanel", mControlPanel->getVisible());
+
+ getChild<LLButton>("slide_left_btn")->setVisible(mControlPanel->getVisible());
+ getChild<LLButton>("slide_right_btn")->setVisible(!mControlPanel->getVisible());
+
+ LLLayoutStack* stack = getChild<LLLayoutStack>("im_panels");
+ if (stack) stack->setAnimate(true);
+}
+
+//static
+LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
+{
+ if (!gIMMgr->hasSession(session_id)) return NULL;
+
+ if(!isChatMultiTab())
+ {
+ //hide all
+ LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel");
+ for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin();
+ iter != inst_list.end(); ++iter)
+ {
+ LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter);
+ if (floater && floater->isDocked())
+ {
+ floater->setVisible(false);
+ }
+ }
+ }
+
+ bool exist = findInstance(session_id);
+
+ LLIMFloater* floater = getInstance(session_id);
+ if (!floater) return NULL;
+
+ if(isChatMultiTab())
+ {
+ LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance();
+
+ // do not add existed floaters to avoid adding torn off instances
+ if (!exist)
+ {
+ // LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END;
+ // TODO: mantipov: use LLTabContainer::RIGHT_OF_CURRENT if it exists
+ LLTabContainer::eInsertionPoint i_pt = LLTabContainer::END;
+
+ if (floater_container)
+ {
+ floater_container->addFloater(floater, TRUE, i_pt);
+ }
+ }
+
+ if (floater_container)
+ {
+ //selecting the panel resets a chiclet's counter
+ floater_container->selectFloater(floater);
+ floater_container->setVisible(TRUE);
+ }
+ }
+ else
+ {
+ // Docking may move chat window, hide it before moving, or user will see how window "jumps"
+ floater->setVisible(false);
+
+ if (floater->getDockControl() == NULL)
+ {
+ LLChiclet* chiclet =
+ LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLChiclet>(
+ session_id);
+ if (chiclet == NULL)
+ {
+ llerror("Dock chiclet for LLIMFloater doesn't exists", 0);
+ }
+ else
+ {
+ LLBottomTray::getInstance()->getChicletPanel()->scrollToChiclet(chiclet);
+ }
+
+ floater->setDockControl(new LLDockControl(chiclet, floater, floater->getDockTongue(),
+ LLDockControl::TOP, boost::bind(&LLIMFloater::getAllowedRect, floater, _1)));
+ }
+
+ // window is positioned, now we can show it.
+ }
+ floater->setVisible(TRUE);
+
+ return floater;
+}
+
+void LLIMFloater::getAllowedRect(LLRect& rect)
+{
+ rect = gViewerWindow->getWorldViewRectRaw();
+ static S32 right_padding = 0;
+ if (right_padding == 0)
+ {
+ LLPanel* side_bar_tabs =
+ gViewerWindow->getRootView()->getChild<LLPanel> (
+ "side_bar_tabs");
+ right_padding = side_bar_tabs->getRect().getWidth();
+ LLTransientFloaterMgr::getInstance()->addControlView(side_bar_tabs);
+ }
+ rect.mRight -= right_padding;
+}
+
+void LLIMFloater::setDocked(bool docked, bool pop_on_undock)
+{
+ // update notification channel state
+ LLNotificationsUI::LLScreenChannel* channel = dynamic_cast<LLNotificationsUI::LLScreenChannel*>
+ (LLNotificationsUI::LLChannelManager::getInstance()->
+ findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
+
+ if(!isChatMultiTab())
+ {
+ LLTransientDockableFloater::setDocked(docked, pop_on_undock);
+ }
+
+ // update notification channel state
+ if(channel)
+ {
+ channel->updateShowToastsState();
+ channel->redrawToasts();
+ }
+}
+
+void LLIMFloater::setVisible(BOOL visible)
+{
+ LLNotificationsUI::LLScreenChannel* channel = dynamic_cast<LLNotificationsUI::LLScreenChannel*>
+ (LLNotificationsUI::LLChannelManager::getInstance()->
+ findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
+ LLTransientDockableFloater::setVisible(visible);
+
+ // update notification channel state
+ if(channel)
+ {
+ channel->updateShowToastsState();
+ channel->redrawToasts();
+ }
+
+ if (visible && mChatHistory && mInputEditor)
+ {
+ //only if floater was construced and initialized from xml
+ updateMessages();
+ mInputEditor->setFocus(TRUE);
+ }
+
+ if(!visible)
+ {
+ LLIMChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(mSessionID);
+ if(chiclet)
+ {
+ chiclet->setToggleState(false);
+ }
+ }
+}
+
+//static
+bool LLIMFloater::toggle(const LLUUID& session_id)
+{
+ if(!isChatMultiTab())
+ {
+ LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id);
+ if (floater && floater->getVisible() && floater->hasFocus())
+ {
+ // clicking on chiclet to close floater just hides it to maintain existing
+ // scroll/text entry state
+ floater->setVisible(false);
+ return false;
+ }
+ else if(floater && (!floater->isDocked() || floater->getVisible() && !floater->hasFocus()))
+ {
+ floater->setVisible(TRUE);
+ floater->setFocus(TRUE);
+ return true;
+ }
+ }
+
+ // ensure the list of messages is updated when floater is made visible
+ show(session_id);
+ return true;
+}
+
+//static
+LLIMFloater* LLIMFloater::findInstance(const LLUUID& session_id)
+{
+ return LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id);
+}
+
+LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id)
+{
+ return LLFloaterReg::getTypedInstance<LLIMFloater>("impanel", session_id);
+}
+
+void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)
+{
+ mSessionInitialized = true;
+
+ //will be different only for an ad-hoc im session
+ if (mSessionID != im_session_id)
+ {
+ mSessionID = im_session_id;
+ setKey(im_session_id);
+ mControlPanel->setSessionId(im_session_id);
+ }
+
+ //*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB)
+
+
+ //need to send delayed messaged collected while waiting for session initialization
+ if (!mQueuedMsgsForInit.size()) return;
+ LLSD::array_iterator iter;
+ for ( iter = mQueuedMsgsForInit.beginArray();
+ iter != mQueuedMsgsForInit.endArray();
+ ++iter)
+ {
+ LLIMModel::sendMessage(iter->asString(), mSessionID,
+ mOtherParticipantUUID, mDialog);
+ }
+}
+
+void LLIMFloater::updateMessages()
+{
+ bool use_plain_text_chat_history = gSavedSettings.getBOOL("PlainTextChatHistory");
+
+ std::list<LLSD> messages;
+ LLIMModel::instance().getMessages(mSessionID, messages, mLastMessageIndex+1);
+
+ if (messages.size())
+ {
+// LLUIColor chat_color = LLUIColorTable::instance().getColor("IMChatColor");
+
+ std::ostringstream message;
+ std::list<LLSD>::const_reverse_iterator iter = messages.rbegin();
+ std::list<LLSD>::const_reverse_iterator iter_end = messages.rend();
+ for (; iter != iter_end; ++iter)
+ {
+ LLSD msg = *iter;
+
+ std::string time = msg["time"].asString();
+ LLUUID from_id = msg["from_id"].asUUID();
+ std::string from = msg["from"].asString();
+ std::string message = msg["message"].asString();
+
+ LLChat chat;
+ chat.mFromID = from_id;
+ chat.mFromName = from;
+ chat.mText = message;
+ chat.mTimeStr = time;
+
+ mChatHistory->appendMessage(chat, use_plain_text_chat_history);
+ mLastMessageIndex = msg["index"].asInteger();
+ }
+ }
+}
+
+// static
+void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata )
+{
+ LLIMFloater* self= (LLIMFloater*) userdata;
+
+ // Allow enabling the LLIMFloater input editor only if session can accept text
+ LLIMModel::LLIMSession* im_session =
+ LLIMModel::instance().findIMSession(self->mSessionID);
+ //TODO: While disabled lllineeditor can receive focus we need to check if it is enabled (EK)
+ if( im_session && im_session->mTextIMPossible && self->mInputEditor->getEnabled())
+ {
+ //in disconnected state IM input editor should be disabled
+ self->mInputEditor->setEnabled(!gDisconnected);
+ }
+
+ // when IM Floater is a part of the multitab container LLTabContainer set focus to the first
+ // child on tab button's mouse up. This leads input field lost focus. See EXT-3852.
+ if (isChatMultiTab())
+ {
+ // So, clear control captured mouse to prevent LLTabContainer set focus on the panel's first child.
+ // do not pass self->mInputEditor, this leads to have "Edit Text" mouse pointer wherever it is.
+ gFocusMgr.setMouseCapture(NULL);
+ }
+}
+
+// static
+void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userdata)
+{
+ LLIMFloater* self = (LLIMFloater*) userdata;
+ self->setTyping(false);
+}
+
+// static
+void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata)
+{
+ LLIMFloater* self = (LLIMFloater*)userdata;
+ std::string text = self->mInputEditor->getText();
+ if (!text.empty())
+ {
+ self->setTyping(true);
+ }
+ else
+ {
+ // Deleting all text counts as stopping typing.
+ self->setTyping(false);
+ }
+}
+
+void LLIMFloater::setTyping(bool typing)
+{
+ if ( typing )
+ {
+ // Started or proceeded typing, reset the typing timeout timer
+ mTypingTimeoutTimer.reset();
+ }
+
+ if ( mMeTyping != typing )
+ {
+ // Typing state is changed
+ mMeTyping = typing;
+ // So, should send current state
+ mShouldSendTypingState = true;
+ // In case typing is started, send state after some delay
+ mTypingTimer.reset();
+ }
+
+ // Don't want to send typing indicators to multiple people, potentially too
+ // much network traffic. Only send in person-to-person IMs.
+ if ( mShouldSendTypingState && mDialog == IM_NOTHING_SPECIAL )
+ {
+ if ( mMeTyping )
+ {
+ if ( mTypingTimer.getElapsedTimeF32() > 1.f )
+ {
+ // Still typing, send 'start typing' notification
+ LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, TRUE);
+ mShouldSendTypingState = false;
+ }
+ }
+ else
+ {
+ // Send 'stop typing' notification immediately
+ LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, FALSE);
+ mShouldSendTypingState = false;
+ }
+ }
+
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+ if (speaker_mgr)
+ speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE);
+
+}
+
+void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing)
+{
+ if ( typing )
+ {
+ // other user started typing
+ addTypingIndicator(im_info);
+ }
+ else
+ {
+ // other user stopped typing
+ removeTypingIndicator(im_info);
+ }
+}
+
+void LLIMFloater::processAgentListUpdates(const LLSD& body)
+{
+ if ( !body.isMap() ) return;
+
+ if ( body.has("agent_updates") && body["agent_updates"].isMap() )
+ {
+ LLSD agent_data = body["agent_updates"].get(gAgentID.asString());
+ if (agent_data.isMap() && agent_data.has("info"))
+ {
+ LLSD agent_info = agent_data["info"];
+
+ if (agent_info.has("mutes"))
+ {
+ BOOL moderator_muted_text = agent_info["mutes"]["text"].asBoolean();
+ mInputEditor->setEnabled(!moderator_muted_text);
+ std::string label;
+ if (moderator_muted_text)
+ label = LLTrans::getString("IM_muted_text_label");
+ else
+ label = LLTrans::getString("IM_to_label") + " " + LLIMModel::instance().getName(mSessionID);
+ mInputEditor->setLabel(label);
+
+ if (moderator_muted_text)
+ LLNotificationsUtil::add("TextChatIsMutedByModerator");
+ }
+ }
+ }
+}
+
+void LLIMFloater::updateChatHistoryStyle()
+{
+ mChatHistory->clear();
+ mLastMessageIndex = -1;
+ updateMessages();
+}
+
+void LLIMFloater::processChatHistoryStyleUpdate(const LLSD& newvalue)
+{
+ LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel");
+ for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin();
+ iter != inst_list.end(); ++iter)
+ {
+ LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter);
+ if (floater)
+ {
+ floater->updateChatHistoryStyle();
+ }
+ }
+
+}
+
+void LLIMFloater::processSessionUpdate(const LLSD& session_update)
+{
+ // *TODO : verify following code when moderated mode will be implemented
+ if ( false && session_update.has("moderated_mode") &&
+ session_update["moderated_mode"].has("voice") )
+ {
+ BOOL voice_moderated = session_update["moderated_mode"]["voice"];
+ const std::string session_label = LLIMModel::instance().getName(mSessionID);
+
+ if (voice_moderated)
+ {
+ setTitle(session_label + std::string(" ") + LLTrans::getString("IM_moderated_chat_label"));
+ }
+ else
+ {
+ setTitle(session_label);
+ }
+
+ // *TODO : uncomment this when/if LLPanelActiveSpeakers panel will be added
+ //update the speakers dropdown too
+ //mSpeakerPanel->setVoiceModerationCtrlMode(voice_moderated);
+ }
+}
+
+BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask,
+ BOOL drop, EDragAndDropType cargo_type,
+ void *cargo_data, EAcceptance *accept,
+ std::string& tooltip_msg)
+{
+
+ if (mDialog == IM_NOTHING_SPECIAL)
+ {
+ LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop,
+ cargo_type, cargo_data, accept);
+ }
+
+ // handle case for dropping calling cards (and folders of calling cards) onto invitation panel for invites
+ else if (isInviteAllowed())
+ {
+ *accept = ACCEPT_NO;
+
+ if (cargo_type == DAD_CALLINGCARD)
+ {
+ if (dropCallingCard((LLInventoryItem*)cargo_data, drop))
+ {
+ *accept = ACCEPT_YES_MULTI;
+ }
+ }
+ else if (cargo_type == DAD_CATEGORY)
+ {
+ if (dropCategory((LLInventoryCategory*)cargo_data, drop))
+ {
+ *accept = ACCEPT_YES_MULTI;
+ }
+ }
+ }
+ return TRUE;
+}
+
+BOOL LLIMFloater::dropCallingCard(LLInventoryItem* item, BOOL drop)
+{
+ BOOL rv = isInviteAllowed();
+ if(rv && item && item->getCreatorUUID().notNull())
+ {
+ if(drop)
+ {
+ std::vector<LLUUID> ids;
+ ids.push_back(item->getCreatorUUID());
+ inviteToSession(ids);
+ }
+ }
+ else
+ {
+ // set to false if creator uuid is null.
+ rv = FALSE;
+ }
+ return rv;
+}
+
+BOOL LLIMFloater::dropCategory(LLInventoryCategory* category, BOOL drop)
+{
+ BOOL rv = isInviteAllowed();
+ if(rv && category)
+ {
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ LLUniqueBuddyCollector buddies;
+ gInventory.collectDescendentsIf(category->getUUID(),
+ cats,
+ items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ buddies);
+ S32 count = items.count();
+ if(count == 0)
+ {
+ rv = FALSE;
+ }
+ else if(drop)
+ {
+ std::vector<LLUUID> ids;
+ ids.reserve(count);
+ for(S32 i = 0; i < count; ++i)
+ {
+ ids.push_back(items.get(i)->getCreatorUUID());
+ }
+ inviteToSession(ids);
+ }
+ }
+ return rv;
+}
+
+BOOL LLIMFloater::isInviteAllowed() const
+{
+
+ return ( (IM_SESSION_CONFERENCE_START == mDialog)
+ || (IM_SESSION_INVITE == mDialog) );
+}
+
+class LLSessionInviteResponder : public LLHTTPClient::Responder
+{
+public:
+ LLSessionInviteResponder(const LLUUID& session_id)
+ {
+ mSessionID = session_id;
+ }
+
+ void error(U32 statusNum, const std::string& reason)
+ {
+ llinfos << "Error inviting all agents to session" << llendl;
+ //throw something back to the viewer here?
+ }
+
+private:
+ LLUUID mSessionID;
+};
+
+BOOL LLIMFloater::inviteToSession(const std::vector<LLUUID>& ids)
+{
+ LLViewerRegion* region = gAgent.getRegion();
+ if (!region)
+ {
+ return FALSE;
+ }
+
+ S32 count = ids.size();
+
+ if( isInviteAllowed() && (count > 0) )
+ {
+ llinfos << "LLIMFloater::inviteToSession() - inviting participants" << llendl;
+
+ std::string url = region->getCapability("ChatSessionRequest");
+
+ LLSD data;
+
+ data["params"] = LLSD::emptyArray();
+ for (int i = 0; i < count; i++)
+ {
+ data["params"].append(ids[i]);
+ }
+
+ data["method"] = "invite";
+ data["session-id"] = mSessionID;
+ LLHTTPClient::post(
+ url,
+ data,
+ new LLSessionInviteResponder(
+ mSessionID));
+ }
+ else
+ {
+ llinfos << "LLIMFloater::inviteToSession -"
+ << " no need to invite agents for "
+ << mDialog << llendl;
+ // successful add, because everyone that needed to get added
+ // was added.
+ }
+
+ return TRUE;
+}
+
+void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info)
+{
+ // We may have lost a "stop-typing" packet, don't add it twice
+ if ( im_info && !mOtherTyping )
+ {
+ mOtherTyping = true;
+
+ // Create typing is started title string
+ LLUIString typing_start(mTypingStart);
+ typing_start.setArg("[NAME]", im_info->mName);
+
+ // Save and set new title
+ mSavedTitle = getTitle();
+ setTitle (typing_start);
+
+ // Update speaker
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+ if ( speaker_mgr )
+ {
+ speaker_mgr->setSpeakerTyping(im_info->mFromID, TRUE);
+ }
+ }
+}
+
+void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info)
+{
+ if ( mOtherTyping )
+ {
+ mOtherTyping = false;
+
+ // Revert the title to saved one
+ setTitle(mSavedTitle);
+
+ if ( im_info )
+ {
+ // Update speaker
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+ if ( speaker_mgr )
+ {
+ speaker_mgr->setSpeakerTyping(im_info->mFromID, FALSE);
+ }
+ }
+
+ }
+}
+
+// static
+bool LLIMFloater::isChatMultiTab()
+{
+ // Restart is required in order to change chat window type.
+ static bool is_single_window = gSavedSettings.getS32("ChatWindow") == 1;
+ return is_single_window;
+}
+
+// static
+void LLIMFloater::initIMFloater()
+{
+ // This is called on viewer start up
+ // init chat window type before user changed it in preferences
+ isChatMultiTab();
+}
+
+//static
+void LLIMFloater::sRemoveTypingIndicator(const LLSD& data)
+{
+ LLUUID session_id = data["session_id"];
+ if (session_id.isNull()) return;
+
+ LLUUID from_id = data["from_id"];
+ if (gAgentID == from_id || LLUUID::null == from_id) return;
+
+ LLIMFloater* floater = LLIMFloater::findInstance(session_id);
+ if (!floater) return;
+
+ if (IM_NOTHING_SPECIAL != floater->mDialog) return;
+
+ floater->removeTypingIndicator();
+}
+
+void LLIMFloater::onIMChicletCreated( const LLUUID& session_id )
+{
+
+ if (isChatMultiTab())
+ {
+ LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance();
+ if (!im_box) return;
+
+ if (LLIMFloater::findInstance(session_id)) return;
+
+ LLIMFloater* new_tab = LLIMFloater::getInstance(session_id);
+
+ im_box->addFloater(new_tab, FALSE, LLTabContainer::END);
+ }
+
+}
diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h
new file mode 100644
index 0000000000..0ca0325451
--- /dev/null
+++ b/indra/newview/llimfloater.h
@@ -0,0 +1,172 @@
+/**
+ * @file llimfloater.h
+ * @brief LLIMFloater class definition
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_IMFLOATER_H
+#define LL_IMFLOATER_H
+
+#include "llinstantmessage.h"
+#include "lllogchat.h"
+#include "lltooldraganddrop.h"
+#include "lltransientdockablefloater.h"
+
+class LLLineEditor;
+class LLPanelChatControlPanel;
+class LLChatHistory;
+class LLInventoryItem;
+class LLInventoryCategory;
+
+/**
+ * Individual IM window that appears at the bottom of the screen,
+ * optionally "docked" to the bottom tray.
+ */
+class LLIMFloater : public LLTransientDockableFloater
+{
+public:
+ LLIMFloater(const LLUUID& session_id);
+
+ virtual ~LLIMFloater();
+
+ // LLView overrides
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void setVisible(BOOL visible);
+ // Check typing timeout timer.
+ /*virtual*/ void draw();
+
+ // LLFloater overrides
+ /*virtual*/ void onClose(bool app_quitting);
+ /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true);
+
+ // Make IM conversion visible and update the message history
+ static LLIMFloater* show(const LLUUID& session_id);
+
+ // Toggle panel specified by session_id
+ // Returns true iff panel became visible
+ static bool toggle(const LLUUID& session_id);
+
+ static LLIMFloater* findInstance(const LLUUID& session_id);
+
+ static LLIMFloater* getInstance(const LLUUID& session_id);
+
+ void sessionInitReplyReceived(const LLUUID& im_session_id);
+
+ // get new messages from LLIMModel
+ void updateMessages();
+ static void onSendMsg( LLUICtrl*, void*);
+ void sendMsg();
+
+ // callback for LLIMModel on new messages
+ // route to specific floater if it is visible
+ static void newIMCallback(const LLSD& data);
+
+ // called when docked floater's position has been set by chiclet
+ void setPositioned(bool b) { mPositioned = b; };
+
+ void onVisibilityChange(const LLSD& new_visibility);
+ void processIMTyping(const LLIMInfo* im_info, BOOL typing);
+ void processAgentListUpdates(const LLSD& body);
+ void processSessionUpdate(const LLSD& session_update);
+
+ void updateChatHistoryStyle();
+ static void processChatHistoryStyleUpdate(const LLSD& newvalue);
+
+ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
+ BOOL drop, EDragAndDropType cargo_type,
+ void *cargo_data, EAcceptance *accept,
+ std::string& tooltip_msg);
+
+ /**
+ * Returns true if chat is displayed in multi tabbed floater
+ * false if chat is displayed in multiple windows
+ */
+ static bool isChatMultiTab();
+
+ static void initIMFloater();
+
+ //used as a callback on receiving new IM message
+ static void sRemoveTypingIndicator(const LLSD& data);
+
+ static void onIMChicletCreated(const LLUUID& session_id);
+
+ virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; }
+
+private:
+ // process focus events to set a currently active session
+ /* virtual */ void onFocusLost();
+ /* virtual */ void onFocusReceived();
+
+ BOOL dropCallingCard(LLInventoryItem* item, BOOL drop);
+ BOOL dropCategory(LLInventoryCategory* category, BOOL drop);
+
+ BOOL isInviteAllowed() const;
+ BOOL inviteToSession(const std::vector<LLUUID>& agent_ids);
+
+ static void onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata );
+ static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata);
+ static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata);
+ void setTyping(bool typing);
+ void onSlide();
+ static void* createPanelIMControl(void* userdata);
+ static void* createPanelGroupControl(void* userdata);
+ static void* createPanelAdHocControl(void* userdata);
+ // gets a rect that bounds possible positions for the LLIMFloater on a screen (EXT-1111)
+ void getAllowedRect(LLRect& rect);
+
+ // Add the "User is typing..." indicator.
+ void addTypingIndicator(const LLIMInfo* im_info);
+
+ // Remove the "User is typing..." indicator.
+ void removeTypingIndicator(const LLIMInfo* im_info = NULL);
+
+ LLPanelChatControlPanel* mControlPanel;
+ LLUUID mSessionID;
+ S32 mLastMessageIndex;
+
+ EInstantMessage mDialog;
+ LLUUID mOtherParticipantUUID;
+ LLChatHistory* mChatHistory;
+ LLLineEditor* mInputEditor;
+ bool mPositioned;
+
+ std::string mSavedTitle;
+ LLUIString mTypingStart;
+ bool mMeTyping;
+ bool mOtherTyping;
+ bool mShouldSendTypingState;
+ LLFrameTimer mTypingTimer;
+ LLFrameTimer mTypingTimeoutTimer;
+
+ bool mSessionInitialized;
+ LLSD mQueuedMsgsForInit;
+};
+
+
+#endif // LL_IMFLOATER_H
diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp
new file mode 100644
index 0000000000..06a7b4a29c
--- /dev/null
+++ b/indra/newview/llimfloatercontainer.cpp
@@ -0,0 +1,181 @@
+/**
+ * @file llimfloatercontainer.cpp
+ * @brief Multifloater containing active IM sessions in separate tab container tabs
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llimfloatercontainer.h"
+#include "llfloaterreg.h"
+#include "llimview.h"
+#include "llavatariconctrl.h"
+#include "llagent.h"
+
+//
+// LLIMFloaterContainer
+//
+LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed)
+: LLMultiFloater(seed)
+{
+ mAutoResize = FALSE;
+}
+
+LLIMFloaterContainer::~LLIMFloaterContainer()
+{
+ LLGroupMgr::getInstance()->removeObserver(this);
+}
+
+BOOL LLIMFloaterContainer::postBuild()
+{
+ // Do not call base postBuild to not connect to mCloseSignal to not close all floaters via Close button
+ // mTabContainer will be initialized in LLMultiFloater::addChild()
+ return TRUE;
+}
+
+void LLIMFloaterContainer::onOpen(const LLSD& key)
+{
+ LLMultiFloater::onOpen(key);
+/*
+ if (key.isDefined())
+ {
+ LLIMFloater* im_floater = LLIMFloater::findInstance(key.asUUID());
+ if (im_floater)
+ {
+ im_floater->openFloater();
+ }
+ }
+*/
+}
+
+void LLIMFloaterContainer::addFloater(LLFloater* floaterp,
+ BOOL select_added_floater,
+ LLTabContainer::eInsertionPoint insertion_point)
+{
+ if(!floaterp) return;
+
+ // already here
+ if (floaterp->getHost() == this)
+ {
+ openFloater(floaterp->getKey());
+ return;
+ }
+
+ LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point);
+
+ LLUUID session_id = floaterp->getKey();
+
+ if(gAgent.isInGroup(session_id))
+ {
+ mSessions[session_id] = floaterp;
+ mID = session_id;
+ mGroupID.push_back(session_id);
+ LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(session_id);
+ LLGroupMgr* gm = LLGroupMgr::getInstance();
+ gm->addObserver(this);
+
+ if (group_data && group_data->mInsigniaID.notNull())
+ {
+ mTabContainer->setTabImage(get_ptr_in_map(mSessions, session_id), group_data->mInsigniaID);
+ }
+ else
+ {
+ gm->sendGroupPropertiesRequest(session_id);
+ }
+ }
+ else
+ {
+ LLUUID avatar_id = LLIMModel::getInstance()->getOtherParticipantID(session_id);
+ LLAvatarPropertiesProcessor& app = LLAvatarPropertiesProcessor::instance();
+ app.addObserver(avatar_id, this);
+ floaterp->mCloseSignal.connect(boost::bind(&LLIMFloaterContainer::onCloseFloater, this, avatar_id));
+ mSessions[avatar_id] = floaterp;
+
+ LLUUID* icon_id_ptr = LLAvatarIconIDCache::getInstance()->get(avatar_id);
+ if(!icon_id_ptr)
+ {
+ app.sendAvatarPropertiesRequest(avatar_id);
+ }
+ else
+ {
+ mTabContainer->setTabImage(floaterp, *icon_id_ptr);
+ }
+ }
+}
+
+void LLIMFloaterContainer::processProperties(void* data, enum EAvatarProcessorType type)
+{
+ if (APT_PROPERTIES == type)
+ {
+ LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data);
+ if (avatar_data)
+ {
+ LLUUID avatar_id = avatar_data->avatar_id;
+ if(avatar_data->image_id != *LLAvatarIconIDCache::getInstance()->get(avatar_id))
+ {
+ LLAvatarIconIDCache::getInstance()->add(avatar_id,avatar_data->image_id);
+ }
+ mTabContainer->setTabImage(get_ptr_in_map(mSessions, avatar_id), avatar_data->image_id);
+ }
+ }
+}
+
+void LLIMFloaterContainer::changed(LLGroupChange gc)
+{
+ if (GC_PROPERTIES == gc)
+ {
+ for(groupIDs_t::iterator it = mGroupID.begin(); it!=mGroupID.end(); it++)
+ {
+ LLUUID group_id = *it;
+ LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(group_id);
+ if (group_data && group_data->mInsigniaID.notNull())
+ {
+ mTabContainer->setTabImage(get_ptr_in_map(mSessions, group_id), group_data->mInsigniaID);
+ }
+ }
+ }
+}
+
+void LLIMFloaterContainer::onCloseFloater(LLUUID id)
+{
+ LLAvatarPropertiesProcessor::instance().removeObserver(id, this);
+}
+
+LLIMFloaterContainer* LLIMFloaterContainer::findInstance()
+{
+ return LLFloaterReg::findTypedInstance<LLIMFloaterContainer>("im_container");
+}
+
+LLIMFloaterContainer* LLIMFloaterContainer::getInstance()
+{
+ return LLFloaterReg::getTypedInstance<LLIMFloaterContainer>("im_container");
+}
+
+// EOF
diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h
new file mode 100644
index 0000000000..1333b098bc
--- /dev/null
+++ b/indra/newview/llimfloatercontainer.h
@@ -0,0 +1,78 @@
+/**
+ * @file llimfloatercontainer.h
+ * @brief Multifloater containing active IM sessions in separate tab container tabs
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLIMFLOATERCONTAINER_H
+#define LL_LLIMFLOATERCONTAINER_H
+
+#include <map>
+#include <vector>
+
+#include "llfloater.h"
+#include "llmultifloater.h"
+#include "llavatarpropertiesprocessor.h"
+#include "llgroupmgr.h"
+
+class LLTabContainer;
+
+class LLIMFloaterContainer : public LLMultiFloater, public LLAvatarPropertiesObserver, public LLGroupMgrObserver
+{
+public:
+ LLIMFloaterContainer(const LLSD& seed);
+ virtual ~LLIMFloaterContainer();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ /*virtual*/ void addFloater(LLFloater* floaterp,
+ BOOL select_added_floater,
+ LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END);
+
+ void processProperties(void* data, EAvatarProcessorType type);
+ void changed(LLGroupChange gc);
+
+ static LLFloater* getCurrentVoiceFloater();
+
+ static LLIMFloaterContainer* findInstance();
+
+ static LLIMFloaterContainer* getInstance();
+
+private:
+ typedef std::map<LLUUID,LLPanel*> avatarID_panel_map_t;
+ avatarID_panel_map_t mSessions;
+
+ typedef std::vector<LLUUID> groupIDs_t;
+ groupIDs_t mGroupID;
+
+ void onCloseFloater(LLUUID avatar_id);
+};
+
+#endif // LL_LLIMFLOATERCONTAINER_H
diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp
new file mode 100644
index 0000000000..1cbd273e96
--- /dev/null
+++ b/indra/newview/llimhandler.cpp
@@ -0,0 +1,136 @@
+/**
+ * @file llimhandler.cpp
+ * @brief Notification Handler Class for IM notifications
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#include "llnotificationhandler.h"
+
+#include "llagentdata.h"
+#include "llnotifications.h"
+#include "lltoastimpanel.h"
+#include "llviewerwindow.h"
+
+using namespace LLNotificationsUI;
+
+//--------------------------------------------------------------------------
+LLIMHandler::LLIMHandler(e_notification_type type, const LLSD& id)
+{
+ mType = type;
+
+ // Getting a Channel for our notifications
+ mChannel = LLChannelManager::getInstance()->createNotificationChannel();
+}
+
+//--------------------------------------------------------------------------
+LLIMHandler::~LLIMHandler()
+{
+}
+
+//--------------------------------------------------------------------------
+void LLIMHandler::initChannel()
+{
+ S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin");
+ S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
+ mChannel->init(channel_right_bound - channel_width, channel_right_bound);
+}
+
+//--------------------------------------------------------------------------
+bool LLIMHandler::processNotification(const LLSD& notify)
+{
+ if(!mChannel)
+ {
+ return false;
+ }
+
+ LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
+
+ if(!notification)
+ return false;
+
+ // arrange a channel on a screen
+ if(!mChannel->getVisible())
+ {
+ initChannel();
+ }
+
+ if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change")
+ {
+ LLSD substitutions = notification->getSubstitutions();
+
+ // According to comments in LLIMMgr::addMessage(), if we get message
+ // from ourselves, the sender id is set to null. This fixes EXT-875.
+ LLUUID avatar_id = substitutions["FROM_ID"].asUUID();
+ if (avatar_id.isNull())
+ avatar_id = gAgentID;
+
+ LLToastIMPanel::Params im_p;
+ im_p.notification = notification;
+ im_p.avatar_id = avatar_id;
+ im_p.from = substitutions["FROM"].asString();
+ im_p.time = substitutions["TIME"].asString();
+ im_p.message = substitutions["MESSAGE"].asString();
+ im_p.session_id = substitutions["SESSION_ID"].asUUID();
+
+ LLToastIMPanel* im_box = new LLToastIMPanel(im_p);
+
+ LLToast::Params p;
+ p.notif_id = notification->getID();
+ p.session_id = im_p.session_id;
+ p.notification = notification;
+ p.panel = im_box;
+ p.can_be_stored = false;
+ p.on_delete_toast = boost::bind(&LLIMHandler::onDeleteToast, this, _1);
+ LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
+ if(channel)
+ channel->addToast(p);
+
+ // send a signal to the counter manager;
+ mNewNotificationSignal();
+ }
+ else if (notify["sigtype"].asString() == "delete")
+ {
+ mChannel->killToastByNotificationID(notification->getID());
+ }
+ return true;
+}
+
+//--------------------------------------------------------------------------
+void LLIMHandler::onDeleteToast(LLToast* toast)
+{
+ // send a signal to the counter manager
+ mDelNotificationSignal();
+}
+
+//--------------------------------------------------------------------------
+
+
diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp
index 0586409283..4bdf5f42dc 100644
--- a/indra/newview/llimpanel.cpp
+++ b/indra/newview/llimpanel.cpp
@@ -35,32 +35,39 @@
#include "llimpanel.h"
#include "indra_constants.h"
+#include "llfloaterreg.h"
#include "llfocusmgr.h"
#include "llfontgl.h"
#include "llrect.h"
#include "llerror.h"
+#include "llmultifloater.h"
#include "llstring.h"
#include "message.h"
#include "lltextbox.h"
#include "llagent.h"
#include "llbutton.h"
+#include "llbottomtray.h"
#include "llcallingcard.h"
+#include "llchannelmanager.h"
#include "llchat.h"
+#include "llchiclet.h"
#include "llconsole.h"
+#include "llgroupactions.h"
#include "llfloater.h"
-#include "llfloatergroupinfo.h"
-#include "llimview.h"
+#include "llfloateractivespeakers.h"
+#include "llavataractions.h"
#include "llinventory.h"
#include "llinventorymodel.h"
-#include "llinventoryview.h"
-#include "llfloateractivespeakers.h"
-#include "llfloateravatarinfo.h"
-#include "llfloaterchat.h"
+#include "llfloaterinventory.h"
+#include "lliconctrl.h"
#include "llkeyboard.h"
#include "lllineeditor.h"
-#include "llnotify.h"
+#include "llpanelimcontrolpanel.h"
+#include "llrecentpeople.h"
#include "llresmgr.h"
+#include "lltooldraganddrop.h"
+#include "lltrans.h"
#include "lltabcontainer.h"
#include "llviewertexteditor.h"
#include "llviewermessage.h"
@@ -68,12 +75,13 @@
#include "llviewercontrol.h"
#include "lluictrlfactory.h"
#include "llviewerwindow.h"
+#include "llvoicechannel.h"
#include "lllogchat.h"
-#include "llfloaterhtml.h"
#include "llweb.h"
#include "llhttpclient.h"
#include "llmutelist.h"
#include "llstylemap.h"
+#include "llappviewer.h"
//
// Constants
@@ -81,7 +89,6 @@
const S32 LINE_HEIGHT = 16;
const S32 MIN_WIDTH = 200;
const S32 MIN_HEIGHT = 130;
-const U32 DEFAULT_RETRIES_COUNT = 3;
//
// Statics
@@ -91,1063 +98,45 @@ static std::string sTitleString = "Instant Message with [NAME]";
static std::string sTypingStartString = "[NAME]: ...";
static std::string sSessionStartString = "Starting session with [NAME] please wait.";
-LLVoiceChannel::voice_channel_map_t LLVoiceChannel::sVoiceChannelMap;
-LLVoiceChannel::voice_channel_map_uri_t LLVoiceChannel::sVoiceChannelURIMap;
-LLVoiceChannel* LLVoiceChannel::sCurrentVoiceChannel = NULL;
-LLVoiceChannel* LLVoiceChannel::sSuspendedVoiceChannel = NULL;
-
-BOOL LLVoiceChannel::sSuspended = FALSE;
-
-void session_starter_helper(
- const LLUUID& temp_session_id,
- const LLUUID& other_participant_id,
- EInstantMessage im_type)
-{
- LLMessageSystem *msg = gMessageSystem;
-
- msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-
- msg->nextBlockFast(_PREHASH_MessageBlock);
- msg->addBOOLFast(_PREHASH_FromGroup, FALSE);
- msg->addUUIDFast(_PREHASH_ToAgentID, other_participant_id);
- msg->addU8Fast(_PREHASH_Offline, IM_ONLINE);
- msg->addU8Fast(_PREHASH_Dialog, im_type);
- msg->addUUIDFast(_PREHASH_ID, temp_session_id);
- msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary
-
- std::string name;
- gAgent.buildFullname(name);
-
- msg->addStringFast(_PREHASH_FromAgentName, name);
- msg->addStringFast(_PREHASH_Message, LLStringUtil::null);
- msg->addU32Fast(_PREHASH_ParentEstateID, 0);
- msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null);
- msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent());
-}
-
-void start_deprecated_conference_chat(
- const LLUUID& temp_session_id,
- const LLUUID& creator_id,
- const LLUUID& other_participant_id,
- const LLSD& agents_to_invite)
-{
- U8* bucket;
- U8* pos;
- S32 count;
- S32 bucket_size;
-
- // *FIX: this could suffer from endian issues
- count = agents_to_invite.size();
- bucket_size = UUID_BYTES * count;
- bucket = new U8[bucket_size];
- pos = bucket;
-
- for(S32 i = 0; i < count; ++i)
- {
- LLUUID agent_id = agents_to_invite[i].asUUID();
-
- memcpy(pos, &agent_id, UUID_BYTES);
- pos += UUID_BYTES;
- }
-
- session_starter_helper(
- temp_session_id,
- other_participant_id,
- IM_SESSION_CONFERENCE_START);
-
- gMessageSystem->addBinaryDataFast(
- _PREHASH_BinaryBucket,
- bucket,
- bucket_size);
-
- gAgent.sendReliableMessage();
-
- delete[] bucket;
-}
-
-class LLStartConferenceChatResponder : public LLHTTPClient::Responder
-{
-public:
- LLStartConferenceChatResponder(
- const LLUUID& temp_session_id,
- const LLUUID& creator_id,
- const LLUUID& other_participant_id,
- const LLSD& agents_to_invite)
- {
- mTempSessionID = temp_session_id;
- mCreatorID = creator_id;
- mOtherParticipantID = other_participant_id;
- mAgents = agents_to_invite;
- }
-
- virtual void error(U32 statusNum, const std::string& reason)
- {
- //try an "old school" way.
- if ( statusNum == 400 )
- {
- start_deprecated_conference_chat(
- mTempSessionID,
- mCreatorID,
- mOtherParticipantID,
- mAgents);
- }
-
- //else throw an error back to the client?
- //in theory we should have just have these error strings
- //etc. set up in this file as opposed to the IMMgr,
- //but the error string were unneeded here previously
- //and it is not worth the effort switching over all
- //the possible different language translations
- }
-
-private:
- LLUUID mTempSessionID;
- LLUUID mCreatorID;
- LLUUID mOtherParticipantID;
-
- LLSD mAgents;
-};
-
-// Returns true if any messages were sent, false otherwise.
-// Is sort of equivalent to "does the server need to do anything?"
-bool send_start_session_messages(
- const LLUUID& temp_session_id,
- const LLUUID& other_participant_id,
- const LLDynamicArray<LLUUID>& ids,
- EInstantMessage dialog)
-{
- if ( dialog == IM_SESSION_GROUP_START )
- {
- session_starter_helper(
- temp_session_id,
- other_participant_id,
- dialog);
-
- switch(dialog)
- {
- case IM_SESSION_GROUP_START:
- gMessageSystem->addBinaryDataFast(
- _PREHASH_BinaryBucket,
- EMPTY_BINARY_BUCKET,
- EMPTY_BINARY_BUCKET_SIZE);
- break;
- default:
- break;
- }
- gAgent.sendReliableMessage();
-
- return true;
- }
- else if ( dialog == IM_SESSION_CONFERENCE_START )
- {
- LLSD agents;
- for (int i = 0; i < (S32) ids.size(); i++)
- {
- agents.append(ids.get(i));
- }
-
- //we have a new way of starting conference calls now
- LLViewerRegion* region = gAgent.getRegion();
- if (region)
- {
- std::string url = region->getCapability(
- "ChatSessionRequest");
- LLSD data;
- data["method"] = "start conference";
- data["session-id"] = temp_session_id;
-
- data["params"] = agents;
-
- LLHTTPClient::post(
- url,
- data,
- new LLStartConferenceChatResponder(
- temp_session_id,
- gAgent.getID(),
- other_participant_id,
- data["params"]));
- }
- else
- {
- start_deprecated_conference_chat(
- temp_session_id,
- gAgent.getID(),
- other_participant_id,
- agents);
- }
- }
-
- return false;
-}
-
-class LLVoiceCallCapResponder : public LLHTTPClient::Responder
-{
-public:
- LLVoiceCallCapResponder(const LLUUID& session_id) : mSessionID(session_id) {};
-
- virtual void error(U32 status, const std::string& reason); // called with bad status codes
- virtual void result(const LLSD& content);
-
-private:
- LLUUID mSessionID;
-};
-
-
-void LLVoiceCallCapResponder::error(U32 status, const std::string& reason)
-{
- llwarns << "LLVoiceCallCapResponder::error("
- << status << ": " << reason << ")"
- << llendl;
- LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
- if ( channelp )
- {
- if ( 403 == status )
- {
- //403 == no ability
- LLNotifications::instance().add(
- "VoiceNotAllowed",
- channelp->getNotifyArgs());
- }
- else
- {
- LLNotifications::instance().add(
- "VoiceCallGenericError",
- channelp->getNotifyArgs());
- }
- channelp->deactivate();
- }
-}
-
-void LLVoiceCallCapResponder::result(const LLSD& content)
-{
- LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
- if (channelp)
- {
- //*TODO: DEBUG SPAM
- LLSD::map_const_iterator iter;
- for(iter = content.beginMap(); iter != content.endMap(); ++iter)
- {
- llinfos << "LLVoiceCallCapResponder::result got "
- << iter->first << llendl;
- }
-
- channelp->setChannelInfo(
- content["voice_credentials"]["channel_uri"].asString(),
- content["voice_credentials"]["channel_credentials"].asString());
- }
-}
-
-//
-// LLVoiceChannel
-//
-LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const std::string& session_name) :
- mSessionID(session_id),
- mState(STATE_NO_CHANNEL_INFO),
- mSessionName(session_name),
- mIgnoreNextSessionLeave(FALSE)
-{
- mNotifyArgs["VOICE_CHANNEL_NAME"] = mSessionName;
-
- if (!sVoiceChannelMap.insert(std::make_pair(session_id, this)).second)
- {
- // a voice channel already exists for this session id, so this instance will be orphaned
- // the end result should simply be the failure to make voice calls
- llwarns << "Duplicate voice channels registered for session_id " << session_id << llendl;
- }
-
- LLVoiceClient::getInstance()->addObserver(this);
-}
-
-LLVoiceChannel::~LLVoiceChannel()
-{
- // Don't use LLVoiceClient::getInstance() here -- this can get called during atexit() time and that singleton MAY have already been destroyed.
- if(gVoiceClient)
- {
- gVoiceClient->removeObserver(this);
- }
-
- sVoiceChannelMap.erase(mSessionID);
- sVoiceChannelURIMap.erase(mURI);
-}
-
-void LLVoiceChannel::setChannelInfo(
- const std::string& uri,
- const std::string& credentials)
-{
- setURI(uri);
-
- mCredentials = credentials;
-
- if (mState == STATE_NO_CHANNEL_INFO)
- {
- if (mURI.empty())
- {
- LLNotifications::instance().add("VoiceChannelJoinFailed", mNotifyArgs);
- llwarns << "Received empty URI for channel " << mSessionName << llendl;
- deactivate();
- }
- else if (mCredentials.empty())
- {
- LLNotifications::instance().add("VoiceChannelJoinFailed", mNotifyArgs);
- llwarns << "Received empty credentials for channel " << mSessionName << llendl;
- deactivate();
- }
- else
- {
- setState(STATE_READY);
-
- // if we are supposed to be active, reconnect
- // this will happen on initial connect, as we request credentials on first use
- if (sCurrentVoiceChannel == this)
- {
- // just in case we got new channel info while active
- // should move over to new channel
- activate();
- }
- }
- }
-}
-
-void LLVoiceChannel::onChange(EStatusType type, const std::string &channelURI, bool proximal)
-{
- if (channelURI != mURI)
- {
- return;
- }
-
- if (type < BEGIN_ERROR_STATUS)
- {
- handleStatusChange(type);
- }
- else
- {
- handleError(type);
- }
-}
-
-void LLVoiceChannel::handleStatusChange(EStatusType type)
-{
- // status updates
- switch(type)
- {
- case STATUS_LOGIN_RETRY:
- //mLoginNotificationHandle = LLNotifyBox::showXml("VoiceLoginRetry")->getHandle();
- LLNotifications::instance().add("VoiceLoginRetry");
- break;
- case STATUS_LOGGED_IN:
- //if (!mLoginNotificationHandle.isDead())
- //{
- // LLNotifyBox* notifyp = (LLNotifyBox*)mLoginNotificationHandle.get();
- // if (notifyp)
- // {
- // notifyp->close();
- // }
- // mLoginNotificationHandle.markDead();
- //}
- break;
- case STATUS_LEFT_CHANNEL:
- if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
- {
- // if forceably removed from channel
- // update the UI and revert to default channel
- LLNotifications::instance().add("VoiceChannelDisconnected", mNotifyArgs);
- deactivate();
- }
- mIgnoreNextSessionLeave = FALSE;
- break;
- case STATUS_JOINING:
- if (callStarted())
- {
- setState(STATE_RINGING);
- }
- break;
- case STATUS_JOINED:
- if (callStarted())
- {
- setState(STATE_CONNECTED);
- }
- default:
- break;
- }
-}
-
-// default behavior is to just deactivate channel
-// derived classes provide specific error messages
-void LLVoiceChannel::handleError(EStatusType type)
-{
- deactivate();
- setState(STATE_ERROR);
-}
-
-BOOL LLVoiceChannel::isActive()
-{
- // only considered active when currently bound channel matches what our channel
- return callStarted() && LLVoiceClient::getInstance()->getCurrentChannel() == mURI;
-}
-
-BOOL LLVoiceChannel::callStarted()
-{
- return mState >= STATE_CALL_STARTED;
-}
-
-void LLVoiceChannel::deactivate()
-{
- if (mState >= STATE_RINGING)
- {
- // ignore session leave event
- mIgnoreNextSessionLeave = TRUE;
- }
-
- if (callStarted())
- {
- setState(STATE_HUNG_UP);
- // mute the microphone if required when returning to the proximal channel
- if (gSavedSettings.getBOOL("AutoDisengageMic") && sCurrentVoiceChannel == this)
- {
- gSavedSettings.setBOOL("PTTCurrentlyEnabled", true);
- }
- }
-
- if (sCurrentVoiceChannel == this)
- {
- // default channel is proximal channel
- sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
- sCurrentVoiceChannel->activate();
- }
-}
-
-void LLVoiceChannel::activate()
-{
- if (callStarted())
- {
- return;
- }
-
- // deactivate old channel and mark ourselves as the active one
- if (sCurrentVoiceChannel != this)
- {
- // mark as current before deactivating the old channel to prevent
- // activating the proximal channel between IM calls
- LLVoiceChannel* old_channel = sCurrentVoiceChannel;
- sCurrentVoiceChannel = this;
- if (old_channel)
- {
- old_channel->deactivate();
- }
- }
-
- if (mState == STATE_NO_CHANNEL_INFO)
- {
- // responsible for setting status to active
- getChannelInfo();
- }
- else
- {
- setState(STATE_CALL_STARTED);
- }
-}
-
-void LLVoiceChannel::getChannelInfo()
-{
- // pretend we have everything we need
- if (sCurrentVoiceChannel == this)
- {
- setState(STATE_CALL_STARTED);
- }
-}
-
-//static
-LLVoiceChannel* LLVoiceChannel::getChannelByID(const LLUUID& session_id)
-{
- voice_channel_map_t::iterator found_it = sVoiceChannelMap.find(session_id);
- if (found_it == sVoiceChannelMap.end())
- {
- return NULL;
- }
- else
- {
- return found_it->second;
- }
-}
-
-//static
-LLVoiceChannel* LLVoiceChannel::getChannelByURI(std::string uri)
-{
- voice_channel_map_uri_t::iterator found_it = sVoiceChannelURIMap.find(uri);
- if (found_it == sVoiceChannelURIMap.end())
- {
- return NULL;
- }
- else
- {
- return found_it->second;
- }
-}
-
-
-void LLVoiceChannel::updateSessionID(const LLUUID& new_session_id)
-{
- sVoiceChannelMap.erase(sVoiceChannelMap.find(mSessionID));
- mSessionID = new_session_id;
- sVoiceChannelMap.insert(std::make_pair(mSessionID, this));
-}
-
-void LLVoiceChannel::setURI(std::string uri)
-{
- sVoiceChannelURIMap.erase(mURI);
- mURI = uri;
- sVoiceChannelURIMap.insert(std::make_pair(mURI, this));
-}
-
-void LLVoiceChannel::setState(EState state)
-{
- switch(state)
- {
- case STATE_RINGING:
- gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
- break;
- case STATE_CONNECTED:
- gIMMgr->addSystemMessage(mSessionID, "connected", mNotifyArgs);
- break;
- case STATE_HUNG_UP:
- gIMMgr->addSystemMessage(mSessionID, "hang_up", mNotifyArgs);
- break;
- default:
- break;
- }
-
- mState = state;
-}
-
-
-//static
-void LLVoiceChannel::initClass()
-{
- sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
-}
-
-
-//static
-void LLVoiceChannel::suspend()
-{
- if (!sSuspended)
- {
- sSuspendedVoiceChannel = sCurrentVoiceChannel;
- sSuspended = TRUE;
- }
-}
-
-//static
-void LLVoiceChannel::resume()
-{
- if (sSuspended)
- {
- if (gVoiceClient->voiceEnabled())
- {
- if (sSuspendedVoiceChannel)
- {
- sSuspendedVoiceChannel->activate();
- }
- else
- {
- LLVoiceChannelProximal::getInstance()->activate();
- }
- }
- sSuspended = FALSE;
- }
-}
-
-
-//
-// LLVoiceChannelGroup
-//
-
-LLVoiceChannelGroup::LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name) :
- LLVoiceChannel(session_id, session_name)
-{
- mRetries = DEFAULT_RETRIES_COUNT;
- mIsRetrying = FALSE;
-}
-
-void LLVoiceChannelGroup::deactivate()
-{
- if (callStarted())
- {
- LLVoiceClient::getInstance()->leaveNonSpatialChannel();
- }
- LLVoiceChannel::deactivate();
-}
-
-void LLVoiceChannelGroup::activate()
-{
- if (callStarted()) return;
-
- LLVoiceChannel::activate();
-
- if (callStarted())
- {
- // we have the channel info, just need to use it now
- LLVoiceClient::getInstance()->setNonSpatialChannel(
- mURI,
- mCredentials);
- }
-}
-
-void LLVoiceChannelGroup::getChannelInfo()
-{
- LLViewerRegion* region = gAgent.getRegion();
- if (region)
- {
- std::string url = region->getCapability("ChatSessionRequest");
- LLSD data;
- data["method"] = "call";
- data["session-id"] = mSessionID;
- LLHTTPClient::post(url,
- data,
- new LLVoiceCallCapResponder(mSessionID));
- }
-}
-
-void LLVoiceChannelGroup::setChannelInfo(
- const std::string& uri,
- const std::string& credentials)
-{
- setURI(uri);
-
- mCredentials = credentials;
-
- if (mState == STATE_NO_CHANNEL_INFO)
- {
- if(!mURI.empty() && !mCredentials.empty())
- {
- setState(STATE_READY);
-
- // if we are supposed to be active, reconnect
- // this will happen on initial connect, as we request credentials on first use
- if (sCurrentVoiceChannel == this)
- {
- // just in case we got new channel info while active
- // should move over to new channel
- activate();
- }
- }
- else
- {
- //*TODO: notify user
- llwarns << "Received invalid credentials for channel " << mSessionName << llendl;
- deactivate();
- }
- }
- else if ( mIsRetrying )
- {
- // we have the channel info, just need to use it now
- LLVoiceClient::getInstance()->setNonSpatialChannel(
- mURI,
- mCredentials);
- }
-}
-
-void LLVoiceChannelGroup::handleStatusChange(EStatusType type)
-{
- // status updates
- switch(type)
- {
- case STATUS_JOINED:
- mRetries = 3;
- mIsRetrying = FALSE;
- default:
- break;
- }
-
- LLVoiceChannel::handleStatusChange(type);
-}
-
-void LLVoiceChannelGroup::handleError(EStatusType status)
-{
- std::string notify;
- switch(status)
- {
- case ERROR_CHANNEL_LOCKED:
- case ERROR_CHANNEL_FULL:
- notify = "VoiceChannelFull";
- break;
- case ERROR_NOT_AVAILABLE:
- //clear URI and credentials
- //set the state to be no info
- //and activate
- if ( mRetries > 0 )
- {
- mRetries--;
- mIsRetrying = TRUE;
- mIgnoreNextSessionLeave = TRUE;
-
- getChannelInfo();
- return;
- }
- else
- {
- notify = "VoiceChannelJoinFailed";
- mRetries = DEFAULT_RETRIES_COUNT;
- mIsRetrying = FALSE;
- }
-
- break;
-
- case ERROR_UNKNOWN:
- default:
- break;
- }
-
- // notification
- if (!notify.empty())
- {
- LLNotificationPtr notification = LLNotifications::instance().add(notify, mNotifyArgs);
- // echo to im window
- gIMMgr->addMessage(mSessionID, LLUUID::null, SYSTEM_FROM, notification->getMessage());
- }
-
- LLVoiceChannel::handleError(status);
-}
-
-void LLVoiceChannelGroup::setState(EState state)
-{
- switch(state)
- {
- case STATE_RINGING:
- if ( !mIsRetrying )
- {
- gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
- }
-
- mState = state;
- break;
- default:
- LLVoiceChannel::setState(state);
- }
-}
-
-//
-// LLVoiceChannelProximal
-//
-LLVoiceChannelProximal::LLVoiceChannelProximal() :
- LLVoiceChannel(LLUUID::null, LLStringUtil::null)
-{
- activate();
-}
-
-BOOL LLVoiceChannelProximal::isActive()
-{
- return callStarted() && LLVoiceClient::getInstance()->inProximalChannel();
-}
-
-void LLVoiceChannelProximal::activate()
-{
- if (callStarted()) return;
-
- LLVoiceChannel::activate();
-
- if (callStarted())
- {
- // this implicitly puts you back in the spatial channel
- LLVoiceClient::getInstance()->leaveNonSpatialChannel();
- }
-}
-
-void LLVoiceChannelProximal::onChange(EStatusType type, const std::string &channelURI, bool proximal)
-{
- if (!proximal)
- {
- return;
- }
-
- if (type < BEGIN_ERROR_STATUS)
- {
- handleStatusChange(type);
- }
- else
- {
- handleError(type);
- }
-}
-
-void LLVoiceChannelProximal::handleStatusChange(EStatusType status)
-{
- // status updates
- switch(status)
- {
- case STATUS_LEFT_CHANNEL:
- // do not notify user when leaving proximal channel
- return;
- case STATUS_VOICE_DISABLED:
- gIMMgr->addSystemMessage(LLUUID::null, "unavailable", mNotifyArgs);
- return;
- default:
- break;
- }
- LLVoiceChannel::handleStatusChange(status);
-}
-
-
-void LLVoiceChannelProximal::handleError(EStatusType status)
-{
- std::string notify;
- switch(status)
- {
- case ERROR_CHANNEL_LOCKED:
- case ERROR_CHANNEL_FULL:
- notify = "ProximalVoiceChannelFull";
- break;
- default:
- break;
- }
-
- // notification
- if (!notify.empty())
- {
- LLNotifications::instance().add(notify, mNotifyArgs);
- }
-
- LLVoiceChannel::handleError(status);
-}
-
-void LLVoiceChannelProximal::deactivate()
-{
- if (callStarted())
- {
- setState(STATE_HUNG_UP);
- }
-}
-
-
-//
-// LLVoiceChannelP2P
-//
-LLVoiceChannelP2P::LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id) :
- LLVoiceChannelGroup(session_id, session_name),
- mOtherUserID(other_user_id),
- mReceivedCall(FALSE)
-{
- // make sure URI reflects encoded version of other user's agent id
- setURI(LLVoiceClient::getInstance()->sipURIFromID(other_user_id));
-}
-
-void LLVoiceChannelP2P::handleStatusChange(EStatusType type)
-{
- // status updates
- switch(type)
- {
- case STATUS_LEFT_CHANNEL:
- if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
- {
- if (mState == STATE_RINGING)
- {
- // other user declined call
- LLNotifications::instance().add("P2PCallDeclined", mNotifyArgs);
- }
- else
- {
- // other user hung up
- LLNotifications::instance().add("VoiceChannelDisconnectedP2P", mNotifyArgs);
- }
- deactivate();
- }
- mIgnoreNextSessionLeave = FALSE;
- return;
- default:
- break;
- }
-
- LLVoiceChannel::handleStatusChange(type);
-}
-
-void LLVoiceChannelP2P::handleError(EStatusType type)
-{
- switch(type)
- {
- case ERROR_NOT_AVAILABLE:
- LLNotifications::instance().add("P2PCallNoAnswer", mNotifyArgs);
- break;
- default:
- break;
- }
-
- LLVoiceChannel::handleError(type);
-}
-
-void LLVoiceChannelP2P::activate()
-{
- if (callStarted()) return;
-
- LLVoiceChannel::activate();
-
- if (callStarted())
- {
- // no session handle yet, we're starting the call
- if (mSessionHandle.empty())
- {
- mReceivedCall = FALSE;
- LLVoiceClient::getInstance()->callUser(mOtherUserID);
- }
- // otherwise answering the call
- else
- {
- LLVoiceClient::getInstance()->answerInvite(mSessionHandle);
-
- // using the session handle invalidates it. Clear it out here so we can't reuse it by accident.
- mSessionHandle.clear();
- }
- }
-}
-
-void LLVoiceChannelP2P::getChannelInfo()
-{
- // pretend we have everything we need, since P2P doesn't use channel info
- if (sCurrentVoiceChannel == this)
- {
- setState(STATE_CALL_STARTED);
- }
-}
-
-// receiving session from other user who initiated call
-void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::string &inURI)
-{
- BOOL needs_activate = FALSE;
- if (callStarted())
- {
- // defer to lower agent id when already active
- if (mOtherUserID < gAgent.getID())
- {
- // pretend we haven't started the call yet, so we can connect to this session instead
- deactivate();
- needs_activate = TRUE;
- }
- else
- {
- // we are active and have priority, invite the other user again
- // under the assumption they will join this new session
- mSessionHandle.clear();
- LLVoiceClient::getInstance()->callUser(mOtherUserID);
- return;
- }
- }
-
- mSessionHandle = handle;
-
- // The URI of a p2p session should always be the other end's SIP URI.
- if(!inURI.empty())
- {
- setURI(inURI);
- }
- else
- {
- setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID));
- }
-
- mReceivedCall = TRUE;
-
- if (needs_activate)
- {
- activate();
- }
-}
-
-void LLVoiceChannelP2P::setState(EState state)
-{
- // you only "answer" voice invites in p2p mode
- // so provide a special purpose message here
- if (mReceivedCall && state == STATE_RINGING)
- {
- gIMMgr->addSystemMessage(mSessionID, "answering", mNotifyArgs);
- mState = state;
- return;
- }
- LLVoiceChannel::setState(state);
-}
-
//
// LLFloaterIMPanel
//
-LLFloaterIMPanel::LLFloaterIMPanel(
- const std::string& session_label,
- const LLUUID& session_id,
- const LLUUID& other_participant_id,
- EInstantMessage dialog) :
- LLFloater(session_label, LLRect(), session_label),
- mInputEditor(NULL),
- mHistoryEditor(NULL),
- mSessionUUID(session_id),
- mVoiceChannel(NULL),
- mSessionInitialized(FALSE),
- mSessionStartMsgPos(0),
- mOtherParticipantUUID(other_participant_id),
- mDialog(dialog),
- mTyping(FALSE),
- mOtherTyping(FALSE),
- mTypingLineStartIndex(0),
- mSentTypingState(TRUE),
- mNumUnreadMessages(0),
- mShowSpeakersOnConnect(TRUE),
- mAutoConnect(FALSE),
- mTextIMPossible(TRUE),
- mProfileButtonEnabled(TRUE),
- mCallBackEnabled(TRUE),
- mSpeakers(NULL),
- mSpeakerPanel(NULL),
- mFirstKeystrokeTimer(),
- mLastKeystrokeTimer()
-{
- init(session_label);
-}
-LLFloaterIMPanel::LLFloaterIMPanel(
- const std::string& session_label,
- const LLUUID& session_id,
- const LLUUID& other_participant_id,
- const LLDynamicArray<LLUUID>& ids,
- EInstantMessage dialog) :
- LLFloater(session_label, LLRect(), session_label),
+LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label,
+ const LLUUID& session_id,
+ const LLUUID& other_participant_id,
+ const std::vector<LLUUID>& ids,
+ EInstantMessage dialog)
+: LLFloater(session_id),
mInputEditor(NULL),
mHistoryEditor(NULL),
mSessionUUID(session_id),
- mVoiceChannel(NULL),
+ mSessionLabel(session_label),
mSessionInitialized(FALSE),
mSessionStartMsgPos(0),
mOtherParticipantUUID(other_participant_id),
mDialog(dialog),
+ mSessionInitialTargetIDs(ids),
mTyping(FALSE),
mOtherTyping(FALSE),
mTypingLineStartIndex(0),
mSentTypingState(TRUE),
+ mNumUnreadMessages(0),
mShowSpeakersOnConnect(TRUE),
- mAutoConnect(FALSE),
mTextIMPossible(TRUE),
mProfileButtonEnabled(TRUE),
mCallBackEnabled(TRUE),
- mSpeakers(NULL),
mSpeakerPanel(NULL),
mFirstKeystrokeTimer(),
mLastKeystrokeTimer()
{
- mSessionInitialTargetIDs = ids;
- init(session_label);
-}
-
-
-void LLFloaterIMPanel::init(const std::string& session_label)
-{
- mSessionLabel = session_label;
-
std::string xml_filename;
switch(mDialog)
{
case IM_SESSION_GROUP_START:
mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this);
xml_filename = "floater_instant_message_group.xml";
- mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, mSessionLabel);
break;
case IM_SESSION_INVITE:
mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this);
@@ -1159,16 +148,13 @@ void LLFloaterIMPanel::init(const std::string& session_label)
{
xml_filename = "floater_instant_message_ad_hoc.xml";
}
- mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, mSessionLabel);
break;
case IM_SESSION_P2P_INVITE:
xml_filename = "floater_instant_message.xml";
- mVoiceChannel = new LLVoiceChannelP2P(mSessionUUID, mSessionLabel, mOtherParticipantUUID);
break;
case IM_SESSION_CONFERENCE_START:
mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this);
xml_filename = "floater_instant_message_ad_hoc.xml";
- mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, mSessionLabel);
break;
// just received text from another user
case IM_NOTHING_SPECIAL:
@@ -1178,8 +164,6 @@ void LLFloaterIMPanel::init(const std::string& session_label)
mTextIMPossible = LLVoiceClient::getInstance()->isSessionTextIMPossible(mSessionUUID);
mProfileButtonEnabled = LLVoiceClient::getInstance()->isParticipantAvatar(mSessionUUID);
mCallBackEnabled = LLVoiceClient::getInstance()->isSessionCallBackPossible(mSessionUUID);
-
- mVoiceChannel = new LLVoiceChannelP2P(mSessionUUID, mSessionLabel, mOtherParticipantUUID);
break;
default:
llwarns << "Unknown session type" << llendl;
@@ -1187,161 +171,106 @@ void LLFloaterIMPanel::init(const std::string& session_label)
break;
}
- mSpeakers = new LLIMSpeakerMgr(mVoiceChannel);
-
- LLUICtrlFactory::getInstance()->buildFloater(this,
- xml_filename,
- &getFactoryMap(),
- FALSE);
+ LLUICtrlFactory::getInstance()->buildFloater(this, xml_filename, NULL);
setTitle(mSessionLabel);
mInputEditor->setMaxTextLength(1023);
// enable line history support for instant message bar
mInputEditor->setEnableLineHistory(TRUE);
- if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
+ //*TODO we probably need the same "awaiting message" thing in LLIMFloater
+ LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(mSessionUUID);
+ if (!im_session)
{
- LLLogChat::loadHistory(mSessionLabel,
- &chatFromLogFile,
- (void *)this);
+ llerror("im session with id " + mSessionUUID.asString() + " does not exist!", 0);
+ return;
}
- if ( !mSessionInitialized )
+ mSessionInitialized = im_session->mSessionInitialized;
+ if (!mSessionInitialized)
{
- if ( !send_start_session_messages(
- mSessionUUID,
- mOtherParticipantUUID,
- mSessionInitialTargetIDs,
- mDialog) )
- {
- //we don't need to need to wait for any responses
- //so we're already initialized
- mSessionInitialized = TRUE;
- mSessionStartMsgPos = 0;
- }
- else
- {
- //locally echo a little "starting session" message
- LLUIString session_start = sSessionStartString;
+ //locally echo a little "starting session" message
+ LLUIString session_start = sSessionStartString;
- session_start.setArg("[NAME]", getTitle());
- mSessionStartMsgPos =
- mHistoryEditor->getWText().length();
+ session_start.setArg("[NAME]", getTitle());
+ mSessionStartMsgPos =
+ mHistoryEditor->getWText().length();
- addHistoryLine(
- session_start,
- gSavedSettings.getColor4("SystemChatColor"),
- false);
- }
+ addHistoryLine(
+ session_start,
+ LLUIColorTable::instance().getColor("SystemChatColor"),
+ false);
}
}
LLFloaterIMPanel::~LLFloaterIMPanel()
{
- delete mSpeakers;
- mSpeakers = NULL;
-
- // End the text IM session if necessary
- if(gVoiceClient && mOtherParticipantUUID.notNull())
- {
- switch(mDialog)
- {
- case IM_NOTHING_SPECIAL:
- case IM_SESSION_P2P_INVITE:
- gVoiceClient->endUserIMSession(mOtherParticipantUUID);
- break;
-
- default:
- // Appease the compiler
- break;
- }
- }
-
- //kicks you out of the voice channel if it is currently active
-
- // HAVE to do this here -- if it happens in the LLVoiceChannel destructor it will call the wrong version (since the object's partially deconstructed at that point).
- mVoiceChannel->deactivate();
-
- delete mVoiceChannel;
- mVoiceChannel = NULL;
-
//delete focus lost callback
- if(mInputEditor)
- {
- mInputEditor->setFocusLostCallback( NULL );
- }
+ mFocusCallbackConnection.disconnect();
}
BOOL LLFloaterIMPanel::postBuild()
{
- requires<LLLineEditor>("chat_editor");
- requires<LLTextEditor>("im_history");
+ setVisibleCallback(boost::bind(&LLFloaterIMPanel::onVisibilityChange, this, _2));
+
+ mInputEditor = getChild<LLLineEditor>("chat_editor");
+ mInputEditor->setFocusReceivedCallback( boost::bind(onInputEditorFocusReceived, _1, this) );
+ mFocusCallbackConnection = mInputEditor->setFocusLostCallback( boost::bind(onInputEditorFocusLost, _1, this));
+ mInputEditor->setKeystrokeCallback( onInputEditorKeystroke, this );
+ mInputEditor->setCommitCallback( onCommitChat, this );
+ mInputEditor->setCommitOnFocusLost( FALSE );
+ mInputEditor->setRevertOnEsc( FALSE );
+ mInputEditor->setReplaceNewlinesWithSpaces( FALSE );
- if (checkRequirements())
- {
- mInputEditor = getChild<LLLineEditor>("chat_editor");
- mInputEditor->setFocusReceivedCallback( onInputEditorFocusReceived, this );
- mInputEditor->setFocusLostCallback( onInputEditorFocusLost, this );
- mInputEditor->setKeystrokeCallback( onInputEditorKeystroke );
- mInputEditor->setCommitCallback( onCommitChat );
- mInputEditor->setCallbackUserData(this);
- mInputEditor->setCommitOnFocusLost( FALSE );
- mInputEditor->setRevertOnEsc( FALSE );
- mInputEditor->setReplaceNewlinesWithSpaces( FALSE );
-
- childSetAction("profile_callee_btn", onClickProfile, this);
- childSetAction("group_info_btn", onClickGroupInfo, this);
-
- childSetAction("start_call_btn", onClickStartCall, this);
- childSetAction("end_call_btn", onClickEndCall, this);
- childSetAction("send_btn", onClickSend, this);
- childSetAction("toggle_active_speakers_btn", onClickToggleActiveSpeakers, this);
-
- childSetAction("moderator_kick_speaker", onKickSpeaker, this);
- //LLButton* close_btn = getChild<LLButton>("close_btn");
- //close_btn->setClickedCallback(&LLFloaterIMPanel::onClickClose, this);
-
- mHistoryEditor = getChild<LLViewerTextEditor>("im_history");
- mHistoryEditor->setParseHTML(TRUE);
- mHistoryEditor->setParseHighlights(TRUE);
-
- if ( IM_SESSION_GROUP_START == mDialog )
- {
- childSetEnabled("profile_btn", FALSE);
- }
-
- if(!mProfileButtonEnabled)
- {
- childSetEnabled("profile_callee_btn", FALSE);
- }
+ childSetAction("profile_callee_btn", onClickProfile, this);
+ childSetAction("group_info_btn", onClickGroupInfo, this);
- sTitleString = getString("title_string");
- sTypingStartString = getString("typing_start_string");
- sSessionStartString = getString("session_start_string");
+ childSetAction("start_call_btn", onClickStartCall, this);
+ childSetAction("end_call_btn", onClickEndCall, this);
+ childSetAction("send_btn", onClickSend, this);
+ childSetAction("toggle_active_speakers_btn", onClickToggleActiveSpeakers, this);
- if (mSpeakerPanel)
- {
- mSpeakerPanel->refreshSpeakers();
- }
+ childSetAction("moderator_kick_speaker", onKickSpeaker, this);
+ //LLButton* close_btn = getChild<LLButton>("close_btn");
+ //close_btn->setClickedCallback(&LLFloaterIMPanel::onClickClose, this);
- if (mDialog == IM_NOTHING_SPECIAL)
- {
- childSetAction("mute_btn", onClickMuteVoice, this);
- childSetCommitCallback("speaker_volume", onVolumeChange, this);
- }
+ mHistoryEditor = getChild<LLViewerTextEditor>("im_history");
+
+ if ( IM_SESSION_GROUP_START == mDialog )
+ {
+ childSetEnabled("profile_btn", FALSE);
+ }
+
+ if(!mProfileButtonEnabled)
+ {
+ childSetEnabled("profile_callee_btn", FALSE);
+ }
- setDefaultBtn("send_btn");
- return TRUE;
+ sTitleString = getString("title_string");
+ sTypingStartString = getString("typing_start_string");
+ sSessionStartString = getString("session_start_string");
+
+ if (mSpeakerPanel)
+ {
+ mSpeakerPanel->refreshSpeakers();
+ }
+
+ if (mDialog == IM_NOTHING_SPECIAL)
+ {
+ childSetAction("mute_btn", onClickMuteVoice, this);
+ childSetCommitCallback("speaker_volume", onVolumeChange, this);
}
- return FALSE;
+ setDefaultBtn("send_btn");
+ return TRUE;
}
void* LLFloaterIMPanel::createSpeakersPanel(void* data)
{
LLFloaterIMPanel* floaterp = (LLFloaterIMPanel*)data;
- floaterp->mSpeakerPanel = new LLPanelActiveSpeakers(floaterp->mSpeakers, TRUE);
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(floaterp->mSessionUUID);
+ floaterp->mSpeakerPanel = new LLPanelActiveSpeakers(speaker_mgr, TRUE);
return floaterp->mSpeakerPanel;
}
@@ -1387,12 +316,21 @@ void LLFloaterIMPanel::draw()
&& mCallBackEnabled;
// hide/show start call and end call buttons
- childSetVisible("end_call_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->getState() >= LLVoiceChannel::STATE_CALL_STARTED);
- childSetVisible("start_call_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->getState() < LLVoiceChannel::STATE_CALL_STARTED);
+ LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionUUID);
+ if (!voice_channel)
+ return;
+
+ childSetVisible("end_call_btn", LLVoiceClient::voiceEnabled() && voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED);
+ childSetVisible("start_call_btn", LLVoiceClient::voiceEnabled() && voice_channel->getState() < LLVoiceChannel::STATE_CALL_STARTED);
childSetEnabled("start_call_btn", enable_connect);
childSetEnabled("send_btn", !childGetValue("chat_editor").asString().empty());
- LLPointer<LLSpeaker> self_speaker = mSpeakers->findSpeaker(gAgent.getID());
+ LLPointer<LLSpeaker> self_speaker;
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionUUID);
+ if (speaker_mgr)
+ {
+ self_speaker = speaker_mgr->findSpeaker(gAgent.getID());
+ }
if(!mTextIMPossible)
{
mInputEditor->setEnabled(FALSE);
@@ -1409,14 +347,8 @@ void LLFloaterIMPanel::draw()
mInputEditor->setLabel(getString("default_text_label"));
}
- if (mAutoConnect && enable_connect)
- {
- onClickStartCall(this);
- mAutoConnect = FALSE;
- }
-
// show speakers window when voice first connects
- if (mShowSpeakersOnConnect && mVoiceChannel->isActive())
+ if (mShowSpeakersOnConnect && voice_channel->isActive())
{
childSetVisible("active_speakers_panel", TRUE);
mShowSpeakersOnConnect = FALSE;
@@ -1452,11 +384,11 @@ void LLFloaterIMPanel::draw()
else
{
// refresh volume and mute checkbox
- childSetVisible("speaker_volume", LLVoiceClient::voiceEnabled() && mVoiceChannel->isActive());
+ childSetVisible("speaker_volume", LLVoiceClient::voiceEnabled() && voice_channel->isActive());
childSetValue("speaker_volume", gVoiceClient->getUserVolume(mOtherParticipantUUID));
childSetValue("mute_btn", LLMuteList::getInstance()->isMuted(mOtherParticipantUUID, LLMute::flagVoiceChat));
- childSetVisible("mute_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->isActive());
+ childSetVisible("mute_btn", LLVoiceClient::voiceEnabled() && voice_channel->isActive());
}
LLFloater::draw();
}
@@ -1479,7 +411,7 @@ private:
LLUUID mSessionID;
};
-BOOL LLFloaterIMPanel::inviteToSession(const LLDynamicArray<LLUUID>& ids)
+BOOL LLFloaterIMPanel::inviteToSession(const std::vector<LLUUID>& ids)
{
LLViewerRegion* region = gAgent.getRegion();
if (!region)
@@ -1487,7 +419,7 @@ BOOL LLFloaterIMPanel::inviteToSession(const LLDynamicArray<LLUUID>& ids)
return FALSE;
}
- S32 count = ids.count();
+ S32 count = ids.size();
if( isInviteAllowed() && (count > 0) )
{
@@ -1500,7 +432,7 @@ BOOL LLFloaterIMPanel::inviteToSession(const LLDynamicArray<LLUUID>& ids)
data["params"] = LLSD::emptyArray();
for (int i = 0; i < count; i++)
{
- data["params"].append(ids.get(i));
+ data["params"].append(ids[i]);
}
data["method"] = "invite";
@@ -1551,64 +483,30 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4
prepend_newline = false;
}
+ std::string separator_string(": ");
+
// 'name' is a sender name that we want to hotlink so that clicking on it opens a profile.
if (!name.empty()) // If name exists, then add it to the front of the message.
{
// Don't hotlink any messages from the system (e.g. "Second Life:"), so just add those in plain text.
if (name == SYSTEM_FROM)
{
- mHistoryEditor->appendColoredText(name,false,prepend_newline,color);
+ mHistoryEditor->appendText(name + separator_string, prepend_newline, LLStyle::Params().color(color));
}
else
{
// Convert the name to a hotlink and add to message.
- const LLStyleSP &source_style = LLStyleMap::instance().lookupAgent(source);
- mHistoryEditor->appendStyledText(name,false,prepend_newline,source_style);
+ mHistoryEditor->appendText(name + separator_string, prepend_newline, LLStyleMap::instance().lookupAgent(source));
}
prepend_newline = false;
}
- mHistoryEditor->appendColoredText(utf8msg, false, prepend_newline, color);
-
- if (log_to_file
- && gSavedPerAccountSettings.getBOOL("LogInstantMessages") )
- {
- std::string histstr;
- if (gSavedPerAccountSettings.getBOOL("IMLogTimestamp"))
- histstr = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate")) + name + utf8msg;
- else
- histstr = name + utf8msg;
-
- LLLogChat::saveHistory(getTitle(),histstr);
- }
+ mHistoryEditor->appendText(utf8msg, prepend_newline, LLStyle::Params().color(color));
+ mHistoryEditor->blockUndo();
if (!isInVisibleChain())
{
mNumUnreadMessages++;
}
-
- if (source != LLUUID::null)
- {
- mSpeakers->speakerChatted(source);
- mSpeakers->setSpeakerTyping(source, FALSE);
- }
-}
-
-
-void LLFloaterIMPanel::setVisible(BOOL b)
-{
- LLPanel::setVisible(b);
-
- LLMultiFloater* hostp = getHost();
- if( b && hostp )
- {
- hostp->setFloaterFlashing(this, FALSE);
-
- /* Don't change containing floater title - leave it "Instant Message" JC
- LLUIString title = sTitleString;
- title.setArg("[NAME]", mSessionLabel);
- hostp->setTitle( title );
- */
- }
}
@@ -1629,7 +527,6 @@ void LLFloaterIMPanel::selectNone()
mInputEditor->deselect();
}
-
BOOL LLFloaterIMPanel::handleKeyHere( KEY key, MASK mask )
{
BOOL handled = FALSE;
@@ -1637,24 +534,11 @@ BOOL LLFloaterIMPanel::handleKeyHere( KEY key, MASK mask )
{
sendMsg();
handled = TRUE;
-
- // Close talk panels on hitting return
- // but not shift-return or control-return
- if ( !gSavedSettings.getBOOL("PinTalkViewOpen") && !(mask & MASK_CONTROL) && !(mask & MASK_SHIFT) )
- {
- gIMMgr->toggle(NULL);
- }
}
else if ( KEY_ESCAPE == key )
{
handled = TRUE;
gFocusMgr.setKeyboardFocus(NULL);
-
- // Close talk panel with escape
- if( !gSavedSettings.getBOOL("PinTalkViewOpen") )
- {
- gIMMgr->toggle(NULL);
- }
}
// May need to call base class LLPanel::handleKeyHere if not handled
@@ -1705,8 +589,8 @@ BOOL LLFloaterIMPanel::dropCallingCard(LLInventoryItem* item, BOOL drop)
{
if(drop)
{
- LLDynamicArray<LLUUID> ids;
- ids.put(item->getCreatorUUID());
+ std::vector<LLUUID> ids;
+ ids.push_back(item->getCreatorUUID());
inviteToSession(ids);
}
}
@@ -1738,10 +622,11 @@ BOOL LLFloaterIMPanel::dropCategory(LLInventoryCategory* category, BOOL drop)
}
else if(drop)
{
- LLDynamicArray<LLUUID> ids;
+ std::vector<LLUUID> ids;
+ ids.reserve(count);
for(S32 i = 0; i < count; ++i)
{
- ids.put(items.get(i)->getCreatorUUID());
+ ids.push_back(items.get(i)->getCreatorUUID());
}
inviteToSession(ids);
}
@@ -1771,9 +656,9 @@ void LLFloaterIMPanel::onClickProfile( void* userdata )
// Bring up the Profile window
LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata;
- if (self->mOtherParticipantUUID.notNull())
+ if (self->getOtherParticipantID().notNull())
{
- LLFloaterAvatarInfo::showFromDirectory(self->getOtherParticipantID());
+ LLAvatarActions::showProfile(self->getOtherParticipantID());
}
}
@@ -1783,7 +668,8 @@ void LLFloaterIMPanel::onClickGroupInfo( void* userdata )
// Bring up the Profile window
LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata;
- LLFloaterGroupInfo::showFromUUID(self->mSessionUUID);
+ LLGroupActions::show(self->mSessionUUID);
+
}
// static
@@ -1792,7 +678,7 @@ void LLFloaterIMPanel::onClickClose( void* userdata )
LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata;
if(self)
{
- self->close();
+ self->closeFloater();
}
}
@@ -1801,7 +687,7 @@ void LLFloaterIMPanel::onClickStartCall(void* userdata)
{
LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata;
- self->mVoiceChannel->activate();
+ gIMMgr->startCall(self->mSessionUUID);
}
// static
@@ -1809,7 +695,7 @@ void LLFloaterIMPanel::onClickEndCall(void* userdata)
{
LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata;
- self->getVoiceChannel()->deactivate();
+ gIMMgr->endCall(self->mSessionUUID);
}
// static
@@ -1864,107 +750,31 @@ void LLFloaterIMPanel::onInputEditorKeystroke(LLLineEditor* caller, void* userda
}
}
+// virtual
void LLFloaterIMPanel::onClose(bool app_quitting)
{
setTyping(FALSE);
- if(mSessionUUID.notNull())
- {
- std::string name;
- gAgent.buildFullname(name);
- pack_instant_message(
- gMessageSystem,
- gAgent.getID(),
- FALSE,
- gAgent.getSessionID(),
- mOtherParticipantUUID,
- name,
- LLStringUtil::null,
- IM_ONLINE,
- IM_SESSION_LEAVE,
- mSessionUUID);
- gAgent.sendReliableMessage();
- }
- gIMMgr->removeSession(mSessionUUID);
+ gIMMgr->leaveSession(mSessionUUID);
- destroy();
+ // *HACK hide the voice floater
+ LLFloaterReg::hideInstance("voice_call", mSessionUUID);
}
-void LLFloaterIMPanel::onVisibilityChange(BOOL new_visibility)
+void LLFloaterIMPanel::onVisibilityChange(const LLSD& new_visibility)
{
- if (new_visibility)
+ if (new_visibility.asBoolean())
{
mNumUnreadMessages = 0;
}
-}
-
-void deliver_message(const std::string& utf8_text,
- const LLUUID& im_session_id,
- const LLUUID& other_participant_id,
- EInstantMessage dialog)
-{
- std::string name;
- bool sent = false;
- gAgent.buildFullname(name);
-
- const LLRelationship* info = NULL;
- info = LLAvatarTracker::instance().getBuddyInfo(other_participant_id);
-
- U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE;
-
- if((offline == IM_OFFLINE) && (LLVoiceClient::getInstance()->isOnlineSIP(other_participant_id)))
- {
- // User is online through the OOW connector, but not with a regular viewer. Try to send the message via SLVoice.
- sent = gVoiceClient->sendTextMessage(other_participant_id, utf8_text);
- }
- if(!sent)
- {
- // Send message normally.
-
- // default to IM_SESSION_SEND unless it's nothing special - in
- // which case it's probably an IM to everyone.
- U8 new_dialog = dialog;
-
- if ( dialog != IM_NOTHING_SPECIAL )
- {
- new_dialog = IM_SESSION_SEND;
- }
- pack_instant_message(
- gMessageSystem,
- gAgent.getID(),
- FALSE,
- gAgent.getSessionID(),
- other_participant_id,
- name.c_str(),
- utf8_text.c_str(),
- offline,
- (EInstantMessage)new_dialog,
- im_session_id);
- gAgent.sendReliableMessage();
- }
-
- // If there is a mute list and this is not a group chat...
- if ( LLMuteList::getInstance() )
+ LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionUUID);
+ if (voice_channel && voice_channel->getState() == LLVoiceChannel::STATE_CONNECTED)
{
- // ... the target should not be in our mute list for some message types.
- // Auto-remove them if present.
- switch( dialog )
- {
- case IM_NOTHING_SPECIAL:
- case IM_GROUP_INVITATION:
- case IM_INVENTORY_OFFERED:
- case IM_SESSION_INVITE:
- case IM_SESSION_P2P_INVITE:
- case IM_SESSION_CONFERENCE_START:
- case IM_SESSION_SEND: // This one is marginal - erring on the side of hearing.
- case IM_LURE_USER:
- case IM_GODLIKE_LURE_USER:
- case IM_FRIENDSHIP_OFFERED:
- LLMuteList::getInstance()->autoRemove(other_participant_id, LLMuteList::AR_IM);
- break;
- default: ; // do nothing
- }
+ if (new_visibility.asBoolean())
+ LLFloaterReg::showInstance("voice_call", mSessionUUID);
+ else
+ LLFloaterReg::hideInstance("voice_call", mSessionUUID);
}
}
@@ -1983,46 +793,19 @@ void LLFloaterIMPanel::sendMsg()
LLWString text = mInputEditor->getConvertedText();
if(!text.empty())
{
+ // store sent line in history, duplicates will get filtered
+ if (mInputEditor) mInputEditor->updateHistory();
// Truncate and convert to UTF8 for transport
std::string utf8_text = wstring_to_utf8str(text);
utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1);
if ( mSessionInitialized )
{
- deliver_message(utf8_text,
+ LLIMModel::sendMessage(utf8_text,
mSessionUUID,
mOtherParticipantUUID,
mDialog);
- // local echo
- if((mDialog == IM_NOTHING_SPECIAL) &&
- (mOtherParticipantUUID.notNull()))
- {
- std::string history_echo;
- gAgent.buildFullname(history_echo);
-
- // Look for IRC-style emotes here.
- std::string prefix = utf8_text.substr(0, 4);
- if (prefix == "/me " || prefix == "/me'")
- {
- utf8_text.replace(0,3,"");
- }
- else
- {
- history_echo += ": ";
- }
- history_echo += utf8_text;
-
- BOOL other_was_typing = mOtherTyping;
-
- addHistoryLine(history_echo, gSavedSettings.getColor("IMChatColor"), true, gAgent.getID());
-
- if (other_was_typing)
- {
- addTypingIndicator(mOtherTypingName);
- }
-
- }
}
else
{
@@ -2043,11 +826,6 @@ void LLFloaterIMPanel::sendMsg()
mSentTypingState = TRUE;
}
-void LLFloaterIMPanel::updateSpeakersList(const LLSD& speaker_updates)
-{
- mSpeakers->updateSpeakers(speaker_updates);
-}
-
void LLFloaterIMPanel::processSessionUpdate(const LLSD& session_update)
{
if (
@@ -2066,20 +844,17 @@ void LLFloaterIMPanel::processSessionUpdate(const LLSD& session_update)
}
- //update the speakers dropdown too
- mSpeakerPanel->setVoiceModerationCtrlMode(voice_moderated);
+ //update the speakers dropdown too, if it's available
+ if (mSpeakerPanel)
+ {
+ mSpeakerPanel->setVoiceModerationCtrlMode(voice_moderated);
+ }
}
}
-void LLFloaterIMPanel::setSpeakers(const LLSD& speaker_list)
-{
- mSpeakers->setSpeakers(speaker_list);
-}
-
void LLFloaterIMPanel::sessionInitReplyReceived(const LLUUID& session_id)
{
mSessionUUID = session_id;
- mVoiceChannel->updateSessionID(session_id);
mSessionInitialized = TRUE;
//we assume the history editor hasn't moved at all since
@@ -2095,7 +870,7 @@ void LLFloaterIMPanel::sessionInitReplyReceived(const LLUUID& session_id)
iter != mQueuedMsgsForInit.endArray();
++iter)
{
- deliver_message(
+ LLIMModel::sendMessage(
iter->asString(),
mSessionUUID,
mOtherParticipantUUID,
@@ -2103,13 +878,9 @@ void LLFloaterIMPanel::sessionInitReplyReceived(const LLUUID& session_id)
}
}
-void LLFloaterIMPanel::requestAutoConnect()
-{
- mAutoConnect = TRUE;
-}
-
void LLFloaterIMPanel::setTyping(BOOL typing)
{
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionUUID);
if (typing)
{
// Every time you type something, reset this timer
@@ -2123,8 +894,9 @@ void LLFloaterIMPanel::setTyping(BOOL typing)
// Will send typing state after a short delay.
mSentTypingState = FALSE;
}
-
- mSpeakers->setSpeakerTyping(gAgent.getID(), TRUE);
+
+ if (speaker_mgr)
+ speaker_mgr->setSpeakerTyping(gAgent.getID(), TRUE);
}
else
{
@@ -2134,7 +906,8 @@ void LLFloaterIMPanel::setTyping(BOOL typing)
sendTypingState(FALSE);
mSentTypingState = TRUE;
}
- mSpeakers->setSpeakerTyping(gAgent.getID(), FALSE);
+ if (speaker_mgr)
+ speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE);
}
mTyping = typing;
@@ -2146,23 +919,10 @@ void LLFloaterIMPanel::sendTypingState(BOOL typing)
// much network traffic. Only send in person-to-person IMs.
if (mDialog != IM_NOTHING_SPECIAL) return;
- std::string name;
- gAgent.buildFullname(name);
-
- pack_instant_message(
- gMessageSystem,
- gAgent.getID(),
- FALSE,
- gAgent.getSessionID(),
- mOtherParticipantUUID,
- name,
- std::string("typing"),
- IM_ONLINE,
- (typing ? IM_TYPING_START : IM_TYPING_STOP),
- mSessionUUID);
- gAgent.sendReliableMessage();
+ LLIMModel::instance().sendTypingState(mSessionUUID, mOtherParticipantUUID, typing);
}
+
void LLFloaterIMPanel::processIMTyping(const LLIMInfo* im_info, BOOL typing)
{
if (typing)
@@ -2186,7 +946,7 @@ void LLFloaterIMPanel::addTypingIndicator(const std::string &name)
mTypingLineStartIndex = mHistoryEditor->getWText().length();
LLUIString typing_start = sTypingStartString;
typing_start.setArg("[NAME]", name);
- addHistoryLine(typing_start, gSavedSettings.getColor4("SystemChatColor"), false);
+ addHistoryLine(typing_start, LLUIColorTable::instance().getColor("SystemChatColor"), false);
mOtherTypingName = name;
mOtherTyping = TRUE;
}
@@ -2207,106 +967,13 @@ void LLFloaterIMPanel::removeTypingIndicator(const LLIMInfo* im_info)
mHistoryEditor->removeTextFromEnd(chars_to_remove);
if (im_info)
{
- mSpeakers->setSpeakerTyping(im_info->mFromID, FALSE);
- }
- }
-}
-
-//static
-void LLFloaterIMPanel::chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata)
-{
- LLFloaterIMPanel* self = (LLFloaterIMPanel*)userdata;
- std::string message = line;
-
- switch (type)
- {
- case LLLogChat::LOG_EMPTY:
- // add warning log enabled message
- if (gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
- {
- message = LLFloaterChat::getInstance()->getString("IM_logging_string");
- }
- break;
- case LLLogChat::LOG_END:
- // add log end message
- if (gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
- {
- message = LLFloaterChat::getInstance()->getString("IM_logging_string");
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionUUID);
+ if (speaker_mgr)
+ {
+ speaker_mgr->setSpeakerTyping(im_info->mFromID, FALSE);
+ }
}
- break;
- case LLLogChat::LOG_LINE:
- // just add normal lines from file
- break;
- default:
- // nothing
- break;
}
-
- //self->addHistoryLine(line, LLColor4::grey, FALSE);
- self->mHistoryEditor->appendColoredText(message, false, true, LLColor4::grey);
-}
-
-void LLFloaterIMPanel::showSessionStartError(
- const std::string& error_string)
-{
- //the error strings etc. should be really be static and local
- //to this file instead of in the LLFloaterIM
- //but they were in llimview.cpp first and unfortunately
- //some translations into non English languages already occurred
- //thus making it a tad harder to change over to a
- //"correct" solution. The best solution
- //would be to store all of the misc. strings into
- //their own XML file which would be read in by any LLIMPanel
- //post build function instead of repeating the same info
- //in the group, adhoc and normal IM xml files.
- LLSD args;
- args["REASON"] =
- LLFloaterIM::sErrorStringsMap[error_string];
- args["RECIPIENT"] = getTitle();
-
- LLSD payload;
- payload["session_id"] = mSessionUUID;
-
- LLNotifications::instance().add(
- "ChatterBoxSessionStartError",
- args,
- payload,
- onConfirmForceCloseError);
-}
-
-void LLFloaterIMPanel::showSessionEventError(
- const std::string& event_string,
- const std::string& error_string)
-{
- LLSD args;
- args["REASON"] =
- LLFloaterIM::sErrorStringsMap[error_string];
- args["EVENT"] =
- LLFloaterIM::sEventStringsMap[event_string];
- args["RECIPIENT"] = getTitle();
-
- LLNotifications::instance().add(
- "ChatterBoxSessionEventError",
- args);
-}
-
-void LLFloaterIMPanel::showSessionForceClose(
- const std::string& reason_string)
-{
- LLSD args;
-
- args["NAME"] = getTitle();
- args["REASON"] = LLFloaterIM::sForceCloseSessionMap[reason_string];
-
- LLSD payload;
- payload["session_id"] = mSessionUUID;
-
- LLNotifications::instance().add(
- "ForceCloseChatterBoxSession",
- args,
- payload,
- LLFloaterIMPanel::onConfirmForceCloseError);
-
}
//static
@@ -2314,20 +981,3 @@ void LLFloaterIMPanel::onKickSpeaker(void* user_data)
{
}
-
-bool LLFloaterIMPanel::onConfirmForceCloseError(const LLSD& notification, const LLSD& response)
-{
- //only 1 option really
- LLUUID session_id = notification["payload"]["session_id"];
-
- if ( gIMMgr )
- {
- LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(
- session_id);
-
- if ( floaterp ) floaterp->close(FALSE);
- }
- return false;
-}
-
-
diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h
index 8b3ca202c7..abbf1e68ab 100644
--- a/indra/newview/llimpanel.h
+++ b/indra/newview/llimpanel.h
@@ -33,7 +33,7 @@
#ifndef LL_IMPANEL_H
#define LL_IMPANEL_H
-#include "llfloater.h"
+#include "lldockablefloater.h"
#include "lllogchat.h"
#include "lluuid.h"
#include "lldarray.h"
@@ -47,131 +47,7 @@ class LLInventoryItem;
class LLInventoryCategory;
class LLIMSpeakerMgr;
class LLPanelActiveSpeakers;
-
-class LLVoiceChannel : public LLVoiceClientStatusObserver
-{
-public:
- typedef enum e_voice_channel_state
- {
- STATE_NO_CHANNEL_INFO,
- STATE_ERROR,
- STATE_HUNG_UP,
- STATE_READY,
- STATE_CALL_STARTED,
- STATE_RINGING,
- STATE_CONNECTED
- } EState;
-
- LLVoiceChannel(const LLUUID& session_id, const std::string& session_name);
- virtual ~LLVoiceChannel();
-
- /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
-
- virtual void handleStatusChange(EStatusType status);
- virtual void handleError(EStatusType status);
- virtual void deactivate();
- virtual void activate();
- virtual void setChannelInfo(
- const std::string& uri,
- const std::string& credentials);
- virtual void getChannelInfo();
- virtual BOOL isActive();
- virtual BOOL callStarted();
-
- const LLUUID getSessionID() { return mSessionID; }
- EState getState() { return mState; }
-
- void updateSessionID(const LLUUID& new_session_id);
- const LLSD& getNotifyArgs() { return mNotifyArgs; }
-
- static LLVoiceChannel* getChannelByID(const LLUUID& session_id);
- static LLVoiceChannel* getChannelByURI(std::string uri);
- static LLVoiceChannel* getCurrentVoiceChannel() { return sCurrentVoiceChannel; }
- static void initClass();
-
- static void suspend();
- static void resume();
-
-protected:
- virtual void setState(EState state);
- void setURI(std::string uri);
-
- std::string mURI;
- std::string mCredentials;
- LLUUID mSessionID;
- EState mState;
- std::string mSessionName;
- LLSD mNotifyArgs;
- BOOL mIgnoreNextSessionLeave;
- LLHandle<LLPanel> mLoginNotificationHandle;
-
- typedef std::map<LLUUID, LLVoiceChannel*> voice_channel_map_t;
- static voice_channel_map_t sVoiceChannelMap;
-
- typedef std::map<std::string, LLVoiceChannel*> voice_channel_map_uri_t;
- static voice_channel_map_uri_t sVoiceChannelURIMap;
-
- static LLVoiceChannel* sCurrentVoiceChannel;
- static LLVoiceChannel* sSuspendedVoiceChannel;
- static BOOL sSuspended;
-};
-
-class LLVoiceChannelGroup : public LLVoiceChannel
-{
-public:
- LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name);
-
- /*virtual*/ void handleStatusChange(EStatusType status);
- /*virtual*/ void handleError(EStatusType status);
- /*virtual*/ void activate();
- /*virtual*/ void deactivate();
- /*vritual*/ void setChannelInfo(
- const std::string& uri,
- const std::string& credentials);
- /*virtual*/ void getChannelInfo();
-
-protected:
- virtual void setState(EState state);
-
-private:
- U32 mRetries;
- BOOL mIsRetrying;
-};
-
-class LLVoiceChannelProximal : public LLVoiceChannel, public LLSingleton<LLVoiceChannelProximal>
-{
-public:
- LLVoiceChannelProximal();
-
- /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
- /*virtual*/ void handleStatusChange(EStatusType status);
- /*virtual*/ void handleError(EStatusType status);
- /*virtual*/ BOOL isActive();
- /*virtual*/ void activate();
- /*virtual*/ void deactivate();
-
-};
-
-class LLVoiceChannelP2P : public LLVoiceChannelGroup
-{
-public:
- LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id);
-
- /*virtual*/ void handleStatusChange(EStatusType status);
- /*virtual*/ void handleError(EStatusType status);
- /*virtual*/ void activate();
- /*virtual*/ void getChannelInfo();
-
- void setSessionHandle(const std::string& handle, const std::string &inURI);
-
-protected:
- virtual void setState(EState state);
-
-private:
- std::string mSessionHandle;
- LLUUID mOtherUserID;
- BOOL mReceivedCall;
-};
+class LLPanelChatControlPanel;
class LLFloaterIMPanel : public LLFloater
{
@@ -185,11 +61,7 @@ public:
LLFloaterIMPanel(const std::string& session_label,
const LLUUID& session_id,
const LLUUID& target_id,
- EInstantMessage dialog);
- LLFloaterIMPanel(const std::string& session_label,
- const LLUUID& session_id,
- const LLUUID& target_id,
- const LLDynamicArray<LLUUID>& ids,
+ const std::vector<LLUUID>& ids,
EInstantMessage dialog);
virtual ~LLFloaterIMPanel();
@@ -197,12 +69,13 @@ public:
// Check typing timeout timer.
/*virtual*/ void draw();
- /*virtual*/ void onClose(bool app_quitting = FALSE);
- /*virtual*/ void onVisibilityChange(BOOL new_visibility);
+
+ /*virtual*/ void onClose(bool app_quitting);
+ void onVisibilityChange(const LLSD& new_visibility);
// add target ids to the session.
// Return TRUE if successful, otherwise FALSE.
- BOOL inviteToSession(const LLDynamicArray<LLUUID>& agent_ids);
+ BOOL inviteToSession(const std::vector<LLUUID>& agent_ids);
void addHistoryLine(const std::string &utf8msg,
const LLColor4& color = LLColor4::white,
@@ -214,7 +87,6 @@ public:
void selectAll();
void selectNone();
- void setVisible(BOOL b);
S32 getNumUnreadMessages() { return mNumUnreadMessages; }
@@ -246,33 +118,16 @@ public:
const LLUUID& getSessionID() const { return mSessionUUID; }
const LLUUID& getOtherParticipantID() const { return mOtherParticipantUUID; }
- void updateSpeakersList(const LLSD& speaker_updates);
void processSessionUpdate(const LLSD& update);
- void setSpeakers(const LLSD& speaker_list);
- LLVoiceChannel* getVoiceChannel() { return mVoiceChannel; }
EInstantMessage getDialogType() const { return mDialog; }
-
- void requestAutoConnect();
+ void setDialogType(EInstantMessage dialog) { mDialog = dialog; }
void sessionInitReplyReceived(const LLUUID& im_session_id);
// Handle other participant in the session typing.
void processIMTyping(const LLIMInfo* im_info, BOOL typing);
- static void chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata);
-
- //show error statuses to the user
- void showSessionStartError(const std::string& error_string);
- void showSessionEventError(
- const std::string& event_string,
- const std::string& error_string);
- void showSessionForceClose(const std::string& reason);
-
- static bool onConfirmForceCloseError(const LLSD& notification, const LLSD& response);
private:
- // called by constructors
- void init(const std::string& session_label);
-
// Called by UI methods.
void sendMsg();
@@ -307,7 +162,6 @@ private:
LLUUID mSessionUUID;
std::string mSessionLabel;
- LLVoiceChannel* mVoiceChannel;
BOOL mSessionInitialized;
LLSD mQueuedMsgsForInit;
@@ -318,7 +172,7 @@ private:
// inventory folder ==> first target id in list
// 911 ==> sender
LLUUID mOtherParticipantUUID;
- LLDynamicArray<LLUUID> mSessionInitialTargetIDs;
+ std::vector<LLUUID> mSessionInitialTargetIDs;
EInstantMessage mDialog;
@@ -342,13 +196,10 @@ private:
BOOL mShowSpeakersOnConnect;
- BOOL mAutoConnect;
-
BOOL mTextIMPossible;
BOOL mProfileButtonEnabled;
BOOL mCallBackEnabled;
- LLIMSpeakerMgr* mSpeakers;
LLPanelActiveSpeakers* mSpeakerPanel;
// Optimization: Don't send "User is typing..." until the
@@ -359,11 +210,9 @@ private:
// Timer to detect when user has stopped typing.
LLFrameTimer mLastKeystrokeTimer;
- void disableWhileSessionStarting();
+ boost::signals2::connection mFocusCallbackConnection;
- typedef std::map<LLUUID, LLStyleSP> styleMap;
- static styleMap mStyleMap;
+ void disableWhileSessionStarting();
};
-
#endif // LL_IMPANEL_H
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index a90ea39265..32b0cbff38 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -34,70 +34,1124 @@
#include "llimview.h"
+#include "llfloaterreg.h"
#include "llfontgl.h"
#include "llrect.h"
#include "llerror.h"
#include "llbutton.h"
#include "llhttpclient.h"
-#include "llsdutil.h"
+#include "llsdutil_math.h"
#include "llstring.h"
+#include "lltrans.h"
#include "lluictrlfactory.h"
#include "llagent.h"
+#include "llagentui.h"
+#include "llappviewer.h"
+#include "llavatariconctrl.h"
+#include "llbottomtray.h"
#include "llcallingcard.h"
#include "llchat.h"
-#include "llresmgr.h"
-#include "llfloaterchat.h"
#include "llfloaterchatterbox.h"
-#include "llfloaternewim.h"
-#include "llhttpnode.h"
-#include "llimpanel.h"
-#include "llresizebar.h"
-#include "lltabcontainer.h"
-#include "llviewercontrol.h"
-#include "llfloater.h"
+#include "llimfloater.h"
+#include "llgroupiconctrl.h"
+#include "llmd5.h"
#include "llmutelist.h"
-#include "llresizehandle.h"
-#include "llkeyboard.h"
-#include "llui.h"
-#include "llviewermenu.h"
-#include "llcallingcard.h"
-#include "lltoolbar.h"
+#include "llrecentpeople.h"
#include "llviewermessage.h"
#include "llviewerwindow.h"
-#include "llnotify.h"
-#include "llviewerregion.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+#include "llnearbychat.h"
+#include "llspeakers.h" //for LLIMSpeakerMgr
+#include "lltextutil.h"
+#include "llviewercontrol.h"
+
+
+const static std::string IM_TIME("time");
+const static std::string IM_TEXT("message");
+const static std::string IM_FROM("from");
+const static std::string IM_FROM_ID("from_id");
-#include "llfirstuse.h"
+const static std::string NO_SESSION("(IM Session Doesn't Exist)");
+const static std::string ADHOC_NAME_SUFFIX(" Conference");
+std::string LLCallDialogManager::sPreviousSessionlName = "";
+LLIMModel::LLIMSession::SType LLCallDialogManager::sPreviousSessionType = LLIMModel::LLIMSession::P2P_SESSION;
+std::string LLCallDialogManager::sCurrentSessionlName = "";
+LLIMModel::LLIMSession* LLCallDialogManager::sSession = NULL;
+LLVoiceChannel::EState LLCallDialogManager::sOldState = LLVoiceChannel::STATE_READY;
+const LLUUID LLOutgoingCallDialog::OCD_KEY = LLUUID("7CF78E11-0CFE-498D-ADB9-1417BF03DDB4");
//
// Globals
//
LLIMMgr* gIMMgr = NULL;
-//
-// Statics
-//
-// *FIXME: make these all either UIStrings or Strings
-static std::string sOnlyUserMessage;
-static LLUIString sOfflineMessage;
-static std::string sMutedMessage;
-static LLUIString sInviteMessage;
+void toast_callback(const LLSD& msg){
+ // do not show toast in busy mode or it goes from agent
+ if (gAgent.getBusy() || gAgent.getID() == msg["from_id"])
+ {
+ return;
+ }
+
+ // check whether incoming IM belongs to an active session or not
+ if (LLIMModel::getInstance()->getActiveSessionID() == msg["session_id"])
+ {
+ return;
+ }
+
+ // Skip toasting for system messages
+ if (msg["from_id"].asUUID() == LLUUID::null)
+ {
+ return;
+ }
+
+ // Skip toasting if we have open window of IM with this session id
+ LLIMFloater* open_im_floater = LLIMFloater::findInstance(msg["session_id"]);
+ if (open_im_floater && open_im_floater->getVisible())
+ {
+ return;
+ }
+
+ LLSD args;
+ args["MESSAGE"] = msg["message"];
+ args["TIME"] = msg["time"];
+ args["FROM"] = msg["from"];
+ args["FROM_ID"] = msg["from_id"];
+ args["SESSION_ID"] = msg["session_id"];
+
+ LLNotificationsUtil::add("IMToast", args, LLSD(), boost::bind(&LLIMFloater::show, msg["session_id"].asUUID()));
+}
+
+void LLIMModel::setActiveSessionID(const LLUUID& session_id)
+{
+ // check if such an ID really exists
+ if (!findIMSession(session_id))
+ {
+ llwarns << "Trying to set as active a non-existent session!" << llendl;
+ return;
+ }
+
+ mActiveSessionID = session_id;
+}
+
+LLIMModel::LLIMModel()
+{
+ addNewMsgCallback(LLIMFloater::newIMCallback);
+ addNewMsgCallback(toast_callback);
+}
+
+LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const std::vector<LLUUID>& ids, bool voice)
+: mSessionID(session_id),
+ mName(name),
+ mType(type),
+ mParticipantUnreadMessageCount(0),
+ mNumUnread(0),
+ mOtherParticipantID(other_participant_id),
+ mInitialTargetIDs(ids),
+ mVoiceChannel(NULL),
+ mSpeakers(NULL),
+ mSessionInitialized(false),
+ mCallBackEnabled(true),
+ mTextIMPossible(true),
+ mOtherParticipantIsAvatar(true),
+ mStartCallOnInitialize(false),
+ mStartedAsIMCall(voice)
+{
+ // set P2P type by default
+ mSessionType = P2P_SESSION;
+
+ if (IM_NOTHING_SPECIAL == type || IM_SESSION_P2P_INVITE == type)
+ {
+ mVoiceChannel = new LLVoiceChannelP2P(session_id, name, other_participant_id);
+ mOtherParticipantIsAvatar = LLVoiceClient::getInstance()->isParticipantAvatar(mSessionID);
+
+ // check if it was AVALINE call
+ if (!mOtherParticipantIsAvatar)
+ {
+ mSessionType = AVALINE_SESSION;
+ }
+ }
+ else
+ {
+ mVoiceChannel = new LLVoiceChannelGroup(session_id, name);
+
+ // determine whether it is group or conference session
+ if (gAgent.isInGroup(mSessionID))
+ {
+ mSessionType = GROUP_SESSION;
+ }
+ else
+ {
+ mSessionType = ADHOC_SESSION;
+ }
+ }
+
+ if(mVoiceChannel)
+ {
+ mVoiceChannelStateChangeConnection = mVoiceChannel->setStateChangedCallback(boost::bind(&LLIMSession::onVoiceChannelStateChanged, this, _1, _2, _3));
+ }
+
+ mSpeakers = new LLIMSpeakerMgr(mVoiceChannel);
+
+ // All participants will be added to the list of people we've recently interacted with.
+
+ // we need to add only _active_ speakers...so comment this.
+ // may delete this later on cleanup
+ //mSpeakers->addListener(&LLRecentPeople::instance(), "add");
+
+ //we need to wait for session initialization for outgoing ad-hoc and group chat session
+ //correct session id for initiated ad-hoc chat will be received from the server
+ if (!LLIMModel::getInstance()->sendStartSession(mSessionID, mOtherParticipantID,
+ mInitialTargetIDs, mType))
+ {
+ //we don't need to wait for any responses
+ //so we're already initialized
+ mSessionInitialized = true;
+ }
+
+ if (IM_NOTHING_SPECIAL == type)
+ {
+ mCallBackEnabled = LLVoiceClient::getInstance()->isSessionCallBackPossible(mSessionID);
+ mTextIMPossible = LLVoiceClient::getInstance()->isSessionTextIMPossible(mSessionID);
+ }
+
+ buildHistoryFileName();
+
+ if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
+ {
+ std::list<LLSD> chat_history;
+
+ //involves parsing of a chat history
+ LLLogChat::loadAllHistory(mHistoryFileName, chat_history);
+ addMessagesFromHistory(chat_history);
+ }
+}
+
+void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction)
+{
+ std::string you = LLTrans::getString("You");
+ std::string started_call = LLTrans::getString("started_call");
+ std::string joined_call = LLTrans::getString("joined_call");
+ std::string other_avatar_name = "";
+
+ std::string message;
+
+ switch(mSessionType)
+ {
+ case AVALINE_SESSION:
+ // no text notifications
+ break;
+ case P2P_SESSION:
+ gCacheName->getFullName(mOtherParticipantID, other_avatar_name);
+
+ if(direction == LLVoiceChannel::INCOMING_CALL)
+ {
+ switch(new_state)
+ {
+ case LLVoiceChannel::STATE_CALL_STARTED :
+ message = other_avatar_name + " " + started_call;
+ LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);
+
+ break;
+ case LLVoiceChannel::STATE_CONNECTED :
+ message = you + " " + joined_call;
+ LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);
+ default:
+ break;
+ }
+ }
+ else // outgoing call
+ {
+ switch(new_state)
+ {
+ case LLVoiceChannel::STATE_CALL_STARTED :
+ message = you + " " + started_call;
+ LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);
+ break;
+ case LLVoiceChannel::STATE_CONNECTED :
+ message = other_avatar_name + " " + joined_call;
+ LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);
+ default:
+ break;
+ }
+ }
+ break;
+
+ case GROUP_SESSION:
+ case ADHOC_SESSION:
+ if(direction == LLVoiceChannel::INCOMING_CALL)
+ {
+ switch(new_state)
+ {
+ case LLVoiceChannel::STATE_CONNECTED :
+ message = you + " " + joined_call;
+ LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);
+ default:
+ break;
+ }
+ }
+ else // outgoing call
+ {
+ switch(new_state)
+ {
+ case LLVoiceChannel::STATE_CALL_STARTED :
+ message = you + " " + started_call;
+ LLIMModel::getInstance()->addMessageSilently(mSessionID, SYSTEM_FROM, LLUUID::null, message);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ // Update speakers list when connected
+ if (LLVoiceChannel::STATE_CONNECTED == new_state)
+ {
+ mSpeakers->update(true);
+ }
+}
+
+LLIMModel::LLIMSession::~LLIMSession()
+{
+ delete mSpeakers;
+ mSpeakers = NULL;
+
+ // End the text IM session if necessary
+ if(gVoiceClient && mOtherParticipantID.notNull())
+ {
+ switch(mType)
+ {
+ case IM_NOTHING_SPECIAL:
+ case IM_SESSION_P2P_INVITE:
+ gVoiceClient->endUserIMSession(mOtherParticipantID);
+ break;
+
+ default:
+ // Appease the linux compiler
+ break;
+ }
+ }
+
+ mVoiceChannelStateChangeConnection.disconnect();
+
+ // HAVE to do this here -- if it happens in the LLVoiceChannel destructor it will call the wrong version (since the object's partially deconstructed at that point).
+ mVoiceChannel->deactivate();
+
+ delete mVoiceChannel;
+ mVoiceChannel = NULL;
+}
+
+void LLIMModel::LLIMSession::sessionInitReplyReceived(const LLUUID& new_session_id)
+{
+ mSessionInitialized = true;
+
+ if (new_session_id != mSessionID)
+ {
+ mSessionID = new_session_id;
+ mVoiceChannel->updateSessionID(new_session_id);
+ }
+}
+
+void LLIMModel::LLIMSession::addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time)
+{
+ LLSD message;
+ message["from"] = from;
+ message["from_id"] = from_id;
+ message["message"] = utf8_text;
+ message["time"] = time;
+ message["index"] = (LLSD::Integer)mMsgs.size();
+
+ mMsgs.push_front(message);
+
+ if (mSpeakers && from_id.notNull())
+ {
+ mSpeakers->speakerChatted(from_id);
+ mSpeakers->setSpeakerTyping(from_id, FALSE);
+ }
+}
-std::map<std::string,std::string> LLFloaterIM::sEventStringsMap;
-std::map<std::string,std::string> LLFloaterIM::sErrorStringsMap;
-std::map<std::string,std::string> LLFloaterIM::sForceCloseSessionMap;
+void LLIMModel::LLIMSession::addMessagesFromHistory(const std::list<LLSD>& history)
+{
+ std::list<LLSD>::const_iterator it = history.begin();
+ while (it != history.end())
+ {
+ const LLSD& msg = *it;
+
+ std::string from = msg[IM_FROM];
+ LLUUID from_id = LLUUID::null;
+ if (msg[IM_FROM_ID].isUndefined())
+ {
+ gCacheName->getUUID(from, from_id);
+ }
+
+
+ std::string timestamp = msg[IM_TIME];
+ std::string text = msg[IM_TEXT];
+
+ addMessage(from, from_id, text, timestamp);
+
+ it++;
+ }
+}
+
+void LLIMModel::LLIMSession::chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata)
+{
+ if (!userdata) return;
+
+ LLIMSession* self = (LLIMSession*) userdata;
+
+ if (type == LLLogChat::LOG_LINE)
+ {
+ self->addMessage("", LLSD(), msg["message"].asString(), "");
+ }
+ else if (type == LLLogChat::LOG_LLSD)
+ {
+ self->addMessage(msg["from"].asString(), msg["from_id"].asUUID(), msg["message"].asString(), msg["time"].asString());
+ }
+}
+
+LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const
+{
+ return get_if_there(mId2SessionMap, session_id,
+ (LLIMModel::LLIMSession*) NULL);
+}
+
+//*TODO consider switching to using std::set instead of std::list for holding LLUUIDs across the whole code
+LLIMModel::LLIMSession* LLIMModel::findAdHocIMSession(const std::vector<LLUUID>& ids)
+{
+ S32 num = ids.size();
+ if (!num) return NULL;
+
+ if (mId2SessionMap.empty()) return NULL;
+
+ std::map<LLUUID, LLIMSession*>::const_iterator it = mId2SessionMap.begin();
+ for (; it != mId2SessionMap.end(); ++it)
+ {
+ LLIMSession* session = (*it).second;
+
+ if (!session->isAdHoc()) continue;
+ if (session->mInitialTargetIDs.size() != num) continue;
+
+ std::list<LLUUID> tmp_list(session->mInitialTargetIDs.begin(), session->mInitialTargetIDs.end());
+
+ std::vector<LLUUID>::const_iterator iter = ids.begin();
+ while (iter != ids.end())
+ {
+ tmp_list.remove(*iter);
+ ++iter;
+
+ if (tmp_list.empty())
+ {
+ break;
+ }
+ }
+
+ if (tmp_list.empty() && iter == ids.end())
+ {
+ return session;
+ }
+ }
+
+ return NULL;
+}
+
+bool LLIMModel::LLIMSession::isAdHoc()
+{
+ return IM_SESSION_CONFERENCE_START == mType || (IM_SESSION_INVITE == mType && !gAgent.isInGroup(mSessionID));
+}
+
+bool LLIMModel::LLIMSession::isP2P()
+{
+ return IM_NOTHING_SPECIAL == mType;
+}
+
+bool LLIMModel::LLIMSession::isOtherParticipantAvaline()
+{
+ return !mOtherParticipantIsAvatar;
+}
+
+void LLIMModel::LLIMSession::buildHistoryFileName()
+{
+ mHistoryFileName = mName;
+
+ //ad-hoc requires sophisticated chat history saving schemes
+ if (isAdHoc())
+ {
+ //in case of outgoing ad-hoc sessions
+ if (mInitialTargetIDs.size())
+ {
+ std::set<LLUUID> sorted_uuids(mInitialTargetIDs.begin(), mInitialTargetIDs.end());
+ mHistoryFileName = mName + " hash" + generateHash(sorted_uuids);
+ return;
+ }
+
+ //in case of incoming ad-hoc sessions
+ mHistoryFileName = mName + " " + LLLogChat::timestamp(true) + " " + mSessionID.asString().substr(0, 4);
+ }
+}
+
+//static
+std::string LLIMModel::LLIMSession::generateHash(const std::set<LLUUID>& sorted_uuids)
+{
+ LLMD5 md5_uuid;
+
+ std::set<LLUUID>::const_iterator it = sorted_uuids.begin();
+ while (it != sorted_uuids.end())
+ {
+ md5_uuid.update((unsigned char*)(*it).mData, 16);
+ it++;
+ }
+ md5_uuid.finalize();
+
+ LLUUID participants_md5_hash;
+ md5_uuid.raw_digest((unsigned char*) participants_md5_hash.mData);
+ return participants_md5_hash.asString();
+}
+
+
+void LLIMModel::processSessionInitializedReply(const LLUUID& old_session_id, const LLUUID& new_session_id)
+{
+ LLIMSession* session = findIMSession(old_session_id);
+ if (session)
+ {
+ session->sessionInitReplyReceived(new_session_id);
+
+ if (old_session_id != new_session_id)
+ {
+ mId2SessionMap.erase(old_session_id);
+ mId2SessionMap[new_session_id] = session;
+
+ gIMMgr->notifyObserverSessionIDUpdated(old_session_id, new_session_id);
+ }
+
+ LLIMFloater* im_floater = LLIMFloater::findInstance(old_session_id);
+ if (im_floater)
+ {
+ im_floater->sessionInitReplyReceived(new_session_id);
+ }
+
+ // auto-start the call on session initialization?
+ if (session->mStartCallOnInitialize)
+ {
+ gIMMgr->startCall(new_session_id);
+ }
+ }
+
+ //*TODO remove this "floater" stuff when Communicate Floater is gone
+ LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(old_session_id);
+ if (floater)
+ {
+ floater->sessionInitReplyReceived(new_session_id);
+ }
+}
+
+void LLIMModel::testMessages()
+{
+ LLUUID bot1_id("d0426ec6-6535-4c11-a5d9-526bb0c654d9");
+ LLUUID bot1_session_id;
+ std::string from = "IM Tester";
+
+ bot1_session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, bot1_id);
+ newSession(bot1_session_id, from, IM_NOTHING_SPECIAL, bot1_id);
+ addMessage(bot1_session_id, from, bot1_id, "Test Message: Hi from testerbot land!");
+
+ LLUUID bot2_id;
+ std::string firstname[] = {"Roflcopter", "Joe"};
+ std::string lastname[] = {"Linden", "Tester", "Resident", "Schmoe"};
+
+ S32 rand1 = ll_rand(sizeof firstname)/(sizeof firstname[0]);
+ S32 rand2 = ll_rand(sizeof lastname)/(sizeof lastname[0]);
+
+ from = firstname[rand1] + " " + lastname[rand2];
+ bot2_id.generate(from);
+ LLUUID bot2_session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, bot2_id);
+ newSession(bot2_session_id, from, IM_NOTHING_SPECIAL, bot2_id);
+ addMessage(bot2_session_id, from, bot2_id, "Test Message: Hello there, I have a question. Can I bother you for a second? ");
+ addMessage(bot2_session_id, from, bot2_id, "Test Message: OMGWTFBBQ.");
+}
+
+//session name should not be empty
+bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type,
+ const LLUUID& other_participant_id, const std::vector<LLUUID>& ids, bool voice)
+{
+ if (name.empty())
+ {
+ llwarns << "Attempt to create a new session with empty name; id = " << session_id << llendl;
+ return false;
+ }
+
+ if (findIMSession(session_id))
+ {
+ llwarns << "IM Session " << session_id << " already exists" << llendl;
+ return false;
+ }
+
+ LLIMSession* session = new LLIMSession(session_id, name, type, other_participant_id, ids, voice);
+ mId2SessionMap[session_id] = session;
+
+ LLIMMgr::getInstance()->notifyObserverSessionAdded(session_id, name, other_participant_id);
+
+ return true;
+
+}
+
+bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, bool voice)
+{
+ std::vector<LLUUID> no_ids;
+ return newSession(session_id, name, type, other_participant_id, no_ids, voice);
+}
+
+bool LLIMModel::clearSession(const LLUUID& session_id)
+{
+ if (mId2SessionMap.find(session_id) == mId2SessionMap.end()) return false;
+ delete (mId2SessionMap[session_id]);
+ mId2SessionMap.erase(session_id);
+ return true;
+}
+
+void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index)
+{
+ LLIMSession* session = findIMSession(session_id);
+ if (!session)
+ {
+ llwarns << "session " << session_id << "does not exist " << llendl;
+ return;
+ }
+
+ int i = session->mMsgs.size() - start_index;
+
+ for (std::list<LLSD>::iterator iter = session->mMsgs.begin();
+ iter != session->mMsgs.end() && i > 0;
+ iter++)
+ {
+ LLSD msg;
+ msg = *iter;
+ messages.push_back(*iter);
+ i--;
+ }
+
+ session->mNumUnread = 0;
+ session->mParticipantUnreadMessageCount = 0;
+
+ LLSD arg;
+ arg["session_id"] = session_id;
+ arg["num_unread"] = 0;
+ arg["participant_unread"] = session->mParticipantUnreadMessageCount;
+ mNoUnreadMsgsSignal(arg);
+}
+
+bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) {
+
+ LLIMSession* session = findIMSession(session_id);
+
+ if (!session)
+ {
+ llwarns << "session " << session_id << "does not exist " << llendl;
+ return false;
+ }
+
+ session->addMessage(from, from_id, utf8_text, LLLogChat::timestamp(false)); //might want to add date separately
+
+ return true;
+}
+
+bool LLIMModel::logToFile(const std::string& file_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text)
+{
+ if (gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
+ {
+ LLLogChat::saveHistory(file_name, from, from_id, utf8_text);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool LLIMModel::logToFile(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text)
+{
+ return logToFile(LLIMModel::getInstance()->getHistoryFileName(session_id), from, from_id, utf8_text);
+}
+
+bool LLIMModel::proccessOnlineOfflineNotification(
+ const LLUUID& session_id,
+ const std::string& utf8_text)
+{
+ // Add message to old one floater
+ LLFloaterIMPanel *floater = gIMMgr->findFloaterBySession(session_id);
+ if ( floater )
+ {
+ if ( !utf8_text.empty() )
+ {
+ floater->addHistoryLine(utf8_text, LLUIColorTable::instance().getColor("SystemChatColor"));
+ }
+ }
+ // Add system message to history
+ return addMessage(session_id, SYSTEM_FROM, LLUUID::null, utf8_text);
+}
+
+bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& from_id,
+ const std::string& utf8_text, bool log2file /* = true */) {
+
+ LLIMSession* session = addMessageSilently(session_id, from, from_id, utf8_text, log2file);
+ if (!session) return false;
+
+ //good place to add some1 to recent list
+ //other places may be called from message history.
+ if( !from_id.isNull() &&
+ ( session->isP2PSessionType() || session->isAdHocSessionType() ) )
+ LLRecentPeople::instance().add(from_id);
+
+ // notify listeners
+ LLSD arg;
+ arg["session_id"] = session_id;
+ arg["num_unread"] = session->mNumUnread;
+ arg["participant_unread"] = session->mParticipantUnreadMessageCount;
+ arg["message"] = utf8_text;
+ arg["from"] = from;
+ arg["from_id"] = from_id;
+ arg["time"] = LLLogChat::timestamp(false);
+ mNewMsgSignal(arg);
+
+ return true;
+}
+
+LLIMModel::LLIMSession* LLIMModel::addMessageSilently(const LLUUID& session_id, const std::string& from, const LLUUID& from_id,
+ const std::string& utf8_text, bool log2file /* = true */)
+{
+ LLIMSession* session = findIMSession(session_id);
+
+ if (!session)
+ {
+ llwarns << "session " << session_id << "does not exist " << llendl;
+ return NULL;
+ }
+
+ addToHistory(session_id, from, from_id, utf8_text);
+ if (log2file) logToFile(session_id, from, from_id, utf8_text);
+
+ session->mNumUnread++;
+
+ //update count of unread messages from real participant
+ if (!(from_id.isNull() || from_id == gAgentID || SYSTEM_FROM == from))
+ {
+ ++(session->mParticipantUnreadMessageCount);
+ }
+
+ return session;
+}
+
+
+const std::string& LLIMModel::getName(const LLUUID& session_id) const
+{
+ LLIMSession* session = findIMSession(session_id);
+
+ if (!session)
+ {
+ llwarns << "session " << session_id << "does not exist " << llendl;
+ return NO_SESSION;
+ }
+
+ return session->mName;
+}
+
+const S32 LLIMModel::getNumUnread(const LLUUID& session_id) const
+{
+ LLIMSession* session = findIMSession(session_id);
+ if (!session)
+ {
+ llwarns << "session " << session_id << "does not exist " << llendl;
+ return -1;
+ }
+
+ return session->mNumUnread;
+}
+
+const LLUUID& LLIMModel::getOtherParticipantID(const LLUUID& session_id) const
+{
+ LLIMSession* session = findIMSession(session_id);
+ if (!session)
+ {
+ llwarns << "session " << session_id << "does not exist " << llendl;
+ return LLUUID::null;
+ }
+
+ return session->mOtherParticipantID;
+}
+
+EInstantMessage LLIMModel::getType(const LLUUID& session_id) const
+{
+ LLIMSession* session = findIMSession(session_id);
+ if (!session)
+ {
+ llwarns << "session " << session_id << "does not exist " << llendl;
+ return IM_COUNT;
+ }
+
+ return session->mType;
+}
+
+LLVoiceChannel* LLIMModel::getVoiceChannel( const LLUUID& session_id ) const
+{
+ LLIMSession* session = findIMSession(session_id);
+ if (!session)
+ {
+ llwarns << "session " << session_id << "does not exist " << llendl;
+ return NULL;
+ }
+
+ return session->mVoiceChannel;
+}
+
+LLIMSpeakerMgr* LLIMModel::getSpeakerManager( const LLUUID& session_id ) const
+{
+ LLIMSession* session = findIMSession(session_id);
+ if (!session)
+ {
+ llwarns << "session " << session_id << " does not exist " << llendl;
+ return NULL;
+ }
+
+ return session->mSpeakers;
+}
+
+const std::string& LLIMModel::getHistoryFileName(const LLUUID& session_id) const
+{
+ LLIMSession* session = findIMSession(session_id);
+ if (!session)
+ {
+ llwarns << "session " << session_id << " does not exist " << llendl;
+ return LLStringUtil::null;
+ }
+
+ return session->mHistoryFileName;
+}
+
+
+// TODO get rid of other participant ID
+void LLIMModel::sendTypingState(LLUUID session_id, LLUUID other_participant_id, BOOL typing)
+{
+ std::string name;
+ LLAgentUI::buildFullname(name);
+
+ pack_instant_message(
+ gMessageSystem,
+ gAgent.getID(),
+ FALSE,
+ gAgent.getSessionID(),
+ other_participant_id,
+ name,
+ std::string("typing"),
+ IM_ONLINE,
+ (typing ? IM_TYPING_START : IM_TYPING_STOP),
+ session_id);
+ gAgent.sendReliableMessage();
+}
+
+void LLIMModel::sendLeaveSession(const LLUUID& session_id, const LLUUID& other_participant_id)
+{
+ if(session_id.notNull())
+ {
+ std::string name;
+ LLAgentUI::buildFullname(name);
+ pack_instant_message(
+ gMessageSystem,
+ gAgent.getID(),
+ FALSE,
+ gAgent.getSessionID(),
+ other_participant_id,
+ name,
+ LLStringUtil::null,
+ IM_ONLINE,
+ IM_SESSION_LEAVE,
+ session_id);
+ gAgent.sendReliableMessage();
+ }
+}
+
+//*TODO this method is better be moved to the LLIMMgr
+void LLIMModel::sendMessage(const std::string& utf8_text,
+ const LLUUID& im_session_id,
+ const LLUUID& other_participant_id,
+ EInstantMessage dialog)
+{
+ std::string name;
+ bool sent = false;
+ LLAgentUI::buildFullname(name);
+
+ const LLRelationship* info = NULL;
+ info = LLAvatarTracker::instance().getBuddyInfo(other_participant_id);
+
+ U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE;
+
+ if((offline == IM_OFFLINE) && (LLVoiceClient::getInstance()->isOnlineSIP(other_participant_id)))
+ {
+ // User is online through the OOW connector, but not with a regular viewer. Try to send the message via SLVoice.
+ sent = gVoiceClient->sendTextMessage(other_participant_id, utf8_text);
+ }
+
+ if(!sent)
+ {
+ // Send message normally.
+
+ // default to IM_SESSION_SEND unless it's nothing special - in
+ // which case it's probably an IM to everyone.
+ U8 new_dialog = dialog;
+
+ if ( dialog != IM_NOTHING_SPECIAL )
+ {
+ new_dialog = IM_SESSION_SEND;
+ }
+ pack_instant_message(
+ gMessageSystem,
+ gAgent.getID(),
+ FALSE,
+ gAgent.getSessionID(),
+ other_participant_id,
+ name.c_str(),
+ utf8_text.c_str(),
+ offline,
+ (EInstantMessage)new_dialog,
+ im_session_id);
+ gAgent.sendReliableMessage();
+ }
+
+ // If there is a mute list and this is not a group chat...
+ if ( LLMuteList::getInstance() )
+ {
+ // ... the target should not be in our mute list for some message types.
+ // Auto-remove them if present.
+ switch( dialog )
+ {
+ case IM_NOTHING_SPECIAL:
+ case IM_GROUP_INVITATION:
+ case IM_INVENTORY_OFFERED:
+ case IM_SESSION_INVITE:
+ case IM_SESSION_P2P_INVITE:
+ case IM_SESSION_CONFERENCE_START:
+ case IM_SESSION_SEND: // This one is marginal - erring on the side of hearing.
+ case IM_LURE_USER:
+ case IM_GODLIKE_LURE_USER:
+ case IM_FRIENDSHIP_OFFERED:
+ LLMuteList::getInstance()->autoRemove(other_participant_id, LLMuteList::AR_IM);
+ break;
+ default: ; // do nothing
+ }
+ }
+
+ if((dialog == IM_NOTHING_SPECIAL) &&
+ (other_participant_id.notNull()))
+ {
+ // Do we have to replace the /me's here?
+ std::string from;
+ LLAgentUI::buildFullname(from);
+ LLIMModel::getInstance()->addMessage(im_session_id, from, gAgentID, utf8_text);
+
+ //local echo for the legacy communicate panel
+ std::string history_echo;
+ LLAgentUI::buildFullname(history_echo);
+
+ history_echo += ": " + utf8_text;
+
+ LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(im_session_id);
+ if (floater) floater->addHistoryLine(history_echo, LLUIColorTable::instance().getColor("IMChatColor"), true, gAgent.getID());
+
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(im_session_id);
+ if (speaker_mgr)
+ {
+ speaker_mgr->speakerChatted(gAgentID);
+ speaker_mgr->setSpeakerTyping(gAgentID, FALSE);
+ }
+ }
+
+ // Add the recipient to the recent people list.
+ LLRecentPeople::instance().add(other_participant_id);
+}
+
+void session_starter_helper(
+ const LLUUID& temp_session_id,
+ const LLUUID& other_participant_id,
+ EInstantMessage im_type)
+{
+ LLMessageSystem *msg = gMessageSystem;
+
+ msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+
+ msg->nextBlockFast(_PREHASH_MessageBlock);
+ msg->addBOOLFast(_PREHASH_FromGroup, FALSE);
+ msg->addUUIDFast(_PREHASH_ToAgentID, other_participant_id);
+ msg->addU8Fast(_PREHASH_Offline, IM_ONLINE);
+ msg->addU8Fast(_PREHASH_Dialog, im_type);
+ msg->addUUIDFast(_PREHASH_ID, temp_session_id);
+ msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary
+
+ std::string name;
+ LLAgentUI::buildFullname(name);
+
+ msg->addStringFast(_PREHASH_FromAgentName, name);
+ msg->addStringFast(_PREHASH_Message, LLStringUtil::null);
+ msg->addU32Fast(_PREHASH_ParentEstateID, 0);
+ msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null);
+ msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent());
+}
+
+void start_deprecated_conference_chat(
+ const LLUUID& temp_session_id,
+ const LLUUID& creator_id,
+ const LLUUID& other_participant_id,
+ const LLSD& agents_to_invite)
+{
+ U8* bucket;
+ U8* pos;
+ S32 count;
+ S32 bucket_size;
+
+ // *FIX: this could suffer from endian issues
+ count = agents_to_invite.size();
+ bucket_size = UUID_BYTES * count;
+ bucket = new U8[bucket_size];
+ pos = bucket;
+
+ for(S32 i = 0; i < count; ++i)
+ {
+ LLUUID agent_id = agents_to_invite[i].asUUID();
+
+ memcpy(pos, &agent_id, UUID_BYTES);
+ pos += UUID_BYTES;
+ }
+
+ session_starter_helper(
+ temp_session_id,
+ other_participant_id,
+ IM_SESSION_CONFERENCE_START);
+
+ gMessageSystem->addBinaryDataFast(
+ _PREHASH_BinaryBucket,
+ bucket,
+ bucket_size);
+
+ gAgent.sendReliableMessage();
+
+ delete[] bucket;
+}
+
+class LLStartConferenceChatResponder : public LLHTTPClient::Responder
+{
+public:
+ LLStartConferenceChatResponder(
+ const LLUUID& temp_session_id,
+ const LLUUID& creator_id,
+ const LLUUID& other_participant_id,
+ const LLSD& agents_to_invite)
+ {
+ mTempSessionID = temp_session_id;
+ mCreatorID = creator_id;
+ mOtherParticipantID = other_participant_id;
+ mAgents = agents_to_invite;
+ }
+
+ virtual void error(U32 statusNum, const std::string& reason)
+ {
+ //try an "old school" way.
+ if ( statusNum == 400 )
+ {
+ start_deprecated_conference_chat(
+ mTempSessionID,
+ mCreatorID,
+ mOtherParticipantID,
+ mAgents);
+ }
+
+ //else throw an error back to the client?
+ //in theory we should have just have these error strings
+ //etc. set up in this file as opposed to the IMMgr,
+ //but the error string were unneeded here previously
+ //and it is not worth the effort switching over all
+ //the possible different language translations
+ }
+
+private:
+ LLUUID mTempSessionID;
+ LLUUID mCreatorID;
+ LLUUID mOtherParticipantID;
+
+ LLSD mAgents;
+};
+
+// Returns true if any messages were sent, false otherwise.
+// Is sort of equivalent to "does the server need to do anything?"
+bool LLIMModel::sendStartSession(
+ const LLUUID& temp_session_id,
+ const LLUUID& other_participant_id,
+ const std::vector<LLUUID>& ids,
+ EInstantMessage dialog)
+{
+ if ( dialog == IM_SESSION_GROUP_START )
+ {
+ session_starter_helper(
+ temp_session_id,
+ other_participant_id,
+ dialog);
+ gMessageSystem->addBinaryDataFast(
+ _PREHASH_BinaryBucket,
+ EMPTY_BINARY_BUCKET,
+ EMPTY_BINARY_BUCKET_SIZE);
+ gAgent.sendReliableMessage();
+
+ return true;
+ }
+ else if ( dialog == IM_SESSION_CONFERENCE_START )
+ {
+ LLSD agents;
+ for (int i = 0; i < (S32) ids.size(); i++)
+ {
+ agents.append(ids[i]);
+ }
+
+ //we have a new way of starting conference calls now
+ LLViewerRegion* region = gAgent.getRegion();
+ if (region)
+ {
+ std::string url = region->getCapability(
+ "ChatSessionRequest");
+ LLSD data;
+ data["method"] = "start conference";
+ data["session-id"] = temp_session_id;
+
+ data["params"] = agents;
+
+ LLHTTPClient::post(
+ url,
+ data,
+ new LLStartConferenceChatResponder(
+ temp_session_id,
+ gAgent.getID(),
+ other_participant_id,
+ data["params"]));
+ }
+ else
+ {
+ start_deprecated_conference_chat(
+ temp_session_id,
+ gAgent.getID(),
+ other_participant_id,
+ agents);
+ }
+
+ //we also need to wait for reply from the server in case of ad-hoc chat (we'll get new session id)
+ return true;
+ }
+
+ return false;
+}
//
// Helper Functions
//
-// returns true if a should appear before b
-//static BOOL group_dictionary_sort( LLGroupData* a, LLGroupData* b )
-//{
-// return (LLStringUtil::compareDict( a->mName, b->mName ) < 0);
-//}
-
class LLViewerChatterBoxInvitationAcceptResponder :
public LLHTTPClient::Responder
{
@@ -114,10 +1168,8 @@ public:
{
if ( gIMMgr)
{
- LLFloaterIMPanel* floaterp =
- gIMMgr->findFloaterBySession(mSessionID);
-
- if (floaterp)
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+ if (speaker_mgr)
{
//we've accepted our invitation
//and received a list of agents that were
@@ -131,26 +1183,26 @@ public:
//but unfortunately, our base that we are receiving here
//may not be the most up to date. It was accurate at
//some point in time though.
- floaterp->setSpeakers(content);
+ speaker_mgr->setSpeakers(content);
//we now have our base of users in the session
//that was accurate at some point, but maybe not now
//so now we apply all of the udpates we've received
//in case of race conditions
- floaterp->updateSpeakersList(
- gIMMgr->getPendingAgentListUpdates(mSessionID));
+ speaker_mgr->updateSpeakers(gIMMgr->getPendingAgentListUpdates(mSessionID));
+ }
- if ( mInvitiationType == LLIMMgr::INVITATION_TYPE_VOICE )
- {
- floaterp->requestAutoConnect();
- LLFloaterIMPanel::onClickStartCall(floaterp);
- // always open IM window when connecting to voice
- LLFloaterChatterBox::showInstance(TRUE);
- }
- else if ( mInvitiationType == LLIMMgr::INVITATION_TYPE_IMMEDIATE )
- {
- LLFloaterChatterBox::showInstance(TRUE);
- }
+ if (LLIMMgr::INVITATION_TYPE_VOICE == mInvitiationType)
+ {
+ gIMMgr->startCall(mSessionID, LLVoiceChannel::INCOMING_CALL);
+ }
+
+ if ((mInvitiationType == LLIMMgr::INVITATION_TYPE_VOICE
+ || mInvitiationType == LLIMMgr::INVITATION_TYPE_IMMEDIATE)
+ && LLIMModel::getInstance()->findIMSession(mSessionID))
+ {
+ // TODO remove in 2010, for voice calls we do not open an IM window
+ //LLIMFloater::show(mSessionID);
}
gIMMgr->clearPendingAgentListUpdates(mSessionID);
@@ -165,20 +1217,11 @@ public:
{
gIMMgr->clearPendingAgentListUpdates(mSessionID);
gIMMgr->clearPendingInvitation(mSessionID);
-
- LLFloaterIMPanel* floaterp =
- gIMMgr->findFloaterBySession(mSessionID);
-
- if ( floaterp )
+ if ( 404 == statusNum )
{
- if ( 404 == statusNum )
- {
- std::string error_string;
- error_string = "does not exist";
-
- floaterp->showSessionStartError(
- error_string);
- }
+ std::string error_string;
+ error_string = "session_does_not_exist_error";
+ gIMMgr->showSessionStartError(error_string, mSessionID);
}
}
}
@@ -230,130 +1273,758 @@ LLUUID LLIMMgr::computeSessionID(
return session_id;
}
+inline LLFloater* getFloaterBySessionID(const LLUUID session_id)
+{
+ LLFloater* floater = NULL;
+ if ( gIMMgr )
+ {
+ floater = dynamic_cast < LLFloater* >
+ ( gIMMgr->findFloaterBySession(session_id) );
+ }
+ if ( !floater )
+ {
+ floater = dynamic_cast < LLFloater* >
+ ( LLIMFloater::findInstance(session_id) );
+ }
+ return floater;
+}
+
+void
+LLIMMgr::showSessionStartError(
+ const std::string& error_string,
+ const LLUUID session_id)
+{
+ const LLFloater* floater = getFloaterBySessionID (session_id);
+ if (!floater) return;
+
+ LLSD args;
+ args["REASON"] = LLTrans::getString(error_string);
+ args["RECIPIENT"] = floater->getTitle();
+
+ LLSD payload;
+ payload["session_id"] = session_id;
+
+ LLNotificationsUtil::add(
+ "ChatterBoxSessionStartError",
+ args,
+ payload,
+ LLIMMgr::onConfirmForceCloseError);
+}
+
+void
+LLIMMgr::showSessionEventError(
+ const std::string& event_string,
+ const std::string& error_string,
+ const LLUUID session_id)
+{
+ LLSD args;
+ LLStringUtil::format_map_t event_args;
+
+ event_args["RECIPIENT"] = LLIMModel::getInstance()->getName(session_id);
+
+ args["REASON"] =
+ LLTrans::getString(error_string);
+ args["EVENT"] =
+ LLTrans::getString(event_string, event_args);
+
+ LLNotificationsUtil::add(
+ "ChatterBoxSessionEventError",
+ args);
+}
+
+void
+LLIMMgr::showSessionForceClose(
+ const std::string& reason_string,
+ const LLUUID session_id)
+{
+ const LLFloater* floater = getFloaterBySessionID (session_id);
+ if (!floater) return;
+
+ LLSD args;
+
+ args["NAME"] = floater->getTitle();
+ args["REASON"] = LLTrans::getString(reason_string);
+
+ LLSD payload;
+ payload["session_id"] = session_id;
+
+ LLNotificationsUtil::add(
+ "ForceCloseChatterBoxSession",
+ args,
+ payload,
+ LLIMMgr::onConfirmForceCloseError);
+}
+
+//static
+bool
+LLIMMgr::onConfirmForceCloseError(
+ const LLSD& notification,
+ const LLSD& response)
+{
+ //only 1 option really
+ LLUUID session_id = notification["payload"]["session_id"];
+
+ LLFloater* floater = getFloaterBySessionID (session_id);
+ if ( floater )
+ {
+ floater->closeFloater(FALSE);
+ }
+ return false;
+}
+
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// LLFloaterIM
+// Class LLCallDialogManager
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-LLFloaterIM::LLFloaterIM()
+LLCallDialogManager::LLCallDialogManager()
+{
+}
+
+LLCallDialogManager::~LLCallDialogManager()
+{
+}
+
+void LLCallDialogManager::initClass()
{
- // autoresize=false is necessary to avoid resizing of the IM window whenever
- // a session is opened or closed (it would otherwise resize the window to match
- // the size of the im-sesssion when they were created. This happens in
- // LLMultiFloater::resizeToContents() when called through LLMultiFloater::addFloater())
- this->mAutoResize = FALSE;
- LLUICtrlFactory::getInstance()->buildFloater(this, "floater_im.xml");
+ LLVoiceChannel::setCurrentVoiceChannelChangedCallback(LLCallDialogManager::onVoiceChannelChanged);
}
-BOOL LLFloaterIM::postBuild()
+void LLCallDialogManager::onVoiceChannelChanged(const LLUUID &session_id)
{
- // IM session initiation warnings
- sOnlyUserMessage = getString("only_user_message");
- sOfflineMessage = getString("offline_message");
- sMutedMessage = getString("muted_message");
+ LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id);
+ if(!session)
+ {
+ sPreviousSessionlName = sCurrentSessionlName;
+ sCurrentSessionlName = ""; // Empty string results in "Nearby Voice Chat" after substitution
+ return;
+ }
+
+ if (sSession)
+ {
+ // store previous session type to process Avaline calls in dialogs
+ sPreviousSessionType = sSession->mSessionType;
+ }
+
+ sSession = session;
+ sSession->mVoiceChannel->setStateChangedCallback(boost::bind(LLCallDialogManager::onVoiceChannelStateChanged, _1, _2, _3));
+ if(sCurrentSessionlName != session->mName)
+ {
+ sPreviousSessionlName = sCurrentSessionlName;
+ sCurrentSessionlName = session->mName;
+ }
+
+ if (LLVoiceChannel::getCurrentVoiceChannel()->getState() == LLVoiceChannel::STATE_CALL_STARTED &&
+ LLVoiceChannel::getCurrentVoiceChannel()->getCallDirection() == LLVoiceChannel::OUTGOING_CALL)
+ {
+
+ //*TODO get rid of duplicated code
+ LLSD mCallDialogPayload;
+ mCallDialogPayload["session_id"] = sSession->mSessionID;
+ mCallDialogPayload["session_name"] = sSession->mName;
+ mCallDialogPayload["other_user_id"] = sSession->mOtherParticipantID;
+ mCallDialogPayload["old_channel_name"] = sPreviousSessionlName;
+ mCallDialogPayload["old_session_type"] = sPreviousSessionType;
+ mCallDialogPayload["state"] = LLVoiceChannel::STATE_CALL_STARTED;
+ mCallDialogPayload["disconnected_channel_name"] = sSession->mName;
+ mCallDialogPayload["session_type"] = sSession->mSessionType;
+
+ LLOutgoingCallDialog* ocd = LLFloaterReg::getTypedInstance<LLOutgoingCallDialog>("outgoing_call", LLOutgoingCallDialog::OCD_KEY);
+ if(ocd)
+ {
+ ocd->show(mCallDialogPayload);
+ }
+ }
- sInviteMessage = getString("invite_message");
+}
+
+void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction)
+{
+ LLSD mCallDialogPayload;
+ LLOutgoingCallDialog* ocd = NULL;
- if ( sErrorStringsMap.find("generic") == sErrorStringsMap.end() )
+ if(sOldState == new_state)
{
- sErrorStringsMap["generic"] =
- getString("generic_request_error");
+ return;
}
- if ( sErrorStringsMap.find("unverified") ==
- sErrorStringsMap.end() )
+ sOldState = new_state;
+
+ mCallDialogPayload["session_id"] = sSession->mSessionID;
+ mCallDialogPayload["session_name"] = sSession->mName;
+ mCallDialogPayload["other_user_id"] = sSession->mOtherParticipantID;
+ mCallDialogPayload["old_channel_name"] = sPreviousSessionlName;
+ mCallDialogPayload["old_session_type"] = sPreviousSessionType;
+ mCallDialogPayload["state"] = new_state;
+ mCallDialogPayload["disconnected_channel_name"] = sSession->mName;
+ mCallDialogPayload["session_type"] = sSession->mSessionType;
+
+ switch(new_state)
+ {
+ case LLVoiceChannel::STATE_CALL_STARTED :
+ // do not show "Calling to..." if it is incoming call
+ if(direction == LLVoiceChannel::INCOMING_CALL)
+ {
+ return;
+ }
+ break;
+
+ case LLVoiceChannel::STATE_HUNG_UP:
+ // this state is coming before session is changed, so, put it into payload map
+ mCallDialogPayload["old_session_type"] = sSession->mSessionType;
+ break;
+
+ case LLVoiceChannel::STATE_CONNECTED :
+ ocd = LLFloaterReg::findTypedInstance<LLOutgoingCallDialog>("outgoing_call", LLOutgoingCallDialog::OCD_KEY);
+ if (ocd)
+ {
+ ocd->closeFloater();
+ }
+ return;
+
+ default:
+ break;
+ }
+
+ ocd = LLFloaterReg::getTypedInstance<LLOutgoingCallDialog>("outgoing_call", LLOutgoingCallDialog::OCD_KEY);
+ if(ocd)
+ {
+ ocd->show(mCallDialogPayload);
+ }
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLCallDialog
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LLCallDialog::LLCallDialog(const LLSD& payload) :
+LLDockableFloater(NULL, false, payload),
+mPayload(payload)
+{
+}
+
+void LLCallDialog::getAllowedRect(LLRect& rect)
+{
+ rect = gViewerWindow->getWorldViewRectScaled();
+}
+
+BOOL LLCallDialog::postBuild()
+{
+ if (!LLDockableFloater::postBuild())
+ return FALSE;
+
+ // dock the dialog to the Speak Button, where other sys messages appear
+ LLView *anchor_panel = LLBottomTray::getInstance()->getChild<LLView>("speak_panel");
+
+ setDockControl(new LLDockControl(
+ anchor_panel, this,
+ getDockTongue(), LLDockControl::TOP,
+ boost::bind(&LLCallDialog::getAllowedRect, this, _1)));
+
+ return TRUE;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLOutgoingCallDialog
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LLOutgoingCallDialog::LLOutgoingCallDialog(const LLSD& payload) :
+LLCallDialog(payload)
+{
+ LLOutgoingCallDialog* instance = LLFloaterReg::findTypedInstance<LLOutgoingCallDialog>("outgoing_call", LLOutgoingCallDialog::OCD_KEY);
+ if(instance && instance->getVisible())
{
- sErrorStringsMap["unverified"] =
- getString("insufficient_perms_error");
+ instance->onCancel(instance);
+ }
+}
+
+void LLCallDialog::draw()
+{
+ if (lifetimeHasExpired())
+ {
+ onLifetimeExpired();
}
- if ( sErrorStringsMap.end() ==
- sErrorStringsMap.find("no_ability") )
+ if (getDockControl() != NULL)
{
- sErrorStringsMap["no_ability"] =
- getString("no_ability_error");
+ LLDockableFloater::draw();
}
+}
+
+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);
- if ( sErrorStringsMap.end() ==
- sErrorStringsMap.find("muted") )
+ LLAvatarIconCtrl* avatar_icon = getChild<LLAvatarIconCtrl>("avatar_icon");
+ LLGroupIconCtrl* group_icon = getChild<LLGroupIconCtrl>("group_icon");
+
+ avatar_icon->setVisible(!is_group);
+ group_icon->setVisible(is_group);
+
+ if (is_group)
+ {
+ group_icon->setValue(session_id);
+ }
+ else if (participant_is_avatar)
{
- sErrorStringsMap["muted"] =
- getString("muted_error");
+ avatar_icon->setValue(participant_id);
}
+ else
+ {
+ avatar_icon->setValue("Avaline_Icon");
+ avatar_icon->setToolTip(std::string(""));
+ }
+}
- if ( sErrorStringsMap.end() ==
- sErrorStringsMap.find("not_a_moderator") )
+bool LLOutgoingCallDialog::lifetimeHasExpired()
+{
+ if (mLifetimeTimer.getStarted())
{
- sErrorStringsMap["not_a_moderator"] =
- getString("not_a_mod_error");
+ F32 elapsed_time = mLifetimeTimer.getElapsedTimeF32();
+ if (elapsed_time > mLifetime)
+ {
+ return true;
+ }
}
+ return false;
+}
+
+void LLOutgoingCallDialog::onLifetimeExpired()
+{
+ mLifetimeTimer.stop();
+ closeFloater();
+}
- if ( sErrorStringsMap.end() ==
- sErrorStringsMap.find("does not exist") )
+void LLOutgoingCallDialog::show(const LLSD& key)
+{
+ mPayload = key;
+
+ // hide all text at first
+ hideAllText();
+
+ // init notification's lifetime
+ std::istringstream ss( getString("lifetime") );
+ if (!(ss >> mLifetime))
{
- sErrorStringsMap["does not exist"] =
- getString("session_does_not_exist_error");
+ mLifetime = DEFAULT_LIFETIME;
}
- if ( sEventStringsMap.end() == sEventStringsMap.find("add") )
+ // customize text strings
+ // tell the user which voice channel they are leaving
+ if (!mPayload["old_channel_name"].asString().empty())
{
- sEventStringsMap["add"] =
- getString("add_session_event");
+ bool was_avaline_call = LLIMModel::LLIMSession::AVALINE_SESSION == mPayload["old_session_type"].asInteger();
+
+ std::string old_caller_name = mPayload["old_channel_name"].asString();
+ if (was_avaline_call)
+ {
+ old_caller_name = LLTextUtil::formatPhoneNumber(old_caller_name);
+ }
+
+ childSetTextArg("leaving", "[CURRENT_CHAT]", old_caller_name);
+ }
+ else
+ {
+ childSetTextArg("leaving", "[CURRENT_CHAT]", getString("localchat"));
}
- if ( sEventStringsMap.end() == sEventStringsMap.find("message") )
+ if (!mPayload["disconnected_channel_name"].asString().empty())
{
- sEventStringsMap["message"] =
- getString("message_session_event");
+ std::string channel_name = mPayload["disconnected_channel_name"].asString();
+ if (LLIMModel::LLIMSession::AVALINE_SESSION == mPayload["session_type"].asInteger())
+ {
+ channel_name = LLTextUtil::formatPhoneNumber(channel_name);
+ }
+ childSetTextArg("nearby", "[VOICE_CHANNEL_NAME]", channel_name);
+ childSetTextArg("nearby_P2P", "[VOICE_CHANNEL_NAME]", mPayload["disconnected_channel_name"].asString());
}
+ std::string callee_name = mPayload["session_name"].asString();
+
+ LLUUID session_id = mPayload["session_id"].asUUID();
+ bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(session_id);
- if ( sForceCloseSessionMap.end() ==
- sForceCloseSessionMap.find("removed") )
+ if (callee_name == "anonymous")
{
- sForceCloseSessionMap["removed"] =
- getString("removed_from_group");
+ callee_name = getString("anonymous");
}
+ else if (!is_avatar)
+ {
+ callee_name = LLTextUtil::formatPhoneNumber(callee_name);
+ }
+
+ setTitle(callee_name);
+
+ LLSD callee_id = mPayload["other_user_id"];
+ childSetTextArg("calling", "[CALLEE_NAME]", callee_name);
+ childSetTextArg("connecting", "[CALLEE_NAME]", callee_name);
- if ( sForceCloseSessionMap.end() ==
- sForceCloseSessionMap.find("no ability") )
+ // for outgoing group calls callee_id == group id == session id
+ setIcon(callee_id, callee_id);
+
+ // stop timer by default
+ mLifetimeTimer.stop();
+
+ // show only necessary strings and controls
+ switch(mPayload["state"].asInteger())
{
- sForceCloseSessionMap["no ability"] =
- getString("close_on_no_ability");
+ case LLVoiceChannel::STATE_CALL_STARTED :
+ getChild<LLTextBox>("calling")->setVisible(true);
+ getChild<LLTextBox>("leaving")->setVisible(true);
+ break;
+ case LLVoiceChannel::STATE_RINGING :
+ getChild<LLTextBox>("leaving")->setVisible(true);
+ getChild<LLTextBox>("connecting")->setVisible(true);
+ break;
+ case LLVoiceChannel::STATE_ERROR :
+ getChild<LLTextBox>("noanswer")->setVisible(true);
+ getChild<LLButton>("Cancel")->setVisible(false);
+ setCanClose(true);
+ mLifetimeTimer.start();
+ break;
+ case LLVoiceChannel::STATE_HUNG_UP :
+ if (mPayload["session_type"].asInteger() == LLIMModel::LLIMSession::P2P_SESSION)
+ {
+ getChild<LLTextBox>("nearby_P2P")->setVisible(true);
+ }
+ else
+ {
+ getChild<LLTextBox>("nearby")->setVisible(true);
+ }
+ getChild<LLButton>("Cancel")->setVisible(false);
+ setCanClose(true);
+ mLifetimeTimer.start();
}
- return TRUE;
+ openFloater(LLOutgoingCallDialog::OCD_KEY);
+}
+
+void LLOutgoingCallDialog::hideAllText()
+{
+ getChild<LLTextBox>("calling")->setVisible(false);
+ getChild<LLTextBox>("leaving")->setVisible(false);
+ getChild<LLTextBox>("connecting")->setVisible(false);
+ getChild<LLTextBox>("nearby_P2P")->setVisible(false);
+ getChild<LLTextBox>("nearby")->setVisible(false);
+ getChild<LLTextBox>("noanswer")->setVisible(false);
+}
+
+//static
+void LLOutgoingCallDialog::onCancel(void* user_data)
+{
+ LLOutgoingCallDialog* self = (LLOutgoingCallDialog*)user_data;
+
+ if (!gIMMgr)
+ return;
+
+ LLUUID session_id = self->mPayload["session_id"].asUUID();
+ gIMMgr->endCall(session_id);
+
+ self->closeFloater();
}
+
+BOOL LLOutgoingCallDialog::postBuild()
+{
+ BOOL success = LLCallDialog::postBuild();
+
+ childSetAction("Cancel", onCancel, this);
+
+ return success;
+}
+
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLIMViewFriendObserver
-//
-// Bridge to suport knowing when the inventory has changed.
+// Class LLIncomingCallDialog
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLIMViewFriendObserver : public LLFriendObserver
+LLIncomingCallDialog::LLIncomingCallDialog(const LLSD& payload) :
+LLCallDialog(payload)
{
-public:
- LLIMViewFriendObserver(LLIMMgr* tv) : mTV(tv) {}
- virtual ~LLIMViewFriendObserver() {}
- virtual void changed(U32 mask)
+}
+
+bool LLIncomingCallDialog::lifetimeHasExpired()
+{
+ if (mLifetimeTimer.getStarted())
{
- if(mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE))
+ F32 elapsed_time = mLifetimeTimer.getElapsedTimeF32();
+ if (elapsed_time > mLifetime)
{
- mTV->refresh();
+ return true;
}
}
-protected:
- LLIMMgr* mTV;
-};
+ return false;
+}
+
+void LLIncomingCallDialog::onLifetimeExpired()
+{
+ // check whether a call is valid or not
+ if (LLVoiceClient::getInstance()->findSession(mPayload["caller_id"].asUUID()))
+ {
+ // restart notification's timer if call is still valid
+ mLifetimeTimer.start();
+ }
+ else
+ {
+ // close invitation if call is already not valid
+ mLifetimeTimer.stop();
+ closeFloater();
+ }
+}
+
+BOOL LLIncomingCallDialog::postBuild()
+{
+ LLCallDialog::postBuild();
+ LLUUID session_id = mPayload["session_id"].asUUID();
+ LLSD caller_id = mPayload["caller_id"];
+ std::string caller_name = mPayload["caller_name"].asString();
+
+ // init notification's lifetime
+ std::istringstream ss( getString("lifetime") );
+ if (!(ss >> mLifetime))
+ {
+ mLifetime = DEFAULT_LIFETIME;
+ }
+
+ std::string call_type;
+ if (gAgent.isInGroup(session_id))
+ {
+ LLStringUtil::format_map_t args;
+ LLGroupData data;
+ if (gAgent.getGroupData(session_id, data))
+ {
+ args["[GROUP]"] = data.mName;
+ call_type = getString(mPayload["notify_box_type"], args);
+ }
+ }
+ else
+ {
+ call_type = getString(mPayload["notify_box_type"]);
+ }
+
+
+ // check to see if this is an Avaline call
+ bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(session_id);
+ childSetVisible("Start IM", is_avatar); // no IM for avaline
+
+ if (caller_name == "anonymous")
+ {
+ caller_name = getString("anonymous");
+ }
+ else if (!is_avatar)
+ {
+ caller_name = LLTextUtil::formatPhoneNumber(caller_name);
+ }
+
+ setTitle(caller_name + " " + call_type);
+
+ LLUICtrl* caller_name_widget = getChild<LLUICtrl>("caller name");
+ caller_name_widget->setValue(caller_name + " " + call_type);
+ setIcon(session_id, caller_id);
+
+ childSetAction("Accept", onAccept, this);
+ childSetAction("Reject", onReject, this);
+ childSetAction("Start IM", onStartIM, this);
+ childSetFocus("Accept");
+
+ std::string notify_box_type = mPayload["notify_box_type"].asString();
+ if(notify_box_type != "VoiceInviteGroup" && notify_box_type != "VoiceInviteAdHoc")
+ {
+ // starting notification's timer for P2P and AVALINE invitations
+ mLifetimeTimer.start();
+ }
+ else
+ {
+ mLifetimeTimer.stop();
+ }
+
+ return TRUE;
+}
+
+
+void LLIncomingCallDialog::onOpen(const LLSD& key)
+{
+ LLCallDialog::onOpen(key);
+
+ // tell the user which voice channel they would be leaving
+ LLVoiceChannel *voice = LLVoiceChannel::getCurrentVoiceChannel();
+ if (voice && !voice->getSessionName().empty())
+ {
+ childSetTextArg("question", "[CURRENT_CHAT]", voice->getSessionName());
+ }
+ else
+ {
+ childSetTextArg("question", "[CURRENT_CHAT]", getString("localchat"));
+ }
+}
+
+//static
+void LLIncomingCallDialog::onAccept(void* user_data)
+{
+ LLIncomingCallDialog* self = (LLIncomingCallDialog*)user_data;
+ self->processCallResponse(0);
+ self->closeFloater();
+}
+
+//static
+void LLIncomingCallDialog::onReject(void* user_data)
+{
+ LLIncomingCallDialog* self = (LLIncomingCallDialog*)user_data;
+ self->processCallResponse(1);
+ self->closeFloater();
+}
+
+//static
+void LLIncomingCallDialog::onStartIM(void* user_data)
+{
+ LLIncomingCallDialog* self = (LLIncomingCallDialog*)user_data;
+ self->processCallResponse(2);
+ self->closeFloater();
+}
+
+void LLIncomingCallDialog::processCallResponse(S32 response)
+{
+ if (!gIMMgr || gDisconnected)
+ return;
+
+ LLUUID session_id = mPayload["session_id"].asUUID();
+ LLUUID caller_id = mPayload["caller_id"].asUUID();
+ std::string session_name = mPayload["session_name"].asString();
+ EInstantMessage type = (EInstantMessage)mPayload["type"].asInteger();
+ LLIMMgr::EInvitationType inv_type = (LLIMMgr::EInvitationType)mPayload["inv_type"].asInteger();
+ bool voice = true;
+ switch(response)
+ {
+ case 2: // start IM: just don't start the voice chat
+ {
+ voice = false;
+ /* FALLTHROUGH */
+ }
+ case 0: // accept
+ {
+ if (type == IM_SESSION_P2P_INVITE)
+ {
+ // create a normal IM session
+ session_id = gIMMgr->addP2PSession(
+ session_name,
+ caller_id,
+ mPayload["session_handle"].asString(),
+ mPayload["session_uri"].asString());
+
+ if (voice)
+ {
+ gIMMgr->startCall(session_id, LLVoiceChannel::INCOMING_CALL);
+ }
+
+ gIMMgr->clearPendingAgentListUpdates(session_id);
+ gIMMgr->clearPendingInvitation(session_id);
+ }
+ else
+ {
+ //session name should not be empty, but it can contain spaces so we don't trim
+ std::string correct_session_name = session_name;
+ if (session_name.empty())
+ {
+ llwarns << "Received an empty session name from a server" << llendl;
+
+ switch(type){
+ case IM_SESSION_CONFERENCE_START:
+ case IM_SESSION_GROUP_START:
+ case IM_SESSION_INVITE:
+ if (gAgent.isInGroup(session_id))
+ {
+ LLGroupData data;
+ if (!gAgent.getGroupData(session_id, data)) break;
+ correct_session_name = data.mName;
+ }
+ else
+ {
+ if (gCacheName->getFullName(caller_id, correct_session_name))
+ {
+ correct_session_name.append(ADHOC_NAME_SUFFIX);
+ }
+ }
+ llinfos << "Corrected session name is " << correct_session_name << llendl;
+ break;
+ default:
+ llwarning("Received an empty session name from a server and failed to generate a new proper session name", 0);
+ break;
+ }
+ }
+
+ LLUUID new_session_id = gIMMgr->addSession(correct_session_name, type, session_id, true);
+
+ std::string url = gAgent.getRegion()->getCapability(
+ "ChatSessionRequest");
+
+ if (voice)
+ {
+ LLSD data;
+ data["method"] = "accept invitation";
+ data["session-id"] = session_id;
+ LLHTTPClient::post(
+ url,
+ data,
+ new LLViewerChatterBoxInvitationAcceptResponder(
+ session_id,
+ inv_type));
+
+ // send notification message to the corresponding chat
+ if (mPayload["notify_box_type"].asString() == "VoiceInviteGroup" || mPayload["notify_box_type"].asString() == "VoiceInviteAdHoc")
+ {
+ std::string started_call = LLTrans::getString("started_call");
+ std::string message = mPayload["caller_name"].asString() + " " + started_call;
+ LLIMModel::getInstance()->addMessageSilently(session_id, SYSTEM_FROM, LLUUID::null, message);
+ }
+ }
+ }
+ if (voice)
+ {
+ break;
+ }
+ }
+ case 1: // decline
+ {
+ if (type == IM_SESSION_P2P_INVITE)
+ {
+ if(gVoiceClient)
+ {
+ std::string s = mPayload["session_handle"].asString();
+ gVoiceClient->declineInvite(s);
+ }
+ }
+ else
+ {
+ std::string url = gAgent.getRegion()->getCapability(
+ "ChatSessionRequest");
+
+ LLSD data;
+ data["method"] = "decline invitation";
+ data["session-id"] = session_id;
+ LLHTTPClient::post(
+ url,
+ data,
+ NULL);
+ }
+ }
+
+ gIMMgr->clearPendingAgentListUpdates(session_id);
+ gIMMgr->clearPendingInvitation(session_id);
+ }
+}
bool inviteUserResponse(const LLSD& notification, const LLSD& response)
{
+ if (!gIMMgr)
+ return false;
+
const LLSD& payload = notification["payload"];
LLUUID session_id = payload["session_id"].asUUID();
EInstantMessage type = (EInstantMessage)payload["type"].asInteger();
LLIMMgr::EInvitationType inv_type = (LLIMMgr::EInvitationType)payload["inv_type"].asInteger();
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
switch(option)
{
case 0: // accept
@@ -367,26 +2038,17 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response)
payload["session_handle"].asString(),
payload["session_uri"].asString());
- LLFloaterIMPanel* im_floater =
- gIMMgr->findFloaterBySession(
- session_id);
- if (im_floater)
- {
- im_floater->requestAutoConnect();
- LLFloaterIMPanel::onClickStartCall(im_floater);
- // always open IM window when connecting to voice
- LLFloaterChatterBox::showInstance(session_id);
- }
+ gIMMgr->startCall(session_id);
gIMMgr->clearPendingAgentListUpdates(session_id);
gIMMgr->clearPendingInvitation(session_id);
}
else
{
- gIMMgr->addSession(
+ LLUUID new_session_id = gIMMgr->addSession(
payload["session_name"].asString(),
type,
- session_id);
+ session_id, true);
std::string url = gAgent.getRegion()->getCapability(
"ChatSessionRequest");
@@ -448,98 +2110,16 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response)
}
//
-// Public Static Member Functions
-//
-
-// This is a helper function to determine what kind of im session
-// should be used for the given agent.
-// static
-EInstantMessage LLIMMgr::defaultIMTypeForAgent(const LLUUID& agent_id)
-{
- EInstantMessage type = IM_NOTHING_SPECIAL;
- if(is_agent_friend(agent_id))
- {
- if(LLAvatarTracker::instance().isBuddyOnline(agent_id))
- {
- type = IM_SESSION_CONFERENCE_START;
- }
- }
- return type;
-}
-
-// static
-//void LLIMMgr::onPinButton(void*)
-//{
-// BOOL state = gSavedSettings.getBOOL( "PinTalkViewOpen" );
-// gSavedSettings.setBOOL( "PinTalkViewOpen", !state );
-//}
-
-// static
-void LLIMMgr::toggle(void*)
-{
- static BOOL return_to_mouselook = FALSE;
-
- // Hide the button and show the floater or vice versa.
- llassert( gIMMgr );
- BOOL old_state = gIMMgr->getFloaterOpen();
-
- // If we're in mouselook and we triggered the Talk View, we want to talk.
- if( gAgent.cameraMouselook() && old_state )
- {
- return_to_mouselook = TRUE;
- gAgent.changeCameraToDefault();
- return;
- }
-
- BOOL new_state = !old_state;
-
- if (new_state)
- {
- // ...making visible
- if ( gAgent.cameraMouselook() )
- {
- return_to_mouselook = TRUE;
- gAgent.changeCameraToDefault();
- }
- }
- else
- {
- // ...hiding
- if ( gAgent.cameraThirdPerson() && return_to_mouselook )
- {
- gAgent.changeCameraToMouselook();
- }
- return_to_mouselook = FALSE;
- }
-
- gIMMgr->setFloaterOpen( new_state );
-}
-
-//
// Member Functions
//
LLIMMgr::LLIMMgr() :
- mFriendObserver(NULL),
mIMReceived(FALSE)
{
- mFriendObserver = new LLIMViewFriendObserver(this);
- LLAvatarTracker::instance().addObserver(mFriendObserver);
-
- // *HACK: use floater to initialize string constants from xml file
- // then delete it right away
- LLFloaterIM* dummy_floater = new LLFloaterIM();
- delete dummy_floater;
-
mPendingInvitations = LLSD::emptyMap();
mPendingAgentListUpdates = LLSD::emptyMap();
-}
-LLIMMgr::~LLIMMgr()
-{
- LLAvatarTracker::instance().removeObserver(mFriendObserver);
- delete mFriendObserver;
- // Children all cleaned up by default view destructor.
+ LLIMModel::getInstance()->addNewMsgCallback(boost::bind(&LLIMFloater::sRemoveTypingIndicator, _1));
}
// Add a message to a session.
@@ -565,13 +2145,6 @@ void LLIMMgr::addMessage(
return;
}
- //not sure why...but if it is from ourselves we set the target_id
- //to be NULL
- if( other_participant_id == gAgent.getID() )
- {
- other_participant_id = LLUUID::null;
- }
-
LLFloaterIMPanel* floater;
LLUUID new_session_id = session_id;
if (new_session_id.isNull())
@@ -579,6 +2152,20 @@ void LLIMMgr::addMessage(
//no session ID...compute new one
new_session_id = computeSessionID(dialog, other_participant_id);
}
+
+ //*NOTE session_name is empty in case of incoming P2P sessions
+ std::string fixed_session_name = from;
+ if(!session_name.empty() && session_name.size()>1)
+ {
+ fixed_session_name = session_name;
+ }
+
+ bool new_session = !hasSession(new_session_id);
+ if (new_session)
+ {
+ LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id);
+ }
+
floater = findFloaterBySession(new_session_id);
if (!floater)
{
@@ -593,20 +2180,16 @@ void LLIMMgr::addMessage(
// create IM window as necessary
if(!floater)
{
- std::string name = from;
- if(!session_name.empty() && session_name.size()>1)
- {
- name = session_name;
- }
-
-
floater = createFloater(
new_session_id,
other_participant_id,
- name,
+ fixed_session_name,
dialog,
FALSE);
+ }
+ if (new_session)
+ {
// When we get a new IM, and if you are a god, display a bit
// of information about the source. This is to help liaisons
// when answering questions.
@@ -614,10 +2197,10 @@ void LLIMMgr::addMessage(
{
// *TODO:translate (low priority, god ability)
std::ostringstream bonus_info;
- bonus_info << "*** parent estate: "
+ bonus_info << LLTrans::getString("***")+ " "+ LLTrans::getString("IMParentEstate") + ":" + " "
<< parent_estate_id
- << ((parent_estate_id == 1) ? ", mainland" : "")
- << ((parent_estate_id == 5) ? ", teen" : "");
+ << ((parent_estate_id == 1) ? "," + LLTrans::getString("IMMainland") : "")
+ << ((parent_estate_id == 5) ? "," + LLTrans::getString ("IMTeen") : "");
// once we have web-services (or something) which returns
// information about a region id, we can print this out
@@ -625,7 +2208,8 @@ void LLIMMgr::addMessage(
//<< "*** region_id: " << region_id << std::endl
//<< "*** position: " << position << std::endl;
- floater->addHistoryLine(bonus_info.str(), gSavedSettings.getColor4("SystemChatColor"));
+ floater->addHistoryLine(bonus_info.str(), LLUIColorTable::instance().getColor("SystemChatColor"));
+ LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, bonus_info.str());
}
make_ui_sound("UISndNewIncomingIMSession");
@@ -634,8 +2218,8 @@ void LLIMMgr::addMessage(
// now add message to floater
bool is_from_system = target_id.isNull() || (from == SYSTEM_FROM);
const LLColor4& color = ( is_from_system ?
- gSavedSettings.getColor4("SystemChatColor") :
- gSavedSettings.getColor("IMChatColor"));
+ LLUIColorTable::instance().getColor("SystemChatColor") :
+ LLUIColorTable::instance().getColor("IMChatColor"));
if ( !link_name )
{
floater->addHistoryLine(msg,color); // No name to prepend, so just add the message normally
@@ -645,10 +2229,12 @@ void LLIMMgr::addMessage(
floater->addHistoryLine(msg, color, true, other_participant_id, from); // Insert linked name to front of message
}
- LLFloaterChatterBox* chat_floater = LLFloaterChatterBox::getInstance(LLSD());
+ LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg);
- if( !chat_floater->getVisible() && !floater->getVisible())
+ if( !LLFloaterReg::instanceVisible("communicate") && !floater->getVisible())
{
+ LLFloaterChatterBox* chat_floater = LLFloaterChatterBox::getInstance();
+
//if the IM window is not open and the floater is not visible (i.e. not torn off)
LLFloater* previouslyActiveFloater = chat_floater->getActiveFloater();
@@ -675,23 +2261,24 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess
// null session id means near me (chat history)
if (session_id.isNull())
{
- LLFloaterChat* floaterp = LLFloaterChat::getInstance();
-
- message = floaterp->getString(message_name);
+ message = LLTrans::getString(message_name);
message.setArgs(args);
LLChat chat(message);
chat.mSourceType = CHAT_SOURCE_SYSTEM;
- LLFloaterChat::getInstance()->addChatHistory(chat);
+
+ LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
+ if(nearby_chat)
+ {
+ nearby_chat->addMessage(chat);
+ }
}
else // going to IM session
{
- LLFloaterIMPanel* floaterp = findFloaterBySession(session_id);
- if (floaterp)
+ if (hasSession(session_id))
{
- message = floaterp->getString(message_name);
+ message = LLTrans::getString(message_name + "-im");
message.setArgs(args);
-
gIMMgr->addMessage(session_id, LLUUID::null, SYSTEM_FROM, message.getString());
}
}
@@ -699,12 +2286,38 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess
void LLIMMgr::notifyNewIM()
{
- if(!gIMMgr->getFloaterOpen())
+ if(!LLFloaterReg::instanceVisible("communicate"))
{
mIMReceived = TRUE;
}
}
+S32 LLIMMgr::getNumberOfUnreadIM()
+{
+ std::map<LLUUID, LLIMModel::LLIMSession*>::iterator it;
+
+ S32 num = 0;
+ for(it = LLIMModel::getInstance()->mId2SessionMap.begin(); it != LLIMModel::getInstance()->mId2SessionMap.end(); ++it)
+ {
+ num += (*it).second->mNumUnread;
+ }
+
+ return num;
+}
+
+S32 LLIMMgr::getNumberOfUnreadParticipantMessages()
+{
+ std::map<LLUUID, LLIMModel::LLIMSession*>::iterator it;
+
+ S32 num = 0;
+ for(it = LLIMModel::getInstance()->mId2SessionMap.begin(); it != LLIMModel::getInstance()->mId2SessionMap.end(); ++it)
+ {
+ num += (*it).second->mParticipantUnreadMessageCount;
+ }
+
+ return num;
+}
+
void LLIMMgr::clearNewIMNotification()
{
mIMReceived = FALSE;
@@ -715,13 +2328,19 @@ BOOL LLIMMgr::getIMReceived() const
return mIMReceived;
}
-// This method returns TRUE if the local viewer has a session
-// currently open keyed to the uuid.
-BOOL LLIMMgr::isIMSessionOpen(const LLUUID& uuid)
+void LLIMMgr::autoStartCallOnStartup(const LLUUID& session_id)
{
- LLFloaterIMPanel* floater = findFloaterBySession(uuid);
- if(floater) return TRUE;
- return FALSE;
+ LLIMModel::LLIMSession *session = LLIMModel::getInstance()->findIMSession(session_id);
+ if (!session) return;
+
+ if (session->mSessionInitialized)
+ {
+ startCall(session_id);
+ }
+ else
+ {
+ session->mStartCallOnInitialize = true;
+ }
}
LLUUID LLIMMgr::addP2PSession(const std::string& name,
@@ -729,15 +2348,17 @@ LLUUID LLIMMgr::addP2PSession(const std::string& name,
const std::string& voice_session_handle,
const std::string& caller_uri)
{
- LLUUID session_id = addSession(name, IM_NOTHING_SPECIAL, other_participant_id);
+ LLUUID session_id = addSession(name, IM_NOTHING_SPECIAL, other_participant_id, true);
- LLFloaterIMPanel* floater = findFloaterBySession(session_id);
- if(floater)
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id);
+ if (speaker_mgr)
{
- LLVoiceChannelP2P* voice_channelp = (LLVoiceChannelP2P*)floater->getVoiceChannel();
- voice_channelp->setSessionHandle(voice_session_handle, caller_uri);
+ LLVoiceChannelP2P* voice_channel = dynamic_cast<LLVoiceChannelP2P*>(speaker_mgr->getVoiceChannel());
+ if (voice_channel)
+ {
+ voice_channel->setSessionHandle(voice_session_handle, caller_uri);
+ }
}
-
return session_id;
}
@@ -748,41 +2369,11 @@ LLUUID LLIMMgr::addP2PSession(const std::string& name,
LLUUID LLIMMgr::addSession(
const std::string& name,
EInstantMessage dialog,
- const LLUUID& other_participant_id)
+ const LLUUID& other_participant_id, bool voice)
{
- LLUUID session_id = computeSessionID(dialog, other_participant_id);
-
- LLFloaterIMPanel* floater = findFloaterBySession(session_id);
- if(!floater)
- {
- LLDynamicArray<LLUUID> ids;
- ids.put(other_participant_id);
-
- floater = createFloater(
- session_id,
- other_participant_id,
- name,
- ids,
- dialog,
- TRUE);
-
- noteOfflineUsers(floater, ids);
- LLFloaterChatterBox::showInstance(session_id);
-
- // Only warn for regular IMs - not group IMs
- if( dialog == IM_NOTHING_SPECIAL )
- {
- noteMutedUsers(floater, ids);
- }
- LLFloaterChatterBox::getInstance(LLSD())->showFloater(floater);
- }
- else
- {
- floater->open();
- }
- //mTabContainer->selectTabPanel(panel);
- floater->setInputFocus(TRUE);
- return floater->getSessionID();
+ LLDynamicArray<LLUUID> ids;
+ ids.put(other_participant_id);
+ return addSession(name, dialog, other_participant_id, ids, voice);
}
// Adds a session using the given session_id. If the session already exists
@@ -791,17 +2382,40 @@ LLUUID LLIMMgr::addSession(
const std::string& name,
EInstantMessage dialog,
const LLUUID& other_participant_id,
- const LLDynamicArray<LLUUID>& ids)
+ const LLDynamicArray<LLUUID>& ids, bool voice)
{
if (0 == ids.getLength())
{
return LLUUID::null;
}
- LLUUID session_id = computeSessionID(
- dialog,
- other_participant_id);
+ if (name.empty())
+ {
+ llwarning("Session name cannot be null!", 0);
+ return LLUUID::null;
+ }
+
+ LLUUID session_id = computeSessionID(dialog,other_participant_id);
+
+ bool new_session = !LLIMModel::getInstance()->findIMSession(session_id);
+ //works only for outgoing ad-hoc sessions
+ if (new_session && IM_SESSION_CONFERENCE_START == dialog && ids.size())
+ {
+ LLIMModel::LLIMSession* ad_hoc_found = LLIMModel::getInstance()->findAdHocIMSession(ids);
+ if (ad_hoc_found)
+ {
+ new_session = false;
+ session_id = ad_hoc_found->mSessionID;
+ }
+ }
+
+ if (new_session)
+ {
+ LLIMModel::getInstance()->newSession(session_id, name, dialog, other_participant_id, ids, voice);
+ }
+
+ //*TODO remove this "floater" thing when Communicate Floater's gone
LLFloaterIMPanel* floater = findFloaterBySession(session_id);
if(!floater)
{
@@ -811,44 +2425,56 @@ LLUUID LLIMMgr::addSession(
session_id,
other_participant_id,
name,
- ids,
dialog,
- TRUE);
-
- if ( !floater ) return LLUUID::null;
+ TRUE,
+ ids);
+ }
- noteOfflineUsers(floater, ids);
- LLFloaterChatterBox::showInstance(session_id);
+ //we don't need to show notes about online/offline, mute/unmute users' statuses for existing sessions
+ if (!new_session) return session_id;
+
+ //Per Plan's suggestion commented "explicit offline status warning" out to make Dessie happier (see EXT-3609)
+ //*TODO After February 2010 remove this commented out line if no one will be missing that warning
+ //noteOfflineUsers(session_id, floater, ids);
- // Only warn for regular IMs - not group IMs
- if( dialog == IM_NOTHING_SPECIAL )
- {
- noteMutedUsers(floater, ids);
- }
- }
- else
+ // Only warn for regular IMs - not group IMs
+ if( dialog == IM_NOTHING_SPECIAL )
{
- floater->open();
+ noteMutedUsers(session_id, floater, ids);
}
- //mTabContainer->selectTabPanel(panel);
- floater->setInputFocus(TRUE);
- return floater->getSessionID();
+
+ return session_id;
+}
+
+bool LLIMMgr::leaveSession(const LLUUID& session_id)
+{
+ LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id);
+ if (!im_session) return false;
+
+ LLIMModel::getInstance()->sendLeaveSession(session_id, im_session->mOtherParticipantID);
+ gIMMgr->removeSession(session_id);
+ return true;
}
-// This removes the panel referenced by the uuid, and then restores
-// internal consistency. The internal pointer is not deleted.
+// Removes data associated with a particular session specified by session_id
void LLIMMgr::removeSession(const LLUUID& session_id)
{
+ llassert_always(hasSession(session_id));
+
+ //*TODO remove this floater thing when Communicate Floater is being deleted (IB)
LLFloaterIMPanel* floater = findFloaterBySession(session_id);
if(floater)
{
mFloaters.erase(floater->getHandle());
- LLFloaterChatterBox::getInstance(LLSD())->removeFloater(floater);
- //mTabContainer->removeTabPanel(floater);
-
- clearPendingInvitation(session_id);
- clearPendingAgentListUpdates(session_id);
+ LLFloaterChatterBox::getInstance()->removeFloater(floater);
}
+
+ clearPendingInvitation(session_id);
+ clearPendingAgentListUpdates(session_id);
+
+ LLIMModel::getInstance()->clearSession(session_id);
+
+ notifyObserverSessionRemoved(session_id);
}
void LLIMMgr::inviteToSession(
@@ -932,65 +2558,26 @@ void LLIMMgr::inviteToSession(
{
if (caller_name.empty())
{
- gCacheName->getName(caller_id, onInviteNameLookup, new LLSD(payload));
+ gCacheName->get(caller_id, FALSE, boost::bind(&LLIMMgr::onInviteNameLookup, payload, _1, _2, _3, _4));
}
else
{
- LLSD args;
- args["NAME"] = caller_name;
- args["GROUP"] = session_name;
-
- LLNotifications::instance().add(notify_box_type,
- args,
- payload,
- &inviteUserResponse);
-
+ LLFloaterReg::showInstance("incoming_call", payload, TRUE);
}
mPendingInvitations[session_id.asString()] = LLSD();
}
}
-//static
-void LLIMMgr::onInviteNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* userdata)
+void LLIMMgr::onInviteNameLookup(LLSD payload, const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
{
- LLSD payload = *(LLSD*)userdata;
- delete (LLSD*)userdata;
-
payload["caller_name"] = first + " " + last;
payload["session_name"] = payload["caller_name"].asString();
- LLSD args;
- args["NAME"] = payload["caller_name"].asString();
-
- LLNotifications::instance().add(
- payload["notify_box_type"].asString(),
- args,
- payload,
- &inviteUserResponse);
-}
-
-void LLIMMgr::refresh()
-{
-}
+ std::string notify_box_type = payload["notify_box_type"].asString();
-void LLIMMgr::setFloaterOpen(BOOL set_open)
-{
- if (set_open)
- {
- LLFloaterChatterBox::showInstance();
- }
- else
- {
- LLFloaterChatterBox::hideInstance();
- }
+ LLFloaterReg::showInstance("incoming_call", payload, TRUE);
}
-
-BOOL LLIMMgr::getFloaterOpen()
-{
- return LLFloaterChatterBox::instanceVisible(LLSD());
-}
-
void LLIMMgr::disconnectAllSessions()
{
LLFloaterIMPanel* floater = NULL;
@@ -1007,7 +2594,7 @@ void LLIMMgr::disconnectAllSessions()
if (floater)
{
floater->setEnabled(FALSE);
- floater->close(TRUE);
+ floater->closeFloater(TRUE);
}
}
}
@@ -1037,7 +2624,7 @@ LLFloaterIMPanel* LLIMMgr::findFloaterBySession(const LLUUID& session_id)
BOOL LLIMMgr::hasSession(const LLUUID& session_id)
{
- return (findFloaterBySession(session_id) != NULL);
+ return LLIMModel::getInstance()->findIMSession(session_id) != NULL;
}
void LLIMMgr::clearPendingInvitation(const LLUUID& session_id)
@@ -1048,6 +2635,34 @@ void LLIMMgr::clearPendingInvitation(const LLUUID& session_id)
}
}
+void LLIMMgr::processAgentListUpdates(const LLUUID& session_id, const LLSD& body)
+{
+ LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+ if ( im_floater )
+ {
+ im_floater->processAgentListUpdates(body);
+ }
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id);
+ if (speaker_mgr)
+ {
+ speaker_mgr->updateSpeakers(body);
+
+ // also the same call is added into LLVoiceClient::participantUpdatedEvent because
+ // sometimes it is called AFTER LLViewerChatterBoxSessionAgentListUpdates::post()
+ // when moderation state changed too late. See EXT-3544.
+ speaker_mgr->update(true);
+ }
+ else
+ {
+ //we don't have a speaker manager yet..something went wrong
+ //we are probably receiving an update here before
+ //a start or an acceptance of an invitation. Race condition.
+ gIMMgr->addPendingAgentListUpdates(
+ session_id,
+ body);
+ }
+}
+
LLSD LLIMMgr::getPendingAgentListUpdates(const LLUUID& session_id)
{
if ( mPendingAgentListUpdates.has(session_id.asString()) )
@@ -1128,41 +2743,79 @@ void LLIMMgr::clearPendingAgentListUpdates(const LLUUID& session_id)
}
}
-// create a floater and update internal representation for
-// consistency. Returns the pointer, caller (the class instance since
-// it is a private method) is not responsible for deleting the
-// pointer. Add the floater to this but do not select it.
-LLFloaterIMPanel* LLIMMgr::createFloater(
- const LLUUID& session_id,
- const LLUUID& other_participant_id,
- const std::string& session_label,
- EInstantMessage dialog,
- BOOL user_initiated)
+void LLIMMgr::notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id)
{
- if (session_id.isNull())
+ for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++)
{
- llwarns << "Creating LLFloaterIMPanel with null session ID" << llendl;
+ (*it)->sessionAdded(session_id, name, other_participant_id);
}
+}
- llinfos << "LLIMMgr::createFloater: from " << other_participant_id
- << " in session " << session_id << llendl;
- LLFloaterIMPanel* floater = new LLFloaterIMPanel(session_label,
- session_id,
- other_participant_id,
- dialog);
- LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END;
- LLFloaterChatterBox::getInstance(LLSD())->addFloater(floater, FALSE, i_pt);
- mFloaters.insert(floater->getHandle());
- return floater;
+void LLIMMgr::notifyObserverSessionRemoved(const LLUUID& session_id)
+{
+ for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++)
+ {
+ (*it)->sessionRemoved(session_id);
+ }
+}
+
+void LLIMMgr::notifyObserverSessionIDUpdated( const LLUUID& old_session_id, const LLUUID& new_session_id )
+{
+ for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++)
+ {
+ (*it)->sessionIDUpdated(old_session_id, new_session_id);
+ }
+
+}
+
+void LLIMMgr::addSessionObserver(LLIMSessionObserver *observer)
+{
+ mSessionObservers.push_back(observer);
+}
+
+void LLIMMgr::removeSessionObserver(LLIMSessionObserver *observer)
+{
+ mSessionObservers.remove(observer);
+}
+
+bool LLIMMgr::startCall(const LLUUID& session_id, LLVoiceChannel::EDirection direction)
+{
+ LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(session_id);
+ if (!voice_channel) return false;
+
+ voice_channel->setCallDirection(direction);
+ voice_channel->activate();
+ return true;
}
+bool LLIMMgr::endCall(const LLUUID& session_id)
+{
+ LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(session_id);
+ if (!voice_channel) return false;
+
+ voice_channel->deactivate();
+ return true;
+}
+
+bool LLIMMgr::isVoiceCall(const LLUUID& session_id)
+{
+ LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id);
+ if (!im_session) return false;
+
+ return im_session->mStartedAsIMCall;
+}
+
+// create a floater and update internal representation for
+// consistency. Returns the pointer, caller (the class instance since
+// it is a private method) is not responsible for deleting the
+// pointer. Add the floater to this but do not select it.
LLFloaterIMPanel* LLIMMgr::createFloater(
const LLUUID& session_id,
const LLUUID& other_participant_id,
const std::string& session_label,
- const LLDynamicArray<LLUUID>& ids,
EInstantMessage dialog,
- BOOL user_initiated)
+ BOOL user_initiated,
+ const LLDynamicArray<LLUUID>& ids)
{
if (session_id.isNull())
{
@@ -1177,24 +2830,31 @@ LLFloaterIMPanel* LLIMMgr::createFloater(
ids,
dialog);
LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END;
- LLFloaterChatterBox::getInstance(LLSD())->addFloater(floater, FALSE, i_pt);
+ LLFloaterChatterBox::getInstance()->addFloater(floater, FALSE, i_pt);
mFloaters.insert(floater->getHandle());
return floater;
}
void LLIMMgr::noteOfflineUsers(
+ const LLUUID& session_id,
LLFloaterIMPanel* floater,
const LLDynamicArray<LLUUID>& ids)
{
S32 count = ids.count();
if(count == 0)
{
- floater->addHistoryLine(sOnlyUserMessage, gSavedSettings.getColor4("SystemChatColor"));
+ const std::string& only_user = LLTrans::getString("only_user_message");
+ if (floater)
+ {
+ floater->addHistoryLine(only_user, LLUIColorTable::instance().getColor("SystemChatColor"));
+ }
+ LLIMModel::getInstance()->addMessage(session_id, SYSTEM_FROM, LLUUID::null, only_user);
}
else
{
const LLRelationship* info = NULL;
LLAvatarTracker& at = LLAvatarTracker::instance();
+ LLIMModel& im_model = LLIMModel::instance();
for(S32 i = 0; i < count; ++i)
{
info = at.getBuddyInfo(ids.get(i));
@@ -1202,16 +2862,16 @@ void LLIMMgr::noteOfflineUsers(
if(info && !info->isOnline()
&& gCacheName->getName(ids.get(i), first, last))
{
- LLUIString offline = sOfflineMessage;
+ LLUIString offline = LLTrans::getString("offline_message");
offline.setArg("[FIRST]", first);
offline.setArg("[LAST]", last);
- floater->addHistoryLine(offline, gSavedSettings.getColor4("SystemChatColor"));
+ im_model.proccessOnlineOfflineNotification(session_id, offline);
}
}
}
}
-void LLIMMgr::noteMutedUsers(LLFloaterIMPanel* floater,
+void LLIMMgr::noteMutedUsers(const LLUUID& session_id, LLFloaterIMPanel* floater,
const LLDynamicArray<LLUUID>& ids)
{
// Don't do this if we don't have a mute list.
@@ -1224,12 +2884,18 @@ void LLIMMgr::noteMutedUsers(LLFloaterIMPanel* floater,
S32 count = ids.count();
if(count > 0)
{
+ LLIMModel* im_model = LLIMModel::getInstance();
+
for(S32 i = 0; i < count; ++i)
{
if( ml->isMuted(ids.get(i)) )
{
- LLUIString muted = sMutedMessage;
+ LLUIString muted = LLTrans::getString("muted_message");
+
+ //*TODO remove this "floater" thing when Communicate Floater's gone
floater->addHistoryLine(muted);
+
+ im_model->addMessage(session_id, SYSTEM_FROM, LLUUID::null, muted);
break;
}
}
@@ -1254,24 +2920,14 @@ void LLIMMgr::processIMTypingCore(const LLIMInfo* im_info, BOOL typing)
{
floater->processIMTyping(im_info, typing);
}
-}
-void LLIMMgr::updateFloaterSessionID(
- const LLUUID& old_session_id,
- const LLUUID& new_session_id)
-{
- LLFloaterIMPanel* floater = findFloaterBySession(old_session_id);
- if (floater)
+ LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+ if ( im_floater )
{
- floater->sessionInitReplyReceived(new_session_id);
+ im_floater->processIMTyping(im_info, typing);
}
}
-LLFloaterChatterBox* LLIMMgr::getFloater()
-{
- return LLFloaterChatterBox::getInstance(LLSD());
-}
-
class LLViewerChatterBoxSessionStartReply : public LLHTTPNode
{
public:
@@ -1300,40 +2956,40 @@ public:
if ( success )
{
session_id = body["session_id"].asUUID();
- gIMMgr->updateFloaterSessionID(
- temp_session_id,
- session_id);
+
+ LLIMModel::getInstance()->processSessionInitializedReply(temp_session_id, session_id);
+
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id);
+ if (speaker_mgr)
+ {
+ speaker_mgr->setSpeakers(body);
+ speaker_mgr->updateSpeakers(gIMMgr->getPendingAgentListUpdates(session_id));
+ }
+
LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(session_id);
if (floaterp)
{
- floaterp->setSpeakers(body);
-
- //apply updates we've possibly received previously
- floaterp->updateSpeakersList(
- gIMMgr->getPendingAgentListUpdates(session_id));
-
if ( body.has("session_info") )
{
floaterp->processSessionUpdate(body["session_info"]);
}
+ }
- //aply updates we've possibly received previously
- floaterp->updateSpeakersList(
- gIMMgr->getPendingAgentListUpdates(session_id));
+ LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+ if ( im_floater )
+ {
+ if ( body.has("session_info") )
+ {
+ im_floater->processSessionUpdate(body["session_info"]);
+ }
}
+
gIMMgr->clearPendingAgentListUpdates(session_id);
}
else
{
- //throw an error dialog and close the temp session's
- //floater
- LLFloaterIMPanel* floater =
- gIMMgr->findFloaterBySession(temp_session_id);
-
- if ( floater )
- {
- floater->showSessionStartError(body["error"].asString());
- }
+ //throw an error dialog and close the temp session's floater
+ gIMMgr->showSessionStartError(body["error"].asString(), temp_session_id);
}
gIMMgr->clearPendingAgentListUpdates(session_id);
@@ -1366,15 +3022,10 @@ public:
if ( !success )
{
//throw an error dialog
- LLFloaterIMPanel* floater =
- gIMMgr->findFloaterBySession(session_id);
-
- if (floater)
- {
- floater->showSessionEventError(
- body["event"].asString(),
- body["error"].asString());
- }
+ gIMMgr->showSessionEventError(
+ body["event"].asString(),
+ body["error"].asString(),
+ session_id);
}
}
};
@@ -1392,13 +3043,7 @@ public:
session_id = input["body"]["session_id"].asUUID();
reason = input["body"]["reason"].asString();
- LLFloaterIMPanel* floater =
- gIMMgr ->findFloaterBySession(session_id);
-
- if ( floater )
- {
- floater->showSessionForceClose(reason);
- }
+ gIMMgr->showSessionForceClose(reason, session_id);
}
};
@@ -1410,21 +3055,8 @@ public:
const LLSD& context,
const LLSD& input) const
{
- LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(input["body"]["session_id"].asUUID());
- if (floaterp)
- {
- floaterp->updateSpeakersList(
- input["body"]);
- }
- else
- {
- //we don't have a floater yet..something went wrong
- //we are probably receiving an update here before
- //a start or an acceptance of an invitation. Race condition.
- gIMMgr->addPendingAgentListUpdates(
- input["body"]["session_id"].asUUID(),
- input["body"]);
- }
+ const LLUUID& session_id = input["body"]["session_id"].asUUID();
+ gIMMgr->processAgentListUpdates(session_id, input["body"]);
}
};
@@ -1436,11 +3068,22 @@ public:
const LLSD& context,
const LLSD& input) const
{
- LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(input["body"]["session_id"].asUUID());
+ LLUUID session_id = input["body"]["session_id"].asUUID();
+ LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(session_id);
if (floaterp)
{
floaterp->processSessionUpdate(input["body"]["info"]);
}
+ LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+ if ( im_floater )
+ {
+ im_floater->processSessionUpdate(input["body"]["info"]);
+ }
+ LLIMSpeakerMgr* im_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id);
+ if (im_mgr)
+ {
+ im_mgr->processSessionUpdate(input["body"]["info"]);
+ }
}
};
@@ -1489,15 +3132,6 @@ public:
BOOL is_linden = LLMuteList::getInstance()->isLinden(name);
std::string separator_string(": ");
- int message_offset=0;
-
- //Handle IRC styled /me messages.
- std::string prefix = message.substr(0, 4);
- if (prefix == "/me " || prefix == "/me'")
- {
- separator_string = "";
- message_offset = 3;
- }
chat.mMuted = is_muted && !is_linden;
chat.mFromID = from_id;
@@ -1514,7 +3148,7 @@ public:
{
saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str());
}
- std::string buffer = separator_string + saved + message.substr(message_offset);
+ std::string buffer = saved + message;
BOOL is_this_agent = FALSE;
if(from_id == gAgentID)
@@ -1533,9 +3167,6 @@ public:
ll_vector3_from_sd(message_params["position"]),
true);
- chat.mText = std::string("IM: ") + name + separator_string + saved + message.substr(message_offset);
- LLFloaterChat::addChat(chat, TRUE, is_this_agent);
-
//K now we want to accept the invitation
std::string url = gAgent.getRegion()->getCapability(
"ChatSessionRequest");
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index a4e419694d..a3b4f78af0 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -33,18 +33,257 @@
#ifndef LL_LLIMVIEW_H
#define LL_LLIMVIEW_H
-#include "llfloater.h"
+#include "lldockablefloater.h"
#include "llinstantmessage.h"
-#include "lluuid.h"
+
+#include "lllogchat.h"
+#include "llvoicechannel.h"
class LLFloaterChatterBox;
class LLUUID;
class LLFloaterIMPanel;
class LLFriendObserver;
-class LLFloaterIM;
+class LLCallDialogManager;
+class LLIMSpeakerMgr;
+
+
+class LLIMModel : public LLSingleton<LLIMModel>
+{
+public:
+
+ struct LLIMSession
+ {
+ typedef enum e_session_type
+ { // for now we have 4 predefined types for a session
+ P2P_SESSION,
+ GROUP_SESSION,
+ ADHOC_SESSION,
+ AVALINE_SESSION,
+ } SType;
+
+ LLIMSession(const LLUUID& session_id, const std::string& name,
+ const EInstantMessage& type, const LLUUID& other_participant_id, const std::vector<LLUUID>& ids, bool voice);
+ virtual ~LLIMSession();
+
+ void sessionInitReplyReceived(const LLUUID& new_session_id);
+ void addMessagesFromHistory(const std::list<LLSD>& history);
+ void addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time);
+ void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction);
+
+ /** @deprecated */
+ static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata);
+
+ bool isAdHoc();
+ bool isP2P();
+ bool isOtherParticipantAvaline();
+
+ bool isP2PSessionType() const { return mSessionType == P2P_SESSION;}
+ bool isAdHocSessionType() const { return mSessionType == ADHOC_SESSION;}
+ bool isGroupSessionType() const { return mSessionType == GROUP_SESSION;}
+ bool isAvalineSessionType() const { return mSessionType == AVALINE_SESSION;}
+
+ //*TODO make private
+ /** ad-hoc sessions involve sophisticated chat history file naming schemes */
+ void buildHistoryFileName();
+
+ //*TODO make private
+ static std::string generateHash(const std::set<LLUUID>& sorted_uuids);
+
+ LLUUID mSessionID;
+ std::string mName;
+ EInstantMessage mType;
+ SType mSessionType;
+ LLUUID mOtherParticipantID;
+ std::vector<LLUUID> mInitialTargetIDs;
+ std::string mHistoryFileName;
+
+ // connection to voice channel state change signal
+ boost::signals2::connection mVoiceChannelStateChangeConnection;
+
+ //does NOT include system messages and agent's messages
+ S32 mParticipantUnreadMessageCount;
+
+ // does include all incoming messages
+ S32 mNumUnread;
+
+ std::list<LLSD> mMsgs;
+
+ LLVoiceChannel* mVoiceChannel;
+ LLIMSpeakerMgr* mSpeakers;
+
+ bool mSessionInitialized;
+
+ //true if calling back the session URI after the session has closed is possible.
+ //Currently this will be false only for PSTN P2P calls.
+ bool mCallBackEnabled;
+
+ bool mTextIMPossible;
+ bool mOtherParticipantIsAvatar;
+ bool mStartCallOnInitialize;
+
+ //if IM session is created for a voice call
+ bool mStartedAsIMCall;
+ };
+
+
+ LLIMModel();
+
+
+ //we should control the currently active session
+ LLUUID mActiveSessionID;
+ void setActiveSessionID(const LLUUID& session_id);
+ void resetActiveSessionID() { mActiveSessionID.setNull(); }
+ LLUUID getActiveSessionID() { return mActiveSessionID; }
+
+ /** Session id to session object */
+ std::map<LLUUID, LLIMSession*> mId2SessionMap;
+
+ typedef boost::signals2::signal<void(const LLSD&)> session_signal_t;
+ typedef boost::function<void(const LLSD&)> session_callback_t;
+ session_signal_t mNewMsgSignal;
+ session_signal_t mNoUnreadMsgsSignal;
+
+ /**
+ * Find an IM Session corresponding to session_id
+ * Returns NULL if the session does not exist
+ */
+ LLIMSession* findIMSession(const LLUUID& session_id) const;
+
+ /**
+ * Find an Ad-Hoc IM Session with specified participants
+ * @return first found Ad-Hoc session or NULL if the session does not exist
+ */
+ LLIMSession* findAdHocIMSession(const std::vector<LLUUID>& ids);
+
+ /**
+ * Rebind session data to a new session id.
+ */
+ void processSessionInitializedReply(const LLUUID& old_session_id, const LLUUID& new_session_id);
+
+ boost::signals2::connection addNewMsgCallback( session_callback_t cb ) { return mNewMsgSignal.connect(cb); }
+ boost::signals2::connection addNoUnreadMsgsCallback( session_callback_t cb ) { return mNoUnreadMsgsSignal.connect(cb); }
+
+ /**
+ * Create new session object in a model
+ * @param name session name should not be empty, will return false if empty
+ */
+ bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id,
+ const std::vector<LLUUID>& ids, bool voice = false);
+
+ bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type,
+ const LLUUID& other_participant_id, bool voice = false);
+
+ /**
+ * Remove all session data associated with a session specified by session_id
+ */
+ bool clearSession(const LLUUID& session_id);
+
+ /**
+ * Populate supplied std::list with messages starting from index specified by start_index
+ */
+ void getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0);
+
+ /**
+ * Add a message to an IM Model - the message is saved in a message store associated with a session specified by session_id
+ * and also saved into a file if log2file is specified.
+ * It sends new message signal for each added message.
+ */
+ bool addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& other_participant_id, const std::string& utf8_text, bool log2file = true);
+
+ /**
+ * Similar to addMessage(...) above but won't send a signal about a new message added
+ */
+ LLIMModel::LLIMSession* addMessageSilently(const LLUUID& session_id, const std::string& from, const LLUUID& from_id,
+ const std::string& utf8_text, bool log2file = true);
+
+ /**
+ * Add a system message to an IM Model
+ */
+ bool proccessOnlineOfflineNotification(const LLUUID& session_id, const std::string& utf8_text);
+
+ /**
+ * Get a session's name.
+ * For a P2P chat - it's an avatar's name,
+ * For a group chat - it's a group's name
+ * For an ad-hoc chat - is received from the server and is in a from of "<Avatar's name> conference"
+ */
+ const std::string& getName(const LLUUID& session_id) const;
+
+ /**
+ * Get number of unread messages in a session with session_id
+ * Returns -1 if the session with session_id doesn't exist
+ */
+ const S32 getNumUnread(const LLUUID& session_id) const;
+
+ /**
+ * Get uuid of other participant in a session with session_id
+ * Returns LLUUID::null if the session doesn't exist
+ *
+ * *TODO what to do with other participants in ad-hoc and group chats?
+ */
+ const LLUUID& getOtherParticipantID(const LLUUID& session_id) const;
+
+ /**
+ * Get type of a session specified by session_id
+ * Returns EInstantMessage::IM_COUNT if the session does not exist
+ */
+ EInstantMessage getType(const LLUUID& session_id) const;
+
+ /**
+ * Get voice channel for the session specified by session_id
+ * Returns NULL if the session does not exist
+ */
+ LLVoiceChannel* getVoiceChannel(const LLUUID& session_id) const;
+
+ /**
+ * Get im speaker manager for the session specified by session_id
+ * Returns NULL if the session does not exist
+ */
+ LLIMSpeakerMgr* getSpeakerManager(const LLUUID& session_id) const;
+
+ const std::string& getHistoryFileName(const LLUUID& session_id) const;
+
+ static void sendLeaveSession(const LLUUID& session_id, const LLUUID& other_participant_id);
+ static bool sendStartSession(const LLUUID& temp_session_id, const LLUUID& other_participant_id,
+ const std::vector<LLUUID>& ids, EInstantMessage dialog);
+ static void sendTypingState(LLUUID session_id, LLUUID other_participant_id, BOOL typing);
+ static void sendMessage(const std::string& utf8_text, const LLUUID& im_session_id,
+ const LLUUID& other_participant_id, EInstantMessage dialog);
+
+ void testMessages();
+
+ /**
+ * Saves an IM message into a file
+ */
+ bool logToFile(const std::string& file_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text);
+
+private:
+
+ /**
+ * Add message to a list of message associated with session specified by session_id
+ */
+ bool addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text);
+
+ /**
+ * Save an IM message into a file
+ */
+ bool logToFile(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text);
+};
+
+class LLIMSessionObserver
+{
+public:
+ virtual ~LLIMSessionObserver() {}
+ virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) = 0;
+ virtual void sessionRemoved(const LLUUID& session_id) = 0;
+ virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) = 0;
+};
+
class LLIMMgr : public LLSingleton<LLIMMgr>
{
+ friend class LLIMModel;
+
public:
enum EInvitationType
{
@@ -54,7 +293,7 @@ public:
};
LLIMMgr();
- virtual ~LLIMMgr();
+ virtual ~LLIMMgr() {};
// Add a message to a session. The session can keyed to sesion id
// or agent id.
@@ -71,11 +310,6 @@ public:
void addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLSD& args);
- // This method returns TRUE if the local viewer has a session
- // currently open keyed to the uuid. The uuid can be keyed by
- // either session id or agent id.
- BOOL isIMSessionOpen(const LLUUID& uuid);
-
// This adds a session to the talk view. The name is the local
// name of the session, dialog specifies the type of
// session. Since sessions can be keyed off of first recipient or
@@ -86,25 +320,33 @@ public:
// session.
LLUUID addSession(const std::string& name,
EInstantMessage dialog,
- const LLUUID& other_participant_id);
+ const LLUUID& other_participant_id, bool voice = false);
// Adds a session using a specific group of starting agents
// the dialog type is assumed correct. Returns the uuid of the session.
LLUUID addSession(const std::string& name,
EInstantMessage dialog,
const LLUUID& other_participant_id,
- const LLDynamicArray<LLUUID>& ids);
-
- // Creates a P2P session with the requisite handle for responding to voice calls
+ const LLDynamicArray<LLUUID>& ids, bool voice = false);
+
+ /**
+ * Creates a P2P session with the requisite handle for responding to voice calls.
+ *
+ * @param name session name, cannot be null
+ * @param caller_uri - sip URI of caller. It should be always be passed into the method to avoid
+ * incorrect working of LLVoiceChannel instances. See EXT-2985.
+ */
LLUUID addP2PSession(const std::string& name,
const LLUUID& other_participant_id,
const std::string& voice_session_handle,
- const std::string& caller_uri = LLStringUtil::null);
+ const std::string& caller_uri);
- // This removes the panel referenced by the uuid, and then
- // restores internal consistency. The internal pointer is not
- // deleted.
- void removeSession(const LLUUID& session_id);
+ /**
+ * Leave the session with session id. Send leave session notification
+ * to the server and removes all associated session data
+ * @return false if the session with specified id was not exist
+ */
+ bool leaveSession(const LLUUID& session_id);
void inviteToSession(
const LLUUID& session_id,
@@ -116,28 +358,25 @@ public:
const std::string& session_handle = LLStringUtil::null,
const std::string& session_uri = LLStringUtil::null);
- //Updates a given session's session IDs. Does not open,
- //create or do anything new. If the old session doesn't
- //exist, then nothing happens.
- void updateFloaterSessionID(const LLUUID& old_session_id,
- const LLUUID& new_session_id);
-
void processIMTypingStart(const LLIMInfo* im_info);
void processIMTypingStop(const LLIMInfo* im_info);
- // Rebuild stuff
- void refresh();
-
void notifyNewIM();
void clearNewIMNotification();
+ // automatically start a call once the session has initialized
+ void autoStartCallOnStartup(const LLUUID& session_id);
+
// IM received that you haven't seen yet
BOOL getIMReceived() const;
- void setFloaterOpen(BOOL open); /*Flawfinder: ignore*/
- BOOL getFloaterOpen();
+ // Calc number of all unread IMs
+ S32 getNumberOfUnreadIM();
- LLFloaterChatterBox* getFloater();
+ /**
+ * Calculates number of unread IMs from real participants in all stored sessions
+ */
+ S32 getNumberOfUnreadParticipantMessages();
// This method is used to go through all active sessions and
// disable all of them. This method is usally called when you are
@@ -145,12 +384,6 @@ public:
// good connection.
void disconnectAllSessions();
- static void toggle(void*);
-
- // This is a helper function to determine what kind of im session
- // should be used for the given agent.
- static EInstantMessage defaultIMTypeForAgent(const LLUUID& agent_id);
-
BOOL hasSession(const LLUUID& session_id);
// This method returns the im panel corresponding to the uuid
@@ -162,6 +395,7 @@ public:
void clearPendingInvitation(const LLUUID& session_id);
+ void processAgentListUpdates(const LLUUID& session_id, const LLSD& body);
LLSD getPendingAgentListUpdates(const LLUUID& session_id);
void addPendingAgentListUpdates(
const LLUUID& sessioN_id,
@@ -169,9 +403,39 @@ public:
void clearPendingAgentListUpdates(const LLUUID& session_id);
//HACK: need a better way of enumerating existing session, or listening to session create/destroy events
+ //@deprecated, is used only by LLToolBox, which is not used anywhere, right? (IB)
const std::set<LLHandle<LLFloater> >& getIMFloaterHandles() { return mFloaters; }
+ void addSessionObserver(LLIMSessionObserver *);
+ void removeSessionObserver(LLIMSessionObserver *);
+
+ //show error statuses to the user
+ void showSessionStartError(const std::string& error_string, const LLUUID session_id);
+ void showSessionEventError(const std::string& event_string, const std::string& error_string, const LLUUID session_id);
+ void showSessionForceClose(const std::string& reason, const LLUUID session_id);
+ static bool onConfirmForceCloseError(const LLSD& notification, const LLSD& response);
+
+ /**
+ * Start call in a session
+ * @return false if voice channel doesn't exist
+ **/
+ bool startCall(const LLUUID& session_id, LLVoiceChannel::EDirection direction = LLVoiceChannel::OUTGOING_CALL);
+
+ /**
+ * End call in a session
+ * @return false if voice channel doesn't exist
+ **/
+ bool endCall(const LLUUID& session_id);
+
+ bool isVoiceCall(const LLUUID& session_id);
+
private:
+
+ /**
+ * Remove data associated with a particular session specified by session_id
+ */
+ void removeSession(const LLUUID& session_id);
+
// create a panel and update internal representation for
// consistency. Returns the pointer, caller (the class instance
// since it is a private method) is not responsible for deleting
@@ -180,29 +444,31 @@ private:
const LLUUID& target_id,
const std::string& name,
EInstantMessage dialog,
- BOOL user_initiated = FALSE);
-
- LLFloaterIMPanel* createFloater(const LLUUID& session_id,
- const LLUUID& target_id,
- const std::string& name,
- const LLDynamicArray<LLUUID>& ids,
- EInstantMessage dialog,
- BOOL user_initiated = FALSE);
+ BOOL user_initiated = FALSE,
+ const LLDynamicArray<LLUUID>& ids = LLDynamicArray<LLUUID>());
// This simple method just iterates through all of the ids, and
// prints a simple message if they are not online. Used to help
// reduce 'hello' messages to the linden employees unlucky enough
// to have their calling card in the default inventory.
- void noteOfflineUsers(LLFloaterIMPanel* panel, const LLDynamicArray<LLUUID>& ids);
- void noteMutedUsers(LLFloaterIMPanel* panel, const LLDynamicArray<LLUUID>& ids);
+ void noteOfflineUsers(const LLUUID& session_id, LLFloaterIMPanel* panel, const LLDynamicArray<LLUUID>& ids);
+ void noteMutedUsers(const LLUUID& session_id, LLFloaterIMPanel* panel, const LLDynamicArray<LLUUID>& ids);
void processIMTypingCore(const LLIMInfo* im_info, BOOL typing);
- static void onInviteNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* userdata);
+ static void onInviteNameLookup(LLSD payload, const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
+
+ void notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id);
+ void notifyObserverSessionRemoved(const LLUUID& session_id);
+ void notifyObserverSessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id);
private:
+
+ //*TODO should be deleted when Communicate Floater is being deleted
std::set<LLHandle<LLFloater> > mFloaters;
- LLFriendObserver* mFriendObserver;
+
+ typedef std::list <LLIMSessionObserver *> session_observers_list_t;
+ session_observers_list_t mSessionObservers;
// An IM has been received that you haven't seen yet.
BOOL mIMReceived;
@@ -211,16 +477,93 @@ private:
LLSD mPendingAgentListUpdates;
};
+class LLCallDialogManager : public LLInitClass<LLCallDialogManager>
+{
+public:
+ LLCallDialogManager();
+ ~LLCallDialogManager();
+
+ static void initClass();
+ static void onVoiceChannelChanged(const LLUUID &session_id);
+ static void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction);
+
+protected:
+ static std::string sPreviousSessionlName;
+ static LLIMModel::LLIMSession::SType sPreviousSessionType;
+ static std::string sCurrentSessionlName;
+ static LLIMModel::LLIMSession* sSession;
+ static LLVoiceChannel::EState sOldState;
+};
-class LLFloaterIM : public LLMultiFloater
+class LLCallDialog : public LLDockableFloater
{
public:
- LLFloaterIM();
+ LLCallDialog(const LLSD& payload);
+ ~LLCallDialog() {}
+
+ virtual BOOL postBuild();
+
+ // check timer state
+ /*virtual*/ void draw();
+
+protected:
+ // lifetime timer for a notification
+ LLTimer mLifetimeTimer;
+ // notification's lifetime in seconds
+ S32 mLifetime;
+ static const S32 DEFAULT_LIFETIME = 5;
+ virtual bool lifetimeHasExpired() {return false;};
+ virtual void onLifetimeExpired() {};
+
+ virtual void getAllowedRect(LLRect& rect);
+
+ /**
+ * Sets icon depend on session.
+ *
+ * If passed session_id is a group id group icon will be shown, otherwise avatar icon for participant_id
+ *
+ * @param session_id - UUID of session
+ * @param participant_id - UUID of other participant
+ */
+ void setIcon(const LLSD& session_id, const LLSD& participant_id);
+
+ LLSD mPayload;
+};
+
+class LLIncomingCallDialog : public LLCallDialog
+{
+public:
+ LLIncomingCallDialog(const LLSD& payload);
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ static void onAccept(void* user_data);
+ static void onReject(void* user_data);
+ static void onStartIM(void* user_data);
+
+private:
+ /*virtual*/ bool lifetimeHasExpired();
+ /*virtual*/ void onLifetimeExpired();
+ void processCallResponse(S32 response);
+};
+
+class LLOutgoingCallDialog : public LLCallDialog
+{
+public:
+ LLOutgoingCallDialog(const LLSD& payload);
+
/*virtual*/ BOOL postBuild();
+ void show(const LLSD& key);
+
+ static void onCancel(void* user_data);
+ static const LLUUID OCD_KEY;
- static std::map<std::string,std::string> sEventStringsMap;
- static std::map<std::string,std::string> sErrorStringsMap;
- static std::map<std::string,std::string> sForceCloseSessionMap;
+private:
+ // hide all text boxes
+ void hideAllText();
+ /*virtual*/ bool lifetimeHasExpired();
+ /*virtual*/ void onLifetimeExpired();
};
// Globals
diff --git a/indra/newview/llinspect.cpp b/indra/newview/llinspect.cpp
new file mode 100644
index 0000000000..c7b8db9635
--- /dev/null
+++ b/indra/newview/llinspect.cpp
@@ -0,0 +1,110 @@
+/**
+ * @file llinspect.cpp
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "llviewerprecompiledheaders.h"
+
+#include "llinspect.h"
+
+#include "llcontrol.h" // LLCachedControl
+#include "llui.h" // LLUI::sSettingsGroups
+
+LLInspect::LLInspect(const LLSD& key)
+: LLFloater(key),
+ mCloseTimer(),
+ mOpenTimer()
+{
+}
+
+LLInspect::~LLInspect()
+{
+}
+
+// virtual
+void LLInspect::draw()
+{
+ static LLCachedControl<F32> FADE_TIME(*LLUI::sSettingGroups["config"], "InspectorFadeTime", 1.f);
+ static LLCachedControl<F32> STAY_TIME(*LLUI::sSettingGroups["config"], "InspectorShowTime", 1.f);
+ if (mOpenTimer.getStarted())
+ {
+ LLFloater::draw();
+ if (mOpenTimer.getElapsedTimeF32() > STAY_TIME)
+ {
+ mOpenTimer.stop();
+ mCloseTimer.start();
+ }
+
+ }
+ else if (mCloseTimer.getStarted())
+ {
+ F32 alpha = clamp_rescale(mCloseTimer.getElapsedTimeF32(), 0.f, FADE_TIME, 1.f, 0.f);
+ LLViewDrawContext context(alpha);
+ LLFloater::draw();
+ if (mCloseTimer.getElapsedTimeF32() > FADE_TIME)
+ {
+ closeFloater(false);
+ }
+ }
+ else
+ {
+ LLFloater::draw();
+ }
+}
+
+// virtual
+void LLInspect::onOpen(const LLSD& data)
+{
+ LLFloater::onOpen(data);
+
+ mCloseTimer.stop();
+ mOpenTimer.start();
+}
+
+// virtual
+void LLInspect::onFocusLost()
+{
+ LLFloater::onFocusLost();
+
+ // Start closing when we lose focus
+ mCloseTimer.start();
+ mOpenTimer.stop();
+}
+
+// virtual
+BOOL LLInspect::handleHover(S32 x, S32 y, MASK mask)
+{
+ mOpenTimer.pause();
+ return LLView::handleHover(x, y, mask);
+}
+
+// virtual
+void LLInspect::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ mOpenTimer.unpause();
+}
diff --git a/indra/newview/llinspect.h b/indra/newview/llinspect.h
new file mode 100644
index 0000000000..a1cb9cd71c
--- /dev/null
+++ b/indra/newview/llinspect.h
@@ -0,0 +1,64 @@
+/**
+ * @file llinspect.h
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLINSPECT_H
+#define LLINSPECT_H
+
+#include "llfloater.h"
+#include "llframetimer.h"
+
+/// Base class for all inspectors (super-tooltips showing a miniature
+/// properties view).
+class LLInspect : public LLFloater
+{
+public:
+ LLInspect(const LLSD& key);
+ virtual ~LLInspect();
+
+ /// Inspectors have a custom fade-in/fade-out animation
+ /*virtual*/ void draw();
+
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+ /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
+
+ /// Start open animation
+ /*virtual*/ void onOpen(const LLSD& avatar_id);
+
+ /// Inspectors close themselves when they lose focus
+ /*virtual*/ void onFocusLost();
+
+protected:
+ LLFrameTimer mCloseTimer;
+ LLFrameTimer mOpenTimer;
+};
+
+#endif
+
diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp
new file mode 100644
index 0000000000..4b0539337b
--- /dev/null
+++ b/indra/newview/llinspectavatar.cpp
@@ -0,0 +1,758 @@
+/**
+ * @file llinspectavatar.cpp
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llinspectavatar.h"
+
+// viewer files
+#include "llagent.h"
+#include "llagentdata.h"
+#include "llavataractions.h"
+#include "llavatarpropertiesprocessor.h"
+#include "llcallingcard.h"
+#include "lldateutil.h"
+#include "llfloaterreporter.h"
+#include "llfloaterworldmap.h"
+#include "llimview.h"
+#include "llinspect.h"
+#include "llmutelist.h"
+#include "llpanelblockedlist.h"
+#include "llstartup.h"
+#include "llspeakers.h"
+#include "llviewermenu.h"
+#include "llvoiceclient.h"
+#include "llviewerobjectlist.h"
+
+// Linden libraries
+#include "llfloater.h"
+#include "llfloaterreg.h"
+#include "llmenubutton.h"
+#include "lltooltip.h" // positionViewNearMouse()
+#include "lluictrl.h"
+
+#include "llavatariconctrl.h"
+
+class LLFetchAvatarData;
+
+
+//////////////////////////////////////////////////////////////////////////////
+// LLInspectAvatar
+//////////////////////////////////////////////////////////////////////////////
+
+// Avatar Inspector, a small information window used when clicking
+// on avatar names in the 2D UI and in the ambient inspector widget for
+// the 3D world.
+class LLInspectAvatar : public LLInspect
+{
+ friend class LLFloaterReg;
+
+public:
+ // avatar_id - Avatar ID for which to show information
+ // Inspector will be positioned relative to current mouse position
+ LLInspectAvatar(const LLSD& avatar_id);
+ virtual ~LLInspectAvatar();
+
+ /*virtual*/ BOOL postBuild(void);
+
+ // Because floater is single instance, need to re-parse data on each spawn
+ // (for example, inspector about same avatar but in different position)
+ /*virtual*/ void onOpen(const LLSD& avatar_id);
+
+ // When closing they should close their gear menu
+ /*virtual*/ void onClose(bool app_quitting);
+
+ // Update view based on information from avatar properties processor
+ void processAvatarData(LLAvatarData* data);
+
+ // override the inspector mouse leave so timer is only paused if
+ // gear menu is not open
+ /* virtual */ void onMouseLeave(S32 x, S32 y, MASK mask);
+
+private:
+ // Make network requests for all the data to display in this view.
+ // Used on construction and if avatar id changes.
+ void requestUpdate();
+
+ // Set the volume slider to this user's current client-side volume setting,
+ // hiding/disabling if the user is not nearby.
+ void updateVolumeSlider();
+
+ // Shows/hides moderator panel depending on voice state
+ void updateModeratorPanel();
+
+ // Moderator ability to enable/disable voice chat for avatar
+ void toggleSelectedVoice(bool enabled);
+
+ // Button callbacks
+ void onClickAddFriend();
+ void onClickViewProfile();
+ void onClickIM();
+ void onClickCall();
+ void onClickTeleport();
+ void onClickInviteToGroup();
+ void onClickPay();
+ void onToggleMute();
+ void onClickReport();
+ void onClickFreeze();
+ void onClickEject();
+ void onClickZoomIn();
+ void onClickFindOnMap();
+ bool onVisibleFindOnMap();
+ bool onVisibleFreezeEject();
+ bool onVisibleZoomIn();
+ void onClickMuteVolume();
+ void onVolumeChange(const LLSD& data);
+ bool enableMute();
+ bool enableUnmute();
+
+ // Is used to determine if "Add friend" option should be enabled in gear menu
+ bool isNotFriend();
+
+ // Callback for gCacheName to look up avatar name
+ void nameUpdatedCallback(
+ const LLUUID& id,
+ const std::string& first,
+ const std::string& last,
+ BOOL is_group);
+
+private:
+ LLUUID mAvatarID;
+ // Need avatar name information to spawn friend add request
+ std::string mAvatarName;
+ // an in-flight request for avatar properties from LLAvatarPropertiesProcessor
+ // is represented by this object
+ LLFetchAvatarData* mPropertiesRequest;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+// LLFetchAvatarData
+//////////////////////////////////////////////////////////////////////////////
+
+// This object represents a pending request for avatar properties information
+class LLFetchAvatarData : public LLAvatarPropertiesObserver
+{
+public:
+ // If the inspector closes it will delete the pending request object, so the
+ // inspector pointer will be valid for the lifetime of this object
+ LLFetchAvatarData(const LLUUID& avatar_id, LLInspectAvatar* inspector)
+ : mAvatarID(avatar_id),
+ mInspector(inspector)
+ {
+ LLAvatarPropertiesProcessor* processor =
+ LLAvatarPropertiesProcessor::getInstance();
+ // register ourselves as an observer
+ processor->addObserver(mAvatarID, this);
+ // send a request (duplicates will be suppressed inside the avatar
+ // properties processor)
+ processor->sendAvatarPropertiesRequest(mAvatarID);
+ }
+
+ ~LLFetchAvatarData()
+ {
+ // remove ourselves as an observer
+ LLAvatarPropertiesProcessor::getInstance()->
+ removeObserver(mAvatarID, this);
+ }
+
+ void processProperties(void* data, EAvatarProcessorType type)
+ {
+ // route the data to the inspector
+ if (data
+ && type == APT_PROPERTIES)
+ {
+ LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data);
+ mInspector->processAvatarData(avatar_data);
+ }
+ }
+
+ // Store avatar ID so we can un-register the observer on destruction
+ LLUUID mAvatarID;
+ LLInspectAvatar* mInspector;
+};
+
+LLInspectAvatar::LLInspectAvatar(const LLSD& sd)
+: LLInspect( LLSD() ), // single_instance, doesn't really need key
+ mAvatarID(), // set in onOpen() *Note: we used to show partner's name but we dont anymore --angela 3rd Dec*
+ mAvatarName(),
+ mPropertiesRequest(NULL)
+{
+ mCommitCallbackRegistrar.add("InspectAvatar.ViewProfile", boost::bind(&LLInspectAvatar::onClickViewProfile, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.AddFriend", boost::bind(&LLInspectAvatar::onClickAddFriend, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.IM",
+ boost::bind(&LLInspectAvatar::onClickIM, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.Call", boost::bind(&LLInspectAvatar::onClickCall, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.Teleport", boost::bind(&LLInspectAvatar::onClickTeleport, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.InviteToGroup", boost::bind(&LLInspectAvatar::onClickInviteToGroup, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.Pay", boost::bind(&LLInspectAvatar::onClickPay, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.ToggleMute", boost::bind(&LLInspectAvatar::onToggleMute, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.Freeze",
+ boost::bind(&LLInspectAvatar::onClickFreeze, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.Eject",
+ boost::bind(&LLInspectAvatar::onClickEject, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.Report", boost::bind(&LLInspectAvatar::onClickReport, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.FindOnMap", boost::bind(&LLInspectAvatar::onClickFindOnMap, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.ZoomIn", boost::bind(&LLInspectAvatar::onClickZoomIn, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.DisableVoice", boost::bind(&LLInspectAvatar::toggleSelectedVoice, this, false));
+ mCommitCallbackRegistrar.add("InspectAvatar.EnableVoice", boost::bind(&LLInspectAvatar::toggleSelectedVoice, this, true));
+ mEnableCallbackRegistrar.add("InspectAvatar.VisibleFindOnMap", boost::bind(&LLInspectAvatar::onVisibleFindOnMap, this));
+ mEnableCallbackRegistrar.add("InspectAvatar.VisibleFreezeEject",
+ boost::bind(&LLInspectAvatar::onVisibleFreezeEject, this));
+ mEnableCallbackRegistrar.add("InspectAvatar.VisibleZoomIn",
+ boost::bind(&LLInspectAvatar::onVisibleZoomIn, this));
+ mEnableCallbackRegistrar.add("InspectAvatar.Gear.Enable", boost::bind(&LLInspectAvatar::isNotFriend, this));
+ mEnableCallbackRegistrar.add("InspectAvatar.EnableMute", boost::bind(&LLInspectAvatar::enableMute, this));
+ mEnableCallbackRegistrar.add("InspectAvatar.EnableUnmute", boost::bind(&LLInspectAvatar::enableUnmute, this));
+
+ // can't make the properties request until the widgets are constructed
+ // as it might return immediately, so do it in postBuild.
+}
+
+LLInspectAvatar::~LLInspectAvatar()
+{
+ // clean up any pending requests so they don't call back into a deleted
+ // view
+ delete mPropertiesRequest;
+ mPropertiesRequest = NULL;
+}
+
+/*virtual*/
+BOOL LLInspectAvatar::postBuild(void)
+{
+ getChild<LLUICtrl>("add_friend_btn")->setCommitCallback(
+ boost::bind(&LLInspectAvatar::onClickAddFriend, this) );
+
+ getChild<LLUICtrl>("view_profile_btn")->setCommitCallback(
+ boost::bind(&LLInspectAvatar::onClickViewProfile, this) );
+
+ getChild<LLUICtrl>("mute_btn")->setCommitCallback(
+ boost::bind(&LLInspectAvatar::onClickMuteVolume, this) );
+
+ getChild<LLUICtrl>("volume_slider")->setCommitCallback(
+ boost::bind(&LLInspectAvatar::onVolumeChange, this, _2));
+
+ return TRUE;
+}
+
+
+// Multiple calls to showInstance("inspect_avatar", foo) will provide different
+// LLSD for foo, which we will catch here.
+//virtual
+void LLInspectAvatar::onOpen(const LLSD& data)
+{
+ // Start open animation
+ LLInspect::onOpen(data);
+
+ // Extract appropriate avatar id
+ mAvatarID = data["avatar_id"];
+
+ BOOL self = mAvatarID == gAgent.getID();
+
+ getChild<LLUICtrl>("gear_self_btn")->setVisible(self);
+ getChild<LLUICtrl>("gear_btn")->setVisible(!self);
+
+ // Position the inspector relative to the mouse cursor
+ // Similar to how tooltips are positioned
+ // See LLToolTipMgr::createToolTip
+ if (data.has("pos"))
+ {
+ LLUI::positionViewNearMouse(this, data["pos"]["x"].asInteger(), data["pos"]["y"].asInteger());
+ }
+ else
+ {
+ LLUI::positionViewNearMouse(this);
+ }
+
+ // can't call from constructor as widgets are not built yet
+ requestUpdate();
+
+ updateVolumeSlider();
+
+ updateModeratorPanel();
+}
+
+// virtual
+void LLInspectAvatar::onClose(bool app_quitting)
+{
+ getChild<LLMenuButton>("gear_btn")->hideMenu();
+}
+
+void LLInspectAvatar::requestUpdate()
+{
+ // Don't make network requests when spawning from the debug menu at the
+ // login screen (which is useful to work on the layout).
+ if (mAvatarID.isNull())
+ {
+ if (LLStartUp::getStartupState() >= STATE_STARTED)
+ {
+ // once we're running we don't want to show the test floater
+ // for bogus LLUUID::null links
+ closeFloater();
+ }
+ return;
+ }
+
+ // Clear out old data so it doesn't flash between old and new
+ getChild<LLUICtrl>("user_name")->setValue("");
+ getChild<LLUICtrl>("user_subtitle")->setValue("");
+ getChild<LLUICtrl>("user_details")->setValue("");
+
+ // Make a new request for properties
+ delete mPropertiesRequest;
+ mPropertiesRequest = new LLFetchAvatarData(mAvatarID, this);
+
+ // You can't re-add someone as a friend if they are already your friend
+ bool is_friend = LLAvatarTracker::instance().getBuddyInfo(mAvatarID) != NULL;
+ bool is_self = (mAvatarID == gAgentID);
+ if (is_self)
+ {
+ getChild<LLUICtrl>("add_friend_btn")->setVisible(false);
+ getChild<LLUICtrl>("im_btn")->setVisible(false);
+ }
+ else if (is_friend)
+ {
+ getChild<LLUICtrl>("add_friend_btn")->setVisible(false);
+ getChild<LLUICtrl>("im_btn")->setVisible(true);
+ }
+ else
+ {
+ getChild<LLUICtrl>("add_friend_btn")->setVisible(true);
+ getChild<LLUICtrl>("im_btn")->setVisible(false);
+ }
+
+ // Use an avatar_icon even though the image id will come down with the
+ // avatar properties because the avatar_icon code maintains a cache of icons
+ // and this may result in the image being visible sooner.
+ // *NOTE: This may generate a duplicate avatar properties request, but that
+ // will be suppressed internally in the avatar properties processor.
+
+ //remove avatar id from cache to get fresh info
+ LLAvatarIconIDCache::getInstance()->remove(mAvatarID);
+
+ childSetValue("avatar_icon", LLSD(mAvatarID) );
+
+ gCacheName->get(mAvatarID, FALSE,
+ boost::bind(&LLInspectAvatar::nameUpdatedCallback,
+ this, _1, _2, _3, _4));
+}
+
+void LLInspectAvatar::processAvatarData(LLAvatarData* data)
+{
+ LLStringUtil::format_map_t args;
+ args["[BORN_ON]"] = data->born_on;
+ args["[AGE]"] = LLDateUtil::ageFromDate(data->born_on, LLDate::now());
+ args["[SL_PROFILE]"] = data->about_text;
+ args["[RW_PROFILE"] = data->fl_about_text;
+ args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(data);
+ std::string payment_info = LLAvatarPropertiesProcessor::paymentInfo(data);
+ args["[PAYMENTINFO]"] = payment_info;
+ args["[COMMA]"] = (payment_info.empty() ? "" : ",");
+
+ std::string subtitle = getString("Subtitle", args);
+ getChild<LLUICtrl>("user_subtitle")->setValue( LLSD(subtitle) );
+ std::string details = getString("Details", args);
+ getChild<LLUICtrl>("user_details")->setValue( LLSD(details) );
+
+ // Delete the request object as it has been satisfied
+ delete mPropertiesRequest;
+ mPropertiesRequest = NULL;
+}
+
+// For the avatar inspector, we only want to unpause the fade timer
+// if neither the gear menu or self gear menu are open
+void LLInspectAvatar::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ LLMenuGL* gear_menu = getChild<LLMenuButton>("gear_btn")->getMenu();
+ LLMenuGL* gear_menu_self = getChild<LLMenuButton>("gear_self_btn")->getMenu();
+ if ( !(gear_menu && gear_menu->getVisible()) &&
+ !(gear_menu_self && gear_menu_self->getVisible()))
+ {
+ mOpenTimer.unpause();
+ }
+}
+
+void LLInspectAvatar::updateModeratorPanel()
+{
+ bool enable_moderator_panel = false;
+
+ if (LLVoiceChannel::getCurrentVoiceChannel() &&
+ mAvatarID != gAgent.getID())
+ {
+ LLUUID session_id = LLVoiceChannel::getCurrentVoiceChannel()->getSessionID();
+
+ if (session_id != LLUUID::null)
+ {
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id);
+
+ if (speaker_mgr)
+ {
+ LLPointer<LLSpeaker> self_speakerp = speaker_mgr->findSpeaker(gAgent.getID());
+ LLPointer<LLSpeaker> selected_speakerp = speaker_mgr->findSpeaker(mAvatarID);
+
+ if(speaker_mgr->isVoiceActive() && selected_speakerp &&
+ selected_speakerp->isInVoiceChannel() &&
+ ((self_speakerp && self_speakerp->mIsModerator) || gAgent.isGodlike()))
+ {
+ getChild<LLUICtrl>("enable_voice")->setVisible(selected_speakerp->mModeratorMutedVoice);
+ getChild<LLUICtrl>("disable_voice")->setVisible(!selected_speakerp->mModeratorMutedVoice);
+
+ enable_moderator_panel = true;
+ }
+ }
+ }
+ }
+
+ if (enable_moderator_panel)
+ {
+ if (!getChild<LLUICtrl>("moderator_panel")->getVisible())
+ {
+ getChild<LLUICtrl>("moderator_panel")->setVisible(true);
+ // stretch the floater so it can accommodate the moderator panel
+ reshape(getRect().getWidth(), getRect().getHeight() + getChild<LLUICtrl>("moderator_panel")->getRect().getHeight());
+ }
+ }
+ else if (getChild<LLUICtrl>("moderator_panel")->getVisible())
+ {
+ getChild<LLUICtrl>("moderator_panel")->setVisible(false);
+ // shrink the inspector floater back to original size
+ reshape(getRect().getWidth(), getRect().getHeight() - getChild<LLUICtrl>("moderator_panel")->getRect().getHeight());
+ }
+}
+
+void LLInspectAvatar::toggleSelectedVoice(bool enabled)
+{
+ LLUUID session_id = LLVoiceChannel::getCurrentVoiceChannel()->getSessionID();
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id);
+
+ if (speaker_mgr)
+ {
+ if (!gAgent.getRegion())
+ return;
+
+ std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest");
+ LLSD data;
+ data["method"] = "mute update";
+ data["session-id"] = session_id;
+ data["params"] = LLSD::emptyMap();
+ data["params"]["agent_id"] = mAvatarID;
+ data["params"]["mute_info"] = LLSD::emptyMap();
+ // ctrl value represents ability to type, so invert
+ data["params"]["mute_info"]["voice"] = !enabled;
+
+ class MuteVoiceResponder : public LLHTTPClient::Responder
+ {
+ public:
+ MuteVoiceResponder(const LLUUID& session_id)
+ {
+ mSessionID = session_id;
+ }
+
+ virtual void error(U32 status, const std::string& reason)
+ {
+ llwarns << status << ": " << reason << llendl;
+
+ if ( gIMMgr )
+ {
+ //403 == you're not a mod
+ //should be disabled if you're not a moderator
+ if ( 403 == status )
+ {
+ gIMMgr->showSessionEventError(
+ "mute",
+ "not_a_moderator",
+ mSessionID);
+ }
+ else
+ {
+ gIMMgr->showSessionEventError(
+ "mute",
+ "generic",
+ mSessionID);
+ }
+ }
+ }
+
+ private:
+ LLUUID mSessionID;
+ };
+
+ LLHTTPClient::post(
+ url,
+ data,
+ new MuteVoiceResponder(speaker_mgr->getSessionID()));
+ }
+
+ closeFloater();
+
+}
+
+void LLInspectAvatar::updateVolumeSlider()
+{
+
+ bool voice_enabled = gVoiceClient->getVoiceEnabled(mAvatarID);
+
+ // Do not display volume slider and mute button if it
+ // is ourself or we are not in a voice channel together
+ if (!voice_enabled || (mAvatarID == gAgent.getID()))
+ {
+ getChild<LLUICtrl>("mute_btn")->setVisible(false);
+ getChild<LLUICtrl>("volume_slider")->setVisible(false);
+ }
+
+ else
+ {
+ getChild<LLUICtrl>("mute_btn")->setVisible(true);
+ getChild<LLUICtrl>("volume_slider")->setVisible(true);
+
+ // By convention, we only display and toggle voice mutes, not all mutes
+ bool is_muted = LLMuteList::getInstance()->
+ isMuted(mAvatarID, LLMute::flagVoiceChat);
+
+ LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn");
+
+ bool is_linden = LLStringUtil::endsWith(mAvatarName, " Linden");
+
+ mute_btn->setEnabled( !is_linden);
+ mute_btn->setValue( is_muted );
+
+ LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider");
+ volume_slider->setEnabled( !is_muted );
+
+ const F32 DEFAULT_VOLUME = 0.5f;
+ F32 volume;
+ if (is_muted)
+ {
+ // it's clearer to display their volume as zero
+ volume = 0.f;
+ }
+ else
+ {
+ // actual volume
+ volume = gVoiceClient->getUserVolume(mAvatarID);
+
+ // *HACK: Voice client doesn't have any data until user actually
+ // says something.
+ if (volume == 0.f)
+ {
+ volume = DEFAULT_VOLUME;
+ }
+ }
+ volume_slider->setValue( (F64)volume );
+ }
+
+}
+
+void LLInspectAvatar::onClickMuteVolume()
+{
+ // By convention, we only display and toggle voice mutes, not all mutes
+ LLMuteList* mute_list = LLMuteList::getInstance();
+ bool is_muted = mute_list->isMuted(mAvatarID, LLMute::flagVoiceChat);
+
+ LLMute mute(mAvatarID, mAvatarName, LLMute::AGENT);
+ if (!is_muted)
+ {
+ mute_list->add(mute, LLMute::flagVoiceChat);
+ }
+ else
+ {
+ mute_list->remove(mute, LLMute::flagVoiceChat);
+ }
+
+ updateVolumeSlider();
+}
+
+void LLInspectAvatar::onVolumeChange(const LLSD& data)
+{
+ F32 volume = (F32)data.asReal();
+ gVoiceClient->setUserVolume(mAvatarID, volume);
+}
+
+void LLInspectAvatar::nameUpdatedCallback(
+ const LLUUID& id,
+ const std::string& first,
+ const std::string& last,
+ BOOL is_group)
+{
+ if (id == mAvatarID)
+ {
+ mAvatarName = first + " " + last;
+ childSetValue("user_name", LLSD(mAvatarName) );
+ }
+}
+
+void LLInspectAvatar::onClickAddFriend()
+{
+ LLAvatarActions::requestFriendshipDialog(mAvatarID, mAvatarName);
+ closeFloater();
+}
+
+void LLInspectAvatar::onClickViewProfile()
+{
+ LLAvatarActions::showProfile(mAvatarID);
+ closeFloater();
+}
+
+bool LLInspectAvatar::isNotFriend()
+{
+ return !LLAvatarActions::isFriend(mAvatarID);
+}
+
+bool LLInspectAvatar::onVisibleFindOnMap()
+{
+ return gAgent.isGodlike() || is_agent_mappable(mAvatarID);
+}
+
+bool LLInspectAvatar::onVisibleFreezeEject()
+{
+ return enable_freeze_eject( LLSD(mAvatarID) );
+}
+
+bool LLInspectAvatar::onVisibleZoomIn()
+{
+ return gObjectList.findObject(mAvatarID);
+}
+
+void LLInspectAvatar::onClickIM()
+{
+ LLAvatarActions::startIM(mAvatarID);
+ closeFloater();
+}
+
+void LLInspectAvatar::onClickCall()
+{
+ LLAvatarActions::startCall(mAvatarID);
+ closeFloater();
+}
+
+void LLInspectAvatar::onClickTeleport()
+{
+ LLAvatarActions::offerTeleport(mAvatarID);
+ closeFloater();
+}
+
+void LLInspectAvatar::onClickInviteToGroup()
+{
+ LLAvatarActions::inviteToGroup(mAvatarID);
+ closeFloater();
+}
+
+void LLInspectAvatar::onClickPay()
+{
+ LLAvatarActions::pay(mAvatarID);
+ closeFloater();
+}
+
+void LLInspectAvatar::onToggleMute()
+{
+ LLMute mute(mAvatarID, mAvatarName, LLMute::AGENT);
+
+ if (LLMuteList::getInstance()->isMuted(mute.mID, mute.mName))
+ {
+ LLMuteList::getInstance()->remove(mute);
+ }
+ else
+ {
+ LLMuteList::getInstance()->add(mute);
+ }
+
+ LLPanelBlockedList::showPanelAndSelect(mute.mID);
+ closeFloater();
+}
+
+void LLInspectAvatar::onClickReport()
+{
+ LLFloaterReporter::showFromAvatar(mAvatarID, mAvatarName);
+ closeFloater();
+}
+
+void LLInspectAvatar::onClickFreeze()
+{
+ handle_avatar_freeze( LLSD(mAvatarID) );
+ closeFloater();
+}
+
+void LLInspectAvatar::onClickEject()
+{
+ handle_avatar_eject( LLSD(mAvatarID) );
+ closeFloater();
+}
+
+void LLInspectAvatar::onClickZoomIn()
+{
+ handle_zoom_to_object(mAvatarID);
+ closeFloater();
+}
+
+void LLInspectAvatar::onClickFindOnMap()
+{
+ gFloaterWorldMap->trackAvatar(mAvatarID, mAvatarName);
+ LLFloaterReg::showInstance("world_map");
+}
+
+
+bool LLInspectAvatar::enableMute()
+{
+ bool is_linden = LLStringUtil::endsWith(mAvatarName, " Linden");
+ bool is_self = mAvatarID == gAgent.getID();
+
+ if (!is_linden && !is_self && !LLMuteList::getInstance()->isMuted(mAvatarID, mAvatarName))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool LLInspectAvatar::enableUnmute()
+{
+ bool is_linden = LLStringUtil::endsWith(mAvatarName, " Linden");
+ bool is_self = mAvatarID == gAgent.getID();
+
+ if (!is_linden && !is_self && LLMuteList::getInstance()->isMuted(mAvatarID, mAvatarName))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// LLInspectAvatarUtil
+//////////////////////////////////////////////////////////////////////////////
+void LLInspectAvatarUtil::registerFloater()
+{
+ LLFloaterReg::add("inspect_avatar", "inspect_avatar.xml",
+ &LLFloaterReg::build<LLInspectAvatar>);
+}
diff --git a/indra/newview/llinspectavatar.h b/indra/newview/llinspectavatar.h
new file mode 100644
index 0000000000..179ad1ffe1
--- /dev/null
+++ b/indra/newview/llinspectavatar.h
@@ -0,0 +1,41 @@
+/**
+ * @file llinspectavatar.h
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLINSPECTAVATAR_H
+#define LLINSPECTAVATAR_H
+
+namespace LLInspectAvatarUtil
+{
+ // Register with LLFloaterReg
+ void registerFloater();
+}
+
+#endif
diff --git a/indra/newview/llinspectgroup.cpp b/indra/newview/llinspectgroup.cpp
new file mode 100644
index 0000000000..7fd7b69021
--- /dev/null
+++ b/indra/newview/llinspectgroup.cpp
@@ -0,0 +1,331 @@
+/**
+ * @file llinspectgroup.cpp
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llinspectgroup.h"
+
+// viewer files
+#include "llgroupactions.h"
+#include "llgroupmgr.h"
+#include "llinspect.h"
+#include "llstartup.h"
+
+// Linden libraries
+#include "llcontrol.h" // LLCachedControl
+#include "llfloater.h"
+#include "llfloaterreg.h"
+#include "llresmgr.h" // getMonetaryString()
+#include "lltooltip.h" // positionViewNearMouse()
+#include "lltrans.h"
+#include "lluictrl.h"
+
+class LLFetchGroupData;
+
+
+//////////////////////////////////////////////////////////////////////////////
+// LLInspectGroup
+//////////////////////////////////////////////////////////////////////////////
+
+/// Group Inspector, a small information window used when clicking
+/// on group names in the 2D UI
+class LLInspectGroup : public LLInspect
+{
+ friend class LLFloaterReg;
+
+public:
+ // key["group_id"] - Group ID for which to show information
+ // Inspector will be positioned relative to current mouse position
+ LLInspectGroup(const LLSD& key);
+ virtual ~LLInspectGroup();
+
+ // Because floater is single instance, need to re-parse data on each spawn
+ // (for example, inspector about same group but in different position)
+ /*virtual*/ void onOpen(const LLSD& group_id);
+
+ // When closing they should close their gear menu
+ /*virtual*/ void onClose(bool app_quitting);
+
+ // Update view based on information from group manager
+ void processGroupData();
+
+ // Make network requests for all the data to display in this view.
+ // Used on construction and if avatar id changes.
+ void requestUpdate();
+
+ // Callback for gCacheName to look up group name
+ // Faster than waiting for group properties to return
+ void nameUpdatedCallback(const LLUUID& id,
+ const std::string& first,
+ const std::string& last,
+ BOOL is_group);
+
+ // Button/menu callbacks
+ void onClickViewProfile();
+ void onClickJoin();
+ void onClickLeave();
+
+private:
+ LLUUID mGroupID;
+ // an in-flight network request for group properties
+ // is represented by this object
+ LLFetchGroupData* mPropertiesRequest;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+// LLFetchGroupData
+//////////////////////////////////////////////////////////////////////////////
+
+// This object represents a pending request for avatar properties information
+class LLFetchGroupData : public LLGroupMgrObserver
+{
+public:
+ // If the inspector closes it will delete the pending request object, so the
+ // inspector pointer will be valid for the lifetime of this object
+ LLFetchGroupData(const LLUUID& group_id, LLInspectGroup* inspector)
+ : LLGroupMgrObserver(group_id),
+ mInspector(inspector)
+ {
+ LLGroupMgr* mgr = LLGroupMgr::getInstance();
+ // register ourselves as an observer
+ mgr->addObserver(this);
+ // send a request
+ mgr->sendGroupPropertiesRequest(group_id);
+ }
+
+ ~LLFetchGroupData()
+ {
+ // remove ourselves as an observer
+ LLGroupMgr::getInstance()->removeObserver(this);
+ }
+
+ void changed(LLGroupChange gc)
+ {
+ if (gc == GC_PROPERTIES)
+ {
+ mInspector->processGroupData();
+ }
+ }
+
+ LLInspectGroup* mInspector;
+};
+
+LLInspectGroup::LLInspectGroup(const LLSD& sd)
+: LLInspect( LLSD() ), // single_instance, doesn't really need key
+ mGroupID(), // set in onOpen()
+ mPropertiesRequest(NULL)
+{
+ mCommitCallbackRegistrar.add("InspectGroup.ViewProfile",
+ boost::bind(&LLInspectGroup::onClickViewProfile, this));
+ mCommitCallbackRegistrar.add("InspectGroup.Join",
+ boost::bind(&LLInspectGroup::onClickJoin, this));
+ mCommitCallbackRegistrar.add("InspectGroup.Leave",
+ boost::bind(&LLInspectGroup::onClickLeave, this));
+
+ // can't make the properties request until the widgets are constructed
+ // as it might return immediately, so do it in postBuild.
+}
+
+LLInspectGroup::~LLInspectGroup()
+{
+ // clean up any pending requests so they don't call back into a deleted
+ // view
+ delete mPropertiesRequest;
+ mPropertiesRequest = NULL;
+}
+
+
+// Multiple calls to showInstance("inspect_avatar", foo) will provide different
+// LLSD for foo, which we will catch here.
+//virtual
+void LLInspectGroup::onOpen(const LLSD& data)
+{
+ // start fade animation
+ LLInspect::onOpen(data);
+
+ mGroupID = 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::positionViewNearMouse(this, data["pos"]["x"].asInteger(), data["pos"]["y"].asInteger());
+ }
+ else
+ {
+ LLUI::positionViewNearMouse(this);
+ }
+
+ // can't call from constructor as widgets are not built yet
+ requestUpdate();
+}
+
+// virtual
+void LLInspectGroup::onClose(bool app_quitting)
+{
+ // *TODO: If we add a gear menu, close it here
+}
+
+void LLInspectGroup::requestUpdate()
+{
+ // Don't make network requests when spawning from the debug menu at the
+ // login screen (which is useful to work on the layout).
+ if (mGroupID.isNull())
+ {
+ if (LLStartUp::getStartupState() >= STATE_STARTED)
+ {
+ // once we're running we don't want to show the test floater
+ // for bogus LLUUID::null links
+ closeFloater();
+ }
+ return;
+ }
+
+ // Clear out old data so it doesn't flash between old and new
+ getChild<LLUICtrl>("group_name")->setValue("");
+ getChild<LLUICtrl>("group_subtitle")->setValue("");
+ getChild<LLUICtrl>("group_details")->setValue("");
+ getChild<LLUICtrl>("group_cost")->setValue("");
+ // Must have a visible button so the inspector can take focus
+ getChild<LLUICtrl>("view_profile_btn")->setVisible(true);
+ getChild<LLUICtrl>("leave_btn")->setVisible(false);
+ getChild<LLUICtrl>("join_btn")->setVisible(false);
+
+ // Make a new request for properties
+ delete mPropertiesRequest;
+ mPropertiesRequest = new LLFetchGroupData(mGroupID, this);
+
+ // Name lookup will be faster out of cache, use that
+ gCacheName->get(mGroupID, TRUE,
+ boost::bind(&LLInspectGroup::nameUpdatedCallback,
+ this, _1, _2, _3, _4));
+}
+
+void LLInspectGroup::nameUpdatedCallback(
+ const LLUUID& id,
+ const std::string& first,
+ const std::string& last,
+ BOOL is_group)
+{
+ if (id == mGroupID)
+ {
+ // group names are returned as a first name
+ childSetValue("group_name", LLSD(first) );
+ }
+
+ // Otherwise possibly a request for an older inspector, ignore it
+}
+
+void LLInspectGroup::processGroupData()
+{
+ LLGroupMgrGroupData* data =
+ LLGroupMgr::getInstance()->getGroupData(mGroupID);
+
+ if (data)
+ {
+ // Noun pluralization depends on language
+ std::string lang = LLUI::getLanguage();
+ std::string members =
+ LLTrans::getCountString(lang, "GroupMembers", data->mMemberCount);
+ getChild<LLUICtrl>("group_subtitle")->setValue( LLSD(members) );
+
+ getChild<LLUICtrl>("group_details")->setValue( LLSD(data->mCharter) );
+
+ getChild<LLUICtrl>("group_icon")->setValue( LLSD(data->mInsigniaID) );
+
+ std::string cost;
+ bool is_member = LLGroupActions::isInGroup(mGroupID);
+ if (is_member)
+ {
+ cost = getString("YouAreMember");
+ }
+ else if (data->mOpenEnrollment)
+ {
+ if (data->mMembershipFee == 0)
+ {
+ cost = getString("FreeToJoin");
+ }
+ else
+ {
+ std::string amount =
+ LLResMgr::getInstance()->getMonetaryString(
+ data->mMembershipFee);
+ LLStringUtil::format_map_t args;
+ args["[AMOUNT]"] = amount;
+ cost = getString("CostToJoin", args);
+ }
+ }
+ else
+ {
+ cost = getString("PrivateGroup");
+ }
+ getChild<LLUICtrl>("group_cost")->setValue(cost);
+
+ getChild<LLUICtrl>("join_btn")->setVisible(!is_member);
+ getChild<LLUICtrl>("leave_btn")->setVisible(is_member);
+
+ // Only enable join button if you are allowed to join
+ bool can_join = !is_member && data->mOpenEnrollment;
+ getChild<LLUICtrl>("join_btn")->setEnabled(can_join);
+ }
+
+ // Delete the request object as it has been satisfied
+ delete mPropertiesRequest;
+ mPropertiesRequest = NULL;
+}
+
+void LLInspectGroup::onClickViewProfile()
+{
+ closeFloater();
+ LLGroupActions::show(mGroupID);
+}
+
+void LLInspectGroup::onClickJoin()
+{
+ closeFloater();
+ LLGroupActions::join(mGroupID);
+}
+
+void LLInspectGroup::onClickLeave()
+{
+ closeFloater();
+ LLGroupActions::leave(mGroupID);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// LLInspectGroupUtil
+//////////////////////////////////////////////////////////////////////////////
+void LLInspectGroupUtil::registerFloater()
+{
+ LLFloaterReg::add("inspect_group", "inspect_group.xml",
+ &LLFloaterReg::build<LLInspectGroup>);
+}
diff --git a/indra/newview/llinspectgroup.h b/indra/newview/llinspectgroup.h
new file mode 100644
index 0000000000..dfd5cbcd55
--- /dev/null
+++ b/indra/newview/llinspectgroup.h
@@ -0,0 +1,41 @@
+/**
+ * @file llinspectgroup.h
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLINSPECTGROUP_H
+#define LLINSPECTGROUP_H
+
+namespace LLInspectGroupUtil
+{
+ // Register with LLFloaterReg
+ void registerFloater();
+}
+
+#endif
diff --git a/indra/newview/llinspectobject.cpp b/indra/newview/llinspectobject.cpp
new file mode 100644
index 0000000000..dd313c528d
--- /dev/null
+++ b/indra/newview/llinspectobject.cpp
@@ -0,0 +1,658 @@
+/**
+ * @file llinspectobject.cpp
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llinspectobject.h"
+
+// Viewer
+#include "llinspect.h"
+#include "llmediaentry.h"
+#include "llnotificationsutil.h" // *TODO: Eliminate, add LLNotificationsUtil wrapper
+#include "llselectmgr.h"
+#include "llslurl.h"
+#include "llviewermenu.h" // handle_object_touch(), handle_buy()
+#include "llviewermedia.h"
+#include "llviewermediafocus.h"
+#include "llviewerobjectlist.h" // to select the requested object
+
+// Linden libraries
+#include "llbutton.h" // setLabel(), not virtual!
+#include "llclickaction.h"
+#include "llfloaterreg.h"
+#include "llmenubutton.h"
+#include "llresmgr.h" // getMonetaryString
+#include "llsafehandle.h"
+#include "lltextbox.h" // for description truncation
+#include "lltrans.h"
+#include "llui.h" // positionViewNearMouse()
+#include "lluictrl.h"
+
+class LLViewerObject;
+
+//////////////////////////////////////////////////////////////////////////////
+// LLInspectObject
+//////////////////////////////////////////////////////////////////////////////
+
+// Object Inspector, a small information window used when clicking
+// in the ambient inspector widget for objects in the 3D world.
+class LLInspectObject : public LLInspect
+{
+ friend class LLFloaterReg;
+
+public:
+ // object_id - Root object ID for which to show information
+ // Inspector will be positioned relative to current mouse position
+ LLInspectObject(const LLSD& object_id);
+ virtual ~LLInspectObject();
+
+ /*virtual*/ BOOL postBuild(void);
+
+ // Because floater is single instance, need to re-parse data on each spawn
+ // (for example, inspector about same avatar but in different position)
+ /*virtual*/ void onOpen(const LLSD& avatar_id);
+
+ // Release the selection and do other cleanup
+ /*virtual*/ void onClose(bool app_quitting);
+
+ // override the inspector mouse leave so timer is only paused if
+ // gear menu is not open
+ /* virtual */ void onMouseLeave(S32 x, S32 y, MASK mask);
+
+private:
+ // Refresh displayed data with information from selection manager
+ void update();
+
+ void hideButtons();
+ void updateButtons(LLSelectNode* nodep);
+ void updateSitLabel(LLSelectNode* nodep);
+ void updateTouchLabel(LLSelectNode* nodep);
+
+ void updateName(LLSelectNode* nodep);
+ void updateDescription(LLSelectNode* nodep);
+ void updatePrice(LLSelectNode* nodep);
+ void updateCreator(LLSelectNode* nodep);
+
+ void updateMediaCurrentURL();
+ void updateSecureBrowsing();
+
+ void onClickBuy();
+ void onClickPay();
+ void onClickTakeFreeCopy();
+ void onClickTouch();
+ void onClickSit();
+ void onClickOpen();
+ void onClickMoreInfo();
+ void onClickZoomIn();
+
+private:
+ LLUUID mObjectID;
+ S32 mObjectFace;
+ viewer_media_t mMediaImpl;
+ LLMediaEntry* mMediaEntry;
+ LLSafeHandle<LLObjectSelection> mObjectSelection;
+};
+
+LLInspectObject::LLInspectObject(const LLSD& sd)
+: LLInspect( LLSD() ), // single_instance, doesn't really need key
+ mObjectID(NULL), // set in onOpen()
+ mObjectFace(0),
+ mObjectSelection(NULL),
+ mMediaImpl(NULL),
+ mMediaEntry(NULL)
+{
+ // can't make the properties request until the widgets are constructed
+ // as it might return immediately, so do it in postBuild.
+ mCommitCallbackRegistrar.add("InspectObject.Buy", boost::bind(&LLInspectObject::onClickBuy, this));
+ mCommitCallbackRegistrar.add("InspectObject.Pay", boost::bind(&LLInspectObject::onClickPay, this));
+ mCommitCallbackRegistrar.add("InspectObject.TakeFreeCopy", boost::bind(&LLInspectObject::onClickTakeFreeCopy, this));
+ mCommitCallbackRegistrar.add("InspectObject.Touch", boost::bind(&LLInspectObject::onClickTouch, this));
+ mCommitCallbackRegistrar.add("InspectObject.Sit", boost::bind(&LLInspectObject::onClickSit, this));
+ mCommitCallbackRegistrar.add("InspectObject.Open", boost::bind(&LLInspectObject::onClickOpen, this));
+ mCommitCallbackRegistrar.add("InspectObject.MoreInfo", boost::bind(&LLInspectObject::onClickMoreInfo, this));
+ mCommitCallbackRegistrar.add("InspectObject.ZoomIn", boost::bind(&LLInspectObject::onClickZoomIn, this));
+}
+
+
+LLInspectObject::~LLInspectObject()
+{
+}
+
+/*virtual*/
+BOOL LLInspectObject::postBuild(void)
+{
+ // The XML file has sample data in it. Clear that out so we don't
+ // flicker when data arrives off network.
+ getChild<LLUICtrl>("object_name")->setValue("");
+ getChild<LLUICtrl>("object_creator")->setValue("");
+ getChild<LLUICtrl>("object_description")->setValue("");
+ getChild<LLUICtrl>("object_media_url")->setValue("");
+ // Set buttons invisible until we know what this object can do
+ hideButtons();
+
+ // Hide floater when name links clicked
+ LLTextBox* textbox = getChild<LLTextBox>("object_creator");
+ textbox->mURLClickSignal.connect(
+ boost::bind(&LLInspectObject::closeFloater, this, false) );
+
+ // Hook up functionality
+ getChild<LLUICtrl>("buy_btn")->setCommitCallback(
+ boost::bind(&LLInspectObject::onClickBuy, this));
+ getChild<LLUICtrl>("pay_btn")->setCommitCallback(
+ boost::bind(&LLInspectObject::onClickPay, this));
+ getChild<LLUICtrl>("take_free_copy_btn")->setCommitCallback(
+ boost::bind(&LLInspectObject::onClickTakeFreeCopy, this));
+ getChild<LLUICtrl>("touch_btn")->setCommitCallback(
+ boost::bind(&LLInspectObject::onClickTouch, this));
+ getChild<LLUICtrl>("sit_btn")->setCommitCallback(
+ boost::bind(&LLInspectObject::onClickSit, this));
+ getChild<LLUICtrl>("open_btn")->setCommitCallback(
+ boost::bind(&LLInspectObject::onClickOpen, this));
+ getChild<LLUICtrl>("more_info_btn")->setCommitCallback(
+ boost::bind(&LLInspectObject::onClickMoreInfo, this));
+
+ // Watch for updates to selection properties off the network
+ LLSelectMgr::getInstance()->mUpdateSignal.connect(
+ boost::bind(&LLInspectObject::update, this) );
+
+ return TRUE;
+}
+
+// Multiple calls to showInstance("inspect_avatar", foo) will provide different
+// LLSD for foo, which we will catch here.
+//virtual
+void LLInspectObject::onOpen(const LLSD& data)
+{
+ // Start animation
+ LLInspect::onOpen(data);
+
+ // Extract appropriate avatar id
+ mObjectID = data["object_id"];
+
+ if(data.has("object_face"))
+ {
+ 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::positionViewNearMouse(this, data["pos"]["x"].asInteger(), data["pos"]["y"].asInteger());
+ }
+ else
+ {
+ LLUI::positionViewNearMouse(this);
+ }
+
+ // Promote hovered object to a complete selection, which will also force
+ // a request for selected object data off the network
+ LLViewerObject* obj = gObjectList.findObject( mObjectID );
+ if (obj)
+ {
+ // Media focus and this code fight over the select manager.
+ // Make sure any media is unfocused before changing the selection here.
+ LLViewerMediaFocus::getInstance()->clearFocus();
+
+ LLSelectMgr::instance().deselectAll();
+ mObjectSelection = LLSelectMgr::instance().selectObjectAndFamily(obj);
+
+ // Mark this as a transient selection
+ struct SetTransient : public LLSelectedNodeFunctor
+ {
+ bool apply(LLSelectNode* node)
+ {
+ node->setTransient(TRUE);
+ return true;
+ }
+ } functor;
+ mObjectSelection->applyToNodes(&functor);
+
+ // Does this face have media?
+ const LLTextureEntry* tep = obj->getTE(mObjectFace);
+ if (!tep)
+ return;
+
+ mMediaEntry = tep->hasMedia() ? tep->getMediaData() : NULL;
+ if(!mMediaEntry)
+ return;
+
+ mMediaImpl = LLViewerMedia::getMediaImplFromTextureID(mMediaEntry->getMediaID());
+ }
+}
+
+// virtual
+void LLInspectObject::onClose(bool app_quitting)
+{
+ // Release selection to deselect
+ mObjectSelection = NULL;
+
+ getChild<LLMenuButton>("gear_btn")->hideMenu();
+}
+
+
+void LLInspectObject::update()
+{
+ // Performance optimization, because we listen to updates from select mgr
+ // but we're never destroyed.
+ if (!getVisible()) return;
+
+ LLObjectSelection* selection = LLSelectMgr::getInstance()->getSelection();
+ if (!selection) return;
+
+ LLSelectNode* nodep = selection->getFirstRootNode();
+ if (!nodep) return;
+
+ updateButtons(nodep);
+ updateName(nodep);
+ updateDescription(nodep);
+ updateCreator(nodep);
+ updatePrice(nodep);
+
+ LLViewerObject* obj = nodep->getObject();
+ if(!obj)
+ return;
+
+ if ( mObjectFace < 0
+ || mObjectFace >= obj->getNumTEs() )
+ {
+ return;
+ }
+
+ // Does this face have media?
+ const LLTextureEntry* tep = obj->getTE(mObjectFace);
+ if (!tep)
+ return;
+
+ mMediaEntry = tep->hasMedia() ? tep->getMediaData() : NULL;
+ if(!mMediaEntry)
+ return;
+
+ mMediaImpl = LLViewerMedia::getMediaImplFromTextureID(mMediaEntry->getMediaID());
+
+ updateMediaCurrentURL();
+ updateSecureBrowsing();
+}
+
+void LLInspectObject::hideButtons()
+{
+ getChild<LLUICtrl>("buy_btn")->setVisible(false);
+ getChild<LLUICtrl>("pay_btn")->setVisible(false);
+ getChild<LLUICtrl>("take_free_copy_btn")->setVisible(false);
+ getChild<LLUICtrl>("touch_btn")->setVisible(false);
+ getChild<LLUICtrl>("sit_btn")->setVisible(false);
+ getChild<LLUICtrl>("open_btn")->setVisible(false);
+}
+
+// *TODO: Extract this method from lltoolpie.cpp and put somewhere shared
+extern U8 final_click_action(LLViewerObject*);
+
+// Choose the "most relevant" operation for this object, and show a button for
+// that operation as the left-most button in the inspector.
+void LLInspectObject::updateButtons(LLSelectNode* nodep)
+{
+ // We'll start with everyone hidden and show the ones we need
+ hideButtons();
+
+ LLViewerObject* object = nodep->getObject();
+ LLViewerObject *parent = (LLViewerObject*)object->getParent();
+ bool for_copy = anyone_copy_selection(nodep);
+ bool for_sale = enable_buy_object();
+ S32 price = nodep->mSaleInfo.getSalePrice();
+ U8 click_action = final_click_action(object);
+
+ if (for_copy
+ || (for_sale && price == 0))
+ {
+ // Free copies have priority over other operations
+ getChild<LLUICtrl>("take_free_copy_btn")->setVisible(true);
+ }
+ else if (for_sale)
+ {
+ getChild<LLUICtrl>("buy_btn")->setVisible(true);
+ }
+ else if ( enable_pay_object() )
+ {
+ getChild<LLUICtrl>("pay_btn")->setVisible(true);
+ }
+ else if (click_action == CLICK_ACTION_SIT)
+ {
+ // Click-action sit must come before "open" because many objects on
+ // which you can sit have scripts, and hence can be opened
+ getChild<LLUICtrl>("sit_btn")->setVisible(true);
+ updateSitLabel(nodep);
+ }
+ else if (object->flagHandleTouch()
+ || (parent && parent->flagHandleTouch()))
+ {
+ getChild<LLUICtrl>("touch_btn")->setVisible(true);
+ updateTouchLabel(nodep);
+ }
+ else if ( enable_object_open() )
+ {
+ // Open is last because anything with a script in it can be opened
+ getChild<LLUICtrl>("open_btn")->setVisible(true);
+ }
+ else
+ {
+ // By default, we can sit on anything
+ getChild<LLUICtrl>("sit_btn")->setVisible(true);
+ updateSitLabel(nodep);
+ }
+
+ // No flash
+ focusFirstItem(FALSE, FALSE);
+}
+
+void LLInspectObject::updateSitLabel(LLSelectNode* nodep)
+{
+ LLButton* sit_btn = getChild<LLButton>("sit_btn");
+ if (!nodep->mSitName.empty())
+ {
+ sit_btn->setLabel( nodep->mSitName );
+ }
+ else
+ {
+ sit_btn->setLabel( getString("Sit") );
+ }
+}
+
+void LLInspectObject::updateTouchLabel(LLSelectNode* nodep)
+{
+ LLButton* sit_btn = getChild<LLButton>("touch_btn");
+ if (!nodep->mTouchName.empty())
+ {
+ sit_btn->setLabel( nodep->mTouchName );
+ }
+ else
+ {
+ sit_btn->setLabel( getString("Touch") );
+ }
+}
+
+void LLInspectObject::updateName(LLSelectNode* nodep)
+{
+ std::string name;
+ if (!nodep->mName.empty())
+ {
+ name = nodep->mName;
+ }
+ else
+ {
+ name = LLTrans::getString("TooltipNoName");
+ }
+ getChild<LLUICtrl>("object_name")->setValue(name);
+}
+
+void LLInspectObject::updateDescription(LLSelectNode* nodep)
+{
+ const char* const DEFAULT_DESC = "(No Description)";
+ std::string desc;
+ if (!nodep->mDescription.empty()
+ && nodep->mDescription != DEFAULT_DESC)
+ {
+ desc = nodep->mDescription;
+ }
+
+ LLTextBox* textbox = getChild<LLTextBox>("object_description");
+ textbox->setValue(desc);
+}
+
+void LLInspectObject::updateMediaCurrentURL()
+{
+ if(!mMediaEntry)
+ return;
+ LLTextBox* textbox = getChild<LLTextBox>("object_media_url");
+ std::string media_url = "";
+ textbox->setValue(media_url);
+ textbox->setToolTip(media_url);
+ LLStringUtil::format_map_t args;
+
+ if(mMediaImpl.notNull() && mMediaImpl->hasMedia())
+ {
+
+ LLPluginClassMedia* media_plugin = NULL;
+ media_plugin = mMediaImpl->getMediaPlugin();
+ if(media_plugin)
+ {
+ if(media_plugin->pluginSupportsMediaTime())
+ {
+ args["[CurrentURL]"] = mMediaImpl->getMediaURL();
+ }
+ else
+ {
+ args["[CurrentURL]"] = media_plugin->getLocation();
+ }
+ media_url = LLTrans::getString("CurrentURL", args);
+
+ }
+ }
+ else if(mMediaEntry->getCurrentURL() != "")
+ {
+ args["[CurrentURL]"] = mMediaEntry->getCurrentURL();
+ media_url = LLTrans::getString("CurrentURL", args);
+ }
+
+ textbox->setText(media_url);
+ textbox->setToolTip(media_url);
+}
+
+void LLInspectObject::updateCreator(LLSelectNode* nodep)
+{
+ // final information for display
+ LLStringUtil::format_map_t args;
+ std::string text;
+
+ // Leave text blank until data loaded
+ if (nodep->mValid)
+ {
+ // Utilize automatic translation of SLURL into name to display
+ // a clickable link
+ // Objects cannot be created by a group, so use agent URL format
+ LLUUID creator_id = nodep->mPermissions->getCreator();
+ std::string creator_url =
+ LLSLURL::buildCommand("agent", creator_id, "about");
+ args["[CREATOR]"] = creator_url;
+
+ // created by one user but owned by another
+ std::string owner_url;
+ LLUUID owner_id;
+ bool group_owned = nodep->mPermissions->isGroupOwned();
+ if (group_owned)
+ {
+ owner_id = nodep->mPermissions->getGroup();
+ owner_url = LLSLURL::buildCommand("group", owner_id, "about");
+ }
+ else
+ {
+ owner_id = nodep->mPermissions->getOwner();
+ owner_url = LLSLURL::buildCommand("agent", owner_id, "about");
+ }
+ args["[OWNER]"] = owner_url;
+
+ if (creator_id == owner_id)
+ {
+ // common case, created and owned by one user
+ text = getString("Creator", args);
+ }
+ else
+ {
+ text = getString("CreatorAndOwner", args);
+ }
+ }
+ getChild<LLUICtrl>("object_creator")->setValue(text);
+}
+
+void LLInspectObject::updatePrice(LLSelectNode* nodep)
+{
+ // *TODO: Only look these up once and use for both updateButtons and here
+ bool for_copy = anyone_copy_selection(nodep);
+ bool for_sale = enable_buy_object();
+ S32 price = nodep->mSaleInfo.getSalePrice();
+
+ bool show_price_icon = false;
+ std::string line;
+ if (for_copy
+ || (for_sale && price == 0))
+ {
+ line = getString("PriceFree");
+ show_price_icon = true;
+ }
+ else if (for_sale)
+ {
+ LLStringUtil::format_map_t args;
+ args["[AMOUNT]"] = LLResMgr::getInstance()->getMonetaryString(price);
+ line = getString("Price", args);
+ show_price_icon = true;
+ }
+ getChild<LLUICtrl>("price_text")->setValue(line);
+ getChild<LLUICtrl>("price_icon")->setVisible(show_price_icon);
+}
+
+void LLInspectObject::updateSecureBrowsing()
+{
+ bool is_secure_browsing = false;
+
+ if(mMediaImpl.notNull()
+ && mMediaImpl->hasMedia())
+ {
+ LLPluginClassMedia* media_plugin = NULL;
+ std::string current_url = "";
+ media_plugin = mMediaImpl->getMediaPlugin();
+ if(media_plugin)
+ {
+ if(media_plugin->pluginSupportsMediaTime())
+ {
+ current_url = mMediaImpl->getMediaURL();
+ }
+ else
+ {
+ current_url = media_plugin->getLocation();
+ }
+ }
+
+ std::string prefix = std::string("https://");
+ std::string test_prefix = current_url.substr(0, prefix.length());
+ LLStringUtil::toLower(test_prefix);
+ if(test_prefix == prefix)
+ {
+ is_secure_browsing = true;
+ }
+ }
+ getChild<LLUICtrl>("secure_browsing")->setVisible(is_secure_browsing);
+}
+
+// For the object inspector, only unpause the fade timer
+// if the gear menu is not open
+void LLInspectObject::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ LLMenuGL* gear_menu = getChild<LLMenuButton>("gear_btn")->getMenu();
+ if ( !(gear_menu && gear_menu->getVisible()))
+ {
+ mOpenTimer.unpause();
+ }
+}
+
+void LLInspectObject::onClickBuy()
+{
+ handle_buy();
+ closeFloater();
+}
+
+void LLInspectObject::onClickPay()
+{
+ handle_give_money_dialog();
+ closeFloater();
+}
+
+void LLInspectObject::onClickTakeFreeCopy()
+{
+ LLObjectSelection* selection = LLSelectMgr::getInstance()->getSelection();
+ if (!selection) return;
+
+ LLSelectNode* nodep = selection->getFirstRootNode();
+ if (!nodep) return;
+
+ // Figure out if this is a "free buy" or a "take copy"
+ bool for_copy = anyone_copy_selection(nodep);
+ // Prefer to just take a free copy
+ if (for_copy)
+ {
+ handle_take_copy();
+ }
+ else
+ {
+ // Buy for free (confusing, but that's how it is)
+ handle_buy();
+ }
+ closeFloater();
+}
+
+void LLInspectObject::onClickTouch()
+{
+ handle_object_touch();
+ closeFloater();
+}
+
+void LLInspectObject::onClickSit()
+{
+ handle_object_sit_or_stand();
+ closeFloater();
+}
+
+void LLInspectObject::onClickOpen()
+{
+ LLFloaterReg::showInstance("openobject");
+ closeFloater();
+}
+
+void LLInspectObject::onClickMoreInfo()
+{
+ // *TODO: Show object info side panel, once that is implemented.
+ LLNotificationsUtil::add("ClickUnimplemented");
+ closeFloater();
+}
+
+void LLInspectObject::onClickZoomIn()
+{
+ handle_look_at_selection("zoom");
+ closeFloater();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// LLInspectObjectUtil
+//////////////////////////////////////////////////////////////////////////////
+void LLInspectObjectUtil::registerFloater()
+{
+ LLFloaterReg::add("inspect_object", "inspect_object.xml",
+ &LLFloaterReg::build<LLInspectObject>);
+}
+
diff --git a/indra/newview/llinspectobject.h b/indra/newview/llinspectobject.h
new file mode 100644
index 0000000000..aa45f401c0
--- /dev/null
+++ b/indra/newview/llinspectobject.h
@@ -0,0 +1,40 @@
+/**
+ * @file llinspectobject.h
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLINSPECTOBJECT_H
+#define LLINSPECTOBJECT_H
+
+namespace LLInspectObjectUtil
+{
+ void registerFloater();
+}
+
+#endif
diff --git a/indra/newview/llinspectremoteobject.cpp b/indra/newview/llinspectremoteobject.cpp
new file mode 100644
index 0000000000..e4d2eec242
--- /dev/null
+++ b/indra/newview/llinspectremoteobject.cpp
@@ -0,0 +1,200 @@
+/**
+ * @file llinspectremoteobject.cpp
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llinspectremoteobject.h"
+#include "llinspect.h"
+#include "llslurl.h"
+#include "llmutelist.h"
+#include "llurlaction.h"
+#include "llpanelblockedlist.h"
+#include "llfloaterreg.h"
+#include "llui.h"
+#include "lluictrl.h"
+
+class LLViewerObject;
+
+//////////////////////////////////////////////////////////////////////////////
+// LLInspectRemoteObject
+//////////////////////////////////////////////////////////////////////////////
+
+// Remote Object Inspector, a small information window used to
+// display information about potentially-remote objects. Used
+// to display details about objects sending messages to the user.
+class LLInspectRemoteObject : public LLInspect
+{
+ friend class LLFloaterReg;
+
+public:
+ LLInspectRemoteObject(const LLSD& object_id);
+ virtual ~LLInspectRemoteObject() {};
+
+ /*virtual*/ BOOL postBuild(void);
+ /*virtual*/ void onOpen(const LLSD& avatar_id);
+
+ void onClickMap();
+ void onClickBlock();
+ void onClickClose();
+
+private:
+ void update();
+ static void nameCallback(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* data);
+
+private:
+ LLUUID mObjectID;
+ LLUUID mOwnerID;
+ std::string mOwner;
+ std::string mSLurl;
+ std::string mName;
+ bool mGroupOwned;
+};
+
+LLInspectRemoteObject::LLInspectRemoteObject(const LLSD& sd) :
+ LLInspect(LLSD()),
+ mObjectID(NULL),
+ mOwnerID(NULL),
+ mOwner(""),
+ mSLurl(""),
+ mName(""),
+ mGroupOwned(false)
+{
+}
+
+/*virtual*/
+BOOL LLInspectRemoteObject::postBuild(void)
+{
+ // hook up the inspector's buttons
+ getChild<LLUICtrl>("map_btn")->setCommitCallback(
+ boost::bind(&LLInspectRemoteObject::onClickMap, this));
+ getChild<LLUICtrl>("block_btn")->setCommitCallback(
+ boost::bind(&LLInspectRemoteObject::onClickBlock, this));
+ getChild<LLUICtrl>("close_btn")->setCommitCallback(
+ boost::bind(&LLInspectRemoteObject::onClickClose, this));
+
+ return TRUE;
+}
+
+/*virtual*/
+void LLInspectRemoteObject::onOpen(const LLSD& data)
+{
+ // Start animation
+ LLInspect::onOpen(data);
+
+ // Extract appropriate object information from input LLSD
+ // (Eventually, it might be nice to query server for details
+ // rather than require caller to pass in the information.)
+ mObjectID = data["object_id"].asUUID();
+ mName = data["name"].asString();
+ mOwnerID = data["owner_id"].asUUID();
+ mGroupOwned = data["group_owned"].asBoolean();
+ mSLurl = data["slurl"].asString();
+
+ // work out the owner's name
+ mOwner = "";
+ if (gCacheName)
+ {
+ gCacheName->get(mOwnerID, mGroupOwned, nameCallback, this);
+ }
+
+ // update the inspector with the current object state
+ update();
+
+ // Position the inspector relative to the mouse cursor
+ LLUI::positionViewNearMouse(this);
+}
+
+void LLInspectRemoteObject::onClickMap()
+{
+ std::string url = "secondlife://" + mSLurl;
+ LLUrlAction::showLocationOnMap(url);
+ closeFloater();
+}
+
+void LLInspectRemoteObject::onClickBlock()
+{
+ LLMute::EType mute_type = mGroupOwned ? LLMute::GROUP : LLMute::AGENT;
+ LLMute mute(mOwnerID, mOwner, mute_type);
+ LLMuteList::getInstance()->add(mute);
+ LLPanelBlockedList::showPanelAndSelect(mute.mID);
+ closeFloater();
+}
+
+void LLInspectRemoteObject::onClickClose()
+{
+ closeFloater();
+}
+
+//static
+void LLInspectRemoteObject::nameCallback(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* data)
+{
+ LLInspectRemoteObject *self = (LLInspectRemoteObject*)data;
+ self->mOwner = first;
+ if (!last.empty())
+ {
+ self->mOwner += " " + last;
+ }
+ self->update();
+}
+
+void LLInspectRemoteObject::update()
+{
+ // show the object name as the inspector's title
+ getChild<LLUICtrl>("object_name")->setValue(mName);
+
+ // show the object's owner - click it to show profile
+ std::string owner = mOwner;
+ if (! mOwnerID.isNull())
+ {
+ if (mGroupOwned)
+ {
+ owner = LLSLURL::buildCommand("group", mOwnerID, "about");
+ }
+ else
+ {
+ owner = LLSLURL::buildCommand("agent", mOwnerID, "about");
+ }
+ }
+ getChild<LLUICtrl>("object_owner")->setValue(owner);
+
+ // display the object's SLurl - click it to teleport
+ std::string url = "secondlife:///app/teleport/" + mSLurl;
+ getChild<LLUICtrl>("object_slurl")->setValue(url);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// LLInspectRemoteObjectUtil
+//////////////////////////////////////////////////////////////////////////////
+void LLInspectRemoteObjectUtil::registerFloater()
+{
+ LLFloaterReg::add("inspect_remote_object", "inspect_remote_object.xml",
+ &LLFloaterReg::build<LLInspectRemoteObject>);
+}
diff --git a/indra/newview/llinspectremoteobject.h b/indra/newview/llinspectremoteobject.h
new file mode 100644
index 0000000000..e756f1caf4
--- /dev/null
+++ b/indra/newview/llinspectremoteobject.h
@@ -0,0 +1,40 @@
+/**
+ * @file llinspectremoteobject.h
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLINSPECTREMOTEOBJECT_H
+#define LLINSPECTREMOTEOBJECT_H
+
+namespace LLInspectRemoteObjectUtil
+{
+ void registerFloater();
+}
+
+#endif
diff --git a/indra/newview/llinspecttoast.cpp b/indra/newview/llinspecttoast.cpp
new file mode 100644
index 0000000000..3ca8fa2f56
--- /dev/null
+++ b/indra/newview/llinspecttoast.cpp
@@ -0,0 +1,122 @@
+/**
+ * @file llinspecttoast.cpp
+ * @brief Toast inspector implementation.
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#include "llinspecttoast.h"
+#include "llinspect.h"
+#include "llfloaterreg.h"
+#include "llscreenchannel.h"
+#include "llchannelmanager.h"
+#include "lltransientfloatermgr.h"
+
+using namespace LLNotificationsUI;
+
+/**
+ * Represents inspectable toast .
+ */
+class LLInspectToast: public LLInspect
+{
+public:
+
+ LLInspectToast(const LLSD& notification_idl);
+ virtual ~LLInspectToast();
+
+ /*virtual*/ void onOpen(const LLSD& notification_id);
+private:
+ void onToastDestroy(LLToast * toast);
+
+private:
+ LLPanel* mPanel;
+ LLScreenChannel* mScreenChannel;
+};
+
+LLInspectToast::LLInspectToast(const LLSD& notification_id) :
+ LLInspect(LLSD()), mPanel(NULL)
+{
+ LLScreenChannelBase* channel = LLChannelManager::getInstance()->findChannelByID(
+ LLUUID(gSavedSettings.getString("NotificationChannelUUID")));
+ mScreenChannel = dynamic_cast<LLScreenChannel*>(channel);
+ if(NULL == mScreenChannel)
+ {
+ llwarns << "Could not get requested screen channel." << llendl;
+ return;
+ }
+
+ LLTransientFloaterMgr::getInstance()->addControlView(this);
+}
+LLInspectToast::~LLInspectToast()
+{
+ LLTransientFloaterMgr::getInstance()->removeControlView(this);
+}
+
+void LLInspectToast::onOpen(const LLSD& notification_id)
+{
+ LLInspect::onOpen(notification_id);
+ LLToast* toast = mScreenChannel->getToastByNotificationID(notification_id);
+ if (toast == NULL)
+ {
+ llwarns << "Could not get requested toast from screen channel." << llendl;
+ return;
+ }
+ toast->setOnToastDestroyedCallback(boost::bind(&LLInspectToast::onToastDestroy, this, _1));
+
+ LLPanel * panel = toast->getPanel();
+ panel->setVisible(TRUE);
+ panel->setMouseOpaque(FALSE);
+ if(mPanel != NULL && mPanel->getParent() == this)
+ {
+ removeChild(mPanel);
+ }
+ addChild(panel);
+ panel->setFocus(TRUE);
+ mPanel = panel;
+
+
+ LLRect panel_rect;
+ panel_rect = panel->getRect();
+ reshape(panel_rect.getWidth(), panel_rect.getHeight());
+
+ LLUI::positionViewNearMouse(this);
+}
+
+void LLInspectToast::onToastDestroy(LLToast * toast)
+{
+ closeFloater(false);
+}
+
+void LLNotificationsUI::registerFloater()
+{
+ LLFloaterReg::add("inspect_toast", "inspect_toast.xml",
+ &LLFloaterReg::build<LLInspectToast>);
+}
+
diff --git a/indra/newview/llinspecttoast.h b/indra/newview/llinspecttoast.h
new file mode 100644
index 0000000000..ff547154b8
--- /dev/null
+++ b/indra/newview/llinspecttoast.h
@@ -0,0 +1,40 @@
+/**
+ * @file llinspecttoast.h
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLINSPECTTOAST_H
+#define LL_LLINSPECTTOAST_H
+
+namespace LLNotificationsUI
+{
+void registerFloater();
+}
+
+#endif
diff --git a/indra/newview/llinventoryactions.h b/indra/newview/llinventoryactions.h
new file mode 100644
index 0000000000..79247e3abb
--- /dev/null
+++ b/indra/newview/llinventoryactions.h
@@ -0,0 +1,47 @@
+/**
+ * @file llinventoryactions.h
+ * @brief inventory callback functions
+ * class definition
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLINVENTORYACTIONS_H
+#define LL_LLINVENTORYACTIONS_H
+
+#include "lluictrl.h"
+
+class LLPanelInventory;
+class LLInventoryView;
+class LLInventoryPanel;
+
+void init_object_inventory_panel_actions(LLPanelInventory *panel, LLUICtrl::CommitCallbackRegistry::Registrar& registrar);
+void init_inventory_actions(LLInventoryView *floater, LLUICtrl::CommitCallbackRegistry::Registrar& registrar);
+void init_inventory_panel_actions(LLInventoryPanel *panel, LLUICtrl::CommitCallbackRegistry::Registrar& registrar);
+
+#endif // LL_LLINVENTORYACTIONS_H
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index e4459e38bd..6c9c7d15be 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1,11 +1,11 @@
-/**
+/**
* @file llinventorybridge.cpp
* @brief Implementation of the Inventory-Folder-View-Bridge classes.
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
- *
+ *
* Copyright (c) 2001-2009, Linden Research, Inc.
- *
+ *
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
@@ -13,17 +13,17 @@
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
+ *
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
+ *
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
- *
+ *
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
@@ -31,61 +31,41 @@
*/
#include "llviewerprecompiledheaders.h"
-
-#include <utility> // for std::pair<>
-
-#include "llinventoryview.h"
#include "llinventorybridge.h"
-#include "message.h"
-
#include "llagent.h"
-#include "llcallingcard.h"
-#include "llcheckboxctrl.h" // for radio buttons
-#include "llradiogroup.h"
-#include "llspinctrl.h"
-#include "lltextbox.h"
-#include "llui.h"
-
-#include "llviewercontrol.h"
-#include "llfirstuse.h"
-#include "llfloateravatarinfo.h"
-#include "llfloaterchat.h"
+#include "llagentwearables.h"
+#include "llappearancemgr.h"
+#include "llavataractions.h"
#include "llfloatercustomize.h"
-#include "llfloaterproperties.h"
+#include "llfloateropenobject.h"
+#include "llfloaterreg.h"
#include "llfloaterworldmap.h"
-#include "llfocusmgr.h"
-#include "llfolderview.h"
+#include "llfriendcard.h"
#include "llgesturemgr.h"
-#include "lliconctrl.h"
-#include "llinventorymodel.h"
+#include "llimfloater.h"
+#include "llimview.h"
#include "llinventoryclipboard.h"
-#include "lllineeditor.h"
-#include "llmenugl.h"
+#include "llinventoryfunctions.h"
+#include "llinventorymodel.h"
+#include "llinventorypanel.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
#include "llpreviewanim.h"
#include "llpreviewgesture.h"
-#include "llpreviewlandmark.h"
-#include "llpreviewnotecard.h"
-#include "llpreviewscript.h"
-#include "llpreviewsound.h"
#include "llpreviewtexture.h"
-#include "llresmgr.h"
-#include "llscrollcontainer.h"
-#include "llimview.h"
-#include "lltooldraganddrop.h"
-#include "llviewerimagelist.h"
-#include "llviewerinventory.h"
+#include "llselectmgr.h"
+#include "llsidetray.h"
+#include "lltrans.h"
+#include "llviewerassettype.h"
+#include "llviewermessage.h"
#include "llviewerobjectlist.h"
#include "llviewerwindow.h"
-#include "llvoavatar.h"
-#include "llwearable.h"
+#include "llvoavatarself.h"
#include "llwearablelist.h"
-#include "llviewermessage.h"
-#include "llviewerregion.h"
-#include "lltabcontainer.h"
-#include "lluictrlfactory.h"
-#include "llselectmgr.h"
-#include "llfloateropenobject.h"
+#include "llpaneloutfitsinventory.h"
+
+using namespace LLOldEvents;
// Helpers
// bug in busy count inc/dec right now, logic is complex... do we really need it?
@@ -103,62 +83,61 @@ void dec_busy_count()
}
// Function declarations
-struct LLWearableHoldingPattern;
-void wear_inventory_category_on_avatar(LLInventoryCategory* category, BOOL append);
-void wear_inventory_category_on_avatar_step2( BOOL proceed, void* userdata);
-void wear_inventory_category_on_avatar_loop(LLWearable* wearable, void*);
-void wear_inventory_category_on_avatar_step3(LLWearableHoldingPattern* holder, BOOL append);
+void wear_add_inventory_item_on_avatar(LLInventoryItem* item);
void remove_inventory_category_from_avatar(LLInventoryCategory* category);
-void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata);
+void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id);
bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*);
bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response);
std::string ICON_NAME[ICON_NAME_COUNT] =
{
- "inv_item_texture.tga",
- "inv_item_sound.tga",
- "inv_item_callingcard_online.tga",
- "inv_item_callingcard_offline.tga",
- "inv_item_landmark.tga",
- "inv_item_landmark_visited.tga",
- "inv_item_script.tga",
- "inv_item_clothing.tga",
- "inv_item_object.tga",
- "inv_item_object_multi.tga",
- "inv_item_notecard.tga",
- "inv_item_skin.tga",
- "inv_item_snapshot.tga",
-
- "inv_item_shape.tga",
- "inv_item_skin.tga",
- "inv_item_hair.tga",
- "inv_item_eyes.tga",
- "inv_item_shirt.tga",
- "inv_item_pants.tga",
- "inv_item_shoes.tga",
- "inv_item_socks.tga",
- "inv_item_jacket.tga",
- "inv_item_gloves.tga",
- "inv_item_undershirt.tga",
- "inv_item_underpants.tga",
- "inv_item_skirt.tga",
-
- "inv_item_animation.tga",
- "inv_item_gesture.tga",
+ "Inv_Texture",
+ "Inv_Sound",
+ "Inv_CallingCard",
+ "Inv_CallingCard",
+ "Inv_Landmark",
+ "Inv_Landmark",
+ "Inv_Script",
+ "Inv_Clothing",
+ "Inv_Object",
+ "Inv_Object",
+ "Inv_Notecard",
+ "Inv_Skin",
+ "Inv_Snapshot",
+
+ "Inv_BodyShape",
+ "Inv_Skin",
+ "Inv_Hair",
+ "Inv_Eye",
+ "Inv_Shirt",
+ "Inv_Pants",
+ "Inv_Shoe",
+ "Inv_Socks",
+ "Inv_Jacket",
+ "Inv_Gloves",
+ "Inv_Undershirt",
+ "Inv_Underpants",
+ "Inv_Skirt",
+ "Inv_Alpha",
+ "Inv_Tattoo",
+
+ "Inv_Animation",
+ "Inv_Gesture",
+
+ "Inv_LinkItem",
+ "Inv_LinkFolder"
};
-struct LLWearInfo
-{
- LLUUID mCategoryID;
- BOOL mAppend;
-};
-
-BOOL gAddToOutfit = FALSE;
-
// +=================================================+
// | LLInvFVBridge |
// +=================================================+
+LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid) :
+mUUID(uuid), mInvType(LLInventoryType::IT_NONE)
+{
+ mInventoryPanel = inventory->getHandle();
+}
+
const std::string& LLInvFVBridge::getName() const
{
LLInventoryObject* obj = getInventoryObject();
@@ -181,41 +160,83 @@ PermissionMask LLInvFVBridge::getPermissionMask() const
return PERM_ALL;
}
+// virtual
+LLFolderType::EType LLInvFVBridge::getPreferredType() const
+{
+ return LLFolderType::FT_NONE;
+}
+
+
// Folders don't have creation dates.
time_t LLInvFVBridge::getCreationDate() const
{
return 0;
}
-// Can be destoryed (or moved to trash)
+// Can be destroyed (or moved to trash)
BOOL LLInvFVBridge::isItemRemovable()
{
- LLInventoryModel* model = mInventoryPanel->getModel();
- if(!model) return FALSE;
- if(model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID()))
+ const LLInventoryModel* model = getInventoryModel();
+ if(!model)
+ {
+ return FALSE;
+ }
+ if(!model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()))
+ {
+ return FALSE;
+ }
+ if (LLAppearanceManager::instance().getIsProtectedCOFItem(mUUID))
+ {
+ return FALSE;
+ }
+
+ const LLInventoryObject *obj = model->getItem(mUUID);
+ if (obj && obj->getIsLinkType())
{
return TRUE;
}
- return FALSE;
+ if (get_is_item_worn(mUUID))
+ {
+ return FALSE;
+ }
+ return TRUE;
}
// Can be moved to another folder
-BOOL LLInvFVBridge::isItemMovable()
+BOOL LLInvFVBridge::isItemMovable() const
{
return TRUE;
}
+/*virtual*/
+/**
+ * @brief Adds this item into clipboard storage
+ */
+void LLInvFVBridge::cutToClipboard()
+{
+ if(isItemMovable())
+ {
+ LLInventoryClipboard::instance().cut(mUUID);
+ }
+}
// *TODO: make sure this does the right thing
void LLInvFVBridge::showProperties()
{
- LLShowProps::showProperties(mUUID);
+ LLSD key;
+ key["id"] = mUUID;
+ LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
+
+ // Disable old properties floater; this is replaced by the sidepanel.
+ /*
+ LLFloaterReg::showInstance("properties", mUUID);
+ */
}
void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch)
{
// Deactivate gestures when moving them into Trash
LLInvFVBridge* bridge;
- LLInventoryModel* model = mInventoryPanel->getModel();
+ LLInventoryModel* model = getInventoryModel();
LLViewerInventoryItem* item = NULL;
LLViewerInventoryCategory* cat = NULL;
LLInventoryModel::cat_array_t descendent_categories;
@@ -223,7 +244,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc
S32 count = batch.count();
S32 i,j;
for(i = 0; i < count; ++i)
- {
+ {
bridge = (LLInvFVBridge*)(batch.get(i));
if(!bridge || !bridge->isItemRemovable()) continue;
item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());
@@ -231,12 +252,12 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc
{
if(LLAssetType::AT_GESTURE == item->getType())
{
- gGestureManager.deactivateGesture(item->getUUID());
+ LLGestureManager::instance().deactivateGesture(item->getUUID());
}
}
}
for(i = 0; i < count; ++i)
- {
+ {
bridge = (LLInvFVBridge*)(batch.get(i));
if(!bridge || !bridge->isItemRemovable()) continue;
cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
@@ -247,7 +268,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc
{
if(LLAssetType::AT_GESTURE == descendent_items[j]->getType())
{
- gGestureManager.deactivateGesture(descendent_items[j]->getUUID());
+ LLGestureManager::instance().deactivateGesture(descendent_items[j]->getUUID());
}
}
}
@@ -263,10 +284,10 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*
// we call LLInventoryModel::moveObject() to move everything
// around.
LLInvFVBridge* bridge;
- LLInventoryModel* model = mInventoryPanel->getModel();
+ LLInventoryModel* model = getInventoryModel();
if(!model) return;
LLMessageSystem* msg = gMessageSystem;
- LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
LLViewerInventoryItem* item = NULL;
LLViewerInventoryCategory* cat = NULL;
std::vector<LLUUID> move_ids;
@@ -367,20 +388,81 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*
BOOL LLInvFVBridge::isClipboardPasteable() const
{
- LLInventoryModel* model = mInventoryPanel->getModel();
- if(!model) return FALSE;
- BOOL is_agent_inventory = model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID());
+ if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
+ {
+ return FALSE;
+ }
+ LLInventoryModel* model = getInventoryModel();
+ if (!model)
+ {
+ return FALSE;
+ }
+
+ const LLUUID &agent_id = gAgent.getID();
- if(LLInventoryClipboard::instance().hasContents() && is_agent_inventory)
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ for(S32 i = 0; i < count; i++)
{
- return TRUE;
+ const LLUUID &item_id = objects.get(i);
+
+ // Can't paste folders
+ const LLInventoryCategory *cat = model->getCategory(item_id);
+ if (cat)
+ {
+ return FALSE;
+ }
+
+ const LLInventoryItem *item = model->getItem(item_id);
+ if (item)
+ {
+ if (!item->getPermissions().allowCopyBy(agent_id))
+ {
+ return FALSE;
+ }
+ }
}
- return FALSE;
+ return TRUE;
}
-void hideContextEntries(LLMenuGL& menu,
- const std::vector<std::string> &entries_to_show,
- const std::vector<std::string> &disabled_entries)
+BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
+{
+ if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
+ {
+ return FALSE;
+ }
+ const LLInventoryModel* model = getInventoryModel();
+ if (!model)
+ {
+ return FALSE;
+ }
+
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ for(S32 i = 0; i < count; i++)
+ {
+ const LLInventoryItem *item = model->getItem(objects.get(i));
+ if (item)
+ {
+ if (!LLAssetType::lookupCanLink(item->getActualType()))
+ {
+ return FALSE;
+ }
+ }
+ const LLViewerInventoryCategory *cat = model->getCategory(objects.get(i));
+ if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+void hide_context_entries(LLMenuGL& menu,
+ const std::vector<std::string> &entries_to_show,
+ const std::vector<std::string> &disabled_entries)
{
const LLView::child_list_t *list = menu.getChildList();
@@ -393,10 +475,10 @@ void hideContextEntries(LLMenuGL& menu,
LLMenuItemBranchGL* branchp = dynamic_cast<LLMenuItemBranchGL*>(*itor);
if ((name == "More") && branchp)
{
- hideContextEntries(*branchp->getBranch(), entries_to_show, disabled_entries);
+ hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries);
}
-
-
+
+
bool found = false;
std::vector<std::string>::const_iterator itor2;
for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2)
@@ -412,6 +494,7 @@ void hideContextEntries(LLMenuGL& menu,
}
else
{
+ (*itor)->setVisible(TRUE);
for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2)
{
if (*itor2 == name)
@@ -424,32 +507,62 @@ void hideContextEntries(LLMenuGL& menu,
}
// Helper for commonly-used entries
-void LLInvFVBridge::getClipboardEntries(bool show_asset_id, std::vector<std::string> &items,
- std::vector<std::string> &disabled_items, U32 flags)
+void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
+ std::vector<std::string> &items,
+ std::vector<std::string> &disabled_items, U32 flags)
{
- // *TODO: Translate
- items.push_back(std::string("Rename"));
- if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0)
- {
- disabled_items.push_back(std::string("Rename"));
- }
+ const LLInventoryObject *obj = getInventoryObject();
- if (show_asset_id)
+ bool is_sidepanel = isInOutfitsSidePanel();
+ if (is_sidepanel)
{
- items.push_back(std::string("Copy Asset UUID"));
- if ( (! ( isItemPermissive() || gAgent.isGodlike() ) )
- || (flags & FIRST_SELECTED_ITEM) == 0)
+ // Sidepanel includes restricted menu.
+ if (obj && obj->getIsLinkType() && !get_is_item_worn(mUUID))
{
- disabled_items.push_back(std::string("Copy Asset UUID"));
+ items.push_back(std::string("Remove Link"));
}
+ return;
}
- items.push_back(std::string("Copy Separator"));
-
- items.push_back(std::string("Copy"));
- if (!isItemCopyable())
+ if (obj)
{
- disabled_items.push_back(std::string("Copy"));
+ if (obj->getIsLinkType())
+ {
+ items.push_back(std::string("Find Original"));
+ if (isLinkedObjectMissing())
+ {
+ disabled_items.push_back(std::string("Find Original"));
+ }
+ }
+ else
+ {
+ if (LLAssetType::lookupCanLink(obj->getType()))
+ {
+ items.push_back(std::string("Find Links"));
+ }
+ items.push_back(std::string("Rename"));
+ if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Rename"));
+ }
+
+ if (show_asset_id)
+ {
+ items.push_back(std::string("Copy Asset UUID"));
+ if ( (! ( isItemPermissive() || gAgent.isGodlike() ) )
+ || (flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Copy Asset UUID"));
+ }
+ }
+ items.push_back(std::string("Copy Separator"));
+
+ items.push_back(std::string("Copy"));
+ if (!isItemCopyable())
+ {
+ disabled_items.push_back(std::string("Copy"));
+ }
+ }
}
items.push_back(std::string("Paste"));
@@ -458,29 +571,48 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, std::vector<std::str
disabled_items.push_back(std::string("Paste"));
}
+ if (gAgent.isGodlike())
+ {
+ items.push_back(std::string("Paste As Link"));
+ if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Paste As Link"));
+ }
+ }
+
items.push_back(std::string("Paste Separator"));
+ if (obj && obj->getIsLinkType() && !get_is_item_worn(mUUID))
+ {
+ items.push_back(std::string("Remove Link"));
+ }
+
items.push_back(std::string("Delete"));
if (!isItemRemovable())
{
disabled_items.push_back(std::string("Delete"));
}
+
+ // If multiple items are selected, disable properties (if it exists).
+ if ((flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Properties"));
+ }
}
void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- // *TODO: Translate
lldebugs << "LLInvFVBridge::buildContextMenu()" << llendl;
std::vector<std::string> items;
std::vector<std::string> disabled_items;
if(isInTrash())
{
- items.push_back(std::string("Purge Item"));
+ items.push_back(std::string("PurgeItem"));
if (!isItemRemovable())
{
- disabled_items.push_back(std::string("Purge Item"));
+ disabled_items.push_back(std::string("PurgeItem"));
}
- items.push_back(std::string("Restore Item"));
+ items.push_back(std::string("RestoreItem"));
}
else
{
@@ -489,7 +621,7 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
getClipboardEntries(true, items, disabled_items, flags);
}
- hideContextEntries(menu, items, disabled_items);
+ hide_context_entries(menu, items, disabled_items);
}
// *TODO: remove this
@@ -501,12 +633,12 @@ BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
if(obj)
{
- *type = LLAssetType::lookupDragAndDropType(obj->getType());
+ *type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType());
if(*type == DAD_NONE)
{
return FALSE;
}
-
+
*id = obj->getUUID();
//object_ids.put(obj->getUUID());
@@ -524,7 +656,7 @@ BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
LLInventoryObject* LLInvFVBridge::getInventoryObject() const
{
LLInventoryObject* obj = NULL;
- LLInventoryModel* model = mInventoryPanel->getModel();
+ LLInventoryModel* model = getInventoryModel();
if(model)
{
obj = (LLInventoryObject*)model->getObject(mUUID);
@@ -532,20 +664,60 @@ LLInventoryObject* LLInvFVBridge::getInventoryObject() const
return obj;
}
+LLInventoryModel* LLInvFVBridge::getInventoryModel() const
+{
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ return panel ? panel->getModel() : NULL;
+}
+
BOOL LLInvFVBridge::isInTrash() const
{
- LLInventoryModel* model = mInventoryPanel->getModel();
+ LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
- LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
return model->isObjectDescendentOf(mUUID, trash_id);
}
+BOOL LLInvFVBridge::isLinkedObjectInTrash() const
+{
+ if (isInTrash()) return TRUE;
+
+ const LLInventoryObject *obj = getInventoryObject();
+ if (obj && obj->getIsLinkType())
+ {
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ return model->isObjectDescendentOf(obj->getLinkedUUID(), trash_id);
+ }
+ return FALSE;
+}
+
+BOOL LLInvFVBridge::isLinkedObjectMissing() const
+{
+ const LLInventoryObject *obj = getInventoryObject();
+ if (!obj)
+ {
+ return TRUE;
+ }
+ if (obj->getIsLinkType() && LLAssetType::lookupIsLinkType(obj->getType()))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
BOOL LLInvFVBridge::isAgentInventory() const
{
- LLInventoryModel* model = mInventoryPanel->getModel();
+ const LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
- if(gAgent.getInventoryRootID() == mUUID) return TRUE;
- return model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID());
+ if(gInventory.getRootFolderID() == mUUID) return TRUE;
+ return model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID());
+}
+
+BOOL LLInvFVBridge::isCOFFolder() const
+{
+ return LLAppearanceManager::instance().getIsInCOF(mUUID);
}
BOOL LLInvFVBridge::isItemPermissive() const
@@ -556,20 +728,20 @@ BOOL LLInvFVBridge::isItemPermissive() const
// static
void LLInvFVBridge::changeItemParent(LLInventoryModel* model,
LLViewerInventoryItem* item,
- const LLUUID& new_parent,
+ const LLUUID& new_parent_id,
BOOL restamp)
{
- if(item->getParentUUID() != new_parent)
+ if(item->getParentUUID() != new_parent_id)
{
LLInventoryModel::update_list_t update;
LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
update.push_back(old_folder);
- LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1);
+ LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
update.push_back(new_folder);
gInventory.accountForUpdate(update);
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
- new_item->setParent(new_parent);
+ new_item->setParent(new_parent_id);
new_item->updateParentOnServer(restamp);
model->updateItem(new_item);
model->notifyObservers();
@@ -579,145 +751,156 @@ void LLInvFVBridge::changeItemParent(LLInventoryModel* model,
// static
void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model,
LLViewerInventoryCategory* cat,
- const LLUUID& new_parent,
+ const LLUUID& new_parent_id,
BOOL restamp)
{
- if(cat->getParentUUID() != new_parent)
+ // Can't move a folder into a child of itself.
+ if (model->isObjectDescendentOf(new_parent_id, cat->getUUID()))
{
- LLInventoryModel::update_list_t update;
- LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1);
- update.push_back(old_folder);
- LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1);
- update.push_back(new_folder);
- gInventory.accountForUpdate(update);
-
- LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
- new_cat->setParent(new_parent);
- new_cat->updateParentOnServer(restamp);
- model->updateCategory(new_cat);
- model->notifyObservers();
+ return;
}
+
+ LLInventoryModel::update_list_t update;
+ LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1);
+ update.push_back(old_folder);
+ LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
+ update.push_back(new_folder);
+ model->accountForUpdate(update);
+
+ LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
+ new_cat->setParent(new_parent_id);
+ new_cat->updateParentOnServer(restamp);
+ model->updateCategory(new_cat);
+ model->notifyObservers();
}
-const char* safe_inv_type_lookup(LLInventoryType::EType inv_type)
+const std::string safe_inv_type_lookup(LLInventoryType::EType inv_type)
{
- const char* rv = LLInventoryType::lookup(inv_type);
- if(!rv)
+ const std::string rv= LLInventoryType::lookup(inv_type);
+ if(rv.empty())
{
- const char* INVALID_TYPE = "<invalid>";
- rv = INVALID_TYPE;
+ return std::string("<invalid>");
}
return rv;
}
LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
- LLInventoryType::EType inv_type,
- LLInventoryPanel* inventory,
- const LLUUID& uuid,
- U32 flags)
+ LLAssetType::EType actual_asset_type,
+ LLInventoryType::EType inv_type,
+ LLInventoryPanel* inventory,
+ const LLUUID& uuid,
+ U32 flags)
{
LLInvFVBridge* new_listener = NULL;
switch(asset_type)
{
- case LLAssetType::AT_TEXTURE:
- if(!(inv_type == LLInventoryType::IT_TEXTURE || inv_type == LLInventoryType::IT_SNAPSHOT))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLTextureBridge(inventory, uuid, inv_type);
- break;
+ case LLAssetType::AT_TEXTURE:
+ if(!(inv_type == LLInventoryType::IT_TEXTURE || inv_type == LLInventoryType::IT_SNAPSHOT))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLTextureBridge(inventory, uuid, inv_type);
+ break;
- case LLAssetType::AT_SOUND:
- if(!(inv_type == LLInventoryType::IT_SOUND))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLSoundBridge(inventory, uuid);
- break;
+ case LLAssetType::AT_SOUND:
+ if(!(inv_type == LLInventoryType::IT_SOUND))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLSoundBridge(inventory, uuid);
+ break;
- case LLAssetType::AT_LANDMARK:
- if(!(inv_type == LLInventoryType::IT_LANDMARK))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLLandmarkBridge(inventory, uuid, flags);
- break;
-
- case LLAssetType::AT_CALLINGCARD:
- if(!(inv_type == LLInventoryType::IT_CALLINGCARD))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLCallingCardBridge(inventory, uuid);
- break;
+ case LLAssetType::AT_LANDMARK:
+ if(!(inv_type == LLInventoryType::IT_LANDMARK))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLLandmarkBridge(inventory, uuid, flags);
+ break;
- case LLAssetType::AT_SCRIPT:
- if(!(inv_type == LLInventoryType::IT_LSL))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLScriptBridge(inventory, uuid);
- break;
+ case LLAssetType::AT_CALLINGCARD:
+ if(!(inv_type == LLInventoryType::IT_CALLINGCARD))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLCallingCardBridge(inventory, uuid);
+ break;
- case LLAssetType::AT_OBJECT:
- if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLObjectBridge(inventory, uuid, inv_type, flags);
- break;
+ case LLAssetType::AT_SCRIPT:
+ if(!(inv_type == LLInventoryType::IT_LSL))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLScriptBridge(inventory, uuid);
+ break;
- case LLAssetType::AT_NOTECARD:
- if(!(inv_type == LLInventoryType::IT_NOTECARD))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLNotecardBridge(inventory, uuid);
- break;
+ case LLAssetType::AT_OBJECT:
+ if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLObjectBridge(inventory, uuid, inv_type, flags);
+ break;
- case LLAssetType::AT_ANIMATION:
- if(!(inv_type == LLInventoryType::IT_ANIMATION))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLAnimationBridge(inventory, uuid);
- break;
+ case LLAssetType::AT_NOTECARD:
+ if(!(inv_type == LLInventoryType::IT_NOTECARD))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLNotecardBridge(inventory, uuid);
+ break;
- case LLAssetType::AT_GESTURE:
- if(!(inv_type == LLInventoryType::IT_GESTURE))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLGestureBridge(inventory, uuid);
- break;
+ case LLAssetType::AT_ANIMATION:
+ if(!(inv_type == LLInventoryType::IT_ANIMATION))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLAnimationBridge(inventory, uuid);
+ break;
- case LLAssetType::AT_LSL_TEXT:
- if(!(inv_type == LLInventoryType::IT_LSL))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLLSLTextBridge(inventory, uuid);
- break;
+ case LLAssetType::AT_GESTURE:
+ if(!(inv_type == LLInventoryType::IT_GESTURE))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLGestureBridge(inventory, uuid);
+ break;
- case LLAssetType::AT_CLOTHING:
- case LLAssetType::AT_BODYPART:
- if(!(inv_type == LLInventoryType::IT_WEARABLE))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLWearableBridge(inventory, uuid, asset_type, inv_type, (EWearableType)flags);
- break;
+ case LLAssetType::AT_LSL_TEXT:
+ if(!(inv_type == LLInventoryType::IT_LSL))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLLSLTextBridge(inventory, uuid);
+ break;
- case LLAssetType::AT_CATEGORY:
- case LLAssetType::AT_ROOT_CATEGORY:
- new_listener = new LLFolderBridge(inventory, uuid);
- break;
-
- default:
- llinfos << "Unhandled asset type (llassetstorage.h): "
- << (S32)asset_type << llendl;
- break;
+ case LLAssetType::AT_CLOTHING:
+ case LLAssetType::AT_BODYPART:
+ if(!(inv_type == LLInventoryType::IT_WEARABLE))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLWearableBridge(inventory, uuid, asset_type, inv_type, (EWearableType)flags);
+ break;
+ case LLAssetType::AT_CATEGORY:
+ if (actual_asset_type == LLAssetType::AT_LINK_FOLDER)
+ {
+ // Create a link folder handler instead.
+ new_listener = new LLLinkFolderBridge(inventory, uuid);
+ break;
+ }
+ new_listener = new LLFolderBridge(inventory, uuid);
+ break;
+ case LLAssetType::AT_LINK:
+ case LLAssetType::AT_LINK_FOLDER:
+ // Only should happen for broken links.
+ new_listener = new LLLinkItemBridge(inventory, uuid);
+ break;
+ default:
+ llinfos << "Unhandled asset type (llassetstorage.h): "
+ << (S32)asset_type << llendl;
+ break;
}
if (new_listener)
@@ -728,41 +911,85 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
return new_listener;
}
+void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
+{
+ LLInventoryCategory* cat = model->getCategory(uuid);
+ if (cat)
+ {
+ model->purgeDescendentsOf(uuid);
+ model->notifyObservers();
+ }
+ LLInventoryObject* obj = model->getObject(uuid);
+ if (obj)
+ {
+ model->purgeObject(uuid);
+ model->notifyObservers();
+ }
+}
+
+bool LLInvFVBridge::isInOutfitsSidePanel() const
+{
+ LLInventoryPanel *my_panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLPanelOutfitsInventory *outfit_panel =
+ dynamic_cast<LLPanelOutfitsInventory*>(LLSideTray::getInstance()->getPanel("panel_outfits_inventory"));
+ if (!outfit_panel)
+ return false;
+ return outfit_panel->isTabPanel(my_panel);
+}
+
+// +=================================================+
+// | InventoryFVBridgeBuilder |
+// +=================================================+
+LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type,
+ LLAssetType::EType actual_asset_type,
+ LLInventoryType::EType inv_type,
+ LLInventoryPanel* inventory,
+ const LLUUID& uuid,
+ U32 flags /* = 0x00 */) const
+{
+ return LLInvFVBridge::createBridge(asset_type,
+ actual_asset_type,
+ inv_type,
+ inventory,
+ uuid,
+ flags);
+}
+
// +=================================================+
// | LLItemBridge |
// +=================================================+
void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
{
+ if ("goto" == action)
+ {
+ gotoItem(folder);
+ }
+
if ("open" == action)
{
openItem();
+ return;
}
else if ("properties" == action)
{
showProperties();
+ return;
}
else if ("purge" == action)
{
- LLInventoryCategory* cat = model->getCategory(mUUID);
- if(cat)
- {
- model->purgeDescendentsOf(mUUID);
- }
- LLInventoryObject* obj = model->getObject(mUUID);
- if(!obj) return;
- obj->removeFromServer();
- LLPreview::hide(mUUID);
- model->deleteObject(mUUID);
- model->notifyObservers();
+ purgeItem(model, mUUID);
+ return;
}
else if ("restoreToWorld" == action)
{
restoreToWorld();
+ return;
}
else if ("restore" == action)
{
restoreItem();
+ return;
}
else if ("copy_uuid" == action)
{
@@ -793,6 +1020,18 @@ void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model,
folder_view_itemp->getListener()->pasteFromClipboard();
return;
}
+ else if ("paste_link" == action)
+ {
+ // Single item only
+ LLInventoryItem* itemp = model->getItem(mUUID);
+ if (!itemp) return;
+
+ LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID());
+ if (!folder_view_itemp) return;
+
+ folder_view_itemp->getListener()->pasteLinkFromClipboard();
+ return;
+ }
}
void LLItemBridge::selectItem()
@@ -809,8 +1048,8 @@ void LLItemBridge::restoreItem()
LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem();
if(item)
{
- LLInventoryModel* model = mInventoryPanel->getModel();
- LLUUID new_parent = model->findCategoryUUIDForType(item->getType());
+ LLInventoryModel* model = getInventoryModel();
+ const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(item->getType()));
// do not restamp on restore.
LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE);
}
@@ -843,8 +1082,7 @@ void LLItemBridge::restoreToWorld()
}
// Check if it's in the trash. (again similar to the normal rez logic)
- LLUUID trash_id;
- trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
if(gInventory.isObjectDescendentOf(itemp->getUUID(), trash_id))
{
remove_from_inventory = TRUE;
@@ -857,6 +1095,19 @@ void LLItemBridge::restoreToWorld()
}
}
+void LLItemBridge::gotoItem(LLFolderView *folder)
+{
+ LLInventoryObject *obj = getInventoryObject();
+ if (obj && obj->getIsLinkType())
+ {
+ LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel();
+ if (active_panel)
+ {
+ active_panel->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO);
+ }
+ }
+}
+
LLUIImagePtr LLItemBridge::getIcon() const
{
return LLUI::getUIImage(ICON_NAME[OBJECT_ICON_NAME]);
@@ -866,7 +1117,7 @@ PermissionMask LLItemBridge::getPermissionMask() const
{
LLViewerInventoryItem* item = getItem();
PermissionMask perm_mask = 0;
- if(item)
+ if(item)
{
BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
@@ -880,7 +1131,7 @@ PermissionMask LLItemBridge::getPermissionMask() const
}
return perm_mask;
}
-
+
const std::string& LLItemBridge::getDisplayName() const
{
if(mDisplayName.empty())
@@ -892,9 +1143,9 @@ const std::string& LLItemBridge::getDisplayName() const
void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name)
{
- if(item)
+ if(item)
{
- name.assign(item->getName());
+ name.assign(item->getName());
}
else
{
@@ -902,35 +1153,63 @@ void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name)
}
}
+LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const
+{
+ U8 font = LLFontGL::NORMAL;
+
+ if (get_is_item_worn(mUUID))
+ {
+ // llinfos << "BOLD" << llendl;
+ font |= LLFontGL::BOLD;
+ }
+
+ const LLViewerInventoryItem* item = getItem();
+ if (item && item->getIsLinkType())
+ {
+ font |= LLFontGL::ITALIC;
+ }
+ return (LLFontGL::StyleFlags)font;
+}
+
std::string LLItemBridge::getLabelSuffix() const
{
+ // String table is loaded before login screen and inventory items are
+ // loaded after login, so LLTrans should be ready.
+ static std::string NO_COPY =LLTrans::getString("no_copy");
+ static std::string NO_MOD = LLTrans::getString("no_modify");
+ static std::string NO_XFER = LLTrans::getString("no_transfer");
+ static std::string LINK = LLTrans::getString("link");
+ static std::string BROKEN_LINK = LLTrans::getString("broken_link");
std::string suffix;
LLInventoryItem* item = getItem();
- if(item)
+ if(item)
{
// it's a bit confusing to put nocopy/nomod/etc on calling cards.
if(LLAssetType::AT_CALLINGCARD != item->getType()
&& item->getPermissions().getOwner() == gAgent.getID())
{
+ BOOL broken_link = LLAssetType::lookupIsLinkType(item->getType());
+ if (broken_link) return BROKEN_LINK;
+
+ BOOL link = item->getIsLinkType();
+ if (link) return LINK;
+
BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
+ if (!copy)
+ {
+ suffix += NO_COPY;
+ }
BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
+ if (!mod)
+ {
+ suffix += NO_MOD;
+ }
BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
gAgent.getID());
- // *TODO: Translate
- const char* EMPTY = "";
- const char* NO_COPY = " (no copy)";
- const char* NO_MOD = " (no modify)";
- const char* NO_XFER = " (no transfer)";
- const char* scopy;
- if(copy) scopy = EMPTY;
- else scopy = NO_COPY;
- const char* smod;
- if(mod) smod = EMPTY;
- else smod = NO_MOD;
- const char* sxfer;
- if(xfer) sxfer = EMPTY;
- else sxfer = NO_XFER;
- suffix = llformat("%s%s%s",scopy,smod,sxfer);
+ if (!xfer)
+ {
+ suffix += NO_XFER;
+ }
}
}
return suffix;
@@ -952,6 +1231,12 @@ BOOL LLItemBridge::isItemRenameable() const
LLViewerInventoryItem* item = getItem();
if(item)
{
+ // (For now) Don't allow calling card rename since that may confuse users as to
+ // what the calling card points to.
+ if (item->getInventoryType() == LLInventoryType::IT_CALLINGCARD)
+ {
+ return FALSE;
+ }
return (item->getPermissions().allowModifyBy(gAgent.getID()));
}
return FALSE;
@@ -959,10 +1244,12 @@ BOOL LLItemBridge::isItemRenameable() const
BOOL LLItemBridge::renameItem(const std::string& new_name)
{
- if(!isItemRenameable()) return FALSE;
- LLPreview::rename(mUUID, getPrefix() + new_name);
- LLInventoryModel* model = mInventoryPanel->getModel();
- if(!model) return FALSE;
+ if(!isItemRenameable())
+ return FALSE;
+ LLPreview::dirty(mUUID);
+ LLInventoryModel* model = getInventoryModel();
+ if(!model)
+ return FALSE;
LLViewerInventoryItem* item = getItem();
if(item && (item->getName() != new_name))
{
@@ -971,6 +1258,7 @@ BOOL LLItemBridge::renameItem(const std::string& new_name)
buildDisplayName(new_item, mDisplayName);
new_item->updateServer(FALSE);
model->updateItem(new_item);
+
model->notifyObservers();
}
// return FALSE because we either notified observers (& therefore
@@ -987,9 +1275,9 @@ BOOL LLItemBridge::removeItem()
}
// move it to the trash
LLPreview::hide(mUUID, TRUE);
- LLInventoryModel* model = mInventoryPanel->getModel();
+ LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
- LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
LLViewerInventoryItem* item = getItem();
// if item is not already in trash
@@ -1012,23 +1300,33 @@ BOOL LLItemBridge::isItemCopyable() const
LLViewerInventoryItem* item = getItem();
if (item)
{
- // can't copy worn objects. DEV-15183
- LLVOAvatar *avatarp = gAgent.getAvatarObject();
- if( !avatarp )
+ // Can't copy worn objects. DEV-15183
+ if(get_is_item_worn(mUUID))
{
return FALSE;
}
- if( avatarp->isWearingAttachment( mUUID ) )
+ // You can never copy a link.
+ if (item->getIsLinkType())
{
return FALSE;
}
-
- return (item->getPermissions().allowCopyBy(gAgent.getID()));
+ if (gAgent.isGodlike())
+ {
+ // All items can be copied in god mode since you can
+ // at least paste-as-link the item, though you
+ // still may not be able paste the item.
+ return TRUE;
+ }
+ else
+ {
+ return (item->getPermissions().allowCopyBy(gAgent.getID()));
+ }
}
return FALSE;
}
+
BOOL LLItemBridge::copyToClipboard() const
{
if(isItemCopyable())
@@ -1042,7 +1340,7 @@ BOOL LLItemBridge::copyToClipboard() const
LLViewerInventoryItem* LLItemBridge::getItem() const
{
LLViewerInventoryItem* item = NULL;
- LLInventoryModel* model = mInventoryPanel->getModel();
+ LLInventoryModel* model = getInventoryModel();
if(model)
{
item = (LLViewerInventoryItem*)model->getItem(mUUID);
@@ -1064,6 +1362,16 @@ BOOL LLItemBridge::isItemPermissive() const
return FALSE;
}
+bool LLItemBridge::isAddAction(std::string action) const
+{
+ return ("wear" == action || "attach" == action || "activate" == action);
+}
+
+bool LLItemBridge::isRemoveAction(std::string action) const
+{
+ return ("take_off" == action || "detach" == action || "deactivate" == action);
+}
+
// +=================================================+
// | LLFolderBridge |
// +=================================================+
@@ -1071,12 +1379,12 @@ BOOL LLItemBridge::isItemPermissive() const
LLFolderBridge* LLFolderBridge::sSelf=NULL;
// Can be moved to another folder
-BOOL LLFolderBridge::isItemMovable()
+BOOL LLFolderBridge::isItemMovable() const
{
LLInventoryObject* obj = getInventoryObject();
if(obj)
{
- return (LLAssetType::AT_NONE == ((LLInventoryCategory*)obj)->getPreferredType());
+ return (!LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)obj)->getPreferredType()));
}
return FALSE;
}
@@ -1086,21 +1394,38 @@ void LLFolderBridge::selectItem()
}
+// Iterate through a folder's children to determine if
+// all the children are removable.
+class LLIsItemRemovable : public LLFolderViewFunctor
+{
+public:
+ LLIsItemRemovable() : mPassed(TRUE) {}
+ virtual void doFolder(LLFolderViewFolder* folder)
+ {
+ mPassed &= folder->getListener()->isItemRemovable();
+ }
+ virtual void doItem(LLFolderViewItem* item)
+ {
+ mPassed &= item->getListener()->isItemRemovable();
+ }
+ BOOL mPassed;
+};
+
// Can be destroyed (or moved to trash)
BOOL LLFolderBridge::isItemRemovable()
{
- LLInventoryModel* model = mInventoryPanel->getModel();
- if(!model)
+ LLInventoryModel* model = getInventoryModel();
+ if(!model)
{
return FALSE;
}
- if(!model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID()))
+ if(!model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()))
{
return FALSE;
}
- LLVOAvatar* avatar = gAgent.getAvatarObject();
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
if( !avatar )
{
return FALSE;
@@ -1112,76 +1437,153 @@ BOOL LLFolderBridge::isItemRemovable()
return FALSE;
}
- if( LLAssetType::AT_NONE != category->getPreferredType() )
+ if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
{
return FALSE;
}
- LLInventoryModel::cat_array_t descendent_categories;
- LLInventoryModel::item_array_t descendent_items;
- gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE );
-
- S32 i;
- for( i = 0; i < descendent_categories.count(); i++ )
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL);
+ if (folderp)
{
- LLInventoryCategory* category = descendent_categories[i];
- if( LLAssetType::AT_NONE != category->getPreferredType() )
+ LLIsItemRemovable folder_test;
+ folderp->applyFunctorToChildren(folder_test);
+ if (!folder_test.mPassed)
{
return FALSE;
}
}
+ return TRUE;
+}
- for( i = 0; i < descendent_items.count(); i++ )
+BOOL LLFolderBridge::isUpToDate() const
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
+ if( !category )
{
- LLInventoryItem* item = descendent_items[i];
- if( (item->getType() == LLAssetType::AT_CLOTHING) ||
- (item->getType() == LLAssetType::AT_BODYPART) )
+ return FALSE;
+ }
+
+ return category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN;
+}
+
+BOOL LLFolderBridge::isItemCopyable() const
+{
+ return TRUE;
+}
+
+BOOL LLFolderBridge::copyToClipboard() const
+{
+ if(isItemCopyable())
+ {
+ LLInventoryClipboard::instance().add(mUUID);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL LLFolderBridge::isClipboardPasteable() const
+{
+ if ( ! LLInvFVBridge::isClipboardPasteable() )
+ return FALSE;
+
+ // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599
+ if ( LLFriendCardsManager::instance().isCategoryInFriendFolder( getCategory() ) )
+ {
+ LLInventoryModel* model = getInventoryModel();
+ if ( !model )
{
- if( gAgent.isWearingItem( item->getUUID() ) )
- {
- return FALSE;
- }
+ return FALSE;
}
- else
- if( item->getType() == LLAssetType::AT_OBJECT )
+
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ const LLViewerInventoryCategory *current_cat = getCategory();
+
+ // Search for the direct descendent of current Friends subfolder among all pasted items,
+ // and return false if is found.
+ for(S32 i = objects.count() - 1; i >= 0; --i)
{
- if( avatar->isWearingAttachment( item->getUUID() ) )
+ const LLUUID &obj_id = objects.get(i);
+ if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) )
{
return FALSE;
}
}
- }
+ }
return TRUE;
}
-BOOL LLFolderBridge::isUpToDate() const
+BOOL LLFolderBridge::isClipboardPasteableAsLink() const
{
- LLInventoryModel* model = mInventoryPanel->getModel();
- if(!model) return FALSE;
- LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
- if( !category )
+ // Check normal paste-as-link permissions
+ if (!LLInvFVBridge::isClipboardPasteableAsLink())
{
return FALSE;
}
- return category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN;
+ const LLInventoryModel* model = getInventoryModel();
+ if (!model)
+ {
+ return FALSE;
+ }
+
+ const LLViewerInventoryCategory *current_cat = getCategory();
+ if (current_cat)
+ {
+ const BOOL is_in_friend_folder = LLFriendCardsManager::instance().isCategoryInFriendFolder( current_cat );
+ const LLUUID &current_cat_id = current_cat->getUUID();
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ for(S32 i = 0; i < count; i++)
+ {
+ const LLUUID &obj_id = objects.get(i);
+ const LLInventoryCategory *cat = model->getCategory(obj_id);
+ if (cat)
+ {
+ const LLUUID &cat_id = cat->getUUID();
+ // Don't allow recursive pasting
+ if ((cat_id == current_cat_id) ||
+ model->isObjectDescendentOf(current_cat_id, cat_id))
+ {
+ return FALSE;
+ }
+ }
+ // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599
+ if ( is_in_friend_folder )
+ {
+ // If object is direct descendent of current Friends subfolder than return false.
+ // Note: We can't use 'const LLInventoryCategory *cat', because it may be null
+ // in case type of obj_id is LLInventoryItem.
+ if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) )
+ {
+ return FALSE;
+ }
+ }
+ }
+ }
+ return TRUE;
+
}
BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
BOOL drop)
{
- // This should never happen, but if an inventory item is incorrectly parented,
+ // This should never happen, but if an inventory item is incorrectly parented,
// the UI will get confused and pass in a NULL.
if(!inv_cat) return FALSE;
- LLInventoryModel* model = mInventoryPanel->getModel();
+ LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
- LLVOAvatar* avatar = gAgent.getAvatarObject();
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
if(!avatar) return FALSE;
- // cannot drag into library
+ // cannot drag categories into library
if(!isAgentInventory())
{
return FALSE;
@@ -1201,11 +1603,24 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
const LLUUID& cat_id = inv_cat->getUUID();
// Is the destination the trash?
- LLUUID trash_id;
- trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
BOOL move_is_into_trash = (mUUID == trash_id)
|| model->isObjectDescendentOf(mUUID, trash_id);
- BOOL is_movable = (LLAssetType::AT_NONE == inv_cat->getPreferredType());
+ BOOL is_movable = (!LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType()));
+ const LLUUID current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
+ BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
+ BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
+ if (move_is_into_current_outfit || move_is_into_outfit)
+ {
+ // BAP - restrictions?
+ is_movable = true;
+ }
+
+ if (mUUID == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE))
+ {
+ is_movable = FALSE; // It's generally movable but not into Favorites folder. EXT-1604
+ }
+
if( is_movable )
{
gInventory.collectDescendents( cat_id, descendent_categories, descendent_items, FALSE );
@@ -1213,14 +1628,14 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
for( i = 0; i < descendent_categories.count(); i++ )
{
LLInventoryCategory* category = descendent_categories[i];
- if( LLAssetType::AT_NONE != category->getPreferredType() )
+ if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
{
// ...can't move "special folders" like Textures
is_movable = FALSE;
break;
}
}
-
+
if( is_movable )
{
if( move_is_into_trash )
@@ -1228,30 +1643,17 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
for( i = 0; i < descendent_items.count(); i++ )
{
LLInventoryItem* item = descendent_items[i];
- if( (item->getType() == LLAssetType::AT_CLOTHING) ||
- (item->getType() == LLAssetType::AT_BODYPART) )
+ if (get_is_item_worn(item->getUUID()))
{
- if( gAgent.isWearingItem( item->getUUID() ) )
- {
- is_movable = FALSE; // It's generally movable, but not into the trash!
- break;
- }
- }
- else
- if( item->getType() == LLAssetType::AT_OBJECT )
- {
- if( avatar->isWearingAttachment( item->getUUID() ) )
- {
- is_movable = FALSE; // It's generally movable, but not into the trash!
- break;
- }
+ is_movable = FALSE;
+ break; // It's generally movable, but not into the trash!
}
}
}
}
}
-
+
accept = is_movable
&& (mUUID != cat_id) // Can't move a folder into itself
&& (mUUID != inv_cat->getParentUUID()) // Avoid moves that would change nothing
@@ -1265,20 +1667,65 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
{
LLInventoryItem* item = descendent_items[i];
if (item->getType() == LLAssetType::AT_GESTURE
- && gGestureManager.isGestureActive(item->getUUID()))
+ && LLGestureManager::instance().isGestureActive(item->getUUID()))
+ {
+ LLGestureManager::instance().deactivateGesture(item->getUUID());
+ }
+ }
+ }
+ // if target is an outfit or current outfit folder we use link
+ if (move_is_into_current_outfit || move_is_into_outfit)
+ {
+ if (inv_cat->getPreferredType() == LLFolderType::FT_NONE)
+ {
+ if (move_is_into_current_outfit)
{
- gGestureManager.deactivateGesture(item->getUUID());
+ // traverse category and add all contents to currently worn.
+ BOOL append = true;
+ LLAppearanceManager::instance().wearInventoryCategory(inv_cat, false, append);
}
+ else
+ {
+ // Recursively create links in target outfit.
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ gInventory.collectDescendents(inv_cat->getUUID(), cats, items, LLInventoryModel::EXCLUDE_TRASH);
+ LLAppearanceManager::instance().linkAll(mUUID,items,NULL);
+ }
+ }
+ else
+ {
+#if SUPPORT_ENSEMBLES
+ // BAP - should skip if dup.
+ if (move_is_into_current_outfit)
+ {
+ LLAppearanceManager::instance().addEnsembleLink(inv_cat);
+ }
+ else
+ {
+ LLPointer<LLInventoryCallback> cb = NULL;
+ link_inventory_item(
+ gAgent.getID(),
+ inv_cat->getUUID(),
+ mUUID,
+ inv_cat->getName(),
+ LLAssetType::AT_LINK_FOLDER,
+ cb);
+ }
+#endif
}
}
+ else
+ {
- // Reparent the folder and restamp children if it's moving
- // into trash.
- LLInvFVBridge::changeCategoryParent(
- model,
- (LLViewerInventoryCategory*)inv_cat,
- mUUID,
- move_is_into_trash);
+ // Reparent the folder and restamp children if it's moving
+ // into trash.
+ LLInvFVBridge::changeCategoryParent(
+ model,
+ (LLViewerInventoryCategory*)inv_cat,
+ mUUID,
+ move_is_into_trash);
+ }
}
}
else if(LLToolDragAndDrop::SOURCE_WORLD == source)
@@ -1302,12 +1749,12 @@ void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv)
{
dialog = "MoveInventoryFromObject";
}
- LLNotifications::instance().add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv));
+ LLNotificationsUtil::add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv));
}
// Move/copy all inventory items from the Contents folder of an in-world
// object to the agent's inventory, inside a given category.
-BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
+BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
const LLUUID& category_id,
BOOL drop,
void (*callback)(S32, void*),
@@ -1334,7 +1781,7 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
llinfos << "Object contents not found for drop." << llendl;
return FALSE;
}
-
+
BOOL accept = TRUE;
BOOL is_move = FALSE;
@@ -1392,21 +1839,40 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
else
{
LLNotification::Params params("MoveInventoryFromObject");
- params.functor(boost::bind(move_task_inventory_callback, _1, _2, move_inv));
+ params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv));
LLNotifications::instance().forceResponse(params, 0);
}
}
return accept;
}
-class LLFindWearables : public LLInventoryCollectFunctor
+bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item)
{
-public:
- LLFindWearables() {}
- virtual ~LLFindWearables() {}
- virtual bool operator()(LLInventoryCategory* cat,
- LLInventoryItem* item);
-};
+ // Valid COF items are:
+ // - links to wearables (body parts or clothing)
+ // - links to attachments
+ // - links to gestures
+ // - links to ensemble folders
+ LLViewerInventoryItem *linked_item = ((LLViewerInventoryItem*)item)->getLinkedItem(); // BAP - safe?
+ if (linked_item)
+ {
+ LLAssetType::EType type = linked_item->getType();
+ return (type == LLAssetType::AT_CLOTHING ||
+ type == LLAssetType::AT_BODYPART ||
+ type == LLAssetType::AT_GESTURE ||
+ type == LLAssetType::AT_OBJECT);
+ }
+ else
+ {
+ LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory(); // BAP - safe?
+ // BAP remove AT_NONE support after ensembles are fully working?
+ return (linked_category &&
+ ((linked_category->getPreferredType() == LLFolderType::FT_NONE) ||
+ (LLFolderType::lookupIsEnsembleType(linked_category->getPreferredType()))));
+ }
+}
+
bool LLFindWearables::operator()(LLInventoryCategory* cat,
LLInventoryItem* item)
@@ -1422,6 +1888,8 @@ bool LLFindWearables::operator()(LLInventoryCategory* cat,
return FALSE;
}
+
+
//Used by LLFolderBridge as callback for directory recursion.
class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver
{
@@ -1441,7 +1909,7 @@ public:
gInventory.removeObserver(this);
delete this;
}
-
+
protected:
LLUUID mCatID;
@@ -1536,7 +2004,7 @@ void LLRightClickInventoryFetchDescendentsObserver::done()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLInventoryWearObserver
//
-// Observer for "copy and wear" operation to support knowing
+// Observer for "copy and wear" operation to support knowing
// when the all of the contents have been added to inventory.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLInventoryCopyAndWearObserver : public LLInventoryObserver
@@ -1558,7 +2026,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
{
if((mask & (LLInventoryObserver::ADD)) != 0)
{
- if (!mFolderAdded)
+ if (!mFolderAdded)
{
const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
@@ -1566,7 +2034,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
std::set<LLUUID>::const_iterator id_end = changed_items.end();
for (;id_it != id_end; ++id_it)
{
- if ((*id_it) == mCatID)
+ if ((*id_it) == mCatID)
{
mFolderAdded = TRUE;
break;
@@ -1574,7 +2042,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
}
}
- if (mFolderAdded)
+ if (mFolderAdded)
{
LLViewerInventoryCategory* category = gInventory.getCategory(mCatID);
@@ -1589,10 +2057,10 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
mContentsCount)
{
gInventory.removeObserver(this);
- wear_inventory_category(category, FALSE, TRUE);
+ LLAppearanceManager::instance().wearInventoryCategory(category, FALSE, TRUE);
delete this;
}
- }
+ }
}
}
@@ -1604,66 +2072,118 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model
{
if ("open" == action)
{
- openItem();
+ LLFolderViewFolder *f = dynamic_cast<LLFolderViewFolder *>(folder->getItemByID(mUUID));
+ if (f)
+ {
+ f->setOpen(TRUE);
+ }
+
+ return;
}
else if ("paste" == action)
{
pasteFromClipboard();
+ return;
+ }
+ else if ("paste_link" == action)
+ {
+ pasteLinkFromClipboard();
+ return;
}
else if ("properties" == action)
{
showProperties();
+ return;
}
else if ("replaceoutfit" == action)
{
modifyOutfit(FALSE);
+ return;
+ }
+#if SUPPORT_ENSEMBLES
+ else if ("wearasensemble" == action)
+ {
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(!cat) return;
+ LLAppearanceManager::instance().addEnsembleLink(cat,true);
+ return;
}
+#endif
else if ("addtooutfit" == action)
{
modifyOutfit(TRUE);
+ return;
+ }
+ else if ("copy" == action)
+ {
+ copyToClipboard();
+ return;
}
else if ("removefromoutfit" == action)
{
- LLInventoryModel* model = mInventoryPanel->getModel();
+ LLInventoryModel* model = getInventoryModel();
if(!model) return;
LLViewerInventoryCategory* cat = getCategory();
if(!cat) return;
-
+
remove_inventory_category_from_avatar ( cat );
- }
+ return;
+ }
else if ("purge" == action)
- {
- LLViewerInventoryCategory* cat;
- cat = (LLViewerInventoryCategory*)getCategory();
-
- if(cat)
- {
- model->purgeDescendentsOf(mUUID);
- }
- LLInventoryObject* obj = model->getObject(mUUID);
- if(!obj) return;
- obj->removeFromServer();
- model->deleteObject(mUUID);
- model->notifyObservers();
+ {
+ purgeItem(model, mUUID);
+ return;
}
else if ("restore" == action)
{
restoreItem();
+ return;
+ }
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+ else if ("delete_system_folder" == action)
+ {
+ removeSystemFolder();
}
+#endif
}
void LLFolderBridge::openItem()
{
lldebugs << "LLFolderBridge::openItem()" << llendl;
- LLInventoryModel* model = mInventoryPanel->getModel();
+ LLInventoryModel* model = getInventoryModel();
if(!model) return;
- model->fetchDescendentsOf(mUUID);
+ if(mUUID.isNull()) return;
+ bool fetching_inventory = model->fetchDescendentsOf(mUUID);
+ // Only change folder type if we have the folder contents.
+ if (!fetching_inventory)
+ {
+ // Disabling this for now, it's causing crash when new items are added to folders
+ // since folder type may change before new item item has finished processing.
+ // determineFolderType();
+ }
+}
+
+void LLFolderBridge::closeItem()
+{
+ determineFolderType();
+}
+
+void LLFolderBridge::determineFolderType()
+{
+ if (isUpToDate())
+ {
+ LLInventoryModel* model = getInventoryModel();
+ LLViewerInventoryCategory* category = model->getCategory(mUUID);
+ category->determineFolderType();
+ }
}
BOOL LLFolderBridge::isItemRenameable() const
{
LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory();
- if(cat && (cat->getPreferredType() == LLAssetType::AT_NONE)
+ if(cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType())
&& (cat->getOwnerID() == gAgent.getID()))
{
return TRUE;
@@ -1677,83 +2197,63 @@ void LLFolderBridge::restoreItem()
cat = (LLViewerInventoryCategory*)getCategory();
if(cat)
{
- LLInventoryModel* model = mInventoryPanel->getModel();
- LLUUID new_parent = model->findCategoryUUIDForType(cat->getType());
+ LLInventoryModel* model = getInventoryModel();
+ const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(cat->getType()));
// do not restamp children on restore
LLInvFVBridge::changeCategoryParent(model, cat, new_parent, FALSE);
}
}
+LLFolderType::EType LLFolderBridge::getPreferredType() const
+{
+ LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(cat)
+ {
+ preferred_type = cat->getPreferredType();
+ }
+
+ return preferred_type;
+}
+
// Icons for folders are based on the preferred type
LLUIImagePtr LLFolderBridge::getIcon() const
{
- const char* control = NULL;
- LLAssetType::EType preferred_type = LLAssetType::AT_NONE;
+ LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
LLViewerInventoryCategory* cat = getCategory();
if(cat)
{
preferred_type = cat->getPreferredType();
}
- switch(preferred_type)
+ return getIcon(preferred_type);
+}
+
+LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type)
+{
+ // we only have one folder image now
+ if (preferred_type == LLFolderType::FT_OUTFIT)
+ {
+ return LLUI::getUIImage("Inv_LookFolderClosed");
+ }
+ return LLUI::getUIImage("Inv_FolderClosed");
+}
+
+LLUIImagePtr LLFolderBridge::getOpenIcon() const
+{
+ if (getPreferredType() == LLFolderType::FT_OUTFIT)
{
- case LLAssetType::AT_TEXTURE:
- control = "inv_folder_texture.tga";
- break;
- case LLAssetType::AT_SOUND:
- control = "inv_folder_sound.tga";
- break;
- case LLAssetType::AT_CALLINGCARD:
- control = "inv_folder_callingcard.tga";
- break;
- case LLAssetType::AT_LANDMARK:
- control = "inv_folder_landmark.tga";
- break;
- case LLAssetType::AT_SCRIPT:
- case LLAssetType::AT_LSL_TEXT:
- control = "inv_folder_script.tga";
- break;
- case LLAssetType::AT_OBJECT:
- control = "inv_folder_object.tga";
- break;
- case LLAssetType::AT_NOTECARD:
- control = "inv_folder_notecard.tga";
- break;
- case LLAssetType::AT_CATEGORY:
- control = "inv_folder_plain_closed.tga";
- break;
- case LLAssetType::AT_CLOTHING:
- control = "inv_folder_clothing.tga";
- break;
- case LLAssetType::AT_BODYPART:
- control = "inv_folder_bodypart.tga";
- break;
- case LLAssetType::AT_TRASH:
- control = "inv_folder_trash.tga";
- break;
- case LLAssetType::AT_SNAPSHOT_CATEGORY:
- control = "inv_folder_snapshot.tga";
- break;
- case LLAssetType::AT_LOST_AND_FOUND:
- control = "inv_folder_lostandfound.tga";
- break;
- case LLAssetType::AT_ANIMATION:
- control = "inv_folder_animation.tga";
- break;
- case LLAssetType::AT_GESTURE:
- control = "inv_folder_gesture.tga";
- break;
- default:
- control = "inv_folder_plain_closed.tga";
- break;
+ return LLUI::getUIImage("Inv_LookFolderOpen");
}
- return LLUI::getUIImage(control);
+ return LLUI::getUIImage("Inv_FolderOpen");
}
BOOL LLFolderBridge::renameItem(const std::string& new_name)
{
- if(!isItemRenameable()) return FALSE;
- LLInventoryModel* model = mInventoryPanel->getModel();
- if(!model) return FALSE;
+ if(!isItemRenameable())
+ return FALSE;
+ LLInventoryModel* model = getInventoryModel();
+ if(!model)
+ return FALSE;
LLViewerInventoryCategory* cat = getCategory();
if(cat && (cat->getName() != new_name))
{
@@ -1761,6 +2261,7 @@ BOOL LLFolderBridge::renameItem(const std::string& new_name)
new_cat->rename(new_name);
new_cat->updateServer(FALSE);
model->updateCategory(new_cat);
+
model->notifyObservers();
}
// return FALSE because we either notified observers (& therefore
@@ -1774,45 +2275,78 @@ BOOL LLFolderBridge::removeItem()
{
return FALSE;
}
- // move it to the trash
- LLPreview::hide(mUUID);
- LLInventoryModel* model = mInventoryPanel->getModel();
- if(!model) return FALSE;
+ const LLViewerInventoryCategory *cat = getCategory();
+
+ LLSD payload;
+ LLSD args;
+ args["FOLDERNAME"] = cat->getName();
- LLUUID trash_id;
- trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ LLNotification::Params params("ConfirmDeleteProtectedCategory");
+ params.payload(payload).substitutions(args).functor.function(boost::bind(&LLFolderBridge::removeItemResponse, this, _1, _2));
+ LLNotifications::instance().forceResponse(params, 0);
+ return TRUE;
+}
- // Look for any gestures and deactivate them
- LLInventoryModel::cat_array_t descendent_categories;
- LLInventoryModel::item_array_t descendent_items;
- gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE );
- S32 i;
- for (i = 0; i < descendent_items.count(); i++)
+BOOL LLFolderBridge::removeSystemFolder()
+{
+ const LLViewerInventoryCategory *cat = getCategory();
+ if (!LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
{
- LLInventoryItem* item = descendent_items[i];
- if (item->getType() == LLAssetType::AT_GESTURE
- && gGestureManager.isGestureActive(item->getUUID()))
- {
- gGestureManager.deactivateGesture(item->getUUID());
- }
+ return FALSE;
}
- // go ahead and do the normal remove if no 'last calling
- // cards' are being removed.
- LLViewerInventoryCategory* cat = getCategory();
- if(cat)
+ LLSD payload;
+ LLSD args;
+ args["FOLDERNAME"] = cat->getName();
+
+ LLNotification::Params params("ConfirmDeleteProtectedCategory");
+ params.payload(payload).substitutions(args).functor.function(boost::bind(&LLFolderBridge::removeItemResponse, this, _1, _2));
{
- LLInvFVBridge::changeCategoryParent(model, cat, trash_id, TRUE);
+ LLNotifications::instance().add(params);
}
-
return TRUE;
}
-BOOL LLFolderBridge::isClipboardPasteable() const
+bool LLFolderBridge::removeItemResponse(const LLSD& notification, const LLSD& response)
{
- if(LLInventoryClipboard::instance().hasContents() && isAgentInventory())
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
+ // if they choose delete, do it. Otherwise, don't do anything
+ if(option == 0)
{
+ // move it to the trash
+ LLPreview::hide(mUUID);
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+
+ // Look for any gestures and deactivate them
+ LLInventoryModel::cat_array_t descendent_categories;
+ LLInventoryModel::item_array_t descendent_items;
+ gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE );
+
+ for (LLInventoryModel::item_array_t::const_iterator iter = descendent_items.begin();
+ iter != descendent_items.end();
+ ++iter)
+ {
+ const LLViewerInventoryItem* item = (*iter);
+ const LLUUID& item_id = item->getUUID();
+ if (item->getType() == LLAssetType::AT_GESTURE
+ && LLGestureManager::instance().isGestureActive(item_id))
+ {
+ LLGestureManager::instance().deactivateGesture(item_id);
+ }
+ }
+
+ // go ahead and do the normal remove if no 'last calling
+ // cards' are being removed.
+ LLViewerInventoryCategory* cat = getCategory();
+ if(cat)
+ {
+ LLInvFVBridge::changeCategoryParent(model, cat, trash_id, TRUE);
+ }
return TRUE;
}
return FALSE;
@@ -1820,25 +2354,77 @@ BOOL LLFolderBridge::isClipboardPasteable() const
void LLFolderBridge::pasteFromClipboard()
{
- LLInventoryModel* model = mInventoryPanel->getModel();
+ LLInventoryModel* model = getInventoryModel();
if(model && isClipboardPasteable())
{
- LLInventoryItem* item = NULL;
+ const LLUUID parent_id(mUUID);
+
LLDynamicArray<LLUUID> objects;
LLInventoryClipboard::instance().retrieve(objects);
- S32 count = objects.count();
- LLUUID parent_id(mUUID);
- for(S32 i = 0; i < count; i++)
+ for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin();
+ iter != objects.end();
+ ++iter)
{
- item = model->getItem(objects.get(i));
+ const LLUUID& item_id = (*iter);
+ LLInventoryItem *item = model->getItem(item_id);
if (item)
{
- copy_inventory_item(
+ if(LLInventoryClipboard::instance().isCutMode())
+ {
+ // move_inventory_item() is not enough,
+ //we have to update inventory locally too
+ changeItemParent(model, dynamic_cast<LLViewerInventoryItem*>(item), parent_id, FALSE);
+ }
+ else
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ parent_id,
+ std::string(),
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ }
+ }
+ }
+}
+
+void LLFolderBridge::pasteLinkFromClipboard()
+{
+ const LLInventoryModel* model = getInventoryModel();
+ if(model)
+ {
+ const LLUUID parent_id(mUUID);
+
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin();
+ iter != objects.end();
+ ++iter)
+ {
+ const LLUUID &object_id = (*iter);
+#if SUPPORT_ENSEMBLES
+ if (LLInventoryCategory *cat = model->getCategory(object_id))
+ {
+ link_inventory_item(
gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
+ cat->getUUID(),
parent_id,
- std::string(),
+ cat->getName(),
+ LLAssetType::AT_LINK_FOLDER,
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ else
+#endif
+ if (LLInventoryItem *item = model->getItem(object_id))
+ {
+ link_inventory_item(
+ gAgent.getID(),
+ item->getLinkedUUID(),
+ parent_id,
+ item->getName(),
+ LLAssetType::AT_LINK,
LLPointer<LLInventoryCallback>(NULL));
}
}
@@ -1855,19 +2441,27 @@ void LLFolderBridge::folderOptionsMenu()
{
std::vector<std::string> disabled_items;
- // *TODO: Translate
-
- LLInventoryModel* model = mInventoryPanel->getModel();
+ LLInventoryModel* model = getInventoryModel();
if(!model) return;
const LLInventoryCategory* category = model->getCategory(mUUID);
- bool is_default_folder = category &&
- (LLAssetType::AT_NONE != category->getPreferredType());
-
+ LLFolderType::EType type = category->getPreferredType();
+ const bool is_system_folder = category && LLFolderType::lookupIsProtectedType(type);
+ // BAP change once we're no longer treating regular categories as ensembles.
+ const bool is_ensemble = category && (type == LLFolderType::FT_NONE ||
+ LLFolderType::lookupIsEnsembleType(type));
+
// calling card related functionality for folders.
- // Only enable calling-card related options for non-default folders.
- if (!is_default_folder)
+ const bool is_sidepanel = isInOutfitsSidePanel();
+ if (is_sidepanel)
+ {
+ mItems.push_back("Rename");
+ mItems.push_back("Delete");
+ }
+
+ // Only enable calling-card related options for non-system folders.
+ if (!is_sidepanel && !is_system_folder)
{
LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard))
@@ -1877,7 +2471,14 @@ void LLFolderBridge::folderOptionsMenu()
mItems.push_back(std::string("IM All Contacts In Folder"));
}
}
-
+
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+ if (LLFolderType::lookupIsProtectedType(type))
+ {
+ mItems.push_back(std::string("Delete System Folder"));
+ }
+#endif
+
// wearables related functionality for folders.
//is_wearable
LLFindWearables is_wearable;
@@ -1889,17 +2490,37 @@ void LLFolderBridge::folderOptionsMenu()
checkFolderForContentsOfType(model, is_object) ||
checkFolderForContentsOfType(model, is_gesture) )
{
- mItems.push_back(std::string("Folder Wearables Separator"));
+ if (!is_sidepanel)
+ {
+ mItems.push_back(std::string("Folder Wearables Separator"));
+ }
- // Only enable add/replace outfit for non-default folders.
- if (!is_default_folder)
+ // Only enable add/replace outfit for non-system folders.
+ if (!is_system_folder)
{
- mItems.push_back(std::string("Add To Outfit"));
+ // Adding an outfit onto another (versus replacing) doesn't make sense.
+ if (type != LLFolderType::FT_OUTFIT)
+ {
+ mItems.push_back(std::string("Add To Outfit"));
+ }
mItems.push_back(std::string("Replace Outfit"));
}
- mItems.push_back(std::string("Take Off Items"));
+ if (is_ensemble)
+ {
+ mItems.push_back(std::string("Wear As Ensemble"));
+ }
+ mItems.push_back(std::string("Remove From Outfit"));
+ if (!areAnyContentsWorn(model))
+ {
+ disabled_items.push_back(std::string("Remove From Outfit"));
+ }
+ mItems.push_back(std::string("Outfit Separator"));
}
- hideContextEntries(*mMenu, mItems, disabled_items);
+ hide_context_entries(*mMenu, mItems, disabled_items);
+
+ // Reposition the menu, in case we're adding items to an existing menu.
+ mMenu->needsArrange();
+ mMenu->arrangeAndClear();
}
BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type)
@@ -1914,16 +2535,48 @@ BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInv
return ((item_array.count() > 0) ? TRUE : FALSE );
}
+class LLFindWorn : public LLInventoryCollectFunctor
+{
+public:
+ LLFindWorn() {}
+ virtual ~LLFindWorn() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item)
+ {
+ if (item && get_is_item_worn(item->getUUID()))
+ {
+ return TRUE;
+ }
+ return FALSE;
+ }
+};
+
+BOOL LLFolderBridge::areAnyContentsWorn(LLInventoryModel* model) const
+{
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ LLFindWorn is_worn;
+ model->collectDescendentsIf(mUUID,
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_worn);
+ return (item_array.size() > 0);
+}
+
// Flags unused
void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- // *TODO: Translate
+ mItems.clear();
+ mDisabledItems.clear();
+
lldebugs << "LLFolderBridge::buildContextMenu()" << llendl;
+
// std::vector<std::string> disabled_items;
- LLInventoryModel* model = mInventoryPanel->getModel();
+ LLInventoryModel* model = getInventoryModel();
if(!model) return;
- LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
- LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ const LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
if (lost_and_found_id == mUUID)
{
@@ -1950,39 +2603,46 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
else if(isAgentInventory()) // do not allow creating in library
{
- // only mature accounts can create undershirts/underwear
- /*if (!gAgent.isTeen())
+ LLViewerInventoryCategory *cat = getCategory();
+ // BAP removed protected check to re-enable standard ops in untyped folders.
+ // Not sure what the right thing is to do here.
+ if (!isCOFFolder() && cat && cat->getPreferredType()!=LLFolderType::FT_OUTFIT /*&&
+ LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())*/)
+ {
+ // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
+ if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
+ mItems.push_back(std::string("New Folder"));
+ mItems.push_back(std::string("New Script"));
+ mItems.push_back(std::string("New Note"));
+ mItems.push_back(std::string("New Gesture"));
+ mItems.push_back(std::string("New Clothes"));
+ mItems.push_back(std::string("New Body Parts"));
+ mItems.push_back(std::string("Change Type"));
+
+ LLViewerInventoryCategory *cat = getCategory();
+ if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
{
- sub_menu->append(new LLMenuItemCallGL("New Undershirt",
- &createNewUndershirt,
- NULL,
- (void*)this));
- sub_menu->append(new LLMenuItemCallGL("New Underpants",
- &createNewUnderpants,
- NULL,
- (void*)this));
- }*/
-
-/* BOOL contains_calling_cards = FALSE;
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
+ mDisabledItems.push_back(std::string("Change Type"));
+ }
- LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
- model->collectDescendentsIf(mUUID,
- cat_array,
- item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_callingcard);
- if(item_array.count() > 0) contains_calling_cards = TRUE;
-*/
- mItems.push_back(std::string("New Folder"));
- mItems.push_back(std::string("New Script"));
- mItems.push_back(std::string("New Note"));
- mItems.push_back(std::string("New Gesture"));
- mItems.push_back(std::string("New Clothes"));
- mItems.push_back(std::string("New Body Parts"));
+ getClipboardEntries(false, mItems, mDisabledItems, flags);
+ }
+ else
+ {
+ // Want some but not all of the items from getClipboardEntries for outfits.
+ if (cat && cat->getPreferredType()==LLFolderType::FT_OUTFIT)
+ {
+ mItems.push_back(std::string("Rename"));
+ mItems.push_back(std::string("Delete"));
- getClipboardEntries(false, mItems, mDisabledItems, flags);
+ // EXT-4030: disallow deletion of currently worn outfit
+ const LLViewerInventoryItem *base_outfit_link = LLAppearanceManager::instance().getBaseOutfitLink();
+ if (base_outfit_link && (cat == base_outfit_link->getLinkedCategory()))
+ {
+ mDisabledItems.push_back(std::string("Delete"));
+ }
+ }
+ }
//Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06
mCallingCards = mWearables = FALSE;
@@ -1992,7 +2652,7 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
mCallingCards=TRUE;
}
-
+
LLFindWearables is_wearable;
LLIsType is_object( LLAssetType::AT_OBJECT );
LLIsType is_gesture( LLAssetType::AT_GESTURE );
@@ -2003,14 +2663,17 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
mWearables=TRUE;
}
-
+
mMenu = &menu;
sSelf = this;
LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE);
LLInventoryFetchDescendentsObserver::folder_ref_t folders;
LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
- folders.push_back(category->getUUID());
+ if (category)
+ {
+ folders.push_back(category->getUUID());
+ }
fetch->fetchDescendents(folders);
inc_busy_count();
if(fetch->isEverythingComplete())
@@ -2030,12 +2693,19 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
mItems.push_back(std::string("--no options--"));
mDisabledItems.push_back(std::string("--no options--"));
}
- hideContextEntries(menu, mItems, mDisabledItems);
+
+ // Preemptively disable system folder removal if more than one item selected.
+ if ((flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ mDisabledItems.push_back(std::string("Delete System Folder"));
+ }
+
+ hide_context_entries(menu, mItems, mDisabledItems);
}
BOOL LLFolderBridge::hasChildren() const
{
- LLInventoryModel* model = mInventoryPanel->getModel();
+ LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
LLInventoryModel::EHasChildren has_children;
has_children = gInventory.categoryHasChildren(mUUID);
@@ -2050,26 +2720,33 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
BOOL accept = FALSE;
switch(cargo_type)
{
- case DAD_TEXTURE:
- case DAD_SOUND:
- case DAD_CALLINGCARD:
- case DAD_LANDMARK:
- case DAD_SCRIPT:
- case DAD_OBJECT:
- case DAD_NOTECARD:
- case DAD_CLOTHING:
- case DAD_BODYPART:
- case DAD_ANIMATION:
- case DAD_GESTURE:
- accept = dragItemIntoFolder((LLInventoryItem*)cargo_data,
- drop);
- break;
- case DAD_CATEGORY:
- accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data,
+ case DAD_TEXTURE:
+ case DAD_SOUND:
+ case DAD_CALLINGCARD:
+ case DAD_LANDMARK:
+ case DAD_SCRIPT:
+ case DAD_OBJECT:
+ case DAD_NOTECARD:
+ case DAD_CLOTHING:
+ case DAD_BODYPART:
+ case DAD_ANIMATION:
+ case DAD_GESTURE:
+ case DAD_LINK:
+ accept = dragItemIntoFolder((LLInventoryItem*)cargo_data,
drop);
- break;
- default:
- break;
+ break;
+ case DAD_CATEGORY:
+ if (LLFriendCardsManager::instance().isAnyFriendCategory(mUUID))
+ {
+ accept = FALSE;
+ }
+ else
+ {
+ accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, drop);
+ }
+ break;
+ default:
+ break;
}
return accept;
}
@@ -2077,7 +2754,7 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
LLViewerInventoryCategory* LLFolderBridge::getCategory() const
{
LLViewerInventoryCategory* cat = NULL;
- LLInventoryModel* model = mInventoryPanel->getModel();
+ LLInventoryModel* model = getInventoryModel();
if(model)
{
cat = (LLViewerInventoryCategory*)model->getCategory(mUUID);
@@ -2097,12 +2774,13 @@ void LLFolderBridge::createNewCategory(void* user_data)
{
LLFolderBridge* bridge = (LLFolderBridge*)user_data;
if(!bridge) return;
- LLInventoryPanel* panel = bridge->mInventoryPanel;
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(bridge->mInventoryPanel.get());
+ if (!panel) return;
LLInventoryModel* model = panel->getModel();
if(!model) return;
LLUUID id;
id = model->createNewCategory(bridge->getUUID(),
- LLAssetType::AT_NONE,
+ LLFolderType::FT_NONE,
LLStringUtil::null);
model->notifyObservers();
@@ -2187,9 +2865,9 @@ void LLFolderBridge::createWearable(LLFolderBridge* bridge, EWearableType type)
// Separate function so can be called by global menu as well as right-click
// menu.
// static
-void LLFolderBridge::createWearable(LLUUID parent_id, EWearableType type)
+void LLFolderBridge::createWearable(const LLUUID &parent_id, EWearableType type)
{
- LLWearable* wearable = gWearableList.createNewWearable(type);
+ LLWearable* wearable = LLWearableList::instance().createNewWearable(type);
LLAssetType::EType asset_type = wearable->getAssetType();
LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE;
create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
@@ -2201,12 +2879,14 @@ void LLFolderBridge::createWearable(LLUUID parent_id, EWearableType type)
void LLFolderBridge::modifyOutfit(BOOL append)
{
- LLInventoryModel* model = mInventoryPanel->getModel();
+ LLInventoryModel* model = getInventoryModel();
if(!model) return;
LLViewerInventoryCategory* cat = getCategory();
if(!cat) return;
-
- wear_inventory_category_on_avatar( cat, append );
+
+ // BAP - was:
+ // wear_inventory_category_on_avatar( cat, append );
+ LLAppearanceManager::instance().wearInventoryCategory( cat, FALSE, append );
}
// helper stuff
@@ -2214,7 +2894,7 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response
{
LLFloaterOpenObject::LLCatAndWear* cat_and_wear = (LLFloaterOpenObject::LLCatAndWear* )move_inv->mUserData;
LLViewerObject* object = gObjectList.findObject(move_inv->mObjectID);
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if(option == 0 && object)
{
@@ -2229,8 +2909,8 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response
}
two_uuids_list_t::iterator move_it;
- for (move_it = move_inv->mMoveList.begin();
- move_it != move_inv->mMoveList.end();
+ for (move_it = move_inv->mMoveList.begin();
+ move_it != move_inv->mMoveList.end();
++move_it)
{
object->moveInventory(move_it->first, move_it->second);
@@ -2252,8 +2932,8 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response
BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
BOOL drop)
{
- LLInventoryModel* model = mInventoryPanel->getModel();
- if(!model) return FALSE;
+ LLInventoryModel* model = getInventoryModel();
+ if(!model || !inv_item) return FALSE;
// cannot drag into library
if(!isAgentInventory())
@@ -2261,7 +2941,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
return FALSE;
}
- LLVOAvatar* avatar = gAgent.getAvatarObject();
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
if(!avatar) return FALSE;
LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
@@ -2271,65 +2951,123 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
{
BOOL is_movable = TRUE;
- switch( inv_item->getType() )
+ switch( inv_item->getActualType() )
{
- case LLAssetType::AT_ROOT_CATEGORY:
- is_movable = FALSE;
- break;
-
case LLAssetType::AT_CATEGORY:
- is_movable = ( LLAssetType::AT_NONE == ((LLInventoryCategory*)inv_item)->getPreferredType() );
+ is_movable = !LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)inv_item)->getPreferredType());
break;
default:
break;
}
- LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id);
+ const LLUUID current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
+ BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
+ BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
+
if(is_movable && move_is_into_trash)
{
- switch(inv_item->getType())
- {
- case LLAssetType::AT_CLOTHING:
- case LLAssetType::AT_BODYPART:
- is_movable = !gAgent.isWearingItem(inv_item->getUUID());
- break;
+ is_movable = inv_item->getIsLinkType() || !get_is_item_worn(inv_item->getUUID());
+ }
- case LLAssetType::AT_OBJECT:
- is_movable = !avatar->isWearingAttachment(inv_item->getUUID());
- break;
- default:
- break;
- }
+ if ( is_movable )
+ {
+ // Don't allow creating duplicates in the Calling Card/Friends
+ // subfolders, see bug EXT-1599. Check is item direct descendent
+ // of target folder and forbid item's movement if it so.
+ // Note: isItemDirectDescendentOfCategory checks if
+ // passed category is in the Calling Card/Friends folder
+ is_movable = ! LLFriendCardsManager::instance()
+ .isObjDirectDescendentOfCategory (inv_item, getCategory());
}
-
- accept = is_movable && (mUUID != inv_item->getParentUUID());
+
+ const LLUUID& favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+ const BOOL folder_allows_reorder = (mUUID == favorites_id);
+
+ // we can move item inside a folder only if this folder is Favorites. See EXT-719
+ accept = is_movable && ((mUUID != inv_item->getParentUUID()) || folder_allows_reorder);
if(accept && drop)
{
if (inv_item->getType() == LLAssetType::AT_GESTURE
- && gGestureManager.isGestureActive(inv_item->getUUID()) && move_is_into_trash)
+ && LLGestureManager::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash)
{
- gGestureManager.deactivateGesture(inv_item->getUUID());
+ LLGestureManager::instance().deactivateGesture(inv_item->getUUID());
}
// If an item is being dragged between windows, unselect
// everything in the active window so that we don't follow
// the selection to its new location (which is very
// annoying).
- if (LLInventoryView::getActiveInventory())
+ LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
+ if (active_panel)
{
- LLInventoryPanel* active_panel = LLInventoryView::getActiveInventory()->getPanel();
- if (active_panel && (mInventoryPanel != active_panel))
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ if (active_panel && (panel != active_panel))
{
active_panel->unSelectAll();
}
}
- // restamp if the move is into the trash.
- LLInvFVBridge::changeItemParent(
- model,
- (LLViewerInventoryItem*)inv_item,
- mUUID,
- move_is_into_trash);
+ // if dragging from/into favorites folder only reorder items
+ if ((mUUID == inv_item->getParentUUID()) && folder_allows_reorder)
+ {
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL;
+ if (itemp)
+ {
+ LLUUID srcItemId = inv_item->getUUID();
+ LLUUID destItemId = itemp->getListener()->getUUID();
+ gInventory.rearrangeFavoriteLandmarks(srcItemId, destItemId);
+ }
+ }
+ else if (favorites_id == mUUID) // if target is the favorites folder we use copy
+ {
+ // use callback to rearrange favorite landmarks after adding
+ // to have new one placed before target (on which it was dropped). See EXT-4312.
+ LLPointer<AddFavoriteLandmarkCallback> cb = new AddFavoriteLandmarkCallback();
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLFolderViewItem* drag_over_item = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL;
+ if (drag_over_item && drag_over_item->getListener())
+ {
+ cb.get()->setTargetLandmarkId(drag_over_item->getListener()->getUUID());
+ }
+
+ copy_inventory_item(
+ gAgent.getID(),
+ inv_item->getPermissions().getOwner(),
+ inv_item->getUUID(),
+ mUUID,
+ std::string(),
+ cb);
+ }
+ else if (move_is_into_current_outfit || move_is_into_outfit)
+ {
+ // BAP - should skip if dup.
+ if (move_is_into_current_outfit)
+ {
+ LLAppearanceManager::instance().addCOFItemLink(inv_item);
+ }
+ else
+ {
+ LLPointer<LLInventoryCallback> cb = NULL;
+ link_inventory_item(
+ gAgent.getID(),
+ inv_item->getLinkedUUID(),
+ mUUID,
+ inv_item->getName(),
+ LLAssetType::AT_LINK,
+ cb);
+ }
+ }
+ else
+ {
+ // restamp if the move is into the trash.
+ LLInvFVBridge::changeItemParent(
+ model,
+ (LLViewerInventoryItem*)inv_item,
+ mUUID,
+ move_is_into_trash);
+ }
}
}
else if(LLToolDragAndDrop::SOURCE_WORLD == source)
@@ -2351,7 +3089,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
&& perm.allowTransferTo(gAgent.getID())))
// || gAgent.isGodlike())
-
+
{
accept = TRUE;
}
@@ -2378,11 +3116,11 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
else
{
LLNotification::Params params("MoveInventoryFromObject");
- params.functor(boost::bind(move_task_inventory_callback, _1, _2, move_inv));
+ params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv));
LLNotifications::instance().forceResponse(params, 0);
}
}
-
+
}
else if(LLToolDragAndDrop::SOURCE_NOTECARD == source)
{
@@ -2431,59 +3169,88 @@ LLUIImagePtr LLScriptBridge::getIcon() const
// | LLTextureBridge |
// +=================================================+
-std::string LLTextureBridge::sPrefix("Texture: ");
-
-
LLUIImagePtr LLTextureBridge::getIcon() const
{
return get_item_icon(LLAssetType::AT_TEXTURE, mInvType, 0, FALSE);
}
+
+void LLTextureBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+}
+
+bool LLTextureBridge::canSaveTexture(void)
+{
+ const LLInventoryModel* model = getInventoryModel();
+ if(!model)
+ {
+ return false;
+ }
-void open_texture(const LLUUID& item_id,
- const std::string& title,
- BOOL show_keep_discard,
- const LLUUID& source_id,
- BOOL take_focus)
+ const LLViewerInventoryItem *item = model->getItem(mUUID);
+ if (item)
+ {
+ return item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED);
+ }
+ return false;
+}
+
+void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- // See if we can bring an exiting preview to the front
- if( !LLPreview::show( item_id, take_focus ) )
+ lldebugs << "LLTextureBridge::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+ if(isInTrash())
{
- // There isn't one, so make a new preview
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- LLRect rect = gSavedSettings.getRect("PreviewTextureRect");
- rect.translate( left - rect.mLeft, top - rect.mTop );
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
- LLPreviewTexture* preview;
- preview = new LLPreviewTexture("preview texture",
- rect,
- title,
- item_id,
- LLUUID::null,
- show_keep_discard);
- preview->setSourceID(source_id);
- if(take_focus) preview->setFocus(TRUE);
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Open"));
+ items.push_back(std::string("Properties"));
- gFloaterView->adjustToFitScreen(preview, FALSE);
+ getClipboardEntries(true, items, disabled_items, flags);
+
+ items.push_back(std::string("Texture Separator"));
+ items.push_back(std::string("Save As"));
+ if (!canSaveTexture())
+ {
+ disabled_items.push_back(std::string("Save As"));
+ }
}
+ hide_context_entries(menu, items, disabled_items);
}
-void LLTextureBridge::openItem()
+// virtual
+void LLTextureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
{
- LLViewerInventoryItem* item = getItem();
- if(item)
+ if ("save_as" == action)
{
- open_texture(mUUID, getPrefix() + item->getName(), FALSE);
+ LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES);
+ LLPreviewTexture* preview_texture = LLFloaterReg::findTypedInstance<LLPreviewTexture>("preview_texture", mUUID);
+ if (preview_texture)
+ {
+ preview_texture->openToSave();
+ }
}
+ else LLItemBridge::performAction(folder, model, action);
}
// +=================================================+
// | LLSoundBridge |
// +=================================================+
-std::string LLSoundBridge::sPrefix("Sound: ");
-
-
LLUIImagePtr LLSoundBridge::getIcon() const
{
return get_item_icon(LLAssetType::AT_SOUND, LLInventoryType::IT_SOUND, 0, FALSE);
@@ -2491,6 +3258,13 @@ LLUIImagePtr LLSoundBridge::getIcon() const
void LLSoundBridge::openItem()
{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+/*
// Changed this back to the way it USED to work:
// only open the preview dialog through the contextual right-click menu
// double-click just plays the sound
@@ -2501,18 +3275,7 @@ void LLSoundBridge::openItem()
openSoundPreview((void*)this);
//send_uuid_sound_trigger(item->getAssetUUID(), 1.0);
}
-
-// if(!LLPreview::show(mUUID))
-// {
-// S32 left, top;
-// gFloaterView->getNewFloaterPosition(&left, &top);
-// LLRect rect = gSavedSettings.getRect("PreviewSoundRect");
-// rect.translate(left - rect.mLeft, top - rect.mTop);
-// new LLPreviewSound("preview sound",
-// rect,
-// getPrefix() + getName(),
-// mUUID));
-// }
+*/
}
void LLSoundBridge::previewItem()
@@ -2527,29 +3290,15 @@ void LLSoundBridge::previewItem()
void LLSoundBridge::openSoundPreview(void* which)
{
LLSoundBridge *me = (LLSoundBridge *)which;
- if(!LLPreview::show(me->mUUID))
- {
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- LLRect rect = gSavedSettings.getRect("PreviewSoundRect");
- rect.translate(left - rect.mLeft, top - rect.mTop);
- LLPreviewSound* preview = new LLPreviewSound("preview sound",
- rect,
- me->getPrefix() + me->getName(),
- me->mUUID);
- preview->setFocus(TRUE);
- // Keep entirely onscreen.
- gFloaterView->adjustToFitScreen(preview, FALSE);
- }
+ LLFloaterReg::showInstance("preview_sound", LLSD(me->mUUID), TAKE_FOCUS_YES);
}
void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- lldebugs << "LLTextureBridge::buildContextMenu()" << llendl;
+ lldebugs << "LLSoundBridge::buildContextMenu()" << llendl;
std::vector<std::string> items;
std::vector<std::string> disabled_items;
- // *TODO: Translate
if(isInTrash())
{
items.push_back(std::string("Purge Item"));
@@ -2571,14 +3320,22 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
items.push_back(std::string("Sound Separator"));
items.push_back(std::string("Sound Play"));
- hideContextEntries(menu, items, disabled_items);
+ hide_context_entries(menu, items, disabled_items);
}
// +=================================================+
// | LLLandmarkBridge |
// +=================================================+
-std::string LLLandmarkBridge::sPrefix("Landmark: ");
+LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags/* = 0x00*/) :
+LLItemBridge(inventory, uuid)
+{
+ mVisited = FALSE;
+ if (flags & LLInventoryItem::II_FLAGS_LANDMARK_VISITED)
+ {
+ mVisited = TRUE;
+ }
+}
LLUIImagePtr LLLandmarkBridge::getIcon() const
{
@@ -2590,7 +3347,6 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
std::vector<std::string> items;
std::vector<std::string> disabled_items;
- // *TODO: Translate
lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl;
if(isInTrash())
{
@@ -2611,10 +3367,31 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
items.push_back(std::string("Landmark Separator"));
- items.push_back(std::string("Teleport To Landmark"));
+ items.push_back(std::string("About Landmark"));
- hideContextEntries(menu, items, disabled_items);
+ // Disable "About Landmark" menu item for
+ // multiple landmarks selected. Only one landmark
+ // info panel can be shown at a time.
+ if ((flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("About Landmark"));
+ }
+
+ hide_context_entries(menu, items, disabled_items);
+}
+// Convenience function for the two functions below.
+void teleport_via_landmark(const LLUUID& asset_id)
+{
+ gAgent.teleportViaLandmark( asset_id );
+
+ // we now automatically track the landmark you're teleporting to
+ // because you'll probably arrive at a telehub instead
+ LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance();
+ if( floater_world_map )
+ {
+ floater_world_map->trackLandmark( asset_id );
+ }
}
// virtual
@@ -2625,71 +3402,35 @@ void LLLandmarkBridge::performAction(LLFolderView* folder, LLInventoryModel* mod
LLViewerInventoryItem* item = getItem();
if(item)
{
- gAgent.teleportViaLandmark(item->getAssetUUID());
-
- // we now automatically track the landmark you're teleporting to
- // because you'll probably arrive at a telehub instead
- if( gFloaterWorldMap )
- {
- gFloaterWorldMap->trackLandmark( item->getAssetUUID() );
- }
+ teleport_via_landmark(item->getAssetUUID());
}
}
- if ("about" == action)
+ else if ("about" == action)
{
LLViewerInventoryItem* item = getItem();
if(item)
{
- open_landmark(item, std::string(" ") + getPrefix() + item->getName(), FALSE);
+ LLSD key;
+ key["type"] = "landmark";
+ key["id"] = item->getUUID();
+
+ LLSideTray::getInstance()->showPanel("panel_places", key);
}
}
- else LLItemBridge::performAction(folder, model, action);
-}
-
-void open_landmark(LLViewerInventoryItem* inv_item,
- const std::string& title,
- BOOL show_keep_discard,
- const LLUUID& source_id,
- BOOL take_focus)
-{
- // See if we can bring an exiting preview to the front
- if( !LLPreview::show( inv_item->getUUID(), take_focus ) )
+ else
{
- // There isn't one, so make a new preview
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- LLRect rect = gSavedSettings.getRect("PreviewLandmarkRect");
- rect.translate( left - rect.mLeft, top - rect.mTop );
-
- LLPreviewLandmark* preview = new LLPreviewLandmark(title,
- rect,
- title,
- inv_item->getUUID(),
- show_keep_discard,
- inv_item);
- preview->setSourceID(source_id);
- if(take_focus) preview->setFocus(TRUE);
- // keep onscreen
- gFloaterView->adjustToFitScreen(preview, FALSE);
+ LLItemBridge::performAction(folder, model, action);
}
}
static bool open_landmark_callback(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLUUID asset_id = notification["payload"]["asset_id"].asUUID();
if (option == 0)
{
- // HACK: This is to demonstrate teleport on double click for landmarks
- gAgent.teleportViaLandmark( asset_id );
-
- // we now automatically track the landmark you're teleporting to
- // because you'll probably arrive at a telehub instead
- if( gFloaterWorldMap )
- {
- gFloaterWorldMap->trackLandmark( asset_id );
- }
+ teleport_via_landmark(asset_id);
}
return false;
@@ -2700,15 +3441,23 @@ static LLNotificationFunctorRegistration open_landmark_callback_reg("TeleportFro
void LLLandmarkBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+/*
+ LLViewerInventoryItem* item = getItem();
if( item )
{
// Opening (double-clicking) a landmark immediately teleports,
// but warns you the first time.
- // open_landmark(item, std::string(" ") + getPrefix() + item->getName(), FALSE);
+ // open_landmark(item);
LLSD payload;
payload["asset_id"] = item->getAssetUUID();
- LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload);
+ LLNotificationsUtil::add("TeleportFromLandmark", LLSD(), payload);
}
+*/
}
@@ -2724,8 +3473,6 @@ void LLCallingCardObserver::changed(U32 mask)
// | LLCallingCardBridge |
// +=================================================+
-std::string LLCallingCardBridge::sPrefix("Calling Card: ");
-
LLCallingCardBridge::LLCallingCardBridge( LLInventoryPanel* inventory, const LLUUID& uuid ) :
LLItemBridge(inventory, uuid)
{
@@ -2741,7 +3488,8 @@ LLCallingCardBridge::~LLCallingCardBridge()
void LLCallingCardBridge::refreshFolderViewItem()
{
- LLFolderViewItem* itemp = mInventoryPanel->getRootFolder()->getItemByID(mUUID);
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL;
if (itemp)
{
itemp->refresh();
@@ -2757,8 +3505,13 @@ void LLCallingCardBridge::performAction(LLFolderView* folder, LLInventoryModel*
if (item && (item->getCreatorUUID() != gAgent.getID()) &&
(!item->getCreatorUUID().isNull()))
{
- gIMMgr->setFloaterOpen(TRUE);
- gIMMgr->addSession(item->getName(), IM_NOTHING_SPECIAL, item->getCreatorUUID());
+ std::string callingcard_name;
+ gCacheName->getFullName(item->getCreatorUUID(), callingcard_name);
+ LLUUID session_id = gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID());
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
}
}
else if ("lure" == action)
@@ -2767,7 +3520,7 @@ void LLCallingCardBridge::performAction(LLFolderView* folder, LLInventoryModel*
if (item && (item->getCreatorUUID() != gAgent.getID()) &&
(!item->getCreatorUUID().isNull()))
{
- handle_lure(item->getCreatorUUID());
+ LLAvatarActions::offerTeleport(item->getCreatorUUID());
}
}
else LLItemBridge::performAction(folder, model, action);
@@ -2800,17 +3553,22 @@ std::string LLCallingCardBridge::getLabelSuffix() const
void LLCallingCardBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+/*
+ LLViewerInventoryItem* item = getItem();
if(item && !item->getCreatorUUID().isNull())
{
- BOOL online;
- online = LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID());
- LLFloaterAvatarInfo::showFromFriend(item->getCreatorUUID(), online);
+ LLAvatarActions::showProfile(item->getCreatorUUID());
}
+*/
}
void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- // *TODO: Translate
lldebugs << "LLCallingCardBridge::buildContextMenu()" << llendl;
std::vector<std::string> items;
std::vector<std::string> disabled_items;
@@ -2852,7 +3610,7 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
disabled_items.push_back(std::string("Conference Chat"));
}
}
- hideContextEntries(menu, items, disabled_items);
+ hide_context_entries(menu, items, disabled_items);
}
BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
@@ -2931,68 +3689,27 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
// | LLNotecardBridge |
// +=================================================+
-std::string LLNotecardBridge::sPrefix("Note: ");
-
-
LLUIImagePtr LLNotecardBridge::getIcon() const
{
return get_item_icon(LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, 0, FALSE);
}
-void open_notecard(LLViewerInventoryItem* inv_item,
- const std::string& title,
- const LLUUID& object_id,
- BOOL show_keep_discard,
- const LLUUID& source_id,
- BOOL take_focus)
-{
- // See if we can bring an existing preview to the front
- if(!LLPreview::show(inv_item->getUUID(), take_focus))
- {
- // There isn't one, so make a new preview
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- LLRect rect = gSavedSettings.getRect("NotecardEditorRect");
- rect.translate(left - rect.mLeft, top - rect.mTop);
- LLPreviewNotecard* preview;
- preview = new LLPreviewNotecard("preview notecard", rect, title,
- inv_item->getUUID(), object_id, inv_item->getAssetUUID(),
- show_keep_discard, inv_item);
- preview->setSourceID(source_id);
- if(take_focus) preview->setFocus(TRUE);
- // Force to be entirely onscreen.
- gFloaterView->adjustToFitScreen(preview, FALSE);
-
- //if (source_id.notNull())
- //{
- // // look for existing tabbed view for content from same source
- // LLPreview* existing_preview = LLPreview::getPreviewForSource(source_id);
- // if (existing_preview)
- // {
- // // found existing preview from this source
- // // is it already hosted in a multi-preview window?
- // LLMultiPreview* preview_hostp = (LLMultiPreview*)existing_preview->getHost();
- // if (!preview_hostp)
- // {
- // // create new multipreview if it doesn't exist
- // LLMultiPreview* preview_hostp = new LLMultiPreview(existing_preview->getRect());
- // preview_hostp->addFloater(existing_preview);
- // }
- // // add this preview to existing host
- // preview_hostp->addFloater(preview);
- // }
- //}
- }
-}
-
-
void LLNotecardBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+
+/*
+ LLViewerInventoryItem* item = getItem();
if (item)
{
- open_notecard(item, getPrefix() + item->getName(), LLUUID::null, FALSE);
+ LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES);
}
+*/
}
@@ -3000,8 +3717,6 @@ void LLNotecardBridge::openItem()
// | LLGestureBridge |
// +=================================================+
-std::string LLGestureBridge::sPrefix("Gesture: ");
-
LLUIImagePtr LLGestureBridge::getIcon() const
{
return get_item_icon(LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, 0, FALSE);
@@ -3009,7 +3724,7 @@ LLUIImagePtr LLGestureBridge::getIcon() const
LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const
{
- if( gGestureManager.isGestureActive(mUUID) )
+ if( LLGestureManager::instance().isGestureActive(mUUID) )
{
return LLFontGL::BOLD;
}
@@ -3021,7 +3736,7 @@ LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const
std::string LLGestureBridge::getLabelSuffix() const
{
- if( gGestureManager.isGestureActive(mUUID) )
+ if( LLGestureManager::instance().isGestureActive(mUUID) )
{
return LLItemBridge::getLabelSuffix() + " (active)";
}
@@ -3034,9 +3749,9 @@ std::string LLGestureBridge::getLabelSuffix() const
// virtual
void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
{
- if ("activate" == action)
+ if (isAddAction(action))
{
- gGestureManager.activateGesture(mUUID);
+ LLGestureManager::instance().activateGesture(mUUID);
LLViewerInventoryItem* item = gInventory.getItem(mUUID);
if (!item) return;
@@ -3046,9 +3761,9 @@ void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* mode
gInventory.updateItem(item);
gInventory.notifyObservers();
}
- else if ("deactivate" == action)
+ else if (isRemoveAction(action))
{
- gGestureManager.deactivateGesture(mUUID);
+ LLGestureManager::instance().deactivateGesture(mUUID);
LLViewerInventoryItem* item = gInventory.getItem(mUUID);
if (!item) return;
@@ -3064,34 +3779,47 @@ void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* mode
void LLGestureBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
- if (!item) return;
- // See if we can bring an existing preview to the front
- if(!LLPreview::show(mUUID))
+ if (item)
{
- LLUUID item_id = mUUID;
- std::string title = getPrefix() + item->getName();
- LLUUID object_id = LLUUID::null;
-
- // TODO: save the rectangle
- LLPreviewGesture* preview = LLPreviewGesture::show(title, item_id, object_id);
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+/*
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null);
preview->setFocus(TRUE);
-
- // Force to be entirely onscreen.
- gFloaterView->adjustToFitScreen(preview, FALSE);
}
+*/
}
BOOL LLGestureBridge::removeItem()
{
- // Force close the preview window, if it exists
- gGestureManager.deactivateGesture(mUUID);
+ // Grab class information locally since *this may be deleted
+ // within this function. Not a great pattern...
+ const LLInventoryModel* model = getInventoryModel();
+ if(!model)
+ {
+ return FALSE;
+ }
+ const LLUUID item_id = mUUID;
+
+ // This will also force close the preview window, if it exists.
+ // This may actually delete *this, if mUUID is in the COF.
+ LLGestureManager::instance().deactivateGesture(item_id);
+
+ // If deactivateGesture deleted *this, then return out immediately.
+ if (!model->getObject(item_id))
+ {
+ return TRUE;
+ }
+
return LLItemBridge::removeItem();
}
void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- // *TODO: Translate
lldebugs << "LLGestureBridge::buildContextMenu()" << llendl;
std::vector<std::string> items;
std::vector<std::string> disabled_items;
@@ -3107,34 +3835,33 @@ void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
else
{
- items.push_back(std::string("Open"));
- items.push_back(std::string("Properties"));
+ bool is_sidepanel = isInOutfitsSidePanel();
+
+ if (!is_sidepanel)
+ {
+ items.push_back(std::string("Open"));
+ items.push_back(std::string("Properties"));
+ }
getClipboardEntries(true, items, disabled_items, flags);
items.push_back(std::string("Gesture Separator"));
- items.push_back(std::string("Activate"));
- items.push_back(std::string("Deactivate"));
-
- /*menu.append(new LLMenuItemCallGL("Activate",
- handleActivateGesture,
- enableActivateGesture,
- (void*)this));
- menu.append(new LLMenuItemCallGL("Deactivate",
- handleDeactivateGesture,
- enableDeactivateGesture,
- (void*)this));*/
+ if (LLGestureManager::instance().isGestureActive(getUUID()))
+ {
+ items.push_back(std::string("Deactivate"));
+ }
+ else
+ {
+ items.push_back(std::string("Activate"));
+ }
}
- hideContextEntries(menu, items, disabled_items);
+ hide_context_entries(menu, items, disabled_items);
}
// +=================================================+
// | LLAnimationBridge |
// +=================================================+
-std::string LLAnimationBridge::sPrefix("Animation: ");
-
-
LLUIImagePtr LLAnimationBridge::getIcon() const
{
return get_item_icon(LLAssetType::AT_ANIMATION, LLInventoryType::IT_ANIMATION, 0, FALSE);
@@ -3142,7 +3869,6 @@ LLUIImagePtr LLAnimationBridge::getIcon() const
void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- // *TODO: Translate
std::vector<std::string> items;
std::vector<std::string> disabled_items;
@@ -3169,39 +3895,25 @@ void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
items.push_back(std::string("Animation Play"));
items.push_back(std::string("Animation Audition"));
- hideContextEntries(menu, items, disabled_items);
+ hide_context_entries(menu, items, disabled_items);
}
// virtual
void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
{
- S32 activate = 0;
-
if ((action == "playworld") || (action == "playlocal"))
{
-
- if ("playworld" == action) activate = 1;
- if ("playlocal" == action) activate = 2;
-
- // See if we can bring an existing preview to the front
- if( !LLPreview::show( mUUID ) )
+ if (getItem())
{
- // There isn't one, so make a new preview
- LLViewerInventoryItem* item = getItem();
- if( item )
+ LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE;
+ if ("playworld" == action) activate = LLPreviewAnim::PLAY;
+ if ("playlocal" == action) activate = LLPreviewAnim::AUDITION;
+
+ LLPreviewAnim* preview = LLFloaterReg::showTypedInstance<LLPreviewAnim>("preview_anim", LLSD(mUUID));
+ if (preview)
{
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- LLRect rect = gSavedSettings.getRect("PreviewAnimRect");
- rect.translate( left - rect.mLeft, top - rect.mTop );
- LLPreviewAnim* preview = new LLPreviewAnim("preview anim",
- rect,
- getPrefix() + item->getName(),
- mUUID,
- activate);
- // Force to be entirely onscreen.
- gFloaterView->adjustToFitScreen(preview, FALSE);
+ preview->activate(activate);
}
}
}
@@ -3213,27 +3925,19 @@ void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* mo
void LLAnimationBridge::openItem()
{
- // See if we can bring an existing preview to the front
- if( !LLPreview::show( mUUID ) )
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
{
- // There isn't one, so make a new preview
- LLViewerInventoryItem* item = getItem();
- if( item )
- {
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- LLRect rect = gSavedSettings.getRect("PreviewAnimRect");
- rect.translate( left - rect.mLeft, top - rect.mTop );
- LLPreviewAnim* preview = new LLPreviewAnim("preview anim",
- rect,
- getPrefix() + item->getName(),
- mUUID,
- 0);
- preview->setFocus(TRUE);
- // Force to be entirely onscreen.
- gFloaterView->adjustToFitScreen(preview, FALSE);
- }
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
}
+/*
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+*/
}
// +=================================================+
@@ -3241,17 +3945,14 @@ void LLAnimationBridge::openItem()
// +=================================================+
// static
-std::string LLObjectBridge::sPrefix("Object: ");
-
-// static
LLUUID LLObjectBridge::sContextMenuItemID;
-BOOL LLObjectBridge::isItemRemovable()
+LLObjectBridge::LLObjectBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type, U32 flags) :
+LLItemBridge(inventory, uuid), mInvType(type)
{
- LLVOAvatar* avatar = gAgent.getAvatarObject();
- if(!avatar) return FALSE;
- if(avatar->isWearingAttachment(mUUID)) return FALSE;
- return LLInvFVBridge::isItemRemovable();
+ mAttachPt = (flags & 0xff); // low bye of inventory flags
+
+ mIsMultiObject = ( flags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ? TRUE: FALSE;
}
LLUIImagePtr LLObjectBridge::getIcon() const
@@ -3259,17 +3960,26 @@ LLUIImagePtr LLObjectBridge::getIcon() const
return get_item_icon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject );
}
-void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment);
+LLInventoryObject* LLObjectBridge::getObject() const
+{
+ LLInventoryObject* object = NULL;
+ LLInventoryModel* model = getInventoryModel();
+ if(model)
+ {
+ object = (LLInventoryObject*)model->getObject(mUUID);
+ }
+ return object;
+}
// virtual
void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
{
- if ("attach" == action)
+ if (isAddAction(action))
{
LLUUID object_id = mUUID;
LLViewerInventoryItem* item;
item = (LLViewerInventoryItem*)gInventory.getItem(object_id);
- if(item && gInventory.isObjectDescendentOf(object_id, gAgent.getInventoryRootID()))
+ if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID()))
{
rez_attachment(item, NULL);
}
@@ -3287,62 +3997,75 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model
}
gFocusMgr.setKeyboardFocus(NULL);
}
- else if ("detach" == action)
+ else if (isRemoveAction(action))
{
LLInventoryItem* item = gInventory.getItem(mUUID);
- if( item )
+ if(item)
{
gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
- gMessageSystem->nextBlockFast(_PREHASH_ObjectData );
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
- gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getUUID() );
-
- gMessageSystem->sendReliable( gAgent.getRegion()->getHost() );
+ gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID());
+ gMessageSystem->sendReliable( gAgent.getRegion()->getHost());
}
// this object might have been selected, so let the selection manager know it's gone now
- LLViewerObject *found_obj =
- gObjectList.findObject(item->getUUID());
+ LLViewerObject *found_obj = gObjectList.findObject(item->getLinkedUUID());
if (found_obj)
{
LLSelectMgr::getInstance()->remove(found_obj);
}
- else
- {
- llwarns << "object not found - ignoring" << llendl;
- }
}
else LLItemBridge::performAction(folder, model, action);
}
void LLObjectBridge::openItem()
{
- /* Disabled -- this preview isn't useful. JC */
- // CP: actually, this code is required - made changes to match LLAnimationBridge::openItem() idiom
- // The properties preview is useful, converting to show object properties. - DaveP
- LLShowProps::showProperties(mUUID);
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+
+ LLSD key;
+ key["id"] = mUUID;
+ LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
+
+ // Disable old properties floater; this is replaced by the sidepanel.
+ /*
+ LLFloaterReg::showInstance("properties", mUUID);
+ */
}
LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const
-{
- LLVOAvatar* avatar = gAgent.getAvatarObject();
- if( avatar && avatar->isWearingAttachment( mUUID ) )
+{
+ U8 font = LLFontGL::NORMAL;
+
+ if(get_is_item_worn( mUUID ) )
{
- return LLFontGL::BOLD;
+ font |= LLFontGL::BOLD;
}
- else
+
+ LLInventoryItem* item = getItem();
+ if (item && item->getIsLinkType())
{
- return LLFontGL::NORMAL;
+ font |= LLFontGL::ITALIC;
}
+
+ return (LLFontGL::StyleFlags)font;
}
std::string LLObjectBridge::getLabelSuffix() const
{
- LLVOAvatar* avatar = gAgent.getAvatarObject();
- if( avatar && avatar->isWearingAttachment( mUUID ) )
+ if (get_is_item_worn(mUUID))
{
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
std::string attachment_point_name = avatar->getAttachedPointName(mUUID);
- LLStringUtil::toLower(attachment_point_name);
- return LLItemBridge::getLabelSuffix() + std::string(" (worn on ") + attachment_point_name + std::string(")");
+
+ // e.g. "(worn on ...)" / "(attached to ...)"
+ LLStringUtil::format_map_t args;
+ args["[ATTACHMENT_POINT]"] = attachment_point_name.c_str();
+ return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args);
}
else
{
@@ -3353,7 +4076,7 @@ std::string LLObjectBridge::getLabelSuffix() const
void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment)
{
LLSD payload;
- payload["item_id"] = item->getUUID();
+ payload["item_id"] = item->getLinkedUUID(); // Wear the base object in case this is a link.
S32 attach_pt = 0;
if (gAgent.getAvatarObject() && attachment)
@@ -3371,11 +4094,13 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach
payload["attachment_point"] = attach_pt;
- if (attachment && attachment->getObject())
+#if !ENABLE_MULTIATTACHMENTS
+ if (attachment && attachment->getNumObjects() > 0)
{
- LLNotifications::instance().add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez);
+ LLNotificationsUtil::add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez);
}
else
+#endif
{
LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/);
}
@@ -3383,11 +4108,21 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach
bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ LLVOAvatar *avatarp = gAgent.getAvatarObject();
+
+ if (!avatarp->canAttachMoreObjects())
+ {
+ LLSD args;
+ args["MAX_ATTACHMENTS"] = llformat("%d", MAX_AGENT_ATTACHMENTS);
+ LLNotificationsUtil::add("MaxAttachmentsOnOutfit", args);
+ return false;
+ }
+
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0/*YES*/)
{
LLViewerInventoryItem* itemp = gInventory.getItem(notification["payload"]["item_id"].asUUID());
-
+
if (itemp)
{
LLMessageSystem* msg = gMessageSystem;
@@ -3398,7 +4133,11 @@ bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& respon
msg->nextBlockFast(_PREHASH_ObjectData);
msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID());
msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner());
- msg->addU8Fast(_PREHASH_AttachmentPt, notification["payload"]["attachment_point"].asInteger());
+ U8 attachment_pt = notification["payload"]["attachment_point"].asInteger();
+#if ENABLE_MULTIATTACHMENTS
+ attachment_pt |= ATTACHMENT_ADD;
+#endif
+ msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt);
pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions());
msg->addStringFast(_PREHASH_Name, itemp->getName());
msg->addStringFast(_PREHASH_Description, itemp->getDescription());
@@ -3411,7 +4150,6 @@ static LLNotificationFunctorRegistration confirm_replace_attachment_rez_reg("Rep
void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- // *TODO: Translate
std::vector<std::string> items;
std::vector<std::string> disabled_items;
if(isInTrash())
@@ -3426,27 +4164,31 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
else
{
- items.push_back(std::string("Properties"));
+ bool is_sidepanel = isInOutfitsSidePanel();
+
+ if (!is_sidepanel)
+ {
+ items.push_back(std::string("Properties"));
+ }
getClipboardEntries(true, items, disabled_items, flags);
LLObjectBridge::sContextMenuItemID = mUUID;
- LLInventoryItem* item = getItem();
+ LLInventoryItem *item = getItem();
if(item)
{
- LLVOAvatar *avatarp = gAgent.getAvatarObject();
+ LLVOAvatarSelf* avatarp = gAgent.getAvatarObject();
if( !avatarp )
{
return;
}
-
- if( avatarp->isWearingAttachment( mUUID ) )
+
+ if( get_is_item_worn( mUUID ) )
{
items.push_back(std::string("Detach From Yourself"));
}
- else
- if( !isInTrash() )
+ else if (!isInTrash() && !isLinkedObjectInTrash() && !isLinkedObjectMissing())
{
items.push_back(std::string("Attach Separator"));
items.push_back(std::string("Object Wear"));
@@ -3455,52 +4197,61 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
// commented out for DEV-32347
//items.push_back(std::string("Restore to Last Position"));
- LLMenuGL* attach_menu = menu.getChildMenuByName("Attach To", TRUE);
- LLMenuGL* attach_hud_menu = menu.getChildMenuByName("Attach To HUD", TRUE);
+ if (!avatarp->canAttachMoreObjects())
+ {
+ disabled_items.push_back(std::string("Object Wear"));
+ disabled_items.push_back(std::string("Attach To"));
+ disabled_items.push_back(std::string("Attach To HUD"));
+ }
+ LLMenuGL* attach_menu = menu.findChildMenuByName("Attach To", TRUE);
+ LLMenuGL* attach_hud_menu = menu.findChildMenuByName("Attach To HUD", TRUE);
LLVOAvatar *avatarp = gAgent.getAvatarObject();
- if (attach_menu && (attach_menu->getChildCount() == 0) &&
- attach_hud_menu && (attach_hud_menu->getChildCount() == 0) &&
- avatarp)
+ if (attach_menu
+ && (attach_menu->getChildCount() == 0)
+ && attach_hud_menu
+ && (attach_hud_menu->getChildCount() == 0)
+ && avatarp)
{
- for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
+ for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
iter != avatarp->mAttachmentPoints.end(); )
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
- LLMenuItemCallGL *new_item;
- if (attachment->getIsHUDAttachment())
+ LLMenuItemCallGL::Params p;
+ std::string submenu_name = attachment->getName();
+ if (LLTrans::getString(submenu_name) != "")
{
- attach_hud_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(),
- NULL, //&LLObjectBridge::attachToAvatar,
- NULL, &attach_label, (void*)attachment));
+ p.name = (" ")+LLTrans::getString(submenu_name)+" ";
}
else
{
- attach_menu->append(new_item = new LLMenuItemCallGL(attachment->getName(),
- NULL, //&LLObjectBridge::attachToAvatar,
- NULL, &attach_label, (void*)attachment));
- }
-
- LLSimpleListener* callback = mInventoryPanel->getListenerByName("Inventory.AttachObject");
-
- if (callback)
- {
- new_item->addListener(callback, "on_click", LLSD(attachment->getName()));
+ p.name = submenu_name;
}
+ LLSD cbparams;
+ cbparams["index"] = curiter->first;
+ cbparams["label"] = attachment->getName();
+ p.on_click.function_name = "Inventory.AttachObject";
+ p.on_click.parameter = LLSD(attachment->getName());
+ p.on_enable.function_name = "Attachment.Label";
+ p.on_enable.parameter = cbparams;
+ LLView* parent = attachment->getIsHUDAttachment() ? attach_hud_menu : attach_menu;
+ LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent);
}
}
}
}
}
- hideContextEntries(menu, items, disabled_items);
+ hide_context_entries(menu, items, disabled_items);
}
BOOL LLObjectBridge::renameItem(const std::string& new_name)
{
- if(!isItemRenameable()) return FALSE;
- LLPreview::rename(mUUID, getPrefix() + new_name);
- LLInventoryModel* model = mInventoryPanel->getModel();
- if(!model) return FALSE;
+ if(!isItemRenameable())
+ return FALSE;
+ LLPreview::dirty(mUUID);
+ LLInventoryModel* model = getInventoryModel();
+ if(!model)
+ return FALSE;
LLViewerInventoryItem* item = getItem();
if(item && (item->getName() != new_name))
{
@@ -3509,9 +4260,10 @@ BOOL LLObjectBridge::renameItem(const std::string& new_name)
buildDisplayName(new_item, mDisplayName);
new_item->updateServer(FALSE);
model->updateItem(new_item);
+
model->notifyObservers();
- LLVOAvatar* avatar = gAgent.getAvatarObject();
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
if( avatar )
{
LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() );
@@ -3533,8 +4285,6 @@ BOOL LLObjectBridge::renameItem(const std::string& new_name)
// | LLLSLTextBridge |
// +=================================================+
-std::string LLLSLTextBridge::sPrefix("Script: ");
-
LLUIImagePtr LLLSLTextBridge::getIcon() const
{
return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE);
@@ -3542,27 +4292,19 @@ LLUIImagePtr LLLSLTextBridge::getIcon() const
void LLLSLTextBridge::openItem()
{
- // See if we can bring an exiting preview to the front
- if(!LLPreview::show(mUUID))
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
{
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- // There isn't one, so make a new preview
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- LLRect rect = gSavedSettings.getRect("PreviewScriptRect");
- rect.translate(left - rect.mLeft, top - rect.mTop);
-
- LLPreviewLSL* preview = new LLPreviewLSL("preview lsl text",
- rect,
- getPrefix() + item->getName(),
- mUUID);
- preview->setFocus(TRUE);
- // keep onscreen
- gFloaterView->adjustToFitScreen(preview, FALSE);
- }
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+ /*
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES);
}
+ */
}
// +=================================================+
@@ -3576,631 +4318,64 @@ void wear_inventory_item_on_avatar( LLInventoryItem* item )
{
lldebugs << "wear_inventory_item_on_avatar( " << item->getName()
<< " )" << llendl;
-
- gWearableList.getAsset(item->getAssetUUID(),
- item->getName(),
- item->getType(),
- LLWearableBridge::onWearOnAvatarArrived,
- new LLUUID(item->getUUID()));
- }
-}
-
-struct LLFoundData
-{
- LLFoundData(const LLUUID& item_id,
- const LLUUID& asset_id,
- const std::string& name,
- LLAssetType::EType asset_type) :
- mItemID(item_id),
- mAssetID(asset_id),
- mName(name),
- mAssetType(asset_type),
- mWearable( NULL ) {}
-
- LLUUID mItemID;
- LLUUID mAssetID;
- std::string mName;
- LLAssetType::EType mAssetType;
- LLWearable* mWearable;
-};
-
-struct LLWearableHoldingPattern
-{
- LLWearableHoldingPattern() : mResolved(0) {}
- ~LLWearableHoldingPattern()
- {
- for_each(mFoundList.begin(), mFoundList.end(), DeletePointer());
- mFoundList.clear();
- }
- typedef std::list<LLFoundData*> found_list_t;
- found_list_t mFoundList;
- S32 mResolved;
-};
-
-
-class LLOutfitObserver : public LLInventoryFetchObserver
-{
-public:
- LLOutfitObserver(const LLUUID& cat_id, bool copy_items, bool append) :
- mCatID(cat_id),
- mCopyItems(copy_items),
- mAppend(append)
- {}
- ~LLOutfitObserver() {}
- virtual void done(); //public
-
-protected:
- LLUUID mCatID;
- bool mCopyItems;
- bool mAppend;
-};
-
-class LLWearInventoryCategoryCallback : public LLInventoryCallback
-{
-public:
- LLWearInventoryCategoryCallback(const LLUUID& cat_id, bool append)
- {
- mCatID = cat_id;
- mAppend = append;
- }
- void fire(const LLUUID& item_id)
- {
- /*
- * Do nothing. We only care about the destructor
- *
- * The reason for this is that this callback is used in a hack where the
- * same callback is given to dozens of items, and the destructor is called
- * after the last item has fired the event and dereferenced it -- if all
- * the events actually fire!
- */
- }
-
-protected:
- ~LLWearInventoryCategoryCallback()
- {
- // Is the destructor called by ordinary dereference, or because the app's shutting down?
- // If the inventory callback manager goes away, we're shutting down, no longer want the callback.
- if( LLInventoryCallbackManager::is_instantiated() )
- {
- wear_inventory_category_on_avatar(gInventory.getCategory(mCatID), mAppend);
- }
- else
- {
- llwarns << "Dropping unhandled LLWearInventoryCategoryCallback" << llendl;
- }
- }
-
-private:
- LLUUID mCatID;
- bool mAppend;
-};
-
-void LLOutfitObserver::done()
-{
- // We now have an outfit ready to be copied to agent inventory. Do
- // it, and wear that outfit normally.
- if(mCopyItems)
- {
- LLInventoryCategory* cat = gInventory.getCategory(mCatID);
- std::string name;
- if(!cat)
- {
- // should never happen.
- name = "New Outfit";
- }
- else
- {
- name = cat->getName();
- }
- LLViewerInventoryItem* item = NULL;
- item_ref_t::iterator it = mComplete.begin();
- item_ref_t::iterator end = mComplete.end();
- LLUUID pid;
- for(; it < end; ++it)
- {
- item = (LLViewerInventoryItem*)gInventory.getItem(*it);
- if(item)
- {
- if(LLInventoryType::IT_GESTURE == item->getInventoryType())
- {
- pid = gInventory.findCategoryUUIDForType(LLAssetType::AT_GESTURE);
- }
- else
- {
- pid = gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
- }
- break;
- }
- }
- if(pid.isNull())
- {
- pid = gAgent.getInventoryRootID();
- }
-
- LLUUID cat_id = gInventory.createNewCategory(
- pid,
- LLAssetType::AT_NONE,
- name);
- mCatID = cat_id;
- LLPointer<LLInventoryCallback> cb = new LLWearInventoryCategoryCallback(mCatID, mAppend);
- it = mComplete.begin();
- for(; it < end; ++it)
- {
- item = (LLViewerInventoryItem*)gInventory.getItem(*it);
- if(item)
- {
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- cat_id,
- std::string(),
- cb);
- }
- }
- }
- else
- {
- // Wear the inventory category.
- wear_inventory_category_on_avatar(gInventory.getCategory(mCatID), mAppend);
- }
-}
-
-class LLOutfitFetch : public LLInventoryFetchDescendentsObserver
-{
-public:
- LLOutfitFetch(bool copy_items, bool append) : mCopyItems(copy_items), mAppend(append) {}
- ~LLOutfitFetch() {}
- virtual void done();
-protected:
- bool mCopyItems;
- bool mAppend;
-};
-
-void LLOutfitFetch::done()
-{
- // What we do here is get the complete information on the items in
- // the library, and set up an observer that will wait for that to
- // happen.
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
- gInventory.collectDescendents(mCompleteFolders.front(),
- cat_array,
- item_array,
- LLInventoryModel::EXCLUDE_TRASH);
- S32 count = item_array.count();
- if(!count)
- {
- llwarns << "Nothing fetched in category " << mCompleteFolders.front()
- << llendl;
- dec_busy_count();
- gInventory.removeObserver(this);
- delete this;
- return;
- }
-
- LLOutfitObserver* outfit;
- outfit = new LLOutfitObserver(mCompleteFolders.front(), mCopyItems, mAppend);
- LLInventoryFetchObserver::item_ref_t ids;
- for(S32 i = 0; i < count; ++i)
- {
- ids.push_back(item_array.get(i)->getUUID());
- }
-
- // clean up, and remove this as an observer since the call to the
- // outfit could notify observers and throw us into an infinite
- // loop.
- dec_busy_count();
- gInventory.removeObserver(this);
- delete this;
- // increment busy count and either tell the inventory to check &
- // call done, or add this object to the inventory for observation.
- inc_busy_count();
-
- // do the fetch
- outfit->fetchItems(ids);
- if(outfit->isEverythingComplete())
- {
- // everything is already here - call done.
- outfit->done();
- }
- else
- {
- // it's all on it's way - add an observer, and the inventory
- // will call done for us when everything is here.
- gInventory.addObserver(outfit);
+ LLAppearanceManager::instance().addCOFItemLink(item);
}
}
-void wear_outfit_by_name(const std::string& name)
+void wear_add_inventory_item_on_avatar( LLInventoryItem* item )
{
- llinfos << "Wearing category " << name << llendl;
- inc_busy_count();
-
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
- LLNameCategoryCollector has_name(name);
- gInventory.collectDescendentsIf(gAgent.getInventoryRootID(),
- cat_array,
- item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- has_name);
- bool copy_items = false;
- LLInventoryCategory* cat = NULL;
- if (cat_array.count() > 0)
- {
- // Just wear the first one that matches
- cat = cat_array.get(0);
- }
- else
+ if(item)
{
- gInventory.collectDescendentsIf(LLUUID::null,
- cat_array,
- item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- has_name);
- if(cat_array.count() > 0)
- {
- cat = cat_array.get(0);
- copy_items = true;
- }
- }
+ lldebugs << "wear_add_inventory_item_on_avatar( " << item->getName()
+ << " )" << llendl;
- if(cat)
- {
- wear_inventory_category(cat, copy_items, false);
- }
- else
- {
- llwarns << "Couldn't find outfit " <<name<< " in wear_outfit_by_name()"
- << llendl;
+ LLWearableList::instance().getAsset(item->getAssetUUID(),
+ item->getName(),
+ item->getType(),
+ LLWearableBridge::onWearAddOnAvatarArrived,
+ new LLUUID(item->getUUID()));
}
-
- dec_busy_count();
}
-void wear_inventory_category(LLInventoryCategory* category, bool copy, bool append)
+void remove_inventory_category_from_avatar( LLInventoryCategory* category )
{
if(!category) return;
-
- lldebugs << "wear_inventory_category( " << category->getName()
+ lldebugs << "remove_inventory_category_from_avatar( " << category->getName()
<< " )" << llendl;
- // What we do here is get the complete information on the items in
- // the inventory, and set up an observer that will wait for that to
- // happen.
- LLOutfitFetch* outfit;
- outfit = new LLOutfitFetch(copy, append);
- LLInventoryFetchDescendentsObserver::folder_ref_t folders;
- folders.push_back(category->getUUID());
- outfit->fetchDescendents(folders);
- inc_busy_count();
- if(outfit->isEverythingComplete())
- {
- // everything is already here - call done.
- outfit->done();
- }
- else
- {
- // it's all on it's way - add an observer, and the inventory
- // will call done for us when everything is here.
- gInventory.addObserver(outfit);
- }
-}
-// *NOTE: hack to get from avatar inventory to avatar
-void wear_inventory_category_on_avatar( LLInventoryCategory* category, BOOL append )
-{
- // Avoid unintentionally overwriting old wearables. We have to do
- // this up front to avoid having to deal with the case of multiple
- // wearables being dirty.
- if(!category) return;
- lldebugs << "wear_inventory_category_on_avatar( " << category->getName()
- << " )" << llendl;
-
- LLWearInfo* userdata = new LLWearInfo;
- userdata->mAppend = append;
- userdata->mCategoryID = category->getUUID();
if( gFloaterCustomize )
{
gFloaterCustomize->askToSaveIfDirty(
- wear_inventory_category_on_avatar_step2,
- userdata);
+ boost::bind(remove_inventory_category_from_avatar_step2, _1, category->getUUID()));
}
else
{
- wear_inventory_category_on_avatar_step2(
- TRUE,
- userdata );
- }
-}
-
-
-void wear_inventory_category_on_avatar_step2( BOOL proceed, void* userdata )
-{
- LLWearInfo* wear_info = (LLWearInfo*)userdata;
- if (!wear_info) return;
-
- // Find all the wearables that are in the category's subtree.
- lldebugs << "wear_inventory_category_on_avatar_step2()" << llendl;
- if(proceed)
- {
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
- LLFindWearables is_wearable;
- gInventory.collectDescendentsIf(wear_info->mCategoryID,
- cat_array,
- item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_wearable);
- S32 i;
- S32 wearable_count = item_array.count();
-
- LLInventoryModel::cat_array_t obj_cat_array;
- LLInventoryModel::item_array_t obj_item_array;
- LLIsType is_object( LLAssetType::AT_OBJECT );
- gInventory.collectDescendentsIf(wear_info->mCategoryID,
- obj_cat_array,
- obj_item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_object);
- S32 obj_count = obj_item_array.count();
-
- // Find all gestures in this folder
- LLInventoryModel::cat_array_t gest_cat_array;
- LLInventoryModel::item_array_t gest_item_array;
- LLIsType is_gesture( LLAssetType::AT_GESTURE );
- gInventory.collectDescendentsIf(wear_info->mCategoryID,
- gest_cat_array,
- gest_item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_gesture);
- S32 gest_count = gest_item_array.count();
-
- if( !wearable_count && !obj_count && !gest_count)
- {
- LLNotifications::instance().add("CouldNotPutOnOutfit");
- delete wear_info;
- return;
- }
-
- // Processes that take time should show the busy cursor
- if (wearable_count > 0 || obj_count > 0)
- {
- inc_busy_count();
- }
-
- // Activate all gestures in this folder
- if (gest_count > 0)
- {
- llinfos << "Activating " << gest_count << " gestures" << llendl;
-
- gGestureManager.activateGestures(gest_item_array);
-
- // Update the inventory item labels to reflect the fact
- // they are active.
- LLViewerInventoryCategory* catp = gInventory.getCategory(wear_info->mCategoryID);
- if (catp)
- {
- gInventory.updateCategory(catp);
- gInventory.notifyObservers();
- }
- }
-
- if(wearable_count > 0)
- {
- // Note: can't do normal iteration, because if all the
- // wearables can be resolved immediately, then the
- // callback will be called (and this object deleted)
- // before the final getNextData().
- LLWearableHoldingPattern* holder = new LLWearableHoldingPattern;
- LLFoundData* found;
- LLDynamicArray<LLFoundData*> found_container;
- for(i = 0; i < wearable_count; ++i)
- {
- found = new LLFoundData(item_array.get(i)->getUUID(),
- item_array.get(i)->getAssetUUID(),
- item_array.get(i)->getName(),
- item_array.get(i)->getType());
- holder->mFoundList.push_front(found);
- found_container.put(found);
- }
- for(i = 0; i < wearable_count; ++i)
- {
- gAddToOutfit = wear_info->mAppend;
-
- found = found_container.get(i);
- gWearableList.getAsset(found->mAssetID,
- found->mName,
- found->mAssetType,
- wear_inventory_category_on_avatar_loop,
- (void*)holder);
- }
- }
-
-
- //If not appending and the folder doesn't contain only gestures, take off all attachments.
- if (!wear_info->mAppend
- && !(wearable_count == 0 && obj_count == 0 && gest_count > 0) )
- {
- LLAgent::userRemoveAllAttachments(NULL);
- }
-
- if( obj_count > 0 )
- {
- // We've found some attachements. Add these.
-
- LLVOAvatar* avatar = gAgent.getAvatarObject();
- if( avatar )
- {
- // Build a compound message to send all the objects that need to be rezzed.
-
- // Limit number of packets to send
- const S32 MAX_PACKETS_TO_SEND = 10;
- const S32 OBJECTS_PER_PACKET = 4;
- const S32 MAX_OBJECTS_TO_SEND = MAX_PACKETS_TO_SEND * OBJECTS_PER_PACKET;
- if( obj_count > MAX_OBJECTS_TO_SEND )
- {
- obj_count = MAX_OBJECTS_TO_SEND;
- }
-
- // Create an id to keep the parts of the compound message together
- LLUUID compound_msg_id;
- compound_msg_id.generate();
- LLMessageSystem* msg = gMessageSystem;
-
- for(i = 0; i < obj_count; ++i)
- {
- if( 0 == (i % OBJECTS_PER_PACKET) )
- {
- // Start a new message chunk
- msg->newMessageFast(_PREHASH_RezMultipleAttachmentsFromInv);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_HeaderData);
- msg->addUUIDFast(_PREHASH_CompoundMsgID, compound_msg_id );
- msg->addU8Fast(_PREHASH_TotalObjects, obj_count );
- msg->addBOOLFast(_PREHASH_FirstDetachAll, !wear_info->mAppend );
- }
-
- LLInventoryItem* item = obj_item_array.get(i);
- msg->nextBlockFast(_PREHASH_ObjectData );
- msg->addUUIDFast(_PREHASH_ItemID, item->getUUID() );
- msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner());
- msg->addU8Fast(_PREHASH_AttachmentPt, 0 ); // Wear at the previous or default attachment point
- pack_permissions_slam(msg, item->getFlags(), item->getPermissions());
- msg->addStringFast(_PREHASH_Name, item->getName());
- msg->addStringFast(_PREHASH_Description, item->getDescription());
-
- if( (i+1 == obj_count) || ((OBJECTS_PER_PACKET-1) == (i % OBJECTS_PER_PACKET)) )
- {
- // End of message chunk
- msg->sendReliable( gAgent.getRegion()->getHost() );
- }
- }
- }
- }
+ remove_inventory_category_from_avatar_step2(TRUE, category->getUUID() );
}
- delete wear_info;
- wear_info = NULL;
}
-void wear_inventory_category_on_avatar_loop(LLWearable* wearable, void* data)
+struct OnRemoveStruct
{
- LLWearableHoldingPattern* holder = (LLWearableHoldingPattern*)data;
- BOOL append= gAddToOutfit;
-
- if(wearable)
- {
- for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->mFoundList.begin();
- iter != holder->mFoundList.end(); ++iter)
- {
- LLFoundData* data = *iter;
- if(wearable->getID() == data->mAssetID)
- {
- data->mWearable = wearable;
- break;
- }
- }
- }
- holder->mResolved += 1;
- if(holder->mResolved >= (S32)holder->mFoundList.size())
- {
- wear_inventory_category_on_avatar_step3(holder, append);
- }
-}
-
-void wear_inventory_category_on_avatar_step3(LLWearableHoldingPattern* holder, BOOL append)
-{
- lldebugs << "wear_inventory_category_on_avatar_step3()" << llendl;
- LLInventoryItem::item_array_t items;
- LLDynamicArray< LLWearable* > wearables;
-
- // For each wearable type, find the first instance in the category
- // that we recursed through.
- for( S32 i = 0; i < WT_COUNT; i++ )
- {
- for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->mFoundList.begin();
- iter != holder->mFoundList.end(); ++iter)
- {
- LLFoundData* data = *iter;
- LLWearable* wearable = data->mWearable;
- if( wearable && ((S32)wearable->getType() == i) )
- {
- LLViewerInventoryItem* item;
- item = (LLViewerInventoryItem*)gInventory.getItem(data->mItemID);
- if( item && (item->getAssetUUID() == wearable->getID()) )
- {
- //RN: after discussing with Brashears, I disabled this code
- //Metadata should reside in the item, not the asset
- //And this code does not handle failed asset uploads properly
-// if(!wearable->isMatchedToInventoryItem(item ))
-// {
-// wearable = gWearableList.createWearableMatchedToInventoryItem( wearable, item );
-// // Now that we have an asset that matches the
-// // item, update the item to point to the new
-// // asset.
-// item->setAssetUUID(wearable->getID());
-// item->updateAssetOnServer();
-// }
- items.put(item);
- wearables.put(wearable);
- }
- break;
- }
- }
- }
-
- if(wearables.count() > 0)
- {
- gAgent.setWearableOutfit(items, wearables, !append);
- gInventory.notifyObservers();
- }
-
- delete holder;
-
- dec_busy_count();
-}
-
-void remove_inventory_category_from_avatar( LLInventoryCategory* category )
-{
- if(!category) return;
- lldebugs << "remove_inventory_category_from_avatar( " << category->getName()
- << " )" << llendl;
-
-
- LLUUID* uuid = new LLUUID(category->getUUID());
-
- if( gFloaterCustomize )
- {
- gFloaterCustomize->askToSaveIfDirty(
- remove_inventory_category_from_avatar_step2,
- uuid);
- }
- else
+ LLUUID mUUID;
+ OnRemoveStruct(const LLUUID& uuid):
+ mUUID(uuid)
{
- remove_inventory_category_from_avatar_step2(
- TRUE,
- uuid );
}
-}
-
+};
-void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata)
+void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id)
{
// Find all the wearables that are in the category's subtree.
- LLUUID* category_id = (LLUUID *)userdata;
-
lldebugs << "remove_inventory_category_from_avatar_step2()" << llendl;
if(proceed)
{
LLInventoryModel::cat_array_t cat_array;
LLInventoryModel::item_array_t item_array;
LLFindWearables is_wearable;
- gInventory.collectDescendentsIf(*category_id,
+ gInventory.collectDescendentsIf(category_id,
cat_array,
item_array,
LLInventoryModel::EXCLUDE_TRASH,
@@ -4211,7 +4386,7 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata)
LLInventoryModel::cat_array_t obj_cat_array;
LLInventoryModel::item_array_t obj_item_array;
LLIsType is_object( LLAssetType::AT_OBJECT );
- gInventory.collectDescendentsIf(*category_id,
+ gInventory.collectDescendentsIf(category_id,
obj_cat_array,
obj_item_array,
LLInventoryModel::EXCLUDE_TRASH,
@@ -4222,7 +4397,7 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata)
LLInventoryModel::cat_array_t gest_cat_array;
LLInventoryModel::item_array_t gest_item_array;
LLIsType is_gesture( LLAssetType::AT_GESTURE );
- gInventory.collectDescendentsIf(*category_id,
+ gInventory.collectDescendentsIf(category_id,
gest_cat_array,
gest_item_array,
LLInventoryModel::EXCLUDE_TRASH,
@@ -4233,39 +4408,43 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata)
{
for(i = 0; i < wearable_count; ++i)
{
- if( gAgent.isWearingItem (item_array.get(i)->getUUID()) )
+ LLViewerInventoryItem *item = item_array.get(i);
+ if (item->getType() == LLAssetType::AT_BODYPART)
+ continue;
+ if (gAgent.isTeen() && item->isWearableType() &&
+ (item->getWearableType() == WT_UNDERPANTS || item->getWearableType() == WT_UNDERSHIRT))
+ continue;
+ if (get_is_item_worn(item->getUUID()))
{
- gWearableList.getAsset(item_array.get(i)->getAssetUUID(),
- item_array.get(i)->getName(),
- item_array.get(i)->getType(),
- LLWearableBridge::onRemoveFromAvatarArrived,
- new LLUUID(item_array.get(i)->getUUID()));
-
+ LLWearableList::instance().getAsset(item->getAssetUUID(),
+ item->getName(),
+ item->getType(),
+ LLWearableBridge::onRemoveFromAvatarArrived,
+ new OnRemoveStruct(item->getLinkedUUID()));
}
}
}
-
-
+
if (obj_count > 0)
{
for(i = 0; i < obj_count; ++i)
{
- gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
- gMessageSystem->nextBlockFast(_PREHASH_ObjectData );
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
- gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item_array.get(i)->getUUID() );
-
- gMessageSystem->sendReliable( gAgent.getRegion()->getHost() );
-
- // this object might have been selected, so let the selection manager know it's gone now
- LLViewerObject *found_obj = gObjectList.findObject( obj_item_array.get(i)->getUUID());
- if (found_obj)
- {
- LLSelectMgr::getInstance()->remove(found_obj);
- }
- else
+ LLViewerInventoryItem *obj_item = obj_item_array.get(i);
+ if (get_is_item_worn(obj_item->getUUID()))
{
- llwarns << "object not found, ignoring" << llendl;
+ gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
+ gMessageSystem->nextBlockFast(_PREHASH_ObjectData );
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+ gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item->getLinkedUUID() );
+
+ gMessageSystem->sendReliable( gAgent.getRegion()->getHost() );
+
+ // this object might have been selected, so let the selection manager know it's gone now
+ LLViewerObject *found_obj = gObjectList.findObject( obj_item->getLinkedUUID());
+ if (found_obj)
+ {
+ LLSelectMgr::getInstance()->remove(found_obj);
+ }
}
}
}
@@ -4274,53 +4453,34 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata)
{
for(i = 0; i < gest_count; ++i)
{
- if ( gGestureManager.isGestureActive( gest_item_array.get(i)->getUUID()) )
+ LLViewerInventoryItem *gest_item = gest_item_array.get(i);
+ if (get_is_item_worn(gest_item->getUUID()))
{
- gGestureManager.deactivateGesture( gest_item_array.get(i)->getUUID() );
- gInventory.updateItem( gest_item_array.get(i) );
+ LLGestureManager::instance().deactivateGesture( gest_item->getLinkedUUID() );
+ gInventory.updateItem( gest_item );
gInventory.notifyObservers();
}
}
}
}
- delete category_id;
- category_id = NULL;
}
BOOL LLWearableBridge::renameItem(const std::string& new_name)
{
- if( gAgent.isWearingItem( mUUID ) )
+ if (get_is_item_worn(mUUID))
{
- gAgent.setWearableName( mUUID, new_name );
+ gAgentWearables.setWearableName( mUUID, new_name );
}
return LLItemBridge::renameItem(new_name);
}
-BOOL LLWearableBridge::isItemRemovable()
-{
- if(gAgent.isWearingItem(mUUID)) return FALSE;
- return LLInvFVBridge::isItemRemovable();
-}
-
-LLFontGL::StyleFlags LLWearableBridge::getLabelStyle() const
-{
- if( gAgent.isWearingItem( mUUID ) )
- {
- // llinfos << "BOLD" << llendl;
- return LLFontGL::BOLD;
- }
- else
- {
- return LLFontGL::NORMAL;
- }
-}
-
std::string LLWearableBridge::getLabelSuffix() const
{
- if( gAgent.isWearingItem( mUUID ) )
+ if (get_is_item_worn(mUUID))
{
- return LLItemBridge::getLabelSuffix() + " (worn)";
+ // e.g. "(worn)"
+ return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn");
}
else
{
@@ -4336,42 +4496,43 @@ LLUIImagePtr LLWearableBridge::getIcon() const
// virtual
void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
{
- if ("wear" == action)
+ if (isAddAction(action))
{
wearOnAvatar();
}
+ else if ("wear_add" == action)
+ {
+ wearAddOnAvatar();
+ }
else if ("edit" == action)
{
editOnAvatar();
return;
}
- else if ("take_off" == action)
+ else if (isRemoveAction(action))
{
- if(gAgent.isWearingItem(mUUID))
- {
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- gWearableList.getAsset(item->getAssetUUID(),
- item->getName(),
- item->getType(),
- LLWearableBridge::onRemoveFromAvatarArrived,
- new LLUUID(mUUID));
- }
- }
+ removeFromAvatar();
+ return;
}
else LLItemBridge::performAction(folder, model, action);
}
void LLWearableBridge::openItem()
{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+ /*
if( isInTrash() )
{
- LLNotifications::instance().add("CannotWearTrash");
+ LLNotificationsUtil::add("CannotWearTrash");
}
else if(isAgentInventory())
{
- if( !gAgent.isWearingItem( mUUID ) )
+ if( !get_is_item_worn( mUUID ) )
{
wearOnAvatar();
}
@@ -4396,14 +4557,14 @@ void LLWearableBridge::openItem()
{
// *TODO: We should fetch the item details, and then do
// the operation above.
- LLNotifications::instance().add("CannotWearInfoNotComplete");
+ LLNotificationsUtil::add("CannotWearInfoNotComplete");
}
}
+ */
}
void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
- // *TODO: Translate
lldebugs << "LLWearableBridge::buildContextMenu()" << llendl;
std::vector<std::string> items;
std::vector<std::string> disabled_items;
@@ -4419,53 +4580,79 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
else
{ // FWIW, it looks like SUPPRESS_OPEN_ITEM is not set anywhere
- BOOL no_open = ((flags & SUPPRESS_OPEN_ITEM) == SUPPRESS_OPEN_ITEM);
+ BOOL can_open = ((flags & SUPPRESS_OPEN_ITEM) != SUPPRESS_OPEN_ITEM);
// If we have clothing, don't add "Open" as it's the same action as "Wear" SL-18976
LLViewerInventoryItem* item = getItem();
- if( !no_open && item )
+ if (can_open && item)
{
- no_open = (item->getType() == LLAssetType::AT_CLOTHING) ||
- (item->getType() == LLAssetType::AT_BODYPART);
+ can_open = (item->getType() != LLAssetType::AT_CLOTHING) &&
+ (item->getType() != LLAssetType::AT_BODYPART);
}
- if (!no_open)
+ if (isLinkedObjectMissing())
+ {
+ can_open = FALSE;
+ }
+
+ bool is_sidepanel = isInOutfitsSidePanel();
+
+ if (can_open && !is_sidepanel)
{
items.push_back(std::string("Open"));
}
- items.push_back(std::string("Properties"));
+ if (!is_sidepanel)
+ {
+ items.push_back(std::string("Properties"));
+ }
getClipboardEntries(true, items, disabled_items, flags);
- items.push_back(std::string("Wearable Separator"));
-
- items.push_back(std::string("Wearable Wear"));
+ if (!is_sidepanel)
+ {
+ items.push_back(std::string("Wearable Separator"));
+ }
+
items.push_back(std::string("Wearable Edit"));
if ((flags & FIRST_SELECTED_ITEM) == 0)
{
disabled_items.push_back(std::string("Wearable Edit"));
}
- //menu.appendSeparator();
- //menu.append(new LLMenuItemCallGL("Wear",
- // LLWearableBridge::onWearOnAvatar,
- // LLWearableBridge::canWearOnAvatar,
- // (void*)this));
- //menu.append(new LLMenuItemCallGL("Edit",
- // LLWearableBridge::onEditOnAvatar,
- // LLWearableBridge::canEditOnAvatar,
- // (void*)this));
+ // Don't allow items to be worn if their baseobj is in the trash.
+ if (isLinkedObjectInTrash() || isLinkedObjectMissing())
+ {
+ disabled_items.push_back(std::string("Wearable Wear"));
+ disabled_items.push_back(std::string("Wearable Add"));
+ disabled_items.push_back(std::string("Wearable Edit"));
+ }
- if( item && (item->getType() == LLAssetType::AT_CLOTHING) )
+ // Disable wear and take off based on whether the item is worn.
+ if(item)
{
- items.push_back(std::string("Take Off"));
- /*menu.append(new LLMenuItemCallGL("Take Off",
- LLWearableBridge::onRemoveFromAvatar,
- LLWearableBridge::canRemoveFromAvatar,
- (void*)this));*/
+ switch (item->getType())
+ {
+ case LLAssetType::AT_CLOTHING:
+ items.push_back(std::string("Take Off"));
+ case LLAssetType::AT_BODYPART:
+ if (get_is_item_worn(item->getUUID()))
+ {
+ disabled_items.push_back(std::string("Wearable Wear"));
+ disabled_items.push_back(std::string("Wearable Add"));
+ }
+ else
+ {
+ items.push_back(std::string("Wearable Wear"));
+ items.push_back(std::string("Wearable Add"));
+ disabled_items.push_back(std::string("Take Off"));
+ }
+ break;
+ default:
+ break;
+ }
}
}
- hideContextEntries(menu, items, disabled_items);
+ hide_context_entries(menu, items, disabled_items);
}
// Called from menus
@@ -4479,7 +4666,7 @@ BOOL LLWearableBridge::canWearOnAvatar(void* user_data)
LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->getItem();
if(!item || !item->isComplete()) return FALSE;
}
- return (!gAgent.isWearingItem(self->mUUID));
+ return (!get_is_item_worn(self->mUUID));
}
// Called from menus
@@ -4495,9 +4682,9 @@ void LLWearableBridge::wearOnAvatar()
{
// Don't wear anything until initial wearables are loaded, can
// destroy clothing items.
- if (!gAgent.areWearablesLoaded())
+ if (!gAgentWearables.areWearablesLoaded())
{
- LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
+ LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded");
return;
}
@@ -4522,6 +4709,37 @@ void LLWearableBridge::wearOnAvatar()
}
}
+void LLWearableBridge::wearAddOnAvatar()
+{
+ // Don't wear anything until initial wearables are loaded, can
+ // destroy clothing items.
+ if (!gAgentWearables.areWearablesLoaded())
+ {
+ LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded");
+ return;
+ }
+
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ if(!isAgentInventory())
+ {
+ LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ else
+ {
+ wear_add_inventory_item_on_avatar(item);
+ }
+ }
+}
+
// static
void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userdata )
{
@@ -4532,24 +4750,36 @@ void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userda
item = (LLViewerInventoryItem*)gInventory.getItem(*item_id);
if(item)
{
- if(item->getAssetUUID() == wearable->getID())
+ if(item->getAssetUUID() == wearable->getAssetID())
+ {
+ gAgentWearables.setWearableItem(item, wearable);
+ gInventory.notifyObservers();
+ //self->getFolderItem()->refreshFromRoot();
+ }
+ else
{
- //RN: after discussing with Brashears, I disabled this code
- //Metadata should reside in the item, not the asset
- //And this code does not handle failed asset uploads properly
+ llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl;
+ }
+ }
+ }
+ delete item_id;
+}
-// if(!wearable->isMatchedToInventoryItem(item))
-// {
-// LLWearable* new_wearable = gWearableList.createWearableMatchedToInventoryItem( wearable, item );
-//
-// // Now that we have an asset that matches the
-// // item, update the item to point to the new
-// // asset.
-// item->setAssetUUID(new_wearable->getID());
-// item->updateAssetOnServer();
-// wearable = new_wearable;
-// }
- gAgent.setWearable(item, wearable);
+// static
+// BAP remove the "add" code path once everything is fully COF-ified.
+void LLWearableBridge::onWearAddOnAvatarArrived( LLWearable* wearable, void* userdata )
+{
+ LLUUID* item_id = (LLUUID*) userdata;
+ if(wearable)
+ {
+ LLViewerInventoryItem* item = NULL;
+ item = (LLViewerInventoryItem*)gInventory.getItem(*item_id);
+ if(item)
+ {
+ if(item->getAssetUUID() == wearable->getAssetID())
+ {
+ bool do_append = true;
+ gAgentWearables.setWearableItem(item, wearable, do_append);
gInventory.notifyObservers();
//self->getFolderItem()->refreshFromRoot();
}
@@ -4568,10 +4798,10 @@ BOOL LLWearableBridge::canEditOnAvatar(void* user_data)
LLWearableBridge* self = (LLWearableBridge*)user_data;
if(!self) return FALSE;
- return (gAgent.isWearingItem(self->mUUID));
+ return (get_is_item_worn(self->mUUID));
}
-// static
+// static
void LLWearableBridge::onEditOnAvatar(void* user_data)
{
LLWearableBridge* self = (LLWearableBridge*)user_data;
@@ -4583,11 +4813,13 @@ void LLWearableBridge::onEditOnAvatar(void* user_data)
void LLWearableBridge::editOnAvatar()
{
- LLWearable* wearable = gAgent.getWearableFromWearableItem(mUUID);
+ LLUUID linked_id = gInventory.getLinkedItemID(mUUID);
+ const LLWearable* wearable = gAgentWearables.getWearableFromItemID(linked_id);
if( wearable )
{
// Set the tab to the right wearable.
- LLFloaterCustomize::setCurrentWearableType( wearable->getType() );
+ if (gFloaterCustomize)
+ gFloaterCustomize->setCurrentWearableType( wearable->getType() );
if( CAMERA_MODE_CUSTOMIZE_AVATAR != gAgent.getCameraMode() )
{
@@ -4603,26 +4835,27 @@ BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data)
LLWearableBridge* self = (LLWearableBridge*)user_data;
if( self && (LLAssetType::AT_BODYPART != self->mAssetType) )
{
- return gAgent.isWearingItem( self->mUUID );
+ return get_is_item_worn( self->mUUID );
}
return FALSE;
}
-// static
+// static
void LLWearableBridge::onRemoveFromAvatar(void* user_data)
{
LLWearableBridge* self = (LLWearableBridge*)user_data;
if(!self) return;
- if(gAgent.isWearingItem(self->mUUID))
+ if(get_is_item_worn(self->mUUID))
{
LLViewerInventoryItem* item = self->getItem();
if (item)
{
- gWearableList.getAsset(item->getAssetUUID(),
- item->getName(),
- item->getType(),
- onRemoveFromAvatarArrived,
- new LLUUID(self->mUUID));
+ LLUUID parent_id = item->getParentUUID();
+ LLWearableList::instance().getAsset(item->getAssetUUID(),
+ item->getName(),
+ item->getType(),
+ onRemoveFromAvatarArrived,
+ new OnRemoveStruct(LLUUID(self->mUUID)));
}
}
}
@@ -4631,19 +4864,527 @@ void LLWearableBridge::onRemoveFromAvatar(void* user_data)
void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable,
void* userdata)
{
- LLUUID* item_id = (LLUUID*) userdata;
+ OnRemoveStruct *on_remove_struct = (OnRemoveStruct*) userdata;
+ const LLUUID &item_id = gInventory.getLinkedItemID(on_remove_struct->mUUID);
if(wearable)
{
- if( gAgent.isWearingItem( *item_id ) )
+ if( get_is_item_worn( item_id ) )
{
EWearableType type = wearable->getType();
-
+
if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES ) ) //&&
//!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) )
{
- gAgent.removeWearable( type );
+ // MULTI_WEARABLE: FIXME HACK - always remove all
+ bool do_remove_all = false;
+ gAgentWearables.removeWearable( type, do_remove_all, 0 );
}
}
}
- delete item_id;
+
+ // Find and remove this item from the COF.
+ LLInventoryModel::item_array_t items = gInventory.collectLinkedItems(item_id, LLAppearanceManager::instance().getCOF());
+ llassert(items.size() == 1); // Should always have one and only one item linked to this in the COF.
+ for (LLInventoryModel::item_array_t::const_iterator iter = items.begin();
+ iter != items.end();
+ ++iter)
+ {
+ const LLViewerInventoryItem *linked_item = (*iter);
+ const LLUUID &item_id = linked_item->getUUID();
+ gInventory.purgeObject(item_id);
+ }
+ gInventory.notifyObservers();
+
+ delete on_remove_struct;
+}
+
+/* static */
+void LLWearableBridge::removeAllClothesFromAvatar()
+{
+ // Remove COF links.
+ for (S32 itype = WT_SHAPE; itype < WT_COUNT; ++itype)
+ {
+ if (itype == WT_SHAPE || itype == WT_SKIN || itype == WT_HAIR || itype == WT_EYES)
+ continue;
+
+ // MULTI-WEARABLES: fixed to index 0
+ LLViewerInventoryItem *item = dynamic_cast<LLViewerInventoryItem*>(
+ gAgentWearables.getWearableInventoryItem((EWearableType)itype, 0));
+ if (!item)
+ continue;
+ const LLUUID &item_id = gInventory.getLinkedItemID(item->getUUID());
+ const LLWearable *wearable = gAgentWearables.getWearableFromItemID(item_id);
+ if (!wearable)
+ continue;
+
+ // Find and remove this item from the COF.
+ LLInventoryModel::item_array_t items = gInventory.collectLinkedItems(
+ item_id, LLAppearanceManager::instance().getCOF());
+ llassert(items.size() == 1); // Should always have one and only one item linked to this in the COF.
+ for (LLInventoryModel::item_array_t::const_iterator iter = items.begin();
+ iter != items.end();
+ ++iter)
+ {
+ const LLViewerInventoryItem *linked_item = (*iter);
+ const LLUUID &item_id = linked_item->getUUID();
+ gInventory.purgeObject(item_id);
+ }
+ }
+ gInventory.notifyObservers();
+
+ // Remove wearables from gAgentWearables
+ LLAgentWearables::userRemoveAllClothes();
+}
+
+/* static */
+void LLWearableBridge::removeItemFromAvatar(LLViewerInventoryItem *item)
+{
+ if (item)
+ {
+ LLWearableList::instance().getAsset(item->getAssetUUID(),
+ item->getName(),
+ item->getType(),
+ LLWearableBridge::onRemoveFromAvatarArrived,
+ new OnRemoveStruct(item->getUUID()));
+ }
+}
+
+void LLWearableBridge::removeFromAvatar()
+{
+ if (get_is_item_worn(mUUID))
+ {
+ LLViewerInventoryItem* item = getItem();
+ removeItemFromAvatar(item);
+ }
+}
+
+LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type,
+ const LLUUID& uuid,LLInventoryModel* model)
+{
+ LLInvFVBridgeAction* action = NULL;
+ switch(asset_type)
+ {
+ case LLAssetType::AT_TEXTURE:
+ action = new LLTextureBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_SOUND:
+ action = new LLSoundBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_LANDMARK:
+ action = new LLLandmarkBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_CALLINGCARD:
+ action = new LLCallingCardBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_OBJECT:
+ action = new LLObjectBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_NOTECARD:
+ action = new LLNotecardBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_ANIMATION:
+ action = new LLAnimationBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_GESTURE:
+ action = new LLGestureBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_LSL_TEXT:
+ action = new LLLSLTextBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_CLOTHING:
+ case LLAssetType::AT_BODYPART:
+ action = new LLWearableBridgeAction(uuid,model);
+
+ break;
+
+ default:
+ break;
+ }
+ return action;
+}
+
+//static
+void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type,
+ const LLUUID& uuid,LLInventoryModel* model)
+{
+ LLInvFVBridgeAction* action = createAction(asset_type,uuid,model);
+ if(action)
+ {
+ action->doIt();
+ delete action;
+ }
+}
+
+//static
+void LLInvFVBridgeAction::doAction(const LLUUID& uuid, LLInventoryModel* model)
+{
+ LLAssetType::EType asset_type = model->getItem(uuid)->getType();
+ LLInvFVBridgeAction* action = createAction(asset_type,uuid,model);
+ if(action)
+ {
+ action->doIt();
+ delete action;
+ }
+}
+
+LLViewerInventoryItem* LLInvFVBridgeAction::getItem() const
+{
+ if(mModel)
+ return (LLViewerInventoryItem*)mModel->getItem(mUUID);
+ return NULL;
+}
+
+//virtual
+void LLTextureBridgeAction::doIt()
+{
+ if (getItem())
+ {
+ LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+//virtual
+void LLSoundBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ LLFloaterReg::showInstance("preview_sound", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+
+//virtual
+void LLLandmarkBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if( item )
+ {
+ // Opening (double-clicking) a landmark immediately teleports,
+ // but warns you the first time.
+ LLSD payload;
+ payload["asset_id"] = item->getAssetUUID();
+
+ LLSD args;
+ args["LOCATION"] = item->getDisplayName();
+
+ LLNotificationsUtil::add("TeleportFromLandmark", args, payload);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+
+//virtual
+void LLCallingCardBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if(item && item->getCreatorUUID().notNull())
+ {
+ LLAvatarActions::showProfile(item->getCreatorUUID());
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+//virtual
+void
+LLNotecardBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+//virtual
+void LLGestureBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null);
+ preview->setFocus(TRUE);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+//virtual
+void LLAnimationBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+
+//virtual
+void LLObjectBridgeAction::doIt()
+{
+ /*
+ LLFloaterReg::showInstance("properties", mUUID);
+ */
+ LLInvFVBridgeAction::doIt();
+}
+
+
+//virtual
+void LLLSLTextBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+
+BOOL LLWearableBridgeAction::isInTrash() const
+{
+ if(!mModel) return FALSE;
+ const LLUUID trash_id = mModel->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ return mModel->isObjectDescendentOf(mUUID, trash_id);
+}
+
+BOOL LLWearableBridgeAction::isAgentInventory() const
+{
+ if(!mModel) return FALSE;
+ if(gInventory.getRootFolderID() == mUUID) return TRUE;
+ return mModel->isObjectDescendentOf(mUUID, gInventory.getRootFolderID());
+}
+
+void LLWearableBridgeAction::wearOnAvatar()
+{
+ // Don't wear anything until initial wearables are loaded, can
+ // destroy clothing items.
+ if (!gAgentWearables.areWearablesLoaded())
+ {
+ LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded");
+ return;
+ }
+
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ if(!isAgentInventory())
+ {
+ LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ else
+ {
+ wear_inventory_item_on_avatar(item);
+ }
+ }
+}
+
+//virtual
+void LLWearableBridgeAction::doIt()
+{
+ if(isInTrash())
+ {
+ LLNotificationsUtil::add("CannotWearTrash");
+ }
+ else if(isAgentInventory())
+ {
+ if(!get_is_item_worn(mUUID))
+ {
+ wearOnAvatar();
+ }
+ }
+ else
+ {
+ // must be in the inventory library. copy it to our inventory
+ // and put it on right away.
+ LLViewerInventoryItem* item = getItem();
+ if(item && item->isComplete())
+ {
+ LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ else if(item)
+ {
+ // *TODO: We should fetch the item details, and then do
+ // the operation above.
+ LLNotificationsUtil::add("CannotWearInfoNotComplete");
+ }
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+// +=================================================+
+// | LLLinkItemBridge |
+// +=================================================+
+// For broken links
+
+std::string LLLinkItemBridge::sPrefix("Link: ");
+
+
+LLUIImagePtr LLLinkItemBridge::getIcon() const
+{
+ if (LLViewerInventoryItem *item = getItem())
+ {
+ return get_item_icon(item->getActualType(), item->getInventoryType(), 0, FALSE);
+ }
+ return get_item_icon(LLAssetType::AT_LINK, LLInventoryType::IT_NONE, 0, FALSE);
+}
+
+void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ // *TODO: Translate
+ lldebugs << "LLLink::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ items.push_back(std::string("Find Original"));
+ disabled_items.push_back(std::string("Find Original"));
+
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Properties"));
+ items.push_back(std::string("Delete"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Delete"));
+ }
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+
+// +=================================================+
+// | LLLinkBridge |
+// +=================================================+
+// For broken links.
+
+std::string LLLinkFolderBridge::sPrefix("Link: ");
+
+
+LLUIImagePtr LLLinkFolderBridge::getIcon() const
+{
+ LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
+ if (LLViewerInventoryItem *item = getItem())
+ {
+ if (const LLViewerInventoryCategory* cat = item->getLinkedCategory())
+ {
+ preferred_type = cat->getPreferredType();
+ }
+ }
+ return LLFolderBridge::getIcon(preferred_type);
+}
+
+void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ // *TODO: Translate
+ lldebugs << "LLLink::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Find Original"));
+ items.push_back(std::string("Delete"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Delete"));
+ }
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+void LLLinkFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("goto" == action)
+ {
+ gotoItem(folder);
+ return;
+ }
+ LLItemBridge::performAction(folder,model,action);
+}
+
+void LLLinkFolderBridge::gotoItem(LLFolderView *folder)
+{
+ const LLUUID &cat_uuid = getFolderID();
+ if (!cat_uuid.isNull())
+ {
+ if (LLFolderViewItem *base_folder = folder->getItemByID(cat_uuid))
+ {
+ if (LLInventoryModel* model = getInventoryModel())
+ {
+ model->fetchDescendentsOf(cat_uuid);
+ }
+ base_folder->setOpen(TRUE);
+ folder->setSelectionFromRoot(base_folder,TRUE);
+ folder->scrollToShowSelection();
+ }
+ }
+}
+
+const LLUUID &LLLinkFolderBridge::getFolderID() const
+{
+ if (LLViewerInventoryItem *link_item = getItem())
+ {
+ if (const LLViewerInventoryCategory *cat = link_item->getLinkedCategory())
+ {
+ const LLUUID& cat_uuid = cat->getUUID();
+ return cat_uuid;
+ }
+ }
+ return LLUUID::null;
}
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 526b30f214..759d0cba18 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -30,10 +30,20 @@
* $/LicenseInfo$
*/
+#ifndef LL_LLINVENTORYBRIDGE_H
+#define LL_LLINVENTORYBRIDGE_H
+
+#include "llcallingcard.h"
#include "llfloaterproperties.h"
-#include "llwearable.h"
+#include "llfoldervieweventlistener.h"
+#include "llinventorymodel.h"
+#include "llinventoryobserver.h"
#include "llviewercontrol.h"
-#include "llcallingcard.h"
+#include "llwearable.h"
+
+class LLInventoryPanel;
+class LLInventoryModel;
+class LLMenuGL;
enum EInventoryIcon
{
@@ -64,10 +74,15 @@ enum EInventoryIcon
CLOTHING_UNDERSHIRT_ICON_NAME,
CLOTHING_UNDERPANTS_ICON_NAME,
CLOTHING_SKIRT_ICON_NAME,
+ CLOTHING_ALPHA_ICON_NAME,
+ CLOTHING_TATTOO_ICON_NAME,
ANIMATION_ICON_NAME,
GESTURE_ICON_NAME,
+ LINKITEM_ICON_NAME,
+ LINKFOLDER_ICON_NAME,
+
ICON_NAME_COUNT
};
@@ -92,46 +107,10 @@ struct LLAttachmentRezAction
S32 mAttachPt;
};
-
-//helper functions
-class LLShowProps
-{
-public:
-
- static void showProperties(const LLUUID& uuid)
- {
- if(!LLFloaterProperties::show(uuid, LLUUID::null))
- {
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- LLRect rect = gSavedSettings.getRect("PropertiesRect");
- rect.translate( left - rect.mLeft, top - rect.mTop );
- LLFloaterProperties* floater;
- floater = new LLFloaterProperties("item properties",
- rect,
- "Inventory Item Properties",
- uuid,
- LLUUID::null);
- // keep onscreen
- gFloaterView->adjustToFitScreen(floater, FALSE);
- }
- }
-};
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryPanelObserver
-//
-// Bridge to support knowing when the inventory has changed.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLInventoryPanelObserver : public LLInventoryObserver
-{
-public:
- LLInventoryPanelObserver(LLInventoryPanel* ip) : mIP(ip) {}
- virtual ~LLInventoryPanelObserver() {}
- virtual void changed(U32 mask) { mIP->modelChanged(mask); }
-protected:
- LLInventoryPanel* mIP;
-};
+const std::string safe_inv_type_lookup(LLInventoryType::EType inv_type);
+void hide_context_entries(LLMenuGL& menu,
+ const std::vector<std::string> &entries_to_show,
+ const std::vector<std::string> &disabled_entries);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLInvFVBridge (& it's derived classes)
@@ -150,6 +129,7 @@ public:
// This method is a convenience function which creates the correct
// type of bridge based on some basic information
static LLInvFVBridge* createBridge(LLAssetType::EType asset_type,
+ LLAssetType::EType actual_asset_type,
LLInventoryType::EType inv_type,
LLInventoryPanel* inventory,
const LLUUID& uuid,
@@ -158,7 +138,6 @@ public:
virtual const LLUUID& getUUID() const { return mUUID; }
- virtual const std::string& getPrefix() { return LLStringUtil::null; }
virtual void restoreItem() {}
virtual void restoreToWorld() {}
@@ -166,6 +145,7 @@ public:
virtual const std::string& getName() const;
virtual const std::string& getDisplayName() const;
virtual PermissionMask getPermissionMask() const;
+ virtual LLFolderType::EType getPreferredType() const;
virtual time_t getCreationDate() const;
virtual LLFontGL::StyleFlags getLabelStyle() const
{
@@ -173,20 +153,23 @@ public:
}
virtual std::string getLabelSuffix() const { return LLStringUtil::null; }
virtual void openItem() {}
+ virtual void closeItem() {}
virtual void previewItem() {openItem();}
virtual void showProperties();
virtual BOOL isItemRenameable() const { return TRUE; }
//virtual BOOL renameItem(const std::string& new_name) {}
virtual BOOL isItemRemovable();
- virtual BOOL isItemMovable();
+ virtual BOOL isItemMovable() const;
//virtual BOOL removeItem() = 0;
virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch);
virtual void move(LLFolderViewEventListener* new_parent_bridge) {}
virtual BOOL isItemCopyable() const { return FALSE; }
virtual BOOL copyToClipboard() const { return FALSE; }
- virtual void cutToClipboard() {}
+ virtual void cutToClipboard();
virtual BOOL isClipboardPasteable() const;
+ virtual BOOL isClipboardPasteableAsLink() const;
virtual void pasteFromClipboard() {}
+ virtual void pasteLinkFromClipboard() {}
void getClipboardEntries(bool show_asset_id, std::vector<std::string> &items,
std::vector<std::string> &disabled_items, U32 flags);
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
@@ -199,15 +182,21 @@ public:
// LLInvFVBridge functionality
virtual void clearDisplayName() {}
+ // Allow context menus to be customized for side panel.
+ bool isInOutfitsSidePanel() const;
+
protected:
- LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid) :
- mInventoryPanel(inventory), mUUID(uuid), mInvType(LLInventoryType::IT_NONE) {}
+ LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid);
LLInventoryObject* getInventoryObject() const;
+ LLInventoryModel* getInventoryModel() const;
+
BOOL isInTrash() const;
- // return true if the item is in agent inventory. if false, it
- // must be lost or in the inventory library.
- BOOL isAgentInventory() const;
+ BOOL isLinkedObjectInTrash() const; // Is this obj or its baseobj in the trash?
+ BOOL isLinkedObjectMissing() const; // Is this a linked obj whose baseobj is not in inventory?
+
+ BOOL isAgentInventory() const; // false if lost or in the inventory library
+ BOOL isCOFFolder() const; // true if COF or descendent of.
virtual BOOL isItemPermissive() const;
static void changeItemParent(LLInventoryModel* model,
LLViewerInventoryItem* item,
@@ -218,11 +207,27 @@ protected:
const LLUUID& new_parent,
BOOL restamp);
void removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch);
-
protected:
- LLInventoryPanel* mInventoryPanel;
- LLUUID mUUID; // item id
+ LLHandle<LLPanel> mInventoryPanel;
+ const LLUUID mUUID; // item id
LLInventoryType::EType mInvType;
+ void purgeItem(LLInventoryModel *model, const LLUUID &uuid);
+};
+
+/**
+ * This class intended to build Folder View Bridge via LLInvFVBridge::createBridge.
+ * It can be overridden with another way of creation necessary Inventory-Folder-View-Bridge.
+ */
+class LLInventoryFVBridgeBuilder
+{
+public:
+ virtual ~LLInventoryFVBridgeBuilder(){}
+ virtual LLInvFVBridge* createBridge(LLAssetType::EType asset_type,
+ LLAssetType::EType actual_asset_type,
+ LLInventoryType::EType inv_type,
+ LLInventoryPanel* inventory,
+ const LLUUID& uuid,
+ U32 flags = 0x00) const;
};
@@ -237,10 +242,11 @@ public:
virtual void selectItem();
virtual void restoreItem();
virtual void restoreToWorld();
-
+ virtual void gotoItem(LLFolderView *folder);
virtual LLUIImagePtr getIcon() const;
virtual const std::string& getDisplayName() const;
virtual std::string getLabelSuffix() const;
+ virtual LLFontGL::StyleFlags getLabelStyle() const;
virtual PermissionMask getPermissionMask() const;
virtual time_t getCreationDate() const;
virtual BOOL isItemRenameable() const;
@@ -255,6 +261,9 @@ public:
virtual void clearDisplayName() { mDisplayName.clear(); }
LLViewerInventoryItem* getItem() const;
+
+ bool isAddAction(std::string action) const;
+ bool isRemoveAction(std::string action) const;
protected:
virtual BOOL isItemPermissive() const;
@@ -273,15 +282,24 @@ public:
BOOL drop);
virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action);
virtual void openItem();
+ virtual void closeItem();
virtual BOOL isItemRenameable() const;
virtual void selectItem();
virtual void restoreItem();
+ virtual LLFolderType::EType getPreferredType() const;
virtual LLUIImagePtr getIcon() const;
+ virtual LLUIImagePtr getOpenIcon() const;
+ static LLUIImagePtr getIcon(LLFolderType::EType preferred_type);
+
virtual BOOL renameItem(const std::string& new_name);
+
virtual BOOL removeItem();
- virtual BOOL isClipboardPasteable() const;
+ BOOL removeSystemFolder();
+ bool removeItemResponse(const LLSD& notification, const LLSD& response);
+
virtual void pasteFromClipboard();
+ virtual void pasteLinkFromClipboard();
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
virtual BOOL hasChildren() const;
virtual BOOL dragOrDrop(MASK mask, BOOL drop,
@@ -289,11 +307,15 @@ public:
void* cargo_data);
virtual BOOL isItemRemovable();
- virtual BOOL isItemMovable();
+ virtual BOOL isItemMovable() const ;
virtual BOOL isUpToDate() const;
-
+ virtual BOOL isItemCopyable() const;
+ virtual BOOL isClipboardPasteable() const;
+ virtual BOOL isClipboardPasteableAsLink() const;
+ virtual BOOL copyToClipboard() const;
+
static void createWearable(LLFolderBridge* bridge, EWearableType type);
- static void createWearable(LLUUID parent_folder_id, EWearableType type);
+ static void createWearable(const LLUUID &parent_folder_id, EWearableType type);
LLViewerInventoryCategory* getCategory() const;
@@ -320,8 +342,11 @@ protected:
static void createNewEyes(void* user_data);
BOOL checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& typeToCheck);
+ BOOL areAnyContentsWorn(LLInventoryModel* model) const;
void modifyOutfit(BOOL append);
+ void determineFolderType();
+
public:
static LLFolderBridge* sSelf;
static void staticFolderOptionsMenu();
@@ -351,15 +376,15 @@ class LLTextureBridge : public LLItemBridge
{
friend class LLInvFVBridge;
public:
- virtual const std::string& getPrefix() { return sPrefix; }
-
virtual LLUIImagePtr getIcon() const;
virtual void openItem();
+ virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
+ virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action);
protected:
LLTextureBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type) :
LLItemBridge(inventory, uuid), mInvType(type) {}
- static std::string sPrefix;
+ bool canSaveTexture(void);
LLInventoryType::EType mInvType;
};
@@ -367,8 +392,6 @@ class LLSoundBridge : public LLItemBridge
{
friend class LLInvFVBridge;
public:
- virtual const std::string& getPrefix() { return sPrefix; }
-
virtual LLUIImagePtr getIcon() const;
virtual void openItem();
virtual void previewItem();
@@ -378,33 +401,21 @@ public:
protected:
LLSoundBridge(LLInventoryPanel* inventory, const LLUUID& uuid) :
LLItemBridge(inventory, uuid) {}
- static std::string sPrefix;
};
class LLLandmarkBridge : public LLItemBridge
{
friend class LLInvFVBridge;
public:
- static const std::string& prefix() { return sPrefix; }
- virtual const std::string& getPrefix() { return sPrefix; }
virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action);
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
virtual LLUIImagePtr getIcon() const;
virtual void openItem();
protected:
- LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags = 0x00) :
- LLItemBridge(inventory, uuid)
- {
- mVisited = FALSE;
- if (flags & LLInventoryItem::II_FLAGS_LANDMARK_VISITED)
- {
- mVisited = TRUE;
- }
- }
+ LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags = 0x00);
protected:
- static std::string sPrefix;
BOOL mVisited;
};
@@ -425,8 +436,6 @@ class LLCallingCardBridge : public LLItemBridge
{
friend class LLInvFVBridge;
public:
- virtual const std::string& getPrefix() { return sPrefix; }
-
virtual std::string getLabelSuffix() const;
//virtual const std::string& getDisplayName() const;
virtual LLUIImagePtr getIcon() const;
@@ -445,7 +454,6 @@ protected:
~LLCallingCardBridge();
protected:
- static std::string sPrefix;
LLCallingCardObserver* mObserver;
};
@@ -454,25 +462,18 @@ class LLNotecardBridge : public LLItemBridge
{
friend class LLInvFVBridge;
public:
- virtual const std::string& getPrefix() { return sPrefix; }
-
virtual LLUIImagePtr getIcon() const;
virtual void openItem();
protected:
LLNotecardBridge(LLInventoryPanel* inventory, const LLUUID& uuid) :
LLItemBridge(inventory, uuid) {}
-
-protected:
- static std::string sPrefix;
};
class LLGestureBridge : public LLItemBridge
{
friend class LLInvFVBridge;
public:
- virtual const std::string& getPrefix() { return sPrefix; }
-
virtual LLUIImagePtr getIcon() const;
// Only suffix for gesture items, not task items, because only
@@ -489,9 +490,6 @@ public:
protected:
LLGestureBridge(LLInventoryPanel* inventory, const LLUUID& uuid)
: LLItemBridge(inventory, uuid) {}
-
-protected:
- static std::string sPrefix;
};
@@ -499,7 +497,6 @@ class LLAnimationBridge : public LLItemBridge
{
friend class LLInvFVBridge;
public:
- virtual const std::string& getPrefix() { return sPrefix; }
virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action);
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
@@ -509,9 +506,6 @@ public:
protected:
LLAnimationBridge(LLInventoryPanel* inventory, const LLUUID& uuid) :
LLItemBridge(inventory, uuid) {}
-
-protected:
- static std::string sPrefix;
};
@@ -519,28 +513,20 @@ class LLObjectBridge : public LLItemBridge
{
friend class LLInvFVBridge;
public:
- virtual const std::string& getPrefix() { return sPrefix; }
-
virtual LLUIImagePtr getIcon() const;
virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action);
virtual void openItem();
virtual LLFontGL::StyleFlags getLabelStyle() const;
virtual std::string getLabelSuffix() const;
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
- virtual BOOL isItemRemovable();
virtual BOOL renameItem(const std::string& new_name);
-protected:
- LLObjectBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type, U32 flags) :
- LLItemBridge(inventory, uuid), mInvType(type)
- {
- mAttachPt = (flags & 0xff); // low bye of inventory flags
+ LLInventoryObject* getObject() const;
- mIsMultiObject = ( flags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ? TRUE: FALSE;
- }
+protected:
+ LLObjectBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type, U32 flags);
protected:
- static std::string sPrefix;
static LLUUID sContextMenuItemID; // Only valid while the context menu is open.
LLInventoryType::EType mInvType;
U32 mAttachPt;
@@ -552,17 +538,12 @@ class LLLSLTextBridge : public LLItemBridge
{
friend class LLInvFVBridge;
public:
- virtual const std::string& getPrefix() { return sPrefix; }
-
virtual LLUIImagePtr getIcon() const;
virtual void openItem();
protected:
LLLSLTextBridge( LLInventoryPanel* inventory, const LLUUID& uuid ) :
LLItemBridge(inventory, uuid) {}
-
-protected:
- static std::string sPrefix;
};
@@ -574,9 +555,7 @@ public:
virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action);
virtual void openItem();
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
- virtual LLFontGL::StyleFlags getLabelStyle() const;
virtual std::string getLabelSuffix() const;
- virtual BOOL isItemRemovable();
virtual BOOL renameItem(const std::string& new_name);
static void onWearOnAvatar( void* userdata ); // Access to wearOnAvatar() from menu
@@ -584,13 +563,19 @@ public:
static void onWearOnAvatarArrived( LLWearable* wearable, void* userdata );
void wearOnAvatar();
+ static void onWearAddOnAvatarArrived( LLWearable* wearable, void* userdata );
+ void wearAddOnAvatar();
+
static BOOL canEditOnAvatar( void* userdata ); // Access to editOnAvatar() from menu
static void onEditOnAvatar( void* userdata );
void editOnAvatar();
static BOOL canRemoveFromAvatar( void* userdata );
static void onRemoveFromAvatar( void* userdata );
- static void onRemoveFromAvatarArrived( LLWearable* wearable, void* userdata );
+ static void onRemoveFromAvatarArrived( LLWearable* wearable, void* userdata );
+ static void removeItemFromAvatar(LLViewerInventoryItem *item);
+ static void removeAllClothesFromAvatar();
+ void removeFromAvatar();
protected:
LLWearableBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLAssetType::EType asset_type, LLInventoryType::EType inv_type, EWearableType wearable_type) :
@@ -605,3 +590,225 @@ protected:
LLInventoryType::EType mInvType;
EWearableType mWearableType;
};
+
+class LLLinkItemBridge : public LLItemBridge
+{
+ friend class LLInvFVBridge;
+public:
+ virtual const std::string& getPrefix() { return sPrefix; }
+
+ virtual LLUIImagePtr getIcon() const;
+ virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
+
+protected:
+ LLLinkItemBridge(LLInventoryPanel* inventory, const LLUUID& uuid) :
+ LLItemBridge(inventory, uuid) {}
+
+protected:
+ static std::string sPrefix;
+};
+
+
+class LLLinkFolderBridge : public LLItemBridge
+{
+ friend class LLInvFVBridge;
+public:
+ virtual const std::string& getPrefix() { return sPrefix; }
+
+ virtual LLUIImagePtr getIcon() const;
+ virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
+ virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action);
+ virtual void gotoItem(LLFolderView *folder);
+
+protected:
+ LLLinkFolderBridge(LLInventoryPanel* inventory, const LLUUID& uuid) :
+ LLItemBridge(inventory, uuid) {}
+ const LLUUID &getFolderID() const;
+
+protected:
+ static std::string sPrefix;
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInvFVBridgeAction (& its derived classes)
+//
+// This is an implementation class to be able to
+// perform action to view inventory items.
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLInvFVBridgeAction
+{
+public:
+ // This method is a convenience function which creates the correct
+ // type of bridge action based on some basic information
+ static LLInvFVBridgeAction* createAction(LLAssetType::EType asset_type,
+ const LLUUID& uuid,LLInventoryModel* model);
+
+ static void doAction(LLAssetType::EType asset_type,
+ const LLUUID& uuid, LLInventoryModel* model);
+ static void doAction(const LLUUID& uuid, LLInventoryModel* model);
+
+ virtual void doIt() { };
+ virtual ~LLInvFVBridgeAction(){}//need this because of warning on OSX
+protected:
+ LLInvFVBridgeAction(const LLUUID& id,LLInventoryModel* model):mUUID(id),mModel(model){}
+
+ LLViewerInventoryItem* getItem() const;
+protected:
+ const LLUUID& mUUID; // item id
+ LLInventoryModel* mModel;
+
+};
+
+
+
+class LLTextureBridgeAction: public LLInvFVBridgeAction
+{
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt() ;
+ virtual ~LLTextureBridgeAction(){}
+protected:
+ LLTextureBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
+
+};
+
+
+class LLSoundBridgeAction: public LLInvFVBridgeAction
+{
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt() ;
+ virtual ~LLSoundBridgeAction(){}
+protected:
+ LLSoundBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
+
+};
+
+
+class LLLandmarkBridgeAction: public LLInvFVBridgeAction
+{
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt() ;
+ virtual ~LLLandmarkBridgeAction(){}
+protected:
+ LLLandmarkBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
+
+};
+
+
+class LLCallingCardBridgeAction: public LLInvFVBridgeAction
+{
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt() ;
+ virtual ~LLCallingCardBridgeAction(){}
+protected:
+ LLCallingCardBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
+
+};
+
+
+class LLNotecardBridgeAction: public LLInvFVBridgeAction
+{
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt() ;
+ virtual ~LLNotecardBridgeAction(){}
+protected:
+ LLNotecardBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
+
+};
+
+
+class LLGestureBridgeAction: public LLInvFVBridgeAction
+{
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt() ;
+ virtual ~LLGestureBridgeAction(){}
+protected:
+ LLGestureBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
+
+};
+
+
+class LLAnimationBridgeAction: public LLInvFVBridgeAction
+{
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt() ;
+ virtual ~LLAnimationBridgeAction(){}
+protected:
+ LLAnimationBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
+
+};
+
+
+class LLObjectBridgeAction: public LLInvFVBridgeAction
+{
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt() ;
+ virtual ~LLObjectBridgeAction(){}
+protected:
+ LLObjectBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
+
+};
+
+
+class LLLSLTextBridgeAction: public LLInvFVBridgeAction
+{
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt() ;
+ virtual ~LLLSLTextBridgeAction(){}
+protected:
+ LLLSLTextBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
+
+};
+
+
+class LLWearableBridgeAction: public LLInvFVBridgeAction
+{
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt();
+ virtual ~LLWearableBridgeAction(){}
+protected:
+ LLWearableBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
+
+
+ BOOL isInTrash() const;
+ // return true if the item is in agent inventory. if false, it
+ // must be lost or in the inventory library.
+ BOOL isAgentInventory() const;
+
+ void wearOnAvatar();
+
+};
+
+void wear_inventory_item_on_avatar(LLInventoryItem* item);
+
+class LLViewerJointAttachment;
+void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment);
+
+// Move items from an in-world object's "Contents" folder to a specified
+// folder in agent inventory.
+BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
+ const LLUUID& category_id,
+ BOOL drop,
+ void (*callback)(S32, void*) = NULL,
+ void* user_data = NULL);
+
+
+
+void teleport_via_landmark(const LLUUID& asset_id);
+
+// Utility function to hide all entries except those in the list
+void hide_context_entries(LLMenuGL& menu,
+ const std::vector<std::string> &entries_to_show,
+ const std::vector<std::string> &disabled_entries);
+
+#endif // LL_LLINVENTORYBRIDGE_H
diff --git a/indra/newview/llinventoryclipboard.cpp b/indra/newview/llinventoryclipboard.cpp
index 94ffcbd457..71a5e12332 100644
--- a/indra/newview/llinventoryclipboard.cpp
+++ b/indra/newview/llinventoryclipboard.cpp
@@ -47,6 +47,7 @@ LLInventoryClipboard LLInventoryClipboard::sInstance;
///----------------------------------------------------------------------------
LLInventoryClipboard::LLInventoryClipboard()
+: mCutMode(false)
{
}
@@ -77,6 +78,16 @@ void LLInventoryClipboard::store(const LLDynamicArray<LLUUID>& inv_objects)
}
}
+void LLInventoryClipboard::cut(const LLUUID& object)
+{
+ if(!mCutMode && !mObjects.empty())
+ {
+ //looks like there are some stored items, reset clipboard state
+ reset();
+ }
+ mCutMode = true;
+ add(object);
+}
void LLInventoryClipboard::retrieve(LLDynamicArray<LLUUID>& inv_objects) const
{
inv_objects.reset();
@@ -90,6 +101,7 @@ void LLInventoryClipboard::retrieve(LLDynamicArray<LLUUID>& inv_objects) const
void LLInventoryClipboard::reset()
{
mObjects.reset();
+ mCutMode = false;
}
// returns true if the clipboard has something pasteable in it.
diff --git a/indra/newview/llinventoryclipboard.h b/indra/newview/llinventoryclipboard.h
index 7a2cf15d62..7e221d650c 100644
--- a/indra/newview/llinventoryclipboard.h
+++ b/indra/newview/llinventoryclipboard.h
@@ -60,6 +60,7 @@ public:
// this method stores an array of objects
void store(const LLDynamicArray<LLUUID>& inventory_objects);
+ void cut(const LLUUID& object);
// this method gets the objects in the clipboard by copying them
// into the array provided.
void retrieve(LLDynamicArray<LLUUID>& inventory_objects) const;
@@ -69,11 +70,13 @@ public:
// returns true if the clipboard has something pasteable in it.
BOOL hasContents() const;
+ bool isCutMode() const { return mCutMode; }
protected:
static LLInventoryClipboard sInstance;
LLDynamicArray<LLUUID> mObjects;
+ bool mCutMode;
public:
// please don't actually call these
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
new file mode 100644
index 0000000000..b4dcb566e4
--- /dev/null
+++ b/indra/newview/llinventoryfilter.cpp
@@ -0,0 +1,877 @@
+/**
+* @file llinventoryfilter.cpp
+* @brief Support for filtering your inventory to only display a subset of the
+* available items.
+*
+* $LicenseInfo:firstyear=2005&license=viewergpl$
+*
+* Copyright (c) 2005-2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+#include "llviewerprecompiledheaders.h"
+
+#include "llinventoryfilter.h"
+
+// viewer includes
+#include "llfoldervieweventlistener.h"
+#include "llfolderviewitem.h"
+#include "llinventorymodel.h" // gInventory.backgroundFetchActive()
+#include "llviewercontrol.h"
+#include "llviewerinventory.h"
+#include "llfolderview.h"
+
+// linden library includes
+#include "lltrans.h"
+
+LLInventoryFilter::FilterOps::FilterOps() :
+ mFilterObjectTypes(0xffffffffffffffffULL),
+ mFilterCategoryTypes(0xffffffffffffffffULL),
+ mMinDate(time_min()),
+ mMaxDate(time_max()),
+ mHoursAgo(0),
+ mShowFolderState(SHOW_NON_EMPTY_FOLDERS),
+ mPermissions(PERM_NONE),
+ mFilterTypes(FILTERTYPE_OBJECT),
+ mFilterUUID(LLUUID::null)
+{
+}
+
+///----------------------------------------------------------------------------
+/// Class LLInventoryFilter
+///----------------------------------------------------------------------------
+LLInventoryFilter::LLInventoryFilter(const std::string& name)
+: mName(name),
+ mModified(FALSE),
+ mNeedTextRebuild(TRUE),
+ mEmptyLookupMessage("InventoryNoMatchingItems")
+{
+ mOrder = SO_FOLDERS_BY_NAME; // This gets overridden by a pref immediately
+
+ mSubStringMatchOffset = 0;
+ mFilterSubString.clear();
+ mFilterGeneration = 0;
+ mMustPassGeneration = S32_MAX;
+ mMinRequiredGeneration = 0;
+ mFilterCount = 0;
+ mNextFilterGeneration = mFilterGeneration + 1;
+
+ mLastLogoff = gSavedPerAccountSettings.getU32("LastLogoff");
+ mFilterBehavior = FILTER_NONE;
+
+ // copy mFilterOps into mDefaultFilterOps
+ markDefault();
+}
+
+LLInventoryFilter::~LLInventoryFilter()
+{
+}
+
+BOOL LLInventoryFilter::check(const LLFolderViewItem* item)
+{
+ // If it's a folder and we're showing all folders, return TRUE automatically.
+ const BOOL is_folder = (dynamic_cast<const LLFolderViewFolder*>(item) != NULL);
+ if (is_folder && (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS))
+ {
+ return TRUE;
+ }
+
+ const LLFolderViewEventListener* listener = item->getListener();
+ mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos;
+
+ const BOOL passed_filtertype = checkAgainstFilterType(item);
+ const BOOL passed = passed_filtertype &&
+ (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos) &&
+ ((listener->getPermissionMask() & mFilterOps.mPermissions) == mFilterOps.mPermissions);
+
+ return passed;
+}
+
+BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item)
+{
+ const LLFolderViewEventListener* listener = item->getListener();
+ if (!listener) return FALSE;
+
+ const LLInventoryType::EType object_type = listener->getInventoryType();
+ const LLUUID object_id = listener->getUUID();
+ const LLInventoryObject *object = gInventory.getObject(object_id);
+
+ const U32 filterTypes = mFilterOps.mFilterTypes;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // FILTERTYPE_OBJECT
+ // Pass if this item's type is of the correct filter type
+ if (filterTypes & FILTERTYPE_OBJECT)
+ {
+ // If it has no type, pass it, unless it's a link.
+ if (object_type == LLInventoryType::IT_NONE)
+ {
+ if (object && object->getIsLinkType())
+ return FALSE;
+ }
+ else if ((1LL << object_type & mFilterOps.mFilterObjectTypes) == U64(0))
+ {
+ return FALSE;
+ }
+ }
+ //
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // FILTERTYPE_CATEGORY
+ // Pass if this item is a category of the filter type, or
+ // if its parent is a category of the filter type.
+ if (filterTypes & FILTERTYPE_CATEGORY)
+ {
+ // Can only filter categories for items in your inventory
+ // (e.g. versus in-world object contents).
+ if (!object) return FALSE;
+
+ LLUUID cat_id = object_id;
+ if (listener->getInventoryType() != LLInventoryType::IT_CATEGORY)
+ {
+ cat_id = object->getParentUUID();
+ }
+ const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
+ if (!cat)
+ return FALSE;
+ if ((1LL << cat->getPreferredType() & mFilterOps.mFilterCategoryTypes) == U64(0))
+ return FALSE;
+ }
+ //
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // FILTERTYPE_UUID
+ // Pass if this item is the target UUID or if it links to the target UUID
+ if (filterTypes & FILTERTYPE_UUID)
+ {
+ if (!object) return FALSE;
+
+ if (object->getLinkedUUID() != mFilterOps.mFilterUUID)
+ return FALSE;
+ }
+ //
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // FILTERTYPE_DATE
+ // Pass if this item is within the date range.
+ if (filterTypes & FILTERTYPE_DATE)
+ {
+ const U16 HOURS_TO_SECONDS = 3600;
+ time_t earliest = time_corrected() - mFilterOps.mHoursAgo * HOURS_TO_SECONDS;
+ if (mFilterOps.mMinDate > time_min() && mFilterOps.mMinDate < earliest)
+ {
+ earliest = mFilterOps.mMinDate;
+ }
+ else if (!mFilterOps.mHoursAgo)
+ {
+ earliest = 0;
+ }
+ if (listener->getCreationDate() < earliest ||
+ listener->getCreationDate() > mFilterOps.mMaxDate)
+ return FALSE;
+ }
+ //
+ ////////////////////////////////////////////////////////////////////////////////
+
+ return TRUE;
+}
+
+
+const std::string& LLInventoryFilter::getFilterSubString(BOOL trim) const
+{
+ return mFilterSubString;
+}
+
+std::string::size_type LLInventoryFilter::getStringMatchOffset() const
+{
+ return mSubStringMatchOffset;
+}
+
+// has user modified default filter params?
+BOOL LLInventoryFilter::isNotDefault() const
+{
+ return mFilterOps.mFilterObjectTypes != mDefaultFilterOps.mFilterObjectTypes
+ || mFilterOps.mFilterTypes != FILTERTYPE_OBJECT
+ || mFilterSubString.size()
+ || mFilterOps.mPermissions != mDefaultFilterOps.mPermissions
+ || mFilterOps.mMinDate != mDefaultFilterOps.mMinDate
+ || mFilterOps.mMaxDate != mDefaultFilterOps.mMaxDate
+ || mFilterOps.mHoursAgo != mDefaultFilterOps.mHoursAgo;
+}
+
+BOOL LLInventoryFilter::isActive() const
+{
+ return mFilterOps.mFilterObjectTypes != 0xffffffffffffffffULL
+ || mFilterOps.mFilterTypes != FILTERTYPE_OBJECT
+ || mFilterSubString.size()
+ || mFilterOps.mPermissions != PERM_NONE
+ || mFilterOps.mMinDate != time_min()
+ || mFilterOps.mMaxDate != time_max()
+ || mFilterOps.mHoursAgo != 0;
+}
+
+BOOL LLInventoryFilter::isModified() const
+{
+ return mModified;
+}
+
+BOOL LLInventoryFilter::isModifiedAndClear()
+{
+ BOOL ret = mModified;
+ mModified = FALSE;
+ return ret;
+}
+
+void LLInventoryFilter::setFilterObjectTypes(U64 types)
+{
+ if (mFilterOps.mFilterObjectTypes != types)
+ {
+ // keep current items only if no type bits getting turned off
+ BOOL fewer_bits_set = (mFilterOps.mFilterObjectTypes & ~types);
+ BOOL more_bits_set = (~mFilterOps.mFilterObjectTypes & types);
+
+ mFilterOps.mFilterObjectTypes = types;
+ if (more_bits_set && fewer_bits_set)
+ {
+ // neither less or more restrive, both simultaneously
+ // so we need to filter from scratch
+ setModified(FILTER_RESTART);
+ }
+ else if (more_bits_set)
+ {
+ // target is only one of all requested types so more type bits == less restrictive
+ setModified(FILTER_LESS_RESTRICTIVE);
+ }
+ else if (fewer_bits_set)
+ {
+ setModified(FILTER_MORE_RESTRICTIVE);
+ }
+ }
+ mFilterOps.mFilterTypes |= FILTERTYPE_OBJECT;
+}
+
+void LLInventoryFilter::setFilterCategoryTypes(U64 types)
+{
+ if (mFilterOps.mFilterCategoryTypes != types)
+ {
+ // keep current items only if no type bits getting turned off
+ BOOL fewer_bits_set = (mFilterOps.mFilterCategoryTypes & ~types);
+ BOOL more_bits_set = (~mFilterOps.mFilterCategoryTypes & types);
+
+ mFilterOps.mFilterCategoryTypes = types;
+ if (more_bits_set && fewer_bits_set)
+ {
+ // neither less or more restrive, both simultaneously
+ // so we need to filter from scratch
+ setModified(FILTER_RESTART);
+ }
+ else if (more_bits_set)
+ {
+ // target is only one of all requested types so more type bits == less restrictive
+ setModified(FILTER_LESS_RESTRICTIVE);
+ }
+ else if (fewer_bits_set)
+ {
+ setModified(FILTER_MORE_RESTRICTIVE);
+ }
+ }
+ mFilterOps.mFilterTypes |= FILTERTYPE_CATEGORY;
+}
+
+void LLInventoryFilter::setFilterUUID(const LLUUID& object_id)
+{
+ if (mFilterOps.mFilterUUID == LLUUID::null)
+ {
+ setModified(FILTER_MORE_RESTRICTIVE);
+ }
+ else
+ {
+ setModified(FILTER_RESTART);
+ }
+ mFilterOps.mFilterUUID = object_id;
+ mFilterOps.mFilterTypes = FILTERTYPE_UUID;
+}
+
+void LLInventoryFilter::setFilterSubString(const std::string& string)
+{
+ if (mFilterSubString != string)
+ {
+ // hitting BACKSPACE, for example
+ const BOOL less_restrictive = mFilterSubString.size() >= string.size() && !mFilterSubString.substr(0, string.size()).compare(string);
+
+ // appending new characters
+ const BOOL more_restrictive = mFilterSubString.size() < string.size() && !string.substr(0, mFilterSubString.size()).compare(mFilterSubString);
+
+ mFilterSubString = string;
+ LLStringUtil::toUpper(mFilterSubString);
+ LLStringUtil::trimHead(mFilterSubString);
+ if (less_restrictive)
+ {
+ setModified(FILTER_LESS_RESTRICTIVE);
+ }
+ else if (more_restrictive)
+ {
+ setModified(FILTER_MORE_RESTRICTIVE);
+ }
+ else
+ {
+ setModified(FILTER_RESTART);
+ }
+
+ // Cancel out UUID once the search string is modified
+ if (mFilterOps.mFilterTypes == FILTERTYPE_UUID)
+ {
+ mFilterOps.mFilterTypes &= ~FILTERTYPE_UUID;
+ mFilterOps.mFilterUUID == LLUUID::null;
+ setModified(FILTER_RESTART);
+ }
+ }
+}
+
+void LLInventoryFilter::setFilterPermissions(PermissionMask perms)
+{
+ if (mFilterOps.mPermissions != perms)
+ {
+ // keep current items only if no perm bits getting turned off
+ BOOL fewer_bits_set = (mFilterOps.mPermissions & ~perms);
+ BOOL more_bits_set = (~mFilterOps.mPermissions & perms);
+ mFilterOps.mPermissions = perms;
+
+ if (more_bits_set && fewer_bits_set)
+ {
+ setModified(FILTER_RESTART);
+ }
+ else if (more_bits_set)
+ {
+ // target must have all requested permission bits, so more bits == more restrictive
+ setModified(FILTER_MORE_RESTRICTIVE);
+ }
+ else if (fewer_bits_set)
+ {
+ setModified(FILTER_LESS_RESTRICTIVE);
+ }
+ }
+}
+
+void LLInventoryFilter::setDateRange(time_t min_date, time_t max_date)
+{
+ mFilterOps.mHoursAgo = 0;
+ if (mFilterOps.mMinDate != min_date)
+ {
+ mFilterOps.mMinDate = min_date;
+ setModified();
+ }
+ if (mFilterOps.mMaxDate != llmax(mFilterOps.mMinDate, max_date))
+ {
+ mFilterOps.mMaxDate = llmax(mFilterOps.mMinDate, max_date);
+ setModified();
+ }
+ mFilterOps.mFilterTypes |= FILTERTYPE_DATE;
+}
+
+void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl)
+{
+ if (sl && !isSinceLogoff())
+ {
+ setDateRange(mLastLogoff, time_max());
+ setModified();
+ }
+ if (!sl && isSinceLogoff())
+ {
+ setDateRange(0, time_max());
+ setModified();
+ }
+ mFilterOps.mFilterTypes |= FILTERTYPE_DATE;
+}
+
+BOOL LLInventoryFilter::isSinceLogoff() const
+{
+ return (mFilterOps.mMinDate == (time_t)mLastLogoff) &&
+ (mFilterOps.mMaxDate == time_max()) &&
+ (mFilterOps.mFilterTypes & FILTERTYPE_DATE);
+}
+
+void LLInventoryFilter::clearModified()
+{
+ mModified = FALSE;
+ mFilterBehavior = FILTER_NONE;
+}
+
+void LLInventoryFilter::setHoursAgo(U32 hours)
+{
+ if (mFilterOps.mHoursAgo != hours)
+ {
+ // *NOTE: need to cache last filter time, in case filter goes stale
+ BOOL less_restrictive = (mFilterOps.mMinDate == time_min() && mFilterOps.mMaxDate == time_max() && hours > mFilterOps.mHoursAgo);
+ BOOL more_restrictive = (mFilterOps.mMinDate == time_min() && mFilterOps.mMaxDate == time_max() && hours <= mFilterOps.mHoursAgo);
+ mFilterOps.mHoursAgo = hours;
+ mFilterOps.mMinDate = time_min();
+ mFilterOps.mMaxDate = time_max();
+ if (less_restrictive)
+ {
+ setModified(FILTER_LESS_RESTRICTIVE);
+ }
+ else if (more_restrictive)
+ {
+ setModified(FILTER_MORE_RESTRICTIVE);
+ }
+ else
+ {
+ setModified(FILTER_RESTART);
+ }
+ }
+ mFilterOps.mFilterTypes |= FILTERTYPE_DATE;
+}
+
+void LLInventoryFilter::setShowFolderState(EFolderShow state)
+{
+ if (mFilterOps.mShowFolderState != state)
+ {
+ mFilterOps.mShowFolderState = state;
+ if (state == SHOW_NON_EMPTY_FOLDERS)
+ {
+ // showing fewer folders than before
+ setModified(FILTER_MORE_RESTRICTIVE);
+ }
+ else if (state == SHOW_ALL_FOLDERS)
+ {
+ // showing same folders as before and then some
+ setModified(FILTER_LESS_RESTRICTIVE);
+ }
+ else
+ {
+ setModified();
+ }
+ }
+}
+
+void LLInventoryFilter::setSortOrder(U32 order)
+{
+ if (mOrder != order)
+ {
+ mOrder = order;
+ setModified();
+ }
+}
+
+void LLInventoryFilter::markDefault()
+{
+ mDefaultFilterOps = mFilterOps;
+}
+
+void LLInventoryFilter::resetDefault()
+{
+ mFilterOps = mDefaultFilterOps;
+ setModified();
+}
+
+void LLInventoryFilter::setModified(EFilterBehavior behavior)
+{
+ mModified = TRUE;
+ mNeedTextRebuild = TRUE;
+ mFilterGeneration = mNextFilterGeneration++;
+
+ if (mFilterBehavior == FILTER_NONE)
+ {
+ mFilterBehavior = behavior;
+ }
+ else if (mFilterBehavior != behavior)
+ {
+ // trying to do both less restrictive and more restrictive filter
+ // basically means restart from scratch
+ mFilterBehavior = FILTER_RESTART;
+ }
+
+ if (isNotDefault())
+ {
+ // if not keeping current filter results, update last valid as well
+ switch(mFilterBehavior)
+ {
+ case FILTER_RESTART:
+ mMustPassGeneration = mFilterGeneration;
+ mMinRequiredGeneration = mFilterGeneration;
+ break;
+ case FILTER_LESS_RESTRICTIVE:
+ mMustPassGeneration = mFilterGeneration;
+ break;
+ case FILTER_MORE_RESTRICTIVE:
+ mMinRequiredGeneration = mFilterGeneration;
+ // must have passed either current filter generation (meaningless, as it hasn't been run yet)
+ // or some older generation, so keep the value
+ mMustPassGeneration = llmin(mMustPassGeneration, mFilterGeneration);
+ break;
+ default:
+ llerrs << "Bad filter behavior specified" << llendl;
+ }
+ }
+ else
+ {
+ // shortcut disabled filters to show everything immediately
+ mMinRequiredGeneration = 0;
+ mMustPassGeneration = S32_MAX;
+ }
+}
+
+BOOL LLInventoryFilter::isFilterObjectTypesWith(LLInventoryType::EType t) const
+{
+ return mFilterOps.mFilterObjectTypes & (1LL << t);
+}
+
+const std::string& LLInventoryFilter::getFilterText()
+{
+ if (!mNeedTextRebuild)
+ {
+ return mFilterText;
+ }
+
+ mNeedTextRebuild = FALSE;
+ std::string filtered_types;
+ std::string not_filtered_types;
+ BOOL filtered_by_type = FALSE;
+ BOOL filtered_by_all_types = TRUE;
+ S32 num_filter_types = 0;
+ mFilterText.clear();
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_ANIMATION))
+ {
+ //filtered_types += " Animations,";
+ filtered_types += LLTrans::getString("Animations");
+ filtered_by_type = TRUE;
+ num_filter_types++;
+ }
+ else
+ {
+ //not_filtered_types += " Animations,";
+ not_filtered_types += LLTrans::getString("Animations");
+
+ filtered_by_all_types = FALSE;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_CALLINGCARD))
+ {
+ //filtered_types += " Calling Cards,";
+ filtered_types += LLTrans::getString("Calling Cards");
+ filtered_by_type = TRUE;
+ num_filter_types++;
+ }
+ else
+ {
+ //not_filtered_types += " Calling Cards,";
+ not_filtered_types += LLTrans::getString("Calling Cards");
+ filtered_by_all_types = FALSE;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_WEARABLE))
+ {
+ //filtered_types += " Clothing,";
+ filtered_types += LLTrans::getString("Clothing");
+ filtered_by_type = TRUE;
+ num_filter_types++;
+ }
+ else
+ {
+ //not_filtered_types += " Clothing,";
+ not_filtered_types += LLTrans::getString("Clothing");
+ filtered_by_all_types = FALSE;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_GESTURE))
+ {
+ //filtered_types += " Gestures,";
+ filtered_types += LLTrans::getString("Gestures");
+ filtered_by_type = TRUE;
+ num_filter_types++;
+ }
+ else
+ {
+ //not_filtered_types += " Gestures,";
+ not_filtered_types += LLTrans::getString("Gestures");
+ filtered_by_all_types = FALSE;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_LANDMARK))
+ {
+ //filtered_types += " Landmarks,";
+ filtered_types += LLTrans::getString("Landmarks");
+ filtered_by_type = TRUE;
+ num_filter_types++;
+ }
+ else
+ {
+ //not_filtered_types += " Landmarks,";
+ not_filtered_types += LLTrans::getString("Landmarks");
+ filtered_by_all_types = FALSE;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_NOTECARD))
+ {
+ //filtered_types += " Notecards,";
+ filtered_types += LLTrans::getString("Notecards");
+ filtered_by_type = TRUE;
+ num_filter_types++;
+ }
+ else
+ {
+ //not_filtered_types += " Notecards,";
+ not_filtered_types += LLTrans::getString("Notecards");
+ filtered_by_all_types = FALSE;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_OBJECT) && isFilterObjectTypesWith(LLInventoryType::IT_ATTACHMENT))
+ {
+ //filtered_types += " Objects,";
+ filtered_types += LLTrans::getString("Objects");
+ filtered_by_type = TRUE;
+ num_filter_types++;
+ }
+ else
+ {
+ //not_filtered_types += " Objects,";
+ not_filtered_types += LLTrans::getString("Objects");
+ filtered_by_all_types = FALSE;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_LSL))
+ {
+ //filtered_types += " Scripts,";
+ filtered_types += LLTrans::getString("Scripts");
+ filtered_by_type = TRUE;
+ num_filter_types++;
+ }
+ else
+ {
+ //not_filtered_types += " Scripts,";
+ not_filtered_types += LLTrans::getString("Scripts");
+ filtered_by_all_types = FALSE;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_SOUND))
+ {
+ //filtered_types += " Sounds,";
+ filtered_types += LLTrans::getString("Sounds");
+ filtered_by_type = TRUE;
+ num_filter_types++;
+ }
+ else
+ {
+ //not_filtered_types += " Sounds,";
+ not_filtered_types += LLTrans::getString("Sounds");
+ filtered_by_all_types = FALSE;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_TEXTURE))
+ {
+ //filtered_types += " Textures,";
+ filtered_types += LLTrans::getString("Textures");
+ filtered_by_type = TRUE;
+ num_filter_types++;
+ }
+ else
+ {
+ //not_filtered_types += " Textures,";
+ not_filtered_types += LLTrans::getString("Textures");
+ filtered_by_all_types = FALSE;
+ }
+
+ if (isFilterObjectTypesWith(LLInventoryType::IT_SNAPSHOT))
+ {
+ //filtered_types += " Snapshots,";
+ filtered_types += LLTrans::getString("Snapshots");
+ filtered_by_type = TRUE;
+ num_filter_types++;
+ }
+ else
+ {
+ //not_filtered_types += " Snapshots,";
+ not_filtered_types += LLTrans::getString("Snapshots");
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!gInventory.backgroundFetchActive()
+ && filtered_by_type
+ && !filtered_by_all_types)
+ {
+ mFilterText += " - ";
+ if (num_filter_types < 5)
+ {
+ mFilterText += filtered_types;
+ }
+ else
+ {
+ //mFilterText += "No ";
+ mFilterText += LLTrans::getString("No Filters");
+ mFilterText += not_filtered_types;
+ }
+ // remove the ',' at the end
+ mFilterText.erase(mFilterText.size() - 1, 1);
+ }
+
+ if (isSinceLogoff())
+ {
+ //mFilterText += " - Since Logoff";
+ mFilterText += LLTrans::getString("Since Logoff");
+ }
+ return mFilterText;
+}
+
+void LLInventoryFilter::toLLSD(LLSD& data) const
+{
+ data["filter_types"] = (LLSD::Integer)getFilterObjectTypes();
+ data["min_date"] = (LLSD::Integer)getMinDate();
+ data["max_date"] = (LLSD::Integer)getMaxDate();
+ data["hours_ago"] = (LLSD::Integer)getHoursAgo();
+ data["show_folder_state"] = (LLSD::Integer)getShowFolderState();
+ data["permissions"] = (LLSD::Integer)getFilterPermissions();
+ data["substring"] = (LLSD::String)getFilterSubString();
+ data["sort_order"] = (LLSD::Integer)getSortOrder();
+ data["since_logoff"] = (LLSD::Boolean)isSinceLogoff();
+}
+
+void LLInventoryFilter::fromLLSD(LLSD& data)
+{
+ if(data.has("filter_types"))
+ {
+ setFilterObjectTypes((U32)data["filter_types"].asInteger());
+ }
+
+ if(data.has("min_date") && data.has("max_date"))
+ {
+ setDateRange(data["min_date"].asInteger(), data["max_date"].asInteger());
+ }
+
+ if(data.has("hours_ago"))
+ {
+ setHoursAgo((U32)data["hours_ago"].asInteger());
+ }
+
+ if(data.has("show_folder_state"))
+ {
+ setShowFolderState((EFolderShow)data["show_folder_state"].asInteger());
+ }
+
+ if(data.has("permissions"))
+ {
+ setFilterPermissions((PermissionMask)data["permissions"].asInteger());
+ }
+
+ if(data.has("substring"))
+ {
+ setFilterSubString(std::string(data["substring"].asString()));
+ }
+
+ if(data.has("sort_order"))
+ {
+ setSortOrder((U32)data["sort_order"].asInteger());
+ }
+
+ if(data.has("since_logoff"))
+ {
+ setDateRangeLastLogoff((bool)data["since_logoff"].asBoolean());
+ }
+}
+
+U32 LLInventoryFilter::getFilterObjectTypes() const
+{
+ return mFilterOps.mFilterObjectTypes;
+}
+
+BOOL LLInventoryFilter::hasFilterString() const
+{
+ return mFilterSubString.size() > 0;
+}
+
+PermissionMask LLInventoryFilter::getFilterPermissions() const
+{
+ return mFilterOps.mPermissions;
+}
+
+time_t LLInventoryFilter::getMinDate() const
+{
+ return mFilterOps.mMinDate;
+}
+
+time_t LLInventoryFilter::getMaxDate() const
+{
+ return mFilterOps.mMaxDate;
+}
+U32 LLInventoryFilter::getHoursAgo() const
+{
+ return mFilterOps.mHoursAgo;
+}
+LLInventoryFilter::EFolderShow LLInventoryFilter::getShowFolderState() const
+{
+ return mFilterOps.mShowFolderState;
+}
+U32 LLInventoryFilter::getSortOrder() const
+{
+ return mOrder;
+}
+const std::string& LLInventoryFilter::getName() const
+{
+ return mName;
+}
+
+void LLInventoryFilter::setFilterCount(S32 count)
+{
+ mFilterCount = count;
+}
+S32 LLInventoryFilter::getFilterCount() const
+{
+ return mFilterCount;
+}
+
+void LLInventoryFilter::decrementFilterCount()
+{
+ mFilterCount--;
+}
+
+S32 LLInventoryFilter::getCurrentGeneration() const
+{
+ return mFilterGeneration;
+}
+S32 LLInventoryFilter::getMinRequiredGeneration() const
+{
+ return mMinRequiredGeneration;
+}
+S32 LLInventoryFilter::getMustPassGeneration() const
+{
+ return mMustPassGeneration;
+}
+
+void LLInventoryFilter::setEmptyLookupMessage(const std::string& message)
+{
+ mEmptyLookupMessage = message;
+}
+
+const std::string& LLInventoryFilter::getEmptyLookupMessage() const
+{
+ return mEmptyLookupMessage;
+
+}
diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h
new file mode 100644
index 0000000000..b01554edc8
--- /dev/null
+++ b/indra/newview/llinventoryfilter.h
@@ -0,0 +1,200 @@
+/**
+* @file llinventoryfilter.h
+* @brief Support for filtering your inventory to only display a subset of the
+* available items.
+*
+* $LicenseInfo:firstyear=2005&license=viewergpl$
+*
+* Copyright (c) 2005-2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+#ifndef LLINVENTORYFILTER_H
+#define LLINVENTORYFILTER_H
+
+#include "llinventorytype.h"
+#include "llpermissionsflags.h"
+
+class LLFolderViewItem;
+
+class LLInventoryFilter
+{
+public:
+ enum EFolderShow
+ {
+ SHOW_ALL_FOLDERS,
+ SHOW_NON_EMPTY_FOLDERS,
+ SHOW_NO_FOLDERS
+ };
+
+ enum EFilterBehavior
+ {
+ FILTER_NONE, // nothing to do, already filtered
+ FILTER_RESTART, // restart filtering from scratch
+ FILTER_LESS_RESTRICTIVE, // existing filtered items will certainly pass this filter
+ FILTER_MORE_RESTRICTIVE // if you didn't pass the previous filter, you definitely won't pass this one
+ };
+
+ enum EFilterType
+ {
+ FILTERTYPE_NONE = 0,
+ FILTERTYPE_OBJECT = 1, // normal default search-by-object-type
+ FILTERTYPE_CATEGORY = 2, // search by folder type
+ FILTERTYPE_UUID = 4, // find the object with UUID and any links to it
+ FILTERTYPE_DATE = 8 // search by date range
+ };
+
+ // REFACTOR: Change this to an enum.
+ static const U32 SO_DATE = 1;
+ static const U32 SO_FOLDERS_BY_NAME = 2;
+ static const U32 SO_SYSTEM_FOLDERS_TO_TOP = 4;
+
+ LLInventoryFilter(const std::string& name);
+ virtual ~LLInventoryFilter();
+
+ // +-------------------------------------------------------------------+
+ // + Parameters
+ // +-------------------------------------------------------------------+
+ void setFilterObjectTypes(U64 types);
+ U32 getFilterObjectTypes() const;
+ BOOL isFilterObjectTypesWith(LLInventoryType::EType t) const;
+ void setFilterCategoryTypes(U64 types);
+ void setFilterUUID(const LLUUID &object_id);
+
+ void setFilterSubString(const std::string& string);
+ const std::string& getFilterSubString(BOOL trim = FALSE) const;
+ BOOL hasFilterString() const;
+
+ void setFilterPermissions(PermissionMask perms);
+ PermissionMask getFilterPermissions() const;
+
+ void setDateRange(time_t min_date, time_t max_date);
+ void setDateRangeLastLogoff(BOOL sl);
+ time_t getMinDate() const;
+ time_t getMaxDate() const;
+
+ void setHoursAgo(U32 hours);
+ U32 getHoursAgo() const;
+
+ // +-------------------------------------------------------------------+
+ // + Execution And Results
+ // +-------------------------------------------------------------------+
+ BOOL check(const LLFolderViewItem* item);
+ BOOL checkAgainstFilterType(const LLFolderViewItem* item);
+ std::string::size_type getStringMatchOffset() const;
+
+ // +-------------------------------------------------------------------+
+ // + Presentation
+ // +-------------------------------------------------------------------+
+ void setShowFolderState( EFolderShow state);
+ EFolderShow getShowFolderState() const;
+
+ void setSortOrder(U32 order);
+ U32 getSortOrder() const;
+
+ void setEmptyLookupMessage(const std::string& message);
+ const std::string& getEmptyLookupMessage() const;
+
+ // +-------------------------------------------------------------------+
+ // + Status
+ // +-------------------------------------------------------------------+
+ BOOL isActive() const;
+ BOOL isModified() const;
+ BOOL isModifiedAndClear();
+ BOOL isSinceLogoff() const;
+ void clearModified();
+ const std::string& getName() const;
+ const std::string& getFilterText();
+ //RN: this is public to allow system to externally force a global refilter
+ void setModified(EFilterBehavior behavior = FILTER_RESTART);
+
+ // +-------------------------------------------------------------------+
+ // + Count
+ // +-------------------------------------------------------------------+
+ void setFilterCount(S32 count);
+ S32 getFilterCount() const;
+ void decrementFilterCount();
+
+ // +-------------------------------------------------------------------+
+ // + Default
+ // +-------------------------------------------------------------------+
+ BOOL isNotDefault() const;
+ void markDefault();
+ void resetDefault();
+
+ // +-------------------------------------------------------------------+
+ // + Generation
+ // +-------------------------------------------------------------------+
+ S32 getCurrentGeneration() const;
+ S32 getMinRequiredGeneration() const;
+ S32 getMustPassGeneration() const;
+
+ // +-------------------------------------------------------------------+
+ // + Conversion
+ // +-------------------------------------------------------------------+
+ void toLLSD(LLSD& data) const;
+ void fromLLSD(LLSD& data);
+
+private:
+ struct FilterOps
+ {
+ FilterOps();
+ U32 mFilterTypes;
+
+ U64 mFilterObjectTypes; // For _OBJECT
+ U64 mFilterCategoryTypes; // For _CATEGORY
+ LLUUID mFilterUUID; // for UUID
+
+ time_t mMinDate;
+ time_t mMaxDate;
+ U32 mHoursAgo;
+ EFolderShow mShowFolderState;
+ PermissionMask mPermissions;
+ };
+
+ U32 mOrder;
+ U32 mLastLogoff;
+
+ FilterOps mFilterOps;
+ FilterOps mDefaultFilterOps;
+
+ std::string::size_type mSubStringMatchOffset;
+ std::string mFilterSubString;
+ const std::string mName;
+
+ S32 mFilterGeneration;
+ S32 mMustPassGeneration;
+ S32 mMinRequiredGeneration;
+ S32 mNextFilterGeneration;
+
+ S32 mFilterCount;
+ EFilterBehavior mFilterBehavior;
+
+ BOOL mModified;
+ BOOL mNeedTextRebuild;
+ std::string mFilterText;
+ std::string mEmptyLookupMessage;
+};
+
+#endif
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
new file mode 100644
index 0000000000..2885ba13fa
--- /dev/null
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -0,0 +1,369 @@
+/**
+ * @file llfloaterinventory.cpp
+ * @brief Implementation of the inventory view and associated stuff.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include <utility> // for std::pair<>
+
+#include "llinventoryfunctions.h"
+
+// library includes
+#include "llagent.h"
+#include "llagentwearables.h"
+#include "llcallingcard.h"
+#include "llfloaterreg.h"
+#include "llsdserialize.h"
+#include "llfiltereditor.h"
+#include "llspinctrl.h"
+#include "llui.h"
+#include "message.h"
+
+// newview includes
+#include "llappearancemgr.h"
+#include "llappviewer.h"
+//#include "llfirstuse.h"
+#include "llfloatercustomize.h"
+#include "llfocusmgr.h"
+#include "llfolderview.h"
+#include "llgesturemgr.h"
+#include "lliconctrl.h"
+#include "llimview.h"
+#include "llinventorybridge.h"
+#include "llinventoryclipboard.h"
+#include "llinventorymodel.h"
+#include "llinventorypanel.h"
+#include "lllineeditor.h"
+#include "llmenugl.h"
+#include "llpreviewanim.h"
+#include "llpreviewgesture.h"
+#include "llpreviewnotecard.h"
+#include "llpreviewscript.h"
+#include "llpreviewsound.h"
+#include "llpreviewtexture.h"
+#include "llresmgr.h"
+#include "llscrollbar.h"
+#include "llscrollcontainer.h"
+#include "llselectmgr.h"
+#include "lltabcontainer.h"
+#include "lltooldraganddrop.h"
+#include "lluictrlfactory.h"
+#include "llviewerinventory.h"
+#include "llviewermessage.h"
+#include "llviewerobjectlist.h"
+#include "llviewerregion.h"
+#include "llviewerwindow.h"
+#include "llvoavatarself.h"
+#include "llwearablelist.h"
+
+BOOL LLInventoryState::sWearNewClothing = FALSE;
+LLUUID LLInventoryState::sWearNewClothingTransactionID;
+
+void LLSaveFolderState::setApply(BOOL apply)
+{
+ mApply = apply;
+ // before generating new list of open folders, clear the old one
+ if(!apply)
+ {
+ clearOpenFolders();
+ }
+}
+
+void LLSaveFolderState::doFolder(LLFolderViewFolder* folder)
+{
+ LLMemType mt(LLMemType::MTYPE_INVENTORY_DO_FOLDER);
+ if(mApply)
+ {
+ // we're applying the open state
+ LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener();
+ if(!bridge) return;
+ LLUUID id(bridge->getUUID());
+ if(mOpenFolders.find(id) != mOpenFolders.end())
+ {
+ folder->setOpen(TRUE);
+ }
+ else
+ {
+ // keep selected filter in its current state, this is less jarring to user
+ if (!folder->isSelected())
+ {
+ folder->setOpen(FALSE);
+ }
+ }
+ }
+ else
+ {
+ // we're recording state at this point
+ if(folder->isOpen())
+ {
+ LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener();
+ if(!bridge) return;
+ mOpenFolders.insert(bridge->getUUID());
+ }
+ }
+}
+
+void LLOpenFilteredFolders::doItem(LLFolderViewItem *item)
+{
+ if (item->getFiltered())
+ {
+ item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
+ }
+}
+
+void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder)
+{
+ if (folder->getFiltered() && folder->getParentFolder())
+ {
+ folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
+ }
+ // if this folder didn't pass the filter, and none of its descendants did
+ else if (!folder->getFiltered() && !folder->hasFilteredDescendants())
+ {
+ folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_NO);
+ }
+}
+
+void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item)
+{
+ if (item->getFiltered() && !mItemSelected)
+ {
+ item->getRoot()->setSelection(item, FALSE, FALSE);
+ if (item->getParentFolder())
+ {
+ item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
+ }
+ item->getRoot()->scrollToShowSelection();
+ mItemSelected = TRUE;
+ }
+}
+
+void LLSelectFirstFilteredItem::doFolder(LLFolderViewFolder* folder)
+{
+ if (folder->getFiltered() && !mItemSelected)
+ {
+ folder->getRoot()->setSelection(folder, FALSE, FALSE);
+ if (folder->getParentFolder())
+ {
+ folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
+ }
+ folder->getRoot()->scrollToShowSelection();
+ mItemSelected = TRUE;
+ }
+}
+
+void LLOpenFoldersWithSelection::doItem(LLFolderViewItem *item)
+{
+ if (item->getParentFolder() && item->isSelected())
+ {
+ item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
+ }
+}
+
+void LLOpenFoldersWithSelection::doFolder(LLFolderViewFolder* folder)
+{
+ if (folder->getParentFolder() && folder->isSelected())
+ {
+ folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
+ }
+}
+
+const std::string& get_item_icon_name(LLAssetType::EType asset_type,
+ LLInventoryType::EType inventory_type,
+ U32 attachment_point,
+ BOOL item_is_multi )
+{
+ EInventoryIcon idx = OBJECT_ICON_NAME;
+ if ( item_is_multi )
+ {
+ idx = OBJECT_MULTI_ICON_NAME;
+ }
+
+ switch(asset_type)
+ {
+ case LLAssetType::AT_TEXTURE:
+ if(LLInventoryType::IT_SNAPSHOT == inventory_type)
+ {
+ idx = SNAPSHOT_ICON_NAME;
+ }
+ else
+ {
+ idx = TEXTURE_ICON_NAME;
+ }
+ break;
+
+ case LLAssetType::AT_SOUND:
+ idx = SOUND_ICON_NAME;
+ break;
+ case LLAssetType::AT_CALLINGCARD:
+ if(attachment_point!= 0)
+ {
+ idx = CALLINGCARD_ONLINE_ICON_NAME;
+ }
+ else
+ {
+ idx = CALLINGCARD_OFFLINE_ICON_NAME;
+ }
+ break;
+ case LLAssetType::AT_LANDMARK:
+ if(attachment_point!= 0)
+ {
+ idx = LANDMARK_VISITED_ICON_NAME;
+ }
+ else
+ {
+ idx = LANDMARK_ICON_NAME;
+ }
+ break;
+ case LLAssetType::AT_SCRIPT:
+ case LLAssetType::AT_LSL_TEXT:
+ case LLAssetType::AT_LSL_BYTECODE:
+ idx = SCRIPT_ICON_NAME;
+ break;
+ case LLAssetType::AT_CLOTHING:
+ idx = CLOTHING_ICON_NAME;
+ case LLAssetType::AT_BODYPART :
+ if(LLAssetType::AT_BODYPART == asset_type)
+ {
+ idx = BODYPART_ICON_NAME;
+ }
+ switch(LLInventoryItem::II_FLAGS_WEARABLES_MASK & attachment_point)
+ {
+ case WT_SHAPE:
+ idx = BODYPART_SHAPE_ICON_NAME;
+ break;
+ case WT_SKIN:
+ idx = BODYPART_SKIN_ICON_NAME;
+ break;
+ case WT_HAIR:
+ idx = BODYPART_HAIR_ICON_NAME;
+ break;
+ case WT_EYES:
+ idx = BODYPART_EYES_ICON_NAME;
+ break;
+ case WT_SHIRT:
+ idx = CLOTHING_SHIRT_ICON_NAME;
+ break;
+ case WT_PANTS:
+ idx = CLOTHING_PANTS_ICON_NAME;
+ break;
+ case WT_SHOES:
+ idx = CLOTHING_SHOES_ICON_NAME;
+ break;
+ case WT_SOCKS:
+ idx = CLOTHING_SOCKS_ICON_NAME;
+ break;
+ case WT_JACKET:
+ idx = CLOTHING_JACKET_ICON_NAME;
+ break;
+ case WT_GLOVES:
+ idx = CLOTHING_GLOVES_ICON_NAME;
+ break;
+ case WT_UNDERSHIRT:
+ idx = CLOTHING_UNDERSHIRT_ICON_NAME;
+ break;
+ case WT_UNDERPANTS:
+ idx = CLOTHING_UNDERPANTS_ICON_NAME;
+ break;
+ case WT_SKIRT:
+ idx = CLOTHING_SKIRT_ICON_NAME;
+ break;
+ case WT_ALPHA:
+ idx = CLOTHING_ALPHA_ICON_NAME;
+ break;
+ case WT_TATTOO:
+ idx = CLOTHING_TATTOO_ICON_NAME;
+ break;
+ default:
+ // no-op, go with choice above
+ break;
+ }
+ break;
+ case LLAssetType::AT_NOTECARD:
+ idx = NOTECARD_ICON_NAME;
+ break;
+ case LLAssetType::AT_ANIMATION:
+ idx = ANIMATION_ICON_NAME;
+ break;
+ case LLAssetType::AT_GESTURE:
+ idx = GESTURE_ICON_NAME;
+ break;
+ case LLAssetType::AT_LINK:
+ idx = LINKITEM_ICON_NAME;
+ break;
+ case LLAssetType::AT_LINK_FOLDER:
+ idx = LINKFOLDER_ICON_NAME;
+ break;
+ default:
+ break;
+ }
+
+ return ICON_NAME[idx];
+}
+
+LLUIImagePtr get_item_icon(LLAssetType::EType asset_type,
+ LLInventoryType::EType inventory_type,
+ U32 attachment_point,
+ BOOL item_is_multi)
+{
+ const std::string& icon_name = get_item_icon_name(asset_type, inventory_type, attachment_point, item_is_multi );
+ return LLUI::getUIImage(icon_name);
+}
+
+BOOL get_is_item_worn(const LLUUID& id)
+{
+ const LLViewerInventoryItem* item = gInventory.getItem(id);
+ if (!item)
+ return FALSE;
+
+ switch(item->getType())
+ {
+ case LLAssetType::AT_OBJECT:
+ {
+ const LLVOAvatarSelf* my_avatar = gAgent.getAvatarObject();
+ if(my_avatar && my_avatar->isWearingAttachment(item->getLinkedUUID()))
+ return TRUE;
+ break;
+ }
+ case LLAssetType::AT_BODYPART:
+ case LLAssetType::AT_CLOTHING:
+ if(gAgentWearables.isWearingItem(item->getLinkedUUID()))
+ return TRUE;
+ break;
+ case LLAssetType::AT_GESTURE:
+ if (LLGestureManager::instance().isGestureActive(item->getLinkedUUID()))
+ return TRUE;
+ break;
+ default:
+ break;
+ }
+ return FALSE;
+}
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
new file mode 100644
index 0000000000..968db84819
--- /dev/null
+++ b/indra/newview/llinventoryfunctions.h
@@ -0,0 +1,118 @@
+/**
+ * @file llinventoryfunctions.h
+ * @brief Miscellaneous inventory-related functions and classes
+ * class definition
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLINVENTORYFUNCTIONS_H
+#define LL_LLINVENTORYFUNCTIONS_H
+
+#include "llinventorytype.h"
+#include "llfolderview.h"
+#include "llfolderviewitem.h"
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// This is a collection of miscellaneous functions and classes
+// that don't fit cleanly into any other class header. Eventually,
+// we should figure out where to put these functions so that we can
+// get rid of this generic file.
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLInventoryState
+{
+public:
+ // HACK: Until we can route this info through the instant message hierarchy
+ static BOOL sWearNewClothing;
+ static LLUUID sWearNewClothingTransactionID; // wear all clothing in this transaction
+};
+
+class LLSelectFirstFilteredItem : public LLFolderViewFunctor
+{
+public:
+ LLSelectFirstFilteredItem() : mItemSelected(FALSE) {}
+ virtual ~LLSelectFirstFilteredItem() {}
+ virtual void doFolder(LLFolderViewFolder* folder);
+ virtual void doItem(LLFolderViewItem* item);
+ BOOL wasItemSelected() { return mItemSelected; }
+protected:
+ BOOL mItemSelected;
+};
+
+class LLOpenFilteredFolders : public LLFolderViewFunctor
+{
+public:
+ LLOpenFilteredFolders() {}
+ virtual ~LLOpenFilteredFolders() {}
+ virtual void doFolder(LLFolderViewFolder* folder);
+ virtual void doItem(LLFolderViewItem* item);
+};
+
+class LLSaveFolderState : public LLFolderViewFunctor
+{
+public:
+ LLSaveFolderState() : mApply(FALSE) {}
+ virtual ~LLSaveFolderState() {}
+ virtual void doFolder(LLFolderViewFolder* folder);
+ virtual void doItem(LLFolderViewItem* item) {}
+ void setApply(BOOL apply);
+ void clearOpenFolders() { mOpenFolders.clear(); }
+protected:
+ std::set<LLUUID> mOpenFolders;
+ BOOL mApply;
+};
+
+class LLOpenFoldersWithSelection : public LLFolderViewFunctor
+{
+public:
+ LLOpenFoldersWithSelection() {}
+ virtual ~LLOpenFoldersWithSelection() {}
+ virtual void doFolder(LLFolderViewFolder* folder);
+ virtual void doItem(LLFolderViewItem* item);
+};
+
+const std::string& get_item_icon_name(LLAssetType::EType asset_type,
+ LLInventoryType::EType inventory_type,
+ U32 attachment_point,
+ BOOL item_is_multi );
+
+LLUIImagePtr get_item_icon(LLAssetType::EType asset_type,
+ LLInventoryType::EType inventory_type,
+ U32 attachment_point,
+ BOOL item_is_multi );
+
+// Is this item or its baseitem is worn, attached, etc...
+BOOL get_is_item_worn(const LLUUID& id);
+
+#endif // LL_LLINVENTORYFUNCTIONS_H
+
+
+
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index f98a3f9ee5..961f7adc0a 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -31,35 +31,26 @@
*/
#include "llviewerprecompiledheaders.h"
-
#include "llinventorymodel.h"
-#include "llassetstorage.h"
-#include "llcrc.h"
-#include "lldir.h"
-#include "llsys.h"
-#include "llxfermanager.h"
-#include "message.h"
-
#include "llagent.h"
-#include "llfloater.h"
-#include "llfocusmgr.h"
-#include "llinventoryview.h"
-#include "llviewerinventory.h"
+#include "llagentwearables.h"
+#include "llinventorypanel.h"
+#include "llinventorybridge.h"
+#include "llinventoryfunctions.h"
+#include "llinventoryobserver.h"
+#include "llinventorypanel.h"
+#include "llnotificationsutil.h"
+#include "llwindow.h"
+#include "llviewercontrol.h"
+#include "llpreview.h"
#include "llviewermessage.h"
+#include "llviewerfoldertype.h"
#include "llviewerwindow.h"
-#include "llviewerregion.h"
#include "llappviewer.h"
-#include "lldbstrings.h"
-#include "llviewerstats.h"
-#include "llmutelist.h"
-#include "llnotify.h"
+#include "llviewerregion.h"
#include "llcallbacklist.h"
-#include "llpreview.h"
-#include "llviewercontrol.h"
-#include "llvoavatar.h"
-#include "llsdutil.h"
-#include <deque>
+#include "llvoavatarself.h"
//#define DIFF_INVENTORY_FILES
#ifdef DIFF_INVENTORY_FILES
@@ -68,13 +59,19 @@
BOOL LLInventoryModel::sBackgroundFetchActive = FALSE;
BOOL LLInventoryModel::sAllFoldersFetched = FALSE;
-BOOL LLInventoryModel::sFullFetchStarted = FALSE;
+BOOL LLInventoryModel::sMyInventoryFetchStarted = FALSE;
+BOOL LLInventoryModel::sLibraryFetchStarted = FALSE;
S32 LLInventoryModel::sNumFetchRetries = 0;
F32 LLInventoryModel::sMinTimeBetweenFetches = 0.3f;
F32 LLInventoryModel::sMaxTimeBetweenFetches = 10.f;
BOOL LLInventoryModel::sTimelyFetchPending = FALSE;
LLFrameTimer LLInventoryModel::sFetchTimer;
S16 LLInventoryModel::sBulkFetchCount = 0;
+BOOL LLInventoryModel::sFirstTimeInViewer2 = TRUE;
+
+// Increment this if the inventory contents change in a non-backwards-compatible way.
+// For viewer 2, the addition of link items makes a pre-viewer-2 cache incorrect.
+const S32 LLInventoryModel::sCurrentInvCacheVersion = 2;
// RN: for some reason, using std::queue in the header file confuses the compiler which things it's an xmlrpc_queue
static std::deque<LLUUID> sFetchQueue;
@@ -87,33 +84,6 @@ static std::deque<LLUUID> sFetchQueue;
const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f;
const S32 MAX_FETCH_RETRIES = 10;
const char CACHE_FORMAT_STRING[] = "%s.inv";
-const char* NEW_CATEGORY_NAME = "New Folder";
-const char* NEW_CATEGORY_NAMES[LLAssetType::AT_COUNT] =
-{
- "Textures", // AT_TEXTURE
- "Sounds", // AT_SOUND
- "Calling Cards", // AT_CALLINGCARD
- "Landmarks", // AT_LANDMARK
- "Scripts", // AT_SCRIPT (deprecated?)
- "Clothing", // AT_CLOTHING
- "Objects", // AT_OBJECT
- "Notecards", // AT_NOTECARD
- "New Folder", // AT_CATEGORY
- "Inventory", // AT_ROOT_CATEGORY
- "Scripts", // AT_LSL_TEXT
- "Scripts", // AT_LSL_BYTECODE
- "Uncompressed Images", // AT_TEXTURE_TGA
- "Body Parts", // AT_BODYPART
- "Trash", // AT_TRASH
- "Photo Album", // AT_SNAPSHOT_CATEGORY
- "Lost And Found", // AT_LOST_AND_FOUND
- "Uncompressed Sounds", // AT_SOUND_WAV
- "Uncompressed Images", // AT_IMAGE_TGA
- "Uncompressed Images", // AT_IMAGE_JPEG
- "Animations", // AT_ANIMATION
- "Gestures", // AT_GESTURE
- "New Folder" // AT_SIMSTATE
-};
struct InventoryIDPtrLess
{
@@ -180,9 +150,21 @@ bool LLCanCache::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
LLInventoryModel gInventory;
// Default constructor
-LLInventoryModel::LLInventoryModel() :
- mModifyMask(LLInventoryObserver::ALL),
+LLInventoryModel::LLInventoryModel()
+: mModifyMask(LLInventoryObserver::ALL),
+ mChangedItemIDs(),
+ mCategoryMap(),
+ mItemMap(),
+ mCategoryLock(),
+ mItemLock(),
mLastItem(NULL),
+ mParentChildCategoryTree(),
+ mParentChildItemTree(),
+ mObservers(),
+ mRootFolderID(),
+ mLibraryRootFolderID(),
+ mLibraryOwnerID(),
+ mIsNotifyObservers(FALSE),
mIsAgentInvUsable(false)
{
}
@@ -190,20 +172,31 @@ LLInventoryModel::LLInventoryModel() :
// Destroys the object
LLInventoryModel::~LLInventoryModel()
{
+ cleanupInventory();
+}
+
+void LLInventoryModel::cleanupInventory()
+{
empty();
- for (observer_list_t::iterator iter = mObservers.begin();
- iter != mObservers.end(); ++iter)
+ // Deleting one observer might erase others from the list, so always pop off the front
+ while (!mObservers.empty())
{
- delete *iter;
+ observer_list_t::iterator iter = mObservers.begin();
+ LLInventoryObserver* observer = *iter;
+ mObservers.erase(iter);
+ delete observer;
}
+ mObservers.clear();
}
// This is a convenience function to check if one object has a parent
// chain up to the category specified by UUID.
BOOL LLInventoryModel::isObjectDescendentOf(const LLUUID& obj_id,
- const LLUUID& cat_id)
+ const LLUUID& cat_id) const
{
- LLInventoryObject* obj = getObject(obj_id);
+ if (obj_id == cat_id) return TRUE;
+
+ const LLInventoryObject* obj = getObject(obj_id);
while(obj)
{
const LLUUID& parent_id = obj->getParentUUID();
@@ -222,6 +215,25 @@ BOOL LLInventoryModel::isObjectDescendentOf(const LLUUID& obj_id,
return FALSE;
}
+const LLViewerInventoryCategory *LLInventoryModel::getFirstNondefaultParent(const LLUUID& obj_id) const
+{
+ const LLInventoryObject* obj = getObject(obj_id);
+ const LLUUID& parent_id = obj->getParentUUID();
+ while (!parent_id.isNull())
+ {
+ const LLViewerInventoryCategory *cat = getCategory(parent_id);
+ if (!cat) break;
+ const LLFolderType::EType folder_type = cat->getPreferredType();
+ if (folder_type != LLFolderType::FT_NONE &&
+ folder_type != LLFolderType::FT_ROOT_INVENTORY &&
+ !LLFolderType::lookupIsEnsembleType(folder_type))
+ {
+ return cat;
+ }
+ }
+ return NULL;
+}
+
// Get the object by id. Returns NULL if not found.
LLInventoryObject* LLInventoryModel::getObject(const LLUUID& id) const
{
@@ -319,15 +331,15 @@ void LLInventoryModel::unlockDirectDescendentArrays(const LLUUID& cat_id)
// specifies 'type' as what it defaults to containing. The category is
// not necessarily only for that type. *NOTE: This will create a new
// inventory category on the fly if one does not exist.
-LLUUID LLInventoryModel::findCategoryUUIDForType(LLAssetType::EType t, bool create_folder)
+const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType t, bool create_folder, bool find_in_library)
{
- LLUUID rv = findCatUUID(t);
- if(rv.isNull() && isInventoryUsable() && create_folder)
+ const LLUUID &rv = findCatUUID(t, find_in_library);
+ if(rv.isNull() && isInventoryUsable() && (create_folder && !find_in_library))
{
- LLUUID root_id = gAgent.getInventoryRootID();
+ const LLUUID &root_id = gInventory.getRootFolderID();
if(root_id.notNull())
{
- rv = createNewCategory(root_id, t, LLStringUtil::null);
+ return createNewCategory(root_id, t, LLStringUtil::null);
}
}
return rv;
@@ -335,10 +347,10 @@ LLUUID LLInventoryModel::findCategoryUUIDForType(LLAssetType::EType t, bool crea
// Internal method which looks for a category with the specified
// preferred type. Returns LLUUID::null if not found.
-LLUUID LLInventoryModel::findCatUUID(LLAssetType::EType preferred_type)
+const LLUUID &LLInventoryModel::findCatUUID(LLFolderType::EType preferred_type, bool find_in_library) const
{
- LLUUID root_id = gAgent.getInventoryRootID();
- if(LLAssetType::AT_CATEGORY == preferred_type)
+ const LLUUID &root_id = (find_in_library) ? gInventory.getLibraryRootFolderID() : gInventory.getRootFolderID();
+ if(LLFolderType::FT_ROOT_INVENTORY == preferred_type)
{
return root_id;
}
@@ -366,7 +378,7 @@ LLUUID LLInventoryModel::findCatUUID(LLAssetType::EType preferred_type)
// version will take care of details like what the name should be
// based on preferred type. Returns the UUID of the new category.
LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
- LLAssetType::EType preferred_type,
+ LLFolderType::EType preferred_type,
const std::string& pname)
{
LLUUID id;
@@ -376,9 +388,9 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
return id;
}
- if(preferred_type == LLAssetType::AT_SIMSTATE)
+ if(LLFolderType::lookup(preferred_type) == LLFolderType::badLookup())
{
- lldebugs << "Attempt to create simstate category." << llendl;
+ lldebugs << "Attempt to create undefined category." << llendl;
return id;
}
@@ -388,14 +400,9 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
{
name.assign(pname);
}
- else if((preferred_type >= LLAssetType::AT_TEXTURE) &&
- (preferred_type < LLAssetType::AT_SIMSTATE))
- {
- name.assign(NEW_CATEGORY_NAMES[preferred_type]);
- }
else
{
- name.assign(NEW_CATEGORY_NAME);
+ name.assign(LLViewerFolderType::lookupNewCategoryName(preferred_type));
}
// Add the category to the internal representation
@@ -453,12 +460,13 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
cat_array_t& cats,
item_array_t& items,
BOOL include_trash,
- LLInventoryCollectFunctor& add)
+ LLInventoryCollectFunctor& add,
+ BOOL follow_folder_links)
{
// Start with categories
if(!include_trash)
{
- LLUUID trash_id(findCatUUID(LLAssetType::AT_TRASH));
+ const LLUUID trash_id = findCategoryUUIDForType(LLFolderType::FT_TRASH);
if(trash_id.notNull() && (trash_id == id))
return;
}
@@ -477,9 +485,40 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
}
}
- // Move onto items
LLViewerInventoryItem* item = NULL;
item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, id);
+
+ // Follow folder links recursively. Currently never goes more
+ // than one level deep (for current outfit support)
+ // Note: if making it fully recursive, need more checking against infinite loops.
+ if (follow_folder_links && item_array)
+ {
+ S32 count = item_array->count();
+ for(S32 i = 0; i < count; ++i)
+ {
+ item = item_array->get(i);
+ if (item->getActualType() == LLAssetType::AT_LINK_FOLDER)
+ {
+ LLViewerInventoryCategory *linked_cat = item->getLinkedCategory();
+ if (linked_cat && linked_cat->getPreferredType() != LLFolderType::FT_OUTFIT)
+ // BAP - was
+ // LLAssetType::lookupIsEnsembleCategoryType(linked_cat->getPreferredType()))
+ // Change back once ensemble typing is in place.
+ {
+ if(add(linked_cat,NULL))
+ {
+ // BAP should this be added here? May not
+ // matter if it's only being used in current
+ // outfit traversal.
+ cats.put(LLPointer<LLViewerInventoryCategory>(linked_cat));
+ }
+ collectDescendentsIf(linked_cat->getUUID(), cats, items, include_trash, add, FALSE);
+ }
+ }
+ }
+ }
+
+ // Move onto items
if(item_array)
{
S32 count = item_array->count();
@@ -494,12 +533,74 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
}
}
+void LLInventoryModel::addChangedMaskForLinks(const LLUUID& object_id, U32 mask)
+{
+ const LLInventoryObject *obj = getObject(object_id);
+ if (!obj || obj->getIsLinkType())
+ return;
+
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ LLLinkedItemIDMatches is_linked_item_match(object_id);
+ collectDescendentsIf(gInventory.getRootFolderID(),
+ cat_array,
+ item_array,
+ LLInventoryModel::INCLUDE_TRASH,
+ is_linked_item_match);
+ if (cat_array.empty() && item_array.empty())
+ {
+ return;
+ }
+ for (LLInventoryModel::cat_array_t::iterator cat_iter = cat_array.begin();
+ cat_iter != cat_array.end();
+ cat_iter++)
+ {
+ LLViewerInventoryCategory *linked_cat = (*cat_iter);
+ addChangedMask(mask, linked_cat->getUUID());
+ };
+
+ for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
+ iter != item_array.end();
+ iter++)
+ {
+ LLViewerInventoryItem *linked_item = (*iter);
+ addChangedMask(mask, linked_item->getUUID());
+ };
+}
+
+const LLUUID& LLInventoryModel::getLinkedItemID(const LLUUID& object_id) const
+{
+ const LLInventoryItem *item = gInventory.getItem(object_id);
+ if (!item)
+ {
+ return object_id;
+ }
+
+ // Find the base item in case this a link (if it's not a link,
+ // this will just be inv_item_id)
+ return item->getLinkedUUID();
+}
+
+LLInventoryModel::item_array_t LLInventoryModel::collectLinkedItems(const LLUUID& id,
+ const LLUUID& start_folder_id)
+{
+ item_array_t items;
+ LLInventoryModel::cat_array_t cat_array;
+ LLLinkedItemIDMatches is_linked_item_match(id);
+ collectDescendentsIf((start_folder_id == LLUUID::null ? gInventory.getRootFolderID() : start_folder_id),
+ cat_array,
+ items,
+ LLInventoryModel::INCLUDE_TRASH,
+ is_linked_item_match);
+ return items;
+}
+
// Generates a string containing the path to the item specified by
// item_id.
-void LLInventoryModel::appendPath(const LLUUID& id, std::string& path)
+void LLInventoryModel::appendPath(const LLUUID& id, std::string& path) const
{
std::string temp;
- LLInventoryObject* obj = getObject(id);
+ const LLInventoryObject* obj = getObject(id);
LLUUID parent_id;
if(obj) parent_id = obj->getParentUUID();
std::string forward_slash("/");
@@ -515,10 +616,10 @@ void LLInventoryModel::appendPath(const LLUUID& id, std::string& path)
path.append(temp);
}
-bool LLInventoryModel::isInventoryUsable()
+bool LLInventoryModel::isInventoryUsable() const
{
bool result = false;
- if(gAgent.getInventoryRootID().notNull() && mIsAgentInvUsable)
+ if(gInventory.getRootFolderID().notNull() && mIsAgentInvUsable)
{
result = true;
}
@@ -543,11 +644,14 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item)
}
LLViewerInventoryItem* old_item = getItem(item->getUUID());
+ LLPointer<LLViewerInventoryItem> new_item;
if(old_item)
{
- // We already have an old item, modify it's values
+ // We already have an old item, modify its values
+ new_item = old_item;
LLUUID old_parent_id = old_item->getParentUUID();
LLUUID new_parent_id = item->getParentUUID();
+
if(old_parent_id != new_parent_id)
{
// need to update the parent-child tree
@@ -574,12 +678,12 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item)
else
{
// Simply add this item
- LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ new_item = new LLViewerInventoryItem(item);
addItem(new_item);
if(item->getParentUUID().isNull())
{
- LLUUID category_id = findCategoryUUIDForType(new_item->getType());
+ const LLUUID category_id = findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(new_item->getType()));
new_item->setParent(category_id);
item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, category_id);
if( item_array )
@@ -603,7 +707,7 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item)
LLUUID parent_id = item->getParentUUID();
if(parent_id == CATEGORIZE_LOST_AND_FOUND_ID)
{
- parent_id = findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
+ parent_id = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
new_item->setParent(parent_id);
}
item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, parent_id);
@@ -616,7 +720,7 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item)
// Whoops! No such parent, make one.
llinfos << "Lost item: " << new_item->getUUID() << " - "
<< new_item->getName() << llendl;
- parent_id = findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
+ parent_id = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
new_item->setParent(parent_id);
item_array = get_ptr_in_map(mParentChildItemTree, parent_id);
if(item_array)
@@ -634,11 +738,28 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item)
}
mask |= LLInventoryObserver::ADD;
}
- if(item->getType() == LLAssetType::AT_CALLINGCARD)
+ if(new_item->getType() == LLAssetType::AT_CALLINGCARD)
{
mask |= LLInventoryObserver::CALLING_CARD;
+ // Handle user created calling cards.
+ // Target ID is stored in the description field of the card.
+ LLUUID id;
+ std::string desc = new_item->getDescription();
+ BOOL isId = desc.empty() ? FALSE : id.set(desc, FALSE);
+ if (isId)
+ {
+ // Valid UUID; set the item UUID and rename it
+ new_item->setCreator(id);
+ std::string avatar_name;
+ // Fetch the currect name
+ gCacheName->get(id, FALSE, boost::bind(&LLViewerInventoryItem::onCallingCardNameLookup, new_item.get(), _1, _2, _3));
+ }
}
- addChangedMask(mask, item->getUUID());
+ else if (new_item->getType() == LLAssetType::AT_GESTURE)
+ {
+ mask |= LLInventoryObserver::GESTURE;
+ }
+ addChangedMask(mask, new_item->getUUID());
return mask;
}
@@ -779,41 +900,78 @@ void LLInventoryModel::deleteObject(const LLUUID& id)
{
lldebugs << "LLInventoryModel::deleteObject()" << llendl;
LLPointer<LLInventoryObject> obj = getObject(id);
+ if (!obj)
+ {
+ llwarns << "Deleting non-existent object [ id: " << id << " ] " << llendl;
+ return;
+ }
+
+ lldebugs << "Deleting inventory object " << id << llendl;
+ mLastItem = NULL;
+ LLUUID parent_id = obj->getParentUUID();
+ mCategoryMap.erase(id);
+ mItemMap.erase(id);
+ //mInventory.erase(id);
+ item_array_t* item_list = getUnlockedItemArray(parent_id);
+ if(item_list)
+ {
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)((LLInventoryObject*)obj);
+ item_list->removeObj(item);
+ }
+ cat_array_t* cat_list = getUnlockedCatArray(parent_id);
+ if(cat_list)
+ {
+ LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)((LLInventoryObject*)obj);
+ cat_list->removeObj(cat);
+ }
+ item_list = getUnlockedItemArray(id);
+ if(item_list)
+ {
+ delete item_list;
+ mParentChildItemTree.erase(id);
+ }
+ cat_list = getUnlockedCatArray(id);
+ if(cat_list)
+ {
+ delete cat_list;
+ mParentChildCategoryTree.erase(id);
+ }
+ addChangedMask(LLInventoryObserver::REMOVE, id);
+ obj = NULL; // delete obj
+ updateLinkedObjectsFromPurge(id);
+ gInventory.notifyObservers();
+}
+
+// Delete a particular inventory item by ID, and remove it from the server.
+void LLInventoryModel::purgeObject(const LLUUID &id)
+{
+ lldebugs << "LLInventoryModel::purgeObject() [ id: " << id << " ] " << llendl;
+ LLPointer<LLInventoryObject> obj = getObject(id);
if(obj)
{
- lldebugs << "Deleting inventory object " << id << llendl;
- mLastItem = NULL;
- LLUUID parent_id = obj->getParentUUID();
- mCategoryMap.erase(id);
- mItemMap.erase(id);
- //mInventory.erase(id);
- item_array_t* item_list = getUnlockedItemArray(parent_id);
- if(item_list)
- {
- LLViewerInventoryItem* item = (LLViewerInventoryItem*)((LLInventoryObject*)obj);
- item_list->removeObj(item);
- }
- cat_array_t* cat_list = getUnlockedCatArray(parent_id);
- if(cat_list)
- {
- LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)((LLInventoryObject*)obj);
- cat_list->removeObj(cat);
- }
- item_list = getUnlockedItemArray(id);
- if(item_list)
- {
- delete item_list;
- mParentChildItemTree.erase(id);
- }
- cat_list = getUnlockedCatArray(id);
- if(cat_list)
- {
- delete cat_list;
- mParentChildCategoryTree.erase(id);
- }
- addChangedMask(LLInventoryObserver::REMOVE, id);
- obj = NULL; // delete obj
+ obj->removeFromServer();
+ LLPreview::hide(id);
+ deleteObject(id);
+ }
+}
+
+void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id)
+{
+ LLInventoryModel::item_array_t item_array = collectLinkedItems(baseobj_id);
+
+ // REBUILD is expensive, so clear the current change list first else
+ // everything else on the changelist will also get rebuilt.
+ gInventory.notifyObservers();
+ for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin();
+ iter != item_array.end();
+ iter++)
+ {
+ const LLViewerInventoryItem *linked_item = (*iter);
+ const LLUUID &item_id = linked_item->getUUID();
+ if (item_id == baseobj_id) continue;
+ addChangedMask(LLInventoryObserver::REBUILD, item_id);
}
+ gInventory.notifyObservers();
}
// This is a method which collects the descendents of the id
@@ -982,17 +1140,34 @@ void LLInventoryModel::removeObserver(LLInventoryObserver* observer)
mObservers.erase(observer);
}
-BOOL LLInventoryModel::containsObserver(LLInventoryObserver* observer)
+BOOL LLInventoryModel::containsObserver(LLInventoryObserver* observer) const
{
return mObservers.find(observer) != mObservers.end();
}
-// Call this method when it's time to update everyone on a new state,
-// by default, the inventory model will not update observers
-// automatically.
+void LLInventoryModel::idleNotifyObservers()
+{
+ if (mModifyMask == LLInventoryObserver::NONE && (mChangedItemIDs.size() == 0))
+ {
+ return;
+ }
+ notifyObservers("");
+}
+
+// Call this method when it's time to update everyone on a new state.
// The optional argument 'service_name' is used by Agent Inventory Service [DEV-20328]
void LLInventoryModel::notifyObservers(const std::string service_name)
{
+ if (mIsNotifyObservers)
+ {
+ // Within notifyObservers, something called notifyObservers
+ // again. This type of recursion is unsafe because it causes items to be
+ // processed twice, and this can easily lead to infinite loops.
+ llwarns << "Call was made to notifyObservers within notifyObservers!" << llendl;
+ return;
+ }
+
+ mIsNotifyObservers = TRUE;
for (observer_list_t::iterator iter = mObservers.begin();
iter != mObservers.end(); )
{
@@ -1008,23 +1183,39 @@ void LLInventoryModel::notifyObservers(const std::string service_name)
observer->changed(mModifyMask);
}
- // safe way to incrament since changed may delete entries! (@!##%@!@&*!)
+ // safe way to increment since changed may delete entries! (@!##%@!@&*!)
iter = mObservers.upper_bound(observer);
}
mModifyMask = LLInventoryObserver::NONE;
mChangedItemIDs.clear();
+ mIsNotifyObservers = FALSE;
}
// store flag for change
// and id of object change applies to
void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
{
+ if (mIsNotifyObservers)
+ {
+ // Something marked an item for change within a call to notifyObservers
+ // (which is in the process of processing the list of items marked for change).
+ // This means the change may fail to be processed.
+ llwarns << "Adding changed mask within notify observers! Change will likely be lost." << llendl;
+ }
+
mModifyMask |= mask;
if (referent.notNull())
{
mChangedItemIDs.insert(referent);
}
+
+ // Update all linked items. Starting with just LABEL because I'm
+ // not sure what else might need to be accounted for this.
+ if (mModifyMask & LLInventoryObserver::LABEL)
+ {
+ addChangedMaskForLinks(referent, LLInventoryObserver::LABEL);
+ }
}
// This method to prepares a set of mock inventory which provides
@@ -1042,7 +1233,7 @@ void LLInventoryModel::mock(const LLUUID& root_id)
root_id,
LLUUID::null,
LLAssetType::AT_CATEGORY,
- NEW_CATEGORY_NAMES[LLAssetType::AT_ROOT_CATEGORY],
+ LLFolderType::lookupNewCategoryName(LLFolderType::FT_ROOT_INVENTORY),
gAgent.getID());
addCategory(cat);
gInventory.buildParentChildMap();
@@ -1122,14 +1313,19 @@ void LLInventoryModel::fetchInventoryResponder::error(U32 status, const std::str
gInventory.notifyObservers("fetchinventory");
}
-void LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id)
+bool LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id)
{
+ if(folder_id.isNull())
+ {
+ llwarns << "Calling fetch descendents on NULL folder id!" << llendl;
+ return false;
+ }
LLViewerInventoryCategory* cat = getCategory(folder_id);
if(!cat)
{
llwarns << "Asked to fetch descendents of non-existent folder: "
<< folder_id << llendl;
- return;
+ return false;
}
//S32 known_descendents = 0;
///cat_array_t* categories = get_ptr_in_map(mParentChildCategoryTree, folder_id);
@@ -1142,24 +1338,20 @@ void LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id)
//{
// known_descendents += items->count();
//}
- if(!cat->fetchDescendents())
- {
- //llinfos << "Not fetching descendents" << llendl;
- }
+ return cat->fetchDescendents();
}
//Initialize statics.
bool LLInventoryModel::isBulkFetchProcessingComplete()
{
- return ( (sFetchQueue.empty()
- && sBulkFetchCount<=0) ? TRUE : FALSE ) ;
+ return sFetchQueue.empty() && sBulkFetchCount<=0;
}
-class fetchDescendentsResponder: public LLHTTPClient::Responder
+class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder
{
public:
- fetchDescendentsResponder(const LLSD& request_sd) : mRequestSD(request_sd) {};
- //fetchDescendentsResponder() {};
+ LLInventoryModelFetchDescendentsResponder(const LLSD& request_sd) : mRequestSD(request_sd) {};
+ //LLInventoryModelFetchDescendentsResponder() {};
void result(const LLSD& content);
void error(U32 status, const std::string& reason);
public:
@@ -1169,7 +1361,7 @@ class fetchDescendentsResponder: public LLHTTPClient::Responder
};
//If we get back a normal response, handle it here
-void fetchDescendentsResponder::result(const LLSD& content)
+void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)
{
if (content.has("folders"))
{
@@ -1203,7 +1395,7 @@ void fetchDescendentsResponder::result(const LLSD& content)
item_it != folder_sd["items"].endArray();
++item_it)
{
- LLUUID lost_uuid = gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
+ const LLUUID lost_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
if (lost_uuid.notNull())
{
LLSD item = *item_it;
@@ -1236,7 +1428,8 @@ void fetchDescendentsResponder::result(const LLSD& content)
LLSD category = *category_it;
tcategory->fromLLSD(category);
- if (LLInventoryModel::sFullFetchStarted)
+ if (LLInventoryModel::sMyInventoryFetchStarted ||
+ LLInventoryModel::sLibraryFetchStarted)
{
sFetchQueue.push_back(tcategory->getUUID());
}
@@ -1263,6 +1456,7 @@ void fetchDescendentsResponder::result(const LLSD& content)
{
cat->setVersion(version);
cat->setDescendentCount(descendents);
+ cat->determineFolderType();
}
}
@@ -1287,20 +1481,16 @@ void fetchDescendentsResponder::result(const LLSD& content)
if (LLInventoryModel::isBulkFetchProcessingComplete())
{
llinfos << "Inventory fetch completed" << llendl;
- if (LLInventoryModel::sFullFetchStarted)
- {
- LLInventoryModel::sAllFoldersFetched = TRUE;
- }
- LLInventoryModel::stopBackgroundFetch();
+ LLInventoryModel::setAllFoldersFetched();
}
gInventory.notifyObservers("fetchDescendents");
}
//If we get back an error (not found, etc...), handle it here
-void fetchDescendentsResponder::error(U32 status, const std::string& reason)
+void LLInventoryModelFetchDescendentsResponder::error(U32 status, const std::string& reason)
{
- llinfos << "fetchDescendentsResponder::error "
+ llinfos << "LLInventoryModelFetchDescendentsResponder::error "
<< status << ": " << reason << llendl;
LLInventoryModel::incrBulkFetch(-1);
@@ -1320,11 +1510,7 @@ void fetchDescendentsResponder::error(U32 status, const std::string& reason)
{
if (LLInventoryModel::isBulkFetchProcessingComplete())
{
- if (LLInventoryModel::sFullFetchStarted)
- {
- LLInventoryModel::sAllFoldersFetched = TRUE;
- }
- LLInventoryModel::stopBackgroundFetch();
+ LLInventoryModel::setAllFoldersFetched();
}
}
gInventory.notifyObservers("fetchDescendents");
@@ -1392,7 +1578,8 @@ void LLInventoryModel::bulkFetch(std::string url)
body["folders"].append(folder_sd);
folder_count++;
}
- if (sFullFetchStarted)
+ if (sMyInventoryFetchStarted ||
+ sLibraryFetchStarted)
{ //Already have this folder but append child folders to list.
// add all children to queue
parent_cat_map_t::iterator cat_it = gInventory.mParentChildCategoryTree.find(cat->getUUID());
@@ -1417,29 +1604,73 @@ void LLInventoryModel::bulkFetch(std::string url)
sBulkFetchCount++;
if (body["folders"].size())
{
- LLHTTPClient::post(url, body, new fetchDescendentsResponder(body),300.0);
+ LLHTTPClient::post(url, body, new LLInventoryModelFetchDescendentsResponder(body),300.0);
}
if (body_lib["folders"].size())
{
std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents");
- LLHTTPClient::post(url_lib, body_lib, new fetchDescendentsResponder(body_lib),300.0);
+ LLHTTPClient::post(url_lib, body_lib, new LLInventoryModelFetchDescendentsResponder(body_lib),300.0);
}
sFetchTimer.reset();
}
else if (isBulkFetchProcessingComplete())
{
- if (sFullFetchStarted)
- {
- sAllFoldersFetched = TRUE;
- }
- stopBackgroundFetch();
+ setAllFoldersFetched();
}
}
+bool fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id)
+{
+ for (std::deque<LLUUID>::iterator it = sFetchQueue.begin();
+ it != sFetchQueue.end(); ++it)
+ {
+ const LLUUID& fetch_id = *it;
+ if (gInventory.isObjectDescendentOf(fetch_id, cat_id))
+ return false;
+ }
+ return true;
+}
+
+/* static */
+bool LLInventoryModel::libraryFetchStarted()
+{
+ return sLibraryFetchStarted;
+}
+
+/* static */
+bool LLInventoryModel::libraryFetchCompleted()
+{
+ return libraryFetchStarted() && fetchQueueContainsNoDescendentsOf(gInventory.getLibraryRootFolderID());
+}
+
+/* static */
+bool LLInventoryModel::libraryFetchInProgress()
+{
+ return libraryFetchStarted() && !libraryFetchCompleted();
+}
+
+/* static */
+bool LLInventoryModel::myInventoryFetchStarted()
+{
+ return sMyInventoryFetchStarted;
+}
+
+/* static */
+bool LLInventoryModel::myInventoryFetchCompleted()
+{
+ return myInventoryFetchStarted() && fetchQueueContainsNoDescendentsOf(gInventory.getRootFolderID());
+}
+
+/* static */
+bool LLInventoryModel::myInventoryFetchInProgress()
+{
+ return myInventoryFetchStarted() && !myInventoryFetchCompleted();
+}
+
// static
bool LLInventoryModel::isEverythingFetched()
{
- return (sAllFoldersFetched ? true : false);
+ return sAllFoldersFetched;
}
//static
@@ -1448,7 +1679,6 @@ BOOL LLInventoryModel::backgroundFetchActive()
return sBackgroundFetchActive;
}
-//static
void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id)
{
if (!sAllFoldersFetched)
@@ -1456,11 +1686,16 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id)
sBackgroundFetchActive = TRUE;
if (cat_id.isNull())
{
- if (!sFullFetchStarted)
+ if (!sMyInventoryFetchStarted)
+ {
+ sMyInventoryFetchStarted = TRUE;
+ sFetchQueue.push_back(gInventory.getRootFolderID());
+ gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
+ }
+ if (!sLibraryFetchStarted)
{
- sFullFetchStarted = TRUE;
- sFetchQueue.push_back(gInventoryLibraryRoot);
- sFetchQueue.push_back(gAgent.getInventoryRootID());
+ sLibraryFetchStarted = TRUE;
+ sFetchQueue.push_back(gInventory.getLibraryRootFolderID());
gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
}
}
@@ -1472,6 +1707,14 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id)
sFetchQueue.push_front(cat_id);
gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
}
+ if (cat_id == gInventory.getLibraryRootFolderID())
+ {
+ sLibraryFetchStarted = TRUE;
+ }
+ if (cat_id == gInventory.getRootFolderID())
+ {
+ sMyInventoryFetchStarted = TRUE;
+ }
}
}
}
@@ -1493,10 +1736,20 @@ void LLInventoryModel::stopBackgroundFetch()
gIdleCallbacks.deleteFunction(&LLInventoryModel::backgroundFetch, NULL);
sBulkFetchCount=0;
sMinTimeBetweenFetches=0.0f;
-// sFullFetchStarted=FALSE;
}
}
+// static
+void LLInventoryModel::setAllFoldersFetched()
+{
+ if (sMyInventoryFetchStarted &&
+ sLibraryFetchStarted)
+ {
+ sAllFoldersFetched = TRUE;
+ }
+ stopBackgroundFetch();
+}
+
//static
void LLInventoryModel::backgroundFetch(void*)
{
@@ -1515,11 +1768,8 @@ void LLInventoryModel::backgroundFetch(void*)
if (sFetchQueue.empty())
{
llinfos << "Inventory fetch completed" << llendl;
- if (sFullFetchStarted)
- {
- sAllFoldersFetched = TRUE;
- }
- stopBackgroundFetch();
+
+ setAllFoldersFetched();
return;
}
@@ -1682,10 +1932,25 @@ void LLInventoryModel::addCategory(LLViewerInventoryCategory* category)
void LLInventoryModel::addItem(LLViewerInventoryItem* item)
{
//llinfos << "LLInventoryModel::addItem()" << llendl;
+
+ // This can happen if assettype enums from llassettype.h ever change.
+ // For example, there is a known backwards compatibility issue in some viewer prototypes prior to when
+ // the AT_LINK enum changed from 23 to 24.
+ if ((item->getType() == LLAssetType::AT_NONE)
+ || LLAssetType::lookup(item->getType()) == LLAssetType::badLookup())
+ {
+ llwarns << "Got bad asset type for item [ name: " << item->getName() << " type: " << item->getType() << " inv-type: " << item->getInventoryType() << " ], ignoring." << llendl;
+ return;
+ }
if(item)
{
+ // This condition means that we tried to add a link without the baseobj being in memory.
+ // The item will show up as a broken link.
+ if (item->getIsBrokenLink())
+ {
+ llinfos << "Adding broken link [ name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ) parent: " << item->getParentUUID() << llendl;
+ }
mItemMap[item->getUUID()] = item;
- //mInventory[item->getUUID()] = item;
}
}
@@ -1709,7 +1974,7 @@ void LLInventoryModel::empty()
//mInventory.clear();
}
-void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update)
+void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update) const
{
LLViewerInventoryCategory* cat = getCategory(update.mCategoryID);
if(cat)
@@ -1733,21 +1998,23 @@ void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update)
descendents_actual += update.mDescendentDelta;
cat->setDescendentCount(descendents_actual);
cat->setVersion(++version);
- llinfos << "accounted: '" << cat->getName() << "' "
- << version << " with " << descendents_actual
- << " descendents." << llendl;
+ lldebugs << "accounted: '" << cat->getName() << "' "
+ << version << " with " << descendents_actual
+ << " descendents." << llendl;
}
}
if(!accounted)
{
- lldebugs << "No accounting for: '" << cat->getName() << "' "
+ // Error condition, this means that the category did not register that
+ // it got new descendents (perhaps because it is still being loaded)
+ // which means its descendent count will be wrong.
+ llwarns << "Accounting failed for '" << cat->getName() << "' version:"
<< version << llendl;
}
}
else
{
- llwarns << "No category found for update " << update.mCategoryID
- << llendl;
+ llwarns << "No category found for update " << update.mCategoryID << llendl;
}
}
@@ -1874,65 +2141,59 @@ bool LLInventoryModel::isCategoryComplete(const LLUUID& cat_id) const
}
bool LLInventoryModel::loadSkeleton(
- const LLInventoryModel::options_t& options,
+ const LLSD& options,
const LLUUID& owner_id)
{
lldebugs << "importing inventory skeleton for " << owner_id << llendl;
typedef std::set<LLPointer<LLViewerInventoryCategory>, InventoryIDPtrLess> cat_set_t;
cat_set_t temp_cats;
-
- update_map_t child_counts;
-
- LLUUID id;
- LLAssetType::EType preferred_type;
bool rv = true;
- for(options_t::const_iterator it = options.begin(); it < options.end(); ++it)
- {
- LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(owner_id);
- response_t::const_iterator no_response = (*it).end();
- response_t::const_iterator skel;
- skel = (*it).find("name");
- if(skel == no_response) goto clean_cat;
- cat->rename(std::string((*skel).second));
- skel = (*it).find("folder_id");
- if(skel == no_response) goto clean_cat;
- id.set((*skel).second);
- // if an id is null, it locks the viewer.
- if(id.isNull()) goto clean_cat;
- cat->setUUID(id);
- skel = (*it).find("parent_id");
- if(skel == no_response) goto clean_cat;
- id.set((*skel).second);
- cat->setParent(id);
- skel = (*it).find("type_default");
- if(skel == no_response)
- {
- preferred_type = LLAssetType::AT_NONE;
+
+ for(LLSD::array_const_iterator it = options.beginArray(),
+ end = options.endArray(); it != end; ++it)
+ {
+ LLSD name = (*it)["name"];
+ LLSD folder_id = (*it)["folder_id"];
+ LLSD parent_id = (*it)["parent_id"];
+ LLSD version = (*it)["version"];
+ if(name.isDefined()
+ && folder_id.isDefined()
+ && parent_id.isDefined()
+ && version.isDefined()
+ && folder_id.asUUID().notNull() // if an id is null, it locks the viewer.
+ )
+ {
+ LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(owner_id);
+ cat->rename(name.asString());
+ cat->setUUID(folder_id.asUUID());
+ cat->setParent(parent_id.asUUID());
+
+ LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
+ LLSD type_default = (*it)["type_default"];
+ if(type_default.isDefined())
+ {
+ preferred_type = (LLFolderType::EType)type_default.asInteger();
+ }
+ cat->setPreferredType(preferred_type);
+ cat->setVersion(version.asInteger());
+ temp_cats.insert(cat);
}
else
{
- S32 t = atoi((*skel).second.c_str());
- preferred_type = (LLAssetType::EType)t;
+ llwarns << "Unable to import near " << name.asString() << llendl;
+ rv = false;
}
- cat->setPreferredType(preferred_type);
- skel = (*it).find("version");
- if(skel == no_response) goto clean_cat;
- cat->setVersion(atoi((*skel).second.c_str()));
- temp_cats.insert(cat);
- continue;
- clean_cat:
- llwarns << "Unable to import near " << cat->getName() << llendl;
- rv = false;
- //delete cat; // automatic when cat is reasigned or destroyed
}
S32 cached_category_count = 0;
S32 cached_item_count = 0;
if(!temp_cats.empty())
{
+ update_map_t child_counts;
cat_array_t categories;
item_array_t items;
+ cat_set_t invalid_categories; // Used to mark categories that weren't successfully loaded.
std::string owner_id_str;
owner_id.toString(owner_id_str);
std::string path(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, owner_id_str));
@@ -1959,7 +2220,8 @@ bool LLInventoryModel::loadSkeleton(
llinfos << "Unable to gunzip " << gzip_filename << llendl;
}
}
- if(loadFromFile(inventory_filename, categories, items))
+ bool is_cache_obsolete = false;
+ if(loadFromFile(inventory_filename, categories, items, is_cache_obsolete))
{
// We were able to find a cache of files. So, use what we
// found to generate a set of categories we should add. We
@@ -1998,7 +2260,7 @@ bool LLInventoryModel::loadSkeleton(
}
// go ahead and add the cats returned during the download
- std::set<LLUUID>::iterator not_cached_id = cached_ids.end();
+ std::set<LLUUID>::const_iterator not_cached_id = cached_ids.end();
cached_category_count = cached_ids.size();
for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it)
{
@@ -2016,23 +2278,43 @@ bool LLInventoryModel::loadSkeleton(
// Add all the items loaded which are parented to a
// category with a correctly cached parent
- count = items.count();
+ S32 bad_link_count = 0;
cat_map_t::iterator unparented = mCategoryMap.end();
- for(int i = 0; i < count; ++i)
+ for(item_array_t::const_iterator item_iter = items.begin();
+ item_iter != items.end();
+ ++item_iter)
{
- cat_map_t::iterator cit = mCategoryMap.find(items[i]->getParentUUID());
+ LLViewerInventoryItem *item = (*item_iter).get();
+ const cat_map_t::iterator cit = mCategoryMap.find(item->getParentUUID());
if(cit != unparented)
{
- LLViewerInventoryCategory* cat = cit->second;
+ const LLViewerInventoryCategory* cat = cit->second.get();
if(cat->getVersion() != NO_VERSION)
{
- addItem(items[i]);
+ // This can happen if the linked object's baseobj is removed from the cache but the linked object is still in the cache.
+ if (item->getIsBrokenLink())
+ {
+ bad_link_count++;
+ lldebugs << "Attempted to add cached link item without baseobj present ( name: "
+ << item->getName() << " itemID: " << item->getUUID()
+ << " assetID: " << item->getAssetUUID()
+ << " ). Ignoring and invalidating " << cat->getName() << " . " << llendl;
+ invalid_categories.insert(cit->second);
+ continue;
+ }
+ addItem(item);
cached_item_count += 1;
++child_counts[cat->getUUID()];
}
}
}
+ if (bad_link_count > 0)
+ {
+ llinfos << "Attempted to add " << bad_link_count
+ << " cached link items without baseobj present. "
+ << "The corresponding categories were invalidated." << llendl;
+ }
}
else
{
@@ -2049,17 +2331,17 @@ bool LLInventoryModel::loadSkeleton(
// At this point, we need to set the known descendents for each
// category which successfully cached so that we do not
// needlessly fetch descendents for categories which we have.
- update_map_t::iterator no_child_counts = child_counts.end();
- update_map_t::iterator the_count;
+ update_map_t::const_iterator no_child_counts = child_counts.end();
for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it)
{
- LLViewerInventoryCategory* cat = (*it);
+ LLViewerInventoryCategory* cat = (*it).get();
if(cat->getVersion() != NO_VERSION)
{
- the_count = child_counts.find(cat->getUUID());
+ update_map_t::const_iterator the_count = child_counts.find(cat->getUUID());
if(the_count != no_child_counts)
{
- cat->setDescendentCount((*the_count).second.mValue);
+ const S32 num_descendents = (*the_count).second.mValue;
+ cat->setDescendentCount(num_descendents);
}
else
{
@@ -2068,11 +2350,28 @@ bool LLInventoryModel::loadSkeleton(
}
}
+ // Invalidate all categories that failed fetching descendents for whatever
+ // reason (e.g. one of the descendents was a broken link).
+ for (cat_set_t::iterator invalid_cat_it = invalid_categories.begin();
+ invalid_cat_it != invalid_categories.end();
+ invalid_cat_it++)
+ {
+ LLViewerInventoryCategory* cat = (*invalid_cat_it).get();
+ cat->setVersion(NO_VERSION);
+ llinfos << "Invalidating category name: " << cat->getName() << " UUID: " << cat->getUUID() << " due to invalid descendents cache" << llendl;
+ }
+
if(remove_inventory_file)
{
// clean up the gunzipped file.
LLFile::remove(inventory_filename);
}
+ if(is_cache_obsolete)
+ {
+ // If out of date, remove the gzipped file too.
+ llwarns << "Inv cache out of date, removing" << llendl;
+ LLFile::remove(gzip_filename);
+ }
categories.clear(); // will unref and delete entries
}
@@ -2083,85 +2382,84 @@ bool LLInventoryModel::loadSkeleton(
return rv;
}
-bool LLInventoryModel::loadMeat(
- const LLInventoryModel::options_t& options, const LLUUID& owner_id)
+bool LLInventoryModel::loadMeat(const LLSD& options, const LLUUID& owner_id)
{
llinfos << "importing inventory for " << owner_id << llendl;
- LLPermissions default_perm;
- default_perm.init(LLUUID::null, owner_id, LLUUID::null, LLUUID::null);
- LLPointer<LLViewerInventoryItem> item;
- LLUUID id;
- LLAssetType::EType type;
- LLInventoryType::EType inv_type;
bool rv = true;
- for(options_t::const_iterator it = options.begin(); it < options.end(); ++it)
- {
- item = new LLViewerInventoryItem;
- response_t::const_iterator no_response = (*it).end();
- response_t::const_iterator meat;
- meat = (*it).find("name");
- if(meat == no_response) goto clean_item;
- item->rename(std::string((*meat).second));
- meat = (*it).find("item_id");
- if(meat == no_response) goto clean_item;
- id.set((*meat).second);
- item->setUUID(id);
- meat = (*it).find("parent_id");
- if(meat == no_response) goto clean_item;
- id.set((*meat).second);
- item->setParent(id);
- meat = (*it).find("type");
- if(meat == no_response) goto clean_item;
- type = (LLAssetType::EType)atoi((*meat).second.c_str());
- item->setType(type);
- meat = (*it).find("inv_type");
- if(meat != no_response)
- {
- inv_type = (LLInventoryType::EType)atoi((*meat).second.c_str());
- item->setInventoryType(inv_type);
- }
- meat = (*it).find("data_id");
- if(meat == no_response) goto clean_item;
- id.set((*meat).second);
- if(LLAssetType::AT_CALLINGCARD == type)
- {
- LLPermissions perm;
- perm.init(id, owner_id, LLUUID::null, LLUUID::null);
- item->setPermissions(perm);
+ for(LLSD::array_const_iterator it = options.beginArray(),
+ end = options.endArray(); it != end; ++it)
+ {
+ LLSD name = (*it)["name"];
+ LLSD item_id = (*it)["item_id"];
+ LLSD parent_id = (*it)["parent_id"];
+ LLSD asset_type = (*it)["type"];
+ LLSD data_id = (*it)["data_id"];
+ if(name.isDefined()
+ && item_id.isDefined()
+ && parent_id.isDefined()
+ && asset_type.isDefined()
+ && data_id.isDefined())
+ {
+ LLPointer<LLViewerInventoryItem> item = new LLViewerInventoryItem;
+ item->rename(name.asString());
+ item->setUUID(item_id.asUUID());
+ item->setParent(parent_id.asUUID());
+ LLAssetType::EType type = (LLAssetType::EType)asset_type.asInteger();
+ item->setType(type);
+
+ LLSD llsd_inv_type = (*it)["inv_type"];
+ if(llsd_inv_type.isDefined())
+ {
+ LLInventoryType::EType inv_type = (LLInventoryType::EType)llsd_inv_type.asInteger();
+ item->setInventoryType(inv_type);
+ }
+
+ if(LLAssetType::AT_CALLINGCARD == type)
+ {
+ LLPermissions perm;
+ perm.init(data_id.asUUID(), owner_id, LLUUID::null, LLUUID::null);
+ item->setPermissions(perm);
+ }
+ else
+ {
+ LLPermissions default_perm;
+ default_perm.init(LLUUID::null, owner_id, LLUUID::null, LLUUID::null);
+ LLSD llsd_perm_mask = (*it)["perm_mask"];
+ if(llsd_perm_mask.isDefined())
+ {
+ PermissionMask perm_mask = llsd_perm_mask.asInteger();
+ default_perm.initMasks(
+ perm_mask, perm_mask, perm_mask, perm_mask, perm_mask);
+ }
+ else
+ {
+ default_perm.initMasks(
+ PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE);
+ }
+ item->setPermissions(default_perm);
+ item->setAssetUUID(data_id.asUUID());
+ }
+
+ LLSD flags = (*it)["flags"];
+ if(flags.isDefined())
+ {
+ // Not sure how well LLSD.asInteger() maps to
+ // unsigned long - using strtoul()
+ item->setFlags(strtoul(flags.asString().c_str(), NULL, 0));
+ }
+
+ LLSD time = (*it)["time"];
+ if(time.isDefined())
+ {
+ item->setCreationDate(time.asInteger());
+ }
+ addItem(item);
}
else
{
- meat = (*it).find("perm_mask");
- if(meat != no_response)
- {
- PermissionMask perm_mask = atoi((*meat).second.c_str());
- default_perm.initMasks(
- perm_mask, perm_mask, perm_mask, perm_mask, perm_mask);
- }
- else
- {
- default_perm.initMasks(
- PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE);
- }
- item->setPermissions(default_perm);
- item->setAssetUUID(id);
- }
- meat = (*it).find("flags");
- if(meat != no_response)
- {
- item->setFlags(strtoul((*meat).second.c_str(), NULL, 0));
- }
- meat = (*it).find("time");
- if(meat != no_response)
- {
- item->setCreationDate(atoi((*meat).second.c_str()));
+ llwarns << "Unable to import near " << name.asString() << llendl;
+ rv = false;
}
- addItem(item);
- continue;
- clean_item:
- llwarns << "Unable to import near " << item->getName() << llendl;
- rv = false;
- //delete item; // automatic when item is reassigned or destroyed
}
return rv;
}
@@ -2239,12 +2537,12 @@ void LLInventoryModel::buildParentChildMap()
<< cat->getName() << llendl;
++lost;
// plop it into the lost & found.
- LLAssetType::EType pref = cat->getPreferredType();
- if(LLAssetType::AT_NONE == pref)
+ LLFolderType::EType pref = cat->getPreferredType();
+ if(LLFolderType::FT_NONE == pref)
{
- cat->setParent(findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND));
+ cat->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND));
}
- else if(LLAssetType::AT_CATEGORY == pref)
+ else if(LLFolderType::FT_ROOT_INVENTORY == pref)
{
// it's the root
cat->setParent(LLUUID::null);
@@ -2252,7 +2550,7 @@ void LLInventoryModel::buildParentChildMap()
else
{
// it's a protected folder.
- cat->setParent(gAgent.getInventoryRootID());
+ cat->setParent(gInventory.getRootFolderID());
}
cat->updateServer(TRUE);
catsp = getUnlockedCatArray(cat->getParentUUID());
@@ -2271,6 +2569,10 @@ void LLInventoryModel::buildParentChildMap()
llwarns << "Found " << lost << " lost categories." << llendl;
}
+ const BOOL COF_exists = (findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, FALSE) != LLUUID::null);
+ sFirstTimeInViewer2 = !COF_exists || gAgent.isFirstLogin();
+
+
// Now the items. We allocated in the last step, so now all we
// have to do is iterate over the items and put them in the right
// place.
@@ -2303,7 +2605,7 @@ void LLInventoryModel::buildParentChildMap()
++lost;
// plop it into the lost & found.
//
- item->setParent(findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND));
+ item->setParent(findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND));
// move it later using a special message to move items. If
// we update server here, the client might crash.
//item->updateServer();
@@ -2324,7 +2626,7 @@ void LLInventoryModel::buildParentChildMap()
llwarns << "Found " << lost << " lost items." << llendl;
LLMessageSystem* msg = gMessageSystem;
BOOL start_new_message = TRUE;
- LLUUID lnf = findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
+ const LLUUID lnf = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
for(std::vector<LLUUID>::iterator it = lost_item_ids.begin() ; it < lost_item_ids.end(); ++it)
{
if(start_new_message)
@@ -2352,16 +2654,47 @@ void LLInventoryModel::buildParentChildMap()
}
}
- const LLUUID& agent_inv_root_id = gAgent.getInventoryRootID();
+ const LLUUID &agent_inv_root_id = gInventory.getRootFolderID();
if (agent_inv_root_id.notNull())
{
cat_array_t* catsp = get_ptr_in_map(mParentChildCategoryTree, agent_inv_root_id);
if(catsp)
{
+ // *HACK - fix root inventory folder
+ // some accounts has pbroken inventory root folders
+
+ std::string name = "My Inventory";
+ LLUUID prev_root_id = mRootFolderID;
+ for (parent_cat_map_t::const_iterator it = mParentChildCategoryTree.begin(),
+ it_end = mParentChildCategoryTree.end(); it != it_end; ++it)
+ {
+ cat_array_t* cat_array = it->second;
+ for (cat_array_t::const_iterator cat_it = cat_array->begin(),
+ cat_it_end = cat_array->end(); cat_it != cat_it_end; ++cat_it)
+ {
+ LLPointer<LLViewerInventoryCategory> category = *cat_it;
+
+ if(category && category->getPreferredType() != LLFolderType::FT_ROOT_INVENTORY)
+ continue;
+ if ( category && 0 == LLStringUtil::compareInsensitive(name, category->getName()) )
+ {
+ if(category->getUUID()!=mRootFolderID)
+ {
+ LLUUID& new_inv_root_folder_id = const_cast<LLUUID&>(mRootFolderID);
+ new_inv_root_folder_id = category->getUUID();
+ }
+ }
+ }
+ }
+
// 'My Inventory',
// root of the agent's inv found.
// The inv tree is built.
mIsAgentInvUsable = true;
+
+ llinfos << "Inventory initialized, notifying observers" << llendl;
+ addChangedMask(LLInventoryObserver::ALL, LLUUID::null);
+ notifyObservers();
}
}
}
@@ -2468,7 +2801,8 @@ bool LLUUIDAndName::operator>(const LLUUIDAndName& rhs) const
// static
bool LLInventoryModel::loadFromFile(const std::string& filename,
LLInventoryModel::cat_array_t& categories,
- LLInventoryModel::item_array_t& items)
+ LLInventoryModel::item_array_t& items,
+ bool &is_cache_obsolete)
{
if(filename.empty())
{
@@ -2485,11 +2819,32 @@ bool LLInventoryModel::loadFromFile(const std::string& filename,
// *NOTE: This buffer size is hard coded into scanf() below.
char buffer[MAX_STRING]; /*Flawfinder: ignore*/
char keyword[MAX_STRING]; /*Flawfinder: ignore*/
+ char value[MAX_STRING]; /*Flawfinder: ignore*/
+ is_cache_obsolete = true; // Obsolete until proven current
while(!feof(file) && fgets(buffer, MAX_STRING, file))
{
- sscanf(buffer, " %254s", keyword); /* Flawfinder: ignore */
- if(0 == strcmp("inv_category", keyword))
+ sscanf(buffer, " %126s %126s", keyword, value); /* Flawfinder: ignore */
+ if(0 == strcmp("inv_cache_version", keyword))
{
+ S32 version;
+ int succ = sscanf(value,"%d",&version);
+ if ((1 == succ) && (version == sCurrentInvCacheVersion))
+ {
+ // Cache is up to date
+ is_cache_obsolete = false;
+ continue;
+ }
+ else
+ {
+ // Cache is out of date
+ break;
+ }
+ }
+ else if(0 == strcmp("inv_category", keyword))
+ {
+ if (is_cache_obsolete)
+ break;
+
LLPointer<LLViewerInventoryCategory> inv_cat = new LLViewerInventoryCategory(LLUUID::null);
if(inv_cat->importFileLocal(file))
{
@@ -2503,6 +2858,9 @@ bool LLInventoryModel::loadFromFile(const std::string& filename,
}
else if(0 == strcmp("inv_item", keyword))
{
+ if (is_cache_obsolete)
+ break;
+
LLPointer<LLViewerInventoryItem> inv_item = new LLViewerInventoryItem;
if( inv_item->importFileLocal(file) )
{
@@ -2534,6 +2892,8 @@ bool LLInventoryModel::loadFromFile(const std::string& filename,
}
}
fclose(file);
+ if (is_cache_obsolete)
+ return false;
return true;
}
@@ -2555,6 +2915,7 @@ bool LLInventoryModel::saveToFile(const std::string& filename,
return false;
}
+ fprintf(file, "\tinv_cache_version\t%d\n",sCurrentInvCacheVersion);
S32 count = categories.count();
S32 i;
for(i = 0; i < count; ++i)
@@ -2773,7 +3134,7 @@ void LLInventoryModel::processUpdateInventoryFolder(LLMessageSystem* msg,
lastfolder = tfolder;
tfolder->unpackMessage(msg, _PREHASH_FolderData, i);
// make sure it's not a protected folder
- tfolder->setPreferredType(LLAssetType::AT_NONE);
+ tfolder->setPreferredType(LLFolderType::FT_NONE);
folders.push_back(tfolder);
// examine update for changes.
LLViewerInventoryCategory* folderp = gInventory.getCategory(tfolder->getUUID());
@@ -2802,10 +3163,10 @@ void LLInventoryModel::processUpdateInventoryFolder(LLMessageSystem* msg,
gInventory.notifyObservers();
// *HACK: Do the 'show' logic for a new item in the inventory.
- LLInventoryView* view = LLInventoryView::getActiveInventory();
- if(view)
+ LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel();
+ if (active_panel)
{
- view->getPanel()->setSelection(lastfolder->getUUID(), TAKE_FOCUS_NO);
+ active_panel->setSelection(lastfolder->getUUID(), TAKE_FOCUS_NO);
}
}
@@ -3011,13 +3372,13 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
// The incoming inventory could span more than one BulkInventoryUpdate packet,
// so record the transaction ID for this purchase, then wear all clothing
// that comes in as part of that transaction ID. JC
- if (LLInventoryView::sWearNewClothing)
+ if (LLInventoryState::sWearNewClothing)
{
- LLInventoryView::sWearNewClothingTransactionID = tid;
- LLInventoryView::sWearNewClothing = FALSE;
+ LLInventoryState::sWearNewClothingTransactionID = tid;
+ LLInventoryState::sWearNewClothing = FALSE;
}
- if (tid == LLInventoryView::sWearNewClothingTransactionID)
+ if (tid == LLInventoryState::sWearNewClothingTransactionID)
{
count = wearable_ids.size();
for (i = 0; i < count; ++i)
@@ -3035,7 +3396,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
gInventoryCallbacks.fire(cbinfo.mCallback, cbinfo.mInvID);
}
// Don't show the inventory. We used to call showAgentInventory here.
- //LLInventoryView* view = LLInventoryView::getActiveInventory();
+ //LLFloaterInventory* view = LLFloaterInventory::getActiveInventory();
//if(view)
//{
// const BOOL take_keyboard_focus = FALSE;
@@ -3045,10 +3406,10 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
// // HACK to open inventory offers that are accepted. This information
// // really needs to flow through the instant messages and inventory
// // transfer/update messages.
- // if (LLInventoryView::sOpenNextNewItem)
+ // if (LLFloaterInventory::sOpenNextNewItem)
// {
// view->openSelected();
- // LLInventoryView::sOpenNextNewItem = FALSE;
+ // LLFloaterInventory::sOpenNextNewItem = FALSE;
// }
//
// // restore keyboard focus
@@ -3063,8 +3424,7 @@ void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**)
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
if(agent_id != gAgent.getID())
{
- llwarns << "Got a UpdateInventoryItem for the wrong agent."
- << llendl;
+ llwarns << "Got a UpdateInventoryItem for the wrong agent." << llendl;
return;
}
LLUUID parent_id;
@@ -3075,6 +3435,7 @@ void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**)
msg->getS32("AgentData", "Version", version);
S32 descendents;
msg->getS32("AgentData", "Descendents", descendents);
+
S32 i;
S32 count = msg->getNumberOfBlocksFast(_PREHASH_FolderData);
LLPointer<LLViewerInventoryCategory> tcategory = new LLViewerInventoryCategory(owner_id);
@@ -3089,6 +3450,12 @@ void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**)
for(i = 0; i < count; ++i)
{
titem->unpackMessage(msg, _PREHASH_ItemData, i);
+ // If the item has already been added (e.g. from link prefetch), then it doesn't need to be re-added.
+ if (gInventory.getItem(titem->getUUID()))
+ {
+ lldebugs << "Skipping prefetched item [ Name: " << titem->getName() << " | Type: " << titem->getActualType() << " | ItemUUID: " << titem->getUUID() << " ] " << llendl;
+ continue;
+ }
gInventory.updateItem(titem);
}
@@ -3098,6 +3465,9 @@ void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**)
{
cat->setVersion(version);
cat->setDescendentCount(descendents);
+ // Get this UUID on the changed list so that whatever's listening for it
+ // will get triggered.
+ gInventory.addChangedMask(LLInventoryObserver::INTERNAL, cat->getUUID());
}
gInventory.notifyObservers();
}
@@ -3158,14 +3528,206 @@ void LLInventoryModel::processMoveInventoryItem(LLMessageSystem* msg, void**)
}
}
+//----------------------------------------------------------------------------
+
+// Trash: LLFolderType::FT_TRASH, "ConfirmEmptyTrash"
+// Lost&Found: LLFolderType::FT_LOST_AND_FOUND, "ConfirmEmptyLostAndFound"
+
+bool LLInventoryModel::callbackEmptyFolderType(const LLSD& notification, const LLSD& response, LLFolderType::EType preferred_type)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option == 0) // YES
+ {
+ const LLUUID folder_id = findCategoryUUIDForType(preferred_type);
+ purgeDescendentsOf(folder_id);
+ notifyObservers();
+ }
+ return false;
+}
+
+void LLInventoryModel::emptyFolderType(const std::string notification, LLFolderType::EType preferred_type)
+{
+ if (!notification.empty())
+ {
+ LLNotificationsUtil::add(notification, LLSD(), LLSD(),
+ boost::bind(&LLInventoryModel::callbackEmptyFolderType, this, _1, _2, preferred_type));
+ }
+ else
+ {
+ const LLUUID folder_id = findCategoryUUIDForType(preferred_type);
+ purgeDescendentsOf(folder_id);
+ notifyObservers();
+ }
+}
+
+//----------------------------------------------------------------------------
+
+void LLInventoryModel::removeItem(const LLUUID& item_id)
+{
+ LLViewerInventoryItem* item = getItem(item_id);
+ const LLUUID new_parent = findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ if (item && item->getParentUUID() != new_parent)
+ {
+ LLInventoryModel::update_list_t update;
+ LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
+ update.push_back(old_folder);
+ LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1);
+ update.push_back(new_folder);
+ accountForUpdate(update);
+
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ new_item->setParent(new_parent);
+ new_item->updateParentOnServer(TRUE);
+ updateItem(new_item);
+ notifyObservers();
+ }
+}
+
+const LLUUID &LLInventoryModel::getRootFolderID() const
+{
+ return mRootFolderID;
+}
+
+void LLInventoryModel::setRootFolderID(const LLUUID& val)
+{
+ mRootFolderID = val;
+}
+
+const LLUUID &LLInventoryModel::getLibraryRootFolderID() const
+{
+ return mLibraryRootFolderID;
+}
+
+void LLInventoryModel::setLibraryRootFolderID(const LLUUID& val)
+{
+ mLibraryRootFolderID = val;
+}
+
+const LLUUID &LLInventoryModel::getLibraryOwnerID() const
+{
+ return mLibraryOwnerID;
+}
+
+void LLInventoryModel::setLibraryOwnerID(const LLUUID& val)
+{
+ mLibraryOwnerID = val;
+}
+
+// static
+BOOL LLInventoryModel::getIsFirstTimeInViewer2()
+{
+ // Do not call this before parentchild map is built.
+ if (!gInventory.mIsAgentInvUsable)
+ {
+ llwarns << "Parent Child Map not yet built; guessing as first time in viewer2." << llendl;
+ return TRUE;
+ }
+
+ return sFirstTimeInViewer2;
+}
+
+static LLInventoryModel::item_array_t::iterator find_item_iter_by_uuid(LLInventoryModel::item_array_t& items, const LLUUID& id)
+{
+ LLInventoryModel::item_array_t::iterator result = items.end();
+
+ for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
+ {
+ if ((*i)->getUUID() == id)
+ {
+ result = i;
+ break;
+ }
+ }
+
+ return result;
+}
+
+// static
+void LLInventoryModel::updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& src_item_id, const LLUUID& dest_item_id)
+{
+ LLInventoryModel::item_array_t::iterator it_src = find_item_iter_by_uuid(items, src_item_id);
+ LLInventoryModel::item_array_t::iterator it_dest = find_item_iter_by_uuid(items, dest_item_id);
+
+ if (it_src == items.end() || it_dest == items.end()) return;
+
+ LLViewerInventoryItem* src_item = *it_src;
+ items.erase(it_src);
+
+ // target iterator can not be valid because the container was changed, so update it.
+ it_dest = find_item_iter_by_uuid(items, dest_item_id);
+ items.insert(it_dest, src_item);
+}
+
+void LLInventoryModel::saveItemsOrder(const LLInventoryModel::item_array_t& items)
+{
+ int sortField = 0;
+
+ // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field
+ for (item_array_t::const_iterator i = items.begin(); i != items.end(); ++i)
+ {
+ LLViewerInventoryItem* item = *i;
+
+ item->setSortField(++sortField);
+ item->setComplete(TRUE);
+ item->updateServer(FALSE);
+
+ updateItem(item);
+
+ // Tell the parent folder to refresh its sort order.
+ addChangedMask(LLInventoryObserver::SORT, item->getParentUUID());
+ }
+
+ notifyObservers();
+}
+
+// See also LLInventorySort where landmarks in the Favorites folder are sorted.
+class LLViewerInventoryItemSort
+{
+public:
+ bool operator()(const LLPointer<LLViewerInventoryItem>& a, const LLPointer<LLViewerInventoryItem>& b)
+ {
+ return a->getSortField() < b->getSortField();
+ }
+};
+
+/**
+ * Sorts passed items by LLViewerInventoryItem sort field.
+ *
+ * @param[in, out] items - array of items, not sorted.
+ */
+static void rearrange_item_order_by_sort_field(LLInventoryModel::item_array_t& items)
+{
+ static LLViewerInventoryItemSort sort_functor;
+ std::sort(items.begin(), items.end(), sort_functor);
+}
+
+void LLInventoryModel::rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id)
+{
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ LLIsType is_type(LLAssetType::AT_LANDMARK);
+ LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+ gInventory.collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type);
+
+ // ensure items are sorted properly before changing order. EXT-3498
+ rearrange_item_order_by_sort_field(items);
+
+ // update order
+ updateItemsOrder(items, source_item_id, target_item_id);
+
+ saveItemsOrder(items);
+}
+
+//----------------------------------------------------------------------------
+
// *NOTE: DEBUG functionality
-void LLInventoryModel::dumpInventory()
+void LLInventoryModel::dumpInventory() const
{
llinfos << "\nBegin Inventory Dump\n**********************:" << llendl;
- llinfos << "mCategroy[] contains " << mCategoryMap.size() << " items." << llendl;
- for(cat_map_t::iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit)
+ llinfos << "mCategory[] contains " << mCategoryMap.size() << " items." << llendl;
+ for(cat_map_t::const_iterator cit = mCategoryMap.begin(); cit != mCategoryMap.end(); ++cit)
{
- LLViewerInventoryCategory* cat = cit->second;
+ const LLViewerInventoryCategory* cat = cit->second;
if(cat)
{
llinfos << " " << cat->getUUID() << " '" << cat->getName() << "' "
@@ -3178,9 +3740,9 @@ void LLInventoryModel::dumpInventory()
}
}
llinfos << "mItemMap[] contains " << mItemMap.size() << " items." << llendl;
- for(item_map_t::iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit)
+ for(item_map_t::const_iterator iit = mItemMap.begin(); iit != mItemMap.end(); ++iit)
{
- LLViewerInventoryItem* item = iit->second;
+ const LLViewerInventoryItem* item = iit->second;
if(item)
{
llinfos << " " << item->getUUID() << " "
@@ -3205,7 +3767,7 @@ bool LLInventoryCollectFunctor::itemTransferCommonlyAllowed(LLInventoryItem* ite
return false;
bool allowed = false;
- LLVOAvatar* my_avatar = NULL;
+ LLVOAvatarSelf* my_avatar = NULL;
switch(item->getType())
{
@@ -3223,7 +3785,7 @@ bool LLInventoryCollectFunctor::itemTransferCommonlyAllowed(LLInventoryItem* ite
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_CLOTHING:
- if(!gAgent.isWearingItem(item->getUUID()))
+ if(!gAgentWearables.isWearingItem(item->getUUID()))
{
allowed = true;
}
@@ -3377,522 +3939,24 @@ bool LLNameCategoryCollector::operator()(
return false;
}
-
-
///----------------------------------------------------------------------------
-/// Observers
+/// LLAssetIDMatches
///----------------------------------------------------------------------------
-
-void LLInventoryCompletionObserver::changed(U32 mask)
-{
- // scan through the incomplete items and move or erase them as
- // appropriate.
- if(!mIncomplete.empty())
- {
- for(item_ref_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); )
- {
- LLViewerInventoryItem* item = gInventory.getItem(*it);
- if(!item)
- {
- it = mIncomplete.erase(it);
- continue;
- }
- if(item->isComplete())
- {
- mComplete.push_back(*it);
- it = mIncomplete.erase(it);
- continue;
- }
- ++it;
- }
- if(mIncomplete.empty())
- {
- done();
- }
- }
-}
-
-void LLInventoryCompletionObserver::watchItem(const LLUUID& id)
-{
- if(id.notNull())
- {
- mIncomplete.push_back(id);
- }
-}
-
-
-void LLInventoryFetchObserver::changed(U32 mask)
-{
- // scan through the incomplete items and move or erase them as
- // appropriate.
- if(!mIncomplete.empty())
- {
- for(item_ref_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); )
- {
- LLViewerInventoryItem* item = gInventory.getItem(*it);
- if(!item)
- {
- // BUG: This can cause done() to get called prematurely below.
- // This happens with the LLGestureInventoryFetchObserver that
- // loads gestures at startup. JC
- it = mIncomplete.erase(it);
- continue;
- }
- if(item->isComplete())
- {
- mComplete.push_back(*it);
- it = mIncomplete.erase(it);
- continue;
- }
- ++it;
- }
- if(mIncomplete.empty())
- {
- done();
- }
- }
- //llinfos << "LLInventoryFetchObserver::changed() mComplete size " << mComplete.size() << llendl;
- //llinfos << "LLInventoryFetchObserver::changed() mIncomplete size " << mIncomplete.size() << llendl;
-}
-
-bool LLInventoryFetchObserver::isEverythingComplete() const
-{
- return mIncomplete.empty();
-}
-
-void fetch_items_from_llsd(const LLSD& items_llsd)
-{
- if (!items_llsd.size()) return;
- LLSD body;
- body[0]["cap_name"] = "FetchInventory";
- body[1]["cap_name"] = "FetchLib";
- for (S32 i=0; i<items_llsd.size();i++)
- {
- if (items_llsd[i]["owner_id"].asString() == gAgent.getID().asString())
- {
- body[0]["items"].append(items_llsd[i]);
- continue;
- }
- if (items_llsd[i]["owner_id"].asString() == ALEXANDRIA_LINDEN_ID.asString())
- {
- body[1]["items"].append(items_llsd[i]);
- continue;
- }
- }
-
- for (S32 i=0; i<body.size(); i++)
- {
- if (0 >= body[i].size()) continue;
- std::string url = gAgent.getRegion()->getCapability(body[i]["cap_name"].asString());
-
- if (!url.empty())
- {
- body[i]["agent_id"] = gAgent.getID();
- LLHTTPClient::post(url, body[i], new LLInventoryModel::fetchInventoryResponder(body[i]));
- break;
- }
-
- LLMessageSystem* msg = gMessageSystem;
- BOOL start_new_message = TRUE;
- for (S32 j=0; j<body[i]["items"].size(); j++)
- {
- LLSD item_entry = body[i]["items"][j];
- if(start_new_message)
- {
- start_new_message = FALSE;
- msg->newMessageFast(_PREHASH_FetchInventory);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- }
- msg->nextBlockFast(_PREHASH_InventoryData);
- msg->addUUIDFast(_PREHASH_OwnerID, item_entry["owner_id"].asUUID());
- msg->addUUIDFast(_PREHASH_ItemID, item_entry["item_id"].asUUID());
- if(msg->isSendFull(NULL))
- {
- start_new_message = TRUE;
- gAgent.sendReliableMessage();
- }
- }
- if(!start_new_message)
- {
- gAgent.sendReliableMessage();
- }
- }
-}
-
-void LLInventoryFetchObserver::fetchItems(
- const LLInventoryFetchObserver::item_ref_t& ids)
-{
- LLUUID owner_id;
- LLSD items_llsd;
- for(item_ref_t::const_iterator it = ids.begin(); it < ids.end(); ++it)
- {
- LLViewerInventoryItem* item = gInventory.getItem(*it);
- if(item)
- {
- if(item->isComplete())
- {
- // It's complete, so put it on the complete container.
- mComplete.push_back(*it);
- continue;
- }
- else
- {
- owner_id = item->getPermissions().getOwner();
- }
- }
- else
- {
- // assume it's agent inventory.
- owner_id = gAgent.getID();
- }
-
- // It's incomplete, so put it on the incomplete container, and
- // pack this on the message.
- mIncomplete.push_back(*it);
-
- // Prepare the data to fetch
- LLSD item_entry;
- item_entry["owner_id"] = owner_id;
- item_entry["item_id"] = (*it);
- items_llsd.append(item_entry);
- }
- fetch_items_from_llsd(items_llsd);
-}
-
-// virtual
-void LLInventoryFetchDescendentsObserver::changed(U32 mask)
-{
- for(folder_ref_t::iterator it = mIncompleteFolders.begin(); it < mIncompleteFolders.end();)
- {
- LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
- if(!cat)
- {
- it = mIncompleteFolders.erase(it);
- continue;
- }
- if(isComplete(cat))
- {
- mCompleteFolders.push_back(*it);
- it = mIncompleteFolders.erase(it);
- continue;
- }
- ++it;
- }
- if(mIncompleteFolders.empty())
- {
- done();
- }
-}
-
-void LLInventoryFetchDescendentsObserver::fetchDescendents(
- const folder_ref_t& ids)
-{
- for(folder_ref_t::const_iterator it = ids.begin(); it != ids.end(); ++it)
- {
- LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
- if(!cat) continue;
- if(!isComplete(cat))
- {
- cat->fetchDescendents(); //blindly fetch it without seeing if anything else is fetching it.
- mIncompleteFolders.push_back(*it); //Add to list of things being downloaded for this observer.
- }
- else
- {
- mCompleteFolders.push_back(*it);
- }
- }
-}
-
-bool LLInventoryFetchDescendentsObserver::isEverythingComplete() const
+bool LLAssetIDMatches::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
- return mIncompleteFolders.empty();
-}
-
-bool LLInventoryFetchDescendentsObserver::isComplete(LLViewerInventoryCategory* cat)
-{
- S32 version = cat->getVersion();
- S32 descendents = cat->getDescendentCount();
- if((LLViewerInventoryCategory::VERSION_UNKNOWN == version)
- || (LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN == descendents))
- {
- return false;
- }
- // it might be complete - check known descendents against
- // currently available.
- LLInventoryModel::cat_array_t* cats;
- LLInventoryModel::item_array_t* items;
- gInventory.getDirectDescendentsOf(cat->getUUID(), cats, items);
- if(!cats || !items)
- {
- // bit of a hack - pretend we're done if they are gone or
- // incomplete. should never know, but it would suck if this
- // kept tight looping because of a corrupt memory state.
- return true;
- }
- S32 known = cats->count() + items->count();
- if(descendents == known)
- {
- // hey - we're done.
- return true;
- }
- return false;
-}
-
-void LLInventoryFetchComboObserver::changed(U32 mask)
-{
- if(!mIncompleteItems.empty())
- {
- for(item_ref_t::iterator it = mIncompleteItems.begin(); it < mIncompleteItems.end(); )
- {
- LLViewerInventoryItem* item = gInventory.getItem(*it);
- if(!item)
- {
- it = mIncompleteItems.erase(it);
- continue;
- }
- if(item->isComplete())
- {
- mCompleteItems.push_back(*it);
- it = mIncompleteItems.erase(it);
- continue;
- }
- ++it;
- }
- }
- if(!mIncompleteFolders.empty())
- {
- for(folder_ref_t::iterator it = mIncompleteFolders.begin(); it < mIncompleteFolders.end();)
- {
- LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
- if(!cat)
- {
- it = mIncompleteFolders.erase(it);
- continue;
- }
- if(gInventory.isCategoryComplete(*it))
- {
- mCompleteFolders.push_back(*it);
- it = mIncompleteFolders.erase(it);
- continue;
- }
- ++it;
- }
- }
- if(!mDone && mIncompleteItems.empty() && mIncompleteFolders.empty())
- {
- mDone = true;
- done();
- }
-}
-
-void LLInventoryFetchComboObserver::fetch(
- const folder_ref_t& folder_ids,
- const item_ref_t& item_ids)
-{
- lldebugs << "LLInventoryFetchComboObserver::fetch()" << llendl;
- for(folder_ref_t::const_iterator fit = folder_ids.begin(); fit != folder_ids.end(); ++fit)
- {
- LLViewerInventoryCategory* cat = gInventory.getCategory(*fit);
- if(!cat) continue;
- if(!gInventory.isCategoryComplete(*fit))
- {
- cat->fetchDescendents();
- lldebugs << "fetching folder " << *fit <<llendl;
- mIncompleteFolders.push_back(*fit);
- }
- else
- {
- mCompleteFolders.push_back(*fit);
- lldebugs << "completing folder " << *fit <<llendl;
- }
- }
-
- // Now for the items - we fetch everything which is not a direct
- // descendent of an incomplete folder because the item will show
- // up in an inventory descendents message soon enough so we do not
- // have to fetch it individually.
- LLSD items_llsd;
- LLUUID owner_id;
- for(item_ref_t::const_iterator iit = item_ids.begin(); iit != item_ids.end(); ++iit)
- {
- LLViewerInventoryItem* item = gInventory.getItem(*iit);
- if(!item)
- {
- lldebugs << "uanble to find item " << *iit << llendl;
- continue;
- }
- if(item->isComplete())
- {
- // It's complete, so put it on the complete container.
- mCompleteItems.push_back(*iit);
- lldebugs << "completing item " << *iit << llendl;
- continue;
- }
- else
- {
- mIncompleteItems.push_back(*iit);
- owner_id = item->getPermissions().getOwner();
- }
- if(std::find(mIncompleteFolders.begin(), mIncompleteFolders.end(), item->getParentUUID()) == mIncompleteFolders.end())
- {
- LLSD item_entry;
- item_entry["owner_id"] = owner_id;
- item_entry["item_id"] = (*iit);
- items_llsd.append(item_entry);
- }
- else
- {
- lldebugs << "not worrying about " << *iit << llendl;
- }
- }
- fetch_items_from_llsd(items_llsd);
-}
-
-void LLInventoryExistenceObserver::watchItem(const LLUUID& id)
-{
- if(id.notNull())
- {
- mMIA.push_back(id);
- }
-}
-
-void LLInventoryExistenceObserver::changed(U32 mask)
-{
- // scan through the incomplete items and move or erase them as
- // appropriate.
- if(!mMIA.empty())
- {
- for(item_ref_t::iterator it = mMIA.begin(); it < mMIA.end(); )
- {
- LLViewerInventoryItem* item = gInventory.getItem(*it);
- if(!item)
- {
- ++it;
- continue;
- }
- mExist.push_back(*it);
- it = mMIA.erase(it);
- }
- if(mMIA.empty())
- {
- done();
- }
- }
-}
-
-void LLInventoryAddedObserver::changed(U32 mask)
-{
- if(!(mask & LLInventoryObserver::ADD))
- {
- return;
- }
-
- // *HACK: If this was in response to a packet off
- // the network, figure out which item was updated.
- LLMessageSystem* msg = gMessageSystem;
-
- std::string msg_name;
- if (mMessageName.empty())
- {
- msg_name = msg->getMessageName();
- }
- else
- {
- msg_name = mMessageName;
- }
-
- if (msg_name.empty())
- {
- return;
- }
-
- // We only want newly created inventory items. JC
- if ( msg_name != "UpdateCreateInventoryItem")
- {
- return;
- }
-
- LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
- S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_InventoryData);
- for(S32 i = 0; i < num_blocks; ++i)
- {
- titem->unpackMessage(msg, _PREHASH_InventoryData, i);
- if (!(titem->getUUID().isNull()))
- {
- //we don't do anything with null keys
- mAdded.push_back(titem->getUUID());
- }
- }
- if (!mAdded.empty())
- {
- done();
- }
-}
-
-LLInventoryTransactionObserver::LLInventoryTransactionObserver(
- const LLTransactionID& transaction_id) :
- mTransactionID(transaction_id)
-{
-}
-
-void LLInventoryTransactionObserver::changed(U32 mask)
-{
- if(mask & LLInventoryObserver::ADD)
- {
- // This could be it - see if we are processing a bulk update
- LLMessageSystem* msg = gMessageSystem;
- if(msg->getMessageName()
- && (0 == strcmp(msg->getMessageName(), "BulkUpdateInventory")))
- {
- // we have a match for the message - now check the
- // transaction id.
- LLUUID id;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TransactionID, id);
- if(id == mTransactionID)
- {
- // woo hoo, we found it
- folder_ref_t folders;
- item_ref_t items;
- S32 count;
- count = msg->getNumberOfBlocksFast(_PREHASH_FolderData);
- S32 i;
- for(i = 0; i < count; ++i)
- {
- msg->getUUIDFast(_PREHASH_FolderData, _PREHASH_FolderID, id, i);
- if(id.notNull())
- {
- folders.push_back(id);
- }
- }
- count = msg->getNumberOfBlocksFast(_PREHASH_ItemData);
- for(i = 0; i < count; ++i)
- {
- msg->getUUIDFast(_PREHASH_ItemData, _PREHASH_ItemID, id, i);
- if(id.notNull())
- {
- items.push_back(id);
- }
- }
-
- // call the derived class the implements this method.
- done(folders, items);
- }
- }
- }
+ return (item && item->getAssetUUID() == mAssetID);
}
-
///----------------------------------------------------------------------------
-/// LLAssetIDMatches
+/// LLLinkedItemIDMatches
///----------------------------------------------------------------------------
-bool LLAssetIDMatches ::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+bool LLLinkedItemIDMatches::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
- return (item && item->getAssetUUID() == mAssetID);
+ return (item &&
+ (item->getIsLinkType()) &&
+ (item->getLinkedUUID() == mBaseItemID)); // A linked item's assetID will be the compared-to item's itemID.
}
-
///----------------------------------------------------------------------------
/// Local function definitions
///----------------------------------------------------------------------------
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index d73fef7207..2a2b48ce3c 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -34,44 +34,29 @@
#define LL_LLINVENTORYMODEL_H
#include "llassettype.h"
+#include "llfoldertype.h"
#include "lldarray.h"
+#include "llframetimer.h"
+#include "llhttpclient.h"
#include "lluuid.h"
#include "llpermissionsflags.h"
#include "llstring.h"
-
#include <map>
#include <set>
#include <string>
#include <vector>
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryObserver
-//
-// This class is designed to be a simple abstract base class which can
-// relay messages when the inventory changes.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLInventoryObserver;
+class LLInventoryObject;
+class LLInventoryItem;
+class LLInventoryCategory;
+class LLViewerInventoryItem;
+class LLViewerInventoryCategory;
+class LLViewerInventoryItem;
+class LLViewerInventoryCategory;
+class LLMessageSystem;
+class LLInventoryCollectFunctor;
-class LLInventoryObserver
-{
-public:
- // This enumeration is a way to refer to what changed in a more
- // human readable format. You can mask the value provided by
- // chaged() to see if the observer is interested in the change.
- enum
- {
- NONE = 0,
- LABEL = 1, // name changed
- INTERNAL = 2, // internal change, eg, asset uuid different
- ADD = 4, // something added
- REMOVE = 8, // something deleted
- STRUCTURE = 16, // structural change, eg, item or folder moved
- CALLING_CARD = 32, // online, grant status, cancel, etc change
- ALL = 0xffffffff
- };
- virtual ~LLInventoryObserver() {};
- virtual void changed(U32 mask) = 0;
- std::string mMessageName; // used by Agent Inventory Service only. [DEV-20328]
-};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLInventoryModel
@@ -84,38 +69,35 @@ public:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLInventoryObject;
-class LLInventoryItem;
-class LLInventoryCategory;
-class LLViewerInventoryItem;
-class LLViewerInventoryCategory;
-class LLViewerInventoryItem;
-class LLViewerInventoryCategory;
-class LLMessageSystem;
-class LLInventoryCollectFunctor;
-
class LLInventoryModel
{
public:
- typedef enum e_has_children
+ friend class LLInventoryModelFetchDescendentsResponder;
+
+ enum EHasChildren
{
CHILDREN_NO,
CHILDREN_YES,
CHILDREN_MAYBE
- }EHasChildren;
+ };
// These are used a lot...
typedef LLDynamicArray<LLPointer<LLViewerInventoryCategory> > cat_array_t;
typedef LLDynamicArray<LLPointer<LLViewerInventoryItem> > item_array_t;
+ typedef std::set<LLUUID> changed_items_t;
+
// construction & destruction
LLInventoryModel();
~LLInventoryModel();
-
- class fetchInventoryResponder: public LLHTTPClient::Responder
+
+ void cleanupInventory();
+
+ class fetchInventoryResponder : public LLHTTPClient::Responder
{
public:
fetchInventoryResponder(const LLSD& request_sd) : mRequestSD(request_sd) {};
void result(const LLSD& content);
+
void error(U32 status, const std::string& reason);
public:
@@ -128,9 +110,11 @@ public:
// Accessors
//
- // This is a convenience function to 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);
+ // 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;
+
+ // Get whatever special folder this object is a child of, if any.
+ const LLViewerInventoryCategory *getFirstNondefaultParent(const LLUUID& obj_id) const;
// Get the object by id. Returns NULL if not found.
// * WARNING: use the pointer returned for read operations - do
@@ -167,7 +151,7 @@ public:
item_array_t*& items);
void unlockDirectDescendentArrays(const LLUUID& cat_id);
- // Starting with the object specified, add it's descendents to the
+ // Starting with the object specified, add its descendents to the
// array provided, but do not add the inventory object specified
// by id. There is no guaranteed order. Neither array will be
// erased before adding objects to it. Do not store a copy of the
@@ -178,17 +162,24 @@ public:
cat_array_t& categories,
item_array_t& items,
BOOL include_trash);
-
void collectDescendentsIf(const LLUUID& id,
cat_array_t& categories,
item_array_t& items,
BOOL include_trash,
- LLInventoryCollectFunctor& add);
+ LLInventoryCollectFunctor& add,
+ BOOL follow_folder_links = FALSE);
+
+ // Collect all items in inventory that are linked to item_id.
+ // Assumes item_id is itself not a linked item.
+ item_array_t collectLinkedItems(const LLUUID& item_id,
+ const LLUUID& start_folder_id = LLUUID::null);
+
+ // Get the inventoryID that this item points to, else just return item_id
+ const LLUUID& getLinkedItemID(const LLUUID& object_id) const;
- // This method will return false if this inventory model is in an usabel state.
// The inventory model usage is sensitive to the initial construction of the
// model.
- bool isInventoryUsable();
+ bool isInventoryUsable() const;
//
// Mutators
@@ -197,7 +188,7 @@ public:
// Calling this method with an inventory item will either change
// an existing item with a matching item_id, or will add the item
// to the current inventory. Returns the change mask generated by
- // the update. No notifcation will be sent to observers. This
+ // the update. No notification will be sent to observers. This
// method will only generate network traffic if the item had to be
// reparented.
// *NOTE: In usage, you will want to perform cache accounting
@@ -224,16 +215,21 @@ public:
// delete a particular inventory object by ID. This will purge one
// object from the internal data structures maintaining a
- // cosistent internal state. No cache accounting, observer
- // notification, or server update is performed.
+ // consistent internal state. No cache accounting, observer
+ // notification, or server update is performed. Purges linked items.
void deleteObject(const LLUUID& id);
+
+ // delete a particular inventory object by ID, and delete it from
+ // the server. Also updates linked items.
+ void purgeObject(const LLUUID& id);
+ void updateLinkedObjectsFromPurge(const LLUUID& baseobj_id);
- // This is a method which collects the descendents of the id
+ // This is a method which collects the descendants of the id
// provided. If the category is not found, no action is
// taken. This method goes through the long winded process of
// removing server representation of folders and items while doing
// cache accounting in a fairly efficient manner. This method does
- // not notify observers (though maybe it shouldd...)
+ // not notify observers (though maybe it should...)
void purgeDescendentsOf(const LLUUID& id);
// This method optimally removes the referenced categories and
@@ -247,7 +243,7 @@ public:
// to remove it.
void addObserver(LLInventoryObserver* observer);
void removeObserver(LLInventoryObserver* observer);
- BOOL containsObserver(LLInventoryObserver* observer);
+ BOOL containsObserver(LLInventoryObserver* observer) const;
//
// Misc Methods
@@ -255,17 +251,19 @@ public:
// findCategoryUUIDForType() returns the uuid of the category that
// specifies 'type' as what it defaults to containing. The
- // category is not necessarily only for that type. *NOTE: This
- // will create a new inventory category on the fly if one does not
- // exist.
-
+ // category is not necessarily only for that type. *NOTE: If create_folder is true, this
+ // will create a new inventory category on the fly if one does not exist. *NOTE: if find_in_library is
+ // true it will search in the user's library folder instead of "My Inventory"
// SDK: Added flag to specify whether the folder should be created if not found. This fixes the horrible
// multiple trash can bug.
- LLUUID findCategoryUUIDForType(LLAssetType::EType preferred_type, bool create_folder = true);
+ const LLUUID findCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder = true, bool find_in_library = false);
+
+ // This gets called by the idle loop. It only updates if new
+ // state is detected. Call notifyObservers() manually to update
+ // regardless of whether state change has been indicated.
+ void idleNotifyObservers();
- // Call this method when it's time to update everyone on a new
- // state, by default, the inventory model will not update
- // observers automatically.
+ // Call this method to explicitly update everyone on a new state.
// The optional argument 'service_name' is used by Agent Inventory Service [DEV-20328]
void notifyObservers(const std::string service_name="");
@@ -277,17 +275,15 @@ public:
// that the next notify will include that notification.
void addChangedMask(U32 mask, const LLUUID& referent);
- const std::set<LLUUID>& getChangedIDs() { return mChangedItemIDs; }
+ const changed_items_t& getChangedIDs() const { return mChangedItemIDs; }
// This method to prepares a set of mock inventory which provides
// minimal functionality before the actual arrival of inventory.
//void mock(const LLUUID& root_id);
- // make sure we have the descendents in the structure.
- void fetchDescendentsOf(const LLUUID& folder_id);
-
- // Add categories to a list to be fetched in bulk.
- static void bulkFetch(std::string url);
+ // Make sure we have the descendents in the structure. Returns true
+ // if a fetch was performed.
+ bool fetchDescendentsOf(const LLUUID& folder_id);
// call this method to request the inventory.
//void requestFromServer(const LLUUID& agent_id);
@@ -297,7 +293,7 @@ public:
// Generates a string containing the path to the item specified by
// item_id.
- void appendPath(const LLUUID& id, std::string& path);
+ void appendPath(const LLUUID& id, std::string& path) const;
// message handling functionality
static void registerCallbacks(LLMessageSystem* msg);
@@ -309,15 +305,13 @@ public:
// category. If you want to use the default name based on type,
// pass in a NULL to the 'name parameter.
LLUUID createNewCategory(const LLUUID& parent_id,
- LLAssetType::EType preferred_type,
+ LLFolderType::EType preferred_type,
const std::string& name);
// methods to load up inventory skeleton & meat. These are used
// during authentication. return true if everything parsed.
- typedef std::map<std::string, std::string> response_t;
- typedef std::vector<response_t> options_t;
- bool loadSkeleton(const options_t& options, const LLUUID& owner_id);
- bool loadMeat(const options_t& options, const LLUUID& owner_id);
+ bool loadSkeleton(const LLSD& options, const LLUUID& owner_id);
+ bool loadMeat(const LLSD& options, const LLUUID& owner_id);
// This is a brute force method to rebuild the entire parent-child
// relations.
@@ -355,7 +349,7 @@ public:
// Call these methods when there are category updates, but call
// them *before* the actual update so the method can do descendent
// accounting correctly.
- void accountForUpdate(const LLCategoryUpdate& update);
+ void accountForUpdate(const LLCategoryUpdate& update) const;
void accountForUpdate(const update_list_t& updates);
void accountForUpdate(const update_map_t& updates);
@@ -365,15 +359,64 @@ public:
// returns true iff category version is known and theoretical
// descendents == actual descendents.
bool isCategoryComplete(const LLUUID& cat_id) const;
+
+ // callbacks
+ // Trigger a notification and empty the folder type (FT_TRASH or FT_LOST_AND_FOUND) if confirmed
+ void emptyFolderType(const std::string notification, LLFolderType::EType folder_type);
+ bool callbackEmptyFolderType(const LLSD& notification, const LLSD& response, LLFolderType::EType preferred_type);
- // start and stop background breadth-first fetching of inventory contents
- // this gets triggered when performing a filter-search
- static void startBackgroundFetch(const LLUUID& cat_id = LLUUID::null); // start fetch process
+ // Utility Functions
+ void removeItem(const LLUUID& item_id);
+
static void findLostItems();
- static BOOL backgroundFetchActive();
- static bool isEverythingFetched();
- static void backgroundFetch(void*); // background fetch idle function
- static void incrBulkFetch(S16 fetching) { sBulkFetchCount+=fetching; if (sBulkFetchCount<0) sBulkFetchCount=0; }
+
+ // Data about the agent's root folder and root library folder
+ // are stored here, rather than in LLAgent where it used to be, because
+ // gInventory is a singleton and represents the agent's inventory.
+ // The "library" is actually the inventory of a special agent,
+ // usually Alexandria Linden.
+ const LLUUID &getRootFolderID() const;
+ const LLUUID &getLibraryOwnerID() const;
+ const LLUUID &getLibraryRootFolderID() const;
+
+ // These are set during login with data from the server
+ void setRootFolderID(const LLUUID& id);
+ void setLibraryOwnerID(const LLUUID& id);
+ void setLibraryRootFolderID(const LLUUID& id);
+
+
+ /**
+ * Changes items order by insertion of the item identified by src_item_id
+ * BEFORE the item identified by dest_item_id. Both items must exist in items array.
+ *
+ * Sorting is stored after method is finished. Only src_item_id is moved before dest_item_id.
+ *
+ * @param[in, out] items - vector with items to be updated. It should be sorted in a right way
+ * before calling this method.
+ * @param src_item_id - LLUUID of inventory item to be moved in new position
+ * @param dest_item_id - LLUUID of inventory item before which source item should be placed.
+ */
+ static void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& src_item_id, const LLUUID& dest_item_id);
+
+ /**
+ * Saves current order of the passed items using inventory item sort field.
+ *
+ * It reset items' sort fields and saves them on server.
+ * Is used to save order for Favorites folder.
+ *
+ * @param[in] items vector of items in order to be saved.
+ */
+ void saveItemsOrder(const LLInventoryModel::item_array_t& items);
+
+ /**
+ * Rearranges Landmarks inside Favorites folder.
+ * Moves source landmark before target one.
+ *
+ * @param source_item_id - LLUUID of the source item to be moved into new position
+ * @param target_item_id - LLUUID of the target item before which source item should be placed.
+ */
+ void rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id);
+
protected:
// Internal methods which add inventory and make sure that all of
@@ -383,9 +426,13 @@ protected:
void addCategory(LLViewerInventoryCategory* category);
void addItem(LLViewerInventoryItem* item);
+ // ! DEPRECRATE ! Remove this and add it into findCategoryUUIDForType,
+ // since that's the only function that uses this. It's too confusing
+ // having both methods.
+ //
// Internal method which looks for a category with the specified
// preferred type. Returns LLUUID::null if not found
- LLUUID findCatUUID(LLAssetType::EType preferred_type);
+ const LLUUID &findCatUUID(LLFolderType::EType preferred_type, bool find_in_library = false) const;
// Empty the entire contents
void empty();
@@ -399,7 +446,8 @@ protected:
// file import/export.
static bool loadFromFile(const std::string& filename,
cat_array_t& categories,
- item_array_t& items);
+ item_array_t& items,
+ bool& is_cache_obsolete);
static bool saveToFile(const std::string& filename,
const cat_array_t& categories,
const item_array_t& items);
@@ -421,27 +469,18 @@ protected:
bool messageUpdateCore(LLMessageSystem* msg, bool do_accounting);
+ // Updates all linked items pointing to this id.
+ void addChangedMaskForLinks(const LLUUID& object_id, U32 mask);
+
protected:
cat_array_t* getUnlockedCatArray(const LLUUID& id);
item_array_t* getUnlockedItemArray(const LLUUID& id);
-protected:
- // Varaibles used to track what has changed since the last notify.
+private:
+ // Variables used to track what has changed since the last notify.
U32 mModifyMask;
- typedef std::set<LLUUID> changed_items_t;
changed_items_t mChangedItemIDs;
- // Information for tracking the actual inventory. We index this
- // information in a lot of different ways so we can access
- // the inventory using several different identifiers.
- // mInventory member data is the 'master' list of inventory, and
- // mCategoryMap and mItemMap store uuid->object mappings.
- typedef std::map<LLUUID, LLPointer<LLViewerInventoryCategory> > cat_map_t;
- typedef std::map<LLUUID, LLPointer<LLViewerInventoryItem> > item_map_t;
- //inv_map_t mInventory;
- cat_map_t mCategoryMap;
- item_map_t mItemMap;
-
std::map<LLUUID, bool> mCategoryLock;
std::map<LLUUID, bool> mItemLock;
@@ -457,26 +496,83 @@ protected:
typedef std::set<LLInventoryObserver*> observer_list_t;
observer_list_t mObservers;
- // completing the fetch once per session should be sufficient
- static BOOL sBackgroundFetchActive;
+ // Agent inventory folder information.
+ LLUUID mRootFolderID;
+ LLUUID mLibraryRootFolderID;
+ LLUUID mLibraryOwnerID;
+
static BOOL sTimelyFetchPending;
static S32 sNumFetchRetries;
static LLFrameTimer sFetchTimer;
static F32 sMinTimeBetweenFetches;
static F32 sMaxTimeBetweenFetches;
- static S16 sBulkFetchCount;
+ // Expected inventory cache version
+ const static S32 sCurrentInvCacheVersion;
+
// This flag is used to handle an invalid inventory state.
bool mIsAgentInvUsable;
+private:
+ // Information for tracking the actual inventory. We index this
+ // information in a lot of different ways so we can access
+ // the inventory using several different identifiers.
+ // mInventory member data is the 'master' list of inventory, and
+ // mCategoryMap and mItemMap store uuid->object mappings.
+ typedef std::map<LLUUID, LLPointer<LLViewerInventoryCategory> > cat_map_t;
+ typedef std::map<LLUUID, LLPointer<LLViewerInventoryItem> > item_map_t;
+ //inv_map_t mInventory;
+ cat_map_t mCategoryMap;
+ item_map_t mItemMap;
+
+ // Flag set when notifyObservers is being called, to look for bugs
+ // where it's called recursively.
+ BOOL mIsNotifyObservers;
public:
// *NOTE: DEBUG functionality
- void dumpInventory();
- static bool isBulkFetchProcessingComplete();
+ void dumpInventory() const;
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Bulk fetch
+public:
+ // Start and stop background breadth-first fetching of inventory contents.
+ // This gets triggered when performing a filter-search
+ void startBackgroundFetch(const LLUUID& cat_id = LLUUID::null);
+ static BOOL backgroundFetchActive();
+ static bool isEverythingFetched();
+ static void backgroundFetch(void*); // background fetch idle function
+ static void incrBulkFetch(S16 fetching) { sBulkFetchCount+=fetching; if (sBulkFetchCount<0) sBulkFetchCount=0; }
static void stopBackgroundFetch(); // stop fetch process
+ static bool isBulkFetchProcessingComplete();
+
+ // Add categories to a list to be fetched in bulk.
+ static void bulkFetch(std::string url);
- static BOOL sFullFetchStarted;
+ static bool libraryFetchStarted();
+ static bool libraryFetchCompleted();
+ static bool libraryFetchInProgress();
+
+ static bool myInventoryFetchStarted();
+ static bool myInventoryFetchCompleted();
+ static bool myInventoryFetchInProgress();
+
+private:
+ static BOOL sMyInventoryFetchStarted;
+ static BOOL sLibraryFetchStarted;
static BOOL sAllFoldersFetched;
+ static void setAllFoldersFetched();
+
+ // completing the fetch once per session should be sufficient
+ static BOOL sBackgroundFetchActive;
+ static S16 sBulkFetchCount;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Login status
+public:
+ static BOOL getIsFirstTimeInViewer2();
+private:
+ static BOOL sFirstTimeInViewer2;
};
// a special inventory model for the agent
@@ -520,6 +616,22 @@ protected:
LLUUID mAssetID;
};
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLLinkedItemIDMatches
+//
+// This functor finds inventory items linked to the specific inventory id.
+// Assumes the inventory id is itself not a linked item.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLLinkedItemIDMatches : public LLInventoryCollectFunctor
+{
+public:
+ LLLinkedItemIDMatches(const LLUUID& item_id) : mBaseItemID(item_id) {}
+ virtual ~LLLinkedItemIDMatches() {}
+ bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
+
+protected:
+ LLUUID mBaseItemID;
+};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLIsType
@@ -666,183 +778,34 @@ protected:
std::string mName;
};
-
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryCompletionObserver
+// Class LLFindCOFValidItems
//
-// Class which can be used as a base class for doing something when
-// when all observed items are locally complete. This class implements
-// the changed() method of LLInventoryObserver and declares a new
-// method named done() which is called when all watched items have
-// complete information in the inventory model.
+// Collects items that can be legitimately linked to in the COF.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLInventoryCompletionObserver : public LLInventoryObserver
+class LLFindCOFValidItems : public LLInventoryCollectFunctor
{
public:
- LLInventoryCompletionObserver() {}
- virtual void changed(U32 mask);
-
- void watchItem(const LLUUID& id);
-
-protected:
- virtual void done() = 0;
-
- typedef std::vector<LLUUID> item_ref_t;
- item_ref_t mComplete;
- item_ref_t mIncomplete;
-};
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryFetchObserver
-//
-// This class is much like the LLInventoryCompletionObserver, except
-// that it handles all the the fetching necessary. Override the done()
-// method to do the thing you want.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLInventoryFetchObserver : public LLInventoryObserver
-{
-public:
- LLInventoryFetchObserver() {}
- virtual void changed(U32 mask);
-
- typedef std::vector<LLUUID> item_ref_t;
-
- bool isEverythingComplete() const;
- void fetchItems(const item_ref_t& ids);
- virtual void done() = 0;
-
-protected:
- item_ref_t mComplete;
- item_ref_t mIncomplete;
-};
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryFetchDescendentsObserver
-//
-// This class is much like the LLInventoryCompletionObserver, except
-// that it handles fetching based on category. Override the done()
-// method to do the thing you want.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLInventoryFetchDescendentsObserver : public LLInventoryObserver
-{
-public:
- LLInventoryFetchDescendentsObserver() {}
- virtual void changed(U32 mask);
-
- typedef std::vector<LLUUID> folder_ref_t;
- void fetchDescendents(const folder_ref_t& ids);
- bool isEverythingComplete() const;
- virtual void done() = 0;
-
-protected:
- bool isComplete(LLViewerInventoryCategory* cat);
- folder_ref_t mIncompleteFolders;
- folder_ref_t mCompleteFolders;
-};
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryFetchComboObserver
-//
-// This class does an appropriate combination of fetch descendents and
-// item fetches based on completion of categories and items. Much like
-// the fetch and fetch descendents, this will call done() when everything
-// has arrived.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLInventoryFetchComboObserver : public LLInventoryObserver
-{
-public:
- LLInventoryFetchComboObserver() : mDone(false) {}
- virtual void changed(U32 mask);
-
- typedef std::vector<LLUUID> folder_ref_t;
- typedef std::vector<LLUUID> item_ref_t;
- void fetch(const folder_ref_t& folder_ids, const item_ref_t& item_ids);
-
- virtual void done() = 0;
-
-protected:
- bool mDone;
- folder_ref_t mCompleteFolders;
- folder_ref_t mIncompleteFolders;
- item_ref_t mCompleteItems;
- item_ref_t mIncompleteItems;
-};
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryExistenceObserver
-//
-// This class is used as a base class for doing somethign when all the
-// observed item ids exist in the inventory somewhere. You can derive
-// a class from this class and implement the done() method to do
-// something useful.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLInventoryExistenceObserver : public LLInventoryObserver
-{
-public:
- LLInventoryExistenceObserver() {}
- virtual void changed(U32 mask);
-
- void watchItem(const LLUUID& id);
-
-protected:
- virtual void done() = 0;
-
- typedef std::vector<LLUUID> item_ref_t;
- item_ref_t mExist;
- item_ref_t mMIA;
-};
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryAddedObserver
-//
-// This class is used as a base class for doing something when
-// a new item arrives in inventory.
-// It does not watch for a certain UUID, rather it acts when anything is added
-// Derive a class from this class and implement the done() method to do
-// something useful.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLInventoryAddedObserver : public LLInventoryObserver
-{
-public:
- LLInventoryAddedObserver() : mAdded() {}
- virtual void changed(U32 mask);
-
-protected:
- virtual void done() = 0;
-
- typedef std::vector<LLUUID> item_ref_t;
- item_ref_t mAdded;
+ LLFindCOFValidItems() {}
+ virtual ~LLFindCOFValidItems() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item);
+
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryTransactionObserver
+// Class LLFindWearables
//
-// Class which can be used as a base class for doing something when an
-// inventory transaction completes.
-//
-// *NOTE: This class is not quite complete. Avoid using unless you fix up it's
-// functionality gaps.
+// Collects wearables based on item type.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLInventoryTransactionObserver : public LLInventoryObserver
+class LLFindWearables : public LLInventoryCollectFunctor
{
public:
- LLInventoryTransactionObserver(const LLTransactionID& transaction_id);
- virtual void changed(U32 mask);
-
-protected:
- typedef std::vector<LLUUID> folder_ref_t;
- typedef std::vector<LLUUID> item_ref_t;
- virtual void done(const folder_ref_t& folders, const item_ref_t& items) = 0;
-
- LLTransactionID mTransactionID;
+ LLFindWearables() {}
+ virtual ~LLFindWearables() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item);
};
-
#endif // LL_LLINVENTORYMODEL_H
diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
new file mode 100644
index 0000000000..2fb8aea4e9
--- /dev/null
+++ b/indra/newview/llinventoryobserver.cpp
@@ -0,0 +1,596 @@
+/**
+ * @file llinventoryobserver.cpp
+ * @brief Implementation of the inventory observers used to track agent inventory.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llinventoryobserver.h"
+
+#include "llassetstorage.h"
+#include "llcrc.h"
+#include "lldir.h"
+#include "llsys.h"
+#include "llxfermanager.h"
+#include "message.h"
+
+#include "llagent.h"
+#include "llagentwearables.h"
+#include "llfloater.h"
+#include "llfocusmgr.h"
+#include "llinventorybridge.h"
+#include "llinventoryfunctions.h"
+#include "llinventorymodel.h"
+#include "llviewermessage.h"
+#include "llviewerwindow.h"
+#include "llviewerregion.h"
+#include "llappviewer.h"
+#include "lldbstrings.h"
+#include "llviewerstats.h"
+#include "llmutelist.h"
+#include "llnotificationsutil.h"
+#include "llcallbacklist.h"
+#include "llpreview.h"
+#include "llviewercontrol.h"
+#include "llvoavatarself.h"
+#include "llsdutil.h"
+#include <deque>
+
+LLInventoryObserver::LLInventoryObserver()
+{
+}
+
+// virtual
+LLInventoryObserver::~LLInventoryObserver()
+{
+}
+
+void LLInventoryCompletionObserver::changed(U32 mask)
+{
+ // scan through the incomplete items and move or erase them as
+ // appropriate.
+ if(!mIncomplete.empty())
+ {
+ for(item_ref_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); )
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(*it);
+ if(!item)
+ {
+ it = mIncomplete.erase(it);
+ continue;
+ }
+ if(item->isComplete())
+ {
+ mComplete.push_back(*it);
+ it = mIncomplete.erase(it);
+ continue;
+ }
+ ++it;
+ }
+ if(mIncomplete.empty())
+ {
+ done();
+ }
+ }
+}
+
+void LLInventoryCompletionObserver::watchItem(const LLUUID& id)
+{
+ if(id.notNull())
+ {
+ mIncomplete.push_back(id);
+ }
+}
+
+
+void LLInventoryFetchObserver::changed(U32 mask)
+{
+ // scan through the incomplete items and move or erase them as
+ // appropriate.
+ if(!mIncomplete.empty())
+ {
+ for(item_ref_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); )
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(*it);
+ if(!item)
+ {
+ if (mRetryIfMissing)
+ {
+ // BAP changed to skip these items, so we should keep retrying until they arrive.
+ // Did not make this the default behavior because of uncertainty about impact -
+ // could cause some observers that currently complete to wait forever.
+ ++it;
+ }
+ else
+ {
+ // BUG: This can cause done() to get called prematurely below.
+ // This happens with the LLGestureInventoryFetchObserver that
+ // loads gestures at startup. JC
+ it = mIncomplete.erase(it);
+ }
+ continue;
+ }
+ if(item->isComplete())
+ {
+ mComplete.push_back(*it);
+ it = mIncomplete.erase(it);
+ continue;
+ }
+ ++it;
+ }
+ if(mIncomplete.empty())
+ {
+ done();
+ }
+ }
+ //llinfos << "LLInventoryFetchObserver::changed() mComplete size " << mComplete.size() << llendl;
+ //llinfos << "LLInventoryFetchObserver::changed() mIncomplete size " << mIncomplete.size() << llendl;
+}
+
+bool LLInventoryFetchObserver::isEverythingComplete() const
+{
+ return mIncomplete.empty();
+}
+
+void fetch_items_from_llsd(const LLSD& items_llsd)
+{
+ if (!items_llsd.size()) return;
+ LLSD body;
+ body[0]["cap_name"] = "FetchInventory";
+ body[1]["cap_name"] = "FetchLib";
+ for (S32 i=0; i<items_llsd.size();i++)
+ {
+ if (items_llsd[i]["owner_id"].asString() == gAgent.getID().asString())
+ {
+ body[0]["items"].append(items_llsd[i]);
+ continue;
+ }
+ if (items_llsd[i]["owner_id"].asString() == ALEXANDRIA_LINDEN_ID.asString())
+ {
+ body[1]["items"].append(items_llsd[i]);
+ continue;
+ }
+ }
+
+ for (S32 i=0; i<body.size(); i++)
+ {
+ if (0 >= body[i].size()) continue;
+ std::string url = gAgent.getRegion()->getCapability(body[i]["cap_name"].asString());
+
+ if (!url.empty())
+ {
+ body[i]["agent_id"] = gAgent.getID();
+ LLHTTPClient::post(url, body[i], new LLInventoryModel::fetchInventoryResponder(body[i]));
+ break;
+ }
+
+ LLMessageSystem* msg = gMessageSystem;
+ BOOL start_new_message = TRUE;
+ for (S32 j=0; j<body[i]["items"].size(); j++)
+ {
+ LLSD item_entry = body[i]["items"][j];
+ if(start_new_message)
+ {
+ start_new_message = FALSE;
+ msg->newMessageFast(_PREHASH_FetchInventory);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ }
+ msg->nextBlockFast(_PREHASH_InventoryData);
+ msg->addUUIDFast(_PREHASH_OwnerID, item_entry["owner_id"].asUUID());
+ msg->addUUIDFast(_PREHASH_ItemID, item_entry["item_id"].asUUID());
+ if(msg->isSendFull(NULL))
+ {
+ start_new_message = TRUE;
+ gAgent.sendReliableMessage();
+ }
+ }
+ if(!start_new_message)
+ {
+ gAgent.sendReliableMessage();
+ }
+ }
+}
+
+void LLInventoryFetchObserver::fetchItems(
+ const LLInventoryFetchObserver::item_ref_t& ids)
+{
+ LLUUID owner_id;
+ LLSD items_llsd;
+ for(item_ref_t::const_iterator it = ids.begin(); it < ids.end(); ++it)
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(*it);
+ if(item)
+ {
+ if(item->isComplete())
+ {
+ // It's complete, so put it on the complete container.
+ mComplete.push_back(*it);
+ continue;
+ }
+ else
+ {
+ owner_id = item->getPermissions().getOwner();
+ }
+ }
+ else
+ {
+ // assume it's agent inventory.
+ owner_id = gAgent.getID();
+ }
+
+ // It's incomplete, so put it on the incomplete container, and
+ // pack this on the message.
+ mIncomplete.push_back(*it);
+
+ // Prepare the data to fetch
+ LLSD item_entry;
+ item_entry["owner_id"] = owner_id;
+ item_entry["item_id"] = (*it);
+ items_llsd.append(item_entry);
+ }
+ fetch_items_from_llsd(items_llsd);
+}
+
+// virtual
+void LLInventoryFetchDescendentsObserver::changed(U32 mask)
+{
+ for(folder_ref_t::iterator it = mIncompleteFolders.begin(); it < mIncompleteFolders.end();)
+ {
+ LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
+ if(!cat)
+ {
+ it = mIncompleteFolders.erase(it);
+ continue;
+ }
+ if(isComplete(cat))
+ {
+ mCompleteFolders.push_back(*it);
+ it = mIncompleteFolders.erase(it);
+ continue;
+ }
+ ++it;
+ }
+ if(mIncompleteFolders.empty())
+ {
+ done();
+ }
+}
+
+void LLInventoryFetchDescendentsObserver::fetchDescendents(
+ const folder_ref_t& ids)
+{
+ for(folder_ref_t::const_iterator it = ids.begin(); it != ids.end(); ++it)
+ {
+ LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
+ if(!cat) continue;
+ if(!isComplete(cat))
+ {
+ cat->fetchDescendents(); //blindly fetch it without seeing if anything else is fetching it.
+ mIncompleteFolders.push_back(*it); //Add to list of things being downloaded for this observer.
+ }
+ else
+ {
+ mCompleteFolders.push_back(*it);
+ }
+ }
+}
+
+bool LLInventoryFetchDescendentsObserver::isEverythingComplete() const
+{
+ return mIncompleteFolders.empty();
+}
+
+bool LLInventoryFetchDescendentsObserver::isComplete(LLViewerInventoryCategory* cat)
+{
+ const S32 version = cat->getVersion();
+ const S32 expected_num_descendents = cat->getDescendentCount();
+ if ((version == LLViewerInventoryCategory::VERSION_UNKNOWN) ||
+ (expected_num_descendents == LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN))
+ {
+ return false;
+ }
+ // it might be complete - check known descendents against
+ // currently available.
+ LLInventoryModel::cat_array_t* cats;
+ LLInventoryModel::item_array_t* items;
+ gInventory.getDirectDescendentsOf(cat->getUUID(), cats, items);
+ if(!cats || !items)
+ {
+ llwarns << "Category '" << cat->getName() << "' descendents corrupted, fetch failed." << llendl;
+ // NULL means the call failed -- cats/items map doesn't exist (note: this does NOT mean
+ // that the cat just doesn't have any items or subfolders).
+ // Unrecoverable, so just return done so that this observer can be cleared
+ // from memory.
+ return true;
+ }
+ const S32 current_num_known_descendents = cats->count() + items->count();
+
+ // Got the number of descendents that we were expecting, so we're done.
+ if (current_num_known_descendents == expected_num_descendents)
+ {
+ return true;
+ }
+
+ // Error condition, but recoverable. This happens if something was added to the
+ // category before it was initialized, so accountForUpdate didn't update descendent
+ // count and thus the category thinks it has fewer descendents than it actually has.
+ if (current_num_known_descendents >= expected_num_descendents)
+ {
+ llwarns << "Category '" << cat->getName() << "' expected descendentcount:" << expected_num_descendents << " descendents but got descendentcount:" << current_num_known_descendents << llendl;
+ cat->setDescendentCount(current_num_known_descendents);
+ return true;
+ }
+ return false;
+}
+
+void LLInventoryFetchComboObserver::changed(U32 mask)
+{
+ if(!mIncompleteItems.empty())
+ {
+ for(item_ref_t::iterator it = mIncompleteItems.begin(); it < mIncompleteItems.end(); )
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(*it);
+ if(!item)
+ {
+ it = mIncompleteItems.erase(it);
+ continue;
+ }
+ if(item->isComplete())
+ {
+ mCompleteItems.push_back(*it);
+ it = mIncompleteItems.erase(it);
+ continue;
+ }
+ ++it;
+ }
+ }
+ if(!mIncompleteFolders.empty())
+ {
+ for(folder_ref_t::iterator it = mIncompleteFolders.begin(); it < mIncompleteFolders.end();)
+ {
+ LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
+ if(!cat)
+ {
+ it = mIncompleteFolders.erase(it);
+ continue;
+ }
+ if(gInventory.isCategoryComplete(*it))
+ {
+ mCompleteFolders.push_back(*it);
+ it = mIncompleteFolders.erase(it);
+ continue;
+ }
+ ++it;
+ }
+ }
+ if(!mDone && mIncompleteItems.empty() && mIncompleteFolders.empty())
+ {
+ mDone = true;
+ done();
+ }
+}
+
+void LLInventoryFetchComboObserver::fetch(
+ const folder_ref_t& folder_ids,
+ const item_ref_t& item_ids)
+{
+ lldebugs << "LLInventoryFetchComboObserver::fetch()" << llendl;
+ for(folder_ref_t::const_iterator fit = folder_ids.begin(); fit != folder_ids.end(); ++fit)
+ {
+ LLViewerInventoryCategory* cat = gInventory.getCategory(*fit);
+ if(!cat) continue;
+ if(!gInventory.isCategoryComplete(*fit))
+ {
+ cat->fetchDescendents();
+ lldebugs << "fetching folder " << *fit <<llendl;
+ mIncompleteFolders.push_back(*fit);
+ }
+ else
+ {
+ mCompleteFolders.push_back(*fit);
+ lldebugs << "completing folder " << *fit <<llendl;
+ }
+ }
+
+ // Now for the items - we fetch everything which is not a direct
+ // descendent of an incomplete folder because the item will show
+ // up in an inventory descendents message soon enough so we do not
+ // have to fetch it individually.
+ LLSD items_llsd;
+ LLUUID owner_id;
+ for(item_ref_t::const_iterator iit = item_ids.begin(); iit != item_ids.end(); ++iit)
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(*iit);
+ if(!item)
+ {
+ lldebugs << "uanble to find item " << *iit << llendl;
+ continue;
+ }
+ if(item->isComplete())
+ {
+ // It's complete, so put it on the complete container.
+ mCompleteItems.push_back(*iit);
+ lldebugs << "completing item " << *iit << llendl;
+ continue;
+ }
+ else
+ {
+ mIncompleteItems.push_back(*iit);
+ owner_id = item->getPermissions().getOwner();
+ }
+ if(std::find(mIncompleteFolders.begin(), mIncompleteFolders.end(), item->getParentUUID()) == mIncompleteFolders.end())
+ {
+ LLSD item_entry;
+ item_entry["owner_id"] = owner_id;
+ item_entry["item_id"] = (*iit);
+ items_llsd.append(item_entry);
+ }
+ else
+ {
+ lldebugs << "not worrying about " << *iit << llendl;
+ }
+ }
+ fetch_items_from_llsd(items_llsd);
+}
+
+void LLInventoryExistenceObserver::watchItem(const LLUUID& id)
+{
+ if(id.notNull())
+ {
+ mMIA.push_back(id);
+ }
+}
+
+void LLInventoryExistenceObserver::changed(U32 mask)
+{
+ // scan through the incomplete items and move or erase them as
+ // appropriate.
+ if(!mMIA.empty())
+ {
+ for(item_ref_t::iterator it = mMIA.begin(); it < mMIA.end(); )
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(*it);
+ if(!item)
+ {
+ ++it;
+ continue;
+ }
+ mExist.push_back(*it);
+ it = mMIA.erase(it);
+ }
+ if(mMIA.empty())
+ {
+ done();
+ }
+ }
+}
+
+void LLInventoryAddedObserver::changed(U32 mask)
+{
+ if(!(mask & LLInventoryObserver::ADD))
+ {
+ return;
+ }
+
+ // *HACK: If this was in response to a packet off
+ // the network, figure out which item was updated.
+ LLMessageSystem* msg = gMessageSystem;
+
+ std::string msg_name;
+ if (mMessageName.empty())
+ {
+ msg_name = msg->getMessageName();
+ }
+ else
+ {
+ msg_name = mMessageName;
+ }
+
+ if (msg_name.empty())
+ {
+ return;
+ }
+
+ // We only want newly created inventory items. JC
+ if ( msg_name != "UpdateCreateInventoryItem")
+ {
+ return;
+ }
+
+ LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
+ S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_InventoryData);
+ for(S32 i = 0; i < num_blocks; ++i)
+ {
+ titem->unpackMessage(msg, _PREHASH_InventoryData, i);
+ if (!(titem->getUUID().isNull()))
+ {
+ //we don't do anything with null keys
+ mAdded.push_back(titem->getUUID());
+ }
+ }
+ if (!mAdded.empty())
+ {
+ done();
+ }
+}
+
+LLInventoryTransactionObserver::LLInventoryTransactionObserver(
+ const LLTransactionID& transaction_id) :
+ mTransactionID(transaction_id)
+{
+}
+
+void LLInventoryTransactionObserver::changed(U32 mask)
+{
+ if(mask & LLInventoryObserver::ADD)
+ {
+ // This could be it - see if we are processing a bulk update
+ LLMessageSystem* msg = gMessageSystem;
+ if(msg->getMessageName()
+ && (0 == strcmp(msg->getMessageName(), "BulkUpdateInventory")))
+ {
+ // we have a match for the message - now check the
+ // transaction id.
+ LLUUID id;
+ msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TransactionID, id);
+ if(id == mTransactionID)
+ {
+ // woo hoo, we found it
+ folder_ref_t folders;
+ item_ref_t items;
+ S32 count;
+ count = msg->getNumberOfBlocksFast(_PREHASH_FolderData);
+ S32 i;
+ for(i = 0; i < count; ++i)
+ {
+ msg->getUUIDFast(_PREHASH_FolderData, _PREHASH_FolderID, id, i);
+ if(id.notNull())
+ {
+ folders.push_back(id);
+ }
+ }
+ count = msg->getNumberOfBlocksFast(_PREHASH_ItemData);
+ for(i = 0; i < count; ++i)
+ {
+ msg->getUUIDFast(_PREHASH_ItemData, _PREHASH_ItemID, id, i);
+ if(id.notNull())
+ {
+ items.push_back(id);
+ }
+ }
+
+ // call the derived class the implements this method.
+ done(folders, items);
+ }
+ }
+ }
+}
diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h
new file mode 100644
index 0000000000..d6dded52d4
--- /dev/null
+++ b/indra/newview/llinventoryobserver.h
@@ -0,0 +1,254 @@
+/**
+ * @file llinventoryobserver.h
+ * @brief LLInventoryObserver class header file
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLINVENTORYOBSERVERS_H
+#define LL_LLINVENTORYOBSERVERS_H
+
+#include "lluuid.h"
+#include <string>
+#include <vector>
+
+class LLViewerInventoryCategory;
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryObserver
+//
+// This class is designed to be a simple abstract base class which can
+// relay messages when the inventory changes.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLInventoryObserver
+{
+public:
+ // This enumeration is a way to refer to what changed in a more
+ // human readable format. You can mask the value provided by
+ // chaged() to see if the observer is interested in the change.
+ enum
+ {
+ NONE = 0,
+ LABEL = 1, // name changed
+ INTERNAL = 2, // internal change (e.g. asset uuid different)
+ ADD = 4, // something added
+ REMOVE = 8, // something deleted
+ STRUCTURE = 16, // structural change (eg item or folder moved)
+ CALLING_CARD = 32, // (eg online, grant status, cancel)
+ GESTURE = 64,
+ REBUILD = 128, // item UI changed (eg item type different)
+ SORT = 256, // folder needs to be resorted.
+ ALL = 0xffffffff
+ };
+ LLInventoryObserver();
+ virtual ~LLInventoryObserver();
+ virtual void changed(U32 mask) = 0;
+ std::string mMessageName; // used by Agent Inventory Service only. [DEV-20328]
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryCompletionObserver
+//
+// Class which can be used as a base class for doing something when
+// when all observed items are locally complete. This class implements
+// the changed() method of LLInventoryObserver and declares a new
+// method named done() which is called when all watched items have
+// complete information in the inventory model.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLInventoryCompletionObserver : public LLInventoryObserver
+{
+public:
+ LLInventoryCompletionObserver() {}
+ virtual void changed(U32 mask);
+
+ void watchItem(const LLUUID& id);
+
+protected:
+ virtual void done() = 0;
+
+ typedef std::vector<LLUUID> item_ref_t;
+ item_ref_t mComplete;
+ item_ref_t mIncomplete;
+};
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryFetchObserver
+//
+// This class is much like the LLInventoryCompletionObserver, except
+// that it handles all the the fetching necessary. Override the done()
+// method to do the thing you want.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLInventoryFetchObserver : public LLInventoryObserver
+{
+public:
+ LLInventoryFetchObserver(bool retry_if_missing = false): mRetryIfMissing(retry_if_missing) {}
+ virtual void changed(U32 mask);
+
+ typedef std::vector<LLUUID> item_ref_t;
+
+ bool isEverythingComplete() const;
+ void fetchItems(const item_ref_t& ids);
+ virtual void done() {};
+
+protected:
+ bool mRetryIfMissing;
+ item_ref_t mComplete;
+ item_ref_t mIncomplete;
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryFetchDescendentsObserver
+//
+// This class is much like the LLInventoryCompletionObserver, except
+// that it handles fetching based on category. Override the done()
+// method to do the thing you want.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLInventoryFetchDescendentsObserver : public LLInventoryObserver
+{
+public:
+ LLInventoryFetchDescendentsObserver() {}
+ virtual void changed(U32 mask);
+
+ typedef std::vector<LLUUID> folder_ref_t;
+ void fetchDescendents(const folder_ref_t& ids);
+ bool isEverythingComplete() const;
+ virtual void done() = 0;
+
+protected:
+ bool isComplete(LLViewerInventoryCategory* cat);
+ folder_ref_t mIncompleteFolders;
+ folder_ref_t mCompleteFolders;
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryFetchComboObserver
+//
+// This class does an appropriate combination of fetch descendents and
+// item fetches based on completion of categories and items. Much like
+// the fetch and fetch descendents, this will call done() when everything
+// has arrived.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLInventoryFetchComboObserver : public LLInventoryObserver
+{
+public:
+ LLInventoryFetchComboObserver() : mDone(false) {}
+ virtual void changed(U32 mask);
+
+ typedef std::vector<LLUUID> folder_ref_t;
+ typedef std::vector<LLUUID> item_ref_t;
+ void fetch(const folder_ref_t& folder_ids, const item_ref_t& item_ids);
+
+ virtual void done() = 0;
+
+protected:
+ bool mDone;
+ folder_ref_t mCompleteFolders;
+ folder_ref_t mIncompleteFolders;
+ item_ref_t mCompleteItems;
+ item_ref_t mIncompleteItems;
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryExistenceObserver
+//
+// This class is used as a base class for doing somethign when all the
+// observed item ids exist in the inventory somewhere. You can derive
+// a class from this class and implement the done() method to do
+// something useful.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLInventoryExistenceObserver : public LLInventoryObserver
+{
+public:
+ LLInventoryExistenceObserver() {}
+ virtual void changed(U32 mask);
+
+ void watchItem(const LLUUID& id);
+
+protected:
+ virtual void done() = 0;
+
+ typedef std::vector<LLUUID> item_ref_t;
+ item_ref_t mExist;
+ item_ref_t mMIA;
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryAddedObserver
+//
+// This class is used as a base class for doing something when
+// a new item arrives in inventory.
+// It does not watch for a certain UUID, rather it acts when anything is added
+// Derive a class from this class and implement the done() method to do
+// something useful.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLInventoryAddedObserver : public LLInventoryObserver
+{
+public:
+ LLInventoryAddedObserver() : mAdded() {}
+ virtual void changed(U32 mask);
+
+protected:
+ virtual void done() = 0;
+
+ typedef std::vector<LLUUID> item_ref_t;
+ item_ref_t mAdded;
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryTransactionObserver
+//
+// Class which can be used as a base class for doing something when an
+// inventory transaction completes.
+//
+// *NOTE: This class is not quite complete. Avoid using unless you fix up it's
+// functionality gaps.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLInventoryTransactionObserver : public LLInventoryObserver
+{
+public:
+ LLInventoryTransactionObserver(const LLTransactionID& transaction_id);
+ virtual void changed(U32 mask);
+
+protected:
+ typedef std::vector<LLUUID> folder_ref_t;
+ typedef std::vector<LLUUID> item_ref_t;
+ virtual void done(const folder_ref_t& folders, const item_ref_t& items) = 0;
+
+ LLTransactionID mTransactionID;
+};
+
+
+#endif // LL_LLINVENTORYOBSERVERS_H
+
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
new file mode 100644
index 0000000000..7e71ac90b4
--- /dev/null
+++ b/indra/newview/llinventorypanel.cpp
@@ -0,0 +1,935 @@
+/*
+ * @file llinventorypanel.cpp
+ * @brief Implementation of the inventory panel and associated stuff.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llinventorypanel.h"
+
+#include <utility> // for std::pair<>
+
+#include "llagent.h"
+#include "llagentwearables.h"
+#include "llappearancemgr.h"
+#include "llfloaterinventory.h"
+#include "llfloaterreg.h"
+#include "llimfloater.h"
+#include "llimview.h"
+#include "llinventorybridge.h"
+#include "llsidepanelinventory.h"
+#include "llsidetray.h"
+#include "llscrollcontainer.h"
+#include "llviewerfoldertype.h"
+#include "llvoavatarself.h"
+
+static LLDefaultChildRegistry::Register<LLInventoryPanel> r("inventory_panel");
+
+const std::string LLInventoryPanel::DEFAULT_SORT_ORDER = std::string("InventorySortOrder");
+const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("RecentItemsSortOrder");
+const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string("");
+static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER;
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryPanelObserver
+//
+// Bridge to support knowing when the inventory has changed.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLInventoryPanelObserver : public LLInventoryObserver
+{
+public:
+ LLInventoryPanelObserver(LLInventoryPanel* ip) : mIP(ip) {}
+ virtual ~LLInventoryPanelObserver() {}
+ virtual void changed(U32 mask)
+ {
+ mIP->modelChanged(mask);
+ }
+protected:
+ LLInventoryPanel* mIP;
+};
+
+LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
+ LLPanel(p),
+ mInventoryObserver(NULL),
+ mFolders(NULL),
+ mScroller(NULL),
+ mSortOrderSetting(p.sort_order_setting),
+ mInventory(p.inventory),
+ mAllowMultiSelect(p.allow_multi_select),
+ mViewsInitialized(false),
+ mStartFolderString(p.start_folder),
+ mBuildDefaultHierarchy(true),
+ mInvFVBridgeBuilder(NULL)
+{
+ mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER;
+
+ // contex menu callbacks
+ mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLInventoryPanel::doToSelected, this, _2));
+ mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH));
+ mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND));
+ mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLInventoryPanel::doCreate, this, _2));
+ mCommitCallbackRegistrar.add("Inventory.AttachObject", boost::bind(&LLInventoryPanel::attachObject, this, _2));
+ mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&LLInventoryPanel::beginIMSession, this));
+
+ if (mStartFolderString != "")
+ {
+ mBuildDefaultHierarchy = false;
+ }
+}
+
+BOOL LLInventoryPanel::postBuild()
+{
+ LLMemType mt(LLMemType::MTYPE_INVENTORY_POST_BUILD);
+
+ mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves
+
+ // Create root folder
+ {
+ LLRect folder_rect(0,
+ 0,
+ getRect().getWidth(),
+ 0);
+ LLFolderView::Params p;
+ p.name = getName();
+ p.rect = folder_rect;
+ p.parent_panel = this;
+ p.tool_tip = p.name;
+ mFolders = LLUICtrlFactory::create<LLFolderView>(p);
+ mFolders->setAllowMultiSelect(mAllowMultiSelect);
+ }
+
+ mCommitCallbackRegistrar.popScope();
+
+ mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar);
+
+ // Scroller
+ {
+ LLRect scroller_view_rect = getRect();
+ scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
+ LLScrollContainer::Params p;
+ p.name("Inventory Scroller");
+ p.rect(scroller_view_rect);
+ p.follows.flags(FOLLOWS_ALL);
+ p.reserve_scroll_corner(true);
+ p.tab_stop(true);
+ mScroller = LLUICtrlFactory::create<LLScrollContainer>(p);
+ addChild(mScroller);
+ mScroller->addChild(mFolders);
+ mFolders->setScrollContainer(mScroller);
+ }
+
+ // Set up the callbacks from the inventory we're viewing, and then build everything.
+ mInventoryObserver = new LLInventoryPanelObserver(this);
+ mInventory->addObserver(mInventoryObserver);
+
+ // Build view of inventory if we need default full hierarchy and inventory ready,
+ // otherwise wait for idle callback.
+ if (mBuildDefaultHierarchy && mInventory->isInventoryUsable() && !mViewsInitialized)
+ {
+ initializeViews();
+ }
+ gIdleCallbacks.addFunction(onIdle, (void*)this);
+
+ if (mSortOrderSetting != INHERIT_SORT_ORDER)
+ {
+ setSortOrder(gSavedSettings.getU32(mSortOrderSetting));
+ }
+ else
+ {
+ setSortOrder(gSavedSettings.getU32(DEFAULT_SORT_ORDER));
+ }
+ mFolders->setSortOrder(getFilter()->getSortOrder());
+
+ return TRUE;
+}
+
+LLInventoryPanel::~LLInventoryPanel()
+{
+ if (mFolders)
+ {
+ U32 sort_order = mFolders->getSortOrder();
+ if (mSortOrderSetting != INHERIT_SORT_ORDER)
+ {
+ gSavedSettings.setU32(mSortOrderSetting, sort_order);
+ }
+ }
+
+ // LLView destructor will take care of the sub-views.
+ mInventory->removeObserver(mInventoryObserver);
+ delete mInventoryObserver;
+ mScroller = NULL;
+}
+
+void LLInventoryPanel::draw()
+{
+ // Select the desired item (in case it wasn't loaded when the selection was requested)
+ mFolders->updateSelection();
+ LLPanel::draw();
+}
+
+LLInventoryFilter* LLInventoryPanel::getFilter()
+{
+ if (mFolders)
+ {
+ return mFolders->getFilter();
+ }
+ return NULL;
+}
+
+void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType filter_type)
+{
+ if (filter_type == LLInventoryFilter::FILTERTYPE_OBJECT)
+ getFilter()->setFilterObjectTypes(types);
+ if (filter_type == LLInventoryFilter::FILTERTYPE_CATEGORY)
+ getFilter()->setFilterCategoryTypes(types);
+}
+
+void LLInventoryPanel::setFilterPermMask(PermissionMask filter_perm_mask)
+{
+ getFilter()->setFilterPermissions(filter_perm_mask);
+}
+
+void LLInventoryPanel::setFilterSubString(const std::string& string)
+{
+ getFilter()->setFilterSubString(string);
+}
+
+void LLInventoryPanel::setSortOrder(U32 order)
+{
+ getFilter()->setSortOrder(order);
+ if (getFilter()->isModified())
+ {
+ mFolders->setSortOrder(order);
+ // try to keep selection onscreen, even if it wasn't to start with
+ mFolders->scrollToShowSelection();
+ }
+}
+
+void LLInventoryPanel::setSinceLogoff(BOOL sl)
+{
+ getFilter()->setDateRangeLastLogoff(sl);
+}
+
+void LLInventoryPanel::setHoursAgo(U32 hours)
+{
+ getFilter()->setHoursAgo(hours);
+}
+
+void LLInventoryPanel::setShowFolderState(LLInventoryFilter::EFolderShow show)
+{
+ getFilter()->setShowFolderState(show);
+}
+
+LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState()
+{
+ return getFilter()->getShowFolderState();
+}
+
+void LLInventoryPanel::modelChanged(U32 mask)
+{
+ static LLFastTimer::DeclareTimer FTM_REFRESH("Inventory Refresh");
+ LLFastTimer t2(FTM_REFRESH);
+
+ bool handled = false;
+
+ if (!mViewsInitialized) return;
+
+ const LLInventoryModel* model = getModel();
+ if (!model) return;
+
+ const LLInventoryModel::changed_items_t& changed_items = model->getChangedIDs();
+ if (changed_items.empty()) return;
+
+ for (LLInventoryModel::changed_items_t::const_iterator items_iter = changed_items.begin();
+ items_iter != changed_items.end();
+ ++items_iter)
+ {
+ const LLUUID& item_id = (*items_iter);
+ const LLInventoryObject* model_item = model->getObject(item_id);
+ LLFolderViewItem* view_item = mFolders->getItemByID(item_id);
+ LLFolderViewFolder* view_folder = mFolders->getFolderByID(item_id);
+
+ //////////////////////////////
+ // LABEL Operation
+ // Empty out the display name for relabel.
+ if (mask & LLInventoryObserver::LABEL)
+ {
+ handled = true;
+ if (view_item)
+ {
+ // Request refresh on this item (also flags for filtering)
+ LLInvFVBridge* bridge = (LLInvFVBridge*)view_item->getListener();
+ if(bridge)
+ { // Clear the display name first, so it gets properly re-built during refresh()
+ bridge->clearDisplayName();
+ }
+ view_item->refresh();
+ }
+ }
+
+ //////////////////////////////
+ // REBUILD Operation
+ // Destroy and regenerate the UI.
+ if (mask & LLInventoryObserver::REBUILD)
+ {
+ handled = true;
+ if (model_item && view_item)
+ {
+ view_item->destroyView();
+ }
+ buildNewViews(item_id);
+ }
+
+ //////////////////////////////
+ // INTERNAL Operation
+ // This could be anything. For now, just refresh the item.
+ if (mask & LLInventoryObserver::INTERNAL)
+ {
+ if (view_item)
+ {
+ view_item->refresh();
+ }
+ }
+
+ //////////////////////////////
+ // SORT Operation
+ // Sort the folder.
+ if (mask & LLInventoryObserver::SORT)
+ {
+ if (view_folder)
+ {
+ view_folder->requestSort();
+ }
+ }
+
+ // We don't typically care which of these masks the item is actually flagged with, since the masks
+ // may not be accurate (e.g. in the main inventory panel, I move an item from My Inventory into
+ // Landmarks; this is a STRUCTURE change for that panel but is an ADD change for the Landmarks
+ // panel). What's relevant is that the item and UI are probably out of sync and thus need to be
+ // resynchronized.
+ if (mask & (LLInventoryObserver::STRUCTURE |
+ LLInventoryObserver::ADD |
+ LLInventoryObserver::REMOVE))
+ {
+ handled = true;
+
+ //////////////////////////////
+ // ADD Operation
+ // Item exists in memory but a UI element hasn't been created for it.
+ if (model_item && !view_item)
+ {
+ // Add the UI element for this item.
+ buildNewViews(item_id);
+ // Select any newly created object that has the auto rename at top of folder root set.
+ if(mFolders->getRoot()->needsAutoRename())
+ {
+ setSelection(item_id, FALSE);
+ }
+ }
+
+ //////////////////////////////
+ // STRUCTURE Operation
+ // This item already exists in both memory and UI. It was probably reparented.
+ if (model_item && view_item)
+ {
+ // Don't process the item if it's hanging from the root, since its
+ // model_item's parent will be NULL.
+ if (view_item->getRoot() != view_item->getParent())
+ {
+ LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolders->getItemByID(model_item->getParentUUID());
+ // Item has been moved.
+ if (view_item->getParentFolder() != new_parent)
+ {
+ if (new_parent != NULL)
+ {
+ // Item is to be moved and we found its new parent in the panel's directory, so move the item's UI.
+ view_item->getParentFolder()->extractItem(view_item);
+ view_item->addToFolder(new_parent, mFolders);
+ }
+ else
+ {
+ // Item is to be moved outside the panel's directory (e.g. moved to trash for a panel that
+ // doesn't include trash). Just remove the item's UI.
+ view_item->destroyView();
+ }
+ }
+ }
+ }
+
+ //////////////////////////////
+ // REMOVE Operation
+ // This item has been removed from memory, but its associated UI element still exists.
+ if (!model_item && view_item)
+ {
+ // Remove the item's UI.
+ view_item->destroyView();
+ }
+ }
+ }
+}
+
+// static
+void LLInventoryPanel::onIdle(void *userdata)
+{
+ if (!gInventory.isInventoryUsable())
+ return;
+
+ LLInventoryPanel *self = (LLInventoryPanel*)userdata;
+ // Inventory just initialized, do complete build
+ if (!self->mViewsInitialized)
+ {
+ self->initializeViews();
+ }
+ if (self->mViewsInitialized)
+ {
+ gIdleCallbacks.deleteFunction(onIdle, (void*)self);
+ }
+}
+
+void LLInventoryPanel::initializeViews()
+{
+ if (!gInventory.isInventoryUsable()) return;
+
+ // Determine the root folder in case specified, and
+ // build the views starting with that folder.
+ const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolderString);
+
+ if ("LIBRARY" == mStartFolderString)
+ {
+ mStartFolderID = gInventory.getLibraryRootFolderID();
+ }
+ else
+ {
+ mStartFolderID = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null);
+ }
+ rebuildViewsFor(mStartFolderID);
+
+ mViewsInitialized = true;
+ openStartFolderOrMyInventory();
+}
+
+void LLInventoryPanel::rebuildViewsFor(const LLUUID& id)
+{
+ // Destroy the old view for this ID so we can rebuild it.
+ LLFolderViewItem* old_view = mFolders->getItemByID(id);
+ if (old_view && id.notNull())
+ {
+ old_view->destroyView();
+ }
+
+ buildNewViews(id);
+}
+
+void LLInventoryPanel::buildNewViews(const LLUUID& id)
+{
+ LLMemType mt(LLMemType::MTYPE_INVENTORY_BUILD_NEW_VIEWS);
+ LLFolderViewItem* itemp = NULL;
+ LLInventoryObject* objectp = gInventory.getObject(id);
+ if (objectp)
+ {
+ const LLUUID &parent_id = objectp->getParentUUID();
+ LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)mFolders->getItemByID(parent_id);
+ if (id == mStartFolderID)
+ {
+ parent_folder = mFolders;
+ }
+ else if ((mStartFolderID != LLUUID::null) && (!gInventory.isObjectDescendentOf(id, mStartFolderID)))
+ {
+ // This item exists outside the inventory's hierarchy, so don't add it.
+ return;
+ }
+
+ if (objectp->getType() <= LLAssetType::AT_NONE ||
+ objectp->getType() >= LLAssetType::AT_COUNT)
+ {
+ llwarns << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : "
+ << ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID()
+ << llendl;
+ return;
+ }
+
+ if ((objectp->getType() == LLAssetType::AT_CATEGORY) &&
+ (objectp->getActualType() != LLAssetType::AT_LINK_FOLDER))
+ {
+ LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(),
+ objectp->getType(),
+ LLInventoryType::IT_CATEGORY,
+ this,
+ objectp->getUUID());
+
+ if (new_listener)
+ {
+ LLFolderViewFolder::Params params;
+ params.name = new_listener->getDisplayName();
+ params.icon = new_listener->getIcon();
+ params.icon_open = new_listener->getOpenIcon();
+ params.root = mFolders;
+ params.listener = new_listener;
+ params.tool_tip = params.name;
+ LLFolderViewFolder* folderp = LLUICtrlFactory::create<LLFolderViewFolder>(params);
+ folderp->setItemSortOrder(mFolders->getSortOrder());
+ itemp = folderp;
+
+ // Hide the root folder, so we can show the contents of a folder flat
+ // but still have the parent folder present for listener-related operations.
+ if (id == mStartFolderID)
+ {
+ folderp->setHidden(TRUE);
+ }
+ }
+ }
+ else
+ {
+ // Build new view for item.
+ LLInventoryItem* item = (LLInventoryItem*)objectp;
+ LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(),
+ item->getActualType(),
+ item->getInventoryType(),
+ this,
+ item->getUUID(),
+ item->getFlags());
+
+ if (new_listener)
+ {
+ LLFolderViewItem::Params params;
+ params.name = new_listener->getDisplayName();
+ params.icon = new_listener->getIcon();
+ params.icon_open = new_listener->getOpenIcon();
+ params.creation_date = new_listener->getCreationDate();
+ params.root = mFolders;
+ params.listener = new_listener;
+ params.rect = LLRect (0, 0, 0, 0);
+ params.tool_tip = params.name;
+ itemp = LLUICtrlFactory::create<LLFolderViewItem> (params);
+ }
+ }
+
+ if (itemp)
+ {
+ itemp->addToFolder(parent_folder, mFolders);
+ }
+ }
+
+ // If this is a folder, add the children of the folder and recursively add any
+ // child folders.
+ if ((id == mStartFolderID) ||
+ (objectp && objectp->getType() == LLAssetType::AT_CATEGORY))
+ {
+ LLViewerInventoryCategory::cat_array_t* categories;
+ LLViewerInventoryItem::item_array_t* items;
+ mInventory->lockDirectDescendentArrays(id, categories, items);
+
+ if(categories)
+ {
+ for (LLViewerInventoryCategory::cat_array_t::const_iterator cat_iter = categories->begin();
+ cat_iter != categories->end();
+ ++cat_iter)
+ {
+ const LLViewerInventoryCategory* cat = (*cat_iter);
+ buildNewViews(cat->getUUID());
+ }
+ }
+
+ if(items)
+ {
+ for (LLViewerInventoryItem::item_array_t::const_iterator item_iter = items->begin();
+ item_iter != items->end();
+ ++item_iter)
+ {
+ const LLViewerInventoryItem* item = (*item_iter);
+ buildNewViews(item->getUUID());
+ }
+ }
+ mInventory->unlockDirectDescendentArrays(id);
+ }
+}
+
+// bit of a hack to make sure the inventory is open.
+void LLInventoryPanel::openStartFolderOrMyInventory()
+{
+ if (mStartFolderString != "")
+ {
+ mFolders->openFolder(mStartFolderString);
+ }
+ else
+ {
+ // Find My Inventory folder and open it up by name
+ for (LLView *child = mFolders->getFirstChild(); child; child = mFolders->findNextSibling(child))
+ {
+ LLFolderViewFolder *fchild = dynamic_cast<LLFolderViewFolder*>(child);
+ if (fchild && fchild->getListener() &&
+ (fchild->getListener()->getUUID() == gInventory.getRootFolderID()))
+ {
+ const std::string& child_name = child->getName();
+ mFolders->openFolder(child_name);
+ break;
+ }
+ }
+ }
+}
+
+void LLInventoryPanel::openSelected()
+{
+ LLFolderViewItem* folder_item = mFolders->getCurSelectedItem();
+ if(!folder_item) return;
+ LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener();
+ if(!bridge) return;
+ bridge->openItem();
+}
+
+BOOL LLInventoryPanel::handleHover(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = LLView::handleHover(x, y, mask);
+ if(handled)
+ {
+ ECursorType cursor = getWindow()->getCursor();
+ if (LLInventoryModel::backgroundFetchActive() && cursor == UI_CURSOR_ARROW)
+ {
+ // replace arrow cursor with arrow and hourglass cursor
+ getWindow()->setCursor(UI_CURSOR_WORKING);
+ }
+ }
+ else
+ {
+ getWindow()->setCursor(UI_CURSOR_ARROW);
+ }
+ return TRUE;
+}
+
+BOOL LLInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg)
+{
+ BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+
+ // If folder view is empty the (x, y) point won't be in its rect
+ // so the handler must be called explicitly.
+ if (!mFolders->hasVisibleChildren())
+ {
+ handled = mFolders->handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+ }
+
+ if (handled)
+ {
+ mFolders->setDragAndDropThisFrame();
+ }
+
+ return handled;
+}
+
+void LLInventoryPanel::onFocusLost()
+{
+ // inventory no longer handles cut/copy/paste/delete
+ if (LLEditMenuHandler::gEditMenuHandler == mFolders)
+ {
+ LLEditMenuHandler::gEditMenuHandler = NULL;
+ }
+
+ LLPanel::onFocusLost();
+}
+
+void LLInventoryPanel::onFocusReceived()
+{
+ // inventory now handles cut/copy/paste/delete
+ LLEditMenuHandler::gEditMenuHandler = mFolders;
+
+ LLPanel::onFocusReceived();
+}
+
+void LLInventoryPanel::openAllFolders()
+{
+ mFolders->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN);
+ mFolders->arrangeAll();
+}
+
+void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus)
+{
+ // Don't select objects in COF (e.g. to prevent refocus when items are worn).
+ const LLInventoryObject *obj = gInventory.getObject(obj_id);
+ if (obj && obj->getParentUUID() == LLAppearanceManager::instance().getCOF())
+ {
+ return;
+ }
+ mFolders->setSelectionByID(obj_id, take_keyboard_focus);
+}
+
+void LLInventoryPanel::setSelectCallback(const LLFolderView::signal_t::slot_type& cb)
+{
+ if (mFolders)
+ {
+ mFolders->setSelectCallback(cb);
+ }
+}
+
+void LLInventoryPanel::clearSelection()
+{
+ mFolders->clearSelection();
+}
+
+void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& items, BOOL user_action)
+{
+ LLFolderView* fv = getRootFolder();
+ if (fv->needsAutoRename()) // auto-selecting a new user-created asset and preparing to rename
+ {
+ fv->setNeedsAutoRename(FALSE);
+ if (items.size()) // new asset is visible and selected
+ {
+ fv->startRenamingSelectedItem();
+ }
+ }
+ // Seraph - Put determineFolderType in here for ensemble typing?
+}
+
+void LLInventoryPanel::doToSelected(const LLSD& userdata)
+{
+ mFolders->doToSelected(&gInventory, userdata);
+}
+
+void LLInventoryPanel::doCreate(const LLSD& userdata)
+{
+ menu_create_inventory_item(mFolders, LLFolderBridge::sSelf, userdata);
+}
+
+bool LLInventoryPanel::beginIMSession()
+{
+ std::set<LLUUID> selected_items;
+ mFolders->getSelectionList(selected_items);
+
+ std::string name;
+ static int session_num = 1;
+
+ LLDynamicArray<LLUUID> members;
+ EInstantMessage type = IM_SESSION_CONFERENCE_START;
+
+ std::set<LLUUID>::const_iterator iter;
+ for (iter = selected_items.begin(); iter != selected_items.end(); iter++)
+ {
+
+ LLUUID item = *iter;
+ LLFolderViewItem* folder_item = mFolders->getItemByID(item);
+
+ if(folder_item)
+ {
+ LLFolderViewEventListener* fve_listener = folder_item->getListener();
+ if (fve_listener && (fve_listener->getInventoryType() == LLInventoryType::IT_CATEGORY))
+ {
+
+ LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getListener();
+ if(!bridge) return true;
+ LLViewerInventoryCategory* cat = bridge->getCategory();
+ if(!cat) return true;
+ name = cat->getName();
+ LLUniqueBuddyCollector is_buddy;
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ gInventory.collectDescendentsIf(bridge->getUUID(),
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_buddy);
+ S32 count = item_array.count();
+ if(count > 0)
+ {
+ LLFloaterReg::showInstance("communicate");
+ // create the session
+ LLAvatarTracker& at = LLAvatarTracker::instance();
+ LLUUID id;
+ for(S32 i = 0; i < count; ++i)
+ {
+ id = item_array.get(i)->getCreatorUUID();
+ if(at.isBuddyOnline(id))
+ {
+ members.put(id);
+ }
+ }
+ }
+ }
+ else
+ {
+ LLFolderViewItem* folder_item = mFolders->getItemByID(item);
+ if(!folder_item) return true;
+ LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getListener();
+
+ if (listenerp->getInventoryType() == LLInventoryType::IT_CALLINGCARD)
+ {
+ LLInventoryItem* inv_item = gInventory.getItem(listenerp->getUUID());
+
+ if (inv_item)
+ {
+ LLAvatarTracker& at = LLAvatarTracker::instance();
+ LLUUID id = inv_item->getCreatorUUID();
+
+ if(at.isBuddyOnline(id))
+ {
+ members.put(id);
+ }
+ }
+ } //if IT_CALLINGCARD
+ } //if !IT_CATEGORY
+ }
+ } //for selected_items
+
+ // the session_id is randomly generated UUID which will be replaced later
+ // with a server side generated number
+
+ if (name.empty())
+ {
+ name = llformat("Session %d", session_num++);
+ }
+
+ LLUUID session_id = gIMMgr->addSession(name, type, members[0], members);
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
+
+ return true;
+}
+
+bool LLInventoryPanel::attachObject(const LLSD& userdata)
+{
+ std::set<LLUUID> selected_items;
+ mFolders->getSelectionList(selected_items);
+
+ std::string joint_name = userdata.asString();
+ LLVOAvatar *avatarp = static_cast<LLVOAvatar*>(gAgent.getAvatarObject());
+ LLViewerJointAttachment* attachmentp = NULL;
+ for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
+ iter != avatarp->mAttachmentPoints.end(); )
+ {
+ LLVOAvatar::attachment_map_t::iterator curiter = iter++;
+ LLViewerJointAttachment* attachment = curiter->second;
+ if (attachment->getName() == joint_name)
+ {
+ attachmentp = attachment;
+ break;
+ }
+ }
+ if (attachmentp == NULL)
+ {
+ return true;
+ }
+
+ for (std::set<LLUUID>::const_iterator set_iter = selected_items.begin();
+ set_iter != selected_items.end();
+ ++set_iter)
+ {
+ const LLUUID &id = *set_iter;
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(id);
+ if(item && gInventory.isObjectDescendentOf(id, gInventory.getRootFolderID()))
+ {
+ rez_attachment(item, attachmentp);
+ }
+ else if(item && item->isComplete())
+ {
+ // must be in library. copy it to our inventory and put it on.
+ LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(attachmentp);
+ copy_inventory_item(gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ }
+ gFocusMgr.setKeyboardFocus(NULL);
+
+ return true;
+}
+
+BOOL LLInventoryPanel::getSinceLogoff()
+{
+ return getFilter()->isSinceLogoff();
+}
+
+// DEBUG ONLY
+// static
+void LLInventoryPanel::dumpSelectionInformation(void* user_data)
+{
+ LLInventoryPanel* iv = (LLInventoryPanel*)user_data;
+ iv->mFolders->dumpSelectionInformation();
+}
+
+BOOL is_inventorysp_active()
+{
+ if (!LLSideTray::getInstance()->isPanelActive("sidepanel_inventory")) return FALSE;
+ LLSidepanelInventory *inventorySP = dynamic_cast<LLSidepanelInventory *>(LLSideTray::getInstance()->getPanel("sidepanel_inventory"));
+ if (!inventorySP) return FALSE;
+ return inventorySP->isMainInventoryPanelActive();
+}
+
+// static
+LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open)
+{
+ // A. If the inventory side panel is open, use that preferably.
+ if (is_inventorysp_active())
+ {
+ LLSidepanelInventory *inventorySP = dynamic_cast<LLSidepanelInventory *>(LLSideTray::getInstance()->getPanel("sidepanel_inventory"));
+ if (inventorySP)
+ {
+ return inventorySP->getActivePanel();
+ }
+ }
+
+ // B. Iterate through the inventory floaters and return whichever is on top.
+ LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory");
+ S32 z_min = S32_MAX;
+ LLInventoryPanel* res = NULL;
+ for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter)
+ {
+ LLFloaterInventory* iv = dynamic_cast<LLFloaterInventory*>(*iter);
+ if (iv && iv->getVisible())
+ {
+ S32 z_order = gFloaterView->getZOrder(iv);
+ if (z_order < z_min)
+ {
+ res = iv->getPanel();
+ z_min = z_order;
+ }
+ }
+ }
+ if (res) return res;
+
+ // C. If no panels are open and we don't want to force open a panel, then just abort out.
+ if (!auto_open) return NULL;
+
+ // D. Open the inventory side panel and use that.
+ LLSD key;
+ LLSidepanelInventory *sidepanel_inventory =
+ dynamic_cast<LLSidepanelInventory *>(LLSideTray::getInstance()->showPanel("sidepanel_inventory", key));
+ if (sidepanel_inventory)
+ {
+ return sidepanel_inventory->getActivePanel();
+ }
+
+ return NULL;
+}
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
new file mode 100644
index 0000000000..ccff795a51
--- /dev/null
+++ b/indra/newview/llinventorypanel.h
@@ -0,0 +1,210 @@
+/**
+ * @file llinventorypanel.h
+ * @brief LLInventoryPanel
+ * class definition
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLINVENTORYPANEL_H
+#define LL_LLINVENTORYPANEL_H
+
+#include "llassetstorage.h"
+#include "lldarray.h"
+#include "llfloater.h"
+#include "llinventory.h"
+#include "llinventoryfilter.h"
+#include "llfolderview.h"
+#include "llinventorymodel.h"
+#include "lluictrlfactory.h"
+#include <set>
+
+class LLFolderViewItem;
+class LLInventoryFilter;
+class LLInventoryModel;
+class LLInvFVBridge;
+class LLInventoryFVBridgeBuilder;
+class LLMenuBarGL;
+class LLCheckBoxCtrl;
+class LLSpinCtrl;
+class LLScrollContainer;
+class LLTextBox;
+class LLIconCtrl;
+class LLSaveFolderState;
+class LLFilterEditor;
+class LLTabContainer;
+
+class LLInventoryPanel : public LLPanel
+{
+public:
+ static const std::string DEFAULT_SORT_ORDER;
+ static const std::string RECENTITEMS_SORT_ORDER;
+ static const std::string INHERIT_SORT_ORDER;
+
+ struct Filter : public LLInitParam::Block<Filter>
+ {
+ Optional<U32> sort_order;
+ Optional<U32> types;
+ Optional<std::string> search_string;
+
+ Filter()
+ : sort_order("sort_order"),
+ types("types", 0xffffffff),
+ search_string("search_string")
+ {}
+ };
+
+ struct Params
+ : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ Optional<std::string> sort_order_setting;
+ Optional<LLInventoryModel*> inventory;
+ Optional<bool> allow_multi_select;
+ Optional<Filter> filter;
+ Optional<std::string> start_folder;
+
+ Params()
+ : sort_order_setting("sort_order_setting"),
+ inventory("", &gInventory),
+ allow_multi_select("allow_multi_select", true),
+ filter("filter"),
+ start_folder("start_folder")
+ {}
+ };
+
+protected:
+ LLInventoryPanel(const Params&);
+ friend class LLUICtrlFactory;
+
+public:
+ virtual ~LLInventoryPanel();
+
+ LLInventoryModel* getModel() { return mInventory; }
+
+ BOOL postBuild();
+
+ // LLView methods
+ void draw();
+ BOOL handleHover(S32 x, S32 y, MASK mask);
+ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg);
+ // LLUICtrl methods
+ /*virtual*/ void onFocusLost();
+ /*virtual*/ void onFocusReceived();
+
+ // Call this method to set the selection.
+ void openAllFolders();
+ void setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus);
+ void setSelectCallback(const LLFolderView::signal_t::slot_type& cb);
+ void clearSelection();
+ LLInventoryFilter* getFilter();
+ void setFilterTypes(U64 filter, LLInventoryFilter::EFilterType = LLInventoryFilter::FILTERTYPE_OBJECT);
+ U32 getFilterObjectTypes() const { return mFolders->getFilterObjectTypes(); }
+ void setFilterPermMask(PermissionMask filter_perm_mask);
+ U32 getFilterPermMask() const { return mFolders->getFilterPermissions(); }
+ void setFilterSubString(const std::string& string);
+ const std::string getFilterSubString() { return mFolders->getFilterSubString(); }
+ void setSortOrder(U32 order);
+ U32 getSortOrder() { return mFolders->getSortOrder(); }
+ void setSinceLogoff(BOOL sl);
+ void setHoursAgo(U32 hours);
+ BOOL getSinceLogoff();
+
+ void setShowFolderState(LLInventoryFilter::EFolderShow show);
+ LLInventoryFilter::EFolderShow getShowFolderState();
+ void setAllowMultiSelect(BOOL allow) { mFolders->setAllowMultiSelect(allow); }
+ // This method is called when something has changed about the inventory.
+ void modelChanged(U32 mask);
+ LLFolderView* getRootFolder() { return mFolders; }
+ LLScrollContainer* getScrollableContainer() { return mScroller; }
+
+ void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
+
+ // Callbacks
+ void doToSelected(const LLSD& userdata);
+ void doCreate(const LLSD& userdata);
+ bool beginIMSession();
+ bool attachObject(const LLSD& userdata);
+
+ // DEBUG ONLY:
+ static void dumpSelectionInformation(void* user_data);
+
+ void openSelected();
+ void unSelectAll() { mFolders->setSelection(NULL, FALSE, FALSE); }
+
+ static void onIdle(void* user_data);
+
+ // Find whichever inventory panel is active / on top.
+ // "Auto_open" determines if we open an inventory panel if none are open.
+ static LLInventoryPanel *getActiveInventoryPanel(BOOL auto_open = TRUE);
+
+protected:
+ void openStartFolderOrMyInventory(); // open the first level of inventory
+
+ LLInventoryModel* mInventory;
+ LLInventoryObserver* mInventoryObserver;
+ BOOL mAllowMultiSelect;
+ std::string mSortOrderSetting;
+
+ LLFolderView* mFolders;
+ LLScrollContainer* mScroller;
+
+ /**
+ * Pointer to LLInventoryFVBridgeBuilder.
+ *
+ * It is set in LLInventoryPanel's constructor and can be overridden in derived classes with
+ * another implementation.
+ * Take into account it will not be deleted by LLInventoryPanel itself.
+ */
+ const LLInventoryFVBridgeBuilder* mInvFVBridgeBuilder;
+
+ //--------------------------------------------------------------------
+ // Initialization routines for building up the UI ("views")
+ //--------------------------------------------------------------------
+public:
+ BOOL getIsViewsInitialized() const { return mViewsInitialized; }
+ const LLUUID& getStartFolderID() const { return mStartFolderID; }
+ const std::string& getStartFolderString() { return mStartFolderString; }
+protected:
+ // Builds the UI. Call this once the inventory is usable.
+ void initializeViews();
+ void rebuildViewsFor(const LLUUID& id); // Given the id and the parent, build all of the folder views.
+ virtual void buildNewViews(const LLUUID& id);
+private:
+ BOOL mBuildDefaultHierarchy; // default inventory hierarchy should be created in postBuild()
+ BOOL mViewsInitialized; // Views have been generated
+ // UUID of category from which hierarchy should be built. Set with the
+ // "start_folder" xml property. Default is LLUUID::null that means total Inventory hierarchy.
+ std::string mStartFolderString;
+ LLUUID mStartFolderID;
+};
+
+#endif // LL_LLINVENTORYPANEL_H
diff --git a/indra/newview/lljoystickbutton.cpp b/indra/newview/lljoystickbutton.cpp
index 326c511fcf..2cc5c8335d 100644
--- a/indra/newview/lljoystickbutton.cpp
+++ b/indra/newview/lljoystickbutton.cpp
@@ -42,15 +42,19 @@
// Project includes
#include "llui.h"
#include "llagent.h"
-#include "llviewerimage.h"
-#include "llviewerimagelist.h"
+#include "llviewertexture.h"
+#include "llviewertexturelist.h"
#include "llviewerwindow.h"
#include "llmoveview.h"
#include "llglheaders.h"
-static LLRegisterWidget<LLJoystickAgentSlide> r1("joystick_slide");
-static LLRegisterWidget<LLJoystickAgentTurn> r2("joystick_turn");
+static LLDefaultChildRegistry::Register<LLJoystickAgentSlide> r1("joystick_slide");
+static LLDefaultChildRegistry::Register<LLJoystickAgentTurn> r2("joystick_turn");
+static LLDefaultChildRegistry::Register<LLJoystickCameraRotate> r3("joystick_rotate");
+static LLDefaultChildRegistry::Register<LLJoystickCameraZoom> r4("joystick_zoom");
+static LLDefaultChildRegistry::Register<LLJoystickCameraTrack> r5("joystick_track");
+
const F32 NUDGE_TIME = 0.25f; // in seconds
@@ -59,15 +63,18 @@ const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed
//
// Public Methods
//
-LLJoystick::LLJoystick(
- const std::string& name,
- LLRect rect,
- const std::string &default_image,
- const std::string &selected_image,
- EJoystickQuadrant initial_quadrant )
- :
- LLButton(name, rect, default_image, selected_image, LLStringUtil::null, NULL, NULL),
- mInitialQuadrant(initial_quadrant),
+void QuadrantNames::declareValues()
+{
+ declare("origin", JQ_ORIGIN);
+ declare("up", JQ_UP);
+ declare("down", JQ_DOWN);
+ declare("left", JQ_LEFT);
+ declare("right", JQ_RIGHT);
+}
+
+
+LLJoystick::LLJoystick(const LLJoystick::Params& p)
+: LLButton(p),
mInitialOffset(0, 0),
mLastMouse(0, 0),
mFirstMouse(0, 0),
@@ -76,10 +83,10 @@ LLJoystick::LLJoystick(
mHorizSlopNear(0),
mHorizSlopFar(0),
mHeldDown(FALSE),
- mHeldDownTimer()
+ mHeldDownTimer(),
+ mInitialQuadrant(p.quadrant)
{
- setHeldDownCallback(&LLJoystick::onHeldDown);
- setCallbackUserData(this);
+ setHeldDownCallback(&LLJoystick::onBtnHeldDown, this);
}
@@ -127,16 +134,33 @@ void LLJoystick::updateSlop()
return;
}
+bool LLJoystick::pointInCircle(S32 x, S32 y) const
+{
+ if(this->getLocalRect().getHeight() != this->getLocalRect().getWidth())
+ {
+ llwarns << "Joystick shape is not square"<<llendl;
+ return true;
+ }
+ //center is x and y coordinates of center of joystick circle, and also its radius
+ int center = this->getLocalRect().getHeight()/2;
+ bool in_circle = (x - center) * (x - center) + (y - center) * (y - center) <= center * center;
+ return in_circle;
+}
BOOL LLJoystick::handleMouseDown(S32 x, S32 y, MASK mask)
{
//llinfos << "joystick mouse down " << x << ", " << y << llendl;
+ bool handles = false;
- mLastMouse.set(x, y);
- mFirstMouse.set(x, y);
+ if(pointInCircle(x, y))
+ {
+ mLastMouse.set(x, y);
+ mFirstMouse.set(x, y);
+ mMouseDownTimer.reset();
+ handles = LLButton::handleMouseDown(x, y, mask);
+ }
- mMouseDownTimer.reset();
- return LLButton::handleMouseDown(x, y, mask);
+ return handles;
}
@@ -178,16 +202,14 @@ F32 LLJoystick::getElapsedHeldDownTime()
}
// static
-void LLJoystick::onHeldDown(void *userdata)
+void LLJoystick::onBtnHeldDown(void *userdata)
{
LLJoystick *self = (LLJoystick *)userdata;
-
- // somebody removed this function without checking the
- // build. Removed 2007-03-26.
- //llassert( gViewerWindow->hasMouseCapture( self ) );
-
- self->mHeldDown = TRUE;
- self->onHeldDown();
+ if (self)
+ {
+ self->mHeldDown = TRUE;
+ self->onHeldDown();
+ }
}
EJoystickQuadrant LLJoystick::selectQuadrant(LLXMLNodePtr node)
@@ -246,23 +268,6 @@ EJoystickQuadrant LLJoystick::quadrantFromName(const std::string& sQuadrant)
}
-LLXMLNodePtr LLJoystick::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLUICtrl::getXML();
-
- node->createChild("halign", TRUE)->setStringValue(LLFontGL::nameFromHAlign(getHAlign()));
- node->createChild("quadrant", TRUE)->setStringValue(nameFromQuadrant(mInitialQuadrant));
-
- addImageAttributeToXML(node,getImageUnselectedName(),getImageUnselectedID(),std::string("image_unselected"));
- addImageAttributeToXML(node,getImageSelectedName(),getImageSelectedID(),std::string("image_selected"));
-
- node->createChild("scale_image", TRUE)->setBoolValue(getScaleImage());
-
- return node;
-}
-
-
-
//-------------------------------------------------------------------------------
// LLJoystickAgentTurn
//-------------------------------------------------------------------------------
@@ -327,46 +332,6 @@ void LLJoystickAgentTurn::onHeldDown()
}
}
-LLView* LLJoystickAgentTurn::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("button");
- node->getAttributeString("name", name);
-
- std::string image_unselected;
- if (node->hasAttribute("image_unselected")) node->getAttributeString("image_unselected",image_unselected);
-
- std::string image_selected;
- if (node->hasAttribute("image_selected")) node->getAttributeString("image_selected",image_selected);
-
- EJoystickQuadrant quad = JQ_ORIGIN;
- if (node->hasAttribute("quadrant")) quad = selectQuadrant(node);
-
- LLJoystickAgentTurn *button = new LLJoystickAgentTurn(name,
- LLRect(),
- image_unselected,
- image_selected,
- quad);
-
- if (node->hasAttribute("halign"))
- {
- LLFontGL::HAlign halign = selectFontHAlign(node);
- button->setHAlign(halign);
- }
-
- if (node->hasAttribute("scale_image"))
- {
- BOOL needsScale = FALSE;
- node->getAttributeBOOL("scale_image",needsScale);
- button->setScaleImage( needsScale );
- }
-
- button->initFromXML(node, parent);
-
- return button;
-}
-
-
-
//-------------------------------------------------------------------------------
// LLJoystickAgentSlide
//-------------------------------------------------------------------------------
@@ -435,54 +400,12 @@ void LLJoystickAgentSlide::onHeldDown()
}
-// static
-LLView* LLJoystickAgentSlide::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("button");
- node->getAttributeString("name", name);
-
- std::string image_unselected;
- if (node->hasAttribute("image_unselected")) node->getAttributeString("image_unselected",image_unselected);
-
- std::string image_selected;
- if (node->hasAttribute("image_selected")) node->getAttributeString("image_selected",image_selected);
-
-
- EJoystickQuadrant quad = JQ_ORIGIN;
- if (node->hasAttribute("quadrant")) quad = selectQuadrant(node);
-
- LLJoystickAgentSlide *button = new LLJoystickAgentSlide(name,
- LLRect(),
- image_unselected,
- image_selected,
- quad);
-
- if (node->hasAttribute("halign"))
- {
- LLFontGL::HAlign halign = selectFontHAlign(node);
- button->setHAlign(halign);
- }
-
- if (node->hasAttribute("scale_image"))
- {
- BOOL needsScale = FALSE;
- node->getAttributeBOOL("scale_image",needsScale);
- button->setScaleImage( needsScale );
- }
-
- button->initFromXML(node, parent);
-
- return button;
-}
-
-
//-------------------------------------------------------------------------------
// LLJoystickCameraRotate
//-------------------------------------------------------------------------------
-LLJoystickCameraRotate::LLJoystickCameraRotate(const std::string& name, LLRect rect, const std::string &out_img, const std::string &in_img)
- :
- LLJoystick(name, rect, out_img, in_img, JQ_ORIGIN),
+LLJoystickCameraRotate::LLJoystickCameraRotate(const LLJoystickCameraRotate::Params& p)
+: LLJoystick(p),
mInLeft( FALSE ),
mInTop( FALSE ),
mInRight( FALSE ),
@@ -611,48 +534,52 @@ void LLJoystickCameraRotate::draw()
LLGLSUIDefault gls_ui;
getImageUnselected()->draw( 0, 0 );
+ LLPointer<LLUIImage> image = getImageSelected();
if( mInTop )
{
- drawRotatedImage( getImageSelected()->getImage(), 0 );
+ drawRotatedImage( getImageSelected(), 0 );
}
if( mInRight )
{
- drawRotatedImage( getImageSelected()->getImage(), 1 );
+ drawRotatedImage( getImageSelected(), 1 );
}
if( mInBottom )
{
- drawRotatedImage( getImageSelected()->getImage(), 2 );
+ drawRotatedImage( getImageSelected(), 2 );
}
if( mInLeft )
{
- drawRotatedImage( getImageSelected()->getImage(), 3 );
- }
-
- if (sDebugRects)
- {
- drawDebugRect();
+ drawRotatedImage( getImageSelected(), 3 );
}
}
// Draws image rotated by multiples of 90 degrees
-void LLJoystickCameraRotate::drawRotatedImage( LLImageGL* image, S32 rotations )
+void LLJoystickCameraRotate::drawRotatedImage( LLPointer<LLUIImage> image, S32 rotations )
{
S32 width = image->getWidth();
S32 height = image->getHeight();
-
+ LLTexture* texture = image->getImage();
+
+ /*
+ * Scale texture coordinate system
+ * to handle the different between image size and size of texture.
+ * If we will use default matrix,
+ * it may break texture mapping after rotation.
+ * see EXT-2023 Camera floater: arrows became shifted when pressed.
+ */
F32 uv[][2] =
{
- { 1.f, 1.f },
- { 0.f, 1.f },
+ { (F32)width/texture->getWidth(), (F32)height/texture->getHeight() },
+ { 0.f, (F32)height/texture->getHeight() },
{ 0.f, 0.f },
- { 1.f, 0.f }
+ { (F32)width/texture->getWidth(), 0.f }
};
- gGL.getTexUnit(0)->bind(image);
+ gGL.getTexUnit(0)->bind(texture);
gGL.color4fv(UI_VERTEX_COLOR.mV);
@@ -679,6 +606,15 @@ void LLJoystickCameraRotate::drawRotatedImage( LLImageGL* image, S32 rotations )
// LLJoystickCameraTrack
//-------------------------------------------------------------------------------
+LLJoystickCameraTrack::Params::Params()
+{
+ held_down_delay.seconds(0.0);
+}
+
+LLJoystickCameraTrack::LLJoystickCameraTrack(const LLJoystickCameraTrack::Params& p)
+: LLJoystickCameraRotate(p)
+{}
+
void LLJoystickCameraTrack::onHeldDown()
{
@@ -717,17 +653,15 @@ void LLJoystickCameraTrack::onHeldDown()
// LLJoystickCameraZoom
//-------------------------------------------------------------------------------
-LLJoystickCameraZoom::LLJoystickCameraZoom(const std::string& name, LLRect rect, const std::string &out_img, const std::string &plus_in_img, const std::string &minus_in_img)
- :
- LLJoystick(name, rect, out_img, LLStringUtil::null, JQ_ORIGIN),
+LLJoystickCameraZoom::LLJoystickCameraZoom(const LLJoystickCameraZoom::Params& p)
+: LLJoystick(p),
mInTop( FALSE ),
- mInBottom( FALSE )
+ mInBottom( FALSE ),
+ mPlusInImage(p.plus_image),
+ mMinusInImage(p.minus_image)
{
- mPlusInImage = LLUIImageList::getInstance()->getUIImage(plus_in_img);
- mMinusInImage = LLUIImageList::getInstance()->getUIImage(minus_in_img);
}
-
BOOL LLJoystickCameraZoom::handleMouseDown(S32 x, S32 y, MASK mask)
{
BOOL handled = LLJoystick::handleMouseDown(x, y, mask);
@@ -803,11 +737,6 @@ void LLJoystickCameraZoom::draw()
{
getImageUnselected()->draw( 0, 0 );
}
-
- if (sDebugRects)
- {
- drawDebugRect();
- }
}
void LLJoystickCameraZoom::updateSlop()
diff --git a/indra/newview/lljoystickbutton.h b/indra/newview/lljoystickbutton.h
index 076a506f14..2b071a8999 100644
--- a/indra/newview/lljoystickbutton.h
+++ b/indra/newview/lljoystickbutton.h
@@ -35,7 +35,7 @@
#include "llbutton.h"
#include "llcoord.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
typedef enum e_joystick_quadrant
{
@@ -46,11 +46,27 @@ typedef enum e_joystick_quadrant
JQ_RIGHT
} EJoystickQuadrant;
+struct QuadrantNames : public LLInitParam::TypeValuesHelper<EJoystickQuadrant, QuadrantNames>
+{
+ static void declareValues();
+};
+
class LLJoystick
: public LLButton
{
public:
- LLJoystick(const std::string& name, LLRect rect, const std::string &default_image, const std::string &selected_image, EJoystickQuadrant initial);
+ struct Params
+ : public LLInitParam::Block<Params, LLButton::Params>
+ {
+ Optional<EJoystickQuadrant, QuadrantNames> quadrant;
+
+ Params()
+ : quadrant("quadrant", JQ_ORIGIN)
+ {
+ label = "";
+ }
+ };
+ LLJoystick(const Params&);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
@@ -60,10 +76,17 @@ public:
virtual void onHeldDown() = 0;
F32 getElapsedHeldDownTime();
- static void onHeldDown(void *userdata); // called by llbutton callback handler
+ static void onBtnHeldDown(void *userdata); // called by llbutton callback handler
void setInitialQuadrant(EJoystickQuadrant initial) { mInitialQuadrant = initial; };
+
+ /**
+ * Checks if click location is inside joystick circle.
+ *
+ * Image containing circle is square and this square has adherent points with joystick
+ * circle. Make sure to change method according to shape other than square.
+ */
+ bool pointInCircle(S32 x, S32 y) const;
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
static std::string nameFromQuadrant(const EJoystickQuadrant quadrant);
static EJoystickQuadrant quadrantFromName(const std::string& name);
static EJoystickQuadrant selectQuadrant(LLXMLNodePtr node);
@@ -91,14 +114,9 @@ class LLJoystickAgentTurn
: public LLJoystick
{
public:
- LLJoystickAgentTurn(const std::string& name, LLRect rect, const std::string &default_image, const std::string &selected_image, EJoystickQuadrant initial)
- : LLJoystick(name, rect, default_image, selected_image, initial)
- { }
-
+ struct Params : public LLJoystick::Params {};
+ LLJoystickAgentTurn(const Params& p) : LLJoystick(p) {}
virtual void onHeldDown();
-
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
-
};
@@ -107,14 +125,11 @@ class LLJoystickAgentSlide
: public LLJoystick
{
public:
- LLJoystickAgentSlide(const std::string& name, LLRect rect, const std::string &default_image, const std::string &selected_image, EJoystickQuadrant initial)
- : LLJoystick(name, rect, default_image, selected_image, initial)
- { }
-
+ struct Params : public LLJoystick::Params {};
+ LLJoystickAgentSlide(const Params& p) : LLJoystick(p) {}
+
virtual void onHeldDown();
virtual void onMouseUp();
-
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
};
@@ -123,7 +138,16 @@ class LLJoystickCameraRotate
: public LLJoystick
{
public:
- LLJoystickCameraRotate(const std::string& name, LLRect rect, const std::string &out_img, const std::string &in_img);
+ struct Params
+ : public LLInitParam::Block<Params, LLJoystick::Params>
+ {
+ Params()
+ {
+ held_down_delay.seconds(0.0);
+ }
+ };
+
+ LLJoystickCameraRotate(const LLJoystickCameraRotate::Params&);
virtual void setToggleState( BOOL left, BOOL top, BOOL right, BOOL bottom );
@@ -134,7 +158,7 @@ public:
protected:
F32 getOrbitRate();
virtual void updateSlop();
- void drawRotatedImage( LLImageGL* image, S32 rotations );
+ void drawRotatedImage( LLPointer<LLUIImage> image, S32 rotations );
protected:
BOOL mInLeft;
@@ -149,10 +173,13 @@ class LLJoystickCameraTrack
: public LLJoystickCameraRotate
{
public:
- LLJoystickCameraTrack(const std::string& name, LLRect rect, const std::string &out_img, const std::string &in_img)
- : LLJoystickCameraRotate(name, rect, out_img, in_img)
- { }
+ struct Params
+ : public LLInitParam::Block<Params, LLJoystickCameraRotate::Params>
+ {
+ Params();
+ };
+ LLJoystickCameraTrack(const LLJoystickCameraTrack::Params&);
virtual void onHeldDown();
};
@@ -162,7 +189,20 @@ class LLJoystickCameraZoom
: public LLJoystick
{
public:
- LLJoystickCameraZoom(const std::string& name, LLRect rect, const std::string &out_img, const std::string &plus_in_img, const std::string &minus_in_img);
+ struct Params
+ : public LLInitParam::Block<Params, LLJoystick::Params>
+ {
+ Optional<LLUIImage*> plus_image;
+ Optional<LLUIImage*> minus_image;
+
+ Params()
+ : plus_image ("plus_image", NULL),
+ minus_image ("minus_image", NULL)
+ {
+ held_down_delay.seconds(0.0);
+ }
+ };
+ LLJoystickCameraZoom(const Params&);
virtual void setToggleState( BOOL top, BOOL bottom );
diff --git a/indra/newview/lllandmarkactions.cpp b/indra/newview/lllandmarkactions.cpp
new file mode 100644
index 0000000000..f25d2ef574
--- /dev/null
+++ b/indra/newview/lllandmarkactions.cpp
@@ -0,0 +1,425 @@
+/**
+* @file lllandmarkactions.cpp
+* @brief LLLandmarkActions class implementation
+*
+* $LicenseInfo:firstyear=2001&license=viewergpl$
+*
+* Copyright (c) 2001-2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+#include "lllandmarkactions.h"
+
+#include "roles_constants.h"
+
+#include "llinventory.h"
+#include "lllandmark.h"
+#include "llparcel.h"
+#include "llregionhandle.h"
+
+#include "llnotificationsutil.h"
+
+#include "llagent.h"
+#include "llagentui.h"
+#include "llinventorymodel.h"
+#include "lllandmarklist.h"
+#include "llslurl.h"
+#include "llstring.h"
+#include "llviewerinventory.h"
+#include "llviewerparcelmgr.h"
+#include "llworldmapmessage.h"
+#include "llviewerwindow.h"
+#include "llwindow.h"
+#include "llworldmap.h"
+
+void copy_slurl_to_clipboard_callback(const std::string& slurl);
+
+class LLFetchlLandmarkByPos : public LLInventoryCollectFunctor
+{
+private:
+ LLVector3d mPos;
+public:
+ LLFetchlLandmarkByPos(const LLVector3d& pos) :
+ mPos(pos)
+ {}
+
+ /*virtual*/ bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+ {
+ if (!item || item->getType() != LLAssetType::AT_LANDMARK)
+ return false;
+
+ LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID());
+ if (!landmark) // the landmark not been loaded yet
+ return false;
+
+ LLVector3d landmark_global_pos;
+ if (!landmark->getGlobalPos(landmark_global_pos))
+ return false;
+ //we have to round off each coordinates to compare positions properly
+ return llround(mPos.mdV[VX]) == llround(landmark_global_pos.mdV[VX])
+ && llround(mPos.mdV[VY]) == llround(landmark_global_pos.mdV[VY])
+ && llround(mPos.mdV[VZ]) == llround(landmark_global_pos.mdV[VZ]);
+ }
+};
+
+class LLFetchLandmarksByName : public LLInventoryCollectFunctor
+{
+private:
+ std::string name;
+ BOOL use_substring;
+ //this member will be contain copy of founded items to keep the result unique
+ std::set<std::string> check_duplicate;
+
+public:
+LLFetchLandmarksByName(std::string &landmark_name, BOOL if_use_substring)
+:name(landmark_name),
+use_substring(if_use_substring)
+ {
+ LLStringUtil::toLower(name);
+ }
+
+public:
+ /*virtual*/ bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+ {
+ if (!item || item->getType() != LLAssetType::AT_LANDMARK)
+ return false;
+
+ LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID());
+ if (!landmark) // the landmark not been loaded yet
+ return false;
+
+ bool acceptable = false;
+ std::string landmark_name = item->getName();
+ LLStringUtil::toLower(landmark_name);
+ if(use_substring)
+ {
+ acceptable = landmark_name.find( name ) != std::string::npos;
+ }
+ else
+ {
+ acceptable = landmark_name == name;
+ }
+ if(acceptable){
+ if(check_duplicate.find(landmark_name) != check_duplicate.end()){
+ // we have duplicated items in landmarks
+ acceptable = false;
+ }else{
+ check_duplicate.insert(landmark_name);
+ }
+ }
+
+ return acceptable;
+ }
+};
+
+// Returns true if the given inventory item is a landmark pointing to the current parcel.
+// Used to find out if there is at least one landmark from current parcel.
+class LLFirstAgentParcelLandmark : public LLInventoryCollectFunctor
+{
+private:
+ bool mFounded;// to avoid unnecessary check
+
+public:
+ LLFirstAgentParcelLandmark(): mFounded(false){}
+
+ /*virtual*/ bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+ {
+ if (mFounded || !item || item->getType() != LLAssetType::AT_LANDMARK)
+ return false;
+
+ LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID());
+ if (!landmark) // the landmark not been loaded yet
+ return false;
+
+ LLVector3d landmark_global_pos;
+ if (!landmark->getGlobalPos(landmark_global_pos))
+ return false;
+ mFounded = LLViewerParcelMgr::getInstance()->inAgentParcel(landmark_global_pos);
+ return mFounded;
+ }
+};
+
+static void fetch_landmarks(LLInventoryModel::cat_array_t& cats,
+ LLInventoryModel::item_array_t& items,
+ LLInventoryCollectFunctor& add)
+{
+ // Look in "My Favorites"
+ const LLUUID favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+ gInventory.collectDescendentsIf(favorites_folder_id,
+ cats,
+ items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ add);
+
+ // Look in "Landmarks"
+ const LLUUID landmarks_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
+ gInventory.collectDescendentsIf(landmarks_folder_id,
+ cats,
+ items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ add);
+}
+
+LLInventoryModel::item_array_t LLLandmarkActions::fetchLandmarksByName(std::string& name, BOOL use_substring)
+{
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ LLFetchLandmarksByName by_name(name, use_substring);
+ fetch_landmarks(cats, items, by_name);
+
+ return items;
+}
+
+bool LLLandmarkActions::landmarkAlreadyExists()
+{
+ // Determine whether there are landmarks pointing to the current global agent position.
+ return findLandmarkForAgentPos() != NULL;
+}
+
+//static
+bool LLLandmarkActions::hasParcelLandmark()
+{
+ LLFirstAgentParcelLandmark get_first_agent_landmark;
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ fetch_landmarks(cats, items, get_first_agent_landmark);
+ return !items.empty();
+
+}
+
+// *TODO: This could be made more efficient by only fetching the FIRST
+// landmark that meets the criteria
+LLViewerInventoryItem* LLLandmarkActions::findLandmarkForGlobalPos(const LLVector3d &pos)
+{
+ // Determine whether there are landmarks pointing to the current parcel.
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ LLFetchlLandmarkByPos is_current_pos_landmark(pos);
+ fetch_landmarks(cats, items, is_current_pos_landmark);
+
+ if(items.empty())
+ {
+ return NULL;
+ }
+
+ return items[0];
+}
+
+LLViewerInventoryItem* LLLandmarkActions::findLandmarkForAgentPos()
+{
+ return findLandmarkForGlobalPos(gAgent.getPositionGlobal());
+}
+
+bool LLLandmarkActions::canCreateLandmarkHere()
+{
+ LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ if(!agent_parcel)
+ {
+ llwarns << "No agent region" << llendl;
+ return false;
+ }
+ if (agent_parcel->getAllowLandmark()
+ || LLViewerParcelMgr::isParcelOwnedByAgent(agent_parcel, GP_LAND_ALLOW_LANDMARK))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+void LLLandmarkActions::createLandmarkHere(
+ const std::string& name,
+ const std::string& desc,
+ const LLUUID& folder_id)
+{
+ if(!gAgent.getRegion())
+ {
+ llwarns << "No agent region" << llendl;
+ return;
+ }
+ LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ if (!agent_parcel)
+ {
+ llwarns << "No agent parcel" << llendl;
+ return;
+ }
+ if (!canCreateLandmarkHere())
+ {
+ LLNotificationsUtil::add("CannotCreateLandmarkNotOwner");
+ return;
+ }
+
+ create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
+ folder_id, LLTransactionID::tnull,
+ name, desc,
+ LLAssetType::AT_LANDMARK,
+ LLInventoryType::IT_LANDMARK,
+ NOT_WEARABLE, PERM_ALL,
+ NULL);
+}
+
+void LLLandmarkActions::createLandmarkHere()
+{
+ std::string landmark_name, landmark_desc;
+
+ LLAgentUI::buildLocationString(landmark_name, LLAgentUI::LOCATION_FORMAT_LANDMARK);
+ LLAgentUI::buildLocationString(landmark_desc, LLAgentUI::LOCATION_FORMAT_FULL);
+ const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
+
+ createLandmarkHere(landmark_name, landmark_desc, folder_id);
+}
+
+void LLLandmarkActions::getSLURLfromPosGlobal(const LLVector3d& global_pos, slurl_callback_t cb, bool escaped /* = true */)
+{
+ std::string sim_name;
+ bool gotSimName = LLWorldMap::getInstance()->simNameFromPosGlobal(global_pos, sim_name);
+ if (gotSimName)
+ {
+ std::string slurl = LLSLURL::buildSLURLfromPosGlobal(sim_name, global_pos, escaped);
+ cb(slurl);
+
+ return;
+ }
+ else
+ {
+ U64 new_region_handle = to_region_handle(global_pos);
+
+ LLWorldMapMessage::url_callback_t url_cb = boost::bind(&LLLandmarkActions::onRegionResponseSLURL,
+ cb,
+ global_pos,
+ escaped,
+ _2);
+
+ LLWorldMapMessage::getInstance()->sendHandleRegionRequest(new_region_handle, url_cb, std::string("unused"), false);
+ }
+}
+
+void LLLandmarkActions::getRegionNameAndCoordsFromPosGlobal(const LLVector3d& global_pos, region_name_and_coords_callback_t cb)
+{
+ std::string sim_name;
+ LLSimInfo* sim_infop = LLWorldMap::getInstance()->simInfoFromPosGlobal(global_pos);
+ if (sim_infop)
+ {
+ LLVector3 pos = sim_infop->getLocalPos(global_pos);
+ std::string name = sim_infop->getName() ;
+ cb(name, llround(pos.mV[VX]), llround(pos.mV[VY]),llround(pos.mV[VZ]));
+ }
+ else
+ {
+ U64 new_region_handle = to_region_handle(global_pos);
+
+ LLWorldMapMessage::url_callback_t url_cb = boost::bind(&LLLandmarkActions::onRegionResponseNameAndCoords,
+ cb,
+ global_pos,
+ _1);
+
+ LLWorldMapMessage::getInstance()->sendHandleRegionRequest(new_region_handle, url_cb, std::string("unused"), false);
+ }
+}
+
+void LLLandmarkActions::onRegionResponseSLURL(slurl_callback_t cb,
+ const LLVector3d& global_pos,
+ bool escaped,
+ const std::string& url)
+{
+ std::string sim_name;
+ std::string slurl;
+ bool gotSimName = LLWorldMap::getInstance()->simNameFromPosGlobal(global_pos, sim_name);
+ if (gotSimName)
+ {
+ slurl = LLSLURL::buildSLURLfromPosGlobal(sim_name, global_pos, escaped);
+ }
+ else
+ {
+ slurl = "";
+ }
+
+ cb(slurl);
+}
+
+void LLLandmarkActions::onRegionResponseNameAndCoords(region_name_and_coords_callback_t cb,
+ const LLVector3d& global_pos,
+ U64 region_handle)
+{
+ LLSimInfo* sim_infop = LLWorldMap::getInstance()->simInfoFromHandle(region_handle);
+ if (sim_infop)
+ {
+ LLVector3 local_pos = sim_infop->getLocalPos(global_pos);
+ std::string name = sim_infop->getName() ;
+ cb(name, llround(local_pos.mV[VX]), llround(local_pos.mV[VY]), llround(local_pos.mV[VZ]));
+ }
+}
+
+bool LLLandmarkActions::getLandmarkGlobalPos(const LLUUID& landmarkInventoryItemID, LLVector3d& posGlobal)
+{
+ LLViewerInventoryItem* item = gInventory.getItem(landmarkInventoryItemID);
+ if (NULL == item)
+ return false;
+
+ const LLUUID& asset_id = item->getAssetUUID();
+
+ LLLandmark* landmark = gLandmarkList.getAsset(asset_id, NULL);
+ if (NULL == landmark)
+ return false;
+
+ return landmark->getGlobalPos(posGlobal);
+}
+
+LLLandmark* LLLandmarkActions::getLandmark(const LLUUID& landmarkInventoryItemID, LLLandmarkList::loaded_callback_t cb)
+{
+ LLViewerInventoryItem* item = gInventory.getItem(landmarkInventoryItemID);
+ if (NULL == item)
+ return NULL;
+
+ const LLUUID& asset_id = item->getAssetUUID();
+
+ LLLandmark* landmark = gLandmarkList.getAsset(asset_id, cb);
+ if (landmark)
+ {
+ return landmark;
+ }
+
+ return NULL;
+}
+
+void LLLandmarkActions::copySLURLtoClipboard(const LLUUID& landmarkInventoryItemID)
+{
+ LLLandmark* landmark = LLLandmarkActions::getLandmark(landmarkInventoryItemID);
+ if(landmark)
+ {
+ LLVector3d global_pos;
+ landmark->getGlobalPos(global_pos);
+ LLLandmarkActions::getSLURLfromPosGlobal(global_pos,&copy_slurl_to_clipboard_callback,true);
+ }
+}
+
+void copy_slurl_to_clipboard_callback(const std::string& slurl)
+{
+ gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(slurl));
+ LLSD args;
+ args["SLURL"] = slurl;
+ LLNotificationsUtil::add("CopySLURL", args);
+}
diff --git a/indra/newview/lllandmarkactions.h b/indra/newview/lllandmarkactions.h
new file mode 100644
index 0000000000..987caf0936
--- /dev/null
+++ b/indra/newview/lllandmarkactions.h
@@ -0,0 +1,144 @@
+/**
+ * @file lllandmarkactions.h
+ * @brief LLLandmark class declaration
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLLANDMARKACTIONS_H
+#define LL_LLLANDMARKACTIONS_H
+
+#include "llinventorymodel.h"
+
+#include "lllandmarklist.h"
+
+class LLLandmark;
+
+/**
+ * @brief Provides helper functions to manage landmarks
+ */
+class LLLandmarkActions
+{
+public:
+ typedef boost::function<void(std::string& slurl)> slurl_callback_t;
+ typedef boost::function<void(std::string& slurl, S32 x, S32 y, S32 z)> region_name_and_coords_callback_t;
+
+ /**
+ * @brief Fetches landmark LLViewerInventoryItems for the given landmark name.
+ */
+ static LLInventoryModel::item_array_t fetchLandmarksByName(std::string& name, BOOL if_use_substring);
+ /**
+ * @brief Checks whether landmark exists for current agent position.
+ */
+ static bool landmarkAlreadyExists();
+
+ /**
+ * @brief Checks whether landmark exists for current agent parcel.
+ */
+ static bool hasParcelLandmark();
+
+ /**
+ * @brief Searches landmark for global position.
+ * @return Returns landmark or NULL.
+ *
+ * *TODO: dzaporozhan: There can be many landmarks for single parcel.
+ */
+ static LLViewerInventoryItem* findLandmarkForGlobalPos(const LLVector3d &pos);
+
+ /**
+ * @brief Searches landmark for agent global position.
+ * @return Returns landmark or NULL.
+ *
+ * *TODO: dzaporozhan: There can be many landmarks for single parcel.
+ */
+ static LLViewerInventoryItem* findLandmarkForAgentPos();
+
+
+ /**
+ * @brief Checks whether agent has rights to create landmark for current parcel.
+ */
+ static bool canCreateLandmarkHere();
+
+ /**
+ * @brief Creates landmark for current parcel.
+ */
+ static void createLandmarkHere();
+
+ /**
+ * @brief Creates landmark for current parcel.
+ */
+ static void createLandmarkHere(
+ const std::string& name,
+ const std::string& desc,
+ const LLUUID& folder_id);
+ /**
+ * @brief Creates SLURL for given global position.
+ */
+ static void getSLURLfromPosGlobal(const LLVector3d& global_pos, slurl_callback_t cb, bool escaped = true);
+
+ static void getRegionNameAndCoordsFromPosGlobal(const LLVector3d& global_pos, region_name_and_coords_callback_t cb);
+
+ /**
+ * @brief Gets landmark global position specified by inventory LLUUID.
+ * Found position is placed into "posGlobal" variable.
+ *.
+ * @return - true if specified item exists in Inventory and an appropriate landmark found.
+ * and its position is known, false otherwise.
+ */
+ // *TODO: mantipov: profide callback for cases, when Landmark is not loaded yet.
+ static bool getLandmarkGlobalPos(const LLUUID& landmarkInventoryItemID, LLVector3d& posGlobal);
+
+ /**
+ * @brief Retrieve a landmark from gLandmarkList by inventory item's id
+ * If a landmark is not currently in the gLandmarkList a callback "cb" is called when it is loaded.
+ *
+ * @return pointer to loaded landmark from gLandmarkList or NULL if landmark does not exist or wasn't loaded.
+ */
+ static LLLandmark* getLandmark(const LLUUID& landmarkInventoryItemID, LLLandmarkList::loaded_callback_t cb = NULL);
+
+ /**
+ * @brief Performs standard action of copying of SLURL from landmark to user's clipboard.
+ * This action requires additional server request. The user will be notified by info message,
+ * when URL is copied .
+ */
+ static void copySLURLtoClipboard(const LLUUID& landmarkInventoryItemID);
+
+private:
+ LLLandmarkActions();
+ LLLandmarkActions(const LLLandmarkActions&);
+
+ static void onRegionResponseSLURL(slurl_callback_t cb,
+ const LLVector3d& global_pos,
+ bool escaped,
+ const std::string& url);
+ static void onRegionResponseNameAndCoords(region_name_and_coords_callback_t cb,
+ const LLVector3d& global_pos,
+ U64 region_handle);
+};
+
+#endif //LL_LLLANDMARKACTIONS_H
diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp
index 2f43b41042..ce84474c05 100644
--- a/indra/newview/lllandmarklist.cpp
+++ b/indra/newview/lllandmarklist.cpp
@@ -37,8 +37,8 @@
#include "message.h"
#include "llassetstorage.h"
+#include "llappviewer.h"
#include "llagent.h"
-#include "llnotify.h"
#include "llvfile.h"
#include "llviewerstats.h"
@@ -54,23 +54,48 @@ LLLandmarkList::~LLLandmarkList()
std::for_each(mList.begin(), mList.end(), DeletePairedPointer());
}
-LLLandmark* LLLandmarkList::getAsset( const LLUUID& asset_uuid )
+LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t cb)
{
LLLandmark* landmark = get_ptr_in_map(mList, asset_uuid);
if(landmark)
{
+ LLVector3d dummy;
+ if(cb && !landmark->getGlobalPos(dummy))
+ {
+ // landmark is not completely loaded yet
+ loaded_callback_map_t::value_type vt(asset_uuid, cb);
+ mLoadedCallbackMap.insert(vt);
+ }
return landmark;
}
else
{
- if ( gLandmarkList.mBadList.find(asset_uuid) == gLandmarkList.mBadList.end() )
+ if ( mBadList.find(asset_uuid) != mBadList.end() )
{
- gAssetStorage->getAssetData(
- asset_uuid,
- LLAssetType::AT_LANDMARK,
- LLLandmarkList::processGetAssetReply,
- NULL);
+ return NULL;
}
+
+ landmark_requested_list_t::iterator iter = mRequestedList.find(asset_uuid);
+ if (iter != mRequestedList.end())
+ {
+ const F32 rerequest_time = 30.f; // 30 seconds between requests
+ if (gFrameTimeSeconds - iter->second < rerequest_time)
+ {
+ return NULL;
+ }
+ }
+
+ if (cb)
+ {
+ loaded_callback_map_t::value_type vt(asset_uuid, cb);
+ mLoadedCallbackMap.insert(vt);
+ }
+
+ gAssetStorage->getAssetData(asset_uuid,
+ LLAssetType::AT_LANDMARK,
+ LLLandmarkList::processGetAssetReply,
+ NULL);
+ mRequestedList[asset_uuid] = gFrameTimeSeconds;
}
return NULL;
}
@@ -96,6 +121,9 @@ void LLLandmarkList::processGetAssetReply(
LLLandmark* landmark = LLLandmark::constructFromString(&buffer[0]);
if (landmark)
{
+ gLandmarkList.mList[ uuid ] = landmark;
+ gLandmarkList.mRequestedList.erase(uuid);
+
LLVector3d pos;
if(!landmark->getGlobalPos(pos))
{
@@ -106,23 +134,30 @@ void LLLandmarkList::processGetAssetReply(
gMessageSystem,
gAgent.getRegionHost(),
region_id,
- NULL);
+ boost::bind(&LLLandmarkList::onRegionHandle, &gLandmarkList, uuid));
}
+
+ // the callback will be called when we get the region handle.
+ }
+ else
+ {
+ gLandmarkList.makeCallbacks(uuid);
}
- gLandmarkList.mList[ uuid ] = landmark;
}
}
else
{
LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED );
-
+ // SJB: No use case for a notification here. Use lldebugs instead
if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status )
{
- LLNotifications::instance().add("LandmarkMissing");
+ LL_WARNS("Landmarks") << "Missing Landmark" << LL_ENDL;
+ //LLNotificationsUtil::add("LandmarkMissing");
}
else
{
- LLNotifications::instance().add("UnableToLoadLandmark");
+ LL_WARNS("Landmarks") << "Unable to load Landmark" << LL_ENDL;
+ //LLNotificationsUtil::add("UnableToLoadLandmark");
}
gLandmarkList.mBadList.insert(uuid);
@@ -134,3 +169,45 @@ BOOL LLLandmarkList::assetExists(const LLUUID& asset_uuid)
{
return mList.count(asset_uuid) != 0 || mBadList.count(asset_uuid) != 0;
}
+
+void LLLandmarkList::onRegionHandle(const LLUUID& landmark_id)
+{
+ LLLandmark* landmark = getAsset(landmark_id);
+
+ if (!landmark)
+ {
+ llwarns << "Got region handle but the landmark not found." << llendl;
+ return;
+ }
+
+ // Calculate landmark global position.
+ // This should succeed since the region handle is available.
+ LLVector3d pos;
+ if (!landmark->getGlobalPos(pos))
+ {
+ llwarns << "Got region handle but the landmark global position is still unknown." << llendl;
+ return;
+ }
+
+ makeCallbacks(landmark_id);
+}
+
+void LLLandmarkList::makeCallbacks(const LLUUID& landmark_id)
+{
+ LLLandmark* landmark = getAsset(landmark_id);
+
+ if (!landmark)
+ {
+ llwarns << "Landmark to make callbacks for not found." << llendl;
+ }
+
+ // make all the callbacks here.
+ loaded_callback_map_t::iterator it;
+ while((it = mLoadedCallbackMap.find(landmark_id)) != mLoadedCallbackMap.end())
+ {
+ if (landmark)
+ (*it).second(landmark);
+
+ mLoadedCallbackMap.erase(it);
+ }
+}
diff --git a/indra/newview/lllandmarklist.h b/indra/newview/lllandmarklist.h
index c41ba7a0f0..d9c3267142 100644
--- a/indra/newview/lllandmarklist.h
+++ b/indra/newview/lllandmarklist.h
@@ -33,6 +33,7 @@
#ifndef LL_LLLANDMARKLIST_H
#define LL_LLLANDMARKLIST_H
+#include <boost/function.hpp>
#include <map>
#include "lllandmark.h"
#include "lluuid.h"
@@ -45,6 +46,8 @@ class LLInventoryItem;
class LLLandmarkList
{
public:
+ typedef boost::function<void(LLLandmark*)> loaded_callback_t;
+
LLLandmarkList() {}
~LLLandmarkList();
@@ -53,7 +56,7 @@ public:
//const LLLandmark* getNext() { return mList.getNextData(); }
BOOL assetExists(const LLUUID& asset_uuid);
- LLLandmark* getAsset(const LLUUID& asset_uuid);
+ LLLandmark* getAsset(const LLUUID& asset_uuid, loaded_callback_t cb = NULL);
static void processGetAssetReply(
LLVFS *vfs,
const LLUUID& uuid,
@@ -63,11 +66,22 @@ public:
LLExtStat ext_status );
protected:
+ void onRegionHandle(const LLUUID& landmark_id);
+ void makeCallbacks(const LLUUID& landmark_id);
+
typedef std::map<LLUUID, LLLandmark*> landmark_list_t;
landmark_list_t mList;
typedef std::set<LLUUID> landmark_bad_list_t;
landmark_bad_list_t mBadList;
+
+ typedef std::map<LLUUID,F32> landmark_requested_list_t;
+ landmark_requested_list_t mRequestedList;
+
+ // *TODO: make the callback multimap a template class and make use of it
+ // here and in LLLandmark.
+ typedef std::multimap<LLUUID, loaded_callback_t> loaded_callback_map_t;
+ loaded_callback_map_t mLoadedCallbackMap;
};
diff --git a/indra/newview/lllistbrowser.cpp b/indra/newview/lllistbrowser.cpp
new file mode 100644
index 0000000000..edd8e9818f
--- /dev/null
+++ b/indra/newview/lllistbrowser.cpp
@@ -0,0 +1,37 @@
+/**
+ * @file lllistbrowser.cpp
+ * @brief UI widget showing a search filter, list view, icon action buttons,
+ * and verb action buttons, as usually embedded in the side tray.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "llviewerprecompiledheaders.h"
+
+#include "lllistbrowser.h"
+
+// TODO
diff --git a/indra/newview/lllistbrowser.h b/indra/newview/lllistbrowser.h
new file mode 100644
index 0000000000..bc9498c514
--- /dev/null
+++ b/indra/newview/lllistbrowser.h
@@ -0,0 +1,36 @@
+/**
+ * @file lllistbrowser.h
+ * @brief UI widget showing a search filter, list view, icon action buttons,
+ * and verb action buttons, as usually embedded in the side tray.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef LLLISTBROWSER_H
+#define LLLISTBROWSER_H
+
+#endif // LLLISTBROWSER_H
diff --git a/indra/newview/lllistview.cpp b/indra/newview/lllistview.cpp
new file mode 100644
index 0000000000..f4f3b1df78
--- /dev/null
+++ b/indra/newview/lllistview.cpp
@@ -0,0 +1,73 @@
+/**
+ * @file lllistview.cpp
+ * @brief UI widget containing a scrollable, possibly hierarchical list of
+ * folders (LLListViewFolder) and items (LLListViewItem).
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "llviewerprecompiledheaders.h"
+
+#include "lllistview.h"
+
+#include "lltextbox.h"
+#include "lluictrlfactory.h" // LLDefaultChildRegistry
+
+// linker optimizes this out on Windows until there is a real reference
+// to this file
+static LLDefaultChildRegistry::Register<LLListView> r("list_view");
+
+LLListView::Params::Params()
+: bg_color("bg_color"),
+ fg_selected_color("fg_selected_color"),
+ bg_selected_color("bg_selected_color")
+{}
+
+LLListView::LLListView(const Params& p)
+: LLUICtrl(p),
+ mLabel(NULL),
+ mBgColor(p.bg_color()),
+ mFgSelectedColor(p.fg_selected_color()),
+ mBgSelectedColor(p.bg_selected_color())
+{
+ LLRect label_rect(0, 20, 300, 0);
+ LLTextBox::Params text_box_params;
+ text_box_params.rect(label_rect);
+ text_box_params.initial_value("This is a list-view");
+ mLabel = LLUICtrlFactory::create<LLTextBox>(text_box_params);
+ addChild(mLabel);
+}
+
+LLListView::~LLListView()
+{}
+
+
+// placeholder for setting a property
+void LLListView::setString(const std::string& s)
+{
+ mLabel->setValue( LLSD(s) );
+}
diff --git a/indra/newview/lllistview.h b/indra/newview/lllistview.h
new file mode 100644
index 0000000000..501c0c9e1f
--- /dev/null
+++ b/indra/newview/lllistview.h
@@ -0,0 +1,66 @@
+/**
+ * @file lllistview.h
+ * @brief UI widget containing a scrollable, possibly hierarchical list of
+ * folders (LLListViewFolder) and items (LLListViewItem).
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef LLLISTVIEW_H
+#define LLLISTVIEW_H
+
+#include "llui.h" // for LLUIColor, *TODO: use more specific header
+#include "lluictrl.h"
+
+class LLTextBox;
+
+class LLListView
+: public LLUICtrl
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<LLUIColor> bg_color,
+ fg_selected_color,
+ bg_selected_color;
+ Params();
+ };
+ LLListView(const Params& p);
+ virtual ~LLListView();
+
+ // placeholder for setting a property
+ void setString(const std::string& s);
+
+private:
+ // TODO: scroll container?
+ LLTextBox* mLabel; // just for testing
+ LLUIColor mBgColor;
+ LLUIColor mFgSelectedColor;
+ LLUIColor mBgSelectedColor;
+};
+
+#endif // LLLISTVIEW_H
diff --git a/indra/newview/lllocaltextureobject.cpp b/indra/newview/lllocaltextureobject.cpp
new file mode 100644
index 0000000000..6bcbe6f58c
--- /dev/null
+++ b/indra/newview/lllocaltextureobject.cpp
@@ -0,0 +1,215 @@
+/**
+ * @file lllocaltextureobject.cpp
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lllocaltextureobject.h"
+
+#include "lltexlayer.h"
+#include "llviewertexture.h"
+#include "lltextureentry.h"
+#include "lluuid.h"
+#include "llwearable.h"
+
+
+LLLocalTextureObject::LLLocalTextureObject() :
+ mIsBakedReady(FALSE),
+ mDiscard(MAX_DISCARD_LEVEL+1)
+{
+ mImage = NULL;
+}
+
+LLLocalTextureObject::LLLocalTextureObject(LLViewerFetchedTexture* image, const LLUUID& id)
+{
+ mImage = image;
+ gGL.getTexUnit(0)->bind(mImage);
+ mID = id;
+}
+
+LLLocalTextureObject::LLLocalTextureObject(const LLLocalTextureObject& lto) :
+ mImage(lto.mImage),
+ mID(lto.mID),
+ mIsBakedReady(lto.mIsBakedReady),
+ mDiscard(lto.mDiscard)
+{
+ U32 num_layers = lto.getNumTexLayers();
+ mTexLayers.reserve(num_layers);
+ for (U32 index = 0; index < num_layers; index++)
+ {
+ LLTexLayer* original_layer = lto.getTexLayer(index);
+ if (!original_layer)
+ {
+ llerrs << "could not clone Local Texture Object: unable to extract texlayer!" << llendl;
+ }
+
+ LLTexLayer* new_layer = new LLTexLayer(*original_layer);
+ new_layer->setLTO(this);
+ mTexLayers.push_back(new_layer);
+ }
+}
+
+LLLocalTextureObject::~LLLocalTextureObject()
+{
+}
+
+LLViewerFetchedTexture* LLLocalTextureObject::getImage() const
+{
+ return mImage;
+}
+
+LLTexLayer* LLLocalTextureObject::getTexLayer(U32 index) const
+{
+ if (index >= getNumTexLayers())
+ {
+ return NULL;
+ }
+
+ return mTexLayers[index];
+}
+
+LLTexLayer* LLLocalTextureObject::getTexLayer(const std::string &name)
+{
+ for( tex_layer_vec_t::iterator iter = mTexLayers.begin(); iter != mTexLayers.end(); iter++)
+ {
+ LLTexLayer *layer = *iter;
+ if (layer->getName().compare(name) == 0)
+ {
+ return layer;
+ }
+ }
+
+ return NULL;
+}
+
+U32 LLLocalTextureObject::getNumTexLayers() const
+{
+ return mTexLayers.size();
+}
+
+LLUUID LLLocalTextureObject::getID() const
+{
+ return mID;
+}
+
+S32 LLLocalTextureObject::getDiscard() const
+{
+ return mDiscard;
+}
+
+BOOL LLLocalTextureObject::getBakedReady() const
+{
+ return mIsBakedReady;
+}
+
+void LLLocalTextureObject::setImage(LLViewerFetchedTexture* new_image)
+{
+ mImage = new_image;
+}
+
+BOOL LLLocalTextureObject::setTexLayer(LLTexLayer *new_tex_layer, U32 index)
+{
+ if (index >= getNumTexLayers() )
+ {
+ return FALSE;
+ }
+
+ if (new_tex_layer == NULL)
+ {
+ return removeTexLayer(index);
+ }
+
+ LLTexLayer *layer = new LLTexLayer(*new_tex_layer);
+ layer->setLTO(this);
+
+ if (mTexLayers[index])
+ {
+ delete mTexLayers[index];
+ }
+ mTexLayers[index] = layer;
+
+ return TRUE;
+}
+
+BOOL LLLocalTextureObject::addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable)
+{
+ if (new_tex_layer == NULL)
+ {
+ return FALSE;
+ }
+
+ LLTexLayer *layer = new LLTexLayer(*new_tex_layer, wearable);
+ layer->setLTO(this);
+ mTexLayers.push_back(layer);
+ return TRUE;
+}
+
+BOOL LLLocalTextureObject::addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable)
+{
+ if (new_tex_layer == NULL)
+ {
+ return FALSE;
+ }
+
+ LLTexLayer *layer = new LLTexLayer(*new_tex_layer, this, wearable);
+ layer->setLTO(this);
+ mTexLayers.push_back(layer);
+ return TRUE;
+}
+
+BOOL LLLocalTextureObject::removeTexLayer(U32 index)
+{
+ if (index >= getNumTexLayers())
+ {
+ return FALSE;
+ }
+ tex_layer_vec_t::iterator iter = mTexLayers.begin();
+ iter += index;
+
+ delete *iter;
+ mTexLayers.erase(iter);
+ return TRUE;
+}
+
+void LLLocalTextureObject::setID(LLUUID new_id)
+{
+ mID = new_id;
+}
+
+void LLLocalTextureObject::setDiscard(S32 new_discard)
+{
+ mDiscard = new_discard;
+}
+
+void LLLocalTextureObject::setBakedReady(BOOL ready)
+{
+ mIsBakedReady = ready;
+}
+
diff --git a/indra/newview/lllocaltextureobject.h b/indra/newview/lllocaltextureobject.h
new file mode 100644
index 0000000000..c8b8aa924b
--- /dev/null
+++ b/indra/newview/lllocaltextureobject.h
@@ -0,0 +1,93 @@
+/**
+ * @file lllocaltextureobject.h
+ * @brief LLLocalTextureObject class header file
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LOCALTEXTUREOBJECT_H
+#define LL_LOCALTEXTUREOBJECT_H
+
+#include <boost/shared_ptr.hpp>
+
+#include "llviewertexture.h"
+
+class LLUUID;
+class LLTexLayer;
+class LLTextureEntry;
+class LLTexLayerTemplate;
+class LLWearable;
+
+// Stores all relevant information for a single texture
+// assumed to have ownership of all objects referred to -
+// will delete objects when being replaced or if object is destroyed.
+class LLLocalTextureObject
+{
+public:
+ LLLocalTextureObject();
+ LLLocalTextureObject(LLViewerFetchedTexture* image, const LLUUID& id);
+ LLLocalTextureObject(const LLLocalTextureObject& lto);
+ ~LLLocalTextureObject();
+
+ LLViewerFetchedTexture* getImage() const;
+ LLTexLayer* getTexLayer(U32 index) const;
+ LLTexLayer* getTexLayer(const std::string &name);
+ U32 getNumTexLayers() const;
+ LLUUID getID() const;
+ S32 getDiscard() const;
+ BOOL getBakedReady() const;
+
+ void setImage(LLViewerFetchedTexture* new_image);
+ BOOL setTexLayer(LLTexLayer *new_tex_layer, U32 index);
+ BOOL addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable);
+ BOOL addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable);
+ BOOL removeTexLayer(U32 index);
+
+ void setID(LLUUID new_id);
+ void setDiscard(S32 new_discard);
+ void setBakedReady(BOOL ready);
+
+protected:
+
+private:
+
+ LLPointer<LLViewerFetchedTexture> mImage;
+ // NOTE: LLLocalTextureObject should be the exclusive owner of mTexEntry and mTexLayer
+ // using shared pointers here only for smart assignment & cleanup
+ // do NOT create new shared pointers to these objects, or keep pointers to them around
+ typedef std::vector<LLTexLayer*> tex_layer_vec_t;
+ tex_layer_vec_t mTexLayers;
+
+ LLUUID mID;
+
+ BOOL mIsBakedReady;
+ S32 mDiscard;
+};
+
+ #endif // LL_LOCALTEXTUREOBJECT_H
+
diff --git a/indra/newview/lllocationhistory.cpp b/indra/newview/lllocationhistory.cpp
new file mode 100644
index 0000000000..ae1b8f8540
--- /dev/null
+++ b/indra/newview/lllocationhistory.cpp
@@ -0,0 +1,182 @@
+/**
+ * @file lllocationhistory.cpp
+ * @brief Typed locations history
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lllocationhistory.h"
+
+#include <iomanip> // for std::setw()
+
+#include "llui.h"
+#include "llsd.h"
+#include "llsdserialize.h"
+
+LLLocationHistory::LLLocationHistory() :
+ mFilename("typed_locations.txt")
+{
+}
+
+void LLLocationHistory::addItem(const LLLocationHistoryItem& item) {
+ static LLUICachedControl<S32> max_items("LocationHistoryMaxSize", 100);
+
+ // check if this item doesn't duplicate any existing one
+ location_list_t::iterator item_iter = std::find(mItems.begin(), mItems.end(),item);
+ if(item_iter != mItems.end()){
+ mItems.erase(item_iter);
+ }
+
+ mItems.push_back(item);
+
+ // If the vector size exceeds the maximum, purge the oldest items.
+ if ((S32)mItems.size() > max_items) {
+ for(location_list_t::iterator i = mItems.begin(); i != mItems.end()-max_items; ++i) {
+ mItems.erase(i);
+ }
+ }
+}
+
+/*
+ * @brief Try to find item in history.
+ * If item has been founded, it will be places into end of history.
+ * @return true - item has founded
+ */
+bool LLLocationHistory::touchItem(const LLLocationHistoryItem& item) {
+ bool result = false;
+ location_list_t::iterator item_iter = std::find(mItems.begin(), mItems.end(), item);
+
+ // the last used item should be the first in the history
+ if (item_iter != mItems.end()) {
+ mItems.erase(item_iter);
+ mItems.push_back(item);
+ result = true;
+ }
+
+ return result;
+}
+
+void LLLocationHistory::removeItems()
+{
+ mItems.clear();
+}
+
+bool LLLocationHistory::getMatchingItems(std::string substring, location_list_t& result) const
+{
+ // *TODO: an STL algorithm would look nicer
+ result.clear();
+
+ std::string needle = substring;
+ LLStringUtil::toLower(needle);
+
+ for (location_list_t::const_iterator it = mItems.begin(); it != mItems.end(); ++it)
+ {
+ std::string haystack = it->getLocation();
+ LLStringUtil::toLower(haystack);
+
+ if (haystack.find(needle) != std::string::npos)
+ result.push_back(*it);
+ }
+
+ return result.size();
+}
+
+void LLLocationHistory::dump() const
+{
+ llinfos << "Location history dump:" << llendl;
+ int i = 0;
+ for (location_list_t::const_iterator it = mItems.begin(); it != mItems.end(); ++it, ++i)
+ {
+ llinfos << "#" << std::setw(2) << std::setfill('0') << i << ": " << it->getLocation() << llendl;
+ }
+}
+
+void LLLocationHistory::save() const
+{
+ // build filename for each user
+ std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, mFilename);
+
+ if (resolved_filename.empty())
+ {
+ llinfos << "can't get path to location history filename - probably not logged in yet." << llendl;
+ return;
+ }
+
+ // open a file for writing
+ llofstream file (resolved_filename);
+ if (!file.is_open())
+ {
+ llwarns << "can't open location history file \"" << mFilename << "\" for writing" << llendl;
+ return;
+ }
+
+ for (location_list_t::const_iterator it = mItems.begin(); it != mItems.end(); ++it)
+ {
+ file << LLSDOStreamer<LLSDNotationFormatter>((*it).toLLSD()) << std::endl;
+ }
+
+ file.close();
+}
+
+void LLLocationHistory::load()
+{
+ llinfos << "Loading location history." << llendl;
+
+ // build filename for each user
+ std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, mFilename);
+ llifstream file(resolved_filename);
+
+ if (!file.is_open())
+ {
+ llwarns << "can't load location history from file \"" << mFilename << "\"" << llendl;
+ return;
+ }
+
+ removeItems();
+
+ // add each line in the file to the list
+ std::string line;
+ LLPointer<LLSDParser> parser = new LLSDNotationParser();
+ while (std::getline(file, line)) {
+ LLSD s_item;
+ std::istringstream iss(line);
+ if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE)
+ {
+ llinfos<< "Parsing saved teleport history failed" << llendl;
+ break;
+ }
+
+ mItems.push_back(s_item);
+ }
+
+ file.close();
+
+ mLoadedSignal();
+}
diff --git a/indra/newview/lllocationhistory.h b/indra/newview/lllocationhistory.h
new file mode 100644
index 0000000000..5f9976f87a
--- /dev/null
+++ b/indra/newview/lllocationhistory.h
@@ -0,0 +1,137 @@
+/**
+ * @file llocationhistory.h
+ * @brief Typed locations history
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLLOCATIONHISTORY_H
+#define LL_LLLOCATIONHISTORY_H
+
+#include "llsingleton.h" // for LLSingleton
+
+#include <vector>
+#include <string>
+#include <map>
+#include <boost/function.hpp>
+
+class LLSD;
+
+enum ELocationType {
+ TYPED_REGION_SURL//region name or surl
+ ,LANDMARK // name of landmark
+ ,TELEPORT_HISTORY
+ };
+class LLLocationHistoryItem {
+
+public:
+ LLLocationHistoryItem(){}
+ LLLocationHistoryItem(std::string typed_location,
+ LLVector3d global_position, std::string tooltip,ELocationType type ):
+ mLocation(typed_location),
+ mGlobalPos(global_position),
+ mToolTip(tooltip),
+ mType(type)
+ {}
+ LLLocationHistoryItem(const LLLocationHistoryItem& item):
+ mGlobalPos(item.mGlobalPos),
+ mToolTip(item.mToolTip),
+ mLocation(item.mLocation),
+ mType(item.mType)
+ {}
+ LLLocationHistoryItem(const LLSD& data):
+ mLocation(data["location"]),
+ mGlobalPos(data["global_pos"]),
+ mToolTip(data["tooltip"]),
+ mType(ELocationType(data["item_type"].asInteger()))
+ {}
+
+ bool operator==(const LLLocationHistoryItem& item)
+ {
+ // do not compare mGlobalPos,
+ // because of a rounding off , the history can contain duplicates
+ return mLocation == item.mLocation && (mType == item.mType);
+ }
+ bool operator!=(const LLLocationHistoryItem& item)
+ {
+ return ! (*this == item);
+ }
+ LLSD toLLSD() const
+ {
+ LLSD val;
+ val["location"]= mLocation;
+ val["global_pos"] = mGlobalPos.getValue();
+ val["tooltip"] = mToolTip;
+ val["item_type"] = mType;
+ return val;
+ }
+ const std::string& getLocation() const { return mLocation; };
+ const std::string& getToolTip() const { return mToolTip; };
+ //static bool equalByRegionParcel(const LLLocationHistoryItem& item1, const LLLocationHistoryItem& item2);
+ static bool equalByLocation(const LLLocationHistoryItem& item1, const std::string& item_location)
+ {
+ return item1.getLocation() == item_location;
+ }
+
+ LLVector3d mGlobalPos; // global position
+ std::string mToolTip;// SURL
+ std::string mLocation;// typed_location
+ ELocationType mType;
+};
+
+class LLLocationHistory: public LLSingleton<LLLocationHistory>
+{
+ LOG_CLASS(LLLocationHistory);
+
+public:
+ typedef std::vector<LLLocationHistoryItem> location_list_t;
+ typedef boost::function<void()> loaded_callback_t;
+ typedef boost::signals2::signal<void()> loaded_signal_t;
+
+ LLLocationHistory();
+
+ void addItem(const LLLocationHistoryItem& item);
+ bool touchItem(const LLLocationHistoryItem& item);
+ void removeItems();
+ size_t getItemCount() const { return mItems.size(); }
+ const location_list_t& getItems() const { return mItems; }
+ bool getMatchingItems(std::string substring, location_list_t& result) const;
+ boost::signals2::connection setLoadedCallback(loaded_callback_t cb) { return mLoadedSignal.connect(cb); }
+
+ void save() const;
+ void load();
+ void dump() const;
+
+private:
+
+ location_list_t mItems;
+ std::string mFilename; /// File to store the history to.
+ loaded_signal_t mLoadedSignal;
+};
+
+#endif
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
new file mode 100644
index 0000000000..7f49a7defb
--- /dev/null
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -0,0 +1,972 @@
+/**
+ * @file lllocationinputctrl.cpp
+ * @brief Combobox-like location input control
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+// file includes
+#include "lllocationinputctrl.h"
+
+// common includes
+#include "llbutton.h"
+#include "llfocusmgr.h"
+#include "llmenugl.h"
+#include "llstring.h"
+#include "lltrans.h"
+#include "lluictrlfactory.h"
+#include "lltooltip.h"
+#include "llnotificationsutil.h"
+#include "llregionflags.h"
+
+// newview includes
+#include "llagent.h"
+#include "llinventoryobserver.h"
+#include "lllandmarkactions.h"
+#include "lllandmarklist.h"
+#include "lllocationhistory.h"
+#include "llteleporthistory.h"
+#include "llsidetray.h"
+#include "llslurl.h"
+#include "llstatusbar.h" // getHealth()
+#include "lltrans.h"
+#include "llviewerinventory.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+#include "llviewercontrol.h"
+#include "llviewermenu.h"
+#include "llurllineeditorctrl.h"
+#include "llagentui.h"
+
+//============================================================================
+/*
+ * "ADD LANDMARK" BUTTON UPDATING LOGIC
+ *
+ * If the current parcel has been landmarked, we should draw
+ * a special image on the button.
+ *
+ * To avoid determining the appropriate image on every draw() we do that
+ * only in the following cases:
+ * 1) Navbar is shown for the first time after login.
+ * 2) Agent moves to another parcel.
+ * 3) A landmark is created or removed.
+ *
+ * The first case is handled by the handleLoginComplete() method.
+ *
+ * The second case is handled by setting the "agent parcel changed" callback
+ * on LLViewerParcelMgr.
+ *
+ * The third case is the most complex one. We have two inventory observers for that:
+ * one is designated to handle adding landmarks, the other handles removal.
+ * Let's see how the former works.
+ *
+ * When we get notified about landmark addition, the landmark position is unknown yet. What we can
+ * do at that point is initiate loading the landmark data by LLLandmarkList and set the
+ * "loading finished" callback on it. Finally, when the callback is triggered,
+ * we can determine whether the landmark refers to a point within the current parcel
+ * and choose the appropriate image for the "Add landmark" button.
+ */
+
+/**
+ * Initiates loading the landmarks that have been just added.
+ *
+ * Once the loading is complete we'll be notified
+ * with the callback we set for LLLandmarkList.
+ */
+class LLAddLandmarkObserver : public LLInventoryAddedObserver
+{
+public:
+ LLAddLandmarkObserver(LLLocationInputCtrl* input) : mInput(input) {}
+
+private:
+ /*virtual*/ void done()
+ {
+ std::vector<LLUUID>::const_iterator it = mAdded.begin(), end = mAdded.end();
+ for(; it != end; ++it)
+ {
+ LLInventoryItem* item = gInventory.getItem(*it);
+ if (!item || item->getType() != LLAssetType::AT_LANDMARK)
+ continue;
+
+ // Start loading the landmark.
+ LLLandmark* lm = gLandmarkList.getAsset(
+ item->getAssetUUID(),
+ boost::bind(&LLLocationInputCtrl::onLandmarkLoaded, mInput, _1));
+ if (lm)
+ {
+ // Already loaded? Great, handle it immediately (the callback won't be called).
+ mInput->onLandmarkLoaded(lm);
+ }
+ }
+
+ mAdded.clear();
+ }
+
+ LLLocationInputCtrl* mInput;
+};
+
+/**
+ * Updates the "Add landmark" button once a landmark gets removed.
+ */
+class LLRemoveLandmarkObserver : public LLInventoryObserver
+{
+public:
+ LLRemoveLandmarkObserver(LLLocationInputCtrl* input) : mInput(input) {}
+
+private:
+ /*virtual*/ void changed(U32 mask)
+ {
+ if (mask & (~(LLInventoryObserver::LABEL|LLInventoryObserver::INTERNAL|LLInventoryObserver::ADD)))
+ {
+ mInput->updateAddLandmarkButton();
+ }
+ }
+
+ LLLocationInputCtrl* mInput;
+};
+
+//============================================================================
+
+
+static LLDefaultChildRegistry::Register<LLLocationInputCtrl> r("location_input");
+
+LLLocationInputCtrl::Params::Params()
+: add_landmark_image_enabled("add_landmark_image_enabled"),
+ add_landmark_image_disabled("add_landmark_image_disabled"),
+ add_landmark_image_hover("add_landmark_image_hover"),
+ add_landmark_image_selected("add_landmark_image_selected"),
+ add_landmark_hpad("add_landmark_hpad", 0),
+ icon_hpad("icon_hpad", 0),
+ add_landmark_button("add_landmark_button"),
+ for_sale_button("for_sale_button"),
+ info_button("info_button"),
+ voice_icon("voice_icon"),
+ fly_icon("fly_icon"),
+ push_icon("push_icon"),
+ build_icon("build_icon"),
+ scripts_icon("scripts_icon"),
+ damage_icon("damage_icon"),
+ damage_text("damage_text")
+{
+}
+
+LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p)
+: LLComboBox(p),
+ mIconHPad(p.icon_hpad),
+ mAddLandmarkHPad(p.add_landmark_hpad),
+ mLocationContextMenu(NULL),
+ mAddLandmarkBtn(NULL),
+ mForSaleBtn(NULL),
+ mInfoBtn(NULL),
+ mLandmarkImageOn(NULL),
+ mLandmarkImageOff(NULL)
+{
+ // Lets replace default LLLineEditor with LLLocationLineEditor
+ // to make needed escaping while copying and cutting url
+ this->removeChild(mTextEntry);
+ delete mTextEntry;
+
+ // Can't access old mTextEntry fields as they are protected, so lets build new params
+ // That is C&P from LLComboBox::createLineEditor function
+ static LLUICachedControl<S32> drop_shadow_button ("DropShadowButton", 0);
+ S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0;
+ LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
+ text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button;
+
+ LLLineEditor::Params params = p.combo_editor;
+ params.rect(text_entry_rect);
+ params.default_text(LLStringUtil::null);
+ params.max_length_bytes(p.max_chars);
+ params.keystroke_callback(boost::bind(&LLComboBox::onTextEntry, this, _1));
+ params.handle_edit_keys_directly(true);
+ params.commit_on_focus_lost(false);
+ params.follows.flags(FOLLOWS_ALL);
+ mTextEntry = LLUICtrlFactory::create<LLURLLineEditor>(params);
+ addChild(mTextEntry);
+ // LLLineEditor is replaced with LLLocationLineEditor
+
+ // "Place information" button.
+ LLButton::Params info_params = p.info_button;
+ mInfoBtn = LLUICtrlFactory::create<LLButton>(info_params);
+ mInfoBtn->setClickedCallback(boost::bind(&LLLocationInputCtrl::onInfoButtonClicked, this));
+ addChild(mInfoBtn);
+
+ // "Add landmark" button.
+ LLButton::Params al_params = p.add_landmark_button;
+
+ // Image for unselected state will be set in updateAddLandmarkButton(),
+ // it will be either mLandmarkOn or mLandmarkOff
+ if (p.add_landmark_image_enabled())
+ {
+ mLandmarkImageOn = p.add_landmark_image_enabled;
+ }
+ if (p.add_landmark_image_disabled())
+ {
+ mLandmarkImageOff = p.add_landmark_image_disabled;
+ }
+
+ if(p.add_landmark_image_selected)
+ {
+ al_params.image_selected = p.add_landmark_image_selected;
+ }
+ if (p.add_landmark_image_hover())
+ {
+ al_params.image_hover_unselected = p.add_landmark_image_hover;
+ }
+
+ al_params.click_callback.function(boost::bind(&LLLocationInputCtrl::onAddLandmarkButtonClicked, this));
+ mAddLandmarkBtn = LLUICtrlFactory::create<LLButton>(al_params);
+ enableAddLandmarkButton(true);
+ addChild(mAddLandmarkBtn);
+
+ LLButton::Params for_sale_button = p.for_sale_button;
+ for_sale_button.tool_tip = LLTrans::getString("LocationCtrlForSaleTooltip");
+ for_sale_button.click_callback.function(
+ boost::bind(&LLLocationInputCtrl::onForSaleButtonClicked, this));
+ mForSaleBtn = LLUICtrlFactory::create<LLButton>( for_sale_button );
+ addChild(mForSaleBtn);
+
+ // Parcel property icons
+ // Must be mouse-opaque so cursor stays as an arrow when hovering to
+ // see tooltip.
+ LLIconCtrl::Params voice_icon = p.voice_icon;
+ voice_icon.tool_tip = LLTrans::getString("LocationCtrlVoiceTooltip");
+ voice_icon.mouse_opaque = true;
+ mParcelIcon[VOICE_ICON] = LLUICtrlFactory::create<LLIconCtrl>(voice_icon);
+ mParcelIcon[VOICE_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, VOICE_ICON));
+ addChild(mParcelIcon[VOICE_ICON]);
+
+ LLIconCtrl::Params fly_icon = p.fly_icon;
+ fly_icon.tool_tip = LLTrans::getString("LocationCtrlFlyTooltip");
+ fly_icon.mouse_opaque = true;
+ mParcelIcon[FLY_ICON] = LLUICtrlFactory::create<LLIconCtrl>(fly_icon);
+ mParcelIcon[FLY_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, FLY_ICON));
+ addChild(mParcelIcon[FLY_ICON]);
+
+ LLIconCtrl::Params push_icon = p.push_icon;
+ push_icon.tool_tip = LLTrans::getString("LocationCtrlPushTooltip");
+ push_icon.mouse_opaque = true;
+ mParcelIcon[PUSH_ICON] = LLUICtrlFactory::create<LLIconCtrl>(push_icon);
+ mParcelIcon[PUSH_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, PUSH_ICON));
+ addChild(mParcelIcon[PUSH_ICON]);
+
+ LLIconCtrl::Params build_icon = p.build_icon;
+ build_icon.tool_tip = LLTrans::getString("LocationCtrlBuildTooltip");
+ build_icon.mouse_opaque = true;
+ mParcelIcon[BUILD_ICON] = LLUICtrlFactory::create<LLIconCtrl>(build_icon);
+ mParcelIcon[BUILD_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, BUILD_ICON));
+ addChild(mParcelIcon[BUILD_ICON]);
+
+ LLIconCtrl::Params scripts_icon = p.scripts_icon;
+ scripts_icon.tool_tip = LLTrans::getString("LocationCtrlScriptsTooltip");
+ scripts_icon.mouse_opaque = true;
+ mParcelIcon[SCRIPTS_ICON] = LLUICtrlFactory::create<LLIconCtrl>(scripts_icon);
+ mParcelIcon[SCRIPTS_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, SCRIPTS_ICON));
+ addChild(mParcelIcon[SCRIPTS_ICON]);
+
+ LLIconCtrl::Params damage_icon = p.damage_icon;
+ damage_icon.tool_tip = LLTrans::getString("LocationCtrlDamageTooltip");
+ damage_icon.mouse_opaque = true;
+ mParcelIcon[DAMAGE_ICON] = LLUICtrlFactory::create<LLIconCtrl>(damage_icon);
+ mParcelIcon[DAMAGE_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, DAMAGE_ICON));
+ addChild(mParcelIcon[DAMAGE_ICON]);
+
+ LLTextBox::Params damage_text = p.damage_text;
+ damage_text.tool_tip = LLTrans::getString("LocationCtrlDamageTooltip");
+ damage_text.mouse_opaque = true;
+ mDamageText = LLUICtrlFactory::create<LLTextBox>(damage_text);
+ addChild(mDamageText);
+
+ // Register callbacks and load the location field context menu (NB: the order matters).
+ LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Navbar.Action", boost::bind(&LLLocationInputCtrl::onLocationContextMenuItemClicked, this, _2));
+ LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Navbar.EnableMenuItem", boost::bind(&LLLocationInputCtrl::onLocationContextMenuItemEnabled, this, _2));
+
+ setPrearrangeCallback(boost::bind(&LLLocationInputCtrl::onLocationPrearrange, this, _2));
+ getTextEntry()->setMouseUpCallback(boost::bind(&LLLocationInputCtrl::changeLocationPresentation, this));
+
+ // Load the location field context menu
+ mLocationContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_navbar.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if (!mLocationContextMenu)
+ {
+ llwarns << "Error loading navigation bar context menu" << llendl;
+
+ }
+ getTextEntry()->setRightMouseUpCallback(boost::bind(&LLLocationInputCtrl::onTextEditorRightClicked,this,_2,_3,_4));
+ updateWidgetlayout();
+
+ // - Make the "Add landmark" button updated when either current parcel gets changed
+ // or a landmark gets created or removed from the inventory.
+ // - Update the location string on parcel change.
+ mParcelMgrConnection = LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(
+ boost::bind(&LLLocationInputCtrl::onAgentParcelChange, this));
+
+ mLocationHistoryConnection = LLLocationHistory::getInstance()->setLoadedCallback(
+ boost::bind(&LLLocationInputCtrl::onLocationHistoryLoaded, this));
+
+ mRemoveLandmarkObserver = new LLRemoveLandmarkObserver(this);
+ mAddLandmarkObserver = new LLAddLandmarkObserver(this);
+ gInventory.addObserver(mRemoveLandmarkObserver);
+ gInventory.addObserver(mAddLandmarkObserver);
+
+ mAddLandmarkTooltip = LLTrans::getString("LocationCtrlAddLandmarkTooltip");
+ mEditLandmarkTooltip = LLTrans::getString("LocationCtrlEditLandmarkTooltip");
+ getChild<LLView>("Location History")->setToolTip(LLTrans::getString("LocationCtrlComboBtnTooltip"));
+ getChild<LLView>("Place Information")->setToolTip(LLTrans::getString("LocationCtrlInfoBtnTooltip"));
+}
+
+LLLocationInputCtrl::~LLLocationInputCtrl()
+{
+ gInventory.removeObserver(mRemoveLandmarkObserver);
+ gInventory.removeObserver(mAddLandmarkObserver);
+ delete mRemoveLandmarkObserver;
+ delete mAddLandmarkObserver;
+
+ mParcelMgrConnection.disconnect();
+ mLocationHistoryConnection.disconnect();
+}
+
+void LLLocationInputCtrl::setEnabled(BOOL enabled)
+{
+ LLComboBox::setEnabled(enabled);
+ mAddLandmarkBtn->setEnabled(enabled);
+}
+
+void LLLocationInputCtrl::hideList()
+{
+ LLComboBox::hideList();
+ if (mTextEntry && hasFocus())
+ focusTextEntry();
+}
+
+BOOL LLLocationInputCtrl::handleToolTip(S32 x, S32 y, MASK mask)
+{
+
+ if(mAddLandmarkBtn->parentPointInView(x,y))
+ {
+ updateAddLandmarkTooltip();
+ }
+ // Let the buttons show their tooltips.
+ if (LLUICtrl::handleToolTip(x, y, mask))
+ {
+ if (mList->getRect().pointInRect(x, y))
+ {
+ S32 loc_x, loc_y;
+ //x,y - contain coordinates related to the location input control, but without taking the expanded list into account
+ //So we have to convert it again into local coordinates of mList
+ localPointToOtherView(x,y,&loc_x,&loc_y,mList);
+
+ LLScrollListItem* item = mList->hitItem(loc_x,loc_y);
+ if (item)
+ {
+ LLSD value = item->getValue();
+ if (value.has("tooltip"))
+ {
+ LLToolTipMgr::instance().show(value["tooltip"]);
+ }
+ }
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL LLLocationInputCtrl::handleKeyHere(KEY key, MASK mask)
+{
+ BOOL result = LLComboBox::handleKeyHere(key, mask);
+
+ if (key == KEY_DOWN && hasFocus() && mList->getItemCount() != 0 && !mList->getVisible())
+ {
+ showList();
+ }
+
+ return result;
+}
+
+void LLLocationInputCtrl::onTextEntry(LLLineEditor* line_editor)
+{
+ KEY key = gKeyboard->currentKey();
+
+ if (line_editor->getText().empty())
+ {
+ prearrangeList(); // resets filter
+ hideList();
+ }
+ // Typing? (moving cursor should not affect showing the list)
+ else if (key != KEY_LEFT && key != KEY_RIGHT && key != KEY_HOME && key != KEY_END)
+ {
+ prearrangeList(line_editor->getText());
+ if (mList->getItemCount() != 0)
+ {
+ showList();
+ focusTextEntry();
+ }
+ else
+ {
+ // Hide the list if it's empty.
+ hideList();
+ }
+ }
+
+ LLComboBox::onTextEntry(line_editor);
+}
+
+/**
+ * Useful if we want to just set the text entry value, no matter what the list contains.
+ *
+ * This is faster than setTextEntry().
+ */
+void LLLocationInputCtrl::setText(const LLStringExplicit& text)
+{
+ mTextEntry->setText(text);
+ mHasAutocompletedText = FALSE;
+}
+
+void LLLocationInputCtrl::setFocus(BOOL b)
+{
+ LLComboBox::setFocus(b);
+
+ if (mTextEntry && b && !mList->getVisible())
+ mTextEntry->setFocus(TRUE);
+}
+
+void LLLocationInputCtrl::handleLoginComplete()
+{
+ // An agent parcel update hasn't occurred yet, so we have to
+ // manually set location and the appropriate "Add landmark" icon.
+ refresh();
+}
+
+//== private methods =========================================================
+
+void LLLocationInputCtrl::onFocusReceived()
+{
+ prearrangeList();
+}
+
+void LLLocationInputCtrl::onFocusLost()
+{
+ LLUICtrl::onFocusLost();
+ refreshLocation();
+ if(mTextEntry->hasSelection()){
+ mTextEntry->deselect();
+ }
+}
+
+void LLLocationInputCtrl::draw()
+{
+ static LLUICachedControl<bool> show_coords("NavBarShowCoordinates", false);
+ if(!hasFocus() && show_coords)
+ {
+ refreshLocation();
+ }
+
+ static LLUICachedControl<bool> show_icons("NavBarShowParcelProperties", false);
+ if (show_icons)
+ {
+ refreshHealth();
+ }
+ LLComboBox::draw();
+}
+
+void LLLocationInputCtrl::onInfoButtonClicked()
+{
+ LLSideTray::getInstance()->showPanel("panel_places", LLSD().with("type", "agent"));
+}
+
+void LLLocationInputCtrl::onForSaleButtonClicked()
+{
+ handle_buy_land();
+}
+
+void LLLocationInputCtrl::onAddLandmarkButtonClicked()
+{
+ LLViewerInventoryItem* landmark = LLLandmarkActions::findLandmarkForAgentPos();
+ // Landmark exists, open it for preview and edit
+ if(landmark && landmark->getUUID().notNull())
+ {
+ LLSD key;
+ key["type"] = "landmark";
+ key["id"] = landmark->getUUID();
+
+ LLSideTray::getInstance()->showPanel("panel_places", key);
+ }
+ else
+ {
+ LLSideTray::getInstance()->showPanel("panel_places", LLSD().with("type", "create_landmark"));
+ }
+}
+
+void LLLocationInputCtrl::onAgentParcelChange()
+{
+ refresh();
+}
+
+void LLLocationInputCtrl::onLandmarkLoaded(LLLandmark* lm)
+{
+ (void) lm;
+ updateAddLandmarkButton();
+}
+
+void LLLocationInputCtrl::onLocationHistoryLoaded()
+{
+ rebuildLocationHistory();
+}
+
+void LLLocationInputCtrl::onLocationPrearrange(const LLSD& data)
+{
+ std::string filter = data.asString();
+ rebuildLocationHistory(filter);
+
+ //Let's add landmarks to the top of the list if any
+ if(!filter.empty() )
+ {
+ LLInventoryModel::item_array_t landmark_items = LLLandmarkActions::fetchLandmarksByName(filter, TRUE);
+
+ for(U32 i=0; i < landmark_items.size(); i++)
+ {
+ LLSD value;
+ //TODO:: DO we need tooltip for Landmark??
+
+ value["item_type"] = LANDMARK;
+ value["AssetUUID"] = landmark_items[i]->getAssetUUID();
+ add(landmark_items[i]->getName(), value);
+
+ }
+ //Let's add teleport history items
+ LLTeleportHistory* th = LLTeleportHistory::getInstance();
+ LLTeleportHistory::slurl_list_t th_items = th->getItems();
+
+ std::set<std::string> new_item_titles;// duplicate control
+ LLTeleportHistory::slurl_list_t::iterator result = std::find_if(
+ th_items.begin(), th_items.end(), boost::bind(
+ &LLLocationInputCtrl::findTeleportItemsByTitle, this,
+ _1, filter));
+
+ while (result != th_items.end())
+ {
+ //mTitile format - region_name[, parcel_name]
+ //mFullTitile format - region_name[, parcel_name] (local_x,local_y, local_z)
+ if (new_item_titles.insert(result->mFullTitle).second)
+ {
+ LLSD value;
+ value["item_type"] = TELEPORT_HISTORY;
+ value["global_pos"] = result->mGlobalPos.getValue();
+ std::string region_name = result->mTitle.substr(0, result->mTitle.find(','));
+ //TODO*: add Surl to teleportitem or parse region name from title
+ value["tooltip"] = LLSLURL::buildSLURLfromPosGlobal(region_name,
+ result->mGlobalPos, false);
+ add(result->getTitle(), value);
+ }
+ result = std::find_if(result + 1, th_items.end(), boost::bind(
+ &LLLocationInputCtrl::findTeleportItemsByTitle, this,
+ _1, filter));
+ }
+ }
+ sortByName();
+
+ mList->mouseOverHighlightNthItem(-1); // Clear highlight on the last selected item.
+}
+
+bool LLLocationInputCtrl::findTeleportItemsByTitle(const LLTeleportHistoryItem& item, const std::string& filter)
+{
+ return item.mTitle.find(filter) != std::string::npos;
+}
+
+void LLLocationInputCtrl::onTextEditorRightClicked(S32 x, S32 y, MASK mask)
+{
+ if (mLocationContextMenu)
+ {
+ updateContextMenu();
+ mLocationContextMenu->buildDrawLabels();
+ mLocationContextMenu->updateParent(LLMenuGL::sMenuContainer);
+ hideList();
+ setFocus(true);
+ changeLocationPresentation();
+ LLMenuGL::showPopup(this, mLocationContextMenu, x, y);
+ }
+}
+
+void LLLocationInputCtrl::refresh()
+{
+ refreshLocation(); // update location string
+ refreshParcelIcons();
+ updateAddLandmarkButton(); // indicate whether current parcel has been landmarked
+}
+
+void LLLocationInputCtrl::refreshLocation()
+{
+ // Is one of our children focused?
+ if (LLUICtrl::hasFocus() || mButton->hasFocus() || mList->hasFocus() ||
+ (mTextEntry && mTextEntry->hasFocus()) || (mAddLandmarkBtn->hasFocus()))
+
+ {
+ llwarns << "Location input should not be refreshed when having focus" << llendl;
+ return;
+ }
+
+ // Update location field.
+ std::string location_name;
+ LLAgentUI::ELocationFormat format =
+ (gSavedSettings.getBOOL("NavBarShowCoordinates")
+ ? LLAgentUI::LOCATION_FORMAT_FULL
+ : LLAgentUI::LOCATION_FORMAT_NO_COORDS);
+
+ if (!LLAgentUI::buildLocationString(location_name, format))
+ {
+ location_name = "???";
+ }
+ // store human-readable location to compare it in changeLocationPresentation()
+ mHumanReadableLocation = location_name;
+ setText(location_name);
+}
+
+// returns new right edge
+static S32 layout_widget(LLUICtrl* widget, S32 right)
+{
+ if (widget->getVisible())
+ {
+ LLRect rect = widget->getRect();
+ rect.mLeft = right - rect.getWidth();
+ rect.mRight = right;
+ widget->setRect( rect );
+ right -= rect.getWidth();
+ }
+ return right;
+}
+
+void LLLocationInputCtrl::refreshParcelIcons()
+{
+ // Our "cursor" moving right to left
+ S32 x = mAddLandmarkBtn->getRect().mLeft;
+
+ static LLUICachedControl<bool> show_properties("NavBarShowParcelProperties", false);
+ if (show_properties)
+ {
+ LLViewerParcelMgr* vpm = LLViewerParcelMgr::getInstance();
+ bool allow_buy = vpm->canAgentBuyParcel( vpm->getAgentParcel(), false);
+ bool allow_voice = vpm->allowAgentVoice();
+ bool allow_fly = vpm->allowAgentFly();
+ bool allow_push = vpm->allowAgentPush();
+ bool allow_build = vpm->allowAgentBuild();
+ bool allow_scripts = vpm->allowAgentScripts();
+ bool allow_damage = vpm->allowAgentDamage();
+
+ // Most icons are "block this ability"
+ mForSaleBtn->setVisible(allow_buy);
+ mParcelIcon[VOICE_ICON]->setVisible( !allow_voice );
+ mParcelIcon[FLY_ICON]->setVisible( !allow_fly );
+ mParcelIcon[PUSH_ICON]->setVisible( !allow_push );
+ mParcelIcon[BUILD_ICON]->setVisible( !allow_build );
+ mParcelIcon[SCRIPTS_ICON]->setVisible( !allow_scripts );
+ mParcelIcon[DAMAGE_ICON]->setVisible( allow_damage );
+ mDamageText->setVisible(allow_damage);
+
+ x = layout_widget(mForSaleBtn, x);
+ // Padding goes to left of both landmark star and for sale btn
+ x -= mAddLandmarkHPad;
+
+ // Slide the parcel icons rect from right to left, adjusting rectangles
+ for (S32 i = 0; i < ICON_COUNT; ++i)
+ {
+ x = layout_widget(mParcelIcon[i], x);
+ x -= mIconHPad;
+ }
+ x = layout_widget(mDamageText, x);
+ x -= mIconHPad;
+ }
+ else
+ {
+ mForSaleBtn->setVisible(false);
+ for (S32 i = 0; i < ICON_COUNT; ++i)
+ {
+ mParcelIcon[i]->setVisible(false);
+ }
+ mDamageText->setVisible(false);
+ }
+
+ S32 left_pad, right_pad;
+ mTextEntry->getTextPadding(&left_pad, &right_pad);
+ right_pad = mTextEntry->getRect().mRight - x;
+ mTextEntry->setTextPadding(left_pad, right_pad);
+}
+
+void LLLocationInputCtrl::refreshHealth()
+{
+ // *FIXME: Status bar owns health information, should be in agent
+ if (gStatusBar)
+ {
+ static S32 last_health = -1;
+ S32 health = gStatusBar->getHealth();
+ if (health != last_health)
+ {
+ std::string text = llformat("%d%%", health);
+ mDamageText->setText(text);
+ last_health = health;
+ }
+ }
+}
+
+void LLLocationInputCtrl::rebuildLocationHistory(std::string filter)
+{
+ LLLocationHistory::location_list_t filtered_items;
+ const LLLocationHistory::location_list_t* itemsp = NULL;
+ LLLocationHistory* lh = LLLocationHistory::getInstance();
+
+ if (filter.empty())
+ {
+ itemsp = &lh->getItems();
+ }
+ else
+ {
+ lh->getMatchingItems(filter, filtered_items);
+ itemsp = &filtered_items;
+ }
+
+ removeall();
+ for (LLLocationHistory::location_list_t::const_reverse_iterator it = itemsp->rbegin(); it != itemsp->rend(); it++)
+ {
+ LLSD value;
+ value["tooltip"] = it->getToolTip();
+ //location history can contain only typed locations
+ value["item_type"] = TYPED_REGION_SURL;
+ value["global_pos"] = it->mGlobalPos.getValue();
+ add(it->getLocation(), value);
+ }
+}
+
+void LLLocationInputCtrl::focusTextEntry()
+{
+ // We can't use "mTextEntry->setFocus(TRUE)" instead because
+ // if the "select_on_focus" parameter is true it places the cursor
+ // at the beginning (after selecting text), thus screwing up updateSelection().
+ if (mTextEntry)
+ gFocusMgr.setKeyboardFocus(mTextEntry);
+}
+
+void LLLocationInputCtrl::enableAddLandmarkButton(bool val)
+{
+ // We don't want to disable the button because it should be click able at any time,
+ // instead switch images.
+ LLUIImage* img = val ? mLandmarkImageOn : mLandmarkImageOff;
+ if(img)
+ {
+ mAddLandmarkBtn->setImageUnselected(img);
+ }
+}
+
+// Change the "Add landmark" button image
+// depending on whether current parcel has been landmarked.
+void LLLocationInputCtrl::updateAddLandmarkButton()
+{
+ enableAddLandmarkButton(LLLandmarkActions::hasParcelLandmark());
+}
+void LLLocationInputCtrl::updateAddLandmarkTooltip()
+{
+ std::string tooltip;
+ if(LLLandmarkActions::landmarkAlreadyExists())
+ {
+ tooltip = mEditLandmarkTooltip;
+ }
+ else
+ {
+ tooltip = mAddLandmarkTooltip;
+ }
+ mAddLandmarkBtn->setToolTip(tooltip);
+}
+
+void LLLocationInputCtrl::updateContextMenu(){
+
+ if (mLocationContextMenu)
+ {
+ LLMenuItemGL* landmarkItem = mLocationContextMenu->getChild<LLMenuItemGL>("Landmark");
+ if (!LLLandmarkActions::landmarkAlreadyExists())
+ {
+ landmarkItem->setLabel(LLTrans::getString("AddLandmarkNavBarMenu"));
+ }
+ else
+ {
+ landmarkItem->setLabel(LLTrans::getString("EditLandmarkNavBarMenu"));
+ }
+ }
+}
+void LLLocationInputCtrl::updateWidgetlayout()
+{
+ const LLRect& rect = getLocalRect();
+ const LLRect& hist_btn_rect = mButton->getRect();
+
+ // Info button is set in the XUI XML location_input.xml
+
+ // "Add Landmark" button
+ LLRect al_btn_rect = mAddLandmarkBtn->getRect();
+ al_btn_rect.translate(
+ hist_btn_rect.mLeft - mIconHPad - al_btn_rect.getWidth(),
+ (rect.getHeight() - al_btn_rect.getHeight()) / 2);
+ mAddLandmarkBtn->setRect(al_btn_rect);
+}
+
+void LLLocationInputCtrl::changeLocationPresentation()
+{
+ //change location presentation only if user does not select/past anything and
+ //human-readable region name is being displayed
+ std::string text = mTextEntry->getText();
+ LLStringUtil::trim(text);
+ if(mTextEntry && !mTextEntry->hasSelection() && text == mHumanReadableLocation )
+ {
+ //needs unescaped one
+ mTextEntry->setText(LLAgentUI::buildSLURL(false));
+ mTextEntry->selectAll();
+ }
+}
+
+void LLLocationInputCtrl::onLocationContextMenuItemClicked(const LLSD& userdata)
+{
+ std::string item = userdata.asString();
+
+ if (item == "show_coordinates")
+ {
+ gSavedSettings.setBOOL("NavBarShowCoordinates",!gSavedSettings.getBOOL("NavBarShowCoordinates"));
+ }
+ else if (item == "show_properties")
+ {
+ gSavedSettings.setBOOL("NavBarShowParcelProperties",
+ !gSavedSettings.getBOOL("NavBarShowParcelProperties"));
+ refreshParcelIcons();
+ }
+ else if (item == "landmark")
+ {
+ LLViewerInventoryItem* landmark = LLLandmarkActions::findLandmarkForAgentPos();
+
+ if(!landmark)
+ {
+ LLSideTray::getInstance()->showPanel("panel_places", LLSD().with("type", "create_landmark"));
+ }
+ else
+ {
+ LLSideTray::getInstance()->showPanel("panel_places",
+ LLSD().with("type", "landmark").with("id",landmark->getUUID()));
+ }
+ }
+ else if (item == "cut")
+ {
+ mTextEntry->cut();
+ }
+ else if (item == "copy")
+ {
+ mTextEntry->copy();
+ }
+ else if (item == "paste")
+ {
+ mTextEntry->paste();
+ }
+ else if (item == "delete")
+ {
+ mTextEntry->deleteSelection();
+ }
+ else if (item == "select_all")
+ {
+ mTextEntry->selectAll();
+ }
+}
+
+bool LLLocationInputCtrl::onLocationContextMenuItemEnabled(const LLSD& userdata)
+{
+ std::string item = userdata.asString();
+
+ if (item == "can_cut")
+ {
+ return mTextEntry->canCut();
+ }
+ else if (item == "can_copy")
+ {
+ return mTextEntry->canCopy();
+ }
+ else if (item == "can_paste")
+ {
+ return mTextEntry->canPaste();
+ }
+ else if (item == "can_delete")
+ {
+ return mTextEntry->canDeselect();
+ }
+ else if (item == "can_select_all")
+ {
+ return mTextEntry->canSelectAll() && (mTextEntry->getLength() > 0);
+ }
+ else if(item == "show_coordinates")
+ {
+ return gSavedSettings.getBOOL("NavBarShowCoordinates");
+ }
+
+ return false;
+}
+
+void LLLocationInputCtrl::onParcelIconClick(EParcelIcon icon)
+{
+ switch (icon)
+ {
+ case VOICE_ICON:
+ LLNotificationsUtil::add("NoVoice");
+ break;
+ case FLY_ICON:
+ LLNotificationsUtil::add("NoFly");
+ break;
+ case PUSH_ICON:
+ LLNotificationsUtil::add("PushRestricted");
+ break;
+ case BUILD_ICON:
+ LLNotificationsUtil::add("NoBuild");
+ break;
+ case SCRIPTS_ICON:
+ {
+ LLViewerRegion* region = gAgent.getRegion();
+ if(region && region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS)
+ {
+ LLNotificationsUtil::add("ScriptsStopped");
+ }
+ else if(region && region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS)
+ {
+ LLNotificationsUtil::add("ScriptsNotRunning");
+ }
+ else
+ {
+ LLNotificationsUtil::add("NoOutsideScripts");
+ }
+ break;
+ }
+ case DAMAGE_ICON:
+ LLNotificationsUtil::add("NotSafe");
+ break;
+ case ICON_COUNT:
+ break;
+ // no default to get compiler warning when a new icon gets added
+ }
+}
diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h
new file mode 100644
index 0000000000..607ccd4da6
--- /dev/null
+++ b/indra/newview/lllocationinputctrl.h
@@ -0,0 +1,179 @@
+/**
+ * @file lllocationinputctrl.h
+ * @brief Combobox-like location input control
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLLOCATIONINPUTCTRL_H
+#define LL_LLLOCATIONINPUTCTRL_H
+
+#include "llcombobox.h"
+#include "lliconctrl.h" // Params
+#include "lltextbox.h" // Params
+
+class LLLandmark;
+
+// internals
+class LLAddLandmarkObserver;
+class LLRemoveLandmarkObserver;
+class LLMenuGL;
+class LLTeleportHistoryItem;
+
+/**
+ * Location input control.
+ *
+ * @see LLNavigationBar
+ */
+class LLLocationInputCtrl
+: public LLComboBox
+{
+ LOG_CLASS(LLLocationInputCtrl);
+ friend class LLAddLandmarkObserver;
+ friend class LLRemoveLandmarkObserver;
+
+public:
+ struct Params
+ : public LLInitParam::Block<Params, LLComboBox::Params>
+ {
+ Optional<LLUIImage*> add_landmark_image_enabled,
+ add_landmark_image_disabled,
+ add_landmark_image_hover,
+ add_landmark_image_selected;
+ Optional<S32> icon_hpad,
+ add_landmark_hpad;
+ Optional<LLButton::Params> add_landmark_button,
+ for_sale_button,
+ info_button;
+ Optional<LLIconCtrl::Params> voice_icon,
+ fly_icon,
+ push_icon,
+ build_icon,
+ scripts_icon,
+ damage_icon;
+ Optional<LLTextBox::Params> damage_text;
+ Params();
+ };
+
+ // LLView interface
+ /*virtual*/ void setEnabled(BOOL enabled);
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
+ /*virtual*/ void onFocusReceived();
+ /*virtual*/ void onFocusLost();
+ /*virtual*/ void draw();
+ //========================================================================
+
+ // LLUICtrl interface
+ /*virtual*/ void setFocus(BOOL b);
+ //========================================================================
+
+ // LLComboBox interface
+ void hideList();
+ void onTextEntry(LLLineEditor* line_editor);
+ //========================================================================
+
+ LLLineEditor* getTextEntry() const { return mTextEntry; }
+ void handleLoginComplete();
+
+private:
+
+ enum EParcelIcon
+ {
+ VOICE_ICON = 0,
+ FLY_ICON,
+ PUSH_ICON,
+ BUILD_ICON,
+ SCRIPTS_ICON,
+ DAMAGE_ICON,
+ ICON_COUNT
+ };
+
+ friend class LLUICtrlFactory;
+ LLLocationInputCtrl(const Params&);
+ virtual ~LLLocationInputCtrl();
+
+ void focusTextEntry();
+ /**
+ * Changes the "Add landmark" button image
+ * depending on whether current parcel has been landmarked.
+ */
+ void enableAddLandmarkButton(bool val);
+ void refresh();
+ void refreshLocation();
+ void refreshParcelIcons();
+ // Refresh the value in the health percentage text field
+ void refreshHealth();
+
+ void rebuildLocationHistory(std::string filter = "");
+ bool findTeleportItemsByTitle(const LLTeleportHistoryItem& item, const std::string& filter);
+ void setText(const LLStringExplicit& text);
+ void updateAddLandmarkButton();
+ void updateAddLandmarkTooltip();
+ void updateContextMenu();
+ void updateWidgetlayout();
+ void changeLocationPresentation();
+
+ void onInfoButtonClicked();
+ void onLocationHistoryLoaded();
+ void onLocationPrearrange(const LLSD& data);
+ void onTextEditorRightClicked(S32 x, S32 y, MASK mask);
+ void onLandmarkLoaded(LLLandmark* lm);
+ void onForSaleButtonClicked();
+ void onAddLandmarkButtonClicked();
+ void onAgentParcelChange();
+ // callbacks
+ bool onLocationContextMenuItemEnabled(const LLSD& userdata);
+ void onLocationContextMenuItemClicked(const LLSD& userdata);
+ void onParcelIconClick(EParcelIcon icon);
+
+ LLMenuGL* mLocationContextMenu;
+ LLButton* mAddLandmarkBtn;
+ LLButton* mForSaleBtn;
+ LLButton* mInfoBtn;
+ S32 mIconHPad; // pad between all icons
+ S32 mAddLandmarkHPad; // pad to left of landmark star
+
+ LLIconCtrl* mParcelIcon[ICON_COUNT];
+ LLTextBox* mDamageText;
+
+ LLAddLandmarkObserver* mAddLandmarkObserver;
+ LLRemoveLandmarkObserver* mRemoveLandmarkObserver;
+
+ boost::signals2::connection mParcelMgrConnection;
+ boost::signals2::connection mLocationHistoryConnection;
+ LLUIImage* mLandmarkImageOn;
+ LLUIImage* mLandmarkImageOff;
+
+ std::string mAddLandmarkTooltip;
+ std::string mEditLandmarkTooltip;
+ // this field holds a human-readable form of the location string, it is needed to be able to compare copy-pated value and real location
+ std::string mHumanReadableLocation;
+};
+
+#endif
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 1709d6465d..dc187bf36c 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -32,12 +32,57 @@
#include "llviewerprecompiledheaders.h"
+#include "llagent.h"
+#include "llagentui.h"
#include "lllogchat.h"
-#include "llappviewer.h"
-#include "llfloaterchat.h"
+#include "lltrans.h"
+#include "llviewercontrol.h"
+
+#include "llinstantmessage.h"
+
+#include <boost/algorithm/string/trim.hpp>
+#include <boost/algorithm/string/replace.hpp>
+#include <boost/regex.hpp>
+#include <boost/regex/v4/match_results.hpp>
const S32 LOG_RECALL_SIZE = 2048;
+const static std::string IM_TIME("time");
+const static std::string IM_TEXT("message");
+const static std::string IM_FROM("from");
+const static std::string IM_FROM_ID("from_id");
+const static std::string IM_SEPARATOR(": ");
+
+const static std::string NEW_LINE("\n");
+const static std::string NEW_LINE_SPACE_PREFIX("\n ");
+const static std::string TWO_SPACES(" ");
+const static std::string MULTI_LINE_PREFIX(" ");
+
+/**
+ * Chat log lines - timestamp and name are optional but message text is mandatory.
+ *
+ * Typical plain text chat log lines:
+ *
+ * SuperCar: You aren't the owner
+ * [2:59] SuperCar: You aren't the owner
+ * [2009/11/20 3:00] SuperCar: You aren't the owner
+ * Katar Ivercourt is Offline
+ * [3:00] Katar Ivercourt is Offline
+ * [2009/11/20 3:01] Corba ProductEngine is Offline
+ */
+const static boost::regex TIMESTAMP_AND_STUFF("^(\\[\\d{4}/\\d{1,2}/\\d{1,2}\\s+\\d{1,2}:\\d{2}\\]\\s+|\\[\\d{1,2}:\\d{2}\\]\\s+)?(.*)$");
+
+/**
+ * Regular expression suitable to match names like
+ * "You", "Second Life", "Igor ProductEngine", "Object", "Mega House"
+ */
+const static boost::regex NAME_AND_TEXT("(You:|Second Life:|[^\\s:]+\\s*[:]{1}|\\S+\\s+[^\\s:]+[:]{1})?(\\s*)(.*)");
+
+const static int IDX_TIMESTAMP = 1;
+const static int IDX_STUFF = 2;
+const static int IDX_NAME = 1;
+const static int IDX_TEXT = 3;
+
//static
std::string LLLogChat::makeLogFileName(std::string filename)
{
@@ -64,25 +109,34 @@ std::string LLLogChat::timestamp(bool withdate)
time_t utc_time;
utc_time = time_corrected();
- // There's only one internal tm buffer.
- struct tm* timep;
+ std::string timeStr;
+ LLSD substitution;
+ substitution["datetime"] = (S32) utc_time;
- // Convert to Pacific, based on server's opinion of whether
- // it's daylight savings time there.
- timep = utc_to_pacific_time(utc_time, gPacificDaylightTime);
-
- std::string text;
if (withdate)
- text = llformat("[%d/%02d/%02d %d:%02d] ", (timep->tm_year-100)+2000, timep->tm_mon+1, timep->tm_mday, timep->tm_hour, timep->tm_min);
+ {
+ timeStr = "["+LLTrans::getString ("TimeYear")+"]/["
+ +LLTrans::getString ("TimeMonth")+"]/["
+ +LLTrans::getString ("TimeDay")+"] ["
+ +LLTrans::getString ("TimeHour")+"]:["
+ +LLTrans::getString ("TimeMin")+"]";
+ }
else
- text = llformat("[%d:%02d] ", timep->tm_hour, timep->tm_min);
+ {
+ timeStr = "[" + LLTrans::getString("TimeHour") + "]:["
+ + LLTrans::getString ("TimeMin")+"]";
+ }
- return text;
+ LLStringUtil::format (timeStr, substitution);
+ return timeStr;
}
//static
-void LLLogChat::saveHistory(std::string filename, std::string line)
+void LLLogChat::saveHistory(const std::string& filename,
+ const std::string& from,
+ const LLUUID& from_id,
+ const std::string& line)
{
if(!filename.size())
{
@@ -90,33 +144,39 @@ void LLLogChat::saveHistory(std::string filename, std::string line)
return;
}
- LLFILE* fp = LLFile::fopen(LLLogChat::makeLogFileName(filename), "a"); /*Flawfinder: ignore*/
- if (!fp)
+ llofstream file (LLLogChat::makeLogFileName(filename), std::ios_base::app);
+ if (!file.is_open())
{
llinfos << "Couldn't open chat history log!" << llendl;
+ return;
}
- else
- {
- fprintf(fp, "%s\n", line.c_str());
-
- fclose (fp);
- }
+
+ LLSD item;
+
+ if (gSavedPerAccountSettings.getBOOL("LogTimestamp"))
+ item["time"] = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate"));
+
+ item["from"] = from;
+ item["from_id"] = from_id;
+ item["message"] = line;
+
+ file << LLChatLogFormatter(item) << std::endl;
+
+ file.close();
}
-void LLLogChat::loadHistory(std::string filename , void (*callback)(ELogLineType,std::string,void*), void* userdata)
+void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLineType, const LLSD&, void*), void* userdata)
{
if(!filename.size())
{
llwarns << "Filename is Empty!" << llendl;
return ;
}
-
+
LLFILE* fptr = LLFile::fopen(makeLogFileName(filename), "r"); /*Flawfinder: ignore*/
if (!fptr)
{
- //LLUIString message = LLFloaterChat::getInstance()->getString("IM_logging_string");
- //callback(LOG_EMPTY,"IM_logging_string",userdata);
- callback(LOG_EMPTY,LLStringUtil::null,userdata);
+ callback(LOG_EMPTY, LLSD(), userdata);
return; //No previous conversation with this name.
}
else
@@ -143,15 +203,221 @@ void LLLogChat::loadHistory(std::string filename , void (*callback)(ELogLineType
if (!firstline)
{
- callback(LOG_LINE,std::string(buffer),userdata);
+ LLSD item;
+ std::string line(buffer);
+ std::istringstream iss(line);
+
+ if (!LLChatLogParser::parse(line, item))
+ {
+ item["message"] = line;
+ callback(LOG_LINE, item, userdata);
+ }
+ else
+ {
+ callback(LOG_LLSD, item, userdata);
+ }
}
else
{
firstline = FALSE;
}
}
- callback(LOG_END,LLStringUtil::null,userdata);
+ callback(LOG_END, LLSD(), userdata);
fclose(fptr);
}
}
+
+void append_to_last_message(std::list<LLSD>& messages, const std::string& line)
+{
+ if (!messages.size()) return;
+
+ std::string im_text = messages.back()[IM_TEXT].asString();
+ im_text.append(line);
+ messages.back()[IM_TEXT] = im_text;
+}
+
+void LLLogChat::loadAllHistory(const std::string& file_name, std::list<LLSD>& messages)
+{
+ if (file_name.empty())
+ {
+ llwarns << "Session name is Empty!" << llendl;
+ return ;
+ }
+
+ LLFILE* fptr = LLFile::fopen(makeLogFileName(file_name), "r"); /*Flawfinder: ignore*/
+ if (!fptr) return; //No previous conversation with this name.
+
+ char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/
+ char *bptr;
+ S32 len;
+ bool firstline = TRUE;
+
+ if (fseek(fptr, (LOG_RECALL_SIZE - 1) * -1 , SEEK_END))
+ { //File is smaller than recall size. Get it all.
+ firstline = FALSE;
+ if (fseek(fptr, 0, SEEK_SET))
+ {
+ fclose(fptr);
+ return;
+ }
+ }
+
+ while (fgets(buffer, LOG_RECALL_SIZE, fptr) && !feof(fptr))
+ {
+ len = strlen(buffer) - 1; /*Flawfinder: ignore*/
+ for (bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--) *bptr='\0';
+
+ if (firstline)
+ {
+ firstline = FALSE;
+ continue;
+ }
+
+ std::string line(buffer);
+
+ //updated 1.23 plaint text log format requires a space added before subsequent lines in a multilined message
+ if (' ' == line[0])
+ {
+ line.erase(0, MULTI_LINE_PREFIX.length());
+ append_to_last_message(messages, '\n' + line);
+ }
+ else if (0 == len && ('\n' == line[0] || '\r' == line[0]))
+ {
+ //to support old format's multilined messages with new lines used to divide paragraphs
+ append_to_last_message(messages, line);
+ }
+ else
+ {
+ LLSD item;
+ if (!LLChatLogParser::parse(line, item))
+ {
+ item[IM_TEXT] = line;
+ }
+ messages.push_back(item);
+ }
+ }
+ fclose(fptr);
+}
+
+//*TODO mark object's names in a special way so that they will be distinguishable form avatar name
+//which are more strict by its nature (only firstname and secondname)
+//Example, an object's name can be writen like "Object <actual_object's_name>"
+void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const
+{
+ if (!im.isMap())
+ {
+ llwarning("invalid LLSD type of an instant message", 0);
+ return;
+ }
+
+ if (im[IM_TIME].isDefined())
+ {
+ std::string timestamp = im[IM_TIME].asString();
+ boost::trim(timestamp);
+ ostr << '[' << timestamp << ']' << TWO_SPACES;
+ }
+
+ //*TODO mark object's names in a special way so that they will be distinguishable form avatar name
+ //which are more strict by its nature (only firstname and secondname)
+ //Example, an object's name can be writen like "Object <actual_object's_name>"
+ if (im[IM_FROM].isDefined())
+ {
+ std::string from = im[IM_FROM].asString();
+ boost::trim(from);
+ if (from.size())
+ {
+ ostr << from << IM_SEPARATOR;
+ }
+ }
+
+ if (im[IM_TEXT].isDefined())
+ {
+ std::string im_text = im[IM_TEXT].asString();
+
+ //multilined text will be saved with prepended spaces
+ boost::replace_all(im_text, NEW_LINE, NEW_LINE_SPACE_PREFIX);
+ ostr << im_text;
+ }
+}
+
+bool LLChatLogParser::parse(std::string& raw, LLSD& im)
+{
+ if (!raw.length()) return false;
+
+ im = LLSD::emptyMap();
+
+ //matching a timestamp
+ boost::match_results<std::string::const_iterator> matches;
+ if (!boost::regex_match(raw, matches, TIMESTAMP_AND_STUFF)) return false;
+
+ bool has_timestamp = matches[IDX_TIMESTAMP].matched;
+ if (has_timestamp)
+ {
+ //timestamp was successfully parsed
+ std::string timestamp = matches[IDX_TIMESTAMP];
+ boost::trim(timestamp);
+ timestamp.erase(0, 1);
+ timestamp.erase(timestamp.length()-1, 1);
+ im[IM_TIME] = timestamp;
+ }
+ else
+ {
+ //timestamp is optional
+ im[IM_TIME] = "";
+ }
+
+ bool has_stuff = matches[IDX_STUFF].matched;
+ if (!has_stuff)
+ {
+ return false; //*TODO should return false or not?
+ }
+
+ //matching a name and a text
+ std::string stuff = matches[IDX_STUFF];
+ boost::match_results<std::string::const_iterator> name_and_text;
+ if (!boost::regex_match(stuff, name_and_text, NAME_AND_TEXT)) return false;
+
+ bool has_name = name_and_text[IDX_NAME].matched;
+ std::string name = name_and_text[IDX_NAME];
+
+ //we don't need a name/text separator
+ if (has_name && name.length() && name[name.length()-1] == ':')
+ {
+ name.erase(name.length()-1, 1);
+ }
+
+ if (!has_name || name == SYSTEM_FROM)
+ {
+ //name is optional too
+ im[IM_FROM] = SYSTEM_FROM;
+ im[IM_FROM_ID] = LLUUID::null;
+ }
+
+ if (!has_name)
+ {
+ //text is mandatory
+ im[IM_TEXT] = stuff;
+ return true; //parse as a message from Second Life
+ }
+
+ bool has_text = name_and_text[IDX_TEXT].matched;
+ if (!has_text) return false;
+
+ //for parsing logs created in very old versions of a viewer
+ if (name == "You")
+ {
+ std::string agent_name;
+ LLAgentUI::buildFullname(agent_name);
+ im[IM_FROM] = agent_name;
+ im[IM_FROM_ID] = gAgentID;
+ }
+ else
+ {
+ im[IM_FROM] = name;
+ }
+
+
+ im[IM_TEXT] = name_and_text[IDX_TEXT];
+ return true; //parsed name and message text, maybe have a timestamp too
+}
diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h
index ad903b66fe..4290e4bbc0 100644
--- a/indra/newview/lllogchat.h
+++ b/indra/newview/lllogchat.h
@@ -41,16 +41,76 @@ public:
enum ELogLineType {
LOG_EMPTY,
LOG_LINE,
+ LOG_LLSD,
LOG_END
};
static std::string timestamp(bool withdate = false);
static std::string makeLogFileName(std::string(filename));
- static void saveHistory(std::string filename, std::string line);
- static void loadHistory(std::string filename,
- void (*callback)(ELogLineType,std::string,void*),
+ static void saveHistory(const std::string& filename,
+ const std::string& from,
+ const LLUUID& from_id,
+ const std::string& line);
+
+ /** @deprecated @see loadAllHistory() */
+ static void loadHistory(const std::string& filename,
+ void (*callback)(ELogLineType, const LLSD&, void*),
void* userdata);
+
+ static void loadAllHistory(const std::string& file_name, std::list<LLSD>& messages);
private:
static std::string cleanFileName(std::string filename);
};
+/**
+ * Formatter for the plain text chat log files
+ */
+class LLChatLogFormatter
+{
+public:
+ LLChatLogFormatter(const LLSD& im) : mIM(im) {}
+ virtual ~LLChatLogFormatter() {};
+
+ friend std::ostream& operator<<(std::ostream& str, const LLChatLogFormatter& formatter)
+ {
+ formatter.format(formatter.mIM, str);
+ return str;
+ }
+
+protected:
+
+ /**
+ * Format an instant message to a stream
+ * Timestamps and sender names are required
+ * New lines of multilined messages are prepended with a space
+ */
+ void format(const LLSD& im, std::ostream& ostr) const;
+
+ LLSD mIM;
+};
+
+/**
+ * Parser for the plain text chat log files
+ */
+class LLChatLogParser
+{
+public:
+
+ /**
+ * Parse a line from the plain text chat log file
+ * General plain text log format is like: "[timestamp] [name]: [message]"
+ * [timestamp] and [name] are optional
+ * Examples of plain text chat log lines:
+ * "[2009/11/20 2:53] Igor ProductEngine: howdy"
+ * "Igor ProductEngine: howdy"
+ * "Dserduk ProductEngine is Online"
+ *
+ * @return false if failed to parse mandatory data - message text
+ */
+ static bool parse(std::string& raw, LLSD& im);
+
+protected:
+ LLChatLogParser();
+ virtual ~LLChatLogParser() {};
+};
+
#endif
diff --git a/indra/newview/llloginhandler.cpp b/indra/newview/llloginhandler.cpp
index 053f798882..1be3430e07 100644
--- a/indra/newview/llloginhandler.cpp
+++ b/indra/newview/llloginhandler.cpp
@@ -40,9 +40,12 @@
#include "llurlsimstring.h"
#include "llviewercontrol.h" // gSavedSettings
#include "llviewernetwork.h" // EGridInfo
+#include "llviewerwindow.h" // getWindow()
// library includes
#include "llmd5.h"
+#include "llweb.h"
+#include "llwindow.h"
// Must have instance to auto-register with LLCommandDispatcher
@@ -56,7 +59,7 @@ bool LLLoginHandler::parseDirectLogin(std::string url)
LLURI uri(url);
parse(uri.queryMap());
- if (mWebLoginKey.isNull() ||
+ if (/*mWebLoginKey.isNull() ||*/
mFirstName.empty() ||
mLastName.empty())
{
@@ -71,7 +74,7 @@ bool LLLoginHandler::parseDirectLogin(std::string url)
void LLLoginHandler::parse(const LLSD& queryMap)
{
- mWebLoginKey = queryMap["web_login_key"].asUUID();
+ //mWebLoginKey = queryMap["web_login_key"].asUUID();
mFirstName = queryMap["first_name"].asString();
mLastName = queryMap["last_name"].asString();
@@ -156,22 +159,50 @@ void LLLoginHandler::parse(const LLSD& queryMap)
{
LLURLSimString::setString(queryMap["region"].asString());
}
- else if (startLocation == "home")
+ else if (!startLocation.empty()) // "last" or "home" or ??? (let LLURLSimString figure it out)
{
- gSavedSettings.setBOOL("LoginLastLocation", FALSE);
- LLURLSimString::setString(LLStringUtil::null);
- }
- else if (startLocation == "last")
- {
- gSavedSettings.setBOOL("LoginLastLocation", TRUE);
- LLURLSimString::setString(LLStringUtil::null);
+ LLURLSimString::setString(startLocation);
}
}
bool LLLoginHandler::handle(const LLSD& tokens,
const LLSD& query_map,
- LLWebBrowserCtrl* web)
-{
+ LLMediaCtrl* web)
+{
+ if (tokens.size() == 1
+ && tokens[0].asString() == "show")
+ {
+ // We're using reg-in-client, so show the XUI login widgets
+ LLPanelLogin::showLoginWidgets();
+ return true;
+ }
+
+ if (tokens.size() == 1
+ && tokens[0].asString() == "reg")
+ {
+ LLWindow* window = gViewerWindow->getWindow();
+ window->incBusyCount();
+ window->setCursor(UI_CURSOR_ARROW);
+
+ // Do this first, as it may be slow and we want to keep something
+ // on the user's screen as long as possible
+ LLWeb::loadURLExternal( "http://join.eniac15.lindenlab.com/" );
+
+ window->decBusyCount();
+ window->setCursor(UI_CURSOR_ARROW);
+
+ // Then hide the window
+ window->minimize();
+ return true;
+ }
+
+ // Make sure window is visible
+ LLWindow* window = gViewerWindow->getWindow();
+ if (window->getMinimized())
+ {
+ window->restore();
+ }
+
parse(query_map);
//if we haven't initialized stuff yet, this is
@@ -206,14 +237,15 @@ bool LLLoginHandler::handle(const LLSD& tokens,
LLPanelLogin::setFields(mFirstName, mLastName, password);
}
- if (mWebLoginKey.isNull())
- {
- LLPanelLogin::loadLoginPage();
- }
- else
- {
- LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );
- }
+ //if (mWebLoginKey.isNull())
+ //{
+ // LLPanelLogin::loadLoginPage();
+ //}
+ //else
+ //{
+ // LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );
+ //}
+ LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );
}
return true;
}
diff --git a/indra/newview/llloginhandler.h b/indra/newview/llloginhandler.h
index c76d7e8274..ac4648761b 100644
--- a/indra/newview/llloginhandler.h
+++ b/indra/newview/llloginhandler.h
@@ -39,8 +39,8 @@ class LLLoginHandler : public LLCommandHandler
{
public:
// allow from external browsers
- LLLoginHandler() : LLCommandHandler("login", false) { }
- /*virtual*/ bool handle(const LLSD& tokens, const LLSD& query_map, LLWebBrowserCtrl* web);
+ LLLoginHandler() : LLCommandHandler("login", UNTRUSTED_ALLOW) { }
+ /*virtual*/ bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web);
// Fill in our internal fields from a SLURL like
// secondlife:///app/login?first=Bob&last=Dobbs
@@ -48,7 +48,9 @@ class LLLoginHandler : public LLCommandHandler
std::string getFirstName() const { return mFirstName; }
std::string getLastName() const { return mLastName; }
- LLUUID getWebLoginKey() const { return mWebLoginKey; }
+
+ // Web-based login unsupported
+ //LLUUID getWebLoginKey() const { return mWebLoginKey; }
private:
void parse(const LLSD& queryMap);
@@ -56,7 +58,7 @@ private:
private:
std::string mFirstName;
std::string mLastName;
- LLUUID mWebLoginKey;
+ //LLUUID mWebLoginKey;
};
extern LLLoginHandler gLoginHandler;
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
new file mode 100644
index 0000000000..24c72c65ce
--- /dev/null
+++ b/indra/newview/lllogininstance.cpp
@@ -0,0 +1,474 @@
+/**
+ * @file lllogininstance.cpp
+ * @brief Viewer's host for a login connection.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lllogininstance.h"
+
+// llcommon
+#include "llevents.h"
+#include "llmd5.h"
+#include "stringize.h"
+
+// llmessage (!)
+#include "llfiltersd2xmlrpc.h" // for xml_escape_string()
+
+// login
+#include "lllogin.h"
+
+// newview
+#include "llviewernetwork.h"
+#include "llviewercontrol.h"
+#include "llurlsimstring.h"
+#include "llfloaterreg.h"
+#include "llnotifications.h"
+#include "llwindow.h"
+#if LL_LINUX || LL_SOLARIS
+#include "lltrans.h"
+#endif
+
+static const char * const TOS_REPLY_PUMP = "lllogininstance_tos_callback";
+static const char * const TOS_LISTENER_NAME = "lllogininstance_tos";
+
+std::string construct_start_string();
+
+LLLoginInstance::LLLoginInstance() :
+ mLoginModule(new LLLogin()),
+ mNotifications(NULL),
+ mLoginState("offline"),
+ mUserInteraction(true),
+ mSkipOptionalUpdate(false),
+ mAttemptComplete(false),
+ mTransferRate(0.0f),
+ mDispatcher("LLLoginInstance", "change")
+{
+ mLoginModule->getEventPump().listen("lllogininstance",
+ boost::bind(&LLLoginInstance::handleLoginEvent, this, _1));
+ mDispatcher.add("fail.login", boost::bind(&LLLoginInstance::handleLoginFailure, this, _1));
+ mDispatcher.add("connect", boost::bind(&LLLoginInstance::handleLoginSuccess, this, _1));
+ mDispatcher.add("disconnect", boost::bind(&LLLoginInstance::handleDisconnect, this, _1));
+ mDispatcher.add("indeterminate", boost::bind(&LLLoginInstance::handleIndeterminate, this, _1));
+}
+
+LLLoginInstance::~LLLoginInstance()
+{
+}
+
+void LLLoginInstance::connect(const LLSD& credentials)
+{
+ std::vector<std::string> uris;
+ LLViewerLogin::getInstance()->getLoginURIs(uris);
+ connect(uris.front(), credentials);
+}
+
+void LLLoginInstance::connect(const std::string& uri, const LLSD& credentials)
+{
+ mAttemptComplete = false; // Reset attempt complete at this point!
+ constructAuthParams(credentials);
+ mLoginModule->connect(uri, mRequestData);
+}
+
+void LLLoginInstance::reconnect()
+{
+ // Sort of like connect, only using the pre-existing
+ // request params.
+ std::vector<std::string> uris;
+ LLViewerLogin::getInstance()->getLoginURIs(uris);
+ mLoginModule->connect(uris.front(), mRequestData);
+}
+
+void LLLoginInstance::disconnect()
+{
+ mAttemptComplete = false; // Reset attempt complete at this point!
+ mRequestData.clear();
+ mLoginModule->disconnect();
+}
+
+LLSD LLLoginInstance::getResponse()
+{
+ return mResponseData;
+}
+
+void LLLoginInstance::constructAuthParams(const LLSD& credentials)
+{
+ // Set up auth request options.
+//#define LL_MINIMIAL_REQUESTED_OPTIONS
+ LLSD requested_options;
+ // *Note: this is where gUserAuth used to be created.
+ requested_options.append("inventory-root");
+ requested_options.append("inventory-skeleton");
+ //requested_options.append("inventory-meat");
+ //requested_options.append("inventory-skel-targets");
+#if (!defined LL_MINIMIAL_REQUESTED_OPTIONS)
+ if(FALSE == gSavedSettings.getBOOL("NoInventoryLibrary"))
+ {
+ requested_options.append("inventory-lib-root");
+ requested_options.append("inventory-lib-owner");
+ requested_options.append("inventory-skel-lib");
+ // requested_options.append("inventory-meat-lib");
+ }
+
+ requested_options.append("initial-outfit");
+ requested_options.append("gestures");
+ requested_options.append("event_categories");
+ requested_options.append("event_notifications");
+ requested_options.append("classified_categories");
+ requested_options.append("adult_compliant");
+ //requested_options.append("inventory-targets");
+ requested_options.append("buddy-list");
+ requested_options.append("ui-config");
+#endif
+ requested_options.append("tutorial_setting");
+ requested_options.append("login-flags");
+ requested_options.append("global-textures");
+ if(gSavedSettings.getBOOL("ConnectAsGod"))
+ {
+ gSavedSettings.setBOOL("UseDebugMenus", TRUE);
+ requested_options.append("god-connect");
+ }
+
+ char hashed_mac_string[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
+ LLMD5 hashed_mac;
+ hashed_mac.update( gMACAddress, MAC_ADDRESS_BYTES );
+ hashed_mac.finalize();
+ hashed_mac.hex_digest(hashed_mac_string);
+
+ // prepend "$1$" to the password to indicate its the md5'd version.
+ std::string dpasswd("$1$");
+ dpasswd.append(credentials["passwd"].asString());
+
+ // (re)initialize the request params with creds.
+ LLSD request_params(credentials);
+ request_params["passwd"] = dpasswd;
+ request_params["start"] = construct_start_string();
+ request_params["skipoptional"] = mSkipOptionalUpdate;
+ request_params["agree_to_tos"] = false; // Always false here. Set true in
+ request_params["read_critical"] = false; // handleTOSResponse
+ request_params["last_exec_event"] = mLastExecEvent;
+ request_params["mac"] = hashed_mac_string;
+ request_params["version"] = gCurrentVersion; // Includes channel name
+ request_params["channel"] = gSavedSettings.getString("VersionChannelName");
+ request_params["id0"] = mSerialNumber;
+
+ mRequestData.clear();
+ mRequestData["method"] = "login_to_simulator";
+ mRequestData["params"] = request_params;
+ mRequestData["options"] = requested_options;
+
+ mRequestData["cfg_srv_timeout"] = gSavedSettings.getF32("LoginSRVTimeout");
+ mRequestData["cfg_srv_pump"] = gSavedSettings.getString("LoginSRVPump");
+}
+
+bool LLLoginInstance::handleLoginEvent(const LLSD& event)
+{
+ LL_DEBUGS("LLLogin") << "LoginListener called!: \n" << event << LL_ENDL;
+
+ if(!(event.has("state") && event.has("change") && event.has("progress")))
+ {
+ llerrs << "Unknown message from LLLogin: " << event << llendl;
+ }
+
+ mLoginState = event["state"].asString();
+ mResponseData = event["data"];
+
+ if(event.has("transfer_rate"))
+ {
+ mTransferRate = event["transfer_rate"].asReal();
+ }
+
+
+
+ // Call the method registered in constructor, if any, for more specific
+ // handling
+ LLEventDispatcher::Callable method(mDispatcher.get(event["change"]));
+ if (! method.empty())
+ {
+ method(event);
+ }
+ return false;
+}
+
+void LLLoginInstance::handleLoginFailure(const LLSD& event)
+{
+ // Login has failed.
+ // Figure out why and respond...
+ LLSD response = event["data"];
+ std::string reason_response = response["reason"].asString();
+ std::string message_response = response["message"].asString();
+ if(mUserInteraction)
+ {
+ // For the cases of critical message or TOS agreement,
+ // start the TOS dialog. The dialog response will be handled
+ // by the LLLoginInstance::handleTOSResponse() callback.
+ // The callback intiates the login attempt next step, either
+ // to reconnect or to end the attempt in failure.
+ if(reason_response == "tos")
+ {
+ LLSD data(LLSD::emptyMap());
+ data["message"] = message_response;
+ data["reply_pump"] = TOS_REPLY_PUMP;
+ LLFloaterReg::showInstance("message_tos", data);
+ LLEventPumps::instance().obtain(TOS_REPLY_PUMP)
+ .listen(TOS_LISTENER_NAME,
+ boost::bind(&LLLoginInstance::handleTOSResponse,
+ this, _1, "agree_to_tos"));
+ }
+ else if(reason_response == "critical")
+ {
+ LLSD data(LLSD::emptyMap());
+ data["message"] = message_response;
+ data["reply_pump"] = TOS_REPLY_PUMP;
+ LLFloaterReg::showInstance("message_critical", data);
+ LLEventPumps::instance().obtain(TOS_REPLY_PUMP)
+ .listen(TOS_LISTENER_NAME,
+ boost::bind(&LLLoginInstance::handleTOSResponse,
+ this, _1, "read_critical"));
+ }
+ else if(reason_response == "update" || gSavedSettings.getBOOL("ForceMandatoryUpdate"))
+ {
+ gSavedSettings.setBOOL("ForceMandatoryUpdate", FALSE);
+ updateApp(true, message_response);
+ }
+ else if(reason_response == "optional")
+ {
+ updateApp(false, message_response);
+ }
+ else
+ {
+ attemptComplete();
+ }
+ }
+ else // no user interaction
+ {
+ attemptComplete();
+ }
+}
+
+void LLLoginInstance::handleLoginSuccess(const LLSD& event)
+{
+ if(gSavedSettings.getBOOL("ForceMandatoryUpdate"))
+ {
+ LLSD response = event["data"];
+ std::string message_response = response["message"].asString();
+
+ // Testing update...
+ gSavedSettings.setBOOL("ForceMandatoryUpdate", FALSE);
+
+ // Don't confuse startup by leaving login "online".
+ mLoginModule->disconnect();
+ updateApp(true, message_response);
+ }
+ else
+ {
+ attemptComplete();
+ }
+}
+
+void LLLoginInstance::handleDisconnect(const LLSD& event)
+{
+ // placeholder
+}
+
+void LLLoginInstance::handleIndeterminate(const LLSD& event)
+{
+ // The indeterminate response means that the server
+ // gave the viewer a new url and params to try.
+ // The login module handles the retry, but it gives us the
+ // server response so that we may show
+ // the user some status.
+ LLSD message = event.get("data").get("message");
+ if(message.isDefined())
+ {
+ LLSD progress_update;
+ progress_update["desc"] = message;
+ LLEventPumps::getInstance()->obtain("LLProgressView").post(progress_update);
+ }
+}
+
+bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key)
+{
+ if(accepted)
+ {
+ // Set the request data to true and retry login.
+ mRequestData["params"][key] = true;
+ reconnect();
+ }
+ else
+ {
+ attemptComplete();
+ }
+
+ LLEventPumps::instance().obtain(TOS_REPLY_PUMP).stopListening(TOS_LISTENER_NAME);
+ return true;
+}
+
+
+void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg)
+{
+ // store off config state, as we might quit soon
+ gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
+ LLUIColorTable::instance().saveUserSettings();
+
+ std::ostringstream message;
+ std::string msg;
+ if (!auth_msg.empty())
+ {
+ msg = "(" + auth_msg + ") \n";
+ }
+
+ LLSD args;
+ args["MESSAGE"] = msg;
+
+ LLSD payload;
+ payload["mandatory"] = mandatory;
+
+/*
+ We're constructing one of the following 6 strings here:
+ "DownloadWindowsMandatory"
+ "DownloadWindowsReleaseForDownload"
+ "DownloadWindows"
+ "DownloadMacMandatory"
+ "DownloadMacReleaseForDownload"
+ "DownloadMac"
+
+ I've called them out explicitly in this comment so that they can be grepped for.
+
+ Also, we assume that if we're not Windows we're Mac. If we ever intend to support
+ Linux with autoupdate, this should be an explicit #elif LL_DARWIN, but
+ we'd rather deliver the wrong message than no message, so until Linux is supported
+ we'll leave it alone.
+ */
+ std::string notification_name = "Download";
+
+#if LL_WINDOWS
+ notification_name += "Windows";
+#elif LL_DARWIN
+ notification_name += "Mac";
+#else
+ notification_name += "Linux";
+#endif
+
+ if (mandatory)
+ {
+ notification_name += "Mandatory";
+ }
+ else
+ {
+#if LL_RELEASE_FOR_DOWNLOAD
+ notification_name += "ReleaseForDownload";
+#endif
+ }
+
+ if(mNotifications)
+ {
+ mNotifications->add(notification_name, args, payload,
+ boost::bind(&LLLoginInstance::updateDialogCallback, this, _1, _2));
+ }
+}
+
+bool LLLoginInstance::updateDialogCallback(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ std::string update_exe_path;
+ bool mandatory = notification["payload"]["mandatory"].asBoolean();
+
+#if !LL_RELEASE_FOR_DOWNLOAD
+ if (option == 2)
+ {
+ // This condition attempts to skip the
+ // update if using a dev build.
+ // The relog probably won't work if the
+ // update is mandatory. :)
+
+ // *REMOVE:Mani - Saving for reference...
+ //LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT );
+ mSkipOptionalUpdate = true;
+ reconnect();
+ return false;
+ }
+#endif
+
+ if (option == 1)
+ {
+ // ...user doesn't want to do it
+ if (mandatory)
+ {
+ // Mandatory update, user chose to not to update...
+ // The login attemp is complete, startup should
+ // quit when detecting this.
+ attemptComplete();
+
+ // *REMOVE:Mani - Saving for reference...
+ //LLAppViewer::instance()->forceQuit();
+ // // Bump them back to the login screen.
+ // //reset_login();
+ }
+ else
+ {
+ // Optional update, user chose to skip
+ mSkipOptionalUpdate = true;
+ reconnect();
+ }
+ return false;
+ }
+
+ if(mUpdaterLauncher)
+ {
+ mUpdaterLauncher();
+ }
+
+ attemptComplete();
+
+ return false;
+}
+
+std::string construct_start_string()
+{
+ std::string start;
+ if (LLURLSimString::parse())
+ {
+ // a startup URL was specified
+ std::string unescaped_start =
+ STRINGIZE( "uri:"
+ << LLURLSimString::sInstance.mSimName << "&"
+ << LLURLSimString::sInstance.mX << "&"
+ << LLURLSimString::sInstance.mY << "&"
+ << LLURLSimString::sInstance.mZ);
+ start = xml_escape_string(unescaped_start);
+ }
+ else
+ {
+ start = gSavedSettings.getString("LoginLocation");
+ }
+ return start;
+}
+
diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h
new file mode 100644
index 0000000000..c8704eddb4
--- /dev/null
+++ b/indra/newview/lllogininstance.h
@@ -0,0 +1,114 @@
+/**
+ * @file lllogininstance.h
+ * @brief A host for the viewer's login connection.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLLOGININSTANCE_H
+#define LL_LLLOGININSTANCE_H
+
+#include "lleventdispatcher.h"
+#include <boost/scoped_ptr.hpp>
+#include <boost/function.hpp>
+class LLLogin;
+class LLEventStream;
+class LLNotificationsInterface;
+
+// This class hosts the login module and is used to
+// negotiate user authentication attempts.
+class LLLoginInstance : public LLSingleton<LLLoginInstance>
+{
+public:
+ LLLoginInstance();
+ ~LLLoginInstance();
+
+ void connect(const LLSD& credential); // Connect to the current grid choice.
+ void connect(const std::string& uri, const LLSD& credential); // Connect to the given uri.
+ void reconnect(); // reconnect using the current credentials.
+ void disconnect();
+
+ bool authFailure() { return mAttemptComplete && mLoginState == "offline"; }
+ bool authSuccess() { return mAttemptComplete && mLoginState == "online"; }
+
+ const std::string& getLoginState() { return mLoginState; }
+ LLSD getResponse(const std::string& key) { return getResponse()[key]; }
+ LLSD getResponse();
+
+ // Only valid when authSuccess == true.
+ const F64 getLastTransferRateBPS() { return mTransferRate; }
+
+ // Set whether this class will drive user interaction.
+ // If not, login failures like 'need tos agreement' will
+ // end the login attempt.
+ void setUserInteraction(bool state) { mUserInteraction = state; }
+ bool getUserInteraction() { return mUserInteraction; }
+
+ // Whether to tell login to skip optional update request.
+ // False by default.
+ void setSkipOptionalUpdate(bool state) { mSkipOptionalUpdate = state; }
+ void setSerialNumber(const std::string& sn) { mSerialNumber = sn; }
+ void setLastExecEvent(int lee) { mLastExecEvent = lee; }
+
+ void setNotificationsInterface(LLNotificationsInterface* ni) { mNotifications = ni; }
+
+ typedef boost::function<void()> UpdaterLauncherCallback;
+ void setUpdaterLauncher(const UpdaterLauncherCallback& ulc) { mUpdaterLauncher = ulc; }
+
+private:
+ void constructAuthParams(const LLSD& credentials);
+ void updateApp(bool mandatory, const std::string& message);
+ bool updateDialogCallback(const LLSD& notification, const LLSD& response);
+
+ bool handleLoginEvent(const LLSD& event);
+ void handleLoginFailure(const LLSD& event);
+ void handleLoginSuccess(const LLSD& event);
+ void handleDisconnect(const LLSD& event);
+ void handleIndeterminate(const LLSD& event);
+
+ bool handleTOSResponse(bool v, const std::string& key);
+
+ void attemptComplete() { mAttemptComplete = true; } // In the future an event?
+
+ boost::scoped_ptr<LLLogin> mLoginModule;
+ LLNotificationsInterface* mNotifications;
+
+ std::string mLoginState;
+ LLSD mRequestData;
+ LLSD mResponseData;
+ bool mUserInteraction;
+ bool mSkipOptionalUpdate;
+ bool mAttemptComplete;
+ F64 mTransferRate;
+ std::string mSerialNumber;
+ int mLastExecEvent;
+ UpdaterLauncherCallback mUpdaterLauncher;
+ LLEventDispatcher mDispatcher;
+};
+
+#endif
diff --git a/indra/newview/lllookshistorypanel.h b/indra/newview/lllookshistorypanel.h
new file mode 100644
index 0000000000..986c9a1c4d
--- /dev/null
+++ b/indra/newview/lllookshistorypanel.h
@@ -0,0 +1,72 @@
+/**
+ * @file llpanelteleporthistory.h
+ * @brief Teleport history represented by a scrolling list
+ * class definition
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELLOOKSHISTORY_H
+#define LL_LLPANELLOOKSHISTORY_H
+
+#include "lluictrlfactory.h"
+#include "llscrolllistctrl.h"
+
+#include "llpanelappearancetab.h"
+#include "lllookshistory.h"
+
+class LLLooksHistoryPanel : public LLPanelAppearanceTab
+{
+public:
+ LLLooksHistoryPanel();
+ virtual ~LLLooksHistoryPanel();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onSearchEdit(const std::string& string);
+ /*virtual*/ void onShowOnMap();
+ /*virtual*/ void onLooks();
+ ///*virtual*/ void onCopySLURL();
+
+ void showLooksHistory();
+ void handleItemSelect(const LLSD& data);
+
+ static void onDoubleClickItem(void* user_data);
+
+private:
+ enum LOOKS_HISTORY_COLUMN_ORDER
+ {
+ LIST_ICON,
+ LIST_ITEM_TITLE,
+ LIST_INDEX
+ };
+
+ LLLooksHistory* mLooksHistory;
+ LLScrollListCtrl* mHistoryItems;
+ std::string mFilterSubString;
+};
+
+#endif //LL_LLPANELLOOKSHISTORY_H
diff --git a/indra/newview/llmanip.cpp b/indra/newview/llmanip.cpp
index 53c74aaec1..a96240e31c 100644
--- a/indra/newview/llmanip.cpp
+++ b/indra/newview/llmanip.cpp
@@ -40,7 +40,7 @@
#include "llrender.h"
#include "llprimitive.h"
#include "llview.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llagent.h"
#include "llviewercontrol.h"
@@ -85,6 +85,7 @@ void LLManip::rebuild(LLViewerObject* vobj)
if (group)
{
group->dirtyGeom();
+ gPipeline.markRebuild(group, TRUE);
}
}
}
@@ -264,8 +265,8 @@ BOOL LLManip::getMousePointOnPlaneGlobal(LLVector3d& point, S32 x, S32 y, LLVect
if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
{
BOOL result = FALSE;
- F32 mouse_x = ((F32)x / gViewerWindow->getWindowWidth() - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgent.mHUDCurZoom;
- F32 mouse_y = ((F32)y / gViewerWindow->getWindowHeight() - 0.5f) / gAgent.mHUDCurZoom;
+ F32 mouse_x = ((F32)x / gViewerWindow->getWorldViewWidthScaled() - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgent.mHUDCurZoom;
+ F32 mouse_y = ((F32)y / gViewerWindow->getWorldViewHeightScaled() - 0.5f) / gAgent.mHUDCurZoom;
LLVector3 origin_agent = gAgent.getPosAgentFromGlobal(origin);
LLVector3 mouse_pos = LLVector3(0.f, -mouse_x, mouse_y);
@@ -303,8 +304,8 @@ BOOL LLManip::nearestPointOnLineFromMouse( S32 x, S32 y, const LLVector3& b1, co
if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
{
- F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidth()) - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgent.mHUDCurZoom;
- F32 mouse_y = (((F32)y / gViewerWindow->getWindowHeight()) - 0.5f) / gAgent.mHUDCurZoom;
+ F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidthScaled()) - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgent.mHUDCurZoom;
+ F32 mouse_y = (((F32)y / gViewerWindow->getWindowHeightScaled()) - 0.5f) / gAgent.mHUDCurZoom;
a1 = LLVector3(llmin(b1.mV[VX] - 0.1f, b2.mV[VX] - 0.1f, 0.f), -mouse_x, mouse_y);
a2 = a1 + LLVector3(1.f, 0.f, 0.f);
}
@@ -428,13 +429,14 @@ void LLManip::renderXYZ(const LLVector3 &vec)
const S32 PAD = 10;
std::string feedback_string;
LLVector3 camera_pos = LLViewerCamera::getInstance()->getOrigin() + LLViewerCamera::getInstance()->getAtAxis();
- S32 vertical_offset = gViewerWindow->getWindowHeight() / 2 - VERTICAL_OFFSET;
- S32 window_center_x = gViewerWindow->getWindowWidth() / 2;
- S32 window_center_y = gViewerWindow->getWindowHeight() / 2;
+ S32 window_center_x = gViewerWindow->getWorldViewRectScaled().getWidth() / 2;
+ S32 window_center_y = gViewerWindow->getWorldViewRectScaled().getHeight() / 2;
+ S32 vertical_offset = window_center_y - VERTICAL_OFFSET;
+
glPushMatrix();
{
- LLUIImagePtr imagep = LLUI::getUIImage("rounded_square.tga");
+ LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square");
gViewerWindow->setup2DRender();
const LLVector2& display_scale = gViewerWindow->getDisplayScale();
glScalef(display_scale.mV[VX], display_scale.mV[VY], 1.f);
@@ -452,35 +454,36 @@ void LLManip::renderXYZ(const LLVector3 &vec)
gViewerWindow->setup3DRender();
{
+ LLFontGL* font = LLFontGL::getFontSansSerif();
LLLocale locale(LLLocale::USER_LOCALE);
LLGLDepthTest gls_depth(GL_FALSE);
// render drop shadowed text
feedback_string = llformat("X: %.3f", vec.mV[VX]);
- hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF ), LLFontGL::NORMAL, -102.f + 1.f, (F32)vertical_offset - 1.f, LLColor4::black, FALSE);
+ hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *font, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -102.f + 1.f, (F32)vertical_offset - 1.f, LLColor4::black, FALSE);
feedback_string = llformat("Y: %.3f", vec.mV[VY]);
- hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF ), LLFontGL::NORMAL, -27.f + 1.f, (F32)vertical_offset - 1.f, LLColor4::black, FALSE);
+ hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *font, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -27.f + 1.f, (F32)vertical_offset - 1.f, LLColor4::black, FALSE);
feedback_string = llformat("Z: %.3f", vec.mV[VZ]);
- hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF ), LLFontGL::NORMAL, 48.f + 1.f, (F32)vertical_offset - 1.f, LLColor4::black, FALSE);
+ hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *font, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, 48.f + 1.f, (F32)vertical_offset - 1.f, LLColor4::black, FALSE);
// render text on top
feedback_string = llformat("X: %.3f", vec.mV[VX]);
- hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF ), LLFontGL::NORMAL, -102.f, (F32)vertical_offset, LLColor4(1.f, 0.5f, 0.5f, 1.f), FALSE);
+ hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *font, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -102.f, (F32)vertical_offset, LLColor4(1.f, 0.5f, 0.5f, 1.f), FALSE);
glColor3f(0.5f, 1.f, 0.5f);
feedback_string = llformat("Y: %.3f", vec.mV[VY]);
- hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF ), LLFontGL::NORMAL, -27.f, (F32)vertical_offset, LLColor4(0.5f, 1.f, 0.5f, 1.f), FALSE);
+ hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *font, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -27.f, (F32)vertical_offset, LLColor4(0.5f, 1.f, 0.5f, 1.f), FALSE);
glColor3f(0.5f, 0.5f, 1.f);
feedback_string = llformat("Z: %.3f", vec.mV[VZ]);
- hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF ), LLFontGL::NORMAL, 48.f, (F32)vertical_offset, LLColor4(0.5f, 0.5f, 1.f, 1.f), FALSE);
+ hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *font, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, 48.f, (F32)vertical_offset, LLColor4(0.5f, 0.5f, 1.f, 1.f), FALSE);
}
}
void LLManip::renderTickText(const LLVector3& pos, const std::string& text, const LLColor4 &color)
{
- const LLFontGL* big_fontp = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF );
+ const LLFontGL* big_fontp = LLFontGL::getFontSansSerif();
BOOL hud_selection = mObjectSelection->getSelectType() == SELECT_TYPE_HUD;
glMatrixMode(GL_MODELVIEW);
@@ -498,10 +501,10 @@ void LLManip::renderTickText(const LLVector3& pos, const std::string& text, cons
// render shadow first
LLColor4 shadow_color = LLColor4::black;
shadow_color.mV[VALPHA] = color.mV[VALPHA] * 0.5f;
- gViewerWindow->setupViewport(1, -1);
- hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(text), 3.f, shadow_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
- gViewerWindow->setupViewport();
- hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(text), 3.f, color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
+ gViewerWindow->setup3DViewport(1, -1);
+ hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(text), 3.f, shadow_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
+ gViewerWindow->setup3DViewport();
+ hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(text), 3.f, color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
glPopMatrix();
}
@@ -510,8 +513,8 @@ void LLManip::renderTickValue(const LLVector3& pos, F32 value, const std::string
{
LLLocale locale(LLLocale::USER_LOCALE);
- const LLFontGL* big_fontp = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF );
- const LLFontGL* small_fontp = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL );
+ const LLFontGL* big_fontp = LLFontGL::getFontSansSerif();
+ const LLFontGL* small_fontp = LLFontGL::getFontSansSerifSmall();
std::string val_string;
std::string fraction_string;
@@ -560,29 +563,29 @@ void LLManip::renderTickValue(const LLVector3& pos, F32 value, const std::string
{
fraction_string = llformat("%c%02d%s", LLResMgr::getInstance()->getDecimalPoint(), fractional_portion, suffix.c_str());
- gViewerWindow->setupViewport(1, -1);
- hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, -1.f * big_fontp->getWidthF32(val_string), 3.f, shadow_color, hud_selection);
- hud_render_utf8text(fraction_string, render_pos, *small_fontp, LLFontGL::NORMAL, 1.f, 3.f, shadow_color, hud_selection);
+ gViewerWindow->setup3DViewport(1, -1);
+ hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -1.f * big_fontp->getWidthF32(val_string), 3.f, shadow_color, hud_selection);
+ hud_render_utf8text(fraction_string, render_pos, *small_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, 1.f, 3.f, shadow_color, hud_selection);
- gViewerWindow->setupViewport();
- hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, -1.f * big_fontp->getWidthF32(val_string), 3.f, color, hud_selection);
- hud_render_utf8text(fraction_string, render_pos, *small_fontp, LLFontGL::NORMAL, 1.f, 3.f, color, hud_selection);
+ gViewerWindow->setup3DViewport();
+ hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -1.f * big_fontp->getWidthF32(val_string), 3.f, color, hud_selection);
+ hud_render_utf8text(fraction_string, render_pos, *small_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, 1.f, 3.f, color, hud_selection);
}
else
{
- gViewerWindow->setupViewport(1, -1);
- hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(val_string), 3.f, shadow_color, hud_selection);
- gViewerWindow->setupViewport();
- hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(val_string), 3.f, color, hud_selection);
+ gViewerWindow->setup3DViewport(1, -1);
+ hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(val_string), 3.f, shadow_color, hud_selection);
+ gViewerWindow->setup3DViewport();
+ hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(val_string), 3.f, color, hud_selection);
}
glPopMatrix();
}
LLColor4 LLManip::setupSnapGuideRenderPass(S32 pass)
{
- static LLColor4 grid_color_fg = gColors.getColor("GridlineColor");
- static LLColor4 grid_color_bg = gColors.getColor("GridlineBGColor");
- static LLColor4 grid_color_shadow = gColors.getColor("GridlineShadowColor");
+ static LLColor4 grid_color_fg = LLUIColorTable::instance().getColor("GridlineColor");
+ static LLColor4 grid_color_bg = LLUIColorTable::instance().getColor("GridlineBGColor");
+ static LLColor4 grid_color_shadow = LLUIColorTable::instance().getColor("GridlineShadowColor");
LLColor4 line_color;
F32 line_alpha = gSavedSettings.getF32("GridOpacity");
@@ -591,14 +594,14 @@ LLColor4 LLManip::setupSnapGuideRenderPass(S32 pass)
{
case 0:
// shadow
- gViewerWindow->setupViewport(1, -1);
+ gViewerWindow->setup3DViewport(1, -1);
line_color = grid_color_shadow;
line_color.mV[VALPHA] *= line_alpha;
LLUI::setLineWidth(2.f);
break;
case 1:
// hidden lines
- gViewerWindow->setupViewport();
+ gViewerWindow->setup3DViewport();
line_color = grid_color_bg;
line_color.mV[VALPHA] *= line_alpha;
LLUI::setLineWidth(1.f);
diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp
index 8b0484bba6..8535d52015 100644
--- a/indra/newview/llmaniprotate.cpp
+++ b/indra/newview/llmaniprotate.cpp
@@ -49,7 +49,7 @@
#include "llbutton.h"
#include "llviewercontrol.h"
#include "llcriticaldamp.h"
-#include "llhoverview.h"
+#include "lltooltip.h"
#include "llfloatertools.h"
#include "llselectmgr.h"
#include "llstatusbar.h"
@@ -63,6 +63,7 @@
#include "pipeline.h"
#include "lldrawable.h"
#include "llglheaders.h"
+#include "lltrans.h"
const F32 RADIUS_PIXELS = 100.f; // size in screen space
const F32 SQ_RADIUS = RADIUS_PIXELS * RADIUS_PIXELS;
@@ -897,7 +898,6 @@ void LLManipRotate::renderSnapGuides()
}
gGL.end();
- // *TODO: Translate
//RN: text rendering does own shadow pass, so only render once
if (pass == 1 && render_text && i % 16 == 0)
{
@@ -905,32 +905,32 @@ void LLManipRotate::renderSnapGuides()
{
if (i == 0)
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? std::string("Forward") : std::string("East"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Forward") : LLTrans::getString("East"), LLColor4::white);
}
else if (i == 16)
{
if (constraint_axis.mV[VZ] > 0.f)
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? std::string("Left") : std::string("North"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Left") : LLTrans::getString("North"), LLColor4::white);
}
else
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? std::string("Right") : std::string("South"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Right") : LLTrans::getString("South"), LLColor4::white);
}
}
else if (i == 32)
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? std::string("Back") : std::string("West"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Back") : LLTrans::getString("West"), LLColor4::white);
}
else
{
if (constraint_axis.mV[VZ] > 0.f)
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? std::string("Right") : std::string("South"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Right") : LLTrans::getString("South"), LLColor4::white);
}
else
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? std::string("Left") : std::string("North"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Left") : LLTrans::getString("North"), LLColor4::white);
}
}
}
@@ -938,32 +938,32 @@ void LLManipRotate::renderSnapGuides()
{
if (i == 0)
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? std::string("Left") : std::string("North"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Left") : LLTrans::getString("North"), LLColor4::white);
}
else if (i == 16)
{
if (constraint_axis.mV[VX] > 0.f)
{
- renderTickText(text_point, std::string("Up"), LLColor4::white);
+ renderTickText(text_point, LLTrans::getString("Up"), LLColor4::white);
}
else
{
- renderTickText(text_point, std::string("Down"), LLColor4::white);
+ renderTickText(text_point, LLTrans::getString("Down"), LLColor4::white);
}
}
else if (i == 32)
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? std::string("Right") : std::string("South"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Right") : LLTrans::getString("South"), LLColor4::white);
}
else
{
if (constraint_axis.mV[VX] > 0.f)
{
- renderTickText(text_point, std::string("Down"), LLColor4::white);
+ renderTickText(text_point, LLTrans::getString("Down"), LLColor4::white);
}
else
{
- renderTickText(text_point, std::string("Up"), LLColor4::white);
+ renderTickText(text_point, LLTrans::getString("Up"), LLColor4::white);
}
}
}
@@ -971,32 +971,32 @@ void LLManipRotate::renderSnapGuides()
{
if (i == 0)
{
- renderTickText(text_point, std::string("Up"), LLColor4::white);
+ renderTickText(text_point, LLTrans::getString("Up"), LLColor4::white);
}
else if (i == 16)
{
if (constraint_axis.mV[VY] > 0.f)
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? std::string("Forward") : std::string("East"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Forward") : LLTrans::getString("East"), LLColor4::white);
}
else
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? std::string("Back") : std::string("West"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Back") : LLTrans::getString("West"), LLColor4::white);
}
}
else if (i == 32)
{
- renderTickText(text_point, std::string("Down"), LLColor4::white);
+ renderTickText(text_point, LLTrans::getString("Down"), LLColor4::white);
}
else
{
if (constraint_axis.mV[VY] > 0.f)
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? std::string("Back") : std::string("West"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Back") : LLTrans::getString("West"), LLColor4::white);
}
else
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? std::string("Forward") : std::string("East"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Forward") : LLTrans::getString("East"), LLColor4::white);
}
}
}
@@ -1107,8 +1107,11 @@ BOOL LLManipRotate::updateVisiblity()
mCenterToProfilePlaneMag = mRadiusMeters * mRadiusMeters / mCenterToCamMag;
mCenterToProfilePlane = -mCenterToProfilePlaneMag * mCenterToCamNorm;
- mCenterScreen.set((S32)((0.5f - mRotationCenter.mdV[VY]) / gAgent.mHUDCurZoom * gViewerWindow->getWindowWidth()),
- (S32)((mRotationCenter.mdV[VZ] + 0.5f) / gAgent.mHUDCurZoom * gViewerWindow->getWindowHeight()));
+ // x axis range is (-aspect * 0.5f, +aspect * 0.5)
+ // y axis range is (-0.5, 0.5)
+ // so use getWorldViewHeightRaw as scale factor when converting to pixel coordinates
+ mCenterScreen.set((S32)((0.5f - center.mV[VY]) / gAgent.mHUDCurZoom * gViewerWindow->getWorldViewHeightScaled()),
+ (S32)((center.mV[VZ] + 0.5f) / gAgent.mHUDCurZoom * gViewerWindow->getWorldViewHeightScaled()));
visible = TRUE;
}
else
@@ -1234,9 +1237,9 @@ LLVector3 LLManipRotate::getConstraintAxis()
else
{
#ifndef LL_RELEASE_FOR_DOWNLOAD
- llerrs << "Got bogus hit part in LLManipRotate::getConstraintAxis():" << mManipPart << llendl
+ llerrs << "Got bogus hit part in LLManipRotate::getConstraintAxis():" << mManipPart << llendl;
#else
- llwarns << "Got bogus hit part in LLManipRotate::getConstraintAxis():" << mManipPart << llendl
+ llwarns << "Got bogus hit part in LLManipRotate::getConstraintAxis():" << mManipPart << llendl;
#endif
axis.mV[0] = 1.f;
}
@@ -1624,8 +1627,8 @@ void LLManipRotate::mouseToRay( S32 x, S32 y, LLVector3* ray_pt, LLVector3* ray_
{
if (LLSelectMgr::getInstance()->getSelection()->getSelectType() == SELECT_TYPE_HUD)
{
- F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidth()) - 0.5f) / gAgent.mHUDCurZoom;
- F32 mouse_y = ((((F32)y) / gViewerWindow->getWindowHeight()) - 0.5f) / gAgent.mHUDCurZoom;
+ F32 mouse_x = (((F32)x / gViewerWindow->getWorldViewRectScaled().getWidth()) - 0.5f) / gAgent.mHUDCurZoom;
+ F32 mouse_y = ((((F32)y) / gViewerWindow->getWorldViewRectScaled().getHeight()) - 0.5f) / gAgent.mHUDCurZoom;
*ray_pt = LLVector3(-1.f, -mouse_x, mouse_y);
*ray_dir = LLVector3(1.f, 0.f, 0.f);
@@ -1699,7 +1702,7 @@ void LLManipRotate::highlightManipulators( S32 x, S32 y )
F32 dist_y = mouse_dir_y.normVec();
F32 dist_z = mouse_dir_z.normVec();
- F32 distance_threshold = (MAX_MANIP_SELECT_DISTANCE * mRadiusMeters) / gViewerWindow->getWindowHeight();
+ F32 distance_threshold = (MAX_MANIP_SELECT_DISTANCE * mRadiusMeters) / gViewerWindow->getWorldViewHeightScaled();
if (llabs(dist_x - mRadiusMeters) * llmax(0.05f, proj_rot_x_axis) < distance_threshold)
{
diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp
index b1cdfe3886..84a5eb7352 100644
--- a/indra/newview/llmanipscale.cpp
+++ b/indra/newview/llmanipscale.cpp
@@ -415,7 +415,7 @@ BOOL LLManipScale::handleHover(S32 x, S32 y, MASK mask)
// Patch up textures, if possible.
LLSelectMgr::getInstance()->adjustTexturesByScale(FALSE, getStretchTextures());
- gViewerWindow->getWindow()->setCursor(UI_CURSOR_TOOLSCALE);
+ gViewerWindow->setCursor(UI_CURSOR_TOOLSCALE);
return TRUE;
}
@@ -493,8 +493,9 @@ void LLManipScale::highlightManipulators(S32 x, S32 y)
mProjectedManipulators.insert(projManipulator);
}
- F32 half_width = (F32)gViewerWindow->getWindowWidth() / 2.f;
- F32 half_height = (F32)gViewerWindow->getWindowHeight() / 2.f;
+ LLRect world_view_rect = gViewerWindow->getWorldViewRectScaled();
+ F32 half_width = (F32)world_view_rect.getWidth() / 2.f;
+ F32 half_height = (F32)world_view_rect.getHeight() / 2.f;
LLVector2 manip2d;
LLVector2 mousePos((F32)x - half_width, (F32)y - half_height);
LLVector2 delta;
@@ -1368,7 +1369,7 @@ void LLManipScale::updateSnapGuides(const LLBBox& bbox)
else
{
F32 object_distance = dist_vec(mScaleCenter, LLViewerCamera::getInstance()->getOrigin());
- mSnapRegimeOffset = (SNAP_GUIDE_SCREEN_OFFSET * gViewerWindow->getWindowWidth() * object_distance) / LLViewerCamera::getInstance()->getPixelMeterRatio();
+ mSnapRegimeOffset = (SNAP_GUIDE_SCREEN_OFFSET * gViewerWindow->getWorldViewWidthRaw() * object_distance) / LLViewerCamera::getInstance()->getPixelMeterRatio();
}
LLVector3 cam_at_axis;
F32 snap_guide_length;
@@ -1381,7 +1382,7 @@ void LLManipScale::updateSnapGuides(const LLBBox& bbox)
{
cam_at_axis = LLViewerCamera::getInstance()->getAtAxis();
F32 manipulator_distance = dist_vec(box_corner_agent, LLViewerCamera::getInstance()->getOrigin());
- snap_guide_length = (SNAP_GUIDE_SCREEN_LENGTH * gViewerWindow->getWindowWidth() * manipulator_distance) / LLViewerCamera::getInstance()->getPixelMeterRatio();
+ snap_guide_length = (SNAP_GUIDE_SCREEN_LENGTH * gViewerWindow->getWorldViewWidthRaw() * manipulator_distance) / LLViewerCamera::getInstance()->getPixelMeterRatio();
}
mSnapGuideLength = snap_guide_length / llmax(0.1f, (llmin(mSnapGuideDir1 * cam_at_axis, mSnapGuideDir2 * cam_at_axis)));
@@ -1827,10 +1828,10 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox)
std::string help_text = "Move mouse cursor over ruler";
LLColor4 help_text_color = LLColor4::white;
help_text_color.mV[VALPHA] = clamp_rescale(mHelpTextTimer.getElapsedTimeF32(), sHelpTextVisibleTime, sHelpTextVisibleTime + sHelpTextFadeTime, grid_alpha, 0.f);
- hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
+ hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
help_text = "to snap to grid";
help_text_pos -= LLViewerCamera::getInstance()->getUpAxis() * mSnapRegimeOffset * 0.4f;
- hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
+ hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
}
}
}
diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp
index f2585c8543..5f30ab4e01 100644
--- a/indra/newview/llmaniptranslate.cpp
+++ b/indra/newview/llmaniptranslate.cpp
@@ -61,7 +61,7 @@
#include "llviewerjoint.h"
#include "llviewerobject.h"
#include "llviewerwindow.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "llworld.h"
#include "llui.h"
#include "pipeline.h"
@@ -78,7 +78,7 @@ const F32 PLANE_TICK_SIZE = 0.4f;
const F32 MANIPULATOR_SCALE_HALF_LIFE = 0.07f;
const F32 SNAP_ARROW_SCALE = 0.7f;
-static LLPointer<LLImageGL> sGridTex = NULL ;
+static LLPointer<LLViewerTexture> sGridTex = NULL ;
const LLManip::EManipPart MANIPULATOR_IDS[9] =
{
@@ -101,6 +101,16 @@ const U32 ARROW_TO_AXIS[4] =
VZ
};
+// Sort manipulator handles by their screen-space projection
+struct ClosestToCamera
+{
+ bool operator()(const LLManipTranslate::ManipulatorHandle& a,
+ const LLManipTranslate::ManipulatorHandle& b) const
+ {
+ return a.mEndPosition.mV[VZ] < b.mEndPosition.mV[VZ];
+ }
+};
+
LLManipTranslate::LLManipTranslate( LLToolComposite* composite )
: LLManip( std::string("Move"), composite ),
mLastHoverMouseX(-1),
@@ -154,7 +164,7 @@ void LLManipTranslate::restoreGL()
U32 mip = 0;
destroyGL() ;
- sGridTex = new LLImageGL() ;
+ sGridTex = LLViewerTextureManager::getLocalTexture() ;
if(!sGridTex->createGLTexture())
{
sGridTex = NULL ;
@@ -163,7 +173,7 @@ void LLManipTranslate::restoreGL()
GLuint* d = new GLuint[rez*rez];
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, sGridTex->getTexName());
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, sGridTex->getTexName(), true);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
while (rez >= 1)
@@ -273,7 +283,6 @@ void LLManipTranslate::restoreGL()
LLManipTranslate::~LLManipTranslate()
{
- for_each(mProjectedManipulators.begin(), mProjectedManipulators.end(), DeletePointer());
}
@@ -379,7 +388,7 @@ BOOL LLManipTranslate::handleMouseDownOnPart( S32 x, S32 y, MASK mask )
}
else if (gSavedSettings.getBOOL("SnapToMouseCursor"))
{
- LLUI::setCursorPositionScreen(mouse_pos.mX, mouse_pos.mY);
+ LLUI::setMousePositionScreen(mouse_pos.mX, mouse_pos.mY);
x = mouse_pos.mX;
y = mouse_pos.mY;
}
@@ -413,8 +422,9 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask)
}
// Handle auto-rotation if necessary.
+ LLRect world_rect = gViewerWindow->getWorldViewRectScaled();
const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD;
- const S32 ROTATE_H_MARGIN = gViewerWindow->getWindowWidth() / 20;
+ const S32 ROTATE_H_MARGIN = world_rect.getWidth() / 20;
const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped;
BOOL rotated = FALSE;
@@ -426,7 +436,7 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask)
gAgent.cameraOrbitAround(rotate_angle);
rotated = TRUE;
}
- else if (x > gViewerWindow->getWindowWidth() - ROTATE_H_MARGIN)
+ else if (x > world_rect.getWidth() - ROTATE_H_MARGIN)
{
gAgent.cameraOrbitAround(-rotate_angle);
rotated = TRUE;
@@ -887,8 +897,9 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y)
planar_manip_xy_visible = TRUE;
}
- for_each(mProjectedManipulators.begin(), mProjectedManipulators.end(), DeletePointer());
- mProjectedManipulators.clear();
+ // Project up to 9 manipulators to screen space 2*X, 2*Y, 2*Z, 3*planes
+ std::vector<ManipulatorHandle> projected_manipulators;
+ projected_manipulators.reserve(9);
for (S32 i = 0; i < num_arrow_manips; i+= 2)
{
@@ -898,12 +909,12 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y)
LLVector4 projected_end = mManipulatorVertices[i + 1] * transform;
projected_end = projected_end * (1.f / projected_end.mV[VW]);
- ManipulatorHandle* projManipulator =
- new ManipulatorHandle(LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]),
+ ManipulatorHandle projected_manip(
+ LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]),
LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]),
MANIPULATOR_IDS[i / 2],
10.f); // 10 pixel hotspot for arrows
- mProjectedManipulators.insert(projManipulator);
+ projected_manipulators.push_back(projected_manip);
}
if (planar_manip_yz_visible)
@@ -915,12 +926,12 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y)
LLVector4 projected_end = mManipulatorVertices[i + 1] * transform;
projected_end = projected_end * (1.f / projected_end.mV[VW]);
- ManipulatorHandle* projManipulator =
- new ManipulatorHandle(LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]),
+ ManipulatorHandle projected_manip(
+ LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]),
LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]),
MANIPULATOR_IDS[i / 2],
20.f); // 20 pixels for planar manipulators
- mProjectedManipulators.insert(projManipulator);
+ projected_manipulators.push_back(projected_manip);
}
if (planar_manip_xz_visible)
@@ -932,12 +943,12 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y)
LLVector4 projected_end = mManipulatorVertices[i + 1] * transform;
projected_end = projected_end * (1.f / projected_end.mV[VW]);
- ManipulatorHandle* projManipulator =
- new ManipulatorHandle(LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]),
+ ManipulatorHandle projected_manip(
+ LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]),
LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]),
MANIPULATOR_IDS[i / 2],
20.f); // 20 pixels for planar manipulators
- mProjectedManipulators.insert(projManipulator);
+ projected_manipulators.push_back(projected_manip);
}
if (planar_manip_xy_visible)
@@ -949,29 +960,35 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y)
LLVector4 projected_end = mManipulatorVertices[i + 1] * transform;
projected_end = projected_end * (1.f / projected_end.mV[VW]);
- ManipulatorHandle* projManipulator =
- new ManipulatorHandle(LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]),
+ ManipulatorHandle projected_manip(
+ LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]),
LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]),
MANIPULATOR_IDS[i / 2],
20.f); // 20 pixels for planar manipulators
- mProjectedManipulators.insert(projManipulator);
+ projected_manipulators.push_back(projected_manip);
}
LLVector2 manip_start_2d;
LLVector2 manip_end_2d;
LLVector2 manip_dir;
- F32 half_width = gViewerWindow->getWindowWidth() / 2.f;
- F32 half_height = gViewerWindow->getWindowHeight() / 2.f;
+ LLRect world_view_rect = gViewerWindow->getWorldViewRectScaled();
+ F32 half_width = (F32)world_view_rect.getWidth() / 2.f;
+ F32 half_height = (F32)world_view_rect.getHeight() / 2.f;
LLVector2 mousePos((F32)x - half_width, (F32)y - half_height);
LLVector2 mouse_delta;
- for (minpulator_list_t::iterator iter = mProjectedManipulators.begin();
- iter != mProjectedManipulators.end(); ++iter)
+ // Keep order consistent with insertion via stable_sort
+ std::stable_sort( projected_manipulators.begin(),
+ projected_manipulators.end(),
+ ClosestToCamera() );
+
+ std::vector<ManipulatorHandle>::iterator it = projected_manipulators.begin();
+ for ( ; it != projected_manipulators.end(); ++it)
{
- ManipulatorHandle* manipulator = *iter;
+ ManipulatorHandle& manipulator = *it;
{
- manip_start_2d.setVec(manipulator->mStartPosition.mV[VX] * half_width, manipulator->mStartPosition.mV[VY] * half_height);
- manip_end_2d.setVec(manipulator->mEndPosition.mV[VX] * half_width, manipulator->mEndPosition.mV[VY] * half_height);
+ manip_start_2d.setVec(manipulator.mStartPosition.mV[VX] * half_width, manipulator.mStartPosition.mV[VY] * half_height);
+ manip_end_2d.setVec(manipulator.mEndPosition.mV[VX] * half_width, manipulator.mEndPosition.mV[VY] * half_height);
manip_dir = manip_end_2d - manip_start_2d;
mouse_delta = mousePos - manip_start_2d;
@@ -983,9 +1000,9 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y)
if (mouse_pos_manip > 0.f &&
mouse_pos_manip < manip_length &&
- mouse_dist_manip_squared < manipulator->mHotSpotRadius * manipulator->mHotSpotRadius)
+ mouse_dist_manip_squared < manipulator.mHotSpotRadius * manipulator.mHotSpotRadius)
{
- mHighlightedPart = manipulator->mManipID;
+ mHighlightedPart = manipulator.mManipID;
break;
}
}
@@ -1225,7 +1242,7 @@ void LLManipTranslate::renderSnapGuides()
{
LLVector3 cam_to_selection = getPivotPoint() - LLViewerCamera::getInstance()->getOrigin();
F32 current_range = cam_to_selection.normVec();
- guide_size_meters = SNAP_GUIDE_SCREEN_SIZE * gViewerWindow->getWindowHeight() * current_range / LLViewerCamera::getInstance()->getPixelMeterRatio();
+ guide_size_meters = SNAP_GUIDE_SCREEN_SIZE * gViewerWindow->getWorldViewHeightRaw() * current_range / LLViewerCamera::getInstance()->getPixelMeterRatio();
F32 fraction_of_fov = mAxisArrowLength / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels();
F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians
@@ -1438,13 +1455,13 @@ void LLManipTranslate::renderSnapGuides()
LLVector3 help_text_pos = selection_center_start + (snap_offset_meters_up * 3.f * mSnapOffsetAxis);
const LLFontGL* big_fontp = LLFontGL::getFontSansSerif();
- std::string help_text = "Move mouse cursor over ruler to snap";
+ std::string help_text = "Move mouse cursor over ruler";
LLColor4 help_text_color = LLColor4::white;
help_text_color.mV[VALPHA] = clamp_rescale(mHelpTextTimer.getElapsedTimeF32(), sHelpTextVisibleTime, sHelpTextVisibleTime + sHelpTextFadeTime, line_alpha, 0.f);
- hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
+ hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
help_text = "to snap to grid";
help_text_pos -= LLViewerCamera::getInstance()->getUpAxis() * mSnapOffsetMeters * 0.2f;
- hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
+ hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
}
}
}
@@ -1522,7 +1539,7 @@ void LLManipTranslate::renderSnapGuides()
float a = line_alpha;
- LLColor4 col = gColors.getColor("SilhouetteChildColor");
+ LLColor4 col = LLUIColorTable::instance().getColor("SilhouetteChildColor");
{
//draw grid behind objects
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
@@ -1800,7 +1817,7 @@ void LLManipTranslate::renderTranslationHandles()
// Drag handles
if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
{
- mArrowLengthMeters = mAxisArrowLength / gViewerWindow->getWindowHeight();
+ mArrowLengthMeters = mAxisArrowLength / gViewerWindow->getWorldViewHeightRaw();
mArrowLengthMeters /= gAgent.mHUDCurZoom;
}
else
diff --git a/indra/newview/llmaniptranslate.h b/indra/newview/llmaniptranslate.h
index 25ff35cc72..d20b86b2f4 100644
--- a/indra/newview/llmaniptranslate.h
+++ b/indra/newview/llmaniptranslate.h
@@ -89,17 +89,6 @@ protected:
F32 getMinGridScale();
private:
- struct compare_manipulators
- {
- bool operator() (const ManipulatorHandle* const a, const ManipulatorHandle* const b) const
- {
- if (a->mEndPosition.mV[VZ] != b->mEndPosition.mV[VZ])
- return (a->mEndPosition.mV[VZ] < b->mEndPosition.mV[VZ]);
- else
- return a->mManipID < b->mManipID;
- }
- };
-
S32 mLastHoverMouseX;
S32 mLastHoverMouseY;
BOOL mSendUpdateOnMouseUp;
@@ -116,8 +105,6 @@ private:
LLVector3d mDragCursorStartGlobal;
LLVector3d mDragSelectionStartGlobal;
LLTimer mUpdateTimer;
- typedef std::set<ManipulatorHandle*, compare_manipulators> minpulator_list_t;
- minpulator_list_t mProjectedManipulators;
LLVector4 mManipulatorVertices[18];
F32 mSnapOffsetMeters;
LLVector3 mSnapOffsetAxis;
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
new file mode 100644
index 0000000000..d464862eed
--- /dev/null
+++ b/indra/newview/llmediactrl.cpp
@@ -0,0 +1,1076 @@
+/**
+ * @file LLMediaCtrl.cpp
+ * @brief Web browser UI control
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ *
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+
+#include "llmediactrl.h"
+
+// viewer includes
+#include "llfloaterworldmap.h"
+#include "lluictrlfactory.h"
+#include "llurldispatcher.h"
+#include "llviewborder.h"
+#include "llviewercontrol.h"
+#include "llviewermedia.h"
+#include "llviewertexture.h"
+#include "llviewerwindow.h"
+#include "llnotificationsutil.h"
+#include "llweb.h"
+#include "llrender.h"
+#include "llpluginclassmedia.h"
+#include "llslurl.h"
+#include "lluictrlfactory.h" // LLDefaultChildRegistry
+#include "llkeyboard.h"
+
+// linden library includes
+#include "llfocusmgr.h"
+
+extern BOOL gRestoreGL;
+
+static LLDefaultChildRegistry::Register<LLMediaCtrl> r("web_browser");
+
+LLMediaCtrl::Params::Params()
+: start_url("start_url"),
+ border_visible("border_visible", true),
+ ignore_ui_scale("ignore_ui_scale", true),
+ hide_loading("hide_loading", false),
+ decouple_texture_size("decouple_texture_size", false),
+ texture_width("texture_width", 1024),
+ texture_height("texture_height", 1024),
+ caret_color("caret_color")
+{
+ tab_stop(false);
+}
+
+LLMediaCtrl::LLMediaCtrl( const Params& p) :
+ LLPanel( p ),
+ mTextureDepthBytes( 4 ),
+ mBorder(NULL),
+ mFrequentUpdates( true ),
+ mForceUpdate( false ),
+ mOpenLinksInExternalBrowser( false ),
+ mOpenLinksInInternalBrowser( false ),
+ mTrusted( false ),
+ mHomePageUrl( "" ),
+ mIgnoreUIScale( true ),
+ mAlwaysRefresh( false ),
+ mMediaSource( 0 ),
+ mTakeFocusOnClick( true ),
+ mCurrentNavUrl( "" ),
+ mStretchToFill( true ),
+ mMaintainAspectRatio ( true ),
+ mHideLoading (false),
+ mHidingInitialLoad (false),
+ mDecoupleTextureSize ( false ),
+ mTextureWidth ( 1024 ),
+ mTextureHeight ( 1024 ),
+ mClearCache(false)
+{
+ {
+ LLColor4 color = p.caret_color().get();
+ setCaretColor( (unsigned int)color.mV[0], (unsigned int)color.mV[1], (unsigned int)color.mV[2] );
+ }
+
+ setIgnoreUIScale(p.ignore_ui_scale);
+
+ setHomePageUrl(p.start_url);
+
+ setBorderVisible(p.border_visible);
+
+ mHideLoading = p.hide_loading;
+
+ setDecoupleTextureSize(p.decouple_texture_size);
+
+ setTextureSize(p.texture_width, p.texture_height);
+
+ if(!getDecoupleTextureSize())
+ {
+ S32 screen_width = mIgnoreUIScale ?
+ llround((F32)getRect().getWidth() * LLUI::sGLScaleFactor.mV[VX]) : getRect().getWidth();
+ S32 screen_height = mIgnoreUIScale ?
+ llround((F32)getRect().getHeight() * LLUI::sGLScaleFactor.mV[VY]) : getRect().getHeight();
+
+ setTextureSize(screen_width, screen_height);
+ }
+
+ mMediaTextureID.generate();
+
+ // We don't need to create the media source up front anymore unless we have a non-empty home URL to navigate to.
+ if(!mHomePageUrl.empty())
+ {
+ navigateHome();
+ }
+
+ // FIXME: How do we create a bevel now?
+// LLRect border_rect( 0, getRect().getHeight() + 2, getRect().getWidth() + 2, 0 );
+// mBorder = new LLViewBorder( std::string("web control border"), border_rect, LLViewBorder::BEVEL_IN );
+// addChild( mBorder );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// note: this is now a singleton and destruction happens via initClass() now
+LLMediaCtrl::~LLMediaCtrl()
+{
+
+ if (mMediaSource)
+ {
+ mMediaSource->remObserver( this );
+ mMediaSource = NULL;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::setBorderVisible( BOOL border_visible )
+{
+ if ( mBorder )
+ {
+ mBorder->setVisible( border_visible );
+ };
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::setTakeFocusOnClick( bool take_focus )
+{
+ mTakeFocusOnClick = take_focus;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// set flag that forces the embedded browser to open links in the external system browser
+void LLMediaCtrl::setOpenInExternalBrowser( bool valIn )
+{
+ mOpenLinksInExternalBrowser = valIn;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// set flag that forces the embedded browser to open links in the internal browser floater
+void LLMediaCtrl::setOpenInInternalBrowser( bool valIn )
+{
+ mOpenLinksInInternalBrowser = valIn;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+void LLMediaCtrl::setTrusted( bool valIn )
+{
+ mTrusted = valIn;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLMediaCtrl::handleHover( S32 x, S32 y, MASK mask )
+{
+ convertInputCoords(x, y);
+
+ if (mMediaSource)
+ {
+ mMediaSource->mouseMove(x, y, mask);
+ gViewerWindow->setCursor(mMediaSource->getLastSetCursor());
+ }
+
+ return TRUE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLMediaCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks )
+{
+ if (mMediaSource && mMediaSource->hasMedia())
+ mMediaSource->getMediaPlugin()->scrollEvent(0, clicks, gKeyboard->currentMask(TRUE));
+
+ return TRUE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask )
+{
+ convertInputCoords(x, y);
+
+ if (mMediaSource)
+ {
+ mMediaSource->mouseUp(x, y, mask);
+
+ // *HACK: LLMediaImplLLMozLib automatically takes focus on mouseup,
+ // in addition to the onFocusReceived() call below. Undo this. JC
+ if (!mTakeFocusOnClick)
+ {
+ mMediaSource->focus(false);
+ gViewerWindow->focusClient();
+ }
+ }
+
+ gFocusMgr.setMouseCapture( NULL );
+
+ return TRUE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLMediaCtrl::handleMouseDown( S32 x, S32 y, MASK mask )
+{
+ convertInputCoords(x, y);
+
+ if (mMediaSource)
+ mMediaSource->mouseDown(x, y, mask);
+
+ gFocusMgr.setMouseCapture( this );
+
+ if (mTakeFocusOnClick)
+ {
+ setFocus( TRUE );
+ }
+
+ return TRUE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLMediaCtrl::handleRightMouseUp( S32 x, S32 y, MASK mask )
+{
+ convertInputCoords(x, y);
+
+ if (mMediaSource)
+ {
+ mMediaSource->mouseUp(x, y, mask, 1);
+
+ // *HACK: LLMediaImplLLMozLib automatically takes focus on mouseup,
+ // in addition to the onFocusReceived() call below. Undo this. JC
+ if (!mTakeFocusOnClick)
+ {
+ mMediaSource->focus(false);
+ gViewerWindow->focusClient();
+ }
+ }
+
+ gFocusMgr.setMouseCapture( NULL );
+
+ return TRUE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask )
+{
+ convertInputCoords(x, y);
+
+ if (mMediaSource)
+ mMediaSource->mouseDown(x, y, mask, 1);
+
+ gFocusMgr.setMouseCapture( this );
+
+ if (mTakeFocusOnClick)
+ {
+ setFocus( TRUE );
+ }
+
+ return TRUE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLMediaCtrl::handleDoubleClick( S32 x, S32 y, MASK mask )
+{
+ convertInputCoords(x, y);
+
+ if (mMediaSource)
+ mMediaSource->mouseDoubleClick( x, y, mask);
+
+ gFocusMgr.setMouseCapture( this );
+
+ if (mTakeFocusOnClick)
+ {
+ setFocus( TRUE );
+ }
+
+ return TRUE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::onFocusReceived()
+{
+ if (mMediaSource)
+ {
+ mMediaSource->focus(true);
+
+ // Set focus for edit menu items
+ LLEditMenuHandler::gEditMenuHandler = mMediaSource;
+ }
+
+ LLPanel::onFocusReceived();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::onFocusLost()
+{
+ if (mMediaSource)
+ {
+ mMediaSource->focus(false);
+
+ if( LLEditMenuHandler::gEditMenuHandler == mMediaSource )
+ {
+ // Clear focus for edit menu items
+ LLEditMenuHandler::gEditMenuHandler = NULL;
+ }
+ }
+
+ gViewerWindow->focusClient();
+
+ LLPanel::onFocusLost();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLMediaCtrl::postBuild ()
+{
+ setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChange, this, _2));
+ return TRUE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask )
+{
+ BOOL result = FALSE;
+
+ if (mMediaSource)
+ {
+ result = mMediaSource->handleKeyHere(key, mask);
+ }
+
+ return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::handleVisibilityChange ( BOOL new_visibility )
+{
+ llinfos << "visibility changed to " << (new_visibility?"true":"false") << llendl;
+ if(mMediaSource)
+ {
+ mMediaSource->setVisible( new_visibility );
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char)
+{
+ BOOL result = FALSE;
+
+ if (mMediaSource)
+ {
+ result = mMediaSource->handleUnicodeCharHere(uni_char);
+ }
+
+ return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::onVisibilityChange ( const LLSD& new_visibility )
+{
+ // set state of frequent updates automatically if visibility changes
+ if ( new_visibility.asBoolean() )
+ {
+ mFrequentUpdates = true;
+ }
+ else
+ {
+ mFrequentUpdates = false;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::reshape( S32 width, S32 height, BOOL called_from_parent )
+{
+ if(!getDecoupleTextureSize())
+ {
+ S32 screen_width = mIgnoreUIScale ? llround((F32)width * LLUI::sGLScaleFactor.mV[VX]) : width;
+ S32 screen_height = mIgnoreUIScale ? llround((F32)height * LLUI::sGLScaleFactor.mV[VY]) : height;
+
+ // when floater is minimized, these sizes are negative
+ if ( screen_height > 0 && screen_width > 0 )
+ {
+ setTextureSize(screen_width, screen_height);
+ }
+ }
+
+ LLUICtrl::reshape( width, height, called_from_parent );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::navigateBack()
+{
+ if (mMediaSource && mMediaSource->hasMedia())
+ {
+ mMediaSource->getMediaPlugin()->browse_back();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::navigateForward()
+{
+ if (mMediaSource && mMediaSource->hasMedia())
+ {
+ mMediaSource->getMediaPlugin()->browse_forward();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+bool LLMediaCtrl::canNavigateBack()
+{
+ if (mMediaSource)
+ return mMediaSource->canNavigateBack();
+ else
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+bool LLMediaCtrl::canNavigateForward()
+{
+ if (mMediaSource)
+ return mMediaSource->canNavigateForward();
+ else
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::set404RedirectUrl( std::string redirect_url )
+{
+ if(mMediaSource && mMediaSource->hasMedia())
+ mMediaSource->getMediaPlugin()->set_status_redirect( 404, redirect_url );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::clr404RedirectUrl()
+{
+ if(mMediaSource && mMediaSource->hasMedia())
+ mMediaSource->getMediaPlugin()->set_status_redirect(404, "");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::clearCache()
+{
+ if(mMediaSource)
+ {
+ mMediaSource->clearCache();
+ }
+ else
+ {
+ mClearCache = true;
+ }
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type)
+{
+ // don't browse to anything that starts with secondlife:// or sl://
+ const std::string protocol1 = "secondlife://";
+ const std::string protocol2 = "sl://";
+ if ((LLStringUtil::compareInsensitive(url_in.substr(0, protocol1.length()), protocol1) == 0) ||
+ (LLStringUtil::compareInsensitive(url_in.substr(0, protocol2.length()), protocol2) == 0))
+ {
+ // TODO: Print out/log this attempt?
+ // llinfos << "Rejecting attempt to load restricted website :" << urlIn << llendl;
+ return;
+ }
+
+ if (ensureMediaSourceExists())
+ {
+ mCurrentNavUrl = url_in;
+ mMediaSource->setSize(mTextureWidth, mTextureHeight);
+ mMediaSource->navigateTo(url_in, mime_type, mime_type.empty());
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::string& filename_in )
+{
+ std::string language = LLUI::getLanguage();
+ std::string delim = gDirUtilp->getDirDelimiter();
+ std::string filename;
+
+ filename += subdir;
+ filename += delim;
+ filename += filename_in;
+
+ std::string expanded_filename = gDirUtilp->findSkinnedFilename("html", language, filename);
+
+ if (! gDirUtilp->fileExists(expanded_filename))
+ {
+ if (language != "en-us")
+ {
+ expanded_filename = gDirUtilp->findSkinnedFilename("html", "en-us", filename);
+ if (! gDirUtilp->fileExists(expanded_filename))
+ {
+ llwarns << "File " << subdir << delim << filename_in << "not found" << llendl;
+ return;
+ }
+ }
+ else
+ {
+ llwarns << "File " << subdir << delim << filename_in << "not found" << llendl;
+ return;
+ }
+ }
+ if (ensureMediaSourceExists())
+ {
+ mCurrentNavUrl = expanded_filename;
+ mMediaSource->setSize(mTextureWidth, mTextureHeight);
+ mMediaSource->navigateTo(expanded_filename, "text/html", false);
+ }
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::navigateHome()
+{
+ if (ensureMediaSourceExists())
+ {
+ mMediaSource->setSize(mTextureWidth, mTextureHeight);
+ mMediaSource->navigateHome();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::setHomePageUrl( const std::string urlIn )
+{
+ mHomePageUrl = urlIn;
+ if (mMediaSource)
+ {
+ mMediaSource->setHomeURL(mHomePageUrl);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+bool LLMediaCtrl::setCaretColor(unsigned int red, unsigned int green, unsigned int blue)
+{
+ //NOOP
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::setTextureSize(S32 width, S32 height)
+{
+ mTextureWidth = width;
+ mTextureHeight = height;
+
+ if(mMediaSource)
+ {
+ mMediaSource->setSize(mTextureWidth, mTextureHeight);
+ mForceUpdate = true;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+std::string LLMediaCtrl::getHomePageUrl()
+{
+ return mHomePageUrl;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+bool LLMediaCtrl::ensureMediaSourceExists()
+{
+ if(mMediaSource.isNull())
+ {
+ // If we don't already have a media source, try to create one.
+ mMediaSource = LLViewerMedia::newMediaImpl(mMediaTextureID, mTextureWidth, mTextureHeight);
+ if ( mMediaSource )
+ {
+ mMediaSource->setUsedInUI(true);
+ mMediaSource->setHomeURL(mHomePageUrl);
+ mMediaSource->setVisible( getVisible() );
+ mMediaSource->addObserver( this );
+ mMediaSource->setBackgroundColor( getBackgroundColor() );
+ if(mClearCache)
+ {
+ mMediaSource->clearCache();
+ mClearCache = false;
+ }
+
+ if(mHideLoading)
+ {
+ mHidingInitialLoad = true;
+ }
+ }
+ else
+ {
+ llwarns << "media source create failed " << llendl;
+ // return;
+ }
+ }
+
+ return !mMediaSource.isNull();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::unloadMediaSource()
+{
+ mMediaSource = NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+LLPluginClassMedia* LLMediaCtrl::getMediaPlugin()
+{
+ return mMediaSource.isNull() ? NULL : mMediaSource->getMediaPlugin();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::draw()
+{
+ if ( gRestoreGL == 1 )
+ {
+ LLRect r = getRect();
+ reshape( r.getWidth(), r.getHeight(), FALSE );
+ return;
+ }
+
+ // NOTE: optimization needed here - probably only need to do this once
+ // unless tearoffs change the parent which they probably do.
+ const LLUICtrl* ptr = findRootMostFocusRoot();
+ if ( ptr && ptr->hasFocus() )
+ {
+ setFrequentUpdates( true );
+ }
+ else
+ {
+ setFrequentUpdates( false );
+ };
+
+ bool draw_media = false;
+
+ LLPluginClassMedia* media_plugin = NULL;
+ LLViewerMediaTexture* media_texture = NULL;
+
+ if(mMediaSource && mMediaSource->hasMedia())
+ {
+ media_plugin = mMediaSource->getMediaPlugin();
+
+ if(media_plugin && (media_plugin->textureValid()))
+ {
+ media_texture = LLViewerTextureManager::findMediaTexture(mMediaTextureID);
+ if(media_texture)
+ {
+ draw_media = true;
+ }
+ }
+ }
+
+ if(mHidingInitialLoad)
+ {
+ // If we're hiding loading, don't draw at all.
+ draw_media = false;
+ }
+
+ bool background_visible = isBackgroundVisible();
+ bool background_opaque = isBackgroundOpaque();
+
+ if(draw_media)
+ {
+ // alpha off for this
+ LLGLSUIDefault gls_ui;
+ LLGLDisable gls_alphaTest( GL_ALPHA_TEST );
+
+ gGL.pushMatrix();
+ {
+ if (mIgnoreUIScale)
+ {
+ glLoadIdentity();
+ // font system stores true screen origin, need to scale this by UI scale factor
+ // to get render origin for this view (with unit scale)
+ gGL.translatef(floorf(LLFontGL::sCurOrigin.mX * LLUI::sGLScaleFactor.mV[VX]),
+ floorf(LLFontGL::sCurOrigin.mY * LLUI::sGLScaleFactor.mV[VY]),
+ LLFontGL::sCurOrigin.mZ);
+ }
+
+ // scale texture to fit the space using texture coords
+ gGL.getTexUnit(0)->bind(media_texture);
+ gGL.color4fv( LLColor4::white.mV );
+ F32 max_u = ( F32 )media_plugin->getWidth() / ( F32 )media_plugin->getTextureWidth();
+ F32 max_v = ( F32 )media_plugin->getHeight() / ( F32 )media_plugin->getTextureHeight();
+
+ LLRect r = getRect();
+ S32 width, height;
+ S32 x_offset = 0;
+ S32 y_offset = 0;
+
+ if(mStretchToFill)
+ {
+ if(mMaintainAspectRatio)
+ {
+ F32 media_aspect = (F32)(media_plugin->getWidth()) / (F32)(media_plugin->getHeight());
+ F32 view_aspect = (F32)(r.getWidth()) / (F32)(r.getHeight());
+ if(media_aspect > view_aspect)
+ {
+ // max width, adjusted height
+ width = r.getWidth();
+ height = llmin(llmax(llround(width / media_aspect), 0), r.getHeight());
+ }
+ else
+ {
+ // max height, adjusted width
+ height = r.getHeight();
+ width = llmin(llmax(llround(height * media_aspect), 0), r.getWidth());
+ }
+ }
+ else
+ {
+ width = r.getWidth();
+ height = r.getHeight();
+ }
+ }
+ else
+ {
+ width = llmin(media_plugin->getWidth(), r.getWidth());
+ height = llmin(media_plugin->getHeight(), r.getHeight());
+ }
+
+ x_offset = (r.getWidth() - width) / 2;
+ y_offset = (r.getHeight() - height) / 2;
+
+ if(mIgnoreUIScale)
+ {
+ x_offset = llround((F32)x_offset * LLUI::sGLScaleFactor.mV[VX]);
+ y_offset = llround((F32)y_offset * LLUI::sGLScaleFactor.mV[VY]);
+ width = llround((F32)width * LLUI::sGLScaleFactor.mV[VX]);
+ height = llround((F32)height * LLUI::sGLScaleFactor.mV[VY]);
+ }
+
+ // draw the browser
+ gGL.setSceneBlendType(LLRender::BT_REPLACE);
+ gGL.begin( LLRender::QUADS );
+ if (! media_plugin->getTextureCoordsOpenGL())
+ {
+ // render using web browser reported width and height, instead of trying to invert GL scale
+ gGL.texCoord2f( max_u, 0.f );
+ gGL.vertex2i( x_offset + width, y_offset + height );
+
+ gGL.texCoord2f( 0.f, 0.f );
+ gGL.vertex2i( x_offset, y_offset + height );
+
+ gGL.texCoord2f( 0.f, max_v );
+ gGL.vertex2i( x_offset, y_offset );
+
+ gGL.texCoord2f( max_u, max_v );
+ gGL.vertex2i( x_offset + width, y_offset );
+ }
+ else
+ {
+ // render using web browser reported width and height, instead of trying to invert GL scale
+ gGL.texCoord2f( max_u, max_v );
+ gGL.vertex2i( x_offset + width, y_offset + height );
+
+ gGL.texCoord2f( 0.f, max_v );
+ gGL.vertex2i( x_offset, y_offset + height );
+
+ gGL.texCoord2f( 0.f, 0.f );
+ gGL.vertex2i( x_offset, y_offset );
+
+ gGL.texCoord2f( max_u, 0.f );
+ gGL.vertex2i( x_offset + width, y_offset );
+ }
+ gGL.end();
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ }
+ gGL.popMatrix();
+
+ }
+ else
+ {
+ // Setting these will make LLPanel::draw draw the opaque background color.
+ setBackgroundVisible(true);
+ setBackgroundOpaque(true);
+ }
+
+ // highlight if keyboard focus here. (TODO: this needs some work)
+ if ( mBorder && mBorder->getVisible() )
+ mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus( this ) );
+
+
+ LLPanel::draw();
+
+ // Restore the previous values
+ setBackgroundVisible(background_visible);
+ setBackgroundOpaque(background_opaque);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::convertInputCoords(S32& x, S32& y)
+{
+ bool coords_opengl = false;
+
+ if(mMediaSource && mMediaSource->hasMedia())
+ {
+ coords_opengl = mMediaSource->getMediaPlugin()->getTextureCoordsOpenGL();
+ }
+
+ x = mIgnoreUIScale ? llround((F32)x * LLUI::sGLScaleFactor.mV[VX]) : x;
+ if ( ! coords_opengl )
+ {
+ y = mIgnoreUIScale ? llround((F32)(y) * LLUI::sGLScaleFactor.mV[VY]) : y;
+ }
+ else
+ {
+ y = mIgnoreUIScale ? llround((F32)(getRect().getHeight() - y) * LLUI::sGLScaleFactor.mV[VY]) : getRect().getHeight() - y;
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// inherited from LLViewerMediaObserver
+//virtual
+void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
+{
+ switch(event)
+ {
+ case MEDIA_EVENT_CONTENT_UPDATED:
+ {
+ // LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CONTENT_UPDATED " << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_TIME_DURATION_UPDATED:
+ {
+ // LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_TIME_DURATION_UPDATED, time is " << self->getCurrentTime() << " of " << self->getDuration() << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_SIZE_CHANGED:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_SIZE_CHANGED " << LL_ENDL;
+ LLRect r = getRect();
+ reshape( r.getWidth(), r.getHeight(), FALSE );
+ };
+ break;
+
+ case MEDIA_EVENT_CURSOR_CHANGED:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << LL_ENDL;
+ }
+ break;
+
+ case MEDIA_EVENT_NAVIGATE_BEGIN:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_BEGIN, url is " << self->getNavigateURI() << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_NAVIGATE_COMPLETE:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << LL_ENDL;
+ if(mHidingInitialLoad)
+ {
+ mHidingInitialLoad = false;
+ }
+ };
+ break;
+
+ case MEDIA_EVENT_PROGRESS_UPDATED:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PROGRESS_UPDATED, loading at " << self->getProgressPercent() << "%" << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_STATUS_TEXT_CHANGED:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_STATUS_TEXT_CHANGED, new status text is: " << self->getStatusText() << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_LOCATION_CHANGED:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_LOCATION_CHANGED, new uri is: " << self->getLocation() << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_CLICK_LINK_HREF:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL;
+ onClickLinkHref(self);
+ };
+ break;
+
+ case MEDIA_EVENT_CLICK_LINK_NOFOLLOW:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is " << self->getClickURL() << LL_ENDL;
+ onClickLinkNoFollow(self);
+ };
+ break;
+
+ case MEDIA_EVENT_PLUGIN_FAILED:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED" << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_NAME_CHANGED:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAME_CHANGED" << LL_ENDL;
+ };
+ break;
+ };
+
+ // chain all events to any potential observers of this object.
+ emitEvent(self, event);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::onClickLinkHref( LLPluginClassMedia* self )
+{
+ // retrieve the event parameters
+ std::string url = self->getClickURL();
+ U32 target_type = self->getClickTargetType();
+
+ // is there is a target specified for the link?
+ if (gSavedSettings.getBOOL("UseExternalBrowser") || target_type == LLPluginClassMedia::TARGET_EXTERNAL)
+ {
+ LLSD payload;
+ payload["url"] = url;
+ payload["target_type"] = LLSD::Integer(target_type);
+ LLNotificationsUtil::add( "WebLaunchExternalTarget", LLSD(), payload, onClickLinkExternalTarget);
+ }
+ else if (target_type == LLPluginClassMedia::TARGET_BLANK)
+ {
+ clickLinkWithTarget(url, target_type);
+ }
+ else {
+ const std::string protocol1( "http://" );
+ const std::string protocol2( "https://" );
+ if( mOpenLinksInExternalBrowser )
+ {
+ if ( !url.empty() )
+ {
+ if ( LLStringUtil::compareInsensitive( url.substr( 0, protocol1.length() ), protocol1 ) == 0 ||
+ LLStringUtil::compareInsensitive( url.substr( 0, protocol2.length() ), protocol2 ) == 0 )
+ {
+ LLWeb::loadURLExternal( url );
+ }
+ }
+ }
+ else
+ if( mOpenLinksInInternalBrowser )
+ {
+ if ( !url.empty() )
+ {
+ if ( LLStringUtil::compareInsensitive( url.substr( 0, protocol1.length() ), protocol1 ) == 0 ||
+ LLStringUtil::compareInsensitive( url.substr( 0, protocol2.length() ), protocol2 ) == 0 )
+ {
+ llwarns << "Dead, unimplemented path that we used to send to the built-in browser long ago." << llendl;
+ }
+ }
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLMediaCtrl::onClickLinkExternalTarget(const LLSD& notification, const LLSD& response )
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if ( 0 == option )
+ {
+ LLSD payload = notification["payload"];
+ std::string url = payload["url"].asString();
+ S32 target_type = payload["target_type"].asInteger();
+ clickLinkWithTarget(url, target_type);
+ }
+ return false;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLMediaCtrl::clickLinkWithTarget(const std::string& url, const S32& target_type )
+{
+ if (gSavedSettings.getBOOL("UseExternalBrowser") || target_type == LLPluginClassMedia::TARGET_EXTERNAL)
+ {
+ // load target in an external browser
+ LLWeb::loadURLExternal(url);
+ }
+ else if (target_type == LLPluginClassMedia::TARGET_BLANK)
+ {
+ // load target in the user's preferred browser
+ LLWeb::loadURL(url);
+ }
+ else {
+ // unsupported link target - shouldn't happen
+ LL_WARNS("LinkTarget") << "Unsupported link target type" << LL_ENDL;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaCtrl::onClickLinkNoFollow( LLPluginClassMedia* self )
+{
+ // let the dispatcher handle blocking/throttling of SLURLs
+ std::string url = self->getClickURL();
+ LLURLDispatcher::dispatch(url, this, mTrusted);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+std::string LLMediaCtrl::getCurrentNavUrl()
+{
+ return mCurrentNavUrl;
+}
+
diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h
new file mode 100644
index 0000000000..60e0c4073b
--- /dev/null
+++ b/indra/newview/llmediactrl.h
@@ -0,0 +1,201 @@
+/**
+ * @file llmediactrl.h
+ * @brief Web browser UI control
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ *
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLMediaCtrl_H
+#define LL_LLMediaCtrl_H
+
+#include "llviewermedia.h"
+
+#include "lluictrl.h"
+#include "llframetimer.h"
+
+class LLViewBorder;
+class LLUICtrlFactory;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+class LLMediaCtrl :
+ public LLPanel,
+ public LLViewerMediaObserver,
+ public LLViewerMediaEventEmitter
+{
+ LOG_CLASS(LLMediaCtrl);
+public:
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ Optional<std::string> start_url;
+
+ Optional<bool> border_visible,
+ ignore_ui_scale,
+ hide_loading,
+ decouple_texture_size;
+
+ Optional<S32> texture_width,
+ texture_height;
+
+ Optional<LLUIColor> caret_color;
+
+ Params();
+ };
+
+protected:
+ LLMediaCtrl(const Params&);
+ friend class LLUICtrlFactory;
+
+public:
+ virtual ~LLMediaCtrl();
+
+ void setBorderVisible( BOOL border_visible );
+
+ // For the tutorial window, we don't want to take focus on clicks,
+ // as the examples include how to move around with the arrow
+ // keys. Thus we keep focus on the app by setting this false.
+ // Defaults to true.
+ void setTakeFocusOnClick( bool take_focus );
+
+ // handle mouse related methods
+ virtual BOOL handleHover( S32 x, S32 y, MASK mask );
+ virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask );
+ virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );
+ virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
+ virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask );
+ virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
+
+ // navigation
+ void navigateTo( std::string url_in, std::string mime_type = "");
+ void navigateBack();
+ void navigateHome();
+ void navigateForward();
+ void navigateToLocalPage( const std::string& subdir, const std::string& filename_in );
+ bool canNavigateBack();
+ bool canNavigateForward();
+ void setOpenInExternalBrowser( bool valIn );
+ void setOpenInInternalBrowser( bool valIn );
+ std::string getCurrentNavUrl();
+
+ // By default, we do not handle "secondlife:///app/" SLURLs, because
+ // those can cause teleports, open windows, etc. We cannot be sure
+ // that each "click" is actually due to a user action, versus
+ // Javascript or some other mechanism. However, we need the search
+ // floater and login page to handle these URLs. Those are safe
+ // because we control the page content. See DEV-9530. JC.
+ void setTrusted( bool valIn );
+
+ void setHomePageUrl( const std::string urlIn );
+ std::string getHomePageUrl();
+
+ // set/clear URL to visit when a 404 page is reached
+ void set404RedirectUrl( std::string redirect_url );
+ void clr404RedirectUrl();
+
+ // Clear the browser cache when the instance gets loaded
+ void clearCache();
+
+ // accessor/mutator for flag that indicates if frequent updates to texture happen
+ bool getFrequentUpdates() { return mFrequentUpdates; };
+ void setFrequentUpdates( bool frequentUpdatesIn ) { mFrequentUpdates = frequentUpdatesIn; };
+
+ void setIgnoreUIScale(bool ignore) { mIgnoreUIScale = ignore; }
+ bool getIgnoreUIScale() { return mIgnoreUIScale; }
+
+ void setAlwaysRefresh(bool refresh) { mAlwaysRefresh = refresh; }
+ bool getAlwaysRefresh() { return mAlwaysRefresh; }
+
+ void setForceUpdate(bool force_update) { mForceUpdate = force_update; }
+ bool getForceUpdate() { return mForceUpdate; }
+
+ bool ensureMediaSourceExists();
+ void unloadMediaSource();
+
+ LLPluginClassMedia* getMediaPlugin();
+
+ bool setCaretColor( unsigned int red, unsigned int green, unsigned int blue );
+
+ void setDecoupleTextureSize(bool decouple) { mDecoupleTextureSize = decouple; }
+ bool getDecoupleTextureSize() { return mDecoupleTextureSize; }
+
+ void setTextureSize(S32 width, S32 height);
+
+
+ // over-rides
+ virtual BOOL handleKeyHere( KEY key, MASK mask);
+ virtual void handleVisibilityChange ( BOOL new_visibility );
+ virtual BOOL handleUnicodeCharHere(llwchar uni_char);
+ virtual void reshape( S32 width, S32 height, BOOL called_from_parent = TRUE);
+ virtual void draw();
+ virtual BOOL postBuild();
+
+ // focus overrides
+ void onFocusLost();
+ void onFocusReceived();
+
+ // Incoming media event dispatcher
+ virtual void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
+
+ // handlers for individual events (could be done inside the switch in handleMediaEvent, they're just individual functions for clarity)
+ void onClickLinkHref( LLPluginClassMedia* self );
+ void onClickLinkNoFollow( LLPluginClassMedia* self );
+
+ protected:
+ void convertInputCoords(S32& x, S32& y);
+
+ private:
+ void onVisibilityChange ( const LLSD& new_visibility );
+ static bool onClickLinkExternalTarget( const LLSD&, const LLSD& );
+ static void clickLinkWithTarget(const std::string& url, const S32& target_type );
+
+ const S32 mTextureDepthBytes;
+ LLUUID mMediaTextureID;
+ LLViewBorder* mBorder;
+ bool mFrequentUpdates;
+ bool mForceUpdate;
+ bool mOpenLinksInExternalBrowser;
+ bool mOpenLinksInInternalBrowser;
+ bool mTrusted;
+ std::string mHomePageUrl;
+ std::string mCurrentNavUrl;
+ bool mIgnoreUIScale;
+ bool mAlwaysRefresh;
+ viewer_media_t mMediaSource;
+ bool mTakeFocusOnClick;
+ bool mStretchToFill;
+ bool mMaintainAspectRatio;
+ bool mHideLoading;
+ bool mHidingInitialLoad;
+ bool mDecoupleTextureSize;
+ S32 mTextureWidth;
+ S32 mTextureHeight;
+ bool mClearCache;
+};
+
+#endif // LL_LLMediaCtrl_H
diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp
new file mode 100755
index 0000000000..b8da368bd7
--- /dev/null
+++ b/indra/newview/llmediadataclient.cpp
@@ -0,0 +1,812 @@
+/**
+ * @file llmediadataclient.cpp
+ * @brief class for queueing up requests for media data
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llmediadataclient.h"
+
+#if LL_MSVC
+// disable boost::lexical_cast warning
+#pragma warning (disable:4702)
+#endif
+
+#include <boost/lexical_cast.hpp>
+
+#include "llhttpstatuscodes.h"
+#include "llsdutil.h"
+#include "llmediaentry.h"
+#include "lltextureentry.h"
+#include "llviewerregion.h"
+
+//
+// When making a request
+// - obtain the "overall interest score" of the object.
+// This would be the sum of the impls' interest scores.
+// - put the request onto a queue sorted by this score
+// (highest score at the front of the queue)
+// - On a timer, once a second, pull off the head of the queue and send
+// the request.
+// - Any request that gets a 503 still goes through the retry logic
+//
+
+//
+// Forward decls
+//
+const F32 LLMediaDataClient::QUEUE_TIMER_DELAY = 1.0; // seconds(s)
+const F32 LLMediaDataClient::UNAVAILABLE_RETRY_TIMER_DELAY = 5.0; // secs
+const U32 LLMediaDataClient::MAX_RETRIES = 4;
+const U32 LLMediaDataClient::MAX_SORTED_QUEUE_SIZE = 10000;
+const U32 LLMediaDataClient::MAX_ROUND_ROBIN_QUEUE_SIZE = 10000;
+
+// << operators
+std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::request_queue_t &q);
+std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &q);
+
+//////////////////////////////////////////////////////////////////////////////////////
+//
+// LLMediaDataClient
+//
+//////////////////////////////////////////////////////////////////////////////////////
+
+LLMediaDataClient::LLMediaDataClient(F32 queue_timer_delay,
+ F32 retry_timer_delay,
+ U32 max_retries,
+ U32 max_sorted_queue_size,
+ U32 max_round_robin_queue_size)
+ : mQueueTimerDelay(queue_timer_delay),
+ mRetryTimerDelay(retry_timer_delay),
+ mMaxNumRetries(max_retries),
+ mMaxSortedQueueSize(max_sorted_queue_size),
+ mMaxRoundRobinQueueSize(max_round_robin_queue_size),
+ mQueueTimerIsRunning(false),
+ mCurrentQueueIsTheSortedQueue(true)
+{
+}
+
+LLMediaDataClient::~LLMediaDataClient()
+{
+ stopQueueTimer();
+
+ // This should clear the queue, and hopefully call all the destructors.
+ LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClient destructor: queue: " <<
+ (isEmpty() ? "<empty> " : "<not empty> ") << LL_ENDL;
+
+ mSortedQueue.clear();
+ mRoundRobinQueue.clear();
+}
+
+bool LLMediaDataClient::isEmpty() const
+{
+ return mSortedQueue.empty() && mRoundRobinQueue.empty();
+}
+
+bool LLMediaDataClient::isInQueue(const LLMediaDataClientObject::ptr_t &object)
+{
+ return (LLMediaDataClient::findOrRemove(mSortedQueue, object, false/*remove*/, LLMediaDataClient::Request::ANY).notNull()
+ || (LLMediaDataClient::findOrRemove(mRoundRobinQueue, object, false/*remove*/, LLMediaDataClient::Request::ANY).notNull()));
+}
+
+bool LLMediaDataClient::removeFromQueue(const LLMediaDataClientObject::ptr_t &object)
+{
+ bool removedFromSortedQueue = LLMediaDataClient::findOrRemove(mSortedQueue, object, true/*remove*/, LLMediaDataClient::Request::ANY).notNull();
+ bool removedFromRoundRobinQueue = LLMediaDataClient::findOrRemove(mRoundRobinQueue, object, true/*remove*/, LLMediaDataClient::Request::ANY).notNull();
+ return removedFromSortedQueue || removedFromRoundRobinQueue;
+}
+
+//static
+LLMediaDataClient::request_ptr_t LLMediaDataClient::findOrRemove(request_queue_t &queue, const LLMediaDataClientObject::ptr_t &obj, bool remove, LLMediaDataClient::Request::Type type)
+{
+ request_ptr_t result;
+ request_queue_t::iterator iter = queue.begin();
+ request_queue_t::iterator end = queue.end();
+ while (iter != end)
+ {
+ if (obj->getID() == (*iter)->getObject()->getID() && (type == LLMediaDataClient::Request::ANY || type == (*iter)->getType()))
+ {
+ result = *iter;
+ if (remove) queue.erase(iter);
+ break;
+ }
+ iter++;
+ }
+ return result;
+}
+
+void LLMediaDataClient::request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload)
+{
+ if (object.isNull() || ! object->hasMedia()) return;
+
+ // Push the object on the queue
+ enqueue(new Request(getCapabilityName(), payload, object, this));
+}
+
+void LLMediaDataClient::enqueue(const Request *request)
+{
+ if (request->isNew())
+ {
+ // Add to sorted queue
+ if (LLMediaDataClient::findOrRemove(mSortedQueue, request->getObject(), true/*remove*/, request->getType()).notNull())
+ {
+ LL_DEBUGS("LLMediaDataClient") << "REMOVING OLD request for " << *request << " ALREADY THERE!" << LL_ENDL;
+ }
+
+ LL_DEBUGS("LLMediaDataClient") << "Queuing SORTED request for " << *request << LL_ENDL;
+
+ // Sadly, we have to const-cast because items put into the queue are not const
+ mSortedQueue.push_back(const_cast<LLMediaDataClient::Request*>(request));
+
+ LL_DEBUGS("LLMediaDataClientQueue") << "SORTED queue:" << mSortedQueue << LL_ENDL;
+ }
+ else {
+ if (mRoundRobinQueue.size() > mMaxRoundRobinQueueSize)
+ {
+ LL_INFOS_ONCE("LLMediaDataClient") << "RR QUEUE MAXED OUT!!!" << LL_ENDL;
+ LL_DEBUGS("LLMediaDataClient") << "Not queuing " << *request << LL_ENDL;
+ return;
+ }
+
+ // ROUND ROBIN: if it is there, and it is a GET request, leave it. If not, put at front!
+ request_ptr_t existing_request;
+ if (request->getType() == Request::GET)
+ {
+ existing_request = LLMediaDataClient::findOrRemove(mRoundRobinQueue, request->getObject(), false/*remove*/, request->getType());
+ }
+ if (existing_request.isNull())
+ {
+ LL_DEBUGS("LLMediaDataClient") << "Queuing RR request for " << *request << LL_ENDL;
+ // Push the request on the pending queue
+ // Sadly, we have to const-cast because items put into the queue are not const
+ mRoundRobinQueue.push_front(const_cast<LLMediaDataClient::Request*>(request));
+
+ LL_DEBUGS("LLMediaDataClientQueue") << "RR queue:" << mRoundRobinQueue << LL_ENDL;
+ }
+ else
+ {
+ LL_DEBUGS("LLMediaDataClient") << "ALREADY THERE: NOT Queuing request for " << *request << LL_ENDL;
+
+ existing_request->markSent(false);
+ }
+ }
+ // Start the timer if not already running
+ startQueueTimer();
+}
+
+void LLMediaDataClient::startQueueTimer()
+{
+ if (! mQueueTimerIsRunning)
+ {
+ LL_DEBUGS("LLMediaDataClient") << "starting queue timer (delay=" << mQueueTimerDelay << " seconds)" << LL_ENDL;
+ // LLEventTimer automagically takes care of the lifetime of this object
+ new QueueTimer(mQueueTimerDelay, this);
+ }
+ else {
+ LL_DEBUGS("LLMediaDataClient") << "not starting queue timer (it's already running, right???)" << LL_ENDL;
+ }
+}
+
+void LLMediaDataClient::stopQueueTimer()
+{
+ mQueueTimerIsRunning = false;
+}
+
+bool LLMediaDataClient::processQueueTimer()
+{
+ sortQueue();
+
+ if(!isEmpty())
+ {
+ LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, SORTED queue size is: " << mSortedQueue.size()
+ << ", RR queue size is: " << mRoundRobinQueue.size() << LL_ENDL;
+ LL_DEBUGS("LLMediaDataClientQueue") << "QueueTimer::tick() started, SORTED queue is: " << mSortedQueue << LL_ENDL;
+ LL_DEBUGS("LLMediaDataClientQueue") << "QueueTimer::tick() started, RR queue is: " << mRoundRobinQueue << LL_ENDL;
+ }
+
+ serviceQueue();
+
+ LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, SORTED queue size is: " << mSortedQueue.size()
+ << ", RR queue size is: " << mRoundRobinQueue.size() << LL_ENDL;
+ LL_DEBUGS("LLMediaDataClientQueue") << "QueueTimer::tick() finished, SORTED queue is: " << mSortedQueue << LL_ENDL;
+ LL_DEBUGS("LLMediaDataClientQueue") << "QueueTimer::tick() finished, RR queue is: " << mRoundRobinQueue << LL_ENDL;
+
+ return isEmpty();
+}
+
+void LLMediaDataClient::sortQueue()
+{
+ if(!mSortedQueue.empty())
+ {
+ // Score all items first
+ request_queue_t::iterator iter = mSortedQueue.begin();
+ request_queue_t::iterator end = mSortedQueue.end();
+ while (iter != end)
+ {
+ (*iter)->updateScore();
+ iter++;
+ }
+
+ // Re-sort the list...
+ // NOTE: should this be a stable_sort? If so we need to change to using a vector.
+ mSortedQueue.sort(LLMediaDataClient::compareRequests);
+
+ // ...then cull items over the max
+ U32 size = mSortedQueue.size();
+ if (size > mMaxSortedQueueSize)
+ {
+ U32 num_to_cull = (size - mMaxSortedQueueSize);
+ LL_INFOS_ONCE("LLMediaDataClient") << "sorted queue MAXED OUT! Culling "
+ << num_to_cull << " items" << LL_ENDL;
+ while (num_to_cull-- > 0)
+ {
+ mSortedQueue.pop_back();
+ }
+ }
+ }
+}
+
+// static
+bool LLMediaDataClient::compareRequests(const request_ptr_t &o1, const request_ptr_t &o2)
+{
+ if (o2.isNull()) return true;
+ if (o1.isNull()) return false;
+ return ( o1->getScore() > o2->getScore() );
+}
+
+void LLMediaDataClient::serviceQueue()
+{
+ request_queue_t *queue_p = getCurrentQueue();
+
+ // quick retry loop for cases where we shouldn't wait for the next timer tick
+ while(true)
+ {
+ if (queue_p->empty())
+ {
+ LL_DEBUGS("LLMediaDataClient") << "queue empty: " << (*queue_p) << LL_ENDL;
+ break;
+ }
+
+ // Peel one off of the items from the queue, and execute request
+ request_ptr_t request = queue_p->front();
+ llassert(!request.isNull());
+ const LLMediaDataClientObject *object = (request.isNull()) ? NULL : request->getObject();
+ llassert(NULL != object);
+
+ // Check for conditions that would make us just pop and rapidly loop through
+ // the queue.
+ if(request.isNull() ||
+ request->isMarkedSent() ||
+ NULL == object ||
+ object->isDead() ||
+ !object->hasMedia())
+ {
+ if (request.isNull())
+ {
+ LL_WARNS("LLMediaDataClient") << "Skipping NULL request" << LL_ENDL;
+ }
+ else {
+ LL_INFOS("LLMediaDataClient") << "Skipping : " << *request << " "
+ << ((request->isMarkedSent()) ? " request is marked sent" :
+ ((NULL == object) ? " object is NULL " :
+ ((object->isDead()) ? "object is dead" :
+ ((!object->hasMedia()) ? "object has no media!" : "BADNESS!")))) << LL_ENDL;
+ }
+ queue_p->pop_front();
+ continue; // jump back to the start of the quick retry loop
+ }
+
+ // Next, ask if this is "interesting enough" to fetch. If not, just stop
+ // and wait for the next timer go-round. Only do this for the sorted
+ // queue.
+ if (mCurrentQueueIsTheSortedQueue && !object->isInterestingEnough())
+ {
+ LL_DEBUGS("LLMediaDataClient") << "Not fetching " << *request << ": not interesting enough" << LL_ENDL;
+ break;
+ }
+
+ // Finally, try to send the HTTP message to the cap url
+ std::string url = request->getCapability();
+ bool maybe_retry = false;
+ if (!url.empty())
+ {
+ const LLSD &sd_payload = request->getPayload();
+ LL_INFOS("LLMediaDataClient") << "Sending request for " << *request << LL_ENDL;
+
+ // Call the subclass for creating the responder
+ LLHTTPClient::post(url, sd_payload, createResponder(request));
+ }
+ else {
+ LL_INFOS("LLMediaDataClient") << "NOT Sending request for " << *request << ": empty cap url!" << LL_ENDL;
+ maybe_retry = true;
+ }
+
+ bool exceeded_retries = request->getRetryCount() > mMaxNumRetries;
+ if (maybe_retry && ! exceeded_retries) // Try N times before giving up
+ {
+ // We got an empty cap, but in that case we will retry again next
+ // timer fire.
+ request->incRetryCount();
+ }
+ else {
+ if (exceeded_retries)
+ {
+ LL_WARNS("LLMediaDataClient") << "Could not send request " << *request << " for "
+ << mMaxNumRetries << " tries...popping object id " << object->getID() << LL_ENDL;
+ // XXX Should we bring up a warning dialog??
+ }
+
+ queue_p->pop_front();
+
+ if (! mCurrentQueueIsTheSortedQueue) {
+ // Round robin
+ request->markSent(true);
+ mRoundRobinQueue.push_back(request);
+ }
+ }
+
+ // end of quick loop -- any cases where we want to loop will use 'continue' to jump back to the start.
+ break;
+ }
+
+ swapCurrentQueue();
+}
+
+void LLMediaDataClient::swapCurrentQueue()
+{
+ // Swap
+ mCurrentQueueIsTheSortedQueue = !mCurrentQueueIsTheSortedQueue;
+ // If its empty, swap back
+ if (getCurrentQueue()->empty())
+ {
+ mCurrentQueueIsTheSortedQueue = !mCurrentQueueIsTheSortedQueue;
+ }
+}
+
+LLMediaDataClient::request_queue_t *LLMediaDataClient::getCurrentQueue()
+{
+ return (mCurrentQueueIsTheSortedQueue) ? &mSortedQueue : &mRoundRobinQueue;
+}
+
+// dump the queue
+std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::request_queue_t &q)
+{
+ int i = 0;
+ LLMediaDataClient::request_queue_t::const_iterator iter = q.begin();
+ LLMediaDataClient::request_queue_t::const_iterator end = q.end();
+ while (iter != end)
+ {
+ s << "\t" << i << "]: " << (*iter)->getObject()->getID().asString() << "(" << (*iter)->getObject()->getMediaInterest() << ")";
+ iter++;
+ i++;
+ }
+ return s;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+//
+// LLMediaDataClient::QueueTimer
+// Queue of LLMediaDataClientObject smart pointers to request media for.
+//
+//////////////////////////////////////////////////////////////////////////////////////
+
+LLMediaDataClient::QueueTimer::QueueTimer(F32 time, LLMediaDataClient *mdc)
+: LLEventTimer(time), mMDC(mdc)
+{
+ mMDC->setIsRunning(true);
+}
+
+LLMediaDataClient::QueueTimer::~QueueTimer()
+{
+ LL_DEBUGS("LLMediaDataClient") << "~QueueTimer" << LL_ENDL;
+ mMDC->setIsRunning(false);
+ mMDC = NULL;
+}
+
+// virtual
+BOOL LLMediaDataClient::QueueTimer::tick()
+{
+ if (mMDC.isNull()) return TRUE;
+ return mMDC->processQueueTimer();
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+//
+// LLMediaDataClient::Responder::RetryTimer
+//
+//////////////////////////////////////////////////////////////////////////////////////
+
+LLMediaDataClient::Responder::RetryTimer::RetryTimer(F32 time, Responder *mdr)
+: LLEventTimer(time), mResponder(mdr)
+{
+}
+
+// virtual
+LLMediaDataClient::Responder::RetryTimer::~RetryTimer()
+{
+ LL_DEBUGS("LLMediaDataClient") << "~RetryTimer" << *(mResponder->getRequest()) << LL_ENDL;
+
+ // XXX This is weird: Instead of doing the work in tick() (which re-schedules
+ // a timer, which might be risky), do it here, in the destructor. Yes, it is very odd.
+ // Instead of retrying, we just put the request back onto the queue
+ LL_INFOS("LLMediaDataClient") << "RetryTimer fired for: " << *(mResponder->getRequest()) << " retrying" << LL_ENDL;
+ mResponder->getRequest()->reEnqueue();
+
+ // Release the ref to the responder.
+ mResponder = NULL;
+}
+
+// virtual
+BOOL LLMediaDataClient::Responder::RetryTimer::tick()
+{
+ // Don't fire again
+ return TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+//
+// LLMediaDataClient::Request
+//
+//////////////////////////////////////////////////////////////////////////////////////
+/*static*/U32 LLMediaDataClient::Request::sNum = 0;
+
+LLMediaDataClient::Request::Request(const char *cap_name,
+ const LLSD& sd_payload,
+ LLMediaDataClientObject *obj,
+ LLMediaDataClient *mdc)
+: mCapName(cap_name),
+ mPayload(sd_payload),
+ mObject(obj),
+ mNum(++sNum),
+ mRetryCount(0),
+ mMDC(mdc),
+ mMarkedSent(false),
+ mScore((F64)0.0)
+{
+}
+
+LLMediaDataClient::Request::~Request()
+{
+ LL_DEBUGS("LLMediaDataClient") << "~Request" << (*this) << LL_ENDL;
+ mMDC = NULL;
+ mObject = NULL;
+}
+
+
+std::string LLMediaDataClient::Request::getCapability() const
+{
+ return getObject()->getCapabilityUrl(getCapName());
+}
+
+// Helper function to get the "type" of request, which just pokes around to
+// discover it.
+LLMediaDataClient::Request::Type LLMediaDataClient::Request::getType() const
+{
+ if (0 == strcmp(mCapName, "ObjectMediaNavigate"))
+ {
+ return NAVIGATE;
+ }
+ else if (0 == strcmp(mCapName, "ObjectMedia"))
+ {
+ const std::string &verb = mPayload["verb"];
+ if (verb == "GET")
+ {
+ return GET;
+ }
+ else if (verb == "UPDATE")
+ {
+ return UPDATE;
+ }
+ }
+ llassert(false);
+ return GET;
+}
+
+const char *LLMediaDataClient::Request::getTypeAsString() const
+{
+ Type t = getType();
+ switch (t)
+ {
+ case GET:
+ return "GET";
+ break;
+ case UPDATE:
+ return "UPDATE";
+ break;
+ case NAVIGATE:
+ return "NAVIGATE";
+ break;
+ case ANY:
+ return "ANY";
+ break;
+ }
+ return "";
+}
+
+
+void LLMediaDataClient::Request::reEnqueue() const
+{
+ // I sure hope this doesn't deref a bad pointer:
+ mMDC->enqueue(this);
+}
+
+F32 LLMediaDataClient::Request::getRetryTimerDelay() const
+{
+ return (mMDC == NULL) ? LLMediaDataClient::UNAVAILABLE_RETRY_TIMER_DELAY :
+ mMDC->mRetryTimerDelay;
+}
+
+U32 LLMediaDataClient::Request::getMaxNumRetries() const
+{
+ return (mMDC == NULL) ? LLMediaDataClient::MAX_RETRIES : mMDC->mMaxNumRetries;
+}
+
+void LLMediaDataClient::Request::markSent(bool flag)
+{
+ if (mMarkedSent != flag)
+ {
+ mMarkedSent = flag;
+ if (!mMarkedSent)
+ {
+ mNum = ++sNum;
+ }
+ }
+}
+
+void LLMediaDataClient::Request::updateScore()
+{
+ F64 tmp = mObject->getMediaInterest();
+ if (tmp != mScore)
+ {
+ LL_DEBUGS("LLMediaDataClient") << "Score for " << mObject->getID() << " changed from " << mScore << " to " << tmp << LL_ENDL;
+ mScore = tmp;
+ }
+}
+
+std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &r)
+{
+ s << "request: num=" << r.getNum()
+ << " type=" << r.getTypeAsString()
+ << " ID=" << r.getObject()->getID()
+ << " #retries=" << r.getRetryCount();
+ return s;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+//
+// LLMediaDataClient::Responder
+//
+//////////////////////////////////////////////////////////////////////////////////////
+
+LLMediaDataClient::Responder::Responder(const request_ptr_t &request)
+: mRequest(request)
+{
+}
+
+LLMediaDataClient::Responder::~Responder()
+{
+ LL_DEBUGS("LLMediaDataClient") << "~Responder" << *(getRequest()) << LL_ENDL;
+ mRequest = NULL;
+}
+
+/*virtual*/
+void LLMediaDataClient::Responder::error(U32 status, const std::string& reason)
+{
+ if (status == HTTP_SERVICE_UNAVAILABLE)
+ {
+ F32 retry_timeout = mRequest->getRetryTimerDelay();
+
+ mRequest->incRetryCount();
+
+ if (mRequest->getRetryCount() < mRequest->getMaxNumRetries())
+ {
+ LL_INFOS("LLMediaDataClient") << *mRequest << " got SERVICE_UNAVAILABLE...retrying in " << retry_timeout << " seconds" << LL_ENDL;
+
+ // Start timer (instances are automagically tracked by
+ // InstanceTracker<> and LLEventTimer)
+ new RetryTimer(F32(retry_timeout/*secs*/), this);
+ }
+ else {
+ LL_INFOS("LLMediaDataClient") << *mRequest << " got SERVICE_UNAVAILABLE...retry count "
+ << mRequest->getRetryCount() << " exceeds " << mRequest->getMaxNumRetries() << ", not retrying" << LL_ENDL;
+ }
+ }
+ else {
+ std::string msg = boost::lexical_cast<std::string>(status) + ": " + reason;
+ LL_WARNS("LLMediaDataClient") << *mRequest << " http error(" << msg << ")" << LL_ENDL;
+ }
+}
+
+/*virtual*/
+void LLMediaDataClient::Responder::result(const LLSD& content)
+{
+ LL_DEBUGS("LLMediaDataClientResponse") << *mRequest << " result : " << ll_print_sd(content) << LL_ENDL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+//
+// LLObjectMediaDataClient
+// Subclass of LLMediaDataClient for the ObjectMedia cap
+//
+//////////////////////////////////////////////////////////////////////////////////////
+
+LLMediaDataClient::Responder *LLObjectMediaDataClient::createResponder(const request_ptr_t &request) const
+{
+ return new LLObjectMediaDataClient::Responder(request);
+}
+
+const char *LLObjectMediaDataClient::getCapabilityName() const
+{
+ return "ObjectMedia";
+}
+
+void LLObjectMediaDataClient::fetchMedia(LLMediaDataClientObject *object)
+{
+ LLSD sd_payload;
+ sd_payload["verb"] = "GET";
+ sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID();
+ request(object, sd_payload);
+}
+
+void LLObjectMediaDataClient::updateMedia(LLMediaDataClientObject *object)
+{
+ LLSD sd_payload;
+ sd_payload["verb"] = "UPDATE";
+ sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID();
+ LLSD object_media_data;
+ int i = 0;
+ int end = object->getMediaDataCount();
+ for ( ; i < end ; ++i)
+ {
+ object_media_data.append(object->getMediaDataLLSD(i));
+ }
+ sd_payload[LLTextureEntry::OBJECT_MEDIA_DATA_KEY] = object_media_data;
+
+ LL_DEBUGS("LLMediaDataClient") << "update media data: " << object->getID() << " " << ll_print_sd(sd_payload) << LL_ENDL;
+
+ request(object, sd_payload);
+}
+
+/*virtual*/
+void LLObjectMediaDataClient::Responder::result(const LLSD& content)
+{
+ const LLMediaDataClient::Request::Type type = getRequest()->getType();
+ llassert(type == LLMediaDataClient::Request::GET || type == LLMediaDataClient::Request::UPDATE)
+ if (type == LLMediaDataClient::Request::GET)
+ {
+ LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " GET returned: " << ll_print_sd(content) << LL_ENDL;
+
+ // Look for an error
+ if (content.has("error"))
+ {
+ const LLSD &error = content["error"];
+ LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error getting media data for object: code=" <<
+ error["code"].asString() << ": " << error["message"].asString() << LL_ENDL;
+
+ // XXX Warn user?
+ }
+ else {
+ // Check the data
+ const LLUUID &object_id = content[LLTextureEntry::OBJECT_ID_KEY];
+ if (object_id != getRequest()->getObject()->getID())
+ {
+ // NOT good, wrong object id!!
+ LL_WARNS("LLMediaDataClient") << *(getRequest()) << " DROPPING response with wrong object id (" << object_id << ")" << LL_ENDL;
+ return;
+ }
+
+ // Otherwise, update with object media data
+ getRequest()->getObject()->updateObjectMediaData(content[LLTextureEntry::OBJECT_MEDIA_DATA_KEY],
+ content[LLTextureEntry::MEDIA_VERSION_KEY]);
+ }
+ }
+ else if (type == LLMediaDataClient::Request::UPDATE)
+ {
+ // just do what our superclass does
+ LLMediaDataClient::Responder::result(content);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+//
+// LLObjectMediaNavigateClient
+// Subclass of LLMediaDataClient for the ObjectMediaNavigate cap
+//
+//////////////////////////////////////////////////////////////////////////////////////
+LLMediaDataClient::Responder *LLObjectMediaNavigateClient::createResponder(const request_ptr_t &request) const
+{
+ return new LLObjectMediaNavigateClient::Responder(request);
+}
+
+const char *LLObjectMediaNavigateClient::getCapabilityName() const
+{
+ return "ObjectMediaNavigate";
+}
+
+void LLObjectMediaNavigateClient::navigate(LLMediaDataClientObject *object, U8 texture_index, const std::string &url)
+{
+ LLSD sd_payload;
+ sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID();
+ sd_payload[LLMediaEntry::CURRENT_URL_KEY] = url;
+ sd_payload[LLTextureEntry::TEXTURE_INDEX_KEY] = (LLSD::Integer)texture_index;
+
+ LL_INFOS("LLMediaDataClient") << "navigate() initiated: " << ll_print_sd(sd_payload) << LL_ENDL;
+
+ request(object, sd_payload);
+}
+
+/*virtual*/
+void LLObjectMediaNavigateClient::Responder::error(U32 status, const std::string& reason)
+{
+ // Bounce back (unless HTTP_SERVICE_UNAVAILABLE, in which case call base
+ // class
+ if (status == HTTP_SERVICE_UNAVAILABLE)
+ {
+ LLMediaDataClient::Responder::error(status, reason);
+ }
+ else {
+ // bounce the face back
+ LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: http code=" << status << LL_ENDL;
+ const LLSD &payload = getRequest()->getPayload();
+ // bounce the face back
+ getRequest()->getObject()->mediaNavigateBounceBack((LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]);
+ }
+}
+
+/*virtual*/
+void LLObjectMediaNavigateClient::Responder::result(const LLSD& content)
+{
+ LL_INFOS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned " << ll_print_sd(content) << LL_ENDL;
+
+ if (content.has("error"))
+ {
+ const LLSD &error = content["error"];
+ int error_code = error["code"];
+
+ if (ERROR_PERMISSION_DENIED_CODE == error_code)
+ {
+ LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Navigation denied: bounce back" << LL_ENDL;
+ const LLSD &payload = getRequest()->getPayload();
+ // bounce the face back
+ getRequest()->getObject()->mediaNavigateBounceBack((LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]);
+ }
+ else {
+ LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: code=" <<
+ error["code"].asString() << ": " << error["message"].asString() << LL_ENDL;
+ }
+ // XXX Warn user?
+ }
+ else {
+ // just do what our superclass does
+ LLMediaDataClient::Responder::result(content);
+ }
+}
diff --git a/indra/newview/llmediadataclient.h b/indra/newview/llmediadataclient.h
new file mode 100755
index 0000000000..75d32e707b
--- /dev/null
+++ b/indra/newview/llmediadataclient.h
@@ -0,0 +1,340 @@
+/**
+ * @file llmediadataclient.h
+ * @brief class for queueing up requests to the media service
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLMEDIADATACLIENT_H
+#define LL_LLMEDIADATACLIENT_H
+
+#include "llhttpclient.h"
+#include <queue>
+#include "llrefcount.h"
+#include "llpointer.h"
+#include "lltimer.h"
+
+
+// Link seam for LLVOVolume
+class LLMediaDataClientObject : public LLRefCount
+{
+public:
+ // Get the number of media data items
+ virtual U8 getMediaDataCount() const = 0;
+ // Get the media data at index, as an LLSD
+ virtual LLSD getMediaDataLLSD(U8 index) const = 0;
+ // Get this object's UUID
+ virtual LLUUID getID() const = 0;
+ // Navigate back to previous URL
+ virtual void mediaNavigateBounceBack(U8 index) = 0;
+ // Does this object have media?
+ virtual bool hasMedia() const = 0;
+ // Update the object's media data to the given array
+ virtual void updateObjectMediaData(LLSD const &media_data_array, const std::string &version_string) = 0;
+ // Return the total "interest" of the media (on-screen area)
+ virtual F64 getMediaInterest() const = 0;
+ // Return the given cap url
+ virtual std::string getCapabilityUrl(const std::string &name) const = 0;
+ // Return whether the object has been marked dead
+ virtual bool isDead() const = 0;
+ // Returns a media version number for the object
+ virtual U32 getMediaVersion() const = 0;
+ // Returns whether the object is "interesting enough" to fetch
+ virtual bool isInterestingEnough() const = 0;
+ // Returns whether we've seen this object yet or not
+ virtual bool isNew() const = 0;
+
+ // smart pointer
+ typedef LLPointer<LLMediaDataClientObject> ptr_t;
+};
+
+// This object creates a priority queue for requests.
+// Abstracts the Cap URL, the request, and the responder
+class LLMediaDataClient : public LLRefCount
+{
+public:
+ LOG_CLASS(LLMediaDataClient);
+
+ const static F32 QUEUE_TIMER_DELAY;// = 1.0; // seconds(s)
+ const static F32 UNAVAILABLE_RETRY_TIMER_DELAY;// = 5.0; // secs
+ const static U32 MAX_RETRIES;// = 4;
+ const static U32 MAX_SORTED_QUEUE_SIZE;// = 10000;
+ const static U32 MAX_ROUND_ROBIN_QUEUE_SIZE;// = 10000;
+
+ // Constructor
+ LLMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
+ F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
+ U32 max_retries = MAX_RETRIES,
+ U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE,
+ U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE);
+
+ // Make the request
+ void request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload);
+
+ F32 getRetryTimerDelay() const { return mRetryTimerDelay; }
+
+ // Returns true iff the queue is empty
+ bool isEmpty() const;
+
+ // Returns true iff the given object is in the queue
+ bool isInQueue(const LLMediaDataClientObject::ptr_t &object);
+
+ // Remove the given object from the queue. Returns true iff the given object is removed.
+ bool removeFromQueue(const LLMediaDataClientObject::ptr_t &object);
+
+ // Called only by the Queue timer and tests (potentially)
+ bool processQueueTimer();
+
+protected:
+ // Destructor
+ virtual ~LLMediaDataClient(); // use unref
+
+ // Request
+ class Request : public LLRefCount
+ {
+ public:
+ enum Type {
+ GET,
+ UPDATE,
+ NAVIGATE,
+ ANY
+ };
+
+ Request(const char *cap_name, const LLSD& sd_payload, LLMediaDataClientObject *obj, LLMediaDataClient *mdc);
+ const char *getCapName() const { return mCapName; }
+ const LLSD &getPayload() const { return mPayload; }
+ LLMediaDataClientObject *getObject() const { return mObject; }
+
+ U32 getNum() const { return mNum; }
+
+ U32 getRetryCount() const { return mRetryCount; }
+ void incRetryCount() { mRetryCount++; }
+
+ // Note: may return empty string!
+ std::string getCapability() const;
+
+ Type getType() const;
+ const char *getTypeAsString() const;
+
+ // Re-enqueue thyself
+ void reEnqueue() const;
+
+ F32 getRetryTimerDelay() const;
+ U32 getMaxNumRetries() const;
+
+ bool isNew() const { return mObject.notNull() ? mObject->isNew() : false; }
+ void markSent(bool flag);
+ bool isMarkedSent() const { return mMarkedSent; }
+ void updateScore();
+ F64 getScore() const { return mScore; }
+
+ public:
+ friend std::ostream& operator<<(std::ostream &s, const Request &q);
+
+ protected:
+ virtual ~Request(); // use unref();
+
+ private:
+ const char *mCapName;
+ LLSD mPayload;
+ LLMediaDataClientObject::ptr_t mObject;
+ // Simple tracking
+ U32 mNum;
+ static U32 sNum;
+ U32 mRetryCount;
+ F64 mScore;
+ bool mMarkedSent;
+
+ // Back pointer to the MDC...not a ref!
+ LLMediaDataClient *mMDC;
+ };
+ typedef LLPointer<Request> request_ptr_t;
+
+ // Responder
+ class Responder : public LLHTTPClient::Responder
+ {
+ public:
+ Responder(const request_ptr_t &request);
+ //If we get back an error (not found, etc...), handle it here
+ virtual void error(U32 status, const std::string& reason);
+ //If we get back a normal response, handle it here. Default just logs it.
+ virtual void result(const LLSD& content);
+
+ const request_ptr_t &getRequest() const { return mRequest; }
+
+ protected:
+ virtual ~Responder();
+
+ private:
+
+ class RetryTimer : public LLEventTimer
+ {
+ public:
+ RetryTimer(F32 time, Responder *);
+ virtual ~RetryTimer();
+ virtual BOOL tick();
+ private:
+ // back-pointer
+ boost::intrusive_ptr<Responder> mResponder;
+ };
+
+ request_ptr_t mRequest;
+ };
+
+protected:
+
+ // Subclasses must override this factory method to return a new responder
+ virtual Responder *createResponder(const request_ptr_t &request) const = 0;
+
+ // Subclasses must override to return a cap name
+ virtual const char *getCapabilityName() const = 0;
+
+ virtual void sortQueue();
+ virtual void serviceQueue();
+
+private:
+ typedef std::list<request_ptr_t> request_queue_t;
+
+ void enqueue(const Request*);
+
+ // Return whether the given object is/was in the queue
+ static LLMediaDataClient::request_ptr_t findOrRemove(request_queue_t &queue, const LLMediaDataClientObject::ptr_t &obj, bool remove, Request::Type type);
+
+ // Comparator for sorting
+ static bool compareRequests(const request_ptr_t &o1, const request_ptr_t &o2);
+ static F64 getObjectScore(const LLMediaDataClientObject::ptr_t &obj);
+
+ friend std::ostream& operator<<(std::ostream &s, const Request &q);
+ friend std::ostream& operator<<(std::ostream &s, const request_queue_t &q);
+
+ class QueueTimer : public LLEventTimer
+ {
+ public:
+ QueueTimer(F32 time, LLMediaDataClient *mdc);
+ virtual BOOL tick();
+ protected:
+ virtual ~QueueTimer();
+ private:
+ // back-pointer
+ LLPointer<LLMediaDataClient> mMDC;
+ };
+
+ void startQueueTimer();
+ void stopQueueTimer();
+ void setIsRunning(bool val) { mQueueTimerIsRunning = val; }
+
+ void swapCurrentQueue();
+ request_queue_t *getCurrentQueue();
+
+ const F32 mQueueTimerDelay;
+ const F32 mRetryTimerDelay;
+ const U32 mMaxNumRetries;
+ const U32 mMaxSortedQueueSize;
+ const U32 mMaxRoundRobinQueueSize;
+
+ bool mQueueTimerIsRunning;
+
+ request_queue_t mSortedQueue;
+ request_queue_t mRoundRobinQueue;
+ bool mCurrentQueueIsTheSortedQueue;
+};
+
+
+// MediaDataClient specific for the ObjectMedia cap
+class LLObjectMediaDataClient : public LLMediaDataClient
+{
+public:
+ LLObjectMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
+ F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
+ U32 max_retries = MAX_RETRIES,
+ U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE,
+ U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE)
+ : LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries)
+ {}
+ virtual ~LLObjectMediaDataClient() {}
+
+ void fetchMedia(LLMediaDataClientObject *object);
+ void updateMedia(LLMediaDataClientObject *object);
+
+protected:
+ // Subclasses must override this factory method to return a new responder
+ virtual Responder *createResponder(const request_ptr_t &request) const;
+
+ // Subclasses must override to return a cap name
+ virtual const char *getCapabilityName() const;
+
+ class Responder : public LLMediaDataClient::Responder
+ {
+ public:
+ Responder(const request_ptr_t &request)
+ : LLMediaDataClient::Responder(request) {}
+ virtual void result(const LLSD &content);
+ };
+};
+
+
+// MediaDataClient specific for the ObjectMediaNavigate cap
+class LLObjectMediaNavigateClient : public LLMediaDataClient
+{
+public:
+ // NOTE: from llmediaservice.h
+ static const int ERROR_PERMISSION_DENIED_CODE = 8002;
+
+ LLObjectMediaNavigateClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
+ F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
+ U32 max_retries = MAX_RETRIES,
+ U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE,
+ U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE)
+ : LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries)
+ {}
+ virtual ~LLObjectMediaNavigateClient() {}
+
+ void navigate(LLMediaDataClientObject *object, U8 texture_index, const std::string &url);
+
+protected:
+ // Subclasses must override this factory method to return a new responder
+ virtual Responder *createResponder(const request_ptr_t &request) const;
+
+ // Subclasses must override to return a cap name
+ virtual const char *getCapabilityName() const;
+
+ class Responder : public LLMediaDataClient::Responder
+ {
+ public:
+ Responder(const request_ptr_t &request)
+ : LLMediaDataClient::Responder(request) {}
+ virtual void error(U32 status, const std::string& reason);
+ virtual void result(const LLSD &content);
+ private:
+ void mediaNavigateBounceBack();
+ };
+
+};
+
+
+#endif // LL_LLMEDIADATACLIENT_H
diff --git a/indra/newview/llmemoryview.cpp b/indra/newview/llmemoryview.cpp
index 215cc6940b..cbe4cef12f 100644
--- a/indra/newview/llmemoryview.cpp
+++ b/indra/newview/llmemoryview.cpp
@@ -32,37 +32,23 @@
#include "llviewerprecompiledheaders.h"
-#include "indra_constants.h"
#include "llmemoryview.h"
-#include "llrect.h"
-#include "llerror.h"
-#include "llgl.h"
-#include "llmath.h"
-#include "llfontgl.h"
-#include "llmemtype.h"
-
-#include "llcharacter.h"
-#include "llui.h"
+#include "llappviewer.h"
+#include "llallocator_heap_profile.h"
+#include "llgl.h" // LLGLSUIDefault
+#include "llviewerwindow.h"
#include "llviewercontrol.h"
-#include "llstat.h"
-
-#include "llfasttimer.h"
+#include <sstream>
+#include <boost/algorithm/string/split.hpp>
-LLMemoryView::LLMemoryView(const std::string& name, const LLRect& rect)
-: LLView(name, rect, TRUE),
-mDelay(120)
+LLMemoryView::LLMemoryView(const LLMemoryView::Params& p)
+: LLView(p),
+ //mDelay(120),
+ mAlloc(NULL)
{
- setVisible(FALSE);
- mDumpTimer.reset();
-
-#ifdef MEM_DUMP_DATA
- // clear out file.
- LLFILE *dump = LLFile::fopen("memusagedump.txt", "w");
- fclose(dump);
-#endif
}
LLMemoryView::~LLMemoryView()
@@ -94,62 +80,101 @@ BOOL LLMemoryView::handleHover(S32 x, S32 y, MASK mask)
return FALSE;
}
-//////////////////////////////////////////////////////////////////////////////
-
-struct mtv_display_info {
- S32 memtype;
- const char *desc;
- const LLColor4 *color;
-};
-
-static const LLColor4 red0(0.5f, 0.0f, 0.0f, 1.0f);
-
-static const struct mtv_display_info mtv_display_table[] =
+void LLMemoryView::refreshProfile()
{
- { LLMemType::MTYPE_INIT, "Init", &LLColor4::white },
- { LLMemType::MTYPE_STARTUP, "Startup", &LLColor4::cyan1 },
- { LLMemType::MTYPE_MAIN, "Main", &LLColor4::cyan2 },
- { LLMemType::MTYPE_IMAGEBASE, "ImageBase", &LLColor4::yellow1 },
- { LLMemType::MTYPE_IMAGERAW, "ImageRaw", &LLColor4::yellow2 },
- { LLMemType::MTYPE_IMAGEFORMATTED, "ImageFmtd", &LLColor4::yellow3 },
- { LLMemType::MTYPE_APPFMTIMAGE, "ViewerImageFmt", &LLColor4::orange1 },
- { LLMemType::MTYPE_APPRAWIMAGE, "ViewerImageRaw", &LLColor4::orange2 },
- { LLMemType::MTYPE_APPAUXRAWIMAGE, "ViewerImageAux", &LLColor4::orange3 },
- { LLMemType::MTYPE_DRAWABLE, "Drawable", &LLColor4::green1 },
- { LLMemType::MTYPE_OBJECT, "ViewerObject", &LLColor4::green2 },
- { LLMemType::MTYPE_PIPELINE, "Pipeline", &LLColor4::green3 },
- { LLMemType::MTYPE_PARTICLES, "Particles", &LLColor4::green4 },
- { LLMemType::MTYPE_SPACE_PARTITION, "Space Partition", &LLColor4::blue2 },
- { LLMemType::MTYPE_VERTEX_DATA, "Vertex Buffer", &LLColor4::blue3 },
- { LLMemType::MTYPE_AVATAR, "Avatar", &LLColor4::purple1 },
- { LLMemType::MTYPE_AVATAR_MESH, "Avatar Mesh", &LLColor4::purple2 },
- { LLMemType::MTYPE_ANIMATION, "Animation", &LLColor4::purple3 },
- { LLMemType::MTYPE_REGIONS, "Regions", &LLColor4::blue1 },
- { LLMemType::MTYPE_VOLUME, "Volume", &LLColor4::pink1 },
- { LLMemType::MTYPE_PRIMITIVE, "Profile", &LLColor4::pink2 },
- { LLMemType::MTYPE_TEMP1, "Temp1", &LLColor4::red1 },
- { LLMemType::MTYPE_TEMP2, "Temp2", &LLColor4::magenta1 },
- { LLMemType::MTYPE_TEMP3, "Temp3", &LLColor4::red2 },
- { LLMemType::MTYPE_TEMP4, "Temp4", &LLColor4::magenta2 },
- { LLMemType::MTYPE_TEMP5, "Temp5", &LLColor4::red3 },
- { LLMemType::MTYPE_TEMP6, "Temp6", &LLColor4::magenta3 },
- { LLMemType::MTYPE_TEMP7, "Temp7", &LLColor4::red4 },
- { LLMemType::MTYPE_TEMP8, "Temp8", &LLColor4::magenta4 },
-
- { LLMemType::MTYPE_OTHER, "Other", &red0 },
-};
-static const int MTV_DISPLAY_NUM = LL_ARRAY_SIZE(mtv_display_table);
+ /*
+ LLAllocator & alloc = LLAppViewer::instance()->getAllocator();
+ if(alloc.isProfiling()) {
+ std::string profile_text = alloc.getRawProfile();
+
+ boost::algorithm::split(mLines, profile_text, boost::bind(std::equal_to<llwchar>(), '\n', _1));
+ } else {
+ mLines.clear();
+ }
+ */
+ if (mAlloc == NULL) {
+ mAlloc = &LLAppViewer::instance()->getAllocator();
+ }
+
+ mLines.clear();
+
+ if(mAlloc->isProfiling())
+ {
+ const LLAllocatorHeapProfile &prof = mAlloc->getProfile();
+ for(size_t i = 0; i < prof.mLines.size(); ++i)
+ {
+ std::stringstream ss;
+ ss << "Unfreed Mem: " << (prof.mLines[i].mLiveSize >> 20) << " M Trace: ";
+ for(size_t k = 0; k < prof.mLines[i].mTrace.size(); ++k)
+ {
+ ss << LLMemType::getNameFromID(prof.mLines[i].mTrace[k]) << " ";
+ }
+ mLines.push_back(utf8string_to_wstring(ss.str()));
+ }
+ }
+}
void LLMemoryView::draw()
{
- std::string tdesc;
- S32 width = getRect().getWidth();
- S32 height = getRect().getHeight();
+ const S32 UPDATE_INTERVAL = 60;
+ const S32 MARGIN_AMT = 10;
+ static S32 curUpdate = UPDATE_INTERVAL;
+ static LLUIColor s_console_color = LLUIColorTable::instance().getColor("ConsoleBackground", LLColor4U::black);
+
+ // setup update interval
+ if (curUpdate >= UPDATE_INTERVAL)
+ {
+ refreshProfile();
+ curUpdate = 0;
+ }
+ curUpdate++;
+
+ // setup window properly
+ S32 height = (S32) (gViewerWindow->getWindowRectScaled().getHeight()*0.75f);
+ S32 width = (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.9f);
+ setRect(LLRect().setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height));
+ // setup window color
+ F32 console_opacity = llclamp(gSavedSettings.getF32("ConsoleBackgroundOpacity"), 0.f, 1.f);
+ LLColor4 color = s_console_color;
+ color.mV[VALPHA] *= console_opacity;
+
LLGLSUIDefault gls_ui;
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gl_rect_2d(0, height, width, 0, LLColor4(0.f, 0.f, 0.f, 0.25f));
+ gl_rect_2d(0, height, width, 0, color);
+ LLFontGL * font = LLFontGL::getFontSansSerifSmall();
+
+ // draw remaining lines
+ F32 y_pos = 0.f;
+ F32 y_off = 0.f;
+
+ F32 line_height = font->getLineHeight();
+ S32 target_width = width - 2 * MARGIN_AMT;
+
+ // cut off lines on bottom
+ U32 max_lines = U32((height - 2 * line_height) / line_height);
+ std::vector<LLWString>::const_iterator end = mLines.end();
+ if(mLines.size() > max_lines) {
+ end = mLines.begin() + max_lines;
+ }
+
+ y_pos = height - MARGIN_AMT - line_height;
+ y_off = 0.f;
+ for (std::vector<LLWString>::const_iterator i = mLines.begin(); i != end; ++i)
+ {
+ font->render(*i, 0, MARGIN_AMT, y_pos - y_off,
+ LLColor4::white,
+ LLFontGL::LEFT,
+ LLFontGL::BASELINE,
+ LLFontGL::NORMAL,
+ LLFontGL::DROP_SHADOW,
+ S32_MAX,
+ target_width
+ );
+ y_off += line_height;
+ }
+
#if MEM_TRACK_TYPE
S32 left, top, right, bottom;
@@ -267,40 +292,3 @@ void LLMemoryView::draw()
LLView::draw();
}
-
-void LLMemoryView::setDataDumpInterval(float delay)
-{
- mDelay = delay;
-}
-
-void LLMemoryView::dumpData()
-{
-#if MEM_TRACK_TYPE && MEM_DUMP_DATA
- if (mDelay && (mDumpTimer.getElapsedTimeF32() > mDelay ))
- {
- // reset timer
- mDumpTimer.reset();
- // append dump info to text file
- LLFILE *dump = LLFile::fopen("memusagedump.txt", "a");
-
- if (dump)
- {
- // write out total memory usage
- fprintf (dump, "Total memory in use = %09d (%03d MB)\n", LLMemType::sTotalMem, LLMemType::sTotalMem>>20);
- fprintf (dump, "High Water Mark = %09d (%03d MB)\n\n", LLMemType::sMaxTotalMem, LLMemType::sMaxTotalMem>>20);
- // dump out usage of 'new' for each memory type
- for (S32 i=0; i<LLMemType::MTYPE_NUM_TYPES; i++)
- {
- if (LLMemType::sMemCount[i])
- {
- std::string outData = llformat("MEM: % 20s %09d %03d MB (%09d %03d MB) in %06d News", LLMemType::sTypeDesc[i], LLMemType::sMemCount[i], LLMemType::sMemCount[i]>>20, LLMemType::sMaxMemCount[i], LLMemType::sMaxMemCount[i]>>20, LLMemType::sNewCount[i]);
- fprintf (dump, "%s\n", outData.c_str());
- }
- }
- fprintf (dump, "\n\n");
-
- fclose(dump);
- }
- }
-#endif
-}
diff --git a/indra/newview/llmemoryview.h b/indra/newview/llmemoryview.h
index 81466bd6b0..774a52b88b 100644
--- a/indra/newview/llmemoryview.h
+++ b/indra/newview/llmemoryview.h
@@ -35,10 +35,20 @@
#include "llview.h"
+class LLAllocator;
+
class LLMemoryView : public LLView
{
public:
- LLMemoryView(const std::string& name, const LLRect& rect);
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
+ {
+ Params()
+ {
+ mouse_opaque = true;
+ visible = false;
+ }
+ };
+ LLMemoryView(const LLMemoryView::Params&);
virtual ~LLMemoryView();
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
@@ -46,14 +56,12 @@ public:
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual void draw();
-private:
- void setDataDumpInterval(float delay);
- void dumpData();
-
- float mDelay;
- LLFrameTimer mDumpTimer;
+ void refreshProfile();
private:
+ std::vector<LLWString> mLines;
+ LLAllocator* mAlloc;
+
};
#endif
diff --git a/indra/newview/llmenucommands.cpp b/indra/newview/llmenucommands.cpp
index ac77a920a5..8d950f072d 100644
--- a/indra/newview/llmenucommands.cpp
+++ b/indra/newview/llmenucommands.cpp
@@ -35,6 +35,7 @@
#include "llmenucommands.h"
#include "imageids.h"
+#include "llfloaterreg.h"
#include "llfontgl.h"
#include "llrect.h"
#include "llerror.h"
@@ -43,16 +44,10 @@
#include "llagent.h"
#include "llcallingcard.h"
-#include "llchatbar.h"
#include "llviewercontrol.h"
-#include "llfirstuse.h"
-#include "llfloaterchat.h"
-#include "llfloaterdirectory.h"
-#include "llfloatermap.h"
+//#include "llfirstuse.h"
#include "llfloaterworldmap.h"
-#include "llgivemoney.h"
-#include "llinventoryview.h"
-#include "llnotify.h"
+#include "lllineeditor.h"
#include "llstatusbar.h"
#include "llimview.h"
#include "lltextbox.h"
@@ -67,20 +62,7 @@
#include "llworld.h"
#include "llworldmap.h"
#include "llfocusmgr.h"
-
-void handle_track_avatar(const LLUUID& agent_id, const std::string& name)
-{
- LLAvatarTracker::instance().track(agent_id, name);
-
- LLFloaterDirectory::hide(NULL);
- LLFloaterWorldMap::show(NULL, TRUE);
-}
-
-void handle_pay_by_id(const LLUUID& agent_id)
-{
- const BOOL is_group = FALSE;
- LLFloaterPay::payDirectly(&give_money, agent_id, is_group);
-}
+#include "llnearbychatbar.h"
void handle_mouselook(void*)
{
@@ -88,55 +70,23 @@ void handle_mouselook(void*)
}
-void handle_map(void*)
-{
- LLFloaterWorldMap::toggle(NULL);
-}
-
-void handle_mini_map(void*)
-{
- LLFloaterMap::toggleInstance();
-}
-
-
-void handle_find(void*)
-{
- LLFloaterDirectory::toggleFind(NULL);
-}
-
-
-void handle_events(void*)
-{
- LLFloaterDirectory::toggleEvents(NULL);
-}
-
-
-void handle_inventory(void*)
-{
- // We're using the inventory, possibly for the
- // first time.
- LLFirstUse::useInventory();
-
- LLInventoryView::toggleVisibility(NULL);
-}
-
-
void handle_chat(void*)
{
// give focus to chatbar if it's open but not focused
- if (gSavedSettings.getBOOL("ChatVisible") && gFocusMgr.childHasKeyboardFocus(gChatBar))
+ if (gSavedSettings.getBOOL("ChatVisible") &&
+ gFocusMgr.childHasKeyboardFocus(LLNearbyChatBar::getInstance()->getChatBox()))
{
- LLChatBar::stopChat();
+ LLNearbyChatBar::stopChat();
}
else
{
- LLChatBar::startChat(NULL);
+ LLNearbyChatBar::startChat(NULL);
}
}
void handle_slash_key(void*)
{
- // LLChatBar::startChat("/");
+ // LLBottomTray::startChat("/");
//
// Don't do this, it results in a double-slash in the input field.
// Another "/" will be automatically typed for us, because the WM_KEYDOWN event
@@ -146,5 +96,5 @@ void handle_slash_key(void*)
// menu accelerators that put input focus into a field. And Mac works
// the same way. JC
- LLChatBar::startChat(NULL);
+ LLNearbyChatBar::startChat(NULL);
}
diff --git a/indra/newview/llmenucommands.h b/indra/newview/llmenucommands.h
index 03f7a2571c..a3611ef6d1 100644
--- a/indra/newview/llmenucommands.h
+++ b/indra/newview/llmenucommands.h
@@ -35,14 +35,7 @@
class LLUUID;
-void handle_track_avatar(const LLUUID& agent_id, const std::string& name);
-void handle_pay_by_id(const LLUUID& agent_id);
void handle_mouselook(void*);
-void handle_map(void*);
-void handle_mini_map(void*);
-void handle_find(void*);
-void handle_events(void*);
-void handle_inventory(void*);
void handle_chat(void*);
void handle_return_key(void*);
void handle_slash_key(void*);
diff --git a/indra/newview/llmetricperformancetester.cpp b/indra/newview/llmetricperformancetester.cpp
new file mode 100644
index 0000000000..93288c98d7
--- /dev/null
+++ b/indra/newview/llmetricperformancetester.cpp
@@ -0,0 +1,258 @@
+/**
+ * @file llmetricperformancetester.cpp
+ * @brief LLMetricPerformanceTester class implementation
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "indra_constants.h"
+#include "llerror.h"
+#include "llmath.h"
+#include "llfontgl.h"
+#include "llsdserialize.h"
+#include "llstat.h"
+#include "lltreeiterators.h"
+#include "llmetricperformancetester.h"
+
+LLMetricPerformanceTester::name_tester_map_t LLMetricPerformanceTester::sTesterMap ;
+
+//static
+void LLMetricPerformanceTester::initClass()
+{
+}
+//static
+void LLMetricPerformanceTester::cleanClass()
+{
+ for(name_tester_map_t::iterator iter = sTesterMap.begin() ; iter != sTesterMap.end() ; ++iter)
+ {
+ delete iter->second ;
+ }
+ sTesterMap.clear() ;
+}
+
+//static
+void LLMetricPerformanceTester::addTester(LLMetricPerformanceTester* tester)
+{
+ if(!tester)
+ {
+ llerrs << "invalid tester!" << llendl ;
+ return ;
+ }
+
+ std::string name = tester->getName() ;
+ if(getTester(name))
+ {
+ llerrs << "Tester name is used by some other tester: " << name << llendl ;
+ return ;
+ }
+
+ sTesterMap.insert(std::make_pair(name, tester));
+
+ return ;
+}
+
+//static
+LLMetricPerformanceTester* LLMetricPerformanceTester::getTester(std::string label)
+{
+ name_tester_map_t::iterator found_it = sTesterMap.find(label) ;
+ if(found_it != sTesterMap.end())
+ {
+ return found_it->second ;
+ }
+
+ return NULL ;
+}
+
+LLMetricPerformanceTester::LLMetricPerformanceTester(std::string name, BOOL use_default_performance_analysis)
+ : mName(name),
+ mBaseSessionp(NULL),
+ mCurrentSessionp(NULL),
+ mCount(0),
+ mUseDefaultPerformanceAnalysis(use_default_performance_analysis)
+{
+ if(mName == std::string())
+ {
+ llerrs << "invalid name." << llendl ;
+ }
+
+ LLMetricPerformanceTester::addTester(this) ;
+}
+
+/*virtual*/
+LLMetricPerformanceTester::~LLMetricPerformanceTester()
+{
+ if(mBaseSessionp)
+ {
+ delete mBaseSessionp ;
+ mBaseSessionp = NULL ;
+ }
+ if(mCurrentSessionp)
+ {
+ delete mCurrentSessionp ;
+ mCurrentSessionp = NULL ;
+ }
+}
+
+void LLMetricPerformanceTester::incLabel()
+{
+ mCurLabel = llformat("%s-%d", mName.c_str(), mCount++) ;
+}
+void LLMetricPerformanceTester::preOutputTestResults(LLSD* sd)
+{
+ incLabel() ;
+ (*sd)[mCurLabel]["Name"] = mName ;
+}
+void LLMetricPerformanceTester::postOutputTestResults(LLSD* sd)
+{
+ LLMutexLock lock(LLFastTimer::sLogLock);
+ LLFastTimer::sLogQueue.push((*sd));
+}
+
+void LLMetricPerformanceTester::outputTestResults()
+{
+ LLSD sd ;
+ preOutputTestResults(&sd) ;
+
+ outputTestRecord(&sd) ;
+
+ postOutputTestResults(&sd) ;
+}
+
+void LLMetricPerformanceTester::addMetricString(std::string str)
+{
+ mMetricStrings.push_back(str) ;
+}
+
+const std::string& LLMetricPerformanceTester::getMetricString(U32 index) const
+{
+ return mMetricStrings[index] ;
+}
+
+void LLMetricPerformanceTester::prePerformanceAnalysis()
+{
+ mCount = 0 ;
+ incLabel() ;
+}
+
+//
+//default analyzing the performance
+//
+/*virtual*/
+void LLMetricPerformanceTester::analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current)
+{
+ if(mUseDefaultPerformanceAnalysis)//use default performance analysis
+ {
+ prePerformanceAnalysis() ;
+
+ BOOL in_base = (*base).has(mCurLabel) ;
+ BOOL in_current = (*current).has(mCurLabel) ;
+
+ while(in_base || in_current)
+ {
+ LLSD::String label = mCurLabel ;
+
+ if(in_base && in_current)
+ {
+ *os << llformat("%s\n", label.c_str()) ;
+
+ for(U32 index = 0 ; index < mMetricStrings.size() ; index++)
+ {
+ switch((*current)[label][ mMetricStrings[index] ].type())
+ {
+ case LLSD::TypeInteger:
+ compareTestResults(os, mMetricStrings[index],
+ (S32)((*base)[label][ mMetricStrings[index] ].asInteger()), (S32)((*current)[label][ mMetricStrings[index] ].asInteger())) ;
+ break ;
+ case LLSD::TypeReal:
+ compareTestResults(os, mMetricStrings[index],
+ (F32)((*base)[label][ mMetricStrings[index] ].asReal()), (F32)((*current)[label][ mMetricStrings[index] ].asReal())) ;
+ break;
+ default:
+ llerrs << "unsupported metric " << mMetricStrings[index] << " LLSD type: " << (S32)(*current)[label][ mMetricStrings[index] ].type() << llendl ;
+ }
+ }
+ }
+
+ incLabel() ;
+ in_base = (*base).has(mCurLabel) ;
+ in_current = (*current).has(mCurLabel) ;
+ }
+ }//end of default
+ else
+ {
+ //load the base session
+ prePerformanceAnalysis() ;
+ mBaseSessionp = loadTestSession(base) ;
+
+ //load the current session
+ prePerformanceAnalysis() ;
+ mCurrentSessionp = loadTestSession(current) ;
+
+ if(!mBaseSessionp || !mCurrentSessionp)
+ {
+ llerrs << "memory error during loading test sessions." << llendl ;
+ }
+
+ //compare
+ compareTestSessions(os) ;
+
+ //release memory
+ if(mBaseSessionp)
+ {
+ delete mBaseSessionp ;
+ mBaseSessionp = NULL ;
+ }
+ if(mCurrentSessionp)
+ {
+ delete mCurrentSessionp ;
+ mCurrentSessionp = NULL ;
+ }
+ }
+}
+
+//virtual
+void LLMetricPerformanceTester::compareTestResults(std::ofstream* os, std::string metric_string, S32 v_base, S32 v_current)
+{
+ *os << llformat(" ,%s, %d, %d, %d, %.4f\n", metric_string.c_str(), v_base, v_current,
+ v_current - v_base, (v_base != 0) ? 100.f * v_current / v_base : 0) ;
+}
+
+//virtual
+void LLMetricPerformanceTester::compareTestResults(std::ofstream* os, std::string metric_string, F32 v_base, F32 v_current)
+{
+ *os << llformat(" ,%s, %.4f, %.4f, %.4f, %.4f\n", metric_string.c_str(), v_base, v_current,
+ v_current - v_base, (fabs(v_base) > 0.0001f) ? 100.f * v_current / v_base : 0.f ) ;
+}
+
+//virtual
+LLMetricPerformanceTester::LLTestSession::~LLTestSession()
+{
+}
+
diff --git a/indra/newview/llmetricperformancetester.h b/indra/newview/llmetricperformancetester.h
new file mode 100644
index 0000000000..ab5ccaeb8e
--- /dev/null
+++ b/indra/newview/llmetricperformancetester.h
@@ -0,0 +1,159 @@
+/**
+ * @file LLMetricPerformanceTester.h
+ * @brief LLMetricPerformanceTester class definition
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_METRICPERFORMANCETESTER_H
+#define LL_METRICPERFORMANCETESTER_H
+
+class LLMetricPerformanceTester
+{
+public:
+ //
+ //name passed to the constructor is a unique string for each tester.
+ //an error is reported if the name is already used by some other tester.
+ //
+ LLMetricPerformanceTester(std::string name, BOOL use_default_performance_analysis) ;
+ virtual ~LLMetricPerformanceTester();
+
+ //
+ //return the name of the tester
+ //
+ std::string getName() const { return mName ;}
+ //
+ //return the number of the test metrics in this tester
+ //
+ S32 getNumOfMetricStrings() const { return mMetricStrings.size() ;}
+ //
+ //return the metric string at the index
+ //
+ const std::string& getMetricString(U32 index) const ;
+
+ //
+ //this function to compare the test results.
+ //by default, it compares the test results against the baseline one by one, item by item,
+ //in the increasing order of the LLSD label counter, starting from the first one.
+ //you can define your own way to analyze performance by passing FALSE to "use_default_performance_analysis",
+ //and implement two abstract virtual functions below: loadTestSession(...) and compareTestSessions(...).
+ //
+ void analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) ;
+
+protected:
+ //
+ //insert metric strings used in the tester.
+ //
+ void addMetricString(std::string str) ;
+
+ //
+ //increase LLSD label by 1
+ //
+ void incLabel() ;
+
+ //
+ //the function to write a set of test results to the log LLSD.
+ //
+ void outputTestResults() ;
+
+ //
+ //compare the test results.
+ //you can write your own to overwrite the default one.
+ //
+ virtual void compareTestResults(std::ofstream* os, std::string metric_string, S32 v_base, S32 v_current) ;
+ virtual void compareTestResults(std::ofstream* os, std::string metric_string, F32 v_base, F32 v_current) ;
+
+ //
+ //for performance analysis use
+ //it defines an interface for the two abstract virtual functions loadTestSession(...) and compareTestSessions(...).
+ //please make your own test session class derived from it.
+ //
+ class LLTestSession
+ {
+ public:
+ virtual ~LLTestSession() ;
+ };
+
+ //
+ //load a test session for log LLSD
+ //you need to implement it only when you define your own way to analyze performance.
+ //otherwise leave it empty.
+ //
+ virtual LLMetricPerformanceTester::LLTestSession* loadTestSession(LLSD* log) = 0 ;
+ //
+ //compare the base session and the target session
+ //you need to implement it only when you define your own way to analyze performance.
+ //otherwise leave it empty.
+ //
+ virtual void compareTestSessions(std::ofstream* os) = 0 ;
+ //
+ //the function to write a set of test results to the log LLSD.
+ //you have to write you own version of this function.
+ //
+ virtual void outputTestRecord(LLSD* sd) = 0 ;
+
+private:
+ void preOutputTestResults(LLSD* sd) ;
+ void postOutputTestResults(LLSD* sd) ;
+ void prePerformanceAnalysis() ;
+
+protected:
+ //
+ //the unique name string of the tester
+ //
+ std::string mName ;
+ //
+ //the current label counter for the log LLSD
+ //
+ std::string mCurLabel ;
+ S32 mCount ;
+
+ BOOL mUseDefaultPerformanceAnalysis ;
+ LLTestSession* mBaseSessionp ;
+ LLTestSession* mCurrentSessionp ;
+
+ //metrics strings
+ std::vector< std::string > mMetricStrings ;
+
+//static members
+private:
+ static void addTester(LLMetricPerformanceTester* tester) ;
+
+public:
+ typedef std::map< std::string, LLMetricPerformanceTester* > name_tester_map_t;
+ static name_tester_map_t sTesterMap ;
+
+ static LLMetricPerformanceTester* getTester(std::string label) ;
+ static BOOL hasMetricPerformanceTesters() {return !sTesterMap.empty() ;}
+
+ static void initClass() ;
+ static void cleanClass() ;
+};
+
+#endif
+
diff --git a/indra/newview/llmimetypes.cpp b/indra/newview/llmimetypes.cpp
index bfbc81aa66..235487cf46 100644
--- a/indra/newview/llmimetypes.cpp
+++ b/indra/newview/llmimetypes.cpp
@@ -34,6 +34,7 @@
#include "llviewerprecompiledheaders.h"
#include "llmimetypes.h"
+#include "llxmlnode.h"
#include "lluictrlfactory.h"
@@ -46,6 +47,8 @@ std::string sDefaultWidgetType;
// Returned when we don't know what widget set to use
std::string sDefaultImpl;
// Returned when we don't know what impl to use
+std::string sXMLFilename;
+ // Squirrel away XML filename so we know how to reset
/////////////////////////////////////////////////////////////////////////////
@@ -146,6 +149,8 @@ bool LLMIMETypes::parseMIMETypes(const std::string& xml_filename)
sWidgetMap[set_name] = info;
}
}
+
+ sXMLFilename = xml_filename;
return true;
}
@@ -267,3 +272,23 @@ bool LLMIMETypes::findAllowLooping(const std::string& mime_type)
}
return allow_looping;
}
+
+// static
+bool LLMIMETypes::isTypeHandled(const std::string& mime_type)
+{
+ mime_info_map_t::const_iterator it = sMap.find(mime_type);
+ if (it != sMap.end())
+ {
+ return true;
+ }
+ return false;
+}
+
+// static
+void LLMIMETypes::reload(void*)
+{
+ sMap.clear();
+ sWidgetMap.clear();
+ (void)LLMIMETypes::parseMIMETypes(sXMLFilename);
+}
+
diff --git a/indra/newview/llmimetypes.h b/indra/newview/llmimetypes.h
index 7a50c29429..b217ce7a81 100644
--- a/indra/newview/llmimetypes.h
+++ b/indra/newview/llmimetypes.h
@@ -72,6 +72,12 @@ public:
static bool findAllowLooping(const std::string& mime_type);
// accessor for flag to enable/disable media looping checkbox
+ static bool isTypeHandled(const std::string& mime_type);
+ // determines if the specific mime type is handled by the media system
+
+ static void reload(void*);
+ // re-loads the MIME types file from the file path last passed into parseMIMETypes
+
public:
struct LLMIMEInfo
{
diff --git a/indra/newview/llmorphview.cpp b/indra/newview/llmorphview.cpp
index 18fd20d12a..b95e8bd3a2 100644
--- a/indra/newview/llmorphview.cpp
+++ b/indra/newview/llmorphview.cpp
@@ -40,14 +40,14 @@
#include "lldrawable.h"
#include "lldrawpoolavatar.h"
#include "llface.h"
-#include "llfirstuse.h"
+//#include "llfirstuse.h"
#include "llfloatercustomize.h"
#include "llfloatertools.h"
#include "llresmgr.h"
#include "lltoolmgr.h"
#include "lltoolmorph.h"
#include "llviewercamera.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "llviewerwindow.h"
#include "pipeline.h"
@@ -67,9 +67,8 @@ const F32 CAMERA_DIST_STEP = 1.5f;
//-----------------------------------------------------------------------------
// LLMorphView()
//-----------------------------------------------------------------------------
-LLMorphView::LLMorphView(const std::string& name, const LLRect& rect)
- :
- LLView(name, rect, FALSE, FOLLOWS_ALL),
+LLMorphView::LLMorphView(const LLMorphView::Params& p)
+: LLView(p),
mCameraTargetJoint( NULL ),
mCameraOffset(-0.5f, 0.05f, 0.07f ),
mCameraTargetOffset(0.f, 0.f, 0.05f ),
@@ -78,8 +77,7 @@ LLMorphView::LLMorphView(const std::string& name, const LLRect& rect)
mCameraYaw( 0.f ),
mCameraDist( -1.f ),
mCameraDrivenByKeys( FALSE )
-{
-}
+{}
//-----------------------------------------------------------------------------
// initialize()
@@ -110,7 +108,7 @@ void LLMorphView::initialize()
//-----------------------------------------------------------------------------
void LLMorphView::shutdown()
{
- LLVOAvatar::onCustomizeEnd();
+ LLVOAvatarSelf::onCustomizeEnd();
LLVOAvatar *avatarp = gAgent.getAvatarObject();
if(avatarp && !avatarp->isDead())
@@ -137,7 +135,7 @@ void LLMorphView::setVisible(BOOL visible)
llassert( !gFloaterCustomize );
gFloaterCustomize = new LLFloaterCustomize();
gFloaterCustomize->fetchInventory();
- gFloaterCustomize->open(); /*Flawfinder: ignore*/
+ gFloaterCustomize->openFloater();
// Must do this _after_ gFloaterView is initialized.
gFloaterCustomize->switchToDefaultSubpart();
@@ -145,7 +143,7 @@ void LLMorphView::setVisible(BOOL visible)
initialize();
// First run dialog
- LLFirstUse::useAppearance();
+ //LLFirstUse::useAppearance();
}
else
{
diff --git a/indra/newview/llmorphview.h b/indra/newview/llmorphview.h
index 1dd8ef7a5f..493f906c6b 100644
--- a/indra/newview/llmorphview.h
+++ b/indra/newview/llmorphview.h
@@ -43,7 +43,15 @@ class LLFloaterCustomize;
class LLMorphView : public LLView
{
public:
- LLMorphView(const std::string& name, const LLRect& rect);
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
+ {
+ Params()
+ {
+ mouse_opaque(false);
+ follows.flags(FOLLOWS_ALL);
+ }
+ };
+ LLMorphView(const LLMorphView::Params&);
void initialize();
void shutdown();
diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp
index a180047875..0ab3b07aea 100644
--- a/indra/newview/llmoveview.cpp
+++ b/indra/newview/llmoveview.cpp
@@ -36,14 +36,23 @@
// Library includes
#include "indra_constants.h"
+#include "llparcel.h"
// Viewer includes
+
#include "llagent.h"
-#include "llviewercontrol.h"
+#include "llvoavatarself.h" // to check gAgent.getAvatarObject()->isSitting()
+#include "llbottomtray.h"
#include "llbutton.h"
-#include "llviewerwindow.h"
+#include "llfloaterreg.h"
#include "lljoystickbutton.h"
#include "lluictrlfactory.h"
+#include "llviewerwindow.h"
+#include "llviewercontrol.h"
+#include "llselectmgr.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+#include "lltooltip.h"
//
// Constants
@@ -53,72 +62,129 @@ const F32 MOVE_BUTTON_DELAY = 0.0f;
const F32 YAW_NUDGE_RATE = 0.05f; // fraction of normal speed
const F32 NUDGE_TIME = 0.25f; // in seconds
+const std::string BOTTOM_TRAY_BUTTON_NAME = "movement_btn";
+
//
// Member functions
//
// protected
LLFloaterMove::LLFloaterMove(const LLSD& key)
-: LLFloater(std::string("move floater"))
+: LLTransientDockableFloater(NULL, true, key),
+ mForwardButton(NULL),
+ mBackwardButton(NULL),
+ mTurnLeftButton(NULL),
+ mTurnRightButton(NULL),
+ mMoveUpButton(NULL),
+ mMoveDownButton(NULL),
+ mStopFlyingButton(NULL),
+ mModeActionsPanel(NULL),
+ mCurrentMode(MM_WALK)
{
- setIsChrome(TRUE);
-
- const BOOL DONT_OPEN = FALSE;
- LLUICtrlFactory::getInstance()->buildFloater(this,"floater_moveview.xml", NULL, DONT_OPEN);
+}
+// virtual
+BOOL LLFloaterMove::postBuild()
+{
+ setIsChrome(TRUE);
+
+ LLDockableFloater::postBuild();
+
mForwardButton = getChild<LLJoystickAgentTurn>("forward btn");
mForwardButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
mBackwardButton = getChild<LLJoystickAgentTurn>("backward btn");
mBackwardButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
- mSlideLeftButton = getChild<LLJoystickAgentSlide>("slide left btn");
- mSlideLeftButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
-
- mSlideRightButton = getChild<LLJoystickAgentSlide>("slide right btn");
- mSlideRightButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
-
mTurnLeftButton = getChild<LLButton>("turn left btn");
mTurnLeftButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
- mTurnLeftButton->setHeldDownCallback( turnLeft );
-
+ mTurnLeftButton->setHeldDownCallback(boost::bind(&LLFloaterMove::turnLeft, this));
mTurnRightButton = getChild<LLButton>("turn right btn");
mTurnRightButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
- mTurnRightButton->setHeldDownCallback( turnRight );
+ mTurnRightButton->setHeldDownCallback(boost::bind(&LLFloaterMove::turnRight, this));
mMoveUpButton = getChild<LLButton>("move up btn");
- childSetAction("move up btn",moveUp,NULL);
mMoveUpButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
- mMoveUpButton->setHeldDownCallback( moveUp );
+ mMoveUpButton->setHeldDownCallback(boost::bind(&LLFloaterMove::moveUp, this));
mMoveDownButton = getChild<LLButton>("move down btn");
- childSetAction("move down btn",moveDown,NULL);
mMoveDownButton->setHeldDownDelay(MOVE_BUTTON_DELAY);
- mMoveDownButton->setHeldDownCallback( moveDown );
+ mMoveDownButton->setHeldDownCallback(boost::bind(&LLFloaterMove::moveDown, this));
+
+
+ mStopFlyingButton = getChild<LLButton>("stop_fly_btn");
+
+ mModeActionsPanel = getChild<LLPanel>("panel_modes");
+
+ LLButton* btn;
+ btn = getChild<LLButton>("mode_walk_btn");
+ btn->setCommitCallback(boost::bind(&LLFloaterMove::onWalkButtonClick, this));
+
+ btn = getChild<LLButton>("mode_run_btn");
+ btn->setCommitCallback(boost::bind(&LLFloaterMove::onRunButtonClick, this));
+
+ btn = getChild<LLButton>("mode_fly_btn");
+ btn->setCommitCallback(boost::bind(&LLFloaterMove::onFlyButtonClick, this));
+
+ btn = getChild<LLButton>("stop_fly_btn");
+ btn->setCommitCallback(boost::bind(&LLFloaterMove::onStopFlyingButtonClick, this));
+
+
+
+ showFlyControls(false);
+
+ initModeTooltips();
+
+ initModeButtonMap();
+
+ initMovementMode();
+
+ LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(LLFloaterMove::sUpdateFlyingStatus);
+
+ return TRUE;
}
// virtual
-void LLFloaterMove::onClose(bool app_quitting)
+void LLFloaterMove::setEnabled(BOOL enabled)
{
- LLFloater::onClose(app_quitting);
-
- if (!app_quitting)
+ //we need to enable/disable only buttons, EXT-1061.
+
+ // is called before postBuild() - use findChild here.
+ LLPanel *panel_actions = findChild<LLPanel>("panel_actions");
+ if (panel_actions) panel_actions->setEnabled(enabled);
+
+ showModeButtons(enabled);
+}
+
+// *NOTE: we assume that setVisible() is called on floater close.
+// virtual
+void LLFloaterMove::setVisible(BOOL visible)
+{
+ // Do nothing with Stand/Stop Flying panel in excessive calls of this method (from LLTransientFloaterMgr?).
+ if (getVisible() == visible)
{
- gSavedSettings.setBOOL("ShowMovementControls", FALSE);
+ LLTransientDockableFloater::setVisible(visible);
+ return;
}
-}
-//
-// Static member functions
-//
+ if (visible)
+ {
+ // Attach the Stand/Stop Flying panel.
+ LLPanelStandStopFlying* ssf_panel = LLPanelStandStopFlying::getInstance();
+ ssf_panel->reparent(this);
+ const LLRect& mode_actions_rect = mModeActionsPanel->getRect();
+ ssf_panel->setOrigin(mode_actions_rect.mLeft, mode_actions_rect.mBottom);
+ }
+ else
+ {
+ // Detach the Stand/Stop Flying panel.
+ LLPanelStandStopFlying::getInstance()->reparent(NULL);
+ }
-void LLFloaterMove::onOpen()
-{
- LLFloater::onOpen();
- gSavedSettings.setBOOL("ShowMovementControls", TRUE);
+ LLTransientDockableFloater::setVisible(visible);
}
-// protected static
+// static
F32 LLFloaterMove::getYawRate( F32 time )
{
if( time < NUDGE_TIME )
@@ -132,32 +198,508 @@ F32 LLFloaterMove::getYawRate( F32 time )
}
}
-// protected static
-void LLFloaterMove::turnLeft(void *)
+
+// static
+void LLFloaterMove::setFlyingMode(BOOL fly)
+{
+ LLFloaterMove* instance = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview");
+ if (instance)
+ {
+ instance->setFlyingModeImpl(fly);
+ instance->showModeButtons(!fly);
+ }
+ if (fly)
+ {
+ LLPanelStandStopFlying::setStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STOP_FLYING);
+ }
+ else
+ {
+ LLPanelStandStopFlying::clearStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STOP_FLYING);
+ }
+}
+//static
+void LLFloaterMove::setAlwaysRunMode(bool run)
+{
+ LLFloaterMove* instance = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview");
+ if (instance)
+ {
+ instance->setAlwaysRunModeImpl(run);
+ }
+}
+
+void LLFloaterMove::setFlyingModeImpl(BOOL fly)
{
- F32 time = getInstance()->mTurnLeftButton->getHeldDownTime();
+ updateButtonsWithMovementMode(fly ? MM_FLY : (gAgent.getAlwaysRun() ? MM_RUN : MM_WALK));
+}
+
+void LLFloaterMove::setAlwaysRunModeImpl(bool run)
+{
+ if (!gAgent.getFlying())
+ {
+ updateButtonsWithMovementMode(run ? MM_RUN : MM_WALK);
+ }
+}
+
+//static
+void LLFloaterMove::setSittingMode(BOOL bSitting)
+{
+ if (bSitting)
+ {
+ LLPanelStandStopFlying::setStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STAND);
+ }
+ else
+ {
+ LLPanelStandStopFlying::clearStandStopFlyingMode(LLPanelStandStopFlying::SSFM_STAND);
+ }
+ enableInstance(!bSitting);
+}
+
+// protected
+void LLFloaterMove::turnLeft()
+{
+ F32 time = mTurnLeftButton->getHeldDownTime();
gAgent.moveYaw( getYawRate( time ) );
}
-// protected static
-void LLFloaterMove::turnRight(void *)
+// protected
+void LLFloaterMove::turnRight()
{
- F32 time = getInstance()->mTurnRightButton->getHeldDownTime();
+ F32 time = mTurnRightButton->getHeldDownTime();
gAgent.moveYaw( -getYawRate( time ) );
}
-// protected static
-void LLFloaterMove::moveUp(void *)
+// protected
+void LLFloaterMove::moveUp()
{
// Jumps or flys up, depending on fly state
gAgent.moveUp(1);
}
-// protected static
-void LLFloaterMove::moveDown(void *)
+// protected
+void LLFloaterMove::moveDown()
{
// Crouches or flys down, depending on fly state
gAgent.moveUp(-1);
}
+//////////////////////////////////////////////////////////////////////////
+// Private Section:
+//////////////////////////////////////////////////////////////////////////
+
+void LLFloaterMove::onWalkButtonClick()
+{
+ setMovementMode(MM_WALK);
+}
+void LLFloaterMove::onRunButtonClick()
+{
+ setMovementMode(MM_RUN);
+}
+void LLFloaterMove::onFlyButtonClick()
+{
+ setMovementMode(MM_FLY);
+}
+void LLFloaterMove::onStopFlyingButtonClick()
+{
+ setMovementMode(gAgent.getAlwaysRun() ? MM_RUN : MM_WALK);
+}
+
+void LLFloaterMove::setMovementMode(const EMovementMode mode)
+{
+ mCurrentMode = mode;
+ gAgent.setFlying(MM_FLY == mode);
+
+ // attempts to set avatar flying can not set it real flying in some cases.
+ // For ex. when avatar fell down & is standing up.
+ // So, no need to continue processing FLY mode. See EXT-1079
+ if (MM_FLY == mode && !gAgent.getFlying())
+ {
+ return;
+ }
+
+ switch (mode)
+ {
+ case MM_RUN:
+ gAgent.setAlwaysRun();
+ gAgent.setRunning();
+ break;
+ case MM_WALK:
+ gAgent.clearAlwaysRun();
+ gAgent.clearRunning();
+ break;
+ default:
+ //do nothing for other modes (MM_FLY)
+ break;
+ }
+ // tell the simulator.
+ gAgent.sendWalkRun(gAgent.getAlwaysRun());
+
+ updateButtonsWithMovementMode(mode);
+
+ bool bHideModeButtons = MM_FLY == mode
+ || (gAgent.getAvatarObject() && gAgent.getAvatarObject()->isSitting());
+
+ showModeButtons(!bHideModeButtons);
+
+}
+
+void LLFloaterMove::updateButtonsWithMovementMode(const EMovementMode newMode)
+{
+ showFlyControls(MM_FLY == newMode);
+ setModeTooltip(newMode);
+ setModeButtonToggleState(newMode);
+}
+
+void LLFloaterMove::showFlyControls(bool bShow)
+{
+ mMoveUpButton->setVisible(bShow);
+ mMoveDownButton->setVisible(bShow);
+
+ // *TODO: mantipov: mStopFlyingButton from the FloaterMove is not used now.
+ // It was not completly removed until functionality is reviewed by LL
+ mStopFlyingButton->setVisible(FALSE);
+}
+
+void LLFloaterMove::initModeTooltips()
+{
+ control_tooltip_map_t walkTipMap;
+ walkTipMap.insert(std::make_pair(mForwardButton, getString("walk_forward_tooltip")));
+ walkTipMap.insert(std::make_pair(mBackwardButton, getString("walk_back_tooltip")));
+ mModeControlTooltipsMap[MM_WALK] = walkTipMap;
+
+ control_tooltip_map_t runTipMap;
+ runTipMap.insert(std::make_pair(mForwardButton, getString("run_forward_tooltip")));
+ runTipMap.insert(std::make_pair(mBackwardButton, getString("run_back_tooltip")));
+ mModeControlTooltipsMap[MM_RUN] = runTipMap;
+
+ control_tooltip_map_t flyTipMap;
+ flyTipMap.insert(std::make_pair(mForwardButton, getString("fly_forward_tooltip")));
+ flyTipMap.insert(std::make_pair(mBackwardButton, getString("fly_back_tooltip")));
+ mModeControlTooltipsMap[MM_FLY] = flyTipMap;
+
+ setModeTooltip(MM_WALK);
+}
+
+void LLFloaterMove::initModeButtonMap()
+{
+ mModeControlButtonMap[MM_WALK] = getChild<LLButton>("mode_walk_btn");
+ mModeControlButtonMap[MM_RUN] = getChild<LLButton>("mode_run_btn");
+ mModeControlButtonMap[MM_FLY] = getChild<LLButton>("mode_fly_btn");
+}
+
+void LLFloaterMove::initMovementMode()
+{
+ EMovementMode initMovementMode = gAgent.getAlwaysRun() ? MM_RUN : MM_WALK;
+ if (gAgent.getFlying())
+ {
+ initMovementMode = MM_FLY;
+ }
+ setMovementMode(initMovementMode);
+
+ if (gAgent.getAvatarObject())
+ {
+ setEnabled(!gAgent.getAvatarObject()->isSitting());
+ }
+}
+
+void LLFloaterMove::setModeTooltip(const EMovementMode mode)
+{
+ llassert_always(mModeControlTooltipsMap.end() != mModeControlTooltipsMap.find(mode));
+ control_tooltip_map_t controlsTipMap = mModeControlTooltipsMap[mode];
+ control_tooltip_map_t::const_iterator it = controlsTipMap.begin();
+ for (; it != controlsTipMap.end(); ++it)
+ {
+ LLView* ctrl = it->first;
+ std::string tooltip = it->second;
+ ctrl->setToolTip(tooltip);
+ }
+}
+
+/**
+ * Updates position of the floater to be center aligned with Move button.
+ *
+ * Because Tip floater created as dependent floater this method
+ * must be called before "showQuickTips()" to get Tip floater be positioned at the right side of the floater
+ */
+void LLFloaterMove::updatePosition()
+{
+ LLBottomTray* tray = LLBottomTray::getInstance();
+ if (!tray) return;
+
+ LLButton* movement_btn = tray->getChild<LLButton>(BOTTOM_TRAY_BUTTON_NAME);
+
+ //align centers of a button and a floater
+ S32 x = movement_btn->calcScreenRect().getCenterX() - getRect().getWidth()/2;
+
+ S32 y = 0;
+ if (!mModeActionsPanel->getVisible())
+ {
+ y = mModeActionsPanel->getRect().getHeight();
+ }
+ setOrigin(x, y);
+}
+
+//static
+void LLFloaterMove::sUpdateFlyingStatus()
+{
+ LLFloaterMove *floater = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview");
+ if (floater) floater->mModeControlButtonMap[MM_FLY]->setEnabled(gAgent.canFly());
+
+}
+
+void LLFloaterMove::showModeButtons(BOOL bShow)
+{
+ // is called from setEnabled so can be called before postBuild(), check mModeActionsPanel agains to NULL
+ if (NULL == mModeActionsPanel || mModeActionsPanel->getVisible() == bShow)
+ return;
+ mModeActionsPanel->setVisible(bShow);
+}
+
+//static
+void LLFloaterMove::enableInstance(BOOL bEnable)
+{
+ LLFloaterMove* instance = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview");
+ if (instance)
+ {
+ instance->setEnabled(bEnable);
+
+ if (gAgent.getFlying())
+ {
+ instance->showModeButtons(FALSE);
+ }
+ }
+}
+
+void LLFloaterMove::onOpen(const LLSD& key)
+{
+ LLButton *anchor_panel = LLBottomTray::getInstance()->getChild<LLButton>("movement_btn");
+
+ if (gAgent.getFlying())
+ {
+ setFlyingMode(TRUE);
+ showModeButtons(FALSE);
+ }
+
+ if (gAgent.getAvatarObject() && gAgent.getAvatarObject()->isSitting())
+ {
+ setSittingMode(TRUE);
+ showModeButtons(FALSE);
+ }
+
+ setDockControl(new LLDockControl(
+ anchor_panel, this,
+ getDockTongue(), LLDockControl::TOP));
+
+ sUpdateFlyingStatus();
+}
+
+//virtual
+void LLFloaterMove::setDocked(bool docked, bool pop_on_undock/* = true*/)
+{
+ LLTransientDockableFloater::setDocked(docked, pop_on_undock);
+}
+
+void LLFloaterMove::setModeButtonToggleState(const EMovementMode mode)
+{
+ llassert_always(mModeControlButtonMap.end() != mModeControlButtonMap.find(mode));
+
+ mode_control_button_map_t::const_iterator it = mModeControlButtonMap.begin();
+ for (; it != mModeControlButtonMap.end(); ++it)
+ {
+ it->second->setToggleState(FALSE);
+ }
+
+ mModeControlButtonMap[mode]->setToggleState(TRUE);
+}
+
+
+
+/************************************************************************/
+/* LLPanelStandStopFlying */
+/************************************************************************/
+LLPanelStandStopFlying::LLPanelStandStopFlying() :
+ mStandButton(NULL),
+ mStopFlyingButton(NULL),
+ mAttached(false)
+{
+ // make sure we have the only instance of this class
+ static bool b = true;
+ llassert_always(b);
+ b=false;
+}
+
+// static
+inline LLPanelStandStopFlying* LLPanelStandStopFlying::getInstance()
+{
+ static LLPanelStandStopFlying* panel = getStandStopFlyingPanel();
+ return panel;
+}
+
+//static
+void LLPanelStandStopFlying::setStandStopFlyingMode(EStandStopFlyingMode mode)
+{
+ LLPanelStandStopFlying* panel = getInstance();
+
+ panel->mStandButton->setVisible(SSFM_STAND == mode);
+ panel->mStopFlyingButton->setVisible(SSFM_STOP_FLYING == mode);
+
+ //visibility of it should be updated after updating visibility of the buttons
+ panel->setVisible(TRUE);
+}
+
+//static
+void LLPanelStandStopFlying::clearStandStopFlyingMode(EStandStopFlyingMode mode)
+{
+ LLPanelStandStopFlying* panel = getInstance();
+ switch(mode) {
+ case SSFM_STAND:
+ panel->mStandButton->setVisible(FALSE);
+ break;
+ case SSFM_STOP_FLYING:
+ panel->mStopFlyingButton->setVisible(FALSE);
+ break;
+ default:
+ llerrs << "Unexpected EStandStopFlyingMode is passed: " << mode << llendl;
+ }
+
+}
+
+BOOL LLPanelStandStopFlying::postBuild()
+{
+ mStandButton = getChild<LLButton>("stand_btn");
+ mStandButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStandButtonClick, this));
+ mStandButton->setCommitCallback(boost::bind(&LLFloaterMove::enableInstance, TRUE));
+ mStandButton->setVisible(FALSE);
+
+ mStopFlyingButton = getChild<LLButton>("stop_fly_btn");
+ //mStopFlyingButton->setCommitCallback(boost::bind(&LLFloaterMove::setFlyingMode, FALSE));
+ mStopFlyingButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStopFlyingButtonClick, this));
+ mStopFlyingButton->setVisible(FALSE);
+
+ return TRUE;
+}
+
+//virtual
+void LLPanelStandStopFlying::setVisible(BOOL visible)
+{
+ //we dont need to show the panel if these buttons are not activated
+ if (gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK) visible = false;
+
+ if (visible)
+ {
+ updatePosition();
+ }
+
+ //change visibility of parent layout_panel to animate in/out
+ if (getParent()) getParent()->setVisible(visible);
+}
+
+BOOL LLPanelStandStopFlying::handleToolTip(S32 x, S32 y, MASK mask)
+{
+ LLToolTipMgr::instance().unblockToolTips();
+
+ if (mStandButton->getVisible())
+ {
+ LLToolTipMgr::instance().show(mStandButton->getToolTip());
+ }
+ else if (mStopFlyingButton->getVisible())
+ {
+ LLToolTipMgr::instance().show(mStopFlyingButton->getToolTip());
+ }
+
+ return LLPanel::handleToolTip(x, y, mask);
+}
+
+void LLPanelStandStopFlying::reparent(LLFloaterMove* move_view)
+{
+ LLPanel* parent = dynamic_cast<LLPanel*>(getParent());
+ if (!parent)
+ {
+ llwarns << "Stand/stop flying panel parent is unset" << llendl;
+ return;
+ }
+
+ if (move_view != NULL)
+ {
+ llassert(move_view != parent); // sanity check
+
+ // Save our original container.
+ if (!mOriginalParent.get())
+ mOriginalParent = parent->getHandle();
+
+ // Attach to movement controls.
+ parent->removeChild(this);
+ move_view->addChild(this);
+ // Origin must be set by movement controls.
+ mAttached = true;
+ }
+ else
+ {
+ if (!mOriginalParent.get())
+ {
+ llwarns << "Original parent of the stand / stop flying panel not found" << llendl;
+ return;
+ }
+
+ // Detach from movement controls.
+ parent->removeChild(this);
+ mOriginalParent.get()->addChild(this);
+ mAttached = false;
+ updatePosition(); // don't defer until next draw() to avoid flicker
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Private Section
+//////////////////////////////////////////////////////////////////////////
+
+//static
+LLPanelStandStopFlying* LLPanelStandStopFlying::getStandStopFlyingPanel()
+{
+ LLPanelStandStopFlying* panel = new LLPanelStandStopFlying();
+ LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_stand_stop_flying.xml");
+
+ panel->setVisible(FALSE);
+ //LLUI::getRootView()->addChild(panel);
+
+ llinfos << "Build LLPanelStandStopFlying panel" << llendl;
+
+ panel->updatePosition();
+ return panel;
+}
+
+void LLPanelStandStopFlying::onStandButtonClick()
+{
+ LLSelectMgr::getInstance()->deselectAllForStandingUp();
+ gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
+
+ setFocus(FALSE); // EXT-482
+
+ BOOL fly = gAgent.getFlying();
+ mStopFlyingButton->setVisible(fly);
+ setVisible(fly);
+}
+
+void LLPanelStandStopFlying::onStopFlyingButtonClick()
+{
+ gAgent.setFlying(FALSE);
+
+ setFocus(FALSE); // EXT-482
+}
+
+/**
+ * Updates position of the Stand & Stop Flying panel to be center aligned with Move button.
+ */
+void LLPanelStandStopFlying::updatePosition()
+{
+ LLBottomTray* tray = LLBottomTray::getInstance();
+ if (!tray || mAttached) return;
+
+ LLButton* movement_btn = tray->getChild<LLButton>(BOTTOM_TRAY_BUTTON_NAME);
+
+ // Align centers of the button and the panel.
+ S32 x = movement_btn->calcScreenRect().getCenterX() - getRect().getWidth()/2;
+ setOrigin(x, 0);
+}
+
+
// EOF
diff --git a/indra/newview/llmoveview.h b/indra/newview/llmoveview.h
index e772551efe..06463f02af 100644
--- a/indra/newview/llmoveview.h
+++ b/indra/newview/llmoveview.h
@@ -34,7 +34,7 @@
#define LL_LLMOVEVIEW_H
// Library includes
-#include "llfloater.h"
+#include "lltransientdockablefloater.h"
class LLButton;
class LLJoystickAgentTurn;
@@ -44,40 +44,151 @@ class LLJoystickAgentSlide;
// Classes
//
class LLFloaterMove
-: public LLFloater,
- public LLFloaterSingleton<LLFloaterMove>
+: public LLTransientDockableFloater
{
- friend class LLUISingleton<LLFloaterMove, VisibilityPolicy<LLFloater> >;
-
-protected:
+ LOG_CLASS(LLFloaterMove);
+ friend class LLFloaterReg;
+
+private:
LLFloaterMove(const LLSD& key);
~LLFloaterMove() {}
-
public:
- /*virtual*/ void onOpen();
- /*virtual*/ void onClose(bool app_quitting);
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void setEnabled(BOOL enabled);
+ /*virtual*/ void setVisible(BOOL visible);
static F32 getYawRate(F32 time);
+ static void setFlyingMode(BOOL fly);
+ void setFlyingModeImpl(BOOL fly);
+ static void setAlwaysRunMode(bool run);
+ void setAlwaysRunModeImpl(bool run);
+ static void setSittingMode(BOOL bSitting);
+ static void enableInstance(BOOL bEnable);
+ /*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true);
+
+ static void sUpdateFlyingStatus();
protected:
- static void turnLeftNudge(void* userdata);
- static void turnLeft(void* userdata);
-
- static void turnRightNudge(void* userdata);
- static void turnRight(void* userdata);
+ void turnLeft();
+ void turnRight();
+
+ void moveUp();
+ void moveDown();
- static void moveUp(void* userdata);
- static void moveDown(void* userdata);
+private:
+ typedef enum movement_mode_t
+ {
+ MM_WALK,
+ MM_RUN,
+ MM_FLY
+ } EMovementMode;
+ void onWalkButtonClick();
+ void onRunButtonClick();
+ void onFlyButtonClick();
+ void onStopFlyingButtonClick();
+ void initMovementMode();
+ void setMovementMode(const EMovementMode mode);
+ void showFlyControls(bool bShow);
+ void initModeTooltips();
+ void setModeTooltip(const EMovementMode mode);
+ void showQuickTips(const EMovementMode mode);
+ void initModeButtonMap();
+ void setModeButtonToggleState(const EMovementMode mode);
+ void updateButtonsWithMovementMode(const EMovementMode newMode);
+ void updatePosition();
+ void showModeButtons(BOOL bShow);
public:
+
LLJoystickAgentTurn* mForwardButton;
LLJoystickAgentTurn* mBackwardButton;
- LLJoystickAgentSlide* mSlideLeftButton;
- LLJoystickAgentSlide* mSlideRightButton;
LLButton* mTurnLeftButton;
LLButton* mTurnRightButton;
LLButton* mMoveUpButton;
LLButton* mMoveDownButton;
+private:
+ LLButton* mStopFlyingButton;
+ LLPanel* mModeActionsPanel;
+
+ typedef std::map<LLView*, std::string> control_tooltip_map_t;
+ typedef std::map<EMovementMode, control_tooltip_map_t> mode_control_tooltip_map_t;
+ mode_control_tooltip_map_t mModeControlTooltipsMap;
+
+ typedef std::map<EMovementMode, LLButton*> mode_control_button_map_t;
+ mode_control_button_map_t mModeControlButtonMap;
+ EMovementMode mCurrentMode;
+
+};
+
+
+/**
+ * This class contains Stand Up and Stop Flying buttons displayed above Move button in bottom tray
+ */
+class LLPanelStandStopFlying : public LLPanel
+{
+ LOG_CLASS(LLPanelStandStopFlying);
+public:
+ typedef enum stand_stop_flying_mode_t
+ {
+ SSFM_STAND,
+ SSFM_STOP_FLYING
+ } EStandStopFlyingMode;
+
+ /**
+ * Attach or detach the panel to/from the movement controls floater.
+ *
+ * Called when the floater gets opened/closed, user sits, stands up or starts/stops flying.
+ *
+ * @param move_view The floater to attach to (not always accessible via floater registry).
+ * If NULL is passed, the panel gets reparented to its original container.
+ *
+ * @see mAttached
+ * @see mOriginalParent
+ */
+ void reparent(LLFloaterMove* move_view);
+
+ static LLPanelStandStopFlying* getInstance();
+ static void setStandStopFlyingMode(EStandStopFlyingMode mode);
+ static void clearStandStopFlyingMode(EStandStopFlyingMode mode);
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void setVisible(BOOL visible);
+
+ // *HACK: due to hard enough to have this control aligned with "Move" button while resizing
+ // let update its position in each frame
+ /*virtual*/ void draw(){updatePosition(); LLPanel::draw();}
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
+
+
+protected:
+ LLPanelStandStopFlying();
+
+
+private:
+ static LLPanelStandStopFlying* getStandStopFlyingPanel();
+ void onStandButtonClick();
+ void onStopFlyingButtonClick();
+ void updatePosition();
+
+ LLButton* mStandButton;
+ LLButton* mStopFlyingButton;
+
+ /**
+ * The original parent of the panel.
+ *
+ * Makes it possible to move (reparent) the panel to the movement controls floater and back.
+ *
+ * @see reparent()
+ */
+ LLHandle<LLPanel> mOriginalParent;
+
+ /**
+ * True if the panel is currently attached to the movement controls floater.
+ *
+ * @see reparent()
+ * @see updatePosition()
+ */
+ bool mAttached;
};
diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp
index 40b1c64146..c1666f5666 100644
--- a/indra/newview/llmutelist.cpp
+++ b/indra/newview/llmutelist.cpp
@@ -52,25 +52,17 @@
#include <boost/tokenizer.hpp>
-#include "llcrc.h"
-#include "lldir.h"
#include "lldispatcher.h"
-#include "llsdserialize.h"
#include "llxfermanager.h"
-#include "message.h"
#include "llagent.h"
#include "llviewergenericmessage.h" // for gGenericDispatcher
-#include "llviewerwindow.h"
#include "llworld.h" //for particle system banning
-#include "llchat.h"
-#include "llfloaterchat.h"
#include "llimpanel.h"
#include "llimview.h"
#include "llnotifications.h"
-#include "lluistring.h"
-#include "llviewerobject.h"
#include "llviewerobjectlist.h"
+#include "lltrans.h"
namespace
{
@@ -111,11 +103,6 @@ static LLDispatchEmptyMuteList sDispatchEmptyMuteList;
//-----------------------------------------------------------------------------
// LLMute()
//-----------------------------------------------------------------------------
-const char BY_NAME_SUFFIX[] = " (by name)";
-const char AGENT_SUFFIX[] = " (resident)";
-const char OBJECT_SUFFIX[] = " (object)";
-const char GROUP_SUFFIX[] = " (group)";
-
LLMute::LLMute(const LLUUID& id, const std::string& name, EType type, U32 flags)
: mID(id),
@@ -149,16 +136,16 @@ std::string LLMute::getDisplayName() const
{
case BY_NAME:
default:
- name_with_suffix += BY_NAME_SUFFIX;
+ name_with_suffix += " " + LLTrans::getString("MuteByName");
break;
case AGENT:
- name_with_suffix += AGENT_SUFFIX;
+ name_with_suffix += " " + LLTrans::getString("MuteAgent");
break;
case OBJECT:
- name_with_suffix += OBJECT_SUFFIX;
+ name_with_suffix += " " + LLTrans::getString("MuteObject");
break;
case GROUP:
- name_with_suffix += GROUP_SUFFIX;
+ name_with_suffix += " " + LLTrans::getString("MuteGroup");
break;
}
return name_with_suffix;
@@ -169,7 +156,7 @@ void LLMute::setFromDisplayName(const std::string& display_name)
size_t pos = 0;
mName = display_name;
- pos = mName.rfind(GROUP_SUFFIX);
+ pos = mName.rfind(" " + LLTrans::getString("MuteGroup"));
if (pos != std::string::npos)
{
mName.erase(pos);
@@ -177,7 +164,7 @@ void LLMute::setFromDisplayName(const std::string& display_name)
return;
}
- pos = mName.rfind(OBJECT_SUFFIX);
+ pos = mName.rfind(" " + LLTrans::getString("MuteObject"));
if (pos != std::string::npos)
{
mName.erase(pos);
@@ -185,7 +172,7 @@ void LLMute::setFromDisplayName(const std::string& display_name)
return;
}
- pos = mName.rfind(AGENT_SUFFIX);
+ pos = mName.rfind(" " + LLTrans::getString("MuteAgent"));
if (pos != std::string::npos)
{
mName.erase(pos);
@@ -193,7 +180,7 @@ void LLMute::setFromDisplayName(const std::string& display_name)
return;
}
- pos = mName.rfind(BY_NAME_SUFFIX);
+ pos = mName.rfind(" " + LLTrans::getString("MuteByName"));
if (pos != std::string::npos)
{
mName.erase(pos);
@@ -224,61 +211,17 @@ LLMuteList* LLMuteList::getInstance()
// LLMuteList()
//-----------------------------------------------------------------------------
LLMuteList::LLMuteList() :
- mIsLoaded(FALSE),
- mUserVolumesLoaded(FALSE)
+ mIsLoaded(FALSE)
{
gGenericDispatcher.addHandler("emptymutelist", &sDispatchEmptyMuteList);
}
-void LLMuteList::loadUserVolumes()
-{
- // call once, after LLDir::setLindenUserDir() has been called
- if (mUserVolumesLoaded)
- return;
- mUserVolumesLoaded = TRUE;
-
- // load per-resident voice volume information
- // conceptually, this is part of the mute list information, although it is only stored locally
- std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "volume_settings.xml");
-
- LLSD settings_llsd;
- llifstream file;
- file.open(filename);
- if (file.is_open())
- {
- LLSDSerialize::fromXML(settings_llsd, file);
- }
-
- for (LLSD::map_const_iterator iter = settings_llsd.beginMap();
- iter != settings_llsd.endMap(); ++iter)
- {
- mUserVolumeSettings.insert(std::make_pair(LLUUID(iter->first), (F32)iter->second.asReal()));
- }
-}
-
//-----------------------------------------------------------------------------
// ~LLMuteList()
//-----------------------------------------------------------------------------
LLMuteList::~LLMuteList()
{
- // If we quit from the login screen we will not have an SL account
- // name. Don't try to save, otherwise we'll dump a file in
- // C:\Program Files\SecondLife\ JC
- std::string user_dir = gDirUtilp->getLindenUserDir();
- if (!user_dir.empty())
- {
- std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "volume_settings.xml");
- LLSD settings_llsd;
-
- for(user_volume_map_t::iterator iter = mUserVolumeSettings.begin(); iter != mUserVolumeSettings.end(); ++iter)
- {
- settings_llsd[iter->first.asString()] = iter->second;
- }
- llofstream file;
- file.open(filename);
- LLSDSerialize::toPrettyXML(settings_llsd, file);
- }
}
BOOL LLMuteList::isLinden(const std::string& name) const
@@ -303,7 +246,7 @@ BOOL LLMuteList::add(const LLMute& mute, U32 flags)
if ((mute.mType == LLMute::AGENT)
&& isLinden(mute.mName) && (flags & LLMute::flagTextChat || flags == 0))
{
- LLNotifications::instance().add("MuteLinden");
+ LLNotifications::instance().add("MuteLinden", LLSD(), LLSD());
return FALSE;
}
@@ -501,11 +444,8 @@ void LLMuteList::updateRemove(const LLMute& mute)
gAgent.sendReliableMessage();
}
-void notify_automute_callback(const LLUUID& agent_id, const std::string& first_name, const std::string& last_name, BOOL is_group, void* user_data)
+void notify_automute_callback(const LLUUID& agent_id, const std::string& first_name, const std::string& last_name, BOOL is_group, LLMuteList::EAutoReason reason)
{
- U32 temp_data = (U32) (uintptr_t) user_data;
- LLMuteList::EAutoReason reason = (LLMuteList::EAutoReason)temp_data;
-
std::string notif_name;
switch (reason)
{
@@ -525,7 +465,7 @@ void notify_automute_callback(const LLUUID& agent_id, const std::string& first_n
args["FIRST"] = first_name;
args["LAST"] = last_name;
- LLNotificationPtr notif_ptr = LLNotifications::instance().add(notif_name, args);
+ LLNotificationPtr notif_ptr = LLNotifications::instance().add(notif_name, args, LLSD());
if (notif_ptr)
{
std::string message = notif_ptr->getMessage();
@@ -537,10 +477,9 @@ void notify_automute_callback(const LLUUID& agent_id, const std::string& first_n
{
timp->addHistoryLine(message);
}
- }
- LLChat auto_chat(message);
- LLFloaterChat::addChat(auto_chat, FALSE, FALSE);
+ LLIMModel::getInstance()->addMessage(agent_id, SYSTEM_FROM, LLUUID::null, message);
+ }
}
}
@@ -561,18 +500,18 @@ BOOL LLMuteList::autoRemove(const LLUUID& agent_id, const EAutoReason reason, co
if (gCacheName->getName(agent_id, cache_first, cache_last))
{
// name in cache, call callback directly
- notify_automute_callback(agent_id, cache_first, cache_last, FALSE, (void *)reason);
+ notify_automute_callback(agent_id, cache_first, cache_last, FALSE, reason);
}
else
{
// not in cache, lookup name from cache
- gCacheName->get(agent_id, FALSE, notify_automute_callback, (void *)reason);
+ gCacheName->get(agent_id, FALSE, boost::bind(&notify_automute_callback, _1, _2, _3, _4, reason));
}
}
else
{
// call callback directly
- notify_automute_callback(agent_id, first_name, last_name, FALSE, (void *)reason);
+ notify_automute_callback(agent_id, first_name, last_name, FALSE, reason);
}
}
@@ -724,8 +663,6 @@ BOOL LLMuteList::isMuted(const LLUUID& id, const std::string& name, U32 flags) c
//-----------------------------------------------------------------------------
void LLMuteList::requestFromServer(const LLUUID& agent_id)
{
- loadUserVolumes();
-
std::string agent_id_string;
std::string filename;
agent_id.toString(agent_id_string);
@@ -760,26 +697,6 @@ void LLMuteList::cache(const LLUUID& agent_id)
}
}
-void LLMuteList::setSavedResidentVolume(const LLUUID& id, F32 volume)
-{
- // store new value in volume settings file
- mUserVolumeSettings[id] = volume;
-}
-
-F32 LLMuteList::getSavedResidentVolume(const LLUUID& id)
-{
- const F32 DEFAULT_VOLUME = 0.5f;
-
- user_volume_map_t::iterator found_it = mUserVolumeSettings.find(id);
- if (found_it != mUserVolumeSettings.end())
- {
- return found_it->second;
- }
- //FIXME: assumes default, should get this from somewhere
- return DEFAULT_VOLUME;
-}
-
-
//-----------------------------------------------------------------------------
// Static message handlers
//-----------------------------------------------------------------------------
diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h
index dec8d7576e..e1e81a24b4 100644
--- a/indra/newview/llmutelist.h
+++ b/indra/newview/llmutelist.h
@@ -127,12 +127,7 @@ public:
// call this method on logout to save everything.
void cache(const LLUUID& agent_id);
- void setSavedResidentVolume(const LLUUID& id, F32 volume);
- F32 getSavedResidentVolume(const LLUUID& id);
-
private:
- void loadUserVolumes();
-
BOOL loadFromFile(const std::string& filename);
BOOL saveToFile(const std::string& filename);
@@ -153,7 +148,13 @@ private:
{
bool operator()(const LLMute& a, const LLMute& b) const
{
- return a.mName < b.mName;
+ std::string name1 = a.mName;
+ std::string name2 = b.mName;
+
+ LLStringUtil::toUpper(name1);
+ LLStringUtil::toUpper(name2);
+
+ return name1 < name2;
}
};
struct compare_by_id
@@ -173,12 +174,8 @@ private:
observer_set_t mObservers;
BOOL mIsLoaded;
- BOOL mUserVolumesLoaded;
friend class LLDispatchEmptyMuteList;
-
- typedef std::map<LLUUID, F32> user_volume_map_t;
- user_volume_map_t mUserVolumeSettings;
};
class LLMuteListObserver
diff --git a/indra/newview/llnamebox.cpp b/indra/newview/llnamebox.cpp
index 98c7a4b631..cd810b9793 100644
--- a/indra/newview/llnamebox.cpp
+++ b/indra/newview/llnamebox.cpp
@@ -41,25 +41,21 @@
#include "lluuid.h"
#include "llcachename.h"
-#include "llagent.h"
// statics
std::set<LLNameBox*> LLNameBox::sInstances;
+static LLDefaultChildRegistry::Register<LLNameBox> r("name_box");
-LLNameBox::LLNameBox(const std::string& name, const LLRect& rect, const LLUUID& name_id, BOOL is_group, const LLFontGL* font, BOOL mouse_opaque)
-: LLTextBox(name, rect, std::string("(retrieving)"), font, mouse_opaque),
- mNameID(name_id)
+
+LLNameBox::LLNameBox(const Params& p)
+: LLTextBox(p)
{
+ mNameID = LLUUID::null;
+ mLink = p.link;
+ mInitialValue = p.initial_value().asString();
LLNameBox::sInstances.insert(this);
- if(!name_id.isNull())
- {
- setNameID(name_id, is_group);
- }
- else
- {
- setText(LLStringUtil::null);
- }
+ setText(LLStringUtil::null);
}
LLNameBox::~LLNameBox()
@@ -72,17 +68,23 @@ void LLNameBox::setNameID(const LLUUID& name_id, BOOL is_group)
mNameID = name_id;
std::string name;
+ BOOL got_name = FALSE;
if (!is_group)
{
- gCacheName->getFullName(name_id, name);
+ got_name = gCacheName->getFullName(name_id, name);
}
else
{
- gCacheName->getGroupName(name_id, name);
+ got_name = gCacheName->getGroupName(name_id, name);
}
- setText(name);
+ // Got the name already? Set it.
+ // Otherwise it will be set later in refresh().
+ if (got_name)
+ setName(name, is_group);
+ else
+ setText(mInitialValue);
}
void LLNameBox::refresh(const LLUUID& id, const std::string& firstname,
@@ -99,7 +101,7 @@ void LLNameBox::refresh(const LLUUID& id, const std::string& firstname,
{
name = firstname;
}
- setText(name);
+ setName(name, is_group);
}
}
@@ -115,3 +117,22 @@ void LLNameBox::refreshAll(const LLUUID& id, const std::string& firstname,
box->refresh(id, firstname, lastname, is_group);
}
}
+
+void LLNameBox::setName(const std::string& name, BOOL is_group)
+{
+ if (mLink)
+ {
+ std::string url;
+
+ if (is_group)
+ url = "[secondlife:///app/group/" + LLURI::escape(name) + "/about " + name + "]";
+ else
+ url = "[secondlife:///app/agent/" + mNameID.asString() + "/about " + name + "]";
+
+ setText(url);
+ }
+ else
+ {
+ setText(name);
+ }
+}
diff --git a/indra/newview/llnamebox.h b/indra/newview/llnamebox.h
index f76850bd3c..48b54faec8 100644
--- a/indra/newview/llnamebox.h
+++ b/indra/newview/llnamebox.h
@@ -44,10 +44,17 @@ class LLNameBox
: public LLTextBox
{
public:
- LLNameBox(const std::string& name, const LLRect& rect, const LLUUID& name_id = LLUUID::null, BOOL is_group = FALSE, const LLFontGL* font = NULL, BOOL mouse_opaque = TRUE );
- // By default, follows top and left and is mouse-opaque.
- // If no text, text = name.
- // If no font, uses default system font.
+ struct Params : public LLInitParam::Block<Params, LLTextBox::Params>
+ {
+ Optional<bool> is_group;
+ Optional<bool> link;
+
+ Params()
+ : is_group("is_group", false)
+ , link("link", false)
+ {}
+ };
+
virtual ~LLNameBox();
void setNameID(const LLUUID& name_id, BOOL is_group);
@@ -57,11 +64,19 @@ public:
static void refreshAll(const LLUUID& id, const std::string& firstname,
const std::string& lastname, BOOL is_group);
+protected:
+ LLNameBox (const Params&);
+
+ friend class LLUICtrlFactory;
private:
+ void setName(const std::string& name, BOOL is_group);
+
static std::set<LLNameBox*> sInstances;
private:
LLUUID mNameID;
+ BOOL mLink;
+ std::string mInitialValue;
};
diff --git a/indra/newview/llnameeditor.cpp b/indra/newview/llnameeditor.cpp
index e4a65734d8..65601da7da 100644
--- a/indra/newview/llnameeditor.cpp
+++ b/indra/newview/llnameeditor.cpp
@@ -34,7 +34,6 @@
#include "llnameeditor.h"
#include "llcachename.h"
-#include "llagent.h"
#include "llfontgl.h"
@@ -43,40 +42,22 @@
#include "llstring.h"
#include "llui.h"
-static LLRegisterWidget<LLNameEditor> r("name_editor");
+static LLDefaultChildRegistry::Register<LLNameEditor> r("name_editor");
// statics
std::set<LLNameEditor*> LLNameEditor::sInstances;
-LLNameEditor::LLNameEditor(const std::string& name, const LLRect& rect,
- const LLUUID& name_id,
- BOOL is_group,
- const LLFontGL* glfont,
- S32 max_text_length,
- void (*commit_callback)(LLUICtrl* caller, void* user_data),
- void (*keystroke_callback)(LLLineEditor* caller, void* user_data),
- void (*focus_lost_callback)(LLFocusableElement* caller, void* user_data),
- void* userdata,
- LLLinePrevalidateFunc prevalidate_func)
-: LLLineEditor(name, rect,
- std::string("(retrieving)"),
- glfont,
- max_text_length,
- commit_callback,
- keystroke_callback,
- focus_lost_callback,
- userdata,
- prevalidate_func),
- mNameID(name_id)
+LLNameEditor::LLNameEditor(const LLNameEditor::Params& p)
+: LLLineEditor(p)
{
LLNameEditor::sInstances.insert(this);
- if(!name_id.isNull())
+
+ if(!p.name_id().isNull())
{
- setNameID(name_id, is_group);
+ setNameID(p.name_id, p.is_group);
}
}
-
LLNameEditor::~LLNameEditor()
{
LLNameEditor::sInstances.erase(this);
@@ -141,35 +122,3 @@ LLSD LLNameEditor::getValue() const
return LLSD(mNameID);
}
-LLView* LLNameEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("name_editor");
- node->getAttributeString("name", name);
-
- LLRect rect;
- createRect(node, rect, parent, LLRect());
-
- S32 max_text_length = 128;
- node->getAttributeS32("max_length", max_text_length);
-
- LLFontGL* font = LLView::selectFont(node);
-
- LLUICtrlCallback commit_callback = NULL;
-
- LLNameEditor* line_editor = new LLNameEditor(name,
- rect,
- LLUUID::null, FALSE,
- font,
- max_text_length,
- commit_callback);
-
- std::string label;
- if(node->getAttributeString("label", label))
- {
- line_editor->setLabel(label);
- }
- line_editor->setColorParameters(node);
- line_editor->initFromXML(node, parent);
-
- return line_editor;
-}
diff --git a/indra/newview/llnameeditor.h b/indra/newview/llnameeditor.h
index bc5a67866c..99e03a1166 100644
--- a/indra/newview/llnameeditor.h
+++ b/indra/newview/llnameeditor.h
@@ -46,24 +46,23 @@ class LLNameEditor
: public LLLineEditor
{
public:
- LLNameEditor(const std::string& name, const LLRect& rect,
- const LLUUID& name_id = LLUUID::null,
- BOOL is_group = FALSE,
- const LLFontGL* glfont = NULL,
- S32 max_text_length = 254,
- void (*commit_callback)(LLUICtrl* caller, void* user_data) = NULL,
- void (*keystroke_callback)(LLLineEditor* caller, void* user_data) = NULL,
- void (*focus_lost_callback)(LLFocusableElement* caller, void* user_data) = NULL,
- void* userdata = NULL,
- LLLinePrevalidateFunc prevalidate_func = NULL);
- // By default, follows top and left and is mouse-opaque.
- // If no text, text = name.
- // If no font, uses default system font.
-
+ struct Params : public LLInitParam::Block<Params, LLLineEditor::Params>
+ {
+ Optional<bool> is_group;
+ Optional<LLUUID> name_id;
+
+ Params()
+ : is_group("is_group"),
+ name_id("name_id")
+ {}
+ };
+
+protected:
+ LLNameEditor(const Params&);
+ friend class LLUICtrlFactory;
+public:
virtual ~LLNameEditor();
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
-
void setNameID(const LLUUID& name_id, BOOL is_group);
void refresh(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp
index baf06567c1..6375362ae2 100644
--- a/indra/newview/llnamelistctrl.cpp
+++ b/indra/newview/llnamelistctrl.cpp
@@ -32,58 +32,54 @@
#include "llviewerprecompiledheaders.h"
-#include <boost/tokenizer.hpp>
-
#include "llnamelistctrl.h"
+#include <boost/tokenizer.hpp>
+
#include "llcachename.h"
-#include "llagent.h"
+#include "llfloaterreg.h"
#include "llinventory.h"
+#include "llscrolllistitem.h"
+#include "llscrolllistcell.h"
+#include "llscrolllistcolumn.h"
+#include "llsdparam.h"
+#include "lltooltip.h"
-static LLRegisterWidget<LLNameListCtrl> r("name_list");
-
-// statics
-std::set<LLNameListCtrl*> LLNameListCtrl::sInstances;
-
-LLNameListCtrl::LLNameListCtrl(const std::string& name,
- const LLRect& rect,
- LLUICtrlCallback cb,
- void* userdata,
- BOOL allow_multiple_selection,
- BOOL draw_border,
- S32 name_column_index,
- const std::string& tooltip)
-: LLScrollListCtrl(name, rect, cb, userdata, allow_multiple_selection,
- draw_border),
- mNameColumnIndex(name_column_index),
- mAllowCallingCardDrop(FALSE)
+static LLDefaultChildRegistry::Register<LLNameListCtrl> r("name_list");
+
+void LLNameListCtrl::NameTypeNames::declareValues()
{
- setToolTip(tooltip);
- LLNameListCtrl::sInstances.insert(this);
+ declare("INDIVIDUAL", LLNameListCtrl::INDIVIDUAL);
+ declare("GROUP", LLNameListCtrl::GROUP);
+ declare("SPECIAL", LLNameListCtrl::SPECIAL);
}
-
-// virtual
-LLNameListCtrl::~LLNameListCtrl()
+LLNameListCtrl::Params::Params()
+: name_column(""),
+ allow_calling_card_drop("allow_calling_card_drop", false)
{
- LLNameListCtrl::sInstances.erase(this);
+ name = "name_list";
}
+LLNameListCtrl::LLNameListCtrl(const LLNameListCtrl::Params& p)
+: LLScrollListCtrl(p),
+ mNameColumnIndex(p.name_column.column_index),
+ mNameColumn(p.name_column.column_name),
+ mAllowCallingCardDrop(p.allow_calling_card_drop)
+{}
// public
-BOOL LLNameListCtrl::addNameItem(const LLUUID& agent_id, EAddPosition pos,
+void LLNameListCtrl::addNameItem(const LLUUID& agent_id, EAddPosition pos,
BOOL enabled, std::string& suffix)
{
//llinfos << "LLNameListCtrl::addNameItem " << agent_id << llendl;
- std::string fullname;
- BOOL result = gCacheName->getFullName(agent_id, fullname);
-
- fullname.append(suffix);
+ NameItem item;
+ item.value = agent_id;
+ item.enabled = enabled;
+ item.target = INDIVIDUAL;
- addStringUUIDItem(fullname, agent_id, pos, enabled);
-
- return result;
+ addNameItemRow(item, pos);
}
// virtual, public
@@ -134,79 +130,153 @@ BOOL LLNameListCtrl::handleDragAndDrop(
return handled;
}
+void LLNameListCtrl::showInspector(const LLUUID& avatar_id, bool is_group)
+{
+ if (is_group)
+ LLFloaterReg::showInstance("inspect_group", LLSD().with("group_id", avatar_id));
+ else
+ LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", avatar_id));
+}
+
+//virtual
+BOOL LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = FALSE;
+ S32 column_index = getColumnIndexFromOffset(x);
+ LLScrollListItem* hit_item = hitItem(x, y);
+ if (hit_item
+ && column_index == mNameColumnIndex)
+ {
+ // ...this is the column with the avatar name
+ LLUUID avatar_id = getItemId(hit_item);
+ if (avatar_id.notNull())
+ {
+ // ...valid avatar id
+ LLScrollListCell* hit_cell = hit_item->getColumn(column_index);
+ if (hit_cell)
+ {
+ S32 row_index = getItemIndex(hit_item);
+ LLRect cell_rect = getCellRect(row_index, column_index);
+ // Convert rect local to screen coordinates
+ LLRect sticky_rect;
+ localRectToScreen(cell_rect, &sticky_rect);
+
+ // Spawn at right side of cell
+ LLCoordGL pos( sticky_rect.mRight - 16, sticky_rect.mTop );
+ LLPointer<LLUIImage> icon = LLUI::getUIImage("Info_Small");
+
+ // Should we show a group or an avatar inspector?
+ bool is_group = hit_item->getValue()["is_group"].asBoolean();
+
+ LLToolTip::Params params;
+ params.background_visible( false );
+ params.click_callback( boost::bind(&LLNameListCtrl::showInspector, this, avatar_id, is_group) );
+ params.delay_time(0.0f); // spawn instantly on hover
+ params.image( icon );
+ params.message("");
+ params.padding(0);
+ params.pos(pos);
+ params.sticky_rect(sticky_rect);
+
+ LLToolTipMgr::getInstance()->show(params);
+ handled = TRUE;
+ }
+ }
+ }
+ if (!handled)
+ {
+ handled = LLScrollListCtrl::handleToolTip(x, y, mask);
+ }
+ return handled;
+}
+
// public
void LLNameListCtrl::addGroupNameItem(const LLUUID& group_id, EAddPosition pos,
BOOL enabled)
{
- //llinfos << "LLNameListCtrl::addGroupNameItem " << group_id << llendl;
- std::string group_name;
- gCacheName->getGroupName(group_id, group_name);
- addStringUUIDItem(group_name, group_id, pos, enabled);
+ NameItem item;
+ item.value = group_id;
+ item.enabled = enabled;
+ item.target = GROUP;
+
+ addNameItemRow(item, pos);
}
// public
-void LLNameListCtrl::addGroupNameItem(LLScrollListItem* item, EAddPosition pos)
-
+void LLNameListCtrl::addGroupNameItem(LLNameListCtrl::NameItem& item, EAddPosition pos)
{
- //llinfos << "LLNameListCtrl::addGroupNameItem " << item->getUUID() << llendl;
-
- std::string group_name;
- gCacheName->getGroupName(item->getUUID(), group_name);
-
- LLScrollListCell* cell = (LLScrollListCell*)item->getColumn(mNameColumnIndex);
- ((LLScrollListText*)cell)->setText( std::string(group_name) );
-
- addItem(item, pos);
+ item.target = GROUP;
+ addNameItemRow(item, pos);
}
-BOOL LLNameListCtrl::addNameItem(LLScrollListItem* item, EAddPosition pos)
+void LLNameListCtrl::addNameItem(LLNameListCtrl::NameItem& item, EAddPosition pos)
{
- //llinfos << "LLNameListCtrl::addNameItem " << item->getUUID() << llendl;
+ item.target = INDIVIDUAL;
+ addNameItemRow(item, pos);
+}
- std::string fullname;
- BOOL result = gCacheName->getFullName(item->getUUID(), fullname);
+LLScrollListItem* LLNameListCtrl::addElement(const LLSD& element, EAddPosition pos, void* userdata)
+{
+ LLNameListCtrl::NameItem item_params;
+ LLParamSDParser::instance().readSD(element, item_params);
+ item_params.userdata = userdata;
+ return addNameItemRow(item_params, pos);
+}
- LLScrollListCell* cell = (LLScrollListCell*)item->getColumn(mNameColumnIndex);
- ((LLScrollListText*)cell)->setText( fullname );
- addItem(item, pos);
+LLScrollListItem* LLNameListCtrl::addNameItemRow(
+ const LLNameListCtrl::NameItem& name_item,
+ EAddPosition pos,
+ std::string& suffix)
+{
+ LLUUID id = name_item.value().asUUID();
+ LLScrollListItem* item = NULL;
- // this column is resizable
- LLScrollListColumn* columnp = getColumn(mNameColumnIndex);
- if (columnp && columnp->mHeader)
+ // Store item type so that we can invoke the proper inspector.
+ // *TODO Vadim: Is there a more proper way of storing additional item data?
{
- columnp->mHeader->setHasResizableElement(TRUE);
+ LLNameListCtrl::NameItem name_item_(name_item);
+ name_item_.value = LLSD().with("uuid", id).with("is_group", name_item.target() == GROUP);
+ item = LLScrollListCtrl::addRow(name_item_, pos);
}
- return result;
-}
-
-LLScrollListItem* LLNameListCtrl::addElement(const LLSD& value, EAddPosition pos, void* userdata)
-{
- LLScrollListItem* item = LLScrollListCtrl::addElement(value, pos, userdata);
+ if (!item) return NULL;
// use supplied name by default
- std::string fullname = value["name"].asString();
- if (value["target"].asString() == "GROUP")
+ std::string fullname = name_item.name;
+ switch(name_item.target)
{
- gCacheName->getGroupName(item->getUUID(), fullname);
+ case GROUP:
+ gCacheName->getGroupName(id, fullname);
// fullname will be "nobody" if group not found
- }
- else if (value["target"].asString() == "SPECIAL")
- {
+ break;
+ case SPECIAL:
// just use supplied name
- }
- else // normal resident
- {
- std::string name;
- if (gCacheName->getFullName(item->getUUID(), name))
+ break;
+ case INDIVIDUAL:
{
- fullname = name;
+ std::string name;
+ if (gCacheName->getFullName(id, name))
+ {
+ fullname = name;
+ }
+ break;
}
+ default:
+ break;
}
- LLScrollListCell* cell = (LLScrollListCell*)item->getColumn(mNameColumnIndex);
- ((LLScrollListText*)cell)->setText( fullname );
+ // Append optional suffix.
+ if (!suffix.empty())
+ {
+ fullname.append(suffix);
+ }
+
+ LLScrollListCell* cell = item->getColumn(mNameColumnIndex);
+ if (cell)
+ {
+ cell->setValue(fullname);
+ }
dirtyColumns();
@@ -223,15 +293,24 @@ LLScrollListItem* LLNameListCtrl::addElement(const LLSD& value, EAddPosition pos
// public
void LLNameListCtrl::removeNameItem(const LLUUID& agent_id)
{
- BOOL item_exists = selectByID( agent_id );
- if(item_exists)
+ // Find the item specified with agent_id.
+ S32 idx = -1;
+ for (item_list::iterator it = getItemList().begin(); it != getItemList().end(); it++)
{
- S32 index = getItemIndex(getFirstSelected());
- if(index >= 0)
+ LLScrollListItem* item = *it;
+ if (getItemId(item) == agent_id)
{
- deleteSingleItem(index);
+ idx = getItemIndex(item);
+ break;
}
}
+
+ // Remove it.
+ if (idx >= 0)
+ {
+ selectNthItem(idx); // not sure whether this is needed, taken from previous implementation
+ deleteSingleItem(idx);
+ }
}
// public
@@ -256,12 +335,14 @@ void LLNameListCtrl::refresh(const LLUUID& id, const std::string& first,
for (iter = getItemList().begin(); iter != getItemList().end(); iter++)
{
LLScrollListItem* item = *iter;
- if (item->getUUID() == id)
+ if (getItemId(item) == id)
{
LLScrollListCell* cell = (LLScrollListCell*)item->getColumn(0);
- cell = (LLScrollListCell*)item->getColumn(mNameColumnIndex);
-
- ((LLScrollListText*)cell)->setText( fullname );
+ cell = item->getColumn(mNameColumnIndex);
+ if (cell)
+ {
+ cell->setValue(fullname);
+ }
}
}
@@ -273,186 +354,30 @@ void LLNameListCtrl::refresh(const LLUUID& id, const std::string& first,
void LLNameListCtrl::refreshAll(const LLUUID& id, const std::string& first,
const std::string& last, BOOL is_group)
{
- std::set<LLNameListCtrl*>::iterator it;
- for (it = LLNameListCtrl::sInstances.begin();
- it != LLNameListCtrl::sInstances.end();
- ++it)
+ LLInstanceTracker<LLNameListCtrl>::instance_iter it;
+ for (it = beginInstances(); it != endInstances(); ++it)
{
- LLNameListCtrl* ctrl = *it;
- ctrl->refresh(id, first, last, is_group);
+ LLNameListCtrl& ctrl = *it;
+ ctrl.refresh(id, first, last, is_group);
}
}
-// virtual
-LLXMLNodePtr LLNameListCtrl::getXML(bool save_children) const
+void LLNameListCtrl::updateColumns()
{
- LLXMLNodePtr node = LLScrollListCtrl::getXML();
-
- node->createChild("allow_calling_card_drop", TRUE)->setBoolValue(mAllowCallingCardDrop);
+ LLScrollListCtrl::updateColumns();
- if (mNameColumnIndex != 0)
+ if (!mNameColumn.empty())
{
- node->createChild("name_column_index", TRUE)->setIntValue(mNameColumnIndex);
- }
-
- // Don't save contents, probably filled by code
-
- return node;
-}
-
-LLView* LLNameListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("name_list");
- node->getAttributeString("name", name);
-
- LLRect rect;
- createRect(node, rect, parent, LLRect());
-
- BOOL multi_select = FALSE;
- node->getAttributeBOOL("multi_select", multi_select);
-
- BOOL draw_border = TRUE;
- node->getAttributeBOOL("draw_border", draw_border);
-
- BOOL draw_heading = FALSE;
- node->getAttributeBOOL("draw_heading", draw_heading);
-
- S32 name_column_index = 0;
- node->getAttributeS32("name_column_index", name_column_index);
-
- LLUICtrlCallback callback = NULL;
-
- LLNameListCtrl* name_list = new LLNameListCtrl(name,
- rect,
- callback,
- NULL,
- multi_select,
- draw_border,
- name_column_index);
-
- name_list->setDisplayHeading(draw_heading);
- if (node->hasAttribute("heading_height"))
- {
- S32 heading_height;
- node->getAttributeS32("heading_height", heading_height);
- name_list->setHeadingHeight(heading_height);
- }
-
- BOOL allow_calling_card_drop = FALSE;
- if (node->getAttributeBOOL("allow_calling_card_drop", allow_calling_card_drop))
- {
- name_list->setAllowCallingCardDrop(allow_calling_card_drop);
- }
-
- name_list->setScrollListParameters(node);
-
- name_list->initFromXML(node, parent);
-
- LLSD columns;
- S32 index = 0;
- //S32 total_static = 0;
- LLXMLNodePtr child;
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
- {
- if (child->hasName("column"))
- {
- std::string labelname("");
- child->getAttributeString("label", labelname);
-
- std::string columnname(labelname);
- child->getAttributeString("name", columnname);
-
- BOOL columndynamicwidth = FALSE;
- child->getAttributeBOOL("dynamicwidth", columndynamicwidth);
-
- std::string sortname(columnname);
- child->getAttributeString("sort", sortname);
-
- S32 columnwidth = -1;
- if (child->hasAttribute("relwidth"))
- {
- F32 columnrelwidth = 0.f;
- child->getAttributeF32("relwidth", columnrelwidth);
- columns[index]["relwidth"] = columnrelwidth;
- }
- else
- {
- child->getAttributeS32("width", columnwidth);
- columns[index]["width"] = columnwidth;
- }
-
- LLFontGL::HAlign h_align = LLFontGL::LEFT;
- h_align = LLView::selectFontHAlign(child);
-
- //if(!columndynamicwidth) total_static += llmax(0, columnwidth);
-
- columns[index]["name"] = columnname;
- columns[index]["label"] = labelname;
- columns[index]["halign"] = (S32)h_align;
- columns[index]["dynamicwidth"] = columndynamicwidth;
- columns[index]["sort"] = sortname;
-
- index++;
- }
- }
- name_list->setColumnHeadings(columns);
-
-
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
- {
- if (child->hasName("row"))
+ LLScrollListColumn* name_column = getColumn(mNameColumn);
+ if (name_column)
{
- LLUUID id;
- child->getAttributeUUID("id", id);
-
- LLSD row;
-
- row["id"] = id;
-
- S32 column_idx = 0;
- LLXMLNodePtr row_child;
- for (row_child = node->getFirstChild(); row_child.notNull(); row_child = row_child->getNextSibling())
- {
- if (row_child->hasName("column"))
- {
- std::string value = row_child->getTextContents();
-
- std::string columnname("");
- row_child->getAttributeString("name", columnname);
-
- std::string font("");
- row_child->getAttributeString("font", font);
-
- std::string font_style("");
- row_child->getAttributeString("font-style", font_style);
-
- row["columns"][column_idx]["column"] = columnname;
- row["columns"][column_idx]["value"] = value;
- row["columns"][column_idx]["font"] = font;
- row["columns"][column_idx]["font-style"] = font_style;
- column_idx++;
- }
- }
- name_list->addElement(row);
+ mNameColumnIndex = name_column->mIndex;
}
}
-
- std::string contents = node->getTextContents();
-
- typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
- boost::char_separator<char> sep("\t\n");
- tokenizer tokens(contents, sep);
- tokenizer::iterator token_iter = tokens.begin();
-
- while(token_iter != tokens.end())
- {
- const std::string& line = *token_iter;
- name_list->addCommentText(line);
- ++token_iter;
- }
-
- return name_list;
}
-
-
+// static
+LLUUID LLNameListCtrl::getItemId(LLScrollListItem* item)
+{
+ return item->getValue()["uuid"].asUUID();
+}
diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h
index 1b7795ddff..192a3a5afa 100644
--- a/indra/newview/llnamelistctrl.h
+++ b/indra/newview/llnamelistctrl.h
@@ -39,35 +39,68 @@
class LLNameListCtrl
-: public LLScrollListCtrl
+: public LLScrollListCtrl, protected LLInstanceTracker<LLNameListCtrl>
{
public:
- LLNameListCtrl(const std::string& name,
- const LLRect& rect,
- LLUICtrlCallback callback,
- void* userdata,
- BOOL allow_multiple_selection,
- BOOL draw_border = TRUE,
- S32 name_column_index = 0,
- const std::string& tooltip = LLStringUtil::null);
- virtual ~LLNameListCtrl();
-
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
-
+ typedef enum e_name_type
+ {
+ INDIVIDUAL,
+ GROUP,
+ SPECIAL
+ } ENameType;
+
+ // provide names for enums
+ struct NameTypeNames : public LLInitParam::TypeValuesHelper<LLNameListCtrl::ENameType, NameTypeNames>
+ {
+ static void declareValues();
+ };
+
+ struct NameItem : public LLInitParam::Block<NameItem, LLScrollListItem::Params>
+ {
+ Optional<std::string> name;
+ Optional<ENameType, NameTypeNames> target;
+
+ NameItem()
+ : name("name"),
+ target("target", INDIVIDUAL)
+ {}
+ };
+
+ struct NameColumn : public LLInitParam::Choice<NameColumn>
+ {
+ Alternative<S32> column_index;
+ Alternative<std::string> column_name;
+ NameColumn()
+ : column_name("name_column"),
+ column_index("name_column_index", 0)
+ {}
+ };
+
+ struct Params : public LLInitParam::Block<Params, LLScrollListCtrl::Params>
+ {
+ Optional<NameColumn> name_column;
+ Optional<bool> allow_calling_card_drop;
+ Params();
+ };
+
+protected:
+ LLNameListCtrl(const Params&);
+ friend class LLUICtrlFactory;
+public:
// Add a user to the list by name. It will be added, the name
// requested from the cache, and updated as necessary.
- BOOL addNameItem(const LLUUID& agent_id, EAddPosition pos = ADD_BOTTOM,
+ void addNameItem(const LLUUID& agent_id, EAddPosition pos = ADD_BOTTOM,
BOOL enabled = TRUE, std::string& suffix = LLStringUtil::null);
- BOOL addNameItem(LLScrollListItem* item, EAddPosition pos = ADD_BOTTOM);
+ void addNameItem(NameItem& item, EAddPosition pos = ADD_BOTTOM);
- virtual LLScrollListItem* addElement(const LLSD& value, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL);
+ /*virtual*/ LLScrollListItem* addElement(const LLSD& element, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL);
+ LLScrollListItem* addNameItemRow(const NameItem& value, EAddPosition pos = ADD_BOTTOM, std::string& suffix = LLStringUtil::null);
// Add a user to the list by name. It will be added, the name
// requested from the cache, and updated as necessary.
void addGroupNameItem(const LLUUID& group_id, EAddPosition pos = ADD_BOTTOM,
BOOL enabled = TRUE);
- void addGroupNameItem(LLScrollListItem* item, EAddPosition pos = ADD_BOTTOM);
+ void addGroupNameItem(NameItem& item, EAddPosition pos = ADD_BOTTOM);
void removeNameItem(const LLUUID& agent_id);
@@ -77,17 +110,24 @@ public:
static void refreshAll(const LLUUID& id, const std::string& firstname,
const std::string& lastname, BOOL is_group);
- virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
+ // LLView interface
+ /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL drop, EDragAndDropType cargo_type, void *cargo_data,
EAcceptance *accept,
std::string& tooltip_msg);
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
void setAllowCallingCardDrop(BOOL b) { mAllowCallingCardDrop = b; }
+ /*virtual*/ void updateColumns();
+private:
+ void showInspector(const LLUUID& avatar_id, bool is_group);
+ static LLUUID getItemId(LLScrollListItem* item);
+
private:
- static std::set<LLNameListCtrl*> sInstances;
- S32 mNameColumnIndex;
- BOOL mAllowCallingCardDrop;
+ S32 mNameColumnIndex;
+ std::string mNameColumn;
+ BOOL mAllowCallingCardDrop;
};
#endif
diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp
new file mode 100644
index 0000000000..71dc0f9011
--- /dev/null
+++ b/indra/newview/llnavigationbar.cpp
@@ -0,0 +1,765 @@
+/**
+ * @file llnavigationbar.cpp
+ * @brief Navigation bar implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llnavigationbar.h"
+
+#include "llregionhandle.h"
+
+#include "llfloaterreg.h"
+#include "llfocusmgr.h"
+#include "lliconctrl.h"
+#include "llmenugl.h"
+
+#include "llagent.h"
+#include "llviewerregion.h"
+#include "lllandmarkactions.h"
+#include "lllocationhistory.h"
+#include "lllocationinputctrl.h"
+#include "llteleporthistory.h"
+#include "llsearchcombobox.h"
+#include "llsidetray.h"
+#include "llslurl.h"
+#include "llurlsimstring.h"
+#include "llurlregistry.h"
+#include "llurldispatcher.h"
+#include "llviewerinventory.h"
+#include "llviewermenu.h"
+#include "llviewerparcelmgr.h"
+#include "llworldmapmessage.h"
+#include "llappviewer.h"
+#include "llviewercontrol.h"
+#include "llfloatermediabrowser.h"
+#include "llweb.h"
+
+#include "llinventorymodel.h"
+#include "lllandmarkactions.h"
+
+#include "llfavoritesbar.h"
+#include "llagentui.h"
+
+#include <boost/regex.hpp>
+
+//-- LLTeleportHistoryMenuItem -----------------------------------------------
+
+/**
+ * Item look varies depending on the type (backward/current/forward).
+ */
+class LLTeleportHistoryMenuItem : public LLMenuItemCallGL
+{
+public:
+ typedef enum e_item_type
+ {
+ TYPE_BACKWARD,
+ TYPE_CURRENT,
+ TYPE_FORWARD,
+ } EType;
+
+ struct Params : public LLInitParam::Block<Params, LLMenuItemCallGL::Params>
+ {
+ Mandatory<EType> item_type;
+ Optional<const LLFontGL*> back_item_font,
+ current_item_font,
+ forward_item_font;
+ Optional<std::string> back_item_image,
+ forward_item_image;
+ Optional<S32> image_hpad,
+ image_vpad;
+ Params()
+ : item_type(),
+ back_item_font("back_item_font"),
+ current_item_font("current_item_font"),
+ forward_item_font("forward_item_font"),
+ back_item_image("back_item_image"),
+ forward_item_image("forward_item_image"),
+ image_hpad("image_hpad"),
+ image_vpad("image_vpad")
+ {}
+ };
+
+ /*virtual*/ void draw();
+ /*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask);
+ /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
+
+private:
+ LLTeleportHistoryMenuItem(const Params&);
+ friend class LLUICtrlFactory;
+
+ static const S32 ICON_WIDTH = 16;
+ static const S32 ICON_HEIGHT = 16;
+
+ LLIconCtrl* mArrowIcon;
+};
+
+static LLDefaultChildRegistry::Register<LLTeleportHistoryMenuItem> r("teleport_history_menu_item");
+
+
+LLTeleportHistoryMenuItem::LLTeleportHistoryMenuItem(const Params& p)
+: LLMenuItemCallGL(p),
+ mArrowIcon(NULL)
+{
+ // Set appearance depending on the item type.
+ if (p.item_type == TYPE_BACKWARD)
+ {
+ setFont( p.back_item_font );
+ }
+ else if (p.item_type == TYPE_CURRENT)
+ {
+ setFont( p.current_item_font );
+ }
+ else
+ {
+ setFont( p.forward_item_font );
+ }
+
+ LLIconCtrl::Params icon_params;
+ icon_params.name("icon");
+ LLRect rect(0, ICON_HEIGHT, ICON_WIDTH, 0);
+ rect.translate( p.image_hpad, p.image_vpad );
+ icon_params.rect( rect );
+ icon_params.mouse_opaque(false);
+ icon_params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP);
+ icon_params.visible(false);
+
+ mArrowIcon = LLUICtrlFactory::create<LLIconCtrl> (icon_params);
+
+ // no image for the current item
+ if (p.item_type == TYPE_BACKWARD)
+ mArrowIcon->setValue( p.back_item_image() );
+ else if (p.item_type == TYPE_FORWARD)
+ mArrowIcon->setValue( p.forward_item_image() );
+
+ addChild(mArrowIcon);
+}
+
+void LLTeleportHistoryMenuItem::draw()
+{
+ // Draw menu item itself.
+ LLMenuItemCallGL::draw();
+
+ // Draw children if any. *TODO: move this to LLMenuItemGL?
+ LLUICtrl::draw();
+}
+
+void LLTeleportHistoryMenuItem::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+ mArrowIcon->setVisible(TRUE);
+}
+
+void LLTeleportHistoryMenuItem::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ mArrowIcon->setVisible(FALSE);
+}
+
+//-- LNavigationBar ----------------------------------------------------------
+
+/*
+TODO:
+- Load navbar height from saved settings (as it's done for status bar) or think of a better way.
+*/
+
+LLNavigationBar::LLNavigationBar()
+: mTeleportHistoryMenu(NULL),
+ mBtnBack(NULL),
+ mBtnForward(NULL),
+ mBtnHome(NULL),
+ mCmbLocation(NULL),
+ mSearchComboBox(NULL),
+ mPurgeTPHistoryItems(false),
+ mSaveToLocationHistory(false)
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_navigation_bar.xml");
+
+ // set a listener function for LoginComplete event
+ LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLNavigationBar::handleLoginComplete, this));
+
+ // Necessary for focus movement among child controls
+ setFocusRoot(TRUE);
+}
+
+LLNavigationBar::~LLNavigationBar()
+{
+ mTeleportFinishConnection.disconnect();
+ mTeleportFailedConnection.disconnect();
+}
+
+BOOL LLNavigationBar::postBuild()
+{
+ mBtnBack = getChild<LLButton>("back_btn");
+ mBtnForward = getChild<LLButton>("forward_btn");
+ mBtnHome = getChild<LLButton>("home_btn");
+
+ mCmbLocation= getChild<LLLocationInputCtrl>("location_combo");
+ mSearchComboBox = getChild<LLSearchComboBox>("search_combo_box");
+
+ fillSearchComboBox();
+
+ if (!mBtnBack || !mBtnForward || !mBtnHome ||
+ !mCmbLocation || !mSearchComboBox)
+ {
+ llwarns << "Malformed navigation bar" << llendl;
+ return FALSE;
+ }
+
+ mBtnBack->setEnabled(FALSE);
+ mBtnBack->setClickedCallback(boost::bind(&LLNavigationBar::onBackButtonClicked, this));
+ mBtnBack->setHeldDownCallback(boost::bind(&LLNavigationBar::onBackOrForwardButtonHeldDown, this, _2));
+
+ mBtnForward->setEnabled(FALSE);
+ mBtnForward->setClickedCallback(boost::bind(&LLNavigationBar::onForwardButtonClicked, this));
+ mBtnForward->setHeldDownCallback(boost::bind(&LLNavigationBar::onBackOrForwardButtonHeldDown, this, _2));
+
+ mBtnHome->setClickedCallback(boost::bind(&LLNavigationBar::onHomeButtonClicked, this));
+
+ mCmbLocation->setCommitCallback(boost::bind(&LLNavigationBar::onLocationSelection, this));
+
+ mSearchComboBox->setCommitCallback(boost::bind(&LLNavigationBar::onSearchCommit, this));
+
+ mTeleportFinishConnection = LLViewerParcelMgr::getInstance()->
+ setTeleportFinishedCallback(boost::bind(&LLNavigationBar::onTeleportFinished, this, _1));
+
+ mTeleportFailedConnection = LLViewerParcelMgr::getInstance()->
+ setTeleportFailedCallback(boost::bind(&LLNavigationBar::onTeleportFailed, this));
+
+ mDefaultNbRect = getRect();
+ mDefaultFpRect = getChild<LLFavoritesBarCtrl>("favorite")->getRect();
+
+ // we'll be notified on teleport history changes
+ LLTeleportHistory::getInstance()->setHistoryChangedCallback(
+ boost::bind(&LLNavigationBar::onTeleportHistoryChanged, this));
+
+ return TRUE;
+}
+
+void LLNavigationBar::setVisible(BOOL visible)
+{
+ // change visibility of grandparent layout_panel to animate in and out
+ if (getParent())
+ {
+ //to avoid some mysterious bugs like EXT-3352, at least try to log an incorrect parent to ping about a problem.
+ if(getParent()->getName() != "nav_bar_container")
+ {
+ LL_WARNS("LLNavigationBar")<<"NavigationBar has an unknown name of the parent: "<<getParent()->getName()<< LL_ENDL;
+ }
+ getParent()->setVisible(visible);
+ }
+}
+
+
+void LLNavigationBar::fillSearchComboBox()
+{
+ if(!mSearchComboBox)
+ {
+ return;
+ }
+
+ LLSearchHistory::getInstance()->load();
+
+ LLSearchHistory::search_history_list_t search_list =
+ LLSearchHistory::getInstance()->getSearchHistoryList();
+ LLSearchHistory::search_history_list_t::const_iterator it = search_list.begin();
+ for( ; search_list.end() != it; ++it)
+ {
+ LLSearchHistory::LLSearchHistoryItem item = *it;
+ mSearchComboBox->add(item.search_query);
+ }
+}
+
+void LLNavigationBar::draw()
+{
+ if(mPurgeTPHistoryItems)
+ {
+ LLTeleportHistory::getInstance()->purgeItems();
+ onTeleportHistoryChanged();
+ mPurgeTPHistoryItems = false;
+ }
+
+ if (isBackgroundVisible())
+ {
+ static LLUICachedControl<S32> drop_shadow_floater ("DropShadowFloater", 0);
+ static LLUIColor color_drop_shadow = LLUIColorTable::instance().getColor("ColorDropShadow");
+ gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0,
+ color_drop_shadow, drop_shadow_floater );
+ }
+
+ LLPanel::draw();
+}
+
+BOOL LLNavigationBar::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = childrenHandleRightMouseDown( x, y, mask) != NULL;
+ if(!handled && !gMenuHolder->hasVisibleMenu())
+ {
+ show_navbar_context_menu(this,x,y);
+ handled = true;
+ }
+
+ return handled;
+}
+
+void LLNavigationBar::onBackButtonClicked()
+{
+ LLTeleportHistory::getInstance()->goBack();
+}
+
+void LLNavigationBar::onBackOrForwardButtonHeldDown(const LLSD& param)
+{
+ if (param["count"].asInteger() == 0)
+ showTeleportHistoryMenu();
+}
+
+void LLNavigationBar::onForwardButtonClicked()
+{
+ LLTeleportHistory::getInstance()->goForward();
+}
+
+void LLNavigationBar::onHomeButtonClicked()
+{
+ gAgent.teleportHome();
+}
+
+void LLNavigationBar::onSearchCommit()
+{
+ std::string search_query = mSearchComboBox->getSimple();
+ if(!search_query.empty())
+ {
+ LLSearchHistory::getInstance()->addEntry(search_query);
+ }
+ invokeSearch(search_query);
+}
+
+void LLNavigationBar::onTeleportHistoryMenuItemClicked(const LLSD& userdata)
+{
+ int idx = userdata.asInteger();
+ LLTeleportHistory::getInstance()->goToItem(idx);
+}
+
+// This is called when user presses enter in the location input
+// or selects a location from the typed locations dropdown.
+void LLNavigationBar::onLocationSelection()
+{
+ std::string typed_location = mCmbLocation->getSimple();
+ LLStringUtil::trim(typed_location);
+
+ // Will not teleport to empty location.
+ if (typed_location.empty())
+ return;
+
+ LLSD value = mCmbLocation->getSelectedValue();
+
+ if(value.has("item_type"))
+ {
+
+ switch(value["item_type"].asInteger())
+ {
+ case LANDMARK:
+
+ if(value.has("AssetUUID"))
+ {
+
+ gAgent.teleportViaLandmark( LLUUID(value["AssetUUID"].asString()));
+ return;
+ }
+ else
+ {
+ LLInventoryModel::item_array_t landmark_items =
+ LLLandmarkActions::fetchLandmarksByName(typed_location,
+ FALSE);
+ if (!landmark_items.empty())
+ {
+ gAgent.teleportViaLandmark( landmark_items[0]->getAssetUUID());
+ return;
+ }
+ }
+ break;
+
+ case TELEPORT_HISTORY:
+ //in case of teleport item was selected, teleport by position too.
+ case TYPED_REGION_SURL:
+ if(value.has("global_pos"))
+ {
+ gAgent.teleportViaLocation(LLVector3d(value["global_pos"]));
+ return;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ //Let's parse surl or region name
+
+ std::string region_name;
+ LLVector3 local_coords(128, 128, 0);
+ S32 x = 0, y = 0, z = 0;
+ // Is the typed location a SLURL?
+ if (LLSLURL::isSLURL(typed_location))
+ {
+ // Yes. Extract region name and local coordinates from it.
+ if (LLURLSimString::parse(LLSLURL::stripProtocol(typed_location), &region_name, &x, &y, &z))
+ local_coords.set(x, y, z);
+ else
+ return;
+ }else
+ {
+ // assume that an user has typed the {region name} or possible {region_name, parcel}
+ region_name = typed_location.substr(0,typed_location.find(','));
+ }
+
+ // Resolve the region name to its global coordinates.
+ // If resolution succeeds we'll teleport.
+ LLWorldMapMessage::url_callback_t cb = boost::bind(
+ &LLNavigationBar::onRegionNameResponse, this,
+ typed_location, region_name, local_coords, _1, _2, _3, _4);
+ mSaveToLocationHistory = true;
+ LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name, cb, std::string("unused"), false);
+}
+
+void LLNavigationBar::onTeleportFailed()
+{
+ mSaveToLocationHistory = false;
+}
+
+void LLNavigationBar::onTeleportFinished(const LLVector3d& global_agent_pos)
+{
+ if (!mSaveToLocationHistory)
+ return;
+ LLLocationHistory* lh = LLLocationHistory::getInstance();
+
+ //TODO*: do we need convert surl into readable format?
+ std::string location;
+ /*NOTE:
+ * We can't use gAgent.getPositionAgent() in case of local teleport to build location.
+ * At this moment gAgent.getPositionAgent() contains previous coordinates.
+ * according to EXT-65 agent position is being reseted on each frame.
+ */
+ LLAgentUI::buildLocationString(location, LLAgentUI::LOCATION_FORMAT_NO_MATURITY,
+ gAgent.getPosAgentFromGlobal(global_agent_pos));
+ std::string tooltip (LLSLURL::buildSLURLfromPosGlobal(gAgent.getRegion()->getName(), global_agent_pos, false));
+
+ LLLocationHistoryItem item (location,
+ global_agent_pos, tooltip,TYPED_REGION_SURL);// we can add into history only TYPED location
+ //Touch it, if it is at list already, add new location otherwise
+ if ( !lh->touchItem(item) ) {
+ lh->addItem(item);
+ }
+
+ lh->save();
+
+ mSaveToLocationHistory = false;
+
+}
+
+void LLNavigationBar::onTeleportHistoryChanged()
+{
+ // Update navigation controls.
+ LLTeleportHistory* h = LLTeleportHistory::getInstance();
+ int cur_item = h->getCurrentItemIndex();
+ mBtnBack->setEnabled(cur_item > 0);
+ mBtnForward->setEnabled(cur_item < ((int)h->getItems().size() - 1));
+}
+
+void LLNavigationBar::rebuildTeleportHistoryMenu()
+{
+ // Has the pop-up menu been built?
+ if (mTeleportHistoryMenu)
+ {
+ // Clear it.
+ mTeleportHistoryMenu->empty();
+ }
+ else
+ {
+ // Create it.
+ LLMenuGL::Params menu_p;
+ menu_p.name("popup");
+ menu_p.can_tear_off(false);
+ menu_p.visible(false);
+ menu_p.bg_visible(true);
+ menu_p.scrollable(true);
+ mTeleportHistoryMenu = LLUICtrlFactory::create<LLMenuGL>(menu_p);
+
+ addChild(mTeleportHistoryMenu);
+ }
+
+ // Populate the menu with teleport history items.
+ LLTeleportHistory* hist = LLTeleportHistory::getInstance();
+ const LLTeleportHistory::slurl_list_t& hist_items = hist->getItems();
+ int cur_item = hist->getCurrentItemIndex();
+
+ // Items will be shown in the reverse order, just like in Firefox.
+ for (int i = (int)hist_items.size()-1; i >= 0; i--)
+ {
+ LLTeleportHistoryMenuItem::EType type;
+ if (i < cur_item)
+ type = LLTeleportHistoryMenuItem::TYPE_BACKWARD;
+ else if (i > cur_item)
+ type = LLTeleportHistoryMenuItem::TYPE_FORWARD;
+ else
+ type = LLTeleportHistoryMenuItem::TYPE_CURRENT;
+
+ LLTeleportHistoryMenuItem::Params item_params;
+ item_params.label = item_params.name = hist_items[i].mTitle;
+ item_params.item_type = type;
+ item_params.on_click.function(boost::bind(&LLNavigationBar::onTeleportHistoryMenuItemClicked, this, i));
+ LLTeleportHistoryMenuItem* new_itemp = LLUICtrlFactory::create<LLTeleportHistoryMenuItem>(item_params);
+ //new_itemp->setFont()
+ mTeleportHistoryMenu->addChild(new_itemp);
+ }
+}
+
+void LLNavigationBar::onRegionNameResponse(
+ std::string typed_location,
+ std::string region_name,
+ LLVector3 local_coords,
+ U64 region_handle, const std::string& url, const LLUUID& snapshot_id, bool teleport)
+{
+ // Invalid location?
+ if (!region_handle)
+ {
+ // handle any secondlife:// SLapps, or
+ // display http:// URLs in the media browser, or
+ // anything else is sent to the search floater
+ if (LLUrlRegistry::instance().isUrl(typed_location))
+ {
+ if (! LLURLDispatcher::dispatchFromTextEditor(typed_location))
+ {
+ LLWeb::loadURL(typed_location);
+ }
+ }
+ else
+ {
+ invokeSearch(typed_location);
+ }
+ return;
+ }
+
+ // Teleport to the location.
+ LLVector3d region_pos = from_region_handle(region_handle);
+ LLVector3d global_pos = region_pos + (LLVector3d) local_coords;
+
+ llinfos << "Teleporting to: " << LLSLURL::buildSLURLfromPosGlobal(region_name, global_pos, false) << llendl;
+ gAgent.teleportViaLocation(global_pos);
+}
+
+void LLNavigationBar::showTeleportHistoryMenu()
+{
+ // Don't show the popup if teleport history is empty.
+ if (LLTeleportHistory::getInstance()->isEmpty())
+ {
+ lldebugs << "Teleport history is empty, will not show the menu." << llendl;
+ return;
+ }
+
+ rebuildTeleportHistoryMenu();
+
+ if (mTeleportHistoryMenu == NULL)
+ return;
+
+ // *TODO: why to draw/update anything before showing the menu?
+ mTeleportHistoryMenu->buildDrawLabels();
+ mTeleportHistoryMenu->updateParent(LLMenuGL::sMenuContainer);
+ const S32 MENU_SPAWN_PAD = -1;
+ LLMenuGL::showPopup(mBtnBack, mTeleportHistoryMenu, 0, MENU_SPAWN_PAD);
+
+ // *HACK pass the mouse capturing to the drop-down menu
+ gFocusMgr.setMouseCapture( NULL );
+}
+
+void LLNavigationBar::handleLoginComplete()
+{
+ mCmbLocation->handleLoginComplete();
+}
+
+void LLNavigationBar::invokeSearch(std::string search_text)
+{
+ LLFloaterReg::showInstance("search", LLSD().with("category", "all").with("id", LLSD(search_text)));
+}
+
+void LLNavigationBar::clearHistoryCache()
+{
+ mCmbLocation->removeall();
+ LLLocationHistory* lh = LLLocationHistory::getInstance();
+ lh->removeItems();
+ lh->save();
+ mPurgeTPHistoryItems= true;
+}
+
+int LLNavigationBar::getDefNavBarHeight()
+{
+ return mDefaultNbRect.getHeight();
+}
+int LLNavigationBar::getDefFavBarHeight()
+{
+ return mDefaultFpRect.getHeight();
+}
+
+void LLNavigationBar::showNavigationPanel(BOOL visible)
+{
+ bool fpVisible = gSavedSettings.getBOOL("ShowNavbarFavoritesPanel");
+
+ LLFavoritesBarCtrl* fb = getChild<LLFavoritesBarCtrl>("favorite");
+ LLPanel* navPanel = getChild<LLPanel>("navigation_panel");
+
+ LLRect nbRect(getRect());
+ LLRect fbRect(fb->getRect());
+
+ navPanel->setVisible(visible);
+
+ if (visible)
+ {
+ if (fpVisible)
+ {
+ // Navigation Panel must be shown. Favorites Panel is visible.
+
+ nbRect.setLeftTopAndSize(nbRect.mLeft, nbRect.mTop, nbRect.getWidth(), mDefaultNbRect.getHeight());
+ fbRect.setLeftTopAndSize(fbRect.mLeft, mDefaultFpRect.mTop, fbRect.getWidth(), fbRect.getHeight());
+
+ // this is duplicated in 'else' section because it should be called BEFORE fb->reshape
+ reshape(nbRect.getWidth(), nbRect.getHeight());
+ setRect(nbRect);
+ // propagate size to parent container
+ getParent()->reshape(nbRect.getWidth(), nbRect.getHeight());
+
+ fb->reshape(fbRect.getWidth(), fbRect.getHeight());
+ fb->setRect(fbRect);
+ }
+ else
+ {
+ // Navigation Panel must be shown. Favorites Panel is hidden.
+
+ S32 height = mDefaultNbRect.getHeight() - mDefaultFpRect.getHeight();
+ nbRect.setLeftTopAndSize(nbRect.mLeft, nbRect.mTop, nbRect.getWidth(), height);
+
+ reshape(nbRect.getWidth(), nbRect.getHeight());
+ setRect(nbRect);
+ getParent()->reshape(nbRect.getWidth(), nbRect.getHeight());
+ }
+ }
+ else
+ {
+ if (fpVisible)
+ {
+ // Navigation Panel must be hidden. Favorites Panel is visible.
+
+ nbRect.setLeftTopAndSize(nbRect.mLeft, nbRect.mTop, nbRect.getWidth(), fbRect.getHeight());
+ fbRect.setLeftTopAndSize(fbRect.mLeft, fbRect.getHeight(), fbRect.getWidth(), fbRect.getHeight());
+
+ // this is duplicated in 'else' section because it should be called BEFORE fb->reshape
+ reshape(nbRect.getWidth(), nbRect.getHeight());
+ setRect(nbRect);
+ getParent()->reshape(nbRect.getWidth(), nbRect.getHeight());
+
+ fb->reshape(fbRect.getWidth(), fbRect.getHeight());
+ fb->setRect(fbRect);
+ }
+ else
+ {
+ // Navigation Panel must be hidden. Favorites Panel is hidden.
+
+ nbRect.setLeftTopAndSize(nbRect.mLeft, nbRect.mTop, nbRect.getWidth(), 0);
+
+ reshape(nbRect.getWidth(), nbRect.getHeight());
+ setRect(nbRect);
+ getParent()->reshape(nbRect.getWidth(), nbRect.getHeight());
+ }
+ }
+
+ childSetVisible("bg_icon", fpVisible);
+ childSetVisible("bg_icon_no_fav", !fpVisible);
+}
+
+void LLNavigationBar::showFavoritesPanel(BOOL visible)
+{
+ bool npVisible = gSavedSettings.getBOOL("ShowNavbarNavigationPanel");
+
+ LLFavoritesBarCtrl* fb = getChild<LLFavoritesBarCtrl>("favorite");
+
+ LLRect nbRect(getRect());
+ LLRect fbRect(fb->getRect());
+
+ if (visible)
+ {
+ if (npVisible)
+ {
+ // Favorites Panel must be shown. Navigation Panel is visible.
+
+ S32 fbHeight = fbRect.getHeight();
+ S32 newHeight = nbRect.getHeight() + fbHeight;
+
+ nbRect.setLeftTopAndSize(nbRect.mLeft, nbRect.mTop, nbRect.getWidth(), newHeight);
+ fbRect.setLeftTopAndSize(mDefaultFpRect.mLeft, mDefaultFpRect.mTop, fbRect.getWidth(), fbRect.getHeight());
+ }
+ else
+ {
+ // Favorites Panel must be shown. Navigation Panel is hidden.
+
+ S32 fpHeight = mDefaultFpRect.getHeight();
+ nbRect.setLeftTopAndSize(nbRect.mLeft, nbRect.mTop, nbRect.getWidth(), fpHeight);
+ fbRect.setLeftTopAndSize(fbRect.mLeft, fpHeight, fbRect.getWidth(), fpHeight);
+ }
+
+ reshape(nbRect.getWidth(), nbRect.getHeight());
+ setRect(nbRect);
+ getParent()->reshape(nbRect.getWidth(), nbRect.getHeight());
+
+ fb->reshape(fbRect.getWidth(), fbRect.getHeight());
+ fb->setRect(fbRect);
+ }
+ else
+ {
+ if (npVisible)
+ {
+ // Favorites Panel must be hidden. Navigation Panel is visible.
+
+ S32 fbHeight = fbRect.getHeight();
+ S32 newHeight = nbRect.getHeight() - fbHeight;
+
+ nbRect.setLeftTopAndSize(nbRect.mLeft, nbRect.mTop, nbRect.getWidth(), newHeight);
+ }
+ else
+ {
+ // Favorites Panel must be hidden. Navigation Panel is hidden.
+
+ nbRect.setLeftTopAndSize(nbRect.mLeft, nbRect.mTop, nbRect.getWidth(), 0);
+ }
+
+ reshape(nbRect.getWidth(), nbRect.getHeight());
+ setRect(nbRect);
+ getParent()->reshape(nbRect.getWidth(), nbRect.getHeight());
+ }
+
+ childSetVisible("bg_icon", visible);
+ childSetVisible("bg_icon_no_fav", !visible);
+
+ fb->setVisible(visible);
+}
diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h
new file mode 100644
index 0000000000..9d0687f193
--- /dev/null
+++ b/indra/newview/llnavigationbar.h
@@ -0,0 +1,111 @@
+/**
+ * @file llnavigationbar.h
+ * @brief Navigation bar definition
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLNAVIGATIONBAR_H
+#define LL_LLNAVIGATIONBAR_H
+
+#include "llpanel.h"
+
+class LLButton;
+class LLLocationInputCtrl;
+class LLMenuGL;
+class LLSearchEditor;
+class LLSearchComboBox;
+
+/**
+ * Web browser-like navigation bar.
+ */
+class LLNavigationBar
+ : public LLPanel, public LLSingleton<LLNavigationBar>
+{
+ LOG_CLASS(LLNavigationBar);
+
+public:
+ LLNavigationBar();
+ virtual ~LLNavigationBar();
+
+ /*virtual*/ void draw();
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void setVisible(BOOL visible);
+
+ void handleLoginComplete();
+ void clearHistoryCache();
+
+ void showNavigationPanel(BOOL visible);
+ void showFavoritesPanel(BOOL visible);
+
+ int getDefNavBarHeight();
+ int getDefFavBarHeight();
+
+private:
+
+ void rebuildTeleportHistoryMenu();
+ void showTeleportHistoryMenu();
+ void invokeSearch(std::string search_text);
+ // callbacks
+ void onTeleportHistoryMenuItemClicked(const LLSD& userdata);
+ void onTeleportHistoryChanged();
+ void onBackButtonClicked();
+ void onBackOrForwardButtonHeldDown(const LLSD& param);
+ void onForwardButtonClicked();
+ void onHomeButtonClicked();
+ void onLocationSelection();
+ void onLocationPrearrange(const LLSD& data);
+ void onSearchCommit();
+ void onTeleportFinished(const LLVector3d& global_agent_pos);
+ void onTeleportFailed();
+ void onRegionNameResponse(
+ std::string typed_location,
+ std::string region_name,
+ LLVector3 local_coords,
+ U64 region_handle, const std::string& url,
+ const LLUUID& snapshot_id, bool teleport);
+
+ void fillSearchComboBox();
+
+ LLMenuGL* mTeleportHistoryMenu;
+ LLButton* mBtnBack;
+ LLButton* mBtnForward;
+ LLButton* mBtnHome;
+ LLSearchComboBox* mSearchComboBox;
+ LLLocationInputCtrl* mCmbLocation;
+ LLRect mDefaultNbRect;
+ LLRect mDefaultFpRect;
+ boost::signals2::connection mTeleportFailedConnection;
+ boost::signals2::connection mTeleportFinishConnection;
+ bool mPurgeTPHistoryItems;
+ // if true, save location to location history when teleport finishes
+ bool mSaveToLocationHistory;
+};
+
+#endif
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
new file mode 100644
index 0000000000..0a8d020b4f
--- /dev/null
+++ b/indra/newview/llnearbychat.cpp
@@ -0,0 +1,278 @@
+/**
+ * @file LLNearbyChat.cpp
+ * @brief Nearby chat history scrolling panel implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llnearbychat.h"
+#include "llviewercontrol.h"
+#include "llviewerwindow.h"
+#include "llrootview.h"
+//#include "llchatitemscontainerctrl.h"
+#include "lliconctrl.h"
+#include "llsidetray.h"
+#include "llfocusmgr.h"
+#include "llresizebar.h"
+#include "llresizehandle.h"
+#include "llmenugl.h"
+#include "llviewermenu.h"//for gMenuHolder
+
+#include "llnearbychathandler.h"
+#include "llchannelmanager.h"
+
+#include "llagent.h" // gAgent
+#include "llfloaterscriptdebug.h"
+#include "llchathistory.h"
+#include "llstylemap.h"
+
+#include "lldraghandle.h"
+
+#include "llbottomtray.h"
+#include "llnearbychatbar.h"
+#include "llfloaterreg.h"
+#include "lltrans.h"
+
+static const S32 RESIZE_BAR_THICKNESS = 3;
+
+LLNearbyChat::LLNearbyChat(const LLSD& key)
+ : LLDockableFloater(NULL, false, false, key)
+ ,mChatHistory(NULL)
+{
+
+}
+
+LLNearbyChat::~LLNearbyChat()
+{
+}
+
+BOOL LLNearbyChat::postBuild()
+{
+ //menu
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+
+ enable_registrar.add("NearbyChat.Check", boost::bind(&LLNearbyChat::onNearbyChatCheckContextMenuItem, this, _2));
+ registrar.add("NearbyChat.Action", boost::bind(&LLNearbyChat::onNearbyChatContextMenuItemClicked, this, _2));
+
+
+ LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if(menu)
+ mPopupMenuHandle = menu->getHandle();
+
+ gSavedSettings.declareS32("nearbychat_showicons_and_names",2,"NearByChat header settings",true);
+
+ mChatHistory = getChild<LLChatHistory>("chat_history");
+
+ if(!LLDockableFloater::postBuild())
+ return false;
+
+ if (getDockControl() == NULL)
+ {
+ setDockControl(new LLDockControl(
+ LLBottomTray::getInstance()->getNearbyChatBar(), this,
+ getDockTongue(), LLDockControl::TOP, boost::bind(&LLNearbyChat::getAllowedRect, this, _1)));
+ }
+
+ setIsChrome(true);
+ //chrome="true" hides floater caption
+ if (mDragHandle)
+ mDragHandle->setTitleVisible(TRUE);
+
+ return true;
+}
+
+
+void LLNearbyChat::applySavedVariables()
+{
+ if (mRectControl.size() > 1)
+ {
+ const LLRect& rect = LLUI::sSettingGroups["floater"]->getRect(mRectControl);
+ if(!rect.isEmpty() && rect.isValid())
+ {
+ reshape(rect.getWidth(), rect.getHeight());
+ setRect(rect);
+ }
+ }
+
+
+ if(!LLUI::sSettingGroups["floater"]->controlExists(mDocStateControl))
+ {
+ setDocked(true);
+ }
+ else
+ {
+ if (mDocStateControl.size() > 1)
+ {
+ bool dockState = LLUI::sSettingGroups["floater"]->getBOOL(mDocStateControl);
+ setDocked(dockState);
+ }
+ }
+}
+
+std::string appendTime()
+{
+ time_t utc_time;
+ utc_time = time_corrected();
+ std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:["
+ +LLTrans::getString("TimeMin")+"]";
+
+ LLSD substitution;
+
+ substitution["datetime"] = (S32) utc_time;
+ LLStringUtil::format (timeStr, substitution);
+
+ return timeStr;
+}
+
+
+void LLNearbyChat::addMessage(const LLChat& chat,bool archive)
+{
+ if (chat.mChatType == CHAT_TYPE_DEBUG_MSG)
+ {
+ if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE)
+ return;
+ if (gSavedSettings.getS32("ShowScriptErrorsLocation")== 1)// show error in window //("ScriptErrorsAsChat"))
+ {
+
+ LLColor4 txt_color;
+
+ LLViewerChat::getChatColor(chat,txt_color);
+
+ LLFloaterScriptDebug::addScriptLine(chat.mText,
+ chat.mFromName,
+ txt_color,
+ chat.mFromID);
+ return;
+ }
+ }
+
+ LLChat& tmp_chat = const_cast<LLChat&>(chat);
+
+ if(tmp_chat.mTimeStr.empty())
+ tmp_chat.mTimeStr = appendTime();
+
+ bool use_plain_text_chat_history = gSavedSettings.getBOOL("PlainTextChatHistory");
+
+ if (!chat.mMuted)
+ {
+ tmp_chat.mFromName = chat.mFromName;
+ mChatHistory->appendMessage(chat, use_plain_text_chat_history);
+ }
+
+ if(archive)
+ {
+ mMessageArchive.push_back(chat);
+ if(mMessageArchive.size()>200)
+ mMessageArchive.erase(mMessageArchive.begin());
+ }
+}
+
+void LLNearbyChat::onNearbySpeakers()
+{
+ LLSD param;
+ param["people_panel_tab_name"] = "nearby_panel";
+ LLSideTray::getInstance()->showPanel("panel_people",param);
+}
+
+
+void LLNearbyChat::onNearbyChatContextMenuItemClicked(const LLSD& userdata)
+{
+}
+bool LLNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata)
+{
+ std::string str = userdata.asString();
+ if(str == "nearby_people")
+ onNearbySpeakers();
+ return false;
+}
+
+void LLNearbyChat::setVisible(BOOL visible)
+{
+ if(visible)
+ {
+ LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID")));
+ if(chat_channel)
+ {
+ chat_channel->removeToastsFromChannel();
+ }
+ }
+
+ LLDockableFloater::setVisible(visible);
+}
+
+void LLNearbyChat::onOpen(const LLSD& key )
+{
+ LLDockableFloater::onOpen(key);
+}
+
+void LLNearbyChat::setRect (const LLRect &rect)
+{
+ LLDockableFloater::setRect(rect);
+}
+
+void LLNearbyChat::getAllowedRect(LLRect& rect)
+{
+ rect = gViewerWindow->getWorldViewRectScaled();
+}
+
+void LLNearbyChat::updateChatHistoryStyle()
+{
+ mChatHistory->clear();
+ for(std::vector<LLChat>::iterator it = mMessageArchive.begin();it!=mMessageArchive.end();++it)
+ {
+ addMessage(*it,false);
+ }
+}
+
+//static
+void LLNearbyChat::processChatHistoryStyleUpdate(const LLSD& newvalue)
+{
+ LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
+ if(nearby_chat)
+ nearby_chat->updateChatHistoryStyle();
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLNearbyChat::onFocusReceived()
+{
+ setBackgroundOpaque(true);
+ LLPanel::onFocusReceived();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLNearbyChat::onFocusLost()
+{
+ setBackgroundOpaque(false);
+ LLPanel::onFocusLost();
+}
diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h
new file mode 100644
index 0000000000..938b77df7a
--- /dev/null
+++ b/indra/newview/llnearbychat.h
@@ -0,0 +1,85 @@
+/**
+ * @file llnearbychat.h
+ * @brief nearby chat history scrolling panel implementation
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLNEARBYCHAT_H_
+#define LL_LLNEARBYCHAT_H_
+
+#include "lldockablefloater.h"
+#include "llscrollbar.h"
+#include "llviewerchat.h"
+
+class LLResizeBar;
+class LLChatHistory;
+
+class LLNearbyChat: public LLDockableFloater
+{
+public:
+ LLNearbyChat(const LLSD& key);
+ ~LLNearbyChat();
+
+ BOOL postBuild ();
+ void addMessage (const LLChat& message,bool archive = true);
+ void onNearbyChatContextMenuItemClicked(const LLSD& userdata);
+ bool onNearbyChatCheckContextMenuItem(const LLSD& userdata);
+
+ // focus overrides
+ /*virtual*/ void onFocusLost();
+ /*virtual*/ void onFocusReceived();
+
+ /*virtual*/ void onOpen (const LLSD& key);
+
+ /*virtual*/ void setVisible(BOOL visible);
+
+ virtual void setRect (const LLRect &rect);
+
+ virtual void updateChatHistoryStyle();
+
+ static void processChatHistoryStyleUpdate(const LLSD& newvalue);
+
+private:
+ virtual void applySavedVariables();
+
+ void getAllowedRect (LLRect& rect);
+
+ void onNearbySpeakers ();
+
+
+private:
+ LLHandle<LLView> mPopupMenuHandle;
+ LLChatHistory* mChatHistory;
+
+ std::vector<LLChat> mMessageArchive;
+};
+
+#endif
+
+
diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp
new file mode 100644
index 0000000000..6cf8bcb417
--- /dev/null
+++ b/indra/newview/llnearbychatbar.cpp
@@ -0,0 +1,848 @@
+/**
+ * @file llnearbychatbar.cpp
+ * @brief LLNearbyChatBar class implementation
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "message.h"
+
+#include "llfloaterreg.h"
+#include "lltrans.h"
+
+#include "llnearbychatbar.h"
+#include "llbottomtray.h"
+#include "llagent.h"
+#include "llgesturemgr.h"
+#include "llmultigesture.h"
+#include "llkeyboard.h"
+#include "llanimationstates.h"
+#include "llviewerstats.h"
+#include "llcommandhandler.h"
+#include "llviewercontrol.h"
+#include "llnavigationbar.h"
+#include "llwindow.h"
+#include "llviewerwindow.h"
+#include "llrootview.h"
+
+S32 LLNearbyChatBar::sLastSpecialChatChannel = 0;
+
+// legacy callback glue
+void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel);
+
+static LLDefaultChildRegistry::Register<LLGestureComboList> r("gesture_combo_list");
+
+struct LLChatTypeTrigger {
+ std::string name;
+ EChatType type;
+};
+
+static LLChatTypeTrigger sChatTypeTriggers[] = {
+ { "/whisper" , CHAT_TYPE_WHISPER},
+ { "/shout" , CHAT_TYPE_SHOUT}
+};
+
+LLGestureComboList::Params::Params()
+: combo_button("combo_button"),
+ combo_list("combo_list")
+{
+}
+
+LLGestureComboList::LLGestureComboList(const LLGestureComboList::Params& p)
+: LLUICtrl(p)
+ , mLabel(p.label)
+ , mViewAllItemIndex(0)
+{
+ LLButton::Params button_params = p.combo_button;
+ button_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_BOTTOM|FOLLOWS_RIGHT);
+
+ mButton = LLUICtrlFactory::create<LLButton>(button_params);
+ mButton->reshape(getRect().getWidth(),getRect().getHeight());
+ mButton->setCommitCallback(boost::bind(&LLGestureComboList::onButtonCommit, this));
+
+ addChild(mButton);
+
+ LLScrollListCtrl::Params params = p.combo_list;
+ params.name("GestureComboList");
+ params.commit_callback.function(boost::bind(&LLGestureComboList::onItemSelected, this, _2));
+ params.visible(false);
+ params.commit_on_keyboard_movement(false);
+
+ mList = LLUICtrlFactory::create<LLScrollListCtrl>(params);
+
+ // *HACK: adding list as a child to NonSideTrayView to make it fully visible without
+ // making it top control (because it would cause problems).
+ gViewerWindow->getNonSideTrayView()->addChild(mList);
+ mList->setVisible(FALSE);
+
+ //****************************Gesture Part********************************/
+
+ setCommitCallback(boost::bind(&LLGestureComboList::onCommitGesture, this));
+
+ // now register us as observer since we have a place to put the results
+ LLGestureManager::instance().addObserver(this);
+
+ // refresh list from current active gestures
+ refreshGestures();
+
+ setFocusLostCallback(boost::bind(&LLGestureComboList::hideList, this));
+}
+
+BOOL LLGestureComboList::handleKey(KEY key, MASK mask, BOOL called_from_parent)
+{
+ BOOL handled = FALSE;
+
+ if (key == KEY_ESCAPE && mask == MASK_NONE )
+ {
+ hideList();
+ handled = TRUE;
+ }
+ else
+ {
+ handled = mList->handleKey(key, mask, called_from_parent);
+ }
+
+ return handled;
+}
+
+void LLGestureComboList::showList()
+{
+ LLRect rect = mList->getRect();
+ LLRect screen;
+ mButton->localRectToScreen(getRect(), &screen);
+
+ // Calculating amount of space between the navigation bar and gestures combo
+ LLNavigationBar* nb = LLNavigationBar::getInstance();
+
+ S32 x, nb_bottom;
+ nb->localPointToScreen(0, 0, &x, &nb_bottom);
+
+ S32 max_height = nb_bottom - screen.mTop;
+ mList->calcColumnWidths();
+ rect.setOriginAndSize(screen.mLeft, screen.mTop, llmax(mList->getMaxContentWidth(),mButton->getRect().getWidth()), max_height);
+
+ mList->setRect(rect);
+ mList->fitContents( llmax(mList->getMaxContentWidth(),mButton->getRect().getWidth()), max_height);
+
+ gFocusMgr.setKeyboardFocus(this);
+
+ // Show the list and push the button down
+ mButton->setToggleState(TRUE);
+ mList->setVisible(TRUE);
+}
+
+void LLGestureComboList::onButtonCommit()
+{
+ if (!mList->getVisible())
+ {
+ // highlight the last selected item from the original selection before potentially selecting a new item
+ // as visual cue to original value of combo box
+ LLScrollListItem* last_selected_item = mList->getLastSelectedItem();
+ if (last_selected_item)
+ {
+ mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item));
+ }
+
+ if (mList->getItemCount() != 0)
+ {
+ showList();
+ }
+ }
+ else
+ {
+ hideList();
+ }
+}
+
+void LLGestureComboList::hideList()
+{
+ if (mList->getVisible())
+ {
+ mButton->setToggleState(FALSE);
+ mList->setVisible(FALSE);
+ mList->mouseOverHighlightNthItem(-1);
+ gFocusMgr.setKeyboardFocus(NULL);
+ }
+}
+
+S32 LLGestureComboList::getCurrentIndex() const
+{
+ LLScrollListItem* item = mList->getFirstSelected();
+ if( item )
+ {
+ return mList->getItemIndex( item );
+ }
+ return -1;
+}
+
+void LLGestureComboList::onItemSelected(const LLSD& data)
+{
+ const std::string name = mList->getSelectedItemLabel();
+
+ S32 cur_id = getCurrentIndex();
+ mLastSelectedIndex = cur_id;
+ if (cur_id != mList->getItemCount()-1 && cur_id != -1)
+ {
+ mButton->setLabel(name);
+ }
+
+ // hiding the list reasserts the old value stored in the text editor/dropdown button
+ hideList();
+
+ // commit does the reverse, asserting the value in the list
+ onCommit();
+}
+
+void LLGestureComboList::sortByName(bool ascending)
+{
+ mList->sortOnce(0, ascending);
+}
+
+LLSD LLGestureComboList::getValue() const
+{
+ LLScrollListItem* item = mList->getFirstSelected();
+ if( item )
+ {
+ return item->getValue();
+ }
+ else
+ {
+ return LLSD();
+ }
+}
+
+void LLGestureComboList::refreshGestures()
+{
+ //store current selection so we can maintain it
+ LLSD cur_gesture = getValue();
+
+ mList->selectFirstItem();
+ mList->clearRows();
+ mGestures.clear();
+
+ LLGestureManager::item_map_t::const_iterator it;
+ const LLGestureManager::item_map_t& active_gestures = LLGestureManager::instance().getActiveGestures();
+ LLSD::Integer idx(0);
+ for (it = active_gestures.begin(); it != active_gestures.end(); ++it)
+ {
+ LLMultiGesture* gesture = (*it).second;
+ if (gesture)
+ {
+ mList->addSimpleElement(gesture->mName, ADD_BOTTOM, LLSD(idx));
+ mGestures.push_back(gesture);
+ idx++;
+ }
+ }
+
+ sortByName();
+
+ // store index followed by the last added Gesture and add View All item at bottom
+ mViewAllItemIndex = idx;
+
+ mList->addSimpleElement(LLTrans::getString("ViewAllGestures"), ADD_BOTTOM, LLSD(mViewAllItemIndex));
+
+ // Insert label after sorting, at top, with separator below it
+ mList->addSeparator(ADD_TOP);
+ mList->addSimpleElement(mLabel, ADD_TOP);
+
+ if (cur_gesture.isDefined())
+ {
+ mList->selectByValue(cur_gesture);
+
+ }
+ else
+ {
+ mList->selectFirstItem();
+ }
+
+ LLCtrlListInterface* gestures = getListInterface();
+ LLMultiGesture* gesture = NULL;
+
+ if (gestures)
+ {
+ S32 index = gestures->getSelectedValue().asInteger();
+ if(index > 0)
+ gesture = mGestures.at(index);
+ }
+
+ if(gesture && LLGestureManager::instance().isGesturePlaying(gesture))
+ {
+ return;
+ }
+
+ mButton->setLabel(mLabel);
+}
+
+void LLGestureComboList::onCommitGesture()
+{
+ LLCtrlListInterface* gestures = getListInterface();
+ if (gestures)
+ {
+ S32 index = gestures->getFirstSelectedIndex();
+ if (index == 0)
+ {
+ return;
+ }
+
+ index = gestures->getSelectedValue().asInteger();
+
+ if (mViewAllItemIndex == index)
+ {
+ // The same behavior as Ctrl+G. EXT-823
+ LLFloaterReg::toggleInstance("gestures");
+ gestures->selectFirstItem();
+ return;
+ }
+
+ LLMultiGesture* gesture = mGestures.at(index);
+ if(gesture)
+ {
+ LLGestureManager::instance().playGesture(gesture);
+ if(!gesture->mReplaceText.empty())
+ {
+ LLNearbyChatBar::sendChatFromViewer(gesture->mReplaceText, CHAT_TYPE_NORMAL, FALSE);
+ }
+ }
+ }
+}
+
+LLGestureComboList::~LLGestureComboList()
+{
+ LLGestureManager::instance().removeObserver(this);
+}
+
+LLNearbyChatBar::LLNearbyChatBar()
+ : LLPanel()
+ , mChatBox(NULL)
+{
+ mSpeakerMgr = LLLocalSpeakerMgr::getInstance();
+}
+
+//virtual
+BOOL LLNearbyChatBar::postBuild()
+{
+ mChatBox = getChild<LLLineEditor>("chat_box");
+
+ mChatBox->setCommitCallback(boost::bind(&LLNearbyChatBar::onChatBoxCommit, this));
+ mChatBox->setKeystrokeCallback(&onChatBoxKeystroke, this);
+ mChatBox->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this));
+
+ mChatBox->setIgnoreArrowKeys( FALSE );
+ mChatBox->setCommitOnFocusLost( FALSE );
+ mChatBox->setRevertOnEsc( FALSE );
+ mChatBox->setIgnoreTab(TRUE);
+ mChatBox->setPassDelete(TRUE);
+ mChatBox->setReplaceNewlinesWithSpaces(FALSE);
+ mChatBox->setEnableLineHistory(TRUE);
+
+ mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator");
+ mOutputMonitor->setVisible(FALSE);
+
+ return TRUE;
+}
+
+//static
+LLNearbyChatBar* LLNearbyChatBar::getInstance()
+{
+ return LLBottomTray::getInstance() ? LLBottomTray::getInstance()->getNearbyChatBar() : NULL;
+}
+
+//static
+bool LLNearbyChatBar::instanceExists()
+{
+ return LLBottomTray::instanceExists() && LLBottomTray::getInstance()->getNearbyChatBar() != NULL;
+}
+
+void LLNearbyChatBar::draw()
+{
+ displaySpeakingIndicator();
+ LLPanel::draw();
+}
+
+std::string LLNearbyChatBar::getCurrentChat()
+{
+ return mChatBox ? mChatBox->getText() : LLStringUtil::null;
+}
+
+// virtual
+BOOL LLNearbyChatBar::handleKeyHere( KEY key, MASK mask )
+{
+ BOOL handled = FALSE;
+
+ // ALT-RETURN is reserved for windowed/fullscreen toggle
+ if( KEY_RETURN == key && mask == MASK_CONTROL)
+ {
+ // shout
+ sendChat(CHAT_TYPE_SHOUT);
+ handled = TRUE;
+ }
+
+ return handled;
+}
+
+S32 LLNearbyChatBar::getMinWidth() const
+{
+ static S32 min_width = -1;
+
+ if (min_width < 0)
+ {
+ const std::string& s = getString("min_width");
+ min_width = !s.empty() ? atoi(s.c_str()) : 300;
+ }
+
+ return min_width;
+}
+
+S32 LLNearbyChatBar::getMaxWidth() const
+{
+ static S32 max_width = -1;
+
+ if (max_width < 0)
+ {
+ const std::string& s = getString("max_width");
+ max_width = !s.empty() ? atoi(s.c_str()) : 510;
+ }
+
+ return max_width;
+}
+
+BOOL LLNearbyChatBar::matchChatTypeTrigger(const std::string& in_str, std::string* out_str)
+{
+ U32 in_len = in_str.length();
+ S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers);
+
+ for (S32 n = 0; n < cnt; n++)
+ {
+ if (in_len > sChatTypeTriggers[n].name.length())
+ continue;
+
+ std::string trigger_trunc = sChatTypeTriggers[n].name;
+ LLStringUtil::truncate(trigger_trunc, in_len);
+
+ if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc))
+ {
+ *out_str = sChatTypeTriggers[n].name;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+void LLNearbyChatBar::onChatBoxKeystroke(LLLineEditor* caller, void* userdata)
+{
+
+ LLNearbyChatBar* self = (LLNearbyChatBar *)userdata;
+
+ LLWString raw_text = self->mChatBox->getWText();
+
+ // Can't trim the end, because that will cause autocompletion
+ // to eat trailing spaces that might be part of a gesture.
+ LLWStringUtil::trimHead(raw_text);
+
+ S32 length = raw_text.length();
+
+ if( (length > 0) && (raw_text[0] != '/') ) // forward slash is used for escape (eg. emote) sequences
+ {
+ gAgent.startTyping();
+ }
+ else
+ {
+ gAgent.stopTyping();
+ }
+
+ /* Doesn't work -- can't tell the difference between a backspace
+ that killed the selection vs. backspace at the end of line.
+ if (length > 1
+ && text[0] == '/'
+ && key == KEY_BACKSPACE)
+ {
+ // the selection will already be deleted, but we need to trim
+ // off the character before
+ std::string new_text = raw_text.substr(0, length-1);
+ self->mInputEditor->setText( new_text );
+ self->mInputEditor->setCursorToEnd();
+ length = length - 1;
+ }
+ */
+
+ KEY key = gKeyboard->currentKey();
+
+ // Ignore "special" keys, like backspace, arrows, etc.
+ if (length > 1
+ && raw_text[0] == '/'
+ && key < KEY_SPECIAL)
+ {
+ // we're starting a gesture, attempt to autocomplete
+
+ std::string utf8_trigger = wstring_to_utf8str(raw_text);
+ std::string utf8_out_str(utf8_trigger);
+
+ if (LLGestureManager::instance().matchPrefix(utf8_trigger, &utf8_out_str))
+ {
+ std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size());
+ self->mChatBox->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part
+ S32 outlength = self->mChatBox->getLength(); // in characters
+
+ // Select to end of line, starting from the character
+ // after the last one the user typed.
+ self->mChatBox->setSelection(length, outlength);
+ }
+ else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str))
+ {
+ std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size());
+ self->mChatBox->setText(utf8_trigger + rest_of_match + " "); // keep original capitalization for user-entered part
+ self->mChatBox->setCursorToEnd();
+ }
+
+ //llinfos << "GESTUREDEBUG " << trigger
+ // << " len " << length
+ // << " outlen " << out_str.getLength()
+ // << llendl;
+ }
+}
+
+// static
+void LLNearbyChatBar::onChatBoxFocusLost(LLFocusableElement* caller, void* userdata)
+{
+ // stop typing animation
+ gAgent.stopTyping();
+}
+
+EChatType LLNearbyChatBar::processChatTypeTriggers(EChatType type, std::string &str)
+{
+ U32 length = str.length();
+ S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers);
+
+ for (S32 n = 0; n < cnt; n++)
+ {
+ if (length >= sChatTypeTriggers[n].name.length())
+ {
+ std::string trigger = str.substr(0, sChatTypeTriggers[n].name.length());
+
+ if (!LLStringUtil::compareInsensitive(trigger, sChatTypeTriggers[n].name))
+ {
+ U32 trigger_length = sChatTypeTriggers[n].name.length();
+
+ // It's to remove space after trigger name
+ if (length > trigger_length && str[trigger_length] == ' ')
+ trigger_length++;
+
+ str = str.substr(trigger_length, length);
+
+ if (CHAT_TYPE_NORMAL == type)
+ return sChatTypeTriggers[n].type;
+ else
+ break;
+ }
+ }
+ }
+
+ return type;
+}
+
+void LLNearbyChatBar::sendChat( EChatType type )
+{
+ if (mChatBox)
+ {
+ LLWString text = mChatBox->getConvertedText();
+ if (!text.empty())
+ {
+ // store sent line in history, duplicates will get filtered
+ mChatBox->updateHistory();
+ // Check if this is destined for another channel
+ S32 channel = 0;
+ stripChannelNumber(text, &channel);
+
+ std::string utf8text = wstring_to_utf8str(text);
+ // Try to trigger a gesture, if not chat to a script.
+ std::string utf8_revised_text;
+ if (0 == channel)
+ {
+ // discard returned "found" boolean
+ LLGestureManager::instance().triggerAndReviseString(utf8text, &utf8_revised_text);
+ }
+ else
+ {
+ utf8_revised_text = utf8text;
+ }
+
+ utf8_revised_text = utf8str_trim(utf8_revised_text);
+
+ type = processChatTypeTriggers(type, utf8_revised_text);
+
+ if (!utf8_revised_text.empty())
+ {
+ // Chat with animation
+ sendChatFromViewer(utf8_revised_text, type, TRUE);
+ }
+ }
+
+ mChatBox->setText(LLStringExplicit(""));
+ }
+
+ gAgent.stopTyping();
+
+ // If the user wants to stop chatting on hitting return, lose focus
+ // and go out of chat mode.
+ if (gSavedSettings.getBOOL("CloseChatOnReturn"))
+ {
+ stopChat();
+ }
+}
+
+void LLNearbyChatBar::onChatBoxCommit()
+{
+ if (mChatBox->getText().length() > 0)
+ {
+ sendChat(CHAT_TYPE_NORMAL);
+ }
+
+ gAgent.stopTyping();
+}
+
+void LLNearbyChatBar::displaySpeakingIndicator()
+{
+ LLSpeakerMgr::speaker_list_t speaker_list;
+ LLUUID id;
+
+ id.setNull();
+ mSpeakerMgr->update(TRUE);
+ mSpeakerMgr->getSpeakerList(&speaker_list, FALSE);
+
+ for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i)
+ {
+ LLPointer<LLSpeaker> s = *i;
+ if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING)
+ {
+ id = s->mID;
+ break;
+ }
+ }
+
+ if (!id.isNull())
+ {
+ mOutputMonitor->setVisible(TRUE);
+ mOutputMonitor->setSpeakerId(id);
+ }
+ else
+ {
+ mOutputMonitor->setVisible(FALSE);
+ }
+}
+
+void LLNearbyChatBar::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate)
+{
+ sendChatFromViewer(utf8str_to_wstring(utf8text), type, animate);
+}
+
+void LLNearbyChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate)
+{
+ // Look for "/20 foo" channel chats.
+ S32 channel = 0;
+ LLWString out_text = stripChannelNumber(wtext, &channel);
+ std::string utf8_out_text = wstring_to_utf8str(out_text);
+ std::string utf8_text = wstring_to_utf8str(wtext);
+
+ utf8_text = utf8str_trim(utf8_text);
+ if (!utf8_text.empty())
+ {
+ utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1);
+ }
+
+ // Don't animate for chats people can't hear (chat to scripts)
+ if (animate && (channel == 0))
+ {
+ if (type == CHAT_TYPE_WHISPER)
+ {
+ lldebugs << "You whisper " << utf8_text << llendl;
+ gAgent.sendAnimationRequest(ANIM_AGENT_WHISPER, ANIM_REQUEST_START);
+ }
+ else if (type == CHAT_TYPE_NORMAL)
+ {
+ lldebugs << "You say " << utf8_text << llendl;
+ gAgent.sendAnimationRequest(ANIM_AGENT_TALK, ANIM_REQUEST_START);
+ }
+ else if (type == CHAT_TYPE_SHOUT)
+ {
+ lldebugs << "You shout " << utf8_text << llendl;
+ gAgent.sendAnimationRequest(ANIM_AGENT_SHOUT, ANIM_REQUEST_START);
+ }
+ else
+ {
+ llinfos << "send_chat_from_viewer() - invalid volume" << llendl;
+ return;
+ }
+ }
+ else
+ {
+ if (type != CHAT_TYPE_START && type != CHAT_TYPE_STOP)
+ {
+ lldebugs << "Channel chat: " << utf8_text << llendl;
+ }
+ }
+
+ send_chat_from_viewer(utf8_out_text, type, channel);
+}
+
+// static
+void LLNearbyChatBar::startChat(const char* line)
+{
+ LLBottomTray *bt = LLBottomTray::getInstance();
+
+ if (!bt)
+ return;
+
+ LLNearbyChatBar* cb = bt->getNearbyChatBar();
+
+ if (!cb )
+ return;
+
+ bt->setVisible(TRUE);
+ cb->mChatBox->setFocus(TRUE);
+
+ if (line)
+ {
+ std::string line_string(line);
+ cb->mChatBox->setText(line_string);
+ }
+
+ cb->mChatBox->setCursorToEnd();
+}
+
+// Exit "chat mode" and do the appropriate focus changes
+// static
+void LLNearbyChatBar::stopChat()
+{
+ LLBottomTray *bt = LLBottomTray::getInstance();
+
+ if (!bt)
+ return;
+
+ LLNearbyChatBar* cb = bt->getNearbyChatBar();
+
+ if (!cb)
+ return;
+
+ cb->mChatBox->setFocus(FALSE);
+
+ // stop typing animation
+ gAgent.stopTyping();
+}
+
+// If input of the form "/20foo" or "/20 foo", returns "foo" and channel 20.
+// Otherwise returns input and channel 0.
+LLWString LLNearbyChatBar::stripChannelNumber(const LLWString &mesg, S32* channel)
+{
+ if (mesg[0] == '/'
+ && mesg[1] == '/')
+ {
+ // This is a "repeat channel send"
+ *channel = sLastSpecialChatChannel;
+ return mesg.substr(2, mesg.length() - 2);
+ }
+ else if (mesg[0] == '/'
+ && mesg[1]
+ && LLStringOps::isDigit(mesg[1]))
+ {
+ // This a special "/20" speak on a channel
+ S32 pos = 0;
+
+ // Copy the channel number into a string
+ LLWString channel_string;
+ llwchar c;
+ do
+ {
+ c = mesg[pos+1];
+ channel_string.push_back(c);
+ pos++;
+ }
+ while(c && pos < 64 && LLStringOps::isDigit(c));
+
+ // Move the pointer forward to the first non-whitespace char
+ // Check isspace before looping, so we can handle "/33foo"
+ // as well as "/33 foo"
+ while(c && iswspace(c))
+ {
+ c = mesg[pos+1];
+ pos++;
+ }
+
+ sLastSpecialChatChannel = strtol(wstring_to_utf8str(channel_string).c_str(), NULL, 10);
+ *channel = sLastSpecialChatChannel;
+ return mesg.substr(pos, mesg.length() - pos);
+ }
+ else
+ {
+ // This is normal chat.
+ *channel = 0;
+ return mesg;
+ }
+}
+
+void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel)
+{
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_ChatFromViewer);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_ChatData);
+ msg->addStringFast(_PREHASH_Message, utf8_out_text);
+ msg->addU8Fast(_PREHASH_Type, type);
+ msg->addS32("Channel", channel);
+
+ gAgent.sendReliableMessage();
+
+ LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT);
+}
+
+class LLChatHandler : public LLCommandHandler
+{
+public:
+ // not allowed from outside the app
+ LLChatHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { }
+
+ // Your code here
+ bool handle(const LLSD& tokens, const LLSD& query_map,
+ LLMediaCtrl* web)
+ {
+ if (tokens.size() < 2) return false;
+ S32 channel = tokens[0].asInteger();
+ std::string mesg = tokens[1].asString();
+ send_chat_from_viewer(mesg, CHAT_TYPE_NORMAL, channel);
+ return true;
+ }
+};
+
+// Creating the object registers with the dispatcher.
+LLChatHandler gChatHandler;
+
+
diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h
new file mode 100644
index 0000000000..d9a7403611
--- /dev/null
+++ b/indra/newview/llnearbychatbar.h
@@ -0,0 +1,144 @@
+/**
+ * @file llnearbychatbar.h
+ * @brief LLNearbyChatBar class definition
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLNEARBYCHATBAR_H
+#define LL_LLNEARBYCHATBAR_H
+
+#include "llpanel.h"
+#include "llcombobox.h"
+#include "llgesturemgr.h"
+#include "llchat.h"
+#include "llvoiceclient.h"
+#include "lloutputmonitorctrl.h"
+#include "llspeakers.h"
+
+
+class LLGestureComboList
+ : public LLGestureManagerObserver
+ , public LLUICtrl
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<LLButton::Params> combo_button;
+ Optional<LLScrollListCtrl::Params> combo_list;
+
+ Params();
+ };
+
+protected:
+
+ friend class LLUICtrlFactory;
+ LLGestureComboList(const Params&);
+ std::vector<LLMultiGesture*> mGestures;
+ std::string mLabel;
+ LLSD::Integer mViewAllItemIndex;
+
+public:
+
+ ~LLGestureComboList();
+
+ LLCtrlListInterface* getListInterface() { return (LLCtrlListInterface*)mList; };
+ virtual void showList();
+ virtual void hideList();
+ virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
+
+ S32 getCurrentIndex() const;
+ void onItemSelected(const LLSD& data);
+ void sortByName(bool ascending = true);
+ void refreshGestures();
+ void onCommitGesture();
+ void onButtonCommit();
+ virtual LLSD getValue() const;
+
+ // LLGestureManagerObserver trigger
+ virtual void changed() { refreshGestures(); }
+
+private:
+
+ LLButton* mButton;
+ LLScrollListCtrl* mList;
+ S32 mLastSelectedIndex;
+};
+
+class LLNearbyChatBar
+: public LLPanel
+{
+public:
+ // constructor for inline chat-bars (e.g. hosted in chat history window)
+ LLNearbyChatBar();
+ ~LLNearbyChatBar() {}
+
+ virtual BOOL postBuild();
+
+ static LLNearbyChatBar* getInstance();
+
+ static bool instanceExists();
+
+ LLLineEditor* getChatBox() { return mChatBox; }
+
+ virtual void draw();
+
+ std::string getCurrentChat();
+ virtual BOOL handleKeyHere( KEY key, MASK mask );
+
+ static void startChat(const char* line);
+ static void stopChat();
+
+ static void sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate);
+ static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate);
+
+ S32 getMinWidth() const;
+ S32 getMaxWidth() const;
+
+protected:
+ static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str);
+ static void onChatBoxKeystroke(LLLineEditor* caller, void* userdata);
+ static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata);
+
+ void sendChat( EChatType type );
+ void onChatBoxCommit();
+
+ static LLWString stripChannelNumber(const LLWString &mesg, S32* channel);
+ EChatType processChatTypeTriggers(EChatType type, std::string &str);
+
+ void displaySpeakingIndicator();
+
+ // Which non-zero channel did we last chat on?
+ static S32 sLastSpecialChatChannel;
+
+ LLLineEditor* mChatBox;
+ LLOutputMonitorCtrl* mOutputMonitor;
+ LLLocalSpeakerMgr* mSpeakerMgr;
+};
+
+#endif
diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp
new file mode 100644
index 0000000000..c50e049d4c
--- /dev/null
+++ b/indra/newview/llnearbychathandler.cpp
@@ -0,0 +1,401 @@
+/**
+ * @file LLNearbyChatHandler.cpp
+ * @brief Nearby chat notification managment
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llnearbychathandler.h"
+
+#include "llchatitemscontainerctrl.h"
+#include "llnearbychat.h"
+#include "llrecentpeople.h"
+
+#include "llviewercontrol.h"
+
+#include "llfloaterreg.h"//for LLFloaterReg::getTypedInstance
+#include "llviewerwindow.h"//for screen channel position
+
+//add LLNearbyChatHandler to LLNotificationsUI namespace
+using namespace LLNotificationsUI;
+
+//-----------------------------------------------------------------------------------------------
+//LLNearbyChatScreenChannel
+//-----------------------------------------------------------------------------------------------
+LLToastPanelBase* createToastPanel()
+{
+ LLNearbyChatToastPanel* item = LLNearbyChatToastPanel::createInstance();
+ return item;
+}
+
+
+class LLNearbyChatScreenChannel: public LLScreenChannelBase
+{
+public:
+ LLNearbyChatScreenChannel(const LLUUID& id):LLScreenChannelBase(id) { mStopProcessing = false;};
+
+ void addNotification (LLSD& notification);
+ void arrangeToasts ();
+ void showToastsBottom ();
+
+ typedef boost::function<LLToastPanelBase* (void )> create_toast_panel_callback_t;
+ void setCreatePanelCallback(create_toast_panel_callback_t value) { m_create_toast_panel_callback_t = value;}
+
+ void onToastDestroyed (LLToast* toast);
+ void onToastFade (LLToast* toast);
+
+ void reshape (S32 width, S32 height, BOOL called_from_parent);
+
+ void redrawToasts()
+ {
+ arrangeToasts();
+ }
+
+ // hide all toasts from screen, but not remove them from a channel
+ virtual void hideToastsFromScreen()
+ {
+ };
+ // removes all toasts from a channel
+ virtual void removeToastsFromChannel()
+ {
+ for(std::vector<LLToast*>::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it)
+ {
+ LLToast* toast = (*it);
+ toast->setVisible(FALSE);
+ toast->stopTimer();
+ m_toast_pool.push_back(toast);
+
+ }
+ m_active_toasts.clear();
+ };
+
+ virtual void deleteAllChildren()
+ {
+ m_toast_pool.clear();
+ m_active_toasts.clear();
+ LLScreenChannelBase::deleteAllChildren();
+ }
+
+protected:
+ void createOverflowToast(S32 bottom, F32 timer);
+
+ create_toast_panel_callback_t m_create_toast_panel_callback_t;
+
+ bool createPoolToast();
+
+ std::vector<LLToast*> m_active_toasts;
+ std::list<LLToast*> m_toast_pool;
+
+ bool mStopProcessing;
+};
+
+void LLNearbyChatScreenChannel::createOverflowToast(S32 bottom, F32 timer)
+{
+ //we don't need overflow toast in nearby chat
+}
+
+void LLNearbyChatScreenChannel::onToastDestroyed(LLToast* toast)
+{
+ mStopProcessing = true;
+}
+
+void LLNearbyChatScreenChannel::onToastFade(LLToast* toast)
+{
+ //fade mean we put toast to toast pool
+ if(!toast)
+ return;
+ m_toast_pool.push_back(toast);
+
+ std::vector<LLToast*>::iterator pos = std::find(m_active_toasts.begin(),m_active_toasts.end(),toast);
+ if(pos!=m_active_toasts.end())
+ m_active_toasts.erase(pos);
+
+ arrangeToasts();
+}
+
+
+bool LLNearbyChatScreenChannel::createPoolToast()
+{
+ LLToastPanelBase* panel= m_create_toast_panel_callback_t();
+ if(!panel)
+ return false;
+
+ LLToast::Params p;
+ p.panel = panel;
+ p.lifetime_secs = gSavedSettings.getS32("NearbyToastLifeTime");
+ p.fading_time_secs = gSavedSettings.getS32("NearbyToastFadingTime");
+
+ LLToast* toast = new LLToast(p);
+
+
+ toast->setOnFadeCallback(boost::bind(&LLNearbyChatScreenChannel::onToastFade, this, _1));
+ toast->setOnToastDestroyedCallback(boost::bind(&LLNearbyChatScreenChannel::onToastDestroyed, this, _1));
+
+ m_toast_pool.push_back(toast);
+ return true;
+}
+
+void LLNearbyChatScreenChannel::addNotification(LLSD& notification)
+{
+ //look in pool. if there is any message
+ if(mStopProcessing)
+ return;
+
+ /*
+ find last toast and check ID
+ */
+
+ if(m_active_toasts.size())
+ {
+ LLUUID fromID = notification["from_id"].asUUID(); // agent id or object id
+ LLToast* toast = m_active_toasts[0];
+ LLNearbyChatToastPanel* panel = dynamic_cast<LLNearbyChatToastPanel*>(toast->getPanel());
+
+ if(panel && panel->messageID() == fromID && panel->canAddText())
+ {
+ panel->addMessage(notification);
+ toast->reshapeToPanel();
+ toast->resetTimer();
+
+ arrangeToasts();
+ return;
+ }
+ }
+
+
+
+ if(m_toast_pool.empty())
+ {
+ //"pool" is empty - create one more panel
+ if(!createPoolToast())//created toast will go to pool. so next call will find it
+ return;
+ addNotification(notification);
+ return;
+ }
+
+ int chat_type = notification["chat_type"].asInteger();
+
+ if( ((EChatType)chat_type == CHAT_TYPE_DEBUG_MSG))
+ {
+ if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE)
+ return;
+ if(gSavedSettings.getS32("ShowScriptErrorsLocation")== 1)
+ return;
+ }
+
+
+ //take 1st element from pool, (re)initialize it, put it in active toasts
+
+ LLToast* toast = m_toast_pool.back();
+
+ m_toast_pool.pop_back();
+
+
+ LLToastPanelBase* panel = dynamic_cast<LLToastPanelBase*>(toast->getPanel());
+ if(!panel)
+ return;
+ panel->init(notification);
+
+ toast->reshapeToPanel();
+ toast->resetTimer();
+
+ m_active_toasts.insert(m_active_toasts.begin(),toast);
+
+ arrangeToasts();
+}
+
+void LLNearbyChatScreenChannel::arrangeToasts()
+{
+ if(m_active_toasts.size() == 0 || isHovering())
+ return;
+
+ hideToastsFromScreen();
+
+ showToastsBottom();
+}
+
+void LLNearbyChatScreenChannel::showToastsBottom()
+{
+ if(mStopProcessing)
+ return;
+
+ LLRect toast_rect;
+ S32 bottom = getRect().mBottom;
+ S32 margin = gSavedSettings.getS32("ToastGap");
+
+ for(std::vector<LLToast*>::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it)
+ {
+ LLToast* toast = (*it);
+ S32 toast_top = bottom + toast->getRect().getHeight() + margin;
+
+ if(toast_top > gFloaterView->getRect().getHeight())
+ {
+ while(it!=m_active_toasts.end())
+ {
+ toast->setVisible(FALSE);
+ toast->stopTimer();
+ m_toast_pool.push_back(toast);
+ it=m_active_toasts.erase(it);
+ }
+ break;
+ }
+ else
+ {
+ toast_rect = toast->getRect();
+ toast_rect.setLeftTopAndSize(getRect().mLeft , toast_top, toast_rect.getWidth() ,toast_rect.getHeight());
+
+ toast->setRect(toast_rect);
+ toast->setIsHidden(false);
+ toast->setVisible(TRUE);
+
+ bottom = toast->getRect().mTop;
+ }
+ }
+}
+
+void LLNearbyChatScreenChannel::reshape (S32 width, S32 height, BOOL called_from_parent)
+{
+ LLScreenChannelBase::reshape(width, height, called_from_parent);
+ arrangeToasts();
+}
+
+
+//-----------------------------------------------------------------------------------------------
+//LLNearbyChatHandler
+//-----------------------------------------------------------------------------------------------
+LLNearbyChatHandler::LLNearbyChatHandler(e_notification_type type, const LLSD& id)
+{
+ mType = type;
+
+ // Getting a Channel for our notifications
+ LLNearbyChatScreenChannel* channel = new LLNearbyChatScreenChannel(LLUUID(gSavedSettings.getString("NearByChatChannelUUID")));
+
+ LLNearbyChatScreenChannel::create_toast_panel_callback_t callback = createToastPanel;
+
+ channel->setCreatePanelCallback(callback);
+
+ mChannel = LLChannelManager::getInstance()->addChannel(channel);
+}
+
+LLNearbyChatHandler::~LLNearbyChatHandler()
+{
+}
+
+
+void LLNearbyChatHandler::initChannel()
+{
+ LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
+ S32 channel_right_bound = nearby_chat->getRect().mRight;
+ S32 channel_width = nearby_chat->getRect().mRight;
+ mChannel->init(channel_right_bound - channel_width, channel_right_bound);
+}
+
+
+
+void LLNearbyChatHandler::processChat(const LLChat& chat_msg)
+{
+ if(chat_msg.mMuted == TRUE)
+ return;
+ if(chat_msg.mSourceType == CHAT_SOURCE_AGENT && chat_msg.mFromID.notNull())
+ LLRecentPeople::instance().add(chat_msg.mFromID);
+
+ if(chat_msg.mText.empty())
+ return;//don't process empty messages
+
+ LLChat& tmp_chat = const_cast<LLChat&>(chat_msg);
+
+ LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
+ {
+ //sometimes its usefull to have no name at all...
+ //if(tmp_chat.mFromName.empty() && tmp_chat.mFromID!= LLUUID::null)
+ // tmp_chat.mFromName = tmp_chat.mFromID.asString();
+ }
+ nearby_chat->addMessage(chat_msg);
+ if(nearby_chat->getVisible())
+ return;//no need in toast if chat is visible
+
+ // Handle irc styled messages for toast panel
+ if (tmp_chat.mChatStyle == CHAT_STYLE_IRC)
+ {
+ if(!tmp_chat.mFromName.empty())
+ tmp_chat.mText = tmp_chat.mFromName + tmp_chat.mText.substr(3);
+ else
+ tmp_chat.mText = tmp_chat.mText.substr(3);
+ }
+
+ // arrange a channel on a screen
+ if(!mChannel->getVisible())
+ {
+ initChannel();
+ }
+
+ //only messages from AGENTS
+ if(CHAT_SOURCE_OBJECT == chat_msg.mSourceType)
+ {
+ if(chat_msg.mChatType == CHAT_TYPE_DEBUG_MSG)
+ return;//ok for now we don't skip messeges from object, so skip only debug messages
+ }
+
+ LLUUID id;
+ id.generate();
+
+ LLNearbyChatScreenChannel* channel = dynamic_cast<LLNearbyChatScreenChannel*>(mChannel);
+
+
+ if(channel)
+ {
+ LLSD notification;
+ notification["id"] = id;
+ notification["message"] = chat_msg.mText;
+ notification["from"] = chat_msg.mFromName;
+ notification["from_id"] = chat_msg.mFromID;
+ notification["time"] = chat_msg.mTime;
+ notification["source"] = (S32)chat_msg.mSourceType;
+ notification["chat_type"] = (S32)chat_msg.mChatType;
+ notification["chat_style"] = (S32)chat_msg.mChatStyle;
+
+ std::string r_color_name = "White";
+ F32 r_color_alpha = 1.0f;
+ LLViewerChat::getChatColor( chat_msg, r_color_name, r_color_alpha);
+
+ notification["text_color"] = r_color_name;
+ notification["color_alpha"] = r_color_alpha;
+ notification["font_size"] = (S32)LLViewerChat::getChatFontSize() ;
+ channel->addNotification(notification);
+ }
+
+}
+
+void LLNearbyChatHandler::onDeleteToast(LLToast* toast)
+{
+}
+
+
+
diff --git a/indra/newview/llnearbychathandler.h b/indra/newview/llnearbychathandler.h
new file mode 100644
index 0000000000..fb2abac6a4
--- /dev/null
+++ b/indra/newview/llnearbychathandler.h
@@ -0,0 +1,57 @@
+/**
+ * @file llnearbychathandler.h
+ * @brief nearby chat notify
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLNEARBYCHATHANDLER_H
+#define LL_LLNEARBYCHATHANDLER_H
+
+#include "llnotificationhandler.h"
+
+//add LLNearbyChatHandler to LLNotificationsUI namespace
+namespace LLNotificationsUI{
+
+class LLNearbyChatHandler : public LLChatHandler
+{
+public:
+ LLNearbyChatHandler(e_notification_type type,const LLSD& id);
+ virtual ~LLNearbyChatHandler();
+
+
+ virtual void processChat(const LLChat& chat_msg);
+
+protected:
+ virtual void onDeleteToast(LLToast* toast);
+ virtual void initChannel();
+};
+
+}
+
+#endif /* LL_LLNEARBYCHATHANDLER_H */
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
index 2eee54df40..234fe13217 100644
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -1,7 +1,7 @@
/**
* @file llnetmap.cpp
* @author James Cook
- * @brief Display of surrounding regions, objects, and agents. View contained by LLFloaterMap.
+ * @brief Display of surrounding regions, objects, and agents.
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
@@ -35,82 +35,66 @@
#include "llnetmap.h"
+// Library includes (should move below)
#include "indra_constants.h"
-#include "llui.h"
-#include "llmath.h" // clampf()
+#include "llmath.h"
+#include "llfloaterreg.h"
#include "llfocusmgr.h"
+#include "lllocalcliprect.h"
#include "llrender.h"
+#include "llui.h"
+#include "lltooltip.h"
+
+#include "llglheaders.h"
+// Viewer includes
#include "llagent.h"
-#include "llcallingcard.h"
-#include "llcolorscheme.h"
-#include "llviewercontrol.h"
-#include "llfloateravatarinfo.h"
-#include "llfloaterworldmap.h"
-#include "llframetimer.h"
+#include "llappviewer.h" // for gDisconnected
+#include "llcallingcard.h" // LLAvatarTracker
#include "lltracker.h"
-#include "llmenugl.h"
#include "llsurface.h"
-#include "lltextbox.h"
-#include "lluictrlfactory.h"
-#include "lluuid.h"
#include "llviewercamera.h"
-#include "llviewerimage.h"
-#include "llviewerimagelist.h"
+#include "llviewercontrol.h"
+#include "llviewertexture.h"
+#include "llviewertexturelist.h"
#include "llviewermenu.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
-#include "llviewerwindow.h"
-#include "llvoavatar.h"
#include "llworld.h"
#include "llworldmapview.h" // shared draw code
-#include "llappviewer.h" // Only for constants!
-#include "llglheaders.h"
+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_MAX = 4096;
-const F32 MAP_SCALE_MIN = 64;
-const F32 MAP_SCALE_MID = 172;
-const F32 MAP_SCALE_MAX = 512;
const F32 MAP_SCALE_INCREMENT = 16;
-const F32 MAP_MIN_PICK_DIST = 4;
-const F32 MAP_MINOR_DIR_THRESHOLD = 0.08f;
-
-const S32 TRACKING_RADIUS = 3;
-
-LLNetMap::LLNetMap(const std::string& name) :
- LLPanel(name),
- mScale(128.f),
- mObjectMapTPM(1.f),
- mObjectMapPixels(255.f),
- mTargetPanX( 0.f ),
- mTargetPanY( 0.f ),
- mCurPanX( 0.f ),
- mCurPanY( 0.f ),
- mUpdateNow( FALSE )
+const F32 MAP_SCALE_ZOOM_FACTOR = 1.04f; // Zoom in factor per click of scroll wheel (4%)
+const F32 MIN_DOT_RADIUS = 3.5f;
+const F32 DOT_SCALE = 0.75f;
+const F32 MIN_PICK_SCALE = 2.f;
+
+LLNetMap::LLNetMap (const Params & p)
+: LLUICtrl (p),
+ mBackgroundColor (p.bg_color()),
+ mScale( MAP_SCALE_MID ),
+ mPixelsPerMeter( MAP_SCALE_MID / REGION_WIDTH_METERS ),
+ mObjectMapTPM(0.f),
+ mObjectMapPixels(0.f),
+ mTargetPanX(0.f),
+ mTargetPanY(0.f),
+ mCurPanX(0.f),
+ mCurPanY(0.f),
+ mUpdateNow(FALSE),
+ mObjectImageCenterGlobal( gAgent.getCameraPositionGlobal() ),
+ mObjectRawImagep(),
+ mObjectImagep(),
+ mClosestAgentToCursor(),
+ mClosestAgentAtLastRightClick(),
+ mToolTipMsg()
{
- mScale = gSavedSettings.getF32("MiniMapScale");
- mPixelsPerMeter = mScale / LLWorld::getInstance()->getRegionWidthInMeters();
-
- mObjectImageCenterGlobal = gAgent.getCameraPositionGlobal();
-
- // Register event listeners for popup menu
- (new LLScaleMap())->registerListener(this, "MiniMap.ZoomLevel");
- (new LLStopTracking())->registerListener(this, "MiniMap.StopTracking");
- (new LLEnableTracking())->registerListener(this, "MiniMap.EnableTracking");
- (new LLShowAgentProfile())->registerListener(this, "MiniMap.ShowProfile");
- (new LLEnableProfile())->registerListener(this, "MiniMap.EnableProfile");
-
- LLUICtrlFactory::getInstance()->buildPanel(this, "panel_mini_map.xml");
-
- updateMinorDirections();
-
- LLMenuGL* menu = LLUICtrlFactory::getInstance()->buildMenu("menu_mini_map.xml", this);
- if (!menu)
- {
- menu = new LLMenuGL(LLStringUtil::null);
- }
- menu->setVisible(FALSE);
- mPopupMenuHandle = menu->getHandle();
+ mDotRadius = llmax(DOT_SCALE * mPixelsPerMeter, MIN_DOT_RADIUS);
}
LLNetMap::~LLNetMap()
@@ -119,13 +103,8 @@ LLNetMap::~LLNetMap()
void LLNetMap::setScale( F32 scale )
{
- mScale = scale;
- if (mScale == 0.f)
- {
- mScale = 0.1f;
- }
- gSavedSettings.setF32("MiniMapScale", mScale);
-
+ mScale = llclamp(scale, 0.1f, 16.f*1024.f); // [reasonably small , unreasonably large]
+
if (mObjectImagep.notNull())
{
F32 width = (F32)(getRect().getWidth());
@@ -138,7 +117,8 @@ void LLNetMap::setScale( F32 scale )
mObjectMapPixels = diameter;
}
- mPixelsPerMeter = mScale / LLWorld::getInstance()->getRegionWidthInMeters();
+ mPixelsPerMeter = mScale / REGION_WIDTH_METERS;
+ mDotRadius = llmax(DOT_SCALE * mPixelsPerMeter, MIN_DOT_RADIUS);
mUpdateNow = TRUE;
}
@@ -155,33 +135,35 @@ void LLNetMap::translatePan( F32 delta_x, F32 delta_y )
void LLNetMap::draw()
{
static LLFrameTimer map_timer;
-
+ static LLUIColor map_avatar_color = LLUIColorTable::instance().getColor("MapAvatarColor", LLColor4::white);
+ static LLUIColor map_avatar_friend_color = LLUIColorTable::instance().getColor("MapAvatarFriendColor", LLColor4::white);
+ 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);
+
if (mObjectImagep.isNull())
{
createObjectImage();
}
-
+
mCurPanX = lerp(mCurPanX, mTargetPanX, LLCriticalDamp::getInterpolant(0.1f));
mCurPanY = lerp(mCurPanY, mTargetPanY, LLCriticalDamp::getInterpolant(0.1f));
+ // Prepare a scissor region
F32 rotation = 0;
- // Prepare a scissor region
{
- LLGLEnable scissor(GL_SCISSOR_TEST);
-
+ LLLocalClipRect clip(getLocalRect());
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- LLLocalClipRect clip(getLocalRect());
glMatrixMode(GL_MODELVIEW);
// Draw background rectangle
- if(isBackgroundVisible())
- {
- gGL.color4fv(isBackgroundOpaque() ? getBackgroundColor().mV : getTransparentColor().mV);
- gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0);
- }
+ LLColor4 background_color = mBackgroundColor.get();
+ gGL.color4fv( background_color.mV );
+ gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0);
}
// region 0,0 is in the middle
@@ -192,7 +174,7 @@ void LLNetMap::draw()
gGL.translatef( (F32) center_sw_left, (F32) center_sw_bottom, 0.f);
- BOOL rotate_map = gSavedSettings.getBOOL( "MiniMapRotate" );
+ static LLUICachedControl<bool> rotate_map("MiniMapRotate", true);
if( rotate_map )
{
// rotate subsequent draws to agent rotation
@@ -202,9 +184,6 @@ void LLNetMap::draw()
// figure out where agent is
S32 region_width = llround(LLWorld::getInstance()->getRegionWidthInMeters());
- LLColor4 this_region_color = gColors.getColor( "NetMapThisRegion" );
- LLColor4 live_region_color = gColors.getColor( "NetMapLiveRegion" );
- LLColor4 dead_region_color = gColors.getColor( "NetMapDeadRegion" );
for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
@@ -222,10 +201,18 @@ void LLNetMap::draw()
F32 top = bottom + mScale ;
F32 right = left + mScale ;
- gGL.color4fv(regionp == gAgent.getRegion() ? this_region_color.mV : live_region_color.mV);
+ if (regionp == gAgent.getRegion())
+ {
+ gGL.color4f(1.f, 1.f, 1.f, 1.f);
+ }
+ else
+ {
+ gGL.color4f(0.8f, 0.8f, 0.8f, 1.f);
+ }
+
if (!regionp->isAlive())
{
- gGL.color4fv(dead_region_color.mV);
+ gGL.color4f(1.f, 0.5f, 0.5f, 1.f);
}
@@ -317,61 +304,93 @@ void LLNetMap::draw()
// Mouse pointer in local coordinates
S32 local_mouse_x;
S32 local_mouse_y;
- LLUI::getCursorPositionLocal(this, &local_mouse_x, &local_mouse_y);
+ //localMouse(&local_mouse_x, &local_mouse_y);
+ LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y);
mClosestAgentToCursor.setNull();
F32 closest_dist = F32_MAX;
+ F32 min_pick_dist = mDotRadius * MIN_PICK_SCALE;
// Draw avatars
- LLColor4 avatar_color = gColors.getColor( "MapAvatar" );
- LLColor4 friend_color = gColors.getColor( "MapFriend" );
- std::vector<LLUUID> avatar_ids;
- std::vector<LLVector3d> positions;
- LLWorld::getInstance()->getAvatars(&avatar_ids, &positions);
- for(U32 i=0; i<avatar_ids.size(); i++)
+ for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
{
+ LLViewerRegion* regionp = *iter;
+ const LLVector3d& origin_global = regionp->getOriginGlobal();
+
+ S32 count = regionp->mMapAvatars.count();
+ S32 i;
+ LLVector3 pos_local;
+ U32 compact_local;
+ U8 bits;
// TODO: it'd be very cool to draw these in sorted order from lowest Z to highest.
// just be careful to sort the avatar IDs along with the positions. -MG
- pos_map = globalPosToView(positions[i], rotate_map);
+ for (i = 0; i < count; i++)
+ {
+ compact_local = regionp->mMapAvatars.get(i);
- LLWorldMapView::drawAvatar(
- pos_map.mV[VX], pos_map.mV[VY],
- is_agent_friend(avatar_ids[i]) ? friend_color : avatar_color,
- pos_map.mV[VZ]);
+ bits = compact_local & 0xFF;
+ pos_local.mV[VZ] = F32(bits) * 4.f;
+ compact_local >>= 8;
- F32 dist_to_cursor = dist_vec(LLVector2(pos_map.mV[VX], pos_map.mV[VY]), LLVector2(local_mouse_x,local_mouse_y));
- if(dist_to_cursor < MAP_MIN_PICK_DIST && dist_to_cursor < closest_dist)
- {
- closest_dist = dist_to_cursor;
- mClosestAgentToCursor = avatar_ids[i];
+ bits = compact_local & 0xFF;
+ pos_local.mV[VY] = (F32)bits;
+ compact_local >>= 8;
+
+ bits = compact_local & 0xFF;
+ pos_local.mV[VX] = (F32)bits;
+
+ pos_global.setVec( pos_local );
+ pos_global += origin_global;
+
+ pos_map = globalPosToView(pos_global);
+
+ BOOL show_as_friend = FALSE;
+ if( i < regionp->mMapAvatarIDs.count())
+ {
+ show_as_friend = (LLAvatarTracker::instance().getBuddyInfo(regionp->mMapAvatarIDs.get(i)) != NULL);
+ }
+ LLWorldMapView::drawAvatar(
+ pos_map.mV[VX], pos_map.mV[VY],
+ show_as_friend ? map_avatar_friend_color : map_avatar_color,
+ pos_map.mV[VZ], mDotRadius);
+
+ F32 dist_to_cursor = dist_vec(LLVector2(pos_map.mV[VX], pos_map.mV[VY]), LLVector2(local_mouse_x,local_mouse_y));
+ if(dist_to_cursor < min_pick_dist && dist_to_cursor < closest_dist)
+ {
+ closest_dist = dist_to_cursor;
+ mClosestAgentToCursor = regionp->mMapAvatarIDs.get(i);
+ }
}
}
// Draw dot for autopilot target
if (gAgent.getAutoPilot())
{
- drawTracking( gAgent.getAutoPilotTargetGlobal(), rotate_map, gTrackColor );
+ drawTracking( gAgent.getAutoPilotTargetGlobal(), map_track_color );
}
else
{
LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus();
if ( LLTracker::TRACKING_AVATAR == tracking_status )
{
- drawTracking( LLAvatarTracker::instance().getGlobalPos(), rotate_map, gTrackColor );
+ drawTracking( LLAvatarTracker::instance().getGlobalPos(), map_track_color );
}
else if ( LLTracker::TRACKING_LANDMARK == tracking_status
|| LLTracker::TRACKING_LOCATION == tracking_status )
{
- drawTracking( LLTracker::getTrackedPositionGlobal(), rotate_map, gTrackColor );
+ drawTracking( LLTracker::getTrackedPositionGlobal(), map_track_color );
}
}
// Draw dot for self avatar position
pos_global = gAgent.getPositionGlobal();
- pos_map = globalPosToView(pos_global, rotate_map);
- LLUIImagePtr you = LLWorldMapView::sAvatarYouSmallImage;
- you->draw(
- llround(pos_map.mV[VX]) - you->getWidth()/2,
- llround(pos_map.mV[VY]) - you->getHeight()/2);
+ pos_map = globalPosToView(pos_global);
+ LLUIImagePtr you = LLWorldMapView::sAvatarYouLargeImage;
+ S32 dot_width = llround(mDotRadius * 2.f);
+ you->draw(llround(pos_map.mV[VX] - mDotRadius),
+ llround(pos_map.mV[VY] - mDotRadius),
+ dot_width,
+ dot_width);
// Draw frustum
F32 meters_to_pixels = mScale/ LLWorld::getInstance()->getRegionWidthInMeters();
@@ -391,7 +410,7 @@ void LLNetMap::draw()
if( rotate_map )
{
- gGL.color4fv(gColors.getColor("NetMapFrustum").mV);
+ gGL.color4fv((map_frustum_color()).mV);
gGL.begin( LLRender::TRIANGLES );
gGL.vertex2f( ctr_x, ctr_y );
@@ -401,7 +420,7 @@ void LLNetMap::draw()
}
else
{
- gGL.color4fv(gColors.getColor("NetMapFrustumRotating").mV);
+ gGL.color4fv((map_frustum_rotating_color()).mV);
// If we don't rotate the map, we have to rotate the frustum.
gGL.pushMatrix();
@@ -416,27 +435,17 @@ void LLNetMap::draw()
}
}
- // Rotation of 0 means that North is up
- setDirectionPos( getChild<LLTextBox>("e_label"), rotation);
- setDirectionPos( getChild<LLTextBox>("n_label"), rotation + F_PI_BY_TWO);
- setDirectionPos( getChild<LLTextBox>("w_label"), rotation + F_PI);
- setDirectionPos( getChild<LLTextBox>("s_label"), rotation + F_PI + F_PI_BY_TWO);
-
- setDirectionPos( getChild<LLTextBox>("ne_label"), rotation + F_PI_BY_TWO / 2);
- setDirectionPos( getChild<LLTextBox>("nw_label"), rotation + F_PI_BY_TWO + F_PI_BY_TWO / 2);
- setDirectionPos( getChild<LLTextBox>("sw_label"), rotation + F_PI + F_PI_BY_TWO / 2);
- setDirectionPos( getChild<LLTextBox>("se_label"), rotation + F_PI + F_PI_BY_TWO + F_PI_BY_TWO / 2);
-
- LLView::draw();
+ LLUICtrl::draw();
}
void LLNetMap::reshape(S32 width, S32 height, BOOL called_from_parent)
{
- LLPanel::reshape(width, height, called_from_parent);
- updateMinorDirections();
+ LLUICtrl::reshape(width, height, called_from_parent);
+ createObjectImage();
}
-LLVector3 LLNetMap::globalPosToView( const LLVector3d& global_pos, BOOL rotated ){
+LLVector3 LLNetMap::globalPosToView( const LLVector3d& global_pos )
+{
LLVector3d relative_pos_global = global_pos - gAgent.getCameraPositionGlobal();
LLVector3 pos_local;
pos_local.setVec(relative_pos_global); // convert to floats from doubles
@@ -445,7 +454,8 @@ LLVector3 LLNetMap::globalPosToView( const LLVector3d& global_pos, BOOL rotated
pos_local.mV[VY] *= mPixelsPerMeter;
// leave Z component in meters
- if( rotated )
+ static LLUICachedControl<bool> rotate_map("MiniMapRotate", true);
+ if( rotate_map )
{
F32 radians = atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] );
LLQuaternion rot(radians, LLVector3(0.f, 0.f, 1.f));
@@ -458,10 +468,10 @@ LLVector3 LLNetMap::globalPosToView( const LLVector3d& global_pos, BOOL rotated
return pos_local;
}
-void LLNetMap::drawTracking(const LLVector3d& pos_global, BOOL rotated,
- const LLColor4& color, BOOL draw_arrow )
+void LLNetMap::drawTracking(const LLVector3d& pos_global, const LLColor4& color,
+ BOOL draw_arrow )
{
- LLVector3 pos_local = globalPosToView( pos_global, rotated );
+ LLVector3 pos_local = globalPosToView( pos_global );
if( (pos_local.mV[VX] < 0) ||
(pos_local.mV[VY] < 0) ||
(pos_local.mV[VX] >= getRect().getWidth()) ||
@@ -484,16 +494,17 @@ void LLNetMap::drawTracking(const LLVector3d& pos_global, BOOL rotated,
}
}
-LLVector3d LLNetMap::viewPosToGlobal( S32 x, S32 y, BOOL rotated )
+LLVector3d LLNetMap::viewPosToGlobal( S32 x, S32 y )
{
x -= llround(getRect().getWidth() / 2 + mCurPanX);
y -= llround(getRect().getHeight() / 2 + mCurPanY);
- LLVector3 pos_local( (F32)x, (F32)y, 0.f );
+ LLVector3 pos_local( (F32)x, (F32)y, 0 );
F32 radians = - atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] );
- if( rotated )
+ static LLUICachedControl<bool> rotate_map("MiniMapRotate", true);
+ if( rotate_map )
{
LLQuaternion rot(radians, LLVector3(0.f, 0.f, 1.f));
pos_local.rotVec( rot );
@@ -510,101 +521,74 @@ LLVector3d LLNetMap::viewPosToGlobal( S32 x, S32 y, BOOL rotated )
BOOL LLNetMap::handleScrollWheel(S32 x, S32 y, S32 clicks)
{
- // note that clicks are reversed from what you'd think
- setScale(llclamp(mScale - clicks*MAP_SCALE_INCREMENT, MAP_SCALE_MIN, MAP_SCALE_MAX));
+ // note that clicks are reversed from what you'd think: i.e. > 0 means zoom out, < 0 means zoom in
+ F32 scale = mScale;
+
+ scale *= pow(MAP_SCALE_ZOOM_FACTOR, -clicks);
+ setScale(llclamp(scale, MAP_SCALE_MIN, MAP_SCALE_MAX));
+
return TRUE;
}
-BOOL LLNetMap::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen )
+BOOL LLNetMap::handleToolTip( S32 x, S32 y, MASK mask )
{
- BOOL handled = FALSE;
if (gDisconnected)
{
return FALSE;
}
- LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( viewPosToGlobal( x, y , gSavedSettings.getBOOL( "MiniMapRotate" )) );
+
+ // mToolTipMsg = "[AGENT][REGION](Double-click to open Map)"
+
+ LLStringUtil::format_map_t args;
+ std::string fullname;
+ if(mClosestAgentToCursor.notNull() && gCacheName->getFullName(mClosestAgentToCursor, fullname))
+ {
+ args["[AGENT]"] = fullname + "\n";
+ }
+ else
+ {
+ args["[AGENT]"] = "";
+ }
+
+ LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( viewPosToGlobal( x, y ) );
if( region )
{
- msg.assign("");
- std::string fullname;
- if(mClosestAgentToCursor.notNull() && gCacheName->getFullName(mClosestAgentToCursor, fullname))
- {
- msg.append(fullname);
- msg.append("\n");
- }
- msg.append( region->getName() );
-
-#ifndef LL_RELEASE_FOR_DOWNLOAD
- std::string buffer;
- msg.append("\n");
- buffer = region->getHost().getHostName();
- msg.append(buffer);
- msg.append("\n");
- buffer = region->getHost().getString();
- msg.append(buffer);
-#endif
- msg.append("\n");
- msg.append(getToolTip());
-
- S32 SLOP = 4;
- localPointToScreen(
- x - SLOP, y - SLOP,
- &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
- sticky_rect_screen->mRight = sticky_rect_screen->mLeft + 2 * SLOP;
- sticky_rect_screen->mTop = sticky_rect_screen->mBottom + 2 * SLOP;
- handled = TRUE;
+ args["[REGION]"] = region->getName() + "\n";
}
- if(!handled)
+ else
{
- return LLPanel::handleToolTip(x, y, msg, sticky_rect_screen);
+ args["[REGION]"] = "";
}
- return handled;
-}
-
-
-void LLNetMap::setDirectionPos( LLTextBox* text_box, F32 rotation )
-{
- // Rotation is in radians.
- // Rotation of 0 means x = 1, y = 0 on the unit circle.
-
- F32 half_height = (F32)( (getRect().getHeight() - text_box->getRect().getHeight()) / 2);
- F32 half_width = (F32)( (getRect().getWidth() - text_box->getRect().getWidth()) / 2);
- F32 radius = llmin( half_height, half_width );
-
- // Inset by a little to account for position display.
- radius -= 8.f;
-
- text_box->setOrigin(llround(half_width + radius * cos( rotation )),
- llround(half_height + radius * sin( rotation )));
-}
-
-void LLNetMap::updateMinorDirections()
-{
- if (getChild<LLTextBox>("ne_label") == NULL)
+
+ std::string msg = mToolTipMsg;
+ LLStringUtil::format(msg, args);
+
+ LLRect sticky_rect;
+ // set sticky_rect
+ if (region)
{
- return;
+ 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;
}
- // Hide minor directions if they cover too much of the map
- bool show_minors = getChild<LLTextBox>("ne_label")->getRect().getHeight() < MAP_MINOR_DIR_THRESHOLD *
- llmin(getRect().getWidth(), getRect().getHeight());
-
- getChild<LLTextBox>("ne_label")->setVisible(show_minors);
- getChild<LLTextBox>("nw_label")->setVisible(show_minors);
- getChild<LLTextBox>("sw_label")->setVisible(show_minors);
- getChild<LLTextBox>("se_label")->setVisible(show_minors);
+ LLToolTipMgr::instance().show(LLToolTip::Params()
+ .message(msg)
+ .sticky_rect(sticky_rect));
+
+ return TRUE;
}
+
void LLNetMap::renderScaledPointGlobal( const LLVector3d& pos, const LLColor4U &color, F32 radius_meters )
{
LLVector3 local_pos;
local_pos.setVec( pos - mObjectImageCenterGlobal );
- // DEV-17370 - megaprims of size > 4096 cause lag. (go figger.)
- const F32 MAX_RADIUS = 256.0f;
- F32 radius_clamped = llmin(radius_meters, MAX_RADIUS);
-
- S32 diameter_pixels = llround(2 * radius_clamped * mObjectMapTPM);
+ S32 diameter_pixels = llround(2 * radius_meters * mObjectMapTPM);
renderPoint( local_pos, color, diameter_pixels );
}
@@ -698,12 +682,12 @@ void LLNetMap::createObjectImage()
{
// Find the size of the side of a square that surrounds the circle that surrounds getRect().
// ... which is, the diagonal of the rect.
- F32 width = getRect().getWidth();
- F32 height = getRect().getHeight();
+ F32 width = (F32)getRect().getWidth();
+ F32 height = (F32)getRect().getHeight();
S32 square_size = llround( sqrt(width*width + height*height) );
// Find the least power of two >= the minimum size.
- const S32 MIN_SIZE = 32;
+ const S32 MIN_SIZE = 64;
const S32 MAX_SIZE = 256;
S32 img_size = MIN_SIZE;
while( (img_size*2 < square_size ) && (img_size < MAX_SIZE) )
@@ -718,80 +702,8 @@ void LLNetMap::createObjectImage()
mObjectRawImagep = new LLImageRaw(img_size, img_size, 4);
U8* data = mObjectRawImagep->getData();
memset( data, 0, img_size * img_size * 4 );
- mObjectImagep = new LLImageGL( mObjectRawImagep, FALSE);
- setScale(mScale);
+ mObjectImagep = LLViewerTextureManager::getLocalTexture( mObjectRawImagep.get(), FALSE);
}
+ setScale(mScale);
mUpdateNow = TRUE;
}
-
-BOOL LLNetMap::handleDoubleClick( S32 x, S32 y, MASK mask )
-{
- LLFloaterWorldMap::show(NULL, FALSE);
- return TRUE;
-}
-
-BOOL LLNetMap::handleRightMouseDown(S32 x, S32 y, MASK mask)
-{
- mClosestAgentAtLastRightClick = mClosestAgentToCursor;
- LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
- if (menu)
- {
- menu->buildDrawLabels();
- menu->updateParent(LLMenuGL::sMenuContainer);
- LLMenuGL::showPopup(this, menu, x, y);
- }
- return TRUE;
-}
-
-
-// static
-bool LLNetMap::LLScaleMap::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
-{
- LLNetMap *self = mPtr;
-
- S32 level = userdata.asInteger();
-
- switch(level)
- {
- case 0:
- self->setScale(MAP_SCALE_MIN);
- break;
- case 1:
- self->setScale(MAP_SCALE_MID);
- break;
- case 2:
- self->setScale(MAP_SCALE_MAX);
- break;
- default:
- break;
- }
-
- return true;
-}
-
-bool LLNetMap::LLStopTracking::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
-{
- LLTracker::stopTracking(NULL);
- return true;
-}
-
-bool LLNetMap::LLEnableTracking::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
-{
- LLNetMap *self = mPtr;
- self->findControl(userdata["control"].asString())->setValue(LLTracker::isTracking(NULL));
- return true;
-}
-
-bool LLNetMap::LLShowAgentProfile::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
-{
- LLNetMap *self = mPtr;
- LLFloaterAvatarInfo::show(self->mClosestAgentAtLastRightClick);
- return true;
-}
-
-bool LLNetMap::LLEnableProfile::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
-{
- LLNetMap *self = mPtr;
- self->findControl(userdata["control"].asString())->setValue(self->isAgentUnderCursor());
- return true;
-}
diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h
index a5bf9f0fb5..3d7f3233ac 100644
--- a/indra/newview/llnetmap.h
+++ b/indra/newview/llnetmap.h
@@ -33,60 +33,81 @@
#ifndef LL_LLNETMAP_H
#define LL_LLNETMAP_H
-#include "llpanel.h"
-#include "llmemberlistener.h"
+#include "llmath.h"
+#include "lluictrl.h"
#include "v3math.h"
#include "v3dmath.h"
#include "v4color.h"
-#include "llimage.h"
-#include "llimagegl.h"
-
+#include "llpointer.h"
+class LLColor4U;
+class LLCoordGL;
+class LLImageRaw;
class LLTextBox;
+class LLViewerTexture;
+
+const F32 MAP_SCALE_MIN = 64.f;
+const F32 MAP_SCALE_MID = 172.f;
+const F32 MAP_SCALE_MAX = 512.f;
-class LLNetMap : public LLPanel
+class LLNetMap : public LLUICtrl
{
public:
- LLNetMap(const std::string& name);
- virtual ~LLNetMap();
+ struct Params
+ : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<LLUIColor> bg_color;
- virtual void draw();
- virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
- virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask );
- virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
- virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
- virtual BOOL handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen );
+ Params()
+ : bg_color("bg_color")
+ {}
+ };
- void renderScaledPointGlobal( const LLVector3d& pos, const LLColor4U &color, F32 radius );
+protected:
+ LLNetMap (const Params & p);
+ friend class LLUICtrlFactory;
-private:
+public:
+ virtual ~LLNetMap();
- void setScale( F32 scale );
+ static const F32 MAP_SCALE_MIN;
+ static const F32 MAP_SCALE_MID;
+ static const F32 MAP_SCALE_MAX;
- // *TODO: Enable panning of the mini-map
+ /*virtual*/ void draw();
+ /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+ /*virtual*/ BOOL handleToolTip( S32 x, S32 y, MASK mask);
+ /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+ void setScale( F32 scale );
+ void setToolTipMsg(const std::string& msg) { mToolTipMsg = msg; }
+ void renderScaledPointGlobal( const LLVector3d& pos, const LLColor4U &color, F32 radius );
+
+private:
void translatePan( F32 delta_x, F32 delta_y );
void setPan( F32 x, F32 y ) { mTargetPanX = x; mTargetPanY = y; }
- void renderPoint(const LLVector3 &pos, const LLColor4U &color,
- S32 diameter, S32 relative_height = 0);
- LLVector3 globalPosToView(const LLVector3d& global_pos, BOOL rotated);
- LLVector3d viewPosToGlobal(S32 x,S32 y, BOOL rotated);
+ const LLVector3d& getObjectImageCenterGlobal() { return mObjectImageCenterGlobal; }
+ void renderPoint(const LLVector3 &pos, const LLColor4U &color,
+ S32 diameter, S32 relative_height = 0);
- void drawTracking( const LLVector3d& pos_global,
- BOOL rotated,
- const LLColor4& color,
- BOOL draw_arrow = TRUE);
+ LLVector3 globalPosToView(const LLVector3d& global_pos);
+ LLVector3d viewPosToGlobal(S32 x,S32 y);
- void setDirectionPos( LLTextBox* text_box, F32 rotation );
- void updateMinorDirections();
+ void drawTracking( const LLVector3d& pos_global,
+ const LLColor4& color,
+ BOOL draw_arrow = TRUE);
+
void createObjectImage();
- LLHandle<LLView> mPopupMenuHandle;
+private:
+ LLUIColor mBackgroundColor;
F32 mScale; // Size of a region in pixels
F32 mPixelsPerMeter; // world meters to map pixels
F32 mObjectMapTPM; // texels per meter on map
- F32 mObjectMapPixels; // Width of object map in pixels;
+ F32 mObjectMapPixels; // Width of object map in pixels
+ F32 mDotRadius; // Size of avatar markers
F32 mTargetPanX;
F32 mTargetPanY;
F32 mCurPanX;
@@ -94,47 +115,12 @@ private:
BOOL mUpdateNow;
LLVector3d mObjectImageCenterGlobal;
LLPointer<LLImageRaw> mObjectRawImagep;
- LLPointer<LLImageGL> mObjectImagep;
+ LLPointer<LLViewerTexture> mObjectImagep;
-private:
LLUUID mClosestAgentToCursor;
LLUUID mClosestAgentAtLastRightClick;
- static BOOL sRotateMap;
- static LLNetMap* sInstance;
- static BOOL isAgentUnderCursor(void*) { return sInstance && sInstance->mClosestAgentToCursor.notNull(); }
- static void showAgentProfile(void*);
- BOOL isAgentUnderCursor() { return mClosestAgentToCursor.notNull(); }
-
- class LLScaleMap : public LLMemberListener<LLNetMap>
- {
- public:
- /*virtual*/ bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata);
- };
-
- class LLStopTracking : public LLMemberListener<LLNetMap>
- {
- public:
- /*virtual*/ bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata);
- };
-
- class LLEnableTracking : public LLMemberListener<LLNetMap>
- {
- public:
- /*virtual*/ bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata);
- };
-
- class LLShowAgentProfile : public LLMemberListener<LLNetMap>
- {
- public:
- /*virtual*/ bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata);
- };
-
- class LLEnableProfile : public LLMemberListener<LLNetMap>
- {
- public:
- /*virtual*/ bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata);
- };
+ std::string mToolTipMsg;
};
diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp
new file mode 100644
index 0000000000..52de8355e9
--- /dev/null
+++ b/indra/newview/llnotificationalerthandler.cpp
@@ -0,0 +1,146 @@
+/**
+ * @file llnotificationalerthandler.cpp
+ * @brief Notification Handler Class for Alert Notifications
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#include "llnotificationhandler.h"
+
+#include "llnotifications.h"
+#include "lltoastnotifypanel.h"
+#include "llviewercontrol.h"
+#include "llviewerwindow.h"
+
+#include "lltoastalertpanel.h"
+
+using namespace LLNotificationsUI;
+
+//--------------------------------------------------------------------------
+LLAlertHandler::LLAlertHandler(e_notification_type type, const LLSD& id) : mIsModal(false)
+{
+ mType = type;
+
+ LLChannelManager::Params p;
+ p.id = LLUUID(gSavedSettings.getString("AlertChannelUUID"));
+ p.display_toasts_always = true;
+ p.toast_align = NA_CENTRE;
+ p.channel_align = CA_CENTRE;
+
+ // Getting a Channel for our notifications
+ mChannel = LLChannelManager::getInstance()->getChannel(p);
+ mChannel->setCanStoreToasts(false);
+}
+
+//--------------------------------------------------------------------------
+LLAlertHandler::~LLAlertHandler()
+{
+}
+
+//--------------------------------------------------------------------------
+void LLAlertHandler::initChannel()
+{
+ S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().getWidth() / 2;
+ mChannel->init(channel_right_bound, channel_right_bound);
+}
+
+//--------------------------------------------------------------------------
+bool LLAlertHandler::processNotification(const LLSD& notify)
+{
+ if(!mChannel)
+ {
+ return false;
+ }
+
+ LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
+
+ if(!notification)
+ return false;
+
+ // arrange a channel on a screen
+ if(!mChannel->getVisible())
+ {
+ initChannel();
+ }
+
+ if (notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "load")
+ {
+ if (LLHandlerUtil::canSpawnSessionAndLogToIM(notification))
+ {
+ const std::string name = LLHandlerUtil::getSubstitutionName(notification);
+
+ LLUUID from_id = notification->getPayload()["from_id"];
+
+ // firstly create session...
+ LLHandlerUtil::spawnIMSession(name, from_id);
+
+ // ...then log message to have IM Well notified about new message
+ LLHandlerUtil::logToIMP2P(notification);
+ }
+
+ LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal);
+ LLToast::Params p;
+ p.notif_id = notification->getID();
+ p.notification = notification;
+ p.panel = dynamic_cast<LLToastPanel*>(alert_dialog);
+ p.enable_hide_btn = false;
+ p.can_fade = false;
+ p.is_modal = mIsModal;
+ p.on_delete_toast = boost::bind(&LLAlertHandler::onDeleteToast, this, _1);
+
+ LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
+ if(channel)
+ channel->addToast(p);
+ }
+ else if (notify["sigtype"].asString() == "change")
+ {
+ LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal);
+ LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
+ if(channel)
+ channel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog);
+ }
+ else
+ {
+ LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
+ if(channel)
+ channel->killToastByNotificationID(notification->getID());
+ }
+ return true;
+}
+
+//--------------------------------------------------------------------------
+
+void LLAlertHandler::onDeleteToast(LLToast* toast)
+{
+}
+
+//--------------------------------------------------------------------------
+
diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp
new file mode 100644
index 0000000000..6889931956
--- /dev/null
+++ b/indra/newview/llnotificationgrouphandler.cpp
@@ -0,0 +1,139 @@
+/**
+ * @file llnotificationgrouphandler.cpp
+ * @brief Notification Handler Class for Group Notifications
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#include "llnotificationhandler.h"
+#include "lltoastgroupnotifypanel.h"
+#include "llgroupactions.h"
+#include "llviewercontrol.h"
+#include "llviewerwindow.h"
+#include "llnotificationmanager.h"
+#include "llnotifications.h"
+
+using namespace LLNotificationsUI;
+
+//--------------------------------------------------------------------------
+LLGroupHandler::LLGroupHandler(e_notification_type type, const LLSD& id)
+{
+ mType = type;
+
+ // Getting a Channel for our notifications
+ mChannel = LLChannelManager::getInstance()->createNotificationChannel();
+ LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
+ if(channel)
+ channel->setOnRejectToastCallback(boost::bind(&LLGroupHandler::onRejectToast, this, _1));
+}
+
+//--------------------------------------------------------------------------
+LLGroupHandler::~LLGroupHandler()
+{
+}
+
+//--------------------------------------------------------------------------
+void LLGroupHandler::initChannel()
+{
+ S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin");
+ S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
+ mChannel->init(channel_right_bound - channel_width, channel_right_bound);
+}
+
+//--------------------------------------------------------------------------
+bool LLGroupHandler::processNotification(const LLSD& notify)
+{
+ if(!mChannel)
+ {
+ return false;
+ }
+
+ LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
+
+ if(!notification)
+ return false;
+
+ // arrange a channel on a screen
+ if(!mChannel->getVisible())
+ {
+ initChannel();
+ }
+
+ if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change")
+ {
+ LLHandlerUtil::logGroupNoticeToIMGroup(notification);
+
+ LLPanel* notify_box = new LLToastGroupNotifyPanel(notification);
+ LLToast::Params p;
+ p.notif_id = notification->getID();
+ p.notification = notification;
+ p.panel = notify_box;
+ p.on_delete_toast = boost::bind(&LLGroupHandler::onDeleteToast, this, _1);
+
+ LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
+ if(channel)
+ channel->addToast(p);
+
+ // send a signal to the counter manager
+ mNewNotificationSignal();
+
+ LLGroupActions::refresh_notices();
+ }
+ else if (notify["sigtype"].asString() == "delete")
+ {
+ mChannel->killToastByNotificationID(notification->getID());
+ }
+ return true;
+}
+
+//--------------------------------------------------------------------------
+void LLGroupHandler::onDeleteToast(LLToast* toast)
+{
+ // send a signal to the counter manager
+ mDelNotificationSignal();
+
+ // send a signal to a listener to let him perform some action
+ // in this case listener is a SysWellWindow and it will remove a corresponding item from its list
+ mNotificationIDSignal(toast->getNotificationID());
+}
+
+//--------------------------------------------------------------------------
+void LLGroupHandler::onRejectToast(LLUUID& id)
+{
+ LLNotificationPtr notification = LLNotifications::instance().find(id);
+
+ if (notification && LLNotificationManager::getInstance()->getHandlerForNotification(notification->getType()) == this)
+ {
+ LLNotifications::instance().cancel(notification);
+ }
+}
+
+//--------------------------------------------------------------------------
+
diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h
new file mode 100644
index 0000000000..0fb438bfe9
--- /dev/null
+++ b/indra/newview/llnotificationhandler.h
@@ -0,0 +1,326 @@
+/**
+ * @file llnotificationhandler.h
+ * @brief Here are implemented Notification Handling Classes.
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLNOTIFICATIONHANDLER_H
+#define LL_LLNOTIFICATIONHANDLER_H
+
+
+#include "llwindow.h"
+
+//#include "llnotificationsutil.h"
+#include "llchannelmanager.h"
+#include "llchat.h"
+#include "llinstantmessage.h"
+#include "llnotificationptr.h"
+
+namespace LLNotificationsUI
+{
+// ENotificationType enumerates all possible types of notifications that could be met
+//
+typedef enum e_notification_type
+{
+ NT_NOTIFY,
+ NT_NOTIFYTIP,
+ NT_GROUPNOTIFY,
+ NT_IMCHAT,
+ NT_GROUPCHAT,
+ NT_NEARBYCHAT,
+ NT_ALERT,
+ NT_ALERTMODAL,
+ NT_OFFER
+} ENotificationType;
+
+/**
+ * Handler of notification events.
+ * This handler manages events related to toasts and chicklets. This is base class
+ * for chat and system notification handlers.
+ */
+
+// LLEventHandler is a base class that specifies a common interface for all
+// notification handlers. It states, that every handler must react on the follofing
+// events:
+// - deleting of a toast;
+// - initialization of a corresponding channel;
+// Also every handler must have the following attributes:
+// - type of the notification that this handler is responsible to;
+// - pointer to a correspondent screen channel, in which all toasts of the handled notification's
+// type should be displayed
+// This class also provides the following signald:
+// - increment counter signal
+// - decrement counter signal
+// - update counter signal
+// - signal, that emits ID of the notification that is being processed
+//
+class LLEventHandler
+{
+public:
+ virtual ~LLEventHandler() {};
+
+ // callbacks for counters
+ typedef boost::function<void (void)> notification_callback_t;
+ typedef boost::signals2::signal<void (void)> notification_signal_t;
+ notification_signal_t mNewNotificationSignal;
+ notification_signal_t mDelNotificationSignal;
+ boost::signals2::connection setNewNotificationCallback(notification_callback_t cb) { return mNewNotificationSignal.connect(cb); }
+ boost::signals2::connection setDelNotification(notification_callback_t cb) { return mDelNotificationSignal.connect(cb); }
+ // callback for notification/toast
+ typedef boost::function<void (const LLUUID id)> notification_id_callback_t;
+ typedef boost::signals2::signal<void (const LLUUID id)> notification_id_signal_t;
+ notification_id_signal_t mNotificationIDSignal;
+ boost::signals2::connection setNotificationIDCallback(notification_id_callback_t cb) { return mNotificationIDSignal.connect(cb); }
+
+protected:
+ virtual void onDeleteToast(LLToast* toast)=0;
+
+ // arrange handler's channel on a screen
+ // is necessary to unbind a moment of creation of a channel and a moment of positioning of it
+ // it is useful when positioning depends on positions of other controls, that could not be created
+ // at the moment, when a handlers creates a channel.
+ virtual void initChannel()=0;
+
+ LLScreenChannelBase* mChannel;
+ e_notification_type mType;
+
+};
+
+// LLSysHandler and LLChatHandler are more specific base classes
+// that divide all notification handlers on to groups:
+// - handlers for different system notifications (script dialogs, tips, group notices, alerts and IMs);
+// - handlers for different messaging notifications (nearby chat)
+/**
+ * Handler for system notifications.
+ */
+class LLSysHandler : public LLEventHandler
+{
+public:
+ virtual ~LLSysHandler() {};
+
+ virtual bool processNotification(const LLSD& notify)=0;
+};
+
+/**
+ * Handler for chat message notifications.
+ */
+class LLChatHandler : public LLEventHandler
+{
+public:
+ virtual ~LLChatHandler() {};
+
+ virtual void processChat(const LLChat& chat_msg)=0;
+};
+
+/**
+ * Handler for IM notifications.
+ * It manages life time of IMs, group messages.
+ */
+class LLIMHandler : public LLSysHandler
+{
+public:
+ LLIMHandler(e_notification_type type, const LLSD& id);
+ virtual ~LLIMHandler();
+
+ // base interface functions
+ virtual bool processNotification(const LLSD& notify);
+
+protected:
+ virtual void onDeleteToast(LLToast* toast);
+ virtual void initChannel();
+};
+
+/**
+ * Handler for system informational notices.
+ * It manages life time of tip notices.
+ */
+class LLTipHandler : public LLSysHandler
+{
+public:
+ LLTipHandler(e_notification_type type, const LLSD& id);
+ virtual ~LLTipHandler();
+
+ // base interface functions
+ virtual bool processNotification(const LLSD& notify);
+
+protected:
+ virtual void onDeleteToast(LLToast* toast);
+ virtual void initChannel();
+};
+
+/**
+ * Handler for system informational notices.
+ * It manages life time of script notices.
+ */
+class LLScriptHandler : public LLSysHandler
+{
+public:
+ LLScriptHandler(e_notification_type type, const LLSD& id);
+ virtual ~LLScriptHandler();
+
+ // base interface functions
+ virtual bool processNotification(const LLSD& notify);
+
+protected:
+ virtual void onDeleteToast(LLToast* toast);
+ virtual void initChannel();
+
+ // own handlers
+ void onRejectToast(LLUUID& id);
+};
+
+
+/**
+ * Handler for group system notices.
+ */
+class LLGroupHandler : public LLSysHandler
+{
+public:
+ LLGroupHandler(e_notification_type type, const LLSD& id);
+ virtual ~LLGroupHandler();
+
+ // base interface functions
+ virtual bool processNotification(const LLSD& notify);
+
+protected:
+ virtual void onDeleteToast(LLToast* toast);
+ virtual void initChannel();
+
+ // own handlers
+ void onRejectToast(LLUUID& id);
+};
+
+/**
+ * Handler for alert system notices.
+ */
+class LLAlertHandler : public LLSysHandler
+{
+public:
+ LLAlertHandler(e_notification_type type, const LLSD& id);
+ virtual ~LLAlertHandler();
+
+ void setAlertMode(bool is_modal) { mIsModal = is_modal; }
+
+ // base interface functions
+ virtual bool processNotification(const LLSD& notify);
+
+protected:
+ virtual void onDeleteToast(LLToast* toast);
+ virtual void initChannel();
+
+ bool mIsModal;
+};
+
+/**
+ * Handler for offers notices.
+ * It manages life time of offer notices.
+ */
+class LLOfferHandler : public LLSysHandler
+{
+public:
+ LLOfferHandler(e_notification_type type, const LLSD& id);
+ virtual ~LLOfferHandler();
+
+ // base interface functions
+ virtual bool processNotification(const LLSD& notify);
+
+protected:
+ virtual void onDeleteToast(LLToast* toast);
+ virtual void initChannel();
+
+ // own handlers
+ void onRejectToast(LLUUID& id);
+};
+
+class LLHandlerUtil
+{
+public:
+ /**
+ * Checks sufficient conditions to log notification message to IM session.
+ */
+ static bool canLogToIM(const LLNotificationPtr& notification);
+
+ /**
+ * Checks sufficient conditions to log notification message to nearby chat session.
+ */
+ static bool canLogToNearbyChat(const LLNotificationPtr& notification);
+
+ /**
+ * Checks sufficient conditions to spawn IM session.
+ */
+ static bool canSpawnIMSession(const LLNotificationPtr& notification);
+
+ /**
+ * Checks if passed notification can create IM session and be written into it.
+ *
+ * This method uses canLogToIM() & canSpawnIMSession().
+ */
+ static bool canSpawnSessionAndLogToIM(const LLNotificationPtr& notification);
+
+ /**
+ * Writes notification message to IM session.
+ */
+ static void logToIM(const EInstantMessage& session_type,
+ const std::string& session_name, const std::string& from_name,
+ const std::string& message, const LLUUID& session_owner_id,
+ const LLUUID& from_id);
+
+ /**
+ * Writes notification message to IM p2p session.
+ */
+ static void logToIMP2P(const LLNotificationPtr& notification);
+
+ /**
+ * Writes group notice notification message to IM group session.
+ */
+ static void logGroupNoticeToIMGroup(const LLNotificationPtr& notification);
+
+ /**
+ * Writes notification message to nearby chat.
+ */
+ static void logToNearbyChat(const LLNotificationPtr& notification, EChatSourceType type);
+
+ /**
+ * Spawns IM session.
+ */
+ static void spawnIMSession(const std::string& name, const LLUUID& from_id);
+
+ /**
+ * Returns name from the notification's substitution.
+ *
+ * Methods gets "NAME" or "[NAME]" from the substitution map.
+ *
+ * @param notification - Notification which substitution's name will be returned.
+ */
+ static std::string getSubstitutionName(const LLNotificationPtr& notification);
+};
+
+}
+#endif
+
diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp
new file mode 100644
index 0000000000..fba5773602
--- /dev/null
+++ b/indra/newview/llnotificationhandlerutil.cpp
@@ -0,0 +1,205 @@
+/**
+ * @file llnotificationofferhandler.cpp
+ * @brief Provides set of utility methods for notifications processing.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#include "llnotificationhandler.h"
+#include "llnotifications.h"
+#include "llimview.h"
+#include "llagent.h"
+#include "llfloaterreg.h"
+#include "llnearbychat.h"
+
+using namespace LLNotificationsUI;
+
+const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"),
+ REVOKED_MODIFY_RIGHTS("RevokedModifyRights"), OBJECT_GIVE_ITEM(
+ "ObjectGiveItem"), OBJECT_GIVE_ITEM_UNKNOWN_USER(
+ "ObjectGiveItemUnknownUser"), PAYMENT_RECIVED("PaymentRecived"),
+ ADD_FRIEND_WITH_MESSAGE("AddFriendWithMessage"),
+ USER_GIVE_ITEM("UserGiveItem"),
+ INVENTORY_ACCEPTED("InventoryAccepted"),
+ INVENTORY_DECLINED("InventoryDeclined"),
+ OFFER_FRIENDSHIP("OfferFriendship"),
+ FRIENDSHIP_ACCEPTED("FriendshipAccepted"),
+ FRIENDSHIP_OFFERED("FriendshipOffered"),
+ FRIEND_ONLINE("FriendOnline"), FRIEND_OFFLINE("FriendOffline"),
+ SERVER_OBJECT_MESSAGE("ServerObjectMessage"),
+ TELEPORT_OFFERED("TeleportOffered");
+
+// static
+bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification)
+{
+ return GRANTED_MODIFY_RIGHTS == notification->getName()
+ || REVOKED_MODIFY_RIGHTS == notification->getName()
+ || PAYMENT_RECIVED == notification->getName()
+ || OFFER_FRIENDSHIP == notification->getName()
+ || FRIENDSHIP_OFFERED == notification->getName()
+ || SERVER_OBJECT_MESSAGE == notification->getName()
+ || INVENTORY_ACCEPTED == notification->getName()
+ || INVENTORY_DECLINED == notification->getName();
+}
+
+// static
+bool LLHandlerUtil::canLogToNearbyChat(const LLNotificationPtr& notification)
+{
+ return notification->getType() == "notifytip"
+ && FRIEND_ONLINE != notification->getName()
+ && FRIEND_OFFLINE != notification->getName()
+ && INVENTORY_ACCEPTED != notification->getName()
+ && INVENTORY_DECLINED != notification->getName();
+}
+
+// static
+bool LLHandlerUtil::canSpawnIMSession(const LLNotificationPtr& notification)
+{
+ return OFFER_FRIENDSHIP == notification->getName()
+ || FRIENDSHIP_ACCEPTED == notification->getName()
+ || USER_GIVE_ITEM == notification->getName()
+ || INVENTORY_ACCEPTED == notification->getName()
+ || INVENTORY_DECLINED == notification->getName();
+}
+
+// static
+bool LLHandlerUtil::canSpawnSessionAndLogToIM(const LLNotificationPtr& notification)
+{
+ return canLogToIM(notification) && canSpawnIMSession(notification);
+}
+
+// static
+void LLHandlerUtil::logToIM(const EInstantMessage& session_type,
+ const std::string& session_name, const std::string& from_name,
+ const std::string& message, const LLUUID& session_owner_id,
+ const LLUUID& from_id)
+{
+ LLUUID session_id = LLIMMgr::computeSessionID(session_type,
+ session_owner_id);
+ LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(
+ session_id);
+ if (session == NULL)
+ {
+ LLIMModel::instance().logToFile(session_name, from_name, from_id, message);
+ }
+ else
+ {
+ // store active session id
+ const LLUUID & active_session_id =
+ LLIMModel::instance().getActiveSessionID();
+
+ // set searched session as active to avoid IM toast popup
+ LLIMModel::instance().setActiveSessionID(session_id);
+
+ LLIMModel::instance().addMessage(session_id, from_name, from_id,
+ message);
+
+ // restore active session id
+ LLIMModel::instance().setActiveSessionID(active_session_id);
+ }
+}
+
+// static
+void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification)
+{
+ const std::string name = LLHandlerUtil::getSubstitutionName(notification);
+
+ const std::string session_name = notification->getPayload().has(
+ "SESSION_NAME") ? notification->getPayload()["SESSION_NAME"].asString() : name;
+
+ // don't create IM p2p session with objects, it's necessary condition to log
+ if (notification->getName() != OBJECT_GIVE_ITEM && notification->getName()
+ != OBJECT_GIVE_ITEM_UNKNOWN_USER)
+ {
+ LLUUID from_id = notification->getPayload()["from_id"];
+
+ logToIM(IM_NOTHING_SPECIAL, session_name, name, notification->getMessage(),
+ from_id, from_id);
+ }
+}
+
+// static
+void LLHandlerUtil::logGroupNoticeToIMGroup(
+ const LLNotificationPtr& notification)
+{
+
+ const LLSD& payload = notification->getPayload();
+ LLGroupData groupData;
+ if (!gAgent.getGroupData(payload["group_id"].asUUID(), groupData))
+ {
+ llwarns
+ << "Group notice for unkown group: "
+ << payload["group_id"].asUUID() << llendl;
+ }
+
+ const std::string group_name = groupData.mName;
+ const std::string sender_name = payload["sender_name"].asString();
+
+ // we can't retrieve sender id from group notice system message, so try to lookup it from cache
+ LLUUID sender_id;
+ gCacheName->getUUID(sender_name, sender_id);
+
+ logToIM(IM_SESSION_GROUP_START, group_name, sender_name, payload["message"],
+ payload["group_id"], sender_id);
+}
+
+// static
+void LLHandlerUtil::logToNearbyChat(const LLNotificationPtr& notification, EChatSourceType type)
+{
+ LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
+ if(nearby_chat)
+ {
+ LLChat chat_msg(notification->getMessage());
+ chat_msg.mSourceType = type;
+ nearby_chat->addMessage(chat_msg);
+ }
+}
+
+// static
+void LLHandlerUtil::spawnIMSession(const std::string& name, const LLUUID& from_id)
+{
+ LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id);
+
+ LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(
+ session_id);
+ if (session == NULL)
+ {
+ LLIMMgr::instance().addSession(name, IM_NOTHING_SPECIAL, from_id);
+ }
+}
+
+// static
+std::string LLHandlerUtil::getSubstitutionName(const LLNotificationPtr& notification)
+{
+ return notification->getSubstitutions().has("NAME")
+ ? notification->getSubstitutions()["NAME"]
+ : notification->getSubstitutions()["[NAME]"];
+}
diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp
new file mode 100644
index 0000000000..66bc217d15
--- /dev/null
+++ b/indra/newview/llnotificationmanager.cpp
@@ -0,0 +1,139 @@
+/**
+ * @file llnotificationmanager.cpp
+ * @brief Class implements a brige between the old and a new notification sistems
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+
+#include "llnotificationmanager.h"
+
+#include "llnearbychathandler.h"
+#include "llnotifications.h"
+
+#include <boost/bind.hpp>
+
+using namespace LLNotificationsUI;
+
+//--------------------------------------------------------------------------
+LLNotificationManager::LLNotificationManager()
+{
+ mNotifyHandlers.clear();
+ init();
+}
+
+//--------------------------------------------------------------------------
+LLNotificationManager::~LLNotificationManager()
+{
+}
+
+//--------------------------------------------------------------------------
+void LLNotificationManager::init()
+{
+ LLNotificationChannel::buildChannel("Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notify"));
+ LLNotificationChannel::buildChannel("NotificationTips", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notifytip"));
+ LLNotificationChannel::buildChannel("Group Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "groupnotify"));
+ LLNotificationChannel::buildChannel("Alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"));
+ LLNotificationChannel::buildChannel("AlertModal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal"));
+ LLNotificationChannel::buildChannel("IM Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notifytoast"));
+ LLNotificationChannel::buildChannel("Offer", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "offer"));
+
+ LLNotifications::instance().getChannel("Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
+ LLNotifications::instance().getChannel("NotificationTips")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
+ LLNotifications::instance().getChannel("Group Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
+ LLNotifications::instance().getChannel("Alerts")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
+ LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
+ LLNotifications::instance().getChannel("IM Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
+ LLNotifications::instance().getChannel("Offer")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
+
+ mNotifyHandlers["notify"] = boost::shared_ptr<LLEventHandler>(new LLScriptHandler(NT_NOTIFY, LLSD()));
+ mNotifyHandlers["notifytip"] = boost::shared_ptr<LLEventHandler>(new LLTipHandler(NT_NOTIFY, LLSD()));
+ mNotifyHandlers["groupnotify"] = boost::shared_ptr<LLEventHandler>(new LLGroupHandler(NT_GROUPNOTIFY, LLSD()));
+ mNotifyHandlers["alert"] = boost::shared_ptr<LLEventHandler>(new LLAlertHandler(NT_ALERT, LLSD()));
+ mNotifyHandlers["alertmodal"] = boost::shared_ptr<LLEventHandler>(new LLAlertHandler(NT_ALERT, LLSD()));
+ static_cast<LLAlertHandler*>(mNotifyHandlers["alertmodal"].get())->setAlertMode(true);
+ mNotifyHandlers["notifytoast"] = boost::shared_ptr<LLEventHandler>(new LLIMHandler(NT_IMCHAT, LLSD()));
+
+ mNotifyHandlers["nearbychat"] = boost::shared_ptr<LLEventHandler>(new LLNearbyChatHandler(NT_NEARBYCHAT, LLSD()));
+ mNotifyHandlers["offer"] = boost::shared_ptr<LLEventHandler>(new LLOfferHandler(NT_OFFER, LLSD()));
+}
+
+//--------------------------------------------------------------------------
+bool LLNotificationManager::onNotification(const LLSD& notify)
+{
+ LLSysHandler* handle = NULL;
+
+ LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
+
+ if (!notification)
+ return false;
+
+ std::string notification_type = notification->getType();
+ handle = static_cast<LLSysHandler*>(mNotifyHandlers[notification_type].get());
+
+ if(!handle)
+ return false;
+
+ return handle->processNotification(notify);
+}
+
+//--------------------------------------------------------------------------
+void LLNotificationManager::onChat(const LLChat& msg,ENotificationType type)
+{
+ switch(type)
+ {
+ case NT_NEARBYCHAT:
+ {
+ LLNearbyChatHandler* handle = dynamic_cast<LLNearbyChatHandler*>(mNotifyHandlers["nearbychat"].get());
+
+ if(handle)
+ handle->processChat(msg);
+ }
+ break;
+ default: //no need to handle all enum types
+ break;
+ }
+}
+
+//--------------------------------------------------------------------------
+LLEventHandler* LLNotificationManager::getHandlerForNotification(std::string notification_type)
+{
+ std::map<std::string, boost::shared_ptr<LLEventHandler> >::iterator it = mNotifyHandlers.find(notification_type);
+
+ if(it != mNotifyHandlers.end())
+ return (*it).second.get();
+
+ return NULL;
+}
+
+//--------------------------------------------------------------------------
+
diff --git a/indra/newview/llnotificationmanager.h b/indra/newview/llnotificationmanager.h
new file mode 100644
index 0000000000..072fc6f24c
--- /dev/null
+++ b/indra/newview/llnotificationmanager.h
@@ -0,0 +1,83 @@
+// Notification Manager Class
+/**
+ * @file llnotificationmanager.h
+ * @brief Class implements a brige between the old and a new notification sistems
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLNOTIFICATIONMANAGER_H
+#define LL_LLNOTIFICATIONMANAGER_H
+
+#include "lluictrl.h"
+#include "llnotificationhandler.h"
+
+
+#include <map>
+#include <string>
+
+#include <boost/shared_ptr.hpp>
+
+namespace LLNotificationsUI {
+
+class LLToast;
+
+/**
+ * Responsible for registering notification handlers.
+ */
+class LLNotificationManager : public LLSingleton<LLNotificationManager>
+{
+ typedef std::pair<std::string, LLEventHandler*> eventhandlers;
+public:
+ LLNotificationManager();
+ virtual ~LLNotificationManager();
+
+ //TODO: make private
+ // this method initialize handlers' map for different types of notifications
+ void init(void);
+ //TODO: combine processing and storage (*)
+
+ // this method reacts on system notifications and calls an appropriate handler
+ bool onNotification(const LLSD& notification);
+
+ // this method reacts on chat notifications and calls an appropriate handler
+ void onChat(const LLChat& msg,ENotificationType type);
+
+ // get a handler for a certain type of notification
+ LLEventHandler* getHandlerForNotification(std::string notification_type);
+
+
+private:
+ //TODO (*)
+ std::map<std::string, boost::shared_ptr<LLEventHandler> > mNotifyHandlers;
+ std::map<std::string, LLChatHandler*> mChatHandlers;
+};
+
+}
+#endif
+
diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp
new file mode 100644
index 0000000000..fad0c6a91e
--- /dev/null
+++ b/indra/newview/llnotificationofferhandler.cpp
@@ -0,0 +1,179 @@
+/**
+ * @file llnotificationofferhandler.cpp
+ * @brief Notification Handler Class for Simple Notifications and Notification Tips
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#include "llnotificationhandler.h"
+#include "lltoastnotifypanel.h"
+#include "llviewercontrol.h"
+#include "llviewerwindow.h"
+#include "llnotificationmanager.h"
+#include "llnotifications.h"
+#include "llscriptfloater.h"
+#include "llimview.h"
+#include "llnotificationsutil.h"
+
+using namespace LLNotificationsUI;
+
+//--------------------------------------------------------------------------
+LLOfferHandler::LLOfferHandler(e_notification_type type, const LLSD& id)
+{
+ mType = type;
+
+ // Getting a Channel for our notifications
+ mChannel = LLChannelManager::getInstance()->createNotificationChannel();
+ mChannel->setControlHovering(true);
+
+ LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
+ if(channel)
+ channel->setOnRejectToastCallback(boost::bind(&LLOfferHandler::onRejectToast, this, _1));
+}
+
+//--------------------------------------------------------------------------
+LLOfferHandler::~LLOfferHandler()
+{
+}
+
+//--------------------------------------------------------------------------
+void LLOfferHandler::initChannel()
+{
+ S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin");
+ S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
+ mChannel->init(channel_right_bound - channel_width, channel_right_bound);
+}
+
+//--------------------------------------------------------------------------
+bool LLOfferHandler::processNotification(const LLSD& notify)
+{
+ if(!mChannel)
+ {
+ return false;
+ }
+
+ LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
+
+ if(!notification)
+ return false;
+
+ // arrange a channel on a screen
+ if(!mChannel->getVisible())
+ {
+ initChannel();
+ }
+
+ if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change")
+ {
+ LLHandlerUtil::logToIMP2P(notification);
+
+ if( notification->getPayload().has("give_inventory_notification")
+ && !notification->getPayload()["give_inventory_notification"] )
+ {
+ // This is an original inventory offer, so add a script floater
+ LLScriptFloaterManager::instance().onAddNotification(notification->getID());
+ }
+ else
+ {
+ if (LLHandlerUtil::canSpawnIMSession(notification))
+ {
+ const std::string name = LLHandlerUtil::getSubstitutionName(notification);
+
+ LLUUID from_id = notification->getPayload()["from_id"];
+
+ LLHandlerUtil::spawnIMSession(name, from_id);
+ }
+
+ if (notification->getPayload().has("SUPPRESS_TOAST")
+ && notification->getPayload()["SUPPRESS_TOAST"])
+ {
+ LLNotificationsUtil::cancel(notification);
+ }
+ else
+ {
+ LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification);
+
+ LLToast::Params p;
+ p.notif_id = notification->getID();
+ p.notification = notification;
+ p.panel = notify_box;
+ p.on_delete_toast = boost::bind(&LLOfferHandler::onDeleteToast, this, _1);
+
+ LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
+ if(channel)
+ channel->addToast(p);
+
+ // send a signal to the counter manager
+ mNewNotificationSignal();
+ }
+ }
+ }
+ else if (notify["sigtype"].asString() == "delete")
+ {
+ if( notification->getPayload().has("give_inventory_notification")
+ && !notification->getPayload()["give_inventory_notification"] )
+ {
+ // Remove original inventory offer script floater
+ LLScriptFloaterManager::instance().onRemoveNotification(notification->getID());
+ }
+ else
+ {
+ mChannel->killToastByNotificationID(notification->getID());
+ }
+ }
+
+ return true;
+}
+
+//--------------------------------------------------------------------------
+
+void LLOfferHandler::onDeleteToast(LLToast* toast)
+{
+ // send a signal to the counter manager
+ mDelNotificationSignal();
+
+ // send a signal to a listener to let him perform some action
+ // in this case listener is a SysWellWindow and it will remove a corresponding item from its list
+ mNotificationIDSignal(toast->getNotificationID());
+}
+
+//--------------------------------------------------------------------------
+void LLOfferHandler::onRejectToast(LLUUID& id)
+{
+ LLNotificationPtr notification = LLNotifications::instance().find(id);
+
+ if (notification
+ && LLNotificationManager::getInstance()->getHandlerForNotification(
+ notification->getType()) == this)
+ {
+ LLNotifications::instance().cancel(notification);
+ }
+}
diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp
new file mode 100644
index 0000000000..c7261199e3
--- /dev/null
+++ b/indra/newview/llnotificationscripthandler.cpp
@@ -0,0 +1,179 @@
+/**
+ * @file llnotificationscripthandler.cpp
+ * @brief Notification Handler Class for Simple Notifications and Notification Tips
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#include "llnotificationhandler.h"
+#include "lltoastnotifypanel.h"
+#include "llviewercontrol.h"
+#include "llviewerwindow.h"
+#include "llnotificationmanager.h"
+#include "llnotifications.h"
+#include "llscriptfloater.h"
+
+using namespace LLNotificationsUI;
+
+static const std::string SCRIPT_DIALOG ("ScriptDialog");
+static const std::string SCRIPT_DIALOG_GROUP ("ScriptDialogGroup");
+static const std::string SCRIPT_LOAD_URL ("LoadWebPage");
+
+//--------------------------------------------------------------------------
+LLScriptHandler::LLScriptHandler(e_notification_type type, const LLSD& id)
+{
+ mType = type;
+
+ // Getting a Channel for our notifications
+ mChannel = LLChannelManager::getInstance()->createNotificationChannel();
+ mChannel->setControlHovering(true);
+
+ LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
+ if(channel)
+ channel->setOnRejectToastCallback(boost::bind(&LLScriptHandler::onRejectToast, this, _1));
+
+}
+
+//--------------------------------------------------------------------------
+LLScriptHandler::~LLScriptHandler()
+{
+}
+
+//--------------------------------------------------------------------------
+void LLScriptHandler::initChannel()
+{
+ S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin");
+ S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
+ mChannel->init(channel_right_bound - channel_width, channel_right_bound);
+}
+
+//--------------------------------------------------------------------------
+bool LLScriptHandler::processNotification(const LLSD& notify)
+{
+ if(!mChannel)
+ {
+ return false;
+ }
+
+ LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
+
+ if(!notification)
+ return false;
+
+ // arrange a channel on a screen
+ if(!mChannel->getVisible())
+ {
+ initChannel();
+ }
+
+ if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change")
+ {
+ if (LLHandlerUtil::canLogToIM(notification))
+ {
+ LLHandlerUtil::logToIMP2P(notification);
+ }
+
+ if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName())
+ {
+ LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID());
+ }
+ else
+ {
+ LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification);
+
+ LLToast::Params p;
+ p.notif_id = notification->getID();
+ p.notification = notification;
+ p.panel = notify_box;
+ p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1);
+
+ LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
+ if(channel)
+ {
+ channel->addToast(p);
+ }
+
+ // send a signal to the counter manager
+ mNewNotificationSignal();
+ }
+ }
+ else if (notify["sigtype"].asString() == "delete")
+ {
+ if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName())
+ {
+ LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID());
+ }
+ else
+ {
+ mChannel->killToastByNotificationID(notification->getID());
+ }
+ }
+ return true;
+}
+
+//--------------------------------------------------------------------------
+
+void LLScriptHandler::onDeleteToast(LLToast* toast)
+{
+ // send a signal to the counter manager
+ mDelNotificationSignal();
+
+ // send a signal to a listener to let him perform some action
+ // in this case listener is a SysWellWindow and it will remove a corresponding item from its list
+ mNotificationIDSignal(toast->getNotificationID());
+
+ LLNotificationPtr notification = LLNotifications::getInstance()->find(toast->getNotificationID());
+
+ if( notification &&
+ (SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName()) )
+ {
+ LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID());
+ }
+}
+
+//--------------------------------------------------------------------------
+void LLScriptHandler::onRejectToast(LLUUID& id)
+{
+ LLNotificationPtr notification = LLNotifications::instance().find(id);
+
+ if (notification
+ && LLNotificationManager::getInstance()->getHandlerForNotification(
+ notification->getType()) == this)
+ {
+ LLNotifications::instance().cancel(notification);
+ }
+}
+
+//--------------------------------------------------------------------------
+
+
+
+
diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp
new file mode 100644
index 0000000000..83a2215ac6
--- /dev/null
+++ b/indra/newview/llnotificationtiphandler.cpp
@@ -0,0 +1,145 @@
+/**
+ * @file llnotificationtiphandler.cpp
+ * @brief Notification Handler Class for Notification Tips
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#include "llfloaterreg.h"
+#include "llnearbychat.h"
+#include "llnotificationhandler.h"
+#include "llnotifications.h"
+#include "lltoastnotifypanel.h"
+#include "llviewercontrol.h"
+#include "llviewerwindow.h"
+
+using namespace LLNotificationsUI;
+
+
+//--------------------------------------------------------------------------
+LLTipHandler::LLTipHandler(e_notification_type type, const LLSD& id)
+{
+ mType = type;
+
+ // Getting a Channel for our notifications
+ mChannel = LLChannelManager::getInstance()->createNotificationChannel();
+}
+
+//--------------------------------------------------------------------------
+LLTipHandler::~LLTipHandler()
+{
+}
+
+//--------------------------------------------------------------------------
+void LLTipHandler::initChannel()
+{
+ S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin");
+ S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
+ mChannel->init(channel_right_bound - channel_width, channel_right_bound);
+}
+
+//--------------------------------------------------------------------------
+bool LLTipHandler::processNotification(const LLSD& notify)
+{
+ if(!mChannel)
+ {
+ return false;
+ }
+
+ LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
+
+ if(!notification)
+ return false;
+
+ // arrange a channel on a screen
+ if(!mChannel->getVisible())
+ {
+ initChannel();
+ }
+
+ if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change")
+ {
+ // archive message in nearby chat
+ if (LLHandlerUtil::canLogToNearbyChat(notification))
+ {
+ LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM);
+
+ // don't show toast if Nearby Chat is opened
+ LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<
+ LLNearbyChat>("nearby_chat", LLSD());
+ if (nearby_chat->getVisible())
+ {
+ return true;
+ }
+ }
+
+ const std::string name = notification->getSubstitutions()["NAME"];
+ LLUUID from_id = notification->getPayload()["from_id"];
+ if (LLHandlerUtil::canLogToIM(notification))
+ {
+ LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, name, name,
+ notification->getMessage(), from_id, from_id);
+ }
+
+ if (LLHandlerUtil::canSpawnIMSession(notification))
+ {
+ LLHandlerUtil::spawnIMSession(name, from_id);
+ }
+
+ LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification);
+
+ LLToast::Params p;
+ p.notif_id = notification->getID();
+ p.notification = notification;
+ p.lifetime_secs = gSavedSettings.getS32("NotificationTipToastLifeTime");
+ p.panel = notify_box;
+ p.is_tip = true;
+ p.can_be_stored = false;
+
+ LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
+ if(channel)
+ channel->addToast(p);
+ }
+ else if (notify["sigtype"].asString() == "delete")
+ {
+ mChannel->killToastByNotificationID(notification->getID());
+ }
+ return true;
+}
+
+//--------------------------------------------------------------------------
+void LLTipHandler::onDeleteToast(LLToast* toast)
+{
+}
+
+//--------------------------------------------------------------------------
+
+
diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp
new file mode 100644
index 0000000000..f816dc589d
--- /dev/null
+++ b/indra/newview/lloutputmonitorctrl.cpp
@@ -0,0 +1,316 @@
+/**
+ * @file lloutputmonitorctrl.cpp
+ * @brief LLOutputMonitorCtrl base class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "lloutputmonitorctrl.h"
+
+// library includes
+#include "llui.h"
+
+// viewer includes
+#include "llvoiceclient.h"
+#include "llmutelist.h"
+#include "llagent.h"
+
+// default options set in output_monitor.xml
+static LLDefaultChildRegistry::Register<LLOutputMonitorCtrl> r("output_monitor");
+
+// The defaults will be initialized in the constructor.
+//LLColor4 LLOutputMonitorCtrl::sColorMuted;
+//LLColor4 LLOutputMonitorCtrl::sColorOverdriven;
+//LLColor4 LLOutputMonitorCtrl::sColorNormal;
+LLColor4 LLOutputMonitorCtrl::sColorBound;
+//S32 LLOutputMonitorCtrl::sRectsNumber = 0;
+//F32 LLOutputMonitorCtrl::sRectWidthRatio = 0.f;
+//F32 LLOutputMonitorCtrl::sRectHeightRatio = 0.f;
+
+LLOutputMonitorCtrl::Params::Params()
+: draw_border("draw_border"),
+ image_mute("image_mute"),
+ image_off("image_off"),
+ image_on("image_on"),
+ image_level_1("image_level_1"),
+ image_level_2("image_level_2"),
+ image_level_3("image_level_3"),
+ auto_update("auto_update"),
+ speaker_id("speaker_id")
+{
+};
+
+LLOutputMonitorCtrl::LLOutputMonitorCtrl(const LLOutputMonitorCtrl::Params& p)
+: LLView(p),
+ mPower(0),
+ mImageMute(p.image_mute),
+ mImageOff(p.image_off),
+ mImageOn(p.image_on),
+ mImageLevel1(p.image_level_1),
+ mImageLevel2(p.image_level_2),
+ mImageLevel3(p.image_level_3),
+ mAutoUpdate(p.auto_update),
+ mSpeakerId(p.speaker_id),
+ mIsAgentControl(false),
+ mIsSwitchDirty(false),
+ mShouldSwitchOn(false)
+{
+ //static LLUIColor output_monitor_muted_color = LLUIColorTable::instance().getColor("OutputMonitorMutedColor", LLColor4::orange);
+ //static LLUIColor output_monitor_overdriven_color = LLUIColorTable::instance().getColor("OutputMonitorOverdrivenColor", LLColor4::red);
+ //static LLUIColor output_monitor_normal_color = LLUIColorTable::instance().getColor("OutputMonitorNotmalColor", LLColor4::green);
+ static LLUIColor output_monitor_bound_color = LLUIColorTable::instance().getColor("OutputMonitorBoundColor", LLColor4::white);
+ //static LLUICachedControl<S32> output_monitor_rects_number("OutputMonitorRectanglesNumber", 20);
+ //static LLUICachedControl<F32> output_monitor_rect_width_ratio("OutputMonitorRectangleWidthRatio", 0.5f);
+ //static LLUICachedControl<F32> output_monitor_rect_height_ratio("OutputMonitorRectangleHeightRatio", 0.8f);
+
+ // IAN BUG compare to existing pattern where these are members - some will change per-widget and need to be anyway
+ // sent feedback to PE
+
+ // *TODO: it looks suboptimal to load the defaults every time an output monitor is constructed.
+ //sColorMuted = output_monitor_muted_color;
+ //sColorOverdriven = output_monitor_overdriven_color;
+ //sColorNormal = output_monitor_normal_color;
+ sColorBound = output_monitor_bound_color;
+ //sRectsNumber = output_monitor_rects_number;
+ //sRectWidthRatio = output_monitor_rect_width_ratio;
+ //sRectHeightRatio = output_monitor_rect_height_ratio;
+
+ mBorder = p.draw_border;
+
+ //with checking mute state
+ setSpeakerId(mSpeakerId);
+}
+
+LLOutputMonitorCtrl::~LLOutputMonitorCtrl()
+{
+ LLMuteList::getInstance()->removeObserver(this);
+ LLSpeakingIndicatorManager::unregisterSpeakingIndicator(mSpeakerId, this);
+}
+
+void LLOutputMonitorCtrl::setPower(F32 val)
+{
+ mPower = llmax(0.f, llmin(1.f, val));
+}
+
+void LLOutputMonitorCtrl::draw()
+{
+ // see also switchIndicator()
+ if (mIsSwitchDirty)
+ {
+ mIsSwitchDirty = false;
+ if (mShouldSwitchOn)
+ {
+ // just notify parent visibility may have changed
+ notifyParentVisibilityChanged();
+ }
+ else
+ {
+ // make itself invisible and notify parent about this
+ setVisible(FALSE);
+ notifyParentVisibilityChanged();
+
+ // no needs to render for invisible element
+ return;
+ }
+ }
+
+ // Copied from llmediaremotectrl.cpp
+ // *TODO: Give the LLOutputMonitorCtrl an agent-id to monitor, then
+ // call directly into gVoiceClient to ask if that agent-id is muted, is
+ // speaking, and what power. This avoids duplicating data, which can get
+ // out of sync.
+ const F32 LEVEL_0 = LLVoiceClient::OVERDRIVEN_POWER_LEVEL / 3.f;
+ const F32 LEVEL_1 = LLVoiceClient::OVERDRIVEN_POWER_LEVEL * 2.f / 3.f;
+ const F32 LEVEL_2 = LLVoiceClient::OVERDRIVEN_POWER_LEVEL;
+
+ if (getVisible() && mAutoUpdate && !mIsMuted && mSpeakerId.notNull())
+ {
+ setPower(gVoiceClient->getCurrentPower(mSpeakerId));
+ if(mIsAgentControl)
+ {
+ setIsTalking(gVoiceClient->getUserPTTState());
+ }
+ else
+ {
+ setIsTalking(gVoiceClient->getIsSpeaking(mSpeakerId));
+ }
+ }
+
+ LLPointer<LLUIImage> icon;
+ if (mIsMuted)
+ {
+ icon = mImageMute;
+ }
+ else if (mPower == 0.f && !mIsTalking)
+ {
+ // only show off if PTT is not engaged
+ icon = mImageOff;
+ }
+ else if (mPower < LEVEL_0)
+ {
+ // PTT is on, possibly with quiet background noise
+ icon = mImageOn;
+ }
+ else if (mPower < LEVEL_1)
+ {
+ icon = mImageLevel1;
+ }
+ else if (mPower < LEVEL_2)
+ {
+ icon = mImageLevel2;
+ }
+ else
+ {
+ // overdriven
+ icon = mImageLevel3;
+ }
+
+ if (icon)
+ {
+ icon->draw(0, 0);
+ }
+
+ //
+ // Fill the monitor with a bunch of small rectangles.
+ // The rectangles will be filled with gradient color,
+ // beginning with sColorNormal and ending with sColorOverdriven.
+ //
+ // *TODO: would using a (partially drawn) pixmap instead be faster?
+ //
+ const int monh = getRect().getHeight();
+ const int monw = getRect().getWidth();
+ //int maxrects = sRectsNumber;
+ //const int period = llmax(1, monw / maxrects, 0, 0); // "1" - min value for the period
+ //const int rectw = llmax(1, llfloor(period * sRectWidthRatio), 0, 0); // "1" - min value for the rect's width
+ //const int recth = llfloor(monh * sRectHeightRatio);
+
+ //if(period == 1 && rectw == 1) //if we have so small control, then "maxrects = monitor's_width - 2*monitor_border's_width
+ // maxrects = monw-2;
+
+ //const int nrects = mIsMuted ? maxrects : llfloor(mPower * maxrects); // how many rects to draw?
+ //const int rectbtm = (monh - recth) / 2;
+ //const int recttop = rectbtm + recth;
+ //
+ //LLColor4 rect_color;
+ //
+ //for (int i=1, xpos = 0; i <= nrects; i++)
+ //{
+ // // Calculate color to use for the current rectangle.
+ // if (mIsMuted)
+ // {
+ // rect_color = sColorMuted;
+ // }
+ // else
+ // {
+ // F32 frac = (mPower * i/nrects) / LLVoiceClient::OVERDRIVEN_POWER_LEVEL;
+ // // Use overdriven color if the power exceeds overdriven level.
+ // if (frac > 1.0f)
+ // frac = 1.0f;
+ // rect_color = lerp(sColorNormal, sColorOverdriven, frac);
+ // }
+
+ // // Draw rectangle filled with the color.
+ // gl_rect_2d(xpos, recttop, xpos+rectw, rectbtm, rect_color, TRUE);
+ // xpos += period;
+ //}
+
+ //
+ // Draw bounding box.
+ //
+ if(mBorder)
+ gl_rect_2d(0, monh, monw, 0, sColorBound, FALSE);
+}
+
+void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id)
+{
+ if (speaker_id.isNull() || speaker_id == mSpeakerId) return;
+
+ mSpeakerId = speaker_id;
+ LLSpeakingIndicatorManager::registerSpeakingIndicator(mSpeakerId, this);
+
+ //mute management
+ if (mAutoUpdate)
+ {
+ if (speaker_id == gAgentID)
+ {
+ setIsMuted(false);
+ }
+ else
+ {
+ // check only blocking on voice. EXT-3542
+ setIsMuted(LLMuteList::getInstance()->isMuted(mSpeakerId, LLMute::flagVoiceChat));
+ LLMuteList::getInstance()->addObserver(this);
+ }
+ }
+}
+
+void LLOutputMonitorCtrl::onChange()
+{
+ // check only blocking on voice. EXT-3542
+ setIsMuted(LLMuteList::getInstance()->isMuted(mSpeakerId, LLMute::flagVoiceChat));
+}
+
+// virtual
+void LLOutputMonitorCtrl::switchIndicator(bool switch_on)
+{
+ // ensure indicator is visible in case it is not in visible chain
+ // to be called when parent became visible next time to notify parent that visibility is changed.
+ setVisible(TRUE);
+
+ // if parent is in visible chain apply switch_on state and notify it immediately
+ if (getParent() && getParent()->isInVisibleChain())
+ {
+ LL_DEBUGS("SpeakingIndicator") << "Indicator is in visible chain, notifying parent: " << mSpeakerId << LL_ENDL;
+ setVisible((BOOL)switch_on);
+ notifyParentVisibilityChanged();
+ }
+
+ // otherwise remember necessary state and mark itself as dirty.
+ // State will be applied i next draw when parents chain became visible.
+ else
+ {
+ LL_DEBUGS("SpeakingIndicator") << "Indicator is not in visible chain, parent won't be notified: " << mSpeakerId << LL_ENDL;
+ mIsSwitchDirty = true;
+ mShouldSwitchOn = switch_on;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// PRIVATE SECTION
+//////////////////////////////////////////////////////////////////////////
+void LLOutputMonitorCtrl::notifyParentVisibilityChanged()
+{
+ LL_DEBUGS("SpeakingIndicator") << "Notify parent that visibility was changed: " << mSpeakerId << " ,new_visibility: " << getVisible() << LL_ENDL;
+
+ LLSD params = LLSD().with("visibility_changed", getVisible());
+
+ notifyParent(params);
+}
+
+// EOF
diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h
new file mode 100644
index 0000000000..2bbfa251e9
--- /dev/null
+++ b/indra/newview/lloutputmonitorctrl.h
@@ -0,0 +1,149 @@
+/**
+ * @file lloutputmonitorctrl.h
+ * @brief LLOutputMonitorCtrl base class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLOUTPUTMONITORCTRL_H
+#define LL_LLOUTPUTMONITORCTRL_H
+
+#include "v4color.h"
+#include "llview.h"
+#include "llmutelist.h"
+#include "llspeakingindicatormanager.h"
+
+class LLTextBox;
+class LLUICtrlFactory;
+
+//
+// Classes
+//
+
+class LLOutputMonitorCtrl
+: public LLView, public LLSpeakingIndicator, LLMuteListObserver
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
+ {
+ Optional<bool> draw_border;
+ Mandatory<LLUIImage*> image_mute,
+ image_off,
+ image_on,
+ image_level_1,
+ image_level_2,
+ image_level_3;
+ Optional<bool> auto_update;
+ Optional<LLUUID> speaker_id;
+
+ Params();
+ };
+protected:
+ bool mBorder;
+ LLOutputMonitorCtrl(const Params&);
+ friend class LLUICtrlFactory;
+
+public:
+ virtual ~LLOutputMonitorCtrl();
+
+ // llview overrides
+ virtual void draw();
+
+ void setPower(F32 val);
+ F32 getPower(F32 val) const { return mPower; }
+
+ bool getIsMuted() const { return mIsMuted; }
+ void setIsMuted(bool val) { mIsMuted = val; }
+
+ // For the current user, need to know the PTT state to show
+ // correct button image.
+ void setIsAgentControl(bool val) { mIsAgentControl = val; }
+
+ void setIsTalking(bool val) { mIsTalking = val; }
+
+ void setSpeakerId(const LLUUID& speaker_id);
+
+ //called by mute list
+ virtual void onChange();
+
+ /**
+ * Implementation of LLSpeakingIndicator interface.
+ * Behavior is implemented via changing visibility.
+ *
+ * If instance is in visible chain now (all parents are visible) it changes visibility
+ * and notify parent about this.
+ *
+ * Otherwise it marks an instance as dirty and stores necessary visibility.
+ * It will be applied in next draw and parent will be notified.
+ */
+ virtual void switchIndicator(bool switch_on);
+
+private:
+
+ /**
+ * Notifies parent about changed visibility.
+ *
+ * Passes LLSD with "visibility_changed" => <current visibility> value.
+ * For now it is processed by LLAvatarListItem to update (reshape) its children.
+ * Implemented fo complete EXT-3976
+ */
+ void notifyParentVisibilityChanged();
+
+ //static LLColor4 sColorMuted;
+ //static LLColor4 sColorNormal;
+ //static LLColor4 sColorOverdriven;
+ static LLColor4 sColorBound;
+ //static S32 sRectsNumber;
+ //static F32 sRectWidthRatio;
+ //static F32 sRectHeightRatio;
+
+
+
+ F32 mPower;
+ bool mIsAgentControl;
+ bool mIsMuted;
+ bool mIsTalking;
+ LLPointer<LLUIImage> mImageMute;
+ LLPointer<LLUIImage> mImageOff;
+ LLPointer<LLUIImage> mImageOn;
+ LLPointer<LLUIImage> mImageLevel1;
+ LLPointer<LLUIImage> mImageLevel2;
+ LLPointer<LLUIImage> mImageLevel3;
+
+ /** whether to deal with gVoiceClient directly */
+ bool mAutoUpdate;
+
+ /** uuid of a speaker being monitored */
+ LLUUID mSpeakerId;
+
+ /** indicates if the instance is dirty and should notify parent */
+ bool mIsSwitchDirty;
+ bool mShouldSwitchOn;
+};
+
+#endif
diff --git a/indra/newview/lloverlaybar.cpp b/indra/newview/lloverlaybar.cpp
index b16f56d0d8..67e048885f 100644
--- a/indra/newview/lloverlaybar.cpp
+++ b/indra/newview/lloverlaybar.cpp
@@ -37,20 +37,18 @@
#include "lloverlaybar.h"
-#include "audioengine.h"
+#include "llaudioengine.h"
#include "llrender.h"
#include "llagent.h"
#include "llbutton.h"
-#include "llchatbar.h"
#include "llfocusmgr.h"
#include "llimview.h"
#include "llmediaremotectrl.h"
-#include "llpanelaudiovolume.h"
#include "llparcel.h"
#include "lltextbox.h"
#include "llui.h"
#include "llviewercontrol.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewerjoystick.h"
#include "llviewermedia.h"
#include "llviewermenu.h" // handle_reset_view()
@@ -60,9 +58,9 @@
#include "lluictrlfactory.h"
#include "llviewerwindow.h"
#include "llvoiceclient.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "llvoiceremotectrl.h"
-#include "llwebbrowserctrl.h"
+#include "llmediactrl.h"
#include "llselectmgr.h"
//
@@ -89,16 +87,10 @@ void* LLOverlayBar::createMediaRemote(void* userdata)
void* LLOverlayBar::createVoiceRemote(void* userdata)
{
LLOverlayBar *self = (LLOverlayBar*)userdata;
- self->mVoiceRemote = new LLVoiceRemoteCtrl(std::string("voice_remote"));
+ self->mVoiceRemote = new LLVoiceRemoteCtrl();
return self->mVoiceRemote;
}
-void* LLOverlayBar::createChatBar(void* userdata)
-{
- gChatBar = new LLChatBar();
- return gChatBar;
-}
-
LLOverlayBar::LLOverlayBar()
: LLPanel(),
mMediaRemote(NULL),
@@ -110,23 +102,23 @@ LLOverlayBar::LLOverlayBar()
mBuilt = false;
- LLCallbackMap::map_t factory_map;
- factory_map["media_remote"] = LLCallbackMap(LLOverlayBar::createMediaRemote, this);
- factory_map["voice_remote"] = LLCallbackMap(LLOverlayBar::createVoiceRemote, this);
- factory_map["chat_bar"] = LLCallbackMap(LLOverlayBar::createChatBar, this);
+ mFactoryMap["media_remote"] = LLCallbackMap(LLOverlayBar::createMediaRemote, this);
+ mFactoryMap["voice_remote"] = LLCallbackMap(LLOverlayBar::createVoiceRemote, this);
- LLUICtrlFactory::getInstance()->buildPanel(this, "panel_overlaybar.xml", &factory_map);
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_overlaybar.xml");
}
BOOL LLOverlayBar::postBuild()
{
- childSetAction("IM Received",onClickIMReceived,this);
childSetAction("Set Not Busy",onClickSetNotBusy,this);
childSetAction("Mouselook",onClickMouselook,this);
childSetAction("Stand Up",onClickStandUp,this);
childSetAction("Flycam",onClickFlycam,this);
childSetVisible("chat_bar", gSavedSettings.getBOOL("ChatVisible"));
+ mVoiceRemote->expandOrCollapse();
+ mMediaRemote->expandOrCollapse();
+
setFocusRoot(TRUE);
mBuilt = true;
@@ -168,8 +160,9 @@ void LLOverlayBar::layoutButtons()
// calculate button widths
const S32 MAX_BUTTON_WIDTH = 150;
+ const S32 STATUS_BAR_PAD = 10;
S32 segment_width = llclamp(lltrunc((F32)(bar_width) / (F32)button_list.size()), 0, MAX_BUTTON_WIDTH);
- S32 btn_width = segment_width - gSavedSettings.getS32("StatusBarPad");
+ S32 btn_width = segment_width - STATUS_BAR_PAD;
// Evenly space all buttons, starting from left
S32 left = 0;
@@ -238,7 +231,7 @@ void LLOverlayBar::refresh()
BOOL sitting = FALSE;
if (gAgent.getAvatarObject())
{
- sitting = gAgent.getAvatarObject()->mIsSitting;
+ sitting = gAgent.getAvatarObject()->isSitting();
}
button = getChild<LLButton>("Stand Up");
@@ -283,13 +276,6 @@ void LLOverlayBar::refresh()
//-----------------------------------------------------------------------
// static
-void LLOverlayBar::onClickIMReceived(void*)
-{
- gIMMgr->setFloaterOpen(TRUE);
-}
-
-
-// static
void LLOverlayBar::onClickSetNotBusy(void*)
{
gAgent.clearBusy();
@@ -329,7 +315,7 @@ void LLOverlayBar::mediaStop(void*)
{
if (!gOverlayBar)
{
- return;
+ // return;
}
LLViewerParcelMedia::stop();
}
@@ -338,15 +324,15 @@ void LLOverlayBar::toggleMediaPlay(void*)
{
if (!gOverlayBar)
{
- return;
+ // return;
}
- if (LLViewerMedia::isMediaPaused())
+ if (LLViewerParcelMedia::getStatus() == LLViewerMediaImpl::MEDIA_PAUSED)
{
LLViewerParcelMedia::start();
}
- else if(LLViewerMedia::isMediaPlaying())
+ else if(LLViewerParcelMedia::getStatus() == LLViewerMediaImpl::MEDIA_PLAYING)
{
LLViewerParcelMedia::pause();
}
@@ -363,14 +349,8 @@ void LLOverlayBar::toggleMediaPlay(void*)
//static
void LLOverlayBar::toggleMusicPlay(void*)
{
- if (!gOverlayBar)
- {
- return;
- }
-
- if (gOverlayBar->mMusicState != PLAYING)
+ if (gAudiop->isInternetStreamPlaying() != 1)
{
- gOverlayBar->mMusicState = PLAYING; // desired state
if (gAudiop)
{
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
@@ -395,7 +375,6 @@ void LLOverlayBar::toggleMusicPlay(void*)
//}
else
{
- gOverlayBar->mMusicState = STOPPED; // desired state
if (gAudiop)
{
gAudiop->stopInternetStream();
diff --git a/indra/newview/lloverlaybar.h b/indra/newview/lloverlaybar.h
index 852d033a10..ffdbd96f60 100644
--- a/indra/newview/lloverlaybar.h
+++ b/indra/newview/lloverlaybar.h
@@ -67,7 +67,6 @@ public:
// helpers for returning desired state
BOOL musicPlaying() { return mMusicState == PLAYING; }
- static void onClickIMReceived(void* data);
static void onClickSetNotBusy(void* data);
static void onClickMouselook(void* data);
static void onClickStandUp(void* data);
@@ -86,7 +85,6 @@ public:
protected:
static void* createMediaRemote(void* userdata);
static void* createVoiceRemote(void* userdata);
- static void* createChatBar(void* userdata);
void enableMediaButtons();
diff --git a/indra/newview/llpanelappearancetab.h b/indra/newview/llpanelappearancetab.h
new file mode 100644
index 0000000000..c2f8dbd074
--- /dev/null
+++ b/indra/newview/llpanelappearancetab.h
@@ -0,0 +1,61 @@
+/**
+ * @file llpanelplacestab.h
+ * @brief Tabs interface for Side Bar "Places" panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELAPPEARANCETAB_H
+#define LL_LLPANELAPPEARANCETAB_H
+
+#include "llpanel.h"
+
+#include "llpanelappearance.h"
+
+class LLPanelAppearanceTab : public LLPanel
+{
+public:
+ LLPanelAppearanceTab(LLPanelAppearance *parent) :
+ LLPanel(),
+ mParent(parent)
+ {}
+ virtual ~LLPanelAppearanceTab() {}
+
+ virtual void onSearchEdit(const std::string& string) = 0;
+ virtual void updateVerbs() = 0; // Updates buttons at the bottom of Appearance panel
+ virtual void onWear() = 0;
+ virtual void onEdit() = 0;
+ virtual void onNew() = 0;
+
+ bool isTabVisible(); // Check if parent TabContainer is visible.
+
+
+protected:
+ LLPanelAppearance* mParent;
+};
+
+#endif //LL_LLPANELAPPEARANCETAB_H
diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp
index 9d5a4ad01c..fe5b20813a 100644
--- a/indra/newview/llpanelavatar.cpp
+++ b/indra/newview/llpanelavatar.cpp
@@ -31,61 +31,28 @@
*/
#include "llviewerprecompiledheaders.h"
-
#include "llpanelavatar.h"
-#include "llclassifiedflags.h"
-#include "llfontgl.h"
-#include "llcachename.h"
-
-#include "llavatarconstants.h"
-#include "lluiconstants.h"
-#include "lltextbox.h"
-#include "llviewertexteditor.h"
-#include "lltexturectrl.h"
#include "llagent.h"
-#include "llviewerwindow.h"
-#include "llbutton.h"
+#include "llavataractions.h"
+#include "llavatarconstants.h" // AVATAR_ONLINE
#include "llcallingcard.h"
-#include "llcheckboxctrl.h"
-#include "llfloater.h"
-
-#include "llfloaterfriends.h"
-#include "llfloatergroupinfo.h"
-#include "llfloaterworldmap.h"
-#include "llfloatermute.h"
-#include "llfloateravatarinfo.h"
-#include "lliconctrl.h"
-#include "llinventoryview.h"
-#include "lllineeditor.h"
-#include "llnameeditor.h"
-#include "llmutelist.h"
-#include "llpanelclassified.h"
-#include "llpanelpick.h"
-#include "llscrolllistctrl.h"
-#include "llstatusbar.h"
-#include "lltabcontainer.h"
-#include "lltabcontainervertical.h"
+#include "llcombobox.h"
+#include "lldateutil.h" // ageFromDate()
#include "llimview.h"
+#include "llnotificationsutil.h"
+#include "lltexteditor.h"
+#include "lltexturectrl.h"
+#include "lltoggleablemenu.h"
#include "lltooldraganddrop.h"
-#include "lluiconstants.h"
-#include "llvoavatar.h"
-#include "llviewercontrol.h"
-#include "llviewermenu.h" // *FIX: for is_agent_friend()
-#include "llviewergenericmessage.h" // send_generic_message
-#include "llviewerobjectlist.h"
-#include "llviewerregion.h"
+#include "llscrollcontainer.h"
+#include "llavatariconctrl.h"
#include "llweb.h"
-#include "llinventorymodel.h"
-#include "roles_constants.h"
-#include "lluictrlfactory.h"
-
-// Statics
-std::list<LLPanelAvatar*> LLPanelAvatar::sAllPanels;
-BOOL LLPanelAvatar::sAllowFirstLife = FALSE;
-
-extern void handle_lure(const LLUUID& invitee);
-extern void handle_pay_by_id(const LLUUID& payee);
+#include "llfloaterworldmap.h"
+#include "llfloaterreg.h"
+#include "llnotificationsutil.h"
+#include "llvoiceclient.h"
+#include "llnamebox.h"
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLDropTarget
@@ -98,7 +65,18 @@ extern void handle_pay_by_id(const LLUUID& payee);
class LLDropTarget : public LLView
{
public:
- LLDropTarget(const std::string& name, const LLRect& rect, const LLUUID& agent_id);
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
+ {
+ Optional<LLUUID> agent_id;
+ Params()
+ : agent_id("agent_id")
+ {
+ mouse_opaque(false);
+ follows.flags(FOLLOWS_ALL);
+ }
+ };
+
+ LLDropTarget(const Params&);
~LLDropTarget();
void doDrop(EDragAndDropType cargo_type, void* cargo_data);
@@ -115,17 +93,13 @@ protected:
LLUUID mAgentID;
};
-
-LLDropTarget::LLDropTarget(const std::string& name, const LLRect& rect,
- const LLUUID& agent_id) :
- LLView(name, rect, NOT_MOUSE_OPAQUE, FOLLOWS_ALL),
- mAgentID(agent_id)
-{
-}
+LLDropTarget::LLDropTarget(const LLDropTarget::Params& p)
+: LLView(p),
+ mAgentID(p.agent_id)
+{}
LLDropTarget::~LLDropTarget()
-{
-}
+{}
void LLDropTarget::doDrop(EDragAndDropType cargo_type, void* cargo_data)
{
@@ -149,2156 +123,766 @@ BOOL LLDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
return FALSE;
}
+static LLDefaultChildRegistry::Register<LLDropTarget> r("drop_target");
+
+static LLRegisterPanelClassWrapper<LLPanelAvatarProfile> t_panel_profile("panel_profile");
+static LLRegisterPanelClassWrapper<LLPanelMyProfile> t_panel_my_profile("panel_my_profile");
+static LLRegisterPanelClassWrapper<LLPanelAvatarNotes> t_panel_notes("panel_notes");
//-----------------------------------------------------------------------------
-// LLPanelAvatarTab()
+// LLPanelAvatarNotes()
//-----------------------------------------------------------------------------
-LLPanelAvatarTab::LLPanelAvatarTab(const std::string& name, const LLRect &rect,
- LLPanelAvatar* panel_avatar)
-: LLPanel(name, rect),
- mPanelAvatar(panel_avatar),
- mDataRequested(false)
-{ }
-
-// virtual
-void LLPanelAvatarTab::draw()
+LLPanelAvatarNotes::LLPanelAvatarNotes()
+: LLPanelProfileTab()
{
- refresh();
- LLPanel::draw();
}
-void LLPanelAvatarTab::sendAvatarProfileRequestIfNeeded(const std::string& method)
+void LLPanelAvatarNotes::updateData()
{
- if (!mDataRequested)
- {
- std::vector<std::string> strings;
- strings.push_back( mPanelAvatar->getAvatarID().asString() );
- send_generic_message(method, strings);
- mDataRequested = true;
- }
+ LLAvatarPropertiesProcessor::getInstance()->
+ sendAvatarNotesRequest(getAvatarId());
}
-//-----------------------------------------------------------------------------
-// LLPanelAvatarSecondLife()
-//-----------------------------------------------------------------------------
-LLPanelAvatarSecondLife::LLPanelAvatarSecondLife(const std::string& name,
- const LLRect &rect,
- LLPanelAvatar* panel_avatar )
-: LLPanelAvatarTab(name, rect, panel_avatar),
- mPartnerID()
+BOOL LLPanelAvatarNotes::postBuild()
{
-}
+ childSetCommitCallback("status_check", boost::bind(&LLPanelAvatarNotes::onCommitRights, this), NULL);
+ childSetCommitCallback("map_check", boost::bind(&LLPanelAvatarNotes::onCommitRights, this), NULL);
+ childSetCommitCallback("objects_check", boost::bind(&LLPanelAvatarNotes::onCommitRights, this), NULL);
-void LLPanelAvatarSecondLife::refresh()
-{
- updatePartnerName();
-}
+ childSetCommitCallback("add_friend", boost::bind(&LLPanelAvatarNotes::onAddFriendButtonClick, this),NULL);
+ childSetCommitCallback("im", boost::bind(&LLPanelAvatarNotes::onIMButtonClick, this), NULL);
+ childSetCommitCallback("call", boost::bind(&LLPanelAvatarNotes::onCallButtonClick, this), NULL);
+ childSetCommitCallback("teleport", boost::bind(&LLPanelAvatarNotes::onTeleportButtonClick, this), NULL);
+ childSetCommitCallback("share", boost::bind(&LLPanelAvatarNotes::onShareButtonClick, this), NULL);
+ childSetCommitCallback("show_on_map_btn", (boost::bind(
+ &LLPanelAvatarNotes::onMapButtonClick, this)), NULL);
-void LLPanelAvatarSecondLife::updatePartnerName()
-{
- if (mPartnerID.notNull())
- {
- std::string first, last;
- BOOL found = gCacheName->getName(mPartnerID, first, last);
- if (found)
- {
- childSetTextArg("partner_edit", "[FIRST]", first);
- childSetTextArg("partner_edit", "[LAST]", last);
- }
- childSetEnabled("partner_info", TRUE);
- }
-}
+ LLTextEditor* te = getChild<LLTextEditor>("notes_edit");
+ te->setCommitCallback(boost::bind(&LLPanelAvatarNotes::onCommitNotes,this));
+ te->setCommitOnFocusLost(TRUE);
-//-----------------------------------------------------------------------------
-// clearControls()
-// Empty the data out of the controls, since we have to wait for new
-// data off the network.
-//-----------------------------------------------------------------------------
-void LLPanelAvatarSecondLife::clearControls()
-{
- LLTextureCtrl* image_ctrl = getChild<LLTextureCtrl>("img");
- if(image_ctrl)
- {
- image_ctrl->setImageAssetID(LLUUID::null);
- }
- childSetValue("about", "");
- childSetValue("born", "");
- childSetValue("acct", "");
+ resetControls();
+ resetData();
- childSetTextArg("partner_edit", "[FIRST]", LLStringUtil::null);
- childSetTextArg("partner_edit", "[LAST]", LLStringUtil::null);
-
- mPartnerID = LLUUID::null;
-
- LLScrollListCtrl* group_list = getChild<LLScrollListCtrl>("groups");
- if(group_list)
- {
- group_list->deleteAllItems();
- }
- LLScrollListCtrl* ratings_list = getChild<LLScrollListCtrl>("ratings");
- if(ratings_list)
- {
- ratings_list->deleteAllItems();
- }
+ gVoiceClient->addObserver((LLVoiceClientStatusObserver*)this);
+ return TRUE;
}
-
-//-----------------------------------------------------------------------------
-// enableControls()
-//-----------------------------------------------------------------------------
-void LLPanelAvatarSecondLife::enableControls(BOOL self)
+void LLPanelAvatarNotes::onOpen(const LLSD& key)
{
- childSetEnabled("img", self);
- childSetEnabled("about", self);
- childSetVisible("allow_publish", self);
- childSetEnabled("allow_publish", self);
- childSetVisible("?", self);
- childSetEnabled("?", self);
-}
+ LLPanelProfileTab::onOpen(key);
+ fillRightsData();
-// static
-void LLPanelAvatarSecondLife::onClickImage(void *)
-{ }
+ //Disable "Add Friend" button for friends.
+ childSetEnabled("add_friend", !LLAvatarActions::isFriend(getAvatarId()));
+}
-// static
-void LLPanelAvatarSecondLife::onDoubleClickGroup(void* data)
+void LLPanelAvatarNotes::fillRightsData()
{
- LLPanelAvatarSecondLife* self = (LLPanelAvatarSecondLife*)data;
+ childSetValue("status_check", FALSE);
+ childSetValue("map_check", FALSE);
+ childSetValue("objects_check", FALSE);
-
- LLScrollListCtrl* group_list = self->getChild<LLScrollListCtrl>("groups");
- if(group_list)
+ const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(getAvatarId());
+ // If true - we are viewing friend's profile, enable check boxes and set values.
+ if(relation)
{
- LLScrollListItem* item = group_list->getFirstSelected();
-
- if(item && item->getUUID().notNull())
- {
- llinfos << "Show group info " << item->getUUID() << llendl;
+ S32 rights = relation->getRightsGrantedTo();
- LLFloaterGroupInfo::showFromUUID(item->getUUID());
- }
- }
-}
+ childSetValue("status_check",LLRelationship::GRANT_ONLINE_STATUS & rights ? TRUE : FALSE);
+ childSetValue("map_check",LLRelationship::GRANT_MAP_LOCATION & rights ? TRUE : FALSE);
+ childSetValue("objects_check",LLRelationship::GRANT_MODIFY_OBJECTS & rights ? TRUE : FALSE);
-// static
-void LLPanelAvatarSecondLife::onClickPublishHelp(void *)
-{
- LLNotifications::instance().add("ClickPublishHelpAvatar");
+ childSetEnabled("status_check",TRUE);
+ childSetEnabled("map_check",TRUE);
+ childSetEnabled("objects_check",TRUE);
+ }
}
-// static
-void LLPanelAvatarSecondLife::onClickPartnerHelp(void *)
+void LLPanelAvatarNotes::onCommitNotes()
{
- LLNotifications::instance().add("ClickPartnerHelpAvatar", LLSD(), LLSD(), onClickPartnerHelpLoadURL);
+ std::string notes = childGetValue("notes_edit").asString();
+ LLAvatarPropertiesProcessor::getInstance()-> sendNotes(getAvatarId(),notes);
}
-// static
-bool LLPanelAvatarSecondLife::onClickPartnerHelpLoadURL(const LLSD& notification, const LLSD& response)
+void LLPanelAvatarNotes::rightsConfirmationCallback(const LLSD& notification,
+ const LLSD& response, S32 rights)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0)
{
- LLWeb::loadURL("http://secondlife.com/partner");
+ LLAvatarPropertiesProcessor::getInstance()->sendFriendRights(
+ getAvatarId(), rights);
}
- return false;
-}
-
-// static
-void LLPanelAvatarSecondLife::onClickPartnerInfo(void *data)
-{
- LLPanelAvatarSecondLife* self = (LLPanelAvatarSecondLife*) data;
- if (self->mPartnerID.notNull())
+ else
{
- LLFloaterAvatarInfo::showFromProfile(self->mPartnerID,
- self->getScreenRect());
+ childSetValue("objects_check",
+ childGetValue("objects_check").asBoolean() ? FALSE : TRUE);
}
}
-//-----------------------------------------------------------------------------
-// LLPanelAvatarFirstLife()
-//-----------------------------------------------------------------------------
-LLPanelAvatarFirstLife::LLPanelAvatarFirstLife(const std::string& name,
- const LLRect &rect,
- LLPanelAvatar* panel_avatar )
-: LLPanelAvatarTab(name, rect, panel_avatar)
-{
-}
-
-void LLPanelAvatarFirstLife::enableControls(BOOL self)
-{
- childSetEnabled("img", self);
- childSetEnabled("about", self);
-}
-
-//-----------------------------------------------------------------------------
-// postBuild
-//-----------------------------------------------------------------------------
-
-BOOL LLPanelAvatarSecondLife::postBuild(void)
-{
- childSetEnabled("born", FALSE);
- childSetEnabled("partner_edit", FALSE);
- childSetAction("partner_help",onClickPartnerHelp,this);
- childSetAction("partner_info", onClickPartnerInfo, this);
- childSetEnabled("partner_info", mPartnerID.notNull());
-
- childSetAction("?",onClickPublishHelp,this);
- BOOL own_avatar = (getPanelAvatar()->getAvatarID() == gAgent.getID() );
- enableControls(own_avatar);
-
- childSetVisible("About:",LLPanelAvatar::sAllowFirstLife);
- childSetVisible("(500 chars)",LLPanelAvatar::sAllowFirstLife);
- childSetVisible("about",LLPanelAvatar::sAllowFirstLife);
-
- childSetVisible("allow_publish",LLPanelAvatar::sAllowFirstLife);
- childSetVisible("?",LLPanelAvatar::sAllowFirstLife);
-
- childSetVisible("online_yes",FALSE);
-
- // These are cruft but may still exist in some xml files
- // TODO: remove the following 2 lines once translators grab these changes
- childSetVisible("online_unknown",FALSE);
- childSetVisible("online_no",FALSE);
-
- childSetAction("Find on Map", LLPanelAvatar::onClickTrack, getPanelAvatar());
- childSetAction("Instant Message...", LLPanelAvatar::onClickIM, getPanelAvatar());
-
- childSetAction("Add Friend...", LLPanelAvatar::onClickAddFriend, getPanelAvatar());
- childSetAction("Pay...", LLPanelAvatar::onClickPay, getPanelAvatar());
- childSetAction("Mute", LLPanelAvatar::onClickMute, getPanelAvatar() );
-
- childSetAction("Offer Teleport...", LLPanelAvatar::onClickOfferTeleport,
- getPanelAvatar() );
-
- childSetDoubleClickCallback("groups", onDoubleClickGroup, this );
-
- getChild<LLTextureCtrl>("img")->setFallbackImageName("default_profile_picture.j2c");
-
- return TRUE;
-}
-
-BOOL LLPanelAvatarFirstLife::postBuild(void)
-{
- BOOL own_avatar = (getPanelAvatar()->getAvatarID() == gAgent.getID() );
- enableControls(own_avatar);
-
- getChild<LLTextureCtrl>("img")->setFallbackImageName("default_profile_picture.j2c");
-
- return TRUE;
-}
-
-BOOL LLPanelAvatarNotes::postBuild(void)
-{
- childSetCommitCallback("notes edit",onCommitNotes,this);
-
- LLTextEditor* te = getChild<LLTextEditor>("notes edit");
- if(te) te->setCommitOnFocusLost(TRUE);
- return TRUE;
-}
-
-BOOL LLPanelAvatarWeb::postBuild(void)
+void LLPanelAvatarNotes::confirmModifyRights(bool grant, S32 rights)
{
- childSetKeystrokeCallback("url_edit", onURLKeystroke, this);
- childSetCommitCallback("load", onCommitLoad, this);
-
- childSetAction("web_profile_help",onClickWebProfileHelp,this);
-
- childSetCommitCallback("url_edit",onCommitURL,this);
-
- childSetControlName("auto_load","AutoLoadWebProfiles");
-
- mWebBrowser = getChild<LLWebBrowserCtrl>("profile_html");
-
- // links open in internally
- mWebBrowser->setOpenInExternalBrowser( false );
-
- // observe browser events
- mWebBrowser->addObserver( this );
-
- return TRUE;
-}
-
-BOOL LLPanelAvatarClassified::postBuild(void)
-{
- childSetAction("New...",onClickNew,NULL);
- childSetAction("Delete...",onClickDelete,NULL);
- return TRUE;
-}
-
-BOOL LLPanelAvatarPicks::postBuild(void)
-{
- childSetAction("New...",onClickNew,NULL);
- childSetAction("Delete...",onClickDelete,NULL);
- return TRUE;
-}
-
-BOOL LLPanelAvatarAdvanced::postBuild()
-{
- for(size_t ii = 0; ii < LL_ARRAY_SIZE(mWantToCheck); ++ii)
- mWantToCheck[ii] = NULL;
- for(size_t ii = 0; ii < LL_ARRAY_SIZE(mSkillsCheck); ++ii)
- mSkillsCheck[ii] = NULL;
- mWantToCount = (8>LL_ARRAY_SIZE(mWantToCheck))?LL_ARRAY_SIZE(mWantToCheck):8;
- for(S32 tt=0; tt < mWantToCount; ++tt)
- {
- std::string ctlname = llformat("chk%d", tt);
- mWantToCheck[tt] = getChild<LLCheckBoxCtrl>(ctlname);
- }
- mSkillsCount = (6>LL_ARRAY_SIZE(mSkillsCheck))?LL_ARRAY_SIZE(mSkillsCheck):6;
-
- for(S32 tt=0; tt < mSkillsCount; ++tt)
+ std::string first, last;
+ LLSD args;
+ if (gCacheName->getName(getAvatarId(), first, last))
{
- //Find the Skills checkboxes and save off thier controls
- std::string ctlname = llformat("schk%d",tt);
- mSkillsCheck[tt] = getChild<LLCheckBoxCtrl>(ctlname);
+ args["FIRST_NAME"] = first;
+ args["LAST_NAME"] = last;
}
- mWantToEdit = getChild<LLLineEditor>("want_to_edit");
- mSkillsEdit = getChild<LLLineEditor>("skills_edit");
- childSetVisible("skills_edit",LLPanelAvatar::sAllowFirstLife);
- childSetVisible("want_to_edit",LLPanelAvatar::sAllowFirstLife);
-
- return TRUE;
-}
-
-//-----------------------------------------------------------------------------
-// LLPanelAvatarWeb
-//-----------------------------------------------------------------------------
-LLPanelAvatarWeb::LLPanelAvatarWeb(const std::string& name, const LLRect& rect,
- LLPanelAvatar* panel_avatar)
-: LLPanelAvatarTab(name, rect, panel_avatar),
- mWebBrowser(NULL)
-{
-}
-
-LLPanelAvatarWeb::~LLPanelAvatarWeb()
-{
- // stop observing browser events
- if ( mWebBrowser )
+ if (grant)
{
- mWebBrowser->remObserver( this );
- };
-}
-
-void LLPanelAvatarWeb::refresh()
-{
- if (mNavigateTo != "")
+ LLNotificationsUtil::add("GrantModifyRights", args, LLSD(),
+ boost::bind(&LLPanelAvatarNotes::rightsConfirmationCallback, this,
+ _1, _2, rights));
+ }
+ else
{
- llinfos << "Loading " << mNavigateTo << llendl;
- mWebBrowser->navigateTo( mNavigateTo );
- mNavigateTo = "";
+ LLNotificationsUtil::add("RevokeModifyRights", args, LLSD(),
+ boost::bind(&LLPanelAvatarNotes::rightsConfirmationCallback, this,
+ _1, _2, rights));
}
}
-
-void LLPanelAvatarWeb::enableControls(BOOL self)
-{
- childSetEnabled("url_edit",self);
-}
-
-void LLPanelAvatarWeb::setWebURL(std::string url)
+void LLPanelAvatarNotes::onCommitRights()
{
- bool changed_url = (mHome != url);
+ S32 rights = 0;
- mHome = url;
- bool have_url = !mHome.empty();
-
- childSetText("url_edit", mHome);
- childSetEnabled("load", mHome.length() > 0);
+ if(childGetValue("status_check").asBoolean())
+ rights |= LLRelationship::GRANT_ONLINE_STATUS;
+ if(childGetValue("map_check").asBoolean())
+ rights |= LLRelationship::GRANT_MAP_LOCATION;
+ if(childGetValue("objects_check").asBoolean())
+ rights |= LLRelationship::GRANT_MODIFY_OBJECTS;
- if (have_url
- && gSavedSettings.getBOOL("AutoLoadWebProfiles"))
+ const LLRelationship* buddy_relationship =
+ LLAvatarTracker::instance().getBuddyInfo(getAvatarId());
+ bool allow_modify_objects = childGetValue("objects_check").asBoolean();
+
+ // if modify objects checkbox clicked
+ if (buddy_relationship->isRightGrantedTo(
+ LLRelationship::GRANT_MODIFY_OBJECTS) != allow_modify_objects)
{
- if (changed_url)
- {
- load(mHome);
- }
+ confirmModifyRights(allow_modify_objects, rights);
}
+ // only one checkbox can trigger commit, so store the rest of rights
else
{
- childSetVisible("profile_html",false);
- childSetVisible("status_text", false);
+ LLAvatarPropertiesProcessor::getInstance()->sendFriendRights(
+ getAvatarId(), rights);
}
}
-// static
-void LLPanelAvatarWeb::onCommitURL(LLUICtrl* ctrl, void* data)
+void LLPanelAvatarNotes::processProperties(void* data, EAvatarProcessorType type)
{
- LLPanelAvatarWeb* self = (LLPanelAvatarWeb*)data;
+ if(APT_NOTES == type)
+ {
+ LLAvatarNotes* avatar_notes = static_cast<LLAvatarNotes*>(data);
+ if(avatar_notes && getAvatarId() == avatar_notes->target_id)
+ {
+ childSetValue("notes_edit",avatar_notes->notes);
+ childSetEnabled("notes edit", true);
- if (!self) return;
-
- self->load( self->childGetText("url_edit") );
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this);
+ }
+ }
}
-// static
-void LLPanelAvatarWeb::onClickWebProfileHelp(void *)
+void LLPanelAvatarNotes::resetData()
{
- LLNotifications::instance().add("ClickWebProfileHelpAvatar");
+ childSetValue("notes_edit",LLStringUtil::null);
+ // Default value is TRUE
+ childSetValue("status_check", TRUE);
}
-void LLPanelAvatarWeb::load(std::string url)
+void LLPanelAvatarNotes::resetControls()
{
- bool have_url = (!url.empty());
-
-
- childSetVisible("profile_html", have_url);
- childSetVisible("status_text", have_url);
- childSetText("status_text", LLStringUtil::null);
+ //Disable "Add Friend" button for friends.
+ childSetEnabled("add_friend", TRUE);
- if (have_url)
- {
- mNavigateTo = url;
- }
+ childSetEnabled("status_check",FALSE);
+ childSetEnabled("map_check",FALSE);
+ childSetEnabled("objects_check",FALSE);
}
-//static
-void LLPanelAvatarWeb::onURLKeystroke(LLLineEditor* editor, void* data)
+void LLPanelAvatarNotes::onAddFriendButtonClick()
{
- LLPanelAvatarWeb* self = (LLPanelAvatarWeb*)data;
- if (!self) return;
- LLSD::String url = editor->getText();
- self->childSetEnabled("load", url.length() > 0);
- return;
+ LLAvatarActions::requestFriendshipDialog(getAvatarId());
}
-// static
-void LLPanelAvatarWeb::onCommitLoad(LLUICtrl* ctrl, void* data)
+void LLPanelAvatarNotes::onIMButtonClick()
{
- LLPanelAvatarWeb* self = (LLPanelAvatarWeb*)data;
-
- if (!self) return;
-
- LLSD::String valstr = ctrl->getValue().asString();
- LLSD::String urlstr = self->childGetText("url_edit");
- if (valstr == "") // load url string into browser panel
- {
- self->load(urlstr);
- }
- else if (valstr == "open") // open in user's external browser
- {
- if (!urlstr.empty())
- {
- LLWeb::loadURLExternal(urlstr);
- }
- }
- else if (valstr == "home") // reload profile owner's home page
- {
- if (!self->mHome.empty())
- {
- self->load(self->mHome);
- }
- }
+ LLAvatarActions::startIM(getAvatarId());
}
-void LLPanelAvatarWeb::onStatusTextChange( const EventType& eventIn )
+void LLPanelAvatarNotes::onTeleportButtonClick()
{
- childSetText("status_text", eventIn.getStringValue() );
+ LLAvatarActions::offerTeleport(getAvatarId());
}
-void LLPanelAvatarWeb::onLocationChange( const EventType& eventIn )
+void LLPanelAvatarNotes::onCallButtonClick()
{
- childSetText("url_edit", eventIn.getStringValue() );
+ LLAvatarActions::startCall(getAvatarId());
}
-
-//-----------------------------------------------------------------------------
-// LLPanelAvatarAdvanced
-//-----------------------------------------------------------------------------
-LLPanelAvatarAdvanced::LLPanelAvatarAdvanced(const std::string& name,
- const LLRect& rect,
- LLPanelAvatar* panel_avatar)
-: LLPanelAvatarTab(name, rect, panel_avatar),
- mWantToCount(0),
- mSkillsCount(0),
- mWantToEdit( NULL ),
- mSkillsEdit( NULL )
+void LLPanelAvatarNotes::onShareButtonClick()
{
+ //*TODO not implemented.
}
-void LLPanelAvatarAdvanced::enableControls(BOOL self)
+LLPanelAvatarNotes::~LLPanelAvatarNotes()
{
- S32 t;
- for(t=0;t<mWantToCount;t++)
+ if(getAvatarId().notNull())
{
- if(mWantToCheck[t])mWantToCheck[t]->setEnabled(self);
- }
- for(t=0;t<mSkillsCount;t++)
- {
- if(mSkillsCheck[t])mSkillsCheck[t]->setEnabled(self);
+ LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this);
+ if(LLVoiceClient::getInstance())
+ LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this);
}
+}
- if (mWantToEdit) mWantToEdit->setEnabled(self);
- if (mSkillsEdit) mSkillsEdit->setEnabled(self);
- childSetEnabled("languages_edit",self);
+// virtual, called by LLAvatarTracker
+void LLPanelAvatarNotes::changed(U32 mask)
+{
+ childSetEnabled("teleport", LLAvatarTracker::instance().isBuddyOnline(getAvatarId()));
}
-void LLPanelAvatarAdvanced::setWantSkills(U32 want_to_mask, const std::string& want_to_text,
- U32 skills_mask, const std::string& skills_text,
- const std::string& languages_text)
+// virtual
+void LLPanelAvatarNotes::onChange(EStatusType status, const std::string &channelURI, bool proximal)
{
- for(int id =0;id<mWantToCount;id++)
- {
- mWantToCheck[id]->set( want_to_mask & 1<<id );
- }
- for(int id =0;id<mSkillsCount;id++)
- {
- mSkillsCheck[id]->set( skills_mask & 1<<id );
- }
- if (mWantToEdit && mSkillsEdit)
+ if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL)
{
- mWantToEdit->setText( want_to_text );
- mSkillsEdit->setText( skills_text );
+ return;
}
- childSetText("languages_edit",languages_text);
+ childSetEnabled("call", LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking());
}
-void LLPanelAvatarAdvanced::getWantSkills(U32* want_to_mask, std::string& want_to_text,
- U32* skills_mask, std::string& skills_text,
- std::string& languages_text)
+void LLPanelAvatarNotes::setAvatarId(const LLUUID& id)
{
- if (want_to_mask)
- {
- *want_to_mask = 0;
- for(int t=0;t<mWantToCount;t++)
- {
- if(mWantToCheck[t]->get())
- *want_to_mask |= 1<<t;
- }
- }
- if (skills_mask)
+ if(id.notNull())
{
- *skills_mask = 0;
- for(int t=0;t<mSkillsCount;t++)
+ if(getAvatarId().notNull())
{
- if(mSkillsCheck[t]->get())
- *skills_mask |= 1<<t;
+ LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this);
}
+ LLPanelProfileTab::setAvatarId(id);
+ LLAvatarTracker::instance().addParticularFriendObserver(getAvatarId(), this);
}
- if (mWantToEdit)
- {
- want_to_text = mWantToEdit->getText();
- }
-
- if (mSkillsEdit)
- {
- skills_text = mSkillsEdit->getText();
- }
-
- languages_text = childGetText("languages_edit");
-}
-
-//-----------------------------------------------------------------------------
-// LLPanelAvatarNotes()
-//-----------------------------------------------------------------------------
-LLPanelAvatarNotes::LLPanelAvatarNotes(const std::string& name, const LLRect& rect, LLPanelAvatar* panel_avatar)
-: LLPanelAvatarTab(name, rect, panel_avatar)
-{
}
-void LLPanelAvatarNotes::refresh()
-{
- sendAvatarProfileRequestIfNeeded("avatarnotesrequest");
-}
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
-void LLPanelAvatarNotes::clearControls()
+LLPanelProfileTab::LLPanelProfileTab()
+: LLPanel()
+, mAvatarId(LLUUID::null)
{
- childSetText("notes edit", getString("Loading"));
- childSetEnabled("notes edit", false);
}
-// static
-void LLPanelAvatarNotes::onCommitNotes(LLUICtrl*, void* userdata)
+LLPanelProfileTab::~LLPanelProfileTab()
{
- LLPanelAvatarNotes* self = (LLPanelAvatarNotes*)userdata;
-
- self->getPanelAvatar()->sendAvatarNotesUpdate();
-}
-
-
-//-----------------------------------------------------------------------------
-// LLPanelAvatarClassified()
-//-----------------------------------------------------------------------------
-LLPanelAvatarClassified::LLPanelAvatarClassified(const std::string& name, const LLRect& rect,
- LLPanelAvatar* panel_avatar)
-: LLPanelAvatarTab(name, rect, panel_avatar)
-{
-}
-
-
-void LLPanelAvatarClassified::refresh()
-{
- BOOL self = (gAgent.getID() == getPanelAvatar()->getAvatarID());
-
- LLTabContainer* tabs = getChild<LLTabContainer>("classified tab");
-
- S32 tab_count = tabs ? tabs->getTabCount() : 0;
-
- bool allow_new = tab_count < MAX_CLASSIFIEDS;
- bool allow_delete = (tab_count > 0);
- bool show_help = (tab_count == 0);
-
- // *HACK: Don't allow making new classifieds from inside the directory.
- // The logic for save/don't save when closing is too hairy, and the
- // directory is conceptually read-only. JC
- bool in_directory = false;
- LLView* view = this;
- while (view)
+ if(getAvatarId().notNull())
{
- if (view->getName() == "directory")
- {
- in_directory = true;
- break;
- }
- view = view->getParent();
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this);
}
- childSetEnabled("New...", self && !in_directory && allow_new);
- childSetVisible("New...", !in_directory);
- childSetEnabled("Delete...", self && !in_directory && allow_delete);
- childSetVisible("Delete...", !in_directory);
- childSetVisible("classified tab",!show_help);
-
- sendAvatarProfileRequestIfNeeded("avatarclassifiedsrequest");
}
-
-BOOL LLPanelAvatarClassified::canClose()
+void LLPanelProfileTab::setAvatarId(const LLUUID& id)
{
- LLTabContainer* tabs = getChild<LLTabContainer>("classified tab");
- for (S32 i = 0; i < tabs->getTabCount(); i++)
+ if(id.notNull())
{
- LLPanelClassified* panel = (LLPanelClassified*)tabs->getPanelByIndex(i);
- if (!panel->canClose())
+ if(getAvatarId().notNull())
{
- return FALSE;
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(mAvatarId,this);
}
+ mAvatarId = id;
+ LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(),this);
}
- return TRUE;
}
-BOOL LLPanelAvatarClassified::titleIsValid()
+void LLPanelProfileTab::onOpen(const LLSD& key)
{
- LLTabContainer* tabs = getChild<LLTabContainer>("classified tab");
- if ( tabs )
+ // Don't reset panel if we are opening it for same avatar.
+ if(getAvatarId() != key.asUUID())
{
- LLPanelClassified* panel = (LLPanelClassified*)tabs->getCurrentPanel();
- if ( panel )
- {
- if ( ! panel->titleIsValid() )
- {
- return FALSE;
- };
- };
- };
+ resetControls();
+ resetData();
- return TRUE;
+ scrollToTop();
+ }
+
+ // Update data even if we are viewing same avatar profile as some data might been changed.
+ setAvatarId(key.asUUID());
+ updateData();
+ updateButtons();
}
-void LLPanelAvatarClassified::apply()
+void LLPanelProfileTab::scrollToTop()
{
- LLTabContainer* tabs = getChild<LLTabContainer>("classified tab");
- for (S32 i = 0; i < tabs->getTabCount(); i++)
- {
- LLPanelClassified* panel = (LLPanelClassified*)tabs->getPanelByIndex(i);
- panel->apply();
- }
+ LLScrollContainer* scrollContainer = findChild<LLScrollContainer>("profile_scroll");
+ if (scrollContainer)
+ scrollContainer->goToTop();
}
-
-void LLPanelAvatarClassified::deleteClassifiedPanels()
+void LLPanelProfileTab::onMapButtonClick()
{
- LLTabContainer* tabs = getChild<LLTabContainer>("classified tab");
- if (tabs)
- {
- tabs->deleteAllTabs();
- }
-
- childSetVisible("New...", false);
- childSetVisible("Delete...", false);
- childSetVisible("loading_text", true);
+ std::string name;
+ gCacheName->getFullName(getAvatarId(), name);
+ gFloaterWorldMap->trackAvatar(getAvatarId(), name);
+ LLFloaterReg::showInstance("world_map");
}
-
-void LLPanelAvatarClassified::processAvatarClassifiedReply(LLMessageSystem* msg, void**)
+void LLPanelProfileTab::updateButtons()
{
- S32 block = 0;
- S32 block_count = 0;
- LLUUID classified_id;
- std::string classified_name;
- LLPanelClassified* panel_classified = NULL;
-
- LLTabContainer* tabs = getChild<LLTabContainer>("classified tab");
-
- // Don't remove old panels. We need to be able to process multiple
- // packets for people who have lots of classifieds. JC
-
- block_count = msg->getNumberOfBlocksFast(_PREHASH_Data);
- for (block = 0; block < block_count; block++)
+ bool is_avatar_online = LLAvatarTracker::instance().isBuddyOnline(getAvatarId());
+
+ if(LLAvatarActions::isFriend(getAvatarId()))
{
- msg->getUUIDFast(_PREHASH_Data, _PREHASH_ClassifiedID, classified_id, block);
- msg->getStringFast(_PREHASH_Data, _PREHASH_Name, classified_name, block);
-
- panel_classified = new LLPanelClassified(false, false);
-
- panel_classified->setClassifiedID(classified_id);
-
- // This will request data from the server when the pick is first drawn.
- panel_classified->markForServerRequest();
-
- // The button should automatically truncate long names for us
- if(tabs)
- {
- tabs->addTabPanel(panel_classified, classified_name);
- }
+ childSetEnabled("teleport", is_avatar_online);
}
-
- // Make sure somebody is highlighted. This works even if there
- // are no tabs in the container.
- if(tabs)
+ else
{
- tabs->selectFirstTab();
+ childSetEnabled("teleport", true);
}
- childSetVisible("New...", true);
- childSetVisible("Delete...", true);
- childSetVisible("loading_text", false);
+ bool enable_map_btn = is_avatar_online && gAgent.isGodlike() || is_agent_mappable(getAvatarId());
+ childSetEnabled("show_on_map_btn", enable_map_btn);
}
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
-// Create a new classified panel. It will automatically handle generating
-// its own id when it's time to save.
-// static
-void LLPanelAvatarClassified::onClickNew(void* data)
+bool enable_god()
{
- LLPanelAvatarClassified* self = (LLPanelAvatarClassified*)data;
-
- LLNotifications::instance().add("AddClassified", LLSD(), LLSD(), boost::bind(&LLPanelAvatarClassified::callbackNew, self, _1, _2));
-
+ return gAgent.isGodlike();
}
-bool LLPanelAvatarClassified::callbackNew(const LLSD& notification, const LLSD& response)
+LLPanelAvatarProfile::LLPanelAvatarProfile()
+: LLPanelProfileTab()
{
- S32 option = LLNotification::getSelectedOption(notification, response);
- if (0 == option)
- {
- LLPanelClassified* panel_classified = new LLPanelClassified(false, false);
- panel_classified->initNewClassified();
- LLTabContainer* tabs = getChild<LLTabContainer>("classified tab");
- if(tabs)
- {
- tabs->addTabPanel(panel_classified, panel_classified->getClassifiedName());
- tabs->selectLastTab();
- }
- }
- return false;
}
-
-// static
-void LLPanelAvatarClassified::onClickDelete(void* data)
+BOOL LLPanelAvatarProfile::postBuild()
{
- LLPanelAvatarClassified* self = (LLPanelAvatarClassified*)data;
+ childSetActionTextbox("homepage_edit", boost::bind(&LLPanelAvatarProfile::onHomepageTextboxClicked, this));
+ childSetCommitCallback("add_friend",(boost::bind(&LLPanelAvatarProfile::onAddFriendButtonClick,this)),NULL);
+ childSetCommitCallback("im",(boost::bind(&LLPanelAvatarProfile::onIMButtonClick,this)),NULL);
+ childSetCommitCallback("call",(boost::bind(&LLPanelAvatarProfile::onCallButtonClick,this)),NULL);
+ childSetCommitCallback("teleport",(boost::bind(&LLPanelAvatarProfile::onTeleportButtonClick,this)),NULL);
+ childSetCommitCallback("overflow_btn", boost::bind(&LLPanelAvatarProfile::onOverflowButtonClicked, this), NULL);
+ childSetCommitCallback("share",(boost::bind(&LLPanelAvatarProfile::onShareButtonClick,this)),NULL);
+ childSetCommitCallback("show_on_map_btn", (boost::bind(
+ &LLPanelAvatarProfile::onMapButtonClick, this)), NULL);
- LLTabContainer* tabs = self->getChild<LLTabContainer>("classified tab");
- LLPanelClassified* panel_classified = NULL;
- if(tabs)
- {
- panel_classified = (LLPanelClassified*)tabs->getCurrentPanel();
- }
- if (!panel_classified) return;
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("Profile.Pay", boost::bind(&LLPanelAvatarProfile::pay, this));
+ registrar.add("Profile.Share", boost::bind(&LLPanelAvatarProfile::share, this));
+ registrar.add("Profile.Kick", boost::bind(&LLPanelAvatarProfile::kick, this));
+ registrar.add("Profile.Freeze", boost::bind(&LLPanelAvatarProfile::freeze, this));
+ registrar.add("Profile.Unfreeze", boost::bind(&LLPanelAvatarProfile::unfreeze, this));
+ registrar.add("Profile.CSR", boost::bind(&LLPanelAvatarProfile::csr, this));
- LLSD args;
- args["NAME"] = panel_classified->getClassifiedName();
- LLNotifications::instance().add("DeleteClassified", args, LLSD(), boost::bind(&LLPanelAvatarClassified::callbackDelete, self, _1, _2));
-
-}
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable;
+ enable.add("Profile.EnableGod", boost::bind(&enable_god));
+ mProfileMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_profile_overflow.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
-bool LLPanelAvatarClassified::callbackDelete(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotification::getSelectedOption(notification, response);
- LLTabContainer* tabs = getChild<LLTabContainer>("classified tab");
- LLPanelClassified* panel_classified=NULL;
- if(tabs)
- {
- panel_classified = (LLPanelClassified*)tabs->getCurrentPanel();
- }
-
- LLMessageSystem* msg = gMessageSystem;
+ LLTextureCtrl* pic = getChild<LLTextureCtrl>("2nd_life_pic");
+ pic->setFallbackImageName("default_profile_picture.j2c");
- if (!panel_classified) return false;
+ pic = getChild<LLTextureCtrl>("real_world_pic");
+ pic->setFallbackImageName("default_profile_picture.j2c");
- if (0 == option)
- {
- msg->newMessageFast(_PREHASH_ClassifiedDelete);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_Data);
- msg->addUUIDFast(_PREHASH_ClassifiedID, panel_classified->getClassifiedID());
- gAgent.sendReliableMessage();
-
- if(tabs)
- {
- tabs->removeTabPanel(panel_classified);
- }
- delete panel_classified;
- panel_classified = NULL;
- }
- return false;
-}
+ gVoiceClient->addObserver((LLVoiceClientStatusObserver*)this);
+ resetControls();
+ resetData();
-//-----------------------------------------------------------------------------
-// LLPanelAvatarPicks()
-//-----------------------------------------------------------------------------
-LLPanelAvatarPicks::LLPanelAvatarPicks(const std::string& name,
- const LLRect& rect,
- LLPanelAvatar* panel_avatar)
-: LLPanelAvatarTab(name, rect, panel_avatar)
-{
+ return TRUE;
}
-
-void LLPanelAvatarPicks::refresh()
+void LLPanelAvatarProfile::onOpen(const LLSD& key)
{
- BOOL self = (gAgent.getID() == getPanelAvatar()->getAvatarID());
- LLTabContainer* tabs = getChild<LLTabContainer>("picks tab");
- S32 tab_count = tabs ? tabs->getTabCount() : 0;
- childSetEnabled("New...", self && tab_count < MAX_AVATAR_PICKS);
- childSetEnabled("Delete...", self && tab_count > 0);
- childSetVisible("New...", self && getPanelAvatar()->isEditable());
- childSetVisible("Delete...", self && getPanelAvatar()->isEditable());
-
- sendAvatarProfileRequestIfNeeded("avatarpicksrequest");
-}
+ LLPanelProfileTab::onOpen(key);
+ mGroups.clear();
-void LLPanelAvatarPicks::deletePickPanels()
-{
- LLTabContainer* tabs = getChild<LLTabContainer>("picks tab");
- if(tabs)
- {
- tabs->deleteAllTabs();
- }
-
- childSetVisible("New...", false);
- childSetVisible("Delete...", false);
- childSetVisible("loading_text", true);
+ //Disable "Add Friend" button for friends.
+ childSetEnabled("add_friend", !LLAvatarActions::isFriend(getAvatarId()));
}
-void LLPanelAvatarPicks::processAvatarPicksReply(LLMessageSystem* msg, void**)
+void LLPanelAvatarProfile::updateData()
{
- S32 block = 0;
- S32 block_count = 0;
- LLUUID pick_id;
- std::string pick_name;
- LLPanelPick* panel_pick = NULL;
-
- LLTabContainer* tabs = getChild<LLTabContainer>("picks tab");
-
- // Clear out all the old panels. We'll replace them with the correct
- // number of new panels.
- deletePickPanels();
-
- // The database needs to know for which user to look up picks.
- LLUUID avatar_id = getPanelAvatar()->getAvatarID();
-
- block_count = msg->getNumberOfBlocks("Data");
- for (block = 0; block < block_count; block++)
+ if (getAvatarId().notNull())
{
- msg->getUUID("Data", "PickID", pick_id, block);
- msg->getString("Data", "PickName", pick_name, block);
-
- panel_pick = new LLPanelPick(FALSE);
-
- panel_pick->setPickID(pick_id, avatar_id);
-
- // This will request data from the server when the pick is first
- // drawn.
- panel_pick->markForServerRequest();
-
- // The button should automatically truncate long names for us
- if(tabs)
- {
- tabs->addTabPanel(panel_pick, pick_name);
- }
+ LLAvatarPropertiesProcessor::getInstance()->
+ sendAvatarPropertiesRequest(getAvatarId());
+ LLAvatarPropertiesProcessor::getInstance()->
+ sendAvatarGroupsRequest(getAvatarId());
}
-
- // Make sure somebody is highlighted. This works even if there
- // are no tabs in the container.
- if(tabs)
- {
- tabs->selectFirstTab();
- }
-
- childSetVisible("New...", true);
- childSetVisible("Delete...", true);
- childSetVisible("loading_text", false);
}
-
-// Create a new pick panel. It will automatically handle generating
-// its own id when it's time to save.
-// static
-void LLPanelAvatarPicks::onClickNew(void* data)
+void LLPanelAvatarProfile::resetControls()
{
- LLPanelAvatarPicks* self = (LLPanelAvatarPicks*)data;
- LLPanelPick* panel_pick = new LLPanelPick(FALSE);
- LLTabContainer* tabs = self->getChild<LLTabContainer>("picks tab");
+ childSetVisible("status_panel", true);
+ childSetVisible("profile_buttons_panel", true);
+ childSetVisible("title_groups_text", true);
+ childSetVisible("sl_groups", true);
+ childSetEnabled("add_friend", true);
- panel_pick->initNewPick();
- if(tabs)
- {
- tabs->addTabPanel(panel_pick, panel_pick->getPickName());
- tabs->selectLastTab();
- }
+ childSetVisible("status_me_panel", false);
+ childSetVisible("profile_me_buttons_panel", false);
+ childSetVisible("account_actions_panel", false);
}
-
-// static
-void LLPanelAvatarPicks::onClickDelete(void* data)
+void LLPanelAvatarProfile::resetData()
{
- LLPanelAvatarPicks* self = (LLPanelAvatarPicks*)data;
- LLTabContainer* tabs = self->getChild<LLTabContainer>("picks tab");
- LLPanelPick* panel_pick = tabs?(LLPanelPick*)tabs->getCurrentPanel():NULL;
-
- if (!panel_pick) return;
-
- LLSD args;
- args["PICK"] = panel_pick->getPickName();
-
- LLNotifications::instance().add("DeleteAvatarPick", args, LLSD(),
- boost::bind(&LLPanelAvatarPicks::callbackDelete, self, _1, _2));
+ mGroups.clear();
+ childSetValue("2nd_life_pic",LLUUID::null);
+ childSetValue("real_world_pic",LLUUID::null);
+ childSetValue("online_status",LLStringUtil::null);
+ childSetValue("status_message",LLStringUtil::null);
+ childSetValue("sl_description_edit",LLStringUtil::null);
+ childSetValue("fl_description_edit",LLStringUtil::null);
+ childSetValue("sl_groups",LLStringUtil::null);
+ childSetValue("homepage_edit",LLStringUtil::null);
+ childSetValue("register_date",LLStringUtil::null);
+ childSetValue("acc_status_text",LLStringUtil::null);
+ childSetTextArg("partner_text", "[FIRST]", LLStringUtil::null);
+ childSetTextArg("partner_text", "[LAST]", LLStringUtil::null);
}
-
-// static
-bool LLPanelAvatarPicks::callbackDelete(const LLSD& notification, const LLSD& response)
+void LLPanelAvatarProfile::processProperties(void* data, EAvatarProcessorType type)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
- LLTabContainer* tabs = getChild<LLTabContainer>("picks tab");
- LLPanelPick* panel_pick = tabs ? (LLPanelPick*)tabs->getCurrentPanel() : NULL;
- LLMessageSystem* msg = gMessageSystem;
-
- if (!panel_pick) return false;
-
- if (0 == option)
+ if(APT_PROPERTIES == type)
{
- // If the viewer has a hacked god-mode, then this call will
- // fail.
- if(gAgent.isGodlike())
+ const LLAvatarData* avatar_data = static_cast<const LLAvatarData*>(data);
+ if(avatar_data && getAvatarId() == avatar_data->avatar_id)
{
- msg->newMessage("PickGodDelete");
- msg->nextBlock("AgentData");
- msg->addUUID("AgentID", gAgent.getID());
- msg->addUUID("SessionID", gAgent.getSessionID());
- msg->nextBlock("Data");
- msg->addUUID("PickID", panel_pick->getPickID());
- // *HACK: We need to send the pick's creator id to accomplish
- // the delete, and we don't use the query id for anything. JC
- msg->addUUID( "QueryID", panel_pick->getPickCreatorID() );
+ processProfileProperties(avatar_data);
}
- else
- {
- msg->newMessage("PickDelete");
- msg->nextBlock("AgentData");
- msg->addUUID("AgentID", gAgent.getID());
- msg->addUUID("SessionID", gAgent.getSessionID());
- msg->nextBlock("Data");
- msg->addUUID("PickID", panel_pick->getPickID());
- }
- gAgent.sendReliableMessage();
-
- if(tabs)
+ }
+ else if(APT_GROUPS == type)
+ {
+ LLAvatarGroups* avatar_groups = static_cast<LLAvatarGroups*>(data);
+ if(avatar_groups && getAvatarId() == avatar_groups->avatar_id)
{
- tabs->removeTabPanel(panel_pick);
+ processGroupProperties(avatar_groups);
}
- delete panel_pick;
- panel_pick = NULL;
}
- return false;
}
+void LLPanelAvatarProfile::processProfileProperties(const LLAvatarData* avatar_data)
+{
+ fillCommonData(avatar_data);
-//-----------------------------------------------------------------------------
-// LLPanelAvatar
-//-----------------------------------------------------------------------------
-LLPanelAvatar::LLPanelAvatar(
- const std::string& name,
- const LLRect &rect,
- BOOL allow_edit)
- :
- LLPanel(name, rect, FALSE),
- mPanelSecondLife(NULL),
- mPanelAdvanced(NULL),
- mPanelClassified(NULL),
- mPanelPicks(NULL),
- mPanelNotes(NULL),
- mPanelFirstLife(NULL),
- mPanelWeb(NULL),
- mDropTarget(NULL),
- mAvatarID( LLUUID::null ), // mAvatarID is set with 'setAvatar' or 'setAvatarID'
- mHaveProperties(FALSE),
- mHaveStatistics(FALSE),
- mHaveNotes(false),
- mLastNotes(),
- mAllowEdit(allow_edit)
-{
-
- sAllPanels.push_back(this);
-
- LLCallbackMap::map_t factory_map;
-
- factory_map["2nd Life"] = LLCallbackMap(createPanelAvatarSecondLife, this);
- factory_map["WebProfile"] = LLCallbackMap(createPanelAvatarWeb, this);
- factory_map["Interests"] = LLCallbackMap(createPanelAvatarInterests, this);
- factory_map["Picks"] = LLCallbackMap(createPanelAvatarPicks, this);
- factory_map["Classified"] = LLCallbackMap(createPanelAvatarClassified, this);
- factory_map["1st Life"] = LLCallbackMap(createPanelAvatarFirstLife, this);
- factory_map["My Notes"] = LLCallbackMap(createPanelAvatarNotes, this);
-
- LLUICtrlFactory::getInstance()->buildPanel(this, "panel_avatar.xml", &factory_map);
-
- selectTab(0);
-
+ fillPartnerData(avatar_data);
+ fillAccountStatus(avatar_data);
}
-BOOL LLPanelAvatar::postBuild(void)
+void LLPanelAvatarProfile::processGroupProperties(const LLAvatarGroups* avatar_groups)
{
- mTab = getChild<LLTabContainer>("tab");
- childSetAction("Kick",onClickKick,this);
- childSetAction("Freeze",onClickFreeze, this);
- childSetAction("Unfreeze", onClickUnfreeze, this);
- childSetAction("csr_btn", onClickCSR, this);
- childSetAction("OK", onClickOK, this);
- childSetAction("Cancel", onClickCancel, this);
+ // *NOTE dzaporozhan
+ // Group properties may arrive in two callbacks, we need to save them across
+ // different calls. We can't do that in textbox as textbox may change the text.
- if(mTab && !sAllowFirstLife)
- {
- LLPanel* panel = mTab->getPanelByName("1st Life");
- if (panel) mTab->removeTabPanel(panel);
+ 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();
- panel = mTab->getPanelByName("WebProfile");
- if (panel) mTab->removeTabPanel(panel);
+ for(; it_end != it; ++it)
+ {
+ LLAvatarGroups::LLGroupData group_data = *it;
+ mGroups[group_data.group_name] = group_data.group_id;
}
- childSetVisible("Kick",FALSE);
- childSetEnabled("Kick",FALSE);
- childSetVisible("Freeze",FALSE);
- childSetEnabled("Freeze",FALSE);
- childSetVisible("Unfreeze",FALSE);
- childSetEnabled("Unfreeze",FALSE);
- childSetVisible("csr_btn", FALSE);
- childSetEnabled("csr_btn", FALSE);
-
- return TRUE;
-}
+ // Creating string, containing group list
+ std::string groups = "";
+ for (group_map_t::iterator it = mGroups.begin(); it != mGroups.end(); ++it)
+ {
+ if (it != mGroups.begin())
+ groups += ", ";
-LLPanelAvatar::~LLPanelAvatar()
-{
- sAllPanels.remove(this);
-}
+ std::string group_name = LLURI::escape(it->first);
+ std::string group_url= it->second.notNull()
+ ? "[secondlife:///app/group/" + it->second.asString() + "/about " + group_name + "]"
+ : getString("no_group_text");
+ groups += group_url;
+ }
-BOOL LLPanelAvatar::canClose()
-{
- return mPanelClassified && mPanelClassified->canClose();
+ childSetValue("sl_groups", groups);
}
-void LLPanelAvatar::setAvatar(LLViewerObject *avatarp)
+void LLPanelAvatarProfile::fillCommonData(const LLAvatarData* avatar_data)
{
- // find the avatar and grab the name
- LLNameValue *firstname = avatarp->getNVPair("FirstName");
- LLNameValue *lastname = avatarp->getNVPair("LastName");
+ //remove avatar id from cache to get fresh info
+ LLAvatarIconIDCache::getInstance()->remove(avatar_data->avatar_id);
- std::string name;
- if (firstname && lastname)
- {
- name.assign( firstname->getString() );
- name.append(" ");
- name.append( lastname->getString() );
- }
- else
- {
- name.assign("");
- }
-
- // If we have an avatar pointer, they must be online.
- setAvatarID(avatarp->getID(), name, ONLINE_STATUS_YES);
+ LLStringUtil::format_map_t args;
+ args["[REG_DATE]"] = avatar_data->born_on;
+ args["[AGE]"] = LLDateUtil::ageFromDate( avatar_data->born_on, LLDate::now());
+ std::string register_date = getString("RegisterDateFormat", args);
+ childSetValue("register_date", register_date );
+ childSetValue("sl_description_edit", avatar_data->about_text);
+ childSetValue("fl_description_edit",avatar_data->fl_about_text);
+ childSetValue("2nd_life_pic", avatar_data->image_id);
+ childSetValue("real_world_pic", avatar_data->fl_image_id);
+ childSetValue("homepage_edit", avatar_data->profile_url);
}
-void LLPanelAvatar::setOnlineStatus(EOnlineStatus online_status)
+void LLPanelAvatarProfile::fillPartnerData(const LLAvatarData* avatar_data)
{
- // Online status NO could be because they are hidden
- // If they are a friend, we may know the truth!
- if ((ONLINE_STATUS_YES != online_status)
- && mIsFriend
- && (LLAvatarTracker::instance().isBuddyOnline( mAvatarID )))
- {
- online_status = ONLINE_STATUS_YES;
- }
-
- mPanelSecondLife->childSetVisible("online_yes", (online_status == ONLINE_STATUS_YES));
-
- // Since setOnlineStatus gets called after setAvatarID
- // need to make sure that "Offer Teleport" doesn't get set
- // to TRUE again for yourself
- if (mAvatarID != gAgent.getID())
- {
- childSetVisible("Offer Teleport...",TRUE);
- }
-
- BOOL in_prelude = gAgent.inPrelude();
- if(gAgent.isGodlike())
- {
- childSetEnabled("Offer Teleport...", TRUE);
- childSetToolTip("Offer Teleport...", childGetValue("TeleportGod").asString());
- }
- else if (in_prelude)
+ LLNameBox* name_box = getChild<LLNameBox>("partner_text");
+ if (avatar_data->partner_id.notNull())
{
- childSetEnabled("Offer Teleport...",FALSE);
- childSetToolTip("Offer Teleport...",childGetValue("TeleportPrelude").asString());
+ name_box->setNameID(avatar_data->partner_id, FALSE);
}
else
{
- childSetEnabled("Offer Teleport...", (online_status == ONLINE_STATUS_YES));
- childSetToolTip("Offer Teleport...", childGetValue("TeleportNormal").asString());
+ name_box->setNameID(LLUUID::null, FALSE);
+ name_box->setText(getString("no_partner_text"));
}
}
-void LLPanelAvatar::setAvatarID(const LLUUID &avatar_id, const std::string &name,
- EOnlineStatus online_status)
+void LLPanelAvatarProfile::fillAccountStatus(const LLAvatarData* avatar_data)
{
- if (avatar_id.isNull()) return;
-
- BOOL avatar_changed = FALSE;
- if (avatar_id != mAvatarID)
- {
- avatar_changed = TRUE;
- }
- mAvatarID = avatar_id;
-
- // Determine if we have their calling card.
- mIsFriend = is_agent_friend(mAvatarID);
-
- // setOnlineStatus uses mIsFriend
- setOnlineStatus(online_status);
-
- BOOL own_avatar = (mAvatarID == gAgent.getID() );
- BOOL avatar_is_friend = LLAvatarTracker::instance().getBuddyInfo(mAvatarID) != NULL;
-
- mPanelSecondLife->enableControls(own_avatar && mAllowEdit);
- mPanelWeb->enableControls(own_avatar && mAllowEdit);
- mPanelAdvanced->enableControls(own_avatar && mAllowEdit);
- // Teens don't have this.
- if (mPanelFirstLife) mPanelFirstLife->enableControls(own_avatar && mAllowEdit);
-
- LLView *target_view = getChild<LLView>("drop_target_rect");
- if(target_view)
- {
- if (mDropTarget)
- {
- delete mDropTarget;
- }
- mDropTarget = new LLDropTarget("drop target", target_view->getRect(), mAvatarID);
- addChild(mDropTarget);
- mDropTarget->setAgentID(mAvatarID);
- }
-
- LLNameEditor* name_edit = getChild<LLNameEditor>("name");
- if(name_edit)
- {
- if (name.empty())
- {
- name_edit->setNameID(avatar_id, FALSE);
- }
- else
- {
- name_edit->setText(name);
- }
- }
-// if (avatar_changed)
- {
- // While we're waiting for data off the network, clear out the
- // old data.
- mPanelSecondLife->clearControls();
-
- mPanelPicks->deletePickPanels();
- mPanelPicks->setDataRequested(false);
-
- mPanelClassified->deleteClassifiedPanels();
- mPanelClassified->setDataRequested(false);
-
- mPanelNotes->clearControls();
- mPanelNotes->setDataRequested(false);
- mHaveNotes = false;
- mLastNotes.clear();
-
- // Request just the first two pages of data. The picks,
- // classifieds, and notes will be requested when that panel
- // is made visible. JC
- sendAvatarPropertiesRequest();
-
- if (own_avatar)
- {
- if (mAllowEdit)
- {
- // OK button disabled until properties data arrives
- childSetVisible("OK", true);
- childSetEnabled("OK", false);
- childSetVisible("Cancel",TRUE);
- childSetEnabled("Cancel",TRUE);
- }
- else
- {
- childSetVisible("OK",FALSE);
- childSetEnabled("OK",FALSE);
- childSetVisible("Cancel",FALSE);
- childSetEnabled("Cancel",FALSE);
- }
- childSetVisible("Instant Message...",FALSE);
- childSetEnabled("Instant Message...",FALSE);
- childSetVisible("Mute",FALSE);
- childSetEnabled("Mute",FALSE);
- childSetVisible("Offer Teleport...",FALSE);
- childSetEnabled("Offer Teleport...",FALSE);
- childSetVisible("drop target",FALSE);
- childSetEnabled("drop target",FALSE);
- childSetVisible("Find on Map",FALSE);
- childSetEnabled("Find on Map",FALSE);
- childSetVisible("Add Friend...",FALSE);
- childSetEnabled("Add Friend...",FALSE);
- childSetVisible("Pay...",FALSE);
- childSetEnabled("Pay...",FALSE);
- }
- else
- {
- childSetVisible("OK",FALSE);
- childSetEnabled("OK",FALSE);
-
- childSetVisible("Cancel",FALSE);
- childSetEnabled("Cancel",FALSE);
-
- childSetVisible("Instant Message...",TRUE);
- childSetEnabled("Instant Message...",FALSE);
- childSetVisible("Mute",TRUE);
- childSetEnabled("Mute",FALSE);
-
- childSetVisible("drop target",TRUE);
- childSetEnabled("drop target",FALSE);
-
- childSetVisible("Find on Map",TRUE);
- // Note: we don't always know online status, so always allow gods to try to track
- BOOL enable_track = gAgent.isGodlike() || is_agent_mappable(mAvatarID);
- childSetEnabled("Find on Map",enable_track);
- if (!mIsFriend)
- {
- childSetToolTip("Find on Map",childGetValue("ShowOnMapNonFriend").asString());
- }
- else if (ONLINE_STATUS_YES != online_status)
- {
- childSetToolTip("Find on Map",childGetValue("ShowOnMapFriendOffline").asString());
- }
- else
- {
- childSetToolTip("Find on Map",childGetValue("ShowOnMapFriendOnline").asString());
- }
- childSetVisible("Add Friend...", true);
- childSetEnabled("Add Friend...", !avatar_is_friend);
- childSetVisible("Pay...",TRUE);
- childSetEnabled("Pay...",FALSE);
- }
- }
-
- BOOL is_god = FALSE;
- if (gAgent.isGodlike()) is_god = TRUE;
-
- childSetVisible("Kick", is_god);
- childSetEnabled("Kick", is_god);
- childSetVisible("Freeze", is_god);
- childSetEnabled("Freeze", is_god);
- childSetVisible("Unfreeze", is_god);
- childSetEnabled("Unfreeze", is_god);
- childSetVisible("csr_btn", is_god);
- childSetEnabled("csr_btn", is_god);
+ LLStringUtil::format_map_t args;
+ args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(avatar_data);
+ args["[PAYMENTINFO]"] = LLAvatarPropertiesProcessor::paymentInfo(avatar_data);
+ // *NOTE: AVATAR_AGEVERIFIED not currently getting set in
+ // dataserver/lldataavatar.cpp for privacy considerations
+ args["[AGEVERIFICATION]"] = "";
+ std::string caption_text = getString("CaptionTextAcctInfo", args);
+ childSetValue("acc_status_text", caption_text);
}
-
-void LLPanelAvatar::resetGroupList()
+void LLPanelAvatarProfile::pay()
{
- // only get these updates asynchronously via the group floater, which works on the agent only
- if (mAvatarID != gAgent.getID())
- {
- return;
- }
-
- if (mPanelSecondLife)
- {
- LLScrollListCtrl* group_list = mPanelSecondLife->getChild<LLScrollListCtrl>("groups");
- if (group_list)
- {
- group_list->deleteAllItems();
-
- S32 count = gAgent.mGroups.count();
- LLUUID id;
-
- for(S32 i = 0; i < count; ++i)
- {
- LLGroupData group_data = gAgent.mGroups.get(i);
- id = group_data.mID;
- std::string group_string;
- /* Show group title? DUMMY_POWER for Don Grep
- if(group_data.mOfficer)
- {
- group_string = "Officer of ";
- }
- else
- {
- group_string = "Member of ";
- }
- */
-
- group_string += group_data.mName;
-
- LLSD row;
-
- row["id"] = id ;
- row["columns"][0]["value"] = group_string;
- row["columns"][0]["font"] = "SANSSERIF_SMALL";
- row["columns"][0]["width"] = 0;
- group_list->addElement(row);
- }
- group_list->sortByColumnIndex(0, TRUE);
- }
- }
+ LLAvatarActions::pay(getAvatarId());
}
-// static
-//-----------------------------------------------------------------------------
-// onClickIM()
-//-----------------------------------------------------------------------------
-void LLPanelAvatar::onClickIM(void* userdata)
+void LLPanelAvatarProfile::share()
{
- LLPanelAvatar* self = (LLPanelAvatar*) userdata;
- gIMMgr->setFloaterOpen(TRUE);
-
- std::string name;
- LLNameEditor* nameedit = self->mPanelSecondLife->getChild<LLNameEditor>("name");
- if (nameedit) name = nameedit->getText();
- gIMMgr->addSession(name, IM_NOTHING_SPECIAL, self->mAvatarID);
+ LLAvatarActions::share(getAvatarId());
}
-
-// static
-//-----------------------------------------------------------------------------
-// onClickTrack()
-//-----------------------------------------------------------------------------
-void LLPanelAvatar::onClickTrack(void* userdata)
+void LLPanelAvatarProfile::kick()
{
- LLPanelAvatar* self = (LLPanelAvatar*) userdata;
-
- if( gFloaterWorldMap )
- {
- std::string name;
- LLNameEditor* nameedit = self->mPanelSecondLife->getChild<LLNameEditor>("name");
- if (nameedit) name = nameedit->getText();
- gFloaterWorldMap->trackAvatar(self->mAvatarID, name);
- LLFloaterWorldMap::show(NULL, TRUE);
- }
+ LLAvatarActions::kick(getAvatarId());
}
-
-// static
-void LLPanelAvatar::onClickAddFriend(void* userdata)
+void LLPanelAvatarProfile::freeze()
{
- LLPanelAvatar* self = (LLPanelAvatar*) userdata;
- LLNameEditor* name_edit = self->mPanelSecondLife->getChild<LLNameEditor>("name");
- if (name_edit)
- {
- LLPanelFriends::requestFriendshipDialog(self->getAvatarID(),
- name_edit->getText());
- }
+ LLAvatarActions::freeze(getAvatarId());
}
-//-----------------------------------------------------------------------------
-// onClickMute()
-//-----------------------------------------------------------------------------
-void LLPanelAvatar::onClickMute(void *userdata)
+void LLPanelAvatarProfile::unfreeze()
{
- LLPanelAvatar* self = (LLPanelAvatar*) userdata;
-
- LLUUID agent_id = self->getAvatarID();
- LLNameEditor* name_edit = self->mPanelSecondLife->getChild<LLNameEditor>("name");
-
- if (name_edit)
- {
- std::string agent_name = name_edit->getText();
- LLFloaterMute::showInstance();
-
- if (LLMuteList::getInstance()->isMuted(agent_id))
- {
- LLFloaterMute::getInstance()->selectMute(agent_id);
- }
- else
- {
- LLMute mute(agent_id, agent_name, LLMute::AGENT);
- LLMuteList::getInstance()->add(mute);
- }
- }
+ LLAvatarActions::unfreeze(getAvatarId());
}
-
-// static
-void LLPanelAvatar::onClickOfferTeleport(void *userdata)
+void LLPanelAvatarProfile::csr()
{
- LLPanelAvatar* self = (LLPanelAvatar*) userdata;
-
- handle_lure(self->mAvatarID);
+ std::string name;
+ gCacheName->getFullName(getAvatarId(), name);
+ LLAvatarActions::csr(getAvatarId(), name);
}
-
-// static
-void LLPanelAvatar::onClickPay(void *userdata)
+void LLPanelAvatarProfile::onUrlTextboxClicked(const std::string& url)
{
- LLPanelAvatar* self = (LLPanelAvatar*) userdata;
- handle_pay_by_id(self->mAvatarID);
+ LLWeb::loadURL(url);
}
-
-// static
-void LLPanelAvatar::onClickOK(void *userdata)
+void LLPanelAvatarProfile::onHomepageTextboxClicked()
{
- LLPanelAvatar *self = (LLPanelAvatar *)userdata;
-
- // JC: Only save the data if we actually got the original
- // properties. Otherwise we might save blanks into
- // the database.
- if (self
- && self->mHaveProperties)
+ std::string url = childGetValue("homepage_edit").asString();
+ if(!url.empty())
{
- self->sendAvatarPropertiesUpdate();
-
- LLTabContainer* tabs = self->getChild<LLTabContainer>("tab");
- if ( tabs->getCurrentPanel() != self->mPanelClassified )
- {
- self->mPanelClassified->apply();
-
- LLFloaterAvatarInfo *infop = LLFloaterAvatarInfo::getInstance(self->mAvatarID);
- if (infop)
- {
- infop->close();
- }
- }
- else
- {
- if ( self->mPanelClassified->titleIsValid() )
- {
- self->mPanelClassified->apply();
-
- LLFloaterAvatarInfo *infop = LLFloaterAvatarInfo::getInstance(self->mAvatarID);
- if (infop)
- {
- infop->close();
- }
- }
- }
+ onUrlTextboxClicked(url);
}
}
-// static
-void LLPanelAvatar::onClickCancel(void *userdata)
+void LLPanelAvatarProfile::onAddFriendButtonClick()
{
- LLPanelAvatar *self = (LLPanelAvatar *)userdata;
-
- if (self)
- {
- LLFloaterAvatarInfo *infop;
- if ((infop = LLFloaterAvatarInfo::getInstance(self->mAvatarID)))
- {
- infop->close();
- }
- else
- {
- // We're in the Search directory and are cancelling an edit
- // to our own profile, so reset.
- self->sendAvatarPropertiesRequest();
- }
- }
+ LLAvatarActions::requestFriendshipDialog(getAvatarId());
}
-
-void LLPanelAvatar::sendAvatarPropertiesRequest()
+void LLPanelAvatarProfile::onIMButtonClick()
{
- lldebugs << "LLPanelAvatar::sendAvatarPropertiesRequest()" << llendl;
- 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, mAvatarID);
- gAgent.sendReliableMessage();
+ LLAvatarActions::startIM(getAvatarId());
}
-void LLPanelAvatar::sendAvatarNotesUpdate()
+void LLPanelAvatarProfile::onTeleportButtonClick()
{
- std::string notes = mPanelNotes->childGetValue("notes edit").asString();
-
- if (!mHaveNotes
- && (notes.empty() || notes == getString("Loading")))
- {
- // no notes from server and no user updates
- return;
- }
- if (notes == mLastNotes)
- {
- // Avatar notes unchanged
- return;
- }
-
- LLMessageSystem *msg = gMessageSystem;
-
- msg->newMessage("AvatarNotesUpdate");
- msg->nextBlock("AgentData");
- msg->addUUID("AgentID", gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlock("Data");
- msg->addUUID("TargetID", mAvatarID);
- msg->addString("Notes", notes);
-
- gAgent.sendReliableMessage();
+ LLAvatarActions::offerTeleport(getAvatarId());
}
-
-// static
-void LLPanelAvatar::processAvatarPropertiesReply(LLMessageSystem *msg, void**)
+void LLPanelAvatarProfile::onCallButtonClick()
{
- LLUUID agent_id; // your id
- LLUUID avatar_id; // target of this panel
- LLUUID image_id;
- LLUUID fl_image_id;
- LLUUID partner_id;
- std::string about_text;
- std::string fl_about_text;
- std::string born_on;
- S32 charter_member_size = 0;
- BOOL allow_publish = FALSE;
- //BOOL mature = FALSE;
- BOOL identified = FALSE;
- BOOL transacted = FALSE;
- BOOL age_verified = FALSE;
- BOOL online = FALSE;
- std::string profile_url;
-
- U32 flags = 0x0;
-
- //llinfos << "properties packet size " << msg->getReceiveSize() << llendl;
-
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AvatarID, avatar_id );
-
- for (panel_list_t::iterator iter = sAllPanels.begin(); iter != sAllPanels.end(); ++iter)
- {
- LLPanelAvatar* self = *iter;
- if (self->mAvatarID != avatar_id)
- {
- continue;
- }
- self->childSetEnabled("Instant Message...",TRUE);
- self->childSetEnabled("Pay...",TRUE);
- self->childSetEnabled("Mute",TRUE);
-
- self->childSetEnabled("drop target",TRUE);
-
- self->mHaveProperties = TRUE;
- self->enableOKIfReady();
-
- msg->getUUIDFast( _PREHASH_PropertiesData, _PREHASH_ImageID, image_id );
- msg->getUUIDFast( _PREHASH_PropertiesData, _PREHASH_FLImageID, fl_image_id );
- msg->getUUIDFast(_PREHASH_PropertiesData, _PREHASH_PartnerID, partner_id);
- msg->getStringFast(_PREHASH_PropertiesData, _PREHASH_AboutText, about_text );
- msg->getStringFast(_PREHASH_PropertiesData, _PREHASH_FLAboutText, fl_about_text );
- msg->getStringFast(_PREHASH_PropertiesData, _PREHASH_BornOn, born_on);
- msg->getString("PropertiesData","ProfileURL", profile_url);
- msg->getU32Fast(_PREHASH_PropertiesData, _PREHASH_Flags, flags);
-
- identified = (flags & AVATAR_IDENTIFIED);
- transacted = (flags & AVATAR_TRANSACTED);
- age_verified = (flags & AVATAR_AGEVERIFIED); // Not currently getting set in dataserver/lldataavatar.cpp for privacy considerations
- allow_publish = (flags & AVATAR_ALLOW_PUBLISH);
- online = (flags & AVATAR_ONLINE);
-
- U8 caption_index = 0;
- std::string caption_text;
- charter_member_size = msg->getSize("PropertiesData", "CharterMember");
- if(1 == charter_member_size)
- {
- msg->getBinaryData("PropertiesData", "CharterMember", &caption_index, 1);
- }
- else if(1 < charter_member_size)
- {
- msg->getString("PropertiesData", "CharterMember", caption_text);
- }
-
-
- if(caption_text.empty())
- {
- LLStringUtil::format_map_t args;
- caption_text = self->mPanelSecondLife->getString("CaptionTextAcctInfo");
-
- const char* ACCT_TYPE[] = {
- "AcctTypeResident",
- "AcctTypeTrial",
- "AcctTypeCharterMember",
- "AcctTypeEmployee"
- };
- caption_index = llclamp(caption_index, (U8)0, (U8)(LL_ARRAY_SIZE(ACCT_TYPE)-1));
- args["[ACCTTYPE]"] = self->mPanelSecondLife->getString(ACCT_TYPE[caption_index]);
-
- std::string payment_text = " ";
- const S32 DEFAULT_CAPTION_LINDEN_INDEX = 3;
- if(caption_index != DEFAULT_CAPTION_LINDEN_INDEX)
- {
- if(transacted)
- {
- payment_text = "PaymentInfoUsed";
- }
- else if (identified)
- {
- payment_text = "PaymentInfoOnFile";
- }
- else
- {
- payment_text = "NoPaymentInfoOnFile";
- }
- args["[PAYMENTINFO]"] = self->mPanelSecondLife->getString(payment_text);
- std::string age_text = age_verified ? "AgeVerified" : "NotAgeVerified";
- // Do not display age verification status at this time
- //args["[[AGEVERIFICATION]]"] = self->mPanelSecondLife->getString(age_text);
- args["[AGEVERIFICATION]"] = " ";
- }
- else
- {
- args["[PAYMENTINFO]"] = " ";
- args["[AGEVERIFICATION]"] = " ";
- }
- LLStringUtil::format(caption_text, args);
- }
-
- self->mPanelSecondLife->childSetValue("acct", caption_text);
- self->mPanelSecondLife->childSetValue("born", born_on);
-
- EOnlineStatus online_status = (online) ? ONLINE_STATUS_YES : ONLINE_STATUS_NO;
-
- self->setOnlineStatus(online_status);
-
- self->mPanelWeb->setWebURL(profile_url);
-
- LLTextureCtrl* image_ctrl = self->mPanelSecondLife->getChild<LLTextureCtrl>("img");
- if(image_ctrl)
- {
- image_ctrl->setImageAssetID(image_id);
- }
- self->childSetValue("about", about_text);
-
- self->mPanelSecondLife->setPartnerID(partner_id);
- self->mPanelSecondLife->updatePartnerName();
-
- if (self->mPanelFirstLife)
- {
- // Teens don't get these
- self->mPanelFirstLife->childSetValue("about", fl_about_text);
- LLTextureCtrl* image_ctrl = self->mPanelFirstLife->getChild<LLTextureCtrl>("img");
- if(image_ctrl)
- {
- image_ctrl->setImageAssetID(fl_image_id);
- }
-
- self->mPanelSecondLife->childSetValue("allow_publish", allow_publish);
-
- }
- }
+ LLAvatarActions::startCall(getAvatarId());
}
-// static
-void LLPanelAvatar::processAvatarInterestsReply(LLMessageSystem *msg, void**)
+void LLPanelAvatarProfile::onShareButtonClick()
{
- LLUUID agent_id; // your id
- LLUUID avatar_id; // target of this panel
-
- U32 want_to_mask;
- std::string want_to_text;
- U32 skills_mask;
- std::string skills_text;
- std::string languages_text;
-
- //llinfos << "properties packet size " << msg->getReceiveSize() << llendl;
-
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AvatarID, avatar_id );
-
- for (panel_list_t::iterator iter = sAllPanels.begin(); iter != sAllPanels.end(); ++iter)
- {
- LLPanelAvatar* self = *iter;
- if (self->mAvatarID != avatar_id)
- {
- continue;
- }
-
- msg->getU32Fast( _PREHASH_PropertiesData, _PREHASH_WantToMask, want_to_mask );
- msg->getStringFast(_PREHASH_PropertiesData, _PREHASH_WantToText, want_to_text );
- msg->getU32Fast( _PREHASH_PropertiesData, _PREHASH_SkillsMask, skills_mask );
- msg->getStringFast(_PREHASH_PropertiesData, _PREHASH_SkillsText, skills_text );
- msg->getString(_PREHASH_PropertiesData, "LanguagesText", languages_text );
-
- self->mPanelAdvanced->setWantSkills(want_to_mask, want_to_text, skills_mask, skills_text, languages_text);
- }
+ //*TODO not implemented
}
-// Separate function because the groups list can be very long, almost
-// filling a packet. JC
-// static
-void LLPanelAvatar::processAvatarGroupsReply(LLMessageSystem *msg, void**)
+void LLPanelAvatarProfile::onOverflowButtonClicked()
{
- LLUUID agent_id; // your id
- LLUUID avatar_id; // target of this panel
- U64 group_powers;
- std::string group_title;
- LLUUID group_id;
- std::string group_name;
- LLUUID group_insignia_id;
-
- llinfos << "groups packet size " << msg->getReceiveSize() << llendl;
+ if (!mProfileMenu->toggleVisibility())
+ return;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AvatarID, avatar_id );
+ LLView* btn = getChild<LLView>("overflow_btn");
- for (panel_list_t::iterator iter = sAllPanels.begin(); iter != sAllPanels.end(); ++iter)
+ if (mProfileMenu->getButtonRect().isEmpty())
{
- LLPanelAvatar* self = *iter;
- if (self->mAvatarID != avatar_id)
- {
- continue;
- }
-
- LLScrollListCtrl* group_list = self->mPanelSecondLife->getChild<LLScrollListCtrl>("groups");
-// if(group_list)
-// {
-// group_list->deleteAllItems();
-// }
-
- S32 group_count = msg->getNumberOfBlocksFast(_PREHASH_GroupData);
- if (0 == group_count)
- {
- if(group_list) group_list->addCommentText(std::string("None")); // *TODO: Translate
- }
- else
- {
- for(S32 i = 0; i < group_count; ++i)
- {
- msg->getU64( _PREHASH_GroupData, "GroupPowers", group_powers, i );
- msg->getStringFast(_PREHASH_GroupData, _PREHASH_GroupTitle, group_title, i );
- msg->getUUIDFast( _PREHASH_GroupData, _PREHASH_GroupID, group_id, i);
- msg->getStringFast(_PREHASH_GroupData, _PREHASH_GroupName, group_name, i );
- msg->getUUIDFast( _PREHASH_GroupData, _PREHASH_GroupInsigniaID, group_insignia_id, i );
-
- std::string group_string;
- if (group_id.notNull())
- {
- group_string.assign(group_name);
- }
- else
- {
- group_string.assign("");
- }
-
- // Is this really necessary? Remove existing entry if it exists.
- // TODO: clear the whole list when a request for data is made
- if (group_list)
- {
- S32 index = group_list->getItemIndex(group_id);
- if ( index >= 0 )
- {
- group_list->deleteSingleItem(index);
- }
- }
-
- LLSD row;
- row["id"] = group_id;
- row["columns"][0]["value"] = group_string;
- row["columns"][0]["font"] = "SANSSERIF_SMALL";
- if (group_list)
- {
- group_list->addElement(row);
- }
- }
- }
- if(group_list) group_list->sortByColumnIndex(0, TRUE);
+ mProfileMenu->setButtonRect(btn);
}
+ mProfileMenu->updateParent(LLMenuGL::sMenuContainer);
+
+ LLRect rect = btn->getRect();
+ LLMenuGL::showPopup(this, mProfileMenu, rect.mRight, rect.mTop);
}
-// Don't enable the OK button until you actually have the data.
-// Otherwise you will write blanks back into the database.
-void LLPanelAvatar::enableOKIfReady()
+LLPanelAvatarProfile::~LLPanelAvatarProfile()
{
- if(mHaveProperties && childIsVisible("OK"))
+ if(getAvatarId().notNull())
{
- childSetEnabled("OK", TRUE);
- }
- else
- {
- childSetEnabled("OK", FALSE);
+ LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this);
+ if(LLVoiceClient::getInstance())
+ LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this);
}
}
-void LLPanelAvatar::sendAvatarPropertiesUpdate()
+// virtual, called by LLAvatarTracker
+void LLPanelAvatarProfile::changed(U32 mask)
{
- llinfos << "Sending avatarinfo update" << llendl;
- BOOL allow_publish = FALSE;
- BOOL mature = FALSE;
- if (LLPanelAvatar::sAllowFirstLife)
- {
- allow_publish = childGetValue("allow_publish");
- //A profile should never be mature.
- mature = FALSE;
- }
- U32 want_to_mask = 0x0;
- U32 skills_mask = 0x0;
- std::string want_to_text;
- std::string skills_text;
- std::string languages_text;
- mPanelAdvanced->getWantSkills(&want_to_mask, want_to_text, &skills_mask, skills_text, languages_text);
-
- LLUUID first_life_image_id;
- std::string first_life_about_text;
- if (mPanelFirstLife)
- {
- first_life_about_text = mPanelFirstLife->childGetValue("about").asString();
- LLTextureCtrl* image_ctrl = mPanelFirstLife->getChild<LLTextureCtrl>("img");
- if(image_ctrl)
- {
- first_life_image_id = image_ctrl->getImageAssetID();
- }
- }
-
- std::string about_text = mPanelSecondLife->childGetValue("about").asString();
-
- LLMessageSystem *msg = gMessageSystem;
-
- msg->newMessageFast(_PREHASH_AvatarPropertiesUpdate);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast( _PREHASH_AgentID, gAgent.getID() );
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
- msg->nextBlockFast(_PREHASH_PropertiesData);
-
- LLTextureCtrl* image_ctrl = mPanelSecondLife->getChild<LLTextureCtrl>("img");
- if(image_ctrl)
- {
- msg->addUUIDFast( _PREHASH_ImageID, image_ctrl->getImageAssetID());
- }
- else
- {
- msg->addUUIDFast( _PREHASH_ImageID, LLUUID::null);
- }
-// msg->addUUIDFast( _PREHASH_ImageID, mPanelSecondLife->mimage_ctrl->getImageAssetID() );
- msg->addUUIDFast( _PREHASH_FLImageID, first_life_image_id);
- msg->addStringFast( _PREHASH_AboutText, about_text);
- msg->addStringFast( _PREHASH_FLAboutText, first_life_about_text);
-
- msg->addBOOL("AllowPublish", allow_publish);
- msg->addBOOL("MaturePublish", mature);
- msg->addString("ProfileURL", mPanelWeb->childGetText("url_edit"));
- gAgent.sendReliableMessage();
-
- msg->newMessage("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, want_to_mask);
- msg->addStringFast( _PREHASH_WantToText, want_to_text);
- msg->addU32Fast( _PREHASH_SkillsMask, skills_mask);
- msg->addStringFast( _PREHASH_SkillsText, skills_text);
- msg->addString( "LanguagesText", languages_text);
- gAgent.sendReliableMessage();
-}
-
-void LLPanelAvatar::selectTab(S32 tabnum)
-{
- if(mTab)
- {
- mTab->selectTab(tabnum);
- }
+ childSetEnabled("teleport", LLAvatarTracker::instance().isBuddyOnline(getAvatarId()));
}
-void LLPanelAvatar::selectTabByName(std::string tab_name)
+// virtual
+void LLPanelAvatarProfile::onChange(EStatusType status, const std::string &channelURI, bool proximal)
{
- if (mTab)
+ if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL)
{
- if (tab_name.empty())
- {
- mTab->selectFirstTab();
- }
- else
- {
- mTab->selectTabByName(tab_name);
- }
+ return;
}
-}
+ childSetEnabled("call", LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking());
+}
-void LLPanelAvatar::processAvatarNotesReply(LLMessageSystem *msg, void**)
+void LLPanelAvatarProfile::setAvatarId(const LLUUID& id)
{
- // extract the agent id
- LLUUID agent_id;
- msg->getUUID("AgentData", "AgentID", agent_id);
-
- LLUUID target_id;
- msg->getUUID("Data", "TargetID", target_id);
-
- // look up all panels which have this avatar
- for (panel_list_t::iterator iter = sAllPanels.begin(); iter != sAllPanels.end(); ++iter)
+ if(id.notNull())
{
- LLPanelAvatar* self = *iter;
- if (self->mAvatarID != target_id)
+ if(getAvatarId().notNull())
{
- continue;
+ LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this);
}
-
- std::string text;
- msg->getString("Data", "Notes", text);
- self->childSetValue("notes edit", text);
- self->childSetEnabled("notes edit", true);
- self->mHaveNotes = true;
- self->mLastNotes = text;
+ LLPanelProfileTab::setAvatarId(id);
+ LLAvatarTracker::instance().addParticularFriendObserver(getAvatarId(), this);
}
}
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
-void LLPanelAvatar::processAvatarClassifiedReply(LLMessageSystem *msg, void** userdata)
+LLPanelMyProfile::LLPanelMyProfile()
+: LLPanelAvatarProfile()
{
- LLUUID agent_id;
- LLUUID target_id;
-
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TargetID, target_id);
-
- // look up all panels which have this avatar target
- for (panel_list_t::iterator iter = sAllPanels.begin(); iter != sAllPanels.end(); ++iter)
- {
- LLPanelAvatar* self = *iter;
- if (self->mAvatarID != target_id)
- {
- continue;
- }
-
- self->mPanelClassified->processAvatarClassifiedReply(msg, userdata);
- }
}
-void LLPanelAvatar::processAvatarPicksReply(LLMessageSystem *msg, void** userdata)
+BOOL LLPanelMyProfile::postBuild()
{
- LLUUID agent_id;
- LLUUID target_id;
+ LLPanelAvatarProfile::postBuild();
- msg->getUUID("AgentData", "AgentID", agent_id);
- msg->getUUID("AgentData", "TargetID", target_id);
+ mStatusCombobox = getChild<LLComboBox>("status_combo");
- // look up all panels which have this avatar target
- for (panel_list_t::iterator iter = sAllPanels.begin(); iter != sAllPanels.end(); ++iter)
- {
- LLPanelAvatar* self = *iter;
- if (self->mAvatarID != target_id)
- {
- continue;
- }
+ childSetCommitCallback("status_combo", boost::bind(&LLPanelMyProfile::onStatusChanged, this), NULL);
+ childSetCommitCallback("status_me_message_text", boost::bind(&LLPanelMyProfile::onStatusMessageChanged, this), NULL);
- self->mPanelPicks->processAvatarPicksReply(msg, userdata);
- }
-}
-
-// static
-void LLPanelAvatar::onClickKick(void* userdata)
-{
- LLPanelAvatar* self = (LLPanelAvatar*) userdata;
-
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- LLRect rect(left, top, left+400, top-300);
+ resetControls();
+ resetData();
- LLSD payload;
- payload["avatar_id"] = self->mAvatarID;
- LLNotifications::instance().add("KickUser", LLSD(), payload, finishKick);
+ return TRUE;
}
-//static
-bool LLPanelAvatar::finishKick(const LLSD& notification, const LLSD& response)
+void LLPanelMyProfile::onOpen(const LLSD& key)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
-
- if (option == 0)
- {
- LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
- LLMessageSystem* msg = gMessageSystem;
-
- msg->newMessageFast(_PREHASH_GodKickUser);
- msg->nextBlockFast(_PREHASH_UserInfo);
- msg->addUUIDFast(_PREHASH_GodID, gAgent.getID() );
- msg->addUUIDFast(_PREHASH_GodSessionID, gAgent.getSessionID());
- msg->addUUIDFast(_PREHASH_AgentID, avatar_id );
- msg->addU32("KickFlags", KICK_FLAGS_DEFAULT );
- msg->addStringFast(_PREHASH_Reason, response["message"].asString() );
- gAgent.sendReliableMessage();
- }
- return false;
+ LLPanelProfileTab::onOpen(key);
}
-// static
-void LLPanelAvatar::onClickFreeze(void* userdata)
+void LLPanelMyProfile::processProfileProperties(const LLAvatarData* avatar_data)
{
- LLPanelAvatar* self = (LLPanelAvatar*) userdata;
- LLSD payload;
- payload["avatar_id"] = self->mAvatarID;
- LLNotifications::instance().add("FreezeUser", LLSD(), payload, LLPanelAvatar::finishFreeze);
-}
+ fillCommonData(avatar_data);
-// static
-bool LLPanelAvatar::finishFreeze(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ fillPartnerData(avatar_data);
- if (option == 0)
- {
- LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
- LLMessageSystem* msg = gMessageSystem;
-
- msg->newMessageFast(_PREHASH_GodKickUser);
- msg->nextBlockFast(_PREHASH_UserInfo);
- msg->addUUIDFast(_PREHASH_GodID, gAgent.getID() );
- msg->addUUIDFast(_PREHASH_GodSessionID, gAgent.getSessionID());
- msg->addUUIDFast(_PREHASH_AgentID, avatar_id );
- msg->addU32("KickFlags", KICK_FLAGS_FREEZE );
- msg->addStringFast(_PREHASH_Reason, response["message"].asString() );
- gAgent.sendReliableMessage();
- }
- return false;
-}
+ fillStatusData(avatar_data);
-// static
-void LLPanelAvatar::onClickUnfreeze(void* userdata)
-{
- LLPanelAvatar* self = (LLPanelAvatar*) userdata;
- LLSD payload;
- payload["avatar_id"] = self->mAvatarID;
- LLNotifications::instance().add("UnFreezeUser", LLSD(), payload, LLPanelAvatar::finishUnfreeze);
+ fillAccountStatus(avatar_data);
}
-// static
-bool LLPanelAvatar::finishUnfreeze(const LLSD& notification, const LLSD& response)
+void LLPanelMyProfile::fillStatusData(const LLAvatarData* avatar_data)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
- std::string text = response["message"].asString();
- if (option == 0)
+ std::string status;
+ if (gAgent.getAFK())
{
- LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
- LLMessageSystem* msg = gMessageSystem;
-
- msg->newMessageFast(_PREHASH_GodKickUser);
- msg->nextBlockFast(_PREHASH_UserInfo);
- msg->addUUIDFast(_PREHASH_GodID, gAgent.getID() );
- msg->addUUIDFast(_PREHASH_GodSessionID, gAgent.getSessionID());
- msg->addUUIDFast(_PREHASH_AgentID, avatar_id );
- msg->addU32("KickFlags", KICK_FLAGS_UNFREEZE );
- msg->addStringFast(_PREHASH_Reason, text );
- gAgent.sendReliableMessage();
+ status = "away";
}
- return false;
-}
-
-// static
-void LLPanelAvatar::onClickCSR(void* userdata)
-{
- LLPanelAvatar* self = (LLPanelAvatar*)userdata;
- if (!self) return;
-
- LLNameEditor* name_edit = self->getChild<LLNameEditor>("name");
- if (!name_edit) return;
-
- std::string name = name_edit->getText();
- if (name.empty()) return;
-
- std::string url = "http://csr.lindenlab.com/agent/";
-
- // slow and stupid, but it's late
- S32 len = name.length();
- for (S32 i = 0; i < len; i++)
+ else if (gAgent.getBusy())
{
- if (name[i] == ' ')
- {
- url += "%20";
- }
- else
- {
- url += name[i];
- }
+ status = "busy";
+ }
+ else
+ {
+ status = "online";
}
-
- LLWeb::loadURL(url);
-}
-
-
-void* LLPanelAvatar::createPanelAvatarSecondLife(void* data)
-{
- LLPanelAvatar* self = (LLPanelAvatar*)data;
- self->mPanelSecondLife = new LLPanelAvatarSecondLife(std::string("2nd Life"),LLRect(),self);
- return self->mPanelSecondLife;
-}
-void* LLPanelAvatar::createPanelAvatarWeb(void* data)
-{
- LLPanelAvatar* self = (LLPanelAvatar*)data;
- self->mPanelWeb = new LLPanelAvatarWeb(std::string("Web"),LLRect(),self);
- return self->mPanelWeb;
+ mStatusCombobox->setValue(status);
}
-void* LLPanelAvatar::createPanelAvatarInterests(void* data)
+void LLPanelMyProfile::resetControls()
{
- LLPanelAvatar* self = (LLPanelAvatar*)data;
- self->mPanelAdvanced = new LLPanelAvatarAdvanced(std::string("Interests"),LLRect(),self);
- return self->mPanelAdvanced;
+ childSetVisible("status_panel", false);
+ childSetVisible("profile_buttons_panel", false);
+ childSetVisible("title_groups_text", false);
+ childSetVisible("sl_groups", false);
+ childSetVisible("status_me_panel", true);
+ childSetVisible("profile_me_buttons_panel", true);
}
-
-void* LLPanelAvatar::createPanelAvatarPicks(void* data)
+void LLPanelMyProfile::onStatusChanged()
{
- LLPanelAvatar* self = (LLPanelAvatar*)data;
- self->mPanelPicks = new LLPanelAvatarPicks(std::string("Picks"),LLRect(),self);
- return self->mPanelPicks;
-}
+ LLSD::String status = mStatusCombobox->getValue().asString();
-void* LLPanelAvatar::createPanelAvatarClassified(void* data)
-{
- LLPanelAvatar* self = (LLPanelAvatar*)data;
- self->mPanelClassified = new LLPanelAvatarClassified(std::string("Classified"),LLRect(),self);
- return self->mPanelClassified;
-}
-
-void* LLPanelAvatar::createPanelAvatarFirstLife(void* data)
-{
- LLPanelAvatar* self = (LLPanelAvatar*)data;
- self->mPanelFirstLife = new LLPanelAvatarFirstLife(std::string("1st Life"), LLRect(), self);
- return self->mPanelFirstLife;
+ if ("online" == status)
+ {
+ gAgent.clearAFK();
+ gAgent.clearBusy();
+ }
+ else if ("away" == status)
+ {
+ gAgent.clearBusy();
+ gAgent.setAFK();
+ }
+ else if ("busy" == status)
+ {
+ gAgent.clearAFK();
+ gAgent.setBusy();
+ LLNotificationsUtil::add("BusyModeSet");
+ }
}
-void* LLPanelAvatar::createPanelAvatarNotes(void* data)
+void LLPanelMyProfile::onStatusMessageChanged()
{
- LLPanelAvatar* self = (LLPanelAvatar*)data;
- self->mPanelNotes = new LLPanelAvatarNotes(std::string("My Notes"),LLRect(),self);
- return self->mPanelNotes;
+ updateData();
}
diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h
index 12e1b99360..ce59f1e93d 100644
--- a/indra/newview/llpanelavatar.h
+++ b/indra/newview/llpanelavatar.h
@@ -34,28 +34,13 @@
#define LL_LLPANELAVATAR_H
#include "llpanel.h"
-#include "v3dmath.h"
-#include "lluuid.h"
-#include "llwebbrowserctrl.h"
-
-class LLButton;
-class LLCheckBoxCtrl;
-class LLDropTarget;
-class LLInventoryItem;
+#include "llavatarpropertiesprocessor.h"
+#include "llcallingcard.h"
+#include "llvoiceclient.h"
+
+class LLComboBox;
class LLLineEditor;
-class LLNameEditor;
-class LLPanelAvatar;
-class LLScrollListCtrl;
-class LLTabContainer;
-class LLTextBox;
-class LLTextEditor;
-class LLTextureCtrl;
-class LLUICtrl;
-class LLViewerImage;
-class LLViewerObject;
-class LLMessageSystem;
-class LLIconCtrl;
-class LLWebBrowserCtrl;
+class LLToggleableMenu;
enum EOnlineStatus
{
@@ -63,321 +48,263 @@ enum EOnlineStatus
ONLINE_STATUS_YES = 1
};
-// Base class for all sub-tabs inside the avatar profile. Many of these
-// panels need to keep track of the parent panel (to get the avatar id)
-// and only request data from the database when they are first drawn. JC
-class LLPanelAvatarTab : public LLPanel
+/**
+* Base class for any Profile View or My Profile Panel.
+*/
+class LLPanelProfileTab
+ : public LLPanel
+ , public LLAvatarPropertiesObserver
{
public:
- LLPanelAvatarTab(const std::string& name, const LLRect &rect,
- LLPanelAvatar* panel_avatar);
- // Calls refresh() once per frame when panel is visible
- /*virtual*/ void draw();
+ /**
+ * Sets avatar ID, sets panel as observer of avatar related info replies from server.
+ */
+ virtual void setAvatarId(const LLUUID& id);
- LLPanelAvatar* getPanelAvatar() const { return mPanelAvatar; }
+ /**
+ * Returns avatar ID.
+ */
+ virtual const LLUUID& getAvatarId() { return mAvatarId; }
- void setDataRequested(bool requested) { mDataRequested = requested; }
- bool isDataRequested() const { return mDataRequested; }
+ /**
+ * Sends update data request to server.
+ */
+ virtual void updateData() = 0;
- // If the data for this tab has not yet been requested,
- // send the request. Used by tabs that are filled in only
- // when they are first displayed.
- // type is one of "avatarnotesrequest", "avatarpicksrequest",
- // or "avatarclassifiedsrequest"
- void sendAvatarProfileRequestIfNeeded(const std::string& method);
+ /**
+ * Clears panel data if viewing avatar info for first time and sends update data request.
+ */
+ virtual void onOpen(const LLSD& key);
-private:
- LLPanelAvatar* mPanelAvatar;
- bool mDataRequested;
-};
+ /**
+ * 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(){};
-class LLPanelAvatarFirstLife : public LLPanelAvatarTab
-{
-public:
- LLPanelAvatarFirstLife(const std::string& name, const LLRect &rect, LLPanelAvatar* panel_avatar);
+ /**
+ * Clears all data received from server.
+ */
+ virtual void resetData(){};
- /*virtual*/ BOOL postBuild(void);
+ /*virtual*/ ~LLPanelProfileTab();
- void enableControls(BOOL own_avatar);
-};
+protected:
+ LLPanelProfileTab();
+
+ /**
+ * Scrolls panel to top when viewing avatar info for first time.
+ */
+ void scrollToTop();
+
+ virtual void onMapButtonClick();
+
+ virtual void updateButtons();
-class LLPanelAvatarSecondLife
-: public LLPanelAvatarTab
-{
-public:
- LLPanelAvatarSecondLife(const std::string& name, const LLRect &rect, LLPanelAvatar* panel_avatar );
-
- /*virtual*/ BOOL postBuild(void);
- /*virtual*/ void refresh();
-
- static void onClickImage( void *userdata);
- static void onClickFriends( void *userdata);
- static void onDoubleClickGroup(void* userdata);
- static void onClickPublishHelp(void *userdata);
- static void onClickPartnerHelp(void *userdata);
- static bool onClickPartnerHelpLoadURL(const LLSD& notification, const LLSD& response);
- static void onClickPartnerInfo(void *userdata);
-
- // Clear out the controls anticipating new network data.
- void clearControls();
- void enableControls(BOOL own_avatar);
- void updateOnlineText(BOOL online, BOOL have_calling_card);
- void updatePartnerName();
-
- void setPartnerID(LLUUID id) { mPartnerID = id; }
-
private:
- LLUUID mPartnerID;
-};
+ LLUUID mAvatarId;
+};
-// WARNING! The order of the inheritance here matters!! Do not change. - KLW
-class LLPanelAvatarWeb :
- public LLPanelAvatarTab
- , public LLWebBrowserCtrlObserver
+/**
+* Panel for displaying Avatar's first and second life related info.
+*/
+class LLPanelAvatarProfile
+ : public LLPanelProfileTab
+ , public LLFriendObserver
+ , public LLVoiceClientStatusObserver
{
public:
- LLPanelAvatarWeb(const std::string& name, const LLRect& rect, LLPanelAvatar* panel_avatar);
- /*virtual*/ ~LLPanelAvatarWeb();
- /*virtual*/ BOOL postBuild(void);
-
- /*virtual*/ void refresh();
+ LLPanelAvatarProfile();
+ /*virtual*/ ~LLPanelAvatarProfile();
- void enableControls(BOOL own_avatar);
+ /*virtual*/ void onOpen(const LLSD& key);
- void setWebURL(std::string url);
+ /**
+ * LLFriendObserver trigger
+ */
+ virtual void changed(U32 mask);
- void load(std::string url);
- static void onURLKeystroke(LLLineEditor* editor, void* data);
- static void onCommitLoad(LLUICtrl* ctrl, void* data);
- static void onCommitURL(LLUICtrl* ctrl, void* data);
- static void onClickWebProfileHelp(void *);
+ // Implements LLVoiceClientStatusObserver::onChange() to enable the call
+ // button when voice is available
+ /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
- // browser observer impls
- virtual void onStatusTextChange( const EventType& eventIn );
- virtual void onLocationChange( const EventType& eventIn );
+ /*virtual*/ void setAvatarId(const LLUUID& id);
-private:
- std::string mHome;
- std::string mNavigateTo;
- LLWebBrowserCtrl* mWebBrowser;
-};
+ /**
+ * Processes data received from server.
+ */
+ /*virtual*/ void processProperties(void* data, EAvatarProcessorType type);
+ /*virtual*/ BOOL postBuild();
-class LLPanelAvatarAdvanced : public LLPanelAvatarTab
-{
-public:
- LLPanelAvatarAdvanced(const std::string& name, const LLRect& rect, LLPanelAvatar* panel_avatar);
+ /*virtual*/ void updateData();
- /*virtual*/ BOOL postBuild(void);
+ /*virtual*/ void resetControls();
- void enableControls(BOOL own_avatar);
- void setWantSkills(U32 want_to_mask, const std::string& want_to_text,
- U32 skills_mask, const std::string& skills_text,
- const std::string& languages_text);
- void getWantSkills(U32* want_to_mask, std::string& want_to_text,
- U32* skills_mask, std::string& skills_text,
- std::string& languages_text);
+ /*virtual*/ void resetData();
-private:
- S32 mWantToCount;
- S32 mSkillsCount;
- LLCheckBoxCtrl *mWantToCheck[8];
- LLLineEditor *mWantToEdit;
- LLCheckBoxCtrl *mSkillsCheck[8];
- LLLineEditor *mSkillsEdit;
-};
+protected:
+ /**
+ * Process profile related data received from server.
+ */
+ virtual void processProfileProperties(const LLAvatarData* avatar_data);
-class LLPanelAvatarNotes : public LLPanelAvatarTab
-{
-public:
- LLPanelAvatarNotes(const std::string& name, const LLRect& rect, LLPanelAvatar* panel_avatar);
+ /**
+ * Processes group related data received from server.
+ */
+ virtual void processGroupProperties(const LLAvatarGroups* avatar_groups);
- /*virtual*/ BOOL postBuild(void);
+ /**
+ * Fills common for Avatar profile and My Profile fields.
+ */
+ virtual void fillCommonData(const LLAvatarData* avatar_data);
- /*virtual*/ void refresh();
+ /**
+ * Fills partner data.
+ */
+ virtual void fillPartnerData(const LLAvatarData* avatar_data);
- void clearControls();
+ /**
+ * Fills account status.
+ */
+ virtual void fillAccountStatus(const LLAvatarData* avatar_data);
- static void onCommitNotes(LLUICtrl* field, void* userdata);
-};
+ /**
+ * Opens "Pay Resident" dialog.
+ */
+ void pay();
+ /**
+ * opens inventory and IM for sharing items
+ */
+ void share();
-class LLPanelAvatarClassified : public LLPanelAvatarTab
-{
-public:
- LLPanelAvatarClassified(const std::string& name, const LLRect& rect, LLPanelAvatar* panel_avatar);
+ void kick();
+ void freeze();
+ void unfreeze();
+ void csr();
+
- /*virtual*/ BOOL postBuild(void);
+ bool enableGod();
- /*virtual*/ void refresh();
- // If can close, return TRUE. If cannot close, pop save/discard dialog
- // and return FALSE.
- BOOL canClose();
+ void onUrlTextboxClicked(const std::string& url);
+ void onHomepageTextboxClicked();
+ void onAddFriendButtonClick();
+ void onIMButtonClick();
+ void onCallButtonClick();
+ void onTeleportButtonClick();
+ void onShareButtonClick();
+ void onOverflowButtonClicked();
- void apply();
+private:
- BOOL titleIsValid();
+ typedef std::map< std::string,LLUUID> group_map_t;
+ group_map_t mGroups;
- // Delete all the classified sub-panels from the tab container
- void deleteClassifiedPanels();
+ LLToggleableMenu* mProfileMenu;
+};
- // Unpack the outline of classified for this avatar (count, names, but not
- // actual data).
- void processAvatarClassifiedReply(LLMessageSystem* msg, void**);
+/**
+ * Panel for displaying own first and second life related info.
+ */
+class LLPanelMyProfile
+ : public LLPanelAvatarProfile
+{
+public:
+ LLPanelMyProfile();
-private:
- static void onClickNew(void* data);
- static void onClickDelete(void* data);
+ /*virtual*/ BOOL postBuild();
- bool callbackDelete(const LLSD& notification, const LLSD& response);
- bool callbackNew(const LLSD& notification, const LLSD& response);
-};
+protected:
+ /*virtual*/ void onOpen(const LLSD& key);
-class LLPanelAvatarPicks : public LLPanelAvatarTab
-{
-public:
- LLPanelAvatarPicks(const std::string& name, const LLRect& rect, LLPanelAvatar* panel_avatar);
+ /*virtual*/ void processProfileProperties(const LLAvatarData* avatar_data);
- /*virtual*/ BOOL postBuild(void);
+ /**
+ * Fills Avatar status data.
+ */
+ virtual void fillStatusData(const LLAvatarData* avatar_data);
- /*virtual*/ void refresh();
+ /*virtual*/ void resetControls();
- // Delete all the pick sub-panels from the tab container
- void deletePickPanels();
+protected:
- // Unpack the outline of picks for this avatar (count, names, but not
- // actual data).
- void processAvatarPicksReply(LLMessageSystem* msg, void**);
- void processAvatarClassifiedReply(LLMessageSystem* msg, void**);
+ void onStatusChanged();
+ void onStatusMessageChanged();
private:
- static void onClickNew(void* data);
- static void onClickDelete(void* data);
- bool callbackDelete(const LLSD& notification, const LLSD& response);
+ LLComboBox* mStatusCombobox;
};
-
-class LLPanelAvatar : public LLPanel
+/**
+* Panel for displaying Avatar's notes and modifying friend's rights.
+*/
+class LLPanelAvatarNotes
+ : public LLPanelProfileTab
+ , public LLFriendObserver
+ , public LLVoiceClientStatusObserver
{
public:
- LLPanelAvatar(const std::string& name, const LLRect &rect, BOOL allow_edit);
- /*virtual*/ ~LLPanelAvatar();
+ LLPanelAvatarNotes();
+ /*virtual*/ ~LLPanelAvatarNotes();
- /*virtual*/ BOOL postBuild(void);
+ virtual void setAvatarId(const LLUUID& id);
- // If can close, return TRUE. If cannot close, pop save/discard dialog
- // and return FALSE.
- BOOL canClose();
+ /**
+ * LLFriendObserver trigger
+ */
+ virtual void changed(U32 mask);
- void setAvatar(LLViewerObject *avatarp);
+ // Implements LLVoiceClientStatusObserver::onChange() to enable the call
+ // button when voice is available
+ /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
- // Fill in the avatar ID and handle some field fill-in, as well as
- // button enablement.
- // Pass one of the ONLINE_STATUS_foo constants above.
- void setAvatarID(const LLUUID &avatar_id, const std::string &name, EOnlineStatus online_status);
+ /*virtual*/ void onOpen(const LLSD& key);
- void setOnlineStatus(EOnlineStatus online_status);
+ /*virtual*/ BOOL postBuild();
- const LLUUID& getAvatarID() const { return mAvatarID; }
-
- void resetGroupList();
+ /*virtual*/ void processProperties(void* data, EAvatarProcessorType type);
- void sendAvatarStatisticsRequest();
+ /*virtual*/ void updateData();
- void sendAvatarPropertiesRequest();
- void sendAvatarPropertiesUpdate();
+protected:
- void sendAvatarNotesRequest();
- void sendAvatarNotesUpdate();
+ /*virtual*/ void resetControls();
- void sendAvatarPicksRequest();
+ /*virtual*/ void resetData();
- void selectTab(S32 tabnum);
- void selectTabByName(std::string tab_name);
+ /**
+ * Fills rights data for friends.
+ */
+ void fillRightsData();
- BOOL haveData() { return mHaveProperties && mHaveStatistics; }
- BOOL isEditable() const { return mAllowEdit; }
+ void rightsConfirmationCallback(const LLSD& notification,
+ const LLSD& response, S32 rights);
+ void confirmModifyRights(bool grant, S32 rights);
+ void onCommitRights();
+ void onCommitNotes();
- static void processAvatarPropertiesReply(LLMessageSystem *msg, void **);
- static void processAvatarInterestsReply(LLMessageSystem *msg, void **);
- static void processAvatarGroupsReply(LLMessageSystem* msg, void**);
- static void processAvatarNotesReply(LLMessageSystem *msg, void **);
- static void processAvatarPicksReply(LLMessageSystem *msg, void **);
- static void processAvatarClassifiedReply(LLMessageSystem *msg, void **);
-
- static void onClickTrack( void *userdata);
- static void onClickIM( void *userdata);
- static void onClickOfferTeleport( void *userdata);
- static void onClickPay( void *userdata);
- static void onClickAddFriend(void* userdata);
- static void onClickOK( void *userdata);
- static void onClickCancel( void *userdata);
- static void onClickKick( void *userdata);
- static void onClickFreeze( void *userdata);
- static void onClickUnfreeze(void *userdata);
- static void onClickCSR( void *userdata);
- static void onClickMute( void *userdata);
-
-private:
- void enableOKIfReady();
-
- static bool finishKick(const LLSD& notification, const LLSD& response);
- static bool finishFreeze(const LLSD& notification, const LLSD& response);
- static bool finishUnfreeze(const LLSD& notification, const LLSD& response);
-
- static void showProfileCallback(S32 option, void *userdata);
-
- static void* createPanelAvatar(void* data);
- static void* createFloaterAvatarInfo(void* data);
- static void* createPanelAvatarSecondLife(void* data);
- static void* createPanelAvatarWeb(void* data);
- static void* createPanelAvatarInterests(void* data);
- static void* createPanelAvatarPicks(void* data);
- static void* createPanelAvatarClassified(void* data);
- static void* createPanelAvatarFirstLife(void* data);
- static void* createPanelAvatarNotes(void* data);
-
-public:
- LLPanelAvatarSecondLife* mPanelSecondLife;
- LLPanelAvatarAdvanced* mPanelAdvanced;
- LLPanelAvatarClassified* mPanelClassified;
- LLPanelAvatarPicks* mPanelPicks;
- LLPanelAvatarNotes* mPanelNotes;
- LLPanelAvatarFirstLife* mPanelFirstLife;
- LLPanelAvatarWeb* mPanelWeb;
-
- LLDropTarget* mDropTarget;
-
- // Teen users are not allowed to see or enter data into the first life page,
- // or their own about/interests text entry fields.
- static BOOL sAllowFirstLife;
-
-private:
- LLUUID mAvatarID; // for which avatar is this window?
- BOOL mIsFriend; // Are we friends?
- BOOL mHaveProperties;
- BOOL mHaveStatistics;
- // only update note if data received from database and
- // note is changed from database version
- bool mHaveNotes;
- std::string mLastNotes;
- LLTabContainer* mTab;
- BOOL mAllowEdit;
-
- typedef std::list<LLPanelAvatar*> panel_list_t;
- static panel_list_t sAllPanels;
+ void onAddFriendButtonClick();
+ void onIMButtonClick();
+ void onCallButtonClick();
+ void onTeleportButtonClick();
+ void onShareButtonClick();
};
-// helper funcs
-void add_left_label(LLPanel *panel, const std::string& name, S32 y);
-
-
#endif // LL_LLPANELAVATAR_H
diff --git a/indra/newview/llpanelavatartag.cpp b/indra/newview/llpanelavatartag.cpp
new file mode 100644
index 0000000000..7563cc7f61
--- /dev/null
+++ b/indra/newview/llpanelavatartag.cpp
@@ -0,0 +1,107 @@
+/**
+ * @file llpanelavatartag.cpp
+ * @brief Avatar tag panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelavatartag.h"
+
+#include "lluictrlfactory.h"
+#include "llavatariconctrl.h"
+#include "lltextbox.h"
+
+LLPanelAvatarTag::LLPanelAvatarTag(const LLUUID& key, const std::string im_time)
+ : LLPanel()
+ , mAvatarId(LLUUID::null)
+// , mFadeTimer()
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_avatar_tag.xml");
+ setLeftButtonClickCallback(boost::bind(&LLPanelAvatarTag::onClick, this));
+ setAvatarId(key);
+ setTime(im_time);
+}
+
+LLPanelAvatarTag::~LLPanelAvatarTag()
+{
+ // Name callbacks will be automatically disconnected since LLPanel is trackable
+}
+
+BOOL LLPanelAvatarTag::postBuild()
+{
+ mIcon = getChild<LLAvatarIconCtrl>("avatar_tag_icon");
+ mName = getChild<LLTextBox>("sender_tag_name");
+ mTime = getChild<LLTextBox>("tag_time");
+ return TRUE;
+}
+
+void LLPanelAvatarTag::draw()
+{
+
+}
+void LLPanelAvatarTag::setName(const std::string& name)
+{
+ if (mName)
+ mName->setText(name);
+}
+
+void LLPanelAvatarTag::setTime(const std::string& time)
+{
+ if (mTime)
+ mTime->setText(time);
+}
+
+
+void LLPanelAvatarTag::setAvatarId(const LLUUID& avatar_id)
+{
+ mAvatarId = avatar_id;
+ if (mIcon)
+ {
+ mIcon->setValue(avatar_id);
+ }
+ setName(std::string(mIcon->getFirstName()+ " "+ mIcon->getLastName()));
+}
+
+boost::signals2::connection LLPanelAvatarTag::setLeftButtonClickCallback(
+ const commit_callback_t& cb)
+{
+ return setCommitCallback(cb);
+}
+
+BOOL LLPanelAvatarTag::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ onCommit();
+ return TRUE;
+}
+
+void LLPanelAvatarTag::onClick()
+{
+ // Do the on click stuff.
+}
diff --git a/indra/newview/llpanelavatartag.h b/indra/newview/llpanelavatartag.h
new file mode 100644
index 0000000000..d68b0d7299
--- /dev/null
+++ b/indra/newview/llpanelavatartag.h
@@ -0,0 +1,93 @@
+/**
+ * @file llpanelavatartag.h
+ * @brief Avatar row panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELAVATARTAG_H
+#define LL_LLPANELAVATARTAG_H
+
+#include "llpanel.h"
+#include "llavatarpropertiesprocessor.h"
+
+class LLAvatarIconCtrl;
+class LLTextBox;
+
+/**
+ * Avatar Tag panel.
+ *
+ * Test.
+ *
+ * Contains avatar name
+ * Provide methods for setting avatar id, state, muted status and speech power.
+ */
+class LLPanelAvatarTag : public LLPanel
+{
+public:
+ LLPanelAvatarTag(const LLUUID& key, const std::string im_time);
+ virtual ~LLPanelAvatarTag();
+
+ /**
+ * Set avatar ID.
+ *
+ * After the ID is set, it is possible to track the avatar status and get its name.
+ */
+ void setAvatarId(const LLUUID& avatar_id);
+ void setTime (const std::string& time);
+
+ const LLUUID& getAvatarId() const { return mAvatarId; }
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void draw();
+
+ virtual boost::signals2::connection setLeftButtonClickCallback(
+ const commit_callback_t& cb);
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+
+ void onClick();
+private:
+ void setName(const std::string& name);
+
+ /**
+ * Called by LLCacheName when the avatar name gets updated.
+ */
+ void nameUpdatedCallback(
+ const LLUUID& id,
+ const std::string& first,
+ const std::string& last,
+ BOOL is_group);
+
+ LLAvatarIconCtrl* mIcon; /// status tracking avatar icon
+ LLTextBox* mName; /// displays avatar name
+ LLTextBox* mTime; /// displays time
+ LLUUID mAvatarId;
+// LLFrameTimer mFadeTimer;
+};
+
+#endif
diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp
new file mode 100644
index 0000000000..362657a458
--- /dev/null
+++ b/indra/newview/llpanelblockedlist.cpp
@@ -0,0 +1,280 @@
+/**
+ * @file llpanelblockedlist.cpp
+ * @brief Container for blocked Residents & Objects list
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelblockedlist.h"
+
+// library include
+#include "llfloater.h"
+#include "llfloaterreg.h"
+#include "llnotificationsutil.h"
+#include "llscrolllistctrl.h"
+
+// project include
+#include "llfloateravatarpicker.h"
+#include "llsidetray.h"
+#include "llsidetraypanelcontainer.h"
+
+static LLRegisterPanelClassWrapper<LLPanelBlockedList> t_panel_blocked_list("panel_block_list_sidetray");
+
+//
+// Constants
+//
+const std::string BLOCKED_PARAM_NAME = "blocked_to_select";
+
+//-----------------------------------------------------------------------------
+// LLPanelBlockedList()
+//-----------------------------------------------------------------------------
+
+LLPanelBlockedList::LLPanelBlockedList()
+: LLPanel()
+{
+ mCommitCallbackRegistrar.add("Block.ClickPick", boost::bind(&LLPanelBlockedList::onPickBtnClick, this));
+ mCommitCallbackRegistrar.add("Block.ClickBlockByName", boost::bind(&LLPanelBlockedList::onBlockByNameClick, this));
+ mCommitCallbackRegistrar.add("Block.ClickRemove", boost::bind(&LLPanelBlockedList::onRemoveBtnClick, this));
+}
+
+LLPanelBlockedList::~LLPanelBlockedList()
+{
+ LLMuteList::getInstance()->removeObserver(this);
+}
+
+BOOL LLPanelBlockedList::postBuild()
+{
+ mBlockedList = getChild<LLScrollListCtrl>("blocked");
+ mBlockedList->setCommitOnSelectionChange(TRUE);
+
+ childSetCommitCallback("back", boost::bind(&LLPanelBlockedList::onBackBtnClick, this), NULL);
+
+ LLMuteList::getInstance()->addObserver(this);
+
+ refreshBlockedList();
+
+ return LLPanel::postBuild();
+}
+
+void LLPanelBlockedList::draw()
+{
+ updateButtons();
+ LLPanel::draw();
+}
+
+void LLPanelBlockedList::onOpen(const LLSD& key)
+{
+ if (key.has(BLOCKED_PARAM_NAME) && key[BLOCKED_PARAM_NAME].asUUID().notNull())
+ {
+ selectBlocked(key[BLOCKED_PARAM_NAME].asUUID());
+ }
+}
+
+void LLPanelBlockedList::selectBlocked(const LLUUID& mute_id)
+{
+ mBlockedList->selectByID(mute_id);
+}
+
+void LLPanelBlockedList::showPanelAndSelect(const LLUUID& idToSelect)
+{
+ LLSideTray::getInstance()->showPanel("panel_block_list_sidetray", LLSD().with(BLOCKED_PARAM_NAME, idToSelect));
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// Private Section
+//////////////////////////////////////////////////////////////////////////
+void LLPanelBlockedList::refreshBlockedList()
+{
+ mBlockedList->deleteAllItems();
+
+ std::vector<LLMute> mutes = LLMuteList::getInstance()->getMutes();
+ std::vector<LLMute>::iterator it;
+ for (it = mutes.begin(); it != mutes.end(); ++it)
+ {
+ std::string display_name = it->getDisplayName();
+ mBlockedList->addStringUUIDItem(display_name, it->mID, ADD_BOTTOM, TRUE);
+ }
+}
+
+void LLPanelBlockedList::updateButtons()
+{
+ bool hasSelected = NULL != mBlockedList->getFirstSelected();
+ childSetEnabled("Unblock", hasSelected);
+}
+
+
+
+void LLPanelBlockedList::onBackBtnClick()
+{
+ LLSideTrayPanelContainer* parent = dynamic_cast<LLSideTrayPanelContainer*>(getParent());
+ if(parent)
+ {
+ parent->openPreviousPanel();
+ }
+}
+
+void LLPanelBlockedList::onRemoveBtnClick()
+{
+ std::string name = mBlockedList->getSelectedItemLabel();
+ LLUUID id = mBlockedList->getStringUUIDSelectedItem();
+ LLMute mute(id);
+ mute.setFromDisplayName(name);
+ // now mute.mName has the suffix trimmed off
+
+ S32 last_selected = mBlockedList->getFirstSelectedIndex();
+ if (LLMuteList::getInstance()->remove(mute))
+ {
+ // Above removals may rebuild this dialog.
+
+ if (last_selected == mBlockedList->getItemCount())
+ {
+ // we were on the last item, so select the last item again
+ mBlockedList->selectNthItem(last_selected - 1);
+ }
+ else
+ {
+ // else select the item after the last item previously selected
+ mBlockedList->selectNthItem(last_selected);
+ }
+ }
+}
+
+void LLPanelBlockedList::onPickBtnClick()
+{
+ const BOOL allow_multiple = FALSE;
+ const BOOL close_on_select = TRUE;
+ /*LLFloaterAvatarPicker* picker = */LLFloaterAvatarPicker::show(boost::bind(&LLPanelBlockedList::callbackBlockPicked, this, _1, _2), allow_multiple, close_on_select);
+
+ // *TODO: mantipov: should LLFloaterAvatarPicker be closed when panel is closed?
+ // old Floater dependency is not enable in panel
+ // addDependentFloater(picker);
+}
+
+void LLPanelBlockedList::onBlockByNameClick()
+{
+ LLFloaterGetBlockedObjectName::show(&LLPanelBlockedList::callbackBlockByName);
+}
+
+void LLPanelBlockedList::callbackBlockPicked(const std::vector<std::string>& names, const std::vector<LLUUID>& ids)
+{
+ if (names.empty() || ids.empty()) return;
+ LLMute mute(ids[0], names[0], LLMute::AGENT);
+ LLMuteList::getInstance()->add(mute);
+ showPanelAndSelect(mute.mID);
+}
+
+//static
+void LLPanelBlockedList::callbackBlockByName(const std::string& text)
+{
+ if (text.empty()) return;
+
+ LLMute mute(LLUUID::null, text, LLMute::BY_NAME);
+ BOOL success = LLMuteList::getInstance()->add(mute);
+ if (!success)
+ {
+ LLNotificationsUtil::add("MuteByNameFailed");
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// LLFloaterGetBlockedObjectName
+//////////////////////////////////////////////////////////////////////////
+
+// Constructor/Destructor
+LLFloaterGetBlockedObjectName::LLFloaterGetBlockedObjectName(const LLSD& key)
+: LLFloater(key)
+, mGetObjectNameCallback(NULL)
+{
+}
+
+// Destroys the object
+LLFloaterGetBlockedObjectName::~LLFloaterGetBlockedObjectName()
+{
+ gFocusMgr.releaseFocusIfNeeded( this );
+}
+
+BOOL LLFloaterGetBlockedObjectName::postBuild()
+{
+ getChild<LLButton>("OK")-> setCommitCallback(boost::bind(&LLFloaterGetBlockedObjectName::applyBlocking, this));
+ getChild<LLButton>("Cancel")-> setCommitCallback(boost::bind(&LLFloaterGetBlockedObjectName::cancelBlocking, this));
+ center();
+
+ return LLFloater::postBuild();
+}
+
+BOOL LLFloaterGetBlockedObjectName::handleKeyHere(KEY key, MASK mask)
+{
+ if (key == KEY_RETURN && mask == MASK_NONE)
+ {
+ applyBlocking();
+ return TRUE;
+ }
+ else if (key == KEY_ESCAPE && mask == MASK_NONE)
+ {
+ cancelBlocking();
+ return TRUE;
+ }
+
+ return LLFloater::handleKeyHere(key, mask);
+}
+
+// static
+LLFloaterGetBlockedObjectName* LLFloaterGetBlockedObjectName::show(get_object_name_callback_t callback)
+{
+ LLFloaterGetBlockedObjectName* floater = LLFloaterReg::showTypedInstance<LLFloaterGetBlockedObjectName>("mute_object_by_name");
+
+ floater->mGetObjectNameCallback = callback;
+
+ // *TODO: mantipov: should LLFloaterGetBlockedObjectName be closed when panel is closed?
+ // old Floater dependency is not enable in panel
+ // addDependentFloater(floater);
+
+ return floater;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Private Section
+void LLFloaterGetBlockedObjectName::applyBlocking()
+{
+ if (mGetObjectNameCallback)
+ {
+ const std::string& text = childGetValue("object_name").asString();
+ mGetObjectNameCallback(text);
+ }
+ closeFloater();
+}
+
+void LLFloaterGetBlockedObjectName::cancelBlocking()
+{
+ closeFloater();
+}
+
+//EOF
diff --git a/indra/newview/llpanelblockedlist.h b/indra/newview/llpanelblockedlist.h
new file mode 100644
index 0000000000..1ef16a02f4
--- /dev/null
+++ b/indra/newview/llpanelblockedlist.h
@@ -0,0 +1,116 @@
+/**
+ * @file llpanelblockedlist.h
+ * @brief Container for blocked Residents & Objects list
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELBLOCKEDLIST_H
+#define LL_LLPANELBLOCKEDLIST_H
+
+#include "llpanel.h"
+#include "llmutelist.h"
+#include "llfloater.h"
+// #include <vector>
+
+// class LLButton;
+// class LLLineEditor;
+// class LLMessageSystem;
+// class LLUUID;
+ class LLScrollListCtrl;
+
+class LLPanelBlockedList
+ : public LLPanel, public LLMuteListObserver
+{
+public:
+ LLPanelBlockedList();
+ ~LLPanelBlockedList();
+
+ virtual BOOL postBuild();
+ virtual void draw();
+ virtual void onOpen(const LLSD& key);
+
+ void selectBlocked(const LLUUID& id);
+
+ /**
+ * Shows current Panel in side tray and select passed blocked item.
+ *
+ * @param idToSelect - LLUUID of blocked Resident or Object to be selected.
+ * If it is LLUUID::null, nothing will be selected.
+ */
+ static void showPanelAndSelect(const LLUUID& idToSelect);
+
+ // LLMuteListObserver callback interface implementation.
+ /* virtual */ void onChange() { refreshBlockedList();}
+
+private:
+ void refreshBlockedList();
+ void updateButtons();
+
+ // UI callbacks
+ void onBackBtnClick();
+ void onRemoveBtnClick();
+ void onPickBtnClick();
+ void onBlockByNameClick();
+
+ void callbackBlockPicked(const std::vector<std::string>& names, const std::vector<LLUUID>& ids);
+ static void callbackBlockByName(const std::string& text);
+
+private:
+ LLScrollListCtrl* mBlockedList;
+};
+
+//-----------------------------------------------------------------------------
+// LLFloaterGetBlockedObjectName()
+//-----------------------------------------------------------------------------
+// Class for handling mute object by name floater.
+class LLFloaterGetBlockedObjectName : public LLFloater
+{
+ friend class LLFloaterReg;
+public:
+ typedef boost::function<void (const std::string&)> get_object_name_callback_t;
+
+ virtual BOOL postBuild();
+
+ virtual BOOL handleKeyHere(KEY key, MASK mask);
+
+ static LLFloaterGetBlockedObjectName* show(get_object_name_callback_t callback);
+
+private:
+ LLFloaterGetBlockedObjectName(const LLSD& key);
+ virtual ~LLFloaterGetBlockedObjectName();
+
+ // UI Callbacks
+ void applyBlocking();
+ void cancelBlocking();
+
+ get_object_name_callback_t mGetObjectNameCallback;
+};
+
+
+#endif // LL_LLPANELBLOCKEDLIST_H
diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp
index 9e4f9709a8..3f5d80c123 100644
--- a/indra/newview/llpanelclassified.cpp
+++ b/indra/newview/llpanelclassified.cpp
@@ -40,11 +40,15 @@
#include "lldir.h"
#include "lldispatcher.h"
+#include "llfloaterreg.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
#include "llparcel.h"
+#include "lltabcontainer.h"
#include "message.h"
#include "llagent.h"
-#include "llalertdialog.h"
+#include "llavataractions.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llclassifiedflags.h"
@@ -52,13 +56,10 @@
#include "llcommandhandler.h" // for classified HTML detail page click tracking
#include "llviewercontrol.h"
#include "lllineeditor.h"
-#include "llfloateravatarinfo.h"
-#include "llfloaterclassified.h"
-#include "lltabcontainervertical.h"
#include "lltextbox.h"
#include "llcombobox.h"
-#include "llviewertexteditor.h"
#include "lltexturectrl.h"
+#include "lltexteditor.h"
#include "lluiconstants.h"
#include "llurldispatcher.h" // for classified HTML detail click teleports
#include "lluictrlfactory.h"
@@ -70,6 +71,8 @@
#include "llviewerregion.h"
#include "llviewerwindow.h" // for window width, height
#include "llappviewer.h" // abortQuit()
+#include "lltrans.h"
+#include "llstatusbar.h"
const S32 MINIMUM_PRICE_FOR_LISTING = 50; // L$
const S32 MATURE_UNDEFINED = -1;
@@ -118,7 +121,7 @@ class LLClassifiedTeleportHandler : public LLCommandHandler
{
public:
// don't allow from external browsers because it moves you immediately
- LLClassifiedTeleportHandler() : LLCommandHandler("classifiedteleport", true) { }
+ LLClassifiedTeleportHandler() : LLCommandHandler("classifiedteleport", UNTRUSTED_BLOCK) { }
bool handle(const LLSD& tokens, const LLSD& queryMap)
{
@@ -141,7 +144,7 @@ public:
const bool from_search = true;
LLPanelClassified::sendClassifiedClickMessage(classified_id, "teleport", from_search);
// Invoke teleport
- LLWebBrowserCtrl* web = NULL;
+ LLMediaCtrl* web = NULL;
const bool trusted_browser = true;
return LLURLDispatcher::dispatch(url, web, trusted_browser);
}
@@ -151,7 +154,7 @@ LLClassifiedTeleportHandler gClassifiedTeleportHandler;
*/
LLPanelClassified::LLPanelClassified(bool in_finder, bool from_search)
-: LLPanel(std::string("Classified Panel")),
+: LLPanel(),
mInFinder(in_finder),
mFromSearch(from_search),
mDirty(false),
@@ -231,44 +234,36 @@ void LLPanelClassified::reset()
BOOL LLPanelClassified::postBuild()
{
mSnapshotCtrl = getChild<LLTextureCtrl>("snapshot_ctrl");
- mSnapshotCtrl->setCommitCallback(onCommitAny);
- mSnapshotCtrl->setCallbackUserData(this);
+ mSnapshotCtrl->setCommitCallback(onCommitAny, this);
mSnapshotSize = mSnapshotCtrl->getRect();
mNameEditor = getChild<LLLineEditor>("given_name_editor");
mNameEditor->setMaxTextLength(DB_PARCEL_NAME_LEN);
mNameEditor->setCommitOnFocusLost(TRUE);
- mNameEditor->setFocusReceivedCallback(focusReceived, this);
- mNameEditor->setCommitCallback(onCommitAny);
- mNameEditor->setCallbackUserData(this);
+ mNameEditor->setFocusReceivedCallback(boost::bind(focusReceived, _1, this));
+ mNameEditor->setCommitCallback(onCommitAny, this);
mNameEditor->setPrevalidate( LLLineEditor::prevalidateASCII );
mDescEditor = getChild<LLTextEditor>("desc_editor");
mDescEditor->setCommitOnFocusLost(TRUE);
- mDescEditor->setFocusReceivedCallback(focusReceived, this);
- mDescEditor->setCommitCallback(onCommitAny);
- mDescEditor->setCallbackUserData(this);
- mDescEditor->setTabsToNextField(TRUE);
-
+ mDescEditor->setFocusReceivedCallback(boost::bind(focusReceived, _1, this));
+ mDescEditor->setCommitCallback(onCommitAny, this);
+
mLocationEditor = getChild<LLLineEditor>("location_editor");
mSetBtn = getChild<LLButton>( "set_location_btn");
- mSetBtn->setClickedCallback(onClickSet);
- mSetBtn->setCallbackUserData(this);
+ mSetBtn->setClickedCallback(onClickSet, this);
mTeleportBtn = getChild<LLButton>( "classified_teleport_btn");
- mTeleportBtn->setClickedCallback(onClickTeleport);
- mTeleportBtn->setCallbackUserData(this);
+ mTeleportBtn->setClickedCallback(onClickTeleport, this);
mMapBtn = getChild<LLButton>( "classified_map_btn");
- mMapBtn->setClickedCallback(onClickMap);
- mMapBtn->setCallbackUserData(this);
+ mMapBtn->setClickedCallback(onClickMap, this);
if(mInFinder)
{
mProfileBtn = getChild<LLButton>( "classified_profile_btn");
- mProfileBtn->setClickedCallback(onClickProfile);
- mProfileBtn->setCallbackUserData(this);
+ mProfileBtn->setClickedCallback(onClickProfile, this);
}
mCategoryCombo = getChild<LLComboBox>( "classified_category_combo");
@@ -277,16 +272,14 @@ BOOL LLPanelClassified::postBuild()
iter != LLClassifiedInfo::sCategories.end();
iter++)
{
- mCategoryCombo->add(iter->second, (void *)((intptr_t)iter->first), ADD_BOTTOM);
+ mCategoryCombo->add(LLTrans::getString(iter->second), (void *)((intptr_t)iter->first), ADD_BOTTOM);
}
mCategoryCombo->setCurrentByIndex(0);
- mCategoryCombo->setCommitCallback(onCommitAny);
- mCategoryCombo->setCallbackUserData(this);
+ mCategoryCombo->setCommitCallback(onCommitAny, this);
mMatureCombo = getChild<LLComboBox>( "classified_mature_check");
mMatureCombo->setCurrentByIndex(0);
- mMatureCombo->setCommitCallback(onCommitAny);
- mMatureCombo->setCallbackUserData(this);
+ mMatureCombo->setCommitCallback(onCommitAny, this);
if (gAgent.wantsPGOnly())
{
// Teens don't get to set mature flag. JC
@@ -297,13 +290,11 @@ BOOL LLPanelClassified::postBuild()
if (!mInFinder)
{
mAutoRenewCheck = getChild<LLCheckBoxCtrl>( "auto_renew_check");
- mAutoRenewCheck->setCommitCallback(onCommitAny);
- mAutoRenewCheck->setCallbackUserData(this);
+ mAutoRenewCheck->setCommitCallback(onCommitAny, this);
}
mUpdateBtn = getChild<LLButton>("classified_update_btn");
- mUpdateBtn->setClickedCallback(onClickUpdate);
- mUpdateBtn->setCallbackUserData(this);
+ mUpdateBtn->setClickedCallback(onClickUpdate, this);
if (!mInFinder)
{
@@ -321,12 +312,12 @@ BOOL LLPanelClassified::titleIsValid()
const std::string& name = mNameEditor->getText();
if (name.empty())
{
- LLNotifications::instance().add("BlankClassifiedName");
+ LLNotificationsUtil::add("BlankClassifiedName");
return FALSE;
}
if (!isalnum(name[0]))
{
- LLNotifications::instance().add("ClassifiedMustBeAlphanumeric");
+ LLNotificationsUtil::add("ClassifiedMustBeAlphanumeric");
return FALSE;
}
@@ -345,7 +336,7 @@ void LLPanelClassified::apply()
bool LLPanelClassified::saveCallback(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
switch(option)
{
@@ -360,7 +351,7 @@ bool LLPanelClassified::saveCallback(const LLSD& notification, const LLSD& respo
LLFloater* parent_floater = gFloaterView->getParentFloater(this);
if (parent_floater)
{
- parent_floater->close();
+ parent_floater->closeFloater();
}
}
break;
@@ -381,7 +372,7 @@ BOOL LLPanelClassified::canClose()
LLSD args;
args["NAME"] = mNameEditor->getText();
- LLNotifications::instance().add("ClassifiedSave", args, LLSD(), boost::bind(&LLPanelClassified::saveCallback, this, _1, _2));
+ LLNotificationsUtil::add("ClassifiedSave", args, LLSD(), boost::bind(&LLPanelClassified::saveCallback, this, _1, _2));
return FALSE;
}
@@ -455,10 +446,11 @@ void LLPanelClassified::setClickThrough(const LLUUID& classified_id,
if (self->mClickThroughText)
{
- std::string msg = llformat("Clicks: %d teleport, %d map, %d profile",
- self->mTeleportClicksNew + self->mTeleportClicksOld,
- self->mMapClicksNew + self->mMapClicksOld,
- self->mProfileClicksNew + self->mProfileClicksOld);
+ LLStringUtil::format_map_t args;
+ args["[TELEPORT]"] = llformat ("%d", self->mTeleportClicksNew + self->mTeleportClicksOld);
+ args["[MAP]"] = llformat ("%d", self->mMapClicksNew + self->mMapClicksOld);
+ args["[PROFILE]"] = llformat ("%d", self->mProfileClicksNew + self->mProfileClicksOld);
+ std::string msg = LLTrans::getString ("ClassifiedClicksTxt", args);
self->mClickThroughText->setText(msg);
}
}
@@ -623,7 +615,6 @@ void LLPanelClassified::processClassifiedInfoReply(LLMessageSystem *msg, void **
U32 date = 0;
msg->getU32Fast(_PREHASH_Data, _PREHASH_CreationDate, date);
time_t tim = date;
- tm *now=localtime(&tim);
// future use
U32 expiration_date = 0;
@@ -674,9 +665,13 @@ void LLPanelClassified::processClassifiedInfoReply(LLMessageSystem *msg, void **
self->mAutoRenewCheck->set(auto_renew);
}
- std::string datestr = llformat("%02d/%02d/%d", now->tm_mon+1, now->tm_mday, now->tm_year+1900);
+ std::string dateStr = self->getString("dateStr");
+ LLSD substitution;
+ substitution["datetime"] = (S32) tim;
+ LLStringUtil::format (dateStr, substitution);
+
LLStringUtil::format_map_t string_args;
- string_args["[DATE]"] = datestr;
+ string_args["[DATE]"] = dateStr;
string_args["[AMT]"] = llformat("%d", price_for_listing);
self->childSetText("classified_info_text", self->getString("ad_placed_paid", string_args));
@@ -802,7 +797,7 @@ void LLPanelClassified::onClickUpdate(void* data)
if(self->mMatureCombo->getCurrentIndex() == DECLINE_TO_STATE)
{
// Tell user about it
- LLNotifications::instance().add("SetClassifiedMature",
+ LLNotificationsUtil::add("SetClassifiedMature",
LLSD(),
LLSD(),
boost::bind(&LLPanelClassified::confirmMature, self, _1, _2));
@@ -816,7 +811,7 @@ void LLPanelClassified::onClickUpdate(void* data)
// Callback from a dialog indicating response to mature notification
bool LLPanelClassified::confirmMature(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
// 0 == Yes
// 1 == No
@@ -846,7 +841,7 @@ void LLPanelClassified::gotMature()
if (mPaidFor)
{
LLNotification::Params params("PublishClassified");
- params.functor(boost::bind(&LLPanelClassified::confirmPublish, this, _1, _2));
+ params.functor.function(boost::bind(&LLPanelClassified::confirmPublish, this, _1, _2));
LLNotifications::instance().forceResponse(params, 0);
}
else
@@ -871,7 +866,7 @@ void LLPanelClassified::callbackGotPriceForListing(S32 option, std::string text,
std::string price_text = llformat("%d", MINIMUM_PRICE_FOR_LISTING);
args["MIN_PRICE"] = price_text;
- LLNotifications::instance().add("MinClassifiedPrice", args);
+ LLNotificationsUtil::add("MinClassifiedPrice", args);
return;
}
@@ -881,7 +876,7 @@ void LLPanelClassified::callbackGotPriceForListing(S32 option, std::string text,
LLSD args;
args["AMOUNT"] = llformat("%d", price_for_listing);
- LLNotifications::instance().add("PublishClassified", args, LLSD(),
+ LLNotificationsUtil::add("PublishClassified", args, LLSD(),
boost::bind(&LLPanelClassified::confirmPublish, self, _1, _2));
}
@@ -908,7 +903,7 @@ void LLPanelClassified::resetDirty()
// invoked from callbackConfirmPublish
bool LLPanelClassified::confirmPublish(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
// Option 0 = publish
if (option != 0) return false;
@@ -916,13 +911,7 @@ bool LLPanelClassified::confirmPublish(const LLSD& notification, const LLSD& res
// Big hack - assume that top picks are always in a browser,
// and non-finder-classifieds are always in a tab container.
- if (mInFinder)
- {
- // TODO: enable this
- //LLPanelDirClassifieds* panel = (LLPanelDirClassifieds*)getParent();
- //panel->renameClassified(mClassifiedID, mNameEditor->getText());
- }
- else
+ if (! mInFinder)
{
LLTabContainer* tab = (LLTabContainer*)getParent();
tab->setCurrentTabName(mNameEditor->getText());
@@ -937,12 +926,12 @@ bool LLPanelClassified::confirmPublish(const LLSD& notification, const LLSD& res
void LLPanelClassified::onClickTeleport(void* data)
{
LLPanelClassified* self = (LLPanelClassified*)data;
-
- if (!self->mPosGlobal.isExactlyZero())
+ LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
+
+ if (!self->mPosGlobal.isExactlyZero()&&worldmap_instance)
{
- gAgent.teleportViaLocation(self->mPosGlobal);
- gFloaterWorldMap->trackLocation(self->mPosGlobal);
-
+ gAgent.teleportViaLocation(self->mPosGlobal);
+ worldmap_instance->trackLocation(self->mPosGlobal);
self->sendClassifiedClickMessage("teleport");
}
}
@@ -952,9 +941,12 @@ void LLPanelClassified::onClickTeleport(void* data)
void LLPanelClassified::onClickMap(void* data)
{
LLPanelClassified* self = (LLPanelClassified*)data;
- gFloaterWorldMap->trackLocation(self->mPosGlobal);
- LLFloaterWorldMap::show(NULL, TRUE);
-
+ LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
+ if(worldmap_instance)
+ {
+ worldmap_instance->trackLocation(self->mPosGlobal);
+ LLFloaterReg::showInstance("world_map", "center");
+ }
self->sendClassifiedClickMessage("map");
}
@@ -962,7 +954,7 @@ void LLPanelClassified::onClickMap(void* data)
void LLPanelClassified::onClickProfile(void* data)
{
LLPanelClassified* self = (LLPanelClassified*)data;
- LLFloaterAvatarInfo::showFromDirectory(self->mCreatorID);
+ LLAvatarActions::showProfile(self->mCreatorID);
self->sendClassifiedClickMessage("profile");
}
@@ -984,7 +976,7 @@ void LLPanelClassified::onClickSet(void* data)
self->mPosGlobal = gAgent.getPositionGlobal();
std::string location_text;
- std::string regionName = "(will update after publish)";
+ std::string regionName = LLTrans::getString("ClassifiedUpdateAfterPublish");
LLViewerRegion* pRegion = gAgent.getRegion();
if (pRegion)
{
@@ -1065,7 +1057,7 @@ void LLPanelClassified::sendClassifiedClickMessage(const std::string& type)
////////////////////////////////////////////////////////////////////////////////////////////
LLFloaterPriceForListing::LLFloaterPriceForListing()
-: LLFloater(std::string("PriceForListing")),
+: LLFloater(LLSD()),
mCallback(NULL),
mUserData(NULL)
{ }
@@ -1101,7 +1093,7 @@ void LLFloaterPriceForListing::show( void (*callback)(S32, std::string, void*),
LLFloaterPriceForListing *self = new LLFloaterPriceForListing();
// Builds and adds to gFloaterView
- LLUICtrlFactory::getInstance()->buildFloater(self, "floater_price_for_listing.xml");
+ LLUICtrlFactory::getInstance()->buildFloater(self, "floater_price_for_listing.xml", NULL);
self->center();
self->mCallback = callback;
@@ -1129,7 +1121,7 @@ void LLFloaterPriceForListing::buttonCore(S32 button, void* data)
{
std::string text = self->childGetText("price_edit");
self->mCallback(button, text, self->mUserData);
- self->close();
+ self->closeFloater();
}
}
@@ -1152,3 +1144,603 @@ void LLPanelClassified::setDefaultAccessCombo()
break;
}
}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLPanelClassifiedInfo::LLPanelClassifiedInfo()
+ : LLPanel()
+ , mInfoLoaded(false)
+{
+}
+
+LLPanelClassifiedInfo::~LLPanelClassifiedInfo()
+{
+}
+
+// static
+LLPanelClassifiedInfo* LLPanelClassifiedInfo::create()
+{
+ LLPanelClassifiedInfo* panel = new LLPanelClassifiedInfo();
+ LLUICtrlFactory::getInstance()->buildPanel(panel, "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));
+
+ 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::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();
+
+ setClassifiedId(key["classified_id"]);
+ setClassifiedName(key["name"]);
+ setDescription(key["desc"]);
+ setSnapshotId(key["snapshot_id"]);
+
+ LLAvatarPropertiesProcessor::getInstance()->addObserver(getAvatarId(), this);
+ LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(getClassifiedId());
+ setInfoLoaded(false);
+}
+
+void LLPanelClassifiedInfo::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)
+ {
+ 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));
+ childSetValue("category", LLClassifiedInfo::sCategories[c_info->category]);
+
+ static std::string mature_str = getString("type_mature");
+ static std::string pg_str = getString("type_pg");
+
+ bool mature = is_cf_mature(c_info->flags);
+ childSetValue("content_type", mature ? mature_str : pg_str);
+ childSetValue("auto_renew", is_cf_auto_renew(c_info->flags));
+
+ childSetTextArg("price_for_listing", "[PRICE]", llformat("%d", c_info->price_for_listing));
+
+ setInfoLoaded(true);
+ }
+ }
+}
+
+void LLPanelClassifiedInfo::resetData()
+{
+ setClassifiedName(LLStringUtil::null);
+ setDescription(LLStringUtil::null);
+ setClassifiedLocation(LLStringUtil::null);
+ setClassifiedId(LLUUID::null);
+ setSnapshotId(LLUUID::null);
+ mPosGlobal.clearVec();
+ childSetValue("category", LLStringUtil::null);
+ childSetValue("content_type", LLStringUtil::null);
+}
+
+void LLPanelClassifiedInfo::resetControls()
+{
+ if(getAvatarId() == gAgent.getID())
+ {
+ childSetEnabled("edit_btn", TRUE);
+ childSetVisible("edit_btn", TRUE);
+ }
+ else
+ {
+ childSetEnabled("edit_btn", FALSE);
+ childSetVisible("edit_btn", FALSE);
+ }
+}
+
+void LLPanelClassifiedInfo::setClassifiedName(const std::string& name)
+{
+ childSetValue("classified_name", name);
+}
+
+std::string LLPanelClassifiedInfo::getClassifiedName()
+{
+ return childGetValue("classified_name").asString();
+}
+
+void LLPanelClassifiedInfo::setDescription(const std::string& desc)
+{
+ childSetValue("classified_desc", desc);
+}
+
+std::string LLPanelClassifiedInfo::getDescription()
+{
+ return childGetValue("classified_desc").asString();
+}
+
+void LLPanelClassifiedInfo::setClassifiedLocation(const std::string& location)
+{
+ childSetValue("classified_location", location);
+}
+
+void LLPanelClassifiedInfo::setSnapshotId(const LLUUID& id)
+{
+ childSetValue("classified_snapshot", id);
+}
+
+LLUUID LLPanelClassifiedInfo::getSnapshotId()
+{
+ return childGetValue("classified_snapshot").asUUID();
+}
+
+// static
+std::string LLPanelClassifiedInfo::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 = llround((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS;
+ S32 region_y = llround((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS;
+ S32 region_z = llround((F32)pos_global.mdV[VZ]);
+ location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z));
+ }
+
+ return location_text;
+}
+
+void LLPanelClassifiedInfo::onMapClick()
+{
+ LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal());
+ LLFloaterReg::showInstance("world_map", "center");
+}
+
+void LLPanelClassifiedInfo::onTeleportClick()
+{
+ if (!getPosGlobal().isExactlyZero())
+ {
+ gAgent.teleportViaLocation(getPosGlobal());
+ LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal());
+ }
+}
+
+void LLPanelClassifiedInfo::onExit()
+{
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+static const S32 CB_ITEM_MATURE = 0;
+static const S32 CB_ITEM_PG = 1;
+
+LLPanelClassifiedEdit::LLPanelClassifiedEdit()
+ : LLPanelClassifiedInfo()
+ , mIsNew(false)
+ , mCanClose(false)
+{
+}
+
+LLPanelClassifiedEdit::~LLPanelClassifiedEdit()
+{
+}
+
+//static
+LLPanelClassifiedEdit* LLPanelClassifiedEdit::create()
+{
+ LLPanelClassifiedEdit* panel = new LLPanelClassifiedEdit();
+ LLUICtrlFactory::getInstance()->buildPanel(panel, "panel_edit_classified.xml");
+ return panel;
+}
+
+BOOL LLPanelClassifiedEdit::postBuild()
+{
+ LLPanelClassifiedInfo::postBuild();
+
+ LLTextureCtrl* snapshot = getChild<LLTextureCtrl>("classified_snapshot");
+ snapshot->setOnSelectCallback(boost::bind(&LLPanelClassifiedEdit::onChange, this));
+
+ LLUICtrl* edit_icon = getChild<LLUICtrl>("edit_icon");
+ snapshot->setMouseEnterCallback(boost::bind(&LLPanelClassifiedEdit::onTexturePickerMouseEnter, this, edit_icon));
+ snapshot->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));
+
+ return TRUE;
+}
+
+void LLPanelClassifiedEdit::onOpen(const LLSD& key)
+{
+ LLUUID classified_id = key["classified_id"];
+
+ mIsNew = classified_id.isNull();
+
+ if(mIsNew)
+ {
+ setAvatarId(gAgent.getID());
+
+ resetData();
+ resetControls();
+
+ 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();
+ }
+
+ childSetValue("classified_name", makeClassifiedName());
+ childSetValue("classified_desc", desc);
+ setSnapshotId(snapshot_id);
+
+ setClassifiedLocation(createLocationText(getLocationNotice(), region_name, getPosGlobal()));
+
+ // server will set valid parcel id
+ setParcelId(LLUUID::null);
+
+ enableVerbs(true);
+ enableEditing(true);
+ }
+ else
+ {
+ LLPanelClassifiedInfo::onOpen(key);
+ enableVerbs(false);
+ enableEditing(false);
+ }
+
+ 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)
+ {
+ enableEditing(true);
+
+ setClassifiedName(c_info->name);
+ setDescription(c_info->description);
+ setSnapshotId(c_info->snapshot_id);
+ setPosGlobal(c_info->pos_global);
+
+ setClassifiedLocation(createLocationText(c_info->parcel_name, c_info->sim_name, c_info->pos_global));
+ getChild<LLComboBox>("category")->setCurrentByIndex(c_info->category + 1);
+ getChild<LLComboBox>("category")->resetDirty();
+
+ bool mature = is_cf_mature(c_info->flags);
+ bool auto_renew = is_cf_auto_renew(c_info->flags);
+
+ getChild<LLComboBox>("content_type")->setCurrentByIndex(mature ? CB_ITEM_MATURE : CB_ITEM_PG);
+ childSetValue("auto_renew", auto_renew);
+ childSetValue("price_for_listing", c_info->price_for_listing);
+
+ resetDirty();
+ setInfoLoaded(true);
+ }
+ }
+}
+
+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();
+ getChild<LLUICtrl>("classified_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_callback_t& cb)
+{
+ getChild<LLButton>("save_changes_btn")->setClickedCallback(cb);
+}
+
+void LLPanelClassifiedEdit::setCancelCallback(const commit_callback_t& cb)
+{
+ getChild<LLButton>("cancel_btn")->setClickedCallback(cb);
+}
+
+void LLPanelClassifiedEdit::resetControls()
+{
+ LLPanelClassifiedInfo::resetControls();
+
+ getChild<LLComboBox>("category")->setCurrentByIndex(0);
+ getChild<LLComboBox>("content_type")->setCurrentByIndex(0);
+ childSetValue("auto_renew", false);
+ childSetValue("price_for_listing", MINIMUM_PRICE_FOR_LISTING);
+}
+
+bool LLPanelClassifiedEdit::canClose()
+{
+ return mCanClose;
+}
+
+void LLPanelClassifiedEdit::sendUpdate()
+{
+ LLAvatarClassifiedInfo c_data;
+
+ if(getClassifiedId().isNull())
+ {
+ LLUUID id;
+ id.generate();
+ setClassifiedId(id);
+ }
+
+ c_data.agent_id = gAgent.getID();
+ c_data.classified_id = getClassifiedId();
+ c_data.category = getCategory();
+ 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);
+}
+
+U32 LLPanelClassifiedEdit::getCategory()
+{
+ LLComboBox* cat_cb = getChild<LLComboBox>("category");
+ return cat_cb->getCurrentIndex() + 1;
+}
+
+U8 LLPanelClassifiedEdit::getFlags()
+{
+ bool auto_renew = childGetValue("auto_renew").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)
+{
+ childSetEnabled("save_changes_btn", enable);
+}
+
+void LLPanelClassifiedEdit::enableEditing(bool enable)
+{
+ childSetEnabled("classified_snapshot", enable);
+ childSetEnabled("classified_name", enable);
+ childSetEnabled("classified_desc", enable);
+ childSetEnabled("set_to_curr_location_btn", enable);
+ childSetEnabled("category", enable);
+ childSetEnabled("content_type", enable);
+ childSetEnabled("price_for_listing", enable);
+ childSetEnabled("auto_renew", enable);
+}
+
+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 childGetValue("price_for_listing").asInteger();
+}
+
+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())
+ {
+ if(gStatusBar->getBalance() < getPriceForListing())
+ {
+ LLNotificationsUtil::add("ClassifiedInsufficientFunds");
+ return;
+ }
+ }
+
+ mCanClose = true;
+ sendUpdate();
+ resetDirty();
+}
+
+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);
+}
+
+//EOF
diff --git a/indra/newview/llpanelclassified.h b/indra/newview/llpanelclassified.h
index 417eddf460..e46806f576 100644
--- a/indra/newview/llpanelclassified.h
+++ b/indra/newview/llpanelclassified.h
@@ -37,6 +37,7 @@
#ifndef LL_LLPANELCLASSIFIED_H
#define LL_LLPANELCLASSIFIED_H
+#include "llavatarpropertiesprocessor.h"
#include "llpanel.h"
#include "llclassifiedinfo.h"
#include "v3dmath.h"
@@ -55,6 +56,8 @@ class LLTextureCtrl;
class LLUICtrl;
class LLMessageSystem;
+// *TODO deprecated, should be removed.
+// New class implemented in ticket EXT-2095
class LLPanelClassified : public LLPanel
{
public:
@@ -198,5 +201,146 @@ private:
void* mUserData;
};
+class LLPanelClassifiedInfo : public LLPanel, public LLAvatarPropertiesObserver
+{
+public:
+
+ static LLPanelClassifiedInfo* create();
+
+ virtual ~LLPanelClassifiedInfo();
+
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ /*virtual*/ BOOL postBuild();
+
+ /*virtual*/ void processProperties(void* data, EAvatarProcessorType type);
+
+ void setAvatarId(const LLUUID& avatar_id) { mAvatarId = avatar_id; }
+
+ LLUUID& getAvatarId() { return mAvatarId; }
+
+ 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);
+
+ void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; }
+
+ LLVector3d& getPosGlobal() { return mPosGlobal; }
+
+ void setParcelId(const LLUUID& id) { mParcelId = id; }
+
+ LLUUID getParcelId() { return mParcelId; }
+
+ bool getInfoLoaded() { return mInfoLoaded; }
+
+ void setInfoLoaded(bool loaded) { mInfoLoaded = loaded; }
+
+ void setExitCallback(const commit_callback_t& cb);
+
+ void setEditClassifiedCallback(const commit_callback_t& cb);
+
+protected:
+
+ LLPanelClassifiedInfo();
+
+ virtual void resetData();
+
+ virtual void resetControls();
+
+ static std::string createLocationText(
+ const std::string& original_name,
+ const std::string& sim_name,
+ const LLVector3d& pos_global);
+
+ void onMapClick();
+ void onTeleportClick();
+ void onExit();
+
+private:
+
+ LLUUID mAvatarId;
+ LLUUID mClassifiedId;
+ LLVector3d mPosGlobal;
+ LLUUID mParcelId;
+ bool mInfoLoaded;
+};
+
+class LLPanelClassifiedEdit : public LLPanelClassifiedInfo
+{
+public:
+
+ static LLPanelClassifiedEdit* create();
+
+ virtual ~LLPanelClassifiedEdit();
+
+ /*virtual*/ BOOL postBuild();
+
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ /*virtual*/ void processProperties(void* data, EAvatarProcessorType type);
+
+ /*virtual*/ BOOL isDirty() const;
+
+ /*virtual*/ void resetDirty();
+
+ void setSaveCallback(const commit_callback_t& cb);
+
+ void setCancelCallback(const commit_callback_t& cb);
+
+ /*virtual*/ void resetControls();
+
+ bool isNew() { return mIsNew; }
+
+ bool canClose();
+
+protected:
+
+ LLPanelClassifiedEdit();
+
+ void sendUpdate();
+
+ U32 getCategory();
+
+ void enableVerbs(bool enable);
+
+ void enableEditing(bool enable);
+
+ std::string makeClassifiedName();
+
+ S32 getPriceForListing();
+
+ U8 getFlags();
+
+ std::string getLocationNotice();
+
+ bool isValidName();
+
+ void notifyInvalidName();
+
+ void onSetLocationClick();
+ void onChange();
+ void onSaveClick();
+
+ void onTexturePickerMouseEnter(LLUICtrl* ctrl);
+ void onTexturePickerMouseLeave(LLUICtrl* ctrl);
+
+private:
+ bool mIsNew;
+ bool mCanClose;
+};
#endif // LL_LLPANELCLASSIFIED_H
diff --git a/indra/newview/llpanelcontents.cpp b/indra/newview/llpanelcontents.cpp
index a2f3d9e12c..9d591ef43d 100644
--- a/indra/newview/llpanelcontents.cpp
+++ b/indra/newview/llpanelcontents.cpp
@@ -36,37 +36,34 @@
#include "llpanelcontents.h"
// linden library includes
+#include "lleconomy.h"
#include "llerror.h"
+#include "llfloaterreg.h"
+#include "llfontgl.h"
+#include "llmaterialtable.h"
+#include "llpermissionsflags.h"
#include "llrect.h"
#include "llstring.h"
-#include "llmaterialtable.h"
-#include "llfontgl.h"
+#include "llui.h"
#include "m3math.h"
-#include "llpermissionsflags.h"
-#include "lleconomy.h"
#include "material_codes.h"
// project includes
-#include "llui.h"
-#include "llspinctrl.h"
-#include "llcheckboxctrl.h"
-#include "lltextbox.h"
-#include "llbutton.h"
-#include "llcombobox.h"
-#include "llfloaterbulkpermission.h"
-
#include "llagent.h"
-#include "llviewerwindow.h"
-#include "llworld.h"
-#include "llviewerobject.h"
-#include "llviewerregion.h"
+#include "llfloaterbulkpermission.h"
+#include "llpanelobjectinventory.h"
+#include "llpreviewscript.h"
#include "llresmgr.h"
#include "llselectmgr.h"
-#include "llpreviewscript.h"
#include "lltool.h"
-#include "lltoolmgr.h"
#include "lltoolcomp.h"
-#include "llpanelinventory.h"
+#include "lltoolmgr.h"
+#include "lltrans.h"
+#include "llviewerassettype.h"
+#include "llviewerobject.h"
+#include "llviewerregion.h"
+#include "llviewerwindow.h"
+#include "llworld.h"
//
// Imported globals
@@ -76,6 +73,13 @@
//
// Globals
//
+const char* LLPanelContents::TENTATIVE_SUFFIX = "_tentative";
+const char* LLPanelContents::PERMS_OWNER_INTERACT_KEY = "perms_owner_interact";
+const char* LLPanelContents::PERMS_OWNER_CONTROL_KEY = "perms_owner_control";
+const char* LLPanelContents::PERMS_GROUP_INTERACT_KEY = "perms_group_interact";
+const char* LLPanelContents::PERMS_GROUP_CONTROL_KEY = "perms_group_control";
+const char* LLPanelContents::PERMS_ANYONE_INTERACT_KEY = "perms_anyone_interact";
+const char* LLPanelContents::PERMS_ANYONE_CONTROL_KEY = "perms_anyone_control";
BOOL LLPanelContents::postBuild()
{
@@ -86,12 +90,14 @@ BOOL LLPanelContents::postBuild()
childSetAction("button new script",&LLPanelContents::onClickNewScript, this);
childSetAction("button permissions",&LLPanelContents::onClickPermissions, this);
+ mPanelInventoryObject = getChild<LLPanelObjectInventory>("contents_inventory");
+
return TRUE;
}
-LLPanelContents::LLPanelContents(const std::string& name)
- : LLPanel(name),
- mPanelInventory(NULL)
+LLPanelContents::LLPanelContents()
+ : LLPanel(),
+ mPanelInventoryObject(NULL)
{
}
@@ -114,7 +120,7 @@ void LLPanelContents::getState(LLViewerObject *objectp )
LLSelectMgr::getInstance()->selectGetGroup(group_id); // sets group_id as a side effect SL-23488
// BUG? Check for all objects being editable?
- BOOL editable = gAgent.isGodlike()
+ bool editable = gAgent.isGodlike()
|| (objectp->permModify()
&& ( objectp->permYouOwner() || ( !group_id.isNull() && gAgent.isInGroup(group_id) ))); // solves SL-23488
BOOL all_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME );
@@ -125,8 +131,8 @@ void LLPanelContents::getState(LLViewerObject *objectp )
all_volume &&
((LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() == 1)
|| (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1)));
-}
+}
void LLPanelContents::refresh()
{
@@ -134,10 +140,10 @@ void LLPanelContents::refresh()
LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(children_ok);
getState(object);
- if (mPanelInventory)
+ if (mPanelInventoryObject)
{
- mPanelInventory->refresh();
- }
+ mPanelInventoryObject->refresh();
+ }
}
@@ -162,7 +168,7 @@ void LLPanelContents::onClickNewScript(void *userdata)
PERM_NONE,
PERM_MOVE | PERM_TRANSFER);
std::string desc;
- LLAssetType::generateDescriptionFor(LLAssetType::AT_LSL_TEXT, desc);
+ LLViewerAssetType::generateDescriptionFor(LLAssetType::AT_LSL_TEXT, desc);
LLPointer<LLViewerInventoryItem> new_item =
new LLViewerInventoryItem(
LLUUID::null,
@@ -171,7 +177,7 @@ void LLPanelContents::onClickNewScript(void *userdata)
LLUUID::null,
LLAssetType::AT_LSL_TEXT,
LLInventoryType::IT_LSL,
- std::string("New Script"),
+ LLTrans::getString("PanelContentsNewScript"),
desc,
LLSaleInfo::DEFAULT,
LLViewerInventoryItem::II_FLAGS_NONE,
@@ -185,21 +191,7 @@ void LLPanelContents::onClickNewScript(void *userdata)
// viewer so the viewer can auto-open the script and start
// editing ASAP.
#if 0
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- LLRect rect = gSavedSettings.getRect("PreviewScriptRect");
- rect.translate( left - rect.mLeft, top - rect.mTop );
-
- LLLiveLSLEditor* editor;
- editor = new LLLiveLSLEditor("script ed",
- rect,
- "Script: New Script",
- object->mID,
- LLUUID::null);
- editor->open(); /*Flawfinder: ignore*/
-
- // keep onscreen
- gFloaterView->adjustToFitScreen(editor, FALSE);
+ LLFloaterReg::showInstance("preview_scriptedit", LLSD(inv_item->getUUID()), TAKE_FOCUS_YES);
#endif
}
}
@@ -209,5 +201,5 @@ void LLPanelContents::onClickNewScript(void *userdata)
void LLPanelContents::onClickPermissions(void *userdata)
{
LLPanelContents* self = (LLPanelContents*)userdata;
- gFloaterView->getParentFloater(self)->addDependentFloater(LLFloaterBulkPermission::showInstance());
+ gFloaterView->getParentFloater(self)->addDependentFloater(LLFloaterReg::showInstance("bulk_perms"));
}
diff --git a/indra/newview/llpanelcontents.h b/indra/newview/llpanelcontents.h
index ea06707494..14256845a6 100644
--- a/indra/newview/llpanelcontents.h
+++ b/indra/newview/llpanelcontents.h
@@ -35,9 +35,14 @@
#include "v3math.h"
#include "llpanel.h"
+#include "llinventory.h"
+#include "lluuid.h"
+#include "llmap.h"
+#include "llviewerobject.h"
+#include "llvoinventorylistener.h"
class LLButton;
-class LLPanelInventory;
+class LLPanelObjectInventory;
class LLViewerObject;
class LLCheckBoxCtrl;
class LLSpinCtrl;
@@ -46,19 +51,31 @@ class LLPanelContents : public LLPanel
{
public:
virtual BOOL postBuild();
- LLPanelContents(const std::string& name);
+ LLPanelContents();
virtual ~LLPanelContents();
void refresh();
- static void onClickNewScript( void* userdata);
- static void onClickPermissions( void* userdata);
+
+ static void onClickNewScript(void*);
+ static void onClickPermissions(void*);
+
+ // Key suffix for "tentative" fields
+ static const char* TENTATIVE_SUFFIX;
+
+ // These aren't fields in LLMediaEntry, so we have to define them ourselves for checkbox control
+ static const char* PERMS_OWNER_INTERACT_KEY;
+ static const char* PERMS_OWNER_CONTROL_KEY;
+ static const char* PERMS_GROUP_INTERACT_KEY;
+ static const char* PERMS_GROUP_CONTROL_KEY;
+ static const char* PERMS_ANYONE_INTERACT_KEY;
+ static const char* PERMS_ANYONE_CONTROL_KEY;
protected:
- void getState(LLViewerObject *object);
+ void getState(LLViewerObject *object);
public:
- LLPanelInventory* mPanelInventory;
+ LLPanelObjectInventory* mPanelInventoryObject;
};
-#endif
+#endif // LL_LLPANELCONTENTS_H
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
new file mode 100644
index 0000000000..e7acc68b93
--- /dev/null
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -0,0 +1,657 @@
+/**
+ * @file llpaneleditwearable.cpp
+ * @brief UI panel for editing of a particular wearable item.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpaneleditwearable.h"
+#include "llpanel.h"
+#include "llwearable.h"
+#include "lluictrl.h"
+#include "llscrollingpanellist.h"
+#include "llvisualparam.h"
+#include "lltoolmorph.h"
+#include "llviewerjointmesh.h"
+#include "lltrans.h"
+#include "llbutton.h"
+#include "llsliderctrl.h"
+#include "llagent.h"
+#include "llvoavatarself.h"
+#include "lltexteditor.h"
+#include "lltextbox.h"
+#include "llaccordionctrltab.h"
+#include "llagentwearables.h"
+#include "llscrollingpanelparam.h"
+
+// register panel with appropriate XML
+static LLRegisterPanelClassWrapper<LLPanelEditWearable> t_edit_wearable("panel_edit_wearable");
+
+// subparts of the UI for focus, camera position, etc.
+enum ESubpart {
+ SUBPART_SHAPE_HEAD = 1, // avoid 0
+ SUBPART_SHAPE_EYES,
+ SUBPART_SHAPE_EARS,
+ SUBPART_SHAPE_NOSE,
+ SUBPART_SHAPE_MOUTH,
+ SUBPART_SHAPE_CHIN,
+ SUBPART_SHAPE_TORSO,
+ SUBPART_SHAPE_LEGS,
+ SUBPART_SHAPE_WHOLE,
+ SUBPART_SHAPE_DETAIL,
+ SUBPART_SKIN_COLOR,
+ SUBPART_SKIN_FACEDETAIL,
+ SUBPART_SKIN_MAKEUP,
+ SUBPART_SKIN_BODYDETAIL,
+ SUBPART_HAIR_COLOR,
+ SUBPART_HAIR_STYLE,
+ SUBPART_HAIR_EYEBROWS,
+ SUBPART_HAIR_FACIAL,
+ SUBPART_EYES,
+ SUBPART_SHIRT,
+ SUBPART_PANTS,
+ SUBPART_SHOES,
+ SUBPART_SOCKS,
+ SUBPART_JACKET,
+ SUBPART_GLOVES,
+ SUBPART_UNDERSHIRT,
+ SUBPART_UNDERPANTS,
+ SUBPART_SKIRT,
+ SUBPART_ALPHA,
+ SUBPART_TATTOO
+ };
+
+typedef std::vector<ESubpart> subpart_vec_t;
+
+// Locally defined classes
+
+class LLEditWearableDictionary : public LLSingleton<LLEditWearableDictionary>
+{
+ //--------------------------------------------------------------------
+ // Constructors and Destructors
+ //--------------------------------------------------------------------
+public:
+ LLEditWearableDictionary();
+ virtual ~LLEditWearableDictionary();
+
+ //--------------------------------------------------------------------
+ // Wearable Types
+ //--------------------------------------------------------------------
+public:
+ struct WearableEntry : public LLDictionaryEntry
+ {
+ WearableEntry(EWearableType type,
+ const std::string &title,
+ const std::string &desc_title,
+ U8 num_subparts, ... ); // number of subparts followed by a list of ESubparts
+
+
+ const EWearableType mWearableType;
+ const std::string mTitle;
+ const std::string mDescTitle;
+ subpart_vec_t mSubparts;
+
+ };
+
+ struct Wearables : public LLDictionary<EWearableType, WearableEntry>
+ {
+ Wearables();
+ } mWearables;
+
+ const WearableEntry* getWearable(EWearableType type) const { return mWearables.lookup(type); }
+
+ //--------------------------------------------------------------------
+ // Subparts
+ //--------------------------------------------------------------------
+public:
+ struct SubpartEntry : public LLDictionaryEntry
+ {
+ SubpartEntry(ESubpart part,
+ const std::string &joint,
+ const std::string &edit_group,
+ const std::string &param_list,
+ const std::string &accordion_tab,
+ const LLVector3d &target_offset,
+ const LLVector3d &camera_offset,
+ const ESex &sex);
+
+ ESubpart mSubpart;
+ std::string mTargetJoint;
+ std::string mEditGroup;
+ std::string mParamList;
+ std::string mAccordionTab;
+ LLVector3d mTargetOffset;
+ LLVector3d mCameraOffset;
+ ESex mSex;
+ };
+
+ struct Subparts : public LLDictionary<ESubpart, SubpartEntry>
+ {
+ Subparts();
+ } mSubparts;
+
+ const SubpartEntry* getSubpart(ESubpart subpart) const { return mSubparts.lookup(subpart); }
+};
+
+LLEditWearableDictionary::LLEditWearableDictionary()
+{
+
+}
+
+//virtual
+LLEditWearableDictionary::~LLEditWearableDictionary()
+{
+}
+
+LLEditWearableDictionary::Wearables::Wearables()
+{
+ addEntry(WT_SHAPE, new WearableEntry(WT_SHAPE,"edit_shape_title","shape_desc_text",9, SUBPART_SHAPE_HEAD, SUBPART_SHAPE_EYES, SUBPART_SHAPE_EARS, SUBPART_SHAPE_NOSE, SUBPART_SHAPE_MOUTH, SUBPART_SHAPE_CHIN, SUBPART_SHAPE_TORSO, SUBPART_SHAPE_LEGS, SUBPART_SHAPE_WHOLE));
+ addEntry(WT_SKIN, new WearableEntry(WT_SKIN,"edit_skin_title","skin_desc_text",4, SUBPART_SKIN_COLOR, SUBPART_SKIN_FACEDETAIL, SUBPART_SKIN_MAKEUP, SUBPART_SKIN_BODYDETAIL));
+ addEntry(WT_HAIR, new WearableEntry(WT_HAIR,"edit_hair_title","hair_desc_text",4, SUBPART_HAIR_COLOR, SUBPART_HAIR_STYLE, SUBPART_HAIR_EYEBROWS, SUBPART_HAIR_FACIAL));
+ addEntry(WT_EYES, new WearableEntry(WT_EYES,"edit_eyes_title","eyes_desc_text",1, SUBPART_EYES));
+ addEntry(WT_SHIRT, new WearableEntry(WT_SHIRT,"edit_shirt_title","shirt_desc_text",1, SUBPART_SHIRT));
+ addEntry(WT_PANTS, new WearableEntry(WT_PANTS,"edit_pants_title","pants_desc_text",1, SUBPART_PANTS));
+ addEntry(WT_SHOES, new WearableEntry(WT_SHOES,"edit_shoes_title","shoes_desc_text",1, SUBPART_SHOES));
+ addEntry(WT_SOCKS, new WearableEntry(WT_SOCKS,"edit_socks_title","socks_desc_text",1, SUBPART_SOCKS));
+ addEntry(WT_JACKET, new WearableEntry(WT_JACKET,"edit_jacket_title","jacket_desc_text",1, SUBPART_JACKET));
+ addEntry(WT_GLOVES, new WearableEntry(WT_GLOVES,"edit_gloves_title","gloves_desc_text",1, SUBPART_GLOVES));
+ addEntry(WT_UNDERSHIRT, new WearableEntry(WT_UNDERSHIRT,"edit_undershirt_title","undershirt_desc_text",1, SUBPART_UNDERSHIRT));
+ addEntry(WT_UNDERPANTS, new WearableEntry(WT_UNDERPANTS,"edit_underpants_title","underpants_desc_text",1, SUBPART_UNDERPANTS));
+ addEntry(WT_SKIRT, new WearableEntry(WT_SKIRT,"edit_skirt_title","skirt_desc_text",1, SUBPART_SKIRT));
+ addEntry(WT_ALPHA, new WearableEntry(WT_ALPHA,"edit_alpha_title","alpha_desc_text",1, SUBPART_ALPHA));
+ addEntry(WT_TATTOO, new WearableEntry(WT_TATTOO,"edit_tattoo_title","tattoo_desc_text",1, SUBPART_TATTOO));
+}
+
+LLEditWearableDictionary::WearableEntry::WearableEntry(EWearableType type,
+ const std::string &title,
+ const std::string &desc_title,
+ U8 num_subparts, ... ) :
+ LLDictionaryEntry(title),
+ mWearableType(type),
+ mTitle(title),
+ mDescTitle(desc_title)
+{
+ va_list argp;
+ va_start(argp, num_subparts);
+
+ for (U8 i = 0; i < num_subparts; ++i)
+ {
+ ESubpart part = (ESubpart)va_arg(argp,int);
+ mSubparts.push_back(part);
+ }
+}
+
+LLEditWearableDictionary::Subparts::Subparts()
+{
+ addEntry(SUBPART_SHAPE_WHOLE, new SubpartEntry(SUBPART_SHAPE_WHOLE, "mPelvis", "shape_body","shape_body_param_list", "shape_body_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH));
+ addEntry(SUBPART_SHAPE_HEAD, new SubpartEntry(SUBPART_SHAPE_HEAD, "mHead", "shape_head", "shape_head_param_list", "shape_head_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
+ addEntry(SUBPART_SHAPE_EYES, new SubpartEntry(SUBPART_SHAPE_EYES, "mHead", "shape_eyes", "shape_eyes_param_list", "shape_eyes_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
+ addEntry(SUBPART_SHAPE_EARS, new SubpartEntry(SUBPART_SHAPE_EARS, "mHead", "shape_ears", "shape_ears_param_list", "shape_ears_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
+ addEntry(SUBPART_SHAPE_NOSE, new SubpartEntry(SUBPART_SHAPE_NOSE, "mHead", "shape_nose", "shape_nose_param_list", "shape_nose_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
+ addEntry(SUBPART_SHAPE_MOUTH, new SubpartEntry(SUBPART_SHAPE_MOUTH, "mHead", "shape_mouth", "shape_mouth_param_list", "shape_mouth_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
+ addEntry(SUBPART_SHAPE_CHIN, new SubpartEntry(SUBPART_SHAPE_CHIN, "mHead", "shape_chin", "shape_chin_param_list", "shape_chin_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
+ addEntry(SUBPART_SHAPE_TORSO, new SubpartEntry(SUBPART_SHAPE_TORSO, "mTorso", "shape_torso", "shape_torso_param_list", "shape_torso_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(-1.f, 0.15f, 0.3f),SEX_BOTH));
+ addEntry(SUBPART_SHAPE_LEGS, new SubpartEntry(SUBPART_SHAPE_LEGS, "mPelvis", "shape_legs", "shape_legs_param_list", "shape_legs_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH));
+
+ addEntry(SUBPART_SKIN_COLOR, new SubpartEntry(SUBPART_SKIN_COLOR, "mHead", "skin_color", "skin_color_param_list", "skin_color_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
+ addEntry(SUBPART_SKIN_FACEDETAIL, new SubpartEntry(SUBPART_SKIN_FACEDETAIL, "mHead", "skin_facedetail", "skin_face_param_list", "skin_face_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
+ addEntry(SUBPART_SKIN_MAKEUP, new SubpartEntry(SUBPART_SKIN_MAKEUP, "mHead", "skin_makeup", "skin_makeup_param_list", "skin_makeup_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
+ addEntry(SUBPART_SKIN_BODYDETAIL, new SubpartEntry(SUBPART_SKIN_BODYDETAIL, "mPelvis", "skin_bodydetail", "skin_body_param_list", "skin_body_tab", LLVector3d(0.f, 0.f, -0.2f), LLVector3d(-2.5f, 0.5f, 0.5f),SEX_BOTH));
+
+ addEntry(SUBPART_HAIR_COLOR, new SubpartEntry(SUBPART_HAIR_COLOR, "mHead", "hair_color", "hair_color_param_list", "hair_color_tab", LLVector3d(0.f, 0.f, 0.10f), LLVector3d(-0.4f, 0.05f, 0.10f),SEX_BOTH));
+ addEntry(SUBPART_HAIR_STYLE, new SubpartEntry(SUBPART_HAIR_STYLE, "mHead", "hair_style", "hair_style_param_list", "hair_style_tab", LLVector3d(0.f, 0.f, 0.10f), LLVector3d(-0.4f, 0.05f, 0.10f),SEX_BOTH));
+ addEntry(SUBPART_HAIR_EYEBROWS, new SubpartEntry(SUBPART_HAIR_EYEBROWS, "mHead", "hair_eyebrows", "hair_eyebrows_param_list", "hair_eyebrows_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
+ addEntry(SUBPART_HAIR_FACIAL, new SubpartEntry(SUBPART_HAIR_FACIAL, "mHead", "hair_facial", "hair_facial_param_list", "hair_facial_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_MALE));
+
+ addEntry(SUBPART_EYES, new SubpartEntry(SUBPART_EYES, "mHead", "eyes", "eyes_main_param_list", "eyes_main_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
+
+ addEntry(SUBPART_SHIRT, new SubpartEntry(SUBPART_SHIRT, "mTorso", "shirt", "shirt_main_param_list", "shirt_main_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(-1.f, 0.15f, 0.3f),SEX_BOTH));
+ addEntry(SUBPART_PANTS, new SubpartEntry(SUBPART_PANTS, "mPelvis", "pants", "pants_main_param_list", "pants_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH));
+ addEntry(SUBPART_SHOES, new SubpartEntry(SUBPART_SHOES, "mPelvis", "shoes", "shoes_main_param_list", "shoes_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH));
+ addEntry(SUBPART_SOCKS, new SubpartEntry(SUBPART_SOCKS, "mPelvis", "socks", "socks_main_param_list", "socks_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH));
+ addEntry(SUBPART_JACKET, new SubpartEntry(SUBPART_JACKET, "mTorso", "jacket", "jacket_main_param_list", "jacket_main_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(-2.f, 0.1f, 0.3f),SEX_BOTH));
+ addEntry(SUBPART_SKIRT, new SubpartEntry(SUBPART_SKIRT, "mPelvis", "skirt", "skirt_main_param_list", "skirt_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH));
+ addEntry(SUBPART_GLOVES, new SubpartEntry(SUBPART_GLOVES, "mTorso", "gloves", "gloves_main_param_list", "gloves_main_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(-1.f, 0.15f, 0.f),SEX_BOTH));
+ addEntry(SUBPART_UNDERSHIRT, new SubpartEntry(SUBPART_UNDERSHIRT, "mTorso", "undershirt", "undershirt_main_param_list", "undershirt_main_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(-1.f, 0.15f, 0.3f),SEX_BOTH));
+ addEntry(SUBPART_UNDERPANTS, new SubpartEntry(SUBPART_UNDERPANTS, "mPelvis", "underpants", "underpants_main_param_list", "underpants_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH));
+ addEntry(SUBPART_ALPHA, new SubpartEntry(SUBPART_ALPHA, "mPelvis", "alpha", "alpha_main_param_list", "alpha_main_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH));
+ addEntry(SUBPART_TATTOO, new SubpartEntry(SUBPART_TATTOO, "mPelvis", "tattoo", "tattoo_main_param_list", "tattoo_main_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH));
+}
+
+LLEditWearableDictionary::SubpartEntry::SubpartEntry(ESubpart part,
+ const std::string &joint,
+ const std::string &edit_group,
+ const std::string &param_list,
+ const std::string &accordion_tab,
+ const LLVector3d &target_offset,
+ const LLVector3d &camera_offset,
+ const ESex &sex) :
+ LLDictionaryEntry(edit_group),
+ mSubpart(part),
+ mTargetJoint(joint),
+ mEditGroup(edit_group),
+ mParamList(param_list),
+ mAccordionTab(accordion_tab),
+ mTargetOffset(target_offset),
+ mCameraOffset(camera_offset),
+ mSex(sex)
+{
+}
+
+
+// LLPanelEditWearable
+
+LLPanelEditWearable::LLPanelEditWearable()
+ : LLPanel()
+{
+}
+
+//virtual
+LLPanelEditWearable::~LLPanelEditWearable()
+{
+
+}
+
+// virtual
+BOOL LLPanelEditWearable::postBuild()
+{
+ // buttons
+ mBtnRevert = getChild<LLButton>("revert_button");
+ mBtnRevert->setClickedCallback(boost::bind(&LLPanelEditWearable::onRevertButtonClicked, this));
+
+ mBtnBack = getChild<LLButton>("back_btn");
+ // handled at appearance panel level?
+ //mBtnBack->setClickedCallback(boost::bind(&LLPanelEditWearable::onBackButtonClicked, this));
+
+ mTextEditor = getChild<LLTextEditor>("description");
+
+ mPanelTitle = getChild<LLTextBox>("edit_wearable_title");
+ mDescTitle = getChild<LLTextBox>("description_text");
+
+ // The following panels will be shown/hidden based on what wearable we're editing
+ // body parts
+ mPanelShape = getChild<LLPanel>("edit_shape_panel");
+ mPanelSkin = getChild<LLPanel>("edit_skin_panel");
+ mPanelEyes = getChild<LLPanel>("edit_eyes_panel");
+ mPanelHair = getChild<LLPanel>("edit_hair_panel");
+
+ //clothes
+ mPanelShirt = getChild<LLPanel>("edit_shirt_panel");
+ mPanelPants = getChild<LLPanel>("edit_pants_panel");
+ mPanelShoes = getChild<LLPanel>("edit_shoes_panel");
+ mPanelSocks = getChild<LLPanel>("edit_socks_panel");
+ mPanelJacket = getChild<LLPanel>("edit_jacket_panel");
+ mPanelGloves = getChild<LLPanel>("edit_gloves_panel");
+ mPanelUndershirt = getChild<LLPanel>("edit_undershirt_panel");
+ mPanelUnderpants = getChild<LLPanel>("edit_underpants_panel");
+ mPanelSkirt = getChild<LLPanel>("edit_skirt_panel");
+ mPanelAlpha = getChild<LLPanel>("edit_alpha_panel");
+ mPanelTattoo = getChild<LLPanel>("edit_tattoo_panel");
+
+ mWearablePtr = NULL;
+
+ return TRUE;
+}
+
+// virtual
+// LLUICtrl
+BOOL LLPanelEditWearable::isDirty() const
+{
+ BOOL isDirty = FALSE;
+ if (mWearablePtr)
+ {
+ if (mWearablePtr->isDirty() ||
+ mWearablePtr->getName().compare(mTextEditor->getText()) != 0)
+ {
+ isDirty = TRUE;
+ }
+ }
+ return isDirty;
+}
+//virtual
+void LLPanelEditWearable::draw()
+{
+ BOOL is_dirty = isDirty();
+ mBtnRevert->setEnabled(is_dirty);
+
+ LLPanel::draw();
+}
+
+void LLPanelEditWearable::setWearable(LLWearable *wearable)
+{
+ showWearable(mWearablePtr, FALSE);
+ mWearablePtr = wearable;
+ showWearable(mWearablePtr, TRUE);
+
+ initializePanel();
+}
+
+//static
+void LLPanelEditWearable::onRevertButtonClicked(void* userdata)
+{
+ LLPanelEditWearable *panel = (LLPanelEditWearable*) userdata;
+ panel->revertChanges();
+}
+
+
+void LLPanelEditWearable::saveChanges()
+{
+ if (!mWearablePtr || !isDirty())
+ {
+ // do nothing if no unsaved changes
+ return;
+ }
+
+ U32 index = gAgentWearables.getWearableIndex(mWearablePtr);
+
+ if (mWearablePtr->getName().compare(mTextEditor->getText()) != 0)
+ {
+ // the name of the wearable has changed, re-save wearable with new name
+ gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, mTextEditor->getText(), FALSE);
+ }
+ else
+ {
+ gAgentWearables.saveWearable(mWearablePtr->getType(), index);
+ }
+}
+
+void LLPanelEditWearable::revertChanges()
+{
+ if (!mWearablePtr || !isDirty())
+ {
+ // no unsaved changes to revert
+ return;
+ }
+
+ mWearablePtr->revertValues();
+ mTextEditor->setText(mWearablePtr->getName());
+}
+
+void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show)
+{
+ if (!wearable)
+ {
+ return;
+ }
+
+ EWearableType type = wearable->getType();
+ LLPanel *targetPanel = NULL;
+ std::string title;
+ std::string description_title;
+
+ const LLEditWearableDictionary::WearableEntry *entry = LLEditWearableDictionary::getInstance()->getWearable(type);
+ if (!entry)
+ {
+ llwarns << "called LLPanelEditWearable::showWearable with an invalid wearable type! (" << type << ")" << llendl;
+ return;
+ }
+
+ targetPanel = getPanel(type);
+ title = getString(entry->mTitle);
+ description_title = getString(entry->mDescTitle);
+
+ targetPanel->setVisible(show);
+ if (show)
+ {
+ mPanelTitle->setText(title);
+ mDescTitle->setText(description_title);
+ }
+
+}
+
+void LLPanelEditWearable::initializePanel()
+{
+ if (!mWearablePtr)
+ {
+ // cannot initialize with a null reference.
+ return;
+ }
+
+ EWearableType type = mWearablePtr->getType();
+
+ // set name
+ mTextEditor->setText(mWearablePtr->getName());
+
+ // clear and rebuild visual param list
+ const LLEditWearableDictionary::WearableEntry *wearable_entry = LLEditWearableDictionary::getInstance()->getWearable(type);
+ if (!wearable_entry)
+ {
+ llwarns << "could not get wearable dictionary entry for wearable of type: " << type << llendl;
+ return;
+ }
+ U8 num_subparts = wearable_entry->mSubparts.size();
+
+ for (U8 index = 0; index < num_subparts; ++index)
+ {
+ // dive into data structures to get the panel we need
+ ESubpart subpart_e = wearable_entry->mSubparts[index];
+ const LLEditWearableDictionary::SubpartEntry *subpart_entry = LLEditWearableDictionary::getInstance()->getSubpart(subpart_e);
+
+ if (!subpart_entry)
+ {
+ llwarns << "could not get wearable subpart dictionary entry for subpart: " << subpart_e << llendl;
+ continue;
+ }
+
+ const std::string scrolling_panel = subpart_entry->mParamList;
+ const std::string accordion_tab = subpart_entry->mAccordionTab;
+
+ LLScrollingPanelList *panel_list = getChild<LLScrollingPanelList>(scrolling_panel);
+ LLAccordionCtrlTab *tab = getChild<LLAccordionCtrlTab>(accordion_tab);
+
+ if (!panel_list)
+ {
+ llwarns << "could not get scrolling panel list: " << scrolling_panel << llendl;
+ continue;
+ }
+
+ if (!tab)
+ {
+ llwarns << "could not get llaccordionctrltab from UI with name: " << accordion_tab << llendl;
+ continue;
+ }
+
+ // what edit group do we want to extract params for?
+ const std::string edit_group = subpart_entry->mEditGroup;
+
+ // storage for ordered list of visual params
+ value_map_t sorted_params;
+ getSortedParams(sorted_params, edit_group);
+
+ buildParamList(panel_list, sorted_params, tab);
+
+ updateScrollingPanelUI();
+ }
+
+}
+
+void LLPanelEditWearable::updateScrollingPanelUI()
+{
+ // do nothing if we don't have a valid wearable we're editing
+ if (mWearablePtr == NULL)
+ {
+ return;
+ }
+
+ EWearableType type = mWearablePtr->getType();
+ LLPanel *panel = getPanel(type);
+
+ if(panel && (mWearablePtr->getItemID().notNull()))
+ {
+ const LLEditWearableDictionary::WearableEntry *wearable_entry = LLEditWearableDictionary::getInstance()->getWearable(type);
+ U8 num_subparts = wearable_entry->mSubparts.size();
+
+ LLScrollingPanelParam::sUpdateDelayFrames = 0;
+ for (U8 index = 0; index < num_subparts; ++index)
+ {
+ // dive into data structures to get the panel we need
+ ESubpart subpart_e = wearable_entry->mSubparts[index];
+ const LLEditWearableDictionary::SubpartEntry *subpart_entry = LLEditWearableDictionary::getInstance()->getSubpart(subpart_e);
+
+ const std::string scrolling_panel = subpart_entry->mParamList;
+
+ LLScrollingPanelList *panel_list = getChild<LLScrollingPanelList>(scrolling_panel);
+
+ if (!panel_list)
+ {
+ llwarns << "could not get scrolling panel list: " << scrolling_panel << llendl;
+ continue;
+ }
+
+ panel_list->updatePanels(TRUE);
+ }
+ }
+}
+
+LLPanel* LLPanelEditWearable::getPanel(EWearableType type)
+{
+ switch (type)
+ {
+ case WT_SHAPE:
+ return mPanelShape;
+ break;
+
+ case WT_SKIN:
+ return mPanelSkin;
+ break;
+
+ case WT_HAIR:
+ return mPanelHair;
+ break;
+
+ case WT_EYES:
+ return mPanelEyes;
+ break;
+
+ case WT_SHIRT:
+ return mPanelShirt;
+ break;
+
+ case WT_PANTS:
+ return mPanelPants;
+ break;
+
+ case WT_SHOES:
+ return mPanelShoes;
+ break;
+
+ case WT_SOCKS:
+ return mPanelSocks;
+ break;
+
+ case WT_JACKET:
+ return mPanelJacket;
+ break;
+
+ case WT_GLOVES:
+ return mPanelGloves;
+ break;
+
+ case WT_UNDERSHIRT:
+ return mPanelUndershirt;
+ break;
+
+ case WT_UNDERPANTS:
+ return mPanelUnderpants;
+ break;
+
+ case WT_SKIRT:
+ return mPanelSkirt;
+ break;
+
+ case WT_ALPHA:
+ return mPanelAlpha;
+ break;
+
+ case WT_TATTOO:
+ return mPanelTattoo;
+ break;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+void LLPanelEditWearable::getSortedParams(value_map_t &sorted_params, const std::string &edit_group)
+{
+ LLWearable::visual_param_vec_t param_list;
+ ESex avatar_sex = gAgent.getAvatarObject()->getSex();
+
+ mWearablePtr->getVisualParams(param_list);
+
+ for (LLWearable::visual_param_vec_t::iterator iter = param_list.begin();
+ iter != param_list.end();
+ ++iter)
+ {
+ LLViewerVisualParam *param = (LLViewerVisualParam*) *iter;
+
+ if (param->getID() == -1
+ || param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE
+ || param->getEditGroup() != edit_group
+ || !(param->getSex() & avatar_sex))
+ {
+ continue;
+ }
+
+ value_map_t::value_type vt(-param->getDisplayOrder(), param);
+ llassert( sorted_params.find(-param->getDisplayOrder()) == sorted_params.end() ); //check for duplicates
+ sorted_params.insert(vt);
+ }
+}
+
+void LLPanelEditWearable::buildParamList(LLScrollingPanelList *panel_list, value_map_t &sorted_params, LLAccordionCtrlTab *tab)
+{
+ // sorted_params is sorted according to magnitude of effect from
+ // least to greatest. Adding to the front of the child list
+ // reverses that order.
+ if( panel_list )
+ {
+ panel_list->clearPanels();
+ value_map_t::iterator end = sorted_params.end();
+ S32 height = 0;
+ for(value_map_t::iterator it = sorted_params.begin(); it != end; ++it)
+ {
+ LLPanel::Params p;
+ p.name("LLScrollingPanelParam");
+ p.rect(LLRect(0, LLScrollingPanelParam::PARAM_PANEL_HEIGHT, LLScrollingPanelParam::PARAM_PANEL_WIDTH, 0 ));
+ LLScrollingPanelParam* panel_param = new LLScrollingPanelParam( p, NULL, (*it).second, TRUE, this->getWearable());
+ height = panel_list->addPanel( panel_param );
+ }
+
+ S32 width = tab->getRect().getWidth();
+
+ tab->reshape(width,height + tab->getHeaderHeight()+10,FALSE);
+ }
+}
+
+
+
+
+
diff --git a/indra/newview/llpaneleditwearable.h b/indra/newview/llpaneleditwearable.h
new file mode 100644
index 0000000000..4178659617
--- /dev/null
+++ b/indra/newview/llpaneleditwearable.h
@@ -0,0 +1,114 @@
+/**
+ * @file llfloatercustomize.h
+ * @brief The customize avatar floater, triggered by "Appearance..."
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELEDITWEARABLE_H
+#define LL_LLPANELEDITWEARABLE_H
+
+#include "llpanel.h"
+#include "llscrollingpanellist.h"
+#include "llmodaldialog.h"
+#include "llwearabledictionary.h"
+
+class LLWearable;
+class LLTextEditor;
+class LLTextBox;
+class LLViewerVisualParam;
+class LLVisualParamHint;
+class LLViewerJointMesh;
+class LLAccordionCtrlTab;
+
+class LLPanelEditWearable : public LLPanel
+{
+public:
+ LLPanelEditWearable( );
+ virtual ~LLPanelEditWearable();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ BOOL isDirty() const; // LLUICtrl
+ /*virtual*/ void draw();
+
+ LLWearable* getWearable() { return mWearablePtr; }
+ void setWearable(LLWearable *wearable);
+
+ void saveChanges();
+ void revertChanges();
+
+ static void onRevertButtonClicked(void* userdata);
+
+private:
+ typedef std::map<F32, LLViewerVisualParam*> value_map_t;
+
+ void showWearable(LLWearable* wearable, BOOL show);
+ void initializePanel();
+ void updateScrollingPanelUI();
+ LLPanel* getPanel(EWearableType type);
+ void getSortedParams(value_map_t &sorted_params, const std::string &edit_group);
+ void buildParamList(LLScrollingPanelList *panel_list, value_map_t &sorted_params, LLAccordionCtrlTab *tab);
+
+ // the pointer to the wearable we're editing. NULL means we're not editing a wearable.
+ LLWearable *mWearablePtr;
+
+ // these are constant no matter what wearable we're editing
+ LLButton *mBtnRevert;
+ LLButton *mBtnBack;
+
+ LLTextBox *mPanelTitle;
+ LLTextBox *mDescTitle;
+
+
+ // This text editor reference will change each time we edit a new wearable -
+ // it will be grabbed from the currently visible panel
+ LLTextEditor *mTextEditor;
+
+ // The following panels will be shown/hidden based on what wearable we're editing
+ // body parts
+ LLPanel *mPanelShape;
+ LLPanel *mPanelSkin;
+ LLPanel *mPanelEyes;
+ LLPanel *mPanelHair;
+
+ //clothes
+ LLPanel *mPanelShirt;
+ LLPanel *mPanelPants;
+ LLPanel *mPanelShoes;
+ LLPanel *mPanelSocks;
+ LLPanel *mPanelJacket;
+ LLPanel *mPanelGloves;
+ LLPanel *mPanelUndershirt;
+ LLPanel *mPanelUnderpants;
+ LLPanel *mPanelSkirt;
+ LLPanel *mPanelAlpha;
+ LLPanel *mPanelTattoo;
+
+};
+
+#endif
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index e93a5be8ed..8c5208678e 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -49,6 +49,7 @@
#include "llcombobox.h"
#include "lldrawpoolbump.h"
#include "lllineeditor.h"
+#include "llmediaentry.h"
#include "llresmgr.h"
#include "llselectmgr.h"
#include "llspinctrl.h"
@@ -61,7 +62,10 @@
#include "llviewermedia.h"
#include "llviewerobject.h"
#include "llviewerstats.h"
+#include "llvovolume.h"
#include "lluictrlfactory.h"
+#include "llpluginclassmedia.h"
+#include "llviewertexturelist.h"
//
// Methods
@@ -69,6 +73,18 @@
BOOL LLPanelFace::postBuild()
{
+ childSetCommitCallback("combobox shininess",&LLPanelFace::onCommitShiny,this);
+ childSetCommitCallback("combobox bumpiness",&LLPanelFace::onCommitBump,this);
+ childSetCommitCallback("TexScaleU",&LLPanelFace::onCommitTextureInfo, this);
+ childSetCommitCallback("checkbox flip s",&LLPanelFace::onCommitTextureInfo, this);
+ childSetCommitCallback("TexScaleV",&LLPanelFace::onCommitTextureInfo, this);
+ childSetCommitCallback("checkbox flip t",&LLPanelFace::onCommitTextureInfo, this);
+ childSetCommitCallback("TexRot",&LLPanelFace::onCommitTextureInfo, this);
+ childSetAction("button apply",&LLPanelFace::onClickApply,this);
+ childSetCommitCallback("TexOffsetU",LLPanelFace::onCommitTextureInfo, this);
+ childSetCommitCallback("TexOffsetV",LLPanelFace::onCommitTextureInfo, this);
+ childSetAction("button align",&LLPanelFace::onClickAutoFix,this);
+
LLRect rect = this->getRect();
LLTextureCtrl* mTextureCtrl;
LLColorSwatchCtrl* mColorSwatch;
@@ -87,11 +103,10 @@ BOOL LLPanelFace::postBuild()
if(mTextureCtrl)
{
mTextureCtrl->setDefaultImageAssetID(LLUUID( gSavedSettings.getString( "DefaultObjectTexture" )));
- mTextureCtrl->setCommitCallback( LLPanelFace::onCommitTexture );
- mTextureCtrl->setOnCancelCallback( LLPanelFace::onCancelTexture );
- mTextureCtrl->setOnSelectCallback( LLPanelFace::onSelectTexture );
- mTextureCtrl->setDragCallback(LLPanelFace::onDragTexture);
- mTextureCtrl->setCallbackUserData( this );
+ mTextureCtrl->setCommitCallback( boost::bind(&LLPanelFace::onCommitTexture, this, _2) );
+ mTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelTexture, this, _2) );
+ mTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectTexture, this, _2) );
+ mTextureCtrl->setDragCallback(boost::bind(&LLPanelFace::onDragTexture, this, _2));
mTextureCtrl->setFollowsTop();
mTextureCtrl->setFollowsLeft();
// Don't allow (no copy) or (no transfer) textures to be selected during immediate mode
@@ -118,10 +133,9 @@ BOOL LLPanelFace::postBuild()
mColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
if(mColorSwatch)
{
- mColorSwatch->setCommitCallback(LLPanelFace::onCommitColor);
- mColorSwatch->setOnCancelCallback(LLPanelFace::onCancelColor);
- mColorSwatch->setOnSelectCallback(LLPanelFace::onSelectColor);
- mColorSwatch->setCallbackUserData( this );
+ mColorSwatch->setCommitCallback(boost::bind(&LLPanelFace::onCommitColor, this, _2));
+ mColorSwatch->setOnCancelCallback(boost::bind(&LLPanelFace::onCancelColor, this, _2));
+ mColorSwatch->setOnSelectCallback(boost::bind(&LLPanelFace::onSelectColor, this, _2));
mColorSwatch->setFollowsTop();
mColorSwatch->setFollowsLeft();
mColorSwatch->setCanApplyImmediately(TRUE);
@@ -137,8 +151,7 @@ BOOL LLPanelFace::postBuild()
mCtrlColorTransp = getChild<LLSpinCtrl>("ColorTrans");
if(mCtrlColorTransp)
{
- mCtrlColorTransp->setCommitCallback(LLPanelFace::onCommitAlpha);
- mCtrlColorTransp->setCallbackUserData(this);
+ mCtrlColorTransp->setCommitCallback(boost::bind(&LLPanelFace::onCommitAlpha, this, _2));
mCtrlColorTransp->setPrecision(0);
mCtrlColorTransp->setFollowsTop();
mCtrlColorTransp->setFollowsLeft();
@@ -147,44 +160,30 @@ BOOL LLPanelFace::postBuild()
mCheckFullbright = getChild<LLCheckBoxCtrl>("checkbox fullbright");
if (mCheckFullbright)
{
- mCheckFullbright->setCommitCallback(LLPanelFace::onCommitFullbright);
- mCheckFullbright->setCallbackUserData( this );
+ mCheckFullbright->setCommitCallback(LLPanelFace::onCommitFullbright, this);
}
mComboTexGen = getChild<LLComboBox>("combobox texgen");
if(mComboTexGen)
{
- mComboTexGen->setCommitCallback(LLPanelFace::onCommitTexGen);
+ mComboTexGen->setCommitCallback(LLPanelFace::onCommitTexGen, this);
mComboTexGen->setFollows(FOLLOWS_LEFT | FOLLOWS_TOP);
- mComboTexGen->setCallbackUserData( this );
}
mCtrlGlow = getChild<LLSpinCtrl>("glow");
if(mCtrlGlow)
{
- mCtrlGlow->setCommitCallback(LLPanelFace::onCommitGlow);
- mCtrlGlow->setCallbackUserData(this);
+ mCtrlGlow->setCommitCallback(LLPanelFace::onCommitGlow, this);
}
- childSetCommitCallback("combobox shininess",&LLPanelFace::onCommitShiny,this);
- childSetCommitCallback("combobox bumpiness",&LLPanelFace::onCommitBump,this);
- childSetCommitCallback("TexScaleU",&LLPanelFace::onCommitTextureInfo, this);
- childSetCommitCallback("checkbox flip s",&LLPanelFace::onCommitTextureInfo, this);
- childSetCommitCallback("TexScaleV",&LLPanelFace::onCommitTextureInfo, this);
- childSetCommitCallback("checkbox flip t",&LLPanelFace::onCommitTextureInfo, this);
- childSetCommitCallback("TexRot",&LLPanelFace::onCommitTextureInfo, this);
- childSetAction("button apply",&onClickApply,this);
- childSetCommitCallback("TexOffsetU",LLPanelFace::onCommitTextureInfo, this);
- childSetCommitCallback("TexOffsetV",LLPanelFace::onCommitTextureInfo, this);
- childSetAction("button align",onClickAutoFix,this);
clearCtrls();
return TRUE;
}
-LLPanelFace::LLPanelFace(const std::string& name)
-: LLPanel(name)
+LLPanelFace::LLPanelFace()
+: LLPanel()
{
}
@@ -387,16 +386,9 @@ void LLPanelFace::getState()
BOOL editable = objectp->permModify();
// only turn on auto-adjust button if there is a media renderer and the media is loaded
- childSetEnabled("textbox autofix",FALSE);
- //mLabelTexAutoFix->setEnabled ( FALSE );
- childSetEnabled("button align",FALSE);
- //mBtnAutoFix->setEnabled ( FALSE );
+ childSetEnabled("textbox autofix", editable);
+ childSetEnabled("button align", editable);
- if(LLViewerMedia::hasMedia())
- {
- childSetEnabled("textbox autofix",editable);
- childSetEnabled("button align",editable);
- }
//if ( LLMediaEngine::getInstance()->getMediaRenderer () )
// if ( LLMediaEngine::getInstance()->getMediaRenderer ()->isLoaded () )
// {
@@ -415,14 +407,40 @@ void LLPanelFace::getState()
LLUUID id;
struct f1 : public LLSelectedTEGetFunctor<LLUUID>
{
- LLUUID get(LLViewerObject* object, S32 te)
+ LLUUID get(LLViewerObject* object, S32 te_index)
{
- LLViewerImage* image = object->getTEImage(te);
- return image ? image->getID() : LLUUID::null;
+ LLUUID id;
+
+ LLViewerTexture* image = object->getTEImage(te_index);
+ if (image) id = image->getID();
+
+ if (!id.isNull() && LLViewerMedia::textureHasMedia(id))
+ {
+ LLTextureEntry *te = object->getTE(te_index);
+ if (te)
+ {
+ LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID()) : NULL ;
+ if(!tex)
+ {
+ tex = LLViewerFetchedTexture::sDefaultImagep;
+ }
+ if (tex)
+ {
+ id = tex->getID();
+ }
+ }
+ }
+ return id;
}
} func;
identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, id );
+ if(LLViewerMedia::textureHasMedia(id))
+ {
+ childSetEnabled("textbox autofix",editable);
+ childSetEnabled("button align",editable);
+ }
+
if (identical)
{
// All selected have the same texture
@@ -454,6 +472,7 @@ void LLPanelFace::getState()
}
}
}
+
LLAggregatePermissions texture_perms;
if(texture_ctrl)
@@ -787,6 +806,9 @@ void LLPanelFace::getState()
childSetEnabled("button align",FALSE);
childSetEnabled("button apply",FALSE);
+ //childSetEnabled("has media", FALSE);
+ //childSetEnabled("media info set", FALSE);
+
}
}
@@ -807,32 +829,25 @@ F32 LLPanelFace::valueGlow(LLViewerObject* object, S32 face)
}
-// static
-void LLPanelFace::onCommitColor(LLUICtrl* ctrl, void* userdata)
+void LLPanelFace::onCommitColor(const LLSD& data)
{
- LLPanelFace* self = (LLPanelFace*) userdata;
- self->sendColor();
+ sendColor();
}
-// static
-void LLPanelFace::onCommitAlpha(LLUICtrl* ctrl, void* userdata)
+void LLPanelFace::onCommitAlpha(const LLSD& data)
{
- LLPanelFace* self = (LLPanelFace*) userdata;
- self->sendAlpha();
+ sendAlpha();
}
-// static
-void LLPanelFace::onCancelColor(LLUICtrl* ctrl, void* userdata)
+void LLPanelFace::onCancelColor(const LLSD& data)
{
LLSelectMgr::getInstance()->selectionRevertColors();
}
-// static
-void LLPanelFace::onSelectColor(LLUICtrl* ctrl, void* userdata)
+void LLPanelFace::onSelectColor(const LLSD& data)
{
- LLPanelFace* self = (LLPanelFace*) userdata;
LLSelectMgr::getInstance()->saveSelectedObjectColors();
- self->sendColor();
+ sendColor();
}
// static
@@ -871,7 +886,7 @@ void LLPanelFace::onCommitGlow(LLUICtrl* ctrl, void* userdata)
}
// static
-BOOL LLPanelFace::onDragTexture(LLUICtrl*, LLInventoryItem* item, void*)
+BOOL LLPanelFace::onDragTexture(LLUICtrl*, LLInventoryItem* item)
{
BOOL accept = TRUE;
for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
@@ -888,28 +903,21 @@ BOOL LLPanelFace::onDragTexture(LLUICtrl*, LLInventoryItem* item, void*)
return accept;
}
-// static
-void LLPanelFace::onCommitTexture( LLUICtrl* ctrl, void* userdata )
+void LLPanelFace::onCommitTexture( const LLSD& data )
{
- LLPanelFace* self = (LLPanelFace*) userdata;
-
LLViewerStats::getInstance()->incStat(LLViewerStats::ST_EDIT_TEXTURE_COUNT );
-
- self->sendTexture();
+ sendTexture();
}
-// static
-void LLPanelFace::onCancelTexture(LLUICtrl* ctrl, void* userdata)
+void LLPanelFace::onCancelTexture(const LLSD& data)
{
LLSelectMgr::getInstance()->selectionRevertTextures();
}
-// static
-void LLPanelFace::onSelectTexture(LLUICtrl* ctrl, void* userdata)
+void LLPanelFace::onSelectTexture(const LLSD& data)
{
- LLPanelFace* self = (LLPanelFace*) userdata;
LLSelectMgr::getInstance()->saveSelectedObjectTextures();
- self->sendTexture();
+ sendTexture();
}
@@ -933,20 +941,34 @@ void LLPanelFace::onClickApply(void* userdata)
LLSelectMgr::getInstance()->selectionTexScaleAutofit( repeats_per_meter );
}
-// commit the fit media texture to prim button
-
struct LLPanelFaceSetMediaFunctor : public LLSelectedTEFunctor
{
virtual bool apply(LLViewerObject* object, S32 te)
{
- // only do this if it's a media texture
- if ( object->getTE ( te )->getID() == LLViewerMedia::getMediaTextureID() )
+ viewer_media_t pMediaImpl;
+
+ const LLTextureEntry* tep = object->getTE(te);
+ const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
+ if ( mep )
{
- S32 media_width, media_height;
- S32 texture_width, texture_height;
- if ( LLViewerMedia::getMediaSize( &media_width, &media_height )
- && LLViewerMedia::getTextureSize( &texture_width, &texture_height ) )
+ pMediaImpl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
+ }
+
+ if ( pMediaImpl.isNull())
+ {
+ // If we didn't find face media for this face, check whether this face is showing parcel media.
+ pMediaImpl = LLViewerMedia::getMediaImplFromTextureID(tep->getID());
+ }
+
+ if ( pMediaImpl.notNull())
+ {
+ LLPluginClassMedia *media = pMediaImpl->getMediaPlugin();
+ if(media)
{
+ S32 media_width = media->getWidth();
+ S32 media_height = media->getHeight();
+ S32 texture_width = media->getTextureWidth();
+ S32 texture_height = media->getTextureHeight();
F32 scale_s = (F32)media_width / (F32)texture_width;
F32 scale_t = (F32)media_height / (F32)texture_height;
@@ -969,3 +991,14 @@ void LLPanelFace::onClickAutoFix(void* userdata)
LLPanelFaceSendFunctor sendfunc;
LLSelectMgr::getInstance()->getSelection()->applyToObjects(&sendfunc);
}
+
+
+
+// TODO: I don't know who put these in or what these are for???
+void LLPanelFace::setMediaURL(const std::string& url)
+{
+}
+void LLPanelFace::setMediaType(const std::string& mime_type)
+{
+}
+
diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h
index a2ead0c8a2..6a8704ce14 100644
--- a/indra/newview/llpanelface.h
+++ b/indra/newview/llpanelface.h
@@ -47,15 +47,18 @@ class LLTextBox;
class LLTextureCtrl;
class LLUICtrl;
class LLViewerObject;
+class LLFloater;
class LLPanelFace : public LLPanel
{
public:
virtual BOOL postBuild();
- LLPanelFace(const std::string& name);
+ LLPanelFace();
virtual ~LLPanelFace();
void refresh();
+ void setMediaURL(const std::string& url);
+ void setMediaType(const std::string& mime_type);
protected:
void getState();
@@ -69,27 +72,30 @@ protected:
void sendShiny(); // applies and sends shininess
void sendFullbright(); // applies and sends full bright
void sendGlow();
+ void sendMedia();
- // this function is to return TRUE if the dra should succeed.
- static BOOL onDragTexture(LLUICtrl* ctrl, LLInventoryItem* item, void* ud);
+ // this function is to return TRUE if the drag should succeed.
+ static BOOL onDragTexture(LLUICtrl* ctrl, LLInventoryItem* item);
- static void onCommitTexture( LLUICtrl* ctrl, void* userdata);
- static void onCancelTexture( LLUICtrl* ctrl, void* userdata);
- static void onSelectTexture( LLUICtrl* ctrl, void* userdata);
- static void onCommitTextureInfo( LLUICtrl* ctrl, void* userdata);
- static void onCommitColor( LLUICtrl* ctrl, void* userdata);
- static void onCommitAlpha( LLUICtrl* ctrl, void* userdata);
- static void onCancelColor( LLUICtrl* ctrl, void* userdata);
- static void onSelectColor( LLUICtrl* ctrl, void* userdata);
+ void onCommitTexture(const LLSD& data);
+ void onCancelTexture(const LLSD& data);
+ void onSelectTexture(const LLSD& data);
+ void onCommitColor(const LLSD& data);
+ void onCommitAlpha(const LLSD& data);
+ void onCancelColor(const LLSD& data);
+ void onSelectColor(const LLSD& data);
+
+ static void onCommitTextureInfo( 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);
static void onCommitFullbright( LLUICtrl* ctrl, void* userdata);
static void onCommitGlow( LLUICtrl* ctrl, void *userdata);
-
+
static void onClickApply(void*);
static void onClickAutoFix(void*);
static F32 valueGlow(LLViewerObject* object, S32 face);
+
};
#endif
diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp
index d9d796fd9e..1d447a22d7 100644
--- a/indra/newview/llpanelgroup.cpp
+++ b/indra/newview/llpanelgroup.cpp
@@ -33,30 +33,46 @@
#include "llpanelgroup.h"
-#include "llagent.h"
+// Library includes
#include "llbutton.h"
-#include "llpanelgroupgeneral.h"
-#include "llpanelgrouproles.h"
-#include "llpanelgrouplandmoney.h"
-#include "llpanelgroupnotices.h"
#include "lltabcontainer.h"
#include "lltextbox.h"
-#include "llviewermessage.h"
#include "lluictrlfactory.h"
+
+// Viewer includes
+#include "llviewermessage.h"
#include "llviewerwindow.h"
#include "llappviewer.h"
-#include "llnotifications.h"
+#include "llnotificationsutil.h"
+#include "llfloaterreg.h"
+#include "llfloater.h"
+#include "llgroupactions.h"
+
+#include "llagent.h"
+
+#include "llsidetraypanelcontainer.h"
+
+#include "llpanelgroupnotices.h"
+#include "llpanelgroupgeneral.h"
-// static
-void* LLPanelGroupTab::createTab(void* data)
+#include "llsidetray.h"
+#include "llaccordionctrltab.h"
+#include "llaccordionctrl.h"
+
+static LLRegisterPanelClassWrapper<LLPanelGroup> t_panel_group("panel_group_info_sidetray");
+
+
+
+LLPanelGroupTab::LLPanelGroupTab()
+ : LLPanel(),
+ mAllowEdit(TRUE),
+ mHasModal(FALSE)
{
- LLUUID* group_id = static_cast<LLUUID*>(data);
- return new LLPanelGroupTab("panel group tab", *group_id);
+ mGroupID = LLUUID::null;
}
LLPanelGroupTab::~LLPanelGroupTab()
{
- mObservers.clear();
}
BOOL LLPanelGroupTab::isVisibleByAgent(LLAgent* agentp)
@@ -67,508 +83,436 @@ BOOL LLPanelGroupTab::isVisibleByAgent(LLAgent* agentp)
BOOL LLPanelGroupTab::postBuild()
{
- // Hook up the help button callback.
- LLButton* button = getChild<LLButton>("help_button");
- if (button)
- {
- button->setClickedCallback(onClickHelp);
- button->setCallbackUserData(this);
- }
-
- mHelpText = getString("help_text");
return TRUE;
}
-void LLPanelGroupTab::addObserver(LLPanelGroupTabObserver *obs)
+LLPanelGroup::LLPanelGroup()
+: LLPanel(),
+ LLGroupMgrObserver( LLUUID() ),
+ mAllowEdit( TRUE )
+ ,mShowingNotifyDialog(false)
{
- mObservers.insert(obs);
+ // Set up the factory callbacks.
+ // Roles sub tabs
+ LLGroupMgr::getInstance()->addObserver(this);
}
-void LLPanelGroupTab::removeObserver(LLPanelGroupTabObserver *obs)
+
+LLPanelGroup::~LLPanelGroup()
{
- mObservers.erase(obs);
+ LLGroupMgr::getInstance()->removeObserver(this);
+ if(LLVoiceClient::getInstance())
+ LLVoiceClient::getInstance()->removeObserver(this);
}
-void LLPanelGroupTab::notifyObservers()
+void LLPanelGroup::onOpen(const LLSD& key)
{
-
- for (observer_list_t::iterator iter = mObservers.begin();
- iter != mObservers.end(); )
+ if(!key.has("group_id"))
+ return;
+
+ LLUUID group_id = key["group_id"];
+ if(!key.has("action"))
{
- LLPanelGroupTabObserver* observer = *iter;
- observer->tabChanged();
-
- // safe way to incrament since changed may delete entries! (@!##%@!@&*!)
- iter = mObservers.upper_bound(observer);
+ setGroupID(group_id);
+ return;
}
-}
-// static
-void LLPanelGroupTab::onClickHelp(void* user_data)
-{
- LLPanelGroupTab* self = static_cast<LLPanelGroupTab*>(user_data);
- self->handleClickHelp();
-}
+ std::string str_action = key["action"];
-void LLPanelGroupTab::handleClickHelp()
-{
- // Display the help text.
- std::string help_text( getHelpText() );
- if ( !help_text.empty() )
+ if(str_action == "refresh")
{
- LLSD args;
- args["MESSAGE"] = help_text;
- LLFloater* parent_floater = gFloaterView->getParentFloater(this);
- LLNotification::Params params(parent_floater->contextualNotification("GenericAlert"));
- params.substitutions(args);
- LLNotifications::instance().add(params);
+ if(mID == group_id || group_id == LLUUID::null)
+ refreshData();
}
-}
-
-LLPanelGroup::LLPanelGroup(const std::string& filename,
- const std::string& name,
- const LLUUID& group_id,
- const std::string& initial_tab_selected)
-: LLPanel(name, LLRect(), FALSE),
- LLGroupMgrObserver( group_id ),
- mCurrentTab( NULL ),
- mRequestedTab( NULL ),
- mTabContainer( NULL ),
- mIgnoreTransition( FALSE ),
- mForceClose( FALSE ),
- mInitialTab(initial_tab_selected),
- mAllowEdit( TRUE ),
- mShowingNotifyDialog( FALSE )
-{
- // Set up the factory callbacks.
- mFactoryMap["general_tab"] = LLCallbackMap(LLPanelGroupGeneral::createTab,
- &mID);
- mFactoryMap["roles_tab"] = LLCallbackMap(LLPanelGroupRoles::createTab,
- &mID);
- mFactoryMap["notices_tab"] = LLCallbackMap(LLPanelGroupNotices::createTab,
- &mID);
- mFactoryMap["land_money_tab"]= LLCallbackMap(LLPanelGroupLandMoney::createTab,
- &mID);
- // Roles sub tabs
- mFactoryMap["members_sub_tab"] = LLCallbackMap(LLPanelGroupMembersSubTab::createTab, &mID);
- mFactoryMap["roles_sub_tab"] = LLCallbackMap(LLPanelGroupRolesSubTab::createTab, &mID);
- mFactoryMap["actions_sub_tab"] = LLCallbackMap(LLPanelGroupActionsSubTab::createTab, &mID);
-
- LLGroupMgr::getInstance()->addObserver(this);
-
- // Pass on construction of this panel to the control factory.
- LLUICtrlFactory::getInstance()->buildPanel(this, filename, &getFactoryMap());
- mFilename = filename;
-}
-
-LLPanelGroup::~LLPanelGroup()
-{
- LLGroupMgr::getInstance()->removeObserver(this);
-
- int i;
- int tab_count = mTabContainer->getTabCount();
-
- for (i = tab_count - 1; i >=0; --i)
+ else if(str_action == "close")
{
- LLPanelGroupTab* panelp =
- (LLPanelGroupTab*) mTabContainer->getPanelByIndex(i);
-
- if ( panelp ) panelp->removeObserver(this);
+ onBackBtnClick();
+ }
+ else if(str_action == "create")
+ {
+ setGroupID(LLUUID::null);
}
+ else if(str_action == "refresh_notices")
+ {
+ LLPanelGroupNotices* panel_notices = findChild<LLPanelGroupNotices>("group_notices_tab_panel");
+ if(panel_notices)
+ panel_notices->refreshNotices();
+ }
+
}
-void LLPanelGroup::updateTabVisibility()
+BOOL LLPanelGroup::postBuild()
{
- S32 i;
- S32 tab_count = mTabContainer->getTabCount();
-
- for (i = tab_count - 1; i >=0; --i)
- {
- LLPanelGroupTab* panelp =
- (LLPanelGroupTab*) mTabContainer->getPanelByIndex(i);
-
- BOOL visible = panelp->isVisibleByAgent(&gAgent) || gAgent.isGodlike();
- mTabContainer->enableTabButton(i, visible);
+ mDefaultNeedsApplyMesg = getString("default_needs_apply_text");
+ mWantApplyMesg = getString("want_apply_text");
- if ( !visible && mCurrentTab == panelp )
- {
- //we are disabling the currently selected tab
- //select the previous one
- mTabContainer->selectPrevTab();
- mCurrentTab =
- (LLPanelGroupTab*) mTabContainer->getCurrentPanel();
- }
- }
-}
+ LLButton* button;
+ button = getChild<LLButton>("btn_apply");
+ button->setClickedCallback(onBtnApply, this);
+ button->setVisible(true);
+ button->setEnabled(false);
+ button = getChild<LLButton>("btn_call");
+ button->setClickedCallback(onBtnGroupCallClicked, this);
-BOOL LLPanelGroup::postBuild()
-{
- mTabContainer = getChild<LLTabContainer>("group_tab_container");
+ button = getChild<LLButton>("btn_chat");
+ button->setClickedCallback(onBtnGroupChatClicked, this);
- if (mTabContainer)
- {
- // Select the initial tab specified via constructor
- const BOOL recurse = TRUE;
- LLPanelGroupTab* tabp =
- getChild<LLPanelGroupTab>(mInitialTab, recurse);
+ button = getChild<LLButton>("btn_join");
+ button->setVisible(false);
+ button->setEnabled(true);
- if (!tabp)
- {
- //our initial tab selection was invalid, just select the
- //first tab then or default to selecting the initial
- //selected tab specified in the layout file
- tabp = (LLPanelGroupTab*) mTabContainer->getCurrentPanel();
-
- //no tab was initially selected through constructor
- //or the XML, select the first tab
- if (!tabp)
- {
- mTabContainer->selectFirstTab();
- tabp = (LLPanelGroupTab*) mTabContainer->getCurrentPanel();
- }
- }
- else
- {
- mTabContainer->selectTabPanel(tabp);
- }
+ button = getChild<LLButton>("btn_cancel");
+ button->setVisible(false); button->setEnabled(true);
- mCurrentTab = tabp;
+ button = getChild<LLButton>("btn_refresh");
+ button->setClickedCallback(onBtnRefresh, this);
+ button->setVisible(mAllowEdit);
- // Add click callbacks.
- S32 i;
- S32 tab_count = mTabContainer->getTabCount();
+ getChild<LLButton>("btn_create")->setVisible(false);
- for (i = tab_count - 1; i >=0; --i)
- {
- LLPanel* tab_panel = mTabContainer->getPanelByIndex(i);
- LLPanelGroupTab* panelp =(LLPanelGroupTab*)tab_panel; // bit of a hack
+ childSetCommitCallback("back",boost::bind(&LLPanelGroup::onBackBtnClick,this),NULL);
- // Pass on whether or not to allow edit to tabs.
- panelp->setAllowEdit(mAllowEdit);
- panelp->addObserver(this);
+ childSetCommitCallback("btn_create",boost::bind(&LLPanelGroup::onBtnCreate,this),NULL);
+ childSetCommitCallback("btn_join",boost::bind(&LLPanelGroup::onBtnJoin,this),NULL);
+ childSetCommitCallback("btn_cancel",boost::bind(&LLPanelGroup::onBtnCancel,this),NULL);
- mTabContainer->setTabChangeCallback(panelp, onClickTab);
- mTabContainer->setTabUserData(panelp, this);
- }
- updateTabVisibility();
+ LLPanelGroupTab* panel_general = findChild<LLPanelGroupTab>("group_general_tab_panel");
+ LLPanelGroupTab* panel_roles = findChild<LLPanelGroupTab>("group_roles_tab_panel");
+ LLPanelGroupTab* panel_notices = findChild<LLPanelGroupTab>("group_notices_tab_panel");
+ LLPanelGroupTab* panel_land = findChild<LLPanelGroupTab>("group_land_tab_panel");
- // Act as though this tab was just activated.
- mCurrentTab->activate();
- }
+ if(panel_general) mTabs.push_back(panel_general);
+ if(panel_roles) mTabs.push_back(panel_roles);
+ if(panel_notices) mTabs.push_back(panel_notices);
+ if(panel_land) mTabs.push_back(panel_land);
- mDefaultNeedsApplyMesg = getString("default_needs_apply_text");
- mWantApplyMesg = getString("want_apply_text");
+ if(panel_general)
+ panel_general->setupCtrls(this);
- LLButton* button = getChild<LLButton>("btn_ok");
- if (button)
- {
- button->setClickedCallback(onBtnOK);
- button->setCallbackUserData(this);
- button->setVisible(mAllowEdit);
- }
+ gVoiceClient->addObserver(this);
- button = getChild<LLButton>("btn_cancel");
- if (button)
- {
- button->setClickedCallback(onBtnCancel);
- button->setCallbackUserData(this);
- button->setVisible(mAllowEdit);
- }
+ return TRUE;
+}
- button = getChild<LLButton>("btn_apply");
- if (button)
- {
- button->setClickedCallback(onBtnApply);
- button->setVisible(mAllowEdit);
- button->setEnabled(FALSE);
+void LLPanelGroup::reposButton(const std::string& name)
+{
+ LLButton* button = findChild<LLButton>(name);
+ if(!button)
+ return;
+ LLRect btn_rect = button->getRect();
+ btn_rect.setLeftTopAndSize( btn_rect.mLeft, btn_rect.getHeight() + 2, btn_rect.getWidth(), btn_rect.getHeight());
+ button->setRect(btn_rect);
+}
- mApplyBtn = button;
- }
+void LLPanelGroup::reposButtons()
+{
+ LLButton* button_refresh = findChild<LLButton>("btn_refresh");
+ LLButton* button_cancel = findChild<LLButton>("btn_cancel");
- button = getChild<LLButton>("btn_refresh");
- if (button)
+ if(button_refresh && button_cancel && button_refresh->getVisible() && button_cancel->getVisible())
{
- button->setClickedCallback(onBtnRefresh);
- button->setCallbackUserData(this);
- button->setVisible(mAllowEdit);
+ LLRect btn_refresh_rect = button_refresh->getRect();
+ LLRect btn_cancel_rect = button_cancel->getRect();
+ btn_refresh_rect.setLeftTopAndSize( btn_cancel_rect.mLeft + btn_cancel_rect.getWidth() + 2,
+ btn_refresh_rect.getHeight() + 2, btn_refresh_rect.getWidth(), btn_refresh_rect.getHeight());
+ button_refresh->setRect(btn_refresh_rect);
}
- return TRUE;
+ reposButton("btn_apply");
+ reposButton("btn_create");
+ reposButton("btn_refresh");
+ reposButton("btn_cancel");
+ reposButton("btn_chat");
+ reposButton("btn_call");
}
-void LLPanelGroup::changed(LLGroupChange gc)
+void LLPanelGroup::reshape(S32 width, S32 height, BOOL called_from_parent )
{
- updateTabVisibility();
- // Notify the currently active panel that group manager information has changed.
- LLPanelGroupTab* panelp = (LLPanelGroupTab*) mTabContainer->getCurrentPanel();
+ LLPanel::reshape(width, height, called_from_parent );
+
+ reposButtons();
+}
- if (panelp)
+void LLPanelGroup::onBackBtnClick()
+{
+ LLSideTrayPanelContainer* parent = dynamic_cast<LLSideTrayPanelContainer*>(getParent());
+ if(parent)
{
- panelp->update(gc);
+ parent->openPreviousPanel();
}
}
-// PanelGroupTab observer trigger
-void LLPanelGroup::tabChanged()
+
+void LLPanelGroup::onBtnCreate()
{
- //some tab information has changed,....enable/disable the apply button
- //based on if they need an apply
- if ( mApplyBtn )
+ LLPanelGroupGeneral* panel_general = findChild<LLPanelGroupGeneral>("group_general_tab_panel");
+ if(!panel_general)
+ return;
+ std::string apply_mesg;
+ if(panel_general->apply(apply_mesg))//yes yes you need to call apply to create...
+ return;
+ if ( !apply_mesg.empty() )
{
- std::string mesg;
- mApplyBtn->setEnabled(mCurrentTab->needsApply(mesg));
+ LLSD args;
+ args["MESSAGE"] = apply_mesg;
+ LLNotificationsUtil::add("GenericAlert", args);
}
}
-// static
-void LLPanelGroup::onClickTab(void* user_data, bool from_click)
+void LLPanelGroup::onBtnRefresh(void* user_data)
{
LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
- self->handleClickTab();
+ self->refreshData();
}
-void LLPanelGroup::handleClickTab()
+void LLPanelGroup::onBtnApply(void* user_data)
{
- // If we are already handling a transition,
- // ignore this.
- if (mIgnoreTransition)
- {
- return;
- }
+ LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
+ self->apply();
+}
- mRequestedTab = (LLPanelGroupTab*) mTabContainer->getCurrentPanel();
+void LLPanelGroup::onBtnGroupCallClicked(void* user_data)
+{
+ LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
+ self->callGroup();
+}
- // Make sure they aren't just clicking the same tab...
- if (mRequestedTab == mCurrentTab)
- {
- return;
- }
+void LLPanelGroup::onBtnGroupChatClicked(void* user_data)
+{
+ LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
+ self->chatGroup();
+}
- // Try to switch from the current panel to the panel the user selected.
- attemptTransition();
+void LLPanelGroup::onBtnJoin()
+{
+ lldebugs << "joining group: " << mID << llendl;
+ LLGroupActions::join(mID);
}
-void LLPanelGroup::setGroupID(const LLUUID& group_id)
+void LLPanelGroup::onBtnCancel()
{
- LLRect rect(getRect());
+ onBackBtnClick();
+}
- LLGroupMgr::getInstance()->removeObserver(this);
- mID = group_id;
- LLGroupMgr::getInstance()->addObserver(this);
- //TODO: this is really bad, we should add a method
- // where the panels can just update themselves
- // on a group id change. Similar to update() but with a group
- // id change.
- // For now, rebuild panel
- //delete children and rebuild panel
- deleteAllChildren();
- LLUICtrlFactory::getInstance()->buildPanel(this, mFilename, &getFactoryMap());
+void LLPanelGroup::changed(LLGroupChange gc)
+{
+ for(std::vector<LLPanelGroupTab* >::iterator it = mTabs.begin();it!=mTabs.end();++it)
+ (*it)->update(gc);
+ update(gc);
}
-void LLPanelGroup::selectTab(std::string tab_name)
+// virtual
+void LLPanelGroup::onChange(EStatusType status, const std::string &channelURI, bool proximal)
{
- const BOOL recurse = TRUE;
-
- LLPanelGroupTab* tabp =
- getChild<LLPanelGroupTab>(tab_name, recurse);
-
- if ( tabp && mTabContainer )
+ if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL)
{
- mTabContainer->selectTabPanel(tabp);
- onClickTab(this, false);
+ return;
}
+
+ childSetEnabled("btn_call", LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking());
}
-BOOL LLPanelGroup::canClose()
+void LLPanelGroup::notifyObservers()
{
- if (mShowingNotifyDialog) return FALSE;
- if (mCurrentTab && mCurrentTab->hasModal()) return FALSE;
- if (mForceClose || !mAllowEdit) return TRUE;
-
- // Try to switch from the current panel to nothing, indicating a close action.
- mRequestedTab = NULL;
- return attemptTransition();
+ changed(GC_ALL);
}
-BOOL LLPanelGroup::attemptTransition()
+void LLPanelGroup::update(LLGroupChange gc)
{
- // Check if the current tab needs to be applied.
- std::string mesg;
- if (mCurrentTab && mCurrentTab->needsApply(mesg))
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID);
+ if(gdatap)
{
- // If no message was provided, give a generic one.
- if (mesg.empty())
- {
- mesg = mDefaultNeedsApplyMesg;
- }
- // Create a notify box, telling the user about the unapplied tab.
- LLSD args;
- args["NEEDS_APPLY_MESSAGE"] = mesg;
- args["WANT_APPLY_MESSAGE"] = mWantApplyMesg;
- LLNotifications::instance().add("PanelGroupApply", args, LLSD(),
- boost::bind(&LLPanelGroup::handleNotifyCallback, this, _1, _2));
- mShowingNotifyDialog = TRUE;
+ childSetValue("group_name", gdatap->mName);
+ childSetToolTip("group_name",gdatap->mName);
+
+ LLButton* btn_join = getChild<LLButton>("btn_join");
+ LLUICtrl* join_text = getChild<LLUICtrl>("join_cost_text");
+
+ LLGroupData agent_gdatap;
+ bool is_member = gAgent.getGroupData(mID,agent_gdatap);
+ bool join_btn_visible = !is_member && gdatap->mOpenEnrollment;
- // We need to reselect the current tab, since it isn't finished.
- if (mTabContainer)
- {
- // selectTabPanel is going to trigger another
- // click event. We want to ignore it so that
- // mRequestedTab is not updated.
- mIgnoreTransition = TRUE;
- mTabContainer->selectTabPanel( mCurrentTab );
- mIgnoreTransition = FALSE;
- }
- // Returning FALSE will block a close action from finishing until
- // we get a response back from the user.
- return FALSE;
- }
- else
- {
- // The current panel didn't have anything it needed to apply.
- if ( mRequestedTab )
+ btn_join->setVisible(join_btn_visible);
+ join_text->setVisible(join_btn_visible);
+
+ if(join_btn_visible)
{
- transitionToTab();
+ LLStringUtil::format_map_t string_args;
+ std::string fee_buff;
+ if(gdatap->mMembershipFee)
+ {
+ string_args["[AMOUNT]"] = llformat("%d", gdatap->mMembershipFee);
+ fee_buff = getString("group_join_btn", string_args);
+
+ }
+ else
+ {
+ fee_buff = getString("group_join_free", string_args);
+ }
+ childSetValue("join_cost_text",fee_buff);
}
- // Returning TRUE will allow any close action to proceed.
- return TRUE;
}
}
-void LLPanelGroup::transitionToTab()
+void LLPanelGroup::setGroupID(const LLUUID& group_id)
{
- // Tell the current panel that it is being deactivated.
- if (mCurrentTab)
+ std::string str_group_id;
+ group_id.toString(str_group_id);
+
+ bool is_same_id = group_id == mID;
+
+ LLGroupMgr::getInstance()->removeObserver(this);
+ mID = group_id;
+ LLGroupMgr::getInstance()->addObserver(this);
+
+ for(std::vector<LLPanelGroupTab* >::iterator it = mTabs.begin();it!=mTabs.end();++it)
+ (*it)->setGroupID(group_id);
+
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID);
+ if(gdatap)
{
- mCurrentTab->deactivate();
+ childSetValue("group_name", gdatap->mName);
+ childSetToolTip("group_name",gdatap->mName);
}
+
+ LLButton* button_apply = findChild<LLButton>("btn_apply");
+ LLButton* button_refresh = findChild<LLButton>("btn_refresh");
+ LLButton* button_create = findChild<LLButton>("btn_create");
+ LLButton* button_join = findChild<LLButton>("btn_join");
+ LLButton* button_cancel = findChild<LLButton>("btn_cancel");
+ LLButton* button_call = findChild<LLButton>("btn_call");
+ LLButton* button_chat = findChild<LLButton>("btn_chat");
+
+
+ bool is_null_group_id = group_id == LLUUID::null;
+ if(button_apply)
+ button_apply->setVisible(!is_null_group_id);
+ if(button_refresh)
+ button_refresh->setVisible(!is_null_group_id);
+
+ if(button_create)
+ button_create->setVisible(is_null_group_id);
+ if(button_cancel)
+ button_cancel->setVisible(!is_null_group_id);
+
+ if(button_call)
+ button_call->setVisible(!is_null_group_id);
+ if(button_chat)
+ button_chat->setVisible(!is_null_group_id);
+
+ getChild<LLUICtrl>("prepend_founded_by")->setVisible(!is_null_group_id);
+
+ LLAccordionCtrl* tab_ctrl = findChild<LLAccordionCtrl>("group_accordion");
+ if(tab_ctrl)
+ tab_ctrl->reset();
+
+ LLAccordionCtrlTab* tab_general = findChild<LLAccordionCtrlTab>("group_general_tab");
+ LLAccordionCtrlTab* tab_roles = findChild<LLAccordionCtrlTab>("group_roles_tab");
+ LLAccordionCtrlTab* tab_notices = findChild<LLAccordionCtrlTab>("group_notices_tab");
+ LLAccordionCtrlTab* tab_land = findChild<LLAccordionCtrlTab>("group_land_tab");
+
+
+ if(!tab_general || !tab_roles || !tab_notices || !tab_land)
+ return;
- // If the requested panel exists, activate it.
- if (mRequestedTab)
+ if(button_join)
+ button_join->setVisible(false);
+
+
+ if(is_null_group_id)//creating new group
{
- // This is now the current tab;
- mCurrentTab = mRequestedTab;
- mCurrentTab->activate();
+ if(!tab_general->getDisplayChildren())
+ tab_general->changeOpenClose(tab_general->getDisplayChildren());
+
+ if(tab_roles->getDisplayChildren())
+ tab_roles->changeOpenClose(tab_roles->getDisplayChildren());
+ if(tab_notices->getDisplayChildren())
+ tab_notices->changeOpenClose(tab_notices->getDisplayChildren());
+ if(tab_land->getDisplayChildren())
+ tab_land->changeOpenClose(tab_land->getDisplayChildren());
+
+ tab_roles->setVisible(false);
+ tab_notices->setVisible(false);
+ tab_land->setVisible(false);
+
+ getChild<LLUICtrl>("group_name")->setVisible(false);
+ getChild<LLUICtrl>("group_name_editor")->setVisible(true);
+
+ if(button_call)
+ button_call->setVisible(false);
+ if(button_chat)
+ button_chat->setVisible(false);
}
- else // NULL requested indicates a close action.
+ else
{
- close();
- }
-}
-
-bool LLPanelGroup::handleNotifyCallback(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotification::getSelectedOption(notification, response);
- mShowingNotifyDialog = FALSE;
- switch (option)
- {
- case 0: // "Apply Changes"
- // Try to apply changes, and switch to the requested tab.
- if ( !apply() )
+ if(!is_same_id)
{
- // There was a problem doing the apply.
- // Skip switching tabs.
- break;
+ if(!tab_general->getDisplayChildren())
+ tab_general->changeOpenClose(tab_general->getDisplayChildren());
+ if(tab_roles->getDisplayChildren())
+ tab_roles->changeOpenClose(tab_roles->getDisplayChildren());
+ if(tab_notices->getDisplayChildren())
+ tab_notices->changeOpenClose(tab_notices->getDisplayChildren());
+ if(tab_land->getDisplayChildren())
+ tab_land->changeOpenClose(tab_land->getDisplayChildren());
}
- // This panel's info successfully applied.
- // Switch to the next panel.
- mIgnoreTransition = TRUE;
- mTabContainer->selectTabPanel( mRequestedTab );
- mIgnoreTransition = FALSE;
- transitionToTab();
- break;
- case 1: // "Ignore Changes"
- // Switch to the requested panel without applying changes
- // (Changes may already have been applied in the previous block)
- mCurrentTab->cancel();
- mIgnoreTransition = TRUE;
- mTabContainer->selectTabPanel( mRequestedTab );
- mIgnoreTransition = FALSE;
- transitionToTab();
- break;
- case 2: // "Cancel"
- default:
- // Do nothing. The user is canceling the action.
- // If we were quitting, we didn't really mean it.
- LLAppViewer::instance()->abortQuit();
- break;
- }
- return false;
-}
-
-// static
-void LLPanelGroup::onBtnOK(void* user_data)
-{
- LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
- // If we are able to apply changes, then close.
- if(self->apply())
- {
- self->close();
+ LLGroupData agent_gdatap;
+ bool is_member = gAgent.getGroupData(mID,agent_gdatap);
+
+ tab_roles->setVisible(is_member);
+ tab_notices->setVisible(is_member);
+ tab_land->setVisible(is_member);
+
+ getChild<LLUICtrl>("group_name")->setVisible(true);
+ getChild<LLUICtrl>("group_name_editor")->setVisible(false);
+
+ if(button_apply)
+ button_apply->setVisible(is_member);
+ if(button_call)
+ button_call->setVisible(is_member);
+ if(button_chat)
+ button_chat->setVisible(is_member);
}
-}
-// static
-void LLPanelGroup::onBtnCancel(void* user_data)
-{
- LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
- self->close();
-}
-
-// static
-void LLPanelGroup::onBtnApply(void* user_data)
-{
- LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
- self->apply();
+ reposButtons();
}
-bool LLPanelGroup::apply()
+bool LLPanelGroup::apply(LLPanelGroupTab* tab)
{
- // Pass this along to the currently visible tab.
- if (!mTabContainer) return false;
+ if(!tab)
+ return false;
- LLPanelGroupTab* panelp = (LLPanelGroupTab*) mTabContainer->getCurrentPanel();
- if (!panelp) return false;
-
std::string mesg;
- if ( !panelp->needsApply(mesg) )
- {
- // We don't need to apply anything.
- // We're done.
+ if ( !tab->needsApply(mesg) )
return true;
- }
-
- // Ignore the needs apply message.
- // Try to do the actual apply.
+
std::string apply_mesg;
- if ( panelp->apply( apply_mesg ) )
- {
- // Everything worked. We're done.
+ if(tab->apply( apply_mesg ) )
return true;
- }
-
- // There was a problem doing the actual apply.
- // Inform the user.
+
if ( !apply_mesg.empty() )
{
LLSD args;
args["MESSAGE"] = apply_mesg;
- LLNotifications::instance().add("GenericAlert", args);
+ LLNotificationsUtil::add("GenericAlert", args);
}
-
return false;
}
-// static
-void LLPanelGroup::onBtnRefresh(void* user_data)
+bool LLPanelGroup::apply()
{
- LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
- self->refreshData();
+ return apply(findChild<LLPanelGroupTab>("group_general_tab_panel"))
+ && apply(findChild<LLPanelGroupTab>("group_roles_tab_panel"))
+ && apply(findChild<LLPanelGroupTab>("group_notices_tab_panel"))
+ && apply(findChild<LLPanelGroupTab>("group_land_tab_panel"))
+ ;
}
+
// virtual
void LLPanelGroup::draw()
{
@@ -579,38 +523,40 @@ void LLPanelGroup::draw()
mRefreshTimer.stop();
childEnable("btn_refresh");
}
- if (mCurrentTab)
+
+ LLButton* button_apply = findChild<LLButton>("btn_apply");
+
+ if(button_apply && button_apply->getVisible())
{
+ bool enable = false;
std::string mesg;
- childSetEnabled("btn_apply", mCurrentTab->needsApply(mesg));
- }
+ for(std::vector<LLPanelGroupTab* >::iterator it = mTabs.begin();it!=mTabs.end();++it)
+ enable = enable || (*it)->needsApply(mesg);
+ childSetEnabled("btn_apply", enable);
+ }
}
void LLPanelGroup::refreshData()
{
LLGroupMgr::getInstance()->clearGroupData(getID());
- mCurrentTab->activate();
+ setGroupID(getID());
+
// 5 second timeout
childDisable("btn_refresh");
mRefreshTimer.start();
mRefreshTimer.setTimerExpirySec(5);
}
-void LLPanelGroup::close()
+void LLPanelGroup::callGroup()
{
- // Pass this to the parent, if it is a floater.
- LLView* viewp = getParent();
- LLFloater* floaterp = dynamic_cast<LLFloater*>(viewp);
- if (floaterp)
- {
- // First, set the force close flag, since the floater
- // will be asking us whether it can close.
- mForceClose = TRUE;
- // Tell the parent floater to close.
- floaterp->close();
- }
+ LLGroupActions::startCall(getID());
+}
+
+void LLPanelGroup::chatGroup()
+{
+ LLGroupActions::startIM(getID());
}
void LLPanelGroup::showNotice(const std::string& subject,
@@ -619,7 +565,8 @@ void LLPanelGroup::showNotice(const std::string& subject,
const std::string& inventory_name,
LLOfferInfo* inventory_offer)
{
- if (mCurrentTab->getName() != "notices_tab")
+ LLPanelGroupNotices* panel_notices = findChild<LLPanelGroupNotices>("group_notices_tab_panel");
+ if(!panel_notices)
{
// We need to clean up that inventory offer.
if (inventory_offer)
@@ -628,8 +575,103 @@ void LLPanelGroup::showNotice(const std::string& subject,
}
return;
}
+ panel_notices->showNotice(subject,message,has_inventory,inventory_name,inventory_offer);
+}
+
+
+
+
+//static
+void LLPanelGroup::refreshCreatedGroup(const LLUUID& group_id)
+{
+ LLPanelGroup* panel = LLSideTray::getInstance()->findChild<LLPanelGroup>("panel_group_info_sidetray");
+ if(!panel)
+ return;
+ panel->setGroupID(group_id);
+}
- LLPanelGroupNotices* notices = static_cast<LLPanelGroupNotices*>(mCurrentTab);
+//static
+
+void LLPanelGroup::showNotice(const std::string& subject,
+ const std::string& message,
+ const LLUUID& group_id,
+ const bool& has_inventory,
+ const std::string& inventory_name,
+ LLOfferInfo* inventory_offer)
+{
+ LLPanelGroup* panel = LLSideTray::getInstance()->findChild<LLPanelGroup>("panel_group_info_sidetray");
+ if(!panel)
+ return;
+
+ if(panel->getID() != group_id)//???? only for current group_id or switch panels? FIXME
+ return;
+ panel->showNotice(subject,message,has_inventory,inventory_name,inventory_offer);
- notices->showNotice(subject,message,has_inventory,inventory_name,inventory_offer);
}
+
+bool LLPanelGroup::canClose()
+{
+ if(getVisible() == false)
+ return true;
+
+ bool need_save = false;
+ std::string mesg;
+ for(std::vector<LLPanelGroupTab* >::iterator it = mTabs.begin();it!=mTabs.end();++it)
+ if(need_save|=(*it)->needsApply(mesg))
+ break;
+ if(!need_save)
+ return false;
+ // If no message was provided, give a generic one.
+ if (mesg.empty())
+ {
+ mesg = mDefaultNeedsApplyMesg;
+ }
+ // Create a notify box, telling the user about the unapplied tab.
+ LLSD args;
+ args["NEEDS_APPLY_MESSAGE"] = mesg;
+ args["WANT_APPLY_MESSAGE"] = mWantApplyMesg;
+
+ LLNotificationsUtil::add("SaveChanges", args, LLSD(), boost::bind(&LLPanelGroup::handleNotifyCallback,this, _1, _2));
+
+ mShowingNotifyDialog = true;
+
+ return false;
+}
+
+bool LLPanelGroup::notifyChildren(const LLSD& info)
+{
+ if(info.has("request") && mID.isNull() )
+ {
+ std::string str_action = info["request"];
+
+ if (str_action == "quit" )
+ {
+ canClose();
+ return true;
+ }
+ if(str_action == "wait_quit")
+ return mShowingNotifyDialog;
+ }
+ return false;
+}
+bool LLPanelGroup::handleNotifyCallback(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ mShowingNotifyDialog = false;
+ switch (option)
+ {
+ case 0: // "Apply Changes"
+ apply();
+ break;
+ case 1: // "Ignore Changes"
+ break;
+ case 2: // "Cancel"
+ default:
+ // Do nothing. The user is canceling the action.
+ // If we were quitting, we didn't really mean it.
+ LLAppViewer::instance()->abortQuit();
+ break;
+ }
+ return false;
+}
+
diff --git a/indra/newview/llpanelgroup.h b/indra/newview/llpanelgroup.h
index 445fb28502..8c84695677 100644
--- a/indra/newview/llpanelgroup.h
+++ b/indra/newview/llpanelgroup.h
@@ -35,6 +35,7 @@
#include "llgroupmgr.h"
#include "llpanel.h"
#include "lltimer.h"
+#include "llvoiceclient.h"
struct LLOfferInfo;
@@ -45,101 +46,101 @@ class LLPanelGroupTab;
class LLTabContainer;
class LLAgent;
-class LLPanelGroupTabObserver
-{
-public:
- LLPanelGroupTabObserver() {};
- virtual ~LLPanelGroupTabObserver(){};
- virtual void tabChanged() = 0;
-};
class LLPanelGroup : public LLPanel,
- public LLGroupMgrObserver,
- public LLPanelGroupTabObserver
+ public LLGroupMgrObserver,
+ public LLVoiceClientStatusObserver
{
public:
- LLPanelGroup(const std::string& filename,
- const std::string& name,
- const LLUUID& group_id,
- const std::string& initial_tab_selected = std::string());
+ LLPanelGroup();
virtual ~LLPanelGroup();
virtual BOOL postBuild();
- static void onBtnOK(void*);
- static void onBtnCancel(void*);
- static void onBtnApply(void*);
- static void onBtnRefresh(void*);
- static void onClickTab(void*,bool);
- void handleClickTab();
-
void setGroupID(const LLUUID& group_id);
- void selectTab(std::string tab_name);
- // Called when embedded in a floater during a close attempt.
- BOOL canClose();
-
- // Checks if the current tab needs to be applied, and tries to switch to the requested tab.
- BOOL attemptTransition();
-
- // Switches to the requested tab (will close() if requested is NULL)
- void transitionToTab();
-
- void updateTabVisibility();
-
- // Used by attemptTransition to query the user's response to a tab that needs to apply.
- bool handleNotifyCallback(const LLSD& notification, const LLSD& response);
-
- bool apply();
- void refreshData();
- void close();
void draw();
+ void onOpen(const LLSD& key);
+
// Group manager observer trigger.
virtual void changed(LLGroupChange gc);
- // PanelGroupTab observer trigger
- virtual void tabChanged();
-
- void setAllowEdit(BOOL v) { mAllowEdit = v; }
+ // Implements LLVoiceClientStatusObserver::onChange() to enable the call
+ // button when voice is available
+ /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
void showNotice(const std::string& subject,
const std::string& message,
const bool& has_inventory,
const std::string& inventory_name,
LLOfferInfo* inventory_offer);
+
+ void notifyObservers();
+
+ bool apply();
+ void refreshData();
+ void callGroup();
+ void chatGroup();
+
+ virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+ void setAllowEdit(BOOL v) { mAllowEdit = v; }
+
+
+ static void refreshCreatedGroup(const LLUUID& group_id);
+
+ static void showNotice(const std::string& subject,
+ const std::string& message,
+ const LLUUID& group_id,
+ const bool& has_inventory,
+ const std::string& inventory_name,
+ LLOfferInfo* inventory_offer);
+
+
+ bool notifyChildren (const LLSD& info);
+ bool handleNotifyCallback(const LLSD&, const LLSD&);
+
protected:
- LLPanelGroupTab* mCurrentTab;
- LLPanelGroupTab* mRequestedTab;
- LLTabContainer* mTabContainer;
- BOOL mIgnoreTransition;
+ virtual void update(LLGroupChange gc);
- LLButton* mApplyBtn;
+ void onBtnCreate();
+ void onBackBtnClick();
+ void onBtnJoin();
+ void onBtnCancel();
- LLTimer mRefreshTimer;
+ static void onBtnApply(void*);
+ static void onBtnRefresh(void*);
+ static void onBtnGroupCallClicked(void*);
+ static void onBtnGroupChatClicked(void*);
- BOOL mForceClose;
+ void reposButton(const std::string& name);
+ void reposButtons();
+
+
+protected:
+ bool apply(LLPanelGroupTab* tab);
+ bool canClose();
- std::string mInitialTab;
- std::string mFilename;
+ bool mShowingNotifyDialog;
+
+ LLTimer mRefreshTimer;
+
+ BOOL mAllowEdit;
std::string mDefaultNeedsApplyMesg;
std::string mWantApplyMesg;
- BOOL mAllowEdit;
- BOOL mShowingNotifyDialog;
+ std::vector<LLPanelGroupTab* > mTabs;
+
};
class LLPanelGroupTab : public LLPanel
{
public:
- LLPanelGroupTab(const std::string& name, const LLUUID& group_id)
- : LLPanel(name), mGroupID(group_id), mAllowEdit(TRUE), mHasModal(FALSE) { }
+ LLPanelGroupTab();
virtual ~LLPanelGroupTab();
- // Factory that returns a new LLPanelGroupFoo tab.
- static void* createTab(void* data);
-
// Triggered when the tab becomes active.
virtual void activate() { }
@@ -163,13 +164,6 @@ public:
// Triggered when group information changes in the group manager.
virtual void update(LLGroupChange gc) { }
- // This is the text to be displayed when a help button is pressed.
- virtual std::string getHelpText() const { return mHelpText; }
-
- // Display anything returned by getHelpText
- static void onClickHelp(void* data);
- void handleClickHelp();
-
// This just connects the help button callback.
virtual BOOL postBuild();
@@ -177,20 +171,18 @@ public:
void setAllowEdit(BOOL v) { mAllowEdit = v; }
- void addObserver(LLPanelGroupTabObserver *obs);
- void removeObserver(LLPanelGroupTabObserver *obs);
- void notifyObservers();
+ virtual void setGroupID(const LLUUID& id) {mGroupID = id;};
+
+ void notifyObservers() {};
+
+ const LLUUID& getGroupID() const { return mGroupID;}
+
+ virtual void setupCtrls (LLPanel* parent) {};
protected:
LLUUID mGroupID;
- LLTabContainer* mTabContainer;
- std::string mHelpText;
-
BOOL mAllowEdit;
BOOL mHasModal;
-
- typedef std::set<LLPanelGroupTabObserver*> observer_list_t;
- observer_list_t mObservers;
};
#endif // LL_LLPANELGROUP_H
diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp
index 3dc5e032c5..21b253223f 100644
--- a/indra/newview/llpanelgroupgeneral.cpp
+++ b/indra/newview/llpanelgroupgeneral.cpp
@@ -37,49 +37,43 @@
#include "lluictrlfactory.h"
#include "llagent.h"
#include "roles_constants.h"
-#include "llfloateravatarinfo.h"
-#include "llfloatergroupinfo.h"
// UI elements
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#include "lldbstrings.h"
+#include "llavataractions.h"
+#include "llgroupactions.h"
#include "lllineeditor.h"
#include "llnamebox.h"
#include "llnamelistctrl.h"
+#include "llnotificationsutil.h"
+#include "llscrolllistitem.h"
#include "llspinctrl.h"
-#include "llstatusbar.h" // can_afford_transaction()
#include "lltextbox.h"
#include "lltexteditor.h"
#include "lltexturectrl.h"
+#include "lltrans.h"
#include "llviewerwindow.h"
+static LLRegisterPanelClassWrapper<LLPanelGroupGeneral> t_panel_group_general("panel_group_general");
+
// consts
const S32 MATURE_CONTENT = 1;
const S32 NON_MATURE_CONTENT = 2;
const S32 DECLINE_TO_STATE = 0;
-// static
-void* LLPanelGroupGeneral::createTab(void* data)
-{
- LLUUID* group_id = static_cast<LLUUID*>(data);
- return new LLPanelGroupGeneral("panel group general", *group_id);
-}
-
-LLPanelGroupGeneral::LLPanelGroupGeneral(const std::string& name,
- const LLUUID& group_id)
-: LLPanelGroupTab(name, group_id),
+LLPanelGroupGeneral::LLPanelGroupGeneral()
+: LLPanelGroupTab(),
mPendingMemberUpdate(FALSE),
mChanged(FALSE),
mFirstUse(TRUE),
mGroupNameEditor(NULL),
- mGroupName(NULL),
mFounderName(NULL),
mInsignia(NULL),
mEditCharter(NULL),
- mBtnJoinGroup(NULL),
mListVisibleMembers(NULL),
mCtrlShowInGroupList(NULL),
mComboMature(NULL),
@@ -100,74 +94,37 @@ LLPanelGroupGeneral::~LLPanelGroupGeneral()
BOOL LLPanelGroupGeneral::postBuild()
{
- llinfos << "LLPanelGroupGeneral::postBuild()" << llendl;
-
bool recurse = true;
- // General info
- mGroupNameEditor = getChild<LLLineEditor>("group_name_editor", recurse);
- mGroupName = getChild<LLTextBox>("group_name", recurse);
-
- mInsignia = getChild<LLTextureCtrl>("insignia", recurse);
- if (mInsignia)
- {
- mInsignia->setCommitCallback(onCommitAny);
- mInsignia->setCallbackUserData(this);
- mDefaultIconID = mInsignia->getImageAssetID();
- }
-
mEditCharter = getChild<LLTextEditor>("charter", recurse);
if(mEditCharter)
{
- mEditCharter->setCommitCallback(onCommitAny);
- mEditCharter->setFocusReceivedCallback(onFocusEdit, this);
- mEditCharter->setFocusChangedCallback(onFocusEdit, this);
- mEditCharter->setCallbackUserData(this);
+ mEditCharter->setCommitCallback(onCommitAny, this);
+ mEditCharter->setFocusReceivedCallback(boost::bind(onFocusEdit, _1, this));
+ mEditCharter->setFocusChangedCallback(boost::bind(onFocusEdit, _1, this));
}
- mBtnJoinGroup = getChild<LLButton>("join_button", recurse);
- if ( mBtnJoinGroup )
- {
- mBtnJoinGroup->setClickedCallback(onClickJoin);
- mBtnJoinGroup->setCallbackUserData(this);
- }
- mBtnInfo = getChild<LLButton>("info_button", recurse);
- if ( mBtnInfo )
- {
- mBtnInfo->setClickedCallback(onClickInfo);
- mBtnInfo->setCallbackUserData(this);
- }
-
- LLTextBox* founder = getChild<LLTextBox>("founder_name");
- if (founder)
- {
- mFounderName = new LLNameBox(founder->getName(),founder->getRect(),LLUUID::null,FALSE,founder->getFont(),founder->getMouseOpaque());
- removeChild(founder, TRUE);
- addChild(mFounderName);
- }
mListVisibleMembers = getChild<LLNameListCtrl>("visible_members", recurse);
if (mListVisibleMembers)
{
- mListVisibleMembers->setDoubleClickCallback(openProfile);
- mListVisibleMembers->setCallbackUserData(this);
+ mListVisibleMembers->setDoubleClickCallback(openProfile, this);
+ mListVisibleMembers->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
}
// Options
mCtrlShowInGroupList = getChild<LLCheckBoxCtrl>("show_in_group_list", recurse);
if (mCtrlShowInGroupList)
{
- mCtrlShowInGroupList->setCommitCallback(onCommitAny);
- mCtrlShowInGroupList->setCallbackUserData(this);
+ mCtrlShowInGroupList->setCommitCallback(onCommitAny, this);
}
mComboMature = getChild<LLComboBox>("group_mature_check", recurse);
if(mComboMature)
{
mComboMature->setCurrentByIndex(0);
- mComboMature->setCommitCallback(onCommitAny);
- mComboMature->setCallbackUserData(this);
+ mComboMature->setCommitCallback(onCommitAny, this);
if (gAgent.isTeen())
{
// Teens don't get to set mature flag. JC
@@ -178,22 +135,19 @@ BOOL LLPanelGroupGeneral::postBuild()
mCtrlOpenEnrollment = getChild<LLCheckBoxCtrl>("open_enrollement", recurse);
if (mCtrlOpenEnrollment)
{
- mCtrlOpenEnrollment->setCommitCallback(onCommitAny);
- mCtrlOpenEnrollment->setCallbackUserData(this);
+ mCtrlOpenEnrollment->setCommitCallback(onCommitAny, this);
}
mCtrlEnrollmentFee = getChild<LLCheckBoxCtrl>("check_enrollment_fee", recurse);
if (mCtrlEnrollmentFee)
{
- mCtrlEnrollmentFee->setCommitCallback(onCommitEnrollment);
- mCtrlEnrollmentFee->setCallbackUserData(this);
+ mCtrlEnrollmentFee->setCommitCallback(onCommitEnrollment, this);
}
mSpinEnrollmentFee = getChild<LLSpinCtrl>("spin_enrollment_fee", recurse);
if (mSpinEnrollmentFee)
{
- mSpinEnrollmentFee->setCommitCallback(onCommitAny);
- mSpinEnrollmentFee->setCallbackUserData(this);
+ mSpinEnrollmentFee->setCommitCallback(onCommitAny, this);
mSpinEnrollmentFee->setPrecision(0);
mSpinEnrollmentFee->resetDirty();
}
@@ -209,8 +163,7 @@ BOOL LLPanelGroupGeneral::postBuild()
mCtrlReceiveNotices = getChild<LLCheckBoxCtrl>("receive_notices", recurse);
if (mCtrlReceiveNotices)
{
- mCtrlReceiveNotices->setCommitCallback(onCommitUserOnly);
- mCtrlReceiveNotices->setCallbackUserData(this);
+ mCtrlReceiveNotices->setCommitCallback(onCommitUserOnly, this);
mCtrlReceiveNotices->set(accept_notices);
mCtrlReceiveNotices->setEnabled(data.mID.notNull());
}
@@ -218,8 +171,7 @@ BOOL LLPanelGroupGeneral::postBuild()
mCtrlListGroup = getChild<LLCheckBoxCtrl>("list_groups_in_profile", recurse);
if (mCtrlListGroup)
{
- mCtrlListGroup->setCommitCallback(onCommitUserOnly);
- mCtrlListGroup->setCallbackUserData(this);
+ mCtrlListGroup->setCommitCallback(onCommitUserOnly, this);
mCtrlListGroup->set(list_in_profile);
mCtrlListGroup->setEnabled(data.mID.notNull());
mCtrlListGroup->resetDirty();
@@ -230,18 +182,15 @@ BOOL LLPanelGroupGeneral::postBuild()
mComboActiveTitle = getChild<LLComboBox>("active_title", recurse);
if (mComboActiveTitle)
{
- mComboActiveTitle->setCommitCallback(onCommitTitle);
- mComboActiveTitle->setCallbackUserData(this);
+ mComboActiveTitle->setCommitCallback(onCommitTitle, this);
mComboActiveTitle->resetDirty();
}
mIncompleteMemberDataStr = getString("incomplete_member_data_str");
- mConfirmGroupCreateStr = getString("confirm_group_create_str");
// If the group_id is null, then we are creating a new group
if (mGroupID.isNull())
{
- mGroupNameEditor->setEnabled(TRUE);
mEditCharter->setEnabled(TRUE);
mCtrlShowInGroupList->setEnabled(TRUE);
@@ -250,14 +199,24 @@ BOOL LLPanelGroupGeneral::postBuild()
mCtrlEnrollmentFee->setEnabled(TRUE);
mSpinEnrollmentFee->setEnabled(TRUE);
- mBtnJoinGroup->setVisible(FALSE);
- mBtnInfo->setVisible(FALSE);
- mGroupName->setVisible(FALSE);
}
return LLPanelGroupTab::postBuild();
}
+void LLPanelGroupGeneral::setupCtrls(LLPanel* panel_group)
+{
+ mInsignia = panel_group->getChild<LLTextureCtrl>("insignia");
+ if (mInsignia)
+ {
+ mInsignia->setCommitCallback(onCommitAny, this);
+ mDefaultIconID = mInsignia->getImageAssetID();
+ }
+ mFounderName = panel_group->getChild<LLNameBox>("founder_name");
+ mGroupNameEditor = panel_group->getChild<LLLineEditor>("group_name_editor");
+ mGroupNameEditor->setPrevalidate( LLLineEditor::prevalidateASCII );
+}
+
// static
void LLPanelGroupGeneral::onFocusEdit(LLFocusableElement* ctrl, void* data)
{
@@ -332,57 +291,8 @@ void LLPanelGroupGeneral::onClickInfo(void *userdata)
lldebugs << "open group info: " << self->mGroupID << llendl;
- LLFloaterGroupInfo::showFromUUID(self->mGroupID);
-}
-
-// static
-void LLPanelGroupGeneral::onClickJoin(void *userdata)
-{
- LLPanelGroupGeneral *self = (LLPanelGroupGeneral *)userdata;
-
- if ( !self ) return;
-
- lldebugs << "joining group: " << self->mGroupID << llendl;
+ LLGroupActions::show(self->mGroupID);
- LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(self->mGroupID);
-
- if (gdatap)
- {
- S32 cost = gdatap->mMembershipFee;
- LLSD args;
- args["COST"] = llformat("%d", cost);
- LLSD payload;
- payload["group_id"] = self->mGroupID;
-
- if (can_afford_transaction(cost))
- {
- LLNotifications::instance().add("JoinGroupCanAfford", args, payload, LLPanelGroupGeneral::joinDlgCB);
- }
- else
- {
- LLNotifications::instance().add("JoinGroupCannotAfford", args, payload);
- }
- }
- else
- {
- llwarns << "LLGroupMgr::getInstance()->getGroupData(" << self->mGroupID
- << ") was NULL" << llendl;
- }
-}
-
-// static
-bool LLPanelGroupGeneral::joinDlgCB(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotification::getSelectedOption(notification, response);
-
- if (option == 1)
- {
- // user clicked cancel
- return false;
- }
-
- LLGroupMgr::getInstance()->sendGroupMemberJoin(notification["payload"]["group_id"].asUUID());
- return false;
}
// static
@@ -395,7 +305,7 @@ void LLPanelGroupGeneral::openProfile(void* data)
LLScrollListItem* selected = self->mListVisibleMembers->getFirstSelected();
if (selected)
{
- LLFloaterAvatarInfo::showFromDirectory( selected->getUUID() );
+ LLAvatarActions::showProfile(selected->getUUID());
}
}
}
@@ -451,7 +361,7 @@ bool LLPanelGroupGeneral::apply(std::string& mesg)
if(mComboMature &&
mComboMature->getCurrentIndex() == DECLINE_TO_STATE)
{
- LLNotifications::instance().add("SetGroupMature", LLSD(), LLSD(),
+ LLNotificationsUtil::add("SetGroupMature", LLSD(), LLSD(),
boost::bind(&LLPanelGroupGeneral::confirmMatureApply, this, _1, _2));
return false;
}
@@ -470,9 +380,7 @@ bool LLPanelGroupGeneral::apply(std::string& mesg)
return false;
}
- LLSD args;
- args["MESSAGE"] = mConfirmGroupCreateStr;
- LLNotifications::instance().add("GenericAlertYesCancel", args, LLSD(), boost::bind(&LLPanelGroupGeneral::createGroupCallback, this, _1, _2));
+ LLNotificationsUtil::add("CreateGroupCost", LLSD(), LLSD(), boost::bind(&LLPanelGroupGeneral::createGroupCallback, this, _1, _2));
return false;
}
@@ -480,8 +388,7 @@ bool LLPanelGroupGeneral::apply(std::string& mesg)
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
if (!gdatap)
{
- // *TODO: Translate
- mesg = std::string("No group data found for group ");
+ mesg = LLTrans::getString("NoGroupDataFound");
mesg.append(mGroupID.asString());
return false;
}
@@ -553,7 +460,7 @@ void LLPanelGroupGeneral::cancel()
// invoked from callbackConfirmMature
bool LLPanelGroupGeneral::confirmMatureApply(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
// 0 == Yes
// 1 == No
// 2 == Cancel
@@ -571,14 +478,21 @@ bool LLPanelGroupGeneral::confirmMatureApply(const LLSD& notification, const LLS
// If we got here it means they set a valid value
std::string mesg = "";
- apply(mesg);
- return false;
+ bool ret = apply(mesg);
+ if ( !mesg.empty() )
+ {
+ LLSD args;
+ args["MESSAGE"] = mesg;
+ LLNotificationsUtil::add("GenericAlert", args);
+ }
+
+ return ret;
}
// static
bool LLPanelGroupGeneral::createGroupCallback(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
switch(option)
{
case 0:
@@ -666,7 +580,6 @@ void LLPanelGroupGeneral::update(LLGroupChange gc)
}
}
- mComboActiveTitle->resetDirty();
}
// If this was just a titles update, we are done.
@@ -681,8 +594,6 @@ void LLPanelGroupGeneral::update(LLGroupChange gc)
{
mCtrlShowInGroupList->set(gdatap->mShowInList);
mCtrlShowInGroupList->setEnabled(mAllowEdit && can_change_ident);
- mCtrlShowInGroupList->resetDirty();
-
}
if (mComboMature)
{
@@ -696,19 +607,16 @@ void LLPanelGroupGeneral::update(LLGroupChange gc)
}
mComboMature->setEnabled(mAllowEdit && can_change_ident);
mComboMature->setVisible( !gAgent.isTeen() );
- mComboMature->resetDirty();
}
if (mCtrlOpenEnrollment)
{
mCtrlOpenEnrollment->set(gdatap->mOpenEnrollment);
mCtrlOpenEnrollment->setEnabled(mAllowEdit && can_change_member_opts);
- mCtrlOpenEnrollment->resetDirty();
}
if (mCtrlEnrollmentFee)
{
mCtrlEnrollmentFee->set(gdatap->mMembershipFee > 0);
mCtrlEnrollmentFee->setEnabled(mAllowEdit && can_change_member_opts);
- mCtrlEnrollmentFee->resetDirty();
}
if (mSpinEnrollmentFee)
@@ -718,28 +626,7 @@ void LLPanelGroupGeneral::update(LLGroupChange gc)
mSpinEnrollmentFee->setEnabled( mAllowEdit &&
(fee > 0) &&
can_change_member_opts);
- mSpinEnrollmentFee->resetDirty();
- }
- if ( mBtnJoinGroup )
- {
- std::string fee_buff;
- bool visible;
-
- visible = !is_member && gdatap->mOpenEnrollment;
- mBtnJoinGroup->setVisible(visible);
-
- if ( visible )
- {
- fee_buff = llformat( "Join (L$%d)", gdatap->mMembershipFee);
- mBtnJoinGroup->setLabelSelected(fee_buff);
- mBtnJoinGroup->setLabelUnselected(fee_buff);
- }
- }
- if ( mBtnInfo )
- {
- mBtnInfo->setVisible(is_member && !mAllowEdit);
}
-
if (mCtrlReceiveNotices)
{
mCtrlReceiveNotices->setVisible(is_member);
@@ -747,14 +634,12 @@ void LLPanelGroupGeneral::update(LLGroupChange gc)
{
mCtrlReceiveNotices->setEnabled(mAllowEdit);
}
- mCtrlReceiveNotices->resetDirty();
}
if (mInsignia) mInsignia->setEnabled(mAllowEdit && can_change_ident);
if (mEditCharter) mEditCharter->setEnabled(mAllowEdit && can_change_ident);
- if (mGroupName) mGroupName->setText(gdatap->mName);
if (mGroupNameEditor) mGroupNameEditor->setVisible(FALSE);
if (mFounderName) mFounderName->setNameID(gdatap->mFounderID,FALSE);
if (mInsignia)
@@ -772,7 +657,6 @@ void LLPanelGroupGeneral::update(LLGroupChange gc)
if (mEditCharter)
{
mEditCharter->setText(gdatap->mCharter);
- mEditCharter->resetDirty();
}
if (mListVisibleMembers)
@@ -800,6 +684,8 @@ void LLPanelGroupGeneral::update(LLGroupChange gc)
mListVisibleMembers->addElement(row);
}
}
+
+ resetDirty();
}
void LLPanelGroupGeneral::updateMembers()
@@ -832,31 +718,36 @@ void LLPanelGroupGeneral::updateMembers()
}
// Owners show up in bold.
std::string style = "NORMAL";
- if ( member->isOwner() )
- {
- style = "BOLD";
- }
-
sd_timer.reset();
LLSD row;
row["id"] = member->getID();
row["columns"][0]["column"] = "name";
- row["columns"][0]["font-style"] = style;
+ row["columns"][0]["font"]["name"] = "SANSSERIF_SMALL";
+ row["columns"][0]["font"]["style"] = style;
// value is filled in by name list control
row["columns"][1]["column"] = "title";
row["columns"][1]["value"] = member->getTitle();
- row["columns"][1]["font-style"] = style;
+ row["columns"][1]["font"]["name"] = "SANSSERIF_SMALL";
+ row["columns"][1]["font"]["style"] = style;
row["columns"][2]["column"] = "online";
row["columns"][2]["value"] = member->getOnlineStatus();
- row["columns"][2]["font-style"] = style;
+ row["columns"][2]["font"]["name"] = "SANSSERIF_SMALL";
+ row["columns"][2]["font"]["style"] = style;
sSDTime += sd_timer.getElapsedTimeF32();
element_timer.reset();
- mListVisibleMembers->addElement(row);//, ADD_SORTED);
+ LLScrollListItem* member_row = mListVisibleMembers->addElement(row);//, ADD_SORTED);
+
+ if ( member->isOwner() )
+ {
+ LLScrollListText* name_textp = dynamic_cast<LLScrollListText*>(member_row->getColumn(0));
+ if (name_textp)
+ name_textp->setFontStyle(LLFontGL::BOLD);
+ }
sElementTime += element_timer.getElapsedTimeF32();
}
sAllTime += all_timer.getElapsedTimeF32();
@@ -884,7 +775,6 @@ void LLPanelGroupGeneral::updateChanged()
LLUICtrl *check_list[] =
{
mGroupNameEditor,
- mGroupName,
mFounderName,
mInsignia,
mEditCharter,
@@ -910,3 +800,140 @@ void LLPanelGroupGeneral::updateChanged()
}
}
}
+
+void LLPanelGroupGeneral::reset()
+{
+ mFounderName->setVisible(false);
+
+
+ mCtrlReceiveNotices->set(false);
+
+
+ mCtrlListGroup->set(true);
+
+ mCtrlReceiveNotices->setEnabled(true);
+ mCtrlReceiveNotices->setVisible(true);
+
+ mCtrlListGroup->setEnabled(true);
+
+ mGroupNameEditor->setEnabled(TRUE);
+ mEditCharter->setEnabled(TRUE);
+
+ mCtrlShowInGroupList->setEnabled(TRUE);
+ mComboMature->setEnabled(TRUE);
+
+ mCtrlOpenEnrollment->setEnabled(TRUE);
+
+ mCtrlEnrollmentFee->setEnabled(TRUE);
+
+ mSpinEnrollmentFee->setEnabled(TRUE);
+ mSpinEnrollmentFee->set((F32)0);
+
+ mGroupNameEditor->setVisible(true);
+
+ mComboActiveTitle->setVisible(false);
+
+ mInsignia->setImageAssetID(LLUUID::null);
+
+ mInsignia->setEnabled(true);
+
+ {
+ std::string empty_str = "";
+ mEditCharter->setText(empty_str);
+ mGroupNameEditor->setText(empty_str);
+ }
+
+ {
+ LLSD row;
+ row["columns"][0]["value"] = "no members yet";
+
+ mListVisibleMembers->deleteAllItems();
+ mListVisibleMembers->setEnabled(FALSE);
+ mListVisibleMembers->addElement(row);
+ }
+
+
+ {
+ mComboMature->setEnabled(true);
+ mComboMature->setVisible( !gAgent.isTeen() );
+ mComboMature->selectFirstItem();
+ }
+
+
+ resetDirty();
+}
+
+void LLPanelGroupGeneral::resetDirty()
+{
+ // List all the controls we want to check for changes...
+ LLUICtrl *check_list[] =
+ {
+ mGroupNameEditor,
+ mFounderName,
+ mInsignia,
+ mEditCharter,
+ mCtrlShowInGroupList,
+ mComboMature,
+ mCtrlOpenEnrollment,
+ mCtrlEnrollmentFee,
+ mSpinEnrollmentFee,
+ mCtrlReceiveNotices,
+ mCtrlListGroup,
+ mActiveTitleLabel,
+ mComboActiveTitle
+ };
+
+ for( size_t i=0; i<LL_ARRAY_SIZE(check_list); i++ )
+ {
+ if( check_list[i] )
+ check_list[i]->resetDirty() ;
+ }
+
+
+}
+
+void LLPanelGroupGeneral::setGroupID(const LLUUID& id)
+{
+ LLPanelGroupTab::setGroupID(id);
+
+ if(id == LLUUID::null)
+ {
+ reset();
+ return;
+ }
+
+ BOOL accept_notices = FALSE;
+ BOOL list_in_profile = FALSE;
+ LLGroupData data;
+ if(gAgent.getGroupData(mGroupID,data))
+ {
+ accept_notices = data.mAcceptNotices;
+ list_in_profile = data.mListInProfile;
+ }
+ mCtrlReceiveNotices = getChild<LLCheckBoxCtrl>("receive_notices");
+ if (mCtrlReceiveNotices)
+ {
+ mCtrlReceiveNotices->set(accept_notices);
+ mCtrlReceiveNotices->setEnabled(data.mID.notNull());
+ }
+
+ mCtrlListGroup = getChild<LLCheckBoxCtrl>("list_groups_in_profile");
+ if (mCtrlListGroup)
+ {
+ mCtrlListGroup->set(list_in_profile);
+ mCtrlListGroup->setEnabled(data.mID.notNull());
+ }
+
+ mActiveTitleLabel = getChild<LLTextBox>("active_title_label");
+
+ mComboActiveTitle = getChild<LLComboBox>("active_title");
+
+ mFounderName->setVisible(true);
+
+ mInsignia->setImageAssetID(LLUUID::null);
+
+ resetDirty();
+
+ activate();
+}
+
diff --git a/indra/newview/llpanelgroupgeneral.h b/indra/newview/llpanelgroupgeneral.h
index 71356677fc..7e90e43cf9 100644
--- a/indra/newview/llpanelgroupgeneral.h
+++ b/indra/newview/llpanelgroupgeneral.h
@@ -49,11 +49,10 @@ class LLSpinCtrl;
class LLPanelGroupGeneral : public LLPanelGroupTab
{
public:
- LLPanelGroupGeneral(const std::string& name, const LLUUID& group_id);
+ LLPanelGroupGeneral();
virtual ~LLPanelGroupGeneral();
// LLPanelGroupTab
- static void* createTab(void* data);
virtual void activate();
virtual bool needsApply(std::string& mesg);
virtual bool apply(std::string& mesg);
@@ -66,13 +65,20 @@ public:
virtual void draw();
+ virtual void setGroupID(const LLUUID& id);
+
+ virtual void setupCtrls (LLPanel* parent);
+
private:
+ void reset();
+
+ void resetDirty();
+
static void onFocusEdit(LLFocusableElement* ctrl, void* data);
static void onCommitAny(LLUICtrl* ctrl, void* data);
static void onCommitUserOnly(LLUICtrl* ctrl, void* data);
static void onCommitTitle(LLUICtrl* ctrl, void* data);
static void onCommitEnrollment(LLUICtrl* ctrl, void* data);
- static void onClickJoin(void* userdata);
static void onClickInfo(void* userdata);
static void onReceiveNotices(LLUICtrl* ctrl, void* data);
static void openProfile(void* data);
@@ -87,17 +93,13 @@ private:
BOOL mChanged;
BOOL mFirstUse;
std::string mIncompleteMemberDataStr;
- std::string mConfirmGroupCreateStr;
LLUUID mDefaultIconID;
// Group information (include any updates in updateChanged)
LLLineEditor *mGroupNameEditor;
- LLTextBox *mGroupName;
LLNameBox *mFounderName;
LLTextureCtrl *mInsignia;
LLTextEditor *mEditCharter;
- LLButton *mBtnJoinGroup;
- LLButton *mBtnInfo;
LLNameListCtrl *mListVisibleMembers;
diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp
index eedec9c8eb..06a682c905 100644
--- a/indra/newview/llpanelgroupinvite.cpp
+++ b/indra/newview/llpanelgroupinvite.cpp
@@ -37,8 +37,11 @@
#include "llfloateravatarpicker.h"
#include "llbutton.h"
#include "llcombobox.h"
+#include "llgroupactions.h"
#include "llgroupmgr.h"
#include "llnamelistctrl.h"
+#include "llnotificationsutil.h"
+#include "llscrolllistitem.h"
#include "llspinctrl.h"
#include "lltextbox.h"
#include "llviewerobject.h"
@@ -79,6 +82,7 @@ public:
LLButton *mRemoveButton;
LLTextBox *mGroupName;
std::string mOwnerWarning;
+ std::string mAlreadyInGroup;
bool mConfirmedOwnerInvite;
void (*mCloseCallback)(void* data);
@@ -161,21 +165,34 @@ void LLPanelGroupInvite::impl::submitInvitations()
{
LLSD args;
args["MESSAGE"] = mOwnerWarning;
- LLNotifications::instance().add("GenericAlertYesCancel", args, LLSD(), boost::bind(&LLPanelGroupInvite::impl::inviteOwnerCallback, this, _1, _2));
+ LLNotificationsUtil::add("GenericAlertYesCancel", args, LLSD(), boost::bind(&LLPanelGroupInvite::impl::inviteOwnerCallback, this, _1, _2));
return; // we'll be called again if user confirms
}
}
+ bool already_in_group = false;
//loop over the users
std::vector<LLScrollListItem*> items = mInvitees->getAllData();
for (std::vector<LLScrollListItem*>::iterator iter = items.begin();
iter != items.end(); ++iter)
{
LLScrollListItem* item = *iter;
+ if(LLGroupActions::isAvatarMemberOfGroup(mGroupID, item->getUUID()))
+ {
+ already_in_group = true;
+ continue;
+ }
role_member_pairs[item->getUUID()] = role_id;
}
-
+
LLGroupMgr::getInstance()->sendGroupMemberInvites(mGroupID, role_member_pairs);
+
+ if(already_in_group)
+ {
+ LLSD msg;
+ msg["MESSAGE"] = mAlreadyInGroup;
+ LLNotificationsUtil::add("GenericAlert", msg);
+ }
//then close
(*mCloseCallback)(mCloseCallbackUserData);
@@ -183,7 +200,7 @@ void LLPanelGroupInvite::impl::submitInvitations()
bool LLPanelGroupInvite::impl::inviteOwnerCallback(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
switch(option)
{
@@ -275,8 +292,8 @@ void LLPanelGroupInvite::impl::callbackClickAdd(void* userdata)
LLFloater* parentp;
parentp = gFloaterView->getParentFloater(panelp);
- parentp->addDependentFloater(LLFloaterAvatarPicker::show(callbackAddUsers,
- panelp->mImplementation,
+ parentp->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(impl::callbackAddUsers, _1, _2,
+ panelp->mImplementation),
TRUE));
}
}
@@ -351,18 +368,13 @@ void LLPanelGroupInvite::impl::callbackAddUsers(const std::vector<std::string>&
if ( selfp) selfp->addUsers(names, ids);
}
-LLPanelGroupInvite::LLPanelGroupInvite(const std::string& name,
- const LLUUID& group_id)
- : LLPanel(name)
+LLPanelGroupInvite::LLPanelGroupInvite(const LLUUID& group_id)
+ : LLPanel(),
+ mImplementation(new impl(group_id)),
+ mPendingUpdate(FALSE)
{
- mImplementation = new impl(group_id);
- mPendingUpdate = FALSE;
- mStoreSelected = LLUUID::null;
-
- std::string panel_def_file;
-
// Pass on construction of this panel to the control factory.
- LLUICtrlFactory::getInstance()->buildPanel(this, "panel_group_invite.xml", &getFactoryMap());
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_group_invite.xml");
}
LLPanelGroupInvite::~LLPanelGroupInvite()
@@ -519,9 +531,8 @@ BOOL LLPanelGroupInvite::postBuild()
getChild<LLNameListCtrl>("invitee_list", recurse);
if ( mImplementation->mInvitees )
{
- mImplementation->mInvitees->setCallbackUserData(mImplementation);
mImplementation->mInvitees->setCommitOnSelectionChange(TRUE);
- mImplementation->mInvitees->setCommitCallback(impl::callbackSelect);
+ mImplementation->mInvitees->setCommitCallback(impl::callbackSelect, mImplementation);
}
LLButton* button = getChild<LLButton>("add_button", recurse);
@@ -529,17 +540,14 @@ BOOL LLPanelGroupInvite::postBuild()
{
// default to opening avatarpicker automatically
// (*impl::callbackClickAdd)((void*)this);
- button->setClickedCallback(impl::callbackClickAdd);
- button->setCallbackUserData(this);
+ button->setClickedCallback(impl::callbackClickAdd, this);
}
mImplementation->mRemoveButton =
getChild<LLButton>("remove_button", recurse);
if ( mImplementation->mRemoveButton )
{
- mImplementation->mRemoveButton->
- setClickedCallback(impl::callbackClickRemove);
- mImplementation->mRemoveButton->setCallbackUserData(mImplementation);
+ mImplementation->mRemoveButton->setClickedCallback(impl::callbackClickRemove, mImplementation);
mImplementation->mRemoveButton->setEnabled(FALSE);
}
@@ -547,20 +555,18 @@ BOOL LLPanelGroupInvite::postBuild()
getChild<LLButton>("ok_button", recurse);
if ( mImplementation->mOKButton )
{
- mImplementation->mOKButton->
- setClickedCallback(impl::callbackClickOK);
- mImplementation->mOKButton->setCallbackUserData(mImplementation);
+ mImplementation->mOKButton->setClickedCallback(impl::callbackClickOK, mImplementation);
mImplementation->mOKButton->setEnabled(FALSE);
}
button = getChild<LLButton>("cancel_button", recurse);
if ( button )
{
- button->setClickedCallback(impl::callbackClickCancel);
- button->setCallbackUserData(mImplementation);
+ button->setClickedCallback(impl::callbackClickCancel, mImplementation);
}
mImplementation->mOwnerWarning = getString("confirm_invite_owner_str");
+ mImplementation->mAlreadyInGroup = getString("already_in_group");
update();
diff --git a/indra/newview/llpanelgroupinvite.h b/indra/newview/llpanelgroupinvite.h
index 9117b83e7d..37135b488a 100644
--- a/indra/newview/llpanelgroupinvite.h
+++ b/indra/newview/llpanelgroupinvite.h
@@ -39,7 +39,7 @@ class LLPanelGroupInvite
: public LLPanel
{
public:
- LLPanelGroupInvite(const std::string& name, const LLUUID& group_id);
+ LLPanelGroupInvite(const LLUUID& group_id);
~LLPanelGroupInvite();
void addUsers(std::vector<LLUUID>& agent_ids);
diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp
index 73a9868962..9023afc602 100644
--- a/indra/newview/llpanelgrouplandmoney.cpp
+++ b/indra/newview/llpanelgrouplandmoney.cpp
@@ -42,20 +42,72 @@
#include "llagent.h"
#include "lliconctrl.h"
+#include "llfloaterreg.h"
#include "lllineeditor.h"
#include "llproductinforequest.h"
#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "llscrolllistcell.h"
#include "lltextbox.h"
#include "lltabcontainer.h"
+#include "lltexteditor.h"
#include "lltrans.h"
#include "lltransactiontypes.h"
+#include "lltrans.h"
#include "lluictrlfactory.h"
#include "llstatusbar.h"
#include "llfloaterworldmap.h"
#include "llviewermessage.h"
+static LLRegisterPanelClassWrapper<LLPanelGroupLandMoney> t_panel_group_money("panel_group_land_money");
+
+
+
////////////////////////////////////////////////////////////////////////////
+//*************************************************
+//** LLGroupMoneyTabEventHandler::impl Functions **
+//*************************************************
+
+class LLGroupMoneyTabEventHandlerImpl
+{
+public:
+ LLGroupMoneyTabEventHandlerImpl(LLButton* earlier_buttonp,
+ LLButton* later_buttonp,
+ LLTextEditor* text_editorp,
+ LLPanel* tabpanelp,
+ const std::string& loading_text,
+ S32 interval_length_days,
+ S32 max_interval_days);
+ ~LLGroupMoneyTabEventHandlerImpl();
+
+ bool getCanClickLater();
+ bool getCanClickEarlier();
+
+ void updateButtons();
+
+ void setGroupID(const LLUUID& group_id) { mGroupID = group_id; } ;
+ const LLUUID& getGroupID() const { return mGroupID;}
+
+
+//member variables
+public:
+ LLUUID mPanelID;
+ LLUUID mGroupID;
+
+ LLPanel* mTabPanelp;
+
+ int mIntervalLength;
+ int mMaxInterval;
+ int mCurrentInterval;
+
+ LLTextEditor* mTextEditorp;
+ LLButton* mEarlierButtonp;
+ LLButton* mLaterButtonp;
+
+ std::string mLoadingText;
+};
+
class LLGroupMoneyTabEventHandler
{
@@ -66,7 +118,6 @@ public:
LLTabContainer* tab_containerp,
LLPanel* panelp,
const std::string& loading_text,
- const LLUUID& group_id,
S32 interval_length_days,
S32 max_interval_days);
virtual ~LLGroupMoneyTabEventHandler();
@@ -78,15 +129,17 @@ public:
virtual void onClickLater();
virtual void onClickTab();
+ void setGroupID(const LLUUID& group_id) { if(mImplementationp) mImplementationp->setGroupID(group_id); } ;
+
static void clickEarlierCallback(void* data);
static void clickLaterCallback(void* data);
- static void clickTabCallback(void* user_data, bool from_click);
+
+
static LLMap<LLUUID, LLGroupMoneyTabEventHandler*> sInstanceIDs;
static std::map<LLPanel*, LLGroupMoneyTabEventHandler*> sTabsToHandlers;
protected:
- class impl;
- impl* mImplementationp;
+ LLGroupMoneyTabEventHandlerImpl* mImplementationp;
};
class LLGroupMoneyDetailsTabEventHandler : public LLGroupMoneyTabEventHandler
@@ -97,8 +150,8 @@ public:
LLTextEditor* text_editorp,
LLTabContainer* tab_containerp,
LLPanel* panelp,
- const std::string& loading_text,
- const LLUUID& group_id);
+ const std::string& loading_text
+ );
virtual ~LLGroupMoneyDetailsTabEventHandler();
virtual void requestData(LLMessageSystem* msg);
@@ -114,8 +167,8 @@ public:
LLTextEditor* text_editorp,
LLTabContainer* tab_containerp,
LLPanel* panelp,
- const std::string& loading_text,
- const LLUUID& group_id);
+ const std::string& loading_text
+ );
virtual ~LLGroupMoneySalesTabEventHandler();
virtual void requestData(LLMessageSystem* msg);
@@ -128,8 +181,8 @@ public:
LLGroupMoneyPlanningTabEventHandler(LLTextEditor* text_editor,
LLTabContainer* tab_containerp,
LLPanel* panelp,
- const std::string& loading_text,
- const LLUUID& group_id);
+ const std::string& loading_text
+ );
virtual ~LLGroupMoneyPlanningTabEventHandler();
virtual void requestData(LLMessageSystem* msg);
@@ -141,7 +194,7 @@ public:
class LLPanelGroupLandMoney::impl
{
public:
- impl(LLPanelGroupLandMoney& panel, const LLUUID& group_id); //constructor
+ impl(LLPanelGroupLandMoney& panel); //constructor
virtual ~impl();
void requestGroupLandInfo();
@@ -175,7 +228,6 @@ public:
LLScrollListCtrl* mGroupParcelsp;
- LLUUID mGroupID;
LLUUID mTransID;
bool mBeenActivated;
@@ -189,9 +241,8 @@ public:
//*******************************************
//** LLPanelGroupLandMoney::impl Functions **
//*******************************************
-LLPanelGroupLandMoney::impl::impl(LLPanelGroupLandMoney& panel, const LLUUID& group_id)
- : mPanel(panel),
- mGroupID(group_id)
+LLPanelGroupLandMoney::impl::impl(LLPanelGroupLandMoney& panel)
+ : mPanel(panel)
{
mTransID = LLUUID::null;
@@ -224,7 +275,7 @@ void LLPanelGroupLandMoney::impl::requestGroupLandInfo()
mTransID.generate();
mGroupParcelsp->deleteAllItems();
- send_places_query(mGroupID, mTransID, "", query_flags, LLParcel::C_ANY, "");
+ send_places_query(mPanel.mGroupID, mTransID, "", query_flags, LLParcel::C_ANY, "");
}
void LLPanelGroupLandMoney::impl::onMapButton()
@@ -244,9 +295,12 @@ void LLPanelGroupLandMoney::impl::onMapButton()
F64 global_z = gAgent.getPositionGlobal().mdV[VZ];
LLVector3d pos_global(global_x, global_y, global_z);
- gFloaterWorldMap->trackLocation(pos_global);
-
- LLFloaterWorldMap::show(NULL, TRUE);
+ LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
+ if(worldmap_instance)
+ {
+ worldmap_instance->trackLocation(pos_global);
+ LLFloaterReg::showInstance("world_map", "center");
+ }
}
bool LLPanelGroupLandMoney::impl::applyContribution()
@@ -271,7 +325,7 @@ bool LLPanelGroupLandMoney::impl::applyContribution()
new_contribution <= sqm_avail )
{
// update group info and server
- if(!gAgent.setGroupContribution(mGroupID, new_contribution))
+ if(!gAgent.setGroupContribution(mPanel.mGroupID, new_contribution))
{
// should never happen...
llwarns << "Unable to set contribution." << llendl;
@@ -298,7 +352,7 @@ int LLPanelGroupLandMoney::impl::getStoredContribution()
LLGroupData group_data;
group_data.mContribution = 0;
- gAgent.getGroupData(mGroupID, group_data);
+ gAgent.getGroupData(mPanel.mGroupID, group_data);
return group_data.mContribution;
}
@@ -397,13 +451,7 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg)
if ( trans_id != mTransID ) return;
// This power was removed to make group roles simpler
//if ( !gAgent.hasPowerInGroup(mGroupID, GP_LAND_VIEW_OWNED) ) return;
- if (!gAgent.isInGroup(mGroupID)) return;
-
- //we updated more than just the available area special block
- if ( count > 1)
- {
- mMapButtonp->setEnabled(TRUE);
- }
+ if (!gAgent.isInGroup(mPanel.mGroupID)) return;
std::string name;
std::string desc;
@@ -460,15 +508,15 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg)
row["columns"][0]["column"] = "name";
row["columns"][0]["value"] = name;
- row["columns"][0]["font"] = "SANSSERIFSMALL";
+ row["columns"][0]["font"] = "SANSSERIF_SMALL";
row["columns"][1]["column"] = "location";
row["columns"][1]["value"] = location;
- row["columns"][1]["font"] = "SANSSERIFSMALL";
+ row["columns"][1]["font"] = "SANSSERIF_SMALL";
row["columns"][2]["column"] = "area";
row["columns"][2]["value"] = area;
- row["columns"][2]["font"] = "SANSSERIFSMALL";
+ row["columns"][2]["font"] = "SANSSERIF_SMALL";
row["columns"][3]["column"] = "type";
row["columns"][3]["value"] = land_type;
@@ -487,26 +535,22 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg)
//** LLPanelGroupLandMoney Functions **
//*************************************
-//static
-void* LLPanelGroupLandMoney::createTab(void* data)
-{
- LLUUID* group_id = static_cast<LLUUID*>(data);
- return new LLPanelGroupLandMoney("panel group land money", *group_id);
-}
//static
LLMap<LLUUID, LLPanelGroupLandMoney*> LLPanelGroupLandMoney::sGroupIDs;
-LLPanelGroupLandMoney::LLPanelGroupLandMoney(const std::string& name,
- const LLUUID& group_id) :
- LLPanelGroupTab(name, group_id)
+LLPanelGroupLandMoney::LLPanelGroupLandMoney() :
+ LLPanelGroupTab()
{
- mImplementationp = new impl(*this, group_id);
+ //FIXME - add setGroupID();
+ mImplementationp = new impl(*this);
//problem what if someone has both the group floater open and the finder
//open to the same group? Some maps that map group ids to panels
//will then only be working for the last panel for a given group id :(
- LLPanelGroupLandMoney::sGroupIDs.addData(group_id, this);
+
+ //FIXME - add to setGroupID()
+ //LLPanelGroupLandMoney::sGroupIDs.addData(group_id, this);
}
LLPanelGroupLandMoney::~LLPanelGroupLandMoney()
@@ -553,6 +597,7 @@ void LLPanelGroupLandMoney::activate()
mImplementationp->setYourMaxContributionTextBox(max_avail);
}
+ mImplementationp->mMapButtonp->setEnabled(false);
update(GC_ALL);
}
@@ -634,9 +679,8 @@ BOOL LLPanelGroupLandMoney::postBuild()
{
LLLineEditor* editor = mImplementationp->mYourContributionEditorp;
- editor->setCommitCallback(mImplementationp->contributionCommitCallback);
- editor->setKeystrokeCallback(mImplementationp->contributionKeystrokeCallback);
- editor->setCallbackUserData(this);
+ editor->setCommitCallback(mImplementationp->contributionCommitCallback, this);
+ editor->setKeystrokeCallback(mImplementationp->contributionKeystrokeCallback, this);
}
mImplementationp->mMapButtonp = getChild<LLButton>("map_button");
@@ -644,6 +688,12 @@ BOOL LLPanelGroupLandMoney::postBuild()
mImplementationp->mGroupParcelsp =
getChild<LLScrollListCtrl>("group_parcel_list");
+ if ( mImplementationp->mGroupParcelsp )
+ {
+ mImplementationp->mGroupParcelsp->setCommitCallback(boost::bind(&LLPanelGroupLandMoney::onLandSelectionChanged, this));
+ mImplementationp->mGroupParcelsp->setCommitOnSelectionChange(true);
+ }
+
mImplementationp->mCantViewParcelsText = getString("cant_view_group_land_text");
mImplementationp->mCantViewAccountsText = getString("cant_view_group_accounting_text");
@@ -662,16 +712,11 @@ BOOL LLPanelGroupLandMoney::postBuild()
mImplementationp->mGroupOverLimitIconp->setVisible(FALSE);
}
- if ( mImplementationp->mMapButtonp )
- {
- mImplementationp->mMapButtonp->setEnabled(FALSE);
- }
-
if ( !can_view )
{
if ( mImplementationp->mGroupParcelsp )
{
- mImplementationp->mGroupParcelsp->addCommentText(
+ mImplementationp->mGroupParcelsp->setCommentText(
mImplementationp->mCantViewParcelsText);
mImplementationp->mGroupParcelsp->setEnabled(FALSE);
}
@@ -719,8 +764,7 @@ BOOL LLPanelGroupLandMoney::postBuild()
textp,
tabcp,
panelp,
- loading_text,
- mGroupID);
+ loading_text);
}
textp = getChild<LLTextEditor>("group_money_planning_text", true);
@@ -737,8 +781,7 @@ BOOL LLPanelGroupLandMoney::postBuild()
new LLGroupMoneyPlanningTabEventHandler(textp,
tabcp,
panelp,
- loading_text,
- mGroupID);
+ loading_text);
}
//pull out the widgets for the L$ sales tab
@@ -759,13 +802,17 @@ BOOL LLPanelGroupLandMoney::postBuild()
textp,
tabcp,
panelp,
- loading_text,
- mGroupID);
+ loading_text);
}
return LLPanelGroupTab::postBuild();
}
+void LLPanelGroupLandMoney::onLandSelectionChanged()
+{
+ mImplementationp->mMapButtonp->setEnabled( mImplementationp->mGroupParcelsp->getItemCount() > 0 );
+}
+
BOOL LLPanelGroupLandMoney::isVisibleByAgent(LLAgent* agentp)
{
return mAllowEdit && agentp->isInGroup(mGroupID);
@@ -787,56 +834,15 @@ void LLPanelGroupLandMoney::processPlacesReply(LLMessageSystem* msg, void**)
selfp->mImplementationp->processGroupLand(msg);
}
-//*************************************************
-//** LLGroupMoneyTabEventHandler::impl Functions **
-//*************************************************
-class LLGroupMoneyTabEventHandler::impl
-{
-public:
- impl(LLButton* earlier_buttonp,
- LLButton* later_buttonp,
- LLTextEditor* text_editorp,
- LLPanel* tabpanelp,
- const std::string& loading_text,
- const LLUUID& group_id,
- S32 interval_length_days,
- S32 max_interval_days);
- ~impl();
-
- bool getCanClickLater();
- bool getCanClickEarlier();
-
- void updateButtons();
-
-//member variables
-public:
- LLUUID mGroupID;
- LLUUID mPanelID;
-
- LLPanel* mTabPanelp;
-
- int mIntervalLength;
- int mMaxInterval;
- int mCurrentInterval;
-
- LLTextEditor* mTextEditorp;
- LLButton* mEarlierButtonp;
- LLButton* mLaterButtonp;
-
- std::string mLoadingText;
-};
-
-LLGroupMoneyTabEventHandler::impl::impl(LLButton* earlier_buttonp,
+LLGroupMoneyTabEventHandlerImpl::LLGroupMoneyTabEventHandlerImpl(LLButton* earlier_buttonp,
LLButton* later_buttonp,
LLTextEditor* text_editorp,
LLPanel* tabpanelp,
const std::string& loading_text,
- const LLUUID& group_id,
S32 interval_length_days,
S32 max_interval_days)
{
- mGroupID = group_id;
mPanelID.generate();
mIntervalLength = interval_length_days;
@@ -851,21 +857,21 @@ LLGroupMoneyTabEventHandler::impl::impl(LLButton* earlier_buttonp,
mLoadingText = loading_text;
}
-LLGroupMoneyTabEventHandler::impl::~impl()
+LLGroupMoneyTabEventHandlerImpl::~LLGroupMoneyTabEventHandlerImpl()
{
}
-bool LLGroupMoneyTabEventHandler::impl::getCanClickEarlier()
+bool LLGroupMoneyTabEventHandlerImpl::getCanClickEarlier()
{
return (mCurrentInterval < mMaxInterval);
}
-bool LLGroupMoneyTabEventHandler::impl::getCanClickLater()
+bool LLGroupMoneyTabEventHandlerImpl::getCanClickLater()
{
return ( mCurrentInterval > 0 );
}
-void LLGroupMoneyTabEventHandler::impl::updateButtons()
+void LLGroupMoneyTabEventHandlerImpl::updateButtons()
{
if ( mEarlierButtonp )
{
@@ -890,16 +896,14 @@ LLGroupMoneyTabEventHandler::LLGroupMoneyTabEventHandler(LLButton* earlier_butto
LLTabContainer* tab_containerp,
LLPanel* panelp,
const std::string& loading_text,
- const LLUUID& group_id,
S32 interval_length_days,
S32 max_interval_days)
{
- mImplementationp = new impl(earlier_buttonp,
+ mImplementationp = new LLGroupMoneyTabEventHandlerImpl(earlier_buttonp,
later_buttonp,
text_editorp,
panelp,
loading_text,
- group_id,
interval_length_days,
max_interval_days);
@@ -917,8 +921,7 @@ LLGroupMoneyTabEventHandler::LLGroupMoneyTabEventHandler(LLButton* earlier_butto
if ( tab_containerp && panelp )
{
- tab_containerp->setTabChangeCallback(panelp, clickTabCallback);
- tab_containerp->setTabUserData(panelp, this);
+ tab_containerp->setCommitCallback(boost::bind(&LLGroupMoneyTabEventHandler::onClickTab, this));
}
sInstanceIDs.addData(mImplementationp->mPanelID, this);
@@ -990,13 +993,6 @@ void LLGroupMoneyTabEventHandler::clickLaterCallback(void* data)
if ( selfp ) selfp->onClickLater();
}
-//static
-void LLGroupMoneyTabEventHandler::clickTabCallback(void* data, bool from_click)
-{
- LLGroupMoneyTabEventHandler* selfp = (LLGroupMoneyTabEventHandler*) data;
- if ( selfp && from_click ) selfp->onClickTab();
-}
-
//**************************************************
//** LLGroupMoneyDetailsTabEventHandler Functions **
//**************************************************
@@ -1006,15 +1002,13 @@ LLGroupMoneyDetailsTabEventHandler::LLGroupMoneyDetailsTabEventHandler(LLButton*
LLTextEditor* text_editorp,
LLTabContainer* tab_containerp,
LLPanel* panelp,
- const std::string& loading_text,
- const LLUUID& group_id)
+ const std::string& loading_text)
: LLGroupMoneyTabEventHandler(earlier_buttonp,
later_buttonp,
text_editorp,
tab_containerp,
panelp,
loading_text,
- group_id,
SUMMARY_INTERVAL,
SUMMARY_MAX)
{
@@ -1030,7 +1024,7 @@ void LLGroupMoneyDetailsTabEventHandler::requestData(LLMessageSystem* msg)
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
- msg->addUUIDFast(_PREHASH_GroupID, mImplementationp->mGroupID );
+ msg->addUUIDFast(_PREHASH_GroupID, mImplementationp->getGroupID() );
msg->nextBlockFast(_PREHASH_MoneyData);
msg->addUUIDFast(_PREHASH_RequestID, mImplementationp->mPanelID );
msg->addS32Fast(_PREHASH_IntervalDays, mImplementationp->mIntervalLength );
@@ -1051,7 +1045,7 @@ void LLGroupMoneyDetailsTabEventHandler::processReply(LLMessageSystem* msg,
{
LLUUID group_id;
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_GroupID, group_id );
- if (mImplementationp->mGroupID != group_id)
+ if (mImplementationp->getGroupID() != group_id)
{
llwarns << "Group Account details not for this group!" << llendl;
return;
@@ -1100,7 +1094,7 @@ void LLGroupMoneyDetailsTabEventHandler::processReply(LLMessageSystem* msg,
text.append(1, '\n');
- text.append(llformat("%-24s %6d\n", "Total", total_amount));
+ text.append(llformat("%-24s %6d\n", LLTrans::getString("GroupMoneyTotal").c_str(), total_amount));
if ( mImplementationp->mTextEditorp )
{
@@ -1141,15 +1135,13 @@ LLGroupMoneySalesTabEventHandler::LLGroupMoneySalesTabEventHandler(LLButton* ear
LLTextEditor* text_editorp,
LLTabContainer* tab_containerp,
LLPanel* panelp,
- const std::string& loading_text,
- const LLUUID& group_id)
+ const std::string& loading_text)
: LLGroupMoneyTabEventHandler(earlier_buttonp,
later_buttonp,
text_editorp,
tab_containerp,
panelp,
loading_text,
- group_id,
SUMMARY_INTERVAL,
SUMMARY_MAX)
{
@@ -1165,7 +1157,7 @@ void LLGroupMoneySalesTabEventHandler::requestData(LLMessageSystem* msg)
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
- msg->addUUIDFast(_PREHASH_GroupID, mImplementationp->mGroupID );
+ msg->addUUIDFast(_PREHASH_GroupID, mImplementationp->getGroupID() );
msg->nextBlockFast(_PREHASH_MoneyData);
msg->addUUIDFast(_PREHASH_RequestID, mImplementationp->mPanelID );
msg->addS32Fast(_PREHASH_IntervalDays, mImplementationp->mIntervalLength );
@@ -1186,7 +1178,7 @@ void LLGroupMoneySalesTabEventHandler::processReply(LLMessageSystem* msg,
{
LLUUID group_id;
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_GroupID, group_id );
- if (mImplementationp->mGroupID != group_id)
+ if (mImplementationp->getGroupID() != group_id)
{
llwarns << "Group Account Transactions not for this group!" << llendl;
return;
@@ -1220,7 +1212,7 @@ void LLGroupMoneySalesTabEventHandler::processReply(LLMessageSystem* msg,
S32 transactions = msg->getNumberOfBlocksFast(_PREHASH_HistoryData);
if (transactions == 0)
{
- text.append("(none)");
+ text.append(LLTrans::getString("none_text"));
}
else
{
@@ -1245,22 +1237,22 @@ void LLGroupMoneySalesTabEventHandler::processReply(LLMessageSystem* msg,
switch(type)
{
case TRANS_OBJECT_SALE:
- verb = "bought";
+ verb = LLTrans::getString("GroupMoneyBought").c_str();
break;
case TRANS_GIFT:
- verb = "paid you";
+ verb = LLTrans::getString("GroupMoneyPaidYou").c_str();
break;
case TRANS_PAY_OBJECT:
- verb = "paid into";
+ verb = LLTrans::getString("GroupMoneyPaidInto").c_str();
break;
case TRANS_LAND_PASS_SALE:
- verb = "bought pass to";
+ verb = LLTrans::getString("GroupMoneyBoughtPassTo").c_str();
break;
case TRANS_EVENT_FEE:
- verb = "paid fee for event";
+ verb = LLTrans::getString("GroupMoneyPaidFeeForEvent").c_str();
break;
case TRANS_EVENT_PRIZE:
- verb = "paid prize for event";
+ verb = LLTrans::getString("GroupMoneyPaidPrizeForEvent").c_str();
break;
default:
verb = "";
@@ -1313,15 +1305,13 @@ void LLPanelGroupLandMoney::processGroupAccountTransactionsReply(LLMessageSystem
LLGroupMoneyPlanningTabEventHandler::LLGroupMoneyPlanningTabEventHandler(LLTextEditor* text_editorp,
LLTabContainer* tab_containerp,
LLPanel* panelp,
- const std::string& loading_text,
- const LLUUID& group_id)
+ const std::string& loading_text)
: LLGroupMoneyTabEventHandler(NULL,
NULL,
text_editorp,
tab_containerp,
panelp,
loading_text,
- group_id,
SUMMARY_INTERVAL,
SUMMARY_MAX)
{
@@ -1337,7 +1327,7 @@ void LLGroupMoneyPlanningTabEventHandler::requestData(LLMessageSystem* msg)
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
- msg->addUUIDFast(_PREHASH_GroupID, mImplementationp->mGroupID );
+ msg->addUUIDFast(_PREHASH_GroupID, mImplementationp->getGroupID() );
msg->nextBlockFast(_PREHASH_MoneyData);
msg->addUUIDFast(_PREHASH_RequestID, mImplementationp->mPanelID );
msg->addS32Fast(_PREHASH_IntervalDays, mImplementationp->mIntervalLength);
@@ -1358,7 +1348,7 @@ void LLGroupMoneyPlanningTabEventHandler::processReply(LLMessageSystem* msg,
{
LLUUID group_id;
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_GroupID, group_id );
- if (mImplementationp->mGroupID != group_id)
+ if (mImplementationp->getGroupID() != group_id)
{
llwarns << "Group Account Summary received not for this group!" << llendl;
return;
@@ -1420,24 +1410,24 @@ void LLGroupMoneyPlanningTabEventHandler::processReply(LLMessageSystem* msg,
return;
}
- text.append("Summary for this week, beginning on ");
+ text.append(LLTrans::getString("SummaryForTheWeek"));
text.append(start_date);
if (current_interval == 0)
{
- text.append("The next stipend day is ");
+ text.append(LLTrans::getString("NextStipendDay"));
text.append(next_stipend_date);
text.append("\n\n");
- text.append(llformat("%-24sL$%6d\n", "Balance", balance ));
+ text.append(llformat("%-24sL$%6d\n", LLTrans::getString("GroupMoneyBalance").c_str(), balance ));
text.append(1, '\n');
}
// [DEV-29503] Hide the individual info since
// non_exempt_member here is a wrong choice to calculate individual shares.
- // text.append( " Group Individual Share\n");
- // text.append(llformat( "%-24s %6d %6d \n", "Credits", total_credits, (S32)floor((F32)total_credits/(F32)non_exempt_members)));
- // text.append(llformat( "%-24s %6d %6d \n", "Debits", total_debits, (S32)floor((F32)total_debits/(F32)non_exempt_members)));
- // text.append(llformat( "%-24s %6d %6d \n", "Total", total_credits + total_debits, (S32)floor((F32)(total_credits + total_debits)/(F32)non_exempt_members)));
+// text.append( LLTrans::getString("GroupIndividualShare"));
+// text.append(llformat( "%-24s %6d %6d \n", LLTrans::getString("GroupMoneyCredits").c_str(), total_credits, (S32)floor((F32)total_credits/(F32)non_exempt_members)));
+// text.append(llformat( "%-24s %6d %6d \n", LLTrans::getString("GroupMoneyDebits").c_str(), total_debits, (S32)floor((F32)total_debits/(F32)non_exempt_members)));
+// text.append(llformat( "%-24s %6d %6d \n", LLTrans::getString("GroupMoneyTotal").c_str(), total_credits + total_debits, (S32)floor((F32)(total_credits + total_debits)/(F32)non_exempt_members)));
text.append( " Group\n");
text.append(llformat( "%-24s %6d\n", "Credits", total_credits));
@@ -1476,3 +1466,140 @@ void LLPanelGroupLandMoney::processGroupAccountSummaryReply(LLMessageSystem* msg
self->processReply(msg, data);
}
+
+void LLPanelGroupLandMoney::setGroupID(const LLUUID& id)
+{
+ LLPanelGroupLandMoney::sGroupIDs.removeData(mGroupID);
+ LLPanelGroupTab::setGroupID(id);
+ LLPanelGroupLandMoney::sGroupIDs.addData(mGroupID, this);
+
+
+ bool can_view = gAgent.isInGroup(mGroupID);
+
+ mImplementationp->mGroupOverLimitIconp =
+ getChild<LLIconCtrl>("group_over_limit_icon");
+ mImplementationp->mGroupOverLimitTextp =
+ getChild<LLTextBox>("group_over_limit_text");
+
+ mImplementationp->mYourContributionEditorp
+ = getChild<LLLineEditor>("your_contribution_line_editor");
+ if ( mImplementationp->mYourContributionEditorp )
+ {
+ LLLineEditor* editor = mImplementationp->mYourContributionEditorp;
+
+ editor->setCommitCallback(mImplementationp->contributionCommitCallback, this);
+ editor->setKeystrokeCallback(mImplementationp->contributionKeystrokeCallback, this);
+ }
+
+ mImplementationp->mMapButtonp = getChild<LLButton>("map_button");
+
+ mImplementationp->mGroupParcelsp =
+ getChild<LLScrollListCtrl>("group_parcel_list");
+
+ if ( mImplementationp->mGroupParcelsp )
+ {
+ mImplementationp->mGroupParcelsp->setCommitCallback(boost::bind(&LLPanelGroupLandMoney::onLandSelectionChanged, this));
+ mImplementationp->mGroupParcelsp->setCommitOnSelectionChange(true);
+ }
+
+ mImplementationp->mCantViewParcelsText = getString("cant_view_group_land_text");
+ mImplementationp->mCantViewAccountsText = getString("cant_view_group_accounting_text");
+
+ if ( mImplementationp->mMapButtonp )
+ {
+ mImplementationp->mMapButtonp->setClickedCallback(LLPanelGroupLandMoney::impl::mapCallback, mImplementationp);
+ }
+
+ if ( mImplementationp->mGroupOverLimitTextp )
+ {
+ mImplementationp->mGroupOverLimitTextp->setVisible(FALSE);
+ }
+
+ if ( mImplementationp->mGroupOverLimitIconp )
+ {
+ mImplementationp->mGroupOverLimitIconp->setVisible(FALSE);
+ }
+
+ if ( mImplementationp->mGroupParcelsp )
+ {
+ mImplementationp->mGroupParcelsp->setEnabled(can_view);
+ }
+
+ if ( !can_view && mImplementationp->mGroupParcelsp )
+ {
+ mImplementationp->mGroupParcelsp->setEnabled(FALSE);
+ }
+
+
+ LLButton* earlierp, *laterp;
+ LLTextEditor* textp;
+ LLPanel* panelp;
+
+ LLTabContainer* tabcp = getChild<LLTabContainer>("group_money_tab_container");
+
+ if ( tabcp )
+ {
+ S32 i;
+ S32 tab_count = tabcp->getTabCount();
+
+ for (i = tab_count - 1; i >=0; --i)
+ {
+ tabcp->enableTabButton(i, can_view );
+ }
+ }
+
+ std::string loading_text = getString("loading_txt");
+
+ //pull out the widgets for the L$ details tab
+ earlierp = getChild<LLButton>("earlier_details_button", true);
+ laterp = getChild<LLButton>("later_details_button", true);
+ textp = getChild<LLTextEditor>("group_money_details_text", true);
+ panelp = getChild<LLPanel>("group_money_details_tab", true);
+
+ if ( !can_view )
+ {
+ textp->setText(mImplementationp->mCantViewAccountsText);
+ }
+ else
+ {
+ if(mImplementationp->mMoneyDetailsTabEHp == 0)
+ mImplementationp->mMoneyDetailsTabEHp = new LLGroupMoneyDetailsTabEventHandler(earlierp,laterp,textp,tabcp,panelp,loading_text);
+ mImplementationp->mMoneyDetailsTabEHp->setGroupID(mGroupID);
+ }
+
+ textp = getChild<LLTextEditor>("group_money_planning_text", true);
+
+
+ if ( !can_view )
+ {
+ textp->setText(mImplementationp->mCantViewAccountsText);
+ }
+ else
+ {
+ panelp = getChild<LLPanel>("group_money_planning_tab", true);
+ if(mImplementationp->mMoneyPlanningTabEHp == 0)
+ mImplementationp->mMoneyPlanningTabEHp = new LLGroupMoneyPlanningTabEventHandler(textp,tabcp,panelp,loading_text);
+ mImplementationp->mMoneyPlanningTabEHp->setGroupID(mGroupID);
+ }
+
+ //pull out the widgets for the L$ sales tab
+ textp = getChild<LLTextEditor>("group_money_sales_text", true);
+
+
+ if ( !can_view )
+ {
+ textp->setText(mImplementationp->mCantViewAccountsText);
+ }
+ else
+ {
+ earlierp = getChild<LLButton>("earlier_sales_button", true);
+ laterp = getChild<LLButton>("later_sales_button", true);
+ panelp = getChild<LLPanel>("group_money_sales_tab", true);
+ if(mImplementationp->mMoneySalesTabEHp == NULL)
+ mImplementationp->mMoneySalesTabEHp = new LLGroupMoneySalesTabEventHandler(earlierp,laterp,textp,tabcp,panelp,loading_text);
+ mImplementationp->mMoneySalesTabEHp->setGroupID(mGroupID);
+ }
+
+ activate();
+}
+
diff --git a/indra/newview/llpanelgrouplandmoney.h b/indra/newview/llpanelgrouplandmoney.h
index 591511a5fb..7e08d26d6f 100644
--- a/indra/newview/llpanelgrouplandmoney.h
+++ b/indra/newview/llpanelgrouplandmoney.h
@@ -37,20 +37,14 @@
#include "llmap.h"
#include "lluuid.h"
-#include "llbutton.h"
-#include "lltexteditor.h"
-#include "llpanel.h"
-
class LLPanelGroupLandMoney : public LLPanelGroupTab
{
public:
- LLPanelGroupLandMoney(const std::string& name, const LLUUID& group_id);
+ LLPanelGroupLandMoney();
virtual ~LLPanelGroupLandMoney();
virtual BOOL postBuild();
virtual BOOL isVisibleByAgent(LLAgent* agentp);
- static void* createTab(void* data);
-
virtual void activate();
virtual bool needsApply(std::string& mesg);
virtual bool apply(std::string& mesg);
@@ -64,6 +58,10 @@ public:
static void processGroupAccountDetailsReply(LLMessageSystem* msg, void** data);
static void processGroupAccountTransactionsReply(LLMessageSystem* msg, void** data);
static void processGroupAccountSummaryReply(LLMessageSystem* msg, void** data);
+
+ virtual void setGroupID(const LLUUID& id);
+
+ virtual void onLandSelectionChanged();
protected:
class impl;
diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp
index 5824df46e2..45fc3d4688 100644
--- a/indra/newview/llpanelgroupnotices.cpp
+++ b/indra/newview/llpanelgroupnotices.cpp
@@ -38,9 +38,11 @@
#include "llinventory.h"
#include "llviewerinventory.h"
+#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
-#include "llinventoryview.h"
+#include "llfloaterinventory.h"
#include "llagent.h"
+#include "llagentui.h"
#include "lltooldraganddrop.h"
#include "lllineeditor.h"
@@ -49,12 +51,17 @@
#include "lliconctrl.h"
#include "llcheckboxctrl.h"
#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
#include "lltextbox.h"
+#include "lltrans.h"
#include "roles_constants.h"
#include "llviewerwindow.h"
#include "llviewermessage.h"
-#include "llnotifications.h"
+#include "llnotificationsutil.h"
+
+static LLRegisterPanelClassWrapper<LLPanelGroupNotices> t_panel_group_notices("panel_group_notices");
+
/////////////////////////
// LLPanelGroupNotices //
@@ -69,7 +76,21 @@
class LLGroupDropTarget : public LLView
{
public:
- LLGroupDropTarget(const std::string& name, const LLRect& rect, LLPanelGroupNotices* panel, const LLUUID& group_id);
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
+ {
+ // *NOTE: These parameters logically Mandatory, but are not
+ // specified in XML files, hence Optional
+ Optional<LLPanelGroupNotices*> panel;
+ Optional<LLUUID> group_id;
+ Params()
+ : panel("panel"),
+ group_id("group_id")
+ {
+ mouse_opaque(false);
+ follows.flags(FOLLOWS_ALL);
+ }
+ };
+ LLGroupDropTarget(const Params&);
~LLGroupDropTarget() {};
void doDrop(EDragAndDropType cargo_type, void* cargo_data);
@@ -81,18 +102,21 @@ public:
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg);
+ void setPanel (LLPanelGroupNotices* panel) {mGroupNoticesPanel = panel;};
+ void setGroup (LLUUID group) {mGroupID = group;};
+
protected:
LLPanelGroupNotices* mGroupNoticesPanel;
LLUUID mGroupID;
};
-LLGroupDropTarget::LLGroupDropTarget(const std::string& name, const LLRect& rect,
- LLPanelGroupNotices* panel, const LLUUID& group_id) :
- LLView(name, rect, NOT_MOUSE_OPAQUE, FOLLOWS_ALL),
- mGroupNoticesPanel(panel),
- mGroupID(group_id)
-{
-}
+static LLDefaultChildRegistry::Register<LLGroupDropTarget> r("group_drop_target");
+
+LLGroupDropTarget::LLGroupDropTarget(const LLGroupDropTarget::Params& p)
+: LLView(p),
+ mGroupNoticesPanel(p.panel),
+ mGroupID(p.group_id)
+{}
void LLGroupDropTarget::doDrop(EDragAndDropType cargo_type, void* cargo_data)
{
@@ -133,6 +157,7 @@ BOOL LLGroupDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
case DAD_BODYPART:
case DAD_ANIMATION:
case DAD_GESTURE:
+ case DAD_CALLINGCARD:
{
LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;
if(gInventory.getItem(inv_item->getUUID())
@@ -156,7 +181,6 @@ BOOL LLGroupDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
break;
}
case DAD_CATEGORY:
- case DAD_CALLINGCARD:
default:
*accept = ACCEPT_NO;
break;
@@ -179,22 +203,22 @@ std::string build_notice_date(const U32& the_time)
time(&t);
}
- tm* lt = localtime(&t);
-
- //for some reason, the month is off by 1. See other uses of
- //"local" time in the code...
- std::string buffer = llformat("%04i-%02i-%02i", lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday);
-
- return buffer;
+ std::string dateStr = "["+LLTrans::getString("LTimeMthNum")+"]/["
+ +LLTrans::getString("LTimeDay")+"]/["
+ +LLTrans::getString("LTimeYear")+"]";
+ LLSD substitution;
+ substitution["datetime"] = (S32) t;
+ LLStringUtil::format (dateStr, substitution);
+ return dateStr;
}
-LLPanelGroupNotices::LLPanelGroupNotices(const std::string& name,
- const LLUUID& group_id) :
- LLPanelGroupTab(name,group_id),
+LLPanelGroupNotices::LLPanelGroupNotices() :
+ LLPanelGroupTab(),
mInventoryItem(NULL),
mInventoryOffer(NULL)
{
- sInstances[group_id] = this;
+
+
}
LLPanelGroupNotices::~LLPanelGroupNotices()
@@ -210,12 +234,6 @@ LLPanelGroupNotices::~LLPanelGroupNotices()
}
}
-// static
-void* LLPanelGroupNotices::createTab(void* data)
-{
- LLUUID* group_id = static_cast<LLUUID*>(data);
- return new LLPanelGroupNotices("panel group notices", *group_id);
-}
BOOL LLPanelGroupNotices::isVisibleByAgent(LLAgent* agentp)
{
@@ -229,17 +247,14 @@ BOOL LLPanelGroupNotices::postBuild()
mNoticesList = getChild<LLScrollListCtrl>("notice_list",recurse);
mNoticesList->setCommitOnSelectionChange(TRUE);
- mNoticesList->setCommitCallback(onSelectNotice);
- mNoticesList->setCallbackUserData(this);
+ mNoticesList->setCommitCallback(onSelectNotice, this);
mBtnNewMessage = getChild<LLButton>("create_new_notice",recurse);
- mBtnNewMessage->setClickedCallback(onClickNewMessage);
- mBtnNewMessage->setCallbackUserData(this);
+ mBtnNewMessage->setClickedCallback(onClickNewMessage, this);
mBtnNewMessage->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_NOTICES_SEND));
mBtnGetPastNotices = getChild<LLButton>("refresh_notices",recurse);
- mBtnGetPastNotices->setClickedCallback(onClickRefreshNotices);
- mBtnGetPastNotices->setCallbackUserData(this);
+ mBtnGetPastNotices->setClickedCallback(onClickRefreshNotices, this);
// Create
mCreateSubject = getChild<LLLineEditor>("create_subject",recurse);
@@ -253,12 +268,10 @@ BOOL LLPanelGroupNotices::postBuild()
mCreateInventoryIcon->setVisible(FALSE);
mBtnSendMessage = getChild<LLButton>("send_notice",recurse);
- mBtnSendMessage->setClickedCallback(onClickSendMessage);
- mBtnSendMessage->setCallbackUserData(this);
+ mBtnSendMessage->setClickedCallback(onClickSendMessage, this);
mBtnRemoveAttachment = getChild<LLButton>("remove_attachment",recurse);
- mBtnRemoveAttachment->setClickedCallback(onClickRemoveAttachment);
- mBtnRemoveAttachment->setCallbackUserData(this);
+ mBtnRemoveAttachment->setClickedCallback(onClickRemoveAttachment, this);
mBtnRemoveAttachment->setEnabled(FALSE);
// View
@@ -273,24 +286,16 @@ BOOL LLPanelGroupNotices::postBuild()
mViewInventoryIcon->setVisible(FALSE);
mBtnOpenAttachment = getChild<LLButton>("open_attachment",recurse);
- mBtnOpenAttachment->setClickedCallback(onClickOpenAttachment);
- mBtnOpenAttachment->setCallbackUserData(this);
+ mBtnOpenAttachment->setClickedCallback(onClickOpenAttachment, this);
mNoNoticesStr = getString("no_notices_text");
mPanelCreateNotice = getChild<LLPanel>("panel_create_new_notice",recurse);
mPanelViewNotice = getChild<LLPanel>("panel_view_past_notice",recurse);
- // Must be in front of all other UI elements.
- LLPanel* dtv = getChild<LLPanel>("drop_target",recurse);
- LLGroupDropTarget* target = new LLGroupDropTarget("drop_target",
- dtv->getRect(),
- this, mGroupID);
- target->setEnabled(TRUE);
- target->setToolTip(dtv->getToolTip());
-
- mPanelCreateNotice->addChild(target);
- mPanelCreateNotice->removeChild(dtv, TRUE);
+ LLGroupDropTarget* target = getChild<LLGroupDropTarget> ("drop_target");
+ target->setPanel (this);
+ target->setGroup (mGroupID);
arrangeNoticeView(VIEW_PAST_NOTICE);
@@ -299,6 +304,9 @@ BOOL LLPanelGroupNotices::postBuild()
void LLPanelGroupNotices::activate()
{
+ if(mNoticesList)
+ mNoticesList->deleteAllItems();
+
BOOL can_send = gAgent.hasPowerInGroup(mGroupID,GP_NOTICES_SEND);
BOOL can_receive = gAgent.hasPowerInGroup(mGroupID,GP_NOTICES_RECEIVE);
@@ -331,7 +339,7 @@ void LLPanelGroupNotices::setItem(LLPointer<LLInventoryItem> inv_item)
inv_item->getFlags(),
item_is_multi );
- mCreateInventoryIcon->setImage(icon_name);
+ mCreateInventoryIcon->setValue(icon_name);
mCreateInventoryIcon->setVisible(TRUE);
std::stringstream ss;
@@ -367,7 +375,7 @@ void LLPanelGroupNotices::onClickSendMessage(void* data)
if (self->mCreateSubject->getText().empty())
{
// Must supply a subject
- LLNotifications::instance().add("MustSpecifyGroupNoticeSubject");
+ LLNotificationsUtil::add("MustSpecifyGroupNoticeSubject");
return;
}
send_group_notice(
@@ -376,13 +384,38 @@ void LLPanelGroupNotices::onClickSendMessage(void* data)
self->mCreateMessage->getText(),
self->mInventoryItem);
+
+ //instantly add new notice. actual notice will be added after ferreshNotices call
+ LLUUID id = LLUUID::generateNewID();
+ std::string subj = self->mCreateSubject->getText();
+ std::string name ;
+ LLAgentUI::buildFullname(name);
+ U32 timestamp = 0;
+
+ LLSD row;
+ row["id"] = id;
+
+ row["columns"][0]["column"] = "icon";
+
+ row["columns"][1]["column"] = "subject";
+ row["columns"][1]["value"] = subj;
+
+ row["columns"][2]["column"] = "from";
+ row["columns"][2]["value"] = name;
+
+ row["columns"][3]["column"] = "date";
+ row["columns"][3]["value"] = build_notice_date(timestamp);
+
+ row["columns"][4]["column"] = "sort";
+ row["columns"][4]["value"] = llformat( "%u", timestamp);
+
+ self->mNoticesList->addElement(row, ADD_BOTTOM);
+
self->mCreateMessage->clear();
self->mCreateSubject->clear();
onClickRemoveAttachment(data);
self->arrangeNoticeView(VIEW_PAST_NOTICE);
- onClickRefreshNotices(self);
-
}
//static
@@ -404,6 +437,26 @@ void LLPanelGroupNotices::onClickNewMessage(void* data)
self->mNoticesList->deselectAllItems(TRUE); // TRUE == don't commit on chnage
}
+void LLPanelGroupNotices::refreshNotices()
+{
+ onClickRefreshNotices(this);
+ /*
+ lldebugs << "LLPanelGroupNotices::onClickGetPastNotices" << llendl;
+
+ mNoticesList->deleteAllItems();
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessage("GroupNoticesListRequest");
+ msg->nextBlock("AgentData");
+ msg->addUUID("AgentID",gAgent.getID());
+ msg->addUUID("SessionID",gAgent.getSessionID());
+ msg->nextBlock("Data");
+ msg->addUUID("GroupID",self->mGroupID);
+ gAgent.sendReliableMessage();
+ */
+
+}
+
void LLPanelGroupNotices::onClickRefreshNotices(void* data)
{
lldebugs << "LLPanelGroupNotices::onClickGetPastNotices" << llendl;
@@ -460,13 +513,16 @@ void LLPanelGroupNotices::processNotices(LLMessageSystem* msg)
S32 i=0;
S32 count = msg->getNumberOfBlocks("Data");
+
+ mNoticesList->setEnabled(TRUE);
+
for (;i<count;++i)
{
msg->getUUID("Data","NoticeID",id,i);
if (1 == count && id.isNull())
{
// Only one entry, the dummy entry.
- mNoticesList->addCommentText(mNoNoticesStr);
+ mNoticesList->setCommentText(mNoNoticesStr);
mNoticesList->setEnabled(FALSE);
return;
}
@@ -505,7 +561,7 @@ void LLPanelGroupNotices::processNotices(LLMessageSystem* msg)
mNoticesList->addElement(row, ADD_BOTTOM);
}
- mNoticesList->sortItems();
+ mNoticesList->updateSort();
}
void LLPanelGroupNotices::onSelectNotice(LLUICtrl* ctrl, void* data)
@@ -554,11 +610,11 @@ void LLPanelGroupNotices::showNotice(const std::string& subject,
LLInventoryType::IT_TEXTURE,
0, FALSE);
- mViewInventoryIcon->setImage(icon_name);
+ mViewInventoryIcon->setValue(icon_name);
mViewInventoryIcon->setVisible(TRUE);
std::stringstream ss;
- ss << " " << inventory_name;
+ ss << " " << LLViewerInventoryItem::getDisplayName(inventory_name);
mViewInventoryName->setText(ss.str());
mBtnOpenAttachment->setEnabled(TRUE);
@@ -585,3 +641,17 @@ void LLPanelGroupNotices::arrangeNoticeView(ENoticeView view_type)
mBtnOpenAttachment->setEnabled(FALSE);
}
}
+void LLPanelGroupNotices::setGroupID(const LLUUID& id)
+{
+ sInstances.erase(mGroupID);
+ LLPanelGroupTab::setGroupID(id);
+ sInstances[mGroupID] = this;
+
+ mBtnNewMessage->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_NOTICES_SEND));
+
+ LLGroupDropTarget* target = getChild<LLGroupDropTarget> ("drop_target");
+ target->setPanel (this);
+ target->setGroup (mGroupID);
+
+ activate();
+}
diff --git a/indra/newview/llpanelgroupnotices.h b/indra/newview/llpanelgroupnotices.h
index 916032c1b6..4bda38c897 100644
--- a/indra/newview/llpanelgroupnotices.h
+++ b/indra/newview/llpanelgroupnotices.h
@@ -34,7 +34,7 @@
#define LL_LLPANELGROUPNOTICES_H
#include "llpanelgroup.h"
-#include "llmemory.h"
+#include "llpointer.h"
#include "llinventory.h"
class LLLineEditor;
@@ -47,11 +47,10 @@ class LLScrollListCtrl;
class LLPanelGroupNotices : public LLPanelGroupTab
{
public:
- LLPanelGroupNotices(const std::string& name, const LLUUID& group_id);
+ LLPanelGroupNotices();
virtual ~LLPanelGroupNotices();
// LLPanelGroupTab
- static void* createTab(void* data);
virtual void activate();
//virtual bool needsApply(std::string& mesg);
//virtual bool apply(std::string& mesg);
@@ -70,6 +69,10 @@ public:
const std::string& inventory_name,
LLOfferInfo* inventory_offer);
+ void refreshNotices();
+
+ virtual void setGroupID(const LLUUID& id);
+
private:
static void onClickRemoveAttachment(void* data);
static void onClickOpenAttachment(void* data);
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 6e65181f99..45f0381d6f 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -36,23 +36,29 @@
#include "llagent.h"
#include "llbutton.h"
-#include "llfloateravatarinfo.h"
+#include "llfiltereditor.h"
#include "llfloatergroupinvite.h"
+#include "llavataractions.h"
#include "lliconctrl.h"
#include "lllineeditor.h"
#include "llnamelistctrl.h"
-#include "llnotify.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
#include "llpanelgrouproles.h"
#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "llscrolllistcell.h"
#include "lltabcontainer.h"
#include "lltextbox.h"
#include "lltexteditor.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewerwindow.h"
#include "llfocusmgr.h"
#include "roles_constants.h"
+static LLRegisterPanelClassWrapper<LLPanelGroupRoles> t_panel_group_roles("panel_group_roles");
+
bool agentCanRemoveFromRole(const LLUUID& group_id,
const LLUUID& role_id)
{
@@ -106,14 +112,9 @@ bool agentCanAddToRole(const LLUUID& group_id,
}
// static
-void* LLPanelGroupRoles::createTab(void* data)
-{
- LLUUID* group_id = static_cast<LLUUID*>(data);
- return new LLPanelGroupRoles("panel group roles", *group_id);
-}
-LLPanelGroupRoles::LLPanelGroupRoles(const std::string& name, const LLUUID& group_id)
-: LLPanelGroupTab(name, group_id),
+LLPanelGroupRoles::LLPanelGroupRoles()
+: LLPanelGroupTab(),
mCurrentTab(NULL),
mRequestedTab( NULL ),
mSubTabContainer( NULL ),
@@ -124,13 +125,6 @@ LLPanelGroupRoles::LLPanelGroupRoles(const std::string& name, const LLUUID& grou
LLPanelGroupRoles::~LLPanelGroupRoles()
{
- int i;
- for (i = 0; i < mSubTabContainer->getTabCount(); ++i)
- {
- LLPanelGroupSubTab* subtabp = (LLPanelGroupSubTab*) mSubTabContainer->getPanelByIndex(i);
-
- subtabp->removeObserver(this);
- }
}
BOOL LLPanelGroupRoles::postBuild()
@@ -142,20 +136,24 @@ BOOL LLPanelGroupRoles::postBuild()
if (!mSubTabContainer) return FALSE;
// Hook up each sub-tabs callback and widgets.
- S32 i;
- for (i = 0; i < mSubTabContainer->getTabCount(); ++i)
+ for (S32 i = 0; i < mSubTabContainer->getTabCount(); ++i)
{
- LLPanelGroupSubTab* subtabp = (LLPanelGroupSubTab*) mSubTabContainer->getPanelByIndex(i);
-
+ LLPanel* panel = mSubTabContainer->getPanelByIndex(i);
+ LLPanelGroupSubTab* subtabp = dynamic_cast<LLPanelGroupSubTab*>(panel);
+ if (!subtabp)
+ {
+ llwarns << "Invalid subtab panel: " << panel->getName() << llendl;
+ return FALSE;
+ }
// Add click callbacks to all the tabs.
- mSubTabContainer->setTabChangeCallback(subtabp, onClickSubTab);
- mSubTabContainer->setTabUserData(subtabp, this);
+ mSubTabContainer->setCommitCallback(boost::bind(&LLPanelGroupRoles::handleClickSubTab, this));
// Hand the subtab a pointer to this LLPanelGroupRoles, so that it can
// look around for the widgets it is interested in.
- if (!subtabp->postBuildSubTab(this)) return FALSE;
+ if (!subtabp->postBuildSubTab(this))
+ return FALSE;
- subtabp->addObserver(this);
+ //subtabp->addObserver(this);
}
// Set the current tab to whatever is currently being shown.
@@ -198,13 +196,6 @@ BOOL LLPanelGroupRoles::isVisibleByAgent(LLAgent* agentp)
}
-// static
-void LLPanelGroupRoles::onClickSubTab(void* user_data, bool from_click)
-{
- LLPanelGroupRoles* self = static_cast<LLPanelGroupRoles*>(user_data);
- self->handleClickSubTab();
-}
-
void LLPanelGroupRoles::handleClickSubTab()
{
// If we are already handling a transition,
@@ -241,7 +232,7 @@ BOOL LLPanelGroupRoles::attemptTransition()
LLSD args;
args["NEEDS_APPLY_MESSAGE"] = mesg;
args["WANT_APPLY_MESSAGE"] = mWantApplyMesg;
- LLNotifications::instance().add("PanelGroupApply", args, LLSD(),
+ LLNotificationsUtil::add("PanelGroupApply", args, LLSD(),
boost::bind(&LLPanelGroupRoles::handleNotifyCallback, this, _1, _2));
mHasModal = TRUE;
// We need to reselect the current tab, since it isn't finished.
@@ -285,7 +276,7 @@ void LLPanelGroupRoles::transitionToTab()
bool LLPanelGroupRoles::handleNotifyCallback(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
mHasModal = FALSE;
switch (option)
{
@@ -301,7 +292,7 @@ bool LLPanelGroupRoles::handleNotifyCallback(const LLSD& notification, const LLS
mHasModal = TRUE;
LLSD args;
args["MESSAGE"] = apply_mesg;
- LLNotifications::instance().add("GenericAlert", args, LLSD(), boost::bind(&LLPanelGroupRoles::onModalClose, this, _1, _2));
+ LLNotificationsUtil::add("GenericAlert", args, LLSD(), boost::bind(&LLPanelGroupRoles::onModalClose, this, _1, _2));
}
// Skip switching tabs.
break;
@@ -371,24 +362,11 @@ void LLPanelGroupRoles::cancel()
panelp->cancel();
}
-// Pass all of these messages to the currently visible sub tab.
-std::string LLPanelGroupRoles::getHelpText() const
-{
- LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
- if (panelp)
- {
- return panelp->getHelpText();
- }
- else
- {
- return mHelpText;
- }
-}
-
void LLPanelGroupRoles::update(LLGroupChange gc)
{
if (mGroupID.isNull()) return;
-
+
+
LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
if (panelp)
{
@@ -398,6 +376,7 @@ void LLPanelGroupRoles::update(LLGroupChange gc)
{
llwarns << "LLPanelGroupRoles::update() -- No subtab to update!" << llendl;
}
+
}
void LLPanelGroupRoles::activate()
@@ -465,22 +444,16 @@ BOOL LLPanelGroupRoles::hasModal()
return panelp->hasModal();
}
-// PanelGroupTab observer trigger
-void LLPanelGroupRoles::tabChanged()
-{
- notifyObservers();
-}
////////////////////////////
// LLPanelGroupSubTab
////////////////////////////
-LLPanelGroupSubTab::LLPanelGroupSubTab(const std::string& name, const LLUUID& group_id)
-: LLPanelGroupTab(name, group_id),
+LLPanelGroupSubTab::LLPanelGroupSubTab()
+: LLPanelGroupTab(),
mHeader(NULL),
mFooter(NULL),
- mSearchLineEditor(NULL),
- mSearchButton(NULL),
- mShowAllButton(NULL)
+ mActivated(false),
+ mSearchEditor(NULL)
{
}
@@ -488,120 +461,58 @@ LLPanelGroupSubTab::~LLPanelGroupSubTab()
{
}
-BOOL LLPanelGroupSubTab::postBuild()
-{
- // Hook up the search widgets.
- bool recurse = true;
- mSearchLineEditor = getChild<LLLineEditor>("search_text", recurse);
-
- if (!mSearchLineEditor) return FALSE;
- mSearchLineEditor->setKeystrokeCallback(onSearchKeystroke);
- mSearchLineEditor->setCallbackUserData(this);
-
- mSearchButton = getChild<LLButton>("search_button", recurse);
-
- if (!mSearchButton) return FALSE;
- mSearchButton->setClickedCallback(onClickSearch);
- mSearchButton->setCallbackUserData(this);
- mSearchButton->setEnabled(FALSE);
-
- mShowAllButton = getChild<LLButton>("show_all_button", recurse);
-
- if (!mShowAllButton) return FALSE;
- mShowAllButton->setClickedCallback(onClickShowAll);
- mShowAllButton->setCallbackUserData(this);
- mShowAllButton->setEnabled(FALSE);
-
+BOOL LLPanelGroupSubTab::postBuildSubTab(LLView* root)
+{
// Get icons for later use.
mActionIcons.clear();
- bool no_recurse = false;
-
- LLIconCtrl* icon = getChild<LLIconCtrl>("power_folder_icon",no_recurse);
- if (icon && !icon->getImageName().empty())
+ if (hasString("power_folder_icon"))
{
- mActionIcons["folder"] = icon->getImageName();
- removeChild(icon, TRUE);
+ mActionIcons["folder"] = getString("power_folder_icon");
}
- icon = getChild<LLIconCtrl>("power_all_have_icon",no_recurse);
- if (icon && !icon->getImageName().empty())
+ if (hasString("power_all_have_icon"))
{
- mActionIcons["full"] = icon->getImageName();
- removeChild(icon, TRUE);
+ mActionIcons["full"] = getString("power_all_have_icon");
}
- icon = getChild<LLIconCtrl>("power_partial_icon",no_recurse);
- if (icon && !icon->getImageName().empty())
+ if (hasString("power_partial_icon"))
{
- mActionIcons["partial"] = icon->getImageName();
- removeChild(icon, TRUE);
+ mActionIcons["partial"] = getString("power_partial_icon");
}
-
- return LLPanelGroupTab::postBuild();
-}
-
-// static
-void LLPanelGroupSubTab::onSearchKeystroke(LLLineEditor* caller, void* user_data)
-{
- LLPanelGroupSubTab* self = static_cast<LLPanelGroupSubTab*>(user_data);
- self->handleSearchKeystroke(caller);
+ return TRUE;
}
-void LLPanelGroupSubTab::handleSearchKeystroke(LLLineEditor* caller)
+BOOL LLPanelGroupSubTab::postBuild()
{
- if (caller->getText().size())
- {
- setDefaultBtn( mSearchButton );
- mSearchButton->setEnabled(TRUE);
- }
- else
- {
- setDefaultBtn( NULL );
- mSearchButton->setEnabled(FALSE);
- }
-}
+ // Hook up the search widgets.
+ bool recurse = true;
+ mSearchEditor = getChild<LLFilterEditor>("filter_input", recurse);
-// static
-void LLPanelGroupSubTab::onClickSearch(void* user_data)
-{
- LLPanelGroupSubTab* self = static_cast<LLPanelGroupSubTab*>(user_data);
- self->handleClickSearch();
-}
-
-void LLPanelGroupSubTab::handleClickSearch()
-{
- lldebugs << "LLPanelGroupSubTab::handleClickSearch()" << llendl;
+ if (!mSearchEditor)
+ return FALSE;
- if (0 == mSearchLineEditor->getText().size())
- {
- // No search text. (This shouldn't happen... the search button should have been disabled).
- llwarns << "handleClickSearch with no search text!" << llendl;
- mSearchButton->setEnabled(FALSE);
- return;
- }
+ mSearchEditor->setCommitCallback(boost::bind(&LLPanelGroupSubTab::setSearchFilter, this, _2));
- setSearchFilter( mSearchLineEditor->getText() );
- mShowAllButton->setEnabled(TRUE);
+ return LLPanelGroupTab::postBuild();
}
-// static
-void LLPanelGroupSubTab::onClickShowAll(void* user_data)
+void LLPanelGroupSubTab::setGroupID(const LLUUID& id)
{
- LLPanelGroupSubTab* self = static_cast<LLPanelGroupSubTab*>(user_data);
- self->handleClickShowAll();
-}
+ LLPanelGroupTab::setGroupID(id);
+ if(mSearchEditor)
+ {
+ mSearchEditor->clear();
+ setSearchFilter("");
+ }
-void LLPanelGroupSubTab::handleClickShowAll()
-{
- lldebugs << "LLPanelGroupSubTab::handleClickShowAll()" << llendl;
- setSearchFilter( LLStringUtil::null );
- mShowAllButton->setEnabled(FALSE);
+ mActivated = false;
}
void LLPanelGroupSubTab::setSearchFilter(const std::string& filter)
{
- lldebugs << "LLPanelGroupSubTab::setSearchFilter() ==> '" << filter << "'" << llendl;
+ if(mSearchFilter == filter)
+ return;
mSearchFilter = filter;
LLStringUtil::toLower(mSearchFilter);
update(GC_ALL);
@@ -609,13 +520,11 @@ void LLPanelGroupSubTab::setSearchFilter(const std::string& filter)
void LLPanelGroupSubTab::activate()
{
- lldebugs << "LLPanelGroupSubTab::activate()" << llendl;
setOthersVisible(TRUE);
}
void LLPanelGroupSubTab::deactivate()
{
- lldebugs << "LLPanelGroupSubTab::deactivate()" << llendl;
setOthersVisible(FALSE);
}
@@ -625,19 +534,11 @@ void LLPanelGroupSubTab::setOthersVisible(BOOL b)
{
mHeader->setVisible( b );
}
- else
- {
- llwarns << "LLPanelGroupSubTab missing header!" << llendl;
- }
if (mFooter)
{
mFooter->setVisible( b );
}
- else
- {
- llwarns << "LLPanelGroupSubTab missing footer!" << llendl;
- }
}
bool LLPanelGroupSubTab::matchesActionSearchFilter(std::string action)
@@ -662,8 +563,7 @@ bool LLPanelGroupSubTab::matchesActionSearchFilter(std::string action)
void LLPanelGroupSubTab::buildActionsList(LLScrollListCtrl* ctrl,
U64 allowed_by_some,
U64 allowed_by_all,
- icon_map_t& icons,
- void (*commit_callback)(LLUICtrl*,void*),
+ LLUICtrl::commit_callback_t commit_callback,
BOOL show_all,
BOOL filter,
BOOL is_owner_role)
@@ -683,7 +583,6 @@ void LLPanelGroupSubTab::buildActionsList(LLScrollListCtrl* ctrl,
allowed_by_some,
allowed_by_all,
(*ras_it),
- icons,
commit_callback,
show_all,
filter,
@@ -695,8 +594,7 @@ void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl,
U64 allowed_by_some,
U64 allowed_by_all,
LLRoleActionSet* action_set,
- icon_map_t& icons,
- void (*commit_callback)(LLUICtrl*,void*),
+ LLUICtrl::commit_callback_t commit_callback,
BOOL show_all,
BOOL filter,
BOOL is_owner_role)
@@ -709,18 +607,25 @@ void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl,
LLSD row;
row["columns"][0]["column"] = "icon";
- icon_map_t::iterator iter = icons.find("folder");
- if (iter != icons.end())
+ row["columns"][0]["type"] = "icon";
+
+ icon_map_t::iterator iter = mActionIcons.find("folder");
+ if (iter != mActionIcons.end())
{
- row["columns"][0]["type"] = "icon";
row["columns"][0]["value"] = (*iter).second;
}
row["columns"][1]["column"] = "action";
+ row["columns"][1]["type"] = "text";
row["columns"][1]["value"] = action_set->mActionSetData->mName;
- row["columns"][1]["font-style"] = "BOLD";
+ row["columns"][1]["font"]["name"] = "SANSSERIF_SMALL";
+
LLScrollListItem* title_row = ctrl->addElement(row, ADD_BOTTOM, action_set->mActionSetData);
+
+ LLScrollListText* name_textp = dynamic_cast<LLScrollListText*>(title_row->getColumn(2)); //?? I have no idea fix getColumn(1) return column spacer...
+ if (name_textp)
+ name_textp->setFontStyle(LLFontGL::BOLD);
bool category_matches_filter = (filter) ? matchesActionSearchFilter(action_set->mActionSetData->mName) : true;
@@ -774,8 +679,8 @@ void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl,
{
if (show_full_strength)
{
- icon_map_t::iterator iter = icons.find("full");
- if (iter != icons.end())
+ icon_map_t::iterator iter = mActionIcons.find("full");
+ if (iter != mActionIcons.end())
{
row["columns"][column_index]["column"] = "checkbox";
row["columns"][column_index]["type"] = "icon";
@@ -785,8 +690,8 @@ void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl,
}
else
{
- icon_map_t::iterator iter = icons.find("partial");
- if (iter != icons.end())
+ icon_map_t::iterator iter = mActionIcons.find("partial");
+ if (iter != mActionIcons.end())
{
row["columns"][column_index]["column"] = "checkbox";
row["columns"][column_index]["type"] = "icon";
@@ -799,7 +704,7 @@ void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl,
row["columns"][column_index]["column"] = "action";
row["columns"][column_index]["value"] = (*ra_it)->mDescription;
- row["columns"][column_index]["font"] = "SANSSERIFSMALL";
+ row["columns"][column_index]["font"] = "SANSSERIF_SMALL";
LLScrollListItem* item = ctrl->addElement(row, ADD_BOTTOM, (*ra_it));
@@ -810,7 +715,6 @@ void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl,
LLCheckBoxCtrl* check = check_cell->getCheckBox();
check->setEnabled(can_change_actions);
check->setCommitCallback(commit_callback);
- check->setCallbackUserData(ctrl->getCallbackUserData());
check->setToolTip( check->getLabel() );
if (show_all)
@@ -860,15 +764,11 @@ void LLPanelGroupSubTab::setFooterEnabled(BOOL enable)
// LLPanelGroupMembersSubTab
////////////////////////////
-// static
-void* LLPanelGroupMembersSubTab::createTab(void* data)
-{
- LLUUID* group_id = static_cast<LLUUID*>(data);
- return new LLPanelGroupMembersSubTab("panel group members sub tab", *group_id);
-}
-LLPanelGroupMembersSubTab::LLPanelGroupMembersSubTab(const std::string& name, const LLUUID& group_id)
-: LLPanelGroupSubTab(name, group_id),
+static LLRegisterPanelClassWrapper<LLPanelGroupMembersSubTab> t_panel_group_members_subtab("panel_group_members_subtab");
+
+LLPanelGroupMembersSubTab::LLPanelGroupMembersSubTab()
+: LLPanelGroupSubTab(),
mMembersList(NULL),
mAssignedRolesList(NULL),
mAllowedActionsList(NULL),
@@ -885,6 +785,8 @@ LLPanelGroupMembersSubTab::~LLPanelGroupMembersSubTab()
BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root)
{
+ LLPanelGroupSubTab::postBuildSubTab(root);
+
// Upcast parent so we can ask it for sibling controls.
LLPanelGroupRoles* parent = (LLPanelGroupRoles*) root;
@@ -900,31 +802,35 @@ BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root)
if (!mMembersList || !mAssignedRolesList || !mAllowedActionsList) return FALSE;
// We want to be notified whenever a member is selected.
- mMembersList->setCallbackUserData(this);
mMembersList->setCommitOnSelectionChange(TRUE);
- mMembersList->setCommitCallback(onMemberSelect);
+ mMembersList->setCommitCallback(onMemberSelect, this);
// Show the member's profile on double click.
- mMembersList->setDoubleClickCallback(onMemberDoubleClick);
+ mMembersList->setDoubleClickCallback(onMemberDoubleClick, this);
+ mMembersList->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
LLButton* button = parent->getChild<LLButton>("member_invite", recurse);
if ( button )
{
- button->setClickedCallback(onInviteMember);
- button->setCallbackUserData(this);
+ button->setClickedCallback(onInviteMember, this);
button->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_MEMBER_INVITE));
}
mEjectBtn = parent->getChild<LLButton>("member_eject", recurse);
if ( mEjectBtn )
{
- mEjectBtn->setClickedCallback(onEjectMembers);
- mEjectBtn->setCallbackUserData(this);
+ mEjectBtn->setClickedCallback(onEjectMembers, this);
mEjectBtn->setEnabled(FALSE);
}
return TRUE;
}
+void LLPanelGroupMembersSubTab::setGroupID(const LLUUID& id)
+{
+ LLPanelGroupSubTab::setGroupID(id);
+
+}
+
// static
void LLPanelGroupMembersSubTab::onMemberSelect(LLUICtrl* ctrl, void* user_data)
@@ -961,10 +867,12 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
for (itor = selection.begin();
itor != selection.end(); ++itor)
{
- selected_members.push_back( (*itor)->getUUID() );
+ LLUUID member_id = (*itor)->getValue()["uuid"];
+
+ selected_members.push_back( member_id );
// Get this member's power mask including any unsaved changes
- U64 powers = getAgentPowersBasedOnRoleChanges((*itor)->getUUID());
+ U64 powers = getAgentPowersBasedOnRoleChanges( member_id );
allowed_by_all &= powers;
allowed_by_some |= powers;
@@ -977,7 +885,6 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
buildActionsList(mAllowedActionsList,
allowed_by_some,
allowed_by_all,
- mActionIcons,
NULL,
FALSE,
FALSE,
@@ -1097,8 +1004,7 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
// Extract the checkbox that was created.
LLScrollListCheck* check_cell = (LLScrollListCheck*) item->getColumn(0);
LLCheckBoxCtrl* check = check_cell->getCheckBox();
- check->setCommitCallback(onRoleCheck);
- check->setCallbackUserData(this);
+ check->setCommitCallback(onRoleCheck, this);
check->set( count > 0 );
check->setTentative(
(0 != count)
@@ -1110,6 +1016,7 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
//last owner. We should check for this special case
// -jwolk
check->setEnabled(cb_enable);
+ item->setEnabled(cb_enable);
}
}
else
@@ -1186,15 +1093,39 @@ void LLPanelGroupMembersSubTab::handleEjectMembers()
for (itor = selection.begin() ;
itor != selection.end(); ++itor)
{
- selected_members.push_back((*itor)->getUUID());
+ LLUUID member_id = (*itor)->getValue()["uuid"];
+ selected_members.push_back( member_id );
}
mMembersList->deleteSelectedItems();
+ sendEjectNotifications(mGroupID, selected_members);
+
LLGroupMgr::getInstance()->sendGroupMemberEjects(mGroupID,
selected_members);
}
+void LLPanelGroupMembersSubTab::sendEjectNotifications(const LLUUID& group_id, const std::vector<LLUUID>& selected_members)
+{
+ LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(group_id);
+
+ if (group_data)
+ {
+ for (std::vector<LLUUID>::const_iterator i = selected_members.begin(); i != selected_members.end(); ++i)
+ {
+ LLSD args;
+ std::string name;
+
+ gCacheName->getFullName(*i, name);
+
+ args["AVATAR_NAME"] = name;
+ args["GROUP_NAME"] = group_data->mName;
+
+ LLNotifications::instance().add(LLNotification::Params("EjectAvatarFromGroup").substitutions(args));
+ }
+ }
+}
+
void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id,
LLRoleMemberChangeType type)
{
@@ -1219,7 +1150,8 @@ void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id,
for (std::vector<LLScrollListItem*>::iterator itor = selection.begin() ;
itor != selection.end(); ++itor)
{
- member_id = (*itor)->getUUID();
+
+ member_id = (*itor)->getValue()["uuid"];
//see if we requested a change for this member before
if ( mMemberRoleChangeData.find(member_id) == mMemberRoleChangeData.end() )
@@ -1278,7 +1210,6 @@ void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id,
buildActionsList(mAllowedActionsList,
powers_some_have,
powers_all_have,
- mActionIcons,
NULL,
FALSE,
FALSE,
@@ -1311,15 +1242,19 @@ void LLPanelGroupMembersSubTab::handleMemberDoubleClick()
LLScrollListItem* selected = mMembersList->getFirstSelected();
if (selected)
{
- LLFloaterAvatarInfo::showFromDirectory( selected->getUUID() );
+ LLUUID member_id = selected->getValue()["uuid"];
+ LLAvatarActions::showProfile( member_id );
}
}
void LLPanelGroupMembersSubTab::activate()
{
LLPanelGroupSubTab::activate();
-
- update(GC_ALL);
+ if(!mActivated)
+ {
+ update(GC_ALL);
+ mActivated = true;
+ }
}
void LLPanelGroupMembersSubTab::deactivate()
@@ -1370,7 +1305,7 @@ bool LLPanelGroupMembersSubTab::apply(std::string& mesg)
{
mHasModal = TRUE;
args["ROLE_NAME"] = rd.mRoleName;
- LLNotifications::instance().add("AddGroupOwnerWarning",
+ LLNotificationsUtil::add("AddGroupOwnerWarning",
args,
LLSD(),
boost::bind(&LLPanelGroupMembersSubTab::addOwnerCB, this, _1, _2));
@@ -1395,7 +1330,7 @@ bool LLPanelGroupMembersSubTab::apply(std::string& mesg)
bool LLPanelGroupMembersSubTab::addOwnerCB(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
mHasModal = FALSE;
if (0 == option)
@@ -1594,9 +1529,6 @@ void LLPanelGroupMembersSubTab::update(LLGroupChange gc)
return;
}
- // Rebuild the members list.
- mMembersList->deleteAllItems();
-
// Wait for both all data to be retrieved before displaying anything.
if ( gdatap->isMemberDataComplete()
&& gdatap->isRoleDataComplete()
@@ -1628,7 +1560,7 @@ void LLPanelGroupMembersSubTab::update(LLGroupChange gc)
retrieved << "Retrieving role member mappings...";
}
mMembersList->setEnabled(FALSE);
- mMembersList->addCommentText(retrieved.str());
+ mMembersList->setCommentText(retrieved.str());
}
}
@@ -1636,7 +1568,7 @@ void LLPanelGroupMembersSubTab::updateMembers()
{
mPendingMemberUpdate = FALSE;
- lldebugs << "LLPanelGroupMembersSubTab::updateMembers()" << llendl;
+ // Rebuild the members list.
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
if (!gdatap)
@@ -1653,7 +1585,12 @@ void LLPanelGroupMembersSubTab::updateMembers()
{
return;
}
-
+
+ //cleanup list only for first iretation
+ if(mMemberProgress == gdatap->mMembers.begin())
+ mMembersList->deleteAllItems();
+
+
LLGroupMgrGroupData::member_list_t::iterator end = gdatap->mMembers.end();
S32 i = 0;
@@ -1691,9 +1628,11 @@ void LLPanelGroupMembersSubTab::updateMembers()
row["columns"][2]["column"] = "online";
row["columns"][2]["value"] = mMemberProgress->second->getOnlineStatus();
- row["columns"][2]["font"] = "SANSSERIFSMALL";
+ row["columns"][2]["font"] = "SANSSERIF_SMALL";
- mMembersList->addElement(row);//, ADD_SORTED);
+ LLScrollListItem* member = mMembersList->addElement(row);//, ADD_SORTED);
+
+ LLUUID id = member->getValue()["uuid"];
mHasMatch = TRUE;
}
}
@@ -1707,7 +1646,7 @@ void LLPanelGroupMembersSubTab::updateMembers()
else
{
mMembersList->setEnabled(FALSE);
- mMembersList->addCommentText(std::string("No match."));
+ mMembersList->setCommentText(std::string("No match."));
}
}
else
@@ -1725,15 +1664,21 @@ void LLPanelGroupMembersSubTab::updateMembers()
// LLPanelGroupRolesSubTab
////////////////////////////
-// static
-void* LLPanelGroupRolesSubTab::createTab(void* data)
-{
- LLUUID* group_id = static_cast<LLUUID*>(data);
- return new LLPanelGroupRolesSubTab("panel group roles sub tab", *group_id);
-}
+static LLRegisterPanelClassWrapper<LLPanelGroupRolesSubTab> t_panel_group_roles_subtab("panel_group_roles_subtab");
-LLPanelGroupRolesSubTab::LLPanelGroupRolesSubTab(const std::string& name, const LLUUID& group_id)
-: LLPanelGroupSubTab(name, group_id), mHasRoleChange(FALSE)
+LLPanelGroupRolesSubTab::LLPanelGroupRolesSubTab()
+ : LLPanelGroupSubTab(),
+ mRolesList(NULL),
+ mAssignedMembersList(NULL),
+ mAllowedActionsList(NULL),
+ mRoleName(NULL),
+ mRoleTitle(NULL),
+ mRoleDescription(NULL),
+ mMemberVisibleCheck(NULL),
+ mDeleteRoleButton(NULL),
+ mCreateRoleButton(NULL),
+
+ mHasRoleChange(FALSE)
{
}
@@ -1743,6 +1688,8 @@ LLPanelGroupRolesSubTab::~LLPanelGroupRolesSubTab()
BOOL LLPanelGroupRolesSubTab::postBuildSubTab(LLView* root)
{
+ LLPanelGroupSubTab::postBuildSubTab(root);
+
// Upcast parent so we can ask it for sibling controls.
LLPanelGroupRoles* parent = (LLPanelGroupRoles*) root;
@@ -1775,8 +1722,7 @@ BOOL LLPanelGroupRolesSubTab::postBuildSubTab(LLView* root)
parent->getChild<LLButton>("role_create", recurse);
if ( mCreateRoleButton )
{
- mCreateRoleButton->setCallbackUserData(this);
- mCreateRoleButton->setClickedCallback(onCreateRole);
+ mCreateRoleButton->setClickedCallback(onCreateRole, this);
mCreateRoleButton->setEnabled(FALSE);
}
@@ -1784,33 +1730,28 @@ BOOL LLPanelGroupRolesSubTab::postBuildSubTab(LLView* root)
parent->getChild<LLButton>("role_delete", recurse);
if ( mDeleteRoleButton )
{
- mDeleteRoleButton->setCallbackUserData(this);
- mDeleteRoleButton->setClickedCallback(onDeleteRole);
+ mDeleteRoleButton->setClickedCallback(onDeleteRole, this);
mDeleteRoleButton->setEnabled(FALSE);
}
mRolesList->setCommitOnSelectionChange(TRUE);
- mRolesList->setCallbackUserData(this);
- mRolesList->setCommitCallback(onRoleSelect);
+ mRolesList->setCommitCallback(onRoleSelect, this);
+
+ mAssignedMembersList->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
- mMemberVisibleCheck->setCallbackUserData(this);
- mMemberVisibleCheck->setCommitCallback(onMemberVisibilityChange);
+ mMemberVisibleCheck->setCommitCallback(onMemberVisibilityChange, this);
mAllowedActionsList->setCommitOnSelectionChange(TRUE);
- mAllowedActionsList->setCallbackUserData(this);
mRoleName->setCommitOnFocusLost(TRUE);
- mRoleName->setCallbackUserData(this);
- mRoleName->setKeystrokeCallback(onPropertiesKey);
+ mRoleName->setKeystrokeCallback(onPropertiesKey, this);
mRoleTitle->setCommitOnFocusLost(TRUE);
- mRoleTitle->setCallbackUserData(this);
- mRoleTitle->setKeystrokeCallback(onPropertiesKey);
+ mRoleTitle->setKeystrokeCallback(onPropertiesKey, this);
mRoleDescription->setCommitOnFocusLost(TRUE);
- mRoleDescription->setCallbackUserData(this);
- mRoleDescription->setCommitCallback(onDescriptionCommit);
- mRoleDescription->setFocusReceivedCallback(onDescriptionFocus, this);
+ mRoleDescription->setCommitCallback(onDescriptionCommit, this);
+ mRoleDescription->setFocusReceivedCallback(boost::bind(onDescriptionFocus, _1, this));
setFooterEnabled(FALSE);
@@ -2059,8 +2000,7 @@ void LLPanelGroupRolesSubTab::handleRoleSelect()
buildActionsList(mAllowedActionsList,
rd.mRolePowers,
0LL,
- mActionIcons,
- onActionCheck,
+ boost::bind(&LLPanelGroupRolesSubTab::handleActionCheck, this, _1, false),
TRUE,
FALSE,
is_owner_role);
@@ -2157,24 +2097,18 @@ void LLPanelGroupRolesSubTab::buildMembersList()
}
}
-// static
-void LLPanelGroupRolesSubTab::onActionCheck(LLUICtrl* ctrl, void* user_data)
-{
- LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
- LLCheckBoxCtrl* check = static_cast<LLCheckBoxCtrl*>(ctrl);
- if (!check || !self) return;
-
- self->handleActionCheck(check);
-}
-
struct ActionCBData
{
LLPanelGroupRolesSubTab* mSelf;
LLCheckBoxCtrl* mCheck;
};
-void LLPanelGroupRolesSubTab::handleActionCheck(LLCheckBoxCtrl* check, bool force)
+void LLPanelGroupRolesSubTab::handleActionCheck(LLUICtrl* ctrl, bool force)
{
+ LLCheckBoxCtrl* check = dynamic_cast<LLCheckBoxCtrl*>(ctrl);
+ if (!check)
+ return;
+
lldebugs << "LLPanelGroupRolesSubTab::handleActionSelect()" << llendl;
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
@@ -2223,7 +2157,7 @@ void LLPanelGroupRolesSubTab::handleActionCheck(LLCheckBoxCtrl* check, bool forc
{
warning = "AssignDangerousAbilityWarning";
}
- LLNotifications::instance().add(warning, args, LLSD(), boost::bind(&LLPanelGroupRolesSubTab::addActionCB, this, _1, _2, check));
+ LLNotificationsUtil::add(warning, args, LLSD(), boost::bind(&LLPanelGroupRolesSubTab::addActionCB, this, _1, _2, check));
}
else
{
@@ -2251,7 +2185,7 @@ bool LLPanelGroupRolesSubTab::addActionCB(const LLSD& notification, const LLSD&
mHasModal = FALSE;
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
// User clicked "Yes"
@@ -2397,7 +2331,7 @@ void LLPanelGroupRolesSubTab::handleDeleteRole()
{
LLSD args;
args["MESSAGE"] = mRemoveEveryoneTxt;
- LLNotifications::instance().add("GenericAlert", args);
+ LLNotificationsUtil::add("GenericAlert", args);
return;
}
@@ -2438,15 +2372,11 @@ void LLPanelGroupRolesSubTab::saveRoleChanges()
// LLPanelGroupActionsSubTab
////////////////////////////
-// static
-void* LLPanelGroupActionsSubTab::createTab(void* data)
-{
- LLUUID* group_id = static_cast<LLUUID*>(data);
- return new LLPanelGroupActionsSubTab("panel group actions sub tab", *group_id);
-}
+static LLRegisterPanelClassWrapper<LLPanelGroupActionsSubTab> t_panel_group_actions_subtab("panel_group_actions_subtab");
+
-LLPanelGroupActionsSubTab::LLPanelGroupActionsSubTab(const std::string& name, const LLUUID& group_id)
-: LLPanelGroupSubTab(name, group_id)
+LLPanelGroupActionsSubTab::LLPanelGroupActionsSubTab()
+: LLPanelGroupSubTab()
{
}
@@ -2456,6 +2386,8 @@ LLPanelGroupActionsSubTab::~LLPanelGroupActionsSubTab()
BOOL LLPanelGroupActionsSubTab::postBuildSubTab(LLView* root)
{
+ LLPanelGroupSubTab::postBuildSubTab(root);
+
// Upcast parent so we can ask it for sibling controls.
LLPanelGroupRoles* parent = (LLPanelGroupRoles*) root;
@@ -2472,12 +2404,9 @@ BOOL LLPanelGroupActionsSubTab::postBuildSubTab(LLView* root)
if (!mActionList || !mActionDescription || !mActionRoles || !mActionMembers) return FALSE;
- mActionList->setCallbackUserData(this);
mActionList->setCommitOnSelectionChange(TRUE);
- mActionList->setCommitCallback(onActionSelect);
-
- mActionMembers->setCallbackUserData(this);
- mActionRoles->setCallbackUserData(this);
+ mActionList->setCommitCallback(boost::bind(&LLPanelGroupActionsSubTab::handleActionSelect, this));
+ mActionList->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
update(GC_ALL);
@@ -2487,12 +2416,8 @@ BOOL LLPanelGroupActionsSubTab::postBuildSubTab(LLView* root)
void LLPanelGroupActionsSubTab::activate()
{
LLPanelGroupSubTab::activate();
- lldebugs << "LLPanelGroupActionsSubTab::activate()" << llendl;
- mActionList->deselectAllItems();
- mActionMembers->deleteAllItems();
- mActionRoles->deleteAllItems();
- mActionDescription->clear();
+ update(GC_ALL);
}
void LLPanelGroupActionsSubTab::deactivate()
@@ -2530,20 +2455,12 @@ void LLPanelGroupActionsSubTab::update(LLGroupChange gc)
buildActionsList(mActionList,
GP_ALL_POWERS,
GP_ALL_POWERS,
- mActionIcons,
NULL,
FALSE,
TRUE,
FALSE);
}
-// static
-void LLPanelGroupActionsSubTab::onActionSelect(LLUICtrl* scroll, void* data)
-{
- LLPanelGroupActionsSubTab* self = static_cast<LLPanelGroupActionsSubTab*>(data);
- self->handleActionSelect();
-}
-
void LLPanelGroupActionsSubTab::handleActionSelect()
{
mActionMembers->deleteAllItems();
@@ -2629,3 +2546,26 @@ void LLPanelGroupActionsSubTab::handleActionSelect()
LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mGroupID);
}
}
+void LLPanelGroupRoles::setGroupID(const LLUUID& id)
+{
+ LLPanelGroupTab::setGroupID(id);
+
+ LLPanelGroupMembersSubTab* group_members_tab = findChild<LLPanelGroupMembersSubTab>("members_sub_tab");
+ LLPanelGroupRolesSubTab* group_roles_tab = findChild<LLPanelGroupRolesSubTab>("roles_sub_tab");
+ LLPanelGroupActionsSubTab* group_actions_tab = findChild<LLPanelGroupActionsSubTab>("actions_sub_tab");
+
+ if(group_members_tab) group_members_tab->setGroupID(id);
+ if(group_roles_tab) group_roles_tab->setGroupID(id);
+ if(group_actions_tab) group_actions_tab->setGroupID(id);
+
+ LLButton* button = getChild<LLButton>("member_invite");
+ if ( button )
+ button->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_MEMBER_INVITE));
+
+ if(mSubTabContainer)
+ mSubTabContainer->selectTab(0);
+
+ activate();
+}
+
+
diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h
index 95057bbfaf..eac22a6338 100644
--- a/indra/newview/llpanelgrouproles.h
+++ b/indra/newview/llpanelgrouproles.h
@@ -35,6 +35,7 @@
#include "llpanelgroup.h"
+class LLFilterEditor;
class LLNameListCtrl;
class LLPanelGroupSubTab;
class LLPanelGroupMembersSubTab;
@@ -42,17 +43,17 @@ class LLPanelGroupRolesSubTab;
class LLPanelGroupActionsSubTab;
class LLScrollListCtrl;
class LLScrollListItem;
+class LLTextEditor;
// Forward declare for friend usage.
//virtual BOOL LLPanelGroupSubTab::postBuildSubTab(LLView*);
typedef std::map<std::string,std::string> icon_map_t;
-class LLPanelGroupRoles : public LLPanelGroupTab,
- public LLPanelGroupTabObserver
+class LLPanelGroupRoles : public LLPanelGroupTab
{
public:
- LLPanelGroupRoles(const std::string& name, const LLUUID& group_id);
+ LLPanelGroupRoles();
virtual ~LLPanelGroupRoles();
// Allow sub tabs to ask for sibling controls.
@@ -63,8 +64,7 @@ public:
virtual BOOL postBuild();
virtual BOOL isVisibleByAgent(LLAgent* agentp);
- static void* createTab(void* data);
- static void onClickSubTab(void*,bool);
+
void handleClickSubTab();
// Checks if the current tab needs to be applied, and tries to switch to the requested tab.
@@ -78,7 +78,6 @@ public:
bool onModalClose(const LLSD& notification, const LLSD& response);
// Most of these messages are just passed on to the current sub-tab.
- virtual std::string getHelpText() const;
virtual void activate();
virtual void deactivate();
virtual bool needsApply(std::string& mesg);
@@ -87,8 +86,7 @@ public:
virtual void cancel();
virtual void update(LLGroupChange gc);
- // PanelGroupTab observer trigger
- virtual void tabChanged();
+ virtual void setGroupID(const LLUUID& id);
protected:
LLPanelGroupTab* mCurrentTab;
@@ -104,21 +102,13 @@ protected:
class LLPanelGroupSubTab : public LLPanelGroupTab
{
public:
- LLPanelGroupSubTab(const std::string& name, const LLUUID& group_id);
+ LLPanelGroupSubTab();
virtual ~LLPanelGroupSubTab();
virtual BOOL postBuild();
// This allows sub-tabs to collect child widgets from a higher level in the view hierarchy.
- virtual BOOL postBuildSubTab(LLView* root) { return TRUE; }
-
- static void onSearchKeystroke(LLLineEditor* caller, void* user_data);
- void handleSearchKeystroke(LLLineEditor* caller);
-
- static void onClickSearch(void*);
- void handleClickSearch();
- static void onClickShowAll(void*);
- void handleClickShowAll();
+ virtual BOOL postBuildSubTab(LLView* root);
virtual void setSearchFilter( const std::string& filter );
@@ -127,11 +117,16 @@ public:
// Helper functions
bool matchesActionSearchFilter(std::string action);
+
+
+ void setFooterEnabled(BOOL enable);
+
+ virtual void setGroupID(const LLUUID& id);
+protected:
void buildActionsList(LLScrollListCtrl* ctrl,
U64 allowed_by_some,
U64 allowed_by_all,
- icon_map_t& icons,
- void (*commit_callback)(LLUICtrl*,void*),
+ LLUICtrl::commit_callback_t commit_callback,
BOOL show_all,
BOOL filter,
BOOL is_owner_role);
@@ -139,38 +134,34 @@ public:
U64 allowed_by_some,
U64 allowed_by_all,
LLRoleActionSet* action_set,
- icon_map_t& icons,
- void (*commit_callback)(LLUICtrl*,void*),
+ LLUICtrl::commit_callback_t commit_callback,
BOOL show_all,
BOOL filter,
BOOL is_owner_role);
- void setFooterEnabled(BOOL enable);
protected:
LLPanel* mHeader;
LLPanel* mFooter;
- LLLineEditor* mSearchLineEditor;
- LLButton* mSearchButton;
- LLButton* mShowAllButton;
+ LLFilterEditor* mSearchEditor;
std::string mSearchFilter;
icon_map_t mActionIcons;
+ bool mActivated;
+
void setOthersVisible(BOOL b);
};
class LLPanelGroupMembersSubTab : public LLPanelGroupSubTab
{
public:
- LLPanelGroupMembersSubTab(const std::string& name, const LLUUID& group_id);
+ LLPanelGroupMembersSubTab();
virtual ~LLPanelGroupMembersSubTab();
virtual BOOL postBuildSubTab(LLView* root);
- static void* createTab(void* data);
-
static void onMemberSelect(LLUICtrl*, void*);
void handleMemberSelect();
@@ -182,6 +173,7 @@ public:
static void onEjectMembers(void*);
void handleEjectMembers();
+ void sendEjectNotifications(const LLUUID& group_id, const std::vector<LLUUID>& selected_members);
static void onRoleCheck(LLUICtrl* check, void* user_data);
void handleRoleCheck(const LLUUID& role_id,
@@ -200,6 +192,8 @@ public:
virtual void draw();
+ virtual void setGroupID(const LLUUID& id);
+
protected:
typedef std::map<LLUUID, LLRoleMemberChangeType> role_change_data_map_t;
typedef std::map<LLUUID, role_change_data_map_t*> member_role_changes_map_t;
@@ -229,13 +223,11 @@ protected:
class LLPanelGroupRolesSubTab : public LLPanelGroupSubTab
{
public:
- LLPanelGroupRolesSubTab(const std::string& name, const LLUUID& group_id);
+ LLPanelGroupRolesSubTab();
virtual ~LLPanelGroupRolesSubTab();
virtual BOOL postBuildSubTab(LLView* root);
- static void* createTab(void* data);
-
virtual void activate();
virtual void deactivate();
virtual bool needsApply(std::string& mesg);
@@ -249,7 +241,6 @@ public:
void buildMembersList();
static void onActionCheck(LLUICtrl*, void*);
- void handleActionCheck(LLCheckBoxCtrl*, bool force=false);
bool addActionCB(const LLSD& notification, const LLSD& response, LLCheckBoxCtrl* check);
static void onPropertiesKey(LLLineEditor*, void*);
@@ -268,10 +259,8 @@ public:
void saveRoleChanges();
protected:
- LLSD createRoleItem(const LLUUID& role_id,
- std::string name,
- std::string title,
- S32 members);
+ void handleActionCheck(LLUICtrl* ctrl, bool force);
+ LLSD createRoleItem(const LLUUID& role_id, std::string name, std::string title, S32 members);
LLScrollListCtrl* mRolesList;
LLNameListCtrl* mAssignedMembersList;
@@ -293,12 +282,11 @@ protected:
class LLPanelGroupActionsSubTab : public LLPanelGroupSubTab
{
public:
- LLPanelGroupActionsSubTab(const std::string& name, const LLUUID& group_id);
+ LLPanelGroupActionsSubTab();
virtual ~LLPanelGroupActionsSubTab();
virtual BOOL postBuildSubTab(LLView* root);
- static void* createTab(void* data);
virtual void activate();
virtual void deactivate();
@@ -306,7 +294,6 @@ public:
virtual bool apply(std::string& mesg);
virtual void update(LLGroupChange gc);
- static void onActionSelect(LLUICtrl*, void*);
void handleActionSelect();
protected:
LLScrollListCtrl* mActionList;
diff --git a/indra/newview/llpanelhome.cpp b/indra/newview/llpanelhome.cpp
new file mode 100644
index 0000000000..713d2d79b4
--- /dev/null
+++ b/indra/newview/llpanelhome.cpp
@@ -0,0 +1,79 @@
+/**
+* @file llpanelhome.cpp
+* @author Martin Reddy
+* @brief The Home side tray panel
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+#include "llpanelhome.h"
+
+#include "llmediactrl.h"
+#include "llviewerhome.h"
+
+static LLRegisterPanelClassWrapper<LLPanelHome> t_home("panel_sidetray_home");
+
+LLPanelHome::LLPanelHome() :
+ LLPanel(),
+ LLViewerMediaObserver(),
+ mBrowser(NULL),
+ mFirstView(true)
+{
+}
+
+void LLPanelHome::onOpen(const LLSD& key)
+{
+ // display the home page the first time we open the panel
+ // *NOTE: this seems to happen during login. Can we avoid that?
+ if (mFirstView && mBrowser)
+ {
+ mBrowser->navigateHome();
+ }
+ mFirstView = false;
+}
+
+BOOL LLPanelHome::postBuild()
+{
+ mBrowser = getChild<LLMediaCtrl>("browser");
+ if (mBrowser)
+ {
+ // read the URL to display from settings.xml
+ std::string url = LLViewerHome::getHomeURL();
+
+ mBrowser->addObserver(this);
+ mBrowser->setTrusted(true);
+ mBrowser->setHomePageUrl(url);
+ }
+
+ return TRUE;
+}
+
+void LLPanelHome::handleMediaEvent(LLPluginClassMedia *self, EMediaEvent event)
+{
+}
diff --git a/indra/newview/llpanelhome.h b/indra/newview/llpanelhome.h
new file mode 100644
index 0000000000..dfeca45b29
--- /dev/null
+++ b/indra/newview/llpanelhome.h
@@ -0,0 +1,64 @@
+/**
+* @file llpanelhome.h
+* @author Martin Reddy
+* @brief The Home side tray panel
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#ifndef LL_LLPANELHOME_H
+#define LL_LLPANELHOME_H
+
+#include "llpanel.h"
+#include "llsd.h"
+#include "llviewermediaobserver.h"
+
+class LLMediaCtrl;
+
+/**
+ * Base class for web-based Home side tray
+ */
+class LLPanelHome :
+ public LLPanel,
+ public LLViewerMediaObserver
+{
+public:
+ LLPanelHome();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+private:
+ // inherited from LLViewerMediaObserver
+ /*virtual*/ void handleMediaEvent(LLPluginClassMedia *self, EMediaEvent event);
+
+ LLMediaCtrl *mBrowser;
+ bool mFirstView;
+};
+
+#endif //LL_LLPANELHOME_H
diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp
new file mode 100644
index 0000000000..ff1e43b526
--- /dev/null
+++ b/indra/newview/llpanelimcontrolpanel.cpp
@@ -0,0 +1,338 @@
+/**
+ * @file llpanelavatar.cpp
+ * @brief LLPanelAvatar and related class implementations
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterreg.h"
+
+#include "llpanelimcontrolpanel.h"
+
+#include "llagent.h"
+#include "llavataractions.h"
+#include "llavatariconctrl.h"
+#include "llbutton.h"
+#include "llgroupactions.h"
+#include "llavatarlist.h"
+#include "llparticipantlist.h"
+#include "llimview.h"
+#include "llvoicechannel.h"
+#include "llsidetray.h"
+#include "llspeakers.h"
+#include "lltrans.h"
+
+void LLPanelChatControlPanel::onCallButtonClicked()
+{
+ gIMMgr->startCall(mSessionId);
+}
+
+void LLPanelChatControlPanel::onEndCallButtonClicked()
+{
+ gIMMgr->endCall(mSessionId);
+}
+
+void LLPanelChatControlPanel::onOpenVoiceControlsClicked()
+{
+ LLFloaterReg::showInstance("voice_controls");
+}
+
+void LLPanelChatControlPanel::onChange(EStatusType status, const std::string &channelURI, bool proximal)
+{
+ if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL)
+ {
+ return;
+ }
+
+ updateCallButton();
+}
+
+void LLPanelChatControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)
+{
+ updateButtons(new_state >= LLVoiceChannel::STATE_CALL_STARTED);
+}
+
+void LLPanelChatControlPanel::updateCallButton()
+{
+ // hide/show call button
+ bool voice_enabled = LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking();
+
+ LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionId);
+ if (!session) return;
+
+ bool session_initialized = session->mSessionInitialized;
+ bool callback_enabled = session->mCallBackEnabled;
+
+ BOOL enable_connect = session_initialized
+ && voice_enabled
+ && callback_enabled;
+ childSetEnabled("call_btn", enable_connect);
+}
+
+void LLPanelChatControlPanel::updateButtons(bool is_call_started)
+{
+ childSetVisible("end_call_btn_panel", is_call_started);
+ childSetVisible("voice_ctrls_btn_panel", is_call_started);
+ childSetVisible("call_btn_panel", ! is_call_started);
+ updateCallButton();
+
+}
+
+LLPanelChatControlPanel::~LLPanelChatControlPanel()
+{
+ mVoiceChannelStateChangeConnection.disconnect();
+ if(LLVoiceClient::getInstance())
+ LLVoiceClient::getInstance()->removeObserver(this);
+}
+
+BOOL LLPanelChatControlPanel::postBuild()
+{
+ childSetAction("call_btn", boost::bind(&LLPanelChatControlPanel::onCallButtonClicked, this));
+ childSetAction("end_call_btn", boost::bind(&LLPanelChatControlPanel::onEndCallButtonClicked, this));
+ childSetAction("voice_ctrls_btn", boost::bind(&LLPanelChatControlPanel::onOpenVoiceControlsClicked, this));
+
+ gVoiceClient->addObserver(this);
+
+ return TRUE;
+}
+
+void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id)
+{
+ //Method is called twice for AdHoc and Group chat. Second time when server init reply received
+ mSessionId = session_id;
+ LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionId);
+ if(voice_channel)
+ {
+ mVoiceChannelStateChangeConnection = voice_channel->setStateChangedCallback(boost::bind(&LLPanelChatControlPanel::onVoiceChannelStateChanged, this, _1, _2));
+
+ //call (either p2p, group or ad-hoc) can be already in started state
+ updateButtons(voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED);
+ }
+}
+
+LLPanelIMControlPanel::LLPanelIMControlPanel()
+{
+}
+
+LLPanelIMControlPanel::~LLPanelIMControlPanel()
+{
+ LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarID, this);
+}
+
+BOOL LLPanelIMControlPanel::postBuild()
+{
+ childSetAction("view_profile_btn", boost::bind(&LLPanelIMControlPanel::onViewProfileButtonClicked, this));
+ childSetAction("add_friend_btn", boost::bind(&LLPanelIMControlPanel::onAddFriendButtonClicked, this));
+
+ childSetAction("share_btn", boost::bind(&LLPanelIMControlPanel::onShareButtonClicked, this));
+ childSetAction("teleport_btn", boost::bind(&LLPanelIMControlPanel::onTeleportButtonClicked, this));
+ childSetAction("pay_btn", boost::bind(&LLPanelIMControlPanel::onPayButtonClicked, this));
+ childSetEnabled("add_friend_btn", !LLAvatarActions::isFriend(getChild<LLAvatarIconCtrl>("avatar_icon")->getAvatarId()));
+
+
+
+ return LLPanelChatControlPanel::postBuild();
+}
+
+void LLPanelIMControlPanel::onTeleportButtonClicked()
+{
+ LLAvatarActions::offerTeleport(mAvatarID);
+}
+void LLPanelIMControlPanel::onPayButtonClicked()
+{
+ LLAvatarActions::pay(mAvatarID);
+}
+
+void LLPanelIMControlPanel::onViewProfileButtonClicked()
+{
+ LLAvatarActions::showProfile(mAvatarID);
+}
+
+void LLPanelIMControlPanel::onAddFriendButtonClicked()
+{
+ LLAvatarIconCtrl* avatar_icon = getChild<LLAvatarIconCtrl>("avatar_icon");
+ std::string full_name = avatar_icon->getFirstName() + " " + avatar_icon->getLastName();
+ LLAvatarActions::requestFriendshipDialog(mAvatarID, full_name);
+}
+
+void LLPanelIMControlPanel::onShareButtonClicked()
+{
+ LLAvatarActions::share(mAvatarID);
+}
+
+void LLPanelIMControlPanel::setSessionId(const LLUUID& session_id)
+{
+ LLPanelChatControlPanel::setSessionId(session_id);
+
+ LLIMModel& im_model = LLIMModel::instance();
+
+ LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarID, this);
+ mAvatarID = im_model.getOtherParticipantID(session_id);
+ LLAvatarTracker::instance().addParticularFriendObserver(mAvatarID, this);
+
+ // Disable "Add friend" button for friends.
+ childSetEnabled("add_friend_btn", !LLAvatarActions::isFriend(mAvatarID));
+
+ // Disable "Teleport" button if friend is offline
+ if(LLAvatarActions::isFriend(mAvatarID))
+ {
+ childSetEnabled("teleport_btn", LLAvatarTracker::instance().isBuddyOnline(mAvatarID));
+ }
+
+ getChild<LLAvatarIconCtrl>("avatar_icon")->setValue(mAvatarID);
+
+ // Disable most profile buttons if the participant is
+ // not really an SL avatar (e.g., an Avaline caller).
+ LLIMModel::LLIMSession* im_session =
+ im_model.findIMSession(session_id);
+ if( im_session && !im_session->mOtherParticipantIsAvatar )
+ {
+ childSetEnabled("view_profile_btn", FALSE);
+ childSetEnabled("add_friend_btn", FALSE);
+
+ childSetEnabled("share_btn", FALSE);
+ childSetEnabled("teleport_btn", FALSE);
+ childSetEnabled("pay_btn", FALSE);
+
+ getChild<LLTextBox>("avatar_name")->setValue(im_session->mName);
+ getChild<LLTextBox>("avatar_name")->setToolTip(im_session->mName);
+ }
+ else
+ {
+ // If the participant is an avatar, fetch the currect name
+ gCacheName->get(mAvatarID, FALSE, boost::bind(&LLPanelIMControlPanel::nameUpdatedCallback, this, _1, _2, _3, _4));
+ }
+}
+
+//virtual
+void LLPanelIMControlPanel::changed(U32 mask)
+{
+ childSetEnabled("add_friend_btn", !LLAvatarActions::isFriend(mAvatarID));
+
+ // Disable "Teleport" button if friend is offline
+ if(LLAvatarActions::isFriend(mAvatarID))
+ {
+ childSetEnabled("teleport_btn", LLAvatarTracker::instance().isBuddyOnline(mAvatarID));
+ }
+}
+
+void LLPanelIMControlPanel::nameUpdatedCallback(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
+{
+ if ( id == mAvatarID )
+ {
+ std::string avatar_name;
+ avatar_name.assign(first);
+ avatar_name.append(" ");
+ avatar_name.append(last);
+ getChild<LLTextBox>("avatar_name")->setValue(avatar_name);
+ getChild<LLTextBox>("avatar_name")->setToolTip(avatar_name);
+ }
+}
+
+LLPanelGroupControlPanel::LLPanelGroupControlPanel(const LLUUID& session_id):
+mParticipantList(NULL)
+{
+}
+
+BOOL LLPanelGroupControlPanel::postBuild()
+{
+ childSetAction("group_info_btn", boost::bind(&LLPanelGroupControlPanel::onGroupInfoButtonClicked, this));
+
+ return LLPanelChatControlPanel::postBuild();
+}
+
+LLPanelGroupControlPanel::~LLPanelGroupControlPanel()
+{
+ delete mParticipantList;
+ mParticipantList = NULL;
+}
+
+// virtual
+void LLPanelGroupControlPanel::draw()
+{
+ // Need to resort the participant list if it's in sort by recent speaker order.
+ if (mParticipantList)
+ mParticipantList->updateRecentSpeakersOrder();
+ //* TODO: find better way to properly enable call button for group and remove this call from draw()
+ updateCallButton();
+ LLPanelChatControlPanel::draw();
+}
+
+void LLPanelGroupControlPanel::onGroupInfoButtonClicked()
+{
+ LLGroupActions::show(mGroupID);
+}
+
+void LLPanelGroupControlPanel::onSortMenuItemClicked(const LLSD& userdata)
+{
+ // TODO: Check this code when when sort order menu will be added. (EM)
+ if (false && !mParticipantList)
+ return;
+
+ std::string chosen_item = userdata.asString();
+
+ if (chosen_item == "sort_name")
+ {
+ mParticipantList->setSortOrder(LLParticipantList::E_SORT_BY_NAME);
+ }
+
+}
+
+void LLPanelGroupControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)
+{
+ LLPanelChatControlPanel::onVoiceChannelStateChanged(old_state, new_state);
+ mParticipantList->setSpeakingIndicatorsVisible(new_state >= LLVoiceChannel::STATE_CALL_STARTED);
+}
+
+void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id)
+{
+ LLPanelChatControlPanel::setSessionId(session_id);
+
+ mGroupID = session_id;
+
+ // for group and Ad-hoc chat we need to include agent into list
+ if(!mParticipantList)
+ {
+ LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(session_id);
+ mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true,false);
+ }
+}
+
+
+LLPanelAdHocControlPanel::LLPanelAdHocControlPanel(const LLUUID& session_id):LLPanelGroupControlPanel(session_id)
+{
+}
+
+BOOL LLPanelAdHocControlPanel::postBuild()
+{
+ //We don't need LLPanelGroupControlPanel::postBuild() to be executed as there is no group_info_btn at AdHoc chat
+ return LLPanelChatControlPanel::postBuild();
+}
+
diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h
new file mode 100644
index 0000000000..3ab505a084
--- /dev/null
+++ b/indra/newview/llpanelimcontrolpanel.h
@@ -0,0 +1,137 @@
+/**
+ * @file llpanelimcontrolpanel.h
+ * @brief LLPanelIMControlPanel and related class definitions
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELIMCONTROLPANEL_H
+#define LL_LLPANELIMCONTROLPANEL_H
+
+#include "llpanel.h"
+#include "llvoicechannel.h"
+#include "llcallingcard.h"
+
+class LLParticipantList;
+
+class LLPanelChatControlPanel
+ : public LLPanel
+ , public LLVoiceClientStatusObserver
+{
+public:
+ LLPanelChatControlPanel() :
+ mSessionId(LLUUID()) {};
+ ~LLPanelChatControlPanel();
+
+ virtual BOOL postBuild();
+
+ void onCallButtonClicked();
+ void onEndCallButtonClicked();
+ void onOpenVoiceControlsClicked();
+
+ // Implements LLVoiceClientStatusObserver::onChange() to enable the call
+ // button when voice is available
+ /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
+
+ virtual void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state);
+
+ void updateButtons(bool is_call_started);
+
+ // Enables/disables call button depending on voice availability
+ void updateCallButton();
+
+ virtual void setSessionId(const LLUUID& session_id);
+ const LLUUID& getSessionId() { return mSessionId; }
+
+private:
+ LLUUID mSessionId;
+
+ // connection to voice channel state change signal
+ boost::signals2::connection mVoiceChannelStateChangeConnection;
+};
+
+
+class LLPanelIMControlPanel : public LLPanelChatControlPanel, LLFriendObserver
+{
+public:
+ LLPanelIMControlPanel();
+ ~LLPanelIMControlPanel();
+
+ BOOL postBuild();
+
+ void setSessionId(const LLUUID& session_id);
+
+ // LLFriendObserver trigger
+ virtual void changed(U32 mask);
+
+protected:
+ void nameUpdatedCallback(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
+
+private:
+ void onViewProfileButtonClicked();
+ void onAddFriendButtonClicked();
+ void onShareButtonClicked();
+ void onTeleportButtonClicked();
+ void onPayButtonClicked();
+
+ LLUUID mAvatarID;
+};
+
+
+class LLPanelGroupControlPanel : public LLPanelChatControlPanel
+{
+public:
+ LLPanelGroupControlPanel(const LLUUID& session_id);
+ ~LLPanelGroupControlPanel();
+
+ BOOL postBuild();
+
+ void setSessionId(const LLUUID& session_id);
+ /*virtual*/ void draw();
+
+protected:
+ LLUUID mGroupID;
+
+ LLParticipantList* mParticipantList;
+
+private:
+ void onGroupInfoButtonClicked();
+ void onSortMenuItemClicked(const LLSD& userdata);
+ /*virtual*/ void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state);
+};
+
+class LLPanelAdHocControlPanel : public LLPanelGroupControlPanel
+{
+public:
+ LLPanelAdHocControlPanel(const LLUUID& session_id);
+
+ BOOL postBuild();
+
+};
+
+#endif // LL_LLPANELIMCONTROLPANEL_H
diff --git a/indra/newview/llpanelland.cpp b/indra/newview/llpanelland.cpp
index 8bb100d335..417a804834 100644
--- a/indra/newview/llpanelland.cpp
+++ b/indra/newview/llpanelland.cpp
@@ -40,6 +40,7 @@
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llfloaterland.h"
+#include "llfloaterreg.h"
#include "lltextbox.h"
#include "llviewercontrol.h"
#include "llviewerparcelmgr.h"
@@ -69,7 +70,6 @@ BOOL LLPanelLandInfo::postBuild()
childSetAction("button subdivide land",onClickDivide,this);
childSetAction("button join land",onClickJoin,this);
childSetAction("button about land",onClickAbout,this);
- childSetAction("button show owners help", onShowOwnersHelp, this);
mCheckShowOwners = getChild<LLCheckBoxCtrl>("checkbox show owners");
childSetValue("checkbox show owners", gSavedSettings.getBOOL("ShowParcelOwners"));
@@ -79,8 +79,8 @@ BOOL LLPanelLandInfo::postBuild()
//
// Methods
//
-LLPanelLandInfo::LLPanelLandInfo(const std::string& name)
-: LLPanel(name),
+LLPanelLandInfo::LLPanelLandInfo()
+: LLPanel(),
mCheckShowOwners(NULL)
{
if (!sInstance)
@@ -262,10 +262,5 @@ void LLPanelLandInfo::onClickAbout(void*)
LLViewerParcelMgr::getInstance()->selectParcelInRectangle();
}
- LLFloaterLand::showInstance();
-}
-
-void LLPanelLandInfo::onShowOwnersHelp(void* user_data)
-{
- LLNotifications::instance().add("ShowOwnersHelp");
+ LLFloaterReg::showInstance("about_land");
}
diff --git a/indra/newview/llpanelland.h b/indra/newview/llpanelland.h
index 9a7e977711..02e7e7bf38 100644
--- a/indra/newview/llpanelland.h
+++ b/indra/newview/llpanelland.h
@@ -46,7 +46,7 @@ class LLPanelLandInfo
: public LLPanel
{
public:
- LLPanelLandInfo(const std::string& name);
+ LLPanelLandInfo();
virtual ~LLPanelLandInfo();
void refresh();
@@ -60,7 +60,6 @@ protected:
static void onClickDivide(void*);
static void onClickJoin(void*);
static void onClickAbout(void*);
- static void onShowOwnersHelp(void*);
protected:
//LLTextBox* mTextPriceLabel;
diff --git a/indra/newview/llpanellandaudio.cpp b/indra/newview/llpanellandaudio.cpp
new file mode 100644
index 0000000000..6a4c909759
--- /dev/null
+++ b/indra/newview/llpanellandaudio.cpp
@@ -0,0 +1,194 @@
+/**
+ * @file llpanellandaudio.cpp
+ * @brief Allows configuration of "media" for a land parcel,
+ * for example movies, web pages, and audio.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanellandaudio.h"
+
+// viewer includes
+#include "llmimetypes.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+#include "lluictrlfactory.h"
+
+// library includes
+#include "llcheckboxctrl.h"
+#include "llcombobox.h"
+#include "llfloaterurlentry.h"
+#include "llfocusmgr.h"
+#include "lllineeditor.h"
+#include "llparcel.h"
+#include "lltextbox.h"
+#include "llradiogroup.h"
+#include "llspinctrl.h"
+#include "llsdutil.h"
+#include "lltexturectrl.h"
+#include "roles_constants.h"
+#include "llscrolllistctrl.h"
+
+// Values for the parcel voice settings radio group
+enum
+{
+ kRadioVoiceChatEstate = 0,
+ kRadioVoiceChatPrivate = 1,
+ kRadioVoiceChatDisable = 2
+};
+
+//---------------------------------------------------------------------------
+// LLPanelLandAudio
+//---------------------------------------------------------------------------
+
+LLPanelLandAudio::LLPanelLandAudio(LLParcelSelectionHandle& parcel)
+: LLPanel(/*std::string("land_media_panel")*/), mParcel(parcel)
+{
+}
+
+
+// virtual
+LLPanelLandAudio::~LLPanelLandAudio()
+{
+}
+
+
+BOOL LLPanelLandAudio::postBuild()
+{
+ mCheckSoundLocal = getChild<LLCheckBoxCtrl>("check sound local");
+ childSetCommitCallback("check sound local", onCommitAny, this);
+
+ mCheckParcelEnableVoice = getChild<LLCheckBoxCtrl>("parcel_enable_voice_channel");
+ childSetCommitCallback("parcel_enable_voice_channel", onCommitAny, this);
+
+ // This one is always disabled so no need for a commit callback
+ mCheckEstateDisabledVoice = getChild<LLCheckBoxCtrl>("parcel_enable_voice_channel_is_estate_disabled");
+
+ mCheckParcelVoiceLocal = getChild<LLCheckBoxCtrl>("parcel_enable_voice_channel_local");
+ childSetCommitCallback("parcel_enable_voice_channel_local", onCommitAny, this);
+
+ mMusicURLEdit = getChild<LLLineEditor>("music_url");
+ childSetCommitCallback("music_url", onCommitAny, this);
+
+ mMusicUrlCheck = getChild<LLCheckBoxCtrl>("hide_music_url");
+ childSetCommitCallback("hide_music_url", onCommitAny, this);
+
+ return TRUE;
+}
+
+
+// public
+void LLPanelLandAudio::refresh()
+{
+ LLParcel *parcel = mParcel->getParcel();
+
+ if (!parcel)
+ {
+ clearCtrls();
+ }
+ else
+ {
+ // something selected, hooray!
+
+ // Display options
+ BOOL can_change_media = LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_LAND_CHANGE_MEDIA);
+
+ mCheckSoundLocal->set( parcel->getSoundLocal() );
+ mCheckSoundLocal->setEnabled( can_change_media );
+
+ mMusicUrlCheck->set( parcel->getObscureMusic() );
+ mMusicUrlCheck->setEnabled( can_change_media );
+
+ bool allow_voice = parcel->getParcelFlagAllowVoice();
+
+ LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
+ if (region && region->isVoiceEnabled())
+ {
+ mCheckEstateDisabledVoice->setVisible(false);
+
+ mCheckParcelEnableVoice->setVisible(true);
+ mCheckParcelEnableVoice->setEnabled( can_change_media );
+ mCheckParcelEnableVoice->set(allow_voice);
+
+ mCheckParcelVoiceLocal->setEnabled( can_change_media && allow_voice );
+ }
+ else
+ {
+ // Voice disabled at estate level, overrides parcel settings
+ // Replace the parcel voice checkbox with a disabled one
+ // labelled with an explanatory message
+ mCheckEstateDisabledVoice->setVisible(true);
+
+ mCheckParcelEnableVoice->setVisible(false);
+ mCheckParcelEnableVoice->setEnabled(false);
+ mCheckParcelVoiceLocal->setEnabled(false);
+ }
+
+ mCheckParcelEnableVoice->set(allow_voice);
+ mCheckParcelVoiceLocal->set(!parcel->getParcelFlagUseEstateVoiceChannel());
+
+ mMusicURLEdit->setText(parcel->getMusicURL());
+ mMusicURLEdit->setEnabled( can_change_media );
+ }
+}
+// static
+void LLPanelLandAudio::onCommitAny(LLUICtrl*, void *userdata)
+{
+ LLPanelLandAudio *self = (LLPanelLandAudio *)userdata;
+
+ LLParcel* parcel = self->mParcel->getParcel();
+ if (!parcel)
+ {
+ return;
+ }
+
+ // Extract data from UI
+ BOOL sound_local = self->mCheckSoundLocal->get();
+ std::string music_url = self->mMusicURLEdit->getText();
+ U8 obscure_music = self->mMusicUrlCheck->get();
+
+ BOOL voice_enabled = self->mCheckParcelEnableVoice->get();
+ BOOL voice_estate_chan = !self->mCheckParcelVoiceLocal->get();
+
+ // Remove leading/trailing whitespace (common when copying/pasting)
+ LLStringUtil::trim(music_url);
+
+ // Push data into current parcel
+ parcel->setParcelFlag(PF_ALLOW_VOICE_CHAT, voice_enabled);
+ parcel->setParcelFlag(PF_USE_ESTATE_VOICE_CHAN, voice_estate_chan);
+ parcel->setParcelFlag(PF_SOUND_LOCAL, sound_local);
+ parcel->setMusicURL(music_url);
+ parcel->setObscureMusic(obscure_music);
+
+ // Send current parcel data upstream to server
+ LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel );
+
+ // Might have changed properties, so let's redraw!
+ self->refresh();
+}
diff --git a/indra/newview/llpanellandaudio.h b/indra/newview/llpanellandaudio.h
new file mode 100644
index 0000000000..19766a40b6
--- /dev/null
+++ b/indra/newview/llpanellandaudio.h
@@ -0,0 +1,64 @@
+/**
+ * @file llpanellandaudio.h
+ * @brief Allows configuration of "audio" for a land parcel.
+ *
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLPANELLANDAUDIO_H
+#define LLPANELLANDAUDIO_H
+
+#include "lllineeditor.h"
+#include "llpanel.h"
+#include "llparcelselection.h"
+#include "lluifwd.h" // widget pointer types
+
+class LLPanelLandAudio
+ : public LLPanel
+{
+public:
+ LLPanelLandAudio(LLSafeHandle<LLParcelSelection>& parcelp);
+ /*virtual*/ ~LLPanelLandAudio();
+ /*virtual*/ BOOL postBuild();
+ void refresh();
+
+private:
+ static void onCommitAny(LLUICtrl* ctrl, void *userdata);
+
+private:
+ LLCheckBoxCtrl* mCheckSoundLocal;
+ LLCheckBoxCtrl* mCheckParcelEnableVoice;
+ LLCheckBoxCtrl* mCheckEstateDisabledVoice;
+ LLCheckBoxCtrl* mCheckParcelVoiceLocal;
+ LLLineEditor* mMusicURLEdit;
+ LLCheckBoxCtrl* mMusicUrlCheck;
+
+ LLSafeHandle<LLParcelSelection>& mParcel;
+};
+
+#endif
diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp
new file mode 100644
index 0000000000..9654e17659
--- /dev/null
+++ b/indra/newview/llpanellandmarkinfo.cpp
@@ -0,0 +1,464 @@
+/**
+ * @file llpanellandmarkinfo.cpp
+ * @brief Displays landmark info in Side Tray.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanellandmarkinfo.h"
+
+#include "llcombobox.h"
+#include "lliconctrl.h"
+#include "lllineeditor.h"
+#include "lltextbox.h"
+#include "lltexteditor.h"
+#include "lltrans.h"
+
+#include "llagent.h"
+#include "llagentui.h"
+#include "lllandmarkactions.h"
+#include "llviewerinventory.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+
+//----------------------------------------------------------------------------
+// Aux types and methods
+//----------------------------------------------------------------------------
+
+typedef std::pair<LLUUID, std::string> folder_pair_t;
+
+static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right);
+static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats);
+
+static LLRegisterPanelClassWrapper<LLPanelLandmarkInfo> t_landmark_info("panel_landmark_info");
+
+// Statics for textures filenames
+static std::string icon_pg;
+static std::string icon_m;
+static std::string icon_r;
+
+LLPanelLandmarkInfo::LLPanelLandmarkInfo()
+: LLPanelPlaceInfo()
+{}
+
+// virtual
+LLPanelLandmarkInfo::~LLPanelLandmarkInfo()
+{}
+
+// virtual
+BOOL LLPanelLandmarkInfo::postBuild()
+{
+ LLPanelPlaceInfo::postBuild();
+
+ mOwner = getChild<LLTextBox>("owner");
+ mCreator = getChild<LLTextBox>("creator");
+ mCreated = getChild<LLTextBox>("created");
+
+ mLandmarkTitle = getChild<LLTextBox>("title_value");
+ mLandmarkTitleEditor = getChild<LLLineEditor>("title_editor");
+ mNotesEditor = getChild<LLTextEditor>("notes_editor");
+ mFolderCombo = getChild<LLComboBox>("folder_combo");
+
+ icon_pg = getString("icon_PG");
+ icon_m = getString("icon_M");
+ icon_r = getString("icon_R");
+
+ return TRUE;
+}
+
+// virtual
+void LLPanelLandmarkInfo::resetLocation()
+{
+ LLPanelPlaceInfo::resetLocation();
+
+ std::string not_available = getString("not_available");
+ mCreator->setText(not_available);
+ mOwner->setText(not_available);
+ mCreated->setText(not_available);
+ mLandmarkTitle->setText(LLStringUtil::null);
+ mLandmarkTitleEditor->setText(LLStringUtil::null);
+ mNotesEditor->setText(LLStringUtil::null);
+}
+
+// virtual
+void LLPanelLandmarkInfo::setInfoType(INFO_TYPE type)
+{
+ LLPanel* landmark_info_panel = getChild<LLPanel>("landmark_info_panel");
+
+ bool is_info_type_create_landmark = type == CREATE_LANDMARK;
+
+ landmark_info_panel->setVisible(type == LANDMARK);
+
+ getChild<LLTextBox>("folder_label")->setVisible(is_info_type_create_landmark);
+ mFolderCombo->setVisible(is_info_type_create_landmark);
+
+ switch(type)
+ {
+ case CREATE_LANDMARK:
+ mCurrentTitle = getString("title_create_landmark");
+
+ mLandmarkTitle->setVisible(FALSE);
+ mLandmarkTitleEditor->setVisible(TRUE);
+ mNotesEditor->setEnabled(TRUE);
+ break;
+
+ case LANDMARK:
+ default:
+ mCurrentTitle = getString("title_landmark");
+
+ mLandmarkTitle->setVisible(TRUE);
+ mLandmarkTitleEditor->setVisible(FALSE);
+ mNotesEditor->setEnabled(FALSE);
+ break;
+ }
+
+ populateFoldersList();
+
+ LLPanelPlaceInfo::setInfoType(type);
+}
+
+// virtual
+void LLPanelLandmarkInfo::processParcelInfo(const LLParcelData& parcel_data)
+{
+ LLPanelPlaceInfo::processParcelInfo(parcel_data);
+
+ // HACK: Flag 0x2 == adult region,
+ // Flag 0x1 == mature region, otherwise assume PG
+ if (parcel_data.flags & 0x2)
+ {
+ mMaturityRatingIcon->setValue(icon_r);
+ mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_ADULT));
+ }
+ else if (parcel_data.flags & 0x1)
+ {
+ mMaturityRatingIcon->setValue(icon_m);
+ mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_MATURE));
+ }
+ else
+ {
+ mMaturityRatingIcon->setValue(icon_pg);
+ mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_PG));
+ }
+
+ S32 region_x;
+ S32 region_y;
+ S32 region_z;
+
+ // If the region position is zero, grab position from the global
+ if(mPosRegion.isExactlyZero())
+ {
+ region_x = llround(parcel_data.global_x) % REGION_WIDTH_UNITS;
+ region_y = llround(parcel_data.global_y) % REGION_WIDTH_UNITS;
+ region_z = llround(parcel_data.global_z);
+ }
+ else
+ {
+ region_x = llround(mPosRegion.mV[VX]);
+ region_y = llround(mPosRegion.mV[VY]);
+ region_z = llround(mPosRegion.mV[VZ]);
+ }
+
+ LLSD info;
+ info["update_verbs"] = true;
+ info["global_x"] = parcel_data.global_x;
+ info["global_y"] = parcel_data.global_y;
+ info["global_z"] = parcel_data.global_z;
+ notifyParent(info);
+
+ if (mInfoType == CREATE_LANDMARK)
+ {
+ if (parcel_data.name.empty())
+ {
+ mLandmarkTitleEditor->setText(llformat("%s (%d, %d, %d)",
+ parcel_data.sim_name.c_str(), region_x, region_y, region_z));
+ }
+ else
+ {
+ mLandmarkTitleEditor->setText(parcel_data.name);
+ }
+
+ std::string desc;
+ LLAgentUI::buildLocationString(desc, LLAgentUI::LOCATION_FORMAT_FULL, gAgent.getPositionAgent());
+ mNotesEditor->setText(desc);
+
+ if (!LLLandmarkActions::landmarkAlreadyExists())
+ {
+ createLandmark(mFolderCombo->getValue().asUUID());
+ }
+ }
+}
+
+void LLPanelLandmarkInfo::displayItemInfo(const LLInventoryItem* pItem)
+{
+ if (!pItem)
+ return;
+
+ if(!gCacheName)
+ return;
+
+ const LLPermissions& perm = pItem->getPermissions();
+
+ //////////////////
+ // CREATOR NAME //
+ //////////////////
+ if (pItem->getCreatorUUID().notNull())
+ {
+ std::string name;
+ LLUUID creator_id = pItem->getCreatorUUID();
+ if (!gCacheName->getFullName(creator_id, name))
+ {
+ gCacheName->get(creator_id, FALSE,
+ boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mCreator, _2, _3));
+ }
+ mCreator->setText(name);
+ }
+ else
+ {
+ mCreator->setText(getString("unknown"));
+ }
+
+ ////////////////
+ // OWNER NAME //
+ ////////////////
+ if(perm.isOwned())
+ {
+ std::string name;
+ if (perm.isGroupOwned())
+ {
+ LLUUID group_id = perm.getGroup();
+ if (!gCacheName->getGroupName(group_id, name))
+ {
+ gCacheName->get(group_id, TRUE,
+ boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mOwner, _2, _3));
+ }
+ }
+ else
+ {
+ LLUUID owner_id = perm.getOwner();
+ if (!gCacheName->getFullName(owner_id, name))
+ {
+ gCacheName->get(owner_id, FALSE,
+ boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mOwner, _2, _3));
+ }
+ }
+ mOwner->setText(name);
+ }
+ else
+ {
+ mOwner->setText(getString("public"));
+ }
+
+ //////////////////
+ // ACQUIRE DATE //
+ //////////////////
+ time_t time_utc = pItem->getCreationDate();
+ if (0 == time_utc)
+ {
+ mCreated->setText(getString("unknown"));
+ }
+ else
+ {
+ std::string timeStr = getString("acquired_date");
+ LLSD substitution;
+ substitution["datetime"] = (S32) time_utc;
+ LLStringUtil::format (timeStr, substitution);
+ mCreated->setText(timeStr);
+ }
+
+ mLandmarkTitle->setText(pItem->getName());
+ mLandmarkTitleEditor->setText(pItem->getName());
+ mNotesEditor->setText(pItem->getDescription());
+}
+
+void LLPanelLandmarkInfo::toggleLandmarkEditMode(BOOL enabled)
+{
+ // If switching to edit mode while creating landmark
+ // the "Create Landmark" title remains.
+ if (enabled && mInfoType != CREATE_LANDMARK)
+ {
+ mTitle->setText(getString("title_edit_landmark"));
+ }
+ else
+ {
+ mTitle->setText(mCurrentTitle);
+
+ mLandmarkTitle->setText(mLandmarkTitleEditor->getText());
+ }
+
+ if (mNotesEditor->getReadOnly() == (enabled == TRUE))
+ {
+ mLandmarkTitle->setVisible(!enabled);
+ mLandmarkTitleEditor->setVisible(enabled);
+ mNotesEditor->setReadOnly(!enabled);
+ mFolderCombo->setVisible(enabled);
+ getChild<LLTextBox>("folder_label")->setVisible(enabled);
+
+ // HACK: To change the text color in a text editor
+ // when it was enabled/disabled we set the text once again.
+ mNotesEditor->setText(mNotesEditor->getText());
+ }
+}
+
+const std::string& LLPanelLandmarkInfo::getLandmarkTitle() const
+{
+ return mLandmarkTitleEditor->getText();
+}
+
+const std::string LLPanelLandmarkInfo::getLandmarkNotes() const
+{
+ return mNotesEditor->getText();
+}
+
+const LLUUID LLPanelLandmarkInfo::getLandmarkFolder() const
+{
+ return mFolderCombo->getValue().asUUID();
+}
+
+BOOL LLPanelLandmarkInfo::setLandmarkFolder(const LLUUID& id)
+{
+ return mFolderCombo->setCurrentByID(id);
+}
+
+void LLPanelLandmarkInfo::createLandmark(const LLUUID& folder_id)
+{
+ std::string name = mLandmarkTitleEditor->getText();
+ std::string desc = mNotesEditor->getText();
+
+ LLStringUtil::trim(name);
+ LLStringUtil::trim(desc);
+
+ // If typed name is empty use the parcel name instead.
+ if (name.empty())
+ {
+ name = mParcelName->getText();
+
+ // If no parcel exists use the region name instead.
+ if (name.empty())
+ {
+ name = mRegionName->getText();
+ }
+ }
+
+ LLStringUtil::replaceChar(desc, '\n', ' ');
+ LLViewerInventoryItem::insertDefaultSortField(name);
+
+ // If no folder chosen use the "Landmarks" folder.
+ LLLandmarkActions::createLandmarkHere(name, desc,
+ folder_id.notNull() ? folder_id : gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK));
+}
+
+// static
+std::string LLPanelLandmarkInfo::getFullFolderName(const LLViewerInventoryCategory* cat)
+{
+ std::string name = cat->getName();
+ LLUUID parent_id;
+
+ // translate category name, if it's right below the root
+ // FIXME: it can throw notification about non existent string in strings.xml
+ if (cat->getParentUUID().notNull() && cat->getParentUUID() == gInventory.getRootFolderID())
+ {
+ LLTrans::findString(name, "InvFolder " + name);
+ }
+
+ // we don't want "My Inventory" to appear in the name
+ while ((parent_id = cat->getParentUUID()).notNull() && parent_id != gInventory.getRootFolderID())
+ {
+ cat = gInventory.getCategory(parent_id);
+ name = cat->getName() + "/" + name;
+ }
+
+ return name;
+}
+
+void LLPanelLandmarkInfo::populateFoldersList()
+{
+ // Collect all folders that can contain landmarks.
+ LLInventoryModel::cat_array_t cats;
+ collectLandmarkFolders(cats);
+
+ mFolderCombo->removeall();
+
+ // Put the "Landmarks" folder first in list.
+ LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
+ const LLViewerInventoryCategory* cat = gInventory.getCategory(landmarks_id);
+ if (!cat)
+ {
+ llwarns << "Cannot find the landmarks folder" << llendl;
+ }
+ std::string cat_full_name = getFullFolderName(cat);
+ mFolderCombo->add(cat_full_name, cat->getUUID());
+
+ typedef std::vector<folder_pair_t> folder_vec_t;
+ folder_vec_t folders;
+ // Sort the folders by their full name.
+ for (S32 i = 0; i < cats.count(); i++)
+ {
+ cat = cats.get(i);
+ cat_full_name = getFullFolderName(cat);
+ folders.push_back(folder_pair_t(cat->getUUID(), cat_full_name));
+ }
+ sort(folders.begin(), folders.end(), cmp_folders);
+
+ // Finally, populate the combobox.
+ for (folder_vec_t::const_iterator it = folders.begin(); it != folders.end(); it++)
+ mFolderCombo->add(it->second, LLSD(it->first));
+}
+
+static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right)
+{
+ return left.second < right.second;
+}
+
+static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats)
+{
+ LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
+
+ // Add descendent folders of the "Landmarks" category.
+ LLInventoryModel::item_array_t items; // unused
+ LLIsType is_category(LLAssetType::AT_CATEGORY);
+ gInventory.collectDescendentsIf(
+ landmarks_id,
+ cats,
+ items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_category);
+
+ // Add the "My Favorites" category.
+ LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+ LLViewerInventoryCategory* favorites_cat = gInventory.getCategory(favorites_id);
+ if (!favorites_cat)
+ {
+ llwarns << "Cannot find the favorites folder" << llendl;
+ }
+ else
+ {
+ cats.put(favorites_cat);
+ }
+}
diff --git a/indra/newview/llpanellandmarkinfo.h b/indra/newview/llpanellandmarkinfo.h
new file mode 100644
index 0000000000..2a9949ae41
--- /dev/null
+++ b/indra/newview/llpanellandmarkinfo.h
@@ -0,0 +1,86 @@
+/**
+ * @file llpanellandmarkinfo.h
+ * @brief Displays landmark info in Side Tray.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELLANDMARKINFO_H
+#define LL_LLPANELLANDMARKINFO_H
+
+#include "llpanelplaceinfo.h"
+
+class LLComboBox;
+class LLLineEditor;
+class LLTextEditor;
+
+class LLPanelLandmarkInfo : public LLPanelPlaceInfo
+{
+public:
+ LLPanelLandmarkInfo();
+ /*virtual*/ ~LLPanelLandmarkInfo();
+
+ /*virtual*/ BOOL postBuild();
+
+ /*virtual*/ void resetLocation();
+
+ /*virtual*/ void setInfoType(INFO_TYPE type);
+
+ /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
+
+ // Displays landmark owner, creator and creation date info.
+ void displayItemInfo(const LLInventoryItem* pItem);
+
+ void toggleLandmarkEditMode(BOOL enabled);
+
+ const std::string& getLandmarkTitle() const;
+ const std::string getLandmarkNotes() const;
+ const LLUUID getLandmarkFolder() const;
+
+ // Select current landmark folder in combobox.
+ BOOL setLandmarkFolder(const LLUUID& id);
+
+ // Create a landmark for the current location
+ // in a folder specified by folder_id.
+ void createLandmark(const LLUUID& folder_id);
+
+ static std::string getFullFolderName(const LLViewerInventoryCategory* cat);
+
+private:
+ void populateFoldersList();
+
+ LLTextBox* mOwner;
+ LLTextBox* mCreator;
+ LLTextBox* mCreated;
+ LLTextBox* mLandmarkTitle;
+ LLLineEditor* mLandmarkTitleEditor;
+ LLTextEditor* mNotesEditor;
+ LLComboBox* mFolderCombo;
+};
+
+#endif // LL_LLPANELLANDMARKINFO_H
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
new file mode 100644
index 0000000000..47feef496a
--- /dev/null
+++ b/indra/newview/llpanellandmarks.cpp
@@ -0,0 +1,1142 @@
+/**
+ * @file llpanellandmarks.cpp
+ * @brief Landmarks tab for Side Bar "Places" panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanellandmarks.h"
+
+#include "llbutton.h"
+#include "llfloaterreg.h"
+#include "llnotificationsutil.h"
+#include "llsdutil.h"
+#include "llsdutil_math.h"
+#include "llregionhandle.h"
+
+#include "llaccordionctrl.h"
+#include "llaccordionctrltab.h"
+#include "llagent.h"
+#include "llagentpicksinfo.h"
+#include "llagentui.h"
+#include "llcallbacklist.h"
+#include "lldndbutton.h"
+#include "llfloaterworldmap.h"
+#include "llfolderviewitem.h"
+#include "llinventorypanel.h"
+#include "lllandmarkactions.h"
+#include "llplacesinventorybridge.h"
+#include "llplacesinventorypanel.h"
+#include "llsidetray.h"
+#include "llviewermenu.h"
+#include "llviewerregion.h"
+
+// Not yet implemented; need to remove buildPanel() from constructor when we switch
+//static LLRegisterPanelClassWrapper<LLLandmarksPanel> t_landmarks("panel_landmarks");
+
+static const std::string OPTIONS_BUTTON_NAME = "options_gear_btn";
+static const std::string ADD_BUTTON_NAME = "add_btn";
+static const std::string ADD_FOLDER_BUTTON_NAME = "add_folder_btn";
+static const std::string TRASH_BUTTON_NAME = "trash_btn";
+
+
+// helper functions
+static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string);
+static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list);
+
+/**
+ * Functor counting expanded and collapsed folders in folder view tree to know
+ * when to enable or disable "Expand all folders" and "Collapse all folders" commands.
+ */
+class LLCheckFolderState : public LLFolderViewFunctor
+{
+public:
+ LLCheckFolderState()
+ : mCollapsedFolders(0),
+ mExpandedFolders(0)
+ {}
+ virtual ~LLCheckFolderState() {}
+ virtual void doFolder(LLFolderViewFolder* folder);
+ virtual void doItem(LLFolderViewItem* item) {}
+ S32 getCollapsedFolders() { return mCollapsedFolders; }
+ S32 getExpandedFolders() { return mExpandedFolders; }
+
+private:
+ S32 mCollapsedFolders;
+ S32 mExpandedFolders;
+};
+
+// virtual
+void LLCheckFolderState::doFolder(LLFolderViewFolder* folder)
+{
+ // Counting only folders that pass the filter.
+ // The listener check allow us to avoid counting the folder view
+ // object itself because it has no listener assigned.
+ if (folder->hasFilteredDescendants() && folder->getListener())
+ {
+ if (folder->isOpen())
+ {
+ ++mExpandedFolders;
+ }
+ else
+ {
+ ++mCollapsedFolders;
+ }
+ }
+}
+
+/**
+ * Bridge to support knowing when the inventory has changed to update Landmarks tab
+ * ShowFolderState filter setting to show all folders when the filter string is empty and
+ * empty folder message when Landmarks inventory category has no children.
+ */
+class LLLandmarksPanelObserver : public LLInventoryObserver
+{
+public:
+ LLLandmarksPanelObserver(LLLandmarksPanel* lp) : mLP(lp) {}
+ virtual ~LLLandmarksPanelObserver() {}
+ /*virtual*/ void changed(U32 mask);
+
+private:
+ LLLandmarksPanel* mLP;
+};
+
+void LLLandmarksPanelObserver::changed(U32 mask)
+{
+ mLP->updateShowFolderState();
+}
+
+LLLandmarksPanel::LLLandmarksPanel()
+ : LLPanelPlacesTab()
+ , mFavoritesInventoryPanel(NULL)
+ , mLandmarksInventoryPanel(NULL)
+ , mMyInventoryPanel(NULL)
+ , mLibraryInventoryPanel(NULL)
+ , mCurrentSelectedList(NULL)
+ , mListCommands(NULL)
+ , mGearFolderMenu(NULL)
+ , mGearLandmarkMenu(NULL)
+{
+ mInventoryObserver = new LLLandmarksPanelObserver(this);
+ gInventory.addObserver(mInventoryObserver);
+
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_landmarks.xml");
+}
+
+LLLandmarksPanel::~LLLandmarksPanel()
+{
+ if (gInventory.containsObserver(mInventoryObserver))
+ {
+ gInventory.removeObserver(mInventoryObserver);
+ }
+}
+
+BOOL LLLandmarksPanel::postBuild()
+{
+ if (!gInventory.isInventoryUsable())
+ return FALSE;
+
+ // mast be called before any other initXXX methods to init Gear menu
+ initListCommandsHandlers();
+
+ U32 sort_order = gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER);
+ mSortByDate = sort_order & LLInventoryFilter::SO_DATE;
+ initFavoritesInventoryPanel();
+ initLandmarksInventoryPanel();
+ initMyInventoryPanel();
+ initLibraryInventoryPanel();
+ getChild<LLAccordionCtrlTab>("tab_favorites")->setDisplayChildren(true);
+ getChild<LLAccordionCtrlTab>("tab_landmarks")->setDisplayChildren(true);
+
+ return TRUE;
+}
+
+// virtual
+void LLLandmarksPanel::onSearchEdit(const std::string& string)
+{
+ // give FolderView a chance to be refreshed. So, made all accordions visible
+ for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
+ {
+ LLAccordionCtrlTab* tab = *iter;
+ tab->setVisible(TRUE);
+
+ // expand accordion to see matched items in each one. See EXT-2014.
+ if (string != "")
+ {
+ tab->changeOpenClose(false);
+ }
+
+ LLPlacesInventoryPanel* inventory_list = dynamic_cast<LLPlacesInventoryPanel*>(tab->getAccordionView());
+ if (NULL == inventory_list) continue;
+
+ if (inventory_list->getFilter())
+ {
+ filter_list(inventory_list, string);
+ }
+ }
+
+ if (sFilterSubString != string)
+ sFilterSubString = string;
+
+ // show all folders in Landmarks Accordion for empty filter
+ // only if Landmarks inventory folder is not empty
+ updateShowFolderState();
+}
+
+// virtual
+void LLLandmarksPanel::onShowOnMap()
+{
+ if (NULL == mCurrentSelectedList)
+ {
+ llwarns << "There are no selected list. No actions are performed." << llendl;
+ return;
+ }
+
+ // Disable the "Map" button because loading landmark can take some time.
+ // During this time the button is useless. It will be enabled on callback finish
+ // or upon switching to other item.
+ mShowOnMapBtn->setEnabled(FALSE);
+
+ doActionOnCurSelectedLandmark(boost::bind(&LLLandmarksPanel::doShowOnMap, this, _1));
+}
+
+// virtual
+void LLLandmarksPanel::onTeleport()
+{
+ LLFolderViewItem* current_item = getCurSelectedItem();
+ if (!current_item)
+ {
+ llwarns << "There are no selected list. No actions are performed." << llendl;
+ return;
+ }
+
+ LLFolderViewEventListener* listenerp = current_item->getListener();
+ if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
+ {
+ listenerp->openItem();
+ }
+}
+
+// virtual
+void LLLandmarksPanel::updateVerbs()
+{
+ if (!isTabVisible())
+ return;
+
+ bool landmark_selected = isLandmarkSelected();
+ mTeleportBtn->setEnabled(landmark_selected && isActionEnabled("teleport"));
+ mShowOnMapBtn->setEnabled(landmark_selected && isActionEnabled("show_on_map"));
+
+ // TODO: mantipov: Uncomment when mShareBtn is supported
+ // Share button should be enabled when neither a folder nor a landmark is selected
+ //mShareBtn->setEnabled(NULL != current_item);
+
+ updateListCommands();
+}
+
+void LLLandmarksPanel::onSelectionChange(LLPlacesInventoryPanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action)
+{
+ if (user_action && (items.size() > 0))
+ {
+ deselectOtherThan(inventory_list);
+ mCurrentSelectedList = inventory_list;
+ }
+ updateVerbs();
+}
+
+void LLLandmarksPanel::onSelectorButtonClicked()
+{
+ // TODO: mantipov: update getting of selected item
+ // TODO: bind to "i" button
+ LLFolderViewItem* cur_item = mFavoritesInventoryPanel->getRootFolder()->getCurSelectedItem();
+ if (!cur_item) return;
+
+ LLFolderViewEventListener* listenerp = cur_item->getListener();
+ if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
+ {
+ LLSD key;
+ key["type"] = "landmark";
+ key["id"] = listenerp->getUUID();
+
+ LLSideTray::getInstance()->showPanel("panel_places", key);
+ }
+}
+
+void LLLandmarksPanel::updateShowFolderState()
+{
+ if (!mLandmarksInventoryPanel->getFilter())
+ return;
+
+ bool show_all_folders = mLandmarksInventoryPanel->getRootFolder()->getFilterSubString().empty();
+ if (show_all_folders)
+ {
+ show_all_folders = category_has_descendents(mLandmarksInventoryPanel);
+ }
+
+ mLandmarksInventoryPanel->setShowFolderState(show_all_folders ?
+ LLInventoryFilter::SHOW_ALL_FOLDERS :
+ LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS
+ );
+}
+
+void LLLandmarksPanel::setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_focus)
+{
+ if (selectItemInAccordionTab(mFavoritesInventoryPanel, "tab_favorites", obj_id, take_keyboard_focus))
+ {
+ return;
+ }
+
+ if (selectItemInAccordionTab(mLandmarksInventoryPanel, "tab_landmarks", obj_id, take_keyboard_focus))
+ {
+ return;
+ }
+
+ if (selectItemInAccordionTab(mMyInventoryPanel, "tab_inventory", obj_id, take_keyboard_focus))
+ {
+ return;
+ }
+
+ if (selectItemInAccordionTab(mLibraryInventoryPanel, "tab_library", obj_id, take_keyboard_focus))
+ {
+ return;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// PROTECTED METHODS
+//////////////////////////////////////////////////////////////////////////
+
+bool LLLandmarksPanel::isLandmarkSelected() const
+{
+ LLFolderViewItem* current_item = getCurSelectedItem();
+ if(current_item && current_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+bool LLLandmarksPanel::isReceivedFolderSelected() const
+{
+ // Received Folder can be only in Landmarks accordion
+ if (mCurrentSelectedList != mLandmarksInventoryPanel) return false;
+
+ // *TODO: it should be filled with logic when EXT-976 is done.
+
+ llwarns << "Not implemented yet until EXT-976 is done." << llendl;
+
+ return false;
+}
+
+void LLLandmarksPanel::doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb)
+{
+ LLFolderViewItem* cur_item = getCurSelectedItem();
+ if(cur_item && cur_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
+ {
+ LLLandmark* landmark = LLLandmarkActions::getLandmark(cur_item->getListener()->getUUID(), cb);
+ if (landmark)
+ {
+ cb(landmark);
+ }
+ }
+}
+
+LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem() const
+{
+ return mCurrentSelectedList ? mCurrentSelectedList->getRootFolder()->getCurSelectedItem() : NULL;
+}
+
+LLFolderViewItem* LLLandmarksPanel::selectItemInAccordionTab(LLPlacesInventoryPanel* inventory_list,
+ const std::string& tab_name,
+ const LLUUID& obj_id,
+ BOOL take_keyboard_focus) const
+{
+ if (!inventory_list)
+ return NULL;
+
+ LLFolderView* folder_view = inventory_list->getRootFolder();
+
+ LLFolderViewItem* item = folder_view->getItemByID(obj_id);
+ if (!item)
+ return NULL;
+
+ LLAccordionCtrlTab* tab = getChild<LLAccordionCtrlTab>(tab_name);
+ if (!tab->isExpanded())
+ {
+ tab->changeOpenClose(false);
+ }
+
+ folder_view->setSelection(item, FALSE, take_keyboard_focus);
+
+ LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("landmarks_accordion");
+ LLRect screen_rc;
+ localRectToScreen(item->getRect(), &screen_rc);
+ accordion->notifyParent(LLSD().with("scrollToShowRect", screen_rc.getValue()));
+
+ return item;
+}
+
+void LLLandmarksPanel::updateSortOrder(LLInventoryPanel* panel, bool byDate)
+{
+ if(!panel) return;
+
+ U32 order = panel->getSortOrder();
+ if (byDate)
+ {
+ panel->setSortOrder( order | LLInventoryFilter::SO_DATE );
+ }
+ else
+ {
+ panel->setSortOrder( order & ~LLInventoryFilter::SO_DATE );
+ }
+}
+
+// virtual
+void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data)
+{
+ //this function will be called after user will try to create a pick for selected landmark.
+ // We have to make request to sever to get parcel_id and snaption_id.
+ if(isLandmarkSelected())
+ {
+ LLFolderViewItem* cur_item = getCurSelectedItem();
+ if (!cur_item) return;
+ LLUUID id = cur_item->getListener()->getUUID();
+ LLInventoryItem* inv_item = mCurrentSelectedList->getModel()->getItem(id);
+ doActionOnCurSelectedLandmark(boost::bind(
+ &LLLandmarksPanel::doProcessParcelInfo, this, _1, cur_item, inv_item, parcel_data));
+ }
+}
+
+// virtual
+void LLLandmarksPanel::setParcelID(const LLUUID& parcel_id)
+{
+ if (!parcel_id.isNull())
+ {
+ LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this);
+ LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id);
+ }
+}
+
+// virtual
+void LLLandmarksPanel::setErrorStatus(U32 status, const std::string& reason)
+{
+ llerrs<< "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// PRIVATE METHODS
+//////////////////////////////////////////////////////////////////////////
+
+void LLLandmarksPanel::initFavoritesInventoryPanel()
+{
+ mFavoritesInventoryPanel = getChild<LLPlacesInventoryPanel>("favorites_list");
+
+ initLandmarksPanel(mFavoritesInventoryPanel);
+ mFavoritesInventoryPanel->getFilter()->setEmptyLookupMessage("FavoritesNoMatchingItems");
+
+ initAccordion("tab_favorites", mFavoritesInventoryPanel);
+}
+
+void LLLandmarksPanel::initLandmarksInventoryPanel()
+{
+ mLandmarksInventoryPanel = getChild<LLPlacesInventoryPanel>("landmarks_list");
+
+ initLandmarksPanel(mLandmarksInventoryPanel);
+
+ // Check if mLandmarksInventoryPanel is properly initialized and has a Filter created.
+ // In case of a dummy widget getFilter() will return NULL.
+ if (mLandmarksInventoryPanel->getFilter())
+ {
+ mLandmarksInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS);
+ }
+
+ // subscribe to have auto-rename functionality while creating New Folder
+ mLandmarksInventoryPanel->setSelectCallback(boost::bind(&LLInventoryPanel::onSelectionChange, mLandmarksInventoryPanel, _1, _2));
+
+ initAccordion("tab_landmarks", mLandmarksInventoryPanel);
+}
+
+void LLLandmarksPanel::initMyInventoryPanel()
+{
+ mMyInventoryPanel= getChild<LLPlacesInventoryPanel>("my_inventory_list");
+
+ initLandmarksPanel(mMyInventoryPanel);
+
+ initAccordion("tab_inventory", mMyInventoryPanel);
+}
+
+void LLLandmarksPanel::initLibraryInventoryPanel()
+{
+ mLibraryInventoryPanel = getChild<LLPlacesInventoryPanel>("library_list");
+
+ initLandmarksPanel(mLibraryInventoryPanel);
+
+ initAccordion("tab_library", mLibraryInventoryPanel);
+}
+
+void LLLandmarksPanel::initLandmarksPanel(LLPlacesInventoryPanel* inventory_list)
+{
+ // In case of a dummy widget further we have no Folder View widget and no Filter,
+ // so further initialization leads to crash.
+ if (!inventory_list->getFilter())
+ return;
+
+ inventory_list->setFilterTypes(0x1 << LLInventoryType::IT_LANDMARK);
+ inventory_list->setSelectCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, inventory_list, _1, _2));
+
+ inventory_list->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
+ updateSortOrder(inventory_list, mSortByDate);
+
+ LLPlacesFolderView* root_folder = dynamic_cast<LLPlacesFolderView*>(inventory_list->getRootFolder());
+ if (root_folder)
+ {
+ root_folder->setupMenuHandle(LLInventoryType::IT_CATEGORY, mGearFolderMenu->getHandle());
+ root_folder->setupMenuHandle(LLInventoryType::IT_LANDMARK, mGearLandmarkMenu->getHandle());
+ }
+
+ root_folder->setParentLandmarksPanel(this);
+ inventory_list->saveFolderState();
+}
+
+void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLPlacesInventoryPanel* inventory_list)
+{
+ LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>(accordion_tab_name);
+
+ mAccordionTabs.push_back(accordion_tab);
+ accordion_tab->setDropDownStateChangedCallback(
+ boost::bind(&LLLandmarksPanel::onAccordionExpandedCollapsed, this, _2, inventory_list));
+ accordion_tab->setDisplayChildren(false);
+}
+
+void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLPlacesInventoryPanel* inventory_list)
+{
+ bool expanded = param.asBoolean();
+
+ if(!expanded && (mCurrentSelectedList == inventory_list))
+ {
+ inventory_list->getRootFolder()->clearSelection();
+
+ mCurrentSelectedList = NULL;
+ updateVerbs();
+ }
+
+ // Start background fetch, mostly for My Inventory and Library
+ if (expanded)
+ {
+ const LLUUID &cat_id = inventory_list->getStartFolderID();
+ // Just because the category itself has been fetched, doesn't mean its child folders have.
+ /*
+ if (!gInventory.isCategoryComplete(cat_id))
+ */
+ {
+ gInventory.startBackgroundFetch(cat_id);
+ }
+
+ // Apply filter substring because it might have been changed
+ // while accordion was closed. See EXT-3714.
+ filter_list(inventory_list, sFilterSubString);
+ }
+}
+
+void LLLandmarksPanel::deselectOtherThan(const LLPlacesInventoryPanel* inventory_list)
+{
+ if (inventory_list != mFavoritesInventoryPanel)
+ {
+ mFavoritesInventoryPanel->getRootFolder()->clearSelection();
+ }
+
+ if (inventory_list != mLandmarksInventoryPanel)
+ {
+ mLandmarksInventoryPanel->getRootFolder()->clearSelection();
+ }
+ if (inventory_list != mMyInventoryPanel)
+ {
+ mMyInventoryPanel->getRootFolder()->clearSelection();
+ }
+ if (inventory_list != mLibraryInventoryPanel)
+ {
+ mLibraryInventoryPanel->getRootFolder()->clearSelection();
+ }
+}
+
+// List Commands Handlers
+void LLLandmarksPanel::initListCommandsHandlers()
+{
+ mListCommands = getChild<LLPanel>("bottom_panel");
+
+ mListCommands->childSetAction(OPTIONS_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onActionsButtonClick, this));
+ mListCommands->childSetAction(TRASH_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onTrashButtonClick, this));
+ mListCommands->getChild<LLButton>(ADD_BUTTON_NAME)->setHeldDownCallback(boost::bind(&LLLandmarksPanel::onAddButtonHeldDown, this));
+ static const LLSD add_landmark_command("add_landmark");
+ mListCommands->childSetAction(ADD_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onAddAction, this, add_landmark_command));
+
+ LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>(TRASH_BUTTON_NAME);
+ trash_btn->setDragAndDropHandler(boost::bind(&LLLandmarksPanel::handleDragAndDropToTrash, this
+ , _4 // BOOL drop
+ , _5 // EDragAndDropType cargo_type
+ , _7 // EAcceptance* accept
+ ));
+
+ mCommitCallbackRegistrar.add("Places.LandmarksGear.Add.Action", boost::bind(&LLLandmarksPanel::onAddAction, this, _2));
+ mCommitCallbackRegistrar.add("Places.LandmarksGear.CopyPaste.Action", boost::bind(&LLLandmarksPanel::onClipboardAction, this, _2));
+ mCommitCallbackRegistrar.add("Places.LandmarksGear.Custom.Action", boost::bind(&LLLandmarksPanel::onCustomAction, this, _2));
+ mCommitCallbackRegistrar.add("Places.LandmarksGear.Folding.Action", boost::bind(&LLLandmarksPanel::onFoldingAction, this, _2));
+ mEnableCallbackRegistrar.add("Places.LandmarksGear.Check", boost::bind(&LLLandmarksPanel::isActionChecked, this, _2));
+ mEnableCallbackRegistrar.add("Places.LandmarksGear.Enable", boost::bind(&LLLandmarksPanel::isActionEnabled, this, _2));
+ mGearLandmarkMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_landmark.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mGearFolderMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_folder.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_place_add_button.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+}
+
+
+void LLLandmarksPanel::updateListCommands()
+{
+ bool add_folder_enabled = isActionEnabled("category");
+ bool trash_enabled = isActionEnabled("delete");
+
+ // keep Options & Add Landmark buttons always enabled
+ mListCommands->childSetEnabled(ADD_FOLDER_BUTTON_NAME, add_folder_enabled);
+ mListCommands->childSetEnabled(TRASH_BUTTON_NAME, trash_enabled);
+ mListCommands->childSetEnabled(OPTIONS_BUTTON_NAME,getCurSelectedItem() != NULL);
+}
+
+void LLLandmarksPanel::onActionsButtonClick()
+{
+ LLFolderViewItem* cur_item = NULL;
+ if(mCurrentSelectedList)
+ cur_item = mCurrentSelectedList->getRootFolder()->getCurSelectedItem();
+
+ if(!cur_item)
+ return;
+
+ LLFolderViewEventListener* listenerp = cur_item->getListener();
+
+ LLMenuGL* menu =NULL;
+ if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
+ {
+ menu = mGearLandmarkMenu;
+ }
+ else if (listenerp->getInventoryType() == LLInventoryType::IT_CATEGORY)
+ {
+ mGearFolderMenu->getChild<LLMenuItemCallGL>("expand")->setVisible(!cur_item->isOpen());
+ mGearFolderMenu->getChild<LLMenuItemCallGL>("collapse")->setVisible(cur_item->isOpen());
+ menu = mGearFolderMenu;
+ }
+ showActionMenu(menu,OPTIONS_BUTTON_NAME);
+}
+
+void LLLandmarksPanel::onAddButtonHeldDown()
+{
+ showActionMenu(mMenuAdd,ADD_BUTTON_NAME);
+}
+
+void LLLandmarksPanel::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
+{
+ if (menu)
+ {
+ menu->buildDrawLabels();
+ menu->updateParent(LLMenuGL::sMenuContainer);
+ LLView* spawning_view = getChild<LLView> (spawning_view_name);
+ S32 menu_x, menu_y;
+ //show menu in co-ordinates of panel
+ spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this);
+ menu_y += menu->getRect().getHeight();
+ LLMenuGL::showPopup(this, menu, menu_x, menu_y);
+ }
+}
+
+void LLLandmarksPanel::onTrashButtonClick() const
+{
+ onClipboardAction("delete");
+}
+
+void LLLandmarksPanel::onAddAction(const LLSD& userdata) const
+{
+ std::string command_name = userdata.asString();
+ if("add_landmark" == command_name)
+ {
+ LLViewerInventoryItem* landmark = LLLandmarkActions::findLandmarkForAgentPos();
+ if(landmark)
+ {
+ LLNotificationsUtil::add("LandmarkAlreadyExists");
+ }
+ else
+ {
+ LLSideTray::getInstance()->showPanel("panel_places", LLSD().with("type", "create_landmark"));
+ }
+ }
+ else if ("category" == command_name)
+ {
+ LLFolderViewItem* item = getCurSelectedItem();
+ if (item && mCurrentSelectedList == mLandmarksInventoryPanel)
+ {
+ LLFolderViewEventListener* folder_bridge = NULL;
+ if (item-> getListener()->getInventoryType()
+ == LLInventoryType::IT_LANDMARK)
+ {
+ // for a landmark get parent folder bridge
+ folder_bridge = item->getParentFolder()->getListener();
+ }
+ else if (item-> getListener()->getInventoryType()
+ == LLInventoryType::IT_CATEGORY)
+ {
+ // for a folder get its own bridge
+ folder_bridge = item->getListener();
+ }
+
+ menu_create_inventory_item(mCurrentSelectedList->getRootFolder(),
+ dynamic_cast<LLFolderBridge*> (folder_bridge), LLSD(
+ "category"), gInventory.findCategoryUUIDForType(
+ LLFolderType::FT_LANDMARK));
+ }
+ }
+}
+
+void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const
+{
+ if(!mCurrentSelectedList)
+ return;
+ std::string command_name = userdata.asString();
+ if("copy_slurl" == command_name)
+ {
+ LLFolderViewItem* cur_item = getCurSelectedItem();
+ if(cur_item)
+ LLLandmarkActions::copySLURLtoClipboard(cur_item->getListener()->getUUID());
+ }
+ else if ( "paste" == command_name)
+ {
+ mCurrentSelectedList->getRootFolder()->paste();
+ }
+ else if ( "cut" == command_name)
+ {
+ mCurrentSelectedList->getRootFolder()->cut();
+ }
+ else
+ {
+ mCurrentSelectedList->getRootFolder()->doToSelected(mCurrentSelectedList->getModel(),command_name);
+ }
+}
+
+void LLLandmarksPanel::onFoldingAction(const LLSD& userdata)
+{
+ if(!mCurrentSelectedList) return;
+
+ LLFolderView* root_folder = mCurrentSelectedList->getRootFolder();
+ std::string command_name = userdata.asString();
+
+ if ("expand_all" == command_name)
+ {
+ root_folder->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN);
+ root_folder->arrangeAll();
+ }
+ else if ("collapse_all" == command_name)
+ {
+ root_folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN);
+
+ // The top level folder is invisible, it must be open to
+ // display its sub-folders.
+ root_folder->openTopLevelFolders();
+ root_folder->arrangeAll();
+ }
+ else if ( "sort_by_date" == command_name)
+ {
+ mSortByDate = !mSortByDate;
+ updateSortOrder(mLandmarksInventoryPanel, mSortByDate);
+ updateSortOrder(mMyInventoryPanel, mSortByDate);
+ updateSortOrder(mLibraryInventoryPanel, mSortByDate);
+ }
+ else
+ {
+ root_folder->doToSelected(&gInventory, userdata);
+ }
+}
+
+bool LLLandmarksPanel::isActionChecked(const LLSD& userdata) const
+{
+ const std::string command_name = userdata.asString();
+
+ if ( "sort_by_date" == command_name)
+ {
+ return mSortByDate;
+ }
+
+ return false;
+}
+
+bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
+{
+ std::string command_name = userdata.asString();
+
+
+ LLPlacesFolderView* rootFolderView = mCurrentSelectedList ?
+ static_cast<LLPlacesFolderView*>(mCurrentSelectedList->getRootFolder()) : NULL;
+
+ if (NULL == rootFolderView) return false;
+
+ // disable some commands for multi-selection. EXT-1757
+ if (rootFolderView->getSelectedCount() > 1)
+ {
+ if ( "teleport" == command_name
+ || "more_info" == command_name
+ || "rename" == command_name
+ || "show_on_map" == command_name
+ || "copy_slurl" == command_name
+ )
+ {
+ return false;
+ }
+
+ }
+
+ // disable some commands for Favorites accordion. EXT-1758
+ if (mCurrentSelectedList == mFavoritesInventoryPanel)
+ {
+ if ( "expand_all" == command_name
+ || "collapse_all" == command_name
+ || "sort_by_date" == command_name
+ )
+ return false;
+ }
+
+ LLCheckFolderState checker;
+ rootFolderView->applyFunctorRecursively(checker);
+
+ // We assume that the root folder is always expanded so we enable "collapse_all"
+ // command when we have at least one more expanded folder.
+ if (checker.getExpandedFolders() < 2 && "collapse_all" == command_name)
+ {
+ return false;
+ }
+
+ if (checker.getCollapsedFolders() < 1 && "expand_all" == command_name)
+ {
+ return false;
+ }
+
+ if("category" == command_name)
+ {
+ // we can add folder only in Landmarks Accordion
+ if (mCurrentSelectedList == mLandmarksInventoryPanel)
+ {
+ // ... but except Received folder
+ return !isReceivedFolderSelected();
+ }
+ else return false;
+ }
+ else if("paste" == command_name || "rename" == command_name || "cut" == command_name || "delete" == command_name)
+ {
+ return canSelectedBeModified(command_name);
+ }
+ else if("create_pick" == command_name)
+ {
+ std::set<LLUUID> selection;
+ if ( mCurrentSelectedList && mCurrentSelectedList->getRootFolder()->getSelectionList(selection) )
+ {
+ return ( 1 == selection.size() && !LLAgentPicksInfo::getInstance()->isPickLimitReached() );
+ }
+ return false;
+ }
+ else
+ {
+ llwarns << "Unprocessed command has come: " << command_name << llendl;
+ }
+
+ return true;
+}
+
+void LLLandmarksPanel::onCustomAction(const LLSD& userdata)
+{
+ LLFolderViewItem* cur_item = getCurSelectedItem();
+ if(!cur_item)
+ return;
+ std::string command_name = userdata.asString();
+ if("more_info" == command_name)
+ {
+ cur_item->getListener()->performAction(mCurrentSelectedList->getRootFolder(),mCurrentSelectedList->getModel(),"about");
+ }
+ else if ("teleport" == command_name)
+ {
+ onTeleport();
+ }
+ else if ("show_on_map" == command_name)
+ {
+ onShowOnMap();
+ }
+ else if ("create_pick" == command_name)
+ {
+ doActionOnCurSelectedLandmark(boost::bind(&LLLandmarksPanel::doCreatePick, this, _1));
+ }
+}
+
+/*
+Processes such actions: cut/rename/delete/paste actions
+
+Rules:
+ 1. We can't perform any action in Library
+ 2. For Landmarks we can:
+ - cut/rename/delete in any other accordions
+ - paste - only in Favorites, Landmarks accordions
+ 3. For Folders we can: perform any action in Landmarks accordion, except Received folder
+ 4. We can not paste folders from Clipboard (processed by LLFolderView::canPaste())
+ 5. Check LLFolderView/Inventory Bridges rules
+ */
+bool LLLandmarksPanel::canSelectedBeModified(const std::string& command_name) const
+{
+ // validate own rules first
+
+ // nothing can be modified in Library
+ if (mLibraryInventoryPanel == mCurrentSelectedList) return false;
+
+ bool can_be_modified = false;
+
+ // landmarks can be modified in any other accordion...
+ if (isLandmarkSelected())
+ {
+ can_be_modified = true;
+
+ // we can modify landmarks anywhere except paste to My Inventory
+ if ("paste" == command_name)
+ {
+ can_be_modified = (mCurrentSelectedList != mMyInventoryPanel);
+ }
+ }
+ else
+ {
+ // ...folders only in the Landmarks accordion...
+ can_be_modified = mLandmarksInventoryPanel == mCurrentSelectedList;
+
+ // ...except "Received" folder
+ can_be_modified &= !isReceivedFolderSelected();
+ }
+
+ // then ask LLFolderView permissions
+ if (can_be_modified)
+ {
+ LLFolderViewItem* selected = getCurSelectedItem();
+ if ("cut" == command_name)
+ {
+ can_be_modified = mCurrentSelectedList->getRootFolder()->canCut();
+ }
+ else if ("rename" == command_name)
+ {
+ can_be_modified = selected ? selected->getListener()->isItemRenameable() : false;
+ }
+ else if ("delete" == command_name)
+ {
+ can_be_modified = selected ? selected->getListener()->isItemRemovable(): false;
+ }
+ else if("paste" == command_name)
+ {
+ return mCurrentSelectedList->getRootFolder()->canPaste();
+ }
+ else
+ {
+ llwarns << "Unprocessed command has come: " << command_name << llendl;
+ }
+ }
+
+ 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, EAcceptance* accept)
+{
+ *accept = ACCEPT_NO;
+
+ switch (cargo_type)
+ {
+
+ case DAD_LANDMARK:
+ case DAD_CATEGORY:
+ {
+ bool is_enabled = isActionEnabled("delete");
+
+ if (is_enabled) *accept = ACCEPT_YES_MULTI;
+
+ if (is_enabled && drop)
+ {
+ onClipboardAction("delete");
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void LLLandmarksPanel::doShowOnMap(LLLandmark* landmark)
+{
+ LLVector3d landmark_global_pos;
+ if (!landmark->getGlobalPos(landmark_global_pos))
+ return;
+
+ LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
+ if (!landmark_global_pos.isExactlyZero() && worldmap_instance)
+ {
+ worldmap_instance->trackLocation(landmark_global_pos);
+ LLFloaterReg::showInstance("world_map", "center");
+ }
+
+ mShowOnMapBtn->setEnabled(TRUE);
+}
+
+void LLLandmarksPanel::doProcessParcelInfo(LLLandmark* landmark,
+ LLFolderViewItem* cur_item,
+ 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 = LLSideTray::getInstance()->getChild<LLPanel>("panel_places");//-> sidebar_places
+ 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 = cur_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));
+}
+
+void LLLandmarksPanel::doCreatePick(LLLandmark* landmark)
+{
+ LLViewerRegion* region = gAgent.getRegion();
+ if (!region) return;
+
+ LLGlobalVec pos_global;
+ LLUUID region_id;
+ landmark->getGlobalPos(pos_global);
+ landmark->getRegionID(region_id);
+ LLVector3 region_pos((F32)fmod(pos_global.mdV[VX], (F64)REGION_WIDTH_METERS),
+ (F32)fmod(pos_global.mdV[VY], (F64)REGION_WIDTH_METERS),
+ (F32)pos_global.mdV[VZ]);
+
+ LLSD body;
+ std::string url = region->getCapability("RemoteParcelRequest");
+ if (!url.empty())
+ {
+ body["location"] = ll_sd_from_vector3(region_pos);
+ if (!region_id.isNull())
+ {
+ body["region_id"] = region_id;
+ }
+ if (!pos_global.isExactlyZero())
+ {
+ U64 region_handle = to_region_handle(pos_global);
+ body["region_handle"] = ll_sd_from_U64(region_handle);
+ }
+ LLHTTPClient::post(url, body, new LLRemoteParcelRequestResponder(getObserverHandle()));
+ }
+ else
+ {
+ llwarns << "Can't create pick for landmark for region" << region_id
+ << ". Region: " << region->getName()
+ << " does not support RemoteParcelRequest" << llendl;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// HELPER FUNCTIONS
+//////////////////////////////////////////////////////////////////////////
+static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string)
+{
+ // When search is cleared, restore the old folder state.
+ if (!inventory_list->getRootFolder()->getFilterSubString().empty() && string == "")
+ {
+ inventory_list->setFilterSubString(LLStringUtil::null);
+ // Re-open folders that were open before
+ inventory_list->restoreFolderState();
+ }
+
+ // Open the immediate children of the root folder, since those
+ // are invisible in the UI and thus must always be open.
+ inventory_list->getRootFolder()->openTopLevelFolders();
+
+ if (inventory_list->getFilterSubString().empty() && string.empty())
+ {
+ // current filter and new filter empty, do nothing
+ return;
+ }
+
+ // save current folder open state if no filter currently applied
+ if (inventory_list->getRootFolder()->getFilterSubString().empty())
+ {
+ inventory_list->saveFolderState();
+ }
+
+ // Set new filter string
+ inventory_list->setFilterSubString(string);
+}
+
+static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list)
+{
+ LLViewerInventoryCategory* category = gInventory.getCategory(inventory_list->getStartFolderID());
+ if (category)
+ {
+ return category->getDescendentCount() > 0;
+ }
+
+ return false;
+}
+// EOF
diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h
new file mode 100644
index 0000000000..96b790844c
--- /dev/null
+++ b/indra/newview/llpanellandmarks.h
@@ -0,0 +1,173 @@
+/**
+ * @file llpanellandmarks.h
+ * @brief Landmarks tab for Side Bar "Places" panel
+ * class definition
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELLANDMARKS_H
+#define LL_LLPANELLANDMARKS_H
+
+#include "lllandmark.h"
+
+// newview
+#include "llinventorymodel.h"
+#include "lllandmarklist.h"
+#include "llpanelplacestab.h"
+#include "llpanelpick.h"
+#include "llremoteparcelrequest.h"
+
+class LLAccordionCtrlTab;
+class LLFolderViewItem;
+class LLMenuGL;
+class LLInventoryPanel;
+class LLPlacesInventoryPanel;
+
+class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver
+{
+public:
+ LLLandmarksPanel();
+ virtual ~LLLandmarksPanel();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onSearchEdit(const std::string& string);
+ /*virtual*/ void onShowOnMap();
+ /*virtual*/ void onTeleport();
+ /*virtual*/ void updateVerbs();
+
+ void onSelectionChange(LLPlacesInventoryPanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action);
+ void onSelectorButtonClicked();
+ void setCurrentSelectedList(LLPlacesInventoryPanel* inventory_list)
+ {
+ mCurrentSelectedList = inventory_list;
+ }
+
+ /**
+ * Update filter ShowFolderState setting to show empty folder message
+ * if Landmarks inventory folder is empty.
+ */
+ void updateShowFolderState();
+
+ /**
+ * Selects item with "obj_id" in one of accordion tabs.
+ */
+ void setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_focus);
+
+protected:
+ /**
+ * @return true - if current selected panel is not null and selected item is a landmark
+ */
+ bool isLandmarkSelected() const;
+ bool isReceivedFolderSelected() const;
+ void doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb);
+ LLFolderViewItem* getCurSelectedItem() const;
+
+ /**
+ * Selects item with "obj_id" in "inventory_list" and scrolls accordion
+ * scrollbar to show the item.
+ * Returns pointer to the item if it is found in "inventory_list", otherwise NULL.
+ */
+ LLFolderViewItem* selectItemInAccordionTab(LLPlacesInventoryPanel* inventory_list,
+ const std::string& tab_name,
+ const LLUUID& obj_id,
+ BOOL take_keyboard_focus) const;
+
+ void updateSortOrder(LLInventoryPanel* panel, bool byDate);
+
+ //LLRemoteParcelInfoObserver interface
+ /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
+ /*virtual*/ void setParcelID(const LLUUID& parcel_id);
+ /*virtual*/ void setErrorStatus(U32 status, const std::string& reason);
+
+private:
+ void initFavoritesInventoryPanel();
+ void initLandmarksInventoryPanel();
+ void initMyInventoryPanel();
+ void initLibraryInventoryPanel();
+ void initLandmarksPanel(LLPlacesInventoryPanel* inventory_list);
+ void initAccordion(const std::string& accordion_tab_name, LLPlacesInventoryPanel* inventory_list);
+ void onAccordionExpandedCollapsed(const LLSD& param, LLPlacesInventoryPanel* inventory_list);
+ void deselectOtherThan(const LLPlacesInventoryPanel* inventory_list);
+
+ // List Commands Handlers
+ void initListCommandsHandlers();
+ void updateListCommands();
+ void onActionsButtonClick();
+ void showActionMenu(LLMenuGL* menu, std::string spawning_view_name);
+ void onAddButtonHeldDown();
+ void onTrashButtonClick() const;
+ void onAddAction(const LLSD& command_name) const;
+ void onClipboardAction(const LLSD& command_name) const;
+ void onFoldingAction(const LLSD& command_name);
+ bool isActionChecked(const LLSD& userdata) const;
+ bool isActionEnabled(const LLSD& command_name) const;
+ void onCustomAction(const LLSD& command_name);
+
+ /**
+ * Determines if selected item can be modified via context/gear menu.
+ *
+ * It validates Places Landmarks rules first. And then LLFolderView permissions.
+ * For now it checks cut/rename/delete/paste actions.
+ */
+ bool canSelectedBeModified(const std::string& command_name) const;
+ void onPickPanelExit( LLPanelPickEdit* pick_panel, LLView* owner, const LLSD& params);
+
+ /**
+ * Processes drag-n-drop of the Landmarks and folders into trash button.
+ */
+ bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);
+
+ /**
+ * Landmark actions callbacks. Fire when a landmark is loaded from the list.
+ */
+ void doShowOnMap(LLLandmark* landmark);
+ void doProcessParcelInfo(LLLandmark* landmark,
+ LLFolderViewItem* cur_item,
+ LLInventoryItem* inv_item,
+ const LLParcelData& parcel_data);
+ void doCreatePick(LLLandmark* landmark);
+
+private:
+ LLPlacesInventoryPanel* mFavoritesInventoryPanel;
+ LLPlacesInventoryPanel* mLandmarksInventoryPanel;
+ LLPlacesInventoryPanel* mMyInventoryPanel;
+ LLPlacesInventoryPanel* mLibraryInventoryPanel;
+ LLMenuGL* mGearLandmarkMenu;
+ LLMenuGL* mGearFolderMenu;
+ LLMenuGL* mMenuAdd;
+ LLPlacesInventoryPanel* mCurrentSelectedList;
+ LLInventoryObserver* mInventoryObserver;
+
+ LLPanel* mListCommands;
+ bool mSortByDate;
+
+ typedef std::vector<LLAccordionCtrlTab*> accordion_tabs_t;
+ accordion_tabs_t mAccordionTabs;
+};
+
+#endif //LL_LLPANELLANDMARKS_H
diff --git a/indra/newview/llpanellandmedia.cpp b/indra/newview/llpanellandmedia.cpp
index b8886c9493..42ad9820a8 100644
--- a/indra/newview/llpanellandmedia.cpp
+++ b/indra/newview/llpanellandmedia.cpp
@@ -39,6 +39,8 @@
#include "llmimetypes.h"
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
+#include "llviewermedia.h"
+#include "llviewerparcelmedia.h"
#include "lluictrlfactory.h"
// library includes
@@ -54,21 +56,15 @@
#include "llsdutil.h"
#include "lltexturectrl.h"
#include "roles_constants.h"
+#include "llscrolllistctrl.h"
//---------------------------------------------------------------------------
// LLPanelLandMedia
//---------------------------------------------------------------------------
LLPanelLandMedia::LLPanelLandMedia(LLParcelSelectionHandle& parcel)
-: LLPanel(std::string("land_media_panel")),
-
+: LLPanel(),
mParcel(parcel),
- mCheckSoundLocal(NULL),
- mSoundHelpButton(NULL),
- mCheckEnableVoiceChat(NULL),
- mCheckEnableVoiceChatIsEstateDisabled(NULL),
- mCheckEnableVoiceChatParcel(NULL),
- mMusicURLEdit(NULL),
mMediaURLEdit(NULL),
mMediaDescEdit(NULL),
mMediaTypeCombo(NULL),
@@ -79,8 +75,7 @@ LLPanelLandMedia::LLPanelLandMedia(LLParcelSelectionHandle& parcel)
mMediaTextureCtrl(NULL),
mMediaAutoScaleCheck(NULL),
mMediaLoopCheck(NULL),
- mMediaUrlCheck(NULL),
- mMusicUrlCheck(NULL)
+ mMediaUrlCheck(NULL)
{
}
@@ -88,38 +83,13 @@ LLPanelLandMedia::LLPanelLandMedia(LLParcelSelectionHandle& parcel)
// virtual
LLPanelLandMedia::~LLPanelLandMedia()
{
- // close LLFloaterURLEntry?
}
-
-// static
-void LLPanelLandMedia::onClickSoundHelp(void*)
-{
- LLNotifications::instance().add("ClickSoundHelpLand");
-}
-
-
BOOL LLPanelLandMedia::postBuild()
{
- mCheckSoundLocal = getChild<LLCheckBoxCtrl>("check sound local");
- childSetCommitCallback("check sound local", onCommitAny, this);
-
- mSoundHelpButton = getChild<LLButton>("?");
- mSoundHelpButton->setClickedCallback(onClickSoundHelp, this);
-
- mCheckEnableVoiceChat = getChild<LLCheckBoxCtrl>("parcel_enable_voice_channel");
- childSetCommitCallback("parcel_enable_voice_channel", onCommitAny, this);
- mCheckEnableVoiceChatIsEstateDisabled = getChild<LLCheckBoxCtrl>("parcel_enable_voice_channel_is_estate_disabled");
- childSetCommitCallback("parcel_enable_voice_channel_is_estate_disabled", onCommitAny, this);
- mCheckEnableVoiceChatParcel = getChild<LLCheckBoxCtrl>("parcel_enable_voice_channel_parcel");
- childSetCommitCallback("parcel_enable_voice_channel_parcel", onCommitAny, this);
-
- mMusicURLEdit = getChild<LLLineEditor>("music_url");
- childSetCommitCallback("music_url", onCommitAny, this);
mMediaTextureCtrl = getChild<LLTextureCtrl>("media texture");
- mMediaTextureCtrl->setCommitCallback( onCommitAny );
- mMediaTextureCtrl->setCallbackUserData( this );
+ mMediaTextureCtrl->setCommitCallback( onCommitAny, this );
mMediaTextureCtrl->setAllowNoTexture ( TRUE );
mMediaTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
mMediaTextureCtrl->setNonImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
@@ -128,16 +98,13 @@ BOOL LLPanelLandMedia::postBuild()
childSetCommitCallback("media_auto_scale", onCommitAny, this);
mMediaLoopCheck = getChild<LLCheckBoxCtrl>("media_loop");
- childSetCommitCallback("media_loop", onCommitAny, this);
+ childSetCommitCallback("media_loop", onCommitAny, this );
mMediaUrlCheck = getChild<LLCheckBoxCtrl>("hide_media_url");
- childSetCommitCallback("hide_media_url", onCommitAny, this);
-
- mMusicUrlCheck = getChild<LLCheckBoxCtrl>("hide_music_url");
- childSetCommitCallback("hide_music_url", onCommitAny, this);
+ childSetCommitCallback("hide_media_url", onCommitAny, this );
mMediaURLEdit = getChild<LLLineEditor>("media_url");
- childSetCommitCallback("media_url", onCommitAny, this);
+ childSetCommitCallback("media_url", onCommitAny, this );
mMediaDescEdit = getChild<LLLineEditor>("url_description");
childSetCommitCallback("url_description", onCommitAny, this);
@@ -175,46 +142,11 @@ void LLPanelLandMedia::refresh()
// Display options
BOOL can_change_media = LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_LAND_CHANGE_MEDIA);
- mCheckSoundLocal->set( parcel->getSoundLocal() );
- mCheckSoundLocal->setEnabled( can_change_media );
-
- LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
- if (!region)
- {
- // never seen this happen, but log it
- llwarns << "Couldn't get selected region." << llendl;
- }
-
- if (region && region->isVoiceEnabled()) // estate-wide voice-disable overrides all
- {
- bool allow_voice = parcel->getParcelFlagAllowVoice();
-
- mCheckEnableVoiceChatIsEstateDisabled->setVisible(false);
-
- mCheckEnableVoiceChat->setVisible(true);
- mCheckEnableVoiceChat->setEnabled( can_change_media );
- mCheckEnableVoiceChat->set(allow_voice);
-
- mCheckEnableVoiceChatParcel->setEnabled( can_change_media && allow_voice );
- }
- else // disabled at region level
- {
- mCheckEnableVoiceChatIsEstateDisabled->setVisible(true); // always disabled
- mCheckEnableVoiceChat->setVisible(false);
- mCheckEnableVoiceChat->setEnabled(false);
- mCheckEnableVoiceChat->set(false);
-
- mCheckEnableVoiceChatParcel->setEnabled(false);
- }
-
- mCheckEnableVoiceChatParcel->set(!parcel->getParcelFlagUseEstateVoiceChannel());
-
- mMusicURLEdit->setText(parcel->getMusicURL());
- mMusicURLEdit->setEnabled( can_change_media );
-
mMediaURLEdit->setText(parcel->getMediaURL());
mMediaURLEdit->setEnabled( FALSE );
+ childSetText("current_url", parcel->getMediaCurrentURL());
+
mMediaDescEdit->setText(parcel->getMediaDesc());
mMediaDescEdit->setEnabled( can_change_media );
@@ -230,15 +162,11 @@ void LLPanelLandMedia::refresh()
mMediaUrlCheck->set( parcel->getObscureMedia() );
mMediaUrlCheck->setEnabled( can_change_media );
- mMusicUrlCheck->set( parcel->getObscureMusic() );
- mMusicUrlCheck->setEnabled( can_change_media );
-
// don't display urls if you're not able to change it
// much requested change in forums so people can't 'steal' urls
// NOTE: bug#2009 means this is still vunerable - however, bug
// should be closed since this bug opens up major security issues elsewhere.
bool obscure_media = ! can_change_media && parcel->getObscureMedia();
- bool obscure_music = ! can_change_media && parcel->getObscureMusic();
// Special code to disable asterixes for html type
if(mime_type == "text/html")
@@ -248,7 +176,6 @@ void LLPanelLandMedia::refresh()
mMediaUrlCheck->setEnabled( false );
}
- mMusicURLEdit->setDrawAsterixes( obscure_music );
mMediaURLEdit->setDrawAsterixes( obscure_media );
mMediaAutoScaleCheck->set( parcel->getMediaAutoScale () );
@@ -262,7 +189,7 @@ void LLPanelLandMedia::refresh()
else
mMediaLoopCheck->set( false );
mMediaLoopCheck->setEnabled ( can_change_media && allow_looping );
-
+
// disallow media size change for mime types that don't allow it
bool allow_resize = LLMIMETypes::findAllowResize( mime_type );
if ( allow_resize )
@@ -286,27 +213,6 @@ void LLPanelLandMedia::refresh()
mSetURLButton->setEnabled( can_change_media );
- #if 0
- // there is a media url and a media texture selected
- if ( ( ! ( std::string ( parcel->getMediaURL() ).empty () ) ) && ( ! ( parcel->getMediaID ().isNull () ) ) )
- {
- // turn on transport controls if allowed for this parcel
- mMediaStopButton->setEnabled ( editable );
- mMediaStartButton->setEnabled ( editable );
- }
- else
- {
- // no media url or no media texture
- mMediaStopButton->setEnabled ( FALSE );
- mMediaStartButton->setEnabled ( FALSE );
- };
- #endif
-
- LLFloaterURLEntry* floater_url_entry = (LLFloaterURLEntry*)mURLEntryFloater.get();
- if (floater_url_entry)
- {
- floater_url_entry->updateFromLandMediaPanel();
- }
}
}
@@ -348,12 +254,19 @@ void LLPanelLandMedia::setMediaType(const std::string& mime_type)
void LLPanelLandMedia::setMediaURL(const std::string& media_url)
{
mMediaURLEdit->setText(media_url);
+ LLParcel *parcel = mParcel->getParcel();
+ if(parcel)
+ parcel->setMediaCurrentURL(media_url);
+ // LLViewerMedia::navigateHome();
+
+
mMediaURLEdit->onCommit();
+ // LLViewerParcelMedia::sendMediaNavigateMessage(media_url);
+ childSetText("current_url", media_url);
}
-
std::string LLPanelLandMedia::getMediaURL()
{
- return mMediaURLEdit->getText();
+ return mMediaURLEdit->getText();
}
// static
@@ -382,33 +295,23 @@ void LLPanelLandMedia::onCommitAny(LLUICtrl*, void *userdata)
}
// Extract data from UI
- BOOL sound_local = self->mCheckSoundLocal->get();
- std::string music_url = self->mMusicURLEdit->getText();
std::string media_url = self->mMediaURLEdit->getText();
std::string media_desc = self->mMediaDescEdit->getText();
std::string mime_type = self->childGetText("mime_type");
U8 media_auto_scale = self->mMediaAutoScaleCheck->get();
U8 media_loop = self->mMediaLoopCheck->get();
U8 obscure_media = self->mMediaUrlCheck->get();
- U8 obscure_music = self->mMusicUrlCheck->get();
S32 media_width = (S32)self->mMediaWidthCtrl->get();
S32 media_height = (S32)self->mMediaHeightCtrl->get();
LLUUID media_id = self->mMediaTextureCtrl->getImageAssetID();
- BOOL voice_enabled = self->mCheckEnableVoiceChat->get();
- BOOL voice_estate_chan = ! self->mCheckEnableVoiceChatParcel->get();
self->childSetText("mime_type", mime_type);
// Remove leading/trailing whitespace (common when copying/pasting)
- LLStringUtil::trim(music_url);
LLStringUtil::trim(media_url);
// Push data into current parcel
- parcel->setParcelFlag(PF_ALLOW_VOICE_CHAT, voice_enabled);
- parcel->setParcelFlag(PF_USE_ESTATE_VOICE_CHAN, voice_estate_chan);
- parcel->setParcelFlag(PF_SOUND_LOCAL, sound_local);
- parcel->setMusicURL(music_url);
parcel->setMediaURL(media_url);
parcel->setMediaType(mime_type);
parcel->setMediaDesc(media_desc);
@@ -418,7 +321,6 @@ void LLPanelLandMedia::onCommitAny(LLUICtrl*, void *userdata)
parcel->setMediaAutoScale ( media_auto_scale );
parcel->setMediaLoop ( media_loop );
parcel->setObscureMedia( obscure_media );
- parcel->setObscureMusic( obscure_music );
// Send current parcel data upstream to server
LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel );
@@ -430,10 +332,23 @@ void LLPanelLandMedia::onCommitAny(LLUICtrl*, void *userdata)
void LLPanelLandMedia::onSetBtn(void *userdata)
{
LLPanelLandMedia *self = (LLPanelLandMedia *)userdata;
- self->mURLEntryFloater = LLFloaterURLEntry::show( self->getHandle() );
+ self->mURLEntryFloater = LLFloaterURLEntry::show( self->getHandle(), self->getMediaURL() );
LLFloater* parent_floater = gFloaterView->getParentFloater(self);
if (parent_floater)
{
parent_floater->addDependentFloater(self->mURLEntryFloater.get());
}
}
+
+// static
+void LLPanelLandMedia::onResetBtn(void *userdata)
+{
+ LLPanelLandMedia *self = (LLPanelLandMedia *)userdata;
+ LLParcel* parcel = self->mParcel->getParcel();
+ // LLViewerMedia::navigateHome();
+ self->refresh();
+ self->childSetText("current_url", parcel->getMediaURL());
+ // LLViewerParcelMedia::sendMediaNavigateMessage(parcel->getMediaURL());
+
+}
+
diff --git a/indra/newview/llpanellandmedia.h b/indra/newview/llpanellandmedia.h
index 6a53dd42a5..3deea29d17 100644
--- a/indra/newview/llpanellandmedia.h
+++ b/indra/newview/llpanellandmedia.h
@@ -56,29 +56,25 @@ private:
static void onCommitAny(LLUICtrl* ctrl, void *userdata);
static void onCommitType(LLUICtrl* ctrl, void *userdata);
static void onSetBtn(void* userdata);
- static void onClickSoundHelp(void*);
-
+ static void onResetBtn(void* userdata);
+
private:
- LLCheckBoxCtrl* mCheckSoundLocal;
- LLButton* mSoundHelpButton;
- LLCheckBoxCtrl* mCheckEnableVoiceChat;
- LLCheckBoxCtrl* mCheckEnableVoiceChatIsEstateDisabled;
- LLCheckBoxCtrl* mCheckEnableVoiceChatParcel;
- LLLineEditor* mMusicURLEdit;
LLLineEditor* mMediaURLEdit;
LLLineEditor* mMediaDescEdit;
LLComboBox* mMediaTypeCombo;
LLButton* mSetURLButton;
LLSpinCtrl* mMediaHeightCtrl;
LLSpinCtrl* mMediaWidthCtrl;
+ LLTextBox* mMediaResetCtrlLabel;
LLTextBox* mMediaSizeCtrlLabel;
LLTextureCtrl* mMediaTextureCtrl;
LLCheckBoxCtrl* mMediaAutoScaleCheck;
LLCheckBoxCtrl* mMediaLoopCheck;
LLCheckBoxCtrl* mMediaUrlCheck;
- LLCheckBoxCtrl* mMusicUrlCheck;
LLHandle<LLFloater> mURLEntryFloater;
+
+
LLSafeHandle<LLParcelSelection>& mParcel;
};
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index bc5e8f2482..87d101b00f 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -34,13 +34,11 @@
#include "llpanellogin.h"
-#include "llpanelgeneral.h"
-
#include "indra_constants.h" // for key and mask constants
+#include "llfloaterreg.h"
#include "llfontgl.h"
#include "llmd5.h"
#include "llsecondlifeurls.h"
-#include "llversionviewer.h"
#include "v4color.h"
#include "llbutton.h"
@@ -49,34 +47,35 @@
#include "llcombobox.h"
#include "llcurl.h"
#include "llviewercontrol.h"
-#include "llfloaterabout.h"
-#include "llfloatertest.h"
#include "llfloaterpreference.h"
#include "llfocusmgr.h"
#include "lllineeditor.h"
+#include "llnotificationsutil.h"
#include "llstartup.h"
#include "lltextbox.h"
#include "llui.h"
#include "lluiconstants.h"
#include "llurlsimstring.h"
-#include "llviewerbuild.h"
-#include "llviewerimagelist.h"
+#include "llversioninfo.h"
+#include "llviewerhelp.h"
+#include "llviewertexturelist.h"
#include "llviewermenu.h" // for handle_preferences()
#include "llviewernetwork.h"
#include "llviewerwindow.h" // to link into child list
-#include "llnotify.h"
-#include "llurlsimstring.h"
#include "lluictrlfactory.h"
#include "llhttpclient.h"
#include "llweb.h"
-#include "llwebbrowserctrl.h"
-
-#include "llfloaterhtml.h"
+#include "llmediactrl.h"
+#include "llrootview.h"
-#include "llfloaterhtmlhelp.h"
#include "llfloatertos.h"
-
+#include "lltrans.h"
#include "llglheaders.h"
+#include "llpanelloginlistener.h"
+
+#if LL_WINDOWS
+#pragma warning(disable: 4355) // 'this' used in initializer list
+#endif // LL_WINDOWS
#define USE_VIEWER_AUTH 0
@@ -91,8 +90,8 @@ class LLLoginRefreshHandler : public LLCommandHandler
{
public:
// don't allow from external browsers
- LLLoginRefreshHandler() : LLCommandHandler("login_refresh", true) { }
- bool handle(const LLSD& tokens, const LLSD& query_map, LLWebBrowserCtrl* web)
+ LLLoginRefreshHandler() : LLCommandHandler("login_refresh", UNTRUSTED_BLOCK) { }
+ bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
{
if (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP)
{
@@ -166,11 +165,12 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
BOOL show_server,
void (*callback)(S32 option, void* user_data),
void *cb_data)
-: LLPanel(std::string("panel_login"), LLRect(0,600,800,0), FALSE), // not bordered
+: LLPanel(),
mLogoImage(),
mCallback(callback),
mCallbackData(cb_data),
- mHtmlAvailable( TRUE )
+ mHtmlAvailable( TRUE ),
+ mListener(new LLPanelLoginListener(this))
{
setFocusRoot(TRUE);
@@ -181,19 +181,19 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
if (LLPanelLogin::sInstance)
{
llwarns << "Duplicate instance of login view deleted" << llendl;
- delete LLPanelLogin::sInstance;
-
// Don't leave bad pointer in gFocusMgr
gFocusMgr.setDefaultKeyboardFocus(NULL);
+
+ delete LLPanelLogin::sInstance;
}
LLPanelLogin::sInstance = this;
// add to front so we are the bottom-most child
- gViewerWindow->getRootView()->addChildAtEnd(this);
+ gViewerWindow->getRootView()->addChildInBack(this);
// Logo
- mLogoImage = LLUI::getUIImage("startup_logo.j2c");
+ mLogoImage = LLUI::getUIImage("startup_logo");
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_login.xml");
@@ -201,15 +201,23 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
//leave room for the login menu bar
setRect(LLRect(0, rect.getHeight()-18, rect.getWidth(), 0));
#endif
- reshape(rect.getWidth(), rect.getHeight());
+ // Legacy login web page is hidden under the menu bar.
+ // Adjust reg-in-client web browser widget to not be hidden.
+ if (gSavedSettings.getBOOL("RegInClient"))
+ {
+ reshape(rect.getWidth(), rect.getHeight() - MENU_BAR_HEIGHT);
+ }
+ else
+ {
+ reshape(rect.getWidth(), rect.getHeight());
+ }
#if !USE_VIEWER_AUTH
- childSetPrevalidate("first_name_edit", LLLineEditor::prevalidatePrintableNoSpace);
- childSetPrevalidate("last_name_edit", LLLineEditor::prevalidatePrintableNoSpace);
+ childSetPrevalidate("first_name_edit", LLLineEditor::prevalidateASCIIPrintableNoSpace);
+ childSetPrevalidate("last_name_edit", LLLineEditor::prevalidateASCIIPrintableNoSpace);
- childSetCommitCallback("password_edit", mungePassword);
- childSetKeystrokeCallback("password_edit", onPassKey, this);
- childSetUserData("password_edit", this);
+ childSetCommitCallback("password_edit", mungePassword, this);
+ getChild<LLLineEditor>("password_edit")->setKeystrokeCallback(onPassKey, this);
// change z sort of clickable text to be behind buttons
sendChildToBack(getChildView("channel_text"));
@@ -219,15 +227,13 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
if (edit) edit->setDrawAsterixes(TRUE);
LLComboBox* combo = getChild<LLComboBox>("start_location_combo");
- combo->setAllowTextEntry(TRUE, 128, FALSE);
-
- // The XML file loads the combo with the following labels:
- // 0 - "My Home"
- // 1 - "My Last Location"
- // 2 - "<Type region name>"
- BOOL login_last = gSavedSettings.getBOOL("LoginLastLocation");
std::string sim_string = LLURLSimString::sInstance.mSimString;
+ if(sim_string.empty())
+ {
+ LLURLSimString::setString(gSavedSettings.getString("LoginLocation"));
+ }
+
if (!sim_string.empty())
{
// Replace "<Type region name>" with this region name
@@ -236,71 +242,64 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
combo->setTextEntry(sim_string);
combo->setCurrentByIndex( 2 );
}
- else if (login_last)
- {
- combo->setCurrentByIndex( 1 );
- }
- else
- {
- combo->setCurrentByIndex( 0 );
- }
- combo->setCommitCallback( &set_start_location );
+ combo->setCommitCallback( &set_start_location, NULL );
LLComboBox* server_choice_combo = sInstance->getChild<LLComboBox>("server_combo");
- server_choice_combo->setCommitCallback(onSelectServer);
- server_choice_combo->setFocusLostCallback(onServerComboLostFocus);
+ server_choice_combo->setCommitCallback(onSelectServer, NULL);
+ server_choice_combo->setFocusLostCallback(boost::bind(onServerComboLostFocus, _1));
childSetAction("connect_btn", onClickConnect, this);
- setDefaultBtn("connect_btn");
-
- // childSetAction("quit_btn", onClickQuit, this);
+ getChild<LLPanel>("login")->setDefaultBtn("connect_btn");
std::string channel = gSavedSettings.getString("VersionChannelName");
- std::string version = llformat("%d.%d.%d (%d)",
- LL_VERSION_MAJOR,
- LL_VERSION_MINOR,
- LL_VERSION_PATCH,
- LL_VIEWER_BUILD );
+ std::string version = llformat("%s (%d)",
+ LLVersionInfo::getShortVersion().c_str(),
+ LLVersionInfo::getBuild());
LLTextBox* channel_text = getChild<LLTextBox>("channel_text");
channel_text->setTextArg("[CHANNEL]", channel); // though not displayed
channel_text->setTextArg("[VERSION]", version);
- channel_text->setClickedCallback(onClickVersion);
- channel_text->setCallbackUserData(this);
+ channel_text->setClickedCallback(onClickVersion, this);
LLTextBox* forgot_password_text = getChild<LLTextBox>("forgot_password_text");
- forgot_password_text->setClickedCallback(onClickForgotPassword);
+ forgot_password_text->setClickedCallback(onClickForgotPassword, NULL);
LLTextBox* create_new_account_text = getChild<LLTextBox>("create_new_account_text");
- create_new_account_text->setClickedCallback(onClickNewAccount);
+ create_new_account_text->setClickedCallback(onClickNewAccount, NULL);
+
+ LLTextBox* need_help_text = getChild<LLTextBox>("login_help");
+ need_help_text->setClickedCallback(onClickHelp, NULL);
#endif
// get the web browser control
- LLWebBrowserCtrl* web_browser = getChild<LLWebBrowserCtrl>("login_html");
+ LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html");
+ web_browser->addObserver(this);
+
+ // Clear the browser's cache to avoid any potential for the cache messing up the login screen.
+ web_browser->clearCache();
+
// Need to handle login secondlife:///app/ URLs
web_browser->setTrusted( true );
- // observe browser events
- web_browser->addObserver( this );
-
// don't make it a tab stop until SL-27594 is fixed
web_browser->setTabStop(FALSE);
- web_browser->navigateToLocalPage( "loading", "loading.html" );
+ // web_browser->navigateToLocalPage( "loading", "loading.html" );
- // make links open in external browser
- web_browser->setOpenInExternalBrowser( true );
+ if (gSavedSettings.getBOOL("RegInClient"))
+ {
+ // need to follow links in the internal browser
+ web_browser->setOpenInExternalBrowser( false );
- // force the size to be correct (XML doesn't seem to be sufficient to do this) (with some padding so the other login screen doesn't show through)
- LLRect htmlRect = getRect();
-#if USE_VIEWER_AUTH
- htmlRect.setCenterAndSize( getRect().getCenterX() - 2, getRect().getCenterY(), getRect().getWidth() + 6, getRect().getHeight());
-#else
- htmlRect.setCenterAndSize( getRect().getCenterX() - 2, getRect().getCenterY() + 40, getRect().getWidth() + 6, getRect().getHeight() - 78 );
-#endif
- web_browser->setRect( htmlRect );
- web_browser->reshape( htmlRect.getWidth(), htmlRect.getHeight(), TRUE );
- reshape( getRect().getWidth(), getRect().getHeight(), 1 );
+ getChild<LLView>("login_widgets")->setVisible(false);
+ }
+ else
+ {
+ // make links open in external browser
+ web_browser->setOpenInExternalBrowser( true );
+
+ reshapeBrowser();
+ }
// kick off a request to grab the url manually
gResponsePtr = LLIamHereLogin::build( this );
@@ -318,9 +317,30 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
}
+// force the size to be correct (XML doesn't seem to be sufficient to do this)
+// (with some padding so the other login screen doesn't show through)
+void LLPanelLogin::reshapeBrowser()
+{
+ LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html");
+ LLRect rect = gViewerWindow->getWindowRectScaled();
+ LLRect html_rect;
+#if USE_VIEWER_AUTH
+ html_rect.setCenterAndSize(
+ rect.getCenterX() - 2, rect.getCenterY(),
+ rect.getWidth() + 6, rect.getHeight());
+#else
+ html_rect.setCenterAndSize(
+ rect.getCenterX() - 2, rect.getCenterY() + 40,
+ rect.getWidth() + 6, rect.getHeight() - 78 );
+#endif
+ web_browser->setRect( html_rect );
+ web_browser->reshape( html_rect.getWidth(), html_rect.getHeight(), TRUE );
+ reshape( rect.getWidth(), rect.getHeight(), 1 );
+}
+
void LLPanelLogin::setSiteIsAlive( bool alive )
{
- LLWebBrowserCtrl* web_browser = getChild<LLWebBrowserCtrl>("login_html");
+ LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html");
// if the contents of the site was retrieved
if ( alive )
{
@@ -382,7 +402,11 @@ LLPanelLogin::~LLPanelLogin()
gResponsePtr->setParent( 0 );
//// We know we're done with the image, so be rid of it.
- //gImageList.deleteImage( mLogoImage );
+ //gTextureList.deleteImage( mLogoImage );
+
+ // Controls having keyboard focus by default
+ // must reset it on destroy. (EXT-2748)
+ gFocusMgr.setDefaultKeyboardFocus(NULL);
}
// virtual
@@ -405,10 +429,14 @@ void LLPanelLogin::draw()
if ( mHtmlAvailable )
{
#if !USE_VIEWER_AUTH
- // draw a background box in black
- gl_rect_2d( 0, height - 264, width, 264, LLColor4( 0.0f, 0.0f, 0.0f, 1.f ) );
- // draw the bottom part of the background image - just the blue background to the native client UI
- mLogoImage->draw(0, -264, width + 8, mLogoImage->getHeight());
+ if (getChild<LLView>("login_widgets")->getVisible())
+ {
+ // draw a background box in black
+ gl_rect_2d( 0, height - 264, width, 264, LLColor4::black );
+ // draw the bottom part of the background image
+ // just the blue background to the native client UI
+ mLogoImage->draw(0, -264, width + 8, mLogoImage->getHeight());
+ }
#endif
}
else
@@ -432,40 +460,12 @@ BOOL LLPanelLogin::handleKeyHere(KEY key, MASK mask)
return TRUE;
}
- if (('P' == key) && (MASK_CONTROL == mask))
- {
- LLFloaterPreference::show(NULL);
- return TRUE;
- }
-
- if (('T' == key) && (MASK_CONTROL == mask))
- {
- new LLFloaterSimple("floater_test.xml");
- return TRUE;
- }
-
if ( KEY_F1 == key )
{
- llinfos << "Spawning HTML help window" << llendl;
- gViewerHtmlHelp.show();
- return TRUE;
- }
-
-# if !LL_RELEASE_FOR_DOWNLOAD
- if ( KEY_F2 == key )
- {
- llinfos << "Spawning floater TOS window" << llendl;
- LLFloaterTOS* tos_dialog = LLFloaterTOS::show(LLFloaterTOS::TOS_TOS,"");
- tos_dialog->startModal();
+ LLViewerHelp* vhelp = LLViewerHelp::getInstance();
+ vhelp->showTopic(vhelp->f1HelpTopic());
return TRUE;
}
-#endif
-
- if (KEY_RETURN == key && MASK_NONE == mask)
- {
- // let the panel handle UICtrl processing: calls onClickConnect()
- return LLPanel::handleKeyHere(key, mask);
- }
return LLPanel::handleKeyHere(key, mask);
}
@@ -526,6 +526,19 @@ void LLPanelLogin::giveFocus()
#endif
}
+// static
+void LLPanelLogin::showLoginWidgets()
+{
+ sInstance->childSetVisible("login_widgets", true);
+ LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
+ web_browser->setOpenInExternalBrowser( true );
+ sInstance->reshapeBrowser();
+ // *TODO: Append all the usual login parameters, like first_login=Y etc.
+ std::string splash_screen_url = sInstance->getString("real_url");
+ web_browser->navigateTo( splash_screen_url, "text/html" );
+ LLUICtrl* first_name_edit = sInstance->getChild<LLUICtrl>("first_name_edit");
+ first_name_edit->setFocus(TRUE);
+}
// static
void LLPanelLogin::show(const LLRect &rect,
@@ -656,45 +669,31 @@ void LLPanelLogin::refreshLocation( bool force_visible )
#if USE_VIEWER_AUTH
loadLoginPage();
#else
- LLComboBox* combo = sInstance->getChild<LLComboBox>("start_location_combo");
-
- if (LLURLSimString::parse())
- {
- combo->setCurrentByIndex( 3 ); // BUG? Maybe 2?
- combo->setTextEntry(LLURLSimString::sInstance.mSimString);
- }
- else
- {
- BOOL login_last = gSavedSettings.getBOOL("LoginLastLocation");
- combo->setCurrentByIndex( login_last ? 1 : 0 );
- }
-
BOOL show_start = TRUE;
if ( ! force_visible )
- show_start = gSavedSettings.getBOOL("ShowStartLocation");
+ {
+ // Don't show on first run after install
+ // Otherwise ShowStartLocation defaults to true.
+ show_start = gSavedSettings.getBOOL("ShowStartLocation")
+ && !gSavedSettings.getBOOL("FirstRunThisInstall");
+ }
sInstance->childSetVisible("start_location_combo", show_start);
sInstance->childSetVisible("start_location_text", show_start);
-#if LL_RELEASE_FOR_DOWNLOAD
BOOL show_server = gSavedSettings.getBOOL("ForceShowGrid");
sInstance->childSetVisible("server_combo", show_server);
-#else
- sInstance->childSetVisible("server_combo", TRUE);
-#endif
#endif
}
// static
-void LLPanelLogin::close()
+void LLPanelLogin::closePanel()
{
if (sInstance)
{
gViewerWindow->getRootView()->removeChild( LLPanelLogin::sInstance );
-
- gFocusMgr.setDefaultKeyboardFocus(NULL);
delete sInstance;
sInstance = NULL;
@@ -706,7 +705,7 @@ void LLPanelLogin::setAlwaysRefresh(bool refresh)
{
if (LLStartUp::getStartupState() >= STATE_LOGIN_CLEANUP) return;
- LLWebBrowserCtrl* web_browser = sInstance->getChild<LLWebBrowserCtrl>("login_html");
+ LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
if (web_browser)
{
@@ -748,8 +747,9 @@ void LLPanelLogin::loadLoginPage()
}
// Channel and Version
- std::string version = llformat("%d.%d.%d (%d)",
- LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH, LL_VIEWER_BUILD);
+ std::string version = llformat("%s (%d)",
+ LLVersionInfo::getShortVersion().c_str(),
+ LLVersionInfo::getBuild());
char* curl_channel = curl_escape(gSavedSettings.getString("VersionChannelName").c_str(), 0);
char* curl_version = curl_escape(version.c_str(), 0);
@@ -787,14 +787,7 @@ void LLPanelLogin::loadLoginPage()
}
else
{
- if (gSavedSettings.getBOOL("LoginLastLocation"))
- {
- location = "last";
- }
- else
- {
- location = "home";
- }
+ location = gSavedSettings.getString("LoginLocation");
}
std::string firstname, lastname;
@@ -836,7 +829,8 @@ void LLPanelLogin::loadLoginPage()
{
oStr << "&auto_login=TRUE";
}
- if (gSavedSettings.getBOOL("ShowStartLocation"))
+ if (gSavedSettings.getBOOL("ShowStartLocation")
+ && !gSavedSettings.getBOOL("FirstRunThisInstall"))
{
oStr << "&show_start_location=TRUE";
}
@@ -852,25 +846,37 @@ void LLPanelLogin::loadLoginPage()
#endif
#endif
- LLWebBrowserCtrl* web_browser = sInstance->getChild<LLWebBrowserCtrl>("login_html");
+ LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
- // navigate to the "real" page
- web_browser->navigateTo( oStr.str() );
+ // navigate to the "real" page
+ if (gSavedSettings.getBOOL("RegInClient"))
+ {
+ web_browser->setFocus(TRUE);
+ login_page = sInstance->getString("reg_in_client_url");
+ web_browser->navigateTo(login_page, "text/html");
+ }
+ else
+ {
+ web_browser->navigateTo( oStr.str(), "text/html" );
+ }
}
-void LLPanelLogin::onNavigateComplete( const EventType& eventIn )
+void LLPanelLogin::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent event)
{
- LLWebBrowserCtrl* web_browser = sInstance->getChild<LLWebBrowserCtrl>("login_html");
- if (web_browser)
+ if(event == MEDIA_EVENT_NAVIGATE_COMPLETE)
{
- // *HACK HACK HACK HACK!
- /* Stuff a Tab key into the browser now so that the first field will
- ** get the focus! The embedded javascript on the page that properly
- ** sets the initial focus in a real web browser is not working inside
- ** the viewer, so this is an UGLY HACK WORKAROUND for now.
- */
- // Commented out as it's not reliable
- //web_browser->handleKey(KEY_TAB, MASK_NONE, false);
+ LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
+ if (web_browser)
+ {
+ // *HACK HACK HACK HACK!
+ /* Stuff a Tab key into the browser now so that the first field will
+ ** get the focus! The embedded javascript on the page that properly
+ ** sets the initial focus in a real web browser is not working inside
+ ** the viewer, so this is an UGLY HACK WORKAROUND for now.
+ */
+ // Commented out as it's not reliable
+ //web_browser->handleKey(KEY_TAB, MASK_NONE, false);
+ }
}
}
@@ -892,28 +898,50 @@ void LLPanelLogin::onClickConnect(void *)
std::string first = sInstance->childGetText("first_name_edit");
std::string last = sInstance->childGetText("last_name_edit");
- if (!first.empty() && !last.empty())
+ LLComboBox* combo = sInstance->getChild<LLComboBox>("start_location_combo");
+ std::string combo_text = combo->getSimple();
+
+ bool has_first_and_last = !(first.empty() || last.empty());
+ bool has_location = false;
+
+ if(combo_text=="<Type region name>" || combo_text =="")
{
- // has both first and last name typed
- sInstance->mCallback(0, sInstance->mCallbackData);
+ // *NOTE: Mani - Location field is not always committed by this point!
+ // This may be duplicate work, but better than not doing the work!
+ LLURLSimString::sInstance.setString("");
+ }
+ else
+ {
+ // *NOTE: Mani - Location field is not always committed by this point!
+ LLURLSimString::sInstance.setString(combo_text);
+ has_location = true;
+ }
+
+ if(!has_first_and_last)
+ {
+ LLNotificationsUtil::add("MustHaveAccountToLogIn");
+ }
+ else if(!has_location)
+ {
+ LLNotificationsUtil::add("StartRegionEmpty");
}
else
{
- LLNotifications::instance().add("MustHaveAccountToLogIn", LLSD(), LLSD(),
- LLPanelLogin::newAccountAlertCallback);
+ // has both first and last name typed
+ sInstance->mCallback(0, sInstance->mCallbackData);
}
}
}
-
+/*
// static
bool LLPanelLogin::newAccountAlertCallback(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
llinfos << "Going to account creation URL" << llendl;
- LLWeb::loadURLExternal( CREATE_ACCOUNT_URL );
+ LLWeb::loadURLExternal( LLNotifications::instance().getGlobalString("CREATE_ACCOUNT_URL"));
}
else
{
@@ -921,35 +949,19 @@ bool LLPanelLogin::newAccountAlertCallback(const LLSD& notification, const LLSD&
}
return false;
}
-
+*/
// static
void LLPanelLogin::onClickNewAccount(void*)
{
- LLWeb::loadURLExternal( CREATE_ACCOUNT_URL );
-}
-
-
-// *NOTE: This function is dead as of 2008 August. I left it here in case
-// we suddenly decide to put the Quit button back. JC
-// static
-void LLPanelLogin::onClickQuit(void*)
-{
- if (sInstance && sInstance->mCallback)
- {
- // tell the responder we're not here anymore
- if ( gResponsePtr )
- gResponsePtr->setParent( 0 );
-
- sInstance->mCallback(1, sInstance->mCallbackData);
- }
+ LLWeb::loadURLExternal(sInstance->getString("create_account_url"));
}
// static
void LLPanelLogin::onClickVersion(void*)
{
- LLFloaterAbout::show(NULL);
+ LLFloaterReg::showInstance("sl_about");
}
//static
@@ -961,12 +973,22 @@ void LLPanelLogin::onClickForgotPassword(void*)
}
}
+//static
+void LLPanelLogin::onClickHelp(void*)
+{
+ if (sInstance)
+ {
+ LLViewerHelp* vhelp = LLViewerHelp::getInstance();
+ vhelp->showTopic(vhelp->preLoginTopic());
+ }
+}
+
// static
void LLPanelLogin::onPassKey(LLLineEditor* caller, void* user_data)
{
if (gKeyboard->getKeyDown(KEY_CAPSLOCK) && sCapslockDidNotification == FALSE)
{
- LLNotifications::instance().add("CapsKeyOn");
+ LLNotificationsUtil::add("CapsKeyOn");
sCapslockDidNotification = TRUE;
}
}
@@ -1021,8 +1043,10 @@ void LLPanelLogin::onSelectServer(LLUICtrl*, void*)
loadLoginPage();
}
-void LLPanelLogin::onServerComboLostFocus(LLFocusableElement* fe, void*)
+void LLPanelLogin::onServerComboLostFocus(LLFocusableElement* fe)
{
+ if (!sInstance) return;
+
LLComboBox* combo = sInstance->getChild<LLComboBox>("server_combo");
if(fe == combo)
{
diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h
index 47d42da7f1..97350ce5c7 100644
--- a/indra/newview/llpanellogin.h
+++ b/indra/newview/llpanellogin.h
@@ -34,15 +34,17 @@
#define LL_LLPANELLOGIN_H
#include "llpanel.h"
-#include "llmemory.h" // LLPointer<>
-#include "llwebbrowserctrl.h" // LLWebBrowserCtrlObserver
+#include "llpointer.h" // LLPointer<>
+#include "llmediactrl.h" // LLMediaCtrlObserver
+#include <boost/scoped_ptr.hpp>
+class LLLineEditor;
class LLUIImage;
-
+class LLPanelLoginListener;
class LLPanelLogin:
public LLPanel,
- public LLWebBrowserCtrlObserver
+ public LLViewerMediaObserver
{
LOG_CLASS(LLPanelLogin);
public:
@@ -55,6 +57,10 @@ public:
virtual void draw();
virtual void setFocus( BOOL b );
+ // Show the XUI first name, last name, and password widgets. They are
+ // hidden on startup for reg-in-client
+ static void showLoginWidgets();
+
static void show(const LLRect &rect, BOOL show_server,
void (*callback)(S32 option, void* user_data),
void* callback_data);
@@ -72,7 +78,7 @@ public:
static BOOL isGridComboDirty();
static void getLocation(std::string &location);
- static void close();
+ static void closePanel();
void setSiteIsAlive( bool alive );
@@ -81,20 +87,25 @@ public:
static void setAlwaysRefresh(bool refresh);
static void mungePassword(LLUICtrl* caller, void* user_data);
+ // inherited from LLViewerMediaObserver
+ /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
+
private:
+ friend class LLPanelLoginListener;
+ void reshapeBrowser();
static void onClickConnect(void*);
static void onClickNewAccount(void*);
- static bool newAccountAlertCallback(const LLSD& notification, const LLSD& response);
- static void onClickQuit(void*);
+// static bool newAccountAlertCallback(const LLSD& notification, const LLSD& response);
static void onClickVersion(void*);
- virtual void onNavigateComplete( const EventType& eventIn );
static void onClickForgotPassword(void*);
+ static void onClickHelp(void*);
static void onPassKey(LLLineEditor* caller, void* user_data);
static void onSelectServer(LLUICtrl*, void*);
- static void onServerComboLostFocus(LLFocusableElement*, void*);
+ static void onServerComboLostFocus(LLFocusableElement*);
private:
LLPointer<LLUIImage> mLogoImage;
+ boost::scoped_ptr<LLPanelLoginListener> mListener;
void (*mCallback)(S32 option, void *userdata);
void* mCallbackData;
diff --git a/indra/newview/llpanelloginlistener.cpp b/indra/newview/llpanelloginlistener.cpp
new file mode 100644
index 0000000000..f7e59aaf54
--- /dev/null
+++ b/indra/newview/llpanelloginlistener.cpp
@@ -0,0 +1,34 @@
+/**
+ * @file llpanelloginlistener.cpp
+ * @author Nat Goodspeed
+ * @date 2009-12-10
+ * @brief Implementation for llpanelloginlistener.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "llviewerprecompiledheaders.h"
+// associated header
+#include "llpanelloginlistener.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llpanellogin.h"
+
+LLPanelLoginListener::LLPanelLoginListener(LLPanelLogin* instance):
+ LLEventAPI("LLPanelLogin", "Access to LLPanelLogin methods"),
+ mPanel(instance)
+{
+ add("onClickConnect",
+ "Pretend user clicked the \"Log In\" button",
+ &LLPanelLoginListener::onClickConnect);
+}
+
+void LLPanelLoginListener::onClickConnect(const LLSD&) const
+{
+ mPanel->onClickConnect(NULL);
+}
diff --git a/indra/newview/llpanelloginlistener.h b/indra/newview/llpanelloginlistener.h
new file mode 100644
index 0000000000..0a56c75422
--- /dev/null
+++ b/indra/newview/llpanelloginlistener.h
@@ -0,0 +1,30 @@
+/**
+ * @file llpanelloginlistener.h
+ * @author Nat Goodspeed
+ * @date 2009-12-10
+ * @brief LLEventAPI for LLPanelLogin
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLPANELLOGINLISTENER_H)
+#define LL_LLPANELLOGINLISTENER_H
+
+#include "lleventapi.h"
+class LLPanelLogin;
+class LLSD;
+
+class LLPanelLoginListener: public LLEventAPI
+{
+public:
+ LLPanelLoginListener(LLPanelLogin* instance);
+
+private:
+ void onClickConnect(const LLSD&) const;
+
+ LLPanelLogin* mPanel;
+};
+
+#endif /* ! defined(LL_LLPANELLOGINLISTENER_H) */
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
new file mode 100644
index 0000000000..a5a61f0c7b
--- /dev/null
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -0,0 +1,1175 @@
+/**
+ * @file llsidepanelmaininventory.cpp
+ * @brief Implementation of llsidepanelmaininventory.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llpanelmaininventory.h"
+
+#include "llagent.h"
+#include "lldndbutton.h"
+#include "lleconomy.h"
+#include "llfilepicker.h"
+#include "llfloaterinventory.h"
+#include "llinventorybridge.h"
+#include "llinventoryfunctions.h"
+#include "llinventorypanel.h"
+#include "llfiltereditor.h"
+#include "llfloaterreg.h"
+#include "llpreviewtexture.h"
+#include "llscrollcontainer.h"
+#include "llsdserialize.h"
+#include "llspinctrl.h"
+#include "lltooldraganddrop.h"
+#include "llviewermenu.h"
+#include "llviewertexturelist.h"
+
+const std::string FILTERS_FILENAME("filters.xml");
+
+static LLRegisterPanelClassWrapper<LLPanelMainInventory> t_inventory("panel_main_inventory");
+
+void on_file_loaded_for_save(BOOL success,
+ LLViewerFetchedTexture *src_vi,
+ LLImageRaw* src,
+ LLImageRaw* aux_src,
+ S32 discard_level,
+ BOOL final,
+ void* userdata);
+
+///----------------------------------------------------------------------------
+/// LLFloaterInventoryFinder
+///----------------------------------------------------------------------------
+
+class LLFloaterInventoryFinder : public LLFloater
+{
+public:
+ LLFloaterInventoryFinder( LLPanelMainInventory* inventory_view);
+ virtual void draw();
+ /*virtual*/ BOOL postBuild();
+ void changeFilter(LLInventoryFilter* filter);
+ void updateElementsFromFilter();
+ BOOL getCheckShowEmpty();
+ BOOL getCheckSinceLogoff();
+
+ static void onTimeAgo(LLUICtrl*, void *);
+ static void onCheckSinceLogoff(LLUICtrl*, void *);
+ static void onCloseBtn(void* user_data);
+ static void selectAllTypes(void* user_data);
+ static void selectNoTypes(void* user_data);
+private:
+ LLPanelMainInventory* mPanelMainInventory;
+ LLSpinCtrl* mSpinSinceDays;
+ LLSpinCtrl* mSpinSinceHours;
+ LLInventoryFilter* mFilter;
+};
+
+///----------------------------------------------------------------------------
+/// LLPanelMainInventory
+///----------------------------------------------------------------------------
+
+LLPanelMainInventory::LLPanelMainInventory()
+ : LLPanel(),
+ mActivePanel(NULL),
+ mSavedFolderState(NULL),
+ mFilterText(""),
+ mMenuGearDefault(NULL),
+ mMenuAdd(NULL),
+ mNeedUploadCost(true)
+{
+ LLMemType mt(LLMemType::MTYPE_INVENTORY_VIEW_INIT);
+ // Menu Callbacks (non contex menus)
+ mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLPanelMainInventory::doToSelected, this, _2));
+ mCommitCallbackRegistrar.add("Inventory.CloseAllFolders", boost::bind(&LLPanelMainInventory::closeAllFolders, this));
+ mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH));
+ mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND));
+ mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLPanelMainInventory::doCreate, this, _2));
+ mCommitCallbackRegistrar.add("Inventory.NewWindow", boost::bind(&LLPanelMainInventory::newWindow, this));
+ mCommitCallbackRegistrar.add("Inventory.ShowFilters", boost::bind(&LLPanelMainInventory::toggleFindOptions, this));
+ mCommitCallbackRegistrar.add("Inventory.ResetFilters", boost::bind(&LLPanelMainInventory::resetFilters, this));
+ mCommitCallbackRegistrar.add("Inventory.SetSortBy", boost::bind(&LLPanelMainInventory::setSortBy, this, _2));
+
+ // Controls
+ // *TODO: Just use persistant settings for each of these
+ U32 sort_order = gSavedSettings.getU32("InventorySortOrder");
+ BOOL sort_by_name = ! ( sort_order & LLInventoryFilter::SO_DATE );
+ BOOL sort_folders_by_name = ( sort_order & LLInventoryFilter::SO_FOLDERS_BY_NAME );
+ BOOL sort_system_folders_to_top = ( sort_order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP );
+
+ gSavedSettings.declareBOOL("Inventory.SortByName", sort_by_name, "Declared in code", FALSE);
+ gSavedSettings.declareBOOL("Inventory.SortByDate", !sort_by_name, "Declared in code", FALSE);
+ gSavedSettings.declareBOOL("Inventory.FoldersAlwaysByName", sort_folders_by_name, "Declared in code", FALSE);
+ gSavedSettings.declareBOOL("Inventory.SystemFoldersToTop", sort_system_folders_to_top, "Declared in code", FALSE);
+
+ mSavedFolderState = new LLSaveFolderState();
+ mSavedFolderState->setApply(FALSE);
+}
+
+BOOL LLPanelMainInventory::postBuild()
+{
+ gInventory.addObserver(this);
+
+ mFilterTabs = getChild<LLTabContainer>("inventory filter tabs");
+ mFilterTabs->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterSelected, this));
+
+ //panel->getFilter()->markDefault();
+
+ // Set up the default inv. panel/filter settings.
+ mActivePanel = getChild<LLInventoryPanel>("All Items");
+ if (mActivePanel)
+ {
+ // "All Items" is the previous only view, so it gets the InventorySortOrder
+ mActivePanel->setSortOrder(gSavedSettings.getU32("InventorySortOrder"));
+ mActivePanel->getFilter()->markDefault();
+ mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
+ mActivePanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mActivePanel, _1, _2));
+ }
+ LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items");
+ if (recent_items_panel)
+ {
+ recent_items_panel->setSinceLogoff(TRUE);
+ recent_items_panel->setSortOrder(LLInventoryFilter::SO_DATE);
+ recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
+ recent_items_panel->getFilter()->markDefault();
+ recent_items_panel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, recent_items_panel, _1, _2));
+ }
+
+ // Now load the stored settings from disk, if available.
+ std::ostringstream filterSaveName;
+ filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME);
+ llinfos << "LLPanelMainInventory::init: reading from " << filterSaveName << llendl;
+ llifstream file(filterSaveName.str());
+ LLSD savedFilterState;
+ if (file.is_open())
+ {
+ LLSDSerialize::fromXML(savedFilterState, file);
+ file.close();
+
+ // Load the persistent "Recent Items" settings.
+ // Note that the "All Items" settings do not persist.
+ if(recent_items_panel)
+ {
+ if(savedFilterState.has(recent_items_panel->getFilter()->getName()))
+ {
+ LLSD recent_items = savedFilterState.get(
+ recent_items_panel->getFilter()->getName());
+ recent_items_panel->getFilter()->fromLLSD(recent_items);
+ }
+ }
+
+ }
+
+ mFilterEditor = getChild<LLFilterEditor>("inventory search editor");
+ if (mFilterEditor)
+ {
+ mFilterEditor->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterEdit, this, _2));
+ }
+
+ // *TODO:Get the cost info from the server
+ const std::string upload_cost("10");
+ childSetLabelArg("Upload Image", "[COST]", upload_cost);
+ childSetLabelArg("Upload Sound", "[COST]", upload_cost);
+ childSetLabelArg("Upload Animation", "[COST]", upload_cost);
+ childSetLabelArg("Bulk Upload", "[COST]", upload_cost);
+
+ initListCommandsHandlers();
+ return TRUE;
+}
+
+// Destroys the object
+LLPanelMainInventory::~LLPanelMainInventory( void )
+{
+ // Save the filters state.
+ LLSD filterRoot;
+ LLInventoryPanel* all_items_panel = getChild<LLInventoryPanel>("All Items");
+ if (all_items_panel)
+ {
+ LLInventoryFilter* filter = all_items_panel->getFilter();
+ if (filter)
+ {
+ LLSD filterState;
+ filter->toLLSD(filterState);
+ filterRoot[filter->getName()] = filterState;
+ }
+ }
+
+ LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items");
+ if (recent_items_panel)
+ {
+ LLInventoryFilter* filter = recent_items_panel->getFilter();
+ if (filter)
+ {
+ LLSD filterState;
+ filter->toLLSD(filterState);
+ filterRoot[filter->getName()] = filterState;
+ }
+ }
+
+ std::ostringstream filterSaveName;
+ filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME);
+ llofstream filtersFile(filterSaveName.str());
+ if(!LLSDSerialize::toPrettyXML(filterRoot, filtersFile))
+ {
+ llwarns << "Could not write to filters save file " << filterSaveName << llendl;
+ }
+ else
+ filtersFile.close();
+
+ gInventory.removeObserver(this);
+ delete mSavedFolderState;
+}
+
+void LLPanelMainInventory::startSearch()
+{
+ // this forces focus to line editor portion of search editor
+ if (mFilterEditor)
+ {
+ mFilterEditor->focusFirstItem(TRUE);
+ }
+}
+
+BOOL LLPanelMainInventory::handleKeyHere(KEY key, MASK mask)
+{
+ LLFolderView* root_folder = mActivePanel ? mActivePanel->getRootFolder() : NULL;
+ if (root_folder)
+ {
+ // first check for user accepting current search results
+ if (mFilterEditor
+ && mFilterEditor->hasFocus()
+ && (key == KEY_RETURN
+ || key == KEY_DOWN)
+ && mask == MASK_NONE)
+ {
+ // move focus to inventory proper
+ mActivePanel->setFocus(TRUE);
+ root_folder->scrollToShowSelection();
+ return TRUE;
+ }
+
+ if (mActivePanel->hasFocus() && key == KEY_UP)
+ {
+ startSearch();
+ }
+ }
+
+ return LLPanel::handleKeyHere(key, mask);
+
+}
+
+//----------------------------------------------------------------------------
+// menu callbacks
+
+void LLPanelMainInventory::doToSelected(const LLSD& userdata)
+{
+ getPanel()->getRootFolder()->doToSelected(&gInventory, userdata);
+}
+
+void LLPanelMainInventory::closeAllFolders()
+{
+ getPanel()->getRootFolder()->closeAllFolders();
+}
+
+void LLPanelMainInventory::newWindow()
+{
+ LLFloaterInventory::showAgentInventory();
+}
+
+void LLPanelMainInventory::doCreate(const LLSD& userdata)
+{
+ menu_create_inventory_item(getPanel()->getRootFolder(), NULL, userdata);
+}
+
+void LLPanelMainInventory::resetFilters()
+{
+ LLFloaterInventoryFinder *finder = getFinder();
+ getActivePanel()->getFilter()->resetDefault();
+ if (finder)
+ {
+ finder->updateElementsFromFilter();
+ }
+
+ setFilterTextFromFilter();
+}
+
+void LLPanelMainInventory::setSortBy(const LLSD& userdata)
+{
+ std::string sort_field = userdata.asString();
+ if (sort_field == "name")
+ {
+ U32 order = getActivePanel()->getSortOrder();
+ getActivePanel()->setSortOrder( order & ~LLInventoryFilter::SO_DATE );
+
+ gSavedSettings.setBOOL("Inventory.SortByName", TRUE );
+ gSavedSettings.setBOOL("Inventory.SortByDate", FALSE );
+ }
+ else if (sort_field == "date")
+ {
+ U32 order = getActivePanel()->getSortOrder();
+ getActivePanel()->setSortOrder( order | LLInventoryFilter::SO_DATE );
+
+ gSavedSettings.setBOOL("Inventory.SortByName", FALSE );
+ gSavedSettings.setBOOL("Inventory.SortByDate", TRUE );
+ }
+ else if (sort_field == "foldersalwaysbyname")
+ {
+ U32 order = getActivePanel()->getSortOrder();
+ if ( order & LLInventoryFilter::SO_FOLDERS_BY_NAME )
+ {
+ order &= ~LLInventoryFilter::SO_FOLDERS_BY_NAME;
+
+ gSavedSettings.setBOOL("Inventory.FoldersAlwaysByName", FALSE );
+ }
+ else
+ {
+ order |= LLInventoryFilter::SO_FOLDERS_BY_NAME;
+
+ gSavedSettings.setBOOL("Inventory.FoldersAlwaysByName", TRUE );
+ }
+ getActivePanel()->setSortOrder( order );
+ }
+ else if (sort_field == "systemfolderstotop")
+ {
+ U32 order = getActivePanel()->getSortOrder();
+ if ( order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP )
+ {
+ order &= ~LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
+
+ gSavedSettings.setBOOL("Inventory.SystemFoldersToTop", FALSE );
+ }
+ else
+ {
+ order |= LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
+
+ gSavedSettings.setBOOL("Inventory.SystemFoldersToTop", TRUE );
+ }
+ getActivePanel()->setSortOrder( order );
+ }
+}
+
+// static
+BOOL LLPanelMainInventory::filtersVisible(void* user_data)
+{
+ LLPanelMainInventory* self = (LLPanelMainInventory*)user_data;
+ if(!self) return FALSE;
+
+ return self->getFinder() != NULL;
+}
+
+void LLPanelMainInventory::onClearSearch()
+{
+ LLFloater *finder = getFinder();
+ if (mActivePanel)
+ {
+ mActivePanel->setFilterSubString(LLStringUtil::null);
+ mActivePanel->setFilterTypes(0xffffffff);
+ }
+
+ if (finder)
+ {
+ LLFloaterInventoryFinder::selectAllTypes(finder);
+ }
+
+ // re-open folders that were initially open
+ if (mActivePanel)
+ {
+ mSavedFolderState->setApply(TRUE);
+ mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
+ LLOpenFoldersWithSelection opener;
+ mActivePanel->getRootFolder()->applyFunctorRecursively(opener);
+ mActivePanel->getRootFolder()->scrollToShowSelection();
+ }
+ mFilterSubString = "";
+}
+
+void LLPanelMainInventory::onFilterEdit(const std::string& search_string )
+{
+ if (search_string == "")
+ {
+ onClearSearch();
+ }
+ if (!mActivePanel)
+ {
+ return;
+ }
+
+ gInventory.startBackgroundFetch();
+
+ std::string uppercase_search_string = search_string;
+ LLStringUtil::toUpper(uppercase_search_string);
+ mFilterSubString = uppercase_search_string;
+ if (mActivePanel->getFilterSubString().empty() && uppercase_search_string.empty())
+ {
+ // current filter and new filter empty, do nothing
+ return;
+ }
+
+ // save current folder open state if no filter currently applied
+ if (!mActivePanel->getRootFolder()->isFilterModified())
+ {
+ mSavedFolderState->setApply(FALSE);
+ mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
+ }
+
+ // set new filter string
+ mActivePanel->setFilterSubString(mFilterSubString);
+}
+
+
+ //static
+ BOOL LLPanelMainInventory::incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward)
+ {
+ LLPanelMainInventory* active_view = NULL;
+
+ LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory");
+ for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter)
+ {
+ LLPanelMainInventory* iv = dynamic_cast<LLPanelMainInventory*>(*iter);
+ if (iv)
+ {
+ if (gFocusMgr.childHasKeyboardFocus(iv))
+ {
+ active_view = iv;
+ break;
+ }
+ }
+ }
+
+ if (!active_view)
+ {
+ return FALSE;
+ }
+
+ std::string search_string(find_text);
+
+ if (search_string.empty())
+ {
+ return FALSE;
+ }
+
+ if (active_view->getPanel() &&
+ active_view->getPanel()->getRootFolder()->search(first_item, search_string, backward))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+void LLPanelMainInventory::onFilterSelected()
+{
+ // Find my index
+ mActivePanel = (LLInventoryPanel*)childGetVisibleTab("inventory filter tabs");
+
+ if (!mActivePanel)
+ {
+ return;
+ }
+ setFilterSubString(mFilterSubString);
+ LLInventoryFilter* filter = mActivePanel->getFilter();
+ LLFloaterInventoryFinder *finder = getFinder();
+ if (finder)
+ {
+ finder->changeFilter(filter);
+ }
+ if (filter->isActive())
+ {
+ // If our filter is active we may be the first thing requiring a fetch so we better start it here.
+ gInventory.startBackgroundFetch();
+ }
+ setFilterTextFromFilter();
+}
+
+const std::string LLPanelMainInventory::getFilterSubString()
+{
+ return mActivePanel->getFilterSubString();
+}
+
+void LLPanelMainInventory::setFilterSubString(const std::string& string)
+{
+ mActivePanel->setFilterSubString(string);
+}
+
+BOOL LLPanelMainInventory::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg)
+{
+ // Check to see if we are auto scrolling from the last frame
+ LLInventoryPanel* panel = (LLInventoryPanel*)this->getActivePanel();
+ BOOL needsToScroll = panel->getScrollableContainer()->autoScroll(x, y);
+ if(mFilterTabs)
+ {
+ if(needsToScroll)
+ {
+ mFilterTabs->startDragAndDropDelayTimer();
+ }
+ }
+
+ BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+
+ return handled;
+}
+
+// virtual
+void LLPanelMainInventory::changed(U32)
+{
+ // empty, but must have this defined for abstract base class.
+}
+
+
+// virtual
+void LLPanelMainInventory::draw()
+{
+ if (mActivePanel && mFilterEditor)
+ {
+ mFilterEditor->setText(mFilterSubString);
+ }
+ LLPanel::draw();
+}
+
+void LLPanelMainInventory::setFilterTextFromFilter()
+{
+ mFilterText = mActivePanel->getFilter()->getFilterText();
+}
+
+void LLPanelMainInventory::toggleFindOptions()
+{
+ LLMemType mt(LLMemType::MTYPE_INVENTORY_VIEW_TOGGLE);
+ LLFloater *floater = getFinder();
+ if (!floater)
+ {
+ LLFloaterInventoryFinder * finder = new LLFloaterInventoryFinder(this);
+ mFinderHandle = finder->getHandle();
+ finder->openFloater();
+
+ LLFloater* parent_floater = gFloaterView->getParentFloater(this);
+ if (parent_floater) // Seraph: Fix this, shouldn't be null even for sidepanel
+ parent_floater->addDependentFloater(mFinderHandle);
+ // start background fetch of folders
+ gInventory.startBackgroundFetch();
+ }
+ else
+ {
+ floater->closeFloater();
+ }
+}
+
+void LLPanelMainInventory::setSelectCallback(const LLFolderView::signal_t::slot_type& cb)
+{
+ getChild<LLInventoryPanel>("All Items")->setSelectCallback(cb);
+ getChild<LLInventoryPanel>("Recent Items")->setSelectCallback(cb);
+}
+
+void LLPanelMainInventory::onSelectionChange(LLInventoryPanel *panel, const std::deque<LLFolderViewItem*>& items, BOOL user_action)
+{
+ updateListCommands();
+ panel->onSelectionChange(items, user_action);
+}
+
+///----------------------------------------------------------------------------
+/// LLFloaterInventoryFinder
+///----------------------------------------------------------------------------
+
+LLFloaterInventoryFinder* LLPanelMainInventory::getFinder()
+{
+ return (LLFloaterInventoryFinder*)mFinderHandle.get();
+}
+
+
+LLFloaterInventoryFinder::LLFloaterInventoryFinder(LLPanelMainInventory* inventory_view) :
+ LLFloater(LLSD()),
+ mPanelMainInventory(inventory_view),
+ mFilter(inventory_view->getPanel()->getFilter())
+{
+ LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inventory_view_finder.xml", NULL);
+ updateElementsFromFilter();
+}
+
+
+void LLFloaterInventoryFinder::onCheckSinceLogoff(LLUICtrl *ctrl, void *user_data)
+{
+ LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data;
+ if (!self) return;
+
+ bool since_logoff= self->childGetValue("check_since_logoff");
+
+ if (!since_logoff &&
+ !( self->mSpinSinceDays->get() || self->mSpinSinceHours->get() ) )
+ {
+ self->mSpinSinceHours->set(1.0f);
+ }
+}
+BOOL LLFloaterInventoryFinder::postBuild()
+{
+ const LLRect& viewrect = mPanelMainInventory->getRect();
+ setRect(LLRect(viewrect.mLeft - getRect().getWidth(), viewrect.mTop, viewrect.mLeft, viewrect.mTop - getRect().getHeight()));
+
+ childSetAction("All", selectAllTypes, this);
+ childSetAction("None", selectNoTypes, this);
+
+ mSpinSinceHours = getChild<LLSpinCtrl>("spin_hours_ago");
+ childSetCommitCallback("spin_hours_ago", onTimeAgo, this);
+
+ mSpinSinceDays = getChild<LLSpinCtrl>("spin_days_ago");
+ childSetCommitCallback("spin_days_ago", onTimeAgo, this);
+
+ // mCheckSinceLogoff = getChild<LLSpinCtrl>("check_since_logoff");
+ childSetCommitCallback("check_since_logoff", onCheckSinceLogoff, this);
+
+ childSetAction("Close", onCloseBtn, this);
+
+ updateElementsFromFilter();
+ return TRUE;
+}
+void LLFloaterInventoryFinder::onTimeAgo(LLUICtrl *ctrl, void *user_data)
+{
+ LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data;
+ if (!self) return;
+
+ bool since_logoff=true;
+ if ( self->mSpinSinceDays->get() || self->mSpinSinceHours->get() )
+ {
+ since_logoff = false;
+ }
+ self->childSetValue("check_since_logoff", since_logoff);
+}
+
+void LLFloaterInventoryFinder::changeFilter(LLInventoryFilter* filter)
+{
+ mFilter = filter;
+ updateElementsFromFilter();
+}
+
+void LLFloaterInventoryFinder::updateElementsFromFilter()
+{
+ if (!mFilter)
+ return;
+
+ // Get data needed for filter display
+ U32 filter_types = mFilter->getFilterObjectTypes();
+ std::string filter_string = mFilter->getFilterSubString();
+ LLInventoryFilter::EFolderShow show_folders = mFilter->getShowFolderState();
+ U32 hours = mFilter->getHoursAgo();
+
+ // update the ui elements
+ setTitle(mFilter->getName());
+
+ childSetValue("check_animation", (S32) (filter_types & 0x1 << LLInventoryType::IT_ANIMATION));
+
+ childSetValue("check_calling_card", (S32) (filter_types & 0x1 << LLInventoryType::IT_CALLINGCARD));
+ childSetValue("check_clothing", (S32) (filter_types & 0x1 << LLInventoryType::IT_WEARABLE));
+ childSetValue("check_gesture", (S32) (filter_types & 0x1 << LLInventoryType::IT_GESTURE));
+ childSetValue("check_landmark", (S32) (filter_types & 0x1 << LLInventoryType::IT_LANDMARK));
+ childSetValue("check_notecard", (S32) (filter_types & 0x1 << LLInventoryType::IT_NOTECARD));
+ childSetValue("check_object", (S32) (filter_types & 0x1 << LLInventoryType::IT_OBJECT));
+ childSetValue("check_script", (S32) (filter_types & 0x1 << LLInventoryType::IT_LSL));
+ childSetValue("check_sound", (S32) (filter_types & 0x1 << LLInventoryType::IT_SOUND));
+ childSetValue("check_texture", (S32) (filter_types & 0x1 << LLInventoryType::IT_TEXTURE));
+ childSetValue("check_snapshot", (S32) (filter_types & 0x1 << LLInventoryType::IT_SNAPSHOT));
+ childSetValue("check_show_empty", show_folders == LLInventoryFilter::SHOW_ALL_FOLDERS);
+ childSetValue("check_since_logoff", mFilter->isSinceLogoff());
+ mSpinSinceHours->set((F32)(hours % 24));
+ mSpinSinceDays->set((F32)(hours / 24));
+}
+
+void LLFloaterInventoryFinder::draw()
+{
+ LLMemType mt(LLMemType::MTYPE_INVENTORY_DRAW);
+ U32 filter = 0xffffffff;
+ BOOL filtered_by_all_types = TRUE;
+
+ if (!childGetValue("check_animation"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_ANIMATION);
+ filtered_by_all_types = FALSE;
+ }
+
+
+ if (!childGetValue("check_calling_card"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_CALLINGCARD);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_clothing"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_WEARABLE);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_gesture"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_GESTURE);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_landmark"))
+
+
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_LANDMARK);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_notecard"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_NOTECARD);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_object"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_OBJECT);
+ filter &= ~(0x1 << LLInventoryType::IT_ATTACHMENT);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_script"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_LSL);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_sound"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_SOUND);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_texture"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_TEXTURE);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_snapshot"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_SNAPSHOT);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!filtered_by_all_types)
+ {
+ // don't include folders in filter, unless I've selected everything
+ filter &= ~(0x1 << LLInventoryType::IT_CATEGORY);
+ }
+
+ // update the panel, panel will update the filter
+ mPanelMainInventory->getPanel()->setShowFolderState(getCheckShowEmpty() ?
+ LLInventoryFilter::SHOW_ALL_FOLDERS : LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
+ mPanelMainInventory->getPanel()->setFilterTypes(filter);
+ if (getCheckSinceLogoff())
+ {
+ mSpinSinceDays->set(0);
+ mSpinSinceHours->set(0);
+ }
+ U32 days = (U32)mSpinSinceDays->get();
+ U32 hours = (U32)mSpinSinceHours->get();
+ if (hours > 24)
+ {
+ days += hours / 24;
+ hours = (U32)hours % 24;
+ mSpinSinceDays->set((F32)days);
+ mSpinSinceHours->set((F32)hours);
+ }
+ hours += days * 24;
+ mPanelMainInventory->getPanel()->setHoursAgo(hours);
+ mPanelMainInventory->getPanel()->setSinceLogoff(getCheckSinceLogoff());
+ mPanelMainInventory->setFilterTextFromFilter();
+
+ LLPanel::draw();
+}
+
+BOOL LLFloaterInventoryFinder::getCheckShowEmpty()
+{
+ return childGetValue("check_show_empty");
+}
+
+BOOL LLFloaterInventoryFinder::getCheckSinceLogoff()
+{
+ return childGetValue("check_since_logoff");
+}
+
+void LLFloaterInventoryFinder::onCloseBtn(void* user_data)
+{
+ LLFloaterInventoryFinder* finderp = (LLFloaterInventoryFinder*)user_data;
+ finderp->closeFloater();
+}
+
+// static
+void LLFloaterInventoryFinder::selectAllTypes(void* user_data)
+{
+ LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data;
+ if(!self) return;
+
+ self->childSetValue("check_animation", TRUE);
+ self->childSetValue("check_calling_card", TRUE);
+ self->childSetValue("check_clothing", TRUE);
+ self->childSetValue("check_gesture", TRUE);
+ self->childSetValue("check_landmark", TRUE);
+ self->childSetValue("check_notecard", TRUE);
+ self->childSetValue("check_object", TRUE);
+ self->childSetValue("check_script", TRUE);
+ self->childSetValue("check_sound", TRUE);
+ self->childSetValue("check_texture", TRUE);
+ self->childSetValue("check_snapshot", TRUE);
+}
+
+//static
+void LLFloaterInventoryFinder::selectNoTypes(void* user_data)
+{
+ LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data;
+ if(!self) return;
+
+ self->childSetValue("check_animation", FALSE);
+ self->childSetValue("check_calling_card", FALSE);
+ self->childSetValue("check_clothing", FALSE);
+ self->childSetValue("check_gesture", FALSE);
+ self->childSetValue("check_landmark", FALSE);
+ self->childSetValue("check_notecard", FALSE);
+ self->childSetValue("check_object", FALSE);
+ self->childSetValue("check_script", FALSE);
+ self->childSetValue("check_sound", FALSE);
+ self->childSetValue("check_texture", FALSE);
+ self->childSetValue("check_snapshot", FALSE);
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// List Commands //
+
+void LLPanelMainInventory::initListCommandsHandlers()
+{
+ mListCommands = getChild<LLPanel>("bottom_panel");
+
+ mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelMainInventory::onGearButtonClick, this));
+ mListCommands->childSetAction("trash_btn", boost::bind(&LLPanelMainInventory::onTrashButtonClick, this));
+ mListCommands->childSetAction("add_btn", boost::bind(&LLPanelMainInventory::onAddButtonClick, this));
+
+ LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>("trash_btn");
+ trash_btn->setDragAndDropHandler(boost::bind(&LLPanelMainInventory::handleDragAndDropToTrash, this
+ , _4 // BOOL drop
+ , _5 // EDragAndDropType cargo_type
+ , _7 // EAcceptance* accept
+ ));
+
+ mCommitCallbackRegistrar.add("Inventory.GearDefault.Custom.Action", boost::bind(&LLPanelMainInventory::onCustomAction, this, _2));
+ mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));
+ mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+}
+
+void LLPanelMainInventory::updateListCommands()
+{
+ bool trash_enabled = isActionEnabled("delete");
+
+ mListCommands->childSetEnabled("trash_btn", trash_enabled);
+}
+
+void LLPanelMainInventory::onGearButtonClick()
+{
+ showActionMenu(mMenuGearDefault,"options_gear_btn");
+}
+
+void LLPanelMainInventory::onAddButtonClick()
+{
+ setUploadCostIfNeeded();
+
+ showActionMenu(mMenuAdd,"add_btn");
+}
+
+void LLPanelMainInventory::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
+{
+ if (menu)
+ {
+ menu->buildDrawLabels();
+ menu->updateParent(LLMenuGL::sMenuContainer);
+ LLView* spawning_view = getChild<LLView> (spawning_view_name);
+ S32 menu_x, menu_y;
+ //show menu in co-ordinates of panel
+ spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this);
+ menu_y += menu->getRect().getHeight();
+ LLMenuGL::showPopup(this, menu, menu_x, menu_y);
+ }
+}
+
+void LLPanelMainInventory::onTrashButtonClick()
+{
+ onClipboardAction("delete");
+}
+
+void LLPanelMainInventory::onClipboardAction(const LLSD& userdata)
+{
+ std::string command_name = userdata.asString();
+ getActivePanel()->getRootFolder()->doToSelected(getActivePanel()->getModel(),command_name);
+}
+
+void LLPanelMainInventory::saveTexture(const LLSD& userdata)
+{
+ LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
+ if (!current_item)
+ {
+ return;
+ }
+
+ const LLUUID& item_id = current_item->getListener()->getUUID();
+ LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", LLSD(item_id), TAKE_FOCUS_YES);
+ if (preview_texture)
+ {
+ preview_texture->openToSave();
+ }
+}
+
+void LLPanelMainInventory::onCustomAction(const LLSD& userdata)
+{
+ if (!isActionEnabled(userdata))
+ return;
+
+ const std::string command_name = userdata.asString();
+ if (command_name == "new_window")
+ {
+ newWindow();
+ }
+ if (command_name == "sort_by_name")
+ {
+ const LLSD arg = "name";
+ setSortBy(arg);
+ }
+ if (command_name == "sort_by_recent")
+ {
+ const LLSD arg = "date";
+ setSortBy(arg);
+ }
+ if (command_name == "show_filters")
+ {
+ toggleFindOptions();
+ }
+ if (command_name == "reset_filters")
+ {
+ resetFilters();
+ }
+ if (command_name == "close_folders")
+ {
+ closeAllFolders();
+ }
+ if (command_name == "empty_trash")
+ {
+ const std::string notification = "ConfirmEmptyTrash";
+ gInventory.emptyFolderType(notification, LLFolderType::FT_TRASH);
+ }
+ if (command_name == "empty_lostnfound")
+ {
+ const std::string notification = "ConfirmEmptyLostAndFound";
+ gInventory.emptyFolderType(notification, LLFolderType::FT_LOST_AND_FOUND);
+ }
+ if (command_name == "save_texture")
+ {
+ saveTexture(userdata);
+ }
+ // This doesn't currently work, since the viewer can't change an assetID an item.
+ if (command_name == "regenerate_link")
+ {
+ LLInventoryPanel *active_panel = getActivePanel();
+ LLFolderViewItem* current_item = active_panel->getRootFolder()->getCurSelectedItem();
+ if (!current_item)
+ {
+ return;
+ }
+ const LLUUID item_id = current_item->getListener()->getUUID();
+ LLViewerInventoryItem *item = gInventory.getItem(item_id);
+ item->regenerateLink();
+ active_panel->setSelection(item_id, TAKE_FOCUS_NO);
+ }
+ if (command_name == "find_original")
+ {
+ LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
+ if (!current_item)
+ {
+ return;
+ }
+ current_item->getListener()->performAction(getActivePanel()->getRootFolder(), getActivePanel()->getModel(), "goto");
+ }
+
+ if (command_name == "find_links")
+ {
+ LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
+ if (!current_item)
+ {
+ return;
+ }
+ const LLUUID& item_id = current_item->getListener()->getUUID();
+ const std::string &item_name = current_item->getListener()->getName();
+ mFilterSubString = item_name;
+ LLInventoryFilter *filter = mActivePanel->getFilter();
+ filter->setFilterSubString(item_name);
+ mFilterEditor->setText(item_name);
+
+ mFilterEditor->setFocus(TRUE);
+ filter->setFilterUUID(item_id);
+ filter->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
+ }
+}
+
+bool LLPanelMainInventory::isSaveTextureEnabled(const LLSD& userdata)
+{
+ LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
+ if (current_item)
+ {
+ LLViewerInventoryItem *inv_item = current_item->getInventoryItem();
+ if(inv_item)
+ {
+ bool can_save = inv_item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED);
+ LLInventoryType::EType curr_type = current_item->getListener()->getInventoryType();
+ return can_save && (curr_type == LLInventoryType::IT_TEXTURE || curr_type == LLInventoryType::IT_SNAPSHOT);
+ }
+ }
+ return false;
+}
+
+BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)
+{
+ const std::string command_name = userdata.asString();
+ if (command_name == "delete")
+ {
+ BOOL can_delete = FALSE;
+ LLFolderView *folder = getActivePanel()->getRootFolder();
+ if (folder)
+ {
+ can_delete = TRUE;
+ std::set<LLUUID> selection_set;
+ folder->getSelectionList(selection_set);
+ if (selection_set.empty()) return FALSE;
+ for (std::set<LLUUID>::iterator iter = selection_set.begin();
+ iter != selection_set.end();
+ ++iter)
+ {
+ const LLUUID &item_id = (*iter);
+ LLFolderViewItem *item = folder->getItemByID(item_id);
+ can_delete &= item->getListener()->isItemRemovable();
+ }
+ return can_delete;
+ }
+ return FALSE;
+ }
+ if (command_name == "save_texture")
+ {
+ return isSaveTextureEnabled(userdata);
+ }
+ if (command_name == "find_original")
+ {
+ LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
+ if (!current_item) return FALSE;
+ const LLUUID& item_id = current_item->getListener()->getUUID();
+ const LLViewerInventoryItem *item = gInventory.getItem(item_id);
+ if (item && item->getIsLinkType() && !item->getIsBrokenLink())
+ {
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ if (command_name == "find_links")
+ {
+ LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
+ if (!current_item) return FALSE;
+ const LLUUID& item_id = current_item->getListener()->getUUID();
+ const LLInventoryObject *obj = gInventory.getObject(item_id);
+ if (obj && !obj->getIsLinkType() && LLAssetType::lookupCanLink(obj->getType()))
+ {
+ return TRUE;
+ }
+ return FALSE;
+ }
+ // This doesn't currently work, since the viewer can't change an assetID an item.
+ if (command_name == "regenerate_link")
+ {
+ LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
+ if (!current_item) return FALSE;
+ const LLUUID& item_id = current_item->getListener()->getUUID();
+ const LLViewerInventoryItem *item = gInventory.getItem(item_id);
+ if (item && item->getIsBrokenLink())
+ {
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+bool LLPanelMainInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept)
+{
+ *accept = ACCEPT_NO;
+
+ const bool is_enabled = isActionEnabled("delete");
+ if (is_enabled) *accept = ACCEPT_YES_MULTI;
+
+ if (is_enabled && drop)
+ {
+ onClipboardAction("delete");
+ }
+ return true;
+}
+
+void LLPanelMainInventory::setUploadCostIfNeeded()
+{
+ // *NOTE dzaporozhan
+ // Upload cost is set in process_economy_data() (llviewermessage.cpp). But since we
+ // have two instances of Inventory panel at the moment(and two instances of context menu),
+ // call to gMenuHolder->childSetLabelArg() sets upload cost only for one of the instances.
+
+ if(mNeedUploadCost && mMenuAdd)
+ {
+ LLMenuItemBranchGL* upload_menu = mMenuAdd->findChild<LLMenuItemBranchGL>("upload");
+ if(upload_menu)
+ {
+ S32 upload_cost = -1;//LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
+ std::string cost_str;
+
+ // getPriceUpload() returns -1 if no data available yet.
+ if(upload_cost >= 0)
+ {
+ mNeedUploadCost = false;
+ cost_str = llformat("%d", upload_cost);
+ }
+ else
+ {
+ cost_str = llformat("%d", gSavedSettings.getU32("DefaultUploadCost"));
+ }
+
+ upload_menu->getChild<LLView>("Upload Image")->setLabelArg("[COST]", cost_str);
+ upload_menu->getChild<LLView>("Upload Sound")->setLabelArg("[COST]", cost_str);
+ upload_menu->getChild<LLView>("Upload Animation")->setLabelArg("[COST]", cost_str);
+ upload_menu->getChild<LLView>("Bulk Upload")->setLabelArg("[COST]", cost_str);
+ }
+ }
+}
+
+// List Commands //
+////////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
new file mode 100644
index 0000000000..d9ea0da2da
--- /dev/null
+++ b/indra/newview/llpanelmaininventory.h
@@ -0,0 +1,159 @@
+/**
+ * @file llpanelmaininventory.h
+ * @brief llpanelmaininventory.h
+ * class definition
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELMAININVENTORY_H
+#define LL_LLPANELMAININVENTORY_H
+
+#include "llpanel.h"
+#include "llinventoryobserver.h"
+
+#include "llfolderview.h"
+
+class LLFolderViewItem;
+class LLInventoryPanel;
+class LLSaveFolderState;
+class LLFilterEditor;
+class LLTabContainer;
+class LLFloaterInventoryFinder;
+class LLMenuGL;
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLPanelMainInventory
+//
+// This is a panel used to view and control an agent's inventory,
+// including all the fixin's (e.g. AllItems/RecentItems tabs, filter floaters).
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLPanelMainInventory : public LLPanel, LLInventoryObserver
+{
+public:
+ friend class LLFloaterInventoryFinder;
+
+ LLPanelMainInventory();
+ ~LLPanelMainInventory();
+
+ BOOL postBuild();
+
+ virtual BOOL handleKeyHere(KEY key, MASK mask);
+
+ // Inherited functionality
+ /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg);
+ /*virtual*/ void changed(U32);
+ /*virtual*/ void draw();
+
+ LLInventoryPanel* getPanel() { return mActivePanel; }
+ LLInventoryPanel* getActivePanel() { return mActivePanel; }
+ const LLInventoryPanel* getActivePanel() const { return mActivePanel; }
+
+ const std::string& getFilterText() const { return mFilterText; }
+
+ void setSelectCallback(const LLFolderView::signal_t::slot_type& cb);
+
+protected:
+ //
+ // Misc functions
+ //
+ void setFilterTextFromFilter();
+ void startSearch();
+
+ void toggleFindOptions();
+ void onSelectionChange(LLInventoryPanel *panel, const std::deque<LLFolderViewItem*>& items, BOOL user_action);
+
+ static BOOL filtersVisible(void* user_data);
+ void onClearSearch();
+ static void onFoldersByName(void *user_data);
+ static BOOL checkFoldersByName(void *user_data);
+ void onFilterEdit(const std::string& search_string );
+ static BOOL incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward);
+ void onFilterSelected();
+
+ const std::string getFilterSubString();
+ void setFilterSubString(const std::string& string);
+
+ // menu callbacks
+ void doToSelected(const LLSD& userdata);
+ void closeAllFolders();
+ void newWindow();
+ void doCreate(const LLSD& userdata);
+ void resetFilters();
+ void setSortBy(const LLSD& userdata);
+ void saveTexture(const LLSD& userdata);
+ bool isSaveTextureEnabled(const LLSD& userdata);
+
+private:
+ LLFloaterInventoryFinder* getFinder();
+
+ LLFilterEditor* mFilterEditor;
+ LLTabContainer* mFilterTabs;
+ LLHandle<LLFloater> mFinderHandle;
+ LLInventoryPanel* mActivePanel;
+ LLSaveFolderState* mSavedFolderState;
+ std::string mFilterText;
+ std::string mFilterSubString;
+
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // List Commands //
+protected:
+ void initListCommandsHandlers();
+ void updateListCommands();
+ void onGearButtonClick();
+ void onAddButtonClick();
+ void showActionMenu(LLMenuGL* menu, std::string spawning_view_name);
+ void onTrashButtonClick();
+ void onClipboardAction(const LLSD& userdata);
+ BOOL isActionEnabled(const LLSD& command_name);
+ void onCustomAction(const LLSD& command_name);
+ bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);
+ /**
+ * Set upload cost in "Upload" sub menu.
+ */
+ void setUploadCostIfNeeded();
+private:
+ LLPanel* mListCommands;
+ LLMenuGL* mMenuGearDefault;
+ LLMenuGL* mMenuAdd;
+
+ bool mNeedUploadCost;
+ // List Commands //
+ ////////////////////////////////////////////////////////////////////////////////
+};
+
+#endif // LL_LLPANELMAININVENTORY_H
+
+
+
diff --git a/indra/newview/llpanelme.cpp b/indra/newview/llpanelme.cpp
new file mode 100644
index 0000000000..0f0fb4b94e
--- /dev/null
+++ b/indra/newview/llpanelme.cpp
@@ -0,0 +1,271 @@
+/**
+ * @file llpanelme.cpp
+ * @brief Side tray "Me" (My Profile) panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelprofile.h"
+#include "llavatarconstants.h"
+#include "llpanelme.h"
+#include "llagent.h"
+#include "llagentwearables.h"
+#include "lliconctrl.h"
+#include "llsidetray.h"
+#include "lltabcontainer.h"
+#include "lltexturectrl.h"
+
+#define PICKER_SECOND_LIFE "2nd_life_pic"
+#define PICKER_FIRST_LIFE "real_world_pic"
+#define PANEL_PROFILE "panel_profile"
+
+static LLRegisterPanelClassWrapper<LLPanelMyProfileEdit> t_panel_me_profile_edit("edit_profile_panel");
+static LLRegisterPanelClassWrapper<LLPanelMe> t_panel_me_profile("panel_me");
+
+LLPanelMe::LLPanelMe(void)
+ : LLPanelProfile()
+ , mEditPanel(NULL)
+{
+ setAvatarId(gAgent.getID());
+}
+
+BOOL LLPanelMe::postBuild()
+{
+ LLPanelProfile::postBuild();
+
+ getTabContainer()[PANEL_PROFILE]->childSetAction("edit_profile_btn", boost::bind(&LLPanelMe::onEditProfileClicked, this), this);
+ getTabContainer()[PANEL_PROFILE]->childSetAction("edit_appearance_btn", boost::bind(&LLPanelMe::onEditAppearanceClicked, this), this);
+
+ return TRUE;
+}
+
+void LLPanelMe::onOpen(const LLSD& key)
+{
+ LLPanelProfile::onOpen(key);
+}
+
+bool LLPanelMe::notifyChildren(const LLSD& info)
+{
+ if (info.has("task-panel-action") && info["task-panel-action"].asString() == "handle-tri-state")
+ {
+ // Implement task panel tri-state behavior.
+ //
+ // When the button of an active open task panel is clicked, side tray
+ // calls notifyChildren() on the panel, passing task-panel-action=>handle-tri-state as an argument.
+ // The task panel is supposed to handle this by reverting to the default view,
+ // i.e. closing any dependent panels like "pick info" or "profile edit".
+
+ bool on_default_view = true;
+
+ const LLRect& task_panel_rect = getRect();
+ for (LLView* child = getFirstChild(); child; child = findNextSibling(child))
+ {
+ LLPanel* panel = dynamic_cast<LLPanel*>(child);
+ if (!panel)
+ continue;
+
+ // *HACK: implement panel stack instead (e.g. me->pick_info->pick_edit).
+ if (panel->getRect().getWidth() == task_panel_rect.getWidth() &&
+ panel->getRect().getHeight() == task_panel_rect.getHeight() &&
+ panel->getVisible())
+ {
+ panel->setVisible(FALSE);
+ on_default_view = false;
+ }
+ }
+
+ if (on_default_view)
+ LLSideTray::getInstance()->collapseSideBar();
+
+ return true; // this notification is only supposed to be handled by task panels
+ }
+
+ return LLPanel::notifyChildren(info);
+}
+
+void LLPanelMe::buildEditPanel()
+{
+ if (NULL == mEditPanel)
+ {
+ mEditPanel = new LLPanelMyProfileEdit();
+ mEditPanel->childSetAction("save_btn", boost::bind(&LLPanelMe::onSaveChangesClicked, this), this);
+ mEditPanel->childSetAction("cancel_btn", boost::bind(&LLPanelMe::onCancelClicked, this), this);
+ }
+}
+
+
+void LLPanelMe::onEditProfileClicked()
+{
+ buildEditPanel();
+ togglePanel(mEditPanel, getAvatarId()); // open
+}
+
+void LLPanelMe::onEditAppearanceClicked()
+{
+ if (gAgentWearables.areWearablesLoaded())
+ {
+ gAgent.changeCameraToCustomizeAvatar();
+ }
+}
+
+void LLPanelMe::onSaveChangesClicked()
+{
+ LLAvatarData data = LLAvatarData();
+ data.avatar_id = gAgent.getID();
+ data.image_id = mEditPanel->getChild<LLTextureCtrl>(PICKER_SECOND_LIFE)->getImageAssetID();
+ data.fl_image_id = mEditPanel->getChild<LLTextureCtrl>(PICKER_FIRST_LIFE)->getImageAssetID();
+ data.about_text = mEditPanel->childGetValue("sl_description_edit").asString();
+ data.fl_about_text = mEditPanel->childGetValue("fl_description_edit").asString();
+ data.profile_url = mEditPanel->childGetValue("homepage_edit").asString();
+ data.allow_publish = mEditPanel->childGetValue("show_in_search_checkbox");
+
+ LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesUpdate(&data);
+ togglePanel(mEditPanel); // close
+ onOpen(getAvatarId());
+}
+
+void LLPanelMe::onCancelClicked()
+{
+ togglePanel(mEditPanel); // close
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLPanelMyProfileEdit::LLPanelMyProfileEdit()
+ : LLPanelMyProfile()
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_edit_profile.xml");
+
+ setAvatarId(gAgent.getID());
+}
+
+void LLPanelMyProfileEdit::onOpen(const LLSD& key)
+{
+ resetData();
+
+ // Disable editing until data is loaded, or edited fields will be overwritten when data
+ // is loaded.
+ enableEditing(false);
+ LLPanelMyProfile::onOpen(getAvatarId());
+}
+
+void LLPanelMyProfileEdit::processProperties(void* data, EAvatarProcessorType type)
+{
+ if(APT_PROPERTIES == type)
+ {
+ const LLAvatarData* avatar_data = static_cast<const LLAvatarData*>(data);
+ if(avatar_data && getAvatarId() == avatar_data->avatar_id)
+ {
+ // *TODO dzaporozhan
+ // Workaround for ticket EXT-1099, waiting for fix for ticket EXT-1128
+ enableEditing(true);
+ processProfileProperties(avatar_data);
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this);
+ }
+ }
+}
+
+void LLPanelMyProfileEdit::processProfileProperties(const LLAvatarData* avatar_data)
+{
+ fillCommonData(avatar_data);
+
+ fillPartnerData(avatar_data);
+
+ fillAccountStatus(avatar_data);
+
+ childSetValue("show_in_search_checkbox", (BOOL)(avatar_data->flags & AVATAR_ALLOW_PUBLISH));
+
+ std::string first, last;
+ BOOL found = gCacheName->getName(avatar_data->avatar_id, first, last);
+ if (found)
+ {
+ childSetTextArg("name_text", "[FIRST]", first);
+ childSetTextArg("name_text", "[LAST]", last);
+ }
+}
+
+BOOL LLPanelMyProfileEdit::postBuild()
+{
+ initTexturePickerMouseEvents();
+
+ childSetTextArg("partner_edit_link", "[URL]", getString("partner_edit_link_url"));
+ childSetTextArg("my_account_link", "[URL]", getString("my_account_link_url"));
+
+ return LLPanelAvatarProfile::postBuild();
+}
+/**
+ * Inits map with texture picker and appropriate edit icon.
+ * Sets callbacks of Mouse Enter and Mouse Leave signals of Texture Pickers
+ */
+void LLPanelMyProfileEdit::initTexturePickerMouseEvents()
+{
+ LLTextureCtrl* text_pic = getChild<LLTextureCtrl>(PICKER_SECOND_LIFE);
+ LLIconCtrl* text_icon = getChild<LLIconCtrl>("2nd_life_edit_icon");
+ mTextureEditIconMap[text_pic->getName()] = text_icon;
+ text_pic->setMouseEnterCallback(boost::bind(&LLPanelMyProfileEdit::onTexturePickerMouseEnter, this, _1));
+ text_pic->setMouseLeaveCallback(boost::bind(&LLPanelMyProfileEdit::onTexturePickerMouseLeave, this, _1));
+ text_icon->setVisible(FALSE);
+
+ text_pic = getChild<LLTextureCtrl>(PICKER_FIRST_LIFE);
+ text_icon = getChild<LLIconCtrl>("real_world_edit_icon");
+ mTextureEditIconMap[text_pic->getName()] = text_icon;
+ text_pic->setMouseEnterCallback(boost::bind(&LLPanelMyProfileEdit::onTexturePickerMouseEnter, this, _1));
+ text_pic->setMouseLeaveCallback(boost::bind(&LLPanelMyProfileEdit::onTexturePickerMouseLeave, this, _1));
+ text_icon->setVisible(FALSE);
+}
+
+void LLPanelMyProfileEdit::resetData()
+{
+ LLPanelMyProfile::resetData();
+
+ childSetTextArg("name_text", "[FIRST]", LLStringUtil::null);
+ childSetTextArg("name_text", "[LAST]", LLStringUtil::null);
+}
+
+void LLPanelMyProfileEdit::onTexturePickerMouseEnter(LLUICtrl* ctrl)
+{
+ mTextureEditIconMap[ctrl->getName()]->setVisible(TRUE);
+}
+void LLPanelMyProfileEdit::onTexturePickerMouseLeave(LLUICtrl* ctrl)
+{
+ mTextureEditIconMap[ctrl->getName()]->setVisible(FALSE);
+}
+
+void LLPanelMyProfileEdit::enableEditing(bool enable)
+{
+ childSetEnabled("2nd_life_pic", enable);
+ childSetEnabled("real_world_pic", enable);
+ childSetEnabled("sl_description_edit", enable);
+ childSetEnabled("fl_description_edit", enable);
+ childSetEnabled("homepage_edit", enable);
+ childSetEnabled("show_in_search_checkbox", enable);
+}
diff --git a/indra/newview/llpanelme.h b/indra/newview/llpanelme.h
new file mode 100644
index 0000000000..1325192bbf
--- /dev/null
+++ b/indra/newview/llpanelme.h
@@ -0,0 +1,111 @@
+/**
+ * @file llpanelme.h
+ * @brief Side tray "Me" (My Profile) panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELMEPROFILE_H
+#define LL_LLPANELMEPROFILE_H
+
+#include "llpanel.h"
+#include "llpanelavatar.h"
+
+class LLPanelMyProfileEdit;
+class LLPanelProfile;
+class LLIconCtrl;
+
+/**
+* Panel for displaying Agent's profile, it consists of two sub panels - Profile
+* and Picks.
+* LLPanelMe allows user to edit his profile and picks.
+*/
+class LLPanelMe : public LLPanelProfile
+{
+ LOG_CLASS(LLPanelMe);
+
+public:
+
+ LLPanelMe();
+
+ /*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ bool notifyChildren(const LLSD& info);
+
+ /*virtual*/ BOOL postBuild();
+
+private:
+
+ void buildEditPanel();
+
+ void onEditProfileClicked();
+ void onEditAppearanceClicked();
+ void onSaveChangesClicked();
+ void onCancelClicked();
+
+ LLPanelMyProfileEdit * mEditPanel;
+
+};
+
+class LLPanelMyProfileEdit : public LLPanelMyProfile
+{
+ LOG_CLASS(LLPanelMyProfileEdit);
+
+public:
+
+ LLPanelMyProfileEdit();
+
+ /*virtual*/void processProperties(void* data, EAvatarProcessorType type);
+
+ /*virtual*/BOOL postBuild();
+
+ /*virtual*/ void onOpen(const LLSD& key);
+
+protected:
+
+ /*virtual*/void resetData();
+
+ void processProfileProperties(const LLAvatarData* avatar_data);
+
+private:
+ void initTexturePickerMouseEvents();
+ void onTexturePickerMouseEnter(LLUICtrl* ctrl);
+ void onTexturePickerMouseLeave(LLUICtrl* ctrl);
+
+ /**
+ * Enabled/disables controls to prevent overwriting edited data upon receiving
+ * current data from server.
+ */
+ void enableEditing(bool enable);
+
+private:
+ // map TexturePicker name => Edit Icon pointer should be visible while hovering Texture Picker
+ typedef std::map<std::string, LLIconCtrl*> texture_edit_icon_map_t;
+ texture_edit_icon_map_t mTextureEditIconMap;
+};
+
+#endif // LL_LLPANELMEPROFILE_H
diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp
new file mode 100644
index 0000000000..f574f55beb
--- /dev/null
+++ b/indra/newview/llpanelmediasettingsgeneral.cpp
@@ -0,0 +1,520 @@
+/**
+ * @file llpanelmediasettingsgeneral.cpp
+ * @brief LLPanelMediaSettingsGeneral class implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelmediasettingsgeneral.h"
+
+// library includes
+#include "llcombobox.h"
+#include "llcheckboxctrl.h"
+#include "llnotificationsutil.h"
+#include "llspinctrl.h"
+#include "lluictrlfactory.h"
+
+// project includes
+#include "llagent.h"
+#include "llviewerwindow.h"
+#include "llviewermedia.h"
+#include "llsdutil.h"
+#include "llselectmgr.h"
+#include "llbutton.h"
+#include "lltexturectrl.h"
+#include "llurl.h"
+#include "llwindow.h"
+#include "llmediaentry.h"
+#include "llmediactrl.h"
+#include "llpanelcontents.h"
+#include "llpermissions.h"
+#include "llpluginclassmedia.h"
+#include "llfloatermediasettings.h"
+#include "llfloatertools.h"
+#include "lltrans.h"
+#include "lltextbox.h"
+#include "llpanelmediasettingssecurity.h"
+
+const char *CHECKERBOARD_DATA_URL = "data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%22100%%22 height=%22100%%22 %3E%3Cdefs%3E%3Cpattern id=%22checker%22 patternUnits=%22userSpaceOnUse%22 x=%220%22 y=%220%22 width=%22128%22 height=%22128%22 viewBox=%220 0 128 128%22 %3E%3Crect x=%220%22 y=%220%22 width=%2264%22 height=%2264%22 fill=%22#ddddff%22 /%3E%3Crect x=%2264%22 y=%2264%22 width=%2264%22 height=%2264%22 fill=%22#ddddff%22 /%3E%3C/pattern%3E%3C/defs%3E%3Crect x=%220%22 y=%220%22 width=%22100%%22 height=%22100%%22 fill=%22url(#checker)%22 /%3E%3C/svg%3E";
+
+////////////////////////////////////////////////////////////////////////////////
+//
+LLPanelMediaSettingsGeneral::LLPanelMediaSettingsGeneral() :
+ mAutoLoop( NULL ),
+ mFirstClick( NULL ),
+ mAutoZoom( NULL ),
+ mAutoPlay( NULL ),
+ mAutoScale( NULL ),
+ mWidthPixels( NULL ),
+ mHeightPixels( NULL ),
+ mHomeURL( NULL ),
+ mCurrentURL( NULL ),
+ mParent( NULL ),
+ mMediaEditable(false)
+{
+ // build dialog from XML
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_general.xml");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLPanelMediaSettingsGeneral::postBuild()
+{
+ // connect member vars with UI widgets
+ mAutoLoop = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_LOOP_KEY );
+ mAutoPlay = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_PLAY_KEY );
+ mAutoScale = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_SCALE_KEY );
+ mAutoZoom = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_ZOOM_KEY );
+ mCurrentURL = getChild< LLTextBox >( LLMediaEntry::CURRENT_URL_KEY );
+ mFirstClick = getChild< LLCheckBoxCtrl >( LLMediaEntry::FIRST_CLICK_INTERACT_KEY );
+ mHeightPixels = getChild< LLSpinCtrl >( LLMediaEntry::HEIGHT_PIXELS_KEY );
+ mHomeURL = getChild< LLLineEditor >( LLMediaEntry::HOME_URL_KEY );
+ mWidthPixels = getChild< LLSpinCtrl >( LLMediaEntry::WIDTH_PIXELS_KEY );
+ mPreviewMedia = getChild<LLMediaCtrl>("preview_media");
+ mFailWhiteListText = getChild<LLTextBox>( "home_fails_whitelist_label" );
+
+ // watch commit action for HOME URL
+ childSetCommitCallback( LLMediaEntry::HOME_URL_KEY, onCommitHomeURL, this);
+ childSetCommitCallback( "current_url_reset_btn",onBtnResetCurrentUrl, this);
+
+ // interrogates controls and updates widgets as required
+ updateMediaPreview();
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+LLPanelMediaSettingsGeneral::~LLPanelMediaSettingsGeneral()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsGeneral::draw()
+{
+ // housekeeping
+ LLPanel::draw();
+
+ // TODO: we need to call this repeatedly until the floater panels are fully
+ // created but once we have a valid answer, we should stop looking here - the
+ // commit callback will handle it
+ checkHomeUrlPassesWhitelist();
+
+ // enable/disable pixel values image entry based on auto scale checkbox
+ if ( mAutoScale->getValue().asBoolean() == false )
+ {
+ childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, true );
+ childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, true );
+ }
+ else
+ {
+ childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, false );
+ childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, false );
+ };
+
+ // enable/disable UI based on type of media
+ bool reset_button_is_active = true;
+ if( mPreviewMedia )
+ {
+ LLPluginClassMedia* media_plugin = mPreviewMedia->getMediaPlugin();
+ if( media_plugin )
+ {
+ // turn off volume (if we can) for preview. Note: this really only
+ // works for QuickTime movies right now - no way to control the
+ // volume of a flash app embedded in a page for example
+ media_plugin->setVolume( 0 );
+
+ // some controls are only appropriate for time or browser type plugins
+ // so we selectively enable/disable them - need to do it in draw
+ // because the information from plugins arrives assynchronously
+ bool show_time_controls = media_plugin->pluginSupportsMediaTime();
+ if ( show_time_controls )
+ {
+ childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, false );
+ reset_button_is_active = false;
+ childSetEnabled( "current_url_label", false );
+ childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, true );
+ }
+ else
+ {
+ childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, true );
+ reset_button_is_active = true;
+ childSetEnabled( "current_url_label", true );
+ childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, false );
+ };
+ };
+ };
+
+ // current URL can change over time, update it here
+ updateCurrentUrl();
+
+ LLPermissions perm;
+ bool user_can_press_reset = mMediaEditable;
+
+ // several places modify this widget so we must collect states in one place
+ if ( reset_button_is_active )
+ {
+ // user has perms to press reset button and it is active
+ if ( user_can_press_reset )
+ {
+ childSetEnabled( "current_url_reset_btn", true );
+ }
+ // user does not has perms to press reset button and it is active
+ else
+ {
+ childSetEnabled( "current_url_reset_btn", false );
+ };
+ }
+ else
+ // reset button is inactive so we just slam it to off - other states don't matter
+ {
+ childSetEnabled( "current_url_reset_btn", false );
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsGeneral::clearValues( void* userdata, bool editable)
+{
+ LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
+ self->mAutoLoop->clear();
+ self->mAutoPlay->clear();
+ self->mAutoScale->clear();
+ self->mAutoZoom ->clear();
+ self->mCurrentURL->clear();
+ self->mFirstClick->clear();
+ self->mHeightPixels->clear();
+ self->mHomeURL->clear();
+ self->mWidthPixels->clear();
+ self->mAutoLoop ->setEnabled(editable);
+ self->mAutoPlay ->setEnabled(editable);
+ self->mAutoScale ->setEnabled(editable);
+ self->mAutoZoom ->setEnabled(editable);
+ self->mCurrentURL ->setEnabled(editable);
+ self->mFirstClick ->setEnabled(editable);
+ self->mHeightPixels ->setEnabled(editable);
+ self->mHomeURL ->setEnabled(editable);
+ self->mWidthPixels ->setEnabled(editable);
+ self->updateMediaPreview();
+}
+
+// static
+bool LLPanelMediaSettingsGeneral::isMultiple()
+{
+ // IF all the faces have media (or all dont have media)
+ if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo )
+ {
+ if(LLFloaterMediaSettings::getInstance()->mMultipleMedia)
+ {
+ return true;
+ }
+
+ }
+ else
+ {
+ if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& media_settings ,bool editable)
+{
+ LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
+ self->mMediaEditable = editable;
+
+ if ( LLPanelMediaSettingsGeneral::isMultiple() )
+ {
+ self->clearValues(self, self->mMediaEditable);
+ // only show multiple
+ self->mHomeURL->setText(LLTrans::getString("Multiple Media"));
+ self->mCurrentURL->setText(LLTrans::getString("Multiple Media"));
+ return;
+ }
+
+ std::string base_key( "" );
+ std::string tentative_key( "" );
+
+ struct
+ {
+ std::string key_name;
+ LLUICtrl* ctrl_ptr;
+ std::string ctrl_type;
+
+ } data_set [] =
+ {
+ { LLMediaEntry::AUTO_LOOP_KEY, self->mAutoLoop, "LLCheckBoxCtrl" },
+ { LLMediaEntry::AUTO_PLAY_KEY, self->mAutoPlay, "LLCheckBoxCtrl" },
+ { LLMediaEntry::AUTO_SCALE_KEY, self->mAutoScale, "LLCheckBoxCtrl" },
+ { LLMediaEntry::AUTO_ZOOM_KEY, self->mAutoZoom, "LLCheckBoxCtrl" },
+ { LLMediaEntry::CURRENT_URL_KEY, self->mCurrentURL, "LLTextBox" },
+ { LLMediaEntry::HEIGHT_PIXELS_KEY, self->mHeightPixels, "LLSpinCtrl" },
+ { LLMediaEntry::HOME_URL_KEY, self->mHomeURL, "LLLineEditor" },
+ { LLMediaEntry::FIRST_CLICK_INTERACT_KEY, self->mFirstClick, "LLCheckBoxCtrl" },
+ { LLMediaEntry::WIDTH_PIXELS_KEY, self->mWidthPixels, "LLSpinCtrl" },
+ { "", NULL , "" }
+ };
+
+ for( int i = 0; data_set[ i ].key_name.length() > 0; ++i )
+ {
+ base_key = std::string( data_set[ i ].key_name );
+ tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX );
+ // TODO: CP - I bet there is a better way to do this using Boost
+ if ( media_settings[ base_key ].isDefined() )
+ {
+ if ( data_set[ i ].ctrl_type == "LLLineEditor" )
+ {
+ static_cast< LLLineEditor* >( data_set[ i ].ctrl_ptr )->
+ setText( media_settings[ base_key ].asString() );
+ }
+ else
+ if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" )
+ static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )->
+ setValue( media_settings[ base_key ].asBoolean() );
+ else
+ if ( data_set[ i ].ctrl_type == "LLComboBox" )
+ static_cast< LLComboBox* >( data_set[ i ].ctrl_ptr )->
+ setCurrentByIndex( media_settings[ base_key ].asInteger() );
+ else
+ if ( data_set[ i ].ctrl_type == "LLSpinCtrl" )
+ static_cast< LLSpinCtrl* >( data_set[ i ].ctrl_ptr )->
+ setValue( media_settings[ base_key ].asInteger() );
+
+ data_set[ i ].ctrl_ptr->setEnabled(self->mMediaEditable);
+ data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
+ };
+ };
+
+ // interrogates controls and updates widgets as required
+ self->updateMediaPreview();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Helper to set media control to media URL as required
+void LLPanelMediaSettingsGeneral::updateMediaPreview()
+{
+ if ( mHomeURL->getValue().asString().length() > 0 )
+ {
+ if(mPreviewMedia->getCurrentNavUrl() != mHomeURL->getValue().asString())
+ {
+ mPreviewMedia->navigateTo( mHomeURL->getValue().asString() );
+ }
+ }
+ else
+ // new home URL will be empty if media is deleted so display a
+ // "preview goes here" data url page
+ {
+ if(mPreviewMedia->getCurrentNavUrl() != CHECKERBOARD_DATA_URL)
+ {
+ mPreviewMedia->navigateTo( CHECKERBOARD_DATA_URL );
+ }
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// virtual
+void LLPanelMediaSettingsGeneral::onClose(bool app_quitting)
+{
+ if(mPreviewMedia)
+ {
+ mPreviewMedia->unloadMediaSource();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsGeneral::checkHomeUrlPassesWhitelist()
+{
+ // parent floater has not constructed the security panel yet
+ if ( mParent->getPanelSecurity() == 0 )
+ return;
+
+ std::string home_url = getHomeUrl();
+ if ( home_url.empty() || mParent->getPanelSecurity()->urlPassesWhiteList( home_url ) )
+ {
+ // Home URL is empty or passes the white list so hide the warning message
+ mFailWhiteListText->setVisible( false );
+ }
+ else
+ {
+ // Home URL does not pass the white list so show the warning message
+ mFailWhiteListText->setVisible( true );
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsGeneral::onCommitHomeURL( LLUICtrl* ctrl, void *userdata )
+{
+ LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata;
+
+ // check home url passes whitelist and display warning if not
+ self->checkHomeUrlPassesWhitelist();
+
+ self->updateMediaPreview();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsGeneral::onBtnResetCurrentUrl(LLUICtrl* ctrl, void *userdata)
+{
+ LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata;
+ self->navigateHomeSelectedFace(false);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsGeneral::preApply()
+{
+ // Make sure the home URL entry is committed
+ mHomeURL->onCommit();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsGeneral::getValues( LLSD &fill_me_in )
+{
+ fill_me_in[LLMediaEntry::AUTO_LOOP_KEY] = (LLSD::Boolean)mAutoLoop->getValue();
+ fill_me_in[LLMediaEntry::AUTO_PLAY_KEY] = (LLSD::Boolean)mAutoPlay->getValue();
+ fill_me_in[LLMediaEntry::AUTO_SCALE_KEY] = (LLSD::Boolean)mAutoScale->getValue();
+ fill_me_in[LLMediaEntry::AUTO_ZOOM_KEY] = (LLSD::Boolean)mAutoZoom->getValue();
+ //Don't fill in current URL: this is only supposed to get changed via navigate
+ // fill_me_in[LLMediaEntry::CURRENT_URL_KEY] = mCurrentURL->getValue();
+ fill_me_in[LLMediaEntry::HEIGHT_PIXELS_KEY] = (LLSD::Integer)mHeightPixels->getValue();
+ // Don't fill in the home URL if it is the special "Multiple Media" string!
+ if (LLTrans::getString("Multiple Media") != mHomeURL->getValue())
+ fill_me_in[LLMediaEntry::HOME_URL_KEY] = (LLSD::String)mHomeURL->getValue();
+ fill_me_in[LLMediaEntry::FIRST_CLICK_INTERACT_KEY] = (LLSD::Boolean)mFirstClick->getValue();
+ fill_me_in[LLMediaEntry::WIDTH_PIXELS_KEY] = (LLSD::Integer)mWidthPixels->getValue();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsGeneral::postApply()
+{
+ // Make sure to navigate to the home URL if the current URL is empty and
+ // autoplay is on
+ navigateHomeSelectedFace(true);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsGeneral::setParent( LLFloaterMediaSettings* parent )
+{
+ mParent = parent;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+bool LLPanelMediaSettingsGeneral::navigateHomeSelectedFace(bool only_if_current_is_empty)
+{
+ struct functor_navigate_media : public LLSelectedTEGetFunctor< bool>
+ {
+ functor_navigate_media(bool flag) : only_if_current_is_empty(flag) {}
+ bool get( LLViewerObject* object, S32 face )
+ {
+ if ( object && object->getTE(face) && object->permModify() )
+ {
+ const LLMediaEntry *media_data = object->getTE(face)->getMediaData();
+ if ( media_data )
+ {
+ if (!only_if_current_is_empty || (media_data->getCurrentURL().empty() && media_data->getAutoPlay()))
+ {
+ viewer_media_t media_impl =
+ LLViewerMedia::getMediaImplFromTextureID(object->getTE(face)->getMediaData()->getMediaID());
+ if(media_impl)
+ {
+ media_impl->navigateHome();
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ };
+ bool only_if_current_is_empty;
+
+ } functor_navigate_media(only_if_current_is_empty);
+
+ bool all_face_media_navigated = false;
+ LLObjectSelectionHandle selected_objects =LLSelectMgr::getInstance()->getSelection();
+ selected_objects->getSelectedTEValue( &functor_navigate_media, all_face_media_navigated );
+
+ // Note: we don't update the 'current URL' field until the media data itself changes
+
+ return all_face_media_navigated;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+const std::string LLPanelMediaSettingsGeneral::getHomeUrl()
+{
+ return mHomeURL->getValue().asString();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsGeneral::updateCurrentUrl()
+{
+ // Get the current URL from the selection
+ const LLMediaEntry default_media_data;
+ std::string 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);
+ bool identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func_current_url, value_str );
+ mCurrentURL->setText(value_str);
+ mCurrentURL->setTentative(identical);
+
+ if ( LLPanelMediaSettingsGeneral::isMultiple() )
+ {
+ mCurrentURL->setText(LLTrans::getString("Multiple Media"));
+ }
+}
diff --git a/indra/newview/llpanelmediasettingsgeneral.h b/indra/newview/llpanelmediasettingsgeneral.h
new file mode 100644
index 0000000000..5f90321362
--- /dev/null
+++ b/indra/newview/llpanelmediasettingsgeneral.h
@@ -0,0 +1,105 @@
+/**
+ * @file llpanelmediasettingsgeneral.h
+ * @brief LLPanelMediaSettingsGeneral class definition
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELMEDIAMEDIASETTINGSGENERAL_H
+#define LL_LLPANELMEDIAMEDIASETTINGSGENERAL_H
+
+#include "llpanel.h"
+
+class LLButton;
+class LLCheckBoxCtrl;
+class LLLineEditor;
+class LLSpinCtrl;
+class LLTextureCtrl;
+class LLMediaCtrl;
+class LLTextBox;
+class LLFloaterMediaSettings;
+
+class LLPanelMediaSettingsGeneral : public LLPanel
+{
+public:
+ LLPanelMediaSettingsGeneral();
+ ~LLPanelMediaSettingsGeneral();
+
+ // XXX TODO: put these into a common parent class?
+ // Hook that the floater calls before applying changes from the panel
+ void preApply();
+ // Function that asks the panel to fill in values associated with the panel
+ void getValues(LLSD &fill_me_in);
+ // Hook that the floater calls after applying changes to the panel
+ void postApply();
+
+ BOOL postBuild();
+ /*virtual*/ void draw();
+ /*virtual*/ void onClose(bool app_quitting);
+
+ void setParent( LLFloaterMediaSettings* parent );
+ static void initValues( void* userdata, const LLSD& media_settings ,bool editable);
+ static void clearValues( void* userdata, bool editable);
+
+ // Navigates the current selected face to the Home URL.
+ // If 'only_if_current_is_empty' is "true", it only performs
+ // the operation if: 1) the current URL is empty, and 2) auto play is true.
+ bool navigateHomeSelectedFace(bool only_if_current_is_empty);
+
+ void updateMediaPreview();
+
+ const std::string getHomeUrl();
+
+protected:
+ LLFloaterMediaSettings* mParent;
+ bool mMediaEditable;
+
+private:
+ void updateCurrentUrl();
+
+ static void onBtnResetCurrentUrl(LLUICtrl* ctrl, void *userdata);
+ static void onCommitHomeURL(LLUICtrl* ctrl, void *userdata );
+
+ static bool isMultiple();
+
+ void checkHomeUrlPassesWhitelist();
+
+ LLCheckBoxCtrl* mAutoLoop;
+ LLCheckBoxCtrl* mFirstClick;
+ LLCheckBoxCtrl* mAutoZoom;
+ LLCheckBoxCtrl* mAutoPlay;
+ LLCheckBoxCtrl* mAutoScale;
+ LLSpinCtrl* mWidthPixels;
+ LLSpinCtrl* mHeightPixels;
+ LLLineEditor* mHomeURL;
+ LLTextBox* mCurrentURL;
+ LLMediaCtrl* mPreviewMedia;
+ LLTextBox* mFailWhiteListText;
+};
+
+#endif // LL_LLPANELMEDIAMEDIASETTINGSGENERAL_H
diff --git a/indra/newview/llpanelmediasettingspermissions.cpp b/indra/newview/llpanelmediasettingspermissions.cpp
new file mode 100644
index 0000000000..a23aed2e98
--- /dev/null
+++ b/indra/newview/llpanelmediasettingspermissions.cpp
@@ -0,0 +1,269 @@
+/**
+ * @file llpanelmediasettingspermissions.cpp
+ * @brief LLPanelMediaSettingsPermissions class implementation
+ *
+ * note that "permissions" tab is really "Controls" tab - refs to 'perms' and
+ * 'permissions' not changed to 'controls' since we don't want to change
+ * shared files in server code and keeping everything the same seemed best.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelmediasettingspermissions.h"
+#include "llpanelcontents.h"
+#include "llcombobox.h"
+#include "llcheckboxctrl.h"
+#include "llspinctrl.h"
+#include "llurlhistory.h"
+#include "lluictrlfactory.h"
+#include "llwindow.h"
+#include "llviewerwindow.h"
+#include "llsdutil.h"
+#include "llselectmgr.h"
+#include "llmediaentry.h"
+#include "llnamebox.h"
+#include "lltrans.h"
+#include "llfloatermediasettings.h"
+
+////////////////////////////////////////////////////////////////////////////////
+//
+LLPanelMediaSettingsPermissions::LLPanelMediaSettingsPermissions() :
+ mControls( NULL ),
+ mPermsOwnerInteract( 0 ),
+ mPermsOwnerControl( 0 ),
+ mPermsGroupName( 0 ),
+ mPermsGroupInteract( 0 ),
+ mPermsGroupControl( 0 ),
+ mPermsWorldInteract( 0 ),
+ mPermsWorldControl( 0 )
+{
+ // build dialog from XML
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_permissions.xml");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLPanelMediaSettingsPermissions::postBuild()
+{
+ // connect member vars with UI widgets
+ mControls = getChild< LLComboBox >( LLMediaEntry::CONTROLS_KEY );
+ mPermsOwnerInteract = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_OWNER_INTERACT_KEY );
+ mPermsOwnerControl = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_OWNER_CONTROL_KEY );
+ mPermsGroupInteract = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_GROUP_INTERACT_KEY );
+ mPermsGroupControl = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_GROUP_CONTROL_KEY );
+ mPermsWorldInteract = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_ANYONE_INTERACT_KEY );
+ mPermsWorldControl = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_ANYONE_CONTROL_KEY );
+
+ mPermsGroupName = getChild< LLNameBox >( "perms_group_name" );
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+LLPanelMediaSettingsPermissions::~LLPanelMediaSettingsPermissions()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+void LLPanelMediaSettingsPermissions::draw()
+{
+ // housekeeping
+ LLPanel::draw();
+
+ childSetText("perms_group_name",LLStringUtil::null);
+ LLUUID group_id;
+ BOOL groups_identical = LLSelectMgr::getInstance()->selectGetGroup(group_id);
+ if (groups_identical)
+ {
+ if(mPermsGroupName)
+ {
+ mPermsGroupName->setNameID(group_id, true);
+ mPermsGroupName->setEnabled(true);
+ };
+ }
+ else
+ {
+ if(mPermsGroupName)
+ {
+ mPermsGroupName->setNameID(LLUUID::null, TRUE);
+ mPermsGroupName->refresh(LLUUID::null, LLStringUtil::null, LLStringUtil::null, true);
+ mPermsGroupName->setEnabled(false);
+ };
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsPermissions::clearValues( void* userdata, bool editable)
+{
+ LLPanelMediaSettingsPermissions *self =(LLPanelMediaSettingsPermissions *)userdata;
+
+ self->mControls->clear();
+ self->mPermsOwnerInteract->clear();
+ self->mPermsOwnerControl->clear();
+ self->mPermsGroupInteract->clear();
+ self->mPermsGroupControl->clear();
+ self->mPermsWorldInteract->clear();
+ self->mPermsWorldControl->clear();
+
+ self->mControls->setEnabled(editable);
+ self->mPermsOwnerInteract->setEnabled(editable);
+ self->mPermsOwnerControl->setEnabled(editable);
+ self->mPermsGroupInteract->setEnabled(editable);
+ self->mPermsGroupControl->setEnabled(editable);
+ self->mPermsWorldInteract->setEnabled(editable);
+ self->mPermsWorldControl->setEnabled(editable);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsPermissions::initValues( void* userdata, const LLSD& media_settings , bool editable)
+{
+ LLPanelMediaSettingsPermissions *self =(LLPanelMediaSettingsPermissions *)userdata;
+
+ if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo )
+ {
+ if(LLFloaterMediaSettings::getInstance()->mMultipleMedia)
+ {
+ self->clearValues(self, editable);
+ // only show multiple
+ return;
+ }
+
+ }
+ else
+ {
+ if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia)
+ {
+ self->clearValues(self, editable);
+ // only show multiple
+ return;
+ }
+
+ }
+ std::string base_key( "" );
+ std::string tentative_key( "" );
+
+ struct
+ {
+ std::string key_name;
+ LLUICtrl* ctrl_ptr;
+ std::string ctrl_type;
+
+ } data_set [] =
+ {
+ { LLMediaEntry::CONTROLS_KEY, self->mControls, "LLComboBox" },
+ { LLPanelContents::PERMS_OWNER_INTERACT_KEY, self->mPermsOwnerInteract, "LLCheckBoxCtrl" },
+ { LLPanelContents::PERMS_OWNER_CONTROL_KEY, self->mPermsOwnerControl, "LLCheckBoxCtrl" },
+ { LLPanelContents::PERMS_GROUP_INTERACT_KEY, self->mPermsGroupInteract, "LLCheckBoxCtrl" },
+ { LLPanelContents::PERMS_GROUP_CONTROL_KEY, self->mPermsGroupControl, "LLCheckBoxCtrl" },
+ { LLPanelContents::PERMS_ANYONE_INTERACT_KEY, self->mPermsWorldInteract, "LLCheckBoxCtrl" },
+ { LLPanelContents::PERMS_ANYONE_CONTROL_KEY, self->mPermsWorldControl, "LLCheckBoxCtrl" },
+ { "", NULL , "" }
+ };
+
+ for( int i = 0; data_set[ i ].key_name.length() > 0; ++i )
+ {
+ base_key = std::string( data_set[ i ].key_name );
+ tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX );
+
+ // TODO: CP - I bet there is a better way to do this using Boost
+ if ( media_settings[ base_key ].isDefined() )
+ {
+ if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" )
+ {
+ // Most recent change to the "sense" of these checkboxes
+ // means the value in the checkbox matches that on the server
+ static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )->
+ setValue( media_settings[ base_key ].asBoolean() );
+ }
+ else
+ if ( data_set[ i ].ctrl_type == "LLComboBox" )
+ static_cast< LLComboBox* >( data_set[ i ].ctrl_ptr )->
+ setCurrentByIndex( media_settings[ base_key ].asInteger() );
+
+ data_set[ i ].ctrl_ptr->setEnabled(editable);
+ data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
+ };
+ };
+
+ self->childSetEnabled("media_perms_label_owner", editable );
+ self->childSetText("media_perms_label_owner", LLTrans::getString("Media Perms Owner") );
+ self->childSetEnabled("media_perms_label_group", editable );
+ self->childSetText("media_perms_label_group", LLTrans::getString("Media Perms Group") );
+ self->childSetEnabled("media_perms_label_anyone", editable );
+ self->childSetText("media_perms_label_anyone", LLTrans::getString("Media Perms Anyone") );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsPermissions::preApply()
+{
+ // no-op
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsPermissions::getValues( LLSD &fill_me_in )
+{
+ // moved over from the 'General settings' tab
+ fill_me_in[LLMediaEntry::CONTROLS_KEY] = (LLSD::Integer)mControls->getCurrentIndex();
+
+ // *NOTE: For some reason, gcc does not like these symbol references in the
+ // expressions below (inside the static_casts). I have NO idea why :(.
+ // For some reason, assigning them to const temp vars here fixes the link
+ // error. Bizarre.
+ const U8 none = LLMediaEntry::PERM_NONE;
+ const U8 owner = LLMediaEntry::PERM_OWNER;
+ const U8 group = LLMediaEntry::PERM_GROUP;
+ const U8 anyone = LLMediaEntry::PERM_ANYONE;
+ const LLSD::Integer control = static_cast<LLSD::Integer>(
+ (mPermsOwnerControl->getValue() ? owner : none ) |
+ (mPermsGroupControl->getValue() ? group: none ) |
+ (mPermsWorldControl->getValue() ? anyone : none ));
+ const LLSD::Integer interact = static_cast<LLSD::Integer>(
+ (mPermsOwnerInteract->getValue() ? owner: none ) |
+ (mPermsGroupInteract->getValue() ? group : none ) |
+ (mPermsWorldInteract->getValue() ? anyone : none ));
+ fill_me_in[LLMediaEntry::PERMS_CONTROL_KEY] = control;
+ fill_me_in[LLMediaEntry::PERMS_INTERACT_KEY] = interact;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsPermissions::postApply()
+{
+ // no-op
+}
+
+
diff --git a/indra/newview/llpanelmediasettingspermissions.h b/indra/newview/llpanelmediasettingspermissions.h
new file mode 100644
index 0000000000..bd0c3b8ab5
--- /dev/null
+++ b/indra/newview/llpanelmediasettingspermissions.h
@@ -0,0 +1,78 @@
+/**
+ * @file llpanelmediasettingspermissions.h
+ * @brief LLPanelMediaSettingsPermissions class definition
+ *
+ * note that "permissions" tab is really "Controls" tab - refs to 'perms' and
+ * 'permissions' not changed to 'controls' since we don't want to change
+ * shared files in server code and keeping everything the same seemed best.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELMEDIAMEDIASETTINGSPERMISSIONS_H
+#define LL_LLPANELMEDIAMEDIASETTINGSPERMISSIONS_H
+
+#include "llpanel.h"
+#include "lluuid.h"
+
+class LLComboBox;
+class LLCheckBoxCtrl;
+class LLNameBox;
+
+class LLPanelMediaSettingsPermissions : public LLPanel
+{
+public:
+ LLPanelMediaSettingsPermissions();
+ ~LLPanelMediaSettingsPermissions();
+
+ BOOL postBuild();
+ virtual void draw();
+
+ // XXX TODO: put these into a common parent class?
+ // Hook that the floater calls before applying changes from the panel
+ void preApply();
+ // Function that asks the panel to fill in values associated with the panel
+ void getValues(LLSD &fill_me_in);
+ // Hook that the floater calls after applying changes to the panel
+ void postApply();
+
+ static void initValues( void* userdata, const LLSD& media_settings, bool editable );
+ static void clearValues( void* userdata, bool editable);
+
+private:
+ LLComboBox* mControls;
+ LLCheckBoxCtrl* mPermsOwnerInteract;
+ LLCheckBoxCtrl* mPermsOwnerControl;
+ LLNameBox* mPermsGroupName;
+ LLCheckBoxCtrl* mPermsGroupInteract;
+ LLCheckBoxCtrl* mPermsGroupControl;
+ LLCheckBoxCtrl* mPermsWorldInteract;
+ LLCheckBoxCtrl* mPermsWorldControl;
+};
+
+#endif // LL_LLPANELMEDIAMEDIASETTINGSPERMISSIONS_H
diff --git a/indra/newview/llpanelmediasettingssecurity.cpp b/indra/newview/llpanelmediasettingssecurity.cpp
new file mode 100644
index 0000000000..81842e3851
--- /dev/null
+++ b/indra/newview/llpanelmediasettingssecurity.cpp
@@ -0,0 +1,362 @@
+/**
+ * @file llpanelmediasettingssecurity.cpp
+ * @brief LLPanelMediaSettingsSecurity class implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelmediasettingssecurity.h"
+
+#include "llfloaterreg.h"
+#include "llpanelcontents.h"
+#include "llcheckboxctrl.h"
+#include "llnotificationsutil.h"
+#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "lluictrlfactory.h"
+#include "llwindow.h"
+#include "llviewerwindow.h"
+#include "llsdutil.h"
+#include "llselectmgr.h"
+#include "llmediaentry.h"
+#include "lltextbox.h"
+#include "llfloaterwhitelistentry.h"
+#include "llfloatermediasettings.h"
+
+////////////////////////////////////////////////////////////////////////////////
+//
+LLPanelMediaSettingsSecurity::LLPanelMediaSettingsSecurity() :
+ mParent( NULL )
+{
+ mCommitCallbackRegistrar.add("Media.whitelistAdd", boost::bind(&LLPanelMediaSettingsSecurity::onBtnAdd, this));
+ mCommitCallbackRegistrar.add("Media.whitelistDelete", boost::bind(&LLPanelMediaSettingsSecurity::onBtnDel, this));
+
+ // build dialog from XML
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_security.xml");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+BOOL LLPanelMediaSettingsSecurity::postBuild()
+{
+ mEnableWhiteList = getChild< LLCheckBoxCtrl >( LLMediaEntry::WHITELIST_ENABLE_KEY );
+ mWhiteListList = getChild< LLScrollListCtrl >( LLMediaEntry::WHITELIST_KEY );
+ mHomeUrlFailsWhiteListText = getChild<LLTextBox>( "home_url_fails_whitelist" );
+
+ setDefaultBtn("whitelist_add");
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+LLPanelMediaSettingsSecurity::~LLPanelMediaSettingsSecurity()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsSecurity::draw()
+{
+ // housekeeping
+ LLPanel::draw();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::initValues( void* userdata, const LLSD& media_settings , bool editable)
+{
+ LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
+
+ if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo )
+ {
+ if(LLFloaterMediaSettings::getInstance()->mMultipleMedia)
+ {
+ self->clearValues(self, editable);
+ // only show multiple
+ return;
+ }
+
+ }
+ else
+ {
+ if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia)
+ {
+ self->clearValues(self, editable);
+ // only show multiple
+ return;
+ }
+
+ }
+ std::string base_key( "" );
+ std::string tentative_key( "" );
+
+ struct
+ {
+ std::string key_name;
+ LLUICtrl* ctrl_ptr;
+ std::string ctrl_type;
+
+ } data_set [] =
+ {
+ { LLMediaEntry::WHITELIST_ENABLE_KEY, self->mEnableWhiteList, "LLCheckBoxCtrl" },
+ { LLMediaEntry::WHITELIST_KEY, self->mWhiteListList, "LLScrollListCtrl" },
+ { "", NULL , "" }
+ };
+
+ for( int i = 0; data_set[ i ].key_name.length() > 0; ++i )
+ {
+ base_key = std::string( data_set[ i ].key_name );
+ tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX );
+
+ // TODO: CP - I bet there is a better way to do this using Boost
+ if ( media_settings[ base_key ].isDefined() )
+ {
+ if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" )
+ {
+ static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )->
+ setValue( media_settings[ base_key ].asBoolean() );
+ }
+ else
+ if ( data_set[ i ].ctrl_type == "LLScrollListCtrl" )
+ {
+ // get control
+ LLScrollListCtrl* list = static_cast< LLScrollListCtrl* >( data_set[ i ].ctrl_ptr );
+ list->deleteAllItems();
+
+ // points to list of white list URLs
+ LLSD url_list = media_settings[ base_key ];
+
+ // iterate over them and add to scroll list
+ LLSD::array_iterator iter = url_list.beginArray();
+ while( iter != url_list.endArray() )
+ {
+ std::string entry = *iter;
+ self->addWhiteListEntry( entry );
+ ++iter;
+ };
+ };
+ data_set[ i ].ctrl_ptr->setEnabled(editable);
+ data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
+ };
+ };
+
+ // initial update - hides/shows status messages etc.
+ self->updateWhitelistEnableStatus();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::clearValues( void* userdata , bool editable)
+{
+ LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
+ self->mEnableWhiteList->clear();
+ self->mWhiteListList->deleteAllItems();
+ self->mEnableWhiteList->setEnabled(editable);
+ self->mWhiteListList->setEnabled(editable);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsSecurity::preApply()
+{
+ // no-op
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsSecurity::getValues( LLSD &fill_me_in )
+{
+ fill_me_in[LLMediaEntry::WHITELIST_ENABLE_KEY] = (LLSD::Boolean)mEnableWhiteList->getValue();
+
+ // iterate over white list and extract items
+ std::vector< LLScrollListItem* > whitelist_items = mWhiteListList->getAllData();
+ std::vector< LLScrollListItem* >::iterator iter = whitelist_items.begin();
+
+ // *NOTE: need actually set the key to be an emptyArray(), or the merge
+ // we do with this LLSD will think there's nothing to change.
+ fill_me_in[LLMediaEntry::WHITELIST_KEY] = LLSD::emptyArray();
+ while( iter != whitelist_items.end() )
+ {
+ LLScrollListCell* cell = (*iter)->getColumn( ENTRY_COLUMN );
+ std::string whitelist_url = cell->getValue().asString();
+
+ fill_me_in[ LLMediaEntry::WHITELIST_KEY ].append( whitelist_url );
+ ++iter;
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsSecurity::postApply()
+{
+ // no-op
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Try to make a valid URL if a fragment (
+// white list list box widget and build a list to test against. Can also
+const std::string LLPanelMediaSettingsSecurity::makeValidUrl( const std::string& src_url )
+{
+ // use LLURI to determine if we have a valid scheme
+ LLURI candidate_url( src_url );
+ if ( candidate_url.scheme().empty() )
+ {
+ // build a URL comprised of default scheme and the original fragment
+ const std::string default_scheme( "http://" );
+ return default_scheme + src_url;
+ };
+
+ // we *could* test the "default scheme" + "original fragment" URL again
+ // using LLURI to see if it's valid but I think the outcome is the same
+ // in either case - our only option is to return the original URL
+
+ // we *think* the original url passed in was valid
+ return src_url;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// wrapper for testing a URL against the whitelist. We grab entries from
+// white list list box widget and build a list to test against.
+bool LLPanelMediaSettingsSecurity::urlPassesWhiteList( const std::string& test_url )
+{
+ // the checkUrlAgainstWhitelist(..) function works on a vector
+ // of strings for the white list entries - in this panel, the white list
+ // is stored in the widgets themselves so we need to build something compatible.
+ std::vector< std::string > whitelist_strings;
+ whitelist_strings.clear(); // may not be required - I forget what the spec says.
+
+ // step through whitelist widget entries and grab them as strings
+ std::vector< LLScrollListItem* > whitelist_items = mWhiteListList->getAllData();
+ std::vector< LLScrollListItem* >::iterator iter = whitelist_items.begin();
+ while( iter != whitelist_items.end() )
+ {
+ LLScrollListCell* cell = (*iter)->getColumn( ENTRY_COLUMN );
+ std::string whitelist_url = cell->getValue().asString();
+
+ whitelist_strings.push_back( whitelist_url );
+
+ ++iter;
+ };
+
+ // possible the URL is just a fragment so we validize it
+ const std::string valid_url = makeValidUrl( test_url );
+
+ // indicate if the URL passes whitelist
+ return LLMediaEntry::checkUrlAgainstWhitelist( valid_url, whitelist_strings );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsSecurity::updateWhitelistEnableStatus()
+{
+ // get the value for home URL and make it a valid URL
+ const std::string valid_url = makeValidUrl( mParent->getHomeUrl() );
+
+ // now check to see if the home url passes the whitelist in its entirity
+ if ( urlPassesWhiteList( valid_url ) )
+ {
+ mEnableWhiteList->setEnabled( true );
+ mHomeUrlFailsWhiteListText->setVisible( false );
+ }
+ else
+ {
+ mEnableWhiteList->set( false );
+ mEnableWhiteList->setEnabled( false );
+ mHomeUrlFailsWhiteListText->setVisible( true );
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Add an entry to the whitelist scrollbox and indicate if the current
+// home URL passes this entry or not using an icon
+void LLPanelMediaSettingsSecurity::addWhiteListEntry( const std::string& entry )
+{
+ // grab the home url
+ std::string home_url( "" );
+ if ( mParent )
+ home_url = mParent->getHomeUrl();
+
+ // try to make a valid URL based on what the user entered - missing scheme for example
+ const std::string valid_url = makeValidUrl( home_url );
+
+ // check the home url against this single whitelist entry
+ std::vector< std::string > whitelist_entries;
+ whitelist_entries.push_back( entry );
+ bool home_url_passes_entry = LLMediaEntry::checkUrlAgainstWhitelist( valid_url, whitelist_entries );
+
+ // build an icon cell based on whether or not the home url pases it or not
+ LLSD row;
+ if ( home_url_passes_entry || home_url.empty() )
+ {
+ row[ "columns" ][ ICON_COLUMN ][ "type" ] = "icon";
+ row[ "columns" ][ ICON_COLUMN ][ "value" ] = "";
+ row[ "columns" ][ ICON_COLUMN ][ "width" ] = 20;
+ }
+ else
+ {
+ row[ "columns" ][ ICON_COLUMN ][ "type" ] = "icon";
+ row[ "columns" ][ ICON_COLUMN ][ "value" ] = "Parcel_Exp_Color";
+ row[ "columns" ][ ICON_COLUMN ][ "width" ] = 20;
+ };
+
+ // always add in the entry itself
+ row[ "columns" ][ ENTRY_COLUMN ][ "type" ] = "text";
+ row[ "columns" ][ ENTRY_COLUMN ][ "value" ] = entry;
+
+ // add to the white list scroll box
+ mWhiteListList->addElement( row );
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::onBtnAdd( void* userdata )
+{
+ LLFloaterReg::showInstance("whitelist_entry");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::onBtnDel( void* userdata )
+{
+ LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
+
+ self->mWhiteListList->deleteSelectedItems();
+
+ // contents of whitelist changed so recheck it against home url
+ self->updateWhitelistEnableStatus();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsSecurity::setParent( LLFloaterMediaSettings* parent )
+{
+ mParent = parent;
+};
diff --git a/indra/newview/llpanelmediasettingssecurity.h b/indra/newview/llpanelmediasettingssecurity.h
new file mode 100644
index 0000000000..66ccb23f46
--- /dev/null
+++ b/indra/newview/llpanelmediasettingssecurity.h
@@ -0,0 +1,87 @@
+/**
+ * @file llpanelmediasettingssecurity.h
+ * @brief LLPanelMediaSettingsSecurity class definition
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELMEDIAMEDIASETTINGSSECURITY_H
+#define LL_LLPANELMEDIAMEDIASETTINGSSECURITY_H
+
+#include "llpanel.h"
+
+class LLCheckBoxCtrl;
+class LLScrollListCtrl;
+class LLTextBox;
+class LLFloaterMediaSettings;
+
+class LLPanelMediaSettingsSecurity : public LLPanel
+{
+public:
+ LLPanelMediaSettingsSecurity();
+ ~LLPanelMediaSettingsSecurity();
+
+ BOOL postBuild();
+ virtual void draw();
+
+ // XXX TODO: put these into a common parent class?
+ // Hook that the floater calls before applying changes from the panel
+ void preApply();
+ // Function that asks the panel to fill in values associated with the panel
+ void getValues(LLSD &fill_me_in);
+ // Hook that the floater calls after applying changes to the panel
+ void postApply();
+
+ static void initValues( void* userdata, const LLSD& media_settings,bool editable );
+ static void clearValues( void* userdata, bool editable);
+ void addWhiteListEntry( const std::string& url );
+ void setParent( LLFloaterMediaSettings* parent );
+ bool urlPassesWhiteList( const std::string& test_url );
+ const std::string makeValidUrl( const std::string& src_url );
+
+ void updateWhitelistEnableStatus();
+
+protected:
+ LLFloaterMediaSettings* mParent;
+
+private:
+ enum ColumnIndex
+ {
+ ICON_COLUMN = 0,
+ ENTRY_COLUMN = 1,
+ };
+
+ LLCheckBoxCtrl* mEnableWhiteList;
+ LLScrollListCtrl* mWhiteListList;
+ LLTextBox* mHomeUrlFailsWhiteListText;
+
+ static void onBtnAdd(void*);
+ static void onBtnDel(void*);
+};
+
+#endif // LL_LLPANELMEDIAMEDIASETTINGSSECURITY_H
diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp
index 75f479c16f..d17c287cc7 100644
--- a/indra/newview/llpanelobject.cpp
+++ b/indra/newview/llpanelobject.cpp
@@ -39,9 +39,11 @@
#include "lleconomy.h"
#include "llerror.h"
#include "llfontgl.h"
+#include "llmaterialtable.h"
#include "llpermissionsflags.h"
#include "llstring.h"
#include "llvolume.h"
+#include "material_codes.h"
#include "m3math.h"
// project includes
@@ -52,7 +54,6 @@
#include "llcombobox.h"
#include "llfocusmgr.h"
#include "llmanipscale.h"
-#include "llpanelinventory.h"
#include "llpreviewscript.h"
#include "llresmgr.h"
#include "llselectmgr.h"
@@ -62,6 +63,7 @@
#include "lltool.h"
#include "lltoolcomp.h"
#include "lltoolmgr.h"
+#include "lltrans.h"
#include "llui.h"
#include "llviewerobject.h"
#include "llviewerregion.h"
@@ -71,7 +73,7 @@
#include "pipeline.h"
#include "llviewercontrol.h"
#include "lluictrlfactory.h"
-#include "llfirstuse.h"
+//#include "llfirstuse.h"
#include "lldrawpool.h"
@@ -99,13 +101,23 @@ enum {
MI_HOLE_COUNT
};
-//*TODO:translate (depricated, so very low priority)
-static const std::string LEGACY_FULLBRIGHT_DESC("Fullbright (Legacy)");
+//static const std::string LEGACY_FULLBRIGHT_DESC =LLTrans::getString("Fullbright");
BOOL LLPanelObject::postBuild()
{
setMouseOpaque(FALSE);
-
+
+ std::map<std::string, std::string> material_name_map;
+ material_name_map["Stone"]= LLTrans::getString("Stone");
+ material_name_map["Metal"]= LLTrans::getString("Metal");
+ material_name_map["Glass"]= LLTrans::getString("Glass");
+ material_name_map["Wood"]= LLTrans::getString("Wood");
+ material_name_map["Flesh"]= LLTrans::getString("Flesh");
+ material_name_map["Plastic"]= LLTrans::getString("Plastic");
+ material_name_map["Rubber"]= LLTrans::getString("Rubber");
+ material_name_map["Light"]= LLTrans::getString("Light");
+
+ LLMaterialTable::basic.initTableTransNames(material_name_map);
//--------------------------------------------------------
// Top
//--------------------------------------------------------
@@ -164,14 +176,14 @@ BOOL LLPanelObject::postBuild()
mComboMaterial = getChild<LLComboBox>("material");
childSetCommitCallback("material",onCommitMaterial,this);
mComboMaterial->removeall();
- // *TODO:translate
+
for (LLMaterialTable::info_list_t::iterator iter = LLMaterialTable::basic.mMaterialInfoList.begin();
iter != LLMaterialTable::basic.mMaterialInfoList.end(); ++iter)
{
LLMaterialInfo* minfop = *iter;
if (minfop->mMCode != LL_MCODE_LIGHT)
{
- mComboMaterial->add(minfop->mName);
+ mComboMaterial->add(minfop->mName);
}
}
mComboMaterialItemCount = mComboMaterial->getItemCount();
@@ -263,11 +275,10 @@ BOOL LLPanelObject::postBuild()
if (mCtrlSculptTexture)
{
mCtrlSculptTexture->setDefaultImageAssetID(LLUUID(SCULPT_DEFAULT_TEXTURE));
- mCtrlSculptTexture->setCommitCallback( LLPanelObject::onCommitSculpt );
- mCtrlSculptTexture->setOnCancelCallback( LLPanelObject::onCancelSculpt );
- mCtrlSculptTexture->setOnSelectCallback( LLPanelObject::onSelectSculpt );
- mCtrlSculptTexture->setDropCallback(LLPanelObject::onDropSculpt);
- mCtrlSculptTexture->setCallbackUserData( this );
+ mCtrlSculptTexture->setCommitCallback( boost::bind(&LLPanelObject::onCommitSculpt, this, _2 ));
+ mCtrlSculptTexture->setOnCancelCallback( boost::bind(&LLPanelObject::onCancelSculpt, this, _2 ));
+ mCtrlSculptTexture->setOnSelectCallback( boost::bind(&LLPanelObject::onSelectSculpt, this, _2 ));
+ mCtrlSculptTexture->setDropCallback( boost::bind(&LLPanelObject::onDropSculpt, this, _2 ));
// Don't allow (no copy) or (no transfer) textures to be selected during immediate mode
mCtrlSculptTexture->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
// Allow any texture to be used during non-immediate mode.
@@ -303,8 +314,8 @@ BOOL LLPanelObject::postBuild()
return TRUE;
}
-LLPanelObject::LLPanelObject(const std::string& name)
-: LLPanel(name),
+LLPanelObject::LLPanelObject()
+: LLPanel(),
mIsPhysical(FALSE),
mIsTemporary(FALSE),
mIsPhantom(FALSE),
@@ -530,7 +541,7 @@ void LLPanelObject::getState( )
}
} func;
bool material_same = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, material_code );
-
+ std::string LEGACY_FULLBRIGHT_DESC = LLTrans::getString("Fullbright");
if (editable && single_volume && material_same)
{
mComboMaterial->setEnabled( TRUE );
@@ -549,7 +560,7 @@ void LLPanelObject::getState( )
{
mComboMaterial->remove(LEGACY_FULLBRIGHT_DESC);
}
- // *TODO:Translate
+
mComboMaterial->setSimple(std::string(LLMaterialTable::basic.getName(material_code)));
}
}
@@ -671,7 +682,7 @@ void LLPanelObject::getState( )
if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT))
{
selected_item = MI_SCULPT;
- LLFirstUse::useSculptedPrim();
+ //LLFirstUse::useSculptedPrim();
}
@@ -1163,7 +1174,7 @@ void LLPanelObject::getState( )
}
// static
-BOOL LLPanelObject::precommitValidate( LLUICtrl* ctrl, void* userdata )
+bool LLPanelObject::precommitValidate( const LLSD& data )
{
// TODO: Richard will fill this in later.
return TRUE; // FALSE means that validation failed and new value should not be commited.
@@ -1244,6 +1255,7 @@ void LLPanelObject::onCommitMaterial( LLUICtrl* ctrl, void* userdata )
{
// apply the currently selected material to the object
const std::string& material_name = box->getSimple();
+ std::string LEGACY_FULLBRIGHT_DESC = LLTrans::getString("Fullbright");
if (material_name != LEGACY_FULLBRIGHT_DESC)
{
U8 material_code = LLMaterialTable::basic.getMCode(material_name);
@@ -1992,60 +2004,49 @@ void LLPanelObject::onCommitCastShadows( LLUICtrl* ctrl, void* userdata )
}
-// static
-void LLPanelObject::onSelectSculpt(LLUICtrl* ctrl, void* userdata)
+void LLPanelObject::onSelectSculpt(const LLSD& data)
{
- LLPanelObject* self = (LLPanelObject*) userdata;
-
- LLTextureCtrl* mTextureCtrl = self->getChild<LLTextureCtrl>("sculpt texture control");
+ LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("sculpt texture control");
if (mTextureCtrl)
{
- self->mSculptTextureRevert = mTextureCtrl->getImageAssetID();
+ mSculptTextureRevert = mTextureCtrl->getImageAssetID();
}
- self->sendSculpt();
+ sendSculpt();
}
-void LLPanelObject::onCommitSculpt( LLUICtrl* ctrl, void* userdata )
+void LLPanelObject::onCommitSculpt( const LLSD& data )
{
- LLPanelObject* self = (LLPanelObject*) userdata;
-
- self->sendSculpt();
+ sendSculpt();
}
-// static
-BOOL LLPanelObject::onDropSculpt(LLUICtrl*, LLInventoryItem* item, void* userdata)
+BOOL LLPanelObject::onDropSculpt(LLInventoryItem* item)
{
- LLPanelObject* self = (LLPanelObject*) userdata;
-
- LLTextureCtrl* mTextureCtrl = self->getChild<LLTextureCtrl>("sculpt texture control");
+ LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("sculpt texture control");
if (mTextureCtrl)
{
LLUUID asset = item->getAssetUUID();
mTextureCtrl->setImageAssetID(asset);
- self->mSculptTextureRevert = asset;
+ mSculptTextureRevert = asset;
}
return TRUE;
}
-// static
-void LLPanelObject::onCancelSculpt(LLUICtrl* ctrl, void* userdata)
+void LLPanelObject::onCancelSculpt(const LLSD& data)
{
- LLPanelObject* self = (LLPanelObject*) userdata;
-
- LLTextureCtrl* mTextureCtrl = self->getChild<LLTextureCtrl>("sculpt texture control");
+ LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("sculpt texture control");
if(!mTextureCtrl)
return;
- mTextureCtrl->setImageAssetID(self->mSculptTextureRevert);
+ mTextureCtrl->setImageAssetID(mSculptTextureRevert);
- self->sendSculpt();
+ sendSculpt();
}
// static
diff --git a/indra/newview/llpanelobject.h b/indra/newview/llpanelobject.h
index 9ed091ed5f..58d9fe9b76 100644
--- a/indra/newview/llpanelobject.h
+++ b/indra/newview/llpanelobject.h
@@ -35,7 +35,7 @@
#include "v3math.h"
#include "llpanel.h"
-#include "llmemory.h"
+#include "llpointer.h"
#include "llvolume.h"
class LLSpinCtrl;
@@ -45,7 +45,6 @@ class LLUICtrl;
class LLButton;
class LLViewerObject;
class LLComboBox;
-class LLPanelInventory;
class LLColorSwatchCtrl;
class LLTextureCtrl;
class LLInventoryItem;
@@ -54,7 +53,7 @@ class LLUUID;
class LLPanelObject : public LLPanel
{
public:
- LLPanelObject(const std::string& name);
+ LLPanelObject();
virtual ~LLPanelObject();
virtual BOOL postBuild();
@@ -63,7 +62,7 @@ public:
void refresh();
- static BOOL precommitValidate(LLUICtrl* ctrl,void* userdata);
+ static bool precommitValidate(const LLSD& data);
static void onCommitLock(LLUICtrl *ctrl, void *data);
static void onCommitPosition( LLUICtrl* ctrl, void* userdata);
@@ -78,10 +77,10 @@ public:
static void onCommitMaterial( LLUICtrl* ctrl, void* userdata);
- static void onCommitSculpt( LLUICtrl* ctrl, void* userdata);
- static void onCancelSculpt( LLUICtrl* ctrl, void* userdata);
- static void onSelectSculpt( LLUICtrl* ctrl, void* userdata);
- static BOOL onDropSculpt( LLUICtrl* ctrl, LLInventoryItem* item, void* ud);
+ void onCommitSculpt(const LLSD& data);
+ void onCancelSculpt(const LLSD& data);
+ void onSelectSculpt(const LLSD& data);
+ BOOL onDropSculpt(LLInventoryItem* item);
static void onCommitSculptType( LLUICtrl *ctrl, void* userdata);
diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp
new file mode 100644
index 0000000000..d4376550d6
--- /dev/null
+++ b/indra/newview/llpanelobjectinventory.cpp
@@ -0,0 +1,1964 @@
+/**
+ * @file llsidepanelinventory.cpp
+ * @brief LLPanelObjectInventory class implementation
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+//*****************************************************************************
+//
+// Implementation of the panel inventory - used to view and control a
+// task's inventory.
+//
+//*****************************************************************************
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelobjectinventory.h"
+
+#include "llmenugl.h"
+#include "llnotificationsutil.h"
+#include "roles_constants.h"
+
+#include "llagent.h"
+#include "llcallbacklist.h"
+#include "llfloaterbuycurrency.h"
+#include "llfloaterreg.h"
+#include "llinventorybridge.h"
+#include "llinventoryfilter.h"
+#include "llinventoryfunctions.h"
+#include "llpreviewanim.h"
+#include "llpreviewgesture.h"
+#include "llpreviewnotecard.h"
+#include "llpreviewscript.h"
+#include "llpreviewsound.h"
+#include "llpreviewtexture.h"
+#include "llscrollcontainer.h"
+#include "llselectmgr.h"
+#include "llsidetray.h"
+#include "llstatusbar.h"
+#include "lltrans.h"
+#include "llviewerassettype.h"
+#include "llviewerregion.h"
+#include "llviewerobjectlist.h"
+#include "llviewermessage.h"
+
+
+///----------------------------------------------------------------------------
+/// Class LLTaskInvFVBridge
+///----------------------------------------------------------------------------
+
+class LLTaskInvFVBridge : public LLFolderViewEventListener
+{
+protected:
+ LLUUID mUUID;
+ std::string mName;
+ mutable std::string mDisplayName;
+ LLPanelObjectInventory* mPanel;
+ U32 mFlags;
+
+ LLInventoryItem* findItem() const;
+
+public:
+ LLTaskInvFVBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name,
+ U32 flags=0);
+ virtual ~LLTaskInvFVBridge( void ) {}
+
+ virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; }
+ virtual std::string getLabelSuffix() const { return LLStringUtil::null; }
+
+ static LLTaskInvFVBridge* createObjectBridge(LLPanelObjectInventory* panel,
+ LLInventoryObject* object);
+ void showProperties();
+ void buyItem();
+ S32 getPrice();
+ static bool commitBuyItem(const LLSD& notification, const LLSD& response);
+
+ // LLFolderViewEventListener functionality
+ virtual const std::string& getName() const;
+ virtual const std::string& getDisplayName() const;
+ virtual PermissionMask getPermissionMask() const { return PERM_NONE; }
+ /*virtual*/ LLFolderType::EType getPreferredType() const { return LLFolderType::FT_NONE; }
+ virtual const LLUUID& getUUID() const { return mUUID; }
+ virtual time_t getCreationDate() const;
+ virtual LLUIImagePtr getIcon() const;
+ virtual void openItem();
+ virtual void closeItem() {}
+ virtual void previewItem();
+ virtual void selectItem() {}
+ virtual BOOL isItemRenameable() const;
+ virtual BOOL renameItem(const std::string& new_name);
+ virtual BOOL isItemMovable() const;
+ virtual BOOL isItemRemovable();
+ virtual BOOL removeItem();
+ virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch);
+ virtual void move(LLFolderViewEventListener* parent_listener);
+ virtual BOOL isItemCopyable() const;
+ virtual BOOL copyToClipboard() const;
+ virtual void cutToClipboard();
+ virtual BOOL isClipboardPasteable() const;
+ virtual void pasteFromClipboard();
+ virtual void pasteLinkFromClipboard();
+ virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
+ virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action);
+ virtual BOOL isUpToDate() const { return TRUE; }
+ virtual BOOL hasChildren() const { return FALSE; }
+ virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; }
+ // LLDragAndDropBridge functionality
+ virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const;
+ virtual BOOL dragOrDrop(MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data);
+};
+
+LLTaskInvFVBridge::LLTaskInvFVBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name,
+ U32 flags):
+ mUUID(uuid),
+ mName(name),
+ mPanel(panel),
+ mFlags(flags)
+{
+
+}
+
+LLInventoryItem* LLTaskInvFVBridge::findItem() const
+{
+ LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
+ if(object)
+ {
+ return dynamic_cast<LLInventoryItem*>(object->getInventoryObject(mUUID));
+ }
+ return NULL;
+}
+
+void LLTaskInvFVBridge::showProperties()
+{
+ LLSD key;
+ key["object"] = mPanel->getTaskUUID();
+ key["id"] = mUUID;
+ LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
+
+
+ // Disable old properties floater; this is replaced by the sidepanel.
+ /*
+ LLFloaterProperties* floater = LLFloaterReg::showTypedInstance<LLFloaterProperties>("properties", mUUID);
+ if (floater)
+ {
+ floater->setObjectID(mPanel->getTaskUUID());
+ }
+ */
+}
+
+struct LLBuyInvItemData
+{
+ LLUUID mTaskID;
+ LLUUID mItemID;
+ LLAssetType::EType mType;
+
+ LLBuyInvItemData(const LLUUID& task,
+ const LLUUID& item,
+ LLAssetType::EType type) :
+ mTaskID(task), mItemID(item), mType(type)
+ {}
+};
+
+void LLTaskInvFVBridge::buyItem()
+{
+ llinfos << "LLTaskInvFVBridge::buyItem()" << llendl;
+ LLInventoryItem* item = findItem();
+ if(!item || !item->getSaleInfo().isForSale()) return;
+ LLBuyInvItemData* inv = new LLBuyInvItemData(mPanel->getTaskUUID(),
+ mUUID,
+ item->getType());
+
+ const LLSaleInfo& sale_info = item->getSaleInfo();
+ const LLPermissions& perm = item->getPermissions();
+ const std::string owner_name; // no owner name currently... FIXME?
+
+ LLViewerObject* obj;
+ if( ( obj = gObjectList.findObject( mPanel->getTaskUUID() ) ) && obj->isAttachment() )
+ {
+ LLNotificationsUtil::add("Cannot_Purchase_an_Attachment");
+ llinfos << "Attempt to purchase an attachment" << llendl;
+ delete inv;
+ }
+ else
+ {
+ LLSD args;
+ args["PRICE"] = llformat("%d",sale_info.getSalePrice());
+ args["OWNER"] = owner_name;
+ if (sale_info.getSaleType() != LLSaleInfo::FS_CONTENTS)
+ {
+ U32 next_owner_mask = perm.getMaskNextOwner();
+ args["MODIFYPERM"] = LLTrans::getString((next_owner_mask & PERM_MODIFY) ? "PermYes" : "PermNo");
+ args["COPYPERM"] = LLTrans::getString((next_owner_mask & PERM_COPY) ? "PermYes" : "PermNo");
+ args["RESELLPERM"] = LLTrans::getString((next_owner_mask & PERM_TRANSFER) ? "PermYes" : "PermNo");
+ }
+
+ std::string alertdesc;
+ switch(sale_info.getSaleType())
+ {
+ case LLSaleInfo::FS_ORIGINAL:
+ alertdesc = owner_name.empty() ? "BuyOriginalNoOwner" : "BuyOriginal";
+ break;
+ case LLSaleInfo::FS_CONTENTS:
+ alertdesc = owner_name.empty() ? "BuyContentsNoOwner" : "BuyContents";
+ break;
+ case LLSaleInfo::FS_COPY:
+ default:
+ alertdesc = owner_name.empty() ? "BuyCopyNoOwner" : "BuyCopy";
+ break;
+ }
+
+ LLSD payload;
+ payload["task_id"] = inv->mTaskID;
+ payload["item_id"] = inv->mItemID;
+ payload["type"] = inv->mType;
+ LLNotificationsUtil::add(alertdesc, args, payload, LLTaskInvFVBridge::commitBuyItem);
+ }
+}
+
+S32 LLTaskInvFVBridge::getPrice()
+{
+ LLInventoryItem* item = findItem();
+ if(item)
+ {
+ return item->getSaleInfo().getSalePrice();
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+// static
+bool LLTaskInvFVBridge::commitBuyItem(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if(0 == option)
+ {
+ LLViewerObject* object = gObjectList.findObject(notification["payload"]["task_id"].asUUID());
+ if(!object || !object->getRegion()) return false;
+
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_BuyObjectInventory);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_Data);
+ msg->addUUIDFast(_PREHASH_ObjectID, notification["payload"]["task_id"].asUUID());
+ msg->addUUIDFast(_PREHASH_ItemID, notification["payload"]["item_id"].asUUID());
+ msg->addUUIDFast(_PREHASH_FolderID,
+ gInventory.findCategoryUUIDForType((LLFolderType::EType)notification["payload"]["type"].asInteger()));
+ msg->sendReliable(object->getRegion()->getHost());
+ }
+ return false;
+}
+
+const std::string& LLTaskInvFVBridge::getName() const
+{
+ return mName;
+}
+
+const std::string& LLTaskInvFVBridge::getDisplayName() const
+{
+ LLInventoryItem* item = findItem();
+
+ if(item)
+ {
+ if(item->getParentUUID().isNull())
+ {
+ if(item->getName() == "Contents")
+ {
+ mDisplayName.assign(LLTrans::getString("ViewerObjectContents"));
+ }
+ else
+ {
+ mDisplayName.assign(item->getName());
+ }
+ }
+ else
+ {
+ mDisplayName.assign(item->getName());
+ }
+ const LLPermissions& perm(item->getPermissions());
+ BOOL copy = gAgent.allowOperation(PERM_COPY, perm, GP_OBJECT_MANIPULATE);
+ BOOL mod = gAgent.allowOperation(PERM_MODIFY, perm, GP_OBJECT_MANIPULATE);
+ BOOL xfer = gAgent.allowOperation(PERM_TRANSFER, perm, GP_OBJECT_MANIPULATE);
+
+ if(!copy)
+ {
+ mDisplayName.append(LLTrans::getString("no_copy"));
+ }
+ if(!mod)
+ {
+ mDisplayName.append(LLTrans::getString("no_modify"));
+ }
+ if(!xfer)
+ {
+ mDisplayName.append(LLTrans::getString("no_transfer"));
+ }
+ }
+
+ return mDisplayName;
+}
+
+// BUG: No creation dates for task inventory
+time_t LLTaskInvFVBridge::getCreationDate() const
+{
+ return 0;
+}
+
+LLUIImagePtr LLTaskInvFVBridge::getIcon() const
+{
+ BOOL item_is_multi = FALSE;
+ if ( mFlags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS )
+ {
+ item_is_multi = TRUE;
+ }
+
+ return get_item_icon(LLAssetType::AT_OBJECT, LLInventoryType::IT_OBJECT, 0, item_is_multi );
+}
+
+void LLTaskInvFVBridge::openItem()
+{
+ // no-op.
+ lldebugs << "LLTaskInvFVBridge::openItem()" << llendl;
+}
+
+void LLTaskInvFVBridge::previewItem()
+{
+ openItem();
+}
+
+BOOL LLTaskInvFVBridge::isItemRenameable() const
+{
+ if(gAgent.isGodlike()) return TRUE;
+ LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
+ if(object)
+ {
+ LLInventoryItem* item;
+ item = (LLInventoryItem*)(object->getInventoryObject(mUUID));
+ if(item && gAgent.allowOperation(PERM_MODIFY, item->getPermissions(),
+ GP_OBJECT_MANIPULATE, GOD_LIKE))
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+BOOL LLTaskInvFVBridge::renameItem(const std::string& new_name)
+{
+ LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
+ if(object)
+ {
+ LLViewerInventoryItem* item = NULL;
+ item = (LLViewerInventoryItem*)object->getInventoryObject(mUUID);
+ if(item && (gAgent.allowOperation(PERM_MODIFY, item->getPermissions(),
+ GP_OBJECT_MANIPULATE, GOD_LIKE)))
+ {
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ new_item->rename(new_name);
+ object->updateInventory(
+ new_item,
+ TASK_INVENTORY_ITEM_KEY,
+ false);
+ }
+ }
+ return TRUE;
+}
+
+BOOL LLTaskInvFVBridge::isItemMovable() const
+{
+ //LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
+ //if(object && (object->permModify() || gAgent.isGodlike()))
+ //{
+ // return TRUE;
+ //}
+ //return FALSE;
+ return TRUE;
+}
+
+BOOL LLTaskInvFVBridge::isItemRemovable()
+{
+ LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
+ if(object
+ && (object->permModify() || object->permYouOwner()))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool remove_task_inventory_callback(const LLSD& notification, const LLSD& response, LLPanelObjectInventory* panel)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ LLViewerObject* object = gObjectList.findObject(notification["payload"]["task_id"].asUUID());
+ if(option == 0 && object)
+ {
+ // yes
+ LLSD::array_const_iterator list_end = notification["payload"]["inventory_ids"].endArray();
+ for (LLSD::array_const_iterator list_it = notification["payload"]["inventory_ids"].beginArray();
+ list_it != list_end;
+ ++list_it)
+ {
+ object->removeInventory(list_it->asUUID());
+ }
+
+ // refresh the UI.
+ panel->refresh();
+ }
+ return false;
+}
+
+// helper for remove
+// ! REFACTOR ! two_uuids_list_t is also defined in llinventorybridge.h, but differently.
+typedef std::pair<LLUUID, std::list<LLUUID> > panel_two_uuids_list_t;
+typedef std::pair<LLPanelObjectInventory*, panel_two_uuids_list_t> remove_data_t;
+BOOL LLTaskInvFVBridge::removeItem()
+{
+ if(isItemRemovable() && mPanel)
+ {
+ LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
+ if(object)
+ {
+ if(object->permModify())
+ {
+ // just do it.
+ object->removeInventory(mUUID);
+ return TRUE;
+ }
+ else
+ {
+ remove_data_t* data = new remove_data_t;
+ data->first = mPanel;
+ data->second.first = mPanel->getTaskUUID();
+ data->second.second.push_back(mUUID);
+ LLSD payload;
+ payload["task_id"] = mPanel->getTaskUUID();
+ payload["inventory_ids"].append(mUUID);
+ LLNotificationsUtil::add("RemoveItemWarn", LLSD(), payload, boost::bind(&remove_task_inventory_callback, _1, _2, mPanel));
+ return FALSE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+void LLTaskInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch)
+{
+ if (!mPanel)
+ {
+ return;
+ }
+
+ LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
+ if (!object)
+ {
+ return;
+ }
+
+ if (!object->permModify())
+ {
+ LLSD payload;
+ payload["task_id"] = mPanel->getTaskUUID();
+ for (S32 i = 0; i < (S32)batch.size(); i++)
+ {
+ LLTaskInvFVBridge* itemp = (LLTaskInvFVBridge*)batch[i];
+ payload["inventory_ids"].append(itemp->getUUID());
+ }
+ LLNotificationsUtil::add("RemoveItemWarn", LLSD(), payload, boost::bind(&remove_task_inventory_callback, _1, _2, mPanel));
+
+ }
+ else
+ {
+ for (S32 i = 0; i < (S32)batch.size(); i++)
+ {
+ LLTaskInvFVBridge* itemp = (LLTaskInvFVBridge*)batch[i];
+
+ if(itemp->isItemRemovable())
+ {
+ // just do it.
+ object->removeInventory(itemp->getUUID());
+ }
+ }
+ }
+}
+
+void LLTaskInvFVBridge::move(LLFolderViewEventListener* parent_listener)
+{
+}
+
+BOOL LLTaskInvFVBridge::isItemCopyable() const
+{
+ LLInventoryItem* item = findItem();
+ if(!item) return FALSE;
+ return gAgent.allowOperation(PERM_COPY, item->getPermissions(),
+ GP_OBJECT_MANIPULATE);
+}
+
+BOOL LLTaskInvFVBridge::copyToClipboard() const
+{
+ return FALSE;
+}
+
+void LLTaskInvFVBridge::cutToClipboard()
+{
+}
+
+BOOL LLTaskInvFVBridge::isClipboardPasteable() const
+{
+ return FALSE;
+}
+
+void LLTaskInvFVBridge::pasteFromClipboard()
+{
+}
+
+void LLTaskInvFVBridge::pasteLinkFromClipboard()
+{
+}
+
+BOOL LLTaskInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
+{
+ //llinfos << "LLTaskInvFVBridge::startDrag()" << llendl;
+ if(mPanel)
+ {
+ LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
+ if(object)
+ {
+ LLInventoryItem* inv = NULL;
+ if((inv = (LLInventoryItem*)object->getInventoryObject(mUUID)))
+ {
+ const LLPermissions& perm = inv->getPermissions();
+ bool can_copy = gAgent.allowOperation(PERM_COPY, perm,
+ GP_OBJECT_MANIPULATE);
+ if (object->isAttachment() && !can_copy)
+ {
+ //RN: no copy contents of attachments cannot be dragged out
+ // due to a race condition and possible exploit where
+ // attached objects do not update their inventory items
+ // when their contents are manipulated
+ return FALSE;
+ }
+ if((can_copy && perm.allowTransferTo(gAgent.getID()))
+ || object->permYouOwner())
+// || gAgent.isGodlike())
+
+ {
+ *type = LLViewerAssetType::lookupDragAndDropType(inv->getType());
+
+ *id = inv->getUUID();
+ return TRUE;
+ }
+ }
+ }
+ }
+ return FALSE;
+}
+
+BOOL LLTaskInvFVBridge::dragOrDrop(MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data)
+{
+ //llinfos << "LLTaskInvFVBridge::dragOrDrop()" << llendl;
+ return FALSE;
+}
+
+// virtual
+void LLTaskInvFVBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if (action == "task_buy")
+ {
+ // Check the price of the item.
+ S32 price = getPrice();
+ if (-1 == price)
+ {
+ llwarns << "label_buy_task_bridged_item: Invalid price" << llendl;
+ }
+ else
+ {
+ if (price > 0 && price > gStatusBar->getBalance())
+ {
+ LLFloaterBuyCurrency::buyCurrency("This costs", price);
+ }
+ else
+ {
+ buyItem();
+ }
+ }
+ }
+ else if (action == "task_open")
+ {
+ openItem();
+ }
+ else if (action == "task_properties")
+ {
+ showProperties();
+ }
+}
+
+void LLTaskInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ LLInventoryItem* item = findItem();
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ if (!item)
+ {
+ hide_context_entries(menu, items, disabled_items);
+ return;
+ }
+
+ if(gAgent.allowOperation(PERM_OWNER, item->getPermissions(),
+ GP_OBJECT_MANIPULATE)
+ && item->getSaleInfo().isForSale())
+ {
+ items.push_back(std::string("Task Buy"));
+
+ std::string label= LLTrans::getString("Buy");
+ // Check the price of the item.
+ S32 price = getPrice();
+ if (-1 == price)
+ {
+ llwarns << "label_buy_task_bridged_item: Invalid price" << llendl;
+ }
+ else
+ {
+ std::ostringstream info;
+ info << LLTrans::getString("BuyforL$") << price;
+ label.assign(info.str());
+ }
+
+ const LLView::child_list_t *list = menu.getChildList();
+ LLView::child_list_t::const_iterator itor;
+ for (itor = list->begin(); itor != list->end(); ++itor)
+ {
+ std::string name = (*itor)->getName();
+ LLMenuItemCallGL* menu_itemp = dynamic_cast<LLMenuItemCallGL*>(*itor);
+ if (name == "Task Buy" && menu_itemp)
+ {
+ menu_itemp->setLabel(label);
+ }
+ }
+ }
+ else
+ {
+ items.push_back(std::string("Task Open"));
+ if (!isItemCopyable())
+ {
+ disabled_items.push_back(std::string("Task Open"));
+ }
+ }
+ items.push_back(std::string("Task Properties"));
+ if(isItemRenameable())
+ {
+ items.push_back(std::string("Task Rename"));
+ }
+ if(isItemRemovable())
+ {
+ items.push_back(std::string("Task Remove"));
+ }
+
+ hide_context_entries(menu, items, disabled_items);
+}
+
+
+///----------------------------------------------------------------------------
+/// Class LLTaskFolderBridge
+///----------------------------------------------------------------------------
+
+class LLTaskCategoryBridge : public LLTaskInvFVBridge
+{
+public:
+ LLTaskCategoryBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name);
+
+ virtual LLUIImagePtr getIcon() const;
+ virtual const std::string& getDisplayName() const { return getName(); }
+ virtual BOOL isItemRenameable() const;
+ // virtual BOOL isItemCopyable() const { return FALSE; }
+ virtual BOOL renameItem(const std::string& new_name);
+ virtual BOOL isItemRemovable();
+ virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
+ virtual BOOL hasChildren() const;
+ virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const;
+ virtual BOOL dragOrDrop(MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data);
+};
+
+LLTaskCategoryBridge::LLTaskCategoryBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name) :
+ LLTaskInvFVBridge(panel, uuid, name)
+{
+}
+
+LLUIImagePtr LLTaskCategoryBridge::getIcon() const
+{
+ return LLUI::getUIImage("Inv_FolderClosed");
+}
+
+BOOL LLTaskCategoryBridge::isItemRenameable() const
+{
+ return FALSE;
+}
+
+BOOL LLTaskCategoryBridge::renameItem(const std::string& new_name)
+{
+ return FALSE;
+}
+
+BOOL LLTaskCategoryBridge::isItemRemovable()
+{
+ return FALSE;
+}
+
+void LLTaskCategoryBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+ items.push_back(std::string("Task Open"));
+ hide_context_entries(menu, items, disabled_items);
+}
+
+BOOL LLTaskCategoryBridge::hasChildren() const
+{
+ // return TRUE if we have or do know know if we have children.
+ // *FIX: For now, return FALSE - we will know for sure soon enough.
+ return FALSE;
+}
+
+BOOL LLTaskCategoryBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
+{
+ //llinfos << "LLTaskInvFVBridge::startDrag()" << llendl;
+ if(mPanel)
+ {
+ LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
+ if(object)
+ {
+ LLInventoryItem* inv = NULL;
+ if((inv = (LLInventoryItem*)object->getInventoryObject(mUUID)))
+ {
+ const LLPermissions& perm = inv->getPermissions();
+ bool can_copy = gAgent.allowOperation(PERM_COPY, perm,
+ GP_OBJECT_MANIPULATE);
+ if((can_copy && perm.allowTransferTo(gAgent.getID()))
+ || object->permYouOwner())
+// || gAgent.isGodlike())
+
+ {
+ *type = LLViewerAssetType::lookupDragAndDropType(inv->getType());
+
+ *id = inv->getUUID();
+ return TRUE;
+ }
+ }
+ }
+ }
+ return FALSE;
+}
+
+BOOL LLTaskCategoryBridge::dragOrDrop(MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data)
+{
+ //llinfos << "LLTaskCategoryBridge::dragOrDrop()" << llendl;
+ BOOL accept = FALSE;
+ LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
+ if(object)
+ {
+ switch(cargo_type)
+ {
+ case DAD_CATEGORY:
+ accept = LLToolDragAndDrop::getInstance()->dadUpdateInventoryCategory(object,drop);
+ break;
+ case DAD_TEXTURE:
+ case DAD_SOUND:
+ case DAD_LANDMARK:
+ case DAD_OBJECT:
+ case DAD_NOTECARD:
+ case DAD_CLOTHING:
+ case DAD_BODYPART:
+ case DAD_ANIMATION:
+ case DAD_GESTURE:
+ case DAD_CALLINGCARD:
+ accept = LLToolDragAndDrop::isInventoryDropAcceptable(object, (LLViewerInventoryItem*)cargo_data);
+ if(accept && drop)
+ {
+ LLToolDragAndDrop::dropInventory(object,
+ (LLViewerInventoryItem*)cargo_data,
+ LLToolDragAndDrop::getInstance()->getSource(),
+ LLToolDragAndDrop::getInstance()->getSourceID());
+ }
+ break;
+ case DAD_SCRIPT:
+ // *HACK: In order to resolve SL-22177, we need to block
+ // drags from notecards and objects onto other
+ // objects. uncomment the simpler version when we have
+ // that right.
+ //accept = LLToolDragAndDrop::isInventoryDropAcceptable(object, (LLViewerInventoryItem*)cargo_data);
+ if(LLToolDragAndDrop::isInventoryDropAcceptable(
+ object, (LLViewerInventoryItem*)cargo_data)
+ && (LLToolDragAndDrop::SOURCE_WORLD != LLToolDragAndDrop::getInstance()->getSource())
+ && (LLToolDragAndDrop::SOURCE_NOTECARD != LLToolDragAndDrop::getInstance()->getSource()))
+ {
+ accept = TRUE;
+ }
+ if(accept && drop)
+ {
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)cargo_data;
+ // rez in the script active by default, rez in
+ // inactive if the control key is being held down.
+ BOOL active = ((mask & MASK_CONTROL) == 0);
+ LLToolDragAndDrop::dropScript(object, item, active,
+ LLToolDragAndDrop::getInstance()->getSource(),
+ LLToolDragAndDrop::getInstance()->getSourceID());
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return accept;
+}
+
+///----------------------------------------------------------------------------
+/// Class LLTaskTextureBridge
+///----------------------------------------------------------------------------
+
+class LLTaskTextureBridge : public LLTaskInvFVBridge
+{
+public:
+ LLTaskTextureBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name,
+ LLInventoryType::EType it);
+
+ virtual LLUIImagePtr getIcon() const;
+ virtual void openItem();
+protected:
+ LLInventoryType::EType mInventoryType;
+};
+
+LLTaskTextureBridge::LLTaskTextureBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name,
+ LLInventoryType::EType it) :
+ LLTaskInvFVBridge(panel, uuid, name),
+ mInventoryType(it)
+{
+}
+
+LLUIImagePtr LLTaskTextureBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_TEXTURE, mInventoryType, 0, FALSE);
+}
+
+void LLTaskTextureBridge::openItem()
+{
+ llinfos << "LLTaskTextureBridge::openItem()" << llendl;
+ LLPreviewTexture* preview = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES);
+ if(preview)
+ {
+ preview->setObjectID(mPanel->getTaskUUID());
+ }
+}
+
+
+///----------------------------------------------------------------------------
+/// Class LLTaskSoundBridge
+///----------------------------------------------------------------------------
+
+class LLTaskSoundBridge : public LLTaskInvFVBridge
+{
+public:
+ LLTaskSoundBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name);
+
+ virtual LLUIImagePtr getIcon() const;
+ virtual void openItem();
+ virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action);
+ virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
+ static void openSoundPreview(void* data);
+};
+
+LLTaskSoundBridge::LLTaskSoundBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name) :
+ LLTaskInvFVBridge(panel, uuid, name)
+{
+}
+
+LLUIImagePtr LLTaskSoundBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_SOUND, LLInventoryType::IT_SOUND, 0, FALSE);
+}
+
+void LLTaskSoundBridge::openItem()
+{
+ openSoundPreview((void*)this);
+}
+
+void LLTaskSoundBridge::openSoundPreview(void* data)
+{
+ LLTaskSoundBridge* self = (LLTaskSoundBridge*)data;
+ if(!self)
+ return;
+
+ LLPreviewSound* preview = LLFloaterReg::showTypedInstance<LLPreviewSound>("preview_sound", LLSD(self->mUUID), TAKE_FOCUS_YES);
+ if (preview)
+ {
+ preview->setObjectID(self->mPanel->getTaskUUID());
+ }
+}
+
+// virtual
+void LLTaskSoundBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if (action == "task_play")
+ {
+ LLInventoryItem* item = findItem();
+ if(item)
+ {
+ send_sound_trigger(item->getAssetUUID(), 1.0);
+ }
+ }
+ LLTaskInvFVBridge::performAction(folder, model, action);
+}
+
+void LLTaskSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ LLInventoryItem* item = findItem();
+ if(!item) return;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ if(item->getPermissions().getOwner() != gAgent.getID()
+ && item->getSaleInfo().isForSale())
+ {
+ items.push_back(std::string("Task Buy"));
+
+ std::string label= LLTrans::getString("Buy");
+ // Check the price of the item.
+ S32 price = getPrice();
+ if (-1 == price)
+ {
+ llwarns << "label_buy_task_bridged_item: Invalid price" << llendl;
+ }
+ else
+ {
+ std::ostringstream info;
+ info << LLTrans::getString("BuyforL$") << price;
+ label.assign(info.str());
+ }
+
+ const LLView::child_list_t *list = menu.getChildList();
+ LLView::child_list_t::const_iterator itor;
+ for (itor = list->begin(); itor != list->end(); ++itor)
+ {
+ std::string name = (*itor)->getName();
+ LLMenuItemCallGL* menu_itemp = dynamic_cast<LLMenuItemCallGL*>(*itor);
+ if (name == "Task Buy" && menu_itemp)
+ {
+ menu_itemp->setLabel(label);
+ }
+ }
+ }
+ else
+ {
+ items.push_back(std::string("Task Open"));
+ if (!isItemCopyable())
+ {
+ disabled_items.push_back(std::string("Task Open"));
+ }
+ }
+ items.push_back(std::string("Task Properties"));
+ if(isItemRenameable())
+ {
+ items.push_back(std::string("Task Rename"));
+ }
+ if(isItemRemovable())
+ {
+ items.push_back(std::string("Task Remove"));
+ }
+
+ items.push_back(std::string("Task Play"));
+
+
+ hide_context_entries(menu, items, disabled_items);
+}
+
+///----------------------------------------------------------------------------
+/// Class LLTaskLandmarkBridge
+///----------------------------------------------------------------------------
+
+class LLTaskLandmarkBridge : public LLTaskInvFVBridge
+{
+public:
+ LLTaskLandmarkBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name);
+
+ virtual LLUIImagePtr getIcon() const;
+};
+
+LLTaskLandmarkBridge::LLTaskLandmarkBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name) :
+ LLTaskInvFVBridge(panel, uuid, name)
+{
+}
+
+LLUIImagePtr LLTaskLandmarkBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, 0, FALSE);
+}
+
+
+///----------------------------------------------------------------------------
+/// Class LLTaskCallingCardBridge
+///----------------------------------------------------------------------------
+
+class LLTaskCallingCardBridge : public LLTaskInvFVBridge
+{
+public:
+ LLTaskCallingCardBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name);
+
+ virtual LLUIImagePtr getIcon() const;
+ virtual BOOL isItemRenameable() const;
+ virtual BOOL renameItem(const std::string& new_name);
+};
+
+LLTaskCallingCardBridge::LLTaskCallingCardBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name) :
+ LLTaskInvFVBridge(panel, uuid, name)
+{
+}
+
+LLUIImagePtr LLTaskCallingCardBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, 0, FALSE);
+}
+
+BOOL LLTaskCallingCardBridge::isItemRenameable() const
+{
+ return FALSE;
+}
+
+BOOL LLTaskCallingCardBridge::renameItem(const std::string& new_name)
+{
+ return FALSE;
+}
+
+
+///----------------------------------------------------------------------------
+/// Class LLTaskScriptBridge
+///----------------------------------------------------------------------------
+
+class LLTaskScriptBridge : public LLTaskInvFVBridge
+{
+public:
+ LLTaskScriptBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name);
+
+ virtual LLUIImagePtr getIcon() const;
+ //static BOOL enableIfCopyable( void* userdata );
+};
+
+LLTaskScriptBridge::LLTaskScriptBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name) :
+ LLTaskInvFVBridge(panel, uuid, name)
+{
+}
+
+LLUIImagePtr LLTaskScriptBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE);
+}
+
+
+class LLTaskLSLBridge : public LLTaskScriptBridge
+{
+public:
+ LLTaskLSLBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name);
+
+ virtual void openItem();
+ virtual BOOL removeItem();
+ //virtual void buildContextMenu(LLMenuGL& menu);
+
+ //static void copyToInventory(void* userdata);
+};
+
+LLTaskLSLBridge::LLTaskLSLBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name) :
+ LLTaskScriptBridge(panel, uuid, name)
+{
+}
+
+void LLTaskLSLBridge::openItem()
+{
+ llinfos << "LLTaskLSLBridge::openItem() " << mUUID << llendl;
+ LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
+ if(!object || object->isInventoryPending())
+ {
+ return;
+ }
+ if (object->permModify() || gAgent.isGodlike())
+ {
+ LLLiveLSLEditor* preview = LLFloaterReg::showTypedInstance<LLLiveLSLEditor>("preview_scriptedit", LLSD(mUUID), TAKE_FOCUS_YES);
+ if (preview)
+ {
+ preview->setObjectID(mPanel->getTaskUUID());
+ }
+ }
+ else
+ {
+ LLNotificationsUtil::add("CannotOpenScriptObjectNoMod");
+ }
+}
+
+BOOL LLTaskLSLBridge::removeItem()
+{
+ LLFloaterReg::hideInstance("preview_scriptedit", LLSD(mUUID));
+ return LLTaskInvFVBridge::removeItem();
+}
+
+///----------------------------------------------------------------------------
+/// Class LLTaskObjectBridge
+///----------------------------------------------------------------------------
+
+class LLTaskObjectBridge : public LLTaskInvFVBridge
+{
+public:
+ LLTaskObjectBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name);
+
+ virtual LLUIImagePtr getIcon() const;
+};
+
+LLTaskObjectBridge::LLTaskObjectBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name) :
+ LLTaskInvFVBridge(panel, uuid, name)
+{
+}
+
+LLUIImagePtr LLTaskObjectBridge::getIcon() const
+{
+ BOOL item_is_multi = FALSE;
+ if ( mFlags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS )
+ {
+ item_is_multi = TRUE;
+ }
+
+ return get_item_icon(LLAssetType::AT_OBJECT, LLInventoryType::IT_OBJECT, 0, item_is_multi);
+}
+
+///----------------------------------------------------------------------------
+/// Class LLTaskNotecardBridge
+///----------------------------------------------------------------------------
+
+class LLTaskNotecardBridge : public LLTaskInvFVBridge
+{
+public:
+ LLTaskNotecardBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name);
+
+ virtual LLUIImagePtr getIcon() const;
+ virtual void openItem();
+ virtual BOOL removeItem();
+};
+
+LLTaskNotecardBridge::LLTaskNotecardBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name) :
+ LLTaskInvFVBridge(panel, uuid, name)
+{
+}
+
+LLUIImagePtr LLTaskNotecardBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, 0, FALSE);
+}
+
+void LLTaskNotecardBridge::openItem()
+{
+ LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
+ if(!object || object->isInventoryPending())
+ {
+ return;
+ }
+ if(object->permModify() || gAgent.isGodlike())
+ {
+ LLPreviewNotecard* preview = LLFloaterReg::showTypedInstance<LLPreviewNotecard>("preview_notecard", LLSD(mUUID), TAKE_FOCUS_YES);
+ if (preview)
+ {
+ preview->setObjectID(mPanel->getTaskUUID());
+ }
+ }
+}
+
+BOOL LLTaskNotecardBridge::removeItem()
+{
+ LLFloaterReg::hideInstance("preview_notecard", LLSD(mUUID));
+ return LLTaskInvFVBridge::removeItem();
+}
+
+///----------------------------------------------------------------------------
+/// Class LLTaskGestureBridge
+///----------------------------------------------------------------------------
+
+class LLTaskGestureBridge : public LLTaskInvFVBridge
+{
+public:
+ LLTaskGestureBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name);
+
+ virtual LLUIImagePtr getIcon() const;
+ virtual void openItem();
+ virtual BOOL removeItem();
+};
+
+LLTaskGestureBridge::LLTaskGestureBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name) :
+ LLTaskInvFVBridge(panel, uuid, name)
+{
+}
+
+LLUIImagePtr LLTaskGestureBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, 0, FALSE);
+}
+
+void LLTaskGestureBridge::openItem()
+{
+ LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
+ if(!object || object->isInventoryPending())
+ {
+ return;
+ }
+ LLPreviewGesture::show(mUUID, mPanel->getTaskUUID());
+}
+
+BOOL LLTaskGestureBridge::removeItem()
+{
+ // Don't need to deactivate gesture because gestures inside objects can never be active.
+ LLFloaterReg::hideInstance("preview_gesture", LLSD(mUUID));
+ return LLTaskInvFVBridge::removeItem();
+}
+
+///----------------------------------------------------------------------------
+/// Class LLTaskAnimationBridge
+///----------------------------------------------------------------------------
+
+class LLTaskAnimationBridge : public LLTaskInvFVBridge
+{
+public:
+ LLTaskAnimationBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name);
+
+ virtual LLUIImagePtr getIcon() const;
+ virtual void openItem();
+ virtual BOOL removeItem();
+};
+
+LLTaskAnimationBridge::LLTaskAnimationBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name) :
+ LLTaskInvFVBridge(panel, uuid, name)
+{
+}
+
+LLUIImagePtr LLTaskAnimationBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_ANIMATION, LLInventoryType::IT_ANIMATION, 0, FALSE);
+}
+
+void LLTaskAnimationBridge::openItem()
+{
+ LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
+ if(!object || object->isInventoryPending())
+ {
+ return;
+ }
+
+ LLPreviewAnim* preview = LLFloaterReg::showTypedInstance<LLPreviewAnim>("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES);
+ if (preview && (object->permModify() || gAgent.isGodlike()))
+ {
+ preview->setObjectID(mPanel->getTaskUUID());
+ }
+}
+
+BOOL LLTaskAnimationBridge::removeItem()
+{
+ LLFloaterReg::hideInstance("preview_anim", LLSD(mUUID));
+ return LLTaskInvFVBridge::removeItem();
+}
+
+///----------------------------------------------------------------------------
+/// Class LLTaskWearableBridge
+///----------------------------------------------------------------------------
+
+class LLTaskWearableBridge : public LLTaskInvFVBridge
+{
+public:
+ LLTaskWearableBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name,
+ LLAssetType::EType asset_type,
+ U32 flags);
+
+ virtual LLUIImagePtr getIcon() const;
+
+protected:
+ LLAssetType::EType mAssetType;
+};
+
+LLTaskWearableBridge::LLTaskWearableBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name,
+ LLAssetType::EType asset_type,
+ U32 flags) :
+ LLTaskInvFVBridge(panel, uuid, name, flags),
+ mAssetType( asset_type )
+{
+}
+
+LLUIImagePtr LLTaskWearableBridge::getIcon() const
+{
+ return get_item_icon(mAssetType, LLInventoryType::IT_WEARABLE, mFlags, FALSE );
+}
+
+
+///----------------------------------------------------------------------------
+/// LLTaskInvFVBridge impl
+//----------------------------------------------------------------------------
+
+LLTaskInvFVBridge* LLTaskInvFVBridge::createObjectBridge(LLPanelObjectInventory* panel,
+ LLInventoryObject* object)
+{
+ LLTaskInvFVBridge* new_bridge = NULL;
+ LLAssetType::EType type = object->getType();
+ LLInventoryItem* item = NULL;
+ switch(type)
+ {
+ case LLAssetType::AT_TEXTURE:
+ item = (LLInventoryItem*)object;
+ new_bridge = new LLTaskTextureBridge(panel,
+ object->getUUID(),
+ object->getName(),
+ item->getInventoryType());
+ break;
+ case LLAssetType::AT_SOUND:
+ new_bridge = new LLTaskSoundBridge(panel,
+ object->getUUID(),
+ object->getName());
+ break;
+ case LLAssetType::AT_LANDMARK:
+ new_bridge = new LLTaskLandmarkBridge(panel,
+ object->getUUID(),
+ object->getName());
+ break;
+ case LLAssetType::AT_CALLINGCARD:
+ new_bridge = new LLTaskCallingCardBridge(panel,
+ object->getUUID(),
+ object->getName());
+ break;
+ case LLAssetType::AT_SCRIPT:
+ // OLD SCRIPTS DEPRECATED - JC
+ llwarns << "Old script" << llendl;
+ //new_bridge = new LLTaskOldScriptBridge(panel,
+ // object->getUUID(),
+ // object->getName());
+ break;
+ case LLAssetType::AT_OBJECT:
+ new_bridge = new LLTaskObjectBridge(panel,
+ object->getUUID(),
+ object->getName());
+ break;
+ case LLAssetType::AT_NOTECARD:
+ new_bridge = new LLTaskNotecardBridge(panel,
+ object->getUUID(),
+ object->getName());
+ break;
+ case LLAssetType::AT_ANIMATION:
+ new_bridge = new LLTaskAnimationBridge(panel,
+ object->getUUID(),
+ object->getName());
+ break;
+ case LLAssetType::AT_GESTURE:
+ new_bridge = new LLTaskGestureBridge(panel,
+ object->getUUID(),
+ object->getName());
+ break;
+ case LLAssetType::AT_CLOTHING:
+ case LLAssetType::AT_BODYPART:
+ item = (LLInventoryItem*)object;
+ new_bridge = new LLTaskWearableBridge(panel,
+ object->getUUID(),
+ object->getName(),
+ type,
+ item->getFlags());
+ break;
+ case LLAssetType::AT_CATEGORY:
+ new_bridge = new LLTaskCategoryBridge(panel,
+ object->getUUID(),
+ object->getName());
+ break;
+ case LLAssetType::AT_LSL_TEXT:
+ new_bridge = new LLTaskLSLBridge(panel,
+ object->getUUID(),
+ object->getName());
+ break;
+
+ break;
+ default:
+ llinfos << "Unhandled inventory type (llassetstorage.h): "
+ << (S32)type << llendl;
+ break;
+ }
+ return new_bridge;
+}
+
+
+///----------------------------------------------------------------------------
+/// Class LLPanelObjectInventory
+///----------------------------------------------------------------------------
+
+static LLDefaultChildRegistry::Register<LLPanelObjectInventory> r("panel_inventory_object");
+
+void do_nothing()
+{
+}
+
+// Default constructor
+LLPanelObjectInventory::LLPanelObjectInventory(const LLPanelObjectInventory::Params& p) :
+ LLPanel(p),
+ mScroller(NULL),
+ mFolders(NULL),
+ mHaveInventory(FALSE),
+ mIsInventoryEmpty(TRUE),
+ mInventoryNeedsUpdate(FALSE)
+{
+ // Setup context menu callbacks
+ mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLPanelObjectInventory::doToSelected, this, _2));
+ mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH));
+ mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND));
+ mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&do_nothing));
+ mCommitCallbackRegistrar.add("Inventory.AttachObject", boost::bind(&do_nothing));
+ mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&do_nothing));
+}
+
+// Destroys the object
+LLPanelObjectInventory::~LLPanelObjectInventory()
+{
+ if (!gIdleCallbacks.deleteFunction(idle, this))
+ {
+ llwarns << "LLPanelObjectInventory::~LLPanelObjectInventory() failed to delete callback" << llendl;
+ }
+}
+
+BOOL LLPanelObjectInventory::postBuild()
+{
+ // clear contents and initialize menus, sets up mFolders
+ reset();
+
+ // Register an idle update callback
+ gIdleCallbacks.addFunction(idle, this);
+
+ return TRUE;
+}
+
+void LLPanelObjectInventory::doToSelected(const LLSD& userdata)
+{
+ mFolders->doToSelected(&gInventory, userdata);
+}
+
+void LLPanelObjectInventory::clearContents()
+{
+ mHaveInventory = FALSE;
+ mIsInventoryEmpty = TRUE;
+ if (LLToolDragAndDrop::getInstance() && LLToolDragAndDrop::getInstance()->getSource() == LLToolDragAndDrop::SOURCE_WORLD)
+ {
+ LLToolDragAndDrop::getInstance()->endDrag();
+ }
+
+ if( mScroller )
+ {
+ // removes mFolders
+ removeChild( mScroller ); //*TODO: Really shouldn't do this during draw()/refresh()
+ mScroller->die();
+ mScroller = NULL;
+ mFolders = NULL;
+ }
+}
+
+
+void LLPanelObjectInventory::reset()
+{
+ clearContents();
+
+ setBorderVisible(FALSE);
+
+ mCommitCallbackRegistrar.pushScope(); // push local callbacks
+
+ LLRect dummy_rect(0, 1, 1, 0);
+ LLFolderView::Params p;
+ p.name = "task inventory";
+ p.task_id = getTaskUUID();
+ p.parent_panel = this;
+ p.tool_tip= p.name;
+ mFolders = LLUICtrlFactory::create<LLFolderView>(p);
+ // this ensures that we never say "searching..." or "no items found"
+ mFolders->getFilter()->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS);
+ mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar);
+
+ LLRect scroller_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
+ LLScrollContainer::Params scroll_p;
+ scroll_p.name("task inventory scroller");
+ scroll_p.rect(scroller_rect);
+ scroll_p.follows.flags(FOLLOWS_ALL);
+ mScroller = LLUICtrlFactory::create<LLScrollContainer>(scroll_p);
+ addChild(mScroller);
+ mScroller->addChild(mFolders);
+
+ mFolders->setScrollContainer( mScroller );
+
+ mCommitCallbackRegistrar.popScope();
+}
+
+void LLPanelObjectInventory::inventoryChanged(LLViewerObject* object,
+ InventoryObjectList* inventory,
+ S32 serial_num,
+ void* data)
+{
+ if(!object) return;
+
+ //llinfos << "invetnory arrived: \n"
+ // << " panel UUID: " << panel->mTaskUUID << "\n"
+ // << " task UUID: " << object->mID << llendl;
+ if(mTaskUUID == object->mID)
+ {
+ mInventoryNeedsUpdate = TRUE;
+ }
+
+ // refresh any properties floaters that are hanging around.
+ if(inventory)
+ {
+ for (InventoryObjectList::const_iterator iter = inventory->begin();
+ iter != inventory->end(); )
+ {
+ LLInventoryObject* item = *iter++;
+ LLFloaterProperties* floater = LLFloaterReg::findTypedInstance<LLFloaterProperties>("properites", item->getUUID());
+ if(floater)
+ {
+ floater->refresh();
+ }
+ }
+ }
+}
+
+void LLPanelObjectInventory::updateInventory()
+{
+ //llinfos << "inventory arrived: \n"
+ // << " panel UUID: " << panel->mTaskUUID << "\n"
+ // << " task UUID: " << object->mID << llendl;
+ // We're still interested in this task's inventory.
+ std::set<LLUUID> selected_items;
+ BOOL inventory_has_focus = FALSE;
+ if (mHaveInventory && mFolders->getNumSelectedDescendants())
+ {
+ mFolders->getSelectionList(selected_items);
+ inventory_has_focus = gFocusMgr.childHasKeyboardFocus(mFolders);
+ }
+
+ reset();
+
+ LLViewerObject* objectp = gObjectList.findObject(mTaskUUID);
+ if (objectp)
+ {
+ LLInventoryObject* inventory_root = objectp->getInventoryRoot();
+ InventoryObjectList contents;
+ objectp->getInventoryContents(contents);
+ if (inventory_root)
+ {
+ createFolderViews(inventory_root, contents);
+ mHaveInventory = TRUE;
+ mIsInventoryEmpty = FALSE;
+ mFolders->setEnabled(TRUE);
+ }
+ else
+ {
+ // TODO: create an empty inventory
+ mIsInventoryEmpty = TRUE;
+ mHaveInventory = TRUE;
+ }
+ }
+ else
+ {
+ // TODO: create an empty inventory
+ mIsInventoryEmpty = TRUE;
+ mHaveInventory = TRUE;
+ }
+
+ // restore previous selection
+ std::set<LLUUID>::iterator selection_it;
+ BOOL first_item = TRUE;
+ for (selection_it = selected_items.begin(); selection_it != selected_items.end(); ++selection_it)
+ {
+ LLFolderViewItem* selected_item = mFolders->getItemByID(*selection_it);
+ if (selected_item)
+ {
+ //HACK: "set" first item then "change" each other one to get keyboard focus right
+ if (first_item)
+ {
+ mFolders->setSelection(selected_item, TRUE, inventory_has_focus);
+ first_item = FALSE;
+ }
+ else
+ {
+ mFolders->changeSelection(selected_item, TRUE);
+ }
+ }
+ }
+
+ mFolders->requestArrange();
+ mInventoryNeedsUpdate = FALSE;
+ // Edit menu handler is set in onFocusReceived
+}
+
+// *FIX: This is currently a very expensive operation, because we have
+// to iterate through the inventory one time for each category. This
+// leads to an N^2 based on the category count. This could be greatly
+// speeded with an efficient multimap implementation, but we don't
+// have that in our current arsenal.
+void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root, InventoryObjectList& contents)
+{
+ if (!inventory_root)
+ {
+ return;
+ }
+ // Create a visible root category.
+ LLTaskInvFVBridge* bridge = NULL;
+ bridge = LLTaskInvFVBridge::createObjectBridge(this, inventory_root);
+ if(bridge)
+ {
+ LLFolderViewFolder* new_folder = NULL;
+ LLFolderViewFolder::Params p;
+ p.name = inventory_root->getName();
+ p.icon = LLUI::getUIImage("Inv_FolderClosed");
+ p.icon_open = LLUI::getUIImage("Inv_FolderOpen");
+ p.root = mFolders;
+ p.listener = bridge;
+ p.tool_tip = p.name;
+ new_folder = LLUICtrlFactory::create<LLFolderViewFolder>(p);
+ new_folder->addToFolder(mFolders, mFolders);
+ new_folder->toggleOpen();
+
+ createViewsForCategory(&contents, inventory_root, new_folder);
+ }
+}
+
+typedef std::pair<LLInventoryObject*, LLFolderViewFolder*> obj_folder_pair;
+
+void LLPanelObjectInventory::createViewsForCategory(InventoryObjectList* inventory,
+ LLInventoryObject* parent,
+ LLFolderViewFolder* folder)
+{
+ // Find all in the first pass
+ LLDynamicArray<obj_folder_pair*> child_categories;
+ LLTaskInvFVBridge* bridge;
+ LLFolderViewItem* view;
+
+ InventoryObjectList::iterator it = inventory->begin();
+ InventoryObjectList::iterator end = inventory->end();
+ for( ; it != end; ++it)
+ {
+ LLInventoryObject* obj = *it;
+
+ if(parent->getUUID() == obj->getParentUUID())
+ {
+ bridge = LLTaskInvFVBridge::createObjectBridge(this, obj);
+ if(!bridge)
+ {
+ continue;
+ }
+ if(LLAssetType::AT_CATEGORY == obj->getType())
+ {
+ LLFolderViewFolder::Params p;
+ p.name = obj->getName();
+ p.icon = LLUI::getUIImage("Inv_FolderClosed");
+ p.icon_open = LLUI::getUIImage("Inv_FolderOpen");
+ p.root = mFolders;
+ p.listener = bridge;
+ p.tool_tip = p.name;
+ view = LLUICtrlFactory::create<LLFolderViewFolder>(p);
+ child_categories.put(new obj_folder_pair(obj,
+ (LLFolderViewFolder*)view));
+ }
+ else
+ {
+ LLFolderViewItem::Params params;
+ params.name(obj->getName());
+ params.icon(bridge->getIcon());
+ params.creation_date(bridge->getCreationDate());
+ params.root(mFolders);
+ params.listener(bridge);
+ params.rect(LLRect());
+ params.tool_tip = params.name;
+ view = LLUICtrlFactory::create<LLFolderViewItem> (params);
+ }
+ view->addToFolder(folder, mFolders);
+ }
+ }
+
+ // now, for each category, do the second pass
+ for(S32 i = 0; i < child_categories.count(); i++)
+ {
+ createViewsForCategory(inventory, child_categories[i]->first,
+ child_categories[i]->second );
+ delete child_categories[i];
+ }
+}
+
+void LLPanelObjectInventory::refresh()
+{
+ //llinfos << "LLPanelObjectInventory::refresh()" << llendl;
+ BOOL has_inventory = FALSE;
+ const BOOL non_root_ok = TRUE;
+ LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(NULL, non_root_ok);
+ if(node)
+ {
+ LLViewerObject* object = node->getObject();
+ if(object && ((LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() == 1)
+ || (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1)))
+ {
+ // determine if we need to make a request. Start with a
+ // default based on if we have inventory at all.
+ BOOL make_request = !mHaveInventory;
+
+ // If the task id is different than what we've stored,
+ // then make the request.
+ if(mTaskUUID != object->mID)
+ {
+ mTaskUUID = object->mID;
+ make_request = TRUE;
+
+ // This is a new object so pre-emptively clear the contents
+ // Otherwise we show the old stuff until the update comes in
+ clearContents();
+
+ // Register for updates from this object,
+ registerVOInventoryListener(object,NULL);
+ }
+
+ // Based on the node information, we may need to dirty the
+ // object inventory and get it again.
+ if(node->mValid)
+ {
+ if(node->mInventorySerial != object->getInventorySerial() || object->isInventoryDirty())
+ {
+ make_request = TRUE;
+ }
+ }
+
+ // do the request if necessary.
+ if(make_request)
+ {
+ requestVOInventory();
+ }
+ has_inventory = TRUE;
+ }
+ }
+ if(!has_inventory)
+ {
+ mTaskUUID = LLUUID::null;
+ removeVOInventoryListener();
+ clearContents();
+ }
+ //llinfos << "LLPanelObjectInventory::refresh() " << mTaskUUID << llendl;
+}
+
+void LLPanelObjectInventory::removeSelectedItem()
+{
+ if(mFolders)
+ {
+ mFolders->removeSelectedItems();
+ }
+}
+
+void LLPanelObjectInventory::startRenamingSelectedItem()
+{
+ if(mFolders)
+ {
+ mFolders->startRenamingSelectedItem();
+ }
+}
+
+void LLPanelObjectInventory::draw()
+{
+ LLPanel::draw();
+
+ if(mIsInventoryEmpty)
+ {
+ if((LLUUID::null != mTaskUUID) && (!mHaveInventory))
+ {
+ LLFontGL::getFontSansSerif()->renderUTF8(LLTrans::getString("LoadingContents"), 0,
+ (S32)(getRect().getWidth() * 0.5f),
+ 10,
+ LLColor4( 1, 1, 1, 1 ),
+ LLFontGL::HCENTER,
+ LLFontGL::BOTTOM);
+ }
+ else if(mHaveInventory)
+ {
+ LLFontGL::getFontSansSerif()->renderUTF8(LLTrans::getString("NoContents"), 0,
+ (S32)(getRect().getWidth() * 0.5f),
+ 10,
+ LLColor4( 1, 1, 1, 1 ),
+ LLFontGL::HCENTER,
+ LLFontGL::BOTTOM);
+ }
+ }
+}
+
+void LLPanelObjectInventory::deleteAllChildren()
+{
+ mScroller = NULL;
+ mFolders = NULL;
+ LLView::deleteAllChildren();
+}
+
+BOOL LLPanelObjectInventory::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg)
+{
+ if (mFolders && mHaveInventory)
+ {
+ LLFolderViewItem* folderp = mFolders->getNextFromChild(NULL);
+ if (!folderp)
+ {
+ return FALSE;
+ }
+ // Try to pass on unmodified mouse coordinates
+ S32 local_x = x - mFolders->getRect().mLeft;
+ S32 local_y = y - mFolders->getRect().mBottom;
+
+ if (mFolders->pointInView(local_x, local_y))
+ {
+ return mFolders->handleDragAndDrop(local_x, local_y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+ }
+ else
+ {
+ //force mouse coordinates to be inside folder rectangle
+ return mFolders->handleDragAndDrop(5, 1, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+ }
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+//static
+void LLPanelObjectInventory::idle(void* user_data)
+{
+ LLPanelObjectInventory* self = (LLPanelObjectInventory*)user_data;
+
+
+ if (self->mInventoryNeedsUpdate)
+ {
+ self->updateInventory();
+ }
+}
+
+void LLPanelObjectInventory::onFocusLost()
+{
+ // inventory no longer handles cut/copy/paste/delete
+ if (LLEditMenuHandler::gEditMenuHandler == mFolders)
+ {
+ LLEditMenuHandler::gEditMenuHandler = NULL;
+ }
+
+ LLPanel::onFocusLost();
+}
+
+void LLPanelObjectInventory::onFocusReceived()
+{
+ // inventory now handles cut/copy/paste/delete
+ LLEditMenuHandler::gEditMenuHandler = mFolders;
+
+ LLPanel::onFocusReceived();
+}
diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h
new file mode 100644
index 0000000000..bc339ece35
--- /dev/null
+++ b/indra/newview/llpanelobjectinventory.h
@@ -0,0 +1,105 @@
+/**
+ * @file llpanelobjectinventory.h
+ * @brief LLPanelObjectInventory class definition
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELOBJECTINVENTORY_H
+#define LL_LLPANELOBJECTINVENTORY_H
+
+#include "llvoinventorylistener.h"
+#include "llpanel.h"
+
+#include "llinventory.h"
+
+class LLScrollContainer;
+class LLFolderView;
+class LLFolderViewFolder;
+class LLViewerObject;
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLPanelObjectInventory
+//
+// This class represents the panel used to view and control a
+// particular task's inventory.
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLPanelObjectInventory : public LLPanel, public LLVOInventoryListener
+{
+public:
+ // dummy param block for template registration purposes
+ struct Params : public LLPanel::Params {};
+
+ LLPanelObjectInventory(const Params&);
+ virtual ~LLPanelObjectInventory();
+
+ virtual BOOL postBuild();
+
+ void doToSelected(const LLSD& userdata);
+
+ void refresh();
+ const LLUUID& getTaskUUID() { return mTaskUUID;}
+ void removeSelectedItem();
+ void startRenamingSelectedItem();
+
+ LLFolderView* getRootFolder() const { return mFolders; }
+
+ virtual void draw();
+ virtual void deleteAllChildren();
+ virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg);
+
+ /*virtual*/ void onFocusLost();
+ /*virtual*/ void onFocusReceived();
+
+ static void idle(void* user_data);
+
+protected:
+ void reset();
+ /*virtual*/ void inventoryChanged(LLViewerObject* object,
+ InventoryObjectList* inventory,
+ S32 serial_num,
+ void* user_data);
+ void updateInventory();
+ void createFolderViews(LLInventoryObject* inventory_root, InventoryObjectList& contents);
+ void createViewsForCategory(InventoryObjectList* inventory,
+ LLInventoryObject* parent,
+ LLFolderViewFolder* folder);
+ void clearContents();
+
+private:
+ LLScrollContainer* mScroller;
+ LLFolderView* mFolders;
+
+ LLUUID mTaskUUID;
+ BOOL mHaveInventory;
+ BOOL mIsInventoryEmpty;
+ BOOL mInventoryNeedsUpdate;
+};
+
+#endif // LL_LLPANELOBJECTINVENTORY_H
diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp
new file mode 100644
index 0000000000..cf903958ee
--- /dev/null
+++ b/indra/newview/llpaneloutfitsinventory.cpp
@@ -0,0 +1,633 @@
+/**
+ * @file llpaneloutfitsinventory.cpp
+ * @brief Outfits inventory panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpaneloutfitsinventory.h"
+
+#include "llagent.h"
+#include "llagentwearables.h"
+#include "llappearancemgr.h"
+
+#include "llbutton.h"
+#include "llfloaterreg.h"
+#include "llfloaterworldmap.h"
+#include "llfloaterinventory.h"
+#include "llfoldervieweventlistener.h"
+#include "llinventoryfunctions.h"
+#include "llinventorypanel.h"
+#include "lllandmark.h"
+#include "lllineeditor.h"
+#include "llmodaldialog.h"
+#include "llsidepanelappearance.h"
+#include "llsidetray.h"
+#include "lltabcontainer.h"
+#include "llviewerfoldertype.h"
+#include "llviewerjointattachment.h"
+#include "llvoavatarself.h"
+
+// List Commands
+#include "lldndbutton.h"
+#include "llmenugl.h"
+#include "llviewermenu.h"
+
+#include "llviewercontrol.h"
+
+static const std::string OUTFITS_TAB_NAME = "outfitslist_tab";
+static const std::string COF_TAB_NAME = "cof_tab";
+
+static LLRegisterPanelClassWrapper<LLPanelOutfitsInventory> t_inventory("panel_outfits_inventory");
+bool LLPanelOutfitsInventory::sShowDebugEditor = false;
+
+class LLOutfitSaveAsDialog : public LLModalDialog
+{
+private:
+ std::string mItemName;
+ std::string mTempItemName;
+
+ boost::signals2::signal<void (const std::string&)> mSaveAsSignal;
+
+public:
+ LLOutfitSaveAsDialog( const LLSD& key )
+ : LLModalDialog( key ),
+ mTempItemName(key.asString())
+ {
+ }
+
+ BOOL postBuild()
+ {
+ getChild<LLUICtrl>("Save")->setCommitCallback(boost::bind(&LLOutfitSaveAsDialog::onSave, this ));
+ getChild<LLUICtrl>("Cancel")->setCommitCallback(boost::bind(&LLOutfitSaveAsDialog::onCancel, this ));
+
+ childSetTextArg("name ed", "[DESC]", mTempItemName);
+ return TRUE;
+ }
+
+ void setSaveAsCommit( const boost::signals2::signal<void (const std::string&)>::slot_type& cb )
+ {
+ mSaveAsSignal.connect(cb);
+ }
+
+ virtual void onOpen(const LLSD& key)
+ {
+ LLLineEditor* edit = getChild<LLLineEditor>("name ed");
+ if (edit)
+ {
+ edit->setFocus(TRUE);
+ edit->selectAll();
+ }
+ }
+
+ void onSave()
+ {
+ mItemName = childGetValue("name ed").asString();
+ LLStringUtil::trim(mItemName);
+ if( !mItemName.empty() )
+ {
+ mSaveAsSignal(mItemName);
+ closeFloater(); // destroys this object
+ }
+ }
+
+ void onCancel()
+ {
+ closeFloater(); // destroys this object
+ }
+};
+
+LLPanelOutfitsInventory::LLPanelOutfitsInventory() :
+ mActivePanel(NULL),
+ mParent(NULL)
+{
+ mSavedFolderState = new LLSaveFolderState();
+ mSavedFolderState->setApply(FALSE);
+
+ static bool registered_dialog = false;
+ if (!registered_dialog)
+ {
+ LLFloaterReg::add("outfit_save_as", "floater_outfit_save_as.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLOutfitSaveAsDialog>);
+ registered_dialog = true;
+ }
+}
+
+LLPanelOutfitsInventory::~LLPanelOutfitsInventory()
+{
+ delete mSavedFolderState;
+}
+
+// virtual
+BOOL LLPanelOutfitsInventory::postBuild()
+{
+ sShowDebugEditor = gSavedSettings.getBOOL("ShowDebugAppearanceEditor");
+ initTabPanels();
+ initListCommandsHandlers();
+
+ return TRUE;
+}
+
+// virtual
+void LLPanelOutfitsInventory::onOpen(const LLSD& key)
+{
+ // Make sure we know which tab is selected, update the filter,
+ // and update verbs.
+ onTabChange();
+}
+
+void LLPanelOutfitsInventory::updateVerbs()
+{
+ if (mParent)
+ {
+ mParent->updateVerbs();
+ }
+
+ if (mListCommands)
+ {
+ mListCommands->childSetVisible("look_edit_btn",sShowDebugEditor);
+ updateListCommands();
+ }
+}
+
+void LLPanelOutfitsInventory::setParent(LLSidepanelAppearance* parent)
+{
+ mParent = parent;
+}
+
+// virtual
+void LLPanelOutfitsInventory::onSearchEdit(const std::string& string)
+{
+ mFilterSubString = string;
+ if (string == "")
+ {
+ mActivePanel->setFilterSubString(LLStringUtil::null);
+
+ // re-open folders that were initially open
+ mSavedFolderState->setApply(TRUE);
+ getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
+ LLOpenFoldersWithSelection opener;
+ getRootFolder()->applyFunctorRecursively(opener);
+ getRootFolder()->scrollToShowSelection();
+ }
+
+ gInventory.startBackgroundFetch();
+
+ if (mActivePanel->getFilterSubString().empty() && string.empty())
+ {
+ // current filter and new filter empty, do nothing
+ return;
+ }
+
+ // save current folder open state if no filter currently applied
+ if (getRootFolder()->getFilterSubString().empty())
+ {
+ mSavedFolderState->setApply(FALSE);
+ getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
+ }
+
+ // set new filter string
+ mActivePanel->setFilterSubString(string);
+}
+
+void LLPanelOutfitsInventory::onWearButtonClick()
+{
+ LLFolderViewEventListener* listenerp = getCorrectListenerForAction();
+ if (listenerp)
+ {
+ listenerp->performAction(NULL, NULL,"replaceoutfit");
+ }
+}
+
+void LLPanelOutfitsInventory::onAdd()
+{
+ LLFolderViewEventListener* listenerp = getCorrectListenerForAction();
+ if (listenerp)
+ {
+ listenerp->performAction(NULL, NULL,"addtooutfit");
+ }
+}
+
+void LLPanelOutfitsInventory::onRemove()
+{
+ LLFolderViewEventListener* listenerp = getCorrectListenerForAction();
+ if (listenerp)
+ {
+ listenerp->performAction(NULL, NULL,"removefromoutfit");
+ }
+}
+
+void LLPanelOutfitsInventory::onEdit()
+{
+}
+
+void LLPanelOutfitsInventory::onSave()
+{
+ std::string outfit_name;
+
+ if (!LLAppearanceManager::getInstance()->getBaseOutfitName(outfit_name))
+ {
+ outfit_name = LLViewerFolderType::lookupNewCategoryName(LLFolderType::FT_OUTFIT);
+ }
+
+ LLOutfitSaveAsDialog* save_as_dialog = LLFloaterReg::showTypedInstance<LLOutfitSaveAsDialog>("outfit_save_as", LLSD(outfit_name), TRUE);
+ if (save_as_dialog)
+ {
+ save_as_dialog->setSaveAsCommit(boost::bind(&LLPanelOutfitsInventory::onSaveCommit, this, _1 ));
+ }
+}
+
+void LLPanelOutfitsInventory::onSaveCommit(const std::string& outfit_name)
+{
+ LLUUID outfit_folder = gAgentWearables.makeNewOutfitLinks(outfit_name);
+ LLSD key;
+ LLSideTray::getInstance()->showPanel("panel_outfits_inventory", key);
+
+ if (mAppearanceTabs)
+ {
+ mAppearanceTabs->selectTabByName(OUTFITS_TAB_NAME);
+ }
+}
+
+void LLPanelOutfitsInventory::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action)
+{
+ updateVerbs();
+ if (getRootFolder()->needsAutoRename() && items.size())
+ {
+ getRootFolder()->startRenamingSelectedItem();
+ getRootFolder()->setNeedsAutoRename(FALSE);
+ }
+}
+
+void LLPanelOutfitsInventory::onSelectorButtonClicked()
+{
+ LLFolderViewItem* cur_item = getRootFolder()->getCurSelectedItem();
+
+ LLFolderViewEventListener* listenerp = cur_item->getListener();
+ if (getIsCorrectType(listenerp))
+ {
+ LLSD key;
+ key["type"] = "look";
+ key["id"] = listenerp->getUUID();
+
+ LLSideTray::getInstance()->showPanel("sidepanel_appearance", key);
+ }
+}
+
+LLFolderViewEventListener *LLPanelOutfitsInventory::getCorrectListenerForAction()
+{
+ LLFolderViewItem* current_item = getRootFolder()->getCurSelectedItem();
+ if (!current_item)
+ return NULL;
+
+ LLFolderViewEventListener* listenerp = current_item->getListener();
+ if (getIsCorrectType(listenerp))
+ {
+ return listenerp;
+ }
+ return NULL;
+}
+
+bool LLPanelOutfitsInventory::getIsCorrectType(const LLFolderViewEventListener *listenerp) const
+{
+ if (listenerp->getInventoryType() == LLInventoryType::IT_CATEGORY)
+ {
+ LLViewerInventoryCategory *cat = gInventory.getCategory(listenerp->getUUID());
+ if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+LLFolderView *LLPanelOutfitsInventory::getRootFolder()
+{
+ return mActivePanel->getRootFolder();
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// List Commands //
+
+void LLPanelOutfitsInventory::initListCommandsHandlers()
+{
+ mListCommands = getChild<LLPanel>("bottom_panel");
+
+ mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelOutfitsInventory::onGearButtonClick, this));
+ mListCommands->childSetAction("trash_btn", boost::bind(&LLPanelOutfitsInventory::onTrashButtonClick, this));
+ mListCommands->childSetAction("make_outfit_btn", boost::bind(&LLPanelOutfitsInventory::onAddButtonClick, this));
+ mListCommands->childSetAction("wear_btn", boost::bind(&LLPanelOutfitsInventory::onWearButtonClick, this));
+
+ mListCommands->childSetAction("look_edit_btn", boost::bind(&LLPanelOutfitsInventory::onSelectorButtonClicked, this));
+
+ LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>("trash_btn");
+ trash_btn->setDragAndDropHandler(boost::bind(&LLPanelOutfitsInventory::handleDragAndDropToTrash, this
+ , _4 // BOOL drop
+ , _5 // EDragAndDropType cargo_type
+ , _7 // EAcceptance* accept
+ ));
+
+ mCommitCallbackRegistrar.add("panel_outfits_inventory_gear_default.Custom.Action",
+ boost::bind(&LLPanelOutfitsInventory::onCustomAction, this, _2));
+ mEnableCallbackRegistrar.add("panel_outfits_inventory_gear_default.Enable",
+ boost::bind(&LLPanelOutfitsInventory::isActionEnabled, this, _2));
+ mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("panel_outfits_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+}
+
+void LLPanelOutfitsInventory::updateListCommands()
+{
+ bool trash_enabled = isActionEnabled("delete");
+ bool wear_enabled = isActionEnabled("wear");
+ bool make_outfit_enabled = isActionEnabled("make_outfit");
+
+ mListCommands->childSetEnabled("trash_btn", trash_enabled);
+ mListCommands->childSetEnabled("wear_btn", wear_enabled);
+ mListCommands->childSetVisible("wear_btn", wear_enabled);
+ mListCommands->childSetEnabled("make_outfit_btn", make_outfit_enabled);
+}
+
+void LLPanelOutfitsInventory::onGearButtonClick()
+{
+ showActionMenu(mMenuGearDefault,"options_gear_btn");
+}
+
+void LLPanelOutfitsInventory::onAddButtonClick()
+{
+ onSave();
+}
+
+void LLPanelOutfitsInventory::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
+{
+ if (menu)
+ {
+ menu->buildDrawLabels();
+ menu->updateParent(LLMenuGL::sMenuContainer);
+ LLView* spawning_view = getChild<LLView> (spawning_view_name);
+ S32 menu_x, menu_y;
+ //show menu in co-ordinates of panel
+ spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this);
+ menu_y += menu->getRect().getHeight();
+ LLMenuGL::showPopup(this, menu, menu_x, menu_y);
+ }
+}
+
+void LLPanelOutfitsInventory::onTrashButtonClick()
+{
+ onClipboardAction("delete");
+}
+
+void LLPanelOutfitsInventory::onClipboardAction(const LLSD& userdata)
+{
+ std::string command_name = userdata.asString();
+ getActivePanel()->getRootFolder()->doToSelected(getActivePanel()->getModel(),command_name);
+ updateListCommands();
+ updateVerbs();
+}
+
+void LLPanelOutfitsInventory::onCustomAction(const LLSD& userdata)
+{
+ if (!isActionEnabled(userdata))
+ return;
+
+ const std::string command_name = userdata.asString();
+ if (command_name == "new")
+ {
+ onSave();
+ }
+ if (command_name == "edit")
+ {
+ onEdit();
+ }
+ if (command_name == "wear")
+ {
+ onWearButtonClick();
+ }
+ // Note: This option has been removed from the gear menu.
+ if (command_name == "add")
+ {
+ onAdd();
+ }
+ if (command_name == "remove")
+ {
+ onRemove();
+ }
+ if (command_name == "rename")
+ {
+ onClipboardAction("rename");
+ }
+ if (command_name == "remove_link")
+ {
+ onClipboardAction("delete");
+ }
+ if (command_name == "delete")
+ {
+ onClipboardAction("delete");
+ }
+ updateListCommands();
+ updateVerbs();
+}
+
+BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata)
+{
+ const std::string command_name = userdata.asString();
+ if (command_name == "delete" || command_name == "remove")
+ {
+ BOOL can_delete = FALSE;
+ LLFolderView *folder = getActivePanel()->getRootFolder();
+ if (folder)
+ {
+ std::set<LLUUID> selection_set;
+ folder->getSelectionList(selection_set);
+ can_delete = (selection_set.size() > 0);
+ for (std::set<LLUUID>::iterator iter = selection_set.begin();
+ iter != selection_set.end();
+ ++iter)
+ {
+ const LLUUID &item_id = (*iter);
+ LLFolderViewItem *item = folder->getItemByID(item_id);
+ can_delete &= item->getListener()->isItemRemovable();
+ }
+ return can_delete;
+ }
+ return FALSE;
+ }
+ if (command_name == "remove_link")
+ {
+ BOOL can_delete = FALSE;
+ LLFolderView *folder = getActivePanel()->getRootFolder();
+ if (folder)
+ {
+ std::set<LLUUID> selection_set;
+ folder->getSelectionList(selection_set);
+ can_delete = (selection_set.size() > 0);
+ for (std::set<LLUUID>::iterator iter = selection_set.begin();
+ iter != selection_set.end();
+ ++iter)
+ {
+ const LLUUID &item_id = (*iter);
+ LLViewerInventoryItem *item = gInventory.getItem(item_id);
+ if (!item || !item->getIsLinkType())
+ return FALSE;
+ }
+ return can_delete;
+ }
+ return FALSE;
+ }
+ if (command_name == "rename" ||
+ command_name == "delete_outfit")
+ {
+ return (getCorrectListenerForAction() != NULL) && hasItemsSelected();
+ }
+
+ if (command_name == "wear")
+ {
+ if (isCOFPanelActive())
+ {
+ return FALSE;
+ }
+ }
+ if (command_name == "make_outfit")
+ {
+ return TRUE;
+ }
+
+ if (command_name == "edit" ||
+ command_name == "add"
+ )
+ {
+ return (getCorrectListenerForAction() != NULL);
+ }
+ return TRUE;
+}
+
+bool LLPanelOutfitsInventory::hasItemsSelected()
+{
+ bool has_items_selected = false;
+ LLFolderView *folder = getActivePanel()->getRootFolder();
+ if (folder)
+ {
+ std::set<LLUUID> selection_set;
+ folder->getSelectionList(selection_set);
+ has_items_selected = (selection_set.size() > 0);
+ }
+ return has_items_selected;
+}
+
+bool LLPanelOutfitsInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept)
+{
+ *accept = ACCEPT_NO;
+
+ const bool is_enabled = isActionEnabled("delete");
+ if (is_enabled) *accept = ACCEPT_YES_MULTI;
+
+ if (is_enabled && drop)
+ {
+ onClipboardAction("delete");
+ }
+ return true;
+}
+
+// List Commands //
+////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////
+// Tab panels //
+
+void LLPanelOutfitsInventory::initTabPanels()
+{
+ LLInventoryPanel *cof_panel = getChild<LLInventoryPanel>(COF_TAB_NAME);
+ cof_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
+ mTabPanels.push_back(cof_panel);
+
+ LLInventoryPanel *myoutfits_panel = getChild<LLInventoryPanel>(OUTFITS_TAB_NAME);
+ myoutfits_panel->setFilterTypes(1LL << LLFolderType::FT_OUTFIT, LLInventoryFilter::FILTERTYPE_CATEGORY);
+ myoutfits_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
+ mTabPanels.push_back(myoutfits_panel);
+
+ for (tabpanels_vec_t::iterator iter = mTabPanels.begin();
+ iter != mTabPanels.end();
+ ++iter)
+ {
+ LLInventoryPanel *panel = (*iter);
+ panel->setSelectCallback(boost::bind(&LLPanelOutfitsInventory::onTabSelectionChange, this, panel, _1, _2));
+ }
+
+ mAppearanceTabs = getChild<LLTabContainer>("appearance_tabs");
+ mAppearanceTabs->setCommitCallback(boost::bind(&LLPanelOutfitsInventory::onTabChange, this));
+ mActivePanel = (LLInventoryPanel*)mAppearanceTabs->getCurrentPanel();
+}
+
+void LLPanelOutfitsInventory::onTabSelectionChange(LLInventoryPanel* tab_panel, const std::deque<LLFolderViewItem*> &items, BOOL user_action)
+{
+ if (user_action && items.size() > 0)
+ {
+ for (tabpanels_vec_t::iterator iter = mTabPanels.begin();
+ iter != mTabPanels.end();
+ ++iter)
+ {
+ LLInventoryPanel *panel = (*iter);
+ if (panel == tab_panel)
+ {
+ mActivePanel = panel;
+ }
+ else
+ {
+ panel->getRootFolder()->clearSelection();
+ }
+ }
+ }
+ onSelectionChange(items, user_action);
+}
+
+void LLPanelOutfitsInventory::onTabChange()
+{
+ mActivePanel = (LLInventoryPanel*)childGetVisibleTab("appearance_tabs");
+ if (!mActivePanel)
+ {
+ return;
+ }
+ mActivePanel->setFilterSubString(mFilterSubString);
+ updateVerbs();
+}
+
+BOOL LLPanelOutfitsInventory::isTabPanel(LLInventoryPanel *panel) const
+{
+ for(tabpanels_vec_t::const_iterator it = mTabPanels.begin();
+ it != mTabPanels.end();
+ ++it)
+ {
+ if (*it == panel)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL LLPanelOutfitsInventory::isCOFPanelActive() const
+{
+ return (getActivePanel()->getName() == COF_TAB_NAME);
+}
diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h
new file mode 100644
index 0000000000..ab25ef0a49
--- /dev/null
+++ b/indra/newview/llpaneloutfitsinventory.h
@@ -0,0 +1,134 @@
+/**
+ * @file llpaneloutfitsinventory.h
+ * @brief Outfits inventory panel
+ * class definition
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELOUTFITSINVENTORY_H
+#define LL_LLPANELOUTFITSINVENTORY_H
+
+#include "llpanel.h"
+#include "llinventoryobserver.h"
+
+class LLFolderView;
+class LLFolderViewItem;
+class LLFolderViewEventListener;
+class LLInventoryPanel;
+class LLSaveFolderState;
+class LLButton;
+class LLMenuGL;
+class LLSidepanelAppearance;
+class LLTabContainer;
+
+class LLPanelOutfitsInventory : public LLPanel
+{
+public:
+ LLPanelOutfitsInventory();
+ virtual ~LLPanelOutfitsInventory();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ void onSearchEdit(const std::string& string);
+ void onAdd();
+ void onRemove();
+ void onEdit();
+ void onSave();
+
+ void onSaveCommit(const std::string& item_name);
+
+ void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
+ void onSelectorButtonClicked();
+
+ // If a compatible listener type is selected, then return a pointer to that.
+ // Otherwise, return NULL.
+ LLFolderViewEventListener* getCorrectListenerForAction();
+ void setParent(LLSidepanelAppearance *parent);
+
+ LLFolderView* getRootFolder();
+
+protected:
+ void updateVerbs();
+ bool getIsCorrectType(const LLFolderViewEventListener *listenerp) const;
+
+private:
+ LLSidepanelAppearance* mParent;
+ LLSaveFolderState* mSavedFolderState;
+ LLTabContainer* mAppearanceTabs;
+ std::string mFilterSubString;
+
+public:
+ //////////////////////////////////////////////////////////////////////////////////
+ // tab panels
+ LLInventoryPanel* getActivePanel() { return mActivePanel; }
+ const LLInventoryPanel* getActivePanel() const { return mActivePanel; }
+ BOOL isTabPanel(LLInventoryPanel *panel) const;
+
+protected:
+ void initTabPanels();
+ void onTabSelectionChange(LLInventoryPanel* tab_panel, const std::deque<LLFolderViewItem*> &items, BOOL user_action);
+ void onTabChange();
+ BOOL isCOFPanelActive() const;
+
+private:
+ LLInventoryPanel* mActivePanel;
+ typedef std::vector<LLInventoryPanel *> tabpanels_vec_t;
+ tabpanels_vec_t mTabPanels;
+
+ // tab panels //
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // List Commands //
+protected:
+ void initListCommandsHandlers();
+ void updateListCommands();
+ void onGearButtonClick();
+ void onWearButtonClick();
+ void onAddButtonClick();
+ void showActionMenu(LLMenuGL* menu, std::string spawning_view_name);
+ void onTrashButtonClick();
+ void onClipboardAction(const LLSD& userdata);
+ BOOL isActionEnabled(const LLSD& command_name);
+ void onCustomAction(const LLSD& command_name);
+ bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);
+ bool hasItemsSelected();
+private:
+ LLPanel* mListCommands;
+ LLMenuGL* mMenuGearDefault;
+ LLMenuGL* mMenuAdd;
+ // List Commands //
+ ////////////////////////////////////////////////////////////////////////////////
+ ///
+public:
+ static bool sShowDebugEditor;
+};
+
+#endif //LL_LLPANELOUTFITSINVENTORY_H
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
new file mode 100644
index 0000000000..b01cdcc832
--- /dev/null
+++ b/indra/newview/llpanelpeople.cpp
@@ -0,0 +1,1474 @@
+/**
+ * @file llpanelpeople.cpp
+ * @brief Side tray "People" panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+// libs
+#include "llfloaterreg.h"
+#include "llmenugl.h"
+#include "llnotificationsutil.h"
+#include "llfiltereditor.h"
+#include "lltabcontainer.h"
+#include "lluictrlfactory.h"
+
+#include "llpanelpeople.h"
+
+// newview
+#include "llaccordionctrl.h"
+#include "llaccordionctrltab.h"
+#include "llagent.h"
+#include "llavataractions.h"
+#include "llavatarlist.h"
+#include "llavatarlistitem.h"
+#include "llcallingcard.h" // for LLAvatarTracker
+#include "llfloateravatarpicker.h"
+//#include "llfloaterminiinspector.h"
+#include "llfriendcard.h"
+#include "llgroupactions.h"
+#include "llgrouplist.h"
+#include "llinventoryobserver.h"
+#include "llpanelpeoplemenus.h"
+#include "llsidetray.h"
+#include "llsidetraypanelcontainer.h"
+#include "llrecentpeople.h"
+#include "llviewercontrol.h" // for gSavedSettings
+#include "llviewermenu.h" // for gMenuHolder
+#include "llvoiceclient.h"
+#include "llworld.h"
+#include "llspeakers.h"
+
+#define FRIEND_LIST_UPDATE_TIMEOUT 0.5
+#define NEARBY_LIST_UPDATE_INTERVAL 1
+
+static const std::string NEARBY_TAB_NAME = "nearby_panel";
+static const std::string FRIENDS_TAB_NAME = "friends_panel";
+static const std::string GROUP_TAB_NAME = "groups_panel";
+static const std::string RECENT_TAB_NAME = "recent_panel";
+
+static const std::string COLLAPSED_BY_USER = "collapsed_by_user";
+
+/** Comparator for comparing avatar items by last interaction date */
+class LLAvatarItemRecentComparator : public LLAvatarItemComparator
+{
+public:
+ LLAvatarItemRecentComparator() {};
+ virtual ~LLAvatarItemRecentComparator() {};
+
+protected:
+ virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const
+ {
+ LLRecentPeople& people = LLRecentPeople::instance();
+ const LLDate& date1 = people.getDate(avatar_item1->getAvatarId());
+ const LLDate& date2 = people.getDate(avatar_item2->getAvatarId());
+
+ //older comes first
+ return date1 > date2;
+ }
+};
+
+/** Compares avatar items by online status, then by name */
+class LLAvatarItemStatusComparator : public LLAvatarItemComparator
+{
+public:
+ LLAvatarItemStatusComparator() {};
+
+protected:
+ /**
+ * @return true if item1 < item2, false otherwise
+ */
+ virtual bool doCompare(const LLAvatarListItem* item1, const LLAvatarListItem* item2) const
+ {
+ LLAvatarTracker& at = LLAvatarTracker::instance();
+ bool online1 = at.isBuddyOnline(item1->getAvatarId());
+ bool online2 = at.isBuddyOnline(item2->getAvatarId());
+
+ if (online1 == online2)
+ {
+ std::string name1 = item1->getAvatarName();
+ std::string name2 = item2->getAvatarName();
+
+ LLStringUtil::toUpper(name1);
+ LLStringUtil::toUpper(name2);
+
+ return name1 < name2;
+ }
+
+ return online1 > online2;
+ }
+};
+
+/** Compares avatar items by distance between you and them */
+class LLAvatarItemDistanceComparator : public LLAvatarItemComparator
+{
+public:
+ typedef std::map < LLUUID, LLVector3d > id_to_pos_map_t;
+ LLAvatarItemDistanceComparator() {};
+
+ void updateAvatarsPositions(std::vector<LLVector3d>& positions, std::vector<LLUUID>& uuids)
+ {
+ std::vector<LLVector3d>::const_iterator
+ pos_it = positions.begin(),
+ pos_end = positions.end();
+
+ std::vector<LLUUID>::const_iterator
+ id_it = uuids.begin(),
+ id_end = uuids.end();
+
+ LLAvatarItemDistanceComparator::id_to_pos_map_t pos_map;
+
+ mAvatarsPositions.clear();
+
+ for (;pos_it != pos_end && id_it != id_end; ++pos_it, ++id_it )
+ {
+ mAvatarsPositions[*id_it] = *pos_it;
+ }
+ };
+
+protected:
+ virtual bool doCompare(const LLAvatarListItem* item1, const LLAvatarListItem* item2) const
+ {
+ const LLVector3d& me_pos = gAgent.getPositionGlobal();
+ const LLVector3d& item1_pos = mAvatarsPositions.find(item1->getAvatarId())->second;
+ const LLVector3d& item2_pos = mAvatarsPositions.find(item2->getAvatarId())->second;
+ F32 dist1 = dist_vec(item1_pos, me_pos);
+ F32 dist2 = dist_vec(item2_pos, me_pos);
+ return dist1 < dist2;
+ }
+private:
+ id_to_pos_map_t mAvatarsPositions;
+};
+
+/** Comparator for comparing nearby avatar items by last spoken time */
+class LLAvatarItemRecentSpeakerComparator : public LLAvatarItemNameComparator
+{
+public:
+ LLAvatarItemRecentSpeakerComparator() {};
+ virtual ~LLAvatarItemRecentSpeakerComparator() {};
+
+protected:
+ virtual bool doCompare(const LLAvatarListItem* item1, const LLAvatarListItem* item2) const
+ {
+ LLPointer<LLSpeaker> lhs = LLLocalSpeakerMgr::instance().findSpeaker(item1->getAvatarId());
+ LLPointer<LLSpeaker> rhs = LLLocalSpeakerMgr::instance().findSpeaker(item2->getAvatarId());
+ if ( lhs.notNull() && rhs.notNull() )
+ {
+ // Compare by last speaking time
+ if( lhs->mLastSpokeTime != rhs->mLastSpokeTime )
+ return ( lhs->mLastSpokeTime > rhs->mLastSpokeTime );
+ }
+ else if ( lhs.notNull() )
+ {
+ // True if only item1 speaker info available
+ return true;
+ }
+ else if ( rhs.notNull() )
+ {
+ // False if only item2 speaker info available
+ return false;
+ }
+ // By default compare by name.
+ return LLAvatarItemNameComparator::doCompare(item1, item2);
+ }
+};
+
+static const LLAvatarItemRecentComparator RECENT_COMPARATOR;
+static const LLAvatarItemStatusComparator STATUS_COMPARATOR;
+static LLAvatarItemDistanceComparator DISTANCE_COMPARATOR;
+static const LLAvatarItemRecentSpeakerComparator RECENT_SPEAKER_COMPARATOR;
+
+static LLRegisterPanelClassWrapper<LLPanelPeople> t_people("panel_people");
+
+//=============================================================================
+
+/**
+ * Updates given list either on regular basis or on external events (up to implementation).
+ */
+class LLPanelPeople::Updater
+{
+public:
+ typedef boost::function<void()> callback_t;
+ Updater(callback_t cb)
+ : mCallback(cb)
+ {
+ }
+
+ virtual ~Updater()
+ {
+ }
+
+ /**
+ * Activate/deactivate updater.
+ *
+ * This may start/stop regular updates.
+ */
+ virtual void setActive(bool) {}
+
+protected:
+ void updateList()
+ {
+ mCallback();
+ }
+
+ callback_t mCallback;
+};
+
+class LLAvatarListUpdater : public LLPanelPeople::Updater, public LLEventTimer
+{
+public:
+ LLAvatarListUpdater(callback_t cb, F32 period)
+ : LLEventTimer(period),
+ LLPanelPeople::Updater(cb)
+ {
+ mEventTimer.stop();
+ }
+
+ virtual BOOL tick() // from LLEventTimer
+ {
+ return FALSE;
+ }
+};
+
+/**
+ * Updates the friends list.
+ *
+ * Updates the list on external events which trigger the changed() method.
+ */
+class LLFriendListUpdater : public LLAvatarListUpdater, public LLFriendObserver
+{
+ LOG_CLASS(LLFriendListUpdater);
+ class LLInventoryFriendCardObserver;
+
+public:
+ friend class LLInventoryFriendCardObserver;
+ LLFriendListUpdater(callback_t cb)
+ : LLAvatarListUpdater(cb, FRIEND_LIST_UPDATE_TIMEOUT)
+ {
+ LLAvatarTracker::instance().addObserver(this);
+
+ // For notification when SIP online status changes.
+ LLVoiceClient::getInstance()->addObserver(this);
+ mInvObserver = new LLInventoryFriendCardObserver(this);
+ }
+
+ ~LLFriendListUpdater()
+ {
+ // will be deleted by ~LLInventoryModel
+ //delete mInvObserver;
+ LLVoiceClient::getInstance()->removeObserver(this);
+ LLAvatarTracker::instance().removeObserver(this);
+ }
+
+ /*virtual*/ void changed(U32 mask)
+ {
+ // events can arrive quickly in bulk - we need not process EVERY one of them -
+ // so we wait a short while to let others pile-in, and process them in aggregate.
+ mEventTimer.start();
+
+ // save-up all the mask-bits which have come-in
+ mMask |= mask;
+ }
+
+
+ /*virtual*/ BOOL tick()
+ {
+ if (mMask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE))
+ updateList();
+
+ // Stop updates.
+ mEventTimer.stop();
+ mMask = 0;
+
+ return FALSE;
+ }
+
+private:
+ U32 mMask;
+ LLInventoryFriendCardObserver* mInvObserver;
+
+ /**
+ * This class is intended for updating Friend List when Inventory Friend Card is added/removed.
+ *
+ * The main usage is when Inventory Friends/All content is added while synchronizing with
+ * friends list on startup is performed. In this case Friend Panel should be updated when
+ * missing Inventory Friend Card is created.
+ * *NOTE: updating is fired when Inventory item is added into CallingCards/Friends subfolder.
+ * Otherwise LLFriendObserver functionality is enough to keep Friends Panel synchronized.
+ */
+ class LLInventoryFriendCardObserver : public LLInventoryObserver
+ {
+ LOG_CLASS(LLFriendListUpdater::LLInventoryFriendCardObserver);
+
+ friend class LLFriendListUpdater;
+
+ private:
+ LLInventoryFriendCardObserver(LLFriendListUpdater* updater) : mUpdater(updater)
+ {
+ gInventory.addObserver(this);
+ }
+ ~LLInventoryFriendCardObserver()
+ {
+ gInventory.removeObserver(this);
+ }
+ /*virtual*/ void changed(U32 mask)
+ {
+ lldebugs << "Inventory changed: " << mask << llendl;
+
+ // *NOTE: deleting of InventoryItem is performed via moving to Trash.
+ // That means LLInventoryObserver::STRUCTURE is present in MASK instead of LLInventoryObserver::REMOVE
+ if ((CALLINGCARD_ADDED & mask) == CALLINGCARD_ADDED)
+ {
+ lldebugs << "Calling card added: count: " << gInventory.getChangedIDs().size()
+ << ", first Inventory ID: "<< (*gInventory.getChangedIDs().begin())
+ << llendl;
+
+ bool friendFound = false;
+ std::set<LLUUID> changedIDs = gInventory.getChangedIDs();
+ for (std::set<LLUUID>::const_iterator it = changedIDs.begin(); it != changedIDs.end(); ++it)
+ {
+ if (isDescendentOfInventoryFriends(*it))
+ {
+ friendFound = true;
+ break;
+ }
+ }
+
+ if (friendFound)
+ {
+ lldebugs << "friend found, panel should be updated" << llendl;
+ mUpdater->changed(LLFriendObserver::ADD);
+ }
+ }
+ }
+
+ bool isDescendentOfInventoryFriends(const LLUUID& invItemID)
+ {
+ LLViewerInventoryItem * item = gInventory.getItem(invItemID);
+ if (NULL == item)
+ return false;
+
+ return LLFriendCardsManager::instance().isItemInAnyFriendsList(item);
+ }
+ LLFriendListUpdater* mUpdater;
+
+ static const U32 CALLINGCARD_ADDED = LLInventoryObserver::ADD | LLInventoryObserver::CALLING_CARD;
+ };
+};
+
+/**
+ * Periodically updates the nearby people list while the Nearby tab is active.
+ *
+ * The period is defined by NEARBY_LIST_UPDATE_INTERVAL constant.
+ */
+class LLNearbyListUpdater : public LLAvatarListUpdater
+{
+ LOG_CLASS(LLNearbyListUpdater);
+
+public:
+ LLNearbyListUpdater(callback_t cb)
+ : LLAvatarListUpdater(cb, NEARBY_LIST_UPDATE_INTERVAL)
+ {
+ setActive(false);
+ }
+
+ /*virtual*/ void setActive(bool val)
+ {
+ if (val)
+ {
+ // update immediately and start regular updates
+ updateList();
+ mEventTimer.start();
+ }
+ else
+ {
+ // stop regular updates
+ mEventTimer.stop();
+ }
+ }
+
+ /*virtual*/ BOOL tick()
+ {
+ updateList();
+ return FALSE;
+ }
+private:
+};
+
+/**
+ * Updates the recent people list (those the agent has recently interacted with).
+ */
+class LLRecentListUpdater : public LLAvatarListUpdater, public boost::signals2::trackable
+{
+ LOG_CLASS(LLRecentListUpdater);
+
+public:
+ LLRecentListUpdater(callback_t cb)
+ : LLAvatarListUpdater(cb, 0)
+ {
+ LLRecentPeople::instance().setChangedCallback(boost::bind(&LLRecentListUpdater::updateList, this));
+ }
+};
+
+//=============================================================================
+
+LLPanelPeople::LLPanelPeople()
+ : LLPanel(),
+ mFilterSubString(LLStringUtil::null),
+ mFilterEditor(NULL),
+ mTabContainer(NULL),
+ mOnlineFriendList(NULL),
+ mAllFriendList(NULL),
+ mNearbyList(NULL),
+ mRecentList(NULL),
+ mGroupList(NULL)
+{
+ mFriendListUpdater = new LLFriendListUpdater(boost::bind(&LLPanelPeople::updateFriendList, this));
+ mNearbyListUpdater = new LLNearbyListUpdater(boost::bind(&LLPanelPeople::updateNearbyList, this));
+ mRecentListUpdater = new LLRecentListUpdater(boost::bind(&LLPanelPeople::updateRecentList, this));
+ mCommitCallbackRegistrar.add("People.addFriend", boost::bind(&LLPanelPeople::onAddFriendButtonClicked, this));
+}
+
+LLPanelPeople::~LLPanelPeople()
+{
+ delete mNearbyListUpdater;
+ delete mFriendListUpdater;
+ delete mRecentListUpdater;
+
+ if(LLVoiceClient::getInstance())
+ LLVoiceClient::getInstance()->removeObserver(this);
+
+ LLView::deleteViewByHandle(mGroupPlusMenuHandle);
+ LLView::deleteViewByHandle(mNearbyViewSortMenuHandle);
+ LLView::deleteViewByHandle(mFriendsViewSortMenuHandle);
+ LLView::deleteViewByHandle(mGroupsViewSortMenuHandle);
+ LLView::deleteViewByHandle(mRecentViewSortMenuHandle);
+
+}
+
+void LLPanelPeople::onFriendsAccordionExpandedCollapsed(LLUICtrl* ctrl, const LLSD& param, LLAvatarList* avatar_list)
+{
+ if(!avatar_list)
+ {
+ llerrs << "Bad parameter" << llendl;
+ return;
+ }
+
+ bool expanded = param.asBoolean();
+
+ setAccordionCollapsedByUser(ctrl, !expanded);
+ if(!expanded)
+ {
+ avatar_list->resetSelection();
+ }
+}
+
+BOOL LLPanelPeople::postBuild()
+{
+ setVisibleCallback(boost::bind(&LLPanelPeople::onVisibilityChange, this, _2));
+
+ mFilterEditor = getChild<LLFilterEditor>("filter_input");
+ mFilterEditor->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));
+
+ mTabContainer = getChild<LLTabContainer>("tabs");
+ mTabContainer->setCommitCallback(boost::bind(&LLPanelPeople::onTabSelected, this, _2));
+
+ mOnlineFriendList = getChild<LLPanel>(FRIENDS_TAB_NAME)->getChild<LLAvatarList>("avatars_online");
+ mAllFriendList = getChild<LLPanel>(FRIENDS_TAB_NAME)->getChild<LLAvatarList>("avatars_all");
+ mOnlineFriendList->setNoItemsCommentText(getString("no_friends_online"));
+ mOnlineFriendList->setShowIcons("FriendsListShowIcons");
+ mAllFriendList->setNoItemsCommentText(getString("no_friends"));
+ mAllFriendList->setShowIcons("FriendsListShowIcons");
+
+ mNearbyList = getChild<LLPanel>(NEARBY_TAB_NAME)->getChild<LLAvatarList>("avatar_list");
+ mNearbyList->setNoItemsCommentText(getString("no_one_near"));
+ mNearbyList->setShowIcons("NearbyListShowIcons");
+
+ mRecentList = getChild<LLPanel>(RECENT_TAB_NAME)->getChild<LLAvatarList>("avatar_list");
+ mRecentList->setNoItemsCommentText(getString("no_people"));
+ mRecentList->setShowIcons("RecentListShowIcons");
+
+ mGroupList = getChild<LLGroupList>("group_list");
+ mGroupList->setNoItemsCommentText(getString("no_groups"));
+
+ mNearbyList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
+ mRecentList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
+ mAllFriendList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
+ mOnlineFriendList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
+
+ setSortOrder(mRecentList, (ESortOrder)gSavedSettings.getU32("RecentPeopleSortOrder"), false);
+ setSortOrder(mAllFriendList, (ESortOrder)gSavedSettings.getU32("FriendsSortOrder"), false);
+ setSortOrder(mNearbyList, (ESortOrder)gSavedSettings.getU32("NearbyPeopleSortOrder"), false);
+
+ LLPanel* groups_panel = getChild<LLPanel>(GROUP_TAB_NAME);
+ groups_panel->childSetAction("activate_btn", boost::bind(&LLPanelPeople::onActivateButtonClicked, this));
+ groups_panel->childSetAction("plus_btn", boost::bind(&LLPanelPeople::onGroupPlusButtonClicked, this));
+
+ LLPanel* friends_panel = getChild<LLPanel>(FRIENDS_TAB_NAME);
+ friends_panel->childSetAction("add_btn", boost::bind(&LLPanelPeople::onAddFriendWizButtonClicked, this));
+ friends_panel->childSetAction("del_btn", boost::bind(&LLPanelPeople::onDeleteFriendButtonClicked, this));
+
+ mOnlineFriendList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1));
+ mAllFriendList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1));
+ mNearbyList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1));
+ mRecentList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1));
+
+ mOnlineFriendList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mOnlineFriendList));
+ mAllFriendList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mAllFriendList));
+ mNearbyList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mNearbyList));
+ mRecentList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mRecentList));
+
+ // Set openning IM as default on return action for avatar lists
+ mOnlineFriendList->setReturnCallback(boost::bind(&LLPanelPeople::onImButtonClicked, this));
+ mAllFriendList->setReturnCallback(boost::bind(&LLPanelPeople::onImButtonClicked, this));
+ mNearbyList->setReturnCallback(boost::bind(&LLPanelPeople::onImButtonClicked, this));
+ mRecentList->setReturnCallback(boost::bind(&LLPanelPeople::onImButtonClicked, this));
+
+ mGroupList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onChatButtonClicked, this));
+ mGroupList->setCommitCallback(boost::bind(&LLPanelPeople::updateButtons, this));
+ mGroupList->setReturnCallback(boost::bind(&LLPanelPeople::onChatButtonClicked, this));
+
+ LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>("tab_all");
+ accordion_tab->setDropDownStateChangedCallback(
+ boost::bind(&LLPanelPeople::onFriendsAccordionExpandedCollapsed, this, _1, _2, mAllFriendList));
+
+ accordion_tab = getChild<LLAccordionCtrlTab>("tab_online");
+ accordion_tab->setDropDownStateChangedCallback(
+ boost::bind(&LLPanelPeople::onFriendsAccordionExpandedCollapsed, this, _1, _2, mOnlineFriendList));
+
+ buttonSetAction("view_profile_btn", boost::bind(&LLPanelPeople::onViewProfileButtonClicked, this));
+ buttonSetAction("group_info_btn", boost::bind(&LLPanelPeople::onGroupInfoButtonClicked, this));
+ buttonSetAction("chat_btn", boost::bind(&LLPanelPeople::onChatButtonClicked, this));
+ buttonSetAction("im_btn", boost::bind(&LLPanelPeople::onImButtonClicked, this));
+ buttonSetAction("call_btn", boost::bind(&LLPanelPeople::onCallButtonClicked, this));
+ buttonSetAction("group_call_btn", boost::bind(&LLPanelPeople::onGroupCallButtonClicked, this));
+ buttonSetAction("teleport_btn", boost::bind(&LLPanelPeople::onTeleportButtonClicked, this));
+ buttonSetAction("share_btn", boost::bind(&LLPanelPeople::onShareButtonClicked, this));
+
+ getChild<LLPanel>(NEARBY_TAB_NAME)->childSetAction("nearby_view_sort_btn",boost::bind(&LLPanelPeople::onNearbyViewSortButtonClicked, this));
+ getChild<LLPanel>(RECENT_TAB_NAME)->childSetAction("recent_viewsort_btn",boost::bind(&LLPanelPeople::onRecentViewSortButtonClicked, this));
+ getChild<LLPanel>(FRIENDS_TAB_NAME)->childSetAction("friends_viewsort_btn",boost::bind(&LLPanelPeople::onFriendsViewSortButtonClicked, this));
+ getChild<LLPanel>(GROUP_TAB_NAME)->childSetAction("groups_viewsort_btn",boost::bind(&LLPanelPeople::onGroupsViewSortButtonClicked, this));
+
+ // Must go after setting commit callback and initializing all pointers to children.
+ mTabContainer->selectTabByName(NEARBY_TAB_NAME);
+
+ // Create menus.
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+
+ registrar.add("People.Group.Plus.Action", boost::bind(&LLPanelPeople::onGroupPlusMenuItemClicked, this, _2));
+ registrar.add("People.Group.Minus.Action", boost::bind(&LLPanelPeople::onGroupMinusButtonClicked, this));
+ registrar.add("People.Friends.ViewSort.Action", boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemClicked, this, _2));
+ registrar.add("People.Nearby.ViewSort.Action", boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemClicked, this, _2));
+ registrar.add("People.Groups.ViewSort.Action", boost::bind(&LLPanelPeople::onGroupsViewSortMenuItemClicked, this, _2));
+ registrar.add("People.Recent.ViewSort.Action", boost::bind(&LLPanelPeople::onRecentViewSortMenuItemClicked, this, _2));
+
+ enable_registrar.add("People.Group.Minus.Enable", boost::bind(&LLPanelPeople::isRealGroup, this));
+ enable_registrar.add("People.Friends.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemCheck, this, _2));
+ enable_registrar.add("People.Recent.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onRecentViewSortMenuItemCheck, this, _2));
+ enable_registrar.add("People.Nearby.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemCheck, this, _2));
+
+ LLMenuGL* plus_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_group_plus.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mGroupPlusMenuHandle = plus_menu->getHandle();
+
+ LLMenuGL* nearby_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_nearby_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if(nearby_view_sort)
+ mNearbyViewSortMenuHandle = nearby_view_sort->getHandle();
+
+ LLMenuGL* friend_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_friends_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if(friend_view_sort)
+ mFriendsViewSortMenuHandle = friend_view_sort->getHandle();
+
+ LLMenuGL* group_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_groups_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if(group_view_sort)
+ mGroupsViewSortMenuHandle = group_view_sort->getHandle();
+
+ LLMenuGL* recent_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_recent_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if(recent_view_sort)
+ mRecentViewSortMenuHandle = recent_view_sort->getHandle();
+
+ gVoiceClient->addObserver(this);
+
+ // call this method in case some list is empty and buttons can be in inconsistent state
+ updateButtons();
+
+ mOnlineFriendList->setRefreshCompleteCallback(boost::bind(&LLPanelPeople::onFriendListRefreshComplete, this, _1, _2));
+ mAllFriendList->setRefreshCompleteCallback(boost::bind(&LLPanelPeople::onFriendListRefreshComplete, this, _1, _2));
+
+ return TRUE;
+}
+
+// virtual
+void LLPanelPeople::onChange(EStatusType status, const std::string &channelURI, bool proximal)
+{
+ if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL)
+ {
+ return;
+ }
+
+ updateButtons();
+}
+
+void LLPanelPeople::updateFriendList()
+{
+ if (!mOnlineFriendList || !mAllFriendList)
+ return;
+
+ // get all buddies we know about
+ const LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
+ LLAvatarTracker::buddy_map_t all_buddies;
+ av_tracker.copyBuddyList(all_buddies);
+
+ // save them to the online and all friends vectors
+ LLAvatarList::uuid_vector_t& online_friendsp = mOnlineFriendList->getIDs();
+ LLAvatarList::uuid_vector_t& all_friendsp = mAllFriendList->getIDs();
+
+ all_friendsp.clear();
+ online_friendsp.clear();
+
+ LLFriendCardsManager::folderid_buddies_map_t listMap;
+
+ // *NOTE: For now collectFriendsLists returns data only for Friends/All folder. EXT-694.
+ LLFriendCardsManager::instance().collectFriendsLists(listMap);
+ if (listMap.size() > 0)
+ {
+ lldebugs << "Friends Cards were found, count: " << listMap.begin()->second.size() << llendl;
+ all_friendsp = listMap.begin()->second;
+ }
+ else
+ {
+ lldebugs << "Friends Cards were not found" << llendl;
+ }
+
+ LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin();
+ for (; buddy_it != all_buddies.end(); ++buddy_it)
+ {
+ LLUUID buddy_id = buddy_it->first;
+ if (av_tracker.isBuddyOnline(buddy_id))
+ online_friendsp.push_back(buddy_id);
+ }
+
+ mOnlineFriendList->setDirty();
+ mAllFriendList->setDirty();
+
+ showFriendsAccordionsIfNeeded();
+}
+
+void LLPanelPeople::updateNearbyList()
+{
+ if (!mNearbyList)
+ return;
+
+ std::vector<LLVector3d> positions;
+
+ LLWorld::getInstance()->getAvatars(&mNearbyList->getIDs(), &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange"));
+ mNearbyList->setDirty();
+
+ DISTANCE_COMPARATOR.updateAvatarsPositions(positions, mNearbyList->getIDs());
+ LLLocalSpeakerMgr::instance().update(TRUE);
+}
+
+void LLPanelPeople::updateRecentList()
+{
+ if (!mRecentList)
+ return;
+
+ LLRecentPeople::instance().get(mRecentList->getIDs());
+ mRecentList->setDirty();
+}
+
+void LLPanelPeople::buttonSetVisible(std::string btn_name, BOOL visible)
+{
+ // To make sure we're referencing the right widget (a child of the button bar).
+ LLButton* button = getChild<LLView>("button_bar")->getChild<LLButton>(btn_name);
+ button->setVisible(visible);
+}
+
+void LLPanelPeople::buttonSetEnabled(const std::string& btn_name, bool enabled)
+{
+ // To make sure we're referencing the right widget (a child of the button bar).
+ LLButton* button = getChild<LLView>("button_bar")->getChild<LLButton>(btn_name);
+ button->setEnabled(enabled);
+}
+
+void LLPanelPeople::buttonSetAction(const std::string& btn_name, const commit_signal_t::slot_type& cb)
+{
+ // To make sure we're referencing the right widget (a child of the button bar).
+ LLButton* button = getChild<LLView>("button_bar")->getChild<LLButton>(btn_name);
+ button->setClickedCallback(cb);
+}
+
+bool LLPanelPeople::isFriendOnline(const LLUUID& id)
+{
+ LLAvatarList::uuid_vector_t ids = mOnlineFriendList->getIDs();
+ return std::find(ids.begin(), ids.end(), id) != ids.end();
+}
+
+void LLPanelPeople::updateButtons()
+{
+ std::string cur_tab = getActiveTabName();
+ bool nearby_tab_active = (cur_tab == NEARBY_TAB_NAME);
+ bool friends_tab_active = (cur_tab == FRIENDS_TAB_NAME);
+ bool group_tab_active = (cur_tab == GROUP_TAB_NAME);
+ //bool recent_tab_active = (cur_tab == RECENT_TAB_NAME);
+ LLUUID selected_id;
+
+ std::vector<LLUUID> selected_uuids;
+ getCurrentItemIDs(selected_uuids);
+ bool item_selected = (selected_uuids.size() == 1);
+ bool multiple_selected = (selected_uuids.size() >= 1);
+
+ buttonSetVisible("group_info_btn", group_tab_active);
+ buttonSetVisible("chat_btn", group_tab_active);
+ buttonSetVisible("view_profile_btn", !group_tab_active);
+ buttonSetVisible("im_btn", !group_tab_active);
+ buttonSetVisible("call_btn", !group_tab_active);
+ buttonSetVisible("group_call_btn", group_tab_active);
+ buttonSetVisible("teleport_btn", friends_tab_active);
+ buttonSetVisible("share_btn", nearby_tab_active || friends_tab_active);
+
+ if (group_tab_active)
+ {
+ bool cur_group_active = true;
+
+ if (item_selected)
+ {
+ selected_id = mGroupList->getSelectedUUID();
+ cur_group_active = (gAgent.getGroupID() == selected_id);
+ }
+
+ LLPanel* groups_panel = mTabContainer->getCurrentPanel();
+ groups_panel->childSetEnabled("activate_btn", item_selected && !cur_group_active); // "none" or a non-active group selected
+ groups_panel->childSetEnabled("minus_btn", item_selected && selected_id.notNull());
+ }
+ else
+ {
+ bool is_friend = true;
+
+ // Check whether selected avatar is our friend.
+ if (item_selected)
+ {
+ selected_id = selected_uuids.front();
+ is_friend = LLAvatarTracker::instance().getBuddyInfo(selected_id) != NULL;
+ }
+
+ LLPanel* cur_panel = mTabContainer->getCurrentPanel();
+ if (cur_panel)
+ {
+ cur_panel->childSetEnabled("add_friend_btn", !is_friend);
+ if (friends_tab_active)
+ {
+ cur_panel->childSetEnabled("del_btn", multiple_selected);
+ }
+ }
+ }
+
+ bool enable_calls = gVoiceClient->voiceWorking() && gVoiceClient->voiceEnabled();
+
+ buttonSetEnabled("teleport_btn", friends_tab_active && item_selected && isFriendOnline(selected_uuids.front()));
+ buttonSetEnabled("view_profile_btn", item_selected);
+ buttonSetEnabled("im_btn", multiple_selected); // allow starting the friends conference for multiple selection
+ buttonSetEnabled("call_btn", multiple_selected && enable_calls);
+ buttonSetEnabled("share_btn", item_selected); // not implemented yet
+
+ bool none_group_selected = item_selected && selected_id.isNull();
+ buttonSetEnabled("group_info_btn", !none_group_selected);
+ buttonSetEnabled("group_call_btn", !none_group_selected && enable_calls);
+ buttonSetEnabled("chat_btn", !none_group_selected);
+}
+
+std::string LLPanelPeople::getActiveTabName() const
+{
+ return mTabContainer->getCurrentPanel()->getName();
+}
+
+LLUUID LLPanelPeople::getCurrentItemID() const
+{
+ std::string cur_tab = getActiveTabName();
+
+ if (cur_tab == FRIENDS_TAB_NAME) // this tab has two lists
+ {
+ LLUUID cur_online_friend;
+
+ if ((cur_online_friend = mOnlineFriendList->getSelectedUUID()).notNull())
+ return cur_online_friend;
+
+ return mAllFriendList->getSelectedUUID();
+ }
+
+ if (cur_tab == NEARBY_TAB_NAME)
+ return mNearbyList->getSelectedUUID();
+
+ if (cur_tab == RECENT_TAB_NAME)
+ return mRecentList->getSelectedUUID();
+
+ if (cur_tab == GROUP_TAB_NAME)
+ return mGroupList->getSelectedUUID();
+
+ llassert(0 && "unknown tab selected");
+ return LLUUID::null;
+}
+
+void LLPanelPeople::getCurrentItemIDs(std::vector<LLUUID>& selected_uuids) const
+{
+ std::string cur_tab = getActiveTabName();
+
+ if (cur_tab == FRIENDS_TAB_NAME)
+ {
+ // friends tab has two lists
+ mOnlineFriendList->getSelectedUUIDs(selected_uuids);
+ mAllFriendList->getSelectedUUIDs(selected_uuids);
+ }
+ else if (cur_tab == NEARBY_TAB_NAME)
+ mNearbyList->getSelectedUUIDs(selected_uuids);
+ else if (cur_tab == RECENT_TAB_NAME)
+ mRecentList->getSelectedUUIDs(selected_uuids);
+ else if (cur_tab == GROUP_TAB_NAME)
+ mGroupList->getSelectedUUIDs(selected_uuids);
+ else
+ llassert(0 && "unknown tab selected");
+
+}
+
+void LLPanelPeople::showGroupMenu(LLMenuGL* menu)
+{
+ // Shows the menu at the top of the button bar.
+
+ // Calculate its coordinates.
+ // (assumes that groups panel is the current tab)
+ LLPanel* bottom_panel = mTabContainer->getCurrentPanel()->getChild<LLPanel>("bottom_panel");
+ LLPanel* parent_panel = mTabContainer->getCurrentPanel();
+ menu->arrangeAndClear();
+ S32 menu_height = menu->getRect().getHeight();
+ S32 menu_x = -2; // *HACK: compensates HPAD in showPopup()
+ S32 menu_y = bottom_panel->getRect().mTop + menu_height;
+
+ // Actually show the menu.
+ menu->buildDrawLabels();
+ menu->updateParent(LLMenuGL::sMenuContainer);
+ LLMenuGL::showPopup(parent_panel, menu, menu_x, menu_y);
+}
+
+void LLPanelPeople::setSortOrder(LLAvatarList* list, ESortOrder order, bool save)
+{
+ switch (order)
+ {
+ case E_SORT_BY_NAME:
+ list->sortByName();
+ break;
+ case E_SORT_BY_STATUS:
+ list->setComparator(&STATUS_COMPARATOR);
+ list->sort();
+ break;
+ case E_SORT_BY_MOST_RECENT:
+ list->setComparator(&RECENT_COMPARATOR);
+ list->sort();
+ break;
+ case E_SORT_BY_RECENT_SPEAKERS:
+ list->setComparator(&RECENT_SPEAKER_COMPARATOR);
+ list->sort();
+ break;
+ case E_SORT_BY_DISTANCE:
+ list->setComparator(&DISTANCE_COMPARATOR);
+ list->sort();
+ break;
+ default:
+ llwarns << "Unrecognized people sort order for " << list->getName() << llendl;
+ return;
+ }
+
+ if (save)
+ {
+ std::string setting;
+
+ if (list == mAllFriendList || list == mOnlineFriendList)
+ setting = "FriendsSortOrder";
+ else if (list == mRecentList)
+ setting = "RecentPeopleSortOrder";
+ else if (list == mNearbyList)
+ setting = "NearbyPeopleSortOrder";
+
+ if (!setting.empty())
+ gSavedSettings.setU32(setting, order);
+ }
+}
+
+void LLPanelPeople::onVisibilityChange(const LLSD& new_visibility)
+{
+ if (new_visibility.asBoolean() == FALSE)
+ {
+ // Don't update anything while we're invisible.
+ mNearbyListUpdater->setActive(FALSE);
+ }
+ else
+ {
+ reSelectedCurrentTab();
+ }
+}
+
+// Make the tab-container re-select current tab
+// for onTabSelected() callback to get called.
+// (currently this is needed to reactivate nearby list updates
+// when we get visible)
+void LLPanelPeople::reSelectedCurrentTab()
+{
+ mTabContainer->selectTab(mTabContainer->getCurrentPanelIndex());
+}
+
+bool LLPanelPeople::isRealGroup()
+{
+ return getCurrentItemID() != LLUUID::null;
+}
+
+void LLPanelPeople::onFilterEdit(const std::string& search_string)
+{
+ std::string search_upper = search_string;
+ // Searches are case-insensitive
+ LLStringUtil::toUpper(search_upper);
+ LLStringUtil::trimHead(search_upper);
+
+ if (mFilterSubString == search_upper)
+ return;
+
+ mFilterSubString = search_upper;
+
+ //store accordion tabs state before any manipulation with accordion tabs
+ if(!mFilterSubString.empty())
+ {
+ notifyChildren(LLSD().with("action","store_state"));
+ }
+
+
+ // Apply new filter.
+ mNearbyList->setNameFilter(mFilterSubString);
+ mOnlineFriendList->setNameFilter(mFilterSubString);
+ mAllFriendList->setNameFilter(mFilterSubString);
+ mRecentList->setNameFilter(mFilterSubString);
+ mGroupList->setNameFilter(mFilterSubString);
+
+ setAccordionCollapsedByUser("tab_online", false);
+ setAccordionCollapsedByUser("tab_all", false);
+
+ showFriendsAccordionsIfNeeded();
+
+ //restore accordion tabs state _after_ all manipulations...
+ if(mFilterSubString.empty())
+ {
+ notifyChildren(LLSD().with("action","restore_state"));
+ }
+}
+
+void LLPanelPeople::onTabSelected(const LLSD& param)
+{
+ std::string tab_name = getChild<LLPanel>(param.asString())->getName();
+ mNearbyListUpdater->setActive(tab_name == NEARBY_TAB_NAME);
+ updateButtons();
+
+ showFriendsAccordionsIfNeeded();
+
+ if (GROUP_TAB_NAME == tab_name)
+ mFilterEditor->setLabel(getString("groups_filter_label"));
+ else
+ mFilterEditor->setLabel(getString("people_filter_label"));
+}
+
+void LLPanelPeople::onAvatarListDoubleClicked(LLUICtrl* ctrl)
+{
+ LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(ctrl);
+ if(!item)
+ {
+ return;
+ }
+
+ LLUUID clicked_id = item->getAvatarId();
+
+#if 0 // SJB: Useful for testing, but not currently functional or to spec
+ LLAvatarActions::showProfile(clicked_id);
+#else // spec says open IM window
+ LLAvatarActions::startIM(clicked_id);
+#endif
+}
+
+void LLPanelPeople::onAvatarListCommitted(LLAvatarList* list)
+{
+ // Make sure only one of the friends lists (online/all) has selection.
+ if (getActiveTabName() == FRIENDS_TAB_NAME)
+ {
+ if (list == mOnlineFriendList)
+ mAllFriendList->resetSelection(true);
+ else if (list == mAllFriendList)
+ mOnlineFriendList->resetSelection(true);
+ else
+ llassert(0 && "commit on unknown friends list");
+ }
+
+ updateButtons();
+}
+
+void LLPanelPeople::onViewProfileButtonClicked()
+{
+ LLUUID id = getCurrentItemID();
+ LLAvatarActions::showProfile(id);
+}
+
+void LLPanelPeople::onAddFriendButtonClicked()
+{
+ LLUUID id = getCurrentItemID();
+ if (id.notNull())
+ {
+ LLAvatarActions::requestFriendshipDialog(id);
+ }
+}
+
+bool LLPanelPeople::isItemsFreeOfFriends(const std::vector<LLUUID>& uuids)
+{
+ const LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
+ for ( std::vector<LLUUID>::const_iterator
+ id = uuids.begin(),
+ id_end = uuids.end();
+ id != id_end; ++id )
+ {
+ if (av_tracker.isBuddy (*id))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+void LLPanelPeople::onAddFriendWizButtonClicked()
+{
+ // Show add friend wizard.
+ LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelPeople::onAvatarPicked, _1, _2), FALSE, TRUE);
+ // Need to disable 'ok' button when friend occurs in selection
+ if (picker) picker->setOkBtnEnableCb(boost::bind(&LLPanelPeople::isItemsFreeOfFriends, this, _1));
+ LLFloater* root_floater = gFloaterView->getParentFloater(this);
+ if (root_floater)
+ {
+ root_floater->addDependentFloater(picker);
+ }
+}
+
+void LLPanelPeople::onDeleteFriendButtonClicked()
+{
+ std::vector<LLUUID> selected_uuids;
+ getCurrentItemIDs(selected_uuids);
+
+ if (selected_uuids.size() == 1)
+ {
+ LLAvatarActions::removeFriendDialog( selected_uuids.front() );
+ }
+ else if (selected_uuids.size() > 1)
+ {
+ LLAvatarActions::removeFriendsDialog( selected_uuids );
+ }
+}
+
+void LLPanelPeople::onGroupInfoButtonClicked()
+{
+ LLGroupActions::show(getCurrentItemID());
+}
+
+void LLPanelPeople::onChatButtonClicked()
+{
+ LLUUID group_id = getCurrentItemID();
+ if (group_id.notNull())
+ LLGroupActions::startIM(group_id);
+}
+
+void LLPanelPeople::onImButtonClicked()
+{
+ std::vector<LLUUID> selected_uuids;
+ getCurrentItemIDs(selected_uuids);
+ if ( selected_uuids.size() == 1 )
+ {
+ // if selected only one person then start up IM
+ LLAvatarActions::startIM(selected_uuids.at(0));
+ }
+ else if ( selected_uuids.size() > 1 )
+ {
+ // for multiple selection start up friends conference
+ LLAvatarActions::startConference(selected_uuids);
+ }
+}
+
+void LLPanelPeople::onActivateButtonClicked()
+{
+ LLGroupActions::activate(mGroupList->getSelectedUUID());
+}
+
+// static
+void LLPanelPeople::onAvatarPicked(
+ const std::vector<std::string>& names,
+ const std::vector<LLUUID>& ids)
+{
+ if (!names.empty() && !ids.empty())
+ LLAvatarActions::requestFriendshipDialog(ids[0], names[0]);
+}
+
+void LLPanelPeople::onGroupPlusButtonClicked()
+{
+ if (!gAgent.canJoinGroups())
+ {
+ LLNotificationsUtil::add("JoinedTooManyGroups");
+ return;
+ }
+
+ LLMenuGL* plus_menu = (LLMenuGL*)mGroupPlusMenuHandle.get();
+ if (!plus_menu)
+ return;
+
+ showGroupMenu(plus_menu);
+}
+
+void LLPanelPeople::onGroupMinusButtonClicked()
+{
+ LLUUID group_id = getCurrentItemID();
+ if (group_id.notNull())
+ LLGroupActions::leave(group_id);
+}
+
+void LLPanelPeople::onGroupPlusMenuItemClicked(const LLSD& userdata)
+{
+ std::string chosen_item = userdata.asString();
+
+ if (chosen_item == "join_group")
+ LLGroupActions::search();
+ else if (chosen_item == "new_group")
+ LLGroupActions::createGroup();
+}
+
+void LLPanelPeople::onFriendsViewSortMenuItemClicked(const LLSD& userdata)
+{
+ std::string chosen_item = userdata.asString();
+
+ if (chosen_item == "sort_name")
+ {
+ setSortOrder(mAllFriendList, E_SORT_BY_NAME);
+ }
+ else if (chosen_item == "sort_status")
+ {
+ setSortOrder(mAllFriendList, E_SORT_BY_STATUS);
+ }
+ else if (chosen_item == "view_icons")
+ {
+ mAllFriendList->toggleIcons();
+ mOnlineFriendList->toggleIcons();
+ }
+}
+
+void LLPanelPeople::onGroupsViewSortMenuItemClicked(const LLSD& userdata)
+{
+ std::string chosen_item = userdata.asString();
+
+ if (chosen_item == "show_icons")
+ {
+ mGroupList->toggleIcons();
+ }
+}
+
+void LLPanelPeople::onNearbyViewSortMenuItemClicked(const LLSD& userdata)
+{
+ std::string chosen_item = userdata.asString();
+
+ if (chosen_item == "sort_by_recent_speakers")
+ {
+ setSortOrder(mNearbyList, E_SORT_BY_RECENT_SPEAKERS);
+ }
+ else if (chosen_item == "sort_name")
+ {
+ setSortOrder(mNearbyList, E_SORT_BY_NAME);
+ }
+ else if (chosen_item == "view_icons")
+ {
+ mNearbyList->toggleIcons();
+ }
+ else if (chosen_item == "sort_distance")
+ {
+ setSortOrder(mNearbyList, E_SORT_BY_DISTANCE);
+ }
+}
+
+bool LLPanelPeople::onNearbyViewSortMenuItemCheck(const LLSD& userdata)
+{
+ std::string item = userdata.asString();
+ U32 sort_order = gSavedSettings.getU32("NearbyPeopleSortOrder");
+
+ if (item == "sort_by_recent_speakers")
+ return sort_order == E_SORT_BY_RECENT_SPEAKERS;
+ if (item == "sort_name")
+ return sort_order == E_SORT_BY_NAME;
+ if (item == "sort_distance")
+ return sort_order == E_SORT_BY_DISTANCE;
+
+ return false;
+}
+
+void LLPanelPeople::onRecentViewSortMenuItemClicked(const LLSD& userdata)
+{
+ std::string chosen_item = userdata.asString();
+
+ if (chosen_item == "sort_recent")
+ {
+ setSortOrder(mRecentList, E_SORT_BY_MOST_RECENT);
+ }
+ else if (chosen_item == "sort_name")
+ {
+ setSortOrder(mRecentList, E_SORT_BY_NAME);
+ }
+ else if (chosen_item == "view_icons")
+ {
+ mRecentList->toggleIcons();
+ }
+}
+
+bool LLPanelPeople::onFriendsViewSortMenuItemCheck(const LLSD& userdata)
+{
+ std::string item = userdata.asString();
+ U32 sort_order = gSavedSettings.getU32("FriendsSortOrder");
+
+ if (item == "sort_name")
+ return sort_order == E_SORT_BY_NAME;
+ if (item == "sort_status")
+ return sort_order == E_SORT_BY_STATUS;
+
+ return false;
+}
+
+bool LLPanelPeople::onRecentViewSortMenuItemCheck(const LLSD& userdata)
+{
+ std::string item = userdata.asString();
+ U32 sort_order = gSavedSettings.getU32("RecentPeopleSortOrder");
+
+ if (item == "sort_recent")
+ return sort_order == E_SORT_BY_MOST_RECENT;
+ if (item == "sort_name")
+ return sort_order == E_SORT_BY_NAME;
+
+ return false;
+}
+
+void LLPanelPeople::onCallButtonClicked()
+{
+ std::vector<LLUUID> selected_uuids;
+ getCurrentItemIDs(selected_uuids);
+
+ if (selected_uuids.size() == 1)
+ {
+ // initiate a P2P voice chat with the selected user
+ LLAvatarActions::startCall(getCurrentItemID());
+ }
+ else if (selected_uuids.size() > 1)
+ {
+ // initiate an ad-hoc voice chat with multiple users
+ LLAvatarActions::startAdhocCall(selected_uuids);
+ }
+}
+
+void LLPanelPeople::onGroupCallButtonClicked()
+{
+ LLGroupActions::startCall(getCurrentItemID());
+}
+
+void LLPanelPeople::onTeleportButtonClicked()
+{
+ LLAvatarActions::offerTeleport(getCurrentItemID());
+}
+
+void LLPanelPeople::onShareButtonClicked()
+{
+ LLAvatarActions::share(getCurrentItemID());
+}
+
+void LLPanelPeople::onMoreButtonClicked()
+{
+ // *TODO: not implemented yet
+}
+
+void LLPanelPeople::onFriendsViewSortButtonClicked()
+{
+ LLMenuGL* menu = (LLMenuGL*)mFriendsViewSortMenuHandle.get();
+ if (!menu)
+ return;
+ showGroupMenu(menu);
+}
+
+void LLPanelPeople::onGroupsViewSortButtonClicked()
+{
+ LLMenuGL* menu = (LLMenuGL*)mGroupsViewSortMenuHandle.get();
+ if (!menu)
+ return;
+ showGroupMenu(menu);
+}
+
+void LLPanelPeople::onRecentViewSortButtonClicked()
+{
+ LLMenuGL* menu = (LLMenuGL*)mRecentViewSortMenuHandle.get();
+ if (!menu)
+ return;
+ showGroupMenu(menu);
+}
+
+void LLPanelPeople::onNearbyViewSortButtonClicked()
+{
+ LLMenuGL* menu = (LLMenuGL*)mNearbyViewSortMenuHandle.get();
+ if (!menu)
+ return;
+ showGroupMenu(menu);
+}
+
+void LLPanelPeople::onOpen(const LLSD& key)
+{
+ std::string tab_name = key["people_panel_tab_name"];
+ mFilterEditor -> clear();
+ onFilterEdit("");
+
+ if (!tab_name.empty())
+ mTabContainer->selectTabByName(tab_name);
+ else
+ reSelectedCurrentTab();
+}
+
+bool LLPanelPeople::notifyChildren(const LLSD& info)
+{
+ if (info.has("task-panel-action") && info["task-panel-action"].asString() == "handle-tri-state")
+ {
+ LLSideTrayPanelContainer* container = dynamic_cast<LLSideTrayPanelContainer*>(getParent());
+ if (!container)
+ {
+ llwarns << "Cannot find People panel container" << llendl;
+ return true;
+ }
+
+ if (container->getCurrentPanelIndex() > 0)
+ {
+ // if not on the default panel, switch to it
+ container->onOpen(LLSD().with(LLSideTrayPanelContainer::PARAM_SUB_PANEL_NAME, getName()));
+ }
+ else
+ LLSideTray::getInstance()->collapseSideBar();
+
+ return true; // this notification is only supposed to be handled by task panels
+ }
+
+ return LLPanel::notifyChildren(info);
+}
+
+void LLPanelPeople::showAccordion(const std::string name, bool show)
+{
+ if(name.empty())
+ {
+ llwarns << "No name provided" << llendl;
+ return;
+ }
+
+ LLAccordionCtrlTab* tab = getChild<LLAccordionCtrlTab>(name);
+ tab->setVisible(show);
+ if(show)
+ {
+ // don't expand accordion if it was collapsed by user
+ if(!isAccordionCollapsedByUser(tab))
+ {
+ // expand accordion
+ tab->changeOpenClose(false);
+ }
+ }
+}
+
+void LLPanelPeople::showFriendsAccordionsIfNeeded()
+{
+ if(FRIENDS_TAB_NAME == getActiveTabName())
+ {
+ // Expand and show accordions if needed, else - hide them
+ showAccordion("tab_online", mOnlineFriendList->filterHasMatches());
+ showAccordion("tab_all", mAllFriendList->filterHasMatches());
+
+ // Rearrange accordions
+ LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("friends_accordion");
+ accordion->arrange();
+ }
+}
+
+void LLPanelPeople::onFriendListRefreshComplete(LLUICtrl*ctrl, const LLSD& param)
+{
+ if(ctrl == mOnlineFriendList)
+ {
+ showAccordion("tab_online", param.asInteger());
+ }
+ else if(ctrl == mAllFriendList)
+ {
+ showAccordion("tab_all", param.asInteger());
+ }
+
+ LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("friends_accordion");
+ accordion->arrange();
+}
+
+void LLPanelPeople::setAccordionCollapsedByUser(LLUICtrl* acc_tab, bool collapsed)
+{
+ if(!acc_tab)
+ {
+ llwarns << "Invalid parameter" << llendl;
+ return;
+ }
+
+ LLSD param = acc_tab->getValue();
+ param[COLLAPSED_BY_USER] = collapsed;
+ acc_tab->setValue(param);
+}
+
+void LLPanelPeople::setAccordionCollapsedByUser(const std::string& name, bool collapsed)
+{
+ setAccordionCollapsedByUser(getChild<LLUICtrl>(name), collapsed);
+}
+
+bool LLPanelPeople::isAccordionCollapsedByUser(LLUICtrl* acc_tab)
+{
+ if(!acc_tab)
+ {
+ llwarns << "Invalid parameter" << llendl;
+ return false;
+ }
+
+ LLSD param = acc_tab->getValue();
+ if(!param.has(COLLAPSED_BY_USER))
+ {
+ return false;
+ }
+ return param[COLLAPSED_BY_USER].asBoolean();
+}
+
+bool LLPanelPeople::isAccordionCollapsedByUser(const std::string& name)
+{
+ return isAccordionCollapsedByUser(getChild<LLUICtrl>(name));
+}
+
+// EOF
diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h
new file mode 100644
index 0000000000..6d3d436156
--- /dev/null
+++ b/indra/newview/llpanelpeople.h
@@ -0,0 +1,173 @@
+/**
+ * @file llpanelpeople.h
+ * @brief Side tray "People" panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELPEOPLE_H
+#define LL_LLPANELPEOPLE_H
+
+#include <llpanel.h>
+
+#include "llcallingcard.h" // for avatar tracker
+#include "llvoiceclient.h"
+
+class LLFilterEditor;
+class LLTabContainer;
+class LLAvatarList;
+class LLGroupList;
+
+class LLPanelPeople
+ : public LLPanel
+ , public LLVoiceClientStatusObserver
+{
+ LOG_CLASS(LLPanelPeople);
+public:
+ LLPanelPeople();
+ virtual ~LLPanelPeople();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ bool notifyChildren(const LLSD& info);
+ // Implements LLVoiceClientStatusObserver::onChange() to enable call buttons
+ // when voice is available
+ /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
+
+ // internals
+ class Updater;
+
+private:
+
+ typedef enum e_sort_oder {
+ E_SORT_BY_NAME = 0,
+ E_SORT_BY_STATUS = 1,
+ E_SORT_BY_MOST_RECENT = 2,
+ E_SORT_BY_DISTANCE = 3,
+ E_SORT_BY_RECENT_SPEAKERS = 4,
+ } ESortOrder;
+
+ // methods indirectly called by the updaters
+ void updateFriendList();
+ void updateNearbyList();
+ void updateRecentList();
+
+ bool isFriendOnline(const LLUUID& id);
+ bool isItemsFreeOfFriends(const std::vector<LLUUID>& uuids);
+
+ void updateButtons();
+ std::string getActiveTabName() const;
+ LLUUID getCurrentItemID() const;
+ void getCurrentItemIDs(std::vector<LLUUID>& selected_uuids) const;
+ void buttonSetVisible(std::string btn_name, BOOL visible);
+ void buttonSetEnabled(const std::string& btn_name, bool enabled);
+ void buttonSetAction(const std::string& btn_name, const commit_signal_t::slot_type& cb);
+ void showGroupMenu(LLMenuGL* menu);
+ void setSortOrder(LLAvatarList* list, ESortOrder order, bool save = true);
+
+ void onVisibilityChange( const LLSD& new_visibility);
+
+ void reSelectedCurrentTab();
+
+ // UI callbacks
+ void onFilterEdit(const std::string& search_string);
+ void onTabSelected(const LLSD& param);
+ void onViewProfileButtonClicked();
+ void onAddFriendButtonClicked();
+ void onAddFriendWizButtonClicked();
+ void onDeleteFriendButtonClicked();
+ void onGroupInfoButtonClicked();
+ void onChatButtonClicked();
+ void onImButtonClicked();
+ void onCallButtonClicked();
+ void onGroupCallButtonClicked();
+ void onTeleportButtonClicked();
+ void onShareButtonClicked();
+ void onMoreButtonClicked();
+ void onActivateButtonClicked();
+ void onRecentViewSortButtonClicked();
+ void onNearbyViewSortButtonClicked();
+ void onFriendsViewSortButtonClicked();
+ void onGroupsViewSortButtonClicked();
+ void onAvatarListDoubleClicked(LLUICtrl* ctrl);
+ void onAvatarListCommitted(LLAvatarList* list);
+ void onGroupPlusButtonClicked();
+ void onGroupMinusButtonClicked();
+ void onGroupPlusMenuItemClicked(const LLSD& userdata);
+
+ void onFriendsViewSortMenuItemClicked(const LLSD& userdata);
+ void onNearbyViewSortMenuItemClicked(const LLSD& userdata);
+ void onGroupsViewSortMenuItemClicked(const LLSD& userdata);
+ void onRecentViewSortMenuItemClicked(const LLSD& userdata);
+
+ //returns false only if group is "none"
+ bool isRealGroup();
+ bool onFriendsViewSortMenuItemCheck(const LLSD& userdata);
+ bool onRecentViewSortMenuItemCheck(const LLSD& userdata);
+ bool onNearbyViewSortMenuItemCheck(const LLSD& userdata);
+
+ // misc callbacks
+ static void onAvatarPicked(
+ const std::vector<std::string>& names,
+ const std::vector<LLUUID>& ids);
+
+ void onFriendsAccordionExpandedCollapsed(LLUICtrl* ctrl, const LLSD& param, LLAvatarList* avatar_list);
+
+ void showAccordion(const std::string name, bool show);
+
+ void showFriendsAccordionsIfNeeded();
+
+ void onFriendListRefreshComplete(LLUICtrl*ctrl, const LLSD& param);
+
+ void setAccordionCollapsedByUser(LLUICtrl* acc_tab, bool collapsed);
+ void setAccordionCollapsedByUser(const std::string& name, bool collapsed);
+ bool isAccordionCollapsedByUser(LLUICtrl* acc_tab);
+ bool isAccordionCollapsedByUser(const std::string& name);
+
+ LLFilterEditor* mFilterEditor;
+ LLTabContainer* mTabContainer;
+ LLAvatarList* mOnlineFriendList;
+ LLAvatarList* mAllFriendList;
+ LLAvatarList* mNearbyList;
+ LLAvatarList* mRecentList;
+ LLGroupList* mGroupList;
+
+ LLHandle<LLView> mGroupPlusMenuHandle;
+ LLHandle<LLView> mNearbyViewSortMenuHandle;
+ LLHandle<LLView> mFriendsViewSortMenuHandle;
+ LLHandle<LLView> mGroupsViewSortMenuHandle;
+ LLHandle<LLView> mRecentViewSortMenuHandle;
+
+ Updater* mFriendListUpdater;
+ Updater* mNearbyListUpdater;
+ Updater* mRecentListUpdater;
+
+ std::string mFilterSubString;
+};
+
+#endif //LL_LLPANELPEOPLE_H
diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp
new file mode 100644
index 0000000000..d9651a6045
--- /dev/null
+++ b/indra/newview/llpanelpeoplemenus.cpp
@@ -0,0 +1,212 @@
+/**
+ * @file llpanelpeoplemenus.h
+ * @brief Menus used by the side tray "People" panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+// libs
+#include "llmenugl.h"
+#include "lluictrlfactory.h"
+
+#include "llpanelpeoplemenus.h"
+
+// newview
+#include "llagentdata.h" // for gAgentID
+#include "llavataractions.h"
+#include "llviewermenu.h" // for gMenuHolder
+
+namespace LLPanelPeopleMenus
+{
+
+NearbyMenu gNearbyMenu;
+
+//== ContextMenu ==============================================================
+
+ContextMenu::ContextMenu()
+: mMenu(NULL)
+{
+}
+
+void ContextMenu::show(LLView* spawning_view, const std::vector<LLUUID>& uuids, S32 x, S32 y)
+{
+ if (mMenu)
+ {
+ //preventing parent (menu holder) from deleting already "dead" context menus on exit
+ LLView* parent = mMenu->getParent();
+ if (parent)
+ {
+ parent->removeChild(mMenu);
+ }
+ delete mMenu;
+ mMenu = NULL;
+ mUUIDs.clear();
+ }
+
+ if ( uuids.empty() )
+ return;
+
+ mUUIDs.resize(uuids.size());
+ std::copy(uuids.begin(), uuids.end(), mUUIDs.begin());
+
+ mMenu = createMenu();
+ mMenu->show(x, y);
+ LLMenuGL::showPopup(spawning_view, mMenu, x, y);
+}
+
+void ContextMenu::hide()
+{
+ if(mMenu)
+ {
+ mMenu->hide();
+ }
+}
+
+//== NearbyMenu ===============================================================
+
+LLContextMenu* NearbyMenu::createMenu()
+{
+ // set up the callbacks for all of the avatar menu items
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+
+ if ( mUUIDs.size() == 1 )
+ {
+ // Set up for one person selected menu
+
+ const LLUUID& id = mUUIDs.front();
+ registrar.add("Avatar.Profile", boost::bind(&LLAvatarActions::showProfile, id));
+ registrar.add("Avatar.AddFriend", boost::bind(&LLAvatarActions::requestFriendshipDialog, id));
+ registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startIM, id));
+ registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startCall, id));
+ registrar.add("Avatar.OfferTeleport", boost::bind(&NearbyMenu::offerTeleport, this));
+ registrar.add("Avatar.ShowOnMap", boost::bind(&LLAvatarActions::startIM, id)); // *TODO: unimplemented
+ registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::share, id));
+ registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, id));
+ registrar.add("Avatar.BlockUnblock", boost::bind(&LLAvatarActions::toggleBlock, id));
+
+ enable_registrar.add("Avatar.EnableItem", boost::bind(&NearbyMenu::enableContextMenuItem, this, _2));
+ enable_registrar.add("Avatar.CheckItem", boost::bind(&NearbyMenu::checkContextMenuItem, this, _2));
+
+ // create the context menu from the XUI
+ return LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
+ "menu_people_nearby.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
+ }
+ else
+ {
+ // Set up for multi-selected People
+
+ // registrar.add("Avatar.AddFriend", boost::bind(&LLAvatarActions::requestFriendshipDialog, mUUIDs)); // *TODO: unimplemented
+ registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startConference, mUUIDs));
+ registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startAdhocCall, mUUIDs));
+ // registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::startIM, mUUIDs)); // *TODO: unimplemented
+ // registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, mUUIDs)); // *TODO: unimplemented
+ enable_registrar.add("Avatar.EnableItem", boost::bind(&NearbyMenu::enableContextMenuItem, this, _2));
+
+ // create the context menu from the XUI
+ return LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>
+ ("menu_people_nearby_multiselect.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
+
+ }
+}
+
+bool NearbyMenu::enableContextMenuItem(const LLSD& userdata)
+{
+ std::string item = userdata.asString();
+
+ // Note: can_block and can_delete is used only for one person selected menu
+ // so we don't need to go over all uuids.
+
+ if (item == std::string("can_block"))
+ {
+ const LLUUID& id = mUUIDs.front();
+ std::string firstname, lastname;
+ gCacheName->getName(id, firstname, lastname);
+ bool is_linden = !LLStringUtil::compareStrings(lastname, "Linden");
+ bool is_self = id == gAgentID;
+ return !is_self && !is_linden;
+ }
+ else if (item == std::string("can_add"))
+ {
+ // We can add friends if:
+ // - there are selected people
+ // - and there are no friends among selection yet.
+
+ bool result = (mUUIDs.size() > 0);
+
+ std::vector<LLUUID>::const_iterator
+ id = mUUIDs.begin(),
+ uuids_end = mUUIDs.end();
+
+ for (;id != uuids_end; ++id)
+ {
+ if ( LLAvatarActions::isFriend(*id) )
+ {
+ result = false;
+ break;
+ }
+ }
+
+ return result;
+ }
+ else if (item == std::string("can_delete"))
+ {
+ const LLUUID& id = mUUIDs.front();
+ return LLAvatarActions::isFriend(id);
+ }
+ else if (item == std::string("can_call"))
+ {
+ return LLAvatarActions::canCall();
+ }
+ return false;
+}
+
+bool NearbyMenu::checkContextMenuItem(const LLSD& userdata)
+{
+ std::string item = userdata.asString();
+ const LLUUID& id = mUUIDs.front();
+
+ if (item == std::string("is_blocked"))
+ {
+ return LLAvatarActions::isBlocked(id);
+ }
+
+ return false;
+}
+
+void NearbyMenu::offerTeleport()
+{
+ // boost::bind cannot recognize overloaded method LLAvatarActions::offerTeleport(),
+ // so we have to use a wrapper.
+ const LLUUID& id = mUUIDs.front();
+ LLAvatarActions::offerTeleport(id);
+}
+
+} // namespace LLPanelPeopleMenus
diff --git a/indra/newview/llpanelpeoplemenus.h b/indra/newview/llpanelpeoplemenus.h
new file mode 100644
index 0000000000..14ae2985f0
--- /dev/null
+++ b/indra/newview/llpanelpeoplemenus.h
@@ -0,0 +1,84 @@
+/**
+ * @file llpanelpeoplemenus.h
+ * @brief Menus used by the side tray "People" panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELPEOPLEMENUS_H
+#define LL_LLPANELPEOPLEMENUS_H
+
+#include "llavatarlistitem.h"
+
+namespace LLPanelPeopleMenus
+{
+
+/**
+ * Base context menu.
+ */
+class ContextMenu : public LLAvatarListItem::ContextMenu
+{
+public:
+ ContextMenu();
+ virtual ~ContextMenu() {}
+
+ /**
+ * Show the menu at specified coordinates.
+ *
+ * @param uuids - an array of avatar or group ids
+ */
+ /*virtual*/ void show(LLView* spawning_view, const std::vector<LLUUID>& uuids, S32 x, S32 y);
+
+ virtual void hide();
+
+protected:
+
+ virtual LLContextMenu* createMenu() = 0;
+
+ std::vector<LLUUID> mUUIDs;
+ LLContextMenu* mMenu;
+};
+
+/**
+ * Menu used in the nearby people list.
+ */
+class NearbyMenu : public ContextMenu
+{
+public:
+ /*virtual*/ LLContextMenu* createMenu();
+private:
+ bool enableContextMenuItem(const LLSD& userdata);
+ bool checkContextMenuItem(const LLSD& userdata);
+ void offerTeleport();
+};
+
+extern NearbyMenu gNearbyMenu;
+
+} // namespace LLPanelPeopleMenus
+
+#endif // LL_LLPANELPEOPLEMENUS_H
diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp
index 389f06f355..8b8b1bed37 100644
--- a/indra/newview/llpanelpermissions.cpp
+++ b/indra/newview/llpanelpermissions.cpp
@@ -36,13 +36,16 @@
#include "llpanelpermissions.h"
+// library includes
#include "lluuid.h"
#include "llpermissions.h"
#include "llcategory.h"
#include "llclickaction.h"
#include "llfocusmgr.h"
+#include "llnotificationsutil.h"
#include "llstring.h"
+// project includes
#include "llviewerwindow.h"
#include "llresmgr.h"
#include "lltextbox.h"
@@ -53,73 +56,120 @@
#include "llagent.h"
#include "llstatusbar.h" // for getBalance()
#include "lllineeditor.h"
-#include "llradiogroup.h"
#include "llcombobox.h"
-#include "llfloateravatarinfo.h"
#include "lluiconstants.h"
#include "lldbstrings.h"
-#include "llfloatergroupinfo.h"
#include "llfloatergroups.h"
+#include "llfloaterreg.h"
+#include "llavataractions.h"
#include "llnamebox.h"
#include "llviewercontrol.h"
#include "lluictrlfactory.h"
+#include "llspinctrl.h"
#include "roles_constants.h"
+#include "llgroupactions.h"
+
+
+U8 string_value_to_click_action(std::string p_value);
+std::string click_action_to_string_value( U8 action);
+
+U8 string_value_to_click_action(std::string p_value)
+{
+ if(p_value == "Touch")
+ {
+ return CLICK_ACTION_TOUCH;
+ }
+ if(p_value == "Sit")
+ {
+ return CLICK_ACTION_SIT;
+ }
+ if(p_value == "Buy")
+ {
+ return CLICK_ACTION_BUY;
+ }
+ if(p_value == "Pay")
+ {
+ return CLICK_ACTION_PAY;
+ }
+ if(p_value == "Open")
+ {
+ return CLICK_ACTION_OPEN;
+ }
+ if(p_value == "Zoom")
+ {
+ return CLICK_ACTION_ZOOM;
+ }
+ return CLICK_ACTION_TOUCH;
+}
+
+std::string click_action_to_string_value( U8 action)
+{
+ switch (action)
+ {
+ case CLICK_ACTION_TOUCH:
+ default:
+ return "Touch";
+ break;
+ case CLICK_ACTION_SIT:
+ return "Sit";
+ break;
+ case CLICK_ACTION_BUY:
+ return "Buy";
+ break;
+ case CLICK_ACTION_PAY:
+ return "Pay";
+ break;
+ case CLICK_ACTION_OPEN:
+ return "Open";
+ break;
+ case CLICK_ACTION_ZOOM:
+ return "Zoom";
+ break;
+ }
+}
///----------------------------------------------------------------------------
/// Class llpanelpermissions
///----------------------------------------------------------------------------
// Default constructor
-LLPanelPermissions::LLPanelPermissions(const std::string& title) :
- LLPanel(title)
+LLPanelPermissions::LLPanelPermissions() :
+ LLPanel()
{
setMouseOpaque(FALSE);
}
BOOL LLPanelPermissions::postBuild()
{
- this->childSetCommitCallback("Object Name",LLPanelPermissions::onCommitName,this);
- this->childSetPrevalidate("Object Name",LLLineEditor::prevalidatePrintableNotPipe);
- this->childSetCommitCallback("Object Description",LLPanelPermissions::onCommitDesc,this);
- this->childSetPrevalidate("Object Description",LLLineEditor::prevalidatePrintableNotPipe);
+ childSetCommitCallback("Object Name",LLPanelPermissions::onCommitName,this);
+ childSetPrevalidate("Object Name",LLLineEditor::prevalidateASCIIPrintableNoPipe);
+ childSetCommitCallback("Object Description",LLPanelPermissions::onCommitDesc,this);
+ childSetPrevalidate("Object Description",LLLineEditor::prevalidateASCIIPrintableNoPipe);
- this->childSetAction("button owner profile",LLPanelPermissions::onClickOwner,this);
- this->childSetAction("button creator profile",LLPanelPermissions::onClickCreator,this);
+ getChild<LLUICtrl>("button set group")->setCommitCallback(boost::bind(&LLPanelPermissions::onClickGroup,this));
- this->childSetAction("button set group",LLPanelPermissions::onClickGroup,this);
+ childSetCommitCallback("checkbox share with group",LLPanelPermissions::onCommitGroupShare,this);
- this->childSetCommitCallback("checkbox share with group",LLPanelPermissions::onCommitGroupShare,this);
+ childSetAction("button deed",LLPanelPermissions::onClickDeedToGroup,this);
- this->childSetAction("button deed",LLPanelPermissions::onClickDeedToGroup,this);
+ childSetCommitCallback("checkbox allow everyone move",LLPanelPermissions::onCommitEveryoneMove,this);
- this->childSetCommitCallback("checkbox allow everyone move",LLPanelPermissions::onCommitEveryoneMove,this);
-
- this->childSetCommitCallback("checkbox allow everyone copy",LLPanelPermissions::onCommitEveryoneCopy,this);
+ childSetCommitCallback("checkbox allow everyone copy",LLPanelPermissions::onCommitEveryoneCopy,this);
- this->childSetCommitCallback("checkbox for sale",LLPanelPermissions::onCommitSaleInfo,this);
+ childSetCommitCallback("checkbox for sale",LLPanelPermissions::onCommitSaleInfo,this);
- this->childSetCommitCallback("Edit Cost",LLPanelPermissions::onCommitSaleInfo,this);
- this->childSetPrevalidate("Edit Cost",LLLineEditor::prevalidateNonNegativeS32);
+ childSetCommitCallback("sale type",LLPanelPermissions::onCommitSaleType,this);
- this->childSetCommitCallback("sale type",LLPanelPermissions::onCommitSaleType,this);
+ childSetCommitCallback("Edit Cost", LLPanelPermissions::onCommitSaleInfo, this);
- this->childSetCommitCallback("checkbox next owner can modify",LLPanelPermissions::onCommitNextOwnerModify,this);
- this->childSetCommitCallback("checkbox next owner can copy",LLPanelPermissions::onCommitNextOwnerCopy,this);
- this->childSetCommitCallback("checkbox next owner can transfer",LLPanelPermissions::onCommitNextOwnerTransfer,this);
- this->childSetCommitCallback("clickaction",LLPanelPermissions::onCommitClickAction,this);
- this->childSetCommitCallback("search_check",LLPanelPermissions::onCommitIncludeInSearch,this);
+ childSetCommitCallback("checkbox next owner can modify",LLPanelPermissions::onCommitNextOwnerModify,this);
+ childSetCommitCallback("checkbox next owner can copy",LLPanelPermissions::onCommitNextOwnerCopy,this);
+ childSetCommitCallback("checkbox next owner can transfer",LLPanelPermissions::onCommitNextOwnerTransfer,this);
+ childSetCommitCallback("clickaction",LLPanelPermissions::onCommitClickAction,this);
+ childSetCommitCallback("search_check",LLPanelPermissions::onCommitIncludeInSearch,this);
- LLTextBox* group_rect_proxy = getChild<LLTextBox>("Group Name Proxy");
- if(group_rect_proxy )
- {
- mLabelGroupName = new LLNameBox("Group Name", group_rect_proxy->getRect());
- addChild(mLabelGroupName);
- }
- else
- {
- mLabelGroupName = NULL;
- }
+ mLabelGroupName = getChild<LLNameBox>("Group Name Proxy");
return TRUE;
}
@@ -131,13 +181,92 @@ LLPanelPermissions::~LLPanelPermissions()
}
+void LLPanelPermissions::disableAll()
+{
+ childSetEnabled("perm_modify", FALSE);
+ childSetText("perm_modify", LLStringUtil::null);
+
+ childSetEnabled("Creator:", FALSE);
+ childSetText("Creator Name", LLStringUtil::null);
+ childSetEnabled("Creator Name", FALSE);
+
+ childSetEnabled("Owner:", FALSE);
+ childSetText("Owner Name", LLStringUtil::null);
+ childSetEnabled("Owner Name", FALSE);
+
+ childSetEnabled("Group:", FALSE);
+ childSetText("Group Name", LLStringUtil::null);
+ childSetEnabled("Group Name", FALSE);
+ childSetEnabled("button set group", FALSE);
+
+ childSetText("Object Name", LLStringUtil::null);
+ childSetEnabled("Object Name", FALSE);
+ childSetEnabled("Name:", FALSE);
+ childSetText("Group Name", LLStringUtil::null);
+ childSetEnabled("Group Name", FALSE);
+ childSetEnabled("Description:", FALSE);
+ childSetText("Object Description", LLStringUtil::null);
+ childSetEnabled("Object Description", FALSE);
+
+ childSetEnabled("Permissions:", FALSE);
+
+ childSetValue("checkbox share with group", FALSE);
+ childSetEnabled("checkbox share with group", FALSE);
+ childSetEnabled("button deed", FALSE);
+
+ childSetValue("checkbox allow everyone move", FALSE);
+ childSetEnabled("checkbox allow everyone move", FALSE);
+ childSetValue("checkbox allow everyone copy", FALSE);
+ childSetEnabled("checkbox allow everyone copy", FALSE);
+
+ //Next owner can:
+ childSetEnabled("Next owner can:", FALSE);
+ childSetValue("checkbox next owner can modify", FALSE);
+ childSetEnabled("checkbox next owner can modify", FALSE);
+ childSetValue("checkbox next owner can copy", FALSE);
+ childSetEnabled("checkbox next owner can copy", FALSE);
+ childSetValue("checkbox next owner can transfer", FALSE);
+ childSetEnabled("checkbox next owner can transfer", FALSE);
+
+ //checkbox for sale
+ childSetValue("checkbox for sale", FALSE);
+ childSetEnabled("checkbox for sale", FALSE);
+
+ //checkbox include in search
+ childSetValue("search_check", FALSE);
+ childSetEnabled("search_check", FALSE);
+
+ LLComboBox* combo_sale_type = getChild<LLComboBox>("sale type");
+ combo_sale_type->setValue(LLSaleInfo::FS_COPY);
+ combo_sale_type->setEnabled(FALSE);
+
+ childSetEnabled("Cost", FALSE);
+ childSetText("Cost", getString("Cost Default"));
+ childSetText("Edit Cost", LLStringUtil::null);
+ childSetEnabled("Edit Cost", FALSE);
+
+ childSetEnabled("label click action", FALSE);
+ LLComboBox* combo_click_action = getChild<LLComboBox>("clickaction");
+ if (combo_click_action)
+ {
+ combo_click_action->setEnabled(FALSE);
+ combo_click_action->clear();
+ }
+ childSetVisible("B:", FALSE);
+ childSetVisible("O:", FALSE);
+ childSetVisible("G:", FALSE);
+ childSetVisible("E:", FALSE);
+ childSetVisible("N:", FALSE);
+ childSetVisible("F:", FALSE);
+}
+
void LLPanelPermissions::refresh()
{
LLButton* BtnDeedToGroup = getChild<LLButton>("button deed");
if(BtnDeedToGroup)
{
std::string deedText;
- if (gSavedSettings.getWarning("DeedObject"))
+ if (gWarningSettings.getBOOL("DeedObject"))
{
deedText = getString("text deed continued");
}
@@ -165,142 +294,58 @@ void LLPanelPermissions::refresh()
if(!nodep || !objectp)// || attachment_selected)
{
// ...nothing selected
- childSetEnabled("perm_modify",false);
- childSetText("perm_modify",LLStringUtil::null);
-
- childSetEnabled("Creator:",false);
- childSetText("Creator Name",LLStringUtil::null);
- childSetEnabled("Creator Name",false);
- childSetEnabled("button creator profile",false);
-
- childSetEnabled("Owner:",false);
- childSetText("Owner Name",LLStringUtil::null);
- childSetEnabled("Owner Name",false);
- childSetEnabled("button owner profile",false);
-
- childSetEnabled("Group:",false);
- childSetText("Group Name",LLStringUtil::null);
- childSetEnabled("Group Name",false);
- childSetEnabled("button set group",false);
-
- childSetText("Object Name",LLStringUtil::null);
- childSetEnabled("Object Name",false);
- childSetEnabled("Name:",false);
- childSetText("Group Name",LLStringUtil::null);
- childSetEnabled("Group Name",false);
- childSetEnabled("Description:",false);
- childSetText("Object Description",LLStringUtil::null);
- childSetEnabled("Object Description",false);
-
- childSetEnabled("Permissions:",false);
-
- childSetValue("checkbox share with group",FALSE);
- childSetEnabled("checkbox share with group",false);
- childSetEnabled("button deed",false);
-
- childSetValue("checkbox allow everyone move",FALSE);
- childSetEnabled("checkbox allow everyone move",false);
- childSetValue("checkbox allow everyone copy",FALSE);
- childSetEnabled("checkbox allow everyone copy",false);
-
- //Next owner can:
- childSetEnabled("Next owner can:",false);
- childSetValue("checkbox next owner can modify",FALSE);
- childSetEnabled("checkbox next owner can modify",false);
- childSetValue("checkbox next owner can copy",FALSE);
- childSetEnabled("checkbox next owner can copy",false);
- childSetValue("checkbox next owner can transfer",FALSE);
- childSetEnabled("checkbox next owner can transfer",false);
-
- //checkbox for sale
- childSetValue("checkbox for sale",FALSE);
- childSetEnabled("checkbox for sale",false);
-
- //checkbox include in search
- childSetValue("search_check", FALSE);
- childSetEnabled("search_check", false);
-
- LLRadioGroup* RadioSaleType = getChild<LLRadioGroup>("sale type");
- if(RadioSaleType)
- {
- RadioSaleType->setSelectedIndex(-1);
- RadioSaleType->setEnabled(FALSE);
- }
-
- childSetEnabled("Cost",false);
- childSetText("Cost",getString("Cost Default"));
- childSetText("Edit Cost",LLStringUtil::null);
- childSetEnabled("Edit Cost",false);
-
- childSetEnabled("label click action",false);
- LLComboBox* ComboClickAction = getChild<LLComboBox>("clickaction");
- if(ComboClickAction)
- {
- ComboClickAction->setEnabled(FALSE);
- ComboClickAction->clear();
- }
- childSetVisible("B:",false);
- childSetVisible("O:",false);
- childSetVisible("G:",false);
- childSetVisible("E:",false);
- childSetVisible("N:",false);
- childSetVisible("F:",false);
-
+ disableAll();
return;
}
// figure out a few variables
- BOOL is_one_object = (object_count == 1);
-
+ const BOOL is_one_object = (object_count == 1);
+
// BUG: fails if a root and non-root are both single-selected.
BOOL is_perm_modify = (LLSelectMgr::getInstance()->getSelection()->getFirstRootNode()
- && LLSelectMgr::getInstance()->selectGetRootsModify())
- || LLSelectMgr::getInstance()->selectGetModify();
- const LLView* keyboard_focus_view = gFocusMgr.getKeyboardFocus();
+ && LLSelectMgr::getInstance()->selectGetRootsModify())
+ || LLSelectMgr::getInstance()->selectGetModify();
+ const LLFocusableElement* keyboard_focus_view = gFocusMgr.getKeyboardFocus();
+
S32 string_index = 0;
std::string MODIFY_INFO_STRINGS[] =
- {
- getString("text modify info 1"),
- getString("text modify info 2"),
- getString("text modify info 3"),
- getString("text modify info 4")
- };
- if(!is_perm_modify)
+ {
+ getString("text modify info 1"),
+ getString("text modify info 2"),
+ getString("text modify info 3"),
+ getString("text modify info 4")
+ };
+ if (!is_perm_modify)
{
string_index += 2;
}
- if(!is_one_object)
+ if (!is_one_object)
{
++string_index;
}
- childSetEnabled("perm_modify",true);
- childSetText("perm_modify",MODIFY_INFO_STRINGS[string_index]);
+ childSetEnabled("perm_modify", TRUE);
+ childSetText("perm_modify", MODIFY_INFO_STRINGS[string_index]);
- childSetEnabled("Permissions:",true);
+ childSetEnabled("Permissions:", TRUE);
// Update creator text field
- childSetEnabled("Creator:",true);
+ childSetEnabled("Creator:", TRUE);
BOOL creators_identical;
std::string creator_name;
creators_identical = LLSelectMgr::getInstance()->selectGetCreator(mCreatorID,
- creator_name);
+ creator_name);
- childSetText("Creator Name",creator_name);
- childSetEnabled("Creator Name",TRUE);
- childSetEnabled("button creator profile", creators_identical && mCreatorID.notNull() );
+ childSetText("Creator Name", creator_name);
+ childSetEnabled("Creator Name", TRUE);
// Update owner text field
- childSetEnabled("Owner:",true);
+ childSetEnabled("Owner:", TRUE);
- BOOL owners_identical;
std::string owner_name;
- owners_identical = LLSelectMgr::getInstance()->selectGetOwner(mOwnerID, owner_name);
-
-// llinfos << "owners_identical " << (owners_identical ? "TRUE": "FALSE") << llendl;
-
+ const BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(mOwnerID, owner_name);
if (mOwnerID.isNull())
{
- if(LLSelectMgr::getInstance()->selectIsGroupOwned())
+ if (LLSelectMgr::getInstance()->selectIsGroupOwned())
{
// Group owned already displayed by selectGetOwner
}
@@ -315,62 +360,53 @@ void LLPanelPermissions::refresh()
if (!mLastOwnerID.isNull() && !last_owner_name.empty())
{
owner_name.append(", last ");
- owner_name.append( last_owner_name );
+ owner_name.append(last_owner_name);
}
}
}
-
- childSetText("Owner Name",owner_name);
- childSetEnabled("Owner Name",TRUE);
- childSetEnabled("button owner profile",owners_identical && (mOwnerID.notNull() || LLSelectMgr::getInstance()->selectIsGroupOwned()));
+ childSetText("Owner Name", owner_name);
+ childSetEnabled("Owner Name", TRUE);
// update group text field
- childSetEnabled("Group:",true);
- childSetText("Group Name",LLStringUtil::null);
+ childSetEnabled("Group:", TRUE);
+ childSetText("Group Name", LLStringUtil::null);
LLUUID group_id;
BOOL groups_identical = LLSelectMgr::getInstance()->selectGetGroup(group_id);
if (groups_identical)
{
- if(mLabelGroupName)
+ if (mLabelGroupName)
{
- mLabelGroupName->setNameID(group_id, TRUE);
+ mLabelGroupName->setNameID(group_id,TRUE);
mLabelGroupName->setEnabled(TRUE);
}
}
else
{
- if(mLabelGroupName)
+ if (mLabelGroupName)
{
mLabelGroupName->setNameID(LLUUID::null, TRUE);
- mLabelGroupName->refresh(LLUUID::null, LLStringUtil::null, LLStringUtil::null, TRUE);
+ mLabelGroupName->refresh(LLUUID::null,LLStringUtil::null, LLStringUtil::null, TRUE);
mLabelGroupName->setEnabled(FALSE);
}
}
- childSetEnabled("button set group",owners_identical && (mOwnerID == gAgent.getID()));
+ childSetEnabled("button set group", owners_identical && (mOwnerID == gAgent.getID()));
- // figure out the contents of the name, description, & category
- BOOL edit_name_desc = FALSE;
- if(is_one_object && objectp->permModify())
- {
- edit_name_desc = TRUE;
- }
-
- childSetEnabled("Name:",true);
+ childSetEnabled("Name:", TRUE);
LLLineEditor* LineEditorObjectName = getChild<LLLineEditor>("Object Name");
- childSetEnabled("Description:",true);
- LLLineEditor* LineEditorObjectDesc = getChild<LLLineEditor>("Object Description");
+ childSetEnabled("Description:", TRUE);
+ LLLineEditor* LineEditorObjectDesc = getChild<LLLineEditor>("Object Description");
- if(is_one_object)
+ if (is_one_object)
{
- if(keyboard_focus_view != LineEditorObjectName)
+ if (keyboard_focus_view != LineEditorObjectName)
{
childSetText("Object Name",nodep->mName);
}
- if(LineEditorObjectDesc)
+ if (LineEditorObjectDesc)
{
- if(keyboard_focus_view != LineEditorObjectDesc)
+ if (keyboard_focus_view != LineEditorObjectDesc)
{
LineEditorObjectDesc->setText(nodep->mDescription);
}
@@ -378,19 +414,25 @@ void LLPanelPermissions::refresh()
}
else
{
- childSetText("Object Name",LLStringUtil::null);
+ childSetText("Object Name", LLStringUtil::null);
LineEditorObjectDesc->setText(LLStringUtil::null);
}
- if(edit_name_desc)
+ // figure out the contents of the name, description, & category
+ BOOL edit_name_desc = FALSE;
+ if (is_one_object && objectp->permModify())
+ {
+ edit_name_desc = TRUE;
+ }
+ if (edit_name_desc)
{
- childSetEnabled("Object Name",true);
- childSetEnabled("Object Description",true);
+ childSetEnabled("Object Name", TRUE);
+ childSetEnabled("Object Description", TRUE);
}
else
{
- childSetEnabled("Object Name",false);
- childSetEnabled("Object Description",false);
+ childSetEnabled("Object Name", FALSE);
+ childSetEnabled("Object Description", FALSE);
}
S32 total_sale_price = 0;
@@ -399,10 +441,10 @@ void LLPanelPermissions::refresh()
BOOL is_sale_price_mixed = FALSE;
U32 num_for_sale = FALSE;
LLSelectMgr::getInstance()->selectGetAggregateSaleInfo(num_for_sale,
- is_for_sale_mixed,
- is_sale_price_mixed,
- total_sale_price,
- individual_sale_price);
+ is_for_sale_mixed,
+ is_sale_price_mixed,
+ total_sale_price,
+ individual_sale_price);
const BOOL self_owned = (gAgent.getID() == mOwnerID);
const BOOL group_owned = LLSelectMgr::getInstance()->selectIsGroupOwned() ;
@@ -410,342 +452,318 @@ void LLPanelPermissions::refresh()
const BOOL can_transfer = LLSelectMgr::getInstance()->selectGetRootsTransfer();
const BOOL can_copy = LLSelectMgr::getInstance()->selectGetRootsCopy();
- if(!owners_identical)
+ if (!owners_identical)
{
- childSetEnabled("Cost",false);
- childSetText("Edit Cost",LLStringUtil::null);
- childSetEnabled("Edit Cost",false);
+ childSetEnabled("Cost", FALSE);
+ childSetText("Edit Cost", LLStringUtil::null);
+ childSetEnabled("Edit Cost", FALSE);
}
// You own these objects.
- else if(self_owned || (group_owned && gAgent.hasPowerInGroup(group_id,GP_OBJECT_SET_SALE)))
+ else if (self_owned || (group_owned && gAgent.hasPowerInGroup(group_id,GP_OBJECT_SET_SALE)))
{
// If there are multiple items for sale then set text to PRICE PER UNIT.
if (num_for_sale > 1)
{
- childSetText("Cost",getString("Cost Per Unit"));
+ childSetText("Cost", getString("Cost Per Unit"));
}
else
{
- childSetText("Cost",getString("Cost Default"));
+ childSetText("Cost", getString("Cost Default"));
}
- LLLineEditor *editPrice = getChild<LLLineEditor>("Edit Cost");
- if(keyboard_focus_view != editPrice)
+ LLSpinCtrl *edit_price = getChild<LLSpinCtrl>("Edit Cost");
+ if (!edit_price->hasFocus())
{
// If the sale price is mixed then set the cost to MIXED, otherwise
// set to the actual cost.
- if (num_for_sale > 0 && is_for_sale_mixed)
+ if ((num_for_sale > 0) && is_for_sale_mixed)
{
- childSetText("Edit Cost",getString("Sale Mixed"));
+ edit_price->setTentative(TRUE);
}
- else if (num_for_sale > 0 && is_sale_price_mixed)
+ else if ((num_for_sale > 0) && is_sale_price_mixed)
{
- childSetText("Edit Cost",getString("Cost Mixed"));
+ edit_price->setTentative(TRUE);
}
else
{
- childSetText("Edit Cost",llformat("%d",individual_sale_price));
+ edit_price->setValue(individual_sale_price);
}
}
// The edit fields are only enabled if you can sell this object
// and the sale price is not mixed.
- bool enable_edit = (num_for_sale && can_transfer) ? !is_for_sale_mixed : false;
- childSetEnabled("Cost",enable_edit);
- childSetEnabled("Edit Cost",enable_edit);
+ BOOL enable_edit = (num_for_sale && can_transfer) ? !is_for_sale_mixed : FALSE;
+ childSetEnabled("Cost", enable_edit);
+ childSetEnabled("Edit Cost", enable_edit);
}
// Someone, not you, owns these objects.
- else if(!public_owned)
+ else if (!public_owned)
{
- childSetEnabled("Cost",false);
- childSetEnabled("Edit Cost",false);
+ childSetEnabled("Cost", FALSE);
+ childSetEnabled("Edit Cost", FALSE);
// Don't show a price if none of the items are for sale.
if (num_for_sale)
- childSetText("Edit Cost",llformat("%d",total_sale_price));
+ childSetText("Edit Cost", llformat("%d",total_sale_price));
else
- childSetText("Edit Cost",LLStringUtil::null);
+ childSetText("Edit Cost", LLStringUtil::null);
// If multiple items are for sale, set text to TOTAL PRICE.
if (num_for_sale > 1)
- childSetText("Cost",getString("Cost Total"));
+ childSetText("Cost", getString("Cost Total"));
else
- childSetText("Cost",getString("Cost Default"));
+ childSetText("Cost", getString("Cost Default"));
}
// This is a public object.
else
{
- childSetEnabled("Cost",false);
- childSetText("Cost",getString("Cost Default"));
+ childSetEnabled("Cost", FALSE);
+ childSetText("Cost", getString("Cost Default"));
- childSetText("Edit Cost",LLStringUtil::null);
- childSetEnabled("Edit Cost",false);
+ childSetText("Edit Cost", LLStringUtil::null);
+ childSetEnabled("Edit Cost", FALSE);
}
// Enable and disable the permissions checkboxes
// based on who owns the object.
// TODO: Creator permissions
- BOOL valid_base_perms = FALSE;
- BOOL valid_owner_perms = FALSE;
- BOOL valid_group_perms = FALSE;
- BOOL valid_everyone_perms = FALSE;
- BOOL valid_next_perms = FALSE;
-
- U32 base_mask_on;
- U32 base_mask_off;
- U32 owner_mask_on;
- U32 owner_mask_off;
- U32 group_mask_on;
- U32 group_mask_off;
- U32 everyone_mask_on;
- U32 everyone_mask_off;
- U32 next_owner_mask_on = 0;
- U32 next_owner_mask_off = 0;
-
- valid_base_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_BASE,
- &base_mask_on,
- &base_mask_off);
-
- valid_owner_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_OWNER,
- &owner_mask_on,
- &owner_mask_off);
-
- valid_group_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_GROUP,
- &group_mask_on,
- &group_mask_off);
+ U32 base_mask_on = 0;
+ U32 base_mask_off = 0;
+ U32 owner_mask_off = 0;
+ U32 owner_mask_on = 0;
+ U32 group_mask_on = 0;
+ U32 group_mask_off = 0;
+ U32 everyone_mask_on = 0;
+ U32 everyone_mask_off = 0;
+ U32 next_owner_mask_on = 0;
+ U32 next_owner_mask_off = 0;
+
+ BOOL valid_base_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_BASE,
+ &base_mask_on,
+ &base_mask_off);
+ //BOOL valid_owner_perms =//
+ LLSelectMgr::getInstance()->selectGetPerm(PERM_OWNER,
+ &owner_mask_on,
+ &owner_mask_off);
+ BOOL valid_group_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_GROUP,
+ &group_mask_on,
+ &group_mask_off);
- valid_everyone_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_EVERYONE,
- &everyone_mask_on,
- &everyone_mask_off);
+ BOOL valid_everyone_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_EVERYONE,
+ &everyone_mask_on,
+ &everyone_mask_off);
- valid_next_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_NEXT_OWNER,
- &next_owner_mask_on,
- &next_owner_mask_off);
+ BOOL valid_next_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_NEXT_OWNER,
+ &next_owner_mask_on,
+ &next_owner_mask_off);
- if( gSavedSettings.getBOOL("DebugPermissions") )
+ if (gSavedSettings.getBOOL("DebugPermissions") )
{
- std::string perm_string;
if (valid_base_perms)
{
- perm_string = "B: ";
- perm_string += mask_to_string(base_mask_on);
- childSetText("B:",perm_string);
- childSetVisible("B:",true);
+ childSetText("B:", "B: " + mask_to_string(base_mask_on));
+ childSetVisible("B:", TRUE);
- perm_string = "O: ";
- perm_string += mask_to_string(owner_mask_on);
- childSetText("O:",perm_string);
- childSetVisible("O:",true);
+ childSetText("O:", "O: " + mask_to_string(owner_mask_on));
+ childSetVisible("O:", TRUE);
- perm_string = "G: ";
- perm_string += mask_to_string(group_mask_on);
- childSetText("G:",perm_string);
- childSetVisible("G:",true);
+ childSetText("G:", "G: " + mask_to_string(group_mask_on));
+ childSetVisible("G:", TRUE);
- perm_string = "E: ";
- perm_string += mask_to_string(everyone_mask_on);
- childSetText("E:",perm_string);
- childSetVisible("E:",true);
+ childSetText("E:", "E: " + mask_to_string(everyone_mask_on));
+ childSetVisible("E:", TRUE);
- perm_string = "N: ";
- perm_string += mask_to_string(next_owner_mask_on);
- childSetText("N:",perm_string);
- childSetVisible("N:",true);
+ childSetText("N:", "N: " + mask_to_string(next_owner_mask_on));
+ childSetVisible("N:", TRUE);
}
- perm_string = "F: ";
+
U32 flag_mask = 0x0;
- if (objectp->permMove())
- flag_mask |= PERM_MOVE;
- if (objectp->permModify())
- flag_mask |= PERM_MODIFY;
- if (objectp->permCopy())
- flag_mask |= PERM_COPY;
- if (objectp->permTransfer())
- flag_mask |= PERM_TRANSFER;
- perm_string += mask_to_string(flag_mask);
- childSetText("F:",perm_string);
- childSetVisible("F:",true);
+ if (objectp->permMove()) flag_mask |= PERM_MOVE;
+ if (objectp->permModify()) flag_mask |= PERM_MODIFY;
+ if (objectp->permCopy()) flag_mask |= PERM_COPY;
+ if (objectp->permTransfer()) flag_mask |= PERM_TRANSFER;
+
+ childSetText("F:", "F:" + mask_to_string(flag_mask));
+ childSetVisible("F:", TRUE);
}
else
{
- childSetVisible("B:",false);
- childSetVisible("O:",false);
- childSetVisible("G:",false);
- childSetVisible("E:",false);
- childSetVisible("N:",false);
- childSetVisible("F:",false);
+ childSetVisible("B:", FALSE);
+ childSetVisible("O:", FALSE);
+ childSetVisible("G:", FALSE);
+ childSetVisible("E:", FALSE);
+ childSetVisible("N:", FALSE);
+ childSetVisible("F:", FALSE);
}
- bool has_change_perm_ability = false;
- bool has_change_sale_ability = false;
+ BOOL has_change_perm_ability = FALSE;
+ BOOL has_change_sale_ability = FALSE;
- if(valid_base_perms
- && (self_owned
- || (group_owned && gAgent.hasPowerInGroup(group_id, GP_OBJECT_MANIPULATE))))
+ if (valid_base_perms &&
+ (self_owned || (group_owned && gAgent.hasPowerInGroup(group_id, GP_OBJECT_MANIPULATE))))
{
- has_change_perm_ability = true;
+ has_change_perm_ability = TRUE;
}
- if(valid_base_perms
- && (self_owned
- || (group_owned && gAgent.hasPowerInGroup(group_id, GP_OBJECT_SET_SALE))))
+ if (valid_base_perms &&
+ (self_owned || (group_owned && gAgent.hasPowerInGroup(group_id, GP_OBJECT_SET_SALE))))
{
- has_change_sale_ability = true;
+ has_change_sale_ability = TRUE;
}
if (!has_change_perm_ability && !has_change_sale_ability && !root_selected)
{
// ...must select root to choose permissions
- childSetValue("perm_modify", getString("text modify warning"));
+ childSetValue("perm_modify", getString("text modify warning"));
}
if (has_change_perm_ability)
{
- childSetEnabled("checkbox share with group",true);
- childSetEnabled("checkbox allow everyone move",owner_mask_on & PERM_MOVE);
- childSetEnabled("checkbox allow everyone copy",owner_mask_on & PERM_COPY && owner_mask_on & PERM_TRANSFER);
+ childSetEnabled("checkbox share with group", TRUE);
+ childSetEnabled("checkbox allow everyone move", owner_mask_on & PERM_MOVE);
+ childSetEnabled("checkbox allow everyone copy", owner_mask_on & PERM_COPY && owner_mask_on & PERM_TRANSFER);
}
else
{
- childSetEnabled("checkbox share with group", FALSE);
- childSetEnabled("checkbox allow everyone move", FALSE);
- childSetEnabled("checkbox allow everyone copy", FALSE);
+ childSetEnabled("checkbox share with group", FALSE);
+ childSetEnabled("checkbox allow everyone move", FALSE);
+ childSetEnabled("checkbox allow everyone copy", FALSE);
}
if (has_change_sale_ability && (owner_mask_on & PERM_TRANSFER))
{
- childSetEnabled("checkbox for sale", can_transfer || (!can_transfer && num_for_sale));
+ childSetEnabled("checkbox for sale", can_transfer || (!can_transfer && num_for_sale));
// Set the checkbox to tentative if the prices of each object selected
// are not the same.
- childSetTentative("checkbox for sale", is_for_sale_mixed);
- childSetEnabled("sale type",num_for_sale && can_transfer && !is_sale_price_mixed);
+ childSetTentative("checkbox for sale", is_for_sale_mixed);
+ childSetEnabled("sale type", num_for_sale && can_transfer && !is_sale_price_mixed);
- childSetEnabled("Next owner can:", TRUE);
- childSetEnabled("checkbox next owner can modify",base_mask_on & PERM_MODIFY);
- childSetEnabled("checkbox next owner can copy",base_mask_on & PERM_COPY);
- childSetEnabled("checkbox next owner can transfer",next_owner_mask_on & PERM_COPY);
+ childSetEnabled("Next owner can:", TRUE);
+ childSetEnabled("checkbox next owner can modify", base_mask_on & PERM_MODIFY);
+ childSetEnabled("checkbox next owner can copy", base_mask_on & PERM_COPY);
+ childSetEnabled("checkbox next owner can transfer", next_owner_mask_on & PERM_COPY);
}
else
{
- childSetEnabled("checkbox for sale",FALSE);
- childSetEnabled("sale type",FALSE);
+ childSetEnabled("checkbox for sale", FALSE);
+ childSetEnabled("sale type", FALSE);
- childSetEnabled("Next owner can:",FALSE);
- childSetEnabled("checkbox next owner can modify",FALSE);
- childSetEnabled("checkbox next owner can copy",FALSE);
- childSetEnabled("checkbox next owner can transfer",FALSE);
+ childSetEnabled("Next owner can:", FALSE);
+ childSetEnabled("checkbox next owner can modify", FALSE);
+ childSetEnabled("checkbox next owner can copy", FALSE);
+ childSetEnabled("checkbox next owner can transfer", FALSE);
}
- if(valid_group_perms)
+ if (valid_group_perms)
{
- if((group_mask_on & PERM_COPY) && (group_mask_on & PERM_MODIFY) && (group_mask_on & PERM_MOVE))
+ if ((group_mask_on & PERM_COPY) && (group_mask_on & PERM_MODIFY) && (group_mask_on & PERM_MOVE))
{
- childSetValue("checkbox share with group",TRUE);
- childSetTentative("checkbox share with group",FALSE);
- childSetEnabled("button deed",gAgent.hasPowerInGroup(group_id, GP_OBJECT_DEED) && (owner_mask_on & PERM_TRANSFER) && !group_owned && can_transfer);
+ childSetValue("checkbox share with group", TRUE);
+ childSetTentative("checkbox share with group", FALSE);
+ childSetEnabled("button deed", gAgent.hasPowerInGroup(group_id, GP_OBJECT_DEED) && (owner_mask_on & PERM_TRANSFER) && !group_owned && can_transfer);
}
- else if((group_mask_off & PERM_COPY) && (group_mask_off & PERM_MODIFY) && (group_mask_off & PERM_MOVE))
+ else if ((group_mask_off & PERM_COPY) && (group_mask_off & PERM_MODIFY) && (group_mask_off & PERM_MOVE))
{
- childSetValue("checkbox share with group",FALSE);
- childSetTentative("checkbox share with group",false);
- childSetEnabled("button deed",false);
+ childSetValue("checkbox share with group", FALSE);
+ childSetTentative("checkbox share with group", FALSE);
+ childSetEnabled("button deed", FALSE);
}
else
{
- childSetValue("checkbox share with group",TRUE);
- childSetTentative("checkbox share with group",true);
- childSetEnabled("button deed",gAgent.hasPowerInGroup(group_id, GP_OBJECT_DEED) && (group_mask_on & PERM_MOVE) && (owner_mask_on & PERM_TRANSFER) && !group_owned && can_transfer);
+ childSetValue("checkbox share with group", TRUE);
+ childSetTentative("checkbox share with group", TRUE);
+ childSetEnabled("button deed", gAgent.hasPowerInGroup(group_id, GP_OBJECT_DEED) && (group_mask_on & PERM_MOVE) && (owner_mask_on & PERM_TRANSFER) && !group_owned && can_transfer);
}
}
- if(valid_everyone_perms)
+ if (valid_everyone_perms)
{
// Move
- if(everyone_mask_on & PERM_MOVE)
+ if (everyone_mask_on & PERM_MOVE)
{
- childSetValue("checkbox allow everyone move",TRUE);
- childSetTentative("checkbox allow everyone move",false);
+ childSetValue("checkbox allow everyone move", TRUE);
+ childSetTentative("checkbox allow everyone move", FALSE);
}
- else if(everyone_mask_off & PERM_MOVE)
+ else if (everyone_mask_off & PERM_MOVE)
{
- childSetValue("checkbox allow everyone move",FALSE);
- childSetTentative("checkbox allow everyone move",false);
+ childSetValue("checkbox allow everyone move", FALSE);
+ childSetTentative("checkbox allow everyone move", FALSE);
}
else
{
- childSetValue("checkbox allow everyone move",TRUE);
- childSetTentative("checkbox allow everyone move",true);
+ childSetValue("checkbox allow everyone move", TRUE);
+ childSetTentative("checkbox allow everyone move", TRUE);
}
// Copy == everyone can't copy
- if(everyone_mask_on & PERM_COPY)
+ if (everyone_mask_on & PERM_COPY)
{
- childSetValue("checkbox allow everyone copy",TRUE);
- childSetTentative("checkbox allow everyone copy",!can_copy || !can_transfer);
+ childSetValue("checkbox allow everyone copy", TRUE);
+ childSetTentative("checkbox allow everyone copy", !can_copy || !can_transfer);
}
- else if(everyone_mask_off & PERM_COPY)
+ else if (everyone_mask_off & PERM_COPY)
{
- childSetValue("checkbox allow everyone copy",FALSE);
- childSetTentative("checkbox allow everyone copy",false);
+ childSetValue("checkbox allow everyone copy", FALSE);
+ childSetTentative("checkbox allow everyone copy", FALSE);
}
else
{
- childSetValue("checkbox allow everyone copy",TRUE);
- childSetTentative("checkbox allow everyone copy",true);
+ childSetValue("checkbox allow everyone copy", TRUE);
+ childSetTentative("checkbox allow everyone copy", TRUE);
}
}
- if(valid_next_perms)
+ if (valid_next_perms)
{
// Modify == next owner canot modify
- if(next_owner_mask_on & PERM_MODIFY)
+ if (next_owner_mask_on & PERM_MODIFY)
{
- childSetValue("checkbox next owner can modify",TRUE);
- childSetTentative("checkbox next owner can modify",false);
+ childSetValue("checkbox next owner can modify", TRUE);
+ childSetTentative("checkbox next owner can modify", FALSE);
}
- else if(next_owner_mask_off & PERM_MODIFY)
+ else if (next_owner_mask_off & PERM_MODIFY)
{
- childSetValue("checkbox next owner can modify",FALSE);
- childSetTentative("checkbox next owner can modify",false);
+ childSetValue("checkbox next owner can modify", FALSE);
+ childSetTentative("checkbox next owner can modify", FALSE);
}
else
{
- childSetValue("checkbox next owner can modify",TRUE);
- childSetTentative("checkbox next owner can modify",true);
+ childSetValue("checkbox next owner can modify", TRUE);
+ childSetTentative("checkbox next owner can modify", TRUE);
}
// Copy == next owner cannot copy
- if(next_owner_mask_on & PERM_COPY)
+ if (next_owner_mask_on & PERM_COPY)
{
- childSetValue("checkbox next owner can copy",TRUE);
- childSetTentative("checkbox next owner can copy",!can_copy);
+ childSetValue("checkbox next owner can copy", TRUE);
+ childSetTentative("checkbox next owner can copy", !can_copy);
}
- else if(next_owner_mask_off & PERM_COPY)
+ else if (next_owner_mask_off & PERM_COPY)
{
- childSetValue("checkbox next owner can copy",FALSE);
- childSetTentative("checkbox next owner can copy",FALSE);
+ childSetValue("checkbox next owner can copy", FALSE);
+ childSetTentative("checkbox next owner can copy", FALSE);
}
else
{
- childSetValue("checkbox next owner can copy",TRUE);
- childSetTentative("checkbox next owner can copy",TRUE);
+ childSetValue("checkbox next owner can copy", TRUE);
+ childSetTentative("checkbox next owner can copy", TRUE);
}
// Transfer == next owner cannot transfer
- if(next_owner_mask_on & PERM_TRANSFER)
+ if (next_owner_mask_on & PERM_TRANSFER)
{
- childSetValue("checkbox next owner can transfer",TRUE);
- childSetTentative("checkbox next owner can transfer",!can_transfer);
+ childSetValue("checkbox next owner can transfer", TRUE);
+ childSetTentative("checkbox next owner can transfer", !can_transfer);
}
- else if(next_owner_mask_off & PERM_TRANSFER)
+ else if (next_owner_mask_off & PERM_TRANSFER)
{
- childSetValue("checkbox next owner can transfer",FALSE);
- childSetTentative("checkbox next owner can transfer",FALSE);
+ childSetValue("checkbox next owner can transfer", FALSE);
+ childSetTentative("checkbox next owner can transfer", FALSE);
}
else
{
- childSetValue("checkbox next owner can transfer",TRUE);
- childSetTentative("checkbox next owner can transfer",TRUE);
+ childSetValue("checkbox next owner can transfer", TRUE);
+ childSetTentative("checkbox next owner can transfer", TRUE);
}
}
@@ -754,53 +772,54 @@ void LLPanelPermissions::refresh()
BOOL valid_sale_info = LLSelectMgr::getInstance()->selectGetSaleInfo(sale_info);
LLSaleInfo::EForSale sale_type = sale_info.getSaleType();
- LLRadioGroup* RadioSaleType = getChild<LLRadioGroup>("sale type");
- if(RadioSaleType)
+ LLComboBox* combo_sale_type = getChild<LLComboBox>("sale type");
+ if (valid_sale_info)
{
- if (valid_sale_info)
- {
- RadioSaleType->setSelectedIndex((S32)sale_type - 1);
- RadioSaleType->setTentative(FALSE); // unfortunately this doesn't do anything at the moment.
- }
- else
- {
- // default option is sell copy, determined to be safest
- RadioSaleType->setSelectedIndex((S32)LLSaleInfo::FS_COPY - 1);
- RadioSaleType->setTentative(TRUE); // unfortunately this doesn't do anything at the moment.
- }
+ combo_sale_type->setValue( sale_type == LLSaleInfo::FS_NOT ? LLSaleInfo::FS_COPY : sale_type);
+ combo_sale_type->setTentative( FALSE); // unfortunately this doesn't do anything at the moment.
+ }
+ else
+ {
+ // default option is sell copy, determined to be safest
+ combo_sale_type->setValue( LLSaleInfo::FS_COPY);
+ combo_sale_type->setTentative( TRUE); // unfortunately this doesn't do anything at the moment.
}
- childSetValue("checkbox for sale", num_for_sale != 0);
+ childSetValue("checkbox for sale", (num_for_sale != 0));
// HACK: There are some old objects in world that are set for sale,
// but are no-transfer. We need to let users turn for-sale off, but only
// if for-sale is set.
bool cannot_actually_sell = !can_transfer || (!can_copy && sale_type == LLSaleInfo::FS_COPY);
- if (num_for_sale && has_change_sale_ability && cannot_actually_sell)
+ if (cannot_actually_sell)
{
- childSetEnabled("checkbox for sale", true);
+ if (num_for_sale && has_change_sale_ability)
+ {
+ childSetEnabled("checkbox for sale", true);
+ }
}
-
+
// Check search status of objects
- BOOL all_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME );
+ const BOOL all_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME );
bool include_in_search;
- bool all_include_in_search = LLSelectMgr::getInstance()->selectionGetIncludeInSearch(&include_in_search);
- childSetEnabled("search_check", has_change_sale_ability && all_volume);
- childSetValue("search_check", include_in_search);
- childSetTentative("search_check", ! all_include_in_search);
+ const BOOL all_include_in_search = LLSelectMgr::getInstance()->selectionGetIncludeInSearch(&include_in_search);
+ childSetEnabled("search_check", has_change_sale_ability && all_volume);
+ childSetValue("search_check", include_in_search);
+ childSetTentative("search_check", !all_include_in_search);
// Click action (touch, sit, buy)
U8 click_action = 0;
if (LLSelectMgr::getInstance()->selectionGetClickAction(&click_action))
{
- LLComboBox* ComboClickAction = getChild<LLComboBox>("clickaction");
- if(ComboClickAction)
+ LLComboBox* combo_click_action = getChild<LLComboBox>("clickaction");
+ if(combo_click_action)
{
- ComboClickAction->setCurrentByIndex((S32)click_action);
+ const std::string combo_value = click_action_to_string_value(click_action);
+ combo_click_action->setValue(LLSD(combo_value));
}
}
- childSetEnabled("label click action",is_perm_modify && all_volume);
- childSetEnabled("clickaction",is_perm_modify && all_volume);
+ childSetEnabled("label click action", is_perm_modify && all_volume);
+ childSetEnabled("clickaction", is_perm_modify && all_volume);
}
@@ -818,68 +837,42 @@ void LLPanelPermissions::onClickRelease(void*)
LLSelectMgr::getInstance()->sendOwner(LLUUID::null, LLUUID::null);
}
-// static
-void LLPanelPermissions::onClickCreator(void *data)
-{
- LLPanelPermissions *self = (LLPanelPermissions *)data;
-
- LLFloaterAvatarInfo::showFromObject(self->mCreatorID);
-}
-
-// static
-void LLPanelPermissions::onClickOwner(void *data)
-{
- LLPanelPermissions *self = (LLPanelPermissions *)data;
-
- if (LLSelectMgr::getInstance()->selectIsGroupOwned())
- {
- LLUUID group_id;
- LLSelectMgr::getInstance()->selectGetGroup(group_id);
- LLFloaterGroupInfo::showFromUUID(group_id);
- }
- else
- {
- LLFloaterAvatarInfo::showFromObject(self->mOwnerID);
- }
-}
-
-void LLPanelPermissions::onClickGroup(void* data)
+void LLPanelPermissions::onClickGroup()
{
- LLPanelPermissions* panelp = (LLPanelPermissions*)data;
LLUUID owner_id;
std::string name;
BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, name);
- LLFloater* parent_floater = gFloaterView->getParentFloater(panelp);
+ LLFloater* parent_floater = gFloaterView->getParentFloater(this);
if(owners_identical && (owner_id == gAgent.getID()))
{
- LLFloaterGroupPicker* fg;
- fg = LLFloaterGroupPicker::showInstance(LLSD(gAgent.getID()));
- fg->setSelectCallback( cbGroupID, data );
-
- if (parent_floater)
+ LLFloaterGroupPicker* fg = LLFloaterReg::showTypedInstance<LLFloaterGroupPicker>("group_picker", LLSD(gAgent.getID()));
+ if (fg)
{
- LLRect new_rect = gFloaterView->findNeighboringPosition(parent_floater, fg);
- fg->setOrigin(new_rect.mLeft, new_rect.mBottom);
- parent_floater->addDependentFloater(fg);
+ fg->setSelectGroupCallback( boost::bind(&LLPanelPermissions::cbGroupID, this, _1) );
+
+ if (parent_floater)
+ {
+ LLRect new_rect = gFloaterView->findNeighboringPosition(parent_floater, fg);
+ fg->setOrigin(new_rect.mLeft, new_rect.mBottom);
+ parent_floater->addDependentFloater(fg);
+ }
}
}
}
-// static
-void LLPanelPermissions::cbGroupID(LLUUID group_id, void* userdata)
+void LLPanelPermissions::cbGroupID(LLUUID group_id)
{
- LLPanelPermissions* self = (LLPanelPermissions*)userdata;
- if(self->mLabelGroupName)
+ if(mLabelGroupName)
{
- self->mLabelGroupName->setNameID(group_id, TRUE);
+ mLabelGroupName->setNameID(group_id, TRUE);
}
LLSelectMgr::getInstance()->sendGroup(group_id);
}
bool callback_deed_to_group(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
LLUUID group_id;
@@ -895,7 +888,7 @@ bool callback_deed_to_group(const LLSD& notification, const LLSD& response)
void LLPanelPermissions::onClickDeedToGroup(void* data)
{
- LLNotifications::instance().add( "DeedObjectToGroup", LLSD(), LLSD(), callback_deed_to_group);
+ LLNotificationsUtil::add( "DeedObjectToGroup", LLSD(), LLSD(), callback_deed_to_group);
}
///----------------------------------------------------------------------------
@@ -1006,61 +999,44 @@ void LLPanelPermissions::setAllSaleInfo()
// Set the sale type if the object(s) are for sale.
if(checkPurchase && checkPurchase->get())
{
- LLRadioGroup* RadioSaleType = getChild<LLRadioGroup>("sale type");
- if(RadioSaleType)
- {
- switch(RadioSaleType->getSelectedIndex())
- {
- case 0:
- sale_type = LLSaleInfo::FS_ORIGINAL;
- break;
- case 1:
- sale_type = LLSaleInfo::FS_COPY;
- break;
- case 2:
- sale_type = LLSaleInfo::FS_CONTENTS;
- break;
- default:
- sale_type = LLSaleInfo::FS_COPY;
- break;
- }
- }
+ sale_type = static_cast<LLSaleInfo::EForSale>(getChild<LLComboBox>("sale type")->getValue().asInteger());
}
S32 price = -1;
- LLLineEditor *editPrice = getChild<LLLineEditor>("Edit Cost");
- if (editPrice)
- {
- // Don't extract the price if it's labeled as MIXED or is empty.
- const std::string& editPriceString = editPrice->getText();
- if (editPriceString != getString("Cost Mixed") && editPriceString != getString("Sale Mixed") &&
- !editPriceString.empty())
- {
- price = atoi(editPriceString.c_str());
- }
- else
- {
- price = DEFAULT_PRICE;
- }
- }
+ LLSpinCtrl *edit_price = getChild<LLSpinCtrl>("Edit Cost");
+ price = (edit_price->getTentative()) ? DEFAULT_PRICE : edit_price->getValue().asInteger();
+
// If somehow an invalid price, turn the sale off.
if (price < 0)
sale_type = LLSaleInfo::FS_NOT;
- LLSaleInfo sale_info(sale_type, price);
- LLSelectMgr::getInstance()->selectionSetObjectSaleInfo(sale_info);
+ LLSaleInfo old_sale_info;
+ LLSelectMgr::getInstance()->selectGetSaleInfo(old_sale_info);
+
+ LLSaleInfo new_sale_info(sale_type, price);
+ LLSelectMgr::getInstance()->selectionSetObjectSaleInfo(new_sale_info);
- // If turned off for-sale, make sure click-action buy is turned
- // off as well
- if (sale_type == LLSaleInfo::FS_NOT)
+ U8 old_click_action = 0;
+ LLSelectMgr::getInstance()->selectionGetClickAction(&old_click_action);
+
+ if (old_sale_info.isForSale()
+ && !new_sale_info.isForSale()
+ && old_click_action == CLICK_ACTION_BUY)
{
- U8 click_action = 0;
- LLSelectMgr::getInstance()->selectionGetClickAction(&click_action);
- if (click_action == CLICK_ACTION_BUY)
- {
- LLSelectMgr::getInstance()->selectionSetClickAction(CLICK_ACTION_TOUCH);
- }
+ // If turned off for-sale, make sure click-action buy is turned
+ // off as well
+ LLSelectMgr::getInstance()->
+ selectionSetClickAction(CLICK_ACTION_TOUCH);
+ }
+ else if (new_sale_info.isForSale()
+ && !old_sale_info.isForSale()
+ && old_click_action == CLICK_ACTION_TOUCH)
+ {
+ // If just turning on for-sale, preemptively turn on one-click buy
+ // unless user have a different click action set
+ LLSelectMgr::getInstance()->
+ selectionSetClickAction(CLICK_ACTION_BUY);
}
}
@@ -1080,21 +1056,22 @@ void LLPanelPermissions::onCommitClickAction(LLUICtrl* ctrl, void*)
{
LLComboBox* box = (LLComboBox*)ctrl;
if (!box) return;
-
- U8 click_action = (U8)box->getCurrentIndex();
+ std::string value = box->getValue().asString();
+ U8 click_action = string_value_to_click_action(value);
+
if (click_action == CLICK_ACTION_BUY)
{
LLSaleInfo sale_info;
LLSelectMgr::getInstance()->selectGetSaleInfo(sale_info);
if (!sale_info.isForSale())
{
- LLNotifications::instance().add("CantSetBuyObject");
+ LLNotificationsUtil::add("CantSetBuyObject");
// Set click action back to its old value
U8 click_action = 0;
LLSelectMgr::getInstance()->selectionGetClickAction(&click_action);
- box->setCurrentByIndex((S32)click_action);
-
+ std::string item_value = click_action_to_string_value(click_action);
+ box->setValue(LLSD(item_value));
return;
}
}
@@ -1106,7 +1083,7 @@ void LLPanelPermissions::onCommitClickAction(LLUICtrl* ctrl, void*)
if (!can_pay)
{
// Warn, but do it anyway.
- LLNotifications::instance().add("ClickActionNotPayable");
+ LLNotificationsUtil::add("ClickActionNotPayable");
}
}
LLSelectMgr::getInstance()->selectionSetClickAction(click_action);
diff --git a/indra/newview/llpanelpermissions.h b/indra/newview/llpanelpermissions.h
index bb816acd07..38d3be532f 100644
--- a/indra/newview/llpanelpermissions.h
+++ b/indra/newview/llpanelpermissions.h
@@ -42,47 +42,32 @@
// Panel for permissions of an object.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLCheckBoxCtrl;
-class LLTextBox;
-class LLButton;
-class LLLineEditor;
-class LLRadioGroup;
-class LLComboBox;
class LLNameBox;
class LLPanelPermissions : public LLPanel
{
public:
- LLPanelPermissions(const std::string& title);
+ LLPanelPermissions();
virtual ~LLPanelPermissions();
- virtual BOOL postBuild();
+ /*virtual*/ BOOL postBuild();
- // MANIPULATORS
void refresh(); // refresh all labels as needed
-// void setPermCheckboxes(U32 mask_on, U32 mask_off,
-// LLCheckBoxCtrl* move, LLCheckboxCtrl* edit,
-// LLCheckBoxCtrl* copy);
+
protected:
// statics
static void onClickClaim(void*);
static void onClickRelease(void*);
- static void onClickCreator(void*);
- static void onClickOwner(void*);
- static void onClickGroup(void*);
- static void cbGroupID(LLUUID group_id, void* userdata);
+ void onClickGroup();
+ void cbGroupID(LLUUID group_id);
static void onClickDeedToGroup(void*);
static void onCommitPerm(LLUICtrl *ctrl, void *data, U8 field, U32 perm);
-// static void onCommitGroupMove(LLUICtrl *ctrl, void *data);
-// static void onCommitGroupCopy(LLUICtrl *ctrl, void *data);
-// static void onCommitGroupModify(LLUICtrl *ctrl, void *data);
static void onCommitGroupShare(LLUICtrl *ctrl, void *data);
static void onCommitEveryoneMove(LLUICtrl *ctrl, void *data);
static void onCommitEveryoneCopy(LLUICtrl *ctrl, void *data);
- //static void onCommitEveryoneModify(LLUICtrl *ctrl, void *data);
static void onCommitNextOwnerModify(LLUICtrl* ctrl, void* data);
static void onCommitNextOwnerCopy(LLUICtrl* ctrl, void* data);
@@ -99,12 +84,11 @@ protected:
static void onCommitIncludeInSearch(LLUICtrl* ctrl, void*);
protected:
+ void disableAll();
+
+private:
LLNameBox* mLabelGroupName; // group name
- //LLTextBox* mBuyerLabel;
- //LLCheckBoxCtrl* mCheckBuyerModify;
- //LLCheckBoxCtrl* mCheckBuyerCopy;
-
LLUUID mCreatorID;
LLUUID mOwnerID;
LLUUID mLastOwnerID;
diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp
index 43ecd273c2..5ac0587550 100644
--- a/indra/newview/llpanelpick.cpp
+++ b/indra/newview/llpanelpick.cpp
@@ -38,478 +38,588 @@
#include "llpanelpick.h"
-#include "lldir.h"
-#include "llparcel.h"
#include "message.h"
-#include "llagent.h"
+#include "llparcel.h"
+
#include "llbutton.h"
-#include "llcheckboxctrl.h"
-#include "llviewercontrol.h"
+#include "llfloaterreg.h"
+#include "lliconctrl.h"
#include "lllineeditor.h"
-#include "lltabcontainervertical.h"
-#include "lltextbox.h"
-#include "llviewertexteditor.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 "llviewergenericmessage.h"
-#include "lluictrlfactory.h"
#include "llviewerparcelmgr.h"
-#include "llworldmap.h"
-#include "llfloaterworldmap.h"
#include "llviewerregion.h"
-#include "llviewerwindow.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"
+
+#define SAVE_BTN_LABEL "[WHAT]"
+#define LABEL_PICK = "Pick"
+#define LABEL_CHANGES = "Changes"
+
+std::string SET_LOCATION_NOTICE("(will update after save)");
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
//static
-std::list<LLPanelPick*> LLPanelPick::sAllPanels;
-
-LLPanelPick::LLPanelPick(BOOL top_pick)
-: LLPanel(std::string("Top Picks Panel")),
- mTopPick(top_pick),
- mPickID(),
- mCreatorID(),
- mParcelID(),
- mDataRequested(FALSE),
- mDataReceived(FALSE),
- mPosGlobal(),
- mSnapshotCtrl(NULL),
- mNameEditor(NULL),
- mDescEditor(NULL),
- mLocationEditor(NULL),
- mTeleportBtn(NULL),
- mMapBtn(NULL),
- //mLandmarkBtn(NULL),
- mSortOrderText(NULL),
- mSortOrderEditor(NULL),
- mEnabledCheck(NULL),
- mSetBtn(NULL)
-{
- sAllPanels.push_back(this);
-
- std::string pick_def_file;
- if (top_pick)
- {
- LLUICtrlFactory::getInstance()->buildPanel(this, "panel_top_pick.xml");
- }
- else
- {
- LLUICtrlFactory::getInstance()->buildPanel(this, "panel_avatar_pick.xml");
- }
+LLPanelPickInfo* LLPanelPickInfo::create()
+{
+ LLPanelPickInfo* panel = new LLPanelPickInfo();
+ LLUICtrlFactory::getInstance()->buildPanel(panel, XML_PANEL_PICK_INFO);
+ return panel;
}
-
-LLPanelPick::~LLPanelPick()
+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)
{
- sAllPanels.remove(this);
}
+LLPanelPickInfo::~LLPanelPickInfo()
+{
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
+
+ if (mParcelId.notNull())
+ {
+ LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this);
+ }
+}
-void LLPanelPick::reset()
+void LLPanelPickInfo::onOpen(const LLSD& key)
{
- mPickID.setNull();
- mCreatorID.setNull();
- mParcelID.setNull();
+ LLUUID avatar_id = key["avatar_id"];
+ if(avatar_id.isNull())
+ {
+ return;
+ }
+
+ if(getAvatarId().notNull())
+ {
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(
+ getAvatarId(), this);
+ }
- // Don't request data, this isn't valid
- mDataRequested = TRUE;
- mDataReceived = FALSE;
+ setAvatarId(avatar_id);
- mPosGlobal.clearVec();
+ resetData();
+ resetControls();
- clearCtrls();
-}
+ 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 LLPanelPick::postBuild()
+BOOL LLPanelPickInfo::postBuild()
{
- mSnapshotCtrl = getChild<LLTextureCtrl>("snapshot_ctrl");
- mSnapshotCtrl->setCommitCallback(onCommitAny);
- mSnapshotCtrl->setCallbackUserData(this);
+ mSnapshotCtrl = getChild<LLTextureCtrl>(XML_SNAPSHOT);
+
+ childSetLabelArg(XML_BTN_SAVE, SAVE_BTN_LABEL, std::string("Pick"));
+
+ 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));
- mNameEditor = getChild<LLLineEditor>("given_name_editor");
- mNameEditor->setCommitOnFocusLost(TRUE);
- mNameEditor->setCommitCallback(onCommitAny);
- mNameEditor->setCallbackUserData(this);
+ mScrollingPanel = getChild<LLPanel>("scroll_content_panel");
+ mScrollContainer = getChild<LLScrollContainer>("profile_scroll");
- mDescEditor = getChild<LLTextEditor>("desc_editor");
- mDescEditor->setCommitOnFocusLost(TRUE);
- mDescEditor->setCommitCallback(onCommitAny);
- mDescEditor->setCallbackUserData(this);
- mDescEditor->setTabsToNextField(TRUE);
+ mScrollingPanelMinHeight = mScrollContainer->getScrolledViewRect().getHeight();
+ mScrollingPanelWidth = mScrollingPanel->getRect().getWidth();
- mLocationEditor = getChild<LLLineEditor>("location_editor");
+ return TRUE;
+}
+
+void LLPanelPickInfo::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ LLPanel::reshape(width, height, called_from_parent);
- mSetBtn = getChild<LLButton>( "set_location_btn");
- mSetBtn->setClickedCallback(onClickSet);
- mSetBtn->setCallbackUserData(this);
+ if (!mScrollContainer || !mScrollingPanel)
+ return;
- mTeleportBtn = getChild<LLButton>( "pick_teleport_btn");
- mTeleportBtn->setClickedCallback(onClickTeleport);
- mTeleportBtn->setCallbackUserData(this);
+ static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
- mMapBtn = getChild<LLButton>( "pick_map_btn");
- mMapBtn->setClickedCallback(onClickMap);
- mMapBtn->setCallbackUserData(this);
+ S32 scroll_height = mScrollContainer->getRect().getHeight();
+ if (mScrollingPanelMinHeight >= scroll_height)
+ {
+ mScrollingPanel->reshape(mScrollingPanelWidth, mScrollingPanelMinHeight);
+ }
+ else
+ {
+ mScrollingPanel->reshape(mScrollingPanelWidth + scrollbar_size, scroll_height);
+ }
+}
- mSortOrderText = getChild<LLTextBox>("sort_order_text");
+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;
+ }
- mSortOrderEditor = getChild<LLLineEditor>("sort_order_editor");
- mSortOrderEditor->setPrevalidate(LLLineEditor::prevalidateInt);
- mSortOrderEditor->setCommitOnFocusLost(TRUE);
- mSortOrderEditor->setCommitCallback(onCommitAny);
- mSortOrderEditor->setCallbackUserData(this);
+ mParcelId = pick_info->parcel_id;
+ setSnapshotId(pick_info->snapshot_id);
+ setPickName(pick_info->name);
+ setPickDesc(pick_info->desc);
+ setPosGlobal(pick_info->pos_global);
- mEnabledCheck = getChild<LLCheckBoxCtrl>( "enabled_check");
- mEnabledCheck->setCommitCallback(onCommitAny);
- mEnabledCheck->setCallbackUserData(this);
+ // Send remote parcel info request to get parcel name and sim (region) name.
+ sendParcelInfoRequest();
- return TRUE;
+ // *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;
+ }
+}
-// Fill in some reasonable defaults for a new pick.
-void LLPanelPick::initNewPick()
+void LLPanelPickInfo::setExitCallback(const commit_callback_t& cb)
{
- mPickID.generate();
+ getChild<LLButton>("back_btn")->setClickedCallback(cb);
+}
- mCreatorID = gAgent.getID();
+void LLPanelPickInfo::processParcelInfo(const LLParcelData& parcel_data)
+{
+ setPickLocation(createLocationText(LLStringUtil::null, parcel_data.name,
+ parcel_data.sim_name, getPosGlobal()));
- mPosGlobal = gAgent.getPositionGlobal();
+ // We have received parcel info for the requested ID so clear it now.
+ mRequestedId.setNull();
- // Try to fill in the current parcel
- LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
- if (parcel)
+ if (mParcelId.notNull())
{
- mNameEditor->setText(parcel->getName());
- mDescEditor->setText(parcel->getDesc());
- mSnapshotCtrl->setImageAssetID(parcel->getSnapshotID());
+ LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this);
}
+}
- // Commit to the database, since we've got "new" values.
- sendPickInfoUpdate();
+void LLPanelPickInfo::setEditPickCallback(const commit_callback_t& cb)
+{
+ getChild<LLButton>("edit_btn")->setClickedCallback(cb);
}
+// PROTECTED AREA
-void LLPanelPick::setPickID(const LLUUID& pick_id, const LLUUID& creator_id)
+void LLPanelPickInfo::resetControls()
{
- mPickID = pick_id;
- mCreatorID = creator_id;
+ if(getAvatarId() == gAgent.getID())
+ {
+ childSetEnabled("edit_btn", TRUE);
+ childSetVisible("edit_btn", TRUE);
+ }
+ else
+ {
+ childSetEnabled("edit_btn", FALSE);
+ childSetVisible("edit_btn", 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();
+}
-// Schedules the panel to request data
-// from the server next time it is drawn.
-void LLPanelPick::markForServerRequest()
+// static
+std::string LLPanelPickInfo::createLocationText(const std::string& owner_name, const std::string& original_name, const std::string& sim_name, const LLVector3d& pos_global)
{
- mDataRequested = FALSE;
- mDataReceived = FALSE;
+ 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 = llround((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS;
+ S32 region_y = llround((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS;
+ S32 region_z = llround((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);
+}
-std::string LLPanelPick::getPickName()
+void LLPanelPickInfo::setPickName(const std::string& name)
{
- return mNameEditor->getText();
+ childSetValue(XML_NAME, name);
}
-
-void LLPanelPick::sendPickInfoRequest()
+void LLPanelPickInfo::setPickDesc(const std::string& desc)
{
- // Must ask for a pick based on the creator id because
- // the pick database is distributed to the inventory cluster. JC
- std::vector<std::string> strings;
- strings.push_back( mCreatorID.asString() );
- strings.push_back( mPickID.asString() );
- send_generic_message("pickinforequest", strings);
+ childSetValue(XML_DESC, desc);
+}
- mDataRequested = TRUE;
+void LLPanelPickInfo::setPickLocation(const std::string& location)
+{
+ childSetValue(XML_LOCATION, location);
}
+void LLPanelPickInfo::onClickMap()
+{
+ LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal());
+ LLFloaterReg::showInstance("world_map", "center");
+}
-void LLPanelPick::sendPickInfoUpdate()
+void LLPanelPickInfo::onClickTeleport()
{
- // 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 (mPickID.isNull())
+ if (!getPosGlobal().isExactlyZero())
{
- mPickID.generate();
+ gAgent.teleportViaLocation(getPosGlobal());
+ LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal());
}
+}
- LLMessageSystem* msg = gMessageSystem;
-
- msg->newMessage("PickInfoUpdate");
- msg->nextBlock("AgentData");
- msg->addUUID("AgentID", gAgent.getID());
- msg->addUUID("SessionID", gAgent.getSessionID());
- msg->nextBlock("Data");
- msg->addUUID("PickID", mPickID);
- msg->addUUID("CreatorID", mCreatorID);
- msg->addBOOL("TopPick", mTopPick);
- // fills in on simulator if null
- msg->addUUID("ParcelID", mParcelID);
- msg->addString("Name", mNameEditor->getText());
- msg->addString("Desc", mDescEditor->getText());
- msg->addUUID("SnapshotID", mSnapshotCtrl->getImageAssetID());
- msg->addVector3d("PosGlobal", mPosGlobal);
-
- // Only top picks have a sort order
- S32 sort_order;
- if (mTopPick)
- {
- sort_order = atoi(mSortOrderEditor->getText().c_str());
- }
- else
- {
- sort_order = 0;
- }
- msg->addS32("SortOrder", sort_order);
- msg->addBOOL("Enabled", mEnabledCheck->get());
- gAgent.sendReliableMessage();
+void LLPanelPickInfo::onClickBack()
+{
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
}
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
//static
-void LLPanelPick::processPickInfoReply(LLMessageSystem *msg, void **)
-{
- // Extract the agent id and verify the message is for this
- // client.
- LLUUID agent_id;
- msg->getUUID("AgentData", "AgentID", agent_id );
- if (agent_id != gAgent.getID())
- {
- llwarns << "Agent ID mismatch in processPickInfoReply"
- << llendl;
- return;
- }
+LLPanelPickEdit* LLPanelPickEdit::create()
+{
+ LLPanelPickEdit* panel = new LLPanelPickEdit();
+ LLUICtrlFactory::getInstance()->buildPanel(panel, XML_PANEL_EDIT_PICK);
+ return panel;
+}
+
+LLPanelPickEdit::LLPanelPickEdit()
+ : LLPanelPickInfo()
+ , mLocationChanged(false)
+ , mNeedData(true)
+ , mNewPick(false)
+{
+}
- LLUUID pick_id;
- msg->getUUID("Data", "PickID", pick_id);
+LLPanelPickEdit::~LLPanelPickEdit()
+{
+}
- LLUUID creator_id;
- msg->getUUID("Data", "CreatorID", creator_id);
+void LLPanelPickEdit::onOpen(const LLSD& key)
+{
+ LLUUID pick_id = key["pick_id"];
+ mNeedData = true;
- BOOL top_pick;
- msg->getBOOL("Data", "TopPick", top_pick);
+ // creating new Pick
+ if(pick_id.isNull())
+ {
+ mNewPick = true;
- LLUUID parcel_id;
- msg->getUUID("Data", "ParcelID", parcel_id);
+ setAvatarId(gAgent.getID());
- std::string name;
- msg->getString("Data", "Name", name);
+ resetData();
+ resetControls();
- std::string desc;
- msg->getString("Data", "Desc", desc);
+ setPosGlobal(gAgent.getPositionGlobal());
- LLUUID snapshot_id;
- msg->getUUID("Data", "SnapshotID", snapshot_id);
+ LLUUID parcel_id = LLUUID::null, snapshot_id = LLUUID::null;
+ std::string pick_name, pick_desc, region_name;
- // "Location text" is actually the owner name, the original
- // name that owner gave the parcel, and the location.
- std::string location_text;
- msg->getString("Data", "User", location_text);
- location_text.append(", ");
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ if(parcel)
+ {
+ parcel_id = parcel->getID();
+ pick_name = parcel->getName();
+ pick_desc = parcel->getDesc();
+ snapshot_id = parcel->getSnapshotID();
+ }
- std::string original_name;
- msg->getString("Data", "OriginalName", original_name);
- if (!original_name.empty())
+ LLViewerRegion* region = gAgent.getRegion();
+ if(region)
+ {
+ region_name = region->getName();
+ }
+
+ setParcelID(parcel_id);
+ childSetValue("pick_name", pick_name.empty() ? region_name : pick_name);
+ childSetValue("pick_desc", pick_desc);
+ setSnapshotId(snapshot_id);
+ setPickLocation(createLocationText(SET_LOCATION_NOTICE, pick_name, region_name, getPosGlobal()));
+
+ enableSaveButton(true);
+ }
+ // editing existing pick
+ else
{
- location_text.append(original_name);
- location_text.append(", ");
+ mNewPick = false;
+ LLPanelPickInfo::onOpen(key);
+
+ enableSaveButton(false);
}
- std::string sim_name;
- msg->getString("Data", "SimName", sim_name);
- location_text.append(sim_name);
- location_text.append(" ");
+ resetDirty();
+}
+
+void LLPanelPickEdit::setPickData(const LLPickData* pick_data)
+{
+ if(!pick_data)
+ {
+ return;
+ }
- LLVector3d pos_global;
- msg->getVector3d("Data", "PosGlobal", pos_global);
+ mNeedData = false;
- S32 region_x = llround((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS;
- S32 region_y = llround((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS;
- S32 region_z = llround((F32)pos_global.mdV[VZ]);
-
- location_text.append(llformat("(%d, %d, %d)", region_x, region_y, region_z));
+ setParcelID(pick_data->parcel_id);
+ childSetValue("pick_name", pick_data->name);
+ childSetValue("pick_desc", 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));
+}
- S32 sort_order;
- msg->getS32("Data", "SortOrder", sort_order);
+BOOL LLPanelPickEdit::postBuild()
+{
+ LLPanelPickInfo::postBuild();
- BOOL enabled;
- msg->getBOOL("Data", "Enabled", enabled);
+ mSnapshotCtrl->setCommitCallback(boost::bind(&LLPanelPickEdit::onSnapshotChanged, this));
- // Look up the panel to fill in
- for (panel_list_t::iterator iter = sAllPanels.begin(); iter != sAllPanels.end(); ++iter)
- {
- LLPanelPick* self = *iter;
- // For top picks, must match pick id
- if (self->mPickID != pick_id)
- {
- continue;
- }
+ LLLineEditor* line_edit = getChild<LLLineEditor>("pick_name");
+ line_edit->setKeystrokeCallback(boost::bind(&LLPanelPickEdit::onPickChanged, this, _1), NULL);
- self->mDataReceived = TRUE;
+ LLTextEditor* text_edit = getChild<LLTextEditor>("pick_desc");
+ text_edit->setKeystrokeCallback(boost::bind(&LLPanelPickEdit::onPickChanged, this, _1));
- // Found the panel, now fill in the information
- self->mPickID = pick_id;
- self->mCreatorID = creator_id;
- self->mParcelID = parcel_id;
- self->mSimName.assign(sim_name);
- self->mPosGlobal = pos_global;
+ childSetAction(XML_BTN_SAVE, boost::bind(&LLPanelPickEdit::onClickSave, this));
+ childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelPickEdit::onClickSetLocation, this));
- // Update UI controls
- self->mNameEditor->setText(std::string(name));
- self->mDescEditor->setText(std::string(desc));
- self->mSnapshotCtrl->setImageAssetID(snapshot_id);
- self->mLocationEditor->setText(location_text);
- self->mEnabledCheck->set(enabled);
+ initTexturePickerMouseEvents();
- self->mSortOrderEditor->setText(llformat("%d", sort_order));
- }
+ return TRUE;
}
-void LLPanelPick::draw()
+void LLPanelPickEdit::setSaveCallback(const commit_callback_t& cb)
{
- refresh();
-
- LLPanel::draw();
+ getChild<LLButton>("save_changes_btn")->setClickedCallback(cb);
}
+void LLPanelPickEdit::setCancelCallback(const commit_callback_t& cb)
+{
+ getChild<LLButton>("cancel_btn")->setClickedCallback(cb);
+}
-void LLPanelPick::refresh()
+void LLPanelPickEdit::resetDirty()
{
- if (!mDataRequested)
- {
- sendPickInfoRequest();
- }
+ LLPanelPickInfo::resetDirty();
- // Check for god mode
- BOOL godlike = gAgent.isGodlike();
- BOOL is_self = (gAgent.getID() == mCreatorID);
+ getChild<LLLineEditor>("pick_name")->resetDirty();
+ getChild<LLTextEditor>("pick_desc")->resetDirty();
+ mSnapshotCtrl->resetDirty();
+ mLocationChanged = false;
+}
- // Set button visibility/enablement appropriately
- if (mTopPick)
+BOOL LLPanelPickEdit::isDirty() const
+{
+ if( mNewPick
+ || LLPanelPickInfo::isDirty()
+ || mLocationChanged
+ || mSnapshotCtrl->isDirty()
+ || getChild<LLLineEditor>("pick_name")->isDirty()
+ || getChild<LLTextEditor>("pick_desc")->isDirty())
{
- mSnapshotCtrl->setEnabled(godlike);
- mNameEditor->setEnabled(godlike);
- mDescEditor->setEnabled(godlike);
-
- mSortOrderText->setVisible(godlike);
+ return TRUE;
+ }
+ return FALSE;
+}
- mSortOrderEditor->setVisible(godlike);
- mSortOrderEditor->setEnabled(godlike);
+// PROTECTED AREA
- mEnabledCheck->setVisible(godlike);
- mEnabledCheck->setEnabled(godlike);
+void LLPanelPickEdit::sendUpdate()
+{
+ LLPickData pick_data;
- mSetBtn->setVisible(godlike);
- mSetBtn->setEnabled(godlike);
- }
- else
+ // 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())
{
- mSnapshotCtrl->setEnabled(is_self);
- mNameEditor->setEnabled(is_self);
- mDescEditor->setEnabled(is_self);
+ getPickId().generate();
+ }
- mSortOrderText->setVisible(FALSE);
+ pick_data.agent_id = gAgent.getID();
+ pick_data.session_id = gAgent.getSessionID();
+ pick_data.pick_id = getPickId();
+ pick_data.creator_id = gAgent.getID();;
- mSortOrderEditor->setVisible(FALSE);
- mSortOrderEditor->setEnabled(FALSE);
+ //legacy var need to be deleted
+ pick_data.top_pick = FALSE;
+ pick_data.parcel_id = mParcelId;
+ pick_data.name = childGetValue(XML_NAME).asString();
+ pick_data.desc = childGetValue(XML_DESC).asString();
+ pick_data.snapshot_id = mSnapshotCtrl->getImageAssetID();
+ pick_data.pos_global = getPosGlobal();
+ pick_data.sort_order = 0;
+ pick_data.enabled = TRUE;
- mEnabledCheck->setVisible(FALSE);
- mEnabledCheck->setEnabled(FALSE);
+ LLAvatarPropertiesProcessor::instance().sendPickInfoUpdate(&pick_data);
- mSetBtn->setVisible(is_self);
- mSetBtn->setEnabled(is_self);
+ 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
-void LLPanelPick::onClickTeleport(void* data)
+void LLPanelPickEdit::onSnapshotChanged()
{
- LLPanelPick* self = (LLPanelPick*)data;
-
- if (!self->mPosGlobal.isExactlyZero())
- {
- gAgent.teleportViaLocation(self->mPosGlobal);
- gFloaterWorldMap->trackLocation(self->mPosGlobal);
- }
+ enableSaveButton(true);
}
-
-// static
-void LLPanelPick::onClickMap(void* data)
+void LLPanelPickEdit::onPickChanged(LLUICtrl* ctrl)
{
- LLPanelPick* self = (LLPanelPick*)data;
- gFloaterWorldMap->trackLocation(self->mPosGlobal);
- LLFloaterWorldMap::show(NULL, TRUE);
+ enableSaveButton(isDirty());
}
-// static
-/*
-void LLPanelPick::onClickLandmark(void* data)
+void LLPanelPickEdit::resetData()
{
- LLPanelPick* self = (LLPanelPick*)data;
- create_landmark(self->mNameEditor->getText(), "", self->mPosGlobal);
+ LLPanelPickInfo::resetData();
+ mLocationChanged = false;
}
-*/
-// static
-void LLPanelPick::onClickSet(void* data)
+void LLPanelPickEdit::enableSaveButton(bool enable)
{
- LLPanelPick* self = (LLPanelPick*)data;
-
- // Save location for later.
- self->mPosGlobal = gAgent.getPositionGlobal();
+ childSetEnabled(XML_BTN_SAVE, enable);
+}
- std::string location_text;
- location_text.assign("(will update after save)");
- location_text.append(", ");
+void LLPanelPickEdit::onClickSetLocation()
+{
+ // Save location for later use.
+ setPosGlobal(gAgent.getPositionGlobal());
- S32 region_x = llround((F32)self->mPosGlobal.mdV[VX]) % REGION_WIDTH_UNITS;
- S32 region_y = llround((F32)self->mPosGlobal.mdV[VY]) % REGION_WIDTH_UNITS;
- S32 region_z = llround((F32)self->mPosGlobal.mdV[VZ]);
+ std::string parcel_name, region_name;
- location_text.append(self->mSimName);
- location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z));
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ if (parcel)
+ {
+ mParcelId = parcel->getID();
+ parcel_name = parcel->getName();
+ }
- // if sim name in pick is different from current sim name
- // make sure it's clear that all that's being changed
- // is the location and nothing else
- if ( gAgent.getRegion ()->getName () != self->mSimName )
+ LLViewerRegion* region = gAgent.getRegion();
+ if(region)
{
- LLNotifications::instance().add("SetPickLocation");
- };
+ region_name = region->getName();
+ }
- self->mLocationEditor->setText(location_text);
+ setPickLocation(createLocationText(SET_LOCATION_NOTICE, parcel_name, region_name, getPosGlobal()));
- onCommitAny(NULL, data);
+ mLocationChanged = true;
+ enableSaveButton(TRUE);
}
-
-// static
-void LLPanelPick::onCommitAny(LLUICtrl* ctrl, void* data)
+void LLPanelPickEdit::onClickSave()
{
- LLPanelPick* self = (LLPanelPick*)data;
+ sendUpdate();
- // have we received up to date data for this pick?
- if (self->mDataReceived)
- {
- self->sendPickInfoUpdate();
+ mLocationChanged = false;
- // Big hack - assume that top picks are always in a browser,
- // and non-top-picks are always in a tab container.
- /*if (self->mTopPick)
- {
- LLPanelDirPicks* panel = (LLPanelDirPicks*)self->getParent();
- panel->renamePick(self->mPickID, self->mNameEditor->getText());
- }
- else
- {*/
- LLTabContainer* tab = (LLTabContainer*)self->getParent();
- if (tab)
- {
- if(tab) tab->setCurrentTabName(self->mNameEditor->getText());
- }
- //}
+ LLSD params;
+ params["action"] = "save_new_pick";
+ notifyParent(params);
+}
+
+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
index 450fa78801..4f27760a8d 100644
--- a/indra/newview/llpanelpick.h
+++ b/indra/newview/llpanelpick.h
@@ -38,90 +38,231 @@
#define LL_LLPANELPICK_H
#include "llpanel.h"
-#include "v3dmath.h"
-#include "lluuid.h"
+#include "llremoteparcelrequest.h"
+#include "llavatarpropertiesprocessor.h"
-class LLButton;
-class LLCheckBoxCtrl;
class LLIconCtrl;
-class LLLineEditor;
-class LLTextBox;
-class LLTextEditor;
class LLTextureCtrl;
-class LLUICtrl;
+class LLScrollContainer;
class LLMessageSystem;
+class LLAvatarPropertiesObserver;
-class LLPanelPick : public LLPanel
+/**
+ * Panel for displaying Pick Information - snapshot, name, description, etc.
+ */
+class LLPanelPickInfo : public LLPanel, public LLAvatarPropertiesObserver, LLRemoteParcelInfoObserver
{
+ LOG_CLASS(LLPanelPickInfo);
public:
- LLPanelPick(BOOL top_pick);
- /*virtual*/ ~LLPanelPick();
+
+ // 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);
- void reset();
+ /*virtual*/ void processProperties(void* data, EAvatarProcessorType type);
- /*virtual*/ BOOL postBuild();
+ /**
+ * Sends remote parcel info request to resolve parcel name from its ID.
+ */
+ void sendParcelInfoRequest();
- /*virtual*/ void draw();
+ /**
+ * 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(U32 status, const std::string& reason) {};
+
+protected:
- /*virtual*/ void refresh();
+ LLPanelPickInfo();
+
+ /**
+ * Resets Pick information
+ */
+ virtual void resetData();
- // Setup a new pick, including creating an id, giving a sane
- // initial position, etc.
- void initNewPick();
+ /**
+ * Resets UI controls (visibility, values)
+ */
+ virtual void resetControls();
- // We need to know the creator id so the database knows which partition
- // to query for the pick data.
- void setPickID(const LLUUID& pick_id, const LLUUID& creator_id);
+ /**
+ * "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);
- // Schedules the panel to request data
- // from the server next time it is drawn.
- void markForServerRequest();
+ virtual void setAvatarId(const LLUUID& avatar_id) { mAvatarId = avatar_id; }
+ virtual LLUUID& getAvatarId() { return mAvatarId; }
- std::string getPickName();
- const LLUUID& getPickID() const { return mPickID; }
- const LLUUID& getPickCreatorID() const { return mCreatorID; }
+ /**
+ * 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; }
- void sendPickInfoRequest();
- void sendPickInfoUpdate();
+ /**
+ * Callback for "Map" button, opens Map
+ */
+ void onClickMap();
- static void processPickInfoReply(LLMessageSystem* msg, void**);
+ /**
+ * Callback for "Teleport" button, teleports user to Pick location.
+ */
+ void onClickTeleport();
+
+ void onClickBack();
protected:
- static void onClickTeleport(void* data);
- static void onClickMap(void* data);
- //static void onClickLandmark(void* data);
- static void onClickSet(void* data);
- static void onCommitAny(LLUICtrl* ctrl, void* data);
+ 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:
- BOOL mTopPick;
- LLUUID mPickID;
- LLUUID mCreatorID;
- LLUUID mParcelID;
- // Data will be requested on first draw
- BOOL mDataRequested;
- BOOL mDataReceived;
+ 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();
+
+protected:
- std::string mSimName;
- LLVector3d mPosGlobal;
+ bool mLocationChanged;
+ bool mNeedData;
+ bool mNewPick;
- LLTextureCtrl* mSnapshotCtrl;
- LLLineEditor* mNameEditor;
- LLTextEditor* mDescEditor;
- LLLineEditor* mLocationEditor;
+private:
- LLButton* mTeleportBtn;
- LLButton* mMapBtn;
+ void initTexturePickerMouseEvents();
+ void onTexturePickerMouseEnter(LLUICtrl* ctrl);
+ void onTexturePickerMouseLeave(LLUICtrl* ctrl);
- LLTextBox* mSortOrderText;
- LLLineEditor* mSortOrderEditor;
- LLCheckBoxCtrl* mEnabledCheck;
- LLButton* mSetBtn;
+private:
- typedef std::list<LLPanelPick*> panel_list_t;
- static panel_list_t sAllPanels;
+ LLIconCtrl* text_icon;
};
#endif // LL_LLPANELPICK_H
diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp
new file mode 100644
index 0000000000..ada65c98a4
--- /dev/null
+++ b/indra/newview/llpanelpicks.cpp
@@ -0,0 +1,1193 @@
+/**
+ * @file llpanelpicks.cpp
+ * @brief LLPanelPicks and related class implementations
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelpicks.h"
+
+#include "llagent.h"
+#include "llagentpicksinfo.h"
+#include "llavatarconstants.h"
+#include "llcommandhandler.h"
+#include "lldispatcher.h"
+#include "llflatlistview.h"
+#include "llfloaterreg.h"
+#include "llfloaterworldmap.h"
+#include "llnotificationsutil.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 "llpanelavatar.h"
+#include "llpanelprofile.h"
+#include "llpanelpick.h"
+#include "llpanelclassified.h"
+#include "llsidetray.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 LLRegisterPanelClassWrapper<LLPanelPicks> t_panel_picks("panel_picks");
+
+class LLClassifiedHandler :
+ public LLCommandHandler,
+ public LLAvatarPropertiesObserver
+{
+public:
+ // throttle calls from untrusted browsers
+ LLClassifiedHandler() : LLCommandHandler("classified", UNTRUSTED_THROTTLE) {}
+
+ std::set<LLUUID> mClassifiedIds;
+
+ bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
+ {
+ // 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")
+ {
+ 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 Me > Picks sidetray
+ LLSD params;
+ params["id"] = gAgent.getID();
+ params["open_tab_name"] = "panel_picks";
+ params["show_tab_panel"] = "create_classified";
+ LLSideTray::getInstance()->showPanel("panel_me", params);
+ }
+
+ void openClassified(LLAvatarClassifiedInfo* c_info)
+ {
+ // 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_avatar_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;
+ LLSideTray::getInstance()->showPanel("panel_profile_view", params);
+ }
+
+ /*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;
+
+//////////////////////////////////////////////////////////////////////////
+
+/**
+ * Copy&Pasted from old LLPanelClassified. This class does nothing at the moment.
+ * Subscribing to "classifiedclickthrough" removes a few warnings.
+ */
+class LLClassifiedClickThrough : public LLDispatchHandler
+{
+public:
+
+ // "classifiedclickthrough"
+ // strings[0] = classified_id
+ // strings[1] = teleport_clicks
+ // strings[2] = map_clicks
+ // strings[3] = profile_clicks
+ virtual bool operator()(
+ const LLDispatcher* dispatcher,
+ const std::string& key,
+ const LLUUID& invoice,
+ const sparam_t& strings)
+ {
+ if (strings.size() != 4)
+ return false;
+
+ return true;
+ }
+};
+
+//-----------------------------------------------------------------------------
+// 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),
+ mPanelClassifiedEdit(NULL),
+ mClickThroughDisp(NULL),
+ mNoClassifieds(false),
+ mNoPicks(false)
+{
+ mClickThroughDisp = new LLClassifiedClickThrough();
+ gGenericDispatcher.addHandler("classifiedclickthrough", mClickThroughDisp);
+}
+
+LLPanelPicks::~LLPanelPicks()
+{
+ if(getAvatarId().notNull())
+ {
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this);
+ }
+
+ delete mClickThroughDisp;
+}
+
+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;
+
+ childSetValue("picks_panel_text", LLTrans::getString("PicksClassifiedsLoadingText"));
+
+ 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)
+ {
+ std::string name, second_name;
+ gCacheName->getName(getAvatarId(),name,second_name);
+ childSetTextArg("pick_title", "[NAME]",name);
+
+ // 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)
+ {
+ LLAvatarClassifieds* c_info = static_cast<LLAvatarClassifieds*>(data);
+ if(c_info && getAvatarId() == c_info->target_id)
+ {
+ mClassifiedsList->clear();
+
+ 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);
+
+ 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();
+ }
+
+ if (mNoPicks && mNoClassifieds)
+ {
+ childSetValue("picks_panel_text", LLTrans::getString("NoPicksClassifiedsText"));
+ }
+}
+
+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"));
+
+ 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));
+ 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;
+}
+
+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
+ childSetEnabled("edit_panel", self);
+ childSetVisible("edit_panel", self);
+
+ // Disable buttons when viewing profile for first time
+ if(getAvatarId() != id)
+ {
+ childSetEnabled(XML_BTN_INFO,FALSE);
+ childSetEnabled(XML_BTN_TELEPORT,FALSE);
+ childSetEnabled(XML_BTN_SHOW_ON_MAP,FALSE);
+ }
+
+ // and see a special title - set as invisible by default in xml file
+ if (self)
+ {
+ childSetVisible("pick_title", !self);
+ childSetVisible("pick_title_agent", 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
+ {
+ llwarns << "Unknown list" << llendl;
+ }
+
+ 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);
+ }
+ 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);
+ }
+ 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();
+
+ 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)
+ 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)
+ {
+ childSetEnabled(XML_BTN_DELETE, has_selected);
+ }
+
+ childSetEnabled(XML_BTN_INFO, has_selected);
+ childSetEnabled(XML_BTN_TELEPORT, has_selected);
+ childSetEnabled(XML_BTN_SHOW_ON_MAP, has_selected);
+}
+
+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;
+ childGetRect(XML_BTN_NEW, rect);
+
+ 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()
+{
+ createClassifiedEditPanel();
+
+ getProfilePanel()->openPanel(mPanelClassifiedEdit, 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();
+
+ openClassifiedInfo(c_item->getClassifiedId(), c_item->getAvatarId(),
+ c_item->getSnapshotId(), c_item->getClassifiedName(),
+ c_item->getDescription());
+}
+
+void LLPanelPicks::openClassifiedInfo(const LLUUID &classified_id,
+ const LLUUID &avatar_id,
+ const LLUUID &snapshot_id,
+ const std::string &name, const std::string &desc)
+{
+ createClassifiedInfoPanel();
+
+ LLSD params;
+ params["classified_id"] = classified_id;
+ params["avatar_id"] = avatar_id;
+ params["snapshot_id"] = snapshot_id;
+ params["name"] = name;
+ params["desc"] = desc;
+
+ getProfilePanel()->openPanel(mPanelClassifiedInfo, params);
+}
+
+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)
+{
+ panel->setVisible(FALSE);
+}
+
+void LLPanelPicks::onPanelPickSave(LLPanel* panel)
+{
+ onPanelPickClose(panel);
+ updateButtons();
+}
+
+void LLPanelPicks::onPanelClassifiedSave(LLPanelClassifiedEdit* panel)
+{
+ if(!panel->canClose())
+ {
+ return;
+ }
+
+ if(panel->isNew())
+ {
+ LLClassifiedItem* c_item = new LLClassifiedItem(getAvatarId(), panel->getClassifiedId());
+
+ c_item->setClassifiedName(panel->getClassifiedName());
+ c_item->setDescription(panel->getDescription());
+ c_item->setSnapshotId(panel->getSnapshotId());
+
+ 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
+ {
+ 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]));
+
+ 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()
+{
+ if(!mPanelClassifiedInfo)
+ {
+ mPanelClassifiedInfo = LLPanelClassifiedInfo::create();
+ mPanelClassifiedInfo->setExitCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, mPanelClassifiedInfo));
+ mPanelClassifiedInfo->setEditClassifiedCallback(boost::bind(&LLPanelPicks::onPanelClassifiedEdit, this));
+ mPanelClassifiedInfo->setVisible(FALSE);
+ }
+}
+
+void LLPanelPicks::createClassifiedEditPanel()
+{
+ if(!mPanelClassifiedEdit)
+ {
+ mPanelClassifiedEdit = LLPanelClassifiedEdit::create();
+ mPanelClassifiedEdit->setExitCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, mPanelClassifiedEdit));
+ mPanelClassifiedEdit->setSaveCallback(boost::bind(&LLPanelPicks::onPanelClassifiedSave, this, mPanelClassifiedEdit));
+ mPanelClassifiedEdit->setCancelCallback(boost::bind(&LLPanelPicks::onPanelClassifiedClose, this, mPanelClassifiedEdit));
+ mPanelClassifiedEdit->setVisible(FALSE);
+ }
+}
+
+void LLPanelPicks::createPickEditPanel()
+{
+ if(!mPanelPickEdit)
+ {
+ 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::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());
+
+ createClassifiedEditPanel();
+
+ LLSD params;
+ params["classified_id"] = c_item->getClassifiedId();
+ params["avatar_id"] = c_item->getAvatarId();
+ params["snapshot_id"] = c_item->getSnapshotId();
+ params["name"] = c_item->getClassifiedName();
+ params["desc"] = c_item->getDescription();
+
+ getProfilePanel()->openPanel(mPanelClassifiedEdit, params);
+}
+
+void LLPanelPicks::onClickMenuEdit()
+{
+ if(getSelectedPickItem())
+ {
+ onPanelPickEdit();
+ }
+ else if(getSelectedClassifiedItem())
+ {
+ onPanelClassifiedEdit();
+ }
+}
+
+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)
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this,"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;
+ childSetValue("picture_name",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)
+{
+ childSetValue("picture_descr",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 childGetValue("picture_descr").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);
+}
+
+BOOL LLPickItem::postBuild()
+{
+ setMouseEnterCallback(boost::bind(&LLPanelPickInfo::childSetVisible, this, "hovered_icon", true));
+ setMouseLeaveCallback(boost::bind(&LLPanelPickInfo::childSetVisible, this, "hovered_icon", false));
+ return TRUE;
+}
+
+void LLPickItem::setValue(const LLSD& value)
+{
+ if (!value.isMap()) return;;
+ if (!value.has("selected")) return;
+ childSetVisible("selected_icon", value["selected"]);
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLClassifiedItem::LLClassifiedItem(const LLUUID& avatar_id, const LLUUID& classified_id)
+ : LLPanel()
+ , mAvatarId(avatar_id)
+ , mClassifiedId(classified_id)
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this,"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(&LLPanelPickInfo::childSetVisible, this, "hovered_icon", true));
+ setMouseLeaveCallback(boost::bind(&LLPanelPickInfo::childSetVisible, this, "hovered_icon", false));
+ return TRUE;
+}
+
+void LLClassifiedItem::setValue(const LLSD& value)
+{
+ if (!value.isMap()) return;;
+ if (!value.has("selected")) return;
+ childSetVisible("selected_icon", value["selected"]);
+}
+
+void LLClassifiedItem::setClassifiedName(const std::string& name)
+{
+ childSetValue("name", name);
+}
+
+void LLClassifiedItem::setDescription(const std::string& desc)
+{
+ childSetValue("description", desc);
+}
+
+void LLClassifiedItem::setSnapshotId(const LLUUID& snapshot_id)
+{
+ childSetValue("picture", snapshot_id);
+}
+
+LLUUID LLClassifiedItem::getSnapshotId()
+{
+ return childGetValue("picture");
+}
+
+//EOF
diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h
new file mode 100644
index 0000000000..3f757e482e
--- /dev/null
+++ b/indra/newview/llpanelpicks.h
@@ -0,0 +1,283 @@
+/**
+ * @file llpanelpicks.h
+ * @brief LLPanelPicks and related class definitions
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_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;
+class LLClassifiedClickThrough;
+
+// *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();
+
+ //*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);
+
+protected:
+ /*virtual*/void updateButtons();
+
+private:
+ void onClickDelete();
+ void onClickTeleport();
+ void onClickMap();
+
+ void onPlusMenuItemClicked(const LLSD& param);
+ bool isActionEnabled(const LLSD& userdata) const;
+
+ void onListCommit(const LLFlatListView* f_list);
+ void onAccordionStateChanged(const LLAccordionCtrlTab* acc_tab);
+
+ //------------------------------------------------
+ // 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 onPanelPickEdit();
+ void onPanelClassifiedEdit();
+ void onClickMenuEdit();
+
+ void createNewPick();
+ void createNewClassified();
+
+ void openPickInfo();
+ void openClassifiedInfo();
+ void openClassifiedInfo(const LLUUID &classified_id, const LLUUID &avatar_id,
+ const LLUUID &snapshot_id, const std::string &name,
+ const std::string &desc);
+ 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();
+
+ LLMenuGL* mPopupMenu;
+ LLPanelProfile* mProfilePanel;
+ LLPanelPickInfo* mPickPanel;
+ LLFlatListView* mPicksList;
+ LLFlatListView* mClassifiedsList;
+ LLPanelPickInfo* mPanelPickInfo;
+ LLPanelClassifiedInfo* mPanelClassifiedInfo;
+ LLPanelClassifiedEdit* mPanelClassifiedEdit;
+ LLPanelPickEdit* mPanelPickEdit;
+ LLToggleableMenu* mPlusMenu;
+
+ LLAccordionCtrlTab* mPicksAccTab;
+ LLAccordionCtrlTab* mClassifiedsAccTab;
+
+ LLClassifiedClickThrough* mClickThroughDisp;
+
+ //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);
+
+ 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 setClassifiedName (const std::string& name);
+
+ std::string getClassifiedName() { return childGetValue("name").asString(); }
+
+ void setDescription(const std::string& desc);
+
+ std::string getDescription() { return childGetValue("description").asString(); }
+
+ void setSnapshotId(const LLUUID& snapshot_id);
+
+ LLUUID getSnapshotId();
+
+private:
+ LLUUID mAvatarId;
+ LLUUID mClassifiedId;
+ LLVector3d mPosGlobal;
+};
+
+#endif // LL_LLPANELPICKS_H
diff --git a/indra/newview/llpanelplace.cpp b/indra/newview/llpanelplace.cpp
index 7ca3622634..6985b73200 100644
--- a/indra/newview/llpanelplace.cpp
+++ b/indra/newview/llpanelplace.cpp
@@ -36,33 +36,34 @@
#include "llviewercontrol.h"
#include "llqueryflags.h"
-#include "message.h"
#include "llui.h"
#include "llsecondlifeurls.h"
-#include "llremoteparcelrequest.h"
#include "llfloater.h"
+#include "llfloaterreg.h"
+#include "llregionhandle.h"
#include "llagent.h"
#include "llviewerwindow.h"
#include "llbutton.h"
#include "llfloaterworldmap.h"
#include "lllineeditor.h"
+#include "llnotificationsutil.h"
#include "lluiconstants.h"
#include "lltextbox.h"
-#include "llviewertexteditor.h"
+#include "lltexteditor.h"
#include "lltexturectrl.h"
+#include "lltrans.h"
#include "llworldmap.h"
#include "llviewerregion.h"
+#include "llvoavatarself.h"
#include "lluictrlfactory.h"
//#include "llviewermenu.h" // create_landmark()
#include "llweb.h"
#include "llsdutil.h"
-
-//static
-std::list<LLPanelPlace*> LLPanelPlace::sAllPanels;
+#include "llsdutil_math.h"
LLPanelPlace::LLPanelPlace()
-: LLPanel(std::string("Places Panel")),
+: LLPanel(),
mParcelID(),
mRequestedID(),
mRegionID(),
@@ -70,17 +71,16 @@ LLPanelPlace::LLPanelPlace()
mPosRegion(),
mAuctionID(0),
mLandmarkAssetID()
-{
- sAllPanels.push_back(this);
-}
-
+{}
LLPanelPlace::~LLPanelPlace()
{
- sAllPanels.remove(this);
+ if (mParcelID.notNull())
+ {
+ LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelID, this);
+ }
}
-
BOOL LLPanelPlace::postBuild()
{
// Since this is only used in the directory browser, always
@@ -102,20 +102,16 @@ BOOL LLPanelPlace::postBuild()
mLocationDisplay = getChild<LLTextBox>("location_editor");
mTeleportBtn = getChild<LLButton>( "teleport_btn");
- mTeleportBtn->setClickedCallback(onClickTeleport);
- mTeleportBtn->setCallbackUserData(this);
+ mTeleportBtn->setClickedCallback(onClickTeleport, this);
mMapBtn = getChild<LLButton>( "map_btn");
- mMapBtn->setClickedCallback(onClickMap);
- mMapBtn->setCallbackUserData(this);
+ mMapBtn->setClickedCallback(onClickMap, this);
//mLandmarkBtn = getChild<LLButton>( "landmark_btn");
- //mLandmarkBtn->setClickedCallback(onClickLandmark);
- //mLandmarkBtn->setCallbackUserData(this);
+ //mLandmarkBtn->setClickedCallback(onClickLandmark, this);
mAuctionBtn = getChild<LLButton>( "auction_btn");
- mAuctionBtn->setClickedCallback(onClickAuction);
- mAuctionBtn->setCallbackUserData(this);
+ mAuctionBtn->setClickedCallback(onClickAuction, this);
// Default to no auction button. We'll show it if we get an auction id
mAuctionBtn->setVisible(FALSE);
@@ -128,8 +124,11 @@ BOOL LLPanelPlace::postBuild()
void LLPanelPlace::displayItemInfo(const LLInventoryItem* pItem)
{
- mNameEditor->setText(pItem->getName());
- mDescEditor->setText(pItem->getDescription());
+ if (pItem)
+ {
+ mNameEditor->setText(pItem->getName());
+ mDescEditor->setText(pItem->getDescription());
+ }
}
// Use this for search directory clicks, because we are totally
@@ -177,6 +176,7 @@ void LLPanelPlace::resetName(const std::string& name)
}
}
+//virtual
void LLPanelPlace::setParcelID(const LLUUID& parcel_id)
{
mParcelID = parcel_id;
@@ -188,7 +188,6 @@ void LLPanelPlace::setSnapshot(const LLUUID& snapshot_id)
mSnapshotCtrl->setImageAssetID(snapshot_id);
}
-
void LLPanelPlace::setLocationString(const std::string& location)
{
mLocationDisplay->setText(location);
@@ -201,27 +200,22 @@ void LLPanelPlace::setLandTypeString(const std::string& land_type)
void LLPanelPlace::sendParcelInfoRequest()
{
- LLMessageSystem *msg = gMessageSystem;
-
if (mParcelID != mRequestedID)
{
- msg->newMessage("ParcelInfoRequest");
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
- msg->addUUID("SessionID", gAgent.getSessionID());
- msg->nextBlock("Data");
- msg->addUUID("ParcelID", mParcelID);
- gAgent.sendReliableMessage();
+ LLRemoteParcelInfoProcessor::getInstance()->addObserver(mParcelID, this);
+ LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(mParcelID);
+
mRequestedID = mParcelID;
}
}
+//virtual
void LLPanelPlace::setErrorStatus(U32 status, const std::string& reason)
{
// We only really handle 404 and 499 errors
std::string error_text;
if(status == 404)
- {
+ {
error_text = getString("server_error_text");
}
else if(status == 499)
@@ -231,140 +225,91 @@ void LLPanelPlace::setErrorStatus(U32 status, const std::string& reason)
mDescEditor->setText(error_text);
}
-//static
-void LLPanelPlace::processParcelInfoReply(LLMessageSystem *msg, void **)
+//virtual
+void LLPanelPlace::processParcelInfo(const LLParcelData& parcel_data)
{
- LLUUID agent_id;
- LLUUID parcel_id;
- LLUUID owner_id;
- std::string name;
- std::string desc;
- S32 actual_area;
- S32 billable_area;
- U8 flags;
- F32 global_x;
- F32 global_y;
- F32 global_z;
- std::string sim_name;
- LLUUID snapshot_id;
- F32 dwell;
- S32 sale_price;
- S32 auction_id;
-
- msg->getUUID("AgentData", "AgentID", agent_id );
- msg->getUUID("Data", "ParcelID", parcel_id);
-
- // look up all panels which have this avatar
- for (panel_list_t::iterator iter = sAllPanels.begin(); iter != sAllPanels.end(); ++iter)
- {
- LLPanelPlace* self = *iter;
- if (self->mParcelID != parcel_id)
- {
- continue;
- }
-
- msg->getUUID ("Data", "OwnerID", owner_id);
- msg->getString ("Data", "Name", name);
- msg->getString ("Data", "Desc", desc);
- msg->getS32 ("Data", "ActualArea", actual_area);
- msg->getS32 ("Data", "BillableArea", billable_area);
- msg->getU8 ("Data", "Flags", flags);
- msg->getF32 ("Data", "GlobalX", global_x);
- msg->getF32 ("Data", "GlobalY", global_y);
- msg->getF32 ("Data", "GlobalZ", global_z);
- msg->getString ("Data", "SimName", sim_name);
- msg->getUUID ("Data", "SnapshotID", snapshot_id);
- msg->getF32 ("Data", "Dwell", dwell);
- msg->getS32 ("Data", "SalePrice", sale_price);
- msg->getS32 ("Data", "AuctionID", auction_id);
-
-
- self->mAuctionID = auction_id;
-
- if(snapshot_id.notNull())
- {
- self->mSnapshotCtrl->setImageAssetID(snapshot_id);
- }
-
- // Only assign the name and description if they are not empty and there is not a
- // value present (passed in from a landmark, e.g.)
+ mAuctionID = parcel_data.auction_id;
- if( !name.empty()
- && self->mNameEditor && self->mNameEditor->getText().empty())
- {
- self->mNameEditor->setText(name);
- }
+ if(parcel_data.snapshot_id.notNull())
+ {
+ mSnapshotCtrl->setImageAssetID(parcel_data.snapshot_id);
+ }
- if( !desc.empty()
- && self->mDescEditor && self->mDescEditor->getText().empty())
- {
- self->mDescEditor->setText(desc);
- }
+ if( !parcel_data.name.empty()
+ && mNameEditor && mNameEditor->getText().empty())
+ {
+ mNameEditor->setText(parcel_data.name);
+ }
- std::string info_text;
- LLUIString traffic = self->getString("traffic_text");
- traffic.setArg("[TRAFFIC]", llformat("%d ", (int)dwell));
- info_text = traffic;
- LLUIString area = self->getString("area_text");
- area.setArg("[AREA]", llformat("%d", actual_area));
- info_text += area;
- if (flags & DFQ_FOR_SALE)
- {
- LLUIString forsale = self->getString("forsale_text");
- forsale.setArg("[PRICE]", llformat("%d", sale_price));
- info_text += forsale;
- }
- if (auction_id != 0)
- {
- LLUIString auction = self->getString("auction_text");
- auction.setArg("[ID]", llformat("%010d ", auction_id));
- info_text += auction;
- }
- if (self->mInfoEditor)
- {
- self->mInfoEditor->setText(info_text);
- }
+ if( !parcel_data.desc.empty()
+ && mDescEditor && mDescEditor->getText().empty())
+ {
+ mDescEditor->setText(parcel_data.desc);
+ }
- // HACK: Flag 0x2 == adult region,
- // Flag 0x1 == mature region, otherwise assume PG
- std::string rating = LLViewerRegion::accessToString(SIM_ACCESS_PG);
- if (flags & 0x2)
- {
- rating = LLViewerRegion::accessToString(SIM_ACCESS_ADULT);
- }
- else if (flags & 0x1)
- {
- rating = LLViewerRegion::accessToString(SIM_ACCESS_MATURE);
- }
+ std::string info_text;
+ LLUIString traffic = getString("traffic_text");
+ traffic.setArg("[TRAFFIC]", llformat("%d ", (int)parcel_data.dwell));
+ info_text = traffic;
+ LLUIString area = getString("area_text");
+ area.setArg("[AREA]", llformat("%d", parcel_data.actual_area));
+ info_text += area;
+ if (parcel_data.flags & DFQ_FOR_SALE)
+ {
+ LLUIString forsale = getString("forsale_text");
+ forsale.setArg("[PRICE]", llformat("%d", parcel_data.sale_price));
+ info_text += forsale;
+ }
+ if (parcel_data.auction_id != 0)
+ {
+ LLUIString auction = getString("auction_text");
+ auction.setArg("[ID]", llformat("%010d ", parcel_data.auction_id));
+ info_text += auction;
+ }
+ if (mInfoEditor)
+ {
+ mInfoEditor->setText(info_text);
+ }
- // Just use given region position for display
- S32 region_x = llround(self->mPosRegion.mV[0]);
- S32 region_y = llround(self->mPosRegion.mV[1]);
- S32 region_z = llround(self->mPosRegion.mV[2]);
+ // HACK: Flag 0x2 == adult region,
+ // Flag 0x1 == mature region, otherwise assume PG
+ std::string rating = LLViewerRegion::accessToString(SIM_ACCESS_PG);
+ if (parcel_data.flags & 0x2)
+ {
+ rating = LLViewerRegion::accessToString(SIM_ACCESS_ADULT);
+ }
+ else if (parcel_data.flags & 0x1)
+ {
+ rating = LLViewerRegion::accessToString(SIM_ACCESS_MATURE);
+ }
- // If the region position is zero, grab position from the global
- if(self->mPosRegion.isExactlyZero())
- {
- region_x = llround(global_x) % REGION_WIDTH_UNITS;
- region_y = llround(global_y) % REGION_WIDTH_UNITS;
- region_z = llround(global_z);
- }
+ // Just use given region position for display
+ S32 region_x = llround(mPosRegion.mV[0]);
+ S32 region_y = llround(mPosRegion.mV[1]);
+ S32 region_z = llround(mPosRegion.mV[2]);
- if(self->mPosGlobal.isExactlyZero())
- {
- self->mPosGlobal.setVec(global_x, global_y, global_z);
- }
+ // If the region position is zero, grab position from the global
+ if(mPosRegion.isExactlyZero())
+ {
+ region_x = llround(parcel_data.global_x) % REGION_WIDTH_UNITS;
+ region_y = llround(parcel_data.global_y) % REGION_WIDTH_UNITS;
+ region_z = llround(parcel_data.global_z);
+ }
- std::string location = llformat("%s %d, %d, %d (%s)",
- sim_name.c_str(), region_x, region_y, region_z, rating.c_str());
- if (self->mLocationDisplay)
- {
- self->mLocationDisplay->setText(location);
- }
+ if(mPosGlobal.isExactlyZero())
+ {
+ mPosGlobal.setVec(parcel_data.global_x, parcel_data.global_y, parcel_data.global_z);
+ }
- BOOL show_auction = (auction_id > 0);
- self->mAuctionBtn->setVisible(show_auction);
+ std::string location = llformat("%s %d, %d, %d (%s)",
+ parcel_data.sim_name.c_str(), region_x, region_y, region_z, rating.c_str());
+ if (mLocationDisplay)
+ {
+ mLocationDisplay->setText(location);
}
+
+ BOOL show_auction = (parcel_data.auction_id > 0);
+ mAuctionBtn->setVisible(show_auction);
}
@@ -390,7 +335,7 @@ void LLPanelPlace::displayParcelInfo(const LLVector3& pos_region,
U64 region_handle = to_region_handle(pos_global);
body["region_handle"] = ll_sd_from_U64(region_handle);
}
- LLHTTPClient::post(url, body, new LLRemoteParcelRequestResponder(this->getHandle()));
+ LLHTTPClient::post(url, body, new LLRemoteParcelRequestResponder(getObserverHandle()));
}
else
{
@@ -400,7 +345,6 @@ void LLPanelPlace::displayParcelInfo(const LLVector3& pos_region,
mSnapshotCtrl->setFallbackImageName("default_land_picture.j2c");
}
-
// static
void LLPanelPlace::onClickTeleport(void* data)
{
@@ -410,20 +354,21 @@ void LLPanelPlace::onClickTeleport(void* data)
LLFloater* parent_floaterp = dynamic_cast<LLFloater*>(parent_viewp);
if (parent_floaterp)
{
- parent_floaterp->close();
+ parent_floaterp->closeFloater();
}
// LLFloater* parent_floaterp = (LLFloater*)self->getParent();
parent_viewp->setVisible(false);
- if(self->mLandmarkAssetID.notNull())
+ LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
+ if(self->mLandmarkAssetID.notNull() && worldmap_instance)
{
gAgent.teleportViaLandmark(self->mLandmarkAssetID);
- gFloaterWorldMap->trackLandmark(self->mLandmarkAssetID);
+ worldmap_instance->trackLandmark(self->mLandmarkAssetID);
}
- else if (!self->mPosGlobal.isExactlyZero())
+ else if (!self->mPosGlobal.isExactlyZero() && worldmap_instance)
{
gAgent.teleportViaLocation(self->mPosGlobal);
- gFloaterWorldMap->trackLocation(self->mPosGlobal);
+ worldmap_instance->trackLocation(self->mPosGlobal);
}
}
@@ -431,10 +376,12 @@ void LLPanelPlace::onClickTeleport(void* data)
void LLPanelPlace::onClickMap(void* data)
{
LLPanelPlace* self = (LLPanelPlace*)data;
- if (!self->mPosGlobal.isExactlyZero())
+ LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
+
+ if (!self->mPosGlobal.isExactlyZero() && worldmap_instance)
{
- gFloaterWorldMap->trackLocation(self->mPosGlobal);
- LLFloaterWorldMap::show(NULL, TRUE);
+ worldmap_instance->trackLocation(self->mPosGlobal);
+ LLFloaterReg::showInstance("world_map", "center");
}
}
@@ -453,21 +400,20 @@ void LLPanelPlace::onClickLandmark(void* data)
void LLPanelPlace::onClickAuction(void* data)
{
LLPanelPlace* self = (LLPanelPlace*)data;
- LLSD payload;
- payload["auction_id"] = self->mAuctionID;
+ LLSD args;
+ args["AUCTION_ID"] = self->mAuctionID;
- LLNotifications::instance().add("GoToAuctionPage", LLSD(), payload, callbackAuctionWebPage);
+ LLNotificationsUtil::add("GoToAuctionPage", args);
}
-
+/*
// static
bool LLPanelPlace::callbackAuctionWebPage(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
std::string url;
- S32 auction_id = notification["payload"]["auction_id"].asInteger();
- url = AUCTION_URL + llformat("%010d", auction_id );
+ url = LLNotifications::instance().getGlobalString("AUCTION_URL") + llformat("%010d", response["auction_id"].asInteger());
llinfos << "Loading auction page " << url << llendl;
@@ -475,3 +421,5 @@ bool LLPanelPlace::callbackAuctionWebPage(const LLSD& notification, const LLSD&
}
return false;
}
+*/
+
diff --git a/indra/newview/llpanelplace.h b/indra/newview/llpanelplace.h
index b11290493a..f90a1b0567 100644
--- a/indra/newview/llpanelplace.h
+++ b/indra/newview/llpanelplace.h
@@ -38,6 +38,8 @@
#include "v3dmath.h"
#include "lluuid.h"
+#include "llremoteparcelrequest.h"
+
class LLButton;
class LLTextBox;
class LLLineEditor;
@@ -46,7 +48,7 @@ class LLTextureCtrl;
class LLMessageSystem;
class LLInventoryItem;
-class LLPanelPlace : public LLPanel
+class LLPanelPlace : public LLPanel, LLRemoteParcelInfoObserver
{
public:
LLPanelPlace();
@@ -58,7 +60,7 @@ public:
// Ignore all old location information, useful if you are
// recycling an existing dialog and need to clear it.
- void setParcelID(const LLUUID& parcel_id);
+ /*virtual*/ void setParcelID(const LLUUID& parcel_id);
// Sends a request for data about the given parcel, which will
// only update the location if there is none already available.
@@ -67,7 +69,7 @@ public:
void setSnapshot(const LLUUID& snapshot_id);
void setLocationString(const std::string& location);
void setLandTypeString(const std::string& land_type);
- void setErrorStatus(U32 status, const std::string& reason);
+ /*virtual*/ void setErrorStatus(U32 status, const std::string& reason);
void resetName(const std::string& name);
void sendParcelInfoRequest();
@@ -75,7 +77,7 @@ public:
const LLUUID& landmark_asset_id,
const LLUUID& region_id,
const LLVector3d& pos_global);
- static void processParcelInfoReply(LLMessageSystem* msg, void**);
+ /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
LLTextureCtrl *getSnapshotCtrl() const { return mSnapshotCtrl; }
@@ -113,9 +115,6 @@ protected:
LLButton* mMapBtn;
//LLButton* mLandmarkBtn;
LLButton* mAuctionBtn;
-
- typedef std::list<LLPanelPlace*> panel_list_t;
- static panel_list_t sAllPanels;
};
#endif // LL_LLPANELPLACE_H
diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp
new file mode 100644
index 0000000000..0c10f11bfc
--- /dev/null
+++ b/indra/newview/llpanelplaceinfo.cpp
@@ -0,0 +1,282 @@
+/**
+ * @file llpanelplaceinfo.cpp
+ * @brief Base class for place information in Side Tray.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelplaceinfo.h"
+
+#include "llsdutil.h"
+
+#include "llsdutil_math.h"
+
+#include "llregionhandle.h"
+
+#include "lliconctrl.h"
+#include "lltextbox.h"
+
+#include "llagent.h"
+#include "llexpandabletextbox.h"
+#include "llpanelpick.h"
+#include "lltexturectrl.h"
+#include "llviewerregion.h"
+
+LLPanelPlaceInfo::LLPanelPlaceInfo()
+: LLPanel(),
+ mParcelID(),
+ mRequestedID(),
+ mPosRegion(),
+ mScrollingPanelMinHeight(0),
+ mScrollingPanelWidth(0),
+ mScrollingPanel(NULL),
+ mScrollContainer(NULL)
+{}
+
+//virtual
+LLPanelPlaceInfo::~LLPanelPlaceInfo()
+{
+ if (mParcelID.notNull())
+ {
+ LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelID, this);
+ }
+}
+
+//virtual
+BOOL LLPanelPlaceInfo::postBuild()
+{
+ mTitle = getChild<LLTextBox>("title");
+ mCurrentTitle = mTitle->getText();
+
+ mSnapshotCtrl = getChild<LLTextureCtrl>("logo");
+ mRegionName = getChild<LLTextBox>("region_title");
+ mParcelName = getChild<LLTextBox>("parcel_title");
+ mDescEditor = getChild<LLExpandableTextBox>("description");
+
+ mMaturityRatingIcon = getChild<LLIconCtrl>("maturity_icon");
+ mMaturityRatingText = getChild<LLTextBox>("maturity_value");
+
+ mScrollingPanel = getChild<LLPanel>("scrolling_panel");
+ mScrollContainer = getChild<LLScrollContainer>("place_scroll");
+
+ mScrollingPanelMinHeight = mScrollContainer->getScrolledViewRect().getHeight();
+ mScrollingPanelWidth = mScrollingPanel->getRect().getWidth();
+
+ return TRUE;
+}
+
+//virtual
+void LLPanelPlaceInfo::resetLocation()
+{
+ mParcelID.setNull();
+ mRequestedID.setNull();
+ mPosRegion.clearVec();
+
+ std::string not_available = getString("not_available");
+ mMaturityRatingIcon->setValue(not_available);
+ mMaturityRatingText->setValue(not_available);
+ mRegionName->setText(not_available);
+ mParcelName->setText(not_available);
+ mDescEditor->setText(not_available);
+
+ mSnapshotCtrl->setImageAssetID(LLUUID::null);
+ mSnapshotCtrl->setFallbackImageName("default_land_picture.j2c");
+}
+
+//virtual
+void LLPanelPlaceInfo::setParcelID(const LLUUID& parcel_id)
+{
+ mParcelID = parcel_id;
+ sendParcelInfoRequest();
+}
+
+//virtual
+void LLPanelPlaceInfo::setInfoType(INFO_TYPE type)
+{
+ mTitle->setText(mCurrentTitle);
+
+ mInfoType = type;
+}
+
+void LLPanelPlaceInfo::sendParcelInfoRequest()
+{
+ if (mParcelID != mRequestedID)
+ {
+ LLRemoteParcelInfoProcessor::getInstance()->addObserver(mParcelID, this);
+ LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(mParcelID);
+
+ mRequestedID = mParcelID;
+ }
+}
+
+void LLPanelPlaceInfo::displayParcelInfo(const LLUUID& region_id,
+ const LLVector3d& pos_global)
+{
+ LLViewerRegion* region = gAgent.getRegion();
+ if (!region)
+ return;
+
+ mPosRegion.setVec((F32)fmod(pos_global.mdV[VX], (F64)REGION_WIDTH_METERS),
+ (F32)fmod(pos_global.mdV[VY], (F64)REGION_WIDTH_METERS),
+ (F32)pos_global.mdV[VZ]);
+
+ LLSD body;
+ std::string url = region->getCapability("RemoteParcelRequest");
+ if (!url.empty())
+ {
+ body["location"] = ll_sd_from_vector3(mPosRegion);
+ if (!region_id.isNull())
+ {
+ body["region_id"] = region_id;
+ }
+ if (!pos_global.isExactlyZero())
+ {
+ U64 region_handle = to_region_handle(pos_global);
+ body["region_handle"] = ll_sd_from_U64(region_handle);
+ }
+ LLHTTPClient::post(url, body, new LLRemoteParcelRequestResponder(getObserverHandle()));
+ }
+ else
+ {
+ mDescEditor->setText(getString("server_update_text"));
+ }
+}
+
+// virtual
+void LLPanelPlaceInfo::setErrorStatus(U32 status, const std::string& reason)
+{
+ // We only really handle 404 and 499 errors
+ std::string error_text;
+ if(status == 404)
+ {
+ error_text = getString("server_error_text");
+ }
+ else if(status == 499)
+ {
+ error_text = getString("server_forbidden_text");
+ }
+ mDescEditor->setText(error_text);
+}
+
+// virtual
+void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)
+{
+ if(parcel_data.snapshot_id.notNull())
+ {
+ mSnapshotCtrl->setImageAssetID(parcel_data.snapshot_id);
+ }
+
+ if(!parcel_data.sim_name.empty())
+ {
+ mRegionName->setText(parcel_data.sim_name);
+ }
+ else
+ {
+ mRegionName->setText(LLStringUtil::null);
+ }
+
+ if(!parcel_data.desc.empty())
+ {
+ mDescEditor->setText(parcel_data.desc);
+ }
+
+ S32 region_x;
+ S32 region_y;
+ S32 region_z;
+
+ // If the region position is zero, grab position from the global
+ if(mPosRegion.isExactlyZero())
+ {
+ region_x = llround(parcel_data.global_x) % REGION_WIDTH_UNITS;
+ region_y = llround(parcel_data.global_y) % REGION_WIDTH_UNITS;
+ region_z = llround(parcel_data.global_z);
+ }
+ else
+ {
+ region_x = llround(mPosRegion.mV[VX]);
+ region_y = llround(mPosRegion.mV[VY]);
+ region_z = llround(mPosRegion.mV[VZ]);
+ }
+
+ if (!parcel_data.name.empty())
+ {
+ mParcelTitle = parcel_data.name;
+
+ mParcelName->setText(llformat("%s (%d, %d, %d)",
+ mParcelTitle.c_str(), region_x, region_y, region_z));
+ }
+ else
+ {
+ mParcelName->setText(getString("not_available"));
+ }
+}
+
+// virtual
+void LLPanelPlaceInfo::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 LLPanelPlaceInfo::createPick(const LLVector3d& pos_global, LLPanelPickEdit* pick_panel)
+{
+ std::string region_name = mRegionName->getText();
+
+ LLPickData data;
+ data.pos_global = pos_global;
+ data.name = mParcelTitle.empty() ? region_name : mParcelTitle;
+ data.sim_name = region_name;
+ data.desc = mDescEditor->getText();
+ data.snapshot_id = mSnapshotCtrl->getImageAssetID();
+ data.parcel_id = mParcelID;
+ pick_panel->setPickData(&data);
+}
+
+// static
+void LLPanelPlaceInfo::nameUpdatedCallback(LLTextBox* text,
+ const std::string& first,
+ const std::string& last)
+{
+ text->setText(first + " " + last);
+}
diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h
new file mode 100644
index 0000000000..3091f7ed24
--- /dev/null
+++ b/indra/newview/llpanelplaceinfo.h
@@ -0,0 +1,130 @@
+/**
+ * @file llpanelplaceinfo.h
+ * @brief Base class for place information in Side Tray.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELPLACEINFO_H
+#define LL_LLPANELPLACEINFO_H
+
+#include "llpanel.h"
+
+#include "v3dmath.h"
+#include "lluuid.h"
+
+#include "llremoteparcelrequest.h"
+
+class LLExpandableTextBox;
+class LLIconCtrl;
+class LLInventoryItem;
+class LLPanelPickEdit;
+class LLParcel;
+class LLScrollContainer;
+class LLTextBox;
+class LLTextureCtrl;
+class LLViewerRegion;
+class LLViewerInventoryCategory;
+
+class LLPanelPlaceInfo : public LLPanel, LLRemoteParcelInfoObserver
+{
+public:
+ enum INFO_TYPE
+ {
+ AGENT,
+ CREATE_LANDMARK,
+ LANDMARK,
+ PLACE,
+ TELEPORT_HISTORY
+ };
+
+ LLPanelPlaceInfo();
+ /*virtual*/ ~LLPanelPlaceInfo();
+
+ /*virtual*/ BOOL postBuild();
+
+ // Ignore all old location information, useful if you are
+ // recycling an existing dialog and need to clear it.
+ virtual void resetLocation();
+
+ // Sends a request for data about the given parcel, which will
+ // only update the location if there is none already available.
+ /*virtual*/ void setParcelID(const LLUUID& parcel_id);
+
+ // Depending on how the panel was triggered
+ // (from landmark or current location, or other)
+ // sets a corresponding title and contents.
+ virtual void setInfoType(INFO_TYPE type);
+
+ // Requests remote parcel info by parcel ID.
+ void sendParcelInfoRequest();
+
+ // Displays information about a remote parcel.
+ // Sends a request to the server.
+ void displayParcelInfo(const LLUUID& region_id,
+ const LLVector3d& pos_global);
+
+ /*virtual*/ void setErrorStatus(U32 status, const std::string& reason);
+
+ /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
+
+ /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+ // Create a pick for the location specified
+ // by global_pos.
+ void createPick(const LLVector3d& pos_global, LLPanelPickEdit* pick_panel);
+
+protected:
+ static void nameUpdatedCallback(LLTextBox* text,
+ const std::string& first,
+ const std::string& last);
+
+ /**
+ * mParcelID is valid only for remote places, in other cases it's null. See resetLocation()
+ */
+ LLUUID mParcelID;
+ LLUUID mRequestedID;
+ LLVector3 mPosRegion;
+ std::string mParcelTitle; // used for pick title without coordinates
+ std::string mCurrentTitle;
+ S32 mScrollingPanelMinHeight;
+ S32 mScrollingPanelWidth;
+ INFO_TYPE mInfoType;
+
+ LLScrollContainer* mScrollContainer;
+ LLPanel* mScrollingPanel;
+ LLTextBox* mTitle;
+ LLTextureCtrl* mSnapshotCtrl;
+ LLTextBox* mRegionName;
+ LLTextBox* mParcelName;
+ LLExpandableTextBox* mDescEditor;
+ LLIconCtrl* mMaturityRatingIcon;
+ LLTextBox* mMaturityRatingText;
+};
+
+#endif // LL_LLPANELPLACEINFO_H
diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp
new file mode 100644
index 0000000000..d892e2885b
--- /dev/null
+++ b/indra/newview/llpanelplaceprofile.cpp
@@ -0,0 +1,608 @@
+/**
+ * @file llpanelplaceprofile.cpp
+ * @brief Displays place profile in Side Tray.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelplaceprofile.h"
+
+#include "llparcel.h"
+#include "message.h"
+
+#include "lliconctrl.h"
+#include "lllineeditor.h"
+#include "lltextbox.h"
+#include "lltexteditor.h"
+
+#include "llaccordionctrl.h"
+#include "llaccordionctrltab.h"
+#include "llagent.h"
+#include "llagentui.h"
+#include "llappviewer.h"
+#include "llcallbacklist.h"
+#include "llfloaterbuycurrency.h"
+#include "llstatusbar.h"
+#include "llviewercontrol.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+
+static LLRegisterPanelClassWrapper<LLPanelPlaceProfile> t_place_profile("panel_place_profile");
+
+// Statics for textures filenames
+static std::string icon_pg;
+static std::string icon_m;
+static std::string icon_r;
+static std::string icon_voice;
+static std::string icon_voice_no;
+static std::string icon_fly;
+static std::string icon_fly_no;
+static std::string icon_push;
+static std::string icon_push_no;
+static std::string icon_build;
+static std::string icon_build_no;
+static std::string icon_scripts;
+static std::string icon_scripts_no;
+static std::string icon_damage;
+static std::string icon_damage_no;
+
+LLPanelPlaceProfile::LLPanelPlaceProfile()
+: LLPanelPlaceInfo(),
+ mForSalePanel(NULL),
+ mYouAreHerePanel(NULL),
+ mSelectedParcelID(-1)
+{}
+
+// virtual
+LLPanelPlaceProfile::~LLPanelPlaceProfile()
+{}
+
+// virtual
+BOOL LLPanelPlaceProfile::postBuild()
+{
+ LLPanelPlaceInfo::postBuild();
+
+ mForSalePanel = getChild<LLPanel>("for_sale_panel");
+ mYouAreHerePanel = getChild<LLPanel>("here_panel");
+ gIdleCallbacks.addFunction(&LLPanelPlaceProfile::updateYouAreHereBanner, this);
+
+ //Icon value should contain sale price of last selected parcel.
+ mForSalePanel->getChild<LLIconCtrl>("icon_for_sale")->
+ setMouseDownCallback(boost::bind(&LLPanelPlaceProfile::onForSaleBannerClick, this));
+
+ mParcelOwner = getChild<LLTextBox>("owner_value");
+
+ mParcelRatingIcon = getChild<LLIconCtrl>("rating_icon");
+ mParcelRatingText = getChild<LLTextBox>("rating_value");
+ mVoiceIcon = getChild<LLIconCtrl>("voice_icon");
+ mVoiceText = getChild<LLTextBox>("voice_value");
+ mFlyIcon = getChild<LLIconCtrl>("fly_icon");
+ mFlyText = getChild<LLTextBox>("fly_value");
+ mPushIcon = getChild<LLIconCtrl>("push_icon");
+ mPushText = getChild<LLTextBox>("push_value");
+ mBuildIcon = getChild<LLIconCtrl>("build_icon");
+ mBuildText = getChild<LLTextBox>("build_value");
+ mScriptsIcon = getChild<LLIconCtrl>("scripts_icon");
+ mScriptsText = getChild<LLTextBox>("scripts_value");
+ mDamageIcon = getChild<LLIconCtrl>("damage_icon");
+ mDamageText = getChild<LLTextBox>("damage_value");
+
+ mRegionNameText = getChild<LLTextBox>("region_name");
+ mRegionTypeText = getChild<LLTextBox>("region_type");
+ mRegionRatingIcon = getChild<LLIconCtrl>("region_rating_icon");
+ mRegionRatingText = getChild<LLTextBox>("region_rating");
+ mRegionOwnerText = getChild<LLTextBox>("region_owner");
+ mRegionGroupText = getChild<LLTextBox>("region_group");
+
+ mEstateNameText = getChild<LLTextBox>("estate_name");
+ mEstateRatingText = getChild<LLTextBox>("estate_rating");
+ mEstateOwnerText = getChild<LLTextBox>("estate_owner");
+ mCovenantText = getChild<LLTextEditor>("covenant");
+
+ mSalesPriceText = getChild<LLTextBox>("sales_price");
+ mAreaText = getChild<LLTextBox>("area");
+ mTrafficText = getChild<LLTextBox>("traffic");
+ mPrimitivesText = getChild<LLTextBox>("primitives");
+ mParcelScriptsText = getChild<LLTextBox>("parcel_scripts");
+ mTerraformLimitsText = getChild<LLTextBox>("terraform_limits");
+ mSubdivideText = getChild<LLTextEditor>("subdivide");
+ mResaleText = getChild<LLTextEditor>("resale");
+ mSaleToText = getChild<LLTextBox>("sale_to");
+
+ icon_pg = getString("icon_PG");
+ icon_m = getString("icon_M");
+ icon_r = getString("icon_R");
+ icon_voice = getString("icon_Voice");
+ icon_voice_no = getString("icon_VoiceNo");
+ icon_fly = getString("icon_Fly");
+ icon_fly_no = getString("icon_FlyNo");
+ icon_push = getString("icon_Push");
+ icon_push_no = getString("icon_PushNo");
+ icon_build = getString("icon_Build");
+ icon_build_no = getString("icon_BuildNo");
+ icon_scripts = getString("icon_Scripts");
+ icon_scripts_no = getString("icon_ScriptsNo");
+ icon_damage = getString("icon_Damage");
+ icon_damage_no = getString("icon_DamageNo");
+
+ return TRUE;
+}
+
+// virtual
+void LLPanelPlaceProfile::resetLocation()
+{
+ LLPanelPlaceInfo::resetLocation();
+
+ mForSalePanel->setVisible(FALSE);
+ mYouAreHerePanel->setVisible(FALSE);
+
+ std::string not_available = getString("not_available");
+ mParcelOwner->setValue(not_available);
+
+ mParcelRatingIcon->setValue(not_available);
+ mParcelRatingText->setText(not_available);
+ mVoiceIcon->setValue(not_available);
+ mVoiceText->setText(not_available);
+ mFlyIcon->setValue(not_available);
+ mFlyText->setText(not_available);
+ mPushIcon->setValue(not_available);
+ mPushText->setText(not_available);
+ mBuildIcon->setValue(not_available);
+ mBuildText->setText(not_available);
+ mScriptsIcon->setValue(not_available);
+ mScriptsText->setText(not_available);
+ mDamageIcon->setValue(not_available);
+ mDamageText->setText(not_available);
+
+ mRegionNameText->setValue(not_available);
+ mRegionTypeText->setValue(not_available);
+ mRegionRatingIcon->setValue(not_available);
+ mRegionRatingText->setValue(not_available);
+ mRegionOwnerText->setValue(not_available);
+ mRegionGroupText->setValue(not_available);
+
+ mEstateNameText->setValue(not_available);
+ mEstateRatingText->setValue(not_available);
+ mEstateOwnerText->setValue(not_available);
+ mCovenantText->setValue(not_available);
+
+ mSalesPriceText->setValue(not_available);
+ mAreaText->setValue(not_available);
+ mTrafficText->setValue(not_available);
+ mPrimitivesText->setValue(not_available);
+ mParcelScriptsText->setValue(not_available);
+ mTerraformLimitsText->setValue(not_available);
+ mSubdivideText->setValue(not_available);
+ mResaleText->setValue(not_available);
+ mSaleToText->setValue(not_available);
+}
+
+// virtual
+void LLPanelPlaceProfile::setInfoType(INFO_TYPE type)
+{
+ bool is_info_type_agent = type == AGENT;
+
+ mMaturityRatingIcon->setVisible(!is_info_type_agent);
+ mMaturityRatingText->setVisible(!is_info_type_agent);
+
+ getChild<LLTextBox>("owner_label")->setVisible(is_info_type_agent);
+ mParcelOwner->setVisible(is_info_type_agent);
+
+ getChild<LLAccordionCtrl>("advanced_info_accordion")->setVisible(is_info_type_agent);
+
+ switch(type)
+ {
+ case AGENT:
+ case PLACE:
+ default:
+ mCurrentTitle = getString("title_place");
+ break;
+
+ case TELEPORT_HISTORY:
+ mCurrentTitle = getString("title_teleport_history");
+ break;
+ }
+
+ LLPanelPlaceInfo::setInfoType(type);
+}
+
+// virtual
+void LLPanelPlaceProfile::processParcelInfo(const LLParcelData& parcel_data)
+{
+ LLPanelPlaceInfo::processParcelInfo(parcel_data);
+
+ // HACK: Flag 0x2 == adult region,
+ // Flag 0x1 == mature region, otherwise assume PG
+ if (parcel_data.flags & 0x2)
+ {
+ mMaturityRatingIcon->setValue(icon_r);
+ mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_ADULT));
+ }
+ else if (parcel_data.flags & 0x1)
+ {
+ mMaturityRatingIcon->setValue(icon_m);
+ mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_MATURE));
+ }
+ else
+ {
+ mMaturityRatingIcon->setValue(icon_pg);
+ mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_PG));
+ }
+}
+
+// virtual
+void LLPanelPlaceProfile::handleVisibilityChange(BOOL new_visibility)
+{
+ LLPanel::handleVisibilityChange(new_visibility);
+
+ LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
+ if (!parcel_mgr)
+ return;
+
+ // Remove land selection when panel hides.
+ if (!new_visibility)
+ {
+ if (!parcel_mgr->selectionEmpty())
+ {
+ parcel_mgr->deselectUnused();
+ }
+ }
+}
+
+void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
+ LLViewerRegion* region,
+ const LLVector3d& pos_global,
+ bool is_current_parcel)
+{
+ if (!region || !parcel)
+ return;
+
+ // send EstateCovenantInfo message
+ LLMessageSystem *msg = gMessageSystem;
+ msg->newMessage("EstateCovenantRequest");
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID());
+ msg->sendReliable(region->getHost());
+
+ LLParcelData parcel_data;
+
+ // HACK: Converting sim access flags to the format
+ // returned by remote parcel response.
+ U8 sim_access = region->getSimAccess();
+ switch(sim_access)
+ {
+ case SIM_ACCESS_MATURE:
+ parcel_data.flags = 0x1;
+
+ mParcelRatingIcon->setValue(icon_m);
+ mRegionRatingIcon->setValue(icon_m);
+ break;
+
+ case SIM_ACCESS_ADULT:
+ parcel_data.flags = 0x2;
+
+ mParcelRatingIcon->setValue(icon_r);
+ mRegionRatingIcon->setValue(icon_r);
+ break;
+
+ default:
+ parcel_data.flags = 0;
+
+ mParcelRatingIcon->setValue(icon_pg);
+ mRegionRatingIcon->setValue(icon_pg);
+ }
+
+ std::string rating = LLViewerRegion::accessToString(sim_access);
+ mParcelRatingText->setText(rating);
+ mRegionRatingText->setText(rating);
+
+ parcel_data.desc = parcel->getDesc();
+ parcel_data.name = parcel->getName();
+ parcel_data.sim_name = region->getName();
+ parcel_data.snapshot_id = parcel->getSnapshotID();
+ mPosRegion.setVec((F32)fmod(pos_global.mdV[VX], (F64)REGION_WIDTH_METERS),
+ (F32)fmod(pos_global.mdV[VY], (F64)REGION_WIDTH_METERS),
+ (F32)pos_global.mdV[VZ]);
+ parcel_data.global_x = pos_global.mdV[VX];
+ parcel_data.global_y = pos_global.mdV[VY];
+ parcel_data.global_z = pos_global.mdV[VZ];
+
+ std::string on = getString("on");
+ std::string off = getString("off");
+
+ // Processing parcel characteristics
+ if (parcel->getParcelFlagAllowVoice())
+ {
+ mVoiceIcon->setValue(icon_voice);
+ mVoiceText->setText(on);
+ }
+ else
+ {
+ mVoiceIcon->setValue(icon_voice_no);
+ mVoiceText->setText(off);
+ }
+
+ if (!region->getBlockFly() && parcel->getAllowFly())
+ {
+ mFlyIcon->setValue(icon_fly);
+ mFlyText->setText(on);
+ }
+ else
+ {
+ mFlyIcon->setValue(icon_fly_no);
+ mFlyText->setText(off);
+ }
+
+ if (region->getRestrictPushObject() || parcel->getRestrictPushObject())
+ {
+ mPushIcon->setValue(icon_push_no);
+ mPushText->setText(off);
+ }
+ else
+ {
+ mPushIcon->setValue(icon_push);
+ mPushText->setText(on);
+ }
+
+ if (parcel->getAllowModify())
+ {
+ mBuildIcon->setValue(icon_build);
+ mBuildText->setText(on);
+ }
+ else
+ {
+ mBuildIcon->setValue(icon_build_no);
+ mBuildText->setText(off);
+ }
+
+ if((region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS) ||
+ (region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS) ||
+ !parcel->getAllowOtherScripts())
+ {
+ mScriptsIcon->setValue(icon_scripts_no);
+ mScriptsText->setText(off);
+ }
+ else
+ {
+ mScriptsIcon->setValue(icon_scripts);
+ mScriptsText->setText(on);
+ }
+
+ if (region->getAllowDamage() || parcel->getAllowDamage())
+ {
+ mDamageIcon->setValue(icon_damage);
+ mDamageText->setText(on);
+ }
+ else
+ {
+ mDamageIcon->setValue(icon_damage_no);
+ mDamageText->setText(off);
+ }
+
+ mRegionNameText->setText(region->getName());
+ mRegionTypeText->setText(region->getSimProductName());
+
+ // Determine parcel owner
+ if (parcel->isPublic())
+ {
+ mParcelOwner->setText(getString("public"));
+ mRegionOwnerText->setText(getString("public"));
+ }
+ else
+ {
+ if (parcel->getIsGroupOwned())
+ {
+ mRegionOwnerText->setText(getString("group_owned_text"));
+
+ if(!parcel->getGroupID().isNull())
+ {
+ // FIXME: Using parcel group as region group.
+ gCacheName->get(parcel->getGroupID(), TRUE,
+ boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mRegionGroupText, _2, _3));
+
+ gCacheName->get(parcel->getGroupID(), TRUE,
+ boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mParcelOwner, _2, _3));
+ }
+ else
+ {
+ std::string owner = getString("none_text");
+ mRegionGroupText->setText(owner);
+ mParcelOwner->setText(owner);
+ }
+ }
+ else
+ {
+ // Figure out the owner's name
+ gCacheName->get(parcel->getOwnerID(), FALSE,
+ boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mParcelOwner, _2, _3));
+ gCacheName->get(region->getOwner(), FALSE,
+ boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mRegionOwnerText, _2, _3));
+ }
+
+ if(LLParcel::OS_LEASE_PENDING == parcel->getOwnershipStatus())
+ {
+ mRegionOwnerText->setText(mRegionOwnerText->getText() + getString("sale_pending_text"));
+ }
+ }
+
+ mEstateRatingText->setText(region->getSimAccessString());
+
+ S32 area;
+ S32 claim_price;
+ S32 rent_price;
+ F32 dwell;
+ BOOL for_sale = parcel->getForSale();
+ LLViewerParcelMgr::getInstance()->getDisplayInfo(&area,
+ &claim_price,
+ &rent_price,
+ &for_sale,
+ &dwell);
+ if (for_sale)
+ {
+ const LLUUID& auth_buyer_id = parcel->getAuthorizedBuyerID();
+ if(auth_buyer_id.notNull())
+ {
+ gCacheName->get(auth_buyer_id, TRUE,
+ boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mSaleToText, _2, _3));
+
+ // Show sales info to a specific person or a group he belongs to.
+ if (auth_buyer_id != gAgent.getID() && !gAgent.isInGroup(auth_buyer_id))
+ {
+ for_sale = FALSE;
+ }
+ }
+ else
+ {
+ mSaleToText->setText(getString("anyone"));
+ }
+
+ mForSalePanel->setVisible(for_sale);
+
+ const U8* sign = (U8*)getString("price_text").c_str();
+ const U8* sqm = (U8*)getString("area_text").c_str();
+
+ mSalesPriceText->setText(llformat("%s%d ", sign, parcel->getSalePrice()));
+ mAreaText->setText(llformat("%d %s", area, sqm));
+ mTrafficText->setText(llformat("%.0f", dwell));
+
+ // Can't have more than region max tasks, regardless of parcel
+ // object bonus factor.
+ S32 primitives = llmin(llround(parcel->getMaxPrimCapacity() * parcel->getParcelPrimBonus()),
+ (S32)region->getMaxTasks());
+
+ const U8* available = (U8*)getString("available").c_str();
+ const U8* allocated = (U8*)getString("allocated").c_str();
+
+ mPrimitivesText->setText(llformat("%d %s, %d %s", primitives, available, parcel->getPrimCount(), allocated));
+
+ if (parcel->getAllowOtherScripts())
+ {
+ mParcelScriptsText->setText(getString("all_residents_text"));
+ }
+ else if (parcel->getAllowGroupScripts())
+ {
+ mParcelScriptsText->setText(getString("group_text"));
+ }
+ else
+ {
+ mParcelScriptsText->setText(off);
+ }
+
+ mTerraformLimitsText->setText(parcel->getAllowTerraform() ? on : off);
+
+ if (region->getRegionFlags() & REGION_FLAGS_ALLOW_PARCEL_CHANGES)
+ {
+ mSubdivideText->setText(getString("can_change"));
+ }
+ else
+ {
+ mSubdivideText->setText(getString("can_not_change"));
+ }
+ if (region->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL)
+ {
+ mResaleText->setText(getString("can_not_resell"));
+ }
+ else
+ {
+ mResaleText->setText(getString("can_resell"));
+ }
+ }
+
+ mSelectedParcelID = parcel->getLocalID();
+ mLastSelectedRegionID = region->getRegionID();
+ LLPanelPlaceInfo::processParcelInfo(parcel_data);
+
+ mYouAreHerePanel->setVisible(is_current_parcel);
+ getChild<LLAccordionCtrlTab>("sales_tab")->setVisible(for_sale);
+}
+
+void LLPanelPlaceProfile::updateEstateName(const std::string& name)
+{
+ mEstateNameText->setText(name);
+}
+
+void LLPanelPlaceProfile::updateEstateOwnerName(const std::string& name)
+{
+ mEstateOwnerText->setText(name);
+}
+
+void LLPanelPlaceProfile::updateCovenantText(const std::string &text)
+{
+ mCovenantText->setText(text);
+}
+
+void LLPanelPlaceProfile::onForSaleBannerClick()
+{
+ LLViewerParcelMgr* mgr = LLViewerParcelMgr::getInstance();
+ LLParcel* parcel = mgr->getFloatingParcelSelection()->getParcel();
+ LLViewerRegion* selected_region = mgr->getSelectionRegion();
+ if(parcel && selected_region)
+ {
+ if(parcel->getLocalID() == mSelectedParcelID &&
+ mLastSelectedRegionID ==selected_region->getRegionID())
+ {
+ if(parcel->getSalePrice() - gStatusBar->getBalance() > 0)
+ {
+ LLFloaterBuyCurrency::buyCurrency("Buying selected land ", parcel->getSalePrice());
+ }
+ else
+ {
+ LLViewerParcelMgr::getInstance()->startBuyLand();
+ }
+ }
+ else
+ {
+ LL_WARNS("Places") << "User is trying to buy remote parcel.Operation is not supported"<< LL_ENDL;
+ }
+
+ }
+}
+
+// static
+void LLPanelPlaceProfile::updateYouAreHereBanner(void* userdata)
+{
+ //YouAreHere Banner should be displayed only for selected places,
+ // If you want to display it for landmark or teleport history item, you should check by mParcelId
+
+ LLPanelPlaceProfile* self = static_cast<LLPanelPlaceProfile*>(userdata);
+ if(!self->getVisible())
+ return;
+
+ if(!gDisconnected && gAgent.getRegion())
+ {
+ static F32 radius = gSavedSettings.getF32("YouAreHereDistance");
+
+ BOOL display_banner = gAgent.getRegion()->getRegionID() == self->mLastSelectedRegionID &&
+ LLAgentUI::checkAgentDistance(self->mPosRegion, radius);
+
+ self->mYouAreHerePanel->setVisible(display_banner);
+ }
+}
diff --git a/indra/newview/llpanelplaceprofile.h b/indra/newview/llpanelplaceprofile.h
new file mode 100644
index 0000000000..8ca9526875
--- /dev/null
+++ b/indra/newview/llpanelplaceprofile.h
@@ -0,0 +1,123 @@
+/**
+ * @file llpanelplaceprofile.h
+ * @brief Displays place profile in Side Tray.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELPLACEPROFILE_H
+#define LL_LLPANELPLACEPROFILE_H
+
+#include "llpanelplaceinfo.h"
+
+class LLIconCtrl;
+class LLTextEditor;
+
+class LLPanelPlaceProfile : public LLPanelPlaceInfo
+{
+public:
+ LLPanelPlaceProfile();
+ /*virtual*/ ~LLPanelPlaceProfile();
+
+ /*virtual*/ BOOL postBuild();
+
+ /*virtual*/ void resetLocation();
+
+ /*virtual*/ void setInfoType(INFO_TYPE type);
+
+ /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
+
+ /*virtual*/ void handleVisibilityChange(BOOL new_visibility);
+
+ // Displays information about the currently selected parcel
+ // without sending a request to the server.
+ // If is_current_parcel true shows "You Are Here" banner.
+ void displaySelectedParcelInfo(LLParcel* parcel,
+ LLViewerRegion* region,
+ const LLVector3d& pos_global,
+ bool is_current_parcel);
+
+ void updateEstateName(const std::string& name);
+ void updateEstateOwnerName(const std::string& name);
+ void updateCovenantText(const std::string &text);
+
+private:
+ void onForSaleBannerClick();
+
+ static void updateYouAreHereBanner(void*);// added to gIdleCallbacks
+
+ /**
+ * Holds last displayed parcel. Needed for YouAreHere banner.
+ */
+ S32 mSelectedParcelID;
+ LLUUID mLastSelectedRegionID;
+
+ LLPanel* mForSalePanel;
+ LLPanel* mYouAreHerePanel;
+
+ LLTextBox* mParcelOwner;
+
+ LLIconCtrl* mParcelRatingIcon;
+ LLTextBox* mParcelRatingText;
+ LLIconCtrl* mVoiceIcon;
+ LLTextBox* mVoiceText;
+ LLIconCtrl* mFlyIcon;
+ LLTextBox* mFlyText;
+ LLIconCtrl* mPushIcon;
+ LLTextBox* mPushText;
+ LLIconCtrl* mBuildIcon;
+ LLTextBox* mBuildText;
+ LLIconCtrl* mScriptsIcon;
+ LLTextBox* mScriptsText;
+ LLIconCtrl* mDamageIcon;
+ LLTextBox* mDamageText;
+
+ LLTextBox* mRegionNameText;
+ LLTextBox* mRegionTypeText;
+ LLIconCtrl* mRegionRatingIcon;
+ LLTextBox* mRegionRatingText;
+ LLTextBox* mRegionOwnerText;
+ LLTextBox* mRegionGroupText;
+
+ LLTextBox* mEstateNameText;
+ LLTextBox* mEstateRatingText;
+ LLTextBox* mEstateOwnerText;
+ LLTextEditor* mCovenantText;
+
+ LLTextBox* mSalesPriceText;
+ LLTextBox* mAreaText;
+ LLTextBox* mTrafficText;
+ LLTextBox* mPrimitivesText;
+ LLTextBox* mParcelScriptsText;
+ LLTextBox* mTerraformLimitsText;
+ LLTextEditor* mSubdivideText;
+ LLTextEditor* mResaleText;
+ LLTextBox* mSaleToText;
+};
+
+#endif // LL_LLPANELPLACEPROFILE_H
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
new file mode 100644
index 0000000000..a8a9717750
--- /dev/null
+++ b/indra/newview/llpanelplaces.cpp
@@ -0,0 +1,1070 @@
+/**
+ * @file llpanelplaces.cpp
+ * @brief Side Bar "Places" panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelplaces.h"
+
+#include "llassettype.h"
+#include "llwindow.h"
+
+#include "llinventory.h"
+#include "lllandmark.h"
+#include "llparcel.h"
+
+#include "llcombobox.h"
+#include "llfiltereditor.h"
+#include "llfloaterreg.h"
+#include "llnotificationsutil.h"
+#include "lltabcontainer.h"
+#include "lltexteditor.h"
+#include "lltrans.h"
+#include "lluictrlfactory.h"
+
+#include "llagent.h"
+#include "llagentpicksinfo.h"
+#include "llavatarpropertiesprocessor.h"
+#include "llfloaterworldmap.h"
+#include "llinventorybridge.h"
+#include "llinventoryobserver.h"
+#include "llinventorymodel.h"
+#include "lllandmarkactions.h"
+#include "lllandmarklist.h"
+#include "llpanellandmarkinfo.h"
+#include "llpanellandmarks.h"
+#include "llpanelpick.h"
+#include "llpanelplaceprofile.h"
+#include "llpanelteleporthistory.h"
+#include "llremoteparcelrequest.h"
+#include "llteleporthistorystorage.h"
+#include "lltoggleablemenu.h"
+#include "llviewerinventory.h"
+#include "llviewermenu.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+#include "llviewerwindow.h"
+
+static const S32 LANDMARK_FOLDERS_MENU_WIDTH = 250;
+static const std::string AGENT_INFO_TYPE = "agent";
+static const std::string CREATE_LANDMARK_INFO_TYPE = "create_landmark";
+static const std::string LANDMARK_INFO_TYPE = "landmark";
+static const std::string REMOTE_PLACE_INFO_TYPE = "remote_place";
+static const std::string TELEPORT_HISTORY_INFO_TYPE = "teleport_history";
+
+// Helper functions
+static bool is_agent_in_selected_parcel(LLParcel* parcel);
+static void onSLURLBuilt(std::string& slurl);
+
+//Observer classes
+class LLPlacesParcelObserver : public LLParcelObserver
+{
+public:
+ LLPlacesParcelObserver(LLPanelPlaces* places_panel) :
+ LLParcelObserver(),
+ mPlaces(places_panel)
+ {}
+
+ /*virtual*/ void changed()
+ {
+ if (mPlaces)
+ mPlaces->changedParcelSelection();
+ }
+
+private:
+ LLPanelPlaces* mPlaces;
+};
+
+class LLPlacesInventoryObserver : public LLInventoryObserver
+{
+public:
+ LLPlacesInventoryObserver(LLPanelPlaces* places_panel) :
+ LLInventoryObserver(),
+ mPlaces(places_panel)
+ {}
+
+ /*virtual*/ void changed(U32 mask)
+ {
+ if (mPlaces)
+ mPlaces->changedInventory(mask);
+ }
+
+private:
+ LLPanelPlaces* mPlaces;
+};
+
+class LLPlacesRemoteParcelInfoObserver : public LLRemoteParcelInfoObserver
+{
+public:
+ LLPlacesRemoteParcelInfoObserver(LLPanelPlaces* places_panel) :
+ LLRemoteParcelInfoObserver(),
+ mPlaces(places_panel)
+ {}
+
+ ~LLPlacesRemoteParcelInfoObserver()
+ {
+ // remove any in-flight observers
+ std::set<LLUUID>::iterator it;
+ for (it = mParcelIDs.begin(); it != mParcelIDs.end(); ++it)
+ {
+ const LLUUID &id = *it;
+ LLRemoteParcelInfoProcessor::getInstance()->removeObserver(id, this);
+ }
+ mParcelIDs.clear();
+ }
+
+ /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data)
+ {
+ if (mPlaces)
+ {
+ mPlaces->changedGlobalPos(LLVector3d(parcel_data.global_x,
+ parcel_data.global_y,
+ parcel_data.global_z));
+ }
+
+ mParcelIDs.erase(parcel_data.parcel_id);
+ LLRemoteParcelInfoProcessor::getInstance()->removeObserver(parcel_data.parcel_id, this);
+ }
+ /*virtual*/ void setParcelID(const LLUUID& parcel_id)
+ {
+ if (!parcel_id.isNull())
+ {
+ mParcelIDs.insert(parcel_id);
+ LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this);
+ LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id);
+ }
+ }
+ /*virtual*/ void setErrorStatus(U32 status, const std::string& reason)
+ {
+ llerrs << "Can't complete remote parcel request. Http Status: "
+ << status << ". Reason : " << reason << llendl;
+ }
+
+private:
+ std::set<LLUUID> mParcelIDs;
+ LLPanelPlaces* mPlaces;
+};
+
+
+static LLRegisterPanelClassWrapper<LLPanelPlaces> t_places("panel_places");
+
+LLPanelPlaces::LLPanelPlaces()
+ : LLPanel(),
+ mActivePanel(NULL),
+ mFilterEditor(NULL),
+ mPlaceProfile(NULL),
+ mLandmarkInfo(NULL),
+ mPickPanel(NULL),
+ mItem(NULL),
+ mPlaceMenu(NULL),
+ mLandmarkMenu(NULL),
+ mPosGlobal(),
+ isLandmarkEditModeOn(false)
+{
+ mParcelObserver = new LLPlacesParcelObserver(this);
+ mInventoryObserver = new LLPlacesInventoryObserver(this);
+ mRemoteParcelObserver = new LLPlacesRemoteParcelInfoObserver(this);
+
+ gInventory.addObserver(mInventoryObserver);
+
+ LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(
+ boost::bind(&LLPanelPlaces::updateVerbs, this));
+
+ //LLUICtrlFactory::getInstance()->buildPanel(this, "panel_places.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder()
+}
+
+LLPanelPlaces::~LLPanelPlaces()
+{
+ if (gInventory.containsObserver(mInventoryObserver))
+ gInventory.removeObserver(mInventoryObserver);
+
+ LLViewerParcelMgr::getInstance()->removeObserver(mParcelObserver);
+
+ delete mInventoryObserver;
+ delete mParcelObserver;
+ delete mRemoteParcelObserver;
+}
+
+BOOL LLPanelPlaces::postBuild()
+{
+ mTeleportBtn = getChild<LLButton>("teleport_btn");
+ mTeleportBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onTeleportButtonClicked, this));
+
+ mShowOnMapBtn = getChild<LLButton>("map_btn");
+ mShowOnMapBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onShowOnMapButtonClicked, this));
+
+ mEditBtn = getChild<LLButton>("edit_btn");
+ mEditBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this));
+
+ mSaveBtn = getChild<LLButton>("save_btn");
+ mSaveBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onSaveButtonClicked, this));
+
+ mCancelBtn = getChild<LLButton>("cancel_btn");
+ mCancelBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onCancelButtonClicked, this));
+
+ mCloseBtn = getChild<LLButton>("close_btn");
+ mCloseBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this));
+
+ mOverflowBtn = getChild<LLButton>("overflow_btn");
+ mOverflowBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onOverflowButtonClicked, this));
+
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("Places.OverflowMenu.Action", boost::bind(&LLPanelPlaces::onOverflowMenuItemClicked, this, _2));
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+ enable_registrar.add("Places.OverflowMenu.Enable", boost::bind(&LLPanelPlaces::onOverflowMenuItemEnable, this, _2));
+
+ mPlaceMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_place.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if (!mPlaceMenu)
+ {
+ llwarns << "Error loading Place menu" << llendl;
+ }
+
+ mLandmarkMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_landmark.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if (!mLandmarkMenu)
+ {
+ llwarns << "Error loading Landmark menu" << llendl;
+ }
+
+ mTabContainer = getChild<LLTabContainer>("Places Tabs");
+ if (mTabContainer)
+ {
+ mTabContainer->setCommitCallback(boost::bind(&LLPanelPlaces::onTabSelected, this));
+ }
+
+ mFilterEditor = getChild<LLFilterEditor>("Filter");
+ if (mFilterEditor)
+ {
+ mFilterEditor->setCommitCallback(boost::bind(&LLPanelPlaces::onFilterEdit, this, _2, false));
+ }
+
+ mPlaceProfile = getChild<LLPanelPlaceProfile>("panel_place_profile");
+ mLandmarkInfo = getChild<LLPanelLandmarkInfo>("panel_landmark_info");
+ if (!mPlaceProfile || !mLandmarkInfo)
+ return FALSE;
+
+ LLButton* back_btn = mPlaceProfile->getChild<LLButton>("back_btn");
+ back_btn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this));
+
+ back_btn = mLandmarkInfo->getChild<LLButton>("back_btn");
+ back_btn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this));
+
+ LLLineEditor* title_editor = mLandmarkInfo->getChild<LLLineEditor>("title_editor");
+ title_editor->setKeystrokeCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this), NULL);
+
+ LLTextEditor* notes_editor = mLandmarkInfo->getChild<LLTextEditor>("notes_editor");
+ notes_editor->setKeystrokeCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this));
+
+ LLComboBox* folder_combo = mLandmarkInfo->getChild<LLComboBox>("folder_combo");
+ folder_combo->setCommitCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this));
+
+ return TRUE;
+}
+
+void LLPanelPlaces::onOpen(const LLSD& key)
+{
+ if (!mPlaceProfile || !mLandmarkInfo)
+ return;
+
+ if (key.size() != 0)
+ {
+ mFilterEditor->clear();
+ onFilterEdit("", false);
+
+ mPlaceInfoType = key["type"].asString();
+ mPosGlobal.setZero();
+ mItem = NULL;
+ isLandmarkEditModeOn = false;
+ togglePlaceInfoPanel(TRUE);
+
+ if (mPlaceInfoType == AGENT_INFO_TYPE)
+ {
+ mPlaceProfile->setInfoType(LLPanelPlaceInfo::AGENT);
+ }
+ else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE)
+ {
+ mLandmarkInfo->setInfoType(LLPanelPlaceInfo::CREATE_LANDMARK);
+
+ if (key.has("x") && key.has("y") && key.has("z"))
+ {
+ mPosGlobal = LLVector3d(key["x"].asReal(),
+ key["y"].asReal(),
+ key["z"].asReal());
+ }
+ else
+ {
+ mPosGlobal = gAgent.getPositionGlobal();
+ }
+
+ mLandmarkInfo->displayParcelInfo(LLUUID(), mPosGlobal);
+
+ // Disable Save button because there is no item to save yet.
+ // The button will be enabled in onLandmarkLoaded callback.
+ mSaveBtn->setEnabled(FALSE);
+ }
+ else if (mPlaceInfoType == LANDMARK_INFO_TYPE)
+ {
+ mLandmarkInfo->setInfoType(LLPanelPlaceInfo::LANDMARK);
+
+ LLInventoryItem* item = gInventory.getItem(key["id"].asUUID());
+ if (!item)
+ return;
+
+ setItem(item);
+ }
+ else if (mPlaceInfoType == REMOTE_PLACE_INFO_TYPE)
+ {
+ if (key.has("id"))
+ {
+ LLUUID parcel_id = key["id"].asUUID();
+ mPlaceProfile->setParcelID(parcel_id);
+
+ // query the server to get the global 3D position of this
+ // parcel - we need this for teleport/mapping functions.
+ mRemoteParcelObserver->setParcelID(parcel_id);
+ }
+ else
+ {
+ mPosGlobal = LLVector3d(key["x"].asReal(),
+ key["y"].asReal(),
+ key["z"].asReal());
+ mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal);
+ }
+
+ mPlaceProfile->setInfoType(LLPanelPlaceInfo::PLACE);
+ }
+ else if (mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
+ {
+ S32 index = key["id"].asInteger();
+
+ const LLTeleportHistoryStorage::slurl_list_t& hist_items =
+ LLTeleportHistoryStorage::getInstance()->getItems();
+
+ mPosGlobal = hist_items[index].mGlobalPos;
+
+ mPlaceProfile->setInfoType(LLPanelPlaceInfo::TELEPORT_HISTORY);
+ mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal);
+ }
+
+ updateVerbs();
+ }
+
+ LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
+ if (!parcel_mgr)
+ return;
+
+ // Start using LLViewerParcelMgr for land selection if
+ // information about nearby land is requested.
+ // Otherwise stop using land selection and deselect land.
+ if (mPlaceInfoType == AGENT_INFO_TYPE)
+ {
+ // We don't know if we are already added to LLViewerParcelMgr observers list
+ // so try to remove observer not to add an extra one.
+ parcel_mgr->removeObserver(mParcelObserver);
+
+ parcel_mgr->addObserver(mParcelObserver);
+ parcel_mgr->selectParcelAt(gAgent.getPositionGlobal());
+ }
+ else
+ {
+ parcel_mgr->removeObserver(mParcelObserver);
+
+ // Clear the reference to selection to allow its removal in deselectUnused().
+ mParcel.clear();
+
+ if (!parcel_mgr->selectionEmpty())
+ {
+ parcel_mgr->deselectUnused();
+ }
+ }
+}
+
+void LLPanelPlaces::setItem(LLInventoryItem* item)
+{
+ if (!mLandmarkInfo || !item)
+ return;
+
+ mItem = item;
+
+ LLAssetType::EType item_type = mItem->getActualType();
+ if (item_type == LLAssetType::AT_LANDMARK || item_type == LLAssetType::AT_LINK)
+ {
+ // If the item is a link get a linked item
+ if (item_type == LLAssetType::AT_LINK)
+ {
+ mItem = gInventory.getItem(mItem->getLinkedUUID());
+ if (mItem.isNull())
+ return;
+ }
+ }
+ else
+ {
+ return;
+ }
+
+ // Check if item is in agent's inventory and he has the permission to modify it.
+ BOOL is_landmark_editable = gInventory.isObjectDescendentOf(mItem->getUUID(), gInventory.getRootFolderID()) &&
+ mItem->getPermissions().allowModifyBy(gAgent.getID());
+
+ mEditBtn->setEnabled(is_landmark_editable);
+ mSaveBtn->setEnabled(is_landmark_editable);
+
+ if (is_landmark_editable)
+ {
+ if(!mLandmarkInfo->setLandmarkFolder(mItem->getParentUUID()) && !mItem->getParentUUID().isNull())
+ {
+ const LLViewerInventoryCategory* cat = gInventory.getCategory(mItem->getParentUUID());
+ if (cat)
+ {
+ std::string cat_fullname = LLPanelLandmarkInfo::getFullFolderName(cat);
+ LLComboBox* folderList = mLandmarkInfo->getChild<LLComboBox>("folder_combo");
+ folderList->add(cat_fullname, cat->getUUID(), ADD_TOP);
+ }
+ }
+ }
+
+ mLandmarkInfo->displayItemInfo(mItem);
+
+ LLLandmark* lm = gLandmarkList.getAsset(mItem->getAssetUUID(),
+ boost::bind(&LLPanelPlaces::onLandmarkLoaded, this, _1));
+ if (lm)
+ {
+ onLandmarkLoaded(lm);
+ }
+}
+
+S32 LLPanelPlaces::notifyParent(const LLSD& info)
+{
+ if(info.has("update_verbs"))
+ {
+ if(mPosGlobal.isExactlyZero())
+ {
+ mPosGlobal.setVec(info["global_x"], info["global_y"], info["global_z"]);
+ }
+
+ updateVerbs();
+
+ return 1;
+ }
+ return LLPanel::notifyParent(info);
+}
+
+void LLPanelPlaces::onLandmarkLoaded(LLLandmark* landmark)
+{
+ if (!mLandmarkInfo)
+ return;
+
+ LLUUID region_id;
+ landmark->getRegionID(region_id);
+ landmark->getGlobalPos(mPosGlobal);
+ mLandmarkInfo->displayParcelInfo(region_id, mPosGlobal);
+
+ mSaveBtn->setEnabled(TRUE);
+
+ updateVerbs();
+}
+
+void LLPanelPlaces::onFilterEdit(const std::string& search_string, bool force_filter)
+{
+ if (!mActivePanel)
+ return;
+
+ if (force_filter || mActivePanel->getFilterSubString() != search_string)
+ {
+ std::string string = search_string;
+
+ // Searches are case-insensitive
+ LLStringUtil::toUpper(string);
+ LLStringUtil::trimHead(string);
+
+ mActivePanel->onSearchEdit(string);
+ }
+}
+
+void LLPanelPlaces::onTabSelected()
+{
+ mActivePanel = dynamic_cast<LLPanelPlacesTab*>(mTabContainer->getCurrentPanel());
+ if (!mActivePanel)
+ return;
+
+ onFilterEdit(mActivePanel->getFilterSubString(), true);
+ mActivePanel->updateVerbs();
+}
+
+void LLPanelPlaces::onTeleportButtonClicked()
+{
+ LLPanelPlaceInfo* panel = getCurrentInfoPanel();
+ if (panel && panel->getVisible())
+ {
+ if (mPlaceInfoType == LANDMARK_INFO_TYPE)
+ {
+ LLSD payload;
+ payload["asset_id"] = mItem->getAssetUUID();
+ LLNotificationsUtil::add("TeleportFromLandmark", LLSD(), payload);
+ }
+ else if (mPlaceInfoType == AGENT_INFO_TYPE ||
+ mPlaceInfoType == REMOTE_PLACE_INFO_TYPE ||
+ mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
+ {
+ LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
+ if (!mPosGlobal.isExactlyZero() && worldmap_instance)
+ {
+ gAgent.teleportViaLocation(mPosGlobal);
+ worldmap_instance->trackLocation(mPosGlobal);
+ }
+ }
+ }
+ else
+ {
+ if (mActivePanel)
+ mActivePanel->onTeleport();
+ }
+}
+
+void LLPanelPlaces::onShowOnMapButtonClicked()
+{
+ LLPanelPlaceInfo* panel = getCurrentInfoPanel();
+ if (panel && panel->getVisible())
+ {
+ LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
+ if(!worldmap_instance)
+ return;
+
+ if (mPlaceInfoType == AGENT_INFO_TYPE ||
+ mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE ||
+ mPlaceInfoType == REMOTE_PLACE_INFO_TYPE ||
+ mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
+ {
+ if (!mPosGlobal.isExactlyZero())
+ {
+ worldmap_instance->trackLocation(mPosGlobal);
+ LLFloaterReg::showInstance("world_map", "center");
+ }
+ }
+ else if (mPlaceInfoType == LANDMARK_INFO_TYPE)
+ {
+ LLLandmark* landmark = gLandmarkList.getAsset(mItem->getAssetUUID());
+ if (!landmark)
+ return;
+
+ LLVector3d landmark_global_pos;
+ if (!landmark->getGlobalPos(landmark_global_pos))
+ return;
+
+ if (!landmark_global_pos.isExactlyZero())
+ {
+ worldmap_instance->trackLocation(landmark_global_pos);
+ LLFloaterReg::showInstance("world_map", "center");
+ }
+ }
+ }
+ else
+ {
+ if (mActivePanel)
+ mActivePanel->onShowOnMap();
+ }
+}
+
+void LLPanelPlaces::onEditButtonClicked()
+{
+ if (!mLandmarkInfo || isLandmarkEditModeOn)
+ return;
+
+ isLandmarkEditModeOn = true;
+
+ mLandmarkInfo->toggleLandmarkEditMode(TRUE);
+
+ updateVerbs();
+}
+
+void LLPanelPlaces::onSaveButtonClicked()
+{
+ if (!mLandmarkInfo || mItem.isNull())
+ return;
+
+ std::string current_title_value = mLandmarkInfo->getLandmarkTitle();
+ std::string item_title_value = mItem->getName();
+ std::string current_notes_value = mLandmarkInfo->getLandmarkNotes();
+ std::string item_notes_value = mItem->getDescription();
+
+ LLStringUtil::trim(current_title_value);
+ LLStringUtil::trim(current_notes_value);
+
+ LLUUID item_id = mItem->getUUID();
+ LLUUID folder_id = mLandmarkInfo->getLandmarkFolder();
+
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(mItem);
+
+ if (!current_title_value.empty() &&
+ (item_title_value != current_title_value || item_notes_value != current_notes_value))
+ {
+ new_item->rename(current_title_value);
+ new_item->setDescription(current_notes_value);
+ new_item->updateServer(FALSE);
+ }
+
+ if(folder_id != mItem->getParentUUID())
+ {
+ LLInventoryModel::update_list_t update;
+ LLInventoryModel::LLCategoryUpdate old_folder(mItem->getParentUUID(),-1);
+ update.push_back(old_folder);
+ LLInventoryModel::LLCategoryUpdate new_folder(folder_id, 1);
+ update.push_back(new_folder);
+ gInventory.accountForUpdate(update);
+
+ new_item->setParent(folder_id);
+ new_item->updateParentOnServer(FALSE);
+ }
+
+ gInventory.updateItem(new_item);
+ gInventory.notifyObservers();
+
+ onCancelButtonClicked();
+}
+
+void LLPanelPlaces::onCancelButtonClicked()
+{
+ if (!mLandmarkInfo)
+ return;
+
+ if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE)
+ {
+ onBackButtonClicked();
+ }
+ else
+ {
+ mLandmarkInfo->toggleLandmarkEditMode(FALSE);
+ isLandmarkEditModeOn = false;
+
+ updateVerbs();
+
+ // Reload the landmark properties.
+ mLandmarkInfo->displayItemInfo(mItem);
+ }
+}
+
+void LLPanelPlaces::onOverflowButtonClicked()
+{
+ LLToggleableMenu* menu;
+
+ bool is_agent_place_info_visible = mPlaceInfoType == AGENT_INFO_TYPE;
+
+ if ((is_agent_place_info_visible ||
+ mPlaceInfoType == "remote_place" ||
+ mPlaceInfoType == "teleport_history") && mPlaceMenu != NULL)
+ {
+ menu = mPlaceMenu;
+
+ // Enable adding a landmark only for agent current parcel and if
+ // there is no landmark already pointing to that parcel in agent's inventory.
+ menu->getChild<LLMenuItemCallGL>("landmark")->setEnabled(is_agent_place_info_visible &&
+ !LLLandmarkActions::landmarkAlreadyExists());
+ }
+ else if (mPlaceInfoType == LANDMARK_INFO_TYPE && mLandmarkMenu != NULL)
+ {
+ menu = mLandmarkMenu;
+
+ BOOL is_landmark_removable = FALSE;
+ if (mItem.notNull())
+ {
+ const LLUUID& item_id = mItem->getUUID();
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ is_landmark_removable = gInventory.isObjectDescendentOf(item_id, gInventory.getRootFolderID()) &&
+ !gInventory.isObjectDescendentOf(item_id, trash_id);
+ }
+
+ menu->getChild<LLMenuItemCallGL>("delete")->setEnabled(is_landmark_removable);
+ }
+ else
+ {
+ return;
+ }
+
+ if (!menu->toggleVisibility())
+ return;
+
+ if (menu->getButtonRect().isEmpty())
+ {
+ menu->setButtonRect(mOverflowBtn);
+ }
+ menu->updateParent(LLMenuGL::sMenuContainer);
+ LLRect rect = mOverflowBtn->getRect();
+ LLMenuGL::showPopup(this, menu, rect.mRight, rect.mTop);
+}
+
+bool LLPanelPlaces::onOverflowMenuItemEnable(const LLSD& param)
+{
+ std::string value = param.asString();
+ if("can_create_pick" == value)
+ {
+ return !LLAgentPicksInfo::getInstance()->isPickLimitReached();
+ }
+ return true;
+}
+
+void LLPanelPlaces::onOverflowMenuItemClicked(const LLSD& param)
+{
+ std::string item = param.asString();
+ if (item == "landmark")
+ {
+ LLSD key;
+ key["type"] = CREATE_LANDMARK_INFO_TYPE;
+ key["x"] = mPosGlobal.mdV[VX];
+ key["y"] = mPosGlobal.mdV[VY];
+ key["z"] = mPosGlobal.mdV[VZ];
+ onOpen(key);
+ }
+ else if (item == "copy")
+ {
+ LLLandmarkActions::getSLURLfromPosGlobal(mPosGlobal, boost::bind(&onSLURLBuilt, _1));
+ }
+ else if (item == "delete")
+ {
+ gInventory.removeItem(mItem->getUUID());
+
+ onBackButtonClicked();
+ }
+ 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);
+ }
+
+ LLRect rect = getRect();
+ mPickPanel->reshape(rect.getWidth(), rect.getHeight());
+ mPickPanel->setRect(rect);
+ }
+ else if (item == "add_to_favbar")
+ {
+ if ( mItem.notNull() )
+ {
+ const LLUUID& favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+ if ( favorites_id.notNull() )
+ {
+ copy_inventory_item(gAgent.getID(),
+ mItem->getPermissions().getOwner(),
+ mItem->getUUID(),
+ favorites_id,
+ std::string(),
+ LLPointer<LLInventoryCallback>(NULL));
+ llinfos << "Copied inventory item #" << mItem->getUUID() << " to favorites." << llendl;
+ }
+ }
+ }
+}
+
+void LLPanelPlaces::onBackButtonClicked()
+{
+ togglePlaceInfoPanel(FALSE);
+
+ // Resetting mPlaceInfoType when Place Info panel is closed.
+ mPlaceInfoType = LLStringUtil::null;
+
+ isLandmarkEditModeOn = false;
+
+ updateVerbs();
+}
+
+void LLPanelPlaces::togglePickPanel(BOOL visible)
+{
+ if (mPickPanel)
+ mPickPanel->setVisible(visible);
+}
+
+void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)
+{
+ if (!mPlaceProfile || !mLandmarkInfo)
+ return;
+
+ mFilterEditor->setVisible(!visible);
+ mTabContainer->setVisible(!visible);
+
+ if (mPlaceInfoType == AGENT_INFO_TYPE ||
+ mPlaceInfoType == REMOTE_PLACE_INFO_TYPE ||
+ mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
+ {
+ mPlaceProfile->setVisible(visible);
+
+ if (visible)
+ {
+ mPlaceProfile->resetLocation();
+
+ LLRect rect = getRect();
+ LLRect new_rect = LLRect(rect.mLeft, rect.mTop, rect.mRight, mTabContainer->getRect().mBottom);
+ mPlaceProfile->reshape(new_rect.getWidth(), new_rect.getHeight());
+
+ mLandmarkInfo->setVisible(FALSE);
+ }
+ else if (mPlaceInfoType == AGENT_INFO_TYPE)
+ {
+ LLViewerParcelMgr::getInstance()->removeObserver(mParcelObserver);
+
+ // Clear reference to parcel selection when closing place profile panel.
+ // LLViewerParcelMgr removes the selection if it has 1 reference to it.
+ mParcel.clear();
+ }
+ }
+ else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE ||
+ mPlaceInfoType == LANDMARK_INFO_TYPE)
+ {
+ mLandmarkInfo->setVisible(visible);
+
+ if (visible)
+ {
+ mLandmarkInfo->resetLocation();
+
+ LLRect rect = getRect();
+ LLRect new_rect = LLRect(rect.mLeft, rect.mTop, rect.mRight, mTabContainer->getRect().mBottom);
+ mLandmarkInfo->reshape(new_rect.getWidth(), new_rect.getHeight());
+
+ mPlaceProfile->setVisible(FALSE);
+ }
+ else
+ {
+ LLLandmarksPanel* landmarks_panel =
+ dynamic_cast<LLLandmarksPanel*>(mTabContainer->getPanelByName("Landmarks"));
+ if (landmarks_panel && mItem.notNull())
+ {
+ // If a landmark info is being closed we open the landmarks tab
+ // and set this landmark selected.
+ mTabContainer->selectTabPanel(landmarks_panel);
+
+ landmarks_panel->setItemSelected(mItem->getUUID(), TRUE);
+ }
+ }
+ }
+}
+
+// virtual
+void LLPanelPlaces::handleVisibilityChange(BOOL new_visibility)
+{
+ LLPanel::handleVisibilityChange(new_visibility);
+
+ if (!new_visibility && mPlaceInfoType == AGENT_INFO_TYPE)
+ {
+ LLViewerParcelMgr::getInstance()->removeObserver(mParcelObserver);
+
+ // Clear reference to parcel selection when closing places panel.
+ mParcel.clear();
+ }
+}
+
+void LLPanelPlaces::changedParcelSelection()
+{
+ if (!mPlaceProfile)
+ return;
+
+ LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
+ mParcel = parcel_mgr->getFloatingParcelSelection();
+ LLParcel* parcel = mParcel->getParcel();
+ LLViewerRegion* region = parcel_mgr->getSelectionRegion();
+ if (!region || !parcel)
+ return;
+
+ LLVector3d prev_pos_global = mPosGlobal;
+
+ // If agent is inside the selected parcel show agent's region<X, Y, Z>,
+ // otherwise show region<X, Y, Z> of agent's selection point.
+ bool is_current_parcel = is_agent_in_selected_parcel(parcel);
+ if (is_current_parcel)
+ {
+ mPosGlobal = gAgent.getPositionGlobal();
+ }
+ else
+ {
+ LLVector3d pos_global = gViewerWindow->getLastPick().mPosGlobal;
+ if (!pos_global.isExactlyZero())
+ {
+ mPosGlobal = pos_global;
+ }
+ }
+
+ // Reset location info only if global position is changed
+ // to reduce unnecessary text and icons updates.
+ if (prev_pos_global != mPosGlobal)
+ {
+ mPlaceProfile->resetLocation();
+ }
+
+ mPlaceProfile->displaySelectedParcelInfo(parcel, region, mPosGlobal, is_current_parcel);
+
+ updateVerbs();
+}
+
+void LLPanelPlaces::changedInventory(U32 mask)
+{
+ if (!(gInventory.isInventoryUsable() && LLTeleportHistory::getInstance()))
+ return;
+
+ LLLandmarksPanel* landmarks_panel = new LLLandmarksPanel();
+ if (landmarks_panel)
+ {
+ landmarks_panel->setPanelPlacesButtons(this);
+
+ mTabContainer->addTabPanel(
+ LLTabContainer::TabPanelParams().
+ panel(landmarks_panel).
+ label(getString("landmarks_tab_title")).
+ insert_at(LLTabContainer::END));
+ }
+
+ LLTeleportHistoryPanel* teleport_history_panel = new LLTeleportHistoryPanel();
+ if (teleport_history_panel)
+ {
+ teleport_history_panel->setPanelPlacesButtons(this);
+
+ mTabContainer->addTabPanel(
+ LLTabContainer::TabPanelParams().
+ panel(teleport_history_panel).
+ label(getString("teleport_history_tab_title")).
+ insert_at(LLTabContainer::END));
+ }
+
+ mTabContainer->selectFirstTab();
+
+ mActivePanel = dynamic_cast<LLPanelPlacesTab*>(mTabContainer->getCurrentPanel());
+
+ // Filter applied to show all items.
+ if (mActivePanel)
+ mActivePanel->onSearchEdit(mActivePanel->getFilterSubString());
+
+ // we don't need to monitor inventory changes anymore,
+ // so remove the observer
+ gInventory.removeObserver(mInventoryObserver);
+}
+
+void LLPanelPlaces::changedGlobalPos(const LLVector3d &global_pos)
+{
+ mPosGlobal = global_pos;
+ updateVerbs();
+}
+
+void LLPanelPlaces::updateVerbs()
+{
+ bool is_place_info_visible;
+
+ LLPanelPlaceInfo* panel = getCurrentInfoPanel();
+ if (panel)
+ {
+ is_place_info_visible = panel->getVisible();
+ }
+ else
+ {
+ is_place_info_visible = false;
+ }
+
+ bool is_agent_place_info_visible = mPlaceInfoType == AGENT_INFO_TYPE;
+ bool is_create_landmark_visible = mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE;
+ bool have_3d_pos = ! mPosGlobal.isExactlyZero();
+
+ mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn);
+ mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn);
+ mOverflowBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn);
+ mEditBtn->setVisible(mPlaceInfoType == LANDMARK_INFO_TYPE && !isLandmarkEditModeOn);
+ mSaveBtn->setVisible(isLandmarkEditModeOn);
+ mCancelBtn->setVisible(isLandmarkEditModeOn);
+ mCloseBtn->setVisible(is_create_landmark_visible && !isLandmarkEditModeOn);
+
+ mShowOnMapBtn->setEnabled(!is_create_landmark_visible && !isLandmarkEditModeOn && have_3d_pos);
+ mOverflowBtn->setEnabled(is_place_info_visible && !is_create_landmark_visible);
+
+ if (is_place_info_visible)
+ {
+ if (is_agent_place_info_visible)
+ {
+ // We don't need to teleport to the current location
+ // so check if the location is not within the current parcel.
+ mTeleportBtn->setEnabled(have_3d_pos &&
+ !LLViewerParcelMgr::getInstance()->inAgentParcel(mPosGlobal));
+ }
+ else if (mPlaceInfoType == LANDMARK_INFO_TYPE || mPlaceInfoType == REMOTE_PLACE_INFO_TYPE)
+ {
+ mTeleportBtn->setEnabled(have_3d_pos);
+ }
+ }
+ else
+ {
+ if (mActivePanel)
+ mActivePanel->updateVerbs();
+ }
+}
+
+LLPanelPlaceInfo* LLPanelPlaces::getCurrentInfoPanel()
+{
+ if (mPlaceInfoType == AGENT_INFO_TYPE ||
+ mPlaceInfoType == REMOTE_PLACE_INFO_TYPE ||
+ mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
+ {
+ return mPlaceProfile;
+ }
+ else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE ||
+ mPlaceInfoType == LANDMARK_INFO_TYPE)
+ {
+ return mLandmarkInfo;
+ }
+
+ return NULL;
+}
+
+static bool is_agent_in_selected_parcel(LLParcel* parcel)
+{
+ LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
+
+ LLViewerRegion* region = parcel_mgr->getSelectionRegion();
+ if (!region || !parcel)
+ return false;
+
+ return region == gAgent.getRegion() &&
+ parcel->getLocalID() == parcel_mgr->getAgentParcel()->getLocalID();
+}
+
+static void onSLURLBuilt(std::string& slurl)
+{
+ LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(slurl));
+
+ LLSD args;
+ args["SLURL"] = slurl;
+
+ LLNotificationsUtil::add("CopySLURL", args);
+}
diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h
new file mode 100644
index 0000000000..0eba7f3afc
--- /dev/null
+++ b/indra/newview/llpanelplaces.h
@@ -0,0 +1,143 @@
+/**
+ * @file llpanelplaces.h
+ * @brief Side Bar "Places" panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELPLACES_H
+#define LL_LLPANELPLACES_H
+
+#include "llpanel.h"
+
+class LLInventoryItem;
+class LLFilterEditor;
+class LLLandmark;
+
+class LLPanelLandmarkInfo;
+class LLPanelPlaceProfile;
+
+class LLPanelPickEdit;
+class LLPanelPlaceInfo;
+class LLPanelPlacesTab;
+class LLParcelSelection;
+class LLPlacesInventoryObserver;
+class LLPlacesParcelObserver;
+class LLRemoteParcelInfoObserver;
+class LLTabContainer;
+class LLToggleableMenu;
+
+typedef std::pair<LLUUID, std::string> folder_pair_t;
+
+class LLPanelPlaces : public LLPanel
+{
+public:
+ LLPanelPlaces();
+ virtual ~LLPanelPlaces();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ // Called on parcel selection change to update place information.
+ void changedParcelSelection();
+ // Called on agent inventory change to find out when inventory gets usable.
+ void changedInventory(U32 mask);
+ // Called when we receive the global 3D position of a parcel.
+ void changedGlobalPos(const LLVector3d &global_pos);
+
+ void setItem(LLInventoryItem* item);
+
+ LLInventoryItem* getItem() { return mItem; }
+
+ std::string getPlaceInfoType() { return mPlaceInfoType; }
+
+ /*virtual*/ S32 notifyParent(const LLSD& info);
+
+private:
+ void onLandmarkLoaded(LLLandmark* landmark);
+ void onFilterEdit(const std::string& search_string, bool force_filter);
+ void onTabSelected();
+
+ void onTeleportButtonClicked();
+ void onShowOnMapButtonClicked();
+ void onEditButtonClicked();
+ void onSaveButtonClicked();
+ void onCancelButtonClicked();
+ void onOverflowButtonClicked();
+ void onOverflowMenuItemClicked(const LLSD& param);
+ bool onOverflowMenuItemEnable(const LLSD& param);
+ void onCreateLandmarkButtonClicked(const LLUUID& folder_id);
+ void onBackButtonClicked();
+
+ void toggleMediaPanel();
+ void togglePickPanel(BOOL visible);
+ void togglePlaceInfoPanel(BOOL visible);
+
+ /*virtual*/ void handleVisibilityChange(BOOL new_visibility);
+
+ void updateVerbs();
+
+ LLPanelPlaceInfo* getCurrentInfoPanel();
+
+ LLFilterEditor* mFilterEditor;
+ LLPanelPlacesTab* mActivePanel;
+ LLTabContainer* mTabContainer;
+ LLPanelPlaceProfile* mPlaceProfile;
+ LLPanelLandmarkInfo* mLandmarkInfo;
+
+ LLPanelPickEdit* mPickPanel;
+ LLToggleableMenu* mPlaceMenu;
+ LLToggleableMenu* mLandmarkMenu;
+
+ LLButton* mTeleportBtn;
+ LLButton* mShowOnMapBtn;
+ LLButton* mEditBtn;
+ LLButton* mSaveBtn;
+ LLButton* mCancelBtn;
+ LLButton* mCloseBtn;
+ LLButton* mOverflowBtn;
+
+ LLPlacesInventoryObserver* mInventoryObserver;
+ LLPlacesParcelObserver* mParcelObserver;
+ LLRemoteParcelInfoObserver* mRemoteParcelObserver;
+
+ // Pointer to a landmark item or to a linked landmark
+ LLPointer<LLInventoryItem> mItem;
+
+ // Absolute position of the location for teleport, may not
+ // be available (hence zero)
+ LLVector3d mPosGlobal;
+
+ // Information type currently shown in Place Information panel
+ std::string mPlaceInfoType;
+
+ bool isLandmarkEditModeOn;
+
+ LLSafeHandle<LLParcelSelection> mParcel;
+};
+
+#endif //LL_LLPANELPLACES_H
diff --git a/indra/newview/llpanelplacestab.cpp b/indra/newview/llpanelplacestab.cpp
new file mode 100644
index 0000000000..9806b8c64d
--- /dev/null
+++ b/indra/newview/llpanelplacestab.cpp
@@ -0,0 +1,89 @@
+/**
+ * @file llpanelplacestab.cpp
+ * @brief Tabs interface for Side Bar "Places" panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelplacestab.h"
+
+#include "llbutton.h"
+#include "llnotificationsutil.h"
+
+#include "llwindow.h"
+
+#include "llpanelplaces.h"
+#include "llslurl.h"
+#include "llworldmap.h"
+
+std::string LLPanelPlacesTab::sFilterSubString = LLStringUtil::null;
+
+bool LLPanelPlacesTab::isTabVisible()
+{
+ LLUICtrl* parent = getParentUICtrl();
+ if (!parent) return false;
+ if (!parent->getVisible()) return false;
+ return true;
+}
+
+void LLPanelPlacesTab::setPanelPlacesButtons(LLPanelPlaces* panel)
+{
+ mTeleportBtn = panel->getChild<LLButton>("teleport_btn");
+ mShowOnMapBtn = panel->getChild<LLButton>("map_btn");
+}
+
+void LLPanelPlacesTab::onRegionResponse(const LLVector3d& landmark_global_pos,
+ U64 region_handle,
+ const std::string& url,
+ const LLUUID& snapshot_id,
+ bool teleport)
+{
+ std::string sim_name;
+ bool gotSimName = LLWorldMap::getInstance()->simNameFromPosGlobal( landmark_global_pos, sim_name );
+
+ std::string sl_url;
+ if ( gotSimName )
+ {
+ F32 region_x = (F32)fmod( landmark_global_pos.mdV[VX], (F64)REGION_WIDTH_METERS );
+ F32 region_y = (F32)fmod( landmark_global_pos.mdV[VY], (F64)REGION_WIDTH_METERS );
+
+ sl_url = LLSLURL::buildSLURL(sim_name, llround(region_x), llround(region_y), llround((F32)landmark_global_pos.mdV[VZ]));
+ }
+ else
+ {
+ sl_url = "";
+ }
+
+ LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(sl_url));
+
+ LLSD args;
+ args["SLURL"] = sl_url;
+
+ LLNotificationsUtil::add("CopySLURL", args);
+}
diff --git a/indra/newview/llpanelplacestab.h b/indra/newview/llpanelplacestab.h
new file mode 100644
index 0000000000..ce77a42259
--- /dev/null
+++ b/indra/newview/llpanelplacestab.h
@@ -0,0 +1,70 @@
+/**
+ * @file llpanelplacestab.h
+ * @brief Tabs interface for Side Bar "Places" panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELPLACESTAB_H
+#define LL_LLPANELPLACESTAB_H
+
+#include "llpanel.h"
+
+class LLPanelPlaces;
+
+class LLPanelPlacesTab : public LLPanel
+{
+public:
+ LLPanelPlacesTab() : LLPanel() {}
+ virtual ~LLPanelPlacesTab() {}
+
+ virtual void onSearchEdit(const std::string& string) = 0;
+ virtual void updateVerbs() = 0; // Updates buttons at the bottom of Places panel
+ virtual void onShowOnMap() = 0;
+ virtual void onTeleport() = 0;
+
+ bool isTabVisible(); // Check if parent TabContainer is visible.
+
+ void setPanelPlacesButtons(LLPanelPlaces* panel);
+ void onRegionResponse(const LLVector3d& landmark_global_pos,
+ U64 region_handle,
+ const std::string& url,
+ const LLUUID& snapshot_id,
+ bool teleport);
+
+ const std::string& getFilterSubString() { return sFilterSubString; }
+ void setFilterSubString(const std::string& string) { sFilterSubString = string; }
+
+protected:
+ LLButton* mTeleportBtn;
+ LLButton* mShowOnMapBtn;
+
+ // Search string for filtering landmarks and teleport history locations
+ static std::string sFilterSubString;
+};
+
+#endif //LL_LLPANELPLACESTAB_H
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
new file mode 100644
index 0000000000..2dc3a62637
--- /dev/null
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -0,0 +1,1286 @@
+/**
+ * @file llpanelprimmediacontrols.cpp
+ * @brief media controls popup panel
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+//LLPanelPrimMediaControls
+#include "llagent.h"
+#include "llparcel.h"
+#include "llpanel.h"
+#include "llselectmgr.h"
+#include "llmediaentry.h"
+#include "llrender.h"
+#include "lldrawable.h"
+#include "llviewerwindow.h"
+#include "lluictrlfactory.h"
+#include "llbutton.h"
+#include "llface.h"
+#include "llcombobox.h"
+#include "lllayoutstack.h"
+#include "llslider.h"
+#include "llhudview.h"
+#include "lliconctrl.h"
+#include "lltoolpie.h"
+#include "llviewercamera.h"
+#include "llviewerobjectlist.h"
+#include "llpanelprimmediacontrols.h"
+#include "llpluginclassmedia.h"
+#include "llprogressbar.h"
+#include "llsliderctrl.h"
+#include "llstring.h"
+#include "llviewercontrol.h"
+#include "llviewerdisplay.h"
+#include "llviewerparcelmgr.h"
+#include "llviewermedia.h"
+#include "llviewermediafocus.h"
+#include "llvovolume.h"
+#include "llweb.h"
+#include "llwindow.h"
+
+#include "llfloatertools.h" // to enable hide if build tools are up
+
+// Functions pulled from pipeline.cpp
+glh::matrix4f glh_get_current_modelview();
+glh::matrix4f glh_get_current_projection();
+// Functions pulled from llviewerdisplay.cpp
+bool get_hud_matrices(glh::matrix4f &proj, glh::matrix4f &model);
+
+// Warning: make sure these two match!
+const LLPanelPrimMediaControls::EZoomLevel LLPanelPrimMediaControls::kZoomLevels[] = { ZOOM_NONE, ZOOM_MEDIUM };
+const int LLPanelPrimMediaControls::kNumZoomLevels = 2;
+
+//
+// LLPanelPrimMediaControls
+//
+
+LLPanelPrimMediaControls::LLPanelPrimMediaControls() :
+ mAlpha(1.f),
+ mCurrentURL(""),
+ mPreviousURL(""),
+ mPauseFadeout(false),
+ mUpdateSlider(true),
+ mClearFaceOnFade(false),
+ mCurrentRate(0.0),
+ mMovieDuration(0.0),
+ mTargetObjectID(LLUUID::null),
+ mTargetObjectFace(0),
+ mTargetImplID(LLUUID::null),
+ mTargetObjectNormal(LLVector3::zero),
+ mZoomObjectID(LLUUID::null),
+ mZoomObjectFace(0),
+ mVolumeSliderVisible(0)
+{
+ mCommitCallbackRegistrar.add("MediaCtrl.Close", boost::bind(&LLPanelPrimMediaControls::onClickClose, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.Back", boost::bind(&LLPanelPrimMediaControls::onClickBack, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.Forward", boost::bind(&LLPanelPrimMediaControls::onClickForward, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.Home", boost::bind(&LLPanelPrimMediaControls::onClickHome, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.Stop", boost::bind(&LLPanelPrimMediaControls::onClickStop, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.MediaStop", boost::bind(&LLPanelPrimMediaControls::onClickMediaStop, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.Reload", boost::bind(&LLPanelPrimMediaControls::onClickReload, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.Play", boost::bind(&LLPanelPrimMediaControls::onClickPlay, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.Pause", boost::bind(&LLPanelPrimMediaControls::onClickPause, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.Open", boost::bind(&LLPanelPrimMediaControls::onClickOpen, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.Zoom", boost::bind(&LLPanelPrimMediaControls::onClickZoom, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.CommitURL", boost::bind(&LLPanelPrimMediaControls::onCommitURL, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.JumpProgress", boost::bind(&LLPanelPrimMediaControls::onCommitSlider, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeUp", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeUp, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeDown", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeDown, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.Volume", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeSlider, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.ToggleMute", boost::bind(&LLPanelPrimMediaControls::onToggleMute, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.ShowVolumeSlider", boost::bind(&LLPanelPrimMediaControls::showVolumeSlider, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.HideVolumeSlider", boost::bind(&LLPanelPrimMediaControls::hideVolumeSlider, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.SkipBack", boost::bind(&LLPanelPrimMediaControls::onClickSkipBack, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.SkipForward", boost::bind(&LLPanelPrimMediaControls::onClickSkipForward, this));
+
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_prim_media_controls.xml");
+ mInactivityTimer.reset();
+ mFadeTimer.stop();
+ mCurrentZoom = ZOOM_NONE;
+ mScrollState = SCROLL_NONE;
+
+ mPanelHandle.bind(this);
+
+ mInactiveTimeout = gSavedSettings.getF32("MediaControlTimeout");
+ mControlFadeTime = gSavedSettings.getF32("MediaControlFadeTime");
+}
+
+LLPanelPrimMediaControls::~LLPanelPrimMediaControls()
+{
+}
+
+BOOL LLPanelPrimMediaControls::postBuild()
+{
+ mMediaRegion = getChild<LLView>("media_region");
+ mBackCtrl = getChild<LLUICtrl>("back");
+ mFwdCtrl = getChild<LLUICtrl>("fwd");
+ mReloadCtrl = getChild<LLUICtrl>("reload");
+ mPlayCtrl = getChild<LLUICtrl>("play");
+ mPauseCtrl = getChild<LLUICtrl>("pause");
+ mStopCtrl = getChild<LLUICtrl>("stop");
+ mMediaStopCtrl = getChild<LLUICtrl>("media_stop");
+ mHomeCtrl = getChild<LLUICtrl>("home");
+ mUnzoomCtrl = getChild<LLUICtrl>("close"); // This is actually "unzoom"
+ mOpenCtrl = getChild<LLUICtrl>("new_window");
+ mZoomCtrl = getChild<LLUICtrl>("zoom_frame");
+ mMediaProgressPanel = getChild<LLPanel>("media_progress_indicator");
+ mMediaProgressBar = getChild<LLProgressBar>("media_progress_bar");
+ mMediaAddressCtrl = getChild<LLUICtrl>("media_address");
+ mMediaAddress = getChild<LLUICtrl>("media_address_url");
+ mMediaPlaySliderPanel = getChild<LLUICtrl>("media_play_position");
+ mMediaPlaySliderCtrl = getChild<LLUICtrl>("media_play_slider");
+ mSkipFwdCtrl = getChild<LLUICtrl>("skip_forward");
+ mSkipBackCtrl = getChild<LLUICtrl>("skip_back");
+ mVolumeCtrl = getChild<LLUICtrl>("media_volume");
+ mMuteBtn = getChild<LLButton>("media_mute_button");
+ mVolumeSliderCtrl = getChild<LLSliderCtrl>("volume_slider");
+ mWhitelistIcon = getChild<LLIconCtrl>("media_whitelist_flag");
+ mSecureLockIcon = getChild<LLIconCtrl>("media_secure_lock_flag");
+ mMediaControlsStack = getChild<LLLayoutStack>("media_controls");
+ mLeftBookend = getChild<LLUICtrl>("left_bookend");
+ mRightBookend = getChild<LLUICtrl>("right_bookend");
+ mBackgroundImage = LLUI::getUIImage(getString("control_background_image_name"));
+ mVolumeSliderBackgroundImage = LLUI::getUIImage(getString("control_background_image_name"));
+ LLStringUtil::convertToF32(getString("skip_step"), mSkipStep);
+ LLStringUtil::convertToS32(getString("min_width"), mMinWidth);
+ LLStringUtil::convertToS32(getString("min_height"), mMinHeight);
+ LLStringUtil::convertToF32(getString("zoom_near_padding"), mZoomNearPadding);
+ LLStringUtil::convertToF32(getString("zoom_medium_padding"), mZoomMediumPadding);
+ LLStringUtil::convertToF32(getString("zoom_far_padding"), mZoomFarPadding);
+ LLStringUtil::convertToS32(getString("top_world_view_avoid_zone"), mTopWorldViewAvoidZone);
+
+ // These are currently removed...but getChild creates a "dummy" widget.
+ // This class handles them missing.
+ mMediaPanelScroll = findChild<LLUICtrl>("media_panel_scroll");
+ mScrollUpCtrl = findChild<LLButton>("scrollup");
+ mScrollLeftCtrl = findChild<LLButton>("scrollleft");
+ mScrollRightCtrl = findChild<LLButton>("scrollright");
+ mScrollDownCtrl = findChild<LLButton>("scrolldown");
+
+ if (mScrollUpCtrl)
+ {
+ mScrollUpCtrl->setClickedCallback(onScrollUp, this);
+ mScrollUpCtrl->setHeldDownCallback(onScrollUpHeld, this);
+ mScrollUpCtrl->setMouseUpCallback(onScrollStop, this);
+ }
+ if (mScrollLeftCtrl)
+ {
+ mScrollLeftCtrl->setClickedCallback(onScrollLeft, this);
+ mScrollLeftCtrl->setHeldDownCallback(onScrollLeftHeld, this);
+ mScrollLeftCtrl->setMouseUpCallback(onScrollStop, this);
+ }
+ if (mScrollRightCtrl)
+ {
+ mScrollRightCtrl->setClickedCallback(onScrollRight, this);
+ mScrollRightCtrl->setHeldDownCallback(onScrollRightHeld, this);
+ mScrollRightCtrl->setMouseUpCallback(onScrollStop, this);
+ }
+ if (mScrollDownCtrl)
+ {
+ mScrollDownCtrl->setClickedCallback(onScrollDown, this);
+ mScrollDownCtrl->setHeldDownCallback(onScrollDownHeld, this);
+ mScrollDownCtrl->setMouseUpCallback(onScrollStop, this);
+ }
+
+ mMediaAddress->setFocusReceivedCallback(boost::bind(&LLPanelPrimMediaControls::onInputURL, _1, this ));
+
+ mCurrentZoom = ZOOM_NONE;
+ // clicks on buttons do not remove keyboard focus from media
+ setIsChrome(TRUE);
+ return TRUE;
+}
+
+void LLPanelPrimMediaControls::setMediaFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal)
+{
+ if (media_impl.notNull() && objectp.notNull())
+ {
+ LLUUID prev_id = mTargetImplID;
+ mTargetImplID = media_impl->getMediaTextureID();
+ mTargetObjectID = objectp->getID();
+ mTargetObjectFace = face;
+ mTargetObjectNormal = pick_normal;
+ mClearFaceOnFade = false;
+
+ if (prev_id != mTargetImplID)
+ mVolumeSliderCtrl->setValue(media_impl->getVolume());
+ }
+ else
+ {
+ // This happens on a timer now.
+// mTargetImplID = LLUUID::null;
+// mTargetObjectID = LLUUID::null;
+// mTargetObjectFace = 0;
+ mClearFaceOnFade = true;
+ }
+
+ updateShape();
+}
+
+void LLPanelPrimMediaControls::focusOnTarget()
+{
+ // Sets the media focus to the current target of the LLPanelPrimMediaControls.
+ // This is how we transition from hover to focus when the user clicks on a control.
+ LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+ if(media_impl)
+ {
+ if(!media_impl->hasFocus())
+ {
+ // The current target doesn't have media focus -- focus on it.
+ LLViewerObject* objectp = getTargetObject();
+ LLViewerMediaFocus::getInstance()->setFocusFace(objectp, mTargetObjectFace, media_impl, mTargetObjectNormal);
+ }
+ }
+}
+
+LLViewerMediaImpl* LLPanelPrimMediaControls::getTargetMediaImpl()
+{
+ return LLViewerMedia::getMediaImplFromTextureID(mTargetImplID);
+}
+
+LLViewerObject* LLPanelPrimMediaControls::getTargetObject()
+{
+ return gObjectList.findObject(mTargetObjectID);
+}
+
+LLPluginClassMedia* LLPanelPrimMediaControls::getTargetMediaPlugin()
+{
+ LLViewerMediaImpl* impl = getTargetMediaImpl();
+ if(impl && impl->hasMedia())
+ {
+ return impl->getMediaPlugin();
+ }
+
+ return NULL;
+}
+
+void LLPanelPrimMediaControls::updateShape()
+{
+ LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+ LLViewerObject* objectp = getTargetObject();
+
+ if(!media_impl || gFloaterTools->getVisible())
+ {
+ setVisible(FALSE);
+ return;
+ }
+
+ LLPluginClassMedia* media_plugin = NULL;
+ if(media_impl->hasMedia())
+ {
+ media_plugin = media_impl->getMediaPlugin();
+ }
+
+ LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+
+ bool can_navigate = parcel->getMediaAllowNavigate();
+ bool enabled = false;
+ bool is_zoomed = (mCurrentZoom != ZOOM_NONE) && (mTargetObjectID == mZoomObjectID) && (mTargetObjectFace == mZoomObjectFace);
+ // There is no such thing as "has_focus" being different from normal controls set
+ // anymore (as of user feedback from bri 10/09). So we cheat here and force 'has_focus'
+ // to 'true' (or, actually, we use a setting)
+ bool has_focus = (gSavedSettings.getBOOL("PrimMediaControlsUseHoverControlSet")) ? media_impl->hasFocus() : true;
+ setVisible(enabled);
+
+ if (objectp)
+ {
+ bool mini_controls = false;
+ LLMediaEntry *media_data = objectp->getTE(mTargetObjectFace)->getMediaData();
+ if (media_data && NULL != dynamic_cast<LLVOVolume*>(objectp))
+ {
+ // Don't show the media controls if we do not have permissions
+ enabled = dynamic_cast<LLVOVolume*>(objectp)->hasMediaPermission(media_data, LLVOVolume::MEDIA_PERM_CONTROL);
+ mini_controls = (LLMediaEntry::MINI == media_data->getControls());
+ }
+ const bool is_hud = objectp->isHUDAttachment();
+
+ //
+ // Set the state of the buttons
+ //
+
+ // XXX RSP: TODO: FIXME: clean this up so that it is clearer what mode we are in,
+ // and that only the proper controls get made visible/enabled according to that mode.
+ mBackCtrl->setVisible(has_focus);
+ mFwdCtrl->setVisible(has_focus);
+ mReloadCtrl->setVisible(has_focus);
+ mStopCtrl->setVisible(false);
+ mHomeCtrl->setVisible(has_focus);
+ mZoomCtrl->setVisible(!is_zoomed);
+ mUnzoomCtrl->setVisible(is_zoomed);
+ mOpenCtrl->setVisible(true);
+ mMediaAddressCtrl->setVisible(has_focus && !mini_controls);
+ mMediaPlaySliderPanel->setVisible(has_focus && !mini_controls);
+ mVolumeCtrl->setVisible(false);
+
+ mWhitelistIcon->setVisible(!mini_controls && (media_data)?media_data->getWhiteListEnable():false);
+ // Disable zoom if HUD
+ mZoomCtrl->setEnabled(!is_hud);
+ mUnzoomCtrl->setEnabled(!is_hud);
+ mSecureLockIcon->setVisible(false);
+ mCurrentURL = media_impl->getCurrentMediaURL();
+
+ mBackCtrl->setEnabled((media_impl != NULL) && media_impl->canNavigateBack() && can_navigate);
+ mFwdCtrl->setEnabled((media_impl != NULL) && media_impl->canNavigateForward() && can_navigate);
+ mStopCtrl->setEnabled(has_focus && can_navigate);
+ mHomeCtrl->setEnabled(has_focus && can_navigate);
+ LLPluginClassMediaOwner::EMediaStatus result = ((media_impl != NULL) && media_impl->hasMedia()) ? media_plugin->getStatus() : LLPluginClassMediaOwner::MEDIA_NONE;
+
+ if(media_plugin && media_plugin->pluginSupportsMediaTime())
+ {
+ mReloadCtrl->setEnabled(false);
+ mReloadCtrl->setVisible(false);
+ mMediaStopCtrl->setVisible(has_focus);
+ mHomeCtrl->setVisible(has_focus);
+ mBackCtrl->setVisible(false);
+ mFwdCtrl->setVisible(false);
+ mMediaAddressCtrl->setVisible(false);
+ mMediaAddressCtrl->setEnabled(false);
+ mMediaPlaySliderPanel->setVisible(has_focus && !mini_controls);
+ mMediaPlaySliderPanel->setEnabled(has_focus && !mini_controls);
+ mSkipFwdCtrl->setVisible(has_focus && !mini_controls);
+ mSkipFwdCtrl->setEnabled(has_focus && !mini_controls);
+ mSkipBackCtrl->setVisible(has_focus && !mini_controls);
+ mSkipBackCtrl->setEnabled(has_focus && !mini_controls);
+
+ mVolumeCtrl->setVisible(has_focus);
+ mVolumeCtrl->setEnabled(has_focus);
+ mVolumeSliderCtrl->setEnabled(has_focus && shouldVolumeSliderBeVisible());
+ mVolumeSliderCtrl->setVisible(has_focus && shouldVolumeSliderBeVisible());
+
+ mWhitelistIcon->setVisible(false);
+ mSecureLockIcon->setVisible(false);
+ if (mMediaPanelScroll)
+ {
+ mMediaPanelScroll->setVisible(false);
+ mScrollUpCtrl->setVisible(false);
+ mScrollDownCtrl->setVisible(false);
+ mScrollRightCtrl->setVisible(false);
+ mScrollDownCtrl->setVisible(false);
+ }
+
+ F32 volume = media_impl->getVolume();
+ // movie's url changed
+ if(mCurrentURL!=mPreviousURL)
+ {
+ mMovieDuration = media_plugin->getDuration();
+ mPreviousURL = mCurrentURL;
+ }
+
+ if(mMovieDuration == 0)
+ {
+ mMovieDuration = media_plugin->getDuration();
+ mMediaPlaySliderCtrl->setValue(0);
+ mMediaPlaySliderCtrl->setEnabled(false);
+ }
+ // TODO: What if it's not fully loaded
+
+ if(mUpdateSlider && mMovieDuration!= 0)
+ {
+ F64 current_time = media_plugin->getCurrentTime();
+ F32 percent = current_time / mMovieDuration;
+ mMediaPlaySliderCtrl->setValue(percent);
+ mMediaPlaySliderCtrl->setEnabled(true);
+ }
+
+ // video vloume
+ if(volume <= 0.0)
+ {
+ mMuteBtn->setToggleState(true);
+ }
+ else if (volume >= 1.0)
+ {
+ mMuteBtn->setToggleState(false);
+ }
+ else
+ {
+ mMuteBtn->setToggleState(false);
+ }
+
+ switch(result)
+ {
+ case LLPluginClassMediaOwner::MEDIA_PLAYING:
+ mPlayCtrl->setEnabled(FALSE);
+ mPlayCtrl->setVisible(FALSE);
+ mPauseCtrl->setEnabled(TRUE);
+ mPauseCtrl->setVisible(has_focus);
+
+ break;
+ case LLPluginClassMediaOwner::MEDIA_PAUSED:
+ default:
+ mPauseCtrl->setEnabled(FALSE);
+ mPauseCtrl->setVisible(FALSE);
+ mPlayCtrl->setEnabled(TRUE);
+ mPlayCtrl->setVisible(has_focus);
+ break;
+ }
+ }
+ else // web based
+ {
+ if(media_plugin)
+ {
+ mCurrentURL = media_plugin->getLocation();
+ }
+ else
+ {
+ mCurrentURL.clear();
+ }
+
+ mPlayCtrl->setVisible(FALSE);
+ mPauseCtrl->setVisible(FALSE);
+ mMediaStopCtrl->setVisible(FALSE);
+ mMediaAddressCtrl->setVisible(has_focus && !mini_controls);
+ mMediaAddressCtrl->setEnabled(has_focus && !mini_controls);
+ mMediaPlaySliderPanel->setVisible(FALSE);
+ mMediaPlaySliderPanel->setEnabled(FALSE);
+ mSkipFwdCtrl->setVisible(FALSE);
+ mSkipFwdCtrl->setEnabled(FALSE);
+ mSkipBackCtrl->setVisible(FALSE);
+ mSkipBackCtrl->setEnabled(FALSE);
+
+ mVolumeCtrl->setVisible(FALSE);
+ mVolumeSliderCtrl->setVisible(FALSE);
+ mVolumeCtrl->setEnabled(FALSE);
+ mVolumeSliderCtrl->setEnabled(FALSE);
+
+ if (mMediaPanelScroll)
+ {
+ mMediaPanelScroll->setVisible(has_focus);
+ mScrollUpCtrl->setVisible(has_focus);
+ mScrollDownCtrl->setVisible(has_focus);
+ mScrollRightCtrl->setVisible(has_focus);
+ mScrollDownCtrl->setVisible(has_focus);
+ }
+ // TODO: get the secure lock bool from media plug in
+ std::string prefix = std::string("https://");
+ std::string test_prefix = mCurrentURL.substr(0, prefix.length());
+ LLStringUtil::toLower(test_prefix);
+ if(test_prefix == prefix)
+ {
+ mSecureLockIcon->setVisible(has_focus);
+ }
+
+ if(mCurrentURL!=mPreviousURL)
+ {
+ setCurrentURL();
+ mPreviousURL = mCurrentURL;
+ }
+
+ if(result == LLPluginClassMediaOwner::MEDIA_LOADING)
+ {
+ mReloadCtrl->setEnabled(FALSE);
+ mReloadCtrl->setVisible(FALSE);
+ mStopCtrl->setEnabled(TRUE);
+ mStopCtrl->setVisible(has_focus);
+ }
+ else
+ {
+ mReloadCtrl->setEnabled(TRUE);
+ mReloadCtrl->setVisible(has_focus);
+ mStopCtrl->setEnabled(FALSE);
+ mStopCtrl->setVisible(FALSE);
+ }
+ }
+
+
+ if(media_plugin)
+ {
+ //
+ // Handle progress bar
+ //
+ if(LLPluginClassMediaOwner::MEDIA_LOADING == media_plugin->getStatus())
+ {
+ mMediaProgressPanel->setVisible(true);
+ mMediaProgressBar->setPercent(media_plugin->getProgressPercent());
+ }
+ else
+ {
+ mMediaProgressPanel->setVisible(false);
+ }
+ }
+
+ if(media_impl)
+ {
+ //
+ // Handle Scrolling
+ //
+ switch (mScrollState)
+ {
+ case SCROLL_UP:
+ media_impl->scrollWheel(0, -1, MASK_NONE);
+ break;
+ case SCROLL_DOWN:
+ media_impl->scrollWheel(0, 1, MASK_NONE);
+ break;
+ case SCROLL_LEFT:
+ media_impl->scrollWheel(1, 0, MASK_NONE);
+ // media_impl->handleKeyHere(KEY_LEFT, MASK_NONE);
+ break;
+ case SCROLL_RIGHT:
+ media_impl->scrollWheel(-1, 0, MASK_NONE);
+ // media_impl->handleKeyHere(KEY_RIGHT, MASK_NONE);
+ break;
+ case SCROLL_NONE:
+ default:
+ break;
+ }
+ }
+
+ setVisible(enabled);
+
+ //
+ // Calculate position and shape of the controls
+ //
+ std::vector<LLVector3>::iterator vert_it;
+ std::vector<LLVector3>::iterator vert_end;
+ std::vector<LLVector3> vect_face;
+
+ LLVolume* volume = objectp->getVolume();
+
+ if (volume)
+ {
+ const LLVolumeFace& vf = volume->getVolumeFace(mTargetObjectFace);
+
+ const LLVector3* ext = vf.mExtents;
+
+ LLVector3 center = (ext[0]+ext[1])*0.5f;
+ LLVector3 size = (ext[1]-ext[0])*0.5f;
+ LLVector3 vert[] =
+ {
+ center + size.scaledVec(LLVector3(1,1,1)),
+ center + size.scaledVec(LLVector3(-1,1,1)),
+ center + size.scaledVec(LLVector3(1,-1,1)),
+ center + size.scaledVec(LLVector3(-1,-1,1)),
+ center + size.scaledVec(LLVector3(1,1,-1)),
+ center + size.scaledVec(LLVector3(-1,1,-1)),
+ center + size.scaledVec(LLVector3(1,-1,-1)),
+ center + size.scaledVec(LLVector3(-1,-1,-1)),
+ };
+
+ LLVOVolume* vo = (LLVOVolume*) objectp;
+
+ for (U32 i = 0; i < 8; i++)
+ {
+ vect_face.push_back(vo->volumePositionToAgent(vert[i]));
+ }
+ }
+ vert_it = vect_face.begin();
+ vert_end = vect_face.end();
+
+ glh::matrix4f mat;
+ if (!is_hud)
+ {
+ mat = glh_get_current_projection() * glh_get_current_modelview();
+ }
+ else {
+ glh::matrix4f proj, modelview;
+ if (get_hud_matrices(proj, modelview))
+ mat = proj * modelview;
+ }
+ LLVector3 min = LLVector3(1,1,1);
+ LLVector3 max = LLVector3(-1,-1,-1);
+ for(; vert_it != vert_end; ++vert_it)
+ {
+ // project silhouette vertices into screen space
+ glh::vec3f screen_vert = glh::vec3f(vert_it->mV);
+ mat.mult_matrix_vec(screen_vert);
+
+ // add to screenspace bounding box
+ update_min_max(min, max, LLVector3(screen_vert.v));
+ }
+
+ // convert screenspace bbox to pixels (in screen coords)
+ LLRect window_rect = gViewerWindow->getWorldViewRectScaled();
+ LLCoordGL screen_min;
+ screen_min.mX = llround((F32)window_rect.getWidth() * (min.mV[VX] + 1.f) * 0.5f);
+ screen_min.mY = llround((F32)window_rect.getHeight() * (min.mV[VY] + 1.f) * 0.5f);
+
+ LLCoordGL screen_max;
+ screen_max.mX = llround((F32)window_rect.getWidth() * (max.mV[VX] + 1.f) * 0.5f);
+ screen_max.mY = llround((F32)window_rect.getHeight() * (max.mV[VY] + 1.f) * 0.5f);
+
+ // grow panel so that screenspace bounding box fits inside "media_region" element of panel
+ LLRect media_panel_rect;
+ // Get the height of the controls (less the volume slider)
+ S32 controls_height = mMediaControlsStack->getRect().getHeight() - mVolumeSliderCtrl->getRect().getHeight();
+ getParent()->screenRectToLocal(LLRect(screen_min.mX, screen_max.mY, screen_max.mX, screen_min.mY), &media_panel_rect);
+ media_panel_rect.mTop += controls_height;
+
+ // keep all parts of panel on-screen
+ // Area of the top of the world view to avoid putting the controls
+ window_rect.mTop -= mTopWorldViewAvoidZone;
+ // Don't include "spacing" bookends on left & right of the media controls
+ window_rect.mLeft -= mLeftBookend->getRect().getWidth();
+ window_rect.mRight += mRightBookend->getRect().getWidth();
+ // Don't include the volume slider
+ window_rect.mBottom -= mVolumeSliderCtrl->getRect().getHeight();
+ media_panel_rect.intersectWith(window_rect);
+
+ // clamp to minimum size, keeping rect inside window
+ S32 centerX = media_panel_rect.getCenterX();
+ S32 centerY = media_panel_rect.getCenterY();
+ // Shrink screen rect by min width and height, to ensure containment
+ window_rect.stretch(-mMinWidth/2, -mMinHeight/2);
+ window_rect.clampPointToRect(centerX, centerY);
+ media_panel_rect.setCenterAndSize(centerX, centerY,
+ llmax(mMinWidth, media_panel_rect.getWidth()),
+ llmax(mMinHeight, media_panel_rect.getHeight()));
+
+ // Finally set the size of the panel
+ setShape(media_panel_rect, true);
+
+ // Test mouse position to see if the cursor is stationary
+ LLCoordWindow cursor_pos_window;
+ getWindow()->getCursorPosition(&cursor_pos_window);
+
+ // If last pos is not equal to current pos, the mouse has moved
+ // We need to reset the timer, and make sure the panel is visible
+ if(cursor_pos_window.mX != mLastCursorPos.mX ||
+ cursor_pos_window.mY != mLastCursorPos.mY ||
+ mScrollState != SCROLL_NONE)
+ {
+ mInactivityTimer.start();
+ mLastCursorPos = cursor_pos_window;
+ }
+
+ if(isMouseOver() || hasFocus())
+ {
+ // Never fade the controls if the mouse is over them or they have keyboard focus.
+ mFadeTimer.stop();
+ }
+ else if(!mClearFaceOnFade && (mInactivityTimer.getElapsedTimeF32() < mInactiveTimeout))
+ {
+ // Mouse is over the object, but has not been stationary for long enough to fade the UI
+ mFadeTimer.stop();
+ }
+ else if(! mFadeTimer.getStarted() )
+ {
+ // we need to start fading the UI (and we have not already started)
+ mFadeTimer.reset();
+ mFadeTimer.start();
+ }
+ else
+ {
+ // I don't think this is correct anymore. This is done in draw() after the fade has completed.
+ // setVisible(FALSE);
+ }
+ }
+}
+
+/*virtual*/
+void LLPanelPrimMediaControls::draw()
+{
+ F32 alpha = getDrawContext().mAlpha;
+ if(mFadeTimer.getStarted())
+ {
+ F32 time = mFadeTimer.getElapsedTimeF32();
+ alpha *= llmax(lerp(1.0, 0.0, time / mControlFadeTime), 0.0f);
+
+ if(time >= mControlFadeTime)
+ {
+ if(mClearFaceOnFade)
+ {
+ // Hiding this object makes scroll events go missing after it fades out
+ // (see DEV-41755 for a full description of the train wreck).
+ // Only hide the controls when we're untargeting.
+ setVisible(FALSE);
+
+ mClearFaceOnFade = false;
+ mVolumeSliderVisible = 0;
+ mTargetImplID = LLUUID::null;
+ mTargetObjectID = LLUUID::null;
+ mTargetObjectFace = 0;
+ }
+ }
+ }
+
+ // Build rect for icon area in coord system of this panel
+ // Assumes layout_stack is a direct child of this panel
+ mMediaControlsStack->updateLayout();
+
+ // adjust for layout stack spacing
+ S32 space = mMediaControlsStack->getPanelSpacing() + 1;
+ LLRect controls_bg_area = mMediaControlsStack->getRect();
+
+ controls_bg_area.mTop += space;
+
+ // adjust to ignore space from volume slider
+ controls_bg_area.mBottom += mVolumeSliderCtrl->getRect().getHeight();
+
+ // adjust to ignore space from left bookend padding
+ controls_bg_area.mLeft += mLeftBookend->getRect().getWidth() - space;
+
+ // ignore space from right bookend padding
+ controls_bg_area.mRight -= mRightBookend->getRect().getWidth() - space;
+
+ // draw control background UI image
+ mBackgroundImage->draw( controls_bg_area, UI_VERTEX_COLOR % alpha);
+
+ // draw volume slider background UI image
+ if (mVolumeSliderCtrl->getVisible())
+ {
+ LLRect volume_slider_rect;
+ screenRectToLocal(mVolumeSliderCtrl->calcScreenRect(), &volume_slider_rect);
+ mVolumeSliderBackgroundImage->draw(volume_slider_rect, UI_VERTEX_COLOR % alpha);
+ }
+
+ {
+ LLViewDrawContext context(alpha);
+ LLPanel::draw();
+ }
+}
+
+BOOL LLPanelPrimMediaControls::handleScrollWheel(S32 x, S32 y, S32 clicks)
+{
+ mInactivityTimer.start();
+ return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks);
+}
+
+BOOL LLPanelPrimMediaControls::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ mInactivityTimer.start();
+ return LLPanel::handleMouseDown(x, y, mask);
+}
+
+BOOL LLPanelPrimMediaControls::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+ mInactivityTimer.start();
+ return LLPanel::handleMouseUp(x, y, mask);
+}
+
+BOOL LLPanelPrimMediaControls::handleKeyHere( KEY key, MASK mask )
+{
+ mInactivityTimer.start();
+ return LLPanel::handleKeyHere(key, mask);
+}
+
+bool LLPanelPrimMediaControls::isMouseOver()
+{
+ bool result = false;
+
+ if( getVisible() )
+ {
+ LLCoordWindow cursor_pos_window;
+ LLCoordScreen cursor_pos_screen;
+ LLCoordGL cursor_pos_gl;
+ S32 x, y;
+ getWindow()->getCursorPosition(&cursor_pos_window);
+ getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl);
+
+ if(mMediaControlsStack->getVisible())
+ {
+ mMediaControlsStack->screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &x, &y);
+
+ LLView *hit_child = mMediaControlsStack->childFromPoint(x, y);
+ if(hit_child && hit_child->getVisible())
+ {
+ // This was useful for debugging both coordinate translation and view hieararchy problems...
+ // llinfos << "mouse coords: " << x << ", " << y << " hit child " << hit_child->getName() << llendl;
+
+ // This will be a direct child of the LLLayoutStack, which should be a layout_panel.
+ // These may not shown/hidden by the logic in updateShape(), so we need to do another hit test on the children of the layout panel,
+ // which are the actual controls.
+ hit_child->screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &x, &y);
+
+ LLView *hit_child_2 = hit_child->childFromPoint(x, y);
+ if(hit_child_2 && hit_child_2->getVisible())
+ {
+ // This was useful for debugging both coordinate translation and view hieararchy problems...
+ // llinfos << " mouse coords: " << x << ", " << y << " hit child 2 " << hit_child_2->getName() << llendl;
+ result = true;
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+
+void LLPanelPrimMediaControls::onClickClose()
+{
+ close();
+}
+
+void LLPanelPrimMediaControls::close()
+{
+ resetZoomLevel(true);
+ LLViewerMediaFocus::getInstance()->clearFocus();
+ setVisible(FALSE);
+}
+
+
+void LLPanelPrimMediaControls::onClickBack()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* impl =getTargetMediaImpl();
+
+ if (impl)
+ {
+ impl->navigateBack();
+ }
+}
+
+void LLPanelPrimMediaControls::onClickForward()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+ if (impl)
+ {
+ impl->navigateForward();
+ }
+}
+
+void LLPanelPrimMediaControls::onClickHome()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+ if(impl)
+ {
+ impl->navigateHome();
+ }
+}
+
+void LLPanelPrimMediaControls::onClickOpen()
+{
+ LLViewerMediaImpl* impl = getTargetMediaImpl();
+ if(impl)
+ {
+ LLWeb::loadURL(impl->getCurrentMediaURL());
+ }
+}
+
+void LLPanelPrimMediaControls::onClickReload()
+{
+ focusOnTarget();
+
+ //LLViewerMedia::navigateHome();
+ LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+ if(impl)
+ {
+ impl->navigateReload();
+ }
+}
+
+void LLPanelPrimMediaControls::onClickPlay()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+ if(impl)
+ {
+ impl->play();
+ }
+}
+
+void LLPanelPrimMediaControls::onClickPause()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+ if(impl)
+ {
+ impl->pause();
+ }
+}
+
+void LLPanelPrimMediaControls::onClickStop()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+ if(impl)
+ {
+ impl->navigateStop();
+ }
+}
+
+void LLPanelPrimMediaControls::onClickMediaStop()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+ if(impl)
+ {
+ impl->stop();
+ }
+}
+
+void LLPanelPrimMediaControls::onClickSkipBack()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* impl =getTargetMediaImpl();
+
+ if (impl)
+ {
+ impl->skipBack(mSkipStep);
+ }
+}
+
+void LLPanelPrimMediaControls::onClickSkipForward()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+ if (impl)
+ {
+ impl->skipForward(mSkipStep);
+ }
+}
+
+void LLPanelPrimMediaControls::onClickZoom()
+{
+ focusOnTarget();
+
+ if(mCurrentZoom == ZOOM_NONE)
+ {
+ nextZoomLevel();
+ }
+}
+
+void LLPanelPrimMediaControls::nextZoomLevel()
+{
+ int index = 0;
+ while (index < kNumZoomLevels)
+ {
+ if (kZoomLevels[index] == mCurrentZoom)
+ {
+ index++;
+ break;
+ }
+ index++;
+ }
+ mCurrentZoom = kZoomLevels[index % kNumZoomLevels];
+ updateZoom();
+}
+
+void LLPanelPrimMediaControls::resetZoomLevel(bool reset_camera)
+{
+ if(mCurrentZoom != ZOOM_NONE)
+ {
+ mCurrentZoom = ZOOM_NONE;
+ if(reset_camera)
+ {
+ updateZoom();
+ }
+ }
+}
+
+void LLPanelPrimMediaControls::updateZoom()
+{
+ F32 zoom_padding = 0.0f;
+ switch (mCurrentZoom)
+ {
+ case ZOOM_NONE:
+ {
+ gAgent.setFocusOnAvatar(TRUE, ANIMATE);
+ break;
+ }
+ case ZOOM_FAR:
+ {
+ zoom_padding = mZoomFarPadding;
+ break;
+ }
+ case ZOOM_MEDIUM:
+ {
+ zoom_padding = mZoomMediumPadding;
+ break;
+ }
+ case ZOOM_NEAR:
+ {
+ zoom_padding = mZoomNearPadding;
+ break;
+ }
+ default:
+ {
+ gAgent.setFocusOnAvatar(TRUE, ANIMATE);
+ break;
+ }
+ }
+
+ if (zoom_padding > 0.0f)
+ {
+ LLViewerMediaFocus::setCameraZoom(getTargetObject(), mTargetObjectNormal, zoom_padding);
+ }
+
+ // Remember the object ID/face we zoomed into, so we can update the zoom icon appropriately
+ mZoomObjectID = mTargetObjectID;
+ mZoomObjectFace = mTargetObjectFace;
+}
+
+void LLPanelPrimMediaControls::onScrollUp(void* user_data)
+{
+ LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+ this_panel->focusOnTarget();
+
+ LLViewerMediaImpl* impl = this_panel->getTargetMediaImpl();
+
+ if(impl)
+ {
+ impl->scrollWheel(0, -1, MASK_NONE);
+ }
+}
+void LLPanelPrimMediaControls::onScrollUpHeld(void* user_data)
+{
+ LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+ this_panel->mScrollState = SCROLL_UP;
+}
+void LLPanelPrimMediaControls::onScrollRight(void* user_data)
+{
+ LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+ this_panel->focusOnTarget();
+
+ LLViewerMediaImpl* impl = this_panel->getTargetMediaImpl();
+
+ if(impl)
+ {
+ impl->scrollWheel(-1, 0, MASK_NONE);
+// impl->handleKeyHere(KEY_RIGHT, MASK_NONE);
+ }
+}
+void LLPanelPrimMediaControls::onScrollRightHeld(void* user_data)
+{
+ LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+ this_panel->mScrollState = SCROLL_RIGHT;
+}
+
+void LLPanelPrimMediaControls::onScrollLeft(void* user_data)
+{
+ LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+ this_panel->focusOnTarget();
+
+ LLViewerMediaImpl* impl = this_panel->getTargetMediaImpl();
+
+ if(impl)
+ {
+ impl->scrollWheel(1, 0, MASK_NONE);
+// impl->handleKeyHere(KEY_LEFT, MASK_NONE);
+ }
+}
+void LLPanelPrimMediaControls::onScrollLeftHeld(void* user_data)
+{
+ LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+ this_panel->mScrollState = SCROLL_LEFT;
+}
+
+void LLPanelPrimMediaControls::onScrollDown(void* user_data)
+{
+ LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+ this_panel->focusOnTarget();
+
+ LLViewerMediaImpl* impl = this_panel->getTargetMediaImpl();
+
+ if(impl)
+ {
+ impl->scrollWheel(0, 1, MASK_NONE);
+ }
+}
+void LLPanelPrimMediaControls::onScrollDownHeld(void* user_data)
+{
+ LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+ this_panel->mScrollState = SCROLL_DOWN;
+}
+
+void LLPanelPrimMediaControls::onScrollStop(void* user_data)
+{
+ LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+ this_panel->mScrollState = SCROLL_NONE;
+}
+
+void LLPanelPrimMediaControls::onCommitURL()
+{
+ focusOnTarget();
+
+ std::string url = mMediaAddress->getValue().asString();
+ if(getTargetMediaImpl() && !url.empty())
+ {
+ getTargetMediaImpl()->navigateTo( url, "", true);
+
+ // Make sure keyboard focus is set to the media focus object.
+ gFocusMgr.setKeyboardFocus(LLViewerMediaFocus::getInstance());
+
+ }
+ mPauseFadeout = false;
+ mFadeTimer.start();
+}
+
+
+void LLPanelPrimMediaControls::onInputURL(LLFocusableElement* caller, void *userdata)
+{
+
+ LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (userdata);
+ this_panel->focusOnTarget();
+
+ this_panel->mPauseFadeout = true;
+ this_panel->mFadeTimer.stop();
+ this_panel->mFadeTimer.reset();
+
+}
+
+void LLPanelPrimMediaControls::setCurrentURL()
+{
+#ifdef USE_COMBO_BOX_FOR_MEDIA_URL
+// LLComboBox* media_address_combo = getChild<LLComboBox>("media_address_combo");
+// // redirects will navigate momentarily to about:blank, don't add to history
+// if (media_address_combo && mCurrentURL != "about:blank")
+// {
+// media_address_combo->remove(mCurrentURL);
+// media_address_combo->add(mCurrentURL, ADD_SORTED);
+// media_address_combo->selectByValue(mCurrentURL);
+// }
+#else // USE_COMBO_BOX_FOR_MEDIA_URL
+ if (mMediaAddress && mCurrentURL != "about:blank")
+ {
+ mMediaAddress->setValue(mCurrentURL);
+ }
+#endif // USE_COMBO_BOX_FOR_MEDIA_URL
+}
+
+void LLPanelPrimMediaControls::onCommitSlider()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+ if (media_impl)
+ {
+ // get slider value
+ F64 slider_value = mMediaPlaySliderCtrl->getValue().asReal();
+ if(slider_value <= 0.0)
+ {
+ media_impl->stop();
+ }
+ else
+ {
+ media_impl->seek(slider_value*mMovieDuration);
+ //mUpdateSlider= false;
+ }
+ }
+}
+
+void LLPanelPrimMediaControls::onCommitVolumeUp()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+ if (media_impl)
+ {
+ F32 volume = media_impl->getVolume();
+
+ volume += 0.1f;
+ if(volume >= 1.0f)
+ {
+ volume = 1.0f;
+ }
+
+ media_impl->setVolume(volume);
+ mMuteBtn->setToggleState(false);
+ }
+}
+
+void LLPanelPrimMediaControls::onCommitVolumeDown()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+ if (media_impl)
+ {
+ F32 volume = media_impl->getVolume();
+
+ volume -= 0.1f;
+ if(volume <= 0.0f)
+ {
+ volume = 0.0f;
+ }
+
+ media_impl->setVolume(volume);
+ mMuteBtn->setToggleState(false);
+ }
+}
+
+void LLPanelPrimMediaControls::onCommitVolumeSlider()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+ if (media_impl)
+ {
+ media_impl->setVolume(mVolumeSliderCtrl->getValueF32());
+ }
+}
+
+void LLPanelPrimMediaControls::onToggleMute()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+ if (media_impl)
+ {
+ F32 volume = media_impl->getVolume();
+
+ if(volume > 0.0)
+ {
+ media_impl->setVolume(0.0);
+ }
+ else if (mVolumeSliderCtrl->getValueF32() == 0.0)
+ {
+ media_impl->setVolume(1.0);
+ mVolumeSliderCtrl->setValue(1.0);
+ }
+ else
+ {
+ media_impl->setVolume(mVolumeSliderCtrl->getValueF32());
+ }
+ }
+}
+
+void LLPanelPrimMediaControls::showVolumeSlider()
+{
+ mVolumeSliderVisible++;
+}
+
+void LLPanelPrimMediaControls::hideVolumeSlider()
+{
+ mVolumeSliderVisible--;
+}
+
+bool LLPanelPrimMediaControls::shouldVolumeSliderBeVisible()
+{
+ return mVolumeSliderVisible > 0;
+}
diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h
new file mode 100644
index 0000000000..743cec70a1
--- /dev/null
+++ b/indra/newview/llpanelprimmediacontrols.h
@@ -0,0 +1,211 @@
+/**
+ * @file llpanelprimmediacontrols.h
+ * @brief Pop-up media controls panel
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_PANELPRIMMEDIACONTROLS_H
+#define LL_PANELPRIMMEDIACONTROLS_H
+
+#include "llpanel.h"
+#include "llviewermedia.h"
+
+class LLButton;
+class LLCoordWindow;
+class LLIconCtrl;
+class LLLayoutStack;
+class LLProgressBar;
+class LLSliderCtrl;
+class LLViewerMediaImpl;
+
+class LLPanelPrimMediaControls : public LLPanel
+{
+public:
+ LLPanelPrimMediaControls();
+ virtual ~LLPanelPrimMediaControls();
+ /*virtual*/ BOOL postBuild();
+ virtual void draw();
+ virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ virtual BOOL handleKeyHere(KEY key, MASK mask);
+
+ void updateShape();
+ bool isMouseOver();
+ void nextZoomLevel();
+ void resetZoomLevel(bool reset_camera = true);
+ void close();
+
+ LLHandle<LLPanelPrimMediaControls> getHandle() const { return mPanelHandle; }
+ void setMediaFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3::zero);
+
+
+ enum EZoomLevel
+ {
+ ZOOM_NONE = 0,
+ ZOOM_FAR,
+ ZOOM_MEDIUM,
+ ZOOM_NEAR
+ };
+ static const EZoomLevel kZoomLevels[];
+ static const int kNumZoomLevels;
+
+ enum EScrollDir
+ {
+ SCROLL_UP = 0,
+ SCROLL_DOWN,
+ SCROLL_LEFT,
+ SCROLL_RIGHT,
+ SCROLL_NONE
+ };
+
+private:
+ void onClickClose();
+ void onClickBack();
+ void onClickForward();
+ void onClickHome();
+ void onClickOpen();
+ void onClickReload();
+ void onClickPlay();
+ void onClickPause();
+ void onClickStop();
+ void onClickZoom();
+ void onClickSkipBack();
+ void onClickSkipForward();
+ void onClickMediaStop();
+ void onCommitURL();
+
+ void updateZoom();
+ void setCurrentURL();
+ void onCommitSlider();
+
+ void onCommitVolumeUp();
+ void onCommitVolumeDown();
+ void onCommitVolumeSlider();
+ void onToggleMute();
+ void showVolumeSlider();
+ void hideVolumeSlider();
+ bool shouldVolumeSliderBeVisible();
+
+ static void onScrollUp(void* user_data);
+ static void onScrollUpHeld(void* user_data);
+ static void onScrollLeft(void* user_data);
+ static void onScrollLeftHeld(void* user_data);
+ static void onScrollRight(void* user_data);
+ static void onScrollRightHeld(void* user_data);
+ static void onScrollDown(void* user_data);
+ static void onScrollDownHeld(void* user_data);
+ static void onScrollStop(void* user_data);
+
+ static void onInputURL(LLFocusableElement* caller, void *userdata);
+ static bool hasControlsPermission(LLViewerObject *obj, const LLMediaEntry *media_entry);
+
+ void focusOnTarget();
+
+ LLViewerMediaImpl* getTargetMediaImpl();
+ LLViewerObject* getTargetObject();
+ LLPluginClassMedia* getTargetMediaPlugin();
+
+private:
+
+ LLView *mMediaRegion;
+ LLUICtrl *mBackCtrl;
+ LLUICtrl *mFwdCtrl;
+ LLUICtrl *mReloadCtrl;
+ LLUICtrl *mPlayCtrl;
+ LLUICtrl *mPauseCtrl;
+ LLUICtrl *mStopCtrl;
+ LLUICtrl *mMediaStopCtrl;
+ LLUICtrl *mHomeCtrl;
+ LLUICtrl *mUnzoomCtrl;
+ LLUICtrl *mOpenCtrl;
+ LLUICtrl *mSkipBackCtrl;
+ LLUICtrl *mSkipFwdCtrl;
+ LLUICtrl *mZoomCtrl;
+ LLPanel *mMediaProgressPanel;
+ LLProgressBar *mMediaProgressBar;
+ LLUICtrl *mMediaAddressCtrl;
+ LLUICtrl *mMediaAddress;
+ LLUICtrl *mMediaPlaySliderPanel;
+ LLUICtrl *mMediaPlaySliderCtrl;
+ LLUICtrl *mVolumeCtrl;
+ LLButton *mMuteBtn;
+ LLSliderCtrl *mVolumeSliderCtrl;
+ LLIconCtrl *mWhitelistIcon;
+ LLIconCtrl *mSecureLockIcon;
+ LLLayoutStack *mMediaControlsStack;
+ LLUICtrl *mLeftBookend;
+ LLUICtrl *mRightBookend;
+ LLUIImage* mBackgroundImage;
+ LLUIImage* mVolumeSliderBackgroundImage;
+ F32 mSkipStep;
+ S32 mMinWidth;
+ S32 mMinHeight;
+ F32 mZoomNearPadding;
+ F32 mZoomMediumPadding;
+ F32 mZoomFarPadding;
+ S32 mTopWorldViewAvoidZone;
+
+ LLUICtrl *mMediaPanelScroll;
+ LLButton *mScrollUpCtrl;
+ LLButton *mScrollLeftCtrl;
+ LLButton *mScrollRightCtrl;
+ LLButton *mScrollDownCtrl;
+
+ bool mPauseFadeout;
+ bool mUpdateSlider;
+ bool mClearFaceOnFade;
+
+ LLMatrix4 mLastCameraMat;
+ EZoomLevel mCurrentZoom;
+ EScrollDir mScrollState;
+ LLCoordWindow mLastCursorPos;
+ LLFrameTimer mInactivityTimer;
+ LLFrameTimer mFadeTimer;
+ F32 mInactiveTimeout;
+ F32 mControlFadeTime;
+ LLRootHandle<LLPanelPrimMediaControls> mPanelHandle;
+ F32 mAlpha;
+ std::string mCurrentURL;
+ std::string mPreviousURL;
+ F64 mCurrentRate;
+ F64 mMovieDuration;
+
+ LLUUID mTargetObjectID;
+ S32 mTargetObjectFace;
+ LLUUID mTargetImplID;
+ LLVector3 mTargetObjectNormal;
+
+ LLUUID mZoomObjectID;
+ S32 mZoomObjectFace;
+
+ S32 mVolumeSliderVisible;
+};
+
+#endif // LL_PANELPRIMMEDIACONTROLS_H
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
new file mode 100644
index 0000000000..c73ade53c8
--- /dev/null
+++ b/indra/newview/llpanelprofile.cpp
@@ -0,0 +1,262 @@
+/**
+* @file llpanelprofile.cpp
+* @brief Profile panel implementation
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+#include "llpanelprofile.h"
+
+#include "llagent.h"
+#include "llavataractions.h"
+#include "llfloaterreg.h"
+#include "llcommandhandler.h"
+#include "llpanelpicks.h"
+#include "lltabcontainer.h"
+
+static const std::string PANEL_PICKS = "panel_picks";
+static const std::string PANEL_PROFILE = "panel_profile";
+
+class LLAgentHandler : public LLCommandHandler
+{
+public:
+ // requires trusted browser to trigger
+ LLAgentHandler() : LLCommandHandler("agent", UNTRUSTED_THROTTLE) { }
+
+ bool handle(const LLSD& params, const LLSD& query_map,
+ LLMediaCtrl* web)
+ {
+ if (params.size() < 2) return false;
+ LLUUID avatar_id;
+ if (!avatar_id.set(params[0], FALSE))
+ {
+ return false;
+ }
+
+ const std::string verb = params[1].asString();
+ if (verb == "about")
+ {
+ LLAvatarActions::showProfile(avatar_id);
+ return true;
+ }
+
+ if (verb == "inspect")
+ {
+ LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", avatar_id));
+ return true;
+ }
+
+ if (verb == "im")
+ {
+ LLAvatarActions::startIM(avatar_id);
+ return true;
+ }
+
+ if (verb == "pay")
+ {
+ LLAvatarActions::pay(avatar_id);
+ return true;
+ }
+
+ if (verb == "offerteleport")
+ {
+ LLAvatarActions::offerTeleport(avatar_id);
+ return true;
+ }
+
+ if (verb == "requestfriend")
+ {
+ LLAvatarActions::requestFriendshipDialog(avatar_id);
+ return true;
+ }
+
+ if (verb == "mute")
+ {
+ if (! LLAvatarActions::isBlocked(avatar_id))
+ {
+ LLAvatarActions::toggleBlock(avatar_id);
+ }
+ return true;
+ }
+
+ if (verb == "unmute")
+ {
+ if (LLAvatarActions::isBlocked(avatar_id))
+ {
+ LLAvatarActions::toggleBlock(avatar_id);
+ }
+ return true;
+ }
+
+ return false;
+ }
+};
+LLAgentHandler gAgentHandler;
+
+
+LLPanelProfile::LLPanelProfile()
+ : LLPanel()
+ , mTabCtrl(NULL)
+ , mAvatarId(LLUUID::null)
+{
+}
+
+BOOL LLPanelProfile::postBuild()
+{
+ mTabCtrl = getChild<LLTabContainer>("tabs");
+
+ getTabCtrl()->setCommitCallback(boost::bind(&LLPanelProfile::onTabSelected, this, _2));
+
+ LLPanelPicks* panel_picks = getChild<LLPanelPicks>(PANEL_PICKS);
+ panel_picks->setProfilePanel(this);
+
+ getTabContainer()[PANEL_PICKS] = panel_picks;
+ getTabContainer()[PANEL_PROFILE] = getChild<LLPanelAvatarProfile>(PANEL_PROFILE);
+
+ return TRUE;
+}
+
+void LLPanelProfile::onOpen(const LLSD& key)
+{
+ // open the desired panel
+ if (key.has("open_tab_name"))
+ {
+ getTabContainer()[PANEL_PICKS]->onClosePanel();
+
+ // onOpen from selected panel will be called from onTabSelected callback
+ getTabCtrl()->selectTabByName(key["open_tab_name"]);
+ }
+ else
+ {
+ getTabCtrl()->getCurrentPanel()->onOpen(getAvatarId());
+ }
+
+ // 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")
+ {
+ LLUUID classified_id = key["classified_id"].asUUID();
+ LLUUID avatar_id = key["classified_avatar_id"].asUUID();
+ LLUUID snapshot_id = key["classified_snapshot_id"].asUUID();
+ std::string name = key["classified_name"].asString();
+ std::string desc = key["classified_desc"].asString();
+ LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]);
+ if (picks)
+ {
+ picks->openClassifiedInfo(classified_id, avatar_id, snapshot_id, name, desc);
+ }
+ }
+ }
+}
+
+//*TODO redo panel toggling
+void LLPanelProfile::togglePanel(LLPanel* panel, const LLSD& key)
+{
+ // TRUE - we need to open/expand "panel"
+ bool expand = getChildList()->front() != panel; // mTabCtrl->getVisible();
+
+ if (expand)
+ {
+ openPanel(panel, key);
+ }
+ else
+ {
+ panel->setVisible(FALSE);
+ if (panel->getParent() == this)
+ {
+ removeChild(panel);
+ }
+
+ getTabCtrl()->getCurrentPanel()->onOpen(getAvatarId());
+ }
+}
+
+void LLPanelProfile::onTabSelected(const LLSD& param)
+{
+ std::string tab_name = param.asString();
+ if (NULL != getTabContainer()[tab_name])
+ {
+ getTabContainer()[tab_name]->onOpen(getAvatarId());
+ }
+}
+
+void LLPanelProfile::setAllChildrenVisible(BOOL visible)
+{
+ const child_list_t* child_list = getChildList();
+ child_list_const_iter_t child_it = child_list->begin();
+ for (; child_it != child_list->end(); ++child_it)
+ {
+ LLView* viewp = *child_it;
+ viewp->setVisible(visible);
+ }
+}
+
+void LLPanelProfile::openPanel(LLPanel* panel, const LLSD& params)
+{
+ if (panel->getParent() != this)
+ {
+ addChild(panel);
+ }
+ else
+ {
+ sendChildToFront(panel);
+ }
+
+ panel->setVisible(TRUE);
+
+ panel->onOpen(params);
+
+ 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);
+}
+
+S32 LLPanelProfile::notifyParent(const LLSD& info)
+{
+ std::string action = info["action"];
+ // lets update Picks list after Pick was saved
+ if("save_new_pick" == action)
+ {
+ onOpen(info);
+ return 1;
+ }
+
+ return LLPanel::notifyParent(info);
+}
diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h
new file mode 100644
index 0000000000..bcf4bdd0ec
--- /dev/null
+++ b/indra/newview/llpanelprofile.h
@@ -0,0 +1,85 @@
+/**
+* @file llpanelprofile.h
+* @brief Profile panel
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#ifndef LL_LLPANELPROFILE_H
+#define LL_LLPANELPROFILE_H
+
+#include "llviewerprecompiledheaders.h"
+#include "llpanel.h"
+#include "llpanelavatar.h"
+
+class LLTabContainer;
+
+/**
+* Base class for Profile View and My Profile.
+*/
+class LLPanelProfile : public LLPanel
+{
+ LOG_CLASS(LLPanelProfile);
+
+public:
+ /*virtual*/ BOOL postBuild();
+
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ virtual void togglePanel(LLPanel*, const LLSD& key = LLSD());
+
+ virtual void openPanel(LLPanel* panel, const LLSD& params);
+
+ S32 notifyParent(const LLSD& info);
+
+protected:
+
+ LLPanelProfile();
+
+ virtual void onTabSelected(const LLSD& param);
+
+ virtual void setAllChildrenVisible(BOOL visible);
+
+ LLTabContainer* getTabCtrl() { return mTabCtrl; }
+
+ const LLUUID& getAvatarId() { return mAvatarId; }
+
+ void setAvatarId(const LLUUID& avatar_id) { mAvatarId = avatar_id; }
+
+ typedef std::map<std::string, LLPanelProfileTab*> profile_tabs_t;
+
+ profile_tabs_t& getTabContainer() { return mTabContainer; }
+
+private:
+
+ LLTabContainer* mTabCtrl;
+ profile_tabs_t mTabContainer;
+ LLUUID mAvatarId;
+};
+
+#endif //LL_LLPANELPROFILE_H
diff --git a/indra/newview/llpanelprofileview.cpp b/indra/newview/llpanelprofileview.cpp
new file mode 100644
index 0000000000..044036ea50
--- /dev/null
+++ b/indra/newview/llpanelprofileview.cpp
@@ -0,0 +1,207 @@
+/**
+* @file llpanelprofileview.cpp
+* @brief Side tray "Profile View" panel
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llavatarconstants.h"
+#include "lluserrelations.h"
+
+#include "llpanelprofileview.h"
+
+#include "llavatarpropertiesprocessor.h"
+#include "llcallingcard.h"
+#include "llpanelavatar.h"
+#include "llpanelpicks.h"
+#include "llpanelprofile.h"
+#include "llsidetraypanelcontainer.h"
+
+static LLRegisterPanelClassWrapper<LLPanelProfileView> t_panel_target_profile("panel_profile_view");
+
+static std::string PANEL_NOTES = "panel_notes";
+static const std::string PANEL_PROFILE = "panel_profile";
+static const std::string PANEL_PICKS = "panel_picks";
+
+
+class AvatarStatusObserver : public LLAvatarPropertiesObserver
+{
+public:
+ AvatarStatusObserver(LLPanelProfileView* profile_view)
+ {
+ mProfileView = profile_view;
+ }
+
+ void processProperties(void* data, EAvatarProcessorType type)
+ {
+ if(APT_PROPERTIES != type) return;
+ const LLAvatarData* avatar_data = static_cast<const LLAvatarData*>(data);
+ if(avatar_data && mProfileView->getAvatarId() == avatar_data->avatar_id)
+ {
+ mProfileView->processOnlineStatus(avatar_data->flags & AVATAR_ONLINE);
+ LLAvatarPropertiesProcessor::instance().removeObserver(mProfileView->getAvatarId(), this);
+ }
+ }
+
+ void subscribe()
+ {
+ LLAvatarPropertiesProcessor::instance().addObserver(mProfileView->getAvatarId(), this);
+ }
+
+private:
+ LLPanelProfileView* mProfileView;
+};
+
+LLPanelProfileView::LLPanelProfileView()
+: LLPanelProfile()
+, mStatusText(NULL)
+, mAvatarStatusObserver(NULL)
+{
+ mAvatarStatusObserver = new AvatarStatusObserver(this);
+}
+
+LLPanelProfileView::~LLPanelProfileView(void)
+{
+ delete mAvatarStatusObserver;
+}
+
+/*virtual*/
+void LLPanelProfileView::onOpen(const LLSD& key)
+{
+ LLUUID id;
+ if(key.has("id"))
+ {
+ id = key["id"];
+ }
+
+ if(id.notNull() && getAvatarId() != id)
+ {
+ setAvatarId(id);
+ }
+
+ // Update the avatar name.
+ gCacheName->get(getAvatarId(), FALSE,
+ boost::bind(&LLPanelProfileView::onAvatarNameCached, this, _1, _2, _3, _4));
+
+ updateOnlineStatus();
+
+
+ LLPanelProfile::onOpen(key);
+}
+
+BOOL LLPanelProfileView::postBuild()
+{
+ LLPanelProfile::postBuild();
+
+ getTabContainer()[PANEL_NOTES] = getChild<LLPanelAvatarNotes>(PANEL_NOTES);
+
+ //*TODO remove this, according to style guide we don't use status combobox
+ getTabContainer()[PANEL_PROFILE]->childSetVisible("online_me_status_text", FALSE);
+ getTabContainer()[PANEL_PROFILE]->childSetVisible("status_combo", FALSE);
+
+ mStatusText = getChild<LLTextBox>("status");
+ mStatusText->setVisible(false);
+
+ childSetCommitCallback("back",boost::bind(&LLPanelProfileView::onBackBtnClick,this),NULL);
+
+ return TRUE;
+}
+
+
+//private
+
+void LLPanelProfileView::onBackBtnClick()
+{
+ // Set dummy value to make picks panel dirty,
+ // This will make Picks reload on next open.
+ getTabContainer()[PANEL_PICKS]->setValue(LLSD());
+
+ LLSideTrayPanelContainer* parent = dynamic_cast<LLSideTrayPanelContainer*>(getParent());
+ if(parent)
+ {
+ parent->openPreviousPanel();
+ }
+}
+
+bool LLPanelProfileView::isGrantedToSeeOnlineStatus()
+{
+ const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId());
+ if (NULL == relationship)
+ return false;
+
+ // *NOTE: GRANT_ONLINE_STATUS is always set to false while changing any other status.
+ // When avatar disallow me to see her online status processOfflineNotification Message is received by the viewer
+ // see comments for ChangeUserRights template message. EXT-453.
+ // If GRANT_ONLINE_STATUS flag is changed it will be applied when viewer restarts. EXT-3880
+ return relationship->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS);
+}
+
+// method was disabled according to EXT-2022. Re-enabled & improved according to EXT-3880
+void LLPanelProfileView::updateOnlineStatus()
+{
+ // set text box visible to show online status for non-friends who has not set in Preferences
+ // "Only Friends & Groups can see when I am online"
+ mStatusText->setVisible(TRUE);
+
+ const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId());
+ if (NULL == relationship)
+ {
+ // this is non-friend avatar. Status will be updated from LLAvatarPropertiesProcessor.
+ // in LLPanelProfileView::processOnlineStatus()
+
+ // subscribe observer to get online status. Request will be sent by LLPanelAvatarProfile itself.
+ // do not subscribe for friend avatar because online status can be wrong overridden
+ // via LLAvatarData::flags if Preferences: "Only Friends & Groups can see when I am online" is set.
+ mAvatarStatusObserver->subscribe();
+ return;
+ }
+ // For friend let check if he allowed me to see his status
+
+ // status should only show if viewer has permission to view online/offline. EXT-453, EXT-3880
+ mStatusText->setVisible(isGrantedToSeeOnlineStatus());
+
+ bool online = relationship->isOnline();
+ processOnlineStatus(online);
+}
+
+void LLPanelProfileView::processOnlineStatus(bool online)
+{
+ std::string status = getString(online ? "status_online" : "status_offline");
+
+ mStatusText->setValue(status);
+}
+
+void LLPanelProfileView::onAvatarNameCached(const LLUUID& id, const std::string& first_name, const std::string& last_name, BOOL is_group)
+{
+ llassert(getAvatarId() == id);
+ getChild<LLUICtrl>("user_name", FALSE)->setValue(first_name + " " + last_name);
+}
+
+// EOF
diff --git a/indra/newview/llpanelprofileview.h b/indra/newview/llpanelprofileview.h
new file mode 100644
index 0000000000..9b87e146a8
--- /dev/null
+++ b/indra/newview/llpanelprofileview.h
@@ -0,0 +1,112 @@
+/**
+* @file llpanelprofileview.h
+* @brief Side tray "Profile View" panel
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#ifndef LL_LLPANELPROFILEVIEW_H
+#define LL_LLPANELPROFILEVIEW_H
+
+#include "llpanel.h"
+#include "llpanelprofile.h"
+#include "llavatarpropertiesprocessor.h"
+#include "llagent.h"
+#include "lltooldraganddrop.h"
+
+class LLPanelProfile;
+class LLPanelProfileTab;
+class LLTextBox;
+class AvatarStatusObserver;
+
+/**
+* Panel for displaying Avatar's profile. It consists of three sub panels - Profile,
+* Picks and Notes.
+*/
+class LLPanelProfileView : public LLPanelProfile
+{
+ LOG_CLASS(LLPanelProfileView);
+ friend class LLUICtrlFactory;
+ friend class AvatarStatusObserver;
+
+public:
+
+ LLPanelProfileView();
+
+ /*virtual*/ ~LLPanelProfileView();
+
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ /*virtual*/ BOOL postBuild();
+
+ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
+ BOOL drop, EDragAndDropType cargo_type,
+ void *cargo_data, EAcceptance *accept,
+ std::string& tooltip_msg)
+ {
+ LLToolDragAndDrop::handleGiveDragAndDrop(getAvatarId(), gAgent.getSessionID(), drop,
+ cargo_type, cargo_data, accept);
+
+ return TRUE;
+ }
+
+
+protected:
+
+ void onBackBtnClick();
+ bool isGrantedToSeeOnlineStatus();
+
+ /**
+ * 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 online);
+
+private:
+ // LLCacheName will call this function when avatar name is loaded from server.
+ // This is required to display names that have not been cached yet.
+ void onAvatarNameCached(
+ const LLUUID& id,
+ const std::string& first_name,
+ const std::string& last_name,
+ BOOL is_group);
+
+ LLTextBox* mStatusText;
+ AvatarStatusObserver* mAvatarStatusObserver;
+};
+
+#endif //LL_LLPANELPROFILEVIEW_H
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
new file mode 100644
index 0000000000..1b8fb49641
--- /dev/null
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -0,0 +1,1058 @@
+/**
+ * @file llpanelteleporthistory.cpp
+ * @brief Teleport history represented by a scrolling list
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterreg.h"
+
+#include "llfloaterworldmap.h"
+#include "llpanelteleporthistory.h"
+#include "llsidetray.h"
+#include "llworldmap.h"
+#include "llteleporthistorystorage.h"
+#include "lltextutil.h"
+
+#include "llaccordionctrl.h"
+#include "llaccordionctrltab.h"
+#include "llflatlistview.h"
+#include "llnotificationsutil.h"
+#include "lltextbox.h"
+#include "llviewermenu.h"
+#include "llviewerinventory.h"
+#include "lllandmarkactions.h"
+#include "llclipboard.h"
+
+// Maximum number of items that can be added to a list in one pass.
+// Used to limit time spent for items list update per frame.
+static const U32 ADD_LIMIT = 50;
+
+static const std::string COLLAPSED_BY_USER = "collapsed_by_user";
+
+class LLTeleportHistoryFlatItem : public LLPanel
+{
+public:
+ LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string &region_name, const std::string &hl);
+ virtual ~LLTeleportHistoryFlatItem();
+
+ virtual BOOL postBuild();
+
+ /*virtual*/ S32 notify(const LLSD& info);
+
+ S32 getIndex() { return mIndex; }
+ void setIndex(S32 index) { mIndex = index; }
+ const std::string& getRegionName() { return mRegionName;}
+ void setRegionName(const std::string& name);
+ void setHighlightedText(const std::string& text);
+ void updateTitle();
+
+ /*virtual*/ void setValue(const LLSD& value);
+
+ void onMouseEnter(S32 x, S32 y, MASK mask);
+ void onMouseLeave(S32 x, S32 y, MASK mask);
+ virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+
+ static void showPlaceInfoPanel(S32 index);
+
+ LLHandle<LLTeleportHistoryFlatItem> getItemHandle() { mItemHandle.bind(this); return mItemHandle; }
+
+private:
+ void onProfileBtnClick();
+
+ LLButton* mProfileBtn;
+ LLTextBox* mTitle;
+
+ LLTeleportHistoryPanel::ContextMenu *mContextMenu;
+
+ S32 mIndex;
+ std::string mRegionName;
+ std::string mHighlight;
+ LLRootHandle<LLTeleportHistoryFlatItem> mItemHandle;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+class LLTeleportHistoryFlatItemStorage: public LLSingleton<LLTeleportHistoryFlatItemStorage> {
+protected:
+ typedef std::vector< LLHandle<LLTeleportHistoryFlatItem> > flat_item_list_t;
+
+public:
+ LLTeleportHistoryFlatItem* getFlatItemForPersistentItem (
+ LLTeleportHistoryPanel::ContextMenu *context_menu,
+ const LLTeleportHistoryPersistentItem& persistent_item,
+ const S32 cur_item_index,
+ const std::string &hl);
+
+ void removeItem(LLTeleportHistoryFlatItem* item);
+
+ void purge();
+
+private:
+
+ flat_item_list_t mItems;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string &region_name, const std::string &hl)
+: LLPanel(),
+ mIndex(index),
+ mContextMenu(context_menu),
+ mRegionName(region_name),
+ mHighlight(hl)
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_teleport_history_item.xml");
+}
+
+LLTeleportHistoryFlatItem::~LLTeleportHistoryFlatItem()
+{
+}
+
+//virtual
+BOOL LLTeleportHistoryFlatItem::postBuild()
+{
+ mTitle = getChild<LLTextBox>("region");
+
+ mProfileBtn = getChild<LLButton>("profile_btn");
+
+ mProfileBtn->setClickedCallback(boost::bind(&LLTeleportHistoryFlatItem::onProfileBtnClick, this));
+
+ updateTitle();
+
+ return true;
+}
+
+S32 LLTeleportHistoryFlatItem::notify(const LLSD& info)
+{
+ if(info.has("detach"))
+ {
+ delete mMouseDownSignal;
+ mMouseDownSignal = NULL;
+ delete mRightMouseDownSignal;
+ mRightMouseDownSignal = NULL;
+ return 1;
+ }
+ return 0;
+}
+
+void LLTeleportHistoryFlatItem::setValue(const LLSD& value)
+{
+ if (!value.isMap()) return;;
+ if (!value.has("selected")) return;
+ childSetVisible("selected_icon", value["selected"]);
+}
+
+void LLTeleportHistoryFlatItem::setHighlightedText(const std::string& text)
+{
+ mHighlight = text;
+}
+
+void LLTeleportHistoryFlatItem::setRegionName(const std::string& name)
+{
+ mRegionName = name;
+}
+
+void LLTeleportHistoryFlatItem::updateTitle()
+{
+ LLTextUtil::textboxSetHighlightedVal(
+ mTitle,
+ LLStyle::Params(),
+ mRegionName,
+ mHighlight);
+}
+
+void LLTeleportHistoryFlatItem::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+ childSetVisible("hovered_icon", true);
+ mProfileBtn->setVisible(true);
+
+ LLPanel::onMouseEnter(x, y, mask);
+}
+
+void LLTeleportHistoryFlatItem::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ childSetVisible("hovered_icon", false);
+ mProfileBtn->setVisible(false);
+
+ LLPanel::onMouseLeave(x, y, mask);
+}
+
+// virtual
+BOOL LLTeleportHistoryFlatItem::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ if (mContextMenu)
+ mContextMenu->show(this, mIndex, x, y);
+
+ return LLPanel::handleRightMouseDown(x, y, mask);
+}
+
+void LLTeleportHistoryFlatItem::showPlaceInfoPanel(S32 index)
+{
+ LLSD params;
+ params["id"] = index;
+ params["type"] = "teleport_history";
+
+ LLSideTray::getInstance()->showPanel("panel_places", params);
+}
+
+void LLTeleportHistoryFlatItem::onProfileBtnClick()
+{
+ LLTeleportHistoryFlatItem::showPlaceInfoPanel(mIndex);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+LLTeleportHistoryFlatItem*
+LLTeleportHistoryFlatItemStorage::getFlatItemForPersistentItem (
+ LLTeleportHistoryPanel::ContextMenu *context_menu,
+ const LLTeleportHistoryPersistentItem& persistent_item,
+ const S32 cur_item_index,
+ const std::string &hl)
+{
+ LLTeleportHistoryFlatItem* item = NULL;
+ if ( cur_item_index < (S32) mItems.size() )
+ {
+ item = mItems[cur_item_index].get();
+ if (item->getParent() == NULL)
+ {
+ item->setIndex(cur_item_index);
+ item->setRegionName(persistent_item.mTitle);
+ item->setHighlightedText(hl);
+ item->setVisible(TRUE);
+ item->updateTitle();
+ }
+ else
+ {
+ // Item already added to parent
+ item = NULL;
+ }
+ }
+
+ if ( !item )
+ {
+ item = new LLTeleportHistoryFlatItem(cur_item_index,
+ context_menu,
+ persistent_item.mTitle,
+ hl);
+ mItems.push_back(item->getItemHandle());
+ }
+
+ return item;
+}
+
+void LLTeleportHistoryFlatItemStorage::removeItem(LLTeleportHistoryFlatItem* item)
+{
+ if (item)
+ {
+ flat_item_list_t::iterator item_iter = std::find(mItems.begin(),
+ mItems.end(),
+ item->getItemHandle());
+ if (item_iter != mItems.end())
+ {
+ mItems.erase(item_iter);
+ }
+ }
+}
+
+void LLTeleportHistoryFlatItemStorage::purge()
+{
+ for ( flat_item_list_t::iterator
+ it = mItems.begin(),
+ it_end = mItems.end();
+ it != it_end; ++it )
+ {
+ LLHandle <LLTeleportHistoryFlatItem> item_handle = *it;
+ if ( !item_handle.isDead() && item_handle.get()->getParent() == NULL )
+ {
+ item_handle.get()->die();
+ }
+ }
+ mItems.clear();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+LLTeleportHistoryPanel::ContextMenu::ContextMenu() :
+ mMenu(NULL)
+{
+}
+
+void LLTeleportHistoryPanel::ContextMenu::show(LLView* spawning_view, S32 index, S32 x, S32 y)
+{
+ if (mMenu)
+ {
+ //preventing parent (menu holder) from deleting already "dead" context menus on exit
+ LLView* parent = mMenu->getParent();
+ if (parent)
+ {
+ parent->removeChild(mMenu);
+ }
+ delete mMenu;
+ }
+
+ mIndex = index;
+ mMenu = createMenu();
+
+ mMenu->show(x, y);
+ LLMenuGL::showPopup(spawning_view, mMenu, x, y);
+}
+
+LLContextMenu* LLTeleportHistoryPanel::ContextMenu::createMenu()
+{
+ // set up the callbacks for all of the avatar menu items
+ // (N.B. callbacks don't take const refs as mID is local scope)
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+
+ registrar.add("TeleportHistory.Teleport", boost::bind(&LLTeleportHistoryPanel::ContextMenu::onTeleport, this));
+ registrar.add("TeleportHistory.MoreInformation",boost::bind(&LLTeleportHistoryPanel::ContextMenu::onInfo, this));
+ registrar.add("TeleportHistory.CopyToClipboard",boost::bind(&LLTeleportHistoryPanel::ContextMenu::onCopyToClipboard, this));
+
+ // create the context menu from the XUI
+ return LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
+ "menu_teleport_history_item.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
+}
+
+void LLTeleportHistoryPanel::ContextMenu::onTeleport()
+{
+ LLTeleportHistoryStorage::getInstance()->goToItem(mIndex);
+}
+
+void LLTeleportHistoryPanel::ContextMenu::onInfo()
+{
+ LLTeleportHistoryFlatItem::showPlaceInfoPanel(mIndex);
+}
+
+//static
+void LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback(const std::string& slurl)
+{
+ gClipboard.copyFromString(utf8str_to_wstring(slurl));
+}
+
+void LLTeleportHistoryPanel::ContextMenu::onCopyToClipboard()
+{
+ LLVector3d globalPos = LLTeleportHistoryStorage::getInstance()->getItems()[mIndex].mGlobalPos;
+ LLLandmarkActions::getSLURLfromPosGlobal(globalPos,
+ boost::bind(&LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback, _1));
+}
+
+// Not yet implemented; need to remove buildPanel() from constructor when we switch
+//static LLRegisterPanelClassWrapper<LLTeleportHistoryPanel> t_teleport_history("panel_teleport_history");
+
+LLTeleportHistoryPanel::LLTeleportHistoryPanel()
+ : LLPanelPlacesTab(),
+ mDirty(true),
+ mCurrentItem(0),
+ mTeleportHistory(NULL),
+ mHistoryAccordion(NULL),
+ mAccordionTabMenu(NULL),
+ mLastSelectedFlatlList(NULL),
+ mLastSelectedItemIndex(-1)
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_teleport_history.xml");
+}
+
+LLTeleportHistoryPanel::~LLTeleportHistoryPanel()
+{
+ LLTeleportHistoryFlatItemStorage::instance().purge();
+ LLView::deleteViewByHandle(mGearMenuHandle);
+}
+
+BOOL LLTeleportHistoryPanel::postBuild()
+{
+ mTeleportHistory = LLTeleportHistoryStorage::getInstance();
+ if (mTeleportHistory)
+ {
+ mTeleportHistory->setHistoryChangedCallback(boost::bind(&LLTeleportHistoryPanel::onTeleportHistoryChange, this, _1));
+ }
+
+ mHistoryAccordion = getChild<LLAccordionCtrl>("history_accordion");
+
+ if (mHistoryAccordion)
+ {
+ for (child_list_const_iter_t iter = mHistoryAccordion->beginChild(); iter != mHistoryAccordion->endChild(); iter++)
+ {
+ if (dynamic_cast<LLAccordionCtrlTab*>(*iter))
+ {
+ LLAccordionCtrlTab* tab = (LLAccordionCtrlTab*)*iter;
+ tab->setRightMouseDownCallback(boost::bind(&LLTeleportHistoryPanel::onAccordionTabRightClick, this, _1, _2, _3, _4));
+ tab->setDisplayChildren(false);
+ tab->setDropDownStateChangedCallback(boost::bind(&LLTeleportHistoryPanel::onAccordionExpand, this, _1, _2));
+
+ // All accordion tabs are collapsed initially
+ setAccordionCollapsedByUser(tab, true);
+
+ mItemContainers.put(tab);
+
+ LLFlatListView* fl = getFlatListViewFromTab(tab);
+ if (fl)
+ {
+ fl->setCommitOnSelectionChange(true);
+ fl->setDoubleClickCallback(boost::bind(&LLTeleportHistoryPanel::onDoubleClickItem, this));
+ fl->setCommitCallback(boost::bind(&LLTeleportHistoryPanel::handleItemSelect, this, fl));
+ fl->setReturnCallback(boost::bind(&LLTeleportHistoryPanel::onReturnKeyPressed, this));
+ }
+ }
+ }
+
+ // Open first 2 accordion tabs
+ if (mItemContainers.size() > 1)
+ {
+ LLAccordionCtrlTab* tab = mItemContainers.get(mItemContainers.size() - 1);
+ tab->setDisplayChildren(true);
+ setAccordionCollapsedByUser(tab, false);
+ }
+
+ if (mItemContainers.size() > 2)
+ {
+ LLAccordionCtrlTab* tab = mItemContainers.get(mItemContainers.size() - 2);
+ tab->setDisplayChildren(true);
+ setAccordionCollapsedByUser(tab, false);
+ }
+ }
+
+ getChild<LLPanel>("bottom_panel")->childSetAction("gear_btn",boost::bind(&LLTeleportHistoryPanel::onGearButtonClicked, this));
+
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+
+ registrar.add("TeleportHistory.ExpandAllFolders", boost::bind(&LLTeleportHistoryPanel::onExpandAllFolders, this));
+ registrar.add("TeleportHistory.CollapseAllFolders", boost::bind(&LLTeleportHistoryPanel::onCollapseAllFolders, this));
+ registrar.add("TeleportHistory.ClearTeleportHistory", boost::bind(&LLTeleportHistoryPanel::onClearTeleportHistory, this));
+ mEnableCallbackRegistrar.add("TeleportHistory.GearMenu.Enable", boost::bind(&LLTeleportHistoryPanel::isActionEnabled, this, _2));
+
+ LLMenuGL* gear_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_teleport_history_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if(gear_menu)
+ mGearMenuHandle = gear_menu->getHandle();
+
+ return TRUE;
+}
+
+// virtual
+void LLTeleportHistoryPanel::draw()
+{
+ if (mDirty)
+ refresh();
+
+ LLPanelPlacesTab::draw();
+}
+
+// virtual
+void LLTeleportHistoryPanel::onSearchEdit(const std::string& string)
+{
+ sFilterSubString = string;
+ showTeleportHistory();
+}
+
+// virtual
+void LLTeleportHistoryPanel::onShowOnMap()
+{
+ if (!mLastSelectedFlatlList)
+ return;
+
+ LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
+
+ if(!itemp)
+ return;
+
+ LLVector3d global_pos = mTeleportHistory->getItems()[itemp->getIndex()].mGlobalPos;
+
+ if (!global_pos.isExactlyZero())
+ {
+ LLFloaterWorldMap::getInstance()->trackLocation(global_pos);
+ LLFloaterReg::showInstance("world_map", "center");
+ }
+}
+
+// virtual
+void LLTeleportHistoryPanel::onTeleport()
+{
+ if (!mLastSelectedFlatlList)
+ return;
+
+ LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
+ if(!itemp)
+ return;
+
+ // teleport to existing item in history, so we don't add it again
+ mTeleportHistory->goToItem(itemp->getIndex());
+}
+
+/*
+// virtual
+void LLTeleportHistoryPanel::onCopySLURL()
+{
+ LLScrollListItem* itemp = mHistoryItems->getFirstSelected();
+ if(!itemp)
+ return;
+
+ S32 index = itemp->getColumn(LIST_INDEX)->getValue().asInteger();
+
+ const LLTeleportHistory::slurl_list_t& hist_items = mTeleportHistory->getItems();
+
+ LLVector3d global_pos = hist_items[index].mGlobalPos;
+
+ U64 new_region_handle = to_region_handle(global_pos);
+
+ LLWorldMapMessage::url_callback_t cb = boost::bind(
+ &LLPanelPlacesTab::onRegionResponse, this,
+ global_pos, _1, _2, _3, _4);
+
+ LLWorldMap::getInstance()->sendHandleRegionRequest(new_region_handle, cb, std::string("unused"), false);
+}
+*/
+
+// virtual
+void LLTeleportHistoryPanel::updateVerbs()
+{
+ if (!isTabVisible())
+ return;
+
+ if (!mLastSelectedFlatlList)
+ {
+ mTeleportBtn->setEnabled(false);
+ mShowOnMapBtn->setEnabled(false);
+ return;
+ }
+
+ LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
+
+ mTeleportBtn->setEnabled(NULL != itemp);
+ mShowOnMapBtn->setEnabled(NULL != itemp);
+}
+
+void LLTeleportHistoryPanel::getNextTab(const LLDate& item_date, S32& tab_idx, LLDate& tab_date)
+{
+ const U32 seconds_in_day = 24 * 60 * 60;
+
+ S32 tabs_cnt = mItemContainers.size();
+ S32 curr_year = 0, curr_month = 0, curr_day = 0;
+
+ tab_date = LLDate::now();
+ tab_date.split(&curr_year, &curr_month, &curr_day);
+ tab_date.fromYMDHMS(curr_year, curr_month, curr_day); // Set hour, min, and sec to 0
+ tab_date.secondsSinceEpoch(tab_date.secondsSinceEpoch() + seconds_in_day);
+
+ tab_idx = -1;
+
+ while (tab_idx < tabs_cnt - 1 && item_date < tab_date)
+ {
+ tab_idx++;
+
+ if (tab_idx <= tabs_cnt - 4)
+ {
+ // All tabs, except last three, are tabs for one day, so just push tab_date back by one day
+ tab_date.secondsSinceEpoch(tab_date.secondsSinceEpoch() - seconds_in_day);
+ }
+ else if (tab_idx == tabs_cnt - 3) // 6 day and older, low boundary is 1 month
+ {
+ tab_date = LLDate::now();
+ tab_date.split(&curr_year, &curr_month, &curr_day);
+ curr_month--;
+ if (0 == curr_month)
+ {
+ curr_month = 12;
+ curr_year--;
+ }
+ tab_date.fromYMDHMS(curr_year, curr_month, curr_day);
+ }
+ else if (tab_idx == tabs_cnt - 2) // 1 month and older, low boundary is 6 months
+ {
+ tab_date = LLDate::now();
+ tab_date.split(&curr_year, &curr_month, &curr_day);
+ if (curr_month > 6)
+ {
+ curr_month -= 6;
+ }
+ else
+ {
+ curr_month += 6;
+ curr_year--;
+ }
+ tab_date.fromYMDHMS(curr_year, curr_month, curr_day);
+ }
+ else // 6 months and older
+ {
+ tab_date.secondsSinceEpoch(0);
+ }
+ }
+}
+
+// Called to add items, no more, than ADD_LIMIT at time
+void LLTeleportHistoryPanel::refresh()
+{
+ if (!mHistoryAccordion)
+ {
+ mDirty = false;
+ return;
+ }
+
+ const LLTeleportHistoryStorage::slurl_list_t& items = mTeleportHistory->getItems();
+
+ // Setting tab_boundary_date to "now", so date from any item would be earlier, than boundary.
+ // That leads to call to getNextTab to get right tab_idx in first pass
+ LLDate tab_boundary_date = LLDate::now();
+
+ LLFlatListView* curr_flat_view = NULL;
+
+ U32 added_items = 0;
+ while (mCurrentItem >= 0)
+ {
+ // Filtering
+ if (!sFilterSubString.empty())
+ {
+ std::string landmark_title(items[mCurrentItem].mTitle);
+ LLStringUtil::toUpper(landmark_title);
+ if( std::string::npos == landmark_title.find(sFilterSubString) )
+ {
+ mCurrentItem--;
+ continue;
+ }
+ }
+
+ // Checking whether date of item is earlier, than tab_boundary_date.
+ // In that case, item should be added to another tab
+ const LLDate &date = items[mCurrentItem].mDate;
+
+ if (date < tab_boundary_date)
+ {
+ // Getting apropriate tab_idx for this and subsequent items,
+ // tab_boundary_date would be earliest possible date for this tab
+ S32 tab_idx = 0;
+ getNextTab(date, tab_idx, tab_boundary_date);
+
+ LLAccordionCtrlTab* tab = mItemContainers.get(mItemContainers.size() - 1 - tab_idx);
+ tab->setVisible(true);
+
+ // Expand all accordion tabs when filtering
+ if(!sFilterSubString.empty())
+ {
+ //store accordion tab state when filter is not empty
+ tab->notifyChildren(LLSD().with("action","store_state"));
+
+ tab->setDisplayChildren(true);
+ }
+ // Restore each tab's expand state when not filtering
+ else
+ {
+ bool collapsed = isAccordionCollapsedByUser(tab);
+ tab->setDisplayChildren(!collapsed);
+
+ //restore accordion state after all those accodrion tabmanipulations
+ tab->notifyChildren(LLSD().with("action","restore_state"));
+ }
+
+ curr_flat_view = getFlatListViewFromTab(tab);
+ }
+
+ if (curr_flat_view)
+ {
+ LLTeleportHistoryFlatItem* item =
+ LLTeleportHistoryFlatItemStorage::instance()
+ .getFlatItemForPersistentItem(&mContextMenu,
+ items[mCurrentItem],
+ mCurrentItem,
+ sFilterSubString);
+ if ( !curr_flat_view->addItem(item, LLUUID::null, ADD_BOTTOM, false) )
+ llerrs << "Couldn't add flat item to teleport history." << llendl;
+ if (mLastSelectedItemIndex == mCurrentItem)
+ curr_flat_view->selectItem(item, true);
+ }
+
+ mCurrentItem--;
+
+ if (++added_items >= ADD_LIMIT)
+ break;
+ }
+
+ for (S32 n = mItemContainers.size() - 1; n >= 0; --n)
+ {
+ LLAccordionCtrlTab* tab = mItemContainers.get(n);
+ LLFlatListView* fv = getFlatListViewFromTab(tab);
+ if (fv)
+ {
+ fv->notify(LLSD().with("rearrange", LLSD()));
+ }
+ }
+
+ mHistoryAccordion->arrange();
+
+ updateVerbs();
+
+ if (mCurrentItem < 0)
+ mDirty = false;
+}
+
+void LLTeleportHistoryPanel::onTeleportHistoryChange(S32 removed_index)
+{
+ mLastSelectedItemIndex = -1;
+
+ if (-1 == removed_index)
+ showTeleportHistory(); // recreate all items
+ else
+ {
+ replaceItem(removed_index); // replace removed item by most recent
+ updateVerbs();
+ }
+}
+
+void LLTeleportHistoryPanel::replaceItem(S32 removed_index)
+{
+ // Flat list for 'Today' (mItemContainers keeps accordion tabs in reverse order)
+ LLFlatListView* fv = getFlatListViewFromTab(mItemContainers[mItemContainers.size() - 1]);
+
+ // Empty flat list for 'Today' means that other flat lists are empty as well,
+ // so all items from teleport history should be added.
+ if (!fv || fv->size() == 0)
+ {
+ showTeleportHistory();
+ return;
+ }
+
+ const LLTeleportHistoryStorage::slurl_list_t& history_items = mTeleportHistory->getItems();
+ LLTeleportHistoryFlatItem* item = LLTeleportHistoryFlatItemStorage::instance()
+ .getFlatItemForPersistentItem(&mContextMenu,
+ history_items[history_items.size() - 1], // Most recent item, it was added instead of removed
+ history_items.size(), // index will be decremented inside loop below
+ sFilterSubString);
+
+ fv->addItem(item, LLUUID::null, ADD_TOP);
+
+ // Index of each item, from last to removed item should be decremented
+ // to point to the right item in LLTeleportHistoryStorage
+ for (S32 tab_idx = mItemContainers.size() - 1; tab_idx >= 0; --tab_idx)
+ {
+ LLAccordionCtrlTab* tab = mItemContainers.get(tab_idx);
+ if (!tab->getVisible())
+ continue;
+
+ fv = getFlatListViewFromTab(tab);
+ if (!fv)
+ {
+ showTeleportHistory();
+ return;
+ }
+
+ std::vector<LLPanel*> items;
+ fv->getItems(items);
+
+ S32 items_cnt = items.size();
+ for (S32 n = 0; n < items_cnt; ++n)
+ {
+ LLTeleportHistoryFlatItem *item = (LLTeleportHistoryFlatItem*) items[n];
+
+ if (item->getIndex() == removed_index)
+ {
+ LLTeleportHistoryFlatItemStorage::instance().removeItem(item);
+
+ fv->removeItem(item);
+
+ // If flat list becames empty, then accordion tab should be hidden
+ if (fv->size() == 0)
+ tab->setVisible(false);
+
+ mHistoryAccordion->arrange();
+
+ return; // No need to decrement idexes for the rest of items
+ }
+
+ item->setIndex(item->getIndex() - 1);
+ }
+ }
+}
+
+void LLTeleportHistoryPanel::showTeleportHistory()
+{
+ mDirty = true;
+
+ // Starting to add items from last one, in reverse order,
+ // since TeleportHistory keeps most recent item at the end
+ mCurrentItem = mTeleportHistory->getItems().size() - 1;
+
+ for (S32 n = mItemContainers.size() - 1; n >= 0; --n)
+ {
+ LLAccordionCtrlTab* tab = mItemContainers.get(n);
+ tab->setVisible(false);
+
+ LLFlatListView* fv = getFlatListViewFromTab(tab);
+ if (fv)
+ {
+ // Detached panels are managed by LLTeleportHistoryFlatItemStorage
+ std::vector<LLPanel*> detached_items;
+ fv->detachItems(detached_items);
+ }
+ }
+}
+
+void LLTeleportHistoryPanel::handleItemSelect(LLFlatListView* selected)
+{
+ mLastSelectedFlatlList = selected;
+ LLTeleportHistoryFlatItem* item = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
+ if (item)
+ mLastSelectedItemIndex = item->getIndex();
+
+ S32 tabs_cnt = mItemContainers.size();
+
+ for (S32 n = 0; n < tabs_cnt; n++)
+ {
+ LLAccordionCtrlTab* tab = mItemContainers.get(n);
+
+ if (!tab->getVisible())
+ continue;
+
+ LLFlatListView *flv = getFlatListViewFromTab(tab);
+ if (!flv)
+ continue;
+
+ if (flv == selected)
+ continue;
+
+ flv->resetSelection(true);
+ }
+
+ updateVerbs();
+}
+
+void LLTeleportHistoryPanel::onReturnKeyPressed()
+{
+ // Teleport to selected region as default action on return key pressed
+ onTeleport();
+}
+
+void LLTeleportHistoryPanel::onDoubleClickItem()
+{
+ // If item got doubleclick, then that item is already selected
+ onTeleport();
+}
+
+void LLTeleportHistoryPanel::onAccordionTabRightClick(LLView *view, S32 x, S32 y, MASK mask)
+{
+ LLAccordionCtrlTab *tab = (LLAccordionCtrlTab *) view;
+
+ // If click occurred below the header, don't show this menu
+ if (y < tab->getRect().getHeight() - tab->getHeaderHeight() - tab->getPaddingBottom())
+ return;
+
+ if (mAccordionTabMenu)
+ {
+ //preventing parent (menu holder) from deleting already "dead" context menus on exit
+ LLView* parent = mAccordionTabMenu->getParent();
+ if (parent)
+ {
+ parent->removeChild(mAccordionTabMenu);
+ }
+ delete mAccordionTabMenu;
+ }
+
+ // set up the callbacks for all of the avatar menu items
+ // (N.B. callbacks don't take const refs as mID is local scope)
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+
+ registrar.add("TeleportHistory.TabOpen", boost::bind(&LLTeleportHistoryPanel::onAccordionTabOpen, this, tab));
+ registrar.add("TeleportHistory.TabClose", boost::bind(&LLTeleportHistoryPanel::onAccordionTabClose, this, tab));
+
+ // create the context menu from the XUI
+ mAccordionTabMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
+ "menu_teleport_history_tab.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
+
+ mAccordionTabMenu->setItemVisible("TabOpen", !tab->isExpanded() ? true : false);
+ mAccordionTabMenu->setItemVisible("TabClose", tab->isExpanded() ? true : false);
+
+ mAccordionTabMenu->show(x, y);
+ LLMenuGL::showPopup(tab, mAccordionTabMenu, x, y);
+}
+
+void LLTeleportHistoryPanel::onAccordionTabOpen(LLAccordionCtrlTab *tab)
+{
+ tab->setDisplayChildren(true);
+ mHistoryAccordion->arrange();
+}
+
+void LLTeleportHistoryPanel::onAccordionTabClose(LLAccordionCtrlTab *tab)
+{
+ tab->setDisplayChildren(false);
+ mHistoryAccordion->arrange();
+}
+
+void LLTeleportHistoryPanel::onExpandAllFolders()
+{
+ S32 tabs_cnt = mItemContainers.size();
+
+ for (S32 n = 0; n < tabs_cnt; n++)
+ {
+ mItemContainers.get(n)->setDisplayChildren(true);
+ }
+ mHistoryAccordion->arrange();
+}
+
+void LLTeleportHistoryPanel::onCollapseAllFolders()
+{
+ S32 tabs_cnt = mItemContainers.size();
+
+ for (S32 n = 0; n < tabs_cnt; n++)
+ {
+ mItemContainers.get(n)->setDisplayChildren(false);
+ }
+ mHistoryAccordion->arrange();
+}
+
+void LLTeleportHistoryPanel::onClearTeleportHistory()
+{
+ LLNotificationsUtil::add("ConfirmClearTeleportHistory", LLSD(), LLSD(), boost::bind(&LLTeleportHistoryPanel::onClearTeleportHistoryDialog, this, _1, _2));
+}
+
+bool LLTeleportHistoryPanel::onClearTeleportHistoryDialog(const LLSD& notification, const LLSD& response)
+{
+
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+ if (0 == option)
+ {
+ LLTeleportHistoryStorage *th = LLTeleportHistoryStorage::getInstance();
+ th->purgeItems();
+ th->save();
+ }
+
+ return false;
+}
+
+LLFlatListView* LLTeleportHistoryPanel::getFlatListViewFromTab(LLAccordionCtrlTab *tab)
+{
+ for (child_list_const_iter_t iter = tab->beginChild(); iter != tab->endChild(); iter++)
+ {
+ if (dynamic_cast<LLFlatListView*>(*iter))
+ {
+ return (LLFlatListView*)*iter; // There should be one scroll list per tab.
+ }
+ }
+
+ return NULL;
+}
+
+void LLTeleportHistoryPanel::onGearButtonClicked()
+{
+ LLMenuGL* menu = (LLMenuGL*)mGearMenuHandle.get();
+ if (!menu)
+ return;
+
+ // Shows the menu at the top of the button bar.
+
+ // Calculate its coordinates.
+ LLPanel* bottom_panel = getChild<LLPanel>("bottom_panel");
+ menu->arrangeAndClear();
+ S32 menu_height = menu->getRect().getHeight();
+ S32 menu_x = -2; // *HACK: compensates HPAD in showPopup()
+ S32 menu_y = bottom_panel->getRect().mTop + menu_height;
+
+ // Actually show the menu.
+ menu->buildDrawLabels();
+ menu->updateParent(LLMenuGL::sMenuContainer);
+ LLMenuGL::showPopup(this, menu, menu_x, menu_y);
+}
+
+bool LLTeleportHistoryPanel::isActionEnabled(const LLSD& userdata) const
+{
+ S32 tabs_cnt = mItemContainers.size();
+
+ bool has_expanded_tabs = false;
+ bool has_collapsed_tabs = false;
+
+ for (S32 n = 0; n < tabs_cnt; n++)
+ {
+ LLAccordionCtrlTab* tab = mItemContainers.get(n);
+ if (!tab->getVisible())
+ continue;
+
+ if (tab->getDisplayChildren())
+ {
+ has_expanded_tabs = true;
+ }
+ else
+ {
+ has_collapsed_tabs = true;
+ }
+
+ if (has_expanded_tabs && has_collapsed_tabs)
+ {
+ break;
+ }
+ }
+
+ std::string command_name = userdata.asString();
+
+ if (has_expanded_tabs && command_name == "collapse_all")
+ {
+ return true;
+ }
+
+ if (has_collapsed_tabs && command_name == "expand_all")
+ {
+ return true;
+ }
+
+ return false;
+}
+
+void LLTeleportHistoryPanel::setAccordionCollapsedByUser(LLUICtrl* acc_tab, bool collapsed)
+{
+ LLSD param = acc_tab->getValue();
+ param[COLLAPSED_BY_USER] = collapsed;
+ acc_tab->setValue(param);
+}
+
+bool LLTeleportHistoryPanel::isAccordionCollapsedByUser(LLUICtrl* acc_tab)
+{
+ LLSD param = acc_tab->getValue();
+ if(!param.has(COLLAPSED_BY_USER))
+ {
+ return false;
+ }
+ return param[COLLAPSED_BY_USER].asBoolean();
+}
+
+void LLTeleportHistoryPanel::onAccordionExpand(LLUICtrl* ctrl, const LLSD& param)
+{
+ bool expanded = param.asBoolean();
+ // Save accordion tab state to restore it in refresh()
+ setAccordionCollapsedByUser(ctrl, !expanded);
+
+ // Reset selection upon accordion being collapsed
+ // to disable "Teleport" and "Map" buttons for hidden item.
+ if (!expanded && mLastSelectedFlatlList)
+ {
+ mLastSelectedFlatlList->resetSelection();
+ }
+}
diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h
new file mode 100644
index 0000000000..4eeaec7705
--- /dev/null
+++ b/indra/newview/llpanelteleporthistory.h
@@ -0,0 +1,122 @@
+/**
+ * @file llpanelteleporthistory.h
+ * @brief Teleport history represented by a scrolling list
+ * class definition
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELTELEPORTHISTORY_H
+#define LL_LLPANELTELEPORTHISTORY_H
+
+#include "lluictrlfactory.h"
+
+#include "llpanelplacestab.h"
+#include "llteleporthistory.h"
+#include "llmenugl.h"
+
+class LLTeleportHistoryStorage;
+class LLAccordionCtrl;
+class LLAccordionCtrlTab;
+class LLFlatListView;
+
+class LLTeleportHistoryPanel : public LLPanelPlacesTab
+{
+public:
+ class ContextMenu
+ {
+ public:
+ ContextMenu();
+ void show(LLView* spawning_view, S32 index, S32 x, S32 y);
+
+ private:
+ LLContextMenu* createMenu();
+ void onTeleport();
+ void onInfo();
+ void onCopyToClipboard();
+
+ static void gotSLURLCallback(const std::string& slurl);
+
+ LLContextMenu* mMenu;
+ S32 mIndex;
+ };
+
+ LLTeleportHistoryPanel();
+ virtual ~LLTeleportHistoryPanel();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void draw();
+
+ /*virtual*/ void onSearchEdit(const std::string& string);
+ /*virtual*/ void onShowOnMap();
+ /*virtual*/ void onTeleport();
+ ///*virtual*/ void onCopySLURL();
+ /*virtual*/ void updateVerbs();
+
+private:
+
+ void onDoubleClickItem();
+ void onReturnKeyPressed();
+ void onAccordionTabRightClick(LLView *view, S32 x, S32 y, MASK mask);
+ void onAccordionTabOpen(LLAccordionCtrlTab *tab);
+ void onAccordionTabClose(LLAccordionCtrlTab *tab);
+ void onExpandAllFolders();
+ void onCollapseAllFolders();
+ void onClearTeleportHistory();
+ bool onClearTeleportHistoryDialog(const LLSD& notification, const LLSD& response);
+
+ void refresh();
+ void getNextTab(const LLDate& item_date, S32& curr_tab, LLDate& tab_date);
+ void onTeleportHistoryChange(S32 removed_index);
+ void replaceItem(S32 removed_index);
+ void showTeleportHistory();
+ void handleItemSelect(LLFlatListView* );
+ LLFlatListView* getFlatListViewFromTab(LLAccordionCtrlTab *);
+ void onGearButtonClicked();
+ bool isActionEnabled(const LLSD& userdata) const;
+
+ void setAccordionCollapsedByUser(LLUICtrl* acc_tab, bool collapsed);
+ bool isAccordionCollapsedByUser(LLUICtrl* acc_tab);
+ void onAccordionExpand(LLUICtrl* ctrl, const LLSD& param);
+
+ LLTeleportHistoryStorage* mTeleportHistory;
+ LLAccordionCtrl* mHistoryAccordion;
+
+ LLFlatListView* mLastSelectedFlatlList;
+ S32 mLastSelectedItemIndex;
+ bool mDirty;
+ S32 mCurrentItem;
+
+ typedef LLDynamicArray<LLAccordionCtrlTab*> item_containers_t;
+ item_containers_t mItemContainers;
+
+ ContextMenu mContextMenu;
+ LLContextMenu* mAccordionTabMenu;
+ LLHandle<LLView> mGearMenuHandle;
+};
+
+#endif //LL_LLPANELTELEPORTHISTORY_H
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index 6d014a23de..fbe68b4d92 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -49,15 +49,14 @@
#include "material_codes.h"
// project includes
-#include "llagent.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llcolorswatch.h"
+#include "lltexturectrl.h"
#include "llcombobox.h"
-#include "llfirstuse.h"
+//#include "llfirstuse.h"
#include "llfocusmgr.h"
#include "llmanipscale.h"
-#include "llpanelinventory.h"
#include "llpreviewscript.h"
#include "llresmgr.h"
#include "llselectmgr.h"
@@ -73,6 +72,7 @@
#include "llvovolume.h"
#include "llworld.h"
#include "pipeline.h"
+#include "llviewershadermgr.h"
#include "lldrawpool.h"
#include "lluictrlfactory.h"
@@ -107,16 +107,32 @@ BOOL LLPanelVolume::postBuild()
childSetCommitCallback("Light Checkbox Ctrl",onCommitIsLight,this);
LLColorSwatchCtrl* LightColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
if(LightColorSwatch){
- LightColorSwatch->setOnCancelCallback(onLightCancelColor);
- LightColorSwatch->setOnSelectCallback(onLightSelectColor);
+ LightColorSwatch->setOnCancelCallback(boost::bind(&LLPanelVolume::onLightCancelColor, this, _2));
+ LightColorSwatch->setOnSelectCallback(boost::bind(&LLPanelVolume::onLightSelectColor, this, _2));
childSetCommitCallback("colorswatch",onCommitLight,this);
}
+
+ LLTextureCtrl* LightTexPicker = getChild<LLTextureCtrl>("light texture control");
+ if (LightTexPicker)
+ {
+ LightTexPicker->setOnCancelCallback(boost::bind(&LLPanelVolume::onLightCancelTexture, this, _2));
+ LightTexPicker->setOnSelectCallback(boost::bind(&LLPanelVolume::onLightSelectTexture, this, _2));
+ childSetCommitCallback("light texture control", onCommitLight, this);
+ }
+
childSetCommitCallback("Light Intensity",onCommitLight,this);
childSetValidate("Light Intensity",precommitValidate);
childSetCommitCallback("Light Radius",onCommitLight,this);
childSetValidate("Light Radius",precommitValidate);
childSetCommitCallback("Light Falloff",onCommitLight,this);
childSetValidate("Light Falloff",precommitValidate);
+
+ childSetCommitCallback("Light FOV", onCommitLight, this);
+ childSetValidate("Light FOV", precommitValidate);
+ childSetCommitCallback("Light Focus", onCommitLight, this);
+ childSetValidate("Light Focus", precommitValidate);
+ childSetCommitCallback("Light Ambiance", onCommitLight, this);
+ childSetValidate("Light Ambiance", precommitValidate);
}
// Start with everyone disabled
@@ -125,8 +141,8 @@ BOOL LLPanelVolume::postBuild()
return TRUE;
}
-LLPanelVolume::LLPanelVolume(const std::string& name)
- : LLPanel(name)
+LLPanelVolume::LLPanelVolume()
+ : LLPanel()
{
setMouseOpaque(FALSE);
@@ -221,14 +237,32 @@ void LLPanelVolume::getState( )
LightColorSwatch->setValid( TRUE );
LightColorSwatch->set(volobjp->getLightBaseColor());
}
+
+ LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control");
+ if (LightTextureCtrl)
+ {
+ LightTextureCtrl->setEnabled(TRUE);
+ LightTextureCtrl->setValid(TRUE);
+ LightTextureCtrl->setImageAssetID(volobjp->getLightTextureID());
+ }
+
childSetEnabled("Light Intensity",true);
childSetEnabled("Light Radius",true);
childSetEnabled("Light Falloff",true);
+ childSetEnabled("Light FOV", true);
+ childSetEnabled("Light Focus", true);
+ childSetEnabled("Light Ambiance", true);
+
childSetValue("Light Intensity",volobjp->getLightIntensity());
childSetValue("Light Radius",volobjp->getLightRadius());
childSetValue("Light Falloff",volobjp->getLightFalloff());
+ LLVector3 params = volobjp->getSpotLightParams();
+ childSetValue("Light FOV", params.mV[0]);
+ childSetValue("Light Focus", params.mV[1]);
+ childSetValue("Light Ambiance", params.mV[2]);
+
mLightSavedColor = volobjp->getLightColor();
}
else
@@ -244,9 +278,20 @@ void LLPanelVolume::getState( )
LightColorSwatch->setEnabled( FALSE );
LightColorSwatch->setValid( FALSE );
}
+ LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control");
+ if (LightTextureCtrl)
+ {
+ LightTextureCtrl->setEnabled(FALSE);
+ LightTextureCtrl->setValid(FALSE);
+ }
+
childSetEnabled("Light Intensity",false);
childSetEnabled("Light Radius",false);
childSetEnabled("Light Falloff",false);
+
+ childSetEnabled("Light FOV",false);
+ childSetEnabled("Light Focus",false);
+ childSetEnabled("Light Ambiance",false);
}
// Flexible properties
@@ -317,7 +362,7 @@ void LLPanelVolume::getState( )
}
// static
-BOOL LLPanelVolume::precommitValidate( LLUICtrl* ctrl, void* userdata )
+bool LLPanelVolume::precommitValidate( const LLSD& data )
{
// TODO: Richard will fill this in later.
return TRUE; // FALSE means that validation failed and new value should not be commited.
@@ -336,6 +381,15 @@ void LLPanelVolume::refresh()
{
mRootObject = NULL;
}
+
+ BOOL visible = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 0 ? TRUE : FALSE;
+
+ childSetVisible("label texture", visible);
+ childSetVisible("Light FOV", visible);
+ childSetVisible("Light Focus", visible);
+ childSetVisible("Light Ambiance", visible);
+ childSetVisible("light texture control", visible);
+
}
@@ -362,6 +416,13 @@ void LLPanelVolume::clearCtrls()
LightColorSwatch->setEnabled( FALSE );
LightColorSwatch->setValid( FALSE );
}
+ LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control");
+ if(LightTextureCtrl)
+ {
+ LightTextureCtrl->setEnabled( FALSE );
+ LightTextureCtrl->setValid( FALSE );
+ }
+
childSetEnabled("Light Intensity",false);
childSetEnabled("Light Radius",false);
childSetEnabled("Light Falloff",false);
@@ -409,7 +470,7 @@ void LLPanelVolume::sendIsFlexible()
if (is_flexible)
{
- LLFirstUse::useFlexible();
+ //LLFirstUse::useFlexible();
if (objectp->getClickAction() == CLICK_ACTION_SIT)
{
@@ -427,21 +488,28 @@ void LLPanelVolume::sendIsFlexible()
llinfos << "update flexible sent" << llendl;
}
-void LLPanelVolume::onLightCancelColor(LLUICtrl* ctrl, void* userdata)
+void LLPanelVolume::onLightCancelColor(const LLSD& data)
{
- LLPanelVolume* self = (LLPanelVolume*) userdata;
- LLColorSwatchCtrl* LightColorSwatch = self->getChild<LLColorSwatchCtrl>("colorswatch");
+ LLColorSwatchCtrl* LightColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
if(LightColorSwatch)
{
- LightColorSwatch->setColor(self->mLightSavedColor);
+ LightColorSwatch->setColor(mLightSavedColor);
}
- onLightSelectColor(NULL, userdata);
+ onLightSelectColor(data);
}
-void LLPanelVolume::onLightSelectColor(LLUICtrl* ctrl, void* userdata)
+void LLPanelVolume::onLightCancelTexture(const LLSD& data)
{
- LLPanelVolume* self = (LLPanelVolume*) userdata;
- LLViewerObject* objectp = self->mObject;
+ LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control");
+ if (LightTextureCtrl)
+ {
+ LightTextureCtrl->setImageAssetID(mLightSavedTexture);
+ }
+}
+
+void LLPanelVolume::onLightSelectColor(const LLSD& data)
+{
+ LLViewerObject* objectp = mObject;
if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
{
return;
@@ -449,13 +517,31 @@ void LLPanelVolume::onLightSelectColor(LLUICtrl* ctrl, void* userdata)
LLVOVolume *volobjp = (LLVOVolume *)objectp;
- LLColorSwatchCtrl* LightColorSwatch = self->getChild<LLColorSwatchCtrl>("colorswatch");
+ LLColorSwatchCtrl* LightColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
if(LightColorSwatch)
{
LLColor4 clr = LightColorSwatch->get();
LLColor3 clr3( clr );
volobjp->setLightColor(clr3);
- self->mLightSavedColor = clr;
+ mLightSavedColor = clr;
+ }
+}
+
+void LLPanelVolume::onLightSelectTexture(const LLSD& data)
+{
+ if (mObject.isNull() || (mObject->getPCode() != LL_PCODE_VOLUME))
+ {
+ return;
+ }
+ LLVOVolume *volobjp = (LLVOVolume *) mObject.get();
+
+
+ LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control");
+ if(LightTextureCtrl)
+ {
+ LLUUID id = LightTextureCtrl->getImageAssetID();
+ volobjp->setLightTextureID(id);
+ mLightSavedTexture = id;
}
}
@@ -474,12 +560,47 @@ void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata )
volobjp->setLightIntensity((F32)self->childGetValue("Light Intensity").asReal());
volobjp->setLightRadius((F32)self->childGetValue("Light Radius").asReal());
volobjp->setLightFalloff((F32)self->childGetValue("Light Falloff").asReal());
+
LLColorSwatchCtrl* LightColorSwatch = self->getChild<LLColorSwatchCtrl>("colorswatch");
if(LightColorSwatch)
{
LLColor4 clr = LightColorSwatch->get();
volobjp->setLightColor(LLColor3(clr));
}
+
+ LLTextureCtrl* LightTextureCtrl = self->getChild<LLTextureCtrl>("light texture control");
+ if(LightTextureCtrl)
+ {
+ LLUUID id = LightTextureCtrl->getImageAssetID();
+ if (id.notNull())
+ {
+ if (volobjp->getLightTextureID().isNull())
+ { //this commit is making this a spot light, set UI to default params
+ volobjp->setLightTextureID(id);
+ LLVector3 spot_params = volobjp->getSpotLightParams();
+ self->childSetValue("Light FOV", spot_params.mV[0]);
+ self->childSetValue("Light Focus", spot_params.mV[1]);
+ self->childSetValue("Light Ambiance", spot_params.mV[2]);
+ }
+ else
+ { //modifying existing params
+ LLVector3 spot_params;
+ spot_params.mV[0] = (F32) self->childGetValue("Light FOV").asReal();
+ spot_params.mV[1] = (F32) self->childGetValue("Light Focus").asReal();
+ spot_params.mV[2] = (F32) self->childGetValue("Light Ambiance").asReal();
+ volobjp->setSpotLightParams(spot_params);
+ }
+ }
+ else if (volobjp->getLightTextureID().notNull())
+ { //no longer a spot light
+ volobjp->setLightTextureID(id);
+ //self->childDisable("Light FOV");
+ //self->childDisable("Light Focus");
+ //self->childDisable("Light Ambiance");
+ }
+ }
+
+
}
// static
diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h
index 841880b147..7bc935f986 100644
--- a/indra/newview/llpanelvolume.h
+++ b/indra/newview/llpanelvolume.h
@@ -35,7 +35,7 @@
#include "v3math.h"
#include "llpanel.h"
-#include "llmemory.h"
+#include "llpointer.h"
#include "llvolume.h"
class LLSpinCtrl;
@@ -45,13 +45,12 @@ class LLUICtrl;
class LLButton;
class LLViewerObject;
class LLComboBox;
-class LLPanelInventory;
class LLColorSwatchCtrl;
class LLPanelVolume : public LLPanel
{
public:
- LLPanelVolume(const std::string& name);
+ LLPanelVolume();
virtual ~LLPanelVolume();
virtual void draw();
@@ -64,15 +63,19 @@ public:
void sendIsLight();
void sendIsFlexible();
- static BOOL precommitValidate(LLUICtrl* ctrl,void* userdata);
+ static bool precommitValidate(const LLSD& data);
static void onCommitIsLight( LLUICtrl* ctrl, void* userdata);
static void onCommitLight( LLUICtrl* ctrl, void* userdata);
static void onCommitIsFlexible( LLUICtrl* ctrl, void* userdata);
static void onCommitFlexible( LLUICtrl* ctrl, void* userdata);
- static void onLightCancelColor(LLUICtrl* ctrl, void* userdata);
- static void onLightSelectColor(LLUICtrl* ctrl, void* userdata);
+ void onLightCancelColor(const LLSD& data);
+ void onLightSelectColor(const LLSD& data);
+
+ void onLightCancelTexture(const LLSD& data);
+ void onLightSelectTexture(const LLSD& data);
+
protected:
void getState();
@@ -99,6 +102,7 @@ protected:
*/
LLColor4 mLightSavedColor;
+ LLUUID mLightSavedTexture;
LLPointer<LLViewerObject> mObject;
LLPointer<LLViewerObject> mRootObject;
};
diff --git a/indra/newview/llpanelvolumepulldown.cpp b/indra/newview/llpanelvolumepulldown.cpp
new file mode 100644
index 0000000000..74e37efe4e
--- /dev/null
+++ b/indra/newview/llpanelvolumepulldown.cpp
@@ -0,0 +1,154 @@
+/**
+ * @file llpanelvolumepulldown.cpp
+ * @author Tofu Linden
+ * @brief A floater showing the master volume pull-down
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelvolumepulldown.h"
+
+// Viewer libs
+#include "llviewercontrol.h"
+#include "llstatusbar.h"
+
+// Linden libs
+#include "llbutton.h"
+#include "lltabcontainer.h"
+#include "llfloaterreg.h"
+#include "llfloaterpreference.h"
+#include "llslider.h"
+
+/* static */ const F32 LLPanelVolumePulldown::sAutoCloseFadeStartTimeSec = 4.0f;
+/* static */ const F32 LLPanelVolumePulldown::sAutoCloseTotalTimeSec = 5.0f;
+
+///----------------------------------------------------------------------------
+/// Class LLPanelVolumePulldown
+///----------------------------------------------------------------------------
+
+// Default constructor
+LLPanelVolumePulldown::LLPanelVolumePulldown()
+{
+ mCommitCallbackRegistrar.add("Vol.setControlFalse", boost::bind(&LLPanelVolumePulldown::setControlFalse, this, _2));
+ mCommitCallbackRegistrar.add("Vol.GoAudioPrefs", boost::bind(&LLPanelVolumePulldown::onAdvancedButtonClick, this, _2));
+ LLUICtrlFactory::instance().buildPanel(this, "panel_volume_pulldown.xml");
+}
+
+BOOL LLPanelVolumePulldown::postBuild()
+{
+ // set the initial volume-slider's position to reflect reality
+ LLSlider* volslider = getChild<LLSlider>( "mastervolume" );
+ volslider->setValue(gSavedSettings.getF32("AudioLevelMaster"));
+
+ return LLPanel::postBuild();
+}
+
+/*virtual*/
+void LLPanelVolumePulldown::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+ mHoverTimer.stop();
+ LLPanel::onMouseEnter(x,y,mask);
+}
+
+
+/*virtual*/
+void LLPanelVolumePulldown::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ mHoverTimer.start();
+ LLPanel::onMouseLeave(x,y,mask);
+}
+
+/*virtual*/
+void LLPanelVolumePulldown::handleVisibilityChange ( BOOL new_visibility )
+{
+ if (new_visibility)
+ {
+ mHoverTimer.start(); // timer will be stopped when mouse hovers over panel
+ gFocusMgr.setTopCtrl(this);
+ }
+ else
+ {
+ mHoverTimer.stop();
+ gFocusMgr.setTopCtrl(NULL);
+ }
+}
+
+/*virtual*/
+void LLPanelVolumePulldown::onTopLost()
+{
+ setVisible(FALSE);
+}
+
+void LLPanelVolumePulldown::onAdvancedButtonClick(const LLSD& user_data)
+{
+ // close the global volume minicontrol, we're bringing up the big one
+ setVisible(FALSE);
+
+ // bring up the prefs floater
+ LLFloaterPreference* prefsfloater = dynamic_cast<LLFloaterPreference*>
+ (LLFloaterReg::showInstance("preferences"));
+ if (prefsfloater)
+ {
+ // grab the 'audio' panel from the preferences floater and
+ // bring it the front!
+ LLTabContainer* tabcontainer = prefsfloater->getChild<LLTabContainer>("pref core");
+ LLPanel* audiopanel = prefsfloater->getChild<LLPanel>("audio");
+ if (tabcontainer && audiopanel)
+ {
+ tabcontainer->selectTabPanel(audiopanel);
+ }
+ }
+}
+
+void LLPanelVolumePulldown::setControlFalse(const LLSD& user_data)
+{
+ std::string control_name = user_data.asString();
+ LLControlVariable* control = findControl(control_name);
+
+ if (control)
+ control->set(LLSD(FALSE));
+}
+
+//virtual
+void LLPanelVolumePulldown::draw()
+{
+ F32 alpha = mHoverTimer.getStarted()
+ ? clamp_rescale(mHoverTimer.getElapsedTimeF32(), sAutoCloseFadeStartTimeSec, sAutoCloseTotalTimeSec, 1.f, 0.f)
+ : 1.0f;
+ LLViewDrawContext context(alpha);
+
+ LLPanel::draw();
+
+ if (alpha == 0.f)
+ {
+ setVisible(FALSE);
+ }
+}
+
diff --git a/indra/newview/llpanelvolumepulldown.h b/indra/newview/llpanelvolumepulldown.h
new file mode 100644
index 0000000000..9f20caa1a8
--- /dev/null
+++ b/indra/newview/llpanelvolumepulldown.h
@@ -0,0 +1,64 @@
+/**
+ * @file llpanelvolumepulldown.h
+ * @author Tofu Linden
+ * @brief A panel showing the master volume pull-down
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELVOLUMEPULLDOWN_H
+#define LL_LLPANELVOLUMEPULLDOWN_H
+
+#include "linden_common.h"
+
+#include "llpanel.h"
+
+class LLFrameTimer;
+
+class LLPanelVolumePulldown : public LLPanel
+{
+ public:
+ LLPanelVolumePulldown();
+ /*virtual*/ void draw();
+ /*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask);
+ /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
+ /*virtual*/ void handleVisibilityChange ( BOOL new_visibility );
+ /*virtual*/ void onTopLost();
+ /*virtual*/ BOOL postBuild();
+
+ private:
+ void setControlFalse(const LLSD& user_data);
+ void onAdvancedButtonClick(const LLSD& user_data);
+
+ LLFrameTimer mHoverTimer;
+ static const F32 sAutoCloseFadeStartTimeSec;
+ static const F32 sAutoCloseTotalTimeSec;
+};
+
+
+#endif // LL_LLPANELVOLUMEPULLDOWN_H
diff --git a/indra/newview/llparcelselection.h b/indra/newview/llparcelselection.h
index 5f26fafc33..0481bea6f7 100644
--- a/indra/newview/llparcelselection.h
+++ b/indra/newview/llparcelselection.h
@@ -33,7 +33,8 @@
#ifndef LLPARCELSELECTION_H
#define LLPARCELSELECTION_H
-#include "llmemory.h"
+#include "llrefcount.h"
+#include "llsafehandle.h"
class LLParcel;
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
new file mode 100644
index 0000000000..c0302eee9e
--- /dev/null
+++ b/indra/newview/llparticipantlist.cpp
@@ -0,0 +1,700 @@
+/**
+ * @file llparticipantlist.cpp
+ * @brief LLParticipantList intended to update view(LLAvatarList) according to incoming messages
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+// common includes
+#include "lltrans.h"
+#include "llavataractions.h"
+#include "llagent.h"
+
+#include "llparticipantlist.h"
+#include "llspeakers.h"
+#include "llviewermenu.h"
+#include "llvoiceclient.h"
+
+//LLParticipantList retrieves add, clear and remove events and updates view accordingly
+#if LL_MSVC
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
+#endif
+
+static const LLAvatarItemAgentOnTopComparator AGENT_ON_TOP_NAME_COMPARATOR;
+
+LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu/* = true*/,
+ bool exclude_agent /*= true*/):
+ mSpeakerMgr(data_source),
+ mAvatarList(avatar_list),
+ mSortOrder(E_SORT_BY_NAME)
+, mParticipantListMenu(NULL)
+, mExcludeAgent(exclude_agent)
+, mValidateSpeakerCallback(NULL)
+{
+ mSpeakerAddListener = new SpeakerAddListener(*this);
+ mSpeakerRemoveListener = new SpeakerRemoveListener(*this);
+ mSpeakerClearListener = new SpeakerClearListener(*this);
+ mSpeakerModeratorListener = new SpeakerModeratorUpdateListener(*this);
+ mSpeakerMuteListener = new SpeakerMuteListener(*this);
+
+ mSpeakerMgr->addListener(mSpeakerAddListener, "add");
+ mSpeakerMgr->addListener(mSpeakerRemoveListener, "remove");
+ mSpeakerMgr->addListener(mSpeakerClearListener, "clear");
+ mSpeakerMgr->addListener(mSpeakerModeratorListener, "update_moderator");
+
+ mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData"));
+ mAvatarListDoubleClickConnection = mAvatarList->setItemDoubleClickCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, _1));
+ mAvatarListRefreshConnection = mAvatarList->setRefreshCompleteCallback(boost::bind(&LLParticipantList::onAvatarListRefreshed, this, _1, _2));
+ // Set onAvatarListDoubleClicked as default on_return action.
+ mAvatarListReturnConnection = mAvatarList->setReturnCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList));
+
+ if (use_context_menu)
+ {
+ mParticipantListMenu = new LLParticipantListMenu(*this);
+ mAvatarList->setContextMenu(mParticipantListMenu);
+ }
+ else
+ {
+ mAvatarList->setContextMenu(NULL);
+ }
+
+ //Lets fill avatarList with existing speakers
+ LLSpeakerMgr::speaker_list_t speaker_list;
+ mSpeakerMgr->getSpeakerList(&speaker_list, true);
+ for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++)
+ {
+ const LLPointer<LLSpeaker>& speakerp = *it;
+
+ addAvatarIDExceptAgent(speakerp->mID);
+ if ( speakerp->mIsModerator )
+ {
+ mModeratorList.insert(speakerp->mID);
+ }
+ else
+ {
+ mModeratorToRemoveList.insert(speakerp->mID);
+ }
+ }
+ // we need to exclude agent id for non group chat
+ sort();
+}
+
+LLParticipantList::~LLParticipantList()
+{
+ mAvatarListDoubleClickConnection.disconnect();
+ mAvatarListRefreshConnection.disconnect();
+ mAvatarListReturnConnection.disconnect();
+
+ // It is possible Participant List will be re-created from LLCallFloater::onCurrentChannelChanged()
+ // See ticket EXT-3427
+ // hide menu before deleting it to stop enable and check handlers from triggering.
+ if(mParticipantListMenu && !LLApp::isExiting())
+ {
+ mParticipantListMenu->hide();
+ }
+
+ if (mParticipantListMenu)
+ {
+ delete mParticipantListMenu;
+ mParticipantListMenu = NULL;
+ }
+
+ mAvatarList->setContextMenu(NULL);
+}
+
+void LLParticipantList::setSpeakingIndicatorsVisible(BOOL visible)
+{
+ mAvatarList->setSpeakingIndicatorsVisible(visible);
+};
+
+void LLParticipantList::onAvatarListDoubleClicked(LLUICtrl* ctrl)
+{
+ LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(ctrl);
+ if(!item)
+ {
+ return;
+ }
+
+ LLUUID clicked_id = item->getAvatarId();
+
+ if (clicked_id.isNull() || clicked_id == gAgent.getID())
+ return;
+
+ LLAvatarActions::startIM(clicked_id);
+}
+
+void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param)
+{
+ LLAvatarList* list = dynamic_cast<LLAvatarList*>(ctrl);
+ if (list)
+ {
+ const std::string moderator_indicator(LLTrans::getString("IM_moderator_label"));
+ const std::size_t moderator_indicator_len = moderator_indicator.length();
+
+ // Firstly remove moderators indicator
+ std::set<LLUUID>::const_iterator
+ moderator_list_it = mModeratorToRemoveList.begin(),
+ moderator_list_end = mModeratorToRemoveList.end();
+ for (;moderator_list_it != moderator_list_end; ++moderator_list_it)
+ {
+ LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*> (list->getItemByValue(*moderator_list_it));
+ if ( item )
+ {
+ std::string name = item->getAvatarName();
+ size_t found = name.find(moderator_indicator);
+ if (found != std::string::npos)
+ {
+ name.erase(found, moderator_indicator_len);
+ item->setName(name);
+ }
+ }
+ }
+
+ mModeratorToRemoveList.clear();
+
+ // Add moderators indicator
+ moderator_list_it = mModeratorList.begin();
+ moderator_list_end = mModeratorList.end();
+ for (;moderator_list_it != moderator_list_end; ++moderator_list_it)
+ {
+ LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*> (list->getItemByValue(*moderator_list_it));
+ if ( item )
+ {
+ std::string name = item->getAvatarName();
+ size_t found = name.find(moderator_indicator);
+ if (found == std::string::npos)
+ {
+ name += " ";
+ name += moderator_indicator;
+ item->setName(name);
+ }
+ }
+ }
+ }
+}
+
+void LLParticipantList::setSortOrder(EParticipantSortOrder order)
+{
+ if ( mSortOrder != order )
+ {
+ mSortOrder = order;
+ sort();
+ }
+}
+
+LLParticipantList::EParticipantSortOrder LLParticipantList::getSortOrder()
+{
+ return mSortOrder;
+}
+
+void LLParticipantList::setValidateSpeakerCallback(validate_speaker_callback_t cb)
+{
+ mValidateSpeakerCallback = cb;
+}
+
+void LLParticipantList::updateRecentSpeakersOrder()
+{
+ if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder())
+ {
+ // Need to update speakers to sort list correctly
+ mSpeakerMgr->update(true);
+ // Resort avatar list
+ sort();
+ }
+}
+
+bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
+{
+ LLUUID uu_id = event->getValue().asUUID();
+
+ if (mValidateSpeakerCallback && !mValidateSpeakerCallback(uu_id))
+ {
+ return true;
+ }
+
+ addAvatarIDExceptAgent(uu_id);
+ sort();
+ return true;
+}
+
+bool LLParticipantList::onRemoveItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
+{
+ LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs();
+ LLAvatarList::uuid_vector_t::iterator pos = std::find(group_members.begin(), group_members.end(), event->getValue().asUUID());
+ if(pos != group_members.end())
+ {
+ group_members.erase(pos);
+ mAvatarList->setDirty();
+ }
+ return true;
+}
+
+bool LLParticipantList::onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
+{
+ LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs();
+ group_members.clear();
+ mAvatarList->setDirty();
+ return true;
+}
+
+bool LLParticipantList::onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
+{
+ const LLSD& evt_data = event->getValue();
+ if ( evt_data.has("id") && evt_data.has("is_moderator") )
+ {
+ LLUUID id = evt_data["id"];
+ bool is_moderator = evt_data["is_moderator"];
+ if ( id.notNull() )
+ {
+ if ( is_moderator )
+ mModeratorList.insert(id);
+ else
+ {
+ std::set<LLUUID>::iterator it = mModeratorList.find (id);
+ if ( it != mModeratorList.end () )
+ {
+ mModeratorToRemoveList.insert(id);
+ mModeratorList.erase(id);
+ }
+ }
+
+ // apply changes immediately
+ onAvatarListRefreshed(mAvatarList, LLSD());
+ }
+ }
+ return true;
+}
+
+bool LLParticipantList::onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
+{
+ LLPointer<LLSpeaker> speakerp = (LLSpeaker*)event->getSource();
+ if (speakerp.isNull()) return false;
+
+ // update UI on confirmation of moderator mutes
+ if (event->getValue().asString() == "voice")
+ {
+ LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(mAvatarList->getItemByValue(speakerp->mID));
+ if (item)
+ {
+ LLOutputMonitorCtrl* indicator = item->getChild<LLOutputMonitorCtrl>("speaking_indicator");
+ indicator->setIsMuted(speakerp->mModeratorMutedVoice);
+ }
+ }
+ return true;
+}
+
+void LLParticipantList::sort()
+{
+ if ( !mAvatarList )
+ return;
+
+ switch ( mSortOrder ) {
+ case E_SORT_BY_NAME :
+ // if mExcludeAgent == true , then no need to keep agent on top of the list
+ if(mExcludeAgent)
+ {
+ mAvatarList->sortByName();
+ }
+ else
+ {
+ mAvatarList->setComparator(&AGENT_ON_TOP_NAME_COMPARATOR);
+ mAvatarList->sort();
+ }
+ break;
+ case E_SORT_BY_RECENT_SPEAKERS:
+ if (mSortByRecentSpeakers.isNull())
+ mSortByRecentSpeakers = new LLAvatarItemRecentSpeakerComparator(*this);
+ mAvatarList->setComparator(mSortByRecentSpeakers.get());
+ mAvatarList->sort();
+ break;
+ default :
+ llwarns << "Unrecognized sort order for " << mAvatarList->getName() << llendl;
+ return;
+ }
+}
+
+void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)
+{
+ if (mExcludeAgent && gAgent.getID() == avatar_id) return;
+ if (mAvatarList->contains(avatar_id)) return;
+
+ mAvatarList->getIDs().push_back(avatar_id);
+ mAvatarList->setDirty();
+ adjustParticipant(avatar_id);
+}
+
+void LLParticipantList::adjustParticipant(const LLUUID& speaker_id)
+{
+ LLPointer<LLSpeaker> speakerp = mSpeakerMgr->findSpeaker(speaker_id);
+ if (speakerp.isNull()) return;
+
+ // add listener to process moderation changes
+ speakerp->addListener(mSpeakerMuteListener);
+}
+
+//
+// LLParticipantList::SpeakerAddListener
+//
+bool LLParticipantList::SpeakerAddListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
+{
+ /**
+ * We need to filter speaking objects. These objects shouldn't appear in the list
+ * @see LLFloaterChat::addChat() in llviewermessage.cpp to get detailed call hierarchy
+ */
+ const LLUUID& speaker_id = event->getValue().asUUID();
+ LLPointer<LLSpeaker> speaker = mParent.mSpeakerMgr->findSpeaker(speaker_id);
+ if(speaker.isNull() || speaker->mType == LLSpeaker::SPEAKER_OBJECT)
+ {
+ return false;
+ }
+ return mParent.onAddItemEvent(event, userdata);
+}
+
+//
+// LLParticipantList::SpeakerRemoveListener
+//
+bool LLParticipantList::SpeakerRemoveListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
+{
+ return mParent.onRemoveItemEvent(event, userdata);
+}
+
+//
+// LLParticipantList::SpeakerClearListener
+//
+bool LLParticipantList::SpeakerClearListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
+{
+ return mParent.onClearListEvent(event, userdata);
+}
+
+//
+// LLParticipantList::SpeakerModeratorListener
+//
+bool LLParticipantList::SpeakerModeratorUpdateListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
+{
+ return mParent.onModeratorUpdateEvent(event, userdata);
+}
+
+bool LLParticipantList::SpeakerMuteListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
+{
+ return mParent.onSpeakerMuteEvent(event, userdata);
+}
+
+LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()
+{
+ // set up the callbacks for all of the avatar menu items
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+
+ registrar.add("ParticipantList.Sort", boost::bind(&LLParticipantList::LLParticipantListMenu::sortParticipantList, this, _2));
+ registrar.add("ParticipantList.ToggleAllowTextChat", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleAllowTextChat, this, _2));
+ registrar.add("ParticipantList.ToggleMuteText", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleMuteText, this, _2));
+
+ registrar.add("Avatar.Profile", boost::bind(&LLAvatarActions::showProfile, mUUIDs.front()));
+ registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startIM, mUUIDs.front()));
+ registrar.add("Avatar.AddFriend", boost::bind(&LLAvatarActions::requestFriendshipDialog, mUUIDs.front()));
+ registrar.add("Avatar.BlockUnblock", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleMuteVoice, this, _2));
+ registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::share, mUUIDs.front()));
+ registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, mUUIDs.front()));
+ registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startCall, mUUIDs.front()));
+
+ registrar.add("ParticipantList.ModerateVoice", boost::bind(&LLParticipantList::LLParticipantListMenu::moderateVoice, this, _2));
+
+ enable_registrar.add("ParticipantList.EnableItem", boost::bind(&LLParticipantList::LLParticipantListMenu::enableContextMenuItem, this, _2));
+ enable_registrar.add("ParticipantList.CheckItem", boost::bind(&LLParticipantList::LLParticipantListMenu::checkContextMenuItem, this, _2));
+
+ // create the context menu from the XUI
+ LLContextMenu* main_menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
+ "menu_participant_list.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
+
+ // Don't show sort options for P2P chat
+ bool is_sort_visible = (mParent.mAvatarList && mParent.mAvatarList->size() > 1);
+ main_menu->setItemVisible("SortByName", is_sort_visible);
+ main_menu->setItemVisible("SortByRecentSpeakers", is_sort_visible);
+ main_menu->setItemVisible("Moderator Options", isGroupModerator());
+ main_menu->arrangeAndClear();
+
+ return main_menu;
+}
+
+void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const std::vector<LLUUID>& uuids, S32 x, S32 y)
+{
+ LLPanelPeopleMenus::ContextMenu::show(spawning_view, uuids, x, y);
+
+ if (uuids.size() == 0) return;
+
+ const LLUUID speaker_id = mUUIDs.front();
+ BOOL is_muted = isMuted(speaker_id);
+
+ if (is_muted)
+ {
+ LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceMuteSelected", false);
+ LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceMuteOthers", false);
+ }
+ else
+ {
+ LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteSelected", false);
+ LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteOthers", false);
+ }
+}
+
+void LLParticipantList::LLParticipantListMenu::sortParticipantList(const LLSD& userdata)
+{
+ std::string param = userdata.asString();
+ if ("sort_by_name" == param)
+ {
+ mParent.setSortOrder(E_SORT_BY_NAME);
+ }
+ else if ("sort_by_recent_speakers" == param)
+ {
+ mParent.setSortOrder(E_SORT_BY_RECENT_SPEAKERS);
+ }
+}
+
+void LLParticipantList::LLParticipantListMenu::toggleAllowTextChat(const LLSD& userdata)
+{
+
+ LLIMSpeakerMgr* mgr = dynamic_cast<LLIMSpeakerMgr*>(mParent.mSpeakerMgr);
+ if (mgr)
+ {
+ const LLUUID speaker_id = mUUIDs.front();
+ mgr->toggleAllowTextChat(speaker_id);
+ }
+}
+
+void LLParticipantList::LLParticipantListMenu::toggleMute(const LLSD& userdata, U32 flags)
+{
+ const LLUUID speaker_id = mUUIDs.front();
+ BOOL is_muted = LLMuteList::getInstance()->isMuted(speaker_id, flags);
+ std::string name;
+
+ //fill in name using voice client's copy of name cache
+ LLPointer<LLSpeaker> speakerp = mParent.mSpeakerMgr->findSpeaker(speaker_id);
+ if (speakerp.isNull())
+ {
+ return;
+ }
+
+ name = speakerp->mDisplayName;
+
+ LLMute mute(speaker_id, name, speakerp->mType == LLSpeaker::SPEAKER_AGENT ? LLMute::AGENT : LLMute::OBJECT);
+
+ if (!is_muted)
+ {
+ LLMuteList::getInstance()->add(mute, flags);
+ }
+ else
+ {
+ LLMuteList::getInstance()->remove(mute, flags);
+ }
+}
+
+void LLParticipantList::LLParticipantListMenu::toggleMuteText(const LLSD& userdata)
+{
+ toggleMute(userdata, LLMute::flagTextChat);
+}
+
+void LLParticipantList::LLParticipantListMenu::toggleMuteVoice(const LLSD& userdata)
+{
+ toggleMute(userdata, LLMute::flagVoiceChat);
+}
+
+bool LLParticipantList::LLParticipantListMenu::isGroupModerator()
+{
+ // Agent is in Group Call
+ if(gAgent.isInGroup(mParent.mSpeakerMgr->getSessionID()))
+ {
+ // Agent is Moderator
+ return mParent.mSpeakerMgr->findSpeaker(gAgentID)->mIsModerator;
+ }
+ return false;
+}
+
+bool LLParticipantList::LLParticipantListMenu::isMuted(const LLUUID& avatar_id)
+{
+ LLPointer<LLSpeaker> selected_speakerp = mParent.mSpeakerMgr->findSpeaker(avatar_id);
+ if (!selected_speakerp) return true;
+
+ return selected_speakerp->mStatus == LLSpeaker::STATUS_MUTED;
+}
+
+void LLParticipantList::LLParticipantListMenu::moderateVoice(const LLSD& userdata)
+{
+ if (!gAgent.getRegion()) return;
+
+ bool moderate_selected = userdata.asString() == "selected";
+ const LLUUID& selected_avatar_id = mUUIDs.front();
+ bool is_muted = isMuted(selected_avatar_id);
+
+ if (moderate_selected)
+ {
+ moderateVoiceParticipant(selected_avatar_id, is_muted);
+ }
+ else
+ {
+ moderateVoiceOtherParticipants(selected_avatar_id, is_muted);
+ }
+}
+
+void LLParticipantList::LLParticipantListMenu::moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute)
+{
+ LLIMSpeakerMgr* mgr = dynamic_cast<LLIMSpeakerMgr*>(mParent.mSpeakerMgr);
+ if (mgr)
+ {
+ mgr->moderateVoiceParticipant(avatar_id, unmute);
+ }
+}
+
+void LLParticipantList::LLParticipantListMenu::moderateVoiceOtherParticipants(const LLUUID& excluded_avatar_id, bool unmute)
+{
+ LLIMSpeakerMgr* mgr = dynamic_cast<LLIMSpeakerMgr*>(mParent.mSpeakerMgr);
+ if (mgr)
+ {
+ mgr->moderateVoiceOtherParticipants(excluded_avatar_id, unmute);
+ }
+}
+
+bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD& userdata)
+{
+ std::string item = userdata.asString();
+ if (item == "can_mute_text" || "can_block" == item || "can_share" == item || "can_im" == item)
+ {
+ return mUUIDs.front() != gAgentID;
+ }
+ else if (item == "can_allow_text_chat")
+ {
+ return isGroupModerator();
+ }
+ else if ("can_moderate_voice" == item)
+ {
+ if (isGroupModerator())
+ {
+ LLPointer<LLSpeaker> speakerp = mParent.mSpeakerMgr->findSpeaker(mUUIDs.front());
+ if (speakerp.notNull())
+ {
+ // not in voice participants can not be moderated
+ return speakerp->isInVoiceChannel();
+ }
+ }
+ return false;
+ }
+ else if (item == std::string("can_add"))
+ {
+ // We can add friends if:
+ // - there are selected people
+ // - and there are no friends among selection yet.
+
+ bool result = (mUUIDs.size() > 0);
+
+ std::vector<LLUUID>::const_iterator
+ id = mUUIDs.begin(),
+ uuids_end = mUUIDs.end();
+
+ for (;id != uuids_end; ++id)
+ {
+ if ( LLAvatarActions::isFriend(*id) )
+ {
+ result = false;
+ break;
+ }
+ }
+ return result;
+ }
+ else if (item == "can_call")
+ {
+ return LLVoiceClient::voiceEnabled()&&gVoiceClient->voiceWorking();
+ }
+
+ return true;
+}
+
+bool LLParticipantList::LLParticipantListMenu::checkContextMenuItem(const LLSD& userdata)
+{
+ std::string item = userdata.asString();
+ const LLUUID& id = mUUIDs.front();
+
+ if (item == "is_muted")
+ {
+ return LLMuteList::getInstance()->isMuted(id, LLMute::flagTextChat);
+ }
+ else if (item == "is_allowed_text_chat")
+ {
+ LLPointer<LLSpeaker> selected_speakerp = mParent.mSpeakerMgr->findSpeaker(id);
+
+ if (selected_speakerp.notNull())
+ {
+ return !selected_speakerp->mModeratorMutedText;
+ }
+ }
+ else if(item == "is_blocked")
+ {
+ return LLMuteList::getInstance()->isMuted(id, LLMute::flagVoiceChat);
+ }
+ else if(item == "is_sorted_by_name")
+ {
+ return E_SORT_BY_NAME == mParent.mSortOrder;
+ }
+ else if(item == "is_sorted_by_recent_speakers")
+ {
+ return E_SORT_BY_RECENT_SPEAKERS == mParent.mSortOrder;
+ }
+
+ return false;
+}
+
+bool LLParticipantList::LLAvatarItemRecentSpeakerComparator::doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const
+{
+ if (mParent.mSpeakerMgr)
+ {
+ LLPointer<LLSpeaker> lhs = mParent.mSpeakerMgr->findSpeaker(avatar_item1->getAvatarId());
+ LLPointer<LLSpeaker> rhs = mParent.mSpeakerMgr->findSpeaker(avatar_item2->getAvatarId());
+ if ( lhs.notNull() && rhs.notNull() )
+ {
+ // Compare by last speaking time
+ if( lhs->mLastSpokeTime != rhs->mLastSpokeTime )
+ return ( lhs->mLastSpokeTime > rhs->mLastSpokeTime );
+ else if ( lhs->mSortIndex != rhs->mSortIndex )
+ return ( lhs->mSortIndex < rhs->mSortIndex );
+ }
+ else if ( lhs.notNull() )
+ {
+ // True if only avatar_item1 speaker info available
+ return true;
+ }
+ else if ( rhs.notNull() )
+ {
+ // False if only avatar_item2 speaker info available
+ return false;
+ }
+ }
+ // By default compare by name.
+ return LLAvatarItemNameComparator::doCompare(avatar_item1, avatar_item2);
+}
+
+//EOF
diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h
new file mode 100644
index 0000000000..e1b1b5af00
--- /dev/null
+++ b/indra/newview/llparticipantlist.h
@@ -0,0 +1,274 @@
+/**
+ * @file llparticipantlist.h
+ * @brief LLParticipantList intended to update view(LLAvatarList) according to incoming messages
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llevent.h"
+#include "llpanelpeoplemenus.h"
+#include "llavatarlist.h" // for LLAvatarItemRecentSpeakerComparator
+
+class LLSpeakerMgr;
+class LLAvatarList;
+class LLUICtrl;
+
+class LLParticipantList
+{
+ LOG_CLASS(LLParticipantList);
+ public:
+
+ typedef boost::function<bool (const LLUUID& speaker_id)> validate_speaker_callback_t;
+
+ LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu = true, bool exclude_agent = true);
+ ~LLParticipantList();
+ void setSpeakingIndicatorsVisible(BOOL visible);
+
+ typedef enum e_participant_sort_oder {
+ E_SORT_BY_NAME = 0,
+ E_SORT_BY_RECENT_SPEAKERS = 1,
+ } EParticipantSortOrder;
+
+ /**
+ * Adds specified avatar ID to the existing list if it is not Agent's ID
+ *
+ * @param[in] avatar_id - Avatar UUID to be added into the list
+ */
+ void addAvatarIDExceptAgent(const LLUUID& avatar_id);
+
+ /**
+ * Set and sort Avatarlist by given order
+ */
+ void setSortOrder(EParticipantSortOrder order = E_SORT_BY_NAME);
+ EParticipantSortOrder getSortOrder();
+
+ /**
+ * Refreshes the participant list if it's in sort by recent speaker order.
+ */
+ void updateRecentSpeakersOrder();
+
+ /**
+ * Set a callback to be called before adding a speaker. Invalid speakers will not be added.
+ *
+ * If the callback is unset all speakers are considered as valid.
+ *
+ * @see onAddItemEvent()
+ */
+ void setValidateSpeakerCallback(validate_speaker_callback_t cb);
+
+ protected:
+ /**
+ * LLSpeakerMgr event handlers
+ */
+ bool onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ bool onRemoveItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ bool onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ bool onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ bool onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+
+ /**
+ * Sorts the Avatarlist by stored order
+ */
+ void sort();
+
+ //List of listeners implementing LLOldEvents::LLSimpleListener.
+ //There is no way to handle all the events in one listener as LLSpeakerMgr registers listeners in such a way
+ //that one listener can handle only one type of event
+ class BaseSpeakerListner : public LLOldEvents::LLSimpleListener
+ {
+ public:
+ BaseSpeakerListner(LLParticipantList& parent) : mParent(parent) {}
+ protected:
+ LLParticipantList& mParent;
+ };
+
+ class SpeakerAddListener : public BaseSpeakerListner
+ {
+ public:
+ SpeakerAddListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {}
+ /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ };
+
+ class SpeakerRemoveListener : public BaseSpeakerListner
+ {
+ public:
+ SpeakerRemoveListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {}
+ /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ };
+
+ class SpeakerClearListener : public BaseSpeakerListner
+ {
+ public:
+ SpeakerClearListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {}
+ /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ };
+
+ class SpeakerModeratorUpdateListener : public BaseSpeakerListner
+ {
+ public:
+ SpeakerModeratorUpdateListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {}
+ /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ };
+
+ class SpeakerMuteListener : public BaseSpeakerListner
+ {
+ public:
+ SpeakerMuteListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {}
+
+ /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ };
+
+ /**
+ * Menu used in the participant list.
+ */
+ class LLParticipantListMenu : public LLPanelPeopleMenus::ContextMenu
+ {
+ public:
+ LLParticipantListMenu(LLParticipantList& parent):mParent(parent){};
+ /*virtual*/ LLContextMenu* createMenu();
+ /*virtual*/ void show(LLView* spawning_view, const std::vector<LLUUID>& uuids, S32 x, S32 y);
+ protected:
+ LLParticipantList& mParent;
+ private:
+ bool enableContextMenuItem(const LLSD& userdata);
+ bool checkContextMenuItem(const LLSD& userdata);
+
+ void sortParticipantList(const LLSD& userdata);
+ void toggleAllowTextChat(const LLSD& userdata);
+ void toggleMute(const LLSD& userdata, U32 flags);
+ void toggleMuteText(const LLSD& userdata);
+ void toggleMuteVoice(const LLSD& userdata);
+
+ /**
+ * Return true if Agent is group moderator(and moderator of group call).
+ */
+ bool isGroupModerator();
+
+ // Voice moderation support
+ /**
+ * Check whether specified by argument avatar is muted for group chat or not.
+ */
+ bool isMuted(const LLUUID& avatar_id);
+
+ /**
+ * Processes Voice moderation menu items.
+ *
+ * It calls either moderateVoiceParticipant() or moderateVoiceParticipant() depend on
+ * passed parameter.
+ *
+ * @param userdata can be "selected" or "others".
+ *
+ * @see moderateVoiceParticipant()
+ * @see moderateVoiceOtherParticipants()
+ */
+ void moderateVoice(const LLSD& userdata);
+
+ /**
+ * Mutes/Unmutes avatar for current group voice chat.
+ *
+ * It only marks avatar as muted for session and does not use local Agent's Block list.
+ * It does not mute Agent itself.
+ *
+ * @param[in] avatar_id UUID of avatar to be processed
+ * @param[in] unmute if true - specified avatar will be muted, otherwise - unmuted.
+ *
+ * @see moderateVoiceOtherParticipants()
+ */
+ void moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute);
+
+ /**
+ * Mutes/Unmutes all avatars except specified for current group voice chat.
+ *
+ * It only marks avatars as muted for session and does not use local Agent's Block list.
+ * It based call moderateVoiceParticipant() for each avatar should be muted/unmuted.
+ *
+ * @param[in] excluded_avatar_id UUID of avatar NOT to be processed
+ * @param[in] unmute if true - avatars will be muted, otherwise - unmuted.
+ *
+ * @see moderateVoiceParticipant()
+ */
+ void moderateVoiceOtherParticipants(const LLUUID& excluded_avatar_id, bool unmute);
+ };
+
+ /**
+ * Comparator for comparing avatar items by last spoken time
+ */
+ class LLAvatarItemRecentSpeakerComparator : public LLAvatarItemNameComparator, public LLRefCount
+ {
+ LOG_CLASS(LLAvatarItemRecentSpeakerComparator);
+ public:
+ LLAvatarItemRecentSpeakerComparator(LLParticipantList& parent):mParent(parent){};
+ virtual ~LLAvatarItemRecentSpeakerComparator() {};
+ protected:
+ virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const;
+ private:
+ LLParticipantList& mParent;
+ };
+
+ private:
+ void onAvatarListDoubleClicked(LLUICtrl* ctrl);
+ void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param);
+
+ /**
+ * Adjusts passed participant to work properly.
+ *
+ * Adds SpeakerMuteListener to process moderation actions.
+ */
+ void adjustParticipant(const LLUUID& speaker_id);
+
+ LLSpeakerMgr* mSpeakerMgr;
+ LLAvatarList* mAvatarList;
+
+ std::set<LLUUID> mModeratorList;
+ std::set<LLUUID> mModeratorToRemoveList;
+
+ LLPointer<SpeakerAddListener> mSpeakerAddListener;
+ LLPointer<SpeakerRemoveListener> mSpeakerRemoveListener;
+ LLPointer<SpeakerClearListener> mSpeakerClearListener;
+ LLPointer<SpeakerModeratorUpdateListener> mSpeakerModeratorListener;
+ LLPointer<SpeakerMuteListener> mSpeakerMuteListener;
+
+ LLParticipantListMenu* mParticipantListMenu;
+
+ EParticipantSortOrder mSortOrder;
+ /*
+ * This field manages an adding a new avatar_id in the mAvatarList
+ * If true, then agent_id wont be added into mAvatarList
+ * Also by default this field is controlling a sort procedure, @c sort()
+ */
+ bool mExcludeAgent;
+
+ // boost::connections
+ boost::signals2::connection mAvatarListDoubleClickConnection;
+ boost::signals2::connection mAvatarListRefreshConnection;
+ boost::signals2::connection mAvatarListReturnConnection;
+
+ LLPointer<LLAvatarItemRecentSpeakerComparator> mSortByRecentSpeakers;
+ validate_speaker_callback_t mValidateSpeakerCallback;
+};
diff --git a/indra/newview/llplacesinventorybridge.cpp b/indra/newview/llplacesinventorybridge.cpp
new file mode 100644
index 0000000000..83443687c9
--- /dev/null
+++ b/indra/newview/llplacesinventorybridge.cpp
@@ -0,0 +1,201 @@
+/**
+ * @file llplacesinventorybridge.cpp
+ * @brief Implementation of the Inventory-Folder-View-Bridge classes for Places Panel.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llmenugl.h"
+
+#include "llplacesinventorybridge.h"
+
+#include "llfloaterinventory.h" // for LLInventoryPanel
+#include "llfolderview.h" // for FIRST_SELECTED_ITEM
+#include "llinventorypanel.h"
+
+
+static const std::string LANDMARKS_INVENTORY_LIST_NAME("landmarks_list");
+
+bool is_landmarks_panel(const LLInventoryPanel* inv_panel)
+{
+ if (NULL == inv_panel)
+ return false;
+ return inv_panel->getName() == LANDMARKS_INVENTORY_LIST_NAME;
+}
+
+void fill_items_with_menu_items(std::vector<std::string>& items, LLMenuGL& menu)
+{
+ LLView::child_list_const_iter_t itor;
+ for (itor = menu.beginChild(); itor != menu.endChild(); ++itor)
+ {
+ std::string name = (*itor)->getName();
+ items.push_back(name);
+ }
+}
+
+// virtual
+void LLPlacesLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ fill_items_with_menu_items(items, menu);
+
+ // Disabled items are processed via LLLandmarksPanel::isActionEnabled()
+ // they should be synchronized with Places/My Landmarks/Gear menu. See EXT-1601
+ }
+
+ hide_context_entries(menu, items, disabled_items);
+}
+
+
+
+void LLPlacesFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ {
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ LLInventoryPanel* inv_panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ bool is_open = false;
+ if (inv_panel)
+ {
+ LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getRootFolder()->getItemByID(mUUID));
+ is_open = (NULL != folder) && folder->isOpen();
+ }
+
+ // collect all items' names
+ fill_items_with_menu_items(items, menu);
+
+ // remove expand or collapse menu item depend on folder state
+ std::string collapse_expand_item_to_hide(is_open ? "expand" : "collapse");
+ std::vector<std::string>::iterator it = std::find(items.begin(), items.end(), collapse_expand_item_to_hide);
+ if (it != items.end()) items.erase(it);
+
+ // Disabled items are processed via LLLandmarksPanel::isActionEnabled()
+ // they should be synchronized with Places/My Landmarks/Gear menu. See EXT-1601
+
+ // repeat parent functionality
+ sSelf = this; // necessary for "New Folder" functionality
+
+ hide_context_entries(menu, items, disabled_items);
+ }
+}
+
+//virtual
+void LLPlacesFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("expand" == action)
+ {
+ LLFolderViewFolder* act_folder = getFolder();
+ act_folder->toggleOpen();
+ }
+ else if ("collapse" == action)
+ {
+ LLFolderViewFolder* act_folder = getFolder();
+ act_folder->toggleOpen();
+ }
+ else
+ {
+ LLFolderBridge::performAction(folder, model, action);
+ }
+}
+
+LLFolderViewFolder* LLPlacesFolderBridge::getFolder()
+{
+ LLFolderViewFolder* folder = NULL;
+ LLInventoryPanel* inv_panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ if (inv_panel)
+ {
+ folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getRootFolder()->getItemByID(mUUID));
+ }
+
+ return folder;
+}
+
+// virtual
+LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge(
+ LLAssetType::EType asset_type,
+ LLAssetType::EType actual_asset_type,
+ LLInventoryType::EType inv_type,
+ LLInventoryPanel* inventory,
+ const LLUUID& uuid,
+ U32 flags/* = 0x00*/) const
+{
+ LLInvFVBridge* new_listener = NULL;
+ switch(asset_type)
+ {
+ case LLAssetType::AT_LANDMARK:
+ if(!(inv_type == LLInventoryType::IT_LANDMARK))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLPlacesLandmarkBridge(inv_type, inventory, uuid, flags);
+ break;
+ case LLAssetType::AT_CATEGORY:
+ if (actual_asset_type == LLAssetType::AT_LINK_FOLDER)
+ {
+ // *TODO: Create a link folder handler instead if it is necessary
+ new_listener = LLInventoryFVBridgeBuilder::createBridge(
+ asset_type,
+ actual_asset_type,
+ inv_type,
+ inventory,
+ uuid,
+ flags);
+ break;
+ }
+ new_listener = new LLPlacesFolderBridge(inv_type, inventory, uuid);
+ break;
+ default:
+ new_listener = LLInventoryFVBridgeBuilder::createBridge(
+ asset_type,
+ actual_asset_type,
+ inv_type,
+ inventory,
+ uuid,
+ flags);
+ }
+ return new_listener;
+}
+
+// EOF
diff --git a/indra/newview/llplacesinventorybridge.h b/indra/newview/llplacesinventorybridge.h
new file mode 100644
index 0000000000..66a8e8e54d
--- /dev/null
+++ b/indra/newview/llplacesinventorybridge.h
@@ -0,0 +1,91 @@
+/**
+ * @file llplacesinventorybridge.h
+ * @brief Declaration of the Inventory-Folder-View-Bridge classes for Places Panel.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPLACESINVENTORYBRIDGE_H
+#define LL_LLPLACESINVENTORYBRIDGE_H
+
+#include "llinventorybridge.h"
+
+class LLFolderViewFolder;
+
+/**
+ * Overridden version of the Inventory-Folder-View-Bridge for Places Panel (Landmarks Tab)
+ */
+class LLPlacesLandmarkBridge : public LLLandmarkBridge
+{
+ friend class LLPlacesInventoryBridgeBuilder;
+
+public:
+ /*virtual*/ void buildContextMenu(LLMenuGL& menu, U32 flags);
+
+protected:
+ LLPlacesLandmarkBridge(LLInventoryType::EType type, LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags = 0x00)
+ : LLLandmarkBridge(inventory, uuid, flags) {mInvType = type;}
+};
+
+/**
+ * Overridden version of the Inventory-Folder-View-Bridge for Folders
+ */
+class LLPlacesFolderBridge : public LLFolderBridge
+{
+ friend class LLPlacesInventoryBridgeBuilder;
+
+public:
+ /*virtual*/ void buildContextMenu(LLMenuGL& menu, U32 flags);
+ /*virtual*/ void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action);
+
+protected:
+ LLPlacesFolderBridge(LLInventoryType::EType type, LLInventoryPanel* inventory, const LLUUID& uuid)
+ : LLFolderBridge(inventory, uuid) {mInvType = type;}
+
+ LLFolderViewFolder* getFolder();
+};
+
+
+/**
+ * This class intended to override default InventoryBridgeBuilder for Inventory Panel.
+ *
+ * It builds Bridges for Landmarks and Folders in Places Landmarks Panel
+ */
+class LLPlacesInventoryBridgeBuilder : public LLInventoryFVBridgeBuilder
+{
+public:
+ /*virtual*/ LLInvFVBridge* createBridge(
+ LLAssetType::EType asset_type,
+ LLAssetType::EType actual_asset_type,
+ LLInventoryType::EType inv_type,
+ LLInventoryPanel* inventory,
+ const LLUUID& uuid,
+ U32 flags = 0x00) const;
+};
+
+#endif // LL_LLPLACESINVENTORYBRIDGE_H
diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp
new file mode 100644
index 0000000000..4de953a59d
--- /dev/null
+++ b/indra/newview/llplacesinventorypanel.cpp
@@ -0,0 +1,191 @@
+/**
+ * @file llplacesinventorypanel.cpp
+ * @brief LLPlacesInventoryPanel class definition
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llscrollcontainer.h"
+
+#include "llplacesinventorypanel.h"
+
+#include "llfoldervieweventlistener.h"
+#include "llinventorybridge.h"
+#include "llinventoryfunctions.h"
+#include "llpanellandmarks.h"
+#include "llplacesinventorybridge.h"
+
+static LLDefaultChildRegistry::Register<LLPlacesInventoryPanel> r("places_inventory_panel");
+
+static const LLPlacesInventoryBridgeBuilder PLACES_INVENTORY_BUILDER;
+
+LLPlacesInventoryPanel::LLPlacesInventoryPanel(const Params& p) :
+ LLInventoryPanel(p),
+ mSavedFolderState(NULL)
+
+{
+ mInvFVBridgeBuilder = &PLACES_INVENTORY_BUILDER;
+ mSavedFolderState = new LLSaveFolderState();
+ mSavedFolderState->setApply(FALSE);
+}
+
+
+LLPlacesInventoryPanel::~LLPlacesInventoryPanel()
+{
+ delete mSavedFolderState;
+}
+
+BOOL LLPlacesInventoryPanel::postBuild()
+{
+ LLInventoryPanel::postBuild();
+
+ // clear Contents();
+ {
+ mFolders->destroyView();
+ mFolders->getParent()->removeChild(mFolders);
+ mFolders->die();
+
+ if( mScroller )
+ {
+ removeChild( mScroller );
+ mScroller->die();
+ mScroller = NULL;
+ }
+ mFolders = NULL;
+ }
+
+
+ mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves
+
+ // create root folder
+ {
+ LLRect folder_rect(0,
+ 0,
+ getRect().getWidth(),
+ 0);
+ LLPlacesFolderView::Params p;
+ p.name = getName();
+ p.rect = folder_rect;
+ p.parent_panel = this;
+ mFolders = (LLFolderView*)LLUICtrlFactory::create<LLPlacesFolderView>(p);
+ mFolders->setAllowMultiSelect(mAllowMultiSelect);
+ }
+
+ mCommitCallbackRegistrar.popScope();
+
+ mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar);
+
+ // scroller
+ {
+ LLRect scroller_view_rect = getRect();
+ scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
+ LLScrollContainer::Params p;
+ p.name("Inventory Scroller");
+ p.rect(scroller_view_rect);
+ p.follows.flags(FOLLOWS_ALL);
+ p.reserve_scroll_corner(true);
+ p.tab_stop(true);
+ mScroller = LLUICtrlFactory::create<LLScrollContainer>(p);
+ }
+ addChild(mScroller);
+ mScroller->addChild(mFolders);
+
+ mFolders->setScrollContainer(mScroller);
+
+
+ // cut subitems
+ mFolders->setUseEllipses(true);
+
+ return TRUE;
+}
+
+// save current folder open state
+void LLPlacesInventoryPanel::saveFolderState()
+{
+ mSavedFolderState->setApply(FALSE);
+ getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
+}
+
+// re-open folders which state was saved
+void LLPlacesInventoryPanel::restoreFolderState()
+{
+ mSavedFolderState->setApply(TRUE);
+ getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
+ LLOpenFoldersWithSelection opener;
+ getRootFolder()->applyFunctorRecursively(opener);
+ getRootFolder()->scrollToShowSelection();
+}
+
+/************************************************************************/
+/* PROTECTED METHODS */
+/************************************************************************/
+
+
+
+/************************************************************************/
+/* LLPlacesFolderView implementation */
+/************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////
+// PUBLIC METHODS
+//////////////////////////////////////////////////////////////////////////
+
+BOOL LLPlacesFolderView::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ // let children to change selection first
+ childrenHandleRightMouseDown(x, y, mask);
+ mParentLandmarksPanel->setCurrentSelectedList((LLPlacesInventoryPanel*)getParentPanel());
+
+ // then determine its type and set necessary menu handle
+ if (getCurSelectedItem())
+ {
+ LLInventoryType::EType inventory_type = getCurSelectedItem()->getListener()->getInventoryType();
+ inventory_type_menu_handle_t::iterator it_handle = mMenuHandlesByInventoryType.find(inventory_type);
+
+ if (it_handle != mMenuHandlesByInventoryType.end())
+ {
+ mPopupMenuHandle = (*it_handle).second;
+ }
+ else
+ {
+ llwarns << "Requested menu handle for non-setup inventory type: " << inventory_type << llendl;
+ }
+
+ }
+
+ return LLFolderView::handleRightMouseDown(x, y, mask);
+}
+
+void LLPlacesFolderView::setupMenuHandle(LLInventoryType::EType asset_type, LLHandle<LLView> menu_handle)
+{
+ mMenuHandlesByInventoryType[asset_type] = menu_handle;
+}
+
+// EOF
diff --git a/indra/newview/llplacesinventorypanel.h b/indra/newview/llplacesinventorypanel.h
new file mode 100644
index 0000000000..7b34045d32
--- /dev/null
+++ b/indra/newview/llplacesinventorypanel.h
@@ -0,0 +1,96 @@
+/**
+ * @file llplacesinventorypanel.h
+ * @brief LLPlacesInventoryPanel class declaration
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLINVENTORYSUBTREEPANEL_H
+#define LL_LLINVENTORYSUBTREEPANEL_H
+
+#include "llfloaterinventory.h"
+#include "llinventorypanel.h"
+#include "llfolderview.h"
+
+class LLLandmarksPanel;
+
+class LLPlacesInventoryPanel : public LLInventoryPanel
+{
+public:
+ struct Params
+ : public LLInitParam::Block<Params, LLInventoryPanel::Params>
+ {
+ Params()
+ {}
+ };
+
+ LLPlacesInventoryPanel(const Params& p);
+ ~LLPlacesInventoryPanel();
+
+ /*virtual*/ BOOL postBuild();
+
+ void saveFolderState();
+ void restoreFolderState();
+
+private:
+ LLSaveFolderState* mSavedFolderState;
+};
+
+
+class LLPlacesFolderView : public LLFolderView
+{
+public:
+ LLPlacesFolderView(const LLFolderView::Params& p) : LLFolderView(p) {};
+ /**
+ * Handles right mouse down
+ *
+ * Contains workaround for EXT-2786: sets current selected list for landmark
+ * panel using @c mParentLandmarksPanel which is set in @c LLLandmarksPanel::initLandmarksPanel
+ */
+ /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
+
+ void setupMenuHandle(LLInventoryType::EType asset_type, LLHandle<LLView> menu_handle);
+
+ void setParentLandmarksPanel(LLLandmarksPanel* panel)
+ {
+ mParentLandmarksPanel = panel;
+ }
+
+ S32 getSelectedCount() { return (S32)mSelectedItems.size(); }
+
+private:
+ /**
+ * holds pointer to landmark panel. This pointer is used in @c LLPlacesFolderView::handleRightMouseDown
+ */
+ LLLandmarksPanel* mParentLandmarksPanel;
+ typedef std::map<LLInventoryType::EType, LLHandle<LLView> > inventory_type_menu_handle_t;
+ inventory_type_menu_handle_t mMenuHandlesByInventoryType;
+
+};
+
+#endif //LL_LLINVENTORYSUBTREEPANEL_H
diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp
index dbe6079ed5..d5a2d66bcf 100644
--- a/indra/newview/llpolymesh.cpp
+++ b/indra/newview/llpolymesh.cpp
@@ -40,6 +40,7 @@
#include "llviewercontrol.h"
#include "llxmltree.h"
#include "llvoavatar.h"
+#include "llwearable.h"
#include "lldir.h"
#include "llvolume.h"
#include "llendianswizzle.h"
@@ -1117,6 +1118,13 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info)
return TRUE;
}
+/*virtual*/ LLViewerVisualParam* LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const
+{
+ LLPolySkeletalDistortion *new_param = new LLPolySkeletalDistortion(mAvatar);
+ *new_param = *this;
+ return new_param;
+}
+
//-----------------------------------------------------------------------------
// apply()
//-----------------------------------------------------------------------------
diff --git a/indra/newview/llpolymesh.h b/indra/newview/llpolymesh.h
index c23617749f..c2e5451dfe 100644
--- a/indra/newview/llpolymesh.h
+++ b/indra/newview/llpolymesh.h
@@ -46,6 +46,7 @@
class LLSkinJoint;
class LLVOAvatar;
+class LLWearable;
//#define USE_STRIPS // Use tri-strips for rendering.
@@ -416,6 +417,8 @@ public:
// This sets mInfo and calls initialization functions
BOOL setInfo(LLPolySkeletalDistortionInfo *info);
+ /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const;
+
// LLVisualParam Virtual functions
///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
/*virtual*/ void apply( ESex sex );
diff --git a/indra/newview/llpolymorph.cpp b/indra/newview/llpolymorph.cpp
index 3a57b6f9f7..80983cad24 100644
--- a/indra/newview/llpolymorph.cpp
+++ b/indra/newview/llpolymorph.cpp
@@ -37,6 +37,7 @@
#include "llpolymorph.h"
#include "llvoavatar.h"
+#include "llwearable.h"
#include "llxmltree.h"
#include "llendianswizzle.h"
@@ -301,6 +302,13 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info)
return TRUE;
}
+/*virtual*/ LLViewerVisualParam* LLPolyMorphTarget::cloneParam(LLWearable* wearable) const
+{
+ LLPolyMorphTarget *new_param = new LLPolyMorphTarget(mMesh);
+ *new_param = *this;
+ return new_param;
+}
+
#if 0 // obsolete
//-----------------------------------------------------------------------------
// parseData()
diff --git a/indra/newview/llpolymorph.h b/indra/newview/llpolymorph.h
index f8dd52ca32..01731402df 100644
--- a/indra/newview/llpolymorph.h
+++ b/indra/newview/llpolymorph.h
@@ -42,6 +42,7 @@ class LLPolyMeshSharedData;
class LLVOAvatar;
class LLVector2;
class LLViewerJointCollisionVolume;
+class LLWearable;
//-----------------------------------------------------------------------------
// LLPolyMorphData()
@@ -153,6 +154,8 @@ public:
// This sets mInfo and calls initialization functions
BOOL setInfo(LLPolyMorphTargetInfo *info);
+ /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const;
+
// LLVisualParam Virtual functions
///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
/*virtual*/ void apply( ESex sex );
diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp
index 6d7082bf9a..0b0c03e9e9 100644
--- a/indra/newview/llpreview.cpp
+++ b/indra/newview/llpreview.cpp
@@ -34,142 +34,88 @@
#include "stdenums.h"
#include "llpreview.h"
+
#include "lllineeditor.h"
#include "llinventory.h"
#include "llinventorymodel.h"
#include "llresmgr.h"
#include "lltextbox.h"
+#include "llfloaterreg.h"
#include "llfocusmgr.h"
#include "lltooldraganddrop.h"
#include "llradiogroup.h"
#include "llassetstorage.h"
+#include "llviewerassettype.h"
#include "llviewerobject.h"
#include "llviewerobjectlist.h"
#include "lldbstrings.h"
#include "llagent.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "llselectmgr.h"
-#include "llinventoryview.h"
#include "llviewerinventory.h"
+#include "llviewerwindow.h"
+#include "lltrans.h"
// Constants
-// Globals and statics
-LLPreview::preview_multimap_t LLPreview::sPreviewsBySource;
-LLPreview::preview_map_t LLPreview::sInstances;
-std::map<LLUUID, LLHandle<LLFloater> > LLMultiPreview::sAutoOpenPreviewHandles;
-
-// Functions
-LLPreview::LLPreview(const std::string& name) :
- LLFloater(name),
- mCopyToInvBtn(NULL),
+LLPreview::LLPreview(const LLSD& key)
+: LLFloater(key),
+ mItemUUID(key.asUUID()),
+ mObjectUUID(), // set later by setObjectID()
+ mCopyToInvBtn( NULL ),
mForceClose(FALSE),
mUserResized(FALSE),
mCloseAfterSave(FALSE),
mAssetStatus(PREVIEW_ASSET_UNLOADED),
- mItem(NULL),
mDirty(TRUE)
{
- // don't add to instance list, since ItemID is null
- mAuxItem = new LLInventoryItem; // (LLPointer is auto-deleted)
+ mAuxItem = new LLInventoryItem;
// don't necessarily steal focus on creation -- sometimes these guys pop up without user action
setAutoFocus(FALSE);
+
gInventory.addObserver(this);
+
+ refreshFromItem();
}
-LLPreview::LLPreview(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& item_uuid, const LLUUID& object_uuid, BOOL allow_resize, S32 min_width, S32 min_height, LLPointer<LLViewerInventoryItem> inv_item )
-: LLFloater(name, rect, title, allow_resize, min_width, min_height ),
- mItemUUID(item_uuid),
- mSourceID(LLUUID::null),
- mObjectUUID(object_uuid),
- mCopyToInvBtn( NULL ),
- mForceClose( FALSE ),
- mUserResized(FALSE),
- mCloseAfterSave(FALSE),
- mAssetStatus(PREVIEW_ASSET_UNLOADED),
- mItem(inv_item),
- mDirty(TRUE)
+BOOL LLPreview::postBuild()
{
- mAuxItem = new LLInventoryItem;
- // don't necessarily steal focus on creation -- sometimes these guys pop up without user action
- setAutoFocus(FALSE);
-
- if (mItemUUID.notNull())
- {
- sInstances[mItemUUID] = this;
- }
- gInventory.addObserver(this);
+ refreshFromItem();
+ return TRUE;
}
LLPreview::~LLPreview()
{
gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit()
-
- if (mItemUUID.notNull())
- {
- sInstances.erase( mItemUUID );
- }
-
- if (mSourceID.notNull())
- {
- preview_multimap_t::iterator found_it = sPreviewsBySource.find(mSourceID);
- for (; found_it != sPreviewsBySource.end(); ++found_it)
- {
- if (found_it->second == getHandle())
- {
- sPreviewsBySource.erase(found_it);
- break;
- }
- }
- }
gInventory.removeObserver(this);
}
-void LLPreview::setItemID(const LLUUID& item_id)
-{
- if (mItemUUID.notNull())
- {
- sInstances.erase(mItemUUID);
- }
-
- mItemUUID = item_id;
-
- if (mItemUUID.notNull())
- {
- sInstances[mItemUUID] = this;
- }
-}
-
void LLPreview::setObjectID(const LLUUID& object_id)
{
mObjectUUID = object_id;
+ if (getAssetStatus() == PREVIEW_ASSET_UNLOADED)
+ {
+ loadAsset();
+ }
}
-void LLPreview::setSourceID(const LLUUID& source_id)
+void LLPreview::setItem( LLInventoryItem* item )
{
- if (mSourceID.notNull())
+ mItem = item;
+ if (mItem && getAssetStatus() == PREVIEW_ASSET_UNLOADED)
{
- // erase old one
- preview_multimap_t::iterator found_it = sPreviewsBySource.find(mSourceID);
- for (; found_it != sPreviewsBySource.end(); ++found_it)
- {
- if (found_it->second == getHandle())
- {
- sPreviewsBySource.erase(found_it);
- break;
- }
- }
+ loadAsset();
}
- mSourceID = source_id;
- sPreviewsBySource.insert(preview_multimap_t::value_type(mSourceID, getHandle()));
}
-const LLViewerInventoryItem *LLPreview::getItem() const
+const LLInventoryItem *LLPreview::getItem() const
{
- if(mItem)
- return mItem;
- const LLViewerInventoryItem *item = NULL;
- if(mObjectUUID.isNull())
+ const LLInventoryItem *item = NULL;
+ if (mItem.notNull())
+ {
+ item = mItem;
+ }
+ else if (mObjectUUID.isNull())
{
// it's an inventory item, so get the item.
item = gInventory.getItem(mItemUUID);
@@ -180,7 +126,7 @@ const LLViewerInventoryItem *LLPreview::getItem() const
LLViewerObject* object = gObjectList.findObject(mObjectUUID);
if(object)
{
- item = (LLViewerInventoryItem*)object->getInventoryObject(mItemUUID);
+ item = dynamic_cast<LLInventoryItem*>(object->getInventoryObject(mItemUUID));
}
}
return item;
@@ -189,7 +135,7 @@ const LLViewerInventoryItem *LLPreview::getItem() const
// Sub-classes should override this function if they allow editing
void LLPreview::onCommit()
{
- const LLViewerInventoryItem *item = getItem();
+ const LLViewerInventoryItem *item = dynamic_cast<const LLViewerInventoryItem*>(getItem());
if(item)
{
if (!item->isComplete())
@@ -204,6 +150,13 @@ void LLPreview::onCommit()
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
new_item->setDescription(childGetText("desc"));
+
+ std::string new_name = childGetText("name");
+ if ( (new_item->getName() != new_name) && !new_name.empty())
+ {
+ new_item->rename(childGetText("name"));
+ }
+
if(mObjectUUID.notNull())
{
// must be in an object
@@ -226,7 +179,7 @@ void LLPreview::onCommit()
// update the object itself.
if( item->getType() == LLAssetType::AT_OBJECT )
{
- LLVOAvatar* avatar = gAgent.getAvatarObject();
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
if( avatar )
{
LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() );
@@ -249,23 +202,37 @@ void LLPreview::changed(U32 mask)
mDirty = TRUE;
}
+void LLPreview::setNotecardInfo(const LLUUID& notecard_inv_id,
+ const LLUUID& object_id)
+{
+ mNotecardInventoryID = notecard_inv_id;
+ mNotecardObjectID = object_id;
+}
+
void LLPreview::draw()
{
LLFloater::draw();
if (mDirty)
{
mDirty = FALSE;
- const LLViewerInventoryItem *item = getItem();
- if (item)
- {
- refreshFromItem(item);
- }
+ refreshFromItem();
}
}
-void LLPreview::refreshFromItem(const LLInventoryItem* item)
+void LLPreview::refreshFromItem()
{
- setTitle(llformat("%s: %s",getTitleName(),item->getName().c_str()));
+ const LLInventoryItem* item = getItem();
+ if (!item)
+ {
+ return;
+ }
+ if (hasString("Title"))
+ {
+ LLStringUtil::format_map_t args;
+ args["[NAME]"] = item->getName();
+ LLUIString title = getString("Title", args);
+ setTitle(title.getString());
+ }
childSetText("desc",item->getDescription());
BOOL can_agent_manipulate = item->getPermissions().allowModifyBy(gAgent.getID());
@@ -287,80 +254,32 @@ void LLPreview::onRadio(LLUICtrl*, void* userdata)
}
// static
-LLPreview* LLPreview::find(const LLUUID& item_uuid)
-{
- LLPreview* instance = NULL;
- preview_map_t::iterator found_it = LLPreview::sInstances.find(item_uuid);
- if(found_it != LLPreview::sInstances.end())
- {
- instance = found_it->second;
- }
- return instance;
-}
-
-// static
-LLPreview* LLPreview::show( const LLUUID& item_uuid, BOOL take_focus )
-{
- LLPreview* instance = LLPreview::find(item_uuid);
- if(instance)
- {
- if (LLFloater::getFloaterHost() && LLFloater::getFloaterHost() != instance->getHost())
- {
- // this preview window is being opened in a new context
- // needs to be rehosted
- LLFloater::getFloaterHost()->addFloater(instance, TRUE);
- }
- instance->open(); /*Flawfinder: ignore*/
- if (take_focus)
- {
- instance->setFocus(TRUE);
- }
- }
-
- return instance;
-}
-
-// static
-bool LLPreview::save( const LLUUID& item_uuid, LLPointer<LLInventoryItem>* itemptr )
-{
- bool res = false;
- LLPreview* instance = LLPreview::find(item_uuid);
- if(instance)
- {
- res = instance->saveItem(itemptr);
- }
- if (!res)
- {
- delete itemptr;
- }
- return res;
-}
-
-// static
void LLPreview::hide(const LLUUID& item_uuid, BOOL no_saving /* = FALSE */ )
{
- preview_map_t::iterator found_it = LLPreview::sInstances.find(item_uuid);
- if(found_it != LLPreview::sInstances.end())
+ LLFloater* floater = LLFloaterReg::findInstance("preview", LLSD(item_uuid));
+ if (!floater) floater = LLFloaterReg::findInstance("preview_avatar", LLSD(item_uuid));
+
+ LLPreview* preview = dynamic_cast<LLPreview*>(floater);
+ if (preview)
{
- LLPreview* instance = found_it->second;
-
if ( no_saving )
{
- instance->mForceClose = TRUE;
+ preview->mForceClose = TRUE;
}
-
- instance->close();
+ preview->closeFloater();
}
}
// static
-void LLPreview::rename(const LLUUID& item_uuid, const std::string& new_name)
+void LLPreview::dirty(const LLUUID& item_uuid)
{
- preview_map_t::iterator found_it = LLPreview::sInstances.find(item_uuid);
- if(found_it != LLPreview::sInstances.end())
+ LLFloater* floater = LLFloaterReg::findInstance("preview", LLSD(item_uuid));
+ if (!floater) floater = LLFloaterReg::findInstance("preview_avatar", LLSD(item_uuid));
+
+ LLPreview* preview = dynamic_cast<LLPreview*>(floater);
+ if(preview)
{
- LLPreview* instance = found_it->second;
- instance->setTitle( new_name );
+ preview->mDirty = TRUE;
}
}
@@ -397,7 +316,7 @@ BOOL LLPreview::handleHover(S32 x, S32 y, MASK mask)
{
S32 screen_x;
S32 screen_y;
- const LLViewerInventoryItem *item = getItem();
+ const LLInventoryItem *item = getItem();
localPointToScreen(x, y, &screen_x, &screen_y );
if(item
@@ -406,7 +325,7 @@ BOOL LLPreview::handleHover(S32 x, S32 y, MASK mask)
&& LLToolDragAndDrop::getInstance()->isOverThreshold(screen_x, screen_y))
{
EDragAndDropType type;
- type = LLAssetType::lookupDragAndDropType(item->getType());
+ type = LLViewerAssetType::lookupDragAndDropType(item->getType());
LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_LIBRARY;
if(!mObjectUUID.isNull())
{
@@ -426,22 +345,20 @@ BOOL LLPreview::handleHover(S32 x, S32 y, MASK mask)
return LLFloater::handleHover(x,y,mask);
}
-void LLPreview::open() /*Flawfinder: ignore*/
+void LLPreview::onOpen(const LLSD& key)
{
if (!getFloaterHost() && !getHost() && getAssetStatus() == PREVIEW_ASSET_UNLOADED)
{
loadAsset();
}
- LLFloater::open(); /*Flawfinder: ignore*/
}
-// virtual
-bool LLPreview::saveItem(LLPointer<LLInventoryItem>* itemptr)
+void LLPreview::setAuxItem( const LLInventoryItem* item )
{
- return false;
+ if ( mAuxItem )
+ mAuxItem->copyItem(item);
}
-
// static
void LLPreview::onBtnCopyToInv(void* userdata)
{
@@ -453,7 +370,7 @@ void LLPreview::onBtnCopyToInv(void* userdata)
// Copy to inventory
if (self->mNotecardInventoryID.notNull())
{
- copy_inventory_from_notecard(self->mObjectID,
+ copy_inventory_from_notecard(self->mNotecardObjectID,
self->mNotecardInventoryID, item);
}
else
@@ -468,14 +385,14 @@ void LLPreview::onBtnCopyToInv(void* userdata)
cb);
}
}
- self->close();
+ self->closeFloater();
}
// static
void LLPreview::onKeepBtn(void* data)
{
LLPreview* self = (LLPreview*)data;
- self->close();
+ self->closeFloater();
}
// static
@@ -483,11 +400,11 @@ void LLPreview::onDiscardBtn(void* data)
{
LLPreview* self = (LLPreview*)data;
- const LLViewerInventoryItem* item = self->getItem();
+ const LLInventoryItem* item = self->getItem();
if (!item) return;
self->mForceClose = TRUE;
- self->close();
+ self->closeFloater();
// Delete the item entirely
/*
@@ -497,7 +414,7 @@ void LLPreview::onDiscardBtn(void* data)
*/
// Move the item to the trash
- LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
if (item->getParentUUID() != trash_id)
{
LLInventoryModel::update_list_t update;
@@ -517,55 +434,60 @@ void LLPreview::onDiscardBtn(void* data)
}
}
-//static
-LLPreview* LLPreview::getFirstPreviewForSource(const LLUUID& source_id)
-{
- preview_multimap_t::iterator found_it = sPreviewsBySource.find(source_id);
- if (found_it != sPreviewsBySource.end())
- {
- // just return first one
- return (LLPreview*)found_it->second.get();
- }
- return NULL;
-}
-
-void LLPreview::userSetShape(const LLRect& new_rect)
+void LLPreview::handleReshape(const LLRect& new_rect, bool by_user)
{
- if(new_rect.getWidth() != getRect().getWidth() || new_rect.getHeight() != getRect().getHeight())
+ if(by_user
+ && (new_rect.getWidth() != getRect().getWidth() || new_rect.getHeight() != getRect().getHeight()))
{
userResized();
}
- LLFloater::userSetShape(new_rect);
+ LLFloater::handleReshape(new_rect, by_user);
}
//
// LLMultiPreview
//
-LLMultiPreview::LLMultiPreview(const LLRect& rect) : LLMultiFloater(std::string("Preview"), rect)
+LLMultiPreview::LLMultiPreview()
+ : LLMultiFloater(LLSD())
{
+ // *TODO: There should be a .xml file for this
+ const LLRect& nextrect = LLFloaterReg::getFloaterRect("preview"); // place where the next preview should show up
+ if (nextrect.getWidth() > 0)
+ {
+ setRect(nextrect);
+ }
+ else
+ {
+ // start with a rect in the top-left corner ; will get resized
+ LLRect rect;
+ rect.setLeftTopAndSize(0, gViewerWindow->getWindowHeightScaled(), 200, 200);
+ setRect(rect);
+ }
+ setTitle(LLTrans::getString("MultiPreviewTitle"));
+ buildTabContainer();
setCanResize(TRUE);
}
-void LLMultiPreview::open() /*Flawfinder: ignore*/
+void LLMultiPreview::onOpen(const LLSD& key)
{
- LLMultiFloater::open(); /*Flawfinder: ignore*/
LLPreview* frontmost_preview = (LLPreview*)mTabContainer->getCurrentPanel();
if (frontmost_preview && frontmost_preview->getAssetStatus() == LLPreview::PREVIEW_ASSET_UNLOADED)
{
frontmost_preview->loadAsset();
}
+ LLMultiFloater::onOpen(key);
}
-void LLMultiPreview::userSetShape(const LLRect& new_rect)
+void LLMultiPreview::handleReshape(const LLRect& new_rect, bool by_user)
{
if(new_rect.getWidth() != getRect().getWidth() || new_rect.getHeight() != getRect().getHeight())
{
LLPreview* frontmost_preview = (LLPreview*)mTabContainer->getCurrentPanel();
if (frontmost_preview) frontmost_preview->userResized();
}
- LLFloater::userSetShape(new_rect);
+ LLFloater::handleReshape(new_rect, by_user);
}
@@ -578,22 +500,31 @@ void LLMultiPreview::tabOpen(LLFloater* opened_floater, bool from_click)
}
}
-//static
-LLMultiPreview* LLMultiPreview::getAutoOpenInstance(const LLUUID& id)
+
+void LLPreview::setAssetId(const LLUUID& asset_id)
{
- handle_map_t::iterator found_it = sAutoOpenPreviewHandles.find(id);
- if (found_it != sAutoOpenPreviewHandles.end())
+ const LLViewerInventoryItem* item = dynamic_cast<const LLViewerInventoryItem*>(getItem());
+ if(NULL == item)
{
- return (LLMultiPreview*)found_it->second.get();
+ return;
}
- return NULL;
-}
-
-//static
-void LLMultiPreview::setAutoOpenInstance(LLMultiPreview* previewp, const LLUUID& id)
-{
- if (previewp)
+
+ if(mObjectUUID.isNull())
+ {
+ // Update avatar inventory asset_id.
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ new_item->setAssetUUID(asset_id);
+ gInventory.updateItem(new_item);
+ gInventory.notifyObservers();
+ }
+ else
{
- sAutoOpenPreviewHandles[id] = previewp->getHandle();
+ // Update object inventory asset_id.
+ LLViewerObject* object = gObjectList.findObject(mObjectUUID);
+ if(NULL == object)
+ {
+ return;
+ }
+ object->updateViewerInventoryAsset(item, asset_id);
}
}
diff --git a/indra/newview/llpreview.h b/indra/newview/llpreview.h
index ff084bea27..3b9f7f9882 100644
--- a/indra/newview/llpreview.h
+++ b/indra/newview/llpreview.h
@@ -33,15 +33,14 @@
#ifndef LL_LLPREVIEW_H
#define LL_LLPREVIEW_H
-#include "llfloater.h"
+#include "llmultifloater.h"
#include "llresizehandle.h"
-#include "llmap.h"
+#include "llpointer.h"
#include "lluuid.h"
-#include "llviewerinventory.h"
-#include "lltabcontainer.h"
-#include "llinventorymodel.h"
+#include "llinventoryobserver.h"
#include <map>
+class LLInventoryItem;
class LLLineEditor;
class LLRadioGroup;
class LLPreview;
@@ -49,18 +48,12 @@ class LLPreview;
class LLMultiPreview : public LLMultiFloater
{
public:
- LLMultiPreview(const LLRect& rect);
+ LLMultiPreview();
- /*virtual*/void open(); /*Flawfinder: ignore*/
+ /*virtual*/void onOpen(const LLSD& key);
/*virtual*/void tabOpen(LLFloater* opened_floater, bool from_click);
- /*virtual*/ void userSetShape(const LLRect& new_rect);
+ /*virtual*/ void handleReshape(const LLRect& new_rect, bool by_user = false);
- static LLMultiPreview* getAutoOpenInstance(const LLUUID& id);
- static void setAutoOpenInstance(LLMultiPreview* previewp, const LLUUID& id);
-
-protected:
- typedef std::map<LLUUID, LLHandle<LLFloater> > handle_map_t;
- static handle_map_t sAutoOpenPreviewHandles;
};
// https://wiki.lindenlab.com/mediawiki/index.php?title=LLPreview&oldid=81373
@@ -76,40 +69,33 @@ public:
PREVIEW_ASSET_LOADED
} EAssetStatus;
public:
- // Used for XML-based construction.
- LLPreview(const std::string& name);
- LLPreview(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& item_uuid, const LLUUID& object_uuid, BOOL allow_resize = FALSE, S32 min_width = 0, S32 min_height = 0, LLPointer<LLViewerInventoryItem> inv_item = NULL );
+ LLPreview(const LLSD& key );
virtual ~LLPreview();
-
- void setItemID(const LLUUID& item_id);
+
+ /*virtual*/ BOOL postBuild();
+
void setObjectID(const LLUUID& object_id);
- void setSourceID(const LLUUID& source_id);
- const LLViewerInventoryItem *getItem() const; // searches if not constructed with it
-
- static LLPreview* find(const LLUUID& item_uuid);
- static LLPreview* show(const LLUUID& item_uuid, BOOL take_focus = TRUE );
- static void hide(const LLUUID& item_uuid, BOOL no_saving = FALSE );
- static void rename(const LLUUID& item_uuid, const std::string& new_name);
- static bool save(const LLUUID& item_uuid, LLPointer<LLInventoryItem>* itemptr);
+ void setItem( LLInventoryItem* item );
+
+ void setAssetId(const LLUUID& asset_id);
+ const LLInventoryItem* getItem() const; // searches if not constructed with it
+ static void hide(const LLUUID& item_uuid, BOOL no_saving = FALSE );
+ static void dirty(const LLUUID& item_uuid);
+
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual void open(); /*Flawfinder: ignore*/
- virtual bool saveItem(LLPointer<LLInventoryItem>* itemptr);
-
- void setAuxItem( const LLInventoryItem* item )
- {
- if ( mAuxItem )
- mAuxItem->copyItem(item);
- }
+ virtual void onOpen(const LLSD& key);
+
+ void setAuxItem( const LLInventoryItem* item );
static void onBtnCopyToInv(void* userdata);
void addKeepDiscardButtons();
static void onKeepBtn(void* data);
static void onDiscardBtn(void* data);
- /*virtual*/ void userSetShape(const LLRect& new_rect);
+ /*virtual*/ void handleReshape(const LLRect& new_rect, bool by_user = false);
void userResized() { mUserResized = TRUE; };
@@ -117,12 +103,13 @@ public:
virtual EAssetStatus getAssetStatus() { return mAssetStatus;}
static LLPreview* getFirstPreviewForSource(const LLUUID& source_id);
- void setNotecardInfo(const LLUUID& notecard_inv_id, const LLUUID& object_id)
- { mNotecardInventoryID = notecard_inv_id; mObjectID = object_id; }
+
+ // Why is this at the LLPreview level? JC
+ void setNotecardInfo(const LLUUID& notecard_inv_id, const LLUUID& object_id);
// llview
- virtual void draw();
- void refreshFromItem(const LLInventoryItem* item);
+ /*virtual*/ void draw();
+ void refreshFromItem();
protected:
virtual void onCommit();
@@ -135,13 +122,11 @@ protected:
// for LLInventoryObserver
virtual void changed(U32 mask);
BOOL mDirty;
- virtual const char *getTitleName() const { return "Preview"; }
protected:
LLUUID mItemUUID;
- LLUUID mSourceID;
- // mObjectID will have a value if it is associated with a task in
+ // mObjectUUID will have a value if it is associated with a task in
// the world, and will be == LLUUID::null if it's in the agent
// inventory.
LLUUID mObjectUUID;
@@ -149,6 +134,7 @@ protected:
LLRect mClientRect;
LLPointer<LLInventoryItem> mAuxItem; // HACK!
+ LLPointer<LLInventoryItem> mItem; // For embedded items (Landmarks)
LLButton* mCopyToInvBtn;
// Close without saving changes
@@ -162,27 +148,20 @@ protected:
EAssetStatus mAssetStatus;
- typedef std::map<LLUUID, LLPreview*> preview_map_t;
- typedef std::multimap<LLUUID, LLHandle<LLFloater> > preview_multimap_t;
-
- static preview_multimap_t sPreviewsBySource;
- static preview_map_t sInstances;
LLUUID mNotecardInventoryID;
- LLUUID mObjectID;
- LLPointer<LLViewerInventoryItem> mItem;
+ // I am unsure if this is always the same as mObjectUUID, or why it exists
+ // at the LLPreview level. JC 2009-06-24
+ LLUUID mNotecardObjectID;
};
const S32 PREVIEW_BORDER = 4;
const S32 PREVIEW_PAD = 5;
-const S32 PREVIEW_BUTTON_WIDTH = 100;
const S32 PREVIEW_LINE_HEIGHT = 19;
-const S32 PREVIEW_CLOSE_BOX_SIZE = 16;
const S32 PREVIEW_BORDER_WIDTH = 2;
const S32 PREVIEW_RESIZE_HANDLE_SIZE = S32(RESIZE_HANDLE_WIDTH * OO_SQRT2) + PREVIEW_BORDER_WIDTH;
const S32 PREVIEW_VPAD = 2;
-const S32 PREVIEW_HPAD = PREVIEW_RESIZE_HANDLE_SIZE;
const S32 PREVIEW_HEADER_SIZE = 2*PREVIEW_LINE_HEIGHT + 2 * PREVIEW_VPAD;
#endif // LL_LLPREVIEW_H
diff --git a/indra/newview/llpreviewanim.cpp b/indra/newview/llpreviewanim.cpp
index 3212de0639..92bd4dc62b 100644
--- a/indra/newview/llpreviewanim.cpp
+++ b/indra/newview/llpreviewanim.cpp
@@ -36,8 +36,7 @@
#include "llbutton.h"
#include "llresmgr.h"
#include "llinventory.h"
-#include "llinventoryview.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "llagent.h" // gAgent
#include "llkeyframemotion.h"
#include "llfilepicker.h"
@@ -47,42 +46,54 @@
extern LLAgent gAgent;
-LLPreviewAnim::LLPreviewAnim(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& item_uuid, const S32& activate, const LLUUID& object_uuid ) :
- LLPreview( name, rect, title, item_uuid, object_uuid)
+LLPreviewAnim::LLPreviewAnim(const LLSD& key)
+ : LLPreview( key )
{
- LLUICtrlFactory::getInstance()->buildFloater(this,"floater_preview_animation.xml");
-
- childSetAction("Anim play btn",playAnim,this);
- childSetAction("Anim audition btn",auditionAnim,this);
-
- const LLInventoryItem* item = getItem();
-
- childSetCommitCallback("desc", LLPreview::onText, this);
- childSetText("desc", item->getDescription());
- childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
-
- setTitle(title);
+ //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this,"floater_preview_animation.xml", FALSE);
+}
- if (!getHost())
+// static
+void LLPreviewAnim::endAnimCallback( void *userdata )
+{
+ LLHandle<LLFloater>* handlep = ((LLHandle<LLFloater>*)userdata);
+ LLFloater* self = handlep->get();
+ delete handlep; // done with the handle
+ if (self)
{
- LLRect curRect = getRect();
- translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop);
+ self->childSetValue("Anim play btn", FALSE);
+ self->childSetValue("Anim audition btn", FALSE);
}
+}
- // preload the animation
+// virtual
+BOOL LLPreviewAnim::postBuild()
+{
+ const LLInventoryItem* item = getItem();
if(item)
{
- gAgent.getAvatarObject()->createMotion(item->getAssetUUID());
+ gAgent.getAvatarObject()->createMotion(item->getAssetUUID()); // preload the animation
+ childSetText("desc", item->getDescription());
}
+
+ childSetAction("Anim play btn",playAnim, this);
+ childSetAction("Anim audition btn",auditionAnim, this);
+
+ childSetCommitCallback("desc", LLPreview::onText, this);
+ childSetPrevalidate("desc", &LLLineEditor::prevalidateASCIIPrintableNoPipe);
- switch ( activate )
+ return LLPreview::postBuild();
+}
+
+void LLPreviewAnim::activate(e_activation_type type)
+{
+ switch ( type )
{
- case 1:
+ case PLAY:
{
playAnim( (void *) this );
break;
}
- case 2:
+ case AUDITION:
{
auditionAnim( (void *) this );
break;
@@ -95,19 +106,6 @@ LLPreviewAnim::LLPreviewAnim(const std::string& name, const LLRect& rect, const
}
// static
-void LLPreviewAnim::endAnimCallback( void *userdata )
-{
- LLHandle<LLFloater>* handlep = ((LLHandle<LLFloater>*)userdata);
- LLFloater* self = handlep->get();
- delete handlep; // done with the handle
- if (self)
- {
- self->childSetValue("Anim play btn", FALSE);
- self->childSetValue("Anim audition btn", FALSE);
- }
-}
-
-// static
void LLPreviewAnim::playAnim( void *userdata )
{
LLPreviewAnim* self = (LLPreviewAnim*) userdata;
@@ -181,6 +179,7 @@ void LLPreviewAnim::auditionAnim( void *userdata )
}
}
+// virtual
void LLPreviewAnim::onClose(bool app_quitting)
{
const LLInventoryItem *item = getItem();
@@ -199,5 +198,4 @@ void LLPreviewAnim::onClose(bool app_quitting)
motion->setDeactivateCallback(NULL, (void *)NULL);
}
}
- destroy();
}
diff --git a/indra/newview/llpreviewanim.h b/indra/newview/llpreviewanim.h
index fe794d4283..616c5789ac 100644
--- a/indra/newview/llpreviewanim.h
+++ b/indra/newview/llpreviewanim.h
@@ -39,18 +39,17 @@
class LLPreviewAnim : public LLPreview
{
public:
- LLPreviewAnim(const std::string& name, const LLRect& rect, const std::string& title,
- const LLUUID& item_uuid,
- const S32& activate,
- const LLUUID& object_uuid = LLUUID::null);
+ enum e_activation_type { NONE = 0, PLAY = 1, AUDITION = 2 };
+ LLPreviewAnim(const LLSD& key);
static void playAnim( void* userdata );
static void auditionAnim( void* userdata );
static void endAnimCallback( void *userdata );
-
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onClose(bool app_quitting);
+ void activate(e_activation_type type);
+
protected:
- virtual void onClose(bool app_quitting);
- virtual const char *getTitleName() const { return "Animation"; }
LLAnimPauseRequest mPauseRequest;
LLUUID mItemID;
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index 76a9b80645..84bdaafacf 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -32,20 +32,23 @@
#include "llviewerprecompiledheaders.h"
-#include <algorithm>
-
#include "llpreviewgesture.h"
+#include <algorithm>
+
// libraries
#include "lldatapacker.h"
#include "lldarray.h"
#include "llstring.h"
#include "lldir.h"
+#include "llfloaterreg.h"
#include "llmultigesture.h"
+#include "llnotificationsutil.h"
#include "llvfile.h"
// newview
#include "llagent.h" // todo: remove
+#include "llanimationstates.h"
#include "llassetuploadresponders.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
@@ -56,9 +59,10 @@
#include "llinventorymodel.h"
#include "llkeyboard.h"
#include "lllineeditor.h"
-#include "llnotify.h"
#include "llradiogroup.h"
#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "llscrolllistcell.h"
#include "lltextbox.h"
#include "lluictrlfactory.h"
#include "llviewerinventory.h"
@@ -67,15 +71,16 @@
#include "llviewerregion.h"
#include "llviewerstats.h"
#include "llviewerwindow.h" // busycount
+#include "llvoavatarself.h"
#include "llappviewer.h" // gVFS
#include "llanimstatelabels.h"
#include "llresmgr.h"
+#include "lltrans.h"
-// *TODO: Translate?
-const std::string NONE_LABEL = "---";
-const std::string SHIFT_LABEL = "Shift";
-const std::string CTRL_LABEL = "Ctrl";
+std::string NONE_LABEL;
+std::string SHIFT_LABEL;
+std::string CTRL_LABEL;
void dialog_refresh_all();
@@ -92,12 +97,9 @@ protected:
void LLInventoryGestureAvailable::done()
{
- LLPreview* preview = NULL;
- item_ref_t::iterator it = mComplete.begin();
- item_ref_t::iterator end = mComplete.end();
- for(; it < end; ++it)
+ for(item_ref_t::iterator it = mComplete.begin(); it != mComplete.end(); ++it)
{
- preview = LLPreview::find((*it));
+ LLPreviewGesture* preview = LLFloaterReg::findTypedInstance<LLPreviewGesture>("preview_gesture", *it);
if(preview)
{
preview->refresh();
@@ -117,53 +119,26 @@ struct SortItemPtrsByName
};
// static
-LLPreviewGesture* LLPreviewGesture::show(const std::string& title, const LLUUID& item_id, const LLUUID& object_id, BOOL take_focus)
+LLPreviewGesture* LLPreviewGesture::show(const LLUUID& item_id, const LLUUID& object_id)
{
- LLPreviewGesture* previewp = (LLPreviewGesture*)LLPreview::find(item_id);
- if (previewp)
+ LLPreviewGesture* preview = LLFloaterReg::showTypedInstance<LLPreviewGesture>("preview_gesture", LLSD(item_id), TAKE_FOCUS_YES);
+ if (!preview)
{
- previewp->open(); /*Flawfinder: ignore*/
- if (take_focus)
- {
- previewp->setFocus(TRUE);
- }
- return previewp;
+ return NULL;
}
-
- LLPreviewGesture* self = new LLPreviewGesture();
-
- // Finish internal construction
- self->init(item_id, object_id);
-
- // Builds and adds to gFloaterView
- LLUICtrlFactory::getInstance()->buildFloater(self, "floater_preview_gesture.xml");
- self->setTitle(title);
-
- // Move window to top-left of screen
- LLMultiFloater* hostp = self->getHost();
- if (hostp == NULL)
- {
- LLRect r = self->getRect();
- LLRect screen = gFloaterView->getRect();
- r.setLeftTopAndSize(0, screen.getHeight(), r.getWidth(), r.getHeight());
- self->setRect(r);
- }
- else
- {
- // re-add to host to update title
- hostp->addFloater(self, TRUE);
- }
-
+
+ preview->setObjectID(object_id);
+
// Start speculative download of sounds and animations
- LLUUID animation_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_ANIMATION);
+ const LLUUID animation_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_ANIMATION);
gInventory.startBackgroundFetch(animation_folder_id);
- LLUUID sound_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_SOUND);
+ const LLUUID sound_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SOUND);
gInventory.startBackgroundFetch(sound_folder_id);
// this will call refresh when we have everything.
- LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->getItem();
- if(item && !item->isComplete())
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)preview->getItem();
+ if (item && !item->isComplete())
{
LLInventoryGestureAvailable* observer;
observer = new LLInventoryGestureAvailable();
@@ -174,18 +149,12 @@ LLPreviewGesture* LLPreviewGesture::show(const std::string& title, const LLUUID&
else
{
// not sure this is necessary.
- self->refresh();
- }
-
- if (take_focus)
- {
- self->setFocus(TRUE);
+ preview->refresh();
}
- return self;
+ return preview;
}
-
// virtual
BOOL LLPreviewGesture::handleKeyHere(KEY key, MASK mask)
{
@@ -285,7 +254,7 @@ BOOL LLPreviewGesture::canClose()
else
{
// Bring up view-modal dialog: Save changes? Yes, No, Cancel
- LLNotifications::instance().add("SaveChanges", LLSD(), LLSD(),
+ LLNotificationsUtil::add("SaveChanges", LLSD(), LLSD(),
boost::bind(&LLPreviewGesture::handleSaveChangesDialog, this, _1, _2) );
return FALSE;
}
@@ -294,8 +263,7 @@ BOOL LLPreviewGesture::canClose()
// virtual
void LLPreviewGesture::onClose(bool app_quitting)
{
- gGestureManager.stopGesture(mPreviewGesture);
- LLPreview::onClose(app_quitting);
+ LLGestureManager::instance().stopGesture(mPreviewGesture);
}
// virtual
@@ -304,37 +272,30 @@ void LLPreviewGesture::onUpdateSucceeded()
refresh();
}
-// virtual
-void LLPreviewGesture::setMinimized(BOOL minimize)
+void LLPreviewGesture::onVisibilityChange ( const LLSD& new_visibility )
{
- if (minimize != isMinimized())
+ if (new_visibility.asBoolean())
{
- LLFloater::setMinimized(minimize);
-
- // We're being restored
- if (!minimize)
- {
- refresh();
- }
+ refresh();
}
}
bool LLPreviewGesture::handleSaveChangesDialog(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
switch(option)
{
case 0: // "Yes"
- gGestureManager.stopGesture(mPreviewGesture);
+ LLGestureManager::instance().stopGesture(mPreviewGesture);
mCloseAfterSave = TRUE;
onClickSave(this);
break;
case 1: // "No"
- gGestureManager.stopGesture(mPreviewGesture);
+ LLGestureManager::instance().stopGesture(mPreviewGesture);
mDirty = FALSE; // Force the dirty flag because user has clicked NO on confirm save dialog...
- close();
+ closeFloater();
break;
case 2: // "Cancel"
@@ -347,8 +308,8 @@ bool LLPreviewGesture::handleSaveChangesDialog(const LLSD& notification, const L
}
-LLPreviewGesture::LLPreviewGesture()
-: LLPreview("Gesture Preview"),
+LLPreviewGesture::LLPreviewGesture(const LLSD& key)
+: LLPreview(key),
mTriggerEditor(NULL),
mModifierCombo(NULL),
mKeyCombo(NULL),
@@ -368,6 +329,12 @@ LLPreviewGesture::LLPreviewGesture()
mPreviewGesture(NULL),
mDirty(FALSE)
{
+ NONE_LABEL = LLTrans::getString("---");
+ SHIFT_LABEL = LLTrans::getString("KBShift");
+ CTRL_LABEL = LLTrans::getString("KBCtrl");
+
+ //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_preview_gesture.xml", FALSE);
+
}
@@ -388,6 +355,8 @@ LLPreviewGesture::~LLPreviewGesture()
BOOL LLPreviewGesture::postBuild()
{
+ setVisibleCallback(boost::bind(&LLPreviewGesture::onVisibilityChange, this, _2));
+
LLLineEditor* edit;
LLComboBox* combo;
LLButton* btn;
@@ -395,11 +364,16 @@ BOOL LLPreviewGesture::postBuild()
LLTextBox* text;
LLCheckBoxCtrl* check;
+ edit = getChild<LLLineEditor>("name");
+ edit->setKeystrokeCallback(onKeystrokeCommit, this);
+
+ edit = getChild<LLLineEditor>("desc");
+ edit->setKeystrokeCallback(onKeystrokeCommit, this);
+
edit = getChild<LLLineEditor>("trigger_editor");
- edit->setKeystrokeCallback(onKeystrokeCommit);
- edit->setCommitCallback(onCommitSetDirty);
+ edit->setKeystrokeCallback(onKeystrokeCommit, this);
+ edit->setCommitCallback(onCommitSetDirty, this);
edit->setCommitOnFocusLost(TRUE);
- edit->setCallbackUserData(this);
edit->setIgnoreTab(TRUE);
mTriggerEditor = edit;
@@ -409,128 +383,107 @@ BOOL LLPreviewGesture::postBuild()
edit = getChild<LLLineEditor>("replace_editor");
edit->setEnabled(FALSE);
- edit->setKeystrokeCallback(onKeystrokeCommit);
- edit->setCommitCallback(onCommitSetDirty);
+ edit->setKeystrokeCallback(onKeystrokeCommit, this);
+ edit->setCommitCallback(onCommitSetDirty, this);
edit->setCommitOnFocusLost(TRUE);
- edit->setCallbackUserData(this);
edit->setIgnoreTab(TRUE);
mReplaceEditor = edit;
combo = getChild<LLComboBox>( "modifier_combo");
- combo->setCommitCallback(onCommitSetDirty);
- combo->setCallbackUserData(this);
+ combo->setCommitCallback(onCommitSetDirty, this);
mModifierCombo = combo;
combo = getChild<LLComboBox>( "key_combo");
- combo->setCommitCallback(onCommitSetDirty);
- combo->setCallbackUserData(this);
+ combo->setCommitCallback(onCommitSetDirty, this);
mKeyCombo = combo;
list = getChild<LLScrollListCtrl>("library_list");
- list->setCommitCallback(onCommitLibrary);
- list->setDoubleClickCallback(onClickAdd);
- list->setCallbackUserData(this);
+ list->setCommitCallback(onCommitLibrary, this);
+ list->setDoubleClickCallback(onClickAdd, this);
mLibraryList = list;
btn = getChild<LLButton>( "add_btn");
- btn->setClickedCallback(onClickAdd);
- btn->setCallbackUserData(this);
+ btn->setClickedCallback(onClickAdd, this);
btn->setEnabled(FALSE);
mAddBtn = btn;
btn = getChild<LLButton>( "up_btn");
- btn->setClickedCallback(onClickUp);
- btn->setCallbackUserData(this);
+ btn->setClickedCallback(onClickUp, this);
btn->setEnabled(FALSE);
mUpBtn = btn;
btn = getChild<LLButton>( "down_btn");
- btn->setClickedCallback(onClickDown);
- btn->setCallbackUserData(this);
+ btn->setClickedCallback(onClickDown, this);
btn->setEnabled(FALSE);
mDownBtn = btn;
btn = getChild<LLButton>( "delete_btn");
- btn->setClickedCallback(onClickDelete);
- btn->setCallbackUserData(this);
+ btn->setClickedCallback(onClickDelete, this);
btn->setEnabled(FALSE);
mDeleteBtn = btn;
list = getChild<LLScrollListCtrl>("step_list");
- list->setCommitCallback(onCommitStep);
- list->setCallbackUserData(this);
+ list->setCommitCallback(onCommitStep, this);
mStepList = list;
// Options
- text = getChild<LLTextBox>("options_text");
- text->setBorderVisible(TRUE);
- mOptionsText = text;
+ mOptionsText = getChild<LLTextBox>("options_text");
combo = getChild<LLComboBox>( "animation_list");
combo->setVisible(FALSE);
- combo->setCommitCallback(onCommitAnimation);
- combo->setCallbackUserData(this);
+ combo->setCommitCallback(onCommitAnimation, this);
mAnimationCombo = combo;
LLRadioGroup* group;
group = getChild<LLRadioGroup>("animation_trigger_type");
group->setVisible(FALSE);
- group->setCommitCallback(onCommitAnimationTrigger);
- group->setCallbackUserData(this);
+ group->setCommitCallback(onCommitAnimationTrigger, this);
mAnimationRadio = group;
combo = getChild<LLComboBox>( "sound_list");
combo->setVisible(FALSE);
- combo->setCommitCallback(onCommitSound);
- combo->setCallbackUserData(this);
+ combo->setCommitCallback(onCommitSound, this);
mSoundCombo = combo;
edit = getChild<LLLineEditor>("chat_editor");
edit->setVisible(FALSE);
- edit->setCommitCallback(onCommitChat);
- //edit->setKeystrokeCallback(onKeystrokeCommit);
+ edit->setCommitCallback(onCommitChat, this);
+ //edit->setKeystrokeCallback(onKeystrokeCommit, this);
edit->setCommitOnFocusLost(TRUE);
- edit->setCallbackUserData(this);
edit->setIgnoreTab(TRUE);
mChatEditor = edit;
check = getChild<LLCheckBoxCtrl>( "wait_anim_check");
check->setVisible(FALSE);
- check->setCommitCallback(onCommitWait);
- check->setCallbackUserData(this);
+ check->setCommitCallback(onCommitWait, this);
mWaitAnimCheck = check;
check = getChild<LLCheckBoxCtrl>( "wait_time_check");
check->setVisible(FALSE);
- check->setCommitCallback(onCommitWait);
- check->setCallbackUserData(this);
+ check->setCommitCallback(onCommitWait, this);
mWaitTimeCheck = check;
edit = getChild<LLLineEditor>("wait_time_editor");
edit->setEnabled(FALSE);
edit->setVisible(FALSE);
edit->setPrevalidate(LLLineEditor::prevalidateFloat);
-// edit->setKeystrokeCallback(onKeystrokeCommit);
+// edit->setKeystrokeCallback(onKeystrokeCommit, this);
edit->setCommitOnFocusLost(TRUE);
- edit->setCommitCallback(onCommitWaitTime);
- edit->setCallbackUserData(this);
+ edit->setCommitCallback(onCommitWaitTime, this);
edit->setIgnoreTab(TRUE);
mWaitTimeEditor = edit;
// Buttons at the bottom
check = getChild<LLCheckBoxCtrl>( "active_check");
- check->setCommitCallback(onCommitActive);
- check->setCallbackUserData(this);
+ check->setCommitCallback(onCommitActive, this);
mActiveCheck = check;
btn = getChild<LLButton>( "save_btn");
- btn->setClickedCallback(onClickSave);
- btn->setCallbackUserData(this);
+ btn->setClickedCallback(onClickSave, this);
mSaveBtn = btn;
btn = getChild<LLButton>( "preview_btn");
- btn->setClickedCallback(onClickPreview);
- btn->setCallbackUserData(this);
+ btn->setClickedCallback(onClickPreview, this);
mPreviewBtn = btn;
@@ -540,17 +493,20 @@ BOOL LLPreviewGesture::postBuild()
addAnimations();
addSounds();
-
const LLInventoryItem* item = getItem();
if (item)
{
childSetCommitCallback("desc", LLPreview::onText, this);
childSetText("desc", item->getDescription());
- childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
+ childSetPrevalidate("desc", &LLLineEditor::prevalidateASCIIPrintableNoPipe);
+
+ childSetCommitCallback("name", LLPreview::onText, this);
+ childSetText("name", item->getName());
+ childSetPrevalidate("name", &LLLineEditor::prevalidateASCIIPrintableNoPipe);
}
- return TRUE;
+ return LLPreview::postBuild();
}
@@ -605,7 +561,7 @@ void LLPreviewGesture::addAnimations()
PERM_ITEM_UNRESTRICTED,
gAgent.getID(),
gAgent.getGroupID());
- gInventory.collectDescendentsIf(gAgent.getInventoryRootID(),
+ gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
cats,
items,
LLInventoryModel::EXCLUDE_TRASH,
@@ -650,7 +606,7 @@ void LLPreviewGesture::addSounds()
PERM_ITEM_UNRESTRICTED,
gAgent.getID(),
gAgent.getGroupID());
- gInventory.collectDescendentsIf(gAgent.getInventoryRootID(),
+ gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
cats,
items,
LLInventoryModel::EXCLUDE_TRASH,
@@ -680,16 +636,9 @@ void LLPreviewGesture::addSounds()
}
-void LLPreviewGesture::init(const LLUUID& item_id, const LLUUID& object_id)
-{
- // Sets ID and adds to instance list
- setItemID(item_id);
- setObjectID(object_id);
-}
-
-
void LLPreviewGesture::refresh()
{
+ LLPreview::refresh();
// If previewing or item is incomplete, all controls are disabled
LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem();
bool is_complete = (item && item->isComplete()) ? true : false;
@@ -831,7 +780,7 @@ void LLPreviewGesture::refresh()
mOptionsText->setText(optionstext);
- BOOL active = gGestureManager.isGestureActive(mItemUUID);
+ BOOL active = LLGestureManager::instance().isGestureActive(mItemUUID);
mActiveCheck->set(active);
// Can only preview if there are steps
@@ -850,7 +799,7 @@ void LLPreviewGesture::initDefaultGesture()
item = addStep( STEP_ANIMATION );
LLGestureStepAnimation* anim = (LLGestureStepAnimation*)item->getUserdata();
anim->mAnimAssetID = ANIM_AGENT_HELLO;
- anim->mAnimName = "Wave";
+ anim->mAnimName = LLTrans::getString("Wave");
updateLabel(item);
item = addStep( STEP_WAIT );
@@ -860,7 +809,7 @@ void LLPreviewGesture::initDefaultGesture()
item = addStep( STEP_CHAT );
LLGestureStepChat* chat_step = (LLGestureStepChat*)item->getUserdata();
- chat_step->mChatText = "Hello, avatar!";
+ chat_step->mChatText = LLTrans::getString("HelloAvatar");
updateLabel(item);
// Start with item list selected
@@ -874,7 +823,11 @@ void LLPreviewGesture::initDefaultGesture()
void LLPreviewGesture::loadAsset()
{
const LLInventoryItem* item = getItem();
- if (!item) return;
+ if (!item)
+ {
+ mAssetStatus = PREVIEW_ASSET_ERROR;
+ return;
+ }
LLUUID asset_id = item->getAssetUUID();
if (asset_id.isNull())
@@ -883,6 +836,7 @@ void LLPreviewGesture::loadAsset()
// Blank gesture will be fine.
initDefaultGesture();
refresh();
+ mAssetStatus = PREVIEW_ASSET_LOADED;
return;
}
@@ -910,11 +864,10 @@ void LLPreviewGesture::onLoadComplete(LLVFS *vfs,
void* user_data, S32 status, LLExtStat ext_status)
{
LLUUID* item_idp = (LLUUID*)user_data;
- LLPreview* preview = LLPreview::find(*item_idp);
- if (preview)
- {
- LLPreviewGesture* self = (LLPreviewGesture*)preview;
+ LLPreviewGesture* self = LLFloaterReg::findTypedInstance<LLPreviewGesture>("preview_gesture", *item_idp);
+ if (self)
+ {
if (0 == status)
{
LLVFile file(vfs, asset_uuid, type, LLVFile::READ);
@@ -1016,7 +969,7 @@ void LLPreviewGesture::loadUIFromGesture(LLMultiGesture* gesture)
LLGestureStep* step = gesture->mSteps[i];
LLGestureStep* new_step = NULL;
-
+
switch(step->getType())
{
case STEP_ANIMATION:
@@ -1061,7 +1014,7 @@ void LLPreviewGesture::loadUIFromGesture(LLMultiGesture* gesture)
// Create an enabled item with this step
LLSD row;
- row["columns"][0]["value"] = new_step->getLabel();
+ row["columns"][0]["value"] = getLabel( new_step->getLabel());
row["columns"][0]["font"] = "SANSSERIF_SMALL";
LLScrollListItem* item = mStepList->addElement(row);
item->setUserdata(new_step);
@@ -1111,14 +1064,14 @@ void LLPreviewGesture::saveIfNeeded()
if (dp.getCurrentSize() > 1000)
{
- LLNotifications::instance().add("GestureSaveFailedTooManySteps");
+ LLNotificationsUtil::add("GestureSaveFailedTooManySteps");
delete gesture;
gesture = NULL;
}
else if (!ok)
{
- LLNotifications::instance().add("GestureSaveFailedTryAgain");
+ LLNotificationsUtil::add("GestureSaveFailedTryAgain");
delete gesture;
gesture = NULL;
}
@@ -1179,10 +1132,10 @@ void LLPreviewGesture::saveIfNeeded()
// If this gesture is active, then we need to update the in-memory
// active map with the new pointer.
- if (!delayedUpload && gGestureManager.isGestureActive(mItemUUID))
+ if (!delayedUpload && LLGestureManager::instance().isGestureActive(mItemUUID))
{
// gesture manager now owns the pointer
- gGestureManager.replaceGesture(mItemUUID, gesture, asset_id);
+ LLGestureManager::instance().replaceGesture(mItemUUID, gesture, asset_id);
// replaceGesture may deactivate other gestures so let the
// inventory know.
@@ -1235,7 +1188,7 @@ void LLPreviewGesture::onSaveComplete(const LLUUID& asset_uuid, void* user_data,
else
{
llwarns << "Inventory item for gesture " << info->mItemUUID
- << " is no longer in agent inventory." << llendl
+ << " is no longer in agent inventory." << llendl;
}
}
else
@@ -1257,15 +1210,15 @@ void LLPreviewGesture::onSaveComplete(const LLUUID& asset_uuid, void* user_data,
}
else
{
- LLNotifications::instance().add("GestureSaveFailedObjectNotFound");
+ LLNotificationsUtil::add("GestureSaveFailedObjectNotFound");
}
}
// Find our window and close it if requested.
- LLPreviewGesture* previewp = (LLPreviewGesture*)LLPreview::find(info->mItemUUID);
+ LLPreviewGesture* previewp = LLFloaterReg::findTypedInstance<LLPreviewGesture>("preview_gesture", info->mItemUUID);
if (previewp && previewp->mCloseAfterSave)
{
- previewp->close();
+ previewp->closeFloater();
}
}
else
@@ -1273,7 +1226,7 @@ void LLPreviewGesture::onSaveComplete(const LLUUID& asset_uuid, void* user_data,
llwarns << "Problem saving gesture: " << status << llendl;
LLSD args;
args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
- LLNotifications::instance().add("GestureSaveFailedReason", args);
+ LLNotificationsUtil::add("GestureSaveFailedReason", args);
}
delete info;
info = NULL;
@@ -1374,7 +1327,7 @@ void LLPreviewGesture::updateLabel(LLScrollListItem* item)
LLScrollListCell* cell = item->getColumn(0);
LLScrollListText* text_cell = (LLScrollListText*)cell;
- std::string label = step->getLabel();
+ std::string label = getLabel( step->getLabel());
text_cell->setText(label);
}
@@ -1619,24 +1572,26 @@ LLScrollListItem* LLPreviewGesture::addStep( const EStepType step_type )
{
case STEP_ANIMATION:
step = new LLGestureStepAnimation();
+
break;
case STEP_SOUND:
step = new LLGestureStepSound();
break;
case STEP_CHAT:
- step = new LLGestureStepChat();
+ step = new LLGestureStepChat();
break;
case STEP_WAIT:
- step = new LLGestureStepWait();
+ step = new LLGestureStepWait();
break;
default:
llerrs << "Unknown step type: " << (S32)step_type << llendl;
return NULL;
}
+
// Create an enabled item with this step
LLSD row;
- row["columns"][0]["value"] = step->getLabel();
+ row["columns"][0]["value"] = getLabel(step->getLabel());
row["columns"][0]["font"] = "SANSSERIF_SMALL";
LLScrollListItem* step_item = mStepList->addElement(row);
step_item->setUserdata(step);
@@ -1651,6 +1606,42 @@ LLScrollListItem* LLPreviewGesture::addStep( const EStepType step_type )
}
// static
+std::string LLPreviewGesture::getLabel(std::vector<std::string> labels)
+{
+ std::vector<std::string> v_labels = labels ;
+ std::string result("");
+
+ if( v_labels.size() != 2)
+ {
+ return result;
+ }
+
+ if(v_labels[0]=="Chat")
+ {
+ result=LLTrans::getString("Chat");
+ }
+ else if(v_labels[0]=="Sound")
+ {
+ result=LLTrans::getString("Sound");
+ }
+ else if(v_labels[0]=="Wait")
+ {
+ result=LLTrans::getString("Wait");
+ }
+ else if(v_labels[0]=="AnimFlagStop")
+ {
+ result=LLTrans::getString("AnimFlagStop");
+ }
+ else if(v_labels[0]=="AnimFlagStart")
+ {
+ result=LLTrans::getString("AnimFlagStart");
+ }
+
+ result.append(v_labels[1]);
+ return result;
+
+}
+// static
void LLPreviewGesture::onClickUp(void* data)
{
LLPreviewGesture* self = (LLPreviewGesture*)data;
@@ -1705,13 +1696,13 @@ void LLPreviewGesture::onClickDelete(void* data)
void LLPreviewGesture::onCommitActive(LLUICtrl* ctrl, void* data)
{
LLPreviewGesture* self = (LLPreviewGesture*)data;
- if (!gGestureManager.isGestureActive(self->mItemUUID))
+ if (!LLGestureManager::instance().isGestureActive(self->mItemUUID))
{
- gGestureManager.activateGesture(self->mItemUUID);
+ LLGestureManager::instance().activateGesture(self->mItemUUID);
}
else
{
- gGestureManager.deactivateGesture(self->mItemUUID);
+ LLGestureManager::instance().deactivateGesture(self->mItemUUID);
}
// Make sure the (active) label in the inventory gets updated.
@@ -1750,14 +1741,14 @@ void LLPreviewGesture::onClickPreview(void* data)
self->mPreviewBtn->setLabel(self->getString("stop_txt"));
// play it, and delete when done
- gGestureManager.playGesture(self->mPreviewGesture);
+ LLGestureManager::instance().playGesture(self->mPreviewGesture);
self->refresh();
}
else
{
// Will call onDonePreview() below
- gGestureManager.stopGesture(self->mPreviewGesture);
+ LLGestureManager::instance().stopGesture(self->mPreviewGesture);
self->refresh();
}
diff --git a/indra/newview/llpreviewgesture.h b/indra/newview/llpreviewgesture.h
index c245c0e8da..19fa1dcc37 100644
--- a/indra/newview/llpreviewgesture.h
+++ b/indra/newview/llpreviewgesture.h
@@ -33,8 +33,9 @@
#ifndef LL_LLPREVIEWGESTURE_H
#define LL_LLPREVIEWGESTURE_H
-#include "llpreview.h"
+#include "llassettype.h"
#include "llmultigesture.h"
+#include "llpreview.h"
class LLMultiGesture;
class LLLineEditor;
@@ -46,46 +47,42 @@ class LLScrollListItem;
class LLButton;
class LLGestureStep;
class LLRadioGroup;
+class LLVFS;
class LLPreviewGesture : public LLPreview
{
public:
// Pass an object_id if this gesture is inside an object in the world,
// otherwise use LLUUID::null.
- static LLPreviewGesture* show(const std::string& title, const LLUUID& item_id, const LLUUID& object_id, BOOL take_focus = TRUE);
+ static LLPreviewGesture* show(const LLUUID& item_id, const LLUUID& object_id);
+
+ LLPreviewGesture(const LLSD& key);
+ virtual ~LLPreviewGesture();
// LLView
- virtual BOOL handleKeyHere(KEY key, MASK mask);
- virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
+ /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg);
// LLPanel
- virtual BOOL postBuild();
+ /*virtual*/ BOOL postBuild();
// LLFloater
- virtual BOOL canClose();
- virtual void setMinimized(BOOL minimize);
- virtual void onClose(bool app_quitting);
- virtual void onUpdateSucceeded();
-
+ /*virtual*/ BOOL canClose();
+ /*virtual*/ void onClose(bool app_quitting);
+ /*virtual*/ void onUpdateSucceeded();
+ /*virtual*/ void refresh();
protected:
- LLPreviewGesture();
- virtual ~LLPreviewGesture();
-
- void init(const LLUUID& item_id, const LLUUID& object_id);
-
// Populate various comboboxes
void addModifiers();
void addKeys();
void addAnimations();
void addSounds();
- void refresh();
-
void initDefaultGesture();
void loadAsset();
@@ -111,7 +108,10 @@ protected:
// Add a step. Pass the name of the step, like "Animation",
// "Sound", "Chat", or "Wait"
LLScrollListItem* addStep(const enum EStepType step_type);
-
+
+ void onVisibilityChange ( const LLSD& new_visibility );
+
+ static std::string getLabel(std::vector<std::string> labels);
static void updateLabel(LLScrollListItem* item);
static void onCommitSetDirty(LLUICtrl* ctrl, void* data);
@@ -139,8 +139,6 @@ protected:
static void onDonePreview(LLMultiGesture* gesture, void* data);
- virtual const char *getTitleName() const { return "Gesture"; }
-
protected:
// LLPreview contains mDescEditor
LLLineEditor* mTriggerEditor;
diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp
index 4abe390bc5..cc70360528 100644
--- a/indra/newview/llpreviewnotecard.cpp
+++ b/indra/newview/llpreviewnotecard.cpp
@@ -40,9 +40,10 @@
#include "llassetuploadresponders.h"
#include "llviewerwindow.h"
#include "llbutton.h"
+#include "llfloaterreg.h"
#include "llinventorymodel.h"
#include "lllineeditor.h"
-#include "llnotify.h"
+#include "llnotificationsutil.h"
#include "llresmgr.h"
#include "roles_constants.h"
#include "llscrollbar.h"
@@ -54,7 +55,6 @@
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "lldir.h"
-//#include "llfloaterchat.h"
#include "llviewerstats.h"
#include "llviewercontrol.h" // gSavedSettings
#include "llappviewer.h" // app_abort_quit()
@@ -62,91 +62,19 @@
#include "lluictrlfactory.h"
///----------------------------------------------------------------------------
-/// Local function declarations, constants, enums, and typedefs
-///----------------------------------------------------------------------------
-
-const S32 PREVIEW_MIN_WIDTH =
- 2 * PREVIEW_BORDER +
- 2 * PREVIEW_BUTTON_WIDTH +
- PREVIEW_PAD + RESIZE_HANDLE_WIDTH +
- PREVIEW_PAD;
-const S32 PREVIEW_MIN_HEIGHT =
- 2 * PREVIEW_BORDER +
- 3*(20 + PREVIEW_PAD) +
- 2 * SCROLLBAR_SIZE + 128;
-
-///----------------------------------------------------------------------------
/// Class LLPreviewNotecard
///----------------------------------------------------------------------------
// Default constructor
-LLPreviewNotecard::LLPreviewNotecard(const std::string& name,
- const LLRect& rect,
- const std::string& title,
- const LLUUID& item_id,
- const LLUUID& object_id,
- const LLUUID& asset_id,
- BOOL show_keep_discard,
- LLPointer<LLViewerInventoryItem> inv_item) :
- LLPreview(name, rect, title, item_id, object_id, TRUE,
- PREVIEW_MIN_WIDTH,
- PREVIEW_MIN_HEIGHT,
- inv_item),
- mAssetID( asset_id ),
- mNotecardItemID(item_id),
- mObjectID(object_id)
+LLPreviewNotecard::LLPreviewNotecard(const LLSD& key) //const LLUUID& item_id,
+ : LLPreview( key )
{
- LLRect curRect = rect;
-
- if (show_keep_discard)
- {
- LLUICtrlFactory::getInstance()->buildFloater(this,"floater_preview_notecard_keep_discard.xml");
- childSetAction("Keep",onKeepBtn,this);
- childSetAction("Discard",onDiscardBtn,this);
- }
- else
- {
- LLUICtrlFactory::getInstance()->buildFloater(this,"floater_preview_notecard.xml");
- childSetAction("Save",onClickSave,this);
-
- if( mAssetID.isNull() )
- {
- const LLInventoryItem* item = getItem();
- if( item )
- {
- mAssetID = item->getAssetUUID();
- }
- }
- }
-
- // only assert shape if not hosted in a multifloater
- if (!getHost())
- {
- reshape(curRect.getWidth(), curRect.getHeight(), TRUE);
- setRect(curRect);
- }
-
- childSetVisible("lock", FALSE);
-
- const LLInventoryItem* item = getItem();
-
- childSetCommitCallback("desc", LLPreview::onText, this);
+ const LLInventoryItem *item = getItem();
if (item)
- childSetText("desc", item->getDescription());
- childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
-
- setTitle(title);
-
- LLViewerTextEditor* editor = getChild<LLViewerTextEditor>("Notecard Editor");
-
- if (editor)
{
- editor->setWordWrap(TRUE);
- editor->setSourceID(item_id);
- editor->setHandleEditKeysDirectly(TRUE);
- }
-
- gAgent.changeCameraToDefault();
+ mAssetID = item->getAssetUUID();
+ }
+ //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this,"floater_preview_notecard.xml", FALSE);
}
LLPreviewNotecard::~LLPreviewNotecard()
@@ -156,27 +84,26 @@ LLPreviewNotecard::~LLPreviewNotecard()
BOOL LLPreviewNotecard::postBuild()
{
LLViewerTextEditor *ed = getChild<LLViewerTextEditor>("Notecard Editor");
- if (ed)
- {
- ed->setNotecardInfo(mNotecardItemID, mObjectID);
- ed->makePristine();
- }
- return TRUE;
+ ed->setNotecardInfo(mItemUUID, mObjectID, getKey());
+ ed->makePristine();
+
+ childSetAction("Save", onClickSave, this);
+ childSetVisible("lock", FALSE);
+
+ const LLInventoryItem* item = getItem();
+
+ childSetCommitCallback("desc", LLPreview::onText, this);
+ if (item)
+ childSetText("desc", item->getDescription());
+ childSetPrevalidate("desc", &LLLineEditor::prevalidateASCIIPrintableNoPipe);
+
+ return LLPreview::postBuild();
}
-bool LLPreviewNotecard::saveItem(LLPointer<LLInventoryItem>* itemptr)
+bool LLPreviewNotecard::saveItem()
{
- LLInventoryItem* item = NULL;
- if (itemptr && itemptr->notNull())
- {
- item = (LLInventoryItem*)(*itemptr);
- }
- bool res = saveIfNeeded(item);
- if (res)
- {
- delete itemptr;
- }
- return res;
+ LLInventoryItem* item = gInventory.getItem(mItemUUID);
+ return saveIfNeeded(item);
}
void LLPreviewNotecard::setEnabled( BOOL enabled )
@@ -188,20 +115,15 @@ void LLPreviewNotecard::setEnabled( BOOL enabled )
childSetVisible("lock", !enabled);
childSetEnabled("desc", enabled);
childSetEnabled("Save", enabled && editor && (!editor->isPristine()));
-
}
void LLPreviewNotecard::draw()
{
-
-
- //childSetFocus("Save", FALSE);
-
LLViewerTextEditor* editor = getChild<LLViewerTextEditor>("Notecard Editor");
- BOOL script_changed = !editor->isPristine();
-
- childSetEnabled("Save", script_changed && getEnabled());
+ BOOL changed = !editor->isPristine();
+
+ childSetEnabled("Save", changed && getEnabled());
LLPreview::draw();
}
@@ -230,7 +152,7 @@ BOOL LLPreviewNotecard::canClose()
else
{
// Bring up view-modal dialog: Save changes? Yes, No, Cancel
- LLNotifications::instance().add("SaveChanges", LLSD(), LLSD(), boost::bind(&LLPreviewNotecard::handleSaveChangesDialog,this, _1, _2));
+ LLNotificationsUtil::add("SaveChanges", LLSD(), LLSD(), boost::bind(&LLPreviewNotecard::handleSaveChangesDialog,this, _1, _2));
return FALSE;
}
@@ -255,8 +177,13 @@ bool LLPreviewNotecard::hasEmbeddedInventory()
return editor->hasEmbeddedInventory();
}
-void LLPreviewNotecard::refreshFromInventory()
+void LLPreviewNotecard::refreshFromInventory(const LLUUID& new_item_id)
{
+ if (new_item_id.notNull())
+ {
+ mItemUUID = new_item_id;
+ setKey(LLSD(new_item_id));
+ }
lldebugs << "LLPreviewNotecard::refreshFromInventory()" << llendl;
loadAsset();
}
@@ -287,7 +214,6 @@ void LLPreviewNotecard::loadAsset()
}
else
{
- LLUUID* new_uuid = new LLUUID(mItemUUID);
LLHost source_sim = LLHost::invalid;
if (mObjectUUID.notNull())
{
@@ -305,7 +231,6 @@ void LLPreviewNotecard::loadAsset()
editor->makePristine();
editor->setEnabled(FALSE);
mAssetStatus = PREVIEW_ASSET_LOADED;
- delete new_uuid;
return;
}
}
@@ -318,7 +243,7 @@ void LLPreviewNotecard::loadAsset()
item->getAssetUUID(),
item->getType(),
&onLoadComplete,
- (void*)new_uuid,
+ (void*)new LLUUID(mItemUUID),
TRUE);
mAssetStatus = PREVIEW_ASSET_LOADING;
}
@@ -343,7 +268,9 @@ void LLPreviewNotecard::loadAsset()
editor->setText(LLStringUtil::null);
editor->makePristine();
editor->setEnabled(TRUE);
- mAssetStatus = PREVIEW_ASSET_LOADED;
+ // Don't set asset status here; we may not have set the item id yet
+ // (e.g. when this gets called initially)
+ //mAssetStatus = PREVIEW_ASSET_LOADED;
}
}
@@ -355,7 +282,8 @@ void LLPreviewNotecard::onLoadComplete(LLVFS *vfs,
{
llinfos << "LLPreviewNotecard::onLoadComplete()" << llendl;
LLUUID* item_id = (LLUUID*)user_data;
- LLPreviewNotecard* preview = LLPreviewNotecard::getInstance(*item_id);
+
+ LLPreviewNotecard* preview = LLFloaterReg::findTypedInstance<LLPreviewNotecard>("preview_notecard", LLSD(*item_id));
if( preview )
{
if(0 == status)
@@ -401,15 +329,15 @@ void LLPreviewNotecard::onLoadComplete(LLVFS *vfs,
if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
LL_ERR_FILE_EMPTY == status)
{
- LLNotifications::instance().add("NotecardMissing");
+ LLNotificationsUtil::add("NotecardMissing");
}
else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
{
- LLNotifications::instance().add("NotecardNoPermissions");
+ LLNotificationsUtil::add("NotecardNoPermissions");
}
else
{
- LLNotifications::instance().add("UnableToLoadNotecard");
+ LLNotificationsUtil::add("UnableToLoadNotecard");
}
llwarns << "Problem loading notecard: " << status << llendl;
@@ -420,18 +348,6 @@ void LLPreviewNotecard::onLoadComplete(LLVFS *vfs,
}
// static
-LLPreviewNotecard* LLPreviewNotecard::getInstance(const LLUUID& item_id)
-{
- LLPreview* instance = NULL;
- preview_map_t::iterator found_it = LLPreview::sInstances.find(item_id);
- if(found_it != LLPreview::sInstances.end())
- {
- instance = found_it->second;
- }
- return (LLPreviewNotecard*)instance;
-}
-
-// static
void LLPreviewNotecard::onClickSave(void* user_data)
{
//llinfos << "LLPreviewNotecard::onBtnSave()" << llendl;
@@ -576,7 +492,7 @@ void LLPreviewNotecard::onSaveComplete(const LLUUID& asset_uuid, void* user_data
}
else
{
- LLNotifications::instance().add("SaveNotecardFailObjectNotFound");
+ LLNotificationsUtil::add("SaveNotecardFailObjectNotFound");
}
}
// Perform item copy to inventory
@@ -590,10 +506,11 @@ void LLPreviewNotecard::onSaveComplete(const LLUUID& asset_uuid, void* user_data
}
// Find our window and close it if requested.
- LLPreviewNotecard* previewp = (LLPreviewNotecard*)LLPreview::find(info->mItemUUID);
+
+ LLPreviewNotecard* previewp = LLFloaterReg::findTypedInstance<LLPreviewNotecard>("preview_notecard", info->mItemUUID);
if (previewp && previewp->mCloseAfterSave)
{
- previewp->close();
+ previewp->closeFloater();
}
}
else
@@ -601,7 +518,7 @@ void LLPreviewNotecard::onSaveComplete(const LLUUID& asset_uuid, void* user_data
llwarns << "Problem saving notecard: " << status << llendl;
LLSD args;
args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
- LLNotifications::instance().add("SaveNotecardFailReason", args);
+ LLNotificationsUtil::add("SaveNotecardFailReason", args);
}
std::string uuid_string;
@@ -614,7 +531,7 @@ void LLPreviewNotecard::onSaveComplete(const LLUUID& asset_uuid, void* user_data
bool LLPreviewNotecard::handleSaveChangesDialog(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
switch(option)
{
case 0: // "Yes"
@@ -624,7 +541,7 @@ bool LLPreviewNotecard::handleSaveChangesDialog(const LLSD& notification, const
case 1: // "No"
mForceClose = TRUE;
- close();
+ closeFloater();
break;
case 2: // "Cancel"
@@ -636,16 +553,4 @@ bool LLPreviewNotecard::handleSaveChangesDialog(const LLSD& notification, const
return false;
}
-void LLPreviewNotecard::reshape(S32 width, S32 height, BOOL called_from_parent)
-{
- LLPreview::reshape( width, height, called_from_parent );
-
- if( !isMinimized() )
- {
- // So that next time you open a script it will have the same height and width
- // (although not the same position).
- gSavedSettings.setRect("NotecardEditorRect", getRect());
- }
-}
-
// EOF
diff --git a/indra/newview/llpreviewnotecard.h b/indra/newview/llpreviewnotecard.h
index f5cd2bb2a9..5b8cf1c2f6 100644
--- a/indra/newview/llpreviewnotecard.h
+++ b/indra/newview/llpreviewnotecard.h
@@ -49,28 +49,21 @@ class LLButton;
class LLPreviewNotecard : public LLPreview
{
public:
- LLPreviewNotecard(const std::string& name, const LLRect& rect, const std::string& title,
- const LLUUID& item_id,
- const LLUUID& object_id = LLUUID::null,
- const LLUUID& asset_id = LLUUID::null,
- BOOL show_keep_discard = FALSE,
- LLPointer<LLViewerInventoryItem> inv_item = NULL);
+ LLPreviewNotecard(const LLSD& key);
virtual ~LLPreviewNotecard();
- // llpreview
- virtual bool saveItem(LLPointer<LLInventoryItem>* itemptr);
+ bool saveItem();
// llview
virtual void draw();
virtual BOOL handleKeyHere(KEY key, MASK mask);
virtual void setEnabled( BOOL enabled );
- virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
// llfloater
virtual BOOL canClose();
// llpanel
- virtual BOOL postBuild();
+ virtual BOOL postBuild();
// reach into the text editor, and grab the drag item
const LLInventoryItem* getDragItem();
@@ -82,15 +75,13 @@ public:
// After saving a notecard, the tcp based upload system will
// change the asset, therefore, we need to re-fetch it from the
// asset system. :(
- void refreshFromInventory();
+ void refreshFromInventory(const LLUUID& item_id = LLUUID::null);
protected:
virtual void loadAsset();
bool saveIfNeeded(LLInventoryItem* copyitem = NULL);
- static LLPreviewNotecard* getInstance(const LLUUID& uuid);
-
static void onLoadComplete(LLVFS *vfs,
const LLUUID& asset_uuid,
LLAssetType::EType type,
@@ -104,15 +95,12 @@ protected:
bool handleSaveChangesDialog(const LLSD& notification, const LLSD& response);
- virtual const char *getTitleName() const { return "Note"; }
-
protected:
LLViewerTextEditor* mEditor;
LLButton* mSaveBtn;
LLUUID mAssetID;
- LLUUID mNotecardItemID;
LLUUID mObjectID;
};
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 0bacb95d2d..fccf71f3cb 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -40,23 +40,27 @@
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#include "lldir.h"
+#include "llfloaterreg.h"
#include "llinventorymodel.h"
#include "llkeyboard.h"
#include "lllineeditor.h"
-
+#include "llhelp.h"
+#include "llnotificationsutil.h"
#include "llresmgr.h"
#include "llscrollbar.h"
#include "llscrollcontainer.h"
#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "llscrolllistcell.h"
#include "llslider.h"
#include "lscript_rt_interface.h"
+#include "lscript_library.h"
#include "lscript_export.h"
#include "lltextbox.h"
#include "lltooldraganddrop.h"
#include "llvfile.h"
#include "llagent.h"
-#include "llnotify.h"
#include "llmenugl.h"
#include "roles_constants.h"
#include "llselectmgr.h"
@@ -75,20 +79,16 @@
#include "llslider.h"
#include "lldir.h"
#include "llcombobox.h"
-//#include "llfloaterchat.h"
#include "llviewerstats.h"
#include "llviewertexteditor.h"
#include "llviewerwindow.h"
#include "lluictrlfactory.h"
-#include "llwebbrowserctrl.h"
+#include "llmediactrl.h"
#include "lluictrlfactory.h"
-
+#include "lltrans.h"
#include "llviewercontrol.h"
#include "llappviewer.h"
-#include "llpanelinventory.h"
-
-
const std::string HELLO_LSL =
"default\n"
"{\n"
@@ -102,41 +102,15 @@ const std::string HELLO_LSL =
" llSay(0, \"Touched.\");\n"
" }\n"
"}\n";
-const std::string HELP_LSL_URL = "http://wiki.secondlife.com/wiki/LSL_Portal";
+const std::string HELP_LSL_PORTAL_TOPIC = "LSL_Portal";
const std::string DEFAULT_SCRIPT_NAME = "New Script"; // *TODO:Translate?
const std::string DEFAULT_SCRIPT_DESC = "(No Description)"; // *TODO:Translate?
// Description and header information
-const S32 SCRIPT_BORDER = 4;
-const S32 SCRIPT_PAD = 5;
-const S32 SCRIPT_BUTTON_WIDTH = 128;
-const S32 SCRIPT_BUTTON_HEIGHT = 24; // HACK: Use BTN_HEIGHT where possible.
-const S32 LINE_COLUMN_HEIGHT = 14;
-const S32 BTN_PAD = 8;
-
-const S32 SCRIPT_EDITOR_MIN_HEIGHT = 2 * SCROLLBAR_SIZE + 2 * LLPANEL_BORDER_WIDTH + 128;
-
-const S32 SCRIPT_MIN_WIDTH =
- 2 * SCRIPT_BORDER +
- 2 * SCRIPT_BUTTON_WIDTH +
- SCRIPT_PAD + RESIZE_HANDLE_WIDTH +
- SCRIPT_PAD;
-
-const S32 SCRIPT_MIN_HEIGHT =
- 2 * SCRIPT_BORDER +
- 3*(SCRIPT_BUTTON_HEIGHT + SCRIPT_PAD) +
- LINE_COLUMN_HEIGHT +
- SCRIPT_EDITOR_MIN_HEIGHT;
-
const S32 MAX_EXPORT_SIZE = 1000;
-const S32 SCRIPT_SEARCH_WIDTH = 300;
-const S32 SCRIPT_SEARCH_HEIGHT = 120;
-const S32 SCRIPT_SEARCH_LABEL_WIDTH = 50;
-const S32 SCRIPT_SEARCH_BUTTON_WIDTH = 80;
-const S32 TEXT_EDIT_COLUMN_HEIGHT = 16;
const S32 MAX_HISTORY_COUNT = 10;
const F32 LIVE_HELP_REFRESH_TIME = 1.f;
@@ -152,9 +126,10 @@ static bool have_script_upload_cap(LLUUID& object_id)
class LLFloaterScriptSearch : public LLFloater
{
public:
- LLFloaterScriptSearch(std::string title, LLRect rect, LLScriptEdCore* editor_core);
+ LLFloaterScriptSearch(LLScriptEdCore* editor_core);
~LLFloaterScriptSearch();
+ /*virtual*/ BOOL postBuild();
static void show(LLScriptEdCore* editor_core);
static void onBtnSearch(void* userdata);
void handleBtnSearch();
@@ -168,8 +143,6 @@ public:
LLScriptEdCore* getEditorCore() { return mEditorCore; }
static LLFloaterScriptSearch* getInstance() { return sInstance; }
- void open(); /*Flawfinder: ignore*/
-
private:
LLScriptEdCore* mEditorCore;
@@ -179,28 +152,14 @@ private:
LLFloaterScriptSearch* LLFloaterScriptSearch::sInstance = NULL;
-LLFloaterScriptSearch::LLFloaterScriptSearch(std::string title, LLRect rect, LLScriptEdCore* editor_core)
- : LLFloater("script search",rect,title), mEditorCore(editor_core)
+LLFloaterScriptSearch::LLFloaterScriptSearch(LLScriptEdCore* editor_core)
+: LLFloater(LLSD()),
+ mEditorCore(editor_core)
{
-
- LLUICtrlFactory::getInstance()->buildFloater(this,"floater_script_search.xml");
+ LLUICtrlFactory::getInstance()->buildFloater(this,"floater_script_search.xml", NULL);
- childSetAction("search_btn", onBtnSearch,this);
- childSetAction("replace_btn", onBtnReplace,this);
- childSetAction("replace_all_btn", onBtnReplaceAll,this);
-
- setDefaultBtn("search_btn");
-
- if (!getHost())
- {
- LLRect curRect = getRect();
- translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop);
- }
-
sInstance = this;
-
- childSetFocus("search_text", TRUE);
-
+
// find floater in which script panel is embedded
LLView* viewp = (LLView*)editor_core;
while(viewp)
@@ -215,26 +174,33 @@ LLFloaterScriptSearch::LLFloaterScriptSearch(std::string title, LLRect rect, LLS
}
}
+BOOL LLFloaterScriptSearch::postBuild()
+{
+ childSetAction("search_btn", onBtnSearch,this);
+ childSetAction("replace_btn", onBtnReplace,this);
+ childSetAction("replace_all_btn", onBtnReplaceAll,this);
+
+ setDefaultBtn("search_btn");
+
+ return TRUE;
+}
+
//static
void LLFloaterScriptSearch::show(LLScriptEdCore* editor_core)
{
if (sInstance && sInstance->mEditorCore && sInstance->mEditorCore != editor_core)
{
- sInstance->close();
+ sInstance->closeFloater();
delete sInstance;
}
if (!sInstance)
{
- S32 left = 0;
- S32 top = 0;
- gFloaterView->getNewFloaterPosition(&left,&top);
-
// sInstance will be assigned in the constructor.
- new LLFloaterScriptSearch("Script Search",LLRect(left,top,left + SCRIPT_SEARCH_WIDTH,top - SCRIPT_SEARCH_HEIGHT),editor_core);
+ new LLFloaterScriptSearch(editor_core);
}
- sInstance->open(); /*Flawfinder: ignore*/
+ sInstance->openFloater();
}
LLFloaterScriptSearch::~LLFloaterScriptSearch()
@@ -281,21 +247,22 @@ void LLFloaterScriptSearch::handleBtnReplaceAll()
mEditorCore->mEditor->replaceTextAll(childGetText("search_text"), childGetText("replace_text"), caseChk->get());
}
-void LLFloaterScriptSearch::open() /*Flawfinder: ignore*/
-{
- LLFloater::open(); /*Flawfinder: ignore*/
- childSetFocus("search_text", TRUE);
-}
+
/// ---------------------------------------------------------------------------
/// LLScriptEdCore
/// ---------------------------------------------------------------------------
+struct LLSECKeywordCompare
+{
+ bool operator()(const std::string& lhs, const std::string& rhs)
+ {
+ return (LLStringUtil::compareDictInsensitive( lhs, rhs ) < 0 );
+ }
+};
+
LLScriptEdCore::LLScriptEdCore(
- const std::string& name,
- const LLRect& rect,
const std::string& sample,
- const std::string& help_url,
const LLHandle<LLFloater>& floater_handle,
void (*load_callback)(void*),
void (*save_callback)(void*, BOOL),
@@ -303,9 +270,8 @@ LLScriptEdCore::LLScriptEdCore(
void* userdata,
S32 bottom_pad)
:
- LLPanel( std::string("name"), rect ),
+ LLPanel(),
mSampleText(sample),
- mHelpURL(help_url),
mEditor( NULL ),
mLoadCallback( load_callback ),
mSaveCallback( save_callback ),
@@ -320,127 +286,155 @@ LLScriptEdCore::LLScriptEdCore(
setFollowsAll();
setBorderVisible(FALSE);
-
- LLUICtrlFactory::getInstance()->buildPanel(this, "floater_script_ed_panel.xml");
+ setXMLFilename("panel_script_ed.xml");
+}
+LLScriptEdCore::~LLScriptEdCore()
+{
+ deleteBridges();
+
+ // If the search window is up for this editor, close it.
+ LLFloaterScriptSearch* script_search = LLFloaterScriptSearch::getInstance();
+ if (script_search && script_search->getEditorCore() == this)
+ {
+ script_search->closeFloater();
+ delete script_search;
+ }
+}
+
+BOOL LLScriptEdCore::postBuild()
+{
mErrorList = getChild<LLScrollListCtrl>("lsl errors");
mFunctions = getChild<LLComboBox>( "Insert...");
-
+
childSetCommitCallback("Insert...", &LLScriptEdCore::onBtnInsertFunction, this);
mEditor = getChild<LLViewerTextEditor>("Script Editor");
- mEditor->setFollowsAll();
- mEditor->setHandleEditKeysDirectly(TRUE);
- mEditor->setEnabled(TRUE);
- mEditor->setWordWrap(TRUE);
+
+ childSetCommitCallback("lsl errors", &LLScriptEdCore::onErrorList, this);
+ childSetAction("Save_btn", boost::bind(&LLScriptEdCore::doSave,this,FALSE));
+
+ initMenu();
+
std::vector<std::string> funcs;
std::vector<std::string> tooltips;
- for (S32 i = 0; i < gScriptLibrary.mNextNumber; i++)
+ for (std::vector<LLScriptLibraryFunction>::const_iterator i = gScriptLibrary.mFunctions.begin();
+ i != gScriptLibrary.mFunctions.end(); ++i)
{
// Make sure this isn't a god only function, or the agent is a god.
- if (!gScriptLibrary.mFunctions[i]->mGodOnly || gAgent.isGodlike())
+ if (!i->mGodOnly || gAgent.isGodlike())
{
- funcs.push_back(ll_safe_string(gScriptLibrary.mFunctions[i]->mName));
- tooltips.push_back(ll_safe_string(gScriptLibrary.mFunctions[i]->mDesc));
+ std::string name = i->mName;
+ funcs.push_back(name);
+
+ std::string desc_name = "LSLTipText_";
+ desc_name += name;
+ std::string desc = LLTrans::getString(desc_name);
+
+ F32 sleep_time = i->mSleepTime;
+ if( sleep_time )
+ {
+ desc += "\n";
+
+ LLStringUtil::format_map_t args;
+ args["[SLEEP_TIME]"] = llformat("%.1f", sleep_time );
+ desc += LLTrans::getString("LSLTipSleepTime", args);
+ }
+
+ // A \n linefeed is not part of xml. Let's add one to keep all
+ // the tips one-per-line in strings.xml
+ LLStringUtil::replaceString( desc, "\\n", "\n" );
+
+ tooltips.push_back(desc);
}
}
+
LLColor3 color(0.5f, 0.0f, 0.15f);
-
mEditor->loadKeywords(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"keywords.ini"), funcs, tooltips, color);
-
+ std::vector<std::string> primary_keywords;
+ std::vector<std::string> secondary_keywords;
LLKeywordToken *token;
LLKeywords::keyword_iterator_t token_it;
for (token_it = mEditor->keywordsBegin(); token_it != mEditor->keywordsEnd(); ++token_it)
{
token = token_it->second;
- if (token->getColor() == color)
- mFunctions->add(wstring_to_utf8str(token->getToken()));
+ if (token->getColor() == color) // Wow, what a disgusting hack.
+ {
+ primary_keywords.push_back( wstring_to_utf8str(token->getToken()) );
+ }
+ else
+ {
+ secondary_keywords.push_back( wstring_to_utf8str(token->getToken()) );
+ }
}
- for (token_it = mEditor->keywordsBegin(); token_it != mEditor->keywordsEnd(); ++token_it)
+ // Case-insensitive dictionary sort for primary keywords. We don't sort the secondary
+ // keywords. They're intelligently grouped in keywords.ini.
+ std::stable_sort( primary_keywords.begin(), primary_keywords.end(), LLSECKeywordCompare() );
+
+ for (std::vector<std::string>::const_iterator iter= primary_keywords.begin();
+ iter!= primary_keywords.end(); ++iter)
{
- token = token_it->second;
- if (token->getColor() != color)
- mFunctions->add(wstring_to_utf8str(token->getToken()));
+ mFunctions->add(*iter);
}
-
- childSetCommitCallback("lsl errors", &LLScriptEdCore::onErrorList, this);
- childSetAction("Save_btn", onBtnSave,this);
-
- initMenu();
-
- // Do the work that addTabPanel() normally does.
- //LLRect tab_panel_rect( 0, getRect().getHeight(), getRect().getWidth(), 0 );
- //tab_panel_rect.stretch( -LLPANEL_BORDER_WIDTH );
- //mCodePanel->setFollowsAll();
- //mCodePanel->translate( tab_panel_rect.mLeft - mCodePanel->getRect().mLeft, tab_panel_rect.mBottom - mCodePanel->getRect().mBottom);
- //mCodePanel->reshape( tab_panel_rect.getWidth(), tab_panel_rect.getHeight(), TRUE );
-
-}
-
-LLScriptEdCore::~LLScriptEdCore()
-{
- deleteBridges();
-
- // If the search window is up for this editor, close it.
- LLFloaterScriptSearch* script_search = LLFloaterScriptSearch::getInstance();
- if (script_search && script_search->getEditorCore() == this)
+ for (std::vector<std::string>::const_iterator iter= secondary_keywords.begin();
+ iter!= secondary_keywords.end(); ++iter)
{
- script_search->close();
- delete script_search;
+ mFunctions->add(*iter);
}
+
+ return TRUE;
}
void LLScriptEdCore::initMenu()
{
-
- LLMenuItemCallGL* menuItem = getChild<LLMenuItemCallGL>("Save");
- menuItem->setMenuCallback(onBtnSave, this);
- menuItem->setEnabledCallback(hasChanged);
+ // *TODO: Skinning - make these callbacks data driven
+ LLMenuItemCallGL* menuItem;
+
+ menuItem = getChild<LLMenuItemCallGL>("Save");
+ menuItem->setClickCallback(boost::bind(&LLScriptEdCore::doSave, this, FALSE));
+ menuItem->setEnableCallback(boost::bind(&LLScriptEdCore::hasChanged, this));
menuItem = getChild<LLMenuItemCallGL>("Revert All Changes");
- menuItem->setMenuCallback(onBtnUndoChanges, this);
- menuItem->setEnabledCallback(hasChanged);
+ menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnUndoChanges, this));
+ menuItem->setEnableCallback(boost::bind(&LLScriptEdCore::hasChanged, this));
menuItem = getChild<LLMenuItemCallGL>("Undo");
- menuItem->setMenuCallback(onUndoMenu, this);
- menuItem->setEnabledCallback(enableUndoMenu);
+ menuItem->setClickCallback(boost::bind(&LLTextEditor::undo, mEditor));
+ menuItem->setEnableCallback(boost::bind(&LLTextEditor::canUndo, mEditor));
menuItem = getChild<LLMenuItemCallGL>("Redo");
- menuItem->setMenuCallback(onRedoMenu, this);
- menuItem->setEnabledCallback(enableRedoMenu);
+ menuItem->setClickCallback(boost::bind(&LLTextEditor::redo, mEditor));
+ menuItem->setEnableCallback(boost::bind(&LLTextEditor::canRedo, mEditor));
menuItem = getChild<LLMenuItemCallGL>("Cut");
- menuItem->setMenuCallback(onCutMenu, this);
- menuItem->setEnabledCallback(enableCutMenu);
+ menuItem->setClickCallback(boost::bind(&LLTextEditor::cut, mEditor));
+ menuItem->setEnableCallback(boost::bind(&LLTextEditor::canCut, mEditor));
menuItem = getChild<LLMenuItemCallGL>("Copy");
- menuItem->setMenuCallback(onCopyMenu, this);
- menuItem->setEnabledCallback(enableCopyMenu);
+ menuItem->setClickCallback(boost::bind(&LLTextEditor::copy, mEditor));
+ menuItem->setEnableCallback(boost::bind(&LLTextEditor::canCopy, mEditor));
menuItem = getChild<LLMenuItemCallGL>("Paste");
- menuItem->setMenuCallback(onPasteMenu, this);
- menuItem->setEnabledCallback(enablePasteMenu);
+ menuItem->setClickCallback(boost::bind(&LLTextEditor::paste, mEditor));
+ menuItem->setEnableCallback(boost::bind(&LLTextEditor::canPaste, mEditor));
menuItem = getChild<LLMenuItemCallGL>("Select All");
- menuItem->setMenuCallback(onSelectAllMenu, this);
- menuItem->setEnabledCallback(enableSelectAllMenu);
+ menuItem->setClickCallback(boost::bind(&LLTextEditor::selectAll, mEditor));
+ menuItem->setEnableCallback(boost::bind(&LLTextEditor::canSelectAll, mEditor));
menuItem = getChild<LLMenuItemCallGL>("Search / Replace...");
- menuItem->setMenuCallback(onSearchMenu, this);
- menuItem->setEnabledCallback(NULL);
+ menuItem->setClickCallback(boost::bind(&LLFloaterScriptSearch::show, this));
menuItem = getChild<LLMenuItemCallGL>("Help...");
- menuItem->setMenuCallback(onBtnHelp, this);
- menuItem->setEnabledCallback(NULL);
+ menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnHelp, this));
- menuItem = getChild<LLMenuItemCallGL>("LSL Wiki Help...");
- menuItem->setMenuCallback(onBtnDynamicHelp, this);
- menuItem->setEnabledCallback(NULL);
+ menuItem = getChild<LLMenuItemCallGL>("Keyword Help...");
+ menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnDynamicHelp, this));
}
void LLScriptEdCore::setScriptText(const std::string& text, BOOL is_valid)
@@ -452,17 +446,16 @@ void LLScriptEdCore::setScriptText(const std::string& text, BOOL is_valid)
}
}
-BOOL LLScriptEdCore::hasChanged(void* userdata)
+bool LLScriptEdCore::hasChanged()
{
- LLScriptEdCore* self = (LLScriptEdCore*)userdata;
- if (!self || !self->mEditor) return FALSE;
+ if (!mEditor) return false;
- return ((!self->mEditor->isPristine() || self->mEnableSave) && self->mHasScriptData);
+ return ((!mEditor->isPristine() || mEnableSave) && mHasScriptData);
}
void LLScriptEdCore::draw()
{
- BOOL script_changed = hasChanged(this);
+ BOOL script_changed = hasChanged();
childSetEnabled("Save_btn", script_changed);
if( mEditor->hasFocus() )
@@ -470,8 +463,11 @@ void LLScriptEdCore::draw()
S32 line = 0;
S32 column = 0;
mEditor->getCurrentLineAndColumn( &line, &column, FALSE ); // don't include wordwrap
+ LLStringUtil::format_map_t args;
std::string cursor_pos;
- cursor_pos = llformat("Line %d, Column %d", line, column );
+ args["[LINE]"] = llformat ("%d", line);
+ args["[COLUMN]"] = llformat ("%d", column);
+ cursor_pos = LLTrans::getString("CursorPos", args);
childSetText("line_col", cursor_pos);
}
else
@@ -492,7 +488,7 @@ void LLScriptEdCore::updateDynamicHelp(BOOL immediate)
// update back and forward buttons
LLButton* fwd_button = help_floater->getChild<LLButton>("fwd_btn");
LLButton* back_button = help_floater->getChild<LLButton>("back_btn");
- LLWebBrowserCtrl* browser = help_floater->getChild<LLWebBrowserCtrl>("lsl_guide_html");
+ LLMediaCtrl* browser = help_floater->getChild<LLMediaCtrl>("lsl_guide_html");
back_button->setEnabled(browser->canNavigateBack());
fwd_button->setEnabled(browser->canNavigateForward());
@@ -501,12 +497,12 @@ void LLScriptEdCore::updateDynamicHelp(BOOL immediate)
return;
}
- const LLTextSegment* segment = NULL;
- std::vector<const LLTextSegment*> selected_segments;
+ LLTextSegmentPtr segment = NULL;
+ std::vector<LLTextSegmentPtr> selected_segments;
mEditor->getSelectedSegments(selected_segments);
// try segments in selection range first
- std::vector<const LLTextSegment*>::iterator segment_iter;
+ std::vector<LLTextSegmentPtr>::iterator segment_iter;
for (segment_iter = selected_segments.begin(); segment_iter != selected_segments.end(); ++segment_iter)
{
if((*segment_iter)->getToken() && (*segment_iter)->getToken()->getType() == LLKeywordToken::WORD)
@@ -519,7 +515,7 @@ void LLScriptEdCore::updateDynamicHelp(BOOL immediate)
// then try previous segment in case we just typed it
if (!segment)
{
- const LLTextSegment* test_segment = mEditor->getPreviousSegment();
+ const LLTextSegmentPtr test_segment = mEditor->getPreviousSegment();
if(test_segment->getToken() && test_segment->getToken()->getType() == LLKeywordToken::WORD)
{
segment = test_segment;
@@ -540,9 +536,12 @@ void LLScriptEdCore::updateDynamicHelp(BOOL immediate)
mLiveHelpTimer.stop();
}
}
- else if (immediate)
+ else
{
- setHelpPage(LLStringUtil::null);
+ if (immediate)
+ {
+ setHelpPage(LLStringUtil::null);
+ }
}
}
@@ -551,13 +550,14 @@ void LLScriptEdCore::setHelpPage(const std::string& help_string)
LLFloater* help_floater = mLiveHelpHandle.get();
if (!help_floater) return;
- LLWebBrowserCtrl* web_browser = help_floater->getChild<LLWebBrowserCtrl>("lsl_guide_html");
+ LLMediaCtrl* web_browser = help_floater->getChild<LLMediaCtrl>("lsl_guide_html");
if (!web_browser) return;
LLComboBox* history_combo = help_floater->getChild<LLComboBox>("history_combo");
if (!history_combo) return;
LLUIString url_string = gSavedSettings.getString("LSLHelpURL");
+
url_string.setArg("[LSL_STRING]", help_string);
addHelpItemToHistory(help_string);
@@ -580,9 +580,7 @@ void LLScriptEdCore::addHelpItemToHistory(const std::string& help_string)
// separate history items from full item list
if (mLiveHelpHistorySize == 0)
{
- LLSD row;
- row["columns"][0]["type"] = "separator";
- history_combo->addElement(row, ADD_TOP);
+ history_combo->addSeparator(ADD_TOP);
}
// delete all history items over history limit
while(mLiveHelpHistorySize > MAX_HISTORY_COUNT - 1)
@@ -612,33 +610,33 @@ void LLScriptEdCore::addHelpItemToHistory(const std::string& help_string)
BOOL LLScriptEdCore::canClose()
{
- if(mForceClose || !hasChanged(this))
+ if(mForceClose || !hasChanged())
{
return TRUE;
}
else
{
// Bring up view-modal dialog: Save changes? Yes, No, Cancel
- LLNotifications::instance().add("SaveChanges", LLSD(), LLSD(), boost::bind(&LLScriptEdCore::handleSaveChangesDialog, this, _1, _2));
+ LLNotificationsUtil::add("SaveChanges", LLSD(), LLSD(), boost::bind(&LLScriptEdCore::handleSaveChangesDialog, this, _1, _2));
return FALSE;
}
}
bool LLScriptEdCore::handleSaveChangesDialog(const LLSD& notification, const LLSD& response )
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
switch( option )
{
case 0: // "Yes"
// close after saving
- LLScriptEdCore::doSave( this, TRUE );
+ doSave( TRUE );
break;
case 1: // "No"
mForceClose = TRUE;
// This will close immediately because mForceClose is true, so we won't
// infinite loop with these dialogs. JC
- ((LLFloater*) getParent())->close();
+ ((LLFloater*) getParent())->closeFloater();
break;
case 2: // "Cancel"
@@ -650,74 +648,53 @@ bool LLScriptEdCore::handleSaveChangesDialog(const LLSD& notification, const LLS
return false;
}
-// static
-bool LLScriptEdCore::onHelpWebDialog(const LLSD& notification, const LLSD& response)
+void LLScriptEdCore::onBtnHelp()
{
- S32 option = LLNotification::getSelectedOption(notification, response);
-
- switch(option)
- {
- case 0:
- LLWeb::loadURL(notification["payload"]["help_url"]);
- break;
- default:
- break;
- }
- return false;
+ LLUI::sHelpImpl->showTopic(HELP_LSL_PORTAL_TOPIC);
}
-// static
-void LLScriptEdCore::onBtnHelp(void* userdata)
+void LLScriptEdCore::onBtnDynamicHelp()
{
- LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
- LLSD payload;
- payload["help_url"] = corep->mHelpURL;
- LLNotifications::instance().add("WebLaunchLSLGuide", LLSD(), payload, onHelpWebDialog);
-}
-
-// static
-void LLScriptEdCore::onBtnDynamicHelp(void* userdata)
-{
- LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
-
- LLFloater* live_help_floater = corep->mLiveHelpHandle.get();
- if (live_help_floater)
+ LLFloater* live_help_floater = mLiveHelpHandle.get();
+ if (!live_help_floater)
{
- live_help_floater->setFocus(TRUE);
- corep->updateDynamicHelp(TRUE);
+ live_help_floater = new LLFloater(LLSD());
+ LLUICtrlFactory::getInstance()->buildFloater(live_help_floater, "floater_lsl_guide.xml", NULL);
+ LLFloater* parent = dynamic_cast<LLFloater*>(getParent());
+ parent->addDependentFloater(live_help_floater, TRUE);
+ live_help_floater->childSetCommitCallback("lock_check", onCheckLock, this);
+ live_help_floater->childSetValue("lock_check", gSavedSettings.getBOOL("ScriptHelpFollowsCursor"));
+ live_help_floater->childSetCommitCallback("history_combo", onHelpComboCommit, this);
+ live_help_floater->childSetAction("back_btn", onClickBack, this);
+ live_help_floater->childSetAction("fwd_btn", onClickForward, this);
- return;
- }
-
- live_help_floater = new LLFloater(std::string("lsl_help"));
- LLUICtrlFactory::getInstance()->buildFloater(live_help_floater, "floater_lsl_guide.xml");
- ((LLFloater*)corep->getParent())->addDependentFloater(live_help_floater, TRUE);
- live_help_floater->childSetCommitCallback("lock_check", onCheckLock, userdata);
- live_help_floater->childSetValue("lock_check", gSavedSettings.getBOOL("ScriptHelpFollowsCursor"));
- live_help_floater->childSetCommitCallback("history_combo", onHelpComboCommit, userdata);
- live_help_floater->childSetAction("back_btn", onClickBack, userdata);
- live_help_floater->childSetAction("fwd_btn", onClickForward, userdata);
+ LLMediaCtrl* browser = live_help_floater->getChild<LLMediaCtrl>("lsl_guide_html");
+ browser->setAlwaysRefresh(TRUE);
- LLWebBrowserCtrl* browser = live_help_floater->getChild<LLWebBrowserCtrl>("lsl_guide_html");
- browser->setAlwaysRefresh(TRUE);
+ LLComboBox* help_combo = live_help_floater->getChild<LLComboBox>("history_combo");
+ LLKeywordToken *token;
+ LLKeywords::keyword_iterator_t token_it;
+ for (token_it = mEditor->keywordsBegin();
+ token_it != mEditor->keywordsEnd();
+ ++token_it)
+ {
+ token = token_it->second;
+ help_combo->add(wstring_to_utf8str(token->getToken()));
+ }
+ help_combo->sortByName();
- LLComboBox* help_combo = live_help_floater->getChild<LLComboBox>("history_combo");
- LLKeywordToken *token;
- LLKeywords::keyword_iterator_t token_it;
- for (token_it = corep->mEditor->keywordsBegin();
- token_it != corep->mEditor->keywordsEnd();
- ++token_it)
- {
- token = token_it->second;
- help_combo->add(wstring_to_utf8str(token->getToken()));
+ // re-initialize help variables
+ mLastHelpToken = NULL;
+ mLiveHelpHandle = live_help_floater->getHandle();
+ mLiveHelpHistorySize = 0;
}
- help_combo->sortByName();
- // re-initialize help variables
- corep->mLastHelpToken = NULL;
- corep->mLiveHelpHandle = live_help_floater->getHandle();
- corep->mLiveHelpHistorySize = 0;
- corep->updateDynamicHelp(TRUE);
+ BOOL visible = TRUE;
+ BOOL take_focus = TRUE;
+ live_help_floater->setVisible(visible);
+ live_help_floater->setFrontmost(take_focus);
+
+ updateDynamicHelp(TRUE);
}
//static
@@ -727,7 +704,7 @@ void LLScriptEdCore::onClickBack(void* userdata)
LLFloater* live_help_floater = corep->mLiveHelpHandle.get();
if (live_help_floater)
{
- LLWebBrowserCtrl* browserp = live_help_floater->getChild<LLWebBrowserCtrl>("lsl_guide_html");
+ LLMediaCtrl* browserp = live_help_floater->getChild<LLMediaCtrl>("lsl_guide_html");
if (browserp)
{
browserp->navigateBack();
@@ -742,7 +719,7 @@ void LLScriptEdCore::onClickForward(void* userdata)
LLFloater* live_help_floater = corep->mLiveHelpHandle.get();
if (live_help_floater)
{
- LLWebBrowserCtrl* browserp = live_help_floater->getChild<LLWebBrowserCtrl>("lsl_guide_html");
+ LLMediaCtrl* browserp = live_help_floater->getChild<LLMediaCtrl>("lsl_guide_html");
if (browserp)
{
browserp->navigateForward();
@@ -784,7 +761,7 @@ void LLScriptEdCore::onHelpComboCommit(LLUICtrl* ctrl, void* userdata)
corep->addHelpItemToHistory(help_string);
- LLWebBrowserCtrl* web_browser = live_help_floater->getChild<LLWebBrowserCtrl>("lsl_guide_html");
+ LLMediaCtrl* web_browser = live_help_floater->getChild<LLMediaCtrl>("lsl_guide_html");
LLUIString url_string = gSavedSettings.getString("LSLHelpURL");
url_string.setArg("[LSL_STRING]", help_string);
web_browser->navigateTo(url_string);
@@ -805,154 +782,25 @@ void LLScriptEdCore::onBtnInsertFunction(LLUICtrl *ui, void* userdata)
self->setHelpPage(self->mFunctions->getSimple());
}
-// static
-void LLScriptEdCore::doSave( void* userdata, BOOL close_after_save )
+void LLScriptEdCore::doSave( BOOL close_after_save )
{
LLViewerStats::getInstance()->incStat( LLViewerStats::ST_LSL_SAVE_COUNT );
- LLScriptEdCore* self = (LLScriptEdCore*) userdata;
-
- if( self->mSaveCallback )
+ if( mSaveCallback )
{
- self->mSaveCallback( self->mUserdata, close_after_save );
+ mSaveCallback( mUserdata, close_after_save );
}
}
-// static
-void LLScriptEdCore::onBtnSave(void* data)
-{
- // do the save, but don't close afterwards
- doSave(data, FALSE);
-}
-// static
-void LLScriptEdCore::onBtnUndoChanges( void* userdata )
+void LLScriptEdCore::onBtnUndoChanges()
{
- LLScriptEdCore* self = (LLScriptEdCore*) userdata;
- if( !self->mEditor->tryToRevertToPristineState() )
+ if( !mEditor->tryToRevertToPristineState() )
{
- LLNotifications::instance().add("ScriptCannotUndo", LLSD(), LLSD(), boost::bind(&LLScriptEdCore::handleReloadFromServerDialog, self, _1, _2));
+ LLNotificationsUtil::add("ScriptCannotUndo", LLSD(), LLSD(), boost::bind(&LLScriptEdCore::handleReloadFromServerDialog, this, _1, _2));
}
}
-void LLScriptEdCore::onSearchMenu(void* userdata)
-{
- LLScriptEdCore* sec = (LLScriptEdCore*)userdata;
- LLFloaterScriptSearch::show(sec);
-}
-
-// static
-void LLScriptEdCore::onUndoMenu(void* userdata)
-{
- LLScriptEdCore* self = (LLScriptEdCore*)userdata;
- if (!self || !self->mEditor) return;
- self->mEditor->undo();
-}
-
-// static
-void LLScriptEdCore::onRedoMenu(void* userdata)
-{
- LLScriptEdCore* self = (LLScriptEdCore*)userdata;
- if (!self || !self->mEditor) return;
- self->mEditor->redo();
-}
-
-// static
-void LLScriptEdCore::onCutMenu(void* userdata)
-{
- LLScriptEdCore* self = (LLScriptEdCore*)userdata;
- if (!self || !self->mEditor) return;
- self->mEditor->cut();
-}
-
-// static
-void LLScriptEdCore::onCopyMenu(void* userdata)
-{
- LLScriptEdCore* self = (LLScriptEdCore*)userdata;
- if (!self || !self->mEditor) return;
- self->mEditor->copy();
-}
-
-// static
-void LLScriptEdCore::onPasteMenu(void* userdata)
-{
- LLScriptEdCore* self = (LLScriptEdCore*)userdata;
- if (!self || !self->mEditor) return;
- self->mEditor->paste();
-}
-
-// static
-void LLScriptEdCore::onSelectAllMenu(void* userdata)
-{
- LLScriptEdCore* self = (LLScriptEdCore*)userdata;
- if (!self || !self->mEditor) return;
- self->mEditor->selectAll();
-}
-
-// static
-void LLScriptEdCore::onDeselectMenu(void* userdata)
-{
- LLScriptEdCore* self = (LLScriptEdCore*)userdata;
- if (!self || !self->mEditor) return;
- self->mEditor->deselect();
-}
-
-// static
-BOOL LLScriptEdCore::enableUndoMenu(void* userdata)
-{
- LLScriptEdCore* self = (LLScriptEdCore*)userdata;
- if (!self || !self->mEditor) return FALSE;
- return self->mEditor->canUndo();
-}
-
-// static
-BOOL LLScriptEdCore::enableRedoMenu(void* userdata)
-{
- LLScriptEdCore* self = (LLScriptEdCore*)userdata;
- if (!self || !self->mEditor) return FALSE;
- return self->mEditor->canRedo();
-}
-
-// static
-BOOL LLScriptEdCore::enableCutMenu(void* userdata)
-{
- LLScriptEdCore* self = (LLScriptEdCore*)userdata;
- if (!self || !self->mEditor) return FALSE;
- return self->mEditor->canCut();
-}
-
-// static
-BOOL LLScriptEdCore::enableCopyMenu(void* userdata)
-{
- LLScriptEdCore* self = (LLScriptEdCore*)userdata;
- if (!self || !self->mEditor) return FALSE;
- return self->mEditor->canCopy();
-}
-
-// static
-BOOL LLScriptEdCore::enablePasteMenu(void* userdata)
-{
- LLScriptEdCore* self = (LLScriptEdCore*)userdata;
- if (!self || !self->mEditor) return FALSE;
- return self->mEditor->canPaste();
-}
-
-// static
-BOOL LLScriptEdCore::enableSelectAllMenu(void* userdata)
-{
- LLScriptEdCore* self = (LLScriptEdCore*)userdata;
- if (!self || !self->mEditor) return FALSE;
- return self->mEditor->canSelectAll();
-}
-
-// static
-BOOL LLScriptEdCore::enableDeselectMenu(void* userdata)
-{
- LLScriptEdCore* self = (LLScriptEdCore*)userdata;
- if (!self || !self->mEditor) return FALSE;
- return self->mEditor->canDeselect();
-}
-
// static
void LLScriptEdCore::onErrorList(LLUICtrl*, void* user_data)
{
@@ -960,8 +808,7 @@ void LLScriptEdCore::onErrorList(LLUICtrl*, void* user_data)
LLScrollListItem* item = self->mErrorList->getFirstSelected();
if(item)
{
- // *FIX: This fucked up little hack is here because we don't
- // have a grep library. This is very brittle code.
+ // *FIX: replace with boost grep
S32 row = 0;
S32 column = 0;
const LLScrollListCell* cell = item->getColumn(0);
@@ -979,7 +826,7 @@ void LLScriptEdCore::onErrorList(LLUICtrl*, void* user_data)
bool LLScriptEdCore::handleReloadFromServerDialog(const LLSD& notification, const LLSD& response )
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
switch( option )
{
case 0: // "Yes"
@@ -1080,10 +927,8 @@ void* LLPreviewLSL::createScriptEdPanel(void* userdata)
LLPreviewLSL *self = (LLPreviewLSL*)userdata;
- self->mScriptEd = new LLScriptEdCore("script panel",
- LLRect(),
+ self->mScriptEd = new LLScriptEdCore(
HELLO_LSL,
- HELP_LSL_URL,
self->getHandle(),
LLPreviewLSL::onLoad,
LLPreviewLSL::onSave,
@@ -1095,49 +940,32 @@ void* LLPreviewLSL::createScriptEdPanel(void* userdata)
}
-LLPreviewLSL::LLPreviewLSL(const std::string& name, const LLRect& rect,
- const std::string& title, const LLUUID& item_id )
-: LLPreview( name, rect, title, item_id, LLUUID::null, TRUE,
- SCRIPT_MIN_WIDTH, SCRIPT_MIN_HEIGHT ),
- mPendingUploads(0)
+LLPreviewLSL::LLPreviewLSL(const LLSD& key )
+ : LLPreview( key ),
+ mPendingUploads(0)
{
+ mFactoryMap["script panel"] = LLCallbackMap(LLPreviewLSL::createScriptEdPanel, this);
+ //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this,"floater_script_preview.xml", FALSE);
+}
- LLRect curRect = rect;
-
-
- LLCallbackMap::map_t factory_map;
- factory_map["script panel"] = LLCallbackMap(LLPreviewLSL::createScriptEdPanel, this);
-
-
- LLUICtrlFactory::getInstance()->buildFloater(this,"floater_script_preview.xml", &factory_map);
-
+// virtual
+BOOL LLPreviewLSL::postBuild()
+{
const LLInventoryItem* item = getItem();
childSetCommitCallback("desc", LLPreview::onText, this);
childSetText("desc", item->getDescription());
- childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
+ childSetPrevalidate("desc", &LLLineEditor::prevalidateASCIIPrintableNoPipe);
- if (!getFloaterHost() && !getHost() && getAssetStatus() == PREVIEW_ASSET_UNLOADED)
- {
- loadAsset();
- }
-
- setTitle(title);
-
- if (!getHost())
- {
- reshape(curRect.getWidth(), curRect.getHeight(), TRUE);
- setRect(curRect);
- }
+ return LLPreview::postBuild();
}
// virtual
void LLPreviewLSL::callbackLSLCompileSucceeded()
{
llinfos << "LSL Bytecode saved" << llendl;
- // *TODO: Translate
- mScriptEd->mErrorList->addCommentText(std::string("Compile successful!"));
- mScriptEd->mErrorList->addCommentText(std::string("Save complete."));
+ mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessful"));
+ mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete"));
closeIfNeeded();
}
@@ -1169,7 +997,7 @@ void LLPreviewLSL::loadAsset()
const LLInventoryItem* item = gInventory.getItem(mItemUUID);
BOOL is_library = item
&& !gInventory.isObjectDescendentOf(mItemUUID,
- gAgent.getInventoryRootID());
+ gInventory.getRootFolderID());
if(!item)
{
// do the more generic search.
@@ -1228,16 +1056,10 @@ void LLPreviewLSL::closeIfNeeded()
mPendingUploads--;
if (mPendingUploads <= 0 && mCloseAfterSave)
{
- close();
+ closeFloater();
}
}
-//override the llpreview open which attempts to load asset, load after xml ui made
-void LLPreviewLSL::open() /*Flawfinder: ignore*/
-{
- LLFloater::open(); /*Flawfinder: ignore*/
-}
-
void LLPreviewLSL::onSearchReplace(void* userdata)
{
LLPreviewLSL* self = (LLPreviewLSL*)userdata;
@@ -1267,7 +1089,7 @@ void LLPreviewLSL::onSave(void* userdata, BOOL close_after_save)
void LLPreviewLSL::saveIfNeeded()
{
// llinfos << "LLPreviewLSL::saveIfNeeded()" << llendl;
- if(!LLScriptEdCore::hasChanged(mScriptEd))
+ if(!mScriptEd->hasChanged())
{
return;
}
@@ -1436,11 +1258,11 @@ void LLPreviewLSL::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32
else
{
llwarns << "Inventory item for script " << info->mItemUUID
- << " is no longer in agent inventory." << llendl
+ << " is no longer in agent inventory." << llendl;
}
// Find our window and close it if requested.
- LLPreviewLSL* self = (LLPreviewLSL*)LLPreview::find(info->mItemUUID);
+ LLPreviewLSL* self = LLFloaterReg::findTypedInstance<LLPreviewLSL>("preview_script", info->mItemUUID);
if (self)
{
getWindow()->decBusyCount();
@@ -1448,7 +1270,7 @@ void LLPreviewLSL::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32
if (self->mPendingUploads <= 0
&& self->mCloseAfterSave)
{
- self->close();
+ self->closeFloater();
}
}
}
@@ -1458,7 +1280,7 @@ void LLPreviewLSL::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32
llwarns << "Problem saving script: " << status << llendl;
LLSD args;
args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
- LLNotifications::instance().add("SaveScriptFailReason", args);
+ LLNotificationsUtil::add("SaveScriptFailReason", args);
}
delete info;
}
@@ -1470,7 +1292,7 @@ void LLPreviewLSL::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* user_d
LLPreviewLSL* self = NULL;
if(instance_uuid)
{
- self = LLPreviewLSL::getInstance(*instance_uuid);
+ self = LLFloaterReg::findTypedInstance<LLPreviewLSL>("preview_script", *instance_uuid);
}
if (0 == status)
{
@@ -1487,7 +1309,7 @@ void LLPreviewLSL::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* user_d
if (self->mPendingUploads <= 0
&& self->mCloseAfterSave)
{
- self->close();
+ self->closeFloater();
}
}
}
@@ -1496,7 +1318,7 @@ void LLPreviewLSL::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* user_d
llwarns << "Problem saving LSL Bytecode (Preview)" << llendl;
LLSD args;
args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
- LLNotifications::instance().add("SaveBytecodeFailReason", args);
+ LLNotificationsUtil::add("SaveBytecodeFailReason", args);
}
delete instance_uuid;
}
@@ -1508,7 +1330,7 @@ void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAsset
lldebugs << "LLPreviewLSL::onLoadComplete: got uuid " << asset_uuid
<< llendl;
LLUUID* item_uuid = (LLUUID*)user_data;
- LLPreviewLSL* preview = LLPreviewLSL::getInstance(*item_uuid);
+ LLPreviewLSL* preview = LLFloaterReg::findTypedInstance<LLPreviewLSL>("preview_script", *item_uuid);
if( preview )
{
if(0 == status)
@@ -1541,15 +1363,15 @@ void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAsset
if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
LL_ERR_FILE_EMPTY == status)
{
- LLNotifications::instance().add("ScriptMissing");
+ LLNotificationsUtil::add("ScriptMissing");
}
else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
{
- LLNotifications::instance().add("ScriptNoPermissions");
+ LLNotificationsUtil::add("ScriptNoPermissions");
}
else
{
- LLNotifications::instance().add("UnableToLoadScript");
+ LLNotificationsUtil::add("UnableToLoadScript");
}
preview->mAssetStatus = PREVIEW_ASSET_ERROR;
@@ -1559,37 +1381,11 @@ void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAsset
delete item_uuid;
}
-// static
-LLPreviewLSL* LLPreviewLSL::getInstance( const LLUUID& item_uuid )
-{
- LLPreview* instance = NULL;
- preview_map_t::iterator found_it = LLPreview::sInstances.find(item_uuid);
- if(found_it != LLPreview::sInstances.end())
- {
- instance = found_it->second;
- }
- return (LLPreviewLSL*)instance;
-}
-
-void LLPreviewLSL::reshape(S32 width, S32 height, BOOL called_from_parent)
-{
- LLPreview::reshape( width, height, called_from_parent );
-
- if( !isMinimized() )
- {
- // So that next time you open a script it will have the same height and width
- // (although not the same position).
- gSavedSettings.setRect("PreviewScriptRect", getRect());
- }
-}
/// ---------------------------------------------------------------------------
/// LLLiveLSLEditor
/// ---------------------------------------------------------------------------
-LLMap<LLUUID, LLLiveLSLEditor*> LLLiveLSLEditor::sInstances;
-
-
//static
void* LLLiveLSLEditor::createScriptEdPanel(void* userdata)
@@ -1597,10 +1393,8 @@ void* LLLiveLSLEditor::createScriptEdPanel(void* userdata)
LLLiveLSLEditor *self = (LLLiveLSLEditor*)userdata;
- self->mScriptEd = new LLScriptEdCore("script ed panel",
- LLRect(),
+ self->mScriptEd = new LLScriptEdCore(
HELLO_LSL,
- HELP_LSL_URL,
self->getHandle(),
&LLLiveLSLEditor::onLoad,
&LLLiveLSLEditor::onSave,
@@ -1612,72 +1406,40 @@ void* LLLiveLSLEditor::createScriptEdPanel(void* userdata)
}
-LLLiveLSLEditor::LLLiveLSLEditor(const std::string& name,
- const LLRect& rect,
- const std::string& title,
- const LLUUID& object_id,
- const LLUUID& item_id) :
- LLPreview(name, rect, title, item_id, object_id, TRUE, SCRIPT_MIN_WIDTH, SCRIPT_MIN_HEIGHT),
- mObjectID(object_id),
- mItemID(item_id),
+LLLiveLSLEditor::LLLiveLSLEditor(const LLSD& key) :
+ LLPreview(key),
mScriptEd(NULL),
mAskedForRunningInfo(FALSE),
mHaveRunningInfo(FALSE),
mCloseAfterSave(FALSE),
mPendingUploads(0),
- mIsModifiable(FALSE)
+ mIsModifiable(FALSE),
+ mIsNew(false)
{
+ mFactoryMap["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this);
+ //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this,"floater_live_lsleditor.xml", FALSE);
+}
-
- BOOL is_new = FALSE;
- if(mItemID.isNull())
- {
- mItemID.generate();
- is_new = TRUE;
- }
-
-
- LLLiveLSLEditor::sInstances.addData(mItemID ^ mObjectID, this);
-
- LLCallbackMap::map_t factory_map;
- factory_map["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this);
-
- LLUICtrlFactory::getInstance()->buildFloater(this,"floater_live_lsleditor.xml", &factory_map);
-
- mMonoCheckbox = getChild<LLCheckBoxCtrl>("mono");
- childSetCommitCallback("mono", &LLLiveLSLEditor::onMonoCheckboxClicked, this);
- childSetEnabled("mono", FALSE);
-
+BOOL LLLiveLSLEditor::postBuild()
+{
childSetCommitCallback("running", LLLiveLSLEditor::onRunningCheckboxClicked, this);
childSetEnabled("running", FALSE);
childSetAction("Reset",&LLLiveLSLEditor::onReset,this);
childSetEnabled("Reset", TRUE);
+ mMonoCheckbox = getChild<LLCheckBoxCtrl>("mono");
+ childSetCommitCallback("mono", &LLLiveLSLEditor::onMonoCheckboxClicked, this);
+ childSetEnabled("mono", FALSE);
mScriptEd->mEditor->makePristine();
- loadAsset(is_new);
mScriptEd->mEditor->setFocus(TRUE);
-
- if (!getHost())
- {
- LLRect curRect = getRect();
- translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop);
- }
-
- setTitle(title);
+ return LLPreview::postBuild();
}
LLLiveLSLEditor::~LLLiveLSLEditor()
{
- LLLiveLSLEditor::sInstances.removeData(mItemID ^ mObjectID);
-}
-
-// this is called via LLPreview::loadAsset() virtual method
-void LLLiveLSLEditor::loadAsset()
-{
- loadAsset(FALSE);
}
// virtual
@@ -1686,9 +1448,8 @@ void LLLiveLSLEditor::callbackLSLCompileSucceeded(const LLUUID& task_id,
bool is_script_running)
{
lldebugs << "LSL Bytecode saved" << llendl;
- // *TODO: Translate
- mScriptEd->mErrorList->addCommentText(std::string("Compile successful!"));
- mScriptEd->mErrorList->addCommentText(std::string("Save complete."));
+ mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessful"));
+ mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete"));
closeIfNeeded();
}
@@ -1704,6 +1465,7 @@ void LLLiveLSLEditor::callbackLSLCompileFailed(const LLSD& compile_errors)
std::string error_message = line->asString();
LLStringUtil::stripNonprintable(error_message);
row["columns"][0]["value"] = error_message;
+ // *TODO: change to "MONOSPACE" and change llfontgl.cpp?
row["columns"][0]["font"] = "OCRA";
mScriptEd->mErrorList->addElement(row);
}
@@ -1711,16 +1473,15 @@ void LLLiveLSLEditor::callbackLSLCompileFailed(const LLSD& compile_errors)
closeIfNeeded();
}
-void LLLiveLSLEditor::loadAsset(BOOL is_new)
+void LLLiveLSLEditor::loadAsset()
{
//llinfos << "LLLiveLSLEditor::loadAsset()" << llendl;
- if(!is_new)
+ if(!mIsNew)
{
- LLViewerObject* object = gObjectList.findObject(mObjectID);
+ LLViewerObject* object = gObjectList.findObject(mObjectUUID);
if(object)
{
- // HACK! we "know" that mItemID refers to a LLViewerInventoryItem...
- LLViewerInventoryItem* item = (LLViewerInventoryItem*)object->getInventoryObject(mItemID);
+ LLViewerInventoryItem* item = dynamic_cast<LLViewerInventoryItem*>(object->getInventoryObject(mItemUUID));
if(item
&& (gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE)
|| gAgent.isGodlike()))
@@ -1744,23 +1505,23 @@ void LLLiveLSLEditor::loadAsset(BOOL is_new)
else if(item && mItem.notNull())
{
// request the text from the object
- LLUUID* user_data = new LLUUID(mItemID ^ mObjectID);
+ LLUUID* user_data = new LLUUID(mItemUUID); // ^ mObjectUUID
gAssetStorage->getInvItemAsset(object->getRegion()->getHost(),
- gAgent.getID(),
- gAgent.getSessionID(),
- item->getPermissions().getOwner(),
- object->getID(),
- item->getUUID(),
- item->getAssetUUID(),
- item->getType(),
- &LLLiveLSLEditor::onLoadComplete,
- (void*)user_data,
- TRUE);
+ gAgent.getID(),
+ gAgent.getSessionID(),
+ item->getPermissions().getOwner(),
+ object->getID(),
+ item->getUUID(),
+ item->getAssetUUID(),
+ item->getType(),
+ &LLLiveLSLEditor::onLoadComplete,
+ (void*)user_data,
+ TRUE);
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_GetScriptRunning);
msg->nextBlockFast(_PREHASH_Script);
- msg->addUUIDFast(_PREHASH_ObjectID, mObjectID);
- msg->addUUIDFast(_PREHASH_ItemID, mItemID);
+ msg->addUUIDFast(_PREHASH_ObjectID, mObjectUUID);
+ msg->addUUIDFast(_PREHASH_ItemID, mItemUUID);
msg->sendReliable(object->getRegion()->getHost());
mAskedForRunningInfo = TRUE;
mAssetStatus = PREVIEW_ASSET_LOADING;
@@ -1789,26 +1550,12 @@ void LLLiveLSLEditor::loadAsset(BOOL is_new)
gMessageSystem->addUUID("AgentID", gAgent.getID());
U32 local_id = object->getLocalID();
gMessageSystem->addData("LocalID", &local_id);
- gMessageSystem->addUUID("ItemID", mItemID);
+ gMessageSystem->addUUID("ItemID", mItemUUID);
LLHost host(object->getRegion()->getIP(),
object->getRegion()->getPort());
gMessageSystem->sendReliable(host);
*/
}
-
- // Initialization of the asset failed. Probably the result
- // of a bug somewhere else. Set up this editor in a no-go mode.
- if(mItem.isNull())
- {
- // Set the inventory item to an incomplete item.
- // This may be better than having a accessible null pointer around,
- // though this newly allocated object will most likely be replaced.
- mItem = new LLViewerInventoryItem();
- mScriptEd->setScriptText(LLStringUtil::null, FALSE);
- mScriptEd->mEditor->makePristine();
- mScriptEd->mEditor->setEnabled(FALSE);
- mAssetStatus = PREVIEW_ASSET_LOADED;
- }
}
else
{
@@ -1817,17 +1564,17 @@ void LLLiveLSLEditor::loadAsset(BOOL is_new)
LLPermissions perm;
perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, gAgent.getGroupID());
perm.initMasks(PERM_ALL, PERM_ALL, PERM_NONE, PERM_NONE, PERM_MOVE | PERM_TRANSFER);
- mItem = new LLViewerInventoryItem(mItemID,
- mObjectID,
- perm,
- LLUUID::null,
- LLAssetType::AT_LSL_TEXT,
- LLInventoryType::IT_LSL,
- DEFAULT_SCRIPT_NAME,
- DEFAULT_SCRIPT_DESC,
- LLSaleInfo::DEFAULT,
- LLInventoryItem::II_FLAGS_NONE,
- time_corrected());
+ mItem = new LLViewerInventoryItem(mItemUUID,
+ mObjectUUID,
+ perm,
+ LLUUID::null,
+ LLAssetType::AT_LSL_TEXT,
+ LLInventoryType::IT_LSL,
+ DEFAULT_SCRIPT_NAME,
+ DEFAULT_SCRIPT_DESC,
+ LLSaleInfo::DEFAULT,
+ LLInventoryItem::II_FLAGS_NONE,
+ time_corrected());
mAssetStatus = PREVIEW_ASSET_LOADED;
}
}
@@ -1839,12 +1586,12 @@ void LLLiveLSLEditor::onLoadComplete(LLVFS *vfs, const LLUUID& asset_id,
{
lldebugs << "LLLiveLSLEditor::onLoadComplete: got uuid " << asset_id
<< llendl;
- LLLiveLSLEditor* instance = NULL;
LLUUID* xored_id = (LLUUID*)user_data;
-
- if( LLLiveLSLEditor::sInstances.checkData(*xored_id) )
+
+ LLLiveLSLEditor* instance = LLFloaterReg::findTypedInstance<LLLiveLSLEditor>("preview_scriptedit", *xored_id);
+
+ if(instance )
{
- instance = LLLiveLSLEditor::sInstances[*xored_id];
if( LL_ERR_NOERR == status )
{
instance->loadScriptText(vfs, asset_id, type);
@@ -1857,15 +1604,15 @@ void LLLiveLSLEditor::onLoadComplete(LLVFS *vfs, const LLUUID& asset_id,
if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
LL_ERR_FILE_EMPTY == status)
{
- LLNotifications::instance().add("ScriptMissing");
+ LLNotificationsUtil::add("ScriptMissing");
}
else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
{
- LLNotifications::instance().add("ScriptNoPermissions");
+ LLNotificationsUtil::add("ScriptNoPermissions");
}
else
{
- LLNotifications::instance().add("UnableToLoadScript");
+ LLNotificationsUtil::add("UnableToLoadScript");
}
instance->mAssetStatus = PREVIEW_ASSET_ERROR;
}
@@ -1930,7 +1677,7 @@ void LLLiveLSLEditor::loadScriptText(LLVFS *vfs, const LLUUID &uuid, LLAssetType
void LLLiveLSLEditor::onRunningCheckboxClicked( LLUICtrl*, void* userdata )
{
LLLiveLSLEditor* self = (LLLiveLSLEditor*) userdata;
- LLViewerObject* object = gObjectList.findObject( self->mObjectID );
+ LLViewerObject* object = gObjectList.findObject( self->mObjectUUID );
LLCheckBoxCtrl* runningCheckbox = self->getChild<LLCheckBoxCtrl>("running");
BOOL running = runningCheckbox->get();
//self->mRunningCheckbox->get();
@@ -1942,15 +1689,15 @@ void LLLiveLSLEditor::onRunningCheckboxClicked( LLUICtrl*, void* userdata )
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->nextBlockFast(_PREHASH_Script);
- msg->addUUIDFast(_PREHASH_ObjectID, self->mObjectID);
- msg->addUUIDFast(_PREHASH_ItemID, self->mItemID);
+ msg->addUUIDFast(_PREHASH_ObjectID, self->mObjectUUID);
+ msg->addUUIDFast(_PREHASH_ItemID, self->mItemUUID);
msg->addBOOLFast(_PREHASH_Running, running);
msg->sendReliable(object->getRegion()->getHost());
}
else
{
runningCheckbox->set(!running);
- LLNotifications::instance().add("CouldNotStartStopScript");
+ LLNotificationsUtil::add("CouldNotStartStopScript");
}
}
@@ -1958,7 +1705,7 @@ void LLLiveLSLEditor::onReset(void *userdata)
{
LLLiveLSLEditor* self = (LLLiveLSLEditor*) userdata;
- LLViewerObject* object = gObjectList.findObject( self->mObjectID );
+ LLViewerObject* object = gObjectList.findObject( self->mObjectUUID );
if(object)
{
LLMessageSystem* msg = gMessageSystem;
@@ -1967,19 +1714,19 @@ void LLLiveLSLEditor::onReset(void *userdata)
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->nextBlockFast(_PREHASH_Script);
- msg->addUUIDFast(_PREHASH_ObjectID, self->mObjectID);
- msg->addUUIDFast(_PREHASH_ItemID, self->mItemID);
+ msg->addUUIDFast(_PREHASH_ObjectID, self->mObjectUUID);
+ msg->addUUIDFast(_PREHASH_ItemID, self->mItemUUID);
msg->sendReliable(object->getRegion()->getHost());
}
else
{
- LLNotifications::instance().add("CouldNotStartStopScript");
+ LLNotificationsUtil::add("CouldNotStartStopScript");
}
}
void LLLiveLSLEditor::draw()
{
- LLViewerObject* object = gObjectList.findObject(mObjectID);
+ LLViewerObject* object = gObjectList.findObject(mObjectUUID);
LLCheckBoxCtrl* runningCheckbox = getChild<LLCheckBoxCtrl>( "running");
if(object && mAskedForRunningInfo && mHaveRunningInfo)
{
@@ -2024,14 +1771,13 @@ void LLLiveLSLEditor::draw()
{
// HACK: Display this information in the title bar.
// Really ought to put in main window.
- // *TODO: Translate
- setTitle(std::string("Script (object out of range)"));
+ setTitle(LLTrans::getString("ObjectOutOfRange"));
runningCheckbox->setEnabled(FALSE);
// object may have fallen out of range.
mHaveRunningInfo = FALSE;
}
- LLFloater::draw();
+ LLPreview::draw();
}
@@ -2046,7 +1792,7 @@ void LLLiveLSLEditor::onSearchReplace(void* userdata)
struct LLLiveLSLSaveData
{
LLLiveLSLSaveData(const LLUUID& id, const LLViewerInventoryItem* item, BOOL active);
- LLUUID mObjectID;
+ LLUUID mSaveObjectID;
LLPointer<LLViewerInventoryItem> mItem;
BOOL mActive;
};
@@ -2054,7 +1800,7 @@ struct LLLiveLSLSaveData
LLLiveLSLSaveData::LLLiveLSLSaveData(const LLUUID& id,
const LLViewerInventoryItem* item,
BOOL active) :
- mObjectID(id),
+ mSaveObjectID(id),
mActive(active)
{
llassert(item);
@@ -2064,10 +1810,10 @@ LLLiveLSLSaveData::LLLiveLSLSaveData(const LLUUID& id,
void LLLiveLSLEditor::saveIfNeeded()
{
llinfos << "LLLiveLSLEditor::saveIfNeeded()" << llendl;
- LLViewerObject* object = gObjectList.findObject(mObjectID);
+ LLViewerObject* object = gObjectList.findObject(mObjectUUID);
if(!object)
{
- LLNotifications::instance().add("SaveScriptFailObjectNotFound");
+ LLNotificationsUtil::add("SaveScriptFailObjectNotFound");
return;
}
@@ -2075,7 +1821,7 @@ void LLLiveLSLEditor::saveIfNeeded()
{
// $NOTE: While the error message may not be exactly correct,
// it's pretty close.
- LLNotifications::instance().add("SaveScriptFailObjectNotFound");
+ LLNotificationsUtil::add("SaveScriptFailObjectNotFound");
return;
}
@@ -2083,15 +1829,14 @@ void LLLiveLSLEditor::saveIfNeeded()
// name on save, because the viewer object version of the item,
// and the editor version would get out of synch. Here's a good
// place to synch them back up.
- // HACK! we "know" that mItemID refers to a LLInventoryItem...
- LLInventoryItem* inv_item = (LLInventoryItem*)object->getInventoryObject(mItemID);
+ LLInventoryItem* inv_item = dynamic_cast<LLInventoryItem*>(object->getInventoryObject(mItemUUID));
if(inv_item)
{
mItem->copyItem(inv_item);
}
// Don't need to save if we're pristine
- if(!LLScriptEdCore::hasChanged(mScriptEd))
+ if(!mScriptEd->hasChanged())
{
return;
}
@@ -2145,8 +1890,7 @@ void LLLiveLSLEditor::saveIfNeeded()
BOOL is_running = getChild<LLCheckBoxCtrl>( "running")->get();
if (!url.empty())
{
- uploadAssetViaCaps(url, filename, mObjectID,
- mItemID, is_running);
+ uploadAssetViaCaps(url, filename, mObjectUUID, mItemUUID, is_running);
}
else if (gAssetStorage)
{
@@ -2175,7 +1919,7 @@ void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename,
const LLTransactionID& tid,
BOOL is_running)
{
- LLLiveLSLSaveData* data = new LLLiveLSLSaveData(mObjectID,
+ LLLiveLSLSaveData* data = new LLLiveLSLSaveData(mObjectUUID,
mItem,
is_running);
gAssetStorage->storeAssetData(filename, tid,
@@ -2238,8 +1982,7 @@ void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename,
else
{
llinfos << "Compile worked!" << llendl;
- // *TODO: Translate
- mScriptEd->mErrorList->addCommentText(std::string("Compile successful, saving..."));
+ mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessfulSaving"));
if(gAssetStorage)
{
llinfos << "LLLiveLSLEditor::saveAsset "
@@ -2247,7 +1990,7 @@ void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename,
getWindow()->incBusyCount();
mPendingUploads++;
LLLiveLSLSaveData* data = NULL;
- data = new LLLiveLSLSaveData(mObjectID,
+ data = new LLLiveLSLSaveData(mObjectUUID,
mItem,
is_running);
gAssetStorage->storeAssetData(dst_filename,
@@ -2279,11 +2022,11 @@ void LLLiveLSLEditor::onSaveTextComplete(const LLUUID& asset_uuid, void* user_da
llwarns << "Unable to save text for a script." << llendl;
LLSD args;
args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
- LLNotifications::instance().add("CompileQueueSaveText", args);
+ LLNotificationsUtil::add("CompileQueueSaveText", args);
}
else
{
- LLLiveLSLEditor* self = sInstances.getIfThere(data->mItem->getUUID() ^ data->mObjectID);
+ LLLiveLSLEditor* self = LLFloaterReg::findTypedInstance<LLLiveLSLEditor>("preview_scriptedit", data->mItem->getUUID()); // ^ data->mSaveObjectID
if (self)
{
self->getWindow()->decBusyCount();
@@ -2291,7 +2034,7 @@ void LLLiveLSLEditor::onSaveTextComplete(const LLUUID& asset_uuid, void* user_da
if (self->mPendingUploads <= 0
&& self->mCloseAfterSave)
{
- self->close();
+ self->closeFloater();
}
}
}
@@ -2308,23 +2051,21 @@ void LLLiveLSLEditor::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* use
if(0 ==status)
{
llinfos << "LSL Bytecode saved" << llendl;
- LLUUID xor_id = data->mItem->getUUID() ^ data->mObjectID;
- LLLiveLSLEditor* self = sInstances.getIfThere(xor_id);
- if(self)
+ LLLiveLSLEditor* self = LLFloaterReg::findTypedInstance<LLLiveLSLEditor>("preview_scriptedit", data->mItem->getUUID()); // ^ data->mSaveObjectID
+ if (self)
{
// Tell the user that the compile worked.
- // *TODO: Translate
- self->mScriptEd->mErrorList->addCommentText(std::string("Save complete."));
+ self->mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete"));
// close the window if this completes both uploads
self->getWindow()->decBusyCount();
self->mPendingUploads--;
if (self->mPendingUploads <= 0
&& self->mCloseAfterSave)
{
- self->close();
+ self->closeFloater();
}
}
- LLViewerObject* object = gObjectList.findObject(data->mObjectID);
+ LLViewerObject* object = gObjectList.findObject(data->mSaveObjectID);
if(object)
{
object->saveScript(data->mItem, data->mActive, false);
@@ -2340,7 +2081,7 @@ void LLLiveLSLEditor::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* use
LLSD args;
args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
- LLNotifications::instance().add("CompileQueueSaveBytecode", args);
+ LLNotificationsUtil::add("CompileQueueSaveBytecode", args);
}
std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_uuid.asString());
@@ -2349,11 +2090,6 @@ void LLLiveLSLEditor::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* use
delete data;
}
-void LLLiveLSLEditor::open()
-{
- LLFloater::open(); /*Flawfinder: ignore*/
-}
-
BOOL LLLiveLSLEditor::canClose()
{
return (mScriptEd->canClose());
@@ -2365,7 +2101,7 @@ void LLLiveLSLEditor::closeIfNeeded()
mPendingUploads--;
if (mPendingUploads <= 0 && mCloseAfterSave)
{
- close();
+ closeFloater();
}
}
@@ -2385,52 +2121,16 @@ void LLLiveLSLEditor::onSave(void* userdata, BOOL close_after_save)
}
// static
-LLLiveLSLEditor* LLLiveLSLEditor::show(const LLUUID& script_id, const LLUUID& object_id)
-{
- LLLiveLSLEditor* instance = NULL;
- LLUUID xored_id = script_id ^ object_id;
- if(LLLiveLSLEditor::sInstances.checkData(xored_id))
- {
- // Move the existing view to the front
- instance = LLLiveLSLEditor::sInstances[xored_id];
- instance->open(); /*Flawfinder: ignore*/
- }
- return instance;
-}
-
-// static
-void LLLiveLSLEditor::hide(const LLUUID& script_id, const LLUUID& object_id)
-{
- LLUUID xored_id = script_id ^ object_id;
- if( LLLiveLSLEditor::sInstances.checkData( xored_id ) )
- {
- LLLiveLSLEditor* instance = LLLiveLSLEditor::sInstances[xored_id];
- if(instance->getParent())
- {
- instance->getParent()->removeChild(instance);
- }
- delete instance;
- }
-}
-// static
-LLLiveLSLEditor* LLLiveLSLEditor::find(const LLUUID& script_id, const LLUUID& object_id)
-{
- LLUUID xored_id = script_id ^ object_id;
- return sInstances.getIfThere(xored_id);
-}
-
-
-// static
void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**)
{
LLUUID item_id;
LLUUID object_id;
msg->getUUIDFast(_PREHASH_Script, _PREHASH_ObjectID, object_id);
msg->getUUIDFast(_PREHASH_Script, _PREHASH_ItemID, item_id);
- LLUUID xored_id = item_id ^ object_id;
- if(LLLiveLSLEditor::sInstances.checkData(xored_id))
+
+ LLLiveLSLEditor* instance = LLFloaterReg::findTypedInstance<LLLiveLSLEditor>("preview_scriptedit", item_id); // ^ object_id
+ if(instance)
{
- LLLiveLSLEditor* instance = LLLiveLSLEditor::sInstances[xored_id];
instance->mHaveRunningInfo = TRUE;
BOOL running;
msg->getBOOLFast(_PREHASH_Script, _PREHASH_Running, running);
@@ -2444,22 +2144,11 @@ void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**)
}
}
-void LLLiveLSLEditor::reshape(S32 width, S32 height, BOOL called_from_parent)
-{
- LLFloater::reshape( width, height, called_from_parent );
-
- if( !isMinimized() )
- {
- // So that next time you open a script it will have the same height and width
- // (although not the same position).
- gSavedSettings.setRect("PreviewScriptRect", getRect());
- }
-}
void LLLiveLSLEditor::onMonoCheckboxClicked(LLUICtrl*, void* userdata)
{
LLLiveLSLEditor* self = static_cast<LLLiveLSLEditor*>(userdata);
- self->mMonoCheckbox->setEnabled(have_script_upload_cap(self->mObjectID));
+ self->mMonoCheckbox->setEnabled(have_script_upload_cap(self->mObjectUUID));
self->mScriptEd->enableSave(self->getIsModifiable());
}
diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h
index eb8b414709..9d194c5557 100644
--- a/indra/newview/llpreviewscript.h
+++ b/indra/newview/llpreviewscript.h
@@ -41,7 +41,6 @@
#include "lliconctrl.h"
#include "llframetimer.h"
-
class LLMessageSystem;
class LLTextEditor;
class LLButton;
@@ -52,6 +51,8 @@ struct LLEntryAndEdCore;
class LLMenuBarGL;
class LLFloaterScriptSearch;
class LLKeywordToken;
+class LLVFS;
+class LLViewerInventoryItem;
// Inner, implementation class. LLPreviewScript and LLLiveLSLEditor each own one of these.
class LLScriptEdCore : public LLPanel
@@ -63,10 +64,7 @@ class LLScriptEdCore : public LLPanel
public:
LLScriptEdCore(
- const std::string& name,
- const LLRect& rect,
const std::string& sample,
- const std::string& help_url,
const LLHandle<LLFloater>& floater_handle,
void (*load_callback)(void* userdata),
void (*save_callback)(void* userdata, BOOL close_after_save),
@@ -78,45 +76,29 @@ public:
void initMenu();
virtual void draw();
-
+ /*virtual*/ BOOL postBuild();
BOOL canClose();
void setScriptText(const std::string& text, BOOL is_valid);
+
+ void doSave( BOOL close_after_save );
bool handleSaveChangesDialog(const LLSD& notification, const LLSD& response);
bool handleReloadFromServerDialog(const LLSD& notification, const LLSD& response);
- static bool onHelpWebDialog(const LLSD& notification, const LLSD& response);
- static void onBtnHelp(void* userdata);
- static void onBtnDynamicHelp(void* userdata);
static void onCheckLock(LLUICtrl*, void*);
static void onHelpComboCommit(LLUICtrl* ctrl, void* userdata);
static void onClickBack(void* userdata);
static void onClickForward(void* userdata);
static void onBtnInsertSample(void*);
static void onBtnInsertFunction(LLUICtrl*, void*);
- static void doSave( void* userdata, BOOL close_after_save );
- static void onBtnSave(void*);
- static void onBtnUndoChanges(void*);
- static void onSearchMenu(void* userdata);
-
- static void onUndoMenu(void* userdata);
- static void onRedoMenu(void* userdata);
- static void onCutMenu(void* userdata);
- static void onCopyMenu(void* userdata);
- static void onPasteMenu(void* userdata);
- static void onSelectAllMenu(void* userdata);
- static void onDeselectMenu(void* userdata);
-
- static BOOL enableUndoMenu(void* userdata);
- static BOOL enableRedoMenu(void* userdata);
- static BOOL enableCutMenu(void* userdata);
- static BOOL enableCopyMenu(void* userdata);
- static BOOL enablePasteMenu(void* userdata);
- static BOOL enableSelectAllMenu(void* userdata);
- static BOOL enableDeselectMenu(void* userdata);
-
- static BOOL hasChanged(void* userdata);
+
+private:
+ void onBtnHelp();
+ void onBtnDynamicHelp();
+ void onBtnUndoChanges();
+
+ bool hasChanged();
void selectFirstError();
@@ -131,11 +113,8 @@ protected:
void addHelpItemToHistory(const std::string& help_string);
static void onErrorList(LLUICtrl*, void* user_data);
- virtual const char *getTitleName() const { return "Script"; }
-
private:
std::string mSampleText;
- std::string mHelpURL;
LLTextEditor* mEditor;
void (*mLoadCallback)(void* userdata);
void (*mSaveCallback)(void* userdata, BOOL close_after_save);
@@ -143,7 +122,6 @@ private:
void* mUserdata;
LLComboBox *mFunctions;
BOOL mForceClose;
- //LLPanel* mGuiPanel;
LLPanel* mCodePanel;
LLScrollListCtrl* mErrorList;
LLDynamicArray<LLEntryAndEdCore*> mBridges;
@@ -160,17 +138,15 @@ private:
class LLPreviewLSL : public LLPreview
{
public:
- LLPreviewLSL(const std::string& name, const LLRect& rect, const std::string& title,
- const LLUUID& item_uuid );
+ LLPreviewLSL(const LLSD& key );
virtual void callbackLSLCompileSucceeded();
virtual void callbackLSLCompileFailed(const LLSD& compile_errors);
- /*virtual*/ void open(); /*Flawfinder: ignore*/
+ /*virtual*/ BOOL postBuild();
protected:
virtual BOOL canClose();
void closeIfNeeded();
- virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
virtual void loadAsset();
void saveIfNeeded();
@@ -190,15 +166,13 @@ protected:
void* user_data, S32 status, LLExtStat ext_status);
static void onSaveComplete(const LLUUID& uuid, void* user_data, S32 status, LLExtStat ext_status);
static void onSaveBytecodeComplete(const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status);
-public:
- static LLPreviewLSL* getInstance(const LLUUID& uuid);
+
protected:
static void* createScriptEdPanel(void* userdata);
protected:
- virtual const char *getTitleName() const { return "Script"; }
LLScriptEdCore* mScriptEd;
// Can safely close only after both text and bytecode are uploaded
S32 mPendingUploads;
@@ -210,16 +184,10 @@ protected:
class LLLiveLSLEditor : public LLPreview
{
public:
- LLLiveLSLEditor(const std::string& name, const LLRect& rect,
- const std::string& title,
- const LLUUID& object_id, const LLUUID& item_id);
+ LLLiveLSLEditor(const LLSD& key);
~LLLiveLSLEditor();
- static LLLiveLSLEditor* show(const LLUUID& item_id, const LLUUID& object_id);
- static void hide(const LLUUID& item_id, const LLUUID& object_id);
- static LLLiveLSLEditor* find(const LLUUID& item_id, const LLUUID& object_id);
-
static void processScriptRunningReply(LLMessageSystem* msg, void**);
virtual void callbackLSLCompileSucceeded(const LLUUID& task_id,
@@ -227,14 +195,14 @@ public:
bool is_script_running);
virtual void callbackLSLCompileFailed(const LLSD& compile_errors);
- // Overide LLPreview::open() to avoid calling loadAsset twice.
- /*virtual*/ void open(); /*Flawfinder: ignore*/
-
-protected:
+ /*virtual*/ BOOL postBuild();
+
+ void setIsNew() { mIsNew = TRUE; }
+
+private:
virtual BOOL canClose();
void closeIfNeeded();
virtual void draw();
- virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
virtual void loadAsset();
void loadAsset(BOOL is_new);
@@ -248,6 +216,8 @@ protected:
LLViewerObject* object,
const LLTransactionID& tid,
BOOL is_running);
+ BOOL monoChecked() const;
+
static void onSearchReplace(void* userdata);
static void onLoad(void* userdata);
@@ -268,30 +238,23 @@ protected:
static void* createScriptEdPanel(void* userdata);
+ static void onMonoCheckboxClicked(LLUICtrl*, void* userdata);
-protected:
- LLUUID mObjectID;
- LLUUID mItemID; // The inventory item this script is associated with
- BOOL mIsNew;
- LLScriptEdCore* mScriptEd;
+private:
+ bool mIsNew;
+ LLScriptEdCore* mScriptEd;
//LLUUID mTransmitID;
- LLCheckBoxCtrl *mRunningCheckbox;
- BOOL mAskedForRunningInfo;
- BOOL mHaveRunningInfo;
- LLButton *mResetButton;
+ LLCheckBoxCtrl* mRunningCheckbox;
+ BOOL mAskedForRunningInfo;
+ BOOL mHaveRunningInfo;
+ LLButton* mResetButton;
LLPointer<LLViewerInventoryItem> mItem;
- BOOL mCloseAfterSave;
+ BOOL mCloseAfterSave;
// need to save both text and script, so need to decide when done
- S32 mPendingUploads;
+ S32 mPendingUploads;
- static LLMap<LLUUID, LLLiveLSLEditor*> sInstances;
BOOL getIsModifiable() const { return mIsModifiable; } // Evaluated on load assert
-private:
-
- static void onMonoCheckboxClicked(LLUICtrl*, void* userdata);
- BOOL monoChecked() const;
-
LLCheckBoxCtrl* mMonoCheckbox;
BOOL mIsModifiable;
};
diff --git a/indra/newview/llpreviewsound.cpp b/indra/newview/llpreviewsound.cpp
index 26d8da5a6b..d7fd252fb6 100644
--- a/indra/newview/llpreviewsound.cpp
+++ b/indra/newview/llpreviewsound.cpp
@@ -32,11 +32,10 @@
#include "llviewerprecompiledheaders.h"
-#include "audioengine.h"
+#include "llaudioengine.h"
#include "llagent.h" // gAgent
#include "llbutton.h"
#include "llinventory.h"
-#include "llinventoryview.h"
#include "lllineeditor.h"
#include "llpreviewsound.h"
#include "llresmgr.h"
@@ -49,12 +48,23 @@ extern LLAgent gAgent;
const F32 SOUND_GAIN = 1.0f;
-LLPreviewSound::LLPreviewSound(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& item_uuid, const LLUUID& object_uuid) :
- LLPreview( name, rect, title, item_uuid, object_uuid)
+LLPreviewSound::LLPreviewSound(const LLSD& key)
+ : LLPreview( key )
{
-
- LLUICtrlFactory::getInstance()->buildFloater(this,"floater_preview_sound.xml");
+ //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this,"floater_preview_sound.xml", FALSE);
+}
+// virtual
+BOOL LLPreviewSound::postBuild()
+{
+ const LLInventoryItem* item = getItem();
+ if (item)
+ {
+ childSetText("desc", item->getDescription());
+ if (gAudiop)
+ gAudiop->preloadSound(item->getAssetUUID()); // preload the sound
+ }
+
childSetAction("Sound play btn",&LLPreviewSound::playSound,this);
childSetAction("Sound audition btn",&LLPreviewSound::auditionSound,this);
@@ -64,26 +74,10 @@ LLPreviewSound::LLPreviewSound(const std::string& name, const LLRect& rect, cons
button = getChild<LLButton>("Sound audition btn");
button->setSoundFlags(LLView::SILENT);
- const LLInventoryItem* item = getItem();
-
childSetCommitCallback("desc", LLPreview::onText, this);
- childSetText("desc", item->getDescription());
- childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
-
- // preload the sound
- if(item && gAudiop)
- {
- gAudiop->preloadSound(item->getAssetUUID());
- }
-
- setTitle(title);
-
- if (!getHost())
- {
- LLRect curRect = getRect();
- translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop);
- }
+ childSetPrevalidate("desc", &LLLineEditor::prevalidateASCIIPrintableNoPipe);
+ return LLPreview::postBuild();
}
// static
diff --git a/indra/newview/llpreviewsound.h b/indra/newview/llpreviewsound.h
index 061fbdf685..c4bf8c9a30 100644
--- a/indra/newview/llpreviewsound.h
+++ b/indra/newview/llpreviewsound.h
@@ -38,16 +38,13 @@
class LLPreviewSound : public LLPreview
{
public:
- LLPreviewSound(const std::string& name, const LLRect& rect, const std::string& title,
- const LLUUID& item_uuid,
- const LLUUID& object_uuid = LLUUID::null);
+ LLPreviewSound(const LLSD& key);
static void playSound( void* userdata );
static void auditionSound( void* userdata );
protected:
- virtual const char *getTitleName() const { return "Sound"; }
-
+ /* virtual */ BOOL postBuild();
};
#endif // LL_LLPREVIEWSOUND_H
diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp
index 13e7cca464..028807a6bd 100644
--- a/indra/newview/llpreviewtexture.cpp
+++ b/indra/newview/llpreviewtexture.cpp
@@ -32,114 +32,69 @@
#include "llviewerprecompiledheaders.h"
+#include "llwindow.h"
+
#include "llpreviewtexture.h"
#include "llagent.h"
#include "llbutton.h"
+#include "llcombobox.h"
#include "llfilepicker.h"
+#include "llfloaterreg.h"
#include "llimagetga.h"
-#include "llinventoryview.h"
#include "llinventory.h"
+#include "llnotificationsutil.h"
#include "llresmgr.h"
+#include "lltrans.h"
#include "lltextbox.h"
#include "lltextureview.h"
#include "llui.h"
-#include "llviewerimage.h"
-#include "llviewerimagelist.h"
+#include "llviewerinventory.h"
+#include "llviewertexture.h"
+#include "llviewertexturelist.h"
#include "lluictrlfactory.h"
#include "llviewerwindow.h"
#include "lllineeditor.h"
-const S32 PREVIEW_TEXTURE_MIN_WIDTH = 300;
-const S32 PREVIEW_TEXTURE_MIN_HEIGHT = 120;
-
const S32 CLIENT_RECT_VPAD = 4;
const F32 SECONDS_TO_SHOW_FILE_SAVED_MSG = 8.f;
-LLPreviewTexture::LLPreviewTexture(const std::string& name,
- const LLRect& rect,
- const std::string& title,
- const LLUUID& item_uuid,
- const LLUUID& object_id,
- BOOL show_keep_discard)
-: LLPreview(name, rect, title, item_uuid, object_id, TRUE, PREVIEW_TEXTURE_MIN_WIDTH, PREVIEW_TEXTURE_MIN_HEIGHT ),
- mLoadingFullImage( FALSE ),
- mShowKeepDiscard(show_keep_discard),
- mCopyToInv(FALSE),
- mIsCopyable(FALSE),
- mLastHeight(0),
- mLastWidth(0)
+const F32 PREVIEW_TEXTURE_MAX_ASPECT = 200.f;
+const F32 PREVIEW_TEXTURE_MIN_ASPECT = 0.005f;
+
+
+LLPreviewTexture::LLPreviewTexture(const LLSD& key)
+ : LLPreview(key),
+ mLoadingFullImage( FALSE ),
+ mShowKeepDiscard(FALSE),
+ mCopyToInv(FALSE),
+ mIsCopyable(FALSE),
+ mUpdateDimensions(TRUE),
+ mLastHeight(0),
+ mLastWidth(0),
+ mAspectRatio(0.f),
+ mPreviewToSave(FALSE)
{
- const LLInventoryItem *item = getItem();
+ const LLViewerInventoryItem *item = static_cast<const LLViewerInventoryItem*>(getItem());
if(item)
{
+ mShowKeepDiscard = item->getPermissions().getCreator() != gAgent.getID();
mImageID = item->getAssetUUID();
- const LLPermissions& perm = item->getPermissions();
- U32 mask = PERM_NONE;
- if(perm.getOwner() == gAgent.getID())
- {
- mask = perm.getMaskBase();
- }
- else if(gAgent.isInGroup(perm.getGroup()))
- {
- mask = perm.getMaskGroup();
- }
- else
- {
- mask = perm.getMaskEveryone();
- }
- if((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
- {
- mIsCopyable = TRUE;
- }
+ mIsCopyable = item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED);
}
-
- init();
-
- setTitle(title);
-
- if (!getHost())
+ else // not an item, assume it's an asset id
{
- LLRect curRect = getRect();
- translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop);
+ mImageID = mItemUUID;
+ mCopyToInv = TRUE;
+ mIsCopyable = TRUE;
}
-}
-
-
-// Note: uses asset_id as a dummy item id.
-LLPreviewTexture::LLPreviewTexture(
- const std::string& name,
- const LLRect& rect,
- const std::string& title,
- const LLUUID& asset_id,
- BOOL copy_to_inv)
- :
- LLPreview(
- name,
- rect,
- title,
- asset_id,
- LLUUID::null,
- TRUE,
- PREVIEW_TEXTURE_MIN_WIDTH,
- PREVIEW_TEXTURE_MIN_HEIGHT ),
- mImageID(asset_id),
- mLoadingFullImage( FALSE ),
- mShowKeepDiscard(FALSE),
- mCopyToInv(copy_to_inv),
- mIsCopyable(TRUE),
- mLastHeight(0),
- mLastWidth(0)
-{
- init();
-
- setTitle(title);
-
- LLRect curRect = getRect();
- translate(curRect.mLeft - rect.mLeft, curRect.mTop - rect.mTop);
-
+ if (key.has("save_as"))
+ {
+ mPreviewToSave = TRUE;
+ }
+ //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_preview_texture.xml", FALSE);
}
@@ -153,32 +108,29 @@ LLPreviewTexture::~LLPreviewTexture()
mImage = NULL;
}
-
-void LLPreviewTexture::init()
+// virtual
+BOOL LLPreviewTexture::postBuild()
{
-
-
if (mCopyToInv)
{
- LLUICtrlFactory::getInstance()->buildFloater(this,"floater_preview_embedded_texture.xml");
-
- childSetAction("Copy To Inventory",LLPreview::onBtnCopyToInv,this);
+ getChild<LLButton>("Keep")->setLabel(getString("Copy"));
+ childSetAction("Keep",LLPreview::onBtnCopyToInv,this);
+ childSetVisible("Discard", false);
}
-
else if (mShowKeepDiscard)
{
- LLUICtrlFactory::getInstance()->buildFloater(this,"floater_preview_texture_keep_discard.xml");
-
childSetAction("Keep",onKeepBtn,this);
childSetAction("Discard",onDiscardBtn,this);
}
-
- else
+ else
{
- LLUICtrlFactory::getInstance()->buildFloater(this,"floater_preview_texture.xml");
+ childSetVisible("Keep", false);
+ childSetVisible("Discard", false);
}
-
-
+
+ childSetAction("save_tex_btn", LLPreviewTexture::onSaveAsBtn, this);
+ childSetVisible("save_tex_btn", canSaveAs());
+
if (!mCopyToInv)
{
const LLInventoryItem* item = getItem();
@@ -187,15 +139,31 @@ void LLPreviewTexture::init()
{
childSetCommitCallback("desc", LLPreview::onText, this);
childSetText("desc", item->getDescription());
- childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
+ childSetPrevalidate("desc", &LLLineEditor::prevalidateASCIIPrintableNoPipe);
}
}
+
+ childSetCommitCallback("combo_aspect_ratio", onAspectRatioCommit, this);
+ LLComboBox* combo = getChild<LLComboBox>("combo_aspect_ratio");
+ combo->setCurrentByIndex(0);
+
+ return LLPreview::postBuild();
}
-void LLPreviewTexture::draw()
+// static
+void LLPreviewTexture::onSaveAsBtn(void* data)
{
- updateDimensions();
+ LLPreviewTexture* self = (LLPreviewTexture*)data;
+ self->saveAs();
+}
+void LLPreviewTexture::draw()
+{
+ if (mUpdateDimensions)
+ {
+ updateDimensions();
+ }
+
LLPreview::draw();
if (!isMinimized())
@@ -213,6 +181,12 @@ void LLPreviewTexture::draw()
if ( mImage.notNull() )
{
+ // Automatically bring up SaveAs dialog if we opened this to save the texture.
+ if (mPreviewToSave)
+ {
+ mPreviewToSave = FALSE;
+ saveAs();
+ }
// Draw the texture
glColor3f( 1.f, 1.f, 1.f );
gl_draw_scaled_image(interior.mLeft,
@@ -241,14 +215,14 @@ void LLPreviewTexture::draw()
if( mLoadingFullImage )
{
- // *TODO: Translate
- LLFontGL::getFontSansSerif()->renderUTF8(std::string("Receiving:"), 0,
+ LLFontGL::getFontSansSerif()->renderUTF8(LLTrans::getString("Receiving"), 0,
interior.mLeft + 4,
interior.mBottom + 4,
LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM,
+ LLFontGL::NORMAL,
LLFontGL::DROP_SHADOW);
- F32 data_progress = mImage->mDownloadProgress;
+ F32 data_progress = mImage->getDownloadProgress() ;
// Draw the progress bar.
const S32 BAR_HEIGHT = 12;
@@ -278,11 +252,11 @@ void LLPreviewTexture::draw()
else
if( !mSavedFileTimer.hasExpired() )
{
- // *TODO: Translate
- LLFontGL::getFontSansSerif()->renderUTF8(std::string("File Saved"), 0,
+ LLFontGL::getFontSansSerif()->renderUTF8(LLTrans::getString("FileSaved"), 0,
interior.mLeft + 4,
interior.mBottom + 4,
LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM,
+ LLFontGL::NORMAL,
LLFontGL::DROP_SHADOW);
}
}
@@ -300,10 +274,11 @@ BOOL LLPreviewTexture::canSaveAs() const
// virtual
void LLPreviewTexture::saveAs()
{
- if( mLoadingFullImage ) return;
+ if( mLoadingFullImage )
+ return;
LLFilePicker& file_picker = LLFilePicker::instance();
- const LLViewerInventoryItem* item = getItem() ;
+ const LLInventoryItem* item = getItem() ;
if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_TGA, item ? LLDir::getScrubbedFileName(item->getName()) : LLStringUtil::null) )
{
// User canceled or we failed to acquire save file.
@@ -317,10 +292,32 @@ void LLPreviewTexture::saveAs()
0, TRUE, FALSE, new LLUUID( mItemUUID ) );
}
+// virtual
+void LLPreviewTexture::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+// mLastHeight = 0;
+// mLastWidth = 0;
+ mUpdateDimensions = TRUE;
+ LLPreview::reshape(width, height, called_from_parent);
+}
+
+// virtual
+void LLPreviewTexture::onFocusReceived()
+{
+ mLastHeight = 0;
+ mLastWidth = 0;
+ mUpdateDimensions = TRUE;
+ LLPreview::onFocusReceived();
+}
+
+void LLPreviewTexture::openToSave()
+{
+ mPreviewToSave = TRUE;
+}
// static
void LLPreviewTexture::onFileLoadedForSave(BOOL success,
- LLViewerImage *src_vi,
+ LLViewerFetchedTexture *src_vi,
LLImageRaw* src,
LLImageRaw* aux_src,
S32 discard_level,
@@ -328,12 +325,8 @@ void LLPreviewTexture::onFileLoadedForSave(BOOL success,
void* userdata)
{
LLUUID* item_uuid = (LLUUID*) userdata;
- LLPreviewTexture* self = NULL;
- preview_map_t::iterator found_it = LLPreview::sInstances.find(*item_uuid);
- if(found_it != LLPreview::sInstances.end())
- {
- self = (LLPreviewTexture*) found_it->second;
- }
+
+ LLPreviewTexture* self = LLFloaterReg::findTypedInstance<LLPreviewTexture>("preview_texture", *item_uuid);
if( final || !success )
{
@@ -353,13 +346,13 @@ void LLPreviewTexture::onFileLoadedForSave(BOOL success,
{
LLSD args;
args["FILE"] = self->mSaveFileName;
- LLNotifications::instance().add("CannotEncodeFile", args);
+ LLNotificationsUtil::add("CannotEncodeFile", args);
}
else if( !image_tga->save( self->mSaveFileName ) )
{
LLSD args;
args["FILE"] = self->mSaveFileName;
- LLNotifications::instance().add("CannotWriteFile", args);
+ LLNotificationsUtil::add("CannotWriteFile", args);
}
else
{
@@ -372,8 +365,9 @@ void LLPreviewTexture::onFileLoadedForSave(BOOL success,
if( self && !success )
{
- LLNotifications::instance().add("CannotDownloadFile");
+ LLNotificationsUtil::add("CannotDownloadFile");
}
+
}
@@ -381,114 +375,119 @@ void LLPreviewTexture::onFileLoadedForSave(BOOL success,
// When we receive it, reshape the window accordingly.
void LLPreviewTexture::updateDimensions()
{
- if (!mImage) return;
-
- S32 image_height = llmax(1, mImage->getHeight(0));
- S32 image_width = llmax(1, mImage->getWidth(0));
- // Attempt to make the image 1:1 on screen.
- // If that fails, cut width by half.
- S32 client_width = image_width;
- S32 client_height = image_height;
- S32 horiz_pad = 2 * (LLPANEL_BORDER_WIDTH + PREVIEW_PAD) + PREVIEW_RESIZE_HANDLE_SIZE;
- S32 vert_pad = PREVIEW_HEADER_SIZE + 2 * CLIENT_RECT_VPAD + LLPANEL_BORDER_WIDTH;
- S32 max_client_width = gViewerWindow->getWindowWidth() - horiz_pad;
- S32 max_client_height = gViewerWindow->getWindowHeight() - vert_pad;
-
- while ((client_width > max_client_width) ||
- (client_height > max_client_height ) )
- {
- client_width /= 2;
- client_height /= 2;
- }
-
- S32 view_width = client_width + horiz_pad;
- S32 view_height = client_height + vert_pad;
+ if (!mImage)
+ return;
- // set text on dimensions display (should be moved out of here and into a callback of some sort)
- childSetTextArg("dimensions", "[WIDTH]", llformat("%d", mImage->mFullWidth));
- childSetTextArg("dimensions", "[HEIGHT]", llformat("%d", mImage->mFullHeight));
+ mUpdateDimensions = FALSE;
- // add space for dimensions
- S32 info_height = 0;
+ // set text on dimensions display (should be moved out of here and into a callback of some sort)
+ childSetTextArg("dimensions", "[WIDTH]", llformat("%d", mImage->getFullWidth()));
+ childSetTextArg("dimensions", "[HEIGHT]", llformat("%d", mImage->getFullHeight()));
+
LLRect dim_rect;
childGetRect("dimensions", dim_rect);
- S32 dim_height = dim_rect.getHeight();
- info_height += dim_height + CLIENT_RECT_VPAD;
- view_height += info_height;
-
- S32 button_height = 0;
- if (mShowKeepDiscard || mCopyToInv) { //mCopyToInvBtn
- // add space for buttons
- view_height += BTN_HEIGHT + CLIENT_RECT_VPAD;
- button_height = BTN_HEIGHT + PREVIEW_PAD;
- }
+ S32 horiz_pad = 2 * (LLPANEL_BORDER_WIDTH + PREVIEW_PAD) + PREVIEW_RESIZE_HANDLE_SIZE;
- view_width = llmax(view_width, getMinWidth());
- view_height = llmax(view_height, getMinHeight());
-
- if (client_height != mLastHeight || client_width != mLastWidth)
- {
- mLastWidth = client_width;
- mLastHeight = client_height;
+ // add space for dimensions and aspect ratio
+ S32 info_height = dim_rect.mTop + CLIENT_RECT_VPAD;
+
+ 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 ;
+
+ S32 client_width = client_rect.getWidth();
+ S32 client_height = client_rect.getHeight();
- S32 old_top = getRect().mTop;
- S32 old_left = getRect().mLeft;
- if (getHost())
+ if (mAspectRatio > 0.f)
+ {
+ if(mAspectRatio > 1.f)
{
- getHost()->growToFit(view_width, view_height);
+ client_height = llceil((F32)client_width / mAspectRatio);
+ if(client_height > client_rect.getHeight())
+ {
+ client_height = client_rect.getHeight();
+ client_width = llceil((F32)client_height * mAspectRatio);
+ }
}
else
{
- reshape( view_width, view_height );
- S32 new_bottom = old_top - getRect().getHeight();
- setOrigin( old_left, new_bottom );
- // Try to keep whole view onscreen, don't allow partial offscreen.
- gFloaterView->adjustToFitScreen(this, FALSE);
+ client_width = llceil((F32)client_height * mAspectRatio);
+ if(client_width > client_rect.getWidth())
+ {
+ client_width = client_rect.getWidth();
+ client_height = llceil((F32)client_width / mAspectRatio);
+ }
}
}
-
- if (!mUserResized)
- {
- // clamp texture size to fit within actual size of floater after attempting resize
- client_width = llmin(client_width, getRect().getWidth() - horiz_pad);
- client_height = llmin(client_height, getRect().getHeight() - PREVIEW_HEADER_SIZE
- - (2 * CLIENT_RECT_VPAD) - LLPANEL_BORDER_WIDTH - info_height);
+ mClientRect.setLeftTopAndSize(client_rect.getCenterX() - (client_width / 2), client_rect.getCenterY() + (client_height / 2), client_width, client_height);
-
- }
- else
+ // Hide the aspect ratio label if the window is too narrow
+ // Assumes the label should be to the right of the dimensions
+ LLRect aspect_label_rect;
+ childGetRect("aspect_ratio", aspect_label_rect);
+ childSetVisible("aspect_ratio", dim_rect.mRight < aspect_label_rect.mLeft);
+}
+
+
+// Return true if everything went fine, false if we somewhat modified the ratio as we bumped on border values
+bool LLPreviewTexture::setAspectRatio(const F32 width, const F32 height)
+{
+ mUpdateDimensions = TRUE;
+
+ // We don't allow negative width or height. Also, if height is positive but too small, we reset to default
+ // A default 0.f value for mAspectRatio means "unconstrained" in the rest of the code
+ if ((width <= 0.f) || (height <= F_APPROXIMATELY_ZERO))
{
- client_width = getRect().getWidth() - horiz_pad;
- client_height = getRect().getHeight() - vert_pad;
+ mAspectRatio = 0.f;
+ return false;
}
+
+ // Compute and store the ratio
+ F32 ratio = width / height;
+ mAspectRatio = llclamp(ratio, PREVIEW_TEXTURE_MIN_ASPECT, PREVIEW_TEXTURE_MAX_ASPECT);
+
+ // Return false if we clamped the value, true otherwise
+ return (ratio == mAspectRatio);
+}
- S32 max_height = getRect().getHeight() - PREVIEW_BORDER - button_height
- - CLIENT_RECT_VPAD - info_height - CLIENT_RECT_VPAD - PREVIEW_HEADER_SIZE;
- S32 max_width = getRect().getWidth() - horiz_pad;
- client_height = llclamp(client_height, 1, max_height);
- client_width = llclamp(client_width, 1, max_width);
+void LLPreviewTexture::onAspectRatioCommit(LLUICtrl* ctrl, void* userdata)
+{
+ LLPreviewTexture* self = (LLPreviewTexture*) userdata;
- LLRect window_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
- window_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD);
- window_rect.mBottom += PREVIEW_BORDER + button_height + CLIENT_RECT_VPAD + info_height + CLIENT_RECT_VPAD;
-
- mClientRect.setLeftTopAndSize(window_rect.getCenterX() - (client_width / 2), window_rect.mTop, client_width, client_height);
+ std::string ratio(ctrl->getValue().asString());
+ std::string::size_type separator(ratio.find_first_of(":/\\"));
+
+ if (std::string::npos == separator) {
+ // If there's no separator assume we want an unconstrained ratio
+ self->setAspectRatio( 0.f, 0.f );
+ return;
+ }
+
+ F32 width, height;
+ std::istringstream numerator(ratio.substr(0, separator));
+ std::istringstream denominator(ratio.substr(separator + 1));
+ numerator >> width;
+ denominator >> height;
+
+ self->setAspectRatio( width, height );
}
-
void LLPreviewTexture::loadAsset()
{
- mImage = gImageList.getImage(mImageID, MIPMAP_TRUE, FALSE);
- mImage->setBoostLevel(LLViewerImage::BOOST_PREVIEW);
+ mImage = LLViewerTextureManager::getFetchedTexture(mImageID, MIPMAP_TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+ mImage->setBoostLevel(LLViewerTexture::BOOST_PREVIEW);
+ mImage->forceToSaveRawImage(0) ;
mAssetStatus = PREVIEW_ASSET_LOADING;
+ updateDimensions();
+ childSetVisible("save_tex_btn", canSaveAs());
}
LLPreview::EAssetStatus LLPreviewTexture::getAssetStatus()
{
- if (mImage.notNull() && (mImage->mFullWidth * mImage->mFullHeight > 0))
+ if (mImage.notNull() && (mImage->getFullWidth() * mImage->getFullHeight() > 0))
{
mAssetStatus = PREVIEW_ASSET_LOADED;
}
diff --git a/indra/newview/llpreviewtexture.h b/indra/newview/llpreviewtexture.h
index 75fd39eab0..980aecee6d 100644
--- a/indra/newview/llpreviewtexture.h
+++ b/indra/newview/llpreviewtexture.h
@@ -36,26 +36,15 @@
#include "llpreview.h"
#include "llbutton.h"
#include "llframetimer.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
+class LLComboBox;
class LLImageRaw;
class LLPreviewTexture : public LLPreview
{
public:
- LLPreviewTexture(
- const std::string& name,
- const LLRect& rect,
- const std::string& title,
- const LLUUID& item_uuid,
- const LLUUID& object_id,
- BOOL show_keep_discard = FALSE);
- LLPreviewTexture(
- const std::string& name,
- const LLRect& rect,
- const std::string& title,
- const LLUUID& asset_id,
- BOOL copy_to_inv = FALSE);
+ LLPreviewTexture(const LLSD& key);
~LLPreviewTexture();
virtual void draw();
@@ -65,40 +54,47 @@ public:
virtual void loadAsset();
virtual EAssetStatus getAssetStatus();
-
- static void saveToFile(void* userdata);
+
+ virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+ virtual void onFocusReceived();
+
static void onFileLoadedForSave(
BOOL success,
- LLViewerImage *src_vi,
+ LLViewerFetchedTexture *src_vi,
LLImageRaw* src,
LLImageRaw* aux_src,
S32 discard_level,
BOOL final,
void* userdata );
-
-
+ void openToSave();
+
+ static void onSaveAsBtn(void* data);
protected:
void init();
-
- virtual const char *getTitleName() const { return "Texture"; }
+ /* virtual */ BOOL postBuild();
+ bool setAspectRatio(const F32 width, const F32 height);
+ static void onAspectRatioCommit(LLUICtrl*,void* userdata);
private:
void updateDimensions();
- LLUUID mImageID;
- LLPointer<LLViewerImage> mImage;
+ LLUUID mImageID;
+ LLPointer<LLViewerFetchedTexture> mImage;
BOOL mLoadingFullImage;
std::string mSaveFileName;
LLFrameTimer mSavedFileTimer;
BOOL mShowKeepDiscard;
BOOL mCopyToInv;
+ // Save the image once it's loaded.
+ BOOL mPreviewToSave;
+
// This is stored off in a member variable, because the save-as
// button and drag and drop functionality need to know.
BOOL mIsCopyable;
S32 mLastHeight;
S32 mLastWidth;
+ F32 mAspectRatio;
+ BOOL mUpdateDimensions;
};
-
-
#endif // LL_LLPREVIEWTEXTURE_H
diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp
index bfd14f709a..7a48f890e0 100644
--- a/indra/newview/llprogressview.cpp
+++ b/indra/newview/llprogressview.cpp
@@ -40,8 +40,8 @@
#include "llrender.h"
#include "llui.h"
#include "llfontgl.h"
-#include "llimagegl.h"
#include "lltimer.h"
+#include "lltextbox.h"
#include "llglheaders.h"
#include "llagent.h"
@@ -50,7 +50,7 @@
#include "llprogressbar.h"
#include "llstartup.h"
#include "llviewercontrol.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewerwindow.h"
#include "llappviewer.h"
#include "llweb.h"
@@ -68,15 +68,16 @@ const F32 TOTAL_LOGIN_TIME = 10.f; // seconds, wild guess at time from GL contex
S32 gLastStartAnimationFrame = 0; // human-style indexing, first image = 1
const S32 ANIMATION_FRAMES = 1; //13;
-// XUI:translate
-LLProgressView::LLProgressView(const std::string& name, const LLRect &rect)
-: LLPanel(name, rect, FALSE),
+// XUI: Translate
+LLProgressView::LLProgressView(const LLRect &rect)
+: LLPanel(),
mPercentDone( 0.f ),
- mURLInMessage(false),
- mMouseDownInActiveArea( false )
+ mMouseDownInActiveArea( false ),
+ mUpdateEvents("LLProgressView")
{
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_progress.xml");
reshape(rect.getWidth(), rect.getHeight());
+ mUpdateEvents.listen("self", boost::bind(&LLProgressView::handleUpdate, this, _1));
}
BOOL LLProgressView::postBuild()
@@ -84,7 +85,7 @@ BOOL LLProgressView::postBuild()
mProgressBar = getChild<LLProgressBar>("login_progress_bar");
mCancelBtn = getChild<LLButton>("cancel_btn");
- mCancelBtn->setClickedCallback( LLProgressView::onCancelButtonClicked );
+ mCancelBtn->setClickedCallback( LLProgressView::onCancelButtonClicked, NULL );
mFadeTimer.stop();
getChild<LLTextBox>("title_text")->setText(LLStringExplicit(LLAppViewer::instance()->getSecondLifeTitle()));
@@ -146,10 +147,10 @@ void LLProgressView::draw()
// Paint bitmap if we've got one
glPushMatrix();
- if (gStartImageGL)
+ if (gStartTexture)
{
LLGLSUIDefault gls_ui;
- gGL.getTexUnit(0)->bind(gStartImageGL);
+ gGL.getTexUnit(0)->bind(gStartTexture.get());
gGL.color4f(1.f, 1.f, 1.f, mFadeTimer.getStarted() ? clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, FADE_IN_TIME, 1.f, 0.f) : 1.f);
F32 image_aspect = (F32)gStartImageWidth / (F32)gStartImageHeight;
S32 width = getRect().getWidth();
@@ -183,9 +184,10 @@ void LLProgressView::draw()
LLPanel::draw();
if (mFadeTimer.getElapsedTimeF32() > FADE_IN_TIME)
{
- gFocusMgr.removeTopCtrlWithoutCallback(this);
+ // Fade is complete, release focus
+ gFocusMgr.releaseFocusIfNeeded( this );
LLPanel::setVisible(FALSE);
- gStartImageGL = NULL;
+ gStartTexture = NULL;
}
return;
}
@@ -196,7 +198,7 @@ void LLProgressView::draw()
void LLProgressView::setText(const std::string& text)
{
- getChild<LLTextBox>("progress_text")->setWrappedText(LLStringExplicit(text));
+ getChild<LLUICtrl>("progress_text")->setValue(text);
}
void LLProgressView::setPercent(const F32 percent)
@@ -207,12 +209,7 @@ void LLProgressView::setPercent(const F32 percent)
void LLProgressView::setMessage(const std::string& msg)
{
mMessage = msg;
- mURLInMessage = (mMessage.find( "https://" ) != std::string::npos ||
- mMessage.find( "http://" ) != std::string::npos ||
- mMessage.find( "ftp://" ) != std::string::npos);
-
- getChild<LLTextBox>("message_text")->setWrappedText(LLStringExplicit(mMessage));
- getChild<LLTextBox>("message_text")->setHoverActive(mURLInMessage);
+ getChild<LLUICtrl>("message_text")->setValue(mMessage);
}
void LLProgressView::setCancelButtonVisible(BOOL b, const std::string& label)
@@ -265,3 +262,26 @@ void LLProgressView::onClickMessage(void* data)
}
}
}
+
+bool LLProgressView::handleUpdate(const LLSD& event_data)
+{
+ LLSD message = event_data.get("message");
+ LLSD desc = event_data.get("desc");
+ LLSD percent = event_data.get("percent");
+
+ if(message.isDefined())
+ {
+ setMessage(message.asString());
+ }
+
+ if(desc.isDefined())
+ {
+ setText(desc.asString());
+ }
+
+ if(percent.isDefined())
+ {
+ setPercent(percent.asReal());
+ }
+ return false;
+}
diff --git a/indra/newview/llprogressview.h b/indra/newview/llprogressview.h
index 9517ee1321..6853674d88 100644
--- a/indra/newview/llprogressview.h
+++ b/indra/newview/llprogressview.h
@@ -35,6 +35,7 @@
#include "llpanel.h"
#include "llframetimer.h"
+#include "llevents.h"
class LLImageRaw;
class LLButton;
@@ -43,7 +44,7 @@ class LLProgressBar;
class LLProgressView : public LLPanel
{
public:
- LLProgressView(const std::string& name, const LLRect& rect);
+ LLProgressView(const LLRect& rect);
virtual ~LLProgressView();
BOOL postBuild();
@@ -74,9 +75,13 @@ protected:
LLFrameTimer mProgressTimer;
LLRect mOutlineRect;
bool mMouseDownInActiveArea;
- bool mURLInMessage;
+ // The LLEventStream mUpdateEvents depends upon this class being a singleton
+ // to avoid pump name conflicts.
static LLProgressView* sInstance;
+ LLEventStream mUpdateEvents;
+
+ bool handleUpdate(const LLSD& event_data);
};
#endif // LL_LLPROGRESSVIEW_H
diff --git a/indra/newview/llrecentpeople.cpp b/indra/newview/llrecentpeople.cpp
new file mode 100644
index 0000000000..bd46b5b56a
--- /dev/null
+++ b/indra/newview/llrecentpeople.cpp
@@ -0,0 +1,88 @@
+/**
+ * @file llrecentpeople.cpp
+ * @brief List of people with which the user has recently interacted.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llrecentpeople.h"
+#include "llgroupmgr.h"
+
+#include "llagent.h"
+
+using namespace LLOldEvents;
+
+bool LLRecentPeople::add(const LLUUID& id)
+{
+ if (id == gAgent.getID())
+ return false;
+
+ bool is_not_group_id = LLGroupMgr::getInstance()->getGroupData(id) == NULL;
+
+ if (is_not_group_id)
+ {
+ LLDate date_added = LLDate::now();
+
+ //[] instead of insert to replace existing id->date with new date value
+ mPeople[id] = date_added;
+ mChangedSignal();
+ }
+
+ return is_not_group_id;
+}
+
+bool LLRecentPeople::contains(const LLUUID& id) const
+{
+ return mPeople.find(id) != mPeople.end();
+}
+
+void LLRecentPeople::get(std::vector<LLUUID>& result) const
+{
+ result.clear();
+ for (recent_people_t::const_iterator pos = mPeople.begin(); pos != mPeople.end(); ++pos)
+ result.push_back((*pos).first);
+}
+
+const LLDate& LLRecentPeople::getDate(const LLUUID& id) const
+{
+ recent_people_t::const_iterator it = mPeople.find(id);
+ if (it!= mPeople.end()) return (*it).second;
+
+ static LLDate no_date = LLDate();
+ return no_date;
+}
+
+// virtual
+bool LLRecentPeople::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+{
+ (void) userdata;
+ add(event->getValue().asUUID());
+ return true;
+}
diff --git a/indra/newview/llrecentpeople.h b/indra/newview/llrecentpeople.h
new file mode 100644
index 0000000000..e0f2faaec5
--- /dev/null
+++ b/indra/newview/llrecentpeople.h
@@ -0,0 +1,106 @@
+/**
+ * @file llrecentpeople.h
+ * @brief List of people with which the user has recently interacted.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLRECENTPEOPLE_H
+#define LL_LLRECENTPEOPLE_H
+
+#include "llevent.h"
+#include "llsingleton.h"
+#include "lluuid.h"
+
+#include <vector>
+#include <set>
+#include <boost/signals2.hpp>
+
+class LLDate;
+
+/**
+ * List of people the agent recently interacted with.
+ *
+ * Includes: anyone with whom the user IM'd or called
+ * (1:1 and ad-hoc but not SL Group chat),
+ * anyone with whom the user has had a transaction
+ * (inventory offer, friend request, etc),
+ * and anyone that has chatted within chat range of the user in-world.
+ *
+ *TODO: purge least recently added items?
+ */
+class LLRecentPeople: public LLSingleton<LLRecentPeople>, public LLOldEvents::LLSimpleListener
+{
+ LOG_CLASS(LLRecentPeople);
+public:
+ typedef boost::signals2::signal<void ()> signal_t;
+
+ /**
+ * Add specified avatar to the list if it's not there already.
+ *
+ * @param id avatar to add.
+ * @return false if the avatar is in the list already, true otherwise
+ */
+ bool add(const LLUUID& id);
+
+ /**
+ * @param id avatar to search.
+ * @return true if the avatar is in the list, false otherwise.
+ */
+ bool contains(const LLUUID& id) const;
+
+ /**
+ * Get the whole list.
+ *
+ * @param result where to put the result.
+ */
+ void get(std::vector<LLUUID>& result) const;
+
+ const LLDate& getDate(const LLUUID& id) const;
+
+ /**
+ * Set callback to be called when the list changed.
+ *
+ * Multiple callbacks can be set.
+ *
+ * @return no connection; use boost::bind + boost::signals2::trackable to disconnect slots.
+ */
+ void setChangedCallback(const signal_t::slot_type& cb) { mChangedSignal.connect(cb); }
+
+ /**
+ * LLSimpleListener interface.
+ */
+ /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+
+private:
+ typedef std::map<LLUUID, LLDate> recent_people_t;
+ recent_people_t mPeople;
+ signal_t mChangedSignal;
+};
+
+#endif // LL_LLRECENTPEOPLE_H
diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp
index 8ff4dea2b1..95e3dd6d78 100644
--- a/indra/newview/llremoteparcelrequest.cpp
+++ b/indra/newview/llremoteparcelrequest.cpp
@@ -34,8 +34,7 @@
#include "llviewerprecompiledheaders.h"
-#include "llagent.h"
-#include "llremoteparcelrequest.h"
+#include "message.h"
#include "llpanelplace.h"
#include "llpanel.h"
@@ -43,37 +42,131 @@
#include "llsdserialize.h"
#include "llviewerregion.h"
#include "llview.h"
-#include "message.h"
-LLRemoteParcelRequestResponder::LLRemoteParcelRequestResponder(LLHandle<LLPanel> place_panel_handle)
-{
- mPlacePanelHandle = place_panel_handle;
-}
-/*virtual*/
+#include "llagent.h"
+#include "llremoteparcelrequest.h"
+
+
+LLRemoteParcelRequestResponder::LLRemoteParcelRequestResponder(LLHandle<LLRemoteParcelInfoObserver> observer_handle)
+ : mObserverHandle(observer_handle)
+{}
+
+//If we get back a normal response, handle it here
+//virtual
void LLRemoteParcelRequestResponder::result(const LLSD& content)
{
LLUUID parcel_id = content["parcel_id"];
- LLPanelPlace* place_panelp = (LLPanelPlace*)mPlacePanelHandle.get();
-
- if(place_panelp)
+ // Panel inspecting the information may be closed and destroyed
+ // before this response is received.
+ LLRemoteParcelInfoObserver* observer = mObserverHandle.get();
+ if (observer)
{
- place_panelp->setParcelID(parcel_id);
+ observer->setParcelID(parcel_id);
}
-
}
-/*virtual*/
+//If we get back an error (not found, etc...), handle it here
+//virtual
void LLRemoteParcelRequestResponder::error(U32 status, const std::string& reason)
{
llinfos << "LLRemoteParcelRequest::error("
<< status << ": " << reason << ")" << llendl;
- LLPanelPlace* place_panelp = (LLPanelPlace*)mPlacePanelHandle.get();
- if(place_panelp)
+ // Panel inspecting the information may be closed and destroyed
+ // before this response is received.
+ LLRemoteParcelInfoObserver* observer = mObserverHandle.get();
+ if (observer)
+ {
+ observer->setErrorStatus(status, reason);
+ }
+}
+
+void LLRemoteParcelInfoProcessor::addObserver(const LLUUID& parcel_id, LLRemoteParcelInfoObserver* observer)
+{
+ // Check if the observer is already in observers list for this UUID
+ observer_multimap_t::iterator it;
+
+ it = mObservers.find(parcel_id);
+ while (it != mObservers.end())
{
- place_panelp->setErrorStatus(status, reason);
+ if (it->second == observer)
+ {
+ return;
+ }
+ else
+ {
+ ++it;
+ }
}
+ mObservers.insert(std::pair<LLUUID, LLRemoteParcelInfoObserver*>(parcel_id, observer));
}
+void LLRemoteParcelInfoProcessor::removeObserver(const LLUUID& parcel_id, LLRemoteParcelInfoObserver* observer)
+{
+ if (!observer)
+ {
+ return;
+ }
+
+ observer_multimap_t::iterator it;
+
+ it = mObservers.find(parcel_id);
+ while (it != mObservers.end())
+ {
+ if (it->second == observer)
+ {
+ mObservers.erase(it);
+ break;
+ }
+ else
+ {
+ ++it;
+ }
+ }
+}
+
+//static
+void LLRemoteParcelInfoProcessor::processParcelInfoReply(LLMessageSystem* msg, void**)
+{
+ LLParcelData parcel_data;
+
+ msg->getUUID ("Data", "ParcelID", parcel_data.parcel_id);
+ msg->getUUID ("Data", "OwnerID", parcel_data.owner_id);
+ msg->getString ("Data", "Name", parcel_data.name);
+ msg->getString ("Data", "Desc", parcel_data.desc);
+ msg->getS32 ("Data", "ActualArea", parcel_data.actual_area);
+ msg->getS32 ("Data", "BillableArea", parcel_data.billable_area);
+ msg->getU8 ("Data", "Flags", parcel_data.flags);
+ msg->getF32 ("Data", "GlobalX", parcel_data.global_x);
+ msg->getF32 ("Data", "GlobalY", parcel_data.global_y);
+ msg->getF32 ("Data", "GlobalZ", parcel_data.global_z);
+ msg->getString ("Data", "SimName", parcel_data.sim_name);
+ msg->getUUID ("Data", "SnapshotID", parcel_data.snapshot_id);
+ msg->getF32 ("Data", "Dwell", parcel_data.dwell);
+ msg->getS32 ("Data", "SalePrice", parcel_data.sale_price);
+ msg->getS32 ("Data", "AuctionID", parcel_data.auction_id);
+
+ LLRemoteParcelInfoProcessor::observer_multimap_t observers = LLRemoteParcelInfoProcessor::getInstance()->mObservers;
+
+ observer_multimap_t::iterator oi = observers.find(parcel_data.parcel_id);
+ observer_multimap_t::iterator end = observers.upper_bound(parcel_data.parcel_id);
+ for (; oi != end; ++oi)
+ {
+ oi->second->processParcelInfo(parcel_data);
+ }
+}
+
+void LLRemoteParcelInfoProcessor::sendParcelInfoRequest(const LLUUID& parcel_id)
+{
+ LLMessageSystem *msg = gMessageSystem;
+
+ msg->newMessage("ParcelInfoRequest");
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+ msg->addUUID("SessionID", gAgent.getSessionID());
+ msg->nextBlock("Data");
+ msg->addUUID("ParcelID", parcel_id);
+ gAgent.sendReliableMessage();
+}
diff --git a/indra/newview/llremoteparcelrequest.h b/indra/newview/llremoteparcelrequest.h
index c92ee3ff3a..c04f6b1858 100644
--- a/indra/newview/llremoteparcelrequest.h
+++ b/indra/newview/llremoteparcelrequest.h
@@ -38,17 +38,74 @@
#include "llhttpclient.h"
#include "llpanel.h"
+class LLMessageSystem;
+class LLRemoteParcelInfoObserver;
+
class LLRemoteParcelRequestResponder : public LLHTTPClient::Responder
{
public:
- LLRemoteParcelRequestResponder(LLHandle<LLPanel> place_panel_handle);
+ LLRemoteParcelRequestResponder(LLHandle<LLRemoteParcelInfoObserver> observer_handle);
+
//If we get back a normal response, handle it here
- virtual void result(const LLSD& content);
+ /*virtual*/ void result(const LLSD& content);
+
//If we get back an error (not found, etc...), handle it here
- virtual void error(U32 status, const std::string& reason);
+ /*virtual*/ void error(U32 status, const std::string& reason);
+
+protected:
+ LLHandle<LLRemoteParcelInfoObserver> mObserverHandle;
+};
+
+struct LLParcelData
+{
+ LLUUID parcel_id;
+ LLUUID owner_id;
+ std::string name;
+ std::string desc;
+ S32 actual_area;
+ S32 billable_area;
+ U8 flags;
+ F32 global_x;
+ F32 global_y;
+ F32 global_z;
+ std::string sim_name;
+ LLUUID snapshot_id;
+ F32 dwell;
+ S32 sale_price;
+ S32 auction_id;
+};
+
+// An interface class for panels which display parcel information
+// like name, description, area, snapshot etc.
+class LLRemoteParcelInfoObserver
+{
+public:
+ LLRemoteParcelInfoObserver() { mObserverHandle.bind(this); }
+ virtual ~LLRemoteParcelInfoObserver() {}
+ virtual void processParcelInfo(const LLParcelData& parcel_data) = 0;
+ virtual void setParcelID(const LLUUID& parcel_id) = 0;
+ virtual void setErrorStatus(U32 status, const std::string& reason) = 0;
+ LLHandle<LLRemoteParcelInfoObserver> getObserverHandle() const { return mObserverHandle; }
protected:
- LLHandle<LLPanel> mPlacePanelHandle;
+ LLRootHandle<LLRemoteParcelInfoObserver> mObserverHandle;
+};
+
+class LLRemoteParcelInfoProcessor : public LLSingleton<LLRemoteParcelInfoProcessor>
+{
+public:
+ virtual ~LLRemoteParcelInfoProcessor() {}
+
+ void addObserver(const LLUUID& parcel_id, LLRemoteParcelInfoObserver* observer);
+ void removeObserver(const LLUUID& parcel_id, LLRemoteParcelInfoObserver* observer);
+
+ void sendParcelInfoRequest(const LLUUID& parcel_id);
+
+ static void processParcelInfoReply(LLMessageSystem* msg, void**);
+
+private:
+ typedef std::multimap<LLUUID, LLRemoteParcelInfoObserver*> observer_multimap_t;
+ observer_multimap_t mObservers;
};
#endif // LL_LLREMOTEPARCELREQUEST_H
diff --git a/indra/newview/llresourcedata.h b/indra/newview/llresourcedata.h
index 46b79150bb..b4b9042689 100644
--- a/indra/newview/llresourcedata.h
+++ b/indra/newview/llresourcedata.h
@@ -39,11 +39,12 @@
struct LLResourceData
{
LLAssetInfo mAssetInfo;
- LLAssetType::EType mPreferredLocation;
+ LLFolderType::EType mPreferredLocation;
LLInventoryType::EType mInventoryType;
U32 mNextOwnerPerm;
S32 mExpectedUploadCost;
void *mUserData;
+ static const S8 INVALID_LOCATION = -2;
};
#endif
diff --git a/indra/newview/llrootview.h b/indra/newview/llrootview.h
new file mode 100644
index 0000000000..760b1a7a4c
--- /dev/null
+++ b/indra/newview/llrootview.h
@@ -0,0 +1,73 @@
+/**
+ * @file llrootview.h
+ * @brief Mother of all Views
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLROOTVIEW_H
+#define LL_LLROOTVIEW_H
+
+#include "llview.h"
+#include "lluictrlfactory.h"
+
+class LLRootViewRegistry : public LLChildRegistry<LLRootViewRegistry>
+{};
+
+class LLRootView : public LLView
+{
+public:
+ typedef LLRootViewRegistry child_registry_t;
+
+ LLRootView(const Params& p)
+ : LLView(p)
+ {}
+
+ // added to provide possibility to handle mouse click event inside all application
+ // window without creating any floater
+ typedef boost::signals2::signal<void(S32 x, S32 y, MASK mask)>
+ mouse_signal_t;
+
+ private:
+ mouse_signal_t mMouseDownSignal;
+
+ public:
+ /*virtual*/
+ BOOL handleMouseDown(S32 x, S32 y, MASK mask)
+ {
+ mMouseDownSignal(x, y, mask);
+ return LLView::handleMouseDown(x, y, mask);
+ }
+
+ boost::signals2::connection addMouseDownCallback(
+ const mouse_signal_t::slot_type& cb)
+ {
+ return mMouseDownSignal.connect(cb);
+ }
+};
+#endif //LL_LLROOTVIEW_H
diff --git a/indra/newview/llsavedsettingsglue.cpp b/indra/newview/llsavedsettingsglue.cpp
index 073b51f80e..4736afa7ba 100644
--- a/indra/newview/llsavedsettingsglue.cpp
+++ b/indra/newview/llsavedsettingsglue.cpp
@@ -39,37 +39,27 @@
#include "llviewercontrol.h"
-void LLSavedSettingsGlue::setBOOL(LLUICtrl* ctrl, void* data)
+void LLSavedSettingsGlue::setBOOL(LLUICtrl* ctrl, const std::string& name)
{
- const char* name = (const char*)data;
- LLSD value = ctrl->getValue();
- gSavedSettings.setBOOL(name, value.asBoolean());
+ gSavedSettings.setBOOL(name, ctrl->getValue().asBoolean());
}
-void LLSavedSettingsGlue::setS32(LLUICtrl* ctrl, void* data)
+void LLSavedSettingsGlue::setS32(LLUICtrl* ctrl, const std::string& name)
{
- const char* name = (const char*)data;
- LLSD value = ctrl->getValue();
- gSavedSettings.setS32(name, value.asInteger());
+ gSavedSettings.setS32(name, ctrl->getValue().asInteger());
}
-void LLSavedSettingsGlue::setF32(LLUICtrl* ctrl, void* data)
+void LLSavedSettingsGlue::setF32(LLUICtrl* ctrl, const std::string& name)
{
- const char* name = (const char*)data;
- LLSD value = ctrl->getValue();
- gSavedSettings.setF32(name, (F32)value.asReal());
+ gSavedSettings.setF32(name, (F32)ctrl->getValue().asReal());
}
-void LLSavedSettingsGlue::setU32(LLUICtrl* ctrl, void* data)
+void LLSavedSettingsGlue::setU32(LLUICtrl* ctrl, const std::string& name)
{
- const char* name = (const char*)data;
- LLSD value = ctrl->getValue();
- gSavedSettings.setU32(name, (U32)value.asInteger());
+ gSavedSettings.setU32(name, (U32)ctrl->getValue().asInteger());
}
-void LLSavedSettingsGlue::setString(LLUICtrl* ctrl, void* data)
+void LLSavedSettingsGlue::setString(LLUICtrl* ctrl, const std::string& name)
{
- const char* name = (const char*)data;
- LLSD value = ctrl->getValue();
- gSavedSettings.setString(name, value.asString());
+ gSavedSettings.setString(name, ctrl->getValue().asString());
}
diff --git a/indra/newview/llsavedsettingsglue.h b/indra/newview/llsavedsettingsglue.h
index 8a0f36945c..6c8662dd58 100644
--- a/indra/newview/llsavedsettingsglue.h
+++ b/indra/newview/llsavedsettingsglue.h
@@ -42,11 +42,11 @@ class LLUICtrl;
class LLSavedSettingsGlue
{
public:
- static void setBOOL(LLUICtrl* ctrl, void* name);
- static void setS32(LLUICtrl* ctrl, void* name);
- static void setF32(LLUICtrl* ctrl, void* name);
- static void setU32(LLUICtrl* ctrl, void* name);
- static void setString(LLUICtrl* ctrl, void* name);
+ static void setBOOL(LLUICtrl* ctrl, const std::string& name);
+ static void setS32(LLUICtrl* ctrl, const std::string& name);
+ static void setF32(LLUICtrl* ctrl, const std::string& name);
+ static void setU32(LLUICtrl* ctrl, const std::string& name);
+ static void setString(LLUICtrl* ctrl, const std::string& name);
};
#endif
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
new file mode 100644
index 0000000000..a00b6a9288
--- /dev/null
+++ b/indra/newview/llscreenchannel.cpp
@@ -0,0 +1,832 @@
+/**
+ * @file llscreenchannel.cpp
+ * @brief Class implements a channel on a screen in which appropriate toasts may appear.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#include "lliconctrl.h"
+#include "lltextbox.h"
+#include "llscreenchannel.h"
+
+#include "lltoastpanel.h"
+#include "llviewercontrol.h"
+#include "llviewerwindow.h"
+#include "llfloaterreg.h"
+#include "lltrans.h"
+
+#include "lldockablefloater.h"
+#include "llsyswellwindow.h"
+#include "llimfloater.h"
+#include "llscriptfloater.h"
+#include "llfontgl.h"
+
+#include <algorithm>
+
+using namespace LLNotificationsUI;
+
+bool LLScreenChannel::mWasStartUpToastShown = false;
+
+//--------------------------------------------------------------------------
+//////////////////////
+// LLScreenChannelBase
+//////////////////////
+LLScreenChannelBase::LLScreenChannelBase(const LLUUID& id) :
+ mToastAlignment(NA_BOTTOM)
+ ,mCanStoreToasts(true)
+ ,mHiddenToastsNum(0)
+ ,mHoveredToast(NULL)
+ ,mControlHovering(false)
+ ,mShowToasts(true)
+{
+ mID = id;
+ mWorldViewRectConnection = gViewerWindow->setOnWorldViewRectUpdated(boost::bind(&LLScreenChannelBase::updatePositionAndSize, this, _1, _2));
+ setMouseOpaque( false );
+ setVisible(FALSE);
+}
+LLScreenChannelBase::~LLScreenChannelBase()
+{
+ mWorldViewRectConnection.disconnect();
+}
+
+bool LLScreenChannelBase::isHovering()
+{
+ bool res = mHoveredToast != NULL;
+ if (!res)
+ {
+ return res;
+ }
+
+ S32 x, y;
+ mHoveredToast->screenPointToLocal(gViewerWindow->getCurrentMouseX(),
+ gViewerWindow->getCurrentMouseY(), &x, &y);
+ res = mHoveredToast->pointInView(x, y) == TRUE;
+ return res;
+}
+
+void LLScreenChannelBase::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect)
+{
+ S32 top_delta = old_world_rect.mTop - new_world_rect.mTop;
+ S32 right_delta = old_world_rect.mRight - new_world_rect.mRight;
+
+ LLRect this_rect = getRect();
+
+ this_rect.mTop -= top_delta;
+ switch(mChannelAlignment)
+ {
+ case CA_LEFT :
+ break;
+ case CA_CENTRE :
+ this_rect.setCenterAndSize(new_world_rect.getWidth() / 2, new_world_rect.getHeight() / 2, this_rect.getWidth(), this_rect.getHeight());
+ break;
+ case CA_RIGHT :
+ this_rect.mLeft -= right_delta;
+ this_rect.mRight -= right_delta;
+ }
+ setRect(this_rect);
+ redrawToasts();
+
+}
+
+void LLScreenChannelBase::init(S32 channel_left, S32 channel_right)
+{
+ S32 channel_top = gViewerWindow->getWorldViewRectScaled().getHeight();
+ S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");
+ setRect(LLRect(channel_left, channel_top, channel_right, channel_bottom));
+ setVisible(TRUE);
+}
+
+//--------------------------------------------------------------------------
+//////////////////////
+// LLScreenChannel
+//////////////////////
+//--------------------------------------------------------------------------
+LLScreenChannel::LLScreenChannel(LLUUID& id):
+LLScreenChannelBase(id)
+,mStartUpToastPanel(NULL)
+{
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::init(S32 channel_left, S32 channel_right)
+{
+ LLScreenChannelBase::init(channel_left, channel_right);
+ LLRect world_rect = gViewerWindow->getWorldViewRectScaled();
+ updatePositionAndSize(world_rect, world_rect);
+}
+
+//--------------------------------------------------------------------------
+LLScreenChannel::~LLScreenChannel()
+{
+
+}
+
+std::list<LLToast*> LLScreenChannel::findToasts(const Matcher& matcher)
+{
+ std::list<LLToast*> res;
+
+ // collect stored toasts
+ for (std::vector<ToastElem>::iterator it = mStoredToastList.begin(); it
+ != mStoredToastList.end(); it++)
+ {
+ if (matcher.matches(it->toast->getNotification()))
+ {
+ res.push_back(it->toast);
+ }
+ }
+
+ // collect displayed toasts
+ for (std::vector<ToastElem>::iterator it = mToastList.begin(); it
+ != mToastList.end(); it++)
+ {
+ if (matcher.matches(it->toast->getNotification()))
+ {
+ res.push_back(it->toast);
+ }
+ }
+
+ return res;
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect)
+{
+ S32 right_delta = old_world_rect.mRight - new_world_rect.mRight;
+ LLRect this_rect = getRect();
+
+ switch(mChannelAlignment)
+ {
+ case CA_LEFT :
+ this_rect.mTop = (S32) (new_world_rect.getHeight() * getHeightRatio());
+ break;
+ case CA_CENTRE :
+ LLScreenChannelBase::updatePositionAndSize(old_world_rect, new_world_rect);
+ return;
+ case CA_RIGHT :
+ this_rect.mTop = (S32) (new_world_rect.getHeight() * getHeightRatio());
+ this_rect.mLeft -= right_delta;
+ this_rect.mRight -= right_delta;
+ }
+ setRect(this_rect);
+ redrawToasts();
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::addToast(const LLToast::Params& p)
+{
+ bool store_toast = false, show_toast = false;
+
+ mDisplayToastsAlways ? show_toast = true : show_toast = mWasStartUpToastShown && (mShowToasts || p.force_show);
+ store_toast = !show_toast && p.can_be_stored && mCanStoreToasts;
+
+ if(!show_toast && !store_toast)
+ {
+ mRejectToastSignal(p.notif_id);
+ return;
+ }
+
+ ToastElem new_toast_elem(p);
+
+ new_toast_elem.toast->setOnFadeCallback(boost::bind(&LLScreenChannel::onToastFade, this, _1));
+ new_toast_elem.toast->setOnToastDestroyedCallback(boost::bind(&LLScreenChannel::onToastDestroyed, this, _1));
+ if(mControlHovering)
+ {
+ new_toast_elem.toast->setOnToastHoverCallback(boost::bind(&LLScreenChannel::onToastHover, this, _1, _2));
+ new_toast_elem.toast->setMouseEnterCallback(boost::bind(&LLScreenChannel::stopFadingToasts, this));
+ new_toast_elem.toast->setMouseLeaveCallback(boost::bind(&LLScreenChannel::startFadingToasts, this));
+ }
+
+ if(show_toast)
+ {
+ mToastList.push_back(new_toast_elem);
+ if(p.can_be_stored)
+ {
+ // store toasts immediately - EXT-3762
+ storeToast(new_toast_elem);
+ }
+ updateShowToastsState();
+ redrawToasts();
+ }
+ else // store_toast
+ {
+ mHiddenToastsNum++;
+ storeToast(new_toast_elem);
+ }
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::onToastDestroyed(LLToast* toast)
+{
+ std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), static_cast<LLPanel*>(toast));
+
+ if(it != mToastList.end())
+ {
+ mToastList.erase(it);
+ }
+
+ it = find(mStoredToastList.begin(), mStoredToastList.end(), static_cast<LLPanel*>(toast));
+
+ if(it != mStoredToastList.end())
+ {
+ mStoredToastList.erase(it);
+ }
+}
+
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::onToastFade(LLToast* toast)
+{
+ std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), static_cast<LLPanel*>(toast));
+
+ if(it != mToastList.end())
+ {
+ bool delete_toast = !mCanStoreToasts || !toast->getCanBeStored();
+ if(delete_toast)
+ {
+ mToastList.erase(it);
+ deleteToast(toast);
+ }
+ else
+ {
+ storeToast((*it));
+ mToastList.erase(it);
+ }
+
+ redrawToasts();
+ }
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::deleteToast(LLToast* toast)
+{
+ if (toast->isDead())
+ {
+ return;
+ }
+
+ // send signal to observers about destroying of a toast
+ toast->mOnDeleteToastSignal(toast);
+
+ // update channel's Hovering state
+ // turning hovering off manually because onMouseLeave won't happen if a toast was closed using a keyboard
+ if(mHoveredToast == toast)
+ {
+ mHoveredToast = NULL;
+ startFadingToasts();
+ }
+
+ // close the toast
+ toast->closeFloater();
+}
+
+//--------------------------------------------------------------------------
+
+void LLScreenChannel::storeToast(ToastElem& toast_elem)
+{
+ // do not store clones
+ std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), toast_elem.id);
+ if( it != mStoredToastList.end() )
+ return;
+
+ mStoredToastList.push_back(toast_elem);
+ mOnStoreToast(toast_elem.toast->getPanel(), toast_elem.id);
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::loadStoredToastsToChannel()
+{
+ std::vector<ToastElem>::iterator it;
+
+ if(mStoredToastList.size() == 0)
+ return;
+
+ for(it = mStoredToastList.begin(); it != mStoredToastList.end(); ++it)
+ {
+ (*it).toast->setIsHidden(false);
+ (*it).toast->resetTimer();
+ mToastList.push_back((*it));
+ }
+
+ mStoredToastList.clear();
+ redrawToasts();
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id)
+{
+ std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), id);
+
+ if( it == mStoredToastList.end() )
+ return;
+
+ LLToast* toast = (*it).toast;
+
+ if(toast->getVisible())
+ {
+ // toast is already in channel
+ return;
+ }
+
+ toast->setIsHidden(false);
+ toast->resetTimer();
+ mToastList.push_back((*it));
+
+ redrawToasts();
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::removeStoredToastByNotificationID(LLUUID id)
+{
+ // *TODO: may be remove this function
+ std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), id);
+
+ if( it == mStoredToastList.end() )
+ return;
+
+ LLToast* toast = (*it).toast;
+ mStoredToastList.erase(it);
+ mRejectToastSignal(toast->getNotificationID());
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::killToastByNotificationID(LLUUID id)
+{
+ // searching among toasts on a screen
+ std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id);
+
+ if( it != mToastList.end())
+ {
+ LLToast* toast = (*it).toast;
+ // if it is a notification toast and notification is UnResponded - then respond on it
+ // else - simply destroy a toast
+ //
+ // NOTE: if a notification is unresponded this function will be called twice for the same toast.
+ // At first, the notification will be discarded, at second (it will be caused by discarding),
+ // the toast will be destroyed.
+ if(toast->isNotificationValid())
+ {
+ mRejectToastSignal(toast->getNotificationID());
+ }
+ else
+ {
+ mToastList.erase(it);
+ deleteToast(toast);
+ redrawToasts();
+ }
+ return;
+ }
+
+ // searching among stored toasts
+ it = find(mStoredToastList.begin(), mStoredToastList.end(), id);
+
+ if( it != mStoredToastList.end() )
+ {
+ LLToast* toast = (*it).toast;
+ mStoredToastList.erase(it);
+ // send signal to a listener to let him perform some action on toast rejecting
+ mRejectToastSignal(toast->getNotificationID());
+ deleteToast(toast);
+ }
+}
+
+void LLScreenChannel::killMatchedToasts(const Matcher& matcher)
+{
+ std::list<LLToast*> to_delete = findToasts(matcher);
+ for (std::list<LLToast*>::iterator it = to_delete.begin(); it
+ != to_delete.end(); it++)
+ {
+ killToastByNotificationID((*it)-> getNotificationID());
+ }
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel)
+{
+ std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id);
+
+ if( it != mToastList.end() && panel)
+ {
+ LLToast* toast = (*it).toast;
+ LLPanel* old_panel = toast->getPanel();
+ toast->removeChild(old_panel);
+ delete old_panel;
+ toast->insertPanel(panel);
+ toast->resetTimer();
+ redrawToasts();
+ }
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::redrawToasts()
+{
+ if(mToastList.size() == 0 || isHovering())
+ return;
+
+ switch(mToastAlignment)
+ {
+ case NA_TOP :
+ showToastsTop();
+ break;
+
+ case NA_CENTRE :
+ showToastsCentre();
+ break;
+
+ case NA_BOTTOM :
+ showToastsBottom();
+ }
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::showToastsBottom()
+{
+ LLRect toast_rect;
+ S32 bottom = getRect().mBottom - gFloaterView->getRect().mBottom;
+ S32 toast_margin = 0;
+ std::vector<ToastElem>::reverse_iterator it;
+
+ LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get());
+
+ for(it = mToastList.rbegin(); it != mToastList.rend(); ++it)
+ {
+ if(it != mToastList.rbegin())
+ {
+ bottom = (*(it-1)).toast->getRect().mTop;
+ toast_margin = gSavedSettings.getS32("ToastGap");
+ }
+
+ toast_rect = (*it).toast->getRect();
+ toast_rect.setOriginAndSize(getRect().mLeft, bottom + toast_margin, toast_rect.getWidth() ,toast_rect.getHeight());
+ (*it).toast->setRect(toast_rect);
+
+ // don't show toasts if there is not enough space
+ if(floater && floater->overlapsScreenChannel())
+ {
+ LLRect world_rect = gViewerWindow->getWorldViewRectScaled();
+ if(toast_rect.mTop > world_rect.mTop)
+ {
+ break;
+ }
+ }
+
+ bool stop_showing_toasts = (*it).toast->getRect().mTop > getRect().mTop;
+
+ if(!stop_showing_toasts)
+ {
+ if( it != mToastList.rend()-1)
+ {
+ S32 toast_top = (*it).toast->getRect().mTop + gSavedSettings.getS32("ToastGap");
+ stop_showing_toasts = toast_top > getRect().mTop;
+ }
+ }
+
+ // at least one toast should be visible
+ if(it == mToastList.rbegin())
+ {
+ stop_showing_toasts = false;
+ }
+
+ if(stop_showing_toasts)
+ break;
+
+ if( !(*it).toast->getVisible() )
+ {
+ // HACK
+ // EXT-2653: it is necessary to prevent overlapping for secondary showed toasts
+ (*it).toast->setVisible(TRUE);
+ // Show toast behind floaters. (EXT-3089)
+ gFloaterView->sendChildToBack((*it).toast);
+ }
+ }
+
+ if(it != mToastList.rend())
+ {
+ mHiddenToastsNum = 0;
+ for(; it != mToastList.rend(); it++)
+ {
+ (*it).toast->stopTimer();
+ (*it).toast->setVisible(FALSE);
+ mHiddenToastsNum++;
+ }
+ }
+ else
+ {
+ closeOverflowToastPanel();
+ }
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::showToastsCentre()
+{
+ LLRect toast_rect;
+ S32 bottom = (getRect().mTop - getRect().mBottom)/2 + mToastList[0].toast->getRect().getHeight()/2;
+ std::vector<ToastElem>::reverse_iterator it;
+
+ for(it = mToastList.rbegin(); it != mToastList.rend(); ++it)
+ {
+ toast_rect = (*it).toast->getRect();
+ toast_rect.setLeftTopAndSize(getRect().mLeft - toast_rect.getWidth() / 2, bottom + toast_rect.getHeight() / 2 + gSavedSettings.getS32("ToastGap"), toast_rect.getWidth() ,toast_rect.getHeight());
+ (*it).toast->setRect(toast_rect);
+
+ (*it).toast->setVisible(TRUE);
+ }
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::showToastsTop()
+{
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::createStartUpToast(S32 notif_num, F32 timer)
+{
+ LLRect toast_rect;
+ LLRect tbox_rect;
+ LLToast::Params p;
+ p.lifetime_secs = timer;
+ p.enable_hide_btn = false;
+ mStartUpToastPanel = new LLToast(p);
+
+ if(!mStartUpToastPanel)
+ return;
+
+ mStartUpToastPanel->setOnFadeCallback(boost::bind(&LLScreenChannel::onStartUpToastHide, this));
+
+ LLTextBox* text_box = mStartUpToastPanel->getChild<LLTextBox>("toast_text");
+
+ std::string text = LLTrans::getString("StartUpNotifications");
+
+ tbox_rect = text_box->getRect();
+ S32 tbox_width = tbox_rect.getWidth();
+ S32 tbox_vpad = text_box->getVPad();
+ S32 text_width = text_box->getDefaultFont()->getWidth(text);
+ S32 text_height = text_box->getTextPixelHeight();
+
+ // EXT - 3703 (Startup toast message doesn't fit toast width)
+ // Calculating TextBox HEIGHT needed to include the whole string according to the given WIDTH of the TextBox.
+ S32 new_tbox_height = (text_width/tbox_width + 1) * text_height;
+ // Calculating TOP position of TextBox
+ S32 new_tbox_top = new_tbox_height + tbox_vpad + gSavedSettings.getS32("ToastGap");
+ // Calculating toast HEIGHT according to the new TextBox size
+ S32 toast_height = new_tbox_height + tbox_vpad * 2;
+
+ tbox_rect.setLeftTopAndSize(tbox_rect.mLeft, new_tbox_top, tbox_rect.getWidth(), new_tbox_height);
+ text_box->setRect(tbox_rect);
+
+ toast_rect = mStartUpToastPanel->getRect();
+ mStartUpToastPanel->reshape(getRect().getWidth(), toast_rect.getHeight(), true);
+ toast_rect.setLeftTopAndSize(0, toast_height + gSavedSettings.getS32("ToastGap"), getRect().getWidth(), toast_height);
+ mStartUpToastPanel->setRect(toast_rect);
+
+ text_box->setValue(text);
+ text_box->setVisible(TRUE);
+ addChild(mStartUpToastPanel);
+
+ mStartUpToastPanel->setVisible(TRUE);
+}
+
+// static --------------------------------------------------------------------------
+F32 LLScreenChannel::getHeightRatio()
+{
+ F32 ratio = gSavedSettings.getF32("NotificationChannelHeightRatio");
+ if(0.0f > ratio)
+ {
+ ratio = 0.0f;
+ }
+ else if(1.0f < ratio)
+ {
+ ratio = 1.0f;
+ }
+ return ratio;
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::updateStartUpString(S32 num)
+{
+ // *TODO: update string if notifications are arriving while the StartUp toast is on a screen
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::onStartUpToastHide()
+{
+ onCommit();
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::closeStartUpToast()
+{
+ if(mStartUpToastPanel != NULL)
+ {
+ mStartUpToastPanel->setVisible(FALSE);
+ mStartUpToastPanel = NULL;
+ }
+}
+
+void LLNotificationsUI::LLScreenChannel::stopFadingToasts()
+{
+ if (!mToastList.size()) return;
+
+ if (!mHoveredToast) return;
+
+ std::vector<ToastElem>::iterator it = mToastList.begin();
+ while (it != mToastList.end())
+ {
+ ToastElem& elem = *it;
+ elem.toast->stopFading();
+ ++it;
+ }
+}
+
+void LLNotificationsUI::LLScreenChannel::startFadingToasts()
+{
+ if (!mToastList.size()) return;
+
+ //because onMouseLeave is processed after onMouseEnter
+ if (isHovering()) return;
+
+ std::vector<ToastElem>::iterator it = mToastList.begin();
+ while (it != mToastList.end())
+ {
+ ToastElem& elem = *it;
+ elem.toast->startFading();
+ ++it;
+ }
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::hideToastsFromScreen()
+{
+ closeOverflowToastPanel();
+ for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++)
+ (*it).toast->setVisible(FALSE);
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::hideToast(const LLUUID& notification_id)
+{
+ std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), notification_id);
+ if(mToastList.end() != it)
+ {
+ ToastElem te = *it;
+ te.toast->setVisible(FALSE);
+ te.toast->stopTimer();
+ mToastList.erase(it);
+ }
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::removeToastsFromChannel()
+{
+ hideToastsFromScreen();
+ for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++)
+ {
+ deleteToast((*it).toast);
+ }
+ mToastList.clear();
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::removeAndStoreAllStorableToasts()
+{
+ if(mToastList.size() == 0)
+ return;
+
+ hideToastsFromScreen();
+ for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end();)
+ {
+ if((*it).toast->getCanBeStored())
+ {
+ storeToast(*(it));
+ it = mToastList.erase(it);
+ }
+ else
+ {
+ ++it;
+ }
+ }
+ redrawToasts();
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::removeToastsBySessionID(LLUUID id)
+{
+ if(mToastList.size() == 0)
+ return;
+
+ hideToastsFromScreen();
+ for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end();)
+ {
+ if((*it).toast->getSessionID() == id)
+ {
+ deleteToast((*it).toast);
+ it = mToastList.erase(it);
+ }
+ else
+ {
+ ++it;
+ }
+ }
+ redrawToasts();
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::onToastHover(LLToast* toast, bool mouse_enter)
+{
+ // because of LLViewerWindow::updateUI() that NOT ALWAYS calls onMouseEnter BEFORE onMouseLeave
+ // we must check hovering directly to prevent incorrect setting for hovering in a channel
+ S32 x,y;
+ if (mouse_enter)
+ {
+ toast->screenPointToLocal(gViewerWindow->getCurrentMouseX(),
+ gViewerWindow->getCurrentMouseY(), &x, &y);
+ bool hover = toast->pointInView(x, y) == TRUE;
+ if (hover)
+ {
+ mHoveredToast = toast;
+ }
+ }
+ else if (mHoveredToast != NULL)
+ {
+ mHoveredToast->screenPointToLocal(gViewerWindow->getCurrentMouseX(),
+ gViewerWindow->getCurrentMouseY(), &x, &y);
+ bool hover = mHoveredToast->pointInView(x, y) == TRUE;
+ if (!hover)
+ {
+ mHoveredToast = NULL;
+ }
+ }
+
+ if(!isHovering())
+ redrawToasts();
+}
+
+//--------------------------------------------------------------------------
+void LLScreenChannel::updateShowToastsState()
+{
+ LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get());
+
+ if(!floater)
+ {
+ setShowToasts(true);
+ return;
+ }
+
+ S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");;
+ LLRect this_rect = getRect();
+
+ // adjust channel's height
+ if(floater->overlapsScreenChannel())
+ {
+ channel_bottom += floater->getRect().getHeight();
+ if(floater->getDockControl())
+ {
+ channel_bottom += floater->getDockControl()->getTongueHeight();
+ }
+ }
+
+ if(channel_bottom != this_rect.mBottom)
+ {
+ setRect(LLRect(this_rect.mLeft, this_rect.mTop, this_rect.mRight, channel_bottom));
+ }
+}
+
+//--------------------------------------------------------------------------
+
+LLToast* LLScreenChannel::getToastByNotificationID(LLUUID id)
+{
+ std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(),
+ mStoredToastList.end(), id);
+
+ if (it == mStoredToastList.end())
+ return NULL;
+
+ return it->toast;
+}
diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h
new file mode 100644
index 0000000000..88053d87d9
--- /dev/null
+++ b/indra/newview/llscreenchannel.h
@@ -0,0 +1,289 @@
+/**
+ * @file llscreenchannel.h
+ * @brief Class implements a channel on a screen in which appropriate toasts may appear.
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSCREENCHANNEL_H
+#define LL_LLSCREENCHANNEL_H
+
+#include "lltoast.h"
+
+#include <map>
+#include <boost/shared_ptr.hpp>
+
+namespace LLNotificationsUI
+{
+
+typedef enum e_notification_toast_alignment
+{
+ NA_TOP,
+ NA_CENTRE,
+ NA_BOTTOM,
+} EToastAlignment;
+
+typedef enum e_channel_alignment
+{
+ CA_LEFT,
+ CA_CENTRE,
+ CA_RIGHT,
+} EChannelAlignment;
+
+class LLScreenChannelBase : public LLUICtrl
+{
+ friend class LLChannelManager;
+public:
+ LLScreenChannelBase(const LLUUID& id);
+ ~LLScreenChannelBase();
+
+ // Channel's outfit-functions
+ // update channel's size and position in the World View
+ virtual void updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect);
+ // initialization of channel's shape and position
+ virtual void init(S32 channel_left, S32 channel_right);
+
+
+ virtual void setToastAlignment(EToastAlignment align) {mToastAlignment = align;}
+
+ virtual void setChannelAlignment(EChannelAlignment align) {mChannelAlignment = align;}
+
+ // kill or modify a toast by its ID
+ virtual void killToastByNotificationID(LLUUID id) {};
+ virtual void modifyToastNotificationByID(LLUUID id, LLSD data) {};
+
+ // hide all toasts from screen, but not remove them from a channel
+ virtual void hideToastsFromScreen() {};
+ // removes all toasts from a channel
+ virtual void removeToastsFromChannel() {};
+
+ // show all toasts in a channel
+ virtual void redrawToasts() {};
+
+ virtual void closeOverflowToastPanel() {};
+ virtual void hideOverflowToastPanel() {};
+
+
+ // Channel's behavior-functions
+ // set whether a channel will control hovering inside itself or not
+ virtual void setControlHovering(bool control) { mControlHovering = control; }
+
+
+ bool isHovering();
+
+ void setCanStoreToasts(bool store) { mCanStoreToasts = store; }
+
+ void setDisplayToastsAlways(bool display_toasts) { mDisplayToastsAlways = display_toasts; }
+ bool getDisplayToastsAlways() { return mDisplayToastsAlways; }
+
+ // get number of hidden notifications from a channel
+ S32 getNumberOfHiddenToasts() { return mHiddenToastsNum;}
+
+
+ void setShowToasts(bool show) { mShowToasts = show; }
+ bool getShowToasts() { return mShowToasts; }
+
+ // get toast allignment preset for a channel
+ e_notification_toast_alignment getToastAlignment() {return mToastAlignment;}
+
+ // get ID of a channel
+ LLUUID getChannelID() { return mID; }
+
+protected:
+ // Channel's flags
+ bool mControlHovering;
+ LLToast* mHoveredToast;
+ bool mCanStoreToasts;
+ bool mDisplayToastsAlways;
+ // controls whether a channel shows toasts or not
+ bool mShowToasts;
+ //
+ EToastAlignment mToastAlignment;
+ EChannelAlignment mChannelAlignment;
+
+ S32 mHiddenToastsNum;
+
+ // channel's ID
+ LLUUID mID;
+
+ // store a connection to prevent futher crash that is caused by sending a signal to a destroyed channel
+ boost::signals2::connection mWorldViewRectConnection;
+};
+
+
+/**
+ * Screen channel manages toasts visibility and positioning on the screen.
+ */
+class LLScreenChannel : public LLScreenChannelBase
+{
+ friend class LLChannelManager;
+public:
+ LLScreenChannel(LLUUID& id);
+ virtual ~LLScreenChannel();
+
+ class Matcher
+ {
+ public:
+ Matcher(){}
+ virtual ~Matcher() {}
+ virtual bool matches(const LLNotificationPtr) const = 0;
+ };
+
+ std::list<LLToast*> findToasts(const Matcher& matcher);
+
+ // Channel's outfit-functions
+ // update channel's size and position in the World View
+ void updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect);
+ // initialization of channel's shape and position
+ void init(S32 channel_left, S32 channel_right);
+
+ // Operating with toasts
+ // add a toast to a channel
+ void addToast(const LLToast::Params& p);
+ // kill or modify a toast by its ID
+ void killToastByNotificationID(LLUUID id);
+ void killMatchedToasts(const Matcher& matcher);
+ void modifyToastByNotificationID(LLUUID id, LLPanel* panel);
+ // hide all toasts from screen, but not remove them from a channel
+ void hideToastsFromScreen();
+ // hide toast by notification id
+ void hideToast(const LLUUID& notification_id);
+ // removes all toasts from a channel
+ void removeToastsFromChannel();
+ // show all toasts in a channel
+ void redrawToasts();
+ //
+ void loadStoredToastsToChannel();
+ // finds a toast among stored by its Notification ID and throws it on a screen to a channel
+ void loadStoredToastByNotificationIDToChannel(LLUUID id);
+ // removes a toast from stored finding it by its Notification ID
+ void removeStoredToastByNotificationID(LLUUID id);
+ // removes from channel all toasts that belongs to the certain IM session
+ void removeToastsBySessionID(LLUUID id);
+ // remove all storable toasts from screen and store them
+ void removeAndStoreAllStorableToasts();
+ // close the StartUp Toast
+ void closeStartUpToast();
+
+
+ /** Stop fading all toasts */
+ virtual void stopFadingToasts();
+
+ /** Start fading all toasts */
+ virtual void startFadingToasts();
+
+ // get StartUp Toast's state
+ static bool getStartUpToastShown() { return mWasStartUpToastShown; }
+ // tell all channels that the StartUp toast was shown and allow them showing of toasts
+ static void setStartUpToastShown() { mWasStartUpToastShown = true; }
+ // let a channel update its ShowToast flag
+ void updateShowToastsState();
+
+
+ // Channel's other interface functions functions
+ // update number of notifications in the StartUp Toast
+ void updateStartUpString(S32 num);
+
+ LLToast* getToastByNotificationID(LLUUID id);
+
+ // Channel's signals
+ // signal on storing of faded toasts event
+ typedef boost::function<void (LLPanel* info_panel, const LLUUID id)> store_tost_callback_t;
+ typedef boost::signals2::signal<void (LLPanel* info_panel, const LLUUID id)> store_tost_signal_t;
+ store_tost_signal_t mOnStoreToast;
+ boost::signals2::connection setOnStoreToastCallback(store_tost_callback_t cb) { return mOnStoreToast.connect(cb); }
+ // signal on rejecting of a toast event
+ typedef boost::function<void (LLUUID id)> reject_tost_callback_t;
+ typedef boost::signals2::signal<void (LLUUID id)> reject_tost_signal_t;
+ reject_tost_signal_t mRejectToastSignal; boost::signals2::connection setOnRejectToastCallback(reject_tost_callback_t cb) { return mRejectToastSignal.connect(cb); }
+
+private:
+ struct ToastElem
+ {
+ LLUUID id;
+ LLToast* toast;
+
+ ToastElem(LLToast::Params p) : id(p.notif_id)
+ {
+ toast = new LLToast(p);
+ }
+
+ ToastElem(const ToastElem& toast_elem)
+ {
+ id = toast_elem.id;
+ toast = toast_elem.toast;
+ }
+
+ bool operator == (const LLUUID &id_op) const
+ {
+ return (id == id_op);
+ }
+
+ bool operator == (LLPanel* panel_op) const
+ {
+ return (toast == panel_op);
+ }
+ };
+
+ // Channel's handlers
+ void onToastHover(LLToast* toast, bool mouse_enter);
+ void onToastFade(LLToast* toast);
+ void onToastDestroyed(LLToast* toast);
+ void onStartUpToastHide();
+
+ //
+ void storeToast(ToastElem& toast_elem);
+ // send signal to observers about destroying of a toast, update channel's Hovering state, close the toast
+ void deleteToast(LLToast* toast);
+
+ // show-functions depending on allignment of toasts
+ void showToastsBottom();
+ void showToastsCentre();
+ void showToastsTop();
+
+ // create the StartUp Toast
+ void createStartUpToast(S32 notif_num, F32 timer);
+
+ /**
+ * Notification channel and World View ratio(0.0 - always show 1 notification, 1.0 - max ratio).
+ */
+ static F32 getHeightRatio();
+
+ // Channel's flags
+ static bool mWasStartUpToastShown;
+
+ // attributes for the StartUp Toast
+ LLToast* mStartUpToastPanel;
+
+
+ std::vector<ToastElem> mToastList;
+ std::vector<ToastElem> mStoredToastList;
+};
+
+}
+#endif
diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp
new file mode 100644
index 0000000000..0d9cf06bc3
--- /dev/null
+++ b/indra/newview/llscriptfloater.cpp
@@ -0,0 +1,445 @@
+/**
+ * @file llscriptfloater.cpp
+ * @brief LLScriptFloater class definition
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llscriptfloater.h"
+
+#include "llbottomtray.h"
+#include "llchannelmanager.h"
+#include "llchiclet.h"
+#include "llfloaterreg.h"
+#include "llnotifications.h"
+#include "llscreenchannel.h"
+#include "llsyswellwindow.h"
+#include "lltoastnotifypanel.h"
+#include "llviewerwindow.h"
+#include "llimfloater.h"
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLUUID notification_id_to_object_id(const LLUUID& notification_id)
+{
+ LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id);
+ if(notification)
+ {
+ return notification->getPayload()["object_id"].asUUID();
+ }
+ return LLUUID::null;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLScriptFloater::LLScriptFloater(const LLSD& key)
+: LLDockableFloater(NULL, true, key)
+, mScriptForm(NULL)
+{
+ setMouseDownCallback(boost::bind(&LLScriptFloater::onMouseDown, this));
+ setOverlapsScreenChannel(true);
+}
+
+bool LLScriptFloater::toggle(const LLUUID& object_id)
+{
+ // Force chiclet toggle on here because first onFocusReceived() will not toggle it on.
+ LLBottomTray::getInstance()->getChicletPanel()->setChicletToggleState(object_id, true);
+
+ LLUUID notification_id = LLScriptFloaterManager::getInstance()->findNotificationId(object_id);
+ LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("script_floater", notification_id);
+
+ // show existing floater
+ if(floater)
+ {
+ if(floater->getVisible())
+ {
+ floater->setVisible(false);
+ return false;
+ }
+ else
+ {
+ floater->setVisible(TRUE);
+ floater->setFocus(TRUE);
+ return true;
+ }
+ }
+ // create and show new floater
+ else
+ {
+ show(object_id);
+ return true;
+ }
+}
+
+LLScriptFloater* LLScriptFloater::show(const LLUUID& object_id)
+{
+ LLUUID notification_id = LLScriptFloaterManager::getInstance()->findNotificationId(object_id);
+
+ LLScriptFloater* floater = LLFloaterReg::showTypedInstance<LLScriptFloater>("script_floater", notification_id);
+ floater->setObjectId(object_id);
+ floater->createForm(object_id);
+
+ if (floater->getDockControl() == NULL)
+ {
+ LLChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLChiclet>(object_id);
+ if (chiclet == NULL)
+ {
+ llerror("Dock chiclet for LLScriptFloater doesn't exist", 0);
+ }
+ else
+ {
+ LLBottomTray::getInstance()->getChicletPanel()->scrollToChiclet(chiclet);
+ }
+
+ floater->setDockControl(new LLDockControl(chiclet, floater, floater->getDockTongue(),
+ LLDockControl::TOP, boost::bind(&LLScriptFloater::getAllowedRect, floater, _1)));
+ }
+
+ return floater;
+}
+
+void LLScriptFloater::getAllowedRect(LLRect& rect)
+{
+ rect = gViewerWindow->getWorldViewRectRaw();
+}
+
+void LLScriptFloater::createForm(const LLUUID& object_id)
+{
+ // delete old form
+ if(mScriptForm)
+ {
+ removeChild(mScriptForm);
+ mScriptForm->die();
+ }
+
+ LLNotificationPtr notification = LLNotifications::getInstance()->find(
+ LLScriptFloaterManager::getInstance()->findNotificationId(object_id));
+ if(NULL == notification)
+ {
+ return;
+ }
+
+ // create new form
+ mScriptForm = new LLToastNotifyPanel(notification);
+ addChild(mScriptForm);
+
+ // position form on floater
+ mScriptForm->setOrigin(0, 0);
+
+ // make floater size fit form size
+ LLRect toast_rect = getRect();
+ LLRect panel_rect = mScriptForm->getRect();
+ toast_rect.setLeftTopAndSize(toast_rect.mLeft, toast_rect.mTop, panel_rect.getWidth(), panel_rect.getHeight() + getHeaderHeight());
+ setShape(toast_rect);
+}
+
+void LLScriptFloater::onClose(bool app_quitting)
+{
+ if(getObjectId().notNull())
+ {
+ LLScriptFloaterManager::getInstance()->removeNotificationByObjectId(getObjectId());
+ }
+}
+
+void LLScriptFloater::setDocked(bool docked, bool pop_on_undock /* = true */)
+{
+ LLDockableFloater::setDocked(docked, pop_on_undock);
+
+ hideToastsIfNeeded();
+}
+
+void LLScriptFloater::setVisible(BOOL visible)
+{
+ LLDockableFloater::setVisible(visible);
+
+ hideToastsIfNeeded();
+
+ if(!visible)
+ {
+ LLIMChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(getObjectId());
+ if(chiclet)
+ {
+ chiclet->setToggleState(false);
+ }
+ }
+}
+
+void LLScriptFloater::onMouseDown()
+{
+ if(getObjectId().notNull())
+ {
+ // Remove new message icon
+ LLIMChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(getObjectId());
+ if (chiclet == NULL)
+ {
+ llerror("Dock chiclet for LLScriptFloater doesn't exist", 0);
+ }
+ else
+ {
+ chiclet->setShowNewMessagesIcon(false);
+ }
+ }
+}
+
+void LLScriptFloater::onFocusLost()
+{
+ LLBottomTray::getInstance()->getChicletPanel()->setChicletToggleState(getObjectId(), false);
+}
+
+void LLScriptFloater::onFocusReceived()
+{
+ // first focus will be received before setObjectId() call - don't toggle chiclet
+ if(getObjectId().notNull())
+ {
+ LLBottomTray::getInstance()->getChicletPanel()->setChicletToggleState(getObjectId(), true);
+ }
+}
+
+void LLScriptFloater::hideToastsIfNeeded()
+{
+ using namespace LLNotificationsUI;
+
+ // find channel
+ LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(LLChannelManager::getInstance()->findChannelByID(
+ LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
+ // update notification channel state
+ if(channel)
+ {
+ channel->updateShowToastsState();
+ channel->redrawToasts();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id)
+{
+ // get scripted Object's ID
+ LLUUID object_id = notification_id_to_object_id(notification_id);
+ if(object_id.isNull())
+ {
+ llwarns << "Invalid notification, no object id" << llendl;
+ return;
+ }
+
+ // Need to indicate of "new message" for object chiclets according to requirements
+ // specified in the Message Bar design specification. See EXT-3142.
+ bool set_new_message = false;
+
+ // If an Object spawns more-than-one floater, only the newest one is shown.
+ // The previous is automatically closed.
+ script_notification_map_t::iterator it = mNotifications.find(object_id);
+ if(it != mNotifications.end())
+ {
+ LLIMChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(object_id);
+ if(chiclet)
+ {
+ // Pass the new_message icon state further.
+ set_new_message = chiclet->getShowNewMessagesIcon();
+ }
+
+ LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("script_floater", it->second.notification_id);
+ if(floater)
+ {
+ // Generate chiclet with a "new message" indicator if a docked window was opened but not in focus. See EXT-3142.
+ set_new_message |= !floater->hasFocus();
+ }
+
+ onRemoveNotification(it->second.notification_id);
+ }
+
+ LLNotificationData nd = {notification_id};
+ mNotifications.insert(std::make_pair(object_id, nd));
+
+ // Create inventory offer chiclet for offer type notifications
+ LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id);
+ if( notification && notification->getType() == "offer" )
+ {
+ LLBottomTray::instance().getChicletPanel()->createChiclet<LLInvOfferChiclet>(object_id);
+ }
+ else
+ {
+ LLBottomTray::getInstance()->getChicletPanel()->createChiclet<LLScriptChiclet>(object_id);
+ }
+
+ LLIMWellWindow::getInstance()->addObjectRow(object_id, set_new_message);
+
+ LLSD data;
+ data["object_id"] = object_id;
+ data["new_message"] = set_new_message;
+ data["unread"] = 1; // each object has got only one floater
+ mNewObjectSignal(data);
+
+ toggleScriptFloater(object_id, set_new_message);
+}
+
+void LLScriptFloaterManager::onRemoveNotification(const LLUUID& notification_id)
+{
+ LLUUID object_id = findObjectId(notification_id);
+ if(object_id.isNull())
+ {
+ llwarns << "Invalid notification, no object id" << llendl;
+ return;
+ }
+
+ using namespace LLNotificationsUI;
+
+ // remove related toast
+ LLUUID channel_id(gSavedSettings.getString("NotificationChannelUUID"));
+ LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>
+ (LLChannelManager::getInstance()->findChannelByID(channel_id));
+ LLUUID n_toast_id = findNotificationToastId(object_id);
+ if(channel && n_toast_id.notNull())
+ {
+ channel->killToastByNotificationID(n_toast_id);
+ }
+
+ // remove related chiclet
+ LLBottomTray::getInstance()->getChicletPanel()->removeChiclet(object_id);
+
+ LLIMWellWindow::getInstance()->removeObjectRow(object_id);
+
+ // close floater
+ LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("script_floater", notification_id);
+ if(floater)
+ {
+ floater->setObjectId(LLUUID::null);
+ floater->closeFloater();
+ }
+
+ mNotifications.erase(object_id);
+}
+
+void LLScriptFloaterManager::removeNotificationByObjectId(const LLUUID& object_id)
+{
+ // Check we have not removed notification yet
+ LLNotificationPtr notification = LLNotifications::getInstance()->find(
+ findNotificationId(object_id));
+ if(notification)
+ {
+ onRemoveNotification(notification->getID());
+ }
+}
+
+void LLScriptFloaterManager::toggleScriptFloater(const LLUUID& object_id, bool set_new_message)
+{
+ // kill toast
+ using namespace LLNotificationsUI;
+ LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(LLChannelManager::getInstance()->findChannelByID(
+ LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
+ if(channel)
+ {
+ channel->killToastByNotificationID(findNotificationToastId(object_id));
+ }
+
+ LLSD data;
+ data["object_id"] = object_id;
+ data["new_message"] = set_new_message;
+ mToggleFloaterSignal(data);
+
+ // toggle floater
+ LLScriptFloater::toggle(object_id);
+}
+
+void LLScriptFloaterManager::setNotificationToastId(const LLUUID& object_id, const LLUUID& notification_id)
+{
+ script_notification_map_t::iterator it = mNotifications.find(object_id);
+ if(mNotifications.end() != it)
+ {
+ it->second.toast_notification_id = notification_id;
+ }
+}
+
+LLUUID LLScriptFloaterManager::findObjectId(const LLUUID& notification_id)
+{
+ if(notification_id.notNull())
+ {
+ script_notification_map_t::const_iterator it = mNotifications.begin();
+ for(; mNotifications.end() != it; ++it)
+ {
+ if(notification_id == it->second.notification_id)
+ {
+ return it->first;
+ }
+ }
+ }
+ return LLUUID::null;
+}
+
+LLUUID LLScriptFloaterManager::findNotificationId(const LLUUID& object_id)
+{
+ script_notification_map_t::const_iterator it = mNotifications.find(object_id);
+ if(mNotifications.end() != it)
+ {
+ return it->second.notification_id;
+ }
+ return LLUUID::null;
+}
+
+LLUUID LLScriptFloaterManager::findNotificationToastId(const LLUUID& object_id)
+{
+ script_notification_map_t::const_iterator it = mNotifications.find(object_id);
+ if(mNotifications.end() != it)
+ {
+ return it->second.toast_notification_id;
+ }
+ return LLUUID::null;
+}
+
+//static
+void LLScriptFloaterManager::onToastButtonClick(const LLSD&notification, const LLSD&response)
+{
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ LLUUID object_id = notification["payload"]["object_id"].asUUID();
+
+ switch(option)
+ {
+ case 0: // "Open"
+ LLScriptFloaterManager::getInstance()->toggleScriptFloater(object_id);
+ break;
+ case 1: // "Ignore"
+ LLScriptFloaterManager::getInstance()->removeNotificationByObjectId(object_id);
+ break;
+ case 2: // "Block"
+ LLMuteList::getInstance()->add(LLMute(object_id, notification["substitutions"]["TITLE"], LLMute::OBJECT));
+ LLScriptFloaterManager::getInstance()->removeNotificationByObjectId(object_id);
+ break;
+ default:
+ llwarns << "Unexpected value" << llendl;
+ break;
+ }
+}
+
+// EOF
diff --git a/indra/newview/llscriptfloater.h b/indra/newview/llscriptfloater.h
new file mode 100644
index 0000000000..f86605c5d1
--- /dev/null
+++ b/indra/newview/llscriptfloater.h
@@ -0,0 +1,186 @@
+/**
+ * @file llscriptfloater.h
+ * @brief LLScriptFloater class definition
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_SCRIPTFLOATER_H
+#define LL_SCRIPTFLOATER_H
+
+#include "lltransientdockablefloater.h"
+
+class LLToastNotifyPanel;
+
+/**
+ * Handles script notifications ("ScriptDialog" and "ScriptDialogGroup")
+ * and manages Script Floaters.
+ */
+class LLScriptFloaterManager : public LLSingleton<LLScriptFloaterManager>
+{
+ // *TODO
+ // LLScriptFloaterManager and LLScriptFloater will need some refactoring after we
+ // know how script notifications should look like.
+public:
+
+ /**
+ * Handles new notifications.
+ * Saves notification and object ids, removes old notification if needed, creates script chiclet
+ * Note that one object can spawn one script floater.
+ */
+ void onAddNotification(const LLUUID& notification_id);
+
+ /**
+ * Handles notification removal.
+ * Removes script notification toast, removes script chiclet, closes script floater
+ */
+ void onRemoveNotification(const LLUUID& notification_id);
+
+ /**
+ * Wrapper for onRemoveNotification, removes notification by object id.
+ */
+ void removeNotificationByObjectId(const LLUUID& object_id);
+
+ /**
+ * Toggles script floater.
+ * Removes "new message" icon from chiclet and removes notification toast.
+ */
+ void toggleScriptFloater(const LLUUID& object_id, bool set_new_message = false);
+
+ LLUUID findObjectId(const LLUUID& notification_id);
+
+ LLUUID findNotificationId(const LLUUID& object_id);
+
+ LLUUID findNotificationToastId(const LLUUID& object_id);
+
+ /**
+ * Associate notification toast id with object id.
+ */
+ void setNotificationToastId(const LLUUID& object_id, const LLUUID& notification_id);
+
+ /**
+ * Callback for notification toast buttons.
+ */
+ static void onToastButtonClick(const LLSD&notification, const LLSD&response);
+
+ typedef boost::signals2::signal<void(const LLSD&)> object_signal_t;
+
+ boost::signals2::connection addNewObjectCallback(const object_signal_t::slot_type& cb) { return mNewObjectSignal.connect(cb); }
+ boost::signals2::connection addToggleObjectFloaterCallback(const object_signal_t::slot_type& cb) { return mToggleFloaterSignal.connect(cb); }
+
+private:
+
+ struct LLNotificationData
+ {
+ LLUUID notification_id;
+ LLUUID toast_notification_id;
+ };
+
+ // <object_id, notification_data>
+ typedef std::map<LLUUID, LLNotificationData> script_notification_map_t;
+
+ script_notification_map_t mNotifications;
+
+ object_signal_t mNewObjectSignal;
+ object_signal_t mToggleFloaterSignal;
+};
+
+/**
+ * Floater script forms.
+ * LLScriptFloater will create script form based on notification data and
+ * will auto fit the form.
+ */
+class LLScriptFloater : public LLDockableFloater
+{
+public:
+
+ /**
+ * key - UUID of scripted Object
+ */
+ LLScriptFloater(const LLSD& key);
+
+ virtual ~LLScriptFloater(){};
+
+ /**
+ * Toggle existing floater or create and show a new one.
+ */
+ static bool toggle(const LLUUID& object_id);
+
+ /**
+ * Creates and shows floater
+ */
+ static LLScriptFloater* show(const LLUUID& object_id);
+
+ const LLUUID& getObjectId() { return mObjectId; }
+
+ void setObjectId(const LLUUID& id) { mObjectId = id; }
+
+ /**
+ * Close notification if script floater is closed.
+ */
+ /*virtual*/ void onClose(bool app_quitting);
+
+ /**
+ * Hide all notification toasts when we show dockable floater
+ */
+ /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true);
+
+ /**
+ * Hide all notification toasts when we show dockable floater
+ */
+ /*virtual*/ void setVisible(BOOL visible);
+
+protected:
+
+ /**
+ * Creates script form, will delete old form if floater is shown for same object.
+ */
+ void createForm(const LLUUID& object_id);
+
+ /*virtual*/ void getAllowedRect(LLRect& rect);
+
+ /**
+ * Hide all notification toasts.
+ */
+ static void hideToastsIfNeeded();
+
+ /**
+ * Removes chiclets new messages icon
+ */
+ void onMouseDown();
+
+ /*virtual*/ void onFocusLost();
+
+ /*virtual*/ void onFocusReceived();
+
+private:
+ LLToastNotifyPanel* mScriptForm;
+ LLUUID mObjectId;
+};
+
+#endif //LL_SCRIPTFLOATER_H
diff --git a/indra/newview/llscrollingpanelparam.cpp b/indra/newview/llscrollingpanelparam.cpp
new file mode 100644
index 0000000000..32a915608e
--- /dev/null
+++ b/indra/newview/llscrollingpanelparam.cpp
@@ -0,0 +1,387 @@
+/**
+ * @file llscrollingpanelparam.cpp
+ * @brief UI panel for a list of visual param panels
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llscrollingpanelparam.h"
+#include "llviewerjointmesh.h"
+#include "llviewervisualparam.h"
+#include "llwearable.h"
+#include "llviewervisualparam.h"
+#include "lltoolmorph.h"
+#include "lltrans.h"
+#include "llbutton.h"
+#include "llsliderctrl.h"
+#include "llagent.h"
+#include "llvoavatarself.h"
+
+// Constants for LLPanelVisualParam
+const F32 LLScrollingPanelParam::PARAM_STEP_TIME_THRESHOLD = 0.25f;
+
+const S32 LLScrollingPanelParam::BTN_BORDER = 2;
+const S32 LLScrollingPanelParam::PARAM_HINT_WIDTH = 128;
+const S32 LLScrollingPanelParam::PARAM_HINT_HEIGHT = 128;
+const S32 LLScrollingPanelParam::PARAM_HINT_LABEL_HEIGHT = 16;
+const S32 LLScrollingPanelParam::PARAM_PANEL_WIDTH = 2 * (3* BTN_BORDER + PARAM_HINT_WIDTH + LLPANEL_BORDER_WIDTH);
+const S32 LLScrollingPanelParam::PARAM_PANEL_HEIGHT = 2 * BTN_BORDER + PARAM_HINT_HEIGHT + PARAM_HINT_LABEL_HEIGHT + 4 * LLPANEL_BORDER_WIDTH;
+
+// LLScrollingPanelParam
+//static
+S32 LLScrollingPanelParam::sUpdateDelayFrames = 0;
+
+LLScrollingPanelParam::LLScrollingPanelParam( const LLPanel::Params& panel_params,
+ LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable )
+ : LLScrollingPanel( panel_params ),
+ mParam(param),
+ mAllowModify(allow_modify),
+ mWearable(wearable)
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_scrolling_param.xml");
+
+ static LLUICachedControl<S32> slider_ctrl_height ("UISliderctrlHeight", 0);
+ S32 pos_x = 2 * LLPANEL_BORDER_WIDTH;
+ S32 pos_y = 3 * LLPANEL_BORDER_WIDTH + slider_ctrl_height;
+ F32 min_weight = param->getMinWeight();
+ F32 max_weight = param->getMaxWeight();
+
+ mHintMin = new LLVisualParamHint( pos_x, pos_y, PARAM_HINT_WIDTH, PARAM_HINT_HEIGHT, mesh, (LLViewerVisualParam*) wearable->getVisualParam(param->getID()), min_weight);
+ pos_x += PARAM_HINT_WIDTH + 3 * BTN_BORDER;
+ mHintMax = new LLVisualParamHint( pos_x, pos_y, PARAM_HINT_WIDTH, PARAM_HINT_HEIGHT, mesh, (LLViewerVisualParam*) wearable->getVisualParam(param->getID()), max_weight );
+
+ mHintMin->setAllowsUpdates( FALSE );
+ mHintMax->setAllowsUpdates( FALSE );
+ childSetValue("param slider", weightToPercent(param->getWeight()));
+
+ std::string display_name = LLTrans::getString(param->getDisplayName());
+ childSetLabelArg("param slider", "[DESC]", display_name);
+ childSetEnabled("param slider", mAllowModify);
+ childSetCommitCallback("param slider", LLScrollingPanelParam::onSliderMoved, this);
+
+ std::string min_name = LLTrans::getString(param->getMinDisplayName());
+ std::string max_name = LLTrans::getString(param->getMaxDisplayName());
+ childSetValue("min param text", min_name);
+ childSetValue("max param text", max_name);
+
+ LLButton* less = getChild<LLButton>("less");
+ if (less)
+ {
+ less->setMouseDownCallback( LLScrollingPanelParam::onHintMinMouseDown, this );
+ less->setMouseUpCallback( LLScrollingPanelParam::onHintMinMouseUp, this );
+ less->setHeldDownCallback( LLScrollingPanelParam::onHintMinHeldDown, this );
+ less->setHeldDownDelay( PARAM_STEP_TIME_THRESHOLD );
+ }
+
+ LLButton* more = getChild<LLButton>("more");
+ if (more)
+ {
+ more->setMouseDownCallback( LLScrollingPanelParam::onHintMaxMouseDown, this );
+ more->setMouseUpCallback( LLScrollingPanelParam::onHintMaxMouseUp, this );
+ more->setHeldDownCallback( LLScrollingPanelParam::onHintMaxHeldDown, this );
+ more->setHeldDownDelay( PARAM_STEP_TIME_THRESHOLD );
+ }
+
+ setVisible(FALSE);
+ setBorderVisible( FALSE );
+}
+
+LLScrollingPanelParam::~LLScrollingPanelParam()
+{
+}
+void LLScrollingPanelParam::updatePanel(BOOL allow_modify)
+{
+ LLViewerVisualParam* param = mHintMin->getVisualParam();
+
+ if (!mWearable)
+ {
+ // not editing a wearable just now, no update necessary
+ return;
+ }
+ F32 current_weight = mWearable->getVisualParamWeight( param->getID() );
+ childSetValue("param slider", weightToPercent( current_weight ) );
+ mHintMin->requestUpdate( sUpdateDelayFrames++ );
+ mHintMax->requestUpdate( sUpdateDelayFrames++ );
+
+ mAllowModify = allow_modify;
+ childSetEnabled("param slider", mAllowModify);
+ childSetEnabled("less", mAllowModify);
+ childSetEnabled("more", mAllowModify);
+}
+
+void LLScrollingPanelParam::setVisible( BOOL visible )
+{
+ if( getVisible() != visible )
+ {
+ LLPanel::setVisible( visible );
+ mHintMin->setAllowsUpdates( visible );
+ mHintMax->setAllowsUpdates( visible );
+
+ if( visible )
+ {
+ mHintMin->setUpdateDelayFrames( sUpdateDelayFrames++ );
+ mHintMax->setUpdateDelayFrames( sUpdateDelayFrames++ );
+ }
+ }
+}
+
+void LLScrollingPanelParam::draw()
+{
+ if( !mWearable )
+ {
+ return;
+ }
+
+ childSetVisible("less", mHintMin->getVisible());
+ childSetVisible("more", mHintMax->getVisible());
+
+ // Draw all the children except for the labels
+ childSetVisible( "min param text", FALSE );
+ childSetVisible( "max param text", FALSE );
+ LLPanel::draw();
+
+ // Draw the hints over the "less" and "more" buttons.
+ glPushMatrix();
+ {
+ const LLRect& r = mHintMin->getRect();
+ F32 left = (F32)(r.mLeft + BTN_BORDER);
+ F32 bot = (F32)(r.mBottom + BTN_BORDER);
+ glTranslatef(left, bot, 0.f);
+ mHintMin->draw();
+ }
+ glPopMatrix();
+
+ glPushMatrix();
+ {
+ const LLRect& r = mHintMax->getRect();
+ F32 left = (F32)(r.mLeft + BTN_BORDER);
+ F32 bot = (F32)(r.mBottom + BTN_BORDER);
+ glTranslatef(left, bot, 0.f);
+ mHintMax->draw();
+ }
+ glPopMatrix();
+
+
+ // Draw labels on top of the buttons
+ childSetVisible( "min param text", TRUE );
+ drawChild(getChild<LLView>("min param text"), BTN_BORDER, BTN_BORDER);
+
+ childSetVisible( "max param text", TRUE );
+ drawChild(getChild<LLView>("max param text"), BTN_BORDER, BTN_BORDER);
+}
+
+// static
+void LLScrollingPanelParam::onSliderMoved(LLUICtrl* ctrl, void* userdata)
+{
+ LLSliderCtrl* slider = (LLSliderCtrl*) ctrl;
+ LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
+ LLViewerVisualParam* param = self->mParam;
+
+ F32 current_weight = self->mWearable->getVisualParamWeight( param->getID() );
+ F32 new_weight = self->percentToWeight( (F32)slider->getValue().asReal() );
+ if (current_weight != new_weight )
+ {
+ self->mWearable->setVisualParamWeight( param->getID(), new_weight, FALSE );
+ gAgent.getAvatarObject()->updateVisualParams();
+ }
+}
+
+// static
+void LLScrollingPanelParam::onSliderMouseDown(LLUICtrl* ctrl, void* userdata)
+{
+}
+
+// static
+void LLScrollingPanelParam::onSliderMouseUp(LLUICtrl* ctrl, void* userdata)
+{
+ LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
+
+ LLVisualParamHint::requestHintUpdates( self->mHintMin, self->mHintMax );
+}
+
+// static
+void LLScrollingPanelParam::onHintMinMouseDown( void* userdata )
+{
+ LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
+ self->onHintMouseDown( self->mHintMin );
+}
+
+// static
+void LLScrollingPanelParam::onHintMaxMouseDown( void* userdata )
+{
+ LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
+ self->onHintMouseDown( self->mHintMax );
+}
+
+
+void LLScrollingPanelParam::onHintMouseDown( LLVisualParamHint* hint )
+{
+ // morph towards this result
+ F32 current_weight = mWearable->getVisualParamWeight( hint->getVisualParam()->getID() );
+
+ // if we have maxed out on this morph, we shouldn't be able to click it
+ if( hint->getVisualParamWeight() != current_weight )
+ {
+ mMouseDownTimer.reset();
+ mLastHeldTime = 0.f;
+ }
+}
+
+// static
+void LLScrollingPanelParam::onHintMinHeldDown( void* userdata )
+{
+ LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
+ self->onHintHeldDown( self->mHintMin );
+}
+
+// static
+void LLScrollingPanelParam::onHintMaxHeldDown( void* userdata )
+{
+ LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
+ self->onHintHeldDown( self->mHintMax );
+}
+
+void LLScrollingPanelParam::onHintHeldDown( LLVisualParamHint* hint )
+{
+ F32 current_weight = mWearable->getVisualParamWeight( hint->getVisualParam()->getID() );
+
+ if (current_weight != hint->getVisualParamWeight() )
+ {
+ const F32 FULL_BLEND_TIME = 2.f;
+ F32 elapsed_time = mMouseDownTimer.getElapsedTimeF32() - mLastHeldTime;
+ mLastHeldTime += elapsed_time;
+
+ F32 new_weight;
+ if (current_weight > hint->getVisualParamWeight() )
+ {
+ new_weight = current_weight - (elapsed_time / FULL_BLEND_TIME);
+ }
+ else
+ {
+ new_weight = current_weight + (elapsed_time / FULL_BLEND_TIME);
+ }
+
+ // Make sure we're not taking the slider out of bounds
+ // (this is where some simple UI limits are stored)
+ F32 new_percent = weightToPercent(new_weight);
+ LLSliderCtrl* slider = getChild<LLSliderCtrl>("param slider");
+ if (slider)
+ {
+ if (slider->getMinValue() < new_percent
+ && new_percent < slider->getMaxValue())
+ {
+ mWearable->setVisualParamWeight( hint->getVisualParam()->getID(), new_weight, FALSE);
+ gAgent.getAvatarObject()->updateVisualParams();
+
+ slider->setValue( weightToPercent( new_weight ) );
+ }
+ }
+ }
+}
+
+// static
+void LLScrollingPanelParam::onHintMinMouseUp( void* userdata )
+{
+ LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
+
+ F32 elapsed_time = self->mMouseDownTimer.getElapsedTimeF32();
+
+ LLVisualParamHint* hint = self->mHintMin;
+
+ if (elapsed_time < PARAM_STEP_TIME_THRESHOLD)
+ {
+ // step in direction
+ F32 current_weight = self->mWearable->getVisualParamWeight( hint->getVisualParam()->getID() );
+ F32 range = self->mHintMax->getVisualParamWeight() - self->mHintMin->getVisualParamWeight();
+ // step a fraction in the negative directiona
+ F32 new_weight = current_weight - (range / 10.f);
+ F32 new_percent = self->weightToPercent(new_weight);
+ LLSliderCtrl* slider = self->getChild<LLSliderCtrl>("param slider");
+ if (slider)
+ {
+ if (slider->getMinValue() < new_percent
+ && new_percent < slider->getMaxValue())
+ {
+ self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight, FALSE);
+ slider->setValue( self->weightToPercent( new_weight ) );
+ }
+ }
+ }
+
+ LLVisualParamHint::requestHintUpdates( self->mHintMin, self->mHintMax );
+}
+
+void LLScrollingPanelParam::onHintMaxMouseUp( void* userdata )
+{
+ LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
+
+ F32 elapsed_time = self->mMouseDownTimer.getElapsedTimeF32();
+
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if (avatar)
+ {
+ LLVisualParamHint* hint = self->mHintMax;
+
+ if (elapsed_time < PARAM_STEP_TIME_THRESHOLD)
+ {
+ // step in direction
+ F32 current_weight = self->mWearable->getVisualParamWeight( hint->getVisualParam()->getID() );
+ F32 range = self->mHintMax->getVisualParamWeight() - self->mHintMin->getVisualParamWeight();
+ // step a fraction in the negative direction
+ F32 new_weight = current_weight + (range / 10.f);
+ F32 new_percent = self->weightToPercent(new_weight);
+ LLSliderCtrl* slider = self->getChild<LLSliderCtrl>("param slider");
+ if (slider)
+ {
+ if (slider->getMinValue() < new_percent
+ && new_percent < slider->getMaxValue())
+ {
+ self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight, FALSE);
+ slider->setValue( self->weightToPercent( new_weight ) );
+ }
+ }
+ }
+ }
+
+ LLVisualParamHint::requestHintUpdates( self->mHintMin, self->mHintMax );
+}
+
+
+F32 LLScrollingPanelParam::weightToPercent( F32 weight )
+{
+ LLViewerVisualParam* param = mParam;
+ return (weight - param->getMinWeight()) / (param->getMaxWeight() - param->getMinWeight()) * 100.f;
+}
+
+F32 LLScrollingPanelParam::percentToWeight( F32 percent )
+{
+ LLViewerVisualParam* param = mParam;
+ return percent / 100.f * (param->getMaxWeight() - param->getMinWeight()) + param->getMinWeight();
+}
diff --git a/indra/newview/llscrollingpanelparam.h b/indra/newview/llscrollingpanelparam.h
new file mode 100644
index 0000000000..8c5db64816
--- /dev/null
+++ b/indra/newview/llscrollingpanelparam.h
@@ -0,0 +1,100 @@
+/**
+ * @file llscrollingpanelparam.h
+ * @brief the scrolling panel containing a list of visual param
+ * panels
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_SCROLLINGPANELPARAM_H
+#define LL_SCROLLINGPANELPARAM_H
+
+#include "llpanel.h"
+#include "llscrollingpanellist.h"
+
+class LLViewerJointMesh;
+class LLViewerVisualParam;
+class LLWearable;
+class LLVisualParamHint;
+class LLViewerVisualParam;
+
+class LLScrollingPanelParam : public LLScrollingPanel
+{
+public:
+ LLScrollingPanelParam( const LLPanel::Params& panel_params,
+ LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable );
+ virtual ~LLScrollingPanelParam();
+
+ virtual void draw();
+ virtual void setVisible( BOOL visible );
+ virtual void updatePanel(BOOL allow_modify);
+
+ static void onSliderMouseDown(LLUICtrl* ctrl, void* userdata);
+ static void onSliderMoved(LLUICtrl* ctrl, void* userdata);
+ static void onSliderMouseUp(LLUICtrl* ctrl, void* userdata);
+
+ static void onHintMinMouseDown(void* userdata);
+ static void onHintMinHeldDown(void* userdata);
+ static void onHintMaxMouseDown(void* userdata);
+ static void onHintMaxHeldDown(void* userdata);
+ static void onHintMinMouseUp(void* userdata);
+ static void onHintMaxMouseUp(void* userdata);
+
+ void onHintMouseDown( LLVisualParamHint* hint );
+ void onHintHeldDown( LLVisualParamHint* hint );
+
+ F32 weightToPercent( F32 weight );
+ F32 percentToWeight( F32 percent );
+
+public:
+ // Constants for LLPanelVisualParam
+ const static F32 PARAM_STEP_TIME_THRESHOLD;
+
+ const static S32 BTN_BORDER;
+ const static S32 PARAM_HINT_WIDTH;
+ const static S32 PARAM_HINT_HEIGHT;
+ const static S32 PARAM_HINT_LABEL_HEIGHT;
+ const static S32 PARAM_PANEL_WIDTH;
+ const static S32 PARAM_PANEL_HEIGHT;
+
+
+public:
+ LLViewerVisualParam* mParam;
+ LLPointer<LLVisualParamHint> mHintMin;
+ LLPointer<LLVisualParamHint> mHintMax;
+ static S32 sUpdateDelayFrames;
+
+protected:
+ LLTimer mMouseDownTimer; // timer for how long mouse has been held down on a hint.
+ F32 mLastHeldTime;
+
+ BOOL mAllowModify;
+ LLWearable *mWearable;
+};
+
+#endif
diff --git a/indra/newview/llsearchcombobox.cpp b/indra/newview/llsearchcombobox.cpp
new file mode 100644
index 0000000000..93a70b6471
--- /dev/null
+++ b/indra/newview/llsearchcombobox.cpp
@@ -0,0 +1,266 @@
+/**
+ * @file llsearchcombobox.cpp
+ * @brief Search Combobox implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llsearchcombobox.h"
+
+#include "llkeyboard.h"
+#include "lltrans.h" // for LLTrans::getString()
+#include "lluictrlfactory.h"
+
+static LLDefaultChildRegistry::Register<LLSearchComboBox> r1("search_combo_box");
+
+class LLSearchHistoryBuilder
+{
+public:
+ LLSearchHistoryBuilder(LLSearchComboBox* combo_box, const std::string& filter);
+
+ virtual void buildSearchHistory();
+
+ virtual ~LLSearchHistoryBuilder(){}
+
+protected:
+
+ virtual bool filterSearchHistory();
+
+ LLSearchComboBox* mComboBox;
+ std::string mFilter;
+ LLSearchHistory::search_history_list_t mFilteredSearchHistory;
+};
+
+LLSearchComboBox::Params::Params()
+: search_button("search_button")
+, dropdown_button_visible("dropdown_button_visible", false)
+{
+}
+
+LLSearchComboBox::LLSearchComboBox(const Params&p)
+: LLComboBox(p)
+{
+ S32 btn_top = p.search_button.top_pad + p.search_button.rect.height;
+ S32 btn_right = p.search_button.rect.width + p.search_button.left_pad;
+ LLRect search_btn_rect(p.search_button.left_pad, btn_top, btn_right, p.search_button.top_pad);
+
+ LLButton::Params button_params(p.search_button);
+ button_params.name(std::string("search_btn"));
+ button_params.rect(search_btn_rect) ;
+ button_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_TOP);
+ button_params.tab_stop(false);
+ button_params.click_callback.function(boost::bind(&LLSearchComboBox::onSelectionCommit, this));
+ mSearchButton = LLUICtrlFactory::create<LLButton>(button_params);
+ mTextEntry->addChild(mSearchButton);
+
+ setButtonVisible(p.dropdown_button_visible);
+ mTextEntry->setCommitCallback(boost::bind(&LLComboBox::onTextCommit, this, _2));
+ mTextEntry->setKeystrokeCallback(boost::bind(&LLComboBox::onTextEntry, this, _1), NULL);
+ setCommitCallback(boost::bind(&LLSearchComboBox::onSelectionCommit, this));
+ setPrearrangeCallback(boost::bind(&LLSearchComboBox::onSearchPrearrange, this, _2));
+ mSearchButton->setCommitCallback(boost::bind(&LLSearchComboBox::onTextCommit, this, _2));
+}
+
+void LLSearchComboBox::rebuildSearchHistory(const std::string& filter)
+{
+ LLSearchHistoryBuilder builder(this, filter);
+ builder.buildSearchHistory();
+}
+
+void LLSearchComboBox::onSearchPrearrange(const LLSD& data)
+{
+ std::string filter = data.asString();
+ rebuildSearchHistory(filter);
+
+ mList->mouseOverHighlightNthItem(-1); // Clear highlight on the last selected item.
+}
+
+void LLSearchComboBox::onTextEntry(LLLineEditor* line_editor)
+{
+ KEY key = gKeyboard->currentKey();
+
+ if (line_editor->getText().empty())
+ {
+ prearrangeList(); // resets filter
+ hideList();
+ }
+ // Typing? (moving cursor should not affect showing the list)
+ else if (key != KEY_LEFT && key != KEY_RIGHT && key != KEY_HOME && key != KEY_END)
+ {
+ prearrangeList(line_editor->getText());
+ if (mList->getItemCount() != 0)
+ {
+ showList();
+ focusTextEntry();
+ }
+ else
+ {
+ // Hide the list if it's empty.
+ hideList();
+ }
+ }
+ LLComboBox::onTextEntry(line_editor);
+}
+
+void LLSearchComboBox::focusTextEntry()
+{
+ // We can't use "mTextEntry->setFocus(TRUE)" instead because
+ // if the "select_on_focus" parameter is true it places the cursor
+ // at the beginning (after selecting text), thus screwing up updateSelection().
+ if (mTextEntry)
+ {
+ gFocusMgr.setKeyboardFocus(mTextEntry);
+ }
+}
+
+void LLSearchComboBox::hideList()
+{
+ LLComboBox::hideList();
+ if (mTextEntry && hasFocus())
+ focusTextEntry();
+}
+
+LLSearchComboBox::~LLSearchComboBox()
+{
+}
+
+void LLSearchComboBox::onSelectionCommit()
+{
+ std::string search_query = getSimple();
+ LLStringUtil::trim(search_query);
+
+ // Order of add() and mTextEntry->setText does matter because add() will select first item
+ // in drop down list and its label will be copied to text box rewriting mTextEntry->setText() call
+ if(!search_query.empty())
+ {
+ remove(search_query);
+ add(search_query, ADD_TOP);
+ }
+
+ mTextEntry->setText(search_query);
+ setControlValue(search_query);
+}
+
+BOOL LLSearchComboBox::remove(const std::string& name)
+{
+ BOOL found = mList->selectItemByLabel(name, FALSE);
+
+ if (found)
+ {
+ LLScrollListItem* item = mList->getFirstSelected();
+ if (item)
+ {
+ LLComboBox::remove(mList->getItemIndex(item));
+ }
+ }
+
+ return found;
+}
+
+void LLSearchComboBox::clearHistory()
+{
+ removeall();
+ setTextEntry(LLStringUtil::null);
+}
+
+BOOL LLSearchComboBox::handleKeyHere(KEY key,MASK mask )
+{
+ if(mTextEntry->hasFocus() && MASK_NONE == mask && KEY_DOWN == key)
+ {
+ S32 first = 0;
+ S32 size = 0;
+
+ // get entered text (without auto-complete part)
+ mTextEntry->getSelectionRange(&first, &size);
+ std::string search_query = mTextEntry->getText();
+ search_query.erase(first, size);
+
+ onSearchPrearrange(search_query);
+ }
+ return LLComboBox::handleKeyHere(key, mask);
+}
+
+LLSearchHistoryBuilder::LLSearchHistoryBuilder(LLSearchComboBox* combo_box, const std::string& filter)
+: mComboBox(combo_box)
+, mFilter(filter)
+{
+}
+
+bool LLSearchHistoryBuilder::filterSearchHistory()
+{
+ // *TODO: an STL algorithm would look nicer
+ mFilteredSearchHistory.clear();
+
+ std::string filter_copy = mFilter;
+ LLStringUtil::toLower(filter_copy);
+
+ LLSearchHistory::search_history_list_t history =
+ LLSearchHistory::getInstance()->getSearchHistoryList();
+
+ LLSearchHistory::search_history_list_t::const_iterator it = history.begin();
+ for ( ; it != history.end(); ++it)
+ {
+ std::string search_query = (*it).search_query;
+ LLStringUtil::toLower(search_query);
+
+ if (search_query.find(filter_copy) != std::string::npos)
+ mFilteredSearchHistory.push_back(*it);
+ }
+
+ return mFilteredSearchHistory.size();
+}
+
+void LLSearchHistoryBuilder::buildSearchHistory()
+{
+ mFilteredSearchHistory.clear();
+
+ LLSearchHistory::search_history_list_t filtered_items;
+ LLSearchHistory::search_history_list_t* itemsp = NULL;
+ LLSearchHistory* sh = LLSearchHistory::getInstance();
+
+ if (mFilter.empty())
+ {
+ itemsp = &sh->getSearchHistoryList();
+ }
+ else
+ {
+ filterSearchHistory();
+ itemsp = &mFilteredSearchHistory;
+ itemsp->sort();
+ }
+
+ mComboBox->removeall();
+
+ LLSearchHistory::search_history_list_t::const_iterator it = itemsp->begin();
+ for ( ; it != itemsp->end(); it++)
+ {
+ LLSearchHistory::LLSearchHistoryItem item = *it;
+ mComboBox->add(item.search_query);
+ }
+}
diff --git a/indra/newview/llsearchcombobox.h b/indra/newview/llsearchcombobox.h
new file mode 100644
index 0000000000..c23ebc8923
--- /dev/null
+++ b/indra/newview/llsearchcombobox.h
@@ -0,0 +1,110 @@
+/**
+ * @file llsearchcombobox.h
+ * @brief LLSearchComboBox class definition
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSEARCHCOMBOBOX_H
+#define LL_LLSEARCHCOMBOBOX_H
+
+#include "llcombobox.h"
+#include "llsearchhistory.h"
+
+/**
+ * Search control with text box for search queries and a drop down list
+ * with recent queries. Supports text auto-complete and filtering of drop down list
+ * according to typed text.
+ */
+class LLSearchComboBox : public LLComboBox
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLComboBox::Params>
+ {
+ Optional<LLButton::Params> search_button;
+ Optional<bool> dropdown_button_visible;
+
+ Params();
+ };
+
+ /**
+ * Removes an entry from combo box, case insensitive
+ */
+ BOOL remove(const std::string& name);
+
+ /**
+ * Clears search history
+ */
+ void clearHistory();
+
+ /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
+
+ ~LLSearchComboBox();
+
+protected:
+
+ LLSearchComboBox(const Params&p);
+ friend class LLUICtrlFactory;
+
+ /**
+ * Handles typing in text box
+ */
+ void onTextEntry(LLLineEditor* line_editor);
+
+ /**
+ * Hides drop down list and focuses text box
+ */
+ void hideList();
+
+ /**
+ * Rebuilds search history, case insensitive
+ * If filter is an empty string - whole history will be added to combo box
+ * if filter is valid string - only matching entries will be added
+ */
+ virtual void rebuildSearchHistory(const std::string& filter);
+
+ /**
+ * Callback for prearrange event
+ */
+ void onSearchPrearrange(const LLSD& data);
+
+ /**
+ * Callback for text box or combo box commit
+ */
+ void onSelectionCommit();
+
+ /**
+ * Sets focus to text box
+ */
+ void focusTextEntry();
+
+ LLButton* mSearchButton;
+};
+
+#endif //LL_LLSEARCHCOMBOBOX_H
diff --git a/indra/newview/llsearchhistory.cpp b/indra/newview/llsearchhistory.cpp
new file mode 100644
index 0000000000..d45a1efa0e
--- /dev/null
+++ b/indra/newview/llsearchhistory.cpp
@@ -0,0 +1,154 @@
+/**
+ * @file llsearchhistory.cpp
+ * @brief Search history container implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llsearchhistory.h"
+
+#include "llfile.h"
+#include "llsdserialize.h"
+#include "llxmlnode.h"
+
+std::string LLSearchHistory::SEARCH_QUERY = "search_query";
+std::string LLSearchHistory::SEARCH_HISTORY_FILE_NAME = "search_history.txt";
+
+LLSearchHistory::LLSearchHistory()
+{
+
+}
+
+bool LLSearchHistory::load()
+{
+ // build filename for each user
+ std::string resolved_filename = getHistoryFilePath();
+ llifstream file(resolved_filename);
+ if (!file.is_open())
+ {
+ return false;
+ }
+
+ clearHistory();
+
+ // add each line in the file to the list
+ std::string line;
+ LLPointer<LLSDParser> parser = new LLSDNotationParser();
+ while (std::getline(file, line))
+ {
+ LLSD s_item;
+ std::istringstream iss(line);
+ if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE)
+ {
+ break;
+ }
+
+ mSearchHistory.push_back(s_item);
+ }
+
+ file.close();
+
+ return true;
+}
+
+bool LLSearchHistory::save()
+{
+ // build filename for each user
+ std::string resolved_filename = getHistoryFilePath();
+ // open a file for writing
+ llofstream file (resolved_filename);
+ if (!file.is_open())
+ {
+ return false;
+ }
+
+ search_history_list_t::const_iterator it = mSearchHistory.begin();
+ for (; mSearchHistory.end() != it; ++it)
+ {
+ file << LLSDOStreamer<LLSDNotationFormatter>((*it).toLLSD()) << std::endl;
+ }
+
+ file.close();
+ return true;
+}
+
+std::string LLSearchHistory::getHistoryFilePath()
+{
+ return gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SEARCH_HISTORY_FILE_NAME);
+}
+
+void LLSearchHistory::addEntry(const std::string& search_query)
+{
+ if(search_query.empty())
+ {
+ return;
+ }
+
+ search_history_list_t::iterator it =
+ find(mSearchHistory.begin(), mSearchHistory.end(), search_query);
+
+ if(mSearchHistory.end() != it)
+ {
+ mSearchHistory.erase(it);
+ }
+
+ LLSearchHistoryItem item(search_query);
+ mSearchHistory.push_front(item);
+}
+
+bool LLSearchHistory::LLSearchHistoryItem::operator < (const LLSearchHistory::LLSearchHistoryItem& right)
+{
+ S32 result = LLStringUtil::compareInsensitive(search_query, right.search_query);
+
+ return result < 0;
+}
+
+bool LLSearchHistory::LLSearchHistoryItem::operator > (const LLSearchHistory::LLSearchHistoryItem& right)
+{
+ S32 result = LLStringUtil::compareInsensitive(search_query, right.search_query);
+
+ return result > 0;
+}
+
+bool LLSearchHistory::LLSearchHistoryItem::operator==(const LLSearchHistory::LLSearchHistoryItem& right)
+{
+ return 0 == LLStringUtil::compareInsensitive(search_query, right.search_query);
+}
+
+bool LLSearchHistory::LLSearchHistoryItem::operator==(const std::string& right)
+{
+ return 0 == LLStringUtil::compareInsensitive(search_query, right);
+}
+
+LLSD LLSearchHistory::LLSearchHistoryItem::toLLSD() const
+{
+ LLSD ret;
+ ret[SEARCH_QUERY] = search_query;
+ return ret;
+}
diff --git a/indra/newview/llsearchhistory.h b/indra/newview/llsearchhistory.h
new file mode 100644
index 0000000000..eb6efdb86f
--- /dev/null
+++ b/indra/newview/llsearchhistory.h
@@ -0,0 +1,147 @@
+/**
+ * @file llsearchhistory.h
+ * @brief Search history container definition
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSEARCHHISTORY_H
+#define LL_LLSEARCHHISTORY_H
+
+#include "llsingleton.h"
+#include "llui.h"
+
+/**
+ * Search history container able to save and load history from file.
+ * History is stored in chronological order, most recent at the beginning.
+ */
+class LLSearchHistory : public LLSingleton<LLSearchHistory>, private LLDestroyClass<LLSearchHistory>
+{
+ friend class LLDestroyClass<LLSearchHistory>;
+public:
+
+ // Forward declaration
+ class LLSearchHistoryItem;
+
+ // Search history container
+ typedef std::list<LLSearchHistoryItem> search_history_list_t;
+
+ /**
+ * Saves search history to file
+ */
+ bool save();
+
+ /**
+ * loads search history from file
+ */
+ bool load();
+
+ /**
+ * Returns search history list
+ */
+ search_history_list_t& getSearchHistoryList() { return mSearchHistory; }
+
+ /**
+ * Deletes all search history queries from list.
+ */
+ void clearHistory() { mSearchHistory.clear(); }
+
+ /**
+ * Adds unique entry to front of search history list, case insensitive
+ * If entry is already in list, it will be deleted and added to front.
+ */
+ void addEntry(const std::string& search_text);
+
+ LLSearchHistory();
+
+ /**
+ * Class for storing data about single search request.
+ */
+ class LLSearchHistoryItem
+ {
+ public:
+
+ LLSearchHistoryItem()
+ {}
+
+ LLSearchHistoryItem(const std::string& query)
+ : search_query(query)
+ {}
+
+ LLSearchHistoryItem(const LLSD& item)
+ {
+ if(item.has(SEARCH_QUERY))
+ search_query = item[SEARCH_QUERY].asString();
+ }
+
+ std::string search_query;
+
+ /**
+ * Allows std::list sorting
+ */
+ bool operator < (const LLSearchHistory::LLSearchHistoryItem& right);
+
+ /**
+ * Allows std::list sorting
+ */
+ bool operator > (const LLSearchHistory::LLSearchHistoryItem& right);
+
+ bool operator==(const LLSearchHistoryItem& right);
+
+ bool operator==(const std::string& right);
+
+ /**
+ * Serializes search history item to LLSD
+ */
+ LLSD toLLSD() const;
+ };
+
+protected:
+
+ /**
+ * Returns path to search history file.
+ */
+ std::string getHistoryFilePath();
+
+ static std::string SEARCH_HISTORY_FILE_NAME;
+ static std::string SEARCH_QUERY;
+
+private:
+
+ // Implementation of LLDestroyClass<LLSearchHistory>
+ static void destroyClass()
+ {
+ LLSearchHistory::getInstance()->save();
+ }
+
+ search_history_list_t mSearchHistory;
+};
+
+class LLSearchComboBox;
+
+#endif //LL_LLSEARCHHISTORY_H
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 0c6b2980dc..60a095506b 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -33,6 +33,7 @@
#include "llviewerprecompiledheaders.h"
// file include
+#define LLSELECTMGR_CPP
#include "llselectmgr.h"
// library includes
@@ -41,8 +42,10 @@
#include "lleconomy.h"
#include "llgl.h"
#include "llrender.h"
+#include "llnotifications.h"
#include "llpermissions.h"
#include "llpermissionsflags.h"
+#include "lltrans.h"
#include "llundo.h"
#include "lluuid.h"
#include "llvolume.h"
@@ -57,13 +60,17 @@
#include "llfloaterinspect.h"
#include "llfloaterproperties.h"
#include "llfloaterreporter.h"
+#include "llfloaterreg.h"
#include "llfloatertools.h"
#include "llframetimer.h"
+#include "llfocusmgr.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
#include "llinventorymodel.h"
#include "llmenugl.h"
#include "llmutelist.h"
+#include "llsidepaneltaskinfo.h"
+#include "llslurl.h"
#include "llstatusbar.h"
#include "llsurface.h"
#include "lltool.h"
@@ -73,13 +80,15 @@
#include "llui.h"
#include "llviewercamera.h"
#include "llviewercontrol.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
+#include "llviewermedia.h"
+#include "llviewermediafocus.h"
#include "llviewermenu.h"
#include "llviewerobject.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "llviewerstats.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "llvovolume.h"
#include "pipeline.h"
@@ -95,15 +104,16 @@ const F32 SILHOUETTE_UPDATE_THRESHOLD_SQUARED = 0.02f;
const S32 MAX_ACTION_QUEUE_SIZE = 20;
const S32 MAX_SILS_PER_FRAME = 50;
const S32 MAX_OBJECTS_PER_PACKET = 254;
+const S32 TE_SELECT_MASK_ALL = 0xFFFFFFFF;
//
// Globals
//
-BOOL gDebugSelectMgr = FALSE;
+//BOOL gDebugSelectMgr = FALSE;
-BOOL gHideSelectedObjects = FALSE;
-BOOL gAllowSelectAvatar = FALSE;
+//BOOL gHideSelectedObjects = FALSE;
+//BOOL gAllowSelectAvatar = FALSE;
BOOL LLSelectMgr::sRectSelectInclusive = TRUE;
BOOL LLSelectMgr::sRenderHiddenSelections = TRUE;
@@ -167,11 +177,16 @@ LLObjectSelection *get_null_object_selection()
return sNullSelection;
}
+// Build time optimization, generate this function once here
+template class LLSelectMgr* LLSingleton<class LLSelectMgr>::getInstance();
//-----------------------------------------------------------------------------
// LLSelectMgr()
//-----------------------------------------------------------------------------
LLSelectMgr::LLSelectMgr()
+ : mHideSelectedObjects(LLCachedControl<bool>(gSavedSettings, "HideSelectedObjects", FALSE)),
+ mAllowSelectAvatar( LLCachedControl<bool>(gSavedSettings, "AllowSelectAvatar", FALSE)),
+ mDebugSelectMgr(LLCachedControl<bool>(gSavedSettings, "DebugSelectMgr", FALSE))
{
mTEMode = FALSE;
mLastCameraPos.clearVec();
@@ -184,12 +199,12 @@ LLSelectMgr::LLSelectMgr()
sHighlightUAnim = gSavedSettings.getF32("SelectionHighlightUAnim");
sHighlightVAnim = gSavedSettings.getF32("SelectionHighlightVAnim");
- sSilhouetteParentColor = gColors.getColor("SilhouetteParentColor");
- sSilhouetteChildColor = gColors.getColor("SilhouetteChildColor");
- sHighlightParentColor = gColors.getColor("HighlightParentColor");
- sHighlightChildColor = gColors.getColor("HighlightChildColor");
- sHighlightInspectColor = gColors.getColor("HighlightInspectColor");
- sContextSilhouetteColor = gColors.getColor("ContextSilhouetteColor")*0.5f;
+ sSilhouetteParentColor =LLUIColorTable::instance().getColor("SilhouetteParentColor");
+ sSilhouetteChildColor = LLUIColorTable::instance().getColor("SilhouetteChildColor");
+ sHighlightParentColor = LLUIColorTable::instance().getColor("HighlightParentColor");
+ sHighlightChildColor = LLUIColorTable::instance().getColor("HighlightChildColor");
+ sHighlightInspectColor = LLUIColorTable::instance().getColor("HighlightInspectColor");
+ sContextSilhouetteColor = LLUIColorTable::instance().getColor("ContextSilhouetteColor")*0.5f;
sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius");
@@ -202,6 +217,8 @@ LLSelectMgr::LLSelectMgr()
mSelectedObjects = new LLObjectSelection();
mHoverObjects = new LLObjectSelection();
mHighlightedObjects = new LLObjectSelection();
+
+
}
@@ -384,7 +401,7 @@ LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj,
}
// Collect all of the objects
- LLDynamicArray<LLViewerObject*> objects;
+ std::vector<LLViewerObject*> objects;
root->addThisAndNonJointChildren(objects);
addAsFamily(objects, add_to_end);
@@ -430,7 +447,7 @@ LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(const std::vector<LLV
BOOL send_to_sim)
{
// Collect all of the objects, children included
- LLDynamicArray<LLViewerObject*> objects;
+ std::vector<LLViewerObject*> objects;
//clear primary object (no primary object)
mSelectedObjects->mPrimaryObject = NULL;
@@ -534,7 +551,7 @@ BOOL LLSelectMgr::removeObjectFromSelections(const LLUUID &id)
object_found = TRUE;
break; // must break here, may have removed multiple objects from list
}
- else if (object->isAvatar())
+ else if (object->isAvatar() && object->getParent() && ((LLViewerObject*)object->getParent())->mID == id)
{
// It's possible the item being removed has an avatar sitting on it
// So remove the avatar that is sitting on the object.
@@ -554,7 +571,7 @@ void LLSelectMgr::deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_s
if(!object->isSelected()) return;
// Collect all of the objects, and remove them
- LLDynamicArray<LLViewerObject*> objects;
+ std::vector<LLViewerObject*> objects;
if (include_entire_object)
{
@@ -673,7 +690,7 @@ void LLSelectMgr::addAsFamily(std::vector<LLViewerObject*>& objects, BOOL add_to
// Can't select yourself
if (objectp->mID == gAgentID
- && !gAllowSelectAvatar)
+ && !LLSelectMgr::getInstance()->mAllowSelectAvatar)
{
continue;
}
@@ -768,48 +785,66 @@ void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoab
}
-LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp)
+LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp, S32 face)
{
- // Always blitz hover list when setting
- mHoverObjects->deleteAllNodes();
-
if (!objectp)
{
+ mHoverObjects->deleteAllNodes();
return NULL;
}
// Can't select yourself
if (objectp->mID == gAgentID)
{
+ mHoverObjects->deleteAllNodes();
return NULL;
}
// Can't select land
if (objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH)
{
+ mHoverObjects->deleteAllNodes();
return NULL;
}
- // Collect all of the objects
- LLDynamicArray<LLViewerObject*> objects;
+ mHoverObjects->mPrimaryObject = objectp;
+
objectp = objectp->getRootEdit();
- objectp->addThisAndNonJointChildren(objects);
- for (std::vector<LLViewerObject*>::iterator iter = objects.begin();
- iter != objects.end(); ++iter)
+ // is the requested object the same as the existing hover object root?
+ // NOTE: there is only ever one linked set in mHoverObjects
+ if (mHoverObjects->getFirstRootObject() != objectp)
{
- LLViewerObject* cur_objectp = *iter;
- LLSelectNode* nodep = new LLSelectNode(cur_objectp, FALSE);
- mHoverObjects->addNodeAtEnd(nodep);
+
+ // Collect all of the objects
+ std::vector<LLViewerObject*> objects;
+ objectp = objectp->getRootEdit();
+ objectp->addThisAndNonJointChildren(objects);
+
+ mHoverObjects->deleteAllNodes();
+ for (std::vector<LLViewerObject*>::iterator iter = objects.begin();
+ iter != objects.end(); ++iter)
+ {
+ LLViewerObject* cur_objectp = *iter;
+ LLSelectNode* nodep = new LLSelectNode(cur_objectp, FALSE);
+ nodep->selectTE(face, TRUE);
+ mHoverObjects->addNodeAtEnd(nodep);
+ }
+
+ requestObjectPropertiesFamily(objectp);
}
- requestObjectPropertiesFamily(objectp);
return mHoverObjects;
}
LLSelectNode *LLSelectMgr::getHoverNode()
{
- return getHoverObjects()->getFirstRootNode();
+ return mHoverObjects->getFirstRootNode();
+}
+
+LLSelectNode *LLSelectMgr::getPrimaryHoverNode()
+{
+ return mHoverObjects->mSelectNodeMap[mHoverObjects->mPrimaryObject];
}
void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp)
@@ -824,8 +859,8 @@ void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp)
return;
}
- if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner()) ||
- (gSavedSettings.getBOOL("SelectMovableOnly") && !objectp->permMove()))
+ if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner())
+ || (gSavedSettings.getBOOL("SelectMovableOnly") && !objectp->permMove()))
{
// only select my own objects
return;
@@ -1276,7 +1311,7 @@ void LLSelectMgr::promoteSelectionToRoot()
//-----------------------------------------------------------------------------
void LLSelectMgr::demoteSelectionToIndividuals()
{
- LLDynamicArray<LLViewerObject*> objects;
+ std::vector<LLViewerObject*> objects;
for (LLObjectSelection::root_iterator iter = getSelection()->root_begin();
iter != getSelection()->root_end(); iter++)
@@ -1285,7 +1320,7 @@ void LLSelectMgr::demoteSelectionToIndividuals()
object->addThisAndNonJointChildren(objects);
}
- if (objects.getLength())
+ if (!objects.empty())
{
deselectAll();
for (std::vector<LLViewerObject*>::iterator iter = objects.begin();
@@ -1419,7 +1454,7 @@ void LLSelectMgr::selectionSetImage(const LLUUID& imageid)
// Texture picker defaults aren't inventory items
// * Don't need to worry about permissions for them
// * Can just apply the texture and be done with it.
- objectp->setTEImage(te, gImageList.getImage(mImageID, TRUE, FALSE));
+ objectp->setTEImage(te, LLViewerTextureManager::getFetchedTexture(mImageID, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
}
return true;
}
@@ -1575,7 +1610,7 @@ BOOL LLSelectMgr::selectionRevertTextures()
}
else
{
- object->setTEImage(te, gImageList.getImage(id));
+ object->setTEImage(te, LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
}
}
}
@@ -1703,13 +1738,8 @@ void LLSelectMgr::selectionSetFullbright(U8 fullbright)
getSelection()->applyToObjects(&sendfunc);
}
-void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string& media_url)
+void LLSelectMgr::selectionSetMedia(U8 media_type)
{
- U8 media_flags = LLTextureEntry::MF_NONE;
- if (media_type == LLViewerObject::MEDIA_TYPE_WEB_PAGE)
- {
- media_flags = LLTextureEntry::MF_WEB_PAGE;
- }
struct f : public LLSelectedTEFunctor
{
@@ -1719,33 +1749,72 @@ void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string&
{
if (object->permModify())
{
- // update viewer side color in anticipation of update from simulator
+ // update viewer has media
object->setTEMediaFlags(te, mMediaFlags);
}
return true;
}
- } setfunc(media_flags);
+ } setfunc(media_type);
getSelection()->applyToTEs(&setfunc);
-
- struct g : public LLSelectedObjectFunctor
+ struct f2 : public LLSelectedObjectFunctor
{
- U8 media_type;
- const std::string& media_url ;
- g(U8 a, const std::string& b) : media_type(a), media_url(b) {}
virtual bool apply(LLViewerObject* object)
{
if (object->permModify())
{
object->sendTEUpdate();
- object->setMediaType(media_type);
- object->setMediaURL(media_url);
}
return true;
}
- } sendfunc(media_type, media_url);
- getSelection()->applyToObjects(&sendfunc);
+ } func2;
+ mSelectedObjects->applyToObjects( &func2 );
}
+// This function expects media_data to be a map containing relevant
+// media data name/value pairs (e.g. home_url, etc.)
+void LLSelectMgr::selectionSetMediaData(const LLSD &media_data)
+{
+
+ struct f : public LLSelectedTEFunctor
+ {
+ const LLSD &mMediaData;
+ f(const LLSD& t) : mMediaData(t) {}
+ bool apply(LLViewerObject* object, S32 te)
+ {
+ if (object->permModify())
+ {
+ LLVOVolume *vo = dynamic_cast<LLVOVolume*>(object);
+ if (NULL != vo)
+ {
+ vo->syncMediaData(te, mMediaData, true/*merge*/, true/*ignore_agent*/);
+ }
+ }
+ return true;
+ }
+ } setfunc(media_data);
+ getSelection()->applyToTEs(&setfunc);
+
+ struct f2 : public LLSelectedObjectFunctor
+ {
+ virtual bool apply(LLViewerObject* object)
+ {
+ if (object->permModify())
+ {
+ LLVOVolume *vo = dynamic_cast<LLVOVolume*>(object);
+ if (NULL != vo)
+ {
+ // Send updated media data FOR THE ENTIRE OBJECT
+ vo->sendMediaDataUpdate();
+ }
+ }
+ return true;
+ }
+ } func2;
+ getSelection()->applyToObjects(&func2);
+}
+
+
+
void LLSelectMgr::selectionSetGlow(F32 glow)
{
struct f1 : public LLSelectedTEFunctor
@@ -2208,6 +2277,26 @@ BOOL LLSelectMgr::selectGetAllValid()
return TRUE;
}
+//-----------------------------------------------------------------------------
+// selectGetAllValidAndObjectsFound() - return TRUE if selections are
+// valid and objects are found.
+//
+// For EXT-3114 - same as selectGetModify() without the modify check.
+//-----------------------------------------------------------------------------
+BOOL LLSelectMgr::selectGetAllValidAndObjectsFound()
+{
+ for (LLObjectSelection::iterator iter = getSelection()->begin();
+ iter != getSelection()->end(); iter++ )
+ {
+ LLSelectNode* node = *iter;
+ LLViewerObject* object = node->getObject();
+ if( !object || !node->mValid )
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
//-----------------------------------------------------------------------------
// selectGetModify() - return TRUE if current agent can modify all
@@ -2337,6 +2426,7 @@ BOOL LLSelectMgr::selectGetCreator(LLUUID& result_id, std::string& name)
}
if (first_id.isNull())
{
+ name = LLTrans::getString("AvatarNameNobody");
return FALSE;
}
@@ -2344,11 +2434,11 @@ BOOL LLSelectMgr::selectGetCreator(LLUUID& result_id, std::string& name)
if (identical)
{
- gCacheName->getFullName(first_id, name);
+ name = LLSLURL::buildCommand("agent", first_id, "inspect");
}
else
{
- name.assign( "(multiple)" );
+ name = LLTrans::getString("AvatarNameMultiple");
}
return identical;
@@ -2403,20 +2493,20 @@ BOOL LLSelectMgr::selectGetOwner(LLUUID& result_id, std::string& name)
BOOL public_owner = (first_id.isNull() && !first_group_owned);
if (first_group_owned)
{
- name.assign( "(Group Owned)");
+ name = LLSLURL::buildCommand("group", first_id, "inspect");
}
else if(!public_owner)
{
- gCacheName->getFullName(first_id, name);
+ name = LLSLURL::buildCommand("agent", first_id, "inspect");
}
else
{
- name.assign("Public");
+ name = LLTrans::getString("AvatarNameNobody");
}
}
else
{
- name.assign( "(multiple)" );
+ name = LLTrans::getString("AvatarNameMultiple");
}
return identical;
@@ -2467,7 +2557,7 @@ BOOL LLSelectMgr::selectGetLastOwner(LLUUID& result_id, std::string& name)
BOOL public_owner = (first_id.isNull());
if(!public_owner)
{
- gCacheName->getFullName(first_id, name);
+ name = LLSLURL::buildCommand("agent", first_id, "inspect");
}
else
{
@@ -2691,7 +2781,7 @@ void LLSelectMgr::selectDelete()
}
LLNotification::Params params("ConfirmObjectDeleteLock");
- params.functor(boost::bind(&LLSelectMgr::confirmDelete, _1, _2, getSelection()));
+ params.functor.function(boost::bind(&LLSelectMgr::confirmDelete, _1, _2, getSelection()));
if(locked_but_deleteable_object ||
no_copy_but_deleteable_object ||
@@ -2763,7 +2853,7 @@ bool LLSelectMgr::confirmDelete(const LLSD& notification, const LLSD& response,
case 0:
{
// TODO: Make sure you have delete permissions on all of them.
- LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
// attempt to derez into the trash.
LLDeRezInfo* info = new LLDeRezInfo(DRD_TRASH, trash_id);
LLSelectMgr::getInstance()->sendListToRegions("DeRezObject",
@@ -3342,7 +3432,7 @@ void LLSelectMgr::deselectAll()
{
return;
}
-
+
// Zap the angular velocity, as the sim will set it to zero
for (LLObjectSelection::iterator iter = mSelectedObjects->begin();
iter != mSelectedObjects->end(); iter++ )
@@ -3424,7 +3514,7 @@ void LLSelectMgr::deselectAllIfTooFar()
// HACK: Don't deselect when we're navigating to rate an object's
// owner or creator. JC
- if (gPieObject->getVisible() || gPieRate->getVisible() )
+ if (gMenuObject->getVisible())
{
return;
}
@@ -3432,6 +3522,7 @@ void LLSelectMgr::deselectAllIfTooFar()
LLVector3d selectionCenter = getSelectionCenterGlobal();
if (gSavedSettings.getBOOL("LimitSelectDistance")
&& (!mSelectedObjects->getPrimaryObject() || !mSelectedObjects->getPrimaryObject()->isAvatar())
+ && (mSelectedObjects->getPrimaryObject() != LLViewerMediaFocus::getInstance()->getFocusedObject())
&& !mSelectedObjects->isAttachment()
&& !selectionCenter.isExactlyZero())
{
@@ -3443,7 +3534,7 @@ void LLSelectMgr::deselectAllIfTooFar()
if (select_dist_sq > deselect_dist_sq)
{
- if (gDebugSelectMgr)
+ if (mDebugSelectMgr)
{
llinfos << "Selection manager: auto-deselecting, select_dist = " << fsqrtf(select_dist_sq) << llendl;
llinfos << "agent pos global = " << gAgent.getPositionGlobal() << llendl;
@@ -3532,6 +3623,9 @@ void LLSelectMgr::sendAttach(U8 attachment_point)
return;
}
+#if ENABLE_MULTIATTACHMENTS
+ attachment_point |= ATTACHMENT_ADD;
+#endif
BOOL build_mode = LLToolMgr::getInstance()->inEdit();
// Special case: Attach to default location for this object.
if (0 == attachment_point ||
@@ -4444,10 +4538,9 @@ void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** use
msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Description, desc);
// the reporter widget askes the server for info about picked objects
- if (request_flags & (COMPLAINT_REPORT_REQUEST | BUG_REPORT_REQUEST))
+ if (request_flags & COMPLAINT_REPORT_REQUEST )
{
- EReportType report_type = (COMPLAINT_REPORT_REQUEST & request_flags) ? COMPLAINT_REPORT : BUG_REPORT;
- LLFloaterReporter *reporterp = LLFloaterReporter::getReporter(report_type);
+ LLFloaterReporter *reporterp = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter");
if (reporterp)
{
std::string fullname;
@@ -4471,7 +4564,7 @@ void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** use
return (node->getObject() && node->getObject()->mID == mID);
}
} func(id);
- LLSelectNode* node = LLSelectMgr::getInstance()->getHoverObjects()->getFirstNode(&func);
+ LLSelectNode* node = LLSelectMgr::getInstance()->mHoverObjects->getFirstNode(&func);
if (node)
{
@@ -4538,7 +4631,7 @@ void LLSelectMgr::updateSilhouettes()
if (!mSilhouetteImagep)
{
- mSilhouetteImagep = gImageList.getImageFromFile("silhouette.j2c", TRUE, TRUE);
+ mSilhouetteImagep = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", TRUE, LLViewerTexture::BOOST_UI);
}
mHighlightedObjects->cleanupNodes();
@@ -4560,54 +4653,7 @@ void LLSelectMgr::updateSilhouettes()
std::vector<LLViewerObject*> changed_objects;
- if (mSelectedObjects->getNumNodes())
- {
- //gGLSPipelineSelection.set();
-
- //mSilhouetteImagep->bindTexture();
- //glAlphaFunc(GL_GREATER, sHighlightAlphaTest);
-
- for (S32 pass = 0; pass < 2; pass++)
- {
- for (LLObjectSelection::iterator iter = mSelectedObjects->begin();
- iter != mSelectedObjects->end(); iter++)
- {
- LLSelectNode* node = *iter;
- LLViewerObject* objectp = node->getObject();
- if (!objectp)
- continue;
- // do roots first, then children so that root flags are cleared ASAP
- BOOL roots_only = (pass == 0);
- BOOL is_root = (objectp->isRootEdit());
- if (roots_only != is_root || objectp->mDrawable.isNull())
- {
- continue;
- }
-
- if (!node->mSilhouetteExists
- || objectp->isChanged(LLXform::SILHOUETTE)
- || (objectp->getParent() && objectp->getParent()->isChanged(LLXform::SILHOUETTE)))
- {
- if (num_sils_genned++ < MAX_SILS_PER_FRAME)// && objectp->mDrawable->isVisible())
- {
- generateSilhouette(node, LLViewerCamera::getInstance()->getOrigin());
- changed_objects.push_back(objectp);
- }
- else if (objectp->isAttachment())
- {
- //RN: hack for orthogonal projection of HUD attachments
- LLViewerJointAttachment* attachment_pt = (LLViewerJointAttachment*)objectp->getRootEdit()->mDrawable->getParent();
- if (attachment_pt && attachment_pt->getIsHUDAttachment())
- {
- LLVector3 camera_pos = LLVector3(-10000.f, 0.f, 0.f);
- generateSilhouette(node, camera_pos);
- }
- }
- }
- }
- }
- }
-
+ updateSelectionSilhouette(mSelectedObjects, num_sils_genned, changed_objects);
if (mRectSelectedObjects.size() > 0)
{
//gGLSPipelineSelection.set();
@@ -4801,6 +4847,56 @@ void LLSelectMgr::updateSilhouettes()
//gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
}
+void LLSelectMgr::updateSelectionSilhouette(LLObjectSelectionHandle object_handle, S32& num_sils_genned, std::vector<LLViewerObject*>& changed_objects)
+{
+ if (object_handle->getNumNodes())
+ {
+ //gGLSPipelineSelection.set();
+
+ //mSilhouetteImagep->bindTexture();
+ //glAlphaFunc(GL_GREATER, sHighlightAlphaTest);
+
+ for (S32 pass = 0; pass < 2; pass++)
+ {
+ for (LLObjectSelection::iterator iter = object_handle->begin();
+ iter != object_handle->end(); iter++)
+ {
+ LLSelectNode* node = *iter;
+ LLViewerObject* objectp = node->getObject();
+ if (!objectp)
+ continue;
+ // do roots first, then children so that root flags are cleared ASAP
+ BOOL roots_only = (pass == 0);
+ BOOL is_root = (objectp->isRootEdit());
+ if (roots_only != is_root || objectp->mDrawable.isNull())
+ {
+ continue;
+ }
+
+ if (!node->mSilhouetteExists
+ || objectp->isChanged(LLXform::SILHOUETTE)
+ || (objectp->getParent() && objectp->getParent()->isChanged(LLXform::SILHOUETTE)))
+ {
+ if (num_sils_genned++ < MAX_SILS_PER_FRAME)// && objectp->mDrawable->isVisible())
+ {
+ generateSilhouette(node, LLViewerCamera::getInstance()->getOrigin());
+ changed_objects.push_back(objectp);
+ }
+ else if (objectp->isAttachment())
+ {
+ //RN: hack for orthogonal projection of HUD attachments
+ LLViewerJointAttachment* attachment_pt = (LLViewerJointAttachment*)objectp->getRootEdit()->mDrawable->getParent();
+ if (attachment_pt && attachment_pt->getIsHUDAttachment())
+ {
+ LLVector3 camera_pos = LLVector3(-10000.f, 0.f, 0.f);
+ generateSilhouette(node, camera_pos);
+ }
+ }
+ }
+ }
+ }
+ }
+}
void LLSelectMgr::renderSilhouettes(BOOL for_hud)
{
if (!mRenderSilhouettes)
@@ -4808,7 +4904,7 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
return;
}
- gGL.getTexUnit(0)->bind(mSilhouetteImagep.get());
+ gGL.getTexUnit(0)->bind(mSilhouetteImagep);
LLGLSPipelineSelection gls_select;
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f);
LLGLEnable blend(GL_BLEND);
@@ -4837,8 +4933,21 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
}
if (mSelectedObjects->getNumNodes())
{
- LLUUID inspect_item_id = LLFloaterInspect::getSelectedUUID();
-
+ LLUUID inspect_item_id= LLUUID::null;
+#if 0
+ LLFloaterInspect* inspect_instance = LLFloaterReg::getTypedInstance<LLFloaterInspect>("inspect");
+ if(inspect_instance)
+ {
+ inspect_item_id = inspect_instance->getSelectedUUID();
+ }
+#endif
+ LLSidepanelTaskInfo *panel_task_info = LLSidepanelTaskInfo::getActivePanel();
+ if (panel_task_info)
+ {
+ inspect_item_id = panel_task_info->getSelectedUUID();
+ }
+
+ LLUUID focus_item_id = LLViewerMediaFocus::getInstance()->getFocusedObjectID();
for (S32 pass = 0; pass < 2; pass++)
{
for (LLObjectSelection::iterator iter = mSelectedObjects->begin();
@@ -4852,7 +4961,11 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
{
continue;
}
- if(objectp->getID() == inspect_item_id)
+ if (objectp->getID() == focus_item_id)
+ {
+ node->renderOneSilhouette(gFocusMgr.getFocusColor());
+ }
+ else if(objectp->getID() == inspect_item_id)
{
node->renderOneSilhouette(sHighlightInspectColor);
}
@@ -4934,6 +5047,16 @@ void LLSelectMgr::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_
// Utility classes
//
LLSelectNode::LLSelectNode(LLViewerObject* object, BOOL glow)
+: mObject(object),
+ mIndividualSelection(FALSE),
+ mTransient(FALSE),
+ mValid(FALSE),
+ mPermissions(new LLPermissions()),
+ mInventorySerial(0),
+ mSilhouetteExists(FALSE),
+ mDuplicated(FALSE),
+ mTESelectMask(0),
+ mLastTESelected(0)
{
mObject = object;
selectAllTEs(FALSE);
@@ -4955,11 +5078,7 @@ LLSelectNode::LLSelectNode(LLViewerObject* object, BOOL glow)
LLSelectNode::LLSelectNode(const LLSelectNode& nodep)
{
- S32 i;
- for (i = 0; i < SELECT_MAX_TES; i++)
- {
- mTESelected[i] = nodep.mTESelected[i];
- }
+ mTESelectMask = nodep.mTESelectMask;
mLastTESelected = nodep.mLastTESelected;
mIndividualSelection = nodep.mIndividualSelection;
@@ -5012,10 +5131,7 @@ LLSelectNode::~LLSelectNode()
void LLSelectNode::selectAllTEs(BOOL b)
{
- for (S32 i = 0; i < SELECT_MAX_TES; i++)
- {
- mTESelected[i] = b;
- }
+ mTESelectMask = b ? TE_SELECT_MASK_ALL : 0x0;
mLastTESelected = 0;
}
@@ -5025,7 +5141,15 @@ void LLSelectNode::selectTE(S32 te_index, BOOL selected)
{
return;
}
- mTESelected[te_index] = selected;
+ S32 mask = 0x1 << te_index;
+ if(selected)
+ {
+ mTESelectMask |= mask;
+ }
+ else
+ {
+ mTESelectMask &= ~mask;
+ }
mLastTESelected = te_index;
}
@@ -5035,7 +5159,7 @@ BOOL LLSelectNode::isTESelected(S32 te_index)
{
return FALSE;
}
- return mTESelected[te_index];
+ return (mTESelectMask & (0x1 << te_index)) != 0;
}
S32 LLSelectNode::getLastSelectedTE()
@@ -5375,30 +5499,45 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color)
// Utility Functions
//
-// Update everyone who cares about the selection list
+// *DEPRECATED: See header comment.
void dialog_refresh_all()
{
- if (gNoRender)
- {
- return;
- }
+ // This is the easiest place to fire the update signal, as it will
+ // make cleaning up the functions below easier. Also, sometimes entities
+ // outside the selection manager change properties of selected objects
+ // and call into this function. Yuck.
+ LLSelectMgr::getInstance()->mUpdateSignal();
- //could refresh selected object info in toolbar here
+ // *TODO: Eliminate all calls into outside classes below, make those
+ // objects register with the update signal.
gFloaterTools->dirty();
- if( gPieObject->getVisible() )
+ gMenuObject->needsArrange();
+
+ if( gMenuAttachmentSelf->getVisible() )
{
- gPieObject->arrange();
+ gMenuAttachmentSelf->arrange();
}
-
- if( gPieAttachment->getVisible() )
+ if( gMenuAttachmentOther->getVisible() )
{
- gPieAttachment->arrange();
+ gMenuAttachmentOther->arrange();
}
LLFloaterProperties::dirtyAll();
- LLFloaterInspect::dirty();
+
+#if 0
+ LLFloaterInspect* inspect_instance = LLFloaterReg::getTypedInstance<LLFloaterInspect>("inspect");
+ if(inspect_instance)
+ {
+ inspect_instance->dirty();
+ }
+#endif
+ LLSidepanelTaskInfo *panel_task_info = LLSidepanelTaskInfo::getActivePanel();
+ if (panel_task_info)
+ {
+ panel_task_info->dirty();
+ }
}
S32 get_family_count(LLViewerObject *parent)
@@ -5639,8 +5778,22 @@ void LLSelectMgr::redo()
//-----------------------------------------------------------------------------
BOOL LLSelectMgr::canDoDelete() const
{
+ bool can_delete = false;
+ // This function is "logically const" - it does not change state in
+ // a way visible outside the selection manager.
+ LLSelectMgr* self = const_cast<LLSelectMgr*>(this);
+ LLViewerObject* obj = self->mSelectedObjects->getFirstDeleteableObject();
// Note: Can only delete root objects (see getFirstDeleteableObject() for more info)
- return const_cast<LLSelectMgr*>(this)->mSelectedObjects->getFirstDeleteableObject() != NULL; // HACK: casting away constness - MG
+ if (obj!= NULL)
+ {
+ // all the faces needs to be selected
+ if(self->mSelectedObjects->contains(obj,SELECT_ALL_TES ))
+ {
+ can_delete = true;
+ }
+ }
+
+ return can_delete;
}
//-----------------------------------------------------------------------------
@@ -5777,6 +5930,27 @@ void LLSelectMgr::setAgentHUDZoom(F32 target_zoom, F32 current_zoom)
gAgent.mHUDCurZoom = current_zoom;
}
+/////////////////////////////////////////////////////////////////////////////
+// Object selection iterator helpers
+/////////////////////////////////////////////////////////////////////////////
+bool LLObjectSelection::is_root::operator()(LLSelectNode *node)
+{
+ LLViewerObject* object = node->getObject();
+ return (object != NULL) && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild());
+}
+
+bool LLObjectSelection::is_valid_root::operator()(LLSelectNode *node)
+{
+ LLViewerObject* object = node->getObject();
+ return (object != NULL) && node->mValid && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild());
+}
+
+bool LLObjectSelection::is_root_object::operator()(LLSelectNode *node)
+{
+ LLViewerObject* object = node->getObject();
+ return (object != NULL) && (object->isRootEdit() || object->isJointChild());
+}
+
LLObjectSelection::LLObjectSelection() :
LLRefCount(),
mSelectType(SELECT_TYPE_WORLD)
@@ -6008,6 +6182,29 @@ bool LLObjectSelection::applyToRootNodes(LLSelectedNodeFunctor *func, bool first
return result;
}
+BOOL LLObjectSelection::isMultipleTESelected()
+{
+ BOOL te_selected = FALSE;
+ // ...all faces
+ for (LLObjectSelection::iterator iter = begin();
+ iter != end(); iter++)
+ {
+ LLSelectNode* nodep = *iter;
+ for (S32 i = 0; i < SELECT_MAX_TES; i++)
+ {
+ if(nodep->isTESelected(i))
+ {
+ if(te_selected)
+ {
+ return TRUE;
+ }
+ te_selected = TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
//-----------------------------------------------------------------------------
// contains()
//-----------------------------------------------------------------------------
@@ -6031,8 +6228,14 @@ BOOL LLObjectSelection::contains(LLViewerObject* object, S32 te)
LLSelectNode* nodep = *iter;
if (nodep->getObject() == object)
{
+ // Optimization
+ if (nodep->getTESelectMask() == TE_SELECT_MASK_ALL)
+ {
+ return TRUE;
+ }
+
BOOL all_selected = TRUE;
- for (S32 i = 0; i < SELECT_MAX_TES; i++)
+ for (S32 i = 0; i < object->getNumTEs(); i++)
{
all_selected = all_selected && nodep->isTESelected(i);
}
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index d6c4b5485d..f8ecfd0674 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -35,10 +35,10 @@
#include "llcharacter.h"
#include "lleditmenuhandler.h"
-#include "llstring.h"
#include "llundo.h"
#include "lluuid.h"
-#include "llmemory.h"
+#include "llpointer.h"
+#include "llsafehandle.h"
#include "llsaleinfo.h"
#include "llcategory.h"
#include "v3dmath.h"
@@ -47,14 +47,15 @@
#include "llframetimer.h"
#include "llbbox.h"
#include "llpermissions.h"
-#include "llviewerobject.h"
+#include "llcontrol.h"
+#include "llviewerobject.h" // LLObjectSelection::getSelectedTEValue template
#include <deque>
-#include "boost/iterator/filter_iterator.hpp"
+#include <boost/iterator/filter_iterator.hpp>
+#include <boost/signals2.hpp>
class LLMessageSystem;
-class LLViewerImage;
-class LLViewerObject;
+class LLViewerTexture;
class LLColor4;
class LLVector3;
class LLSelectNode;
@@ -138,6 +139,7 @@ public:
void selectTE(S32 te_index, BOOL selected);
BOOL isTESelected(S32 te_index);
S32 getLastSelectedTE();
+ S32 getTESelectMask() { return mTESelectMask; }
void renderOneSilhouette(const LLColor4 &color);
void setTransient(BOOL transient) { mTransient = transient; }
BOOL isTransient() { return mTransient; }
@@ -190,7 +192,7 @@ public:
protected:
LLPointer<LLViewerObject> mObject;
- BOOL mTESelected[SELECT_MAX_TES];
+ S32 mTESelectMask;
S32 mLastTESelected;
};
@@ -201,13 +203,9 @@ class LLObjectSelection : public LLRefCount
protected:
~LLObjectSelection();
- // List
public:
typedef std::list<LLSelectNode*> list_t;
-private:
- list_t mList;
-public:
// Iterators
struct is_non_null
{
@@ -233,11 +231,7 @@ public:
struct is_root
{
- bool operator()(LLSelectNode* node)
- {
- LLViewerObject* object = node->getObject();
- return (object != NULL) && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild());
- }
+ bool operator()(LLSelectNode* node);
};
typedef boost::filter_iterator<is_root, list_t::iterator > root_iterator;
root_iterator root_begin() { return root_iterator(mList.begin(), mList.end()); }
@@ -245,11 +239,7 @@ public:
struct is_valid_root
{
- bool operator()(LLSelectNode* node)
- {
- LLViewerObject* object = node->getObject();
- return (object != NULL) && node->mValid && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild());
- }
+ bool operator()(LLSelectNode* node);
};
typedef boost::filter_iterator<is_root, list_t::iterator > valid_root_iterator;
valid_root_iterator valid_root_begin() { return valid_root_iterator(mList.begin(), mList.end()); }
@@ -257,11 +247,7 @@ public:
struct is_root_object
{
- bool operator()(LLSelectNode* node)
- {
- LLViewerObject* object = node->getObject();
- return (object != NULL) && (object->isRootEdit() || object->isJointChild());
- }
+ bool operator()(LLSelectNode* node);
};
typedef boost::filter_iterator<is_root_object, list_t::iterator > root_object_iterator;
root_object_iterator root_object_begin() { return root_object_iterator(mList.begin(), mList.end()); }
@@ -287,11 +273,14 @@ public:
LLViewerObject* getFirstCopyableObject(BOOL get_parent = FALSE);
LLViewerObject* getFirstDeleteableObject();
LLViewerObject* getFirstMoveableObject(BOOL get_parent = FALSE);
+
+ /// Return the object that lead to this selection, possible a child
LLViewerObject* getPrimaryObject() { return mPrimaryObject; }
// iterate through texture entries
template <typename T> bool getSelectedTEValue(LLSelectedTEGetFunctor<T>* func, T& res);
-
+ template <typename T> bool isMultipleTEValue(LLSelectedTEGetFunctor<T>* func, const T& ignore_value);
+
void addNode(LLSelectNode *nodep);
void addNodeAtEnd(LLSelectNode *nodep);
void moveNodeToFront(LLSelectNode *nodep);
@@ -305,6 +294,7 @@ public:
S32 getTECount();
S32 getRootObjectCount();
+ BOOL isMultipleTESelected();
BOOL contains(LLViewerObject* object);
BOOL contains(LLViewerObject* object, S32 te);
@@ -323,6 +313,7 @@ public:
ESelectType getSelectType() const { return mSelectType; }
private:
+ list_t mList;
const LLObjectSelection &operator=(const LLObjectSelection &);
LLPointer<LLViewerObject> mPrimaryObject;
@@ -332,12 +323,18 @@ private:
typedef LLSafeHandle<LLObjectSelection> LLObjectSelectionHandle;
+// Build time optimization, generate this once in .cpp file
+#ifndef LLSELECTMGR_CPP
+extern template class LLSelectMgr* LLSingleton<class LLSelectMgr>::getInstance();
+#endif
+
class LLSelectMgr : public LLEditMenuHandler, public LLSingleton<LLSelectMgr>
{
public:
static BOOL sRectSelectInclusive; // do we need to surround an object to pick it?
static BOOL sRenderHiddenSelections; // do we show selection silhouettes that are occluded?
static BOOL sRenderLightRadius; // do we show the radius of selected lights?
+
static F32 sHighlightThickness;
static F32 sHighlightUScale;
static F32 sHighlightVScale;
@@ -352,6 +349,10 @@ public:
static LLColor4 sHighlightInspectColor;
static LLColor4 sContextSilhouetteColor;
+ LLCachedControl<bool> mHideSelectedObjects;
+ LLCachedControl<bool> mAllowSelectAvatar;
+ LLCachedControl<bool> mDebugSelectMgr;
+
public:
LLSelectMgr();
~LLSelectMgr();
@@ -390,20 +391,25 @@ public:
// Add
////////////////////////////////////////////////////////////////
- // For when you want just a child object.
- LLObjectSelectionHandle selectObjectOnly(LLViewerObject* object, S32 face = SELECT_ALL_TES);
-
// This method is meant to select an object, and then select all
- // of the ancestors and descendents. This should be the normal behavior.
+ // of the ancestors and descendants. This should be the normal behavior.
+ //
+ // *NOTE: You must hold on to the object selection handle, otherwise
+ // the objects will be automatically deselected in 1 frame.
LLObjectSelectionHandle selectObjectAndFamily(LLViewerObject* object, BOOL add_to_end = FALSE);
+ // For when you want just a child object.
+ LLObjectSelectionHandle selectObjectOnly(LLViewerObject* object, S32 face = SELECT_ALL_TES);
+
// Same as above, but takes a list of objects. Used by rectangle select.
LLObjectSelectionHandle selectObjectAndFamily(const std::vector<LLViewerObject*>& object_list, BOOL send_to_sim = TRUE);
// converts all objects currently highlighted to a selection, and returns it
LLObjectSelectionHandle selectHighlightedObjects();
- LLObjectSelectionHandle setHoverObject(LLViewerObject *objectp);
+ LLObjectSelectionHandle setHoverObject(LLViewerObject *objectp, S32 face = -1);
+ LLSelectNode *getHoverNode();
+ LLSelectNode *getPrimaryHoverNode();
void highlightObjectOnly(LLViewerObject *objectp);
void highlightObjectAndFamily(LLViewerObject *objectp);
@@ -438,14 +444,11 @@ public:
////////////////////////////////////////////////////////////////
// Selection accessors
////////////////////////////////////////////////////////////////
- LLObjectSelectionHandle getHoverObjects() { return mHoverObjects; }
LLObjectSelectionHandle getSelection() { return mSelectedObjects; }
// right now this just renders the selection with root/child colors instead of a single color
LLObjectSelectionHandle getEditSelection() { convertTransient(); return mSelectedObjects; }
LLObjectSelectionHandle getHighlightedObjects() { return mHighlightedObjects; }
- LLSelectNode *getHoverNode();
-
////////////////////////////////////////////////////////////////
// Grid manipulation
////////////////////////////////////////////////////////////////
@@ -499,7 +502,8 @@ public:
void selectionSetTexGen( U8 texgen );
void selectionSetShiny( U8 shiny );
void selectionSetFullbright( U8 fullbright );
- void selectionSetMediaTypeAndURL( U8 media_type, const std::string& media_url );
+ void selectionSetMedia( U8 media_type );
+ void selectionSetMediaData(const LLSD &media_data); // NOTE: modifies media_data!!!
void selectionSetClickAction(U8 action);
void selectionSetIncludeInSearch(bool include_in_search);
void selectionSetGlow(const F32 glow);
@@ -531,6 +535,7 @@ public:
// Returns TRUE if the viewer has information on all selected objects
BOOL selectGetAllRootsValid();
BOOL selectGetAllValid();
+ BOOL selectGetAllValidAndObjectsFound();
// returns TRUE if you can modify all selected objects.
BOOL selectGetRootsModify();
@@ -643,6 +648,7 @@ private:
ESelectType getSelectTypeForObject(LLViewerObject* object);
void addAsFamily(std::vector<LLViewerObject*>& objects, BOOL add_to_end = FALSE);
void generateSilhouette(LLSelectNode *nodep, const LLVector3& view_point);
+ void updateSelectionSilhouette(LLObjectSelectionHandle object_handle, S32& num_sils_genned, std::vector<LLViewerObject*>& changed_objects);
// Send one message to each region containing an object on selection list.
void sendListToRegions( const std::string& message_name,
void (*pack_header)(void *user_data),
@@ -650,6 +656,7 @@ private:
void *user_data,
ESendType send_type);
+
static void packAgentID( void *);
static void packAgentAndSessionID(void* user_data);
static void packAgentAndGroupID(void* user_data);
@@ -660,7 +667,7 @@ private:
static void packDeRezHeader(void* user_data);
static void packObjectID( LLSelectNode* node, void *);
static void packObjectIDAsParam(LLSelectNode* node, void *);
- static void packObjectIDAndRotation( LLSelectNode* node, void *);
+ static void packObjectIDAndRotation(LLSelectNode* node, void *);
static void packObjectLocalID(LLSelectNode* node, void *);
static void packObjectClickAction(LLSelectNode* node, void* data);
static void packObjectIncludeInSearch(LLSelectNode* node, void* data);
@@ -682,9 +689,15 @@ private:
static void packPermissionsHead(void* user_data);
static void packGodlikeHead(void* user_data);
static bool confirmDelete(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle);
-
+
+public:
+ // Observer/callback support for when object selection changes or
+ // properties are received/updated
+ typedef boost::signals2::signal< void ()> update_signal_t;
+ update_signal_t mUpdateSignal;
+
private:
- LLPointer<LLViewerImage> mSilhouetteImagep;
+ LLPointer<LLViewerTexture> mSilhouetteImagep;
LLObjectSelectionHandle mSelectedObjects;
LLObjectSelectionHandle mHoverObjects;
LLObjectSelectionHandle mHighlightedObjects;
@@ -714,8 +727,10 @@ private:
LLAnimPauseRequest mPauseRequest;
};
-// Utilities
-void dialog_refresh_all(); // Update subscribers to the selection list
+// *DEPRECATED: For callbacks or observers, use
+// LLSelectMgr::getInstance()->mUpdateSignal.connect( callback )
+// Update subscribers to the selection list
+void dialog_refresh_all();
// Templates
//-----------------------------------------------------------------------------
@@ -778,5 +793,52 @@ template <typename T> bool LLObjectSelection::getSelectedTEValue(LLSelectedTEGet
return identical;
}
+// Templates
+//-----------------------------------------------------------------------------
+// isMultipleTEValue iterate through all TEs and test for uniqueness
+// with certain return value ignored when performing the test.
+// e.g. when testing if the selection has a unique non-empty homeurl :
+// you can set ignore_value = "" and it will only compare among the non-empty
+// homeUrls and ignore the empty ones.
+//-----------------------------------------------------------------------------
+template <typename T> bool LLObjectSelection::isMultipleTEValue(LLSelectedTEGetFunctor<T>* func, const T& ignore_value)
+{
+ bool have_first = false;
+ T selected_value = T();
+
+ // Now iterate through all TEs to test for sameness
+ bool unique = TRUE;
+ for (iterator iter = begin(); iter != end(); iter++)
+ {
+ LLSelectNode* node = *iter;
+ LLViewerObject* object = node->getObject();
+ for (S32 te = 0; te < object->getNumTEs(); ++te)
+ {
+ if (!node->isTESelected(te))
+ {
+ continue;
+ }
+ T value = func->get(object, te);
+ if(value == ignore_value)
+ {
+ continue;
+ }
+ if (!have_first)
+ {
+ have_first = true;
+ }
+ else
+ {
+ if (value !=selected_value )
+ {
+ unique = false;
+ return !unique;
+ }
+ }
+ }
+ }
+ return !unique;
+}
+
#endif
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
new file mode 100644
index 0000000000..43215f86bd
--- /dev/null
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -0,0 +1,405 @@
+/**
+ * @file llsidepanelappearance.cpp
+ * @brief Side Bar "Appearance" panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llsidepanelappearance.h"
+
+#include "llaccordionctrltab.h"
+#include "llagent.h"
+#include "llagentwearables.h"
+#include "llappearancemgr.h"
+#include "llinventorypanel.h"
+#include "llfiltereditor.h"
+#include "llfloaterreg.h"
+#include "llfloaterworldmap.h"
+#include "llfoldervieweventlistener.h"
+#include "llpaneleditwearable.h"
+#include "llpaneloutfitsinventory.h"
+#include "lltextbox.h"
+#include "lluictrlfactory.h"
+#include "llviewerregion.h"
+#include "llvoavatarself.h"
+#include "llwearable.h"
+
+static LLRegisterPanelClassWrapper<LLSidepanelAppearance> t_appearance("sidepanel_appearance");
+
+class LLCurrentlyWornFetchObserver : public LLInventoryFetchObserver
+{
+public:
+ LLCurrentlyWornFetchObserver(LLSidepanelAppearance *panel) :
+ mPanel(panel)
+ {}
+ ~LLCurrentlyWornFetchObserver() {}
+ virtual void done()
+ {
+ mPanel->inventoryFetched();
+ gInventory.removeObserver(this);
+ delete this;
+ }
+private:
+ LLSidepanelAppearance *mPanel;
+};
+
+class LLWatchForOutfitRenameObserver : public LLInventoryObserver
+{
+public:
+ LLWatchForOutfitRenameObserver(LLSidepanelAppearance *panel) :
+ mPanel(panel)
+ {}
+ virtual void changed(U32 mask);
+
+private:
+ LLSidepanelAppearance *mPanel;
+};
+
+void LLWatchForOutfitRenameObserver::changed(U32 mask)
+{
+ if (mask & LABEL)
+ {
+ mPanel->refreshCurrentOutfitName();
+ }
+}
+
+LLSidepanelAppearance::LLSidepanelAppearance() :
+ LLPanel(),
+ mFilterSubString(LLStringUtil::null),
+ mFilterEditor(NULL),
+ mLookInfo(NULL),
+ mCurrOutfitPanel(NULL)
+{
+}
+
+LLSidepanelAppearance::~LLSidepanelAppearance()
+{
+ gInventory.removeObserver(mOutfitRenameWatcher);
+ delete mOutfitRenameWatcher;
+}
+
+// virtual
+BOOL LLSidepanelAppearance::postBuild()
+{
+ mOpenOutfitBtn = getChild<LLButton>("openoutfit_btn");
+ mOpenOutfitBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onOpenOutfitButtonClicked, this));
+
+ mEditAppearanceBtn = getChild<LLButton>("editappearance_btn");
+ mEditAppearanceBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditAppearanceButtonClicked, this));
+
+ mEditBtn = getChild<LLButton>("edit_btn");
+ mEditBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditButtonClicked, this));
+
+ mNewOutfitBtn = getChild<LLButton>("newlook_btn");
+ mNewOutfitBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onNewOutfitButtonClicked, this));
+ mNewOutfitBtn->setEnabled(false);
+
+ mFilterEditor = getChild<LLFilterEditor>("Filter");
+ if (mFilterEditor)
+ {
+ mFilterEditor->setCommitCallback(boost::bind(&LLSidepanelAppearance::onFilterEdit, this, _2));
+ }
+
+ mPanelOutfitsInventory = dynamic_cast<LLPanelOutfitsInventory *>(getChild<LLPanel>("panel_outfits_inventory"));
+ mPanelOutfitsInventory->setParent(this);
+
+ mLookInfo = dynamic_cast<LLPanelLookInfo*>(getChild<LLPanel>("panel_look_info"));
+ if (mLookInfo)
+ {
+ LLButton* back_btn = mLookInfo->getChild<LLButton>("back_btn");
+ if (back_btn)
+ {
+ back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onBackButtonClicked, this));
+ }
+
+ }
+
+ mEditWearable = dynamic_cast<LLPanelEditWearable*>(getChild<LLPanel>("panel_edit_wearable"));
+ if (mEditWearable)
+ {
+ LLButton* edit_wearable_back_btn = mEditWearable->getChild<LLButton>("back_btn");
+ if (edit_wearable_back_btn)
+ {
+ edit_wearable_back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditWearBackClicked, this));
+ }
+ }
+
+ mCurrentLookName = getChild<LLTextBox>("currentlook_name");
+
+ mOutfitDirtyTag = getChild<LLTextBox>("currentlook_title");
+
+ mCurrOutfitPanel = getChild<LLPanel>("panel_currentlook");
+
+ mOutfitRenameWatcher = new LLWatchForOutfitRenameObserver(this);
+ gInventory.addObserver(mOutfitRenameWatcher);
+
+ return TRUE;
+}
+
+// virtual
+void LLSidepanelAppearance::onOpen(const LLSD& key)
+{
+ fetchInventory();
+ refreshCurrentOutfitName();
+ updateVerbs();
+
+ if (mPanelOutfitsInventory)
+ {
+ mPanelOutfitsInventory->onOpen(key);
+ }
+
+ if(key.size() == 0)
+ return;
+
+ toggleLookInfoPanel(TRUE);
+ updateVerbs();
+
+ mLookInfoType = key["type"].asString();
+
+ if (mLookInfoType == "look")
+ {
+ LLInventoryCategory *pLook = gInventory.getCategory(key["id"].asUUID());
+ if (pLook)
+ mLookInfo->displayLookInfo(pLook);
+ }
+}
+
+void LLSidepanelAppearance::onFilterEdit(const std::string& search_string)
+{
+ if (mFilterSubString != search_string)
+ {
+ mFilterSubString = search_string;
+
+ // Searches are case-insensitive
+ LLStringUtil::toUpper(mFilterSubString);
+ LLStringUtil::trimHead(mFilterSubString);
+
+ mPanelOutfitsInventory->onSearchEdit(mFilterSubString);
+ }
+}
+
+void LLSidepanelAppearance::onOpenOutfitButtonClicked()
+{
+ const LLViewerInventoryItem *outfit_link = LLAppearanceManager::getInstance()->getBaseOutfitLink();
+ if (!outfit_link)
+ return;
+ if (!outfit_link->getIsLinkType())
+ return;
+
+ LLAccordionCtrlTab* tab_outfits = mPanelOutfitsInventory->findChild<LLAccordionCtrlTab>("tab_outfits");
+ if (tab_outfits)
+ {
+ tab_outfits->changeOpenClose(FALSE);
+ LLInventoryPanel *inventory_panel = tab_outfits->findChild<LLInventoryPanel>("outfitslist_tab");
+ if (inventory_panel)
+ {
+ LLFolderView *folder = inventory_panel->getRootFolder();
+ LLFolderViewItem *outfit_folder = folder->getItemByID(outfit_link->getLinkedUUID());
+ if (outfit_folder)
+ {
+ outfit_folder->setOpen(!outfit_folder->isOpen());
+ folder->setSelectionFromRoot(outfit_folder,TRUE);
+ folder->scrollToShowSelection();
+ }
+ }
+ }
+}
+
+void LLSidepanelAppearance::onEditAppearanceButtonClicked()
+{
+ if (gAgentWearables.areWearablesLoaded())
+ {
+ gAgent.changeCameraToCustomizeAvatar();
+ }
+}
+
+void LLSidepanelAppearance::onEditButtonClicked()
+{
+ toggleLookInfoPanel(FALSE);
+ toggleWearableEditPanel(TRUE, NULL);
+ /*if (mLookInfo->getVisible())
+ {
+ }
+ else
+ {
+ mPanelOutfitsInventory->onEdit();
+ }*/
+}
+
+void LLSidepanelAppearance::onNewOutfitButtonClicked()
+{
+ if (!mLookInfo->getVisible())
+ {
+ mPanelOutfitsInventory->onSave();
+ }
+}
+
+
+void LLSidepanelAppearance::onBackButtonClicked()
+{
+ toggleLookInfoPanel(FALSE);
+}
+
+void LLSidepanelAppearance::onEditWearBackClicked()
+{
+ mEditWearable->saveChanges();
+ toggleWearableEditPanel(FALSE, NULL);
+ toggleLookInfoPanel(TRUE);
+}
+
+void LLSidepanelAppearance::toggleLookInfoPanel(BOOL visible)
+{
+ if (!mLookInfo)
+ return;
+
+ mLookInfo->setVisible(visible);
+ mPanelOutfitsInventory->setVisible(!visible);
+ mFilterEditor->setVisible(!visible);
+ mEditBtn->setVisible(!visible);
+ mNewOutfitBtn->setVisible(!visible);
+ mCurrOutfitPanel->setVisible(!visible);
+}
+
+void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *wearable)
+{
+ if (!wearable)
+ {
+ wearable = gAgentWearables.getWearable(WT_SHAPE, 0);
+ }
+ if (!mEditWearable || !wearable)
+ {
+ return;
+ }
+
+ mEditWearable->setVisible(visible);
+ mFilterEditor->setVisible(!visible);
+ mPanelOutfitsInventory->setVisible(!visible);
+}
+
+void LLSidepanelAppearance::updateVerbs()
+{
+ bool is_look_info_visible = mLookInfo->getVisible();
+
+ if (!is_look_info_visible)
+ {
+ const bool is_correct_type = (mPanelOutfitsInventory->getCorrectListenerForAction() != NULL);
+ mEditBtn->setEnabled(is_correct_type);
+ }
+ else
+ {
+ mEditBtn->setEnabled(FALSE);
+ }
+}
+
+void LLSidepanelAppearance::refreshCurrentOutfitName(const std::string& name)
+{
+ mOutfitDirtyTag->setVisible(LLAppearanceManager::getInstance()->isOutfitDirty());
+ if (name == "")
+ {
+ std::string outfit_name;
+ if (LLAppearanceManager::getInstance()->getBaseOutfitName(outfit_name))
+ {
+ mCurrentLookName->setText(outfit_name);
+ return;
+ }
+ mCurrentLookName->setText(getString("No Outfit"));
+ mOpenOutfitBtn->setEnabled(FALSE);
+ }
+ else
+ {
+ mCurrentLookName->setText(name);
+ // Can't just call update verbs since the folder link may not have been created yet.
+ mOpenOutfitBtn->setEnabled(TRUE);
+ }
+}
+
+//static
+void LLSidepanelAppearance::editWearable(LLWearable *wearable, void *data)
+{
+ LLSidepanelAppearance *panel = (LLSidepanelAppearance*) data;
+ panel->toggleLookInfoPanel(FALSE);
+ panel->toggleWearableEditPanel(TRUE, wearable);
+}
+
+// Fetch currently worn items and only enable the New Look button after everything's been
+// fetched. Alternatively, we could stuff this logic into llagentwearables::makeNewOutfitLinks.
+void LLSidepanelAppearance::fetchInventory()
+{
+
+ mNewOutfitBtn->setEnabled(false);
+ LLInventoryFetchObserver::item_ref_t ids;
+ LLUUID item_id;
+ for(S32 type = (S32)WT_SHAPE; type < (S32)WT_COUNT; ++type)
+ {
+ // MULTI_WEARABLE:
+ item_id = gAgentWearables.getWearableItemID((EWearableType)type,0);
+ if(item_id.notNull())
+ {
+ ids.push_back(item_id);
+ }
+ }
+
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if( avatar )
+ {
+ for (LLVOAvatar::attachment_map_t::const_iterator iter = avatar->mAttachmentPoints.begin();
+ iter != avatar->mAttachmentPoints.end(); ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+ if (!attachment) continue;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject* attached_object = (*attachment_iter);
+ if (!attached_object) continue;
+ const LLUUID& item_id = attached_object->getItemID();
+ if (item_id.isNull()) continue;
+ ids.push_back(item_id);
+ }
+ }
+ }
+
+ LLCurrentlyWornFetchObserver *fetch_worn = new LLCurrentlyWornFetchObserver(this);
+ fetch_worn->fetchItems(ids);
+ // If no items to be fetched, done will never be triggered.
+ // TODO: Change LLInventoryFetchObserver::fetchItems to trigger done() on this condition.
+ if (fetch_worn->isEverythingComplete())
+ {
+ fetch_worn->done();
+ }
+ else
+ {
+ gInventory.addObserver(fetch_worn);
+ }
+}
+
+void LLSidepanelAppearance::inventoryFetched()
+{
+ mNewOutfitBtn->setEnabled(true);
+}
diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h
new file mode 100644
index 0000000000..aa2e67fd16
--- /dev/null
+++ b/indra/newview/llsidepanelappearance.h
@@ -0,0 +1,106 @@
+/**
+ * @file llsidepanelappearance.h
+ * @brief Side Bar "Appearance" panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSIDEPANELAPPEARANCE_H
+#define LL_LLSIDEPANELAPPEARANCE_H
+
+#include "llpanel.h"
+#include "llinventoryobserver.h"
+
+#include "llinventory.h"
+#include "llpanellookinfo.h"
+
+class LLFilterEditor;
+class LLCurrentlyWornFetchObserver;
+class LLWatchForOutfitRenameObserver;
+class LLPanelEditWearable;
+class LLWearable;
+class LLPanelOutfitsInventory;
+
+class LLSidepanelAppearance : public LLPanel
+{
+public:
+ LLSidepanelAppearance();
+ virtual ~LLSidepanelAppearance();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ void refreshCurrentOutfitName(const std::string& name = "");
+
+ static void editWearable(LLWearable *wearable, void *data);
+
+ void fetchInventory();
+ void inventoryFetched();
+ void updateVerbs();
+ void onNewOutfitButtonClicked();
+
+private:
+ void onFilterEdit(const std::string& search_string);
+
+ void onOpenOutfitButtonClicked();
+ void onEditAppearanceButtonClicked();
+ void onEditButtonClicked();
+ void onBackButtonClicked();
+ void onEditWearBackClicked();
+ void toggleLookInfoPanel(BOOL visible);
+ void toggleWearableEditPanel(BOOL visible, LLWearable* wearable);
+
+ LLFilterEditor* mFilterEditor;
+ LLPanelOutfitsInventory* mPanelOutfitsInventory;
+ LLPanelLookInfo* mLookInfo;
+ LLPanelEditWearable* mEditWearable;
+
+ LLButton* mOpenOutfitBtn;
+ LLButton* mEditAppearanceBtn;
+ LLButton* mEditBtn;
+ LLButton* mNewOutfitBtn;
+ LLPanel* mCurrOutfitPanel;
+
+ LLTextBox* mCurrentLookName;
+ LLTextBox* mOutfitDirtyTag;
+
+ // Used to make sure the user's inventory is in memory.
+ LLCurrentlyWornFetchObserver* mFetchWorn;
+
+ // Used to update title when currently worn outfit gets renamed.
+ LLWatchForOutfitRenameObserver* mOutfitRenameWatcher;
+
+ // Search string for filtering landmarks and teleport
+ // history locations
+ std::string mFilterSubString;
+
+ // Information type currently shown in Look Information panel
+ std::string mLookInfoType;
+
+};
+
+#endif //LL_LLSIDEPANELAPPEARANCE_H
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
new file mode 100644
index 0000000000..5383158cd3
--- /dev/null
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -0,0 +1,303 @@
+/**
+ * @file LLSidepanelInventory.cpp
+ * @brief Side Bar "Inventory" panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llsidepanelinventory.h"
+
+#include "llagent.h"
+#include "llbutton.h"
+#include "llinventorybridge.h"
+#include "llinventorypanel.h"
+#include "llpanelmaininventory.h"
+#include "llsidepaneliteminfo.h"
+#include "llsidepaneltaskinfo.h"
+#include "lltabcontainer.h"
+#include "llselectmgr.h"
+
+static LLRegisterPanelClassWrapper<LLSidepanelInventory> t_inventory("sidepanel_inventory");
+
+LLSidepanelInventory::LLSidepanelInventory()
+ : LLPanel(),
+ mItemPanel(NULL),
+ mPanelMainInventory(NULL)
+{
+
+ //LLUICtrlFactory::getInstance()->buildPanel(this, "panel_inventory.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder()
+}
+
+LLSidepanelInventory::~LLSidepanelInventory()
+{
+}
+
+BOOL LLSidepanelInventory::postBuild()
+{
+ // UI elements from inventory panel
+ {
+ mInventoryPanel = getChild<LLPanel>("sidepanel__inventory_panel");
+
+ mInfoBtn = mInventoryPanel->getChild<LLButton>("info_btn");
+ mInfoBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onInfoButtonClicked, this));
+
+ mShareBtn = mInventoryPanel->getChild<LLButton>("share_btn");
+ mShareBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onShareButtonClicked, this));
+
+ mWearBtn = mInventoryPanel->getChild<LLButton>("wear_btn");
+ mWearBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onWearButtonClicked, this));
+
+ mPlayBtn = mInventoryPanel->getChild<LLButton>("play_btn");
+ mPlayBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onPlayButtonClicked, this));
+
+ mTeleportBtn = mInventoryPanel->getChild<LLButton>("teleport_btn");
+ mTeleportBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onTeleportButtonClicked, this));
+
+ mOverflowBtn = mInventoryPanel->getChild<LLButton>("overflow_btn");
+ mOverflowBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onOverflowButtonClicked, this));
+
+ mPanelMainInventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
+ mPanelMainInventory->setSelectCallback(boost::bind(&LLSidepanelInventory::onSelectionChange, this, _1, _2));
+ }
+
+ // UI elements from item panel
+ {
+ mItemPanel = getChild<LLSidepanelItemInfo>("sidepanel__item_panel");
+
+ LLButton* back_btn = mItemPanel->getChild<LLButton>("back_btn");
+ back_btn->setClickedCallback(boost::bind(&LLSidepanelInventory::onBackButtonClicked, this));
+ }
+
+ // UI elements from task panel
+ {
+ mTaskPanel = getChild<LLSidepanelTaskInfo>("sidepanel__task_panel");
+ if (mTaskPanel)
+ {
+ LLButton* back_btn = mTaskPanel->getChild<LLButton>("back_btn");
+ back_btn->setClickedCallback(boost::bind(&LLSidepanelInventory::onBackButtonClicked, this));
+ }
+ }
+
+ return TRUE;
+}
+
+void LLSidepanelInventory::onOpen(const LLSD& key)
+{
+ if(key.size() == 0)
+ return;
+
+ mItemPanel->reset();
+
+ if (key.has("id"))
+ {
+ mItemPanel->setItemID(key["id"].asUUID());
+ if (key.has("object"))
+ {
+ mItemPanel->setObjectID(key["object"].asUUID());
+ }
+ showItemInfoPanel();
+ }
+ if (key.has("task"))
+ {
+ if (mTaskPanel)
+ mTaskPanel->setObjectSelection(LLSelectMgr::getInstance()->getSelection());
+ showTaskInfoPanel();
+ }
+}
+
+void LLSidepanelInventory::onInfoButtonClicked()
+{
+ LLInventoryItem *item = getSelectedItem();
+ if (item)
+ {
+ mItemPanel->reset();
+ mItemPanel->setItemID(item->getUUID());
+ showItemInfoPanel();
+ }
+}
+
+void LLSidepanelInventory::onShareButtonClicked()
+{
+}
+
+void LLSidepanelInventory::performActionOnSelection(const std::string &action)
+{
+ LLPanelMainInventory *panel_main_inventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
+ LLFolderViewItem* current_item = panel_main_inventory->getActivePanel()->getRootFolder()->getCurSelectedItem();
+ if (!current_item)
+ {
+ return;
+ }
+ current_item->getListener()->performAction(panel_main_inventory->getActivePanel()->getRootFolder(), panel_main_inventory->getActivePanel()->getModel(), action);
+}
+
+void LLSidepanelInventory::onWearButtonClicked()
+{
+ performActionOnSelection("wear");
+ performActionOnSelection("attach");
+}
+
+void LLSidepanelInventory::onPlayButtonClicked()
+{
+ performActionOnSelection("activate");
+}
+
+void LLSidepanelInventory::onTeleportButtonClicked()
+{
+ performActionOnSelection("teleport");
+}
+
+void LLSidepanelInventory::onOverflowButtonClicked()
+{
+}
+
+void LLSidepanelInventory::onBackButtonClicked()
+{
+ showInventoryPanel();
+}
+
+void LLSidepanelInventory::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action)
+{
+ updateVerbs();
+}
+
+void LLSidepanelInventory::showItemInfoPanel()
+{
+ mItemPanel->setVisible(TRUE);
+ if (mTaskPanel)
+ mTaskPanel->setVisible(FALSE);
+ mInventoryPanel->setVisible(FALSE);
+
+ mItemPanel->dirty();
+ mItemPanel->setIsEditing(FALSE);
+}
+
+void LLSidepanelInventory::showTaskInfoPanel()
+{
+ mItemPanel->setVisible(FALSE);
+ mInventoryPanel->setVisible(FALSE);
+
+ if (mTaskPanel)
+ {
+ mTaskPanel->setVisible(TRUE);
+ mTaskPanel->dirty();
+ mTaskPanel->setIsEditing(FALSE);
+ }
+}
+
+void LLSidepanelInventory::showInventoryPanel()
+{
+ mItemPanel->setVisible(FALSE);
+ if (mTaskPanel)
+ mTaskPanel->setVisible(FALSE);
+ mInventoryPanel->setVisible(TRUE);
+ updateVerbs();
+}
+
+void LLSidepanelInventory::updateVerbs()
+{
+ mInfoBtn->setEnabled(FALSE);
+ mShareBtn->setEnabled(FALSE);
+
+ mWearBtn->setVisible(FALSE);
+ mWearBtn->setEnabled(FALSE);
+ mPlayBtn->setVisible(FALSE);
+ mPlayBtn->setEnabled(FALSE);
+ mTeleportBtn->setVisible(FALSE);
+ mTeleportBtn->setEnabled(FALSE);
+
+ const LLInventoryItem *item = getSelectedItem();
+ if (!item)
+ return;
+
+ bool is_single_selection = getSelectedCount() == 1;
+
+ mInfoBtn->setEnabled(is_single_selection);
+ mShareBtn->setEnabled(is_single_selection);
+
+ switch(item->getInventoryType())
+ {
+ case LLInventoryType::IT_WEARABLE:
+ case LLInventoryType::IT_OBJECT:
+ case LLInventoryType::IT_ATTACHMENT:
+ mWearBtn->setVisible(TRUE);
+ mWearBtn->setEnabled(TRUE);
+ break;
+ case LLInventoryType::IT_SOUND:
+ case LLInventoryType::IT_GESTURE:
+ case LLInventoryType::IT_ANIMATION:
+ mPlayBtn->setVisible(TRUE);
+ mPlayBtn->setEnabled(TRUE);
+ break;
+ case LLInventoryType::IT_LANDMARK:
+ mTeleportBtn->setVisible(TRUE);
+ mTeleportBtn->setEnabled(TRUE);
+ break;
+ default:
+ break;
+ }
+}
+
+LLInventoryItem *LLSidepanelInventory::getSelectedItem()
+{
+ LLPanelMainInventory *panel_main_inventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
+ LLFolderViewItem* current_item = panel_main_inventory->getActivePanel()->getRootFolder()->getCurSelectedItem();
+ if (!current_item)
+ {
+ return NULL;
+ }
+ const LLUUID &item_id = current_item->getListener()->getUUID();
+ LLInventoryItem *item = gInventory.getItem(item_id);
+ return item;
+}
+
+U32 LLSidepanelInventory::getSelectedCount()
+{
+ LLPanelMainInventory *panel_main_inventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
+ std::set<LLUUID> selection_list;
+ panel_main_inventory->getActivePanel()->getRootFolder()->getSelectionList(selection_list);
+ return selection_list.size();
+}
+
+LLInventoryPanel *LLSidepanelInventory::getActivePanel()
+{
+ if (!getVisible())
+ {
+ return NULL;
+ }
+ if (mInventoryPanel->getVisible())
+ {
+ return mPanelMainInventory->getActivePanel();
+ }
+ return NULL;
+}
+
+BOOL LLSidepanelInventory::isMainInventoryPanelActive() const
+{
+ return mInventoryPanel->getVisible();
+}
diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h
new file mode 100644
index 0000000000..ee11fb6b54
--- /dev/null
+++ b/indra/newview/llsidepanelinventory.h
@@ -0,0 +1,96 @@
+/**
+ * @file LLSidepanelInventory.h
+ * @brief Side Bar "Inventory" panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSIDEPANELINVENTORY_H
+#define LL_LLSIDEPANELINVENTORY_H
+
+#include "llpanel.h"
+
+class LLFolderViewItem;
+class LLInventoryItem;
+class LLInventoryPanel;
+class LLPanelMainInventory;
+class LLSidepanelItemInfo;
+class LLSidepanelTaskInfo;
+
+class LLSidepanelInventory : public LLPanel
+{
+public:
+ LLSidepanelInventory();
+ virtual ~LLSidepanelInventory();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ LLInventoryPanel* getActivePanel(); // Returns an active inventory panel, if any.
+ BOOL isMainInventoryPanelActive() const;
+
+protected:
+ // Tracks highlighted (selected) item in inventory panel.
+ LLInventoryItem *getSelectedItem();
+ U32 getSelectedCount();
+ void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
+ // "wear", "teleport", etc.
+ void performActionOnSelection(const std::string &action);
+
+ void showItemInfoPanel();
+ void showTaskInfoPanel();
+ void showInventoryPanel();
+ void updateVerbs();
+
+ //
+ // UI Elements
+ //
+private:
+ LLPanel* mInventoryPanel; // Main inventory view
+ LLSidepanelItemInfo* mItemPanel; // Individual item view
+ LLSidepanelTaskInfo* mTaskPanel; // Individual in-world object view
+ LLPanelMainInventory* mPanelMainInventory;
+
+protected:
+ void onInfoButtonClicked();
+ void onShareButtonClicked();
+ void onWearButtonClicked();
+ void onPlayButtonClicked();
+ void onTeleportButtonClicked();
+ void onOverflowButtonClicked();
+ void onBackButtonClicked();
+private:
+ LLButton* mInfoBtn;
+ LLButton* mShareBtn;
+ LLButton* mWearBtn;
+ LLButton* mPlayBtn;
+ LLButton* mTeleportBtn;
+ LLButton* mOverflowBtn;
+
+};
+
+#endif //LL_LLSIDEPANELINVENTORY_H
diff --git a/indra/newview/llsidepanelinventorysubpanel.cpp b/indra/newview/llsidepanelinventorysubpanel.cpp
new file mode 100644
index 0000000000..56e342c3ce
--- /dev/null
+++ b/indra/newview/llsidepanelinventorysubpanel.cpp
@@ -0,0 +1,152 @@
+/**
+ * @file llsidepanelinventorysubpanel.cpp
+ * @brief A floater which shows an inventory item's properties.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llsidepanelinventorysubpanel.h"
+
+#include "roles_constants.h"
+
+#include "llagent.h"
+#include "llavataractions.h"
+#include "llbutton.h"
+#include "llfloaterreg.h"
+#include "llgroupactions.h"
+#include "llinventorymodel.h"
+#include "lllineeditor.h"
+#include "llradiogroup.h"
+#include "llviewercontrol.h"
+#include "llviewerinventory.h"
+#include "llviewerobjectlist.h"
+
+
+///----------------------------------------------------------------------------
+/// Class LLSidepanelInventorySubpanel
+///----------------------------------------------------------------------------
+
+// Default constructor
+LLSidepanelInventorySubpanel::LLSidepanelInventorySubpanel()
+ : LLPanel(),
+ mIsDirty(TRUE),
+ mIsEditing(FALSE),
+ mCancelBtn(NULL),
+ mSaveBtn(NULL)
+{
+}
+
+// Destroys the object
+LLSidepanelInventorySubpanel::~LLSidepanelInventorySubpanel()
+{
+}
+
+// virtual
+BOOL LLSidepanelInventorySubpanel::postBuild()
+{
+ mSaveBtn = getChild<LLButton>("save_btn");
+ mSaveBtn->setClickedCallback(boost::bind(&LLSidepanelInventorySubpanel::onSaveButtonClicked, this));
+
+ mCancelBtn = getChild<LLButton>("cancel_btn");
+ mCancelBtn->setClickedCallback(boost::bind(&LLSidepanelInventorySubpanel::onCancelButtonClicked, this));
+ return TRUE;
+}
+
+void LLSidepanelInventorySubpanel::setVisible(BOOL visible)
+{
+ if (visible)
+ {
+ dirty();
+ }
+ LLPanel::setVisible(visible);
+}
+
+void LLSidepanelInventorySubpanel::setIsEditing(BOOL edit)
+{
+ mIsEditing = edit;
+ mIsDirty = TRUE;
+}
+
+BOOL LLSidepanelInventorySubpanel::getIsEditing() const
+{
+
+ return TRUE; // Default everything to edit mode since we're not using an edit button anymore.
+ // return mIsEditing;
+}
+
+void LLSidepanelInventorySubpanel::reset()
+{
+ mIsDirty = TRUE;
+}
+
+void LLSidepanelInventorySubpanel::draw()
+{
+ if (mIsDirty)
+ {
+ refresh();
+ updateVerbs();
+ mIsDirty = FALSE;
+ }
+
+ LLPanel::draw();
+}
+
+void LLSidepanelInventorySubpanel::dirty()
+{
+ mIsDirty = TRUE;
+ setIsEditing(FALSE);
+}
+
+void LLSidepanelInventorySubpanel::updateVerbs()
+{
+ mSaveBtn->setVisible(mIsEditing);
+ mCancelBtn->setVisible(mIsEditing);
+}
+
+void LLSidepanelInventorySubpanel::onEditButtonClicked()
+{
+ setIsEditing(TRUE);
+ refresh();
+ updateVerbs();
+}
+
+void LLSidepanelInventorySubpanel::onSaveButtonClicked()
+{
+ save();
+ setIsEditing(FALSE);
+ refresh();
+ updateVerbs();
+}
+
+void LLSidepanelInventorySubpanel::onCancelButtonClicked()
+{
+ setIsEditing(FALSE);
+ refresh();
+ updateVerbs();
+}
diff --git a/indra/newview/llsidepanelinventorysubpanel.h b/indra/newview/llsidepanelinventorysubpanel.h
new file mode 100644
index 0000000000..b7bee6809f
--- /dev/null
+++ b/indra/newview/llsidepanelinventorysubpanel.h
@@ -0,0 +1,81 @@
+/**
+ * @file llsidepanelinventorysubpanel.h
+ * @brief A panel which shows an inventory item's properties.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSIDEPANELINVENTORYSUBPANEL_H
+#define LL_LLSIDEPANELINVENTORYSUBPANEL_H
+
+#include "llpanel.h"
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLSidepanelInventorySubpanel
+// Base class for inventory sidepanel panels (e.g. item info, task info).
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLButton;
+class LLInventoryItem;
+
+class LLSidepanelInventorySubpanel : public LLPanel
+{
+public:
+ LLSidepanelInventorySubpanel();
+ virtual ~LLSidepanelInventorySubpanel();
+
+ /*virtual*/ void setVisible(BOOL visible);
+ virtual BOOL postBuild();
+ virtual void draw();
+ virtual void reset();
+
+ void dirty();
+ void setIsEditing(BOOL edit);
+protected:
+ virtual void refresh() = 0;
+ virtual void save() = 0;
+ virtual void updateVerbs();
+
+ BOOL getIsEditing() const;
+
+ //
+ // UI Elements
+ //
+protected:
+ void onEditButtonClicked();
+ void onSaveButtonClicked();
+ void onCancelButtonClicked();
+ LLButton* mSaveBtn;
+ LLButton* mCancelBtn;
+
+private:
+ BOOL mIsDirty; // item properties need to be updated
+ BOOL mIsEditing; // if we're in edit mode
+};
+
+#endif // LL_LLSIDEPANELINVENTORYSUBPANEL_H
diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp
new file mode 100644
index 0000000000..94fe95d215
--- /dev/null
+++ b/indra/newview/llsidepaneliteminfo.cpp
@@ -0,0 +1,939 @@
+/**
+ * @file llsidepaneliteminfo.cpp
+ * @brief A floater which shows an inventory item's properties.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llsidepaneliteminfo.h"
+
+#include "roles_constants.h"
+
+#include "llagent.h"
+#include "llavataractions.h"
+#include "llbutton.h"
+#include "llfloaterreg.h"
+#include "llgroupactions.h"
+#include "llinventorymodel.h"
+#include "llinventoryobserver.h"
+#include "lllineeditor.h"
+#include "llradiogroup.h"
+#include "llviewercontrol.h"
+#include "llviewerinventory.h"
+#include "llviewerobjectlist.h"
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLItemPropertiesObserver
+//
+// Helper class to watch for changes to the item.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLItemPropertiesObserver : public LLInventoryObserver
+{
+public:
+ LLItemPropertiesObserver(LLSidepanelItemInfo* floater)
+ : mFloater(floater)
+ {
+ gInventory.addObserver(this);
+ }
+ virtual ~LLItemPropertiesObserver()
+ {
+ gInventory.removeObserver(this);
+ }
+ virtual void changed(U32 mask);
+private:
+ LLSidepanelItemInfo* mFloater;
+};
+
+void LLItemPropertiesObserver::changed(U32 mask)
+{
+ // if there's a change we're interested in.
+ if((mask & (LLInventoryObserver::LABEL | LLInventoryObserver::INTERNAL | LLInventoryObserver::REMOVE)) != 0)
+ {
+ mFloater->dirty();
+ }
+}
+
+
+
+///----------------------------------------------------------------------------
+/// Class LLSidepanelItemInfo
+///----------------------------------------------------------------------------
+
+static LLRegisterPanelClassWrapper<LLSidepanelItemInfo> t_item_info("sidepanel_item_info");
+
+// Default constructor
+LLSidepanelItemInfo::LLSidepanelItemInfo()
+ : mItemID(LLUUID::null)
+{
+ mPropertiesObserver = new LLItemPropertiesObserver(this);
+
+ //LLUICtrlFactory::getInstance()->buildFloater(this,"floater_inventory_item_properties.xml");
+}
+
+// Destroys the object
+LLSidepanelItemInfo::~LLSidepanelItemInfo()
+{
+ delete mPropertiesObserver;
+ mPropertiesObserver = NULL;
+}
+
+// virtual
+BOOL LLSidepanelItemInfo::postBuild()
+{
+ LLSidepanelInventorySubpanel::postBuild();
+
+ childSetPrevalidate("LabelItemName",&LLLineEditor::prevalidateASCIIPrintableNoPipe);
+ getChild<LLUICtrl>("LabelItemName")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitName,this));
+ childSetPrevalidate("LabelItemDesc",&LLLineEditor::prevalidateASCIIPrintableNoPipe);
+ getChild<LLUICtrl>("LabelItemDesc")->setCommitCallback(boost::bind(&LLSidepanelItemInfo:: onCommitDescription, this));
+ // Creator information
+ getChild<LLUICtrl>("BtnCreator")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onClickCreator,this));
+ // owner information
+ getChild<LLUICtrl>("BtnOwner")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onClickOwner,this));
+ // acquired date
+ // owner permissions
+ // Permissions debug text
+ // group permissions
+ getChild<LLUICtrl>("CheckShareWithGroup")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
+ // everyone permissions
+ getChild<LLUICtrl>("CheckEveryoneCopy")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
+ // next owner permissions
+ getChild<LLUICtrl>("CheckNextOwnerModify")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
+ getChild<LLUICtrl>("CheckNextOwnerCopy")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
+ getChild<LLUICtrl>("CheckNextOwnerTransfer")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
+ // Mark for sale or not, and sale info
+ getChild<LLUICtrl>("CheckPurchase")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this));
+ getChild<LLUICtrl>("RadioSaleType")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleType, this));
+ // "Price" label for edit
+ getChild<LLUICtrl>("Edit Cost")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this));
+ refresh();
+ return TRUE;
+}
+
+void LLSidepanelItemInfo::setObjectID(const LLUUID& object_id)
+{
+ mObjectID = object_id;
+}
+
+void LLSidepanelItemInfo::setItemID(const LLUUID& item_id)
+{
+ mItemID = item_id;
+}
+
+void LLSidepanelItemInfo::reset()
+{
+ LLSidepanelInventorySubpanel::reset();
+
+ mObjectID = LLUUID::null;
+ mItemID = LLUUID::null;
+}
+
+void LLSidepanelItemInfo::refresh()
+{
+ LLViewerInventoryItem* item = findItem();
+ if(item)
+ {
+ refreshFromItem(item);
+ updateVerbs();
+ return;
+ }
+ else
+ {
+ if (getIsEditing())
+ {
+ setIsEditing(FALSE);
+ }
+ }
+
+ if (!getIsEditing())
+ {
+ const std::string no_item_names[]={
+ "LabelItemName",
+ "LabelItemDesc",
+ "LabelCreatorName",
+ "LabelOwnerName",
+ "CheckOwnerModify",
+ "CheckOwnerCopy",
+ "CheckOwnerTransfer",
+ "CheckShareWithGroup",
+ "CheckEveryoneCopy",
+ "CheckNextOwnerModify",
+ "CheckNextOwnerCopy",
+ "CheckNextOwnerTransfer",
+ "CheckPurchase",
+ "RadioSaleType",
+ "Edit Cost"
+ };
+
+ for(size_t t=0; t<LL_ARRAY_SIZE(no_item_names); ++t)
+ {
+ childSetEnabled(no_item_names[t],false);
+ }
+
+ const std::string hide_names[]={
+ "BaseMaskDebug",
+ "OwnerMaskDebug",
+ "GroupMaskDebug",
+ "EveryoneMaskDebug",
+ "NextMaskDebug"
+ };
+ for(size_t t=0; t<LL_ARRAY_SIZE(hide_names); ++t)
+ {
+ childSetVisible(hide_names[t],false);
+ }
+ }
+
+ if (!item)
+ {
+ const std::string no_edit_mode_names[]={
+ "BtnCreator",
+ "BtnOwner",
+ };
+ for(size_t t=0; t<LL_ARRAY_SIZE(no_edit_mode_names); ++t)
+ {
+ childSetEnabled(no_edit_mode_names[t],false);
+ }
+ }
+
+ updateVerbs();
+}
+
+void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item)
+{
+ ////////////////////////
+ // PERMISSIONS LOOKUP //
+ ////////////////////////
+
+ // do not enable the UI for incomplete items.
+ BOOL is_complete = item->isComplete();
+ const BOOL cannot_restrict_permissions = LLInventoryType::cannotRestrictPermissions(item->getInventoryType());
+ const BOOL is_calling_card = (item->getInventoryType() == LLInventoryType::IT_CALLINGCARD);
+ const LLPermissions& perm = item->getPermissions();
+ const BOOL can_agent_manipulate = gAgent.allowOperation(PERM_OWNER, perm,
+ GP_OBJECT_MANIPULATE);
+ const BOOL can_agent_sell = gAgent.allowOperation(PERM_OWNER, perm,
+ GP_OBJECT_SET_SALE) &&
+ !cannot_restrict_permissions;
+ const BOOL is_link = item->getIsLinkType();
+
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ bool not_in_trash = item && (item->getUUID() != trash_id) && !gInventory.isObjectDescendentOf(item->getUUID(), trash_id);
+
+ // You need permission to modify the object to modify an inventory
+ // item in it.
+ LLViewerObject* object = NULL;
+ if(!mObjectID.isNull()) object = gObjectList.findObject(mObjectID);
+ BOOL is_obj_modify = TRUE;
+ if(object)
+ {
+ is_obj_modify = object->permOwnerModify();
+ }
+
+ //////////////////////
+ // ITEM NAME & DESC //
+ //////////////////////
+ BOOL is_modifiable = gAgent.allowOperation(PERM_MODIFY, perm,
+ GP_OBJECT_MANIPULATE)
+ && is_obj_modify && is_complete && not_in_trash;
+
+ childSetEnabled("LabelItemNameTitle",TRUE);
+ childSetEnabled("LabelItemName",is_modifiable && !is_calling_card); // for now, don't allow rename of calling cards
+ childSetText("LabelItemName",item->getName());
+ childSetEnabled("LabelItemDescTitle",TRUE);
+ childSetEnabled("LabelItemDesc",is_modifiable);
+ childSetVisible("IconLocked",!is_modifiable);
+ childSetText("LabelItemDesc",item->getDescription());
+
+ //////////////////
+ // CREATOR NAME //
+ //////////////////
+ if(!gCacheName) return;
+ if(!gAgent.getRegion()) return;
+
+ if (item->getCreatorUUID().notNull())
+ {
+ std::string name;
+ gCacheName->getFullName(item->getCreatorUUID(), name);
+ childSetEnabled("BtnCreator",TRUE);
+ childSetEnabled("LabelCreatorTitle",TRUE);
+ childSetEnabled("LabelCreatorName",TRUE);
+ childSetText("LabelCreatorName",name);
+ }
+ else
+ {
+ childSetEnabled("BtnCreator",FALSE);
+ childSetEnabled("LabelCreatorTitle",FALSE);
+ childSetEnabled("LabelCreatorName",FALSE);
+ childSetText("LabelCreatorName",getString("unknown"));
+ }
+
+ ////////////////
+ // OWNER NAME //
+ ////////////////
+ if(perm.isOwned())
+ {
+ std::string name;
+ if (perm.isGroupOwned())
+ {
+ gCacheName->getGroupName(perm.getGroup(), name);
+ }
+ else
+ {
+ gCacheName->getFullName(perm.getOwner(), name);
+ }
+ childSetEnabled("BtnOwner",TRUE);
+ childSetEnabled("LabelOwnerTitle",TRUE);
+ childSetEnabled("LabelOwnerName",TRUE);
+ childSetText("LabelOwnerName",name);
+ }
+ else
+ {
+ childSetEnabled("BtnOwner",FALSE);
+ childSetEnabled("LabelOwnerTitle",FALSE);
+ childSetEnabled("LabelOwnerName",FALSE);
+ childSetText("LabelOwnerName",getString("public"));
+ }
+
+ //////////////////
+ // ACQUIRE DATE //
+ //////////////////
+
+ time_t time_utc = item->getCreationDate();
+ if (0 == time_utc)
+ {
+ childSetText("LabelAcquiredDate",getString("unknown"));
+ }
+ else
+ {
+ std::string timeStr = getString("acquiredDate");
+ LLSD substitution;
+ substitution["datetime"] = (S32) time_utc;
+ LLStringUtil::format (timeStr, substitution);
+ childSetText ("LabelAcquiredDate", timeStr);
+ }
+
+ /////////////////////////////////////
+ // PERMISSIONS AND SALE ITEM HIDING
+ /////////////////////////////////////
+
+ const std::string perm_and_sale_items[]={
+ "perms_inv",
+ "OwnerLabel",
+ "perm_modify",
+ "CheckOwnerModify",
+ "CheckOwnerCopy",
+ "CheckOwnerTransfer",
+ "GroupLabel",
+ "CheckShareWithGroup",
+ "AnyoneLabel",
+ "CheckEveryoneCopy",
+ "NextOwnerLabel",
+ "CheckNextOwnerModify",
+ "CheckNextOwnerCopy",
+ "CheckNextOwnerTransfer",
+ "CheckPurchase",
+ "SaleLabel",
+ "RadioSaleType",
+ "combobox sale copy",
+ "Edit Cost",
+ "TextPrice"
+ };
+
+ const std::string debug_items[]={
+ "BaseMaskDebug",
+ "OwnerMaskDebug",
+ "GroupMaskDebug",
+ "EveryoneMaskDebug",
+ "NextMaskDebug"
+ };
+
+ // Hide permissions checkboxes and labels and for sale info if in the trash
+ // or ui elements don't apply to these objects and return from function
+ if (!not_in_trash || cannot_restrict_permissions)
+ {
+ for(size_t t=0; t<LL_ARRAY_SIZE(perm_and_sale_items); ++t)
+ {
+ childSetVisible(perm_and_sale_items[t],false);
+ }
+
+ for(size_t t=0; t<LL_ARRAY_SIZE(debug_items); ++t)
+ {
+ childSetVisible(debug_items[t],false);
+ }
+ return;
+ }
+ else // Make sure perms and sale ui elements are visible
+ {
+ for(size_t t=0; t<LL_ARRAY_SIZE(perm_and_sale_items); ++t)
+ {
+ childSetVisible(perm_and_sale_items[t],true);
+ }
+ }
+
+ ///////////////////////
+ // OWNER PERMISSIONS //
+ ///////////////////////
+ if(can_agent_manipulate)
+ {
+ childSetText("OwnerLabel",getString("you_can"));
+ }
+ else
+ {
+ childSetText("OwnerLabel",getString("owner_can"));
+ }
+
+ U32 base_mask = perm.getMaskBase();
+ U32 owner_mask = perm.getMaskOwner();
+ U32 group_mask = perm.getMaskGroup();
+ U32 everyone_mask = perm.getMaskEveryone();
+ U32 next_owner_mask = perm.getMaskNextOwner();
+
+ childSetEnabled("OwnerLabel",TRUE);
+ childSetEnabled("CheckOwnerModify",FALSE);
+ childSetValue("CheckOwnerModify",LLSD((BOOL)(owner_mask & PERM_MODIFY)));
+ childSetEnabled("CheckOwnerCopy",FALSE);
+ childSetValue("CheckOwnerCopy",LLSD((BOOL)(owner_mask & PERM_COPY)));
+ childSetEnabled("CheckOwnerTransfer",FALSE);
+ childSetValue("CheckOwnerTransfer",LLSD((BOOL)(owner_mask & PERM_TRANSFER)));
+
+ ///////////////////////
+ // DEBUG PERMISSIONS //
+ ///////////////////////
+
+ if( gSavedSettings.getBOOL("DebugPermissions") )
+ {
+ BOOL slam_perm = FALSE;
+ BOOL overwrite_group = FALSE;
+ BOOL overwrite_everyone = FALSE;
+
+ if (item->getType() == LLAssetType::AT_OBJECT)
+ {
+ U32 flags = item->getFlags();
+ slam_perm = flags & LLInventoryItem::II_FLAGS_OBJECT_SLAM_PERM;
+ overwrite_everyone = flags & LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE;
+ overwrite_group = flags & LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
+ }
+
+ std::string perm_string;
+
+ perm_string = "B: ";
+ perm_string += mask_to_string(base_mask);
+ childSetText("BaseMaskDebug",perm_string);
+ childSetVisible("BaseMaskDebug",TRUE);
+
+ perm_string = "O: ";
+ perm_string += mask_to_string(owner_mask);
+ childSetText("OwnerMaskDebug",perm_string);
+ childSetVisible("OwnerMaskDebug",TRUE);
+
+ perm_string = "G";
+ perm_string += overwrite_group ? "*: " : ": ";
+ perm_string += mask_to_string(group_mask);
+ childSetText("GroupMaskDebug",perm_string);
+ childSetVisible("GroupMaskDebug",TRUE);
+
+ perm_string = "E";
+ perm_string += overwrite_everyone ? "*: " : ": ";
+ perm_string += mask_to_string(everyone_mask);
+ childSetText("EveryoneMaskDebug",perm_string);
+ childSetVisible("EveryoneMaskDebug",TRUE);
+
+ perm_string = "N";
+ perm_string += slam_perm ? "*: " : ": ";
+ perm_string += mask_to_string(next_owner_mask);
+ childSetText("NextMaskDebug",perm_string);
+ childSetVisible("NextMaskDebug",TRUE);
+ }
+ else
+ {
+ childSetVisible("BaseMaskDebug",FALSE);
+ childSetVisible("OwnerMaskDebug",FALSE);
+ childSetVisible("GroupMaskDebug",FALSE);
+ childSetVisible("EveryoneMaskDebug",FALSE);
+ childSetVisible("NextMaskDebug",FALSE);
+ }
+
+ /////////////
+ // SHARING //
+ /////////////
+
+ // Check for ability to change values.
+ if (is_link || cannot_restrict_permissions)
+ {
+ childSetEnabled("CheckShareWithGroup",FALSE);
+ childSetEnabled("CheckEveryoneCopy",FALSE);
+ }
+ else if (is_obj_modify && can_agent_manipulate)
+ {
+ childSetEnabled("CheckShareWithGroup",TRUE);
+ childSetEnabled("CheckEveryoneCopy",(owner_mask & PERM_COPY) && (owner_mask & PERM_TRANSFER));
+ }
+ else
+ {
+ childSetEnabled("CheckShareWithGroup",FALSE);
+ childSetEnabled("CheckEveryoneCopy",FALSE);
+ }
+
+ // Set values.
+ BOOL is_group_copy = (group_mask & PERM_COPY) ? TRUE : FALSE;
+ BOOL is_group_modify = (group_mask & PERM_MODIFY) ? TRUE : FALSE;
+ BOOL is_group_move = (group_mask & PERM_MOVE) ? TRUE : FALSE;
+
+ if (is_group_copy && is_group_modify && is_group_move)
+ {
+ childSetValue("CheckShareWithGroup",LLSD((BOOL)TRUE));
+
+ LLCheckBoxCtrl* ctl = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
+ if(ctl)
+ {
+ ctl->setTentative(FALSE);
+ }
+ }
+ else if (!is_group_copy && !is_group_modify && !is_group_move)
+ {
+ childSetValue("CheckShareWithGroup",LLSD((BOOL)FALSE));
+ LLCheckBoxCtrl* ctl = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
+ if(ctl)
+ {
+ ctl->setTentative(FALSE);
+ }
+ }
+ else
+ {
+ LLCheckBoxCtrl* ctl = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
+ if(ctl)
+ {
+ ctl->setTentative(TRUE);
+ ctl->set(TRUE);
+ }
+ }
+
+ childSetValue("CheckEveryoneCopy",LLSD((BOOL)(everyone_mask & PERM_COPY)));
+
+ ///////////////
+ // SALE INFO //
+ ///////////////
+
+ const LLSaleInfo& sale_info = item->getSaleInfo();
+ BOOL is_for_sale = sale_info.isForSale();
+ // Check for ability to change values.
+ if (is_obj_modify && can_agent_sell
+ && gAgent.allowOperation(PERM_TRANSFER, perm, GP_OBJECT_MANIPULATE))
+ {
+ childSetEnabled("SaleLabel",is_complete);
+ childSetEnabled("CheckPurchase",is_complete);
+
+ childSetEnabled("NextOwnerLabel",TRUE);
+ childSetEnabled("CheckNextOwnerModify",(base_mask & PERM_MODIFY) && !cannot_restrict_permissions);
+ childSetEnabled("CheckNextOwnerCopy",(base_mask & PERM_COPY) && !cannot_restrict_permissions);
+ childSetEnabled("CheckNextOwnerTransfer",(next_owner_mask & PERM_COPY) && !cannot_restrict_permissions);
+
+ childSetEnabled("RadioSaleType",is_complete && is_for_sale);
+ childSetEnabled("TextPrice",is_complete && is_for_sale);
+ childSetEnabled("Edit Cost",is_complete && is_for_sale);
+ }
+ else
+ {
+ childSetEnabled("SaleLabel",FALSE);
+ childSetEnabled("CheckPurchase",FALSE);
+
+ childSetEnabled("NextOwnerLabel",FALSE);
+ childSetEnabled("CheckNextOwnerModify",FALSE);
+ childSetEnabled("CheckNextOwnerCopy",FALSE);
+ childSetEnabled("CheckNextOwnerTransfer",FALSE);
+
+ childSetEnabled("RadioSaleType",FALSE);
+ childSetEnabled("TextPrice",FALSE);
+ childSetEnabled("Edit Cost",FALSE);
+ }
+
+ // Set values.
+ childSetValue("CheckPurchase", is_for_sale);
+ childSetEnabled("combobox sale copy", is_for_sale);
+ childSetEnabled("Edit Cost", is_for_sale);
+ childSetValue("CheckNextOwnerModify",LLSD(BOOL(next_owner_mask & PERM_MODIFY)));
+ childSetValue("CheckNextOwnerCopy",LLSD(BOOL(next_owner_mask & PERM_COPY)));
+ childSetValue("CheckNextOwnerTransfer",LLSD(BOOL(next_owner_mask & PERM_TRANSFER)));
+
+ LLRadioGroup* radioSaleType = getChild<LLRadioGroup>("RadioSaleType");
+ if (is_for_sale)
+ {
+ radioSaleType->setSelectedIndex((S32)sale_info.getSaleType() - 1);
+ S32 numerical_price;
+ numerical_price = sale_info.getSalePrice();
+ childSetText("Edit Cost",llformat("%d",numerical_price));
+ }
+ else
+ {
+ radioSaleType->setSelectedIndex(-1);
+ childSetText("Edit Cost",llformat("%d",0));
+ }
+}
+
+void LLSidepanelItemInfo::onClickCreator()
+{
+ LLViewerInventoryItem* item = findItem();
+ if(!item) return;
+ if(!item->getCreatorUUID().isNull())
+ {
+ LLAvatarActions::showProfile(item->getCreatorUUID());
+ }
+}
+
+// static
+void LLSidepanelItemInfo::onClickOwner()
+{
+ LLViewerInventoryItem* item = findItem();
+ if(!item) return;
+ if(item->getPermissions().isGroupOwned())
+ {
+ LLGroupActions::show(item->getPermissions().getGroup());
+ }
+ else
+ {
+ LLAvatarActions::showProfile(item->getPermissions().getOwner());
+ }
+}
+
+// static
+void LLSidepanelItemInfo::onCommitName()
+{
+ //llinfos << "LLSidepanelItemInfo::onCommitName()" << llendl;
+ LLViewerInventoryItem* item = findItem();
+ if(!item)
+ {
+ return;
+ }
+ LLLineEditor* labelItemName = getChild<LLLineEditor>("LabelItemName");
+
+ if(labelItemName&&
+ (item->getName() != labelItemName->getText()) &&
+ (gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE)) )
+ {
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ new_item->rename(labelItemName->getText());
+ if(mObjectID.isNull())
+ {
+ new_item->updateServer(FALSE);
+ gInventory.updateItem(new_item);
+ gInventory.notifyObservers();
+ }
+ else
+ {
+ LLViewerObject* object = gObjectList.findObject(mObjectID);
+ if(object)
+ {
+ object->updateInventory(
+ new_item,
+ TASK_INVENTORY_ITEM_KEY,
+ false);
+ }
+ }
+ }
+}
+
+void LLSidepanelItemInfo::onCommitDescription()
+{
+ //llinfos << "LLSidepanelItemInfo::onCommitDescription()" << llendl;
+ LLViewerInventoryItem* item = findItem();
+ if(!item) return;
+
+ LLLineEditor* labelItemDesc = getChild<LLLineEditor>("LabelItemDesc");
+ if(!labelItemDesc)
+ {
+ return;
+ }
+ if((item->getDescription() != labelItemDesc->getText()) &&
+ (gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE)))
+ {
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+
+ new_item->setDescription(labelItemDesc->getText());
+ if(mObjectID.isNull())
+ {
+ new_item->updateServer(FALSE);
+ gInventory.updateItem(new_item);
+ gInventory.notifyObservers();
+ }
+ else
+ {
+ LLViewerObject* object = gObjectList.findObject(mObjectID);
+ if(object)
+ {
+ object->updateInventory(
+ new_item,
+ TASK_INVENTORY_ITEM_KEY,
+ false);
+ }
+ }
+ }
+}
+
+// static
+void LLSidepanelItemInfo::onCommitPermissions()
+{
+ //llinfos << "LLSidepanelItemInfo::onCommitPermissions()" << llendl;
+ LLViewerInventoryItem* item = findItem();
+ if(!item) return;
+ LLPermissions perm(item->getPermissions());
+
+
+ LLCheckBoxCtrl* CheckShareWithGroup = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
+
+ if(CheckShareWithGroup)
+ {
+ perm.setGroupBits(gAgent.getID(), gAgent.getGroupID(),
+ CheckShareWithGroup->get(),
+ PERM_MODIFY | PERM_MOVE | PERM_COPY);
+ }
+ LLCheckBoxCtrl* CheckEveryoneCopy = getChild<LLCheckBoxCtrl>("CheckEveryoneCopy");
+ if(CheckEveryoneCopy)
+ {
+ perm.setEveryoneBits(gAgent.getID(), gAgent.getGroupID(),
+ CheckEveryoneCopy->get(), PERM_COPY);
+ }
+
+ LLCheckBoxCtrl* CheckNextOwnerModify = getChild<LLCheckBoxCtrl>("CheckNextOwnerModify");
+ if(CheckNextOwnerModify)
+ {
+ perm.setNextOwnerBits(gAgent.getID(), gAgent.getGroupID(),
+ CheckNextOwnerModify->get(), PERM_MODIFY);
+ }
+ LLCheckBoxCtrl* CheckNextOwnerCopy = getChild<LLCheckBoxCtrl>("CheckNextOwnerCopy");
+ if(CheckNextOwnerCopy)
+ {
+ perm.setNextOwnerBits(gAgent.getID(), gAgent.getGroupID(),
+ CheckNextOwnerCopy->get(), PERM_COPY);
+ }
+ LLCheckBoxCtrl* CheckNextOwnerTransfer = getChild<LLCheckBoxCtrl>("CheckNextOwnerTransfer");
+ if(CheckNextOwnerTransfer)
+ {
+ perm.setNextOwnerBits(gAgent.getID(), gAgent.getGroupID(),
+ CheckNextOwnerTransfer->get(), PERM_TRANSFER);
+ }
+ if(perm != item->getPermissions()
+ && item->isComplete())
+ {
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ new_item->setPermissions(perm);
+ U32 flags = new_item->getFlags();
+ // If next owner permissions have changed (and this is an object)
+ // then set the slam permissions flag so that they are applied on rez.
+ if((perm.getMaskNextOwner()!=item->getPermissions().getMaskNextOwner())
+ && (item->getType() == LLAssetType::AT_OBJECT))
+ {
+ flags |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_PERM;
+ }
+ // If everyone permissions have changed (and this is an object)
+ // then set the overwrite everyone permissions flag so they
+ // are applied on rez.
+ if ((perm.getMaskEveryone()!=item->getPermissions().getMaskEveryone())
+ && (item->getType() == LLAssetType::AT_OBJECT))
+ {
+ flags |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE;
+ }
+ // If group permissions have changed (and this is an object)
+ // then set the overwrite group permissions flag so they
+ // are applied on rez.
+ if ((perm.getMaskGroup()!=item->getPermissions().getMaskGroup())
+ && (item->getType() == LLAssetType::AT_OBJECT))
+ {
+ flags |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
+ }
+ new_item->setFlags(flags);
+ if(mObjectID.isNull())
+ {
+ new_item->updateServer(FALSE);
+ gInventory.updateItem(new_item);
+ gInventory.notifyObservers();
+ }
+ else
+ {
+ LLViewerObject* object = gObjectList.findObject(mObjectID);
+ if(object)
+ {
+ object->updateInventory(
+ new_item,
+ TASK_INVENTORY_ITEM_KEY,
+ false);
+ }
+ }
+ }
+ else
+ {
+ // need to make sure we don't just follow the click
+ refresh();
+ }
+}
+
+// static
+void LLSidepanelItemInfo::onCommitSaleInfo()
+{
+ //llinfos << "LLSidepanelItemInfo::onCommitSaleInfo()" << llendl;
+ updateSaleInfo();
+}
+
+// static
+void LLSidepanelItemInfo::onCommitSaleType()
+{
+ //llinfos << "LLSidepanelItemInfo::onCommitSaleType()" << llendl;
+ updateSaleInfo();
+}
+
+void LLSidepanelItemInfo::updateSaleInfo()
+{
+ LLViewerInventoryItem* item = findItem();
+ if(!item) return;
+ LLSaleInfo sale_info(item->getSaleInfo());
+ if(!gAgent.allowOperation(PERM_TRANSFER, item->getPermissions(), GP_OBJECT_SET_SALE))
+ {
+ childSetValue("CheckPurchase",LLSD((BOOL)FALSE));
+ }
+
+ if((BOOL)childGetValue("CheckPurchase"))
+ {
+ // turn on sale info
+ LLSaleInfo::EForSale sale_type = LLSaleInfo::FS_COPY;
+
+ LLRadioGroup* RadioSaleType = getChild<LLRadioGroup>("RadioSaleType");
+ if(RadioSaleType)
+ {
+ switch (RadioSaleType->getSelectedIndex())
+ {
+ case 0:
+ sale_type = LLSaleInfo::FS_ORIGINAL;
+ break;
+ case 1:
+ sale_type = LLSaleInfo::FS_COPY;
+ break;
+ case 2:
+ sale_type = LLSaleInfo::FS_CONTENTS;
+ break;
+ default:
+ sale_type = LLSaleInfo::FS_COPY;
+ break;
+ }
+ }
+
+ if (sale_type == LLSaleInfo::FS_COPY
+ && !gAgent.allowOperation(PERM_COPY, item->getPermissions(),
+ GP_OBJECT_SET_SALE))
+ {
+ sale_type = LLSaleInfo::FS_ORIGINAL;
+ }
+
+
+
+ S32 price = -1;
+ price = getChild<LLUICtrl>("Edit Cost")->getValue().asInteger();;
+
+ // Invalid data - turn off the sale
+ if (price < 0)
+ {
+ sale_type = LLSaleInfo::FS_NOT;
+ price = 0;
+ }
+
+ sale_info.setSaleType(sale_type);
+ sale_info.setSalePrice(price);
+ }
+ else
+ {
+ sale_info.setSaleType(LLSaleInfo::FS_NOT);
+ }
+ if(sale_info != item->getSaleInfo()
+ && item->isComplete())
+ {
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+
+ // Force an update on the sale price at rez
+ if (item->getType() == LLAssetType::AT_OBJECT)
+ {
+ U32 flags = new_item->getFlags();
+ flags |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_SALE;
+ new_item->setFlags(flags);
+ }
+
+ new_item->setSaleInfo(sale_info);
+ if(mObjectID.isNull())
+ {
+ // This is in the agent's inventory.
+ new_item->updateServer(FALSE);
+ gInventory.updateItem(new_item);
+ gInventory.notifyObservers();
+ }
+ else
+ {
+ // This is in an object's contents.
+ LLViewerObject* object = gObjectList.findObject(mObjectID);
+ if(object)
+ {
+ object->updateInventory(
+ new_item,
+ TASK_INVENTORY_ITEM_KEY,
+ false);
+ }
+ }
+ }
+ else
+ {
+ // need to make sure we don't just follow the click
+ refresh();
+ }
+}
+
+LLViewerInventoryItem* LLSidepanelItemInfo::findItem() const
+{
+ LLViewerInventoryItem* item = NULL;
+ if(mObjectID.isNull())
+ {
+ // it is in agent inventory
+ item = gInventory.getItem(mItemID);
+ }
+ else
+ {
+ LLViewerObject* object = gObjectList.findObject(mObjectID);
+ if(object)
+ {
+ item = static_cast<LLViewerInventoryItem*>(object->getInventoryObject(mItemID));
+ }
+ }
+ return item;
+}
+
+// virtual
+void LLSidepanelItemInfo::save()
+{
+ onCommitName();
+ onCommitDescription();
+ onCommitPermissions();
+ onCommitSaleInfo();
+ onCommitSaleType();
+}
diff --git a/indra/newview/llsidepaneliteminfo.h b/indra/newview/llsidepaneliteminfo.h
new file mode 100644
index 0000000000..e6dbf400ee
--- /dev/null
+++ b/indra/newview/llsidepaneliteminfo.h
@@ -0,0 +1,90 @@
+/**
+ * @file llsidepaneliteminfo.h
+ * @brief A panel which shows an inventory item's properties.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSIDEPANELITEMINFO_H
+#define LL_LLSIDEPANELITEMINFO_H
+
+#include "llsidepanelinventorysubpanel.h"
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLSidepanelItemInfo
+// Object properties for inventory side panel.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLButton;
+class LLViewerInventoryItem;
+class LLItemPropertiesObserver;
+class LLViewerObject;
+class LLPermissions;
+
+class LLSidepanelItemInfo : public LLSidepanelInventorySubpanel
+{
+public:
+ LLSidepanelItemInfo();
+ virtual ~LLSidepanelItemInfo();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void reset();
+
+ void setObjectID(const LLUUID& object_id);
+ void setItemID(const LLUUID& item_id);
+ void setEditMode(BOOL edit);
+
+protected:
+ /*virtual*/ void refresh();
+ /*virtual*/ void save();
+
+ LLViewerInventoryItem* findItem() const;
+ LLViewerObject* findObject() const;
+
+ void refreshFromItem(LLViewerInventoryItem* item);
+
+private:
+ LLUUID mItemID; // inventory UUID for the inventory item.
+ LLUUID mObjectID; // in-world task UUID, or null if in agent inventory.
+ LLItemPropertiesObserver* mPropertiesObserver; // for syncing changes to item
+
+ //
+ // UI Elements
+ //
+protected:
+ void onClickCreator();
+ void onClickOwner();
+ void onCommitName();
+ void onCommitDescription();
+ void onCommitPermissions();
+ void onCommitSaleInfo();
+ void onCommitSaleType();
+ void updateSaleInfo();
+};
+
+#endif // LL_LLSIDEPANELITEMINFO_H
diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp
new file mode 100644
index 0000000000..0b8f66c5f3
--- /dev/null
+++ b/indra/newview/llsidepaneltaskinfo.cpp
@@ -0,0 +1,1199 @@
+/**
+ * @file llsidepaneltaskinfo.cpp
+ * @brief LLSidepanelTaskInfo class implementation
+ * This class represents the panel in the build view for
+ * viewing/editing object names, owners, permissions, etc.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llsidepaneltaskinfo.h"
+
+#include "lluuid.h"
+#include "llpermissions.h"
+#include "llcategory.h"
+#include "llclickaction.h"
+#include "llfocusmgr.h"
+#include "llnotificationsutil.h"
+#include "llstring.h"
+
+#include "llviewerwindow.h"
+#include "llresmgr.h"
+#include "lltextbox.h"
+#include "llbutton.h"
+#include "llcheckboxctrl.h"
+#include "llviewerobject.h"
+#include "llselectmgr.h"
+#include "llagent.h"
+#include "llstatusbar.h" // for getBalance()
+#include "lllineeditor.h"
+#include "llcombobox.h"
+#include "lluiconstants.h"
+#include "lldbstrings.h"
+#include "llfloatergroups.h"
+#include "llfloaterreg.h"
+#include "llavataractions.h"
+#include "llnamebox.h"
+#include "llviewercontrol.h"
+#include "llviewermenu.h"
+#include "lluictrlfactory.h"
+#include "llspinctrl.h"
+#include "roles_constants.h"
+#include "llgroupactions.h"
+
+///----------------------------------------------------------------------------
+/// Class llsidepaneltaskinfo
+///----------------------------------------------------------------------------
+
+LLSidepanelTaskInfo* LLSidepanelTaskInfo::sActivePanel = NULL;
+
+static LLRegisterPanelClassWrapper<LLSidepanelTaskInfo> t_task_info("sidepanel_task_info");
+
+// Default constructor
+LLSidepanelTaskInfo::LLSidepanelTaskInfo()
+{
+ setMouseOpaque(FALSE);
+}
+
+
+LLSidepanelTaskInfo::~LLSidepanelTaskInfo()
+{
+ if (sActivePanel == this)
+ sActivePanel = NULL;
+}
+
+// virtual
+BOOL LLSidepanelTaskInfo::postBuild()
+{
+ LLSidepanelInventorySubpanel::postBuild();
+
+ mOpenBtn = getChild<LLButton>("open_btn");
+ mOpenBtn->setClickedCallback(boost::bind(&LLSidepanelTaskInfo::onOpenButtonClicked, this));
+ mPayBtn = getChild<LLButton>("pay_btn");
+ mPayBtn->setClickedCallback(boost::bind(&LLSidepanelTaskInfo::onPayButtonClicked, this));
+ mBuyBtn = getChild<LLButton>("buy_btn");
+ mBuyBtn->setClickedCallback(boost::bind(&LLSidepanelTaskInfo::onBuyButtonClicked, this));
+
+ mLabelGroupName = getChild<LLNameBox>("Group Name Proxy");
+
+ childSetCommitCallback("Object Name", LLSidepanelTaskInfo::onCommitName,this);
+ childSetPrevalidate("Object Name", LLLineEditor::prevalidateASCIIPrintableNoPipe);
+ childSetCommitCallback("Object Description", LLSidepanelTaskInfo::onCommitDesc,this);
+ childSetPrevalidate("Object Description", LLLineEditor::prevalidateASCIIPrintableNoPipe);
+ getChild<LLUICtrl>("button set group")->setCommitCallback(boost::bind(&LLSidepanelTaskInfo::onClickGroup,this));
+ childSetCommitCallback("checkbox share with group", &LLSidepanelTaskInfo::onCommitGroupShare,this);
+ childSetAction("button deed", &LLSidepanelTaskInfo::onClickDeedToGroup,this);
+ childSetCommitCallback("checkbox allow everyone move", &LLSidepanelTaskInfo::onCommitEveryoneMove,this);
+ childSetCommitCallback("checkbox allow everyone copy", &LLSidepanelTaskInfo::onCommitEveryoneCopy,this);
+ childSetCommitCallback("checkbox for sale", &LLSidepanelTaskInfo::onCommitSaleInfo,this);
+ childSetCommitCallback("sale type", &LLSidepanelTaskInfo::onCommitSaleType,this);
+ childSetCommitCallback("Edit Cost", &LLSidepanelTaskInfo::onCommitSaleInfo, this);
+ childSetCommitCallback("checkbox next owner can modify", &LLSidepanelTaskInfo::onCommitNextOwnerModify,this);
+ childSetCommitCallback("checkbox next owner can copy", &LLSidepanelTaskInfo::onCommitNextOwnerCopy,this);
+ childSetCommitCallback("checkbox next owner can transfer", &LLSidepanelTaskInfo::onCommitNextOwnerTransfer,this);
+ childSetCommitCallback("clickaction", &LLSidepanelTaskInfo::onCommitClickAction,this);
+ childSetCommitCallback("search_check", &LLSidepanelTaskInfo::onCommitIncludeInSearch,this);
+ return TRUE;
+}
+
+// virtual
+void LLSidepanelTaskInfo::setVisible(BOOL visible)
+{
+ LLPanel::setVisible(visible);
+ if (visible)
+ {
+ sActivePanel = this;
+ mObject = getFirstSelectedObject();
+ }
+ else
+ {
+ sActivePanel = NULL;
+ }
+}
+
+void LLSidepanelTaskInfo::disableAll()
+{
+ childSetEnabled("perm_modify", FALSE);
+ childSetText("perm_modify", LLStringUtil::null);
+
+ childSetEnabled("Creator:", FALSE);
+ childSetText("Creator Name", LLStringUtil::null);
+ childSetEnabled("Creator Name", FALSE);
+
+ childSetEnabled("Owner:", FALSE);
+ childSetText("Owner Name", LLStringUtil::null);
+ childSetEnabled("Owner Name", FALSE);
+
+ childSetEnabled("Group:", FALSE);
+ childSetText("Group Name", LLStringUtil::null);
+ childSetEnabled("Group Name", FALSE);
+ childSetEnabled("button set group", FALSE);
+
+ childSetText("Object Name", LLStringUtil::null);
+ childSetEnabled("Object Name", FALSE);
+ childSetEnabled("Name:", FALSE);
+ childSetText("Group Name", LLStringUtil::null);
+ childSetEnabled("Group Name", FALSE);
+ childSetEnabled("Description:", FALSE);
+ childSetText("Object Description", LLStringUtil::null);
+ childSetEnabled("Object Description", FALSE);
+
+ childSetEnabled("Permissions:", FALSE);
+
+ childSetValue("checkbox share with group", FALSE);
+ childSetEnabled("checkbox share with group", FALSE);
+ childSetEnabled("button deed", FALSE);
+
+ childSetValue("checkbox allow everyone move", FALSE);
+ childSetEnabled("checkbox allow everyone move", FALSE);
+ childSetValue("checkbox allow everyone copy", FALSE);
+ childSetEnabled("checkbox allow everyone copy", FALSE);
+
+ //Next owner can:
+ childSetEnabled("Next owner can:", FALSE);
+ childSetValue("checkbox next owner can modify", FALSE);
+ childSetEnabled("checkbox next owner can modify", FALSE);
+ childSetValue("checkbox next owner can copy", FALSE);
+ childSetEnabled("checkbox next owner can copy", FALSE);
+ childSetValue("checkbox next owner can transfer", FALSE);
+ childSetEnabled("checkbox next owner can transfer", FALSE);
+
+ //checkbox for sale
+ childSetValue("checkbox for sale", FALSE);
+ childSetEnabled("checkbox for sale", FALSE);
+
+ //checkbox include in search
+ childSetValue("search_check", FALSE);
+ childSetEnabled("search_check", FALSE);
+
+ LLComboBox* combo_sale_type = getChild<LLComboBox>("sale type");
+ combo_sale_type->setValue(LLSaleInfo::FS_COPY);
+ combo_sale_type->setEnabled(FALSE);
+
+ childSetEnabled("Cost", FALSE);
+ childSetText("Cost", getString("Cost Default"));
+ childSetText("Edit Cost", LLStringUtil::null);
+ childSetEnabled("Edit Cost", FALSE);
+
+ childSetEnabled("label click action", FALSE);
+ LLComboBox* combo_click_action = getChild<LLComboBox>("clickaction");
+ if (combo_click_action)
+ {
+ combo_click_action->setEnabled(FALSE);
+ combo_click_action->clear();
+ }
+ childSetVisible("B:", FALSE);
+ childSetVisible("O:", FALSE);
+ childSetVisible("G:", FALSE);
+ childSetVisible("E:", FALSE);
+ childSetVisible("N:", FALSE);
+ childSetVisible("F:", FALSE);
+
+ mOpenBtn->setEnabled(FALSE);
+ mPayBtn->setEnabled(FALSE);
+ mBuyBtn->setEnabled(FALSE);
+}
+
+void LLSidepanelTaskInfo::refresh()
+{
+ LLButton* btn_deed_to_group = getChild<LLButton>("button deed");
+ if (btn_deed_to_group)
+ {
+ std::string deedText;
+ if (gWarningSettings.getBOOL("DeedObject"))
+ {
+ deedText = getString("text deed continued");
+ }
+ else
+ {
+ deedText = getString("text deed");
+ }
+ btn_deed_to_group->setLabelSelected(deedText);
+ btn_deed_to_group->setLabelUnselected(deedText);
+ }
+
+ BOOL root_selected = TRUE;
+ LLSelectNode* nodep = mObjectSelection->getFirstRootNode();
+ S32 object_count = mObjectSelection->getRootObjectCount();
+ if (!nodep || (object_count == 0))
+ {
+ nodep = mObjectSelection->getFirstNode();
+ object_count = mObjectSelection->getObjectCount();
+ root_selected = FALSE;
+ }
+
+ LLViewerObject* objectp = NULL;
+ if (nodep)
+ {
+ objectp = nodep->getObject();
+ }
+
+ // ...nothing selected
+ if (!nodep || !objectp)
+ {
+ disableAll();
+ return;
+ }
+
+ // figure out a few variables
+ const BOOL is_one_object = (object_count == 1);
+
+ // BUG: fails if a root and non-root are both single-selected.
+ const BOOL is_perm_modify = (mObjectSelection->getFirstRootNode() && LLSelectMgr::getInstance()->selectGetRootsModify()) ||
+ LLSelectMgr::getInstance()->selectGetModify();
+ const LLFocusableElement* keyboard_focus_view = gFocusMgr.getKeyboardFocus();
+
+ S32 string_index = 0;
+ std::string MODIFY_INFO_STRINGS[] =
+ {
+ getString("text modify info 1"),
+ getString("text modify info 2"),
+ getString("text modify info 3"),
+ getString("text modify info 4")
+ };
+ if (!is_perm_modify)
+ {
+ string_index += 2;
+ }
+ if (!is_one_object)
+ {
+ ++string_index;
+ }
+ childSetEnabled("perm_modify", TRUE);
+ childSetText("perm_modify", MODIFY_INFO_STRINGS[string_index]);
+
+ childSetEnabled("Permissions:", TRUE);
+
+ // Update creator text field
+ childSetEnabled("Creator:", TRUE);
+ BOOL creators_identical;
+ std::string creator_name;
+ creators_identical = LLSelectMgr::getInstance()->selectGetCreator(mCreatorID,
+ creator_name);
+
+ childSetText("Creator Name", creator_name);
+ childSetEnabled("Creator Name", TRUE);
+
+ // Update owner text field
+ childSetEnabled("Owner:", TRUE);
+
+ std::string owner_name;
+ const BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(mOwnerID, owner_name);
+ if (mOwnerID.isNull())
+ {
+ if (LLSelectMgr::getInstance()->selectIsGroupOwned())
+ {
+ // Group owned already displayed by selectGetOwner
+ }
+ else
+ {
+ // Display last owner if public
+ std::string last_owner_name;
+ LLSelectMgr::getInstance()->selectGetLastOwner(mLastOwnerID, last_owner_name);
+
+ // It should never happen that the last owner is null and the owner
+ // is null, but it seems to be a bug in the simulator right now. JC
+ if (!mLastOwnerID.isNull() && !last_owner_name.empty())
+ {
+ owner_name.append(", last ");
+ owner_name.append(last_owner_name);
+ }
+ }
+ }
+ childSetText("Owner Name", owner_name);
+ childSetEnabled("Owner Name", TRUE);
+
+ // update group text field
+ childSetEnabled("Group:", TRUE);
+ childSetText("Group Name", LLStringUtil::null);
+ LLUUID group_id;
+ BOOL groups_identical = LLSelectMgr::getInstance()->selectGetGroup(group_id);
+ if (groups_identical)
+ {
+ if (mLabelGroupName)
+ {
+ mLabelGroupName->setNameID(group_id,TRUE);
+ mLabelGroupName->setEnabled(TRUE);
+ }
+ }
+ else
+ {
+ if (mLabelGroupName)
+ {
+ mLabelGroupName->setNameID(LLUUID::null, TRUE);
+ mLabelGroupName->refresh(LLUUID::null,LLStringUtil::null, LLStringUtil::null, TRUE);
+ mLabelGroupName->setEnabled(FALSE);
+ }
+ }
+
+ childSetEnabled("button set group", owners_identical && (mOwnerID == gAgent.getID()));
+
+ childSetEnabled("Name:", TRUE);
+ LLLineEditor* LineEditorObjectName = getChild<LLLineEditor>("Object Name");
+ childSetEnabled("Description:", TRUE);
+ LLLineEditor* LineEditorObjectDesc = getChild<LLLineEditor>("Object Description");
+
+ if (is_one_object)
+ {
+ if (keyboard_focus_view != LineEditorObjectName)
+ {
+ childSetText("Object Name",nodep->mName);
+ }
+
+ if (LineEditorObjectDesc)
+ {
+ if (keyboard_focus_view != LineEditorObjectDesc)
+ {
+ LineEditorObjectDesc->setText(nodep->mDescription);
+ }
+ }
+ }
+ else
+ {
+ childSetText("Object Name", LLStringUtil::null);
+ LineEditorObjectDesc->setText(LLStringUtil::null);
+ }
+
+ // figure out the contents of the name, description, & category
+ BOOL edit_name_desc = FALSE;
+ if (is_one_object && objectp->permModify())
+ {
+ edit_name_desc = TRUE;
+ }
+ if (edit_name_desc)
+ {
+ childSetEnabled("Object Name", TRUE);
+ childSetEnabled("Object Description", TRUE);
+ }
+ else
+ {
+ childSetEnabled("Object Name", FALSE);
+ childSetEnabled("Object Description", FALSE);
+ }
+
+ S32 total_sale_price = 0;
+ S32 individual_sale_price = 0;
+ BOOL is_for_sale_mixed = FALSE;
+ BOOL is_sale_price_mixed = FALSE;
+ U32 num_for_sale = FALSE;
+ LLSelectMgr::getInstance()->selectGetAggregateSaleInfo(num_for_sale,
+ is_for_sale_mixed,
+ is_sale_price_mixed,
+ total_sale_price,
+ individual_sale_price);
+
+ const BOOL self_owned = (gAgent.getID() == mOwnerID);
+ const BOOL group_owned = LLSelectMgr::getInstance()->selectIsGroupOwned() ;
+ const BOOL public_owned = (mOwnerID.isNull() && !LLSelectMgr::getInstance()->selectIsGroupOwned());
+ const BOOL can_transfer = LLSelectMgr::getInstance()->selectGetRootsTransfer();
+ const BOOL can_copy = LLSelectMgr::getInstance()->selectGetRootsCopy();
+
+ if (!owners_identical)
+ {
+ childSetEnabled("Cost", FALSE);
+ childSetText("Edit Cost", LLStringUtil::null);
+ childSetEnabled("Edit Cost", FALSE);
+ }
+ // You own these objects.
+ else if (self_owned || (group_owned && gAgent.hasPowerInGroup(group_id,GP_OBJECT_SET_SALE)))
+ {
+ // If there are multiple items for sale then set text to PRICE PER UNIT.
+ if (num_for_sale > 1)
+ {
+ childSetText("Cost", getString("Cost Per Unit"));
+ }
+ else
+ {
+ childSetText("Cost", getString("Cost Default"));
+ }
+
+ LLSpinCtrl *edit_price = getChild<LLSpinCtrl>("Edit Cost");
+ if (!edit_price->hasFocus())
+ {
+ // If the sale price is mixed then set the cost to MIXED, otherwise
+ // set to the actual cost.
+ if ((num_for_sale > 0) && is_for_sale_mixed)
+ {
+ edit_price->setTentative(TRUE);
+ }
+ else if ((num_for_sale > 0) && is_sale_price_mixed)
+ {
+ edit_price->setTentative(TRUE);
+ }
+ else
+ {
+ edit_price->setValue(individual_sale_price);
+ }
+ }
+ // The edit fields are only enabled if you can sell this object
+ // and the sale price is not mixed.
+ BOOL enable_edit = (num_for_sale && can_transfer) ? !is_for_sale_mixed : FALSE;
+ childSetEnabled("Cost", enable_edit);
+ childSetEnabled("Edit Cost", enable_edit);
+ }
+ // Someone, not you, owns these objects.
+ else if (!public_owned)
+ {
+ childSetEnabled("Cost", FALSE);
+ childSetEnabled("Edit Cost", FALSE);
+
+ // Don't show a price if none of the items are for sale.
+ if (num_for_sale)
+ childSetText("Edit Cost", llformat("%d",total_sale_price));
+ else
+ childSetText("Edit Cost", LLStringUtil::null);
+
+ // If multiple items are for sale, set text to TOTAL PRICE.
+ if (num_for_sale > 1)
+ childSetText("Cost", getString("Cost Total"));
+ else
+ childSetText("Cost", getString("Cost Default"));
+ }
+ // This is a public object.
+ else
+ {
+ childSetEnabled("Cost", FALSE);
+ childSetText("Cost", getString("Cost Default"));
+
+ childSetText("Edit Cost", LLStringUtil::null);
+ childSetEnabled("Edit Cost", FALSE);
+ }
+
+ // Enable and disable the permissions checkboxes
+ // based on who owns the object.
+ // TODO: Creator permissions
+
+ U32 base_mask_on = 0;
+ U32 base_mask_off = 0;
+ U32 owner_mask_off = 0;
+ U32 owner_mask_on = 0;
+ U32 group_mask_on = 0;
+ U32 group_mask_off = 0;
+ U32 everyone_mask_on = 0;
+ U32 everyone_mask_off = 0;
+ U32 next_owner_mask_on = 0;
+ U32 next_owner_mask_off = 0;
+
+ BOOL valid_base_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_BASE,
+ &base_mask_on,
+ &base_mask_off);
+ //BOOL valid_owner_perms =//
+ LLSelectMgr::getInstance()->selectGetPerm(PERM_OWNER,
+ &owner_mask_on,
+ &owner_mask_off);
+ BOOL valid_group_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_GROUP,
+ &group_mask_on,
+ &group_mask_off);
+
+ BOOL valid_everyone_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_EVERYONE,
+ &everyone_mask_on,
+ &everyone_mask_off);
+
+ BOOL valid_next_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_NEXT_OWNER,
+ &next_owner_mask_on,
+ &next_owner_mask_off);
+
+
+ if (gSavedSettings.getBOOL("DebugPermissions") )
+ {
+ if (valid_base_perms)
+ {
+ childSetText("B:", "B: " + mask_to_string(base_mask_on));
+ childSetVisible("B:", TRUE);
+
+ childSetText("O:", "O: " + mask_to_string(owner_mask_on));
+ childSetVisible("O:", TRUE);
+
+ childSetText("G:", "G: " + mask_to_string(group_mask_on));
+ childSetVisible("G:", TRUE);
+
+ childSetText("E:", "E: " + mask_to_string(everyone_mask_on));
+ childSetVisible("E:", TRUE);
+
+ childSetText("N:", "N: " + mask_to_string(next_owner_mask_on));
+ childSetVisible("N:", TRUE);
+ }
+
+ U32 flag_mask = 0x0;
+ if (objectp->permMove()) flag_mask |= PERM_MOVE;
+ if (objectp->permModify()) flag_mask |= PERM_MODIFY;
+ if (objectp->permCopy()) flag_mask |= PERM_COPY;
+ if (objectp->permTransfer()) flag_mask |= PERM_TRANSFER;
+
+ childSetText("F:", "F:" + mask_to_string(flag_mask));
+ childSetVisible("F:", TRUE);
+ }
+ else
+ {
+ childSetVisible("B:", FALSE);
+ childSetVisible("O:", FALSE);
+ childSetVisible("G:", FALSE);
+ childSetVisible("E:", FALSE);
+ childSetVisible("N:", FALSE);
+ childSetVisible("F:", FALSE);
+ }
+
+ BOOL has_change_perm_ability = FALSE;
+ BOOL has_change_sale_ability = FALSE;
+
+ if (valid_base_perms &&
+ (self_owned || (group_owned && gAgent.hasPowerInGroup(group_id, GP_OBJECT_MANIPULATE))))
+ {
+ has_change_perm_ability = TRUE;
+ }
+ if (valid_base_perms &&
+ (self_owned || (group_owned && gAgent.hasPowerInGroup(group_id, GP_OBJECT_SET_SALE))))
+ {
+ has_change_sale_ability = TRUE;
+ }
+
+ if (!has_change_perm_ability && !has_change_sale_ability && !root_selected)
+ {
+ // ...must select root to choose permissions
+ childSetValue("perm_modify", getString("text modify warning"));
+ }
+
+ if (has_change_perm_ability)
+ {
+ childSetEnabled("checkbox share with group", TRUE);
+ childSetEnabled("checkbox allow everyone move", owner_mask_on & PERM_MOVE);
+ childSetEnabled("checkbox allow everyone copy", owner_mask_on & PERM_COPY && owner_mask_on & PERM_TRANSFER);
+ }
+ else
+ {
+ childSetEnabled("checkbox share with group", FALSE);
+ childSetEnabled("checkbox allow everyone move", FALSE);
+ childSetEnabled("checkbox allow everyone copy", FALSE);
+ }
+
+ if (has_change_sale_ability && (owner_mask_on & PERM_TRANSFER))
+ {
+ childSetEnabled("checkbox for sale", can_transfer || (!can_transfer && num_for_sale));
+ // Set the checkbox to tentative if the prices of each object selected
+ // are not the same.
+ childSetTentative("checkbox for sale", is_for_sale_mixed);
+ childSetEnabled("sale type", num_for_sale && can_transfer && !is_sale_price_mixed);
+
+ childSetEnabled("Next owner can:", TRUE);
+ childSetEnabled("checkbox next owner can modify", base_mask_on & PERM_MODIFY);
+ childSetEnabled("checkbox next owner can copy", base_mask_on & PERM_COPY);
+ childSetEnabled("checkbox next owner can transfer", next_owner_mask_on & PERM_COPY);
+ }
+ else
+ {
+ childSetEnabled("checkbox for sale", FALSE);
+ childSetEnabled("sale type", FALSE);
+
+ childSetEnabled("Next owner can:", FALSE);
+ childSetEnabled("checkbox next owner can modify", FALSE);
+ childSetEnabled("checkbox next owner can copy", FALSE);
+ childSetEnabled("checkbox next owner can transfer", FALSE);
+ }
+
+ if (valid_group_perms)
+ {
+ if ((group_mask_on & PERM_COPY) && (group_mask_on & PERM_MODIFY) && (group_mask_on & PERM_MOVE))
+ {
+ childSetValue("checkbox share with group", TRUE);
+ childSetTentative("checkbox share with group", FALSE);
+ childSetEnabled("button deed", gAgent.hasPowerInGroup(group_id, GP_OBJECT_DEED) && (owner_mask_on & PERM_TRANSFER) && !group_owned && can_transfer);
+ }
+ else if ((group_mask_off & PERM_COPY) && (group_mask_off & PERM_MODIFY) && (group_mask_off & PERM_MOVE))
+ {
+ childSetValue("checkbox share with group", FALSE);
+ childSetTentative("checkbox share with group", FALSE);
+ childSetEnabled("button deed", FALSE);
+ }
+ else
+ {
+ childSetValue("checkbox share with group", TRUE);
+ childSetTentative("checkbox share with group", TRUE);
+ childSetEnabled("button deed", gAgent.hasPowerInGroup(group_id, GP_OBJECT_DEED) && (group_mask_on & PERM_MOVE) && (owner_mask_on & PERM_TRANSFER) && !group_owned && can_transfer);
+ }
+ }
+
+ if (valid_everyone_perms)
+ {
+ // Move
+ if (everyone_mask_on & PERM_MOVE)
+ {
+ childSetValue("checkbox allow everyone move", TRUE);
+ childSetTentative("checkbox allow everyone move", FALSE);
+ }
+ else if (everyone_mask_off & PERM_MOVE)
+ {
+ childSetValue("checkbox allow everyone move", FALSE);
+ childSetTentative("checkbox allow everyone move", FALSE);
+ }
+ else
+ {
+ childSetValue("checkbox allow everyone move", TRUE);
+ childSetTentative("checkbox allow everyone move", TRUE);
+ }
+
+ // Copy == everyone can't copy
+ if (everyone_mask_on & PERM_COPY)
+ {
+ childSetValue("checkbox allow everyone copy", TRUE);
+ childSetTentative("checkbox allow everyone copy", !can_copy || !can_transfer);
+ }
+ else if (everyone_mask_off & PERM_COPY)
+ {
+ childSetValue("checkbox allow everyone copy", FALSE);
+ childSetTentative("checkbox allow everyone copy", FALSE);
+ }
+ else
+ {
+ childSetValue("checkbox allow everyone copy", TRUE);
+ childSetTentative("checkbox allow everyone copy", TRUE);
+ }
+ }
+
+ if (valid_next_perms)
+ {
+ // Modify == next owner canot modify
+ if (next_owner_mask_on & PERM_MODIFY)
+ {
+ childSetValue("checkbox next owner can modify", TRUE);
+ childSetTentative("checkbox next owner can modify", FALSE);
+ }
+ else if (next_owner_mask_off & PERM_MODIFY)
+ {
+ childSetValue("checkbox next owner can modify", FALSE);
+ childSetTentative("checkbox next owner can modify", FALSE);
+ }
+ else
+ {
+ childSetValue("checkbox next owner can modify", TRUE);
+ childSetTentative("checkbox next owner can modify", TRUE);
+ }
+
+ // Copy == next owner cannot copy
+ if (next_owner_mask_on & PERM_COPY)
+ {
+ childSetValue("checkbox next owner can copy", TRUE);
+ childSetTentative("checkbox next owner can copy", !can_copy);
+ }
+ else if (next_owner_mask_off & PERM_COPY)
+ {
+ childSetValue("checkbox next owner can copy", FALSE);
+ childSetTentative("checkbox next owner can copy", FALSE);
+ }
+ else
+ {
+ childSetValue("checkbox next owner can copy", TRUE);
+ childSetTentative("checkbox next owner can copy", TRUE);
+ }
+
+ // Transfer == next owner cannot transfer
+ if (next_owner_mask_on & PERM_TRANSFER)
+ {
+ childSetValue("checkbox next owner can transfer", TRUE);
+ childSetTentative("checkbox next owner can transfer", !can_transfer);
+ }
+ else if (next_owner_mask_off & PERM_TRANSFER)
+ {
+ childSetValue("checkbox next owner can transfer", FALSE);
+ childSetTentative("checkbox next owner can transfer", FALSE);
+ }
+ else
+ {
+ childSetValue("checkbox next owner can transfer", TRUE);
+ childSetTentative("checkbox next owner can transfer", TRUE);
+ }
+ }
+
+ // reflect sale information
+ LLSaleInfo sale_info;
+ BOOL valid_sale_info = LLSelectMgr::getInstance()->selectGetSaleInfo(sale_info);
+ LLSaleInfo::EForSale sale_type = sale_info.getSaleType();
+
+ LLComboBox* combo_sale_type = getChild<LLComboBox>("sale type");
+ if (valid_sale_info)
+ {
+ combo_sale_type->setValue( sale_type == LLSaleInfo::FS_NOT ? LLSaleInfo::FS_COPY : sale_type);
+ combo_sale_type->setTentative( FALSE); // unfortunately this doesn't do anything at the moment.
+ }
+ else
+ {
+ // default option is sell copy, determined to be safest
+ combo_sale_type->setValue( LLSaleInfo::FS_COPY);
+ combo_sale_type->setTentative( TRUE); // unfortunately this doesn't do anything at the moment.
+ }
+
+ childSetValue("checkbox for sale", (num_for_sale != 0));
+
+ // HACK: There are some old objects in world that are set for sale,
+ // but are no-transfer. We need to let users turn for-sale off, but only
+ // if for-sale is set.
+ bool cannot_actually_sell = !can_transfer || (!can_copy && sale_type == LLSaleInfo::FS_COPY);
+ if (cannot_actually_sell)
+ {
+ if (num_for_sale && has_change_sale_ability)
+ {
+ childSetEnabled("checkbox for sale", true);
+ }
+ }
+
+ // Check search status of objects
+ const BOOL all_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME );
+ bool include_in_search;
+ const BOOL all_include_in_search = LLSelectMgr::getInstance()->selectionGetIncludeInSearch(&include_in_search);
+ childSetEnabled("search_check", has_change_sale_ability && all_volume);
+ childSetValue("search_check", include_in_search);
+ childSetTentative("search_check", !all_include_in_search);
+
+ // Click action (touch, sit, buy)
+ U8 click_action = 0;
+ if (LLSelectMgr::getInstance()->selectionGetClickAction(&click_action))
+ {
+ LLComboBox* ComboClickAction = getChild<LLComboBox>("clickaction");
+ if (ComboClickAction)
+ {
+ ComboClickAction->setCurrentByIndex((S32)click_action);
+ }
+ }
+ childSetEnabled("label click action", is_perm_modify && all_volume);
+ childSetEnabled("clickaction", is_perm_modify && all_volume);
+
+ if (!getIsEditing())
+ {
+ const std::string no_item_names[] =
+ {
+ "Object Name",
+ "Object Description",
+ "button set group",
+ "checkbox share with group",
+ "button deed",
+ "checkbox allow everyone move",
+ "checkbox allow everyone copy",
+ "checkbox for sale",
+ "sale type",
+ "Edit Cost",
+ "checkbox next owner can modify",
+ "checkbox next owner can copy",
+ "checkbox next owner can transfer",
+ "clickaction",
+ "search_check",
+ "perm_modify",
+ "Group Name",
+ };
+ for (size_t t=0; t<LL_ARRAY_SIZE(no_item_names); ++t)
+ {
+ childSetEnabled(no_item_names[t], FALSE);
+ }
+ }
+ updateVerbs();
+}
+
+
+// static
+void LLSidepanelTaskInfo::onClickClaim(void*)
+{
+ // try to claim ownership
+ LLSelectMgr::getInstance()->sendOwner(gAgent.getID(), gAgent.getGroupID());
+}
+
+// static
+void LLSidepanelTaskInfo::onClickRelease(void*)
+{
+ // try to release ownership
+ LLSelectMgr::getInstance()->sendOwner(LLUUID::null, LLUUID::null);
+}
+
+void LLSidepanelTaskInfo::onClickGroup()
+{
+ LLUUID owner_id;
+ std::string name;
+ BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, name);
+ LLFloater* parent_floater = gFloaterView->getParentFloater(this);
+
+ if (owners_identical && (owner_id == gAgent.getID()))
+ {
+ LLFloaterGroupPicker* fg = LLFloaterReg::showTypedInstance<LLFloaterGroupPicker>("group_picker", LLSD(gAgent.getID()));
+ if (fg)
+ {
+ fg->setSelectGroupCallback( boost::bind(&LLSidepanelTaskInfo::cbGroupID, this, _1) );
+ if (parent_floater)
+ {
+ LLRect new_rect = gFloaterView->findNeighboringPosition(parent_floater, fg);
+ fg->setOrigin(new_rect.mLeft, new_rect.mBottom);
+ parent_floater->addDependentFloater(fg);
+ }
+ }
+ }
+}
+
+void LLSidepanelTaskInfo::cbGroupID(LLUUID group_id)
+{
+ if (mLabelGroupName)
+ {
+ mLabelGroupName->setNameID(group_id, TRUE);
+ }
+ LLSelectMgr::getInstance()->sendGroup(group_id);
+}
+
+static bool callback_deed_to_group(const LLSD& notification, const LLSD& response)
+{
+ const S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option == 0)
+ {
+ LLUUID group_id;
+ const BOOL groups_identical = LLSelectMgr::getInstance()->selectGetGroup(group_id);
+ if (group_id.notNull() && groups_identical && (gAgent.hasPowerInGroup(group_id, GP_OBJECT_DEED)))
+ {
+ LLSelectMgr::getInstance()->sendOwner(LLUUID::null, group_id, FALSE);
+// LLViewerStats::getInstance()->incStat(LLViewerStats::ST_RELEASE_COUNT);
+ }
+ }
+ return FALSE;
+}
+
+void LLSidepanelTaskInfo::onClickDeedToGroup(void *data)
+{
+ LLNotificationsUtil::add("DeedObjectToGroup", LLSD(), LLSD(), callback_deed_to_group);
+}
+
+///----------------------------------------------------------------------------
+/// Permissions checkboxes
+///----------------------------------------------------------------------------
+
+// static
+void LLSidepanelTaskInfo::onCommitPerm(LLUICtrl *ctrl, void *data, U8 field, U32 perm)
+{
+ LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject();
+ if(!object) return;
+
+ // Checkbox will have toggled itself
+ // LLSidepanelTaskInfo* self = (LLSidepanelTaskInfo*)data;
+ LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
+ BOOL new_state = check->get();
+
+ LLSelectMgr::getInstance()->selectionSetObjectPermissions(field, new_state, perm);
+}
+
+// static
+void LLSidepanelTaskInfo::onCommitGroupShare(LLUICtrl *ctrl, void *data)
+{
+ onCommitPerm(ctrl, data, PERM_GROUP, PERM_MODIFY | PERM_MOVE | PERM_COPY);
+}
+
+// static
+void LLSidepanelTaskInfo::onCommitEveryoneMove(LLUICtrl *ctrl, void *data)
+{
+ onCommitPerm(ctrl, data, PERM_EVERYONE, PERM_MOVE);
+}
+
+
+// static
+void LLSidepanelTaskInfo::onCommitEveryoneCopy(LLUICtrl *ctrl, void *data)
+{
+ onCommitPerm(ctrl, data, PERM_EVERYONE, PERM_COPY);
+}
+
+// static
+void LLSidepanelTaskInfo::onCommitNextOwnerModify(LLUICtrl* ctrl, void* data)
+{
+ //llinfos << "LLSidepanelTaskInfo::onCommitNextOwnerModify" << llendl;
+ onCommitPerm(ctrl, data, PERM_NEXT_OWNER, PERM_MODIFY);
+}
+
+// static
+void LLSidepanelTaskInfo::onCommitNextOwnerCopy(LLUICtrl* ctrl, void* data)
+{
+ //llinfos << "LLSidepanelTaskInfo::onCommitNextOwnerCopy" << llendl;
+ onCommitPerm(ctrl, data, PERM_NEXT_OWNER, PERM_COPY);
+}
+
+// static
+void LLSidepanelTaskInfo::onCommitNextOwnerTransfer(LLUICtrl* ctrl, void* data)
+{
+ //llinfos << "LLSidepanelTaskInfo::onCommitNextOwnerTransfer" << llendl;
+ onCommitPerm(ctrl, data, PERM_NEXT_OWNER, PERM_TRANSFER);
+}
+
+// static
+void LLSidepanelTaskInfo::onCommitName(LLUICtrl*, void* data)
+{
+ //llinfos << "LLSidepanelTaskInfo::onCommitName()" << llendl;
+ LLSidepanelTaskInfo* self = (LLSidepanelTaskInfo*)data;
+ LLLineEditor* tb = self->getChild<LLLineEditor>("Object Name");
+ if(tb)
+ {
+ LLSelectMgr::getInstance()->selectionSetObjectName(tb->getText());
+// LLSelectMgr::getInstance()->selectionSetObjectName(self->mLabelObjectName->getText());
+ }
+}
+
+
+// static
+void LLSidepanelTaskInfo::onCommitDesc(LLUICtrl*, void* data)
+{
+ //llinfos << "LLSidepanelTaskInfo::onCommitDesc()" << llendl;
+ LLSidepanelTaskInfo* self = (LLSidepanelTaskInfo*)data;
+ LLLineEditor* le = self->getChild<LLLineEditor>("Object Description");
+ if(le)
+ {
+ LLSelectMgr::getInstance()->selectionSetObjectDescription(le->getText());
+ }
+}
+
+// static
+void LLSidepanelTaskInfo::onCommitSaleInfo(LLUICtrl*, void* data)
+{
+ LLSidepanelTaskInfo* self = (LLSidepanelTaskInfo*)data;
+ self->setAllSaleInfo();
+}
+
+// static
+void LLSidepanelTaskInfo::onCommitSaleType(LLUICtrl*, void* data)
+{
+ LLSidepanelTaskInfo* self = (LLSidepanelTaskInfo*)data;
+ self->setAllSaleInfo();
+}
+
+
+void LLSidepanelTaskInfo::setAllSaleInfo()
+{
+ LLSaleInfo::EForSale sale_type = LLSaleInfo::FS_NOT;
+
+ LLCheckBoxCtrl *checkPurchase = getChild<LLCheckBoxCtrl>("checkbox for sale");
+
+ // Set the sale type if the object(s) are for sale.
+ if(checkPurchase && checkPurchase->get())
+ {
+ sale_type = static_cast<LLSaleInfo::EForSale>(getChild<LLComboBox>("sale type")->getValue().asInteger());
+ }
+
+ S32 price = -1;
+
+ LLSpinCtrl *edit_price = getChild<LLSpinCtrl>("Edit Cost");
+ price = (edit_price->getTentative()) ? DEFAULT_PRICE : edit_price->getValue().asInteger();
+
+ // If somehow an invalid price, turn the sale off.
+ if (price < 0)
+ sale_type = LLSaleInfo::FS_NOT;
+
+ LLSaleInfo old_sale_info;
+ LLSelectMgr::getInstance()->selectGetSaleInfo(old_sale_info);
+
+ LLSaleInfo new_sale_info(sale_type, price);
+ LLSelectMgr::getInstance()->selectionSetObjectSaleInfo(new_sale_info);
+
+ U8 old_click_action = 0;
+ LLSelectMgr::getInstance()->selectionGetClickAction(&old_click_action);
+
+ if (old_sale_info.isForSale()
+ && !new_sale_info.isForSale()
+ && old_click_action == CLICK_ACTION_BUY)
+ {
+ // If turned off for-sale, make sure click-action buy is turned
+ // off as well
+ LLSelectMgr::getInstance()->
+ selectionSetClickAction(CLICK_ACTION_TOUCH);
+ }
+ else if (new_sale_info.isForSale()
+ && !old_sale_info.isForSale()
+ && old_click_action == CLICK_ACTION_TOUCH)
+ {
+ // If just turning on for-sale, preemptively turn on one-click buy
+ // unless user have a different click action set
+ LLSelectMgr::getInstance()->
+ selectionSetClickAction(CLICK_ACTION_BUY);
+ }
+}
+
+struct LLSelectionPayable : public LLSelectedObjectFunctor
+{
+ virtual bool apply(LLViewerObject* obj)
+ {
+ // can pay if you or your parent has money() event in script
+ LLViewerObject* parent = (LLViewerObject*)obj->getParent();
+ return (obj->flagTakesMoney() ||
+ (parent && parent->flagTakesMoney()));
+ }
+};
+
+static U8 string_value_to_click_action(std::string p_value)
+{
+ if (p_value == "Touch")
+ return CLICK_ACTION_TOUCH;
+ if (p_value == "Sit")
+ return CLICK_ACTION_SIT;
+ if (p_value == "Buy")
+ return CLICK_ACTION_BUY;
+ if (p_value == "Pay")
+ return CLICK_ACTION_PAY;
+ if (p_value == "Open")
+ return CLICK_ACTION_OPEN;
+ if (p_value == "Zoom")
+ return CLICK_ACTION_ZOOM;
+ return CLICK_ACTION_TOUCH;
+}
+
+// static
+void LLSidepanelTaskInfo::onCommitClickAction(LLUICtrl* ctrl, void*)
+{
+ LLComboBox* box = (LLComboBox*)ctrl;
+ if (!box) return;
+ std::string value = box->getValue().asString();
+ U8 click_action = string_value_to_click_action(value);
+ doClickAction(click_action);
+}
+
+// static
+void LLSidepanelTaskInfo::doClickAction(U8 click_action)
+{
+ if (click_action == CLICK_ACTION_BUY)
+ {
+ LLSaleInfo sale_info;
+ LLSelectMgr::getInstance()->selectGetSaleInfo(sale_info);
+ if (!sale_info.isForSale())
+ {
+ LLNotificationsUtil::add("CantSetBuyObject");
+
+ // Set click action back to its old value
+ U8 click_action = 0;
+ LLSelectMgr::getInstance()->selectionGetClickAction(&click_action);
+// box->setCurrentByIndex((S32)click_action);
+
+ return;
+ }
+ }
+ else if (click_action == CLICK_ACTION_PAY)
+ {
+ // Verify object has script with money() handler
+ LLSelectionPayable payable;
+ bool can_pay = LLSelectMgr::getInstance()->getSelection()->applyToObjects(&payable);
+ if (!can_pay)
+ {
+ // Warn, but do it anyway.
+ LLNotificationsUtil::add("ClickActionNotPayable");
+ }
+ }
+ LLSelectMgr::getInstance()->selectionSetClickAction(click_action);
+}
+
+// static
+void LLSidepanelTaskInfo::onCommitIncludeInSearch(LLUICtrl* ctrl, void* data)
+{
+ LLCheckBoxCtrl* box = (LLCheckBoxCtrl*)ctrl;
+ llassert(box);
+ LLSelectMgr::getInstance()->selectionSetIncludeInSearch(box->get());
+}
+
+// virtual
+void LLSidepanelTaskInfo::updateVerbs()
+{
+ LLSidepanelInventorySubpanel::updateVerbs();
+
+ /*
+ mOpenBtn->setVisible(!getIsEditing());
+ mPayBtn->setVisible(!getIsEditing());
+ mBuyBtn->setVisible(!getIsEditing());
+ //const LLViewerObject *obj = getFirstSelectedObject();
+ //mEditBtn->setEnabled(obj && obj->permModify());
+ */
+
+ mOpenBtn->setEnabled(enable_object_open());
+ mPayBtn->setEnabled(enable_pay_object());
+ mBuyBtn->setEnabled(enable_buy_object());
+}
+
+void LLSidepanelTaskInfo::onOpenButtonClicked()
+{
+ if (enable_object_open())
+ {
+ handle_object_open();
+ }
+}
+
+void LLSidepanelTaskInfo::onPayButtonClicked()
+{
+ doClickAction(CLICK_ACTION_PAY);
+}
+
+void LLSidepanelTaskInfo::onBuyButtonClicked()
+{
+ doClickAction(CLICK_ACTION_BUY);
+}
+
+// virtual
+void LLSidepanelTaskInfo::save()
+{
+ onCommitGroupShare(getChild<LLCheckBoxCtrl>("checkbox share with group"), this);
+ onCommitEveryoneMove(getChild<LLCheckBoxCtrl>("checkbox allow everyone move"), this);
+ onCommitEveryoneCopy(getChild<LLCheckBoxCtrl>("checkbox allow everyone copy"), this);
+ onCommitNextOwnerModify(getChild<LLCheckBoxCtrl>("checkbox next owner can modify"), this);
+ onCommitNextOwnerCopy(getChild<LLCheckBoxCtrl>("checkbox next owner can copy"), this);
+ onCommitNextOwnerTransfer(getChild<LLCheckBoxCtrl>("checkbox next owner can transfer"), this);
+ onCommitName(getChild<LLLineEditor>("Object Name"), this);
+ onCommitDesc(getChild<LLLineEditor>("Object Description"), this);
+ onCommitSaleInfo(NULL, this);
+ onCommitSaleType(NULL, this);
+ onCommitIncludeInSearch(getChild<LLCheckBoxCtrl>("search_check"), this);
+}
+
+void LLSidepanelTaskInfo::setObjectSelection(LLObjectSelectionHandle selection)
+{
+ mObjectSelection = selection;
+}
+
+LLSidepanelTaskInfo* LLSidepanelTaskInfo::getActivePanel()
+{
+ return sActivePanel;
+}
+
+LLViewerObject* LLSidepanelTaskInfo::getObject()
+{
+ if (!mObject->isDead())
+ return mObject;
+ return NULL;
+}
+
+LLViewerObject* LLSidepanelTaskInfo::getFirstSelectedObject()
+{
+ LLSelectNode *node = mObjectSelection->getFirstRootNode();
+ if (node)
+ {
+ return node->getObject();
+ }
+ return NULL;
+}
+
+const LLUUID& LLSidepanelTaskInfo::getSelectedUUID()
+{
+ const LLViewerObject* obj = getFirstSelectedObject();
+ if (obj)
+ {
+ return obj->getID();
+ }
+ return LLUUID::null;
+}
diff --git a/indra/newview/llsidepaneltaskinfo.h b/indra/newview/llsidepaneltaskinfo.h
new file mode 100644
index 0000000000..cf36c20767
--- /dev/null
+++ b/indra/newview/llsidepaneltaskinfo.h
@@ -0,0 +1,126 @@
+/**
+ * @file llsidepaneltaskinfo.h
+ * @brief LLSidepanelTaskInfo class header file
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSIDEPANELTASKINFO_H
+#define LL_LLSIDEPANELTASKINFO_H
+
+#include "llsidepanelinventorysubpanel.h"
+#include "lluuid.h"
+#include "llselectmgr.h"
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLSidepanelTaskInfo
+//
+// Panel for permissions of an object.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLNameBox;
+class LLCheckBoxCtrl;
+class LLViewerObject;
+
+class LLSidepanelTaskInfo : public LLSidepanelInventorySubpanel
+{
+public:
+ LLSidepanelTaskInfo();
+ virtual ~LLSidepanelTaskInfo();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void setVisible(BOOL visible);
+
+ void setObjectSelection(LLObjectSelectionHandle selection);
+
+ const LLUUID& getSelectedUUID();
+ LLViewerObject* getFirstSelectedObject();
+
+ static LLSidepanelTaskInfo *getActivePanel();
+protected:
+ /*virtual*/ void refresh(); // refresh all labels as needed
+ /*virtual*/ void save();
+ /*virtual*/ void updateVerbs();
+
+ // statics
+ static void onClickClaim(void*);
+ static void onClickRelease(void*);
+ void onClickGroup();
+ void cbGroupID(LLUUID group_id);
+ static void onClickDeedToGroup(void*);
+
+ static void onCommitPerm(LLUICtrl *ctrl, void *data, U8 field, U32 perm);
+
+ static void onCommitGroupShare(LLUICtrl *ctrl, void *data);
+
+ static void onCommitEveryoneMove(LLUICtrl *ctrl, void *data);
+ static void onCommitEveryoneCopy(LLUICtrl *ctrl, void *data);
+
+ static void onCommitNextOwnerModify(LLUICtrl* ctrl, void* data);
+ static void onCommitNextOwnerCopy(LLUICtrl* ctrl, void* data);
+ static void onCommitNextOwnerTransfer(LLUICtrl* ctrl, void* data);
+
+ static void onCommitName(LLUICtrl* ctrl, void* data);
+ static void onCommitDesc(LLUICtrl* ctrl, void* data);
+
+ static void onCommitSaleInfo(LLUICtrl* ctrl, void* data);
+ static void onCommitSaleType(LLUICtrl* ctrl, void* data);
+ void setAllSaleInfo();
+
+ static void onCommitClickAction(LLUICtrl* ctrl, void* data);
+ static void onCommitIncludeInSearch(LLUICtrl* ctrl, void*);
+
+ static void doClickAction(U8 click_action);
+ void disableAll();
+
+private:
+ LLNameBox* mLabelGroupName; // group name
+
+ LLUUID mCreatorID;
+ LLUUID mOwnerID;
+ LLUUID mLastOwnerID;
+
+protected:
+ void onOpenButtonClicked();
+ void onPayButtonClicked();
+ void onBuyButtonClicked();
+private:
+ LLButton* mOpenBtn;
+ LLButton* mPayBtn;
+ LLButton* mBuyBtn;
+
+protected:
+ LLViewerObject* getObject();
+private:
+ LLViewerObject* mObject;
+ LLObjectSelectionHandle mObjectSelection;
+ static LLSidepanelTaskInfo* sActivePanel;
+};
+
+
+#endif // LL_LLSIDEPANELTASKINFO_H
diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp
new file mode 100644
index 0000000000..50c47e293e
--- /dev/null
+++ b/indra/newview/llsidetray.cpp
@@ -0,0 +1,731 @@
+/**
+ * @file llsidetray.cpp
+ * @brief SideBar implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lltextbox.h"
+
+#include "llagent.h"
+#include "llbottomtray.h"
+#include "llsidetray.h"
+#include "llviewerwindow.h"
+#include "llaccordionctrl.h"
+#include "llfocusmgr.h"
+#include "llrootview.h"
+#include "llnavigationbar.h"
+
+#include "llaccordionctrltab.h"
+
+#include "llfloater.h" //for gFloaterView
+#include "lliconctrl.h"//for OpenClose tab icon
+#include "llsidetraypanelcontainer.h"
+#include "llwindow.h"//for SetCursor
+#include "lltransientfloatermgr.h"
+
+//#include "llscrollcontainer.h"
+
+using namespace std;
+
+static LLRootViewRegistry::Register<LLSideTray> t1("side_tray");
+static LLDefaultChildRegistry::Register<LLSideTrayTab> t2("sidetray_tab");
+
+static const std::string COLLAPSED_NAME = "<<";
+static const std::string EXPANDED_NAME = ">>";
+
+static const std::string TAB_PANEL_CAPTION_NAME = "sidetray_tab_panel";
+static const std::string TAB_PANEL_CAPTION_TITLE_BOX = "sidetray_tab_title";
+
+LLSideTray* LLSideTray::sInstance = 0;
+
+LLSideTray* LLSideTray::getInstance()
+{
+ if (!sInstance)
+ {
+ sInstance = LLUICtrlFactory::createFromFile<LLSideTray>("panel_side_tray.xml",NULL, LLRootView::child_registry_t::instance());
+ sInstance->setXMLFilename("panel_side_tray.xml");
+ }
+
+ return sInstance;
+}
+
+bool LLSideTray::instanceCreated ()
+{
+ return sInstance!=0;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// LLSideTrayTab
+// Represents a single tab in the side tray, only used by LLSideTray
+//////////////////////////////////////////////////////////////////////////////
+
+class LLSideTrayTab: public LLPanel
+{
+ friend class LLUICtrlFactory;
+ friend class LLSideTray;
+public:
+
+ struct Params
+ : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ // image name
+ Optional<std::string> image;
+ Optional<std::string> image_selected;
+ Optional<std::string> tab_title;
+ Optional<std::string> description;
+ Params()
+ : image("image"),
+ image_selected("image_selected"),
+ tab_title("tab_title","no title"),
+ description("description","no description")
+ {};
+ };
+protected:
+ LLSideTrayTab(const Params& params);
+
+
+public:
+ virtual ~LLSideTrayTab();
+
+ /*virtual*/ BOOL postBuild ();
+ /*virtual*/ bool addChild (LLView* view, S32 tab_group);
+
+
+ void reshape (S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+ static LLSideTrayTab* createInstance ();
+
+ const std::string& getDescription () const { return mDescription;}
+ const std::string& getTabTitle() const { return mTabTitle;}
+
+ void onOpen (const LLSD& key);
+
+ LLPanel *getPanel();
+private:
+ std::string mTabTitle;
+ std::string mImage;
+ std::string mImageSelected;
+ std::string mDescription;
+
+ LLView* mMainPanel;
+};
+
+LLSideTrayTab::LLSideTrayTab(const Params& p)
+: LLPanel(),
+ mTabTitle(p.tab_title),
+ mImage(p.image),
+ mImageSelected(p.image_selected),
+ mDescription(p.description),
+ mMainPanel(NULL)
+{
+ // Necessary for focus movement among child controls
+ setFocusRoot(TRUE);
+}
+
+LLSideTrayTab::~LLSideTrayTab()
+{
+}
+
+bool LLSideTrayTab::addChild(LLView* view, S32 tab_group)
+{
+ if(mMainPanel == 0 && TAB_PANEL_CAPTION_NAME != view->getName())//skip our caption panel
+ mMainPanel = view;
+ return LLPanel::addChild(view,tab_group);
+ //return res;
+}
+
+
+
+//virtual
+BOOL LLSideTrayTab::postBuild()
+{
+ LLPanel* title_panel = LLUICtrlFactory::getInstance()->createFromFile<LLPanel>("panel_side_tray_tab_caption.xml",this, child_registry_t::instance());
+ string name = title_panel->getName();
+ LLPanel::addChild(title_panel);
+
+ title_panel->getChild<LLTextBox>(TAB_PANEL_CAPTION_TITLE_BOX)->setValue(mTabTitle);
+
+ return true;
+}
+
+static const S32 splitter_margin = 1;
+
+void LLSideTrayTab::reshape (S32 width, S32 height, BOOL called_from_parent )
+{
+ LLPanel::reshape(width, height, called_from_parent);
+ LLView* title_panel = findChildView(TAB_PANEL_CAPTION_NAME, true);
+ if (!title_panel)
+ {
+ // not fully constructed yet
+ return;
+ }
+
+ S32 title_height = title_panel->getRect().getHeight();
+ title_panel->setOrigin( 0, height - title_height );
+ title_panel->reshape(width,title_height);
+
+ LLRect sRect;
+ sRect.setLeftTopAndSize( splitter_margin, height - title_height - splitter_margin,
+ width - 2*splitter_margin, height - title_height - 2*splitter_margin);
+ mMainPanel->setShape(sRect);
+}
+
+void LLSideTrayTab::onOpen (const LLSD& key)
+{
+ LLPanel *panel = getPanel();
+ if(panel)
+ panel->onOpen(key);
+}
+
+LLPanel* LLSideTrayTab::getPanel()
+{
+ LLPanel* panel = dynamic_cast<LLPanel*>(mMainPanel);
+ return panel;
+}
+
+LLSideTrayTab* LLSideTrayTab::createInstance ()
+{
+ LLSideTrayTab::Params tab_params;
+ tab_params.tab_title("openclose");
+
+ LLSideTrayTab* tab = LLUICtrlFactory::create<LLSideTrayTab>(tab_params);
+ return tab;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// LLSideTray
+//////////////////////////////////////////////////////////////////////////////
+
+LLSideTray::Params::Params()
+: collapsed("collapsed",false),
+ tab_btn_image_normal("tab_btn_image","sidebar_tab_left.tga"),
+ tab_btn_image_selected("tab_btn_image_selected","button_enabled_selected_32x128.tga"),
+ default_button_width("tab_btn_width",32),
+ default_button_height("tab_btn_height",32),
+ default_button_margin("tab_btn_margin",0)
+{}
+
+//virtual
+LLSideTray::LLSideTray(Params& params)
+ : LLPanel(params)
+ ,mActiveTab(0)
+ ,mCollapsed(false)
+ ,mCollapseButton(0)
+{
+ mCollapsed=params.collapsed;
+
+ LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar();
+
+ // register handler function to process data from the xml.
+ // panel_name should be specified via "parameter" attribute.
+ commit.add("SideTray.ShowPanel", boost::bind(&LLSideTray::showPanel, this, _2, LLUUID::null));
+ LLTransientFloaterMgr::getInstance()->addControlView(this);
+
+ LLPanel::Params p;
+ p.name = "buttons_panel";
+ p.mouse_opaque = false;
+ mButtonsPanel = LLUICtrlFactory::create<LLPanel>(p);
+}
+
+
+BOOL LLSideTray::postBuild()
+{
+ createButtons();
+
+ arrange();
+ selectTabByName("sidebar_home");
+
+ if(mCollapsed)
+ collapseSideBar();
+
+ setMouseOpaque(false);
+ return true;
+}
+
+LLSideTrayTab* LLSideTray::getTab(const std::string& name)
+{
+ return getChild<LLSideTrayTab>(name,false);
+}
+
+
+void LLSideTray::toggleTabButton(LLSideTrayTab* tab)
+{
+ if(tab == NULL)
+ return;
+ std::string name = tab->getName();
+ std::map<std::string,LLButton*>::iterator it = mTabButtons.find(name);
+ if(it != mTabButtons.end())
+ {
+ LLButton* btn = it->second;
+ bool new_state = !btn->getToggleState();
+ btn->setToggleState(new_state);
+ btn->setImageOverlay( new_state ? tab->mImageSelected : tab->mImage );
+ }
+}
+
+bool LLSideTray::selectTabByIndex(size_t index)
+{
+ if(index>=mTabs.size())
+ return false;
+
+ LLSideTrayTab* sidebar_tab = mTabs[index];
+ return selectTabByName(sidebar_tab->getName());
+}
+
+bool LLSideTray::selectTabByName (const std::string& name)
+{
+ LLSideTrayTab* side_bar = getTab(name);
+
+ if(side_bar == mActiveTab)
+ return false;
+ //deselect old tab
+ toggleTabButton(mActiveTab);
+ if(mActiveTab)
+ mActiveTab->setVisible(false);
+
+ //select new tab
+ mActiveTab = side_bar;
+ toggleTabButton(mActiveTab);
+ LLSD key;//empty
+ mActiveTab->onOpen(key);
+
+ mActiveTab->setVisible(true);
+
+ //arrange();
+
+ //hide all tabs - show active tab
+ child_vector_const_iter_t child_it;
+ for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it)
+ {
+ LLSideTrayTab* sidebar_tab = *child_it;
+ sidebar_tab->setVisible(sidebar_tab == mActiveTab);
+ }
+ return true;
+}
+
+LLButton* LLSideTray::createButton (const std::string& name,const std::string& image,const std::string& tooltip,
+ LLUICtrl::commit_callback_t callback)
+{
+ static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>());
+
+ LLButton::Params bparams;
+
+ LLRect rect;
+ rect.setOriginAndSize(0, 0, sidetray_params.default_button_width, sidetray_params.default_button_height);
+
+ bparams.name(name);
+ bparams.follows.flags (FOLLOWS_LEFT | FOLLOWS_TOP);
+ bparams.rect (rect);
+ bparams.tab_stop(false);
+ bparams.image_unselected.name(sidetray_params.tab_btn_image_normal);
+ bparams.image_selected.name(sidetray_params.tab_btn_image_selected);
+ bparams.image_disabled.name(sidetray_params.tab_btn_image_normal);
+ bparams.image_disabled_selected.name(sidetray_params.tab_btn_image_selected);
+
+ LLButton* button = LLUICtrlFactory::create<LLButton> (bparams);
+ button->setLabel(name);
+ button->setClickedCallback(callback);
+
+ button->setToolTip(tooltip);
+
+ if(image.length())
+ {
+ button->setImageOverlay(image);
+ }
+
+ mButtonsPanel->addChildInBack(button);
+
+ return button;
+}
+
+bool LLSideTray::addChild(LLView* view, S32 tab_group)
+{
+ LLSideTrayTab* tab_panel = dynamic_cast<LLSideTrayTab*>(view);
+
+ if (tab_panel)
+ {
+ mTabs.push_back(tab_panel);
+ }
+
+ return LLUICtrl::addChild(view, tab_group);
+}
+
+
+void LLSideTray::createButtons ()
+{
+ //create buttons for tabs
+ child_vector_const_iter_t child_it = mTabs.begin();
+ for ( ; child_it != mTabs.end(); ++child_it)
+ {
+ LLSideTrayTab* sidebar_tab = *child_it;
+
+ std::string name = sidebar_tab->getName();
+
+ // The "OpenClose" button will open/close the whole panel
+ if (name == "sidebar_openclose")
+ {
+ mCollapseButton = createButton("",sidebar_tab->mImage,sidebar_tab->getTabTitle(),
+ boost::bind(&LLSideTray::onToggleCollapse, this));
+ }
+ else
+ {
+ LLButton* button = createButton("",sidebar_tab->mImage,sidebar_tab->getTabTitle(),
+ boost::bind(&LLSideTray::onTabButtonClick, this, name));
+ mTabButtons[name] = button;
+ }
+ }
+}
+
+void LLSideTray::processTriState ()
+{
+ if(mCollapsed)
+ expandSideBar();
+ else
+ {
+#if 0 // *TODO: EXT-2092
+
+ // Tell the active task panel to switch to its default view
+ // or collapse side tray if already on the default view.
+ LLSD info;
+ info["task-panel-action"] = "handle-tri-state";
+ mActiveTab->notifyChildren(info);
+#else
+ collapseSideBar();
+#endif
+ }
+}
+
+void LLSideTray::onTabButtonClick(string name)
+{
+ LLSideTrayTab* side_bar = getTab(name);
+ if(side_bar == mActiveTab)
+ {
+ processTriState ();
+ return;
+ }
+ selectTabByName (name);
+ if(mCollapsed)
+ expandSideBar();
+}
+
+void LLSideTray::onToggleCollapse()
+{
+ if(mCollapsed)
+ {
+ expandSideBar();
+ //selectTabByName("sidebar_openclose");
+ }
+ else
+ collapseSideBar();
+}
+
+
+void LLSideTray::reflectCollapseChange()
+{
+ updateSidetrayVisibility();
+
+ if(mCollapsed)
+ {
+ gFloaterView->setSnapOffsetRight(0);
+ setFocus(FALSE);
+ }
+ else
+ {
+ gFloaterView->setSnapOffsetRight(getRect().getWidth());
+ setFocus(TRUE);
+ }
+
+ gFloaterView->refresh();
+}
+
+void LLSideTray::arrange()
+{
+ static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>());
+
+ updateSidetrayVisibility();
+
+ LLRect ctrl_rect;
+ ctrl_rect.setLeftTopAndSize(0,
+ mButtonsPanel->getRect().getHeight() - sidetray_params.default_button_width,
+ sidetray_params.default_button_width,
+ sidetray_params.default_button_height);
+
+ mCollapseButton->setRect(ctrl_rect);
+
+ //arrange tab buttons
+ //arrange tab buttons
+ child_vector_const_iter_t child_it;
+ int offset = (sidetray_params.default_button_height+sidetray_params.default_button_margin)*2;
+ for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it)
+ {
+ LLSideTrayTab* sidebar_tab = *child_it;
+
+ ctrl_rect.setLeftTopAndSize(0,
+ mButtonsPanel->getRect().getHeight()-offset,
+ sidetray_params.default_button_width,
+ sidetray_params.default_button_height);
+
+ if(mTabButtons.find(sidebar_tab->getName()) == mTabButtons.end())
+ continue;
+
+ LLButton* btn = mTabButtons[sidebar_tab->getName()];
+
+ btn->setRect(ctrl_rect);
+ offset+=sidetray_params.default_button_height;
+ offset+=sidetray_params.default_button_margin;
+
+ btn->setVisible(ctrl_rect.mBottom > 0);
+ }
+
+ //arrange tabs
+ for ( child_vector_t::iterator child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it)
+ {
+ LLSideTrayTab* sidebar_tab = *child_it;
+ sidebar_tab->setShape(getLocalRect());
+ }
+}
+
+void LLSideTray::collapseSideBar()
+{
+ mCollapsed = true;
+ // Reset all overlay images, because there is no "selected" tab when the
+ // whole side tray is hidden.
+ child_vector_const_iter_t it = mTabs.begin();
+ for ( ; it != mTabs.end(); ++it )
+ {
+ LLSideTrayTab* tab = *it;
+ std::string name = tab->getName();
+ std::map<std::string,LLButton*>::const_iterator btn_it =
+ mTabButtons.find(name);
+ if (btn_it != mTabButtons.end())
+ {
+ LLButton* btn = btn_it->second;
+ btn->setImageOverlay( tab->mImage );
+ }
+ }
+
+ // OpenClose tab doesn't put its button in mTabButtons
+ LLSideTrayTab* openclose_tab = getTab("sidebar_openclose");
+ if (openclose_tab)
+ {
+ mCollapseButton->setImageOverlay( openclose_tab->mImage );
+ }
+ //mActiveTab->setVisible(FALSE);
+ reflectCollapseChange();
+ setFocus( FALSE );
+
+}
+
+void LLSideTray::expandSideBar()
+{
+ mCollapsed = false;
+ LLSideTrayTab* openclose_tab = getTab("sidebar_openclose");
+ if (openclose_tab)
+ {
+ mCollapseButton->setImageOverlay( openclose_tab->mImageSelected );
+ }
+ LLSD key;//empty
+ mActiveTab->onOpen(key);
+
+ reflectCollapseChange();
+
+
+ std::string name = mActiveTab->getName();
+ std::map<std::string,LLButton*>::const_iterator btn_it =
+ mTabButtons.find(name);
+ if (btn_it != mTabButtons.end())
+ {
+ LLButton* btn = btn_it->second;
+ btn->setImageOverlay( mActiveTab->mImageSelected );
+ }
+
+}
+
+void LLSideTray::highlightFocused()
+{
+ /* uncomment in case something change
+ if(!mActiveTab)
+ return;
+ BOOL dependent_has_focus = gFocusMgr.childHasKeyboardFocus(this);
+ setBackgroundOpaque( dependent_has_focus );
+ mActiveTab->setBackgroundOpaque( dependent_has_focus );
+ */
+}
+
+//virtual
+BOOL LLSideTray::handleMouseDown (S32 x, S32 y, MASK mask)
+{
+ BOOL ret = LLPanel::handleMouseDown(x,y,mask);
+ if(ret)
+ setFocus(true);
+ return ret;
+}
+
+void LLSideTray::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ LLPanel::reshape(width, height, called_from_parent);
+ if(!mActiveTab)
+ return;
+
+ arrange();
+}
+
+/**
+ * Activate tab with "panel_name" panel
+ * if no such tab - return false, otherwise true.
+ * TODO* In some cases a pointer to a panel of
+ * a specific class may be needed so this method
+ * would need to use templates.
+ */
+LLPanel* LLSideTray::showPanel (const std::string& panel_name, const LLSD& params)
+{
+ //arrange tabs
+ child_vector_const_iter_t child_it;
+ for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it)
+ {
+ LLView* view = (*child_it)->findChildView(panel_name,true);
+ if(view)
+ {
+ selectTabByName ((*child_it)->getName());
+ if(mCollapsed)
+ expandSideBar();
+
+ LLSideTrayPanelContainer* container = dynamic_cast<LLSideTrayPanelContainer*>(view->getParent());
+ if(container)
+ {
+ LLSD new_params = params;
+ new_params[LLSideTrayPanelContainer::PARAM_SUB_PANEL_NAME] = panel_name;
+ container->onOpen(new_params);
+
+ return container->getCurrentPanel();
+ }
+
+ LLPanel* panel = dynamic_cast<LLPanel*>(view);
+ if(panel)
+ {
+ panel->onOpen(params);
+ }
+ return panel;
+ }
+ }
+ return NULL;
+}
+
+void LLSideTray::togglePanel(LLPanel* &sub_panel, const std::string& panel_name, const LLSD& params)
+{
+ if(!sub_panel)
+ return;
+
+ if (sub_panel->isInVisibleChain())
+ {
+ LLSideTray::getInstance()->collapseSideBar();
+ }
+ else
+ {
+ LLSideTray::getInstance()->showPanel(panel_name, params);
+ }
+}
+
+// This is just LLView::findChildView specialized to restrict the search to LLPanels.
+// Optimization for EXT-4068 to avoid searching down to the individual item level
+// when inventories are large.
+LLPanel *findChildPanel(LLPanel *panel, const std::string& name, bool recurse)
+{
+ for (LLView::child_list_const_iter_t child_it = panel->beginChild();
+ child_it != panel->endChild(); ++child_it)
+ {
+ LLPanel *child_panel = dynamic_cast<LLPanel*>(*child_it);
+ if (!child_panel)
+ continue;
+ if (child_panel->getName() == name)
+ return child_panel;
+ }
+ if (recurse)
+ {
+ for (LLView::child_list_const_iter_t child_it = panel->beginChild();
+ child_it != panel->endChild(); ++child_it)
+ {
+ LLPanel *child_panel = dynamic_cast<LLPanel*>(*child_it);
+ if (!child_panel)
+ continue;
+ LLPanel *found_panel = findChildPanel(child_panel,name,recurse);
+ if (found_panel)
+ {
+ return found_panel;
+ }
+ }
+ }
+ return NULL;
+}
+
+LLPanel* LLSideTray::getPanel(const std::string& panel_name)
+{
+ for ( child_vector_const_iter_t child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it)
+ {
+ LLPanel *panel = findChildPanel(*child_it,panel_name,true);
+ if(panel)
+ {
+ return panel;
+ }
+ }
+ return NULL;
+}
+
+LLPanel* LLSideTray::getActivePanel()
+{
+ if (mActiveTab && !mCollapsed)
+ {
+ return mActiveTab->getPanel();
+ }
+ return NULL;
+}
+
+bool LLSideTray::isPanelActive(const std::string& panel_name)
+{
+ LLPanel *panel = getActivePanel();
+ if (!panel) return false;
+ return (panel->getName() == panel_name);
+}
+
+
+// *TODO: Eliminate magic constants.
+static const S32 fake_offset = 132;
+static const S32 fake_top_offset = 18;
+
+void LLSideTray::updateSidetrayVisibility()
+{
+ // set visibility of parent container based on collapsed state
+ if (getParent())
+ {
+ getParent()->setVisible(!mCollapsed && !gAgent.cameraMouselook());
+ }
+}
+
diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h
new file mode 100644
index 0000000000..b1c8675793
--- /dev/null
+++ b/indra/newview/llsidetray.h
@@ -0,0 +1,195 @@
+/**
+ * @file LLSideTray.h
+ * @brief SideBar header file
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSIDETRAY_H_
+#define LL_LLSIDETRAY_H_
+
+#include "llpanel.h"
+#include "string"
+
+class LLAccordionCtrl;
+class LLSideTrayTab;
+
+// added inheritance from LLDestroyClass<LLSideTray> to enable Side Tray perform necessary actions
+// while disconnecting viewer in LLAppViewer::disconnectViewer().
+// LLDestroyClassList::instance().fireCallbacks() calls destroyClass method. See EXT-245.
+class LLSideTray : public LLPanel, private LLDestroyClass<LLSideTray>
+{
+ friend class LLUICtrlFactory;
+ friend class LLDestroyClass<LLSideTray>;
+public:
+
+ LOG_CLASS(LLSideTray);
+
+ struct Params
+ : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ // initial state
+ Optional<bool> collapsed;
+ Optional<std::string> tab_btn_image_normal;
+ Optional<std::string> tab_btn_image_selected;
+
+ Optional<S32> default_button_width;
+ Optional<S32> default_button_height;
+ Optional<S32> default_button_margin;
+
+ Params();
+ };
+
+ static LLSideTray* getInstance ();
+ static bool instanceCreated ();
+protected:
+ LLSideTray(Params& params);
+ typedef std::vector<LLSideTrayTab*> child_vector_t;
+ typedef child_vector_t::iterator child_vector_iter_t;
+ typedef child_vector_t::const_iterator child_vector_const_iter_t;
+ typedef child_vector_t::reverse_iterator child_vector_reverse_iter_t;
+ typedef child_vector_t::const_reverse_iterator child_vector_const_reverse_iter_t;
+
+public:
+
+ // interface functions
+
+ /**
+ * Select tab with specific name and set it active
+ */
+ bool selectTabByName (const std::string& name);
+
+ /**
+ * Select tab with specific index and set it active
+ */
+ bool selectTabByIndex(size_t index);
+
+ /**
+ * Activate tab with "panel_name" panel
+ * if no such tab - return NULL, otherwise a pointer to the panel
+ * Pass params as array, or they may be overwritten(example - params["name"]="nearby")
+ */
+ LLPanel* showPanel (const std::string& panel_name, const LLSD& params);
+
+ /**
+ * Toggling Side Tray tab which contains "sub_panel" child of "panel_name" panel.
+ * If "sub_panel" is not visible Side Tray is opened to display it,
+ * otherwise Side Tray is collapsed.
+ * params are passed to "panel_name" panel onOpen().
+ */
+ void togglePanel (LLPanel* &sub_panel, const std::string& panel_name, const LLSD& params);
+
+ /*
+ * get the panel (don't show it or do anything else with it)
+ */
+ LLPanel* getPanel (const std::string& panel_name);
+ LLPanel* getActivePanel ();
+ bool isPanelActive (const std::string& panel_name);
+ /*
+ * get currently active tab
+ */
+ const LLSideTrayTab* getActiveTab() const { return mActiveTab; }
+
+ /*
+ * collapse SideBar, hiding visible tab and moving tab buttons
+ * to the right corner of the screen
+ */
+ void collapseSideBar ();
+
+ /*
+ * expand SideBar
+ */
+ void expandSideBar ();
+
+
+ /**
+ *hightlight if focused. manly copypaste from highlightFocusedFloater
+ */
+ void highlightFocused();
+
+ void setVisible(BOOL visible)
+ {
+ if (getParent()) getParent()->setVisible(visible);
+ }
+
+ LLPanel* getButtonsPanel() { return mButtonsPanel; }
+
+public:
+ virtual ~LLSideTray(){};
+
+ virtual BOOL postBuild();
+
+ void onTabButtonClick(std::string name);
+ void onToggleCollapse();
+
+ bool addChild (LLView* view, S32 tab_group);
+
+ BOOL handleMouseDown (S32 x, S32 y, MASK mask);
+
+ void reshape (S32 width, S32 height, BOOL called_from_parent = TRUE);
+
+ void processTriState ();
+
+ void updateSidetrayVisibility();
+
+protected:
+ LLSideTrayTab* getTab (const std::string& name);
+
+ void createButtons ();
+ LLButton* createButton (const std::string& name,const std::string& image,const std::string& tooltip,
+ LLUICtrl::commit_callback_t callback);
+ void arrange ();
+ void reflectCollapseChange();
+
+ void toggleTabButton (LLSideTrayTab* tab);
+
+private:
+ // Implementation of LLDestroyClass<LLSideTray>
+ static void destroyClass()
+ {
+ // Disable SideTray to avoid crashes. EXT-245
+ if (LLSideTray::instanceCreated())
+ LLSideTray::getInstance()->setEnabled(FALSE);
+ }
+
+private:
+
+ LLPanel* mButtonsPanel;
+ typedef std::map<std::string,LLButton*> button_map_t;
+ button_map_t mTabButtons;
+ child_vector_t mTabs;
+ LLSideTrayTab* mActiveTab;
+
+ LLButton* mCollapseButton;
+ bool mCollapsed;
+
+ static LLSideTray* sInstance;
+};
+
+#endif
+
diff --git a/indra/newview/llsidetraypanelcontainer.cpp b/indra/newview/llsidetraypanelcontainer.cpp
new file mode 100644
index 0000000000..f2215a2250
--- /dev/null
+++ b/indra/newview/llsidetraypanelcontainer.cpp
@@ -0,0 +1,92 @@
+/**
+* @file llsidetraypanelcontainer.cpp
+* @brief LLSideTrayPanelContainer implementation
+*
+* $LicenseInfo:firstyear=2001&license=viewergpl$
+*
+* Copyright (c) 2001-2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+#include "llsidetraypanelcontainer.h"
+
+static LLDefaultChildRegistry::Register<LLSideTrayPanelContainer> r2("panel_container");
+
+std::string LLSideTrayPanelContainer::PARAM_SUB_PANEL_NAME = "sub_panel_name";
+
+LLSideTrayPanelContainer::Params::Params()
+ : default_panel_name("default_panel_name")
+{
+ // Always hide tabs.
+ hide_tabs(true);
+}
+
+LLSideTrayPanelContainer::LLSideTrayPanelContainer(const Params& p)
+ : LLTabContainer(p)
+ , mDefaultPanelName(p.default_panel_name)
+{
+}
+
+void LLSideTrayPanelContainer::onOpen(const LLSD& key)
+{
+ // Select specified panel and save navigation history.
+ if(key.has(PARAM_SUB_PANEL_NAME))
+ {
+ //*NOTE dzaporozhan
+ // Navigation history is not used after fix for EXT-3186,
+ // openPreviousPanel() always opens default panel
+
+ // Save panel navigation history
+ std::string panel_name = key[PARAM_SUB_PANEL_NAME];
+
+ selectTabByName(panel_name);
+ }
+ // Will reopen current panel if no panel name was passed.
+ getCurrentPanel()->onOpen(key);
+}
+
+void LLSideTrayPanelContainer::openPreviousPanel()
+{
+ if(!mDefaultPanelName.empty())
+ {
+ selectTabByName(mDefaultPanelName);
+ }
+ else
+ {
+ selectTab(0);
+ }
+}
+
+BOOL LLSideTrayPanelContainer::handleKeyHere(KEY key, MASK mask)
+{
+ // No key press handling code for Panel Container - this disables
+ // Tab Container's Alt + Left/Right Button tab switching.
+
+ // Let default handler process key presses, don't simply return TRUE or FALSE
+ // as this may brake some functionality as it did with Copy/Paste for
+ // text_editor (ticket EXT-642).
+ return LLPanel::handleKeyHere(key, mask);
+}
diff --git a/indra/newview/llsidetraypanelcontainer.h b/indra/newview/llsidetraypanelcontainer.h
new file mode 100644
index 0000000000..beed328269
--- /dev/null
+++ b/indra/newview/llsidetraypanelcontainer.h
@@ -0,0 +1,97 @@
+/**
+* @file llsidetraypanelcontainer.h
+* @brief LLSideTrayPanelContainer class declaration
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#ifndef LL_LLSIDETRAY_PANEL_CONTAINER_H
+#define LL_LLSIDETRAY_PANEL_CONTAINER_H
+
+#include "lltabcontainer.h"
+
+/**
+* LLSideTrayPanelContainer class acts like LLTabContainer with invisible tabs.
+* It is designed to make panel switching easier, avoid setVisible(TRUE) setVisible(FALSE)
+* calls and related workarounds.
+* use onOpen to open sub panel, pass the name of panel to open
+* in key[PARAM_SUB_PANEL_NAME].
+* LLSideTrayPanelContainer also implements panel navigation history - it allows to
+* open previous or next panel if navigation history is available(after user
+* has opened two or more panels). *NOTE - only back navigation is implemented so far.
+*/
+class LLSideTrayPanelContainer : public LLTabContainer
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLTabContainer::Params>
+ {
+ Optional<std::string> default_panel_name;
+ Params();
+ };
+
+ /**
+ * Opens sub panel
+ * @param key - params to be passed to panel, use key[PARAM_SUB_PANEL_NAME]
+ * to specify panel name to be opened.
+ */
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ /**
+ * Opens previous panel from panel navigation history.
+ */
+ void openPreviousPanel();
+
+ /**
+ * Overrides LLTabContainer::handleKeyHere to disable panel switch on
+ * Alt + Left/Right button press.
+ */
+ BOOL handleKeyHere(KEY key, MASK mask);
+
+ /**
+ * Name of parameter that stores panel name to open.
+ */
+ static std::string PARAM_SUB_PANEL_NAME;
+
+protected:
+ LLSideTrayPanelContainer(const Params& p);
+ friend class LLUICtrlFactory;
+
+ /**
+ * std::string - name of panel
+ * S32 - index of previous panel
+ * *NOTE - no forward navigation implemented yet
+ */
+ typedef std::map<std::string, S32> panel_navigation_history_t;
+
+ // Navigation history
+ panel_navigation_history_t mPanelHistory;
+ std::string mDefaultPanelName;
+};
+
+#endif //LL_LLSIDETRAY_PANEL_CONTAINER_H
diff --git a/indra/newview/llsky.cpp b/indra/newview/llsky.cpp
index b779aa0f83..de99cb86fa 100644
--- a/indra/newview/llsky.cpp
+++ b/indra/newview/llsky.cpp
@@ -52,7 +52,6 @@
#include "llviewerobject.h"
#include "llviewercamera.h"
#include "pipeline.h"
-#include "llagent.h"
#include "lldrawpool.h"
#include "llvosky.h"
@@ -67,6 +66,9 @@ F32 elevation_from_vector(const LLVector3 &v);
LLSky gSky;
// ---------------- LLSky ----------------
+const F32 LLSky::NIGHTTIME_ELEVATION = -8.0f; // degrees
+const F32 LLSky::NIGHTTIME_ELEVATION_COS = (F32)sin(NIGHTTIME_ELEVATION*DEG_TO_RAD);
+
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
@@ -422,20 +424,6 @@ void LLSky::updateFog(const F32 distance)
void LLSky::updateCull()
{
- /*if (mVOSkyp.notNull() && mVOSkyp->mDrawable.notNull())
- {
- gPipeline.markVisible(mVOSkyp->mDrawable);
- }
- else
- {
- llinfos << "No sky drawable!" << llendl;
- }*/
-
- /*if (mVOGroundp.notNull() && mVOGroundp->mDrawable.notNull())
- {
- gPipeline.markVisible(mVOGroundp->mDrawable);
- }*/
-
// *TODO: do culling for wl sky properly -Brad
}
diff --git a/indra/newview/llsky.h b/indra/newview/llsky.h
index abd4205e6c..d7796dea83 100644
--- a/indra/newview/llsky.h
+++ b/indra/newview/llsky.h
@@ -42,9 +42,6 @@
#include "llvosky.h"
#include "llvoground.h"
-const F32 NIGHTTIME_ELEVATION = -8.0f; // degrees
-const F32 NIGHTTIME_ELEVATION_COS = (F32)sin(NIGHTTIME_ELEVATION*DEG_TO_RAD);
-
class LLViewerCamera;
class LLVOWLSky;
@@ -111,6 +108,9 @@ public:
// Legacy stuff
LLVector3 mSunDefaultPosition;
+ static const F32 NIGHTTIME_ELEVATION; // degrees
+ static const F32 NIGHTTIME_ELEVATION_COS;
+
protected:
BOOL mOverrideSimSunPosition;
diff --git a/indra/newview/llslurl.cpp b/indra/newview/llslurl.cpp
new file mode 100644
index 0000000000..37e268ad34
--- /dev/null
+++ b/indra/newview/llslurl.cpp
@@ -0,0 +1,153 @@
+/**
+ * @file llslurl.cpp
+ * @brief SLURL manipulation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llslurl.h"
+
+#include "llweb.h"
+
+const std::string LLSLURL::PREFIX_SL_HELP = "secondlife://app.";
+const std::string LLSLURL::PREFIX_SL = "sl://";
+const std::string LLSLURL::PREFIX_SECONDLIFE = "secondlife://";
+const std::string LLSLURL::PREFIX_SLURL = "http://slurl.com/secondlife/";
+
+const std::string LLSLURL::APP_TOKEN = "app/";
+
+// static
+std::string LLSLURL::stripProtocol(const std::string& url)
+{
+ std::string stripped = url;
+ if (matchPrefix(stripped, PREFIX_SL_HELP))
+ {
+ stripped.erase(0, PREFIX_SL_HELP.length());
+ }
+ else if (matchPrefix(stripped, PREFIX_SL))
+ {
+ stripped.erase(0, PREFIX_SL.length());
+ }
+ else if (matchPrefix(stripped, PREFIX_SECONDLIFE))
+ {
+ stripped.erase(0, PREFIX_SECONDLIFE.length());
+ }
+ else if (matchPrefix(stripped, PREFIX_SLURL))
+ {
+ stripped.erase(0, PREFIX_SLURL.length());
+ }
+
+ return stripped;
+}
+
+// static
+bool LLSLURL::isSLURL(const std::string& url)
+{
+ if (matchPrefix(url, PREFIX_SL_HELP)) return true;
+ if (matchPrefix(url, PREFIX_SL)) return true;
+ if (matchPrefix(url, PREFIX_SECONDLIFE)) return true;
+ if (matchPrefix(url, PREFIX_SLURL)) return true;
+
+ return false;
+}
+
+// static
+bool LLSLURL::isSLURLCommand(const std::string& url)
+{
+ if (matchPrefix(url, PREFIX_SL + APP_TOKEN) ||
+ matchPrefix(url, PREFIX_SECONDLIFE + "/" + APP_TOKEN) ||
+ matchPrefix(url, PREFIX_SLURL + APP_TOKEN) )
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// static
+bool LLSLURL::isSLURLHelp(const std::string& url)
+{
+ return matchPrefix(url, PREFIX_SL_HELP);
+}
+
+// static
+std::string LLSLURL::buildSLURL(const std::string& regionname, S32 x, S32 y, S32 z)
+{
+ std::string slurl = PREFIX_SLURL + regionname + llformat("/%d/%d/%d",x,y,z);
+ slurl = LLWeb::escapeURL( slurl );
+ return slurl;
+}
+
+// static
+std::string LLSLURL::buildCommand(const char* noun, const LLUUID& id, const char* verb)
+{
+ std::string slurl = llformat("secondlife:///app/%s/%s/%s",
+ noun, id.asString().c_str(), verb);
+ return slurl;
+}
+
+// static
+std::string LLSLURL::buildUnescapedSLURL(const std::string& regionname, S32 x, S32 y, S32 z)
+{
+ std::string unescapedslurl = PREFIX_SLURL + regionname + llformat("/%d/%d/%d",x,y,z);
+ return unescapedslurl;
+}
+
+// static
+std::string LLSLURL::buildSLURLfromPosGlobal(const std::string& regionname,
+ const LLVector3d& global_pos,
+ bool escaped /*= true*/)
+{
+ S32 x, y, z;
+ globalPosToXYZ(global_pos, x, y, z);
+ if(escaped)
+ {
+ return buildSLURL(regionname, x, y, z);
+ }
+ else
+ {
+ return buildUnescapedSLURL(regionname, x, y, z);
+ }
+}
+
+// static
+bool LLSLURL::matchPrefix(const std::string& url, const std::string& prefix)
+{
+ std::string test_prefix = url.substr(0, prefix.length());
+ LLStringUtil::toLower(test_prefix);
+ return test_prefix == prefix;
+}
+
+void LLSLURL::globalPosToXYZ(const LLVector3d& pos, S32& x, S32& y, S32& z)
+{
+ x = llround((F32)fmod(pos.mdV[VX], (F64)REGION_WIDTH_METERS));
+ y = llround((F32)fmod(pos.mdV[VY], (F64)REGION_WIDTH_METERS));
+ z = llround((F32)pos.mdV[VZ]);
+}
diff --git a/indra/newview/llslurl.h b/indra/newview/llslurl.h
new file mode 100644
index 0000000000..05b0143e72
--- /dev/null
+++ b/indra/newview/llslurl.h
@@ -0,0 +1,106 @@
+/**
+ * @file llslurl.h
+ * @brief SLURL manipulation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_SLURL_H
+#define LL_SLURL_H
+
+#include <string>
+
+// IAN BUG: where should this live?
+// IAN BUG: are static utility functions right? See LLUUID.
+// question of whether to have a LLSLURL object or a
+// some of this was moved from LLURLDispatcher
+
+/**
+ * SLURL manipulation
+ */
+class LLSLURL
+{
+public:
+ static const std::string PREFIX_SL_HELP;
+ static const std::string PREFIX_SL;
+ static const std::string PREFIX_SECONDLIFE;
+ static const std::string PREFIX_SLURL;
+
+ static const std::string APP_TOKEN;
+
+ /**
+ * Is this any sort of secondlife:// or sl:// URL?
+ */
+ static bool isSLURL(const std::string& url);
+
+ /**
+ * Is this a special secondlife://app/ URL?
+ */
+ static bool isSLURLCommand(const std::string& url);
+
+ /**
+ * Not sure what it is.
+ */
+ static bool isSLURLHelp(const std::string& url);
+
+ /**
+ * builds: http://slurl.com/secondlife/Region%20Name/x/y/z/ escaping result url.
+ */
+ static std::string buildSLURL(const std::string& regionname, S32 x, S32 y, S32 z);
+
+ /// Build a SLURL like secondlife:///app/agent/<uuid>/inspect
+ static std::string buildCommand(const char* noun, const LLUUID& id, const char* verb);
+
+ /**
+ * builds: http://slurl.com/secondlife/Region Name/x/y/z/ without escaping result url.
+ */
+ static std::string buildUnescapedSLURL(const std::string& regionname, S32 x, S32 y, S32 z);
+
+ /**
+ * builds SLURL from global position. Returns escaped or unescaped url.
+ * Returns escaped url by default.
+ */
+ static std::string buildSLURLfromPosGlobal(const std::string& regionname,
+ const LLVector3d& global_pos,
+ bool escaped = true);
+ /**
+ * Strip protocol part from the URL.
+ */
+ static std::string stripProtocol(const std::string& url);
+
+ /**
+ * Convert global position to X, Y Z
+ */
+ static void globalPosToXYZ(const LLVector3d& pos, S32& x, S32& y, S32& z);
+
+private:
+ static bool matchPrefix(const std::string& url, const std::string& prefix);
+
+};
+
+#endif
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index f8b824732f..514d8facb4 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -41,13 +41,16 @@
#include "llviewercamera.h"
#include "llface.h"
#include "llviewercontrol.h"
-#include "llagent.h"
#include "llviewerregion.h"
#include "llcamera.h"
#include "pipeline.h"
#include "llrender.h"
#include "lloctree.h"
#include "llvoavatar.h"
+#include "lltextureatlas.h"
+
+static LLFastTimer::DeclareTimer FTM_FRUSTUM_CULL("Frustum Culling");
+static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound");
const F32 SG_OCCLUSION_FUDGE = 0.25f;
#define SG_DISCARD_TOLERANCE 0.01f
@@ -86,8 +89,6 @@ protected:
static LLOcclusionQueryPool sQueryPool;
-BOOL LLSpatialPartition::sFreezeState = FALSE;
-
//static counter for frame to switch LOD on
void sg_assert(BOOL expr)
@@ -281,10 +282,10 @@ S32 LLSphereAABB(const LLVector3& center, const LLVector3& size, const LLVector3
LLSpatialGroup::~LLSpatialGroup()
{
- if (sNoDelete)
+ /*if (sNoDelete)
{
llerrs << "Illegal deletion of LLSpatialGroup!" << llendl;
- }
+ }*/
if (isState(DEAD))
{
@@ -295,13 +296,136 @@ LLSpatialGroup::~LLSpatialGroup()
if (gGLManager.mHasOcclusionQuery && mOcclusionQuery)
{
- sQueryPool.release(mOcclusionQuery);
+ sQueryPool.release(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
}
delete [] mOcclusionVerts;
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
clearDrawMap();
+ clearAtlasList() ;
+}
+
+BOOL LLSpatialGroup::hasAtlas(LLTextureAtlas* atlasp)
+{
+ S8 type = atlasp->getComponents() - 1 ;
+ for(std::list<LLTextureAtlas*>::iterator iter = mAtlasList[type].begin(); iter != mAtlasList[type].end() ; ++iter)
+ {
+ if(atlasp == *iter)
+ {
+ return TRUE ;
+ }
+ }
+ return FALSE ;
+}
+
+void LLSpatialGroup::addAtlas(LLTextureAtlas* atlasp, S8 recursive_level)
+{
+ if(!hasAtlas(atlasp))
+ {
+ mAtlasList[atlasp->getComponents() - 1].push_back(atlasp) ;
+ atlasp->addSpatialGroup(this) ;
+ }
+
+ --recursive_level;
+ if(recursive_level)//levels propagating up.
+ {
+ LLSpatialGroup* parent = getParent() ;
+ if(parent)
+ {
+ parent->addAtlas(atlasp, recursive_level) ;
+ }
+ }
+}
+
+void LLSpatialGroup::removeAtlas(LLTextureAtlas* atlasp, BOOL remove_group, S8 recursive_level)
+{
+ mAtlasList[atlasp->getComponents() - 1].remove(atlasp) ;
+ if(remove_group)
+ {
+ atlasp->removeSpatialGroup(this) ;
+ }
+
+ --recursive_level;
+ if(recursive_level)//levels propagating up.
+ {
+ LLSpatialGroup* parent = getParent() ;
+ if(parent)
+ {
+ parent->removeAtlas(atlasp, recursive_level) ;
+ }
+ }
+}
+
+void LLSpatialGroup::clearAtlasList()
+{
+ std::list<LLTextureAtlas*>::iterator iter ;
+ for(S8 i = 0 ; i < 4 ; i++)
+ {
+ if(mAtlasList[i].size() > 0)
+ {
+ for(iter = mAtlasList[i].begin(); iter != mAtlasList[i].end() ; ++iter)
+ {
+ ((LLTextureAtlas*)*iter)->removeSpatialGroup(this) ;
+ }
+ mAtlasList[i].clear() ;
+ }
+ }
+}
+
+LLTextureAtlas* LLSpatialGroup::getAtlas(S8 ncomponents, S8 to_be_reserved, S8 recursive_level)
+{
+ S8 type = ncomponents - 1 ;
+ if(mAtlasList[type].size() > 0)
+ {
+ for(std::list<LLTextureAtlas*>::iterator iter = mAtlasList[type].begin(); iter != mAtlasList[type].end() ; ++iter)
+ {
+ if(!((LLTextureAtlas*)*iter)->isFull(to_be_reserved))
+ {
+ return *iter ;
+ }
+ }
+ }
+
+ --recursive_level;
+ if(recursive_level)
+ {
+ LLSpatialGroup* parent = getParent() ;
+ if(parent)
+ {
+ return parent->getAtlas(ncomponents, to_be_reserved, recursive_level) ;
+ }
+ }
+ return NULL ;
+}
+
+void LLSpatialGroup::setCurUpdatingSlot(LLTextureAtlasSlot* slotp)
+{
+ mCurUpdatingSlotp = slotp;
+
+ //if(!hasAtlas(mCurUpdatingSlotp->getAtlas()))
+ //{
+ // addAtlas(mCurUpdatingSlotp->getAtlas()) ;
+ //}
+}
+
+LLTextureAtlasSlot* LLSpatialGroup::getCurUpdatingSlot(LLViewerTexture* imagep, S8 recursive_level)
+{
+ if(gFrameCount && mCurUpdatingTime == gFrameCount && mCurUpdatingTexture == imagep)
+ {
+ return mCurUpdatingSlotp ;
+ }
+
+ //--recursive_level ;
+ //if(recursive_level)
+ //{
+ // LLSpatialGroup* parent = getParent() ;
+ // if(parent)
+ // {
+ // return parent->getCurUpdatingSlot(imagep, recursive_level) ;
+ // }
+ //}
+ return NULL ;
}
void LLSpatialGroup::clearDrawMap()
@@ -309,17 +433,19 @@ void LLSpatialGroup::clearDrawMap()
mDrawMap.clear();
}
+BOOL LLSpatialGroup::isRecentlyVisible() const
+{
+ return (LLDrawable::getCurrentFrame() - mVisible[LLViewerCamera::sCurCameraID]) < LLDrawable::getMinVisFrameRange() ;
+}
+
BOOL LLSpatialGroup::isVisible() const
{
- return mVisible == LLDrawable::getCurrentFrame() ? TRUE : FALSE;
+ return mVisible[LLViewerCamera::sCurCameraID] == LLDrawable::getCurrentFrame() ? TRUE : FALSE;
}
void LLSpatialGroup::setVisible()
{
- if (!LLSpatialPartition::sFreezeState)
- {
- mVisible = LLDrawable::getCurrentFrame();
- }
+ mVisible[LLViewerCamera::sCurCameraID] = LLDrawable::getCurrentFrame();
}
void LLSpatialGroup::validate()
@@ -378,63 +504,6 @@ void LLSpatialGroup::validate()
#endif
}
-
-
-class LLOctreeStateCheck : public LLOctreeTraveler<LLDrawable>
-{
-public:
- U32 mInheritedMask;
-
- LLOctreeStateCheck(): mInheritedMask(0) { }
-
- virtual void traverse(const LLSpatialGroup::OctreeNode* node)
- {
- LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
-
- node->accept(this);
-
- U32 temp = mInheritedMask;
- mInheritedMask |= group->getState() &
- (LLSpatialGroup::OCCLUDED);
-
- for (U32 i = 0; i < node->getChildCount(); i++)
- {
- traverse(node->getChild(i));
- }
-
- mInheritedMask = temp;
- }
-
- virtual void visit(const LLOctreeNode<LLDrawable>* state)
- {
- LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0);
-
- if (mInheritedMask && !group->isState(mInheritedMask))
- {
- llerrs << "Spatial group failed inherited mask test." << llendl;
- }
-
- if (group->isState(LLSpatialGroup::DIRTY))
- {
- assert_parent_state(group, LLSpatialGroup::DIRTY);
- }
- }
-
- void assert_parent_state(LLSpatialGroup* group, U32 state)
- {
- LLSpatialGroup* parent = group->getParent();
- while (parent)
- {
- if (!parent->isState(state))
- {
- llerrs << "Spatial group failed parent state check." << llendl;
- }
- parent = parent->getParent();
- }
- }
-};
-
-
void LLSpatialGroup::checkStates()
{
#if LL_OCTREE_PARANOIA_CHECK
@@ -468,17 +537,17 @@ void validate_draw_info(LLDrawInfo& params)
}
//bad indices
- U32* indicesp = (U32*) params.mVertexBuffer->getIndicesPointer();
+ U16* indicesp = (U16*) params.mVertexBuffer->getIndicesPointer();
if (indicesp)
{
for (U32 i = params.mOffset; i < params.mOffset+params.mCount; i++)
{
- if (indicesp[i] < params.mStart)
+ if (indicesp[i] < (U16)params.mStart)
{
llerrs << "Draw batch has vertex buffer index out of range error (index too low)." << llendl;
}
- if (indicesp[i] > params.mEnd)
+ if (indicesp[i] > (U16)params.mEnd)
{
llerrs << "Draw batch has vertex buffer index out of range error (index too high)." << llendl;
}
@@ -539,7 +608,9 @@ BOOL LLSpatialGroup::addObject(LLDrawable *drawablep, BOOL add_all, BOOL from_oc
{
drawablep->setSpatialGroup(this);
validate_drawable(drawablep);
- setState(OBJECT_DIRTY | GEOM_DIRTY | DISCARD_QUERY);
+ setState(OBJECT_DIRTY | GEOM_DIRTY);
+ setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS);
+ gPipeline.markRebuild(this, TRUE);
if (drawablep->isSpatialBridge())
{
mBridgeList.push_back((LLSpatialBridge*) drawablep);
@@ -570,11 +641,22 @@ void LLSpatialGroup::rebuildMesh()
}
}
+static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt");
+
void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
{
- if (!gPipeline.hasRenderType(mDrawableType))
+ /*if (!gPipeline.hasRenderType(mDrawableType))
{
return;
+ }*/
+
+ if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY))
+ {
+ /*if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && mRenderByGroup)
+ {
+ llerrs << "WTF?" << llendl;
+ }*/
+ return;
}
if (group->changeLOD())
@@ -582,13 +664,8 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
group->mLastUpdateDistance = group->mDistance;
group->mLastUpdateViewAngle = group->mViewAngle;
}
-
- if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY))
- {
- return;
- }
-
- LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO);
+
+ LLFastTimer ftm(FTM_REBUILD_VBO);
group->clearDrawMap();
@@ -625,6 +702,7 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
group->clearState(LLSpatialGroup::GEOM_DIRTY);
}
+
void LLSpatialPartition::rebuildMesh(LLSpatialGroup* group)
{
@@ -663,8 +741,11 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO
drawablep = *i;
minMax = drawablep->getSpatialExtents();
+ update_min_max(newMin, newMax, minMax[0]);
+ update_min_max(newMin, newMax, minMax[1]);
+
//bin up the object
- for (U32 i = 0; i < 3; i++)
+ /*for (U32 i = 0; i < 3; i++)
{
if (minMax[0].mV[i] < newMin.mV[i])
{
@@ -674,7 +755,7 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO
{
newMax.mV[i] = minMax[1].mV[i];
}
- }
+ }*/
}
mObjectBounds[0] = (newMin + newMax) * 0.5f;
@@ -738,6 +819,10 @@ LLSpatialGroup* LLSpatialGroup::getParent()
return NULL;
}
+ if(!mOctreeNode)
+ {
+ return NULL;
+ }
OctreeNode* parent = mOctreeNode->getOctParent();
if (parent)
@@ -763,6 +848,8 @@ BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree)
{
drawablep->setSpatialGroup(NULL);
setState(GEOM_DIRTY);
+ gPipeline.markRebuild(this, TRUE);
+
if (drawablep->isSpatialBridge())
{
for (bridge_list_t::iterator i = mBridgeList.begin(); i != mBridgeList.end(); ++i)
@@ -799,6 +886,7 @@ void LLSpatialGroup::shift(const LLVector3 &offset)
//if (!mSpatialPartition->mRenderByGroup)
{
setState(GEOM_DIRTY);
+ gPipeline.markRebuild(this, TRUE);
}
if (mOcclusionVerts)
@@ -826,7 +914,7 @@ class LLSpatialSetStateDiff : public LLSpatialSetState
public:
LLSpatialSetStateDiff(U32 state) : LLSpatialSetState(state) { }
- virtual void traverse(const LLSpatialGroup::TreeNode* n)
+ virtual void traverse(const LLSpatialGroup::OctreeNode* n)
{
LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
@@ -839,18 +927,21 @@ public:
void LLSpatialGroup::setState(U32 state)
{
- if (!LLSpatialPartition::sFreezeState)
+ mState |= state;
+
+ if (state > LLSpatialGroup::STATE_MASK)
{
- mState |= state;
+ llerrs << "WTF?" << llendl;
}
}
void LLSpatialGroup::setState(U32 state, S32 mode)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- if (LLSpatialPartition::sFreezeState)
+
+ if (state > LLSpatialGroup::STATE_MASK)
{
- return;
+ llerrs << "WTF?" << llendl;
}
if (mode > STATE_MODE_SINGLE)
@@ -885,7 +976,7 @@ class LLSpatialClearStateDiff : public LLSpatialClearState
public:
LLSpatialClearStateDiff(U32 state) : LLSpatialClearState(state) { }
- virtual void traverse(const LLSpatialGroup::TreeNode* n)
+ virtual void traverse(const LLSpatialGroup::OctreeNode* n)
{
LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
@@ -898,20 +989,23 @@ public:
void LLSpatialGroup::clearState(U32 state)
{
- if (!LLSpatialPartition::sFreezeState)
+ if (state > LLSpatialGroup::STATE_MASK)
{
- mState &= ~state;
+ llerrs << "WTF?" << llendl;
}
+
+ mState &= ~state;
}
void LLSpatialGroup::clearState(U32 state, S32 mode)
{
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- if (LLSpatialPartition::sFreezeState)
+ if (state > LLSpatialGroup::STATE_MASK)
{
- return;
+ llerrs << "WTF?" << llendl;
}
+ LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
+
if (mode > STATE_MODE_SINGLE)
{
if (mode == STATE_MODE_DIFF)
@@ -931,6 +1025,128 @@ void LLSpatialGroup::clearState(U32 state, S32 mode)
}
}
+BOOL LLSpatialGroup::isState(U32 state) const
+{
+ if (state > LLSpatialGroup::STATE_MASK)
+ {
+ llerrs << "WTF?" << llendl;
+ }
+
+ return mState & state ? TRUE : FALSE;
+}
+
+//=====================================
+// Occlusion State Set/Clear
+//=====================================
+class LLSpatialSetOcclusionState : public LLSpatialGroup::OctreeTraveler
+{
+public:
+ U32 mState;
+ LLSpatialSetOcclusionState(U32 state) : mState(state) { }
+ virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->setOcclusionState(mState); }
+};
+
+class LLSpatialSetOcclusionStateDiff : public LLSpatialSetOcclusionState
+{
+public:
+ LLSpatialSetOcclusionStateDiff(U32 state) : LLSpatialSetOcclusionState(state) { }
+
+ virtual void traverse(const LLSpatialGroup::OctreeNode* n)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
+
+ if (!group->isOcclusionState(mState))
+ {
+ LLSpatialGroup::OctreeTraveler::traverse(n);
+ }
+ }
+};
+
+
+void LLSpatialGroup::setOcclusionState(U32 state, S32 mode)
+{
+ LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
+
+ if (mode > STATE_MODE_SINGLE)
+ {
+ if (mode == STATE_MODE_DIFF)
+ {
+ LLSpatialSetOcclusionStateDiff setter(state);
+ setter.traverse(mOctreeNode);
+ }
+ else if (mode == STATE_MODE_BRANCH)
+ {
+ LLSpatialSetOcclusionState setter(state);
+ setter.traverse(mOctreeNode);
+ }
+ else
+ {
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ mOcclusionState[i] |= state;
+ }
+ }
+ }
+ else
+ {
+ mOcclusionState[LLViewerCamera::sCurCameraID] |= state;
+ }
+}
+
+class LLSpatialClearOcclusionState : public LLSpatialGroup::OctreeTraveler
+{
+public:
+ U32 mState;
+
+ LLSpatialClearOcclusionState(U32 state) : mState(state) { }
+ virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearOcclusionState(mState); }
+};
+
+class LLSpatialClearOcclusionStateDiff : public LLSpatialClearOcclusionState
+{
+public:
+ LLSpatialClearOcclusionStateDiff(U32 state) : LLSpatialClearOcclusionState(state) { }
+
+ virtual void traverse(const LLSpatialGroup::OctreeNode* n)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
+
+ if (group->isOcclusionState(mState))
+ {
+ LLSpatialGroup::OctreeTraveler::traverse(n);
+ }
+ }
+};
+
+void LLSpatialGroup::clearOcclusionState(U32 state, S32 mode)
+{
+ LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
+
+ if (mode > STATE_MODE_SINGLE)
+ {
+ if (mode == STATE_MODE_DIFF)
+ {
+ LLSpatialClearOcclusionStateDiff clearer(state);
+ clearer.traverse(mOctreeNode);
+ }
+ else if (mode == STATE_MODE_BRANCH)
+ {
+ LLSpatialClearOcclusionState clearer(state);
+ clearer.traverse(mOctreeNode);
+ }
+ else
+ {
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ mOcclusionState[i] &= ~state;
+ }
+ }
+ }
+ else
+ {
+ mOcclusionState[LLViewerCamera::sCurCameraID] &= ~state;
+ }
+}
//======================================
// Octree Listener Implementation
//======================================
@@ -942,13 +1158,16 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
mSpatialPartition(part),
mVertexBuffer(NULL),
mBufferUsage(GL_STATIC_DRAW_ARB),
- mVisible(0),
mDistance(0.f),
mDepth(0.f),
mLastUpdateDistance(-1.f),
mLastUpdateTime(gFrameTimeSeconds),
mViewAngle(0.f),
- mLastUpdateViewAngle(-1.f)
+ mLastUpdateViewAngle(-1.f),
+ mAtlasList(4),
+ mCurUpdatingTime(0),
+ mCurUpdatingSlotp(NULL),
+ mCurUpdatingTexture (NULL)
{
sNodeCount++;
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
@@ -956,14 +1175,25 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
sg_assert(mOctreeNode->getListenerCount() == 0);
mOctreeNode->addListener(this);
setState(SG_INITIAL_STATE_MASK);
+ gPipeline.markRebuild(this, TRUE);
mBounds[0] = LLVector3(node->getCenter());
mBounds[1] = LLVector3(node->getSize());
part->mLODSeed = (part->mLODSeed+1)%part->mLODPeriod;
mLODHash = part->mLODSeed;
-
- mOcclusionQuery = 0;
+
+ OctreeNode* oct_parent = node->getOctParent();
+
+ LLSpatialGroup* parent = oct_parent ? (LLSpatialGroup*) oct_parent->getListener(0) : NULL;
+
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ mOcclusionQuery[i] = 0;
+ mOcclusionState[i] = parent ? SG_STATE_INHERIT_MASK & parent->mOcclusionState[i] : 0;
+ mVisible[i] = 0;
+ }
+
mOcclusionVerts = NULL;
mRadius = 1;
@@ -972,13 +1202,18 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
void LLSpatialGroup::updateDistance(LLCamera &camera)
{
+ if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD)
+ {
+ llerrs << "WTF?" << llendl;
+ }
+
#if !LL_RELEASE_FOR_DOWNLOAD
if (isState(LLSpatialGroup::OBJECT_DIRTY))
{
llerrs << "Spatial group dirty on distance update." << llendl;
}
#endif
- if (!getData().empty() && !LLSpatialPartition::sFreezeState)
+ if (!getData().empty())
{
mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].magVec() :
(F32) mOctreeNode->getSize().magVec();
@@ -1014,6 +1249,7 @@ F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera)
//NOTE: If there is a trivial way to detect that alpha sorting here would not change the render order,
//not setting this node to dirty would be a very good thing
group->setState(LLSpatialGroup::ALPHA_DIRTY);
+ gPipeline.markRebuild(group, FALSE);
}
}
}
@@ -1050,6 +1286,18 @@ F32 LLSpatialPartition::calcPixelArea(LLSpatialGroup* group, LLCamera& camera)
return LLPipeline::calcPixelArea(group->mObjectBounds[0], group->mObjectBounds[1], camera);
}
+F32 LLSpatialGroup::getUpdateUrgency() const
+{
+ if (!isVisible())
+ {
+ return 0.f;
+ }
+ else
+ {
+ return (gFrameTimeSeconds - mLastUpdateTime+4.f)/mDistance;
+ }
+}
+
BOOL LLSpatialGroup::needsUpdate()
{
return (LLDrawable::getCurrentFrame()%mSpatialPartition->mLODPeriod == mLODHash) ? TRUE : FALSE;
@@ -1136,8 +1384,7 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
if (child->getListenerCount() == 0)
{
- LLSpatialGroup* group = new LLSpatialGroup(child, mSpatialPartition);
- group->setState(mState & SG_STATE_INHERIT_MASK);
+ new LLSpatialGroup(child, mSpatialPartition);
}
else
{
@@ -1157,16 +1404,21 @@ void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNo
void LLSpatialGroup::destroyGL()
{
setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY);
+ gPipeline.markRebuild(this, TRUE);
+
mLastUpdateTime = gFrameTimeSeconds;
mVertexBuffer = NULL;
mBufferMap.clear();
clearDrawMap();
- if (mOcclusionQuery)
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
{
- sQueryPool.release(mOcclusionQuery);
- mOcclusionQuery = 0;
+ if (mOcclusionQuery[i])
+ {
+ sQueryPool.release(mOcclusionQuery[i]);
+ mOcclusionQuery[i] = 0;
+ }
}
delete [] mOcclusionVerts;
@@ -1256,43 +1508,49 @@ BOOL LLSpatialGroup::rebound()
return TRUE;
}
+static LLFastTimer::DeclareTimer FTM_OCCLUSION_READBACK("Readback Occlusion");
void LLSpatialGroup::checkOcclusion()
{
if (LLPipeline::sUseOcclusion > 1)
{
LLSpatialGroup* parent = getParent();
- if (parent && parent->isState(LLSpatialGroup::OCCLUDED))
+ if (parent && parent->isOcclusionState(LLSpatialGroup::OCCLUDED))
{ //if the parent has been marked as occluded, the child is implicitly occluded
- clearState(QUERY_PENDING | DISCARD_QUERY);
+ clearOcclusionState(QUERY_PENDING | DISCARD_QUERY);
}
- else if (isState(QUERY_PENDING))
+ else if (isOcclusionState(QUERY_PENDING))
{ //otherwise, if a query is pending, read it back
- LLFastTimer t(LLFastTimer::FTM_OCCLUSION_READBACK);
+ LLFastTimer t(FTM_OCCLUSION_READBACK);
GLuint res = 1;
- if (!isState(DISCARD_QUERY) && mOcclusionQuery)
+ if (!isOcclusionState(DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID])
{
- glGetQueryObjectuivARB(mOcclusionQuery, GL_QUERY_RESULT_ARB, &res);
+ glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_ARB, &res);
+ }
+
+ if (isOcclusionState(DISCARD_QUERY))
+ {
+ res = 2;
}
if (res > 0)
{
assert_states_valid(this);
- clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
+ clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
assert_states_valid(this);
}
else
{
assert_states_valid(this);
- setState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
+ setOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
assert_states_valid(this);
}
- clearState(QUERY_PENDING | DISCARD_QUERY);
+ clearOcclusionState(QUERY_PENDING | DISCARD_QUERY);
}
- else if (mSpatialPartition->isOcclusionEnabled() && isState(LLSpatialGroup::OCCLUDED))
+ else if (mSpatialPartition->isOcclusionEnabled() && isOcclusionState(LLSpatialGroup::OCCLUDED))
{ //check occlusion has been issued for occluded node that has not had a query issued
assert_states_valid(this);
- clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
+ clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
assert_states_valid(this);
}
}
@@ -1304,19 +1562,19 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
{
if (earlyFail(camera, this))
{
- setState(LLSpatialGroup::DISCARD_QUERY);
+ setOcclusionState(LLSpatialGroup::DISCARD_QUERY);
assert_states_valid(this);
- clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
+ clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
assert_states_valid(this);
}
else
{
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_OCCLUSION);
+ LLFastTimer t(FTM_RENDER_OCCLUSION);
- if (!mOcclusionQuery)
+ if (!mOcclusionQuery[LLViewerCamera::sCurCameraID])
{
- mOcclusionQuery = sQueryPool.allocate();
+ mOcclusionQuery[LLViewerCamera::sCurCameraID] = sQueryPool.allocate();
}
if (!mOcclusionVerts || isState(LLSpatialGroup::OCCLUSION_DIRTY))
@@ -1324,22 +1582,33 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
buildOcclusion();
}
- glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQuery);
+ glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQuery[LLViewerCamera::sCurCameraID]);
glVertexPointer(3, GL_FLOAT, 0, mOcclusionVerts);
- glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
- GL_UNSIGNED_BYTE, get_box_fan_indices(camera, mBounds[0]));
+ if (camera->getOrigin().isExactlyZero())
+ { //origin is invalid, draw entire box
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_BYTE, sOcclusionIndices);
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_BYTE, sOcclusionIndices+b111*8);
+ }
+ else
+ {
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_BYTE, get_box_fan_indices(camera, mBounds[0]));
+ }
glEndQueryARB(GL_SAMPLES_PASSED_ARB);
}
- setState(LLSpatialGroup::QUERY_PENDING);
- clearState(LLSpatialGroup::DISCARD_QUERY);
+ setOcclusionState(LLSpatialGroup::QUERY_PENDING);
+ clearOcclusionState(LLSpatialGroup::DISCARD_QUERY);
}
}
}
//==============================================
-LLSpatialPartition::LLSpatialPartition(U32 data_mask, U32 buffer_usage)
+LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage)
+: mRenderByGroup(render_by_group)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
mOcclusionEnabled = TRUE;
@@ -1351,7 +1620,6 @@ LLSpatialPartition::LLSpatialPartition(U32 data_mask, U32 buffer_usage)
mBufferUsage = buffer_usage;
mDepthMask = FALSE;
mSlopRatio = 0.25f;
- mRenderByGroup = TRUE;
mInfiniteFarClip = FALSE;
LLGLNamePool::registerPool(&sQueryPool);
@@ -1388,9 +1656,9 @@ LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible)
LLSpatialGroup* group = drawablep->getSpatialGroup();
- if (group && was_visible && group->isState(LLSpatialGroup::QUERY_PENDING))
+ if (group && was_visible && group->isOcclusionState(LLSpatialGroup::QUERY_PENDING))
{
- group->setState(LLSpatialGroup::DISCARD_QUERY);
+ group->setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS);
}
return group;
@@ -1489,7 +1757,7 @@ public:
if (group->mOctreeNode->getParent() && //never occlusion cull the root node
LLPipeline::sUseOcclusion && //ignore occlusion if disabled
- group->isState(LLSpatialGroup::OCCLUDED))
+ group->isOcclusionState(LLSpatialGroup::OCCLUDED))
{
gPipeline.markOccluder(group);
return true;
@@ -1498,7 +1766,7 @@ public:
return false;
}
- virtual void traverse(const LLSpatialGroup::TreeNode* n)
+ virtual void traverse(const LLSpatialGroup::OctreeNode* n)
{
LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
@@ -1571,7 +1839,7 @@ public:
virtual void processGroup(LLSpatialGroup* group)
{
if (group->needsUpdate() ||
- group->mVisible < LLDrawable::getCurrentFrame() - 1)
+ group->mVisible[LLViewerCamera::sCurCameraID] < LLDrawable::getCurrentFrame() - 1)
{
group->doOcclusion(mCamera);
}
@@ -1639,7 +1907,7 @@ public:
{
if (group->mOctreeNode->getParent() && //never occlusion cull the root node
LLPipeline::sUseOcclusion && //ignore occlusion if disabled
- group->isState(LLSpatialGroup::OCCLUDED))
+ group->isOcclusionState(LLSpatialGroup::OCCLUDED))
{
return true;
}
@@ -1647,13 +1915,57 @@ public:
return false;
}
+ virtual void traverse(const LLSpatialGroup::OctreeNode* n)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
+
+ if (earlyFail(group))
+ {
+ return;
+ }
+
+ if (mRes == 2)
+ {
+ //fully in, don't traverse further (won't effect extents
+ }
+ else if (mRes && group->isState(LLSpatialGroup::SKIP_FRUSTUM_CHECK))
+ { //don't need to do frustum check
+ LLSpatialGroup::OctreeTraveler::traverse(n);
+ }
+ else
+ {
+ mRes = frustumCheck(group);
+
+ if (mRes)
+ { //at least partially in, run on down
+ LLSpatialGroup::OctreeTraveler::traverse(n);
+ }
+
+ mRes = 0;
+ }
+ }
+
virtual void processGroup(LLSpatialGroup* group)
{
- if (group->mObjectBounds[1].magVecSquared() < 256.f * 256.f)
- { //megaprims and water edge patches be damned!
+ if (group->isState(LLSpatialGroup::DIRTY) || group->getData().empty())
+ {
+ llerrs << "WTF?" << llendl;
+ }
+
+ if (mRes < 2)
+ {
+ if (mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1]) > 0)
+ {
+ mEmpty = FALSE;
+ update_min_max(mMin, mMax, group->mObjectExtents[0]);
+ update_min_max(mMin, mMax, group->mObjectExtents[1]);
+ }
+ }
+ else
+ {
mEmpty = FALSE;
- update_min_max(mMin, mMax, group->mObjectExtents[0]);
- update_min_max(mMin, mMax, group->mObjectExtents[1]);
+ update_min_max(mMin, mMax, group->mExtents[0]);
+ update_min_max(mMin, mMax, group->mExtents[1]);
}
}
@@ -1671,9 +1983,9 @@ public:
virtual bool earlyFail(LLSpatialGroup* group)
{
if (mResult || //already found a node, don't check any more
- group->mOctreeNode->getParent() && //never occlusion cull the root node
- LLPipeline::sUseOcclusion && //ignore occlusion if disabled
- group->isState(LLSpatialGroup::OCCLUDED))
+ (group->mOctreeNode->getParent() && //never occlusion cull the root node
+ LLPipeline::sUseOcclusion && //ignore occlusion if disabled
+ group->isOcclusionState(LLSpatialGroup::OCCLUDED)))
{
return true;
}
@@ -1852,6 +2164,12 @@ BOOL LLSpatialPartition::isOcclusionEnabled()
BOOL LLSpatialPartition::getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax)
{
+ {
+ LLFastTimer ftm(FTM_CULL_REBOUND);
+ LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0);
+ group->rebound();
+ }
+
LLOctreeCullVisExtents vis(&camera, visMin, visMax);
vis.traverse(mOctree);
return vis.mEmpty;
@@ -1871,12 +2189,9 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result
((LLSpatialGroup*)mOctree->getListener(0))->checkStates();
#endif
{
- BOOL temp = sFreezeState;
- sFreezeState = FALSE;
- LLFastTimer ftm(LLFastTimer::FTM_CULL_REBOUND);
+ LLFastTimer ftm(FTM_CULL_REBOUND);
LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0);
group->rebound();
- sFreezeState = temp;
}
#if LL_OCTREE_PARANOIA_CHECK
@@ -1891,19 +2206,19 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result
}
else if (LLPipeline::sShadowRender)
{
- LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL);
+ LLFastTimer ftm(FTM_FRUSTUM_CULL);
LLOctreeCullShadow culler(&camera);
culler.traverse(mOctree);
}
else if (mInfiniteFarClip || !LLPipeline::sUseFarClip)
{
- LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL);
+ LLFastTimer ftm(FTM_FRUSTUM_CULL);
LLOctreeCullNoFarClip culler(&camera);
culler.traverse(mOctree);
}
else
{
- LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL);
+ LLFastTimer ftm(FTM_FRUSTUM_CULL);
LLOctreeCull culler(&camera);
culler.traverse(mOctree);
}
@@ -1913,6 +2228,11 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result
BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group)
{
+ if (camera->getOrigin().isExactlyZero())
+ {
+ return FALSE;
+ }
+
const F32 vel = SG_OCCLUSION_FUDGE*2.f;
LLVector3 c = group->mBounds[0];
LLVector3 r = group->mBounds[1] + LLVector3(vel,vel,vel);
@@ -2140,7 +2460,6 @@ void renderOctree(LLSpatialGroup* group)
gGL.color4fv(col.mV);
drawBox(group->mObjectBounds[0], group->mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f));
- glDepthMask(GL_TRUE);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
if (group->mBuilt <= 0.f)
@@ -2190,7 +2509,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera)
LLGLEnable cull(GL_CULL_FACE);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isState(LLSpatialGroup::OCCLUDED)) && group->isVisible() &&
+ BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() &&
!group->getData().empty();
if (render_objects)
{
@@ -2356,11 +2675,10 @@ void renderTexturePriority(LLDrawable* drawable)
LLGLDisable blend(GL_BLEND);
- //LLViewerImage* imagep = facep->getTexture();
+ //LLViewerTexture* imagep = facep->getTexture();
//if (imagep)
{
-
- //F32 vsize = LLVOVolume::getTextureVirtualSize(facep);
+
//F32 vsize = imagep->mMaxVirtualSize;
F32 vsize = facep->getPixelArea();
@@ -2384,9 +2702,9 @@ void renderTexturePriority(LLDrawable* drawable)
drawBox(center, size);
/*S32 boost = imagep->getBoostLevel();
- if (boost)
+ if (boost>LLViewerTexture::BOOST_NONE)
{
- F32 t = (F32) boost / (F32) (LLViewerImage::BOOST_MAX_LEVEL-1);
+ F32 t = (F32) boost / (F32) (LLViewerTexture::BOOST_MAX_LEVEL-1);
LLVector4 col = lerp(boost_cold, boost_hot, t);
LLGLEnable blend_on(GL_BLEND);
gGL.blendFunc(GL_SRC_ALPHA, GL_ONE);
@@ -2431,6 +2749,39 @@ void renderBatchSize(LLDrawInfo* params)
pushVerts(params, LLVertexBuffer::MAP_VERTEX);
}
+void renderShadowFrusta(LLDrawInfo* params)
+{
+ LLGLEnable blend(GL_BLEND);
+ gGL.setSceneBlendType(LLRender::BT_ADD);
+
+ LLVector3 center = (params->mExtents[1]+params->mExtents[0])*0.5f;
+ LLVector3 size = (params->mExtents[1]-params->mExtents[0])*0.5f;
+
+ if (gPipeline.mShadowCamera[4].AABBInFrustum(center, size))
+ {
+ glColor3f(1,0,0);
+ pushVerts(params, LLVertexBuffer::MAP_VERTEX);
+ }
+ if (gPipeline.mShadowCamera[5].AABBInFrustum(center, size))
+ {
+ glColor3f(0,1,0);
+ pushVerts(params, LLVertexBuffer::MAP_VERTEX);
+ }
+ if (gPipeline.mShadowCamera[6].AABBInFrustum(center, size))
+ {
+ glColor3f(0,0,1);
+ pushVerts(params, LLVertexBuffer::MAP_VERTEX);
+ }
+ if (gPipeline.mShadowCamera[7].AABBInFrustum(center, size))
+ {
+ glColor3f(1,0,1);
+ pushVerts(params, LLVertexBuffer::MAP_VERTEX);
+ }
+
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+}
+
+
void renderLights(LLDrawable* drawablep)
{
if (!drawablep->isLight())
@@ -2566,6 +2917,9 @@ public:
//draw tight fit bounding boxes for spatial group
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE))
{
+ group->rebuildGeom();
+ group->rebuildMesh();
+
renderOctree(group);
stop_glerror();
}
@@ -2573,6 +2927,9 @@ public:
//render visibility wireframe
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
{
+ group->rebuildGeom();
+ group->rebuildMesh();
+
gGL.flush();
glPushMatrix();
gGLLastMatrix = NULL;
@@ -2598,6 +2955,19 @@ public:
LLVector3 nodeCenter = group->mBounds[0];
LLVector3 octCenter = LLVector3(group->mOctreeNode->getCenter());
+ group->rebuildGeom();
+ group->rebuildMesh();
+
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES))
+ {
+ if (!group->getData().empty())
+ {
+ gGL.color3f(0,0,1);
+ drawBoxOutline(group->mObjectBounds[0],
+ group->mObjectBounds[1]);
+ }
+ }
+
for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
{
LLDrawable* drawable = *i;
@@ -2607,6 +2977,16 @@ public:
renderBoundingBox(drawable);
}
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BUILD_QUEUE))
+ {
+ if (drawable->isState(LLDrawable::IN_REBUILD_Q2))
+ {
+ gGL.color4f(0.6f, 0.6f, 0.1f, 1.f);
+ const LLVector3* ext = drawable->getSpatialExtents();
+ drawBoxOutline((ext[0]+ext[1])*0.5f, (ext[1]-ext[0])*0.5f);
+ }
+ }
+
if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
{
renderTexturePriority(drawable);
@@ -2655,6 +3035,10 @@ public:
{
renderBatchSize(draw_info);
}
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ renderShadowFrusta(draw_info);
+ }
}
}
}
@@ -2705,6 +3089,79 @@ void LLSpatialPartition::renderIntersectingBBoxes(LLCamera* camera)
pusher.traverse(mOctree);
}
+class LLOctreeStateCheck : public LLOctreeTraveler<LLDrawable>
+{
+public:
+ U32 mInheritedMask[LLViewerCamera::NUM_CAMERAS];
+
+ LLOctreeStateCheck()
+ {
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ mInheritedMask[i] = 0;
+ }
+ }
+
+ virtual void traverse(const LLSpatialGroup::OctreeNode* node)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
+
+ node->accept(this);
+
+
+ U32 temp[LLViewerCamera::NUM_CAMERAS];
+
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ temp[i] = mInheritedMask[i];
+ mInheritedMask[i] |= group->mOcclusionState[i] & LLSpatialGroup::OCCLUDED;
+ }
+
+ for (U32 i = 0; i < node->getChildCount(); i++)
+ {
+ traverse(node->getChild(i));
+ }
+
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ mInheritedMask[i] = temp[i];
+ }
+ }
+
+
+ virtual void visit(const LLOctreeNode<LLDrawable>* state)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0);
+
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ if (mInheritedMask[i] && !(group->mOcclusionState[i] & mInheritedMask[i]))
+ {
+ llerrs << "Spatial group failed inherited mask test." << llendl;
+ }
+ }
+
+ if (group->isState(LLSpatialGroup::DIRTY))
+ {
+ assert_parent_state(group, LLSpatialGroup::DIRTY);
+ }
+ }
+
+ void assert_parent_state(LLSpatialGroup* group, U32 state)
+ {
+ LLSpatialGroup* parent = group->getParent();
+ while (parent)
+ {
+ if (!parent->isState(state))
+ {
+ llerrs << "Spatial group failed parent state check." << llendl;
+ }
+ parent = parent->getParent();
+ }
+ }
+};
+
+
void LLSpatialPartition::renderDebug()
{
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE |
@@ -2717,7 +3174,9 @@ void LLSpatialPartition::renderDebug()
LLPipeline::RENDER_DEBUG_TEXTURE_ANIM |
LLPipeline::RENDER_DEBUG_RAYCAST |
LLPipeline::RENDER_DEBUG_AVATAR_VOLUME |
- LLPipeline::RENDER_DEBUG_AGENT_TARGET))
+ LLPipeline::RENDER_DEBUG_AGENT_TARGET |
+ LLPipeline::RENDER_DEBUG_BUILD_QUEUE |
+ LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
{
return;
}
@@ -2752,6 +3211,12 @@ void LLSpatialPartition::renderDebug()
render_debug.traverse(mOctree);
}
+void LLSpatialGroup::drawObjectBox(LLColor4 col)
+{
+ gGL.color4fv(col.mV);
+ drawBox(mObjectBounds[0], mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f));
+}
+
BOOL LLSpatialPartition::isVisible(const LLVector3& v)
{
@@ -2896,7 +3361,7 @@ LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector3& start, con
}
LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,
- LLViewerImage* texture, LLVertexBuffer* buffer,
+ LLViewerTexture* texture, LLVertexBuffer* buffer,
BOOL fullbright, U8 bump, BOOL particle, F32 part_size)
:
mVertexBuffer(buffer),
@@ -2932,10 +3397,10 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,
LLDrawInfo::~LLDrawInfo()
{
- if (LLSpatialGroup::sNoDelete)
+ /*if (LLSpatialGroup::sNoDelete)
{
llerrs << "LLDrawInfo deleted illegally!" << llendl;
- }
+ }*/
if (mFace)
{
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 4d67b374c8..64c2a9acbc 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -35,14 +35,16 @@
#define SG_MIN_DIST_RATIO 0.00001f
-#include "llmemory.h"
#include "lldrawable.h"
#include "lloctree.h"
+#include "llpointer.h"
+#include "llrefcount.h"
#include "llvertexbuffer.h"
#include "llgltypes.h"
#include "llcubemap.h"
#include "lldrawpool.h"
#include "llface.h"
+#include "llviewercamera.h"
#include <queue>
@@ -52,6 +54,8 @@
class LLSpatialPartition;
class LLSpatialBridge;
class LLSpatialGroup;
+class LLTextureAtlas;
+class LLTextureAtlasSlot;
S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad);
S32 AABBSphereIntersectR2(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &radius_squared);
@@ -66,12 +70,12 @@ protected:
public:
LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,
- LLViewerImage* image, LLVertexBuffer* buffer,
+ LLViewerTexture* image, LLVertexBuffer* buffer,
BOOL fullbright = FALSE, U8 bump = 0, BOOL particle = FALSE, F32 part_size = 0);
LLPointer<LLVertexBuffer> mVertexBuffer;
- LLPointer<LLViewerImage> mTexture;
+ LLPointer<LLViewerTexture> mTexture;
LLColor4U mGlowColor;
S32 mDebugColor;
const LLMatrix4* mTextureMatrix;
@@ -153,17 +157,19 @@ public:
class LLSpatialGroup : public LLOctreeListener<LLDrawable>
{
friend class LLSpatialPartition;
+ friend class LLOctreeStateCheck;
public:
static U32 sNodeCount;
static BOOL sNoDelete; //deletion of spatial groups and draw info not allowed if TRUE
typedef std::vector<LLPointer<LLSpatialGroup> > sg_vector_t;
typedef std::set<LLPointer<LLSpatialGroup> > sg_set_t;
+ typedef std::list<LLPointer<LLSpatialGroup> > sg_list_t;
typedef std::vector<LLPointer<LLSpatialBridge> > bridge_list_t;
typedef std::vector<LLPointer<LLDrawInfo> > drawmap_elem_t;
typedef std::map<U32, drawmap_elem_t > draw_map_t;
typedef std::vector<LLPointer<LLVertexBuffer> > buffer_list_t;
- typedef std::map<LLPointer<LLViewerImage>, buffer_list_t> buffer_texture_map_t;
+ typedef std::map<LLPointer<LLViewerTexture>, buffer_list_t> buffer_texture_map_t;
typedef std::map<U32, buffer_texture_map_t> buffer_map_t;
typedef LLOctreeListener<LLDrawable> BaseType;
@@ -183,6 +189,14 @@ public:
}
};
+ struct CompareUpdateUrgency
+ {
+ bool operator()(const LLPointer<LLSpatialGroup> lhs, const LLPointer<LLSpatialGroup> rhs)
+ {
+ return lhs->getUpdateUrgency() > rhs->getUpdateUrgency();
+ }
+ };
+
struct CompareDepthGreater
{
bool operator()(const LLSpatialGroup* const& lhs, const LLSpatialGroup* const& rhs)
@@ -193,35 +207,44 @@ public:
typedef enum
{
- OCCLUDED = 0x00000001,
- IN_QUEUE = 0x00000002,
- QUERY_PENDING = 0x00000004,
- ACTIVE_OCCLUSION = 0x00000008,
- DISCARD_QUERY = 0x00000010,
- DEAD = 0x00000020,
- EARLY_FAIL = 0x00000040,
- DIRTY = 0x00000080,
- OBJECT_DIRTY = 0x00000100,
- GEOM_DIRTY = 0x00000200,
- ALPHA_DIRTY = 0x00000800,
- SKIP_FRUSTUM_CHECK = 0x00001000,
- IN_IMAGE_QUEUE = 0x00002000,
- IMAGE_DIRTY = 0x00004000,
- OCCLUSION_DIRTY = 0x00008000,
- MESH_DIRTY = 0x00010000,
+ OCCLUDED = 0x00010000,
+ QUERY_PENDING = 0x00020000,
+ ACTIVE_OCCLUSION = 0x00040000,
+ DISCARD_QUERY = 0x00080000,
+ EARLY_FAIL = 0x00100000,
+ } eOcclusionState;
+
+ typedef enum
+ {
+ DEAD = 0x00000001,
+ DIRTY = 0x00000002,
+ OBJECT_DIRTY = 0x00000004,
+ GEOM_DIRTY = 0x00000008,
+ ALPHA_DIRTY = 0x00000010,
+ SKIP_FRUSTUM_CHECK = 0x00000020,
+ IN_IMAGE_QUEUE = 0x00000040,
+ IMAGE_DIRTY = 0x00000080,
+ OCCLUSION_DIRTY = 0x00000100,
+ MESH_DIRTY = 0x00000200,
+ NEW_DRAWINFO = 0x00000400,
+ IN_BUILD_Q1 = 0x00000800,
+ IN_BUILD_Q2 = 0x00001000,
+ STATE_MASK = 0x0000FFFF,
} eSpatialState;
typedef enum
{
STATE_MODE_SINGLE = 0, //set one node
STATE_MODE_BRANCH, //set entire branch
- STATE_MODE_DIFF //set entire branch as long as current state is different
+ STATE_MODE_DIFF, //set entire branch as long as current state is different
+ STATE_MODE_ALL_CAMERAS, //used for occlusion state, set state for all cameras
} eSetStateMode;
LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part);
BOOL isDead() { return isState(DEAD); }
- BOOL isState(U32 state) const { return mState & state ? TRUE : FALSE; }
+ BOOL isState(U32 state) const;
+ BOOL isOcclusionState(U32 state) const { return mOcclusionState[LLViewerCamera::sCurCameraID] & state ? TRUE : FALSE; }
U32 getState() { return mState; }
void setState(U32 state);
void clearState(U32 state);
@@ -232,14 +255,19 @@ public:
void validateDrawMap();
void setState(U32 state, S32 mode);
+ void clearState(U32 state, S32 mode);
+
+ void setOcclusionState(U32 state, S32 mode = STATE_MODE_SINGLE);
+ void clearOcclusionState(U32 state, S32 mode = STATE_MODE_SINGLE);
LLSpatialGroup* getParent();
- void clearState(U32 state, S32 mode);
+
BOOL addObject(LLDrawable *drawablep, BOOL add_all = FALSE, BOOL from_octree = FALSE);
BOOL removeObject(LLDrawable *drawablep, BOOL from_octree = FALSE);
BOOL updateInGroup(LLDrawable *drawablep, BOOL immediate = FALSE); // Update position if it's in the group
BOOL isVisible() const;
+ BOOL isRecentlyVisible() const;
void setVisible();
void shift(const LLVector3 &offset);
BOOL boundObjects(BOOL empty, LLVector3& newMin, LLVector3& newMax);
@@ -252,6 +280,7 @@ public:
void updateDistance(LLCamera& camera);
BOOL needsUpdate();
+ F32 getUpdateUrgency() const;
BOOL changeLOD();
void rebuildGeom();
void rebuildMesh();
@@ -261,6 +290,8 @@ public:
element_list& getData() { return mOctreeNode->getData(); }
U32 getElementCount() const { return mOctreeNode->getElementCount(); }
+ void drawObjectBox(LLColor4 col);
+
//LISTENER FUNCTIONS
virtual void handleInsertion(const TreeNode* node, LLDrawable* face);
virtual void handleRemoval(const TreeNode* node, LLDrawable* face);
@@ -269,10 +300,41 @@ public:
virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child);
virtual void handleChildRemoval(const OctreeNode* parent, const OctreeNode* child);
+//-------------------
+//for atlas use
+//-------------------
+ //atlas
+ void setCurUpdatingTime(U32 t) {mCurUpdatingTime = t ;}
+ U32 getCurUpdatingTime() const { return mCurUpdatingTime ;}
+
+ void setCurUpdatingSlot(LLTextureAtlasSlot* slotp) ;
+ LLTextureAtlasSlot* getCurUpdatingSlot(LLViewerTexture* imagep, S8 recursive_level = 3) ;
+
+ void setCurUpdatingTexture(LLViewerTexture* tex){ mCurUpdatingTexture = tex ;}
+ LLViewerTexture* getCurUpdatingTexture() const { return mCurUpdatingTexture ;}
+
+ BOOL hasAtlas(LLTextureAtlas* atlasp) ;
+ LLTextureAtlas* getAtlas(S8 ncomponents, S8 to_be_reserved, S8 recursive_level = 3) ;
+ void addAtlas(LLTextureAtlas* atlasp, S8 recursive_level = 3) ;
+ void removeAtlas(LLTextureAtlas* atlasp, BOOL remove_group = TRUE, S8 recursive_level = 3) ;
+ void clearAtlasList() ;
+private:
+ U32 mCurUpdatingTime ;
+ //do not make the below two to use LLPointer
+ //because mCurUpdatingTime invalidates them automatically.
+ LLTextureAtlasSlot* mCurUpdatingSlotp ;
+ LLViewerTexture* mCurUpdatingTexture ;
+
+ std::vector< std::list<LLTextureAtlas*> > mAtlasList ;
+//-------------------
+//end for atlas use
+//-------------------
+
protected:
virtual ~LLSpatialGroup();
U32 mState;
+ U32 mOcclusionState[LLViewerCamera::NUM_CAMERAS];
S32 mLODHash;
static S32 sLODSeed;
@@ -291,12 +353,12 @@ public:
LLPointer<LLVertexBuffer> mVertexBuffer;
F32* mOcclusionVerts;
- GLuint mOcclusionQuery;
+ GLuint mOcclusionQuery[LLViewerCamera::NUM_CAMERAS];
U32 mBufferUsage;
draw_map_t mDrawMap;
- S32 mVisible;
+ S32 mVisible[LLViewerCamera::NUM_CAMERAS];
F32 mDistance;
F32 mDepth;
F32 mLastUpdateDistance;
@@ -325,9 +387,7 @@ public:
class LLSpatialPartition: public LLGeometryManager
{
public:
- static BOOL sFreezeState; //if true, no spatialgroup state updates will be made
-
- LLSpatialPartition(U32 data_mask, U32 mBufferUsage = GL_STATIC_DRAW_ARB);
+ LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 mBufferUsage);
virtual ~LLSpatialPartition();
LLSpatialGroup *put(LLDrawable *drawablep, BOOL was_visible = FALSE);
@@ -373,7 +433,7 @@ public:
BOOL mOcclusionEnabled; // if TRUE, occlusion culling is performed
BOOL mInfiniteFarClip; // if TRUE, frustum culling ignores far clip plane
U32 mBufferUsage;
- BOOL mRenderByGroup;
+ const BOOL mRenderByGroup;
U32 mLODSeed;
U32 mLODPeriod; //number of frames between LOD updates for a given spatial group (staggered by mLODSeed)
U32 mVertexDataMask;
@@ -392,14 +452,14 @@ protected:
public:
typedef std::vector<LLPointer<LLSpatialBridge> > bridge_vector_t;
- LLSpatialBridge(LLDrawable* root, U32 data_mask);
+ LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask);
virtual BOOL isSpatialBridge() const { return TRUE; }
virtual void updateSpatialExtents();
virtual void updateBinRadius();
virtual void setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* results = NULL, BOOL for_select = FALSE);
- virtual void updateDistance(LLCamera& camera_in);
+ virtual void updateDistance(LLCamera& camera_in, bool force_update);
virtual void makeActive();
virtual void move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate = FALSE);
virtual BOOL updateMove();
diff --git a/indra/newview/llspeakbutton.cpp b/indra/newview/llspeakbutton.cpp
new file mode 100644
index 0000000000..8f2c877c7a
--- /dev/null
+++ b/indra/newview/llspeakbutton.cpp
@@ -0,0 +1,176 @@
+/**
+* @file llspeakbutton.cpp
+* @brief LLSpeakButton class implementation
+*
+* $LicenseInfo:firstyear=2002&license=viewergpl$
+*
+* Copyright (c) 2002-2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#include "llbutton.h"
+#include "llfloaterreg.h"
+
+#include "llagent.h"
+#include "llbottomtray.h"
+#include "llcallfloater.h"
+#include "lloutputmonitorctrl.h"
+#include "lltransientfloatermgr.h"
+
+#include "llspeakbutton.h"
+
+static LLDefaultChildRegistry::Register<LLSpeakButton> t1("talk_button");
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+LLSpeakButton::Params::Params()
+ : speak_button("speak_button")
+ , show_button("show_button")
+ , monitor("monitor")
+{
+ // See widgets/talk_button.xml
+}
+
+void LLSpeakButton::draw()
+{
+ // gVoiceClient is the authoritative global source of info regarding our open-mic state, we merely reflect that state.
+ bool openmic = gVoiceClient->getUserPTTState();
+ bool voiceenabled = gVoiceClient->voiceEnabled();
+ mSpeakBtn->setToggleState(openmic && voiceenabled);
+ mOutputMonitor->setIsMuted(!voiceenabled);
+ LLUICtrl::draw();
+}
+
+LLSpeakButton::LLSpeakButton(const Params& p)
+: LLUICtrl(p)
+, mOutputMonitor(NULL)
+, mSpeakBtn(NULL)
+, mShowBtn(NULL)
+{
+ LLRect rect = p.rect();
+ LLRect speak_rect(0, rect.getHeight(), rect.getWidth(), 0);
+ LLRect show_rect = p.show_button.rect();
+ show_rect.set(0, rect.getHeight(), show_rect.getWidth(), 0);
+
+ speak_rect.mRight -= show_rect.getWidth();
+ show_rect.mLeft = speak_rect.getWidth();
+ show_rect.mRight = rect.getWidth();
+
+ LLButton::Params speak_params = p.speak_button;
+ speak_params.rect(speak_rect);
+ mSpeakBtn = LLUICtrlFactory::create<LLButton>(speak_params);
+ addChild(mSpeakBtn);
+ LLTransientFloaterMgr::getInstance()->addControlView(mSpeakBtn);
+
+ mSpeakBtn->setMouseDownCallback(boost::bind(&LLSpeakButton::onMouseDown_SpeakBtn, this));
+ mSpeakBtn->setMouseUpCallback(boost::bind(&LLSpeakButton::onMouseUp_SpeakBtn, this));
+ mSpeakBtn->setToggleState(FALSE);
+
+ LLButton::Params show_params = p.show_button;
+ show_params.rect(show_rect);
+ mShowBtn = LLUICtrlFactory::create<LLButton>(show_params);
+ addChild(mShowBtn);
+ LLTransientFloaterMgr::getInstance()->addControlView(mShowBtn);
+
+// mShowBtn->setClickedCallback(boost::bind(&LLSpeakButton::onClick_ShowBtn, this));
+// mShowBtn->setToggleState(FALSE);
+
+ static const S32 MONITOR_RIGHT_PAD = 2;
+
+ LLRect monitor_rect = p.monitor.rect();
+ S32 monitor_height = monitor_rect.getHeight();
+ monitor_rect.mLeft = speak_rect.getWidth() - monitor_rect.getWidth() - MONITOR_RIGHT_PAD;
+ monitor_rect.mRight = speak_rect.getWidth() - MONITOR_RIGHT_PAD;
+ monitor_rect.mBottom = (rect.getHeight() / 2) - (monitor_height / 2);
+ monitor_rect.mTop = monitor_rect.mBottom + monitor_height;
+
+ LLOutputMonitorCtrl::Params monitor_params = p.monitor;
+ monitor_params.draw_border(false);
+ monitor_params.rect(monitor_rect);
+ monitor_params.auto_update(true);
+ monitor_params.speaker_id(gAgentID);
+ mOutputMonitor = LLUICtrlFactory::create<LLOutputMonitorCtrl>(monitor_params);
+ mSpeakBtn->addChild(mOutputMonitor);
+
+ // never show "muted" because you can't mute yourself
+ mOutputMonitor->setIsMuted(false);
+ mOutputMonitor->setIsAgentControl(true);
+
+ //*TODO find a better place to do that
+ LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::sOnCurrentChannelChanged, _1), true);
+}
+
+LLSpeakButton::~LLSpeakButton()
+{
+ LLTransientFloaterMgr::getInstance()->removeControlView(mSpeakBtn);
+ LLTransientFloaterMgr::getInstance()->removeControlView(mShowBtn);
+}
+
+void LLSpeakButton::setSpeakToolTip(const std::string& msg)
+{
+ mSpeakBtn->setToolTip(msg);
+}
+
+void LLSpeakButton::setShowToolTip(const std::string& msg)
+{
+ mShowBtn->setToolTip(msg);
+}
+
+void LLSpeakButton::setLabelVisible(bool visible)
+{
+ static std::string label_selected = mSpeakBtn->getLabelSelected();
+ static std::string label_unselected = mSpeakBtn->getLabelUnselected();
+
+ if (visible)
+ {
+ mSpeakBtn->setLabelSelected(label_selected);
+ mSpeakBtn->setLabelUnselected(label_unselected);
+ }
+ else
+ {
+ static LLStringExplicit empty_string("");
+ mSpeakBtn->setLabelSelected(empty_string);
+ mSpeakBtn->setLabelUnselected(empty_string);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// PROTECTED SECTION
+//////////////////////////////////////////////////////////////////////////
+void LLSpeakButton::onMouseDown_SpeakBtn()
+{
+ bool down = true;
+ gVoiceClient->inputUserControlState(down); // this method knows/care about whether this translates into a toggle-to-talk or down-to-talk
+}
+void LLSpeakButton::onMouseUp_SpeakBtn()
+{
+ bool down = false;
+ gVoiceClient->inputUserControlState(down);
+}
+
diff --git a/indra/newview/llspeakbutton.h b/indra/newview/llspeakbutton.h
new file mode 100644
index 0000000000..6660b50240
--- /dev/null
+++ b/indra/newview/llspeakbutton.h
@@ -0,0 +1,96 @@
+/**
+* @file llspeakbutton.h
+* @brief LLSpeakButton class header file
+*
+* $LicenseInfo:firstyear=2002&license=viewergpl$
+*
+* Copyright (c) 2002-2009, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#ifndef LL_LLSPEAKBUTTON_H
+#define LL_LLSPEAKBUTTON_H
+
+#include "llinitparam.h"
+#include "lluictrl.h"
+
+class LLCallFloater;
+class LLButton;
+class LLOutputMonitorCtrl;
+
+/*
+ * Button displaying voice chat status. Displays voice chat options when
+ * clicked.
+*/
+class LLSpeakButton : public LLUICtrl
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<LLButton::Params>
+ speak_button,
+ show_button;
+
+ Optional<LLOutputMonitorCtrl::Params> monitor;
+
+ Params();
+ };
+
+ /*virtual*/ ~LLSpeakButton();
+ /*virtual*/ void draw();
+
+ // *HACK: Need to put tooltips in a translatable location,
+ // the panel that contains this button.
+ void setSpeakToolTip(const std::string& msg);
+ void setShowToolTip(const std::string& msg);
+
+ /**
+ * Sets visibility of speak button's label according to passed parameter.
+ *
+ * It removes label/selected label if "visible" is false and restores otherwise.
+ *
+ * @param visible if true - show label and selected label.
+ *
+ * @see mSpeakBtn
+ * @see LLBottomTray::processShrinkButtons()
+ */
+ void setLabelVisible(bool visible);
+
+protected:
+ friend class LLUICtrlFactory;
+ LLSpeakButton(const Params& p);
+
+ void onMouseDown_SpeakBtn();
+ void onMouseUp_SpeakBtn();
+
+private:
+ LLButton* mSpeakBtn;
+ LLButton* mShowBtn;
+ LLHandle<LLFloater> mPrivateCallPanel;
+ LLOutputMonitorCtrl* mOutputMonitor;
+};
+
+#endif // LL_LLSPEAKBUTTON_H
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
new file mode 100644
index 0000000000..6f9a1ccdbe
--- /dev/null
+++ b/indra/newview/llspeakers.cpp
@@ -0,0 +1,903 @@
+/**
+ * @file llspeakers.cpp
+ * @brief Management interface for muting and controlling volume of residents currently speaking
+ *
+ * $LicenseInfo:firstyear=2005&license=viewergpl$
+ *
+ * Copyright (c) 2005-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llspeakers.h"
+
+#include "llagent.h"
+#include "llappviewer.h"
+#include "llimview.h"
+#include "llmutelist.h"
+#include "llsdutil.h"
+#include "lluicolortable.h"
+#include "llviewerobjectlist.h"
+#include "llvoavatar.h"
+#include "llworld.h"
+
+const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f);
+const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f);
+
+LLSpeaker::LLSpeaker(const LLUUID& id, const std::string& name, const ESpeakerType type) :
+ mStatus(LLSpeaker::STATUS_TEXT_ONLY),
+ mLastSpokeTime(0.f),
+ mSpeechVolume(0.f),
+ mHasSpoken(FALSE),
+ mHasLeftCurrentCall(FALSE),
+ mDotColor(LLColor4::white),
+ mID(id),
+ mTyping(FALSE),
+ mSortIndex(0),
+ mType(type),
+ mIsModerator(FALSE),
+ mModeratorMutedVoice(FALSE),
+ mModeratorMutedText(FALSE)
+{
+ if (name.empty() && type == SPEAKER_AGENT)
+ {
+ lookupName();
+ }
+ else
+ {
+ mDisplayName = name;
+ }
+}
+
+
+void LLSpeaker::lookupName()
+{
+ gCacheName->get(mID, FALSE, boost::bind(&LLSpeaker::onAvatarNameLookup, this, _1, _2, _3, _4));
+}
+
+void LLSpeaker::onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
+{
+ mDisplayName = first + " " + last;
+}
+
+bool LLSpeaker::isInVoiceChannel()
+{
+ return mStatus == LLSpeaker::STATUS_VOICE_ACTIVE || mStatus == LLSpeaker::STATUS_MUTED;
+}
+
+LLSpeakerUpdateModeratorEvent::LLSpeakerUpdateModeratorEvent(LLSpeaker* source)
+: LLEvent(source, "Speaker add moderator event"),
+ mSpeakerID (source->mID),
+ mIsModerator (source->mIsModerator)
+{
+}
+
+LLSD LLSpeakerUpdateModeratorEvent::getValue()
+{
+ LLSD ret;
+ ret["id"] = mSpeakerID;
+ ret["is_moderator"] = mIsModerator;
+ return ret;
+}
+
+LLSpeakerTextModerationEvent::LLSpeakerTextModerationEvent(LLSpeaker* source)
+: LLEvent(source, "Speaker text moderation event")
+{
+}
+
+LLSD LLSpeakerTextModerationEvent::getValue()
+{
+ return std::string("text");
+}
+
+
+LLSpeakerVoiceModerationEvent::LLSpeakerVoiceModerationEvent(LLSpeaker* source)
+: LLEvent(source, "Speaker voice moderation event")
+{
+}
+
+LLSD LLSpeakerVoiceModerationEvent::getValue()
+{
+ return std::string("voice");
+}
+
+LLSpeakerListChangeEvent::LLSpeakerListChangeEvent(LLSpeakerMgr* source, const LLUUID& speaker_id)
+: LLEvent(source, "Speaker added/removed from speaker mgr"),
+ mSpeakerID(speaker_id)
+{
+}
+
+LLSD LLSpeakerListChangeEvent::getValue()
+{
+ return mSpeakerID;
+}
+
+// helper sort class
+struct LLSortRecentSpeakers
+{
+ bool operator()(const LLPointer<LLSpeaker> lhs, const LLPointer<LLSpeaker> rhs) const;
+};
+
+bool LLSortRecentSpeakers::operator()(const LLPointer<LLSpeaker> lhs, const LLPointer<LLSpeaker> rhs) const
+{
+ // Sort first on status
+ if (lhs->mStatus != rhs->mStatus)
+ {
+ return (lhs->mStatus < rhs->mStatus);
+ }
+
+ // and then on last speaking time
+ if(lhs->mLastSpokeTime != rhs->mLastSpokeTime)
+ {
+ return (lhs->mLastSpokeTime > rhs->mLastSpokeTime);
+ }
+
+ // and finally (only if those are both equal), on name.
+ return( lhs->mDisplayName.compare(rhs->mDisplayName) < 0 );
+}
+
+LLSpeakerActionTimer::LLSpeakerActionTimer(action_callback_t action_cb, F32 action_period, const LLUUID& speaker_id)
+: LLEventTimer(action_period)
+, mActionCallback(action_cb)
+, mSpeakerId(speaker_id)
+{
+}
+
+BOOL LLSpeakerActionTimer::tick()
+{
+ if (mActionCallback)
+ {
+ return (BOOL)mActionCallback(mSpeakerId);
+ }
+ return TRUE;
+}
+
+LLSpeakersDelayActionsStorage::LLSpeakersDelayActionsStorage(LLSpeakerActionTimer::action_callback_t action_cb, F32 action_delay)
+: mActionCallback(action_cb)
+, mActionDelay(action_delay)
+{
+}
+
+LLSpeakersDelayActionsStorage::~LLSpeakersDelayActionsStorage()
+{
+ removeAllTimers();
+}
+
+void LLSpeakersDelayActionsStorage::setActionTimer(const LLUUID& speaker_id)
+{
+ bool not_found = true;
+ if (mActionTimersMap.size() > 0)
+ {
+ not_found = mActionTimersMap.find(speaker_id) == mActionTimersMap.end();
+ }
+
+ // If there is already a started timer for the passed UUID don't do anything.
+ if (not_found)
+ {
+ // Starting a timer to remove an participant after delay is completed
+ mActionTimersMap.insert(LLSpeakerActionTimer::action_value_t(speaker_id,
+ new LLSpeakerActionTimer(
+ boost::bind(&LLSpeakersDelayActionsStorage::onTimerActionCallback, this, _1),
+ mActionDelay, speaker_id)));
+ }
+}
+
+void LLSpeakersDelayActionsStorage::unsetActionTimer(const LLUUID& speaker_id)
+{
+ if (mActionTimersMap.size() == 0) return;
+
+ LLSpeakerActionTimer::action_timer_iter_t it_speaker = mActionTimersMap.find(speaker_id);
+
+ if (it_speaker != mActionTimersMap.end())
+ {
+ delete it_speaker->second;
+ mActionTimersMap.erase(it_speaker);
+ }
+}
+
+void LLSpeakersDelayActionsStorage::removeAllTimers()
+{
+ LLSpeakerActionTimer::action_timer_iter_t iter = mActionTimersMap.begin();
+ for (; iter != mActionTimersMap.end(); ++iter)
+ {
+ delete iter->second;
+ }
+ mActionTimersMap.clear();
+}
+
+bool LLSpeakersDelayActionsStorage::onTimerActionCallback(const LLUUID& speaker_id)
+{
+ unsetActionTimer(speaker_id);
+
+ if (mActionCallback)
+ {
+ mActionCallback(speaker_id);
+ }
+
+ // do not return true to avoid deleting of an timer twice:
+ // in LLSpeakersDelayActionsStorage::unsetActionTimer() & LLEventTimer::updateClass()
+ return false;
+}
+
+
+//
+// LLSpeakerMgr
+//
+
+LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) :
+ mVoiceChannel(channelp)
+{
+ static LLUICachedControl<F32> remove_delay ("SpeakerParticipantRemoveDelay", 10.0);
+
+ mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLSpeakerMgr::removeSpeaker, this, _1), remove_delay);
+}
+
+LLSpeakerMgr::~LLSpeakerMgr()
+{
+ delete mSpeakerDelayRemover;
+}
+
+LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::string& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type)
+{
+ if (id.isNull()) return NULL;
+
+ LLPointer<LLSpeaker> speakerp;
+ if (mSpeakers.find(id) == mSpeakers.end())
+ {
+ speakerp = new LLSpeaker(id, name, type);
+ speakerp->mStatus = status;
+ mSpeakers.insert(std::make_pair(speakerp->mID, speakerp));
+ mSpeakersSorted.push_back(speakerp);
+ fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "add");
+ }
+ else
+ {
+ speakerp = findSpeaker(id);
+ if (speakerp.notNull())
+ {
+ // keep highest priority status (lowest value) instead of overriding current value
+ speakerp->mStatus = llmin(speakerp->mStatus, status);
+ // RN: due to a weird behavior where IMs from attached objects come from the wearer's agent_id
+ // we need to override speakers that we think are objects when we find out they are really
+ // residents
+ if (type == LLSpeaker::SPEAKER_AGENT)
+ {
+ speakerp->mType = LLSpeaker::SPEAKER_AGENT;
+ speakerp->lookupName();
+ }
+ }
+ }
+
+ mSpeakerDelayRemover->unsetActionTimer(speakerp->mID);
+
+ return speakerp;
+}
+
+void LLSpeakerMgr::update(BOOL resort_ok)
+{
+ if (!gVoiceClient)
+ {
+ return;
+ }
+
+ LLColor4 speaking_color = LLUIColorTable::instance().getColor("SpeakingColor");
+ LLColor4 overdriven_color = LLUIColorTable::instance().getColor("OverdrivenColor");
+
+ if(resort_ok) // only allow list changes when user is not interacting with it
+ {
+ updateSpeakerList();
+ }
+
+ // update status of all current speakers
+ BOOL voice_channel_active = (!mVoiceChannel && gVoiceClient->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive());
+ for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end();)
+ {
+ LLUUID speaker_id = speaker_it->first;
+ LLSpeaker* speakerp = speaker_it->second;
+
+ speaker_map_t::iterator cur_speaker_it = speaker_it++;
+
+ if (voice_channel_active && gVoiceClient->getVoiceEnabled(speaker_id))
+ {
+ speakerp->mSpeechVolume = gVoiceClient->getCurrentPower(speaker_id);
+ BOOL moderator_muted_voice = gVoiceClient->getIsModeratorMuted(speaker_id);
+ if (moderator_muted_voice != speakerp->mModeratorMutedVoice)
+ {
+ speakerp->mModeratorMutedVoice = moderator_muted_voice;
+ speakerp->fireEvent(new LLSpeakerVoiceModerationEvent(speakerp));
+ }
+
+ if (gVoiceClient->getOnMuteList(speaker_id) || speakerp->mModeratorMutedVoice)
+ {
+ speakerp->mStatus = LLSpeaker::STATUS_MUTED;
+ }
+ else if (gVoiceClient->getIsSpeaking(speaker_id))
+ {
+ // reset inactivity expiration
+ if (speakerp->mStatus != LLSpeaker::STATUS_SPEAKING)
+ {
+ speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32();
+ speakerp->mHasSpoken = TRUE;
+ }
+ speakerp->mStatus = LLSpeaker::STATUS_SPEAKING;
+ // interpolate between active color and full speaking color based on power of speech output
+ speakerp->mDotColor = speaking_color;
+ if (speakerp->mSpeechVolume > LLVoiceClient::OVERDRIVEN_POWER_LEVEL)
+ {
+ speakerp->mDotColor = overdriven_color;
+ }
+ }
+ else
+ {
+ speakerp->mSpeechVolume = 0.f;
+ speakerp->mDotColor = ACTIVE_COLOR;
+
+ if (speakerp->mHasSpoken)
+ {
+ // have spoken once, not currently speaking
+ speakerp->mStatus = LLSpeaker::STATUS_HAS_SPOKEN;
+ }
+ else
+ {
+ // default state for being in voice channel
+ speakerp->mStatus = LLSpeaker::STATUS_VOICE_ACTIVE;
+ }
+ }
+ }
+ // speaker no longer registered in voice channel, demote to text only
+ else if (speakerp->mStatus != LLSpeaker::STATUS_NOT_IN_CHANNEL)
+ {
+ if(speakerp->mType == LLSpeaker::SPEAKER_EXTERNAL)
+ {
+ // external speakers should be timed out when they leave the voice channel (since they only exist via SLVoice)
+ speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+ }
+ else
+ {
+ speakerp->mStatus = LLSpeaker::STATUS_TEXT_ONLY;
+ speakerp->mSpeechVolume = 0.f;
+ speakerp->mDotColor = ACTIVE_COLOR;
+ }
+ }
+ }
+
+ if(resort_ok) // only allow list changes when user is not interacting with it
+ {
+ // sort by status then time last spoken
+ std::sort(mSpeakersSorted.begin(), mSpeakersSorted.end(), LLSortRecentSpeakers());
+ }
+
+ // for recent speakers who are not currently speaking, show "recent" color dot for most recent
+ // fading to "active" color
+
+ S32 recent_speaker_count = 0;
+ S32 sort_index = 0;
+ speaker_list_t::iterator sorted_speaker_it;
+ for(sorted_speaker_it = mSpeakersSorted.begin();
+ sorted_speaker_it != mSpeakersSorted.end(); ++sorted_speaker_it)
+ {
+ LLPointer<LLSpeaker> speakerp = *sorted_speaker_it;
+
+ // color code recent speakers who are not currently speaking
+ if (speakerp->mStatus == LLSpeaker::STATUS_HAS_SPOKEN)
+ {
+ speakerp->mDotColor = lerp(speaking_color, ACTIVE_COLOR, clamp_rescale((F32)recent_speaker_count, -2.f, 3.f, 0.f, 1.f));
+ recent_speaker_count++;
+ }
+
+ // stuff sort ordinal into speaker so the ui can sort by this value
+ speakerp->mSortIndex = sort_index++;
+ }
+}
+
+void LLSpeakerMgr::updateSpeakerList()
+{
+ // are we bound to the currently active voice channel?
+ if ((!mVoiceChannel && gVoiceClient->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive()))
+ {
+ LLVoiceClient::participantMap* participants = gVoiceClient->getParticipantList();
+ if(participants)
+ {
+ LLVoiceClient::participantMap::iterator participant_it;
+
+ // add new participants to our list of known speakers
+ for (participant_it = participants->begin(); participant_it != participants->end(); ++participant_it)
+ {
+ LLVoiceClient::participantState* participantp = participant_it->second;
+ setSpeaker(participantp->mAvatarID, participantp->mDisplayName, LLSpeaker::STATUS_VOICE_ACTIVE, (participantp->isAvatar()?LLSpeaker::SPEAKER_AGENT:LLSpeaker::SPEAKER_EXTERNAL));
+ }
+ }
+ }
+}
+
+void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp)
+{
+ speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+ speakerp->mDotColor = INACTIVE_COLOR;
+ mSpeakerDelayRemover->setActionTimer(speakerp->mID);
+}
+
+bool LLSpeakerMgr::removeSpeaker(const LLUUID& speaker_id)
+{
+ mSpeakers.erase(speaker_id);
+
+ speaker_list_t::iterator sorted_speaker_it = mSpeakersSorted.begin();
+
+ for(; sorted_speaker_it != mSpeakersSorted.end(); ++sorted_speaker_it)
+ {
+ if (speaker_id == (*sorted_speaker_it)->mID)
+ {
+ mSpeakersSorted.erase(sorted_speaker_it);
+ break;
+ }
+ }
+
+ fireEvent(new LLSpeakerListChangeEvent(this, speaker_id), "remove");
+
+ update(TRUE);
+
+ return false;
+}
+
+LLPointer<LLSpeaker> LLSpeakerMgr::findSpeaker(const LLUUID& speaker_id)
+{
+ //In some conditions map causes crash if it is empty(Windows only), adding check (EK)
+ if (mSpeakers.size() == 0)
+ return NULL;
+ speaker_map_t::iterator found_it = mSpeakers.find(speaker_id);
+ if (found_it == mSpeakers.end())
+ {
+ return NULL;
+ }
+ return found_it->second;
+}
+
+void LLSpeakerMgr::getSpeakerList(speaker_list_t* speaker_list, BOOL include_text)
+{
+ speaker_list->clear();
+ for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)
+ {
+ LLPointer<LLSpeaker> speakerp = speaker_it->second;
+ // what about text only muted or inactive?
+ if (include_text || speakerp->mStatus != LLSpeaker::STATUS_TEXT_ONLY)
+ {
+ speaker_list->push_back(speakerp);
+ }
+ }
+}
+
+const LLUUID LLSpeakerMgr::getSessionID()
+{
+ return mVoiceChannel->getSessionID();
+}
+
+
+void LLSpeakerMgr::setSpeakerTyping(const LLUUID& speaker_id, BOOL typing)
+{
+ LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id);
+ if (speakerp.notNull())
+ {
+ speakerp->mTyping = typing;
+ }
+}
+
+// speaker has chatted via either text or voice
+void LLSpeakerMgr::speakerChatted(const LLUUID& speaker_id)
+{
+ LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id);
+ if (speakerp.notNull())
+ {
+ speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32();
+ speakerp->mHasSpoken = TRUE;
+ }
+}
+
+BOOL LLSpeakerMgr::isVoiceActive()
+{
+ // mVoiceChannel = NULL means current voice channel, whatever it is
+ return LLVoiceClient::voiceEnabled() && mVoiceChannel && mVoiceChannel->isActive();
+}
+
+
+//
+// LLIMSpeakerMgr
+//
+LLIMSpeakerMgr::LLIMSpeakerMgr(LLVoiceChannel* channel) : LLSpeakerMgr(channel)
+{
+}
+
+void LLIMSpeakerMgr::updateSpeakerList()
+{
+ // don't do normal updates which are pulled from voice channel
+ // rely on user list reported by sim
+
+ // We need to do this to allow PSTN callers into group chats to show in the list.
+ LLSpeakerMgr::updateSpeakerList();
+
+ return;
+}
+
+void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers)
+{
+ if ( !speakers.isMap() ) return;
+
+ if ( speakers.has("agent_info") && speakers["agent_info"].isMap() )
+ {
+ LLSD::map_const_iterator speaker_it;
+ for(speaker_it = speakers["agent_info"].beginMap();
+ speaker_it != speakers["agent_info"].endMap();
+ ++speaker_it)
+ {
+ LLUUID agent_id(speaker_it->first);
+
+ LLPointer<LLSpeaker> speakerp = setSpeaker(
+ agent_id,
+ LLStringUtil::null,
+ LLSpeaker::STATUS_TEXT_ONLY);
+
+ if ( speaker_it->second.isMap() )
+ {
+ BOOL is_moderator = speakerp->mIsModerator;
+ speakerp->mIsModerator = speaker_it->second["is_moderator"];
+ speakerp->mModeratorMutedText =
+ speaker_it->second["mutes"]["text"];
+ // Fire event only if moderator changed
+ if ( is_moderator != speakerp->mIsModerator )
+ fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator");
+ }
+ }
+ }
+ else if ( speakers.has("agents" ) && speakers["agents"].isArray() )
+ {
+ //older, more decprecated way. Need here for
+ //using older version of servers
+ LLSD::array_const_iterator speaker_it;
+ for(speaker_it = speakers["agents"].beginArray();
+ speaker_it != speakers["agents"].endArray();
+ ++speaker_it)
+ {
+ const LLUUID agent_id = (*speaker_it).asUUID();
+
+ LLPointer<LLSpeaker> speakerp = setSpeaker(
+ agent_id,
+ LLStringUtil::null,
+ LLSpeaker::STATUS_TEXT_ONLY);
+ }
+ }
+}
+
+void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
+{
+ if ( !update.isMap() ) return;
+
+ if ( update.has("agent_updates") && update["agent_updates"].isMap() )
+ {
+ LLSD::map_const_iterator update_it;
+ for(
+ update_it = update["agent_updates"].beginMap();
+ update_it != update["agent_updates"].endMap();
+ ++update_it)
+ {
+ LLUUID agent_id(update_it->first);
+ LLPointer<LLSpeaker> speakerp = findSpeaker(agent_id);
+
+ LLSD agent_data = update_it->second;
+
+ if (agent_data.isMap() && agent_data.has("transition"))
+ {
+ if (agent_data["transition"].asString() == "LEAVE" && speakerp.notNull())
+ {
+ setSpeakerNotInChannel(speakerp);
+ }
+ else if (agent_data["transition"].asString() == "ENTER")
+ {
+ // add or update speaker
+ speakerp = setSpeaker(agent_id);
+ }
+ else
+ {
+ llwarns << "bad membership list update " << ll_print_sd(agent_data["transition"]) << llendl;
+ }
+ }
+
+ if (speakerp.isNull()) continue;
+
+ // should have a valid speaker from this point on
+ if (agent_data.isMap() && agent_data.has("info"))
+ {
+ LLSD agent_info = agent_data["info"];
+
+ if (agent_info.has("is_moderator"))
+ {
+ BOOL is_moderator = speakerp->mIsModerator;
+ speakerp->mIsModerator = agent_info["is_moderator"];
+ // Fire event only if moderator changed
+ if ( is_moderator != speakerp->mIsModerator )
+ fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator");
+ }
+
+ if (agent_info.has("mutes"))
+ {
+ speakerp->mModeratorMutedText = agent_info["mutes"]["text"];
+ }
+ }
+ }
+ }
+ else if ( update.has("updates") && update["updates"].isMap() )
+ {
+ LLSD::map_const_iterator update_it;
+ for (
+ update_it = update["updates"].beginMap();
+ update_it != update["updates"].endMap();
+ ++update_it)
+ {
+ LLUUID agent_id(update_it->first);
+ LLPointer<LLSpeaker> speakerp = findSpeaker(agent_id);
+
+ std::string agent_transition = update_it->second.asString();
+ if (agent_transition == "LEAVE" && speakerp.notNull())
+ {
+ setSpeakerNotInChannel(speakerp);
+ }
+ else if ( agent_transition == "ENTER")
+ {
+ // add or update speaker
+ speakerp = setSpeaker(agent_id);
+ }
+ else
+ {
+ llwarns << "bad membership list update "
+ << agent_transition << llendl;
+ }
+ }
+ }
+}
+
+class ModerationResponder : public LLHTTPClient::Responder
+{
+public:
+ ModerationResponder(const LLUUID& session_id)
+ {
+ mSessionID = session_id;
+ }
+
+ virtual void error(U32 status, const std::string& reason)
+ {
+ llwarns << status << ": " << reason << llendl;
+
+ if ( gIMMgr )
+ {
+ //403 == you're not a mod
+ //should be disabled if you're not a moderator
+ if ( 403 == status )
+ {
+ gIMMgr->showSessionEventError(
+ "mute",
+ "not_a_mod_error",
+ mSessionID);
+ }
+ else
+ {
+ gIMMgr->showSessionEventError(
+ "mute",
+ "generic_request_error",
+ mSessionID);
+ }
+ }
+ }
+
+private:
+ LLUUID mSessionID;
+};
+
+void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id)
+{
+ LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id);
+ if (!speakerp) return;
+
+ std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest");
+ LLSD data;
+ data["method"] = "mute update";
+ data["session-id"] = getSessionID();
+ data["params"] = LLSD::emptyMap();
+ data["params"]["agent_id"] = speaker_id;
+ data["params"]["mute_info"] = LLSD::emptyMap();
+ //current value represents ability to type, so invert
+ data["params"]["mute_info"]["text"] = !speakerp->mModeratorMutedText;
+
+ LLHTTPClient::post(url, data, new ModerationResponder(getSessionID()));
+}
+
+void LLIMSpeakerMgr::moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute)
+{
+ LLPointer<LLSpeaker> speakerp = findSpeaker(avatar_id);
+ if (!speakerp) return;
+
+ // *NOTE: mantipov: probably this condition will be incorrect when avatar will be blocked for
+ // text chat via moderation (LLSpeaker::mModeratorMutedText == TRUE)
+ bool is_in_voice = speakerp->mStatus <= LLSpeaker::STATUS_VOICE_ACTIVE || speakerp->mStatus == LLSpeaker::STATUS_MUTED;
+
+ // do not send voice moderation changes for avatars not in voice channel
+ if (!is_in_voice) return;
+
+ std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest");
+ LLSD data;
+ data["method"] = "mute update";
+ data["session-id"] = getSessionID();
+ data["params"] = LLSD::emptyMap();
+ data["params"]["agent_id"] = avatar_id;
+ data["params"]["mute_info"] = LLSD::emptyMap();
+ data["params"]["mute_info"]["voice"] = !unmute;
+
+ LLHTTPClient::post(
+ url,
+ data,
+ new ModerationResponder(getSessionID()));
+}
+
+void LLIMSpeakerMgr::moderateVoiceOtherParticipants(const LLUUID& excluded_avatar_id, bool unmute_everyone_else)
+{
+ // *TODO: mantipov: add more intellectual processing of several following requests if it is needed.
+ /*
+ Such situation should be tested:
+ "Moderator sends the same second request before first response is come"
+ Moderator sends "mute everyone else" for A and then for B
+ two requests to disallow voice chat are sent
+ UUID of B is stored.
+ Then first response (to disallow voice chat) is come
+ request to allow voice for stored avatar (B)
+ Then second response (to disallow voice chat) is come
+ have nothing to do, the latest selected speaker is already enabled
+
+ What can happen?
+ If request to allow voice for stored avatar (B) is processed on server BEFORE
+ second request to disallow voice chat all speakers will be disabled on voice.
+ But I'm not sure such situation is possible.
+ See EXT-3431.
+ */
+
+ mReverseVoiceModeratedAvatarID = excluded_avatar_id;
+ moderateVoiceSession(getSessionID(), !unmute_everyone_else);
+}
+
+void LLIMSpeakerMgr::processSessionUpdate(const LLSD& session_update)
+{
+ if (mReverseVoiceModeratedAvatarID.isNull()) return;
+
+ if (session_update.has("moderated_mode") &&
+ session_update["moderated_mode"].has("voice"))
+ {
+ BOOL voice_moderated = session_update["moderated_mode"]["voice"];
+
+ moderateVoiceParticipant(mReverseVoiceModeratedAvatarID, voice_moderated);
+
+ mReverseVoiceModeratedAvatarID = LLUUID::null;
+ }
+}
+
+void LLIMSpeakerMgr::moderateVoiceSession(const LLUUID& session_id, bool disallow_voice)
+{
+ std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest");
+ LLSD data;
+ data["method"] = "session update";
+ data["session-id"] = session_id;
+ data["params"] = LLSD::emptyMap();
+
+ data["params"]["update_info"] = LLSD::emptyMap();
+
+ data["params"]["update_info"]["moderated_mode"] = LLSD::emptyMap();
+ data["params"]["update_info"]["moderated_mode"]["voice"] = disallow_voice;
+
+ LLHTTPClient::post(url, data, new ModerationResponder(session_id));
+}
+
+
+//
+// LLActiveSpeakerMgr
+//
+
+LLActiveSpeakerMgr::LLActiveSpeakerMgr() : LLSpeakerMgr(NULL)
+{
+}
+
+void LLActiveSpeakerMgr::updateSpeakerList()
+{
+ // point to whatever the current voice channel is
+ mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel();
+
+ // always populate from active voice channel
+ if (LLVoiceChannel::getCurrentVoiceChannel() != mVoiceChannel) //MA: seems this is always false
+ {
+ fireEvent(new LLSpeakerListChangeEvent(this, LLUUID::null), "clear");
+ mSpeakers.clear();
+ mSpeakersSorted.clear();
+ mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel();
+ mSpeakerDelayRemover->removeAllTimers();
+ }
+ LLSpeakerMgr::updateSpeakerList();
+
+ // clean up text only speakers
+ for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)
+ {
+ LLUUID speaker_id = speaker_it->first;
+ LLSpeaker* speakerp = speaker_it->second;
+ if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY)
+ {
+ // automatically flag text only speakers for removal
+ speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+ }
+ }
+
+}
+
+
+
+//
+// LLLocalSpeakerMgr
+//
+
+LLLocalSpeakerMgr::LLLocalSpeakerMgr() : LLSpeakerMgr(LLVoiceChannelProximal::getInstance())
+{
+}
+
+LLLocalSpeakerMgr::~LLLocalSpeakerMgr ()
+{
+}
+
+void LLLocalSpeakerMgr::updateSpeakerList()
+{
+ // pull speakers from voice channel
+ LLSpeakerMgr::updateSpeakerList();
+
+ if (gDisconnected)//the world is cleared.
+ {
+ return ;
+ }
+
+ // pick up non-voice speakers in chat range
+ std::vector<LLUUID> avatar_ids;
+ std::vector<LLVector3d> positions;
+ LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgent.getPositionGlobal(), CHAT_NORMAL_RADIUS);
+ for(U32 i=0; i<avatar_ids.size(); i++)
+ {
+ setSpeaker(avatar_ids[i]);
+ }
+
+ // check if text only speakers have moved out of chat range
+ for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)
+ {
+ LLUUID speaker_id = speaker_it->first;
+ LLSpeaker* speakerp = speaker_it->second;
+ if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY)
+ {
+ LLVOAvatar* avatarp = (LLVOAvatar*)gObjectList.findObject(speaker_id);
+ if (!avatarp || dist_vec(avatarp->getPositionAgent(), gAgent.getPositionAgent()) > CHAT_NORMAL_RADIUS)
+ {
+ setSpeakerNotInChannel(speakerp);
+ }
+ }
+ }
+}
diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h
new file mode 100644
index 0000000000..63237204c8
--- /dev/null
+++ b/indra/newview/llspeakers.h
@@ -0,0 +1,311 @@
+/**
+ * @file llspeakers.h
+ * @brief Management interface for muting and controlling volume of residents currently speaking
+ *
+ * $LicenseInfo:firstyear=2005&license=viewergpl$
+ *
+ * Copyright (c) 2005-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSPEAKERS_H
+#define LL_LLSPEAKERS_H
+
+#include "llevent.h"
+#include "llspeakers.h"
+#include "llvoicechannel.h"
+
+class LLSpeakerMgr;
+
+// data for a given participant in a voice channel
+class LLSpeaker : public LLRefCount, public LLOldEvents::LLObservable, public LLHandleProvider<LLSpeaker>, public boost::signals2::trackable
+{
+public:
+ typedef enum e_speaker_type
+ {
+ SPEAKER_AGENT,
+ SPEAKER_OBJECT,
+ SPEAKER_EXTERNAL // Speaker that doesn't map to an avatar or object (i.e. PSTN caller in a group)
+ } ESpeakerType;
+
+ typedef enum e_speaker_status
+ {
+ STATUS_SPEAKING,
+ STATUS_HAS_SPOKEN,
+ STATUS_VOICE_ACTIVE,
+ STATUS_TEXT_ONLY,
+ STATUS_NOT_IN_CHANNEL,
+ STATUS_MUTED
+ } ESpeakerStatus;
+
+
+ LLSpeaker(const LLUUID& id, const std::string& name = LLStringUtil::null, const ESpeakerType type = SPEAKER_AGENT);
+ ~LLSpeaker() {};
+ void lookupName();
+
+ void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
+
+ bool isInVoiceChannel();
+
+ ESpeakerStatus mStatus; // current activity status in speech group
+ F32 mLastSpokeTime; // timestamp when this speaker last spoke
+ F32 mSpeechVolume; // current speech amplitude (timea average rms amplitude?)
+ std::string mDisplayName; // cache user name for this speaker
+ BOOL mHasSpoken; // has this speaker said anything this session?
+ BOOL mHasLeftCurrentCall; // has this speaker left the current voice call?
+ LLColor4 mDotColor;
+ LLUUID mID;
+ BOOL mTyping;
+ S32 mSortIndex;
+ ESpeakerType mType;
+ BOOL mIsModerator;
+ BOOL mModeratorMutedVoice;
+ BOOL mModeratorMutedText;
+};
+
+class LLSpeakerUpdateModeratorEvent : public LLOldEvents::LLEvent
+{
+public:
+ LLSpeakerUpdateModeratorEvent(LLSpeaker* source);
+ /*virtual*/ LLSD getValue();
+private:
+ const LLUUID& mSpeakerID;
+ BOOL mIsModerator;
+};
+
+class LLSpeakerTextModerationEvent : public LLOldEvents::LLEvent
+{
+public:
+ LLSpeakerTextModerationEvent(LLSpeaker* source);
+ /*virtual*/ LLSD getValue();
+};
+
+class LLSpeakerVoiceModerationEvent : public LLOldEvents::LLEvent
+{
+public:
+ LLSpeakerVoiceModerationEvent(LLSpeaker* source);
+ /*virtual*/ LLSD getValue();
+};
+
+class LLSpeakerListChangeEvent : public LLOldEvents::LLEvent
+{
+public:
+ LLSpeakerListChangeEvent(LLSpeakerMgr* source, const LLUUID& speaker_id);
+ /*virtual*/ LLSD getValue();
+
+private:
+ const LLUUID& mSpeakerID;
+};
+
+/**
+ * class LLSpeakerActionTimer
+ *
+ * Implements a timer that calls stored callback action for stored speaker after passed period.
+ *
+ * Action is called until callback returns "true".
+ * In this case the timer will be removed via LLEventTimer::updateClass().
+ * Otherwise it should be deleted manually in place where it is used.
+ * If action callback is not set timer will tick only once and deleted.
+ */
+class LLSpeakerActionTimer : public LLEventTimer
+{
+public:
+ typedef boost::function<bool(const LLUUID&)> action_callback_t;
+ typedef std::map<LLUUID, LLSpeakerActionTimer*> action_timers_map_t;
+ typedef action_timers_map_t::value_type action_value_t;
+ typedef action_timers_map_t::const_iterator action_timer_const_iter_t;
+ typedef action_timers_map_t::iterator action_timer_iter_t;
+
+ /**
+ * Constructor.
+ *
+ * @param action_cb - callback which will be called each time after passed action period.
+ * @param action_period - time in seconds timer should tick.
+ * @param speaker_id - LLUUID of speaker which will be passed into action callback.
+ */
+ LLSpeakerActionTimer(action_callback_t action_cb, F32 action_period, const LLUUID& speaker_id);
+ virtual ~LLSpeakerActionTimer() {};
+
+ /**
+ * Implements timer "tick".
+ *
+ * If action callback is not specified returns true. Instance will be deleted by LLEventTimer::updateClass().
+ */
+ virtual BOOL tick();
+
+private:
+ action_callback_t mActionCallback;
+ LLUUID mSpeakerId;
+};
+
+/**
+ * Represents a functionality to store actions for speakers with delay.
+ * Is based on LLSpeakerActionTimer.
+ */
+class LLSpeakersDelayActionsStorage
+{
+public:
+ LLSpeakersDelayActionsStorage(LLSpeakerActionTimer::action_callback_t action_cb, F32 action_delay);
+ ~LLSpeakersDelayActionsStorage();
+
+ /**
+ * Sets new LLSpeakerActionTimer with passed speaker UUID.
+ */
+ void setActionTimer(const LLUUID& speaker_id);
+
+ /**
+ * Removes stored LLSpeakerActionTimer for passed speaker UUID from internal map and deletes it.
+ *
+ * @see onTimerActionCallback()
+ */
+ void unsetActionTimer(const LLUUID& speaker_id);
+
+ void removeAllTimers();
+private:
+ /**
+ * Callback of the each instance of LLSpeakerActionTimer.
+ *
+ * Unsets an appropriate timer instance and calls action callback for specified speacker_id.
+ * It always returns false to not use LLEventTimer::updateClass functionality of timer deleting.
+ *
+ * @see unsetActionTimer()
+ */
+ bool onTimerActionCallback(const LLUUID& speaker_id);
+
+ LLSpeakerActionTimer::action_timers_map_t mActionTimersMap;
+ LLSpeakerActionTimer::action_callback_t mActionCallback;
+
+ /**
+ * Delay to call action callback for speakers after timer was set.
+ */
+ F32 mActionDelay;
+
+};
+
+
+class LLSpeakerMgr : public LLOldEvents::LLObservable
+{
+public:
+ LLSpeakerMgr(LLVoiceChannel* channelp);
+ virtual ~LLSpeakerMgr();
+
+ LLPointer<LLSpeaker> findSpeaker(const LLUUID& avatar_id);
+ void update(BOOL resort_ok);
+ void setSpeakerTyping(const LLUUID& speaker_id, BOOL typing);
+ void speakerChatted(const LLUUID& speaker_id);
+ LLPointer<LLSpeaker> setSpeaker(const LLUUID& id,
+ const std::string& name = LLStringUtil::null,
+ LLSpeaker::ESpeakerStatus status = LLSpeaker::STATUS_TEXT_ONLY,
+ LLSpeaker::ESpeakerType = LLSpeaker::SPEAKER_AGENT);
+
+ BOOL isVoiceActive();
+
+ typedef std::vector<LLPointer<LLSpeaker> > speaker_list_t;
+ void getSpeakerList(speaker_list_t* speaker_list, BOOL include_text);
+ LLVoiceChannel* getVoiceChannel() { return mVoiceChannel; }
+ const LLUUID getSessionID();
+
+protected:
+ virtual void updateSpeakerList();
+ void setSpeakerNotInChannel(LLSpeaker* speackerp);
+ bool removeSpeaker(const LLUUID& speaker_id);
+
+ typedef std::map<LLUUID, LLPointer<LLSpeaker> > speaker_map_t;
+ speaker_map_t mSpeakers;
+
+ speaker_list_t mSpeakersSorted;
+ LLFrameTimer mSpeechTimer;
+ LLVoiceChannel* mVoiceChannel;
+
+ /**
+ * time out speakers when they are not part of current session
+ */
+ LLSpeakersDelayActionsStorage* mSpeakerDelayRemover;
+};
+
+class LLIMSpeakerMgr : public LLSpeakerMgr
+{
+public:
+ LLIMSpeakerMgr(LLVoiceChannel* channel);
+
+ void updateSpeakers(const LLSD& update);
+ void setSpeakers(const LLSD& speakers);
+
+ void toggleAllowTextChat(const LLUUID& speaker_id);
+
+ /**
+ * Mutes/Unmutes avatar for current group voice chat.
+ *
+ * It only marks avatar as muted for session and does not use local Agent's Block list.
+ * It does not mute Agent itself.
+ *
+ * @param[in] avatar_id UUID of avatar to be processed
+ * @param[in] unmute if false - specified avatar will be muted, otherwise - unmuted.
+ *
+ * @see moderateVoiceOtherParticipants()
+ */
+ void moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute);
+
+ /**
+ * Mutes/Unmutes all avatars except specified for current group voice chat.
+ *
+ * It only marks avatars as muted for session and does not use local Agent's Block list.
+ * It based call moderateVoiceParticipant() for each avatar should be muted/unmuted.
+ *
+ * @param[in] excluded_avatar_id UUID of avatar NOT to be processed
+ * @param[in] unmute_everyone_else if false - avatars will be muted, otherwise - unmuted.
+ *
+ * @see moderateVoiceParticipant()
+ */
+ void moderateVoiceOtherParticipants(const LLUUID& excluded_avatar_id, bool unmute_everyone_else);
+
+ void processSessionUpdate(const LLSD& session_update);
+
+protected:
+ virtual void updateSpeakerList();
+
+ void moderateVoiceSession(const LLUUID& session_id, bool disallow_voice);
+
+ LLUUID mReverseVoiceModeratedAvatarID;
+};
+
+class LLActiveSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLActiveSpeakerMgr>
+{
+public:
+ LLActiveSpeakerMgr();
+protected:
+ virtual void updateSpeakerList();
+};
+
+class LLLocalSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLLocalSpeakerMgr>
+{
+public:
+ LLLocalSpeakerMgr();
+ ~LLLocalSpeakerMgr ();
+protected:
+ virtual void updateSpeakerList();
+};
+
+#endif // LL_LLSPEAKERS_H
diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp
new file mode 100644
index 0000000000..5e1d408e8d
--- /dev/null
+++ b/indra/newview/llspeakingindicatormanager.cpp
@@ -0,0 +1,249 @@
+/**
+ * @file llspeakingindicatormanager.cpp
+ * @author Mike Antipov
+ * @brief Implementation of SpeackerIndicatorManager class to process registered LLSpeackerIndicator
+ * depend on avatars are in the same voice channel.
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llspeakingindicatormanager.h"
+
+
+#include "llvoicechannel.h"
+#include "llvoiceclient.h"
+
+/**
+ * This class intended to control visibility of avatar speaking indicators depend on whether avatars
+ * are in the same voice channel.
+ *
+ * Speaking indicator should be visible for avatars in the same voice channel. See EXT-3976.
+ *
+ * It stores passed instances of LLOutputMonitorCtrl in a multimap by avatar LLUUID.
+ * It observes changing of voice channel and changing of participant list in voice channel.
+ * When voice channel or voice participant list is changed it updates visibility of an appropriate
+ * speaking indicator.
+ *
+ * Several indicators can be registered for the same avatar.
+ */
+class SpeakingIndicatorManager : public LLSingleton<SpeakingIndicatorManager>, LLVoiceClientParticipantObserver
+{
+ LOG_CLASS(SpeakingIndicatorManager);
+public:
+
+ /**
+ * Stores passed speaking indicator to control its visibility.
+ *
+ * Registered indicator is set visible if an appropriate avatar is in the same voice channel with Agent.
+ * It ignores instances of Agent's indicator.
+ *
+ * @param speaker_id LLUUID of an avatar whose speaking indicator is registered.
+ * @param speaking_indicator instance of the speaking indicator to be registered.
+ */
+ void registerSpeakingIndicator(const LLUUID& speaker_id, LLSpeakingIndicator* const speaking_indicator);
+
+ /**
+ * Removes passed speaking indicator from observing.
+ *
+ * @param speaker_id LLUUID of an avatar whose speaking indicator should be unregistered.
+ * @param speaking_indicator instance of the speaking indicator to be unregistered.
+ */
+ void unregisterSpeakingIndicator(const LLUUID& speaker_id, const LLSpeakingIndicator* const speaking_indicator);
+
+private:
+ typedef std::set<LLUUID> speaker_ids_t;
+ typedef std::multimap<LLUUID, LLSpeakingIndicator*> speaking_indicators_mmap_t;
+ typedef speaking_indicators_mmap_t::value_type speaking_indicator_value_t;
+ typedef speaking_indicators_mmap_t::const_iterator indicator_const_iterator;
+ typedef std::pair<indicator_const_iterator, indicator_const_iterator> indicator_range_t;
+
+ friend class LLSingleton<SpeakingIndicatorManager>;
+ SpeakingIndicatorManager();
+ ~SpeakingIndicatorManager();
+
+ /**
+ * Callback to determine when voice channel is changed.
+ *
+ * It switches all registered speaking indicators off.
+ * To reduce overheads only switched on indicators are processed.
+ */
+ void sOnCurrentChannelChanged(const LLUUID& session_id);
+
+ /**
+ * Callback of changing voice participant list (from LLVoiceClientParticipantObserver).
+ *
+ * Switches off indicators had been switched on and switches on indicators of current participants list.
+ * There is only a few indicators in lists should be switched off/on.
+ * So, method does not calculate difference between these list it only switches off already
+ * switched on indicators and switches on indicators of voice channel participants
+ */
+ void onChange();
+
+ /**
+ * Changes state of indicators specified by LLUUIDs
+ *
+ * @param speakers_uuids - avatars' LLUUIDs whose speaking indicators should be switched
+ * @param switch_on - if TRUE specified indicator will be switched on, off otherwise.
+ */
+ void switchSpeakerIndicators(const speaker_ids_t& speakers_uuids, BOOL switch_on);
+
+ /**
+ * Multimap with all registered speaking indicators
+ */
+ speaking_indicators_mmap_t mSpeakingIndicators;
+
+ /**
+ * LUUIDs of avatar for which we have speaking indicators switched on.
+ *
+ * Is used to switch off all previously ON indicators when voice participant list is changed.
+ *
+ * @see onChange()
+ */
+ speaker_ids_t mSwitchedIndicatorsOn;
+};
+
+//////////////////////////////////////////////////////////////////////////
+// PUBLIC SECTION
+//////////////////////////////////////////////////////////////////////////
+void SpeakingIndicatorManager::registerSpeakingIndicator(const LLUUID& speaker_id, LLSpeakingIndicator* const speaking_indicator)
+{
+ // do not exclude agent's indicators. They should be processed in the same way as others. See EXT-3889.
+
+ LL_DEBUGS("SpeakingIndicator") << "Registering indicator: " << speaker_id << LL_ENDL;
+ speaking_indicator_value_t value_type(speaker_id, speaking_indicator);
+ mSpeakingIndicators.insert(value_type);
+
+ speaker_ids_t speakers_uuids;
+ BOOL is_in_same_voice = LLVoiceClient::getInstance()->findParticipantByID(speaker_id) != NULL;
+
+ speakers_uuids.insert(speaker_id);
+ switchSpeakerIndicators(speakers_uuids, is_in_same_voice);
+}
+
+void SpeakingIndicatorManager::unregisterSpeakingIndicator(const LLUUID& speaker_id, const LLSpeakingIndicator* const speaking_indicator)
+{
+ speaking_indicators_mmap_t::iterator it;
+ it = mSpeakingIndicators.find(speaker_id);
+ for (;it != mSpeakingIndicators.end(); ++it)
+ {
+ if (it->second == speaking_indicator)
+ {
+ mSpeakingIndicators.erase(it);
+ break;
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// PRIVATE SECTION
+//////////////////////////////////////////////////////////////////////////
+SpeakingIndicatorManager::SpeakingIndicatorManager()
+{
+ LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&SpeakingIndicatorManager::sOnCurrentChannelChanged, this, _1));
+ LLVoiceClient::getInstance()->addObserver(this);
+}
+
+SpeakingIndicatorManager::~SpeakingIndicatorManager()
+{
+ // Don't use LLVoiceClient::getInstance() here without check
+ // singleton MAY have already been destroyed.
+ if(LLVoiceClient::instanceExists())
+ {
+ LLVoiceClient::getInstance()->removeObserver(this);
+ }
+}
+
+void SpeakingIndicatorManager::sOnCurrentChannelChanged(const LLUUID& /*session_id*/)
+{
+ switchSpeakerIndicators(mSwitchedIndicatorsOn, FALSE);
+ mSwitchedIndicatorsOn.clear();
+}
+
+void SpeakingIndicatorManager::onChange()
+{
+ LL_DEBUGS("SpeakingIndicator") << "Voice participant list was changed, updating indicators" << LL_ENDL;
+
+ speaker_ids_t speakers_uuids;
+ LLVoiceClient::getInstance()->getParticipantsUUIDSet(speakers_uuids);
+
+ LL_DEBUGS("SpeakingIndicator") << "Switching all OFF, count: " << mSwitchedIndicatorsOn.size() << LL_ENDL;
+ // switch all indicators off
+ switchSpeakerIndicators(mSwitchedIndicatorsOn, FALSE);
+ mSwitchedIndicatorsOn.clear();
+
+ LL_DEBUGS("SpeakingIndicator") << "Switching all ON, count: " << speakers_uuids.size() << LL_ENDL;
+ // then switch current voice participants indicators on
+ switchSpeakerIndicators(speakers_uuids, TRUE);
+}
+
+void SpeakingIndicatorManager::switchSpeakerIndicators(const speaker_ids_t& speakers_uuids, BOOL switch_on)
+{
+ speaker_ids_t::const_iterator it_uuid = speakers_uuids.begin();
+ for (; it_uuid != speakers_uuids.end(); ++it_uuid)
+ {
+ LL_DEBUGS("SpeakingIndicator") << "Looking for indicator: " << *it_uuid << LL_ENDL;
+ indicator_range_t it_range = mSpeakingIndicators.equal_range(*it_uuid);
+ indicator_const_iterator it_indicator = it_range.first;
+ bool was_found = false;
+ for (; it_indicator != it_range.second; ++it_indicator)
+ {
+ was_found = true;
+ LLSpeakingIndicator* indicator = (*it_indicator).second;
+ indicator->switchIndicator(switch_on);
+ }
+
+ if (was_found)
+ {
+ LL_DEBUGS("SpeakingIndicator") << mSpeakingIndicators.count(*it_uuid) << " indicators where found" << LL_ENDL;
+
+ if (switch_on)
+ {
+ // store switched on indicator to be able switch it off
+ mSwitchedIndicatorsOn.insert(*it_uuid);
+ }
+ }
+ }
+}
+
+/************************************************************************/
+/* LLSpeakingIndicatorManager namespace implementation */
+/************************************************************************/
+
+void LLSpeakingIndicatorManager::registerSpeakingIndicator(const LLUUID& speaker_id, LLSpeakingIndicator* const speaking_indicator)
+{
+ SpeakingIndicatorManager::instance().registerSpeakingIndicator(speaker_id, speaking_indicator);
+}
+
+void LLSpeakingIndicatorManager::unregisterSpeakingIndicator(const LLUUID& speaker_id, const LLSpeakingIndicator* const speaking_indicator)
+{
+ SpeakingIndicatorManager::instance().unregisterSpeakingIndicator(speaker_id, speaking_indicator);
+}
+
+// EOF
+
diff --git a/indra/newview/llspeakingindicatormanager.h b/indra/newview/llspeakingindicatormanager.h
new file mode 100644
index 0000000000..ce0158f7d8
--- /dev/null
+++ b/indra/newview/llspeakingindicatormanager.h
@@ -0,0 +1,67 @@
+/**
+ * @file llspeakingindicatormanager.h
+ * @author Mike Antipov
+ * @brief Interfeace of LLSpeackerIndicator class to be processed depend on avatars are in the same voice channel.
+ * Also register/unregister methods for this class are declared
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSPEAKINGINDICATORMANAGER_H
+#define LL_LLSPEAKINGINDICATORMANAGER_H
+
+class LLSpeakingIndicator
+{
+public:
+ virtual void switchIndicator(bool switch_on) = 0;
+};
+
+// See EXT-3976.
+namespace LLSpeakingIndicatorManager
+{
+ /**
+ * Stores passed speaking indicator to control its visibility.
+ *
+ * Registered indicator is set visible if an appropriate avatar is in the same voice channel with Agent.
+ * It ignores instances of Agent's indicator.
+ *
+ * @param speaker_id LLUUID of an avatar whose speaker indicator is registered.
+ * @param speaking_indicator instance of the speaker indicator to be registered.
+ */
+ void registerSpeakingIndicator(const LLUUID& speaker_id, LLSpeakingIndicator* const speaking_indicator);
+
+ /**
+ * Removes passed speaking indicator from observing.
+ *
+ * @param speaker_id LLUUID of an avatar whose speaker indicator should be unregistered.
+ * @param speaking_indicator instance of the speaker indicator to be unregistered.
+ */
+ void unregisterSpeakingIndicator(const LLUUID& speaker_id, const LLSpeakingIndicator* const speaking_indicator);
+}
+
+#endif // LL_LLSPEAKINGINDICATORMANAGER_H
diff --git a/indra/newview/llsplitbutton.cpp b/indra/newview/llsplitbutton.cpp
new file mode 100644
index 0000000000..ffd9bc7624
--- /dev/null
+++ b/indra/newview/llsplitbutton.cpp
@@ -0,0 +1,275 @@
+/**
+ * @file llsplitbutton.cpp
+ * @brief LLSplitButton base class
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// A control that consolidates several buttons as options
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llsplitbutton.h"
+
+#include "llinitparam.h"
+#include "llpanel.h"
+#include "llfocusmgr.h"
+#include "llviewerwindow.h"
+#include "llrootview.h"
+
+
+S32 BUTTON_PAD = 2; //pad between buttons on an items panel
+
+
+static LLDefaultChildRegistry::Register<LLSplitButton> split_button("split_button");
+
+void LLSplitButton::ArrowPositionValues::declareValues()
+{
+ declare("left", LEFT);
+ declare("right", RIGHT);
+}
+
+LLSplitButton::ItemParams::ItemParams()
+{
+}
+
+LLSplitButton::Params::Params()
+: arrow_position("arrow_position", LEFT),
+ items("item"),
+ arrow_button("arrow_button"),
+ items_panel("items_panel")
+{
+}
+
+
+void LLSplitButton::onFocusLost()
+{
+ hideButtons();
+ LLUICtrl::onFocusLost();
+}
+
+void LLSplitButton::setFocus(BOOL b)
+{
+ LLUICtrl::setFocus(b);
+
+ if (b)
+ {
+ if (mItemsPanel && mItemsPanel->getVisible())
+ {
+ mItemsPanel->setFocus(TRUE);
+ }
+ }
+}
+
+void LLSplitButton::setEnabled(BOOL enabled)
+{
+ LLView::setEnabled(enabled);
+ mArrowBtn->setEnabled(enabled);
+}
+
+
+void LLSplitButton::onArrowBtnDown()
+{
+ if (!mItemsPanel->getVisible())
+ {
+ showButtons();
+
+ setFocus(TRUE);
+
+ if (mArrowBtn->hasMouseCapture() || mShownItem->hasMouseCapture())
+ {
+ gFocusMgr.setMouseCapture(this);
+ }
+ }
+ else
+ {
+ hideButtons();
+ }
+}
+
+void LLSplitButton::onHeldDownShownButton()
+{
+ if (!mItemsPanel->getVisible()) onArrowBtnDown();
+}
+
+void LLSplitButton::onItemSelected(LLUICtrl* ctrl)
+{
+ if (!ctrl) return;
+
+ hideButtons();
+
+ // call the callback if it exists
+ if(!mSelectionCallback.empty())
+ {
+ mSelectionCallback(this, ctrl->getName());
+ }
+
+ gFocusMgr.setKeyboardFocus(NULL);
+}
+
+BOOL LLSplitButton::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+ gFocusMgr.setMouseCapture(NULL);
+
+ if (mShownItem->parentPointInView(x, y))
+ {
+ onItemSelected(mShownItem);
+ return TRUE;
+ }
+
+ for (std::list<LLButton*>::const_iterator it = mHidenItems.begin(); it != mHidenItems.end(); ++it)
+ {
+ LLButton* item = *it;
+
+ S32 panel_x = 0;
+ S32 panel_y = 0;
+ localPointToOtherView(x, y, &panel_x, &panel_y, mItemsPanel);
+
+ if (item->parentPointInView(panel_x, panel_y))
+ {
+ onItemSelected(item);
+ return TRUE;
+ }
+ }
+ return TRUE;
+}
+
+void LLSplitButton::showButtons()
+{
+ mItemsPanel->setOrigin(0, getRect().getHeight());
+
+ // register ourselves as a "top" control
+ // effectively putting us into a special draw layer
+ gFocusMgr.setTopCtrl(this);
+
+ mItemsPanel->setFocus(TRUE);
+
+ //push arrow button down and show the item buttons
+ mArrowBtn->setToggleState(TRUE);
+ mItemsPanel->setVisible(TRUE);
+
+ setUseBoundingRect(TRUE);
+}
+
+void LLSplitButton::hideButtons()
+{
+ mItemsPanel->setVisible(FALSE);
+ mArrowBtn->setToggleState(FALSE);
+
+ setUseBoundingRect(FALSE);
+ if(gFocusMgr.getTopCtrl() == this)
+ {
+ gFocusMgr.setTopCtrl(NULL);
+ }
+}
+
+
+// protected/private
+
+LLSplitButton::LLSplitButton(const LLSplitButton::Params& p)
+: LLUICtrl(p),
+ mArrowBtn(NULL),
+ mShownItem(NULL),
+ mItemsPanel(NULL),
+ mArrowPosition(p.arrow_position)
+{
+ LLRect rc(p.rect);
+
+ LLButton::Params arrow_params = p.arrow_button;
+ S32 arrow_width = p.arrow_button.rect.width;
+
+ //Default arrow rect values for LEFT arrow position
+ S32 arrow_left = 0;
+ S32 arrow_right = arrow_width;
+ S32 btn_left = arrow_width;
+ S32 btn_right = rc.getWidth();
+
+ if (mArrowPosition == RIGHT)
+ {
+ arrow_left = rc.getWidth()- arrow_width;
+ arrow_right = rc.getWidth();
+ btn_left = 0;
+ btn_right = arrow_left;
+ }
+
+ arrow_params.rect(LLRect(arrow_left, rc.getHeight(), arrow_right, 0));
+ arrow_params.label("");
+ arrow_params.mouse_down_callback.function(boost::bind(&LLSplitButton::onArrowBtnDown, this));
+ mArrowBtn = LLUICtrlFactory::create<LLButton>(arrow_params);
+ addChild(mArrowBtn);
+
+ //a panel for hidden item buttons
+ LLPanel::Params panel_params = p.items_panel;
+ mItemsPanel= prepareItemsPanel(panel_params, p.items.numValidElements());
+ addChild(mItemsPanel);
+
+
+ LLInitParam::ParamIterator<ItemParams>::const_iterator it = p.items().begin();
+
+ //processing shown item button
+ mShownItem = prepareItemButton(*it);
+ mShownItem->setHeldDownCallback(boost::bind(&LLSplitButton::onHeldDownShownButton, this));
+ mShownItem->setMouseUpCallback(boost::bind(&LLSplitButton::onItemSelected, this, _1));
+ mShownItem->setRect(LLRect(btn_left, rc.getHeight(), btn_right, 0));
+ addChild(mShownItem);
+
+ //processing hidden item buttons
+ S32 item_top = mItemsPanel->getRect().getHeight();
+ for (++it; it != p.items().end(); ++it)
+ {
+ LLButton* hidden_button = prepareItemButton(*it);
+ hidden_button->setRect(LLRect(btn_left, item_top, btn_right, item_top - rc.getHeight()));
+ hidden_button->setMouseDownCallback(boost::bind(&LLSplitButton::onItemSelected, this, _1));
+ mHidenItems.push_back(hidden_button);
+ mItemsPanel->addChild(hidden_button);
+
+ //calculate next button's top
+ item_top -= (rc.getHeight() + BUTTON_PAD);
+ }
+
+ setTopLostCallback(boost::bind(&LLSplitButton::hideButtons, this));
+}
+
+
+LLButton* LLSplitButton::prepareItemButton(LLButton::Params params)
+{
+ params.label("");
+ params.is_toggle(false);
+ return LLUICtrlFactory::create<LLButton>(params);
+}
+
+LLPanel* LLSplitButton::prepareItemsPanel(LLPanel::Params params, S32 items_count)
+{
+ S32 num_hiden_btns = items_count - 1;
+ S32 panel_height = num_hiden_btns * (getRect().getHeight() + BUTTON_PAD);
+ params.visible(false);
+ params.rect.width(getRect().getWidth());
+ params.rect.height(panel_height);
+ return LLUICtrlFactory::create<LLPanel>(params);
+}
+
diff --git a/indra/newview/llsplitbutton.h b/indra/newview/llsplitbutton.h
new file mode 100644
index 0000000000..0fb5f6594e
--- /dev/null
+++ b/indra/newview/llsplitbutton.h
@@ -0,0 +1,112 @@
+/**
+ * @file llsplitbutton.h
+ * @brief LLSplitButton base class
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// A control that displays the name of the chosen item, which when clicked
+// shows a scrolling box of choices.
+
+
+#include "llbutton.h"
+#include "llpanel.h"
+#include "lluictrl.h"
+
+
+#ifndef LL_LLSPLITBUTTON_H
+#define LL_LLSPLITBUTTON_H
+
+class LLSplitButton
+ : public LLUICtrl
+{
+public:
+ typedef enum e_arrow_position
+ {
+ LEFT,
+ RIGHT
+ } EArrowPosition;
+
+ struct ArrowPositionValues : public LLInitParam::TypeValuesHelper<EArrowPosition, ArrowPositionValues>
+ {
+ static void declareValues();
+ };
+
+ struct ItemParams : public LLInitParam::Block<ItemParams, LLButton::Params>
+ {
+ ItemParams();
+ };
+
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<EArrowPosition, ArrowPositionValues> arrow_position;
+ Optional<LLButton::Params> arrow_button;
+ Optional<LLPanel::Params> items_panel;
+ Multiple<ItemParams> items;
+
+ Params();
+ };
+
+
+ virtual ~LLSplitButton() {};
+
+ //Overridden
+ virtual void onFocusLost();
+ virtual void setFocus(BOOL b);
+ virtual void setEnabled(BOOL enabled);
+
+ //Callbacks
+ void onArrowBtnDown();
+ void onHeldDownShownButton();
+ void onItemSelected(LLUICtrl* ctrl);
+ void setSelectionCallback(commit_callback_t cb) { mSelectionCallback = cb; }
+
+ virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+
+ virtual void showButtons();
+ virtual void hideButtons();
+
+
+protected:
+ friend class LLUICtrlFactory;
+ LLSplitButton(const LLSplitButton::Params& p);
+
+ LLButton* prepareItemButton(LLButton::Params params);
+ LLPanel* prepareItemsPanel(LLPanel::Params params, S32 items_count);
+
+ LLPanel* mItemsPanel;
+ std::list<LLButton*> mHidenItems;
+ LLButton* mArrowBtn;
+ LLButton* mShownItem;
+ EArrowPosition mArrowPosition;
+
+ commit_callback_t mSelectionCallback;
+};
+
+
+#endif
diff --git a/indra/newview/llsprite.cpp b/indra/newview/llsprite.cpp
index 893ed22297..dce4e9d144 100644
--- a/indra/newview/llsprite.cpp
+++ b/indra/newview/llsprite.cpp
@@ -48,7 +48,7 @@
#include "lldrawable.h"
#include "llface.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
LLVector3 LLSprite::sCameraUp(0.0f,0.0f,1.0f);
LLVector3 LLSprite::sCameraRight(1.0f,0.0f,0.0f);
diff --git a/indra/newview/llsprite.h b/indra/newview/llsprite.h
index 28f4ec5d03..eefe2a2386 100644
--- a/indra/newview/llsprite.h
+++ b/indra/newview/llsprite.h
@@ -40,7 +40,7 @@
#include "v4color.h"
#include "lluuid.h"
#include "llgl.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
class LLViewerCamera;
@@ -82,7 +82,7 @@ public:
public:
LLUUID mImageID;
- LLPointer<LLViewerImage> mImagep;
+ LLPointer<LLViewerTexture> mImagep;
private:
F32 mWidth;
F32 mHeight;
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 2c0d11baab..6b816f8786 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -40,88 +40,88 @@
# include <sys/stat.h> // mkdir()
#endif
-#include "audioengine.h"
+#include "llviewermedia_streamingaudio.h"
+#include "llaudioengine.h"
#ifdef LL_FMOD
-# include "audioengine_fmod.h"
+# include "llaudioengine_fmod.h"
#endif
#ifdef LL_OPENAL
-#include "audioengine_openal.h"
+#include "llaudioengine_openal.h"
#endif
#include "llares.h"
+#include "lllandmark.h"
#include "llcachename.h"
-#include "llviewercontrol.h"
#include "lldir.h"
#include "llerrorcontrol.h"
-#include "llfiltersd2xmlrpc.h"
+#include "llfloaterreg.h"
#include "llfocusmgr.h"
#include "llhttpsender.h"
-#include "imageids.h"
-#include "lllandmark.h"
+#include "llimfloater.h"
+#include "lllocationhistory.h"
+#include "llimageworker.h"
#include "llloginflags.h"
#include "llmd5.h"
#include "llmemorystream.h"
#include "llmessageconfig.h"
#include "llmoveview.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+#include "llteleporthistory.h"
#include "llregionhandle.h"
#include "llsd.h"
#include "llsdserialize.h"
-#include "llsdutil.h"
+#include "llsdutil_math.h"
#include "llsecondlifeurls.h"
#include "llstring.h"
#include "lluserrelations.h"
-#include "llversionviewer.h"
+#include "llversioninfo.h"
+#include "llviewercontrol.h"
#include "llvfs.h"
#include "llxorcipher.h" // saved password, MAC address
+#include "llwindow.h"
+#include "imageids.h"
#include "message.h"
#include "v3math.h"
#include "llagent.h"
+#include "llagentpicksinfo.h"
+#include "llagentwearables.h"
#include "llagentpilot.h"
#include "llfloateravatarpicker.h"
#include "llcallbacklist.h"
#include "llcallingcard.h"
-#include "llcolorscheme.h"
#include "llconsole.h"
#include "llcontainerview.h"
-#include "llfloaterstats.h"
#include "lldebugview.h"
#include "lldrawable.h"
#include "lleventnotifier.h"
#include "llface.h"
#include "llfeaturemanager.h"
-#include "llfirstuse.h"
-#include "llfloateractivespeakers.h"
-#include "llfloaterbeacons.h"
-#include "llfloatercamera.h"
-#include "llfloaterchat.h"
-#include "llfloatergesture.h"
+//#include "llfirstuse.h"
#include "llfloaterhud.h"
#include "llfloaterland.h"
+#include "llfloaterpreference.h"
#include "llfloatertopobjects.h"
-#include "llfloatertos.h"
#include "llfloaterworldmap.h"
-#include "llframestats.h"
-#include "llframestatview.h"
#include "llgesturemgr.h"
#include "llgroupmgr.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
#include "llhttpclient.h"
#include "llimagebmp.h"
+#include "llinventorybridge.h"
#include "llinventorymodel.h"
-#include "llinventoryview.h"
+#include "llfriendcard.h"
#include "llkeyboard.h"
#include "llloginhandler.h" // gLoginHandler, SLURL support
+#include "lllogininstance.h" // Host the login module.
#include "llpanellogin.h"
-#include "llprefsim.h"
#include "llmutelist.h"
-#include "llnotify.h"
#include "llpanelavatar.h"
-#include "llpaneldirbrowser.h"
-#include "llpaneldirland.h"
+#include "llavatarpropertiesprocessor.h"
#include "llpanelevent.h"
#include "llpanelclassified.h"
#include "llpanelpick.h"
@@ -134,7 +134,6 @@
#include "llsecondlifeurls.h"
#include "llselectmgr.h"
#include "llsky.h"
-#include "llsrv.h"
#include "llstatview.h"
#include "lltrans.h"
#include "llstatusbar.h" // sendMoneyBalanceRequest(), owns L$ balance
@@ -147,14 +146,13 @@
#include "llurlsimstring.h"
#include "llurlhistory.h"
#include "llurlwhitelist.h"
-#include "lluserauth.h"
#include "llvieweraudio.h"
#include "llviewerassetstorage.h"
#include "llviewercamera.h"
#include "llviewerdisplay.h"
#include "llviewergenericmessage.h"
#include "llviewergesture.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewermedia.h"
#include "llviewermenu.h"
#include "llviewermessage.h"
@@ -167,10 +165,11 @@
#include "llviewerthrottle.h"
#include "llviewerwindow.h"
#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "llvoclouds.h"
#include "llweb.h"
#include "llworld.h"
-#include "llworldmap.h"
+#include "llworldmapmessage.h"
#include "llxfermanager.h"
#include "pipeline.h"
#include "llappviewer.h"
@@ -185,26 +184,34 @@
#include "llwlparammanager.h"
#include "llwaterparammanager.h"
#include "llagentlanguage.h"
+#include "llwearable.h"
+#include "llinventorybridge.h"
+#include "llappearancemgr.h"
+#include "llavatariconctrl.h"
-#if LL_LIBXUL_ENABLED
-#include "llmozlib.h"
-#endif // LL_LIBXUL_ENABLED
+#include "lllogin.h"
+#include "llevents.h"
+#include "llstartuplistener.h"
#if LL_WINDOWS
#include "llwindebug.h"
#include "lldxhardware.h"
#endif
+#if (LL_LINUX || LL_SOLARIS) && LL_GTK
+#include <glib/gspawn.h>
+#endif
+
//
// exported globals
//
bool gAgentMovementCompleted = false;
-std::string gInitialOutfit;
-std::string gInitialOutfitGender;
std::string SCREEN_HOME_FILENAME = "screen_home.bmp";
std::string SCREEN_LAST_FILENAME = "screen_last.bmp";
+LLPointer<LLViewerTexture> gStartTexture;
+
//
// Imported globals
//
@@ -214,12 +221,6 @@ extern S32 gStartImageHeight;
//
// local globals
//
-
-LLPointer<LLImageGL> gStartImageGL;
-
-static LLHost gAgentSimHost;
-static BOOL gSkipOptionalUpdate = FALSE;
-
static bool gGotUseCircuitCodeAck = false;
static std::string sInitialOutfit;
static std::string sInitialOutfitGender; // "male" or "female"
@@ -228,6 +229,19 @@ static bool gUseCircuitCallbackCalled = false;
EStartupState LLStartUp::gStartupState = STATE_FIRST;
+// *NOTE:Mani - to reconcile with giab changes...
+static std::string gFirstname;
+static std::string gLastname;
+static std::string gPassword;
+
+static U64 gFirstSimHandle = 0;
+static LLHost gFirstSim;
+static std::string gFirstSimSeedCap;
+static LLVector3 gAgentStartLookAt(1.0f, 0.f, 0.f);
+static std::string gAgentStartLocation = "safe";
+
+boost::scoped_ptr<LLEventPump> LLStartUp::sStateWatcher(new LLEventStream("StartupState"));
+boost::scoped_ptr<LLStartupListener> LLStartUp::sListener(new LLStartupListener());
//
// local function declaration
@@ -240,20 +254,19 @@ void show_first_run_dialog();
bool first_run_dialog_callback(const LLSD& notification, const LLSD& response);
void set_startup_status(const F32 frac, const std::string& string, const std::string& msg);
bool login_alert_status(const LLSD& notification, const LLSD& response);
-void update_app(BOOL mandatory, const std::string& message);
-bool update_dialog_callback(const LLSD& notification, const LLSD& response);
void login_packet_failed(void**, S32 result);
void use_circuit_callback(void**, S32 result);
void register_viewer_callbacks(LLMessageSystem* msg);
-void init_stat_view();
void asset_callback_nothing(LLVFS*, const LLUUID&, LLAssetType::EType, void*, S32);
bool callback_choose_gender(const LLSD& notification, const LLSD& response);
void init_start_screen(S32 location_id);
void release_start_screen();
void reset_login();
void apply_udp_blacklist(const std::string& csv);
+bool process_login_success_response();
+void transition_back_to_login_panel(const std::string& emsg);
-void callback_cache_name(const LLUUID& id, const std::string& firstname, const std::string& lastname, BOOL is_group, void* data)
+void callback_cache_name(const LLUUID& id, const std::string& firstname, const std::string& lastname, BOOL is_group)
{
LLNameListCtrl::refreshAll(id, firstname, lastname, is_group);
LLNameBox::refreshAll(id, firstname, lastname, is_group);
@@ -286,31 +299,14 @@ namespace
};
}
-class LLGestureInventoryFetchObserver : public LLInventoryFetchObserver
-{
-public:
- LLGestureInventoryFetchObserver() {}
- virtual void done()
- {
- // we've downloaded all the items, so repaint the dialog
- LLFloaterGesture::refreshAll();
-
- gInventory.removeObserver(this);
- delete this;
- }
-};
-
void update_texture_fetch()
{
LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread
LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
- gImageList.updateImages(0.10f);
+ gTextureList.updateImages(0.10f);
}
-static std::vector<std::string> sAuthUris;
-static S32 sAuthUriNum = -1;
-
// Returns false to skip other idle processing. Should only return
// true when all initialization done.
bool idle_startup()
@@ -318,8 +314,6 @@ bool idle_startup()
LLMemType mt1(LLMemType::MTYPE_STARTUP);
const F32 PRECACHING_DELAY = gSavedSettings.getF32("PrecachingDelay");
- const F32 TIMEOUT_SECONDS = 5.f;
- const S32 MAX_TIMEOUT_COUNT = 3;
static LLTimer timeout;
static S32 timeout_count = 0;
@@ -329,23 +323,11 @@ bool idle_startup()
// auth/transform loop will do.
static F32 progress = 0.10f;
- static std::string auth_method;
static std::string auth_desc;
static std::string auth_message;
- static std::string firstname;
- static std::string lastname;
- static LLUUID web_login_key;
- static std::string password;
- static std::vector<const char*> requested_options;
-
- static U64 first_sim_handle = 0;
- static LLHost first_sim;
- static std::string first_sim_seed_cap;
static LLVector3 initial_sun_direction(1.f, 0.f, 0.f);
static LLVector3 agent_start_position_region(10.f, 10.f, 10.f); // default for when no space server
- static LLVector3 agent_start_look_at(1.0f, 0.f, 0.f);
- static std::string agent_start_location = "safe";
// last location by default
static S32 agent_location_id = START_LOCATION_ID_LAST;
@@ -353,26 +335,31 @@ bool idle_startup()
static bool show_connect_box = true;
- static bool stipend_since_login = false;
-
- static bool samename = false;
+ //static bool stipend_since_login = false;
// HACK: These are things from the main loop that usually aren't done
// until initialization is complete, but need to be done here for things
// to work.
gIdleCallbacks.callFunctions();
- gViewerWindow->handlePerFrameHover();
+ gViewerWindow->updateUI();
LLMortician::updateClass();
- if (gNoRender)
- {
- // HACK, skip optional updates if you're running drones
- gSkipOptionalUpdate = TRUE;
- }
- else
+ const std::string delims (" ");
+ std::string system;
+ int begIdx, endIdx;
+ std::string osString = LLAppViewer::instance()->getOSInfo().getOSStringSimple();
+
+ begIdx = osString.find_first_not_of (delims);
+ endIdx = osString.find_first_of (delims, begIdx);
+ system = osString.substr (begIdx, endIdx - begIdx);
+ system += "Locale";
+
+ LLStringUtil::setLocale (LLTrans::getString(system));
+
+ if (!gNoRender)
{
- // Update images?
- gImageList.updateImages(0.01f);
+ //note: Removing this line will cause incorrect button size in the login screen. -- bao.
+ gTextureList.updateImages(0.01f) ;
}
if ( STATE_FIRST == LLStartUp::getStartupState() )
@@ -387,16 +374,16 @@ bool idle_startup()
if (LLFeatureManager::getInstance()->isSafe())
{
- LLNotifications::instance().add("DisplaySetToSafe");
+ LLNotificationsUtil::add("DisplaySetToSafe");
}
else if ((gSavedSettings.getS32("LastFeatureVersion") < LLFeatureManager::getInstance()->getVersion()) &&
(gSavedSettings.getS32("LastFeatureVersion") != 0))
{
- LLNotifications::instance().add("DisplaySetToRecommended");
+ LLNotificationsUtil::add("DisplaySetToRecommended");
}
else if (!gViewerWindow->getInitAlert().empty())
{
- LLNotifications::instance().add(gViewerWindow->getInitAlert());
+ LLNotificationsUtil::add(gViewerWindow->getInitAlert());
}
gSavedSettings.setS32("LastFeatureVersion", LLFeatureManager::getInstance()->getVersion());
@@ -431,8 +418,6 @@ bool idle_startup()
// Load autopilot and stats stuff
gAgentPilot.load(gSavedSettings.getString("StatsPilotFile"));
- gFrameStats.setFilename(gSavedSettings.getString("StatsFile"));
- gFrameStats.setSummaryFilename(gSavedSettings.getString("StatsSummaryFile"));
//gErrorStream.setTime(gSavedSettings.getBOOL("LogTimestamps"));
@@ -443,7 +428,7 @@ bool idle_startup()
{
std::string diagnostic = "Could not start address resolution system";
LL_WARNS("AppInit") << diagnostic << LL_ENDL;
- LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().insert("DIAGNOSTIC", diagnostic));
+ LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().with("DIAGNOSTIC", diagnostic));
}
//
@@ -458,13 +443,24 @@ bool idle_startup()
#if LL_WINDOWS
// On the windows dev builds, unpackaged, the message_template.msg
- // file will be located in
- // indra/build-vc**/newview/<config>/app_settings.
+ // file will be located in:
+ // build-vc**/newview/<config>/app_settings
if (!found_template)
{
message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", "message_template.msg");
found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */
}
+ #elif LL_DARWIN
+ // On Mac dev builds, message_template.msg lives in:
+ // indra/build-*/newview/<config>/Second Life/Contents/Resources/app_settings
+ if (!found_template)
+ {
+ message_template_path =
+ gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE,
+ "../Resources/app_settings",
+ "message_template.msg");
+ found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */
+ }
#endif
if (found_template)
@@ -491,9 +487,9 @@ bool idle_startup()
if(!start_messaging_system(
message_template_path,
port,
- LL_VERSION_MAJOR,
- LL_VERSION_MINOR,
- LL_VERSION_PATCH,
+ LLVersionInfo::getMajor(),
+ LLVersionInfo::getMinor(),
+ LLVersionInfo::getPatch(),
FALSE,
std::string(),
responder,
@@ -503,7 +499,7 @@ bool idle_startup()
{
std::string diagnostic = llformat(" Error: %d", gMessageSystem->getErrorCode());
LL_WARNS("AppInit") << diagnostic << LL_ENDL;
- LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().insert("DIAGNOSTIC", diagnostic));
+ LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().with("DIAGNOSTIC", diagnostic));
}
#if LL_WINDOWS
@@ -526,7 +522,7 @@ bool idle_startup()
}
else
{
- LLAppViewer::instance()->earlyExit("MessageTemplateNotFound", LLSD().insert("PATH", message_template_path));
+ LLAppViewer::instance()->earlyExit("MessageTemplateNotFound", LLSD().with("PATH", message_template_path));
}
if(gMessageSystem && gMessageSystem->isOK())
@@ -643,6 +639,16 @@ bool idle_startup()
delete gAudiop;
gAudiop = NULL;
}
+
+ if (gAudiop)
+ {
+ // if the audio engine hasn't set up its own preferred handler for streaming audio then set up the generic streaming audio implementation which uses media plugins
+ if (NULL == gAudiop->getStreamingAudioImpl())
+ {
+ LL_INFOS("AppInit") << "Using media plugins to render streaming audio" << LL_ENDL;
+ gAudiop->setStreamingAudioImpl(new LLStreamingAudio_MediaPlugins());
+ }
+ }
}
}
@@ -663,27 +669,28 @@ bool idle_startup()
}
if (!gLoginHandler.getFirstName().empty()
|| !gLoginHandler.getLastName().empty()
- || !gLoginHandler.getWebLoginKey().isNull() )
+ /*|| !gLoginHandler.getWebLoginKey().isNull()*/ )
{
// We have at least some login information on a SLURL
- firstname = gLoginHandler.getFirstName();
- lastname = gLoginHandler.getLastName();
- web_login_key = gLoginHandler.getWebLoginKey();
+ gFirstname = gLoginHandler.getFirstName();
+ gLastname = gLoginHandler.getLastName();
+ LL_DEBUGS("LLStartup") << "STATE_FIRST: setting gFirstname, gLastname from gLoginHandler: '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL;
// Show the login screen if we don't have everything
show_connect_box =
- firstname.empty() || lastname.empty() || web_login_key.isNull();
+ gFirstname.empty() || gLastname.empty();
}
else if(gSavedSettings.getLLSD("UserLoginInfo").size() == 3)
{
LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo");
- firstname = cmd_line_login[0].asString();
- lastname = cmd_line_login[1].asString();
+ gFirstname = cmd_line_login[0].asString();
+ gLastname = cmd_line_login[1].asString();
+ LL_DEBUGS("LLStartup") << "Setting gFirstname, gLastname from gSavedSettings(\"UserLoginInfo\"): '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL;
LLMD5 pass((unsigned char*)cmd_line_login[2].asString().c_str());
char md5pass[33]; /* Flawfinder: ignore */
pass.hex_digest(md5pass);
- password = md5pass;
+ gPassword = md5pass;
#ifdef USE_VIEWER_AUTH
show_connect_box = true;
@@ -694,9 +701,10 @@ bool idle_startup()
}
else if (gSavedSettings.getBOOL("AutoLogin"))
{
- firstname = gSavedSettings.getString("FirstName");
- lastname = gSavedSettings.getString("LastName");
- password = LLStartUp::loadPasswordFromDisk();
+ gFirstname = gSavedSettings.getString("FirstName");
+ gLastname = gSavedSettings.getString("LastName");
+ LL_DEBUGS("LLStartup") << "AutoLogin: setting gFirstname, gLastname from gSavedSettings(\"First|LastName\"): '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL;
+ gPassword = LLStartUp::loadPasswordFromDisk();
gSavedSettings.setBOOL("RememberPassword", TRUE);
#ifdef USE_VIEWER_AUTH
@@ -709,9 +717,10 @@ bool idle_startup()
{
// if not automatically logging in, display login dialog
// a valid grid is selected
- firstname = gSavedSettings.getString("FirstName");
- lastname = gSavedSettings.getString("LastName");
- password = LLStartUp::loadPasswordFromDisk();
+ gFirstname = gSavedSettings.getString("FirstName");
+ gLastname = gSavedSettings.getString("LastName");
+ LL_DEBUGS("LLStartup") << "normal login: setting gFirstname, gLastname from gSavedSettings(\"First|LastName\"): '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL;
+ gPassword = LLStartUp::loadPasswordFromDisk();
show_connect_box = true;
}
@@ -728,8 +737,7 @@ bool idle_startup()
std::string msg = LLTrans::getString("LoginInitializingBrowser");
set_startup_status(0.03f, msg.c_str(), gAgent.mMOTD.c_str());
display_startup();
- LLViewerMedia::initBrowser();
-
+ // LLViewerMedia::initBrowser();
LLStartUp::setStartupState( STATE_LOGIN_SHOW );
return FALSE;
}
@@ -748,7 +756,7 @@ bool idle_startup()
// Load all the name information out of the login view
// NOTE: Hits "Attempted getFields with no login view shown" warning, since we don't
// show the login view until login_show() is called below.
- // LLPanelLogin::getFields(firstname, lastname, password);
+ // LLPanelLogin::getFields(gFirstname, gLastname, gPassword);
if (gNoRender)
{
@@ -760,7 +768,7 @@ bool idle_startup()
// Show the login dialog
login_show();
// connect dialog is already shown, so fill in the names
- LLPanelLogin::setFields( firstname, lastname, password);
+ LLPanelLogin::setFields( gFirstname, gLastname, gPassword);
LLPanelLogin::giveFocus();
@@ -780,15 +788,11 @@ bool idle_startup()
// *NOTE: This is where gMuteList used to get allocated before becoming LLMuteList::getInstance().
- // Initialize UI
- if (!gNoRender)
+ // Login screen needs menus for preferences, but we can enter
+ // this startup phase more than once.
+ if (gLoginMenuBarView == NULL)
{
- // Initialize all our tools. Must be done after saved settings loaded.
- // NOTE: This also is where gToolMgr used to be instantiated before being turned into a singleton.
- LLToolMgr::getInstance()->initTools();
-
- // Quickly get something onscreen to look at.
- gViewerWindow->initWorldUI();
+ init_menus();
}
gViewerWindow->setNormalControlsVisible( FALSE );
@@ -799,6 +803,9 @@ bool idle_startup()
gViewerWindow->getWindow()->show();
display_startup();
+ //DEV-10530. do cleanup. remove at some later date. jan-2009
+ LLFloaterPreference::cleanupBadSetting();
+
// DEV-16927. The following code removes errant keystrokes that happen while the window is being
// first made visible.
#ifdef _WIN32
@@ -821,46 +828,53 @@ bool idle_startup()
if (STATE_LOGIN_CLEANUP == LLStartUp::getStartupState())
{
+ // Move the progress view in front of the UI immediately when login is performed
+ // this allows not to see main menu after Alt+Tab was pressed while login. EXT-744.
+ gViewerWindow->moveProgressViewToFront();
+
//reset the values that could have come in from a slurl
- if (!gLoginHandler.getWebLoginKey().isNull())
+ // DEV-42215: Make sure they're not empty -- gFirstname and gLastname
+ // might already have been set from gSavedSettings, and it's too bad
+ // to overwrite valid values with empty strings.
+ if (! gLoginHandler.getFirstName().empty() && ! gLoginHandler.getLastName().empty())
{
- firstname = gLoginHandler.getFirstName();
- lastname = gLoginHandler.getLastName();
- web_login_key = gLoginHandler.getWebLoginKey();
+ gFirstname = gLoginHandler.getFirstName();
+ gLastname = gLoginHandler.getLastName();
+ LL_DEBUGS("LLStartup") << "STATE_LOGIN_CLEANUP: setting gFirstname, gLastname from gLoginHandler: '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL;
}
-
+
if (show_connect_box)
{
// TODO if not use viewer auth
// Load all the name information out of the login view
- LLPanelLogin::getFields(&firstname, &lastname, &password);
+ LLPanelLogin::getFields(&gFirstname, &gLastname, &gPassword);
// end TODO
// HACK: Try to make not jump on login
gKeyboard->resetKeys();
}
- if (!firstname.empty() && !lastname.empty())
+ if (!gFirstname.empty() && !gLastname.empty())
{
- gSavedSettings.setString("FirstName", firstname);
- gSavedSettings.setString("LastName", lastname);
+ gSavedSettings.setString("FirstName", gFirstname);
+ gSavedSettings.setString("LastName", gLastname);
- LL_INFOS("AppInit") << "Attempting login as: " << firstname << " " << lastname << LL_ENDL;
- gDebugInfo["LoginName"] = firstname + " " + lastname;
+ LL_INFOS("AppInit") << "Attempting login as: " << gFirstname << " " << gLastname << LL_ENDL;
+ gDebugInfo["LoginName"] = gFirstname + " " + gLastname;
}
// create necessary directories
// *FIX: these mkdir's should error check
- gDirUtilp->setLindenUserDir(firstname, lastname);
- LLFile::mkdir(gDirUtilp->getLindenUserDir());
-
- // Set PerAccountSettingsFile to the default value.
+ gDirUtilp->setLindenUserDir(gFirstname, gLastname);
+ LLFile::mkdir(gDirUtilp->getLindenUserDir());
+
+ // Set PerAccountSettingsFile to the default value.
gSavedSettings.setString("PerAccountSettingsFile",
gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT,
- LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount")
- )
- );
+ LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount")));
+ // Note: can't store warnings files per account because some come up before login
+
// Overwrite default user settings with user settings
LLAppViewer::instance()->loadSettingsFromDirectory("Account");
@@ -872,17 +886,20 @@ bool idle_startup()
}
//Default the path if one isn't set.
- if (gSavedPerAccountSettings.getString("InstantMessageLogPath").empty())
+ if (gSavedPerAccountSettings.getString("InstantMessageLogFolder").empty())
{
gDirUtilp->setChatLogsDir(gDirUtilp->getOSUserAppDir());
- gSavedPerAccountSettings.setString("InstantMessageLogPath",gDirUtilp->getChatLogsDir());
+ std::string chat_log_dir = gDirUtilp->getChatLogsDir();
+ std::string chat_log_top_folder=gDirUtilp->getBaseFileName(chat_log_dir);
+ gSavedPerAccountSettings.setString("InstantMessageLogPath",chat_log_dir);
+ gSavedPerAccountSettings.setString("InstantMessageLogFolder",chat_log_top_folder);
}
else
{
gDirUtilp->setChatLogsDir(gSavedPerAccountSettings.getString("InstantMessageLogPath"));
}
- gDirUtilp->setPerAccountChatLogsDir(firstname, lastname);
+ gDirUtilp->setPerAccountChatLogsDir(gFirstname, gLastname);
LLFile::mkdir(gDirUtilp->getChatLogsDir());
LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir());
@@ -903,27 +920,22 @@ bool idle_startup()
if (show_connect_box)
{
- if ( LLPanelLogin::isGridComboDirty() )
- {
- // User picked a grid from the popup, so clear the
- // stored uris and they will be reacquired from the grid choice.
- sAuthUris.clear();
- }
-
std::string location;
LLPanelLogin::getLocation( location );
LLURLSimString::setString( location );
// END TODO
- LLPanelLogin::close();
+ LLPanelLogin::closePanel();
}
- //For HTML parsing in text boxes.
- LLTextEditor::setLinkColor( gSavedSettings.getColor4("HTMLLinkColor") );
-
// Load URL History File
LLURLHistory::loadFile("url_history.xml");
+ // Load location history
+ LLLocationHistory::getInstance()->load();
+
+ // Load Avatars icons cache
+ LLAvatarIconIDCache::getInstance()->load();
//-------------------------------------------------
// Handle startup progress screen
@@ -939,11 +951,11 @@ bool idle_startup()
agent_location_id = START_LOCATION_ID_URL;
// doesn't really matter what location_which is, since
- // agent_start_look_at will be overwritten when the
+ // gAgentStartLookAt will be overwritten when the
// UserLoginLocationReply arrives
location_which = START_LOCATION_ID_LAST;
}
- else if (gSavedSettings.getBOOL("LoginLastLocation"))
+ else if (gSavedSettings.getString("LoginLocation") == "last" )
{
agent_location_id = START_LOCATION_ID_LAST; // last location
location_which = START_LOCATION_ID_LAST;
@@ -963,7 +975,7 @@ bool idle_startup()
// Display the startup progress bar.
gViewerWindow->setShowProgress(TRUE);
- gViewerWindow->setProgressCancelButtonVisible(TRUE, std::string("Quit")); // *TODO: Translate
+ gViewerWindow->setProgressCancelButtonVisible(TRUE, LLTrans::getString("Quit"));
// Poke the VFS, which could potentially block for a while if
// Windows XP is acting up
@@ -972,614 +984,139 @@ bool idle_startup()
gVFS->pokeFiles();
- // color init must be after saved settings loaded
- init_colors();
-
- // skipping over STATE_UPDATE_CHECK because that just waits for input
LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT );
return FALSE;
}
- if (STATE_UPDATE_CHECK == LLStartUp::getStartupState())
- {
- // wait for user to give input via dialog box
- return FALSE;
- }
-
if(STATE_LOGIN_AUTH_INIT == LLStartUp::getStartupState())
{
-//#define LL_MINIMIAL_REQUESTED_OPTIONS
gDebugInfo["GridName"] = LLViewerLogin::getInstance()->getGridLabel();
- // *Note: this is where gUserAuth used to be created.
- requested_options.clear();
- requested_options.push_back("inventory-root");
- requested_options.push_back("inventory-skeleton");
- //requested_options.push_back("inventory-meat");
- //requested_options.push_back("inventory-skel-targets");
-#if (!defined LL_MINIMIAL_REQUESTED_OPTIONS)
- if(FALSE == gSavedSettings.getBOOL("NoInventoryLibrary"))
- {
- requested_options.push_back("inventory-lib-root");
- requested_options.push_back("inventory-lib-owner");
- requested_options.push_back("inventory-skel-lib");
- // requested_options.push_back("inventory-meat-lib");
- }
-
- requested_options.push_back("initial-outfit");
- requested_options.push_back("gestures");
- requested_options.push_back("event_categories");
- requested_options.push_back("event_notifications");
- requested_options.push_back("classified_categories");
- //requested_options.push_back("inventory-targets");
- requested_options.push_back("buddy-list");
- requested_options.push_back("ui-config");
-#endif
- requested_options.push_back("tutorial_setting");
- requested_options.push_back("login-flags");
- requested_options.push_back("global-textures");
- if(gSavedSettings.getBOOL("ConnectAsGod"))
- {
- gSavedSettings.setBOOL("UseDebugMenus", TRUE);
- requested_options.push_back("god-connect");
- }
- std::vector<std::string> uris;
- LLViewerLogin::getInstance()->getLoginURIs(uris);
- std::vector<std::string>::const_iterator iter, end;
- for (iter = uris.begin(), end = uris.end(); iter != end; ++iter)
- {
- std::vector<std::string> rewritten;
- rewritten = LLSRV::rewriteURI(*iter);
- sAuthUris.insert(sAuthUris.end(),
- rewritten.begin(), rewritten.end());
- }
- sAuthUriNum = 0;
- auth_method = "login_to_simulator";
-
- LLStringUtil::format_map_t args;
- args["[APP_NAME]"] = LLAppViewer::instance()->getSecondLifeTitle();
- auth_desc = LLTrans::getString("LoginInProgress", args);
- LLStartUp::setStartupState( STATE_LOGIN_AUTHENTICATE );
- }
-
- if (STATE_LOGIN_AUTHENTICATE == LLStartUp::getStartupState())
- {
- LL_DEBUGS("AppInit") << "STATE_LOGIN_AUTHENTICATE" << LL_ENDL;
+ // Update progress status and the display loop.
+ auth_desc = LLTrans::getString("LoginInProgress");
set_startup_status(progress, auth_desc, auth_message);
progress += 0.02f;
display_startup();
-
- std::stringstream start;
- if (LLURLSimString::parse())
- {
- // a startup URL was specified
- std::stringstream unescaped_start;
- unescaped_start << "uri:"
- << LLURLSimString::sInstance.mSimName << "&"
- << LLURLSimString::sInstance.mX << "&"
- << LLURLSimString::sInstance.mY << "&"
- << LLURLSimString::sInstance.mZ;
- start << xml_escape_string(unescaped_start.str());
-
- }
- else if (gSavedSettings.getBOOL("LoginLastLocation"))
+
+ // Setting initial values...
+ LLLoginInstance* login = LLLoginInstance::getInstance();
+ login->setNotificationsInterface(LLNotifications::getInstance());
+ if(gNoRender)
{
- start << "last";
+ // HACK, skip optional updates if you're running drones
+ login->setSkipOptionalUpdate(true);
}
- else
- {
- start << "home";
- }
-
- char hashed_mac_string[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
- LLMD5 hashed_mac;
- hashed_mac.update( gMACAddress, MAC_ADDRESS_BYTES );
- hashed_mac.finalize();
- hashed_mac.hex_digest(hashed_mac_string);
-
- // TODO if statement here to use web_login_key
- sAuthUriNum = llclamp(sAuthUriNum, 0, (S32)sAuthUris.size()-1);
- LLUserAuth::getInstance()->authenticate(
- sAuthUris[sAuthUriNum],
- auth_method,
- firstname,
- lastname,
- password, // web_login_key,
- start.str(),
- gSkipOptionalUpdate,
- gAcceptTOS,
- gAcceptCriticalMessage,
- gLastExecEvent,
- requested_options,
- hashed_mac_string,
- LLAppViewer::instance()->getSerialNumber());
-
- // reset globals
- gAcceptTOS = FALSE;
- gAcceptCriticalMessage = FALSE;
- LLStartUp::setStartupState( STATE_LOGIN_NO_DATA_YET );
+
+ login->setUserInteraction(show_connect_box);
+ login->setSerialNumber(LLAppViewer::instance()->getSerialNumber());
+ login->setLastExecEvent(gLastExecEvent);
+ login->setUpdaterLauncher(boost::bind(&LLAppViewer::launchUpdater, LLAppViewer::instance()));
+
+ // This call to LLLoginInstance::connect() starts the
+ // authentication process.
+ LLSD credentials;
+ credentials["first"] = gFirstname;
+ credentials["last"] = gLastname;
+ credentials["passwd"] = gPassword;
+ login->connect(credentials);
+
+ LLStartUp::setStartupState( STATE_LOGIN_CURL_UNSTUCK );
return FALSE;
}
- if(STATE_LOGIN_NO_DATA_YET == LLStartUp::getStartupState())
+ if(STATE_LOGIN_CURL_UNSTUCK == LLStartUp::getStartupState())
{
- LL_DEBUGS("AppInit") << "STATE_LOGIN_NO_DATA_YET" << LL_ENDL;
// If we get here we have gotten past the potential stall
// in curl, so take "may appear frozen" out of progress bar. JC
- auth_desc = "Logging in...";
- set_startup_status(progress, auth_desc, auth_message);
- // Process messages to keep from dropping circuit.
- LLMessageSystem* msg = gMessageSystem;
- while (msg->checkAllMessages(gFrameCount, gServicePump))
- {
- }
- msg->processAcks();
- LLUserAuth::UserAuthcode error = LLUserAuth::getInstance()->authResponse();
- if(LLUserAuth::E_NO_RESPONSE_YET == error)
- {
- LL_DEBUGS("AppInit") << "waiting..." << LL_ENDL;
- return FALSE;
- }
- LLStartUp::setStartupState( STATE_LOGIN_DOWNLOADING );
- progress += 0.01f;
+ auth_desc = LLTrans::getString("LoginInProgressNoFrozen");
set_startup_status(progress, auth_desc, auth_message);
- return FALSE;
- }
- if(STATE_LOGIN_DOWNLOADING == LLStartUp::getStartupState())
- {
- LL_DEBUGS("AppInit") << "STATE_LOGIN_DOWNLOADING" << LL_ENDL;
- // Process messages to keep from dropping circuit.
- LLMessageSystem* msg = gMessageSystem;
- while (msg->checkAllMessages(gFrameCount, gServicePump))
- {
- }
- msg->processAcks();
- LLUserAuth::UserAuthcode error = LLUserAuth::getInstance()->authResponse();
- if(LLUserAuth::E_DOWNLOADING == error)
- {
- LL_DEBUGS("AppInit") << "downloading..." << LL_ENDL;
- return FALSE;
- }
LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE );
- progress += 0.01f;
- set_startup_status(progress, LLTrans::getString("LoginProcessingResponse"), auth_message);
return FALSE;
}
- if(STATE_LOGIN_PROCESS_RESPONSE == LLStartUp::getStartupState())
+ if(STATE_LOGIN_PROCESS_RESPONSE == LLStartUp::getStartupState())
{
- LL_DEBUGS("AppInit") << "STATE_LOGIN_PROCESS_RESPONSE" << LL_ENDL;
std::ostringstream emsg;
- bool quit = false;
- bool update = false;
- std::string login_response;
- std::string reason_response;
- std::string message_response;
- bool successful_login = false;
- LLUserAuth::UserAuthcode error = LLUserAuth::getInstance()->authResponse();
- // reset globals
- gAcceptTOS = FALSE;
- gAcceptCriticalMessage = FALSE;
- switch(error)
- {
- case LLUserAuth::E_OK:
- login_response = LLUserAuth::getInstance()->getResponse("login");
- if(login_response == "true")
- {
- // Yay, login!
- successful_login = true;
- }
- else if(login_response == "indeterminate")
+ emsg << "Login failed.\n";
+ if(LLLoginInstance::getInstance()->authFailure())
+ {
+ LL_INFOS("LLStartup") << "Login failed, LLLoginInstance::getResponse(): "
+ << LLLoginInstance::getInstance()->getResponse() << LL_ENDL;
+ // Still have error conditions that may need some
+ // sort of handling.
+ std::string reason_response = LLLoginInstance::getInstance()->getResponse("reason");
+ std::string message_response = LLLoginInstance::getInstance()->getResponse("message");
+
+ if(!message_response.empty())
{
- LL_INFOS("AppInit") << "Indeterminate login..." << LL_ENDL;
- sAuthUris = LLSRV::rewriteURI(LLUserAuth::getInstance()->getResponse("next_url"));
- sAuthUriNum = 0;
- auth_method = LLUserAuth::getInstance()->getResponse("next_method");
- auth_message = LLUserAuth::getInstance()->getResponse("message");
- if(auth_method.substr(0, 5) == "login")
+ // XUI: fix translation for strings returned during login
+ // We need a generic table for translations
+ std::string big_reason = LLAgent::sTeleportErrorMessages[ message_response ];
+ if ( big_reason.size() == 0 )
{
- auth_desc.assign(LLTrans::getString("LoginAuthenticating"));
+ emsg << message_response;
}
else
{
- auth_desc.assign(LLTrans::getString("LoginMaintenance"));
+ emsg << big_reason;
}
- // ignoring the duration & options array for now.
- // Go back to authenticate.
- LLStartUp::setStartupState( STATE_LOGIN_AUTHENTICATE );
- return FALSE;
- }
- else
- {
- emsg << "Login failed.\n";
- reason_response = LLUserAuth::getInstance()->getResponse("reason");
- message_response = LLUserAuth::getInstance()->getResponse("message");
-
- if (!message_response.empty())
- {
- // XUI: fix translation for strings returned during login
- // We need a generic table for translations
- std::string big_reason = LLAgent::sTeleportErrorMessages[ message_response ];
- if ( big_reason.size() == 0 )
- {
- emsg << message_response;
- }
- else
- {
- emsg << big_reason;
- }
- }
-
- if(reason_response == "tos")
- {
- if (show_connect_box)
- {
- LL_DEBUGS("AppInit") << "Need tos agreement" << LL_ENDL;
- LLStartUp::setStartupState( STATE_UPDATE_CHECK );
- LLFloaterTOS* tos_dialog = LLFloaterTOS::show(LLFloaterTOS::TOS_TOS,
- message_response);
- tos_dialog->startModal();
- // LLFloaterTOS deletes itself.
- return false;
- }
- else
- {
- quit = true;
- }
- }
- if(reason_response == "critical")
- {
- if (show_connect_box)
- {
- LL_DEBUGS("AppInit") << "Need critical message" << LL_ENDL;
- LLStartUp::setStartupState( STATE_UPDATE_CHECK );
- LLFloaterTOS* tos_dialog = LLFloaterTOS::show(LLFloaterTOS::TOS_CRITICAL_MESSAGE,
- message_response);
- tos_dialog->startModal();
- // LLFloaterTOS deletes itself.
- return false;
- }
- else
- {
- quit = true;
- }
- }
- if(reason_response == "key")
- {
- // Couldn't login because user/password is wrong
- // Clear the password
- password = "";
- }
- if(reason_response == "update")
- {
- auth_message = LLUserAuth::getInstance()->getResponse("message");
- update = true;
- }
- if(reason_response == "optional")
- {
- LL_DEBUGS("AppInit") << "Login got optional update" << LL_ENDL;
- auth_message = LLUserAuth::getInstance()->getResponse("message");
- if (show_connect_box)
- {
- update_app(FALSE, auth_message);
- LLStartUp::setStartupState( STATE_UPDATE_CHECK );
- gSkipOptionalUpdate = TRUE;
- return false;
- }
- }
- }
- break;
- case LLUserAuth::E_COULDNT_RESOLVE_HOST:
- case LLUserAuth::E_SSL_PEER_CERTIFICATE:
- case LLUserAuth::E_UNHANDLED_ERROR:
- case LLUserAuth::E_SSL_CACERT:
- case LLUserAuth::E_SSL_CONNECT_ERROR:
- default:
- if (sAuthUriNum >= (int) sAuthUris.size() - 1)
- {
- emsg << "Unable to connect to " << LLAppViewer::instance()->getSecondLifeTitle() << ".\n";
- emsg << LLUserAuth::getInstance()->errorMessage();
- } else {
- sAuthUriNum++;
- std::ostringstream s;
- LLStringUtil::format_map_t args;
- args["[NUMBER]"] = llformat("%d", sAuthUriNum + 1);
- auth_desc = LLTrans::getString("LoginAttempt", args);
- LLStartUp::setStartupState( STATE_LOGIN_AUTHENTICATE );
- return FALSE;
- }
- break;
- }
-
- if (update || gSavedSettings.getBOOL("ForceMandatoryUpdate"))
- {
- gSavedSettings.setBOOL("ForceMandatoryUpdate", FALSE);
- update_app(TRUE, auth_message);
- LLStartUp::setStartupState( STATE_UPDATE_CHECK );
- return false;
- }
-
- // Version update and we're not showing the dialog
- if(quit)
- {
- LLUserAuth::getInstance()->reset();
- LLAppViewer::instance()->forceQuit();
- return false;
- }
-
- if(successful_login)
- {
- std::string text;
- text = LLUserAuth::getInstance()->getResponse("udp_blacklist");
- if(!text.empty())
- {
- apply_udp_blacklist(text);
}
- // unpack login data needed by the application
- text = LLUserAuth::getInstance()->getResponse("agent_id");
- if(!text.empty()) gAgentID.set(text);
- gDebugInfo["AgentID"] = text;
-
- text = LLUserAuth::getInstance()->getResponse("session_id");
- if(!text.empty()) gAgentSessionID.set(text);
- gDebugInfo["SessionID"] = text;
-
- text = LLUserAuth::getInstance()->getResponse("secure_session_id");
- if(!text.empty()) gAgent.mSecureSessionID.set(text);
-
- text = LLUserAuth::getInstance()->getResponse("first_name");
- if(!text.empty())
+ if(reason_response == "key")
{
- // Remove quotes from string. Login.cgi sends these to force
- // names that look like numbers into strings.
- firstname.assign(text);
- LLStringUtil::replaceChar(firstname, '"', ' ');
- LLStringUtil::trim(firstname);
+ // Couldn't login because user/password is wrong
+ // Clear the password
+ gPassword = "";
}
- text = LLUserAuth::getInstance()->getResponse("last_name");
- if(!text.empty()) lastname.assign(text);
- gSavedSettings.setString("FirstName", firstname);
- gSavedSettings.setString("LastName", lastname);
- if (gSavedSettings.getBOOL("RememberPassword"))
+ if(reason_response == "update"
+ || reason_response == "optional")
{
- // Successful login means the password is valid, so save it.
- LLStartUp::savePasswordToDisk(password);
+ // In the case of a needed update, quit.
+ // Its either downloading or declined.
+ // If optional was skipped this case shouldn't
+ // be reached.
+ LLLoginInstance::getInstance()->disconnect();
+ LLAppViewer::instance()->forceQuit();
}
else
{
- // Don't leave password from previous session sitting around
- // during this login session.
- LLStartUp::deletePasswordFromDisk();
- }
-
- // this is their actual ability to access content
- text = LLUserAuth::getInstance()->getResponse("agent_access_max");
- if (!text.empty())
- {
- // agent_access can be 'A', 'M', and 'PG'.
- gAgent.setMaturity(text[0]);
- }
-
- // this is the value of their preference setting for that content
- // which will always be <= agent_access_max
- text = LLUserAuth::getInstance()->getResponse("agent_region_access");
- if (!text.empty())
- {
- int preferredMaturity = LLAgent::convertTextToMaturity(text[0]);
- gSavedSettings.setU32("PreferredMaturity", preferredMaturity);
- }
- // During the AO transition, this flag will be true. Then the flag will
- // go away. After the AO transition, this code and all the code that
- // uses it can be deleted.
- text = LLUserAuth::getInstance()->getResponse("ao_transition");
- if (!text.empty())
- {
- if (text == "1")
- {
- gAgent.setAOTransition();
- }
- }
-
- text = LLUserAuth::getInstance()->getResponse("start_location");
- if(!text.empty()) agent_start_location.assign(text);
- text = LLUserAuth::getInstance()->getResponse("circuit_code");
- if(!text.empty())
- {
- gMessageSystem->mOurCircuitCode = strtoul(text.c_str(), NULL, 10);
- }
- std::string sim_ip_str = LLUserAuth::getInstance()->getResponse("sim_ip");
- std::string sim_port_str = LLUserAuth::getInstance()->getResponse("sim_port");
- if(!sim_ip_str.empty() && !sim_port_str.empty())
- {
- U32 sim_port = strtoul(sim_port_str.c_str(), NULL, 10);
- first_sim.set(sim_ip_str, sim_port);
- if (first_sim.isOk())
- {
- gMessageSystem->enableCircuit(first_sim, TRUE);
- }
- }
- std::string region_x_str = LLUserAuth::getInstance()->getResponse("region_x");
- std::string region_y_str = LLUserAuth::getInstance()->getResponse("region_y");
- if(!region_x_str.empty() && !region_y_str.empty())
- {
- U32 region_x = strtoul(region_x_str.c_str(), NULL, 10);
- U32 region_y = strtoul(region_y_str.c_str(), NULL, 10);
- first_sim_handle = to_region_handle(region_x, region_y);
- }
-
- const std::string look_at_str = LLUserAuth::getInstance()->getResponse("look_at");
- if (!look_at_str.empty())
- {
- size_t len = look_at_str.size();
- LLMemoryStream mstr((U8*)look_at_str.c_str(), len);
- LLSD sd = LLSDSerialize::fromNotation(mstr, len);
- agent_start_look_at = ll_vector3_from_sd(sd);
- }
-
- text = LLUserAuth::getInstance()->getResponse("seed_capability");
- if (!text.empty()) first_sim_seed_cap = text;
-
- text = LLUserAuth::getInstance()->getResponse("seconds_since_epoch");
- if(!text.empty())
- {
- U32 server_utc_time = strtoul(text.c_str(), NULL, 10);
- if(server_utc_time)
- {
- time_t now = time(NULL);
- gUTCOffset = (server_utc_time - now);
- }
- }
-
- std::string home_location = LLUserAuth::getInstance()->getResponse("home");
- if(!home_location.empty())
- {
- size_t len = home_location.size();
- LLMemoryStream mstr((U8*)home_location.c_str(), len);
- LLSD sd = LLSDSerialize::fromNotation(mstr, len);
- S32 region_x = sd["region_handle"][0].asInteger();
- S32 region_y = sd["region_handle"][1].asInteger();
- U64 region_handle = to_region_handle(region_x, region_y);
- LLVector3 position = ll_vector3_from_sd(sd["position"]);
- gAgent.setHomePosRegion(region_handle, position);
- }
-
- gAgent.mMOTD.assign(LLUserAuth::getInstance()->getResponse("message"));
- LLUserAuth::options_t options;
- if(LLUserAuth::getInstance()->getOptions("inventory-root", options))
- {
- LLUserAuth::response_t::iterator it;
- it = options[0].find("folder_id");
- if(it != options[0].end())
- {
- gAgent.mInventoryRootID.set((*it).second);
- //gInventory.mock(gAgent.getInventoryRootID());
- }
- }
-
- options.clear();
- if(LLUserAuth::getInstance()->getOptions("login-flags", options))
- {
- LLUserAuth::response_t::iterator it;
- LLUserAuth::response_t::iterator no_flag = options[0].end();
- it = options[0].find("ever_logged_in");
- if(it != no_flag)
- {
- if((*it).second == "N") gAgent.setFirstLogin(TRUE);
- else gAgent.setFirstLogin(FALSE);
- }
- it = options[0].find("stipend_since_login");
- if(it != no_flag)
- {
- if((*it).second == "Y") stipend_since_login = true;
- }
- it = options[0].find("gendered");
- if(it != no_flag)
- {
- if((*it).second == "Y") gAgent.setGenderChosen(TRUE);
- }
- it = options[0].find("daylight_savings");
- if(it != no_flag)
- {
- if((*it).second == "Y") gPacificDaylightTime = TRUE;
- else gPacificDaylightTime = FALSE;
- }
- }
- options.clear();
- if (LLUserAuth::getInstance()->getOptions("initial-outfit", options)
- && !options.empty())
- {
- LLUserAuth::response_t::iterator it;
- LLUserAuth::response_t::iterator it_end = options[0].end();
- it = options[0].find("folder_name");
- if(it != it_end)
- {
- // Initial outfit is a folder in your inventory,
- // must be an exact folder-name match.
- sInitialOutfit = (*it).second;
- }
- it = options[0].find("gender");
- if (it != it_end)
+ // Don't pop up a notification in the TOS case because
+ // LLFloaterTOS::onCancel() already scolded the user.
+ if (reason_response != "tos")
{
- sInitialOutfitGender = (*it).second;
+ LLSD args;
+ args["ERROR_MESSAGE"] = emsg.str();
+ LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL;
+ LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done);
}
- }
- options.clear();
- if(LLUserAuth::getInstance()->getOptions("global-textures", options))
- {
- // Extract sun and moon texture IDs. These are used
- // in the LLVOSky constructor, but I can't figure out
- // how to pass them in. JC
- LLUserAuth::response_t::iterator it;
- LLUserAuth::response_t::iterator no_texture = options[0].end();
- it = options[0].find("sun_texture_id");
- if(it != no_texture)
- {
- gSunTextureID.set((*it).second);
- }
- it = options[0].find("moon_texture_id");
- if(it != no_texture)
- {
- gMoonTextureID.set((*it).second);
- }
- it = options[0].find("cloud_texture_id");
- if(it != no_texture)
- {
- gCloudTextureID.set((*it).second);
- }
+ //setup map of datetime strings to codes and slt & local time offset from utc
+ // *TODO: Does this need to be here?
+ LLStringOps::setupDatetimeInfo (false);
+ transition_back_to_login_panel(emsg.str());
+ show_connect_box = true;
}
-
-
- // JC: gesture loading done below, when we have an asset system
- // in place. Don't delete/clear user_credentials until then.
-
- if(gAgentID.notNull()
- && gAgentSessionID.notNull()
- && gMessageSystem->mOurCircuitCode
- && first_sim.isOk()
- && gAgent.mInventoryRootID.notNull())
+ }
+ else if(LLLoginInstance::getInstance()->authSuccess())
+ {
+ if(process_login_success_response())
{
- LLStartUp::setStartupState( STATE_WORLD_INIT );
+ // Pass the user information to the voice chat server interface.
+ gVoiceClient->userAuthorized(gFirstname, gLastname, gAgentID);
+ LLStartUp::setStartupState( STATE_WORLD_INIT);
}
else
{
- if (gNoRender)
- {
- LL_WARNS("AppInit") << "Bad login - missing return values" << LL_ENDL;
- LL_WARNS("AppInit") << emsg << LL_ENDL;
- exit(0);
- }
- // Bounce back to the login screen.
LLSD args;
args["ERROR_MESSAGE"] = emsg.str();
- LLNotifications::instance().add("ErrorMessage", args, LLSD(), login_alert_done);
- reset_login();
- gSavedSettings.setBOOL("AutoLogin", FALSE);
+ LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL;
+ LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done);
+ transition_back_to_login_panel(emsg.str());
show_connect_box = true;
}
-
- // Pass the user information to the voice chat server interface.
- gVoiceClient->userAuthorized(firstname, lastname, gAgentID);
- }
- else // if(successful_login)
- {
- if (gNoRender)
- {
- LL_WARNS("AppInit") << "Failed to login!" << LL_ENDL;
- LL_WARNS("AppInit") << emsg << LL_ENDL;
- exit(0);
- }
- // Bounce back to the login screen.
- LLSD args;
- args["ERROR_MESSAGE"] = emsg.str();
- LLNotifications::instance().add("ErrorMessage", args, LLSD(), login_alert_done);
- reset_login();
- gSavedSettings.setBOOL("AutoLogin", FALSE);
- show_connect_box = true;
}
return FALSE;
}
@@ -1589,7 +1126,7 @@ bool idle_startup()
//---------------------------------------------------------------------
if (STATE_WORLD_INIT == LLStartUp::getStartupState())
{
- set_startup_status(0.40f, LLTrans::getString("LoginInitializingWorld"), gAgent.mMOTD);
+ set_startup_status(0.30f, LLTrans::getString("LoginInitializingWorld"), gAgent.mMOTD);
display_startup();
// We should have an agent id by this point.
llassert(!(gAgentID == LLUUID::null));
@@ -1601,11 +1138,12 @@ bool idle_startup()
// Since we connected, save off the settings so the user doesn't have to
// type the name/password again if we crash.
gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
+ LLUIColorTable::instance().saveUserSettings();
//
// Initialize classes w/graphics stuff.
//
- gImageList.doPrefetchImages();
+ gTextureList.doPrefetchImages();
LLSurface::initClasses();
LLFace::initClass();
@@ -1617,9 +1155,16 @@ bool idle_startup()
LLWLParamManager::initClass();
LLWaterParamManager::initClass();
- // RN: don't initialize VO classes in drone mode, they are too closely tied to rendering
LLViewerObject::initVOClasses();
+ // Initialize all our tools. Must be done after saved settings loaded.
+ // NOTE: This also is where gToolMgr used to be instantiated before being turned into a singleton.
+ LLToolMgr::getInstance()->initTools();
+
+ // Pre-load floaters, like the world map, that are slow to spawn
+ // due to XML complexity.
+ gViewerWindow->initWorldUI();
+
display_startup();
// This is where we used to initialize gWorldp. Original comment said:
@@ -1632,14 +1177,14 @@ bool idle_startup()
// This is necessary because creating objects before this is set will result in a
// bad mPositionAgent cache.
- gAgent.initOriginGlobal(from_region_handle(first_sim_handle));
+ gAgent.initOriginGlobal(from_region_handle(gFirstSimHandle));
- LLWorld::getInstance()->addRegion(first_sim_handle, first_sim);
+ LLWorld::getInstance()->addRegion(gFirstSimHandle, gFirstSim);
- LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(first_sim_handle);
+ LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(gFirstSimHandle);
LL_INFOS("AppInit") << "Adding initial simulator " << regionp->getOriginGlobal() << LL_ENDL;
- regionp->setSeedCapability(first_sim_seed_cap);
+ regionp->setSeedCapability(gFirstSimSeedCap);
LL_DEBUGS("AppInit") << "Waiting for seed grant ...." << LL_ENDL;
// Set agent's initial region to be the one we just created.
@@ -1662,6 +1207,14 @@ bool idle_startup()
if (STATE_MULTIMEDIA_INIT == LLStartUp::getStartupState())
{
LLStartUp::multimediaInit();
+ LLStartUp::setStartupState( STATE_FONT_INIT );
+ return FALSE;
+ }
+
+ // Loading fonts takes several seconds
+ if (STATE_FONT_INIT == LLStartUp::getStartupState())
+ {
+ LLStartUp::fontInit();
LLStartUp::setStartupState( STATE_SEED_GRANTED_WAIT );
return FALSE;
}
@@ -1690,45 +1243,16 @@ bool idle_startup()
gLoginMenuBarView->setVisible( FALSE );
gLoginMenuBarView->setEnabled( FALSE );
- LLRect window(0, gViewerWindow->getWindowHeight(), gViewerWindow->getWindowWidth(), 0);
- gViewerWindow->adjustControlRectanglesForFirstUse(window);
-
- if(gSavedSettings.getBOOL("ShowMiniMap"))
- {
- LLFloaterMap::showInstance();
- }
-
- if (gSavedSettings.getBOOL("ShowCameraControls"))
- {
- LLFloaterCamera::showInstance();
- }
- if (gSavedSettings.getBOOL("ShowMovementControls"))
- {
- LLFloaterMove::showInstance();
- }
-
- if (gSavedSettings.getBOOL("ShowActiveSpeakers"))
- {
- LLFloaterActiveSpeakers::showInstance();
- }
-
- if (gSavedSettings.getBOOL("BeaconAlwaysOn"))
- {
- LLFloaterBeacons::showInstance();
- }
-
if (!gNoRender)
{
// Move the progress view in front of the UI
gViewerWindow->moveProgressViewToFront();
+ // direct logging to the debug console's line buffer
LLError::logToFixedBuffer(gDebugView->mDebugConsolep);
+
// set initial visibility of debug console
gDebugView->mDebugConsolep->setVisible(gSavedSettings.getBOOL("ShowDebugConsole"));
- if (gSavedSettings.getBOOL("ShowDebugStats"))
- {
- LLFloaterStats::showInstance();
- }
}
//
@@ -1752,8 +1276,10 @@ bool idle_startup()
if ( gCacheName == NULL )
{
gCacheName = new LLCacheName(gMessageSystem);
- gCacheName->addObserver(callback_cache_name);
-
+ gCacheName->addObserver(&callback_cache_name);
+ gCacheName->LocalizeCacheName("waiting", LLTrans::getString("AvatarNameWaiting"));
+ gCacheName->LocalizeCacheName("nobody", LLTrans::getString("AvatarNameNobody"));
+ gCacheName->LocalizeCacheName("none", LLTrans::getString("GroupNameNone"));
// Load stored cache if possible
LLAppViewer::instance()->loadNameCache();
}
@@ -1767,14 +1293,6 @@ bool idle_startup()
//reset statistics
LLViewerStats::getInstance()->resetStats();
- if (!gNoRender)
- {
- //
- // Set up all of our statistics UI stuff.
- //
- init_stat_view();
- }
-
display_startup();
//
// Set up region and surface defaults
@@ -1796,15 +1314,8 @@ bool idle_startup()
// Make sure agent knows correct aspect ratio
// FOV limits depend upon aspect ratio so this needs to happen before initializing the FOV below
- LLViewerCamera::getInstance()->setViewHeightInPixels(gViewerWindow->getWindowDisplayHeight());
- if (gViewerWindow->mWindow->getFullscreen())
- {
- LLViewerCamera::getInstance()->setAspect(gViewerWindow->getDisplayAspectRatio());
- }
- else
- {
- LLViewerCamera::getInstance()->setAspect( (F32) gViewerWindow->getWindowWidth() / (F32) gViewerWindow->getWindowHeight());
- }
+ LLViewerCamera::getInstance()->setViewHeightInPixels(gViewerWindow->getWorldViewHeightRaw());
+ LLViewerCamera::getInstance()->setAspect(gViewerWindow->getWorldViewAspectRatio());
// Initialize FOV
LLViewerCamera::getInstance()->setDefaultFOV(gSavedSettings.getF32("CameraAngle"));
@@ -1814,7 +1325,7 @@ bool idle_startup()
// the coordinates handed to us to fit in the local region.
gAgent.setPositionAgent(agent_start_position_region);
- gAgent.resetAxes(agent_start_look_at);
+ gAgent.resetAxes(gAgentStartLookAt);
gAgent.stopCameraAnimation();
gAgent.resetCamera();
@@ -1841,7 +1352,7 @@ bool idle_startup()
F32 frac = (F32)i / (F32)DECODE_TIME_SEC;
set_startup_status(0.45f + frac*0.1f, LLTrans::getString("LoginDecodingImages"), gAgent.mMOTD);
display_startup();
- gImageList.decodeAllImages(1.f);
+ gTextureList.decodeAllImages(1.f);
}
LLStartUp::setStartupState( STATE_WORLD_WAIT );
@@ -1853,21 +1364,21 @@ bool idle_startup()
LL_WARNS("AppInit") << "Attempting to connect to simulator with a zero circuit code!" << LL_ENDL;
}
- gUseCircuitCallbackCalled = FALSE;
+ gUseCircuitCallbackCalled = false;
- msg->enableCircuit(first_sim, TRUE);
+ msg->enableCircuit(gFirstSim, TRUE);
// now, use the circuit info to tell simulator about us!
- LL_INFOS("AppInit") << "viewer: UserLoginLocationReply() Enabling " << first_sim << " with code " << msg->mOurCircuitCode << LL_ENDL;
+ LL_INFOS("AppInit") << "viewer: UserLoginLocationReply() Enabling " << gFirstSim << " with code " << msg->mOurCircuitCode << LL_ENDL;
msg->newMessageFast(_PREHASH_UseCircuitCode);
msg->nextBlockFast(_PREHASH_CircuitCode);
msg->addU32Fast(_PREHASH_Code, msg->mOurCircuitCode);
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->addUUIDFast(_PREHASH_ID, gAgent.getID());
msg->sendReliable(
- first_sim,
- MAX_TIMEOUT_COUNT,
+ gFirstSim,
+ gSavedSettings.getS32("UseCircuitCodeMaxRetries"),
FALSE,
- TIMEOUT_SECONDS,
+ gSavedSettings.getF32("UseCircuitCodeTimeout"),
use_circuit_callback,
NULL);
@@ -1975,153 +1486,145 @@ bool idle_startup()
LLAgentLanguage::update();
// unpack thin inventory
- LLUserAuth::options_t options;
- options.clear();
+ LLSD response = LLLoginInstance::getInstance()->getResponse();
//bool dump_buffer = false;
-
- if(LLUserAuth::getInstance()->getOptions("inventory-lib-root", options)
- && !options.empty())
+
+ LLSD inv_lib_root = response["inventory-lib-root"];
+ if(inv_lib_root.isDefined())
{
// should only be one
- LLUserAuth::response_t::iterator it;
- it = options[0].find("folder_id");
- if(it != options[0].end())
+ LLSD id = inv_lib_root[0]["folder_id"];
+ if(id.isDefined())
{
- gInventoryLibraryRoot.set((*it).second);
+ gInventory.setLibraryRootFolderID(id.asUUID());
}
}
- options.clear();
- if(LLUserAuth::getInstance()->getOptions("inventory-lib-owner", options)
- && !options.empty())
+
+ LLSD inv_lib_owner = response["inventory-lib-owner"];
+ if(inv_lib_owner.isDefined())
{
// should only be one
- LLUserAuth::response_t::iterator it;
- it = options[0].find("agent_id");
- if(it != options[0].end())
+ LLSD id = inv_lib_owner[0]["agent_id"];
+ if(id.isDefined())
{
- gInventoryLibraryOwner.set((*it).second);
+ gInventory.setLibraryOwnerID( LLUUID(id.asUUID()));
}
}
- options.clear();
- if(LLUserAuth::getInstance()->getOptions("inventory-skel-lib", options)
- && gInventoryLibraryOwner.notNull())
+
+ LLSD inv_skel_lib = response["inventory-skel-lib"];
+ if(inv_skel_lib.isDefined() && gInventory.getLibraryOwnerID().notNull())
{
- if(!gInventory.loadSkeleton(options, gInventoryLibraryOwner))
+ if(!gInventory.loadSkeleton(inv_skel_lib, gInventory.getLibraryOwnerID()))
{
LL_WARNS("AppInit") << "Problem loading inventory-skel-lib" << LL_ENDL;
}
}
- options.clear();
- if(LLUserAuth::getInstance()->getOptions("inventory-skeleton", options))
+
+ LLSD inv_skeleton = response["inventory-skeleton"];
+ if(inv_skeleton.isDefined())
{
- if(!gInventory.loadSkeleton(options, gAgent.getID()))
+ if(!gInventory.loadSkeleton(inv_skeleton, gAgent.getID()))
{
LL_WARNS("AppInit") << "Problem loading inventory-skel-targets" << LL_ENDL;
}
}
- options.clear();
- if(LLUserAuth::getInstance()->getOptions("buddy-list", options))
+ LLSD buddy_list = response["buddy-list"];
+ if(buddy_list.isDefined())
{
- LLUserAuth::options_t::iterator it = options.begin();
- LLUserAuth::options_t::iterator end = options.end();
LLAvatarTracker::buddy_map_t list;
LLUUID agent_id;
S32 has_rights = 0, given_rights = 0;
- for (; it != end; ++it)
+ for(LLSD::array_const_iterator it = buddy_list.beginArray(),
+ end = buddy_list.endArray(); it != end; ++it)
{
- LLUserAuth::response_t::const_iterator option_it;
- option_it = (*it).find("buddy_id");
- if(option_it != (*it).end())
+ LLSD buddy_id = (*it)["buddy_id"];
+ if(buddy_id.isDefined())
{
- agent_id.set((*option_it).second);
+ agent_id = buddy_id.asUUID();
}
- option_it = (*it).find("buddy_rights_has");
- if(option_it != (*it).end())
+
+ LLSD buddy_rights_has = (*it)["buddy_rights_has"];
+ if(buddy_rights_has.isDefined())
{
- has_rights = atoi((*option_it).second.c_str());
+ has_rights = buddy_rights_has.asInteger();
}
- option_it = (*it).find("buddy_rights_given");
- if(option_it != (*it).end())
+
+ LLSD buddy_rights_given = (*it)["buddy_rights_given"];
+ if(buddy_rights_given.isDefined())
{
- given_rights = atoi((*option_it).second.c_str());
+ given_rights = buddy_rights_given.asInteger();
}
+
list[agent_id] = new LLRelationship(given_rights, has_rights, false);
}
LLAvatarTracker::instance().addBuddyList(list);
}
- options.clear();
- if(LLUserAuth::getInstance()->getOptions("ui-config", options))
- {
- LLUserAuth::options_t::iterator it = options.begin();
- LLUserAuth::options_t::iterator end = options.end();
- for (; it != end; ++it)
- {
- LLUserAuth::response_t::const_iterator option_it;
- option_it = (*it).find("allow_first_life");
- if(option_it != (*it).end())
- {
- if (option_it->second == "Y")
- {
- LLPanelAvatar::sAllowFirstLife = TRUE;
- }
- }
- }
- }
- options.clear();
bool show_hud = false;
- if(LLUserAuth::getInstance()->getOptions("tutorial_setting", options))
+ LLSD tutorial_setting = response["tutorial_setting"];
+ if(tutorial_setting.isDefined())
{
- LLUserAuth::options_t::iterator it = options.begin();
- LLUserAuth::options_t::iterator end = options.end();
- for (; it != end; ++it)
+ for(LLSD::array_const_iterator it = tutorial_setting.beginArray(),
+ end = tutorial_setting.endArray(); it != end; ++it)
{
- LLUserAuth::response_t::const_iterator option_it;
- option_it = (*it).find("tutorial_url");
- if(option_it != (*it).end())
+ LLSD tutorial_url = (*it)["tutorial_url"];
+ if(tutorial_url.isDefined())
{
// Tutorial floater will append language code
- gSavedSettings.setString("TutorialURL", option_it->second);
- }
- option_it = (*it).find("use_tutorial");
- if(option_it != (*it).end())
- {
- if (option_it->second == "true")
- {
- show_hud = true;
- }
+ gSavedSettings.setString("TutorialURL", tutorial_url.asString());
}
+
+ // For Viewer 2.0 we are not using the web-based tutorial
+ // If we reverse that decision, put this code back and use
+ // login.cgi to send a different URL with content that matches
+ // the Viewer 2.0 UI.
+ //LLSD use_tutorial = (*it)["use_tutorial"];
+ //if(use_tutorial.asString() == "true")
+ //{
+ // show_hud = true;
+ //}
}
}
// Either we want to show tutorial because this is the first login
// to a Linden Help Island or the user quit with the tutorial
// visible. JC
- if (show_hud
- || gSavedSettings.getBOOL("ShowTutorial"))
+ if (show_hud || gSavedSettings.getBOOL("ShowTutorial"))
{
- LLFloaterHUD::showHUD();
+ LLFloaterReg::showInstance("hud", LLSD(), FALSE);
}
- options.clear();
- if(LLUserAuth::getInstance()->getOptions("event_categories", options))
+ LLSD event_categories = response["event_categories"];
+ if(event_categories.isDefined())
{
- LLEventInfo::loadCategories(options);
+ LLEventInfo::loadCategories(event_categories);
}
- if(LLUserAuth::getInstance()->getOptions("event_notifications", options))
+
+ LLSD event_notifications = response["event_notifications"];
+ if(event_notifications.isDefined())
{
- gEventNotifier.load(options);
+ gEventNotifier.load(event_notifications);
}
- options.clear();
- if(LLUserAuth::getInstance()->getOptions("classified_categories", options))
+
+ LLSD classified_categories = response["classified_categories"];
+ if(classified_categories.isDefined())
{
- LLClassifiedInfo::loadCategories(options);
+ LLClassifiedInfo::loadCategories(classified_categories);
}
+
+
+ // This method MUST be called before gInventory.findCategoryUUIDForType because of
+ // gInventory.mIsAgentInvUsable is set to true in the gInventory.buildParentChildMap.
gInventory.buildParentChildMap();
- llinfos << "Setting Inventory changed mask and notifying observers" << llendl;
- gInventory.addChangedMask(LLInventoryObserver::ALL, LLUUID::null);
- gInventory.notifyObservers();
+ //all categories loaded. lets create "My Favorites" category
+ gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE,true);
+
+ // Checks whether "Friends" and "Friends/All" folders exist in "Calling Cards" folder,
+ // fetches their contents if needed and synchronizes it with buddies list.
+ // If the folders are not found they are created.
+ LLFriendCardsManager::instance().syncFriendCardsFolders();
+
// set up callbacks
llinfos << "Registering Callbacks" << llendl;
@@ -2145,17 +1648,9 @@ bool idle_startup()
llinfos << "Requesting Agent Data" << llendl;
gAgent.sendAgentDataUpdateRequest();
- bool shown_at_exit = gSavedSettings.getBOOL("ShowInventory");
-
// Create the inventory views
llinfos << "Creating Inventory Views" << llendl;
- LLInventoryView::showAgentInventory();
-
- // Hide the inventory if it wasn't shown at exit
- if(!shown_at_exit)
- {
- LLInventoryView::toggleVisibility(NULL);
- }
+ LLFloaterReg::getInstance("inventory");
LLStartUp::setStartupState( STATE_MISC );
return FALSE;
@@ -2175,7 +1670,7 @@ bool idle_startup()
// This is actually a pessimistic computation, because TCP may not have enough
// time to ramp up on the (small) default inventory file to truly measure max
// bandwidth. JC
- F64 rate_bps = LLUserAuth::getInstance()->getLastTransferRateBPS();
+ F64 rate_bps = LLLoginInstance::getInstance()->getLastTransferRateBPS();
const F32 FAST_RATE_BPS = 600.f * 1024.f;
const F32 FASTER_RATE_BPS = 750.f * 1024.f;
F32 max_bandwidth = gViewerThrottle.getMaxBandwidth();
@@ -2200,6 +1695,7 @@ bool idle_startup()
// We're successfully logged in.
gSavedSettings.setBOOL("FirstLoginThisInstall", FALSE);
+ LLFloaterReg::showInitialVisibleInstances();
// based on the comments, we've successfully logged in so we can delete the 'forced'
// URL that the updater set in settings.ini (in a mostly paranoid fashion)
@@ -2211,6 +1707,7 @@ bool idle_startup()
// and make sure it's saved
gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile") , TRUE );
+ LLUIColorTable::instance().saveUserSettings();
};
if (!gNoRender)
@@ -2221,41 +1718,27 @@ bool idle_startup()
// JC: Initialize "active" gestures. This may also trigger
// many gesture downloads, if this is the user's first
// time on this machine or -purge has been run.
- LLUserAuth::options_t gesture_options;
- if (LLUserAuth::getInstance()->getOptions("gestures", gesture_options))
+ LLSD gesture_options
+ = LLLoginInstance::getInstance()->getResponse("gestures");
+ if (gesture_options.isDefined())
{
LL_DEBUGS("AppInit") << "Gesture Manager loading " << gesture_options.size()
<< LL_ENDL;
std::vector<LLUUID> item_ids;
- LLUserAuth::options_t::iterator resp_it;
- for (resp_it = gesture_options.begin();
- resp_it != gesture_options.end();
- ++resp_it)
+ for(LLSD::array_const_iterator resp_it = gesture_options.beginArray(),
+ end = gesture_options.endArray(); resp_it != end; ++resp_it)
{
- const LLUserAuth::response_t& response = *resp_it;
- LLUUID item_id;
- LLUUID asset_id;
- LLUserAuth::response_t::const_iterator option_it;
-
- option_it = response.find("item_id");
- if (option_it != response.end())
- {
- const std::string& uuid_string = (*option_it).second;
- item_id.set(uuid_string);
- }
- option_it = response.find("asset_id");
- if (option_it != response.end())
- {
- const std::string& uuid_string = (*option_it).second;
- asset_id.set(uuid_string);
- }
+ // If the id is not specifed in the LLSD,
+ // the LLSD operator[]() will return a null LLUUID.
+ LLUUID item_id = (*resp_it)["item_id"];
+ LLUUID asset_id = (*resp_it)["asset_id"];
if (item_id.notNull() && asset_id.notNull())
{
// Could schedule and delay these for later.
const BOOL no_inform_server = FALSE;
const BOOL no_deactivate_similar = FALSE;
- gGestureManager.activateGestureWithAsset(item_id, asset_id,
+ LLGestureManager::instance().activateGestureWithAsset(item_id, asset_id,
no_inform_server,
no_deactivate_similar);
// We need to fetch the inventory items for these gestures
@@ -2263,11 +1746,8 @@ bool idle_startup()
item_ids.push_back(item_id);
}
}
-
- LLGestureInventoryFetchObserver* fetch = new LLGestureInventoryFetchObserver();
- fetch->fetchItems(item_ids);
- // deletes itself when done
- gInventory.addObserver(fetch);
+ // no need to add gesture to inventory observer, it's already made in constructor
+ LLGestureManager::instance().fetchItems(item_ids);
}
}
gDisplaySwapBuffers = TRUE;
@@ -2296,38 +1776,20 @@ bool idle_startup()
//{
//}
+ // The reason we show the alert is because we want to
+ // reduce confusion for when you log in and your provided
+ // location is not your expected location. So, if this is
+ // your first login, then you do not have an expectation,
+ // thus, do not show this alert.
if (!gAgent.isFirstLogin())
{
bool url_ok = LLURLSimString::sInstance.parse();
- if (!((agent_start_location == "url" && url_ok) ||
- (!url_ok && ((agent_start_location == "last" && gSavedSettings.getBOOL("LoginLastLocation")) ||
- (agent_start_location == "home" && !gSavedSettings.getBOOL("LoginLastLocation"))))))
- {
- // The reason we show the alert is because we want to
- // reduce confusion for when you log in and your provided
- // location is not your expected location. So, if this is
- // your first login, then you do not have an expectation,
- // thus, do not show this alert.
- LLSD args;
- if (url_ok)
- {
- args["TYPE"] = "desired";
- args["HELP"] = "";
- }
- else if (gSavedSettings.getBOOL("LoginLastLocation"))
- {
- args["TYPE"] = "last";
- args["HELP"] = "";
- }
- else
- {
- args["TYPE"] = "home";
- args["HELP"] = "You may want to set a new home location.";
- }
- LLNotifications::instance().add("AvatarMoved", args);
- }
- else
+ if ((url_ok && gAgentStartLocation == "url") ||
+ (!url_ok && ((gAgentStartLocation == gSavedSettings.getString("LoginLocation")))))
{
+ // Start location is OK
+ // Disabled code to restore camera location and focus if logging in to default location
+ static bool samename = false;
if (samename)
{
// restore old camera pos
@@ -2342,14 +1804,28 @@ bool idle_startup()
gAgent.stopCameraAnimation();
}
}
+ else
+ {
+ std::string msg;
+ if (url_ok)
+ {
+ msg = "AvatarMovedDesired";
+ }
+ else if (gSavedSettings.getString("LoginLocation") == "home")
+ {
+ msg = "AvatarMovedHome";
+ }
+ else
+ {
+ msg = "AvatarMovedLast";
+ }
+ LLNotificationsUtil::add(msg);
+ }
}
//DEV-17797. get null folder. Any items found here moved to Lost and Found
LLInventoryModel::findLostItems();
- //DEV-10530. do cleanup. remove at some later date. jan-2009
- LLPrefsIM::cleanupBadSetting();
-
LLStartUp::setStartupState( STATE_PRECACHE );
timeout.reset();
return FALSE;
@@ -2428,7 +1904,7 @@ bool idle_startup()
// initial outfit, but if the load hasn't started
// already then something is wrong so fall back
// to generic outfits. JC
- LLNotifications::instance().add("WelcomeChooseSex", LLSD(), LLSD(),
+ LLNotificationsUtil::add("WelcomeChooseSex", LLSD(), LLSD(),
callback_choose_gender);
LLStartUp::setStartupState( STATE_CLEANUP );
return TRUE;
@@ -2436,7 +1912,7 @@ bool idle_startup()
if (wearables_time > MAX_WEARABLES_TIME)
{
- LLNotifications::instance().add("ClothingLoading");
+ LLNotificationsUtil::add("ClothingLoading");
LLViewerStats::getInstance()->incStat(LLViewerStats::ST_WEARABLES_TOO_LONG);
LLStartUp::setStartupState( STATE_CLEANUP );
return TRUE;
@@ -2456,7 +1932,7 @@ bool idle_startup()
else
{
// OK to just get the wearables
- if ( gAgent.areWearablesLoaded() )
+ if ( gAgentWearables.areWearablesLoaded() )
{
// We have our clothing, proceed.
//llinfos << "wearables loaded" << llendl;
@@ -2477,12 +1953,12 @@ bool idle_startup()
set_startup_status(1.0, "", "");
// Let the map know about the inventory.
- if(gFloaterWorldMap)
+ LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance();
+ if(floater_world_map)
{
- gFloaterWorldMap->observeInventory(&gInventory);
- gFloaterWorldMap->observeFriends();
+ floater_world_map->observeInventory(&gInventory);
+ floater_world_map->observeFriends();
}
-
gViewerWindow->showCursor();
gViewerWindow->getWindow()->resetBusyCount();
gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
@@ -2502,13 +1978,15 @@ bool idle_startup()
}
// Start automatic replay if the flag is set.
- if (gSavedSettings.getBOOL("StatsAutoRun"))
+ if (gSavedSettings.getBOOL("StatsAutoRun") || LLAgentPilot::sReplaySession)
{
LLUUID id;
LL_DEBUGS("AppInit") << "Starting automatic playback" << LL_ENDL;
gAgentPilot.startPlayback();
}
+ show_debug_menus(); // Debug menu visiblity and First Use trigger
+
// If we've got a startup URL, dispatch it
LLStartUp::dispatchURL();
@@ -2517,8 +1995,10 @@ bool idle_startup()
// then the data is cached for the viewer's lifetime)
LLProductInfoRequestManager::instance();
+ // *FIX:Mani - What do I do here?
+ // Need we really clear the Auth response data?
// Clean up the userauth stuff.
- LLUserAuth::getInstance()->reset();
+ // LLUserAuth::getInstance()->reset();
LLStartUp::setStartupState( STATE_STARTED );
@@ -2539,6 +2019,13 @@ bool idle_startup()
LLAppViewer::instance()->handleLoginComplete();
+ // reset timers now that we are running "logged in" logic
+ LLFastTimer::reset();
+
+ LLAgentPicksInfo::getInstance()->requestNumberOfPicks();
+
+ LLIMFloater::initIMFloater();
+
return TRUE;
}
@@ -2560,7 +2047,7 @@ void login_show()
BOOL bUseDebugLogin = TRUE;
#endif
- LLPanelLogin::show( gViewerWindow->getVirtualWindowRect(),
+ LLPanelLogin::show( gViewerWindow->getWindowRectScaled(),
bUseDebugLogin,
login_callback, NULL );
@@ -2588,7 +2075,7 @@ void login_callback(S32 option, void *userdata)
LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );
return;
}
- else if (QUIT_OPTION == option)
+ else if (QUIT_OPTION == option) // *TODO: THIS CODE SEEMS TO BE UNREACHABLE!!!!! login_callback is never called with option equal to QUIT_OPTION
{
// Make sure we don't save the password if the user is trying to clear it.
std::string first, last, password;
@@ -2597,6 +2084,7 @@ void login_callback(S32 option, void *userdata)
{
// turn off the setting and write out to disk
gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile") , TRUE );
+ LLUIColorTable::instance().saveUserSettings();
}
// Next iteration through main loop should shut down the app cleanly.
@@ -2604,7 +2092,7 @@ void login_callback(S32 option, void *userdata)
if (LLAppViewer::instance()->quitRequested())
{
- LLPanelLogin::close();
+ LLPanelLogin::closePanel();
}
return;
}
@@ -2752,16 +2240,16 @@ bool is_hex_string(U8* str, S32 len)
void show_first_run_dialog()
{
- LLNotifications::instance().add("FirstRun", LLSD(), LLSD(), first_run_dialog_callback);
+ LLNotificationsUtil::add("FirstRun", LLSD(), LLSD(), first_run_dialog_callback);
}
bool first_run_dialog_callback(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
LL_DEBUGS("AppInit") << "First run dialog cancelling" << LL_ENDL;
- LLWeb::loadURL( CREATE_ACCOUNT_URL );
+ LLWeb::loadURLExternal(LLTrans::getString("create_account_url") );
}
LLPanelLogin::giveFocus();
@@ -2780,18 +2268,18 @@ void set_startup_status(const F32 frac, const std::string& string, const std::st
bool login_alert_status(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
// Buttons
switch( option )
{
case 0: // OK
break;
- case 1: // Help
- LLWeb::loadURL( SUPPORT_URL );
- break;
+ // case 1: // Help
+ // LLWeb::loadURL(LLNotifications::instance().getGlobalString("SUPPORT_URL") );
+ // break;
case 2: // Teleport
// Restart the login process, starting at our home locaton
- LLURLSimString::setString(LLURLSimString::sLocationStringHome);
+ LLURLSimString::setString("home");
LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );
break;
default:
@@ -2802,197 +2290,6 @@ bool login_alert_status(const LLSD& notification, const LLSD& response)
return false;
}
-void update_app(BOOL mandatory, const std::string& auth_msg)
-{
- // store off config state, as we might quit soon
- gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
-
- std::ostringstream message;
-
- //*TODO:translate
- std::string msg;
- if (!auth_msg.empty())
- {
- msg = "(" + auth_msg + ") \n";
- }
-
- LLSD args;
- args["MESSAGE"] = msg;
-
- LLSD payload;
- payload["mandatory"] = mandatory;
-
-/*
- We're constructing one of the following 6 strings here:
- "DownloadWindowsMandatory"
- "DownloadWindowsReleaseForDownload"
- "DownloadWindows"
- "DownloadMacMandatory"
- "DownloadMacReleaseForDownload"
- "DownloadMac"
-
- I've called them out explicitly in this comment so that they can be grepped for.
-
- Also, we assume that if we're not Windows we're Mac. If we ever intend to support
- Linux with autoupdate, this should be an explicit #elif LL_DARWIN, but
- we'd rather deliver the wrong message than no message, so until Linux is supported
- we'll leave it alone.
- */
- std::string notification_name = "Download";
-
-#if LL_WINDOWS
- notification_name += "Windows";
-#else
- notification_name += "Mac";
-#endif
-
- if (mandatory)
- {
- notification_name += "Mandatory";
- }
- else
- {
-#if LL_RELEASE_FOR_DOWNLOAD
- notification_name += "ReleaseForDownload";
-#endif
- }
-
- LLNotifications::instance().add(notification_name, args, payload, update_dialog_callback);
-
-}
-
-bool update_dialog_callback(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotification::getSelectedOption(notification, response);
- std::string update_exe_path;
- bool mandatory = notification["payload"]["mandatory"].asBoolean();
-
-#if !LL_RELEASE_FOR_DOWNLOAD
- if (option == 2)
- {
- LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT );
- return false;
- }
-#endif
-
- if (option == 1)
- {
- // ...user doesn't want to do it
- if (mandatory)
- {
- LLAppViewer::instance()->forceQuit();
- // Bump them back to the login screen.
- //reset_login();
- }
- else
- {
- LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT );
- }
- return false;
- }
-
- LLSD query_map = LLSD::emptyMap();
- // *TODO place os string in a global constant
-#if LL_WINDOWS
- query_map["os"] = "win";
-#elif LL_DARWIN
- query_map["os"] = "mac";
-#elif LL_LINUX
- query_map["os"] = "lnx";
-#elif LL_SOLARIS
- query_map["os"] = "sol";
-#endif
- // *TODO change userserver to be grid on both viewer and sim, since
- // userserver no longer exists.
- query_map["userserver"] = LLViewerLogin::getInstance()->getGridLabel();
- query_map["channel"] = gSavedSettings.getString("VersionChannelName");
- // *TODO constantize this guy
- // *NOTE: This URL is also used in win_setup/lldownloader.cpp
- LLURI update_url = LLURI::buildHTTP("secondlife.com", 80, "update.php", query_map);
-
- if(LLAppViewer::sUpdaterInfo)
- {
- delete LLAppViewer::sUpdaterInfo ;
- }
- LLAppViewer::sUpdaterInfo = new LLAppViewer::LLUpdaterInfo() ;
-
-#if LL_WINDOWS
- LLAppViewer::sUpdaterInfo->mUpdateExePath = gDirUtilp->getTempFilename();
- if (LLAppViewer::sUpdaterInfo->mUpdateExePath.empty())
- {
- delete LLAppViewer::sUpdaterInfo ;
- LLAppViewer::sUpdaterInfo = NULL ;
-
- // We're hosed, bail
- LL_WARNS("AppInit") << "LLDir::getTempFilename() failed" << LL_ENDL;
- LLAppViewer::instance()->forceQuit();
- return false;
- }
-
- LLAppViewer::sUpdaterInfo->mUpdateExePath += ".exe";
-
- std::string updater_source = gDirUtilp->getAppRODataDir();
- updater_source += gDirUtilp->getDirDelimiter();
- updater_source += "updater.exe";
-
- LL_DEBUGS("AppInit") << "Calling CopyFile source: " << updater_source
- << " dest: " << LLAppViewer::sUpdaterInfo->mUpdateExePath
- << LL_ENDL;
-
-
- if (!CopyFileA(updater_source.c_str(), LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), FALSE))
- {
- delete LLAppViewer::sUpdaterInfo ;
- LLAppViewer::sUpdaterInfo = NULL ;
-
- LL_WARNS("AppInit") << "Unable to copy the updater!" << LL_ENDL;
- LLAppViewer::instance()->forceQuit();
- return false;
- }
-
- // if a sim name was passed in via command line parameter (typically through a SLURL)
- if ( LLURLSimString::sInstance.mSimString.length() )
- {
- // record the location to start at next time
- gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString );
- };
-
- LLAppViewer::sUpdaterInfo->mParams << "-url \"" << update_url.asString() << "\"";
-
- LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << " " << LLAppViewer::sUpdaterInfo->mParams.str() << LL_ENDL;
-
- //Explicitly remove the marker file, otherwise we pass the lock onto the child process and things get weird.
- LLAppViewer::instance()->removeMarkerFile(); // In case updater fails
-
-#elif LL_DARWIN
- // if a sim name was passed in via command line parameter (typically through a SLURL)
- if ( LLURLSimString::sInstance.mSimString.length() )
- {
- // record the location to start at next time
- gSavedSettings.setString( "NextLoginLocation", LLURLSimString::sInstance.mSimString );
- };
-
- LLAppViewer::sUpdaterInfo->mUpdateExePath = "'";
- LLAppViewer::sUpdaterInfo->mUpdateExePath += gDirUtilp->getAppRODataDir();
- LLAppViewer::sUpdaterInfo->mUpdateExePath += "/mac-updater.app/Contents/MacOS/mac-updater' -url \"";
- LLAppViewer::sUpdaterInfo->mUpdateExePath += update_url.asString();
- LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" -name \"";
- LLAppViewer::sUpdaterInfo->mUpdateExePath += LLAppViewer::instance()->getSecondLifeTitle();
- LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" &";
-
- LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL;
-
- // Run the auto-updater.
- system(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str()); /* Flawfinder: ignore */
-
-#elif LL_LINUX || LL_SOLARIS
- OSMessageBox("Automatic updating is not yet implemented for Linux.\n"
- "Please download the latest version from www.secondlife.com.",
- LLStringUtil::null, OSMB_OK);
-#endif
- LLAppViewer::instance()->forceQuit();
- return false;
-}
void use_circuit_callback(void**, S32 result)
{
@@ -3005,7 +2302,7 @@ void use_circuit_callback(void**, S32 result)
{
// Make sure user knows something bad happened. JC
LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL;
- LLNotifications::instance().add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
+ LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
reset_login();
}
else
@@ -3018,8 +2315,8 @@ void use_circuit_callback(void**, S32 result)
void register_viewer_callbacks(LLMessageSystem* msg)
{
msg->setHandlerFuncFast(_PREHASH_LayerData, process_layer_data );
- msg->setHandlerFuncFast(_PREHASH_ImageData, LLViewerImageList::receiveImageHeader );
- msg->setHandlerFuncFast(_PREHASH_ImagePacket, LLViewerImageList::receiveImagePacket );
+ msg->setHandlerFuncFast(_PREHASH_ImageData, LLViewerTextureList::receiveImageHeader );
+ msg->setHandlerFuncFast(_PREHASH_ImagePacket, LLViewerTextureList::receiveImagePacket );
msg->setHandlerFuncFast(_PREHASH_ObjectUpdate, process_object_update );
msg->setHandlerFunc("ObjectUpdateCompressed", process_compressed_object_update );
msg->setHandlerFunc("ObjectUpdateCached", process_cached_object_update );
@@ -3049,7 +2346,7 @@ void register_viewer_callbacks(LLMessageSystem* msg)
msg->setHandlerFuncFast(_PREHASH_AvatarAnimation, process_avatar_animation);
msg->setHandlerFuncFast(_PREHASH_AvatarAppearance, process_avatar_appearance);
msg->setHandlerFunc("AgentCachedTextureResponse", LLAgent::processAgentCachedTextureResponse);
- msg->setHandlerFunc("RebakeAvatarTextures", LLVOAvatar::processRebakeAvatarTextures);
+ msg->setHandlerFunc("RebakeAvatarTextures", LLVOAvatarSelf::processRebakeAvatarTextures);
msg->setHandlerFuncFast(_PREHASH_CameraConstraint, process_camera_constraint);
msg->setHandlerFuncFast(_PREHASH_AvatarSitResponse, process_avatar_sit_response);
msg->setHandlerFunc("SetFollowCamProperties", process_set_follow_cam_properties);
@@ -3093,20 +2390,20 @@ void register_viewer_callbacks(LLMessageSystem* msg)
LLViewerParcelMgr::processParcelDwellReply);
msg->setHandlerFunc("AvatarPropertiesReply",
- LLPanelAvatar::processAvatarPropertiesReply);
+ &LLAvatarPropertiesProcessor::processAvatarPropertiesReply);
msg->setHandlerFunc("AvatarInterestsReply",
- LLPanelAvatar::processAvatarInterestsReply);
+ &LLAvatarPropertiesProcessor::processAvatarInterestsReply);
msg->setHandlerFunc("AvatarGroupsReply",
- LLPanelAvatar::processAvatarGroupsReply);
+ &LLAvatarPropertiesProcessor::processAvatarGroupsReply);
// ratings deprecated
//msg->setHandlerFuncFast(_PREHASH_AvatarStatisticsReply,
// LLPanelAvatar::processAvatarStatisticsReply);
msg->setHandlerFunc("AvatarNotesReply",
- LLPanelAvatar::processAvatarNotesReply);
+ &LLAvatarPropertiesProcessor::processAvatarNotesReply);
msg->setHandlerFunc("AvatarPicksReply",
- LLPanelAvatar::processAvatarPicksReply);
- msg->setHandlerFunc("AvatarClassifiedReply",
- LLPanelAvatar::processAvatarClassifiedReply);
+ &LLAvatarPropertiesProcessor::processAvatarPicksReply);
+ msg->setHandlerFunc("AvatarClassifiedReply",
+ &LLAvatarPropertiesProcessor::processAvatarClassifiedsReply);
msg->setHandlerFuncFast(_PREHASH_CreateGroupReply,
LLGroupMgr::processCreateGroupReply);
@@ -3124,7 +2421,7 @@ void register_viewer_callbacks(LLMessageSystem* msg)
// LLFloaterRate::processReputationIndividualReply);
msg->setHandlerFuncFast(_PREHASH_AgentWearablesUpdate,
- LLAgent::processAgentInitialWearablesUpdate );
+ LLAgentWearables::processAgentInitialWearablesUpdate );
msg->setHandlerFunc("ScriptControlChange",
LLAgent::processScriptControlChange );
@@ -3150,7 +2447,7 @@ void register_viewer_callbacks(LLMessageSystem* msg)
msg->setHandlerFunc("TeleportFailed", process_teleport_failed, NULL);
msg->setHandlerFunc("TeleportLocal", process_teleport_local, NULL);
- msg->setHandlerFunc("ImageNotInDatabase", LLViewerImageList::processImageNotInDatabase, NULL);
+ msg->setHandlerFunc("ImageNotInDatabase", LLViewerTextureList::processImageNotInDatabase, NULL);
msg->setHandlerFuncFast(_PREHASH_GroupMembersReply,
LLGroupMgr::processGroupMembersReply);
@@ -3164,25 +2461,16 @@ void register_viewer_callbacks(LLMessageSystem* msg)
msg->setHandlerFunc("PlacesReply", process_places_reply);
msg->setHandlerFunc("GroupNoticesListReply", LLPanelGroupNotices::processGroupNoticesListReply);
- msg->setHandlerFunc("DirPlacesReply", LLPanelDirBrowser::processDirPlacesReply);
- msg->setHandlerFunc("DirPeopleReply", LLPanelDirBrowser::processDirPeopleReply);
- msg->setHandlerFunc("DirEventsReply", LLPanelDirBrowser::processDirEventsReply);
- msg->setHandlerFunc("DirGroupsReply", LLPanelDirBrowser::processDirGroupsReply);
- //msg->setHandlerFunc("DirPicksReply", LLPanelDirBrowser::processDirPicksReply);
- msg->setHandlerFunc("DirClassifiedReply", LLPanelDirBrowser::processDirClassifiedReply);
- msg->setHandlerFunc("DirLandReply", LLPanelDirBrowser::processDirLandReply);
- //msg->setHandlerFunc("DirPopularReply",LLPanelDirBrowser::processDirPopularReply);
-
msg->setHandlerFunc("AvatarPickerReply", LLFloaterAvatarPicker::processAvatarPickerReply);
- msg->setHandlerFunc("MapLayerReply", LLWorldMap::processMapLayerReply);
- msg->setHandlerFunc("MapBlockReply", LLWorldMap::processMapBlockReply);
- msg->setHandlerFunc("MapItemReply", LLWorldMap::processMapItemReply);
+ msg->setHandlerFunc("MapBlockReply", LLWorldMapMessage::processMapBlockReply);
+ msg->setHandlerFunc("MapItemReply", LLWorldMapMessage::processMapItemReply);
msg->setHandlerFunc("EventInfoReply", LLPanelEvent::processEventInfoReply);
- msg->setHandlerFunc("PickInfoReply", LLPanelPick::processPickInfoReply);
- msg->setHandlerFunc("ClassifiedInfoReply", LLPanelClassified::processClassifiedInfoReply);
- msg->setHandlerFunc("ParcelInfoReply", LLPanelPlace::processParcelInfoReply);
+ 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);
msg->setHandlerFunc("LoadURL", process_load_url);
msg->setHandlerFunc("ScriptTeleportRequest", process_script_teleport_request);
@@ -3202,14 +2490,6 @@ void register_viewer_callbacks(LLMessageSystem* msg)
msg->setHandlerFuncFast(_PREHASH_FeatureDisabled, process_feature_disabled_message);
}
-
-void init_stat_view()
-{
- LLFrameStatView *frameviewp = gDebugView->mFrameStatView;
- frameviewp->setup(gFrameStats);
- frameviewp->mShowPercent = FALSE;
-}
-
void asset_callback_nothing(LLVFS*, const LLUUID&, LLAssetType::EType, void*, S32)
{
// nothing
@@ -3227,7 +2507,7 @@ const S32 OPT_FEMALE = 1;
bool callback_choose_gender(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
switch(option)
{
case OPT_MALE:
@@ -3271,14 +2551,14 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
has_name);
if (0 == cat_array.count())
{
- gAgent.createStandardWearables(gender);
+ gAgentWearables.createStandardWearables(gender);
}
else
{
- wear_outfit_by_name(outfit_folder_name);
+ LLAppearanceManager::instance().wearOutfitByName(outfit_folder_name);
}
- wear_outfit_by_name(gestures);
- wear_outfit_by_name(COMMON_GESTURES_FOLDER);
+ LLAppearanceManager::instance().wearOutfitByName(gestures);
+ LLAppearanceManager::instance().wearOutfitByName(COMMON_GESTURES_FOLDER);
// This is really misnamed -- it means we have started loading
// an outfit/shape that will give the avatar a gender eventually. JC
@@ -3287,13 +2567,11 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
}
// Loads a bitmap to display during load
-// location_id = 0 => last position
-// location_id = 1 => home position
void init_start_screen(S32 location_id)
{
- if (gStartImageGL.notNull())
+ if (gStartTexture.notNull())
{
- gStartImageGL = NULL;
+ gStartTexture = NULL;
LL_INFOS("AppInit") << "re-initializing start screen" << LL_ENDL;
}
@@ -3325,7 +2603,6 @@ void init_start_screen(S32 location_id)
return;
}
- gStartImageGL = new LLImageGL(FALSE);
gStartImageWidth = start_image_bmp->getWidth();
gStartImageHeight = start_image_bmp->getHeight();
@@ -3333,12 +2610,12 @@ void init_start_screen(S32 location_id)
if (!start_image_bmp->decode(raw, 0.0f))
{
LL_WARNS("AppInit") << "Bitmap decode failed" << LL_ENDL;
- gStartImageGL = NULL;
+ gStartTexture = NULL;
return;
}
raw->expandToPowerOfTwo();
- gStartImageGL->createGLTexture(0, raw);
+ gStartTexture = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE) ;
}
@@ -3346,7 +2623,7 @@ void init_start_screen(S32 location_id)
void release_start_screen()
{
LL_DEBUGS("AppInit") << "Releasing bitmap..." << LL_ENDL;
- gStartImageGL = NULL;
+ gStartTexture = NULL;
}
@@ -3356,16 +2633,16 @@ std::string LLStartUp::startupStateToString(EStartupState state)
#define RTNENUM(E) case E: return #E
switch(state){
RTNENUM( STATE_FIRST );
+ RTNENUM( STATE_BROWSER_INIT );
RTNENUM( STATE_LOGIN_SHOW );
RTNENUM( STATE_LOGIN_WAIT );
RTNENUM( STATE_LOGIN_CLEANUP );
- RTNENUM( STATE_UPDATE_CHECK );
RTNENUM( STATE_LOGIN_AUTH_INIT );
- RTNENUM( STATE_LOGIN_AUTHENTICATE );
- RTNENUM( STATE_LOGIN_NO_DATA_YET );
- RTNENUM( STATE_LOGIN_DOWNLOADING );
+ RTNENUM( STATE_LOGIN_CURL_UNSTUCK );
RTNENUM( STATE_LOGIN_PROCESS_RESPONSE );
RTNENUM( STATE_WORLD_INIT );
+ RTNENUM( STATE_MULTIMEDIA_INIT );
+ RTNENUM( STATE_FONT_INIT );
RTNENUM( STATE_SEED_GRANTED_WAIT );
RTNENUM( STATE_SEED_CAP_GRANTED );
RTNENUM( STATE_WORLD_WAIT );
@@ -3383,19 +2660,30 @@ std::string LLStartUp::startupStateToString(EStartupState state)
#undef RTNENUM
}
-
// static
void LLStartUp::setStartupState( EStartupState state )
{
LL_INFOS("AppInit") << "Startup state changing from " <<
- startupStateToString(gStartupState) << " to " <<
+ getStartupStateString() << " to " <<
startupStateToString(state) << LL_ENDL;
gStartupState = state;
+ postStartupState();
+}
+
+void LLStartUp::postStartupState()
+{
+ LLSD stateInfo;
+ stateInfo["str"] = getStartupStateString();
+ stateInfo["enum"] = gStartupState;
+ sStateWatcher->post(stateInfo);
}
void reset_login()
{
+ gAgent.cleanup();
+ LLWorld::getInstance()->destroyClass();
+
LLStartUp::setStartupState( STATE_LOGIN_SHOW );
if ( gViewerWindow )
@@ -3406,7 +2694,7 @@ void reset_login()
}
// Hide any other stuff
- LLFloaterMap::hideInstance();
+ LLFloaterReg::hideVisibleInstances();
}
//---------------------------------------------------------------------------
@@ -3427,16 +2715,26 @@ void LLStartUp::multimediaInit()
set_startup_status(0.42f, msg.c_str(), gAgent.mMOTD.c_str());
display_startup();
- LLViewerMedia::initClass();
+ // LLViewerMedia::initClass();
LLViewerParcelMedia::initClass();
}
+void LLStartUp::fontInit()
+{
+ LL_DEBUGS("AppInit") << "Initializing fonts...." << LL_ENDL;
+ std::string msg = LLTrans::getString("LoginInitializingFonts");
+ set_startup_status(0.45f, msg.c_str(), gAgent.mMOTD.c_str());
+ display_startup();
+
+ LLFontGL::loadDefaultFonts();
+}
+
bool LLStartUp::dispatchURL()
{
// ok, if we've gotten this far and have a startup URL
if (!sSLURLCommand.empty())
{
- LLWebBrowserCtrl* web = NULL;
+ LLMediaCtrl* web = NULL;
const bool trusted_browser = false;
LLURLDispatcher::dispatch(sSLURLCommand, web, trusted_browser);
}
@@ -3454,7 +2752,7 @@ bool LLStartUp::dispatchURL()
|| (dy*dy > SLOP*SLOP) )
{
std::string url = LLURLSimString::getURL();
- LLWebBrowserCtrl* web = NULL;
+ LLMediaCtrl* web = NULL;
const bool trusted_browser = false;
LLURLDispatcher::dispatch(url, web, trusted_browser);
}
@@ -3494,3 +2792,278 @@ void apply_udp_blacklist(const std::string& csv)
}
+bool process_login_success_response()
+{
+ LLSD response = LLLoginInstance::getInstance()->getResponse();
+
+ std::string text(response["udp_blacklist"]);
+ if(!text.empty())
+ {
+ apply_udp_blacklist(text);
+ }
+
+ // unpack login data needed by the application
+ text = response["agent_id"].asString();
+ if(!text.empty()) gAgentID.set(text);
+ gDebugInfo["AgentID"] = text;
+
+ text = response["session_id"].asString();
+ if(!text.empty()) gAgentSessionID.set(text);
+ gDebugInfo["SessionID"] = text;
+
+ text = response["secure_session_id"].asString();
+ if(!text.empty()) gAgent.mSecureSessionID.set(text);
+
+ text = response["first_name"].asString();
+ if(!text.empty())
+ {
+ // Remove quotes from string. Login.cgi sends these to force
+ // names that look like numbers into strings.
+ gFirstname.assign(text);
+ LLStringUtil::replaceChar(gFirstname, '"', ' ');
+ LLStringUtil::trim(gFirstname);
+ }
+ text = response["last_name"].asString();
+ if(!text.empty())
+ {
+ gLastname.assign(text);
+ }
+ gSavedSettings.setString("FirstName", gFirstname);
+ gSavedSettings.setString("LastName", gLastname);
+
+ if (gSavedSettings.getBOOL("RememberPassword"))
+ {
+ // Successful login means the password is valid, so save it.
+ LLStartUp::savePasswordToDisk(gPassword);
+ }
+ else
+ {
+ // Don't leave password from previous session sitting around
+ // during this login session.
+ LLStartUp::deletePasswordFromDisk();
+ }
+
+ // this is their actual ability to access content
+ text = response["agent_access_max"].asString();
+ if (!text.empty())
+ {
+ // agent_access can be 'A', 'M', and 'PG'.
+ gAgent.setMaturity(text[0]);
+ }
+
+ // this is the value of their preference setting for that content
+ // which will always be <= agent_access_max
+ text = response["agent_region_access"].asString();
+ if (!text.empty())
+ {
+ int preferredMaturity = LLAgent::convertTextToMaturity(text[0]);
+ gSavedSettings.setU32("PreferredMaturity", preferredMaturity);
+ }
+ // During the AO transition, this flag will be true. Then the flag will
+ // go away. After the AO transition, this code and all the code that
+ // uses it can be deleted.
+ text = response["ao_transition"].asString();
+ if (!text.empty())
+ {
+ if (text == "1")
+ {
+ gAgent.setAOTransition();
+ }
+ }
+
+ text = response["start_location"].asString();
+ if(!text.empty())
+ {
+ gAgentStartLocation.assign(text);
+ }
+
+ text = response["circuit_code"].asString();
+ if(!text.empty())
+ {
+ gMessageSystem->mOurCircuitCode = strtoul(text.c_str(), NULL, 10);
+ }
+ std::string sim_ip_str = response["sim_ip"];
+ std::string sim_port_str = response["sim_port"];
+ if(!sim_ip_str.empty() && !sim_port_str.empty())
+ {
+ U32 sim_port = strtoul(sim_port_str.c_str(), NULL, 10);
+ gFirstSim.set(sim_ip_str, sim_port);
+ if (gFirstSim.isOk())
+ {
+ gMessageSystem->enableCircuit(gFirstSim, TRUE);
+ }
+ }
+ std::string region_x_str = response["region_x"];
+ std::string region_y_str = response["region_y"];
+ if(!region_x_str.empty() && !region_y_str.empty())
+ {
+ U32 region_x = strtoul(region_x_str.c_str(), NULL, 10);
+ U32 region_y = strtoul(region_y_str.c_str(), NULL, 10);
+ gFirstSimHandle = to_region_handle(region_x, region_y);
+ }
+
+ const std::string look_at_str = response["look_at"];
+ if (!look_at_str.empty())
+ {
+ size_t len = look_at_str.size();
+ LLMemoryStream mstr((U8*)look_at_str.c_str(), len);
+ LLSD sd = LLSDSerialize::fromNotation(mstr, len);
+ gAgentStartLookAt = ll_vector3_from_sd(sd);
+ }
+
+ text = response["seed_capability"].asString();
+ if (!text.empty()) gFirstSimSeedCap = text;
+
+ text = response["seconds_since_epoch"].asString();
+ if(!text.empty())
+ {
+ U32 server_utc_time = strtoul(text.c_str(), NULL, 10);
+ if(server_utc_time)
+ {
+ time_t now = time(NULL);
+ gUTCOffset = (server_utc_time - now);
+ }
+ }
+
+ // this is the base used to construct help URLs
+ text = response["help_url_format"].asString();
+ if (!text.empty())
+ {
+ // replace the default help URL format
+ gSavedSettings.setString("HelpURLFormat",text);
+
+ // don't fall back to Nebraska's pre-connection static help
+ gSavedSettings.setBOOL("HelpUseLocal", false);
+ }
+
+ std::string home_location = response["home"];
+ if(!home_location.empty())
+ {
+ size_t len = home_location.size();
+ LLMemoryStream mstr((U8*)home_location.c_str(), len);
+ LLSD sd = LLSDSerialize::fromNotation(mstr, len);
+ S32 region_x = sd["region_handle"][0].asInteger();
+ S32 region_y = sd["region_handle"][1].asInteger();
+ U64 region_handle = to_region_handle(region_x, region_y);
+ LLVector3 position = ll_vector3_from_sd(sd["position"]);
+ gAgent.setHomePosRegion(region_handle, position);
+ }
+
+ gAgent.mMOTD.assign(response["message"]);
+
+ // Options...
+ // Each 'option' is an array of submaps.
+ // It appears that we only ever use the first element of the array.
+ LLUUID inv_root_folder_id = response["inventory-root"][0]["folder_id"];
+ if(inv_root_folder_id.notNull())
+ {
+ gInventory.setRootFolderID(inv_root_folder_id);
+ //gInventory.mock(gAgent.getInventoryRootID());
+ }
+
+ LLSD login_flags = response["login-flags"][0];
+ if(login_flags.size())
+ {
+ std::string flag = login_flags["ever_logged_in"];
+ if(!flag.empty())
+ {
+ gAgent.setFirstLogin((flag == "N") ? TRUE : FALSE);
+ }
+
+ /* Flag is currently ignored by the viewer.
+ flag = login_flags["stipend_since_login"];
+ if(flag == "Y")
+ {
+ stipend_since_login = true;
+ }
+ */
+
+ flag = login_flags["gendered"].asString();
+ if(flag == "Y")
+ {
+ gAgent.setGenderChosen(TRUE);
+ }
+
+ bool pacific_daylight_time = false;
+ flag = login_flags["daylight_savings"].asString();
+ if(flag == "Y")
+ {
+ pacific_daylight_time = (flag == "Y");
+ }
+
+ //setup map of datetime strings to codes and slt & local time offset from utc
+ LLStringOps::setupDatetimeInfo(pacific_daylight_time);
+ }
+
+ LLSD initial_outfit = response["initial-outfit"][0];
+ if(initial_outfit.size())
+ {
+ std::string flag = initial_outfit["folder_name"];
+ if(!flag.empty())
+ {
+ // Initial outfit is a folder in your inventory,
+ // must be an exact folder-name match.
+ sInitialOutfit = flag;
+ }
+
+ flag = initial_outfit["gender"].asString();
+ if(!flag.empty())
+ {
+ sInitialOutfitGender = flag;
+ }
+ }
+
+ LLSD global_textures = response["global-textures"][0];
+ if(global_textures.size())
+ {
+ // Extract sun and moon texture IDs. These are used
+ // in the LLVOSky constructor, but I can't figure out
+ // how to pass them in. JC
+ LLUUID id = global_textures["sun_texture_id"];
+ if(id.notNull())
+ {
+ gSunTextureID = id;
+ }
+
+ id = global_textures["moon_texture_id"];
+ if(id.notNull())
+ {
+ gMoonTextureID = id;
+ }
+
+ id = global_textures["cloud_texture_id"];
+ if(id.notNull())
+ {
+ gCloudTextureID = id;
+ }
+ }
+
+
+ bool success = false;
+ // JC: gesture loading done below, when we have an asset system
+ // in place. Don't delete/clear user_credentials until then.
+ if(gAgentID.notNull()
+ && gAgentSessionID.notNull()
+ && gMessageSystem->mOurCircuitCode
+ && gFirstSim.isOk()
+ && gInventory.getRootFolderID().notNull())
+ {
+ success = true;
+ }
+
+ return success;
+}
+
+void transition_back_to_login_panel(const std::string& emsg)
+{
+ if (gNoRender)
+ {
+ LL_WARNS("AppInit") << "Failed to login!" << LL_ENDL;
+ LL_WARNS("AppInit") << emsg << LL_ENDL;
+ exit(0);
+ }
+
+ // Bounce back to the login screen.
+ reset_login(); // calls LLStartUp::setStartupState( STATE_LOGIN_SHOW );
+ gSavedSettings.setBOOL("AutoLogin", FALSE);
+}
diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h
index fe347e9efe..92fe9521d3 100644
--- a/indra/newview/llstartup.h
+++ b/indra/newview/llstartup.h
@@ -33,7 +33,11 @@
#ifndef LL_LLSTARTUP_H
#define LL_LLSTARTUP_H
-#include "llimagegl.h"
+#include <boost/scoped_ptr.hpp>
+
+class LLViewerTexture ;
+class LLEventPump;
+class LLStartupListener;
// functions
bool idle_startup();
@@ -50,14 +54,12 @@ typedef enum {
STATE_LOGIN_SHOW, // Show login screen
STATE_LOGIN_WAIT, // Wait for user input at login screen
STATE_LOGIN_CLEANUP, // Get rid of login screen and start login
- STATE_UPDATE_CHECK, // Wait for user at a dialog box (updates, term-of-service, etc)
STATE_LOGIN_AUTH_INIT, // Start login to SL servers
- STATE_LOGIN_AUTHENTICATE, // Do authentication voodoo
- STATE_LOGIN_NO_DATA_YET, // Waiting for authentication replies to start
- STATE_LOGIN_DOWNLOADING, // Waiting for authentication replies to download
+ STATE_LOGIN_CURL_UNSTUCK, // Update progress to remove "SL appears frozen" msg.
STATE_LOGIN_PROCESS_RESPONSE, // Check authentication reply
STATE_WORLD_INIT, // Start building the world
STATE_MULTIMEDIA_INIT, // Init the rest of multimedia library
+ STATE_FONT_INIT, // Load default fonts
STATE_SEED_GRANTED_WAIT, // Wait for seed cap grant
STATE_SEED_CAP_GRANTED, // Have seed cap grant
STATE_WORLD_WAIT, // Waiting for simulator
@@ -73,9 +75,7 @@ typedef enum {
// exported symbols
extern bool gAgentMovementCompleted;
-extern LLPointer<LLImageGL> gStartImageGL;
-extern std::string gInitialOutfit;
-extern std::string gInitialOutfitGender; // "male" or "female"
+extern LLPointer<LLViewerTexture> gStartTexture;
class LLStartUp
{
@@ -92,6 +92,9 @@ public:
static void multimediaInit();
// Initialize LLViewerMedia multimedia engine.
+ // Load default fonts not already loaded at start screen
+ static void fontInit();
+
// outfit_folder_name can be a folder anywhere in your inventory,
// but the name must be a case-sensitive exact match.
// gender_name is either "male" or "female"
@@ -115,9 +118,13 @@ public:
// *HACK: On startup, if we were passed a secondlife://app/do/foo
// command URL, store it for later processing.
+ static void postStartupState();
+
private:
static std::string startupStateToString(EStartupState state);
static EStartupState gStartupState; // Do not set directly, use LLStartup::setStartupState
+ static boost::scoped_ptr<LLEventPump> sStateWatcher;
+ static boost::scoped_ptr<LLStartupListener> sListener;
};
diff --git a/indra/newview/llstartuplistener.cpp b/indra/newview/llstartuplistener.cpp
new file mode 100644
index 0000000000..5a76a297c7
--- /dev/null
+++ b/indra/newview/llstartuplistener.cpp
@@ -0,0 +1,34 @@
+/**
+ * @file llstartuplistener.cpp
+ * @author Nat Goodspeed
+ * @date 2009-12-08
+ * @brief Implementation for llstartuplistener.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "llviewerprecompiledheaders.h"
+// associated header
+#include "llstartuplistener.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llstartup.h"
+
+
+LLStartupListener::LLStartupListener(/* LLStartUp* instance */):
+ LLEventAPI("LLStartUp", "Access e.g. LLStartup::postStartupState()") /* ,
+ mStartup(instance) */
+{
+ add("postStartupState", "Refresh \"StartupState\" listeners with current startup state",
+ &LLStartupListener::postStartupState);
+}
+
+void LLStartupListener::postStartupState(const LLSD&) const
+{
+ LLStartUp::postStartupState();
+}
diff --git a/indra/newview/llstartuplistener.h b/indra/newview/llstartuplistener.h
new file mode 100644
index 0000000000..a2a4d3a08e
--- /dev/null
+++ b/indra/newview/llstartuplistener.h
@@ -0,0 +1,30 @@
+/**
+ * @file llstartuplistener.h
+ * @author Nat Goodspeed
+ * @date 2009-12-07
+ * @brief Event API to provide access to LLStartUp
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLSTARTUPLISTENER_H)
+#define LL_LLSTARTUPLISTENER_H
+
+#include "lleventapi.h"
+class LLStartUp;
+class LLSD;
+
+class LLStartupListener: public LLEventAPI
+{
+public:
+ LLStartupListener(/* LLStartUp* instance */); // all static members!
+
+private:
+ void postStartupState(const LLSD&) const;
+
+ //LLStartup* mStartup;
+};
+
+#endif /* ! defined(LL_LLSTARTUPLISTENER_H) */
diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp
index f36d12d638..8a36475510 100644
--- a/indra/newview/llstatusbar.cpp
+++ b/indra/newview/llstatusbar.cpp
@@ -40,19 +40,16 @@
#include "llcommandhandler.h"
#include "llviewercontrol.h"
#include "llfloaterbuycurrency.h"
-#include "llfloaterchat.h"
-#include "llfloaterdirectory.h" // to spawn search
#include "llfloaterlagmeter.h"
-#include "llfloaterland.h"
+#include "llpanelvolumepulldown.h"
#include "llfloaterregioninfo.h"
#include "llfloaterscriptdebug.h"
#include "llhudicon.h"
-#include "llinventoryview.h"
+#include "llnavigationbar.h"
#include "llkeyboard.h"
#include "lllineeditor.h"
#include "llmenugl.h"
-#include "llnotify.h"
-#include "llimview.h"
+#include "llsd.h"
#include "lltextbox.h"
#include "llui.h"
#include "llviewerparceloverlay.h"
@@ -60,7 +57,7 @@
#include "llviewerstats.h"
#include "llviewerwindow.h"
#include "llframetimer.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "llresmgr.h"
#include "llworld.h"
#include "llstatgraph.h"
@@ -68,17 +65,19 @@
#include "llviewerparcelmgr.h"
#include "llviewerthrottle.h"
#include "lluictrlfactory.h"
-#include "llvoiceclient.h" // for gVoiceClient
#include "lltoolmgr.h"
#include "llfocusmgr.h"
#include "llappviewer.h"
+#include "lltrans.h"
// library includes
#include "imageids.h"
+#include "llfloaterreg.h"
#include "llfontgl.h"
#include "llrect.h"
#include "llerror.h"
+#include "llnotificationsutil.h"
#include "llparcel.h"
#include "llstring.h"
#include "message.h"
@@ -91,7 +90,7 @@
// Globals
//
LLStatusBar *gStatusBar = NULL;
-S32 STATUS_BAR_HEIGHT = 0;
+S32 STATUS_BAR_HEIGHT = 26;
extern S32 MENU_BAR_HEIGHT;
@@ -107,29 +106,28 @@ const F32 ICON_TIMER_EXPIRY = 3.f; // How long the balance and health icons sho
const F32 ICON_FLASH_FREQUENCY = 2.f;
const S32 TEXT_HEIGHT = 18;
-static void onClickParcelInfo(void*);
-static void onClickBalance(void*);
-static void onClickBuyCurrency(void*);
static void onClickHealth(void*);
-static void onClickFly(void*);
-static void onClickPush(void*);
-static void onClickVoice(void*);
-static void onClickBuild(void*);
-static void onClickScripts(void*);
-static void onClickBuyLand(void*);
static void onClickScriptDebug(void*);
+static void onClickVolume(void*);
std::vector<std::string> LLStatusBar::sDays;
std::vector<std::string> LLStatusBar::sMonths;
const U32 LLStatusBar::MAX_DATE_STRING_LENGTH = 2000;
-LLStatusBar::LLStatusBar(const std::string& name, const LLRect& rect)
-: LLPanel(name, LLRect(), FALSE), // not mouse opaque
-mBalance(0),
-mHealth(100),
-mSquareMetersCredit(0),
-mSquareMetersCommitted(0)
-{
+LLStatusBar::LLStatusBar(const LLRect& rect)
+: LLPanel(),
+ mTextHealth(NULL),
+ mTextTime(NULL),
+ mSGBandwidth(NULL),
+ mSGPacketLoss(NULL),
+ mBtnVolume(NULL),
+ mBalance(0),
+ mHealth(100),
+ mSquareMetersCredit(0),
+ mSquareMetersCommitted(0)
+{
+ setRect(rect);
+
// status bar can possible overlay menus?
setMouseOpaque(FALSE);
setIsChrome(TRUE);
@@ -149,56 +147,51 @@ mSquareMetersCommitted(0)
// build date necessary data (must do after panel built)
setupDate();
- mTextParcelName = getChild<LLTextBox>("ParcelNameText" );
- mTextBalance = getChild<LLTextBox>("BalanceText" );
-
mTextHealth = getChild<LLTextBox>("HealthText" );
mTextTime = getChild<LLTextBox>("TimeText" );
+
+ getChild<LLUICtrl>("buycurrency")->setCommitCallback(
+ boost::bind(&LLStatusBar::onClickBuyCurrency, this));
+ getChild<LLUICtrl>("buyL")->setCommitCallback(
+ boost::bind(&LLStatusBar::onClickBuyCurrency, this));
- childSetAction("scriptout", onClickScriptDebug, this);
- childSetAction("health", onClickHealth, this);
- childSetAction("no_fly", onClickFly, this);
- childSetAction("buyland", onClickBuyLand, this );
- childSetAction("buycurrency", onClickBuyCurrency, this );
- childSetAction("no_build", onClickBuild, this );
- childSetAction("no_scripts", onClickScripts, this );
- childSetAction("restrictpush", onClickPush, this );
- childSetAction("status_no_voice", onClickVoice, this );
-
- childSetCommitCallback("search_editor", onCommitSearch, this);
- childSetAction("search_btn", onClickSearch, this);
+ mBtnVolume = getChild<LLButton>( "volume_btn" );
+ mBtnVolume->setClickedCallback( onClickVolume, this );
+ mBtnVolume->setMouseEnterCallback(boost::bind(&LLStatusBar::onMouseEnterVolume, this));
+ mBtnVolume->setIsChrome(TRUE);
- childSetVisible("search_editor", gSavedSettings.getBOOL("ShowSearchBar"));
- childSetVisible("search_btn", gSavedSettings.getBOOL("ShowSearchBar"));
- childSetVisible("menubar_search_bevel_bg", gSavedSettings.getBOOL("ShowSearchBar"));
+ gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&LLStatusBar::onVolumeChanged, this, _2));
- childSetActionTextbox("ParcelNameText", onClickParcelInfo );
- childSetActionTextbox("BalanceText", onClickBalance );
+ childSetAction("scriptout", onClickScriptDebug, this);
+ childSetAction("health", onClickHealth, this);
// Adding Net Stat Graph
S32 x = getRect().getWidth() - 2;
S32 y = 0;
LLRect r;
r.set( x-SIM_STAT_WIDTH, y+MENU_BAR_HEIGHT-1, x, y+1);
- mSGBandwidth = new LLStatGraph("BandwidthGraph", r);
- mSGBandwidth->setFollows(FOLLOWS_BOTTOM | FOLLOWS_RIGHT);
+ LLStatGraph::Params sgp;
+ sgp.name("BandwidthGraph");
+ sgp.rect(r);
+ sgp.follows.flags(FOLLOWS_BOTTOM | FOLLOWS_RIGHT);
+ sgp.mouse_opaque(false);
+ mSGBandwidth = LLUICtrlFactory::create<LLStatGraph>(sgp);
mSGBandwidth->setStat(&LLViewerStats::getInstance()->mKBitStat);
- std::string text = childGetText("bandwidth_tooltip") + " ";
- LLUIString bandwidth_tooltip = text; // get the text from XML until this widget is XML driven
- mSGBandwidth->setLabel(bandwidth_tooltip.getString());
mSGBandwidth->setUnits("Kbps");
mSGBandwidth->setPrecision(0);
- mSGBandwidth->setMouseOpaque(FALSE);
addChild(mSGBandwidth);
x -= SIM_STAT_WIDTH + 2;
r.set( x-SIM_STAT_WIDTH, y+MENU_BAR_HEIGHT-1, x, y+1);
- mSGPacketLoss = new LLStatGraph("PacketLossPercent", r);
- mSGPacketLoss->setFollows(FOLLOWS_BOTTOM | FOLLOWS_RIGHT);
+ //these don't seem to like being reused
+ LLStatGraph::Params pgp;
+ pgp.name("PacketLossPercent");
+ pgp.rect(r);
+ pgp.follows.flags(FOLLOWS_BOTTOM | FOLLOWS_RIGHT);
+ pgp.mouse_opaque(false);
+
+ mSGPacketLoss = LLUICtrlFactory::create<LLStatGraph>(pgp);
mSGPacketLoss->setStat(&LLViewerStats::getInstance()->mPacketsLostPercentStat);
- text = childGetText("packet_loss_tooltip") + " ";
- LLUIString packet_loss_tooltip = text; // get the text from XML until this widget is XML driven
- mSGPacketLoss->setLabel(packet_loss_tooltip.getString());
mSGPacketLoss->setUnits("%");
mSGPacketLoss->setMin(0.f);
mSGPacketLoss->setMax(5.f);
@@ -206,12 +199,25 @@ mSquareMetersCommitted(0)
mSGPacketLoss->setThreshold(1, 1.f);
mSGPacketLoss->setThreshold(2, 3.f);
mSGPacketLoss->setPrecision(1);
- mSGPacketLoss->setMouseOpaque(FALSE);
mSGPacketLoss->mPerSec = FALSE;
addChild(mSGPacketLoss);
childSetActionTextbox("stat_btn", onClickStatGraph);
+ mPanelVolumePulldown = new LLPanelVolumePulldown();
+ addChild(mPanelVolumePulldown);
+
+ LLRect volume_pulldown_rect = mPanelVolumePulldown->getRect();
+ LLButton* volbtn = getChild<LLButton>( "volume_btn" );
+ volume_pulldown_rect.setLeftTopAndSize(volbtn->getRect().mLeft -
+ (volume_pulldown_rect.getWidth() - volbtn->getRect().getWidth())/2,
+ volbtn->calcScreenRect().mBottom,
+ volume_pulldown_rect.getWidth(),
+ volume_pulldown_rect.getHeight());
+
+ mPanelVolumePulldown->setShape(volume_pulldown_rect);
+ mPanelVolumePulldown->setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT);
+ mPanelVolumePulldown->setVisible(FALSE);
}
LLStatusBar::~LLStatusBar()
@@ -233,80 +239,59 @@ LLStatusBar::~LLStatusBar()
void LLStatusBar::draw()
{
refresh();
-
- if (isBackgroundVisible())
- {
- gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0,
- LLUI::sColorsGroup->getColor("ColorDropShadow"),
- LLUI::sConfigGroup->getS32("DropShadowFloater") );
- }
LLPanel::draw();
}
+BOOL LLStatusBar::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ show_navbar_context_menu(this,x,y);
+ return TRUE;
+}
-// Per-frame updates of visibility
-void LLStatusBar::refresh()
+BOOL LLStatusBar::postBuild()
{
- // Adding Net Stat Meter back in
- F32 bwtotal = gViewerThrottle.getMaxBandwidth() / 1000.f;
- mSGBandwidth->setMin(0.f);
- mSGBandwidth->setMax(bwtotal*1.25f);
- mSGBandwidth->setThreshold(0, bwtotal*0.75f);
- mSGBandwidth->setThreshold(1, bwtotal);
- mSGBandwidth->setThreshold(2, bwtotal);
+ gMenuBarView->setRightMouseDownCallback(boost::bind(&show_navbar_context_menu, _1, _2, _3));
- // *TODO: Localize / translate time
+ return TRUE;
+}
+// Per-frame updates of visibility
+void LLStatusBar::refresh()
+{
+ bool net_stats_visible = gSavedSettings.getBOOL("ShowNetStats");
+
+ if (net_stats_visible)
+ {
+ // Adding Net Stat Meter back in
+ F32 bwtotal = gViewerThrottle.getMaxBandwidth() / 1000.f;
+ mSGBandwidth->setMin(0.f);
+ mSGBandwidth->setMax(bwtotal*1.25f);
+ mSGBandwidth->setThreshold(0, bwtotal*0.75f);
+ mSGBandwidth->setThreshold(1, bwtotal);
+ mSGBandwidth->setThreshold(2, bwtotal);
+ }
+
// Get current UTC time, adjusted for the user's clock
// being off.
time_t utc_time;
utc_time = time_corrected();
- // There's only one internal tm buffer.
- struct tm* internal_time;
-
- // Convert to Pacific, based on server's opinion of whether
- // it's daylight savings time there.
- internal_time = utc_to_pacific_time(utc_time, gPacificDaylightTime);
-
- S32 hour = internal_time->tm_hour;
- S32 min = internal_time->tm_min;
+ std::string timeStr = getString("time");
+ LLSD substitution;
+ substitution["datetime"] = (S32) utc_time;
+ LLStringUtil::format (timeStr, substitution);
+ mTextTime->setText(timeStr);
- std::string am_pm = "AM";
- if (hour > 11)
- {
- hour -= 12;
- am_pm = "PM";
- }
-
- std::string tz = "PST";
- if (gPacificDaylightTime)
- {
- tz = "PDT";
- }
- // Zero hour is 12 AM
- if (hour == 0) hour = 12;
- std::ostringstream t;
- t << std::setfill(' ') << std::setw(2) << hour << ":"
- << std::setfill('0') << std::setw(2) << min
- << " " << am_pm << " " << tz;
- mTextTime->setText(t.str());
-
- // Year starts at 1900, set the tooltip to have the date
- std::ostringstream date;
- date << sDays[internal_time->tm_wday] << ", "
- << std::setfill('0') << std::setw(2) << internal_time->tm_mday << " "
- << sMonths[internal_time->tm_mon] << " "
- << internal_time->tm_year + 1900;
- mTextTime->setToolTip(date.str());
+ // set the tooltip to have the date
+ std::string dtStr = getString("timeTooltip");
+ LLStringUtil::format (dtStr, substitution);
+ mTextTime->setToolTip (dtStr);
LLRect r;
const S32 MENU_RIGHT = gMenuBarView->getRightmostMenuEdge();
S32 x = MENU_RIGHT + MENU_PARCEL_SPACING;
S32 y = 0;
- bool search_visible = gSavedSettings.getBOOL("ShowSearchBar");
-
// reshape menu bar to its content's width
if (MENU_RIGHT != gMenuBarView->getRect().getWidth())
{
@@ -331,8 +316,8 @@ void LLStatusBar::refresh()
childSetVisible("scriptout", false);
}
- if ((region && region->getAllowDamage()) ||
- (parcel && parcel->getAllowDamage()) )
+ if (gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK &&
+ ((region && region->getAllowDamage()) || (parcel && parcel->getAllowDamage())))
{
// set visibility based on flashing
if( mHealthTimer->hasExpired() )
@@ -364,293 +349,20 @@ void LLStatusBar::refresh()
mTextHealth->setVisible(FALSE);
}
- if ((region && region->getBlockFly()) ||
- (parcel && !parcel->getAllowFly()) )
- {
- // No Fly Zone
- childGetRect( "no_fly", buttonRect );
- childSetVisible( "no_fly", true );
- r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight());
- childSetRect( "no_fly", r );
- x += buttonRect.getWidth();
- }
- else
- {
- // Fly Zone
- childSetVisible("no_fly", false);
- }
-
- BOOL no_build = parcel && !parcel->getAllowModify();
- if (no_build)
- {
- childSetVisible("no_build", TRUE);
- childGetRect( "no_build", buttonRect );
- // No Build Zone
- r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight());
- childSetRect( "no_build", r );
- x += buttonRect.getWidth();
- }
- else
- {
- childSetVisible("no_build", FALSE);
- }
-
- BOOL no_scripts = FALSE;
- if((region
- && ((region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS)
- || (region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS)))
- || (parcel && !parcel->getAllowOtherScripts()))
- {
- no_scripts = TRUE;
- }
- if (no_scripts)
- {
- // No scripts
- childSetVisible("no_scripts", TRUE);
- childGetRect( "no_scripts", buttonRect );
- r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight());
- childSetRect( "no_scripts", r );
- x += buttonRect.getWidth();
- }
- else
- {
- // Yes scripts
- childSetVisible("no_scripts", FALSE);
- }
-
- BOOL no_region_push = (region && region->getRestrictPushObject());
- BOOL no_push = no_region_push || (parcel && parcel->getRestrictPushObject());
- if (no_push)
- {
- childSetVisible("restrictpush", TRUE);
- childGetRect( "restrictpush", buttonRect );
- r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight());
- childSetRect( "restrictpush", r );
- x += buttonRect.getWidth();
- }
- else
- {
- childSetVisible("restrictpush", FALSE);
- }
-
- BOOL have_voice = parcel && parcel->getParcelFlagAllowVoice();
- if (have_voice)
- {
- childSetVisible("status_no_voice", FALSE);
- }
- else
- {
- childSetVisible("status_no_voice", TRUE);
- childGetRect( "status_no_voice", buttonRect );
- r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight());
- childSetRect( "status_no_voice", r );
- x += buttonRect.getWidth();
- }
-
- BOOL canBuyLand = parcel
- && !parcel->isPublic()
- && LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, false);
- childSetVisible("buyland", canBuyLand);
- if (canBuyLand)
- {
- //HACK: layout tweak until this is all xml
- x += 9;
- childGetRect( "buyland", buttonRect );
- r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight());
- childSetRect( "buyland", r );
- x += buttonRect.getWidth();
- }
-
- std::string location_name;
- if (region)
- {
- const LLVector3& agent_pos_region = gAgent.getPositionAgent();
- S32 pos_x = lltrunc( agent_pos_region.mV[VX] );
- S32 pos_y = lltrunc( agent_pos_region.mV[VY] );
- S32 pos_z = lltrunc( agent_pos_region.mV[VZ] );
-
- // Round the numbers based on the velocity
- LLVector3 agent_velocity = gAgent.getVelocity();
- F32 velocity_mag_sq = agent_velocity.magVecSquared();
-
- const F32 FLY_CUTOFF = 6.f; // meters/sec
- const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF;
- const F32 WALK_CUTOFF = 1.5f; // meters/sec
- const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF;
-
- if (velocity_mag_sq > FLY_CUTOFF_SQ)
- {
- pos_x -= pos_x % 4;
- pos_y -= pos_y % 4;
- }
- else if (velocity_mag_sq > WALK_CUTOFF_SQ)
- {
- pos_x -= pos_x % 2;
- pos_y -= pos_y % 2;
- }
-
- mRegionDetails.mTime = mTextTime->getText();
- mRegionDetails.mBalance = mBalance;
- mRegionDetails.mAccessString = region->getSimAccessString();
- mRegionDetails.mPing = region->getNetDetailsForLCD();
- if (parcel)
- {
- location_name = region->getName()
- + llformat(" %d, %d, %d (%s) - %s",
- pos_x, pos_y, pos_z,
- region->getSimAccessString().c_str(),
- parcel->getName().c_str());
-
- // keep these around for the LCD to use
- mRegionDetails.mRegionName = region->getName();
- mRegionDetails.mParcelName = parcel->getName();
- mRegionDetails.mX = pos_x;
- mRegionDetails.mY = pos_y;
- mRegionDetails.mZ = pos_z;
-
- mRegionDetails.mArea = parcel->getArea();
- mRegionDetails.mForSale = parcel->getForSale();
- mRegionDetails.mTraffic = LLViewerParcelMgr::getInstance()->getDwelling();
-
- if (parcel->isPublic())
- {
- mRegionDetails.mOwner = "Public";
- }
- else
- {
- if (parcel->getIsGroupOwned())
- {
- if(!parcel->getGroupID().isNull())
- {
- gCacheName->getGroupName(parcel->getGroupID(), mRegionDetails.mOwner);
- }
- else
- {
- mRegionDetails.mOwner = "Group Owned";
- }
- }
- else
- {
- // Figure out the owner's name
- gCacheName->getFullName(parcel->getOwnerID(), mRegionDetails.mOwner);
- }
- }
- }
- else
- {
- location_name = region->getName()
- + llformat(" %d, %d, %d (%s)",
- pos_x, pos_y, pos_z,
- region->getSimAccessString().c_str());
- // keep these around for the LCD to use
- mRegionDetails.mRegionName = region->getName();
- mRegionDetails.mParcelName = "Unknown";
-
- mRegionDetails.mX = pos_x;
- mRegionDetails.mY = pos_y;
- mRegionDetails.mZ = pos_z;
- mRegionDetails.mArea = 0;
- mRegionDetails.mForSale = FALSE;
- mRegionDetails.mOwner = "Unknown";
- mRegionDetails.mTraffic = 0.0f;
- }
- }
- else
- {
- // no region
- location_name = "(Unknown)";
- // keep these around for the LCD to use
- mRegionDetails.mRegionName = "Unknown";
- mRegionDetails.mParcelName = "Unknown";
- mRegionDetails.mAccessString = "Unknown";
- mRegionDetails.mX = 0;
- mRegionDetails.mY = 0;
- mRegionDetails.mZ = 0;
- mRegionDetails.mArea = 0;
- mRegionDetails.mForSale = FALSE;
- mRegionDetails.mOwner = "Unknown";
- mRegionDetails.mTraffic = 0.0f;
- }
-
- mTextParcelName->setText(location_name);
-
-
-
- // x = right edge
- // loop through: stat graphs, search btn, search text editor, money, buy money, clock
- // adjust rect
- // finally adjust parcel name rect
+ mSGBandwidth->setVisible(net_stats_visible);
+ mSGPacketLoss->setVisible(net_stats_visible);
+ childSetEnabled("stat_btn", net_stats_visible);
- S32 new_right = getRect().getWidth();
- if (search_visible)
- {
- childGetRect("search_btn", r);
- //r.translate( new_right - r.mRight, 0);
- //childSetRect("search_btn", r);
- new_right -= r.getWidth();
-
- childGetRect("search_editor", r);
- //r.translate( new_right - r.mRight, 0);
- //childSetRect("search_editor", r);
- new_right -= r.getWidth() + 6;
- }
- else
- {
- childGetRect("stat_btn", r);
- r.translate( new_right - r.mRight, 0);
- childSetRect("stat_btn", r);
- new_right -= r.getWidth() + 6;
- }
-
- // Set rects of money, buy money, time
- childGetRect("BalanceText", r);
- r.translate( new_right - r.mRight, 0);
- childSetRect("BalanceText", r);
- new_right -= r.getWidth() - 18;
-
- childGetRect("buycurrency", r);
- r.translate( new_right - r.mRight, 0);
- childSetRect("buycurrency", r);
- new_right -= r.getWidth() + 6;
-
- childGetRect("TimeText", r);
- // mTextTime->getTextPixelWidth();
- r.translate( new_right - r.mRight, 0);
- childSetRect("TimeText", r);
- // new_right -= r.getWidth() + MENU_PARCEL_SPACING;
-
-
- // Adjust region name and parcel name
- x += 8;
-
- const S32 PARCEL_RIGHT = llmin(mTextTime->getRect().mLeft, mTextParcelName->getTextPixelWidth() + x + 5);
- r.set(x+4, getRect().getHeight() - 2, PARCEL_RIGHT, 0);
- mTextParcelName->setRect(r);
-
- // Set search bar visibility
-
- if (gAgent.getCameraMode() != CAMERA_MODE_MOUSELOOK)
- {
- // don't monkey with search visibility in mouselook - it will be set
- // with setVisibleForMouselook() below
- childSetVisible("search_editor", search_visible);
- childSetVisible("search_btn", search_visible);
- childSetVisible("menubar_search_bevel_bg", search_visible);
- }
-
- mSGBandwidth->setVisible(! search_visible);
- mSGPacketLoss->setVisible(! search_visible);
- childSetEnabled("stat_btn", ! search_visible);
+ // update the master volume button state
+ BOOL mute_audio = gSavedSettings.getBOOL("MuteAudio");
+ mBtnVolume->setToggleState(mute_audio);
}
void LLStatusBar::setVisibleForMouselook(bool visible)
{
- mTextBalance->setVisible(visible);
mTextTime->setVisible(visible);
- childSetVisible("buycurrency", visible);
- childSetVisible("search_editor", visible);
- childSetVisible("search_btn", visible);
- childSetVisible("menubar_search_bevel_bg", visible);
+ getChild<LLUICtrl>("buycurrency")->setVisible(visible);
+ getChild<LLUICtrl>("buyL")->setVisible(visible);
mSGBandwidth->setVisible(visible);
mSGPacketLoss->setVisible(visible);
setBackgroundVisible(visible);
@@ -669,9 +381,20 @@ void LLStatusBar::creditBalance(S32 credit)
void LLStatusBar::setBalance(S32 balance)
{
std::string money_str = LLResMgr::getInstance()->getMonetaryString( balance );
- std::string balance_str = "L$";
- balance_str += money_str;
- mTextBalance->setText( balance_str );
+
+ LLButton* btn_buy_currency = getChild<LLButton>("buycurrency");
+ LLStringUtil::format_map_t string_args;
+ string_args["[AMT]"] = llformat("%s", money_str.c_str());
+ std::string labe_str = getString("buycurrencylabel", string_args);
+ btn_buy_currency->setLabel(labe_str);
+
+ // Resize the balance button so that the label fits it, and the button expands to the left.
+ // *TODO: LLButton should have an option where to expand.
+ {
+ S32 saved_right = btn_buy_currency->getRect().mRight;
+ btn_buy_currency->autoResize();
+ btn_buy_currency->translate(saved_right - btn_buy_currency->getRect().mRight, 0);
+ }
if (mBalance && (fabs((F32)(mBalance - balance)) > gSavedSettings.getF32("UISndMoneyChangeThreshold")))
{
@@ -775,26 +498,14 @@ S32 LLStatusBar::getSquareMetersLeft() const
return mSquareMetersCredit - mSquareMetersCommitted;
}
-static void onClickParcelInfo(void* data)
-{
- LLViewerParcelMgr::getInstance()->selectParcelAt(gAgent.getPositionGlobal());
-
- LLFloaterLand::showInstance();
-}
-
-static void onClickBalance(void* data)
-{
- onClickBuyCurrency(data);
-}
-
-static void onClickBuyCurrency(void* data)
+void LLStatusBar::onClickBuyCurrency()
{
LLFloaterBuyCurrency::buyCurrency();
}
static void onClickHealth(void* )
{
- LLNotifications::instance().add("NotSafe");
+ LLNotificationsUtil::add("NotSafe");
}
static void onClickScriptDebug(void*)
@@ -802,47 +513,18 @@ static void onClickScriptDebug(void*)
LLFloaterScriptDebug::show(LLUUID::null);
}
-static void onClickFly(void* )
-{
- LLNotifications::instance().add("NoFly");
-}
-
-static void onClickPush(void* )
-{
- LLNotifications::instance().add("PushRestricted");
-}
-
-static void onClickVoice(void* )
-{
- LLNotifications::instance().add("NoVoice");
-}
-
-static void onClickBuild(void*)
+//static
+void LLStatusBar::onMouseEnterVolume(LLUICtrl* ctrl)
{
- LLNotifications::instance().add("NoBuild");
+ // show the master volume pull-down
+ gStatusBar->mPanelVolumePulldown->setVisible(TRUE);
}
-static void onClickScripts(void*)
+static void onClickVolume(void* data)
{
- LLViewerRegion* region = gAgent.getRegion();
- if(region && region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS)
- {
- LLNotifications::instance().add("ScriptsStopped");
- }
- else if(region && region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS)
- {
- LLNotifications::instance().add("ScriptsNotRunning");
- }
- else
- {
- LLNotifications::instance().add("NoOutsideScripts");
- }
-}
-
-static void onClickBuyLand(void*)
-{
- LLViewerParcelMgr::getInstance()->selectParcelAt(gAgent.getPositionGlobal());
- LLViewerParcelMgr::getInstance()->startBuyLand();
+ // toggle the master mute setting
+ BOOL mute_audio = gSavedSettings.getBOOL("MuteAudio");
+ gSavedSettings.setBOOL("MuteAudio", !mute_audio);
}
// sets the static variables necessary for the date
@@ -909,24 +591,9 @@ void LLStatusBar::setupDate()
}
// static
-void LLStatusBar::onCommitSearch(LLUICtrl*, void* data)
-{
- // committing is the same as clicking "search"
- onClickSearch(data);
-}
-
-// static
-void LLStatusBar::onClickSearch(void* data)
-{
- LLStatusBar* self = (LLStatusBar*)data;
- std::string search_text = self->childGetText("search_editor");
- LLFloaterDirectory::showFindAll(search_text);
-}
-
-// static
void LLStatusBar::onClickStatGraph(void* data)
{
- LLFloaterLagMeter::showInstance();
+ LLFloaterReg::showInstance("lagmeter");
}
BOOL can_afford_transaction(S32 cost)
@@ -934,6 +601,10 @@ BOOL can_afford_transaction(S32 cost)
return((cost <= 0)||((gStatusBar) && (gStatusBar->getBalance() >=cost)));
}
+void LLStatusBar::onVolumeChanged(const LLSD& newvalue)
+{
+ refresh();
+}
// Implements secondlife:///app/balance/request to request a L$ balance
// update via UDP message system. JC
@@ -941,8 +612,8 @@ class LLBalanceHandler : public LLCommandHandler
{
public:
// Requires "trusted" browser/URL source
- LLBalanceHandler() : LLCommandHandler("balance", true) { }
- bool handle(const LLSD& tokens, const LLSD& query_map, LLWebBrowserCtrl* web)
+ LLBalanceHandler() : LLCommandHandler("balance", UNTRUSTED_BLOCK) { }
+ bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
{
if (tokens.size() == 1
&& tokens[0].asString() == "request")
diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h
index c5b4be035a..21a98dd753 100644
--- a/indra/newview/llstatusbar.h
+++ b/indra/newview/llstatusbar.h
@@ -47,50 +47,20 @@ class LLUICtrl;
class LLUUID;
class LLFrameTimer;
class LLStatGraph;
-
-// used by LCD screen
-class LLRegionDetails
-{
-public:
- LLRegionDetails() :
- mRegionName("Unknown"),
- mParcelName("Unknown"),
- mAccessString("Unknown"),
- mX(0),
- mY(0),
- mZ(0),
- mArea (0),
- mForSale(FALSE),
- mOwner("Unknown"),
- mTraffic(0),
- mBalance(0),
- mPing(0)
- {
- }
- std::string mRegionName;
- std::string mParcelName;
- std::string mAccessString;
- S32 mX;
- S32 mY;
- S32 mZ;
- S32 mArea;
- BOOL mForSale;
- std::string mOwner;
- F32 mTraffic;
- S32 mBalance;
- std::string mTime;
- U32 mPing;
-};
+class LLPanelVolumePulldown;
class LLStatusBar
: public LLPanel
{
public:
- LLStatusBar(const std::string& name, const LLRect& rect );
+ LLStatusBar(const LLRect& rect );
/*virtual*/ ~LLStatusBar();
/*virtual*/ void draw();
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL postBuild();
+
// MANIPULATORS
void setBalance(S32 balance);
void debitBalance(S32 debit);
@@ -116,27 +86,25 @@ public:
S32 getSquareMetersCredit() const;
S32 getSquareMetersCommitted() const;
S32 getSquareMetersLeft() const;
- LLRegionDetails mRegionDetails;
private:
// simple method to setup the part that holds the date
void setupDate();
- static void onCommitSearch(LLUICtrl*, void* data);
- static void onClickSearch(void* data);
+ void onClickBuyCurrency();
+ void onVolumeChanged(const LLSD& newvalue);
+
+ static void onMouseEnterVolume(LLUICtrl* ctrl);
static void onClickStatGraph(void* data);
private:
- LLTextBox *mTextBalance;
LLTextBox *mTextHealth;
LLTextBox *mTextTime;
- LLTextBox* mTextParcelName;
-
LLStatGraph *mSGBandwidth;
LLStatGraph *mSGPacketLoss;
- LLButton *mBtnBuyCurrency;
+ LLButton *mBtnVolume;
S32 mBalance;
S32 mHealth;
@@ -144,7 +112,7 @@ private:
S32 mSquareMetersCommitted;
LLFrameTimer* mBalanceTimer;
LLFrameTimer* mHealthTimer;
-
+ LLPanelVolumePulldown* mPanelVolumePulldown;
static std::vector<std::string> sDays;
static std::vector<std::string> sMonths;
static const U32 MAX_DATE_STRING_LENGTH;
diff --git a/indra/newview/llstylemap.cpp b/indra/newview/llstylemap.cpp
index a34b4b83f3..2485563cbc 100644
--- a/indra/newview/llstylemap.cpp
+++ b/indra/newview/llstylemap.cpp
@@ -33,88 +33,61 @@
#include "llviewerprecompiledheaders.h"
#include "llstylemap.h"
+
#include "llstring.h"
#include "llui.h"
+#include "llslurl.h"
#include "llviewercontrol.h"
#include "llagent.h"
-LLStyleMap::LLStyleMap()
-{
-}
-
-LLStyleMap::~LLStyleMap()
-{
-}
-
-LLStyleMap &LLStyleMap::instance()
-{
- static LLStyleMap style_map;
- return style_map;
-}
-
-// This is similar to the [] accessor except that if the entry doesn't already exist,
-// then this will create the entry.
-const LLStyleSP &LLStyleMap::lookupAgent(const LLUUID &source)
+const LLStyle::Params &LLStyleMap::lookupAgent(const LLUUID &source)
{
// Find this style in the map or add it if not. This map holds links to residents' profiles.
- if (find(source) == end())
+ if (mMap.find(source) == mMap.end())
{
- LLStyleSP style(new LLStyle);
- style->setVisible(true);
- style->setFontName(LLStringUtil::null);
+ LLStyle::Params style_params;
if (source != LLUUID::null && source != gAgent.getID() )
{
- style->setColor(gSavedSettings.getColor4("HTMLLinkColor"));
- std::string link = llformat("secondlife:///app/agent/%s/about",source.asString().c_str());
- style->setLinkHREF(link);
+ style_params.color.control = "HTMLLinkColor";
+ style_params.link_href =
+ LLSLURL::buildCommand("agent", source, "inspect");
}
else
{
// Make the resident's own name white and don't make the name clickable.
- style->setColor(LLColor4::white);
+ style_params.color = LLColor4::white;
}
- (*this)[source] = style;
+
+ mMap[source] = style_params;
}
- return (*this)[source];
+ return mMap[source];
}
// This is similar to lookupAgent for any generic URL encoded style.
-const LLStyleSP &LLStyleMap::lookup(const LLUUID& id, const std::string& link)
+const LLStyle::Params &LLStyleMap::lookup(const LLUUID& id, const std::string& link)
{
// Find this style in the map or add it if not.
- iterator iter = find(id);
- if (iter == end())
+ style_map_t::iterator iter = mMap.find(id);
+ if (iter == mMap.end())
{
- LLStyleSP style(new LLStyle);
- style->setVisible(true);
- style->setFontName(LLStringUtil::null);
+ LLStyle::Params style_params;
+
if (id != LLUUID::null && !link.empty())
{
- style->setColor(gSavedSettings.getColor4("HTMLLinkColor"));
- style->setLinkHREF(link);
+ style_params.color.control = "HTMLLinkColor";
+ style_params.link_href = link;
}
else
- style->setColor(LLColor4::white);
- (*this)[id] = style;
+ {
+ style_params.color = LLColor4::white;
+ }
+ mMap[id] = style_params;
}
else
{
- LLStyleSP style = (*iter).second;
- if ( style->getLinkHREF() != link )
- {
- style->setLinkHREF(link);
- }
+ iter->second.link_href = link;
}
- return (*this)[id];
+ return mMap[id];
}
-void LLStyleMap::update()
-{
- for (style_map_t::iterator iter = begin(); iter != end(); ++iter)
- {
- LLStyleSP &style = iter->second;
- // Update the link color in case it has been changed.
- style->setColor(gSavedSettings.getColor4("HTMLLinkColor"));
- }
-}
diff --git a/indra/newview/llstylemap.h b/indra/newview/llstylemap.h
index 254509ea1d..d29ff1ae28 100644
--- a/indra/newview/llstylemap.h
+++ b/indra/newview/llstylemap.h
@@ -36,24 +36,22 @@
#include "llstyle.h"
#include "lluuid.h"
+#include "llsingleton.h"
// Lightweight class for holding and managing mappings between UUIDs and links.
// Used (for example) to create clickable name links off of IM chat.
-typedef std::map<LLUUID, LLStyleSP> style_map_t;
+typedef std::map<LLUUID, LLStyle::Params> style_map_t;
-class LLStyleMap : public style_map_t
+class LLStyleMap : public LLSingleton<LLStyleMap>
{
public:
- LLStyleMap();
- ~LLStyleMap();
// Just like the [] accessor but it will add the entry in if it doesn't exist.
- const LLStyleSP &lookupAgent(const LLUUID &source);
- const LLStyleSP &lookup(const LLUUID &source, const std::string& link);
- static LLStyleMap &instance();
+ const LLStyle::Params &lookupAgent(const LLUUID &source);
+ const LLStyle::Params &lookup(const LLUUID &source, const std::string& link);
- // Forces refresh of the entries, call when something changes (e.g. link color).
- void update();
+private:
+ style_map_t mMap;
};
#endif // LL_LLSTYLE_MAP_H
diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp
index a27f0e2254..1d479bac8c 100644
--- a/indra/newview/llsurface.cpp
+++ b/indra/newview/llsurface.cpp
@@ -36,7 +36,7 @@
#include "llrender.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llpatchvertexarray.h"
#include "patch_dct.h"
#include "patch_code.h"
@@ -47,7 +47,7 @@
#include "llappviewer.h"
#include "llworld.h"
#include "llviewercontrol.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
#include "llsurfacepatch.h"
#include "llvosurfacepatch.h"
#include "llvowater.h"
@@ -68,7 +68,6 @@ LLColor4U MAX_WATER_COLOR(0, 48, 96, 240);
S32 LLSurface::sTextureSize = 256;
S32 LLSurface::sTexelsUpdated = 0;
F32 LLSurface::sTextureUpdateTime = 0.f;
-LLStat LLSurface::sTexelsUpdatedPerSecStat;
// ---------------- LLSurface:: Public Members ---------------
@@ -138,12 +137,10 @@ LLSurface::~LLSurface()
// Don't enable this until we blitz the draw pool for it as well. -- djs
if (mSTexturep)
{
- gImageList.deleteImage(mSTexturep);
mSTexturep = NULL;
}
if (mWaterTexturep)
{
- gImageList.deleteImage(mWaterTexturep);
mWaterTexturep = NULL;
}
}
@@ -215,18 +212,18 @@ void LLSurface::create(const S32 grids_per_edge,
createPatchData();
}
-LLViewerImage* LLSurface::getSTexture()
+LLViewerTexture* LLSurface::getSTexture()
{
- if (mSTexturep.notNull() && !mSTexturep->getHasGLTexture())
+ if (mSTexturep.notNull() && !mSTexturep->hasGLTexture())
{
createSTexture();
}
return mSTexturep;
}
-LLViewerImage* LLSurface::getWaterTexture()
+LLViewerTexture* LLSurface::getWaterTexture()
{
- if (mWaterTexturep.notNull() && !mWaterTexturep->getHasGLTexture())
+ if (mWaterTexturep.notNull() && !mWaterTexturep->hasGLTexture())
{
createWaterTexture();
}
@@ -237,7 +234,8 @@ void LLSurface::createSTexture()
{
if (!mSTexturep)
{
- // Fill with dummy gray data.
+ // Fill with dummy gray data.
+ // GL NOT ACTIVE HERE
LLPointer<LLImageRaw> raw = new LLImageRaw(sTextureSize, sTextureSize, 3);
U8 *default_texture = raw->getData();
for (S32 i = 0; i < sTextureSize; i++)
@@ -250,11 +248,10 @@ void LLSurface::createSTexture()
}
}
- mSTexturep = new LLViewerImage(raw, FALSE);
+ mSTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
mSTexturep->dontDiscard();
- gGL.getTexUnit(0)->bind(mSTexturep.get());
- mSTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
- gImageList.addImage(mSTexturep);
+ gGL.getTexUnit(0)->bind(mSTexturep);
+ mSTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
}
}
@@ -274,12 +271,12 @@ void LLSurface::createWaterTexture()
*(default_texture + (i*sTextureSize/2 + j)*4 + 2) = MAX_WATER_COLOR.mV[2];
*(default_texture + (i*sTextureSize/2 + j)*4 + 3) = MAX_WATER_COLOR.mV[3];
}
- }
- mWaterTexturep = new LLViewerImage(raw, FALSE);
+ }
+
+ mWaterTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
mWaterTexturep->dontDiscard();
- gGL.getTexUnit(0)->bind(mWaterTexturep.get());
+ gGL.getTexUnit(0)->bind(mWaterTexturep);
mWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
- gImageList.addImage(mWaterTexturep);
}
}
@@ -629,6 +626,7 @@ void LLSurface::updatePatchVisibilities(LLAgent &agent)
BOOL LLSurface::idleUpdate(F32 max_update_time)
{
+ LLMemType mt_ius(LLMemType::MTYPE_IDLE_UPDATE_SURFACE);
if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TERRAIN))
{
return FALSE;
@@ -1277,6 +1275,11 @@ BOOL LLSurface::generateWaterTexture(const F32 x, const F32 y,
}
}
+ if (!mWaterTexturep->hasGLTexture())
+ {
+ mWaterTexturep->createGLTexture(0, raw);
+ }
+
mWaterTexturep->setSubImage(raw, x_begin, y_begin, x_end - x_begin, y_end - y_begin);
return TRUE;
}
diff --git a/indra/newview/llsurface.h b/indra/newview/llsurface.h
index 003b2f2505..1f672d2250 100644
--- a/indra/newview/llsurface.h
+++ b/indra/newview/llsurface.h
@@ -46,7 +46,7 @@
#include "llvowater.h"
#include "llpatchvertexarray.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
class LLTimer;
class LLUUID;
@@ -133,8 +133,8 @@ public:
void setWaterHeight(F32 height);
F32 getWaterHeight() const;
- LLViewerImage *getSTexture();
- LLViewerImage *getWaterTexture();
+ LLViewerTexture *getSTexture();
+ LLViewerTexture *getWaterTexture();
BOOL hasZData() const { return mHasZData; }
void dirtyAllPatches(); // Use this to dirty all patches when changing terrain parameters
@@ -173,7 +173,6 @@ public:
static F32 sTextureUpdateTime;
static S32 sTexelsUpdated;
- static LLStat sTexelsUpdatedPerSecStat;
protected:
void createSTexture();
@@ -206,8 +205,8 @@ protected:
// The textures should never be directly initialized - use the setter methods!
- LLPointer<LLViewerImage> mSTexturep; // Texture for surface
- LLPointer<LLViewerImage> mWaterTexturep; // Water texture
+ LLPointer<LLViewerTexture> mSTexturep; // Texture for surface
+ LLPointer<LLViewerTexture> mWaterTexturep; // Water texture
LLPointer<LLVOWater> mWaterObjp;
diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp
index 5fac5fd1e4..0ce794addb 100644
--- a/indra/newview/llsurfacepatch.cpp
+++ b/indra/newview/llsurfacepatch.cpp
@@ -712,17 +712,7 @@ BOOL LLSurfacePatch::updateTexture()
if (mVObjp)
{
mVObjp->dirtyGeom();
- }
- updateCompositionStats();
- F32 tex_patch_size = meters_per_grid*grids_per_patch_edge;
- if (comp->generateTexture((F32)origin_region[VX], (F32)origin_region[VY],
- tex_patch_size, tex_patch_size))
- {
- mSTexUpdate = FALSE;
-
- // Also generate the water texture
- mSurfacep->generateWaterTexture((F32)origin_region.mdV[VX], (F32)origin_region.mdV[VY],
- tex_patch_size, tex_patch_size);
+ gPipeline.markGLRebuild(mVObjp);
return TRUE;
}
}
@@ -735,6 +725,28 @@ BOOL LLSurfacePatch::updateTexture()
}
}
+void LLSurfacePatch::updateGL()
+{
+ F32 meters_per_grid = getSurface()->getMetersPerGrid();
+ F32 grids_per_patch_edge = (F32)getSurface()->getGridsPerPatchEdge();
+
+ LLViewerRegion *regionp = getSurface()->getRegion();
+ LLVector3d origin_region = getOriginGlobal() - getSurface()->getOriginGlobal();
+
+ LLVLComposition* comp = regionp->getComposition();
+
+ updateCompositionStats();
+ F32 tex_patch_size = meters_per_grid*grids_per_patch_edge;
+ if (comp->generateTexture((F32)origin_region[VX], (F32)origin_region[VY],
+ tex_patch_size, tex_patch_size))
+ {
+ mSTexUpdate = FALSE;
+
+ // Also generate the water texture
+ mSurfacep->generateWaterTexture((F32)origin_region.mdV[VX], (F32)origin_region.mdV[VY],
+ tex_patch_size, tex_patch_size);
+ }
+}
void LLSurfacePatch::dirtyZ()
{
diff --git a/indra/newview/llsurfacepatch.h b/indra/newview/llsurfacepatch.h
index 7e84f7f6c5..ebfb64c1d8 100644
--- a/indra/newview/llsurfacepatch.h
+++ b/indra/newview/llsurfacepatch.h
@@ -35,7 +35,7 @@
#include "v3math.h"
#include "v3dmath.h"
-#include "llmemory.h"
+#include "llpointer.h"
class LLSurface;
class LLVOSurfacePatch;
@@ -90,6 +90,7 @@ public:
void updateCameraDistanceRegion( const LLVector3 &pos_region);
void updateVisibility();
+ void updateGL();
void dirtyZ(); // Dirty the z values of this patch
void setHasReceivedData();
diff --git a/indra/newview/llsyswellitem.cpp b/indra/newview/llsyswellitem.cpp
new file mode 100644
index 0000000000..0cfcfdc634
--- /dev/null
+++ b/indra/newview/llsyswellitem.cpp
@@ -0,0 +1,101 @@
+/**
+ * @file llsyswellitem.cpp
+ * @brief // TODO
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#include "llsyswellitem.h"
+
+#include "llwindow.h"
+#include "v4color.h"
+#include "lluicolortable.h"
+
+//---------------------------------------------------------------------------------
+LLSysWellItem::LLSysWellItem(const Params& p) : LLPanel(p),
+ mTitle(NULL),
+ mCloseBtn(NULL),
+ mIcon(NULL)
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_sys_well_item.xml");
+
+ mTitle = getChild<LLTextBox>("title");
+ mCloseBtn = getChild<LLButton>("close_btn");
+ mIcon = getChild<LLIconCtrl>("icon");
+
+ mTitle->setValue(p.title);
+ mCloseBtn->setClickedCallback(boost::bind(&LLSysWellItem::onClickCloseBtn,this));
+
+ mID = p.notification_id;
+}
+
+//---------------------------------------------------------------------------------
+LLSysWellItem::~LLSysWellItem()
+{
+}
+
+//---------------------------------------------------------------------------------
+void LLSysWellItem::setTitle( std::string title )
+{
+ mTitle->setValue(title);
+}
+
+//---------------------------------------------------------------------------------
+void LLSysWellItem::onClickCloseBtn()
+{
+ mOnItemClose(this);
+}
+
+//---------------------------------------------------------------------------------
+BOOL LLSysWellItem::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ BOOL res = LLPanel::handleMouseDown(x, y, mask);
+ if(!mCloseBtn->getRect().pointInRect(x, y))
+ mOnItemClick(this);
+
+ return res;
+}
+
+//---------------------------------------------------------------------------------
+void LLSysWellItem::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+ setTransparentColor(LLUIColorTable::instance().getColor( "SysWellItemSelected" ));
+}
+
+//---------------------------------------------------------------------------------
+void LLSysWellItem::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ setTransparentColor(LLUIColorTable::instance().getColor( "SysWellItemUnselected" ));
+}
+
+//---------------------------------------------------------------------------------
+
+
diff --git a/indra/newview/llsyswellitem.h b/indra/newview/llsyswellitem.h
new file mode 100644
index 0000000000..b9b00e972a
--- /dev/null
+++ b/indra/newview/llsyswellitem.h
@@ -0,0 +1,88 @@
+/**
+ * @file llsyswellitem.h
+ * @brief // TODO
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSYSWELLITEM_H
+#define LL_LLSYSWELLITEM_H
+
+#include "llpanel.h"
+#include "lltextbox.h"
+#include "llbutton.h"
+#include "lliconctrl.h"
+
+#include <string>
+
+class LLSysWellItem : public LLPanel
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ LLUUID notification_id;
+ std::string title;
+ Params() {};
+ };
+
+
+ LLSysWellItem(const Params& p);
+ virtual ~LLSysWellItem();
+
+ // title
+ void setTitle( std::string title );
+
+ // get item's ID
+ LLUUID getID() { return mID; }
+
+ // handlers
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ virtual void onMouseEnter(S32 x, S32 y, MASK mask);
+ virtual void onMouseLeave(S32 x, S32 y, MASK mask);
+
+ //callbacks
+ typedef boost::function<void (LLSysWellItem* item)> syswell_item_callback_t;
+ typedef boost::signals2::signal<void (LLSysWellItem* item)> syswell_item_signal_t;
+ syswell_item_signal_t mOnItemClose;
+ syswell_item_signal_t mOnItemClick;
+ boost::signals2::connection setOnItemCloseCallback(syswell_item_callback_t cb) { return mOnItemClose.connect(cb); }
+ boost::signals2::connection setOnItemClickCallback(syswell_item_callback_t cb) { return mOnItemClick.connect(cb); }
+
+private:
+
+ void onClickCloseBtn();
+
+ LLTextBox* mTitle;
+ LLButton* mCloseBtn;
+ LLIconCtrl* mIcon;
+ LLUUID mID;
+};
+
+#endif // LL_LLSYSWELLITEM_H
+
+
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp
new file mode 100644
index 0000000000..ba15053381
--- /dev/null
+++ b/indra/newview/llsyswellwindow.cpp
@@ -0,0 +1,992 @@
+/**
+ * @file llsyswellwindow.cpp
+ * @brief // TODO
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#include "llagent.h"
+
+#include "llflatlistview.h"
+#include "llfloaterreg.h"
+#include "llnotifications.h"
+
+#include "llsyswellwindow.h"
+
+#include "llbottomtray.h"
+#include "llscriptfloater.h"
+#include "llviewercontrol.h"
+#include "llviewerwindow.h"
+
+#include "llchiclet.h"
+#include "lltoastpanel.h"
+#include "llnotificationmanager.h"
+#include "llnotificationsutil.h"
+#include "llspeakers.h"
+
+//---------------------------------------------------------------------------------
+LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLTransientDockableFloater(NULL, true, key),
+ mChannel(NULL),
+ mMessageList(NULL),
+ mSysWellChiclet(NULL),
+ mSeparator(NULL),
+ NOTIFICATION_WELL_ANCHOR_NAME("notification_well_panel"),
+ IM_WELL_ANCHOR_NAME("im_well_panel")
+
+{
+ mTypedItemsCount[IT_NOTIFICATION] = 0;
+ mTypedItemsCount[IT_INSTANT_MESSAGE] = 0;
+ setOverlapsScreenChannel(true);
+}
+
+//---------------------------------------------------------------------------------
+BOOL LLSysWellWindow::postBuild()
+{
+ mMessageList = getChild<LLFlatListView>("notification_list");
+
+ // get a corresponding channel
+ initChannel();
+
+ LLPanel::Params params;
+ mSeparator = LLUICtrlFactory::create<LLPanel>(params);
+ LLUICtrlFactory::instance().buildPanel(mSeparator, "panel_separator.xml");
+
+ LLRect rc = mSeparator->getRect();
+ rc.setOriginAndSize(0, 0, mMessageList->getItemsRect().getWidth(), rc.getHeight());
+ mSeparator->setRect(rc);
+ mSeparator->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP);
+ mSeparator->setVisible(FALSE);
+
+ mMessageList->addItem(mSeparator);
+
+ // click on SysWell Window should clear "new message" state (and 'Lit' status). EXT-3147.
+ // mouse up callback is not called in this case.
+ setMouseDownCallback(boost::bind(&LLSysWellWindow::releaseNewMessagesState, this));
+
+ return LLTransientDockableFloater::postBuild();
+}
+
+//---------------------------------------------------------------------------------
+void LLSysWellWindow::setMinimized(BOOL minimize)
+{
+ LLTransientDockableFloater::setMinimized(minimize);
+}
+
+//---------------------------------------------------------------------------------
+void LLSysWellWindow::onStartUpToastClick(S32 x, S32 y, MASK mask)
+{
+ // just set floater visible. Screen channels will be cleared.
+ setVisible(TRUE);
+}
+
+void LLSysWellWindow::setSysWellChiclet(LLSysWellChiclet* chiclet)
+{
+ mSysWellChiclet = chiclet;
+ if(mSysWellChiclet)
+ mSysWellChiclet->updateWidget(isWindowEmpty());
+}
+//---------------------------------------------------------------------------------
+LLSysWellWindow::~LLSysWellWindow()
+{
+}
+
+//---------------------------------------------------------------------------------
+void LLSysWellWindow::removeItemByID(const LLUUID& id)
+{
+ if(mMessageList->removeItemByValue(id))
+ {
+ handleItemRemoved(IT_NOTIFICATION);
+ reshapeWindow();
+ }
+ else
+ {
+ llwarns << "Unable to remove notification from the list, ID: " << id
+ << llendl;
+ }
+
+ // hide chiclet window if there are no items left
+ if(isWindowEmpty())
+ {
+ setVisible(FALSE);
+ }
+}
+
+//---------------------------------------------------------------------------------
+//---------------------------------------------------------------------------------
+void LLSysWellWindow::initChannel()
+{
+ LLNotificationsUI::LLScreenChannelBase* channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(
+ LLUUID(gSavedSettings.getString("NotificationChannelUUID")));
+ mChannel = dynamic_cast<LLNotificationsUI::LLScreenChannel*>(channel);
+ if(NULL == mChannel)
+ {
+ llwarns << "LLSysWellWindow::initChannel() - could not get a requested screen channel" << llendl;
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLSysWellWindow::getAllowedRect(LLRect& rect)
+{
+ rect = gViewerWindow->getWorldViewRectScaled();
+}
+
+//---------------------------------------------------------------------------------
+
+
+//---------------------------------------------------------------------------------
+void LLSysWellWindow::setVisible(BOOL visible)
+{
+ if (visible)
+ {
+ if (NULL == getDockControl() && getDockTongue().notNull())
+ {
+ setDockControl(new LLDockControl(
+ LLBottomTray::getInstance()->getChild<LLView>(getAnchorViewName()), this,
+ getDockTongue(), LLDockControl::TOP, boost::bind(&LLSysWellWindow::getAllowedRect, this, _1)));
+ }
+ }
+
+ // do not show empty window
+ if (NULL == mMessageList || isWindowEmpty()) visible = FALSE;
+
+ LLTransientDockableFloater::setVisible(visible);
+
+ // update notification channel state
+ if(mChannel)
+ {
+ mChannel->updateShowToastsState();
+ mChannel->redrawToasts();
+ }
+
+ if (visible)
+ {
+ releaseNewMessagesState();
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLSysWellWindow::setDocked(bool docked, bool pop_on_undock)
+{
+ LLTransientDockableFloater::setDocked(docked, pop_on_undock);
+
+ // update notification channel state
+ if(mChannel)
+ {
+ mChannel->updateShowToastsState();
+ mChannel->redrawToasts();
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLSysWellWindow::reshapeWindow()
+{
+ // save difference between floater height and the list height to take it into account while calculating new window height
+ // it includes height from floater top to list top and from floater bottom and list bottom
+ static S32 parent_list_delta_height = getRect().getHeight() - mMessageList->getRect().getHeight();
+
+ S32 notif_list_height = mMessageList->getItemsRect().getHeight() + 2 * mMessageList->getBorderWidth();
+
+ LLRect curRect = getRect();
+
+ S32 new_window_height = notif_list_height + parent_list_delta_height;
+
+ if (new_window_height > MAX_WINDOW_HEIGHT)
+ {
+ new_window_height = MAX_WINDOW_HEIGHT;
+ }
+ S32 newY = curRect.mTop + new_window_height - curRect.getHeight();
+ S32 newWidth = curRect.getWidth() < MIN_WINDOW_WIDTH ? MIN_WINDOW_WIDTH
+ : curRect.getWidth();
+ curRect.setLeftTopAndSize(curRect.mLeft, newY, newWidth, new_window_height);
+ reshape(curRect.getWidth(), curRect.getHeight(), TRUE);
+ setRect(curRect);
+
+ // update notification channel state
+ // update on a window reshape is important only when a window is visible and docked
+ if(mChannel && getVisible() && isDocked())
+ {
+ mChannel->updateShowToastsState();
+ }
+}
+
+void LLSysWellWindow::releaseNewMessagesState()
+{
+ if (NULL != mSysWellChiclet)
+ {
+ mSysWellChiclet->setNewMessagesState(false);
+ }
+}
+
+//---------------------------------------------------------------------------------
+bool LLSysWellWindow::isWindowEmpty()
+{
+ // keep in mind, mSeparator is always in the list
+ return mMessageList->size() == 1;
+}
+
+// *TODO: mantipov: probably is deprecated
+void LLSysWellWindow::handleItemAdded(EItemType added_item_type)
+{
+ bool should_be_shown = ++mTypedItemsCount[added_item_type] == 1 && anotherTypeExists(added_item_type);
+
+ if (should_be_shown && !mSeparator->getVisible())
+ {
+ mSeparator->setVisible(TRUE);
+
+ // refresh list to recalculate mSeparator position
+ mMessageList->reshape(mMessageList->getRect().getWidth(), mMessageList->getRect().getHeight());
+ }
+
+ //fix for EXT-3254
+ //set limits for min_height.
+ S32 parent_list_delta_height = getRect().getHeight() - mMessageList->getRect().getHeight();
+
+ std::vector<LLPanel*> items;
+ mMessageList->getItems(items);
+
+ if(items.size()>1)//first item is separator
+ {
+ S32 min_height;
+ S32 min_width;
+ getResizeLimits(&min_width,&min_height);
+
+ min_height = items[1]->getRect().getHeight() + 2 * mMessageList->getBorderWidth() + parent_list_delta_height;
+
+ setResizeLimits(min_width,min_height);
+ }
+ mSysWellChiclet->updateWidget(isWindowEmpty());
+}
+
+void LLSysWellWindow::handleItemRemoved(EItemType removed_item_type)
+{
+ bool should_be_hidden = --mTypedItemsCount[removed_item_type] == 0;
+
+ if (should_be_hidden && mSeparator->getVisible())
+ {
+ mSeparator->setVisible(FALSE);
+
+ // refresh list to recalculate mSeparator position
+ mMessageList->reshape(mMessageList->getRect().getWidth(), mMessageList->getRect().getHeight());
+ }
+ mSysWellChiclet->updateWidget(isWindowEmpty());
+}
+
+bool LLSysWellWindow::anotherTypeExists(EItemType item_type)
+{
+ bool exists = false;
+ switch(item_type)
+ {
+ case IT_INSTANT_MESSAGE:
+ if (mTypedItemsCount[IT_NOTIFICATION] > 0)
+ {
+ exists = true;
+ }
+ break;
+ case IT_NOTIFICATION:
+ if (mTypedItemsCount[IT_INSTANT_MESSAGE] > 0)
+ {
+ exists = true;
+ }
+ break;
+ }
+ return exists;
+}
+
+/************************************************************************/
+/* RowPanel implementation */
+/************************************************************************/
+
+//---------------------------------------------------------------------------------
+LLIMWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID& sessionId,
+ S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId) :
+ LLPanel(LLPanel::Params()), mChiclet(NULL), mParent(parent)
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_activeim_row.xml", NULL);
+
+ // Choose which of the pre-created chiclets (IM/group) to use.
+ // The other one gets hidden.
+
+ LLIMChiclet::EType im_chiclet_type = LLIMChiclet::getIMSessionType(sessionId);
+ switch (im_chiclet_type)
+ {
+ case LLIMChiclet::TYPE_GROUP:
+ mChiclet = getChild<LLIMGroupChiclet>("group_chiclet");
+ break;
+ case LLIMChiclet::TYPE_AD_HOC:
+ mChiclet = getChild<LLAdHocChiclet>("adhoc_chiclet");
+ break;
+ case LLIMChiclet::TYPE_UNKNOWN: // assign mChiclet a non-null value anyway
+ case LLIMChiclet::TYPE_IM:
+ mChiclet = getChild<LLIMP2PChiclet>("p2p_chiclet");
+ break;
+ }
+
+ // Initialize chiclet.
+ mChiclet->setChicletSizeChangedCallback(boost::bind(&LLIMWellWindow::RowPanel::onChicletSizeChanged, this, mChiclet, _2));
+ mChiclet->enableCounterControl(true);
+ mChiclet->setCounter(chicletCounter);
+ mChiclet->setSessionId(sessionId);
+ mChiclet->setIMSessionName(name);
+ mChiclet->setOtherParticipantId(otherParticipantId);
+ mChiclet->setVisible(true);
+
+ LLTextBox* contactName = getChild<LLTextBox>("contact_name");
+ contactName->setValue(name);
+
+ mCloseBtn = getChild<LLButton>("hide_btn");
+ mCloseBtn->setCommitCallback(boost::bind(&LLIMWellWindow::RowPanel::onClosePanel, this));
+}
+
+//---------------------------------------------------------------------------------
+void LLIMWellWindow::RowPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param)
+{
+ LLTextBox* text = getChild<LLTextBox>("contact_name");
+ S32 new_text_left = mChiclet->getRect().mRight + CHICLET_HPAD;
+ LLRect text_rect = text->getRect();
+ text_rect.mLeft = new_text_left;
+ text->setRect(text_rect);
+}
+
+//---------------------------------------------------------------------------------
+LLIMWellWindow::RowPanel::~RowPanel()
+{
+}
+
+//---------------------------------------------------------------------------------
+void LLIMWellWindow::RowPanel::onClosePanel()
+{
+ gIMMgr->leaveSession(mChiclet->getSessionId());
+ // This row panel will be removed from the list in LLSysWellWindow::sessionRemoved().
+}
+
+//---------------------------------------------------------------------------------
+void LLIMWellWindow::RowPanel::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+ setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemSelected"));
+}
+
+//---------------------------------------------------------------------------------
+void LLIMWellWindow::RowPanel::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemUnselected"));
+}
+
+//---------------------------------------------------------------------------------
+// virtual
+BOOL LLIMWellWindow::RowPanel::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ // Pass the mouse down event to the chiclet (EXT-596).
+ if (!mChiclet->pointInView(x, y) && !mCloseBtn->getRect().pointInRect(x, y)) // prevent double call of LLIMChiclet::onMouseDown()
+ mChiclet->onMouseDown();
+
+ return LLPanel::handleMouseDown(x, y, mask);
+}
+
+// virtual
+BOOL LLIMWellWindow::RowPanel::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ return mChiclet->handleRightMouseDown(x, y, mask);
+}
+/************************************************************************/
+/* ObjectRowPanel implementation */
+/************************************************************************/
+
+LLIMWellWindow::ObjectRowPanel::ObjectRowPanel(const LLUUID& object_id, bool new_message/* = false*/)
+ : LLPanel()
+ , mChiclet(NULL)
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_active_object_row.xml", NULL);
+
+ initChiclet(object_id);
+
+ LLTextBox* obj_name = getChild<LLTextBox>("object_name");
+ obj_name->setValue(getObjectName(object_id));
+
+ mCloseBtn = getChild<LLButton>("hide_btn");
+ mCloseBtn->setCommitCallback(boost::bind(&LLIMWellWindow::ObjectRowPanel::onClosePanel, this));
+}
+
+//---------------------------------------------------------------------------------
+LLIMWellWindow::ObjectRowPanel::~ObjectRowPanel()
+{
+}
+
+std::string LLIMWellWindow::ObjectRowPanel::getObjectName(const LLUUID& object_id)
+{
+ using namespace LLNotificationsUI;
+ LLUUID notification_id = LLScriptFloaterManager::getInstance()->findNotificationId(object_id);
+ LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id);
+ if(!notification)
+ {
+ llwarns << "Invalid notification" << llendl;
+ return LLStringUtil::null;
+ }
+
+ std::string text;
+
+ switch(getObjectType(notification))
+ {
+ case OBJ_SCRIPT:
+ text = notification->getSubstitutions()["TITLE"].asString();
+ break;
+ case OBJ_LOAD_URL:
+ text = notification->getSubstitutions()["OBJECTNAME"].asString();
+ break;
+ case OBJ_GIVE_INVENTORY:
+ text = notification->getSubstitutions()["NAME"].asString();
+ break;
+ default:
+ text = getString("unknown_obj");
+ break;
+ }
+
+ return text;
+}
+
+//---------------------------------------------------------------------------------
+void LLIMWellWindow::ObjectRowPanel::onClosePanel()
+{
+ LLScriptFloaterManager::getInstance()->removeNotificationByObjectId(mChiclet->getSessionId());
+}
+
+//static
+LLIMWellWindow::ObjectRowPanel::object_type_map LLIMWellWindow::ObjectRowPanel::initObjectTypeMap()
+{
+ object_type_map type_map;
+ type_map["ScriptDialog"] = OBJ_SCRIPT;
+ type_map["LoadWebPage"] = OBJ_LOAD_URL;
+ type_map["ObjectGiveItem"] = OBJ_GIVE_INVENTORY;
+ return type_map;
+}
+
+// static
+LLIMWellWindow::ObjectRowPanel::EObjectType LLIMWellWindow::ObjectRowPanel::getObjectType(const LLNotificationPtr& notification)
+{
+ if(!notification)
+ {
+ llwarns << "Invalid notification" << llendl;
+ return OBJ_UNKNOWN;
+ }
+
+ static object_type_map type_map = initObjectTypeMap();
+ std::string name = notification->getName();
+ object_type_map::const_iterator it = type_map.find(name);
+ if(it != type_map.end())
+ {
+ return it->second;
+ }
+
+ llwarns << "Unknown object type" << llendl;
+ return OBJ_UNKNOWN;
+}
+
+void LLIMWellWindow::ObjectRowPanel::initChiclet(const LLUUID& object_id, bool new_message/* = false*/)
+{
+ using namespace LLNotificationsUI;
+ LLUUID notification_id = LLScriptFloaterManager::getInstance()->findNotificationId(object_id);
+ LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id);
+ if(!notification)
+ {
+ llwarns << "Invalid notification" << llendl;
+ return;
+ }
+
+ // Choose which of the pre-created chiclets to use.
+ switch(getObjectType(notification))
+ {
+ case OBJ_GIVE_INVENTORY:
+ mChiclet = getChild<LLInvOfferChiclet>("inv_offer_chiclet");
+ break;
+ default:
+ mChiclet = getChild<LLScriptChiclet>("object_chiclet");
+ break;
+ }
+
+ mChiclet->setVisible(true);
+ mChiclet->setSessionId(object_id);
+// mChiclet->setShowNewMessagesIcon(new_message);
+}
+
+//---------------------------------------------------------------------------------
+void LLIMWellWindow::ObjectRowPanel::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+ setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemSelected"));
+}
+
+//---------------------------------------------------------------------------------
+void LLIMWellWindow::ObjectRowPanel::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemUnselected"));
+}
+
+//---------------------------------------------------------------------------------
+// virtual
+BOOL LLIMWellWindow::ObjectRowPanel::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ // Pass the mouse down event to the chiclet (EXT-596).
+ if (!mChiclet->pointInView(x, y) && !mCloseBtn->getRect().pointInRect(x, y)) // prevent double call of LLIMChiclet::onMouseDown()
+ mChiclet->onMouseDown();
+
+ return LLPanel::handleMouseDown(x, y, mask);
+}
+
+// virtual
+BOOL LLIMWellWindow::ObjectRowPanel::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ return mChiclet->handleRightMouseDown(x, y, mask);
+}
+
+/************************************************************************/
+/* LLNotificationWellWindow implementation */
+/************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////
+// PUBLIC METHODS
+LLNotificationWellWindow::LLNotificationWellWindow(const LLSD& key)
+: LLSysWellWindow(key)
+{
+ // init connections to the list's update events
+ connectListUpdaterToSignal("notify");
+ connectListUpdaterToSignal("groupnotify");
+ connectListUpdaterToSignal("offer");
+}
+
+// static
+LLNotificationWellWindow* LLNotificationWellWindow::getInstance(const LLSD& key /*= LLSD()*/)
+{
+ return LLFloaterReg::getTypedInstance<LLNotificationWellWindow>("notification_well_window", key);
+}
+
+// virtual
+BOOL LLNotificationWellWindow::postBuild()
+{
+ BOOL rv = LLSysWellWindow::postBuild();
+ setTitle(getString("title_notification_well_window"));
+ return rv;
+}
+
+// virtual
+void LLNotificationWellWindow::setVisible(BOOL visible)
+{
+ if (visible)
+ {
+ // when Notification channel is cleared, storable toasts will be added into the list.
+ clearScreenChannels();
+ }
+
+ LLSysWellWindow::setVisible(visible);
+}
+
+//---------------------------------------------------------------------------------
+void LLNotificationWellWindow::addItem(LLSysWellItem::Params p)
+{
+ LLSD value = p.notification_id;
+ // do not add clones
+ if( mMessageList->getItemByValue(value))
+ return;
+
+ LLSysWellItem* new_item = new LLSysWellItem(p);
+ if (mMessageList->addItem(new_item, value, ADD_TOP))
+ {
+ handleItemAdded(IT_NOTIFICATION);
+
+ reshapeWindow();
+
+ new_item->setOnItemCloseCallback(boost::bind(&LLNotificationWellWindow::onItemClose, this, _1));
+ new_item->setOnItemClickCallback(boost::bind(&LLNotificationWellWindow::onItemClick, this, _1));
+ }
+ else
+ {
+ llwarns << "Unable to add Notification into the list, notification ID: " << p.notification_id
+ << ", title: " << p.title
+ << llendl;
+
+ new_item->die();
+ }
+}
+
+void LLNotificationWellWindow::closeAll()
+{
+ // Need to clear notification channel, to add storable toasts into the list.
+ clearScreenChannels();
+ std::vector<LLPanel*> items;
+ mMessageList->getItems(items);
+ for (std::vector<LLPanel*>::iterator
+ iter = items.begin(),
+ iter_end = items.end();
+ iter != iter_end; ++iter)
+ {
+ LLSysWellItem* sys_well_item = dynamic_cast<LLSysWellItem*>(*iter);
+ if (sys_well_item)
+ onItemClose(sys_well_item);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// PRIVATE METHODS
+void LLNotificationWellWindow::initChannel()
+{
+ LLSysWellWindow::initChannel();
+ if(mChannel)
+ {
+ mChannel->setOnStoreToastCallback(boost::bind(&LLNotificationWellWindow::onStoreToast, this, _1, _2));
+ }
+}
+
+void LLNotificationWellWindow::clearScreenChannels()
+{
+ // 1 - remove StartUp toast and channel if present
+ if(!LLNotificationsUI::LLScreenChannel::getStartUpToastShown())
+ {
+ LLNotificationsUI::LLChannelManager::getInstance()->onStartUpToastClose();
+ }
+
+ // 2 - remove toasts in Notification channel
+ if(mChannel)
+ {
+ mChannel->removeAndStoreAllStorableToasts();
+ }
+}
+
+void LLNotificationWellWindow::onStoreToast(LLPanel* info_panel, LLUUID id)
+{
+ LLSysWellItem::Params p;
+ p.notification_id = id;
+ p.title = static_cast<LLToastPanel*>(info_panel)->getTitle();
+ addItem(p);
+}
+
+void LLNotificationWellWindow::connectListUpdaterToSignal(std::string notification_type)
+{
+ LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance();
+ LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type);
+ if(n_handler)
+ {
+ n_handler->setNotificationIDCallback(boost::bind(&LLNotificationWellWindow::removeItemByID, this, _1));
+ }
+ else
+ {
+ llwarns << "LLSysWellWindow::connectListUpdaterToSignal() - could not get a handler for '" << notification_type <<"' type of notifications" << llendl;
+ }
+}
+
+void LLNotificationWellWindow::onItemClick(LLSysWellItem* item)
+{
+ LLUUID id = item->getID();
+ LLFloaterReg::showInstance("inspect_toast", id);
+}
+
+void LLNotificationWellWindow::onItemClose(LLSysWellItem* item)
+{
+ LLUUID id = item->getID();
+ removeItemByID(id);
+ if(mChannel)
+ mChannel->killToastByNotificationID(id);
+}
+
+
+
+/************************************************************************/
+/* LLIMWellWindow implementation */
+/************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////
+// PUBLIC METHODS
+LLIMWellWindow::LLIMWellWindow(const LLSD& key)
+: LLSysWellWindow(key)
+{
+ LLIMMgr::getInstance()->addSessionObserver(this);
+ LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLIMWellWindow::findIMChiclet, this, _1));
+ LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLIMWellWindow::findObjectChiclet, this, _1));
+}
+
+LLIMWellWindow::~LLIMWellWindow()
+{
+ LLIMMgr::getInstance()->removeSessionObserver(this);
+}
+
+// static
+LLIMWellWindow* LLIMWellWindow::getInstance(const LLSD& key /*= LLSD()*/)
+{
+ return LLFloaterReg::getTypedInstance<LLIMWellWindow>("im_well_window", key);
+}
+
+BOOL LLIMWellWindow::postBuild()
+{
+ BOOL rv = LLSysWellWindow::postBuild();
+ setTitle(getString("title_im_well_window"));
+ return rv;
+}
+
+//virtual
+void LLIMWellWindow::sessionAdded(const LLUUID& session_id,
+ const std::string& name, const LLUUID& other_participant_id)
+{
+ LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id);
+ if (!session) return;
+
+ // no need to spawn chiclets for participants in P2P calls called through Avaline
+ if (session->isP2P() && session->isOtherParticipantAvaline()) return;
+
+ if (mMessageList->getItemByValue(session_id)) return;
+
+ addIMRow(session_id, 0, name, other_participant_id);
+ reshapeWindow();
+}
+
+//virtual
+void LLIMWellWindow::sessionRemoved(const LLUUID& sessionId)
+{
+ delIMRow(sessionId);
+ reshapeWindow();
+}
+
+//virtual
+void LLIMWellWindow::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id)
+{
+ //for outgoing ad-hoc and group im sessions only
+ LLChiclet* chiclet = findIMChiclet(old_session_id);
+ if (chiclet)
+ {
+ chiclet->setSessionId(new_session_id);
+ mMessageList->updateValue(old_session_id, new_session_id);
+ }
+}
+
+LLChiclet* LLIMWellWindow::findObjectChiclet(const LLUUID& object_id)
+{
+ LLChiclet* res = NULL;
+ ObjectRowPanel* panel = mMessageList->getTypedItemByValue<ObjectRowPanel>(object_id);
+ if (panel != NULL)
+ {
+ res = panel->mChiclet;
+ }
+
+ return res;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// PRIVATE METHODS
+LLChiclet* LLIMWellWindow::findIMChiclet(const LLUUID& sessionId)
+{
+ LLChiclet* res = NULL;
+ RowPanel* panel = mMessageList->getTypedItemByValue<RowPanel>(sessionId);
+ if (panel != NULL)
+ {
+ res = panel->mChiclet;
+ }
+
+ return res;
+}
+
+//---------------------------------------------------------------------------------
+void LLIMWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter,
+ const std::string& name, const LLUUID& otherParticipantId)
+{
+ RowPanel* item = new RowPanel(this, sessionId, chicletCounter, name, otherParticipantId);
+ if (mMessageList->insertItemAfter(mSeparator, item, sessionId))
+ {
+ handleItemAdded(IT_INSTANT_MESSAGE);
+ }
+ else
+ {
+ llwarns << "Unable to add IM Row into the list, sessionID: " << sessionId
+ << ", name: " << name
+ << ", other participant ID: " << otherParticipantId
+ << llendl;
+
+ item->die();
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLIMWellWindow::delIMRow(const LLUUID& sessionId)
+{
+ //fix for EXT-3252
+ //without this line LLIMWellWindow receive onFocusLost
+ //and hide itself. It was becaue somehow LLIMChicklet was in focus group for
+ //LLIMWellWindow...
+ //But I didn't find why this happen..
+ gFocusMgr.clearLastFocusForGroup(this);
+
+ if (mMessageList->removeItemByValue(sessionId))
+ {
+ handleItemRemoved(IT_INSTANT_MESSAGE);
+ }
+ else
+ {
+ llwarns << "Unable to remove IM Row from the list, sessionID: " << sessionId
+ << llendl;
+ }
+
+ // remove all toasts that belong to this session from a screen
+ if(mChannel)
+ mChannel->removeToastsBySessionID(sessionId);
+
+ // hide chiclet window if there are no items left
+ if(isWindowEmpty())
+ {
+ setVisible(FALSE);
+ }
+ else
+ {
+ setFocus(true);
+ }
+}
+
+void LLIMWellWindow::addObjectRow(const LLUUID& object_id, bool new_message/* = false*/)
+{
+ if (mMessageList->getItemByValue(object_id) == NULL)
+ {
+ ObjectRowPanel* item = new ObjectRowPanel(object_id, new_message);
+ if (mMessageList->insertItemAfter(mSeparator, item, object_id))
+ {
+ handleItemAdded(IT_INSTANT_MESSAGE);
+ }
+ else
+ {
+ llwarns << "Unable to add Object Row into the list, objectID: " << object_id << llendl;
+ item->die();
+ }
+ reshapeWindow();
+ }
+}
+
+void LLIMWellWindow::removeObjectRow(const LLUUID& object_id)
+{
+ if (mMessageList->removeItemByValue(object_id))
+ {
+ handleItemRemoved(IT_INSTANT_MESSAGE);
+ }
+ else
+ {
+ llwarns << "Unable to remove Object Row from the list, objectID: " << object_id << llendl;
+ }
+
+ reshapeWindow();
+ // hide chiclet window if there are no items left
+ if(isWindowEmpty())
+ {
+ setVisible(FALSE);
+ }
+}
+
+
+void LLIMWellWindow::addIMRow(const LLUUID& session_id)
+{
+ if (hasIMRow(session_id)) return;
+
+ LLIMModel* im_model = LLIMModel::getInstance();
+ addIMRow(session_id, 0, im_model->getName(session_id), im_model->getOtherParticipantID(session_id));
+ reshapeWindow();
+}
+
+bool LLIMWellWindow::hasIMRow(const LLUUID& session_id)
+{
+ return mMessageList->getItemByValue(session_id);
+}
+
+void LLIMWellWindow::closeAll()
+{
+ // Generate an ignorable alert dialog if there is an active voice IM sesion
+ bool need_confirmation = false;
+ const LLIMModel& im_model = LLIMModel::instance();
+ std::vector<LLSD> values;
+ mMessageList->getValues(values);
+ for (std::vector<LLSD>::iterator
+ iter = values.begin(),
+ iter_end = values.end();
+ iter != iter_end; ++iter)
+ {
+ LLIMSpeakerMgr* speaker_mgr = im_model.getSpeakerManager(*iter);
+ if (speaker_mgr && speaker_mgr->isVoiceActive())
+ {
+ need_confirmation = true;
+ break;
+ }
+ }
+ if ( need_confirmation )
+ {
+ //Bring up a confirmation dialog
+ LLNotificationsUtil::add
+ ("ConfirmCloseAll", LLSD(), LLSD(),
+ boost::bind(&LLIMWellWindow::confirmCloseAll, this, _1, _2));
+ }
+ else
+ {
+ closeAllImpl();
+ }
+}
+
+void LLIMWellWindow::closeAllImpl()
+{
+ std::vector<LLSD> values;
+ mMessageList->getValues(values);
+
+ for (std::vector<LLSD>::iterator
+ iter = values.begin(),
+ iter_end = values.end();
+ iter != iter_end; ++iter)
+ {
+ LLPanel* panel = mMessageList->getItemByValue(*iter);
+
+ RowPanel* im_panel = dynamic_cast <RowPanel*> (panel);
+ if (im_panel)
+ {
+ gIMMgr->leaveSession(*iter);
+ continue;
+ }
+
+ ObjectRowPanel* obj_panel = dynamic_cast <ObjectRowPanel*> (panel);
+ if (obj_panel)
+ {
+ LLScriptFloaterManager::instance()
+ .removeNotificationByObjectId(*iter);
+ }
+ }
+}
+
+bool LLIMWellWindow::confirmCloseAll(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ switch(option)
+ {
+ case 0:
+ {
+ closeAllImpl();
+ return true;
+ }
+ default:
+ break;
+ }
+ return false;
+}
+
+// EOF
diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h
new file mode 100644
index 0000000000..0c81d1f369
--- /dev/null
+++ b/indra/newview/llsyswellwindow.h
@@ -0,0 +1,273 @@
+/**
+ * @file llsyswellwindow.h
+ * @brief // TODO
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSYSWELLWINDOW_H
+#define LL_LLSYSWELLWINDOW_H
+
+#include "llsyswellitem.h"
+
+#include "lltransientdockablefloater.h"
+#include "llbutton.h"
+#include "llscreenchannel.h"
+#include "llscrollcontainer.h"
+#include "llimview.h"
+
+#include "boost/shared_ptr.hpp"
+
+class LLFlatListView;
+class LLChiclet;
+class LLIMChiclet;
+class LLScriptChiclet;
+class LLSysWellChiclet;
+
+
+class LLSysWellWindow : public LLTransientDockableFloater
+{
+public:
+ LLSysWellWindow(const LLSD& key);
+ ~LLSysWellWindow();
+ BOOL postBuild();
+
+ // other interface functions
+ // check is window empty
+ bool isWindowEmpty();
+
+ // Operating with items
+ void removeItemByID(const LLUUID& id);
+
+ // Operating with outfit
+ virtual void setVisible(BOOL visible);
+ void adjustWindowPosition();
+ /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true);
+ // override LLFloater's minimization according to EXT-1216
+ /*virtual*/ void setMinimized(BOOL minimize);
+
+ void onStartUpToastClick(S32 x, S32 y, MASK mask);
+
+ void setSysWellChiclet(LLSysWellChiclet* chiclet);
+
+ // size constants for the window and for its elements
+ static const S32 MAX_WINDOW_HEIGHT = 200;
+ static const S32 MIN_WINDOW_WIDTH = 318;
+
+protected:
+
+ typedef enum{
+ IT_NOTIFICATION,
+ IT_INSTANT_MESSAGE
+ }EItemType;
+
+ // gets a rect that bounds possible positions for the SysWellWindow on a screen (EXT-1111)
+ void getAllowedRect(LLRect& rect);
+
+
+ // init Window's channel
+ virtual void initChannel();
+ void handleItemAdded(EItemType added_item_type);
+ void handleItemRemoved(EItemType removed_item_type);
+ bool anotherTypeExists(EItemType item_type) ;
+
+ const std::string NOTIFICATION_WELL_ANCHOR_NAME;
+ const std::string IM_WELL_ANCHOR_NAME;
+ virtual const std::string& getAnchorViewName() = 0;
+
+ void reshapeWindow();
+ void releaseNewMessagesState();
+
+ // pointer to a corresponding channel's instance
+ LLNotificationsUI::LLScreenChannel* mChannel;
+ LLFlatListView* mMessageList;
+
+ /**
+ * Reference to an appropriate Well chiclet to release "new message" state. EXT-3147
+ */
+ LLSysWellChiclet* mSysWellChiclet;
+
+ /**
+ * Special panel which is used as separator of Notifications & IM Rows.
+ * It is always presents in the list and shown when it is necessary.
+ * It should be taken into account when reshaping and checking list size
+ */
+ LLPanel* mSeparator;
+
+ typedef std::map<EItemType, S32> typed_items_count_t;
+ typed_items_count_t mTypedItemsCount;
+
+};
+
+/**
+ * Class intended to manage incoming notifications.
+ *
+ * It contains a list of notifications that have not been responded to.
+ */
+class LLNotificationWellWindow : public LLSysWellWindow
+{
+public:
+ LLNotificationWellWindow(const LLSD& key);
+ static LLNotificationWellWindow* getInstance(const LLSD& key = LLSD());
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void setVisible(BOOL visible);
+
+ // Operating with items
+ void addItem(LLSysWellItem::Params p);
+
+ // Closes all notifications and removes them from the Notification Well
+ void closeAll();
+
+protected:
+ /*virtual*/ const std::string& getAnchorViewName() { return NOTIFICATION_WELL_ANCHOR_NAME; }
+
+private:
+ // init Window's channel
+ void initChannel();
+ void clearScreenChannels();
+
+
+ void onStoreToast(LLPanel* info_panel, LLUUID id);
+
+ // connect counter and list updaters to the corresponding signals
+ void connectListUpdaterToSignal(std::string notification_type);
+
+ // Handlers
+ void onItemClick(LLSysWellItem* item);
+ void onItemClose(LLSysWellItem* item);
+
+ // ID of a toast loaded by user (by clicking notification well item)
+ LLUUID mLoadedToastId;
+
+};
+
+/**
+ * Class intended to manage incoming messages in IM chats.
+ *
+ * It contains a list list of all active IM sessions.
+ */
+class LLIMWellWindow : public LLSysWellWindow, LLIMSessionObserver, LLInitClass<LLIMWellWindow>
+{
+public:
+ LLIMWellWindow(const LLSD& key);
+ ~LLIMWellWindow();
+
+ static LLIMWellWindow* getInstance(const LLSD& key = LLSD());
+ static void initClass() { getInstance(); }
+
+ /*virtual*/ BOOL postBuild();
+
+ // LLIMSessionObserver observe triggers
+ /*virtual*/ void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id);
+ /*virtual*/ void sessionRemoved(const LLUUID& session_id);
+ /*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id);
+
+ void addObjectRow(const LLUUID& object_id, bool new_message = false);
+ void removeObjectRow(const LLUUID& object_id);
+
+ void addIMRow(const LLUUID& session_id);
+ bool hasIMRow(const LLUUID& session_id);
+
+ void closeAll();
+
+protected:
+ /*virtual*/ const std::string& getAnchorViewName() { return IM_WELL_ANCHOR_NAME; }
+
+private:
+ LLChiclet * findIMChiclet(const LLUUID& sessionId);
+ LLChiclet* findObjectChiclet(const LLUUID& object_id);
+
+ void addIMRow(const LLUUID& sessionId, S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId);
+ void delIMRow(const LLUUID& sessionId);
+ bool confirmCloseAll(const LLSD& notification, const LLSD& response);
+ void closeAllImpl();
+
+ /**
+ * Scrolling row panel.
+ */
+ class RowPanel: public LLPanel
+ {
+ public:
+ RowPanel(const LLSysWellWindow* parent, const LLUUID& sessionId, S32 chicletCounter,
+ const std::string& name, const LLUUID& otherParticipantId);
+ virtual ~RowPanel();
+ void onMouseEnter(S32 x, S32 y, MASK mask);
+ void onMouseLeave(S32 x, S32 y, MASK mask);
+ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+
+ private:
+ static const S32 CHICLET_HPAD = 10;
+ void onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param);
+ void onClosePanel();
+ public:
+ LLIMChiclet* mChiclet;
+ private:
+ LLButton* mCloseBtn;
+ const LLSysWellWindow* mParent;
+ };
+
+ class ObjectRowPanel: public LLPanel
+ {
+ typedef enum e_object_type
+ {
+ OBJ_UNKNOWN,
+
+ OBJ_SCRIPT,
+ OBJ_GIVE_INVENTORY,
+ OBJ_LOAD_URL
+ }EObjectType;
+
+ public:
+ ObjectRowPanel(const LLUUID& object_id, bool new_message = false);
+ virtual ~ObjectRowPanel();
+ /*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask);
+ /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+
+ private:
+ void onClosePanel();
+ static EObjectType getObjectType(const LLNotificationPtr& notification);
+ void initChiclet(const LLUUID& object_id, bool new_message = false);
+ std::string getObjectName(const LLUUID& object_id);
+
+ typedef std::map<std::string, EObjectType> object_type_map;
+ static object_type_map initObjectTypeMap();
+ public:
+ LLIMChiclet* mChiclet;
+ private:
+ LLButton* mCloseBtn;
+ };
+};
+
+#endif // LL_LLSYSWELLWINDOW_H
+
+
+
diff --git a/indra/newview/llteleporthistory.cpp b/indra/newview/llteleporthistory.cpp
new file mode 100644
index 0000000000..ce00dec802
--- /dev/null
+++ b/indra/newview/llteleporthistory.cpp
@@ -0,0 +1,201 @@
+/**
+ * @file llteleporthistory.cpp
+ * @brief Teleport history
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llteleporthistory.h"
+
+#include "llparcel.h"
+#include "llsdserialize.h"
+
+#include "llagent.h"
+#include "llslurl.h"
+#include "llviewercontrol.h" // for gSavedSettings
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+#include "llworldmap.h"
+#include "llagentui.h"
+
+//////////////////////////////////////////////////////////////////////////////
+// LLTeleportHistoryItem
+//////////////////////////////////////////////////////////////////////////////
+
+const std::string& LLTeleportHistoryItem::getTitle() const
+{
+ return gSavedSettings.getBOOL("NavBarShowCoordinates") ? mFullTitle : mTitle;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// LLTeleportHistory
+//////////////////////////////////////////////////////////////////////////////
+
+LLTeleportHistory::LLTeleportHistory():
+ mCurrentItem(-1),
+ mRequestedItem(-1),
+ mGotInitialUpdate(false)
+{
+ mTeleportFinishedConn = LLViewerParcelMgr::getInstance()->
+ setTeleportFinishedCallback(boost::bind(&LLTeleportHistory::updateCurrentLocation, this, _1));
+ mTeleportFailedConn = LLViewerParcelMgr::getInstance()->
+ setTeleportFailedCallback(boost::bind(&LLTeleportHistory::onTeleportFailed, this));
+}
+
+LLTeleportHistory::~LLTeleportHistory()
+{
+ mTeleportFinishedConn.disconnect();
+ mTeleportFailedConn.disconnect();
+}
+
+void LLTeleportHistory::goToItem(int idx)
+
+{
+ // Validate specified index.
+ if (idx < 0 || idx >= (int)mItems.size())
+ {
+ llwarns << "Invalid teleport history index (" << idx << ") specified" << llendl;
+ dump();
+ return;
+ }
+
+ if (idx == mCurrentItem)
+ {
+ llwarns << "Will not teleport to the same location." << llendl;
+ dump();
+ return;
+ }
+
+ // Attempt to teleport to the requested item.
+ gAgent.teleportViaLocation(mItems[idx].mGlobalPos);
+ mRequestedItem = idx;
+}
+
+void LLTeleportHistory::onTeleportFailed()
+{
+ // Are we trying to teleport within the history?
+ if (mRequestedItem != -1)
+ {
+ // Not anymore.
+ mRequestedItem = -1;
+ }
+}
+
+void LLTeleportHistory::updateCurrentLocation(const LLVector3d& new_pos)
+{
+ if (mRequestedItem != -1) // teleport within the history in progress?
+ {
+ mCurrentItem = mRequestedItem;
+ mRequestedItem = -1;
+ }
+ else
+ {
+ // If we're getting the initial location update
+ // while we already have a (loaded) non-empty history,
+ // there's no need to purge forward items or add a new item.
+
+ if (mGotInitialUpdate || mItems.size() == 0)
+ {
+ // Purge forward items (if any).
+ if(mItems.size())
+ mItems.erase (mItems.begin() + mCurrentItem + 1, mItems.end());
+
+ // Append an empty item to the history and make it current.
+ mItems.push_back(LLTeleportHistoryItem("", LLVector3d()));
+ mCurrentItem++;
+ }
+
+ // Update current history item.
+ if (mCurrentItem < 0 || mCurrentItem >= (int) mItems.size()) // sanity check
+ {
+ llwarns << "Invalid current item. (this should not happen)" << llendl;
+ return;
+ }
+ LLVector3 new_pos_local = gAgent.getPosAgentFromGlobal(new_pos);
+ mItems[mCurrentItem].mFullTitle = getCurrentLocationTitle(true, new_pos_local);
+ mItems[mCurrentItem].mTitle = getCurrentLocationTitle(false, new_pos_local);
+ mItems[mCurrentItem].mGlobalPos = new_pos;
+ mItems[mCurrentItem].mRegionID = gAgent.getRegion()->getRegionID();
+ }
+
+ dump();
+
+ if (!mGotInitialUpdate)
+ mGotInitialUpdate = true;
+
+ // Signal the interesting party that we've changed.
+ onHistoryChanged();
+}
+
+boost::signals2::connection LLTeleportHistory::setHistoryChangedCallback(history_callback_t cb)
+{
+ return mHistoryChangedSignal.connect(cb);
+}
+
+void LLTeleportHistory::onHistoryChanged()
+{
+ mHistoryChangedSignal();
+}
+
+void LLTeleportHistory::purgeItems()
+{
+ if (mItems.size() > 0)
+ {
+ mItems.erase(mItems.begin(), mItems.end()-1);
+ }
+ // reset the count
+ mRequestedItem = -1;
+ mCurrentItem = 0;
+}
+
+// static
+std::string LLTeleportHistory::getCurrentLocationTitle(bool full, const LLVector3& local_pos_override)
+{
+ std::string location_name;
+ LLAgentUI::ELocationFormat fmt = full ? LLAgentUI::LOCATION_FORMAT_NO_MATURITY : LLAgentUI::LOCATION_FORMAT_NORMAL;
+
+ if (!LLAgentUI::buildLocationString(location_name, fmt, local_pos_override)) location_name = "Unknown";
+ return location_name;
+}
+
+void LLTeleportHistory::dump() const
+{
+ llinfos << "Teleport history dump (" << mItems.size() << " items):" << llendl;
+
+ for (size_t i=0; i<mItems.size(); i++)
+ {
+ std::stringstream line;
+ line << ((i == mCurrentItem) ? " * " : " ");
+ line << i << ": " << mItems[i].mTitle;
+ line << " REGION_ID: " << mItems[i].mRegionID;
+ line << ", pos: " << mItems[i].mGlobalPos;
+ llinfos << line.str() << llendl;
+ }
+}
diff --git a/indra/newview/llteleporthistory.h b/indra/newview/llteleporthistory.h
new file mode 100644
index 0000000000..a82bec7c4f
--- /dev/null
+++ b/indra/newview/llteleporthistory.h
@@ -0,0 +1,238 @@
+/**
+ * @file llteleporthistory.h
+ * @brief Teleport history
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTELEPORTHISTORY_H
+#define LL_LLTELEPORTHISTORY_H
+
+#include "llsingleton.h" // for LLSingleton
+
+#include <vector>
+#include <string>
+#include <boost/function.hpp>
+#include <boost/signals2.hpp>
+
+
+/**
+ * An item of the teleport history.
+ *
+ * Contains the location's global coordinates and its title.
+ */
+class LLTeleportHistoryItem
+{
+public:
+ LLTeleportHistoryItem()
+ {}
+
+ LLTeleportHistoryItem(std::string title, LLVector3d global_pos)
+ : mTitle(title), mGlobalPos(global_pos)
+ {}
+
+ /**
+ * @return title formatted according to the current value of the
+ * NavBarShowCoordinates setting.
+ */
+ const std::string& getTitle() const;
+
+ std::string mTitle; // human-readable location title
+ std::string mFullTitle; // human-readable location title including coordinates
+ LLVector3d mGlobalPos; // global position
+ LLUUID mRegionID; // region ID for getting the region info
+};
+
+/**
+ * Teleport history.
+ *
+ * Along with the navigation bar "Back" and "Forward" buttons
+ * implements web browser-like navigation functionality.
+ *
+ * @see LLNavigationBar
+ */
+class LLTeleportHistory: public LLSingleton<LLTeleportHistory>
+{
+ LOG_CLASS(LLTeleportHistory);
+
+public:
+
+ typedef std::vector<LLTeleportHistoryItem> slurl_list_t;
+ typedef boost::function<void()> history_callback_t;
+ typedef boost::signals2::signal<void()> history_signal_t;
+
+ LLTeleportHistory();
+ ~LLTeleportHistory();
+
+ /**
+ * Go back in the history.
+ */
+ void goBack() { goToItem(getCurrentItemIndex() - 1); }
+
+ /**
+ * Go forward in the history.
+ */
+ void goForward() { goToItem(getCurrentItemIndex() + 1); }
+
+ /**
+ * Go to specific item in the history.
+ *
+ * The item is specified by its index (starting from 0).
+ */
+ void goToItem(int idx);
+
+ /**
+ * @return history items.
+ */
+ const slurl_list_t& getItems() const { return mItems; }
+ void purgeItems();
+ /**
+ * Is the history empty?
+ *
+ * History containing single item is treated as empty
+ * because the item points to the current location.
+ */
+ bool isEmpty() const { return mItems.size() <= 1; }
+
+ /**
+ * Get index of the current location in the history.
+ */
+ int getCurrentItemIndex() const { return mCurrentItem; }
+ /**
+ * Set a callback to be called upon history changes.
+ *
+ * Multiple callbacks can be set.
+ */
+ boost::signals2::connection setHistoryChangedCallback(history_callback_t cb);
+
+ /**
+ * Save history to a file so that we can restore it on startup.
+ *
+ * @see load()
+ */
+ void dump() const;
+
+private:
+
+ /**
+ * Called by when a teleport fails.
+ *
+ * Called via callback set on the LLViewerParcelMgr "teleport failed" signal.
+ *
+ * @see mTeleportFailedConn
+ */
+ void onTeleportFailed();
+
+ /**
+ * Update current location.
+ *
+ * @param new_pos Current agent global position. After local teleports we
+ * cannot rely on gAgent.getPositionGlobal(),
+ * so the new position gets passed explicitly.
+ *
+ * Called when a teleport finishes.
+ * Called via callback set on the LLViewerParcelMgr "teleport finished" signal.
+ *
+ * Takes mRequestedItem into consideration: if it's not -1
+ * (i.e. user is teleporting to an arbitrary location, not to a history item)
+ * we purge forward items and append a new one, making it current. Otherwise
+ * we just modify mCurrentItem.
+ *
+ * @see mRequestedItem
+ * @see mGotInitialUpdate
+ */
+ void updateCurrentLocation(const LLVector3d& new_pos);
+
+ /**
+ * Invokes the "history changed" callback(s).
+ */
+ void onHistoryChanged();
+
+ /**
+ * Format current agent location in a human-readable manner.
+ *
+ * @param full whether to include coordinates
+ * @param local_pos_override hack: see description of updateCurrentLocation()
+ * @return
+ */
+ static std::string getCurrentLocationTitle(bool full, const LLVector3& local_pos_override);
+
+ /**
+ * Actually, the teleport history.
+ */
+ slurl_list_t mItems;
+
+ /**
+ * Current position within the history.
+ */
+ int mCurrentItem;
+
+ /**
+ * Requested position within the history.
+ *
+ * When a teleport succeeds, this is checked by updateCurrentLocation() to tell
+ * if this is a teleport within the history (mRequestedItem >=0) or not (-1).
+ *
+ * Set by goToItem(); reset by onTeleportFailed() (if teleport fails).
+ *
+ * @see goToItem()
+ * @see updateCurrentLocation()
+ */
+ int mRequestedItem;
+
+ /**
+ * Have we received the initial location update?
+ *
+ * @see updateCurrentLocation()
+ */
+ bool mGotInitialUpdate;
+
+ /**
+ * Signal emitted when the history gets changed.
+ *
+ * Invokes callbacks set with setHistoryChangedCallback().
+ */
+ history_signal_t mHistoryChangedSignal;
+
+ /**
+ * Teleport success notification connection.
+ *
+ * Using this connection we get notified when a teleport finishes
+ * or initial location update occurs.
+ */
+ boost::signals2::connection mTeleportFinishedConn;
+
+ /**
+ * Teleport failure notification connection.
+ *
+ * Using this connection we get notified when a teleport fails.
+ */
+ boost::signals2::connection mTeleportFailedConn;
+};
+
+#endif
diff --git a/indra/newview/llteleporthistorystorage.cpp b/indra/newview/llteleporthistorystorage.cpp
new file mode 100644
index 0000000000..c635f91423
--- /dev/null
+++ b/indra/newview/llteleporthistorystorage.cpp
@@ -0,0 +1,253 @@
+/**
+ * @file llteleporthistorystorage.cpp
+ * @brief Teleport history
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llteleporthistorystorage.h"
+
+#include "llsd.h"
+#include "llsdserialize.h"
+#include "lldir.h"
+#include "llteleporthistory.h"
+#include "llagent.h"
+
+// Max offset for two global positions to consider them as equal
+const F64 MAX_GLOBAL_POS_OFFSET = 5.0f;
+
+LLTeleportHistoryPersistentItem::LLTeleportHistoryPersistentItem(const LLSD& val)
+{
+ mTitle = val["title"].asString();
+ mGlobalPos.setValue(val["global_pos"]);
+ mDate = val["date"];
+}
+
+LLSD LLTeleportHistoryPersistentItem::toLLSD() const
+{
+ LLSD val;
+
+ val["title"] = mTitle;
+ val["global_pos"] = mGlobalPos.getValue();
+ val["date"] = mDate;
+
+ return val;
+}
+
+struct LLSortItemsByDate
+{
+ bool operator()(const LLTeleportHistoryPersistentItem& a, const LLTeleportHistoryPersistentItem& b)
+ {
+ return a.mDate < b.mDate;
+ }
+};
+
+LLTeleportHistoryStorage::LLTeleportHistoryStorage() :
+ mFilename("teleport_history.txt")
+{
+ LLTeleportHistory *th = LLTeleportHistory::getInstance();
+ if (th)
+ th->setHistoryChangedCallback(boost::bind(&LLTeleportHistoryStorage::onTeleportHistoryChange, this));
+
+ load();
+}
+
+LLTeleportHistoryStorage::~LLTeleportHistoryStorage()
+{
+}
+
+void LLTeleportHistoryStorage::onTeleportHistoryChange()
+{
+ LLTeleportHistory *th = LLTeleportHistory::getInstance();
+ if (!th)
+ return;
+
+ const LLTeleportHistoryItem &item = th->getItems()[th->getCurrentItemIndex()];
+
+ addItem(item.mTitle, item.mGlobalPos);
+ save();
+}
+
+void LLTeleportHistoryStorage::purgeItems()
+{
+ mItems.clear();
+ mHistoryChangedSignal(-1);
+}
+
+void LLTeleportHistoryStorage::addItem(const std::string title, const LLVector3d& global_pos)
+{
+ addItem(title, global_pos, LLDate::now());
+}
+
+
+bool LLTeleportHistoryStorage::compareByTitleAndGlobalPos(const LLTeleportHistoryPersistentItem& a, const LLTeleportHistoryPersistentItem& b)
+{
+ return a.mTitle == b.mTitle && (a.mGlobalPos - b.mGlobalPos).length() < MAX_GLOBAL_POS_OFFSET;
+}
+
+void LLTeleportHistoryStorage::addItem(const std::string title, const LLVector3d& global_pos, const LLDate& date)
+{
+ LLTeleportHistoryPersistentItem item(title, global_pos, date);
+
+ slurl_list_t::iterator item_iter = std::find_if(mItems.begin(), mItems.end(),
+ boost::bind(&LLTeleportHistoryStorage::compareByTitleAndGlobalPos, this, _1, item));
+
+ // If there is such item already, remove it, since new item is more recent
+ S32 removed_index = -1;
+ if (item_iter != mItems.end())
+ {
+ removed_index = item_iter - mItems.begin();
+ mItems.erase(item_iter);
+ }
+
+ mItems.push_back(item);
+
+ // Check whether sorting is needed
+ if (mItems.size() > 1)
+ {
+ item_iter = mItems.end();
+
+ item_iter--;
+ item_iter--;
+
+ // If second to last item is more recent than last, then resort items
+ if (item_iter->mDate > item.mDate)
+ {
+ removed_index = -1;
+ std::sort(mItems.begin(), mItems.end(), LLSortItemsByDate());
+ }
+ }
+
+ mHistoryChangedSignal(removed_index);
+}
+
+void LLTeleportHistoryStorage::removeItem(S32 idx)
+{
+ if (idx < 0 || idx >= (S32)mItems.size())
+ return;
+
+ mItems.erase (mItems.begin() + idx);
+}
+
+void LLTeleportHistoryStorage::save()
+{
+ // build filename for each user
+ std::string resolvedFilename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, mFilename);
+
+ // open the history file for writing
+ llofstream file (resolvedFilename);
+ if (!file.is_open())
+ {
+ llwarns << "can't open teleport history file \"" << mFilename << "\" for writing" << llendl;
+ return;
+ }
+
+ for (size_t i=0; i<mItems.size(); i++)
+ {
+ LLSD s_item = mItems[i].toLLSD();
+ file << LLSDOStreamer<LLSDNotationFormatter>(s_item) << std::endl;
+ }
+
+ file.close();
+}
+
+void LLTeleportHistoryStorage::load()
+{
+ // build filename for each user
+ std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, mFilename);
+
+ // open the history file for reading
+ llifstream file(resolved_filename);
+ if (!file.is_open())
+ {
+ llwarns << "can't load teleport history from file \"" << mFilename << "\"" << llendl;
+ return;
+ }
+
+ // remove current entries before we load over them
+ mItems.clear();
+
+ // the parser's destructor is protected so we cannot create in the stack.
+ LLPointer<LLSDParser> parser = new LLSDNotationParser();
+ std::string line;
+ while (std::getline(file, line))
+ {
+ LLSD s_item;
+ std::istringstream iss(line);
+ if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE)
+ {
+ llinfos << "Parsing saved teleport history failed" << llendl;
+ break;
+ }
+
+ mItems.push_back(s_item);
+ }
+
+ file.close();
+
+ std::sort(mItems.begin(), mItems.end(), LLSortItemsByDate());
+
+ mHistoryChangedSignal(-1);
+}
+
+void LLTeleportHistoryStorage::dump() const
+{
+ llinfos << "Teleport history storage dump (" << mItems.size() << " items):" << llendl;
+
+ for (size_t i=0; i<mItems.size(); i++)
+ {
+ std::stringstream line;
+ line << i << ": " << mItems[i].mTitle;
+ line << " global pos: " << mItems[i].mGlobalPos;
+ line << " date: " << mItems[i].mDate;
+
+ llinfos << line.str() << llendl;
+ }
+}
+
+boost::signals2::connection LLTeleportHistoryStorage::setHistoryChangedCallback(history_callback_t cb)
+{
+ return mHistoryChangedSignal.connect(cb);
+}
+
+void LLTeleportHistoryStorage::goToItem(S32 idx)
+{
+ // Validate specified index.
+ if (idx < 0 || idx >= (S32)mItems.size())
+ {
+ llwarns << "Invalid teleport history index (" << idx << ") specified" << llendl;
+ dump();
+ return;
+ }
+
+ // Attempt to teleport to the requested item.
+ gAgent.teleportViaLocation(mItems[idx].mGlobalPos);
+}
+
diff --git a/indra/newview/llteleporthistorystorage.h b/indra/newview/llteleporthistorystorage.h
new file mode 100644
index 0000000000..2eaa94f2ed
--- /dev/null
+++ b/indra/newview/llteleporthistorystorage.h
@@ -0,0 +1,136 @@
+/**
+ * @file llteleporthistorystorage.h
+ * @brief Saving/restoring of teleport history.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTELEPORTHISTORYSTORAGE_H
+#define LL_LLTELEPORTHISTORYSTORAGE_H
+
+#include <vector>
+
+#include "llsingleton.h"
+#include "lldate.h"
+#include "v3dmath.h"
+
+class LLSD;
+
+/**
+ * An item of the teleport history, stored in file
+ *
+ * Contains the location's global coordinates, title and date.
+ */
+class LLTeleportHistoryPersistentItem
+{
+public:
+ LLTeleportHistoryPersistentItem()
+ {}
+
+ LLTeleportHistoryPersistentItem(const std::string title, const LLVector3d& global_pos)
+ : mTitle(title), mGlobalPos(global_pos), mDate(LLDate::now())
+ {}
+
+ LLTeleportHistoryPersistentItem(const std::string title, const LLVector3d& global_pos, const LLDate& date)
+ : mTitle(title), mGlobalPos(global_pos), mDate(date)
+ {}
+
+ LLTeleportHistoryPersistentItem(const LLSD& val);
+ LLSD toLLSD() const;
+
+ std::string mTitle;
+ LLVector3d mGlobalPos;
+ LLDate mDate;
+};
+
+/**
+ * Persistent teleport history.
+ *
+ */
+class LLTeleportHistoryStorage: public LLSingleton<LLTeleportHistoryStorage>
+{
+ LOG_CLASS(LLTeleportHistoryStorage);
+
+public:
+
+ typedef std::vector<LLTeleportHistoryPersistentItem> slurl_list_t;
+
+ // removed_index is index of removed item, which replaced by more recent
+ typedef boost::function<void(S32 removed_index)> history_callback_t;
+ typedef boost::signals2::signal<void(S32 removed_index)> history_signal_t;
+
+ LLTeleportHistoryStorage();
+ ~LLTeleportHistoryStorage();
+
+ /**
+ * @return history items.
+ */
+ const slurl_list_t& getItems() const { return mItems; }
+ void purgeItems();
+
+ void addItem(const std::string title, const LLVector3d& global_pos);
+ void addItem(const std::string title, const LLVector3d& global_pos, const LLDate& date);
+
+ void removeItem(S32 idx);
+
+ void save();
+ void load();
+
+ void dump() const;
+
+ /**
+ * Set a callback to be called upon history changes.
+ *
+ * Multiple callbacks can be set.
+ */
+ boost::signals2::connection setHistoryChangedCallback(history_callback_t cb);
+
+ /**
+ * Go to specific item in the history.
+ *
+ * The item is specified by its index (starting from 0).
+ */
+ void goToItem(S32 idx);
+
+private:
+
+ void onTeleportHistoryChange();
+ bool compareByTitleAndGlobalPos(const LLTeleportHistoryPersistentItem& a, const LLTeleportHistoryPersistentItem& b);
+
+ slurl_list_t mItems;
+ std::string mFilename;
+
+ /**
+ * Signal emitted when the history gets changed.
+ *
+ * Invokes callbacks set with setHistoryChangedCallback().
+ */
+ history_signal_t mHistoryChangedSignal;
+};
+
+#endif //LL_LLTELEPORTHISTORYSTORAGE_H
diff --git a/indra/newview/lltexglobalcolor.cpp b/indra/newview/lltexglobalcolor.cpp
new file mode 100644
index 0000000000..d7840fb435
--- /dev/null
+++ b/indra/newview/lltexglobalcolor.cpp
@@ -0,0 +1,157 @@
+/**
+ * @file lltexlayerglobalcolor.cpp
+ * @brief SERAPH - ADD IN
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llagent.h"
+#include "lltexlayer.h"
+#include "llvoavatar.h"
+#include "llwearable.h"
+#include "lltexglobalcolor.h"
+
+//-----------------------------------------------------------------------------
+// LLTexGlobalColor
+//-----------------------------------------------------------------------------
+
+LLTexGlobalColor::LLTexGlobalColor(LLVOAvatar* avatar)
+ :
+ mAvatar(avatar),
+ mInfo(NULL)
+{
+}
+
+LLTexGlobalColor::~LLTexGlobalColor()
+{
+ // mParamColorList are LLViewerVisualParam's and get deleted with ~LLCharacter()
+ //std::for_each(mParamColorList.begin(), mParamColorList.end(), DeletePointer());
+}
+
+BOOL LLTexGlobalColor::setInfo(LLTexGlobalColorInfo *info)
+{
+ llassert(mInfo == NULL);
+ mInfo = info;
+ //mID = info->mID; // No ID
+
+ mParamGlobalColorList.reserve(mInfo->mParamColorInfoList.size());
+ for (param_color_info_list_t::iterator iter = mInfo->mParamColorInfoList.begin();
+ iter != mInfo->mParamColorInfoList.end();
+ iter++)
+ {
+ LLTexParamGlobalColor* param_color = new LLTexParamGlobalColor(this);
+ if (!param_color->setInfo(*iter, TRUE))
+ {
+ mInfo = NULL;
+ return FALSE;
+ }
+ mParamGlobalColorList.push_back(param_color);
+ }
+
+ return TRUE;
+}
+
+LLColor4 LLTexGlobalColor::getColor() const
+{
+ // Sum of color params
+ if (mParamGlobalColorList.empty())
+ return LLColor4(1.f, 1.f, 1.f, 1.f);
+
+ LLColor4 net_color(0.f, 0.f, 0.f, 0.f);
+ LLTexLayer::calculateTexLayerColor(mParamGlobalColorList, net_color);
+ return net_color;
+}
+
+const std::string& LLTexGlobalColor::getName() const
+{
+ return mInfo->mName;
+}
+
+//-----------------------------------------------------------------------------
+// LLTexParamGlobalColor
+//-----------------------------------------------------------------------------
+LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color) :
+ LLTexLayerParamColor(tex_global_color->getAvatar()),
+ mTexGlobalColor(tex_global_color)
+{
+}
+
+/*virtual*/ LLViewerVisualParam* LLTexParamGlobalColor::cloneParam(LLWearable* wearable) const
+{
+ LLTexParamGlobalColor *new_param = new LLTexParamGlobalColor(mTexGlobalColor);
+ *new_param = *this;
+ return new_param;
+}
+
+void LLTexParamGlobalColor::onGlobalColorChanged(bool upload_bake)
+{
+ mAvatar->onGlobalColorChanged(mTexGlobalColor, upload_bake);
+}
+
+//-----------------------------------------------------------------------------
+// LLTexGlobalColorInfo
+//-----------------------------------------------------------------------------
+
+LLTexGlobalColorInfo::LLTexGlobalColorInfo()
+{
+}
+
+
+LLTexGlobalColorInfo::~LLTexGlobalColorInfo()
+{
+ for_each(mParamColorInfoList.begin(), mParamColorInfoList.end(), DeletePointer());
+}
+
+BOOL LLTexGlobalColorInfo::parseXml(LLXmlTreeNode* node)
+{
+ // name attribute
+ static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
+ if (!node->getFastAttributeString(name_string, mName))
+ {
+ llwarns << "<global_color> element is missing name attribute." << llendl;
+ return FALSE;
+ }
+ // <param> sub-element
+ for (LLXmlTreeNode* child = node->getChildByName("param");
+ child;
+ child = node->getNextNamedChild())
+ {
+ if (child->getChildByName("param_color"))
+ {
+ // <param><param_color/></param>
+ LLTexLayerParamColorInfo* info = new LLTexLayerParamColorInfo();
+ if (!info->parseXml(child))
+ {
+ delete info;
+ return FALSE;
+ }
+ mParamColorInfoList.push_back(info);
+ }
+ }
+ return TRUE;
+}
diff --git a/indra/newview/lltexglobalcolor.h b/indra/newview/lltexglobalcolor.h
new file mode 100644
index 0000000000..829a7d645b
--- /dev/null
+++ b/indra/newview/lltexglobalcolor.h
@@ -0,0 +1,88 @@
+/**
+ * @file lltexglobalcolor.h
+ * @brief This is global texture color info used by llvoavatar.
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTEXGLOBALCOLOR_H
+#define LL_LLTEXGLOBALCOLOR_H
+
+#include "lltexlayer.h"
+#include "lltexlayerparams.h"
+
+class LLVOAvatar;
+class LLWearable;
+class LLTexGlobalColorInfo;
+
+class LLTexGlobalColor
+{
+public:
+ LLTexGlobalColor( LLVOAvatar* avatar );
+ ~LLTexGlobalColor();
+
+ LLTexGlobalColorInfo* getInfo() const { return mInfo; }
+ // This sets mInfo and calls initialization functions
+ BOOL setInfo(LLTexGlobalColorInfo *info);
+
+ LLVOAvatar* getAvatar() const { return mAvatar; }
+ LLColor4 getColor() const;
+ const std::string& getName() const;
+
+private:
+ param_color_list_t mParamGlobalColorList;
+ LLVOAvatar* mAvatar; // just backlink, don't LLPointer
+ LLTexGlobalColorInfo *mInfo;
+};
+
+// Used by llvoavatar to determine skin/eye/hair color.
+class LLTexGlobalColorInfo
+{
+ friend class LLTexGlobalColor;
+public:
+ LLTexGlobalColorInfo();
+ ~LLTexGlobalColorInfo();
+
+ BOOL parseXml(LLXmlTreeNode* node);
+
+private:
+ param_color_info_list_t mParamColorInfoList;
+ std::string mName;
+};
+
+class LLTexParamGlobalColor : public LLTexLayerParamColor
+{
+public:
+ LLTexParamGlobalColor(LLTexGlobalColor *tex_color);
+ /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const;
+protected:
+ /*virtual*/ void onGlobalColorChanged(bool upload_bake);
+private:
+ LLTexGlobalColor* mTexGlobalColor;
+};
+
+#endif
diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp
index b05da8c6d8..84c8b9d5f0 100644
--- a/indra/newview/lltexlayer.cpp
+++ b/indra/newview/lltexlayer.cpp
@@ -32,147 +32,88 @@
#include "llviewerprecompiledheaders.h"
-#include "imageids.h"
+#include "lltexlayer.h"
+
#include "llagent.h"
-#include "llcrc.h"
-#include "lldir.h"
-#include "llglheaders.h"
-#include "llimagebmp.h"
#include "llimagej2c.h"
#include "llimagetga.h"
-#include "llpolymorph.h"
-#include "llquantize.h"
-#include "lltexlayer.h"
-#include "llui.h"
#include "llvfile.h"
-#include "llviewerimagelist.h"
-#include "llviewerimagelist.h"
-#include "llviewerregion.h"
+#include "llvfs.h"
#include "llviewerstats.h"
-#include "llviewerwindow.h"
+#include "llviewerregion.h"
#include "llvoavatar.h"
-#include "llxmltree.h"
+#include "llvoavatarself.h"
#include "pipeline.h"
-#include "v4coloru.h"
-#include "llrender.h"
#include "llassetuploadresponders.h"
+#include "lltexlayerparams.h"
+#include "llui.h"
+#include "llagentwearables.h"
+#include "llwearable.h"
+#include "llviewervisualparam.h"
//#include "../tools/imdebug/imdebug.h"
using namespace LLVOAvatarDefines;
-// static
-S32 LLTexLayerSetBuffer::sGLByteCount = 0;
-S32 LLTexLayerSetBuffer::sGLBumpByteCount = 0;
-
//-----------------------------------------------------------------------------
// LLBakedUploadData()
//-----------------------------------------------------------------------------
-LLBakedUploadData::LLBakedUploadData( LLVOAvatar* avatar,
- LLTexLayerSet* layerset,
- LLTexLayerSetBuffer* layerset_buffer,
- const LLUUID & id ) :
- mAvatar( avatar ),
- mLayerSet( layerset ),
- mLayerSetBuffer( layerset_buffer ),
- mID(id)
+LLBakedUploadData::LLBakedUploadData(const LLVOAvatarSelf* avatar,
+ LLTexLayerSet* layerset,
+ const LLUUID& id) :
+ mAvatar(avatar),
+ mTexLayerSet(layerset),
+ mID(id),
+ mStartTime(LLFrameTimer::getTotalTime()) // Record starting time
{
- mStartTime = LLFrameTimer::getTotalTime(); // Record starting time
- for( S32 i = 0; i < WT_COUNT; i++ )
- {
- LLWearable* wearable = gAgent.getWearable( (EWearableType)i);
- if( wearable )
- {
- mWearableAssets[i] = wearable->getID();
- }
- }
}
//-----------------------------------------------------------------------------
// LLTexLayerSetBuffer
// The composite image that a LLTexLayerSet writes to. Each LLTexLayerSet has one.
//-----------------------------------------------------------------------------
-LLTexLayerSetBuffer::LLTexLayerSetBuffer( LLTexLayerSet* owner, S32 width, S32 height, BOOL has_bump )
- :
+
+// static
+S32 LLTexLayerSetBuffer::sGLByteCount = 0;
+
+LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* const owner,
+ S32 width, S32 height) :
// ORDER_LAST => must render these after the hints are created.
- LLDynamicTexture( width, height, 4, LLDynamicTexture::ORDER_LAST, TRUE ),
+ LLViewerDynamicTexture( width, height, 4, LLViewerDynamicTexture::ORDER_LAST, TRUE ),
mNeedsUpdate( TRUE ),
mNeedsUpload( FALSE ),
mUploadPending( FALSE ), // Not used for any logic here, just to sync sending of updates
- mTexLayerSet( owner )
+ mTexLayerSet(owner)
{
LLTexLayerSetBuffer::sGLByteCount += getSize();
- mHasBump = has_bump ;
- mBumpTex = NULL ;
-
- createBumpTexture() ;
}
LLTexLayerSetBuffer::~LLTexLayerSetBuffer()
{
LLTexLayerSetBuffer::sGLByteCount -= getSize();
-
- if( mBumpTex.notNull())
+ destroyGLTexture();
+ for( S32 order = 0; order < ORDER_COUNT; order++ )
{
- mBumpTex = NULL ;
- LLImageGL::sGlobalTextureMemory -= mWidth * mHeight * 4;
- LLTexLayerSetBuffer::sGLBumpByteCount -= mWidth * mHeight * 4;
+ LLViewerDynamicTexture::sInstances[order].erase(this); // will fail in all but one case.
}
}
+
//virtual
void LLTexLayerSetBuffer::restoreGLTexture()
{
- createBumpTexture() ;
- LLDynamicTexture::restoreGLTexture() ;
+ LLViewerDynamicTexture::restoreGLTexture() ;
}
//virtual
void LLTexLayerSetBuffer::destroyGLTexture()
{
- if( mBumpTex.notNull() )
- {
- mBumpTex = NULL ;
- LLImageGL::sGlobalTextureMemory -= mWidth * mHeight * 4;
- LLTexLayerSetBuffer::sGLBumpByteCount -= mWidth * mHeight * 4;
- }
-
- LLDynamicTexture::destroyGLTexture() ;
-}
-
-void LLTexLayerSetBuffer::createBumpTexture()
-{
- if( mHasBump )
- {
- LLGLSUIDefault gls_ui;
- mBumpTex = new LLImageGL(FALSE) ;
- if(!mBumpTex->createGLTexture())
- {
- mBumpTex = NULL ;
- return ;
- }
-
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mBumpTex->getTexName());
- stop_glerror();
-
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
-
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-
- LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_RGBA8, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- stop_glerror();
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- LLImageGL::sGlobalTextureMemory += mWidth * mHeight * 4;
- LLTexLayerSetBuffer::sGLBumpByteCount += mWidth * mHeight * 4;
- }
+ LLViewerDynamicTexture::destroyGLTexture() ;
}
// static
void LLTexLayerSetBuffer::dumpTotalByteCount()
{
llinfos << "Composite System GL Buffers: " << (LLTexLayerSetBuffer::sGLByteCount/1024) << "KB" << llendl;
- llinfos << "Composite System GL Bump Buffers: " << (LLTexLayerSetBuffer::sGLBumpByteCount/1024) << "KB" << llendl;
}
void LLTexLayerSetBuffer::requestUpdate()
@@ -202,19 +143,19 @@ void LLTexLayerSetBuffer::cancelUpload()
mUploadPending = FALSE;
}
-void LLTexLayerSetBuffer::pushProjection()
+void LLTexLayerSetBuffer::pushProjection() const
{
glMatrixMode(GL_PROJECTION);
gGL.pushMatrix();
glLoadIdentity();
- glOrtho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f);
+ glOrtho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
gGL.pushMatrix();
glLoadIdentity();
}
-void LLTexLayerSetBuffer::popProjection()
+void LLTexLayerSetBuffer::popProjection() const
{
glMatrixMode(GL_PROJECTION);
gGL.popMatrix();
@@ -225,12 +166,12 @@ void LLTexLayerSetBuffer::popProjection()
BOOL LLTexLayerSetBuffer::needsRender()
{
- LLVOAvatar* avatar = mTexLayerSet->getAvatar();
+ const LLVOAvatarSelf* avatar = mTexLayerSet->getAvatar();
BOOL upload_now = mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal();
- BOOL needs_update = gAgent.mNumPendingQueries == 0 && (mNeedsUpdate || upload_now) && !avatar->mAppearanceAnimating;
+ BOOL needs_update = gAgentQueryManager.hasNoPendingQueries() && (mNeedsUpdate || upload_now) && !avatar->mAppearanceAnimating;
if (needs_update)
{
- BOOL invalid_skirt = avatar->getBakedTE(mTexLayerSet) == TEX_SKIRT_BAKED && !avatar->isWearingWearableType(WT_SKIRT);
+ BOOL invalid_skirt = avatar->getBakedTE(mTexLayerSet) == LLVOAvatarDefines::TEX_SKIRT_BAKED && !avatar->isWearingWearableType(WT_SKIRT);
if (invalid_skirt)
{
// we were trying to create a skirt texture
@@ -253,72 +194,51 @@ void LLTexLayerSetBuffer::preRender(BOOL clear_depth)
pushProjection();
// keep depth buffer, we don't need to clear it
- LLDynamicTexture::preRender(FALSE);
+ LLViewerDynamicTexture::preRender(FALSE);
}
void LLTexLayerSetBuffer::postRender(BOOL success)
{
popProjection();
- LLDynamicTexture::postRender(success);
+ LLViewerDynamicTexture::postRender(success);
}
BOOL LLTexLayerSetBuffer::render()
{
- U8* baked_bump_data = NULL;
-
// Default color mask for tex layer render
gGL.setColorMask(true, true);
// do we need to upload, and do we have sufficient data to create an uploadable composite?
// When do we upload the texture if gAgent.mNumPendingQueries is non-zero?
- BOOL upload_now = (gAgent.mNumPendingQueries == 0 && mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal());
+ BOOL upload_now = (gAgentQueryManager.hasNoPendingQueries() && mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal());
BOOL success = TRUE;
- // Composite bump
- if( mBumpTex.notNull() )
- {
- // Composite the bump data
- success &= mTexLayerSet->renderBump( mOrigin.mX, mOrigin.mY, mWidth, mHeight );
- stop_glerror();
-
- if (success)
- {
- LLGLSUIDefault gls_ui;
-
- // read back into texture (this is done externally for the color data)
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mBumpTex->getTexName());
- stop_glerror();
-
- glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mOrigin.mX, mOrigin.mY, mWidth, mHeight);
- stop_glerror();
-
- // if we need to upload the data, read it back into a buffer
- if( upload_now )
- {
- baked_bump_data = new U8[ mWidth * mHeight * 4 ];
- glReadPixels(mOrigin.mX, mOrigin.mY, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_bump_data );
- stop_glerror();
- }
- }
- }
// Composite the color data
LLGLSUIDefault gls_ui;
- success &= mTexLayerSet->render( mOrigin.mX, mOrigin.mY, mWidth, mHeight );
+ success &= mTexLayerSet->render( mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight );
gGL.flush();
if( upload_now )
{
if (!success)
{
- delete [] baked_bump_data;
llinfos << "Failed attempt to bake " << mTexLayerSet->getBodyRegion() << llendl;
mUploadPending = FALSE;
}
else
{
- readBackAndUpload(baked_bump_data);
+ if (mTexLayerSet->isVisible())
+ {
+ readBackAndUpload();
+ }
+ else
+ {
+ mUploadPending = FALSE;
+ mNeedsUpload = FALSE;
+ mTexLayerSet->getAvatar()->setNewBakedTexture(mTexLayerSet->getBakedTexIndex(),IMG_INVISIBLE);
+ }
}
}
@@ -327,7 +247,7 @@ BOOL LLTexLayerSetBuffer::render()
gGL.setSceneBlendType(LLRender::BT_ALPHA);
// we have valid texture data now
- mTexture->setGLTextureCreated(true);
+ mGLTexturep->setGLTextureCreated(true);
mNeedsUpdate = FALSE;
return success;
@@ -335,7 +255,7 @@ BOOL LLTexLayerSetBuffer::render()
bool LLTexLayerSetBuffer::isInitialized(void) const
{
- return mTexture.notNull() && mTexture->isGLTextureCreated();
+ return mGLTexturep.notNull() && mGLTexturep->isGLTextureCreated();
}
BOOL LLTexLayerSetBuffer::updateImmediate()
@@ -353,12 +273,12 @@ BOOL LLTexLayerSetBuffer::updateImmediate()
return result;
}
-void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data)
+void LLTexLayerSetBuffer::readBackAndUpload()
{
// pointers for storing data to upload
- U8* baked_color_data = new U8[ mWidth * mHeight * 4 ];
+ U8* baked_color_data = new U8[ mFullWidth * mFullHeight * 4 ];
- glReadPixels(mOrigin.mX, mOrigin.mY, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_color_data );
+ glReadPixels(mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_color_data );
stop_glerror();
llinfos << "Baked " << mTexLayerSet->getBodyRegion() << llendl;
@@ -373,89 +293,31 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data)
LLGLSUIDefault gls_ui;
- LLPointer<LLImageRaw> baked_mask_image = new LLImageRaw(mWidth, mHeight, 1 );
+ LLPointer<LLImageRaw> baked_mask_image = new LLImageRaw(mFullWidth, mFullHeight, 1 );
U8* baked_mask_data = baked_mask_image->getData();
-
- mTexLayerSet->gatherAlphaMasks(baked_mask_data, mWidth, mHeight);
-// imdebug("lum b=8 w=%d h=%d %p", mWidth, mHeight, baked_mask_data);
-
+
+ mTexLayerSet->gatherMorphMaskAlpha(baked_mask_data, mFullWidth, mFullHeight);
// writes into baked_color_data
const char* comment_text = NULL;
- S32 baked_image_components = mBumpTex.notNull() ? 5 : 4; // red green blue [bump] clothing
- LLPointer<LLImageRaw> baked_image = new LLImageRaw( mWidth, mHeight, baked_image_components );
+ S32 baked_image_components = 5; // red green blue [bump] clothing
+ LLPointer<LLImageRaw> baked_image = new LLImageRaw( mFullWidth, mFullHeight, baked_image_components );
U8* baked_image_data = baked_image->getData();
- if( mBumpTex.notNull() )
- {
- comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // 5 channels: rgb, heightfield/alpha, mask
+ comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // 5 channels: rgb, heightfield/alpha, mask
- // Hide the alpha for the eyelashes in a corner of the bump map
- if (mTexLayerSet->getBodyRegion() == "head")
- {
- S32 i = 0;
- for( S32 u = 0; u < mWidth; u++ )
- {
- for( S32 v = 0; v < mHeight; v++ )
- {
- baked_image_data[5*i + 0] = baked_color_data[4*i + 0];
- baked_image_data[5*i + 1] = baked_color_data[4*i + 1];
- baked_image_data[5*i + 2] = baked_color_data[4*i + 2];
- baked_image_data[5*i + 3] = baked_color_data[4*i + 3]; // alpha should be correct for eyelashes.
- baked_image_data[5*i + 4] = baked_mask_data[i];
- i++;
- }
- }
- }
- else
- {
- S32 i = 0;
- for( S32 u = 0; u < mWidth; u++ )
- {
- for( S32 v = 0; v < mHeight; v++ )
- {
- baked_image_data[5*i + 0] = baked_color_data[4*i + 0];
- baked_image_data[5*i + 1] = baked_color_data[4*i + 1];
- baked_image_data[5*i + 2] = baked_color_data[4*i + 2];
- baked_image_data[5*i + 3] = 255; // reserve for alpha
- baked_image_data[5*i + 4] = baked_mask_data[i];
- i++;
- }
- }
- }
- }
- else
- {
- if (mTexLayerSet->getBodyRegion() == "skirt" || mTexLayerSet->getBodyRegion() == "hair")
- {
- S32 i = 0;
- for( S32 u = 0; u < mWidth; u++ )
- {
- for( S32 v = 0; v < mHeight; v++ )
- {
- baked_image_data[4*i + 0] = baked_color_data[4*i + 0];
- baked_image_data[4*i + 1] = baked_color_data[4*i + 1];
- baked_image_data[4*i + 2] = baked_color_data[4*i + 2];
- baked_image_data[4*i + 3] = baked_color_data[4*i + 3]; // Use alpha, not bump
- i++;
- }
- }
- }
- else
+ S32 i = 0;
+ for( S32 u = 0; u < mFullWidth; u++ )
+ {
+ for( S32 v = 0; v < mFullHeight; v++ )
{
- S32 i = 0;
- for( S32 u = 0; u < mWidth; u++ )
- {
- for( S32 v = 0; v < mHeight; v++ )
- {
- baked_image_data[4*i + 0] = baked_color_data[4*i + 0];
- baked_image_data[4*i + 1] = baked_color_data[4*i + 1];
- baked_image_data[4*i + 2] = baked_color_data[4*i + 2];
- baked_image_data[4*i + 3] = 255; // eyes should have no mask - reserve for alpha
- i++;
- }
- }
+ baked_image_data[5*i + 0] = baked_color_data[4*i + 0];
+ baked_image_data[5*i + 1] = baked_color_data[4*i + 1];
+ baked_image_data[5*i + 2] = baked_color_data[4*i + 2];
+ baked_image_data[5*i + 3] = baked_color_data[4*i + 3]; // alpha should be correct for eyelashes.
+ baked_image_data[5*i + 4] = baked_mask_data[i];
+ i++;
}
}
@@ -490,7 +352,7 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data)
{
// baked_upload_data is owned by the responder and deleted after the request completes
LLBakedUploadData* baked_upload_data =
- new LLBakedUploadData( gAgent.getAvatarObject(), this->mTexLayerSet, this, asset_id );
+ new LLBakedUploadData(gAgent.getAvatarObject(), this->mTexLayerSet, asset_id);
mUploadID = asset_id;
// upload the image
@@ -536,107 +398,86 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data)
}
delete [] baked_color_data;
- delete [] baked_bump_data;
}
// static
-void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, void* userdata, S32 result, LLExtStat ext_status) // StoreAssetData callback (not fixed)
+void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid,
+ void* userdata,
+ S32 result,
+ LLExtStat ext_status) // StoreAssetData callback (not fixed)
{
LLBakedUploadData* baked_upload_data = (LLBakedUploadData*)userdata;
- LLVOAvatar* avatar = gAgent.getAvatarObject();
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if (0 == result && avatar && !avatar->isDead())
+ if (0 == result &&
+ avatar &&
+ !avatar->isDead() &&
+ baked_upload_data->mAvatar == avatar && // Sanity check: only the user's avatar should be uploading textures.
+ baked_upload_data->mTexLayerSet->hasComposite()
+ )
{
- // Sanity check: only the user's avatar should be uploading textures.
- if( baked_upload_data->mAvatar == avatar )
+ LLTexLayerSetBuffer* layerset_buffer = baked_upload_data->mTexLayerSet->getComposite();
+
+ if (layerset_buffer->mUploadID.isNull())
+ {
+ // The upload got canceled, we should be in the
+ // process of baking a new texture so request an
+ // upload with the new data
+
+ // BAP: does this really belong in this callback, as
+ // opposed to where the cancellation takes place?
+ // suspect this does nothing.
+ layerset_buffer->requestUpload();
+ }
+ else if (baked_upload_data->mID == layerset_buffer->mUploadID)
{
- // Composite may have changed since the pointer was stored - need to do some checking.
- LLTexLayerSetBuffer* prev_layerset_buffer = baked_upload_data->mLayerSetBuffer;
- // Can't just call getComposite() because this will trigger creation if none exists.
- LLTexLayerSetBuffer* curr_layerset_buffer =
- baked_upload_data->mLayerSet->hasComposite()?baked_upload_data->mLayerSet->getComposite():NULL;
+ // This is the upload we're currently waiting for.
+ layerset_buffer->mUploadID.setNull();
+ layerset_buffer->mUploadPending = FALSE;
- if (prev_layerset_buffer != curr_layerset_buffer)
+ if (result >= 0)
{
- llinfos << "Baked texture out of date, composite no longer valid, ignored" << llendl;
+ LLVOAvatarDefines::ETextureIndex baked_te = avatar->getBakedTE(layerset_buffer->mTexLayerSet);
+ // Update baked texture info with the new UUID
+ U64 now = LLFrameTimer::getTotalTime(); // Record starting time
+ llinfos << "Baked texture upload took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << llendl;
+ avatar->setNewBakedTexture(baked_te, uuid);
}
else
- {
- curr_layerset_buffer->mUploadPending = FALSE;
-
- if (curr_layerset_buffer->mUploadID.isNull())
- {
- // The upload got canceled, we should be in the process of baking a new texture
- // so request an upload with the new data
- curr_layerset_buffer->requestUpload();
- }
- else if( baked_upload_data->mID == curr_layerset_buffer->mUploadID )
- {
- // This is the upload we're currently waiting for.
- curr_layerset_buffer->mUploadID.setNull();
-
- if( result >= 0 )
- {
- ETextureIndex baked_te = avatar->getBakedTE( curr_layerset_buffer->mTexLayerSet );
- U64 now = LLFrameTimer::getTotalTime(); // Record starting time
- llinfos << "Baked texture upload took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << llendl;
- avatar->setNewBakedTexture( baked_te, uuid );
- }
- else
- {
- llinfos << "Baked upload failed. Reason: " << result << llendl;
- // *FIX: retry upload after n seconds, asset server could be busy
- }
- }
- else
- {
- llinfos << "Received baked texture out of date, ignored." << llendl;
- }
-
- avatar->dirtyMesh();
+ {
+ // Avatar appearance is changing, ignore the upload results
+ llinfos << "Baked upload failed. Reason: " << result << llendl;
+ // *FIX: retry upload after n seconds, asset server could be busy
}
}
+ else
+ {
+ llinfos << "Received baked texture out of date, ignored." << llendl;
+ }
+
+ avatar->dirtyMesh();
}
else
{
- // Baked texture failed to upload, but since we didn't set the new baked texture, it means that they'll
- // try and rebake it at some point in the future (after login?)
+ // Baked texture failed to upload (in which case since we
+ // didn't set the new baked texture, it means that they'll try
+ // and rebake it at some point in the future (after login?)),
+ // or this response to upload is out of date, in which case a
+ // current response should be on the way or already processed.
llwarns << "Baked upload failed" << llendl;
}
delete baked_upload_data;
}
-void LLTexLayerSetBuffer::bindBumpTexture( U32 stage )
-{
- if( mBumpTex.notNull() )
- {
- gGL.getTexUnit(stage)->bindManual(LLTexUnit::TT_TEXTURE, mBumpTex->getTexName());
- gGL.getTexUnit(0)->activate();
-
- if( mLastBindTime != LLImageGL::sLastFrameTime )
- {
- mLastBindTime = LLImageGL::sLastFrameTime;
- LLImageGL::updateBoundTexMem(mWidth * mHeight * 4);
- }
- }
- else
- {
- gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.getTexUnit(0)->activate();
- }
-}
-
-
//-----------------------------------------------------------------------------
// LLTexLayerSet
// An ordered set of texture layers that get composited into a single texture.
//-----------------------------------------------------------------------------
-LLTexLayerSetInfo::LLTexLayerSetInfo( )
- :
+LLTexLayerSetInfo::LLTexLayerSetInfo() :
mBodyRegion( "" ),
mWidth( 512 ),
mHeight( 512 ),
@@ -701,6 +542,19 @@ BOOL LLTexLayerSetInfo::parseXml(LLXmlTreeNode* node)
return TRUE;
}
+// creates visual params without generating layersets or layers
+void LLTexLayerSetInfo::createVisualParams(LLVOAvatar *avatar)
+{
+ //layer_info_list_t mLayerInfoList;
+ for (layer_info_list_t::iterator layer_iter = mLayerInfoList.begin();
+ layer_iter != mLayerInfoList.end();
+ layer_iter++)
+ {
+ LLTexLayerInfo *layer_info = *layer_iter;
+ layer_info->createVisualParams(avatar);
+ }
+}
+
//-----------------------------------------------------------------------------
// LLTexLayerSet
// An ordered set of texture layers that get composited into a single texture.
@@ -708,43 +562,60 @@ BOOL LLTexLayerSetInfo::parseXml(LLXmlTreeNode* node)
BOOL LLTexLayerSet::sHasCaches = FALSE;
-LLTexLayerSet::LLTexLayerSet( LLVOAvatar* avatar )
- :
+LLTexLayerSet::LLTexLayerSet(LLVOAvatarSelf* const avatar) :
mComposite( NULL ),
mAvatar( avatar ),
mUpdatesEnabled( FALSE ),
- mHasBump( FALSE ),
+ mIsVisible( TRUE ),
mInfo( NULL )
{
}
LLTexLayerSet::~LLTexLayerSet()
{
+ deleteCaches();
std::for_each(mLayerList.begin(), mLayerList.end(), DeletePointer());
- delete mComposite;
+ std::for_each(mMaskLayerList.begin(), mMaskLayerList.end(), DeletePointer());
}
//-----------------------------------------------------------------------------
// setInfo
//-----------------------------------------------------------------------------
-BOOL LLTexLayerSet::setInfo(LLTexLayerSetInfo *info)
+BOOL LLTexLayerSet::setInfo(const LLTexLayerSetInfo *info)
{
llassert(mInfo == NULL);
mInfo = info;
//mID = info->mID; // No ID
- LLTexLayerSetInfo::layer_info_list_t::iterator iter;
mLayerList.reserve(info->mLayerInfoList.size());
- for (iter = info->mLayerInfoList.begin(); iter != info->mLayerInfoList.end(); iter++)
+ for (LLTexLayerSetInfo::layer_info_list_t::const_iterator iter = info->mLayerInfoList.begin();
+ iter != info->mLayerInfoList.end();
+ iter++)
{
- LLTexLayer* layer = new LLTexLayer( this );
- if (!layer->setInfo(*iter))
+ LLTexLayerInterface *layer = NULL;
+ if ( (*iter)->isUserSettable() )
+ {
+ layer = new LLTexLayerTemplate( this );
+ }
+ else
+ {
+ layer = new LLTexLayer(this);
+ }
+ // this is the first time this layer (of either type) is being created - make sure you add the parameters to the avatar
+ if (!layer->setInfo(*iter, NULL))
{
mInfo = NULL;
return FALSE;
}
- mLayerList.push_back( layer );
+ if (!layer->isVisibilityMask())
+ {
+ mLayerList.push_back( layer );
+ }
+ else
+ {
+ mMaskLayerList.push_back(layer);
+ }
}
requestUpdate();
@@ -781,124 +652,111 @@ void LLTexLayerSet::deleteCaches()
{
for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
{
- LLTexLayer* layer = *iter;
+ LLTexLayerInterface* layer = *iter;
+ layer->deleteCaches();
+ }
+ for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++)
+ {
+ LLTexLayerInterface* layer = *iter;
layer->deleteCaches();
}
}
// Returns TRUE if at least one packet of data has been received for each of the textures that this layerset depends on.
-BOOL LLTexLayerSet::isLocalTextureDataAvailable()
+BOOL LLTexLayerSet::isLocalTextureDataAvailable() const
{
- return mAvatar->isLocalTextureDataAvailable( this );
+ if (!mAvatar->isSelf()) return FALSE;
+ return ((LLVOAvatarSelf *)mAvatar)->isLocalTextureDataAvailable(this);
}
// Returns TRUE if all of the data for the textures that this layerset depends on have arrived.
-BOOL LLTexLayerSet::isLocalTextureDataFinal()
+BOOL LLTexLayerSet::isLocalTextureDataFinal() const
{
- return mAvatar->isLocalTextureDataFinal( this );
+ if (!mAvatar->isSelf()) return FALSE;
+ return ((LLVOAvatarSelf *)mAvatar)->isLocalTextureDataFinal(this);
}
BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height )
{
BOOL success = TRUE;
+ mIsVisible = TRUE;
- LLGLSUIDefault gls_ui;
- LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE);
- gGL.setColorMask(true, true);
-
- // composite color layers
- for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
+ if (mMaskLayerList.size() > 0)
{
- LLTexLayer* layer = *iter;
- if( layer->getRenderPass() == RP_COLOR )
+ for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++)
{
- gGL.flush();
- success &= layer->render( x, y, width, height );
- gGL.flush();
+ LLTexLayerInterface* layer = *iter;
+ if (layer->isInvisibleAlphaMask())
+ {
+ mIsVisible = FALSE;
+ }
}
}
- // (Optionally) replace alpha with a single component image from a tga file.
- if( !getInfo()->mStaticAlphaFileName.empty() )
+ LLGLSUIDefault gls_ui;
+ LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE);
+ gGL.setColorMask(true, true);
+
+ // clear buffer area to ensure we don't pick up UI elements
{
- LLGLSNoAlphaTest gls_no_alpha_test;
gGL.flush();
- gGL.setColorMask(false, true);
- gGL.setSceneBlendType(LLRender::BT_REPLACE);
+ LLGLDisable no_alpha(GL_ALPHA_TEST);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.color4f( 0.f, 0.f, 0.f, 1.f );
+
+ gl_rect_2d_simple( width, height );
+ gGL.flush();
+ }
+
+ if (mIsVisible)
+ {
+ // composite color layers
+ for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
{
- LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticAlphaFileName, TRUE );
- if( image_gl )
- {
- LLGLSUIDefault gls_ui;
- gGL.getTexUnit(0)->bind(image_gl);
- gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE );
- gl_rect_2d_simple_tex( width, height );
- }
- else
+ LLTexLayerInterface* layer = *iter;
+ if (layer->getRenderPass() == LLTexLayer::RP_COLOR)
{
- success = FALSE;
+ gGL.flush();
+ success &= layer->render(x, y, width, height);
+ gGL.flush();
}
}
- gGL.flush();
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
- gGL.setColorMask(true, true);
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
+ renderAlphaMaskTextures(x, y, width, height, false);
+
+ stop_glerror();
}
- else
- if( getInfo()->mClearAlpha )
+ else
{
- // Set the alpha channel to one (clean up after previous blending)
+ gGL.flush();
+
+ gGL.setSceneBlendType(LLRender::BT_REPLACE);
LLGLDisable no_alpha(GL_ALPHA_TEST);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.color4f( 0.f, 0.f, 0.f, 1.f );
- gGL.flush();
- gGL.setColorMask(false, true);
+ gGL.color4f( 0.f, 0.f, 0.f, 0.f );
gl_rect_2d_simple( width, height );
-
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
gGL.flush();
- gGL.setColorMask(true, true);
+
}
- stop_glerror();
return success;
}
-BOOL LLTexLayerSet::renderBump( S32 x, S32 y, S32 width, S32 height )
-{
- BOOL success = TRUE;
-
- LLGLSUIDefault gls_ui;
- LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE);
-
- //static S32 bump_layer_count = 1;
-
- for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
- {
- LLTexLayer* layer = *iter;
- if( layer->getRenderPass() == RP_BUMP )
- {
- success &= layer->render( x, y, width, height );
- }
- }
-
- // Set the alpha channel to one (clean up after previous blending)
- LLGLDisable no_alpha(GL_ALPHA_TEST);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.color4f( 0.f, 0.f, 0.f, 1.f );
- gGL.setColorMask(false, true);
- gl_rect_2d_simple( width, height );
-
- gGL.setColorMask(true, true);
- stop_glerror();
+BOOL LLTexLayerSet::isBodyRegion(const std::string& region) const
+{
+ return mInfo->mBodyRegion == region;
+}
- return success;
+const std::string LLTexLayerSet::getBodyRegion() const
+{
+ return mInfo->mBodyRegion;
}
void LLTexLayerSet::requestUpdate()
@@ -933,10 +791,9 @@ void LLTexLayerSet::createComposite()
// Composite other avatars at reduced resolution
if( !mAvatar->isSelf() )
{
- width /= 2;
- height /= 2;
+ llerrs << "composites should not be created for non-self avatars!" << llendl;
}
- mComposite = new LLTexLayerSetBuffer( this, width, height, mHasBump );
+ mComposite = new LLTexLayerSetBuffer( this, width, height );
}
}
@@ -944,7 +801,6 @@ void LLTexLayerSet::destroyComposite()
{
if( mComposite )
{
- delete mComposite;
mComposite = NULL;
}
}
@@ -967,65 +823,129 @@ LLTexLayerSetBuffer* LLTexLayerSet::getComposite()
return mComposite;
}
-void LLTexLayerSet::gatherAlphaMasks(U8 *data, S32 width, S32 height)
+void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 width, S32 height)
{
- S32 size = width * height;
-
memset(data, 255, width * height);
for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
{
- LLTexLayer* layer = *iter;
- U8* alphaData = layer->getAlphaData();
- if (!alphaData && layer->hasAlphaParams())
- {
- LLColor4 net_color;
- layer->findNetColor( &net_color );
- layer->invalidateMorphMasks();
- layer->renderAlphaMasks(mComposite->getOriginX(), mComposite->getOriginY(), width, height, &net_color);
- alphaData = layer->getAlphaData();
- }
- if (alphaData)
+ LLTexLayerInterface* layer = *iter;
+ layer->gatherAlphaMasks(data, mComposite->getOriginX(),mComposite->getOriginY(), width, height);
+ }
+
+ // Set alpha back to that of our alpha masks.
+ renderAlphaMaskTextures(mComposite->getOriginX(), mComposite->getOriginY(), width, height, true);
+}
+
+void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear)
+{
+ const LLTexLayerSetInfo *info = getInfo();
+
+ gGL.setColorMask(false, true);
+ gGL.setSceneBlendType(LLRender::BT_REPLACE);
+
+ // (Optionally) replace alpha with a single component image from a tga file.
+ if (!info->mStaticAlphaFileName.empty())
+ {
+ LLGLSNoAlphaTest gls_no_alpha_test;
+ gGL.flush();
{
- for( S32 i = 0; i < size; i++ )
+ LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(info->mStaticAlphaFileName, TRUE);
+ if( tex )
{
- U8 curAlpha = data[i];
- U16 resultAlpha = curAlpha;
- resultAlpha *= (alphaData[i] + 1);
- resultAlpha = resultAlpha >> 8;
- data[i] = (U8)resultAlpha;
+ LLGLSUIDefault gls_ui;
+ gGL.getTexUnit(0)->bind(tex);
+ gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE );
+ gl_rect_2d_simple_tex( width, height );
}
}
+ gGL.flush();
+ }
+ else if (forceClear || info->mClearAlpha || (mMaskLayerList.size() > 0))
+ {
+ // Set the alpha channel to one (clean up after previous blending)
+ gGL.flush();
+ LLGLDisable no_alpha(GL_ALPHA_TEST);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.color4f( 0.f, 0.f, 0.f, 1.f );
+
+ gl_rect_2d_simple( width, height );
+
+ gGL.flush();
+ }
+
+ // (Optional) Mask out part of the baked texture with alpha masks
+ // will still have an effect even if mClearAlpha is set or the alpha component was replaced
+ if (mMaskLayerList.size() > 0)
+ {
+ gGL.setSceneBlendType(LLRender::BT_MULT_ALPHA);
+ gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE );
+ for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++)
+ {
+ LLTexLayerInterface* layer = *iter;
+ gGL.flush();
+ layer->blendAlphaTexture(x,y,width, height);
+ gGL.flush();
+ }
+
}
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+ gGL.setColorMask(true, true);
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components)
{
+ mAvatar->applyMorphMask(tex_data, width, height, num_components, mBakedTexIndex);
+}
+
+BOOL LLTexLayerSet::isMorphValid()
+{
+ for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
+ {
+ LLTexLayerInterface* layer = *iter;
+ if (layer && !layer->isMorphValid())
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+void LLTexLayerSet::invalidateMorphMasks()
+{
for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
{
- LLTexLayer* layer = *iter;
- layer->applyMorphMask(tex_data, width, height, num_components);
+ LLTexLayerInterface* layer = *iter;
+ if (layer)
+ {
+ layer->invalidateMorphMasks();
+ }
}
}
+
//-----------------------------------------------------------------------------
// LLTexLayerInfo
//-----------------------------------------------------------------------------
-LLTexLayerInfo::LLTexLayerInfo( )
- :
+LLTexLayerInfo::LLTexLayerInfo() :
mWriteAllChannels( FALSE ),
- mRenderPass( RP_COLOR ),
+ mRenderPass(LLTexLayer::RP_COLOR),
mFixedColor( 0.f, 0.f, 0.f, 0.f ),
mLocalTexture( -1 ),
mStaticImageIsMask( FALSE ),
- mUseLocalTextureAlphaOnly( FALSE )
+ mUseLocalTextureAlphaOnly(FALSE),
+ mIsVisibilityMask(FALSE)
{
}
LLTexLayerInfo::~LLTexLayerInfo( )
{
- std::for_each(mColorInfoList.begin(), mColorInfoList.end(), DeletePointer());
- std::for_each(mAlphaInfoList.begin(), mAlphaInfoList.end(), DeletePointer());
+ std::for_each(mParamColorInfoList.begin(), mParamColorInfoList.end(), DeletePointer());
+ std::for_each(mParamAlphaInfoList.begin(), mParamAlphaInfoList.end(), DeletePointer());
}
BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node)
@@ -1048,7 +968,7 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node)
{
if( render_pass_name == "bump" )
{
- mRenderPass = RP_BUMP;
+ mRenderPass = LLTexLayer::RP_BUMP;
}
}
@@ -1057,6 +977,14 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node)
static LLStdStringHandle global_color_string = LLXmlTree::addAttributeString("global_color");
node->getFastAttributeString( global_color_string, mGlobalColor );
+ // Visibility mask (optional)
+ BOOL is_visibility;
+ static LLStdStringHandle visibility_mask_string = LLXmlTree::addAttributeString("visibility_mask");
+ if (node->getFastAttributeBOOL(visibility_mask_string, is_visibility))
+ {
+ mIsVisibilityMask = is_visibility;
+ }
+
// color attribute (optional)
LLColor4U color4u;
static LLStdStringHandle fixed_color_string = LLXmlTree::addAttributeString("fixed_color");
@@ -1070,7 +998,7 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node)
texture_node;
texture_node = node->getNextNamedChild())
{
- std::string local_texture;
+ std::string local_texture_name;
static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file");
static LLStdStringHandle local_texture_string = LLXmlTree::addAttributeString("local_texture");
static LLStdStringHandle file_is_mask_string = LLXmlTree::addAttributeString("file_is_mask");
@@ -1079,73 +1007,27 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node)
{
texture_node->getFastAttributeBOOL( file_is_mask_string, mStaticImageIsMask );
}
- else if( texture_node->getFastAttributeString( local_texture_string, local_texture ) )
+ else if (texture_node->getFastAttributeString(local_texture_string, local_texture_name))
{
texture_node->getFastAttributeBOOL( local_texture_alpha_only_string, mUseLocalTextureAlphaOnly );
- if( "upper_shirt" == local_texture )
- {
- mLocalTexture = TEX_UPPER_SHIRT;
- }
- else if( "upper_bodypaint" == local_texture )
- {
- mLocalTexture = TEX_UPPER_BODYPAINT;
- }
- else if( "lower_pants" == local_texture )
- {
- mLocalTexture = TEX_LOWER_PANTS;
- }
- else if( "lower_bodypaint" == local_texture )
- {
- mLocalTexture = TEX_LOWER_BODYPAINT;
- }
- else if( "lower_shoes" == local_texture )
- {
- mLocalTexture = TEX_LOWER_SHOES;
- }
- else if( "head_bodypaint" == local_texture )
- {
- mLocalTexture = TEX_HEAD_BODYPAINT;
- }
- else if( "lower_socks" == local_texture )
- {
- mLocalTexture = TEX_LOWER_SOCKS;
- }
- else if( "upper_jacket" == local_texture )
- {
- mLocalTexture = TEX_UPPER_JACKET;
- }
- else if( "lower_jacket" == local_texture )
- {
- mLocalTexture = TEX_LOWER_JACKET;
- }
- else if( "upper_gloves" == local_texture )
- {
- mLocalTexture = TEX_UPPER_GLOVES;
- }
- else if( "upper_undershirt" == local_texture )
- {
- mLocalTexture = TEX_UPPER_UNDERSHIRT;
- }
- else if( "lower_underpants" == local_texture )
+ /* if ("upper_shirt" == local_texture_name)
+ mLocalTexture = TEX_UPPER_SHIRT; */
+ mLocalTexture = TEX_NUM_INDICES;
+ for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
+ iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
+ iter++)
{
- mLocalTexture = TEX_LOWER_UNDERPANTS;
- }
- else if( "eyes_iris" == local_texture )
+ const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
+ if (local_texture_name == texture_dict->mName)
{
- mLocalTexture = TEX_EYES_IRIS;
+ mLocalTexture = iter->first;
+ break;
}
- else if( "skirt" == local_texture )
- {
- mLocalTexture = TEX_SKIRT;
- }
- else if( "hair_grain" == local_texture )
- {
- mLocalTexture = TEX_HAIR;
}
- else
+ if (mLocalTexture == TEX_NUM_INDICES)
{
- llwarns << "<texture> element has invalid local_texure attribute: " << mName << " " << local_texture << llendl;
+ llwarns << "<texture> element has invalid local_texure attribute: " << mName << " " << local_texture_name << llendl;
return FALSE;
}
}
@@ -1179,13 +1061,13 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node)
if( child->getChildByName( "param_color" ) )
{
// <param><param_color/></param>
- LLTexParamColorInfo* info = new LLTexParamColorInfo( );
+ LLTexLayerParamColorInfo* info = new LLTexLayerParamColorInfo();
if (!info->parseXml(child))
{
delete info;
return FALSE;
}
- mColorInfoList.push_back( info );
+ mParamColorInfoList.push_back(info);
}
else if( child->getChildByName( "param_alpha" ) )
{
@@ -1196,13 +1078,183 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node)
delete info;
return FALSE;
}
- mAlphaInfoList.push_back( info );
+ mParamAlphaInfoList.push_back(info);
}
}
return TRUE;
}
+BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar)
+{
+ BOOL success = TRUE;
+ for (param_color_info_list_t::iterator color_info_iter = mParamColorInfoList.begin();
+ color_info_iter != mParamColorInfoList.end();
+ color_info_iter++)
+ {
+ LLTexLayerParamColorInfo * color_info = *color_info_iter;
+ LLTexLayerParamColor* param_color = new LLTexLayerParamColor(avatar);
+ if (!param_color->setInfo(color_info, TRUE))
+ {
+ llwarns << "NULL TexLayer Color Param could not be added to visual param list. Deleting." << llendl;
+ delete param_color;
+ success = FALSE;
+ }
+ }
+
+ for (param_alpha_info_list_t::iterator alpha_info_iter = mParamAlphaInfoList.begin();
+ alpha_info_iter != mParamAlphaInfoList.end();
+ alpha_info_iter++)
+ {
+ LLTexLayerParamAlphaInfo * alpha_info = *alpha_info_iter;
+ LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha(avatar);
+ if (!param_alpha->setInfo(alpha_info, TRUE))
+ {
+ llwarns << "NULL TexLayer Alpha Param could not be added to visual param list. Deleting." << llendl;
+ delete param_alpha;
+ success = FALSE;
+ }
+ }
+
+ return success;
+}
+
+LLTexLayerInterface::LLTexLayerInterface(LLTexLayerSet* const layer_set):
+ mTexLayerSet( layer_set ),
+ mMorphMasksValid( FALSE ),
+ mStaticImageInvalid( FALSE ),
+ mInfo(NULL),
+ mHasMorph(FALSE)
+{
+}
+
+LLTexLayerInterface::LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable):
+ mTexLayerSet( layer.mTexLayerSet )
+{
+ // don't add visual params for cloned layers
+ setInfo(layer.getInfo(), wearable);
+
+ mHasMorph = layer.mHasMorph;
+}
+
+BOOL LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearable ) // This sets mInfo and calls initialization functions
+{
+ //llassert(mInfo == NULL); // nyx says this is probably bogus but needs investigating
+ if (mInfo != NULL) // above llassert(), but softened into a warning
+ {
+ llwarns << "BAD STUFF! mInfo != NULL" << llendl;
+ }
+ mInfo = info;
+ //mID = info->mID; // No ID
+
+ mParamColorList.reserve(mInfo->mParamColorInfoList.size());
+ for (param_color_info_list_t::const_iterator iter = mInfo->mParamColorInfoList.begin();
+ iter != mInfo->mParamColorInfoList.end();
+ iter++)
+ {
+ LLTexLayerParamColor* param_color;
+ if (!wearable)
+ {
+ param_color = new LLTexLayerParamColor(this);
+ if (!param_color->setInfo(*iter, TRUE))
+ {
+ mInfo = NULL;
+ return FALSE;
+ }
+ }
+ else
+ {
+ param_color = (LLTexLayerParamColor*)wearable->getVisualParam((*iter)->getID());
+ if (!param_color)
+ {
+ mInfo = NULL;
+ return FALSE;
+ }
+ }
+ mParamColorList.push_back( param_color );
+ }
+
+ mParamAlphaList.reserve(mInfo->mParamAlphaInfoList.size());
+ for (param_alpha_info_list_t::const_iterator iter = mInfo->mParamAlphaInfoList.begin();
+ iter != mInfo->mParamAlphaInfoList.end();
+ iter++)
+ {
+ LLTexLayerParamAlpha* param_alpha;
+ if (!wearable)
+ {
+ param_alpha = new LLTexLayerParamAlpha( this );
+ if (!param_alpha->setInfo(*iter, TRUE))
+ {
+ mInfo = NULL;
+ return FALSE;
+ }
+ }
+ else
+ {
+ param_alpha = (LLTexLayerParamAlpha*) wearable->getVisualParam((*iter)->getID());
+ if (!param_alpha)
+ {
+ mInfo = NULL;
+ return FALSE;
+ }
+ }
+ mParamAlphaList.push_back( param_alpha );
+ }
+
+ return TRUE;
+}
+
+/*virtual*/ void LLTexLayerInterface::requestUpdate()
+{
+ mTexLayerSet->requestUpdate();
+}
+
+const std::string& LLTexLayerInterface::getName() const
+{
+ return mInfo->mName;
+}
+
+LLTexLayerInterface::ERenderPass LLTexLayerInterface::getRenderPass() const
+{
+ return mInfo->mRenderPass;
+}
+
+const std::string& LLTexLayerInterface::getGlobalColor() const
+{
+ return mInfo->mGlobalColor;
+}
+
+BOOL LLTexLayerInterface::isVisibilityMask() const
+{
+ return mInfo->mIsVisibilityMask;
+}
+
+void LLTexLayerInterface::invalidateMorphMasks()
+{
+ mMorphMasksValid = FALSE;
+}
+
+LLViewerVisualParam* LLTexLayerInterface::getVisualParamPtr(S32 index)
+{
+ LLViewerVisualParam *result = NULL;
+ for (param_color_list_t::iterator color_iter = mParamColorList.begin(); color_iter != mParamColorList.end() && !result; ++color_iter)
+ {
+ if ((*color_iter)->getID() == index)
+ {
+ result = *color_iter;
+ }
+ }
+ for (param_alpha_list_t::iterator alpha_iter = mParamAlphaList.begin(); alpha_iter != mParamAlphaList.end() && !result; ++alpha_iter)
+ {
+ if ((*alpha_iter)->getID() == index)
+ {
+ result = *alpha_iter;
+ }
+ }
+
+ return result;
+}
+
//-----------------------------------------------------------------------------
// LLTexLayer
// A single texture layer, consisting of:
@@ -1216,12 +1268,21 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node)
// * a texture entry index (TE)
// * (optional) one or more alpha parameters (weighted alpha textures)
//-----------------------------------------------------------------------------
-LLTexLayer::LLTexLayer( LLTexLayerSet* layer_set )
- :
- mTexLayerSet( layer_set ),
- mMorphMasksValid( FALSE ),
- mStaticImageInvalid( FALSE ),
- mInfo( NULL )
+LLTexLayer::LLTexLayer(LLTexLayerSet* const layer_set) :
+ LLTexLayerInterface( layer_set ),
+ mLocalTextureObject(NULL)
+{
+}
+
+LLTexLayer::LLTexLayer(const LLTexLayer &layer, LLWearable *wearable) :
+ LLTexLayerInterface( layer, wearable ),
+ mLocalTextureObject(NULL)
+{
+}
+
+LLTexLayer::LLTexLayer(const LLTexLayerTemplate &layer_template, LLLocalTextureObject *lto, LLWearable *wearable) :
+ LLTexLayerInterface( layer_template, wearable ),
+ mLocalTextureObject(lto)
{
}
@@ -1238,144 +1299,92 @@ LLTexLayer::~LLTexLayer()
U8* alpha_data = iter->second;
delete [] alpha_data;
}
+
}
//-----------------------------------------------------------------------------
// setInfo
//-----------------------------------------------------------------------------
-BOOL LLTexLayer::setInfo(LLTexLayerInfo* info)
+BOOL LLTexLayer::setInfo(const LLTexLayerInfo* info, LLWearable* wearable )
{
- llassert(mInfo == NULL);
- mInfo = info;
- //mID = info->mID; // No ID
-
- if (info->mRenderPass == RP_BUMP)
- mTexLayerSet->setBump(TRUE);
-
- {
- LLTexLayerInfo::morph_name_list_t::iterator iter;
- for (iter = mInfo->mMorphNameList.begin(); iter != mInfo->mMorphNameList.end(); iter++)
- {
- // *FIX: we assume that the referenced visual param is a
- // morph target, need a better way of actually looking
- // this up.
- LLPolyMorphTarget *morph_param;
- std::string *name = &(iter->first);
- morph_param = (LLPolyMorphTarget *)(getTexLayerSet()->getAvatar()->getVisualParam(name->c_str()));
- if (morph_param)
- {
- BOOL invert = iter->second;
- addMaskedMorph(morph_param, invert);
- }
- }
- }
-
- {
- LLTexLayerInfo::color_info_list_t::iterator iter;
- mParamColorList.reserve(mInfo->mColorInfoList.size());
- for (iter = mInfo->mColorInfoList.begin(); iter != mInfo->mColorInfoList.end(); iter++)
- {
- LLTexParamColor* param_color = new LLTexParamColor( this );
- if (!param_color->setInfo(*iter))
- {
- mInfo = NULL;
- return FALSE;
- }
- mParamColorList.push_back( param_color );
- }
- }
- {
- LLTexLayerInfo::alpha_info_list_t::iterator iter;
- mParamAlphaList.reserve(mInfo->mAlphaInfoList.size());
- for (iter = mInfo->mAlphaInfoList.begin(); iter != mInfo->mAlphaInfoList.end(); iter++)
- {
- LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha( this );
- if (!param_alpha->setInfo(*iter))
- {
- mInfo = NULL;
- return FALSE;
- }
- mParamAlphaList.push_back( param_alpha );
- }
- }
-
- return TRUE;
+ return LLTexLayerInterface::setInfo(info, wearable);
}
-#if 0 // obsolete
-//-----------------------------------------------------------------------------
-// parseData
-//-----------------------------------------------------------------------------
-BOOL LLTexLayer::parseData( LLXmlTreeNode* node )
+//static
+void LLTexLayer::calculateTexLayerColor(const param_color_list_t &param_list, LLColor4 &net_color)
{
- LLTexLayerInfo *info = new LLTexLayerInfo;
-
- if (!info->parseXml(node))
+ for (param_color_list_t::const_iterator iter = param_list.begin();
+ iter != param_list.end(); iter++)
{
- delete info;
- return FALSE;
- }
- if (!setInfo(info))
- {
- delete info;
- return FALSE;
+ const LLTexLayerParamColor* param = *iter;
+ LLColor4 param_net = param->getNetColor();
+ const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)param->getInfo();
+ switch(info->getOperation())
+ {
+ case LLTexLayerParamColor::OP_ADD:
+ net_color += param_net;
+ break;
+ case LLTexLayerParamColor::OP_MULTIPLY:
+ net_color = net_color * param_net;
+ break;
+ case LLTexLayerParamColor::OP_BLEND:
+ net_color = lerp(net_color, param_net, param->getWeight());
+ break;
+ default:
+ llassert(0);
+ break;
+ }
}
- return TRUE;
+ net_color.clamp();
}
-#endif
-
-//-----------------------------------------------------------------------------
-
-void LLTexLayer::deleteCaches()
+/*virtual*/ void LLTexLayer::deleteCaches()
{
- for( alpha_list_t::iterator iter = mParamAlphaList.begin();
+ // Only need to delete caches for alpha params. Color params don't hold extra memory
+ for (param_alpha_list_t::iterator iter = mParamAlphaList.begin();
iter != mParamAlphaList.end(); iter++ )
{
LLTexLayerParamAlpha* param = *iter;
param->deleteCaches();
}
- mStaticImageRaw = NULL;
}
-BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
+BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height)
{
LLGLEnable color_mat(GL_COLOR_MATERIAL);
gPipeline.disableLights();
- BOOL success = TRUE;
-
- BOOL color_specified = FALSE;
- BOOL alpha_mask_specified = FALSE;
-
LLColor4 net_color;
- color_specified = findNetColor( &net_color );
-
+ BOOL color_specified = findNetColor(&net_color);
+
if (mTexLayerSet->getAvatar()->mIsDummy)
{
color_specified = true;
net_color = LLVOAvatar::getDummyColor();
}
+ BOOL success = TRUE;
+
// If you can't see the layer, don't render it.
if( is_approx_zero( net_color.mV[VW] ) )
{
return success;
}
- alpha_list_t::iterator iter = mParamAlphaList.begin();
+ BOOL alpha_mask_specified = FALSE;
+ param_alpha_list_t::const_iterator iter = mParamAlphaList.begin();
if( iter != mParamAlphaList.end() )
{
// If we have alpha masks, but we're skipping all of them, skip the whole layer.
// However, we can't do this optimization if we have morph masks that need updating.
- if( mMaskedMorphs.empty() )
+/* if (!mHasMorph)
{
BOOL skip_layer = TRUE;
while( iter != mParamAlphaList.end() )
{
- LLTexLayerParamAlpha* param = *iter;
+ const LLTexLayerParamAlpha* param = *iter;
if( !param->getSkip() )
{
@@ -1390,9 +1399,9 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
{
return success;
}
- }
+ }//*/
- renderAlphaMasks( x, y, width, height, &net_color );
+ renderMorphMasks(x, y, width, height, net_color);
alpha_mask_specified = TRUE;
gGL.flush();
gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ONE_MINUS_DEST_ALPHA);
@@ -1409,16 +1418,28 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
if( (getInfo()->mLocalTexture != -1) && !getInfo()->mUseLocalTextureAlphaOnly )
{
{
- LLImageGL* image_gl = NULL;
- if( mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl ) )
+ LLViewerTexture* tex = NULL;
+ if (mLocalTextureObject && mLocalTextureObject->getImage())
+ {
+ tex = mLocalTextureObject->getImage();
+ if (mLocalTextureObject->getID() == IMG_DEFAULT_AVATAR)
+ {
+ tex = NULL;
+ }
+ }
+ else
+ {
+ llinfos << "lto not defined or image not defined: " << getInfo()->getLocalTexture() << " lto: " << mLocalTextureObject << llendl;
+ }
+// if( mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl ) )
{
- if( image_gl )
+ if( tex )
{
LLGLDisable alpha_test(getInfo()->mWriteAllChannels ? GL_ALPHA_TEST : 0);
- LLTexUnit::eTextureAddressMode old_mode = image_gl->getAddressMode();
+ LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode();
- gGL.getTexUnit(0)->bind(image_gl);
+ gGL.getTexUnit(0)->bind(tex, TRUE);
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
gl_rect_2d_simple_tex( width, height );
@@ -1427,20 +1448,20 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
}
- else
- {
- success = FALSE;
- }
+// else
+// {
+// success = FALSE;
+// }
}
}
if( !getInfo()->mStaticImageFileName.empty() )
{
{
- LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask );
- if( image_gl )
+ LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask);
+ if( tex )
{
- gGL.getTexUnit(0)->bind(image_gl);
+ gGL.getTexUnit(0)->bind(tex, TRUE);
gl_rect_2d_simple_tex( width, height );
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
@@ -1451,14 +1472,14 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
}
}
- if( ((-1 == getInfo()->mLocalTexture) ||
+ if(((-1 == getInfo()->mLocalTexture) ||
getInfo()->mUseLocalTextureAlphaOnly) &&
getInfo()->mStaticImageFileName.empty() &&
color_specified )
{
LLGLDisable no_alpha(GL_ALPHA_TEST);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.color4fv( net_color.mV);
+ gGL.color4fv( net_color.mV );
gl_rect_2d_simple( width, height );
}
@@ -1480,12 +1501,13 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
U8* LLTexLayer::getAlphaData()
{
LLCRC alpha_mask_crc;
- const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID((ETextureIndex)getInfo()->mLocalTexture);
+ const LLUUID& uuid = getUUID();
alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES);
- for( alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ )
+ for (param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++)
{
- LLTexLayerParamAlpha* param = *iter;
+ const LLTexLayerParamAlpha* param = *iter;
+ // MULTI-WEARABLE: verify visual parameters used here
F32 param_weight = param->getWeight();
alpha_mask_crc.update((U8*)&param_weight, sizeof(F32));
}
@@ -1496,7 +1518,7 @@ U8* LLTexLayer::getAlphaData()
return (iter2 == mAlphaCache.end()) ? 0 : iter2->second;
}
-BOOL LLTexLayer::findNetColor( LLColor4* net_color )
+BOOL LLTexLayer::findNetColor(LLColor4* net_color) const
{
// Color is either:
// * one or more color parameters (weighted colors) (which may make use of a global color or fixed color)
@@ -1510,8 +1532,7 @@ BOOL LLTexLayer::findNetColor( LLColor4* net_color )
{
net_color->setVec( mTexLayerSet->getAvatar()->getGlobalColor( getInfo()->mGlobalColor ) );
}
- else
- if( getInfo()->mFixedColor.mV[VW] )
+ else if (getInfo()->mFixedColor.mV[VW])
{
net_color->setVec( getInfo()->mFixedColor );
}
@@ -1520,30 +1541,7 @@ BOOL LLTexLayer::findNetColor( LLColor4* net_color )
net_color->setVec( 0.f, 0.f, 0.f, 0.f );
}
- for( color_list_t::iterator iter = mParamColorList.begin();
- iter != mParamColorList.end(); iter++ )
- {
- LLTexParamColor* param = *iter;
- LLColor4 param_net = param->getNetColor();
- switch( param->getOperation() )
- {
- case OP_ADD:
- *net_color += param_net;
- break;
- case OP_MULTIPLY:
- net_color->mV[VX] *= param_net.mV[VX];
- net_color->mV[VY] *= param_net.mV[VY];
- net_color->mV[VZ] *= param_net.mV[VZ];
- net_color->mV[VW] *= param_net.mV[VW];
- break;
- case OP_BLEND:
- net_color->setVec( lerp(*net_color, param_net, param->getWeight()) );
- break;
- default:
- llassert(0);
- break;
- }
- }
+ calculateTexLayerColor(mParamColorList, *net_color);
return TRUE;
}
@@ -1564,8 +1562,52 @@ BOOL LLTexLayer::findNetColor( LLColor4* net_color )
return FALSE; // No need to draw a separate colored polygon
}
+BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height)
+{
+ BOOL success = TRUE;
+
+ gGL.flush();
+
+ if( !getInfo()->mStaticImageFileName.empty() )
+ {
+ LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask );
+ if( tex )
+ {
+ LLGLSNoAlphaTest gls_no_alpha_test;
+ gGL.getTexUnit(0)->bind(tex, TRUE);
+ gl_rect_2d_simple_tex( width, height );
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ }
+ else
+ {
+ success = FALSE;
+ }
+ }
+ else
+ {
+ if (getInfo()->mLocalTexture >=0 && getInfo()->mLocalTexture < TEX_NUM_INDICES)
+ {
+ LLViewerTexture* tex = mLocalTextureObject->getImage();
+ if (tex)
+ {
+ LLGLSNoAlphaTest gls_no_alpha_test;
+ gGL.getTexUnit(0)->bind(tex);
+ gl_rect_2d_simple_tex( width, height );
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ success = TRUE;
+ }
+ }
+ }
+
+ return success;
+}
+
+/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height)
+{
+ addAlphaMask(data, originX, originY, width, height);
+}
-BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4* colorp )
+BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color)
{
BOOL success = TRUE;
@@ -1573,9 +1615,7 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4
gGL.setColorMask(false, true);
- alpha_list_t::iterator iter = mParamAlphaList.begin();
- LLTexLayerParamAlpha* first_param = *iter;
-
+ LLTexLayerParamAlpha* first_param = *mParamAlphaList.begin();
// Note: if the first param is a mulitply, multiply against the current buffer's alpha
if( !first_param || !first_param->getMultiplyBlend() )
{
@@ -1593,8 +1633,7 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4
// Accumulate alphas
LLGLSNoAlphaTest gls_no_alpha_test;
gGL.color4f( 1.f, 1.f, 1.f, 1.f );
-
- for( iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ )
+ for (param_alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++)
{
LLTexLayerParamAlpha* param = *iter;
success &= param->render( x, y, width, height );
@@ -1602,66 +1641,51 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4
// Approximates a min() function
gGL.flush();
- gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO);
+ gGL.setSceneBlendType(LLRender::BT_MULT_ALPHA);
// Accumulate the alpha component of the texture
if( getInfo()->mLocalTexture != -1 )
{
+ LLViewerTexture* tex = mLocalTextureObject->getImage();
+ if( tex && (tex->getComponents() == 4) )
{
- LLImageGL* image_gl = NULL;
- if( mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl ) )
- {
- if( image_gl && (image_gl->getComponents() == 4) )
- {
- LLGLSNoAlphaTest gls_no_alpha_test;
+ LLGLSNoAlphaTest gls_no_alpha_test;
- LLTexUnit::eTextureAddressMode old_mode = image_gl->getAddressMode();
-
- gGL.getTexUnit(0)->bind(image_gl);
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+ LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode();
+
+ gGL.getTexUnit(0)->bind(tex, TRUE);
+ gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
- gl_rect_2d_simple_tex( width, height );
+ gl_rect_2d_simple_tex( width, height );
- gGL.getTexUnit(0)->setTextureAddressMode(old_mode);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- }
- }
- else
- {
- success = FALSE;
- }
+ gGL.getTexUnit(0)->setTextureAddressMode(old_mode);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
}
if( !getInfo()->mStaticImageFileName.empty() )
{
+ LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask);
+ if( tex )
{
- LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask );
- if( image_gl )
- {
- if( (image_gl->getComponents() == 4) ||
- ( (image_gl->getComponents() == 1) && getInfo()->mStaticImageIsMask ) )
- {
- LLGLSNoAlphaTest gls_no_alpha_test;
- gGL.getTexUnit(0)->bind(image_gl);
- gl_rect_2d_simple_tex( width, height );
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- }
- }
- else
+ if( (tex->getComponents() == 4) ||
+ ( (tex->getComponents() == 1) && getInfo()->mStaticImageIsMask ) )
{
- success = FALSE;
+ LLGLSNoAlphaTest gls_no_alpha_test;
+ gGL.getTexUnit(0)->bind(tex, TRUE);
+ gl_rect_2d_simple_tex( width, height );
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
}
}
// Draw a rectangle with the layer color to multiply the alpha by that color's alpha.
// Note: we're still using gGL.blendFunc( GL_DST_ALPHA, GL_ZERO );
- if( colorp->mV[VW] != 1.f )
+ if (layer_color.mV[VW] != 1.f)
{
LLGLDisable no_alpha(GL_ALPHA_TEST);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.color4fv( colorp->mV );
+ gGL.color4fv(layer_color.mV);
gl_rect_2d_simple( width, height );
}
@@ -1670,34 +1694,28 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4
gGL.setColorMask(true, true);
- if (!mMorphMasksValid && !mMaskedMorphs.empty())
+ if (hasMorph() && success)
{
LLCRC alpha_mask_crc;
- const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID((ETextureIndex)getInfo()->mLocalTexture);
+ const LLUUID& uuid = getUUID();
alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES);
- for( alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ )
+ for (param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++)
{
- LLTexLayerParamAlpha* param = *iter;
+ const LLTexLayerParamAlpha* param = *iter;
F32 param_weight = param->getWeight();
alpha_mask_crc.update((U8*)&param_weight, sizeof(F32));
}
U32 cache_index = alpha_mask_crc.getCRC();
-
- alpha_cache_t::iterator iter2 = mAlphaCache.find(cache_index);
- U8* alpha_data;
- if (iter2 != mAlphaCache.end())
- {
- alpha_data = iter2->second;
- }
- else
+ U8* alpha_data = get_if_there(mAlphaCache,cache_index,(U8*)NULL);
+ if (!alpha_data)
{
// clear out a slot if we have filled our cache
S32 max_cache_entries = getTexLayerSet()->getAvatar()->isSelf() ? 4 : 1;
while ((S32)mAlphaCache.size() >= max_cache_entries)
{
- iter2 = mAlphaCache.begin(); // arbitrarily grab the first entry
+ alpha_cache_t::iterator iter2 = mAlphaCache.begin(); // arbitrarily grab the first entry
alpha_data = iter2->second;
delete [] alpha_data;
mAlphaCache.erase(iter2);
@@ -1710,764 +1728,329 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4
getTexLayerSet()->getAvatar()->dirtyMesh();
mMorphMasksValid = TRUE;
-
- for( morph_list_t::iterator iter3 = mMaskedMorphs.begin();
- iter3 != mMaskedMorphs.end(); iter3++ )
- {
- LLMaskedMorph* maskedMorph = &(*iter3);
- maskedMorph->mMorphTarget->applyMask(alpha_data, width, height, 1, maskedMorph->mInvert);
- }
+ getTexLayerSet()->applyMorphMask(alpha_data, width, height, 1);
}
return success;
}
-void LLTexLayer::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components)
-{
- for( morph_list_t::iterator iter = mMaskedMorphs.begin();
- iter != mMaskedMorphs.end(); iter++ )
- {
- LLMaskedMorph* maskedMorph = &(*iter);
- maskedMorph->mMorphTarget->applyMask(tex_data, width, height, num_components, maskedMorph->mInvert);
- }
-}
-
-// Returns TRUE on success.
-BOOL LLTexLayer::renderImageRaw( U8* in_data, S32 in_width, S32 in_height, S32 in_components, S32 width, S32 height, BOOL is_mask )
+void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height)
{
- if (!in_data)
- {
- return FALSE;
- }
- GLenum format_options[4] = { GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA };
- GLenum format = format_options[in_components-1];
- if( is_mask )
+ S32 size = width * height;
+ U8* alphaData = getAlphaData();
+ if (!alphaData && hasAlphaParams())
{
- llassert( 1 == in_components );
- format = GL_ALPHA;
+ LLColor4 net_color;
+ findNetColor( &net_color );
+ // TODO: eliminate need for layer morph mask valid flag
+ invalidateMorphMasks();
+ renderMorphMasks(originX, originY, width, height, net_color);
+ alphaData = getAlphaData();
}
-
- if( (in_width != SCRATCH_TEX_WIDTH) || (in_height != SCRATCH_TEX_HEIGHT) )
+ if (alphaData)
{
- LLGLSNoAlphaTest gls_no_alpha_test;
-
- GLenum internal_format_options[4] = { GL_LUMINANCE8, GL_LUMINANCE8_ALPHA8, GL_RGB8, GL_RGBA8 };
- GLenum internal_format = internal_format_options[in_components-1];
- if( is_mask )
+ for( S32 i = 0; i < size; i++ )
{
- llassert( 1 == in_components );
- internal_format = GL_ALPHA8;
+ U8 curAlpha = data[i];
+ U16 resultAlpha = curAlpha;
+ resultAlpha *= (alphaData[i] + 1);
+ resultAlpha = resultAlpha >> 8;
+ data[i] = (U8)resultAlpha;
}
-
- U32 name = 0;
- LLImageGL::generateTextures(1, &name );
- stop_glerror();
-
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, name);
- stop_glerror();
-
- LLImageGL::setManualImage(
- GL_TEXTURE_2D, 0, internal_format,
- in_width, in_height,
- format, GL_UNSIGNED_BYTE, in_data );
- stop_glerror();
-
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
-
- gl_rect_2d_simple_tex( width, height );
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- LLImageGL::deleteTextures(1, &name );
- stop_glerror();
}
- else
- {
- LLGLSNoAlphaTest gls_no_alpha_test;
+}
- if( !mTexLayerSet->getAvatar()->bindScratchTexture(format) )
+/*virtual*/ BOOL LLTexLayer::isInvisibleAlphaMask()
+{
+ if (mLocalTextureObject)
+ {
+ if (mLocalTextureObject->getID() == IMG_INVISIBLE)
{
- return FALSE;
+ return TRUE;
}
-
- glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, in_width, in_height, format, GL_UNSIGNED_BYTE, in_data );
- stop_glerror();
-
- gl_rect_2d_simple_tex( width, height );
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
- return TRUE;
-}
-
-void LLTexLayer::requestUpdate()
-{
- mTexLayerSet->requestUpdate();
-}
-
-void LLTexLayer::addMaskedMorph(LLPolyMorphTarget* morph_target, BOOL invert)
-{
- mMaskedMorphs.push_front(LLMaskedMorph(morph_target, invert));
-}
-
-void LLTexLayer::invalidateMorphMasks()
-{
- mMorphMasksValid = FALSE;
-}
-
-//-----------------------------------------------------------------------------
-// LLTexLayerParamAlphaInfo
-//-----------------------------------------------------------------------------
-LLTexLayerParamAlphaInfo::LLTexLayerParamAlphaInfo( )
- :
- mMultiplyBlend( FALSE ),
- mSkipIfZeroWeight( FALSE ),
- mDomain( 0.f )
-{
+ return FALSE;
}
-BOOL LLTexLayerParamAlphaInfo::parseXml(LLXmlTreeNode* node)
+// private helper function
+LLUUID LLTexLayer::getUUID()
{
- llassert( node->hasName( "param" ) && node->getChildByName( "param_alpha" ) );
-
- if( !LLViewerVisualParamInfo::parseXml(node) )
- return FALSE;
-
- LLXmlTreeNode* param_alpha_node = node->getChildByName( "param_alpha" );
- if( !param_alpha_node )
+ LLUUID uuid;
+ if( getInfo()->mLocalTexture != -1 )
{
- return FALSE;
+ LLViewerTexture* tex = mLocalTextureObject->getImage();
+ if (tex)
+ {
+ uuid = mLocalTextureObject->getID();
+ }
}
-
- static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file");
- if( param_alpha_node->getFastAttributeString( tga_file_string, mStaticImageFileName ) )
+ if( !getInfo()->mStaticImageFileName.empty() )
{
- // Don't load the image file until it's actually needed.
+ LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask);
+ if( tex )
+ {
+ uuid = tex->getID();
+ }
}
-// else
-// {
-// llwarns << "<param_alpha> element is missing tga_file attribute." << llendl;
-// }
-
- static LLStdStringHandle multiply_blend_string = LLXmlTree::addAttributeString("multiply_blend");
- param_alpha_node->getFastAttributeBOOL( multiply_blend_string, mMultiplyBlend );
-
- static LLStdStringHandle skip_if_zero_string = LLXmlTree::addAttributeString("skip_if_zero");
- param_alpha_node->getFastAttributeBOOL( skip_if_zero_string, mSkipIfZeroWeight );
-
- static LLStdStringHandle domain_string = LLXmlTree::addAttributeString("domain");
- param_alpha_node->getFastAttributeF32( domain_string, mDomain );
-
- return TRUE;
+ return uuid;
}
+
//-----------------------------------------------------------------------------
-// LLTexLayerParamAlpha
+// LLTexLayerTemplate
+// A single texture layer, consisting of:
+// * color, consisting of either
+// * one or more color parameters (weighted colors)
+// * a reference to a global color
+// * a fixed color with non-zero alpha
+// * opaque white (the default)
+// * (optional) a texture defined by either
+// * a GUID
+// * a texture entry index (TE)
+// * (optional) one or more alpha parameters (weighted alpha textures)
//-----------------------------------------------------------------------------
-
-// static
-LLTexLayerParamAlpha::param_alpha_ptr_list_t LLTexLayerParamAlpha::sInstances;
-
-// static
-void LLTexLayerParamAlpha::dumpCacheByteCount()
+LLTexLayerTemplate::LLTexLayerTemplate(LLTexLayerSet* layer_set) :
+ LLTexLayerInterface(layer_set)
{
- S32 gl_bytes = 0;
- getCacheByteCount( &gl_bytes );
- llinfos << "Processed Alpha Texture Cache GL:" << (gl_bytes/1024) << "KB" << llendl;
}
-// static
-void LLTexLayerParamAlpha::getCacheByteCount( S32* gl_bytes )
+LLTexLayerTemplate::LLTexLayerTemplate(const LLTexLayerTemplate &layer) :
+ LLTexLayerInterface(layer)
{
- *gl_bytes = 0;
-
- for( param_alpha_ptr_list_t::iterator iter = sInstances.begin();
- iter != sInstances.end(); iter++ )
- {
- LLTexLayerParamAlpha* instance = *iter;
- LLImageGL* image_gl = instance->mCachedProcessedImageGL;
- if( image_gl )
- {
- S32 bytes = (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents();
-
- if( image_gl->getHasGLTexture() )
- {
- *gl_bytes += bytes;
- }
- }
- }
}
-LLTexLayerParamAlpha::LLTexLayerParamAlpha( LLTexLayer* layer )
- :
- mCachedProcessedImageGL( NULL ),
- mTexLayer( layer ),
- mNeedsCreateTexture( FALSE ),
- mStaticImageInvalid( FALSE ),
- mAvgDistortionVec(1.f, 1.f, 1.f),
- mCachedEffectiveWeight(0.f)
+LLTexLayerTemplate::~LLTexLayerTemplate()
{
- sInstances.push_front( this );
}
-LLTexLayerParamAlpha::~LLTexLayerParamAlpha()
-{
- deleteCaches();
- sInstances.remove( this );
-}
-
-//-----------------------------------------------------------------------------
-// setInfo()
//-----------------------------------------------------------------------------
-BOOL LLTexLayerParamAlpha::setInfo(LLTexLayerParamAlphaInfo *info)
-{
- llassert(mInfo == NULL);
- if (info->mID < 0)
- return FALSE;
- mInfo = info;
- mID = info->mID;
-
- mTexLayer->getTexLayerSet()->getAvatar()->addVisualParam( this );
- setWeight(getDefaultWeight(), FALSE );
-
- return TRUE;
-}
-
+// setInfo
//-----------------------------------------------------------------------------
-void LLTexLayerParamAlpha::deleteCaches()
+/*virtual*/ BOOL LLTexLayerTemplate::setInfo(const LLTexLayerInfo* info, LLWearable* wearable )
{
- mStaticImageTGA = NULL; // deletes image
- mCachedProcessedImageGL = NULL;
- mStaticImageRaw = NULL;
- mNeedsCreateTexture = FALSE;
+ return LLTexLayerInterface::setInfo(info, wearable);
}
-void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL set_by_user)
+U32 LLTexLayerTemplate::updateWearableCache()
{
- if (mIsAnimating)
+ mWearableCache.clear();
+
+ S32 te = mInfo->mLocalTexture;
+ if (te == -1)
{
- return;
+ //this isn't a cloneable layer
+ return 0;
}
- F32 min_weight = getMinWeight();
- F32 max_weight = getMaxWeight();
- F32 new_weight = llclamp(weight, min_weight, max_weight);
- U8 cur_u8 = F32_to_U8( mCurWeight, min_weight, max_weight );
- U8 new_u8 = F32_to_U8( new_weight, min_weight, max_weight );
- if( cur_u8 != new_u8)
+ EWearableType wearable_type = LLVOAvatarDictionary::getTEWearableType((ETextureIndex)te);
+ U32 num_wearables = gAgentWearables.getWearableCount(wearable_type);
+ U32 added = 0;
+ for (U32 i = 0; i < num_wearables; i++)
{
- mCurWeight = new_weight;
-
- LLVOAvatar* avatar = mTexLayer->getTexLayerSet()->getAvatar();
- if( avatar->getSex() & getSex() )
+ LLWearable* wearable = gAgentWearables.getWearable(wearable_type, i);
+ if (!wearable)
{
- if ( gAgent.cameraCustomizeAvatar() )
- {
- set_by_user = FALSE;
- }
- avatar->invalidateComposite( mTexLayer->getTexLayerSet(), set_by_user );
- mTexLayer->invalidateMorphMasks();
- avatar->updateMeshTextures();
+ continue;
}
+ mWearableCache.push_back(wearable);
+ added++;
}
+ return added;
}
-
-void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value, BOOL set_by_user)
-{
- mTargetWeight = target_value;
- setWeight(target_value, set_by_user);
- mIsAnimating = TRUE;
- if (mNext)
- {
- mNext->setAnimationTarget(target_value, set_by_user);
- }
-}
-
-void LLTexLayerParamAlpha::animate(F32 delta, BOOL set_by_user)
+LLTexLayer* LLTexLayerTemplate::getLayer(U32 i)
{
- if (mNext)
+ if (mWearableCache.size() <= i || i < 0)
{
- mNext->animate(delta, set_by_user);
+ return NULL;
}
-}
-
-BOOL LLTexLayerParamAlpha::getSkip()
-{
- LLVOAvatar *avatar = mTexLayer->getTexLayerSet()->getAvatar();
-
- if( getInfo()->mSkipIfZeroWeight )
+ LLWearable *wearable = mWearableCache[i];
+ LLLocalTextureObject *lto = NULL;
+ LLTexLayer *layer = NULL;
+ if (wearable)
{
- F32 effective_weight = ( avatar->getSex() & getSex() ) ? mCurWeight : getDefaultWeight();
- if (is_approx_zero( effective_weight ))
- {
- return TRUE;
- }
+ lto = wearable->getLocalTextureObject(mInfo->mLocalTexture);
}
-
- EWearableType type = (EWearableType)getWearableType();
- if( (type != WT_INVALID) && !avatar->isWearingWearableType( type ) )
+ if (lto)
{
- return TRUE;
+ layer = lto->getTexLayer(getName());
}
-
- return FALSE;
+ return layer;
}
-
-BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height )
+/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height)
{
BOOL success = TRUE;
-
- F32 effective_weight = ( mTexLayer->getTexLayerSet()->getAvatar()->getSex() & getSex() ) ? mCurWeight : getDefaultWeight();
- BOOL weight_changed = effective_weight != mCachedEffectiveWeight;
- if( getSkip() )
- {
- return success;
- }
-
- gGL.flush();
- if( getInfo()->mMultiplyBlend )
- {
- gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO); // Multiplication: approximates a min() function
- }
- else
- {
- gGL.setSceneBlendType(LLRender::BT_ADD); // Addition: approximates a max() function
- }
-
- if( !getInfo()->mStaticImageFileName.empty() && !mStaticImageInvalid)
+ updateWearableCache();
+ for (wearable_cache_t::const_iterator iter = mWearableCache.begin(); iter!= mWearableCache.end(); iter++)
{
- if( mStaticImageTGA.isNull() )
- {
- // Don't load the image file until we actually need it the first time. Like now.
- mStaticImageTGA = gTexStaticImageList.getImageTGA( getInfo()->mStaticImageFileName );
- // We now have something in one of our caches
- LLTexLayerSet::sHasCaches |= mStaticImageTGA.notNull() ? TRUE : FALSE;
-
- if( mStaticImageTGA.isNull() )
- {
- llwarns << "Unable to load static file: " << getInfo()->mStaticImageFileName << llendl;
- mStaticImageInvalid = TRUE; // don't try again.
- return FALSE;
- }
- }
-
- const S32 image_tga_width = mStaticImageTGA->getWidth();
- const S32 image_tga_height = mStaticImageTGA->getHeight();
- if( !mCachedProcessedImageGL ||
- (mCachedProcessedImageGL->getWidth() != image_tga_width) ||
- (mCachedProcessedImageGL->getHeight() != image_tga_height) ||
- (weight_changed) )
+ LLWearable* wearable = NULL;
+ LLLocalTextureObject *lto = NULL;
+ LLTexLayer *layer = NULL;
+ wearable = *iter;
+ if (wearable)
{
-// llinfos << "Building Cached Alpha: " << mName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << effective_weight << llendl;
- mCachedEffectiveWeight = effective_weight;
-
- if( !mCachedProcessedImageGL )
- {
- mCachedProcessedImageGL = new LLImageGL( image_tga_width, image_tga_height, 1, FALSE);
-
- // We now have something in one of our caches
- LLTexLayerSet::sHasCaches |= mCachedProcessedImageGL ? TRUE : FALSE;
-
- mCachedProcessedImageGL->setExplicitFormat( GL_ALPHA8, GL_ALPHA );
- }
-
- // Applies domain and effective weight to data as it is decoded. Also resizes the raw image if needed.
- mStaticImageRaw = NULL;
- mStaticImageRaw = new LLImageRaw;
- mStaticImageTGA->decodeAndProcess( mStaticImageRaw, getInfo()->mDomain, effective_weight );
- mNeedsCreateTexture = TRUE;
+ lto = wearable->getLocalTextureObject(mInfo->mLocalTexture);
}
-
- if( mCachedProcessedImageGL )
+ if (lto)
{
- {
- // Create the GL texture, and then hang onto it for future use.
- if( mNeedsCreateTexture )
- {
- mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw);
- mNeedsCreateTexture = FALSE;
- gGL.getTexUnit(0)->bind(mCachedProcessedImageGL);
- mCachedProcessedImageGL->setAddressMode(LLTexUnit::TAM_CLAMP);
- }
-
- LLGLSNoAlphaTest gls_no_alpha_test;
- gGL.getTexUnit(0)->bind(mCachedProcessedImageGL);
- gl_rect_2d_simple_tex( width, height );
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- stop_glerror();
- }
+ layer = lto->getTexLayer(getName());
}
-
- // Don't keep the cache for other people's avatars
- // (It's not really a "cache" in that case, but the logic is the same)
- if( !mTexLayer->getTexLayerSet()->getAvatar()->isSelf() )
+ if (layer)
{
- mCachedProcessedImageGL = NULL;
+ wearable->writeToAvatar();
+ layer->setLTO(lto);
+ success &= layer->render(x,y,width,height);
}
}
- else
- {
- LLGLDisable no_alpha(GL_ALPHA_TEST);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.color4f( 0.f, 0.f, 0.f, effective_weight );
- gl_rect_2d_simple( width, height );
- }
return success;
}
-//-----------------------------------------------------------------------------
-// LLTexGlobalColorInfo
-//-----------------------------------------------------------------------------
-
-LLTexGlobalColorInfo::LLTexGlobalColorInfo()
-{
-}
-
-
-LLTexGlobalColorInfo::~LLTexGlobalColorInfo()
-{
- for_each(mColorInfoList.begin(), mColorInfoList.end(), DeletePointer());
-}
-
-BOOL LLTexGlobalColorInfo::parseXml(LLXmlTreeNode* node)
+/*virtual*/ BOOL LLTexLayerTemplate::blendAlphaTexture( S32 x, S32 y, S32 width, S32 height) // Multiplies a single alpha texture against the frame buffer
{
- // name attribute
- static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
- if( !node->getFastAttributeString( name_string, mName ) )
- {
- llwarns << "<global_color> element is missing name attribute." << llendl;
- return FALSE;
- }
- // <param> sub-element
- for (LLXmlTreeNode* child = node->getChildByName( "param" );
- child;
- child = node->getNextNamedChild())
+ BOOL success = TRUE;
+ U32 num_wearables = updateWearableCache();
+ for (U32 i = 0; i < num_wearables; i++)
{
- if( child->getChildByName( "param_color" ) )
+ LLTexLayer *layer = getLayer(i);
+ if (layer)
{
- // <param><param_color/></param>
- LLTexParamColorInfo* info = new LLTexParamColorInfo();
- if (!info->parseXml(child))
- {
- delete info;
- return FALSE;
- }
- mColorInfoList.push_back( info );
+ success &= layer->blendAlphaTexture(x,y,width,height);
}
}
- return TRUE;
-}
-
-//-----------------------------------------------------------------------------
-// LLTexGlobalColor
-//-----------------------------------------------------------------------------
-
-LLTexGlobalColor::LLTexGlobalColor( LLVOAvatar* avatar )
- :
- mAvatar( avatar ),
- mInfo( NULL )
-{
-}
-
-
-LLTexGlobalColor::~LLTexGlobalColor()
-{
- // mParamList are LLViewerVisualParam's and get deleted with ~LLCharacter()
- //std::for_each(mParamList.begin(), mParamList.end(), DeletePointer());
+ return success;
}
-BOOL LLTexGlobalColor::setInfo(LLTexGlobalColorInfo *info)
+/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height)
{
- llassert(mInfo == NULL);
- mInfo = info;
- //mID = info->mID; // No ID
-
- LLTexGlobalColorInfo::color_info_list_t::iterator iter;
- mParamList.reserve(mInfo->mColorInfoList.size());
- for (iter = mInfo->mColorInfoList.begin(); iter != mInfo->mColorInfoList.end(); iter++)
+ U32 num_wearables = updateWearableCache();
+ for (U32 i = 0; i < num_wearables; i++)
{
- LLTexParamColor* param_color = new LLTexParamColor( this );
- if (!param_color->setInfo(*iter))
+ LLTexLayer *layer = getLayer(i);
+ if (layer)
{
- mInfo = NULL;
- return FALSE;
+ layer->addAlphaMask(data, originX, originY, width, height);
}
- mParamList.push_back( param_color );
}
-
- return TRUE;
}
-//-----------------------------------------------------------------------------
-
-LLColor4 LLTexGlobalColor::getColor()
-{
- // Sum of color params
- if( !mParamList.empty() )
+/*virtual*/ void LLTexLayerTemplate::setHasMorph(BOOL newval)
+{
+ mHasMorph = newval;
+ U32 num_wearables = updateWearableCache();
+ for (U32 i = 0; i < num_wearables; i++)
{
- LLColor4 net_color( 0.f, 0.f, 0.f, 0.f );
-
- for( param_list_t::iterator iter = mParamList.begin();
- iter != mParamList.end(); iter++ )
- {
- LLTexParamColor* param = *iter;
- LLColor4 param_net = param->getNetColor();
- switch( param->getOperation() )
- {
- case OP_ADD:
- net_color += param_net;
- break;
- case OP_MULTIPLY:
- net_color.mV[VX] *= param_net.mV[VX];
- net_color.mV[VY] *= param_net.mV[VY];
- net_color.mV[VZ] *= param_net.mV[VZ];
- net_color.mV[VW] *= param_net.mV[VW];
- break;
- case OP_BLEND:
- net_color = lerp(net_color, param_net, param->getWeight());
- break;
- default:
- llassert(0);
- break;
- }
+ LLTexLayer *layer = getLayer(i);
+ if (layer)
+ {
+ layer->setHasMorph(newval);
}
-
- net_color.mV[VX] = llclampf( net_color.mV[VX] );
- net_color.mV[VY] = llclampf( net_color.mV[VY] );
- net_color.mV[VZ] = llclampf( net_color.mV[VZ] );
- net_color.mV[VW] = llclampf( net_color.mV[VW] );
-
- return net_color;
}
- return LLColor4( 1.f, 1.f, 1.f, 1.f );
-}
-
-//-----------------------------------------------------------------------------
-// LLTexParamColorInfo
-//-----------------------------------------------------------------------------
-LLTexParamColorInfo::LLTexParamColorInfo()
- :
- mOperation( OP_ADD ),
- mNumColors( 0 )
-{
}
-BOOL LLTexParamColorInfo::parseXml(LLXmlTreeNode *node)
+/*virtual*/ void LLTexLayerTemplate::deleteCaches()
{
- llassert( node->hasName( "param" ) && node->getChildByName( "param_color" ) );
-
- if (!LLViewerVisualParamInfo::parseXml(node))
- return FALSE;
-
- LLXmlTreeNode* param_color_node = node->getChildByName( "param_color" );
- if( !param_color_node )
- {
- return FALSE;
- }
-
- std::string op_string;
- static LLStdStringHandle operation_string = LLXmlTree::addAttributeString("operation");
- if( param_color_node->getFastAttributeString( operation_string, op_string ) )
- {
- LLStringUtil::toLower(op_string);
- if ( op_string == "add" ) mOperation = OP_ADD;
- else if ( op_string == "multiply" ) mOperation = OP_MULTIPLY;
- else if ( op_string == "blend" ) mOperation = OP_BLEND;
- }
-
- mNumColors = 0;
-
- LLColor4U color4u;
- for (LLXmlTreeNode* child = param_color_node->getChildByName( "value" );
- child;
- child = param_color_node->getNextNamedChild())
+ U32 num_wearables = updateWearableCache();
+ for (U32 i = 0; i < num_wearables; i++)
{
- if( (mNumColors < MAX_COLOR_VALUES) )
+ LLTexLayer *layer = getLayer(i);
+ if (layer)
{
- static LLStdStringHandle color_string = LLXmlTree::addAttributeString("color");
- if( child->getFastAttributeColor4U( color_string, color4u ) )
- {
- mColors[ mNumColors ].setVec(color4u);
- mNumColors++;
- }
+ layer->deleteCaches();
}
}
- if( !mNumColors )
- {
- llwarns << "<param_color> is missing <value> sub-elements" << llendl;
- return FALSE;
- }
-
- if( (mOperation == OP_BLEND) && (mNumColors != 1) )
- {
- llwarns << "<param_color> with operation\"blend\" must have exactly one <value>" << llendl;
- return FALSE;
- }
-
- return TRUE;
}
-//-----------------------------------------------------------------------------
-// LLTexParamColor
-//-----------------------------------------------------------------------------
-LLTexParamColor::LLTexParamColor( LLTexGlobalColor* tex_global_color )
- :
- mAvgDistortionVec(1.f, 1.f, 1.f),
- mTexGlobalColor( tex_global_color ),
- mTexLayer( NULL ),
- mAvatar( tex_global_color->getAvatar() )
+/*virtual*/ BOOL LLTexLayerTemplate::isInvisibleAlphaMask()
{
-}
+ U32 num_wearables = updateWearableCache();
+ for (U32 i = 0; i < num_wearables; i++)
+ {
+ LLTexLayer *layer = getLayer(i);
+ if (layer)
+ {
+ if (layer->isInvisibleAlphaMask())
+ {
+ return TRUE;
+ }
+ }
+ }
-LLTexParamColor::LLTexParamColor( LLTexLayer* layer )
- :
- mAvgDistortionVec(1.f, 1.f, 1.f),
- mTexGlobalColor( NULL ),
- mTexLayer( layer ),
- mAvatar( layer->getTexLayerSet()->getAvatar() )
-{
+ return FALSE;
}
-LLTexParamColor::~LLTexParamColor()
-{
-}
-
//-----------------------------------------------------------------------------
-// setInfo()
+// finds a specific layer based on a passed in name
//-----------------------------------------------------------------------------
-
-BOOL LLTexParamColor::setInfo(LLTexParamColorInfo *info)
-{
- llassert(mInfo == NULL);
- if (info->mID < 0)
- return FALSE;
- mID = info->mID;
- mInfo = info;
-
- mAvatar->addVisualParam( this );
- setWeight( getDefaultWeight(), FALSE );
-
- return TRUE;
-}
-
-LLColor4 LLTexParamColor::getNetColor()
+LLTexLayerInterface* LLTexLayerSet::findLayerByName(const std::string& name)
{
- llassert( getInfo()->mNumColors >= 1 );
-
- F32 effective_weight = ( mAvatar && (mAvatar->getSex() & getSex()) ) ? mCurWeight : getDefaultWeight();
-
- S32 index_last = getInfo()->mNumColors - 1;
- F32 scaled_weight = effective_weight * index_last;
- S32 index_start = (S32) scaled_weight;
- S32 index_end = index_start + 1;
- if( index_start == index_last )
- {
- return getInfo()->mColors[index_last];
- }
- else
- {
- F32 weight = scaled_weight - index_start;
- const LLColor4 *start = &getInfo()->mColors[ index_start ];
- const LLColor4 *end = &getInfo()->mColors[ index_end ];
- return LLColor4(
- (1.f - weight) * start->mV[VX] + weight * end->mV[VX],
- (1.f - weight) * start->mV[VY] + weight * end->mV[VY],
- (1.f - weight) * start->mV[VZ] + weight * end->mV[VZ],
- (1.f - weight) * start->mV[VW] + weight * end->mV[VW] );
- }
-}
-
-void LLTexParamColor::setWeight(F32 weight, BOOL set_by_user)
-{
- if (mIsAnimating)
- {
- return;
- }
- F32 min_weight = getMinWeight();
- F32 max_weight = getMaxWeight();
- F32 new_weight = llclamp(weight, min_weight, max_weight);
- U8 cur_u8 = F32_to_U8( mCurWeight, min_weight, max_weight );
- U8 new_u8 = F32_to_U8( new_weight, min_weight, max_weight );
- if( cur_u8 != new_u8)
+ for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
{
- mCurWeight = new_weight;
+ LLTexLayerInterface* layer = *iter;
- if( getInfo()->mNumColors <= 0 )
+ if (layer->getName() == name)
{
- // This will happen when we set the default weight the first time.
- return;
+ return layer;
}
+ }
+ for( layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++ )
+ {
+ LLTexLayerInterface* layer = *iter;
- if( mAvatar->getSex() & getSex() )
+ if (layer->getName() == name)
{
- if( mTexGlobalColor )
- {
- mAvatar->onGlobalColorChanged( mTexGlobalColor, set_by_user );
- }
- else
- if( mTexLayer )
- {
- mAvatar->invalidateComposite( mTexLayer->getTexLayerSet(), set_by_user );
- }
+ return layer;
}
-// llinfos << "param " << mName << " = " << new_weight << llendl;
}
+ return NULL;
}
-void LLTexParamColor::setAnimationTarget(F32 target_value, BOOL set_by_user)
-{
- // set value first then set interpolating flag to ignore further updates
- mTargetWeight = target_value;
- setWeight(target_value, set_by_user);
- mIsAnimating = TRUE;
- if (mNext)
+void LLTexLayerSet::cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable *wearable)
+{
+ // initialize all texlayers with this texture type for this LTO
+ for( LLTexLayerSet::layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
{
- mNext->setAnimationTarget(target_value, set_by_user);
+ LLTexLayerTemplate* layer = (LLTexLayerTemplate*)*iter;
+ if (layer->getInfo()->getLocalTexture() == (S32) tex_index)
+ {
+ lto->addTexLayer(layer, wearable);
+ }
}
-}
-
-void LLTexParamColor::animate(F32 delta, BOOL set_by_user)
-{
- if (mNext)
+ for( LLTexLayerSet::layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++ )
{
- mNext->animate(delta, set_by_user);
+ LLTexLayerTemplate* layer = (LLTexLayerTemplate*)*iter;
+ if (layer->getInfo()->getLocalTexture() == (S32) tex_index)
+ {
+ lto->addTexLayer(layer, wearable);
+ }
}
}
-
-
//-----------------------------------------------------------------------------
-// LLTexStaticImageList
+// LLTexLayerStaticImageList
//-----------------------------------------------------------------------------
-// static
-LLTexStaticImageList gTexStaticImageList;
-LLStringTable LLTexStaticImageList::sImageNames(16384);
-
-LLTexStaticImageList::LLTexStaticImageList()
- :
- mGLBytes( 0 ),
- mTGABytes( 0 )
-{}
+LLTexLayerStaticImageList::LLTexLayerStaticImageList() :
+ mGLBytes(0),
+ mTGABytes(0),
+ mImageNames(16384)
+{
+}
-LLTexStaticImageList::~LLTexStaticImageList()
+LLTexLayerStaticImageList::~LLTexLayerStaticImageList()
{
deleteCachedImages();
}
-void LLTexStaticImageList::dumpByteCount()
+void LLTexLayerStaticImageList::dumpByteCount()
{
llinfos << "Avatar Static Textures " <<
"KB GL:" << (mGLBytes / 1024) <<
"KB TGA:" << (mTGABytes / 1024) << "KB" << llendl;
}
-void LLTexStaticImageList::deleteCachedImages()
+void LLTexLayerStaticImageList::deleteCachedImages()
{
if( mGLBytes || mTGABytes )
{
@@ -2478,23 +2061,23 @@ void LLTexStaticImageList::deleteCachedImages()
//mStaticImageLists uses LLPointers, clear() will cause deletion
mStaticImageListTGA.clear();
- mStaticImageListGL.clear();
+ mStaticImageList.clear();
mGLBytes = 0;
mTGABytes = 0;
}
}
-// Note: in general, for a given image image we'll call either getImageTga() or getImageGL().
+// Note: in general, for a given image image we'll call either getImageTga() or getTexture().
// We call getImageTga() if the image is used as an alpha gradient.
-// Otherwise, we call getImageGL()
+// Otherwise, we call getTexture()
// Returns an LLImageTGA that contains the encoded data from a tga file named file_name.
// Caches the result to speed identical subsequent requests.
-LLImageTGA* LLTexStaticImageList::getImageTGA(const std::string& file_name)
+LLImageTGA* LLTexLayerStaticImageList::getImageTGA(const std::string& file_name)
{
- const char *namekey = sImageNames.addString(file_name);
- image_tga_map_t::iterator iter = mStaticImageListTGA.find(namekey);
+ const char *namekey = mImageNames.addString(file_name);
+ image_tga_map_t::const_iterator iter = mStaticImageListTGA.find(namekey);
if( iter != mStaticImageListTGA.end() )
{
return iter->second;
@@ -2517,23 +2100,21 @@ LLImageTGA* LLTexStaticImageList::getImageTGA(const std::string& file_name)
}
}
-
-
// Returns a GL Image (without a backing ImageRaw) that contains the decoded data from a tga file named file_name.
// Caches the result to speed identical subsequent requests.
-LLImageGL* LLTexStaticImageList::getImageGL(const std::string& file_name, BOOL is_mask )
+LLViewerTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, BOOL is_mask)
{
- LLPointer<LLImageGL> image_gl;
- const char *namekey = sImageNames.addString(file_name);
+ LLPointer<LLViewerTexture> tex;
+ const char *namekey = mImageNames.addString(file_name);
- image_gl_map_t::iterator iter = mStaticImageListGL.find(namekey);
- if( iter != mStaticImageListGL.end() )
+ texture_map_t::const_iterator iter = mStaticImageList.find(namekey);
+ if( iter != mStaticImageList.end() )
{
- image_gl = iter->second;
+ tex = iter->second;
}
else
{
- image_gl = new LLImageGL( FALSE );
+ tex = LLViewerTextureManager::getLocalTexture( FALSE );
LLPointer<LLImageRaw> image_raw = new LLImageRaw;
if( loadImageRaw( file_name, image_raw ) )
{
@@ -2541,28 +2122,28 @@ LLImageGL* LLTexStaticImageList::getImageGL(const std::string& file_name, BOOL i
{
// Note: these are static, unchanging images so it's ok to assume
// that once an image is a mask it's always a mask.
- image_gl->setExplicitFormat( GL_ALPHA8, GL_ALPHA );
+ tex->setExplicitFormat( GL_ALPHA8, GL_ALPHA );
}
- image_gl->createGLTexture(0, image_raw);
+ tex->createGLTexture(0, image_raw, 0, TRUE, LLViewerTexture::LOCAL);
- gGL.getTexUnit(0)->bind(image_gl);
- image_gl->setAddressMode(LLTexUnit::TAM_CLAMP);
+ gGL.getTexUnit(0)->bind(tex);
+ tex->setAddressMode(LLTexUnit::TAM_CLAMP);
- mStaticImageListGL [ namekey ] = image_gl;
- mGLBytes += (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents();
+ mStaticImageList [ namekey ] = tex;
+ mGLBytes += (S32)tex->getWidth() * tex->getHeight() * tex->getComponents();
}
else
{
- image_gl = NULL;
+ tex = NULL;
}
}
- return image_gl;
+ return tex;
}
// Reads a .tga file, decodes it, and puts the decoded data in image_raw.
// Returns TRUE if successful.
-BOOL LLTexStaticImageList::loadImageRaw( const std::string& file_name, LLImageRaw* image_raw )
+BOOL LLTexLayerStaticImageList::loadImageRaw(const std::string& file_name, LLImageRaw* image_raw)
{
BOOL success = FALSE;
std::string path;
@@ -2577,11 +2158,4 @@ BOOL LLTexStaticImageList::loadImageRaw( const std::string& file_name, LLImageRa
return success;
}
-//-----------------------------------------------------------------------------
-// LLMaskedMorph()
-//-----------------------------------------------------------------------------
-LLMaskedMorph::LLMaskedMorph( LLPolyMorphTarget *morph_target, BOOL invert ) : mMorphTarget(morph_target), mInvert(invert)
-{
- morph_target->addPendingMorphMask();
-}
diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h
index 1924d0bee3..5be58f64a9 100644
--- a/indra/newview/lltexlayer.h
+++ b/indra/newview/lltexlayer.h
@@ -34,150 +34,185 @@
#define LL_LLTEXLAYER_H
#include <deque>
-#include "llassetstorage.h"
#include "lldynamictexture.h"
-#include "llrect.h"
-#include "llstring.h"
-#include "lluuid.h"
-#include "llviewerimage.h"
-#include "llviewervisualparam.h"
#include "llwearable.h"
-#include "v4color.h"
-#include "llfloater.h"
+#include "llvoavatardefines.h"
-class LLTexLayerSetInfo;
-class LLTexLayerSet;
-class LLTexLayerInfo;
-class LLTexLayer;
-class LLImageGL;
+class LLVOAvatar;
+class LLVOAvatarSelf;
class LLImageTGA;
-class LLTexGlobalColorInfo;
-class LLTexLayerParamAlphaInfo;
-class LLTexLayerParamAlpha;
-class LLTexParamColorInfo;
-class LLTexParamColor;
-class LLPolyMesh;
-class LLXmlTreeNode;
class LLImageRaw;
+class LLXmlTreeNode;
class LLPolyMorphTarget;
+class LLTexLayerSet;
+class LLTexLayerSetInfo;
+class LLTexLayerInfo;
+class LLTexLayerSetBuffer;
+class LLTexLayerParamColor;
+class LLTexLayerParamColorInfo;
+class LLTexLayerParamAlpha;
+class LLTexLayerParamAlphaInfo;
+class LLWearable;
+class LLViewerVisualParam;
-class LLTextureCtrl;
-class LLVOAvatar;
-
-
-enum EColorOperation
-{
- OP_ADD = 0,
- OP_MULTIPLY = 1,
- OP_BLEND = 2,
- OP_COUNT = 3 // Number of operations
-};
+typedef std::vector<LLTexLayerParamColor *> param_color_list_t;
+typedef std::vector<LLTexLayerParamAlpha *> param_alpha_list_t;
+typedef std::vector<LLTexLayerParamColorInfo *> param_color_info_list_t;
+typedef std::vector<LLTexLayerParamAlphaInfo *> param_alpha_info_list_t;
//-----------------------------------------------------------------------------
-// LLTexLayerParamAlphaInfo
-//-----------------------------------------------------------------------------
-class LLTexLayerParamAlphaInfo : public LLViewerVisualParamInfo
+// LLTexLayerInterface
+// Interface class to generalize functionality shared by LLTexLayer and LLTexLayerTemplate.
+
+class LLTexLayerInterface
{
- friend class LLTexLayerParamAlpha;
public:
- LLTexLayerParamAlphaInfo();
- /*virtual*/ ~LLTexLayerParamAlphaInfo() {};
+ enum ERenderPass
+ {
+ RP_COLOR,
+ RP_BUMP,
+ RP_SHINE
+ };
+
+ LLTexLayerInterface(LLTexLayerSet* const layer_set);
+ LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable);
+ virtual ~LLTexLayerInterface() {}
+
+ const LLTexLayerInfo* getInfo() const { return mInfo; }
+ virtual BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable ); // This sets mInfo and calls initialization functions
+ virtual BOOL render(S32 x, S32 y, S32 width, S32 height) = 0;
+ void requestUpdate();
+ LLTexLayerSet* const getTexLayerSet() const { return mTexLayerSet; }
- /*virtual*/ BOOL parseXml(LLXmlTreeNode* node);
+ virtual void deleteCaches() = 0;
+ void invalidateMorphMasks();
+ virtual void setHasMorph(BOOL newval) { mHasMorph = newval; }
+ BOOL hasMorph() { return mHasMorph; }
+ BOOL isMorphValid() { return mMorphMasksValid; }
-protected:
- std::string mStaticImageFileName;
- BOOL mMultiplyBlend;
- BOOL mSkipIfZeroWeight;
- F32 mDomain;
-};
+ const std::string& getName() const;
+ ERenderPass getRenderPass() const;
+ const std::string& getGlobalColor() const;
+
+ virtual BOOL blendAlphaTexture( S32 x, S32 y, S32 width, S32 height) = 0;
+ virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) = 0;
+ BOOL hasAlphaParams() const { return !mParamAlphaList.empty(); }
+ BOOL isVisibilityMask() const;
+ virtual BOOL isInvisibleAlphaMask() = 0;
+
+ LLTexLayerSet* getLayerSet() {return mTexLayerSet;}
+
+ LLViewerVisualParam* getVisualParamPtr(S32 index);
-//-----------------------------------------------------------------------------
-// LLTexParamColorInfo
-//-----------------------------------------------------------------------------
-class LLTexParamColorInfo : public LLViewerVisualParamInfo
-{
- friend class LLTexParamColor;
-public:
- LLTexParamColorInfo();
- virtual ~LLTexParamColorInfo() {};
- BOOL parseXml( LLXmlTreeNode* node );
-
protected:
- enum { MAX_COLOR_VALUES = 20 };
- EColorOperation mOperation;
- LLColor4 mColors[MAX_COLOR_VALUES];
- S32 mNumColors;
+ LLTexLayerSet* const mTexLayerSet;
+
+ // Layers can have either mParamColorList, mGlobalColor, or mFixedColor. They are looked for in that order.
+ param_color_list_t mParamColorList;
+ // mGlobalColor name stored in mInfo
+ // mFixedColor value stored in mInfo
+ param_alpha_list_t mParamAlphaList;
+
+ BOOL mMorphMasksValid;
+ BOOL mStaticImageInvalid;
+
+ BOOL mHasMorph;
+
+ const LLTexLayerInfo *mInfo;
+
};
//-----------------------------------------------------------------------------
-// LLTexGlobalColorInfo
-//-----------------------------------------------------------------------------
-class LLTexGlobalColorInfo
+// LLTexLayerTemplate
+// Template class
+// Only exists for llvoavatarself
+
+class LLTexLayerTemplate : public LLTexLayerInterface
{
- friend class LLTexGlobalColor;
public:
- LLTexGlobalColorInfo();
- ~LLTexGlobalColorInfo();
+ LLTexLayerTemplate(LLTexLayerSet* const layer_set);
+ LLTexLayerTemplate(const LLTexLayerTemplate &layer);
+ /*virtual*/ ~LLTexLayerTemplate();
+
+ /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height);
+ /*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable ); // This sets mInfo and calls initialization functions
+ /*virtual*/ BOOL blendAlphaTexture( S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer
+ /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height);
+ /*virtual*/ void setHasMorph(BOOL newval);
+ /*virtual*/ void deleteCaches();
+ /*virtual*/ BOOL isInvisibleAlphaMask();
+
+private:
+ U32 updateWearableCache();
+ LLTexLayer* getLayer(U32 i);
+ typedef std::vector<LLWearable*> wearable_cache_t;
+ wearable_cache_t mWearableCache;
- BOOL parseXml(LLXmlTreeNode* node);
-
-protected:
- typedef std::vector<LLTexParamColorInfo *> color_info_list_t;
- color_info_list_t mColorInfoList;
- std::string mName;
};
//-----------------------------------------------------------------------------
-// LLTexLayerSetInfo
-// Containes shared layer set data
-//-----------------------------------------------------------------------------
-class LLTexLayerSetInfo
+// LLTexLayer
+// A single texture layer
+// Only exists for llvoavatarself
+
+class LLTexLayer : public LLTexLayerInterface
{
- friend class LLTexLayerSet;
public:
- LLTexLayerSetInfo();
- ~LLTexLayerSetInfo();
-
- BOOL parseXml(LLXmlTreeNode* node);
+ LLTexLayer(LLTexLayerSet* const layer_set);
+ LLTexLayer(const LLTexLayer &layer, LLWearable *wearable);
+ LLTexLayer(const LLTexLayerTemplate &layer_template, LLLocalTextureObject *lto, LLWearable *wearable);
+ /*virtual*/ ~LLTexLayer();
-protected:
- std::string mBodyRegion;
- S32 mWidth;
- S32 mHeight;
- std::string mStaticAlphaFileName;
- BOOL mClearAlpha; // Set alpha to 1 for this layerset (if there is no mStaticAlphaFileName)
-
- typedef std::vector<LLTexLayerInfo*> layer_info_list_t;
- layer_info_list_t mLayerInfoList;
-};
+ /*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable ); // This sets mInfo and calls initialization functions
+ /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height);
-//-----------------------------------------------------------------------------
-// LLTexLayerInfo
-//-----------------------------------------------------------------------------
-enum ERenderPass
-{
- RP_COLOR,
- RP_BUMP,
- RP_SHINE
+ /*virtual*/ void deleteCaches();
+ U8* getAlphaData();
+
+ BOOL findNetColor(LLColor4* color) const;
+ /*virtual*/ BOOL blendAlphaTexture( S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer
+ /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height);
+ BOOL renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color);
+ void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height);
+ /*virtual*/ BOOL isInvisibleAlphaMask();
+
+ void setLTO(LLLocalTextureObject *lto) { mLocalTextureObject = lto; }
+ LLLocalTextureObject* getLTO() { return mLocalTextureObject; }
+
+ static void calculateTexLayerColor(const param_color_list_t &param_list, LLColor4 &net_color);
+
+private:
+ LLUUID getUUID();
+
+ typedef std::map<U32, U8*> alpha_cache_t;
+ alpha_cache_t mAlphaCache;
+ LLLocalTextureObject *mLocalTextureObject;
};
+// Make private
class LLTexLayerInfo
{
friend class LLTexLayer;
+ friend class LLTexLayerTemplate;
+ friend class LLTexLayerInterface;
public:
LLTexLayerInfo();
~LLTexLayerInfo();
BOOL parseXml(LLXmlTreeNode* node);
+ BOOL createVisualParams(LLVOAvatar *avatar);
+ BOOL isUserSettable() { return mLocalTexture != -1; }
+ S32 getLocalTexture() const { return mLocalTexture; }
+ BOOL getOnlyAlpha() const { return mUseLocalTextureAlphaOnly; }
+ std::string getName() const { return mName; }
-protected:
+private:
std::string mName;
- BOOL mWriteAllChannels; // Don't use masking. Just write RGBA into buffer,
- ERenderPass mRenderPass;
+ BOOL mWriteAllChannels; // Don't use masking. Just write RGBA into buffer,
+ LLTexLayer::ERenderPass mRenderPass;
std::string mGlobalColor;
LLColor4 mFixedColor;
@@ -185,377 +220,197 @@ protected:
S32 mLocalTexture;
std::string mStaticImageFileName;
BOOL mStaticImageIsMask;
- BOOL mUseLocalTextureAlphaOnly; // Ignore RGB channels from the input texture. Use alpha as a mask
-
- typedef std::vector<std::pair<std::string,BOOL> > morph_name_list_t;
- morph_name_list_t mMorphNameList;
+ BOOL mUseLocalTextureAlphaOnly; // Ignore RGB channels from the input texture. Use alpha as a mask
+ BOOL mIsVisibilityMask;
- typedef std::vector<LLTexParamColorInfo*> color_info_list_t;
- color_info_list_t mColorInfoList;
-
- typedef std::vector<LLTexLayerParamAlphaInfo*> alpha_info_list_t;
- alpha_info_list_t mAlphaInfoList;
-
+ typedef std::vector< std::pair< std::string,BOOL > > morph_name_list_t;
+ morph_name_list_t mMorphNameList;
+ param_color_info_list_t mParamColorInfoList;
+ param_alpha_info_list_t mParamAlphaInfoList;
};
+//
+// LLTexLayer
//-----------------------------------------------------------------------------
-// LLTexLayerSetBuffer
-// The composite image that a LLTexLayerSet writes to. Each LLTexLayerSet has one.
-//-----------------------------------------------------------------------------
-class LLTexLayerSetBuffer : public LLDynamicTexture
-{
-public:
- LLTexLayerSetBuffer( LLTexLayerSet* owner, S32 width, S32 height, BOOL has_bump );
- virtual ~LLTexLayerSetBuffer();
-
- virtual void preRender(BOOL clear_depth);
- virtual void postRender(BOOL success);
- virtual BOOL render();
- BOOL updateImmediate();
- void bindBumpTexture( U32 stage );
- bool isInitialized(void) const;
- BOOL needsRender();
- void requestUpdate();
- void requestUpload();
- void cancelUpload();
- BOOL uploadPending() { return mUploadPending; }
- BOOL render( S32 x, S32 y, S32 width, S32 height );
- void readBackAndUpload(U8* baked_bump_data);
- void createBumpTexture() ;
-
- static void onTextureUploadComplete( const LLUUID& uuid,
- void* userdata,
- S32 result, LLExtStat ext_status);
- static void dumpTotalByteCount();
-
- virtual void restoreGLTexture() ;
- virtual void destroyGLTexture() ;
-
-private:
- void pushProjection();
- void popProjection();
-
-private:
- BOOL mHasBump ;
- BOOL mNeedsUpdate;
- BOOL mNeedsUpload;
- BOOL mUploadPending;
- LLUUID mUploadID; // Identifys the current upload process (null if none). Used to avoid overlaps (eg, when the user rapidly makes two changes outside of Face Edit)
- LLTexLayerSet* mTexLayerSet;
- LLPointer<LLImageGL> mBumpTex; // zero if none
-
- static S32 sGLByteCount;
- static S32 sGLBumpByteCount;
-};
//-----------------------------------------------------------------------------
// LLTexLayerSet
// An ordered set of texture layers that get composited into a single texture.
-//-----------------------------------------------------------------------------
+// Only exists for llvoavatarself
+
class LLTexLayerSet
{
+ friend class LLTexLayerSetBuffer;
public:
- LLTexLayerSet( LLVOAvatar* avatar );
+ LLTexLayerSet(LLVOAvatarSelf* const avatar);
~LLTexLayerSet();
- //BOOL parseData(LLXmlTreeNode* node);
- LLTexLayerSetInfo* getInfo() const { return mInfo; }
- // This sets mInfo and calls initialization functions
- BOOL setInfo(LLTexLayerSetInfo *info);
-
- BOOL render( S32 x, S32 y, S32 width, S32 height );
- BOOL renderBump( S32 x, S32 y, S32 width,S32 height );
- BOOL isBodyRegion( const std::string& region ) { return mInfo->mBodyRegion == region; }
+ const LLTexLayerSetInfo* getInfo() const { return mInfo; }
+ BOOL setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions
+
+ BOOL render(S32 x, S32 y, S32 width, S32 height);
+ void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear = false);
+
+ BOOL isBodyRegion(const std::string& region) const;
LLTexLayerSetBuffer* getComposite();
void requestUpdate();
void requestUpload();
void cancelUpload();
- LLVOAvatar* getAvatar() { return mAvatar; }
void updateComposite();
- BOOL isLocalTextureDataAvailable();
- BOOL isLocalTextureDataFinal();
+ BOOL isLocalTextureDataAvailable() const;
+ BOOL isLocalTextureDataFinal() const;
void createComposite();
void destroyComposite();
- void setUpdatesEnabled( BOOL b );
- BOOL getUpdatesEnabled() { return mUpdatesEnabled; }
+ void setUpdatesEnabled(BOOL b);
+ BOOL getUpdatesEnabled() const { return mUpdatesEnabled; }
void deleteCaches();
- void gatherAlphaMasks(U8 *data, S32 width, S32 height);
+ void gatherMorphMaskAlpha(U8 *data, S32 width, S32 height);
void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components);
- const std::string getBodyRegion() { return mInfo->mBodyRegion; }
- BOOL hasComposite() { return (mComposite != NULL); }
- void setBump( BOOL b ) { mHasBump = b; }
- BOOL hasBump() { return mHasBump; }
+ BOOL isMorphValid();
+ void invalidateMorphMasks();
+ LLTexLayerInterface* findLayerByName(const std::string& name);
+ void cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable* wearable);
+
+ LLVOAvatarSelf* getAvatar() const { return mAvatar; }
+ const std::string getBodyRegion() const;
+ BOOL hasComposite() const { return (mComposite.notNull()); }
+ LLVOAvatarDefines::EBakedTextureIndex getBakedTexIndex() { return mBakedTexIndex; }
+ void setBakedTexIndex( LLVOAvatarDefines::EBakedTextureIndex index) { mBakedTexIndex = index; }
+ BOOL isVisible() const { return mIsVisible; }
public:
static BOOL sHasCaches;
-protected:
- typedef std::vector<LLTexLayer *> layer_list_t;
+ typedef std::vector<LLTexLayerInterface *> layer_list_t;
+
+private:
layer_list_t mLayerList;
- LLTexLayerSetBuffer* mComposite;
- // Backlink only; don't make this an LLPointer.
- LLVOAvatar* mAvatar;
+ layer_list_t mMaskLayerList;
+ LLPointer<LLTexLayerSetBuffer> mComposite;
+ LLVOAvatarSelf* const mAvatar; // Backlink only; don't make this an LLPointer.
BOOL mUpdatesEnabled;
- BOOL mHasBump;
+ BOOL mIsVisible;
- LLTexLayerSetInfo *mInfo;
-};
+ LLVOAvatarDefines::EBakedTextureIndex mBakedTexIndex;
-//-----------------------------------------------------------------------------
-// LLMaskedMorph
-//-----------------------------------------------------------------------------
-
-class LLMaskedMorph
-{
-public:
- LLMaskedMorph( LLPolyMorphTarget *morph_target, BOOL invert );
-
-public:
- LLPolyMorphTarget *mMorphTarget;
- BOOL mInvert;
+ const LLTexLayerSetInfo *mInfo;
};
-//-----------------------------------------------------------------------------
-// LLTexLayer
-// A single texture layer
-//-----------------------------------------------------------------------------
-class LLTexLayer
+// Contains shared layer set data
+class LLTexLayerSetInfo
{
+ friend class LLTexLayerSet;
public:
- LLTexLayer( LLTexLayerSet* layer_set );
- ~LLTexLayer();
-
- //BOOL parseData(LLXmlTreeNode* node);
- LLTexLayerInfo* getInfo() const { return mInfo; }
- // This sets mInfo and calls initialization functions
- BOOL setInfo(LLTexLayerInfo *info);
+ LLTexLayerSetInfo();
+ ~LLTexLayerSetInfo();
- BOOL render( S32 x, S32 y, S32 width, S32 height );
- void requestUpdate();
- LLTexLayerSet* getTexLayerSet() { return mTexLayerSet; }
-
- const std::string& getName() { return mInfo->mName; }
-
- void addMaskedMorph(LLPolyMorphTarget* morph_target, BOOL invert);
- void deleteCaches();
- U8* getAlphaData();
- void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components);
-
- void invalidateMorphMasks();
- ERenderPass getRenderPass() { return mInfo->mRenderPass; }
- const std::string& getGlobalColor() { return mInfo->mGlobalColor; }
- BOOL findNetColor( LLColor4* color );
- BOOL renderImageRaw( U8* in_data, S32 in_width, S32 in_height, S32 in_components, S32 width, S32 height, BOOL is_mask );
- BOOL renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4* colorp );
- BOOL hasAlphaParams() { return (!mParamAlphaList.empty());}
-
-protected:
- LLTexLayerSet* mTexLayerSet;
- LLPointer<LLImageRaw> mStaticImageRaw;
-
- // Layers can have either mParamColorList, mGlobalColor, or mFixedColor. They are looked for in that order.
- typedef std::vector<LLTexParamColor *> color_list_t;
- color_list_t mParamColorList;
- // mGlobalColor name stored in mInfo
- // mFixedColor value stored in mInfo
+ BOOL parseXml(LLXmlTreeNode* node);
+ void createVisualParams(LLVOAvatar *avatar);
- typedef std::vector<LLTexLayerParamAlpha *> alpha_list_t;
- alpha_list_t mParamAlphaList;
-
+private:
+ std::string mBodyRegion;
+ S32 mWidth;
+ S32 mHeight;
+ std::string mStaticAlphaFileName;
+ BOOL mClearAlpha; // Set alpha to 1 for this layerset (if there is no mStaticAlphaFileName)
- typedef std::deque<LLMaskedMorph> morph_list_t;
- morph_list_t mMaskedMorphs;
- typedef std::map<U32, U8*> alpha_cache_t;
- alpha_cache_t mAlphaCache;
- BOOL mMorphMasksValid;
- BOOL mStaticImageInvalid;
-
- LLTexLayerInfo *mInfo;
+ typedef std::vector<LLTexLayerInfo*> layer_info_list_t;
+ layer_info_list_t mLayerInfoList;
};
-//-----------------------------------------------------------------------------
-// LLTexLayerParamAlpha
-//-----------------------------------------------------------------------------
-class LLTexLayerParamAlpha : public LLViewerVisualParam
+// The composite image that a LLTexLayerSet writes to. Each LLTexLayerSet has one.
+class LLTexLayerSetBuffer : public LLViewerDynamicTexture
{
public:
- LLTexLayerParamAlpha( LLTexLayer* layer );
- /*virtual*/ ~LLTexLayerParamAlpha();
+ LLTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height);
+ virtual ~LLTexLayerSetBuffer();
- // Special: These functions are overridden by child classes
- LLTexLayerParamAlphaInfo* getInfo() const { return (LLTexLayerParamAlphaInfo*)mInfo; }
- // This sets mInfo and calls initialization functions
- BOOL setInfo(LLTexLayerParamAlphaInfo *info);
-
- // LLVisualParam Virtual functions
- ///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
- /*virtual*/ void apply( ESex avatar_sex ) {}
- /*virtual*/ void setWeight(F32 weight, BOOL set_by_user);
- /*virtual*/ void setAnimationTarget(F32 target_value, BOOL set_by_user);
- /*virtual*/ void animate(F32 delta, BOOL set_by_user);
-
- // LLViewerVisualParam Virtual functions
- /*virtual*/ F32 getTotalDistortion() { return 1.f; }
- /*virtual*/ const LLVector3& getAvgDistortion() { return mAvgDistortionVec; }
- /*virtual*/ F32 getMaxDistortion() { return 3.f; }
- /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector3(1.f, 1.f, 1.f);}
- /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;};
- /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;};
-
- // New functions
+ virtual void preRender(BOOL clear_depth);
+ virtual void postRender(BOOL success);
+ virtual BOOL render();
+ BOOL updateImmediate();
+ bool isInitialized(void) const;
+ BOOL needsRender();
+ void requestUpdate();
+ void requestUpload();
+ void cancelUpload();
+ BOOL uploadPending() { return mUploadPending; }
BOOL render( S32 x, S32 y, S32 width, S32 height );
- BOOL getSkip();
- void deleteCaches();
- LLTexLayer* getTexLayer() { return mTexLayer; }
- BOOL getMultiplyBlend() { return getInfo()->mMultiplyBlend; }
-
-protected:
- LLPointer<LLImageGL> mCachedProcessedImageGL;
- LLTexLayer* mTexLayer;
- LLPointer<LLImageTGA> mStaticImageTGA;
- LLPointer<LLImageRaw> mStaticImageRaw;
- BOOL mNeedsCreateTexture;
- BOOL mStaticImageInvalid;
- LLVector3 mAvgDistortionVec;
- F32 mCachedEffectiveWeight;
+ void readBackAndUpload();
-public:
- // Global list of instances for gathering statistics
- static void dumpCacheByteCount();
- static void getCacheByteCount( S32* gl_bytes );
-
- typedef std::list< LLTexLayerParamAlpha* > param_alpha_ptr_list_t;
- static param_alpha_ptr_list_t sInstances;
-};
+ static void onTextureUploadComplete(const LLUUID& uuid,
+ void* userdata,
+ S32 result, LLExtStat ext_status);
+ static void dumpTotalByteCount();
+ virtual void restoreGLTexture();
+ virtual void destroyGLTexture();
-//-----------------------------------------------------------------------------
-// LLTexGlobalColor
-//-----------------------------------------------------------------------------
-class LLTexGlobalColor
-{
-public:
- LLTexGlobalColor( LLVOAvatar* avatar );
- ~LLTexGlobalColor();
+private:
+ void pushProjection() const;
+ void popProjection() const;
- //BOOL parseData(LLXmlTreeNode* node);
- LLTexGlobalColorInfo* getInfo() const { return mInfo; }
- // This sets mInfo and calls initialization functions
- BOOL setInfo(LLTexGlobalColorInfo *info);
-
- void requstUpdate();
- LLVOAvatar* getAvatar() { return mAvatar; }
- LLColor4 getColor();
- const std::string& getName() { return mInfo->mName; }
+private:
+ LLTexLayerSet* const mTexLayerSet;
-protected:
- typedef std::vector<LLTexParamColor *> param_list_t;
- param_list_t mParamList;
- LLVOAvatar* mAvatar; // just backlink, don't LLPointer
+ BOOL mNeedsUpdate;
+ BOOL mNeedsUpload;
+ BOOL mUploadPending;
+ LLUUID mUploadID; // Identifys the current upload process (null if none). Used to avoid overlaps (eg, when the user rapidly makes two changes outside of Face Edit)
- LLTexGlobalColorInfo *mInfo;
+ static S32 sGLByteCount;
};
-
-//-----------------------------------------------------------------------------
-// LLTexParamColor
+//
+// LLTexLayerSet
//-----------------------------------------------------------------------------
-class LLTexParamColor : public LLViewerVisualParam
-{
-public:
- LLTexParamColor( LLTexGlobalColor* tex_color );
- LLTexParamColor( LLTexLayer* layer );
- /* virtual */ ~LLTexParamColor();
-
- // Special: These functions are overridden by child classes
- LLTexParamColorInfo* getInfo() const { return (LLTexParamColorInfo*)mInfo; }
- // This sets mInfo and calls initialization functions
- BOOL setInfo(LLTexParamColorInfo *info);
-
- // LLVisualParam Virtual functions
- ///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
- /*virtual*/ void apply( ESex avatar_sex ) {}
- /*virtual*/ void setWeight(F32 weight, BOOL set_by_user);
- /*virtual*/ void setAnimationTarget(F32 target_value, BOOL set_by_user);
- /*virtual*/ void animate(F32 delta, BOOL set_by_user);
-
-
- // LLViewerVisualParam Virtual functions
- /*virtual*/ F32 getTotalDistortion() { return 1.f; }
- /*virtual*/ const LLVector3& getAvgDistortion() { return mAvgDistortionVec; }
- /*virtual*/ F32 getMaxDistortion() { return 3.f; }
- /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector3(1.f, 1.f, 1.f); }
- /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;};
- /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;};
-
- // New functions
- LLColor4 getNetColor();
- EColorOperation getOperation() const { return getInfo()->mOperation; }
-
-protected:
- LLVector3 mAvgDistortionVec;
- LLTexGlobalColor* mTexGlobalColor; // either has mTexGlobalColor or mTexLayer as its parent
- LLTexLayer* mTexLayer;
- LLVOAvatar* mAvatar; // redundant, but simplifies the code (don't LLPointer)
-};
-
-//-----------------------------------------------------------------------------
-// LLTexStaticImageList
//-----------------------------------------------------------------------------
+// LLTexLayerStaticImageList
+//
-class LLTexStaticImageList
+class LLTexLayerStaticImageList : public LLSingleton<LLTexLayerStaticImageList>
{
public:
- LLTexStaticImageList();
- ~LLTexStaticImageList();
+ LLTexLayerStaticImageList();
+ ~LLTexLayerStaticImageList();
- LLImageRaw* getImageRaw( const std::string& file_name );
- LLImageGL* getImageGL( const std::string& file_name, BOOL is_mask );
- LLImageTGA* getImageTGA( const std::string& file_name );
+ LLViewerTexture* getTexture(const std::string& file_name, BOOL is_mask);
+ LLImageTGA* getImageTGA(const std::string& file_name);
void deleteCachedImages();
void dumpByteCount();
private:
- BOOL loadImageRaw( const std::string& file_name, LLImageRaw* image_raw );
+ BOOL loadImageRaw(const std::string& file_name, LLImageRaw* image_raw);
private:
- static LLStringTable sImageNames;
+ LLStringTable mImageNames;
- typedef std::map< const char *, LLPointer<LLImageGL> > image_gl_map_t;
- typedef std::map< const char *, LLPointer<LLImageTGA> > image_tga_map_t;
- image_gl_map_t mStaticImageListGL;
+ typedef std::map< const char*, LLPointer<LLViewerTexture> > texture_map_t;
+ texture_map_t mStaticImageList;
+ typedef std::map< const char*, LLPointer<LLImageTGA> > image_tga_map_t;
image_tga_map_t mStaticImageListTGA;
-public:
S32 mGLBytes;
S32 mTGABytes;
};
// Used by LLTexLayerSetBuffer for a callback.
-
-// For DEV-DEV-31590, "Heap corruption and crash after outfit
-// changes", added the mLayerSet member. The current
-// LLTexLayerSetBuffer can be found by querying mLayerSet->mComposite,
-// but we still store the original mLayerSetBuffer here so we can
-// detect when an upload is out of date. This prevents a memory
-// stomp. See LLTexLayerSetBuffer::onTextureUploadComplete() for usage.
+// Note to anyone merging branches - this supercedes the previous fix
+// for DEV-31590 "Heap corruption and crash after outfit changes",
+// here and in lltexlayer.cpp. Equally correct and a bit simpler.
class LLBakedUploadData
{
public:
- LLBakedUploadData( LLVOAvatar* avatar, LLTexLayerSet* layerset, LLTexLayerSetBuffer* layerset_buffer, const LLUUID & id);
+ LLBakedUploadData(const LLVOAvatarSelf* avatar, LLTexLayerSet* layerset, const LLUUID& id);
~LLBakedUploadData() {}
- LLUUID mID;
- LLVOAvatar* mAvatar; // just backlink, don't LLPointer
- LLTexLayerSet* mLayerSet;
- LLTexLayerSetBuffer* mLayerSetBuffer;
- LLUUID mWearableAssets[WT_COUNT];
- U64 mStartTime; // Used to measure time baked texture upload requires
+ const LLUUID mID;
+ const LLVOAvatarSelf* mAvatar; // just backlink, don't LLPointer
+ LLTexLayerSet* mTexLayerSet;
+ const U64 mStartTime; // Used to measure time baked texture upload requires
};
-extern LLTexStaticImageList gTexStaticImageList;
-
#endif // LL_LLTEXLAYER_H
diff --git a/indra/newview/lltexlayerparams.cpp b/indra/newview/lltexlayerparams.cpp
new file mode 100644
index 0000000000..d55468841d
--- /dev/null
+++ b/indra/newview/lltexlayerparams.cpp
@@ -0,0 +1,573 @@
+/**
+ * @file lltexlayerparams.cpp
+ * @brief SERAPH - ADD IN
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lltexlayerparams.h"
+
+#include "llagent.h"
+#include "llimagetga.h"
+#include "lltexlayer.h"
+#include "llvoavatarself.h"
+#include "llwearable.h"
+#include "llui.h"
+
+//-----------------------------------------------------------------------------
+// LLTexLayerParam
+//-----------------------------------------------------------------------------
+LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) :
+ mTexLayer(layer),
+ mAvatar(NULL)
+{
+ if (mTexLayer != NULL)
+ {
+ mAvatar = mTexLayer->getTexLayerSet()->getAvatar();
+ }
+ else
+ {
+ llerrs << "LLTexLayerParam constructor passed with NULL reference for layer!" << llendl;
+ }
+}
+
+LLTexLayerParam::LLTexLayerParam(LLVOAvatar *avatar) :
+ mTexLayer(NULL)
+{
+ mAvatar = avatar;
+}
+
+
+BOOL LLTexLayerParam::setInfo(LLViewerVisualParamInfo *info, BOOL add_to_avatar )
+{
+ LLViewerVisualParam::setInfo(info);
+
+ if (add_to_avatar)
+ {
+ mAvatar->addVisualParam( this);
+ }
+
+ return TRUE;
+}
+
+
+//-----------------------------------------------------------------------------
+// LLTexLayerParamAlpha
+//-----------------------------------------------------------------------------
+
+// static
+LLTexLayerParamAlpha::param_alpha_ptr_list_t LLTexLayerParamAlpha::sInstances;
+
+// static
+void LLTexLayerParamAlpha::dumpCacheByteCount()
+{
+ S32 gl_bytes = 0;
+ getCacheByteCount( &gl_bytes);
+ llinfos << "Processed Alpha Texture Cache GL:" << (gl_bytes/1024) << "KB" << llendl;
+}
+
+// static
+void LLTexLayerParamAlpha::getCacheByteCount(S32* gl_bytes)
+{
+ *gl_bytes = 0;
+
+ for (param_alpha_ptr_list_t::iterator iter = sInstances.begin();
+ iter != sInstances.end(); iter++)
+ {
+ LLTexLayerParamAlpha* instance = *iter;
+ LLViewerTexture* tex = instance->mCachedProcessedTexture;
+ if (tex)
+ {
+ S32 bytes = (S32)tex->getWidth() * tex->getHeight() * tex->getComponents();
+
+ if (tex->hasGLTexture())
+ {
+ *gl_bytes += bytes;
+ }
+ }
+ }
+}
+
+LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayerInterface* layer) :
+ LLTexLayerParam(layer),
+ mCachedProcessedTexture(NULL),
+ mNeedsCreateTexture(FALSE),
+ mStaticImageInvalid(FALSE),
+ mAvgDistortionVec(1.f, 1.f, 1.f),
+ mCachedEffectiveWeight(0.f)
+{
+ sInstances.push_front(this);
+}
+
+LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLVOAvatar* avatar) :
+ LLTexLayerParam(avatar),
+ mCachedProcessedTexture(NULL),
+ mNeedsCreateTexture(FALSE),
+ mStaticImageInvalid(FALSE),
+ mAvgDistortionVec(1.f, 1.f, 1.f),
+ mCachedEffectiveWeight(0.f)
+{
+ sInstances.push_front(this);
+}
+
+
+LLTexLayerParamAlpha::~LLTexLayerParamAlpha()
+{
+ deleteCaches();
+ sInstances.remove(this);
+}
+
+/*virtual*/ LLViewerVisualParam* LLTexLayerParamAlpha::cloneParam(LLWearable* wearable) const
+{
+ LLTexLayerParamAlpha *new_param = new LLTexLayerParamAlpha(mTexLayer);
+ *new_param = *this;
+ return new_param;
+}
+
+void LLTexLayerParamAlpha::deleteCaches()
+{
+ mStaticImageTGA = NULL; // deletes image
+ mCachedProcessedTexture = NULL;
+ mStaticImageRaw = NULL;
+ mNeedsCreateTexture = FALSE;
+}
+
+BOOL LLTexLayerParamAlpha::getMultiplyBlend() const
+{
+ return ((LLTexLayerParamAlphaInfo *)getInfo())->mMultiplyBlend;
+}
+
+void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL upload_bake)
+{
+ if (mIsAnimating || mTexLayer == NULL)
+ {
+ return;
+ }
+ F32 min_weight = getMinWeight();
+ F32 max_weight = getMaxWeight();
+ F32 new_weight = llclamp(weight, min_weight, max_weight);
+ U8 cur_u8 = F32_to_U8(mCurWeight, min_weight, max_weight);
+ U8 new_u8 = F32_to_U8(new_weight, min_weight, max_weight);
+ if (cur_u8 != new_u8)
+ {
+ mCurWeight = new_weight;
+
+ if ((mAvatar->getSex() & getSex()) && (mAvatar->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
+ {
+ if (gAgent.cameraCustomizeAvatar())
+ {
+ upload_bake = FALSE;
+ }
+ mAvatar->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake);
+ mTexLayer->invalidateMorphMasks();
+ }
+ }
+}
+
+void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value, BOOL upload_bake)
+{
+ // do not animate dummy parameters
+ if (mIsDummy)
+ {
+ setWeight(target_value, upload_bake);
+ return;
+ }
+
+ mTargetWeight = target_value;
+ setWeight(target_value, upload_bake);
+ mIsAnimating = TRUE;
+ if (mNext)
+ {
+ mNext->setAnimationTarget(target_value, upload_bake);
+ }
+}
+
+void LLTexLayerParamAlpha::animate(F32 delta, BOOL upload_bake)
+{
+ if (mNext)
+ {
+ mNext->animate(delta, upload_bake);
+ }
+}
+
+BOOL LLTexLayerParamAlpha::getSkip() const
+{
+ if (!mTexLayer)
+ {
+ return TRUE;
+ }
+
+ const LLVOAvatar *avatar = mTexLayer->getTexLayerSet()->getAvatar();
+
+ if (((LLTexLayerParamAlphaInfo *)getInfo())->mSkipIfZeroWeight)
+ {
+ F32 effective_weight = (avatar->getSex() & getSex()) ? mCurWeight : getDefaultWeight();
+ if (is_approx_zero(effective_weight))
+ {
+ return TRUE;
+ }
+ }
+
+ EWearableType type = (EWearableType)getWearableType();
+ if ((type != WT_INVALID) && !avatar->isWearingWearableType(type))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height)
+{
+ BOOL success = TRUE;
+
+ if (!mTexLayer)
+ {
+ return success;
+ }
+
+ F32 effective_weight = (mTexLayer->getTexLayerSet()->getAvatar()->getSex() & getSex()) ? mCurWeight : getDefaultWeight();
+ BOOL weight_changed = effective_weight != mCachedEffectiveWeight;
+ if (getSkip())
+ {
+ return success;
+ }
+
+ LLTexLayerParamAlphaInfo *info = (LLTexLayerParamAlphaInfo *)getInfo();
+ gGL.flush();
+ if (info->mMultiplyBlend)
+ {
+ gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO); // Multiplication: approximates a min() function
+ }
+ else
+ {
+ gGL.setSceneBlendType(LLRender::BT_ADD); // Addition: approximates a max() function
+ }
+
+ if (!info->mStaticImageFileName.empty() && !mStaticImageInvalid)
+ {
+ if (mStaticImageTGA.isNull())
+ {
+ // Don't load the image file until we actually need it the first time. Like now.
+ mStaticImageTGA = LLTexLayerStaticImageList::getInstance()->getImageTGA(info->mStaticImageFileName);
+ // We now have something in one of our caches
+ LLTexLayerSet::sHasCaches |= mStaticImageTGA.notNull() ? TRUE : FALSE;
+
+ if (mStaticImageTGA.isNull())
+ {
+ llwarns << "Unable to load static file: " << info->mStaticImageFileName << llendl;
+ mStaticImageInvalid = TRUE; // don't try again.
+ return FALSE;
+ }
+ }
+
+ const S32 image_tga_width = mStaticImageTGA->getWidth();
+ const S32 image_tga_height = mStaticImageTGA->getHeight();
+ if (!mCachedProcessedTexture ||
+ (mCachedProcessedTexture->getWidth() != image_tga_width) ||
+ (mCachedProcessedTexture->getHeight() != image_tga_height) ||
+ (weight_changed))
+ {
+// llinfos << "Building Cached Alpha: " << mName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << effective_weight << llendl;
+ mCachedEffectiveWeight = effective_weight;
+
+ if (!mCachedProcessedTexture)
+ {
+ mCachedProcessedTexture = LLViewerTextureManager::getLocalTexture(image_tga_width, image_tga_height, 1, FALSE);
+
+ // We now have something in one of our caches
+ LLTexLayerSet::sHasCaches |= mCachedProcessedTexture ? TRUE : FALSE;
+
+ mCachedProcessedTexture->setExplicitFormat(GL_ALPHA8, GL_ALPHA);
+ }
+
+ // Applies domain and effective weight to data as it is decoded. Also resizes the raw image if needed.
+ mStaticImageRaw = NULL;
+ mStaticImageRaw = new LLImageRaw;
+ mStaticImageTGA->decodeAndProcess(mStaticImageRaw, info->mDomain, effective_weight);
+ mNeedsCreateTexture = TRUE;
+ }
+
+ if (mCachedProcessedTexture)
+ {
+ {
+ // Create the GL texture, and then hang onto it for future use.
+ if (mNeedsCreateTexture)
+ {
+ mCachedProcessedTexture->createGLTexture(0, mStaticImageRaw);
+ mNeedsCreateTexture = FALSE;
+ gGL.getTexUnit(0)->bind(mCachedProcessedTexture);
+ mCachedProcessedTexture->setAddressMode(LLTexUnit::TAM_CLAMP);
+ }
+
+ LLGLSNoAlphaTest gls_no_alpha_test;
+ gGL.getTexUnit(0)->bind(mCachedProcessedTexture);
+ gl_rect_2d_simple_tex(width, height);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ stop_glerror();
+ }
+ }
+
+ // Don't keep the cache for other people's avatars
+ // (It's not really a "cache" in that case, but the logic is the same)
+ if (!mAvatar->isSelf())
+ {
+ mCachedProcessedTexture = NULL;
+ }
+ }
+ else
+ {
+ LLGLDisable no_alpha(GL_ALPHA_TEST);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.color4f(0.f, 0.f, 0.f, effective_weight);
+ gl_rect_2d_simple(width, height);
+ }
+
+ return success;
+}
+
+//-----------------------------------------------------------------------------
+// LLTexLayerParamAlphaInfo
+//-----------------------------------------------------------------------------
+LLTexLayerParamAlphaInfo::LLTexLayerParamAlphaInfo() :
+ mMultiplyBlend(FALSE),
+ mSkipIfZeroWeight(FALSE),
+ mDomain(0.f)
+{
+}
+
+BOOL LLTexLayerParamAlphaInfo::parseXml(LLXmlTreeNode* node)
+{
+ llassert(node->hasName("param") && node->getChildByName("param_alpha"));
+
+ if (!LLViewerVisualParamInfo::parseXml(node))
+ return FALSE;
+
+ LLXmlTreeNode* param_alpha_node = node->getChildByName("param_alpha");
+ if (!param_alpha_node)
+ {
+ return FALSE;
+ }
+
+ static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file");
+ if (param_alpha_node->getFastAttributeString(tga_file_string, mStaticImageFileName))
+ {
+ // Don't load the image file until it's actually needed.
+ }
+// else
+// {
+// llwarns << "<param_alpha> element is missing tga_file attribute." << llendl;
+// }
+
+ static LLStdStringHandle multiply_blend_string = LLXmlTree::addAttributeString("multiply_blend");
+ param_alpha_node->getFastAttributeBOOL(multiply_blend_string, mMultiplyBlend);
+
+ static LLStdStringHandle skip_if_zero_string = LLXmlTree::addAttributeString("skip_if_zero");
+ param_alpha_node->getFastAttributeBOOL(skip_if_zero_string, mSkipIfZeroWeight);
+
+ static LLStdStringHandle domain_string = LLXmlTree::addAttributeString("domain");
+ param_alpha_node->getFastAttributeF32(domain_string, mDomain);
+
+ return TRUE;
+}
+
+
+
+
+LLTexLayerParamColor::LLTexLayerParamColor(LLTexLayerInterface* layer) :
+ LLTexLayerParam(layer),
+ mAvgDistortionVec(1.f, 1.f, 1.f)
+{
+}
+
+LLTexLayerParamColor::LLTexLayerParamColor(LLVOAvatar *avatar) :
+ LLTexLayerParam(avatar),
+ mAvgDistortionVec(1.f, 1.f, 1.f)
+{
+}
+
+LLTexLayerParamColor::~LLTexLayerParamColor()
+{
+}
+
+/*virtual*/ LLViewerVisualParam* LLTexLayerParamColor::cloneParam(LLWearable* wearable) const
+{
+ LLTexLayerParamColor *new_param = new LLTexLayerParamColor(mTexLayer);
+ *new_param = *this;
+ return new_param;
+}
+
+LLColor4 LLTexLayerParamColor::getNetColor() const
+{
+ const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo();
+
+ llassert(info->mNumColors >= 1);
+
+ F32 effective_weight = (mAvatar && (mAvatar->getSex() & getSex())) ? mCurWeight : getDefaultWeight();
+
+ S32 index_last = info->mNumColors - 1;
+ F32 scaled_weight = effective_weight * index_last;
+ S32 index_start = (S32) scaled_weight;
+ S32 index_end = index_start + 1;
+ if (index_start == index_last)
+ {
+ return info->mColors[index_last];
+ }
+ else
+ {
+ F32 weight = scaled_weight - index_start;
+ const LLColor4 *start = &info->mColors[ index_start ];
+ const LLColor4 *end = &info->mColors[ index_end ];
+ return LLColor4((1.f - weight) * start->mV[VX] + weight * end->mV[VX],
+ (1.f - weight) * start->mV[VY] + weight * end->mV[VY],
+ (1.f - weight) * start->mV[VZ] + weight * end->mV[VZ],
+ (1.f - weight) * start->mV[VW] + weight * end->mV[VW]);
+ }
+}
+
+void LLTexLayerParamColor::setWeight(F32 weight, BOOL upload_bake)
+{
+ if (mIsAnimating)
+ {
+ return;
+ }
+
+ const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo();
+ F32 min_weight = getMinWeight();
+ F32 max_weight = getMaxWeight();
+ F32 new_weight = llclamp(weight, min_weight, max_weight);
+ U8 cur_u8 = F32_to_U8(mCurWeight, min_weight, max_weight);
+ U8 new_u8 = F32_to_U8(new_weight, min_weight, max_weight);
+ if (cur_u8 != new_u8)
+ {
+ mCurWeight = new_weight;
+
+ if (info->mNumColors <= 0)
+ {
+ // This will happen when we set the default weight the first time.
+ return;
+ }
+
+ if ((mAvatar->getSex() & getSex()) && (mAvatar->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
+ {
+ onGlobalColorChanged(upload_bake);
+ if (mTexLayer)
+ {
+ mAvatar->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake);
+ }
+ }
+
+// llinfos << "param " << mName << " = " << new_weight << llendl;
+ }
+}
+
+void LLTexLayerParamColor::setAnimationTarget(F32 target_value, BOOL upload_bake)
+{
+ // set value first then set interpolating flag to ignore further updates
+ mTargetWeight = target_value;
+ setWeight(target_value, upload_bake);
+ mIsAnimating = TRUE;
+ if (mNext)
+ {
+ mNext->setAnimationTarget(target_value, upload_bake);
+ }
+}
+
+void LLTexLayerParamColor::animate(F32 delta, BOOL upload_bake)
+{
+ if (mNext)
+ {
+ mNext->animate(delta, upload_bake);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// LLTexLayerParamColorInfo
+//-----------------------------------------------------------------------------
+LLTexLayerParamColorInfo::LLTexLayerParamColorInfo() :
+ mOperation(LLTexLayerParamColor::OP_ADD),
+ mNumColors(0)
+{
+}
+
+BOOL LLTexLayerParamColorInfo::parseXml(LLXmlTreeNode *node)
+{
+ llassert(node->hasName("param") && node->getChildByName("param_color"));
+
+ if (!LLViewerVisualParamInfo::parseXml(node))
+ return FALSE;
+
+ LLXmlTreeNode* param_color_node = node->getChildByName("param_color");
+ if (!param_color_node)
+ {
+ return FALSE;
+ }
+
+ std::string op_string;
+ static LLStdStringHandle operation_string = LLXmlTree::addAttributeString("operation");
+ if (param_color_node->getFastAttributeString(operation_string, op_string))
+ {
+ LLStringUtil::toLower(op_string);
+ if (op_string == "add") mOperation = LLTexLayerParamColor::OP_ADD;
+ else if (op_string == "multiply") mOperation = LLTexLayerParamColor::OP_MULTIPLY;
+ else if (op_string == "blend") mOperation = LLTexLayerParamColor::OP_BLEND;
+ }
+
+ mNumColors = 0;
+
+ LLColor4U color4u;
+ for (LLXmlTreeNode* child = param_color_node->getChildByName("value");
+ child;
+ child = param_color_node->getNextNamedChild())
+ {
+ if ((mNumColors < MAX_COLOR_VALUES))
+ {
+ static LLStdStringHandle color_string = LLXmlTree::addAttributeString("color");
+ if (child->getFastAttributeColor4U(color_string, color4u))
+ {
+ mColors[ mNumColors ].setVec(color4u);
+ mNumColors++;
+ }
+ }
+ }
+ if (!mNumColors)
+ {
+ llwarns << "<param_color> is missing <value> sub-elements" << llendl;
+ return FALSE;
+ }
+
+ if ((mOperation == LLTexLayerParamColor::OP_BLEND) && (mNumColors != 1))
+ {
+ llwarns << "<param_color> with operation\"blend\" must have exactly one <value>" << llendl;
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/indra/newview/lltexlayerparams.h b/indra/newview/lltexlayerparams.h
new file mode 100644
index 0000000000..93d01352d4
--- /dev/null
+++ b/indra/newview/lltexlayerparams.h
@@ -0,0 +1,191 @@
+/**
+ * @file lltexlayerparams.h
+ * @brief Texture layer parameters, used by lltexlayer.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTEXLAYERPARAMS_H
+#define LL_LLTEXLAYERPARAMS_H
+
+#include "llviewervisualparam.h"
+
+class LLImageRaw;
+class LLImageTGA;
+class LLTexLayer;
+class LLTexLayerInterface;
+class LLViewerTexture;
+class LLVOAvatar;
+class LLWearable;
+
+class LLTexLayerParam : public LLViewerVisualParam
+{
+public:
+ LLTexLayerParam(LLTexLayerInterface *layer);
+ LLTexLayerParam(LLVOAvatar *avatar);
+ /*virtual*/ BOOL setInfo(LLViewerVisualParamInfo *info, BOOL add_to_avatar );
+ /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const = 0;
+
+protected:
+ LLTexLayerInterface* mTexLayer;
+ LLVOAvatar* mAvatar;
+};
+
+//-----------------------------------------------------------------------------
+// LLTexLayerParamAlpha
+//
+class LLTexLayerParamAlpha : public LLTexLayerParam
+{
+public:
+ LLTexLayerParamAlpha( LLTexLayerInterface* layer );
+ LLTexLayerParamAlpha( LLVOAvatar* avatar );
+ /*virtual*/ ~LLTexLayerParamAlpha();
+
+ /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const;
+
+ // LLVisualParam Virtual functions
+ ///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
+ /*virtual*/ void apply( ESex avatar_sex ) {}
+ /*virtual*/ void setWeight(F32 weight, BOOL upload_bake);
+ /*virtual*/ void setAnimationTarget(F32 target_value, BOOL upload_bake);
+ /*virtual*/ void animate(F32 delta, BOOL upload_bake);
+
+ // LLViewerVisualParam Virtual functions
+ /*virtual*/ F32 getTotalDistortion() { return 1.f; }
+ /*virtual*/ const LLVector3& getAvgDistortion() { return mAvgDistortionVec; }
+ /*virtual*/ F32 getMaxDistortion() { return 3.f; }
+ /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector3(1.f, 1.f, 1.f);}
+ /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;};
+ /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;};
+
+ // New functions
+ BOOL render( S32 x, S32 y, S32 width, S32 height );
+ BOOL getSkip() const;
+ void deleteCaches();
+ BOOL getMultiplyBlend() const;
+
+private:
+ LLPointer<LLViewerTexture> mCachedProcessedTexture;
+ LLPointer<LLImageTGA> mStaticImageTGA;
+ LLPointer<LLImageRaw> mStaticImageRaw;
+ BOOL mNeedsCreateTexture;
+ BOOL mStaticImageInvalid;
+ LLVector3 mAvgDistortionVec;
+ F32 mCachedEffectiveWeight;
+
+public:
+ // Global list of instances for gathering statistics
+ static void dumpCacheByteCount();
+ static void getCacheByteCount( S32* gl_bytes );
+
+ typedef std::list< LLTexLayerParamAlpha* > param_alpha_ptr_list_t;
+ static param_alpha_ptr_list_t sInstances;
+};
+class LLTexLayerParamAlphaInfo : public LLViewerVisualParamInfo
+{
+ friend class LLTexLayerParamAlpha;
+public:
+ LLTexLayerParamAlphaInfo();
+ /*virtual*/ ~LLTexLayerParamAlphaInfo() {};
+
+ /*virtual*/ BOOL parseXml(LLXmlTreeNode* node);
+
+private:
+ std::string mStaticImageFileName;
+ BOOL mMultiplyBlend;
+ BOOL mSkipIfZeroWeight;
+ F32 mDomain;
+};
+//
+// LLTexLayerParamAlpha
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// LLTexLayerParamColor
+//
+class LLTexLayerParamColor : public LLTexLayerParam
+{
+public:
+ enum EColorOperation
+ {
+ OP_ADD = 0,
+ OP_MULTIPLY = 1,
+ OP_BLEND = 2,
+ OP_COUNT = 3 // Number of operations
+ };
+
+ LLTexLayerParamColor( LLTexLayerInterface* layer );
+ LLTexLayerParamColor( LLVOAvatar* avatar );
+ /* virtual */ ~LLTexLayerParamColor();
+
+ /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const;
+
+ // LLVisualParam Virtual functions
+ ///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
+ /*virtual*/ void apply( ESex avatar_sex ) {}
+ /*virtual*/ void setWeight(F32 weight, BOOL upload_bake);
+ /*virtual*/ void setAnimationTarget(F32 target_value, BOOL upload_bake);
+ /*virtual*/ void animate(F32 delta, BOOL upload_bake);
+
+
+ // LLViewerVisualParam Virtual functions
+ /*virtual*/ F32 getTotalDistortion() { return 1.f; }
+ /*virtual*/ const LLVector3& getAvgDistortion() { return mAvgDistortionVec; }
+ /*virtual*/ F32 getMaxDistortion() { return 3.f; }
+ /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector3(1.f, 1.f, 1.f); }
+ /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;};
+ /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;};
+
+ // New functions
+ LLColor4 getNetColor() const;
+protected:
+ virtual void onGlobalColorChanged(bool upload_bake) {}
+private:
+ LLVector3 mAvgDistortionVec;
+};
+
+class LLTexLayerParamColorInfo : public LLViewerVisualParamInfo
+{
+ friend class LLTexLayerParamColor;
+
+public:
+ LLTexLayerParamColorInfo();
+ virtual ~LLTexLayerParamColorInfo() {};
+ BOOL parseXml( LLXmlTreeNode* node );
+ LLTexLayerParamColor::EColorOperation getOperation() const { return mOperation; }
+private:
+ enum { MAX_COLOR_VALUES = 20 };
+ LLTexLayerParamColor::EColorOperation mOperation;
+ LLColor4 mColors[MAX_COLOR_VALUES];
+ S32 mNumColors;
+};
+
+//
+// LLTexLayerParamColor
+//-----------------------------------------------------------------------------
+
+#endif
diff --git a/indra/newview/lltextureatlas.cpp b/indra/newview/lltextureatlas.cpp
new file mode 100644
index 0000000000..79b3686386
--- /dev/null
+++ b/indra/newview/lltextureatlas.cpp
@@ -0,0 +1,422 @@
+/**
+ * @file lltextureatlas.cpp
+ * @brief LLTextureAtlas class implementation.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "llviewerprecompiledheaders.h"
+#include "linden_common.h"
+#include "llerror.h"
+#include "llimage.h"
+#include "llmath.h"
+#include "llgl.h"
+#include "llrender.h"
+#include "lltextureatlas.h"
+
+//-------------------
+S16 LLTextureAtlas::sMaxSubTextureSize = 64 ;
+S16 LLTextureAtlas::sSlotSize = 32 ;
+
+#ifndef DEBUG_ATLAS
+#define DEBUG_ATLAS 0
+#endif
+
+#ifndef DEBUG_USAGE_BITS
+#define DEBUG_USAGE_BITS 0
+#endif
+//**************************************************************************************************************
+LLTextureAtlas::LLTextureAtlas(U8 ncomponents, S16 atlas_dim) :
+ LLViewerTexture(atlas_dim * sSlotSize, atlas_dim * sSlotSize, ncomponents, TRUE),
+ mAtlasDim(atlas_dim),
+ mNumSlotsReserved(0),
+ mMaxSlotsInAtlas(atlas_dim * atlas_dim)
+{
+ generateEmptyUsageBits() ;
+
+ //generate an empty texture
+ generateGLTexture() ;
+ LLPointer<LLImageRaw> image_raw = new LLImageRaw(mFullWidth, mFullHeight, mComponents);
+ createGLTexture(0, image_raw, 0);
+ image_raw = NULL;
+}
+
+LLTextureAtlas::~LLTextureAtlas()
+{
+ if(mSpatialGroupList.size() > 0)
+ {
+ llerrs << "Not clean up the spatial groups!" << llendl ;
+ }
+ releaseUsageBits() ;
+}
+
+//virtual
+S8 LLTextureAtlas::getType() const
+{
+ return LLViewerTexture::ATLAS_TEXTURE ;
+}
+
+void LLTextureAtlas::getTexCoordOffset(S16 col, S16 row, F32& xoffset, F32& yoffset)
+{
+ xoffset = (F32)col / mAtlasDim ;
+ yoffset = (F32)row / mAtlasDim ;
+}
+
+void LLTextureAtlas::getTexCoordScale(S32 w, S32 h, F32& xscale, F32& yscale)
+{
+ xscale = (F32)w / (mAtlasDim * sSlotSize) ;
+ yscale = (F32)h / (mAtlasDim * sSlotSize) ;
+}
+
+//insert a texture piece into the atlas
+LLGLuint LLTextureAtlas::insertSubTexture(LLImageGL* source_gl_tex, S32 discard_level, const LLImageRaw* raw_image, S16 slot_col, S16 slot_row)
+{
+ if(!getTexName())
+ {
+ return 0 ;
+ }
+
+ S32 w = raw_image->getWidth() ;
+ S32 h = raw_image->getHeight() ;
+ if(w < 8 || w > sMaxSubTextureSize || h < 8 || h > sMaxSubTextureSize)
+ {
+ //size overflow
+ return 0 ;
+ }
+
+ BOOL res = gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getTexName());
+ if (!res)
+ {
+ llerrs << "bindTexture failed" << llendl;
+ }
+
+ GLint xoffset = sSlotSize * slot_col ;
+ GLint yoffset = sSlotSize * slot_row ;
+
+ if(!source_gl_tex->preAddToAtlas(discard_level, raw_image))
+ {
+ return 0 ;
+ }
+
+ glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, TRUE);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, w, h,
+ mGLTexturep->getPrimaryFormat(), mGLTexturep->getFormatType(), raw_image->getData());
+
+ source_gl_tex->postAddToAtlas() ;
+ return getTexName();
+}
+
+//release a sub-texture slot from the atlas
+void LLTextureAtlas::releaseSlot(S16 slot_col, S16 slot_row, S8 slot_width)
+{
+ unmarkUsageBits(slot_width, slot_col, slot_row) ;
+ mNumSlotsReserved -= slot_width * slot_width ;
+}
+
+BOOL LLTextureAtlas::isEmpty() const
+{
+ return !mNumSlotsReserved ;
+}
+
+BOOL LLTextureAtlas::isFull(S8 to_be_reserved) const
+{
+ return mNumSlotsReserved + to_be_reserved > mMaxSlotsInAtlas ;
+}
+F32 LLTextureAtlas::getFullness() const
+{
+ return (F32)mNumSlotsReserved / mMaxSlotsInAtlas ;
+}
+
+void LLTextureAtlas::addSpatialGroup(LLSpatialGroup* groupp)
+{
+ if(groupp && !hasSpatialGroup(groupp))
+ {
+ mSpatialGroupList.push_back(groupp);
+ }
+}
+
+void LLTextureAtlas::removeSpatialGroup(LLSpatialGroup* groupp)
+{
+ if(groupp)
+ {
+ mSpatialGroupList.remove(groupp);
+ }
+}
+
+void LLTextureAtlas::clearSpatialGroup()
+{
+ mSpatialGroupList.clear();
+}
+void LLTextureAtlas::removeLastSpatialGroup()
+{
+ mSpatialGroupList.pop_back() ;
+}
+
+LLSpatialGroup* LLTextureAtlas::getLastSpatialGroup()
+{
+ if(mSpatialGroupList.size() > 0)
+ {
+ return mSpatialGroupList.back() ;
+ }
+ return NULL ;
+}
+
+BOOL LLTextureAtlas::hasSpatialGroup(LLSpatialGroup* groupp)
+{
+ for(std::list<LLSpatialGroup*>::iterator iter = mSpatialGroupList.begin(); iter != mSpatialGroupList.end() ; ++iter)
+ {
+ if(*iter == groupp)
+ {
+ return TRUE ;
+ }
+ }
+ return FALSE ;
+}
+
+//--------------------------------------------------------------------------------------
+//private
+void LLTextureAtlas::generateEmptyUsageBits()
+{
+ S32 col_len = (mAtlasDim + 7) >> 3 ;
+ mUsageBits = new U8*[mAtlasDim] ;
+ *mUsageBits = new U8[mAtlasDim * col_len] ;
+
+ mUsageBits[0] = *mUsageBits ;
+ for(S32 i = 1 ; i < mAtlasDim ; i++)
+ {
+ mUsageBits[i] = mUsageBits[i-1] + col_len ;
+
+ for(S32 j = 0 ; j < col_len ; j++)
+ {
+ //init by 0 for all bits.
+ mUsageBits[i][j] = 0 ;
+ }
+ }
+
+ //do not forget mUsageBits[0]!
+ for(S32 j = 0 ; j < col_len ; j++)
+ {
+ //init by 0 for all bits.
+ mUsageBits[0][j] = 0 ;
+ }
+
+ mTestBits = NULL ;
+#if DEBUG_USAGE_BITS
+ //------------
+ //test
+ mTestBits = new U8*[mAtlasDim] ;
+ *mTestBits = new U8[mAtlasDim * mAtlasDim] ;
+ mTestBits[0] = *mTestBits ;
+ for(S32 i = 1 ; i < mAtlasDim ; i++)
+ {
+ mTestBits[i] = mTestBits[i-1] + mAtlasDim ;
+
+ for(S32 j = 0 ; j < mAtlasDim ; j++)
+ {
+ //init by 0 for all bits.
+ mTestBits[i][j] = 0 ;
+ }
+ }
+
+ for(S32 j = 0 ; j < mAtlasDim ; j++)
+ {
+ //init by 0 for all bits.
+ mTestBits[0][j] = 0 ;
+ }
+#endif
+}
+
+void LLTextureAtlas::releaseUsageBits()
+{
+ if(mUsageBits)
+ {
+ delete[] *mUsageBits ;
+ delete[] mUsageBits ;
+ }
+ mUsageBits = NULL ;
+
+ //test
+ if( mTestBits)
+ {
+ delete[] *mTestBits;
+ delete[] mTestBits;
+ }
+ mTestBits = NULL ;
+}
+
+void LLTextureAtlas::markUsageBits(S8 bits_len, U8 mask, S16 col, S16 row)
+{
+ S16 x = col >> 3 ;
+
+ for(S8 i = 0 ; i < bits_len ; i++)
+ {
+ mUsageBits[row + i][x] |= mask ;
+ }
+
+#if DEBUG_USAGE_BITS
+ //test
+ for(S8 i = row ; i < row + bits_len ; i++)
+ {
+ for(S8 j = col ; j < col + bits_len ; j++)
+ {
+ mTestBits[i][j] = 1 ;
+ }
+ }
+#endif
+}
+
+void LLTextureAtlas::unmarkUsageBits(S8 bits_len, S16 col, S16 row)
+{
+ S16 x = col >> 3 ;
+ U8 mask = 1 ;
+ for(S8 i = 1 ; i < bits_len ; i++)
+ {
+ mask |= (1 << i) ;
+ }
+ mask <<= (col & 7) ;
+ mask = ~mask ;
+
+ for(S8 i = 0 ; i < bits_len ; i++)
+ {
+ mUsageBits[row + i][x] &= mask ;
+ }
+
+#if DEBUG_USAGE_BITS
+ //test
+ for(S8 i = row ; i < row + bits_len ; i++)
+ {
+ for(S8 j = col ; j < col + bits_len ; j++)
+ {
+ mTestBits[i][j] = 0 ;
+ }
+ }
+#endif
+}
+
+//return true if any of bits in the range marked.
+BOOL LLTextureAtlas::areUsageBitsMarked(S8 bits_len, U8 mask, S16 col, S16 row)
+{
+ BOOL ret = FALSE ;
+ S16 x = col >> 3 ;
+
+ for(S8 i = 0 ; i < bits_len ; i++)
+ {
+ if(mUsageBits[row + i][x] & mask)
+ {
+ ret = TRUE ;
+ break ;
+ //return TRUE ;
+ }
+ }
+
+#if DEBUG_USAGE_BITS
+ //test
+ BOOL ret2 = FALSE ;
+ for(S8 i = row ; i < row + bits_len ; i++)
+ {
+ for(S8 j = col ; j < col + bits_len ; j++)
+ {
+ if(mTestBits[i][j])
+ {
+ ret2 = TRUE ;
+ }
+ }
+ }
+
+ if(ret != ret2)
+ {
+ llerrs << "bits map corrupted." << llendl ;
+ }
+#endif
+ return ret ;//FALSE ;
+}
+
+//----------------------------------------------------------------------
+//
+//index order: Z order, i.e.:
+// |-----|-----|-----|-----|
+// | 10 | 11 | 14 | 15 |
+// |-----|-----|-----|-----|
+// | 8 | 9 | 12 | 13 |
+// |-----|-----|-----|-----|
+// | 2 | 3 | 6 | 7 |
+// |-----|-----|-----|-----|
+// | 0 | 1 | 4 | 5 |
+// |-----|-----|-----|-----|
+void LLTextureAtlas::getPositionFromIndex(S16 index, S16& col, S16& row)
+{
+ col = 0 ;
+ row = 0 ;
+
+ S16 index_copy = index ;
+ for(S16 i = 0 ; index_copy && i < 16 ; i += 2)
+ {
+ col |= ((index & (1 << i)) >> i) << (i >> 1) ;
+ row |= ((index & (1 << (i + 1))) >> (i + 1)) << (i >> 1) ;
+ index_copy >>= 2 ;
+ }
+}
+void LLTextureAtlas::getIndexFromPosition(S16 col, S16 row, S16& index)
+{
+ index = 0 ;
+ S16 col_copy = col ;
+ S16 row_copy = row ;
+ for(S16 i = 0 ; (col_copy || row_copy) && i < 16 ; i++)
+ {
+ index |= ((col & 1 << i) << i) | ((row & 1 << i) << ( i + 1)) ;
+ col_copy >>= 1 ;
+ row_copy >>= 1 ;
+ }
+}
+//----------------------------------------------------------------------
+//return TRUE if succeeds.
+BOOL LLTextureAtlas::getNextAvailableSlot(S8 bits_len, S16& col, S16& row)
+{
+ S16 index_step = bits_len * bits_len ;
+
+ U8 mask = 1 ;
+ for(S8 i = 1 ; i < bits_len ; i++)
+ {
+ mask |= (1 << i) ;
+ }
+
+ U8 cur_mask ;
+ for(S16 index = 0 ; index < mMaxSlotsInAtlas ; index += index_step)
+ {
+ getPositionFromIndex(index, col, row) ;
+
+ cur_mask = mask << (col & 7) ;
+ if(!areUsageBitsMarked(bits_len, cur_mask, col, row))
+ {
+ markUsageBits(bits_len, cur_mask, col, row) ;
+ mNumSlotsReserved += bits_len * bits_len ;
+
+ return TRUE ;
+ }
+ }
+
+ return FALSE ;
+}
diff --git a/indra/newview/lltextureatlas.h b/indra/newview/lltextureatlas.h
new file mode 100644
index 0000000000..1f756ccf1a
--- /dev/null
+++ b/indra/newview/lltextureatlas.h
@@ -0,0 +1,95 @@
+/**
+ * @file lltextureatlas.h
+ * @brief LLTextureAtlas base class.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#ifndef LL_TEXTUREATLAS_H
+#define LL_TEXTUREATLAS_H
+
+#include "llviewertexture.h"
+class LLSpatialGroup ;
+
+class LLTextureAtlas : public LLViewerTexture
+{
+protected:
+ /*virtual*/ ~LLTextureAtlas() ;
+
+public:
+ LLTextureAtlas(U8 ncomponents, S16 atlas_dim = 16) ;
+
+ /*virtual*/ S8 getType() const;
+
+ LLGLuint insertSubTexture(LLImageGL* source_gl_tex, S32 discard_level, const LLImageRaw* raw_image, S16 slot_col, S16 slot_row) ;
+ void releaseSlot(S16 slot_col, S16 slot_row, S8 slot_width);
+
+ BOOL getNextAvailableSlot(S8 bits_len, S16& col, S16& row) ;
+ void getTexCoordOffset(S16 col, S16 row, F32& xoffset, F32& yOffset) ;
+ void getTexCoordScale(S32 w, S32 h, F32& xscale, F32& yscale) ;
+
+ BOOL isEmpty() const ;
+ BOOL isFull(S8 to_be_reserved = 1) const ;
+ F32 getFullness() const ;
+
+ void addSpatialGroup(LLSpatialGroup* groupp) ;
+ void removeSpatialGroup(LLSpatialGroup* groupp) ;
+ LLSpatialGroup* getLastSpatialGroup() ;
+ void removeLastSpatialGroup() ;
+ BOOL hasSpatialGroup(LLSpatialGroup* groupp) ;
+ void clearSpatialGroup() ;
+ std::list<LLSpatialGroup*>* getSpatialGroupList() {return &mSpatialGroupList;}
+private:
+ void generateEmptyUsageBits() ;
+ void releaseUsageBits() ;
+
+ void markUsageBits(S8 bits_len, U8 mask, S16 col, S16 row) ;
+ void unmarkUsageBits(S8 bits_len, S16 col, S16 row) ;
+
+ void getPositionFromIndex(S16 index, S16& col, S16& row) ;
+ void getIndexFromPosition(S16 col, S16 row, S16& index) ;
+ BOOL areUsageBitsMarked(S8 bits_len, U8 mask, S16 col, S16 row) ;
+
+private:
+ S16 mAtlasDim ; //number of slots per edge, i.e, there are "mAtlasDim * mAtlasDim" total slots in the atlas.
+ S16 mNumSlotsReserved ;
+ S16 mMaxSlotsInAtlas ;
+ U8 **mUsageBits ;
+ std::list<LLSpatialGroup*> mSpatialGroupList ;
+
+public:
+ //debug use only
+ U8 **mTestBits ;
+
+public:
+ static S16 sMaxSubTextureSize ;
+ static S16 sSlotSize ;
+};
+
+#endif
+
diff --git a/indra/newview/lltextureatlasmanager.cpp b/indra/newview/lltextureatlasmanager.cpp
new file mode 100644
index 0000000000..8f026787ca
--- /dev/null
+++ b/indra/newview/lltextureatlasmanager.cpp
@@ -0,0 +1,273 @@
+/**
+ * @file lltextureatlasmanager.cpp
+ * @brief LLTextureAtlasManager class implementation.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "llviewerprecompiledheaders.h"
+#include "linden_common.h"
+#include "llerror.h"
+#include "llmath.h"
+#include "lltextureatlas.h"
+#include "lltextureatlasmanager.h"
+#include "llspatialpartition.h"
+
+const S8 MAX_NUM_EMPTY_ATLAS = 2 ;
+const F32 MIN_ATLAS_FULLNESS = 0.6f ;
+
+//*********************************************************************************************
+//implementation of class LLTextureAtlasInfo
+//*********************************************************************************************
+LLTextureAtlasSlot::LLTextureAtlasSlot(LLTextureAtlas* atlasp, LLSpatialGroup* groupp, S16 col, S16 row, F32 xoffset, F32 yoffset, S8 slot_width) :
+ mAtlasp(atlasp),
+ mGroupp(groupp),
+ mCol(col),
+ mRow(row),
+ mReservedSlotWidth(slot_width),
+ mValid(FALSE),
+ mUpdatedTime(0),
+ mTexCoordOffset(xoffset, yoffset),
+ mTexCoordScale(1.f, 1.f)
+{
+ llassert_always(mAtlasp || mGroupp || mReservedSlotWidth) ;
+}
+
+LLTextureAtlasSlot::~LLTextureAtlasSlot()
+{
+ if(mAtlasp)
+ {
+ mAtlasp->releaseSlot(mCol, mRow, mReservedSlotWidth) ;
+ if(mAtlasp->isEmpty())
+ {
+ LLTextureAtlasManager::getInstance()->releaseAtlas(mAtlasp) ;
+ }
+ mAtlasp = NULL ;
+ }
+}
+
+//void LLTextureAtlasSlot::setAtlas(LLTextureAtlas* atlasp)
+//{
+// mAtlasp = atlasp ;
+//}
+//void LLTextureAtlasSlot::setSlotPos(S16 col, S16 row)
+//{
+// mCol = col ;
+// mRow = row ;
+//}
+//void LLTextureAtlasSlot::setSlotWidth(S8 width)
+//{
+// //slot is a square with each edge length a power-of-two number
+// mReservedSlotWidth = width ;
+//}
+//void LLTextureAtlasSlot::setTexCoordOffset(F32 xoffset, F32 yoffset)
+//{
+// mTexCoordOffset.mV[0] = xoffset ;
+// mTexCoordOffset.mV[1] = yoffset ;
+//}
+
+void LLTextureAtlasSlot::setSpatialGroup(LLSpatialGroup* groupp)
+{
+ mGroupp = groupp ;
+}
+void LLTextureAtlasSlot::setTexCoordScale(F32 xscale, F32 yscale)
+{
+ mTexCoordScale.mV[0] = xscale ;
+ mTexCoordScale.mV[1] = yscale ;
+}
+//*********************************************************************************************
+//END of implementation of class LLTextureAtlasInfo
+//*********************************************************************************************
+
+//*********************************************************************************************
+//implementation of class LLTextureAtlasManager
+//*********************************************************************************************
+LLTextureAtlasManager::LLTextureAtlasManager() :
+ mAtlasMap(4),
+ mEmptyAtlasMap(4)
+{
+}
+
+LLTextureAtlasManager::~LLTextureAtlasManager()
+{
+ for(S32 i = 0 ; i < 4 ; i++)
+ {
+ for(ll_texture_atlas_list_t::iterator j = mAtlasMap[i].begin() ; j != mAtlasMap[i].end() ; ++j)
+ {
+ *j = NULL ;
+ }
+ for(ll_texture_atlas_list_t::iterator j = mEmptyAtlasMap[i].begin() ; j != mEmptyAtlasMap[i].end() ; ++j)
+ {
+ *j = NULL ;
+ }
+
+ mAtlasMap[i].clear() ;
+ mEmptyAtlasMap[i].clear() ;
+ }
+ mAtlasMap.clear() ;
+ mEmptyAtlasMap.clear() ;
+}
+
+//return TRUE if qualified
+BOOL LLTextureAtlasManager::canAddToAtlas(S32 w, S32 h, S8 ncomponents, LLGLenum target)
+{
+ if(ncomponents < 1 || ncomponents > 4)
+ {
+ return FALSE ;
+ }
+ //only support GL_TEXTURE_2D
+ if(GL_TEXTURE_2D != target)
+ {
+ return FALSE ;
+ }
+ //real image size overflows
+ if(w < 8 || w > LLTextureAtlas::sMaxSubTextureSize || h < 8 || h > LLTextureAtlas::sMaxSubTextureSize)
+ {
+ return FALSE ;
+ }
+
+ //if non-power-of-two number
+ if((w & (w - 1)) || (h & (h - 1)))
+ {
+ return FALSE ;
+ }
+
+ return TRUE ;
+}
+
+void LLTextureAtlasManager::releaseAtlas(LLTextureAtlas* atlasp)
+{
+ LLSpatialGroup* groupp = atlasp->getLastSpatialGroup() ;
+ while(groupp)
+ {
+ groupp->removeAtlas(atlasp, FALSE) ;
+ atlasp->removeLastSpatialGroup() ;
+
+ groupp = atlasp->getLastSpatialGroup() ;
+ }
+
+ S8 type = atlasp->getComponents() - 1 ;
+ //insert to the empty list
+ if(mEmptyAtlasMap[type].size() < MAX_NUM_EMPTY_ATLAS)
+ {
+ mEmptyAtlasMap[type].push_back(atlasp) ;
+ }
+
+ //delete the atlasp
+ mAtlasMap[type].remove(atlasp) ;
+}
+
+//
+//this function reserves an appropriate slot from atlas pool for an image.
+//return non-NULL if succeeds.
+//Note:
+//1, this function does not check if the image this slot assigned for qualifies for atlas or not,
+// call LLTextureAtlasManager::canAddToAtlas(...) to do the check before calling this function.
+//2, this function also dose not check if the image is already in atlas. It always assigns a new slot anyway.
+//3, this function tries to group sub-textures from same spatial group into ONE atlas to improve render batching.
+//
+LLPointer<LLTextureAtlasSlot> LLTextureAtlasManager::reserveAtlasSlot(S32 sub_texture_size, S8 ncomponents,
+ LLSpatialGroup* groupp, LLViewerTexture* imagep)
+{
+ if(!groupp)
+ {
+ //do not insert to atlas if does not have a group.
+ return NULL ;
+ }
+
+ //bits_len must <= 8 and is a power of two number, i.e.: must be one of these numbers: 1, 2, 4, 8.
+ if(sub_texture_size > LLTextureAtlas::sMaxSubTextureSize)
+ {
+ sub_texture_size = LLTextureAtlas::sMaxSubTextureSize ;
+ }
+ S8 bits_len = sub_texture_size / LLTextureAtlas::sSlotSize ;
+ if(bits_len < 1)
+ {
+ bits_len = 1 ;
+ }
+
+ S16 col = -1, row = -1;
+ S8 total_bits = bits_len * bits_len ;
+
+ //insert to the atlas reserved by the same spatial group
+ LLPointer<LLTextureAtlas> atlasp = groupp->getAtlas(ncomponents, total_bits) ;
+ if(atlasp.notNull())
+ {
+ if(!atlasp->getNextAvailableSlot(bits_len, col, row))
+ {
+ //failed
+ atlasp = NULL ;
+ }
+ }
+
+ //search an atlas to fit for 'size'
+ if(!atlasp)
+ {
+ S8 atlas_index = ncomponents - 1 ;
+ ll_texture_atlas_list_t::iterator iter = mAtlasMap[atlas_index].begin() ;
+ for(; iter != mAtlasMap[atlas_index].end(); ++iter)
+ {
+ LLTextureAtlas* cur = (LLTextureAtlas*)*iter ;
+ if(cur->getFullness() < MIN_ATLAS_FULLNESS)//this atlas is empty enough for this group to insert more sub-textures later if necessary.
+ {
+ if(cur->getNextAvailableSlot(bits_len, col, row))
+ {
+ atlasp = cur ;
+ groupp->addAtlas(atlasp) ;
+ break ;
+ }
+ }
+ }
+ }
+
+ //create a new atlas if necessary
+ if(!atlasp)
+ {
+ if(mEmptyAtlasMap[ncomponents - 1].size() > 0)
+ {
+ //there is an empty one
+ atlasp = mEmptyAtlasMap[ncomponents - 1].back() ;
+ mEmptyAtlasMap[ncomponents - 1].pop_back() ;
+ }
+ else
+ {
+ atlasp = new LLTextureAtlas(ncomponents, 16) ;
+ }
+ mAtlasMap[ncomponents - 1].push_back(atlasp) ;
+ atlasp->getNextAvailableSlot(bits_len, col, row) ;
+ groupp->addAtlas(atlasp) ;
+ }
+
+ F32 xoffset, yoffset ;
+ atlasp->getTexCoordOffset(col, row, xoffset, yoffset) ;
+ LLPointer<LLTextureAtlasSlot> slot_infop = new LLTextureAtlasSlot(atlasp, groupp, col, row, xoffset, yoffset, bits_len) ;
+
+ return slot_infop ;
+}
+
+//*********************************************************************************************
+//END of implementation of class LLTextureAtlasManager
+//*********************************************************************************************
diff --git a/indra/newview/lltextureatlasmanager.h b/indra/newview/lltextureatlasmanager.h
new file mode 100644
index 0000000000..4dba0759f9
--- /dev/null
+++ b/indra/newview/lltextureatlasmanager.h
@@ -0,0 +1,111 @@
+/**
+ * @file lltextureatlasmanager.h
+ * @brief LLTextureAtlasManager base class.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#ifndef LL_TEXTUREATLASMANAGER_H
+#define LL_TEXTUREATLASMANAGER_H
+
+#include "llmemory.h"
+
+class LLSpatialGroup ;
+class LLViewerTexture ;
+
+//just use it as a structure.
+class LLTextureAtlasSlot : public LLRefCount
+{
+public:
+ LLTextureAtlasSlot(LLTextureAtlas* atlasp, LLSpatialGroup* groupp, S16 col, S16 row, F32 xoffset, F32 yoffset, S8 slot_width) ;
+
+protected:
+ virtual ~LLTextureAtlasSlot();
+
+public:
+
+ //
+ //do not allow to change those values
+ //
+ //void setAtlas(LLTextureAtlas* atlasp) ;
+ //void setSlotPos(S16 col, S16 row) ;
+ //void setSlotWidth(S8 width) ;
+ //void setTexCoordOffset(F32 xoffser, F32 yoffset) ;
+ //
+
+ void setSpatialGroup(LLSpatialGroup* groupp) ;
+ void setTexCoordScale(F32 xscale, F32 yscale) ;
+ void setValid() {mValid = TRUE ;}
+
+ LLTextureAtlas* getAtlas()const {return mAtlasp;}
+ LLSpatialGroup* getSpatialGroup() const {return mGroupp ;}
+ S16 getSlotCol()const {return mCol;}
+ S16 getSlotRow()const {return mRow;}
+ S8 getSlotWidth()const{return mReservedSlotWidth;}
+ BOOL isValid()const { return mValid;}
+ const LLVector2* getTexCoordOffset()const {return &mTexCoordOffset;}
+ const LLVector2* getTexCoordScale() const {return &mTexCoordScale;}
+
+ void setUpdatedTime(U32 t) {mUpdatedTime = t;}
+ U32 getUpdatedTime()const {return mUpdatedTime;}
+
+private:
+ LLTextureAtlas* mAtlasp;
+ S16 mCol ;//col of the slot
+ S16 mRow ;//row of the slot
+ S8 mReservedSlotWidth ; //slot is a square with each edge length a power-of-two number
+ LLSpatialGroup* mGroupp ;
+ BOOL mValid ;
+
+ LLVector2 mTexCoordOffset ;
+ LLVector2 mTexCoordScale ;
+
+ U32 mUpdatedTime ;
+} ;
+
+class LLTextureAtlasManager : public LLSingleton<LLTextureAtlasManager>
+{
+private:
+ typedef std::list<LLPointer<LLTextureAtlas> > ll_texture_atlas_list_t ;
+
+public:
+ LLTextureAtlasManager();
+ ~LLTextureAtlasManager();
+
+ LLPointer<LLTextureAtlasSlot> reserveAtlasSlot(S32 sub_texture_size, S8 ncomponents,
+ LLSpatialGroup* groupp, LLViewerTexture* imagep) ;
+ void releaseAtlas(LLTextureAtlas* atlasp);
+
+ BOOL canAddToAtlas(S32 w, S32 h, S8 ncomponents, LLGLenum target) ;
+
+private:
+ std::vector<ll_texture_atlas_list_t> mAtlasMap ;
+ std::vector<ll_texture_atlas_list_t> mEmptyAtlasMap ; //delay some empty atlases deletion to avoid possible creation of new atlas immediately.
+};
+
+#endif
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index a3966ed666..051c189013 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -43,11 +43,17 @@
// Included to allow LLTextureCache::purgeTextures() to pause watchdog timeout
#include "llappviewer.h"
-#define USE_LFS_READ 0
-#define USE_LFS_WRITE 0
-
-// Note: first 4 bytes store file size, rest is j2c data
-const S32 TEXTURE_CACHE_ENTRY_SIZE = FIRST_PACKET_SIZE; //1024;
+// Cache organization:
+// cache/texture.entries
+// Unordered array of Entry structs
+// cache/texture.cache
+// First TEXTURE_CACHE_ENTRY_SIZE bytes of each texture in texture.entries in same order
+// cache/textures/[0-F]/UUID.texture
+// Actual texture body files
+
+const S32 TEXTURE_CACHE_ENTRY_SIZE = 1024;
+const F32 TEXTURE_CACHE_PURGE_AMOUNT = .20f; // % amount to reduce the cache by when it exceeds its limit
+const F32 TEXTURE_CACHE_LRU_SIZE = .10f; // % amount for LRU list (low overhead to regenerate)
class LLTextureCacheWorker : public LLWorkerClass
{
@@ -309,94 +315,75 @@ void LLTextureCacheWorker::startWork(S32 param)
{
}
+// This is where a texture is read from the cache system (header and body)
+// Current assumption are:
+// - the whole data are in a raw form, will be stored at mReadData
+// - the size of this raw data is mDataSize and can be smaller than TEXTURE_CACHE_ENTRY_SIZE (the size of a record in the header cache)
+// - the code supports offset reading but this is actually never exercised in the viewer
bool LLTextureCacheRemoteWorker::doRead()
{
+ bool done = false;
+ S32 idx = -1;
+
S32 local_size = 0;
std::string local_filename;
+ // First state / stage : find out if the file is local
if (mState == INIT)
{
std::string filename = mCache->getLocalFileName(mID);
- local_filename = filename + ".j2c";
- local_size = LLAPRFile::size(local_filename, mCache->getLocalAPRFilePool());
- if (local_size == 0)
+ // Is it a JPEG2000 file?
{
- local_filename = filename + ".tga";
+ local_filename = filename + ".j2c";
local_size = LLAPRFile::size(local_filename, mCache->getLocalAPRFilePool());
if (local_size > 0)
{
- mImageFormat = IMG_CODEC_TGA;
- mDataSize = local_size; // Only a complete .tga file is valid
+ mImageFormat = IMG_CODEC_J2C;
}
}
- if (local_size > 0)
- {
- mState = LOCAL;
- }
- else
- {
- mState = CACHE;
- }
- }
-
- if (mState == LOCAL)
- {
-#if USE_LFS_READ
- if (mFileHandle == LLLFSThread::nullHandle())
+ // If not, is it a jpeg file?
+ if (local_size == 0)
{
- mImageLocal = TRUE;
- mImageSize = local_size;
- if (!mDataSize || mDataSize + mOffset > local_size)
- {
- mDataSize = local_size - mOffset;
- }
- if (mDataSize <= 0)
+ local_filename = filename + ".jpg";
+ local_size = LLAPRFile::size(local_filename, mCache->getLocalAPRFilePool());
+ if (local_size > 0)
{
- // no more data to read
- mDataSize = 0;
- return true;
+ mImageFormat = IMG_CODEC_JPEG;
+ mDataSize = local_size; // Only a complete .jpg file is valid
}
- mReadData = new U8[mDataSize];
- mBytesRead = -1;
- mBytesToRead = mDataSize;
- setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
- mFileHandle = LLLFSThread::sLocal->read(local_filename, mReadData, mOffset, mDataSize,
- new ReadResponder(mCache, mRequestHandle));
- return false;
}
- else
+ // Hmm... What about a targa file? (used for UI texture mostly)
+ if (local_size == 0)
{
- if (mBytesRead >= 0)
- {
- if (mBytesRead != mBytesToRead)
- {
-// llwarns << "Error reading file from local cache: " << local_filename
-// << " Bytes: " << mDataSize << " Offset: " << mOffset
-// << " / " << mDataSize << llendl;
- mDataSize = 0; // failed
- delete[] mReadData;
- mReadData = NULL;
- }
- return true;
- }
- else
+ local_filename = filename + ".tga";
+ local_size = LLAPRFile::size(local_filename, mCache->getLocalAPRFilePool());
+ if (local_size > 0)
{
- return false;
+ mImageFormat = IMG_CODEC_TGA;
+ mDataSize = local_size; // Only a complete .tga file is valid
}
}
-#else
+ // Determine the next stage: if we found a file, then LOCAL else CACHE
+ mState = (local_size > 0 ? LOCAL : CACHE);
+ }
+
+ // Second state / stage : if the file is local, load it and leave
+ if (!done && (mState == LOCAL))
+ {
+ llassert(local_size != 0); // we're assuming there is a non empty local file here...
if (!mDataSize || mDataSize > local_size)
{
mDataSize = local_size;
}
+ // Allocate read buffer
mReadData = new U8[mDataSize];
S32 bytes_read = LLAPRFile::readEx(local_filename,
mReadData, mOffset, mDataSize, mCache->getLocalAPRFilePool());
if (bytes_read != mDataSize)
{
-// llwarns << "Error reading file from local cache: " << local_filename
-// << " Bytes: " << mDataSize << " Offset: " << mOffset
-// << " / " << mDataSize << llendl;
+ llwarns << "Error reading file from local cache: " << local_filename
+ << " Bytes: " << mDataSize << " Offset: " << mOffset
+ << " / " << mDataSize << llendl;
mDataSize = 0;
delete[] mReadData;
mReadData = NULL;
@@ -406,405 +393,275 @@ bool LLTextureCacheRemoteWorker::doRead()
mImageSize = local_size;
mImageLocal = TRUE;
}
- return true;
-#endif
+ // We're done...
+ done = true;
}
- S32 idx = -1;
-
- if (mState == CACHE)
+ // Second state / stage : identify the cache or not...
+ if (!done && (mState == CACHE))
{
- llassert_always(mImageSize == 0);
- idx = mCache->getHeaderCacheEntry(mID, false, &mImageSize);
- if (idx >= 0 && mImageSize > mOffset)
+ idx = mCache->getHeaderCacheEntry(mID, mImageSize);
+ if (idx < 0)
{
- llassert_always(mImageSize > 0);
- if (!mDataSize || mDataSize > mImageSize)
- {
- mDataSize = mImageSize;
- }
- mState = mOffset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY;
+ // The texture is *not* cached. We're done here...
+ mDataSize = 0; // no data
+ done = true;
}
else
{
- mDataSize = 0; // no data
- return true;
+ // If the read offset is bigger than the header cache, we read directly from the body
+ // Note that currently, we *never* read with offset from the cache, so the result is *always* HEADER
+ mState = mOffset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY;
}
}
- if (mState == HEADER)
+ // Third state / stage : read data from the header cache (texture.entries) file
+ if (!done && (mState == HEADER))
{
-#if USE_LFS_READ
- if (mFileHandle == LLLFSThread::nullHandle())
- {
- llassert_always(idx >= 0);
- llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE);
- S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset;
- S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
- llassert_always(mReadData == NULL);
- mReadData = new U8[size];
- mBytesRead = -1;
- mBytesToRead = size;
- setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
- mFileHandle = LLLFSThread::sLocal->read(mCache->mHeaderDataFileName,
- mReadData, offset, mBytesToRead,
- new ReadResponder(mCache, mRequestHandle));
- return false;
- }
- else
- {
- if (mBytesRead >= 0)
- {
- if (mBytesRead != mBytesToRead)
- {
-// llwarns << "LLTextureCacheWorker: " << mID
-// << " incorrect number of bytes read from header: " << mBytesRead
-// << " != " << mBytesToRead << llendl;
- mDataSize = -1; // failed
- return true;
- }
- if (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE)
- {
- return true; // done
- }
- else
- {
- mFileHandle = LLLFSThread::nullHandle();
- mState = BODY;
- }
- }
- else
- {
- return false;
- }
- }
-#else
- llassert_always(idx >= 0);
+ llassert_always(idx >= 0); // we need an entry here or reading the header makes no sense
llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE);
S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset;
+ // Compute the size we need to read (in bytes)
S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
+ size = llmin(size, mDataSize);
+ // Allocate the read buffer
mReadData = new U8[size];
S32 bytes_read = LLAPRFile::readEx(mCache->mHeaderDataFileName,
mReadData, offset, size, mCache->getLocalAPRFilePool());
if (bytes_read != size)
{
-// llwarns << "LLTextureCacheWorker: " << mID
-// << " incorrect number of bytes read from header: " << bytes_read
-// << " / " << size << llendl;
+ llwarns << "LLTextureCacheWorker: " << mID
+ << " incorrect number of bytes read from header: " << bytes_read
+ << " / " << size << llendl;
+ delete[] mReadData;
+ mReadData = NULL;
mDataSize = -1; // failed
- return true;
+ done = true;
}
- if (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE)
+ // If we already read all we expected, we're actually done
+ if (mDataSize <= bytes_read)
{
- return true; // done
+ done = true;
}
else
{
mState = BODY;
}
-#endif
}
- if (mState == BODY)
+ // Fourth state / stage : read the rest of the data from the UUID based cached file
+ if (!done && (mState == BODY))
{
-#if USE_LFS_READ
- if (mFileHandle == LLLFSThread::nullHandle())
- {
- std::string filename = mCache->getTextureFileName(mID);
- S32 filesize = LLAPRFile::size(filename, mCache->getLocalAPRFilePool());
- if (filesize > mOffset)
- {
- S32 datasize = TEXTURE_CACHE_ENTRY_SIZE + filesize;
- mDataSize = llmin(datasize, mDataSize);
- S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
- data_offset = llmax(data_offset, 0);
- S32 file_size = mDataSize - data_offset;
- S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE;
- file_offset = llmax(file_offset, 0);
-
- llassert_always(mDataSize > 0);
- U8* data = new U8[mDataSize];
- if (data_offset > 0)
- {
- llassert_always(mReadData);
- llassert_always(data_offset <= mDataSize);
- memcpy(data, mReadData, data_offset);
- delete[] mReadData;
- mReadData = NULL;
- }
- llassert_always(mReadData == NULL);
- mReadData = data;
-
- mBytesRead = -1;
- mBytesToRead = file_size;
- setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
- llassert_always(data_offset + mBytesToRead <= mDataSize);
- mFileHandle = LLLFSThread::sLocal->read(filename,
- mReadData + data_offset, file_offset, mBytesToRead,
- new ReadResponder(mCache, mRequestHandle));
- return false;
- }
- else
- {
- mDataSize = TEXTURE_CACHE_ENTRY_SIZE;
- return true; // done
- }
- }
- else
- {
- if (mBytesRead >= 0)
- {
- if (mBytesRead != mBytesToRead)
- {
-// llwarns << "LLTextureCacheWorker: " << mID
-// << " incorrect number of bytes read from body: " << mBytesRead
-// << " != " << mBytesToRead << llendl;
- mDataSize = -1; // failed
- }
- return true;
- }
- else
- {
- return false;
- }
- }
-#else
std::string filename = mCache->getTextureFileName(mID);
S32 filesize = LLAPRFile::size(filename, mCache->getLocalAPRFilePool());
- S32 bytes_read = 0;
- if (filesize > mOffset)
+
+ if (filesize && (filesize + TEXTURE_CACHE_ENTRY_SIZE) > mOffset)
{
- S32 datasize = TEXTURE_CACHE_ENTRY_SIZE + filesize;
- mDataSize = llmin(datasize, mDataSize);
- S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
- data_offset = llmax(data_offset, 0);
- S32 file_size = mDataSize - data_offset;
- S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE;
- file_offset = llmax(file_offset, 0);
+ S32 max_datasize = TEXTURE_CACHE_ENTRY_SIZE + filesize - mOffset;
+ mDataSize = llmin(max_datasize, mDataSize);
+
+ S32 data_offset, file_size, file_offset;
+ // Reserve the whole data buffer first
U8* data = new U8[mDataSize];
- if (data_offset > 0)
+
+ // Set the data file pointers taking the read offset into account. 2 cases:
+ if (mOffset < TEXTURE_CACHE_ENTRY_SIZE)
{
+ // Offset within the header record. That means we read something from the header cache.
+ // Note: most common case is (mOffset = 0), so this is the "normal" code path.
+ data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset; // i.e. TEXTURE_CACHE_ENTRY_SIZE if mOffset nul (common case)
+ file_offset = 0;
+ file_size = mDataSize - data_offset;
+ // Copy the raw data we've been holding from the header cache into the new sized buffer
llassert_always(mReadData);
memcpy(data, mReadData, data_offset);
delete[] mReadData;
+ mReadData = NULL;
+ }
+ else
+ {
+ // Offset bigger than the header record. That means we haven't read anything yet.
+ data_offset = 0;
+ file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE;
+ file_size = mDataSize;
+ // No data from header cache to copy in that case, we skipped it all
}
+
+ // Now use that buffer as the object read buffer
+ llassert_always(mReadData == NULL);
mReadData = data;
- bytes_read = LLAPRFile::readEx(filename,
+
+ // Read the data at last
+ S32 bytes_read = LLAPRFile::readEx(filename,
mReadData + data_offset,
file_offset, file_size,
mCache->getLocalAPRFilePool());
if (bytes_read != file_size)
{
-// llwarns << "LLTextureCacheWorker: " << mID
-// << " incorrect number of bytes read from body: " << bytes_read
-// << " / " << file_size << llendl;
+ llwarns << "LLTextureCacheWorker: " << mID
+ << " incorrect number of bytes read from body: " << bytes_read
+ << " / " << file_size << llendl;
+ delete[] mReadData;
+ mReadData = NULL;
mDataSize = -1; // failed
- return true;
+ done = true;
}
}
else
{
- mDataSize = TEXTURE_CACHE_ENTRY_SIZE;
- }
-
- return true;
-#endif
+ // No body, we're done.
+ mDataSize = llmax(TEXTURE_CACHE_ENTRY_SIZE - mOffset, 0);
+ lldebugs << "No body file for: " << filename << llendl;
+ }
+ // Nothing else to do at that point...
+ done = true;
}
-
- return false;
+
+ // Clean up and exit
+ return done;
}
+// This is where *everything* about a texture is written down in the cache system (entry map, header and body)
+// Current assumption are:
+// - the whole data are in a raw form, starting at mWriteData
+// - the size of this raw data is mDataSize and can be smaller than TEXTURE_CACHE_ENTRY_SIZE (the size of a record in the header cache)
+// - the code *does not* support offset writing so there are no difference between buffer addresses and start of data
bool LLTextureCacheRemoteWorker::doWrite()
{
+ bool done = false;
S32 idx = -1;
- // No LOCAL state for write()
-
+ // First state / stage : check that what we're trying to cache is in an OK shape
if (mState == INIT)
{
+ llassert_always(mOffset == 0); // We currently do not support write offsets
+ llassert_always(mDataSize > 0); // Things will go badly wrong if mDataSize is nul or negative...
+ mState = CACHE;
+ }
+
+ // No LOCAL state for write(): because it doesn't make much sense to cache a local file...
+
+ // Second state / stage : set an entry in the headers entry (texture.entries) file
+ if (!done && (mState == CACHE))
+ {
+ bool alreadyCached = false;
S32 cur_imagesize = 0;
- S32 offset = mOffset;
- idx = mCache->getHeaderCacheEntry(mID, false, &cur_imagesize);
- if (idx >= 0 && cur_imagesize > 0)
+ // Checks if this image is already in the entry list
+ idx = mCache->getHeaderCacheEntry(mID, cur_imagesize);
+ if (idx >= 0 && (cur_imagesize >= 0))
{
- offset = TEXTURE_CACHE_ENTRY_SIZE; // don't re-write header
+ alreadyCached = true; // already there and non empty
}
- idx = mCache->getHeaderCacheEntry(mID, true, &mImageSize); // touch entry
- if (idx >= 0)
+ idx = mCache->setHeaderCacheEntry(mID, mImageSize); // create or touch the entry
+ if (idx < 0)
{
- if(cur_imagesize > 0 && mImageSize != cur_imagesize)
- {
-// llwarns << "Header cache entry size: " << cur_imagesize << " != mImageSize: " << mImageSize << llendl;
- offset = 0; // re-write header
- }
- mState = offset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY;
+ llwarns << "LLTextureCacheWorker: " << mID
+ << " Unable to create header entry for writing!" << llendl;
+ mDataSize = -1; // failed
+ done = true;
}
else
{
- mDataSize = -1; // failed
- return true;
+ if (cur_imagesize > 0 && (mImageSize != cur_imagesize))
+ {
+ alreadyCached = false; // re-write the header if the size changed in all cases
+ }
+ if (alreadyCached && (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE))
+ {
+ // Small texture already cached case: we're done with writing
+ done = true;
+ }
+ else
+ {
+ // If the texture has already been cached, we don't resave the header and go directly to the body part
+ mState = alreadyCached ? BODY : HEADER;
+ }
}
}
-
- if (mState == HEADER)
+
+ // Third stage / state : write the header record in the header file (texture.cache)
+ if (!done && (mState == HEADER))
{
-#if USE_LFS_WRITE
- if (mFileHandle == LLLFSThread::nullHandle())
+ llassert_always(idx >= 0); // we need an entry here or storing the header makes no sense
+ S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE; // skip to the correct spot in the header file
+ S32 size = TEXTURE_CACHE_ENTRY_SIZE; // record size is fixed for the header
+ S32 bytes_written;
+
+ if (mDataSize < TEXTURE_CACHE_ENTRY_SIZE)
{
- llassert_always(idx >= 0);
- llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE);
- S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset;
- S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
- mBytesRead = -1;
- mBytesToRead = size;
- setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
- mFileHandle = LLLFSThread::sLocal->write(mCache->mHeaderDataFileName,
- mWriteData, offset, mBytesToRead,
- new WriteResponder(mCache, mRequestHandle));
- return false;
+ // We need to write a full record in the header cache so, if the amount of data is smaller
+ // than a record, we need to transfer the data to a buffer padded with 0 and write that
+ U8* padBuffer = new U8[TEXTURE_CACHE_ENTRY_SIZE];
+ memset(padBuffer, 0, TEXTURE_CACHE_ENTRY_SIZE); // Init with zeros
+ memcpy(padBuffer, mWriteData, mDataSize); // Copy the write buffer
+ bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, padBuffer, offset, size, mCache->getLocalAPRFilePool());
+ delete [] padBuffer;
}
else
{
- if (mBytesRead >= 0)
- {
- if (mBytesRead != mBytesToRead)
- {
-// llwarns << "LLTextureCacheWorker: " << mID
-// << " incorrect number of bytes written to header: " << mBytesRead
-// << " != " << mBytesToRead << llendl;
- mDataSize = -1; // failed
- return true;
- }
- if (mDataSize <= mBytesToRead)
- {
- return true; // done
- }
- else
- {
- mFileHandle = LLLFSThread::nullHandle();
- mState = BODY;
- }
- }
- else
- {
- return false;
- }
+ // Write the header record (== first TEXTURE_CACHE_ENTRY_SIZE bytes of the raw file) in the header file
+ bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, mWriteData, offset, size, mCache->getLocalAPRFilePool());
}
-#else
- llassert_always(idx >= 0);
- llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE);
- S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset;
- S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
- S32 bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, mWriteData, offset, size, mCache->getLocalAPRFilePool());
if (bytes_written <= 0)
{
-// llwarns << "LLTextureCacheWorker: missing entry: " << mID << llendl;
+ llwarns << "LLTextureCacheWorker: " << mID
+ << " Unable to write header entry!" << llendl;
mDataSize = -1; // failed
- return true;
+ done = true;
}
- if (mDataSize <= size)
+ // If we wrote everything (may be more with padding) in the header cache,
+ // we're done so we don't have a body to store
+ if (mDataSize <= bytes_written)
{
- return true; // done
+ done = true;
}
else
{
mState = BODY;
}
-#endif
}
- if (mState == BODY)
+ // Fourth stage / state : write the body file, i.e. the rest of the texture in a "UUID" file name
+ if (!done && (mState == BODY))
{
-#if USE_LFS_WRITE
- if (mFileHandle == LLLFSThread::nullHandle())
- {
- S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
- data_offset = llmax(data_offset, 0);
- S32 file_size = mDataSize - data_offset;
- S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE;
- file_offset = llmax(file_offset, 0);
- if (file_size > 0 && mCache->appendToTextureEntryList(mID, file_size))
- {
- std::string filename = mCache->getTextureFileName(mID);
- mBytesRead = -1;
- mBytesToRead = file_size;
- setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
- mFileHandle = LLLFSThread::sLocal->write(filename,
- mWriteData + data_offset, file_offset, mBytesToRead,
- new WriteResponder(mCache, mRequestHandle));
- return false;
- }
- else
- {
- mDataSize = 0; // no data written
- return true; // done
- }
- }
- else
- {
- if (mBytesRead >= 0)
- {
- if (mBytesRead != mBytesToRead)
- {
-// llwarns << "LLTextureCacheWorker: " << mID
-// << " incorrect number of bytes written to body: " << mBytesRead
-// << " != " << mBytesToRead << llendl;
- mDataSize = -1; // failed
- }
- return true;
- }
- else
- {
- return false;
- }
- }
-#else
- S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
- data_offset = llmax(data_offset, 0);
- S32 file_size = mDataSize - data_offset;
- S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE;
- file_offset = llmax(file_offset, 0);
- S32 bytes_written = 0;
- if (file_size > 0 && mCache->appendToTextureEntryList(mID, file_size))
+ llassert(mDataSize > TEXTURE_CACHE_ENTRY_SIZE); // wouldn't make sense to be here otherwise...
+ S32 file_size = mDataSize - TEXTURE_CACHE_ENTRY_SIZE;
+ if ((file_size > 0) && mCache->updateTextureEntryList(mID, file_size))
{
- std::string filename = mCache->getTextureFileName(mID);
-
- bytes_written = LLAPRFile::writeEx(filename,
- mWriteData + data_offset,
- file_offset, file_size,
- mCache->getLocalAPRFilePool());
+ // build the cache file name from the UUID
+ std::string filename = mCache->getTextureFileName(mID);
+// llinfos << "Writing Body: " << filename << " Bytes: " << file_offset+file_size << llendl;
+ S32 bytes_written = LLAPRFile::writeEx( filename,
+ mWriteData + TEXTURE_CACHE_ENTRY_SIZE,
+ 0, file_size,
+ mCache->getLocalAPRFilePool());
if (bytes_written <= 0)
{
+ llwarns << "LLTextureCacheWorker: " << mID
+ << " incorrect number of bytes written to body: " << bytes_written
+ << " / " << file_size << llendl;
mDataSize = -1; // failed
+ done = true;
}
}
else
{
mDataSize = 0; // no data written
}
-
- return true;
-#endif
+ // Nothing else to do at that point...
+ done = true;
}
-
- return false;
+
+ // Clean up and exit
+ return done;
}
//virtual
bool LLTextureCacheWorker::doWork(S32 param)
{
-// *TODO reenable disabled apr_pool usage disabled due to maint-render-9 merge breakage -brad
- //allocate a new local apr_pool
-// LLAPRPool pool ;
-
- //save the current mFileAPRPool to avoid breaking anything.
-// apr_pool_t* old_pool = mCache->getFileAPRPool() ;
- //make mFileAPRPool to point to the local one
-// mCache->setFileAPRPool(pool.getAPRPool()) ;
-
bool res = false;
if (param == 0) // read
{
@@ -818,10 +675,6 @@ bool LLTextureCacheWorker::doWork(S32 param)
{
llassert_always(0);
}
-
- //set mFileAPRPool back, the local one will be released automatically.
-// mCache->setFileAPRPool(old_pool) ;
-
return res;
}
@@ -887,6 +740,7 @@ LLTextureCache::LLTextureCache(bool threaded)
mWorkersMutex(NULL),
mHeaderMutex(NULL),
mListMutex(NULL),
+ mHeaderAPRFile(NULL),
mReadOnly(FALSE),
mTexturesSizeTotal(0),
mDoPurge(FALSE)
@@ -926,6 +780,9 @@ S32 LLTextureCache::update(U32 max_time_ms)
}
}
+ unlockWorkers();
+
+ // call 'completed' with workers list unlocked (may call readComplete() or writeComplete()
for (responder_list_t::iterator iter1 = completed_list.begin();
iter1 != completed_list.end(); ++iter1)
{
@@ -934,8 +791,6 @@ S32 LLTextureCache::update(U32 max_time_ms)
responder->completed(success);
}
- unlockWorkers();
-
return res;
}
@@ -946,7 +801,7 @@ std::string LLTextureCache::getLocalFileName(const LLUUID& id)
// Does not include extension
std::string idstr = id.asString();
// TODO: should we be storing cached textures in skin directory?
- std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, "default", "textures", idstr);
+ std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_LOCAL_ASSETS, idstr);
return filename;
}
@@ -954,33 +809,48 @@ std::string LLTextureCache::getTextureFileName(const LLUUID& id)
{
std::string idstr = id.asString();
std::string delem = gDirUtilp->getDirDelimiter();
- std::string filename = mTexturesDirName + delem + idstr[0] + delem + idstr;
+ std::string filename = mTexturesDirName + delem + idstr[0] + delem + idstr + ".texture";
return filename;
}
-bool LLTextureCache::appendToTextureEntryList(const LLUUID& id, S32 bodysize)
+bool LLTextureCache::updateTextureEntryList(const LLUUID& id, S32 bodysize)
{
bool res = false;
bool purge = false;
- // Append UUID to end of texture entries
{
LLMutexLock lock(&mHeaderMutex);
- size_map_t::iterator iter = mTexturesSizeMap.find(id);
- if (iter == mTexturesSizeMap.end() || iter->second < bodysize)
+ size_map_t::iterator iter1 = mTexturesSizeMap.find(id);
+ if (iter1 == mTexturesSizeMap.end() || iter1->second < bodysize)
{
llassert_always(bodysize > 0);
- Entry* entry = new Entry(id, bodysize, time(NULL));
- LLAPRFile::writeEx(mTexturesDirEntriesFileName,
- (U8*)entry, -1, 1*sizeof(Entry),
- getLocalAPRFilePool());
- delete entry;
- if (iter != mTexturesSizeMap.end())
+ S32 oldbodysize = 0;
+ if (iter1 != mTexturesSizeMap.end())
+ {
+ oldbodysize = iter1->second;
+ }
+
+ Entry entry;
+ S32 idx = openAndReadEntry(id, entry, false);
+ if (idx < 0)
{
- mTexturesSizeTotal -= iter->second;
+ llwarns << "Failed to open entry: " << id << llendl;
+ removeHeaderCacheEntry(id);
+ LLAPRFile::remove(getTextureFileName(id), getLocalAPRFilePool());
+ return false;
+ }
+ else if (oldbodysize != entry.mBodySize)
+ {
+ // TODO: change to llwarns
+ llerrs << "Entry mismatch in mTextureSizeMap / mHeaderIDMap"
+ << " idx=" << idx << " oldsize=" << oldbodysize << " entrysize=" << entry.mBodySize << llendl;
}
+ entry.mBodySize = bodysize;
+ writeEntryAndClose(idx, entry);
+
+ mTexturesSizeTotal -= oldbodysize;
mTexturesSizeTotal += bodysize;
- mTexturesSizeMap[id] = bodysize;
+
if (mTexturesSizeTotal > sCacheMaxTexturesSize)
{
purge = true;
@@ -995,11 +865,59 @@ bool LLTextureCache::appendToTextureEntryList(const LLUUID& id, S32 bodysize)
return res;
}
+//debug
+BOOL LLTextureCache::isInCache(const LLUUID& id)
+{
+ LLMutexLock lock(&mHeaderMutex);
+ id_map_t::const_iterator iter = mHeaderIDMap.find(id);
+
+ return (iter != mHeaderIDMap.end()) ;
+}
+
+//debug
+BOOL LLTextureCache::isInLocal(const LLUUID& id)
+{
+ S32 local_size = 0;
+ std::string local_filename;
+
+ std::string filename = getLocalFileName(id);
+ // Is it a JPEG2000 file?
+ {
+ local_filename = filename + ".j2c";
+ local_size = LLAPRFile::size(local_filename, getLocalAPRFilePool());
+ if (local_size > 0)
+ {
+ return TRUE ;
+ }
+ }
+
+ // If not, is it a jpeg file?
+ {
+ local_filename = filename + ".jpg";
+ local_size = LLAPRFile::size(local_filename, getLocalAPRFilePool());
+ if (local_size > 0)
+ {
+ return TRUE ;
+ }
+ }
+
+ // Hmm... What about a targa file? (used for UI texture mostly)
+ {
+ local_filename = filename + ".tga";
+ local_size = LLAPRFile::size(local_filename, getLocalAPRFilePool());
+ if (local_size > 0)
+ {
+ return TRUE ;
+ }
+ }
+
+ return FALSE ;
+}
//////////////////////////////////////////////////////////////////////////////
//static
const S32 MAX_REASONABLE_FILE_SIZE = 512*1024*1024; // 512 MB
-F32 LLTextureCache::sHeaderCacheVersion = 1.0f;
+F32 LLTextureCache::sHeaderCacheVersion = 1.4f;
U32 LLTextureCache::sCacheMaxEntries = MAX_REASONABLE_FILE_SIZE / TEXTURE_CACHE_ENTRY_SIZE;
S64 LLTextureCache::sCacheMaxTexturesSize = 0; // no limit
const char* entries_filename = "texture.entries";
@@ -1012,15 +930,16 @@ void LLTextureCache::setDirNames(ELLPath location)
mHeaderEntriesFileName = gDirUtilp->getExpandedFilename(location, entries_filename);
mHeaderDataFileName = gDirUtilp->getExpandedFilename(location, cache_filename);
mTexturesDirName = gDirUtilp->getExpandedFilename(location, textures_dirname);
- mTexturesDirEntriesFileName = mTexturesDirName + delem + entries_filename;
}
void LLTextureCache::purgeCache(ELLPath location)
{
+ LLMutexLock lock(&mHeaderMutex);
+
if (!mReadOnly)
{
setDirNames(location);
-
+ llassert_always(mHeaderAPRFile == NULL);
LLAPRFile::remove(mHeaderEntriesFileName, getLocalAPRFilePool());
LLAPRFile::remove(mHeaderDataFileName, getLocalAPRFilePool());
}
@@ -1063,85 +982,335 @@ S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL read_only)
return max_size; // unused cache space
}
-struct lru_data
+//----------------------------------------------------------------------------
+// mHeaderMutex must be locked for the following functions!
+
+LLAPRFile* LLTextureCache::openHeaderEntriesFile(bool readonly, S32 offset)
+{
+ llassert_always(mHeaderAPRFile == NULL);
+ apr_int32_t flags = readonly ? APR_READ|APR_BINARY : APR_READ|APR_WRITE|APR_BINARY;
+ mHeaderAPRFile = new LLAPRFile(mHeaderEntriesFileName, flags, getLocalAPRFilePool());
+ mHeaderAPRFile->seek(APR_SET, offset);
+ return mHeaderAPRFile;
+}
+
+void LLTextureCache::closeHeaderEntriesFile()
+{
+ llassert_always(mHeaderAPRFile != NULL);
+ delete mHeaderAPRFile;
+ mHeaderAPRFile = NULL;
+}
+
+void LLTextureCache::readEntriesHeader()
+{
+ // mHeaderEntriesInfo initializes to default values so safe not to read it
+ llassert_always(mHeaderAPRFile == NULL);
+ if (LLAPRFile::isExist(mHeaderEntriesFileName, getLocalAPRFilePool()))
+ {
+ LLAPRFile::readEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo),
+ getLocalAPRFilePool());
+ }
+}
+
+void LLTextureCache::writeEntriesHeader()
+{
+ llassert_always(mHeaderAPRFile == NULL);
+ if (!mReadOnly)
+ {
+ LLAPRFile::writeEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo),
+ getLocalAPRFilePool());
+ }
+}
+
+static S32 mHeaderEntriesMaxWriteIdx = 0;
+
+S32 LLTextureCache::openAndReadEntry(const LLUUID& id, Entry& entry, bool create)
{
- lru_data(U32 t, S32 i, const LLUUID& id) { time=t; index=i; uuid=id; }
- U32 time;
- S32 index;
- LLUUID uuid;
- struct Compare
- {
- // lhs < rhs
- typedef const lru_data* lru_data_ptr;
- bool operator()(const lru_data_ptr& a, const lru_data_ptr& b) const
+ S32 idx = -1;
+
+ id_map_t::iterator iter1 = mHeaderIDMap.find(id);
+ if (iter1 != mHeaderIDMap.end())
+ {
+ idx = iter1->second;
+ }
+
+ if (idx < 0)
+ {
+ if (create && !mReadOnly)
{
- if(a->time == b->time)
- return (a->index < b->index);
+ if (mHeaderEntriesInfo.mEntries < sCacheMaxEntries)
+ {
+ // Add an entry to the end of the list
+ idx = mHeaderEntriesInfo.mEntries++;
+
+ }
+ else if (!mFreeList.empty())
+ {
+ idx = *(mFreeList.begin());
+ mFreeList.erase(mFreeList.begin());
+ }
else
- return (a->time >= b->time);
+ {
+ // Look for a still valid entry in the LRU
+ for (std::set<LLUUID>::iterator iter2 = mLRU.begin(); iter2 != mLRU.end();)
+ {
+ std::set<LLUUID>::iterator curiter2 = iter2++;
+ LLUUID oldid = *curiter2;
+ // Erase entry from LRU regardless
+ mLRU.erase(curiter2);
+ // Look up entry and use it if it is valid
+ id_map_t::iterator iter3 = mHeaderIDMap.find(oldid);
+ if (iter3 != mHeaderIDMap.end() && iter3->second >= 0)
+ {
+ idx = iter3->second;
+ mHeaderIDMap.erase(oldid);
+ mTexturesSizeMap.erase(oldid);
+ break;
+ }
+ }
+ // if (idx < 0) at this point, we will rebuild the LRU
+ // and retry if called from setHeaderCacheEntry(),
+ // otherwise this shouldn't happen and will trigger an error
+ }
+ if (idx >= 0)
+ {
+ // Set the header index
+ mHeaderIDMap[id] = idx;
+ llassert_always(mTexturesSizeMap.erase(id) == 0);
+ // Initialize the entry (will get written later)
+ entry.init(id, time(NULL));
+ // Update Header
+ writeEntriesHeader();
+ // Write Entry
+ S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry);
+ LLAPRFile* aprfile = openHeaderEntriesFile(false, offset);
+ S32 bytes_written = aprfile->write((void*)&entry, (S32)sizeof(Entry));
+ llassert_always(bytes_written == sizeof(Entry));
+ mHeaderEntriesMaxWriteIdx = llmax(mHeaderEntriesMaxWriteIdx, idx);
+ closeHeaderEntriesFile();
+ }
}
- };
-};
+ }
+ else
+ {
+ // Remove this entry from the LRU if it exists
+ mLRU.erase(id);
+ // Read the entry
+ S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry);
+ LLAPRFile* aprfile = openHeaderEntriesFile(true, offset);
+ S32 bytes_read = aprfile->read((void*)&entry, (S32)sizeof(Entry));
+ llassert_always(bytes_read == sizeof(Entry));
+ llassert_always(entry.mImageSize == 0 || entry.mImageSize == -1 || entry.mImageSize > entry.mBodySize);
+ closeHeaderEntriesFile();
+ }
+ return idx;
+}
-// Called from either the main thread or the worker thread
-void LLTextureCache::readHeaderCache()
+void LLTextureCache::writeEntryAndClose(S32 idx, Entry& entry)
{
- LLMutexLock lock(&mHeaderMutex);
- mHeaderEntriesInfo.mVersion = 0.f;
- mHeaderEntriesInfo.mEntries = 0;
- if (LLAPRFile::isExist(mHeaderEntriesFileName, getLocalAPRFilePool()))
+ if (idx >= 0)
+ {
+ if (!mReadOnly)
+ {
+ entry.mTime = time(NULL);
+ llassert_always(entry.mImageSize == 0 || entry.mImageSize == -1 || entry.mImageSize > entry.mBodySize);
+ if (entry.mBodySize > 0)
+ {
+ mTexturesSizeMap[entry.mID] = entry.mBodySize;
+ }
+// llinfos << "Updating TE: " << idx << ": " << id << " Size: " << entry.mBodySize << " Time: " << entry.mTime << llendl;
+ S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry);
+ LLAPRFile* aprfile = openHeaderEntriesFile(false, offset);
+ S32 bytes_written = aprfile->write((void*)&entry, (S32)sizeof(Entry));
+ llassert_always(bytes_written == sizeof(Entry));
+ mHeaderEntriesMaxWriteIdx = llmax(mHeaderEntriesMaxWriteIdx, idx);
+ closeHeaderEntriesFile();
+ }
+ }
+}
+
+U32 LLTextureCache::openAndReadEntries(std::vector<Entry>& entries)
+{
+ U32 num_entries = mHeaderEntriesInfo.mEntries;
+
+ mHeaderIDMap.clear();
+ mTexturesSizeMap.clear();
+ mFreeList.clear();
+ mTexturesSizeTotal = 0;
+
+ LLAPRFile* aprfile = openHeaderEntriesFile(false, (S32)sizeof(EntriesInfo));
+ for (U32 idx=0; idx<num_entries; idx++)
+ {
+ Entry entry;
+ S32 bytes_read = aprfile->read((void*)(&entry), (S32)sizeof(Entry));
+ if (bytes_read < sizeof(Entry))
+ {
+ llwarns << "Corrupted header entries, failed at " << idx << " / " << num_entries << llendl;
+ closeHeaderEntriesFile();
+ purgeAllTextures(false);
+ return 0;
+ }
+ entries.push_back(entry);
+// llinfos << "ENTRY: " << entry.mTime << " TEX: " << entry.mID << " IDX: " << idx << " Size: " << entry.mImageSize << llendl;
+ if (entry.mImageSize < 0)
+ {
+ mFreeList.insert(idx);
+ }
+ else
+ {
+ mHeaderIDMap[entry.mID] = idx;
+ if (entry.mBodySize > 0)
+ {
+ mTexturesSizeMap[entry.mID] = entry.mBodySize;
+ mTexturesSizeTotal += entry.mBodySize;
+ }
+ llassert_always(entry.mImageSize == 0 || entry.mImageSize > entry.mBodySize);
+ }
+ }
+ closeHeaderEntriesFile();
+ return num_entries;
+}
+
+void LLTextureCache::writeEntriesAndClose(const std::vector<Entry>& entries)
+{
+ S32 num_entries = entries.size();
+ llassert_always(num_entries == mHeaderEntriesInfo.mEntries);
+
+ if (!mReadOnly)
{
- LLAPRFile::readEx(mHeaderEntriesFileName,
- (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo),
- getLocalAPRFilePool());
+ LLAPRFile* aprfile = openHeaderEntriesFile(false, (S32)sizeof(EntriesInfo));
+ for (S32 idx=0; idx<num_entries; idx++)
+ {
+ S32 bytes_written = aprfile->write((void*)(&entries[idx]), (S32)sizeof(Entry));
+ llassert_always(bytes_written == sizeof(Entry));
+ }
+ mHeaderEntriesMaxWriteIdx = llmax(mHeaderEntriesMaxWriteIdx, num_entries-1);
+ closeHeaderEntriesFile();
}
+}
+
+//----------------------------------------------------------------------------
+
+// Called from either the main thread or the worker thread
+void LLTextureCache::readHeaderCache()
+{
+ mHeaderMutex.lock();
+
+ mLRU.clear(); // always clear the LRU
+
+ readEntriesHeader();
+
if (mHeaderEntriesInfo.mVersion != sHeaderCacheVersion)
{
if (!mReadOnly)
{
- // Info with 0 entries
- mHeaderEntriesInfo.mVersion = sHeaderCacheVersion;
-
- LLAPRFile::writeEx(mHeaderEntriesFileName,
- (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo),
- getLocalAPRFilePool());
+ purgeAllTextures(false);
}
}
else
{
- S32 num_entries = mHeaderEntriesInfo.mEntries;
+ std::vector<Entry> entries;
+ U32 num_entries = openAndReadEntries(entries);
if (num_entries)
{
- Entry* entries = new Entry[num_entries];
+ U32 empty_entries = 0;
+ typedef std::pair<U32, S32> lru_data_t;
+ std::set<lru_data_t> lru;
+ std::set<LLUUID> purge_list;
+ for (U32 i=0; i<num_entries; i++)
+ {
+ Entry& entry = entries[i];
+ const LLUUID& id = entry.mID;
+ if (entry.mImageSize < 0)
+ {
+ // This will be in the Free List, don't put it in the LRU
+ ++empty_entries;
+ }
+ else
+ {
+ lru.insert(std::make_pair(entry.mTime, i));
+ if (entry.mBodySize > 0)
+ {
+ if (entry.mBodySize > entry.mImageSize)
+ {
+ // Shouldn't happen, failsafe only
+ llwarns << "Bad entry: " << i << ": " << id << ": BodySize: " << entry.mBodySize << llendl;
+ purge_list.insert(entry.mID);
+ entry.mImageSize = -1; // empty/available
+ }
+ }
+ }
+ }
+ if (num_entries > sCacheMaxEntries)
+ {
+ // Special case: cache size was reduced, need to remove entries
+ // Note: After we prune entries, we will call this again and create the LRU
+ U32 entries_to_purge = (num_entries-empty_entries) - sCacheMaxEntries;
+ llinfos << "Texture Cache Entries: " << num_entries << " Max: " << sCacheMaxEntries << " Empty: " << empty_entries << " Purging: " << entries_to_purge << llendl;
+ if (entries_to_purge > 0)
+ {
+ for (std::set<lru_data_t>::iterator iter = lru.begin(); iter != lru.end(); ++iter)
+ {
+ S32 idx = iter->second;
+ if (entries[idx].mImageSize >= 0)
+ {
+ purge_list.insert(entries[idx].mID);
+ entries[idx].mImageSize = -1;
+ if (purge_list.size() >= entries_to_purge)
+ break;
+ }
+ }
+ }
+ llassert_always(purge_list.size() >= entries_to_purge);
+ }
+ else
{
- LLAPRFile::readEx(mHeaderEntriesFileName,
- (U8*)entries, sizeof(EntriesInfo), num_entries*sizeof(Entry),
- getLocalAPRFilePool());
+ S32 lru_entries = (S32)((F32)sCacheMaxEntries * TEXTURE_CACHE_LRU_SIZE);
+ for (std::set<lru_data_t>::iterator iter = lru.begin(); iter != lru.end(); ++iter)
+ {
+ S32 idx = iter->second;
+ const LLUUID& id = entries[idx].mID;
+ mLRU.insert(id);
+// llinfos << "LRU: " << iter->first << " : " << iter->second << llendl;
+ if (--lru_entries <= 0)
+ break;
+ }
}
- typedef std::set<lru_data*, lru_data::Compare> lru_set_t;
- lru_set_t lru;
- for (S32 i=0; i<num_entries; i++)
+
+ if (purge_list.size() > 0)
{
- if (entries[i].mSize >= 0) // -1 indicates erased entry, skip
+ for (std::set<LLUUID>::iterator iter = purge_list.begin(); iter != purge_list.end(); ++iter)
{
- const LLUUID& id = entries[i].mID;
- lru.insert(new lru_data(entries[i].mTime, i, id));
- mHeaderIDMap[id] = i;
+ const LLUUID& id = *iter;
+ bool res = removeHeaderCacheEntry(id); // sets entry size on disk to -1
+ llassert_always(res);
+ LLAPRFile::remove(getTextureFileName(id), getLocalAPRFilePool());
}
+ // If we removed any entries, we need to rebuild the entries list,
+ // write the header, and call this again
+ std::vector<Entry> new_entries;
+ for (U32 i=0; i<num_entries; i++)
+ {
+ const Entry& entry = entries[i];
+ if (entry.mImageSize >=0)
+ {
+ new_entries.push_back(entry);
+ }
+ }
+ llassert_always(new_entries.size() <= sCacheMaxEntries);
+ mHeaderEntriesInfo.mEntries = new_entries.size();
+ writeEntriesAndClose(new_entries);
+ mHeaderMutex.unlock(); // unlock the mutex before calling again
+ readHeaderCache(); // repeat with new entries file
+ mHeaderMutex.lock();
}
- mLRU.clear();
- S32 lru_entries = sCacheMaxEntries / 10;
- for (lru_set_t::iterator iter = lru.begin(); iter != lru.end(); ++iter)
+ else
{
- lru_data* data = *iter;
- mLRU[data->index] = data->uuid;
- if (--lru_entries <= 0)
- break;
+ writeEntriesAndClose(entries);
}
- for_each(lru.begin(), lru.end(), DeletePointer());
- delete[] entries;
}
}
+ mHeaderMutex.unlock();
}
//////////////////////////////////////////////////////////////////////////////
@@ -1156,19 +1325,28 @@ void LLTextureCache::purgeAllTextures(bool purge_directories)
for (S32 i=0; i<16; i++)
{
std::string dirname = mTexturesDirName + delem + subdirs[i];
+ llinfos << "Deleting files in directory: " << dirname << llendl;
gDirUtilp->deleteFilesInDir(dirname,mask);
if (purge_directories)
{
LLFile::rmdir(dirname);
}
}
- LLAPRFile::remove(mTexturesDirEntriesFileName, getLocalAPRFilePool());
if (purge_directories)
{
LLFile::rmdir(mTexturesDirName);
}
}
+ mHeaderIDMap.clear();
mTexturesSizeMap.clear();
+ mTexturesSizeTotal = 0;
+ mFreeList.clear();
+ mTexturesSizeTotal = 0;
+
+ // Info with 0 entries
+ mHeaderEntriesInfo.mVersion = sHeaderCacheVersion;
+ mHeaderEntriesInfo.mEntries = 0;
+ writeEntriesHeader();
}
void LLTextureCache::purgeTextures(bool validate)
@@ -1178,55 +1356,44 @@ void LLTextureCache::purgeTextures(bool validate)
return;
}
- // *FIX:Mani - watchdog off.
- LLAppViewer::instance()->pauseMainloopTimeout();
-
- LLMutexLock lock(&mHeaderMutex);
-
- S32 filesize = LLAPRFile::size(mTexturesDirEntriesFileName, getLocalAPRFilePool());
- S32 num_entries = filesize / sizeof(Entry);
- if (num_entries * (S32)sizeof(Entry) != filesize)
+ if (!mThreaded)
{
- LL_WARNS("TextureCache") << "Bad cache file: " << mTexturesDirEntriesFileName << " Purging." << LL_ENDL;
- purgeAllTextures(false);
- return;
- }
- if (num_entries == 0)
- {
- return; // nothing to do
+ // *FIX:Mani - watchdog off.
+ LLAppViewer::instance()->pauseMainloopTimeout();
}
- Entry* entries = new Entry[num_entries];
- S32 bytes_read = LLAPRFile::readEx(mTexturesDirEntriesFileName,
- (U8*)entries, 0, num_entries*sizeof(Entry),
- getLocalAPRFilePool());
- if (bytes_read != filesize)
- {
- LL_WARNS("TextureCache") << "Bad cache file (2): " << mTexturesDirEntriesFileName << " Purging." << LL_ENDL;
- purgeAllTextures(false);
- return;
+ LLMutexLock lock(&mHeaderMutex);
+
+ llinfos << "TEXTURE CACHE: Purging." << llendl;
+
+ // Read the entries list
+ std::vector<Entry> entries;
+ U32 num_entries = openAndReadEntries(entries);
+ if (!num_entries)
+ {
+ writeEntriesAndClose(entries);
+ return; // nothing to purge
}
- LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Reading Entries..." << LL_ENDL;
-
- std::map<LLUUID, S32> entry_idx_map;
- S64 total_size = 0;
- for (S32 idx=0; idx<num_entries; idx++)
- {
- const LLUUID& id = entries[idx].mID;
- LL_DEBUGS("TextureCache") << "Entry: " << id << " Size: " << entries[idx].mSize << " Time: " << entries[idx].mTime << LL_ENDL;
- std::map<LLUUID, S32>::iterator iter = entry_idx_map.find(id);
- if (iter != entry_idx_map.end())
+ // Use mTexturesSizeMap to collect UUIDs of textures with bodies
+ typedef std::set<std::pair<U32,S32> > time_idx_set_t;
+ std::set<std::pair<U32,S32> > time_idx_set;
+ for (size_map_t::iterator iter1 = mTexturesSizeMap.begin();
+ iter1 != mTexturesSizeMap.end(); ++iter1)
+ {
+ if (iter1->second > 0)
{
- // Newer entry replacing older entry
- S32 pidx = iter->second;
- total_size -= entries[pidx].mSize;
- entries[pidx].mSize = 0; // flag: skip older entry
+ id_map_t::iterator iter2 = mHeaderIDMap.find(iter1->first);
+ if (iter2 != mHeaderIDMap.end())
+ {
+ S32 idx = iter2->second;
+ time_idx_set.insert(std::make_pair(entries[idx].mTime, idx));
+// llinfos << "TIME: " << entries[idx].mTime << " TEX: " << entries[idx].mID << " IDX: " << idx << " Size: " << entries[idx].mImageSize << llendl;
+ }
}
- entry_idx_map[id] = idx;
- total_size += entries[idx].mSize;
}
-
+
+ // Validate 1/256th of the files on startup
U32 validate_idx = 0;
if (validate)
{
@@ -1235,19 +1402,17 @@ void LLTextureCache::purgeTextures(bool validate)
gSavedSettings.setU32("CacheValidateCounter", next_idx);
LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Validating: " << validate_idx << LL_ENDL;
}
-
- S64 min_cache_size = (sCacheMaxTexturesSize * 9) / 10;
+
+ S64 cache_size = mTexturesSizeTotal;
+ S64 purged_cache_size = (sCacheMaxTexturesSize * (S64)((1.f-TEXTURE_CACHE_PURGE_AMOUNT)*100)) / 100;
S32 purge_count = 0;
- S32 next_idx = 0;
- for (S32 idx=0; idx<num_entries; idx++)
+ for (time_idx_set_t::iterator iter = time_idx_set.begin();
+ iter != time_idx_set.end(); ++iter)
{
- if (entries[idx].mSize == 0)
- {
- continue;
- }
+ S32 idx = iter->second;
bool purge_entry = false;
std::string filename = getTextureFileName(entries[idx].mID);
- if (total_size >= min_cache_size)
+ if (cache_size >= purged_cache_size)
{
purge_entry = true;
}
@@ -1257,60 +1422,44 @@ void LLTextureCache::purgeTextures(bool validate)
U32 uuididx = entries[idx].mID.mData[0];
if (uuididx == validate_idx)
{
- LL_DEBUGS("TextureCache") << "Validating: " << filename << "Size: " << entries[idx].mSize << LL_ENDL;
+ LL_DEBUGS("TextureCache") << "Validating: " << filename << "Size: " << entries[idx].mBodySize << LL_ENDL;
S32 bodysize = LLAPRFile::size(filename, getLocalAPRFilePool());
- if (bodysize != entries[idx].mSize)
+ if (bodysize != entries[idx].mBodySize)
{
- LL_WARNS("TextureCache") << "TEXTURE CACHE BODY HAS BAD SIZE: " << bodysize << " != " << entries[idx].mSize
+ LL_WARNS("TextureCache") << "TEXTURE CACHE BODY HAS BAD SIZE: " << bodysize << " != " << entries[idx].mBodySize
<< filename << LL_ENDL;
purge_entry = true;
}
}
}
+ else
+ {
+ break;
+ }
+
if (purge_entry)
{
purge_count++;
LL_DEBUGS("TextureCache") << "PURGING: " << filename << LL_ENDL;
LLAPRFile::remove(filename, getLocalAPRFilePool());
- total_size -= entries[idx].mSize;
- entries[idx].mSize = 0;
- }
- else
- {
- if (next_idx != idx)
- {
- entries[next_idx] = entries[idx];
- }
- ++next_idx;
+ cache_size -= entries[idx].mBodySize;
+ mTexturesSizeTotal -= entries[idx].mBodySize;
+ entries[idx].mBodySize = 0;
+ mTexturesSizeMap.erase(entries[idx].mID);
}
}
- num_entries = next_idx;
LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Writing Entries: " << num_entries << LL_ENDL;
-
- LLAPRFile::remove(mTexturesDirEntriesFileName, getLocalAPRFilePool());
- LLAPRFile::writeEx(mTexturesDirEntriesFileName,
- (U8*)&entries[0], 0, num_entries*sizeof(Entry),
- getLocalAPRFilePool());
-
- mTexturesSizeTotal = 0;
- mTexturesSizeMap.clear();
- for (S32 idx=0; idx<num_entries; idx++)
- {
- mTexturesSizeMap[entries[idx].mID] = entries[idx].mSize;
- mTexturesSizeTotal += entries[idx].mSize;
- }
- llassert(mTexturesSizeTotal == total_size);
-
- delete[] entries;
+ writeEntriesAndClose(entries);
+
// *FIX:Mani - watchdog back on.
LLAppViewer::instance()->resumeMainloopTimeout();
LL_INFOS("TextureCache") << "TEXTURE CACHE:"
<< " PURGED: " << purge_count
<< " ENTRIES: " << num_entries
- << " CACHE SIZE: " << total_size / 1024*1024 << " MB"
+ << " CACHE SIZE: " << mTexturesSizeTotal / 1024*1024 << " MB"
<< llendl;
}
@@ -1340,78 +1489,43 @@ LLTextureCacheWorker* LLTextureCache::getWriter(handle_t handle)
}
//////////////////////////////////////////////////////////////////////////////
-
// Called from work thread
-S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, bool touch, S32* imagesize)
-{
- bool retry = false;
- S32 idx = -1;
+// Reads imagesize from the header, updates timestamp
+S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, S32& imagesize)
+{
+ LLMutexLock lock(&mHeaderMutex);
+ Entry entry;
+ S32 idx = openAndReadEntry(id, entry, false);
+ if (idx >= 0)
{
- LLMutexLock lock(&mHeaderMutex);
- id_map_t::iterator iter = mHeaderIDMap.find(id);
- if (iter != mHeaderIDMap.end())
- {
- idx = iter->second;
- }
- else if (touch && !mReadOnly)
- {
- if (mHeaderEntriesInfo.mEntries < sCacheMaxEntries)
- {
- // Add an entry
- idx = mHeaderEntriesInfo.mEntries++;
- mHeaderIDMap[id] = idx;
- // Update Info
- LLAPRFile::writeEx(mHeaderEntriesFileName,
- (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo),
- getLocalAPRFilePool());
- }
- else if (!mLRU.empty())
- {
- idx = mLRU.begin()->first; // will be erased below
- const LLUUID& oldid = mLRU.begin()->second;
- mHeaderIDMap.erase(oldid);
- mTexturesSizeMap.erase(oldid);
- mHeaderIDMap[id] = idx;
- }
- else
- {
- idx = -1;
- retry = true;
- }
- }
- if (idx >= 0)
- {
- if (touch && !mReadOnly)
- {
- // Update the lru entry
- mLRU.erase(idx);
- llassert_always(imagesize && *imagesize > 0);
- Entry* entry = new Entry(id, *imagesize, time(NULL));
- S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry);
- LLAPRFile::writeEx(mHeaderEntriesFileName,
- (U8*)entry, offset, sizeof(Entry),
- getLocalAPRFilePool());
- delete entry;
- }
- else if (imagesize)
- {
- // Get the image size
- Entry entry;
- S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry);
+ imagesize = entry.mImageSize;
+ writeEntryAndClose(idx, entry); // updates time
+ }
+ return idx;
+}
- LLAPRFile::readEx(mHeaderEntriesFileName,
- (U8*)&entry, offset, sizeof(Entry),
- getLocalAPRFilePool());
- *imagesize = entry.mSize;
- }
- }
+// Writes imagesize to the header, updates timestamp
+S32 LLTextureCache::setHeaderCacheEntry(const LLUUID& id, S32 imagesize)
+{
+ mHeaderMutex.lock();
+ llassert_always(imagesize >= 0);
+ Entry entry;
+ S32 idx = openAndReadEntry(id, entry, true);
+ if (idx >= 0)
+ {
+ entry.mImageSize = imagesize;
+ writeEntryAndClose(idx, entry);
+ mHeaderMutex.unlock();
}
- if (retry)
+ else // retry
{
- readHeaderCache(); // updates the lru
+ mHeaderMutex.unlock();
+ readHeaderCache(); // We couldn't write an entry, so refresh the LRU
+ mHeaderMutex.lock();
llassert_always(!mLRU.empty() || mHeaderEntriesInfo.mEntries < sCacheMaxEntries);
- idx = getHeaderCacheEntry(id, touch, imagesize); // assert above ensures no inf. recursion
+ mHeaderMutex.unlock();
+ idx = setHeaderCacheEntry(id, imagesize); // assert above ensures no inf. recursion
}
return idx;
}
@@ -1427,8 +1541,8 @@ LLTextureCache::handle_t LLTextureCache::readFromCache(const std::string& filena
// so let the thread handle it
LLMutexLock lock(&mWorkersMutex);
LLTextureCacheWorker* worker = new LLTextureCacheLocalFileWorker(this, priority, filename, id,
- NULL, size, offset, 0,
- responder);
+ NULL, size, offset, 0,
+ responder);
handle_t handle = worker->read();
mReaders[handle] = worker;
return handle;
@@ -1441,8 +1555,8 @@ LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 pri
// so let the thread handle it
LLMutexLock lock(&mWorkersMutex);
LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id,
- NULL, size, offset, 0,
- responder);
+ NULL, size, offset,
+ 0, responder);
handle_t handle = worker->read();
mReaders[handle] = worker;
return handle;
@@ -1453,21 +1567,24 @@ bool LLTextureCache::readComplete(handle_t handle, bool abort)
{
lockWorkers();
handle_map_t::iterator iter = mReaders.find(handle);
- llassert_always(iter != mReaders.end());
- LLTextureCacheWorker* worker = iter->second;
- bool res = worker->complete();
- if (res || abort)
+ LLTextureCacheWorker* worker = NULL;
+ bool complete = false;
+ if (iter != mReaders.end())
{
- mReaders.erase(handle);
+ worker = iter->second;
+ complete = worker->complete();
+ }
+ if (worker && (complete || abort))
+ {
+ mReaders.erase(iter);
unlockWorkers();
worker->scheduleDelete();
- return true;
}
else
{
unlockWorkers();
- return false;
}
+ return (complete || abort);
}
LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 priority,
@@ -1487,19 +1604,13 @@ LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 prio
purgeTextures(false);
mDoPurge = FALSE;
}
- if (datasize >= TEXTURE_CACHE_ENTRY_SIZE)
- {
- LLMutexLock lock(&mWorkersMutex);
- llassert_always(imagesize > 0);
- LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id,
- data, datasize, 0,
- imagesize, responder);
- handle_t handle = worker->write();
- mWriters[handle] = worker;
- return handle;
- }
- delete responder;
- return LLWorkerThread::nullHandle();
+ LLMutexLock lock(&mWorkersMutex);
+ LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id,
+ data, datasize, 0,
+ imagesize, responder);
+ handle_t handle = worker->write();
+ mWriters[handle] = worker;
+ return handle;
}
bool LLTextureCache::writeComplete(handle_t handle, bool abort)
@@ -1539,32 +1650,20 @@ void LLTextureCache::addCompleted(Responder* responder, bool success)
//////////////////////////////////////////////////////////////////////////////
// Called from MAIN thread (endWork())
-
+// Ensure that mHeaderMutex is locked first!
bool LLTextureCache::removeHeaderCacheEntry(const LLUUID& id)
{
- if (mReadOnly)
- {
- return false;
- }
- LLMutexLock lock(&mHeaderMutex);
- id_map_t::iterator iter = mHeaderIDMap.find(id);
- if (iter != mHeaderIDMap.end())
- {
- S32 idx = iter->second;
- if (idx >= 0)
- {
- Entry* entry = new Entry(id, -1, time(NULL));
- S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry);
-
- LLAPRFile::writeEx(mHeaderEntriesFileName,
- (U8*)entry, offset, sizeof(Entry),
- getLocalAPRFilePool());
- delete entry;
- mLRU[idx] = id;
- mHeaderIDMap.erase(id);
- mTexturesSizeMap.erase(id);
- return true;
- }
+ Entry entry;
+ S32 idx = openAndReadEntry(id, entry, false);
+ if (idx >= 0)
+ {
+ entry.mImageSize = -1;
+ entry.mBodySize = 0;
+ writeEntryAndClose(idx, entry);
+ mFreeList.insert(idx);
+ mHeaderIDMap.erase(id);
+ mTexturesSizeMap.erase(id);
+ return true;
}
return false;
}
@@ -1574,6 +1673,7 @@ void LLTextureCache::removeFromCache(const LLUUID& id)
//llwarns << "Removing texture from cache: " << id << llendl;
if (!mReadOnly)
{
+ LLMutexLock lock(&mHeaderMutex);
removeHeaderCacheEntry(id);
LLAPRFile::remove(getTextureFileName(id), getLocalAPRFilePool());
}
diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h
index 68b1458e9a..4203cbbc43 100644
--- a/indra/newview/lltexturecache.h
+++ b/indra/newview/lltexturecache.h
@@ -40,6 +40,7 @@
#include "llworkerthread.h"
+class LLImageFormatted;
class LLTextureCacheWorker;
class LLTextureCache : public LLWorkerThread
@@ -48,6 +49,27 @@ class LLTextureCache : public LLWorkerThread
friend class LLTextureCacheRemoteWorker;
friend class LLTextureCacheLocalFileWorker;
+private:
+ // Entries
+ struct EntriesInfo
+ {
+ EntriesInfo() : mVersion(0.f), mEntries(0) {}
+ F32 mVersion;
+ U32 mEntries;
+ };
+ struct Entry
+ {
+ Entry() {}
+ Entry(const LLUUID& id, S32 imagesize, S32 bodysize, U32 time) :
+ mID(id), mImageSize(imagesize), mBodySize(bodysize), mTime(time) {}
+ void init(const LLUUID& id, U32 time) { mID = id, mImageSize = 0; mBodySize = 0; mTime = time; }
+ LLUUID mID; // 16 bytes
+ S32 mImageSize; // total size of image if known
+ S32 mBodySize; // size of body file in body cache
+ U32 mTime; // seconds since 1/1/1970
+ };
+
+
public:
class Responder : public LLResponder
@@ -106,10 +128,16 @@ public:
// debug
S32 getNumReads() { return mReaders.size(); }
S32 getNumWrites() { return mWriters.size(); }
+ S64 getUsage() { return mTexturesSizeTotal; }
+ S64 getMaxUsage() { return sCacheMaxTexturesSize; }
+ U32 getEntries() { return mHeaderEntriesInfo.mEntries; }
+ U32 getMaxEntries() { return sCacheMaxEntries; };
+ BOOL isInCache(const LLUUID& id) ;
+ BOOL isInLocal(const LLUUID& id) ;
protected:
// Accessed by LLTextureCacheWorker
- bool appendToTextureEntryList(const LLUUID& id, S32 size);
+ bool updateTextureEntryList(const LLUUID& id, S32 size);
std::string getLocalFileName(const LLUUID& id);
std::string getTextureFileName(const LLUUID& id);
void addCompleted(Responder* responder, bool success);
@@ -122,7 +150,16 @@ private:
void readHeaderCache();
void purgeAllTextures(bool purge_directories);
void purgeTextures(bool validate);
- S32 getHeaderCacheEntry(const LLUUID& id, bool touch, S32* imagesize = NULL);
+ LLAPRFile* openHeaderEntriesFile(bool readonly, S32 offset);
+ void closeHeaderEntriesFile();
+ void readEntriesHeader();
+ void writeEntriesHeader();
+ S32 openAndReadEntry(const LLUUID& id, Entry& entry, bool create);
+ void writeEntryAndClose(S32 idx, Entry& entry);
+ U32 openAndReadEntries(std::vector<Entry>& entries);
+ void writeEntriesAndClose(const std::vector<Entry>& entries);
+ S32 getHeaderCacheEntry(const LLUUID& id, S32& imagesize);
+ S32 setHeaderCacheEntry(const LLUUID& id, S32 imagesize);
bool removeHeaderCacheEntry(const LLUUID& id);
void lockHeaders() { mHeaderMutex.lock(); }
void unlockHeaders() { mHeaderMutex.unlock(); }
@@ -132,6 +169,7 @@ private:
LLMutex mWorkersMutex;
LLMutex mHeaderMutex;
LLMutex mListMutex;
+ LLAPRFile* mHeaderAPRFile;
typedef std::map<handle_t, LLTextureCacheWorker*> handle_map_t;
handle_map_t mReaders;
@@ -145,42 +183,28 @@ private:
BOOL mReadOnly;
- // Entries
- struct EntriesInfo
- {
- F32 mVersion;
- U32 mEntries;
- };
- struct Entry
- {
- Entry() {}
- Entry(const LLUUID& id, S32 size, U32 time) : mID(id), mSize(size), mTime(time) {}
- LLUUID mID; // 128 bits
- S32 mSize; // total size of image if known (NOT size cached)
- U32 mTime; // seconds since 1/1/1970
- };
-
// HEADERS (Include first mip)
std::string mHeaderEntriesFileName;
std::string mHeaderDataFileName;
EntriesInfo mHeaderEntriesInfo;
- typedef std::map<S32,LLUUID> index_map_t;
- index_map_t mLRU; // index, id; stored as a map for fast removal
+ std::set<S32> mFreeList; // deleted entries
+ std::set<LLUUID> mLRU;
typedef std::map<LLUUID,S32> id_map_t;
id_map_t mHeaderIDMap;
// BODIES (TEXTURES minus headers)
std::string mTexturesDirName;
- std::string mTexturesDirEntriesFileName;
typedef std::map<LLUUID,S32> size_map_t;
size_map_t mTexturesSizeMap;
S64 mTexturesSizeTotal;
LLAtomic32<BOOL> mDoPurge;
-
+
// Statics
static F32 sHeaderCacheVersion;
static U32 sCacheMaxEntries;
static S64 sCacheMaxTexturesSize;
};
+extern const S32 TEXTURE_CACHE_ENTRY_SIZE;
+
#endif // LL_LLTEXTURECACHE_H
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index dc34c5ad37..2b846d33fc 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -37,17 +37,20 @@
#include "llrender.h"
#include "llagent.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#include "llbutton.h"
#include "lldraghandle.h"
#include "llfocusmgr.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
#include "llfolderview.h"
+#include "llfoldervieweventlistener.h"
#include "llinventory.h"
-#include "llinventorymodel.h"
-#include "llinventoryview.h"
+#include "llinventoryfunctions.h"
+#include "llinventoryobserver.h"
+#include "llinventorypanel.h"
+#include "llfloaterinventory.h"
#include "lllineeditor.h"
#include "llui.h"
#include "llviewerinventory.h"
@@ -59,6 +62,7 @@
#include "llscrollcontainer.h"
#include "lltoolmgr.h"
#include "lltoolpipette.h"
+#include "llfiltereditor.h"
#include "lltool.h"
#include "llviewerwindow.h"
@@ -69,26 +73,9 @@
#include "lltrans.h"
-static const S32 CLOSE_BTN_WIDTH = 100;
-const S32 PIPETTE_BTN_WIDTH = 32;
static const S32 HPAD = 4;
static const S32 VPAD = 4;
static const S32 LINE = 16;
-static const S32 SMALL_BTN_WIDTH = 64;
-static const S32 TEX_PICKER_MIN_WIDTH =
- (HPAD +
- CLOSE_BTN_WIDTH +
- HPAD +
- CLOSE_BTN_WIDTH +
- HPAD +
- SMALL_BTN_WIDTH +
- HPAD +
- SMALL_BTN_WIDTH +
- HPAD +
- 30 +
- RESIZE_HANDLE_WIDTH * 2);
-static const S32 CLEAR_BTN_WIDTH = 50;
-static const S32 TEX_PICKER_MIN_HEIGHT = 290;
static const S32 FOOTER_HEIGHT = 100;
static const S32 BORDER_PAD = HPAD;
static const S32 TEXTURE_INVENTORY_PADDING = 30;
@@ -108,7 +95,6 @@ class LLFloaterTexturePicker : public LLFloater
public:
LLFloaterTexturePicker(
LLTextureCtrl* owner,
- const LLRect& rect,
const std::string& label,
PermissionMask immediate_filter_perm_mask,
PermissionMask non_immediate_filter_perm_mask,
@@ -118,16 +104,16 @@ public:
virtual ~LLFloaterTexturePicker();
// LLView overrides
- virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
+ /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL drop, EDragAndDropType cargo_type, void *cargo_data,
EAcceptance *accept,
std::string& tooltip_msg);
- virtual void draw();
- virtual BOOL handleKeyHere(KEY key, MASK mask);
+ /*virtual*/ void draw();
+ /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
// LLFloater overrides
- virtual void onClose(bool app_quitting);
- virtual BOOL postBuild();
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onClose(bool app_settings);
// New functions
void setImageID( const LLUUID& image_asset_id);
@@ -136,8 +122,6 @@ public:
const LLUUID& findItemID(const LLUUID& asset_id, BOOL copyable_only);
void setCanApplyImmediately(BOOL b);
- void setDirty( BOOL b ) { mIsDirty = b; }
- BOOL isDirty() const { return mIsDirty; }
void setActive( BOOL active );
LLTextureCtrl* getOwner() const { return mOwner; }
@@ -147,23 +131,24 @@ public:
PermissionMask getFilterPermMask();
void updateFilterPermMask();
void commitIfImmediateSet();
-
+
+ void onFilterEdit(const std::string& search_string );
+
static void onBtnSetToDefault( void* userdata );
static void onBtnSelect( void* userdata );
static void onBtnCancel( void* userdata );
- static void onBtnPipette( void* userdata );
+ void onBtnPipette( );
//static void onBtnRevert( void* userdata );
static void onBtnWhite( void* userdata );
static void onBtnNone( void* userdata );
static void onBtnClear( void* userdata );
- static void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action, void* data);
+ void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
static void onShowFolders(LLUICtrl* ctrl, void* userdata);
static void onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata);
- static void onSearchEdit(const std::string& search_string, void* user_data );
- static void onTextureSelect( const LLTextureEntry& te, void *data );
+ void onTextureSelect( const LLTextureEntry& te );
protected:
- LLPointer<LLViewerImage> mTexturep;
+ LLPointer<LLViewerTexture> mTexturep;
LLTextureCtrl* mOwner;
LLUUID mImageAssetID; // Currently selected texture
@@ -179,10 +164,9 @@ protected:
LLTextBox* mResolutionLabel;
std::string mPendingName;
- BOOL mIsDirty;
BOOL mActive;
- LLSearchEditor* mSearchEdit;
+ LLFilterEditor* mFilterEdit;
LLInventoryPanel* mInventoryPanel;
PermissionMask mImmediateFilterPermMask;
PermissionMask mNonImmediateFilterPermMask;
@@ -194,18 +178,12 @@ protected:
LLFloaterTexturePicker::LLFloaterTexturePicker(
LLTextureCtrl* owner,
- const LLRect& rect,
const std::string& label,
PermissionMask immediate_filter_perm_mask,
PermissionMask non_immediate_filter_perm_mask,
BOOL can_apply_immediately,
const std::string& fallback_image_name)
- :
- LLFloater( std::string("texture picker"),
- rect,
- std::string( "Pick: " ) + label,
- TRUE,
- TEX_PICKER_MIN_WIDTH, TEX_PICKER_MIN_HEIGHT ),
+: LLFloater(LLSD()),
mOwner( owner ),
mImageAssetID( owner->getImageAssetID() ),
mFallbackImageName( fallback_image_name ),
@@ -214,78 +192,15 @@ LLFloaterTexturePicker::LLFloaterTexturePicker(
mLabel(label),
mTentativeLabel(NULL),
mResolutionLabel(NULL),
- mIsDirty( FALSE ),
mActive( TRUE ),
- mSearchEdit(NULL),
+ mFilterEdit(NULL),
mImmediateFilterPermMask(immediate_filter_perm_mask),
mNonImmediateFilterPermMask(non_immediate_filter_perm_mask),
mContextConeOpacity(0.f)
{
- LLUICtrlFactory::getInstance()->buildFloater(this,"floater_texture_ctrl.xml");
-
- mTentativeLabel = getChild<LLTextBox>("Multiple");
-
- mResolutionLabel = getChild<LLTextBox>("unknown");
-
-
- childSetAction("Default",LLFloaterTexturePicker::onBtnSetToDefault,this);
- childSetAction("None", LLFloaterTexturePicker::onBtnNone,this);
- childSetAction("Blank", LLFloaterTexturePicker::onBtnWhite,this);
-
-
- childSetCommitCallback("show_folders_check", onShowFolders, this);
- childSetVisible("show_folders_check", FALSE);
-
- mSearchEdit = getChild<LLSearchEditor>("inventory search editor");
- mSearchEdit->setSearchCallback(onSearchEdit, this);
-
- mInventoryPanel = getChild<LLInventoryPanel>("inventory panel");
-
- if(mInventoryPanel)
- {
- U32 filter_types = 0x0;
- filter_types |= 0x1 << LLInventoryType::IT_TEXTURE;
- filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT;
-
- mInventoryPanel->setFilterTypes(filter_types);
- //mInventoryPanel->setFilterPermMask(getFilterPermMask()); //Commented out due to no-copy texture loss.
- mInventoryPanel->setFilterPermMask(immediate_filter_perm_mask);
- mInventoryPanel->setSelectCallback(onSelectionChange, this);
- mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
- mInventoryPanel->setAllowMultiSelect(FALSE);
-
- // store this filter as the default one
- mInventoryPanel->getRootFolder()->getFilter()->markDefault();
-
- // Commented out to stop opening all folders with textures
- // mInventoryPanel->openDefaultFolderForType(LLAssetType::AT_TEXTURE);
-
- // don't put keyboard focus on selected item, because the selection callback
- // will assume that this was user input
- mInventoryPanel->setSelection(findItemID(mImageAssetID, FALSE), TAKE_FOCUS_NO);
- }
-
mCanApplyImmediately = can_apply_immediately;
- mNoCopyTextureSelected = FALSE;
-
- childSetValue("apply_immediate_check", gSavedSettings.getBOOL("ApplyTextureImmediately"));
- childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this);
-
- if (!can_apply_immediately)
- {
- childSetEnabled("show_folders_check", FALSE);
- }
-
- childSetAction("Pipette", LLFloaterTexturePicker::onBtnPipette,this);
- childSetAction("Cancel", LLFloaterTexturePicker::onBtnCancel,this);
- childSetAction("Select", LLFloaterTexturePicker::onBtnSelect,this);
-
- // update permission filter once UI is fully initialized
- updateFilterPermMask();
-
+ LLUICtrlFactory::getInstance()->buildFloater(this,"floater_texture_ctrl.xml",NULL);
setCanMinimize(FALSE);
-
- mSavedFolderState.setApply(FALSE);
}
LLFloaterTexturePicker::~LLFloaterTexturePicker()
@@ -297,7 +212,7 @@ void LLFloaterTexturePicker::setImageID(const LLUUID& image_id)
if( mImageAssetID != image_id && mActive)
{
mNoCopyTextureSelected = FALSE;
- mIsDirty = TRUE;
+ mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here?
mImageAssetID = image_id;
LLUUID item_id = findItemID(mImageAssetID, FALSE);
if (item_id.isNull())
@@ -350,9 +265,9 @@ void LLFloaterTexturePicker::updateImageStats()
if (mTexturep.notNull())
{
//RN: have we received header data for this image?
- if (mTexturep->getWidth(0) > 0 && mTexturep->getHeight(0) > 0)
+ if (mTexturep->getFullWidth() > 0 && mTexturep->getFullHeight() > 0)
{
- std::string formatted_dims = llformat("%d x %d", mTexturep->getWidth(0),mTexturep->getHeight(0));
+ std::string formatted_dims = llformat("%d x %d", mTexturep->getFullWidth(),mTexturep->getFullHeight());
mResolutionLabel->setTextArg("[DIMENSIONS]", formatted_dims);
}
else
@@ -360,6 +275,10 @@ void LLFloaterTexturePicker::updateImageStats()
mResolutionLabel->setTextArg("[DIMENSIONS]", std::string("[? x ?]"));
}
}
+ else
+ {
+ mResolutionLabel->setTextArg("[DIMENSIONS]", std::string(""));
+ }
}
// virtual
@@ -418,15 +337,15 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask)
{
LLFolderView* root_folder = mInventoryPanel->getRootFolder();
- if (root_folder && mSearchEdit)
+ if (root_folder && mFilterEdit)
{
- if (mSearchEdit->hasFocus()
+ if (mFilterEdit->hasFocus()
&& (key == KEY_RETURN || key == KEY_DOWN)
&& mask == MASK_NONE)
{
if (!root_folder->getCurSelectedItem())
{
- LLFolderViewItem* itemp = root_folder->getItemByID(gAgent.getInventoryRootID());
+ LLFolderViewItem* itemp = root_folder->getItemByID(gInventory.getRootFolderID());
if (itemp)
{
root_folder->setSelection(itemp, FALSE, FALSE);
@@ -435,7 +354,7 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask)
root_folder->scrollToShowSelection();
// move focus to inventory proper
- root_folder->setFocus(TRUE);
+ mInventoryPanel->setFocus(TRUE);
// treat this as a user selection of the first filtered result
commitIfImmediateSet();
@@ -443,16 +362,15 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask)
return TRUE;
}
- if (root_folder->hasFocus() && key == KEY_UP)
+ if (mInventoryPanel->hasFocus() && key == KEY_UP)
{
- mSearchEdit->focusFirstItem(TRUE);
+ mFilterEdit->focusFirstItem(TRUE);
}
}
return LLFloater::handleKeyHere(key, mask);
}
-// virtual
void LLFloaterTexturePicker::onClose(bool app_quitting)
{
if (mOwner)
@@ -460,7 +378,6 @@ void LLFloaterTexturePicker::onClose(bool app_quitting)
mOwner->onFloaterClose();
}
stopUsingPipette();
- destroy();
}
// virtual
@@ -474,13 +391,76 @@ BOOL LLFloaterTexturePicker::postBuild()
setTitle(pick + mLabel);
}
+ mTentativeLabel = getChild<LLTextBox>("Multiple");
+
+ mResolutionLabel = getChild<LLTextBox>("unknown");
+
+ childSetAction("Default",LLFloaterTexturePicker::onBtnSetToDefault,this);
+ childSetAction("None", LLFloaterTexturePicker::onBtnNone,this);
+ childSetAction("Blank", LLFloaterTexturePicker::onBtnWhite,this);
+
+
+ childSetCommitCallback("show_folders_check", onShowFolders, this);
+ childSetVisible("show_folders_check", FALSE);
+
+ mFilterEdit = getChild<LLFilterEditor>("inventory search editor");
+ mFilterEdit->setCommitCallback(boost::bind(&LLFloaterTexturePicker::onFilterEdit, this, _2));
+
+ mInventoryPanel = getChild<LLInventoryPanel>("inventory panel");
+
+ if(mInventoryPanel)
+ {
+ U32 filter_types = 0x0;
+ filter_types |= 0x1 << LLInventoryType::IT_TEXTURE;
+ filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT;
+
+ mInventoryPanel->setFilterTypes(filter_types);
+ //mInventoryPanel->setFilterPermMask(getFilterPermMask()); //Commented out due to no-copy texture loss.
+ mInventoryPanel->setFilterPermMask(mImmediateFilterPermMask);
+ mInventoryPanel->setSelectCallback(boost::bind(&LLFloaterTexturePicker::onSelectionChange, this, _1, _2));
+ mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
+ mInventoryPanel->setAllowMultiSelect(FALSE);
+
+ // store this filter as the default one
+ mInventoryPanel->getRootFolder()->getFilter()->markDefault();
+
+ // Commented out to stop opening all folders with textures
+ // mInventoryPanel->openDefaultFolderForType(LLFolderType::FT_TEXTURE);
+
+ // don't put keyboard focus on selected item, because the selection callback
+ // will assume that this was user input
+ mInventoryPanel->setSelection(findItemID(mImageAssetID, FALSE), TAKE_FOCUS_NO);
+ }
+
+
+ mNoCopyTextureSelected = FALSE;
+
+ childSetValue("apply_immediate_check", gSavedSettings.getBOOL("ApplyTextureImmediately"));
+ childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this);
+
+ if (!mCanApplyImmediately)
+ {
+ childSetEnabled("show_folders_check", FALSE);
+ }
+
+ getChild<LLUICtrl>("Pipette")->setCommitCallback( boost::bind(&LLFloaterTexturePicker::onBtnPipette, this));
+ childSetAction("Cancel", LLFloaterTexturePicker::onBtnCancel,this);
+ childSetAction("Select", LLFloaterTexturePicker::onBtnSelect,this);
+
+ // update permission filter once UI is fully initialized
+ updateFilterPermMask();
+ mSavedFolderState.setApply(FALSE);
+
+ LLToolPipette::getInstance()->setToolSelectCallback(boost::bind(&LLFloaterTexturePicker::onTextureSelect, this, _1));
+
return TRUE;
}
// virtual
void LLFloaterTexturePicker::draw()
{
+ S32 floater_header_size = getHeaderHeight();
if (mOwner)
{
// draw cone of context pointing back to texture swatch
@@ -543,22 +523,19 @@ void LLFloaterTexturePicker::draw()
childSetEnabled("Pipette", mActive);
childSetValue("Pipette", LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance());
- //RN: reset search bar to reflect actual search query (all caps, for example)
- mSearchEdit->setText(mInventoryPanel->getFilterSubString());
-
//BOOL allow_copy = FALSE;
if( mOwner )
{
mTexturep = NULL;
if(mImageAssetID.notNull())
{
- mTexturep = gImageList.getImage(mImageAssetID, MIPMAP_YES, IMMEDIATE_NO);
- mTexturep->setBoostLevel(LLViewerImage::BOOST_PREVIEW);
+ mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES);
+ mTexturep->setBoostLevel(LLViewerTexture::BOOST_PREVIEW);
}
else if (!mFallbackImageName.empty())
{
- mTexturep = gImageList.getImageFromFile(mFallbackImageName);
- mTexturep->setBoostLevel(LLViewerImage::BOOST_PREVIEW);
+ mTexturep = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName);
+ mTexturep->setBoostLevel(LLViewerTexture::BOOST_PREVIEW);
}
if (mTentativeLabel)
@@ -579,9 +556,9 @@ void LLFloaterTexturePicker::draw()
// Border
LLRect border( BORDER_PAD,
- getRect().getHeight() - LLFLOATER_HEADER_SIZE - BORDER_PAD,
- ((TEX_PICKER_MIN_WIDTH / 2) - TEXTURE_INVENTORY_PADDING - HPAD) - BORDER_PAD,
- BORDER_PAD + FOOTER_HEIGHT + (getRect().getHeight() - TEX_PICKER_MIN_HEIGHT));
+ getRect().getHeight() - floater_header_size - BORDER_PAD,
+ ((getMinWidth() / 2) - TEXTURE_INVENTORY_PADDING - HPAD) - BORDER_PAD,
+ BORDER_PAD + FOOTER_HEIGHT + (getRect().getHeight() - getMinHeight()));
gl_rect_2d( border, LLColor4::black, FALSE );
@@ -602,7 +579,7 @@ void LLFloaterTexturePicker::draw()
mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) );
// Draw Tentative Label over the image
- if( mOwner->getTentative() && !mIsDirty )
+ if( mOwner->getTentative() && !mViewModel->isDirty() )
{
mTentativeLabel->setVisible( TRUE );
drawChild(mTentativeLabel);
@@ -719,7 +696,7 @@ void LLFloaterTexturePicker::onBtnRevert(void* userdata)
// TODO: Change this to tell the owner to cancel. It needs to be
// smart enough to restore multi-texture selections.
self->mOwner->onFloaterCommit();
- self->mIsDirty = FALSE;
+ self->mViewModel->resetDirty();
}*/
// static
@@ -731,8 +708,8 @@ void LLFloaterTexturePicker::onBtnCancel(void* userdata)
{
self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CANCEL);
}
- self->mIsDirty = FALSE;
- self->close();
+ self->mViewModel->resetDirty();
+ self->closeFloater();
}
// static
@@ -743,52 +720,42 @@ void LLFloaterTexturePicker::onBtnSelect(void* userdata)
{
self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_SELECT);
}
- self->close();
+ self->closeFloater();
}
-// static
-void LLFloaterTexturePicker::onBtnPipette( void* userdata )
+void LLFloaterTexturePicker::onBtnPipette()
{
- LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
-
- if ( self)
+ BOOL pipette_active = childGetValue("Pipette").asBoolean();
+ pipette_active = !pipette_active;
+ if (pipette_active)
{
- BOOL pipette_active = self->childGetValue("Pipette").asBoolean();
- pipette_active = !pipette_active;
- if (pipette_active)
- {
- LLToolPipette::getInstance()->setSelectCallback(onTextureSelect, self);
- LLToolMgr::getInstance()->setTransientTool(LLToolPipette::getInstance());
- }
- else
- {
- LLToolMgr::getInstance()->clearTransientTool();
- }
+ LLToolMgr::getInstance()->setTransientTool(LLToolPipette::getInstance());
+ }
+ else
+ {
+ LLToolMgr::getInstance()->clearTransientTool();
}
-
}
-// static
-void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action, void* data)
+void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action)
{
- LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)data;
if (items.size())
{
LLFolderViewItem* first_item = items.front();
LLInventoryItem* itemp = gInventory.getItem(first_item->getListener()->getUUID());
- self->mNoCopyTextureSelected = FALSE;
+ mNoCopyTextureSelected = FALSE;
if (itemp)
{
if (!itemp->getPermissions().allowCopyBy(gAgent.getID()))
{
- self->mNoCopyTextureSelected = TRUE;
+ mNoCopyTextureSelected = TRUE;
}
- self->mImageAssetID = itemp->getAssetUUID();
- self->mIsDirty = TRUE;
+ mImageAssetID = itemp->getAssetUUID();
+ mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here?
if (user_action)
{
// only commit intentional selections, not implicit ones
- self->commitIfImmediateSet();
+ commitIfImmediateSet();
}
}
}
@@ -827,107 +794,98 @@ void LLFloaterTexturePicker::updateFilterPermMask()
//mInventoryPanel->setFilterPermMask( getFilterPermMask() ); Commented out due to no-copy texture loss.
}
-void LLFloaterTexturePicker::onSearchEdit(const std::string& search_string, void* user_data )
+void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string )
{
- LLFloaterTexturePicker* picker = (LLFloaterTexturePicker*)user_data;
-
std::string upper_case_search_string = search_string;
LLStringUtil::toUpper(upper_case_search_string);
if (upper_case_search_string.empty())
{
- if (picker->mInventoryPanel->getFilterSubString().empty())
+ if (mInventoryPanel->getFilterSubString().empty())
{
// current filter and new filter empty, do nothing
return;
}
- picker->mSavedFolderState.setApply(TRUE);
- picker->mInventoryPanel->getRootFolder()->applyFunctorRecursively(picker->mSavedFolderState);
+ mSavedFolderState.setApply(TRUE);
+ mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState);
// add folder with current item to list of previously opened folders
LLOpenFoldersWithSelection opener;
- picker->mInventoryPanel->getRootFolder()->applyFunctorRecursively(opener);
- picker->mInventoryPanel->getRootFolder()->scrollToShowSelection();
+ mInventoryPanel->getRootFolder()->applyFunctorRecursively(opener);
+ mInventoryPanel->getRootFolder()->scrollToShowSelection();
}
- else if (picker->mInventoryPanel->getFilterSubString().empty())
+ else if (mInventoryPanel->getFilterSubString().empty())
{
// first letter in search term, save existing folder open state
- if (!picker->mInventoryPanel->getRootFolder()->isFilterModified())
+ if (!mInventoryPanel->getRootFolder()->isFilterModified())
{
- picker->mSavedFolderState.setApply(FALSE);
- picker->mInventoryPanel->getRootFolder()->applyFunctorRecursively(picker->mSavedFolderState);
+ mSavedFolderState.setApply(FALSE);
+ mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState);
}
}
- picker->mInventoryPanel->setFilterSubString(upper_case_search_string);
+ mInventoryPanel->setFilterSubString(upper_case_search_string);
}
-//static
-void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te, void *data )
+void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te )
{
- LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)data;
-
- LLUUID inventory_item_id = self->findItemID(te.getID(), TRUE);
- if (self && inventory_item_id.notNull())
+ LLUUID inventory_item_id = findItemID(te.getID(), TRUE);
+ if (inventory_item_id.notNull())
{
LLToolPipette::getInstance()->setResult(TRUE, "");
- self->setImageID(te.getID());
+ setImageID(te.getID());
- self->mNoCopyTextureSelected = FALSE;
+ mNoCopyTextureSelected = FALSE;
LLInventoryItem* itemp = gInventory.getItem(inventory_item_id);
if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID()))
{
// no copy texture
- self->mNoCopyTextureSelected = TRUE;
+ mNoCopyTextureSelected = TRUE;
}
- self->commitIfImmediateSet();
+ commitIfImmediateSet();
}
else
{
- LLToolPipette::getInstance()->setResult(FALSE, "You do not have a copy this \nof texture in your inventory");
+ LLToolPipette::getInstance()->setResult(FALSE, LLTrans::getString("InventoryNoTexture"));
}
}
///////////////////////////////////////////////////////////////////////
// LLTextureCtrl
-static LLRegisterWidget<LLTextureCtrl> r("texture_picker");
+static LLDefaultChildRegistry::Register<LLTextureCtrl> r("texture_picker");
-LLTextureCtrl::LLTextureCtrl(
- const std::string& name,
- const LLRect &rect,
- const std::string& label,
- const LLUUID &image_id,
- const LLUUID &default_image_id,
- const std::string& default_image_name )
- :
- LLUICtrl(name, rect, TRUE, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP),
+LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p)
+: LLUICtrl(p),
mDragCallback(NULL),
mDropCallback(NULL),
mOnCancelCallback(NULL),
mOnSelectCallback(NULL),
- mBorderColor( gColors.getColor("DefaultHighlightLight") ),
- mImageAssetID( image_id ),
- mDefaultImageAssetID( default_image_id ),
- mDefaultImageName( default_image_name ),
- mLabel( label ),
+ mBorderColor( p.border_color() ),
mAllowNoTexture( FALSE ),
mImmediateFilterPermMask( PERM_NONE ),
mNonImmediateFilterPermMask( PERM_NONE ),
mCanApplyImmediately( FALSE ),
mNeedsRawImageData( FALSE ),
mValid( TRUE ),
- mDirty( FALSE ),
- mShowLoadingPlaceholder( TRUE )
+ mShowLoadingPlaceholder( TRUE ),
+ mImageAssetID(p.image_id),
+ mDefaultImageAssetID(p.default_image_id),
+ mDefaultImageName(p.default_image_name)
{
- mCaption = new LLTextBox( label,
- LLRect( 0, BTN_HEIGHT_SMALL, getRect().getWidth(), 0 ),
- label,
- LLFontGL::getFontSansSerifSmall() );
- mCaption->setFollows( FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM );
+ setAllowNoTexture(p.allow_no_texture);
+ setCanApplyImmediately(p.can_apply_immediately);
+ mCommitOnSelection = !p.no_commit_on_selection;
+
+ LLTextBox::Params params(p.caption_text);
+ params.name(p.label);
+ params.rect(LLRect( 0, BTN_HEIGHT_SMALL, getRect().getWidth(), 0 ));
+ params.initial_value(p.label());
+ params.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
+ mCaption = LLUICtrlFactory::create<LLTextBox> (params);
addChild( mCaption );
S32 image_top = getRect().getHeight();
@@ -935,92 +893,27 @@ LLTextureCtrl::LLTextureCtrl(
S32 image_middle = (image_top + image_bottom) / 2;
S32 line_height = llround(LLFontGL::getFontSansSerifSmall()->getLineHeight());
- mTentativeLabel = new LLTextBox( std::string("Multiple"),
- LLRect(
- 0, image_middle + line_height / 2,
- getRect().getWidth(), image_middle - line_height / 2 ),
- std::string("Multiple"),
- LLFontGL::getFontSansSerifSmall() );
- mTentativeLabel->setHAlign( LLFontGL::HCENTER );
- mTentativeLabel->setFollowsAll();
+ LLTextBox::Params tentative_label_p(p.multiselect_text);
+ tentative_label_p.name("Multiple");
+ tentative_label_p.rect(LLRect (0, image_middle + line_height / 2, getRect().getWidth(), image_middle - line_height / 2 ));
+ tentative_label_p.follows.flags(FOLLOWS_ALL);
+ mTentativeLabel = LLUICtrlFactory::create<LLTextBox> (tentative_label_p);
addChild( mTentativeLabel );
- LLRect border_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
+ LLRect border_rect = getLocalRect();
border_rect.mBottom += BTN_HEIGHT_SMALL;
- mBorder = new LLViewBorder(std::string("border"), border_rect, LLViewBorder::BEVEL_IN);
- mBorder->setFollowsAll();
+ LLViewBorder::Params vbparams(p.border);
+ vbparams.name("border");
+ vbparams.rect(border_rect);
+ mBorder = LLUICtrlFactory::create<LLViewBorder> (vbparams);
addChild(mBorder);
- setEnabled(TRUE); // for the tooltip
mLoadingPlaceholderString = LLTrans::getString("texture_loading");
}
-
LLTextureCtrl::~LLTextureCtrl()
{
- closeFloater();
-}
-
-// virtual
-LLXMLNodePtr LLTextureCtrl::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLUICtrl::getXML();
-
- node->createChild("label", TRUE)->setStringValue(getLabel());
-
- node->createChild("default_image_name", TRUE)->setStringValue(getDefaultImageName());
-
- node->createChild("allow_no_texture", TRUE)->setBoolValue(mAllowNoTexture);
-
- node->createChild("can_apply_immediately", TRUE)->setBoolValue(mCanApplyImmediately );
-
- return node;
-}
-
-LLView* LLTextureCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("texture_picker");
- node->getAttributeString("name", name);
-
- LLRect rect;
- createRect(node, rect, parent);
-
- std::string label;
- node->getAttributeString("label", label);
-
- std::string image_id("");
- node->getAttributeString("image", image_id);
-
- std::string default_image_id("");
- node->getAttributeString("default_image", default_image_id);
-
- std::string default_image_name("Default");
- node->getAttributeString("default_image_name", default_image_name);
-
- BOOL allow_no_texture = FALSE;
- node->getAttributeBOOL("allow_no_texture", allow_no_texture);
-
- BOOL can_apply_immediately = FALSE;
- node->getAttributeBOOL("can_apply_immediately", can_apply_immediately);
-
- if (label.empty())
- {
- label.assign(node->getValue());
- }
-
- LLTextureCtrl* texture_picker = new LLTextureCtrl(
- name,
- rect,
- label,
- LLUUID(image_id),
- LLUUID(default_image_id),
- default_image_name );
- texture_picker->setAllowNoTexture(allow_no_texture);
- texture_picker->setCanApplyImmediately(can_apply_immediately);
-
- texture_picker->initFromXML(node, parent);
-
- return texture_picker;
+ closeDependentFloater();
}
void LLTextureCtrl::setShowLoadingPlaceholder(BOOL showLoadingPlaceholder)
@@ -1047,7 +940,7 @@ void LLTextureCtrl::setVisible( BOOL visible )
{
if( !visible )
{
- closeFloater();
+ closeDependentFloater();
}
LLUICtrl::setVisible( visible );
}
@@ -1066,7 +959,7 @@ void LLTextureCtrl::setEnabled( BOOL enabled )
setToolTip( std::string() );
// *TODO: would be better to keep floater open and show
// disabled state.
- closeFloater();
+ closeDependentFloater();
}
if( floaterp )
@@ -1092,18 +985,6 @@ void LLTextureCtrl::setValid(BOOL valid )
}
}
-// virtual
-BOOL LLTextureCtrl::isDirty() const
-{
- return mDirty;
-}
-
-// virtual
-void LLTextureCtrl::resetDirty()
-{
- mDirty = FALSE;
-}
-
// virtual
void LLTextureCtrl::clear()
@@ -1119,25 +1000,20 @@ void LLTextureCtrl::setLabel(const std::string& label)
void LLTextureCtrl::showPicker(BOOL take_focus)
{
+ // show hourglass cursor when loading inventory window
+ // because inventory construction is slooow
+ getWindow()->setCursor(UI_CURSOR_WAIT);
LLFloater* floaterp = mFloaterHandle.get();
// Show the dialog
if( floaterp )
{
- floaterp->open( ); /* Flawfinder: ignore */
+ floaterp->openFloater();
}
else
{
- if( !mLastFloaterLeftTop.mX && !mLastFloaterLeftTop.mY )
- {
- gFloaterView->getNewFloaterPosition(&mLastFloaterLeftTop.mX, &mLastFloaterLeftTop.mY);
- }
- LLRect rect = gSavedSettings.getRect("TexturePickerRect");
- rect.translate( mLastFloaterLeftTop.mX - rect.mLeft, mLastFloaterLeftTop.mY - rect.mTop );
-
floaterp = new LLFloaterTexturePicker(
this,
- rect,
mLabel,
mImmediateFilterPermMask,
mNonImmediateFilterPermMask,
@@ -1146,8 +1022,10 @@ void LLTextureCtrl::showPicker(BOOL take_focus)
mFloaterHandle = floaterp->getHandle();
- gFloaterView->getParentFloater(this)->addDependentFloater(floaterp);
- floaterp->open(); /* Flawfinder: ignore */
+ LLFloater* root_floater = gFloaterView->getParentFloater(this);
+ if (root_floater)
+ root_floater->addDependentFloater(floaterp);
+ floaterp->openFloater();
}
if (take_focus)
@@ -1157,13 +1035,13 @@ void LLTextureCtrl::showPicker(BOOL take_focus)
}
-void LLTextureCtrl::closeFloater()
+void LLTextureCtrl::closeDependentFloater()
{
LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
if( floaterp )
{
floaterp->setOwner(NULL);
- floaterp->close();
+ floaterp->closeFloater();
}
}
@@ -1191,15 +1069,17 @@ BOOL LLTextureCtrl::handleHover(S32 x, S32 y, MASK mask)
BOOL LLTextureCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
{
BOOL handled = LLUICtrl::handleMouseDown( x, y , mask );
- if( handled )
+
+ if( !handled )
{
showPicker(FALSE);
-
//grab textures first...
- gInventory.startBackgroundFetch(gInventory.findCategoryUUIDForType(LLAssetType::AT_TEXTURE));
+ gInventory.startBackgroundFetch(gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE));
//...then start full inventory fetch.
gInventory.startBackgroundFetch();
+ handled = TRUE;
}
+
return handled;
}
@@ -1210,7 +1090,6 @@ void LLTextureCtrl::onFloaterClose()
if (floaterp)
{
floaterp->setOwner(NULL);
- mLastFloaterLeftTop.set( floaterp->getRect().mLeft, floaterp->getRect().mTop );
}
mFloaterHandle.markDead();
@@ -1222,7 +1101,14 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op)
if( floaterp && getEnabled())
{
- mDirty = (op != TEXTURE_CANCEL);
+ if (op == TEXTURE_CANCEL)
+ mViewModel->resetDirty();
+ // If the "no_commit_on_selection" parameter is set
+ // we get dirty only when user presses OK in the picker
+ // (i.e. op == TEXTURE_SELECT) or texture changes via DnD.
+ else if (mCommitOnSelection || op == TEXTURE_SELECT)
+ mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here?
+
if( floaterp->isDirty() )
{
setTentative( FALSE );
@@ -1232,15 +1118,19 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op)
lldebugs << "mImageAssetID: " << mImageAssetID << llendl;
if (op == TEXTURE_SELECT && mOnSelectCallback)
{
- mOnSelectCallback(this, mCallbackUserData);
+ mOnSelectCallback( this, LLSD() );
}
else if (op == TEXTURE_CANCEL && mOnCancelCallback)
{
- mOnCancelCallback(this, mCallbackUserData);
+ mOnCancelCallback( this, LLSD() );
}
else
{
- onCommit();
+ // If the "no_commit_on_selection" parameter is set
+ // we commit only when user presses OK in the picker
+ // (i.e. op == TEXTURE_SELECT) or texture changes via DnD.
+ if (mCommitOnSelection || op == TEXTURE_SELECT)
+ onCommit();
}
}
}
@@ -1256,7 +1146,7 @@ void LLTextureCtrl::setImageAssetID( const LLUUID& asset_id )
if( floaterp && getEnabled() )
{
floaterp->setImageID( asset_id );
- floaterp->setDirty( FALSE );
+ floaterp->resetDirty();
}
}
}
@@ -1278,6 +1168,9 @@ BOOL LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask,
{
if(doDrop(item))
{
+ if (!mCommitOnSelection)
+ mViewModel->setDirty();
+
// This removes the 'Multiple' overlay, since
// there is now only one texture selected.
setTentative( FALSE );
@@ -1308,19 +1201,27 @@ void LLTextureCtrl::draw()
}
else if (!mImageAssetID.isNull())
{
- mTexturep = gImageList.getImage(mImageAssetID, MIPMAP_YES, IMMEDIATE_NO);
- mTexturep->setBoostLevel(LLViewerImage::BOOST_PREVIEW);
+ LLPointer<LLViewerFetchedTexture> texture = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES,LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+
+ texture->setBoostLevel(LLViewerTexture::BOOST_PREVIEW);
+ texture->forceToSaveRawImage(0) ;
+
+ mTexturep = texture;
}
else if (!mFallbackImageName.empty())
{
// Show fallback image.
- mTexturep = gImageList.getImageFromFile(mFallbackImageName);
- mTexturep->setBoostLevel(LLViewerImage::BOOST_PREVIEW);
+ mTexturep = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName);
+ mTexturep->setBoostLevel(LLViewerTexture::BOOST_PREVIEW);
+ }
+ else//mImageAssetID == LLUUID::null
+ {
+ mTexturep = NULL;
}
// Border
LLRect border( 0, getRect().getHeight(), getRect().getWidth(), BTN_HEIGHT_SMALL );
- gl_rect_2d( border, mBorderColor, FALSE );
+ gl_rect_2d( border, mBorderColor.get(), FALSE );
// Interior
LLRect interior = border;
@@ -1351,15 +1252,16 @@ void LLTextureCtrl::draw()
// Using the discard level, do not show the string if the texture is almost but not
// fully loaded.
if ( mTexturep.notNull() &&
+ (!mTexturep->isFullyLoaded()) &&
(mShowLoadingPlaceholder == TRUE) &&
(mTexturep->getDiscardLevel() != 1) &&
(mTexturep->getDiscardLevel() != 0))
{
- LLFontGL* font = LLFontGL::getFontSansSerifBig();
+ LLFontGL* font = LLFontGL::getFontSansSerif();
font->renderUTF8(
mLoadingPlaceholderString, 0,
- llfloor(interior.mLeft+10),
- llfloor(interior.mTop-20),
+ llfloor(interior.mLeft+3),
+ llfloor(interior.mTop-25),
LLColor4::white,
LLFontGL::LEFT,
LLFontGL::BASELINE,
@@ -1388,7 +1290,7 @@ BOOL LLTextureCtrl::allowDrop(LLInventoryItem* item)
{
if(mDragCallback)
{
- return mDragCallback(this, item, mCallbackUserData);
+ return mDragCallback(this, item);
}
else
{
@@ -1408,7 +1310,7 @@ BOOL LLTextureCtrl::doDrop(LLInventoryItem* item)
{
// if it returns TRUE, we return TRUE, and therefore the
// commit is called above.
- return mDropCallback(this, item, mCallbackUserData);
+ return mDropCallback(this, item);
}
// no callback installed, so just set the image ids and carry on.
@@ -1438,66 +1340,6 @@ LLSD LLTextureCtrl::getValue() const
}
-/////////////////////////////////////////////////////////////////////////////////
-// LLToolTexEyedropper
-
-class LLToolTexEyedropper : public LLTool
-{
-public:
- LLToolTexEyedropper( void (*callback)(const LLUUID& obj_id, const LLUUID& image_id, void* userdata ), void* userdata );
- virtual ~LLToolTexEyedropper();
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleHover(S32 x, S32 y, MASK mask);
-
-protected:
- void (*mCallback)(const LLUUID& obj_id, const LLUUID& image_id, void* userdata );
- void* mCallbackUserData;
-};
-
-
-LLToolTexEyedropper::LLToolTexEyedropper(
- void (*callback)(const LLUUID& obj_id, const LLUUID& image_id, void* userdata ),
- void* userdata )
- : LLTool(std::string("texeyedropper")),
- mCallback( callback ),
- mCallbackUserData( userdata )
-{
-}
-
-LLToolTexEyedropper::~LLToolTexEyedropper()
-{
-}
-
-
-BOOL LLToolTexEyedropper::handleMouseDown(S32 x, S32 y, MASK mask)
-{
- // this will affect framerate on mouse down
- const LLPickInfo& pick = gViewerWindow->pickImmediate(x, y, FALSE);
- LLViewerObject* hit_obj = pick.getObject();
- if (hit_obj &&
- !hit_obj->isAvatar())
- {
- if( (0 <= pick.mObjectFace) && (pick.mObjectFace < hit_obj->getNumTEs()) )
- {
- LLViewerImage* image = hit_obj->getTEImage( pick.mObjectFace );
- if( image )
- {
- if( mCallback )
- {
- mCallback( hit_obj->getID(), image->getID(), mCallbackUserData );
- }
- }
- }
- }
- return TRUE;
-}
-
-BOOL LLToolTexEyedropper::handleHover(S32 x, S32 y, MASK mask)
-{
- lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolTexEyedropper" << llendl;
- gViewerWindow->getWindow()->setCursor(UI_CURSOR_CROSS); // TODO: better cursor
- return TRUE;
-}
diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h
index 623f15eef5..8ca92c3d87 100644
--- a/indra/newview/lltexturectrl.h
+++ b/indra/newview/lltexturectrl.h
@@ -39,16 +39,17 @@
#include "llstring.h"
#include "lluictrl.h"
#include "llpermissionsflags.h"
+#include "lltextbox.h" // for params
+#include "llviewborder.h" // for params
class LLButton;
class LLFloaterTexturePicker;
class LLInventoryItem;
-class LLTextBox;
-class LLViewBorder;
-class LLViewerImage;
+class LLViewerFetchedTexture;
// used for setting drag & drop callbacks.
-typedef BOOL (*drag_n_drop_callback)(LLUICtrl*, LLInventoryItem*, void*);
+typedef boost::function<BOOL (LLUICtrl*, LLInventoryItem*)> drag_n_drop_callback;
+
//////////////////////////////////////////////////////////////////////////////////////////
// LLTextureCtrl
@@ -66,17 +67,48 @@ public:
} ETexturePickOp;
public:
- LLTextureCtrl(
- const std::string& name, const LLRect& rect,
- const std::string& label,
- const LLUUID& image_id,
- const LLUUID& default_image_id,
- const std::string& default_image_name );
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<LLUUID> image_id;
+ Optional<LLUUID> default_image_id;
+ Optional<std::string> default_image_name;
+ Optional<bool> allow_no_texture;
+ Optional<bool> can_apply_immediately;
+ Optional<bool> no_commit_on_selection; // alternative mode: commit occurs and the widget gets dirty
+ // only on DnD or when OK is pressed in the picker
+ Optional<S32> label_width;
+ Optional<LLUIColor> border_color;
+
+ Optional<LLTextBox::Params> multiselect_text,
+ caption_text;
+
+ Optional<LLViewBorder::Params> border;
+
+ Params()
+ : image_id("image"),
+ default_image_id("default_image_id"),
+ default_image_name("default_image_name"),
+ allow_no_texture("allow_no_texture"),
+ can_apply_immediately("can_apply_immediately"),
+ no_commit_on_selection("no_commit_on_selection", false),
+ label_width("label_width", -1),
+ border_color("border_color"),
+ multiselect_text("multiselect_text"),
+ caption_text("caption_text"),
+ border("border")
+ {
+ name = "texture picker";
+ mouse_opaque(true);
+ follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP);
+ }
+ };
+protected:
+ LLTextureCtrl(const Params&);
+ friend class LLUICtrlFactory;
+public:
virtual ~LLTextureCtrl();
// LLView interface
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
@@ -90,9 +122,6 @@ public:
virtual void setVisible( BOOL visible );
virtual void setEnabled( BOOL enabled );
- virtual BOOL isDirty() const;
- virtual void resetDirty();
-
void setValid(BOOL valid);
// LLUICtrl interface
@@ -105,6 +134,7 @@ public:
// LLTextureCtrl interface
void showPicker(BOOL take_focus);
void setLabel(const std::string& label);
+ void setLabelWidth(S32 label_width) {mLabelWidth =label_width;}
const std::string& getLabel() const { return mLabel; }
void setAllowNoTexture( BOOL b ) { mAllowNoTexture = b; }
@@ -133,7 +163,7 @@ public:
PermissionMask getImmediateFilterPermMask() { return mImmediateFilterPermMask; }
PermissionMask getNonImmediateFilterPermMask() { return mNonImmediateFilterPermMask; }
- void closeFloater();
+ void closeDependentFloater();
void onFloaterClose();
void onFloaterCommit(ETexturePickOp op);
@@ -146,10 +176,10 @@ public:
// the drop happened - resulting in an on commit callback, but not
// necessariliy any other change.
void setDropCallback(drag_n_drop_callback cb) { mDropCallback = cb; }
-
- void setOnCancelCallback(LLUICtrlCallback cb) { mOnCancelCallback = cb; }
- void setOnSelectCallback(LLUICtrlCallback cb) { mOnSelectCallback = cb; }
+ void setOnCancelCallback(commit_callback_t cb) { mOnCancelCallback = cb; }
+
+ void setOnSelectCallback(commit_callback_t cb) { mOnSelectCallback = cb; }
void setShowLoadingPlaceholder(BOOL showLoadingPlaceholder);
@@ -160,10 +190,10 @@ private:
private:
drag_n_drop_callback mDragCallback;
drag_n_drop_callback mDropCallback;
- LLUICtrlCallback mOnCancelCallback;
- LLUICtrlCallback mOnSelectCallback;
- LLPointer<LLViewerImage> mTexturep;
- LLColor4 mBorderColor;
+ commit_callback_t mOnCancelCallback;
+ commit_callback_t mOnSelectCallback;
+ LLPointer<LLViewerFetchedTexture> mTexturep;
+ LLUIColor mBorderColor;
LLUUID mImageItemID;
LLUUID mImageAssetID;
LLUUID mDefaultImageAssetID;
@@ -174,16 +204,16 @@ private:
LLTextBox* mCaption;
std::string mLabel;
BOOL mAllowNoTexture; // If true, the user can select "none" as an option
- LLCoordGL mLastFloaterLeftTop;
PermissionMask mImmediateFilterPermMask;
PermissionMask mNonImmediateFilterPermMask;
BOOL mCanApplyImmediately;
+ BOOL mCommitOnSelection;
BOOL mNeedsRawImageData;
LLViewBorder* mBorder;
BOOL mValid;
- BOOL mDirty;
BOOL mShowLoadingPlaceholder;
std::string mLoadingPlaceholderString;
+ S32 mLabelWidth;
};
// XUI HACK: When floaters converted, switch this file to lltexturepicker.h/cpp
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index e9dd7921cd..5ce6884239 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -32,108 +32,37 @@
#include "llviewerprecompiledheaders.h"
+#include <iostream>
+
#include "llstl.h"
#include "lltexturefetch.h"
#include "llcurl.h"
+#include "lldir.h"
#include "llhttpclient.h"
+#include "llhttpstatuscodes.h"
#include "llimage.h"
+#include "llimagej2c.h"
#include "llimageworker.h"
#include "llworkerthread.h"
+#include "message.h"
#include "llagent.h"
#include "lltexturecache.h"
-#include "llviewerimagelist.h"
-#include "llviewerimage.h"
+#include "llviewercontrol.h"
+#include "llviewertexturelist.h"
+#include "llviewertexture.h"
#include "llviewerregion.h"
+#include "llworld.h"
//////////////////////////////////////////////////////////////////////////////
-//static
class LLTextureFetchWorker : public LLWorkerClass
{
-friend class LLTextureFetch;
-
-private:
-#if 0
- class URLResponder : public LLHTTPClient::Responder
- {
- public:
- URLResponder(LLTextureFetch* fetcher, const LLUUID& id)
- : mFetcher(fetcher), mID(id)
- {
- }
- ~URLResponder()
- {
- }
- virtual void error(U32 status, const std::string& reason)
- {
- mFetcher->lockQueue();
- LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
- if (worker)
- {
-// llwarns << "LLTextureFetchWorker::URLResponder::error " << status << ": " << reason << llendl;
- worker->callbackURLReceived(LLSD(), false);
- }
- mFetcher->unlockQueue();
- }
- virtual void result(const LLSD& content)
- {
- mFetcher->lockQueue();
- LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
- if (worker)
- {
- worker->callbackURLReceived(content, true);
- }
- mFetcher->unlockQueue();
- }
- private:
- LLTextureFetch* mFetcher;
- LLUUID mID;
- };
-
- class HTTPGetResponder : public LLHTTPClient::Responder
- {
- public:
- HTTPGetResponder(LLTextureFetch* fetcher, const LLUUID& id)
- : mFetcher(fetcher), mID(id)
- {
- }
- ~HTTPGetResponder()
- {
- }
- virtual void completed(U32 status, const std::stringstream& content)
- {
- mFetcher->lockQueue();
- LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
- if (worker)
- {
- const std::string& cstr = content.str();
- if (200 <= status && status < 300)
- {
- if (203 == status) // partial information (i.e. last block)
- {
- worker->callbackHttpGet((U8*)cstr.c_str(), cstr.length(), true);
- }
- else
- {
- worker->callbackHttpGet((U8*)cstr.c_str(), cstr.length(), false);
- }
- }
- else
- {
-// llinfos << "LLTextureFetchWorker::HTTPGetResponder::error " << status << ": " << cstr << llendl;
- worker->callbackHttpGet(NULL, -1, true);
- }
- }
- mFetcher->unlockQueue();
- }
- private:
- LLTextureFetch* mFetcher;
- LLUUID mID;
- };
-#endif
+ friend class LLTextureFetch;
+ friend class HTTPGetResponder;
+private:
class CacheReadResponder : public LLTextureCache::ReadResponder
{
public:
@@ -179,20 +108,20 @@ private:
LLUUID mID;
};
- class DecodeResponder : public LLResponder
+ class DecodeResponder : public LLImageDecodeThread::Responder
{
public:
DecodeResponder(LLTextureFetch* fetcher, const LLUUID& id, LLTextureFetchWorker* worker)
: mFetcher(fetcher), mID(id), mWorker(worker)
{
}
- virtual void completed(bool success)
+ virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux)
{
mFetcher->lockQueue();
LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
if (worker)
{
- worker->callbackDecoded(success);
+ worker->callbackDecoded(success, raw, aux);
}
mFetcher->unlockQueue();
}
@@ -227,37 +156,45 @@ public:
~LLTextureFetchWorker();
void relese() { --mActiveCount; }
+ void callbackHttpGet(const LLChannelDescriptors& channels,
+ const LLIOPipe::buffer_ptr_t& buffer,
+ bool partial, bool success);
+ void callbackCacheRead(bool success, LLImageFormatted* image,
+ S32 imagesize, BOOL islocal);
+ void callbackCacheWrite(bool success);
+ void callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux);
+
+ void setGetStatus(U32 status, const std::string& reason)
+ {
+ mGetStatus = status;
+ mGetReason = reason;
+ }
+
protected:
LLTextureFetchWorker(LLTextureFetch* fetcher, const LLUUID& id, const LLHost& host,
F32 priority, S32 discard, S32 size);
+ LLTextureFetchWorker(LLTextureFetch* fetcher, const std::string& url, const LLUUID& id, const LLHost& host,
+ F32 priority, S32 discard, S32 size);
private:
/*virtual*/ void startWork(S32 param); // called from addWork() (MAIN THREAD)
/*virtual*/ void endWork(S32 param, bool aborted); // called from doWork() (MAIN THREAD)
- virtual std::string getName() { return LLStringUtil::null; }
void resetFormattedData();
void setImagePriority(F32 priority);
void setDesiredDiscard(S32 discard, S32 size);
bool insertPacket(S32 index, U8* data, S32 size);
void clearPackets();
+ void setupPacketData();
U32 calcWorkPriority();
void removeFromCache();
bool processSimulatorPackets();
- bool decodeImage();
bool writeToCacheComplete();
- void lockWorkData() { mWorkMutex.lock(); }
- void unlockWorkData() { mWorkMutex.unlock(); }
+ void lockWorkMutex() { mWorkMutex.lock(); }
+ void unlockWorkMutex() { mWorkMutex.unlock(); }
- void callbackURLReceived(const LLSD& data, bool success);
- void callbackHttpGet(U8* data, S32 data_size, bool last_block);
- void callbackCacheRead(bool success, LLImageFormatted* image,
- S32 imagesize, BOOL islocal);
- void callbackCacheWrite(bool success);
- void callbackDecoded(bool success);
-
private:
enum e_state // mState
{
@@ -268,8 +205,8 @@ private:
CACHE_POST,
LOAD_FROM_NETWORK,
LOAD_FROM_SIMULATOR,
- LOAD_FROM_HTTP_GET_URL,
- LOAD_FROM_HTTP_GET_DATA,
+ SEND_HTTP_REQ,
+ WAIT_HTTP_REQ,
DECODE_IMAGE,
DECODE_IMAGE_UPDATE,
WRITE_TO_CACHE,
@@ -280,19 +217,17 @@ private:
{
UNSENT = 0,
QUEUED = 1,
- SENT_SIM = 2,
- SENT_URL = 3,
- SENT_HTTP = 4
+ SENT_SIM = 2
};
static const char* sStateDescs[];
e_state mState;
LLTextureFetch* mFetcher;
- LLImageWorker* mImageWorker;
LLPointer<LLImageFormatted> mFormattedImage;
LLPointer<LLImageRaw> mRawImage;
LLPointer<LLImageRaw> mAuxImage;
LLUUID mID;
LLHost mHost;
+ std::string mUrl;
U8 mType;
F32 mImagePriority;
U32 mWorkPriority;
@@ -314,15 +249,18 @@ private:
S32 mCachedSize;
BOOL mLoaded;
e_request_state mSentRequest;
+ handle_t mDecodeHandle;
BOOL mDecoded;
BOOL mWritten;
BOOL mNeedsAux;
BOOL mHaveAllData;
BOOL mInLocalCache;
+ S32 mHTTPFailCount;
S32 mRetryAttempt;
- std::string mURL;
S32 mActiveCount;
-
+ U32 mGetStatus;
+ std::string mGetReason;
+
// Work Data
LLMutex mWorkMutex;
struct PacketData
@@ -340,25 +278,79 @@ private:
U8 mImageCodec;
};
-class LLTextureFetchLocalFileWorker : public LLTextureFetchWorker
-{
-friend class LLTextureFetch;
-
-protected:
- LLTextureFetchLocalFileWorker(LLTextureFetch* fetcher, const std::string& filename, const LLUUID& id, const LLHost& host,
- F32 priority, S32 discard, S32 size)
- : LLTextureFetchWorker(fetcher, id, host, priority, discard, size),
- mFileName(filename)
- {}
+//////////////////////////////////////////////////////////////////////////////
-private:
- /*virtual*/ std::string getName() { return mFileName; }
+class HTTPGetResponder : public LLCurl::Responder
+{
+ LOG_CLASS(HTTPGetResponder);
+public:
+ HTTPGetResponder(LLTextureFetch* fetcher, const LLUUID& id, U64 startTime, S32 requestedSize, U32 offset)
+ : mFetcher(fetcher), mID(id), mStartTime(startTime), mRequestedSize(requestedSize), mOffset(offset)
+ {
+ }
+ ~HTTPGetResponder()
+ {
+ }
+ virtual void completedRaw(U32 status, const std::string& reason,
+ const LLChannelDescriptors& channels,
+ const LLIOPipe::buffer_ptr_t& buffer)
+ {
+ if ((gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog")) || (gSavedSettings.getBOOL("LogTextureDownloadsToSimulator")))
+ {
+ mFetcher->mTextureInfo.setRequestStartTime(mID, mStartTime);
+ U64 timeNow = LLTimer::getTotalTime();
+ mFetcher->mTextureInfo.setRequestType(mID, LLTextureInfoDetails::REQUEST_TYPE_HTTP);
+ mFetcher->mTextureInfo.setRequestSize(mID, mRequestedSize);
+ mFetcher->mTextureInfo.setRequestOffset(mID, mOffset);
+ mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, timeNow);
+ }
+ lldebugs << "HTTP COMPLETE: " << mID << llendl;
+ mFetcher->lockQueue();
+ LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
+ if (worker)
+ {
+ bool success = false;
+ bool partial = false;
+ if (HTTP_OK <= status && status < HTTP_MULTIPLE_CHOICES)
+ {
+ success = true;
+ if (HTTP_PARTIAL_CONTENT == status) // partial information
+ {
+ partial = true;
+ }
+ }
+ else
+ {
+ worker->setGetStatus(status, reason);
+// llwarns << status << ": " << reason << llendl;
+ }
+ if (!success)
+ {
+ worker->setGetStatus(status, reason);
+// llwarns << "CURL GET FAILED, status:" << status << " reason:" << reason << llendl;
+ }
+ mFetcher->removeFromHTTPQueue(mID);
+ worker->callbackHttpGet(channels, buffer, partial, success);
+ }
+ else
+ {
+ mFetcher->removeFromHTTPQueue(mID);
+ llwarns << "Worker not found: " << mID << llendl;
+ }
+ mFetcher->unlockQueue();
+ }
+
private:
- std::string mFileName;
+ LLTextureFetch* mFetcher;
+ LLUUID mID;
+ U64 mStartTime;
+ S32 mRequestedSize;
+ U32 mOffset;
};
+//////////////////////////////////////////////////////////////////////////////
//static
const char* LLTextureFetchWorker::sStateDescs[] = {
@@ -368,8 +360,8 @@ const char* LLTextureFetchWorker::sStateDescs[] = {
"CACHE_POST",
"LOAD_FROM_NETWORK",
"LOAD_FROM_SIMULATOR",
- "LOAD_FROM_HTTP_URL",
- "LOAD_FROM_HTTP_DATA",
+ "SEND_HTTP_REQ",
+ "WAIT_HTTP_REQ",
"DECODE_IMAGE",
"DECODE_IMAGE_UPDATE",
"WRITE_TO_CACHE",
@@ -380,6 +372,7 @@ const char* LLTextureFetchWorker::sStateDescs[] = {
// called from MAIN THREAD
LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
+ const std::string& url, // Optional URL
const LLUUID& id, // Image UUID
const LLHost& host, // Simulator host
F32 priority, // Priority
@@ -388,9 +381,9 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
: LLWorkerClass(fetcher, "TextureFetch"),
mState(INIT),
mFetcher(fetcher),
- mImageWorker(NULL),
mID(id),
mHost(host),
+ mUrl(url),
mImagePriority(priority),
mWorkPriority(0),
mRequestedPriority(0.f),
@@ -404,18 +397,21 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
mBuffer(NULL),
mBufferSize(0),
mRequestedSize(0),
- mDesiredSize(FIRST_PACKET_SIZE),
+ mDesiredSize(TEXTURE_CACHE_ENTRY_SIZE),
mFileSize(0),
mCachedSize(0),
mLoaded(FALSE),
mSentRequest(UNSENT),
+ mDecodeHandle(0),
mDecoded(FALSE),
mWritten(FALSE),
mNeedsAux(FALSE),
mHaveAllData(FALSE),
mInLocalCache(FALSE),
+ mHTTPFailCount(0),
mRetryAttempt(0),
mActiveCount(0),
+ mGetStatus(0),
mWorkMutex(NULL),
mFirstPacket(0),
mLastPacket(-1),
@@ -440,7 +436,7 @@ LLTextureFetchWorker::~LLTextureFetchWorker()
// << " Requested=" << mRequestedDiscard
// << " Desired=" << mDesiredDiscard << llendl;
llassert_always(!haveWork());
- lockWorkData();
+ lockWorkMutex();
if (mCacheReadHandle != LLTextureCache::nullHandle())
{
mFetcher->mTextureCache->readComplete(mCacheReadHandle, true);
@@ -449,13 +445,10 @@ LLTextureFetchWorker::~LLTextureFetchWorker()
{
mFetcher->mTextureCache->writeComplete(mCacheWriteHandle, true);
}
- if (mImageWorker)
- {
- mImageWorker->scheduleDelete();
- }
mFormattedImage = NULL;
clearPackets();
- unlockWorkData();
+ unlockWorkMutex();
+ mFetcher->removeFromHTTPQueue(mID);
}
void LLTextureFetchWorker::clearPackets()
@@ -467,11 +460,43 @@ void LLTextureFetchWorker::clearPackets()
mFirstPacket = 0;
}
+void LLTextureFetchWorker::setupPacketData()
+{
+ S32 data_size = 0;
+ if (mFormattedImage.notNull())
+ {
+ data_size = mFormattedImage->getDataSize();
+ }
+ if (data_size > 0)
+ {
+ // Only used for simulator requests
+ mFirstPacket = (data_size - FIRST_PACKET_SIZE) / MAX_IMG_PACKET_SIZE + 1;
+ if (FIRST_PACKET_SIZE + (mFirstPacket-1) * MAX_IMG_PACKET_SIZE != data_size)
+ {
+ llwarns << "Bad CACHED TEXTURE size: " << data_size << " removing." << llendl;
+ removeFromCache();
+ resetFormattedData();
+ clearPackets();
+ }
+ else if (mFileSize > 0)
+ {
+ mLastPacket = mFirstPacket-1;
+ mTotalPackets = (mFileSize - FIRST_PACKET_SIZE + MAX_IMG_PACKET_SIZE-1) / MAX_IMG_PACKET_SIZE + 1;
+ }
+ else
+ {
+ // This file was cached using HTTP so we have to refetch the first packet
+ resetFormattedData();
+ clearPackets();
+ }
+ }
+}
+
U32 LLTextureFetchWorker::calcWorkPriority()
{
-// llassert_always(mImagePriority >= 0 && mImagePriority <= LLViewerImage::maxDecodePriority());
- F32 priority_scale = (F32)LLWorkerThread::PRIORITY_LOWBITS / LLViewerImage::maxDecodePriority();
- mWorkPriority = (U32)(mImagePriority * priority_scale);
+// llassert_always(mImagePriority >= 0 && mImagePriority <= LLViewerTexture::maxDecodePriority());
+ static F32 PRIORITY_SCALE = (F32)LLWorkerThread::PRIORITY_LOWBITS / LLViewerFetchedTexture::maxDecodePriority();
+ mWorkPriority = (U32)(mImagePriority * PRIORITY_SCALE);
return mWorkPriority;
}
@@ -502,6 +527,7 @@ void LLTextureFetchWorker::setDesiredDiscard(S32 discard, S32 size)
mDesiredSize = size;
prioritize = true;
}
+ mDesiredSize = llmax(mDesiredSize, TEXTURE_CACHE_ENTRY_SIZE);
if ((prioritize && mState == INIT) || mState == DONE)
{
mState = INIT;
@@ -512,7 +538,7 @@ void LLTextureFetchWorker::setDesiredDiscard(S32 discard, S32 size)
void LLTextureFetchWorker::setImagePriority(F32 priority)
{
-// llassert_always(priority >= 0 && priority <= LLViewerImage::maxDecodePriority());
+// llassert_always(priority >= 0 && priority <= LLViewerTexture::maxDecodePriority());
F32 delta = fabs(priority - mImagePriority);
if (delta > (mImagePriority * .05f) || mState == DONE)
{
@@ -538,17 +564,24 @@ void LLTextureFetchWorker::resetFormattedData()
// Called from MAIN thread
void LLTextureFetchWorker::startWork(S32 param)
{
- llassert(mImageWorker == NULL);
llassert(mFormattedImage.isNull());
}
-#include "llviewerimagelist.h" // debug
+#include "llviewertexturelist.h" // debug
// Called from LLWorkerThread::processRequest()
bool LLTextureFetchWorker::doWork(S32 param)
{
LLMutexLock lock(&mWorkMutex);
+ if ((mFetcher->isQuitting() || mImagePriority < 1.0f || getFlags(LLWorkerClass::WCF_DELETE_REQUESTED)))
+ {
+ if (mState < WRITE_TO_CACHE)
+ {
+ return true; // abort
+ }
+ }
+
if (mFetcher->mDebugPause)
{
return false; // debug: don't do any work
@@ -563,16 +596,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
mFetchTimer.reset();
}
- if (mImagePriority <= 0.0f)
- {
- if (mState < WRITE_TO_CACHE)
- {
- return true; // cancel request
- }
- }
-
if (mState == INIT)
{
+ mRawImage = NULL ;
mRequestedDiscard = -1;
mLoadedDiscard = -1;
mDecodedDiscard = -1;
@@ -590,8 +616,10 @@ bool LLTextureFetchWorker::doWork(S32 param)
clearPackets(); // TODO: Shouldn't be necessary
mCacheReadHandle = LLTextureCache::nullHandle();
mCacheWriteHandle = LLTextureCache::nullHandle();
- mURL.clear();
mState = LOAD_FROM_TEXTURE_CACHE;
+ mDesiredSize = llmax(mDesiredSize, TEXTURE_CACHE_ENTRY_SIZE); // min desired size is TEXTURE_CACHE_ENTRY_SIZE
+ LL_DEBUGS("Texture") << mID << ": Priority: " << llformat("%8.0f",mImagePriority)
+ << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL;
// fall through
}
@@ -612,16 +640,27 @@ bool LLTextureFetchWorker::doWork(S32 param)
setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);
- if (getName().empty())
+ if (mUrl.compare(0, 7, "file://") == 0)
+ {
+ // read file from local disk
+ std::string filename = mUrl.substr(7, std::string::npos);
+ mCacheReadHandle = mFetcher->mTextureCache->readFromCache(filename, mID, cache_priority,
+ offset, size, responder);
+ }
+ else if (mUrl.empty())
{
mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority,
offset, size, responder);
}
else
{
- // read file from local disk
- mCacheReadHandle = mFetcher->mTextureCache->readFromCache(getName(), mID, cache_priority,
- offset, size, responder);
+ if (!(mUrl.compare(0, 7, "http://") == 0))
+ {
+ // *TODO:?remove this warning
+ llwarns << "Unknown URL Type: " << mUrl << llendl;
+ }
+ setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
+ mState = SEND_HTTP_REQ;
}
}
@@ -647,75 +686,101 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mState == CACHE_POST)
{
- mDesiredSize = llmax(mDesiredSize, FIRST_PACKET_SIZE);
mCachedSize = mFormattedImage.notNull() ? mFormattedImage->getDataSize() : 0;
// Successfully loaded
if ((mCachedSize >= mDesiredSize) || mHaveAllData)
{
// we have enough data, decode it
llassert_always(mFormattedImage->getDataSize() > 0);
+ mLoadedDiscard = mDesiredDiscard;
mState = DECODE_IMAGE;
+ LL_DEBUGS("Texture") << mID << ": Cached. Bytes: " << mFormattedImage->getDataSize()
+ << " Size: " << llformat("%dx%d",mFormattedImage->getWidth(),mFormattedImage->getHeight())
+ << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL;
// fall through
}
else
{
- if (!getName().empty())
+ if (mUrl.compare(0, 7, "file://") == 0)
{
// failed to load local file, we're done.
return true;
}
// need more data
- mState = LOAD_FROM_NETWORK;
+ else
+ {
+ LL_DEBUGS("Texture") << mID << ": Not in Cache" << LL_ENDL;
+ mState = LOAD_FROM_NETWORK;
+ }
// fall through
}
}
if (mState == LOAD_FROM_NETWORK)
{
- if (mSentRequest == UNSENT)
+ bool get_url = gSavedSettings.getBOOL("ImagePipelineUseHTTP");
+ if (!mUrl.empty()) get_url = false;
+// if (mHost != LLHost::invalid) get_url = false;
+ if ( get_url )
{
- if (mFormattedImage.isNull())
- {
- mFormattedImage = new LLImageJ2C;
- }
- // Add this to the network queue and sit here.
- // LLTextureFetch::update() will send off a request which will change our state
- S32 data_size = mFormattedImage->getDataSize();
- if (data_size > 0)
+ LLViewerRegion* region = NULL;
+ if (mHost == LLHost::invalid)
+ region = gAgent.getRegion();
+ else
+ region = LLWorld::getInstance()->getRegion(mHost);
+
+ if (region)
{
- // Only used for simulator requests
- mFirstPacket = (data_size - FIRST_PACKET_SIZE) / MAX_IMG_PACKET_SIZE + 1;
- if (FIRST_PACKET_SIZE + (mFirstPacket-1) * MAX_IMG_PACKET_SIZE != data_size)
+ std::string http_url = region->getCapability("GetTexture");
+ if (!http_url.empty())
{
-// llwarns << "Bad CACHED TEXTURE size: " << data_size << " removing." << llendl;
- removeFromCache();
- resetFormattedData();
- clearPackets();
- }
- else
- {
- mLastPacket = mFirstPacket-1;
- mTotalPackets = (mFileSize - FIRST_PACKET_SIZE + MAX_IMG_PACKET_SIZE-1) / MAX_IMG_PACKET_SIZE + 1;
+ mUrl = http_url + "/?texture_id=" + mID.asString().c_str();
}
}
+ else
+ {
+ // This will happen if not logged in or if a region deoes not have HTTP Texture enabled
+ //llwarns << "Region not found for host: " << mHost << llendl;
+ }
+ }
+ if (!mUrl.empty())
+ {
+ mState = LLTextureFetchWorker::SEND_HTTP_REQ;
+ setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
+ // don't return, fall through to next state
+ }
+ else if (mSentRequest == UNSENT)
+ {
+ // Add this to the network queue and sit here.
+ // LLTextureFetch::update() will send off a request which will change our state
mRequestedSize = mDesiredSize;
mRequestedDiscard = mDesiredDiscard;
mSentRequest = QUEUED;
- mFetcher->lockQueue();
mFetcher->addToNetworkQueue(this);
- mFetcher->unlockQueue();
setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
+ return false;
+ }
+ else
+ {
+ // Shouldn't need to do anything here
+ //llassert_always(mFetcher->mNetworkQueue.find(mID) != mFetcher->mNetworkQueue.end());
+ // Make certain this is in the network queue
+ //mFetcher->addToNetworkQueue(this);
+ //setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
+ return false;
}
- return false;
}
if (mState == LOAD_FROM_SIMULATOR)
{
+ if (mFormattedImage.isNull())
+ {
+ mFormattedImage = new LLImageJ2C;
+ }
if (processSimulatorPackets())
{
- mFetcher->lockQueue();
- mFetcher->removeFromNetworkQueue(this);
- mFetcher->unlockQueue();
+ LL_DEBUGS("Texture") << mID << ": Loaded from Sim. Bytes: " << mFormattedImage->getDataSize() << LL_ENDL;
+ mFetcher->removeFromNetworkQueue(this, false);
if (mFormattedImage.isNull() || !mFormattedImage->getDataSize())
{
// processSimulatorPackets() failed
@@ -727,115 +792,145 @@ bool LLTextureFetchWorker::doWork(S32 param)
}
else
{
+ mFetcher->addToNetworkQueue(this); // failsafe
setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
}
return false;
}
-#if 0
- if (mState == LOAD_FROM_HTTP_GET_URL)
- {
- if (!mSentRequest)
- {
- mSentRequest = TRUE;
- mLoaded = FALSE;
- std::string url;
- LLViewerRegion* region = gAgent.getRegion();
- if (region)
- {
- url = region->getCapability("RequestTextureDownload");
- }
- if (!url.empty())
- {
- LLSD sd;
- sd = mID.asString();
- setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
- LLHTTPClient::post(url, sd, new URLResponder(mFetcher, mID));
- return false;
- }
- else
+ if (mState == SEND_HTTP_REQ)
+ {
+ {
+ const S32 HTTP_QUEUE_MAX_SIZE = 8;
+ // *TODO: Integrate this with llviewerthrottle
+ // Note: LLViewerThrottle uses dynamic throttling which makes sense for UDP,
+ // but probably not for Textures.
+ // Set the throttle to the entire bandwidth, assuming UDP packets will get priority
+ // when they are needed
+ F32 max_bandwidth = mFetcher->mMaxBandwidth;
+ if ((mFetcher->getHTTPQueueSize() >= HTTP_QUEUE_MAX_SIZE) ||
+ (mFetcher->getTextureBandwidth() > max_bandwidth))
{
-// llwarns << mID << ": HTTP get url failed, requesting from simulator" << llendl;
- mSentRequest = FALSE;
- mState = LOAD_FROM_SIMULATOR;
+ // Make normal priority and return (i.e. wait until there is room in the queue)
+ setPriority(LLWorkerThread::PRIORITY_NORMAL | mWorkPriority);
return false;
}
- }
- else
- {
- if (mLoaded)
+
+ mFetcher->removeFromNetworkQueue(this, false);
+
+ S32 cur_size = 0;
+ if (mFormattedImage.notNull())
{
- if (!mURL.empty())
+ cur_size = mFormattedImage->getDataSize(); // amount of data we already have
+ if (mFormattedImage->getDiscardLevel() == 0)
{
- mState = LOAD_FROM_HTTP_GET_DATA;
- mSentRequest = FALSE; // reset
- mLoaded = FALSE; // reset
- }
- else
- {
-// llwarns << mID << ": HTTP get url is empty, requesting from simulator" << llendl;
- mSentRequest = FALSE;
- mState = LOAD_FROM_SIMULATOR;
+ // We already have all the data, just decode it
+ mLoadedDiscard = mFormattedImage->getDiscardLevel();
+ mState = DECODE_IMAGE;
return false;
}
}
- }
- // fall through
- }
-
- if (mState == LOAD_FROM_HTTP_GET_DATA)
- {
- if (!mSentRequest)
- {
- mSentRequest = TRUE;
- S32 cur_size = mFormattedImage->getDataSize(); // amount of data we already have
mRequestedSize = mDesiredSize;
mRequestedDiscard = mDesiredDiscard;
-#if 1 // *TODO: LLCurl::getByteRange is broken (ignores range)
- cur_size = 0;
- mFormattedImage->deleteData();
-#endif
mRequestedSize -= cur_size;
- // F32 priority = mImagePriority / (F32)LLViewerImage::maxDecodePriority(); // 0-1
S32 offset = cur_size;
mBufferSize = cur_size; // This will get modified by callbackHttpGet()
- std::string url;
- if (mURL.empty())
+
+ bool res = false;
+ if (!mUrl.empty())
{
- //url = "http://asset.agni/0000002f-38ae-0e17-8e72-712e58964e9c.texture";
- std::stringstream urlstr;
- urlstr << "http://asset.agni/" << mID.asString() << ".texture";
- url = urlstr.str();
+ mLoaded = FALSE;
+ mGetStatus = 0;
+ mGetReason.clear();
+ LL_DEBUGS("Texture") << "HTTP GET: " << mID << " Offset: " << offset
+ << " Bytes: " << mRequestedSize
+ << " Bandwidth(kbps): " << mFetcher->getTextureBandwidth() << "/" << max_bandwidth
+ << LL_ENDL;
+ setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
+ mState = WAIT_HTTP_REQ;
+
+ mFetcher->addToHTTPQueue(mID);
+ // Will call callbackHttpGet when curl request completes
+ std::vector<std::string> headers;
+ headers.push_back("Accept: image/x-j2c");
+ res = mFetcher->mCurlGetRequest->getByteRange(mUrl, headers, offset, mRequestedSize,
+ new HTTPGetResponder(mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, offset));
}
- else
+ if (!res)
{
- url = mURL;
+ llwarns << "HTTP GET request failed for " << mID << llendl;
+ resetFormattedData();
+ ++mHTTPFailCount;
+ return true; // failed
}
- mLoaded = FALSE;
-// llinfos << "HTTP GET: " << mID << " Offset: " << offset << " Bytes: " << mRequestedSize << llendl;
- setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
- LLCurl::getByteRange(url, offset, mRequestedSize,
- new HTTPGetResponder(mFetcher, mID)); // *TODO: use mWorkPriority
- return false; // not done
+ // fall through
}
-
+ }
+
+ if (mState == WAIT_HTTP_REQ)
+ {
if (mLoaded)
{
- S32 cur_size = mFormattedImage->getDataSize();
+ S32 cur_size = mFormattedImage.notNull() ? mFormattedImage->getDataSize() : 0;
if (mRequestedSize < 0)
{
-// llwarns << "http get failed for: " << mID << llendl;
- if (cur_size == 0)
+ S32 max_attempts;
+ if (mGetStatus == HTTP_NOT_FOUND)
{
- resetFormattedData();
- return true; // failed
+ mHTTPFailCount = max_attempts = 1; // Don't retry
+ llinfos << "Texture missing from server (404): " << mUrl << llendl;
+ }
+ else if (mGetStatus == HTTP_SERVICE_UNAVAILABLE)
+ {
+ // *TODO: Should probably introduce a timer here to delay future HTTP requsts
+ // for a short time (~1s) to ease server load? Ideally the server would queue
+ // requests instead of returning 503... we already limit the number pending.
+ ++mHTTPFailCount;
+ max_attempts = mHTTPFailCount+1; // Keep retrying
+ LL_INFOS_ONCE("Texture") << "Texture server busy (503): " << mUrl << LL_ENDL;
}
else
{
- mState = DECODE_IMAGE;
- return false; // use what we have
+ const S32 HTTP_MAX_RETRY_COUNT = 3;
+ max_attempts = HTTP_MAX_RETRY_COUNT + 1;
+ ++mHTTPFailCount;
+ llinfos << "HTTP GET failed for: " << mUrl
+ << " Status: " << mGetStatus << " Reason: '" << mGetReason << "'"
+ << " Attempt:" << mHTTPFailCount+1 << "/" << max_attempts << llendl;
+ }
+ if (mHTTPFailCount >= max_attempts)
+ {
+ if (cur_size > 0)
+ {
+ // Use available data
+ mLoadedDiscard = mFormattedImage->getDiscardLevel();
+ mState = DECODE_IMAGE;
+ return false;
+ }
+ else
+ {
+ resetFormattedData();
+ return true; // failed
+ }
+ }
+ else
+ {
+ mState = SEND_HTTP_REQ;
+ return false; // retry
}
}
+
+ if (mFormattedImage.isNull())
+ {
+ // For now, create formatted image based on extension
+ std::string extension = gDirUtilp->getExtension(mUrl);
+ mFormattedImage = LLImageFormatted::createFromType(LLImageBase::getCodecFromExtension(extension));
+ if (mFormattedImage.isNull())
+ {
+ mFormattedImage = new LLImageJ2C; // default
+ }
+ }
+
llassert_always(mBufferSize == cur_size + mRequestedSize);
if (mHaveAllData)
{
@@ -854,43 +949,71 @@ bool LLTextureFetchWorker::doWork(S32 param)
mBuffer = NULL;
mBufferSize = 0;
mLoadedDiscard = mRequestedDiscard;
- setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
mState = DECODE_IMAGE;
+ setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
+ return false;
+ }
+ else
+ {
+ setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
return false;
}
-
- // NOTE: Priority gets updated when the http get completes (in callbackHTTPGet())
- setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
- return false;
}
-#endif
if (mState == DECODE_IMAGE)
{
- llassert_always(mFormattedImage->getDataSize() > 0);
+ static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled");
+ if(textures_decode_disabled)
+ {
+ // for debug use, don't decode
+ mState = DONE;
+ setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
+ return true;
+ }
+
+ if (mDesiredDiscard < 0)
+ {
+ // We aborted, don't decode
+ mState = DONE;
+ setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
+ return true;
+ }
+
+ if (mFormattedImage->getDataSize() <= 0)
+ {
+ llerrs << "Decode entered with invalid mFormattedImage. ID = " << mID << llendl;
+ }
+ if (mLoadedDiscard < 0)
+ {
+ llerrs << "Decode entered with invalid mLoadedDiscard. ID = " << mID << llendl;
+ }
setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
mRawImage = NULL;
mAuxImage = NULL;
- llassert_always(mImageWorker == NULL);
llassert_always(mFormattedImage.notNull());
S32 discard = mHaveAllData ? 0 : mLoadedDiscard;
U32 image_priority = LLWorkerThread::PRIORITY_NORMAL | mWorkPriority;
mDecoded = FALSE;
mState = DECODE_IMAGE_UPDATE;
- mImageWorker = new LLImageWorker(mFormattedImage, image_priority, discard, new DecodeResponder(mFetcher, mID, this));
- // fall though (need to call requestDecodedData() to start work)
+ LL_DEBUGS("Texture") << mID << ": Decoding. Bytes: " << mFormattedImage->getDataSize() << " Discard: " << discard
+ << " All Data: " << mHaveAllData << LL_ENDL;
+ mDecodeHandle = mFetcher->mImageDecodeThread->decodeImage(mFormattedImage, image_priority, discard, mNeedsAux,
+ new DecodeResponder(mFetcher, mID, this));
+ // fall though
}
if (mState == DECODE_IMAGE_UPDATE)
{
- if (decodeImage())
+ if (mDecoded)
{
if (mDecodedDiscard < 0)
{
+ LL_DEBUGS("Texture") << mID << ": Failed to Decode." << LL_ENDL;
if (mCachedSize > 0 && !mInLocalCache && mRetryAttempt == 0)
{
// Cache file should be deleted, try again
// llwarns << mID << ": Decode of cached file failed (removed), retrying" << llendl;
+ llassert_always(mDecodeHandle == 0);
mFormattedImage = NULL;
++mRetryAttempt;
setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
@@ -905,6 +1028,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
}
else
{
+ llassert_always(mRawImage.notNull());
+ LL_DEBUGS("Texture") << mID << ": Decoded. Discard: " << mDecodedDiscard
+ << " Raw Image: " << llformat("%dx%d",mRawImage->getWidth(),mRawImage->getHeight()) << LL_ENDL;
setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
mState = WRITE_TO_CACHE;
}
@@ -918,9 +1044,10 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mState == WRITE_TO_CACHE)
{
- if (mInLocalCache || !mFileSize || mSentRequest == UNSENT)
+ if (mInLocalCache || mSentRequest == UNSENT || mFormattedImage.isNull())
{
- // If we're in a local cache or we didn't actually receive any new data, skip
+ // If we're in a local cache or we didn't actually receive any new data,
+ // or we failed to load anything, skip
mState = DONE;
return false;
}
@@ -979,10 +1106,10 @@ bool LLTextureFetchWorker::doWork(S32 param)
// Called from MAIN thread
void LLTextureFetchWorker::endWork(S32 param, bool aborted)
{
- if (mImageWorker)
+ if (mDecodeHandle != 0)
{
- mImageWorker->scheduleDelete();
- mImageWorker = NULL;
+ mFetcher->mImageDecodeThread->abortRequest(mDecodeHandle, false);
+ mDecodeHandle = 0;
}
mFormattedImage = NULL;
}
@@ -1035,7 +1162,7 @@ bool LLTextureFetchWorker::deleteOK()
if ((haveWork() &&
// not ok to delete from these states
- ((mState >= LOAD_FROM_HTTP_GET_URL && mState <= LOAD_FROM_HTTP_GET_DATA) ||
+ ((mState >= SEND_HTTP_REQ && mState <= WAIT_HTTP_REQ) ||
(mState >= WRITE_TO_CACHE && mState <= WAIT_ON_WRITE))))
{
delete_ok = false;
@@ -1044,7 +1171,6 @@ bool LLTextureFetchWorker::deleteOK()
return delete_ok;
}
-
void LLTextureFetchWorker::removeFromCache()
{
if (!mInLocalCache)
@@ -1061,6 +1187,7 @@ bool LLTextureFetchWorker::processSimulatorPackets()
if (mFormattedImage.isNull() || mRequestedSize < 0)
{
// not sure how we got here, but not a valid state, abort!
+ llassert_always(mDecodeHandle == 0);
mFormattedImage = NULL;
return true;
}
@@ -1074,6 +1201,12 @@ bool LLTextureFetchWorker::processSimulatorPackets()
buffer_size += mPackets[i]->mSize;
}
bool have_all_data = mLastPacket >= mTotalPackets-1;
+ if (mRequestedSize <= 0)
+ {
+ // We received a packed but haven't requested anything yet (edge case)
+ // Return true (we're "done") since we didn't request anything
+ return true;
+ }
if (buffer_size >= mRequestedSize || have_all_data)
{
/// We have enough (or all) data
@@ -1109,61 +1242,48 @@ bool LLTextureFetchWorker::processSimulatorPackets()
//////////////////////////////////////////////////////////////////////////////
-void LLTextureFetchWorker::callbackURLReceived(const LLSD& data, bool success)
+void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
+ const LLIOPipe::buffer_ptr_t& buffer,
+ bool partial, bool success)
{
-#if 0
LLMutexLock lock(&mWorkMutex);
- if (!mSentRequest || mState != LOAD_FROM_HTTP_GET_URL)
- {
- llwarns << "callbackURLReceived for unrequested fetch worker, req="
- << mSentRequest << " state= " << mState << llendl;
- return;
- }
- if (success)
- {
- mURL = data.asString();
- }
- mLoaded = TRUE;
- setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
-#endif
-}
-//////////////////////////////////////////////////////////////////////////////
-
-void LLTextureFetchWorker::callbackHttpGet(U8* data, S32 data_size, bool last_block)
-{
-#if 0
- LLMutexLock lock(&mWorkMutex);
- if (!mSentRequest || mState != LOAD_FROM_HTTP_GET_DATA)
+ if (mState != WAIT_HTTP_REQ)
{
- llwarns << "callbackHttpGet for unrequested fetch worker, req="
- << mSentRequest << " state= " << mState << llendl;
+ llwarns << "callbackHttpGet for unrequested fetch worker: " << mID
+ << " req=" << mSentRequest << " state= " << mState << llendl;
return;
}
-// llinfos << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << llendl;
if (mLoaded)
{
llwarns << "Duplicate callback for " << mID.asString() << llendl;
return; // ignore duplicate callback
}
- if (data_size >= 0)
+ if (success)
{
+ // get length of stream:
+ S32 data_size = buffer->countAfter(channels.in(), NULL);
+
+ gTextureList.sTextureBits += data_size * 8; // Approximate - does not include header bits
+
+ LL_DEBUGS("Texture") << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << LL_ENDL;
if (data_size > 0)
{
+ // *TODO: set the formatted image data here directly to avoid the copy
mBuffer = new U8[data_size];
- // *TODO: set the formatted image data here
- memcpy(mBuffer, data, data_size);
+ buffer->readAfter(channels.in(), NULL, mBuffer, data_size);
mBufferSize += data_size;
- if (data_size < mRequestedSize || last_block == true)
+ if (data_size < mRequestedSize && mRequestedDiscard == 0)
{
mHaveAllData = TRUE;
}
else if (data_size > mRequestedSize)
{
- // *TODO: This will happen until we fix LLCurl::getByteRange()
-// llinfos << "HUH?" << llendl;
+ // *TODO: This shouldn't be happening any more
+ llwarns << "data_size = " << data_size << " > requested: " << mRequestedSize << llendl;
mHaveAllData = TRUE;
- mFormattedImage->deleteData();
+ llassert_always(mDecodeHandle == 0);
+ mFormattedImage = NULL; // discard any previous data we had
mBufferSize = data_size;
}
}
@@ -1181,7 +1301,6 @@ void LLTextureFetchWorker::callbackHttpGet(U8* data, S32 data_size, bool last_bl
}
mLoaded = TRUE;
setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
-#endif
}
//////////////////////////////////////////////////////////////////////////////
@@ -1197,7 +1316,7 @@ void LLTextureFetchWorker::callbackCacheRead(bool success, LLImageFormatted* ima
}
if (success)
{
- llassert_always(imagesize > 0);
+ llassert_always(imagesize >= 0);
mFileSize = imagesize;
mFormattedImage = image;
mImageCodec = image->getCodec();
@@ -1225,65 +1344,40 @@ void LLTextureFetchWorker::callbackCacheWrite(bool success)
//////////////////////////////////////////////////////////////////////////////
-void LLTextureFetchWorker::callbackDecoded(bool success)
+void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux)
{
+ LLMutexLock lock(&mWorkMutex);
+ if (mDecodeHandle == 0)
+ {
+ return; // aborted, ignore
+ }
if (mState != DECODE_IMAGE_UPDATE)
{
// llwarns << "Decode callback for " << mID << " with state = " << mState << llendl;
+ mDecodeHandle = 0;
return;
}
-// llinfos << mID << " : DECODE COMPLETE " << llendl;
- setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-bool LLTextureFetchWorker::decodeImage()
-{
- if(!mImageWorker)
- {
- //LLTextureFetchWorker is aborted, skip image decoding.
- return true ;
- }
-
- bool res = true;
- if (mRawImage.isNull())
- {
- res = false;
- if (mImageWorker->requestDecodedData(mRawImage, -1))
- {
- res = true;
-// llinfos << mID << " : BASE DECODE FINISHED" << llendl;
- }
- }
- if (res &&
- (mRawImage.notNull() && mRawImage->getDataSize() > 0) &&
- (mNeedsAux && mAuxImage.isNull()))
+ llassert_always(mFormattedImage.notNull());
+
+ mDecodeHandle = 0;
+ if (success)
{
- res = false;
- if (mImageWorker->requestDecodedAuxData(mAuxImage, 4, -1))
- {
- res = true;
-// llinfos << mID << " : AUX DECODE FINISHED" << llendl;
- }
+ llassert_always(raw);
+ mRawImage = raw;
+ mAuxImage = aux;
+ mDecodedDiscard = mFormattedImage->getDiscardLevel();
+ LL_DEBUGS("Texture") << mID << ": Decode Finished. Discard: " << mDecodedDiscard
+ << " Raw Image: " << llformat("%dx%d",mRawImage->getWidth(),mRawImage->getHeight()) << LL_ENDL;
}
- if (res)
+ else
{
- if ((mRawImage.notNull() && mRawImage->getDataSize() > 0) &&
- (!mNeedsAux || (mAuxImage.notNull() && mAuxImage->getDataSize() > 0)))
- {
- mDecodedDiscard = mFormattedImage->getDiscardLevel();
-// llinfos << mID << " : DECODE FINISHED. DISCARD: " << mDecodedDiscard << llendl;
- }
- else
- {
-// llwarns << "DECODE FAILED: " << mID << " Discard: " << (S32)mFormattedImage->getDiscardLevel() << llendl;
- removeFromCache();
- }
- mImageWorker->scheduleDelete();
- mImageWorker = NULL;
+ llwarns << "DECODE FAILED: " << mID << " Discard: " << (S32)mFormattedImage->getDiscardLevel() << llendl;
+ removeFromCache();
+ mDecodedDiscard = -1; // Redundant, here for clarity and paranoia
}
- return res;
+ mDecoded = TRUE;
+// llinfos << mID << " : DECODE COMPLETE " << llendl;
+ setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
}
//////////////////////////////////////////////////////////////////////////////
@@ -1314,15 +1408,21 @@ bool LLTextureFetchWorker::writeToCacheComplete()
//////////////////////////////////////////////////////////////////////////////
// public
-LLTextureFetch::LLTextureFetch(LLTextureCache* cache, bool threaded)
+LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* imagedecodethread, bool threaded)
: LLWorkerThread("TextureFetch", threaded),
mDebugCount(0),
mDebugPause(FALSE),
mPacketCount(0),
mBadPacketCount(0),
mQueueMutex(getAPRPool()),
- mTextureCache(cache)
+ mNetworkQueueMutex(getAPRPool()),
+ mTextureCache(cache),
+ mImageDecodeThread(imagedecodethread),
+ mTextureBandwidth(0),
+ mCurlGetRequest(NULL)
{
+ mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS");
+ mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), gSavedSettings.getU32("TextureLoggingThreshold"));
}
LLTextureFetch::~LLTextureFetch()
@@ -1330,13 +1430,7 @@ LLTextureFetch::~LLTextureFetch()
// ~LLQueuedThread() called here
}
-bool LLTextureFetch::createRequest(const LLUUID& id, const LLHost& host, F32 priority,
- S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux)
-{
- return createRequest(LLStringUtil::null, id, host, priority, w, h, c, desired_discard, needs_aux);
-}
-
-bool LLTextureFetch::createRequest(const std::string& filename, const LLUUID& id, const LLHost& host, F32 priority,
+bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,
S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux)
{
if (mDebugPause)
@@ -1361,7 +1455,15 @@ bool LLTextureFetch::createRequest(const std::string& filename, const LLUUID& id
}
S32 desired_size;
- if (desired_discard == 0)
+ std::string exten = gDirUtilp->getExtension(url);
+ if (!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C))
+ {
+ // Only do partial requests for J2C at the moment
+ //llinfos << "Merov : LLTextureFetch::createRequest(), blocking fetch on " << url << llendl;
+ desired_size = MAX_IMAGE_DATA_SIZE;
+ desired_discard = 0;
+ }
+ else if (desired_discard == 0)
{
// if we want the entire image, and we know its size, then get it all
// (calcDataSizeJ2C() below makes assumptions about how the image
@@ -1371,14 +1473,14 @@ bool LLTextureFetch::createRequest(const std::string& filename, const LLUUID& id
}
else if (w*h*c > 0)
{
- // If the requester knows the dimentions of the image,
+ // If the requester knows the dimensions of the image,
// this will calculate how much data we need without having to parse the header
desired_size = LLImageJ2C::calcDataSizeJ2C(w, h, c, desired_discard);
}
else
{
- desired_size = FIRST_PACKET_SIZE;
+ desired_size = TEXTURE_CACHE_ENTRY_SIZE;
desired_discard = MAX_DISCARD_LEVEL;
}
@@ -1389,10 +1491,10 @@ bool LLTextureFetch::createRequest(const std::string& filename, const LLUUID& id
{
return false; // need to wait for previous aborted request to complete
}
- worker->lockWorkData();
+ worker->lockWorkMutex();
worker->setImagePriority(priority);
worker->setDesiredDiscard(desired_discard, desired_size);
- worker->unlockWorkData();
+ worker->unlockWorkMutex();
if (!worker->haveWork())
{
worker->mState = LLTextureFetchWorker::INIT;
@@ -1401,16 +1503,7 @@ bool LLTextureFetch::createRequest(const std::string& filename, const LLUUID& id
}
else
{
- if (filename.empty())
- {
- // do remote fetch
- worker = new LLTextureFetchWorker(this, id, host, priority, desired_discard, desired_size);
- }
- else
- {
- // do local file fetch
- worker = new LLTextureFetchLocalFileWorker(this, filename, id, host, priority, desired_discard, desired_size);
- }
+ worker = new LLTextureFetchWorker(this, url, id, host, priority, desired_discard, desired_size);
mRequestMap[id] = worker;
}
worker->mActiveCount++;
@@ -1430,10 +1523,9 @@ void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel)
}
// protected
-
-// call lockQueue() first!
void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker)
{
+ LLMutexLock lock(&mNetworkQueueMutex);
if (mRequestMap.find(worker->mID) != mRequestMap.end())
{
// only add to the queue if in the request map
@@ -1447,10 +1539,27 @@ void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker)
}
}
-// call lockQueue() first!
-void LLTextureFetch::removeFromNetworkQueue(LLTextureFetchWorker* worker)
+void LLTextureFetch::removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel)
{
- mNetworkQueue.erase(worker->mID);
+ LLMutexLock lock(&mNetworkQueueMutex);
+ size_t erased = mNetworkQueue.erase(worker->mID);
+ if (cancel && erased > 0)
+ {
+ mCancelQueue[worker->mHost].insert(worker->mID);
+ }
+}
+
+// protected
+void LLTextureFetch::addToHTTPQueue(const LLUUID& id)
+{
+ LLMutexLock lock(&mNetworkQueueMutex);
+ mHTTPTextureQueue.insert(id);
+}
+
+void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id)
+{
+ LLMutexLock lock(&mNetworkQueueMutex);
+ mHTTPTextureQueue.erase(id);
}
// call lockQueue() first!
@@ -1458,11 +1567,7 @@ void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel)
{
size_t erased_1 = mRequestMap.erase(worker->mID);
llassert_always(erased_1 > 0) ;
- size_t erased = mNetworkQueue.erase(worker->mID);
- if (cancel && erased > 0)
- {
- mCancelQueue[worker->mHost].insert(worker->mID);
- }
+ removeFromNetworkQueue(worker, cancel);
llassert_always(!(worker->getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) ;
worker->scheduleDelete();
@@ -1504,24 +1609,27 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level,
}
else if (worker->checkWork())
{
+ worker->lockWorkMutex();
discard_level = worker->mDecodedDiscard;
- raw = worker->mRawImage; worker->mRawImage = NULL;
- aux = worker->mAuxImage; worker->mAuxImage = NULL;
+ raw = worker->mRawImage;
+ aux = worker->mAuxImage;
res = true;
+ LL_DEBUGS("Texture") << id << ": Request Finished. State: " << worker->mState << " Discard: " << discard_level << LL_ENDL;
+ worker->unlockWorkMutex();
}
else
{
- worker->lockWorkData();
+ worker->lockWorkMutex();
if ((worker->mDecodedDiscard >= 0) &&
(worker->mDecodedDiscard < discard_level || discard_level < 0) &&
(worker->mState >= LLTextureFetchWorker::WAIT_ON_WRITE))
{
// Not finished, but data is ready
discard_level = worker->mDecodedDiscard;
- if (worker->mRawImage) raw = worker->mRawImage;
- if (worker->mAuxImage) aux = worker->mAuxImage;
+ raw = worker->mRawImage;
+ aux = worker->mAuxImage;
}
- worker->unlockWorkData();
+ worker->unlockWorkMutex();
}
}
else
@@ -1538,9 +1646,9 @@ bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority)
LLTextureFetchWorker* worker = getWorker(id);
if (worker)
{
- worker->lockWorkData();
+ worker->lockWorkMutex();
worker->setImagePriority(priority);
- worker->unlockWorkData();
+ worker->unlockWorkMutex();
res = true;
}
return res;
@@ -1548,40 +1656,116 @@ bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority)
//////////////////////////////////////////////////////////////////////////////
+// MAIN THREAD
//virtual
S32 LLTextureFetch::update(U32 max_time_ms)
{
S32 res;
+
+ mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS");
+
res = LLWorkerThread::update(max_time_ms);
- const F32 REQUEST_TIME = 1.f;
-
- // Periodically, gather the list of textures that need data from the network
- // And send the requests out to the simulators
- if (mNetworkTimer.getElapsedTimeF32() >= REQUEST_TIME)
+ if (!mDebugPause)
{
- mNetworkTimer.reset();
sendRequestListToSimulators();
}
+
+ if (!mThreaded)
+ {
+ // Update Curl on same thread as mCurlGetRequest was constructed
+ S32 processed = mCurlGetRequest->process();
+ if (processed > 0)
+ {
+ lldebugs << "processed: " << processed << " messages." << llendl;
+ }
+ }
return res;
}
+// WORKER THREAD
+void LLTextureFetch::startThread()
+{
+ // Construct mCurlGetRequest from Worker Thread
+ mCurlGetRequest = new LLCurlRequest();
+}
+
+// WORKER THREAD
+void LLTextureFetch::endThread()
+{
+ // Destroy mCurlGetRequest from Worker Thread
+ delete mCurlGetRequest;
+ mCurlGetRequest = NULL;
+}
+
+// WORKER THREAD
+void LLTextureFetch::threadedUpdate()
+{
+ llassert_always(mCurlGetRequest);
+
+ // Limit update frequency
+ const F32 PROCESS_TIME = 0.05f;
+ static LLFrameTimer process_timer;
+ if (process_timer.getElapsedTimeF32() < PROCESS_TIME)
+ {
+ return;
+ }
+ process_timer.reset();
+
+ // Update Curl on same thread as mCurlGetRequest was constructed
+ S32 processed = mCurlGetRequest->process();
+ if (processed > 0)
+ {
+ lldebugs << "processed: " << processed << " messages." << llendl;
+ }
+
+#if 0
+ const F32 INFO_TIME = 1.0f;
+ static LLFrameTimer info_timer;
+ if (info_timer.getElapsedTimeF32() >= INFO_TIME)
+ {
+ S32 q = mCurlGetRequest->getQueued();
+ if (q > 0)
+ {
+ llinfos << "Queued gets: " << q << llendl;
+ info_timer.reset();
+ }
+ }
+#endif
+
+}
+
//////////////////////////////////////////////////////////////////////////////
void LLTextureFetch::sendRequestListToSimulators()
{
+ // All requests
+ const F32 REQUEST_DELTA_TIME = 0.10f; // 10 fps
+
+ // Sim requests
const S32 IMAGES_PER_REQUEST = 50;
- const F32 LAZY_FLUSH_TIMEOUT = 15.f; // 10.0f // temp
+ const F32 SIM_LAZY_FLUSH_TIMEOUT = 10.0f; // temp
const F32 MIN_REQUEST_TIME = 1.0f;
const F32 MIN_DELTA_PRIORITY = 1000.f;
- LLMutexLock lock(&mQueueMutex);
+ // Periodically, gather the list of textures that need data from the network
+ // And send the requests out to the simulators
+ static LLFrameTimer timer;
+ if (timer.getElapsedTimeF32() < REQUEST_DELTA_TIME)
+ {
+ return;
+ }
+ timer.reset();
+ LLMutexLock lock(&mQueueMutex);
+
// Send requests
typedef std::set<LLTextureFetchWorker*,LLTextureFetchWorker::Compare> request_list_t;
typedef std::map< LLHost, request_list_t > work_request_map_t;
work_request_map_t requests;
+ {
+ LLMutexLock lock2(&mNetworkQueueMutex);
for (queue_t::iterator iter = mNetworkQueue.begin(); iter != mNetworkQueue.end(); )
{
queue_t::iterator curiter = iter++;
@@ -1591,65 +1775,65 @@ void LLTextureFetch::sendRequestListToSimulators()
mNetworkQueue.erase(curiter);
continue; // paranoia
}
+ if ((req->mState != LLTextureFetchWorker::LOAD_FROM_NETWORK) &&
+ (req->mState != LLTextureFetchWorker::LOAD_FROM_SIMULATOR))
+ {
+ // We already received our URL, remove from the queue
+ llwarns << "Worker: " << req->mID << " in mNetworkQueue but in wrong state: " << req->mState << llendl;
+ mNetworkQueue.erase(curiter);
+ continue;
+ }
if (req->mID == mDebugID)
{
mDebugCount++; // for setting breakpoints
}
- if (req->mTotalPackets > 0 && req->mLastPacket >= req->mTotalPackets-1)
+ if (req->mSentRequest == LLTextureFetchWorker::SENT_SIM &&
+ req->mTotalPackets > 0 &&
+ req->mLastPacket >= req->mTotalPackets-1)
{
// We have all the packets... make sure this is high priority
// req->setPriority(LLWorkerThread::PRIORITY_HIGH | req->mWorkPriority);
continue;
}
F32 elapsed = req->mRequestedTimer.getElapsedTimeF32();
- F32 delta_priority = llabs(req->mRequestedPriority - req->mImagePriority);
- if ((req->mSimRequestedDiscard != req->mDesiredDiscard) ||
- (delta_priority > MIN_DELTA_PRIORITY && elapsed >= MIN_REQUEST_TIME) ||
- (elapsed >= LAZY_FLUSH_TIMEOUT))
{
- requests[req->mHost].insert(req);
+ F32 delta_priority = llabs(req->mRequestedPriority - req->mImagePriority);
+ if ((req->mSimRequestedDiscard != req->mDesiredDiscard) ||
+ (delta_priority > MIN_DELTA_PRIORITY && elapsed >= MIN_REQUEST_TIME) ||
+ (elapsed >= SIM_LAZY_FLUSH_TIMEOUT))
+ {
+ requests[req->mHost].insert(req);
+ }
}
}
-
- std::string http_url;
-#if 0
- if (gSavedSettings.getBOOL("ImagePipelineUseHTTP"))
- {
- LLViewerRegion* region = gAgent.getRegion();
- if (region)
- {
- http_url = region->getCapability("RequestTextureDownload");
- }
}
-#endif
-
+
for (work_request_map_t::iterator iter1 = requests.begin();
iter1 != requests.end(); ++iter1)
{
- bool use_http = http_url.empty() ? false : true;
LLHost host = iter1->first;
// invalid host = use agent host
if (host == LLHost::invalid)
{
host = gAgent.getRegionHost();
}
- else
- {
- use_http = false;
- }
- if (use_http)
+ S32 sim_request_count = 0;
+
+ for (request_list_t::iterator iter2 = iter1->second.begin();
+ iter2 != iter1->second.end(); ++iter2)
{
- }
- else
- {
- S32 request_count = 0;
- for (request_list_t::iterator iter2 = iter1->second.begin();
- iter2 != iter1->second.end(); ++iter2)
+ LLTextureFetchWorker* req = *iter2;
+ if (gMessageSystem)
{
- LLTextureFetchWorker* req = *iter2;
- req->mSentRequest = LLTextureFetchWorker::SENT_SIM;
- if (0 == request_count)
+ if (req->mSentRequest != LLTextureFetchWorker::SENT_SIM)
+ {
+ // Initialize packet data based on data read from cache
+ req->lockWorkMutex();
+ req->setupPacketData();
+ req->unlockWorkMutex();
+ }
+ if (0 == sim_request_count)
{
gMessageSystem->newMessageFast(_PREHASH_RequestImage);
gMessageSystem->nextBlockFast(_PREHASH_AgentData);
@@ -1666,30 +1850,42 @@ void LLTextureFetch::sendRequestListToSimulators()
// llinfos << "IMAGE REQUEST: " << req->mID << " Discard: " << req->mDesiredDiscard
// << " Packet: " << packet << " Priority: " << req->mImagePriority << llendl;
- req->lockWorkData();
+ if ((gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog")) || (gSavedSettings.getBOOL("LogTextureDownloadsToSimulator")))
+ {
+ mTextureInfo.setRequestStartTime(req->mID, LLTimer::getTotalTime());
+ mTextureInfo.setRequestOffset(req->mID, 0);
+ mTextureInfo.setRequestSize(req->mID, 0);
+ mTextureInfo.setRequestType(req->mID, LLTextureInfoDetails::REQUEST_TYPE_UDP);
+ }
+
+ req->lockWorkMutex();
+ req->mSentRequest = LLTextureFetchWorker::SENT_SIM;
req->mSimRequestedDiscard = req->mDesiredDiscard;
req->mRequestedPriority = req->mImagePriority;
req->mRequestedTimer.reset();
- req->unlockWorkData();
- request_count++;
- if (request_count >= IMAGES_PER_REQUEST)
+ req->unlockWorkMutex();
+ sim_request_count++;
+ if (sim_request_count >= IMAGES_PER_REQUEST)
{
-// llinfos << "REQUESTING " << request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl;
+// llinfos << "REQUESTING " << sim_request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl;
+
gMessageSystem->sendSemiReliable(host, NULL, NULL);
- request_count = 0;
+ sim_request_count = 0;
}
}
- if (request_count > 0 && request_count < IMAGES_PER_REQUEST)
- {
-// llinfos << "REQUESTING " << request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl;
- gMessageSystem->sendSemiReliable(host, NULL, NULL);
- request_count = 0;
- }
+ }
+ if (gMessageSystem && sim_request_count > 0 && sim_request_count < IMAGES_PER_REQUEST)
+ {
+// llinfos << "REQUESTING " << sim_request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl;
+ gMessageSystem->sendSemiReliable(host, NULL, NULL);
+ sim_request_count = 0;
}
}
// Send cancelations
- if (!mCancelQueue.empty())
+ {
+ LLMutexLock lock2(&mNetworkQueueMutex);
+ if (gMessageSystem && !mCancelQueue.empty())
{
for (cancel_queue_t::iterator iter1 = mCancelQueue.begin();
iter1 != mCancelQueue.end(); ++iter1)
@@ -1732,6 +1928,7 @@ void LLTextureFetch::sendRequestListToSimulators()
}
mCancelQueue.clear();
}
+ }
}
//////////////////////////////////////////////////////////////////////////////
@@ -1808,7 +2005,7 @@ bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8
return false;
}
- worker->lockWorkData();
+ worker->lockWorkMutex();
// Copy header data into image object
worker->mImageCodec = codec;
@@ -1819,7 +2016,7 @@ bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8
res = worker->insertPacket(0, data, data_size);
worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority);
worker->mState = LLTextureFetchWorker::LOAD_FROM_SIMULATOR;
- worker->unlockWorkData();
+ worker->unlockWorkMutex();
return res;
}
@@ -1853,7 +2050,7 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1
return false;
}
- worker->lockWorkData();
+ worker->lockWorkMutex();
res = worker->insertPacket(packet_num, data, data_size);
@@ -1866,17 +2063,40 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1
else
{
// llwarns << "receiveImagePacket " << packet_num << "/" << worker->mLastPacket << " for worker: " << id
-// << " in state: " << LLTextureFetchWorker::sStateDescs[worker->mState] << llendl;
- removeFromNetworkQueue(worker); // failsafe
- mCancelQueue[host].insert(id);
+// << " in state: " << LLTextureFetchWorker::sStateDescs[worker->mState] << llendl;
+ removeFromNetworkQueue(worker, true); // failsafe
}
-
- worker->unlockWorkData();
+
+ if(packet_num >= (worker->mTotalPackets - 1))
+ {
+ if ((gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog")) || (gSavedSettings.getBOOL("LogTextureDownloadsToSimulator")))
+ {
+ U64 timeNow = LLTimer::getTotalTime();
+ mTextureInfo.setRequestSize(id, worker->mFileSize);
+ mTextureInfo.setRequestCompleteTimeAndLog(id, timeNow);
+ }
+ }
+ worker->unlockWorkMutex();
return res;
}
//////////////////////////////////////////////////////////////////////////////
+BOOL LLTextureFetch::isFromLocalCache(const LLUUID& id)
+{
+ BOOL from_cache = FALSE ;
+
+ LLMutexLock lock(&mQueueMutex);
+ LLTextureFetchWorker* worker = getWorker(id);
+ if (worker)
+ {
+ worker->lockWorkMutex() ;
+ from_cache = worker->mInLocalCache ;
+ worker->unlockWorkMutex() ;
+ }
+
+ return from_cache ;
+}
S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& requested_priority_p,
U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p)
@@ -1892,7 +2112,7 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r
LLTextureFetchWorker* worker = getWorker(id);
if (worker && worker->haveWork())
{
- worker->lockWorkData();
+ worker->lockWorkMutex();
state = worker->mState;
fetch_dtime = worker->mFetchTimer.getElapsedTimeF32();
request_dtime = worker->mRequestedTimer.getElapsedTimeF32();
@@ -1909,7 +2129,7 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r
data_progress = (F32)worker->mFormattedImage->getDataSize() / (F32)worker->mFileSize;
}
}
- if (state >= LLTextureFetchWorker::LOAD_FROM_NETWORK && state <= LLTextureFetchWorker::LOAD_FROM_HTTP_GET_DATA)
+ if (state >= LLTextureFetchWorker::LOAD_FROM_NETWORK && state <= LLTextureFetchWorker::WAIT_HTTP_REQ)
{
requested_priority = worker->mRequestedPriority;
}
@@ -1918,7 +2138,7 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r
requested_priority = worker->mImagePriority;
}
fetch_priority = worker->getPriority();
- worker->unlockWorkData();
+ worker->unlockWorkMutex();
}
data_progress_p = data_progress;
requested_priority_p = requested_priority;
@@ -1944,5 +2164,3 @@ void LLTextureFetch::dump()
}
}
-
-//////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index 56650e721c..373e38a83c 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -37,26 +37,29 @@
#include "llimage.h"
#include "lluuid.h"
#include "llworkerthread.h"
+#include "llcurl.h"
+#include "lltextureinfo.h"
-class LLViewerImage;
+class LLViewerTexture;
class LLTextureFetchWorker;
+class HTTPGetResponder;
class LLTextureCache;
+class LLImageDecodeThread;
class LLHost;
// Interface class
class LLTextureFetch : public LLWorkerThread
{
friend class LLTextureFetchWorker;
+ friend class HTTPGetResponder;
public:
- LLTextureFetch(LLTextureCache* cache, bool threaded);
+ LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* imagedecodethread, bool threaded);
~LLTextureFetch();
/*virtual*/ S32 update(U32 max_time_ms);
- bool createRequest(const LLUUID& id, const LLHost& host, F32 priority,
- S32 w, S32 h, S32 c, S32 discard, bool needs_aux);
- bool createRequest(const std::string& filename, const LLUUID& id, const LLHost& host, F32 priority,
+ bool createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,
S32 w, S32 h, S32 c, S32 discard, bool needs_aux);
void deleteRequest(const LLUUID& id, bool cancel);
bool getRequestFinished(const LLUUID& id, S32& discard_level,
@@ -66,24 +69,39 @@ public:
bool receiveImageHeader(const LLHost& host, const LLUUID& id, U8 codec, U16 packets, U32 totalbytes, U16 data_size, U8* data);
bool receiveImagePacket(const LLHost& host, const LLUUID& id, U16 packet_num, U16 data_size, U8* data);
+ void setTextureBandwidth(F32 bandwidth) { mTextureBandwidth = bandwidth; }
+ F32 getTextureBandwidth() { return mTextureBandwidth; }
+
// Debug
+ BOOL isFromLocalCache(const LLUUID& id);
S32 getFetchState(const LLUUID& id, F32& decode_progress_p, F32& requested_priority_p,
U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p);
void dump();
S32 getNumRequests() { return mRequestMap.size(); }
+ S32 getNumHTTPRequests() { return mHTTPTextureQueue.size(); }
// Public for access by callbacks
void lockQueue() { mQueueMutex.lock(); }
void unlockQueue() { mQueueMutex.unlock(); }
LLTextureFetchWorker* getWorker(const LLUUID& id);
+
+ LLTextureInfo* getTextureInfo() { return &mTextureInfo; }
protected:
void addToNetworkQueue(LLTextureFetchWorker* worker);
- void removeFromNetworkQueue(LLTextureFetchWorker* worker);
+ void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel);
+ void addToHTTPQueue(const LLUUID& id);
+ void removeFromHTTPQueue(const LLUUID& id);
+ S32 getHTTPQueueSize() { return (S32)mHTTPTextureQueue.size(); }
void removeRequest(LLTextureFetchWorker* worker, bool cancel);
+ // Called from worker thread (during doWork)
+ void processCurlRequests();
private:
void sendRequestListToSimulators();
+ /*virtual*/ void startThread(void);
+ /*virtual*/ void endThread(void);
+ /*virtual*/ void threadedUpdate(void);
public:
LLUUID mDebugID;
@@ -94,8 +112,11 @@ public:
private:
LLMutex mQueueMutex;
+ LLMutex mNetworkQueueMutex;
LLTextureCache* mTextureCache;
+ LLImageDecodeThread* mImageDecodeThread;
+ LLCurlRequest* mCurlGetRequest;
// Map of all requests by UUID
typedef std::map<LLUUID,LLTextureFetchWorker*> map_t;
@@ -104,10 +125,13 @@ private:
// Set of requests that require network data
typedef std::set<LLUUID> queue_t;
queue_t mNetworkQueue;
+ queue_t mHTTPTextureQueue;
typedef std::map<LLHost,std::set<LLUUID> > cancel_queue_t;
cancel_queue_t mCancelQueue;
-
- LLFrameTimer mNetworkTimer;
+ F32 mTextureBandwidth;
+ F32 mMaxBandwidth;
+ LLTextureInfo mTextureInfo;
};
#endif // LL_LLTEXTUREFETCH_H
+
diff --git a/indra/newview/lltextureinfo.cpp b/indra/newview/lltextureinfo.cpp
new file mode 100644
index 0000000000..672a36a8bd
--- /dev/null
+++ b/indra/newview/lltextureinfo.cpp
@@ -0,0 +1,290 @@
+/**
+ * @file lltextureinfo.cpp
+ * @brief Object which handles local texture info
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lltextureinfo.h"
+#include "lltexturestats.h"
+#include "llviewercontrol.h"
+
+LLTextureInfo::LLTextureInfo() :
+ mLogTextureDownloadsToViewerLog(false),
+ mLogTextureDownloadsToSimulator(false),
+ mTotalBytes(0),
+ mTotalMilliseconds(0),
+ mTextureDownloadsStarted(0),
+ mTextureDownloadsCompleted(0),
+ mTextureDownloadProtocol("NONE"),
+ mTextureLogThreshold(100 * 1024),
+ mCurrentStatsBundleStartTime(0)
+{
+ mTextures.clear();
+}
+
+void LLTextureInfo::setUpLogging(bool writeToViewerLog, bool sendToSim, U32 textureLogThreshold)
+{
+ mLogTextureDownloadsToViewerLog = writeToViewerLog;
+ mLogTextureDownloadsToSimulator = sendToSim;
+ mTextureLogThreshold = textureLogThreshold;
+}
+
+LLTextureInfo::~LLTextureInfo()
+{
+ std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator;
+ for (iterator = mTextures.begin(); iterator != mTextures.end(); iterator++)
+ {
+ LLTextureInfoDetails *info = (*iterator).second;
+ delete info;
+ }
+
+ mTextures.clear();
+}
+
+void LLTextureInfo::addRequest(const LLUUID& id)
+{
+ LLTextureInfoDetails *info = new LLTextureInfoDetails();
+ mTextures[id] = info;
+}
+
+U32 LLTextureInfo::getTextureInfoMapSize()
+{
+ return mTextures.size();
+}
+
+bool LLTextureInfo::has(const LLUUID& id)
+{
+ std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id);
+ if (iterator == mTextures.end())
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+void LLTextureInfo::setRequestStartTime(const LLUUID& id, U64 startTime)
+{
+ if (!has(id))
+ {
+ addRequest(id);
+ }
+ mTextures[id]->mStartTime = startTime;
+ mTextureDownloadsStarted++;
+}
+
+void LLTextureInfo::setRequestSize(const LLUUID& id, U32 size)
+{
+ if (!has(id))
+ {
+ addRequest(id);
+ }
+ mTextures[id]->mSize = size;
+}
+
+void LLTextureInfo::setRequestOffset(const LLUUID& id, U32 offset)
+{
+ if (!has(id))
+ {
+ addRequest(id);
+ }
+ mTextures[id]->mOffset = offset;
+}
+
+void LLTextureInfo::setRequestType(const LLUUID& id, LLTextureInfoDetails::LLRequestType type)
+{
+ if (!has(id))
+ {
+ addRequest(id);
+ }
+ mTextures[id]->mType = type;
+}
+
+void LLTextureInfo::setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeTime)
+{
+ if (!has(id))
+ {
+ addRequest(id);
+ }
+ mTextures[id]->mCompleteTime = completeTime;
+
+ std::string protocol = "NONE";
+ switch(mTextures[id]->mType)
+ {
+ case LLTextureInfoDetails::REQUEST_TYPE_HTTP:
+ protocol = "HTTP";
+ break;
+
+ case LLTextureInfoDetails::REQUEST_TYPE_UDP:
+ protocol = "UDP";
+ break;
+
+ case LLTextureInfoDetails::REQUEST_TYPE_NONE:
+ default:
+ break;
+ }
+
+ if (mLogTextureDownloadsToViewerLog)
+ {
+ llinfos << "texture=" << id
+ << " start=" << mTextures[id]->mStartTime
+ << " end=" << mTextures[id]->mCompleteTime
+ << " size=" << mTextures[id]->mSize
+ << " offset=" << mTextures[id]->mOffset
+ << " length_in_ms=" << (mTextures[id]->mCompleteTime - mTextures[id]->mStartTime) / 1000
+ << " protocol=" << protocol
+ << llendl;
+ }
+
+ if(mLogTextureDownloadsToSimulator)
+ {
+ S32 texture_stats_upload_threshold = mTextureLogThreshold;
+ mTotalBytes += mTextures[id]->mSize;
+ mTotalMilliseconds += mTextures[id]->mCompleteTime - mTextures[id]->mStartTime;
+ mTextureDownloadsCompleted++;
+ mTextureDownloadProtocol = protocol;
+ if (mTotalBytes >= texture_stats_upload_threshold)
+ {
+ LLSD texture_data;
+ std::stringstream startTime;
+ startTime << mCurrentStatsBundleStartTime;
+ texture_data["start_time"] = startTime.str();
+ std::stringstream endTime;
+ endTime << completeTime;
+ texture_data["end_time"] = endTime.str();
+ texture_data["averages"] = getAverages();
+ send_texture_stats_to_sim(texture_data);
+ resetTextureStatistics();
+ }
+ }
+
+ mTextures.erase(id);
+}
+
+LLSD LLTextureInfo::getAverages()
+{
+ LLSD averagedTextureData;
+ S32 averageDownloadRate;
+ if(mTotalMilliseconds == 0)
+ {
+ averageDownloadRate = 0;
+ }
+ else
+ {
+ averageDownloadRate = (mTotalBytes * 8) / mTotalMilliseconds;
+ }
+
+ averagedTextureData["bits_per_second"] = averageDownloadRate;
+ averagedTextureData["bytes_downloaded"] = mTotalBytes;
+ averagedTextureData["texture_downloads_started"] = mTextureDownloadsStarted;
+ averagedTextureData["texture_downloads_completed"] = mTextureDownloadsCompleted;
+ averagedTextureData["transport"] = mTextureDownloadProtocol;
+
+ return averagedTextureData;
+}
+
+void LLTextureInfo::resetTextureStatistics()
+{
+ mTotalMilliseconds = 0;
+ mTotalBytes = 0;
+ mTextureDownloadsStarted = 0;
+ mTextureDownloadsCompleted = 0;
+ mTextureDownloadProtocol = "NONE";
+ mCurrentStatsBundleStartTime = LLTimer::getTotalTime();
+}
+
+U32 LLTextureInfo::getRequestStartTime(const LLUUID& id)
+{
+ if (!has(id))
+ {
+ return 0;
+ }
+ else
+ {
+ std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id);
+ return (*iterator).second->mStartTime;
+ }
+}
+
+U32 LLTextureInfo::getRequestSize(const LLUUID& id)
+{
+ if (!has(id))
+ {
+ return 0;
+ }
+ else
+ {
+ std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id);
+ return (*iterator).second->mSize;
+ }
+}
+
+U32 LLTextureInfo::getRequestOffset(const LLUUID& id)
+{
+ if (!has(id))
+ {
+ return 0;
+ }
+ else
+ {
+ std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id);
+ return (*iterator).second->mOffset;
+ }
+}
+
+LLTextureInfoDetails::LLRequestType LLTextureInfo::getRequestType(const LLUUID& id)
+{
+ if (!has(id))
+ {
+ return LLTextureInfoDetails::REQUEST_TYPE_NONE;
+ }
+ else
+ {
+ std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id);
+ return (*iterator).second->mType;
+ }
+}
+
+U32 LLTextureInfo::getRequestCompleteTime(const LLUUID& id)
+{
+ if (!has(id))
+ {
+ return 0;
+ }
+ else
+ {
+ std::map<LLUUID, LLTextureInfoDetails *>::iterator iterator = mTextures.find(id);
+ return (*iterator).second->mCompleteTime;
+ }
+}
+
diff --git a/indra/newview/lltextureinfo.h b/indra/newview/lltextureinfo.h
new file mode 100644
index 0000000000..71b0ea431f
--- /dev/null
+++ b/indra/newview/lltextureinfo.h
@@ -0,0 +1,80 @@
+/**
+ * @file lltextureinfo.h
+ * @brief Object for managing texture information.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTEXTUREINFO_H
+#define LL_LLTEXTUREINFO_H
+
+#include "lluuid.h"
+#include "lltextureinfodetails.h"
+#include <map>
+
+class LLTextureInfo
+{
+public:
+ LLTextureInfo();
+ ~LLTextureInfo();
+
+ void setUpLogging(bool writeToViewerLog, bool sendToSim, U32 textureLogThreshold);
+ bool has(const LLUUID& id);
+ void setRequestStartTime(const LLUUID& id, U64 startTime);
+ void setRequestSize(const LLUUID& id, U32 size);
+ void setRequestOffset(const LLUUID& id, U32 offset);
+ void setRequestType(const LLUUID& id, LLTextureInfoDetails::LLRequestType type);
+ void setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeTime);
+ U32 getRequestStartTime(const LLUUID& id);
+ U32 getRequestSize(const LLUUID& id);
+ U32 getRequestOffset(const LLUUID& id);
+ LLTextureInfoDetails::LLRequestType getRequestType(const LLUUID& id);
+ U32 getRequestCompleteTime(const LLUUID& id);
+ void resetTextureStatistics();
+ U32 getTextureInfoMapSize();
+ LLSD getAverages();
+
+private:
+ void addRequest(const LLUUID& id);
+
+ std::map<LLUUID, LLTextureInfoDetails *> mTextures;
+
+ LLSD mAverages;
+
+ bool mLogTextureDownloadsToViewerLog;
+ bool mLogTextureDownloadsToSimulator;
+ S32 mTotalBytes;
+ S32 mTotalMilliseconds;
+ S32 mTextureDownloadsStarted;
+ S32 mTextureDownloadsCompleted;
+ std::string mTextureDownloadProtocol;
+ U32 mTextureLogThreshold; // in bytes
+ U64 mCurrentStatsBundleStartTime;
+};
+
+#endif // LL_LLTEXTUREINFO_H
diff --git a/indra/newview/lltextureinfodetails.cpp b/indra/newview/lltextureinfodetails.cpp
new file mode 100644
index 0000000000..f6ef47a2ee
--- /dev/null
+++ b/indra/newview/lltextureinfodetails.cpp
@@ -0,0 +1,40 @@
+/**
+ * @file lltextureinfodetails.cpp
+ * @brief Object which handles details of any individual texture
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lltextureinfodetails.h"
+
+LLTextureInfoDetails::LLTextureInfoDetails() : mStartTime(0), mCompleteTime(0), mSize(0), mType(REQUEST_TYPE_NONE), mOffset(0)
+{
+}
+
diff --git a/indra/newview/lltextureinfodetails.h b/indra/newview/lltextureinfodetails.h
new file mode 100644
index 0000000000..091fa01a3d
--- /dev/null
+++ b/indra/newview/lltextureinfodetails.h
@@ -0,0 +1,58 @@
+/**
+ * @file lltextureinfo.h
+ * @brief Object for managing texture information.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTEXTUREINFODETAILS_H
+#define LL_LLTEXTUREINFODETAILS_H
+
+#include "lluuid.h"
+
+class LLTextureInfoDetails
+{
+public:
+ enum LLRequestType
+ {
+ REQUEST_TYPE_NONE,
+ REQUEST_TYPE_HTTP,
+ REQUEST_TYPE_UDP
+ };
+
+ U32 mStartTime;
+ U32 mCompleteTime;
+ U32 mOffset;
+ U32 mSize;
+ LLRequestType mType;
+
+ LLTextureInfoDetails();
+};
+
+#endif // LL_LLTEXTUREINFODETAILS_H
+
diff --git a/indra/newview/lltexturestats.cpp b/indra/newview/lltexturestats.cpp
new file mode 100644
index 0000000000..c91bfd4df2
--- /dev/null
+++ b/indra/newview/lltexturestats.cpp
@@ -0,0 +1,61 @@
+/**
+ * @file lltexturerstats.cpp
+ * @brief texture stats helper methods
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "pipeline.h"
+#include "llagent.h"
+#include "lltexturefetch.h"
+#include "lltexturestats.h"
+#include "lltexturestatsuploader.h"
+#include "llviewerregion.h"
+
+void send_texture_stats_to_sim(const LLSD &texture_stats)
+{
+ LLSD texture_stats_report;
+ // Only send stats if the agent is connected to a region.
+ if (!gAgent.getRegion() || gNoRender)
+ {
+ return;
+ }
+
+ LLUUID agent_id = gAgent.getID();
+ texture_stats_report["agent_id"] = agent_id;
+ texture_stats_report["region_id"] = gAgent.getRegion()->getRegionID();
+ texture_stats_report["stats_data"] = texture_stats;
+
+ std::string texture_cap_url = gAgent.getRegion()->getCapability("TextureStats");
+ LLTextureStatsUploader tsu;
+ llinfos << "uploading texture stats data to simulator" << llendl;
+ tsu.uploadStatsToSimulator(texture_cap_url, texture_stats);
+}
+
diff --git a/indra/newview/lltexturestats.h b/indra/newview/lltexturestats.h
new file mode 100644
index 0000000000..2deb377dfd
--- /dev/null
+++ b/indra/newview/lltexturestats.h
@@ -0,0 +1,41 @@
+/**
+ * @file lltexturestats.h
+ * @brief texture stats utilities
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTEXTURESTATS_H
+#define LL_LLTEXTURESTATS_H
+
+#include "llappviewer.h"
+
+// utility functions to capture data on texture download speeds and send to simulator periodically
+void send_texture_stats_to_sim(const LLSD &texture_stats);
+
+#endif // LL_LLTEXTURESTATS_H
diff --git a/indra/newview/lltexturestatsuploader.cpp b/indra/newview/lltexturestatsuploader.cpp
new file mode 100644
index 0000000000..1df73db9b0
--- /dev/null
+++ b/indra/newview/lltexturestatsuploader.cpp
@@ -0,0 +1,61 @@
+/**
+ * @file lltexturerstats.cpp
+ * @brief texture stats upload class
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lltexturestatsuploader.h"
+
+#include "llhttpclient.h"
+
+LLTextureStatsUploader::LLTextureStatsUploader()
+{
+}
+
+LLTextureStatsUploader::~LLTextureStatsUploader()
+{
+}
+
+void LLTextureStatsUploader::uploadStatsToSimulator(const std::string texture_cap_url, const LLSD &texture_stats)
+{
+ if ( texture_cap_url != "" )
+ {
+ LLHTTPClient::post(texture_cap_url, texture_stats, NULL);
+ }
+ else
+ {
+ llinfos << "Not sending texture stats: "
+ << texture_stats
+ << " as there is no cap url."
+ << llendl;
+ }
+}
+
diff --git a/indra/newview/lltexturestatsuploader.h b/indra/newview/lltexturestatsuploader.h
new file mode 100644
index 0000000000..f6cc8be8fe
--- /dev/null
+++ b/indra/newview/lltexturestatsuploader.h
@@ -0,0 +1,48 @@
+/**
+ * @file lltexturestatsuploader.h
+ * @brief Class to send the texture stats to the simulatore
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTEXTURESTATSUPLOADER_H
+#define LL_LLTEXTURESTATSUPLOADER_H
+
+#include "llappviewer.h"
+
+// utility functions to capture data on texture download speeds and send to simulator periodically
+
+class LLTextureStatsUploader
+{
+public:
+ LLTextureStatsUploader();
+ ~LLTextureStatsUploader();
+ void uploadStatsToSimulator(const std::string texture_cap_url, const LLSD &texture_stats);
+};
+
+#endif // LL_LLTEXTURESTATSUPLOADER_H
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index f00d5e5b48..98731f90f4 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -43,33 +43,36 @@
#include "llimageworker.h"
#include "llrender.h"
-#include "llhoverview.h"
+#include "lltooltip.h"
+#include "llappviewer.h"
#include "llselectmgr.h"
#include "lltexlayer.h"
#include "lltexturecache.h"
#include "lltexturefetch.h"
+#include "llviewercontrol.h"
#include "llviewerobject.h"
-#include "llviewerimage.h"
-#include "llviewerimagelist.h"
-#include "llappviewer.h"
-
+#include "llviewertexture.h"
+#include "llviewertexturelist.h"
+#include "llvovolume.h"
extern F32 texmem_lower_bound_scale;
LLTextureView *gTextureView = NULL;
+LLTextureSizeView *gTextureSizeView = NULL;
+LLTextureSizeView *gTextureCategoryView = NULL;
//static
-std::set<LLViewerImage*> LLTextureView::sDebugImages;
+std::set<LLViewerFetchedTexture*> LLTextureView::sDebugImages;
////////////////////////////////////////////////////////////////////////////
-static std::string title_string1a("Tex UUID Area DDis(Req) DecodePri(Fetch) [download] pk/max");
-static std::string title_string1b("Tex UUID Area DDis(Req) Fetch(DecodePri) [download] pk/max");
+static std::string title_string1a("Tex UUID Area DDis(Req) DecodePri(Fetch) [download] pk/max");
+static std::string title_string1b("Tex UUID Area DDis(Req) Fetch(DecodePri) [download] pk/max");
static std::string title_string2("State");
static std::string title_string3("Pkt Bnd");
static std::string title_string4(" W x H (Dis) Mem");
static S32 title_x1 = 0;
-static S32 title_x2 = 440;
+static S32 title_x2 = 460;
static S32 title_x3 = title_x2 + 40;
static S32 title_x4 = title_x3 + 50;
static S32 texture_bar_height = 8;
@@ -79,16 +82,24 @@ static S32 texture_bar_height = 8;
class LLTextureBar : public LLView
{
public:
- LLPointer<LLViewerImage> mImagep;
+ LLPointer<LLViewerFetchedTexture> mImagep;
S32 mHilite;
public:
- LLTextureBar(const std::string& name, const LLRect& r, LLTextureView* texview)
- : LLView(name, r, FALSE),
- mHilite(0),
- mTextureView(texview)
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
{
- }
+ Mandatory<LLTextureView*> texture_view;
+ Params()
+ : texture_view("texture_view")
+ {
+ mouse_opaque(false);
+ }
+ };
+ LLTextureBar(const Params& p)
+ : LLView(p),
+ mHilite(0),
+ mTextureView(p.texture_view)
+ {}
virtual void draw();
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
@@ -101,8 +112,8 @@ public:
{
LLTextureBar* bar1p = (LLTextureBar*)i1;
LLTextureBar* bar2p = (LLTextureBar*)i2;
- LLViewerImage *i1p = bar1p->mImagep;
- LLViewerImage *i2p = bar2p->mImagep;
+ LLViewerFetchedTexture *i1p = bar1p->mImagep;
+ LLViewerFetchedTexture *i2p = bar2p->mImagep;
F32 pri1 = i1p->getDecodePriority(); // i1p->mRequestedDownloadPriority
F32 pri2 = i2p->getDecodePriority(); // i2p->mRequestedDownloadPriority
if (pri1 > pri2)
@@ -120,10 +131,10 @@ public:
{
LLTextureBar* bar1p = (LLTextureBar*)i1;
LLTextureBar* bar2p = (LLTextureBar*)i2;
- LLViewerImage *i1p = bar1p->mImagep;
- LLViewerImage *i2p = bar2p->mImagep;
- U32 pri1 = i1p->mFetchPriority;
- U32 pri2 = i2p->mFetchPriority;
+ LLViewerFetchedTexture *i1p = bar1p->mImagep;
+ LLViewerFetchedTexture *i2p = bar2p->mImagep;
+ U32 pri1 = i1p->getFetchPriority() ;
+ U32 pri2 = i2p->getFetchPriority() ;
if (pri1 > pri2)
return true;
else if (pri2 > pri1)
@@ -159,7 +170,7 @@ void LLTextureBar::draw()
{
color = LLColor4::green4;
}
- else if (mImagep->getBoostLevel())
+ else if (mImagep->getBoostLevel() > LLViewerTexture::BOOST_NONE)
{
color = LLColor4::magenta;
}
@@ -221,10 +232,10 @@ void LLTextureBar::draw()
{ "DSK", LLColor4::blue }, // CACHE_POST
{ "NET", LLColor4::green }, // LOAD_FROM_NETWORK
{ "SIM", LLColor4::green }, // LOAD_FROM_SIMULATOR
- { "URL", LLColor4::green2 },// LOAD_FROM_HTTP_GET_URL
- { "HTP", LLColor4::green }, // LOAD_FROM_HTTP_GET_DATA
+ { "REQ", LLColor4::yellow },// SEND_HTTP_REQ
+ { "HTP", LLColor4::green }, // WAIT_HTTP_REQ
{ "DEC", LLColor4::yellow },// DECODE_IMAGE
- { "DEC", LLColor4::yellow },// DECODE_IMAGE_UPDATE
+ { "DEC", LLColor4::green }, // DECODE_IMAGE_UPDATE
{ "WRT", LLColor4::purple },// WRITE_TO_CACHE
{ "WRT", LLColor4::orange },// WAIT_ON_WRITE
{ "END", LLColor4::red }, // DONE
@@ -252,7 +263,7 @@ void LLTextureBar::draw()
// Draw the progress bar.
S32 bar_width = 100;
- S32 bar_left = 280;
+ S32 bar_left = 260;
left = bar_left;
right = left + bar_width;
@@ -277,40 +288,41 @@ void LLTextureBar::draw()
S32 pip_x = title_x3 + pip_space/2;
// Draw the packet pip
+ const F32 pip_max_time = 5.f;
F32 last_event = mImagep->mLastPacketTimer.getElapsedTimeF32();
- if (last_event < 1.f)
+ if (last_event < pip_max_time)
{
clr = LLColor4::white;
}
else
{
last_event = mImagep->mRequestDeltaTime;
- if (last_event < 1.f)
+ if (last_event < pip_max_time)
{
clr = LLColor4::green;
}
else
{
last_event = mImagep->mFetchDeltaTime;
- if (last_event < 1.f)
+ if (last_event < pip_max_time)
{
clr = LLColor4::yellow;
}
}
}
- if (last_event < 1.f)
+ if (last_event < pip_max_time)
{
- clr.setAlpha(1.f - last_event);
+ clr.setAlpha(1.f - last_event/pip_max_time);
gGL.color4fv(clr.mV);
gl_rect_2d(pip_x, top, pip_x + pip_width, bottom);
}
pip_x += pip_width + pip_space;
// we don't want to show bind/resident pips for textures using the default texture
- if (mImagep->getHasGLTexture())
+ if (mImagep->hasGLTexture())
{
// Draw the bound pip
- last_event = mImagep->sLastFrameTime - mImagep->mLastBindTime;
+ last_event = mImagep->getTimePassedSinceLastBound();
if (last_event < 1.f)
{
clr = mImagep->getMissed() ? LLColor4::red : LLColor4::magenta1;
@@ -334,7 +346,7 @@ void LLTextureBar::draw()
// draw the image size at the end
{
std::string num_str = llformat("%3dx%3d (%d) %7d", mImagep->getWidth(), mImagep->getHeight(),
- mImagep->getDiscardLevel(), mImagep->mTextureMemory);
+ mImagep->getDiscardLevel(), mImagep->hasGLTexture() ? mImagep->getTextureMemory() : 0);
LLFontGL::getFontMonospace()->renderUTF8(num_str, 0, title_x4, getRect().getHeight(), color,
LLFontGL::LEFT, LLFontGL::TOP);
}
@@ -366,13 +378,21 @@ LLRect LLTextureBar::getRequiredRect()
class LLGLTexMemBar : public LLView
{
public:
- LLGLTexMemBar(const std::string& name, LLTextureView* texview)
- : LLView(name, FALSE),
- mTextureView(texview)
+ struct Params : public LLInitParam::Block<Params, LLView::Params>
{
- S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
- setRect(LLRect(0,0,100,line_height * 4));
- }
+ Mandatory<LLTextureView*> texture_view;
+ Params()
+ : texture_view("texture_view")
+ {
+ S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
+ rect(LLRect(0,0,100,line_height * 4));
+ }
+ };
+
+ LLGLTexMemBar(const Params& p)
+ : LLView(p),
+ mTextureView(p.texture_view)
+ {}
virtual void draw();
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
@@ -384,126 +404,151 @@ private:
void LLGLTexMemBar::draw()
{
- S32 bound_mem = (LLViewerImage::sBoundTextureMemory >> 20);
- S32 max_bound_mem = LLViewerImage::sMaxBoundTextureMem;
- S32 total_mem = (LLViewerImage::sTotalTextureMemory >> 20);
- S32 max_total_mem = LLViewerImage::sMaxTotalTextureMem;
- F32 discard_bias = LLViewerImage::sDesiredDiscardBias;
+ S32 bound_mem = BYTES_TO_MEGA_BYTES(LLViewerTexture::sBoundTextureMemoryInBytes);
+ S32 max_bound_mem = LLViewerTexture::sMaxBoundTextureMemInMegaBytes;
+ S32 total_mem = BYTES_TO_MEGA_BYTES(LLViewerTexture::sTotalTextureMemoryInBytes);
+ S32 max_total_mem = LLViewerTexture::sMaxTotalTextureMemInMegaBytes;
+ F32 discard_bias = LLViewerTexture::sDesiredDiscardBias;
+ F32 cache_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getUsage()) ;
+ F32 cache_max_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getMaxUsage()) ;
S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
-
+ S32 v_offset = (S32)((texture_bar_height + 2.5f) * mTextureView->mNumTextureBars + 2.5f);
//----------------------------------------------------------------------------
LLGLSUIDefault gls_ui;
- F32 text_color[] = {1.f, 1.f, 1.f, 0.75f};
+ LLColor4 text_color(1.f, 1.f, 1.f, 0.75f);
+ LLColor4 color;
std::string text;
- text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB Discard Bias: %.2f",
+ text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
total_mem,
max_total_mem,
bound_mem,
max_bound_mem,
- discard_bias);
+ LLImageRaw::sGlobalRawMemory >> 20, discard_bias,
+ cache_usage, cache_max_usage);
+ //, cache_entries, cache_max_entries
- LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, line_height*3,
- text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*3,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
//----------------------------------------------------------------------------
- S32 bar_left = 380;
+#if 0
+ S32 bar_left = 400;
S32 bar_width = 200;
- S32 top = line_height*3 - 2;
+ S32 top = line_height*3 - 2 + v_offset;
S32 bottom = top - 6;
S32 left = bar_left;
S32 right = left + bar_width;
-
- F32 bar_scale = (F32)bar_width / (max_bound_mem * 1.5f);
+ F32 bar_scale;
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- gGL.color4f(0.5f, 0.5f, 0.5f, 0.75f);
- gl_rect_2d(left, top, right, bottom);
-
+ // GL Mem Bar
+
left = bar_left;
- right = left + llfloor(bound_mem * bar_scale);
- if (bound_mem < llfloor(max_bound_mem * texmem_lower_bound_scale))
- {
- gGL.color4f(0.f, 1.f, 0.f, 0.75f);
- }
- else if (bound_mem < max_bound_mem)
- {
- gGL.color4f(1.f, 1.f, 0.f, 0.75f);
- }
- else
- {
- gGL.color4f(1.f, 0.f, 0.f, 0.75f);
- }
+ text = "GL";
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, line_height*3,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+
+ left = bar_left+20;
+ right = left + bar_width;
+
+ gGL.color4f(0.5f, 0.5f, 0.5f, 0.75f); // grey
gl_rect_2d(left, top, right, bottom);
bar_scale = (F32)bar_width / (max_total_mem * 1.5f);
+ right = left + llfloor(total_mem * bar_scale);
+ right = llclamp(right, bar_left, bar_left + bar_width);
+
+ color = (total_mem < llfloor(max_total_mem * texmem_lower_bound_scale)) ? LLColor4::green :
+ (total_mem < max_total_mem) ? LLColor4::yellow : LLColor4::red;
+ color[VALPHA] = .75f;
+ glColor4fv(color.mV);
- top = bottom - 2;
- bottom = top - 6;
+ gl_rect_2d(left, top, right, bottom); // red/yellow/green
+
+ //
+ bar_left += bar_width + bar_space;
+ //top = bottom - 2; bottom = top - 6;
+
+ // Bound Mem Bar
+
left = bar_left;
- right = left + llfloor(total_mem * bar_scale);
- if (total_mem < llfloor(max_total_mem * texmem_lower_bound_scale))
- {
- gGL.color4f(0.f, 1.f, 0.f, 0.75f);
- }
- else if (total_mem < max_total_mem)
- {
- gGL.color4f(1.f, 1.f, 0.f, 0.75f);
- }
- else
- {
- gGL.color4f(1.f, 0.f, 0.f, 0.75f);
- }
+ text = "GL";
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, line_height*3,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ left = bar_left + 20;
+ right = left + bar_width;
+
+ gGL.color4f(0.5f, 0.5f, 0.5f, 0.75f);
gl_rect_2d(left, top, right, bottom);
+ color = (bound_mem < llfloor(max_bound_mem * texmem_lower_bound_scale)) ? LLColor4::green :
+ (bound_mem < max_bound_mem) ? LLColor4::yellow : LLColor4::red;
+ color[VALPHA] = .75f;
+ glColor4fv(color.mV);
+
+ gl_rect_2d(left, top, right, bottom);
+#else
+ S32 left = 0 ;
+#endif
//----------------------------------------------------------------------------
- text = llformat("Textures: Count: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d IW:%d(%d) RAW:%d mRaw:%d mAux:%d CB:%d",
- gImageList.getNumImages(),
+ text = llformat("Textures: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d RAW:%d HTP:%d DEC:%d CRE:%d",
+ gTextureList.getNumImages(),
LLAppViewer::getTextureFetch()->getNumRequests(), LLAppViewer::getTextureFetch()->getNumDeletes(),
LLAppViewer::getTextureFetch()->mPacketCount, LLAppViewer::getTextureFetch()->mBadPacketCount,
LLAppViewer::getTextureCache()->getNumReads(), LLAppViewer::getTextureCache()->getNumWrites(),
LLLFSThread::sLocal->getPending(),
- LLImageWorker::sCount, LLImageWorker::getWorkerThread()->getNumDeletes(),
- LLImageRaw::sRawImageCount, LLViewerImage::sRawCount, LLViewerImage::sAuxCount,
- gImageList.mCallbackList.size());
+ LLImageRaw::sRawImageCount,
+ LLAppViewer::getTextureFetch()->getNumHTTPRequests(),
+ LLAppViewer::getImageDecodeThread()->getPending(),
+ gTextureList.mCreateTextureList.size());
- LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, line_height*2,
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*2,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
+
+
+ left = 550;
+ F32 bandwidth = LLAppViewer::getTextureFetch()->getTextureBandwidth();
+ F32 max_bandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS");
+ color = bandwidth > max_bandwidth ? LLColor4::red : bandwidth > max_bandwidth*.75f ? LLColor4::yellow : text_color;
+ color[VALPHA] = text_color[VALPHA];
+ text = llformat("BW:%.0f/%.0f",bandwidth, max_bandwidth);
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, v_offset + line_height*2,
+ color, LLFontGL::LEFT, LLFontGL::TOP);
S32 dx1 = 0;
if (LLAppViewer::getTextureFetch()->mDebugPause)
{
- LLFontGL::getFontMonospace()->renderUTF8(std::string("!"), 0, title_x1, line_height,
+ LLFontGL::getFontMonospace()->renderUTF8(std::string("!"), 0, title_x1, v_offset + line_height,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
dx1 += 8;
}
if (mTextureView->mFreezeView)
{
- LLFontGL::getFontMonospace()->renderUTF8(std::string("*"), 0, title_x1, line_height,
+ LLFontGL::getFontMonospace()->renderUTF8(std::string("*"), 0, title_x1, v_offset + line_height,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
dx1 += 8;
}
if (mTextureView->mOrderFetch)
{
- LLFontGL::getFontMonospace()->renderUTF8(title_string1b, 0, title_x1+dx1, line_height,
+ LLFontGL::getFontMonospace()->renderUTF8(title_string1b, 0, title_x1+dx1, v_offset + line_height,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
}
else
{
- LLFontGL::getFontMonospace()->renderUTF8(title_string1a, 0, title_x1+dx1, line_height,
+ LLFontGL::getFontMonospace()->renderUTF8(title_string1a, 0, title_x1+dx1, v_offset + line_height,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
}
- LLFontGL::getFontMonospace()->renderUTF8(title_string2, 0, title_x2, line_height,
+ LLFontGL::getFontMonospace()->renderUTF8(title_string2, 0, title_x2, v_offset + line_height,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
- LLFontGL::getFontMonospace()->renderUTF8(title_string3, 0, title_x3, line_height,
+ LLFontGL::getFontMonospace()->renderUTF8(title_string3, 0, title_x3, v_offset + line_height,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
- LLFontGL::getFontMonospace()->renderUTF8(title_string4, 0, title_x4, line_height,
+ LLFontGL::getFontMonospace()->renderUTF8(title_string4, 0, title_x4, v_offset + line_height,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
}
@@ -520,9 +565,72 @@ LLRect LLGLTexMemBar::getRequiredRect()
}
////////////////////////////////////////////////////////////////////////////
+class LLGLTexSizeBar
+{
+public:
+ LLGLTexSizeBar(S32 index, S32 left, S32 bottom, S32 right, S32 line_height)
+ {
+ mIndex = index ;
+ mLeft = left ;
+ mBottom = bottom ;
+ mRight = right ;
+ mLineHeight = line_height ;
+ mTopLoaded = 0 ;
+ mTopBound = 0 ;
+ mScale = 1.0f ;
+ }
+
+ void setTop(S32 loaded, S32 bound, F32 scale) {mTopLoaded = loaded ; mTopBound = bound; mScale = scale ;}
+
+ void draw();
+ BOOL handleHover(S32 x, S32 y, MASK mask, BOOL set_pick_size) ;
+
+private:
+ S32 mIndex ;
+ S32 mLeft ;
+ S32 mBottom ;
+ S32 mRight ;
+ S32 mTopLoaded ;
+ S32 mTopBound ;
+ S32 mLineHeight ;
+ F32 mScale ;
+};
+
+BOOL LLGLTexSizeBar::handleHover(S32 x, S32 y, MASK mask, BOOL set_pick_size)
+{
+ if(y > mBottom && (y < mBottom + (S32)(mTopLoaded * mScale) || y < mBottom + (S32)(mTopBound * mScale)))
+ {
+ LLImageGL::setCurTexSizebar(mIndex, set_pick_size);
+ }
+ return TRUE ;
+}
+void LLGLTexSizeBar::draw()
+{
+ LLGLSUIDefault gls_ui;
+
+ if(LLImageGL::sCurTexSizeBar == mIndex)
+ {
+ F32 text_color[] = {1.f, 1.f, 1.f, 0.75f};
+ std::string text;
+
+ text = llformat("%d", mTopLoaded) ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, mLeft, mBottom + (S32)(mTopLoaded * mScale) + mLineHeight,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+
+ text = llformat("%d", mTopBound) ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, (mLeft + mRight) / 2, mBottom + (S32)(mTopBound * mScale) + mLineHeight,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ }
+
+ F32 loaded_color[] = {1.0f, 0.0f, 0.0f, 0.75f};
+ F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f};
+ gl_rect_2d(mLeft, mBottom + (S32)(mTopLoaded * mScale), (mLeft + mRight) / 2, mBottom, loaded_color) ;
+ gl_rect_2d((mLeft + mRight) / 2, mBottom + (S32)(mTopBound * mScale), mRight, mBottom, bound_color) ;
+}
+////////////////////////////////////////////////////////////////////////////
-LLTextureView::LLTextureView(const std::string& name, const LLRect& rect)
- : LLContainerView(name, rect),
+LLTextureView::LLTextureView(const LLTextureView::Params& p)
+ : LLContainerView(p),
mFreezeView(FALSE),
mOrderFetch(FALSE),
mPrintList(FALSE),
@@ -541,7 +649,7 @@ LLTextureView::~LLTextureView()
mGLTexMemBar = 0;
}
-typedef std::pair<F32,LLViewerImage*> decode_pair_t;
+typedef std::pair<F32,LLViewerFetchedTexture*> decode_pair_t;
struct compare_decode_pair
{
bool operator()(const decode_pair_t& a, const decode_pair_t& b)
@@ -571,18 +679,19 @@ void LLTextureView::draw()
llinfos << "ID\tMEM\tBOOST\tPRI\tWIDTH\tHEIGHT\tDISCARD" << llendl;
}
- for (LLViewerImageList::image_priority_list_t::iterator iter = gImageList.mImageList.begin();
- iter != gImageList.mImageList.end(); )
+ for (LLViewerTextureList::image_priority_list_t::iterator iter = gTextureList.mImageList.begin();
+ iter != gTextureList.mImageList.end(); )
{
- LLPointer<LLViewerImage> imagep = *iter++;
+ LLPointer<LLViewerFetchedTexture> imagep = *iter++;
S32 cur_discard = imagep->getDiscardLevel();
S32 desired_discard = imagep->mDesiredDiscardLevel;
if (mPrintList)
{
+ S32 tex_mem = imagep->hasGLTexture() ? imagep->getTextureMemory() : 0 ;
llinfos << imagep->getID()
- << "\t" << imagep->mTextureMemory
+ << "\t" << tex_mem
<< "\t" << imagep->getBoostLevel()
<< "\t" << imagep->getDecodePriority()
<< "\t" << imagep->getWidth()
@@ -590,7 +699,13 @@ void LLTextureView::draw()
<< "\t" << cur_discard
<< llendl;
}
-
+
+ if (imagep->getID() == LLAppViewer::getTextureFetch()->mDebugID)
+ {
+ static S32 debug_count = 0;
+ ++debug_count; // for breakpoints
+ }
+
#if 0
if (imagep->getDontDiscard())
{
@@ -627,8 +742,8 @@ void LLTextureView::draw()
{
struct f : public LLSelectedTEFunctor
{
- LLViewerImage* mImage;
- f(LLViewerImage* image) : mImage(image) {}
+ LLViewerFetchedTexture* mImage;
+ f(LLViewerFetchedTexture* image) : mImage(image) {}
virtual bool apply(LLViewerObject* object, S32 te)
{
return (mImage == object->getTEImage(te));
@@ -645,16 +760,20 @@ void LLTextureView::draw()
#if 1
if (pri < HIGH_PRIORITY && (cur_discard< 0 || desired_discard < cur_discard))
{
- LLViewerObject *objectp = gHoverView->getLastHoverObject();
- if (objectp)
+ LLSelectNode* hover_node = LLSelectMgr::instance().getHoverNode();
+ if (hover_node)
{
- S32 tex_count = objectp->getNumTEs();
- for (S32 i = 0; i < tex_count; i++)
+ LLViewerObject *objectp = hover_node->getObject();
+ if (objectp)
{
- if (imagep == objectp->getTEImage(i))
+ S32 tex_count = objectp->getNumTEs();
+ for (S32 i = 0; i < tex_count; i++)
{
- pri += 2*HIGH_PRIORITY;
- break;
+ if (imagep == objectp->getTEImage(i))
+ {
+ pri += 2*HIGH_PRIORITY;
+ break;
+ }
}
}
}
@@ -685,10 +804,11 @@ void LLTextureView::draw()
static S32 max_count = 50;
S32 count = 0;
+ mNumTextureBars = 0 ;
for (display_list_t::iterator iter = display_image_list.begin();
iter != display_image_list.end(); iter++)
{
- LLViewerImage* imagep = iter->second;
+ LLViewerFetchedTexture* imagep = iter->second;
S32 hilite = 0;
F32 pri = iter->first;
if (pri >= 1 * HIGH_PRIORITY)
@@ -709,13 +829,16 @@ void LLTextureView::draw()
else
sortChildren(LLTextureBar::sort());
- mGLTexMemBar = new LLGLTexMemBar("gl texmem bar", this);
+ LLGLTexMemBar::Params tmbp;
+ tmbp.name("gl texmem bar");
+ tmbp.texture_view(this);
+ mGLTexMemBar = LLUICtrlFactory::create<LLGLTexMemBar>(tmbp);
addChild(mGLTexMemBar);
reshape(getRect().getWidth(), getRect().getHeight(), TRUE);
/*
- count = gImageList.getNumImages();
+ count = gTextureList.getNumImages();
std::string info_string;
info_string = llformat("Global Info:\nTexture Count: %d", count);
mInfoTextp->setText(info_string);
@@ -737,7 +860,7 @@ void LLTextureView::draw()
}
-BOOL LLTextureView::addBar(LLViewerImage *imagep, S32 hilite)
+BOOL LLTextureView::addBar(LLViewerFetchedTexture *imagep, S32 hilite)
{
llassert(imagep);
@@ -746,7 +869,11 @@ BOOL LLTextureView::addBar(LLViewerImage *imagep, S32 hilite)
mNumTextureBars++;
- barp = new LLTextureBar("texture bar", r, this);
+ LLTextureBar::Params tbp;
+ tbp.name("texture bar");
+ tbp.rect(r);
+ tbp.texture_view(this);
+ barp = LLUICtrlFactory::create<LLTextureBar>(tbp);
barp->mImagep = imagep;
barp->mHilite = hilite;
@@ -791,4 +918,302 @@ BOOL LLTextureView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
return FALSE;
}
+//-----------------------------------------------------------------
+LLTextureSizeView::LLTextureSizeView(const LLTextureSizeView::Params& p) : LLContainerView(p)
+{
+ setVisible(FALSE) ;
+
+ mTextureSizeBarWidth = 30 ;
+}
+
+LLTextureSizeView::~LLTextureSizeView()
+{
+ if(mTextureSizeBar.size())
+ {
+ for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
+ {
+ delete mTextureSizeBar[i] ;
+ }
+ mTextureSizeBar.clear() ;
+ }
+}
+void LLTextureSizeView::draw()
+{
+ if(mType == TEXTURE_MEM_OVER_SIZE)
+ {
+ drawTextureSizeGraph();
+ }
+ else
+ {
+ drawTextureCategoryGraph() ;
+ }
+
+ LLView::draw();
+}
+
+BOOL LLTextureSizeView::handleHover(S32 x, S32 y, MASK mask)
+{
+ if(x > mTextureSizeBarRect.mLeft && x < mTextureSizeBarRect.mRight)
+ {
+ mTextureSizeBar[(x - mTextureSizeBarRect.mLeft) / mTextureSizeBarWidth]->handleHover(x, y, mask, (mType == TEXTURE_MEM_OVER_SIZE)) ;
+ }
+
+ return TRUE ;
+}
+
+//draw real-time texture mem bar over size
+void LLTextureSizeView::drawTextureSizeGraph()
+{
+ if(mTextureSizeBar.size() == 0)
+ {
+ S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
+ mTextureSizeBar.resize(LLImageGL::sTextureLoadedCounter.size()) ;
+ mTextureSizeBarRect.set(700, line_height * 2 + 400, 700 + mTextureSizeBar.size() * mTextureSizeBarWidth, line_height * 2) ;
+
+ for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
+ {
+ mTextureSizeBar[i] = new LLGLTexSizeBar(i, mTextureSizeBarRect.mLeft + i * mTextureSizeBarWidth ,
+ line_height * 2, mTextureSizeBarRect.mLeft + (i + 1) * mTextureSizeBarWidth, line_height) ;
+ }
+ }
+
+ F32 size_bar_scale = drawTextureSizeDistributionGraph() ;
+ for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
+ {
+ mTextureSizeBar[i]->setTop(LLImageGL::sTextureLoadedCounter[i], LLImageGL::sTextureBoundCounter[i], size_bar_scale) ;
+ mTextureSizeBar[i]->draw() ;
+ }
+ LLImageGL::resetCurTexSizebar();
+}
+
+//draw background of texture size bar graph
+F32 LLTextureSizeView::drawTextureSizeDistributionGraph()
+{
+ //scale
+ F32 scale = 1.0f ;
+
+ LLGLSUIDefault gls_ui;
+
+ {
+ S32 count = 0 ;
+ for(U32 i = 0 ; i < LLImageGL::sTextureLoadedCounter.size() ; i++)
+ {
+ if(LLImageGL::sTextureLoadedCounter[i] > count)
+ {
+ count = LLImageGL::sTextureLoadedCounter[i] ;
+ }
+ }
+ if(count > mTextureSizeBarRect.getHeight())
+ {
+ scale = (F32)mTextureSizeBarRect.getHeight() / count ;
+ }
+ }
+
+ S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
+ S32 left = mTextureSizeBarRect.mLeft ;
+ S32 bottom = mTextureSizeBarRect.mBottom ;
+ S32 right = mTextureSizeBarRect.mRight ;
+ S32 top = mTextureSizeBarRect.mTop ;
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ //background rect
+ gl_rect_2d(left - 25, top + 30, right + 100, bottom - 25, LLColor4(0.0f, 0.0f, 0.0f, 0.25f)) ;
+
+ //--------------------------------------------------
+ gGL.color4f(1.0f, 0.5f, 0.5f, 0.75f);
+ gl_line_2d(left, bottom, right, bottom) ; //x axis
+ gl_line_2d(left, bottom, left, top) ; //y axis
+
+ //ruler
+ //--------------------------------------------------
+ gGL.color4f(1.0f, 0.5f, 0.5f, 0.5f);
+ for(S32 i = bottom + 50 ; i <= top ; i += 50)
+ {
+ gl_line_2d(left, i, right, i) ;
+ }
+
+ //texts
+ //--------------------------------------------------
+ F32 text_color[] = {1.f, 1.f, 1.f, 0.75f};
+ std::string text;
+
+ //-------
+ //x axis: size label
+ text = llformat("%d", 0) ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 12, bottom - line_height / 2,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ for(U32 i = 1 ; i < mTextureSizeBar.size() ; i++)
+ {
+ text = llformat("%d", (1 << (i / 2)) + ((i & 1) ? ((1 << (i / 2)) >> 1) : 0)) ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + i * mTextureSizeBarWidth + 12, bottom - line_height / 2,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ }
+ text = llformat("(w + h)/2") ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 10, bottom - line_height / 2,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ //-------
+
+ //y axis: number label
+ for(S32 i = bottom + 50 ; i <= top ; i += 50)
+ {
+ text = llformat("%d", (S32)((i - bottom) / scale)) ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, i + line_height / 2 ,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 5, i + line_height / 2 ,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ }
+
+ //--------------------------------------------------
+ F32 loaded_color[] = {1.0f, 0.0f, 0.0f, 0.75f};
+ gl_rect_2d(left + 70, top + line_height * 2, left + 90, top + line_height, loaded_color) ;
+ text = llformat("Loaded") ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 100, top + line_height * 2,
+ loaded_color, LLFontGL::LEFT, LLFontGL::TOP);
+
+ F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f};
+ gl_rect_2d(left + 170, top + line_height * 2, left + 190, top + line_height, bound_color) ;
+ text = llformat("Bound") ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 200, top + line_height * 2,
+ bound_color, LLFontGL::LEFT, LLFontGL::TOP);
+
+ //--------------------------------------------------
+
+ //title
+ text = llformat("Texture Size Distribution") ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 250, top + line_height * 3,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ return scale ;
+}
+
+//draw real-time texture mem bar over category
+void LLTextureSizeView::drawTextureCategoryGraph()
+{
+ if(mTextureSizeBar.size() == 0)
+ {
+ S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
+ mTextureSizeBar.resize(LLViewerTexture::getTotalNumOfCategories()) ;
+ mTextureSizeBarRect.set(700, line_height * 2 + 400, 700 + mTextureSizeBar.size() * mTextureSizeBarWidth, line_height * 2) ;
+
+ for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
+ {
+ mTextureSizeBar[i] = new LLGLTexSizeBar(i, mTextureSizeBarRect.mLeft + i * mTextureSizeBarWidth ,
+ line_height * 2, mTextureSizeBarRect.mLeft + (i + 1) * mTextureSizeBarWidth, line_height) ;
+ }
+ }
+
+ F32 size_bar_scale = drawTextureCategoryDistributionGraph() ;
+ for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
+ {
+ U32 k = LLViewerTexture::getIndexFromCategory(i) ;
+ mTextureSizeBar[i]->setTop(LLImageGL::sTextureMemByCategory[k] >> 20, LLImageGL::sTextureMemByCategoryBound[k] >> 20, size_bar_scale) ;
+ mTextureSizeBar[i]->draw() ;
+ }
+ LLImageGL::resetCurTexSizebar();
+}
+
+//draw background for TEXTURE_MEM_OVER_CATEGORY
+F32 LLTextureSizeView::drawTextureCategoryDistributionGraph()
+{
+ //scale
+ F32 scale = 4.0f ;
+
+ LLGLSUIDefault gls_ui;
+
+ {
+ S32 count = 0 ;
+ for(U32 i = 0 ; i < LLImageGL::sTextureMemByCategory.size() ; i++)
+ {
+ S32 tmp = LLImageGL::sTextureMemByCategory[i] >> 20 ;
+ if(tmp > count)
+ {
+ count = tmp ;
+ }
+ }
+ if(count > mTextureSizeBarRect.getHeight() * 0.25f)
+ {
+ scale = (F32)mTextureSizeBarRect.getHeight() * 0.25f / count ;
+ }
+ }
+
+ S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
+ S32 left = mTextureSizeBarRect.mLeft ;
+ S32 bottom = mTextureSizeBarRect.mBottom ;
+ S32 right = mTextureSizeBarRect.mRight ;
+ S32 top = mTextureSizeBarRect.mTop ;
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ //background rect
+ gl_rect_2d(left - 25, top + 30, right + 100, bottom - 25, LLColor4(0.0f, 0.0f, 0.0f, 0.25f)) ;
+
+ //--------------------------------------------------
+ gGL.color4f(1.0f, 0.5f, 0.5f, 0.75f);
+ gl_line_2d(left, bottom, right, bottom) ; //x axis
+ gl_line_2d(left, bottom, left, top) ; //y axis
+
+ //ruler
+ //--------------------------------------------------
+ gGL.color4f(1.0f, 0.5f, 0.5f, 0.5f);
+ for(S32 i = bottom + 50 ; i <= top ; i += 50)
+ {
+ gl_line_2d(left, i, right, i) ;
+ }
+
+ //texts
+ //--------------------------------------------------
+ F32 text_color[] = {1.f, 1.f, 1.f, 0.75f};
+ std::string text;
+
+ //-------
+ //x axis: size label
+ static char category[LLViewerTexture::MAX_GL_IMAGE_CATEGORY][4] =
+ {"Non", "Bak", "Av", "Cld", "Scp", "Hi", "Trn", "Slt", "Hud", "Bsf", "UI", "Pvw", "Map", "Mvs", "Slf", "Loc", "Scr", "Dyn", "Mdi", "ALT", "Oth" } ;
+
+ text = llformat("%s", category[0]) ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 12, bottom - line_height / 2,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ for(U32 i = 1 ; i < mTextureSizeBar.size() ; i++)
+ {
+ text = llformat("%s", category[i]) ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + i * mTextureSizeBarWidth + 12, bottom - line_height / 2,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ }
+ //-------
+
+ //y axis: number label
+ for(S32 i = bottom + 50 ; i <= top ; i += 50)
+ {
+ text = llformat("%d", (S32)((i - bottom) / scale)) ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, i + line_height / 2 ,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 5, i + line_height / 2 ,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ }
+ text = llformat("MB") ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, top + line_height * 2 ,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ //--------------------------------------------------
+ F32 loaded_color[] = {1.0f, 0.0f, 0.0f, 0.75f};
+ gl_rect_2d(left + 70, top + line_height * 2, left + 90, top + line_height, loaded_color) ;
+ text = llformat("Loaded") ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 100, top + line_height * 2,
+ loaded_color,
+ LLFontGL::LEFT, LLFontGL::TOP);
+
+ F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f};
+ gl_rect_2d(left + 170, top + line_height * 2, left + 190, top + line_height, bound_color) ;
+ text = llformat("Bound") ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 200, top + line_height * 2,
+ bound_color, LLFontGL::LEFT, LLFontGL::TOP);
+
+ //--------------------------------------------------
+
+ //title
+ text = llformat("Texture Category Distribution") ;
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 250, top + line_height * 3,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+
+ return scale ;
+}
diff --git a/indra/newview/lltextureview.h b/indra/newview/lltextureview.h
index f91a296b97..435a55df83 100644
--- a/indra/newview/lltextureview.h
+++ b/indra/newview/lltextureview.h
@@ -35,7 +35,7 @@
#include "llcontainerview.h"
-class LLViewerImage;
+class LLViewerFetchedTexture;
class LLTextureBar;
class LLGLTexMemBar;
@@ -43,8 +43,10 @@ class LLTextureView : public LLContainerView
{
friend class LLTextureBar;
friend class LLGLTexMemBar;
+protected:
+ LLTextureView(const Params&);
+ friend class LLUICtrlFactory;
public:
- LLTextureView(const std::string& name, const LLRect& rect);
~LLTextureView();
/*virtual*/ void draw();
@@ -52,12 +54,12 @@ public:
/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
- static void addDebugImage(LLViewerImage* image) { sDebugImages.insert(image); }
- static void removeDebugImage(LLViewerImage* image) { sDebugImages.insert(image); }
+ static void addDebugImage(LLViewerFetchedTexture* image) { sDebugImages.insert(image); }
+ static void removeDebugImage(LLViewerFetchedTexture* image) { sDebugImages.insert(image); }
static void clearDebugImages() { sDebugImages.clear(); }
private:
- BOOL addBar(LLViewerImage *image, BOOL hilight = FALSE);
+ BOOL addBar(LLViewerFetchedTexture *image, BOOL hilight = FALSE);
void removeAllBars();
private:
@@ -73,8 +75,45 @@ private:
LLGLTexMemBar* mGLTexMemBar;
public:
- static std::set<LLViewerImage*> sDebugImages;
+ static std::set<LLViewerFetchedTexture*> sDebugImages;
};
+class LLGLTexSizeBar;
+class LLTextureSizeView : public LLContainerView
+{
+protected:
+ LLTextureSizeView(const Params&);
+ friend class LLUICtrlFactory;
+public:
+ ~LLTextureSizeView();
+
+ /*virtual*/ void draw();
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) ;
+
+ void setType(S32 type) {mType = type ;}
+ enum
+ {
+ TEXTURE_MEM_OVER_SIZE,
+ TEXTURE_MEM_OVER_CATEGORY
+ };
+private:
+ //draw background for TEXTURE_MEM_OVER_SIZE
+ F32 drawTextureSizeDistributionGraph() ;
+ //draw real-time texture mem bar over size
+ void drawTextureSizeGraph();
+
+ //draw background for TEXTURE_MEM_OVER_CATEGORY
+ F32 drawTextureCategoryDistributionGraph() ;
+ //draw real-time texture mem bar over category
+ void drawTextureCategoryGraph();
+
+private:
+ std::vector<LLGLTexSizeBar*> mTextureSizeBar ;
+ LLRect mTextureSizeBarRect ;
+ S32 mTextureSizeBarWidth ;
+ S32 mType ;
+};
extern LLTextureView *gTextureView;
+extern LLTextureSizeView *gTextureSizeView;
+extern LLTextureSizeView *gTextureCategoryView;
#endif // LL_TEXTURE_VIEW_H
diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp
new file mode 100644
index 0000000000..110d158e2d
--- /dev/null
+++ b/indra/newview/lltoast.cpp
@@ -0,0 +1,342 @@
+/**
+ * @file lltoast.cpp
+ * @brief This class implements a placeholder for any notification panel.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#include "lltoast.h"
+
+#include "llbutton.h"
+#include "llfocusmgr.h"
+#include "llnotifications.h"
+#include "llviewercontrol.h"
+
+using namespace LLNotificationsUI;
+
+//--------------------------------------------------------------------------
+LLToast::Params::Params()
+: can_fade("can_fade", true),
+ can_be_stored("can_be_stored", true),
+ is_modal("is_modal", false),
+ is_tip("is_tip", false),
+ enable_hide_btn("enable_hide_btn", true),
+ force_show("force_show", false),
+ force_store("force_store", false),
+ fading_time_secs("fading_time_secs", gSavedSettings.getS32("ToastFadingTime")),
+ lifetime_secs("lifetime_secs", gSavedSettings.getS32("NotificationToastLifeTime"))
+{};
+
+LLToast::LLToast(const LLToast::Params& p)
+: LLModalDialog(LLSD(), p.is_modal),
+ mPanel(p.panel),
+ mToastLifetime(p.lifetime_secs),
+ mToastFadingTime(p.fading_time_secs),
+ mNotificationID(p.notif_id),
+ mSessionID(p.session_id),
+ mCanFade(p.can_fade),
+ mCanBeStored(p.can_be_stored),
+ mHideBtnEnabled(p.enable_hide_btn),
+ mHideBtn(NULL),
+ mNotification(p.notification),
+ mIsHidden(false),
+ mHideBtnPressed(false),
+ mIsTip(p.is_tip)
+{
+ LLUICtrlFactory::getInstance()->buildFloater(this, "panel_toast.xml", NULL);
+
+ setCanDrag(FALSE);
+
+ if(mPanel)
+ {
+ insertPanel(mPanel);
+ }
+
+ if(mHideBtnEnabled)
+ {
+ mHideBtn = getChild<LLButton>("hide_btn");
+ mHideBtn->setClickedCallback(boost::bind(&LLToast::hide,this));
+ }
+
+ // init callbacks if present
+ if(!p.on_delete_toast().empty())
+ mOnDeleteToastSignal.connect(p.on_delete_toast());
+
+ if(!p.on_mouse_enter().empty())
+ mOnMouseEnterSignal.connect(p.on_mouse_enter());
+}
+
+//--------------------------------------------------------------------------
+BOOL LLToast::postBuild()
+{
+ if(!mCanFade)
+ {
+ mTimer.stop();
+ }
+
+ if (mIsTip)
+ {
+ mTextEditor = mPanel->getChild<LLTextEditor>("text_editor_box");
+
+ if (mTextEditor)
+ {
+ mTextEditor->setMouseUpCallback(boost::bind(&LLToast::hide,this));
+ mPanel->setMouseUpCallback(boost::bind(&LLToast::handleTipToastClick, this, _2, _3, _4));
+ }
+ }
+
+ return TRUE;
+}
+
+//--------------------------------------------------------------------------
+void LLToast::handleTipToastClick(S32 x, S32 y, MASK mask)
+{
+ if (!mTextEditor->getRect().pointInRect(x, y))
+ {
+ hide();
+ }
+}
+
+//--------------------------------------------------------------------------
+void LLToast::setHideButtonEnabled(bool enabled)
+{
+ if(mHideBtn)
+ mHideBtn->setEnabled(enabled);
+}
+
+//--------------------------------------------------------------------------
+LLToast::~LLToast()
+{
+ mOnToastDestroyedSignal(this);
+}
+
+//--------------------------------------------------------------------------
+void LLToast::setAndStartTimer(F32 period)
+{
+ if(mCanFade)
+ {
+ mToastLifetime = period;
+ mTimer.start();
+ }
+}
+
+//--------------------------------------------------------------------------
+bool LLToast::lifetimeHasExpired()
+{
+ if (mTimer.getStarted())
+ {
+ F32 elapsed_time = mTimer.getElapsedTimeF32();
+ if ((mToastLifetime - elapsed_time) <= mToastFadingTime)
+ {
+ setBackgroundOpaque(FALSE);
+ }
+ if (elapsed_time > mToastLifetime)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+//--------------------------------------------------------------------------
+void LLToast::hide()
+{
+ setVisible(FALSE);
+ mTimer.stop();
+ mIsHidden = true;
+ mOnFadeSignal(this);
+}
+
+//--------------------------------------------------------------------------
+void LLToast::setCanFade(bool can_fade)
+{
+ mCanFade = can_fade;
+ if(!mCanFade)
+ mTimer.stop();
+}
+
+//--------------------------------------------------------------------------
+void LLToast::tick()
+{
+ if(mCanFade)
+ {
+ hide();
+ }
+}
+
+//--------------------------------------------------------------------------
+
+void LLToast::reshapeToPanel()
+{
+ LLPanel* panel = getPanel();
+ if(!panel)
+ return;
+
+ LLRect panel_rect;
+
+ panel_rect = panel->getRect();
+ reshape(panel_rect.getWidth(), panel_rect.getHeight());
+ panel_rect.setLeftTopAndSize(0, panel_rect.getHeight(), panel_rect.getWidth(), panel_rect.getHeight());
+ panel->setRect(panel_rect);
+
+ LLRect toast_rect = getRect();
+ toast_rect.setLeftTopAndSize(toast_rect.mLeft,toast_rect.mTop,panel_rect.getWidth(), panel_rect.getHeight());
+ setRect(toast_rect);
+
+}
+
+void LLToast::insertPanel(LLPanel* panel)
+{
+ addChild(panel);
+ reshapeToPanel();
+}
+
+//--------------------------------------------------------------------------
+void LLToast::draw()
+{
+ if(lifetimeHasExpired())
+ {
+ tick();
+ }
+
+ LLFloater::draw();
+}
+
+//--------------------------------------------------------------------------
+void LLToast::setVisible(BOOL show)
+{
+ if(mIsHidden)
+ {
+ // this toast is invisible after fade until its ScreenChannel will allow it
+ //
+ // (EXT-1849) according to this bug a toast can be resurrected from
+ // invisible state if it faded during a teleportation
+ // then it fades a second time and causes a crash
+ return;
+ }
+
+ if(show)
+ {
+ setBackgroundOpaque(TRUE);
+ if(!mTimer.getStarted() && mCanFade)
+ {
+ mTimer.start();
+ }
+ LLModalDialog::setFrontmost(FALSE);
+ }
+ LLFloater::setVisible(show);
+ if(mPanel)
+ {
+ if(!mPanel->isDead())
+ {
+ mPanel->setVisible(show);
+ }
+ }
+}
+
+//--------------------------------------------------------------------------
+void LLToast::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+ mOnToastHoverSignal(this, MOUSE_ENTER);
+
+ setBackgroundOpaque(TRUE);
+
+ //toasts fading is management by Screen Channel
+
+ sendChildToFront(mHideBtn);
+ if(mHideBtn && mHideBtn->getEnabled())
+ mHideBtn->setVisible(TRUE);
+ mOnMouseEnterSignal(this);
+
+ LLModalDialog::onMouseEnter(x, y, mask);
+}
+
+//--------------------------------------------------------------------------
+void LLToast::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ mOnToastHoverSignal(this, MOUSE_LEAVE);
+
+ //toasts fading is management by Screen Channel
+
+ if(mHideBtn && mHideBtn->getEnabled())
+ {
+ if( mHideBtnPressed )
+ {
+ mHideBtnPressed = false;
+ return;
+ }
+ mHideBtn->setVisible(FALSE);
+ }
+
+ LLModalDialog::onMouseLeave(x, y, mask);
+}
+
+
+void LLNotificationsUI::LLToast::stopFading()
+{
+ if(mCanFade)
+ {
+ stopTimer();
+ }
+}
+
+void LLNotificationsUI::LLToast::startFading()
+{
+ if(mCanFade)
+ {
+ resetTimer();
+ }
+}
+
+//--------------------------------------------------------------------------
+
+BOOL LLToast::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ if(mHideBtn && mHideBtn->getEnabled())
+ {
+ mHideBtnPressed = mHideBtn->getRect().pointInRect(x, y);
+ }
+
+ return LLFloater::handleMouseDown(x, y, mask);
+}
+
+//--------------------------------------------------------------------------
+bool LLToast::isNotificationValid()
+{
+ if(mNotification)
+ {
+ return !mNotification->isCancelled();
+ }
+ return false;
+}
+
+//--------------------------------------------------------------------------
+
+
diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h
new file mode 100644
index 0000000000..3d25fd4f02
--- /dev/null
+++ b/indra/newview/lltoast.h
@@ -0,0 +1,190 @@
+/**
+ * @file lltoast.h
+ * @brief This class implements a placeholder for any notification panel.
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTOAST_H
+#define LL_LLTOAST_H
+
+
+#include "llpanel.h"
+#include "llmodaldialog.h"
+#include "lltimer.h"
+#include "llnotificationptr.h"
+
+#include "llviewercontrol.h"
+#include "lltexteditor.h"
+
+#define MOUSE_LEAVE false
+#define MOUSE_ENTER true
+
+namespace LLNotificationsUI
+{
+
+/**
+ * Represents toast pop-up.
+ * This is a parent view for all toast panels.
+ */
+class LLToast : public LLModalDialog
+{
+public:
+ typedef boost::function<void (LLToast* toast)> toast_callback_t;
+ typedef boost::signals2::signal<void (LLToast* toast)> toast_signal_t;
+
+ struct Params : public LLInitParam::Block<Params>
+ {
+ Mandatory<LLPanel*> panel;
+ Optional<LLUUID> notif_id, //notification ID
+ session_id; //im session ID
+ Optional<LLNotificationPtr> notification;
+ Optional<F32> lifetime_secs,
+ fading_time_secs; // Number of seconds while a toast is fading
+ Optional<toast_callback_t> on_delete_toast,
+ on_mouse_enter;
+ Optional<bool> can_fade,
+ can_be_stored,
+ enable_hide_btn,
+ is_modal,
+ is_tip,
+ force_show,
+ force_store;
+
+
+ Params();
+ };
+
+ LLToast(const LLToast::Params& p);
+ virtual ~LLToast();
+ BOOL postBuild();
+
+ // Toast handlers
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ virtual void onMouseEnter(S32 x, S32 y, MASK mask);
+ virtual void onMouseLeave(S32 x, S32 y, MASK mask);
+
+ //Fading
+
+ /** Stop fading timer */
+ virtual void stopFading();
+
+ /** Start fading timer */
+ virtual void startFading();
+
+
+ // Operating with toasts
+ // insert a panel to a toast
+ void insertPanel(LLPanel* panel);
+
+ void reshapeToPanel();
+
+ // get toast's panel
+ LLPanel* getPanel() { return mPanel; }
+ // enable/disable Toast's Hide button
+ void setHideButtonEnabled(bool enabled);
+ // initialize and start Toast's timer
+ void setAndStartTimer(F32 period);
+ //
+ void resetTimer() { mTimer.start(); }
+ //
+ void stopTimer() { mTimer.stop(); }
+ //
+ virtual void draw();
+ //
+ virtual void setVisible(BOOL show);
+ //
+ virtual void hide();
+
+
+
+ // get/set Toast's flags or states
+ // get information whether the notification corresponding to the toast is valid or not
+ bool isNotificationValid();
+ // get toast's Notification ID
+ const LLUUID getNotificationID() { return mNotificationID;}
+ // get toast's Session ID
+ const LLUUID getSessionID() { return mSessionID;}
+ //
+ void setCanFade(bool can_fade);
+ //
+ void setCanBeStored(bool can_be_stored) { mCanBeStored = can_be_stored; }
+ //
+ bool getCanBeStored() { return mCanBeStored; }
+ // set whether this toast considered as hidden or not
+ void setIsHidden( bool is_toast_hidden ) { mIsHidden = is_toast_hidden; }
+
+ const LLNotificationPtr& getNotification() { return mNotification;}
+
+ // Registers signals/callbacks for events
+ toast_signal_t mOnFadeSignal;
+ toast_signal_t mOnMouseEnterSignal;
+ toast_signal_t mOnDeleteToastSignal;
+ toast_signal_t mOnToastDestroyedSignal;
+ boost::signals2::connection setOnFadeCallback(toast_callback_t cb) { return mOnFadeSignal.connect(cb); }
+ boost::signals2::connection setOnToastDestroyedCallback(toast_callback_t cb) { return mOnToastDestroyedSignal.connect(cb); }
+
+ typedef boost::function<void (LLToast* toast, bool mouse_enter)> toast_hover_check_callback_t;
+ typedef boost::signals2::signal<void (LLToast* toast, bool mouse_enter)> toast_hover_check_signal_t;
+ toast_hover_check_signal_t mOnToastHoverSignal;
+ boost::signals2::connection setOnToastHoverCallback(toast_hover_check_callback_t cb) { return mOnToastHoverSignal.connect(cb); }
+
+
+private:
+
+ void handleTipToastClick(S32 x, S32 y, MASK mask);
+
+ // check timer
+ bool lifetimeHasExpired();
+ // on timer finished function
+ void tick();
+
+ LLUUID mNotificationID;
+ LLUUID mSessionID;
+ LLNotificationPtr mNotification;
+
+ // timer counts a lifetime of a toast
+ LLTimer mTimer;
+ F32 mToastLifetime; // in seconds
+ F32 mToastFadingTime; // in seconds
+
+ LLPanel* mPanel;
+ LLButton* mHideBtn;
+ LLTextEditor* mTextEditor;
+
+ LLColor4 mBgColor;
+ bool mCanFade;
+ bool mCanBeStored;
+ bool mHideBtnEnabled;
+ bool mHideBtnPressed;
+ bool mIsHidden; // this flag is TRUE when a toast has faded or was hidden with (x) button (EXT-1849)
+ bool mIsTip;
+};
+
+}
+#endif
diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp
new file mode 100644
index 0000000000..c3ccb9380b
--- /dev/null
+++ b/indra/newview/lltoastalertpanel.cpp
@@ -0,0 +1,485 @@
+/**
+ * @file lltoastalertpanel.cpp
+ * @brief Panel for alert toasts.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#include "linden_common.h"
+
+#include "llboost.h"
+
+#include "lltoastalertpanel.h"
+#include "llfontgl.h"
+#include "lltextbox.h"
+#include "llbutton.h"
+#include "llcheckboxctrl.h"
+#include "llkeyboard.h"
+#include "llfocusmgr.h"
+#include "lliconctrl.h"
+#include "llui.h"
+#include "lllineeditor.h"
+#include "lluictrlfactory.h"
+#include "llnotifications.h"
+#include "llfunctorregistry.h"
+#include "llrootview.h"
+
+const S32 MAX_ALLOWED_MSG_WIDTH = 400;
+const F32 DEFAULT_BUTTON_DELAY = 0.5f;
+const S32 MSG_PAD = 8;
+
+/*static*/ LLControlGroup* LLToastAlertPanel::sSettings = NULL;
+/*static*/ LLToastAlertPanel::URLLoader* LLToastAlertPanel::sURLLoader;
+
+//-----------------------------------------------------------------------------
+// Private methods
+
+static const S32 VPAD = 16;
+static const S32 HPAD = 25;
+static const S32 BTN_HPAD = 8;
+
+LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal)
+ : LLToastPanel(notification),
+ mDefaultOption( 0 ),
+ mCheck(NULL),
+ mCaution(notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH),
+ mLabel(notification->getName()),
+ mLineEditor(NULL)
+{
+ const LLFontGL* font = LLFontGL::getFontSansSerif();
+ const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f);
+ const S32 EDITOR_HEIGHT = 20;
+
+ LLNotificationFormPtr form = mNotification->getForm();
+ std::string edit_text_name;
+ std::string edit_text_contents;
+ bool is_password = false;
+
+ LLToastPanel::setBackgroundVisible(FALSE);
+ LLToastPanel::setBackgroundOpaque(TRUE);
+
+
+ typedef std::vector<std::pair<std::string, std::string> > options_t;
+ options_t supplied_options;
+
+ // for now, get LLSD to iterator over form elements
+ LLSD form_sd = form->asLLSD();
+
+ S32 option_index = 0;
+ for (LLSD::array_const_iterator it = form_sd.beginArray(); it != form_sd.endArray(); ++it)
+ {
+ std::string type = (*it)["type"].asString();
+ if (type == "button")
+ {
+ if((*it)["default"])
+ {
+ mDefaultOption = option_index;
+ }
+
+ supplied_options.push_back(std::make_pair((*it)["name"].asString(), (*it)["text"].asString()));
+
+ ButtonData data;
+ if (option_index == mNotification->getURLOption())
+ {
+ data.mURL = mNotification->getURL();
+ data.mURLExternal = mNotification->getURLOpenExternally();
+ }
+
+ mButtonData.push_back(data);
+ option_index++;
+ }
+ else if (type == "text")
+ {
+ edit_text_contents = (*it)["value"].asString();
+ edit_text_name = (*it)["name"].asString();
+ }
+ else if (type == "password")
+ {
+ edit_text_contents = (*it)["value"].asString();
+ edit_text_name = (*it)["name"].asString();
+ is_password = true;
+ }
+ }
+
+ // Buttons
+ options_t options;
+ if (supplied_options.empty())
+ {
+ options.push_back(std::make_pair(std::string("close"), LLNotifications::instance().getGlobalString("implicitclosebutton")));
+
+ // add data for ok button.
+ ButtonData ok_button;
+ mButtonData.push_back(ok_button);
+ mDefaultOption = 0;
+ }
+ else
+ {
+ options = supplied_options;
+ }
+
+ S32 num_options = options.size();
+
+ // Calc total width of buttons
+ S32 button_width = 0;
+ S32 sp = font->getWidth(std::string("OO"));
+ for( S32 i = 0; i < num_options; i++ )
+ {
+ S32 w = S32(font->getWidth( options[i].second ) + 0.99f) + sp + 2 * LLBUTTON_H_PAD;
+ button_width = llmax( w, button_width );
+ }
+ S32 btn_total_width = button_width;
+ if( num_options > 1 )
+ {
+ btn_total_width = (num_options * button_width) + ((num_options - 1) * BTN_HPAD);
+ }
+
+ // Message: create text box using raw string, as text has been structure deliberately
+ // Use size of created text box to generate dialog box size
+ std::string msg = mNotification->getMessage();
+ llwarns << "Alert: " << msg << llendl;
+ LLTextBox::Params params;
+ params.name("Alert message");
+ params.font(font);
+ params.tab_stop(false);
+ params.wrap(true);
+ params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP);
+
+ LLTextBox * msg_box = LLUICtrlFactory::create<LLTextBox> (params);
+ // Compute max allowable height for the dialog text, so we can allocate
+ // space before wrapping the text to fit.
+ S32 max_allowed_msg_height =
+ gFloaterView->getRect().getHeight()
+ - LINE_HEIGHT // title bar
+ - 3*VPAD - BTN_HEIGHT;
+ msg_box->reshape( MAX_ALLOWED_MSG_WIDTH, max_allowed_msg_height );
+ msg_box->setValue(msg);
+ msg_box->reshapeToFitText();
+
+ const LLRect& text_rect = msg_box->getRect();
+ S32 dialog_width = llmax( btn_total_width, text_rect.getWidth() ) + 2 * HPAD;
+ S32 dialog_height = text_rect.getHeight() + 3 * VPAD + BTN_HEIGHT;
+
+ if (hasTitleBar())
+ {
+ dialog_height += LINE_HEIGHT; // room for title bar
+ }
+
+ // it's ok for the edit text body to be empty, but we want the name to exist if we're going to draw it
+ if (!edit_text_name.empty())
+ {
+ dialog_height += EDITOR_HEIGHT + VPAD;
+ dialog_width = llmax(dialog_width, (S32)(font->getWidth( edit_text_contents ) + 0.99f));
+ }
+
+ if (mCaution)
+ {
+ // Make room for the caution icon.
+ dialog_width += 32 + HPAD;
+ }
+
+ LLToastPanel::reshape( dialog_width, dialog_height, FALSE );
+
+ S32 msg_y = LLToastPanel::getRect().getHeight() - VPAD;
+ S32 msg_x = HPAD;
+ if (hasTitleBar())
+ {
+ msg_y -= LINE_HEIGHT; // room for title
+ }
+
+ static LLUIColor alert_caution_text_color = LLUIColorTable::instance().getColor("AlertCautionTextColor");
+ static LLUIColor alert_text_color = LLUIColorTable::instance().getColor("AlertTextColor");
+ if (mCaution)
+ {
+ LLIconCtrl* icon = LLUICtrlFactory::getInstance()->createFromFile<LLIconCtrl>("alert_icon.xml", this, LLPanel::child_registry_t::instance());
+ if(icon)
+ {
+ icon->setRect(LLRect(msg_x, msg_y, msg_x+32, msg_y-32));
+ LLToastPanel::addChild(icon);
+ }
+
+ msg_x += 32 + HPAD;
+ msg_box->setColor( alert_caution_text_color );
+ }
+ else
+ {
+ msg_box->setColor( alert_text_color );
+ }
+
+ LLRect rect;
+ rect.setLeftTopAndSize( msg_x, msg_y, text_rect.getWidth(), text_rect.getHeight() );
+ msg_box->setRect( rect );
+ LLToastPanel::addChild(msg_box);
+
+ // Buttons
+ S32 button_left = (LLToastPanel::getRect().getWidth() - btn_total_width) / 2;
+
+ for( S32 i = 0; i < num_options; i++ )
+ {
+ LLRect button_rect;
+
+ LLButton* btn = LLUICtrlFactory::getInstance()->createFromFile<LLButton>("alert_button.xml", this, LLPanel::child_registry_t::instance());
+ if(btn)
+ {
+ btn->setName(options[i].first);
+ btn->setRect(button_rect.setOriginAndSize( button_left, VPAD, button_width, BTN_HEIGHT ));
+ btn->setLabel(options[i].second);
+ btn->setFont(font);
+
+ btn->setClickedCallback(boost::bind(&LLToastAlertPanel::onButtonPressed, this, _2, i));
+
+ mButtonData[i].mButton = btn;
+
+ LLToastPanel::addChild(btn);
+
+ if( i == mDefaultOption )
+ {
+ btn->setFocus(TRUE);
+ }
+ }
+ button_left += button_width + BTN_HPAD;
+ }
+
+ // (Optional) Edit Box
+ if (!edit_text_name.empty())
+ {
+ S32 y = VPAD + BTN_HEIGHT + VPAD/2;
+ mLineEditor = LLUICtrlFactory::getInstance()->createFromFile<LLLineEditor>("alert_line_editor.xml", this, LLPanel::child_registry_t::instance());
+
+ if (mLineEditor)
+ {
+ LLRect leditor_rect = LLRect( HPAD, y+EDITOR_HEIGHT, dialog_width-HPAD, y);
+ mLineEditor->setName(edit_text_name);
+ mLineEditor->reshape(leditor_rect.getWidth(), leditor_rect.getHeight());
+ mLineEditor->setRect(leditor_rect);
+ mLineEditor->setText(edit_text_contents);
+ mLineEditor->setMaxTextLength(STD_STRING_STR_LEN - 1);
+
+ // make sure all edit keys get handled properly (DEV-22396)
+ mLineEditor->setHandleEditKeysDirectly(TRUE);
+
+ LLToastPanel::addChild(mLineEditor);
+
+ mLineEditor->setDrawAsterixes(is_password);
+
+ setEditTextArgs(notification->getSubstitutions());
+ }
+ }
+
+ std::string ignore_label;
+
+ if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE)
+ {
+ setCheckBox(LLNotifications::instance().getGlobalString("skipnexttime"), ignore_label);
+ }
+ else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
+ {
+ setCheckBox(LLNotifications::instance().getGlobalString("alwayschoose"), ignore_label);
+ }
+
+ // *TODO: check necessity of this code
+ //gFloaterView->adjustToFitScreen(this, FALSE);
+ if (mLineEditor)
+ {
+ mLineEditor->selectAll();
+ }
+ if(mDefaultOption >= 0)
+ {
+ // delay before enabling default button
+ mDefaultBtnTimer.start();
+ mDefaultBtnTimer.setTimerExpirySec(DEFAULT_BUTTON_DELAY);
+ }
+}
+
+bool LLToastAlertPanel::setCheckBox( const std::string& check_title, const std::string& check_control )
+{
+ mCheck = LLUICtrlFactory::getInstance()->createFromFile<LLCheckBoxCtrl>("alert_check_box.xml", this, LLPanel::child_registry_t::instance());
+
+ if(!mCheck)
+ {
+ return false;
+ }
+
+ const LLFontGL* font = mCheck->getFont();
+ const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f);
+
+ // Extend dialog for "check next time"
+ S32 max_msg_width = LLToastPanel::getRect().getWidth() - 2 * HPAD;
+ S32 check_width = S32(font->getWidth(check_title) + 0.99f) + 16;
+ max_msg_width = llmax(max_msg_width, check_width);
+ S32 dialog_width = max_msg_width + 2 * HPAD;
+
+ S32 dialog_height = LLToastPanel::getRect().getHeight();
+ dialog_height += LINE_HEIGHT;
+ dialog_height += LINE_HEIGHT / 2;
+
+ LLToastPanel::reshape( dialog_width, dialog_height, FALSE );
+
+ S32 msg_x = (LLToastPanel::getRect().getWidth() - max_msg_width) / 2;
+
+ // set check_box's attributes
+ LLRect check_rect;
+ mCheck->setRect(check_rect.setOriginAndSize(msg_x, VPAD+BTN_HEIGHT+LINE_HEIGHT/2, max_msg_width, LINE_HEIGHT));
+ mCheck->setLabel(check_title);
+ mCheck->setCommitCallback(boost::bind(&LLToastAlertPanel::onClickIgnore, this, _1));
+
+ LLToastPanel::addChild(mCheck);
+
+ return true;
+}
+
+void LLToastAlertPanel::setVisible( BOOL visible )
+{
+ // only make the "ding" sound if it's newly visible
+ if( visible && !LLToastPanel::getVisible() )
+ {
+ make_ui_sound("UISndAlert");
+ }
+
+ LLToastPanel::setVisible( visible );
+
+}
+
+LLToastAlertPanel::~LLToastAlertPanel()
+{
+}
+
+BOOL LLToastAlertPanel::hasTitleBar() const
+{
+ // *TODO: check necessity of this code
+ /*
+ return (getCurrentTitle() != "" && getCurrentTitle() != " ") // has title
+ || isMinimizeable()
+ || isCloseable();
+ */
+ return false;
+}
+
+BOOL LLToastAlertPanel::handleKeyHere(KEY key, MASK mask )
+{
+ if( KEY_RETURN == key && mask == MASK_NONE )
+ {
+ LLButton* defaultBtn = getDefaultButton();
+ if(defaultBtn && defaultBtn->getVisible() && defaultBtn->getEnabled())
+ {
+ // If we have a default button, click it when return is pressed
+ defaultBtn->onCommit();
+ }
+ return TRUE;
+ }
+ else if (KEY_RIGHT == key)
+ {
+ LLToastPanel::focusNextItem(FALSE);
+ return TRUE;
+ }
+ else if (KEY_LEFT == key)
+ {
+ LLToastPanel::focusPrevItem(FALSE);
+ return TRUE;
+ }
+ else if (KEY_TAB == key && mask == MASK_NONE)
+ {
+ LLToastPanel::focusNextItem(FALSE);
+ return TRUE;
+ }
+ else if (KEY_TAB == key && mask == MASK_SHIFT)
+ {
+ LLToastPanel::focusPrevItem(FALSE);
+ return TRUE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+// virtual
+void LLToastAlertPanel::draw()
+{
+ // if the default button timer has just expired, activate the default button
+ if(mDefaultBtnTimer.hasExpired() && mDefaultBtnTimer.getStarted())
+ {
+ mDefaultBtnTimer.stop(); // prevent this block from being run more than once
+ LLToastPanel::setDefaultBtn(mButtonData[mDefaultOption].mButton);
+ }
+
+ static LLUIColor shadow_color = LLUIColorTable::instance().getColor("ColorDropShadow");
+ static LLUICachedControl<S32> shadow_lines ("DropShadowFloater");
+
+ gl_drop_shadow( 0, LLToastPanel::getRect().getHeight(), LLToastPanel::getRect().getWidth(), 0,
+ shadow_color, shadow_lines);
+
+ LLToastPanel::draw();
+}
+
+void LLToastAlertPanel::setEditTextArgs(const LLSD& edit_args)
+{
+ if (mLineEditor)
+ {
+ std::string msg = mLineEditor->getText();
+ mLineEditor->setText(msg);
+ }
+ else
+ {
+ llwarns << "LLToastAlertPanel::setEditTextArgs called on dialog with no line editor" << llendl;
+ }
+}
+
+void LLToastAlertPanel::onButtonPressed( const LLSD& data, S32 button )
+{
+ ButtonData* button_data = &mButtonData[button];
+
+ LLSD response = mNotification->getResponseTemplate();
+ if (mLineEditor)
+ {
+ response[mLineEditor->getName()] = mLineEditor->getValue();
+ }
+ response[button_data->mButton->getName()] = true;
+
+ // If we declared a URL and chose the URL option, go to the url
+ if (!button_data->mURL.empty() && sURLLoader != NULL)
+ {
+ sURLLoader->load(button_data->mURL, button_data->mURLExternal);
+ }
+
+ mNotification->respond(response); // new notification reponse
+}
+
+void LLToastAlertPanel::onClickIgnore(LLUICtrl* ctrl)
+{
+ // checkbox sometimes means "hide and do the default" and
+ // other times means "warn me again". Yuck. JC
+ BOOL check = ctrl->getValue().asBoolean();
+ if (mNotification->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN)
+ {
+ // question was "show again" so invert value to get "ignore"
+ check = !check;
+ }
+ mNotification->setIgnored(check);
+}
diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h
new file mode 100644
index 0000000000..43e105a4f1
--- /dev/null
+++ b/indra/newview/lltoastalertpanel.h
@@ -0,0 +1,125 @@
+/**
+ * @file lltoastalertpanel.h
+ * @brief Panel for alert toasts.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_TOASTALERTPANEL_H
+#define LL_TOASTALERTPANEL_H
+
+#include "lltoastpanel.h"
+#include "llfloater.h"
+#include "llui.h"
+#include "llnotificationptr.h"
+#include "llerror.h"
+
+class LLButton;
+class LLCheckBoxCtrl;
+class LLLineEditor;
+
+/**
+ * Toast panel for alert notification.
+ * Alerts notifications doesn't require user interaction.
+ *
+ * Replaces class LLAlertDialog.
+ * https://wiki.lindenlab.com/mediawiki/index.php?title=LLAlertDialog&oldid=81388
+ */
+
+class LLToastAlertPanel
+ : public LLToastPanel
+{
+ LOG_CLASS(LLToastAlertPanel);
+public:
+ typedef bool (*display_callback_t)(S32 modal);
+
+ class URLLoader
+ {
+ public:
+ virtual void load(const std::string& url, bool force_open_externally = 0) = 0;
+ virtual ~URLLoader()
+ {
+ }
+ };
+
+ static void setURLLoader(URLLoader* loader)
+ {
+ sURLLoader = loader;
+ }
+
+public:
+ // User's responsibility to call show() after creating these.
+ LLToastAlertPanel( LLNotificationPtr notep, bool is_modal );
+
+ virtual BOOL handleKeyHere(KEY key, MASK mask );
+
+ virtual void draw();
+ virtual void setVisible( BOOL visible );
+
+ bool setCheckBox( const std::string&, const std::string& );
+ void setCaution(BOOL val = TRUE) { mCaution = val; }
+ // If mUnique==TRUE only one copy of this message should exist
+ void setUnique(BOOL val = TRUE) { mUnique = val; }
+ void setEditTextArgs(const LLSD& edit_args);
+
+ void onClickIgnore(LLUICtrl* ctrl);
+ void onButtonPressed(const LLSD& data, S32 button);
+
+private:
+ static std::map<std::string, LLToastAlertPanel*> sUniqueActiveMap;
+
+ virtual ~LLToastAlertPanel();
+ // No you can't kill it. It can only kill itself.
+
+ // Does it have a readable title label, or minimize or close buttons?
+ BOOL hasTitleBar() const;
+
+private:
+ static URLLoader* sURLLoader;
+ static LLControlGroup* sSettings;
+
+ struct ButtonData
+ {
+ LLButton* mButton;
+ std::string mURL;
+ U32 mURLExternal;
+ };
+ std::vector<ButtonData> mButtonData;
+
+ S32 mDefaultOption;
+ LLCheckBoxCtrl* mCheck;
+ BOOL mCaution;
+ BOOL mUnique;
+ LLUIString mLabel;
+ LLFrameTimer mDefaultBtnTimer;
+ // For Dialogs that take a line as text as input:
+ LLLineEditor* mLineEditor;
+
+};
+
+#endif // LL_TOASTALERTPANEL_H
diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp
new file mode 100644
index 0000000000..e49044cdca
--- /dev/null
+++ b/indra/newview/lltoastgroupnotifypanel.cpp
@@ -0,0 +1,231 @@
+/**
+ * @file lltoastgroupnotifypanel.cpp
+ * @brief Panel for group notify toasts.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lltoastgroupnotifypanel.h"
+
+#include "llfocusmgr.h"
+
+#include "llbutton.h"
+#include "lliconctrl.h"
+#include "llinventoryfunctions.h"
+#include "llnotifications.h"
+#include "llviewertexteditor.h"
+
+#include "lluiconstants.h"
+#include "llui.h"
+#include "llviewercontrol.h"
+#include "lltrans.h"
+#include "llstyle.h"
+
+#include "llglheaders.h"
+#include "llagent.h"
+#include "llavatariconctrl.h"
+#include "llfloaterinventory.h"
+#include "llinventorytype.h"
+
+const S32 LLToastGroupNotifyPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT = 7;
+
+LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification)
+: LLToastPanel(notification),
+ mInventoryOffer(NULL)
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_group_notify.xml");
+ const LLSD& payload = notification->getPayload();
+ LLGroupData groupData;
+ if (!gAgent.getGroupData(payload["group_id"].asUUID(),groupData))
+ {
+ llwarns << "Group notice for unkown group: " << payload["group_id"].asUUID() << llendl;
+ }
+
+ //group icon
+ LLIconCtrl* pGroupIcon = getChild<LLIconCtrl>("group_icon", TRUE);
+ pGroupIcon->setValue(groupData.mInsigniaID);
+
+ //header title
+ const std::string& from_name = payload["sender_name"].asString();
+ std::stringstream from;
+ from << from_name << "/" << groupData.mName;
+ LLTextBox* pTitleText = getChild<LLTextBox>("title");
+ pTitleText->setValue(from.str());
+
+ //message subject
+ const std::string& subject = payload["subject"].asString();
+ //message body
+ const std::string& message = payload["message"].asString();
+
+ std::string timeStr = "["+LLTrans::getString("UTCTimeWeek")+"],["
+ +LLTrans::getString("UTCTimeDay")+"] ["
+ +LLTrans::getString("UTCTimeMth")+"] ["
+ +LLTrans::getString("UTCTimeYr")+"] ["
+ +LLTrans::getString("UTCTimeHr")+"]:["
+ +LLTrans::getString("UTCTimeMin")+"]:["
+ +LLTrans::getString("UTCTimeSec")+"] ["
+ +LLTrans::getString("UTCTimeTimezone")+"]";
+ const LLDate timeStamp = notification->getDate();
+ LLDate notice_date = timeStamp.notNull() ? timeStamp : LLDate::now();
+ LLSD substitution;
+ substitution["datetime"] = (S32) notice_date.secondsSinceEpoch();
+ LLStringUtil::format(timeStr, substitution);
+
+ LLViewerTextEditor* pMessageText = getChild<LLViewerTextEditor>("message");
+ pMessageText->clear();
+
+ LLStyle::Params style;
+ LLFontGL* subject_font = LLFontGL::getFontByName(getString("subject_font"));
+ if (subject_font)
+ style.font = subject_font;
+ pMessageText->appendText(subject, FALSE, style);
+
+ LLFontGL* date_font = LLFontGL::getFontByName(getString("date_font"));
+ if (date_font)
+ style.font = date_font;
+ pMessageText->appendText(timeStr + "\n", TRUE, style);
+
+ style.font = pMessageText->getDefaultFont();
+ pMessageText->appendText(message, TRUE, style);
+
+ //attachment
+ BOOL hasInventory = payload["inventory_offer"].isDefined();
+
+ //attachment text
+ LLTextBox * pAttachLink = getChild<LLTextBox>("attachment");
+ //attachment icon
+ LLIconCtrl* pAttachIcon = getChild<LLIconCtrl>("attachment_icon", TRUE);
+
+ //If attachment is empty let it be invisible and not take place at the panel
+ pAttachLink->setVisible(hasInventory);
+ pAttachIcon->setVisible(hasInventory);
+ if (hasInventory) {
+ std::string dis_name;
+ std::string inv_name = payload["inventory_name"];
+
+ if (LLViewerInventoryItem::extractSortFieldAndDisplayName(inv_name, NULL, &dis_name))
+ {
+ pAttachLink->setValue(dis_name);
+ }
+ else
+ {
+ pAttachLink->setValue(inv_name);
+ }
+
+ mInventoryOffer = new LLOfferInfo(payload["inventory_offer"]);
+ childSetActionTextbox("attachment", boost::bind(
+ &LLToastGroupNotifyPanel::onClickAttachment, this));
+
+ LLUIImagePtr attachIconImg = get_item_icon(mInventoryOffer->mType,
+ LLInventoryType::IT_TEXTURE,
+ 0, FALSE);
+ pAttachIcon->setValue(attachIconImg->getName());
+ }
+
+ //ok button
+ LLButton* pOkBtn = getChild<LLButton>("btn_ok");
+ pOkBtn->setClickedCallback((boost::bind(&LLToastGroupNotifyPanel::onClickOk, this)));
+ setDefaultBtn(pOkBtn);
+
+ S32 maxLinesCount;
+ std::istringstream ss( getString("message_max_lines_count") );
+ if (!(ss >> maxLinesCount))
+ {
+ maxLinesCount = DEFAULT_MESSAGE_MAX_LINE_COUNT;
+ }
+ snapToMessageHeight(pMessageText, maxLinesCount);
+}
+
+// virtual
+LLToastGroupNotifyPanel::~LLToastGroupNotifyPanel()
+{
+}
+
+void LLToastGroupNotifyPanel::close()
+{
+ // The group notice dialog may be an inventory offer.
+ // If it has an inventory save button and that button is still enabled
+ // Then we need to send the inventory declined message
+ if(mInventoryOffer != NULL)
+ {
+ mInventoryOffer->forceResponse(IOR_DECLINE);
+ mInventoryOffer = NULL;
+ }
+
+ die();
+}
+
+void LLToastGroupNotifyPanel::onClickOk()
+{
+ LLSD response = mNotification->getResponseTemplate();
+ mNotification->respond(response);
+ close();
+}
+
+void LLToastGroupNotifyPanel::onClickAttachment()
+{
+ if (mInventoryOffer != NULL) {
+ mInventoryOffer->forceResponse(IOR_ACCEPT);
+
+ LLTextBox * pAttachLink = getChild<LLTextBox> ("attachment");
+ static const LLUIColor textColor = LLUIColorTable::instance().getColor(
+ "GroupNotifyDimmedTextColor");
+ pAttachLink->setColor(textColor);
+
+ LLIconCtrl* pAttachIcon =
+ getChild<LLIconCtrl> ("attachment_icon", TRUE);
+ pAttachIcon->setEnabled(FALSE);
+
+ //if attachment isn't openable - notify about saving
+ if (!isAttachmentOpenable(mInventoryOffer->mType)) {
+ LLNotifications::instance().add("AttachmentSaved", LLSD(), LLSD());
+ }
+
+ mInventoryOffer = NULL;
+ }
+}
+
+//static
+bool LLToastGroupNotifyPanel::isAttachmentOpenable(LLAssetType::EType type)
+{
+ switch(type)
+ {
+ case LLAssetType::AT_LANDMARK:
+ case LLAssetType::AT_NOTECARD:
+ case LLAssetType::AT_IMAGE_JPEG:
+ case LLAssetType::AT_IMAGE_TGA:
+ case LLAssetType::AT_TEXTURE:
+ case LLAssetType::AT_TEXTURE_TGA:
+ return true;
+ default:
+ return false;
+ }
+}
+
diff --git a/indra/newview/lltoastgroupnotifypanel.h b/indra/newview/lltoastgroupnotifypanel.h
new file mode 100644
index 0000000000..4879000e8c
--- /dev/null
+++ b/indra/newview/lltoastgroupnotifypanel.h
@@ -0,0 +1,85 @@
+/**
+ * @file lltoastgroupnotifypanel.h
+ * @brief Panel for group notify toasts.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLGROUPNOTIFY_H
+#define LL_LLGROUPNOTIFY_H
+
+#include "llfontgl.h"
+#include "lltoastpanel.h"
+#include "lldarray.h"
+#include "lltimer.h"
+#include "llviewermessage.h"
+#include "llnotificationptr.h"
+
+class LLButton;
+
+/**
+ * Toast panel for group notification.
+ *
+ * Replaces class LLGroupNotifyBox.
+ */
+class LLToastGroupNotifyPanel
+: public LLToastPanel
+{
+public:
+ void close();
+
+ static bool onNewNotification(const LLSD& notification);
+
+
+ // Non-transient messages. You can specify non-default button
+ // layouts (like one for script dialogs) by passing various
+ // numbers in for "layout".
+ LLToastGroupNotifyPanel(LLNotificationPtr& notification);
+
+ /*virtual*/ ~LLToastGroupNotifyPanel();
+protected:
+ void onClickOk();
+ void onClickAttachment();
+private:
+ static bool isAttachmentOpenable(LLAssetType::EType);
+
+ static const S32 DEFAULT_MESSAGE_MAX_LINE_COUNT;
+
+ LLButton* mSaveInventoryBtn;
+
+ LLUUID mGroupID;
+ LLOfferInfo* mInventoryOffer;
+};
+
+// This view contains the stack of notification windows.
+//extern LLView* gGroupNotifyBoxView;
+
+const S32 GROUP_LAYOUT_DEFAULT = 0;
+const S32 GROUP_LAYOUT_SCRIPT_DIALOG = 1;
+
+#endif
diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp
new file mode 100644
index 0000000000..d62017cc2f
--- /dev/null
+++ b/indra/newview/lltoastimpanel.cpp
@@ -0,0 +1,121 @@
+/**
+ * @file lltoastimpanel.cpp
+ * @brief Panel for IM toasts.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "lltoastimpanel.h"
+
+#include "llnotifications.h"
+#include "llinstantmessage.h"
+#include "llviewerchat.h"
+
+const S32 LLToastIMPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT = 6;
+
+//--------------------------------------------------------------------------
+LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notification),
+ mAvatar(NULL), mUserName(NULL),
+ mTime(NULL), mMessage(NULL)
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_instant_message.xml");
+
+ LLIconCtrl* sys_msg_icon = getChild<LLIconCtrl>("sys_msg_icon");
+ mAvatar = getChild<LLAvatarIconCtrl>("avatar_icon");
+ mUserName = getChild<LLTextBox>("user_name");
+ mTime = getChild<LLTextBox>("time_box");
+ mMessage = getChild<LLTextBox>("message");
+
+ LLStyle::Params style_params;
+ LLFontGL* fontp = LLViewerChat::getChatFont();
+ std::string font_name = LLFontGL::nameFromFont(fontp);
+ std::string font_size = LLFontGL::sizeFromFont(fontp);
+ style_params.font.name(font_name);
+ style_params.font.size(font_size);
+ style_params.font.style = "UNDERLINE";
+
+ //Handle IRC styled /me messages.
+ std::string prefix = p.message.substr(0, 4);
+ if (prefix == "/me " || prefix == "/me'")
+ {
+ mMessage->clear();
+
+ style_params.font.style ="ITALIC";
+ mMessage->appendText(p.from, FALSE, style_params);
+
+ style_params.font.style = "ITALIC";
+ mMessage->appendText(p.message.substr(3), FALSE, style_params);
+ }
+ else
+ {
+ mMessage->setValue(p.message);
+ }
+
+ mUserName->setValue(p.from);
+ mTime->setValue(p.time);
+ mSessionID = p.session_id;
+ mNotification = p.notification;
+
+ if(p.from == SYSTEM_FROM)
+ {
+ mAvatar->setVisible(FALSE);
+ sys_msg_icon->setVisible(TRUE);
+ }
+ else
+ {
+ mAvatar->setVisible(TRUE);
+ sys_msg_icon->setVisible(FALSE);
+
+ mAvatar->setValue(p.avatar_id);
+ }
+
+ S32 maxLinesCount;
+ std::istringstream ss( getString("message_max_lines_count") );
+ if (!(ss >> maxLinesCount))
+ {
+ maxLinesCount = DEFAULT_MESSAGE_MAX_LINE_COUNT;
+ }
+ snapToMessageHeight(mMessage, maxLinesCount);
+}
+
+//--------------------------------------------------------------------------
+LLToastIMPanel::~LLToastIMPanel()
+{
+}
+
+//virtual
+BOOL LLToastIMPanel::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ if (LLPanel::handleMouseDown(x,y,mask) == FALSE)
+ {
+ mNotification->respond(mNotification->getResponseTemplate());
+ }
+
+ return TRUE;
+}
diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h
new file mode 100644
index 0000000000..53661f2cf6
--- /dev/null
+++ b/indra/newview/lltoastimpanel.h
@@ -0,0 +1,74 @@
+/**
+ * @file lltoastimpanel.h
+ * @brief Panel for IM toasts.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLTOASTIMPANEL_H_
+#define LLTOASTIMPANEL_H_
+
+
+#include "lltoastpanel.h"
+#include "lltextbox.h"
+#include "llbutton.h"
+#include "llavatariconctrl.h"
+
+
+class LLToastIMPanel: public LLToastPanel
+{
+public:
+ struct Params
+ {
+ LLNotificationPtr notification;
+ LLUUID avatar_id;
+ LLUUID session_id;
+ std::string from;
+ std::string time;
+ std::string message;
+
+ Params() {}
+ };
+
+ LLToastIMPanel(LLToastIMPanel::Params &p);
+ virtual ~LLToastIMPanel();
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+private:
+ static const S32 DEFAULT_MESSAGE_MAX_LINE_COUNT;
+
+ LLNotificationPtr mNotification;
+ LLUUID mSessionID;
+ LLAvatarIconCtrl* mAvatar;
+ LLTextBox* mUserName;
+ LLTextBox* mTime;
+ LLTextBox* mMessage;
+};
+
+#endif // LLTOASTIMPANEL_H_
+
+
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
new file mode 100644
index 0000000000..94acb2ae8c
--- /dev/null
+++ b/indra/newview/lltoastnotifypanel.cpp
@@ -0,0 +1,307 @@
+/**
+ * @file lltoastnotifypanel.cpp
+ * @brief Panel for notify toasts.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lltoastnotifypanel.h"
+
+// project includes
+#include "llviewercontrol.h"
+
+// library includes
+#include "lldbstrings.h"
+#include "llnotifications.h"
+#include "lluiconstants.h"
+#include "llrect.h"
+#include "lltrans.h"
+
+const S32 BOTTOM_PAD = VPAD * 3;
+S32 BUTTON_WIDTH = 90;
+
+//static
+const LLFontGL* LLToastNotifyPanel::sFont = NULL;
+const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL;
+
+LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification) :
+LLToastPanel(notification),
+mTextBox(NULL),
+mInfoPanel(NULL),
+mControlPanel(NULL),
+mNumOptions(0),
+mNumButtons(0),
+mAddedDefaultBtn(false)
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_notification.xml");
+ mInfoPanel = getChild<LLPanel>("info_panel");
+ mControlPanel = getChild<LLPanel>("control_panel");
+ BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth");
+ // customize panel's attributes
+ // is it intended for displaying a tip
+ mIsTip = notification->getType() == "notifytip";
+ // is it a script dialog
+ mIsScriptDialog = (notification->getName() == "ScriptDialog" || notification->getName() == "ScriptDialogGroup");
+ // is it a caution
+ //
+ // caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the
+ // notify xml template specifies that it is a caution
+ // tip-style notification handle 'caution' differently -they display the tip in a different color
+ mIsCaution = notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH;
+
+ // setup parameters
+ // get a notification message
+ mMessage = notification->getMessage();
+ // init font variables
+ if (!sFont)
+ {
+ sFont = LLFontGL::getFontSansSerif();
+ sFontSmall = LLFontGL::getFontSansSerifSmall();
+ }
+ // clicking on a button does not steal current focus
+ setIsChrome(TRUE);
+ // initialize
+ setFocusRoot(!mIsTip);
+ // get a form for the notification
+ LLNotificationFormPtr form(notification->getForm());
+ // get number of elements
+ mNumOptions = form->getNumElements();
+
+ // customize panel's outfit
+ // preliminary adjust panel's layout
+ //move to the end
+ //mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form);
+
+ // adjust text options according to the notification type
+ // add a caution textbox at the top of a caution notification
+ if (mIsCaution && !mIsTip)
+ {
+ mTextBox = getChild<LLTextBox>("caution_text_box");
+ }
+ else
+ {
+ mTextBox = getChild<LLTextEditor>("text_editor_box");
+ }
+
+ // *TODO: magic numbers(???) - copied from llnotify.cpp(250)
+ const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE;
+
+ mTextBox->setMaxTextLength(MAX_LENGTH);
+ mTextBox->setVisible(TRUE);
+ mTextBox->setValue(notification->getMessage());
+
+ // add buttons for a script notification
+ if (mIsTip)
+ {
+ adjustPanelForTipNotice();
+ }
+ else
+ {
+ std::vector<index_button_pair_t> buttons;
+ buttons.reserve(mNumOptions);
+ for (S32 i = 0; i < mNumOptions; i++)
+ {
+ LLSD form_element = form->getElement(i);
+ if (form_element["type"].asString() != "button")
+ {
+ continue;
+ }
+ }
+ S32 buttons_width = 0;
+ // create all buttons and accumulate they total width to reshape mControlPanel
+ for (S32 i = 0; i < mNumOptions; i++)
+ {
+ LLSD form_element = form->getElement(i);
+ if (form_element["type"].asString() != "button")
+ {
+ continue;
+ }
+ LLButton* new_button = createButton(form_element, TRUE);
+ buttons_width += new_button->getRect().getWidth();
+ S32 index = form_element["index"].asInteger();
+ buttons.push_back(index_button_pair_t(index,new_button));
+ }
+ if (buttons.empty())
+ {
+ addDefaultButton();
+ }
+ else
+ {
+ //try get an average left_pad to spread out buttons
+ S32 left_pad = (getRect().getWidth() - buttons_width) / (S32(buttons.size() + 1));
+ // left_pad can be < 2*HPAD if we have a lot of buttons.
+ if(left_pad < 2*HPAD)
+ {
+ //Probably it is a scriptdialog toast, set default left_pad
+ left_pad = 2*HPAD;
+ }
+ //how many rows we need to fit all buttons with current width of the panel
+ S32 button_rows = (buttons_width + left_pad * S32(buttons.size() + 1)) / getRect().getWidth() + 1;
+ //calculate required panel height
+ S32 button_panel_height = button_rows *( BTN_HEIGHT + VPAD) + BOTTOM_PAD;
+
+ adjustPanelForScriptNotice(getRect().getWidth(), button_panel_height);
+ //we begin from lefttop angle and go to rightbottom.
+ updateButtonsLayout(buttons, left_pad, button_panel_height);
+ }
+ }
+ // adjust panel's height to the text size
+ mInfoPanel->setFollowsAll();
+ snapToMessageHeight(mTextBox, MAX_LENGTH);
+}
+void LLToastNotifyPanel::addDefaultButton()
+{
+ LLSD form_element;
+ form_element.with("name", "OK").with("text", LLTrans::getString("ok")).with("default", true);
+ LLButton* ok_btn = createButton(form_element, FALSE);
+ LLRect new_btn_rect(ok_btn->getRect());
+
+ new_btn_rect.setOriginAndSize(llabs(getRect().getWidth() - BUTTON_WIDTH)/ 2, BOTTOM_PAD,
+ //auto_size for ok button makes it very small, so let's make it wider
+ BUTTON_WIDTH, new_btn_rect.getHeight());
+ ok_btn->setRect(new_btn_rect);
+ addChild(ok_btn, -1);
+ mNumButtons = 1;
+ mAddedDefaultBtn = true;
+}
+LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_option)
+{
+
+ InstanceAndS32* userdata = new InstanceAndS32;
+ userdata->mSelf = this;
+ userdata->mButtonName = is_option ? form_element["name"].asString() : "";
+
+ mBtnCallbackData.push_back(userdata);
+
+ LLButton::Params p;
+ const LLFontGL* font = form_element["index"].asInteger() == -1 ? sFontSmall: sFont; // for ignore button in script dialog
+ p.name(form_element["name"].asString());
+ p.label(form_element["text"].asString());
+ p.font(font);
+ p.rect.height = BTN_HEIGHT;
+ p.click_callback.function(boost::bind(&LLToastNotifyPanel::onClickButton, userdata));
+ p.rect.width = BUTTON_WIDTH;
+ p.auto_resize = false;
+ p.follows.flags(FOLLOWS_RIGHT | FOLLOWS_LEFT | FOLLOWS_BOTTOM);
+ if (mIsCaution)
+ {
+ p.image_color(LLUIColorTable::instance().getColor("ButtonCautionImageColor"));
+ p.image_color_disabled(LLUIColorTable::instance().getColor("ButtonCautionImageColor"));
+ }
+ if (!mIsScriptDialog && font->getWidth(form_element["text"].asString()) > BUTTON_WIDTH)
+ {
+ p.rect.width = 1;
+ p.auto_resize = true;
+ }
+
+ LLButton* btn = LLUICtrlFactory::create<LLButton>(p);
+ mNumButtons++;
+ btn->autoResize();
+ if (form_element["default"].asBoolean())
+ {
+ setDefaultBtn(btn);
+ }
+
+ return btn;
+}
+
+LLToastNotifyPanel::~LLToastNotifyPanel()
+{
+ std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer());
+}
+void LLToastNotifyPanel::updateButtonsLayout(const std::vector<index_button_pair_t>& buttons, S32 left_pad, S32 top)
+{
+ S32 left = left_pad;
+ LLButton* ignore_btn = NULL;
+ for (std::vector<index_button_pair_t>::const_iterator it = buttons.begin(); it != buttons.end(); it++)
+ {
+ if(left + it->second->getRect().getWidth() + 2*HPAD > getRect().getWidth())
+ {
+ // looks like we need to add button to the next row
+ left = left_pad;
+ top-= (BTN_HEIGHT + VPAD);
+ }
+ LLRect btn_rect(it->second->getRect());
+ if(mIsScriptDialog && it->first == -1)
+ {
+ //this is ignore button ( index == -1) we need to add it into new extra row at the end
+ ignore_btn = it->second;
+ continue;
+ }
+ btn_rect.setLeftTopAndSize(left, top, btn_rect.getWidth(), btn_rect.getHeight());
+ it->second->setRect(btn_rect);
+ left = btn_rect.mLeft + btn_rect.getWidth() + left_pad;
+ addChild(it->second, -1);
+ }
+ if(ignore_btn)
+ {
+ LLRect btn_rect(ignore_btn->getRect());
+ btn_rect.setOriginAndSize(getRect().getWidth() - btn_rect.getWidth() - left_pad,
+ BOTTOM_PAD,// move button at the bottom edge
+ btn_rect.getWidth(), btn_rect.getHeight());
+ ignore_btn->setRect(btn_rect);
+ addChild(ignore_btn, -1);
+ }
+}
+
+void LLToastNotifyPanel::adjustPanelForScriptNotice(S32 button_panel_width, S32 button_panel_height)
+{
+ //adjust layout
+ // we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed
+ LLRect button_rect = mControlPanel->getRect();
+ reshape(getRect().getWidth(), mInfoPanel->getRect().getHeight() + button_panel_height + VPAD);
+ button_rect.set(0, button_rect.mBottom + button_panel_height, button_rect.getWidth(), button_rect.mBottom);
+ mControlPanel->reshape(button_rect.getWidth(), button_panel_height);
+ mControlPanel->setRect(button_rect);
+}
+
+void LLToastNotifyPanel::adjustPanelForTipNotice()
+{
+ LLRect info_rect = mInfoPanel->getRect();
+ LLRect this_rect = getRect();
+
+ mControlPanel->setVisible(FALSE);
+ reshape(getRect().getWidth(), mInfoPanel->getRect().getHeight());
+}
+
+// static
+void LLToastNotifyPanel::onClickButton(void* data)
+{
+ InstanceAndS32* self_and_button = (InstanceAndS32*)data;
+ LLToastNotifyPanel* self = self_and_button->mSelf;
+ std::string button_name = self_and_button->mButtonName;
+
+ LLSD response = self->mNotification->getResponseTemplate();
+ if (!self->mAddedDefaultBtn && !button_name.empty())
+ {
+ response[button_name] = true;
+ }
+ self->mNotification->respond(response);
+}
diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h
new file mode 100644
index 0000000000..1f50c21f6f
--- /dev/null
+++ b/indra/newview/lltoastnotifypanel.h
@@ -0,0 +1,99 @@
+/**
+ * @file lltoastnotifypanel.h
+ * @brief Panel for notify toasts.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLTOASTNOTIFYPANEL_H_
+#define LLTOASTNOTIFYPANEL_H_
+
+#include "llpanel.h"
+#include "llfontgl.h"
+#include "llnotificationptr.h"
+#include "llbutton.h"
+#include "lltoastpanel.h"
+#include "lliconctrl.h"
+#include "lltexteditor.h"
+#include "lltextbox.h"
+
+class LLNotificationForm;
+
+/**
+ * Toast panel for notification.
+ * Notification panel should be used for notifications that require a response from the user.
+ *
+ * Replaces class LLNotifyBox.
+ */
+class LLToastNotifyPanel: public LLToastPanel
+{
+public:
+ LLToastNotifyPanel(LLNotificationPtr&);
+ virtual ~LLToastNotifyPanel();
+
+protected:
+ LLButton* createButton(const LLSD& form_element, BOOL is_option);
+
+ // Used for callbacks
+ struct InstanceAndS32
+ {
+ LLToastNotifyPanel* mSelf;
+ std::string mButtonName;
+ };
+ std::vector<InstanceAndS32*> mBtnCallbackData;
+
+private:
+
+ typedef std::pair<int,LLButton*> index_button_pair_t;
+ void adjustPanelForScriptNotice(S32 max_width, S32 max_height);
+ void adjustPanelForTipNotice();
+ void addDefaultButton();
+ void updateButtonsLayout(const std::vector<index_button_pair_t>& buttons, S32 left_pad, S32 top);
+
+ // panel elements
+ LLTextBase* mTextBox;
+ LLPanel* mInfoPanel; // a panel, that contains an information
+ LLPanel* mControlPanel; // a panel, that contains buttons (if present)
+
+ // internal handler for button being clicked
+ static void onClickButton(void* data);
+
+ bool mIsTip;
+ bool mAddedDefaultBtn;
+ bool mIsScriptDialog;
+ bool mIsCaution;
+
+ std::string mMessage;
+ S32 mNumOptions;
+ S32 mNumButtons;
+
+ static const LLFontGL* sFont;
+ static const LLFontGL* sFontSmall;
+};
+
+#endif /* LLTOASTNOTIFYPANEL_H_ */
diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp
new file mode 100644
index 0000000000..755e647777
--- /dev/null
+++ b/indra/newview/lltoastpanel.cpp
@@ -0,0 +1,93 @@
+/**
+ * @file lltoastpanel.cpp
+ * @brief Creates a panel of a specific kind for a toast
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lltoastpanel.h"
+
+#include "llnotifications.h"
+
+//static
+const S32 LLToastPanel::MIN_PANEL_HEIGHT = 40; // VPAD(4)*2 + ICON_HEIGHT(32)
+
+LLToastPanel::LLToastPanel(LLNotificationPtr& notification)
+{
+ mNotification = notification;
+}
+
+LLToastPanel::~LLToastPanel()
+{
+}
+
+//virtual
+std::string LLToastPanel::getTitle()
+{
+ // *TODO: create Title and localize it. If it will be required.
+ return mNotification->getMessage();
+}
+
+//virtual
+const LLUUID& LLToastPanel::getID()
+{
+ return mNotification->id();
+}
+
+//snap to the message height if it is visible
+void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount)
+{
+ if(!message)
+ {
+ return;
+ }
+
+ //Add message height if it is visible
+ if (message->getVisible())
+ {
+ S32 heightDelta = 0;
+ S32 maxTextHeight = (S32)(message->getDefaultFont()->getLineHeight() * maxLineCount);
+
+ LLRect messageRect = message->getRect();
+ S32 oldTextHeight = messageRect.getHeight();
+
+ //Knowing the height is set to max allowed, getTextPixelHeight returns needed text height
+ //Perhaps we need to pass maxLineCount as parameter to getTextPixelHeight to avoid previous reshape.
+ S32 requiredTextHeight = message->getTextBoundingRect().getHeight();
+ S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight);
+
+ //Calculate last delta height deducting previous heightDelta
+ heightDelta = newTextHeight - oldTextHeight - heightDelta;
+
+ //reshape the panel with new height
+ reshape( getRect().getWidth(), llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT));
+ }
+}
+
diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h
new file mode 100644
index 0000000000..f1dd7d7a86
--- /dev/null
+++ b/indra/newview/lltoastpanel.h
@@ -0,0 +1,68 @@
+/**
+ * @file lltoastpanel.h
+ * @brief Creates a panel of a specific kind for a toast.
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTOASTPANEL_H
+#define LL_LLTOASTPANEL_H
+
+#include "llpanel.h"
+#include "lltextbox.h"
+#include "llnotificationptr.h"
+
+#include <string>
+
+class LLToastPanelBase: public LLPanel
+{
+public:
+ virtual void init(LLSD& data){};
+};
+
+/**
+ * Base class for all panels that can be added to the toast.
+ * All toast panels should contain necessary logic for representing certain notification
+ * but shouldn't contain logic related to this panel lifetime control and positioning
+ * on the parent view.
+ */
+class LLToastPanel: public LLPanel {
+public:
+ LLToastPanel(LLNotificationPtr&);
+ virtual ~LLToastPanel() = 0;
+
+ virtual std::string getTitle();
+ virtual const LLUUID& getID();
+
+ static const S32 MIN_PANEL_HEIGHT;
+protected:
+ LLNotificationPtr mNotification;
+ void snapToMessageHeight(LLTextBase* message, S32 maxLineCount);
+};
+
+#endif /* LL_TOASTPANEL_H */
diff --git a/indra/newview/lltool.cpp b/indra/newview/lltool.cpp
index 6a3ada0474..669a62a238 100644
--- a/indra/newview/lltool.cpp
+++ b/indra/newview/lltool.cpp
@@ -65,6 +65,22 @@ LLTool::~LLTool()
}
}
+BOOL LLTool::handleAnyMouseClick(S32 x, S32 y, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down)
+{
+ BOOL result = LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down);
+
+ // This behavior was moved here from LLViewerWindow::handleAnyMouseClick, so it can be selectively overridden by LLTool subclasses.
+ if(down && result)
+ {
+ // This is necessary to force clicks in the world to cause edit
+ // boxes that might have keyboard focus to relinquish it, and hence
+ // cause a commit to update their value. JC
+ gFocusMgr.setKeyboardFocus(NULL);
+ }
+
+ return result;
+}
+
BOOL LLTool::handleMouseDown(S32 x, S32 y, MASK mask)
{
if (gDebugClicks)
@@ -91,7 +107,7 @@ BOOL LLTool::handleMouseUp(S32 x, S32 y, MASK mask)
BOOL LLTool::handleHover(S32 x, S32 y, MASK mask)
{
- gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
+ gViewerWindow->setCursor(UI_CURSOR_ARROW);
lldebugst(LLERR_USER_INPUT) << "hover handled by a tool" << llendl;
// by default, do nothing, say we handled it
return TRUE;
@@ -139,7 +155,7 @@ BOOL LLTool::handleMiddleMouseUp(S32 x, S32 y, MASK mask)
return FALSE;
}
-BOOL LLTool::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
+BOOL LLTool::handleToolTip(S32 x, S32 y, MASK mask)
{
// by default, didn't handle it
// llinfos << "LLTool::handleToolTip" << llendl;
diff --git a/indra/newview/lltool.h b/indra/newview/lltool.h
index f954a8c243..c3573cd38c 100644
--- a/indra/newview/lltool.h
+++ b/indra/newview/lltool.h
@@ -55,6 +55,7 @@ public:
virtual BOOL isView() const { return FALSE; }
// Virtual functions inherited from LLMouseHandler
+ virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask);
@@ -65,9 +66,7 @@ public:
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen);
-
- virtual EShowToolTip getShowToolTip() { return SHOW_ALWAYS; }; // tools should permit tips even when the mouse is down, as that's pretty normal for tools
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
// Return FALSE to allow context menu to be shown.
virtual void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const
@@ -75,7 +74,7 @@ public:
virtual void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const
{ *screen_x = local_x; *screen_y = local_y; }
- virtual const std::string& getName() const { return mName; }
+ virtual std::string getName() const { return mName; }
// New virtual functions
virtual LLViewerObject* getEditingObject() { return NULL; }
diff --git a/indra/newview/lltoolbar.cpp b/indra/newview/lltoolbar.cpp
index 33edb3ef27..edbaa0d45a 100644
--- a/indra/newview/lltoolbar.cpp
+++ b/indra/newview/lltoolbar.cpp
@@ -36,58 +36,47 @@
#include "lltoolbar.h"
#include "imageids.h"
+#include "llfloaterreg.h"
#include "llfontgl.h"
+#include "llflyoutbutton.h"
#include "llrect.h"
#include "llparcel.h"
#include "llagent.h"
+#include "llagentwearables.h"
#include "llbutton.h"
#include "llfocusmgr.h"
#include "llviewercontrol.h"
#include "llmenucommands.h"
#include "llimview.h"
#include "lluiconstants.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "lltooldraganddrop.h"
-#include "llinventoryview.h"
+#include "llfloaterinventory.h"
#include "llfloaterchatterbox.h"
#include "llfloaterfriends.h"
#include "llfloatersnapshot.h"
+#include "llinventorypanel.h"
#include "lltoolmgr.h"
#include "llui.h"
#include "llviewermenu.h"
-#include "llfirstuse.h"
+//#include "llfirstuse.h"
+#include "llpanelblockedlist.h"
+#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "llscrolllistcell.h"
#include "llviewerparcelmgr.h"
#include "lluictrlfactory.h"
#include "llviewerwindow.h"
#include "lltoolgrab.h"
#include "llcombobox.h"
-#include "llfloaterchat.h"
-#include "llfloatermute.h"
#include "llimpanel.h"
-#include "llscrolllistctrl.h"
+#include "lllayoutstack.h"
#if LL_DARWIN
#include "llresizehandle.h"
- // This class draws like an LLResizeHandle but has no interactivity.
- // It's just there to provide a cue to the user that the lower right corner of the window functions as a resize handle.
- class LLFakeResizeHandle : public LLResizeHandle
- {
- public:
- LLFakeResizeHandle(const std::string& name, const LLRect& rect, S32 min_width, S32 min_height, ECorner corner = RIGHT_BOTTOM )
- : LLResizeHandle(name, rect, min_width, min_height, corner )
- {
-
- }
-
- virtual BOOL handleHover(S32 x, S32 y, MASK mask) { return FALSE; };
- virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; };
- virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) { return FALSE; };
-
- };
-
#endif // LL_DARWIN
//
@@ -95,7 +84,6 @@
//
LLToolBar *gToolBar = NULL;
-S32 TOOL_BAR_HEIGHT = 20;
//
// Statics
@@ -114,44 +102,13 @@ LLToolBar::LLToolBar()
{
setIsChrome(TRUE);
setFocusRoot(TRUE);
+
+ mCommitCallbackRegistrar.add("HandleCommunicate", &LLToolBar::onClickCommunicate);
}
BOOL LLToolBar::postBuild()
{
- childSetCommitCallback("communicate_btn", onClickCommunicate, this);
- childSetControlName("communicate_btn", "ShowCommunicate");
-
- childSetAction("chat_btn", onClickChat, this);
- childSetControlName("chat_btn", "ChatVisible");
-
- childSetAction("appearance_btn", onClickAppearance, this);
- childSetControlName("appearance_btn", "");
-
- childSetAction("fly_btn", onClickFly, this);
- childSetControlName("fly_btn", "FlyBtnState");
-
- childSetAction("sit_btn", onClickSit, this);
- childSetControlName("sit_btn", "SitBtnState");
-
- childSetAction("snapshot_btn", onClickSnapshot, this);
- childSetControlName("snapshot_btn", "");
-
- childSetAction("directory_btn", onClickDirectory, this);
- childSetControlName("directory_btn", "ShowDirectory");
-
- childSetAction("build_btn", onClickBuild, this);
- childSetControlName("build_btn", "BuildBtnState");
-
- childSetAction("radar_btn", onClickRadar, this);
- childSetControlName("radar_btn", "ShowMiniMap");
-
- childSetAction("map_btn", onClickMap, this);
- childSetControlName("map_btn", "ShowWorldMap");
-
- childSetAction("inventory_btn", onClickInventory, this);
- childSetControlName("inventory_btn", "ShowInventory");
-
for (child_list_const_iter_t child_iter = getChildList()->begin();
child_iter != getChildList()->end(); ++child_iter)
{
@@ -167,8 +124,14 @@ BOOL LLToolBar::postBuild()
if(mResizeHandle == NULL)
{
LLRect rect(0, 0, RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT);
- mResizeHandle = new LLFakeResizeHandle(std::string(""), rect, RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT);
- this->addChildAtEnd(mResizeHandle);
+ LLResizeHandle::Params p;
+ p.name("");
+ p.rect(rect);
+ p.min_width(RESIZE_HANDLE_WIDTH);
+ p.min_height(RESIZE_HANDLE_HEIGHT);
+ p.enabled(false);
+ mResizeHandle = LLUICtrlFactory::create<LLResizeHandle>(p);
+ addChildInBack(mResizeHandle);
LLLayoutStack* toolbar_stack = getChild<LLLayoutStack>("toolbar_stack");
toolbar_stack->reshape(toolbar_stack->getRect().getWidth() - RESIZE_HANDLE_WIDTH, toolbar_stack->getRect().getHeight());
}
@@ -194,20 +157,22 @@ BOOL LLToolBar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
LLButton* inventory_btn = getChild<LLButton>("inventory_btn");
if (!inventory_btn) return FALSE;
- LLInventoryView* active_inventory = LLInventoryView::getActiveInventory();
-
- if(active_inventory && active_inventory->getVisible())
+ LLRect button_screen_rect;
+ inventory_btn->localRectToScreen(inventory_btn->getRect(),&button_screen_rect);
+
+ const LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel();
+ if(active_panel)
{
mInventoryAutoOpen = FALSE;
}
- else if (inventory_btn->getRect().pointInRect(x, y))
+ else if (button_screen_rect.pointInRect(x, y))
{
if (mInventoryAutoOpen)
{
- if (!(active_inventory && active_inventory->getVisible()) &&
- mInventoryAutoOpenTimer.getElapsedTimeF32() > sInventoryAutoOpenTime)
+ if (!active_panel &&
+ mInventoryAutoOpenTimer.getElapsedTimeF32() > sInventoryAutoOpenTime)
{
- LLInventoryView::showAgentInventory();
+ LLFloaterInventory::showAgentInventory();
}
}
else
@@ -240,7 +205,7 @@ void LLToolBar::layoutButtons()
{
#if LL_DARWIN
const S32 FUDGE_WIDTH_OF_SCREEN = 4;
- S32 width = gViewerWindow->getWindowWidth() + FUDGE_WIDTH_OF_SCREEN;
+ S32 width = gViewerWindow->getWindowWidthScaled() + FUDGE_WIDTH_OF_SCREEN;
S32 pad = 2;
// this function may be called before postBuild(), in which case mResizeHandle won't have been set up yet.
@@ -284,25 +249,6 @@ void LLToolBar::refresh()
BOOL mouselook = gAgent.cameraMouselook();
setVisible(show && !mouselook);
- BOOL sitting = FALSE;
- if (gAgent.getAvatarObject())
- {
- sitting = gAgent.getAvatarObject()->mIsSitting;
- }
-
- childSetEnabled("fly_btn", (gAgent.canFly() || gAgent.getFlying()) && !sitting );
-
- childSetEnabled("build_btn", LLViewerParcelMgr::getInstance()->agentCanBuild() );
-
- // Check to see if we're in build mode
- BOOL build_mode = LLToolMgr::getInstance()->inEdit();
- // And not just clicking on a scripted object
- if (LLToolGrab::getInstance()->getHideBuildHighlight())
- {
- build_mode = FALSE;
- }
- gSavedSettings.setBOOL("BuildBtnState", build_mode);
-
if (isInVisibleChain())
{
updateCommunicateList();
@@ -319,30 +265,26 @@ void LLToolBar::updateCommunicateList()
LLFloater* frontmost_floater = LLFloaterChatterBox::getInstance()->getActiveFloater();
LLScrollListItem* itemp = NULL;
- itemp = communicate_button->add(LLFloaterMyFriends::getInstance()->getShortTitle(), LLSD("contacts"), ADD_TOP);
+ LLSD contact_sd;
+ contact_sd["value"] = "contacts";
+ contact_sd["columns"][0]["value"] = LLFloaterMyFriends::getInstance()->getShortTitle();
if (LLFloaterMyFriends::getInstance() == frontmost_floater)
{
- ((LLScrollListText*)itemp->getColumn(0))->setFontStyle(LLFontGL::BOLD);
+ contact_sd["columns"][0]["font"]["name"] = "SANSSERIF_SMALL";
+ contact_sd["columns"][0]["font"]["style"] = "BOLD";
// make sure current tab is selected in list
if (selected.isUndefined())
{
- selected = itemp->getValue();
- }
- }
- itemp = communicate_button->add(LLFloaterChat::getInstance()->getShortTitle(), LLSD("local chat"), ADD_TOP);
- if (LLFloaterChat::getInstance() == frontmost_floater)
- {
- ((LLScrollListText*)itemp->getColumn(0))->setFontStyle(LLFontGL::BOLD);
- if (selected.isUndefined())
- {
- selected = itemp->getValue();
+ selected = "contacts";
}
}
+ itemp = communicate_button->addElement(contact_sd, ADD_TOP);
+
communicate_button->addSeparator(ADD_TOP);
communicate_button->add(getString("Redock Windows"), LLSD("redock"), ADD_TOP);
communicate_button->addSeparator(ADD_TOP);
- communicate_button->add(LLFloaterMute::getInstance()->getShortTitle(), LLSD("mute list"), ADD_TOP);
-
+ communicate_button->add(getString("Blocked List"), LLSD("mute list"), ADD_TOP);
+
std::set<LLHandle<LLFloater> >::const_iterator floater_handle_it;
if (gIMMgr->getIMFloaterHandles().size() > 0)
@@ -357,165 +299,79 @@ void LLToolBar::updateCommunicateList()
{
std::string floater_title = im_floaterp->getNumUnreadMessages() > 0 ? "*" : "";
floater_title.append(im_floaterp->getShortTitle());
- itemp = communicate_button->add(floater_title, im_floaterp->getSessionID(), ADD_TOP);
+ LLSD im_sd;
+ im_sd["value"] = im_floaterp->getSessionID();
+ im_sd["columns"][0]["value"] = floater_title;
if (im_floaterp == frontmost_floater)
{
- ((LLScrollListText*)itemp->getColumn(0))->setFontStyle(LLFontGL::BOLD);
+ im_sd["columns"][0]["font"]["name"] = "SANSSERIF_SMALL";
+ im_sd["columns"][0]["font"]["style"] = "BOLD";
if (selected.isUndefined())
{
- selected = itemp->getValue();
+ selected = im_floaterp->getSessionID();
}
}
+ itemp = communicate_button->addElement(im_sd, ADD_TOP);
}
}
- communicate_button->setToggleState(gSavedSettings.getBOOL("ShowCommunicate"));
communicate_button->setValue(selected);
}
// static
-void LLToolBar::onClickCommunicate(LLUICtrl* ctrl, void* user_data)
+void LLToolBar::onClickCommunicate(LLUICtrl* ctrl, const LLSD& user_data)
{
- LLToolBar* toolbar = (LLToolBar*)user_data;
- LLFlyoutButton* communicate_button = toolbar->getChild<LLFlyoutButton>("communicate_btn");
+ LLFlyoutButton* communicate_button = dynamic_cast<LLFlyoutButton*>(ctrl);
+ llassert_always(communicate_button);
LLSD selected_option = communicate_button->getValue();
if (selected_option.asString() == "contacts")
{
- LLFloaterMyFriends::showInstance();
+ LLFloaterReg::showInstance("contacts", "friends");
}
else if (selected_option.asString() == "local chat")
{
- LLFloaterChat::showInstance();
+ LLFloaterReg::showInstance("communicate", "local");
}
else if (selected_option.asString() == "redock")
{
- LLFloaterChatterBox::getInstance()->addFloater(LLFloaterMyFriends::getInstance(), FALSE);
- LLFloaterChatterBox::getInstance()->addFloater(LLFloaterChat::getInstance(), FALSE);
- LLUUID session_to_show;
-
- std::set<LLHandle<LLFloater> >::const_iterator floater_handle_it;
- for(floater_handle_it = gIMMgr->getIMFloaterHandles().begin(); floater_handle_it != gIMMgr->getIMFloaterHandles().end(); ++floater_handle_it)
+ LLFloaterChatterBox* chatterbox_instance = LLFloaterChatterBox::getInstance();
+ if(chatterbox_instance)
{
- LLFloater* im_floaterp = floater_handle_it->get();
- if (im_floaterp)
+ chatterbox_instance->addFloater(LLFloaterMyFriends::getInstance(), FALSE);
+
+ LLUUID session_to_show;
+
+ std::set<LLHandle<LLFloater> >::const_iterator floater_handle_it;
+ for(floater_handle_it = gIMMgr->getIMFloaterHandles().begin(); floater_handle_it != gIMMgr->getIMFloaterHandles().end(); ++floater_handle_it)
{
- if (im_floaterp->isFrontmost())
+ LLFloater* im_floaterp = floater_handle_it->get();
+ if (im_floaterp)
{
- session_to_show = ((LLFloaterIMPanel*)im_floaterp)->getSessionID();
+ if (im_floaterp->isFrontmost())
+ {
+ session_to_show = ((LLFloaterIMPanel*)im_floaterp)->getSessionID();
+ }
+ chatterbox_instance->addFloater(im_floaterp, FALSE);
}
- LLFloaterChatterBox::getInstance()->addFloater(im_floaterp, FALSE);
}
+ LLFloaterReg::showInstance("communicate", session_to_show);
}
-
- LLFloaterChatterBox::showInstance(session_to_show);
}
else if (selected_option.asString() == "mute list")
{
- LLFloaterMute::showInstance();
+ LLPanelBlockedList::showPanelAndSelect(LLUUID::null);
}
else if (selected_option.isUndefined()) // user just clicked the communicate button, treat as toggle
{
- if (LLFloaterChatterBox::getInstance()->getFloaterCount() == 0)
- {
- LLFloaterMyFriends::toggleInstance();
+ LLFloaterReg::toggleInstance("communicate");
}
- else
- {
- LLFloaterChatterBox::toggleInstance();
- }
- }
- else // otherwise selection_option is a specific IM session id
+ else // otherwise selection_option is undifined or a specific IM session id
{
- LLFloaterChatterBox::showInstance(selected_option);
+ LLFloaterReg::showInstance("communicate", selected_option);
}
}
-// static
-void LLToolBar::onClickChat(void* user_data)
-{
- handle_chat(NULL);
-}
-
-// static
-void LLToolBar::onClickAppearance(void*)
-{
- if (gAgent.areWearablesLoaded())
- {
- gAgent.changeCameraToCustomizeAvatar();
- }
-}
-
-
-// static
-void LLToolBar::onClickFly(void*)
-{
- gAgent.toggleFlying();
-}
-
-
-// static
-void LLToolBar::onClickSit(void*)
-{
- if (!(gAgent.getControlFlags() & AGENT_CONTROL_SIT_ON_GROUND))
- {
- // sit down
- gAgent.setFlying(FALSE);
- gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
-
- // Might be first sit
- LLFirstUse::useSit();
- }
- else
- {
- // stand up
- gAgent.setFlying(FALSE);
- gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
- }
-}
-
-
-// static
-void LLToolBar::onClickSnapshot(void*)
-{
- LLFloaterSnapshot::show (0);
-}
-
-
-// static
-void LLToolBar::onClickDirectory(void*)
-{
- handle_find(NULL);
-}
-
-
-// static
-void LLToolBar::onClickBuild(void*)
-{
- toggle_build_mode();
-}
-
-
-// static
-void LLToolBar::onClickRadar(void*)
-{
- handle_mini_map(NULL);
-}
-
-
-// static
-void LLToolBar::onClickMap(void*)
-{
- handle_map(NULL);
-}
-
-
-// static
-void LLToolBar::onClickInventory(void*)
-{
- handle_inventory(NULL);
-}
-
diff --git a/indra/newview/lltoolbar.h b/indra/newview/lltoolbar.h
index 094d016e39..954c6270a6 100644
--- a/indra/newview/lltoolbar.h
+++ b/indra/newview/lltoolbar.h
@@ -37,12 +37,7 @@
#include "llframetimer.h"
-// "Constants" loaded from settings.xml at start time
-extern S32 TOOL_BAR_HEIGHT;
-
-#if LL_DARWIN
- class LLFakeResizeHandle;
-#endif // LL_DARWIN
+class LLResizeHandle;
class LLToolBar
: public LLPanel
@@ -71,17 +66,7 @@ public:
void refresh();
// callbacks
- static void onClickCommunicate(LLUICtrl*, void*);
- static void onClickChat(void* data);
- static void onClickAppearance(void* data);
- static void onClickFly(void*);
- static void onClickSit(void*);
- static void onClickSnapshot(void* data);
- static void onClickDirectory(void* data);
- static void onClickBuild(void* data);
- static void onClickRadar(void* data);
- static void onClickMap(void* data);
- static void onClickInventory(void* data);
+ static void onClickCommunicate(LLUICtrl*, const LLSD&);
static F32 sInventoryAutoOpenTime;
@@ -94,7 +79,7 @@ private:
LLFrameTimer mInventoryAutoOpenTimer;
S32 mNumUnreadIMs;
#if LL_DARWIN
- LLFakeResizeHandle *mResizeHandle;
+ LLResizeHandle *mResizeHandle;
#endif // LL_DARWIN
};
diff --git a/indra/newview/lltoolbrush.cpp b/indra/newview/lltoolbrush.cpp
index c42693d03f..3593064bef 100644
--- a/indra/newview/lltoolbrush.cpp
+++ b/indra/newview/lltoolbrush.cpp
@@ -35,9 +35,10 @@
#include "lltoolbrush.h"
#include "lltoolselectland.h"
+// library headers
#include "llgl.h"
+#include "llnotificationsutil.h"
#include "llrender.h"
-
#include "message.h"
#include "llagent.h"
@@ -412,7 +413,7 @@ BOOL LLToolBrushLand::handleHover( S32 x, S32 y, MASK mask )
mMouseX = x;
mMouseY = y;
mGotHover = TRUE;
- gViewerWindow->getWindow()->setCursor(UI_CURSOR_TOOLLAND);
+ gViewerWindow->setCursor(UI_CURSOR_TOOLLAND);
return TRUE;
}
@@ -672,7 +673,7 @@ void LLToolBrushLand::alertNoTerraform(LLViewerRegion* regionp)
LLSD args;
args["REGION"] = regionp->getName();
- LLNotifications::instance().add("RegionNoTerraforming", args);
+ LLNotificationsUtil::add("RegionNoTerraforming", args);
}
diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp
index 0b6e01886a..fff18df442 100644
--- a/indra/newview/lltoolcomp.cpp
+++ b/indra/newview/lltoolcomp.cpp
@@ -34,6 +34,7 @@
#include "lltoolcomp.h"
+#include "llfloaterreg.h"
#include "llgl.h"
#include "indra_constants.h"
@@ -64,6 +65,9 @@ const S32 HPAD = 4;
extern LLControlGroup gSavedSettings;
+// we use this in various places instead of NULL
+static LLTool* sNullTool = new LLTool(std::string("null"), NULL);
+
//-----------------------------------------------------------------------
// LLToolComposite
@@ -87,7 +91,9 @@ void LLToolComposite::setCurrentTool( LLTool* new_tool )
LLToolComposite::LLToolComposite(const std::string& name)
: LLTool(name),
- mCur(NULL), mDefault(NULL), mSelected(FALSE),
+ mCur(sNullTool),
+ mDefault(sNullTool),
+ mSelected(FALSE),
mMouseDown(FALSE), mManip(NULL), mSelectRect(NULL)
{
}
@@ -290,7 +296,7 @@ BOOL LLToolCompTranslate::handleDoubleClick(S32 x, S32 y, MASK mask)
{
// You should already have an object selected from the mousedown.
// If so, show its properties
- gFloaterTools->showPanel(LLFloaterTools::PANEL_CONTENTS);
+ LLFloaterReg::showInstance("build", "Content");
return TRUE;
}
// Nothing selected means the first mouse click was probably
@@ -407,8 +413,7 @@ BOOL LLToolCompScale::handleDoubleClick(S32 x, S32 y, MASK mask)
{
// You should already have an object selected from the mousedown.
// If so, show its properties
- gFloaterTools->showPanel(LLFloaterTools::PANEL_CONTENTS);
- //gBuildView->setPropertiesPanelOpen(TRUE);
+ LLFloaterReg::showInstance("build", "Content");
return TRUE;
}
else
@@ -605,8 +610,7 @@ BOOL LLToolCompRotate::handleDoubleClick(S32 x, S32 y, MASK mask)
{
// You should already have an object selected from the mousedown.
// If so, show its properties
- gFloaterTools->showPanel(LLFloaterTools::PANEL_CONTENTS);
- //gBuildView->setPropertiesPanelOpen(TRUE);
+ LLFloaterReg::showInstance("build", "Content");
return TRUE;
}
else
@@ -638,7 +642,7 @@ LLToolCompGun::LLToolCompGun()
{
mGun = new LLToolGun(this);
mGrab = new LLToolGrab(this);
- mNull = new LLTool(std::string("null"), this);
+ mNull = sNullTool;
setCurrentTool(mGun);
mDefault = mGun;
@@ -653,7 +657,8 @@ LLToolCompGun::~LLToolCompGun()
delete mGrab;
mGrab = NULL;
- delete mNull;
+ // don't delete a static object
+ // delete mNull;
mNull = NULL;
}
@@ -760,10 +765,6 @@ void LLToolCompGun::onMouseCaptureLost()
return;
}
mCur->onMouseCaptureLost();
-
- // JC - I don't know if this is necessary. Maybe we could lose capture
- // if someone ALT-Tab's out when in mouselook.
- setCurrentTool( (LLTool*) mGun );
}
void LLToolCompGun::handleSelect()
diff --git a/indra/newview/lltoolcomp.h b/indra/newview/lltoolcomp.h
index b24ba25d5a..81ed0ba8e4 100644
--- a/indra/newview/lltoolcomp.h
+++ b/indra/newview/lltoolcomp.h
@@ -229,6 +229,7 @@ public:
virtual void onMouseCaptureLost();
virtual void handleSelect();
virtual void handleDeselect();
+ virtual LLTool* getOverrideTool(MASK mask) { return NULL; }
protected:
LLToolGun* mGun;
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index 156093a21a..4420b046d8 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -31,44 +31,37 @@
*/
#include "llviewerprecompiledheaders.h"
-
-#include "message.h"
#include "lltooldraganddrop.h"
-#include "llinstantmessage.h"
-#include "lldir.h"
-
+// library headers
+#include "llnotificationsutil.h"
+// project headers
#include "llagent.h"
-#include "llviewercontrol.h"
-#include "llfirstuse.h"
-#include "llfloater.h"
+#include "llagentui.h"
+#include "llagentwearables.h"
+#include "llappearancemgr.h"
+#include "lldictionary.h"
+//#include "llfirstuse.h"
+#include "llfloaterreg.h"
#include "llfloatertools.h"
-#include "llfocusmgr.h"
#include "llgesturemgr.h"
-#include "llhudeffecttrail.h"
#include "llhudmanager.h"
-#include "llinventorymodel.h"
-#include "llinventoryview.h"
+#include "llhudeffecttrail.h"
+#include "llimview.h"
+#include "llinventorybridge.h"
#include "llmutelist.h"
-#include "llnotify.h"
#include "llpreviewnotecard.h"
+#include "llrecentpeople.h"
+#include "llrootview.h"
#include "llselectmgr.h"
#include "lltoolmgr.h"
+#include "lltooltip.h"
#include "lltrans.h"
-#include "llui.h"
-#include "llviewerimagelist.h"
-#include "llviewerinventory.h"
-#include "llviewerobject.h"
#include "llviewerobjectlist.h"
-#include "llviewerregion.h"
#include "llviewerstats.h"
#include "llviewerwindow.h"
-#include "llvoavatar.h"
-#include "llvolume.h"
+#include "llvoavatarself.h"
#include "llworld.h"
-#include "object_flags.h"
-#include "llimview.h"
-
// MAX ITEMS is based on (sizeof(uuid)+2) * count must be < MTUBYTES
// or 18 * count < 1200 => count < 1200/18 => 66. I've cut it down a
@@ -86,7 +79,7 @@ public:
virtual bool operator()(LLInventoryCategory* cat,
LLInventoryItem* item)
{
- if(cat && (cat->getPreferredType() == LLAssetType::AT_NONE))
+ if(cat && (cat->getPreferredType() == LLFolderType::FT_NONE))
{
return true;
}
@@ -103,7 +96,7 @@ public:
LLInventoryItem* item)
{
if(item) return true;
- if(cat && (cat->getPreferredType() == LLAssetType::AT_NONE))
+ if(cat && (cat->getPreferredType() == LLFolderType::FT_NONE))
{
return true;
}
@@ -349,126 +342,51 @@ void LLCategoryDropDescendentsObserver::done()
delete this;
}
-// This array is used to more easily control what happens when a 3d
-// drag and drop event occurs. Since there's an array of drop target
-// and cargo type, it's implemented as an array of pointers to member
-// functions which correctly carry out the actual drop.
-LLToolDragAndDrop::dragOrDrop3dImpl LLToolDragAndDrop::sDragAndDrop3d[DAD_COUNT][LLToolDragAndDrop::DT_COUNT] =
-{
- // Source: DAD_NONE
- {
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_AVATAR
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_OBJECT
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_LAND
- },
- // Source: DAD_TEXTURE
- {
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF
- &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR
- &LLToolDragAndDrop::dad3dTextureObject, // Dest: DT_OBJECT
- &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND
- },
- // Source: DAD_SOUND
- {
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF
- &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR
- &LLToolDragAndDrop::dad3dUpdateInventory, // Dest: DT_OBJECT
- &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND
- },
- // Source: DAD_CALLINGCARD
- {
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_AVATAR
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_OBJECT
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_LAND
- },
- // Source: DAD_LANDMARK
- {
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF
- &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR
- &LLToolDragAndDrop::dad3dUpdateInventory, // Dest: DT_OBJECT
- &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND
- },
- // Source: DAD_SCRIPT
- {
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF
- &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR
- &LLToolDragAndDrop::dad3dRezScript, // Dest: DT_OBJECT
- &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND
- },
- // Source: DAD_CLOTHING
- {
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE
- &LLToolDragAndDrop::dad3dWearItem, // Dest: DT_SELF
- &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR
- &LLToolDragAndDrop::dad3dUpdateInventory, // Dest: DT_OBJECT
- &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND
- },
- // Source: DAD_OBJECT
- {
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE
- &LLToolDragAndDrop::dad3dRezAttachmentFromInv, // Dest: DT_SELF
- &LLToolDragAndDrop::dad3dGiveInventoryObject, // Dest: DT_AVATAR
- &LLToolDragAndDrop::dad3dRezObjectOnObject, // Dest: DT_OBJECT
- &LLToolDragAndDrop::dad3dRezObjectOnLand, // Dest: DT_LAND
- },
- // Source: DAD_NOTECARD
- {
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF
- &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR
- &LLToolDragAndDrop::dad3dUpdateInventory, // Dest: DT_OBJECT
- &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND
- },
- // Source: DAD_CATEGORY
- {
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE
- &LLToolDragAndDrop::dad3dWearCategory, // Dest: DT_SELF
- &LLToolDragAndDrop::dad3dGiveInventoryCategory, // Dest: DT_AVATAR
- &LLToolDragAndDrop::dad3dUpdateInventoryCategory, // Dest: DT_OBJECT
- &LLToolDragAndDrop::dad3dNULL,//dad3dCategoryOnLand, // Dest: DT_LAND
- },
- // Source: DAD_ROOT
- {
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_AVATAR
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_OBJECT
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_LAND
- },
- // Source: DAD_BODYPART
- {
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE
- &LLToolDragAndDrop::dad3dWearItem, // Dest: DT_SELF
- &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR
- &LLToolDragAndDrop::dad3dUpdateInventory, // Dest: DT_OBJECT
- &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND
- },
- // Source: DAD_ANIMATION
- // TODO: animation on self could play it? edit it?
+LLToolDragAndDrop::DragAndDropEntry::DragAndDropEntry(dragOrDrop3dImpl f_none,
+ dragOrDrop3dImpl f_self,
+ dragOrDrop3dImpl f_avatar,
+ dragOrDrop3dImpl f_object,
+ dragOrDrop3dImpl f_land) :
+ LLDictionaryEntry("")
+{
+ mFunctions[DT_NONE] = f_none;
+ mFunctions[DT_SELF] = f_self;
+ mFunctions[DT_AVATAR] = f_avatar;
+ mFunctions[DT_OBJECT] = f_object;
+ mFunctions[DT_LAND] = f_land;
+}
+
+LLToolDragAndDrop::dragOrDrop3dImpl LLToolDragAndDrop::LLDragAndDropDictionary::get(EDragAndDropType dad_type, LLToolDragAndDrop::EDropTarget drop_target)
+{
+ const DragAndDropEntry *entry = lookup(dad_type);
+ if (entry)
{
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF
- &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR
- &LLToolDragAndDrop::dad3dUpdateInventory, // Dest: DT_OBJECT
- &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND
- },
- // Source: DAD_GESTURE
+ return (entry->mFunctions[(U8)drop_target]);
+ }
+ return &LLToolDragAndDrop::dad3dNULL;
+}
+
+LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary()
+{
+ // DT_NONE DT_SELF DT_AVATAR DT_OBJECT DT_LAND
+ // |--------------|---------------------------|---------------------------|-------------------------------|--------------|
+ addEntry(DAD_NONE, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL));
+ addEntry(DAD_TEXTURE, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dTextureObject, &LLToolDragAndDrop::dad3dNULL));
+ addEntry(DAD_SOUND, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
+ addEntry(DAD_CALLINGCARD, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
+ addEntry(DAD_LANDMARK, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
+ addEntry(DAD_SCRIPT, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dRezScript, &LLToolDragAndDrop::dad3dNULL));
+ addEntry(DAD_CLOTHING, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dWearItem, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
+ addEntry(DAD_OBJECT, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dRezAttachmentFromInv, &LLToolDragAndDrop::dad3dGiveInventoryObject, &LLToolDragAndDrop::dad3dRezObjectOnObject, &LLToolDragAndDrop::dad3dRezObjectOnLand));
+ addEntry(DAD_NOTECARD, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
+ addEntry(DAD_CATEGORY, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dWearCategory, &LLToolDragAndDrop::dad3dGiveInventoryCategory,&LLToolDragAndDrop::dad3dUpdateInventoryCategory, &LLToolDragAndDrop::dad3dNULL));
+ addEntry(DAD_ROOT_CATEGORY, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL));
+ addEntry(DAD_BODYPART, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dWearItem, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
+ addEntry(DAD_ANIMATION, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
+ addEntry(DAD_GESTURE, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dActivateGesture, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
+ addEntry(DAD_LINK, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL));
+ // TODO: animation on self could play it? edit it?
// TODO: gesture on self could play it? edit it?
- {
- &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE
- &LLToolDragAndDrop::dad3dActivateGesture, // Dest: DT_SELF
- &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR
- &LLToolDragAndDrop::dad3dUpdateInventory, // Dest: DT_OBJECT
- &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND
- },
};
LLToolDragAndDrop::LLToolDragAndDrop()
@@ -633,6 +551,7 @@ void LLToolDragAndDrop::beginMultiDrag(
void LLToolDragAndDrop::endDrag()
{
+ mEndDragSignal();
LLSelectMgr::getInstance()->unhighlightAll();
setMouseCapture(FALSE);
}
@@ -747,12 +666,13 @@ BOOL LLToolDragAndDrop::handleKey(KEY key, MASK mask)
return FALSE;
}
-BOOL LLToolDragAndDrop::handleToolTip(S32 x, S32 y, std::string& msg, LLRect *sticky_rect_screen)
+BOOL LLToolDragAndDrop::handleToolTip(S32 x, S32 y, MASK mask)
{
if (!mToolTipMsg.empty())
{
- msg = mToolTipMsg;
- //*sticky_rect_screen = gViewerWindow->getWindowRect();
+ LLToolTipMgr::instance().show(LLToolTip::Params()
+ .message(mToolTipMsg)
+ .delay_time(gSavedSettings.getF32( "DragAndDropToolTipDelay" )));
return TRUE;
}
return FALSE;
@@ -846,12 +766,15 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,
{
handled = TRUE;
- LLView* root_view = gViewerWindow->getRootView();
+ LLRootView* root_view = gViewerWindow->getRootView();
for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)
{
LLInventoryObject* cargo = locateInventory(item, cat);
+ // fix for EXT-3191
+ if (NULL == cargo) return;
+
EAcceptance item_acceptance = ACCEPT_NO;
handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE,
mCargoTypes[mCurItemIndex],
@@ -909,7 +832,7 @@ void LLToolDragAndDrop::dragOrDrop3D( S32 x, S32 y, MASK mask, BOOL drop, EAccep
if (mDrop)
{
// don't allow drag and drop onto transparent objects
- pickCallback(gViewerWindow->pickImmediate(x, y, FALSE));
+ pick(gViewerWindow->pickImmediate(x, y, FALSE));
}
else
{
@@ -922,6 +845,14 @@ void LLToolDragAndDrop::dragOrDrop3D( S32 x, S32 y, MASK mask, BOOL drop, EAccep
void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info)
{
+ if (getInstance() != NULL)
+ {
+ getInstance()->pick(pick_info);
+ }
+}
+
+void LLToolDragAndDrop::pick(const LLPickInfo& pick_info)
+{
EDropTarget target = DT_NONE;
S32 hit_face = -1;
@@ -929,31 +860,30 @@ void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info)
LLSelectMgr::getInstance()->unhighlightAll();
// Treat attachments as part of the avatar they are attached to.
- if (hit_obj)
+ if (hit_obj != NULL)
{
// don't allow drag and drop on grass, trees, etc.
- if(pick_info.mPickType == LLPickInfo::PICK_FLORA)
+ if (pick_info.mPickType == LLPickInfo::PICK_FLORA)
{
- LLToolDragAndDrop::getInstance()->mCursor = UI_CURSOR_NO;
- gViewerWindow->getWindow()->setCursor( LLToolDragAndDrop::getInstance()->mCursor );
+ mCursor = UI_CURSOR_NO;
+ gViewerWindow->getWindow()->setCursor( mCursor );
return;
}
- if(hit_obj->isAttachment() && !hit_obj->isHUDAttachment())
+ if (hit_obj->isAttachment() && !hit_obj->isHUDAttachment())
{
LLVOAvatar* avatar = LLVOAvatar::findAvatarFromAttachment( hit_obj );
if( !avatar )
{
- LLToolDragAndDrop::getInstance()->mLastAccept = ACCEPT_NO;
- LLToolDragAndDrop::getInstance()->mCursor = UI_CURSOR_NO;
- gViewerWindow->getWindow()->setCursor( LLToolDragAndDrop::getInstance()->mCursor );
+ mLastAccept = ACCEPT_NO;
+ mCursor = UI_CURSOR_NO;
+ gViewerWindow->getWindow()->setCursor( mCursor );
return;
}
-
hit_obj = avatar;
}
- if(hit_obj->isAvatar())
+ if (hit_obj->isAvatar())
{
if(((LLVOAvatar*) hit_obj)->isSelf())
{
@@ -972,9 +902,9 @@ void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info)
hit_face = pick_info.mObjectFace;
// if any item being dragged will be applied to the object under our cursor
// highlight that object
- for (S32 i = 0; i < (S32)LLToolDragAndDrop::getInstance()->mCargoIDs.size(); i++)
+ for (S32 i = 0; i < (S32)mCargoIDs.size(); i++)
{
- if (LLToolDragAndDrop::getInstance()->mCargoTypes[i] != DAD_OBJECT || (pick_info.mKeyMask & MASK_CONTROL))
+ if (mCargoTypes[i] != DAD_OBJECT || (pick_info.mKeyMask & MASK_CONTROL))
{
LLSelectMgr::getInstance()->highlightObjectAndFamily(hit_obj);
break;
@@ -982,55 +912,54 @@ void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info)
}
}
}
- else if(pick_info.mPickType == LLPickInfo::PICK_LAND)
+ else if (pick_info.mPickType == LLPickInfo::PICK_LAND)
{
target = DT_LAND;
hit_face = -1;
}
- LLToolDragAndDrop::getInstance()->mLastAccept = ACCEPT_YES_MULTI;
+ mLastAccept = ACCEPT_YES_MULTI;
- for (LLToolDragAndDrop::getInstance()->mCurItemIndex = 0; LLToolDragAndDrop::getInstance()->mCurItemIndex < (S32)LLToolDragAndDrop::getInstance()->mCargoIDs.size();
- LLToolDragAndDrop::getInstance()->mCurItemIndex++)
+ for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)
{
+ const S32 item_index = mCurItemIndex;
+ const EDragAndDropType dad_type = mCargoTypes[item_index];
// Call the right implementation function
- LLToolDragAndDrop::getInstance()->mLastAccept = (EAcceptance)llmin(
- (U32)LLToolDragAndDrop::getInstance()->mLastAccept,
- (U32)callMemberFunction((*LLToolDragAndDrop::getInstance()),
- LLToolDragAndDrop::getInstance()->sDragAndDrop3d[LLToolDragAndDrop::getInstance()->mCargoTypes[LLToolDragAndDrop::getInstance()->mCurItemIndex]][target])
- (hit_obj, hit_face, pick_info.mKeyMask, FALSE));
+ mLastAccept = (EAcceptance)llmin(
+ (U32)mLastAccept,
+ (U32)callMemberFunction(*this,
+ LLDragAndDropDictionary::instance().get(dad_type, target))
+ (hit_obj, hit_face, pick_info.mKeyMask, FALSE));
}
- if (LLToolDragAndDrop::getInstance()->mDrop &&
- (U32)LLToolDragAndDrop::getInstance()->mLastAccept >= ACCEPT_YES_COPY_SINGLE)
+ if (mDrop && ((U32)mLastAccept >= ACCEPT_YES_COPY_SINGLE))
{
// if target allows multi-drop or there is only one item being dropped, go ahead
- if (LLToolDragAndDrop::getInstance()->mLastAccept >= ACCEPT_YES_COPY_MULTI ||
- LLToolDragAndDrop::getInstance()->mCargoIDs.size() == 1)
+ if ((mLastAccept >= ACCEPT_YES_COPY_MULTI) || (mCargoIDs.size() == 1))
{
// Target accepts multi, or cargo is a single-drop
- for (LLToolDragAndDrop::getInstance()->mCurItemIndex = 0;
- LLToolDragAndDrop::getInstance()->mCurItemIndex < (S32)LLToolDragAndDrop::getInstance()->mCargoIDs.size();
- LLToolDragAndDrop::getInstance()->mCurItemIndex++)
+ for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)
{
+ const S32 item_index = mCurItemIndex;
+ const EDragAndDropType dad_type = mCargoTypes[item_index];
// Call the right implementation function
- (U32)callMemberFunction((*LLToolDragAndDrop::getInstance()),
- LLToolDragAndDrop::getInstance()->sDragAndDrop3d[LLToolDragAndDrop::getInstance()->mCargoTypes[LLToolDragAndDrop::getInstance()->mCurItemIndex]][target])
+ (U32)callMemberFunction(*this,
+ LLDragAndDropDictionary::instance().get(dad_type, target))
(hit_obj, hit_face, pick_info.mKeyMask, TRUE);
}
}
else
{
// Target does not accept multi, but cargo is multi
- LLToolDragAndDrop::getInstance()->mLastAccept = ACCEPT_NO;
+ mLastAccept = ACCEPT_NO;
}
}
- ECursorType cursor = LLToolDragAndDrop::getInstance()->acceptanceToCursor( LLToolDragAndDrop::getInstance()->mLastAccept );
+ ECursorType cursor = acceptanceToCursor( mLastAccept );
gViewerWindow->getWindow()->setCursor( cursor );
- LLToolDragAndDrop::getInstance()->mLastHitPos = pick_info.mPosGlobal;
- LLToolDragAndDrop::getInstance()->mLastCameraPos = gAgent.getCameraPositionGlobal();
+ mLastHitPos = pick_info.mPosGlobal;
+ mLastCameraPos = gAgent.getCameraPositionGlobal();
}
// static
@@ -1055,7 +984,7 @@ BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj,
hit_obj->fetchInventoryFromServer();
LLSD args;
args["ERROR_MESSAGE"] = "Unable to add texture.\nPlease wait a few seconds and try again.";
- LLNotifications::instance().add("ErrorMessage", args);
+ LLNotificationsUtil::add("ErrorMessage", args);
return FALSE;
}
if (hit_obj->getInventoryItemByAsset(item->getAssetUUID()))
@@ -1142,7 +1071,7 @@ void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj,
{
return;
}
- LLViewerImage* image = gImageList.getImage(asset_id);
+ LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(asset_id);
LLViewerStats::getInstance()->incStat(LLViewerStats::ST_EDIT_TEXTURE_COUNT );
S32 num_faces = hit_obj->getNumTEs();
for( S32 face = 0; face < num_faces; face++ )
@@ -1160,7 +1089,7 @@ void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj,
void LLToolDragAndDrop::dropTextureOneFaceAvatar(LLVOAvatar* avatar, S32 hit_face, LLInventoryItem* item)
{
if (hit_face == -1) return;
- LLViewerImage* image = gImageList.getImage(item->getAssetUUID());
+ LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(item->getAssetUUID());
avatar->userSetOptionalTE( hit_face, image);
}
@@ -1185,7 +1114,7 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj,
return;
}
// update viewer side image in anticipation of update from simulator
- LLViewerImage* image = gImageList.getImage(asset_id);
+ LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(asset_id);
LLViewerStats::getInstance()->incStat(LLViewerStats::ST_EDIT_TEXTURE_COUNT );
hit_obj->setTEImage(hit_face, image);
dialog_refresh_all();
@@ -1270,11 +1199,11 @@ void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target,
locateInventory(item, cat);
if(!item || !item->isComplete()) return;
- if (regionp
- && (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX))
- {
- LLFirstUse::useSandbox();
- }
+ //if (regionp
+ // && (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX))
+ //{
+ // LLFirstUse::useSandbox();
+ //}
// check if it cannot be copied, and mark as remove if it is -
// this will remove the object from inventory after rez. Only
// bother with this check if we would not normally remove from
@@ -1301,8 +1230,7 @@ void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target,
// Check if it's in the trash.
bool is_in_trash = false;
- LLUUID trash_id;
- trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id))
{
is_in_trash = true;
@@ -1461,10 +1389,10 @@ void LLToolDragAndDrop::dropInventory(LLViewerObject* hit_obj,
}
}
hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true);
- if (gFloaterTools->getVisible())
+ if (LLFloaterReg::instanceVisible("build"))
{
// *FIX: only show this if panel not expanded?
- gFloaterTools->showPanel(LLFloaterTools::PANEL_CONTENTS);
+ LLFloaterReg::showInstance("build", "Content");
}
// VEFFECT: AddToInventory
@@ -1509,14 +1437,14 @@ void LLToolDragAndDrop::giveInventory(const LLUUID& to_agent,
LLSD payload;
payload["agent_id"] = to_agent;
payload["item_id"] = item->getUUID();
- LLNotifications::instance().add("CannotCopyWarning", LLSD(), payload,
+ LLNotificationsUtil::add("CannotCopyWarning", LLSD(), payload,
&LLToolDragAndDrop::handleCopyProtectedItem);
}
}
// static
bool LLToolDragAndDrop::handleCopyProtectedItem(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLInventoryItem* item = NULL;
switch(option)
{
@@ -1533,12 +1461,12 @@ bool LLToolDragAndDrop::handleCopyProtectedItem(const LLSD& notification, const
}
else
{
- LLNotifications::instance().add("CannotGiveItem");
+ LLNotificationsUtil::add("CannotGiveItem");
}
break;
default: // no, cancel, whatever, who cares, not yes.
- LLNotifications::instance().add("TransactionCancelled");
+ LLNotificationsUtil::add("TransactionCancelled");
break;
}
return false;
@@ -1551,7 +1479,7 @@ void LLToolDragAndDrop::commitGiveInventoryItem(const LLUUID& to_agent,
{
if(!item) return;
std::string name;
- gAgent.buildFullname(name);
+ LLAgentUI::buildFullname(name);
LLUUID transaction_id;
transaction_id.generate();
const S32 BUCKET_SIZE = sizeof(U8) + UUID_BYTES;
@@ -1594,6 +1522,8 @@ void LLToolDragAndDrop::commitGiveInventoryItem(const LLUUID& to_agent,
gIMMgr->addSystemMessage(im_session_id, "inventory_item_offered", args);
}
+ // add buddy to recent people list
+ LLRecentPeople::instance().add(to_agent);
}
void LLToolDragAndDrop::giveInventoryCategory(const LLUUID& to_agent,
@@ -1632,18 +1562,18 @@ void LLToolDragAndDrop::giveInventoryCategory(const LLUUID& to_agent,
}
if(!complete)
{
- LLNotifications::instance().add("IncompleteInventory");
+ LLNotificationsUtil::add("IncompleteInventory");
return;
}
count = items.count() + cats.count();
if(count > MAX_ITEMS)
{
- LLNotifications::instance().add("TooManyItems");
+ LLNotificationsUtil::add("TooManyItems");
return;
}
else if(count == 0)
{
- LLNotifications::instance().add("NoItems");
+ LLNotificationsUtil::add("NoItems");
return;
}
else
@@ -1661,7 +1591,7 @@ void LLToolDragAndDrop::giveInventoryCategory(const LLUUID& to_agent,
LLSD payload;
payload["agent_id"] = to_agent;
payload["folder_id"] = cat->getUUID();
- LLNotifications::instance().add("CannotCopyCountItems", args, payload, &LLToolDragAndDrop::handleCopyProtectedCategory);
+ LLNotificationsUtil::add("CannotCopyCountItems", args, payload, &LLToolDragAndDrop::handleCopyProtectedCategory);
}
}
}
@@ -1670,7 +1600,7 @@ void LLToolDragAndDrop::giveInventoryCategory(const LLUUID& to_agent,
// static
bool LLToolDragAndDrop::handleCopyProtectedCategory(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLInventoryCategory* cat = NULL;
switch(option)
{
@@ -1697,12 +1627,12 @@ bool LLToolDragAndDrop::handleCopyProtectedCategory(const LLSD& notification, co
}
else
{
- LLNotifications::instance().add("CannotGiveCategory");
+ LLNotificationsUtil::add("CannotGiveCategory");
}
break;
default: // no, cancel, whatever, who cares, not yes.
- LLNotifications::instance().add("TransactionCancelled");
+ LLNotificationsUtil::add("TransactionCancelled");
break;
}
return false;
@@ -1718,6 +1648,9 @@ void LLToolDragAndDrop::commitGiveInventoryCategory(const LLUUID& to_agent,
llinfos << "LLToolDragAndDrop::commitGiveInventoryCategory() - "
<< cat->getUUID() << llendl;
+ // add buddy to recent people list
+ LLRecentPeople::instance().add(to_agent);
+
// Test out how many items are being given.
LLViewerInventoryCategory::cat_array_t cats;
LLViewerInventoryItem::item_array_t items;
@@ -1734,18 +1667,18 @@ void LLToolDragAndDrop::commitGiveInventoryCategory(const LLUUID& to_agent,
S32 count = items.count() + cats.count();
if(count > MAX_ITEMS)
{
- LLNotifications::instance().add("TooManyItems");
+ LLNotificationsUtil::add("TooManyItems");
return;
}
else if(count == 0)
{
- LLNotifications::instance().add("NoItems");
+ LLNotificationsUtil::add("NoItems");
return;
}
else
{
std::string name;
- gAgent.buildFullname(name);
+ LLAgentUI::buildFullname(name);
LLUUID transaction_id;
transaction_id.generate();
S32 bucket_size = (sizeof(U8) + UUID_BYTES) * (count + 1);
@@ -1827,7 +1760,7 @@ BOOL LLToolDragAndDrop::isInventoryGiveAcceptable(LLInventoryItem* item)
BOOL copyable = FALSE;
if(item->getPermissions().allowCopyBy(gAgent.getID())) copyable = TRUE;
- LLVOAvatar* my_avatar = gAgent.getAvatarObject();
+ LLVOAvatarSelf* my_avatar = gAgent.getAvatarObject();
if(!my_avatar)
{
return FALSE;
@@ -1836,9 +1769,6 @@ BOOL LLToolDragAndDrop::isInventoryGiveAcceptable(LLInventoryItem* item)
BOOL acceptable = TRUE;
switch(item->getType())
{
- case LLAssetType::AT_CALLINGCARD:
- acceptable = FALSE;
- break;
case LLAssetType::AT_OBJECT:
if(my_avatar->isWearingAttachment(item->getUUID()))
{
@@ -1847,7 +1777,7 @@ BOOL LLToolDragAndDrop::isInventoryGiveAcceptable(LLInventoryItem* item)
break;
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_CLOTHING:
- if(!copyable && gAgent.isWearingItem(item->getUUID()))
+ if(!copyable && gAgentWearables.isWearingItem(item->getUUID()))
{
acceptable = FALSE;
}
@@ -1877,7 +1807,7 @@ BOOL LLToolDragAndDrop::isInventoryGroupGiveAcceptable(LLInventoryItem* item)
return FALSE;
}
- LLVOAvatar* my_avatar = gAgent.getAvatarObject();
+ LLVOAvatarSelf* my_avatar = gAgent.getAvatarObject();
if(!my_avatar)
{
return FALSE;
@@ -1886,9 +1816,6 @@ BOOL LLToolDragAndDrop::isInventoryGroupGiveAcceptable(LLInventoryItem* item)
BOOL acceptable = TRUE;
switch(item->getType())
{
- case LLAssetType::AT_CALLINGCARD:
- acceptable = FALSE;
- break;
case LLAssetType::AT_OBJECT:
if(my_avatar->isWearingAttachment(item->getUUID()))
{
@@ -1906,10 +1833,11 @@ BOOL LLToolDragAndDrop::isInventoryGroupGiveAcceptable(LLInventoryItem* item)
EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item)
{
// check the basics
- if(!item || !obj) return ACCEPT_NO;
+ if (!item || !obj) return ACCEPT_NO;
// HACK: downcast
LLViewerInventoryItem* vitem = (LLViewerInventoryItem*)item;
- if(!vitem->isComplete()) return ACCEPT_NO;
+ if (!vitem->isComplete()) return ACCEPT_NO;
+ if (vitem->getIsLinkType()) return ACCEPT_NO; // No giving away links
// deny attempts to drop from an object onto itself. This is to
// help make sure that drops that are from an object to an object
@@ -1919,12 +1847,12 @@ EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LL
{
return ACCEPT_NO;
}
-
+
//BOOL copy = (perm.allowCopyBy(gAgent.getID(),
// gAgent.getGroupID())
// && (obj->mPermModify || obj->mFlagAllowInventoryAdd));
BOOL worn = FALSE;
- LLVOAvatar* my_avatar = NULL;
+ LLVOAvatarSelf* my_avatar = NULL;
switch(item->getType())
{
case LLAssetType::AT_OBJECT:
@@ -1936,7 +1864,7 @@ EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LL
break;
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_CLOTHING:
- if(gAgent.isWearingItem(item->getUUID()))
+ if(gAgentWearables.isWearingItem(item->getUUID()))
{
worn = TRUE;
}
@@ -1991,6 +1919,7 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_
case DAD_BODYPART:
case DAD_ANIMATION:
case DAD_GESTURE:
+ case DAD_CALLINGCARD:
{
LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;
if(gInventory.getItem(inv_item->getUUID())
@@ -2035,7 +1964,6 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_
}
break;
}
- case DAD_CALLINGCARD:
default:
*accept = ACCEPT_NO;
break;
@@ -2073,14 +2001,14 @@ EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv(
if(!item || !item->isComplete()) return ACCEPT_NO;
// must not be in the trash
- LLUUID trash_id(gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH));
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) )
{
return ACCEPT_NO;
}
// must not be already wearing it
- LLVOAvatar* avatar = gAgent.getAvatarObject();
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
if( !avatar || avatar->isWearingAttachment(item->getUUID()) )
{
return ACCEPT_NO;
@@ -2122,7 +2050,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezObjectOnLand(
locateInventory(item, cat);
if(!item || !item->isComplete()) return ACCEPT_NO;
- LLVOAvatar* my_avatar = gAgent.getAvatarObject();
+ LLVOAvatarSelf* my_avatar = gAgent.getAvatarObject();
if( !my_avatar || my_avatar->isWearingAttachment( item->getUUID() ) )
{
return ACCEPT_NO;
@@ -2155,8 +2083,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezObjectOnLand(
}
// Check if it's in the trash.
- LLUUID trash_id;
- trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id))
{
accept = ACCEPT_YES_SINGLE;
@@ -2185,7 +2112,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezObjectOnObject(
LLViewerInventoryCategory* cat;
locateInventory(item, cat);
if(!item || !item->isComplete()) return ACCEPT_NO;
- LLVOAvatar* my_avatar = gAgent.getAvatarObject();
+ LLVOAvatarSelf* my_avatar = gAgent.getAvatarObject();
if( !my_avatar || my_avatar->isWearingAttachment( item->getUUID() ) )
{
return ACCEPT_NO;
@@ -2234,8 +2161,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezObjectOnObject(
}
// Check if it's in the trash.
- LLUUID trash_id;
- trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id))
{
accept = ACCEPT_YES_SINGLE;
@@ -2373,7 +2299,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearItem(
if(mSource == SOURCE_AGENT || mSource == SOURCE_LIBRARY)
{
// it's in the agent inventory
- LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) )
{
return ACCEPT_NO;
@@ -2383,9 +2309,9 @@ EAcceptance LLToolDragAndDrop::dad3dWearItem(
{
// Don't wear anything until initial wearables are loaded, can
// destroy clothing items.
- if (!gAgent.areWearablesLoaded())
+ if (!gAgentWearables.areWearablesLoaded())
{
- LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
+ LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded");
return ACCEPT_NO;
}
@@ -2428,7 +2354,7 @@ EAcceptance LLToolDragAndDrop::dad3dActivateGesture(
if(mSource == SOURCE_AGENT || mSource == SOURCE_LIBRARY)
{
// it's in the agent inventory
- LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) )
{
return ACCEPT_NO;
@@ -2452,7 +2378,7 @@ EAcceptance LLToolDragAndDrop::dad3dActivateGesture(
}
else
{
- gGestureManager.activateGesture(item->getUUID());
+ LLGestureManager::instance().activateGesture(item->getUUID());
gInventory.updateItem(item);
gInventory.notifyObservers();
}
@@ -2478,16 +2404,16 @@ EAcceptance LLToolDragAndDrop::dad3dWearCategory(
{
// Don't wear anything until initial wearables are loaded, can
// destroy clothing items.
- if (!gAgent.areWearablesLoaded())
+ if (!gAgentWearables.areWearablesLoaded())
{
- LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
+ LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded");
return ACCEPT_NO;
}
}
if(mSource == SOURCE_AGENT)
{
- LLUUID trash_id(gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH));
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
if( gInventory.isObjectDescendentOf( category->getUUID(), trash_id ) )
{
return ACCEPT_NO;
@@ -2496,7 +2422,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearCategory(
if(drop)
{
BOOL append = ( (mask & MASK_SHIFT) ? TRUE : FALSE );
- wear_inventory_category(category, false, append);
+ LLAppearanceManager::instance().wearInventoryCategory(category, false, append);
}
return ACCEPT_YES_MULTI;
}
@@ -2504,7 +2430,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearCategory(
{
if(drop)
{
- wear_inventory_category(category, true, false);
+ LLAppearanceManager::instance().wearInventoryCategory(category, true, false);
}
return ACCEPT_YES_MULTI;
}
@@ -2560,24 +2486,30 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory(
LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
{
lldebugs << "LLToolDragAndDrop::dad3dUpdateInventoryCategory()" << llendl;
- if (NULL==obj)
+ if (obj == NULL)
{
llwarns << "obj is NULL; aborting func with ACCEPT_NO" << llendl;
return ACCEPT_NO;
}
- if (mSource != SOURCE_AGENT && mSource != SOURCE_LIBRARY)
+ if ((mSource != SOURCE_AGENT) && (mSource != SOURCE_LIBRARY))
{
return ACCEPT_NO;
}
- if(obj->isAttachment()) return ACCEPT_NO_LOCKED;
- LLViewerInventoryItem* item;
- LLViewerInventoryCategory* cat;
+ if (obj->isAttachment())
+ {
+ return ACCEPT_NO_LOCKED;
+ }
+
+ LLViewerInventoryItem* item = NULL;
+ LLViewerInventoryCategory* cat = NULL;
locateInventory(item, cat);
- if(!cat) return ACCEPT_NO;
- EAcceptance rv = ACCEPT_NO;
+ if (!cat)
+ {
+ return ACCEPT_NO;
+ }
- // find all the items in the category
+ // Find all the items in the category
LLDroppableItem droppable(!obj->permYouOwner());
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
@@ -2587,7 +2519,7 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory(
LLInventoryModel::EXCLUDE_TRASH,
droppable);
cats.put(cat);
- if(droppable.countNoCopy() > 0)
+ if (droppable.countNoCopy() > 0)
{
llwarns << "*** Need to confirm this step" << llendl;
}
@@ -2601,46 +2533,57 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory(
}
}
+ EAcceptance rv = ACCEPT_NO;
+
// Check for accept
- S32 i;
- S32 count = cats.count();
- for(i = 0; i < count; ++i)
+ for (LLInventoryModel::cat_array_t::const_iterator cat_iter = cats.begin();
+ cat_iter != cats.end();
+ ++cat_iter)
{
- rv = gInventory.isCategoryComplete(cats.get(i)->getUUID()) ? ACCEPT_YES_MULTI : ACCEPT_NO;
+ const LLViewerInventoryCategory *cat = (*cat_iter);
+ rv = gInventory.isCategoryComplete(cat->getUUID()) ? ACCEPT_YES_MULTI : ACCEPT_NO;
if(rv < ACCEPT_YES_SINGLE)
{
- lldebugs << "Category " << cats.get(i)->getUUID()
- << "is not complete." << llendl;
+ lldebugs << "Category " << cat->getUUID() << "is not complete." << llendl;
break;
}
}
- if(ACCEPT_YES_COPY_SINGLE <= rv)
+ if (ACCEPT_YES_COPY_SINGLE <= rv)
{
- count = items.count();
- for(i = 0; i < count; ++i)
+ for (LLInventoryModel::item_array_t::const_iterator item_iter = items.begin();
+ item_iter != items.end();
+ ++item_iter)
{
- rv = willObjectAcceptInventory(root_object, items.get(i));
- if(rv < ACCEPT_YES_COPY_SINGLE)
+ LLViewerInventoryItem *item = (*item_iter);
+ /*
+ // Pass the base objects, not the links.
+ if (item && item->getIsLinkType())
{
- lldebugs << "Object will not accept "
- << items.get(i)->getUUID() << llendl;
+ item = item->getLinkedItem();
+ (*item_iter) = item;
+ }
+ */
+ rv = willObjectAcceptInventory(root_object, item);
+ if (rv < ACCEPT_YES_COPY_SINGLE)
+ {
+ lldebugs << "Object will not accept " << item->getUUID() << llendl;
break;
}
}
}
- // if every item is accepted, go ahead and send it on.
- if(drop && (ACCEPT_YES_COPY_SINGLE <= rv))
+ // If every item is accepted, send it on
+ if (drop && (ACCEPT_YES_COPY_SINGLE <= rv))
{
- S32 count = items.count();
LLInventoryFetchObserver::item_ref_t ids;
- for(i = 0; i < count; ++i)
+ for (LLInventoryModel::item_array_t::const_iterator item_iter = items.begin();
+ item_iter != items.end();
+ ++item_iter)
{
- //dropInventory(root_object, items.get(i), mSource, mSourceID);
- ids.push_back(items.get(i)->getUUID());
+ const LLViewerInventoryItem *item = (*item_iter);
+ ids.push_back(item->getUUID());
}
- LLCategoryDropObserver* dropper;
- dropper = new LLCategoryDropObserver(obj->getID(), mSource);
+ LLCategoryDropObserver* dropper = new LLCategoryDropObserver(obj->getID(), mSource);
dropper->fetchItems(ids);
if(dropper->isEverythingComplete())
{
@@ -2679,7 +2622,7 @@ EAcceptance LLToolDragAndDrop::dad3dGiveInventoryObject(
// cannot give away no-transfer objects
return ACCEPT_NO;
}
- LLVOAvatar* avatar = gAgent.getAvatarObject();
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
if(avatar && avatar->isWearingAttachment( item->getUUID() ) )
{
// You can't give objects that are attached to you
@@ -2897,11 +2840,10 @@ LLInventoryObject* LLToolDragAndDrop::locateInventory(
}
else if(mSource == SOURCE_NOTECARD)
{
- LLPreviewNotecard* card;
- card = (LLPreviewNotecard*)LLPreview::find(mSourceID);
- if(card)
+ LLPreviewNotecard* preview = LLFloaterReg::findTypedInstance<LLPreviewNotecard>("preview_notecard", mSourceID);
+ if(preview)
{
- item = (LLViewerInventoryItem*)card->getDragItem();
+ item = (LLViewerInventoryItem*)preview->getDragItem();
}
}
if(item) return item;
diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h
index f9e5bec143..79b2bc32a3 100644
--- a/indra/newview/lltooldraganddrop.h
+++ b/indra/newview/lltooldraganddrop.h
@@ -33,6 +33,7 @@
#ifndef LL_TOOLDRAGANDDROP_H
#define LL_TOOLDRAGANDDROP_H
+#include "lldictionary.h"
#include "lltool.h"
#include "llview.h"
#include "lluuid.h"
@@ -51,13 +52,15 @@ class LLPickInfo;
class LLToolDragAndDrop : public LLTool, public LLSingleton<LLToolDragAndDrop>
{
public:
+ typedef boost::signals2::signal<void ()> enddrag_signal_t;
+
LLToolDragAndDrop();
// overridden from LLTool
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleKey(KEY key, MASK mask);
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect *sticky_rect_screen);
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
virtual void onMouseCaptureLost();
virtual void handleDeselect();
@@ -87,6 +90,8 @@ public:
const LLUUID& getObjectID() const { return mObjectID; }
EAcceptance getLastAccept() { return mLastAccept; }
+ boost::signals2::connection setEndDragCallback( const enddrag_signal_t::slot_type& cb ) { return mEndDragSignal.connect(cb); }
+
protected:
enum EDropTarget
{
@@ -98,6 +103,7 @@ protected:
DT_COUNT = 5
};
+protected:
// dragOrDrop3dImpl points to a member of LLToolDragAndDrop that
// takes parameters (LLViewerObject* obj, S32 face, MASK, BOOL
// drop) and returns a BOOL if drop is ok
@@ -108,7 +114,9 @@ protected:
EAcceptance* acceptance);
void dragOrDrop3D(S32 x, S32 y, MASK mask, BOOL drop,
EAcceptance* acceptance);
+
static void pickCallback(const LLPickInfo& pick_info);
+ void pick(const LLPickInfo& pick_info);
protected:
@@ -131,9 +139,7 @@ protected:
S32 mCurItemIndex;
std::string mToolTipMsg;
- // array of pointers to functions that implement the logic to
- // dragging and dropping into the simulator.
- static dragOrDrop3dImpl sDragAndDrop3d[DAD_COUNT][DT_COUNT];
+ enddrag_signal_t mEndDragSignal;
protected:
// 3d drop functions. these call down into the static functions
@@ -266,6 +272,25 @@ public:
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept);
+
+ // Classes used for determining 3d drag and drop types.
+private:
+ struct DragAndDropEntry : public LLDictionaryEntry
+ {
+ DragAndDropEntry(dragOrDrop3dImpl f_none,
+ dragOrDrop3dImpl f_self,
+ dragOrDrop3dImpl f_avatar,
+ dragOrDrop3dImpl f_object,
+ dragOrDrop3dImpl f_land);
+ dragOrDrop3dImpl mFunctions[DT_COUNT];
+ };
+ class LLDragAndDropDictionary : public LLSingleton<LLDragAndDropDictionary>,
+ public LLDictionary<EDragAndDropType, DragAndDropEntry>
+ {
+ public:
+ LLDragAndDropDictionary();
+ dragOrDrop3dImpl get(EDragAndDropType dad_type, EDropTarget drop_target);
+ };
};
// utility functions
diff --git a/indra/newview/lltoolface.cpp b/indra/newview/lltoolface.cpp
index d06e41c771..1d78dc5019 100644
--- a/indra/newview/lltoolface.cpp
+++ b/indra/newview/lltoolface.cpp
@@ -36,14 +36,12 @@
#include "lltoolface.h"
// Library includes
+#include "llfloaterreg.h"
#include "v3math.h"
// Viewer includes
-#include "llagent.h"
-//#include "llbuildview.h"
#include "llviewercontrol.h"
#include "llselectmgr.h"
-#include "lltoolview.h"
#include "llviewerobject.h"
#include "llviewerwindow.h"
#include "llfloatertools.h"
@@ -67,9 +65,7 @@ BOOL LLToolFace::handleDoubleClick(S32 x, S32 y, MASK mask)
{
// You should already have an object selected from the mousedown.
// If so, show its properties
- //gBuildView->showFacePanel();
- gFloaterTools->showPanel( LLFloaterTools::PANEL_FACE );
- //gBuildView->showMore(LLBuildView::PANEL_FACE);
+ LLFloaterReg::showInstance("build", "Texture");
return TRUE;
}
else
diff --git a/indra/newview/lltoolfocus.cpp b/indra/newview/lltoolfocus.cpp
index 4e8274a6ef..2320ae57df 100644
--- a/indra/newview/lltoolfocus.cpp
+++ b/indra/newview/lltoolfocus.cpp
@@ -45,7 +45,7 @@
#include "llbutton.h"
#include "llviewercontrol.h"
#include "lldrawable.h"
-#include "llhoverview.h"
+#include "lltooltip.h"
#include "llhudmanager.h"
#include "llfloatertools.h"
#include "llselectmgr.h"
@@ -54,8 +54,10 @@
#include "llviewercamera.h"
#include "llviewerobject.h"
#include "llviewerwindow.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "llmorphview.h"
+#include "llfloaterreg.h"
+#include "llfloatercamera.h"
// Globals
BOOL gCameraBtnZoom = TRUE;
@@ -254,7 +256,11 @@ void LLToolCamera::releaseMouse()
gViewerWindow->showCursor();
- LLToolMgr::getInstance()->clearTransientTool();
+ //for the situation when left click was performed on the Agent
+ if (!LLFloaterCamera::inFreeCameraMode())
+ {
+ LLToolMgr::getInstance()->clearTransientTool();
+ }
mMouseSteering = FALSE;
mValidClickPoint = FALSE;
@@ -281,12 +287,12 @@ BOOL LLToolCamera::handleMouseUp(S32 x, S32 y, MASK mask)
BOOL success = LLViewerCamera::getInstance()->projectPosAgentToScreen(focus_pos, mouse_pos);
if (success)
{
- LLUI::setCursorPositionScreen(mouse_pos.mX, mouse_pos.mY);
+ LLUI::setMousePositionScreen(mouse_pos.mX, mouse_pos.mY);
}
}
else if (mMouseSteering)
{
- LLUI::setCursorPositionScreen(mMouseDownX, mMouseDownY);
+ LLUI::setMousePositionScreen(mMouseDownX, mMouseDownY);
}
else
{
@@ -296,7 +302,7 @@ BOOL LLToolCamera::handleMouseUp(S32 x, S32 y, MASK mask)
else
{
// not a valid zoomable object
- LLUI::setCursorPositionScreen(mMouseDownX, mMouseDownY);
+ LLUI::setMousePositionScreen(mMouseDownX, mMouseDownY);
}
// calls releaseMouse() internally
@@ -359,7 +365,7 @@ BOOL LLToolCamera::handleHover(S32 x, S32 y, MASK mask)
// Orbit tool
if (hasMouseCapture())
{
- const F32 RADIANS_PER_PIXEL = 360.f * DEG_TO_RAD / gViewerWindow->getWindowWidth();
+ const F32 RADIANS_PER_PIXEL = 360.f * DEG_TO_RAD / gViewerWindow->getWorldViewWidthScaled();
if (dx != 0)
{
@@ -387,7 +393,7 @@ BOOL LLToolCamera::handleHover(S32 x, S32 y, MASK mask)
F32 dist = (F32) camera_to_focus.normVec();
// Fudge factor for pan
- F32 meters_per_pixel = 3.f * dist / gViewerWindow->getWindowWidth();
+ F32 meters_per_pixel = 3.f * dist / gViewerWindow->getWorldViewWidthScaled();
if (dx != 0)
{
@@ -409,7 +415,7 @@ BOOL LLToolCamera::handleHover(S32 x, S32 y, MASK mask)
if (hasMouseCapture())
{
- const F32 RADIANS_PER_PIXEL = 360.f * DEG_TO_RAD / gViewerWindow->getWindowWidth();
+ const F32 RADIANS_PER_PIXEL = 360.f * DEG_TO_RAD / gViewerWindow->getWorldViewWidthScaled();
if (dx != 0)
{
diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp
index d9811dac6c..26dbe6a489 100644
--- a/indra/newview/lltoolgrab.cpp
+++ b/indra/newview/lltoolgrab.cpp
@@ -46,7 +46,6 @@
// newview headers
#include "llagent.h"
-//#include "llfloateravatarinfo.h"
#include "lldrawable.h"
#include "llfloatertools.h"
#include "llhudeffect.h"
@@ -61,7 +60,7 @@
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "llviewerwindow.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "llworld.h"
const S32 SLOP_DIST_SQ = 4;
@@ -135,7 +134,7 @@ BOOL LLToolGrab::handleMouseDown(S32 x, S32 y, MASK mask)
if (!gAgent.leftButtonGrabbed())
{
// can grab transparent objects (how touch event propagates, scripters rely on this)
- gViewerWindow->pickAsync(x, y, mask, pickCallback, TRUE, TRUE);
+ gViewerWindow->pickAsync(x, y, mask, pickCallback, TRUE);
}
return TRUE;
}
@@ -511,8 +510,8 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
const F32 RADIANS_PER_PIXEL_X = 0.01f;
const F32 RADIANS_PER_PIXEL_Y = 0.01f;
- S32 dx = x - (gViewerWindow->getWindowWidth() / 2);
- S32 dy = y - (gViewerWindow->getWindowHeight() / 2);
+ S32 dx = x - (gViewerWindow->getWorldViewWidthScaled() / 2);
+ S32 dy = y - (gViewerWindow->getWorldViewHeightScaled() / 2);
if (dx != 0 || dy != 0)
{
@@ -632,10 +631,10 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
// Handle auto-rotation at screen edge.
LLVector3 grab_pos_agent = gAgent.getPosAgentFromGlobal( grab_point_global );
- LLCoordGL grab_center_gl( gViewerWindow->getWindowWidth() / 2, gViewerWindow->getWindowHeight() / 2);
+ LLCoordGL grab_center_gl( gViewerWindow->getWorldViewWidthScaled() / 2, gViewerWindow->getWorldViewHeightScaled() / 2);
LLViewerCamera::getInstance()->projectPosAgentToScreen(grab_pos_agent, grab_center_gl);
- const S32 ROTATE_H_MARGIN = gViewerWindow->getWindowWidth() / 20;
+ const S32 ROTATE_H_MARGIN = gViewerWindow->getWorldViewWidthScaled() / 20;
const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD;
const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped;
// ...build mode moves camera about focus point
@@ -650,7 +649,7 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
gAgent.cameraOrbitAround(rotate_angle);
}
}
- else if (grab_center_gl.mX > gViewerWindow->getWindowWidth() - ROTATE_H_MARGIN)
+ else if (grab_center_gl.mX > gViewerWindow->getWorldViewWidthScaled() - ROTATE_H_MARGIN)
{
if (gAgent.getFocusOnAvatar())
{
@@ -663,7 +662,7 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
}
// Don't move above top of screen or below bottom
- if ((grab_center_gl.mY < gViewerWindow->getWindowHeight() - 6)
+ if ((grab_center_gl.mY < gViewerWindow->getWorldViewHeightScaled() - 6)
&& (grab_center_gl.mY > 24))
{
// Transmit update to simulator
@@ -885,7 +884,7 @@ void LLToolGrab::handleHoverInactive(S32 x, S32 y, MASK mask)
// Look for cursor against the edge of the screen
// Only works in fullscreen
- if (gSavedSettings.getBOOL("FullScreen"))
+ if (gSavedSettings.getBOOL("WindowFullScreen"))
{
if (gAgent.cameraThirdPerson() )
{
@@ -894,7 +893,7 @@ void LLToolGrab::handleHoverInactive(S32 x, S32 y, MASK mask)
gAgent.yaw(rotate_angle);
//gAgent.setControlFlags(AGENT_CONTROL_YAW_POS);
}
- else if (x == (gViewerWindow->getWindowWidth() - 1) )
+ else if (x == (gViewerWindow->getWorldViewWidthScaled() - 1) )
{
gAgent.yaw(-rotate_angle);
//gAgent.setControlFlags(AGENT_CONTROL_YAW_NEG);
@@ -997,7 +996,7 @@ void LLToolGrab::onMouseCaptureLost()
// ...move cursor "naturally", as if it had moved when hidden
S32 x = mGrabPick.mMousePt.mX + mAccumDeltaX;
S32 y = mGrabPick.mMousePt.mY + mAccumDeltaY;
- LLUI::setCursorPositionScreen(x, y);
+ LLUI::setMousePositionScreen(x, y);
}
else if (mHasMoved)
{
@@ -1007,13 +1006,13 @@ void LLToolGrab::onMouseCaptureLost()
LLCoordGL gl_point;
if (LLViewerCamera::getInstance()->projectPosAgentToScreen(grab_point_agent, gl_point))
{
- LLUI::setCursorPositionScreen(gl_point.mX, gl_point.mY);
+ LLUI::setMousePositionScreen(gl_point.mX, gl_point.mY);
}
}
else
{
// ...move cursor back to click position
- LLUI::setCursorPositionScreen(mGrabPick.mMousePt.mX, mGrabPick.mMousePt.mY);
+ LLUI::setMousePositionScreen(mGrabPick.mMousePt.mX, mGrabPick.mMousePt.mY);
}
gViewerWindow->showCursor();
diff --git a/indra/newview/lltoolgrab.h b/indra/newview/lltoolgrab.h
index cf2405cafc..16ccb3f24f 100644
--- a/indra/newview/lltoolgrab.h
+++ b/indra/newview/lltoolgrab.h
@@ -36,7 +36,7 @@
#include "lltool.h"
#include "v3math.h"
#include "llquaternion.h"
-#include "llmemory.h"
+#include "llsingleton.h"
#include "lluuid.h"
#include "llviewerwindow.h" // for LLPickInfo
diff --git a/indra/newview/lltoolgun.cpp b/indra/newview/lltoolgun.cpp
index d21fd49647..a441d653c7 100644
--- a/indra/newview/lltoolgun.cpp
+++ b/indra/newview/lltoolgun.cpp
@@ -42,14 +42,18 @@
#include "llresmgr.h"
#include "llfontgl.h"
#include "llui.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewercamera.h"
#include "llhudmanager.h"
#include "lltoolmgr.h"
#include "lltoolgrab.h"
+// Linden library includes
+#include "llwindow.h" // setMouseClipping()
+
LLToolGun::LLToolGun( LLToolComposite* composite )
-: LLTool( std::string("gun"), composite )
+: LLTool( std::string("gun"), composite ),
+ mIsSelected(FALSE)
{
}
@@ -58,6 +62,7 @@ void LLToolGun::handleSelect()
gViewerWindow->hideCursor();
gViewerWindow->moveCursorToCenter();
gViewerWindow->mWindow->setMouseClipping(TRUE);
+ mIsSelected = TRUE;
}
void LLToolGun::handleDeselect()
@@ -65,6 +70,7 @@ void LLToolGun::handleDeselect()
gViewerWindow->moveCursorToCenter();
gViewerWindow->showCursor();
gViewerWindow->mWindow->setMouseClipping(FALSE);
+ mIsSelected = FALSE;
}
BOOL LLToolGun::handleMouseDown(S32 x, S32 y, MASK mask)
@@ -77,7 +83,7 @@ BOOL LLToolGun::handleMouseDown(S32 x, S32 y, MASK mask)
BOOL LLToolGun::handleHover(S32 x, S32 y, MASK mask)
{
- if( gAgent.cameraMouselook() )
+ if( gAgent.cameraMouselook() && mIsSelected )
{
const F32 NOMINAL_MOUSE_SENSITIVITY = 0.0025f;
@@ -132,9 +138,9 @@ void LLToolGun::draw()
{
if( gSavedSettings.getBOOL("ShowCrosshairs") )
{
- LLUIImagePtr crosshair = LLUI::getUIImage("UIImgCrosshairsUUID");
+ LLUIImagePtr crosshair = LLUI::getUIImage("crosshairs.tga");
crosshair->draw(
- ( gViewerWindow->getWindowWidth() - crosshair->getWidth() ) / 2,
- ( gViewerWindow->getWindowHeight() - crosshair->getHeight() ) / 2);
+ ( gViewerWindow->getWorldViewRectScaled().getWidth() - crosshair->getWidth() ) / 2,
+ ( gViewerWindow->getWorldViewRectScaled().getHeight() - crosshair->getHeight() ) / 2);
}
}
diff --git a/indra/newview/lltoolgun.h b/indra/newview/lltoolgun.h
index 4e945d796c..4644e686b7 100644
--- a/indra/newview/lltoolgun.h
+++ b/indra/newview/lltoolgun.h
@@ -52,6 +52,8 @@ public:
virtual LLTool* getOverrideTool(MASK mask) { return NULL; }
virtual BOOL clipMouseWhenDown() { return FALSE; }
+private:
+ BOOL mIsSelected;
};
#endif
diff --git a/indra/newview/lltoolindividual.cpp b/indra/newview/lltoolindividual.cpp
index 8382e0d72d..163c7cbd9b 100644
--- a/indra/newview/lltoolindividual.cpp
+++ b/indra/newview/lltoolindividual.cpp
@@ -41,6 +41,7 @@
#include "llviewerprecompiledheaders.h"
#include "lltoolindividual.h"
+#include "llfloaterreg.h"
#include "llselectmgr.h"
#include "llviewerobject.h"
#include "llviewerwindow.h"
@@ -93,9 +94,7 @@ BOOL LLToolIndividual::handleDoubleClick(S32 x, S32 y, MASK mask)
{
// You should already have an object selected from the mousedown.
// If so, show its inventory.
- //gBuildView->showInventoryPanel();
- //gBuildView->showPanel(LLBuildView::PANEL_CONTENTS);
- gFloaterTools->showPanel(LLFloaterTools::PANEL_CONTENTS);
+ LLFloaterReg::showInstance("build", "Content");
return TRUE;
}
else
diff --git a/indra/newview/lltoolmgr.cpp b/indra/newview/lltoolmgr.cpp
index 5ba7217c99..fd12163fd3 100644
--- a/indra/newview/lltoolmgr.cpp
+++ b/indra/newview/lltoolmgr.cpp
@@ -34,8 +34,13 @@
#include "lltoolmgr.h"
-#include "lltool.h"
+#include "lluictrl.h"
+#include "llmenugl.h"
+#include "llfloaterreg.h"
+
+//#include "llfirstuse.h"
// tools and manipulators
+#include "lltool.h"
#include "llmanipscale.h"
#include "llselectmgr.h"
#include "lltoolbrush.h"
@@ -47,12 +52,14 @@
#include "lltoolindividual.h"
#include "lltoolmorph.h"
#include "lltoolpie.h"
-#include "lltoolplacer.h"
#include "lltoolselectland.h"
#include "lltoolobjpicker.h"
#include "lltoolpipette.h"
#include "llagent.h"
#include "llviewercontrol.h"
+#include "llviewerjoystick.h"
+#include "llviewermenu.h"
+#include "llviewerparcelmgr.h"
// Used when app not active to avoid processing hover.
@@ -76,6 +83,11 @@ LLToolMgr::LLToolMgr()
mSelectedTool( NULL ),
mCurrentToolset( NULL )
{
+ // Not a panel, register these callbacks globally.
+ LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Active", boost::bind(&LLToolMgr::inEdit, this));
+ LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Enabled", boost::bind(&LLToolMgr::canEdit, this));
+ LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Build.Toggle", boost::bind(&LLToolMgr::toggleBuildMode, this));
+
gToolNull = new LLTool(LLStringUtil::null); // Does nothing
setCurrentTool(gToolNull);
@@ -168,11 +180,13 @@ void LLToolMgr::setCurrentTool( LLTool* tool )
mBaseTool = tool;
updateToolStatus();
+
+ mSavedTool = NULL;
}
LLTool* LLToolMgr::getCurrentTool()
{
- MASK override_mask = gKeyboard->currentMask(TRUE);
+ MASK override_mask = gKeyboard ? gKeyboard->currentMask(TRUE) : 0;
LLTool* cur_tool = NULL;
// always use transient tools if available
@@ -226,18 +240,83 @@ void LLToolMgr::updateToolStatus()
getCurrentTool();
}
-BOOL LLToolMgr::inEdit()
+bool LLToolMgr::inEdit()
{
return mBaseTool != LLToolPie::getInstance() && mBaseTool != gToolNull;
}
+bool LLToolMgr::canEdit()
+{
+ return LLViewerParcelMgr::getInstance()->allowAgentBuild();
+}
+
+void LLToolMgr::toggleBuildMode()
+{
+ if (inBuildMode())
+ {
+ if (gSavedSettings.getBOOL("EditCameraMovement"))
+ {
+ // just reset the view, will pull us out of edit mode
+ handle_reset_view();
+ }
+ else
+ {
+ // manually disable edit mode, but do not affect the camera
+ gAgent.resetView(false);
+ LLFloaterReg::hideInstance("build");
+ gViewerWindow->showCursor();
+ }
+ // avoid spurious avatar movements pulling out of edit mode
+ LLViewerJoystick::getInstance()->setNeedsReset();
+ }
+ else
+ {
+ ECameraMode camMode = gAgent.getCameraMode();
+ if (CAMERA_MODE_MOUSELOOK == camMode || CAMERA_MODE_CUSTOMIZE_AVATAR == camMode)
+ {
+ // pull the user out of mouselook or appearance mode when entering build mode
+ handle_reset_view();
+ }
+
+ if (gSavedSettings.getBOOL("EditCameraMovement"))
+ {
+ // camera should be set
+ if (LLViewerJoystick::getInstance()->getOverrideCamera())
+ {
+ handle_toggle_flycam();
+ }
+
+ if (gAgent.getFocusOnAvatar())
+ {
+ // zoom in if we're looking at the avatar
+ gAgent.setFocusOnAvatar(FALSE, ANIMATE);
+ gAgent.setFocusGlobal(gAgent.getPositionGlobal() + 2.0 * LLVector3d(gAgent.getAtAxis()));
+ gAgent.cameraZoomIn(0.666f);
+ gAgent.cameraOrbitOver( 30.f * DEG_TO_RAD );
+ }
+ }
+
+
+ setCurrentToolset(gBasicToolset);
+ getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() );
+
+ // Could be first use
+ //LLFirstUse::useBuild();
+
+ gAgent.resetView(false);
+
+ // avoid spurious avatar movements
+ LLViewerJoystick::getInstance()->setNeedsReset();
+
+ }
+}
+
bool LLToolMgr::inBuildMode()
{
// when entering mouselook inEdit() immediately returns true before
// cameraMouselook() actually starts returning true. Also, appearance edit
// sets build mode to true, so let's exclude that.
bool b=(inEdit()
- && gSavedSettings.getBOOL("BuildBtnState")
&& !gAgent.cameraMouselook()
&& mCurrentToolset != gFaceEditToolset);
@@ -277,22 +356,20 @@ void LLToolMgr::clearTransientTool()
}
-// The "gun tool", used for handling mouselook, captures the mouse and
-// locks it within the window. When the app loses focus we need to
-// release this locking.
void LLToolMgr::onAppFocusLost()
{
- mSavedTool = mBaseTool;
- mBaseTool = gToolNull;
+ if (mSelectedTool)
+ {
+ mSelectedTool->handleDeselect();
+ }
updateToolStatus();
}
void LLToolMgr::onAppFocusGained()
{
- if (mSavedTool)
+ if (mSelectedTool)
{
- mBaseTool = mSavedTool;
- mSavedTool = NULL;
+ mSelectedTool->handleSelect();
}
updateToolStatus();
}
@@ -396,8 +473,6 @@ void LLToolset::selectPrevTool()
}
}
-void select_tool( void *tool_pointer )
-{
- LLTool *tool = (LLTool *)tool_pointer;
- LLToolMgr::getInstance()->getCurrentToolset()->selectTool( tool );
-}
+////////////////////////////////////////////////////////////////////////////
+
+
diff --git a/indra/newview/lltoolmgr.h b/indra/newview/lltoolmgr.h
index 92647c99de..22aec97864 100644
--- a/indra/newview/lltoolmgr.h
+++ b/indra/newview/lltoolmgr.h
@@ -58,7 +58,9 @@ public:
LLTool* getCurrentTool(); // returns active tool, taking into account keyboard state
LLTool* getBaseTool(); // returns active tool when overrides are deactivated
- BOOL inEdit();
+ bool inEdit();
+ bool canEdit();
+ void toggleBuildMode();
/* Determines if we are in Build mode or not. */
bool inBuildMode();
@@ -115,10 +117,6 @@ protected:
tool_list_t mToolList;
};
-// Handy callbacks for switching tools
-void select_tool(void *tool);
-
-
// Globals
extern LLToolset* gBasicToolset;
diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp
index 75e19645a6..4fb75f7a49 100644
--- a/indra/newview/lltoolmorph.cpp
+++ b/indra/newview/lltoolmorph.cpp
@@ -37,7 +37,7 @@
#include "llrender.h"
// Library includes
-#include "audioengine.h"
+#include "llaudioengine.h"
#include "llviewercontrol.h"
#include "llfontgl.h"
#include "sound_ids.h"
@@ -56,13 +56,12 @@
#include "llsky.h"
#include "lltexlayer.h"
#include "lltoolmgr.h"
-#include "lltoolview.h"
#include "llui.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewerobject.h"
#include "llviewerwindow.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "pipeline.h"
@@ -82,7 +81,7 @@ LLVisualParamHint::LLVisualParamHint(
LLViewerVisualParam *param,
F32 param_weight)
:
- LLDynamicTexture(width, height, 3, LLDynamicTexture::ORDER_MIDDLE, TRUE ),
+ LLViewerDynamicTexture(width, height, 3, LLViewerDynamicTexture::ORDER_MIDDLE, TRUE ),
mNeedsUpdate( TRUE ),
mIsVisible( FALSE ),
mJointMesh( mesh ),
@@ -145,10 +144,11 @@ BOOL LLVisualParamHint::needsRender()
void LLVisualParamHint::preRender(BOOL clear_depth)
{
- LLVOAvatar* avatarp = gAgent.getAvatarObject();
+ LLVOAvatarSelf* avatarp = gAgent.getAvatarObject();
- mLastParamWeight = avatarp->getVisualParamWeight(mVisualParam);
- avatarp->setVisualParamWeight(mVisualParam, mVisualParamWeight);
+ mLastParamWeight = mVisualParam->getWeight();
+ mVisualParam->setWeight(mVisualParamWeight, FALSE);
+ avatarp->setVisualParamWeight(mVisualParam->getID(), mVisualParamWeight, FALSE);
avatarp->setVisualParamWeight("Blink_Left", 0.f);
avatarp->setVisualParamWeight("Blink_Right", 0.f);
avatarp->updateComposites();
@@ -156,7 +156,7 @@ void LLVisualParamHint::preRender(BOOL clear_depth)
avatarp->updateGeometry(avatarp->mDrawable);
avatarp->updateLOD();
- LLDynamicTexture::preRender(clear_depth);
+ LLViewerDynamicTexture::preRender(clear_depth);
}
//-----------------------------------------------------------------------------
@@ -170,7 +170,7 @@ BOOL LLVisualParamHint::render()
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
- glOrtho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f);
+ glOrtho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
@@ -178,7 +178,7 @@ BOOL LLVisualParamHint::render()
LLGLSUIDefault gls_ui;
//LLGLState::verify(TRUE);
- mBackgroundp->draw(0, 0, mWidth, mHeight);
+ mBackgroundp->draw(0, 0, mFullWidth, mFullHeight);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
@@ -225,13 +225,13 @@ BOOL LLVisualParamHint::render()
gGL.flush();
- LLViewerCamera::getInstance()->setAspect((F32)mWidth / (F32)mHeight);
+ LLViewerCamera::getInstance()->setAspect((F32)mFullWidth / (F32)mFullHeight);
LLViewerCamera::getInstance()->setOriginAndLookAt(
camera_pos, // camera
LLVector3(0.f, 0.f, 1.f), // up
target_pos ); // point of interest
- LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mWidth, mHeight, FALSE);
+ LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE);
if (avatarp->mDrawable.notNull())
{
@@ -243,9 +243,10 @@ BOOL LLVisualParamHint::render()
gGL.setSceneBlendType(LLRender::BT_ALPHA);
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
}
- avatarp->setVisualParamWeight(mVisualParam, mLastParamWeight);
+ avatarp->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight);
+ mVisualParam->setWeight(mLastParamWeight, FALSE);
gGL.color4f(1,1,1,1);
- mTexture->setGLTextureCreated(true);
+ mGLTexturep->setGLTextureCreated(true);
return TRUE;
}
@@ -257,7 +258,7 @@ void LLVisualParamHint::draw()
{
if (!mIsVisible) return;
- gGL.getTexUnit(0)->bind(getTexture());
+ gGL.getTexUnit(0)->bind(this);
gGL.color4f(1.f, 1.f, 1.f, 1.f);
@@ -265,13 +266,13 @@ void LLVisualParamHint::draw()
gGL.begin(LLRender::QUADS);
{
gGL.texCoord2i(0, 1);
- gGL.vertex2i(0, mHeight);
+ gGL.vertex2i(0, mFullHeight);
gGL.texCoord2i(0, 0);
gGL.vertex2i(0, 0);
gGL.texCoord2i(1, 0);
- gGL.vertex2i(mWidth, 0);
+ gGL.vertex2i(mFullWidth, 0);
gGL.texCoord2i(1, 1);
- gGL.vertex2i(mWidth, mHeight);
+ gGL.vertex2i(mFullWidth, mFullHeight);
}
gGL.end();
@@ -281,7 +282,7 @@ void LLVisualParamHint::draw()
//-----------------------------------------------------------------------------
// LLVisualParamReset()
//-----------------------------------------------------------------------------
-LLVisualParamReset::LLVisualParamReset() : LLDynamicTexture(1, 1, 1, ORDER_RESET, FALSE)
+LLVisualParamReset::LLVisualParamReset() : LLViewerDynamicTexture(1, 1, 1, ORDER_RESET, FALSE)
{
}
@@ -292,7 +293,7 @@ BOOL LLVisualParamReset::render()
{
if (sDirty)
{
- LLVOAvatar* avatarp = gAgent.getAvatarObject();
+ LLVOAvatarSelf* avatarp = gAgent.getAvatarObject();
avatarp->updateComposites();
avatarp->updateVisualParams();
avatarp->updateGeometry(avatarp->mDrawable);
diff --git a/indra/newview/lltoolmorph.h b/indra/newview/lltoolmorph.h
index 11de8160eb..b7df718ba2 100644
--- a/indra/newview/lltoolmorph.h
+++ b/indra/newview/lltoolmorph.h
@@ -42,7 +42,7 @@
#include "llstrider.h"
#include "llviewervisualparam.h"
#include "llframetimer.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
class LLViewerJointMesh;
class LLPolyMesh;
@@ -51,17 +51,18 @@ class LLViewerObject;
//-----------------------------------------------------------------------------
// LLVisualParamHint
//-----------------------------------------------------------------------------
-class LLVisualParamHint
-: public LLDynamicTexture
+class LLVisualParamHint : public LLViewerDynamicTexture
{
+protected:
+ virtual ~LLVisualParamHint();
+
public:
LLVisualParamHint(
S32 pos_x, S32 pos_y,
S32 width, S32 height,
LLViewerJointMesh *mesh,
LLViewerVisualParam *param,
- F32 param_weight);
- virtual ~LLVisualParamHint();
+ F32 param_weight);
BOOL needsRender();
void preRender(BOOL clear_depth);
@@ -94,13 +95,15 @@ protected:
LLUIImagePtr mBackgroundp;
- typedef std::set<LLVisualParamHint*> instance_list_t;
+ typedef std::set< LLVisualParamHint* > instance_list_t;
static instance_list_t sInstances;
};
// this class resets avatar data at the end of an update cycle
-class LLVisualParamReset : public LLDynamicTexture
+class LLVisualParamReset : public LLViewerDynamicTexture
{
+protected:
+ /*virtual */ ~LLVisualParamReset(){}
public:
LLVisualParamReset();
/*virtual */ BOOL render();
diff --git a/indra/newview/lltoolobjpicker.cpp b/indra/newview/lltoolobjpicker.cpp
index d69688706f..b2088a8232 100644
--- a/indra/newview/lltoolobjpicker.cpp
+++ b/indra/newview/lltoolobjpicker.cpp
@@ -48,6 +48,7 @@
#include "llviewercamera.h"
#include "llviewerwindow.h"
#include "lldrawable.h"
+#include "llrootview.h"
LLToolObjPicker::LLToolObjPicker()
@@ -62,7 +63,7 @@ LLToolObjPicker::LLToolObjPicker()
// returns TRUE if an object was selected
BOOL LLToolObjPicker::handleMouseDown(S32 x, S32 y, MASK mask)
{
- LLView* viewp = gViewerWindow->getRootView();
+ LLRootView* viewp = gViewerWindow->getRootView();
BOOL handled = viewp->handleMouseDown(x, y, mask);
mHitObjectID.setNull();
@@ -131,7 +132,7 @@ BOOL LLToolObjPicker::handleHover(S32 x, S32 y, MASK mask)
cursor = UI_CURSOR_TOOLPICKOBJECT3;
- gViewerWindow->getWindow()->setCursor(cursor);
+ gViewerWindow->setCursor(cursor);
}
return handled;
}
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 986555db49..c79a66892d 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -36,18 +36,20 @@
#include "indra_constants.h"
#include "llclickaction.h"
-#include "llmediabase.h" // for status codes
#include "llparcel.h"
#include "llagent.h"
#include "llviewercontrol.h"
-#include "llfirstuse.h"
-#include "llfloateravatarinfo.h"
+#include "llfocusmgr.h"
+//#include "llfirstuse.h"
#include "llfloaterland.h"
+#include "llfloaterreg.h"
#include "llfloaterscriptdebug.h"
-#include "llhoverview.h"
+#include "lltooltip.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
+#include "llkeyboard.h"
+#include "llmediaentry.h"
#include "llmenugl.h"
#include "llmutelist.h"
#include "llselectmgr.h"
@@ -55,6 +57,7 @@
#include "lltoolgrab.h"
#include "lltoolmgr.h"
#include "lltoolselect.h"
+#include "lltrans.h"
#include "llviewercamera.h"
#include "llviewerparcelmedia.h"
#include "llviewermenu.h"
@@ -63,12 +66,12 @@
#include "llviewerparcelmgr.h"
#include "llviewerwindow.h"
#include "llviewermedia.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
+#include "llviewermediafocus.h"
#include "llworld.h"
#include "llui.h"
#include "llweb.h"
-
-extern void handle_buy(void*);
+#include "pipeline.h" // setHighlightObject
extern BOOL gDebugClicks;
@@ -78,52 +81,68 @@ static ECursorType cursor_from_parcel_media(U8 click_action);
LLToolPie::LLToolPie()
-: LLTool(std::string("Select")),
- mPieMouseButtonDown( FALSE ),
+: LLTool(std::string("Pie")),
mGrabMouseButtonDown( FALSE ),
mMouseOutsideSlop( FALSE ),
mClickAction(0)
{ }
+BOOL LLToolPie::handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down)
+{
+ BOOL result = LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down);
+
+ // This override DISABLES the keyboard focus reset that LLTool::handleAnyMouseClick adds.
+ // LLToolPie will do the right thing in its pick callback.
+
+ return result;
+}
+
BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask)
{
//left mouse down always picks transparent
- gViewerWindow->pickAsync(x, y, mask, leftMouseCallback, TRUE, TRUE);
+ mPick = gViewerWindow->pickImmediate(x, y, TRUE);
+ mPick.mKeyMask = mask;
mGrabMouseButtonDown = TRUE;
- return TRUE;
-}
+
+ pickLeftMouseDownCallback();
-// static
-void LLToolPie::leftMouseCallback(const LLPickInfo& pick_info)
-{
- LLToolPie::getInstance()->mPick = pick_info;
- LLToolPie::getInstance()->pickAndShowMenu(FALSE);
+ return TRUE;
}
+// Spawn context menus on right mouse down so you can drag over and select
+// an item.
BOOL LLToolPie::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
// don't pick transparent so users can't "pay" transparent objects
- gViewerWindow->pickAsync(x, y, mask, rightMouseCallback, FALSE, TRUE);
- mPieMouseButtonDown = TRUE;
- // don't steal focus from UI
+ mPick = gViewerWindow->pickImmediate(x, y, FALSE);
+ mPick.mKeyMask = mask;
+
+ // claim not handled so UI focus stays same
+
+ pickRightMouseDownCallback();
+
return FALSE;
}
-// static
-void LLToolPie::rightMouseCallback(const LLPickInfo& pick_info)
+BOOL LLToolPie::handleRightMouseUp(S32 x, S32 y, MASK mask)
{
- LLToolPie::getInstance()->mPick = pick_info;
- LLToolPie::getInstance()->pickAndShowMenu(TRUE);
+ LLToolMgr::getInstance()->clearTransientTool();
+ return LLTool::handleRightMouseUp(x, y, mask);
+}
+
+BOOL LLToolPie::handleScrollWheel(S32 x, S32 y, S32 clicks)
+{
+ return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks);
}
// True if you selected an object.
-BOOL LLToolPie::pickAndShowMenu(BOOL always_show)
+BOOL LLToolPie::pickLeftMouseDownCallback()
{
S32 x = mPick.mMousePt.mX;
S32 y = mPick.mMousePt.mY;
MASK mask = mPick.mKeyMask;
- if (!always_show && mPick.mPickType == LLPickInfo::PICK_PARCEL_WALL)
+ if (mPick.mPickType == LLPickInfo::PICK_PARCEL_WALL)
{
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getCollisionParcel();
if (parcel)
@@ -139,10 +158,11 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show)
else
{
// not selling passes, get info
- LLFloaterLand::showInstance();
+ LLFloaterReg::showInstance("about_land");
}
}
+ gFocusMgr.setKeyboardFocus(NULL);
return LLTool::handleMouseDown(x, y, mask);
}
@@ -160,11 +180,13 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show)
parent = object->getRootEdit();
}
+
BOOL touchable = (object && object->flagHandleTouch())
|| (parent && parent->flagHandleTouch());
+
// If it's a left-click, and we have a special action, do it.
- if (useClickAction(always_show, mask, object, parent))
+ if (useClickAction(mask, object, parent))
{
mClickAction = 0;
if (object && object->getClickAction())
@@ -182,15 +204,18 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show)
// touch behavior down below...
break;
case CLICK_ACTION_SIT:
- if ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->mIsSitting)) // agent not already sitting
+
+ if ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->isSitting())) // agent not already sitting
{
- handle_sit_or_stand();
+ handle_object_sit_or_stand();
+ // put focus in world when sitting on an object
+ gFocusMgr.setKeyboardFocus(NULL);
return TRUE;
} // else nothing (fall through to touch)
case CLICK_ACTION_PAY:
- if (object && object->flagTakesMoney()
- || parent && parent->flagTakesMoney())
+ if ((object && object->flagTakesMoney())
+ || (parent && parent->flagTakesMoney()))
{
// pay event goes to object actually clicked on
mClickActionObject = object;
@@ -223,7 +248,7 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show)
selectionPropertiesReceived();
}
}
- return TRUE;
+ return TRUE;
case CLICK_ACTION_PLAY:
handle_click_action_play();
return TRUE;
@@ -231,17 +256,48 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show)
// mClickActionObject = object;
handle_click_action_open_media(object);
return TRUE;
+ case CLICK_ACTION_ZOOM:
+ {
+ const F32 PADDING_FACTOR = 2.f;
+ LLViewerObject* object = gObjectList.findObject(mPick.mObjectID);
+
+ if (object)
+ {
+ gAgent.setFocusOnAvatar(FALSE, ANIMATE);
+
+ LLBBox bbox = object->getBoundingBoxAgent() ;
+ F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView());
+ F32 distance = bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view);
+
+ LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - bbox.getCenterAgent();
+ obj_to_cam.normVec();
+
+ LLVector3d object_center_global = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent());
+ gAgent.setCameraPosAndFocusGlobal(object_center_global + LLVector3d(obj_to_cam * distance),
+ object_center_global,
+ mPick.mObjectID );
+ }
+ }
+ return TRUE;
default:
// nothing
break;
}
}
+ if (handleMediaClick(mPick))
+ {
+ return TRUE;
+ }
+
+ // put focus back "in world"
+ gFocusMgr.setKeyboardFocus(NULL);
+
// Switch to grab tool if physical or triggerable
if (object &&
!object->isAvatar() &&
- ((object->usePhysics() || (parent && !parent->isAvatar() && parent->usePhysics())) || touchable) &&
- !always_show)
+ ((object->usePhysics() || (parent && !parent->isAvatar() && parent->usePhysics())) || touchable)
+ )
{
gGrabTransientTool = this;
LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolGrab::getInstance() );
@@ -256,8 +312,7 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show)
// If left-click never selects or spawns a menu
// Eat the event.
- if (!gSavedSettings.getBOOL("LeftClickShowMenu")
- && !always_show)
+ if (!gSavedSettings.getBOOL("LeftClickShowMenu"))
{
// mouse already released
if (!mGrabMouseButtonDown)
@@ -285,14 +340,16 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show)
return TRUE;
}
- // Could be first left-click on nothing
- LLFirstUse::useLeftClickNoHit();
-
+ //////////
+ // // Could be first left-click on nothing
+ // LLFirstUse::useLeftClickNoHit();
+ /////////
+
// Eat the event
return LLTool::handleMouseDown(x, y, mask);
}
- if (!always_show && gAgent.leftButtonGrabbed())
+ if (gAgent.leftButtonGrabbed())
{
// if the left button is grabbed, don't put up the pie menu
return LLTool::handleMouseDown(x, y, mask);
@@ -302,116 +359,15 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show)
LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE);
// Spawn pie menu
- if (mPick.mPickType == LLPickInfo::PICK_LAND)
- {
- LLParcelSelectionHandle selection = LLViewerParcelMgr::getInstance()->selectParcelAt( mPick.mPosGlobal );
- gMenuHolder->setParcelSelection(selection);
- gPieLand->show(x, y, mPieMouseButtonDown);
-
- // VEFFECT: ShowPie
- LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE);
- effectp->setPositionGlobal(mPick.mPosGlobal);
- effectp->setColor(LLColor4U(gAgent.getEffectColor()));
- effectp->setDuration(0.25f);
- }
- else if (mPick.mObjectID == gAgent.getID() )
- {
- if(!gPieSelf)
- {
- //either at very early startup stage or at late quitting stage,
- //this event is ignored.
- return TRUE ;
- }
-
- gPieSelf->show(x, y, mPieMouseButtonDown);
- }
- else if (object)
- {
- gMenuHolder->setObjectSelection(LLSelectMgr::getInstance()->getSelection());
-
- if (object->isAvatar()
- || (object->isAttachment() && !object->isHUDAttachment() && !object->permYouOwner()))
- {
- // Find the attachment's avatar
- while( object && object->isAttachment())
- {
- object = (LLViewerObject*)object->getParent();
- }
-
- // Object is an avatar, so check for mute by id.
- LLVOAvatar* avatar = (LLVOAvatar*)object;
- std::string name = avatar->getFullname();
- if (LLMuteList::getInstance()->isMuted(avatar->getID(), name))
- {
- gMenuHolder->childSetText("Avatar Mute", std::string("Unmute")); // *TODO:Translate
- //gMutePieMenu->setLabel("Unmute");
- }
- else
- {
- gMenuHolder->childSetText("Avatar Mute", std::string("Mute")); // *TODO:Translate
- //gMutePieMenu->setLabel("Mute");
- }
-
- gPieAvatar->show(x, y, mPieMouseButtonDown);
- }
- else if (object->isAttachment())
- {
- gPieAttachment->show(x, y, mPieMouseButtonDown);
- }
- else
- {
- // BUG: What about chatting child objects?
- std::string name;
- LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
- if (node)
- {
- name = node->mName;
- }
- if (LLMuteList::getInstance()->isMuted(object->getID(), name))
- {
- gMenuHolder->childSetText("Object Mute", std::string("Unmute")); // *TODO:Translate
- //gMuteObjectPieMenu->setLabel("Unmute");
- }
- else
- {
- gMenuHolder->childSetText("Object Mute", std::string("Mute")); // *TODO:Translate
- //gMuteObjectPieMenu->setLabel("Mute");
- }
-
- gPieObject->show(x, y, mPieMouseButtonDown);
-
- // VEFFECT: ShowPie object
- // Don't show when you click on someone else, it freaks them
- // out.
- LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE);
- effectp->setPositionGlobal(mPick.mPosGlobal);
- effectp->setColor(LLColor4U(gAgent.getEffectColor()));
- effectp->setDuration(0.25f);
- }
- }
-
- if (always_show)
- {
- // ignore return value
- LLTool::handleRightMouseDown(x, y, mask);
- }
- else
- {
- // ignore return value
- LLTool::handleMouseDown(x, y, mask);
- }
-
- // We handled the event.
+ LLTool::handleRightMouseDown(x, y, mask);
return TRUE;
}
-BOOL LLToolPie::useClickAction(BOOL always_show,
- MASK mask,
+BOOL LLToolPie::useClickAction(MASK mask,
LLViewerObject* object,
LLViewerObject* parent)
{
- return !always_show
- && mask == MASK_NONE
+ return mask == MASK_NONE
&& object
&& !object->isAttachment()
&& LLPrimitive::isPrimitive(object->getPCode())
@@ -454,28 +410,31 @@ ECursorType cursor_from_object(LLViewerObject* object)
switch(click_action)
{
case CLICK_ACTION_SIT:
- if ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->mIsSitting)) // not already sitting?
+ if ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->isSitting())) // not already sitting?
{
- cursor = UI_CURSOR_TOOLSIT;
+ cursor = UI_CURSOR_HAND;
}
break;
case CLICK_ACTION_BUY:
- cursor = UI_CURSOR_TOOLBUY;
+ cursor = UI_CURSOR_HAND;
break;
case CLICK_ACTION_OPEN:
// Open always opens the parent.
if (parent && parent->allowOpen())
{
- cursor = UI_CURSOR_TOOLOPEN;
+ cursor = UI_CURSOR_HAND;
}
break;
case CLICK_ACTION_PAY:
if ((object && object->flagTakesMoney())
|| (parent && parent->flagTakesMoney()))
{
- cursor = UI_CURSOR_TOOLPAY;
+ cursor = UI_CURSOR_HAND;
}
break;
+ case CLICK_ACTION_ZOOM:
+ cursor = UI_CURSOR_TOOLZOOMIN;
+ break;
case CLICK_ACTION_PLAY:
case CLICK_ACTION_OPEN_MEDIA:
cursor = cursor_from_parcel_media(click_action);
@@ -518,13 +477,13 @@ void LLToolPie::selectionPropertiesReceived()
switch (click_action)
{
case CLICK_ACTION_BUY:
- handle_buy(NULL);
+ handle_buy();
break;
case CLICK_ACTION_PAY:
handle_give_money_dialog();
break;
case CLICK_ACTION_OPEN:
- handle_object_open();
+ LLFloaterReg::showInstance("openobject");
break;
default:
break;
@@ -536,67 +495,76 @@ void LLToolPie::selectionPropertiesReceived()
BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
{
- /*
- // If auto-rotate occurs, tag mouse-outside-slop to make sure the drag
- // gets started.
- const S32 ROTATE_H_MARGIN = (S32) (0.1f * gViewerWindow->getWindowWidth() );
- const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD;
- const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped;
- // ...normal modes can only yaw
- if (x < ROTATE_H_MARGIN)
- {
- gAgent.yaw(rotate_angle);
- mMouseOutsideSlop = TRUE;
- }
- else if (x > gViewerWindow->getWindowWidth() - ROTATE_H_MARGIN)
- {
- gAgent.yaw(-rotate_angle);
- mMouseOutsideSlop = TRUE;
- }
- */
-
- LLViewerObject *object = NULL;
+ mHoverPick = gViewerWindow->pickImmediate(x, y, FALSE);
+
+ // Show screen-space highlight glow effect
+ bool show_highlight = false;
LLViewerObject *parent = NULL;
- if (gHoverView)
- {
- object = gViewerWindow->getHoverPick().getObject();
- }
+ LLViewerObject *object = mHoverPick.getObject();
if (object)
{
parent = object->getRootEdit();
}
- if (object && useClickAction(FALSE, mask, object, parent))
+ if (object && useClickAction(mask, object, parent))
{
+ show_highlight = true;
ECursorType cursor = cursor_from_object(object);
- gViewerWindow->getWindow()->setCursor(cursor);
+ gViewerWindow->setCursor(cursor);
+ lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
+ }
+ else if (handleMediaHover(mHoverPick))
+ {
+ // *NOTE: If you think the hover glow conflicts with the media outline, you
+ // could disable it here.
+ show_highlight = true;
+ // cursor set by media object
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
}
else if ((object && !object->isAvatar() && object->usePhysics())
|| (parent && !parent->isAvatar() && parent->usePhysics()))
{
- gViewerWindow->getWindow()->setCursor(UI_CURSOR_TOOLGRAB);
+ show_highlight = true;
+ gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB);
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
}
else if ( (object && object->flagHandleTouch())
|| (parent && parent->flagHandleTouch()))
{
- gViewerWindow->getWindow()->setCursor(UI_CURSOR_HAND);
+ show_highlight = true;
+ gViewerWindow->setCursor(UI_CURSOR_HAND);
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
}
else
{
- gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
+ gViewerWindow->setCursor(UI_CURSOR_ARROW);
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
+
+ if(!object)
+ {
+ LLViewerMediaFocus::getInstance()->clearHover();
+ }
}
+ static LLCachedControl<bool> enable_highlight(
+ gSavedSettings, "RenderHoverGlowEnable", false);
+ LLDrawable* drawable = NULL;
+ if (enable_highlight && show_highlight && object)
+ {
+ drawable = object->mDrawable;
+ }
+ gPipeline.setHighlightObject(drawable);
+
return TRUE;
}
BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask)
{
LLViewerObject* obj = mPick.getObject();
+
+ handleMediaMouseUp();
+
U8 click_action = final_click_action(obj);
if (click_action != CLICK_ACTION_NONE)
{
@@ -605,32 +573,29 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask)
case CLICK_ACTION_BUY:
case CLICK_ACTION_PAY:
case CLICK_ACTION_OPEN:
+ case CLICK_ACTION_ZOOM:
+ case CLICK_ACTION_PLAY:
+ case CLICK_ACTION_OPEN_MEDIA:
// Because these actions open UI dialogs, we won't change
// the cursor again until the next hover and GL pick over
// the world. Keep the cursor an arrow, assuming that
// after the user moves off the UI, they won't be on the
// same object anymore.
- gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
+ gViewerWindow->setCursor(UI_CURSOR_ARROW);
// Make sure the hover-picked object is ignored.
- gHoverView->resetLastHoverObject();
+ //gToolTipView->resetLastHoverObject();
break;
default:
break;
}
}
+
mGrabMouseButtonDown = FALSE;
LLToolMgr::getInstance()->clearTransientTool();
gAgent.setLookAt(LOOKAT_TARGET_CONVERSATION, obj); // maybe look at object/person clicked on
return LLTool::handleMouseUp(x, y, mask);
}
-BOOL LLToolPie::handleRightMouseUp(S32 x, S32 y, MASK mask)
-{
- mPieMouseButtonDown = FALSE;
- LLToolMgr::getInstance()->clearTransientTool();
- return LLTool::handleRightMouseUp(x, y, mask);
-}
-
BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask)
{
@@ -650,39 +615,543 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask)
else if (mPick.mObjectID.notNull()
&& !mPick.mPosGlobal.isExactlyZero())
{
- // Hit an object
- // HACK: Call the last hit position the point we hit on the object
- //gLastHitPosGlobal += gLastHitObjectOffset;
handle_go_to();
return TRUE;
}
}
return FALSE;
+}
- /* JC - don't do go-there, because then double-clicking on physical
- objects gets you into trouble.
+static bool needs_tooltip(LLSelectNode* nodep)
+{
+ if (!nodep)
+ return false;
+
+ LLViewerObject* object = nodep->getObject();
+ LLViewerObject *parent = (LLViewerObject *)object->getParent();
+ if (object->flagHandleTouch()
+ || (parent && parent->flagHandleTouch())
+ || object->flagTakesMoney()
+ || (parent && parent->flagTakesMoney())
+ || object->flagAllowInventoryAdd()
+ )
+ {
+ return true;
+ }
- // If double-click on object or land, go there.
- LLViewerObject *object = gViewerWindow->getLastPick().getObject();
- if (object)
+ U8 click_action = final_click_action(object);
+ if (click_action != 0)
{
- if (object->isAvatar())
+ return true;
+ }
+
+ if (nodep->mValid)
+ {
+ bool anyone_copy = anyone_copy_selection(nodep);
+ bool for_sale = for_sale_selection(nodep);
+ if (anyone_copy || for_sale)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+BOOL LLToolPie::handleTooltipLand(std::string line, std::string tooltip_msg)
+{
+ LLViewerParcelMgr::getInstance()->setHoverParcel( mHoverPick.mPosGlobal );
+ //
+ // Do not show hover for land unless prefs are set to allow it.
+ //
+
+ if (!gSavedSettings.getBOOL("ShowLandHoverTip")) return TRUE;
+
+ // Didn't hit an object, but since we have a land point we
+ // must be hovering over land.
+
+ LLParcel* hover_parcel = LLViewerParcelMgr::getInstance()->getHoverParcel();
+ LLUUID owner;
+ S32 width = 0;
+ S32 height = 0;
+
+ if ( hover_parcel )
+ {
+ owner = hover_parcel->getOwnerID();
+ width = S32(LLViewerParcelMgr::getInstance()->getHoverParcelWidth());
+ height = S32(LLViewerParcelMgr::getInstance()->getHoverParcelHeight());
+ }
+
+ // Line: "Land"
+ line.clear();
+ line.append(LLTrans::getString("TooltipLand"));
+ if (hover_parcel)
+ {
+ line.append(hover_parcel->getName());
+ }
+ tooltip_msg.append(line);
+ tooltip_msg.push_back('\n');
+
+ // Line: "Owner: James Linden"
+ line.clear();
+ line.append(LLTrans::getString("TooltipOwner") + " ");
+
+ if ( hover_parcel )
+ {
+ std::string name;
+ if (LLUUID::null == owner)
+ {
+ line.append(LLTrans::getString("TooltipPublic"));
+ }
+ else if (hover_parcel->getIsGroupOwned())
+ {
+ if (gCacheName->getGroupName(owner, name))
+ {
+ line.append(name);
+ line.append(LLTrans::getString("TooltipIsGroup"));
+ }
+ else
+ {
+ line.append(LLTrans::getString("RetrievingData"));
+ }
+ }
+ else if(gCacheName->getFullName(owner, name))
{
- LLFloaterAvatarInfo::showFromAvatar(object->getID());
+ line.append(name);
}
else
{
- handle_go_to(NULL);
+ line.append(LLTrans::getString("RetrievingData"));
+ }
+ }
+ else
+ {
+ line.append(LLTrans::getString("RetrievingData"));
+ }
+ tooltip_msg.append(line);
+ tooltip_msg.push_back('\n');
+
+ // Line: "no fly, not safe, no build"
+
+ // Don't display properties for your land. This is just
+ // confusing, because you can do anything on your own land.
+ if ( hover_parcel && owner != gAgent.getID() )
+ {
+ S32 words = 0;
+
+ line.clear();
+ // JC - Keep this in the same order as the checkboxes
+ // on the land info panel
+ if ( !hover_parcel->getAllowModify() )
+ {
+ if ( hover_parcel->getAllowGroupModify() )
+ {
+ line.append(LLTrans::getString("TooltipFlagGroupBuild"));
+ }
+ else
+ {
+ line.append(LLTrans::getString("TooltipFlagNoBuild"));
+ }
+ words++;
+ }
+
+ if ( !hover_parcel->getAllowTerraform() )
+ {
+ if (words) line.append(", ");
+ line.append(LLTrans::getString("TooltipFlagNoEdit"));
+ words++;
+ }
+
+ if ( hover_parcel->getAllowDamage() )
+ {
+ if (words) line.append(", ");
+ line.append(LLTrans::getString("TooltipFlagNotSafe"));
+ words++;
+ }
+
+ // Maybe we should reflect the estate's block fly bit here as well? DK 12/1/04
+ if ( !hover_parcel->getAllowFly() )
+ {
+ if (words) line.append(", ");
+ line.append(LLTrans::getString("TooltipFlagNoFly"));
+ words++;
+ }
+
+ if ( !hover_parcel->getAllowOtherScripts() )
+ {
+ if (words) line.append(", ");
+ if ( hover_parcel->getAllowGroupScripts() )
+ {
+ line.append(LLTrans::getString("TooltipFlagGroupScripts"));
+ }
+ else
+ {
+ line.append(LLTrans::getString("TooltipFlagNoScripts"));
+ }
+
+ words++;
+ }
+
+ if (words)
+ {
+ tooltip_msg.append(line);
+ tooltip_msg.push_back('\n');
+ }
+ }
+
+ if (hover_parcel && hover_parcel->getParcelFlag(PF_FOR_SALE))
+ {
+ LLStringUtil::format_map_t args;
+ args["[AMOUNT]"] = llformat("%d", hover_parcel->getSalePrice());
+ line = LLTrans::getString("TooltipForSaleL$", args);
+ tooltip_msg.append(line);
+ tooltip_msg.push_back('\n');
+ }
+
+ // trim last newlines
+ if (!tooltip_msg.empty())
+ {
+ tooltip_msg.erase(tooltip_msg.size() - 1);
+ LLToolTipMgr::instance().show(tooltip_msg);
+ }
+
+ return TRUE;
+}
+
+BOOL LLToolPie::handleTooltipObject( LLViewerObject* hover_object, std::string line, std::string tooltip_msg)
+{
+ if ( hover_object->isHUDAttachment() )
+ {
+ // no hover tips for HUD elements, since they can obscure
+ // what the HUD is displaying
+ return TRUE;
+ }
+
+ if ( hover_object->isAttachment() )
+ {
+ // get root of attachment then parent, which is avatar
+ LLViewerObject* root_edit = hover_object->getRootEdit();
+ if (!root_edit)
+ {
+ // Strange parenting issue, don't show any text
+ return TRUE;
+ }
+ hover_object = (LLViewerObject*)root_edit->getParent();
+ if (!hover_object)
+ {
+ // another strange parenting issue, bail out
+ return TRUE;
+ }
+ }
+
+ line.clear();
+ if (hover_object->isAvatar())
+ {
+ // only show tooltip if same inspector not already open
+ LLFloater* existing_inspector = LLFloaterReg::findInstance("inspect_avatar");
+ if (!existing_inspector
+ || !existing_inspector->getVisible()
+ || existing_inspector->getKey()["avatar_id"].asUUID() != hover_object->getID())
+ {
+ std::string avatar_name;
+ LLNameValue* firstname = hover_object->getNVPair("FirstName");
+ LLNameValue* lastname = hover_object->getNVPair("LastName");
+ if (firstname && lastname)
+ {
+ avatar_name = llformat("%s %s", firstname->getString(), lastname->getString());
+ }
+ else
+ {
+ avatar_name = LLTrans::getString("TooltipPerson");
+ }
+
+ // *HACK: We may select this object, so pretend it was clicked
+ mPick = mHoverPick;
+ LLInspector::Params p;
+ p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>());
+ p.message(avatar_name);
+ p.image.name("Inspector_I");
+ p.click_callback(boost::bind(showAvatarInspector, hover_object->getID()));
+ p.visible_time_near(6.f);
+ p.visible_time_far(3.f);
+ p.delay_time(0.35f);
+ p.wrap(false);
+
+ LLToolTipMgr::instance().show(p);
+ }
+ }
+ else
+ {
+ //
+ // We have hit a regular object (not an avatar or attachment)
+ //
+
+ //
+ // Default prefs will suppress display unless the object is interactive
+ //
+ bool show_all_object_tips =
+ (bool)gSavedSettings.getBOOL("ShowAllObjectHoverTip");
+ LLSelectNode *nodep = LLSelectMgr::getInstance()->getHoverNode();
+
+ // only show tooltip if same inspector not already open
+ LLFloater* existing_inspector = LLFloaterReg::findInstance("inspect_object");
+ if (nodep &&
+ (!existing_inspector
+ || !existing_inspector->getVisible()
+ || existing_inspector->getKey()["object_id"].asUUID() != hover_object->getID()))
+ {
+ if (nodep->mName.empty())
+ {
+ tooltip_msg.append(LLTrans::getString("TooltipNoName"));
+ }
+ else
+ {
+ tooltip_msg.append( nodep->mName );
+ }
+
+ bool is_time_based_media = false;
+ bool is_web_based_media = false;
+ bool is_media_playing = false;
+
+ // Does this face have media?
+ const LLTextureEntry* tep = hover_object->getTE(mHoverPick.mObjectFace);
+
+ if(tep)
+ {
+ const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
+ if (mep)
+ {
+ viewer_media_t media_impl = mep ? LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()) : NULL;
+ LLPluginClassMedia* media_plugin = NULL;
+
+ if (media_impl.notNull() && (media_impl->hasMedia()))
+ {
+ LLStringUtil::format_map_t args;
+
+ media_plugin = media_impl->getMediaPlugin();
+ if(media_plugin)
+ { if(media_plugin->pluginSupportsMediaTime())
+ {
+ is_time_based_media = true;
+ is_web_based_media = false;
+ //args["[CurrentURL]"] = media_impl->getMediaURL();
+ is_media_playing = media_impl->isMediaPlaying();
+ }
+ else
+ {
+ is_time_based_media = false;
+ is_web_based_media = true;
+ //args["[CurrentURL]"] = media_plugin->getLocation();
+ }
+ //tooltip_msg.append(LLTrans::getString("CurrentURL", args));
+ }
+ }
+ }
+ }
+
+ // also check the primary node since sometimes it can have an action even though
+ // the root node doesn't
+ bool needs_tip = needs_tooltip(nodep) ||
+ needs_tooltip(LLSelectMgr::getInstance()->getPrimaryHoverNode());
+
+ if (show_all_object_tips || needs_tip)
+ {
+ // We may select this object, so pretend it was clicked
+ mPick = mHoverPick;
+ LLInspector::Params p;
+ p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>());
+ p.message(tooltip_msg);
+ p.image.name("Inspector_I");
+ p.click_callback(boost::bind(showObjectInspector, hover_object->getID(), mHoverPick.mObjectFace));
+ p.time_based_media(is_time_based_media);
+ p.web_based_media(is_web_based_media);
+ p.media_playing(is_media_playing);
+ p.click_playmedia_callback(boost::bind(playCurrentMedia, mHoverPick));
+ p.click_homepage_callback(boost::bind(VisitHomePage, mHoverPick));
+ p.visible_time_near(6.f);
+ p.visible_time_far(3.f);
+ p.delay_time(0.35f);
+ p.wrap(false);
+
+ LLToolTipMgr::instance().show(p);
+ }
}
}
- else if (!gLastHitPosGlobal.isExactlyZero())
+
+ return TRUE;
+}
+
+BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask)
+{
+ if (!LLUI::sSettingGroups["config"]->getBOOL("ShowHoverTips")) return TRUE;
+ if (!mHoverPick.isValid()) return TRUE;
+
+ LLViewerObject* hover_object = mHoverPick.getObject();
+
+ // update hover object and hover parcel
+ LLSelectMgr::getInstance()->setHoverObject(hover_object, mHoverPick.mObjectFace);
+
+
+ std::string tooltip_msg;
+ std::string line;
+
+ if ( hover_object )
+ {
+ handleTooltipObject(hover_object, line, tooltip_msg );
+ }
+ else if (mHoverPick.mPickType == LLPickInfo::PICK_LAND)
{
- handle_go_to(NULL);
+ handleTooltipLand(line, tooltip_msg);
}
return TRUE;
- */
+}
+
+static void show_inspector(const char* inspector, const char* param, const LLUUID& source_id)
+{
+ LLSD params;
+ params[param] = source_id;
+ if (LLToolTipMgr::instance().toolTipVisible())
+ {
+ LLRect rect = LLToolTipMgr::instance().getToolTipRect();
+ params["pos"]["x"] = rect.mLeft;
+ params["pos"]["y"] = rect.mTop;
+ }
+
+ LLFloaterReg::showInstance(inspector, params);
+}
+
+
+static void show_inspector(const char* inspector, LLSD& params)
+{
+ if (LLToolTipMgr::instance().toolTipVisible())
+ {
+ LLRect rect = LLToolTipMgr::instance().getToolTipRect();
+ params["pos"]["x"] = rect.mLeft;
+ params["pos"]["y"] = rect.mTop;
+ }
+
+ LLFloaterReg::showInstance(inspector, params);
+}
+
+
+// static
+void LLToolPie::showAvatarInspector(const LLUUID& avatar_id)
+{
+ show_inspector("inspect_avatar", "avatar_id", avatar_id);
+}
+
+// static
+void LLToolPie::showObjectInspector(const LLUUID& object_id)
+{
+ show_inspector("inspect_object", "object_id", object_id);
+}
+
+
+// static
+void LLToolPie::showObjectInspector(const LLUUID& object_id, const S32& object_face)
+{
+ LLSD params;
+ params["object_id"] = object_id;
+ params["object_face"] = object_face;
+ show_inspector("inspect_object", params);
+}
+
+// static
+void LLToolPie::playCurrentMedia(const LLPickInfo& info)
+{
+ //FIXME: how do we handle object in different parcel than us?
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ if (!parcel) return;
+
+ LLPointer<LLViewerObject> objectp = info.getObject();
+
+ // Early out cases. Must clear media hover.
+ // did not hit an object or did not hit a valid face
+ if ( objectp.isNull() ||
+ info.mObjectFace < 0 ||
+ info.mObjectFace >= objectp->getNumTEs() )
+ {
+ return;
+ }
+
+ // Does this face have media?
+ const LLTextureEntry* tep = objectp->getTE(info.mObjectFace);
+ if (!tep)
+ return;
+
+ const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
+ if(!mep)
+ return;
+
+ //TODO: Can you Use it?
+
+ LLPluginClassMedia* media_plugin = NULL;
+
+ viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
+
+ if(media_impl.notNull() && media_impl->hasMedia())
+ {
+ media_plugin = media_impl->getMediaPlugin();
+ if (media_plugin && media_plugin->pluginSupportsMediaTime())
+ {
+ if(media_impl->isMediaPlaying())
+ {
+ media_impl->pause();
+ }
+ else
+ {
+ media_impl->play();
+ }
+ }
+ }
+
+
+}
+
+// static
+void LLToolPie::VisitHomePage(const LLPickInfo& info)
+{
+ //FIXME: how do we handle object in different parcel than us?
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ if (!parcel) return;
+
+ LLPointer<LLViewerObject> objectp = info.getObject();
+
+ // Early out cases. Must clear media hover.
+ // did not hit an object or did not hit a valid face
+ if ( objectp.isNull() ||
+ info.mObjectFace < 0 ||
+ info.mObjectFace >= objectp->getNumTEs() )
+ {
+ return;
+ }
+
+ // Does this face have media?
+ const LLTextureEntry* tep = objectp->getTE(info.mObjectFace);
+ if (!tep)
+ return;
+
+ const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
+ if(!mep)
+ return;
+
+ //TODO: Can you Use it?
+
+ LLPluginClassMedia* media_plugin = NULL;
+
+ viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
+
+ if(media_impl.notNull() && media_impl->hasMedia())
+ {
+ media_plugin = media_impl->getMediaPlugin();
+
+ if (media_plugin && !(media_plugin->pluginSupportsMediaTime()))
+ {
+ media_impl->navigateHome();
+ }
+ }
}
@@ -693,6 +1162,7 @@ void LLToolPie::handleDeselect()
setMouseCapture( FALSE ); // Calls onMouseCaptureLost() indirectly
}
// remove temporary selection for pie menu
+ LLSelectMgr::getInstance()->setHoverObject(NULL);
LLSelectMgr::getInstance()->validateSelection();
}
@@ -721,6 +1191,7 @@ void LLToolPie::stopEditing()
void LLToolPie::onMouseCaptureLost()
{
mMouseOutsideSlop = FALSE;
+ handleMediaMouseUp();
}
@@ -744,14 +1215,14 @@ static void handle_click_action_play()
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
if (!parcel) return;
- LLMediaBase::EStatus status = LLViewerParcelMedia::getStatus();
+ LLViewerMediaImpl::EMediaStatus status = LLViewerParcelMedia::getStatus();
switch(status)
{
- case LLMediaBase::STATUS_STARTED:
+ case LLViewerMediaImpl::MEDIA_PLAYING:
LLViewerParcelMedia::pause();
break;
- case LLMediaBase::STATUS_PAUSED:
+ case LLViewerMediaImpl::MEDIA_PAUSED:
LLViewerParcelMedia::start();
break;
@@ -761,6 +1232,142 @@ static void handle_click_action_play()
}
}
+bool LLToolPie::handleMediaClick(const LLPickInfo& pick)
+{
+ //FIXME: how do we handle object in different parcel than us?
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ LLPointer<LLViewerObject> objectp = pick.getObject();
+
+
+ if (!parcel ||
+ objectp.isNull() ||
+ pick.mObjectFace < 0 ||
+ pick.mObjectFace >= objectp->getNumTEs())
+ {
+ LLViewerMediaFocus::getInstance()->clearFocus();
+
+ return false;
+ }
+
+ // Does this face have media?
+ const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace);
+ if(!tep)
+ return false;
+
+ LLMediaEntry* mep = (tep->hasMedia()) ? tep->getMediaData() : NULL;
+
+ if(!mep)
+ return false;
+
+ viewer_media_t media_impl = mep ? LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()) : NULL;
+
+ if (gSavedSettings.getBOOL("MediaOnAPrimUI"))
+ {
+ if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) || media_impl.isNull())
+ {
+ // It's okay to give this a null impl
+ LLViewerMediaFocus::getInstance()->setFocusFace(pick.getObject(), pick.mObjectFace, media_impl, pick.mNormal);
+ }
+ else
+ {
+ // Make sure keyboard focus is set to the media focus object.
+ gFocusMgr.setKeyboardFocus(LLViewerMediaFocus::getInstance());
+
+ media_impl->mouseDown(pick.mUVCoords, gKeyboard->currentMask(TRUE));
+ mMediaMouseCaptureID = mep->getMediaID();
+ setMouseCapture(TRUE); // This object will send a mouse-up to the media when it loses capture.
+ }
+
+ return true;
+ }
+
+ LLViewerMediaFocus::getInstance()->clearFocus();
+
+ return false;
+}
+
+bool LLToolPie::handleMediaHover(const LLPickInfo& pick)
+{
+ //FIXME: how do we handle object in different parcel than us?
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ if (!parcel) return false;
+
+ LLPointer<LLViewerObject> objectp = pick.getObject();
+
+ // Early out cases. Must clear media hover.
+ // did not hit an object or did not hit a valid face
+ if ( objectp.isNull() ||
+ pick.mObjectFace < 0 ||
+ pick.mObjectFace >= objectp->getNumTEs() )
+ {
+ LLViewerMediaFocus::getInstance()->clearHover();
+ return false;
+ }
+
+ // Does this face have media?
+ const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace);
+ if(!tep)
+ return false;
+
+ const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
+ if (mep
+ && gSavedSettings.getBOOL("MediaOnAPrimUI"))
+ {
+ viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID());
+
+ if(media_impl.notNull())
+ {
+ // Update media hover object
+ if (!LLViewerMediaFocus::getInstance()->isHoveringOverFace(objectp, pick.mObjectFace))
+ {
+ LLViewerMediaFocus::getInstance()->setHoverFace(objectp, pick.mObjectFace, media_impl, pick.mNormal);
+ }
+
+ // If this is the focused media face, send mouse move events.
+ if (LLViewerMediaFocus::getInstance()->isFocusedOnFace(objectp, pick.mObjectFace))
+ {
+ media_impl->mouseMove(pick.mUVCoords, gKeyboard->currentMask(TRUE));
+ gViewerWindow->setCursor(media_impl->getLastSetCursor());
+ }
+ else
+ {
+ // This is not the focused face -- set the default cursor.
+ gViewerWindow->setCursor(UI_CURSOR_ARROW);
+ }
+
+ return true;
+ }
+ }
+
+ // In all other cases, clear media hover.
+ LLViewerMediaFocus::getInstance()->clearHover();
+
+ return false;
+}
+
+bool LLToolPie::handleMediaMouseUp()
+{
+ bool result = false;
+ if(mMediaMouseCaptureID.notNull())
+ {
+ // Face media needs to know the mouse went up.
+ viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mMediaMouseCaptureID);
+ if(media_impl)
+ {
+ // This will send a mouseUp event to the plugin using the last known mouse coordinate (from a mouseDown or mouseMove), which is what we want.
+ media_impl->onMouseCaptureLost();
+ }
+
+ mMediaMouseCaptureID.setNull();
+
+ setMouseCapture(FALSE);
+
+ result = true;
+ }
+
+ return result;
+}
+
static void handle_click_action_open_media(LLPointer<LLViewerObject> objectp)
{
//FIXME: how do we handle object in different parcel than us?
@@ -775,7 +1382,7 @@ static void handle_click_action_open_media(LLPointer<LLViewerObject> objectp)
if( face < 0 || face >= objectp->getNumTEs() ) return;
// is media playing on this face?
- if (!LLViewerMedia::isActiveMediaTexture(objectp->getTE(face)->getID()))
+ if (LLViewerMedia::getMediaImplFromTextureID(objectp->getTE(face)->getID()) != NULL)
{
handle_click_action_play();
return;
@@ -785,18 +1392,7 @@ static void handle_click_action_open_media(LLPointer<LLViewerObject> objectp)
std::string media_type = std::string ( parcel->getMediaType() );
LLStringUtil::trim(media_url);
- // Get the scheme, see if that is handled as well.
- LLURI uri(media_url);
- std::string media_scheme = uri.scheme() != "" ? uri.scheme() : "http";
-
- // HACK: This is directly referencing an impl name. BAD!
- // This can be removed when we have a truly generic media browser that only
- // builds an impl based on the type of url it is passed.
-
- if( LLMediaManager::getInstance()->supportsMediaType( "LLMediaImplLLMozLib", media_scheme, media_type ) )
- {
- LLWeb::loadURL(media_url);
- }
+ LLWeb::loadURL(media_url);
}
static ECursorType cursor_from_parcel_media(U8 click_action)
@@ -814,21 +1410,140 @@ static ECursorType cursor_from_parcel_media(U8 click_action)
std::string media_type = std::string ( parcel->getMediaType() );
LLStringUtil::trim(media_url);
- // Get the scheme, see if that is handled as well.
- LLURI uri(media_url);
- std::string media_scheme = uri.scheme() != "" ? uri.scheme() : "http";
-
- if( LLMediaManager::getInstance()->supportsMediaType( "LLMediaImplLLMozLib", media_scheme, media_type ) )
- {
- open_cursor = UI_CURSOR_TOOLMEDIAOPEN;
- }
+ open_cursor = UI_CURSOR_TOOLMEDIAOPEN;
- LLMediaBase::EStatus status = LLViewerParcelMedia::getStatus();
+ LLViewerMediaImpl::EMediaStatus status = LLViewerParcelMedia::getStatus();
switch(status)
{
- case LLMediaBase::STATUS_STARTED:
+ case LLViewerMediaImpl::MEDIA_PLAYING:
return click_action == CLICK_ACTION_PLAY ? UI_CURSOR_TOOLPAUSE : open_cursor;
default:
return UI_CURSOR_TOOLPLAY;
}
}
+
+
+// True if we handled the event.
+BOOL LLToolPie::pickRightMouseDownCallback()
+{
+ S32 x = mPick.mMousePt.mX;
+ S32 y = mPick.mMousePt.mY;
+ MASK mask = mPick.mKeyMask;
+
+ if (mPick.mPickType != LLPickInfo::PICK_LAND)
+ {
+ LLViewerParcelMgr::getInstance()->deselectLand();
+ }
+
+ // didn't click in any UI object, so must have clicked in the world
+ LLViewerObject *object = mPick.getObject();
+ LLViewerObject *parent = NULL;
+ if(object)
+ parent = object->getRootEdit();
+
+ // Can't ignore children here.
+ LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE);
+
+ // Spawn pie menu
+ if (mPick.mPickType == LLPickInfo::PICK_LAND)
+ {
+ LLParcelSelectionHandle selection = LLViewerParcelMgr::getInstance()->selectParcelAt( mPick.mPosGlobal );
+ gMenuHolder->setParcelSelection(selection);
+ gMenuLand->show(x, y);
+
+ showVisualContextMenuEffect();
+
+ }
+ else if (mPick.mObjectID == gAgent.getID() )
+ {
+ if(!gMenuAvatarSelf)
+ {
+ //either at very early startup stage or at late quitting stage,
+ //this event is ignored.
+ return TRUE ;
+ }
+
+ gMenuAvatarSelf->show(x, y);
+ }
+ else if (object)
+ {
+ gMenuHolder->setObjectSelection(LLSelectMgr::getInstance()->getSelection());
+
+ bool is_other_attachment = (object->isAttachment() && !object->isHUDAttachment() && !object->permYouOwner());
+ if (object->isAvatar()
+ || is_other_attachment)
+ {
+ // Find the attachment's avatar
+ while( object && object->isAttachment())
+ {
+ object = (LLViewerObject*)object->getParent();
+ }
+
+ // Object is an avatar, so check for mute by id.
+ LLVOAvatar* avatar = (LLVOAvatar*)object;
+ std::string name = avatar->getFullname();
+ std::string mute_msg;
+ if (LLMuteList::getInstance()->isMuted(avatar->getID(), avatar->getFullname()))
+ {
+ mute_msg = LLTrans::getString("UnmuteAvatar");
+ }
+ else
+ {
+ mute_msg = LLTrans::getString("MuteAvatar");
+ }
+
+ if (is_other_attachment)
+ {
+ gMenuAttachmentOther->getChild<LLUICtrl>("Avatar Mute")->setValue(mute_msg);
+ gMenuAttachmentOther->show(x, y);
+ }
+ else
+ {
+ gMenuAvatarOther->getChild<LLUICtrl>("Avatar Mute")->setValue(mute_msg);
+ gMenuAvatarOther->show(x, y);
+ }
+ }
+ else if (object->isAttachment())
+ {
+ gMenuAttachmentSelf->show(x, y);
+ }
+ else
+ {
+ // BUG: What about chatting child objects?
+ std::string name;
+ LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
+ if (node)
+ {
+ name = node->mName;
+ }
+ std::string mute_msg;
+ if (LLMuteList::getInstance()->isMuted(object->getID(), name))
+ {
+ mute_msg = LLTrans::getString("UnmuteObject");
+ }
+ else
+ {
+ mute_msg = LLTrans::getString("MuteObject2");
+ }
+
+ gMenuHolder->childSetText("Object Mute", mute_msg);
+ gMenuObject->show(x, y);
+
+ showVisualContextMenuEffect();
+ }
+ }
+
+ LLTool::handleRightMouseDown(x, y, mask);
+ // We handled the event.
+ return TRUE;
+}
+
+void LLToolPie::showVisualContextMenuEffect()
+{
+ // VEFFECT: ShowPie
+ LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE);
+ effectp->setPositionGlobal(mPick.mPosGlobal);
+ effectp->setColor(LLColor4U(gAgent.getEffectColor()));
+ effectp->setDuration(0.25f);
+
+}
diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h
index 83df03cda2..8a4c949aef 100644
--- a/indra/newview/lltoolpie.h
+++ b/indra/newview/lltoolpie.h
@@ -42,15 +42,20 @@ class LLObjectSelection;
class LLToolPie : public LLTool, public LLSingleton<LLToolPie>
{
+ LOG_CLASS(LLToolPie);
public:
LLToolPie( );
+ // Virtual functions inherited from LLMouseHandler
+ virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
+ virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
virtual void render();
@@ -66,26 +71,38 @@ public:
LLObjectSelection* getLeftClickSelection() { return (LLObjectSelection*)mLeftClickSelection; }
void resetSelection();
- static void leftMouseCallback(const LLPickInfo& pick_info);
- static void rightMouseCallback(const LLPickInfo& pick_info);
-
static void selectionPropertiesReceived();
-
+ static void showAvatarInspector(const LLUUID& avatar_id);
+ static void showObjectInspector(const LLUUID& object_id);
+ static void showObjectInspector(const LLUUID& object_id, const S32& object_face);
+ static void playCurrentMedia(const LLPickInfo& info);
+ static void VisitHomePage(const LLPickInfo& info);
+
private:
- BOOL outsideSlop(S32 x, S32 y, S32 start_x, S32 start_y);
- BOOL pickAndShowMenu(BOOL edit_menu);
- BOOL useClickAction(BOOL always_show, MASK mask, LLViewerObject* object,
- LLViewerObject* parent);
+ BOOL outsideSlop (S32 x, S32 y, S32 start_x, S32 start_y);
+ BOOL pickLeftMouseDownCallback();
+ BOOL pickRightMouseDownCallback();
+ BOOL useClickAction (MASK mask, LLViewerObject* object,LLViewerObject* parent);
+
+ void showVisualContextMenuEffect();
+
+ bool handleMediaClick(const LLPickInfo& info);
+ bool handleMediaHover(const LLPickInfo& info);
+ bool handleMediaMouseUp();
+ BOOL handleTooltipLand(std::string line, std::string tooltip_msg);
+ BOOL handleTooltipObject( LLViewerObject* hover_object, std::string line, std::string tooltip_msg);
private:
- BOOL mPieMouseButtonDown;
BOOL mGrabMouseButtonDown;
BOOL mMouseOutsideSlop; // for this drag, has mouse moved outside slop region
+ LLUUID mMediaMouseCaptureID;
LLPickInfo mPick;
+ LLPickInfo mHoverPick;
LLPointer<LLViewerObject> mClickActionObject;
U8 mClickAction;
LLSafeHandle<LLObjectSelection> mLeftClickSelection;
+
};
diff --git a/indra/newview/lltoolpipette.cpp b/indra/newview/lltoolpipette.cpp
index 9d95ccc06f..beebb47537 100644
--- a/indra/newview/lltoolpipette.cpp
+++ b/indra/newview/lltoolpipette.cpp
@@ -40,6 +40,7 @@
#include "lltoolpipette.h"
// Library includes
+#include "lltooltip.h"
// Viewer includes
#include "llviewerobjectlist.h"
@@ -55,8 +56,6 @@ LLToolPipette::LLToolPipette()
: LLTool(std::string("Pipette")),
mSuccess(TRUE)
{
- mSelectCallback = NULL;
- mUserData = NULL;
}
@@ -94,18 +93,31 @@ BOOL LLToolPipette::handleHover(S32 x, S32 y, MASK mask)
return FALSE;
}
-BOOL LLToolPipette::handleToolTip(S32 x, S32 y, std::string& msg, LLRect *sticky_rect_screen)
+BOOL LLToolPipette::handleToolTip(S32 x, S32 y, MASK mask)
{
if (mTooltipMsg.empty())
{
return FALSE;
}
- // keep tooltip message up when mouse in this part of screen
- sticky_rect_screen->setCenterAndSize(x, y, 20, 20);
- msg = mTooltipMsg;
+
+ LLRect sticky_rect;
+ sticky_rect.setCenterAndSize(x, y, 20, 20);
+ LLToolTipMgr::instance().show(LLToolTip::Params()
+ .message(mTooltipMsg)
+ .sticky_rect(sticky_rect));
+
return TRUE;
}
+void LLToolPipette::setTextureEntry(const LLTextureEntry* entry)
+{
+ if (entry)
+ {
+ mTextureEntry = *entry;
+ mSignal(mTextureEntry);
+ }
+}
+
void LLToolPipette::pickCallback(const LLPickInfo& pick_info)
{
LLViewerObject* hit_obj = pick_info.getObject();
@@ -118,20 +130,11 @@ void LLToolPipette::pickCallback(const LLPickInfo& pick_info)
{
//TODO: this should highlight the selected face only
LLSelectMgr::getInstance()->highlightObjectOnly(hit_obj);
- LLToolPipette::getInstance()->mTextureEntry = *hit_obj->getTE(pick_info.mObjectFace);
- if (LLToolPipette::getInstance()->mSelectCallback)
- {
- LLToolPipette::getInstance()->mSelectCallback(LLToolPipette::getInstance()->mTextureEntry, LLToolPipette::getInstance()->mUserData);
- }
+ const LLTextureEntry* entry = hit_obj->getTE(pick_info.mObjectFace);
+ LLToolPipette::getInstance()->setTextureEntry(entry);
}
}
-void LLToolPipette::setSelectCallback(select_callback callback, void* user_data)
-{
- mSelectCallback = callback;
- mUserData = user_data;
-}
-
void LLToolPipette::setResult(BOOL success, const std::string& msg)
{
mTooltipMsg = msg;
diff --git a/indra/newview/lltoolpipette.h b/indra/newview/lltoolpipette.h
index 54c24e9467..f86939cfeb 100644
--- a/indra/newview/lltoolpipette.h
+++ b/indra/newview/lltoolpipette.h
@@ -40,6 +40,8 @@
#include "lltool.h"
#include "lltextureentry.h"
+#include <boost/function.hpp>
+#include <boost/signals2.hpp>
class LLViewerObject;
class LLPickInfo;
@@ -54,20 +56,21 @@ public:
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect *sticky_rect_screen);
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
- typedef void (*select_callback)(const LLTextureEntry& te, void *data);
- void setSelectCallback(select_callback callback, void* user_data);
+ // Note: Don't return connection; use boost::bind + boost::signals2::trackable to disconnect slots
+ typedef boost::signals2::signal<void (const LLTextureEntry& te)> signal_t;
+ void setToolSelectCallback(const signal_t::slot_type& cb) { mSignal.connect(cb); }
void setResult(BOOL success, const std::string& msg);
-
+
+ void setTextureEntry(const LLTextureEntry* entry);
static void pickCallback(const LLPickInfo& pick_info);
protected:
LLTextureEntry mTextureEntry;
- select_callback mSelectCallback;
+ signal_t mSignal;
BOOL mSuccess;
std::string mTooltipMsg;
- void* mUserData;
};
#endif //LL_LLTOOLPIPETTE_H
diff --git a/indra/newview/lltoolplacer.cpp b/indra/newview/lltoolplacer.cpp
index 88fddd9336..612bcc03bd 100644
--- a/indra/newview/lltoolplacer.cpp
+++ b/indra/newview/lltoolplacer.cpp
@@ -35,13 +35,10 @@
// self header
#include "lltoolplacer.h"
-// linden library headers
-#include "llprimitive.h"
-
// viewer headers
#include "llbutton.h"
#include "llviewercontrol.h"
-#include "llfirstuse.h"
+//#include "llfirstuse.h"
#include "llfloatertools.h"
#include "llselectmgr.h"
#include "llstatusbar.h"
@@ -59,19 +56,24 @@
#include "llvolumemessage.h"
#include "llhudmanager.h"
#include "llagent.h"
-#include "audioengine.h"
+#include "llaudioengine.h"
#include "llhudeffecttrail.h"
#include "llviewerobjectlist.h"
#include "llviewercamera.h"
#include "llviewerstats.h"
+// linden library headers
+#include "llprimitive.h"
+#include "llwindow.h" // incBusyCount()
+#include "material_codes.h"
+
const LLVector3 DEFAULT_OBJECT_SCALE(0.5f, 0.5f, 0.5f);
//static
LLPCode LLToolPlacer::sObjectType = LL_PCODE_CUBE;
LLToolPlacer::LLToolPlacer()
-: LLTool( std::string("Create") )
+: LLTool( "Create" )
{
}
@@ -186,7 +188,7 @@ BOOL LLToolPlacer::addObject( LLPCode pcode, S32 x, S32 y, U8 use_physics )
if (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX)
{
- LLFirstUse::useSandbox();
+ //LLFirstUse::useSandbox();
}
// Set params for new object based on its PCode.
@@ -489,7 +491,7 @@ BOOL LLToolPlacer::addDuplicate(S32 x, S32 y)
if (regionp
&& (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX))
{
- LLFirstUse::useSandbox();
+ //LLFirstUse::useSandbox();
}
return TRUE;
@@ -521,7 +523,7 @@ BOOL LLToolPlacer::placeObject(S32 x, S32 y, MASK mask)
BOOL LLToolPlacer::handleHover(S32 x, S32 y, MASK mask)
{
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPlacer" << llendl;
- gViewerWindow->getWindow()->setCursor(UI_CURSOR_TOOLCREATE);
+ gViewerWindow->setCursor(UI_CURSOR_TOOLCREATE);
return TRUE;
}
@@ -534,92 +536,3 @@ void LLToolPlacer::handleDeselect()
{
}
-//////////////////////////////////////////////////////
-// LLToolPlacerPanel
-
-// static
-LLPCode LLToolPlacerPanel::sCube = LL_PCODE_CUBE;
-LLPCode LLToolPlacerPanel::sPrism = LL_PCODE_PRISM;
-LLPCode LLToolPlacerPanel::sPyramid = LL_PCODE_PYRAMID;
-LLPCode LLToolPlacerPanel::sTetrahedron = LL_PCODE_TETRAHEDRON;
-LLPCode LLToolPlacerPanel::sCylinder = LL_PCODE_CYLINDER;
-LLPCode LLToolPlacerPanel::sCylinderHemi= LL_PCODE_CYLINDER_HEMI;
-LLPCode LLToolPlacerPanel::sCone = LL_PCODE_CONE;
-LLPCode LLToolPlacerPanel::sConeHemi = LL_PCODE_CONE_HEMI;
-LLPCode LLToolPlacerPanel::sTorus = LL_PCODE_TORUS;
-LLPCode LLToolPlacerPanel::sSquareTorus = LLViewerObject::LL_VO_SQUARE_TORUS;
-LLPCode LLToolPlacerPanel::sTriangleTorus = LLViewerObject::LL_VO_TRIANGLE_TORUS;
-LLPCode LLToolPlacerPanel::sSphere = LL_PCODE_SPHERE;
-LLPCode LLToolPlacerPanel::sSphereHemi = LL_PCODE_SPHERE_HEMI;
-LLPCode LLToolPlacerPanel::sTree = LL_PCODE_LEGACY_TREE;
-LLPCode LLToolPlacerPanel::sGrass = LL_PCODE_LEGACY_GRASS;
-
-S32 LLToolPlacerPanel::sButtonsAdded = 0;
-LLButton* LLToolPlacerPanel::sButtons[ TOOL_PLACER_NUM_BUTTONS ];
-
-LLToolPlacerPanel::LLToolPlacerPanel(const std::string& name, const LLRect& rect)
- :
- LLPanel( name, rect )
-{
- /* DEPRECATED - JC
- addButton( "UIImgCubeUUID", "UIImgCubeSelectedUUID", &LLToolPlacerPanel::sCube );
- addButton( "UIImgPrismUUID", "UIImgPrismSelectedUUID", &LLToolPlacerPanel::sPrism );
- addButton( "UIImgPyramidUUID", "UIImgPyramidSelectedUUID", &LLToolPlacerPanel::sPyramid );
- addButton( "UIImgTetrahedronUUID", "UIImgTetrahedronSelectedUUID", &LLToolPlacerPanel::sTetrahedron );
- addButton( "UIImgCylinderUUID", "UIImgCylinderSelectedUUID", &LLToolPlacerPanel::sCylinder );
- addButton( "UIImgHalfCylinderUUID", "UIImgHalfCylinderSelectedUUID",&LLToolPlacerPanel::sCylinderHemi );
- addButton( "UIImgConeUUID", "UIImgConeSelectedUUID", &LLToolPlacerPanel::sCone );
- addButton( "UIImgHalfConeUUID", "UIImgHalfConeSelectedUUID", &LLToolPlacerPanel::sConeHemi );
- addButton( "UIImgSphereUUID", "UIImgSphereSelectedUUID", &LLToolPlacerPanel::sSphere );
- addButton( "UIImgHalfSphereUUID", "UIImgHalfSphereSelectedUUID", &LLToolPlacerPanel::sSphereHemi );
- addButton( "UIImgTreeUUID", "UIImgTreeSelectedUUID", &LLToolPlacerPanel::sTree );
- addButton( "UIImgGrassUUID", "UIImgGrassSelectedUUID", &LLToolPlacerPanel::sGrass );
- addButton( "ObjectTorusImageID", "ObjectTorusActiveImageID", &LLToolPlacerPanel::sTorus );
- addButton( "ObjectTubeImageID", "ObjectTubeActiveImageID", &LLToolPlacerPanel::sSquareTorus );
- */
-}
-
-void LLToolPlacerPanel::addButton( const std::string& up_state, const std::string& down_state, LLPCode* pcode )
-{
- const S32 TOOL_SIZE = 32;
- const S32 HORIZ_SPACING = TOOL_SIZE + 5;
- const S32 VERT_SPACING = TOOL_SIZE + 5;
- const S32 VPAD = 10;
- const S32 HPAD = 7;
-
- S32 row = sButtonsAdded / 4;
- S32 column = sButtonsAdded % 4;
-
- LLRect help_rect = gSavedSettings.getRect("ToolHelpRect");
-
- // Build the rectangle, recalling the origin is at lower left
- // and we want the icons to build down from the top.
- LLRect rect;
- rect.setLeftTopAndSize(
- HPAD + (column * HORIZ_SPACING),
- help_rect.mBottom - VPAD - (row * VERT_SPACING),
- TOOL_SIZE,
- TOOL_SIZE );
-
- LLButton* btn = new LLButton(
- std::string("ToolPlacerOptBtn"),
- rect,
- up_state,
- down_state,
- LLStringUtil::null, &LLToolPlacerPanel::setObjectType,
- pcode,
- LLFontGL::getFontSansSerif());
- btn->setFollowsBottom();
- btn->setFollowsLeft();
- addChild(btn);
-
- sButtons[sButtonsAdded] = btn;
- sButtonsAdded++;
-}
-
-// static
-void LLToolPlacerPanel::setObjectType( void* data )
-{
- LLPCode pcode = *(LLPCode*) data;
- LLToolPlacer::setObjectType( pcode );
-}
diff --git a/indra/newview/lltoolplacer.h b/indra/newview/lltoolplacer.h
index d478f7b1c2..b7422380d4 100644
--- a/indra/newview/lltoolplacer.h
+++ b/indra/newview/lltoolplacer.h
@@ -67,43 +67,4 @@ private:
BOOL addDuplicate(S32 x, S32 y);
};
-////////////////////////////////////////////////////
-// LLToolPlacerPanel
-
-
-const S32 TOOL_PLACER_NUM_BUTTONS = 14;
-
-
-class LLToolPlacerPanel : public LLPanel
-{
-public:
-
- LLToolPlacerPanel(const std::string& name, const LLRect& rect);
-
- static void setObjectType( void* data );
-
- static LLPCode sCube;
- static LLPCode sPrism;
- static LLPCode sPyramid;
- static LLPCode sTetrahedron;
- static LLPCode sCylinder;
- static LLPCode sCylinderHemi;
- static LLPCode sCone;
- static LLPCode sConeHemi;
- static LLPCode sTorus;
- static LLPCode sSquareTorus;
- static LLPCode sTriangleTorus;
- static LLPCode sSphere;
- static LLPCode sSphereHemi;
- static LLPCode sTree;
- static LLPCode sGrass;
-
-private:
- void addButton( const std::string& up_state, const std::string& down_state, LLPCode* pcode );
-
-private:
- static S32 sButtonsAdded;
- static LLButton* sButtons[ TOOL_PLACER_NUM_BUTTONS ];
-};
-
#endif
diff --git a/indra/newview/lltoolselect.cpp b/indra/newview/lltoolselect.cpp
index 80e99174c7..97e2865179 100644
--- a/indra/newview/lltoolselect.cpp
+++ b/indra/newview/lltoolselect.cpp
@@ -48,11 +48,11 @@
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "llviewerwindow.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "llworld.h"
// Globals
-extern BOOL gAllowSelectAvatar;
+//extern BOOL gAllowSelectAvatar;
const F32 SELECTION_ROTATION_TRESHOLD = 0.1f;
@@ -87,7 +87,7 @@ LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pi
BOOL select_movable = gSavedSettings.getBOOL("SelectMovableOnly");
// *NOTE: These settings must be cleaned up at bottom of function.
- if (temp_select || gAllowSelectAvatar)
+ if (temp_select || LLSelectMgr::getInstance()->mAllowSelectAvatar)
{
gSavedSettings.setBOOL("SelectOwnedOnly", FALSE);
gSavedSettings.setBOOL("SelectMovableOnly", FALSE);
@@ -217,7 +217,7 @@ LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pi
} //if(!object)
// Cleanup temp select settings above.
- if (temp_select || gAllowSelectAvatar)
+ if (temp_select ||LLSelectMgr::getInstance()->mAllowSelectAvatar)
{
gSavedSettings.setBOOL("SelectOwnedOnly", select_owned);
gSavedSettings.setBOOL("SelectMovableOnly", select_movable);
diff --git a/indra/newview/lltoolselectland.cpp b/indra/newview/lltoolselectland.cpp
index 91223904b7..5c8b08db3b 100644
--- a/indra/newview/lltoolselectland.cpp
+++ b/indra/newview/lltoolselectland.cpp
@@ -38,12 +38,10 @@
#include "llparcel.h"
// Viewer includes
-#include "llagent.h"
#include "llviewercontrol.h"
#include "llfloatertools.h"
#include "llselectmgr.h"
#include "llstatusbar.h"
-#include "lltoolview.h"
#include "llviewerparcelmgr.h"
#include "llviewerwindow.h"
@@ -177,13 +175,13 @@ BOOL LLToolSelectLand::handleHover(S32 x, S32 y, MASK mask)
roundXY(mEastNorthTop);
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolSelectLand (active, land)" << llendl;
- gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
+ gViewerWindow->setCursor(UI_CURSOR_ARROW);
}
else
{
mDragEndValid = FALSE;
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolSelectLand (active, no land)" << llendl;
- gViewerWindow->getWindow()->setCursor(UI_CURSOR_NO);
+ gViewerWindow->setCursor(UI_CURSOR_NO);
}
mDragEndX = x;
@@ -192,13 +190,13 @@ BOOL LLToolSelectLand::handleHover(S32 x, S32 y, MASK mask)
else
{
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolSelectLand (active, in slop)" << llendl;
- gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
+ gViewerWindow->setCursor(UI_CURSOR_ARROW);
}
}
else
{
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolSelectLand (inactive)" << llendl;
- gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
+ gViewerWindow->setCursor(UI_CURSOR_ARROW);
}
return TRUE;
diff --git a/indra/newview/lltoolselectrect.cpp b/indra/newview/lltoolselectrect.cpp
index d544bff992..f87d1480d7 100644
--- a/indra/newview/lltoolselectrect.cpp
+++ b/indra/newview/lltoolselectrect.cpp
@@ -44,7 +44,6 @@
#include "llviewercontrol.h"
#include "llui.h"
#include "llselectmgr.h"
-#include "lltoolview.h"
#include "lltoolmgr.h"
#include "llviewerobject.h"
#include "llviewerobjectlist.h"
@@ -159,7 +158,7 @@ BOOL LLToolSelectRect::handleHover(S32 x, S32 y, MASK mask)
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolSelectRect (inactive)" << llendl;
}
- gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
+ gViewerWindow->setCursor(UI_CURSOR_ARROW);
return TRUE;
}
diff --git a/indra/newview/lltoolview.cpp b/indra/newview/lltoolview.cpp
index 9f6a77d245..f8393ebc47 100644
--- a/indra/newview/lltoolview.cpp
+++ b/indra/newview/lltoolview.cpp
@@ -65,9 +65,9 @@ LLToolContainer::~LLToolContainer()
LLToolView::LLToolView(const std::string& name, const LLRect& rect)
-: LLView(name, rect, MOUSE_OPAQUE),
- mButtonCount(0)
+: mButtonCount(0)
{
+ LLView::init(LLView::Params().name(name).rect(rect).mouse_opaque(true));
}
diff --git a/indra/newview/lltracker.cpp b/indra/newview/lltracker.cpp
index d54cc798d2..407cc23d0d 100644
--- a/indra/newview/lltracker.cpp
+++ b/indra/newview/lltracker.cpp
@@ -39,7 +39,7 @@
#include "llgl.h"
#include "llrender.h"
#include "llinventory.h"
-#include "llmemory.h"
+#include "llpointer.h"
#include "llstring.h"
#include "lluuid.h"
#include "v3math.h"
@@ -51,11 +51,11 @@
#include "lltracker.h"
#include "llagent.h"
#include "llcallingcard.h"
-#include "llcolorscheme.h"
#include "llfloaterworldmap.h"
#include "llhudtext.h"
#include "llhudview.h"
#include "llinventorymodel.h"
+#include "llinventoryobserver.h"
#include "lllandmarklist.h"
#include "llsky.h"
#include "llui.h"
@@ -113,12 +113,14 @@ void LLTracker::stopTracking(void* userdata)
// static virtual
void LLTracker::drawHUDArrow()
{
+ static LLUIColor map_track_color = LLUIColorTable::instance().getColor("MapTrackColor", LLColor4::white);
+
/* tracking autopilot destination has been disabled
-- 2004.01.09, Leviathan
// Draw dot for autopilot target
if (gAgent.getAutoPilot())
{
- instance()->drawMarker( gAgent.getAutoPilotTargetGlobal(), gTrackColor );
+ instance()->drawMarker( gAgent.getAutoPilotTargetGlobal(), map_track_color );
return;
}
*/
@@ -128,12 +130,12 @@ void LLTracker::drawHUDArrow()
// Tracked avatar
if(LLAvatarTracker::instance().haveTrackingInfo())
{
- instance()->drawMarker( LLAvatarTracker::instance().getGlobalPos(), gTrackColor );
+ instance()->drawMarker( LLAvatarTracker::instance().getGlobalPos(), map_track_color );
}
break;
case TRACKING_LANDMARK:
- instance()->drawMarker( getTrackedPositionGlobal(), gTrackColor );
+ instance()->drawMarker( getTrackedPositionGlobal(), map_track_color );
break;
case TRACKING_LOCATION:
@@ -145,7 +147,7 @@ void LLTracker::drawHUDArrow()
+ 0.1f * (LLWorld::getInstance()->resolveLandHeightGlobal(getTrackedPositionGlobal()) + 1.5f);
#endif
instance()->mTrackedPositionGlobal.mdV[VZ] = llclamp((F32)instance()->mTrackedPositionGlobal.mdV[VZ], LLWorld::getInstance()->resolveLandHeightGlobal(getTrackedPositionGlobal()) + 1.5f, (F32)instance()->getTrackedPositionGlobal().mdV[VZ]);
- instance()->drawMarker( getTrackedPositionGlobal(), gTrackColor );
+ instance()->drawMarker( getTrackedPositionGlobal(), map_track_color );
break;
default:
@@ -161,7 +163,9 @@ void LLTracker::render3D()
{
return;
}
-
+
+ static LLUIColor map_track_color = LLUIColorTable::instance().getColor("MapTrackColor", LLColor4::white);
+
// Arbitary location beacon
if( instance()->mIsTrackingLocation )
{
@@ -181,7 +185,7 @@ void LLTracker::render3D()
}
else
{
- renderBeacon( instance()->mTrackedPositionGlobal, gTrackColor,
+ renderBeacon( instance()->mTrackedPositionGlobal, map_track_color,
instance()->mBeaconText, instance()->mTrackedLocationName );
}
}
@@ -223,7 +227,7 @@ void LLTracker::render3D()
// and back again
instance()->mHasReachedLandmark = FALSE;
}
- renderBeacon( instance()->mTrackedPositionGlobal, gTrackColor,
+ renderBeacon( instance()->mTrackedPositionGlobal, map_track_color,
instance()->mBeaconText, instance()->mTrackedLandmarkName );
}
}
@@ -252,7 +256,7 @@ void LLTracker::render3D()
}
else
{
- renderBeacon( av_tracker.getGlobalPos(), gTrackColor,
+ renderBeacon( av_tracker.getGlobalPos(), map_track_color,
instance()->mBeaconText, av_tracker.getName() );
}
}
@@ -413,10 +417,10 @@ F32 pulse_func(F32 t, F32 z)
return 0.f;
}
- t *= 3.14159f;
+ t *= F_PI;
z -= t*64.f - 256.f;
- F32 a = cosf(z*3.14159/512.f)*10.0f;
+ F32 a = cosf(z*F_PI/512.f)*10.0f;
a = llmax(a, 9.9f);
a -= 9.9f;
a *= 10.f;
@@ -430,7 +434,7 @@ void draw_shockwave(F32 center_z, F32 t, S32 steps, LLColor4 color)
return;
}
- t *= 0.6284f/3.14159f;
+ t *= 0.6284f/F_PI;
t -= (F32) (S32) t;
diff --git a/indra/newview/lltracker.h b/indra/newview/lltracker.h
index 2850365272..bfe9d6c6b5 100644
--- a/indra/newview/lltracker.h
+++ b/indra/newview/lltracker.h
@@ -40,7 +40,7 @@
#define LL_LLTRACKER_H
#include "lldarray.h"
-#include "llmemory.h"
+#include "llpointer.h"
#include "llstring.h"
#include "lluuid.h"
#include "v3dmath.h"
diff --git a/indra/newview/lltransientdockablefloater.cpp b/indra/newview/lltransientdockablefloater.cpp
new file mode 100644
index 0000000000..9d39aa5182
--- /dev/null
+++ b/indra/newview/lltransientdockablefloater.cpp
@@ -0,0 +1,105 @@
+/**
+ * @file lltransientdockablefloater.cpp
+ * @brief Creates a panel of a specific kind for a toast
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lltransientfloatermgr.h"
+#include "lltransientdockablefloater.h"
+#include "llfloaterreg.h"
+
+
+LLTransientDockableFloater::LLTransientDockableFloater(LLDockControl* dockControl, bool uniqueDocking,
+ const LLSD& key, const Params& params) :
+ LLDockableFloater(dockControl, uniqueDocking, key, params)
+{
+ LLTransientFloaterMgr::getInstance()->registerTransientFloater(this);
+ LLTransientFloater::init(this);
+}
+
+LLTransientDockableFloater::~LLTransientDockableFloater()
+{
+ LLTransientFloaterMgr::getInstance()->unregisterTransientFloater(this);
+ LLView* dock = getDockWidget();
+ LLTransientFloaterMgr::getInstance()->removeControlView(
+ LLTransientFloaterMgr::DOCKED, this);
+ if (dock != NULL)
+ {
+ LLTransientFloaterMgr::getInstance()->removeControlView(
+ LLTransientFloaterMgr::DOCKED, dock);
+ }
+}
+
+void LLTransientDockableFloater::setVisible(BOOL visible)
+{
+ LLView* dock = getDockWidget();
+ if(visible && isDocked())
+ {
+ LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::DOCKED, this);
+ if (dock != NULL)
+ {
+ LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::DOCKED, dock);
+ }
+ }
+ else
+ {
+ LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::DOCKED, this);
+ if (dock != NULL)
+ {
+ LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::DOCKED, dock);
+ }
+ }
+
+ LLDockableFloater::setVisible(visible);
+}
+
+void LLTransientDockableFloater::setDocked(bool docked, bool pop_on_undock)
+{
+ LLView* dock = getDockWidget();
+ if(docked)
+ {
+ LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::DOCKED, this);
+ if (dock != NULL)
+ {
+ LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::DOCKED, dock);
+ }
+ }
+ else
+ {
+ LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::DOCKED, this);
+ if (dock != NULL)
+ {
+ LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::DOCKED, dock);
+ }
+ }
+
+ LLDockableFloater::setDocked(docked, pop_on_undock);
+}
diff --git a/indra/newview/lltransientdockablefloater.h b/indra/newview/lltransientdockablefloater.h
new file mode 100644
index 0000000000..e0541d6597
--- /dev/null
+++ b/indra/newview/lltransientdockablefloater.h
@@ -0,0 +1,59 @@
+/**
+ * @file lltransientdockablefloater.h
+ * @brief Creates a panel of a specific kind for a toast.
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_TRANSIENTDOCKABLEFLOATER_H
+#define LL_TRANSIENTDOCKABLEFLOATER_H
+
+#include "llerror.h"
+#include "llfloater.h"
+#include "lldockcontrol.h"
+#include "lldockablefloater.h"
+#include "lltransientfloatermgr.h"
+
+/**
+ * Represents floater that can dock and managed by transient floater manager.
+ * Transient floaters should be hidden if user click anywhere except defined view list.
+ */
+class LLTransientDockableFloater : public LLDockableFloater, LLTransientFloater
+{
+public:
+ LOG_CLASS(LLTransientDockableFloater);
+ LLTransientDockableFloater(LLDockControl* dockControl, bool uniqueDocking,
+ const LLSD& key, const Params& params = getDefaultParams());
+ virtual ~LLTransientDockableFloater();
+
+ /*virtual*/ void setVisible(BOOL visible);
+ /* virtual */void setDocked(bool docked, bool pop_on_undock = true);
+ virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::GLOBAL; }
+};
+
+#endif /* LL_TRANSIENTDOCKABLEFLOATER_H */
diff --git a/indra/newview/lltransientfloatermgr.cpp b/indra/newview/lltransientfloatermgr.cpp
new file mode 100644
index 0000000000..d82403070b
--- /dev/null
+++ b/indra/newview/lltransientfloatermgr.cpp
@@ -0,0 +1,149 @@
+/**
+ * @file lltransientfloatermgr.cpp
+ * @brief LLFocusMgr base class
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lltransientfloatermgr.h"
+#include "llfocusmgr.h"
+#include "llrootview.h"
+#include "llviewerwindow.h"
+#include "lldockablefloater.h"
+#include "llmenugl.h"
+
+
+LLTransientFloaterMgr::LLTransientFloaterMgr()
+{
+ gViewerWindow->getRootView()->addMouseDownCallback(boost::bind(
+ &LLTransientFloaterMgr::leftMouseClickCallback, this, _1, _2, _3));
+
+ mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(GLOBAL, std::set<LLView*>()));
+ mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(DOCKED, std::set<LLView*>()));
+ mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(IM, std::set<LLView*>()));
+}
+
+void LLTransientFloaterMgr::registerTransientFloater(LLTransientFloater* floater)
+{
+ mTransSet.insert(floater);
+}
+
+void LLTransientFloaterMgr::unregisterTransientFloater(LLTransientFloater* floater)
+{
+ mTransSet.erase(floater);
+}
+
+void LLTransientFloaterMgr::addControlView(ETransientGroup group, LLView* view)
+{
+ mGroupControls.find(group)->second.insert(view);
+}
+
+void LLTransientFloaterMgr::removeControlView(ETransientGroup group, LLView* view)
+{
+ mGroupControls.find(group)->second.erase(view);
+}
+
+void LLTransientFloaterMgr::addControlView(LLView* view)
+{
+ addControlView(GLOBAL, view);
+}
+
+void LLTransientFloaterMgr::removeControlView(LLView* view)
+{
+ // we will still get focus lost callbacks on this view, but that's ok
+ // since we run sanity checking logic every time
+ removeControlView(GLOBAL, view);
+}
+
+void LLTransientFloaterMgr::hideTransientFloaters(S32 x, S32 y)
+{
+ for (std::set<LLTransientFloater*>::iterator it = mTransSet.begin(); it
+ != mTransSet.end(); it++)
+ {
+ LLTransientFloater* floater = *it;
+ if (floater->isTransientDocked())
+ {
+ ETransientGroup group = floater->getGroup();
+
+ bool hide = isControlClicked(mGroupControls.find(group)->second, x, y);
+ if (hide)
+ {
+ floater->setTransientVisible(FALSE);
+ }
+ }
+ }
+}
+
+bool LLTransientFloaterMgr::isControlClicked(std::set<LLView*>& set, S32 x, S32 y)
+{
+ bool res = true;
+ for (controls_set_t::iterator it = set.begin(); it
+ != set.end(); it++)
+ {
+ LLView* control_view = *it;
+ if (!control_view->getVisible())
+ {
+ continue;
+ }
+
+ LLRect rect = control_view->calcScreenRect();
+ // if click inside view rect
+ if (rect.pointInRect(x, y))
+ {
+ res = false;
+ break;
+ }
+ }
+ return res;
+}
+
+void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y,
+ MASK mask)
+{
+ // don't hide transient floater if any context menu opened
+ if (LLMenuGL::sMenuContainer->getVisibleMenu() != NULL)
+ {
+ return;
+ }
+
+ bool hide = isControlClicked(mGroupControls.find(DOCKED)->second, x, y)
+ && isControlClicked(mGroupControls.find(GLOBAL)->second, x, y);
+ if (hide)
+ {
+ hideTransientFloaters(x, y);
+ }
+}
+
+void LLTransientFloater::init(LLFloater* thiz)
+{
+ // used since LLTransientFloater(this) can't be used in descendant constructor parameter initialization.
+ mFloater = thiz;
+}
+
diff --git a/indra/newview/lltransientfloatermgr.h b/indra/newview/lltransientfloatermgr.h
new file mode 100644
index 0000000000..9c5ae295f2
--- /dev/null
+++ b/indra/newview/lltransientfloatermgr.h
@@ -0,0 +1,96 @@
+/**
+ * @file lltransientfloatermgr.h
+ * @brief LLFocusMgr base class
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTRANSIENTFLOATERMGR_H
+#define LL_LLTRANSIENTFLOATERMGR_H
+
+#include "llui.h"
+#include "llsingleton.h"
+#include "llfloater.h"
+
+class LLTransientFloater;
+
+/**
+ * Provides functionality to hide transient floaters.
+ */
+class LLTransientFloaterMgr: public LLSingleton<LLTransientFloaterMgr>
+{
+protected:
+ LLTransientFloaterMgr();
+ friend class LLSingleton<LLTransientFloaterMgr>;
+
+public:
+ enum ETransientGroup
+ {
+ GLOBAL, DOCKED, IM
+ };
+
+ void registerTransientFloater(LLTransientFloater* floater);
+ void unregisterTransientFloater(LLTransientFloater* floater);
+ void addControlView(ETransientGroup group, LLView* view);
+ void removeControlView(ETransientGroup group, LLView* view);
+ void addControlView(LLView* view);
+ void removeControlView(LLView* view);
+
+private:
+ void hideTransientFloaters(S32 x, S32 y);
+ void leftMouseClickCallback(S32 x, S32 y, MASK mask);
+ bool isControlClicked(std::set<LLView*>& set, S32 x, S32 y);
+private:
+ std::set<LLTransientFloater*> mTransSet;
+
+ typedef std::set<LLView*> controls_set_t;
+ typedef std::map<ETransientGroup, std::set<LLView*> > group_controls_t;
+ group_controls_t mGroupControls;
+};
+
+/**
+ * An abstract class declares transient floater interfaces.
+ */
+class LLTransientFloater
+{
+protected:
+ /**
+ * Class initialization method.
+ * Should be called from descendant constructor.
+ */
+ void init(LLFloater* thiz);
+public:
+ virtual LLTransientFloaterMgr::ETransientGroup getGroup() = 0;
+ bool isTransientDocked() { return mFloater->isDocked(); };
+ void setTransientVisible(BOOL visible) {mFloater->setVisible(visible); }
+
+private:
+ LLFloater* mFloater;
+};
+
+#endif // LL_LLTRANSIENTFLOATERMGR_H
diff --git a/indra/newview/lluilistener.cpp b/indra/newview/lluilistener.cpp
new file mode 100644
index 0000000000..3ad9887bec
--- /dev/null
+++ b/indra/newview/lluilistener.cpp
@@ -0,0 +1,56 @@
+/**
+ * @file lluilistener.cpp
+ * @author Nat Goodspeed
+ * @date 2009-08-18
+ * @brief Implementation for lluilistener.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "llviewerprecompiledheaders.h"
+// associated header
+#include "lluilistener.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "lluictrl.h"
+#include "llerror.h"
+
+LLUIListener::LLUIListener():
+ LLEventAPI("UI",
+ "LLUICtrl::CommitCallbackRegistry listener.\n"
+ "Capable of invoking any function (with parameter) you can specify in XUI.")
+{
+ add("call",
+ "Invoke the operation named by [\"function\"], passing [\"parameter\"],\n"
+ "as if from a user gesture on a menu -- or a button click.",
+ &LLUIListener::call,
+ LLSD().with("function", LLSD()));
+}
+
+void LLUIListener::call(const LLSD& event) const
+{
+ LLUICtrl::commit_callback_t* func =
+ LLUICtrl::CommitCallbackRegistry::getValue(event["function"]);
+ if (! func)
+ {
+ // This API is intended for use by a script. It's a fire-and-forget
+ // API: we provide no reply. Therefore, a typo in the script will
+ // provide no feedback whatsoever to that script. To rub the coder's
+ // nose in such an error, crump rather than quietly ignoring it.
+ LL_ERRS("LLUIListener") << "function '" << event["function"] << "' not found" << LL_ENDL;
+ }
+ else
+ {
+ // Interestingly, view_listener_t::addMenu() (addCommit(),
+ // addEnable()) constructs a commit_callback_t callable that accepts
+ // two parameters but discards the first. Only the second is passed to
+ // handleEvent(). Therefore we feel completely safe passing NULL for
+ // the first parameter.
+ (*func)(NULL, event["parameter"]);
+ }
+}
diff --git a/indra/newview/lluilistener.h b/indra/newview/lluilistener.h
new file mode 100644
index 0000000000..8605d60bd3
--- /dev/null
+++ b/indra/newview/lluilistener.h
@@ -0,0 +1,29 @@
+/**
+ * @file lluilistener.h
+ * @author Nat Goodspeed
+ * @date 2009-08-18
+ * @brief Engage named functions as specified by XUI
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLUILISTENER_H)
+#define LL_LLUILISTENER_H
+
+#include "lleventapi.h"
+#include <string>
+
+class LLSD;
+
+class LLUIListener: public LLEventAPI
+{
+public:
+ LLUIListener();
+
+private:
+ void call(const LLSD& event) const;
+};
+
+#endif /* ! defined(LL_LLUILISTENER_H) */
diff --git a/indra/newview/lluploaddialog.cpp b/indra/newview/lluploaddialog.cpp
index 7f63972c8d..577b5952e5 100644
--- a/indra/newview/lluploaddialog.cpp
+++ b/indra/newview/lluploaddialog.cpp
@@ -41,6 +41,7 @@
#include "llkeyboard.h"
#include "llfocusmgr.h"
#include "llviewercontrol.h"
+#include "llrootview.h"
// static
LLUploadDialog* LLUploadDialog::sDialog = NULL;
@@ -64,8 +65,7 @@ void LLUploadDialog::modalUploadFinished()
// Private methods
LLUploadDialog::LLUploadDialog( const std::string& msg)
- :
- LLPanel( std::string("Uploading..."), LLRect(0,100,100,0) ) // dummy rect. Will reshape below.
+ : LLPanel()
{
setBackgroundVisible( TRUE );
@@ -75,11 +75,16 @@ LLUploadDialog::LLUploadDialog( const std::string& msg)
}
LLUploadDialog::sDialog = this;
- const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF );
+ const LLFontGL* font = LLFontGL::getFontSansSerif();
LLRect msg_rect;
for (int line_num=0; line_num<16; ++line_num)
{
- mLabelBox[line_num] = new LLTextBox( std::string("Filename"), msg_rect, std::string("Filename"), font );
+ LLTextBox::Params params;
+ params.name("Filename");
+ params.rect(msg_rect);
+ params.initial_value("Filename");
+ params.font(font);
+ mLabelBox[line_num] = LLUICtrlFactory::create<LLTextBox> (params);
addChild(mLabelBox[line_num]);
}
@@ -91,7 +96,7 @@ LLUploadDialog::LLUploadDialog( const std::string& msg)
void LLUploadDialog::setMessage( const std::string& msg)
{
- const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF );
+ const LLFontGL* font = LLFontGL::getFontSansSerif();
const S32 VPAD = 16;
const S32 HPAD = 25;
@@ -139,7 +144,7 @@ void LLUploadDialog::setMessage( const std::string& msg)
msg_rect.setOriginAndSize( msg_x, msg_y, max_msg_width, line_height );
mLabelBox[line_num]->setRect(msg_rect);
mLabelBox[line_num]->setText(cur_line);
- mLabelBox[line_num]->setColor( gColors.getColor( "LabelTextColor" ) );
+ mLabelBox[line_num]->setColor( LLUIColorTable::instance().getColor( "LabelTextColor" ) );
mLabelBox[line_num]->setVisible(TRUE);
msg_y -= line_height;
++line_num;
diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp
index 85ab44bc13..0b6bd4b401 100644
--- a/indra/newview/llurldispatcher.cpp
+++ b/indra/newview/llurldispatcher.cpp
@@ -36,36 +36,31 @@
// viewer includes
#include "llagent.h" // teleportViaLocation()
#include "llcommandhandler.h"
+#include "llfloaterhelpbrowser.h"
+#include "llfloaterreg.h"
#include "llfloaterurldisplay.h"
-#include "llfloaterdirectory.h"
-#include "llfloaterhtml.h"
#include "llfloaterworldmap.h"
-#include "llfloaterhtmlhelp.h"
#include "llpanellogin.h"
+#include "llregionhandle.h"
+#include "llsidetray.h"
+#include "llslurl.h"
#include "llstartup.h" // gStartupState
#include "llurlsimstring.h"
#include "llweb.h"
-#include "llworldmap.h"
+#include "llworldmapmessage.h"
+#include "llurldispatcherlistener.h"
// library includes
+#include "llnotificationsutil.h"
#include "llsd.h"
-const std::string SLURL_SL_HELP_PREFIX = "secondlife://app.";
-const std::string SLURL_SL_PREFIX = "sl://";
-const std::string SLURL_SECONDLIFE_PREFIX = "secondlife://";
-const std::string SLURL_SLURL_PREFIX = "http://slurl.com/secondlife/";
-
-const std::string SLURL_APP_TOKEN = "app/";
+static LLURLDispatcherListener sURLDispatcherListener;
class LLURLDispatcherImpl
{
public:
- static bool isSLURL(const std::string& url);
-
- static bool isSLURLCommand(const std::string& url);
-
static bool dispatch(const std::string& url,
- LLWebBrowserCtrl* web,
+ LLMediaCtrl* web,
bool trusted_browser);
// returns true if handled or explicitly blocked.
@@ -74,7 +69,7 @@ public:
private:
static bool dispatchCore(const std::string& url,
bool right_mouse,
- LLWebBrowserCtrl* web,
+ LLMediaCtrl* web,
bool trusted_browser);
// handles both left and right click
@@ -84,7 +79,7 @@ private:
static bool dispatchApp(const std::string& url,
bool right_mouse,
- LLWebBrowserCtrl* web,
+ LLMediaCtrl* web,
bool trusted_browser);
// Handles secondlife:///app/agent/<agent_id>/about and similar
// by showing panel in Search floater.
@@ -104,43 +99,17 @@ private:
// Called by LLWorldMap when a region name has been resolved to a
// location in-world, used by places-panel display.
- static bool matchPrefix(const std::string& url, const std::string& prefix);
-
- static std::string stripProtocol(const std::string& url);
-
friend class LLTeleportHandler;
};
// static
-bool LLURLDispatcherImpl::isSLURL(const std::string& url)
-{
- if (matchPrefix(url, SLURL_SL_HELP_PREFIX)) return true;
- if (matchPrefix(url, SLURL_SL_PREFIX)) return true;
- if (matchPrefix(url, SLURL_SECONDLIFE_PREFIX)) return true;
- if (matchPrefix(url, SLURL_SLURL_PREFIX)) return true;
- return false;
-}
-
-// static
-bool LLURLDispatcherImpl::isSLURLCommand(const std::string& url)
-{
- if (matchPrefix(url, SLURL_SL_PREFIX + SLURL_APP_TOKEN)
- || matchPrefix(url, SLURL_SECONDLIFE_PREFIX + "/" + SLURL_APP_TOKEN)
- || matchPrefix(url, SLURL_SLURL_PREFIX + SLURL_APP_TOKEN) )
- {
- return true;
- }
- return false;
-}
-
-// static
bool LLURLDispatcherImpl::dispatchCore(const std::string& url,
bool right_mouse,
- LLWebBrowserCtrl* web,
+ LLMediaCtrl* web,
bool trusted_browser)
{
if (url.empty()) return false;
- if (dispatchHelp(url, right_mouse)) return true;
+ //if (dispatchHelp(url, right_mouse)) return true;
if (dispatchApp(url, right_mouse, web, trusted_browser)) return true;
if (dispatchRegion(url, right_mouse)) return true;
@@ -156,7 +125,7 @@ bool LLURLDispatcherImpl::dispatchCore(const std::string& url,
// static
bool LLURLDispatcherImpl::dispatch(const std::string& url,
- LLWebBrowserCtrl* web,
+ LLMediaCtrl* web,
bool trusted_browser)
{
llinfos << "url: " << url << llendl;
@@ -169,31 +138,19 @@ bool LLURLDispatcherImpl::dispatchRightClick(const std::string& url)
{
llinfos << "url: " << url << llendl;
const bool right_click = true;
- LLWebBrowserCtrl* web = NULL;
+ LLMediaCtrl* web = NULL;
const bool trusted_browser = false;
return dispatchCore(url, right_click, web, trusted_browser);
}
// static
-bool LLURLDispatcherImpl::dispatchHelp(const std::string& url, bool right_mouse)
-{
-#if LL_LIBXUL_ENABLED
- if (matchPrefix(url, SLURL_SL_HELP_PREFIX))
- {
- gViewerHtmlHelp.show();
- return true;
- }
-#endif
- return false;
-}
-
-// static
bool LLURLDispatcherImpl::dispatchApp(const std::string& url,
bool right_mouse,
- LLWebBrowserCtrl* web,
+ LLMediaCtrl* web,
bool trusted_browser)
{
- if (!isSLURL(url))
+ // ensure the URL is in the secondlife:///app/ format
+ if (!LLSLURL::isSLURLCommand(url))
{
return false;
}
@@ -205,13 +162,20 @@ bool LLURLDispatcherImpl::dispatchApp(const std::string& url,
pathArray.erase(0); // erase "cmd"
bool handled = LLCommandDispatcher::dispatch(
cmd, pathArray, uri.queryMap(), web, trusted_browser);
- return handled;
+
+ // alert if we didn't handle this secondlife:///app/ SLURL
+ // (but still return true because it is a valid app SLURL)
+ if (! handled)
+ {
+ LLNotificationsUtil::add("UnsupportedCommandSLURL");
+ }
+ return true;
}
// static
bool LLURLDispatcherImpl::dispatchRegion(const std::string& url, bool right_mouse)
{
- if (!isSLURL(url))
+ if (!LLSLURL::isSLURL(url))
{
return false;
}
@@ -230,18 +194,19 @@ bool LLURLDispatcherImpl::dispatchRegion(const std::string& url, bool right_mous
return true;
}
- std::string sim_string = stripProtocol(url);
+ std::string sim_string = LLSLURL::stripProtocol(url);
std::string region_name;
S32 x = 128;
S32 y = 128;
S32 z = 0;
LLURLSimString::parse(sim_string, &region_name, &x, &y, &z);
- LLFloaterURLDisplay* url_displayp = LLFloaterURLDisplay::getInstance(LLSD());
- url_displayp->setName(region_name);
+ // LLFloaterURLDisplay functionality moved to LLPanelPlaces in Side Tray.
+ //LLFloaterURLDisplay* url_displayp = LLFloaterReg::getTypedInstance<LLFloaterURLDisplay>("preview_url",LLSD());
+ //if(url_displayp) url_displayp->setName(region_name);
// Request a region handle by name
- LLWorldMap::getInstance()->sendNamedRegionRequest(region_name,
+ LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name,
LLURLDispatcherImpl::regionNameCallback,
url,
false); // don't teleport
@@ -251,7 +216,7 @@ bool LLURLDispatcherImpl::dispatchRegion(const std::string& url, bool right_mous
/*static*/
void LLURLDispatcherImpl::regionNameCallback(U64 region_handle, const std::string& url, const LLUUID& snapshot_id, bool teleport)
{
- std::string sim_string = stripProtocol(url);
+ std::string sim_string = LLSLURL::stripProtocol(url);
std::string region_name;
S32 x = 128;
S32 y = 128;
@@ -280,7 +245,7 @@ void LLURLDispatcherImpl::regionNameCallback(U64 region_handle, const std::strin
LLVector3d global_pos = from_region_handle(region_handle) + LLVector3d(local_pos);
U64 new_region_handle = to_region_handle(global_pos);
- LLWorldMap::getInstance()->sendHandleRegionRequest(new_region_handle,
+ LLWorldMapMessage::getInstance()->sendHandleRegionRequest(new_region_handle,
LLURLDispatcherImpl::regionHandleCallback,
url, teleport);
}
@@ -289,7 +254,7 @@ void LLURLDispatcherImpl::regionNameCallback(U64 region_handle, const std::strin
/* static */
void LLURLDispatcherImpl::regionHandleCallback(U64 region_handle, const std::string& url, const LLUUID& snapshot_id, bool teleport)
{
- std::string sim_string = stripProtocol(url);
+ std::string sim_string = LLSLURL::stripProtocol(url);
std::string region_name;
S32 x = 128;
S32 y = 128;
@@ -309,65 +274,45 @@ void LLURLDispatcherImpl::regionHandleCallback(U64 region_handle, const std::str
local_pos.mV[VY] = (F32)local_y;
local_pos.mV[VZ] = (F32)z;
-
+ LLVector3d global_pos = from_region_handle(region_handle);
+ global_pos += LLVector3d(local_pos);
if (teleport)
- {
- LLVector3d global_pos = from_region_handle(region_handle);
- global_pos += LLVector3d(local_pos);
+ {
gAgent.teleportViaLocation(global_pos);
- if(gFloaterWorldMap)
+ LLFloaterWorldMap* instance = LLFloaterWorldMap::getInstance();
+ if(instance)
{
- gFloaterWorldMap->trackLocation(global_pos);
+ instance->trackLocation(global_pos);
}
}
else
{
- // display informational floater, allow user to click teleport btn
- LLFloaterURLDisplay* url_displayp = LLFloaterURLDisplay::getInstance(LLSD());
-
-
- url_displayp->displayParcelInfo(region_handle, local_pos);
- if(snapshot_id.notNull())
- {
- url_displayp->setSnapshotDisplay(snapshot_id);
- }
- std::string locationString = llformat("%s %d, %d, %d", region_name.c_str(), x, y, z);
- url_displayp->setLocationString(locationString);
+ LLSD key;
+ key["type"] = "remote_place";
+ key["x"] = global_pos.mdV[VX];
+ key["y"] = global_pos.mdV[VY];
+ key["z"] = global_pos.mdV[VZ];
+
+ LLSideTray::getInstance()->showPanel("panel_places", key);
+
+ // LLFloaterURLDisplay functionality moved to LLPanelPlaces in Side Tray.
+
+// // display informational floater, allow user to click teleport btn
+// LLFloaterURLDisplay* url_displayp = LLFloaterReg::getTypedInstance<LLFloaterURLDisplay>("preview_url",LLSD());
+// if(url_displayp)
+// {
+// url_displayp->displayParcelInfo(region_handle, local_pos);
+// if(snapshot_id.notNull())
+// {
+// url_displayp->setSnapshotDisplay(snapshot_id);
+// }
+// std::string locationString = llformat("%s %d, %d, %d", region_name.c_str(), x, y, z);
+// url_displayp->setLocationString(locationString);
+// }
}
}
-// static
-bool LLURLDispatcherImpl::matchPrefix(const std::string& url, const std::string& prefix)
-{
- std::string test_prefix = url.substr(0, prefix.length());
- LLStringUtil::toLower(test_prefix);
- return test_prefix == prefix;
-}
-
-// static
-std::string LLURLDispatcherImpl::stripProtocol(const std::string& url)
-{
- std::string stripped = url;
- if (matchPrefix(stripped, SLURL_SL_HELP_PREFIX))
- {
- stripped.erase(0, SLURL_SL_HELP_PREFIX.length());
- }
- else if (matchPrefix(stripped, SLURL_SL_PREFIX))
- {
- stripped.erase(0, SLURL_SL_PREFIX.length());
- }
- else if (matchPrefix(stripped, SLURL_SECONDLIFE_PREFIX))
- {
- stripped.erase(0, SLURL_SECONDLIFE_PREFIX.length());
- }
- else if (matchPrefix(stripped, SLURL_SLURL_PREFIX))
- {
- stripped.erase(0, SLURL_SLURL_PREFIX.length());
- }
- return stripped;
-}
-
//---------------------------------------------------------------------------
// Teleportation links are handled here because they are tightly coupled
// to URL parsing and sim-fragment parsing
@@ -377,10 +322,10 @@ public:
// Teleport requests *must* come from a trusted browser
// inside the app, otherwise a malicious web page could
// cause a constant teleport loop. JC
- LLTeleportHandler() : LLCommandHandler("teleport", true) { }
+ LLTeleportHandler() : LLCommandHandler("teleport", UNTRUSTED_BLOCK) { }
bool handle(const LLSD& tokens, const LLSD& query_map,
- LLWebBrowserCtrl* web)
+ LLMediaCtrl* web)
{
// construct a "normal" SLURL, resolve the region to
// a global position, and teleport to it
@@ -390,12 +335,12 @@ public:
std::string region_name = LLURLSimString::unescapeRegionName(tokens[0]);
// build secondlife://De%20Haro/123/45/67 for use in callback
- std::string url = SLURL_SECONDLIFE_PREFIX;
+ std::string url = LLSLURL::PREFIX_SECONDLIFE;
for (int i = 0; i < tokens.size(); ++i)
{
url += tokens[i].asString() + "/";
}
- LLWorldMap::getInstance()->sendNamedRegionRequest(region_name,
+ LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name,
LLURLDispatcherImpl::regionHandleCallback,
url,
true); // teleport
@@ -407,20 +352,8 @@ LLTeleportHandler gTeleportHandler;
//---------------------------------------------------------------------------
// static
-bool LLURLDispatcher::isSLURL(const std::string& url)
-{
- return LLURLDispatcherImpl::isSLURL(url);
-}
-
-// static
-bool LLURLDispatcher::isSLURLCommand(const std::string& url)
-{
- return LLURLDispatcherImpl::isSLURLCommand(url);
-}
-
-// static
bool LLURLDispatcher::dispatch(const std::string& url,
- LLWebBrowserCtrl* web,
+ LLMediaCtrl* web,
bool trusted_browser)
{
return LLURLDispatcherImpl::dispatch(url, web, trusted_browser);
@@ -436,21 +369,12 @@ bool LLURLDispatcher::dispatchRightClick(const std::string& url)
bool LLURLDispatcher::dispatchFromTextEditor(const std::string& url)
{
// *NOTE: Text editors are considered sources of trusted URLs
- // in order to make objectim and avatar profile links in chat
- // history work. While a malicious resident could chat an app
- // SLURL, the receiving resident will see it and must affirmatively
+ // in order to make avatar profile links in chat history work.
+ // While a malicious resident could chat an app SLURL, the
+ // receiving resident will see it and must affirmatively
// click on it.
// *TODO: Make this trust model more refined. JC
const bool trusted_browser = true;
- LLWebBrowserCtrl* web = NULL;
+ LLMediaCtrl* web = NULL;
return LLURLDispatcherImpl::dispatch(url, web, trusted_browser);
}
-
-// static
-std::string LLURLDispatcher::buildSLURL(const std::string& regionname,
- S32 x, S32 y, S32 z)
-{
- std::string slurl = SLURL_SLURL_PREFIX + regionname + llformat("/%d/%d/%d",x,y,z);
- slurl = LLWeb::escapeURL( slurl );
- return slurl;
-}
diff --git a/indra/newview/llurldispatcher.h b/indra/newview/llurldispatcher.h
index a4f6866a07..ff8a351253 100644
--- a/indra/newview/llurldispatcher.h
+++ b/indra/newview/llurldispatcher.h
@@ -32,20 +32,14 @@
#ifndef LLURLDISPATCHER_H
#define LLURLDISPATCHER_H
-class LLWebBrowserCtrl;
+class LLMediaCtrl;
class LLURLDispatcher
{
public:
- static bool isSLURL(const std::string& url);
- // Is this any sort of secondlife:// or sl:// URL?
-
- static bool isSLURLCommand(const std::string& url);
- // Is this a special secondlife://app/ URL?
-
static bool dispatch(const std::string& url,
- LLWebBrowserCtrl* web,
+ LLMediaCtrl* web,
bool trusted_browser);
// At startup time and on clicks in internal web browsers,
// teleport, open map, or run requested command.
@@ -54,7 +48,7 @@ public:
// secondlife:///app/agent/3d6181b0-6a4b-97ef-18d8-722652995cf1/show
// sl://app/foo/bar
// @param web
- // Pointer to LLWebBrowserCtrl sending URL, can be NULL
+ // Pointer to LLMediaCtrl sending URL, can be NULL
// @param trusted_browser
// True if coming inside the app AND from a brower instance
// that navigates to trusted (Linden Lab) pages.
@@ -63,9 +57,6 @@ public:
static bool dispatchRightClick(const std::string& url);
static bool dispatchFromTextEditor(const std::string& url);
-
- static std::string buildSLURL(const std::string& regionname, S32 x, S32 y, S32 z);
- // builds: http://slurl.com/secondlife/RegionName/x/y/z/
};
#endif
diff --git a/indra/newview/llurldispatcherlistener.cpp b/indra/newview/llurldispatcherlistener.cpp
new file mode 100644
index 0000000000..fea6a769c5
--- /dev/null
+++ b/indra/newview/llurldispatcherlistener.cpp
@@ -0,0 +1,58 @@
+/**
+ * @file llurldispatcherlistener.cpp
+ * @author Nat Goodspeed
+ * @date 2009-12-10
+ * @brief Implementation for llurldispatcherlistener.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "llviewerprecompiledheaders.h"
+// associated header
+#include "llurldispatcherlistener.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llurldispatcher.h"
+
+LLURLDispatcherListener::LLURLDispatcherListener(/* LLURLDispatcher* instance */):
+ LLEventAPI("LLURLDispatcher", "Internal URL handling") /* ,
+ mDispatcher(instance) */
+{
+ add("dispatch",
+ "At startup time or on clicks in internal web browsers,\n"
+ "teleport, open map, or run requested command.\n"
+ "[\"url\"] string url to dispatch\n"
+ "[\"trusted\"] boolean indicating trusted browser [default true]",
+ &LLURLDispatcherListener::dispatch);
+ add("dispatchRightClick", "Dispatch [\"url\"] as if from a right-click on a hot link.",
+ &LLURLDispatcherListener::dispatchRightClick);
+ add("dispatchFromTextEditor", "Dispatch [\"url\"] as if from an edit field.",
+ &LLURLDispatcherListener::dispatchFromTextEditor);
+}
+
+void LLURLDispatcherListener::dispatch(const LLSD& params) const
+{
+ // For most purposes, we expect callers to want to be trusted.
+ bool trusted_browser = true;
+ if (params.has("trusted"))
+ {
+ // But for testing, allow a caller to specify untrusted.
+ trusted_browser = params["trusted"].asBoolean();
+ }
+ LLURLDispatcher::dispatch(params["url"], NULL, trusted_browser);
+}
+
+void LLURLDispatcherListener::dispatchRightClick(const LLSD& params) const
+{
+ LLURLDispatcher::dispatchRightClick(params["url"]);
+}
+
+void LLURLDispatcherListener::dispatchFromTextEditor(const LLSD& params) const
+{
+ LLURLDispatcher::dispatchFromTextEditor(params["url"]);
+}
diff --git a/indra/newview/llurldispatcherlistener.h b/indra/newview/llurldispatcherlistener.h
new file mode 100644
index 0000000000..894afcbb51
--- /dev/null
+++ b/indra/newview/llurldispatcherlistener.h
@@ -0,0 +1,32 @@
+/**
+ * @file llurldispatcherlistener.h
+ * @author Nat Goodspeed
+ * @date 2009-12-10
+ * @brief LLEventAPI for LLURLDispatcher
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLURLDISPATCHERLISTENER_H)
+#define LL_LLURLDISPATCHERLISTENER_H
+
+#include "lleventapi.h"
+class LLURLDispatcher;
+class LLSD;
+
+class LLURLDispatcherListener: public LLEventAPI
+{
+public:
+ LLURLDispatcherListener(/* LLURLDispatcher* instance */); // all static members
+
+private:
+ void dispatch(const LLSD& params) const;
+ void dispatchRightClick(const LLSD& params) const;
+ void dispatchFromTextEditor(const LLSD& params) const;
+
+ //LLURLDispatcher* mDispatcher;
+};
+
+#endif /* ! defined(LL_LLURLDISPATCHERLISTENER_H) */
diff --git a/indra/newview/llurlhistory.cpp b/indra/newview/llurlhistory.cpp
index e8b5aa7c74..08dd82ab86 100644
--- a/indra/newview/llurlhistory.cpp
+++ b/indra/newview/llurlhistory.cpp
@@ -77,7 +77,7 @@ bool LLURLHistory::saveFile(const std::string& filename)
std::string temp_str = gDirUtilp->getLindenUserDir();
if( temp_str.empty() )
{
- llwarns << "Can't save. No user directory set." << llendl;
+ llinfos << "Can't save URL history - no user directory set yet." << llendl;
return false;
}
diff --git a/indra/newview/llurllineeditorctrl.cpp b/indra/newview/llurllineeditorctrl.cpp
new file mode 100644
index 0000000000..258c3ddd75
--- /dev/null
+++ b/indra/newview/llurllineeditorctrl.cpp
@@ -0,0 +1,103 @@
+/**
+ * @file llurllineeditorctrl.cpp
+ * @brief LLURLLineEditor base class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llclipboard.h"
+#include "lluictrlfactory.h"
+
+#include "llurllineeditorctrl.h"
+
+#include "llweb.h"
+#include "llslurl.h"
+
+//Constructor
+LLURLLineEditor::LLURLLineEditor(const LLLineEditor::Params& p)
+: LLLineEditor(p){
+
+}
+
+// copy selection to clipboard
+void LLURLLineEditor::copy()
+{
+ if( canCopy() )
+ {
+ copyEscapedURLToClipboard();
+ }
+}
+
+// cut selection to clipboard
+void LLURLLineEditor::cut()
+{
+ if( canCut() )
+ {
+ // Prepare for possible rollback
+ LLURLLineEditorRollback rollback( this );
+
+ copyEscapedURLToClipboard();
+
+ deleteSelection();
+
+ // Validate new string and rollback the if needed.
+ BOOL need_to_rollback = ( mPrevalidateFunc && !mPrevalidateFunc( mText.getWString() ) );
+ if( need_to_rollback )
+ {
+ rollback.doRollback( this );
+ reportBadKeystroke();
+ }
+ else
+ if( mKeystrokeCallback )
+ {
+ mKeystrokeCallback( this );
+ }
+ }
+}
+// Copies escaped URL to clipboard
+void LLURLLineEditor::copyEscapedURLToClipboard()
+{
+ S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
+ S32 length = llabs( mSelectionStart - mSelectionEnd );
+
+ const std::string unescaped_text = wstring_to_utf8str(mText.getWString().substr(left_pos, length));
+ LLWString text_to_copy;
+ if (LLSLURL::isSLURL(unescaped_text))
+ text_to_copy = utf8str_to_wstring(LLWeb::escapeURL(unescaped_text));
+ else
+ text_to_copy = utf8str_to_wstring(unescaped_text);
+
+ gClipboard.copyFromString( text_to_copy );
+}
+// Makes UISndBadKeystroke sound
+void LLURLLineEditor::reportBadKeystroke()
+{
+ make_ui_sound("UISndBadKeystroke");
+}
diff --git a/indra/newview/llurllineeditorctrl.h b/indra/newview/llurllineeditorctrl.h
new file mode 100644
index 0000000000..618f29dfbf
--- /dev/null
+++ b/indra/newview/llurllineeditorctrl.h
@@ -0,0 +1,100 @@
+/**
+ * @file llurllineeditorctrl.h
+ * @brief Combobox-like location input control
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLURLLINEEDITOR_H_
+#define LLURLLINEEDITOR_H_
+
+#include "linden_common.h"
+
+#include "lllineeditor.h"
+#include "lluictrl.h"
+
+// LLURLLineEditor class performing escaping of an URL while copying or cutting the target text
+class LLURLLineEditor: public LLLineEditor {
+ LOG_CLASS( LLURLLineEditor);
+
+public:
+ // LLLineEditor overrides to do necessary escaping
+ /*virtual*/ void copy();
+ /*virtual*/ void cut();
+
+protected:
+ LLURLLineEditor(const Params&);
+ friend class LLUICtrlFactory;
+ friend class LLFloaterEditUI;
+
+private:
+ // util function to escape selected text and copy it to clipboard
+ void copyEscapedURLToClipboard();
+ // send a beep signal if keystroke is bad. As it is private at LLLineEditor we need own function
+ void reportBadKeystroke();
+
+ // Helper class to do rollback if needed
+ class LLURLLineEditorRollback
+ {
+ public:
+ LLURLLineEditorRollback( LLURLLineEditor* ed )
+ :
+ mCursorPos( ed->mCursorPos ),
+ mScrollHPos( ed->mScrollHPos ),
+ mIsSelecting( ed->mIsSelecting ),
+ mSelectionStart( ed->mSelectionStart ),
+ mSelectionEnd( ed->mSelectionEnd )
+ {
+ mText = ed->getText();
+ }
+
+ void doRollback( LLURLLineEditor* ed )
+ {
+ ed->mCursorPos = mCursorPos;
+ ed->mScrollHPos = mScrollHPos;
+ ed->mIsSelecting = mIsSelecting;
+ ed->mSelectionStart = mSelectionStart;
+ ed->mSelectionEnd = mSelectionEnd;
+ ed->mText = mText;
+ ed->mPrevText = mText;
+ }
+
+ std::string getText() { return mText; }
+
+ private:
+ std::string mText;
+ S32 mCursorPos;
+ S32 mScrollHPos;
+ BOOL mIsSelecting;
+ S32 mSelectionStart;
+ S32 mSelectionEnd;
+ }; // end class LLURLLineEditorRollback
+
+};
+
+#endif /* LLURLLINEEDITOR_H_ */
diff --git a/indra/newview/llurlwhitelist.cpp b/indra/newview/llurlwhitelist.cpp
index da69039cf9..46bc9276c1 100644
--- a/indra/newview/llurlwhitelist.cpp
+++ b/indra/newview/llurlwhitelist.cpp
@@ -121,6 +121,12 @@ bool LLUrlWhiteList::save ()
// build filename for each user
std::string resolvedFilename = gDirUtilp->getExpandedFilename ( LL_PATH_PER_SL_ACCOUNT, mFilename );
+ if (resolvedFilename.empty())
+ {
+ llinfos << "No per-user dir for saving URL whitelist - presumably not logged in yet. Skipping." << llendl;
+ return false;
+ }
+
// open a file for writing
llofstream file ( resolvedFilename );
if ( file.is_open () )
diff --git a/indra/newview/llversioninfo.cpp b/indra/newview/llversioninfo.cpp
new file mode 100644
index 0000000000..148931d3ad
--- /dev/null
+++ b/indra/newview/llversioninfo.cpp
@@ -0,0 +1,109 @@
+/**
+ * @file llversioninfo.cpp
+ * @brief Routines to access the viewer version and build information
+ * @author Martin Reddy
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llversioninfo.h"
+
+#include "llversionviewer.h"
+
+//
+// Set the version numbers in indra/llcommon/llversionviewer.h
+//
+
+//static
+S32 LLVersionInfo::getMajor()
+{
+ return LL_VERSION_MAJOR;
+}
+
+//static
+S32 LLVersionInfo::getMinor()
+{
+ return LL_VERSION_MINOR;
+}
+
+//static
+S32 LLVersionInfo::getPatch()
+{
+ return LL_VERSION_PATCH;
+}
+
+//static
+S32 LLVersionInfo::getBuild()
+{
+ return LL_VERSION_BUILD;
+}
+
+//static
+const std::string &LLVersionInfo::getVersion()
+{
+ static std::string version("");
+
+ if (version.empty())
+ {
+ // cache the version string
+ std::ostringstream stream;
+ stream << LL_VERSION_MAJOR << "."
+ << LL_VERSION_MINOR << "."
+ << LL_VERSION_PATCH << "."
+ << LL_VERSION_BUILD;
+ version = stream.str();
+ }
+
+ return version;
+}
+
+//static
+const std::string &LLVersionInfo::getShortVersion()
+{
+ static std::string version("");
+
+ if (version.empty())
+ {
+ // cache the version string
+ std::ostringstream stream;
+ stream << LL_VERSION_MAJOR << "."
+ << LL_VERSION_MINOR << "."
+ << LL_VERSION_PATCH;
+ version = stream.str();
+ }
+
+ return version;
+}
+
+//static
+const std::string &LLVersionInfo::getChannel()
+{
+ static std::string name(LL_CHANNEL);
+ return name;
+}
diff --git a/indra/newview/llversioninfo.h b/indra/newview/llversioninfo.h
new file mode 100644
index 0000000000..b05109e478
--- /dev/null
+++ b/indra/newview/llversioninfo.h
@@ -0,0 +1,71 @@
+/**
+ * @file llversioninfo.h
+ * @brief Routines to access the viewer version and build information
+ * @author Martin Reddy
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLVERSIONINFO_H
+#define LL_LLVERSIONINFO_H
+
+#include <string>
+
+///
+/// This API provides version information for the viewer. This
+/// includes access to the major, minor, patch, and build integer
+/// values, as well as human-readable string representations. All
+/// viewer code that wants to query the current version should
+/// use this API.
+///
+class LLVersionInfo
+{
+public:
+ /// return the major verion number as an integer
+ static S32 getMajor();
+
+ /// return the minor verion number as an integer
+ static S32 getMinor();
+
+ /// return the patch verion number as an integer
+ static S32 getPatch();
+
+ /// return the build number as an integer
+ static S32 getBuild();
+
+ /// return the full viewer version as a string like "2.0.0.200030"
+ static const std::string &getVersion();
+
+ /// return the viewer version as a string like "2.0.0"
+ static const std::string &getShortVersion();
+
+ /// return the channel name, e.g. "Second Life"
+ static const std::string &getChannel();
+};
+
+#endif
diff --git a/indra/newview/llviewchildren.cpp b/indra/newview/llviewchildren.cpp
index 1a66b24891..41eafa871d 100644
--- a/indra/newview/llviewchildren.cpp
+++ b/indra/newview/llviewchildren.cpp
@@ -74,17 +74,6 @@ void LLViewChildren::setText(
}
}
-void LLViewChildren::setWrappedText(
- const std::string& id, const std::string& text, bool visible)
-{
- LLTextBox* child = mParent.getChild<LLTextBox>(id);
- if (child)
- {
- child->setVisible(visible);
- child->setWrappedText(text);
- }
-}
-
void LLViewChildren::setBadge(const std::string& id, Badge badge, bool visible)
{
LLIconCtrl* child = mParent.getChild<LLIconCtrl>(id);
@@ -94,10 +83,10 @@ void LLViewChildren::setBadge(const std::string& id, Badge badge, bool visible)
switch (badge)
{
default:
- case BADGE_OK: child->setImage(std::string("badge_ok.j2c")); break;
- case BADGE_NOTE: child->setImage(std::string("badge_note.j2c")); break;
- case BADGE_WARN: child->setImage(std::string("badge_warn.j2c")); break;
- case BADGE_ERROR: child->setImage(std::string("badge_error.j2c")); break;
+ case BADGE_OK: child->setValue(std::string("badge_ok.j2c")); break;
+ case BADGE_NOTE: child->setValue(std::string("badge_note.j2c")); break;
+ case BADGE_WARN: child->setValue(std::string("badge_warn.j2c")); break;
+ case BADGE_ERROR: child->setValue(std::string("badge_error.j2c")); break;
}
}
}
diff --git a/indra/newview/llviewchildren.h b/indra/newview/llviewchildren.h
index 9263d77bdc..6cfa535a94 100644
--- a/indra/newview/llviewchildren.h
+++ b/indra/newview/llviewchildren.h
@@ -53,8 +53,6 @@ public:
// LLTextBox
void setText(const std::string& id,
const std::string& text, bool visible = true);
- void setWrappedText(const std::string& id,
- const std::string& text, bool visible = true);
// LLIconCtrl
enum Badge { BADGE_OK, BADGE_NOTE, BADGE_WARN, BADGE_ERROR };
diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp
index c32e67ef90..bb49804aff 100644
--- a/indra/newview/llviewerassetstorage.cpp
+++ b/indra/newview/llviewerassetstorage.cpp
@@ -32,13 +32,13 @@
#include "llviewerprecompiledheaders.h"
-#include "linden_common.h"
-
-#include "llagent.h"
#include "llviewerassetstorage.h"
-#include "llviewerbuild.h"
+
#include "llvfile.h"
#include "llvfs.h"
+#include "message.h"
+
+#include "llagent.h"
LLViewerAssetStorage::LLViewerAssetStorage(LLMessageSystem *msg, LLXferManager *xfer,
LLVFS *vfs, const LLHost &upstream_host)
diff --git a/indra/newview/llviewerassetstorage.h b/indra/newview/llviewerassetstorage.h
index 15c11c7025..512b590a1b 100644
--- a/indra/newview/llviewerassetstorage.h
+++ b/indra/newview/llviewerassetstorage.h
@@ -47,6 +47,7 @@ public:
LLViewerAssetStorage(LLMessageSystem *msg, LLXferManager *xfer,
LLVFS *vfs);
+ using LLAssetStorage::storeAssetData;
virtual void storeAssetData(
const LLTransactionID& tid,
LLAssetType::EType atype,
diff --git a/indra/newview/llviewerassettype.cpp b/indra/newview/llviewerassettype.cpp
new file mode 100644
index 0000000000..b382ff6306
--- /dev/null
+++ b/indra/newview/llviewerassettype.cpp
@@ -0,0 +1,113 @@
+/**
+ * @file llassettype.cpp
+ * @brief Implementatino of LLViewerAssetType functionality.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llviewerassettype.h"
+#include "lldictionary.h"
+#include "llmemory.h"
+#include "llsingleton.h"
+
+static const std::string empty_string;
+
+struct ViewerAssetEntry : public LLDictionaryEntry
+{
+ ViewerAssetEntry(EDragAndDropType dad_type // drag and drop type
+ )
+ :
+ LLDictionaryEntry(empty_string), // no reverse lookup needed for now, so just leave this blank
+ mDadType(dad_type)
+ {
+ }
+ EDragAndDropType mDadType;
+};
+
+class LLViewerAssetDictionary : public LLSingleton<LLViewerAssetDictionary>,
+ public LLDictionary<LLViewerAssetType::EType, ViewerAssetEntry>
+{
+public:
+ LLViewerAssetDictionary();
+};
+
+LLViewerAssetDictionary::LLViewerAssetDictionary()
+{
+ // DRAG&DROP TYPE
+ // |--------------------|
+ addEntry(LLViewerAssetType::AT_TEXTURE, new ViewerAssetEntry(DAD_TEXTURE));
+ addEntry(LLViewerAssetType::AT_SOUND, new ViewerAssetEntry(DAD_SOUND));
+ addEntry(LLViewerAssetType::AT_CALLINGCARD, new ViewerAssetEntry(DAD_CALLINGCARD));
+ addEntry(LLViewerAssetType::AT_LANDMARK, new ViewerAssetEntry(DAD_LANDMARK));
+ addEntry(LLViewerAssetType::AT_SCRIPT, new ViewerAssetEntry(DAD_NONE));
+ addEntry(LLViewerAssetType::AT_CLOTHING, new ViewerAssetEntry(DAD_CLOTHING));
+ addEntry(LLViewerAssetType::AT_OBJECT, new ViewerAssetEntry(DAD_OBJECT));
+ addEntry(LLViewerAssetType::AT_NOTECARD, new ViewerAssetEntry(DAD_NOTECARD));
+ addEntry(LLViewerAssetType::AT_CATEGORY, new ViewerAssetEntry(DAD_CATEGORY));
+ addEntry(LLViewerAssetType::AT_LSL_TEXT, new ViewerAssetEntry(DAD_SCRIPT));
+ addEntry(LLViewerAssetType::AT_LSL_BYTECODE, new ViewerAssetEntry(DAD_NONE));
+ addEntry(LLViewerAssetType::AT_TEXTURE_TGA, new ViewerAssetEntry(DAD_NONE));
+ addEntry(LLViewerAssetType::AT_BODYPART, new ViewerAssetEntry(DAD_BODYPART));
+ addEntry(LLViewerAssetType::AT_SOUND_WAV, new ViewerAssetEntry(DAD_NONE));
+ addEntry(LLViewerAssetType::AT_IMAGE_TGA, new ViewerAssetEntry(DAD_NONE));
+ addEntry(LLViewerAssetType::AT_IMAGE_JPEG, new ViewerAssetEntry(DAD_NONE));
+ addEntry(LLViewerAssetType::AT_ANIMATION, new ViewerAssetEntry(DAD_ANIMATION));
+ addEntry(LLViewerAssetType::AT_GESTURE, new ViewerAssetEntry(DAD_GESTURE));
+ addEntry(LLViewerAssetType::AT_SIMSTATE, new ViewerAssetEntry(DAD_NONE));
+
+ addEntry(LLViewerAssetType::AT_LINK, new ViewerAssetEntry(DAD_LINK));
+ addEntry(LLViewerAssetType::AT_LINK_FOLDER, new ViewerAssetEntry(DAD_LINK));
+
+ addEntry(LLViewerAssetType::AT_NONE, new ViewerAssetEntry(DAD_NONE));
+};
+
+EDragAndDropType LLViewerAssetType::lookupDragAndDropType(EType asset_type)
+{
+ const LLViewerAssetDictionary *dict = LLViewerAssetDictionary::getInstance();
+ const ViewerAssetEntry *entry = dict->lookup(asset_type);
+ if (entry)
+ return entry->mDadType;
+ else
+ return DAD_NONE;
+}
+
+// Generate a good default description
+void LLViewerAssetType::generateDescriptionFor(LLViewerAssetType::EType asset_type,
+ std::string& description)
+{
+ const S32 BUF_SIZE = 30;
+ char time_str[BUF_SIZE]; /* Flawfinder: ignore */
+ time_t now;
+ time(&now);
+ memset(time_str, '\0', BUF_SIZE);
+ strftime(time_str, BUF_SIZE - 1, "%Y-%m-%d %H:%M:%S ", localtime(&now));
+ description.assign(time_str);
+ description.append(LLAssetType::lookupHumanReadable(asset_type));
+}
diff --git a/indra/newview/llviewerassettype.h b/indra/newview/llviewerassettype.h
new file mode 100644
index 0000000000..01158885ce
--- /dev/null
+++ b/indra/newview/llviewerassettype.h
@@ -0,0 +1,54 @@
+/**
+ * @file llviewerassettype.h
+ * @brief Declaration of LLViewerViewerAssetType.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLVIEWERASSETTYPE_H
+#define LL_LLVIEWERASSETTYPE_H
+
+#include <string>
+#include "llassettype.h"
+
+// This class is similar to llassettype, but contains methods
+// only used by the viewer.
+class LLViewerAssetType : public LLAssetType
+{
+public:
+ // Generate a good default description. You may want to add a verb
+ // or agent name after this depending on your application.
+ static void generateDescriptionFor(LLViewerAssetType::EType asset_type,
+ std::string& description);
+ static EDragAndDropType lookupDragAndDropType(EType asset_type);
+protected:
+ LLViewerAssetType() {}
+ ~LLViewerAssetType() {}
+};
+
+#endif // LL_LLVIEWERASSETTYPE_H
diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp
index a1e55c1137..38103f9e41 100644
--- a/indra/newview/llvieweraudio.cpp
+++ b/indra/newview/llvieweraudio.cpp
@@ -32,7 +32,7 @@
#include "llviewerprecompiledheaders.h"
-#include "audioengine.h"
+#include "llaudioengine.h"
#include "llagent.h"
#include "llappviewer.h"
#include "llvieweraudio.h"
@@ -86,16 +86,6 @@ void init_audio()
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndObjectDelete")));
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndObjectRezIn")));
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndObjectRezOut")));
- gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuAppear")));
- gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuHide")));
- gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight0")));
- gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight1")));
- gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight2")));
- gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight3")));
- gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight4")));
- gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight5")));
- gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight6")));
- gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight7")));
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndSnapshot")));
//gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndStartAutopilot")));
//gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndStartFollowpilot")));
@@ -128,7 +118,6 @@ void audio_update_volume(bool force_update)
gAudiop->setMasterGain ( master_volume );
gAudiop->setDopplerFactor(gSavedSettings.getF32("AudioLevelDoppler"));
- gAudiop->setDistanceFactor(gSavedSettings.getF32("AudioLevelDistance"));
gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelRolloff"));
#ifdef kAUDIO_ENABLE_WIND
gAudiop->enableWind(!mute_audio);
@@ -222,19 +211,31 @@ void audio_update_wind(bool force_update)
//
if (force_update || (last_camera_water_height * camera_water_height) < 0.f)
{
+ static LLUICachedControl<F32> rolloff("AudioLevelRolloff", 1.0f);
if (camera_water_height < 0.f)
{
- gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelRolloff") * LL_ROLLOFF_MULTIPLIER_UNDER_WATER);
+ gAudiop->setRolloffFactor(rolloff * LL_ROLLOFF_MULTIPLIER_UNDER_WATER);
}
else
{
- gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelRolloff"));
+ gAudiop->setRolloffFactor(rolloff);
}
}
- // this line rotates the wind vector to be listener (agent) relative
- // unfortunately we have to pre-translate to undo the translation that
- // occurs in the transform call
- gRelativeWindVec = gAgent.getFrameAgent().rotateToLocal(gWindVec - gAgent.getVelocity());
+
+ // Scale down the contribution of weather-simulation wind to the
+ // ambient wind noise. Wind velocity averages 3.5 m/s, with gusts to 7 m/s
+ // whereas steady-state avatar walk velocity is only 3.2 m/s.
+ // Without this the world feels desolate on first login when you are
+ // standing still.
+ static LLUICachedControl<F32> wind_level("AudioLevelWind", 0.5f);
+ LLVector3 scaled_wind_vec = gWindVec * wind_level;
+
+ // Mix in the avatar's motion, subtract because when you walk north,
+ // the apparent wind moves south.
+ LLVector3 final_wind_vec = scaled_wind_vec - gAgent.getVelocity();
+
+ // rotate the wind vector to be listener (agent) relative
+ gRelativeWindVec = gAgent.getFrameAgent().rotateToLocal( final_wind_vec );
// don't use the setter setMaxWindGain() because we don't
// want to screw up the fade-in on startup by setting actual source gain
diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp
index 72d1494d96..bd4f172907 100644
--- a/indra/newview/llviewercamera.cpp
+++ b/indra/newview/llviewercamera.cpp
@@ -31,18 +31,13 @@
*/
#include "llviewerprecompiledheaders.h"
-#include "llviewercamera.h"
-
-#include <iomanip> // for setprecision
-#include "llquaternion.h"
+#define LLVIEWERCAMERA_CPP
+#include "llviewercamera.h"
+// Viewer includes
#include "llagent.h"
#include "llviewercontrol.h"
-#include "lldrawable.h"
-#include "llface.h"
-#include "llgl.h"
-#include "llglheaders.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "llviewerwindow.h"
@@ -51,6 +46,19 @@
#include "lltoolmgr.h"
#include "llviewerjoystick.h"
+// Linden library includes
+#include "lldrawable.h"
+#include "llface.h"
+#include "llgl.h"
+#include "llglheaders.h"
+#include "llquaternion.h"
+#include "llwindow.h" // getPixelAspectRatio()
+
+// System includes
+#include <iomanip> // for setprecision
+
+U32 LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+
//glu pick matrix implementation borrowed from Mesa3D
glh::matrix4f gl_pick_matrix(GLfloat x, GLfloat y, GLfloat width, GLfloat height, GLint* viewport)
{
@@ -98,23 +106,29 @@ glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up)
}
+// Build time optimization, generate this once in .cpp file
+template class LLViewerCamera* LLSingleton<class LLViewerCamera>::getInstance();
+
LLViewerCamera::LLViewerCamera() : LLCamera()
{
calcProjection(getFar());
mCameraFOVDefault = DEFAULT_FIELD_OF_VIEW;
+ mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f);
mPixelMeterRatio = 0.f;
mScreenPixelArea = 0;
mZoomFactor = 1.f;
mZoomSubregion = 1;
+ mAverageSpeed = 0.f;
+ mAverageAngularSpeed = 0.f;
+ gSavedSettings.getControl("CameraAngle")->getCommitSignal()->connect(boost::bind(&LLViewerCamera::updateCameraAngle, this, _2));
}
void LLViewerCamera::updateCameraLocation(const LLVector3 &center,
const LLVector3 &up_direction,
const LLVector3 &point_of_interest)
{
- // do not update if we are in build mode AND avatar didn't move
- if (LLToolMgr::getInstance()->inBuildMode()
- && !LLViewerJoystick::getInstance()->getCameraNeedsUpdate())
+ // do not update if avatar didn't move
+ if (!LLViewerJoystick::getInstance()->getCameraNeedsUpdate())
{
return;
}
@@ -144,15 +158,22 @@ void LLViewerCamera::updateCameraLocation(const LLVector3 &center,
setOriginAndLookAt(origin, up_direction, point_of_interest);
- F32 dpos = (center - last_position).magVec();
+ mVelocityDir = center - last_position ;
+ F32 dpos = mVelocityDir.normVec() ;
LLQuaternion rotation;
rotation.shortestArc(last_axis, getAtAxis());
F32 x, y, z;
F32 drot;
rotation.getAngleAxis(&drot, &x, &y, &z);
+
mVelocityStat.addValue(dpos);
mAngularVelocityStat.addValue(drot);
+
+ mAverageSpeed = mVelocityStat.getMeanPerSec() ;
+ mAverageAngularSpeed = mAngularVelocityStat.getMeanPerSec() ;
+ mCosHalfCameraFOV = cosf(0.5f * getView() * llmax(1.0f, getAspect()));
+
// update pixel meter ratio using default fov, not modified one
mPixelMeterRatio = getViewHeightInPixels()/ (2.f*tanf(mCameraFOVDefault*0.5));
// update screen pixel area
@@ -384,10 +405,10 @@ void LLViewerCamera::setPerspective(BOOL for_selection,
if (for_selection && (width > 1 || height > 1))
{
- calculateFrustumPlanesFromWindow((F32)(x - width / 2) / (F32)gViewerWindow->getWindowWidth() - 0.5f,
- (F32)(y_from_bot - height / 2) / (F32)gViewerWindow->getWindowHeight() - 0.5f,
- (F32)(x + width / 2) / (F32)gViewerWindow->getWindowWidth() - 0.5f,
- (F32)(y_from_bot + height / 2) / (F32)gViewerWindow->getWindowHeight() - 0.5f);
+ calculateFrustumPlanesFromWindow((F32)(x - width / 2) / (F32)gViewerWindow->getWindowWidthScaled() - 0.5f,
+ (F32)(y_from_bot - height / 2) / (F32)gViewerWindow->getWindowHeightScaled() - 0.5f,
+ (F32)(x + width / 2) / (F32)gViewerWindow->getWindowWidthScaled() - 0.5f,
+ (F32)(y_from_bot + height / 2) / (F32)gViewerWindow->getWindowHeightScaled() - 0.5f);
}
@@ -452,8 +473,15 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord
}
}
+ LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw();
+ S32 viewport[4];
+ viewport[0] = world_view_rect.mLeft;
+ viewport[1] = world_view_rect.mBottom;
+ viewport[2] = world_view_rect.getWidth();
+ viewport[3] = world_view_rect.getHeight();
+
if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ],
- gGLModelView, gGLProjection, (GLint*)gGLViewport,
+ gGLModelView, gGLProjection, (GLint*)viewport,
&x, &y, &z))
{
// convert screen coordinates to virtual UI coordinates
@@ -461,9 +489,9 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord
y /= gViewerWindow->getDisplayScale().mV[VY];
// should now have the x,y coords of grab_point in screen space
- const LLRect& window_rect = gViewerWindow->getWindowRect();
+ LLRect world_rect = gViewerWindow->getWorldViewRectScaled();
- // ...sanity check
+ // convert to pixel coordinates
S32 int_x = lltrunc(x);
S32 int_y = lltrunc(y);
@@ -471,14 +499,14 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord
if (clamp)
{
- if (int_x < window_rect.mLeft)
+ if (int_x < world_rect.mLeft)
{
- out_point.mX = window_rect.mLeft;
+ out_point.mX = world_rect.mLeft;
valid = FALSE;
}
- else if (int_x > window_rect.mRight)
+ else if (int_x > world_rect.mRight)
{
- out_point.mX = window_rect.mRight;
+ out_point.mX = world_rect.mRight;
valid = FALSE;
}
else
@@ -486,14 +514,14 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord
out_point.mX = int_x;
}
- if (int_y < window_rect.mBottom)
+ if (int_y < world_rect.mBottom)
{
- out_point.mY = window_rect.mBottom;
+ out_point.mY = world_rect.mBottom;
valid = FALSE;
}
- else if (int_y > window_rect.mTop)
+ else if (int_y > world_rect.mTop)
{
- out_point.mY = window_rect.mTop;
+ out_point.mY = world_rect.mTop;
valid = FALSE;
}
else
@@ -507,19 +535,19 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord
out_point.mX = int_x;
out_point.mY = int_y;
- if (int_x < window_rect.mLeft)
+ if (int_x < world_rect.mLeft)
{
valid = FALSE;
}
- else if (int_x > window_rect.mRight)
+ else if (int_x > world_rect.mRight)
{
valid = FALSE;
}
- if (int_y < window_rect.mBottom)
+ if (int_y < world_rect.mBottom)
{
valid = FALSE;
}
- else if (int_y > window_rect.mTop)
+ else if (int_y > world_rect.mTop)
{
valid = FALSE;
}
@@ -548,24 +576,30 @@ BOOL LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3 &pos_agent,
in_front = FALSE;
}
+ LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw();
+ S32 viewport[4];
+ viewport[0] = world_view_rect.mLeft;
+ viewport[1] = world_view_rect.mBottom;
+ viewport[2] = world_view_rect.getWidth();
+ viewport[3] = world_view_rect.getHeight();
GLdouble x, y, z; // object's window coords, GL-style
if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY],
pos_agent.mV[VZ], gGLModelView,
- gGLProjection, (GLint*)gGLViewport,
+ gGLProjection, (GLint*)viewport,
&x, &y, &z))
{
x /= gViewerWindow->getDisplayScale().mV[VX];
y /= gViewerWindow->getDisplayScale().mV[VY];
// should now have the x,y coords of grab_point in screen space
- const LLRect& window_rect = gViewerWindow->getVirtualWindowRect();
+ const LLRect& world_rect = gViewerWindow->getWorldViewRectScaled();
// ...sanity check
S32 int_x = lltrunc(x);
S32 int_y = lltrunc(y);
// find the center
- GLdouble center_x = (GLdouble)(0.5f * (window_rect.mLeft + window_rect.mRight));
- GLdouble center_y = (GLdouble)(0.5f * (window_rect.mBottom + window_rect.mTop));
+ GLdouble center_x = (GLdouble)world_rect.getCenterX();
+ GLdouble center_y = (GLdouble)world_rect.getCenterY();
if (x == center_x && y == center_y)
{
@@ -586,41 +620,41 @@ BOOL LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3 &pos_agent,
// the slope of the line is undefined
if (line_y > 0.f)
{
- int_y = window_rect.mTop;
+ int_y = world_rect.mTop;
}
else
{
- int_y = window_rect.mBottom;
+ int_y = world_rect.mBottom;
}
}
- else if (0 == window_rect.getWidth())
+ else if (0 == world_rect.getWidth())
{
// the diagonal slope of the view is undefined
- if (y < window_rect.mBottom)
+ if (y < world_rect.mBottom)
{
- int_y = window_rect.mBottom;
+ int_y = world_rect.mBottom;
}
- else if ( y > window_rect.mTop)
+ else if ( y > world_rect.mTop)
{
- int_y = window_rect.mTop;
+ int_y = world_rect.mTop;
}
}
else
{
F32 line_slope = (F32)(line_y / line_x);
- F32 rect_slope = ((F32)window_rect.getHeight()) / ((F32)window_rect.getWidth());
+ F32 rect_slope = ((F32)world_rect.getHeight()) / ((F32)world_rect.getWidth());
if (fabs(line_slope) > rect_slope)
{
if (line_y < 0.f)
{
// bottom
- int_y = window_rect.mBottom;
+ int_y = world_rect.mBottom;
}
else
{
// top
- int_y = window_rect.mTop;
+ int_y = world_rect.mTop;
}
int_x = lltrunc(((GLdouble)int_y - center_y) / line_slope + center_x);
}
@@ -629,12 +663,12 @@ BOOL LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3 &pos_agent,
if (line_x < 0.f)
{
// left
- int_x = window_rect.mLeft;
+ int_x = world_rect.mLeft;
}
else
{
// right
- int_x = window_rect.mRight;
+ int_x = world_rect.mRight;
}
int_y = lltrunc(((GLdouble)int_x - center_x) * line_slope + center_y);
}
@@ -643,29 +677,30 @@ BOOL LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3 &pos_agent,
// exactly parallel ==> push to the corners
if (line_x > 0.f)
{
- int_x = window_rect.mRight;
+ int_x = world_rect.mRight;
}
else
{
- int_x = window_rect.mLeft;
+ int_x = world_rect.mLeft;
}
if (line_y > 0.0f)
{
- int_y = window_rect.mTop;
+ int_y = world_rect.mTop;
}
else
{
- int_y = window_rect.mBottom;
+ int_y = world_rect.mBottom;
}
}
}
if (!in_front)
{
- int_x = window_rect.mLeft + window_rect.mRight - int_x;
- int_y = window_rect.mBottom + window_rect.mTop - int_y;
+ int_x = world_rect.mLeft + world_rect.mRight - int_x;
+ int_y = world_rect.mBottom + world_rect.mTop - int_y;
}
- out_point.mX = int_x;
- out_point.mY = int_y;
+
+ out_point.mX = int_x + world_rect.mLeft;
+ out_point.mY = int_y + world_rect.mBottom;
return TRUE;
}
return FALSE;
@@ -759,8 +794,8 @@ BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts)
BOOL in_frustum = pointInFrustum(LLVector3(vec)) > 0;
- if ( !in_frustum && all_verts ||
- in_frustum && !all_verts)
+ if (( !in_frustum && all_verts) ||
+ (in_frustum && !all_verts))
{
return !all_verts;
}
@@ -797,9 +832,19 @@ BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts)
LLCamera::setView(vertical_fov_rads); // call base implementation
}
-void LLViewerCamera::setDefaultFOV(F32 vertical_fov_rads) {
+void LLViewerCamera::setDefaultFOV(F32 vertical_fov_rads)
+{
vertical_fov_rads = llclamp(vertical_fov_rads, getMinView(), getMaxView());
setView(vertical_fov_rads);
mCameraFOVDefault = vertical_fov_rads;
+ mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f);
+}
+
+
+// static
+void LLViewerCamera::updateCameraAngle( void* user_data, const LLSD& value)
+{
+ LLViewerCamera* self=(LLViewerCamera*)user_data;
+ self->setDefaultFOV(value.asReal());
}
diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h
index 6a0c42beec..cd67af5fef 100644
--- a/indra/newview/llviewercamera.h
+++ b/indra/newview/llviewercamera.h
@@ -34,8 +34,9 @@
#define LL_LLVIEWERCAMERA_H
#include "llcamera.h"
-#include "lltimer.h"
+#include "llsingleton.h"
#include "llstat.h"
+#include "lltimer.h"
#include "m4math.h"
class LLCoordGL;
@@ -51,9 +52,32 @@ const F32 OGL_TO_CFR_ROTATION[16] = { 0.f, 0.f, -1.f, 0.f, // -Z becomes X
const BOOL FOR_SELECTION = TRUE;
const BOOL NOT_FOR_SELECTION = FALSE;
+// Build time optimization, generate this once in .cpp file
+#ifndef LLVIEWERCAMERA_CPP
+extern template class LLViewerCamera* LLSingleton<class LLViewerCamera>::getInstance();
+#endif
+
class LLViewerCamera : public LLCamera, public LLSingleton<LLViewerCamera>
{
public:
+
+ typedef enum
+ {
+ CAMERA_WORLD = 0,
+ CAMERA_SHADOW0,
+ CAMERA_SHADOW1,
+ CAMERA_SHADOW2,
+ CAMERA_SHADOW3,
+ CAMERA_SHADOW4,
+ CAMERA_SHADOW5,
+ CAMERA_WATER0,
+ CAMERA_WATER1,
+ CAMERA_GI_SOURCE,
+ NUM_CAMERAS
+ } eCameraID;
+
+ static U32 sCurCameraID;
+
LLViewerCamera();
void updateCameraLocation(const LLVector3 &center,
@@ -61,6 +85,7 @@ public:
const LLVector3 &point_of_interest);
static void updateFrustumPlanes(LLCamera& camera, BOOL ortho = FALSE, BOOL zflip = FALSE, BOOL no_hacks = FALSE);
+ static void updateCameraAngle(void* user_data, const LLSD& value);
void setPerspective(BOOL for_selection, S32 x, S32 y_from_bot, S32 width, S32 height, BOOL limit_select_distance, F32 z_near = 0, F32 z_far = 0);
const LLMatrix4 &getProjection() const;
@@ -71,17 +96,20 @@ public:
BOOL projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoordGL &out_point, const BOOL clamp = TRUE) const;
BOOL projectPosAgentToScreenEdge(const LLVector3 &pos_agent, LLCoordGL &out_point) const;
-
+ const LLVector3* getVelocityDir() const {return &mVelocityDir;}
LLStat *getVelocityStat() { return &mVelocityStat; }
LLStat *getAngularVelocityStat() { return &mAngularVelocityStat; }
+ F32 getCosHalfFov() {return mCosHalfCameraFOV;}
+ F32 getAverageSpeed() {return mAverageSpeed ;}
+ F32 getAverageAngularSpeed() {return mAverageAngularSpeed;}
void getPixelVectors(const LLVector3 &pos_agent, LLVector3 &up, LLVector3 &right);
LLVector3 roundToPixel(const LLVector3 &pos_agent);
// Sets the current matrix
/* virtual */ void setView(F32 vertical_fov_rads);
- // Sets the current matrix AND remembers result as default view
- void setDefaultFOV(F32 vertical_fov_rads);
+
+ void setDefaultFOV(F32 fov) ;
F32 getDefaultFOV() { return mCameraFOVDefault; }
BOOL cameraUnderWater() const;
@@ -100,9 +128,14 @@ protected:
LLStat mVelocityStat;
LLStat mAngularVelocityStat;
+ LLVector3 mVelocityDir ;
+ F32 mAverageSpeed ;
+ F32 mAverageAngularSpeed ;
+
mutable LLMatrix4 mProjectionMatrix; // Cache of perspective matrix
mutable LLMatrix4 mModelviewMatrix;
F32 mCameraFOVDefault;
+ F32 mCosHalfCameraFOV;
LLVector3 mLastPointOfInterest;
F32 mPixelMeterRatio; // Divide by distance from camera to get pixels per meter at that distance.
S32 mScreenPixelArea; // Pixel area of entire window
diff --git a/indra/newview/llviewerchat.cpp b/indra/newview/llviewerchat.cpp
new file mode 100644
index 0000000000..8de87eb602
--- /dev/null
+++ b/indra/newview/llviewerchat.cpp
@@ -0,0 +1,221 @@
+/**
+ * @file llviewerchat.cpp
+ * @brief Builds menus out of items.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llviewerchat.h"
+
+// newview includes
+#include "llagent.h" // gAgent
+#include "lluicolortable.h"
+#include "llviewercontrol.h" // gSavedSettings
+
+// LLViewerChat
+
+//static
+void LLViewerChat::getChatColor(const LLChat& chat, LLColor4& r_color)
+{
+ if(chat.mMuted)
+ {
+ r_color= LLUIColorTable::instance().getColor("LtGray");
+ }
+ else
+ {
+ switch(chat.mSourceType)
+ {
+ case CHAT_SOURCE_SYSTEM:
+ r_color = LLUIColorTable::instance().getColor("SystemChatColor");
+ break;
+ case CHAT_SOURCE_AGENT:
+ if (chat.mFromID.isNull())
+ {
+ r_color = LLUIColorTable::instance().getColor("SystemChatColor");
+ }
+ else
+ {
+ if(gAgentID == chat.mFromID)
+ {
+ r_color = LLUIColorTable::instance().getColor("UserChatColor");
+ }
+ else
+ {
+ r_color = LLUIColorTable::instance().getColor("AgentChatColor");
+ }
+ }
+ break;
+ case CHAT_SOURCE_OBJECT:
+ if (chat.mChatType == CHAT_TYPE_DEBUG_MSG)
+ {
+ r_color = LLUIColorTable::instance().getColor("ScriptErrorColor");
+ }
+ else if ( chat.mChatType == CHAT_TYPE_OWNER )
+ {
+ r_color = LLUIColorTable::instance().getColor("llOwnerSayChatColor");
+ }
+ else
+ {
+ r_color = LLUIColorTable::instance().getColor("ObjectChatColor");
+ }
+ break;
+ default:
+ r_color.setToWhite();
+ }
+
+ if (!chat.mPosAgent.isExactlyZero())
+ {
+ LLVector3 pos_agent = gAgent.getPositionAgent();
+ F32 distance = dist_vec(pos_agent, chat.mPosAgent);
+ if (distance > gAgent.getNearChatRadius())
+ {
+ // diminish far-off chat
+ r_color.mV[VALPHA] = 0.8f;
+ }
+ }
+ }
+}
+
+
+//static
+void LLViewerChat::getChatColor(const LLChat& chat, std::string& r_color_name, F32& r_color_alpha)
+{
+ if(chat.mMuted)
+ {
+ r_color_name = "LtGray";
+ }
+ else
+ {
+ switch(chat.mSourceType)
+ {
+ case CHAT_SOURCE_SYSTEM:
+ r_color_name = "SystemChatColor";
+ break;
+
+ case CHAT_SOURCE_AGENT:
+ if (chat.mFromID.isNull())
+ {
+ r_color_name = "SystemChatColor";
+ }
+ else
+ {
+ if(gAgentID == chat.mFromID)
+ {
+ r_color_name = "UserChatColor";
+ }
+ else
+ {
+ r_color_name = "AgentChatColor";
+ }
+ }
+ break;
+
+ case CHAT_SOURCE_OBJECT:
+ if (chat.mChatType == CHAT_TYPE_DEBUG_MSG)
+ {
+ r_color_name = "ScriptErrorColor";
+ }
+ else if ( chat.mChatType == CHAT_TYPE_OWNER )
+ {
+ r_color_name = "llOwnerSayChatColor";
+ }
+ else
+ {
+ r_color_name = "ObjectChatColor";
+ }
+ break;
+ default:
+ r_color_name = "White";
+ }
+
+ if (!chat.mPosAgent.isExactlyZero())
+ {
+ LLVector3 pos_agent = gAgent.getPositionAgent();
+ F32 distance = dist_vec(pos_agent, chat.mPosAgent);
+ if (distance > gAgent.getNearChatRadius())
+ {
+ // diminish far-off chat
+ r_color_alpha = 0.8f;
+ }
+ else
+ {
+ r_color_alpha = 1.0f;
+ }
+ }
+ }
+
+}
+
+
+//static
+LLFontGL* LLViewerChat::getChatFont()
+{
+ S32 font_size = gSavedSettings.getS32("ChatFontSize");
+ LLFontGL* fontp = NULL;
+ switch(font_size)
+ {
+ case 0:
+ fontp = LLFontGL::getFontSansSerifSmall();
+ break;
+ default:
+ case 1:
+ fontp = LLFontGL::getFontSansSerif();
+ break;
+ case 2:
+ fontp = LLFontGL::getFontSansSerifBig();
+ break;
+ }
+
+ return fontp;
+
+}
+
+//static
+S32 LLViewerChat::getChatFontSize()
+{
+ return gSavedSettings.getS32("ChatFontSize");
+}
+
+
+//static
+void LLViewerChat::formatChatMsg(const LLChat& chat, std::string& formated_msg)
+{
+ std::string tmpmsg = chat.mText;
+
+ if(chat.mChatStyle == CHAT_STYLE_IRC)
+ {
+ formated_msg = chat.mFromName + tmpmsg.substr(3);
+ }
+ else
+ {
+ formated_msg = tmpmsg;
+ }
+
+}
+
diff --git a/indra/newview/llviewerchat.h b/indra/newview/llviewerchat.h
new file mode 100644
index 0000000000..502d6ea7e5
--- /dev/null
+++ b/indra/newview/llviewerchat.h
@@ -0,0 +1,52 @@
+/**
+ * @file llviewerchat.h
+ * @brief wrapper of LLChat in viewer
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLVIEWERCHAT_H
+#define LL_LLVIEWERCHAT_H
+
+#include "llchat.h"
+#include "llfontgl.h"
+#include "v4color.h"
+
+
+class LLViewerChat
+{
+public:
+ static void getChatColor(const LLChat& chat, LLColor4& r_color);
+ static void getChatColor(const LLChat& chat, std::string& r_color_name, F32& r_color_alpha);
+ static LLFontGL* getChatFont();
+ static S32 getChatFontSize();
+ static void formatChatMsg(const LLChat& chat, std::string& formated_msg);
+
+};
+
+#endif
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index eb8cdd82b3..57434bd1e4 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -35,24 +35,25 @@
#include "llviewercontrol.h"
-#include "indra_constants.h"
+// Library includes
+#include "llwindow.h" // getGamma()
// For Listeners
-#include "audioengine.h"
+#include "llaudioengine.h"
#include "llagent.h"
#include "llconsole.h"
#include "lldrawpoolterrain.h"
#include "llflexibleobject.h"
#include "llfeaturemanager.h"
#include "llviewershadermgr.h"
-#include "llpanelgeneral.h"
-#include "llpanelinput.h"
+
#include "llsky.h"
#include "llvieweraudio.h"
-#include "llviewerimagelist.h"
+#include "llviewermenu.h"
+#include "llviewertexturelist.h"
#include "llviewerthrottle.h"
#include "llviewerwindow.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "llvoiceclient.h"
#include "llvosky.h"
#include "llvotree.h"
@@ -62,33 +63,34 @@
#include "llviewerjoystick.h"
#include "llviewerparcelmgr.h"
#include "llparcel.h"
-#include "llnotify.h"
#include "lloverlaybar.h"
#include "llkeyboard.h"
#include "llerrorcontrol.h"
-#include "llversionviewer.h"
#include "llappviewer.h"
#include "llvosurfacepatch.h"
#include "llvowlsky.h"
#include "llrender.h"
+#include "llbottomtray.h"
+#include "llnavigationbar.h"
+#include "llfloatertools.h"
+#include "llpaneloutfitsinventory.h"
#ifdef TOGGLE_HACKED_GODLIKE_VIEWER
BOOL gHackGodmode = FALSE;
#endif
-std::map<std::string, LLControlGroup*> gSettings;
-LLControlGroup gSavedSettings; // saved at end of session
-LLControlGroup gSavedPerAccountSettings; // saved at end of session
-LLControlGroup gColors; // read-only
-LLControlGroup gCrashSettings; // saved at end of session
+LLControlGroup gSavedSettings("Global"); // saved at end of session
+LLControlGroup gSavedPerAccountSettings("PerAccount"); // saved at end of session
+LLControlGroup gCrashSettings("CrashSettings"); // saved at end of session
+LLControlGroup gWarningSettings("Warnings"); // persists ignored dialogs/warnings
std::string gLastRunVersion;
std::string gCurrentVersion;
extern BOOL gResizeScreenTexture;
extern BOOL gDebugGL;
-
+extern BOOL gAuditTexture;
////////////////////////////////////////////////////////////////////////////
// Listeners
@@ -119,12 +121,6 @@ static bool handleSetShaderChanged(const LLSD& newvalue)
return true;
}
-static bool handleSetSelfInvisible( const LLSD& newvalue)
-{
- LLVOAvatar::onChangeSelfInvisible( newvalue.asBoolean() );
- return true;
-}
-
static bool handleReleaseGLBufferChanged(const LLSD& newvalue)
{
if (gPipeline.isInit())
@@ -213,7 +209,7 @@ static bool handleMaxPartCountChanged(const LLSD& newvalue)
static bool handleVideoMemoryChanged(const LLSD& newvalue)
{
- gImageList.updateMaxResidentTexMem(newvalue.asInteger());
+ gTextureList.updateMaxResidentTexMem(newvalue.asInteger());
return true;
}
@@ -376,9 +372,15 @@ static bool handleRenderUseImpostorsChanged(const LLSD& newvalue)
return true;
}
+static bool handleAuditTextureChanged(const LLSD& newvalue)
+{
+ gAuditTexture = newvalue.asBoolean();
+ return true;
+}
+
static bool handleRenderDebugGLChanged(const LLSD& newvalue)
{
- gDebugGL = newvalue.asBoolean();
+ gDebugGL = newvalue.asBoolean() || gDebugSession;
gGL.clearErrors();
return true;
}
@@ -427,6 +429,16 @@ bool handleVectorizeChanged(const LLSD& newvalue)
return true;
}
+bool handleHighResSnapshotChanged(const LLSD& newvalue)
+{
+ // High Res Snapshot active, must uncheck RenderUIInSnapshot
+ if (newvalue.asBoolean())
+ {
+ gSavedSettings.setBOOL( "RenderUIInSnapshot", FALSE );
+ }
+ return true;
+}
+
bool handleVoiceClientPrefsChanged(const LLSD& newvalue)
{
if(gVoiceClient)
@@ -436,216 +448,236 @@ bool handleVoiceClientPrefsChanged(const LLSD& newvalue)
return true;
}
-////////////////////////////////////////////////////////////////////////////
+bool handleVelocityInterpolate(const LLSD& newvalue)
+{
+ LLMessageSystem* msg = gMessageSystem;
+ if ( newvalue.asBoolean() )
+ {
+ msg->newMessageFast(_PREHASH_VelocityInterpolateOn);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ gAgent.sendReliableMessage();
+ llinfos << "Velocity Interpolation On" << llendl;
+ }
+ else
+ {
+ msg->newMessageFast(_PREHASH_VelocityInterpolateOff);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ gAgent.sendReliableMessage();
+ llinfos << "Velocity Interpolation Off" << llendl;
+ }
+ return true;
+}
-void settings_setup_listeners()
+bool toggle_agent_pause(const LLSD& newvalue)
{
- gSavedSettings.getControl("FirstPersonAvatarVisible")->getSignal()->connect(boost::bind(&handleRenderAvatarMouselookChanged, _1));
- gSavedSettings.getControl("RenderFarClip")->getSignal()->connect(boost::bind(&handleRenderFarClipChanged, _1));
- gSavedSettings.getControl("RenderTerrainDetail")->getSignal()->connect(boost::bind(&handleTerrainDetailChanged, _1));
- gSavedSettings.getControl("RenderAnimateTrees")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _1));
- gSavedSettings.getControl("RenderAvatarVP")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1));
- gSavedSettings.getControl("VertexShaderEnable")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1));
- gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1));
- gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1));
- gSavedSettings.getControl("EnableRippleWater")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1));
- gSavedSettings.getControl("RenderGlowResolutionPow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1));
- gSavedSettings.getControl("RenderAvatarCloth")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1));
- gSavedSettings.getControl("WindLightUseAtmosShaders")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1));
- gSavedSettings.getControl("RenderGammaFull")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1));
- gSavedSettings.getControl("RenderAvatarMaxVisible")->getSignal()->connect(boost::bind(&handleAvatarMaxVisibleChanged, _1));
- gSavedSettings.getControl("RenderAvatarInvisible")->getSignal()->connect(boost::bind(&handleSetSelfInvisible, _1));
- gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _1));
- gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _1));
- gSavedSettings.getControl("RenderTerrainLODFactor")->getSignal()->connect(boost::bind(&handleTerrainLODChanged, _1));
- gSavedSettings.getControl("RenderTreeLODFactor")->getSignal()->connect(boost::bind(&handleTreeLODChanged, _1));
- gSavedSettings.getControl("RenderFlexTimeFactor")->getSignal()->connect(boost::bind(&handleFlexLODChanged, _1));
- gSavedSettings.getControl("ThrottleBandwidthKBPS")->getSignal()->connect(boost::bind(&handleBandwidthChanged, _1));
- gSavedSettings.getControl("RenderGamma")->getSignal()->connect(boost::bind(&handleGammaChanged, _1));
- gSavedSettings.getControl("RenderFogRatio")->getSignal()->connect(boost::bind(&handleFogRatioChanged, _1));
- gSavedSettings.getControl("RenderMaxPartCount")->getSignal()->connect(boost::bind(&handleMaxPartCountChanged, _1));
- gSavedSettings.getControl("RenderDynamicLOD")->getSignal()->connect(boost::bind(&handleRenderDynamicLODChanged, _1));
- gSavedSettings.getControl("RenderDebugTextureBind")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _1));
- gSavedSettings.getControl("RenderFastAlpha")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _1));
- gSavedSettings.getControl("RenderObjectBump")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _1));
- gSavedSettings.getControl("RenderMaxVBOSize")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _1));
- gSavedSettings.getControl("RenderUseFBO")->getSignal()->connect(boost::bind(&handleRenderUseFBOChanged, _1));
- gSavedSettings.getControl("RenderDeferredNoise")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1));
- gSavedSettings.getControl("RenderUseImpostors")->getSignal()->connect(boost::bind(&handleRenderUseImpostorsChanged, _1));
- gSavedSettings.getControl("RenderDebugGL")->getSignal()->connect(boost::bind(&handleRenderDebugGLChanged, _1));
- gSavedSettings.getControl("RenderDebugPipeline")->getSignal()->connect(boost::bind(&handleRenderDebugPipelineChanged, _1));
- gSavedSettings.getControl("RenderResolutionDivisor")->getSignal()->connect(boost::bind(&handleRenderResolutionDivisorChanged, _1));
- gSavedSettings.getControl("RenderDeferred")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1));
- gSavedSettings.getControl("TextureMemory")->getSignal()->connect(boost::bind(&handleVideoMemoryChanged, _1));
- gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&handleChatFontSizeChanged, _1));
- gSavedSettings.getControl("ChatPersistTime")->getSignal()->connect(boost::bind(&handleChatPersistTimeChanged, _1));
- gSavedSettings.getControl("ConsoleMaxLines")->getSignal()->connect(boost::bind(&handleConsoleMaxLinesChanged, _1));
- gSavedSettings.getControl("UploadBakedTexOld")->getSignal()->connect(boost::bind(&handleUploadBakedTexOldChanged, _1));
- gSavedSettings.getControl("UseOcclusion")->getSignal()->connect(boost::bind(&handleUseOcclusionChanged, _1));
- gSavedSettings.getControl("AudioLevelMaster")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1));
- gSavedSettings.getControl("AudioLevelSFX")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1));
- gSavedSettings.getControl("AudioLevelUI")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1));
- gSavedSettings.getControl("AudioLevelAmbient")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1));
- gSavedSettings.getControl("AudioLevelMusic")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1));
- gSavedSettings.getControl("AudioLevelMedia")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1));
- gSavedSettings.getControl("AudioLevelVoice")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1));
- gSavedSettings.getControl("AudioLevelDistance")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1));
- gSavedSettings.getControl("AudioLevelDoppler")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1));
- gSavedSettings.getControl("AudioLevelRolloff")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1));
- gSavedSettings.getControl("AudioStreamingMusic")->getSignal()->connect(boost::bind(&handleAudioStreamMusicChanged, _1));
- gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1));
- gSavedSettings.getControl("MuteMusic")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1));
- gSavedSettings.getControl("MuteMedia")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1));
- gSavedSettings.getControl("MuteVoice")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1));
- gSavedSettings.getControl("MuteAmbient")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1));
- gSavedSettings.getControl("MuteUI")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1));
- gSavedSettings.getControl("RenderVBOEnable")->getSignal()->connect(boost::bind(&handleRenderUseVBOChanged, _1));
- gSavedSettings.getControl("WLSkyDetail")->getSignal()->connect(boost::bind(&handleWLSkyDetailChanged, _1));
- gSavedSettings.getControl("RenderLightingDetail")->getSignal()->connect(boost::bind(&handleRenderLightingDetailChanged, _1));
- gSavedSettings.getControl("NumpadControl")->getSignal()->connect(boost::bind(&handleNumpadControlChanged, _1));
- gSavedSettings.getControl("JoystickAxis0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("JoystickAxis1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("JoystickAxis2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("JoystickAxis3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("JoystickAxis4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("JoystickAxis5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("JoystickAxis6")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("FlycamAxisScale0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("FlycamAxisScale1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("FlycamAxisScale2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("FlycamAxisScale3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("FlycamAxisScale4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("FlycamAxisScale5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("FlycamAxisScale6")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("FlycamAxisDeadZone0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("FlycamAxisDeadZone1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("FlycamAxisDeadZone2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("FlycamAxisDeadZone3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("FlycamAxisDeadZone4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("FlycamAxisDeadZone5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("FlycamAxisDeadZone6")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("AvatarAxisScale0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("AvatarAxisScale1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("AvatarAxisScale2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("AvatarAxisScale3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("AvatarAxisScale4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("AvatarAxisScale5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("AvatarAxisDeadZone0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("AvatarAxisDeadZone1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("AvatarAxisDeadZone2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("AvatarAxisDeadZone3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("AvatarAxisDeadZone4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("AvatarAxisDeadZone5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("BuildAxisScale0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("BuildAxisScale1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("BuildAxisScale2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("BuildAxisScale3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("BuildAxisScale4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("BuildAxisScale5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("BuildAxisDeadZone0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("BuildAxisDeadZone1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("BuildAxisDeadZone2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("BuildAxisDeadZone3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("BuildAxisDeadZone4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("BuildAxisDeadZone5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));
- gSavedSettings.getControl("DebugViews")->getSignal()->connect(boost::bind(&handleDebugViewsChanged, _1));
- gSavedSettings.getControl("UserLogFile")->getSignal()->connect(boost::bind(&handleLogFileChanged, _1));
- gSavedSettings.getControl("RenderHideGroupTitle")->getSignal()->connect(boost::bind(handleHideGroupTitleChanged, _1));
- gSavedSettings.getControl("EffectColor")->getSignal()->connect(boost::bind(handleEffectColorChanged, _1));
- gSavedSettings.getControl("VectorizePerfTest")->getSignal()->connect(boost::bind(&handleVectorizeChanged, _1));
- gSavedSettings.getControl("VectorizeEnable")->getSignal()->connect(boost::bind(&handleVectorizeChanged, _1));
- gSavedSettings.getControl("VectorizeProcessor")->getSignal()->connect(boost::bind(&handleVectorizeChanged, _1));
- gSavedSettings.getControl("VectorizeSkin")->getSignal()->connect(boost::bind(&handleVectorizeChanged, _1));
- gSavedSettings.getControl("EnableVoiceChat")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
- gSavedSettings.getControl("PTTCurrentlyEnabled")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
- gSavedSettings.getControl("PushToTalkButton")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
- gSavedSettings.getControl("PushToTalkToggle")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
- gSavedSettings.getControl("VoiceEarLocation")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
- gSavedSettings.getControl("VoiceInputAudioDevice")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
- gSavedSettings.getControl("VoiceOutputAudioDevice")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
- gSavedSettings.getControl("AudioLevelMic")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
- gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
-}
-
-template <> eControlType get_control_type<U32>(const U32& in, LLSD& out)
-{
- out = (LLSD::Integer)in;
- return TYPE_U32;
-}
-
-template <> eControlType get_control_type<S32>(const S32& in, LLSD& out)
-{
- out = in;
- return TYPE_S32;
-}
-
-template <> eControlType get_control_type<F32>(const F32& in, LLSD& out)
-{
- out = in;
- return TYPE_F32;
-}
-
-template <> eControlType get_control_type<bool> (const bool& in, LLSD& out)
-{
- out = in;
- return TYPE_BOOLEAN;
-}
-/*
-// Yay BOOL, its really an S32.
-template <> eControlType get_control_type<BOOL> (const BOOL& in, LLSD& out)
-{
- out = in;
- return TYPE_BOOLEAN;
-}
-*/
-template <> eControlType get_control_type<std::string>(const std::string& in, LLSD& out)
-{
- out = in;
- return TYPE_STRING;
-}
-
-template <> eControlType get_control_type<LLVector3>(const LLVector3& in, LLSD& out)
-{
- out = in.getValue();
- return TYPE_VEC3;
-}
-
-template <> eControlType get_control_type<LLVector3d>(const LLVector3d& in, LLSD& out)
-{
- out = in.getValue();
- return TYPE_VEC3D;
-}
-
-template <> eControlType get_control_type<LLRect>(const LLRect& in, LLSD& out)
-{
- out = in.getValue();
- return TYPE_RECT;
-}
-
-template <> eControlType get_control_type<LLColor4>(const LLColor4& in, LLSD& out)
-{
- out = in.getValue();
- return TYPE_COL4;
-}
-
-template <> eControlType get_control_type<LLColor3>(const LLColor3& in, LLSD& out)
-{
- out = in.getValue();
- return TYPE_COL3;
-}
-
-template <> eControlType get_control_type<LLColor4U>(const LLColor4U& in, LLSD& out)
-{
- out = in.getValue();
- return TYPE_COL4U;
+ if ( newvalue.asBoolean() )
+ {
+ send_agent_pause();
+ }
+ else
+ {
+ send_agent_resume();
+ }
+ return true;
}
-template <> eControlType get_control_type<LLSD>(const LLSD& in, LLSD& out)
-{
- out = in;
- return TYPE_LLSD;
+bool toggle_show_gesture_button(const LLSD& newvalue)
+{
+ LLBottomTray::getInstance()->showGestureButton(newvalue.asBoolean());
+ return true;
}
+bool toggle_show_move_button(const LLSD& newvalue)
+{
+ LLBottomTray::getInstance()->showMoveButton(newvalue.asBoolean());
+ return true;
+}
+
+bool toggle_show_camera_button(const LLSD& newvalue)
+{
+ LLBottomTray::getInstance()->showCameraButton(newvalue.asBoolean());
+ return true;
+}
+
+bool toggle_show_snapshot_button(const LLSD& newvalue)
+{
+ LLBottomTray::getInstance()->showSnapshotButton(newvalue.asBoolean());
+ return true;
+}
+
+bool toggle_show_navigation_panel(const LLSD& newvalue)
+{
+ LLNavigationBar::getInstance()->showNavigationPanel(newvalue.asBoolean());
+ return true;
+}
+
+bool toggle_show_favorites_panel(const LLSD& newvalue)
+{
+ LLNavigationBar::getInstance()->showFavoritesPanel(newvalue.asBoolean());
+ return true;
+}
+
+bool toggle_show_appearance_editor(const LLSD& newvalue)
+{
+ LLPanelOutfitsInventory::sShowDebugEditor = newvalue.asBoolean();
+ return true;
+}
+
+bool toggle_show_object_render_cost(const LLSD& newvalue)
+{
+ LLFloaterTools::sShowObjectCost = newvalue.asBoolean();
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+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("RenderAnimateTrees")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
+ gSavedSettings.getControl("RenderAvatarVP")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
+ gSavedSettings.getControl("VertexShaderEnable")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
+ gSavedSettings.getControl("RenderUIBuffer")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
+ gSavedSettings.getControl("RenderShadowResolutionScale")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
+ gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
+ gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
+ gSavedSettings.getControl("EnableRippleWater")->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("RenderAvatarMaxVisible")->getSignal()->connect(boost::bind(&handleAvatarMaxVisibleChanged, _2));
+ gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _2));
+ gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _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("ThrottleBandwidthKBPS")->getSignal()->connect(boost::bind(&handleBandwidthChanged, _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("RenderDebugTextureBind")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
+ gSavedSettings.getControl("RenderFastAlpha")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
+ gSavedSettings.getControl("RenderObjectBump")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
+ gSavedSettings.getControl("RenderMaxVBOSize")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
+ gSavedSettings.getControl("RenderUseFBO")->getSignal()->connect(boost::bind(&handleRenderUseFBOChanged, _2));
+ gSavedSettings.getControl("RenderDeferredNoise")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
+ gSavedSettings.getControl("RenderUseImpostors")->getSignal()->connect(boost::bind(&handleRenderUseImpostorsChanged, _2));
+ gSavedSettings.getControl("RenderDebugGL")->getSignal()->connect(boost::bind(&handleRenderDebugGLChanged, _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(&handleSetShaderChanged, _2));
+ gSavedSettings.getControl("RenderDeferredShadow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
+ gSavedSettings.getControl("RenderDeferredGI")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
+ gSavedSettings.getControl("TextureMemory")->getSignal()->connect(boost::bind(&handleVideoMemoryChanged, _2));
+ gSavedSettings.getControl("AuditTexture")->getSignal()->connect(boost::bind(&handleAuditTextureChanged, _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("AudioStreamingMusic")->getSignal()->connect(boost::bind(&handleAudioStreamMusicChanged, _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(&handleRenderUseVBOChanged, _2));
+ gSavedSettings.getControl("WLSkyDetail")->getSignal()->connect(boost::bind(&handleWLSkyDetailChanged, _2));
+ gSavedSettings.getControl("RenderLightingDetail")->getSignal()->connect(boost::bind(&handleRenderLightingDetailChanged, _2));
+ gSavedSettings.getControl("NumpadControl")->getSignal()->connect(boost::bind(&handleNumpadControlChanged, _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("VectorizePerfTest")->getSignal()->connect(boost::bind(&handleVectorizeChanged, _2));
+ gSavedSettings.getControl("VectorizeEnable")->getSignal()->connect(boost::bind(&handleVectorizeChanged, _2));
+ gSavedSettings.getControl("VectorizeProcessor")->getSignal()->connect(boost::bind(&handleVectorizeChanged, _2));
+ gSavedSettings.getControl("VectorizeSkin")->getSignal()->connect(boost::bind(&handleVectorizeChanged, _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("ShowGestureButton")->getSignal()->connect(boost::bind(&toggle_show_gesture_button, _2));
+ gSavedSettings.getControl("ShowMoveButton")->getSignal()->connect(boost::bind(&toggle_show_move_button, _2));
+ gSavedSettings.getControl("ShowCameraButton")->getSignal()->connect(boost::bind(&toggle_show_camera_button, _2));
+ gSavedSettings.getControl("ShowSnapshotButton")->getSignal()->connect(boost::bind(&toggle_show_snapshot_button, _2));
+ gSavedSettings.getControl("ShowNavbarNavigationPanel")->getSignal()->connect(boost::bind(&toggle_show_navigation_panel, _2));
+ gSavedSettings.getControl("ShowNavbarFavoritesPanel")->getSignal()->connect(boost::bind(&toggle_show_favorites_panel, _2));
+ gSavedSettings.getControl("ShowDebugAppearanceEditor")->getSignal()->connect(boost::bind(&toggle_show_appearance_editor, _2));
+ gSavedSettings.getControl("ShowObjectRenderingCost")->getSignal()->connect(boost::bind(&toggle_show_object_render_cost, _2));
+}
#if TEST_CACHED_CONTROL
@@ -670,7 +702,7 @@ static LLCachedControl<std::string> test_BrowserHomePage("BrowserHomePage", "hah
void test_cached_control()
{
-#define TEST_LLCC(T, V) if((T)mySetting_##T != V) llerrs << "Fail "#T << llendl
+#define do { TEST_LLCC(T, V) if((T)mySetting_##T != V) llerrs << "Fail "#T << llendl; } while(0)
TEST_LLCC(U32, 666);
TEST_LLCC(S32, (S32)-666);
TEST_LLCC(F32, (F32)-666.666);
diff --git a/indra/newview/llviewercontrol.h b/indra/newview/llviewercontrol.h
index d0dc80cb9a..9b4e80cae0 100644
--- a/indra/newview/llviewercontrol.h
+++ b/indra/newview/llviewercontrol.h
@@ -43,21 +43,20 @@
extern BOOL gHackGodmode;
#endif
+bool toggle_show_navigation_panel(const LLSD& newvalue);
+bool toggle_show_favorites_panel(const LLSD& newvalue);
+
// These functions found in llcontroldef.cpp *TODO: clean this up!
//setting variables are declared in this function
void settings_setup_listeners();
-extern std::map<std::string, LLControlGroup*> gSettings;
-
// for the graphics settings
void create_graphics_group(LLControlGroup& group);
// saved at end of session
extern LLControlGroup gSavedSettings;
extern LLControlGroup gSavedPerAccountSettings;
-
-// Read-only
-extern LLControlGroup gColors;
+extern LLControlGroup gWarningSettings;
// Saved at end of session
extern LLControlGroup gCrashSettings;
@@ -66,114 +65,5 @@ extern LLControlGroup gCrashSettings;
extern std::string gLastRunVersion;
extern std::string gCurrentVersion;
-//! Helper function for LLCachedControl
-template <class T>
-eControlType get_control_type(const T& in, LLSD& out)
-{
- llerrs << "Usupported control type: " << typeid(T).name() << "." << llendl;
- return TYPE_COUNT;
-}
-
-//! Publish/Subscribe object to interact with LLControlGroups.
-
-//! An LLCachedControl instance to connect to a LLControlVariable
-//! without have to manually create and bind a listener to a local
-//! object.
-template <class T>
-class LLCachedControl
-{
- T mCachedValue;
- LLPointer<LLControlVariable> mControl;
- boost::signals::connection mConnection;
-
-public:
- LLCachedControl(const std::string& name,
- const T& default_value,
- const std::string& comment = "Declared In Code")
- {
- mControl = gSavedSettings.getControl(name);
- if(mControl.isNull())
- {
- declareTypedControl(gSavedSettings, name, default_value, comment);
- mControl = gSavedSettings.getControl(name);
- if(mControl.isNull())
- {
- llerrs << "The control could not be created!!!" << llendl;
- }
-
- mCachedValue = default_value;
- }
- else
- {
- mCachedValue = (const T&)mControl->getValue();
- }
-
- // Add a listener to the controls signal...
- mControl->getSignal()->connect(
- boost::bind(&LLCachedControl<T>::handleValueChange, this, _1)
- );
- }
-
- ~LLCachedControl()
- {
- if(mConnection.connected())
- {
- mConnection.disconnect();
- }
- }
-
- LLCachedControl& operator =(const T& newvalue)
- {
- setTypeValue(*mControl, newvalue);
- }
-
- operator const T&() { return mCachedValue; }
-
-private:
- void declareTypedControl(LLControlGroup& group,
- const std::string& name,
- const T& default_value,
- const std::string& comment)
- {
- LLSD init_value;
- eControlType type = get_control_type<T>(default_value, init_value);
- if(type < TYPE_COUNT)
- {
- group.declareControl(name, type, init_value, comment, FALSE);
- }
- }
-
- bool handleValueChange(const LLSD& newvalue)
- {
- mCachedValue = (const T &)newvalue;
- return true;
- }
-
- void setTypeValue(LLControlVariable& c, const T& v)
- {
- // Implicit conversion from T to LLSD...
- c.set(v);
- }
-};
-
-template <> eControlType get_control_type<U32>(const U32& in, LLSD& out);
-template <> eControlType get_control_type<S32>(const S32& in, LLSD& out);
-template <> eControlType get_control_type<F32>(const F32& in, LLSD& out);
-template <> eControlType get_control_type<bool> (const bool& in, LLSD& out);
-// Yay BOOL, its really an S32.
-//template <> eControlType get_control_type<BOOL> (const BOOL& in, LLSD& out)
-template <> eControlType get_control_type<std::string>(const std::string& in, LLSD& out);
-template <> eControlType get_control_type<LLVector3>(const LLVector3& in, LLSD& out);
-template <> eControlType get_control_type<LLVector3d>(const LLVector3d& in, LLSD& out);
-template <> eControlType get_control_type<LLRect>(const LLRect& in, LLSD& out);
-template <> eControlType get_control_type<LLColor4>(const LLColor4& in, LLSD& out);
-template <> eControlType get_control_type<LLColor3>(const LLColor3& in, LLSD& out);
-template <> eControlType get_control_type<LLColor4U>(const LLColor4U& in, LLSD& out);
-template <> eControlType get_control_type<LLSD>(const LLSD& in, LLSD& out);
-
-//#define TEST_CACHED_CONTROL 1
-#ifdef TEST_CACHED_CONTROL
-void test_cached_control();
-#endif // TEST_CACHED_CONTROL
#endif // LL_LLVIEWERCONTROL_H
diff --git a/indra/newview/llviewercontrollistener.cpp b/indra/newview/llviewercontrollistener.cpp
new file mode 100644
index 0000000000..0b9db1b906
--- /dev/null
+++ b/indra/newview/llviewercontrollistener.cpp
@@ -0,0 +1,112 @@
+/**
+ * @file llviewercontrollistener.cpp
+ * @author Brad Kittenbrink
+ * @date 2009-07-09
+ * @brief Implementation for llviewercontrollistener.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llviewercontrollistener.h"
+
+#include "llviewercontrol.h"
+
+LLViewerControlListener gSavedSettingsListener;
+
+LLViewerControlListener::LLViewerControlListener()
+ : LLEventAPI("LLViewerControl",
+ "LLViewerControl listener: set, toggle or set default for various controls",
+ "group")
+{
+ add("Global",
+ "Set gSavedSettings control [\"key\"] to value [\"value\"]",
+ boost::bind(&LLViewerControlListener::set, &gSavedSettings, _1));
+ add("PerAccount",
+ "Set gSavedPerAccountSettings control [\"key\"] to value [\"value\"]",
+ boost::bind(&LLViewerControlListener::set, &gSavedPerAccountSettings, _1));
+ add("Warning",
+ "Set gWarningSettings control [\"key\"] to value [\"value\"]",
+ boost::bind(&LLViewerControlListener::set, &gWarningSettings, _1));
+ add("Crash",
+ "Set gCrashSettings control [\"key\"] to value [\"value\"]",
+ boost::bind(&LLViewerControlListener::set, &gCrashSettings, _1));
+
+#if 0
+ add(/*"toggleControl",*/ "Global", boost::bind(&LLViewerControlListener::toggleControl, &gSavedSettings, _1));
+ add(/*"toggleControl",*/ "PerAccount", boost::bind(&LLViewerControlListener::toggleControl, &gSavedPerAccountSettings, _1));
+ add(/*"toggleControl",*/ "Warning", boost::bind(&LLViewerControlListener::toggleControl, &gWarningSettings, _1));
+ add(/*"toggleControl",*/ "Crash", boost::bind(&LLViewerControlListener::toggleControl, &gCrashSettings, _1));
+
+ add(/*"setDefault",*/ "Global", boost::bind(&LLViewerControlListener::setDefault, &gSavedSettings, _1));
+ add(/*"setDefault",*/ "PerAccount", boost::bind(&LLViewerControlListener::setDefault, &gSavedPerAccountSettings, _1));
+ add(/*"setDefault",*/ "Warning", boost::bind(&LLViewerControlListener::setDefault, &gWarningSettings, _1));
+ add(/*"setDefault",*/ "Crash", boost::bind(&LLViewerControlListener::setDefault, &gCrashSettings, _1));
+#endif // 0
+}
+
+//static
+void LLViewerControlListener::set(LLControlGroup * controls, LLSD const & event_data)
+{
+ if(event_data.has("key"))
+ {
+ std::string key(event_data["key"]);
+
+ if(controls->controlExists(key))
+ {
+ controls->setUntypedValue(key, event_data["value"]);
+ }
+ else
+ {
+ llwarns << "requested unknown control: \"" << key << '\"' << llendl;
+ }
+ }
+}
+
+//static
+void LLViewerControlListener::toggleControl(LLControlGroup * controls, LLSD const & event_data)
+{
+ if(event_data.has("key"))
+ {
+ std::string key(event_data["key"]);
+
+ if(controls->controlExists(key))
+ {
+ LLControlVariable * control = controls->getControl(key);
+ if(control->isType(TYPE_BOOLEAN))
+ {
+ control->set(!control->get().asBoolean());
+ }
+ else
+ {
+ llwarns << "requested toggle of non-boolean control: \"" << key << "\", type is " << control->type() << llendl;
+ }
+ }
+ else
+ {
+ llwarns << "requested unknown control: \"" << key << '\"' << llendl;
+ }
+ }
+}
+
+//static
+void LLViewerControlListener::setDefault(LLControlGroup * controls, LLSD const & event_data)
+{
+ if(event_data.has("key"))
+ {
+ std::string key(event_data["key"]);
+
+ if(controls->controlExists(key))
+ {
+ LLControlVariable * control = controls->getControl(key);
+ control->resetToDefault();
+ }
+ else
+ {
+ llwarns << "requested unknown control: \"" << key << '\"' << llendl;
+ }
+ }
+}
diff --git a/indra/newview/llviewercontrollistener.h b/indra/newview/llviewercontrollistener.h
new file mode 100644
index 0000000000..88afbb871d
--- /dev/null
+++ b/indra/newview/llviewercontrollistener.h
@@ -0,0 +1,33 @@
+/**
+ * @file llviewercontrollistener.h
+ * @author Brad Kittenbrink
+ * @date 2009-07-09
+ * @brief Event API for subset of LLViewerControl methods
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLVIEWERCONTROLLISTENER_H
+#define LL_LLVIEWERCONTROLLISTENER_H
+
+#include "lleventapi.h"
+
+class LLControlGroup;
+class LLSD;
+
+class LLViewerControlListener : public LLEventAPI
+{
+public:
+ LLViewerControlListener();
+
+private:
+ static void set(LLControlGroup *controls, LLSD const & event_data);
+ static void toggleControl(LLControlGroup *controls, LLSD const & event_data);
+ static void setDefault(LLControlGroup *controls, LLSD const & event_data);
+};
+
+extern LLViewerControlListener gSavedSettingsListener;
+
+#endif // LL_LLVIEWERCONTROLLISTENER_H
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 977582ba24..ba256d70e8 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -45,11 +45,10 @@
#include "lldynamictexture.h"
#include "lldrawpoolalpha.h"
#include "llfeaturemanager.h"
-#include "llfirstuse.h"
-#include "llframestats.h"
+//#include "llfirstuse.h"
#include "llhudmanager.h"
#include "llimagebmp.h"
-#include "llimagegl.h"
+#include "llmemory.h"
#include "llselectmgr.h"
#include "llsky.h"
#include "llstartup.h"
@@ -58,12 +57,13 @@
#include "lltooldraganddrop.h"
#include "lltoolpie.h"
#include "lltracker.h"
+#include "lltrans.h"
#include "llui.h"
#include "llviewercamera.h"
#include "llviewerobjectlist.h"
#include "llviewerparcelmgr.h"
#include "llviewerwindow.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "llvograss.h"
#include "llworld.h"
#include "pipeline.h"
@@ -73,7 +73,7 @@
#include "llviewershadermgr.h"
#include "llfasttimer.h"
#include "llfloatertools.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llfocusmgr.h"
#include "llcubemap.h"
#include "llviewerregion.h"
@@ -83,9 +83,9 @@
#include "llwaterparammanager.h"
#include "llpostprocess.h"
-extern LLPointer<LLImageGL> gStartImageGL;
+extern LLPointer<LLViewerTexture> gStartTexture;
-LLPointer<LLImageGL> gDisconnectedImagep = NULL;
+LLPointer<LLViewerTexture> gDisconnectedImagep = NULL;
// used to toggle renderer back on after teleport
const F32 TELEPORT_RENDER_DELAY = 20.f; // Max time a teleport is allowed to take before we raise the curtain
@@ -125,6 +125,11 @@ void display_startup()
return;
}
+ gPipeline.updateGL();
+
+ // Update images?
+ //gImageList.updateImages(0.01f);
+
LLGLSDefault gls_default;
// Required for HTML update in login screen
@@ -135,7 +140,7 @@ void display_startup()
if (frame_count++ > 1) // make sure we have rendered a frame first
{
- LLDynamicTexture::updateAllInstances();
+ LLViewerDynamicTexture::updateAllInstances();
}
LLGLState::checkStates();
@@ -163,6 +168,7 @@ void display_startup()
void display_update_camera()
{
+ LLMemType mt_uc(LLMemType::MTYPE_DISPLAY_UPDATE_CAMERA);
llpushcallstacks ;
// TODO: cut draw distance down if customizing avatar?
// TODO: cut draw distance on per-parcel basis?
@@ -199,17 +205,24 @@ void display_stats()
F32 mem_log_freq = gSavedSettings.getF32("MemoryLogFrequency");
if (mem_log_freq > 0.f && gRecentMemoryTime.getElapsedTimeF32() >= mem_log_freq)
{
- gMemoryAllocated = getCurrentRSS();
+ gMemoryAllocated = LLMemory::getCurrentRSS();
U32 memory = (U32)(gMemoryAllocated / (1024*1024));
llinfos << llformat("MEMORY: %d MB", memory) << llendl;
gRecentMemoryTime.reset();
}
}
+static LLFastTimer::DeclareTimer FTM_PICK("Picking");
+static LLFastTimer::DeclareTimer FTM_RENDER("Render", true);
+static LLFastTimer::DeclareTimer FTM_UPDATE_SKY("Update Sky");
+static LLFastTimer::DeclareTimer FTM_UPDATE_TEXTURES("Update Textures");
+static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE("Update Images");
+
// Paint the display!
void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER);
+ LLMemType mt_render(LLMemType::MTYPE_RENDER);
+ LLFastTimer t(FTM_RENDER);
if (LLPipeline::sRenderFrameTest)
{
@@ -226,8 +239,12 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLGLState::checkStates();
LLGLState::checkTextureChannels();
+ stop_glerror();
+
gPipeline.disableLights();
+ stop_glerror();
+
// Don't draw if the window is hidden or minimized.
// In fact, must explicitly check the minimized state before drawing.
// Attempting to draw into a minimized window causes a GL error. JC
@@ -238,18 +255,21 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
// Clean up memory the pools may have allocated
if (rebuild)
{
- gFrameStats.start(LLFrameStats::REBUILD);
+ stop_glerror();
gPipeline.rebuildPools();
+ stop_glerror();
}
+ stop_glerror();
gViewerWindow->returnEmptyPicks();
+ stop_glerror();
return;
}
gViewerWindow->checkSettings();
{
- LLFastTimer ftm(LLFastTimer::FTM_PICK);
+ LLFastTimer ftm(FTM_PICK);
LLAppViewer::instance()->pingMainloopTimeout("Display:Pick");
gViewerWindow->performPick();
}
@@ -299,13 +319,12 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
//
LLAppViewer::instance()->pingMainloopTimeout("Display:TextureStats");
- gFrameStats.start(LLFrameStats::UPDATE_TEX_STATS);
stop_glerror();
LLImageGL::updateStats(gFrameTimeSeconds);
- LLVOAvatar::sRenderName = gSavedSettings.getS32("RenderName");
- LLVOAvatar::sRenderGroupTitles = !gSavedSettings.getBOOL("RenderHideGroupTitleAll");
+ LLVOAvatar::sRenderName = gSavedSettings.getS32("AvatarNameTagMode");
+ LLVOAvatar::sRenderGroupTitles = (gSavedSettings.getBOOL("RenderShowGroupTitleAll") && gSavedSettings.getS32("AvatarNameTagMode"));
gPipeline.mBackfaceCull = TRUE;
gFrameCount++;
@@ -369,12 +388,12 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
case LLAgent::TELEPORT_START_ARRIVAL:
// Transition to ARRIVING. Viewer has received avatar update, etc., from destination simulator
gTeleportArrivalTimer.reset();
- gViewerWindow->setProgressCancelButtonVisible(FALSE, std::string("Cancel")); //TODO: Translate
+ gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel"));
gViewerWindow->setProgressPercent(75.f);
gAgent.setTeleportState( LLAgent::TELEPORT_ARRIVING );
gAgent.setTeleportMessage(
LLAgent::sTeleportProgressMessages["arriving"]);
- gImageList.mForceResetTextureStats = TRUE;
+ gTextureList.mForceResetTextureStats = TRUE;
gAgent.resetView(TRUE, TRUE);
break;
@@ -385,10 +404,10 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
if( arrival_fraction > 1.f )
{
arrival_fraction = 1.f;
- LLFirstUse::useTeleport();
+ //LLFirstUse::useTeleport();
gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
}
- gViewerWindow->setProgressCancelButtonVisible(FALSE, std::string("Cancel")); //TODO: Translate
+ gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel"));
gViewerWindow->setProgressPercent( arrival_fraction * 25.f + 75.f);
gViewerWindow->setProgressString(message);
}
@@ -464,7 +483,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
{
LLAppViewer::instance()->pingMainloopTimeout("Display:Disconnected");
render_ui();
- render_disconnected_background();
}
//////////////////////////
@@ -496,19 +514,20 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES))
{
LLAppViewer::instance()->pingMainloopTimeout("Display:DynamicTextures");
- LLFastTimer t(LLFastTimer::FTM_UPDATE_TEXTURES);
- if (LLDynamicTexture::updateAllInstances())
+ LLFastTimer t(FTM_UPDATE_TEXTURES);
+ if (LLViewerDynamicTexture::updateAllInstances())
{
gGL.setColorMask(true, true);
glClear(GL_DEPTH_BUFFER_BIT);
}
}
- gViewerWindow->setupViewport();
+ gViewerWindow->setup3DViewport();
gPipeline.resetFrameStats(); // Reset per-frame statistics.
if (!gDisconnected)
{
+ LLMemType mt_du(LLMemType::MTYPE_DISPLAY_UPDATE);
LLAppViewer::instance()->pingMainloopTimeout("Display:Update");
if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
{ //don't draw hud objects in this frame
@@ -528,17 +547,24 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
stop_glerror();
// *TODO: merge these two methods
- LLHUDManager::getInstance()->updateEffects();
- LLHUDObject::updateAll();
- stop_glerror();
-
- gFrameStats.start(LLFrameStats::UPDATE_GEOM);
- const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time
- gPipeline.createObjects(max_geom_update_time);
- gPipeline.updateGeom(max_geom_update_time);
+ {
+ LLMemType mt_uh(LLMemType::MTYPE_DISPLAY_UPDATE_HUD);
+ LLHUDManager::getInstance()->updateEffects();
+ LLHUDObject::updateAll();
+ stop_glerror();
+ }
+
+ {
+ LLMemType mt_ug(LLMemType::MTYPE_DISPLAY_UPDATE_GEOM);
+ const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time
+ gPipeline.createObjects(max_geom_update_time);
+ gPipeline.updateGeom(max_geom_update_time);
+ stop_glerror();
+ }
+
+ gPipeline.updateGL();
stop_glerror();
-
- gFrameStats.start(LLFrameStats::UPDATE_CULL);
+
S32 water_clip = 0;
if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) &&
gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER))
@@ -552,7 +578,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
water_clip = 1;
}
}
-
+
LLAppViewer::instance()->pingMainloopTimeout("Display:Cull");
//Increment drawable frame counter
@@ -587,6 +613,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLGLState::checkClientArrays();
static LLCullResult result;
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
gPipeline.updateCull(*LLViewerCamera::getInstance(), result, water_clip);
stop_glerror();
@@ -601,8 +628,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLAppViewer::instance()->pingMainloopTimeout("Display:Swap");
{
+ LLMemType mt_ds(LLMemType::MTYPE_DISPLAY_SWAP);
{
- LLFastTimer ftm(LLFastTimer::FTM_CLIENT_COPY);
+ LLFastTimer ftm(FTM_CLIENT_COPY);
LLVertexBuffer::clientCopy(0.016);
}
@@ -627,6 +655,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
gPipeline.generateSunShadow(*LLViewerCamera::getInstance());
}
+ LLVertexBuffer::unbind();
+
LLGLState::checkStates();
LLGLState::checkTextureChannels();
LLGLState::checkClientArrays();
@@ -643,7 +673,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
glLoadMatrixf(proj.m);
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(mod.m);
- gViewerWindow->setupViewport();
+ gViewerWindow->setup3DViewport();
LLGLState::checkStates();
LLGLState::checkTextureChannels();
@@ -655,8 +685,10 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
if (!for_snapshot)
{
+ LLMemType mt_gw(LLMemType::MTYPE_DISPLAY_GEN_REFLECTION);
LLAppViewer::instance()->pingMainloopTimeout("Display:Imagery");
gPipeline.generateWaterReflection(*LLViewerCamera::getInstance());
+ gPipeline.generateHighlight(*LLViewerCamera::getInstance());
}
//////////////////////////////////////
@@ -669,18 +701,22 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLAppViewer::instance()->pingMainloopTimeout("Display:UpdateImages");
LLError::LLCallStacks::clear() ;
llpushcallstacks ;
- gFrameStats.start(LLFrameStats::IMAGE_UPDATE);
{
- LLFastTimer t(LLFastTimer::FTM_IMAGE_UPDATE);
+ LLMemType mt_iu(LLMemType::MTYPE_DISPLAY_IMAGE_UPDATE);
+ LLFastTimer t(FTM_IMAGE_UPDATE);
- LLViewerImage::updateClass(LLViewerCamera::getInstance()->getVelocityStat()->getMean(),
+ LLViewerTexture::updateClass(LLViewerCamera::getInstance()->getVelocityStat()->getMean(),
LLViewerCamera::getInstance()->getAngularVelocityStat()->getMean());
- gBumpImageList.updateImages(); // must be called before gImageList version so that it's textures are thrown out first.
+ gBumpImageList.updateImages(); // must be called before gTextureList version so that it's textures are thrown out first.
+
+ F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds; // 50 ms/second decode time
+ max_image_decode_time = llclamp(max_image_decode_time, 0.002f, 0.005f ); // min 2ms/frame, max 5ms/frame)
+ gTextureList.updateImages(max_image_decode_time);
- const F32 max_image_decode_time = llmin(0.005f, 0.005f*10.f*gFrameIntervalSeconds); // 50 ms/second decode time (no more than 5ms/frame)
- gImageList.updateImages(max_image_decode_time);
+ //remove dead textures from GL
+ LLImageGL::deleteDeadTextures();
stop_glerror();
}
llpushcallstacks ;
@@ -694,7 +730,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
//
LLAppViewer::instance()->pingMainloopTimeout("Display:StateSort");
{
- gFrameStats.start(LLFrameStats::STATE_SORT);
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+ LLMemType mt_ss(LLMemType::MTYPE_DISPLAY_STATE_SORT);
gPipeline.stateSort(*LLViewerCamera::getInstance(), result);
stop_glerror();
@@ -705,7 +742,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
// rebuildPools
//
//
- gFrameStats.start(LLFrameStats::REBUILD);
gPipeline.rebuildPools();
stop_glerror();
}
@@ -714,8 +750,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLPipeline::sUseOcclusion = occlusion;
{
+ LLMemType mt_ds(LLMemType::MTYPE_DISPLAY_SKY);
LLAppViewer::instance()->pingMainloopTimeout("Display:Sky");
- LLFastTimer t(LLFastTimer::FTM_UPDATE_SKY);
+ LLFastTimer t(FTM_UPDATE_SKY);
gSky.updateSky();
}
@@ -741,13 +778,13 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
// glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
// glLoadIdentity();
- // LLRect floater_rect = frontmost_floaterp->getScreenRect();
+ // LLRect floater_rect = frontmost_floaterp->calcScreenRect();
// // deflate by one pixel so rounding errors don't occlude outside of floater extents
// floater_rect.stretch(-1);
- // LLRectf floater_3d_rect((F32)floater_rect.mLeft / (F32)gViewerWindow->getWindowWidth(),
- // (F32)floater_rect.mTop / (F32)gViewerWindow->getWindowHeight(),
- // (F32)floater_rect.mRight / (F32)gViewerWindow->getWindowWidth(),
- // (F32)floater_rect.mBottom / (F32)gViewerWindow->getWindowHeight());
+ // LLRectf floater_3d_rect((F32)floater_rect.mLeft / (F32)gViewerWindow->getWindowWidthScaled(),
+ // (F32)floater_rect.mTop / (F32)gViewerWindow->getWindowHeightScaled(),
+ // (F32)floater_rect.mRight / (F32)gViewerWindow->getWindowWidthScaled(),
+ // (F32)floater_rect.mBottom / (F32)gViewerWindow->getWindowHeightScaled());
// floater_3d_rect.translate(-0.5f, -0.5f);
// glTranslatef(0.f, 0.f, -LLViewerCamera::getInstance()->getNear());
// glScalef(LLViewerCamera::getInstance()->getNear() * LLViewerCamera::getInstance()->getAspect() / sinf(LLViewerCamera::getInstance()->getView()), LLViewerCamera::getInstance()->getNear() / sinf(LLViewerCamera::getInstance()->getView()), 1.f);
@@ -776,6 +813,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
{
gPipeline.mDeferredScreen.bindTarget();
+ glClearColor(0,0,0,0);
gPipeline.mDeferredScreen.clear();
}
else
@@ -792,7 +830,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
if (!(LLAppViewer::instance()->logoutRequestSent() && LLAppViewer::instance()->hasSavedFinalSnapshot())
&& !gRestoreGL)
{
-
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+ LLMemType mt_rg(LLMemType::MTYPE_DISPLAY_RENDER_GEOM);
gGL.setColorMask(true, false);
if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
{
@@ -810,6 +849,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
for (U32 i = 0; i < 16; i++)
{
gGLLastModelView[i] = gGLModelView[i];
+ gGLLastProjection[i] = gGLProjection[i];
}
stop_glerror();
}
@@ -818,6 +858,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
if (to_texture)
{
+ LLMemType mt_rf(LLMemType::MTYPE_DISPLAY_RENDER_FLUSH);
if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
{
gPipeline.mDeferredScreen.flush();
@@ -832,7 +873,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
/// and then display it again with compositor effects.
/// Using render to texture would be faster/better, but I don't have a
/// grasp of their full display stack just yet.
- // gPostProcess->apply(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight());
+ // gPostProcess->apply(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
{
@@ -844,16 +885,17 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI");
if (!for_snapshot)
{
- gFrameStats.start(LLFrameStats::RENDER_UI);
+ LLFastTimer t(FTM_RENDER_UI);
render_ui();
}
+ gPipeline.rebuildGroups();
+
LLSpatialGroup::sNoDelete = FALSE;
}
-
+
LLAppViewer::instance()->pingMainloopTimeout("Display:FrameStats");
- gFrameStats.start(LLFrameStats::MISC_END);
stop_glerror();
if (LLPipeline::sRenderFrameTest)
@@ -869,6 +911,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
void render_hud_attachments()
{
+ LLMemType mt_ra(LLMemType::MTYPE_DISPLAY_RENDER_ATTACHMENTS);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
@@ -922,6 +965,7 @@ void render_hud_attachments()
static LLCullResult result;
LLSpatialGroup::sNoDelete = TRUE;
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
gPipeline.updateCull(hud_cam, result);
gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_BUMP);
@@ -929,6 +973,15 @@ void render_hud_attachments()
gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME);
gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA);
gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_BUMP);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_SHINY);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISIBLE);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY);
gPipeline.stateSort(hud_cam, result);
@@ -955,67 +1008,58 @@ void render_hud_attachments()
glh_set_current_modelview(current_mod);
}
-BOOL setup_hud_matrices()
+LLRect get_whole_screen_region()
{
- LLRect whole_screen = gViewerWindow->getVirtualWindowRect();
-
+ LLRect whole_screen = gViewerWindow->getWorldViewRectScaled();
+
// apply camera zoom transform (for high res screenshots)
F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor();
S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion();
if (zoom_factor > 1.f)
{
S32 num_horizontal_tiles = llceil(zoom_factor);
- S32 tile_width = llround((F32)gViewerWindow->getWindowWidth() / zoom_factor);
- S32 tile_height = llround((F32)gViewerWindow->getWindowHeight() / zoom_factor);
+ S32 tile_width = llround((F32)gViewerWindow->getWorldViewWidthScaled() / zoom_factor);
+ S32 tile_height = llround((F32)gViewerWindow->getWorldViewHeightScaled() / zoom_factor);
int tile_y = sub_region / num_horizontal_tiles;
int tile_x = sub_region - (tile_y * num_horizontal_tiles);
glh::matrix4f mat;
-
- whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWindowHeight() - (tile_y * tile_height), tile_width, tile_height);
+
+ whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWorldViewHeightScaled() - (tile_y * tile_height), tile_width, tile_height);
}
-
- return setup_hud_matrices(whole_screen);
+ return whole_screen;
}
-BOOL setup_hud_matrices(const LLRect& screen_region)
+bool get_hud_matrices(const LLRect& screen_region, glh::matrix4f &proj, glh::matrix4f &model)
{
LLVOAvatar* my_avatarp = gAgent.getAvatarObject();
if (my_avatarp && my_avatarp->hasHUDAttachment())
{
F32 zoom_level = gAgent.mHUDCurZoom;
LLBBox hud_bbox = my_avatarp->getHUDBBox();
-
- // set up transform to keep HUD objects in front of camera
- glMatrixMode(GL_PROJECTION);
+
F32 hud_depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
- glh::matrix4f proj = gl_ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, hud_depth);
+ proj = gl_ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, hud_depth);
proj.element(2,2) = -0.01f;
-
+
F32 aspect_ratio = LLViewerCamera::getInstance()->getAspect();
-
+
glh::matrix4f mat;
- F32 scale_x = (F32)gViewerWindow->getWindowWidth() / (F32)screen_region.getWidth();
- F32 scale_y = (F32)gViewerWindow->getWindowHeight() / (F32)screen_region.getHeight();
+ F32 scale_x = (F32)gViewerWindow->getWorldViewWidthScaled() / (F32)screen_region.getWidth();
+ F32 scale_y = (F32)gViewerWindow->getWorldViewHeightScaled() / (F32)screen_region.getHeight();
mat.set_scale(glh::vec3f(scale_x, scale_y, 1.f));
mat.set_translate(
- glh::vec3f(clamp_rescale((F32)screen_region.getCenterX(), 0.f, (F32)gViewerWindow->getWindowWidth(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio),
- clamp_rescale((F32)screen_region.getCenterY(), 0.f, (F32)gViewerWindow->getWindowHeight(), 0.5f * scale_y, -0.5f * scale_y),
- 0.f));
+ glh::vec3f(clamp_rescale((F32)screen_region.getCenterX(), 0.f, (F32)gViewerWindow->getWorldViewWidthScaled(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio),
+ clamp_rescale((F32)screen_region.getCenterY(), 0.f, (F32)gViewerWindow->getWorldViewHeightScaled(), 0.5f * scale_y, -0.5f * scale_y),
+ 0.f));
proj *= mat;
-
- glLoadMatrixf(proj.m);
- glh_set_current_projection(proj);
-
- glMatrixMode(GL_MODELVIEW);
- glh::matrix4f model((GLfloat*) OGL_TO_CFR_ROTATION);
+
+ glh::matrix4f tmp_model((GLfloat*) OGL_TO_CFR_ROTATION);
mat.set_scale(glh::vec3f(zoom_level, zoom_level, zoom_level));
mat.set_translate(glh::vec3f(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f));
-
- model *= mat;
- glLoadMatrixf(model.m);
- glh_set_current_modelview(model);
-
+
+ tmp_model *= mat;
+ model = tmp_model;
return TRUE;
}
else
@@ -1024,9 +1068,40 @@ BOOL setup_hud_matrices(const LLRect& screen_region)
}
}
+bool get_hud_matrices(glh::matrix4f &proj, glh::matrix4f &model)
+{
+ LLRect whole_screen = get_whole_screen_region();
+ return get_hud_matrices(whole_screen, proj, model);
+}
+
+BOOL setup_hud_matrices()
+{
+ LLRect whole_screen = get_whole_screen_region();
+ return setup_hud_matrices(whole_screen);
+}
+
+BOOL setup_hud_matrices(const LLRect& screen_region)
+{
+ glh::matrix4f proj, model;
+ bool result = get_hud_matrices(screen_region, proj, model);
+ if (!result) return result;
+
+ // set up transform to keep HUD objects in front of camera
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(proj.m);
+ glh_set_current_projection(proj);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(model.m);
+ glh_set_current_modelview(model);
+ return TRUE;
+}
+
+static LLFastTimer::DeclareTimer FTM_SWAP("Swap");
void render_ui(F32 zoom_factor, int subfield)
{
+ LLMemType mt_ru(LLMemType::MTYPE_DISPLAY_RENDER_UI);
LLGLState::checkStates();
glPushMatrix();
@@ -1058,13 +1133,17 @@ void render_ui(F32 zoom_factor, int subfield)
gGL.color4f(1,1,1,1);
if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_UI);
+ LLFastTimer t(FTM_RENDER_UI);
if (!gDisconnected)
{
render_ui_3d();
LLGLState::checkStates();
}
+ else
+ {
+ render_disconnected_background();
+ }
render_ui_2d();
LLGLState::checkStates();
@@ -1085,7 +1164,7 @@ void render_ui(F32 zoom_factor, int subfield)
if (gDisplaySwapBuffers)
{
- LLFastTimer t(LLFastTimer::FTM_SWAP);
+ LLFastTimer t(FTM_SWAP);
gViewerWindow->mWindow->swapBuffers();
}
gDisplaySwapBuffers = TRUE;
@@ -1213,8 +1292,8 @@ void render_ui_2d()
int pos_y = sub_region / llceil(zoom_factor);
int pos_x = sub_region - (pos_y*llceil(zoom_factor));
// offset for this tile
- LLFontGL::sCurOrigin.mX -= llround((F32)gViewerWindow->getWindowWidth() * (F32)pos_x / zoom_factor);
- LLFontGL::sCurOrigin.mY -= llround((F32)gViewerWindow->getWindowHeight() * (F32)pos_y / zoom_factor);
+ LLFontGL::sCurOrigin.mX -= llround((F32)gViewerWindow->getWindowWidthScaled() * (F32)pos_x / zoom_factor);
+ LLFontGL::sCurOrigin.mY -= llround((F32)gViewerWindow->getWindowHeightScaled() * (F32)pos_y / zoom_factor);
}
stop_glerror();
@@ -1224,8 +1303,8 @@ void render_ui_2d()
if (gAgent.getAvatarObject() && gAgent.mHUDCurZoom < 0.98f)
{
glPushMatrix();
- S32 half_width = (gViewerWindow->getWindowWidth() / 2);
- S32 half_height = (gViewerWindow->getWindowHeight() / 2);
+ S32 half_width = (gViewerWindow->getWorldViewWidthScaled() / 2);
+ S32 half_height = (gViewerWindow->getWorldViewHeightScaled() / 2);
glScalef(LLUI::sGLScaleFactor.mV[0], LLUI::sGLScaleFactor.mV[1], 1.f);
glTranslatef((F32)half_width, (F32)half_height, 0.f);
F32 zoom = gAgent.mHUDCurZoom;
@@ -1235,12 +1314,74 @@ void render_ui_2d()
glPopMatrix();
stop_glerror();
}
- gViewerWindow->draw();
- if (gDebugSelect)
+
+
+ if (gSavedSettings.getBOOL("RenderUIBuffer"))
+ {
+ if (LLUI::sDirty)
+ {
+ LLUI::sDirty = FALSE;
+ LLRect t_rect;
+
+ gPipeline.mUIScreen.bindTarget();
+ gGL.setColorMask(true, true);
+ {
+ static const S32 pad = 8;
+
+ LLUI::sDirtyRect.mLeft -= pad;
+ LLUI::sDirtyRect.mRight += pad;
+ LLUI::sDirtyRect.mBottom -= pad;
+ LLUI::sDirtyRect.mTop += pad;
+
+ LLGLEnable scissor(GL_SCISSOR_TEST);
+ static LLRect last_rect = LLUI::sDirtyRect;
+
+ //union with last rect to avoid mouse poop
+ last_rect.unionWith(LLUI::sDirtyRect);
+
+ t_rect = LLUI::sDirtyRect;
+ LLUI::sDirtyRect = last_rect;
+ last_rect = t_rect;
+
+ last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::sGLScaleFactor.mV[0]);
+ last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::sGLScaleFactor.mV[0]);
+ last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::sGLScaleFactor.mV[1]);
+ last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::sGLScaleFactor.mV[1]);
+
+ LLRect clip_rect(last_rect);
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ gViewerWindow->draw();
+ }
+
+ gPipeline.mUIScreen.flush();
+ gGL.setColorMask(true, false);
+
+ LLUI::sDirtyRect = t_rect;
+
+ }
+
+ LLGLDisable cull(GL_CULL_FACE);
+ LLGLDisable blend(GL_BLEND);
+ S32 width = gViewerWindow->getWindowWidthScaled();
+ S32 height = gViewerWindow->getWindowHeightScaled();
+ gGL.getTexUnit(0)->bind(&gPipeline.mUIScreen);
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.color4f(1,1,1,1);
+ gGL.texCoord2f(0, 0); gGL.vertex2i(0, 0);
+ gGL.texCoord2f(width, 0); gGL.vertex2i(width, 0);
+ gGL.texCoord2f(0, height); gGL.vertex2i(0, height);
+ gGL.texCoord2f(width, height); gGL.vertex2i(width, height);
+ gGL.end();
+ }
+ else
{
- gViewerWindow->drawPickBuffer();
+ gViewerWindow->draw();
}
+
+
// reset current origin for font rendering, in case of tiling render
LLFontGL::sCurOrigin.set(0, 0);
}
@@ -1261,8 +1402,7 @@ void render_disconnected_background()
//llinfos << "Bitmap load failed" << llendl;
return;
}
-
- gDisconnectedImagep = new LLImageGL( FALSE );
+
LLPointer<LLImageRaw> raw = new LLImageRaw;
if (!image_bmp->decode(raw, 0.0f))
{
@@ -1288,14 +1428,14 @@ void render_disconnected_background()
raw->expandToPowerOfTwo();
- gDisconnectedImagep->createGLTexture(0, raw);
- gStartImageGL = gDisconnectedImagep;
+ gDisconnectedImagep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE );
+ gStartTexture = gDisconnectedImagep;
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
// Make sure the progress view always fills the entire window.
- S32 width = gViewerWindow->getWindowWidth();
- S32 height = gViewerWindow->getWindowHeight();
+ S32 width = gViewerWindow->getWindowWidthScaled();
+ S32 height = gViewerWindow->getWindowHeightScaled();
if (gDisconnectedImagep)
{
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
new file mode 100644
index 0000000000..3a834e7532
--- /dev/null
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -0,0 +1,271 @@
+/**
+ * @file llviewerfloaterreg.cpp
+ * @brief LLViewerFloaterReg class registers floaters used in the viewer
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterreg.h"
+
+#include "llviewerfloaterreg.h"
+
+#include "llcompilequeue.h"
+#include "llcallfloater.h"
+#include "llfloaterabout.h"
+#include "llfloateractivespeakers.h"
+#include "llfloateranimpreview.h"
+#include "llfloaterauction.h"
+#include "llfloateravatarpicker.h"
+#include "llfloateravatartextures.h"
+#include "llfloaterbeacons.h"
+#include "llfloaterbuildoptions.h"
+#include "llfloaterbuy.h"
+#include "llfloaterbuycontents.h"
+#include "llfloaterbuycurrency.h"
+#include "llfloaterbuyland.h"
+#include "llfloaterbulkpermission.h"
+#include "llfloaterbump.h"
+#include "llfloatercamera.h"
+#include "llfloaterchatterbox.h"
+#include "llfloaterdaycycle.h"
+#include "llfloatersearch.h"
+#include "llfloaterenvsettings.h"
+#include "llfloaterfonttest.h"
+#include "llfloatergesture.h"
+#include "llfloatergodtools.h"
+#include "llfloatergroups.h"
+#include "llfloaterhardwaresettings.h"
+#include "llfloaterhelpbrowser.h"
+#include "llfloatermediabrowser.h"
+#include "llfloatermediasettings.h"
+#include "llfloaterhud.h"
+#include "llfloaterimagepreview.h"
+#include "llimfloater.h"
+#include "llimpanel.h"
+#include "llfloaterinspect.h"
+#include "llfloaterinventory.h"
+#include "llfloaterjoystick.h"
+#include "llfloaterlagmeter.h"
+#include "llfloaterland.h"
+#include "llfloaterlandholdings.h"
+#include "llfloatermap.h"
+#include "llfloatermemleak.h"
+#include "llfloaternamedesc.h"
+#include "llfloaternearbymedia.h"
+#include "llfloaternotificationsconsole.h"
+#include "llfloateropenobject.h"
+#include "llfloaterpay.h"
+#include "llfloaterparcel.h"
+#include "llfloaterperms.h"
+#include "llfloaterpostcard.h"
+#include "llfloaterpostprocess.h"
+#include "llfloaterpreference.h"
+#include "llfloaterproperties.h"
+#include "llfloaterregioninfo.h"
+#include "llfloaterreporter.h"
+#include "llfloaterscriptdebug.h"
+#include "llfloaterscriptlimits.h"
+#include "llfloatersellland.h"
+#include "llfloatersettingsdebug.h"
+#include "llfloatersnapshot.h"
+#include "llfloatertelehub.h"
+#include "llfloatertestinspectors.h"
+#include "llfloatertestlistview.h"
+#include "llfloatertools.h"
+#include "llfloatertos.h"
+#include "llfloatertopobjects.h"
+#include "llfloateruipreview.h"
+#include "llfloaterurldisplay.h"
+#include "llfloatervoicedevicesettings.h"
+#include "llfloaterwater.h"
+#include "llfloaterwhitelistentry.h"
+#include "llfloaterwindlight.h"
+#include "llfloaterwindowsize.h"
+#include "llfloaterworldmap.h"
+#include "llimfloatercontainer.h"
+#include "llinspectavatar.h"
+#include "llinspectgroup.h"
+#include "llinspectobject.h"
+#include "llinspectremoteobject.h"
+#include "llinspecttoast.h"
+#include "llmediaremotectrl.h"
+#include "llmoveview.h"
+#include "llnearbychat.h"
+#include "llpanelblockedlist.h"
+#include "llpreviewanim.h"
+#include "llpreviewgesture.h"
+#include "llpreviewnotecard.h"
+#include "llpreviewscript.h"
+#include "llpreviewsound.h"
+#include "llpreviewtexture.h"
+#include "llsyswellwindow.h"
+#include "llscriptfloater.h"
+// *NOTE: Please add files in alphabetical order to keep merges easy.
+
+
+void LLViewerFloaterReg::registerFloaters()
+{
+ // *NOTE: Please keep these alphabetized for easier merges
+
+ LLFloaterAboutUtil::registerFloater();
+ LLFloaterReg::add("about_land", "floater_about_land.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLand>);
+ LLFloaterReg::add("active_speakers", "floater_active_speakers.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterActiveSpeakers>);
+ LLFloaterReg::add("auction", "floater_auction.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAuction>);
+ LLFloaterReg::add("avatar_picker", "floater_avatar_picker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatarPicker>);
+ LLFloaterReg::add("avatar_textures", "floater_avatar_textures.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatarTextures>);
+
+ LLFloaterReg::add("beacons", "floater_beacons.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBeacons>);
+ LLFloaterReg::add("bulk_perms", "floater_bulk_perms.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBulkPermission>);
+ LLFloaterReg::add("buy_currency", "floater_buy_currency.xml", &LLFloaterBuyCurrency::buildFloater);
+ LLFloaterReg::add("buy_land", "floater_buy_land.xml", &LLFloaterBuyLand::buildFloater);
+ LLFloaterReg::add("buy_object", "floater_buy_object.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBuy>);
+ LLFloaterReg::add("buy_object_contents", "floater_buy_contents.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBuyContents>);
+ LLFloaterReg::add("build", "floater_tools.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTools>);
+ LLFloaterReg::add("build_options", "floater_build_options.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBuildOptions>);
+ LLFloaterReg::add("bumps", "floater_bumps.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBump>);
+
+ LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>);
+ //LLFloaterReg::add("chat", "floater_chat_history.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterChat>);
+ LLFloaterReg::add("nearby_chat", "floater_nearby_chat.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChat>);
+ LLFloaterReg::add("communicate", "floater_chatterbox.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterChatterBox>);
+ LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>);
+ LLFloaterReg::add("contacts", "floater_my_friends.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMyFriends>);
+
+ LLFloaterReg::add("env_day_cycle", "floater_day_cycle_options.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDayCycle>);
+ LLFloaterReg::add("env_post_process", "floater_post_process.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPostProcess>);
+ LLFloaterReg::add("env_settings", "floater_env_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEnvSettings>);
+ LLFloaterReg::add("env_water", "floater_water.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWater>);
+ LLFloaterReg::add("env_windlight", "floater_windlight_options.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWindLight>);
+
+ LLFloaterReg::add("font_test", "floater_font_test.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFontTest>);
+
+ LLFloaterReg::add("gestures", "floater_gesture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGesture>);
+ LLFloaterReg::add("god_tools", "floater_god_tools.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGodTools>);
+ LLFloaterReg::add("group_picker", "floater_choose_group.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGroupPicker>);
+
+ LLFloaterReg::add("help_browser", "floater_help_browser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHelpBrowser>);
+ LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHUD>);
+
+ LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloater>);
+ LLFloaterReg::add("im_container", "floater_im_container.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloaterContainer>);
+ LLFloaterReg::add("im_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMWellWindow>);
+ LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIncomingCallDialog>);
+ LLFloaterReg::add("inventory", "floater_inventory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterInventory>);
+ LLFloaterReg::add("inspect", "floater_inspect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterInspect>);
+ LLInspectAvatarUtil::registerFloater();
+ LLInspectGroupUtil::registerFloater();
+ LLInspectObjectUtil::registerFloater();
+ LLInspectRemoteObjectUtil::registerFloater();
+ LLNotificationsUI::registerFloater();
+
+ LLFloaterReg::add("lagmeter", "floater_lagmeter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLagMeter>);
+ LLFloaterReg::add("land_holdings", "floater_land_holdings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLandHoldings>);
+
+ LLFloaterReg::add("mem_leaking", "floater_mem_leaking.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMemLeak>);
+ LLFloaterReg::add("media_browser", "floater_media_browser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMediaBrowser>);
+ LLFloaterReg::add("media_settings", "floater_media_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMediaSettings>);
+ LLFloaterReg::add("message_critical", "floater_critical.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>);
+ LLFloaterReg::add("message_tos", "floater_tos.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>);
+ LLFloaterReg::add("moveview", "floater_moveview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMove>);
+ LLFloaterReg::add("mute_object_by_name", "floater_mute_object.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGetBlockedObjectName>);
+ LLFloaterReg::add("mini_map", "floater_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMap>);
+
+ LLFloaterReg::add("nearby_media", "floater_nearby_media.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNearbyMedia>);
+ LLFloaterReg::add("notifications_console", "floater_notifications_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationConsole>);
+ LLFloaterReg::add("notification_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNotificationWellWindow>);
+
+ LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>);
+ LLFloaterReg::add("outgoing_call", "floater_outgoing_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLOutgoingCallDialog>);
+ LLFloaterReg::add("parcel_info", "floater_preview_url.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterParcelInfo>);
+ LLFloaterPayUtil::registerFloater();
+
+ LLFloaterReg::add("postcard", "floater_postcard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPostcard>);
+ LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>);
+ LLFloaterReg::add("prefs_hardware_settings", "floater_hardware_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHardwareSettings>);
+ LLFloaterReg::add("perm_prefs", "floater_perm_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPerms>);
+ LLFloaterReg::add("preview_url", "floater_preview_url.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterURLDisplay>);
+ LLFloaterReg::add("pref_joystick", "floater_joystick.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterJoystick>);
+ LLFloaterReg::add("pref_voicedevicesettings", "floater_device_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterVoiceDeviceSettings>);
+ LLFloaterReg::add("preview_anim", "floater_preview_animation.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewAnim>, "preview");
+ LLFloaterReg::add("preview_gesture", "floater_preview_gesture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewGesture>, "preview");
+ LLFloaterReg::add("preview_notecard", "floater_preview_notecard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewNotecard>, "preview");
+ LLFloaterReg::add("preview_script", "floater_script_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewLSL>, "preview");
+ LLFloaterReg::add("preview_scriptedit", "floater_live_lsleditor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLLiveLSLEditor>, "preview");
+ LLFloaterReg::add("preview_sound", "floater_preview_sound.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewSound>, "preview");
+ LLFloaterReg::add("preview_texture", "floater_preview_texture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLPreviewTexture>, "preview");
+ LLFloaterReg::add("properties", "floater_inventory_item_properties.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterProperties>);
+
+ LLFloaterReg::add("telehubs", "floater_telehub.xml",&LLFloaterReg::build<LLFloaterTelehub>);
+ LLFloaterReg::add("test_inspectors", "floater_test_inspectors.xml",
+ &LLFloaterReg::build<LLFloaterTestInspectors>);
+ //LLFloaterReg::add("test_list_view", "floater_test_list_view.xml",&LLFloaterReg::build<LLFloaterTestListView>);
+ LLFloaterReg::add("test_textbox", "floater_test_textbox.xml",
+ &LLFloaterReg::build<LLFloater>);
+ LLFloaterReg::add("test_text_editor", "floater_test_text_editor.xml",
+ &LLFloaterReg::build<LLFloater>);
+ LLFloaterReg::add("test_widgets", "floater_test_widgets.xml",
+ &LLFloaterReg::build<LLFloater>);
+ LLFloaterReg::add("top_objects", "floater_top_objects.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTopObjects>);
+
+ LLFloaterReg::add("reporter", "floater_report_abuse.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterReporter>);
+ LLFloaterReg::add("reset_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterResetQueue>);
+ LLFloaterReg::add("region_info", "floater_region_info.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRegionInfo>);
+
+ LLFloaterReg::add("script_debug", "floater_script_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptDebug>);
+ LLFloaterReg::add("script_debug_output", "floater_script_debug_panel.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptDebugOutput>);
+ LLFloaterReg::add("script_floater", "floater_script.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLScriptFloater>);
+ LLFloaterReg::add("script_limits", "floater_script_limits.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptLimits>);
+ LLFloaterReg::add("sell_land", "floater_sell_land.xml", &LLFloaterSellLand::buildFloater);
+ LLFloaterReg::add("settings_debug", "floater_settings_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSettingsDebug>);
+ LLFloaterReg::add("stats", "floater_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>);
+ LLFloaterReg::add("start_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRunQueue>);
+ LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotRunQueue>);
+ LLFloaterReg::add("snapshot", "floater_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSnapshot>);
+ LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>);
+
+ LLFloaterUIPreviewUtil::registerFloater();
+ LLFloaterReg::add("upload_anim", "floater_animation_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAnimPreview>, "upload");
+ LLFloaterReg::add("upload_image", "floater_image_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterImagePreview>, "upload");
+ LLFloaterReg::add("upload_sound", "floater_sound_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundPreview>, "upload");
+
+ LLFloaterReg::add("voice_controls", "floater_voice_controls.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLCallFloater>);
+
+ LLFloaterReg::add("whitelist_entry", "floater_whitelist_entry.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWhiteListEntry>);
+ LLFloaterWindowSizeUtil::registerFloater();
+ LLFloaterReg::add("world_map", "floater_world_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWorldMap>);
+
+ // *NOTE: Please keep these alphabetized for easier merges
+
+ // debug use only
+ LLFloaterReg::add("media_remote_ctrl", "floater_media_remote.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMediaRemoteCtrl>);
+
+ LLFloaterReg::registerControlVariables(); // Make sure visibility and rect controls get preserved when saving
+}
diff --git a/indra/newview/llviewerfloaterreg.h b/indra/newview/llviewerfloaterreg.h
new file mode 100644
index 0000000000..08c9589ebb
--- /dev/null
+++ b/indra/newview/llviewerfloaterreg.h
@@ -0,0 +1,43 @@
+/**
+ * @file llviewerfloaterreg.h
+ * @brief The LLViewerFloaterReg class declaration
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLVIEWERFLOATERREG_H
+#define LL_LLVIEWERFLOATERREG_H
+
+class LLViewerFloaterReg
+{
+public:
+ static void registerFloaters();
+};
+
+
+#endif // LL_LLVIEWERFLOATERREG_H
diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp
new file mode 100644
index 0000000000..033d35d80a
--- /dev/null
+++ b/indra/newview/llviewerfoldertype.cpp
@@ -0,0 +1,277 @@
+/**
+ * @file llfoldertype.cpp
+ * @brief Implementation of LLViewerFolderType functionality.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llviewerfoldertype.h"
+#include "lldictionary.h"
+#include "llmemory.h"
+#include "llvisualparam.h"
+
+static const std::string empty_string;
+
+struct ViewerFolderEntry : public LLDictionaryEntry
+{
+ // Constructor for non-ensembles
+ ViewerFolderEntry(const std::string &new_category_name, // default name when creating a new category of this type
+ const std::string &icon_name, // name of the folder icon
+ BOOL is_quiet // folder doesn't need a UI update when changed
+ )
+ :
+ LLDictionaryEntry(empty_string), // no reverse lookup needed on non-ensembles, so just leave this blank
+ mIconName(icon_name),
+ mNewCategoryName(new_category_name),
+ mIsQuiet(is_quiet)
+ {
+ mAllowedNames.clear();
+ }
+
+ // Constructor for ensembles
+ ViewerFolderEntry(const std::string &xui_name, // name of the xui menu item
+ const std::string &new_category_name, // default name when creating a new category of this type
+ const std::string &icon_name, // name of the folder icon
+ const std::string allowed_names // allowed item typenames for this folder type
+ )
+ :
+ LLDictionaryEntry(xui_name),
+ mIconName(icon_name),
+ mNewCategoryName(new_category_name),
+ mIsQuiet(FALSE)
+ {
+ const std::string delims (",");
+ LLStringUtilBase<char>::getTokens(allowed_names, mAllowedNames, delims);
+ }
+
+ bool getIsAllowedName(const std::string &name) const
+ {
+ if (mAllowedNames.empty())
+ return false;
+ for (name_vec_t::const_iterator iter = mAllowedNames.begin();
+ iter != mAllowedNames.end();
+ iter++)
+ {
+ if (name == (*iter))
+ return true;
+ }
+ return false;
+ }
+ const std::string mIconName;
+ const std::string mNewCategoryName;
+ typedef std::vector<std::string> name_vec_t;
+ name_vec_t mAllowedNames;
+ BOOL mIsQuiet;
+};
+
+class LLViewerFolderDictionary : public LLSingleton<LLViewerFolderDictionary>,
+ public LLDictionary<LLFolderType::EType, ViewerFolderEntry>
+{
+public:
+ LLViewerFolderDictionary();
+protected:
+ bool initEnsemblesFromFile(); // Reads in ensemble information from foldertypes.xml
+};
+
+LLViewerFolderDictionary::LLViewerFolderDictionary()
+{
+ initEnsemblesFromFile();
+
+ // NEW CATEGORY NAME FOLDER ICON NAME QUIET?
+ // |-------------------------|-------------------------------|-----------|
+ addEntry(LLFolderType::FT_TEXTURE, new ViewerFolderEntry("Textures", "inv_folder_texture.tga", FALSE));
+ addEntry(LLFolderType::FT_SOUND, new ViewerFolderEntry("Sounds", "inv_folder_sound.tga", FALSE));
+ addEntry(LLFolderType::FT_CALLINGCARD, new ViewerFolderEntry("Calling Cards", "inv_folder_callingcard.tga", FALSE));
+ addEntry(LLFolderType::FT_LANDMARK, new ViewerFolderEntry("Landmarks", "inv_folder_landmark.tga", FALSE));
+ addEntry(LLFolderType::FT_CLOTHING, new ViewerFolderEntry("Clothing", "inv_folder_clothing.tga", FALSE));
+ addEntry(LLFolderType::FT_OBJECT, new ViewerFolderEntry("Objects", "inv_folder_object.tga", FALSE));
+ addEntry(LLFolderType::FT_NOTECARD, new ViewerFolderEntry("Notecards", "inv_folder_notecard.tga", FALSE));
+ addEntry(LLFolderType::FT_ROOT_INVENTORY, new ViewerFolderEntry("My Inventory", "", FALSE));
+ addEntry(LLFolderType::FT_LSL_TEXT, new ViewerFolderEntry("Scripts", "inv_folder_script.tga", FALSE));
+ addEntry(LLFolderType::FT_BODYPART, new ViewerFolderEntry("Body Parts", "inv_folder_bodypart.tga", FALSE));
+ addEntry(LLFolderType::FT_TRASH, new ViewerFolderEntry("Trash", "inv_folder_trash.tga", TRUE));
+ addEntry(LLFolderType::FT_SNAPSHOT_CATEGORY, new ViewerFolderEntry("Photo Album", "inv_folder_snapshot.tga", FALSE));
+ addEntry(LLFolderType::FT_LOST_AND_FOUND, new ViewerFolderEntry("Lost And Found", "inv_folder_lostandfound.tga", TRUE));
+ addEntry(LLFolderType::FT_ANIMATION, new ViewerFolderEntry("Animations", "inv_folder_animation.tga", FALSE));
+ addEntry(LLFolderType::FT_GESTURE, new ViewerFolderEntry("Gestures", "inv_folder_gesture.tga", FALSE));
+ addEntry(LLFolderType::FT_FAVORITE, new ViewerFolderEntry("Favorites", "inv_folder_plain_closed.tga", FALSE));
+
+ addEntry(LLFolderType::FT_CURRENT_OUTFIT, new ViewerFolderEntry("Current Outfit", "inv_folder_current_outfit.tga",TRUE));
+ addEntry(LLFolderType::FT_OUTFIT, new ViewerFolderEntry("New Outfit", "inv_folder_outfit.tga", TRUE));
+ addEntry(LLFolderType::FT_MY_OUTFITS, new ViewerFolderEntry("My Outfits", "inv_folder_my_outfits.tga", TRUE));
+ addEntry(LLFolderType::FT_INBOX, new ViewerFolderEntry("Inbox", "inv_folder_inbox.tga", FALSE));
+
+ addEntry(LLFolderType::FT_NONE, new ViewerFolderEntry("New Folder", "inv_folder_plain_closed.tga", FALSE));
+}
+
+bool LLViewerFolderDictionary::initEnsemblesFromFile()
+{
+ std::string xml_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"foldertypes.xml");
+ LLXmlTree folder_def;
+ if (!folder_def.parseFile(xml_filename))
+ {
+ llerrs << "Failed to parse folders file " << xml_filename << llendl;
+ return false;
+ }
+
+ LLXmlTreeNode* rootp = folder_def.getRoot();
+ for (LLXmlTreeNode* ensemble = rootp->getFirstChild();
+ ensemble;
+ ensemble = rootp->getNextChild())
+ {
+ if (!ensemble->hasName("ensemble"))
+ {
+ llwarns << "Invalid ensemble definition node " << ensemble->getName() << llendl;
+ continue;
+ }
+
+ S32 ensemble_type;
+ static LLStdStringHandle ensemble_num_string = LLXmlTree::addAttributeString("foldertype_num");
+ if (!ensemble->getFastAttributeS32(ensemble_num_string, ensemble_type))
+ {
+ llwarns << "No ensemble type defined" << llendl;
+ continue;
+ }
+
+
+ if (ensemble_type < S32(LLFolderType::FT_ENSEMBLE_START) || ensemble_type > S32(LLFolderType::FT_ENSEMBLE_END))
+ {
+ llwarns << "Exceeded maximum ensemble index" << LLFolderType::FT_ENSEMBLE_END << llendl;
+ break;
+ }
+
+ std::string xui_name;
+ static LLStdStringHandle xui_name_string = LLXmlTree::addAttributeString("xui_name");
+ if (!ensemble->getFastAttributeString(xui_name_string, xui_name))
+ {
+ llwarns << "No xui name defined" << llendl;
+ continue;
+ }
+
+ std::string icon_name;
+ static LLStdStringHandle icon_name_string = LLXmlTree::addAttributeString("icon_name");
+ if (!ensemble->getFastAttributeString(icon_name_string, icon_name))
+ {
+ llwarns << "No ensemble icon name defined" << llendl;
+ continue;
+ }
+
+ std::string allowed_names;
+ static LLStdStringHandle allowed_names_string = LLXmlTree::addAttributeString("allowed");
+ if (!ensemble->getFastAttributeString(allowed_names_string, allowed_names))
+ {
+ }
+
+ // Add the entry and increment the asset number.
+ const static std::string new_ensemble_name = "New Ensemble";
+ addEntry(LLFolderType::EType(ensemble_type), new ViewerFolderEntry(xui_name, new_ensemble_name, icon_name, allowed_names));
+ }
+
+ return true;
+}
+
+
+const std::string &LLViewerFolderType::lookupXUIName(LLFolderType::EType folder_type)
+{
+ const ViewerFolderEntry *entry = LLViewerFolderDictionary::getInstance()->lookup(folder_type);
+ if (entry)
+ {
+ return entry->mName;
+ }
+ return badLookup();
+}
+
+LLFolderType::EType LLViewerFolderType::lookupTypeFromXUIName(const std::string &name)
+{
+ return LLViewerFolderDictionary::getInstance()->lookup(name);
+}
+
+const std::string &LLViewerFolderType::lookupIconName(LLFolderType::EType folder_type)
+{
+ const ViewerFolderEntry *entry = LLViewerFolderDictionary::getInstance()->lookup(folder_type);
+ if (entry)
+ {
+ return entry->mIconName;
+ }
+ return badLookup();
+}
+
+BOOL LLViewerFolderType::lookupIsQuietType(LLFolderType::EType folder_type)
+{
+ const ViewerFolderEntry *entry = LLViewerFolderDictionary::getInstance()->lookup(folder_type);
+ if (entry)
+ {
+ return entry->mIsQuiet;
+ }
+ return FALSE;
+}
+
+
+const std::string &LLViewerFolderType::lookupNewCategoryName(LLFolderType::EType folder_type)
+{
+ const ViewerFolderEntry *entry = LLViewerFolderDictionary::getInstance()->lookup(folder_type);
+ if (entry)
+ {
+ return entry->mNewCategoryName;
+ }
+ return badLookup();
+}
+
+LLFolderType::EType LLViewerFolderType::lookupTypeFromNewCategoryName(const std::string& name)
+{
+ for (LLViewerFolderDictionary::const_iterator iter = LLViewerFolderDictionary::getInstance()->begin();
+ iter != LLViewerFolderDictionary::getInstance()->end();
+ iter++)
+ {
+ const ViewerFolderEntry *entry = iter->second;
+ if (entry->mNewCategoryName == name)
+ {
+ return iter->first;
+ }
+ }
+ return FT_NONE;
+}
+
+
+U64 LLViewerFolderType::lookupValidFolderTypes(const std::string& item_name)
+{
+ U64 matching_folders = 0;
+ for (LLViewerFolderDictionary::const_iterator iter = LLViewerFolderDictionary::getInstance()->begin();
+ iter != LLViewerFolderDictionary::getInstance()->end();
+ iter++)
+ {
+ const ViewerFolderEntry *entry = iter->second;
+ if (entry->getIsAllowedName(item_name))
+ {
+ matching_folders |= 1LL << iter->first;
+ }
+ }
+ return matching_folders;
+}
diff --git a/indra/newview/llviewerfoldertype.h b/indra/newview/llviewerfoldertype.h
new file mode 100644
index 0000000000..dd9360da90
--- /dev/null
+++ b/indra/newview/llviewerfoldertype.h
@@ -0,0 +1,59 @@
+/**
+ * @file llviewerfoldertype.h
+ * @brief Declaration of LLAssetType.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLVIEWERFOLDERTYPE_H
+#define LL_LLVIEWERFOLDERTYPE_H
+
+#include <string>
+#include "llfoldertype.h"
+
+// This class is similar to llfoldertype, but contains methods
+// only used by the viewer. This also handles ensembles.
+class LLViewerFolderType : public LLFolderType
+{
+public:
+ static const std::string& lookupXUIName(EType folder_type); // name used by the UI
+ static LLFolderType::EType lookupTypeFromXUIName(const std::string& name);
+
+ static const std::string& lookupIconName(EType folder_type); // folder icon name
+ static BOOL lookupIsQuietType(EType folder_type); // folder doesn't require UI update when changes have occured
+ static const std::string& lookupNewCategoryName(EType folder_type); // default name when creating new category
+ static LLFolderType::EType lookupTypeFromNewCategoryName(const std::string& name); // default name when creating new category
+
+ static U64 lookupValidFolderTypes(const std::string& item_name); // which folders allow an item of this type?
+
+protected:
+ LLViewerFolderType() {}
+ ~LLViewerFolderType() {}
+};
+
+#endif // LL_LLVIEWERFOLDERTYPE_H
diff --git a/indra/newview/llviewergenericmessage.h b/indra/newview/llviewergenericmessage.h
index 6e1f0945b8..6b0a2e5d81 100644
--- a/indra/newview/llviewergenericmessage.h
+++ b/indra/newview/llviewergenericmessage.h
@@ -36,6 +36,7 @@
class LLUUID;
class LLDispatcher;
+class LLMessageSystem;
void send_generic_message(const std::string& method,
diff --git a/indra/newview/llviewergesture.cpp b/indra/newview/llviewergesture.cpp
index 168f9af1d1..93b126b67d 100644
--- a/indra/newview/llviewergesture.cpp
+++ b/indra/newview/llviewergesture.cpp
@@ -34,12 +34,11 @@
#include "llviewergesture.h"
-#include "audioengine.h"
+#include "llaudioengine.h"
#include "lldir.h"
#include "llviewerinventory.h"
#include "sound_ids.h" // for testing
-#include "llchatbar.h"
#include "llkeyboard.h" // for key shortcuts for testing
#include "llinventorymodel.h"
#include "llvoavatar.h"
@@ -47,6 +46,7 @@
#include "llviewermessage.h" // send_guid_sound_trigger
#include "llviewernetwork.h"
#include "llagent.h"
+#include "llnearbychatbar.h"
// Globals
LLViewerGestureList gGestureList;
@@ -132,11 +132,11 @@ void LLViewerGesture::doTrigger( BOOL send_chat )
}
}
- if ( send_chat && !mOutputString.empty())
+ if (send_chat && !mOutputString.empty())
{
// Don't play nodding animation, since that might not blend
// with the gesture animation.
- gChatBar->sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE);
+ LLNearbyChatBar::getInstance()->sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE);
}
}
diff --git a/indra/newview/llviewerhelp.cpp b/indra/newview/llviewerhelp.cpp
new file mode 100644
index 0000000000..7c491ad154
--- /dev/null
+++ b/indra/newview/llviewerhelp.cpp
@@ -0,0 +1,156 @@
+/**
+ * @file llviewerhelp.cpp
+ * @brief Utility functions for the Help system
+ * @author Tofu Linden
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterhelpbrowser.h"
+#include "llfloaterreg.h"
+#include "llfocusmgr.h"
+#include "llviewercontrol.h"
+#include "llappviewer.h"
+#include "lllogininstance.h"
+
+#include "llviewerhelputil.h"
+#include "llviewerhelp.h"
+
+
+//////////////////////////////
+// implement LLHelp interface
+
+void LLViewerHelp::showTopic(const std::string &topic)
+{
+ // allow overriding the help server with a local help file
+ if( gSavedSettings.getBOOL("HelpUseLocal") )
+ {
+ showHelp();
+ LLFloaterHelpBrowser* helpbrowser = dynamic_cast<LLFloaterHelpBrowser*>(LLFloaterReg::getInstance("help_browser"));
+ helpbrowser->navigateToLocalPage( "help-offline" , "index.html" );
+ return;
+ }
+
+ // if the help topic is empty, use the default topic
+ std::string help_topic = topic;
+ if (help_topic.empty())
+ {
+ help_topic = defaultTopic();
+ }
+
+ // f1 help topic means: if the user is not logged in yet, show
+ // the pre-login topic instead of the default fallback topic,
+ // otherwise show help for the focused item
+ if (help_topic == f1HelpTopic())
+ {
+ help_topic = getTopicFromFocus();
+ if (help_topic == defaultTopic() && ! LLLoginInstance::getInstance()->authSuccess())
+ {
+ help_topic = preLoginTopic();
+ }
+ }
+
+ // work out the URL for this topic and display it
+ showHelp();
+ std::string helpURL = LLViewerHelpUtil::buildHelpURL( help_topic );
+ setRawURL( helpURL );
+}
+
+std::string LLViewerHelp::defaultTopic()
+{
+ // *hack: to be done properly
+ return "this_is_fallbacktopic";
+}
+
+std::string LLViewerHelp::preLoginTopic()
+{
+ // *hack: to be done properly
+ return "pre_login_help";
+}
+
+std::string LLViewerHelp::f1HelpTopic()
+{
+ // *hack: to be done properly
+ return "f1_help";
+}
+
+//////////////////////////////
+// our own interfaces
+
+std::string LLViewerHelp::getTopicFromFocus()
+{
+ // use UI element with viewer's keyboard focus as basis for searching
+ LLUICtrl* focused = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
+
+ if (focused)
+ {
+ std::string topic;
+ if (focused->findHelpTopic(topic))
+ {
+ return topic;
+ }
+ }
+
+ // didn't find a help topic in the UI hierarchy for focused
+ // element, return the fallback topic name instead.
+ return defaultTopic();
+}
+
+// static
+void LLViewerHelp::showHelp()
+{
+ LLFloaterHelpBrowser* helpbrowser = dynamic_cast<LLFloaterHelpBrowser*>(LLFloaterReg::getInstance("help_browser"));
+ if (helpbrowser)
+ {
+ BOOL visible = TRUE;
+ BOOL take_focus = TRUE;
+ helpbrowser->setVisible(visible);
+ helpbrowser->setFrontmost(take_focus);
+ }
+ else
+ {
+ llwarns << "Eep, help_browser floater not found" << llendl;
+ }
+}
+
+// static
+void LLViewerHelp::setRawURL(std::string url)
+{
+ LLFloaterHelpBrowser* helpbrowser = dynamic_cast<LLFloaterHelpBrowser*>(LLFloaterReg::getInstance("help_browser"));
+ if (helpbrowser)
+ {
+ helpbrowser->openMedia(url);
+ }
+ else
+ {
+ llwarns << "Eep, help_browser floater not found" << llendl;
+ }
+}
+
diff --git a/indra/newview/llviewerhelp.h b/indra/newview/llviewerhelp.h
new file mode 100644
index 0000000000..07971a593e
--- /dev/null
+++ b/indra/newview/llviewerhelp.h
@@ -0,0 +1,71 @@
+/**
+ * @file llviewerhelp.h
+ * @brief Utility functions for the Help system
+ * @author Tofu Linden
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLVIEWERHELP_H
+#define LL_LLVIEWERHELP_H
+
+// The Help UI lives in llfloaterhelpbrowser, llviewerhelp provides a
+// layer of abstraction that protects help-system-using code from the details of
+// the Help UI floater and how help topics are converted into URLs.
+
+#include "llhelp.h" // our abstract base
+#include "llsingleton.h"
+
+class LLUICtrl;
+
+class LLViewerHelp : public LLHelp, public LLSingleton<LLViewerHelp>
+{
+ friend class LLSingleton<LLViewerHelp>;
+
+ public:
+ /// display the specified help topic in the help viewer
+ /*virtual*/ void showTopic(const std::string &topic);
+
+ // return topic derived from viewer UI focus, else default topic
+ std::string getTopicFromFocus();
+
+ /// return default (fallback) topic name suitable for showTopic()
+ /*virtual*/ std::string defaultTopic();
+
+ // return topic to use before the user logs in
+ /*virtual*/ std::string preLoginTopic();
+
+ // return topic to use for the top-level help, invoked by F1
+ /*virtual*/ std::string f1HelpTopic();
+
+ private:
+ static void showHelp(); // make sure help UI is visible & raised
+ static void setRawURL(std::string url); // send URL to help UI
+};
+
+#endif // header guard
diff --git a/indra/newview/llviewerhelputil.cpp b/indra/newview/llviewerhelputil.cpp
new file mode 100644
index 0000000000..967a2925e3
--- /dev/null
+++ b/indra/newview/llviewerhelputil.cpp
@@ -0,0 +1,73 @@
+/**
+ * @file llviewerhelp.cpp
+ * @brief Utility functions for the Help system
+ * @author Soft Linden
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llviewerhelputil.h"
+
+#include "llagent.h"
+#include "llsd.h"
+#include "llstring.h"
+#include "lluri.h"
+#include "llweb.h"
+#include "llviewercontrol.h"
+
+//////////////////////////////////////////////
+// Build a help URL from a topic and formatter
+
+//static
+std::string LLViewerHelpUtil::helpURLEncode( const std::string &component )
+{
+ // Every character rfc3986 allows as unreserved in 2.3, minus the tilde
+ // which we may grant special meaning. Yay.
+ const char* allowed =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "-._";
+ std::string escaped = LLURI::escape(component, allowed);
+
+ return escaped;
+}
+
+//static
+std::string LLViewerHelpUtil::buildHelpURL( const std::string &topic)
+{
+ LLSD substitution;
+ substitution["TOPIC"] = helpURLEncode(topic);
+ substitution["DEBUG_MODE"] = gAgent.isGodlike() ? "/debug" : "";
+
+ // get the help URL and expand all of the substitutions
+ // (also adds things like [LANGUAGE], [VERSION], [OS], etc.)
+ std::string helpURL = gSavedSettings.getString("HelpURLFormat");
+ return LLWeb::expandURLSubstitutions(helpURL, substitution);
+}
diff --git a/indra/newview/llviewerhelputil.h b/indra/newview/llviewerhelputil.h
new file mode 100644
index 0000000000..95e6744842
--- /dev/null
+++ b/indra/newview/llviewerhelputil.h
@@ -0,0 +1,47 @@
+/**
+ * @file llviewerhelputil.h
+ * @brief Utility functions for the Help system
+ * @author Soft Linden
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLVIEWERHELPUTIL_H
+#define LL_LLVIEWERHELPUTIL_H
+
+class LLControlGroup;
+class LLOSInfo;
+
+class LLViewerHelpUtil
+{
+ public:
+ static std::string helpURLEncode( const std::string &component );
+ static std::string buildHelpURL( const std::string &topic );
+};
+
+#endif // header guard
diff --git a/indra/newview/llviewerhome.cpp b/indra/newview/llviewerhome.cpp
new file mode 100644
index 0000000000..8fdbe0a4ae
--- /dev/null
+++ b/indra/newview/llviewerhome.cpp
@@ -0,0 +1,83 @@
+/**
+ * @file llviewerhome.cpp
+ * @brief Model (non-View) component for the web-based Home side panel
+ * @author Martin Reddy
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llviewerhome.h"
+
+#include "lllogininstance.h"
+#include "llsd.h"
+#include "llui.h"
+#include "lluri.h"
+#include "llviewercontrol.h"
+#include "llweb.h"
+
+//static
+std::string LLViewerHome::getHomeURL()
+{
+ // Return the URL to display in the Home side tray. We read
+ // this value from settings.xml and support various substitutions
+
+ LLSD substitution;
+ substitution["AUTH_TOKEN"] = LLURI::escape(getAuthKey());
+
+ // get the home URL from the settings.xml file
+ std::string homeURL = gSavedSettings.getString("HomeSidePanelURL");
+
+ // support a grid-level override of the URL from login.cgi
+ LLSD grid_url = LLLoginInstance::getInstance()->getResponse("home_sidetray_url");
+ if (! grid_url.asString().empty())
+ {
+ homeURL = grid_url.asString();
+ }
+
+ // expand all substitution strings in the URL and return it
+ // (also adds things like [LANGUAGE], [VERSION], [OS], etc.)
+ return LLWeb::expandURLSubstitutions(homeURL, substitution);
+}
+
+//static
+std::string LLViewerHome::getAuthKey()
+{
+ // return the value of the (optional) auth token returned by login.cgi
+ // this lets the server provide an authentication token that we can
+ // blindly pass to the Home web page for it to perform authentication.
+ // We use "home_sidetray_token", and fallback to "auth_token" if not
+ // present.
+ LLSD auth_token = LLLoginInstance::getInstance()->getResponse("home_sidetray_token");
+ if (auth_token.asString().empty())
+ {
+ auth_token = LLLoginInstance::getInstance()->getResponse("auth_token");
+ }
+ return auth_token.asString();
+}
+
diff --git a/indra/newview/llviewerhome.h b/indra/newview/llviewerhome.h
new file mode 100644
index 0000000000..50454a71b7
--- /dev/null
+++ b/indra/newview/llviewerhome.h
@@ -0,0 +1,49 @@
+/**
+ * @file llviewerhome.h
+ * @brief Model (non-View) component for the web-based Home side panel
+ * @author Martin Reddy
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLVIEWERHOME_H
+#define LL_LLVIEWERHOME_H
+
+#include <string>
+
+class LLViewerHome
+{
+public:
+ /// return the URL to use for the web-based Home side panel
+ static std::string getHomeURL();
+
+ /// return the authentication key for the Home web site
+ static std::string getAuthKey();
+};
+
+#endif
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 7f1f0fe6d0..b330c1ba83 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -33,28 +33,84 @@
#include "llviewerprecompiledheaders.h"
#include "llviewerinventory.h"
+#include "llnotificationsutil.h"
#include "message.h"
#include "indra_constants.h"
#include "llagent.h"
+#include "llviewerfoldertype.h"
+#include "llfolderview.h"
#include "llviewercontrol.h"
#include "llconsole.h"
#include "llinventorymodel.h"
-#include "llnotify.h"
-#include "llimview.h"
#include "llgesturemgr.h"
+#include "llsidetray.h"
-#include "llinventoryview.h"
+#include "llinventorybridge.h"
+#include "llfloaterinventory.h"
+#include "llviewerassettype.h"
#include "llviewerregion.h"
#include "llviewerobjectlist.h"
#include "llpreviewgesture.h"
#include "llviewerwindow.h"
+#include "lltrans.h"
+#include "llappearancemgr.h"
+#include "llfloatercustomize.h"
+#include "llcommandhandler.h"
+#include "llviewermessage.h"
///----------------------------------------------------------------------------
/// Local function declarations, constants, enums, and typedefs
///----------------------------------------------------------------------------
+class LLInventoryHandler : public LLCommandHandler
+{
+public:
+ // requires trusted browser to trigger
+ LLInventoryHandler() : LLCommandHandler("inventory", UNTRUSTED_THROTTLE) { }
+
+ bool handle(const LLSD& params, const LLSD& query_map,
+ LLMediaCtrl* web)
+ {
+ if (params.size() < 1)
+ {
+ return false;
+ }
+
+ // support secondlife:///app/inventory/show
+ if (params[0].asString() == "show")
+ {
+ LLSideTray::getInstance()->showPanel("sidepanel_inventory", LLSD());
+ return true;
+ }
+
+ // otherwise, we need a UUID and a verb...
+ if (params.size() < 2)
+ {
+ return false;
+ }
+ LLUUID inventory_id;
+ if (!inventory_id.set(params[0], FALSE))
+ {
+ return false;
+ }
+
+ const std::string verb = params[1].asString();
+ if (verb == "select")
+ {
+ std::vector<LLUUID> items_to_open;
+ items_to_open.push_back(inventory_id);
+ //inventory_handler is just a stub, because we don't know from who this offer
+ open_inventory_offer(items_to_open, "inventory_handler");
+ return true;
+ }
+
+ return false;
+ }
+};
+LLInventoryHandler gInventoryHandler;
+
///----------------------------------------------------------------------------
/// Class LLViewerInventoryItem
///----------------------------------------------------------------------------
@@ -199,10 +255,19 @@ void LLViewerInventoryItem::fetchFromServer(void) const
{
std::string url;
- if( ALEXANDRIA_LINDEN_ID.getString() == mPermissions.getOwner().getString())
- url = gAgent.getRegion()->getCapability("FetchLib");
- else
- url = gAgent.getRegion()->getCapability("FetchInventory");
+ LLViewerRegion* region = gAgent.getRegion();
+ // we have to check region. It can be null after region was destroyed. See EXT-245
+ if (region)
+ {
+ if( ALEXANDRIA_LINDEN_ID.getString() == mPermissions.getOwner().getString())
+ url = region->getCapability("FetchLib");
+ else
+ url = region->getCapability("FetchInventory");
+ }
+ else
+ {
+ llwarns << "Agent Region is absent" << llendl;
+ }
if (!url.empty())
{
@@ -242,8 +307,7 @@ BOOL LLViewerInventoryItem::unpackMessage(LLSD item)
}
// virtual
-BOOL LLViewerInventoryItem::unpackMessage(
- LLMessageSystem* msg, const char* block, S32 block_num)
+BOOL LLViewerInventoryItem::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num)
{
BOOL rv = LLInventoryItem::unpackMessage(msg, block, block_num);
mIsComplete = TRUE;
@@ -307,8 +371,8 @@ bool LLViewerInventoryItem::exportFileLocal(LLFILE* fp) const
fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str());
mPermissions.exportFile(fp);
fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
- const char* inv_type_str = LLInventoryType::lookup(mInventoryType);
- if(inv_type_str) fprintf(fp, "\t\tinv_type\t%s\n", inv_type_str);
+ const std::string inv_type_str = LLInventoryType::lookup(mInventoryType);
+ if(!inv_type_str.empty()) fprintf(fp, "\t\tinv_type\t%s\n", inv_type_str.c_str());
fprintf(fp, "\t\tname\t%s|\n", mName.c_str());
fprintf(fp, "\t\tcreation_date\t%d\n", (S32) mCreationDate);
fprintf(fp,"\t}\n");
@@ -346,7 +410,7 @@ void LLViewerInventoryItem::updateParentOnServer(BOOL restamp) const
LLViewerInventoryCategory::LLViewerInventoryCategory(const LLUUID& uuid,
const LLUUID& parent_uuid,
- LLAssetType::EType pref,
+ LLFolderType::EType pref,
const std::string& name,
const LLUUID& owner_id) :
LLInventoryCategory(uuid, parent_uuid, pref, name),
@@ -402,9 +466,10 @@ void LLViewerInventoryCategory::updateParentOnServer(BOOL restamp) const
void LLViewerInventoryCategory::updateServer(BOOL is_new) const
{
// communicate that change with the server.
- if(LLAssetType::AT_NONE != mPreferredType)
+
+ if (LLFolderType::lookupIsProtectedType(mPreferredType))
{
- LLNotifications::instance().add("CannotModifyProtectedCategories");
+ LLNotificationsUtil::add("CannotModifyProtectedCategories");
return;
}
@@ -426,9 +491,9 @@ void LLViewerInventoryCategory::removeFromServer( void )
llinfos << "Removing inventory category " << mUUID << " from server."
<< llendl;
// communicate that change with the server.
- if(LLAssetType::AT_NONE != mPreferredType)
+ if(LLFolderType::lookupIsProtectedType(mPreferredType))
{
- LLNotifications::instance().add("CannotRemoveProtectedCategories");
+ LLNotificationsUtil::add("CannotRemoveProtectedCategories");
return;
}
@@ -461,11 +526,16 @@ bool LLViewerInventoryCategory::fetchDescendents()
// This comes from LLInventoryFilter from llfolderview.h
U32 sort_order = gSavedSettings.getU32("InventorySortOrder") & 0x1;
+ // *NOTE: For bug EXT-2879, originally commented out
+ // gAgent.getRegion()->getCapability in order to use the old
+ // message-based system. This has been uncommented now that
+ // AIS folks are aware of the issue and have a fix in process.
+ // see ticket for details.
+
std::string url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents");
-
if (!url.empty()) //Capability found. Build up LLSD and use it.
{
- LLInventoryModel::startBackgroundFetch(mUUID);
+ gInventory.startBackgroundFetch(mUUID);
}
else
{ //Deprecated, but if we don't have a capability, use the old system.
@@ -529,7 +599,7 @@ bool LLViewerInventoryCategory::importFileLocal(LLFILE* fp)
}
else if(0 == strcmp("pref_type", keyword))
{
- mPreferredType = LLAssetType::lookup(valuestr);
+ mPreferredType = LLFolderType::lookup(valuestr);
}
else if(0 == strcmp("name", keyword))
{
@@ -567,7 +637,7 @@ bool LLViewerInventoryCategory::exportFileLocal(LLFILE* fp) const
mParentUUID.toString(uuid_str);
fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str());
fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
- fprintf(fp, "\t\tpref_type\t%s\n", LLAssetType::lookup(mPreferredType));
+ fprintf(fp, "\t\tpref_type\t%s\n", LLFolderType::lookup(mPreferredType).c_str());
fprintf(fp, "\t\tname\t%s|\n", mName.c_str());
mOwnerID.toString(uuid_str);
fprintf(fp, "\t\towner_id\t%s\n", uuid_str.c_str());
@@ -576,6 +646,75 @@ bool LLViewerInventoryCategory::exportFileLocal(LLFILE* fp) const
return true;
}
+void LLViewerInventoryCategory::determineFolderType()
+{
+ LLFolderType::EType original_type = getPreferredType();
+ if (LLFolderType::lookupIsProtectedType(original_type))
+ return;
+
+ U64 folder_valid = 0;
+ U64 folder_invalid = 0;
+ LLInventoryModel::cat_array_t category_array;
+ LLInventoryModel::item_array_t item_array;
+ gInventory.collectDescendents(getUUID(),category_array,item_array,FALSE);
+
+ // For ensembles
+ if (category_array.empty())
+ {
+ for (LLInventoryModel::item_array_t::iterator item_iter = item_array.begin();
+ item_iter != item_array.end();
+ item_iter++)
+ {
+ const LLViewerInventoryItem *item = (*item_iter);
+ if (item->getIsLinkType())
+ return;
+ if (item->isWearableType())
+ {
+ const EWearableType wearable_type = item->getWearableType();
+ const std::string& wearable_name = LLWearableDictionary::getTypeName(wearable_type);
+ U64 valid_folder_types = LLViewerFolderType::lookupValidFolderTypes(wearable_name);
+ folder_valid |= valid_folder_types;
+ folder_invalid |= ~valid_folder_types;
+ }
+ }
+ for (U8 i = LLFolderType::FT_ENSEMBLE_START; i <= LLFolderType::FT_ENSEMBLE_END; i++)
+ {
+ if ((folder_valid & (1LL << i)) &&
+ !(folder_invalid & (1LL << i)))
+ {
+ changeType((LLFolderType::EType)i);
+ return;
+ }
+ }
+ }
+ if (LLFolderType::lookupIsEnsembleType(original_type))
+ {
+ changeType(LLFolderType::FT_NONE);
+ }
+}
+
+void LLViewerInventoryCategory::changeType(LLFolderType::EType new_folder_type)
+{
+ const LLUUID &folder_id = getUUID();
+ const LLUUID &parent_id = getParentUUID();
+ const std::string &name = getName();
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_UpdateInventoryFolder);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_FolderData);
+ msg->addUUIDFast(_PREHASH_FolderID, folder_id);
+ msg->addUUIDFast(_PREHASH_ParentID, parent_id);
+ msg->addS8Fast(_PREHASH_Type, new_folder_type);
+ msg->addStringFast(_PREHASH_Name, name);
+ gAgent.sendReliableMessage();
+
+ setPreferredType(new_folder_type);
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, folder_id);
+}
+
///----------------------------------------------------------------------------
/// Local function definitions
///----------------------------------------------------------------------------
@@ -643,6 +782,19 @@ void WearOnAvatarCallback::fire(const LLUUID& inv_item)
}
}
+void ModifiedCOFCallback::fire(const LLUUID& inv_item)
+{
+ LLAppearanceManager::instance().updateAppearanceFromCOF();
+ if( CAMERA_MODE_CUSTOMIZE_AVATAR == gAgent.getCameraMode() )
+ {
+ // If we're in appearance editing mode, the current tab may need to be refreshed
+ if (gFloaterCustomize)
+ {
+ gFloaterCustomize->switchToDefaultSubpart();
+ }
+ }
+}
+
RezAttachmentCallback::RezAttachmentCallback(LLViewerJointAttachment *attachmentp)
{
mAttach = attachmentp;
@@ -663,13 +815,12 @@ void RezAttachmentCallback::fire(const LLUUID& inv_item)
}
}
-extern LLGestureManager gGestureManager;
void ActivateGestureCallback::fire(const LLUUID& inv_item)
{
if (inv_item.isNull())
return;
- gGestureManager.activateGesture(inv_item);
+ LLGestureManager::instance().activateGesture(inv_item);
}
void CreateGestureCallback::fire(const LLUUID& inv_item)
@@ -677,19 +828,23 @@ void CreateGestureCallback::fire(const LLUUID& inv_item)
if (inv_item.isNull())
return;
- gGestureManager.activateGesture(inv_item);
+ LLGestureManager::instance().activateGesture(inv_item);
LLViewerInventoryItem* item = gInventory.getItem(inv_item);
if (!item) return;
gInventory.updateItem(item);
gInventory.notifyObservers();
- if(!LLPreview::show(inv_item,FALSE))
- {
- LLPreviewGesture* preview = LLPreviewGesture::show(std::string("Gesture: ") + item->getName(), inv_item, LLUUID::null);
- // Force to be entirely onscreen.
- gFloaterView->adjustToFitScreen(preview, FALSE);
- }
+ LLPreviewGesture* preview = LLPreviewGesture::show(inv_item, LLUUID::null);
+ // Force to be entirely onscreen.
+ gFloaterView->adjustToFitScreen(preview, FALSE);
+}
+
+void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id)
+{
+ if (mTargetLandmarkId.isNull()) return;
+
+ gInventory.rearrangeFavoriteLandmarks(inv_item_id, mTargetLandmarkId);
}
LLInventoryCallbackManager gInventoryCallbacks;
@@ -721,6 +876,16 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
gAgent.sendReliableMessage();
}
+void create_inventory_callingcard(const LLUUID& avatar_id, const LLUUID& parent /*= LLUUID::null*/, LLPointer<LLInventoryCallback> cb/*=NULL*/)
+{
+ std::string item_desc = avatar_id.asString();
+ std::string item_name;
+ gCacheName->getFullName(avatar_id, item_name);
+ create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
+ parent, LLTransactionID::tnull, item_name, item_desc, LLAssetType::AT_CALLINGCARD,
+ LLInventoryType::IT_CALLINGCARD, NOT_WEARABLE, PERM_MOVE | PERM_TRANSFER, cb);
+}
+
void copy_inventory_item(
const LLUUID& agent_id,
const LLUUID& current_owner,
@@ -743,6 +908,72 @@ void copy_inventory_item(
gAgent.sendReliableMessage();
}
+void link_inventory_item(
+ const LLUUID& agent_id,
+ const LLUUID& item_id,
+ const LLUUID& parent_id,
+ const std::string& new_name,
+ const LLAssetType::EType asset_type,
+ LLPointer<LLInventoryCallback> cb)
+{
+ const LLInventoryObject *baseobj = gInventory.getObject(item_id);
+ if (!baseobj)
+ {
+ llwarns << "attempt to link to unknown item, linked-to-item's itemID " << item_id << llendl;
+ return;
+ }
+ if (baseobj && baseobj->getIsLinkType())
+ {
+ llwarns << "attempt to create a link to a link, linked-to-item's itemID " << item_id << llendl;
+ return;
+ }
+
+ if (baseobj && !LLAssetType::lookupCanLink(baseobj->getType()))
+ {
+ // Fail if item can be found but is of a type that can't be linked.
+ // Arguably should fail if the item can't be found too, but that could
+ // be a larger behavioral change.
+ llwarns << "attempt to link an unlinkable item, type = " << baseobj->getActualType() << llendl;
+ return;
+ }
+
+ LLUUID transaction_id;
+ std::string desc = "Broken link"; // This should only show if the object can't find its baseobj.
+ LLInventoryType::EType inv_type = LLInventoryType::IT_NONE;
+ if (dynamic_cast<const LLInventoryCategory *>(baseobj))
+ {
+ inv_type = LLInventoryType::IT_CATEGORY;
+ }
+ else
+ {
+ const LLViewerInventoryItem *baseitem = dynamic_cast<const LLViewerInventoryItem *>(baseobj);
+ if (baseitem)
+ {
+ inv_type = baseitem->getInventoryType();
+ }
+ }
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_LinkInventoryItem);
+ msg->nextBlock(_PREHASH_AgentData);
+ {
+ msg->addUUIDFast(_PREHASH_AgentID, agent_id);
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ }
+ msg->nextBlock(_PREHASH_InventoryBlock);
+ {
+ msg->addU32Fast(_PREHASH_CallbackID, gInventoryCallbacks.registerCB(cb));
+ msg->addUUIDFast(_PREHASH_FolderID, parent_id);
+ msg->addUUIDFast(_PREHASH_TransactionID, transaction_id);
+ msg->addUUIDFast(_PREHASH_OldItemID, item_id);
+ msg->addS8Fast(_PREHASH_Type, (S8)asset_type);
+ msg->addS8Fast(_PREHASH_InvType, (S8)inv_type);
+ msg->addStringFast(_PREHASH_Name, new_name);
+ msg->addStringFast(_PREHASH_Description, desc);
+ }
+ gAgent.sendReliableMessage();
+}
+
void move_inventory_item(
const LLUUID& agent_id,
const LLUUID& session_id,
@@ -764,56 +995,518 @@ void move_inventory_item(
gAgent.sendReliableMessage();
}
-class LLCopyInventoryFromNotecardResponder : public LLHTTPClient::Responder
+void copy_inventory_from_notecard(const LLUUID& object_id, const LLUUID& notecard_inv_id, const LLInventoryItem *src, U32 callback_id)
{
-public:
- //If we get back a normal response, handle it here
- virtual void result(const LLSD& content)
+ LLViewerRegion* viewer_region = NULL;
+ LLViewerObject* vo = NULL;
+ if (object_id.notNull() && (vo = gObjectList.findObject(object_id)) != NULL)
+ {
+ viewer_region = vo->getRegion();
+ }
+
+ // Fallback to the agents region if for some reason the
+ // object isn't found in the viewer.
+ if (! viewer_region)
{
- // What do we do here?
- llinfos << "CopyInventoryFromNotecard request successful." << llendl;
+ viewer_region = gAgent.getRegion();
}
- //If we get back an error (not found, etc...), handle it here
- virtual void error(U32 status, const std::string& reason)
+ if (! viewer_region)
{
- llinfos << "LLCopyInventoryFromNotecardResponder::error "
- << status << ": " << reason << llendl;
+ LL_WARNS("copy_inventory_from_notecard") << "Can't find region from object_id "
+ << object_id << " or gAgent"
+ << LL_ENDL;
+ return;
+ }
+
+ LLSD request, body;
+ body["notecard-id"] = notecard_inv_id;
+ body["object-id"] = object_id;
+ body["item-id"] = src->getUUID();
+ body["folder-id"] = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(src->getType()));
+ body["callback-id"] = (LLSD::Integer)callback_id;
+
+ request["message"] = "CopyInventoryFromNotecard";
+ request["payload"] = body;
+
+ viewer_region->getCapAPI().post(request);
+}
+
+void create_new_item(const std::string& name,
+ const LLUUID& parent_id,
+ LLAssetType::EType asset_type,
+ LLInventoryType::EType inv_type,
+ U32 next_owner_perm)
+{
+ std::string desc;
+ LLViewerAssetType::generateDescriptionFor(asset_type, desc);
+ next_owner_perm = (next_owner_perm) ? next_owner_perm : PERM_MOVE | PERM_TRANSFER;
+
+
+ if (inv_type == LLInventoryType::IT_GESTURE)
+ {
+ LLPointer<LLInventoryCallback> cb = new CreateGestureCallback();
+ create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
+ parent_id, LLTransactionID::tnull, name, desc, asset_type, inv_type,
+ NOT_WEARABLE, next_owner_perm, cb);
}
-};
+ else
+ {
+ LLPointer<LLInventoryCallback> cb = NULL;
+ create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
+ parent_id, LLTransactionID::tnull, name, desc, asset_type, inv_type,
+ NOT_WEARABLE, next_owner_perm, cb);
+ }
+
+}
-void copy_inventory_from_notecard(const LLUUID& object_id, const LLUUID& notecard_inv_id, const LLInventoryItem *src, U32 callback_id)
+const std::string NEW_LSL_NAME = "New Script"; // *TODO:Translate? (probably not)
+const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably not)
+const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not)
+
+// ! REFACTOR ! Really need to refactor this so that it's not a bunch of if-then statements...
+void menu_create_inventory_item(LLFolderView* folder, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid)
{
- LLSD body;
- LLViewerRegion* viewer_region = NULL;
- if(object_id.notNull())
+ std::string type_name = userdata.asString();
+
+ if (("category" == type_name) || ("current" == type_name) || ("outfit" == type_name) || ("my_otfts" == type_name))
{
- LLViewerObject* vo = gObjectList.findObject(object_id);
- if(vo)
+ LLFolderType::EType preferred_type = LLFolderType::lookup(type_name);
+
+ LLUUID parent_id;
+ if (bridge)
+ {
+ parent_id = bridge->getUUID();
+ }
+ else if (default_parent_uuid.notNull())
+ {
+ parent_id = default_parent_uuid;
+ }
+ else
{
- viewer_region = vo->getRegion();
+ parent_id = gInventory.getRootFolderID();
}
+
+ LLUUID category = gInventory.createNewCategory(parent_id, preferred_type, LLStringUtil::null);
+ gInventory.notifyObservers();
+ folder->setSelectionByID(category, TRUE);
}
+ else if ("lsl" == type_name)
+ {
+ const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_LSL_TEXT);
+ create_new_item(NEW_LSL_NAME,
+ parent_id,
+ LLAssetType::AT_LSL_TEXT,
+ LLInventoryType::IT_LSL,
+ PERM_MOVE | PERM_TRANSFER);
+ }
+ else if ("notecard" == type_name)
+ {
+ const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_NOTECARD);
+ create_new_item(NEW_NOTECARD_NAME,
+ parent_id,
+ LLAssetType::AT_NOTECARD,
+ LLInventoryType::IT_NOTECARD,
+ PERM_ALL);
+ }
+ else if ("gesture" == type_name)
+ {
+ const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE);
+ create_new_item(NEW_GESTURE_NAME,
+ parent_id,
+ LLAssetType::AT_GESTURE,
+ LLInventoryType::IT_GESTURE,
+ PERM_ALL);
+ }
+ else
+ {
+ // Use for all clothing and body parts. Adding new wearable types requires updating LLWearableDictionary.
+ EWearableType wearable_type = LLWearableDictionary::typeNameToType(type_name);
+ if (wearable_type >= WT_SHAPE && wearable_type < WT_COUNT)
+ {
+ LLAssetType::EType asset_type = LLWearableDictionary::getAssetType(wearable_type);
+ LLFolderType::EType folder_type = LLFolderType::assetTypeToFolderType(asset_type);
+ const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(folder_type);
+ LLFolderBridge::createWearable(parent_id, wearable_type);
+ }
+ else
+ {
+ llwarns << "Can't create unrecognized type " << type_name << llendl;
+ }
+ }
+ folder->setNeedsAutoRename(TRUE);
+}
- // Fallback to the agents region if for some reason the
- // object isn't found in the viewer.
- if(!viewer_region)
+LLAssetType::EType LLViewerInventoryItem::getType() const
+{
+ if (const LLViewerInventoryItem *linked_item = getLinkedItem())
{
- viewer_region = gAgent.getRegion();
+ return linked_item->getType();
}
+ if (const LLViewerInventoryCategory *linked_category = getLinkedCategory())
+ {
+ return linked_category->getType();
+ }
+ return LLInventoryItem::getType();
+}
- if(viewer_region)
+const LLUUID& LLViewerInventoryItem::getAssetUUID() const
+{
+ if (const LLViewerInventoryItem *linked_item = getLinkedItem())
{
- std::string url = viewer_region->getCapability("CopyInventoryFromNotecard");
- if (!url.empty())
+ return linked_item->getAssetUUID();
+ }
+
+ return LLInventoryItem::getAssetUUID();
+}
+
+const std::string& LLViewerInventoryItem::getName() const
+{
+ if (const LLViewerInventoryItem *linked_item = getLinkedItem())
+ {
+ return linked_item->getName();
+ }
+ if (const LLViewerInventoryCategory *linked_category = getLinkedCategory())
+ {
+ return linked_category->getName();
+ }
+
+ return getDisplayName();
+}
+
+const std::string& LLViewerInventoryItem::getDisplayName() const
+{
+ std::string result;
+ BOOL hasSortField = extractSortFieldAndDisplayName(0, &result);
+
+ return mDisplayName = hasSortField ? result : LLInventoryItem::getName();
+}
+
+// static
+std::string LLViewerInventoryItem::getDisplayName(const std::string& name)
+{
+ std::string result;
+ BOOL hasSortField = extractSortFieldAndDisplayName(name, 0, &result);
+
+ return hasSortField ? result : name;
+}
+
+S32 LLViewerInventoryItem::getSortField() const
+{
+ S32 result;
+ BOOL hasSortField = extractSortFieldAndDisplayName(&result, 0);
+
+ return hasSortField ? result : -1;
+}
+
+void LLViewerInventoryItem::setSortField(S32 sortField)
+{
+ using std::string;
+
+ std::stringstream ss;
+ ss << sortField;
+
+ string newSortField = ss.str();
+
+ const char separator = getSeparator();
+ const string::size_type separatorPos = mName.find(separator, 0);
+
+ if (separatorPos < string::npos)
+ {
+ // the name of the LLViewerInventoryItem already consists of sort field and display name.
+ mName = newSortField + separator + mName.substr(separatorPos + 1, string::npos);
+ }
+ else
+ {
+ // there is no sort field in the name of LLViewerInventoryItem, we should add it
+ mName = newSortField + separator + mName;
+ }
+}
+
+void LLViewerInventoryItem::rename(const std::string& n)
+{
+ using std::string;
+
+ string new_name(n);
+ LLStringUtil::replaceNonstandardASCII(new_name, ' ');
+ LLStringUtil::replaceChar(new_name, '|', ' ');
+ LLStringUtil::trim(new_name);
+ LLStringUtil::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN);
+
+ const char separator = getSeparator();
+ const string::size_type separatorPos = mName.find(separator, 0);
+
+ if (separatorPos < string::npos)
+ {
+ mName.replace(separatorPos + 1, string::npos, new_name);
+ }
+ else
+ {
+ mName = new_name;
+ }
+}
+
+const LLPermissions& LLViewerInventoryItem::getPermissions() const
+{
+ // Use the actual permissions of the symlink, not its parent.
+ return LLInventoryItem::getPermissions();
+}
+
+const LLUUID& LLViewerInventoryItem::getCreatorUUID() const
+{
+ if (const LLViewerInventoryItem *linked_item = getLinkedItem())
+ {
+ return linked_item->getCreatorUUID();
+ }
+
+ return LLInventoryItem::getCreatorUUID();
+}
+
+const std::string& LLViewerInventoryItem::getDescription() const
+{
+ if (const LLViewerInventoryItem *linked_item = getLinkedItem())
+ {
+ return linked_item->getDescription();
+ }
+
+ return LLInventoryItem::getDescription();
+}
+
+const LLSaleInfo& LLViewerInventoryItem::getSaleInfo() const
+{
+ if (const LLViewerInventoryItem *linked_item = getLinkedItem())
+ {
+ return linked_item->getSaleInfo();
+ }
+
+ return LLInventoryItem::getSaleInfo();
+}
+
+LLInventoryType::EType LLViewerInventoryItem::getInventoryType() const
+{
+ if (const LLViewerInventoryItem *linked_item = getLinkedItem())
+ {
+ return linked_item->getInventoryType();
+ }
+
+ // Categories don't have types. If this item is an AT_FOLDER_LINK,
+ // treat it as a category.
+ if (getLinkedCategory())
+ {
+ return LLInventoryType::IT_CATEGORY;
+ }
+
+ return LLInventoryItem::getInventoryType();
+}
+
+U32 LLViewerInventoryItem::getFlags() const
+{
+ if (const LLViewerInventoryItem *linked_item = getLinkedItem())
+ {
+ return linked_item->getFlags();
+ }
+ return LLInventoryItem::getFlags();
+}
+
+bool LLViewerInventoryItem::isWearableType() const
+{
+ return (getInventoryType() == LLInventoryType::IT_WEARABLE);
+}
+
+EWearableType LLViewerInventoryItem::getWearableType() const
+{
+ if (!isWearableType())
+ {
+ llwarns << "item is not a wearable" << llendl;
+ return WT_INVALID;
+ }
+ return EWearableType(getFlags() & LLInventoryItem::II_FLAGS_WEARABLES_MASK);
+}
+
+
+time_t LLViewerInventoryItem::getCreationDate() const
+{
+ return LLInventoryItem::getCreationDate();
+}
+
+U32 LLViewerInventoryItem::getCRC32() const
+{
+ return LLInventoryItem::getCRC32();
+}
+
+BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName)
+{
+ using std::string;
+ using std::stringstream;
+
+ const char separator = getSeparator();
+ const string::size_type separatorPos = name.find(separator, 0);
+
+ BOOL result = FALSE;
+
+ if (separatorPos < string::npos)
+ {
+ if (sortField)
+ {
+ /*
+ * The conversion from string to S32 is made this way instead of old plain
+ * atoi() to ensure portability. If on some other platform S32 will not be
+ * defined to be signed int, this conversion will still work because of
+ * operators overloading, but atoi() may fail.
+ */
+ stringstream ss(name.substr(0, separatorPos));
+ ss >> *sortField;
+ }
+
+ if (displayName)
+ {
+ *displayName = name.substr(separatorPos + 1, string::npos);
+ }
+
+ result = TRUE;
+ }
+
+ return result;
+}
+
+void LLViewerInventoryItem::insertDefaultSortField(std::string& name)
+{
+ name.insert(0, std::string("1") + getSeparator());
+}
+
+
+// This returns true if the item that this item points to
+// doesn't exist in memory (i.e. LLInventoryModel). The baseitem
+// might still be in the database but just not loaded yet.
+bool LLViewerInventoryItem::getIsBrokenLink() const
+{
+ // If the item's type resolves to be a link, that means either:
+ // A. It wasn't able to perform indirection, i.e. the baseobj doesn't exist in memory.
+ // B. It's pointing to another link, which is illegal.
+ return LLAssetType::lookupIsLinkType(getType());
+}
+
+LLViewerInventoryItem *LLViewerInventoryItem::getLinkedItem() const
+{
+ if (mType == LLAssetType::AT_LINK)
+ {
+ LLViewerInventoryItem *linked_item = gInventory.getItem(mAssetUUID);
+ if (linked_item && linked_item->getIsLinkType())
{
- body["notecard-id"] = notecard_inv_id;
- body["object-id"] = object_id;
- body["item-id"] = src->getUUID();
- body["folder-id"] = gInventory.findCategoryUUIDForType(src->getType());
- body["callback-id"] = (LLSD::Integer)callback_id;
+ llwarns << "Warning: Accessing link to link" << llendl;
+ return NULL;
+ }
+ return linked_item;
+ }
+ return NULL;
+}
+
+LLViewerInventoryCategory *LLViewerInventoryItem::getLinkedCategory() const
+{
+ if (mType == LLAssetType::AT_LINK_FOLDER)
+ {
+ LLViewerInventoryCategory *linked_category = gInventory.getCategory(mAssetUUID);
+ return linked_category;
+ }
+ return NULL;
+}
- LLHTTPClient::post(url, body, new LLCopyInventoryFromNotecardResponder());
+bool LLViewerInventoryItem::checkPermissionsSet(PermissionMask mask) const
+{
+ const LLPermissions& perm = getPermissions();
+ PermissionMask curr_mask = PERM_NONE;
+ if(perm.getOwner() == gAgent.getID())
+ {
+ curr_mask = perm.getMaskBase();
+ }
+ else if(gAgent.isInGroup(perm.getGroup()))
+ {
+ curr_mask = perm.getMaskGroup();
+ }
+ else
+ {
+ curr_mask = perm.getMaskEveryone();
+ }
+ return ((curr_mask & mask) == mask);
+}
+
+//----------
+
+void LLViewerInventoryItem::onCallingCardNameLookup(const LLUUID& id, const std::string& first_name, const std::string& last_name)
+{
+ rename(first_name + " " + last_name);
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, getUUID());
+ gInventory.notifyObservers();
+}
+
+class LLRegenerateLinkCollector : public LLInventoryCollectFunctor
+{
+public:
+ LLRegenerateLinkCollector(const LLViewerInventoryItem *target_item) : mTargetItem(target_item) {}
+ virtual ~LLRegenerateLinkCollector() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item)
+ {
+ if (item)
+ {
+ if ((item->getName() == mTargetItem->getName()) &&
+ (item->getInventoryType() == mTargetItem->getInventoryType()) &&
+ (!item->getIsLinkType()))
+ {
+ return true;
+ }
}
+ return false;
+ }
+protected:
+ const LLViewerInventoryItem* mTargetItem;
+};
+
+LLUUID find_possible_item_for_regeneration(const LLViewerInventoryItem *target_item)
+{
+ LLViewerInventoryCategory::cat_array_t cats;
+ LLViewerInventoryItem::item_array_t items;
+
+ LLRegenerateLinkCollector candidate_matches(target_item);
+ gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
+ cats,
+ items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ candidate_matches);
+ for (LLViewerInventoryItem::item_array_t::const_iterator item_iter = items.begin();
+ item_iter != items.end();
+ ++item_iter)
+ {
+ const LLViewerInventoryItem *item = (*item_iter);
+ if (true) return item->getUUID();
+ }
+ return LLUUID::null;
+}
+
+// This currently dosen't work, because the sim does not allow us
+// to change an item's assetID.
+BOOL LLViewerInventoryItem::regenerateLink()
+{
+ const LLUUID target_item_id = find_possible_item_for_regeneration(this);
+ if (target_item_id.isNull())
+ return FALSE;
+ LLViewerInventoryCategory::cat_array_t cats;
+ LLViewerInventoryItem::item_array_t items;
+ LLAssetIDMatches asset_id_matches(getAssetUUID());
+ gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
+ cats,
+ items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ asset_id_matches);
+ for (LLViewerInventoryItem::item_array_t::iterator item_iter = items.begin();
+ item_iter != items.end();
+ item_iter++)
+ {
+ LLViewerInventoryItem *item = (*item_iter);
+ item->setAssetUUID(target_item_id);
+ item->updateServer(FALSE);
+ gInventory.addChangedMask(LLInventoryObserver::REBUILD, item->getUUID());
}
+ gInventory.notifyObservers();
+ return TRUE;
}
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index 1ddf8a58f9..917b8747ea 100644
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -37,6 +37,12 @@
#include "llframetimer.h"
#include "llwearable.h"
+#include <boost/signals2.hpp> // boost::signals2::trackable
+
+class LLFolderView;
+class LLFolderBridge;
+class LLViewerInventoryCategory;
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLViewerInventoryItem
//
@@ -44,15 +50,40 @@
// their inventory.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLViewerInventoryItem : public LLInventoryItem
+class LLViewerInventoryItem : public LLInventoryItem, public boost::signals2::trackable
{
public:
typedef LLDynamicArray<LLPointer<LLViewerInventoryItem> > item_array_t;
protected:
~LLViewerInventoryItem( void ); // ref counted
+ BOOL extractSortFieldAndDisplayName(S32* sortField, std::string* displayName) const { return extractSortFieldAndDisplayName(mName, sortField, displayName); }
+ static char getSeparator() { return '@'; }
+ mutable std::string mDisplayName;
public:
+ virtual LLAssetType::EType getType() const;
+ virtual const LLUUID& getAssetUUID() const;
+ virtual const std::string& getName() const;
+ virtual const std::string& getDisplayName() const;
+ static std::string getDisplayName(const std::string& name);
+ virtual S32 getSortField() const;
+ virtual void setSortField(S32 sortField);
+ virtual void rename(const std::string& new_name);
+ virtual const LLPermissions& getPermissions() const;
+ virtual const LLUUID& getCreatorUUID() const;
+ virtual const std::string& getDescription() const;
+ virtual const LLSaleInfo& getSaleInfo() const;
+ virtual LLInventoryType::EType getInventoryType() const;
+ virtual bool isWearableType() const;
+ virtual EWearableType getWearableType() const;
+ virtual U32 getFlags() const;
+ virtual time_t getCreationDate() const;
+ virtual U32 getCRC32() const; // really more of a checksum.
+
+ static BOOL extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName);
+ static void insertDefaultSortField(std::string& name);
+
// construct a complete viewer inventory item
LLViewerInventoryItem(const LLUUID& uuid, const LLUUID& parent_uuid,
const LLPermissions& permissions,
@@ -125,7 +156,20 @@ public:
};
LLTransactionID getTransactionID() const { return mTransactionID; }
-protected:
+ bool getIsBrokenLink() const; // true if the baseitem this points to doesn't exist in memory.
+ LLViewerInventoryItem *getLinkedItem() const;
+ LLViewerInventoryCategory *getLinkedCategory() const;
+
+ // Checks the items permissions (for owner, group, or everyone) and returns true if all mask bits are set.
+ bool checkPermissionsSet(PermissionMask mask) const;
+
+ // callback
+ void onCallingCardNameLookup(const LLUUID& id, const std::string& first_name, const std::string& last_name);
+
+ // If this is a broken link, try to fix it and any other identical link.
+ BOOL regenerateLink();
+
+public:
BOOL mIsComplete;
LLTransactionID mTransactionID;
};
@@ -149,7 +193,7 @@ protected:
public:
LLViewerInventoryCategory(const LLUUID& uuid, const LLUUID& parent_uuid,
- LLAssetType::EType preferred_type,
+ LLFolderType::EType preferred_type,
const std::string& name,
const LLUUID& owner_id);
LLViewerInventoryCategory(const LLUUID& owner_id);
@@ -184,7 +228,8 @@ public:
// other than cacheing.
bool exportFileLocal(LLFILE* fp) const;
bool importFileLocal(LLFILE* fp);
-
+ void determineFolderType();
+ void changeType(LLFolderType::EType new_folder_type);
protected:
LLUUID mOwnerID;
S32 mVersion;
@@ -203,6 +248,11 @@ class WearOnAvatarCallback : public LLInventoryCallback
void fire(const LLUUID& inv_item);
};
+class ModifiedCOFCallback : public LLInventoryCallback
+{
+ void fire(const LLUUID& inv_item);
+};
+
class LLViewerJointAttachment;
class RezAttachmentCallback : public LLInventoryCallback
@@ -230,6 +280,18 @@ public:
void fire(const LLUUID& inv_item);
};
+class AddFavoriteLandmarkCallback : public LLInventoryCallback
+{
+public:
+ AddFavoriteLandmarkCallback() : mTargetLandmarkId(LLUUID::null) {}
+ void setTargetLandmarkId(const LLUUID& target_uuid) { mTargetLandmarkId = target_uuid; }
+
+private:
+ void fire(const LLUUID& inv_item);
+
+ LLUUID mTargetLandmarkId;
+};
+
// misc functions
//void inventory_reliable_callback(void**, S32 status);
@@ -253,6 +315,7 @@ extern LLInventoryCallbackManager gInventoryCallbacks;
#define NOT_WEARABLE (EWearableType)0
+// *TODO: Find a home for these
void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
const LLUUID& parent, const LLTransactionID& transaction_id,
const std::string& name,
@@ -261,6 +324,8 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
U32 next_owner_perm,
LLPointer<LLInventoryCallback> cb);
+void create_inventory_callingcard(const LLUUID& avatar_id, const LLUUID& parent = LLUUID::null, LLPointer<LLInventoryCallback> cb=NULL);
+
/**
* @brief Securely create a new inventory item by copying from another.
*/
@@ -272,6 +337,14 @@ void copy_inventory_item(
const std::string& new_name,
LLPointer<LLInventoryCallback> cb);
+void link_inventory_item(
+ const LLUUID& agent_id,
+ const LLUUID& item_id,
+ const LLUUID& parent_id,
+ const std::string& new_name,
+ const LLAssetType::EType asset_type,
+ LLPointer<LLInventoryCallback> cb);
+
void move_inventory_item(
const LLUUID& agent_id,
const LLUUID& session_id,
@@ -286,4 +359,9 @@ void copy_inventory_from_notecard(const LLUUID& object_id,
U32 callback_id = 0);
+void menu_create_inventory_item(LLFolderView* folder,
+ LLFolderBridge* bridge,
+ const LLSD& userdata,
+ const LLUUID& default_parent_uuid = LLUUID::null);
+
#endif // LL_LLVIEWERINVENTORY_H
diff --git a/indra/newview/llviewerjoint.h b/indra/newview/llviewerjoint.h
index 0e993a2ebe..08c4ec36fd 100644
--- a/indra/newview/llviewerjoint.h
+++ b/indra/newview/llviewerjoint.h
@@ -37,7 +37,6 @@
// Header Files
//-----------------------------------------------------------------------------
#include "lljoint.h"
-#include "llapr.h"
class LLFace;
class LLViewerJointMesh;
diff --git a/indra/newview/llviewerjointattachment.cpp b/indra/newview/llviewerjointattachment.cpp
index 63c63e5546..2b4b78d82d 100644
--- a/indra/newview/llviewerjointattachment.cpp
+++ b/indra/newview/llviewerjointattachment.cpp
@@ -57,14 +57,14 @@ extern LLPipeline gPipeline;
// LLViewerJointAttachment()
//-----------------------------------------------------------------------------
LLViewerJointAttachment::LLViewerJointAttachment() :
-mAttachedObject(NULL),
-mVisibleInFirst(FALSE),
-mGroup(0),
-mIsHUDAttachment(FALSE),
-mPieSlice(-1)
+ mVisibleInFirst(FALSE),
+ mGroup(0),
+ mIsHUDAttachment(FALSE),
+ mPieSlice(-1)
{
mValid = FALSE;
mUpdateXform = FALSE;
+ mAttachedObjects.clear();
}
//-----------------------------------------------------------------------------
@@ -103,36 +103,43 @@ U32 LLViewerJointAttachment::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_
return 0;
}
-void LLViewerJointAttachment::setupDrawable(LLDrawable* drawablep)
+void LLViewerJointAttachment::setupDrawable(LLViewerObject *object)
{
- drawablep->mXform.setParent(&mXform); // LLViewerJointAttachment::lazyAttach
- drawablep->makeActive();
- LLVector3 current_pos = mAttachedObject->getRenderPosition();
- LLQuaternion current_rot = mAttachedObject->getRenderRotation();
- LLQuaternion attachment_pt_inv_rot = ~getWorldRotation();
+ if (!object->mDrawable)
+ return;
+ if (object->mDrawable->isActive())
+ {
+ object->mDrawable->makeStatic(FALSE);
+ }
+
+ object->mDrawable->mXform.setParent(getXform()); // LLViewerJointAttachment::lazyAttach
+ object->mDrawable->makeActive();
+ LLVector3 current_pos = object->getRenderPosition();
+ LLQuaternion current_rot = object->getRenderRotation();
+ LLQuaternion attachment_pt_inv_rot = ~(getWorldRotation());
current_pos -= getWorldPosition();
current_pos.rotVec(attachment_pt_inv_rot);
current_rot = current_rot * attachment_pt_inv_rot;
- drawablep->mXform.setPosition(current_pos);
- drawablep->mXform.setRotation(current_rot);
- gPipeline.markMoved(drawablep);
- gPipeline.markTextured(drawablep); // face may need to change draw pool to/from POOL_HUD
- drawablep->setState(LLDrawable::USE_BACKLIGHT);
+ object->mDrawable->mXform.setPosition(current_pos);
+ object->mDrawable->mXform.setRotation(current_rot);
+ gPipeline.markMoved(object->mDrawable);
+ gPipeline.markTextured(object->mDrawable); // face may need to change draw pool to/from POOL_HUD
+ object->mDrawable->setState(LLDrawable::USE_BACKLIGHT);
if(mIsHUDAttachment)
{
- for (S32 face_num = 0; face_num < drawablep->getNumFaces(); face_num++)
+ for (S32 face_num = 0; face_num < object->mDrawable->getNumFaces(); face_num++)
{
- drawablep->getFace(face_num)->setState(LLFace::HUD_RENDER);
+ object->mDrawable->getFace(face_num)->setState(LLFace::HUD_RENDER);
}
}
- LLViewerObject::const_child_list_t& child_list = mAttachedObject->getChildren();
+ LLViewerObject::const_child_list_t& child_list = object->getChildren();
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
+ iter != child_list.end(); ++iter)
{
LLViewerObject* childp = *iter;
if (childp && childp->mDrawable.notNull())
@@ -157,27 +164,13 @@ void LLViewerJointAttachment::setupDrawable(LLDrawable* drawablep)
//-----------------------------------------------------------------------------
BOOL LLViewerJointAttachment::addObject(LLViewerObject* object)
{
- if (mAttachedObject)
+ if (isObjectAttached(object))
{
- llwarns << "Attempted to attach object where an attachment already exists!" << llendl;
-
- if (mAttachedObject == object) {
- llinfos << "(same object re-attached)" << llendl;
- removeObject(mAttachedObject);
- // Pass through anyway to let setupDrawable()
- // re-connect object to the joint correctly
- }
- else {
- llinfos << "(objects differ, removing existing object)" << llendl;
- // Rather hacky, but no-one can think of something
- // better to do for this case.
- gObjectList.killObject(mAttachedObject);
- // Proceed with new object attachment
- }
+ llinfos << "(same object re-attached)" << llendl;
+ removeObject(object);
+ // Pass through anyway to let setupDrawable()
+ // re-connect object to the joint correctly
}
- mAttachedObject = object;
-
- LLUUID item_id;
// Find the inventory item ID of the attached object
LLNameValue* item_id_nv = object->getNVPair("AttachItemID");
@@ -186,26 +179,15 @@ BOOL LLViewerJointAttachment::addObject(LLViewerObject* object)
const char* s = item_id_nv->getString();
if( s )
{
- item_id.set( s );
+ LLUUID item_id;
+ item_id.set(s);
+ object->setItemID(item_id);
lldebugs << "getNVPair( AttachItemID ) = " << item_id << llendl;
}
}
-
- mItemID = item_id;
-
- LLDrawable* drawablep = object->mDrawable;
-
- if (drawablep)
- {
- //if object is active, make it static
- if(drawablep->isActive())
- {
- drawablep->makeStatic(FALSE) ;
- }
-
- setupDrawable(drawablep);
- }
-
+ mAttachedObjects.push_back(object);
+ setupDrawable(object);
+
if (mIsHUDAttachment)
{
if (object->mText.notNull())
@@ -214,7 +196,7 @@ BOOL LLViewerJointAttachment::addObject(LLViewerObject* object)
}
LLViewerObject::const_child_list_t& child_list = object->getChildren();
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
+ iter != child_list.end(); ++iter)
{
LLViewerObject* childp = *iter;
if (childp && childp->mText.notNull())
@@ -234,15 +216,33 @@ BOOL LLViewerJointAttachment::addObject(LLViewerObject* object)
//-----------------------------------------------------------------------------
void LLViewerJointAttachment::removeObject(LLViewerObject *object)
{
+ attachedobjs_vec_t::iterator iter;
+ for (iter = mAttachedObjects.begin();
+ iter != mAttachedObjects.end();
+ ++iter)
+ {
+ LLViewerObject *attached_object = (*iter);
+ if (attached_object == object)
+ {
+ break;
+ }
+ }
+ if (iter == mAttachedObjects.end())
+ {
+ llwarns << "Could not find object to detach" << llendl;
+ return;
+ }
+
// force object visibile
setAttachmentVisibility(TRUE);
+ mAttachedObjects.erase(iter);
if (object->mDrawable.notNull())
{
//if object is active, make it static
if(object->mDrawable->isActive())
{
- object->mDrawable->makeStatic(FALSE) ;
+ object->mDrawable->makeStatic(FALSE);
}
LLVector3 cur_position = object->getRenderPosition();
@@ -265,7 +265,7 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object)
LLViewerObject::const_child_list_t& child_list = object->getChildren();
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
+ iter != child_list.end(); ++iter)
{
LLViewerObject* childp = *iter;
if (childp && childp->mDrawable.notNull())
@@ -290,7 +290,7 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object)
}
LLViewerObject::const_child_list_t& child_list = object->getChildren();
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
+ iter != child_list.end(); ++iter)
{
LLViewerObject* childp = *iter;
if (childp->mText.notNull())
@@ -299,10 +299,11 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object)
}
}
}
-
- mAttachedObject = NULL;
- mUpdateXform = FALSE;
- mItemID.setNull();
+ if (mAttachedObjects.size() == 0)
+ {
+ mUpdateXform = FALSE;
+ }
+ object->setItemID(LLUUID::null);
}
//-----------------------------------------------------------------------------
@@ -310,20 +311,26 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object)
//-----------------------------------------------------------------------------
void LLViewerJointAttachment::setAttachmentVisibility(BOOL visible)
{
- if (!mAttachedObject || mAttachedObject->mDrawable.isNull() ||
- !(mAttachedObject->mDrawable->getSpatialBridge()))
- return;
-
- if (visible)
- {
- // Hack to make attachments not visible by disabling their type mask!
- // This will break if you can ever attach non-volumes! - djs 02/14/03
- mAttachedObject->mDrawable->getSpatialBridge()->mDrawableType =
- mAttachedObject->isHUDAttachment() ? LLPipeline::RENDER_TYPE_HUD : LLPipeline::RENDER_TYPE_VOLUME;
- }
- else
+ for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin();
+ iter != mAttachedObjects.end();
+ ++iter)
{
- mAttachedObject->mDrawable->getSpatialBridge()->mDrawableType = 0;
+ LLViewerObject *attached_obj = (*iter);
+ if (!attached_obj || attached_obj->mDrawable.isNull() ||
+ !(attached_obj->mDrawable->getSpatialBridge()))
+ continue;
+
+ if (visible)
+ {
+ // Hack to make attachments not visible by disabling their type mask!
+ // This will break if you can ever attach non-volumes! - djs 02/14/03
+ attached_obj->mDrawable->getSpatialBridge()->mDrawableType =
+ attached_obj->isHUDAttachment() ? LLPipeline::RENDER_TYPE_HUD : LLPipeline::RENDER_TYPE_VOLUME;
+ }
+ else
+ {
+ attached_obj->mDrawable->getSpatialBridge()->mDrawableType = 0;
+ }
}
}
@@ -341,14 +348,19 @@ void LLViewerJointAttachment::setOriginalPosition(LLVector3& position)
//-----------------------------------------------------------------------------
void LLViewerJointAttachment::clampObjectPosition()
{
- if (mAttachedObject)
+ for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin();
+ iter != mAttachedObjects.end();
+ ++iter)
{
- // *NOTE: object can drift when hitting maximum radius
- LLVector3 attachmentPos = mAttachedObject->getPosition();
- F32 dist = attachmentPos.normVec();
- dist = llmin(dist, MAX_ATTACHMENT_DIST);
- attachmentPos *= dist;
- mAttachedObject->setPosition(attachmentPos);
+ if (LLViewerObject *attached_object = (*iter))
+ {
+ // *NOTE: object can drift when hitting maximum radius
+ LLVector3 attachmentPos = attached_object->getPosition();
+ F32 dist = attachmentPos.normVec();
+ dist = llmin(dist, MAX_ATTACHMENT_DIST);
+ attachmentPos *= dist;
+ attached_object->setPosition(attachmentPos);
+ }
}
}
@@ -357,14 +369,23 @@ void LLViewerJointAttachment::clampObjectPosition()
//-----------------------------------------------------------------------------
void LLViewerJointAttachment::calcLOD()
{
- F32 maxarea = mAttachedObject->getMaxScale() * mAttachedObject->getMidScale();
- LLViewerObject::const_child_list_t& child_list = mAttachedObject->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
+ F32 maxarea = 0;
+ for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin();
+ iter != mAttachedObjects.end();
+ ++iter)
{
- LLViewerObject* childp = *iter;
- F32 area = childp->getMaxScale() * childp->getMidScale();
- maxarea = llmax(maxarea, area);
+ if (LLViewerObject *attached_object = (*iter))
+ {
+ maxarea = llmax(maxarea,attached_object->getMaxScale() * attached_object->getMidScale());
+ LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
+ for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
+ iter != child_list.end(); ++iter)
+ {
+ LLViewerObject* childp = *iter;
+ F32 area = childp->getMaxScale() * childp->getMidScale();
+ maxarea = llmax(maxarea, area);
+ }
+ }
}
maxarea = llclamp(maxarea, .01f*.01f, 1.f);
F32 avatar_area = (4.f * 4.f); // pixels for an avatar sized attachment
@@ -386,3 +407,47 @@ BOOL LLViewerJointAttachment::updateLOD(F32 pixel_area, BOOL activate)
return res;
}
+BOOL LLViewerJointAttachment::isObjectAttached(const LLViewerObject *viewer_object) const
+{
+ for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin();
+ iter != mAttachedObjects.end();
+ ++iter)
+ {
+ const LLViewerObject* attached_object = (*iter);
+ if (attached_object == viewer_object)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+const LLViewerObject *LLViewerJointAttachment::getAttachedObject(const LLUUID &object_id) const
+{
+ for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin();
+ iter != mAttachedObjects.end();
+ ++iter)
+ {
+ const LLViewerObject* attached_object = (*iter);
+ if (attached_object->getItemID() == object_id)
+ {
+ return attached_object;
+ }
+ }
+ return NULL;
+}
+
+LLViewerObject *LLViewerJointAttachment::getAttachedObject(const LLUUID &object_id)
+{
+ for (attachedobjs_vec_t::iterator iter = mAttachedObjects.begin();
+ iter != mAttachedObjects.end();
+ ++iter)
+ {
+ LLViewerObject* attached_object = (*iter);
+ if (attached_object->getItemID() == object_id)
+ {
+ return attached_object;
+ }
+ }
+ return NULL;
+}
diff --git a/indra/newview/llviewerjointattachment.h b/indra/newview/llviewerjointattachment.h
index 4847ac7a72..221b5460f1 100644
--- a/indra/newview/llviewerjointattachment.h
+++ b/indra/newview/llviewerjointattachment.h
@@ -71,20 +71,20 @@ public:
void setPieSlice(S32 pie_slice) { mPieSlice = pie_slice; }
void setVisibleInFirstPerson(BOOL visibility) { mVisibleInFirst = visibility; }
- BOOL getVisibleInFirstPerson() { return mVisibleInFirst; }
+ BOOL getVisibleInFirstPerson() const { return mVisibleInFirst; }
void setGroup(S32 group) { mGroup = group; }
void setOriginalPosition(LLVector3 &position);
void setAttachmentVisibility(BOOL visible);
void setIsHUDAttachment(BOOL is_hud) { mIsHUDAttachment = is_hud; }
- BOOL getIsHUDAttachment() { return mIsHUDAttachment; }
+ BOOL getIsHUDAttachment() const { return mIsHUDAttachment; }
- BOOL isAnimatable() { return FALSE; }
+ BOOL isAnimatable() const { return FALSE; }
- S32 getGroup() { return mGroup; }
- S32 getPieSlice() { return mPieSlice; }
- LLViewerObject *getObject() { return mAttachedObject; }
- S32 getNumObjects() { return (mAttachedObject ? 1 : 0); }
- const LLUUID& getItemID() { return mItemID; }
+ S32 getGroup() const { return mGroup; }
+ S32 getPieSlice() const { return mPieSlice; }
+ S32 getNumObjects() const { return mAttachedObjects.size(); }
+
+ void clampObjectPosition();
//
// unique methods
@@ -92,21 +92,27 @@ public:
BOOL addObject(LLViewerObject* object);
void removeObject(LLViewerObject *object);
- void setupDrawable(LLDrawable* drawable);
- void clampObjectPosition();
+ //
+ // attachments operations
+ //
+ BOOL isObjectAttached(const LLViewerObject *viewer_object) const;
+ const LLViewerObject *getAttachedObject(const LLUUID &object_id) const;
+ LLViewerObject *getAttachedObject(const LLUUID &object_id);
+
+ // list of attachments for this joint
+ typedef std::vector<LLViewerObject *> attachedobjs_vec_t;
+ attachedobjs_vec_t mAttachedObjects;
protected:
void calcLOD();
-
-protected:
- // Backlink only; don't make this an LLPointer.
- LLViewerObject* mAttachedObject;
+ void setupDrawable(LLViewerObject *object);
+
+private:
BOOL mVisibleInFirst;
LLVector3 mOriginalPos;
S32 mGroup;
BOOL mIsHUDAttachment;
S32 mPieSlice;
- LLUUID mItemID; // Inventory item id of the attached item (null if not in inventory)
};
#endif // LL_LLVIEWERJOINTATTACHMENT_H
diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp
index b6f0dafae6..5b8902dec4 100644
--- a/indra/newview/llviewerjointmesh.cpp
+++ b/indra/newview/llviewerjointmesh.cpp
@@ -39,7 +39,6 @@
#include "llfasttimer.h"
#include "llrender.h"
-#include "llagent.h"
#include "llapr.h"
#include "llbox.h"
#include "lldrawable.h"
@@ -52,7 +51,7 @@
#include "lltexlayer.h"
#include "llviewercamera.h"
#include "llviewercontrol.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewerjointmesh.h"
#include "llvoavatar.h"
#include "llsky.h"
@@ -230,7 +229,7 @@ void LLViewerJointMesh::setColor( F32 red, F32 green, F32 blue, F32 alpha )
//--------------------------------------------------------------------
// LLViewerJointMesh::getTexture()
//--------------------------------------------------------------------
-//LLViewerImage *LLViewerJointMesh::getTexture()
+//LLViewerTexture *LLViewerJointMesh::getTexture()
//{
// return mTexture;
//}
@@ -238,7 +237,7 @@ void LLViewerJointMesh::setColor( F32 red, F32 green, F32 blue, F32 alpha )
//--------------------------------------------------------------------
// LLViewerJointMesh::setTexture()
//--------------------------------------------------------------------
-void LLViewerJointMesh::setTexture( LLViewerImage *texture )
+void LLViewerJointMesh::setTexture( LLViewerTexture *texture )
{
mTexture = texture;
@@ -557,7 +556,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
{
if( mLayerSet->hasComposite() )
{
- gGL.getTexUnit(0)->bind(mLayerSet->getComposite()->getTexture());
+ gGL.getTexUnit(0)->bind(mLayerSet->getComposite());
}
else
{
@@ -565,21 +564,25 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
// Ignore the warning if that's the case.
if (!gSavedSettings.getBOOL("RenderUnloadedAvatar"))
{
- llwarns << "Layerset without composite" << llendl;
+ //llwarns << "Layerset without composite" << llendl;
}
- gGL.getTexUnit(0)->bind(gImageList.getImage(IMG_DEFAULT));
+ gGL.getTexUnit(0)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT));
}
}
else
if ( !is_dummy && mTexture.notNull() )
{
- old_mode = mTexture->getAddressMode();
+ if(mTexture->hasGLTexture())
+ {
+ old_mode = mTexture->getAddressMode();
+ }
gGL.getTexUnit(0)->bind(mTexture.get());
+ gGL.getTexUnit(0)->bind(mTexture);
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
}
else
{
- gGL.getTexUnit(0)->bind(gImageList.getImage(IMG_DEFAULT_AVATAR));
+ gGL.getTexUnit(0)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT));
}
if (gRenderForSelect)
@@ -633,7 +636,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
if (mTexture.notNull() && !is_dummy)
{
- gGL.getTexUnit(0)->bind(mTexture.get());
+ gGL.getTexUnit(0)->bind(mTexture);
gGL.getTexUnit(0)->setTextureAddressMode(old_mode);
}
diff --git a/indra/newview/llviewerjointmesh.h b/indra/newview/llviewerjointmesh.h
index 0cae48df93..d62b0ada85 100644
--- a/indra/newview/llviewerjointmesh.h
+++ b/indra/newview/llviewerjointmesh.h
@@ -34,10 +34,9 @@
#define LL_LLVIEWERJOINTMESH_H
#include "llviewerjoint.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
#include "llpolymesh.h"
#include "v4color.h"
-#include "llapr.h"
class LLDrawable;
class LLFace;
@@ -72,7 +71,7 @@ protected:
LLColor4 mColor; // color value
// LLColor4 mSpecular; // specular color (always white for now)
F32 mShiny; // shiny value
- LLPointer<LLViewerImage> mTexture; // ptr to a global texture
+ LLPointer<LLViewerTexture> mTexture; // ptr to a global texture
LLTexLayerSet* mLayerSet; // ptr to a layer set owned by the avatar
U32 mTestImageName; // handle to a temporary texture for previewing uploads
LLPolyMesh* mMesh; // ptr to a global polymesh
@@ -110,7 +109,7 @@ public:
void setSpecular( const LLColor4& color, F32 shiny ) { /*mSpecular = color;*/ mShiny = shiny; };
// Sets the shape texture
- void setTexture( LLViewerImage *texture );
+ void setTexture( LLViewerTexture *texture );
void setTestTexture( U32 name ) { mTestImageName = name; }
@@ -148,7 +147,7 @@ public:
void setIsTransparent(BOOL is_transparent) { mIsTransparent = is_transparent; }
- /*virtual*/ BOOL isAnimatable() { return FALSE; }
+ /*virtual*/ BOOL isAnimatable() const { return FALSE; }
static void updateVectorize(); // Update globals when settings variables change
diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp
index 9f7e4d338b..b593fbfb00 100644
--- a/indra/newview/llviewerjoystick.cpp
+++ b/indra/newview/llviewerjoystick.cpp
@@ -282,7 +282,7 @@ void LLViewerJoystick::terminate()
ndof_libcleanup();
llinfos << "Terminated connection with NDOF device." << llendl;
-
+ mDriverState = JDS_UNINITIALIZED;
#endif
}
@@ -414,14 +414,41 @@ void LLViewerJoystick::agentFly(F32 inc)
}
// -----------------------------------------------------------------------------
-void LLViewerJoystick::agentRotate(F32 pitch_inc, F32 yaw_inc)
+void LLViewerJoystick::agentPitch(F32 pitch_inc)
{
- LLQuaternion new_rot;
- pitch_inc = gAgent.clampPitchToLimits(-pitch_inc);
- const LLQuaternion qx(pitch_inc, gAgent.getLeftAxis());
- const LLQuaternion qy(-yaw_inc, gAgent.getReferenceUpVector());
- new_rot.setQuat(qx * qy);
- gAgent.rotate(new_rot);
+ if (pitch_inc < 0)
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_PITCH_POS);
+ }
+ else if (pitch_inc > 0)
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_PITCH_NEG);
+ }
+
+ gAgent.pitch(-pitch_inc);
+}
+
+// -----------------------------------------------------------------------------
+void LLViewerJoystick::agentYaw(F32 yaw_inc)
+{
+ // Cannot steer some vehicles in mouselook if the script grabs the controls
+ if (gAgent.cameraMouselook() && !gSavedSettings.getBOOL("JoystickMouselookYaw"))
+ {
+ gAgent.rotate(-yaw_inc, gAgent.getReferenceUpVector());
+ }
+ else
+ {
+ if (yaw_inc < 0)
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_YAW_POS);
+ }
+ else if (yaw_inc > 0)
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_YAW_NEG);
+ }
+
+ gAgent.yaw(-yaw_inc);
+ }
}
// -----------------------------------------------------------------------------
@@ -595,12 +622,38 @@ void LLViewerJoystick::moveAvatar(bool reset)
}
bool is_zero = true;
+ static bool button_held = false;
if (mBtn[1] == 1)
{
- agentJump();
+ // If AutomaticFly is enabled, then button1 merely causes a
+ // jump (as the up/down axis already controls flying) if on the
+ // ground, or cease flight if already flying.
+ // If AutomaticFly is disabled, then button1 toggles flying.
+ if (gSavedSettings.getBOOL("AutomaticFly"))
+ {
+ if (!gAgent.getFlying())
+ {
+ gAgent.moveUp(1);
+ }
+ else if (!button_held)
+ {
+ button_held = true;
+ gAgent.setFlying(FALSE);
+ }
+ }
+ else if (!button_held)
+ {
+ button_held = true;
+ gAgent.setFlying(!gAgent.getFlying());
+ }
+
is_zero = false;
}
+ else
+ {
+ button_held = false;
+ }
F32 axis_scale[] =
{
@@ -758,11 +811,13 @@ void LLViewerJoystick::moveAvatar(bool reset)
{
if (gAgent.getFlying())
{
- agentRotate(eff_rx, eff_ry);
+ agentPitch(eff_rx);
+ agentYaw(eff_ry);
}
else
{
- agentRotate(eff_rx, 2.f * eff_ry);
+ agentPitch(eff_rx);
+ agentYaw(2.f * eff_ry);
}
}
}
@@ -771,7 +826,8 @@ void LLViewerJoystick::moveAvatar(bool reset)
agentSlide(sDelta[X_I]); // move sideways
agentFly(sDelta[Y_I]); // up/down & crouch
agentPush(sDelta[Z_I]); // forward/back
- agentRotate(sDelta[RX_I], sDelta[RY_I]); // pitch & turn
+ agentPitch(sDelta[RX_I]); // pitch
+ agentYaw(sDelta[RY_I]); // turn
}
}
@@ -963,15 +1019,10 @@ bool LLViewerJoystick::toggleFlycam()
moveFlycam(true);
}
- else if (!LLToolMgr::getInstance()->inBuildMode())
- {
- moveAvatar(true);
- }
else
{
- // we are in build mode, exiting from the flycam mode: since we are
- // going to keep the flycam POV for the main camera until the avatar
- // moves, we need to track this situation.
+ // Exiting from the flycam mode: since we are going to keep the flycam POV for
+ // the main camera until the avatar moves, we need to track this situation.
setCameraNeedsUpdate(false);
setNeedsReset(true);
}
diff --git a/indra/newview/llviewerjoystick.h b/indra/newview/llviewerjoystick.h
index 6be9db3313..a3904bd2c3 100644
--- a/indra/newview/llviewerjoystick.h
+++ b/indra/newview/llviewerjoystick.h
@@ -56,6 +56,8 @@ public:
virtual ~LLViewerJoystick();
void init(bool autoenable);
+ void terminate();
+
void updateStatus();
void scanJoystick();
void moveObjects(bool reset = false);
@@ -76,13 +78,13 @@ public:
protected:
void updateEnabled(bool autoenable);
- void terminate();
void handleRun(F32 inc);
void agentSlide(F32 inc);
void agentPush(F32 inc);
void agentFly(F32 inc);
- void agentRotate(F32 pitch_inc, F32 turn_inc);
- void agentJump();
+ void agentPitch(F32 pitch_inc);
+ void agentYaw(F32 yaw_inc);
+ void agentJump();
void resetDeltas(S32 axis[]);
#if LIB_NDOF
static NDOF_HotPlugResult HotPlugAddCallback(NDOF_Device *dev);
diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp
index 15c814829c..f757155b94 100644
--- a/indra/newview/llviewerkeyboard.cpp
+++ b/indra/newview/llviewerkeyboard.cpp
@@ -36,14 +36,15 @@
#include "llviewerkeyboard.h"
#include "llmath.h"
#include "llagent.h"
-#include "llchatbar.h"
+#include "llnearbychatbar.h"
#include "llviewercontrol.h"
#include "llfocusmgr.h"
#include "llmorphview.h"
#include "llmoveview.h"
#include "lltoolfocus.h"
#include "llviewerwindow.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
+#include "llfloatercamera.h"
//
// Constants
@@ -98,7 +99,7 @@ static void agent_handle_doubletap_run(EKeystate s, LLAgent::EDoubleTapRunMode m
gAgent.sendWalkRun(gAgent.getRunning());
}
}
- else if (gAllowTapTapHoldRun &&
+ else if (gSavedSettings.getBOOL("AllowTapTapHoldRun") &&
KEYSTATE_DOWN == s &&
!gAgent.getRunning())
{
@@ -135,14 +136,29 @@ static void agent_push_forwardbackward( EKeystate s, S32 direction, LLAgent::EDo
}
}
+void camera_move_forward( EKeystate s );
+
void agent_push_forward( EKeystate s )
{
+ //in free camera control mode we need to intercept keyboard events for avatar movements
+ if (LLFloaterCamera::inFreeCameraMode())
+ {
+ camera_move_forward(s);
+ return;
+ }
agent_push_forwardbackward(s, 1, LLAgent::DOUBLETAP_FORWARD);
}
+void camera_move_backward( EKeystate s );
void agent_push_backward( EKeystate s )
{
+ //in free camera control mode we need to intercept keyboard events for avatar movements
+ if (LLFloaterCamera::inFreeCameraMode())
+ {
+ camera_move_backward(s);
+ return;
+ }
agent_push_forwardbackward(s, -1, LLAgent::DOUBLETAP_BACKWARD);
}
@@ -175,8 +191,17 @@ void agent_slide_right( EKeystate s )
agent_slide_leftright(s, -1, LLAgent::DOUBLETAP_SLIDERIGHT);
}
+void camera_spin_around_cw( EKeystate s );
+
void agent_turn_left( EKeystate s )
{
+ //in free camera control mode we need to intercept keyboard events for avatar movements
+ if (LLFloaterCamera::inFreeCameraMode())
+ {
+ camera_spin_around_cw(s);
+ return;
+ }
+
if (LLToolCamera::getInstance()->mouseSteerMode())
{
agent_slide_left(s);
@@ -189,9 +214,17 @@ void agent_turn_left( EKeystate s )
}
}
+void camera_spin_around_ccw( EKeystate s );
void agent_turn_right( EKeystate s )
{
+ //in free camera control mode we need to intercept keyboard events for avatar movements
+ if (LLFloaterCamera::inFreeCameraMode())
+ {
+ camera_spin_around_ccw(s);
+ return;
+ }
+
if (LLToolCamera::getInstance()->mouseSteerMode())
{
agent_slide_right(s);
@@ -224,7 +257,7 @@ void agent_toggle_fly( EKeystate s )
// Only catch the edge
if (KEYSTATE_DOWN == s )
{
- gAgent.toggleFlying();
+ LLAgent::toggleFlying();
}
}
@@ -500,24 +533,25 @@ void stop_moving( EKeystate s )
void start_chat( EKeystate s )
{
// start chat
- gChatBar->startChat(NULL);
+ LLNearbyChatBar::startChat(NULL);
}
void start_gesture( EKeystate s )
{
+ LLUICtrl* focus_ctrlp = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
if (KEYSTATE_UP == s &&
- !(gFocusMgr.getKeyboardFocus() && gFocusMgr.getKeyboardFocus()->acceptsTextInput()))
+ ! (focus_ctrlp && focus_ctrlp->acceptsTextInput()))
{
- if (gChatBar->getCurrentChat().empty())
- {
- // No existing chat in chat editor, insert '/'
- gChatBar->startChat("/");
- }
- else
- {
- // Don't overwrite existing text in chat editor
- gChatBar->startChat(NULL);
- }
+ if (LLNearbyChatBar::getInstance()->getCurrentChat().empty())
+ {
+ // No existing chat in chat editor, insert '/'
+ LLNearbyChatBar::startChat("/");
+ }
+ else
+ {
+ // Don't overwrite existing text in chat editor
+ LLNearbyChatBar::startChat(NULL);
+ }
}
}
@@ -683,7 +717,7 @@ BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, c
if (idx >=2 && idx <= 12)
{
U32 keyidx = ((mask<<16)|key);
- (mRemapKeys[mode])[keyidx] = ((0<<16)|KEY_F1+(idx-1));
+ (mRemapKeys[mode])[keyidx] = ((0<<16)|(KEY_F1+(idx-1)));
return TRUE;
}
}
@@ -842,7 +876,7 @@ EKeyboardMode LLViewerKeyboard::getMode()
{
return MODE_EDIT_AVATAR;
}
- else if (gAgent.getAvatarObject() && gAgent.getAvatarObject()->mIsSitting)
+ else if (gAgent.getAvatarObject() && gAgent.getAvatarObject()->isSitting())
{
return MODE_SITTING;
}
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 70fc78d277..98d8780b34 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -32,675 +32,2660 @@
#include "llviewerprecompiledheaders.h"
+#include "llagent.h"
#include "llviewermedia.h"
-
+#include "llviewermediafocus.h"
#include "llmimetypes.h"
+#include "llmediaentry.h"
+#include "llversioninfo.h"
#include "llviewercontrol.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
+#include "llviewerparcelmedia.h"
+#include "llviewerparcelmgr.h"
+#include "llviewertexturelist.h"
+#include "llvovolume.h"
+#include "llpluginclassmedia.h"
#include "llviewerwindow.h"
-#include "llversionviewer.h"
-#include "llviewerimagelist.h"
+#include "llfocusmgr.h"
+#include "llcallbacklist.h"
+#include "llparcel.h"
+#include "llaudioengine.h" // for gAudiop
#include "llevent.h" // LLSimpleListener
-#include "llmediamanager.h"
+#include "llnotificationsutil.h"
#include "lluuid.h"
+#include "llkeyboard.h"
+#include "llmutelist.h"
+//#include "llfirstuse.h"
#include <boost/bind.hpp> // for SkinFolder listener
-#include <boost/signal.hpp>
-
-
-// Implementation functions not exported into header file
-class LLViewerMediaImpl
- : public LLMediaObserver
-{
- public:
- LLViewerMediaImpl()
- : mMediaSource( NULL ),
- mMovieImageID(),
- mMovieImageHasMips(false)
- { }
-
- void destroyMediaSource();
-
- void play(const std::string& media_url,
- const std::string& mime_type,
- const LLUUID& placeholder_texture_id,
- S32 media_width, S32 media_height, U8 media_auto_scale,
- U8 media_loop);
-
- void stop();
- void pause();
- void start();
- void seek(F32 time);
- void setVolume(F32 volume);
- LLMediaBase::EStatus getStatus();
-
- /*virtual*/ void onMediaSizeChange(const EventType& event_in);
- /*virtual*/ void onMediaContentsChange(const EventType& event_in);
-
- void updateMovieImage(const LLUUID& image_id, BOOL active);
- void updateImagesMediaStreams();
- LLUUID getMediaTextureID();
-
- // Internally set our desired browser user agent string, including
- // the Second Life version and skin name. Used because we can
- // switch skins without restarting the app.
- static void updateBrowserUserAgent();
-
- // Callback for when the SkinCurrent control is changed to
- // switch the user agent string to indicate the new skin.
- static bool handleSkinCurrentChanged(const LLSD& newvalue);
-
- public:
-
- // a single media url with some data and an impl.
- LLMediaBase* mMediaSource;
- LLUUID mMovieImageID;
- bool mMovieImageHasMips;
- std::string mMediaURL;
- std::string mMimeType;
- private:
- void initializePlaceholderImage(LLViewerImage *placeholder_image, LLMediaBase *media_source);
-};
+#include <boost/signals2.hpp>
-static LLViewerMediaImpl sViewerMediaImpl;
+/*static*/ const char* LLViewerMedia::AUTO_PLAY_MEDIA_SETTING = "ParcelMediaAutoPlayEnable";
-//////////////////////////////////////////////////////////////////////////////////////////
+// Move this to its own file.
-void LLViewerMediaImpl::destroyMediaSource()
+LLViewerMediaEventEmitter::~LLViewerMediaEventEmitter()
{
- LLMediaManager* mgr = LLMediaManager::getInstance();
- if ( mMediaSource )
+ observerListType::iterator iter = mObservers.begin();
+
+ while( iter != mObservers.end() )
{
- bool was_playing = LLViewerMedia::isMediaPlaying();
- mMediaSource->remObserver(this);
- mgr->destroySource( mMediaSource );
+ LLViewerMediaObserver *self = *iter;
+ iter++;
+ remObserver(self);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+bool LLViewerMediaEventEmitter::addObserver( LLViewerMediaObserver* observer )
+{
+ if ( ! observer )
+ return false;
- // Restore the texture
- updateMovieImage(LLUUID::null, was_playing);
+ if ( std::find( mObservers.begin(), mObservers.end(), observer ) != mObservers.end() )
+ return false;
+ mObservers.push_back( observer );
+ observer->mEmitters.push_back( this );
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+bool LLViewerMediaEventEmitter::remObserver( LLViewerMediaObserver* observer )
+{
+ if ( ! observer )
+ return false;
+
+ mObservers.remove( observer );
+ observer->mEmitters.remove(this);
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+void LLViewerMediaEventEmitter::emitEvent( LLPluginClassMedia* media, LLViewerMediaObserver::EMediaEvent event )
+{
+ // Broadcast the event to any observers.
+ observerListType::iterator iter = mObservers.begin();
+ while( iter != mObservers.end() )
+ {
+ LLViewerMediaObserver *self = *iter;
+ ++iter;
+ self->handleMediaEvent( media, event );
}
- mMediaSource = NULL;
}
-void LLViewerMediaImpl::play(const std::string& media_url,
- const std::string& mime_type,
- const LLUUID& placeholder_texture_id,
- S32 media_width, S32 media_height, U8 media_auto_scale,
- U8 media_loop)
+// Move this to its own file.
+LLViewerMediaObserver::~LLViewerMediaObserver()
{
- // first stop any previously playing media
- stop();
+ std::list<LLViewerMediaEventEmitter *>::iterator iter = mEmitters.begin();
+
+ while( iter != mEmitters.end() )
+ {
+ LLViewerMediaEventEmitter *self = *iter;
+ iter++;
+ self->remObserver( this );
+ }
+}
- // Save this first, as init/load below may fire events
- mMovieImageID = placeholder_texture_id;
- // If the mime_type passed in is different than the cached one, and
- // Auto-discovery is turned OFF, replace the cached mime_type with the new one.
- if(mime_type != mMimeType &&
- ! gSavedSettings.getBOOL("AutoMimeDiscovery"))
+// Move this to its own file.
+// helper class that tries to download a URL from a web site and calls a method
+// on the Panel Land Media and to discover the MIME type
+class LLMimeDiscoveryResponder : public LLHTTPClient::Responder
+{
+LOG_CLASS(LLMimeDiscoveryResponder);
+public:
+ LLMimeDiscoveryResponder( viewer_media_t media_impl)
+ : mMediaImpl(media_impl),
+ mInitialized(false)
{
- mMimeType = mime_type;
+ if(mMediaImpl->mMimeTypeProbe != NULL)
+ {
+ llerrs << "impl already has an outstanding responder" << llendl;
+ }
+
+ mMediaImpl->mMimeTypeProbe = this;
}
- LLURI url(media_url);
- std::string scheme = url.scheme() != "" ? url.scheme() : "http";
- LLMediaManager* mgr = LLMediaManager::getInstance();
- mMediaSource = mgr->createSourceFromMimeType(scheme, mMimeType );
- if ( !mMediaSource )
+ ~LLMimeDiscoveryResponder()
{
- if (mMimeType != "none/none")
+ disconnectOwner();
+ }
+
+ virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+ {
+ std::string media_type = content["content-type"].asString();
+ std::string::size_type idx1 = media_type.find_first_of(";");
+ std::string mime_type = media_type.substr(0, idx1);
+
+ lldebugs << "status is " << status << ", media type \"" << media_type << "\"" << llendl;
+
+ // 2xx status codes indicate success.
+ // Most 4xx status codes are successful enough for our purposes.
+ // 499 is the error code for host not found, timeout, etc.
+ // 500 means "Internal Server error" but we decided it's okay to
+ // accept this and go past it in the MIME type probe
+ // 302 means the resource can be found temporarily in a different place - added this for join.secondlife.com
+ // 499 is a code specifc to join.secondlife.com (????) apparently safe to ignore
+// if( ((status >= 200) && (status < 300)) ||
+// ((status >= 400) && (status < 499)) ||
+// (status == 500) ||
+// (status == 302) ||
+// (status == 499)
+// )
+ // We now no longer check the error code returned from the probe.
+ // If we have a mime type, use it. If not, default to the web plugin and let it handle error reporting.
+ if(1)
{
- llwarns << "media source create failed " << media_url
- << " type " << mMimeType
- << llendl;
+ // The probe was successful.
+ if(mime_type.empty())
+ {
+ // Some sites don't return any content-type header at all.
+ // Treat an empty mime type as text/html.
+ mime_type = "text/html";
+ }
+
+ completeAny(status, mime_type);
+ }
+ else
+ {
+ llwarns << "responder failed with status " << status << ", reason " << reason << llendl;
+
+ if(mMediaImpl)
+ {
+ mMediaImpl->mMediaSourceFailed = true;
+ }
+ }
+
+ }
+
+ void completeAny(U32 status, const std::string& mime_type)
+ {
+ // the call to initializeMedia may disconnect the responder, which will clear mMediaImpl.
+ // Make a local copy so we can call loadURI() afterwards.
+ LLViewerMediaImpl *impl = mMediaImpl;
+
+ if(impl && !mInitialized && ! mime_type.empty())
+ {
+ if(impl->initializeMedia(mime_type))
+ {
+ mInitialized = true;
+ impl->loadURI();
+ disconnectOwner();
+ }
+ }
+ }
+
+ void cancelRequest()
+ {
+ disconnectOwner();
+ }
+
+private:
+ void disconnectOwner()
+ {
+ if(mMediaImpl)
+ {
+ if(mMediaImpl->mMimeTypeProbe != this)
+ {
+ llerrs << "internal error: mMediaImpl->mMimeTypeProbe != this" << llendl;
+ }
+
+ mMediaImpl->mMimeTypeProbe = NULL;
+ }
+ mMediaImpl = NULL;
+ }
+
+
+public:
+ LLViewerMediaImpl *mMediaImpl;
+ bool mInitialized;
+};
+static LLViewerMedia::impl_list sViewerMediaImplList;
+static LLViewerMedia::impl_id_map sViewerMediaTextureIDMap;
+static LLTimer sMediaCreateTimer;
+static const F32 LLVIEWERMEDIA_CREATE_DELAY = 1.0f;
+static F32 sGlobalVolume = 1.0f;
+static F64 sLowestLoadableImplInterest = 0.0f;
+
+//////////////////////////////////////////////////////////////////////////////////////////
+static void add_media_impl(LLViewerMediaImpl* media)
+{
+ sViewerMediaImplList.push_back(media);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+static void remove_media_impl(LLViewerMediaImpl* media)
+{
+ LLViewerMedia::impl_list::iterator iter = sViewerMediaImplList.begin();
+ LLViewerMedia::impl_list::iterator end = sViewerMediaImplList.end();
+
+ for(; iter != end; iter++)
+ {
+ if(media == *iter)
+ {
+ sViewerMediaImplList.erase(iter);
+ return;
}
- return;
}
+}
+
+class LLViewerMediaMuteListObserver : public LLMuteListObserver
+{
+ /* virtual */ void onChange() { LLViewerMedia::muteListChanged();}
+};
+
+static LLViewerMediaMuteListObserver sViewerMediaMuteListObserver;
+static bool sViewerMediaMuteListObserverInitialized = false;
+static bool sInWorldMediaDisabled = false;
- // Store the URL and Mime Type
- mMediaURL = media_url;
- if ((media_width != 0) && (media_height != 0))
+//////////////////////////////////////////////////////////////////////////////////////////
+// LLViewerMedia
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+viewer_media_t LLViewerMedia::newMediaImpl(
+ const LLUUID& texture_id,
+ S32 media_width,
+ S32 media_height,
+ U8 media_auto_scale,
+ U8 media_loop)
+{
+ LLViewerMediaImpl* media_impl = getMediaImplFromTextureID(texture_id);
+ if(media_impl == NULL || texture_id.isNull())
+ {
+ // Create the media impl
+ media_impl = new LLViewerMediaImpl(texture_id, media_width, media_height, media_auto_scale, media_loop);
+ }
+ else
{
- mMediaSource->setRequestedMediaSize(media_width, media_height);
+ media_impl->unload();
+ media_impl->setTextureID(texture_id);
+ media_impl->mMediaWidth = media_width;
+ media_impl->mMediaHeight = media_height;
+ media_impl->mMediaAutoScale = media_auto_scale;
+ media_impl->mMediaLoop = media_loop;
}
- mMediaSource->setLooping(media_loop);
- mMediaSource->setAutoScaled(media_auto_scale);
- mMediaSource->addObserver( this );
- mMediaSource->navigateTo( media_url );
- mMediaSource->addCommand(LLMediaBase::COMMAND_START);
+ return media_impl;
}
-void LLViewerMediaImpl::stop()
+viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const std::string& previous_url, bool update_from_self)
+{
+ // Try to find media with the same media ID
+ viewer_media_t media_impl = getMediaImplFromTextureID(media_entry->getMediaID());
+
+ lldebugs << "called, current URL is \"" << media_entry->getCurrentURL()
+ << "\", previous URL is \"" << previous_url
+ << "\", update_from_self is " << (update_from_self?"true":"false")
+ << llendl;
+
+ bool was_loaded = false;
+ bool needs_navigate = false;
+
+ if(media_impl)
+ {
+ was_loaded = media_impl->hasMedia();
+
+ media_impl->setHomeURL(media_entry->getHomeURL());
+
+ media_impl->mMediaAutoScale = media_entry->getAutoScale();
+ media_impl->mMediaLoop = media_entry->getAutoLoop();
+ media_impl->mMediaWidth = media_entry->getWidthPixels();
+ media_impl->mMediaHeight = media_entry->getHeightPixels();
+ media_impl->mMediaAutoPlay = media_entry->getAutoPlay();
+ media_impl->mMediaEntryURL = media_entry->getCurrentURL();
+ if (media_impl->mMediaSource)
+ {
+ media_impl->mMediaSource->setAutoScale(media_impl->mMediaAutoScale);
+ media_impl->mMediaSource->setLoop(media_impl->mMediaLoop);
+ media_impl->mMediaSource->setSize(media_entry->getWidthPixels(), media_entry->getHeightPixels());
+ }
+
+ bool url_changed = (media_impl->mMediaEntryURL != previous_url);
+ if(media_impl->mMediaEntryURL.empty())
+ {
+ if(url_changed)
+ {
+ // The current media URL is now empty. Unload the media source.
+ media_impl->unload();
+
+ lldebugs << "Unloading media instance (new current URL is empty)." << llendl;
+ }
+ }
+ else
+ {
+ // The current media URL is not empty.
+ // If (the media was already loaded OR the media was set to autoplay) AND this update didn't come from this agent,
+ // do a navigate.
+ bool auto_play = (media_impl->mMediaAutoPlay && gSavedSettings.getBOOL(AUTO_PLAY_MEDIA_SETTING));
+
+ if((was_loaded || auto_play) && !update_from_self)
+ {
+ needs_navigate = url_changed;
+ }
+
+ lldebugs << "was_loaded is " << (was_loaded?"true":"false")
+ << ", auto_play is " << (auto_play?"true":"false")
+ << ", needs_navigate is " << (needs_navigate?"true":"false") << llendl;
+ }
+ }
+ else
+ {
+ media_impl = newMediaImpl(
+ media_entry->getMediaID(),
+ media_entry->getWidthPixels(),
+ media_entry->getHeightPixels(),
+ media_entry->getAutoScale(),
+ media_entry->getAutoLoop());
+
+ media_impl->setHomeURL(media_entry->getHomeURL());
+ media_impl->mMediaAutoPlay = media_entry->getAutoPlay();
+ media_impl->mMediaEntryURL = media_entry->getCurrentURL();
+
+ if(media_impl->mMediaAutoPlay && gSavedSettings.getBOOL(AUTO_PLAY_MEDIA_SETTING))
+ {
+ needs_navigate = true;
+ }
+ }
+
+ if(media_impl)
+ {
+ if(needs_navigate)
+ {
+ media_impl->navigateTo(media_impl->mMediaEntryURL, "", true, true);
+ lldebugs << "navigating to URL " << media_impl->mMediaEntryURL << llendl;
+ }
+ else if(!media_impl->mMediaURL.empty() && (media_impl->mMediaURL != media_impl->mMediaEntryURL))
+ {
+ // If we already have a non-empty media URL set and we aren't doing a navigate, update the media URL to match the media entry.
+ media_impl->mMediaURL = media_impl->mMediaEntryURL;
+
+ // If this causes a navigate at some point (such as after a reload), it should be considered server-driven so it isn't broadcast.
+ media_impl->mNavigateServerRequest = true;
+
+ lldebugs << "updating URL in the media impl to " << media_impl->mMediaEntryURL << llendl;
+ }
+ }
+
+ return media_impl;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+LLViewerMediaImpl* LLViewerMedia::getMediaImplFromTextureID(const LLUUID& texture_id)
{
- destroyMediaSource();
+ LLViewerMediaImpl* result = NULL;
+
+ // Look up the texture ID in the texture id->impl map.
+ impl_id_map::iterator iter = sViewerMediaTextureIDMap.find(texture_id);
+ if(iter != sViewerMediaTextureIDMap.end())
+ {
+ result = iter->second;
+ }
+
+ return result;
}
-void LLViewerMediaImpl::pause()
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+std::string LLViewerMedia::getCurrentUserAgent()
{
- if(mMediaSource)
+ // Don't use user-visible string to avoid
+ // punctuation and strange characters.
+ std::string skin_name = gSavedSettings.getString("SkinCurrent");
+
+ // Just in case we need to check browser differences in A/B test
+ // builds.
+ std::string channel = gSavedSettings.getString("VersionChannelName");
+
+ // append our magic version number string to the browser user agent id
+ // See the HTTP 1.0 and 1.1 specifications for allowed formats:
+ // http://www.ietf.org/rfc/rfc1945.txt section 10.15
+ // http://www.ietf.org/rfc/rfc2068.txt section 3.8
+ // This was also helpful:
+ // http://www.mozilla.org/build/revised-user-agent-strings.html
+ std::ostringstream codec;
+ codec << "SecondLife/";
+ codec << LLVersionInfo::getVersion();
+ codec << " (" << channel << "; " << skin_name << " skin)";
+ llinfos << codec.str() << llendl;
+
+ return codec.str();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::updateBrowserUserAgent()
+{
+ std::string user_agent = getCurrentUserAgent();
+
+ impl_list::iterator iter = sViewerMediaImplList.begin();
+ impl_list::iterator end = sViewerMediaImplList.end();
+
+ for(; iter != end; iter++)
{
- mMediaSource->addCommand(LLMediaBase::COMMAND_PAUSE);
+ LLViewerMediaImpl* pimpl = *iter;
+ if(pimpl->mMediaSource && pimpl->mMediaSource->pluginSupportsMediaBrowser())
+ {
+ pimpl->mMediaSource->setBrowserUserAgent(user_agent);
+ }
}
+
}
-void LLViewerMediaImpl::start()
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::handleSkinCurrentChanged(const LLSD& /*newvalue*/)
{
- if(mMediaSource)
+ // gSavedSettings is already updated when this function is called.
+ updateBrowserUserAgent();
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::textureHasMedia(const LLUUID& texture_id)
+{
+ impl_list::iterator iter = sViewerMediaImplList.begin();
+ impl_list::iterator end = sViewerMediaImplList.end();
+
+ for(; iter != end; iter++)
{
- mMediaSource->addCommand(LLMediaBase::COMMAND_START);
+ LLViewerMediaImpl* pimpl = *iter;
+ if(pimpl->getMediaTextureID() == texture_id)
+ {
+ return true;
+ }
}
+ return false;
}
-void LLViewerMediaImpl::seek(F32 time)
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::setVolume(F32 volume)
{
- if(mMediaSource)
+ if(volume != sGlobalVolume)
{
- mMediaSource->seek(time);
+ sGlobalVolume = volume;
+ impl_list::iterator iter = sViewerMediaImplList.begin();
+ impl_list::iterator end = sViewerMediaImplList.end();
+
+ for(; iter != end; iter++)
+ {
+ LLViewerMediaImpl* pimpl = *iter;
+ pimpl->updateVolume();
+ }
}
}
-void LLViewerMediaImpl::setVolume(F32 volume)
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+F32 LLViewerMedia::getVolume()
{
- if(mMediaSource)
+ return sGlobalVolume;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::muteListChanged()
+{
+ // When the mute list changes, we need to check mute status on all impls.
+ impl_list::iterator iter = sViewerMediaImplList.begin();
+ impl_list::iterator end = sViewerMediaImplList.end();
+
+ for(; iter != end; iter++)
{
- mMediaSource->setVolume( volume);
+ LLViewerMediaImpl* pimpl = *iter;
+ pimpl->mNeedsMuteCheck = true;
}
}
-LLMediaBase::EStatus LLViewerMediaImpl::getStatus()
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::setInWorldMediaDisabled(bool disabled)
{
- if (mMediaSource)
+ sInWorldMediaDisabled = disabled;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::getInWorldMediaDisabled()
+{
+ return sInWorldMediaDisabled;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::isInterestingEnough(const LLVOVolume *object, const F64 &object_interest)
+{
+ bool result = false;
+
+ if (NULL == object)
{
- return mMediaSource->getStatus();
+ result = false;
+ }
+ // Focused? Then it is interesting!
+ else if (LLViewerMediaFocus::getInstance()->getFocusedObjectID() == object->getID())
+ {
+ result = true;
+ }
+ // Selected? Then it is interesting!
+ // XXX Sadly, 'contains()' doesn't take a const :(
+ else if (LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(object)))
+ {
+ result = true;
+ }
+ else
+ {
+ lldebugs << "object interest = " << object_interest << ", lowest loadable = " << sLowestLoadableImplInterest << llendl;
+ if(object_interest >= sLowestLoadableImplInterest)
+ result = true;
+ }
+
+ return result;
+}
+
+LLViewerMedia::impl_list &LLViewerMedia::getPriorityList()
+{
+ return sViewerMediaImplList;
+}
+
+// This is the predicate function used to sort sViewerMediaImplList by priority.
+bool LLViewerMedia::priorityComparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2)
+{
+ if(i1->isForcedUnloaded() && !i2->isForcedUnloaded())
+ {
+ // Muted or failed items always go to the end of the list, period.
+ return false;
+ }
+ else if(i2->isForcedUnloaded() && !i1->isForcedUnloaded())
+ {
+ // Muted or failed items always go to the end of the list, period.
+ return true;
+ }
+ else if(i1->hasFocus())
+ {
+ // The item with user focus always comes to the front of the list, period.
+ return true;
+ }
+ else if(i2->hasFocus())
+ {
+ // The item with user focus always comes to the front of the list, period.
+ return false;
+ }
+ else if(i1->isParcelMedia())
+ {
+ // The parcel media impl sorts above all other inworld media, unless one has focus.
+ return true;
+ }
+ else if(i2->isParcelMedia())
+ {
+ // The parcel media impl sorts above all other inworld media, unless one has focus.
+ return false;
+ }
+ else if(i1->getUsedInUI() && !i2->getUsedInUI())
+ {
+ // i1 is a UI element, i2 is not. This makes i1 "less than" i2, so it sorts earlier in our list.
+ return true;
+ }
+ else if(i2->getUsedInUI() && !i1->getUsedInUI())
+ {
+ // i2 is a UI element, i1 is not. This makes i2 "less than" i1, so it sorts earlier in our list.
+ return false;
+ }
+ else if(i1->isPlayable() && !i2->isPlayable())
+ {
+ // Playable items sort above ones that wouldn't play even if they got high enough priority
+ return true;
+ }
+ else if(!i1->isPlayable() && i2->isPlayable())
+ {
+ // Playable items sort above ones that wouldn't play even if they got high enough priority
+ return false;
+ }
+ else if(i1->getInterest() == i2->getInterest())
+ {
+ // Generally this will mean both objects have zero interest. In this case, sort on distance.
+ return (i1->getProximityDistance() < i2->getProximityDistance());
+ }
+ else
+ {
+ // The object with the larger interest value should be earlier in the list, so we reverse the sense of the comparison here.
+ return (i1->getInterest() > i2->getInterest());
+ }
+}
+
+static bool proximity_comparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2)
+{
+ if(i1->getProximityDistance() < i2->getProximityDistance())
+ {
+ return true;
+ }
+ else if(i1->getProximityDistance() > i2->getProximityDistance())
+ {
+ return false;
}
else
{
- return LLMediaBase::STATUS_UNKNOWN;
+ // Both objects have the same distance. This most likely means they're two faces of the same object.
+ // They may also be faces on different objects with exactly the same distance (like HUD objects).
+ // We don't actually care what the sort order is for this case, as long as it's stable and doesn't change when you enable/disable media.
+ // Comparing the impl pointers gives a completely arbitrary ordering, but it will be stable.
+ return (i1 < i2);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
// static
-void LLViewerMediaImpl::updateMovieImage(const LLUUID& uuid, BOOL active)
+void LLViewerMedia::updateMedia(void *dummy_arg)
{
- // IF the media image hasn't changed, do nothing
- if (mMovieImageID == uuid)
+ impl_list::iterator iter = sViewerMediaImplList.begin();
+ impl_list::iterator end = sViewerMediaImplList.end();
+
+ for(; iter != end; iter++)
{
- return;
+ LLViewerMediaImpl* pimpl = *iter;
+ pimpl->update();
+ pimpl->calculateInterest();
}
- // If we have changed media uuid, restore the old one
- if (!mMovieImageID.isNull())
+
+ // Sort the static instance list using our interest criteria
+ std::stable_sort(sViewerMediaImplList.begin(), sViewerMediaImplList.end(), priorityComparitor);
+
+ // Go through the list again and adjust according to priority.
+ iter = sViewerMediaImplList.begin();
+ end = sViewerMediaImplList.end();
+
+ F64 total_cpu = 0.0f;
+ int impl_count_total = 0;
+ int impl_count_interest_low = 0;
+ int impl_count_interest_normal = 0;
+
+ std::vector<LLViewerMediaImpl*> proximity_order;
+
+ bool inworld_media_enabled = gSavedSettings.getBOOL("AudioStreamingMedia");
+ bool needs_first_run = LLViewerMedia::needsMediaFirstRun();
+ U32 max_instances = gSavedSettings.getU32("PluginInstancesTotal");
+ U32 max_normal = gSavedSettings.getU32("PluginInstancesNormal");
+ U32 max_low = gSavedSettings.getU32("PluginInstancesLow");
+ F32 max_cpu = gSavedSettings.getF32("PluginInstancesCPULimit");
+ // Setting max_cpu to 0.0 disables CPU usage checking.
+ bool check_cpu_usage = (max_cpu != 0.0f);
+
+ LLViewerMediaImpl* lowest_interest_loadable = NULL;
+
+ // Notes on tweakable params:
+ // max_instances must be set high enough to allow the various instances used in the UI (for the help browser, search, etc.) to be loaded.
+ // If max_normal + max_low is less than max_instances, things will tend to get unloaded instead of being set to slideshow.
+
+ for(; iter != end; iter++)
{
- LLViewerImage* oldImage = LLViewerImage::getImage( mMovieImageID );
- if (oldImage)
+ LLViewerMediaImpl* pimpl = *iter;
+
+ LLPluginClassMedia::EPriority new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
+
+ if(pimpl->isForcedUnloaded() || (impl_count_total >= (int)max_instances))
+ {
+ // Never load muted or failed impls.
+ // Hard limit on the number of instances that will be loaded at one time
+ new_priority = LLPluginClassMedia::PRIORITY_UNLOADED;
+ }
+ else if(!pimpl->getVisible())
+ {
+ new_priority = LLPluginClassMedia::PRIORITY_HIDDEN;
+ }
+ else if(pimpl->hasFocus())
+ {
+ new_priority = LLPluginClassMedia::PRIORITY_HIGH;
+ impl_count_interest_normal++; // count this against the count of "normal" instances for priority purposes
+ }
+ else if(pimpl->getUsedInUI())
+ {
+ new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
+ impl_count_interest_normal++;
+ }
+ else if(pimpl->isParcelMedia())
+ {
+ new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
+ impl_count_interest_normal++;
+ }
+ else
+ {
+ // Look at interest and CPU usage for instances that aren't in any of the above states.
+
+ // Heuristic -- if the media texture's approximate screen area is less than 1/4 of the native area of the texture,
+ // turn it down to low instead of normal. This may downsample for plugins that support it.
+ bool media_is_small = false;
+ F64 approximate_interest = pimpl->getApproximateTextureInterest();
+ if(approximate_interest == 0.0f)
+ {
+ // this media has no current size, which probably means it's not loaded.
+ media_is_small = true;
+ }
+ else if(pimpl->getInterest() < (approximate_interest / 4))
+ {
+ media_is_small = true;
+ }
+
+ if(pimpl->getInterest() == 0.0f)
+ {
+ // This media is completely invisible, due to being outside the view frustrum or out of range.
+ new_priority = LLPluginClassMedia::PRIORITY_HIDDEN;
+ }
+ else if(check_cpu_usage && (total_cpu > max_cpu))
+ {
+ // Higher priority plugins have already used up the CPU budget. Set remaining ones to slideshow priority.
+ new_priority = LLPluginClassMedia::PRIORITY_SLIDESHOW;
+ }
+ else if((impl_count_interest_normal < (int)max_normal) && !media_is_small)
+ {
+ // Up to max_normal inworld get normal priority
+ new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
+ impl_count_interest_normal++;
+ }
+ else if (impl_count_interest_low + impl_count_interest_normal < (int)max_low + (int)max_normal)
+ {
+ // The next max_low inworld get turned down
+ new_priority = LLPluginClassMedia::PRIORITY_LOW;
+ impl_count_interest_low++;
+
+ // Set the low priority size for downsampling to approximately the size the texture is displayed at.
+ {
+ F32 approximate_interest_dimension = fsqrtf(pimpl->getInterest());
+
+ pimpl->setLowPrioritySizeLimit(llround(approximate_interest_dimension));
+ }
+ }
+ else
+ {
+ // Any additional impls (up to max_instances) get very infrequent time
+ new_priority = LLPluginClassMedia::PRIORITY_SLIDESHOW;
+ }
+ }
+
+ if(!pimpl->getUsedInUI() && (new_priority != LLPluginClassMedia::PRIORITY_UNLOADED))
{
- oldImage->reinit(mMovieImageHasMips);
- oldImage->mIsMediaTexture = FALSE;
+ // This is a loadable inworld impl -- the last one in the list in this class defines the lowest loadable interest.
+ lowest_interest_loadable = pimpl;
+
+ impl_count_total++;
}
- mMovieImageID.setNull();
+
+ // Overrides if the window is minimized or we lost focus (taking care
+ // not to accidentally "raise" the priority either)
+ if (!gViewerWindow->getActive() /* viewer window minimized? */
+ && new_priority > LLPluginClassMedia::PRIORITY_HIDDEN)
+ {
+ new_priority = LLPluginClassMedia::PRIORITY_HIDDEN;
+ }
+ else if (!gFocusMgr.getAppHasFocus() /* viewer window lost focus? */
+ && new_priority > LLPluginClassMedia::PRIORITY_LOW)
+ {
+ new_priority = LLPluginClassMedia::PRIORITY_LOW;
+ }
+
+ if(!inworld_media_enabled)
+ {
+ // If inworld media is locked out, force all inworld media to stay unloaded.
+ if(!pimpl->getUsedInUI())
+ {
+ new_priority = LLPluginClassMedia::PRIORITY_UNLOADED;
+ if(needs_first_run)
+ {
+ // Don't do this more than once in this loop.
+ needs_first_run = false;
+ LLViewerMedia::displayMediaFirstRun();
+ }
+ }
+ }
+
+ pimpl->setPriority(new_priority);
+
+ if(pimpl->getUsedInUI())
+ {
+ // Any impls used in the UI should not be in the proximity list.
+ pimpl->mProximity = -1;
+ }
+ else
+ {
+ proximity_order.push_back(pimpl);
+ }
+
+ total_cpu += pimpl->getCPUUsage();
}
- // If the movie is playing, set the new media image
- if (active && !uuid.isNull())
+
+ // Re-calculate this every time.
+ sLowestLoadableImplInterest = 0.0f;
+
+ // Only do this calculation if we've hit the impl count limit -- up until that point we always need to load media data.
+ if(lowest_interest_loadable && (impl_count_total >= (int)max_instances))
{
- LLViewerImage* viewerImage = LLViewerImage::getImage( uuid );
- if( viewerImage )
+ // Get the interest value of this impl's object for use by isInterestingEnough
+ LLVOVolume *object = lowest_interest_loadable->getSomeObject();
+ if(object)
{
- mMovieImageID = uuid;
- // Can't use mipmaps for movies because they don't update the full image
- mMovieImageHasMips = viewerImage->getUseMipMaps();
- viewerImage->reinit(FALSE);
- viewerImage->mIsMediaTexture = TRUE;
+ // NOTE: Don't use getMediaInterest() here. We want the pixel area, not the total media interest,
+ // so that we match up with the calculation done in LLMediaDataClient.
+ sLowestLoadableImplInterest = object->getPixelArea();
}
}
+
+ if(gSavedSettings.getBOOL("MediaPerformanceManagerDebug"))
+ {
+ // Give impls the same ordering as the priority list
+ // they're already in the right order for this.
+ }
+ else
+ {
+ // Use a distance-based sort for proximity values.
+ std::stable_sort(proximity_order.begin(), proximity_order.end(), proximity_comparitor);
+ }
+
+ // Transfer the proximity order to the proximity fields in the objects.
+ for(int i = 0; i < (int)proximity_order.size(); i++)
+ {
+ proximity_order[i]->mProximity = i;
+ }
+
+ LL_DEBUGS("PluginPriority") << "Total reported CPU usage is " << total_cpu << llendl;
+
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::initClass()
+{
+ gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, NULL);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::cleanupClass()
+{
+ gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, NULL);
}
//////////////////////////////////////////////////////////////////////////////////////////
// static
-void LLViewerMediaImpl::updateImagesMediaStreams()
+bool LLViewerMedia::needsMediaFirstRun()
{
- LLMediaManager::updateClass();
+ return gWarningSettings.getBOOL("FirstStreamingMedia");
}
-void LLViewerMediaImpl::initializePlaceholderImage(LLViewerImage *placeholder_image, LLMediaBase *media_source)
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::displayMediaFirstRun()
{
- int media_width = media_source->getMediaWidth();
- int media_height = media_source->getMediaHeight();
- //int media_rowspan = media_source->getMediaRowSpan();
+ gWarningSettings.setBOOL("FirstStreamingMedia", FALSE);
- // if width & height are invalid, don't bother doing anything
- if ( media_width < 1 || media_height < 1 )
- return;
+ LLNotificationsUtil::add("ParcelCanPlayMedia", LLSD(), LLSD(),
+ boost::bind(firstRunCallback, _1, _2));
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::firstRunCallback(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option == 0)
+ {
+ // user has elected to automatically play media.
+ gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, TRUE);
+ gSavedSettings.setBOOL("AudioStreamingMusic", TRUE);
+ gSavedSettings.setBOOL("AudioStreamingMedia", TRUE);
+
+ LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+
+ if (parcel)
+ {
+ // play media right now, if available
+ LLViewerParcelMedia::play(parcel);
+
+ // play music right now, if available
+ std::string music_url = parcel->getMusicURL();
+ if (gAudiop && !music_url.empty())
+ gAudiop->startInternetStream(music_url);
+ }
+ }
+ else
+ {
+ gSavedSettings.setBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING, FALSE);
+ gSavedSettings.setBOOL("AudioStreamingMedia", FALSE);
+ gSavedSettings.setBOOL("AudioStreamingMusic", FALSE);
+ }
+ return false;
+}
- llinfos << "initializing media placeholder" << llendl;
- llinfos << "movie image id " << mMovieImageID << llendl;
- int texture_width = LLMediaManager::textureWidthFromMediaWidth( media_width );
- int texture_height = LLMediaManager::textureHeightFromMediaHeight( media_height );
- int texture_depth = media_source->getMediaDepth();
+//////////////////////////////////////////////////////////////////////////////////////////
+// LLViewerMediaImpl
+//////////////////////////////////////////////////////////////////////////////////////////
+LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id,
+ S32 media_width,
+ S32 media_height,
+ U8 media_auto_scale,
+ U8 media_loop)
+:
+ mMediaSource( NULL ),
+ mMovieImageHasMips(false),
+ mMediaWidth(media_width),
+ mMediaHeight(media_height),
+ mMediaAutoScale(media_auto_scale),
+ mMediaLoop(media_loop),
+ mNeedsNewTexture(true),
+ mTextureUsedWidth(0),
+ mTextureUsedHeight(0),
+ mSuspendUpdates(false),
+ mVisible(true),
+ mLastSetCursor( UI_CURSOR_ARROW ),
+ mMediaNavState( MEDIANAVSTATE_NONE ),
+ mInterest(0.0f),
+ mUsedInUI(false),
+ mHasFocus(false),
+ mPriority(LLPluginClassMedia::PRIORITY_UNLOADED),
+ mNavigateRediscoverType(false),
+ mNavigateServerRequest(false),
+ mMediaSourceFailed(false),
+ mRequestedVolume(1.0f),
+ mIsMuted(false),
+ mNeedsMuteCheck(false),
+ mPreviousMediaState(MEDIA_NONE),
+ mPreviousMediaTime(0.0f),
+ mIsDisabled(false),
+ mIsParcelMedia(false),
+ mProximity(-1),
+ mProximityDistance(0.0f),
+ mMimeTypeProbe(NULL),
+ mMediaAutoPlay(false),
+ mInNearbyMediaList(false),
+ mClearCache(false),
+ mBackgroundColor(LLColor4::white),
+ mNavigateSuspended(false),
+ mNavigateSuspendedDeferred(false),
+ mIsUpdated(false)
+{
+
+ // Set up the mute list observer if it hasn't been set up already.
+ if(!sViewerMediaMuteListObserverInitialized)
+ {
+ LLMuteList::getInstance()->addObserver(&sViewerMediaMuteListObserver);
+ sViewerMediaMuteListObserverInitialized = true;
+ }
+
+ add_media_impl(this);
+
+ setTextureID(texture_id);
+
+ // connect this media_impl to the media texture, creating it if it doesn't exist.0
+ // This is necessary because we need to be able to use getMaxVirtualSize() even if the media plugin is not loaded.
+ LLViewerMediaTexture* media_tex = LLViewerTextureManager::getMediaTexture(mTextureId);
+ if(media_tex)
+ {
+ media_tex->setMediaImpl();
+ }
- // MEDIAOPT: check to see if size actually changed before doing work
- placeholder_image->destroyGLTexture();
- // MEDIAOPT: apparently just calling setUseMipMaps(FALSE) doesn't work?
- placeholder_image->reinit(FALSE); // probably not needed
+}
- // MEDIAOPT: seems insane that we actually have to make an imageraw then
- // immediately discard it
- LLPointer<LLImageRaw> raw = new LLImageRaw(texture_width, texture_height, texture_depth);
- raw->clear(0x0f, 0x0f, 0x0f, 0xff);
- int discard_level = 0;
+//////////////////////////////////////////////////////////////////////////////////////////
+LLViewerMediaImpl::~LLViewerMediaImpl()
+{
+ if( gEditMenuHandler == this )
+ {
+ gEditMenuHandler = NULL;
+ }
+
+ destroyMediaSource();
+
+ LLViewerMediaTexture::removeMediaImplFromTexture(mTextureId) ;
- // ask media source for correct GL image format constants
- placeholder_image->setExplicitFormat(media_source->getTextureFormatInternal(),
- media_source->getTextureFormatPrimary(),
- media_source->getTextureFormatType());
+ setTextureID();
+ remove_media_impl(this);
+}
- placeholder_image->createGLTexture(discard_level, raw);
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::emitEvent(LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event)
+{
+ // Broadcast to observers using the superclass version
+ LLViewerMediaEventEmitter::emitEvent(plugin, event);
+
+ // If this media is on one or more LLVOVolume objects, tell them about the event as well.
+ std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
+ while(iter != mObjectList.end())
+ {
+ LLVOVolume *self = *iter;
+ ++iter;
+ self->mediaEvent(this, plugin, event);
+ }
+}
- // placeholder_image->setExplicitFormat()
- placeholder_image->setUseMipMaps(FALSE);
+//////////////////////////////////////////////////////////////////////////////////////////
+bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type)
+{
+ bool mimeTypeChanged = (mMimeType != mime_type);
+ bool pluginChanged = (LLMIMETypes::implType(mCurrentMimeType) != LLMIMETypes::implType(mime_type));
+
+ if(!mMediaSource || pluginChanged)
+ {
+ // We don't have a plugin at all, or the new mime type is handled by a different plugin than the old mime type.
+ (void)initializePlugin(mime_type);
+ }
+ else if(mimeTypeChanged)
+ {
+ // The same plugin should be able to handle the new media -- just update the stored mime type.
+ mMimeType = mime_type;
+ }
- // MEDIAOPT: set this dynamically on play/stop
- placeholder_image->mIsMediaTexture = true;
+ return (mMediaSource != NULL);
}
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::createMediaSource()
+{
+ if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
+ {
+ // This media shouldn't be created yet.
+ return;
+ }
+
+ if(! mMediaURL.empty())
+ {
+ navigateInternal();
+ }
+ else if(! mMimeType.empty())
+ {
+ initializeMedia(mMimeType);
+ }
+}
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::destroyMediaSource()
+{
+ mNeedsNewTexture = true;
-// virtual
-void LLViewerMediaImpl::onMediaContentsChange(const EventType& event_in)
+ // Tell the viewer media texture it's no longer active
+ LLViewerMediaTexture* oldImage = LLViewerTextureManager::findMediaTexture( mTextureId );
+ if (oldImage)
+ {
+ oldImage->setPlaying(FALSE) ;
+ }
+
+ cancelMimeTypeProbe();
+
+ if(mMediaSource)
+ {
+ delete mMediaSource;
+ mMediaSource = NULL;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::setMediaType(const std::string& media_type)
+{
+ mMimeType = media_type;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+/*static*/
+LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height)
+{
+ std::string plugin_basename = LLMIMETypes::implType(media_type);
+
+ if(plugin_basename.empty())
+ {
+ LL_WARNS("Media") << "Couldn't find plugin for media type " << media_type << LL_ENDL;
+ }
+ else
+ {
+ std::string launcher_name = gDirUtilp->getLLPluginLauncher();
+ std::string plugin_name = gDirUtilp->getLLPluginFilename(plugin_basename);
+ std::string user_data_path = gDirUtilp->getOSUserAppDir();
+ user_data_path += gDirUtilp->getDirDelimiter();
+
+ // See if the plugin executable exists
+ llstat s;
+ if(LLFile::stat(launcher_name, &s))
+ {
+ LL_WARNS("Media") << "Couldn't find launcher at " << launcher_name << LL_ENDL;
+ }
+ else if(LLFile::stat(plugin_name, &s))
+ {
+ LL_WARNS("Media") << "Couldn't find plugin at " << plugin_name << LL_ENDL;
+ }
+ else
+ {
+ LLPluginClassMedia* media_source = new LLPluginClassMedia(owner);
+ media_source->setSize(default_width, default_height);
+ if (media_source->init(launcher_name, plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"), user_data_path))
+ {
+ return media_source;
+ }
+ else
+ {
+ LL_WARNS("Media") << "Failed to init plugin. Destroying." << LL_ENDL;
+ delete media_source;
+ }
+ }
+ }
+
+ LL_WARNS("Plugin") << "plugin intialization failed for mime type: " << media_type << LL_ENDL;
+ LLSD args;
+ args["MIME_TYPE"] = media_type;
+ LLNotificationsUtil::add("NoPlugin", args);
+
+ return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
{
- LLMediaBase* media_source = event_in.getSubject();
- LLViewerImage* placeholder_image = gImageList.getImage( mMovieImageID );
- if ((placeholder_image) && (placeholder_image->getHasGLTexture()))
+ if(mMediaSource)
{
- if (placeholder_image->getUseMipMaps())
+ // Save the previous media source's last set size before destroying it.
+ mMediaWidth = mMediaSource->getSetWidth();
+ mMediaHeight = mMediaSource->getSetHeight();
+ }
+
+ // Always delete the old media impl first.
+ destroyMediaSource();
+
+ // and unconditionally set the mime type
+ mMimeType = media_type;
+
+ if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
+ {
+ // This impl should not be loaded at this time.
+ LL_DEBUGS("PluginPriority") << this << "Not loading (PRIORITY_UNLOADED)" << LL_ENDL;
+
+ return false;
+ }
+
+ // If we got here, we want to ignore previous init failures.
+ mMediaSourceFailed = false;
+
+ // Save the MIME type that really caused the plugin to load
+ mCurrentMimeType = mMimeType;
+
+ LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight);
+
+ if (media_source)
+ {
+ media_source->setDisableTimeout(gSavedSettings.getBOOL("DebugPluginDisableTimeout"));
+ media_source->setLoop(mMediaLoop);
+ media_source->setAutoScale(mMediaAutoScale);
+ media_source->setBrowserUserAgent(LLViewerMedia::getCurrentUserAgent());
+ media_source->focus(mHasFocus);
+ media_source->setBackgroundColor(mBackgroundColor);
+
+ if(mClearCache)
{
- // bad image! NO MIPMAPS!
- initializePlaceholderImage(placeholder_image, media_source);
+ mClearCache = false;
+ media_source->clear_cache();
}
+
+ mMediaSource = media_source;
+
+ updateVolume();
- U8* data = media_source->getMediaData();
- S32 x_pos = 0;
- S32 y_pos = 0;
- S32 width = media_source->getMediaWidth();
- S32 height = media_source->getMediaHeight();
- S32 data_width = media_source->getMediaDataWidth();
- S32 data_height = media_source->getMediaDataHeight();
- placeholder_image->setSubImage(data, data_width, data_height,
- x_pos, y_pos, width, height);
+ return true;
}
+
+ // Make sure the timer doesn't try re-initing this plugin repeatedly until something else changes.
+ mMediaSourceFailed = true;
+
+ return false;
}
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::loadURI()
+{
+ if(mMediaSource)
+ {
+ // *HACK: we don't know if the URI coming in is properly escaped
+ // (the contract doesn't specify whether it is escaped or not.
+ // but LLQtWebKit expects it to be, so we do our best to encode
+ // special characters)
+ // The strings below were taken right from http://www.ietf.org/rfc/rfc1738.txt
+ // Note especially that '%' and '/' are there.
+ std::string uri = LLURI::escape(mMediaURL,
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "$-_.+"
+ "!*'(),"
+ "{}|\\^~[]`"
+ "<>#%"
+ ";/?:@&=",
+ false);
+ llinfos << "Asking media source to load URI: " << uri << llendl;
+
+ mMediaSource->loadURI( uri );
+
+ if(mPreviousMediaState == MEDIA_PLAYING)
+ {
+ // This media was playing before this instance was unloaded.
-// virtual
-void LLViewerMediaImpl::onMediaSizeChange(const EventType& event_in)
+ if(mPreviousMediaTime != 0.0f)
+ {
+ // Seek back to where we left off, if possible.
+ seek(mPreviousMediaTime);
+ }
+
+ start();
+ }
+ else if(mPreviousMediaState == MEDIA_PAUSED)
+ {
+ // This media was paused before this instance was unloaded.
+
+ if(mPreviousMediaTime != 0.0f)
+ {
+ // Seek back to where we left off, if possible.
+ seek(mPreviousMediaTime);
+ }
+
+ pause();
+ }
+ else
+ {
+ // No relevant previous media play state -- if we're loading the URL, we want to start playing.
+ start();
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::setSize(int width, int height)
{
- LLMediaBase* media_source = event_in.getSubject();
- LLViewerImage* placeholder_image = gImageList.getImage( mMovieImageID );
- if (placeholder_image)
+ mMediaWidth = width;
+ mMediaHeight = height;
+ if(mMediaSource)
{
- initializePlaceholderImage(placeholder_image, media_source);
+ mMediaSource->setSize(width, height);
}
- else
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::play()
+{
+ // If the media source isn't there, try to initialize it and load an URL.
+ if(mMediaSource == NULL)
+ {
+ if(!initializeMedia(mMimeType))
+ {
+ // This may be the case where the plugin's priority is PRIORITY_UNLOADED
+ return;
+ }
+
+ // Only do this if the media source was just loaded.
+ loadURI();
+ }
+
+ // always start the media
+ start();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::stop()
+{
+ if(mMediaSource)
{
- llinfos << "no placeholder image" << llendl;
+ mMediaSource->stop();
+ // destroyMediaSource();
}
}
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::pause()
+{
+ if(mMediaSource)
+ {
+ mMediaSource->pause();
+ }
+}
- // Get the image we're using
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::start()
+{
+ if(mMediaSource)
+ {
+ mMediaSource->start();
+ }
+}
- /*
- // update media stream if required
- LLMediaEngine* media_engine = LLMediaEngine::getInstance();
- if (media_engine)
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::seek(F32 time)
+{
+ if(mMediaSource)
+ {
+ mMediaSource->seek(time);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::skipBack(F32 step_scale)
+{
+ if(mMediaSource)
{
- if ( media_engine->update() )
+ if(mMediaSource->pluginSupportsMediaTime())
{
- LLUUID media_uuid = media_engine->getImageUUID();
- updateMovieImage(media_uuid, TRUE);
- if (!media_uuid.isNull())
+ F64 back_step = mMediaSource->getCurrentTime() - (mMediaSource->getDuration()*step_scale);
+ if(back_step < 0.0)
{
- LLViewerImage* viewerImage = getImage( media_uuid );
- if( viewerImage )
- {
- LLMediaBase* renderer = media_engine->getMediaRenderer();
- if ((renderer->getTextureWidth() != viewerImage->getWidth()) ||
- (renderer->getTextureHeight() != viewerImage->getHeight()) ||
- (renderer->getTextureDepth() != viewerImage->getComponents()) ||
- (viewerImage->getHasGLTexture() == FALSE))
- {
- // destroy existing GL image
- viewerImage->destroyGLTexture();
-
- // set new size
- viewerImage->setSize( renderer->getTextureWidth(),
- renderer->getTextureHeight(),
- renderer->getTextureDepth() );
-
- LLPointer<LLImageRaw> raw = new LLImageRaw(renderer->getTextureWidth(),
- renderer->getTextureHeight(),
- renderer->getTextureDepth());
- raw->clear(0x7f,0x7f,0x7f,0xff);
- viewerImage->createGLTexture(0, raw);
- }
-
- // Set the explicit format the instance wants
- viewerImage->setExplicitFormat(renderer->getTextureFormatInternal(),
- renderer->getTextureFormatPrimary(),
- renderer->getTextureFormatType(),
- renderer->getTextureFormatSwapBytes());
- // This should be redundant, but just in case:
- viewerImage->setUseMipMaps(FALSE);
-
- LLImageRaw* rawImage = media_engine->getImageRaw();
- if ( rawImage )
- {
- viewerImage->setSubImage(rawImage, 0, 0,
- renderer->getMediaWidth(),
- renderer->getMediaHeight());
- }
- }
- else
- {
- llwarns << "MediaEngine update unable to get viewer image for GL texture" << llendl;
- }
+ back_step = 0.0;
}
+ mMediaSource->seek(back_step);
}
- else
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::skipForward(F32 step_scale)
+{
+ if(mMediaSource)
+ {
+ if(mMediaSource->pluginSupportsMediaTime())
{
- LLUUID media_uuid = media_engine->getImageUUID();
- updateMovieImage(media_uuid, FALSE);
+ F64 forward_step = mMediaSource->getCurrentTime() + (mMediaSource->getDuration()*step_scale);
+ if(forward_step > mMediaSource->getDuration())
+ {
+ forward_step = mMediaSource->getDuration();
+ }
+ mMediaSource->seek(forward_step);
}
}
- */
+}
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::setVolume(F32 volume)
+{
+ mRequestedVolume = volume;
+ updateVolume();
+}
-LLUUID LLViewerMediaImpl::getMediaTextureID()
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::updateVolume()
{
- return mMovieImageID;
+ if(mMediaSource)
+ {
+ mMediaSource->setVolume(mRequestedVolume * LLViewerMedia::getVolume());
+ }
}
-// static
-void LLViewerMediaImpl::updateBrowserUserAgent()
+//////////////////////////////////////////////////////////////////////////////////////////
+F32 LLViewerMediaImpl::getVolume()
{
- // Don't use user-visible string to avoid
- // punctuation and strange characters.
- std::string skin_name = gSavedSettings.getString("SkinCurrent");
+ return mRequestedVolume;
+}
- // Just in case we need to check browser differences in A/B test
- // builds.
- std::string channel = gSavedSettings.getString("VersionChannelName");
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::focus(bool focus)
+{
+ mHasFocus = focus;
+
+ if (mMediaSource)
+ {
+ // call focus just for the hell of it, even though this apopears to be a nop
+ mMediaSource->focus(focus);
+ if (focus)
+ {
+ // spoof a mouse click to *actually* pass focus
+ // Don't do this anymore -- it actually clicks through now.
+// mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, 1, 1, 0);
+// mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, 1, 1, 0);
+ }
+ }
+}
- // append our magic version number string to the browser user agent id
- // See the HTTP 1.0 and 1.1 specifications for allowed formats:
- // http://www.ietf.org/rfc/rfc1945.txt section 10.15
- // http://www.ietf.org/rfc/rfc2068.txt section 3.8
- // This was also helpful:
- // http://www.mozilla.org/build/revised-user-agent-strings.html
- std::ostringstream codec;
- codec << "SecondLife/";
- codec << LL_VERSION_MAJOR << "." << LL_VERSION_MINOR << "." << LL_VERSION_PATCH << "." << LL_VERSION_BUILD;
- codec << " (" << channel << "; " << skin_name << " skin)";
- llinfos << codec.str() << llendl;
- LLMediaManager::setBrowserUserAgent( codec.str() );
+//////////////////////////////////////////////////////////////////////////////////////////
+bool LLViewerMediaImpl::hasFocus() const
+{
+ // FIXME: This might be able to be a bit smarter by hooking into LLViewerMediaFocus, etc.
+ return mHasFocus;
}
-// static
-bool LLViewerMediaImpl::handleSkinCurrentChanged(const LLSD& /*newvalue*/)
+std::string LLViewerMediaImpl::getCurrentMediaURL()
{
- // gSavedSettings is already updated when this function is called.
- updateBrowserUserAgent();
- return true;
+ if(!mCurrentMediaURL.empty())
+ {
+ return mCurrentMediaURL;
+ }
+
+ return mMediaURL;
}
//////////////////////////////////////////////////////////////////////////////////////////
-// Wrapper class
+void LLViewerMediaImpl::clearCache()
+{
+ if(mMediaSource)
+ {
+ mMediaSource->clear_cache();
+ }
+ else
+ {
+ mClearCache = true;
+ }
+}
+
//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::mouseDown(S32 x, S32 y, MASK mask, S32 button)
+{
+ scaleMouse(&x, &y);
+ mLastMouseX = x;
+ mLastMouseY = y;
+// llinfos << "mouse down (" << x << ", " << y << ")" << llendl;
+ if (mMediaSource)
+ {
+ mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, button, x, y, mask);
+ }
+}
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::mouseUp(S32 x, S32 y, MASK mask, S32 button)
+{
+ scaleMouse(&x, &y);
+ mLastMouseX = x;
+ mLastMouseY = y;
+// llinfos << "mouse up (" << x << ", " << y << ")" << llendl;
+ if (mMediaSource)
+ {
+ mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, button, x, y, mask);
+ }
+}
//////////////////////////////////////////////////////////////////////////////////////////
-// The viewer takes a long time to load the start screen. Part of the problem
-// is media initialization -- in particular, QuickTime loads many DLLs and
-// hits the disk heavily. So we initialize only the browser component before
-// the login screen, then do the rest later when we have a progress bar. JC
-// static
-void LLViewerMedia::initBrowser()
+void LLViewerMediaImpl::mouseMove(S32 x, S32 y, MASK mask)
{
- LLMediaManagerData* init_data = new LLMediaManagerData;
- buildMediaManagerData( init_data );
- LLMediaManager::initBrowser( init_data );
- delete init_data;
+ scaleMouse(&x, &y);
+ mLastMouseX = x;
+ mLastMouseY = y;
+// llinfos << "mouse move (" << x << ", " << y << ")" << llendl;
+ if (mMediaSource)
+ {
+ mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, x, y, mask);
+ }
+}
- // We use a custom user agent with viewer version and skin name.
- LLViewerMediaImpl::updateBrowserUserAgent();
+//////////////////////////////////////////////////////////////////////////////////////////
+//static
+void LLViewerMediaImpl::scaleTextureCoords(const LLVector2& texture_coords, S32 *x, S32 *y)
+{
+ F32 texture_x = texture_coords.mV[VX];
+ F32 texture_y = texture_coords.mV[VY];
+
+ // Deal with repeating textures by wrapping the coordinates into the range [0, 1.0)
+ texture_x = fmodf(texture_x, 1.0f);
+ if(texture_x < 0.0f)
+ texture_x = 1.0 + texture_x;
+
+ texture_y = fmodf(texture_y, 1.0f);
+ if(texture_y < 0.0f)
+ texture_y = 1.0 + texture_y;
+
+ // scale x and y to texel units.
+ *x = llround(texture_x * mMediaSource->getTextureWidth());
+ *y = llround((1.0f - texture_y) * mMediaSource->getTextureHeight());
+
+ // Adjust for the difference between the actual texture height and the amount of the texture in use.
+ *y -= (mMediaSource->getTextureHeight() - mMediaSource->getHeight());
}
//////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::initClass()
+void LLViewerMediaImpl::mouseDown(const LLVector2& texture_coords, MASK mask, S32 button)
+{
+ if(mMediaSource)
+ {
+ S32 x, y;
+ scaleTextureCoords(texture_coords, &x, &y);
+
+ mouseDown(x, y, mask, button);
+ }
+}
+
+void LLViewerMediaImpl::mouseUp(const LLVector2& texture_coords, MASK mask, S32 button)
+{
+ if(mMediaSource)
+ {
+ S32 x, y;
+ scaleTextureCoords(texture_coords, &x, &y);
+
+ mouseUp(x, y, mask, button);
+ }
+}
+
+void LLViewerMediaImpl::mouseMove(const LLVector2& texture_coords, MASK mask)
+{
+ if(mMediaSource)
+ {
+ S32 x, y;
+ scaleTextureCoords(texture_coords, &x, &y);
+
+ mouseMove(x, y, mask);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::mouseDoubleClick(S32 x, S32 y, MASK mask, S32 button)
{
- // *TODO: This looks like a memory leak to me. JC
- LLMediaManagerData* init_data = new LLMediaManagerData;
- buildMediaManagerData( init_data );
- LLMediaManager::initClass( init_data );
- delete init_data;
+ scaleMouse(&x, &y);
+ mLastMouseX = x;
+ mLastMouseY = y;
+ if (mMediaSource)
+ {
+ mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOUBLE_CLICK, button, x, y, mask);
+ }
+}
- LLMediaManager* mm = LLMediaManager::getInstance();
- LLMIMETypes::mime_info_map_t::const_iterator it;
- for (it = LLMIMETypes::sMap.begin(); it != LLMIMETypes::sMap.end(); ++it)
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::scrollWheel(S32 x, S32 y, MASK mask)
+{
+ scaleMouse(&x, &y);
+ mLastMouseX = x;
+ mLastMouseY = y;
+ if (mMediaSource)
{
- const std::string& mime_type = it->first;
- const LLMIMETypes::LLMIMEInfo& info = it->second;
- mm->addMimeTypeImplNameMap( mime_type, info.mImpl );
+ mMediaSource->scrollEvent(x, y, mask);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::buildMediaManagerData( LLMediaManagerData* init_data )
-{
-// std::string executable_dir = std::string( arg0 ).substr( 0, std::string( arg0 ).find_last_of("\\/") );
-// std::string component_dir = std::string( executable_dir ).substr( 0, std::string( executable_dir ).find_last_of("\\/") );
-// component_dir = std::string( component_dir ).substr( 0, std::string( component_dir ).find_last_of("\\/") );
-// component_dir = std::string( component_dir ).substr( 0, std::string( component_dir ).find_last_of("\\/") );
-// component_dir += "\\newview\\app_settings\\mozilla";
-
-
-#if LL_DARWIN
- // For Mac OS, we store both the shared libraries and the runtime files (chrome/, plugins/, etc) in
- // Second Life.app/Contents/MacOS/. This matches the way Firefox is distributed on the Mac.
- std::string component_dir(gDirUtilp->getExecutableDir());
-#elif LL_WINDOWS
- std::string component_dir( gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "" ) );
- component_dir += gDirUtilp->getDirDelimiter();
- #ifdef LL_DEBUG
- component_dir += "mozilla_debug";
- #else // LL_DEBUG
- component_dir += "mozilla";
- #endif // LL_DEBUG
-#elif LL_LINUX
- std::string component_dir( gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "" ) );
- component_dir += gDirUtilp->getDirDelimiter();
- component_dir += "mozilla-runtime-linux-i686";
-#elif LL_SOLARIS
- std::string component_dir( gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "" ) );
- component_dir += gDirUtilp->getDirDelimiter();
- #ifdef __sparc
- component_dir += "mozilla-solaris-sparc";
- #else
- component_dir += "mozilla-solaris-i686";
- #endif
-#else
- std::string component_dir( gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "" ) );
- component_dir += gDirUtilp->getDirDelimiter();
- component_dir += "mozilla";
-#endif
+void LLViewerMediaImpl::onMouseCaptureLost()
+{
+ if (mMediaSource)
+ {
+ mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, 0, mLastMouseX, mLastMouseY, 0);
+ }
+}
- std::string application_dir = gDirUtilp->getExecutableDir();
+//////////////////////////////////////////////////////////////////////////////////////////
+BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+ // NOTE: this is called when the mouse is released when we have capture.
+ // Due to the way mouse coordinates are mapped to the object, we can't use the x and y coordinates that come in with the event.
+
+ if(hasMouseCapture())
+ {
+ // Release the mouse -- this will also send a mouseup to the media
+ gFocusMgr.setMouseCapture( FALSE );
+ }
- init_data->setBrowserApplicationDir( application_dir );
- std::string profile_dir = gDirUtilp->getExpandedFilename( LL_PATH_MOZILLA_PROFILE, "" );
- init_data->setBrowserProfileDir( profile_dir );
- init_data->setBrowserComponentDir( component_dir );
- std::string profile_name("Second Life");
- init_data->setBrowserProfileName( profile_name );
- init_data->setBrowserParentWindow( gViewerWindow->getMediaWindow() );
+ return TRUE;
+}
- // Users can change skins while client is running, so make sure
- // we pick up on changes.
- gSavedSettings.getControl("SkinCurrent")->getSignal()->connect(
- boost::bind( LLViewerMediaImpl::handleSkinCurrentChanged, _1 ) );
+//////////////////////////////////////////////////////////////////////////////////////////
+std::string LLViewerMediaImpl::getName() const
+{
+ if (mMediaSource)
+ {
+ return mMediaSource->getMediaName();
+ }
+
+ return LLStringUtil::null;
+};
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateBack()
+{
+ if (mMediaSource)
+ {
+ mMediaSource->browse_back();
+ }
}
//////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::cleanupClass()
+void LLViewerMediaImpl::navigateForward()
{
- stop() ;
- LLMediaManager::cleanupClass();
+ if (mMediaSource)
+ {
+ mMediaSource->browse_forward();
+ }
}
-// static
-void LLViewerMedia::play(const std::string& media_url,
- const std::string& mime_type,
- const LLUUID& placeholder_texture_id,
- S32 media_width, S32 media_height, U8 media_auto_scale,
- U8 media_loop)
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateReload()
{
- sViewerMediaImpl.play(media_url, mime_type, placeholder_texture_id,
- media_width, media_height, media_auto_scale, media_loop);
+ navigateTo(getCurrentMediaURL(), "", true, false);
}
-// static
-void LLViewerMedia::stop()
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateHome()
{
- sViewerMediaImpl.stop();
+ navigateTo(mHomeURL, "", true, false);
}
-// static
-void LLViewerMedia::pause()
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::unload()
{
- sViewerMediaImpl.pause();
+ // Unload the media impl and clear its state.
+ destroyMediaSource();
+ resetPreviousMediaState();
+ mMediaURL.clear();
+ mMimeType.clear();
+ mCurrentMediaURL.clear();
+ mCurrentMimeType.clear();
}
-// static
-void LLViewerMedia::start()
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request)
{
- sViewerMediaImpl.start();
+ cancelMimeTypeProbe();
+
+ if(mMediaURL != url)
+ {
+ // Don't carry media play state across distinct URLs.
+ resetPreviousMediaState();
+ }
+
+ // Always set the current URL and MIME type.
+ mMediaURL = url;
+ mMimeType = mime_type;
+
+ // Clear the current media URL, since it will no longer be correct.
+ mCurrentMediaURL.clear();
+
+ // if mime type discovery was requested, we'll need to do it when the media loads
+ mNavigateRediscoverType = rediscover_type;
+
+ // and if this was a server request, the navigate on load will also need to be one.
+ mNavigateServerRequest = server_request;
+
+ // An explicit navigate resets the "failed" flag.
+ mMediaSourceFailed = false;
+
+ if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
+ {
+ // Helpful to have media urls in log file. Shouldn't be spammy.
+ llinfos << "NOT LOADING media id= " << mTextureId << " url=" << url << " mime_type=" << mime_type << llendl;
+
+ // This impl should not be loaded at this time.
+ LL_DEBUGS("PluginPriority") << this << "Not loading (PRIORITY_UNLOADED)" << LL_ENDL;
+
+ return;
+ }
+
+ navigateInternal();
}
-// static
-void LLViewerMedia::seek(F32 time)
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateInternal()
{
- sViewerMediaImpl.seek(time);
+ // Helpful to have media urls in log file. Shouldn't be spammy.
+ llinfos << "media id= " << mTextureId << " url=" << mMediaURL << " mime_type=" << mMimeType << llendl;
+
+ if(mNavigateSuspended)
+ {
+ llwarns << "Deferring navigate." << llendl;
+ mNavigateSuspendedDeferred = true;
+ return;
+ }
+
+ if(mMimeTypeProbe != NULL)
+ {
+ llwarns << "MIME type probe already in progress -- bailing out." << llendl;
+ return;
+ }
+
+ if(mNavigateServerRequest)
+ {
+ setNavState(MEDIANAVSTATE_SERVER_SENT);
+ }
+ else
+ {
+ setNavState(MEDIANAVSTATE_NONE);
+ }
+
+ // If the caller has specified a non-empty MIME type, look that up in our MIME types list.
+ // If we have a plugin for that MIME type, use that instead of attempting auto-discovery.
+ // This helps in supporting legacy media content where the server the media resides on returns a bogus MIME type
+ // but the parcel owner has correctly set the MIME type in the parcel media settings.
+
+ if(!mMimeType.empty() && (mMimeType != "none/none"))
+ {
+ std::string plugin_basename = LLMIMETypes::implType(mMimeType);
+ if(!plugin_basename.empty())
+ {
+ // We have a plugin for this mime type
+ mNavigateRediscoverType = false;
+ }
+ }
+
+ if(mNavigateRediscoverType)
+ {
+
+ LLURI uri(mMediaURL);
+ std::string scheme = uri.scheme();
+
+ if(scheme.empty() || "http" == scheme || "https" == scheme)
+ {
+ // If we don't set an Accept header, LLHTTPClient will add one like this:
+ // Accept: application/llsd+xml
+ // which is really not what we want.
+ LLSD headers = LLSD::emptyMap();
+ headers["Accept"] = "*/*";
+ LLHTTPClient::getHeaderOnly( mMediaURL, new LLMimeDiscoveryResponder(this), headers, 10.0f);
+ }
+ else if("data" == scheme || "file" == scheme || "about" == scheme)
+ {
+ // FIXME: figure out how to really discover the type for these schemes
+ // We use "data" internally for a text/html url for loading the login screen
+ if(initializeMedia("text/html"))
+ {
+ loadURI();
+ }
+ }
+ else
+ {
+ // This catches 'rtsp://' urls
+ if(initializeMedia(scheme))
+ {
+ loadURI();
+ }
+ }
+ }
+ else if(initializeMedia(mMimeType))
+ {
+ loadURI();
+ }
+ else
+ {
+ LL_WARNS("Media") << "Couldn't navigate to: " << mMediaURL << " as there is no media type for: " << mMimeType << LL_ENDL;
+ }
}
-// static
-void LLViewerMedia::setVolume(F32 volume)
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateStop()
{
- sViewerMediaImpl.setVolume(volume);
+ if(mMediaSource)
+ {
+ mMediaSource->browse_stop();
+ }
}
-// static
-LLMediaBase::EStatus LLViewerMedia::getStatus()
+//////////////////////////////////////////////////////////////////////////////////////////
+bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask)
{
- return sViewerMediaImpl.getStatus();
+ bool result = false;
+ // *NOTE:Mani - if this doesn't exist llmozlib goes crashy in the debug build.
+ // LLMozlib::init wants to write some files to <exe_dir>/components
+ std::string debug_init_component_dir( gDirUtilp->getExecutableDir() );
+ debug_init_component_dir += "/components";
+ LLAPRFile::makeDir(debug_init_component_dir.c_str());
+
+ if (mMediaSource)
+ {
+ // FIXME: THIS IS SO WRONG.
+ // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it...
+ if( MASK_CONTROL & mask )
+ {
+ if( 'C' == key )
+ {
+ mMediaSource->copy();
+ result = true;
+ }
+ else
+ if( 'V' == key )
+ {
+ mMediaSource->paste();
+ result = true;
+ }
+ else
+ if( 'X' == key )
+ {
+ mMediaSource->cut();
+ result = true;
+ }
+ }
+
+ if(!result)
+ {
+ result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask);
+ // Since the viewer internal event dispatching doesn't give us key-up events, simulate one here.
+ (void)mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_UP ,key, mask);
+ }
+ }
+
+ return result;
}
//////////////////////////////////////////////////////////////////////////////////////////
-// static
-LLUUID LLViewerMedia::getMediaTextureID()
+bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char)
{
- return sViewerMediaImpl.getMediaTextureID();
+ bool result = false;
+
+ if (mMediaSource)
+ {
+ // only accept 'printable' characters, sigh...
+ if (uni_char >= 32 // discard 'control' characters
+ && uni_char != 127) // SDL thinks this is 'delete' - yuck.
+ {
+ mMediaSource->textInput(wstring_to_utf8str(LLWString(1, uni_char)), gKeyboard->currentMask(FALSE));
+ }
+ }
+
+ return result;
}
//////////////////////////////////////////////////////////////////////////////////////////
-// static
-bool LLViewerMedia::getMediaSize(S32 *media_width, S32 *media_height)
+bool LLViewerMediaImpl::canNavigateForward()
{
- // make sure we're valid
+ BOOL result = FALSE;
+ if (mMediaSource)
+ {
+ result = mMediaSource->getHistoryForwardAvailable();
+ }
+ return result;
+}
- if ( sViewerMediaImpl.mMediaSource != NULL )
+//////////////////////////////////////////////////////////////////////////////////////////
+bool LLViewerMediaImpl::canNavigateBack()
+{
+ BOOL result = FALSE;
+ if (mMediaSource)
{
- *media_width = sViewerMediaImpl.mMediaSource->getMediaWidth();
- *media_height = sViewerMediaImpl.mMediaSource->getMediaHeight();
- return true;
+ result = mMediaSource->getHistoryBackAvailable();
}
- return false;
+ return result;
}
//////////////////////////////////////////////////////////////////////////////////////////
-// static
-bool LLViewerMedia::getTextureSize(S32 *texture_width, S32 *texture_height)
+void LLViewerMediaImpl::update()
{
- if ( sViewerMediaImpl.mMediaSource != NULL )
+ if(mMediaSource == NULL)
{
- S32 media_width = sViewerMediaImpl.mMediaSource->getMediaWidth();
- S32 media_height = sViewerMediaImpl.mMediaSource->getMediaHeight();
- *texture_width = LLMediaManager::textureWidthFromMediaWidth( media_width );
- *texture_height = LLMediaManager::textureHeightFromMediaHeight( media_height );
- return true;
+ if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
+ {
+ // This media source should not be loaded.
+ }
+ else if(mPriority <= LLPluginClassMedia::PRIORITY_SLIDESHOW)
+ {
+ // Don't load new instances that are at PRIORITY_SLIDESHOW or below. They're just kept around to preserve state.
+ }
+ else if(mMimeTypeProbe != NULL)
+ {
+ // this media source is doing a MIME type probe -- don't try loading it again.
+ }
+ else
+ {
+ // This media may need to be loaded.
+ if(sMediaCreateTimer.hasExpired())
+ {
+ LL_DEBUGS("PluginPriority") << this << ": creating media based on timer expiration" << LL_ENDL;
+ createMediaSource();
+ sMediaCreateTimer.setTimerExpirySec(LLVIEWERMEDIA_CREATE_DELAY);
+ }
+ else
+ {
+ LL_DEBUGS("PluginPriority") << this << ": NOT creating media (waiting on timer)" << LL_ENDL;
+ }
+ }
+ }
+
+ if(mMediaSource == NULL)
+ {
+ return;
+ }
+
+ // Make sure a navigate doesn't happen during the idle -- it can cause mMediaSource to get destroyed, which can cause a crash.
+ setNavigateSuspended(true);
+
+ mMediaSource->idle();
+
+ setNavigateSuspended(false);
+
+ if(mMediaSource == NULL)
+ {
+ return;
+ }
+
+ if(mMediaSource->isPluginExited())
+ {
+ resetPreviousMediaState();
+ destroyMediaSource();
+ return;
+ }
+
+ if(!mMediaSource->textureValid())
+ {
+ return;
+ }
+
+ if(mSuspendUpdates || !mVisible)
+ {
+ return;
+ }
+
+ LLViewerMediaTexture* placeholder_image = updatePlaceholderImage();
+
+ if(placeholder_image)
+ {
+ LLRect dirty_rect;
+
+ // Since we're updating this texture, we know it's playing. Tell the texture to do its replacement magic so it gets rendered.
+ placeholder_image->setPlaying(TRUE);
+
+ if(mMediaSource->getDirty(&dirty_rect))
+ {
+ // Constrain the dirty rect to be inside the texture
+ S32 x_pos = llmax(dirty_rect.mLeft, 0);
+ S32 y_pos = llmax(dirty_rect.mBottom, 0);
+ S32 width = llmin(dirty_rect.mRight, placeholder_image->getWidth()) - x_pos;
+ S32 height = llmin(dirty_rect.mTop, placeholder_image->getHeight()) - y_pos;
+
+ if(width > 0 && height > 0)
+ {
+
+ U8* data = mMediaSource->getBitsData();
+
+ // Offset the pixels pointer to match x_pos and y_pos
+ data += ( x_pos * mMediaSource->getTextureDepth() * mMediaSource->getBitsWidth() );
+ data += ( y_pos * mMediaSource->getTextureDepth() );
+
+ placeholder_image->setSubImage(
+ data,
+ mMediaSource->getBitsWidth(),
+ mMediaSource->getBitsHeight(),
+ x_pos,
+ y_pos,
+ width,
+ height);
+
+ }
+
+ mMediaSource->resetDirty();
+ }
}
- return false;
}
//////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::updateImagesMediaStreams()
+void LLViewerMediaImpl::updateImagesMediaStreams()
{
- sViewerMediaImpl.updateImagesMediaStreams();
}
+
+
//////////////////////////////////////////////////////////////////////////////////////////
-// static
-bool LLViewerMedia::isMediaPlaying()
+LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage()
{
- LLMediaBase::EStatus status = sViewerMediaImpl.getStatus();
- return (status == LLMediaBase::STATUS_STARTED );
+ if(mTextureId.isNull())
+ {
+ // The code that created this instance will read from the plugin's bits.
+ return NULL;
+ }
+
+ LLViewerMediaTexture* placeholder_image = LLViewerTextureManager::getMediaTexture( mTextureId );
+
+ if (mNeedsNewTexture
+ || placeholder_image->getUseMipMaps()
+ || (placeholder_image->getWidth() != mMediaSource->getTextureWidth())
+ || (placeholder_image->getHeight() != mMediaSource->getTextureHeight())
+ || (mTextureUsedWidth != mMediaSource->getWidth())
+ || (mTextureUsedHeight != mMediaSource->getHeight())
+ )
+ {
+ LL_DEBUGS("Media") << "initializing media placeholder" << LL_ENDL;
+ LL_DEBUGS("Media") << "movie image id " << mTextureId << LL_ENDL;
+
+ int texture_width = mMediaSource->getTextureWidth();
+ int texture_height = mMediaSource->getTextureHeight();
+ int texture_depth = mMediaSource->getTextureDepth();
+
+ // MEDIAOPT: check to see if size actually changed before doing work
+ placeholder_image->destroyGLTexture();
+ // MEDIAOPT: apparently just calling setUseMipMaps(FALSE) doesn't work?
+ placeholder_image->reinit(FALSE); // probably not needed
+
+ // MEDIAOPT: seems insane that we actually have to make an imageraw then
+ // immediately discard it
+ LLPointer<LLImageRaw> raw = new LLImageRaw(texture_width, texture_height, texture_depth);
+ // Clear the texture to the background color, ignoring alpha.
+ // convert background color channels from [0.0, 1.0] to [0, 255];
+ raw->clear(int(mBackgroundColor.mV[VX] * 255.0f), int(mBackgroundColor.mV[VY] * 255.0f), int(mBackgroundColor.mV[VZ] * 255.0f), 0xff);
+ int discard_level = 0;
+
+ // ask media source for correct GL image format constants
+ placeholder_image->setExplicitFormat(mMediaSource->getTextureFormatInternal(),
+ mMediaSource->getTextureFormatPrimary(),
+ mMediaSource->getTextureFormatType(),
+ mMediaSource->getTextureFormatSwapBytes());
+
+ placeholder_image->createGLTexture(discard_level, raw);
+
+ // MEDIAOPT: set this dynamically on play/stop
+ // FIXME
+// placeholder_image->mIsMediaTexture = true;
+ mNeedsNewTexture = false;
+
+ // If the amount of the texture being drawn by the media goes down in either width or height,
+ // recreate the texture to avoid leaving parts of the old image behind.
+ mTextureUsedWidth = mMediaSource->getWidth();
+ mTextureUsedHeight = mMediaSource->getHeight();
+ }
+
+ return placeholder_image;
}
+
+
//////////////////////////////////////////////////////////////////////////////////////////
-// static
-bool LLViewerMedia::isMediaPaused()
+LLUUID LLViewerMediaImpl::getMediaTextureID() const
{
- LLMediaBase::EStatus status = sViewerMediaImpl.getStatus();
- return (status == LLMediaBase::STATUS_PAUSED);
+ return mTextureId;
}
+
//////////////////////////////////////////////////////////////////////////////////////////
-// static
-bool LLViewerMedia::hasMedia()
+void LLViewerMediaImpl::setVisible(bool visible)
{
- return sViewerMediaImpl.mMediaSource != NULL;
+ mVisible = visible;
+
+ if(mVisible)
+ {
+ if(mMediaSource && mMediaSource->isPluginExited())
+ {
+ destroyMediaSource();
+ }
+
+ if(!mMediaSource)
+ {
+ createMediaSource();
+ }
+ }
}
//////////////////////////////////////////////////////////////////////////////////////////
-//static
-bool LLViewerMedia::isActiveMediaTexture(const LLUUID& id)
+void LLViewerMediaImpl::mouseCapture()
{
- return (id.notNull()
- && id == getMediaTextureID()
- && isMediaPlaying());
+ gFocusMgr.setMouseCapture(this);
}
//////////////////////////////////////////////////////////////////////////////////////////
-// static
-std::string LLViewerMedia::getMediaURL()
+void LLViewerMediaImpl::scaleMouse(S32 *mouse_x, S32 *mouse_y)
+{
+#if 0
+ S32 media_width, media_height;
+ S32 texture_width, texture_height;
+ getMediaSize( &media_width, &media_height );
+ getTextureSize( &texture_width, &texture_height );
+ S32 y_delta = texture_height - media_height;
+
+ *mouse_y -= y_delta;
+#endif
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+bool LLViewerMediaImpl::isMediaPlaying()
{
- return sViewerMediaImpl.mMediaURL;
+ bool result = false;
+
+ if(mMediaSource)
+ {
+ EMediaStatus status = mMediaSource->getStatus();
+ if(status == MEDIA_PLAYING || status == MEDIA_LOADING)
+ result = true;
+ }
+
+ return result;
}
//////////////////////////////////////////////////////////////////////////////////////////
-// static
-std::string LLViewerMedia::getMimeType()
+bool LLViewerMediaImpl::isMediaPaused()
{
- return sViewerMediaImpl.mMimeType;
+ bool result = false;
+
+ if(mMediaSource)
+ {
+ if(mMediaSource->getStatus() == MEDIA_PAUSED)
+ result = true;
+ }
+
+ return result;
}
+
//////////////////////////////////////////////////////////////////////////////////////////
-// static
-void LLViewerMedia::setMimeType(std::string mime_type)
+//
+bool LLViewerMediaImpl::hasMedia() const
+{
+ return mMediaSource != NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+void LLViewerMediaImpl::resetPreviousMediaState()
+{
+ mPreviousMediaState = MEDIA_NONE;
+ mPreviousMediaTime = 0.0f;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+void LLViewerMediaImpl::setDisabled(bool disabled)
+{
+ if(mIsDisabled != disabled)
+ {
+ // Only do this on actual state transitions.
+ mIsDisabled = disabled;
+
+ if(mIsDisabled)
+ {
+ // We just disabled this media. Clear all state.
+ unload();
+ }
+ else
+ {
+ // We just (re)enabled this media. Do a navigate if auto-play is in order.
+ if(mMediaAutoPlay && gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING))
+ {
+ navigateTo(mMediaEntryURL, "", true, true);
+ }
+ }
+
+ }
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+bool LLViewerMediaImpl::isForcedUnloaded() const
+{
+ if(mIsMuted || mMediaSourceFailed || mIsDisabled)
+ {
+ return true;
+ }
+
+ if(sInWorldMediaDisabled)
+ {
+ // When inworld media is disabled, all instances that aren't marked as "used in UI" will not be loaded.
+ if(!mUsedInUI)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+bool LLViewerMediaImpl::isPlayable() const
+{
+ if(isForcedUnloaded())
+ {
+ // All of the forced-unloaded criteria also imply not playable.
+ return false;
+ }
+
+ if(hasMedia())
+ {
+ // Anything that's already playing is, by definition, playable.
+ return true;
+ }
+
+ if(!mMediaURL.empty())
+ {
+ // If something has navigated the instance, it's ready to be played.
+ return true;
+ }
+
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent event)
+{
+ switch(event)
+ {
+ case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
+ {
+ // The plugin failed to load properly. Make sure the timer doesn't retry.
+ // TODO: maybe mark this plugin as not loadable somehow?
+ mMediaSourceFailed = true;
+
+ // Reset the last known state of the media to defaults.
+ resetPreviousMediaState();
+
+ // TODO: may want a different message for this case?
+ LLSD args;
+ args["PLUGIN"] = LLMIMETypes::implType(mCurrentMimeType);
+ LLNotificationsUtil::add("MediaPluginFailed", args);
+ }
+ break;
+
+ case MEDIA_EVENT_PLUGIN_FAILED:
+ {
+ // The plugin crashed.
+ mMediaSourceFailed = true;
+
+ // Reset the last known state of the media to defaults.
+ resetPreviousMediaState();
+
+ LLSD args;
+ args["PLUGIN"] = LLMIMETypes::implType(mCurrentMimeType);
+ // SJB: This is getting called every frame if the plugin fails to load, continuously respawining the alert!
+ //LLNotificationsUtil::add("MediaPluginFailed", args);
+ }
+ break;
+
+ case MEDIA_EVENT_CURSOR_CHANGED:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << plugin->getCursorName() << LL_ENDL;
+
+ std::string cursor = plugin->getCursorName();
+
+ if(cursor == "arrow")
+ mLastSetCursor = UI_CURSOR_ARROW;
+ else if(cursor == "ibeam")
+ mLastSetCursor = UI_CURSOR_IBEAM;
+ else if(cursor == "splith")
+ mLastSetCursor = UI_CURSOR_SIZEWE;
+ else if(cursor == "splitv")
+ mLastSetCursor = UI_CURSOR_SIZENS;
+ else if(cursor == "hand")
+ mLastSetCursor = UI_CURSOR_HAND;
+ else // for anything else, default to the arrow
+ mLastSetCursor = UI_CURSOR_ARROW;
+ }
+ break;
+
+ case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_BEGIN:
+ {
+ LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_BEGIN, uri is: " << plugin->getNavigateURI() << LL_ENDL;
+
+ if(getNavState() == MEDIANAVSTATE_SERVER_SENT)
+ {
+ setNavState(MEDIANAVSTATE_SERVER_BEGUN);
+ }
+ else
+ {
+ setNavState(MEDIANAVSTATE_BEGUN);
+ }
+ }
+ break;
+
+ case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE:
+ {
+ LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_COMPLETE, uri is: " << plugin->getNavigateURI() << LL_ENDL;
+
+ if(getNavState() == MEDIANAVSTATE_BEGUN)
+ {
+ mCurrentMediaURL = plugin->getNavigateURI();
+ setNavState(MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED);
+ }
+ else if(getNavState() == MEDIANAVSTATE_SERVER_BEGUN)
+ {
+ mCurrentMediaURL = plugin->getNavigateURI();
+ setNavState(MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED);
+ }
+ else
+ {
+ // all other cases need to leave the state alone.
+ }
+ }
+ break;
+
+ case LLViewerMediaObserver::MEDIA_EVENT_LOCATION_CHANGED:
+ {
+ LL_DEBUGS("Media") << "MEDIA_EVENT_LOCATION_CHANGED, uri is: " << plugin->getLocation() << LL_ENDL;
+
+ if(getNavState() == MEDIANAVSTATE_BEGUN)
+ {
+ mCurrentMediaURL = plugin->getLocation();
+ setNavState(MEDIANAVSTATE_FIRST_LOCATION_CHANGED);
+ }
+ else if(getNavState() == MEDIANAVSTATE_SERVER_BEGUN)
+ {
+ mCurrentMediaURL = plugin->getLocation();
+ setNavState(MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED);
+ }
+ else
+ {
+ // Don't track redirects.
+ setNavState(MEDIANAVSTATE_NONE);
+ }
+ }
+ break;
+
+
+ default:
+ break;
+ }
+
+ // Just chain the event to observers.
+ emitEvent(plugin, event);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+void
+LLViewerMediaImpl::cut()
+{
+ if (mMediaSource)
+ mMediaSource->cut();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+BOOL
+LLViewerMediaImpl::canCut() const
+{
+ if (mMediaSource)
+ return mMediaSource->canCut();
+ else
+ return FALSE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+void
+LLViewerMediaImpl::copy()
+{
+ if (mMediaSource)
+ mMediaSource->copy();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+BOOL
+LLViewerMediaImpl::canCopy() const
+{
+ if (mMediaSource)
+ return mMediaSource->canCopy();
+ else
+ return FALSE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+void
+LLViewerMediaImpl::paste()
+{
+ if (mMediaSource)
+ mMediaSource->paste();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+BOOL
+LLViewerMediaImpl::canPaste() const
+{
+ if (mMediaSource)
+ return mMediaSource->canPaste();
+ else
+ return FALSE;
+}
+
+void LLViewerMediaImpl::setUpdated(BOOL updated)
+{
+ mIsUpdated = updated ;
+}
+
+BOOL LLViewerMediaImpl::isUpdated()
+{
+ return mIsUpdated ;
+}
+
+void LLViewerMediaImpl::calculateInterest()
+{
+ LLViewerMediaTexture* texture = LLViewerTextureManager::findMediaTexture( mTextureId );
+
+ if(texture != NULL)
+ {
+ mInterest = texture->getMaxVirtualSize();
+ }
+ else
+ {
+ // This will be a relatively common case now, since it will always be true for unloaded media.
+ mInterest = 0.0f;
+ }
+
+ // Calculate distance from the avatar, for use in the proximity calculation.
+ mProximityDistance = 0.0f;
+ if(!mObjectList.empty())
+ {
+ // Just use the first object in the list. We could go through the list and find the closest object, but this should work well enough.
+ LLVector3d global_delta = gAgent.getPositionGlobal() - (*mObjectList.begin())->getPositionGlobal();
+ mProximityDistance = global_delta.magVecSquared(); // use distance-squared because it's cheaper and sorts the same.
+ }
+
+ if(mNeedsMuteCheck)
+ {
+ // Check all objects this instance is associated with, and those objects' owners, against the mute list
+ mIsMuted = false;
+
+ std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
+ for(; iter != mObjectList.end() ; ++iter)
+ {
+ LLVOVolume *obj = *iter;
+ if(LLMuteList::getInstance()->isMuted(obj->getID()))
+ mIsMuted = true;
+ else
+ {
+ // We won't have full permissions data for all objects. Attempt to mute objects when we can tell their owners are muted.
+ LLPermissions* obj_perm = LLSelectMgr::getInstance()->findObjectPermissions(obj);
+ if(obj_perm)
+ {
+ if(LLMuteList::getInstance()->isMuted(obj_perm->getOwner()))
+ mIsMuted = true;
+ }
+ }
+ }
+
+ mNeedsMuteCheck = false;
+ }
+}
+
+F64 LLViewerMediaImpl::getApproximateTextureInterest()
+{
+ F64 result = 0.0f;
+
+ if(mMediaSource)
+ {
+ result = mMediaSource->getFullWidth();
+ result *= mMediaSource->getFullHeight();
+ }
+ else
+ {
+ // No media source is loaded -- all we have to go on is the texture size that has been set on the impl, if any.
+ result = mMediaWidth;
+ result *= mMediaHeight;
+ }
+
+ return result;
+}
+
+void LLViewerMediaImpl::setUsedInUI(bool used_in_ui)
+{
+ mUsedInUI = used_in_ui;
+
+ // HACK: Force elements used in UI to load right away.
+ // This fixes some issues where UI code that uses the browser instance doesn't expect it to be unloaded.
+ if(mUsedInUI && (mPriority == LLPluginClassMedia::PRIORITY_UNLOADED))
+ {
+ if(getVisible())
+ {
+ setPriority(LLPluginClassMedia::PRIORITY_NORMAL);
+ }
+ else
+ {
+ setPriority(LLPluginClassMedia::PRIORITY_HIDDEN);
+ }
+
+ createMediaSource();
+ }
+};
+
+void LLViewerMediaImpl::setBackgroundColor(LLColor4 color)
+{
+ mBackgroundColor = color;
+
+ if(mMediaSource)
+ {
+ mMediaSource->setBackgroundColor(mBackgroundColor);
+ }
+};
+
+F64 LLViewerMediaImpl::getCPUUsage() const
+{
+ F64 result = 0.0f;
+
+ if(mMediaSource)
+ {
+ result = mMediaSource->getCPUUsage();
+ }
+
+ return result;
+}
+
+void LLViewerMediaImpl::setPriority(LLPluginClassMedia::EPriority priority)
{
- sViewerMediaImpl.mMimeType = mime_type;
+ if(mPriority != priority)
+ {
+ LL_DEBUGS("PluginPriority")
+ << "changing priority of media id " << mTextureId
+ << " from " << LLPluginClassMedia::priorityToString(mPriority)
+ << " to " << LLPluginClassMedia::priorityToString(priority)
+ << LL_ENDL;
+ }
+
+ mPriority = priority;
+
+ if(priority == LLPluginClassMedia::PRIORITY_UNLOADED)
+ {
+ if(mMediaSource)
+ {
+ // Need to unload the media source
+
+ // First, save off previous media state
+ mPreviousMediaState = mMediaSource->getStatus();
+ mPreviousMediaTime = mMediaSource->getCurrentTime();
+
+ destroyMediaSource();
+ }
+ }
+
+ if(mMediaSource)
+ {
+ mMediaSource->setPriority(mPriority);
+ }
+
+ // NOTE: loading (or reloading) media sources whose priority has risen above PRIORITY_UNLOADED is done in update().
+}
+
+void LLViewerMediaImpl::setLowPrioritySizeLimit(int size)
+{
+ if(mMediaSource)
+ {
+ mMediaSource->setLowPrioritySizeLimit(size);
+ }
}
+
+void LLViewerMediaImpl::setNavState(EMediaNavState state)
+{
+ mMediaNavState = state;
+
+ switch (state)
+ {
+ case MEDIANAVSTATE_NONE: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_NONE" << llendl; break;
+ case MEDIANAVSTATE_BEGUN: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_BEGUN" << llendl; break;
+ case MEDIANAVSTATE_FIRST_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_FIRST_LOCATION_CHANGED" << llendl; break;
+ case MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED" << llendl; break;
+ case MEDIANAVSTATE_SERVER_SENT: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_SENT" << llendl; break;
+ case MEDIANAVSTATE_SERVER_BEGUN: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_BEGUN" << llendl; break;
+ case MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED" << llendl; break;
+ case MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED" << llendl; break;
+ }
+}
+
+void LLViewerMediaImpl::setNavigateSuspended(bool suspend)
+{
+ if(mNavigateSuspended != suspend)
+ {
+ mNavigateSuspended = suspend;
+ if(!suspend)
+ {
+ // We're coming out of suspend. If someone tried to do a navigate while suspended, do one now instead.
+ if(mNavigateSuspendedDeferred)
+ {
+ mNavigateSuspendedDeferred = false;
+ navigateInternal();
+ }
+ }
+ }
+}
+
+void LLViewerMediaImpl::cancelMimeTypeProbe()
+{
+ if(mMimeTypeProbe != NULL)
+ {
+ // There doesn't seem to be a way to actually cancel an outstanding request.
+ // Simulate it by telling the LLMimeDiscoveryResponder not to write back any results.
+ mMimeTypeProbe->cancelRequest();
+
+ // The above should already have set mMimeTypeProbe to NULL.
+ if(mMimeTypeProbe != NULL)
+ {
+ llerrs << "internal error: mMimeTypeProbe is not NULL after cancelling request." << llendl;
+ }
+ }
+}
+
+void LLViewerMediaImpl::addObject(LLVOVolume* obj)
+{
+ std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
+ for(; iter != mObjectList.end() ; ++iter)
+ {
+ if(*iter == obj)
+ {
+ return ; //already in the list.
+ }
+ }
+
+ mObjectList.push_back(obj) ;
+ mNeedsMuteCheck = true;
+}
+
+void LLViewerMediaImpl::removeObject(LLVOVolume* obj)
+{
+ mObjectList.remove(obj) ;
+ mNeedsMuteCheck = true;
+}
+
+const std::list< LLVOVolume* >* LLViewerMediaImpl::getObjectList() const
+{
+ return &mObjectList ;
+}
+
+LLVOVolume *LLViewerMediaImpl::getSomeObject()
+{
+ LLVOVolume *result = NULL;
+
+ std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ;
+ if(iter != mObjectList.end())
+ {
+ result = *iter;
+ }
+
+ return result;
+}
+
+void LLViewerMediaImpl::setTextureID(LLUUID id)
+{
+ if(id != mTextureId)
+ {
+ if(mTextureId.notNull())
+ {
+ // Remove this item's entry from the map
+ sViewerMediaTextureIDMap.erase(mTextureId);
+ }
+
+ if(id.notNull())
+ {
+ sViewerMediaTextureIDMap.insert(LLViewerMedia::impl_id_map::value_type(id, this));
+ }
+
+ mTextureId = id;
+ }
+}
+
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index 600d7409e2..ff18ed605a 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -33,50 +33,358 @@
#ifndef LLVIEWERMEDIA_H
#define LLVIEWERMEDIA_H
-#include "llmediabase.h" // for status codes
+#include "llfocusmgr.h"
+#include "lleditmenuhandler.h"
-class LLMediaManagerData;
+#include "llpanel.h"
+#include "llpluginclassmediaowner.h"
+
+#include "llviewermediaobserver.h"
+
+#include "llpluginclassmedia.h"
+#include "v4color.h"
+
+class LLViewerMediaImpl;
class LLUUID;
+class LLViewerMediaTexture;
+class LLMediaEntry;
+class LLVOVolume ;
+class LLMimeDiscoveryResponder;
+
+typedef LLPointer<LLViewerMediaImpl> viewer_media_t;
+///////////////////////////////////////////////////////////////////////////////
+//
+class LLViewerMediaEventEmitter
+{
+public:
+ virtual ~LLViewerMediaEventEmitter();
+
+ bool addObserver( LLViewerMediaObserver* subject );
+ bool remObserver( LLViewerMediaObserver* subject );
+ virtual void emitEvent(LLPluginClassMedia* self, LLViewerMediaObserver::EMediaEvent event);
+
+private:
+ typedef std::list< LLViewerMediaObserver* > observerListType;
+ observerListType mObservers;
+};
+
+class LLViewerMediaImpl;
class LLViewerMedia
{
+ LOG_CLASS(LLViewerMedia);
public:
+
+ // String to get/set media autoplay in gSavedSettings
+ static const char *AUTO_PLAY_MEDIA_SETTING;
+
+ typedef std::vector<LLViewerMediaImpl*> impl_list;
+
+ typedef std::map<LLUUID, LLViewerMediaImpl*> impl_id_map;
+
// Special case early init for just web browser component
// so we can show login screen. See .cpp file for details. JC
- static void initBrowser();
+
+ static viewer_media_t newMediaImpl(const LLUUID& texture_id,
+ S32 media_width = 0,
+ S32 media_height = 0,
+ U8 media_auto_scale = false,
+ U8 media_loop = false);
+
+ static viewer_media_t updateMediaImpl(LLMediaEntry* media_entry, const std::string& previous_url, bool update_from_self);
+ static LLViewerMediaImpl* getMediaImplFromTextureID(const LLUUID& texture_id);
+ static std::string getCurrentUserAgent();
+ static void updateBrowserUserAgent();
+ static bool handleSkinCurrentChanged(const LLSD& /*newvalue*/);
+ static bool textureHasMedia(const LLUUID& texture_id);
+ static void setVolume(F32 volume);
+
+ static void updateMedia(void* dummy_arg = NULL);
static void initClass();
static void cleanupClass();
- static void play(const std::string& media_url,
- const std::string& mime_type,
- const LLUUID& placeholder_texture_id,
- S32 media_width, S32 media_height, U8 media_auto_scale,
- U8 media_loop);
- static void stop();
- static void pause();
- static void start();
- static void seek(F32 time);
- static void setVolume(F32 volume);
- static LLMediaBase::EStatus getStatus();
+ static F32 getVolume();
+ static void muteListChanged();
+ static void setInWorldMediaDisabled(bool disabled);
+ static bool getInWorldMediaDisabled();
+
+ static bool isInterestingEnough(const LLVOVolume* object, const F64 &object_interest);
+
+ // Returns the priority-sorted list of all media impls.
+ static impl_list &getPriorityList();
+
+ // This is the comparitor used to sort the list.
+ static bool priorityComparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2);
+
+ // For displaying the media first-run dialog.
+ static bool needsMediaFirstRun();
+ static void displayMediaFirstRun();
+ static bool firstRunCallback(const LLSD& notification, const LLSD& response);
+
+};
+
+// Implementation functions not exported into header file
+class LLViewerMediaImpl
+ : public LLMouseHandler, public LLRefCount, public LLPluginClassMediaOwner, public LLViewerMediaEventEmitter, public LLEditMenuHandler
+{
+ LOG_CLASS(LLViewerMediaImpl);
+public:
+
+ friend class LLViewerMedia;
+ friend class LLMimeDiscoveryResponder;
+
+ LLViewerMediaImpl(
+ const LLUUID& texture_id,
+ S32 media_width,
+ S32 media_height,
+ U8 media_auto_scale,
+ U8 media_loop);
+
+ ~LLViewerMediaImpl();
+
+ // Override inherited version from LLViewerMediaEventEmitter
+ virtual void emitEvent(LLPluginClassMedia* self, LLViewerMediaObserver::EMediaEvent event);
+
+ void createMediaSource();
+ void destroyMediaSource();
+ void setMediaType(const std::string& media_type);
+ bool initializeMedia(const std::string& mime_type);
+ bool initializePlugin(const std::string& media_type);
+ void loadURI();
+ LLPluginClassMedia* getMediaPlugin() { return mMediaSource; }
+ void setSize(int width, int height);
+
+ void play();
+ void stop();
+ void pause();
+ void start();
+ void seek(F32 time);
+ void skipBack(F32 step_scale);
+ void skipForward(F32 step_scale);
+ void setVolume(F32 volume);
+ void updateVolume();
+ F32 getVolume();
+ void focus(bool focus);
+ // True if the impl has user focus.
+ bool hasFocus() const;
+ void mouseDown(S32 x, S32 y, MASK mask, S32 button = 0);
+ void mouseUp(S32 x, S32 y, MASK mask, S32 button = 0);
+ void mouseMove(S32 x, S32 y, MASK mask);
+ void mouseDown(const LLVector2& texture_coords, MASK mask, S32 button = 0);
+ void mouseUp(const LLVector2& texture_coords, MASK mask, S32 button = 0);
+ void mouseMove(const LLVector2& texture_coords, MASK mask);
+ void mouseDoubleClick(S32 x,S32 y, MASK mask, S32 button = 0);
+ void scrollWheel(S32 x, S32 y, MASK mask);
+ void mouseCapture();
+
+ void navigateBack();
+ void navigateForward();
+ void navigateReload();
+ void navigateHome();
+ void unload();
+ void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false);
+ void navigateInternal();
+ void navigateStop();
+ bool handleKeyHere(KEY key, MASK mask);
+ bool handleUnicodeCharHere(llwchar uni_char);
+ bool canNavigateForward();
+ bool canNavigateBack();
+ std::string getMediaURL() const { return mMediaURL; }
+ std::string getCurrentMediaURL();
+ std::string getHomeURL() { return mHomeURL; }
+ std::string getMediaEntryURL() { return mMediaEntryURL; }
+ void setHomeURL(const std::string& home_url) { mHomeURL = home_url; };
+ void clearCache();
+ std::string getMimeType() { return mMimeType; }
+ void scaleMouse(S32 *mouse_x, S32 *mouse_y);
+ void scaleTextureCoords(const LLVector2& texture_coords, S32 *x, S32 *y);
+
+ void update();
+ void updateImagesMediaStreams();
+ LLUUID getMediaTextureID() const;
+
+ void suspendUpdates(bool suspend) { mSuspendUpdates = suspend; };
+ void setVisible(bool visible);
+ bool getVisible() const { return mVisible; };
+
+ bool isMediaPlaying();
+ bool isMediaPaused();
+ bool hasMedia() const;
+ bool isMediaFailed() const { return mMediaSourceFailed; };
+ void setMediaFailed(bool val) { mMediaSourceFailed = val; }
+ void resetPreviousMediaState();
+
+ void setDisabled(bool disabled);
+ bool isMediaDisabled() const { return mIsDisabled; };
+
+ void setInNearbyMediaList(bool in_list) { mInNearbyMediaList = in_list; }
+ bool getInNearbyMediaList() { return mInNearbyMediaList; }
+
+ // returns true if this instance should not be loaded (disabled, muted object, crashed, etc.)
+ bool isForcedUnloaded() const;
+
+ // returns true if this instance could be playable based on autoplay setting, current load state, etc.
+ bool isPlayable() const;
+
+ void setIsParcelMedia(bool is_parcel_media) { mIsParcelMedia = is_parcel_media; };
+ bool isParcelMedia() const { return mIsParcelMedia; };
+
+ ECursorType getLastSetCursor() { return mLastSetCursor; };
+
+ // utility function to create a ready-to-use media instance from a desired media type.
+ static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height);
+
+ // Internally set our desired browser user agent string, including
+ // the Second Life version and skin name. Used because we can
+ // switch skins without restarting the app.
+ static void updateBrowserUserAgent();
+
+ // Callback for when the SkinCurrent control is changed to
+ // switch the user agent string to indicate the new skin.
+ static bool handleSkinCurrentChanged(const LLSD& newvalue);
+
+ // need these to handle mouseup...
+ /*virtual*/ void onMouseCaptureLost();
+ /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+
+ // Grr... the only thing I want as an LLMouseHandler are the onMouseCaptureLost and handleMouseUp calls.
+ // Sadly, these are all pure virtual, so I have to supply implementations here:
+ /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; };
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) { return FALSE; };
+ /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) { return FALSE; };
+ /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask) { return FALSE; };
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) { return FALSE; };
+ /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) { return FALSE; };
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask) { return FALSE; };
+ /*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; };
+ /*virtual*/ BOOL handleMiddleMouseUp(S32 x, S32 y, MASK mask) {return FALSE; };
+ /*virtual*/ std::string getName() const;
+
+ /*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const {};
+ /*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const {};
+ /*virtual*/ BOOL hasMouseCapture() { return gFocusMgr.getMouseCapture() == this; };
+
+ // Inherited from LLPluginClassMediaOwner
+ /*virtual*/ void handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent);
+
+ // LLEditMenuHandler overrides
+ /*virtual*/ void cut();
+ /*virtual*/ BOOL canCut() const;
+
+ /*virtual*/ void copy();
+ /*virtual*/ BOOL canCopy() const;
+
+ /*virtual*/ void paste();
+ /*virtual*/ BOOL canPaste() const;
+
+ void addObject(LLVOVolume* obj) ;
+ void removeObject(LLVOVolume* obj) ;
+ const std::list< LLVOVolume* >* getObjectList() const ;
+ LLVOVolume *getSomeObject();
+ void setUpdated(BOOL updated) ;
+ BOOL isUpdated() ;
+
+ // Updates the "interest" value in this object
+ void calculateInterest();
+ F64 getInterest() const { return mInterest; };
+ F64 getApproximateTextureInterest();
+ S32 getProximity() const { return mProximity; };
+ F64 getProximityDistance() const { return mProximityDistance; };
+
+ // Mark this object as being used in a UI panel instead of on a prim
+ // This will be used as part of the interest sorting algorithm.
+ void setUsedInUI(bool used_in_ui);
+ bool getUsedInUI() const { return mUsedInUI; };
- static LLUUID getMediaTextureID();
- static bool getMediaSize(S32 *media_width, S32 *media_height);
- static bool getTextureSize(S32 *texture_width, S32 *texture_height);
- static bool isMediaPlaying();
- static bool isMediaPaused();
- static bool hasMedia();
- static bool isActiveMediaTexture(const LLUUID& id);
+ void setBackgroundColor(LLColor4 color);
+
+ F64 getCPUUsage() const;
+
+ void setPriority(LLPluginClassMedia::EPriority priority);
+ LLPluginClassMedia::EPriority getPriority() { return mPriority; };
- static std::string getMediaURL();
- static std::string getMimeType();
- static void setMimeType(std::string mime_type);
+ void setLowPrioritySizeLimit(int size);
- static void updateImagesMediaStreams();
+ void setTextureID(LLUUID id = LLUUID::null);
+
+ typedef enum
+ {
+ MEDIANAVSTATE_NONE, // State is outside what we need to track for navigation.
+ MEDIANAVSTATE_BEGUN, // a MEDIA_EVENT_NAVIGATE_BEGIN has been received which was not server-directed
+ MEDIANAVSTATE_FIRST_LOCATION_CHANGED, // first LOCATION_CHANGED event after a non-server-directed BEGIN
+ MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED, // we received a NAVIGATE_COMPLETE event before the first LOCATION_CHANGED
+ MEDIANAVSTATE_SERVER_SENT, // server-directed nav has been requested, but MEDIA_EVENT_NAVIGATE_BEGIN hasn't been received yet
+ MEDIANAVSTATE_SERVER_BEGUN, // MEDIA_EVENT_NAVIGATE_BEGIN has been received which was server-directed
+ MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED, // first LOCATION_CHANGED event after a server-directed BEGIN
+ MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED // we received a NAVIGATE_COMPLETE event before the first LOCATION_CHANGED
+
+ }EMediaNavState;
+
+ // Returns the current nav state of the media.
+ // note that this will be updated BEFORE listeners and objects receive media messages
+ EMediaNavState getNavState() { return mMediaNavState; }
+ void setNavState(EMediaNavState state);
+
+ void setNavigateSuspended(bool suspend);
+ bool isNavigateSuspended() { return mNavigateSuspended; };
+
+ void cancelMimeTypeProbe();
+
+private:
+ // a single media url with some data and an impl.
+ LLPluginClassMedia* mMediaSource;
+ LLUUID mTextureId;
+ bool mMovieImageHasMips;
+ std::string mMediaURL; // The last media url set with NavigateTo
+ std::string mHomeURL;
+ std::string mMimeType;
+ std::string mCurrentMediaURL; // The most current media url from the plugin (via the "location changed" or "navigate complete" events).
+ std::string mCurrentMimeType; // The MIME type that caused the currently loaded plugin to be loaded.
+ S32 mLastMouseX; // save the last mouse coord we get, so when we lose capture we can simulate a mouseup at that point.
+ S32 mLastMouseY;
+ S32 mMediaWidth;
+ S32 mMediaHeight;
+ bool mMediaAutoScale;
+ bool mMediaLoop;
+ bool mNeedsNewTexture;
+ S32 mTextureUsedWidth;
+ S32 mTextureUsedHeight;
+ bool mSuspendUpdates;
+ bool mVisible;
+ ECursorType mLastSetCursor;
+ EMediaNavState mMediaNavState;
+ F64 mInterest;
+ bool mUsedInUI;
+ bool mHasFocus;
+ LLPluginClassMedia::EPriority mPriority;
+ bool mNavigateRediscoverType;
+ bool mNavigateServerRequest;
+ bool mMediaSourceFailed;
+ F32 mRequestedVolume;
+ bool mIsMuted;
+ bool mNeedsMuteCheck;
+ int mPreviousMediaState;
+ F64 mPreviousMediaTime;
+ bool mIsDisabled;
+ bool mIsParcelMedia;
+ S32 mProximity;
+ F64 mProximityDistance;
+ LLMimeDiscoveryResponder *mMimeTypeProbe;
+ bool mMediaAutoPlay;
+ std::string mMediaEntryURL;
+ bool mInNearbyMediaList; // used by LLFloaterNearbyMedia::refreshList() for performance reasons
+ bool mClearCache;
+ LLColor4 mBackgroundColor;
+ bool mNavigateSuspended;
+ bool mNavigateSuspendedDeferred;
+
+private:
+ BOOL mIsUpdated ;
+ std::list< LLVOVolume* > mObjectList ;
- private:
- // Fill in initialization data for LLMediaManager::initClass()
- static void buildMediaManagerData( LLMediaManagerData* init_data );
+private:
+ LLViewerMediaTexture *updatePlaceholderImage();
};
#endif // LLVIEWERMEDIA_H
diff --git a/indra/newview/llviewermedia_streamingaudio.cpp b/indra/newview/llviewermedia_streamingaudio.cpp
new file mode 100644
index 0000000000..67b051e536
--- /dev/null
+++ b/indra/newview/llviewermedia_streamingaudio.cpp
@@ -0,0 +1,172 @@
+/**
+ * @file llviewermedia_streamingaudio.h
+ * @author Tofu Linden, Sam Kolb
+ * @brief LLStreamingAudio_MediaPlugins implementation - an implementation of the streaming audio interface which is implemented as a client of the media plugin API.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "llviewerprecompiledheaders.h"
+#include "linden_common.h"
+#include "llpluginclassmedia.h"
+#include "llpluginclassmediaowner.h"
+#include "llviewermedia.h"
+
+#include "llviewermedia_streamingaudio.h"
+
+#include "llmimetypes.h"
+#include "llvfs.h"
+#include "lldir.h"
+
+
+LLStreamingAudio_MediaPlugins::LLStreamingAudio_MediaPlugins() :
+ mMediaPlugin(NULL),
+ mGain(1.0)
+{
+ // nothing interesting to do?
+ // we will lazily create a media plugin at play-time, if none exists.
+}
+
+LLStreamingAudio_MediaPlugins::~LLStreamingAudio_MediaPlugins()
+{
+ delete mMediaPlugin;
+ mMediaPlugin = NULL;
+}
+
+void LLStreamingAudio_MediaPlugins::start(const std::string& url)
+{
+ if (!mMediaPlugin) // lazy-init the underlying media plugin
+ {
+ mMediaPlugin = initializeMedia("audio/mpeg"); // assumes that whatever media implementation supports mp3 also supports vorbis.
+ llinfos << "streaming audio mMediaPlugin is now " << mMediaPlugin << llendl;
+ }
+
+ if(!mMediaPlugin)
+ return;
+
+ if (!url.empty()) {
+ llinfos << "Starting internet stream: " << url << llendl;
+ mURL = url;
+ mMediaPlugin->loadURI ( url );
+ mMediaPlugin->start();
+ llinfos << "Playing stream..." << llendl;
+ } else {
+ llinfos << "setting stream to NULL"<< llendl;
+ mURL.clear();
+ mMediaPlugin->stop();
+ }
+}
+
+void LLStreamingAudio_MediaPlugins::stop()
+{
+ llinfos << "Stopping internet stream." << llendl;
+ if(mMediaPlugin)
+ {
+ mMediaPlugin->stop();
+ }
+
+ mURL.clear();
+}
+
+void LLStreamingAudio_MediaPlugins::pause(int pause)
+{
+ if(!mMediaPlugin)
+ return;
+
+ if(pause)
+ {
+ llinfos << "Pausing internet stream." << llendl;
+ mMediaPlugin->pause();
+ }
+ else
+ {
+ llinfos << "Unpausing internet stream." << llendl;
+ mMediaPlugin->start();
+ }
+}
+
+void LLStreamingAudio_MediaPlugins::update()
+{
+ if (mMediaPlugin)
+ mMediaPlugin->idle();
+}
+
+int LLStreamingAudio_MediaPlugins::isPlaying()
+{
+ if (!mMediaPlugin)
+ return 0; // stopped
+
+ LLPluginClassMediaOwner::EMediaStatus status =
+ mMediaPlugin->getStatus();
+
+ switch (status)
+ {
+ case LLPluginClassMediaOwner::MEDIA_LOADING: // but not MEDIA_LOADED
+ case LLPluginClassMediaOwner::MEDIA_PLAYING:
+ return 1; // Active and playing
+ case LLPluginClassMediaOwner::MEDIA_PAUSED:
+ return 2; // paused
+ default:
+ return 0; // stopped
+ }
+}
+
+void LLStreamingAudio_MediaPlugins::setGain(F32 vol)
+{
+ mGain = vol;
+
+ if(!mMediaPlugin)
+ return;
+
+ vol = llclamp(vol, 0.f, 1.f);
+ mMediaPlugin->setVolume(vol);
+}
+
+F32 LLStreamingAudio_MediaPlugins::getGain()
+{
+ return mGain;
+}
+
+std::string LLStreamingAudio_MediaPlugins::getURL()
+{
+ return mURL;
+}
+
+LLPluginClassMedia* LLStreamingAudio_MediaPlugins::initializeMedia(const std::string& media_type)
+{
+ LLPluginClassMediaOwner* owner = NULL;
+ S32 default_size = 1; // audio-only - be minimal, doesn't matter
+ LLPluginClassMedia* media_source = LLViewerMediaImpl::newSourceFromMediaType(media_type, owner, default_size, default_size);
+
+ if (media_source)
+ {
+ media_source->setLoop(false); // audio streams are not expected to loop
+ }
+
+ return media_source;
+}
+
diff --git a/indra/newview/llviewermedia_streamingaudio.h b/indra/newview/llviewermedia_streamingaudio.h
new file mode 100644
index 0000000000..270bab7625
--- /dev/null
+++ b/indra/newview/llviewermedia_streamingaudio.h
@@ -0,0 +1,69 @@
+/**
+ * @file llviewermedia_streamingaudio.h
+ * @author Tofu Linden
+ * @brief Definition of LLStreamingAudio_MediaPlugins implementation - an implementation of the streaming audio interface which is implemented as a client of the media plugins API.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_VIEWERMEDIA_STREAMINGAUDIO_H
+#define LL_VIEWERMEDIA_STREAMINGAUDIO_H
+
+
+#include "stdtypes.h" // from llcommon
+
+#include "llstreamingaudio.h"
+
+class LLPluginClassMedia;
+
+class LLStreamingAudio_MediaPlugins : public LLStreamingAudioInterface
+{
+ public:
+ LLStreamingAudio_MediaPlugins();
+ /*virtual*/ ~LLStreamingAudio_MediaPlugins();
+
+ /*virtual*/ void start(const std::string& url);
+ /*virtual*/ void stop();
+ /*virtual*/ void pause(int pause);
+ /*virtual*/ void update();
+ /*virtual*/ int isPlaying();
+ /*virtual*/ void setGain(F32 vol);
+ /*virtual*/ F32 getGain();
+ /*virtual*/ std::string getURL();
+
+private:
+ LLPluginClassMedia* initializeMedia(const std::string& media_type);
+
+ LLPluginClassMedia *mMediaPlugin;
+
+ std::string mURL;
+ F32 mGain;
+};
+
+
+#endif //LL_VIEWERMEDIA_STREAMINGAUDIO_H
diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp
new file mode 100644
index 0000000000..a0ac9c2091
--- /dev/null
+++ b/indra/newview/llviewermediafocus.cpp
@@ -0,0 +1,566 @@
+/**
+ * @file llviewermediafocus.cpp
+ * @brief Governs focus on Media prims
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llviewermediafocus.h"
+
+//LLViewerMediaFocus
+#include "llviewerobjectlist.h"
+#include "llpanelprimmediacontrols.h"
+#include "llpluginclassmedia.h"
+#include "llagent.h"
+#include "lltoolpie.h"
+#include "llviewercamera.h"
+#include "llviewermedia.h"
+#include "llhudview.h"
+#include "lluictrlfactory.h"
+#include "lldrawable.h"
+#include "llparcel.h"
+#include "llviewerparcelmgr.h"
+#include "llweb.h"
+#include "llmediaentry.h"
+#include "llkeyboard.h"
+#include "lltoolmgr.h"
+#include "llvovolume.h"
+#include "llhelp.h"
+
+//
+// LLViewerMediaFocus
+//
+
+LLViewerMediaFocus::LLViewerMediaFocus()
+: mFocusedObjectFace(0),
+ mHoverObjectFace(0)
+{
+}
+
+LLViewerMediaFocus::~LLViewerMediaFocus()
+{
+ // The destructor for LLSingletons happens at atexit() time, which is too late to do much.
+ // Clean up in cleanupClass() instead.
+}
+
+void LLViewerMediaFocus::setFocusFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal)
+{
+ LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+
+ LLViewerMediaImpl *old_media_impl = getFocusedMediaImpl();
+ if(old_media_impl)
+ {
+ old_media_impl->focus(false);
+ }
+
+ // Always clear the current selection. If we're setting focus on a face, we'll reselect the correct object below.
+ LLSelectMgr::getInstance()->deselectAll();
+ mSelection = NULL;
+
+ if (media_impl.notNull() && objectp.notNull())
+ {
+ bool face_auto_zoom = false;
+
+ mFocusedImplID = media_impl->getMediaTextureID();
+ mFocusedObjectID = objectp->getID();
+ mFocusedObjectFace = face;
+ mFocusedObjectNormal = pick_normal;
+
+ // Set the selection in the selection manager so we can draw the focus ring.
+ mSelection = LLSelectMgr::getInstance()->selectObjectOnly(objectp, face);
+
+ // Focusing on a media face clears its disable flag.
+ media_impl->setDisabled(false);
+
+ LLTextureEntry* tep = objectp->getTE(face);
+ if(tep->hasMedia())
+ {
+ LLMediaEntry* mep = tep->getMediaData();
+ face_auto_zoom = mep->getAutoZoom();
+ if(!media_impl->hasMedia())
+ {
+ std::string url = mep->getCurrentURL().empty() ? mep->getHomeURL() : mep->getCurrentURL();
+ media_impl->navigateTo(url, "", true);
+ }
+ }
+ else
+ {
+ // This should never happen.
+ llwarns << "Can't find media entry for focused face" << llendl;
+ }
+
+ media_impl->focus(true);
+ gFocusMgr.setKeyboardFocus(this);
+
+ // We must do this before processing the media HUD zoom, or it may zoom to the wrong face.
+ update();
+
+ if(mMediaControls.get())
+ {
+ if(face_auto_zoom && ! parcel->getMediaPreventCameraZoom())
+ {
+ // Zoom in on this face
+ mMediaControls.get()->resetZoomLevel();
+ mMediaControls.get()->nextZoomLevel();
+ }
+ else
+ {
+ // Reset the controls' zoom level without moving the camera.
+ // This fixes the case where clicking focus between two non-autozoom faces doesn't change the zoom-out button back to a zoom-in button.
+ mMediaControls.get()->resetZoomLevel(false);
+ }
+ }
+ }
+ else
+ {
+ if(hasFocus())
+ {
+ gFocusMgr.setKeyboardFocus(NULL);
+ }
+
+ mFocusedImplID = LLUUID::null;
+ if (objectp.notNull())
+ {
+ // Still record the focused object...it may mean we need to load media data.
+ // This will aid us in determining this object is "important enough"
+ mFocusedObjectID = objectp->getID();
+ mFocusedObjectFace = face;
+ }
+ else {
+ mFocusedObjectID = LLUUID::null;
+ mFocusedObjectFace = 0;
+ }
+ }
+
+}
+
+void LLViewerMediaFocus::clearFocus()
+{
+ setFocusFace(NULL, 0, NULL);
+}
+
+void LLViewerMediaFocus::setHoverFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal)
+{
+ if (media_impl.notNull())
+ {
+ mHoverImplID = media_impl->getMediaTextureID();
+ mHoverObjectID = objectp->getID();
+ mHoverObjectFace = face;
+ mHoverObjectNormal = pick_normal;
+ }
+ else
+ {
+ mHoverObjectID = LLUUID::null;
+ mHoverObjectFace = 0;
+ mHoverImplID = LLUUID::null;
+ }
+}
+
+void LLViewerMediaFocus::clearHover()
+{
+ setHoverFace(NULL, 0, NULL);
+}
+
+
+bool LLViewerMediaFocus::getFocus()
+{
+ if (gFocusMgr.getKeyboardFocus() == this)
+ {
+ return true;
+ }
+ return false;
+}
+
+// This function selects an ideal viewing distance based on the focused object, pick normal, and padding value
+void LLViewerMediaFocus::setCameraZoom(LLViewerObject* object, LLVector3 normal, F32 padding_factor)
+{
+ if (object)
+ {
+ gAgent.setFocusOnAvatar(FALSE, ANIMATE);
+
+ LLBBox bbox = object->getBoundingBoxAgent();
+ LLVector3d center = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent());
+ F32 height;
+ F32 width;
+ F32 depth;
+ F32 angle_of_view;
+ F32 distance;
+
+ // We need the aspect ratio, and the 3 components of the bbox as height, width, and depth.
+ F32 aspect_ratio = getBBoxAspectRatio(bbox, normal, &height, &width, &depth);
+ F32 camera_aspect = LLViewerCamera::getInstance()->getAspect();
+
+ // We will normally use the side of the volume aligned with the short side of the screen (i.e. the height for
+ // a screen in a landscape aspect ratio), however there is an edge case where the aspect ratio of the object is
+ // more extreme than the screen. In this case we invert the logic, using the longer component of both the object
+ // and the screen.
+ bool invert = (camera_aspect > 1.0f && aspect_ratio > camera_aspect) ||
+ (camera_aspect < 1.0f && aspect_ratio < camera_aspect);
+
+ // To calculate the optimum viewing distance we will need the angle of the shorter side of the view rectangle.
+ // In portrait mode this is the width, and in landscape it is the height.
+ // We then calculate the distance based on the corresponding side of the object bbox (width for portrait, height for landscape)
+ // We will add half the depth of the bounding box, as the distance projection uses the center point of the bbox.
+ if(camera_aspect < 1.0f || invert)
+ {
+ angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect());
+ distance = width * 0.5 * padding_factor / tan(angle_of_view * 0.5f );
+ }
+ else
+ {
+ angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getView());
+ distance = height * 0.5 * padding_factor / tan(angle_of_view * 0.5f );
+ }
+
+ distance += depth * 0.5;
+
+ // Finally animate the camera to this new position and focal point
+ LLVector3d camera_pos, target_pos;
+ // The target lookat position is the center of the selection (in global coords)
+ target_pos = center;
+ // Target look-from (camera) position is "distance" away from the target along the normal
+ LLVector3d pickNormal = LLVector3d(normal);
+ pickNormal.normalize();
+ camera_pos = target_pos + pickNormal * distance;
+ if (pickNormal == LLVector3d::z_axis || pickNormal == LLVector3d::z_axis_neg)
+ {
+ // If the normal points directly up, the camera will "flip" around.
+ // We try to avoid this by adjusting the target camera position a
+ // smidge towards current camera position
+ // *NOTE: this solution is not perfect. All it attempts to solve is the
+ // "looking down" problem where the camera flips around when it animates
+ // to that position. You still are not guaranteed to be looking at the
+ // media in the correct orientation. What this solution does is it will
+ // put the camera into position keeping as best it can the current
+ // orientation with respect to the face. In other words, if before zoom
+ // the media appears "upside down" from the camera, after zooming it will
+ // still be upside down, but at least it will not flip.
+ LLVector3d cur_camera_pos = LLVector3d(gAgent.getCameraPositionGlobal());
+ LLVector3d delta = (cur_camera_pos - camera_pos);
+ F64 len = delta.length();
+ delta.normalize();
+ // Move 1% of the distance towards original camera location
+ camera_pos += 0.01 * len * delta;
+ }
+
+ gAgent.setCameraPosAndFocusGlobal(camera_pos, target_pos, object->getID() );
+ }
+ else
+ {
+ // If we have no object, focus back on the avatar.
+ gAgent.setFocusOnAvatar(TRUE, ANIMATE);
+ }
+}
+void LLViewerMediaFocus::onFocusReceived()
+{
+ LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+ if(media_impl)
+ media_impl->focus(true);
+
+ LLFocusableElement::onFocusReceived();
+}
+
+void LLViewerMediaFocus::onFocusLost()
+{
+ LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+ if(media_impl)
+ media_impl->focus(false);
+
+ gViewerWindow->focusClient();
+ LLFocusableElement::onFocusLost();
+}
+
+BOOL LLViewerMediaFocus::handleKey(KEY key, MASK mask, BOOL called_from_parent)
+{
+ LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+ if(media_impl)
+ {
+ media_impl->handleKeyHere(key, mask);
+
+ if (KEY_ESCAPE == key)
+ {
+ // Reset camera zoom in this case.
+ if(mFocusedImplID.notNull())
+ {
+ if(mMediaControls.get())
+ {
+ mMediaControls.get()->resetZoomLevel(true);
+ }
+ }
+
+ clearFocus();
+ }
+
+ if ( KEY_F1 == key && LLUI::sHelpImpl && mMediaControls.get())
+ {
+ std::string help_topic;
+ if (mMediaControls.get()->findHelpTopic(help_topic))
+ {
+ LLUI::sHelpImpl->showTopic(help_topic);
+ }
+ }
+ }
+
+ return true;
+}
+
+BOOL LLViewerMediaFocus::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
+{
+ LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+ if(media_impl)
+ media_impl->handleUnicodeCharHere(uni_char);
+ return true;
+}
+BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks)
+{
+ BOOL retval = FALSE;
+ LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+ if(media_impl && media_impl->hasMedia())
+ {
+ // the scrollEvent() API's x and y are not the same as handleScrollWheel's x and y.
+ // The latter is the position of the mouse at the time of the event
+ // The former is the 'scroll amount' in x and y, respectively.
+ // All we have for 'scroll amount' here is 'clicks'.
+ // We're also not passed the keyboard modifier mask, but we can get that from gKeyboard.
+ media_impl->getMediaPlugin()->scrollEvent(0, clicks, gKeyboard->currentMask(TRUE));
+ retval = TRUE;
+ }
+ return retval;
+}
+
+void LLViewerMediaFocus::update()
+{
+ if(mFocusedImplID.notNull())
+ {
+ // We have a focused impl/face.
+ if(!getFocus())
+ {
+ // We've lost keyboard focus -- check to see whether the media controls have it
+ if(mMediaControls.get() && mMediaControls.get()->hasFocus())
+ {
+ // the media controls have focus -- don't clear.
+ }
+ else
+ {
+ // Someone else has focus -- back off.
+ clearFocus();
+ }
+ }
+ else if(LLToolMgr::getInstance()->inBuildMode())
+ {
+ // Build tools are selected -- clear focus.
+ clearFocus();
+ }
+ }
+
+
+ LLViewerMediaImpl *media_impl = getFocusedMediaImpl();
+ LLViewerObject *viewer_object = getFocusedObject();
+ S32 face = mFocusedObjectFace;
+ LLVector3 normal = mFocusedObjectNormal;
+ bool focus = true;
+
+ if(!media_impl || !viewer_object)
+ {
+ focus = false;
+ media_impl = getHoverMediaImpl();
+ viewer_object = getHoverObject();
+ face = mHoverObjectFace;
+ normal = mHoverObjectNormal;
+ }
+
+ if(media_impl && viewer_object)
+ {
+ // We have an object and impl to point at.
+
+ // Make sure the media HUD object exists.
+ if(! mMediaControls.get())
+ {
+ LLPanelPrimMediaControls* media_controls = new LLPanelPrimMediaControls();
+ mMediaControls = media_controls->getHandle();
+ gHUDView->addChild(media_controls);
+ }
+ mMediaControls.get()->setMediaFace(viewer_object, face, media_impl, normal);
+ }
+ else
+ {
+ // The media HUD is no longer needed.
+ if(mMediaControls.get())
+ {
+ mMediaControls.get()->setMediaFace(NULL, 0, NULL);
+ }
+ }
+}
+
+
+// This function calculates the aspect ratio and the world aligned components of a selection bounding box.
+F32 LLViewerMediaFocus::getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth)
+{
+ // Convert the selection normal and an up vector to local coordinate space of the bbox
+ LLVector3 local_normal = bbox.agentToLocalBasis(normal);
+ LLVector3 z_vec = bbox.agentToLocalBasis(LLVector3(0.0f, 0.0f, 1.0f));
+
+ LLVector3 comp1(0.f,0.f,0.f);
+ LLVector3 comp2(0.f,0.f,0.f);
+ LLVector3 bbox_max = bbox.getExtentLocal();
+ F32 dot1 = 0.f;
+ F32 dot2 = 0.f;
+
+ // The largest component of the localized normal vector is the depth component
+ // meaning that the other two are the legs of the rectangle.
+ local_normal.abs();
+ if(local_normal.mV[VX] > local_normal.mV[VY])
+ {
+ if(local_normal.mV[VX] > local_normal.mV[VZ])
+ {
+ // Use the y and z comps
+ comp1.mV[VY] = bbox_max.mV[VY];
+ comp2.mV[VZ] = bbox_max.mV[VZ];
+ *depth = bbox_max.mV[VX];
+ }
+ else
+ {
+ // Use the x and y comps
+ comp1.mV[VY] = bbox_max.mV[VY];
+ comp2.mV[VZ] = bbox_max.mV[VZ];
+ *depth = bbox_max.mV[VZ];
+ }
+ }
+ else if(local_normal.mV[VY] > local_normal.mV[VZ])
+ {
+ // Use the x and z comps
+ comp1.mV[VX] = bbox_max.mV[VX];
+ comp2.mV[VZ] = bbox_max.mV[VZ];
+ *depth = bbox_max.mV[VY];
+ }
+ else
+ {
+ // Use the x and y comps
+ comp1.mV[VY] = bbox_max.mV[VY];
+ comp2.mV[VZ] = bbox_max.mV[VZ];
+ *depth = bbox_max.mV[VX];
+ }
+
+ // The height is the vector closest to vertical in the bbox coordinate space (highest dot product value)
+ dot1 = comp1 * z_vec;
+ dot2 = comp2 * z_vec;
+ if(fabs(dot1) > fabs(dot2))
+ {
+ *height = comp1.length();
+ *width = comp2.length();
+ }
+ else
+ {
+ *height = comp2.length();
+ *width = comp1.length();
+ }
+
+ // Return the aspect ratio.
+ return *width / *height;
+}
+
+bool LLViewerMediaFocus::isFocusedOnFace(LLPointer<LLViewerObject> objectp, S32 face)
+{
+ return objectp->getID() == mFocusedObjectID && face == mFocusedObjectFace;
+}
+
+bool LLViewerMediaFocus::isHoveringOverFace(LLPointer<LLViewerObject> objectp, S32 face)
+{
+ return objectp->getID() == mHoverObjectID && face == mHoverObjectFace;
+}
+
+
+LLViewerMediaImpl* LLViewerMediaFocus::getFocusedMediaImpl()
+{
+ return LLViewerMedia::getMediaImplFromTextureID(mFocusedImplID);
+}
+
+LLViewerObject* LLViewerMediaFocus::getFocusedObject()
+{
+ return gObjectList.findObject(mFocusedObjectID);
+}
+
+LLViewerMediaImpl* LLViewerMediaFocus::getHoverMediaImpl()
+{
+ return LLViewerMedia::getMediaImplFromTextureID(mHoverImplID);
+}
+
+LLViewerObject* LLViewerMediaFocus::getHoverObject()
+{
+ return gObjectList.findObject(mHoverObjectID);
+}
+
+void LLViewerMediaFocus::focusZoomOnMedia(LLUUID media_id)
+{
+ LLViewerMediaImpl* impl = LLViewerMedia::getMediaImplFromTextureID(media_id);
+
+ if(impl)
+ {
+ // Get the first object from the media impl's object list. This is completely arbitrary, but should suffice.
+ LLVOVolume *obj = impl->getSomeObject();
+ if(obj)
+ {
+ // This media is attached to at least one object. Figure out which face it's on.
+ S32 face = obj->getFaceIndexWithMediaImpl(impl, -1);
+
+ // We don't have a proper pick normal here, and finding a face's real normal is... complicated.
+ LLVector3 normal = obj->getApproximateFaceNormal(face);
+ if(normal.isNull())
+ {
+ // If that didn't work, use the inverse of the camera "look at" axis, which should keep the camera pointed in the same direction.
+// llinfos << "approximate face normal invalid, using camera direction." << llendl;
+ normal = LLViewerCamera::getInstance()->getAtAxis();
+ normal *= (F32)-1.0f;
+ }
+
+ // Attempt to focus/zoom on that face.
+ setFocusFace(obj, face, impl, normal);
+
+ if(mMediaControls.get())
+ {
+ mMediaControls.get()->resetZoomLevel();
+ mMediaControls.get()->nextZoomLevel();
+ }
+ }
+ }
+}
+
+LLUUID LLViewerMediaFocus::getControlsMediaID()
+{
+ if(getFocusedMediaImpl())
+ {
+ return mFocusedImplID;
+ }
+ else if(getHoverMediaImpl())
+ {
+ return mHoverImplID;
+ }
+
+ return LLUUID::null;
+}
diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h
new file mode 100644
index 0000000000..89ee0ae283
--- /dev/null
+++ b/indra/newview/llviewermediafocus.h
@@ -0,0 +1,113 @@
+/**
+ * @file llpanelmsgs.h
+ * @brief Message popup preferences panel
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_VIEWERMEDIAFOCUS_H
+#define LL_VIEWERMEDIAFOCUS_H
+
+// includes for LLViewerMediaFocus
+#include "llfocusmgr.h"
+#include "llviewermedia.h"
+#include "llviewerobject.h"
+#include "llviewerwindow.h"
+#include "llselectmgr.h"
+
+class LLViewerMediaImpl;
+class LLPanelPrimMediaControls;
+
+class LLViewerMediaFocus :
+ public LLFocusableElement,
+ public LLSingleton<LLViewerMediaFocus>
+{
+public:
+ LLViewerMediaFocus();
+ ~LLViewerMediaFocus();
+
+ // Set/clear the face that has media focus (takes keyboard input and has the full set of controls)
+ void setFocusFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3::zero);
+ void clearFocus();
+
+ // Set/clear the face that has "media hover" (has the mimimal set of controls to zoom in or pop out into a media browser).
+ // If a media face has focus, the media hover will be ignored.
+ void setHoverFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3::zero);
+ void clearHover();
+
+ /*virtual*/ bool getFocus();
+ /*virtual*/ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
+ /*virtual*/ BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
+ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+
+ void update();
+
+ static void setCameraZoom(LLViewerObject* object, LLVector3 normal, F32 padding_factor);
+ static F32 getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth);
+
+ bool isFocusedOnFace(LLPointer<LLViewerObject> objectp, S32 face);
+ bool isHoveringOverFace(LLPointer<LLViewerObject> objectp, S32 face);
+
+ // These look up (by uuid) and return the values that were set with setFocusFace. They will return null if the objects have been destroyed.
+ LLViewerMediaImpl* getFocusedMediaImpl();
+ LLViewerObject* getFocusedObject();
+ S32 getFocusedFace() { return mFocusedObjectFace; }
+ LLUUID getFocusedObjectID() { return mFocusedObjectID; }
+
+ // These look up (by uuid) and return the values that were set with setHoverFace. They will return null if the objects have been destroyed.
+ LLViewerMediaImpl* getHoverMediaImpl();
+ LLViewerObject* getHoverObject();
+ S32 getHoverFace() { return mHoverObjectFace; }
+
+ // Try to focus/zoom on the specified media (if it's on an object in world).
+ void focusZoomOnMedia(LLUUID media_id);
+
+ // Return the ID of the media instance the controls are currently attached to (either focus or hover).
+ LLUUID getControlsMediaID();
+
+protected:
+ /*virtual*/ void onFocusReceived();
+ /*virtual*/ void onFocusLost();
+
+private:
+
+ LLHandle<LLPanelPrimMediaControls> mMediaControls;
+ LLObjectSelectionHandle mSelection;
+
+ LLUUID mFocusedObjectID;
+ S32 mFocusedObjectFace;
+ LLUUID mFocusedImplID;
+ LLVector3 mFocusedObjectNormal;
+
+ LLUUID mHoverObjectID;
+ S32 mHoverObjectFace;
+ LLUUID mHoverImplID;
+ LLVector3 mHoverObjectNormal;
+};
+
+
+#endif // LL_VIEWERMEDIAFOCUS_H
diff --git a/indra/newview/llviewermediaobserver.h b/indra/newview/llviewermediaobserver.h
new file mode 100644
index 0000000000..6667f982b6
--- /dev/null
+++ b/indra/newview/llviewermediaobserver.h
@@ -0,0 +1,71 @@
+/**
+ * @file llviewermediaobserver.h
+ * @brief Methods to override to catch events from LLViewerMedia class
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLVIEWERMEDIAOBSERVER_H
+#define LLVIEWERMEDIAOBSERVER_H
+
+#include "llpluginclassmediaowner.h"
+
+class LLViewerMediaEventEmitter;
+
+class LLViewerMediaObserver : public LLPluginClassMediaOwner
+{
+public:
+ virtual ~LLViewerMediaObserver();
+
+private:
+ // Emitters will manage this list in addObserver/remObserver.
+ friend class LLViewerMediaEventEmitter;
+ std::list<LLViewerMediaEventEmitter *> mEmitters;
+};
+
+
+#if 0
+ // Classes that inherit from LLViewerMediaObserver should add this to their class declaration:
+
+ // inherited from LLViewerMediaObserver
+ /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
+
+ /* and will probably need to add this to their cpp file:
+
+ #include "llpluginclassmedia.h"
+
+ */
+
+ // The list of events is in llpluginclassmediaowner.h
+
+
+#endif
+
+
+#endif // LLVIEWERMEDIAOBSERVER_H
+
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index fe91da05fa..5ff5b82a17 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -1,4 +1,3 @@
-
/**
* @file llviewermenu.cpp
* @brief Builds menus out of items.
@@ -32,200 +31,81 @@
*/
#include "llviewerprecompiledheaders.h"
-
#include "llviewermenu.h"
-// system library includes
-#include <iostream>
-#include <fstream>
-#include <sstream>
-
// linden library includes
-#include "audioengine.h"
-#include "indra_constants.h"
-#include "llassetstorage.h"
-#include "llchat.h"
-#include "llfeaturemanager.h"
-#include "llfocusmgr.h"
-#include "llfontgl.h"
-#include "llinstantmessage.h"
-#include "llpermissionsflags.h"
-#include "llrect.h"
-#include "llsecondlifeurls.h"
-#include "lltransactiontypes.h"
-#include "llui.h"
-#include "llview.h"
-#include "llxfermanager.h"
-#include "message.h"
-#include "raytrace.h"
-#include "llsdserialize.h"
-#include "lltimer.h"
-#include "llvfile.h"
-#include "llvolumemgr.h"
+#include "llfloaterreg.h"
+#include "llcombobox.h"
+#include "llinventorypanel.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
// newview includes
#include "llagent.h"
-
+#include "llagentwearables.h"
#include "llagentpilot.h"
-#include "llbox.h"
-#include "llcallingcard.h"
-#include "llclipboard.h"
#include "llcompilequeue.h"
#include "llconsole.h"
-#include "llviewercontrol.h"
#include "lldebugview.h"
-#include "lldir.h"
-#include "lldrawable.h"
-#include "lldrawpoolalpha.h"
-#include "lldrawpooltree.h"
-#include "llface.h"
-#include "llfirstuse.h"
-#include "llfloater.h"
-#include "llfloaterabout.h"
-#include "llfloaterbuycurrency.h"
-#include "llfloateractivespeakers.h"
-#include "llfloateranimpreview.h"
-#include "llfloateravatarinfo.h"
-#include "llfloateravatartextures.h"
-#include "llfloaterbeacons.h"
-#include "llfloaterbuildoptions.h"
-#include "llfloaterbump.h"
+#include "llfilepicker.h"
+//#include "llfirstuse.h"
#include "llfloaterbuy.h"
#include "llfloaterbuycontents.h"
#include "llfloaterbuycurrency.h"
-#include "llfloaterbuyland.h"
-#include "llfloatercamera.h"
-#include "llfloaterchat.h"
#include "llfloatercustomize.h"
-#include "llfloaterdaycycle.h"
-#include "llfloaterdirectory.h"
-#include "llfloatereditui.h"
#include "llfloaterchatterbox.h"
-#include "llfloaterfriends.h"
-#include "llfloaterfonttest.h"
-#include "llfloatergesture.h"
#include "llfloatergodtools.h"
-#include "llfloatergroupinfo.h"
-#include "llfloatergroupinvite.h"
-#include "llfloatergroups.h"
-#include "llfloaterhtml.h"
-#include "llfloaterhtmlcurrency.h"
-#include "llfloaterhtmlhelp.h" // gViewerHtmlHelp
-#include "llfloaterhtmlsimple.h"
-#include "llfloaterhud.h"
-#include "llfloaterinspect.h"
-#include "llfloaterlagmeter.h"
+#include "llfloaterinventory.h"
#include "llfloaterland.h"
-#include "llfloaterlandholdings.h"
-#include "llfloatermap.h"
-#include "llfloatermute.h"
-#include "llfloateropenobject.h"
-#include "llfloaterpermissionsmgr.h"
-#include "llfloaterperms.h"
-#include "llfloaterpostprocess.h"
-#include "llfloaterpreference.h"
-#include "llfloaterregioninfo.h"
+#include "llfloaterpay.h"
#include "llfloaterreporter.h"
+#include "llfloatersearch.h"
#include "llfloaterscriptdebug.h"
-#include "llfloatersettingsdebug.h"
-#include "llfloaterenvsettings.h"
-#include "llfloaterstats.h"
-#include "llfloatertest.h"
+#include "llfloatersnapshot.h"
#include "llfloatertools.h"
-#include "llfloaterwater.h"
-#include "llfloaterwindlight.h"
#include "llfloaterworldmap.h"
-#include "llfloatermemleak.h"
-#include "llframestats.h"
-#include "llframestatview.h"
-#include "llfasttimerview.h"
-#include "llmemoryview.h"
-#include "llgivemoney.h"
+#include "llavataractions.h"
+#include "lllandmarkactions.h"
#include "llgroupmgr.h"
-#include "llhoverview.h"
+#include "lltooltip.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
-#include "llimage.h"
-#include "llimagebmp.h"
-#include "llimagej2c.h"
-#include "llimagetga.h"
-#include "llinventorymodel.h"
-#include "llinventoryview.h"
-#include "llkeyboard.h"
+#include "llimview.h"
+#include "llinventorybridge.h"
#include "llpanellogin.h"
+#include "llpanelblockedlist.h"
#include "llmenucommands.h"
-#include "llmenugl.h"
-#include "llmorphview.h"
#include "llmoveview.h"
-#include "llmutelist.h"
-#include "llnotify.h"
-#include "llpanelobject.h"
#include "llparcel.h"
-#include "llprimitive.h"
-#include "llresmgr.h"
+#include "llrootview.h"
#include "llselectmgr.h"
-#include "llsky.h"
+#include "llsidetray.h"
#include "llstatusbar.h"
-#include "llstatview.h"
-#include "llstring.h"
-#include "llsurfacepatch.h"
-#include "llimview.h"
#include "lltextureview.h"
-#include "lltool.h"
#include "lltoolbar.h"
#include "lltoolcomp.h"
-#include "lltoolfocus.h"
-#include "lltoolgrab.h"
#include "lltoolmgr.h"
#include "lltoolpie.h"
-#include "lltoolplacer.h"
#include "lltoolselectland.h"
-#include "lluictrlfactory.h"
-#include "lluploaddialog.h"
-#include "lluserauth.h"
-#include "lluuid.h"
-#include "llvelocitybar.h"
-#include "llviewercamera.h"
#include "llviewergenericmessage.h"
-#include "llviewergesture.h"
-#include "llviewerimagelist.h" // gImageList
-#include "llviewerinventory.h"
+#include "llviewerhelp.h"
#include "llviewermenufile.h" // init_menu_file()
#include "llviewermessage.h"
#include "llviewernetwork.h"
#include "llviewerobjectlist.h"
#include "llviewerparcelmgr.h"
-#include "llviewerparceloverlay.h"
-#include "llviewerregion.h"
#include "llviewerstats.h"
-#include "llviewerwindow.h"
-#include "llvoavatar.h"
-#include "llvolume.h"
-#include "llweb.h"
-#include "llworld.h"
+#include "llvoavatarself.h"
#include "llworldmap.h"
-#include "object_flags.h"
#include "pipeline.h"
-#include "llappviewer.h"
-#include "roles_constants.h"
#include "llviewerjoystick.h"
#include "llwlanimator.h"
#include "llwlparammanager.h"
-#include "llwaterparammanager.h"
-#include "llfloaternotificationsconsole.h"
-
-#include "lltexlayer.h"
+#include "llfloatercamera.h"
+#include "lluilistener.h"
+#include "llappearancemgr.h"
using namespace LLVOAvatarDefines;
-void init_client_menu(LLMenuGL* menu);
-void init_server_menu(LLMenuGL* menu);
-
-void init_debug_world_menu(LLMenuGL* menu);
-void init_debug_rendering_menu(LLMenuGL* menu);
-void init_debug_ui_menu(LLMenuGL* menu);
-void init_debug_xui_menu(LLMenuGL* menu);
-void init_debug_avatar_menu(LLMenuGL* menu);
-void init_debug_baked_texture_menu(LLMenuGL* menu);
BOOL enable_land_build(void*);
BOOL enable_object_build(void*);
@@ -237,13 +117,14 @@ void handle_test_load_url(void*);
//
// Evil hackish imported globals
-//
-extern BOOL gRenderLightGlows;
-extern BOOL gRenderAvatar;
-extern BOOL gHideSelectedObjects;
-extern BOOL gShowOverlayTitle;
-extern BOOL gOcclusionCull;
-extern BOOL gAllowSelectAvatar;
+
+//extern BOOL gHideSelectedObjects;
+//extern BOOL gAllowSelectAvatar;
+//extern BOOL gDebugAvatarRotation;
+extern BOOL gDebugClicks;
+extern BOOL gDebugWindowProc;
+//extern BOOL gDebugTextEditorTips;
+//extern BOOL gDebugSelectMgr;
//
// Globals
@@ -255,15 +136,12 @@ LLMenuGL *gPopupMenuView = NULL;
LLMenuBarGL *gLoginMenuBarView = NULL;
// Pie menus
-LLPieMenu *gPieSelf = NULL;
-LLPieMenu *gPieAvatar = NULL;
-LLPieMenu *gPieObject = NULL;
-LLPieMenu *gPieAttachment = NULL;
-LLPieMenu *gPieLand = NULL;
-
-// local constants
-const std::string CLIENT_MENU_NAME("Advanced");
-const std::string SERVER_MENU_NAME("Admin");
+LLContextMenu *gMenuAvatarSelf = NULL;
+LLContextMenu *gMenuAvatarOther = NULL;
+LLContextMenu *gMenuObject = NULL;
+LLContextMenu *gMenuAttachmentSelf = NULL;
+LLContextMenu *gMenuAttachmentOther = NULL;
+LLContextMenu *gMenuLand = NULL;
const std::string SAVE_INTO_INVENTORY("Save Object Back to My Inventory");
const std::string SAVE_INTO_TASK_INVENTORY("Save Object Back to Object Contents");
@@ -271,35 +149,29 @@ const std::string SAVE_INTO_TASK_INVENTORY("Save Object Back to Object Contents"
LLMenuGL* gAttachSubMenu = NULL;
LLMenuGL* gDetachSubMenu = NULL;
LLMenuGL* gTakeOffClothes = NULL;
-LLPieMenu* gPieRate = NULL;
-LLPieMenu* gAttachScreenPieMenu = NULL;
-LLPieMenu* gAttachPieMenu = NULL;
-LLPieMenu* gAttachBodyPartPieMenus[8];
-LLPieMenu* gDetachPieMenu = NULL;
-LLPieMenu* gDetachScreenPieMenu = NULL;
-LLPieMenu* gDetachBodyPartPieMenus[8];
+LLContextMenu* gAttachScreenPieMenu = NULL;
+LLContextMenu* gAttachPieMenu = NULL;
+LLContextMenu* gAttachBodyPartPieMenus[8];
+LLContextMenu* gDetachPieMenu = NULL;
+LLContextMenu* gDetachScreenPieMenu = NULL;
+LLContextMenu* gDetachBodyPartPieMenus[8];
LLMenuItemCallGL* gAFKMenu = NULL;
LLMenuItemCallGL* gBusyMenu = NULL;
-typedef LLMemberListener<LLView> view_listener_t;
-
//
// Local prototypes
-//
-void handle_leave_group(void *);
// File Menu
+const char* upload_pick(void* data);
void handle_compress_image(void*);
-BOOL enable_save_as(void *);
+
// Edit menu
void handle_dump_group_info(void *);
void handle_dump_capabilities_info(void *);
-void handle_dump_focus(void*);
// Advanced->Consoles menu
-void handle_show_notifications_console(void*);
void handle_region_dump_settings(void*);
void handle_region_dump_temp_asset_data(void*);
void handle_region_clear_temp_asset_data(void*);
@@ -308,7 +180,7 @@ void handle_region_clear_temp_asset_data(void*);
BOOL sitting_on_selection();
void near_sit_object();
-void label_sit_or_stand(std::string& label, void*);
+//void label_sit_or_stand(std::string& label, void*);
// buy and take alias into the same UI positions, so these
// declarations handle this mess.
BOOL is_selection_buy_not_take();
@@ -316,56 +188,34 @@ S32 selection_price();
BOOL enable_take();
void handle_take();
bool confirm_take(const LLSD& notification, const LLSD& response);
-BOOL enable_buy(void*);
-void handle_buy(void *);
+
void handle_buy_object(LLSaleInfo sale_info);
void handle_buy_contents(LLSaleInfo sale_info);
-void label_touch(std::string& label, void*);
// Land pie menu
void near_sit_down_point(BOOL success, void *);
// Avatar pie menu
-void handle_follow(void *userdata);
-void handle_talk_to(void *userdata);
// Debug menu
-void show_permissions_control(void*);
-void toggle_build_options(void* user_data);
-void reload_ui(void*);
-void handle_agent_stop_moving(void*);
-void print_packets_lost(void*);
-void drop_packet(void*);
-void velocity_interpolate( void* data );
-void toggle_wind_audio(void);
-void toggle_water_audio(void);
+
+
+void velocity_interpolate( void* );
+
void handle_rebake_textures(void*);
BOOL check_admin_override(void*);
void handle_admin_override_toggle(void*);
#ifdef TOGGLE_HACKED_GODLIKE_VIEWER
void handle_toggle_hacked_godmode(void*);
BOOL check_toggle_hacked_godmode(void*);
+bool enable_toggle_hacked_godmode(void*);
#endif
-void toggle_glow(void *);
-BOOL check_glow(void *);
-
-void toggle_vertex_shaders(void *);
-BOOL check_vertex_shaders(void *);
-
-void toggle_cull_small(void *);
-
void toggle_show_xui_names(void *);
BOOL check_show_xui_names(void *);
-void run_vectorize_perf_test(void *)
-{
- gSavedSettings.setBOOL("VectorizePerfTest", TRUE);
-}
-
// Debug UI
-void handle_web_search_demo(void*);
-void handle_web_browser_test(void*);
+
void handle_buy_currency_test(void*);
void handle_save_to_xml(void*);
void handle_load_from_xml(void*);
@@ -375,16 +225,12 @@ void handle_god_mode(void*);
// God menu
void handle_leave_god_mode(void*);
-BOOL is_inventory_visible( void* user_data );
+
void handle_reset_view();
-void disabled_duplicate(void*);
void handle_duplicate_in_place(void*);
-void handle_repeat_duplicate(void*);
-void handle_export(void*);
-// void handle_deed_object_to_group(void*);
-// BOOL enable_deed_object_to_group(void*);
+
void handle_object_owner_self(void*);
void handle_object_owner_permissive(void*);
void handle_object_lock(void*);
@@ -399,11 +245,8 @@ void handle_force_parcel_owner_to_me(void*);
void handle_force_parcel_to_content(void*);
void handle_claim_public_land(void*);
-void handle_god_request_havok(void *);
void handle_god_request_avatar_geometry(void *); // Hack for easy testing of new avatar geometry
-void reload_personal_settings_overrides(void *);
void reload_vertex_shader(void *);
-void slow_mo_animations(void *);
void handle_disconnect_viewer(void *);
void force_error_breakpoint(void *);
@@ -413,27 +256,14 @@ void force_error_infinite_loop(void *);
void force_error_software_exception(void *);
void force_error_driver_crash(void *);
-void handle_stopall(void*);
-//void handle_hinge(void*);
-//void handle_ptop(void*);
-//void handle_lptop(void*);
-//void handle_wheel(void*);
-//void handle_dehinge(void*);
-BOOL enable_dehinge(void*);
void handle_force_delete(void*);
void print_object_info(void*);
void print_agent_nvpairs(void*);
void toggle_debug_menus(void*);
-void export_info_callback(LLAssetInfo *info, void **user_data, S32 result);
-void export_data_callback(LLVFS *vfs, const LLUUID& uuid, LLAssetType::EType type, void **user_data, S32 result);
void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExtStat ext_status);
-BOOL menu_check_build_tool( void* user_data );
-void handle_reload_settings(void*);
-void focus_here(void*);
void dump_select_mgr(void*);
-void dump_volume_mgr(void*);
+
void dump_inventory(void*);
-void edit_ui(void*);
void toggle_visibility(void*);
BOOL get_visibility(void*);
@@ -441,52 +271,30 @@ BOOL get_visibility(void*);
void request_friendship(const LLUUID& agent_id);
// Tools menu
-void handle_force_unlock(void*);
void handle_selected_texture_info(void*);
-void handle_dump_image_list(void*);
-void handle_crash(void*);
void handle_dump_followcam(void*);
void handle_viewer_enable_message_log(void*);
void handle_viewer_disable_message_log(void*);
-void handle_send_postcard(void*);
-void handle_gestures_old(void*);
-void handle_focus(void *);
+
BOOL enable_buy_land(void*);
-void handle_move(void*);
-void handle_show_inventory(void*);
-void handle_activate(void*);
-BOOL enable_activate(void*);
// Help menu
-void handle_buy_currency(void*);
void handle_test_male(void *);
void handle_test_female(void *);
void handle_toggle_pg(void*);
void handle_dump_attachments(void *);
-void handle_show_overlay_title(void*);
void handle_dump_avatar_local_textures(void*);
void handle_debug_avatar_textures(void*);
void handle_grab_texture(void*);
BOOL enable_grab_texture(void*);
void handle_dump_region_object_cache(void*);
-BOOL menu_ui_enabled(void *user_data);
-BOOL menu_check_control( void* user_data);
-void menu_toggle_variable( void* user_data );
-BOOL menu_check_variable( void* user_data);
-BOOL enable_land_selected( void* );
-BOOL enable_more_than_one_selected(void* );
-BOOL enable_selection_you_own_all(void*);
-BOOL enable_selection_you_own_one(void*);
BOOL enable_save_into_inventory(void*);
BOOL enable_save_into_task_inventory(void*);
-BOOL enable_not_thirdperson(void*);
-// BOOL enable_export_selected(void *);
-BOOL enable_have_card(void*);
-BOOL enable_detach(void*);
-BOOL enable_region_owner(void*);
+
+BOOL enable_detach(const LLSD& = LLSD());
void menu_toggle_attached_lights(void* user_data);
void menu_toggle_attached_particles(void* user_data);
@@ -500,6 +308,8 @@ public:
static LLMenuParcelObserver* gMenuParcelObserver = NULL;
+static LLUIListener sUIListener;
+
LLMenuParcelObserver::LLMenuParcelObserver()
{
LLViewerParcelMgr::getInstance()->addObserver(this);
@@ -520,27 +330,6 @@ void LLMenuParcelObserver::changed()
}
-//-----------------------------------------------------------------------------
-// Menu Construction
-//-----------------------------------------------------------------------------
-
-// code required to calculate anything about the menus
-void pre_init_menus()
-{
- // static information
- LLColor4 color;
- color = gColors.getColor( "MenuDefaultBgColor" );
- LLMenuGL::setDefaultBackgroundColor( color );
- color = gColors.getColor( "MenuItemEnabledColor" );
- LLMenuItemGL::setEnabledColor( color );
- color = gColors.getColor( "MenuItemDisabledColor" );
- LLMenuItemGL::setDisabledColor( color );
- color = gColors.getColor( "MenuItemHighlightBgColor" );
- LLMenuItemGL::setHighlightBGColor( color );
- color = gColors.getColor( "MenuItemHighlightFgColor" );
- LLMenuItemGL::setHighlightFGColor( color );
-}
-
void initialize_menus();
//-----------------------------------------------------------------------------
@@ -559,29 +348,19 @@ void set_underclothes_menu_options()
{
if (gMenuHolder && gAgent.isTeen())
{
- gMenuHolder->getChild<LLView>("Self Underpants", TRUE)->setVisible(FALSE);
- gMenuHolder->getChild<LLView>("Self Undershirt", TRUE)->setVisible(FALSE);
+ gMenuHolder->getChild<LLView>("Self Underpants")->setVisible(FALSE);
+ gMenuHolder->getChild<LLView>("Self Undershirt")->setVisible(FALSE);
}
if (gMenuBarView && gAgent.isTeen())
{
- gMenuBarView->getChild<LLView>("Menu Underpants", TRUE)->setVisible(FALSE);
- gMenuBarView->getChild<LLView>("Menu Undershirt", TRUE)->setVisible(FALSE);
+ gMenuBarView->getChild<LLView>("Menu Underpants")->setVisible(FALSE);
+ gMenuBarView->getChild<LLView>("Menu Undershirt")->setVisible(FALSE);
}
}
void init_menus()
{
S32 top = gViewerWindow->getRootView()->getRect().getHeight();
- S32 width = gViewerWindow->getRootView()->getRect().getWidth();
-
- //
- // Main menu bar
- //
- gMenuHolder = new LLViewerMenuHolderGL();
- gMenuHolder->setRect(LLRect(0, top, width, 0));
- gMenuHolder->setFollowsAll();
-
- LLMenuGL::sMenuContainer = gMenuHolder;
// Initialize actions
initialize_menus();
@@ -592,72 +371,77 @@ void init_menus()
/// The popup menu is now populated by the show_context_menu()
/// method.
- gPopupMenuView = new LLMenuGL( "Popup" );
- gPopupMenuView->setVisible( FALSE );
+ LLMenuGL::Params menu_params;
+ menu_params.name = "Popup";
+ menu_params.visible = false;
+ gPopupMenuView = LLUICtrlFactory::create<LLMenuGL>(menu_params);
gMenuHolder->addChild( gPopupMenuView );
///
- /// Pie menus
+ /// Context menus
///
- gPieSelf = LLUICtrlFactory::getInstance()->buildPieMenu("menu_pie_self.xml", gMenuHolder);
-
- // TomY TODO: what shall we do about these?
- gDetachScreenPieMenu = gMenuHolder->getChild<LLPieMenu>("Object Detach HUD", true);
- gDetachPieMenu = gMenuHolder->getChild<LLPieMenu>("Object Detach", true);
+ const widget_registry_t& registry =
+ LLViewerMenuHolderGL::child_registry_t::instance();
+ gMenuAvatarSelf = LLUICtrlFactory::createFromFile<LLContextMenu>(
+ "menu_avatar_self.xml", gMenuHolder, registry);
+ gMenuAvatarOther = LLUICtrlFactory::createFromFile<LLContextMenu>(
+ "menu_avatar_other.xml", gMenuHolder, registry);
- gPieAvatar = LLUICtrlFactory::getInstance()->buildPieMenu("menu_pie_avatar.xml", gMenuHolder);
+ gDetachScreenPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Detach HUD", true);
+ gDetachPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Detach", true);
- gPieObject = LLUICtrlFactory::getInstance()->buildPieMenu("menu_pie_object.xml", gMenuHolder);
+ gMenuObject = LLUICtrlFactory::createFromFile<LLContextMenu>(
+ "menu_object.xml", gMenuHolder, registry);
- gAttachScreenPieMenu = gMenuHolder->getChild<LLPieMenu>("Object Attach HUD");
- gAttachPieMenu = gMenuHolder->getChild<LLPieMenu>("Object Attach");
- gPieRate = gMenuHolder->getChild<LLPieMenu>("Rate Menu");
+ gAttachScreenPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Attach HUD");
+ gAttachPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Attach");
- gPieAttachment = LLUICtrlFactory::getInstance()->buildPieMenu("menu_pie_attachment.xml", gMenuHolder);
+ gMenuAttachmentSelf = LLUICtrlFactory::createFromFile<LLContextMenu>(
+ "menu_attachment_self.xml", gMenuHolder, registry);
+ gMenuAttachmentOther = LLUICtrlFactory::createFromFile<LLContextMenu>(
+ "menu_attachment_other.xml", gMenuHolder, registry);
- gPieLand = LLUICtrlFactory::getInstance()->buildPieMenu("menu_pie_land.xml", gMenuHolder);
+ gMenuLand = LLUICtrlFactory::createFromFile<LLContextMenu>(
+ "menu_land.xml", gMenuHolder, registry);
///
/// set up the colors
///
LLColor4 color;
- LLColor4 pie_color = gColors.getColor("PieMenuBgColor");
- gPieSelf->setBackgroundColor( pie_color );
- gPieAvatar->setBackgroundColor( pie_color );
- gPieObject->setBackgroundColor( pie_color );
- gPieAttachment->setBackgroundColor( pie_color );
- gPieLand->setBackgroundColor( pie_color );
+ LLColor4 context_menu_color = LLUIColorTable::instance().getColor("MenuPopupBgColor");
+
+ gMenuAvatarSelf->setBackgroundColor( context_menu_color );
+ gMenuAvatarOther->setBackgroundColor( context_menu_color );
+ gMenuObject->setBackgroundColor( context_menu_color );
+ gMenuAttachmentSelf->setBackgroundColor( context_menu_color );
+ gMenuAttachmentOther->setBackgroundColor( context_menu_color );
+
+ gMenuLand->setBackgroundColor( context_menu_color );
- color = gColors.getColor( "MenuPopupBgColor" );
+ color = LLUIColorTable::instance().getColor( "MenuPopupBgColor" );
gPopupMenuView->setBackgroundColor( color );
// If we are not in production, use a different color to make it apparent.
if (LLViewerLogin::getInstance()->isInProductionGrid())
{
- color = gColors.getColor( "MenuBarBgColor" );
+ color = LLUIColorTable::instance().getColor( "MenuBarBgColor" );
}
else
{
- color = gColors.getColor( "MenuNonProductionBgColor" );
+ color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" );
}
- gMenuBarView = (LLMenuBarGL*)LLUICtrlFactory::getInstance()->buildMenu("menu_viewer.xml", gMenuHolder);
+ gMenuBarView = LLUICtrlFactory::getInstance()->createFromFile<LLMenuBarGL>("menu_viewer.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
gMenuBarView->setRect(LLRect(0, top, 0, top - MENU_BAR_HEIGHT));
gMenuBarView->setBackgroundColor( color );
- // gMenuBarView->setItemVisible("Tools", FALSE);
- gMenuBarView->arrange();
-
gMenuHolder->addChild(gMenuBarView);
-
- // menu holder appears on top of menu bar so you can see the menu title
- // flash when an item is triggered (the flash occurs in the holder)
- gViewerWindow->getRootView()->addChild(gMenuHolder);
-
+
gViewerWindow->setMenuBackgroundColor(false,
LLViewerLogin::getInstance()->isInProductionGrid());
// Assume L$10 for now, the server will tell us the real cost at login
+ // *TODO:Also fix cost in llfolderview.cpp for Inventory menus
const std::string upload_cost("10");
gMenuHolder->childSetLabelArg("Upload Image", "[COST]", upload_cost);
gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", upload_cost);
@@ -666,820 +450,1829 @@ void init_menus()
gAFKMenu = gMenuBarView->getChild<LLMenuItemCallGL>("Set Away", TRUE);
gBusyMenu = gMenuBarView->getChild<LLMenuItemCallGL>("Set Busy", TRUE);
- gAttachSubMenu = gMenuBarView->getChildMenuByName("Attach Object", TRUE);
- gDetachSubMenu = gMenuBarView->getChildMenuByName("Detach Object", TRUE);
-
- // TomY TODO convert these two
- LLMenuGL*menu;
-
- menu = new LLMenuGL(CLIENT_MENU_NAME);
- init_client_menu(menu);
- gMenuBarView->appendMenu( menu );
- menu->updateParent(LLMenuGL::sMenuContainer);
+ gAttachSubMenu = gMenuBarView->findChildMenuByName("Attach Object", TRUE);
+ gDetachSubMenu = gMenuBarView->findChildMenuByName("Detach Object", TRUE);
- menu = new LLMenuGL(SERVER_MENU_NAME);
- init_server_menu(menu);
- gMenuBarView->appendMenu( menu );
- menu->updateParent(LLMenuGL::sMenuContainer);
+#if !MEM_TRACK_MEM
+ // Don't display the Memory console menu if the feature is turned off
+ LLMenuItemCheckGL *memoryMenu = gMenuBarView->getChild<LLMenuItemCheckGL>("Memory", TRUE);
+ if (memoryMenu)
+ {
+ memoryMenu->setVisible(FALSE);
+ }
+#endif
gMenuBarView->createJumpKeys();
// Let land based option enable when parcel changes
gMenuParcelObserver = new LLMenuParcelObserver();
- //
- // Debug menu visiblity
- //
- show_debug_menus();
-
- gLoginMenuBarView = (LLMenuBarGL*)LLUICtrlFactory::getInstance()->buildMenu("menu_login.xml", gMenuHolder);
+ gLoginMenuBarView = LLUICtrlFactory::getInstance()->createFromFile<LLMenuBarGL>("menu_login.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ gLoginMenuBarView->arrangeAndClear();
LLRect menuBarRect = gLoginMenuBarView->getRect();
gLoginMenuBarView->setRect(LLRect(menuBarRect.mLeft, menuBarRect.mTop, gViewerWindow->getRootView()->getRect().getWidth() - menuBarRect.mLeft, menuBarRect.mBottom));
-
gLoginMenuBarView->setBackgroundColor( color );
-
gMenuHolder->addChild(gLoginMenuBarView);
+ // tooltips are on top of EVERYTHING, including menus
+ gViewerWindow->getRootView()->sendChildToFront(gToolTipView);
}
+///////////////////
+// SHOW CONSOLES //
+///////////////////
-void init_client_menu(LLMenuGL* menu)
+class LLAdvancedToggleConsole : public view_listener_t
{
- LLMenuGL* sub_menu = NULL;
-
- //menu->append(new LLMenuItemCallGL("Permissions Control", &show_permissions_control));
- // this is now in the view menu so we don't need it here!
-
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string console_type = userdata.asString();
+ if ("texture" == console_type)
+ {
+ toggle_visibility( (void*)gTextureView );
+ }
+ else if ("debug" == console_type)
+ {
+ toggle_visibility( (void*)static_cast<LLUICtrl*>(gDebugView->mDebugConsolep));
+ }
+ else if (gTextureSizeView && "texture size" == console_type)
+ {
+ toggle_visibility( (void*)gTextureSizeView );
+ }
+ else if (gTextureCategoryView && "texture category" == console_type)
+ {
+ toggle_visibility( (void*)gTextureCategoryView );
+ }
+ else if ("fast timers" == console_type)
+ {
+ toggle_visibility( (void*)gDebugView->mFastTimerView );
+ }
+#if MEM_TRACK_MEM
+ else if ("memory view" == console_type)
+ {
+ toggle_visibility( (void*)gDebugView->mMemoryView );
+ }
+#endif
+ return true;
+ }
+};
+class LLAdvancedCheckConsole : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
{
- // *TODO: Translate
- LLMenuGL* sub = new LLMenuGL("Consoles");
- menu->appendMenu(sub);
- sub->append(new LLMenuItemCheckGL("Frame Console",
- &toggle_visibility,
- NULL,
- &get_visibility,
- (void*)gDebugView->mFrameStatView,
- '2', MASK_CONTROL|MASK_SHIFT ) );
- sub->append(new LLMenuItemCheckGL("Texture Console",
- &toggle_visibility,
- NULL,
- &get_visibility,
- (void*)gTextureView,
- '3', MASK_CONTROL|MASK_SHIFT ) );
- LLView* debugview = gDebugView->mDebugConsolep;
- sub->append(new LLMenuItemCheckGL("Debug Console",
- &toggle_visibility,
- NULL,
- &get_visibility,
- debugview,
- '4', MASK_CONTROL|MASK_SHIFT ) );
-
- sub->append(new LLMenuItemCheckGL("Fast Timers",
- &toggle_visibility,
- NULL,
- &get_visibility,
- (void*)gDebugView->mFastTimerView,
- '9', MASK_CONTROL|MASK_SHIFT ) );
+ std::string console_type = userdata.asString();
+ bool new_value = false;
+ if ("texture" == console_type)
+ {
+ new_value = get_visibility( (void*)gTextureView );
+ }
+ else if ("debug" == console_type)
+ {
+ new_value = get_visibility( (void*)((LLView*)gDebugView->mDebugConsolep) );
+ }
+ else if (gTextureSizeView && "texture size" == console_type)
+ {
+ new_value = get_visibility( (void*)gTextureSizeView );
+ }
+ else if (gTextureCategoryView && "texture category" == console_type)
+ {
+ new_value = get_visibility( (void*)gTextureCategoryView );
+ }
+ else if ("fast timers" == console_type)
+ {
+ new_value = get_visibility( (void*)gDebugView->mFastTimerView );
+ }
#if MEM_TRACK_MEM
- sub->append(new LLMenuItemCheckGL("Memory",
- &toggle_visibility,
- NULL,
- &get_visibility,
- (void*)gDebugView->mMemoryView,
- '0', MASK_CONTROL|MASK_SHIFT ) );
+ else if ("memory view" == console_type)
+ {
+ new_value = get_visibility( (void*)gDebugView->mMemoryView );
+ }
#endif
-
- sub->appendSeparator();
-
- // Debugging view for unified notifications
- sub->append(new LLMenuItemCallGL("Notifications Console...",
- &handle_show_notifications_console, NULL, NULL, '5', MASK_CONTROL|MASK_SHIFT ));
-
- sub->appendSeparator();
+ return new_value;
+ }
+};
+
+
+//////////////////////////
+// DUMP INFO TO CONSOLE //
+//////////////////////////
+
+
+class LLAdvancedDumpInfoToConsole : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string info_type = userdata.asString();
+ if ("region" == info_type)
+ {
+ handle_region_dump_settings(NULL);
+ }
+ else if ("group" == info_type)
+ {
+ handle_dump_group_info(NULL);
+ }
+ else if ("capabilities" == info_type)
+ {
+ handle_dump_capabilities_info(NULL);
+ }
+ return true;
+ }
+};
+
+
+//////////////
+// HUD INFO //
+//////////////
+
+
+class LLAdvancedToggleHUDInfo : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string info_type = userdata.asString();
+
+ if ("camera" == info_type)
+ {
+ gDisplayCameraPos = !(gDisplayCameraPos);
+ }
+ else if ("wind" == info_type)
+ {
+ gDisplayWindInfo = !(gDisplayWindInfo);
+ }
+ else if ("fov" == info_type)
+ {
+ gDisplayFOV = !(gDisplayFOV);
+ }
+ return true;
+ }
+};
- sub->append(new LLMenuItemCallGL("Region Info to Debug Console",
- &handle_region_dump_settings, NULL));
- sub->append(new LLMenuItemCallGL("Group Info to Debug Console",
- &handle_dump_group_info, NULL, NULL));
- sub->append(new LLMenuItemCallGL("Capabilities Info to Debug Console",
- &handle_dump_capabilities_info, NULL, NULL));
- sub->createJumpKeys();
+class LLAdvancedCheckHUDInfo : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string info_type = userdata.asString();
+ bool new_value = false;
+ if ("camera" == info_type)
+ {
+ new_value = gDisplayCameraPos;
+ }
+ else if ("wind" == info_type)
+ {
+ new_value = gDisplayWindInfo;
+ }
+ else if ("fov" == info_type)
+ {
+ new_value = gDisplayFOV;
+ }
+ return new_value;
}
+};
+
+
+//////////////
+// FLYING //
+//////////////
+
+class LLAdvancedAgentFlyingInfo : public view_listener_t
+{
+ bool handleEvent(const LLSD&)
+ {
+ return gAgent.getFlying();
+ }
+};
+
+
+///////////////////////
+// CLEAR GROUP CACHE //
+///////////////////////
+
+class LLAdvancedClearGroupCache : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLGroupMgr::debugClearAllGroups(NULL);
+ return true;
+ }
+};
+
+
+
+
+/////////////////
+// RENDER TYPE //
+/////////////////
+U32 render_type_from_string(std::string render_type)
+{
+ if ("simple" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_SIMPLE;
+ }
+ else if ("alpha" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_ALPHA;
+ }
+ else if ("tree" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_TREE;
+ }
+ else if ("character" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_AVATAR;
+ }
+ else if ("surfacePath" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_TERRAIN;
+ }
+ else if ("sky" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_SKY;
+ }
+ else if ("water" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_WATER;
+ }
+ else if ("ground" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_GROUND;
+ }
+ else if ("volume" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_VOLUME;
+ }
+ else if ("grass" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_GRASS;
+ }
+ else if ("clouds" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_CLOUDS;
+ }
+ else if ("particles" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_PARTICLES;
+ }
+ else if ("bump" == render_type)
+ {
+ return LLPipeline::RENDER_TYPE_BUMP;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+class LLAdvancedToggleRenderType : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ U32 render_type = render_type_from_string( userdata.asString() );
+ if ( render_type != 0 )
+ {
+ LLPipeline::toggleRenderTypeControl( (void*)render_type );
+ }
+ return true;
+ }
+};
+
+
+class LLAdvancedCheckRenderType : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ U32 render_type = render_type_from_string( userdata.asString() );
+ bool new_value = false;
+
+ if ( render_type != 0 )
+ {
+ new_value = LLPipeline::hasRenderTypeControl( (void*)render_type );
+ }
+
+ return new_value;
+ }
+};
+
+
+/////////////
+// FEATURE //
+/////////////
+U32 feature_from_string(std::string feature)
+{
+ if ("ui" == feature)
+ {
+ return LLPipeline::RENDER_DEBUG_FEATURE_UI;
+ }
+ else if ("selected" == feature)
+ {
+ return LLPipeline::RENDER_DEBUG_FEATURE_SELECTED;
+ }
+ else if ("highlighted" == feature)
+ {
+ return LLPipeline::RENDER_DEBUG_FEATURE_HIGHLIGHTED;
+ }
+ else if ("dynamic textures" == feature)
+ {
+ return LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES;
+ }
+ else if ("foot shadows" == feature)
+ {
+ return LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS;
+ }
+ else if ("fog" == feature)
+ {
+ return LLPipeline::RENDER_DEBUG_FEATURE_FOG;
+ }
+ else if ("fr info" == feature)
+ {
+ return LLPipeline::RENDER_DEBUG_FEATURE_FR_INFO;
+ }
+ else if ("flexible" == feature)
+ {
+ return LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE;
+ }
+ else
+ {
+ return 0;
+ }
+};
+
+
+class LLAdvancedToggleFeature : public view_listener_t{
+ bool handleEvent(const LLSD& userdata)
+ {
+ U32 feature = feature_from_string( userdata.asString() );
+ if ( feature != 0 )
+ {
+ LLPipeline::toggleRenderDebugFeature( (void*)feature );
+ }
+ return true;
+ }
+};
+
+class LLAdvancedCheckFeature : public view_listener_t
+{bool handleEvent(const LLSD& userdata)
+{
+ U32 feature = feature_from_string( userdata.asString() );
+ bool new_value = false;
+
+ if ( feature != 0 )
+ {
+ new_value = LLPipeline::toggleRenderDebugFeatureControl( (void*)feature );
+ }
+
+ return new_value;
+}
+};
+
+
+//////////////////
+// INFO DISPLAY //
+//////////////////
+U32 info_display_from_string(std::string info_display)
+{
+ if ("verify" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_VERIFY;
+ }
+ else if ("bboxes" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_BBOXES;
+ }
+ else if ("points" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_POINTS;
+ }
+ else if ("octree" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_OCTREE;
+ }
+ else if ("shadow frusta" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA;
+ }
+ else if ("occlusion" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_OCCLUSION;
+ }
+ else if ("render batches" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_BATCH_SIZE;
+ }
+ else if ("texture anim" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_TEXTURE_ANIM;
+ }
+ else if ("texture priority" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY;
+ }
+ else if ("shame" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_SHAME;
+ }
+ else if ("texture area" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_TEXTURE_AREA;
+ }
+ else if ("face area" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_FACE_AREA;
+ }
+ else if ("lights" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_LIGHTS;
+ }
+ else if ("particles" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_PARTICLES;
+ }
+ else if ("composition" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_COMPOSITION;
+ }
+ else if ("glow" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_GLOW;
+ }
+ else if ("collision skeleton" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_AVATAR_VOLUME;
+ }
+ else if ("raycast" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_RAYCAST;
+ }
+ else if ("agent target" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_AGENT_TARGET;
+ }
+ else
+ {
+ return 0;
+ }
+};
+
+class LLAdvancedToggleInfoDisplay : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ U32 info_display = info_display_from_string( userdata.asString() );
+
+ if ( info_display != 0 )
+ {
+ LLPipeline::toggleRenderDebug( (void*)info_display );
+ }
+
+ return true;
+ }
+};
+
+
+class LLAdvancedCheckInfoDisplay : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ U32 info_display = info_display_from_string( userdata.asString() );
+ bool new_value = false;
+
+ if ( info_display != 0 )
+ {
+ new_value = LLPipeline::toggleRenderDebugControl( (void*)info_display );
+ }
+
+ return new_value;
+ }
+};
+
+
+///////////////////////////
+//// RANDOMIZE FRAMERATE //
+///////////////////////////
+
+
+class LLAdvancedToggleRandomizeFramerate : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ gRandomizeFramerate = !(gRandomizeFramerate);
+ return true;
+ }
+};
+
+class LLAdvancedCheckRandomizeFramerate : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = gRandomizeFramerate;
+ return new_value;
+ }
+};
+
+void run_vectorize_perf_test(void *)
+{
+ gSavedSettings.setBOOL("VectorizePerfTest", TRUE);
+}
+
+
+////////////////////////////////
+// RUN Vectorized Perform Test//
+////////////////////////////////
+
+
+class LLAdvancedVectorizePerfTest : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ run_vectorize_perf_test(NULL);
+ return true;
+ }
+};
+
+///////////////////////////
+//// PERIODIC SLOW FRAME //
+///////////////////////////
+
+
+class LLAdvancedTogglePeriodicSlowFrame : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ gPeriodicSlowFrame = !(gPeriodicSlowFrame);
+ return true;
+ }
+};
+
+class LLAdvancedCheckPeriodicSlowFrame : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = gPeriodicSlowFrame;
+ return new_value;
+ }
+};
+
+
+
+////////////////
+// FRAME TEST //
+////////////////
+
+
+class LLAdvancedToggleFrameTest : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLPipeline::sRenderFrameTest = !(LLPipeline::sRenderFrameTest);
+ return true;
+ }
+};
+
+class LLAdvancedCheckFrameTest : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLPipeline::sRenderFrameTest;
+ return new_value;
+ }
+};
+
+
+///////////////////////////
+// SELECTED TEXTURE INFO //
+///////////////////////////
+
+
+class LLAdvancedSelectedTextureInfo : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_selected_texture_info(NULL);
+ return true;
+ }
+};
+
+//////////////////////
+// TOGGLE WIREFRAME //
+//////////////////////
+
+class LLAdvancedToggleWireframe : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ gUseWireframe = !(gUseWireframe);
+ return true;
+ }
+};
+
+class LLAdvancedCheckWireframe : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = gUseWireframe;
+ return new_value;
+ }
+};
- // neither of these works particularly well at the moment
- /*menu->append(new LLMenuItemCallGL( "Reload UI XML", &reload_ui,
- NULL, NULL) );*/
- /*menu->append(new LLMenuItemCallGL("Reload settings/colors",
- &handle_reload_settings, NULL, NULL));*/
- menu->append(new LLMenuItemCallGL("Reload personal setting overrides",
- &reload_personal_settings_overrides, NULL, NULL, KEY_F12, MASK_CONTROL|MASK_SHIFT));
-
- sub_menu = new LLMenuGL("HUD Info");
- {
- sub_menu->append(new LLMenuItemCheckGL("Velocity",
- &toggle_visibility,
- NULL,
- &get_visibility,
- (void*)gVelocityBar));
-
- sub_menu->append(new LLMenuItemToggleGL("Camera", &gDisplayCameraPos ) );
- sub_menu->append(new LLMenuItemToggleGL("Wind", &gDisplayWindInfo) );
- sub_menu->append(new LLMenuItemToggleGL("FOV", &gDisplayFOV ) );
- sub_menu->createJumpKeys();
- }
- menu->appendMenu(sub_menu);
-
- menu->appendSeparator();
-
- menu->append(new LLMenuItemCheckGL( "High-res Snapshot",
- &menu_toggle_control,
- NULL,
- &menu_check_control,
- (void*)"HighResSnapshot"));
-
- menu->append(new LLMenuItemCheckGL( "Quiet Snapshots to Disk",
- &menu_toggle_control,
- NULL,
- &menu_check_control,
- (void*)"QuietSnapshotsToDisk"));
-
- menu->append(new LLMenuItemCheckGL("Show Mouselook Crosshairs",
- &menu_toggle_control,
- NULL,
- &menu_check_control,
- (void*)"ShowCrosshairs"));
-
- menu->append(new LLMenuItemCheckGL("Debug Permissions",
- &menu_toggle_control,
- NULL,
- &menu_check_control,
- (void*)"DebugPermissions"));
+//////////////////////
+// TEXTURE ATLAS //
+//////////////////////
+
+class LLAdvancedToggleTextureAtlas : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLViewerTexture::sUseTextureAtlas = !LLViewerTexture::sUseTextureAtlas;
+ gSavedSettings.setBOOL("EnableTextureAtlas", LLViewerTexture::sUseTextureAtlas) ;
+ return true;
+ }
+};
+
+class LLAdvancedCheckTextureAtlas : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLViewerTexture::sUseTextureAtlas; // <-- make this using LLCacheControl
+ return new_value;
+ }
+};
+
+//////////////////////////
+// DUMP SCRIPTED CAMERA //
+//////////////////////////
+class LLAdvancedDumpScriptedCamera : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_dump_followcam(NULL);
+ return true;
+}
+};
-#ifdef TOGGLE_HACKED_GODLIKE_VIEWER
- if (!LLViewerLogin::getInstance()->isInProductionGrid())
+
+//////////////////////////////
+// DUMP REGION OBJECT CACHE //
+//////////////////////////////
+
+
+class LLAdvancedDumpRegionObjectCache : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+{
+ handle_dump_region_object_cache(NULL);
+ return true;
+ }
+};
+
+class LLAdvancedBuyCurrencyTest : public view_listener_t
+ {
+ bool handleEvent(const LLSD& userdata)
{
- menu->append(new LLMenuItemCheckGL("Hacked Godmode",
- &handle_toggle_hacked_godmode,
- NULL,
- &check_toggle_hacked_godmode,
- (void*)"HackedGodmode"));
+ handle_buy_currency_test(NULL);
+ return true;
}
-#endif
+};
- menu->append(new LLMenuItemCallGL("Clear Group Cache",
- LLGroupMgr::debugClearAllGroups));
- menu->appendSeparator();
- sub_menu = new LLMenuGL("Rendering");
- init_debug_rendering_menu(sub_menu);
- menu->appendMenu(sub_menu);
+/////////////////////
+// DUMP SELECT MGR //
+/////////////////////
- sub_menu = new LLMenuGL("World");
- init_debug_world_menu(sub_menu);
- menu->appendMenu(sub_menu);
- sub_menu = new LLMenuGL("UI");
- init_debug_ui_menu(sub_menu);
- menu->appendMenu(sub_menu);
+class LLAdvancedDumpSelectMgr : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ dump_select_mgr(NULL);
+ return true;
+ }
+};
+
- sub_menu = new LLMenuGL("XUI");
- init_debug_xui_menu(sub_menu);
- menu->appendMenu(sub_menu);
- sub_menu = new LLMenuGL("Character");
- init_debug_avatar_menu(sub_menu);
- menu->appendMenu(sub_menu);
+////////////////////
+// DUMP INVENTORY //
+////////////////////
+
+class LLAdvancedDumpInventory : public view_listener_t
{
- LLMenuGL* sub = NULL;
- sub = new LLMenuGL("Network");
+ bool handleEvent(const LLSD& userdata)
+ {
+ dump_inventory(NULL);
+ return true;
+ }
+};
+
+
+
+////////////////////////////////
+// PRINT SELECTED OBJECT INFO //
+////////////////////////////////
+
+
+class LLAdvancedPrintSelectedObjectInfo : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ print_object_info(NULL);
+ return true;
+ }
+};
+
+
+
+//////////////////////
+// PRINT AGENT INFO //
+//////////////////////
+
+
+class LLAdvancedPrintAgentInfo : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ print_agent_nvpairs(NULL);
+ return true;
+ }
+};
+
+
+
+////////////////////////////////
+// PRINT TEXTURE MEMORY STATS //
+////////////////////////////////
+
+
+class LLAdvancedPrintTextureMemoryStats : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ output_statistics(NULL);
+ return true;
+ }
+};
+
+//////////////////
+// DEBUG CLICKS //
+//////////////////
+
+
+class LLAdvancedToggleDebugClicks : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ gDebugClicks = !(gDebugClicks);
+ return true;
+ }
+};
- sub->append(new LLMenuItemCallGL("Enable Message Log",
- &handle_viewer_enable_message_log, NULL));
- sub->append(new LLMenuItemCallGL("Disable Message Log",
- &handle_viewer_disable_message_log, NULL));
+class LLAdvancedCheckDebugClicks : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = gDebugClicks;
+ return new_value;
+ }
+};
- sub->appendSeparator();
- sub->append(new LLMenuItemCheckGL("Velocity Interpolate Objects",
- &velocity_interpolate,
- NULL,
- &menu_check_control,
- (void*)"VelocityInterpolate"));
- sub->append(new LLMenuItemCheckGL("Ping Interpolate Object Positions",
- &menu_toggle_control,
- NULL,
- &menu_check_control,
- (void*)"PingInterpolate"));
- sub->appendSeparator();
+/////////////////
+// DEBUG VIEWS //
+/////////////////
- sub->append(new LLMenuItemCallGL("Drop a Packet",
- &drop_packet, NULL, NULL,
- 'L', MASK_ALT | MASK_CONTROL));
- menu->appendMenu( sub );
- sub->createJumpKeys();
+class LLAdvancedToggleDebugViews : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLView::sDebugRects = !(LLView::sDebugRects);
+ return true;
}
+};
+
+class LLAdvancedCheckDebugViews : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
{
- LLMenuGL* sub = NULL;
- sub = new LLMenuGL("Recorder");
+ bool new_value = LLView::sDebugRects;
+ return new_value;
+ }
+};
+
- sub->append(new LLMenuItemCheckGL("Full Session Logging", &menu_toggle_control, NULL, &menu_check_control, (void*)"StatsSessionTrackFrameStats"));
- sub->append(new LLMenuItemCallGL("Start Logging", &LLFrameStats::startLogging, NULL));
- sub->append(new LLMenuItemCallGL("Stop Logging", &LLFrameStats::stopLogging, NULL));
- sub->append(new LLMenuItemCallGL("Log 10 Seconds", &LLFrameStats::timedLogging10, NULL));
- sub->append(new LLMenuItemCallGL("Log 30 Seconds", &LLFrameStats::timedLogging30, NULL));
- sub->append(new LLMenuItemCallGL("Log 60 Seconds", &LLFrameStats::timedLogging60, NULL));
- sub->appendSeparator();
- sub->append(new LLMenuItemCallGL("Start Playback", &LLAgentPilot::startPlayback, NULL));
- sub->append(new LLMenuItemCallGL("Stop Playback", &LLAgentPilot::stopPlayback, NULL));
- sub->append(new LLMenuItemToggleGL("Loop Playback", &LLAgentPilot::sLoop) );
- sub->append(new LLMenuItemCallGL("Start Record", &LLAgentPilot::startRecord, NULL));
- sub->append(new LLMenuItemCallGL("Stop Record", &LLAgentPilot::saveRecord, NULL));
+///////////////////////
+// XUI NAME TOOLTIPS //
+///////////////////////
- menu->appendMenu( sub );
- sub->createJumpKeys();
+
+class LLAdvancedToggleXUINameTooltips : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ toggle_show_xui_names(NULL);
+ return true;
+ }
+};
+
+class LLAdvancedCheckXUINameTooltips : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = check_show_xui_names(NULL);
+ return new_value;
}
+};
+
+
- menu->appendSeparator();
+////////////////////////
+// DEBUG MOUSE EVENTS //
+////////////////////////
- menu->append(new LLMenuItemToggleGL("Show Updates",
- &gShowObjectUpdates));
+
+class LLAdvancedToggleDebugMouseEvents : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLView::sDebugMouseHandling = !(LLView::sDebugMouseHandling);
+ return true;
+ }
+};
+
+class LLAdvancedCheckDebugMouseEvents : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLView::sDebugMouseHandling;
+ return new_value;
+ }
+};
+
+
+
+////////////////
+// DEBUG KEYS //
+////////////////
+
+
+class LLAdvancedToggleDebugKeys : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLView::sDebugKeys = !(LLView::sDebugKeys);
+ return true;
+ }
+};
- menu->appendSeparator();
+class LLAdvancedCheckDebugKeys : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLView::sDebugKeys;
+ return new_value;
+ }
+};
- menu->append(new LLMenuItemCallGL("Compress Images...",
- &handle_compress_image, NULL, NULL));
-
- menu->append(new LLMenuItemCheckGL("Limit Select Distance",
- &menu_toggle_control,
- NULL,
- &menu_check_control,
- (void*)"LimitSelectDistance"));
-
- menu->append(new LLMenuItemCheckGL("Disable Camera Constraints",
- &menu_toggle_control,
- NULL,
- &menu_check_control,
- (void*)"DisableCameraConstraints"));
-
- menu->append(new LLMenuItemCheckGL("Mouse Smoothing",
- &menu_toggle_control,
- NULL,
- &menu_check_control,
- (void*) "MouseSmooth"));
- menu->appendSeparator();
-
- menu->append(new LLMenuItemCheckGL( "Console Window",
- &menu_toggle_control,
- NULL,
- &menu_check_control,
- (void*)"ShowConsoleWindow"));
-
- if(gSavedSettings.getBOOL("QAMode"))
- {
- LLMenuGL* sub = NULL;
- sub = new LLMenuGL("Debugging");
-#if LL_WINDOWS
- sub->append(new LLMenuItemCallGL("Force Breakpoint", &force_error_breakpoint, NULL, NULL, 'B', MASK_CONTROL | MASK_ALT));
-#endif
- sub->append(new LLMenuItemCallGL("Force LLError And Crash", &force_error_llerror));
- sub->append(new LLMenuItemCallGL("Force Bad Memory Access", &force_error_bad_memory_access));
- sub->append(new LLMenuItemCallGL("Force Infinite Loop", &force_error_infinite_loop));
- sub->append(new LLMenuItemCallGL("Force Driver Crash", &force_error_driver_crash));
- sub->append(new LLMenuItemCallGL("Force Disconnect Viewer", &handle_disconnect_viewer));
- // *NOTE:Mani this isn't handled yet... sub->append(new LLMenuItemCallGL("Force Software Exception", &force_error_unhandled_exception));
- sub->createJumpKeys();
- menu->appendMenu(sub);
+
+
+///////////////////////
+// DEBUG WINDOW PROC //
+///////////////////////
+
+
+class LLAdvancedToggleDebugWindowProc : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ gDebugWindowProc = !(gDebugWindowProc);
+ return true;
}
+};
- menu->append(new LLMenuItemCheckGL( "Output Debug Minidump",
- &menu_toggle_control,
- NULL,
- &menu_check_control,
- (void*)"SaveMinidump"));
+class LLAdvancedCheckDebugWindowProc : public view_listener_t
+ {
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = gDebugWindowProc;
+ return new_value;
+ }
+};
- menu->append(new LLMenuItemCallGL("Debug Settings...", LLFloaterSettingsDebug::show, NULL, NULL));
- menu->append(new LLMenuItemCheckGL("View Admin Options", &handle_admin_override_toggle, NULL, &check_admin_override, NULL, 'V', MASK_CONTROL | MASK_ALT));
+// ------------------------------XUI MENU ---------------------------
- menu->append(new LLMenuItemCallGL("Request Admin Status",
- &handle_god_mode, NULL, NULL, 'G', MASK_ALT | MASK_CONTROL));
+//////////////////////
+// LOAD UI FROM XML //
+//////////////////////
- menu->append(new LLMenuItemCallGL("Leave Admin Status",
- &handle_leave_god_mode, NULL, NULL, 'G', MASK_ALT | MASK_SHIFT | MASK_CONTROL));
- menu->createJumpKeys();
+class LLAdvancedLoadUIFromXML : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_load_from_xml(NULL);
+ return true;
}
+};
-void init_debug_world_menu(LLMenuGL* menu)
+
+
+////////////////////
+// SAVE UI TO XML //
+////////////////////
+
+
+class LLAdvancedSaveUIToXML : public view_listener_t
{
-/* REMOVE mouse move sun from menu options
- menu->append(new LLMenuItemCheckGL("Mouse Moves Sun",
- &menu_toggle_control,
- NULL,
- &menu_check_control,
- (void*)"MouseSun",
- 'M', MASK_CONTROL|MASK_ALT));
-*/
- menu->append(new LLMenuItemCheckGL("Sim Sun Override",
- &menu_toggle_control,
- NULL,
- &menu_check_control,
- (void*)"SkyOverrideSimSunPosition"));
- menu->append(new LLMenuItemCallGL("Dump Scripted Camera",
- &handle_dump_followcam, NULL, NULL));
- menu->append(new LLMenuItemCheckGL("Fixed Weather",
- &menu_toggle_control,
- NULL,
- &menu_check_control,
- (void*)"FixedWeather"));
- menu->append(new LLMenuItemCallGL("Dump Region Object Cache",
- &handle_dump_region_object_cache, NULL, NULL));
- menu->createJumpKeys();
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_save_to_xml(NULL);
+ return true;
}
+};
-void handle_export_menus_to_xml(void*)
+class LLAdvancedSendTestIms : public view_listener_t
{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLIMModel::instance().testMessages();
+ return true;
+}
+};
- LLFilePicker& picker = LLFilePicker::instance();
- if(!picker.getSaveFile(LLFilePicker::FFSAVE_XML))
+
+///////////////
+// XUI NAMES //
+///////////////
+
+
+class LLAdvancedToggleXUINames : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
{
- llwarns << "No file" << llendl;
- return;
+ toggle_show_xui_names(NULL);
+ return true;
}
- std::string filename = picker.getFirstFile();
+};
+
+class LLAdvancedCheckXUINames : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = check_show_xui_names(NULL);
+ return new_value;
+ }
+};
+
+
+////////////////////////
+// GRAB BAKED TEXTURE //
+////////////////////////
- llofstream out(filename);
- LLXMLNodePtr node = gMenuBarView->getXML();
- node->writeToOstream(out);
- out.close();
+
+class LLAdvancedGrabBakedTexture : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string texture_type = userdata.asString();
+ if ("iris" == texture_type)
+ {
+ handle_grab_texture( (void*)TEX_EYES_BAKED );
+ }
+ else if ("head" == texture_type)
+ {
+ handle_grab_texture( (void*)TEX_HEAD_BAKED );
+ }
+ else if ("upper" == texture_type)
+ {
+ handle_grab_texture( (void*)TEX_UPPER_BAKED );
+ }
+ else if ("lower" == texture_type)
+ {
+ handle_grab_texture( (void*)TEX_SKIRT_BAKED );
+ }
+ else if ("skirt" == texture_type)
+ {
+ handle_grab_texture( (void*)TEX_SKIRT_BAKED );
+ }
+ else if ("hair" == texture_type)
+ {
+ handle_grab_texture( (void*)TEX_HAIR_BAKED );
}
-extern BOOL gDebugClicks;
-extern BOOL gDebugWindowProc;
-extern BOOL gDebugTextEditorTips;
-extern BOOL gDebugSelectMgr;
-
-void init_debug_ui_menu(LLMenuGL* menu)
-{
- menu->append(new LLMenuItemCheckGL("Rotate Mini-Map", menu_toggle_control, NULL, menu_check_control, (void*)"MiniMapRotate"));
- menu->append(new LLMenuItemCheckGL("Use default system color picker", menu_toggle_control, NULL, menu_check_control, (void*)"UseDefaultColorPicker"));
- menu->append(new LLMenuItemCheckGL("Show search panel in overlay bar", menu_toggle_control, NULL, menu_check_control, (void*)"ShowSearchBar"));
- menu->appendSeparator();
-
- menu->append(new LLMenuItemCallGL("Web Browser Test", &handle_web_browser_test));
- // commented out until work is complete: DEV-32268
- // menu->append(new LLMenuItemCallGL("Buy Currency Test", &handle_buy_currency_test));
- menu->append(new LLMenuItemCallGL("Editable UI", &edit_ui));
- menu->append(new LLMenuItemCallGL( "Dump SelectMgr", &dump_select_mgr));
- menu->append(new LLMenuItemCallGL( "Dump Inventory", &dump_inventory));
- menu->append(new LLMenuItemCallGL( "Dump Focus Holder", &handle_dump_focus, NULL, NULL, 'F', MASK_ALT | MASK_CONTROL));
- menu->append(new LLMenuItemCallGL( "Print Selected Object Info", &print_object_info, NULL, NULL, 'P', MASK_CONTROL|MASK_SHIFT ));
- menu->append(new LLMenuItemCallGL( "Print Agent Info", &print_agent_nvpairs, NULL, NULL, 'P', MASK_SHIFT ));
- menu->append(new LLMenuItemCallGL( "Memory Stats", &output_statistics, NULL, NULL, 'M', MASK_SHIFT | MASK_ALT | MASK_CONTROL));
- menu->append(new LLMenuItemCheckGL("Double-Click Auto-Pilot",
- menu_toggle_control, NULL, menu_check_control,
- (void*)"DoubleClickAutoPilot"));
- menu->appendSeparator();
-// menu->append(new LLMenuItemCallGL( "Print Packets Lost", &print_packets_lost, NULL, NULL, 'L', MASK_SHIFT ));
- menu->append(new LLMenuItemToggleGL("Debug SelectMgr", &gDebugSelectMgr));
- menu->append(new LLMenuItemToggleGL("Debug Clicks", &gDebugClicks));
- menu->append(new LLMenuItemToggleGL("Debug Views", &LLView::sDebugRects));
- menu->append(new LLMenuItemCheckGL("Show Name Tooltips", toggle_show_xui_names, NULL, check_show_xui_names, NULL));
- menu->append(new LLMenuItemToggleGL("Debug Mouse Events", &LLView::sDebugMouseHandling));
- menu->append(new LLMenuItemToggleGL("Debug Keys", &LLView::sDebugKeys));
- menu->append(new LLMenuItemToggleGL("Debug WindowProc", &gDebugWindowProc));
- menu->append(new LLMenuItemToggleGL("Debug Text Editor Tips", &gDebugTextEditorTips));
- menu->appendSeparator();
- menu->append(new LLMenuItemCheckGL("Show Time", menu_toggle_control, NULL, menu_check_control, (void*)"DebugShowTime"));
- menu->append(new LLMenuItemCheckGL("Show Render Info", menu_toggle_control, NULL, menu_check_control, (void*)"DebugShowRenderInfo"));
- menu->append(new LLMenuItemCheckGL("Show Matrices", menu_toggle_control, NULL, menu_check_control, (void*)"DebugShowRenderMatrices"));
- menu->append(new LLMenuItemCheckGL("Show Color Under Cursor", menu_toggle_control, NULL, menu_check_control, (void*)"DebugShowColor"));
+ return true;
+ }
+};
+
+class LLAdvancedEnableGrabBakedTexture : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+{
+ std::string texture_type = userdata.asString();
+ bool new_value = false;
+
+ if ("iris" == texture_type)
+ {
+ new_value = enable_grab_texture( (void*)TEX_EYES_BAKED );
+ }
+ else if ("head" == texture_type)
+ {
+ new_value = enable_grab_texture( (void*)TEX_HEAD_BAKED );
+ }
+ else if ("upper" == texture_type)
+ {
+ new_value = enable_grab_texture( (void*)TEX_UPPER_BAKED );
+ }
+ else if ("lower" == texture_type)
+ {
+ new_value = enable_grab_texture( (void*)TEX_LOWER_BAKED );
+ }
+ else if ("skirt" == texture_type)
+ {
+ new_value = enable_grab_texture( (void*)TEX_SKIRT_BAKED );
+ }
- menu->createJumpKeys();
+ return new_value;
}
+};
-void init_debug_xui_menu(LLMenuGL* menu)
+///////////////////////
+// APPEARANCE TO XML //
+///////////////////////
+
+
+class LLAdvancedAppearanceToXML : public view_listener_t
{
- menu->append(new LLMenuItemCallGL("Floater Test...", LLFloaterTest::show));
- menu->append(new LLMenuItemCallGL("Font Test...", LLFloaterFontTest::show));
- menu->append(new LLMenuItemCallGL("Export Menus to XML...", handle_export_menus_to_xml));
- menu->append(new LLMenuItemCallGL("Edit UI...", LLFloaterEditUI::show));
- menu->append(new LLMenuItemCallGL("Load from XML...", handle_load_from_xml));
- menu->append(new LLMenuItemCallGL("Save to XML...", handle_save_to_xml));
- menu->append(new LLMenuItemCheckGL("Show XUI Names", toggle_show_xui_names, NULL, check_show_xui_names, NULL));
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVOAvatar::dumpArchetypeXML(NULL);
+ return true;
+ }
+};
- //menu->append(new LLMenuItemCallGL("Buy Currency...", handle_buy_currency));
- menu->createJumpKeys();
-}
-void init_debug_rendering_menu(LLMenuGL* menu)
+
+///////////////////////////////
+// TOGGLE CHARACTER GEOMETRY //
+///////////////////////////////
+
+
+class LLAdvancedToggleCharacterGeometry : public view_listener_t
{
- LLMenuGL* sub_menu = NULL;
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_god_request_avatar_geometry(NULL);
+ return true;
+}
+};
- ///////////////////////////
- //
- // Debug menu for types/pools
- //
- sub_menu = new LLMenuGL("Types");
- menu->appendMenu(sub_menu);
-
- sub_menu->append(new LLMenuItemCheckGL("Simple",
- &LLPipeline::toggleRenderTypeControl, NULL,
- &LLPipeline::hasRenderTypeControl,
- (void*)LLPipeline::RENDER_TYPE_SIMPLE, '1', MASK_ALT|MASK_SHIFT));
- sub_menu->append(new LLMenuItemCheckGL("Alpha",
- &LLPipeline::toggleRenderTypeControl, NULL,
- &LLPipeline::hasRenderTypeControl,
- (void*)LLPipeline::RENDER_TYPE_ALPHA, '2', MASK_ALT|MASK_SHIFT));
- sub_menu->append(new LLMenuItemCheckGL("Tree",
- &LLPipeline::toggleRenderTypeControl, NULL,
- &LLPipeline::hasRenderTypeControl,
- (void*)LLPipeline::RENDER_TYPE_TREE, '3', MASK_ALT|MASK_SHIFT));
- sub_menu->append(new LLMenuItemCheckGL("Character",
- &LLPipeline::toggleRenderTypeControl, NULL,
- &LLPipeline::hasRenderTypeControl,
- (void*)LLPipeline::RENDER_TYPE_AVATAR, '4', MASK_ALT|MASK_SHIFT));
- sub_menu->append(new LLMenuItemCheckGL("SurfacePatch",
- &LLPipeline::toggleRenderTypeControl, NULL,
- &LLPipeline::hasRenderTypeControl,
- (void*)LLPipeline::RENDER_TYPE_TERRAIN, '5', MASK_ALT|MASK_SHIFT));
- sub_menu->append(new LLMenuItemCheckGL("Sky",
- &LLPipeline::toggleRenderTypeControl, NULL,
- &LLPipeline::hasRenderTypeControl,
- (void*)LLPipeline::RENDER_TYPE_SKY, '6', MASK_ALT|MASK_SHIFT));
- sub_menu->append(new LLMenuItemCheckGL("Water",
- &LLPipeline::toggleRenderTypeControl, NULL,
- &LLPipeline::hasRenderTypeControl,
- (void*)LLPipeline::RENDER_TYPE_WATER, '7', MASK_ALT|MASK_SHIFT));
- sub_menu->append(new LLMenuItemCheckGL("Ground",
- &LLPipeline::toggleRenderTypeControl, NULL,
- &LLPipeline::hasRenderTypeControl,
- (void*)LLPipeline::RENDER_TYPE_GROUND, '8', MASK_ALT|MASK_SHIFT));
- sub_menu->append(new LLMenuItemCheckGL("Volume",
- &LLPipeline::toggleRenderTypeControl, NULL,
- &LLPipeline::hasRenderTypeControl,
- (void*)LLPipeline::RENDER_TYPE_VOLUME, '9', MASK_ALT|MASK_SHIFT));
- sub_menu->append(new LLMenuItemCheckGL("Grass",
- &LLPipeline::toggleRenderTypeControl, NULL,
- &LLPipeline::hasRenderTypeControl,
- (void*)LLPipeline::RENDER_TYPE_GRASS, '0', MASK_ALT|MASK_SHIFT));
- sub_menu->append(new LLMenuItemCheckGL("Clouds",
- &LLPipeline::toggleRenderTypeControl, NULL,
- &LLPipeline::hasRenderTypeControl,
- (void*)LLPipeline::RENDER_TYPE_CLOUDS, '-', MASK_ALT|MASK_SHIFT));
- sub_menu->append(new LLMenuItemCheckGL("Particles",
- &LLPipeline::toggleRenderTypeControl, NULL,
- &LLPipeline::hasRenderTypeControl,
- (void*)LLPipeline::RENDER_TYPE_PARTICLES, '`', MASK_ALT|MASK_SHIFT));
- sub_menu->append(new LLMenuItemCheckGL("Bump",
- &LLPipeline::toggleRenderTypeControl, NULL,
- &LLPipeline::hasRenderTypeControl,
- (void*)LLPipeline::RENDER_TYPE_BUMP, '\\', MASK_ALT|MASK_SHIFT));
-
- sub_menu->createJumpKeys();
- sub_menu = new LLMenuGL("Features");
- menu->appendMenu(sub_menu);
- sub_menu->append(new LLMenuItemCheckGL("UI",
- &LLPipeline::toggleRenderDebugFeature, NULL,
- &LLPipeline::toggleRenderDebugFeatureControl,
- (void*)LLPipeline::RENDER_DEBUG_FEATURE_UI, KEY_F1, MASK_CONTROL|MASK_SHIFT));
- sub_menu->append(new LLMenuItemCheckGL("Selected",
- &LLPipeline::toggleRenderDebugFeature, NULL,
- &LLPipeline::toggleRenderDebugFeatureControl,
- (void*)LLPipeline::RENDER_DEBUG_FEATURE_SELECTED, KEY_F2, MASK_CONTROL|MASK_SHIFT));
- sub_menu->append(new LLMenuItemCheckGL("Highlighted",
- &LLPipeline::toggleRenderDebugFeature, NULL,
- &LLPipeline::toggleRenderDebugFeatureControl,
- (void*)LLPipeline::RENDER_DEBUG_FEATURE_HIGHLIGHTED, KEY_F3, MASK_CONTROL|MASK_SHIFT));
- sub_menu->append(new LLMenuItemCheckGL("Dynamic Textures",
- &LLPipeline::toggleRenderDebugFeature, NULL,
- &LLPipeline::toggleRenderDebugFeatureControl,
- (void*)LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES, KEY_F4, MASK_CONTROL|MASK_SHIFT));
- sub_menu->append(new LLMenuItemCheckGL( "Foot Shadows",
- &LLPipeline::toggleRenderDebugFeature, NULL,
- &LLPipeline::toggleRenderDebugFeatureControl,
- (void*)LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS, KEY_F5, MASK_CONTROL|MASK_SHIFT));
- sub_menu->append(new LLMenuItemCheckGL("Fog",
- &LLPipeline::toggleRenderDebugFeature, NULL,
- &LLPipeline::toggleRenderDebugFeatureControl,
- (void*)LLPipeline::RENDER_DEBUG_FEATURE_FOG, KEY_F6, MASK_CONTROL|MASK_SHIFT));
- sub_menu->append(new LLMenuItemCheckGL("Test FRInfo",
- &LLPipeline::toggleRenderDebugFeature, NULL,
- &LLPipeline::toggleRenderDebugFeatureControl,
- (void*)LLPipeline::RENDER_DEBUG_FEATURE_FR_INFO, KEY_F8, MASK_CONTROL|MASK_SHIFT));
- sub_menu->append(new LLMenuItemCheckGL( "Flexible Objects",
- &LLPipeline::toggleRenderDebugFeature, NULL,
- &LLPipeline::toggleRenderDebugFeatureControl,
- (void*)LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE, KEY_F9, MASK_CONTROL|MASK_SHIFT));
- sub_menu->createJumpKeys();
/////////////////////////////
- //
- // Debug menu for info displays
- //
- sub_menu = new LLMenuGL("Info Displays");
- menu->appendMenu(sub_menu);
-
- sub_menu->append(new LLMenuItemCheckGL("Verify", &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_VERIFY));
- sub_menu->append(new LLMenuItemCheckGL("BBoxes", &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_BBOXES));
- sub_menu->append(new LLMenuItemCheckGL("Points", &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_POINTS));
- sub_menu->append(new LLMenuItemCheckGL("Octree", &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_OCTREE));
- sub_menu->append(new LLMenuItemCheckGL("Shadow Frusta", &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA));
- sub_menu->append(new LLMenuItemCheckGL("Occlusion", &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_OCCLUSION));
- sub_menu->append(new LLMenuItemCheckGL("Render Batches", &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_BATCH_SIZE));
- sub_menu->append(new LLMenuItemCheckGL("Animated Textures", &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_TEXTURE_ANIM));
- sub_menu->append(new LLMenuItemCheckGL("Texture Priority", &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY));
- sub_menu->append(new LLMenuItemCheckGL("Avatar Rendering Cost", &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_SHAME));
- sub_menu->append(new LLMenuItemCheckGL("Texture Area (sqrt(A))",&LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_TEXTURE_AREA));
- sub_menu->append(new LLMenuItemCheckGL("Face Area (sqrt(A))",&LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_FACE_AREA));
- sub_menu->append(new LLMenuItemCheckGL("Lights", &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_LIGHTS));
- sub_menu->append(new LLMenuItemCheckGL("Particles", &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_PARTICLES));
- sub_menu->append(new LLMenuItemCheckGL("Composition", &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_COMPOSITION));
- sub_menu->append(new LLMenuItemCheckGL("Glow",&LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_GLOW));
- sub_menu->append(new LLMenuItemCheckGL("Raycasting", &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_RAYCAST));
- sub_menu->append(new LLMenuItemCheckGL("Sculpt", &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_SCULPTED));
+// TEST MALE / TEST FEMALE //
+/////////////////////////////
+
+class LLAdvancedTestMale : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_test_male(NULL);
+ return true;
+ }
+};
+
+
+class LLAdvancedTestFemale : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_test_female(NULL);
+ return true;
+ }
+};
+
+
+
+///////////////
+// TOGGLE PG //
+///////////////
+
+
+class LLAdvancedTogglePG : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_toggle_pg(NULL);
+ return true;
+ }
+};
+
+
+class LLAdvancedForceParamsToDefault : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLAgent::clearVisualParams(NULL);
+ return true;
+ }
+};
+
+
+
+//////////////////////////
+// RELOAD VERTEX SHADER //
+//////////////////////////
+
+
+class LLAdvancedReloadVertexShader : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ reload_vertex_shader(NULL);
+ return true;
+ }
+};
+
+
+
+////////////////////
+// ANIMATION INFO //
+////////////////////
+
+
+class LLAdvancedToggleAnimationInfo : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVOAvatar::sShowAnimationDebug = !(LLVOAvatar::sShowAnimationDebug);
+ return true;
+ }
+};
+
+class LLAdvancedCheckAnimationInfo : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLVOAvatar::sShowAnimationDebug;
+ return new_value;
+ }
+};
+
+
+//////////////////
+// SHOW LOOK AT //
+//////////////////
+
+
+class LLAdvancedToggleShowLookAt : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLHUDEffectLookAt::sDebugLookAt = !(LLHUDEffectLookAt::sDebugLookAt);
+ return true;
+ }
+};
+
+class LLAdvancedCheckShowLookAt : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLHUDEffectLookAt::sDebugLookAt;
+ return new_value;
+ }
+};
+
+
+
+///////////////////
+// SHOW POINT AT //
+///////////////////
+
+
+class LLAdvancedToggleShowPointAt : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLHUDEffectPointAt::sDebugPointAt = !(LLHUDEffectPointAt::sDebugPointAt);
+ return true;
+ }
+};
+
+class LLAdvancedCheckShowPointAt : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLHUDEffectPointAt::sDebugPointAt;
+ return new_value;
+ }
+};
+
+
+
+/////////////////////////
+// DEBUG JOINT UPDATES //
+/////////////////////////
+
+
+class LLAdvancedToggleDebugJointUpdates : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVOAvatar::sJointDebug = !(LLVOAvatar::sJointDebug);
+ return true;
+ }
+};
+
+class LLAdvancedCheckDebugJointUpdates : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLVOAvatar::sJointDebug;
+ return new_value;
+ }
+};
+
+
+
+/////////////////
+// DISABLE LOD //
+/////////////////
+
+
+class LLAdvancedToggleDisableLOD : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLViewerJoint::sDisableLOD = !(LLViewerJoint::sDisableLOD);
+ return true;
+ }
+};
- sub_menu->append(new LLMenuItemCallGL("Vectorize Perf Test", &run_vectorize_perf_test));
+class LLAdvancedCheckDisableLOD : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLViewerJoint::sDisableLOD;
+ return new_value;
+ }
+};
- sub_menu = new LLMenuGL("Render Tests");
- sub_menu->append(new LLMenuItemCheckGL("Camera Offset",
- &menu_toggle_control,
- NULL,
- &menu_check_control,
- (void*)"CameraOffset"));
- sub_menu->append(new LLMenuItemToggleGL("Randomize Framerate", &gRandomizeFramerate));
+/////////////////////////
+// DEBUG CHARACTER VIS //
+/////////////////////////
- sub_menu->append(new LLMenuItemToggleGL("Periodic Slow Frame", &gPeriodicSlowFrame));
- sub_menu->append(new LLMenuItemToggleGL("Frame Test", &LLPipeline::sRenderFrameTest));
+class LLAdvancedToggleDebugCharacterVis : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVOAvatar::sDebugInvisible = !(LLVOAvatar::sDebugInvisible);
+ return true;
+ }
+};
- sub_menu->createJumpKeys();
+class LLAdvancedCheckDebugCharacterVis : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLVOAvatar::sDebugInvisible;
+ return new_value;
+ }
+};
- menu->appendMenu( sub_menu );
- menu->appendSeparator();
- menu->append(new LLMenuItemCheckGL("Axes", menu_toggle_control, NULL, menu_check_control, (void*)"ShowAxes"));
-// menu->append(new LLMenuItemCheckGL("Cull Small Objects", toggle_cull_small, NULL, menu_check_control, (void*)"RenderCullBySize"));
+//////////////////////
+// DUMP ATTACHMENTS //
+//////////////////////
- menu->appendSeparator();
- menu->append(new LLMenuItemToggleGL("Hide Selected", &gHideSelectedObjects));
- menu->appendSeparator();
- menu->append(new LLMenuItemCheckGL("Tangent Basis", menu_toggle_control, NULL, menu_check_control, (void*)"ShowTangentBasis"));
- menu->append(new LLMenuItemCallGL("Selected Texture Info", handle_selected_texture_info, NULL, NULL, 'T', MASK_CONTROL|MASK_SHIFT|MASK_ALT));
- //menu->append(new LLMenuItemCallGL("Dump Image List", handle_dump_image_list, NULL, NULL, 'I', MASK_CONTROL|MASK_SHIFT));
- menu->append(new LLMenuItemToggleGL("Wireframe", &gUseWireframe,
- 'R', MASK_CONTROL|MASK_SHIFT));
+class LLAdvancedDumpAttachments : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_dump_attachments(NULL);
+ return true;
+ }
+};
- LLMenuItemCheckGL* item;
- item = new LLMenuItemCheckGL("Object-Object Occlusion", menu_toggle_control, NULL, menu_check_control, (void*)"UseOcclusion", 'O', MASK_CONTROL|MASK_SHIFT);
- item->setEnabled(gGLManager.mHasOcclusionQuery && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion"));
- menu->append(item);
- item = new LLMenuItemCheckGL("Debug GL", menu_toggle_control, NULL, menu_check_control, (void*)"RenderDebugGL");
- menu->append(item);
- item = new LLMenuItemCheckGL("Debug Pipeline", menu_toggle_control, NULL, menu_check_control, (void*)"RenderDebugPipeline");
- menu->append(item);
+/////////////////////
+// REBAKE TEXTURES //
+/////////////////////
- item = new LLMenuItemCheckGL("Fast Alpha", menu_toggle_control, NULL, menu_check_control, (void*)"RenderFastAlpha");
- menu->append(item);
- item = new LLMenuItemCheckGL("Animate Textures", menu_toggle_control, NULL, menu_check_control, (void*)"AnimateTextures");
- menu->append(item);
+class LLAdvancedRebakeTextures : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_rebake_textures(NULL);
+ return true;
+ }
+};
- item = new LLMenuItemCheckGL("Disable Textures", menu_toggle_variable, NULL, menu_check_variable, (void*)&LLViewerImage::sDontLoadVolumeTextures);
- menu->append(item);
+#if 1 //ndef LL_RELEASE_FOR_DOWNLOAD
+///////////////////////////
+// DEBUG AVATAR TEXTURES //
+///////////////////////////
+
+
+class LLAdvancedDebugAvatarTextures : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+ handle_debug_avatar_textures(NULL);
+#endif
+ return true;
+ }
+};
+
+////////////////////////////////
+// DUMP AVATAR LOCAL TEXTURES //
+////////////////////////////////
+
+
+class LLAdvancedDumpAvatarLocalTextures : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
#ifndef LL_RELEASE_FOR_DOWNLOAD
- item = new LLMenuItemCheckGL("HTTP Get Textures", menu_toggle_control, NULL, menu_check_control, (void*)"ImagePipelineUseHTTP");
- menu->append(item);
+ handle_dump_avatar_local_textures(NULL);
+#endif
+ return true;
+ }
+};
+
#endif
- item = new LLMenuItemCheckGL("Run Multiple Threads", menu_toggle_control, NULL, menu_check_control, (void*)"RunMultipleThreads");
- menu->append(item);
+/////////////////
+// MESSAGE LOG //
+/////////////////
+
+
+class LLAdvancedEnableMessageLog : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_viewer_enable_message_log(NULL);
+ return true;
+ }
+};
- item = new LLMenuItemCheckGL("Cheesy Beacon", menu_toggle_control, NULL, menu_check_control, (void*)"CheesyBeacon");
- menu->append(item);
+class LLAdvancedDisableMessageLog : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_viewer_disable_message_log(NULL);
+ return true;
+ }
+};
- item = new LLMenuItemCheckGL("Attached Lights", menu_toggle_attached_lights, NULL, menu_check_control, (void*)"RenderAttachedLights");
- menu->append(item);
+/////////////////
+// DROP PACKET //
+/////////////////
- item = new LLMenuItemCheckGL("Attached Particles", menu_toggle_attached_particles, NULL, menu_check_control, (void*)"RenderAttachedParticles");
- menu->append(item);
-#ifndef LL_RELEASE_FOR_DOWNLOAD
- menu->appendSeparator();
- menu->append(new LLMenuItemCallGL("Memory Leaking Simulation", LLFloaterMemLeak::show, NULL, NULL));
-#else
- if(gSavedSettings.getBOOL("QAMode"))
+class LLAdvancedDropPacket : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
{
- menu->appendSeparator();
- menu->append(new LLMenuItemCallGL("Memory Leaking Simulation", LLFloaterMemLeak::show, NULL, NULL));
+ gMessageSystem->mPacketRing.dropPackets(1);
+ return true;
}
-#endif
+};
+
+
+
+/////////////////
+// AGENT PILOT //
+/////////////////
+
+
+class LLAdvancedAgentPilot : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string command = userdata.asString();
+ if ("start playback" == command)
+ {
+ LLAgentPilot::startPlayback(NULL);
+ }
+ else if ("stop playback" == command)
+ {
+ LLAgentPilot::stopPlayback(NULL);
+ }
+ else if ("start record" == command)
+ {
+ LLAgentPilot::startRecord(NULL);
+ }
+ else if ("stop record" == command)
+ {
+ LLAgentPilot::saveRecord(NULL);
+ }
+
+ return true;
+ }
+};
+
+
+
+//////////////////////
+// AGENT PILOT LOOP //
+//////////////////////
+
+
+class LLAdvancedToggleAgentPilotLoop : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLAgentPilot::sLoop = !(LLAgentPilot::sLoop);
+ return true;
+ }
+};
+
+class LLAdvancedCheckAgentPilotLoop : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLAgentPilot::sLoop;
+ return new_value;
+ }
+};
+
+
+/////////////////////////
+// SHOW OBJECT UPDATES //
+/////////////////////////
+
+
+class LLAdvancedToggleShowObjectUpdates : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ gShowObjectUpdates = !(gShowObjectUpdates);
+ return true;
+ }
+};
+
+class LLAdvancedCheckShowObjectUpdates : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = gShowObjectUpdates;
+ return new_value;
+ }
+};
+
+
+
+////////////////////
+// COMPRESS IMAGE //
+////////////////////
+
+
+class LLAdvancedCompressImage : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_compress_image(NULL);
+ return true;
+ }
+};
+
+
+
+/////////////////////////
+// SHOW DEBUG SETTINGS //
+/////////////////////////
+
+
+class LLAdvancedShowDebugSettings : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLFloaterReg::showInstance("settings_debug",userdata);
+ return true;
+ }
+};
+
+
+
+////////////////////////
+// VIEW ADMIN OPTIONS //
+////////////////////////
+
+
+class LLAdvancedToggleViewAdminOptions : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_admin_override_toggle(NULL);
+ return true;
+ }
+};
+
+class LLAdvancedCheckViewAdminOptions : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = check_admin_override(NULL);
+ return new_value;
+ }
+};
+
+/////////////////////////////////////
+// Enable Object Object Occlusion ///
+/////////////////////////////////////
+class LLAdvancedEnableObjectObjectOcclusion: public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
- menu->createJumpKeys();
-}
-
-void init_debug_avatar_menu(LLMenuGL* menu)
-{
- LLMenuGL* sub_menu = new LLMenuGL("Grab Baked Texture");
- init_debug_baked_texture_menu(sub_menu);
- menu->appendMenu(sub_menu);
-
- sub_menu = new LLMenuGL("Character Tests");
- sub_menu->append(new LLMenuItemCheckGL("Go Away/AFK When Idle",
- menu_toggle_control,
- NULL,
- menu_check_control,
- (void*)"AllowIdleAFK"));
-
- sub_menu->append(new LLMenuItemCallGL("Appearance To XML",
- &LLVOAvatar::dumpArchetypeXML));
-
- // HACK for easy testing of avatar geometry
- sub_menu->append(new LLMenuItemCallGL( "Toggle Character Geometry",
- &handle_god_request_avatar_geometry, &enable_god_customer_service, NULL));
-
- sub_menu->append(new LLMenuItemCallGL("Test Male",
- handle_test_male));
-
- sub_menu->append(new LLMenuItemCallGL("Test Female",
- handle_test_female));
-
- sub_menu->append(new LLMenuItemCallGL("Toggle PG", handle_toggle_pg));
-
- sub_menu->append(new LLMenuItemToggleGL("Allow Select Avatar", &gAllowSelectAvatar));
- sub_menu->createJumpKeys();
-
- menu->appendMenu(sub_menu);
-
- menu->append(new LLMenuItemCheckGL("Enable Lip Sync (Beta)", menu_toggle_control, NULL, menu_check_control, (void*)"LipSyncEnabled"));
- menu->append(new LLMenuItemToggleGL("Tap-Tap-Hold To Run", &gAllowTapTapHoldRun));
- menu->append(new LLMenuItemCallGL("Force Params to Default", &LLAgent::clearVisualParams, NULL));
- menu->append(new LLMenuItemCallGL("Reload Vertex Shader", &reload_vertex_shader, NULL));
- menu->append(new LLMenuItemToggleGL("Animation Info", &LLVOAvatar::sShowAnimationDebug));
- menu->append(new LLMenuItemCallGL("Slow Motion Animations", &slow_mo_animations, NULL));
- menu->append(new LLMenuItemToggleGL("Show Look At", &LLHUDEffectLookAt::sDebugLookAt));
- menu->append(new LLMenuItemToggleGL("Show Point At", &LLHUDEffectPointAt::sDebugPointAt));
- menu->append(new LLMenuItemToggleGL("Debug Joint Updates", &LLVOAvatar::sJointDebug));
- menu->append(new LLMenuItemToggleGL("Disable LOD", &LLViewerJoint::sDisableLOD));
- menu->append(new LLMenuItemToggleGL("Debug Character Vis", &LLVOAvatar::sDebugInvisible));
- //menu->append(new LLMenuItemToggleGL("Show Attachment Points", &LLVOAvatar::sShowAttachmentPoints));
- //diabling collision plane due to DEV-14477 -brad
- //menu->append(new LLMenuItemToggleGL("Show Collision Plane", &LLVOAvatar::sShowFootPlane));
- menu->append(new LLMenuItemCheckGL("Show Collision Skeleton",
- &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_AVATAR_VOLUME));
- menu->append(new LLMenuItemCheckGL("Display Agent Target",
- &LLPipeline::toggleRenderDebug, NULL,
- &LLPipeline::toggleRenderDebugControl,
- (void*)LLPipeline::RENDER_DEBUG_AGENT_TARGET));
- menu->append(new LLMenuItemToggleGL( "Debug Rotation", &LLVOAvatar::sDebugAvatarRotation));
- menu->append(new LLMenuItemCallGL("Dump Attachments", handle_dump_attachments));
- menu->append(new LLMenuItemCallGL("Rebake Textures", handle_rebake_textures, NULL, NULL, 'R', MASK_ALT | MASK_CONTROL ));
-#ifndef LL_RELEASE_FOR_DOWNLOAD
- menu->append(new LLMenuItemCallGL("Debug Avatar Textures", handle_debug_avatar_textures, NULL, NULL, 'A', MASK_SHIFT|MASK_CONTROL|MASK_ALT));
- menu->append(new LLMenuItemCallGL("Dump Local Textures", handle_dump_avatar_local_textures, NULL, NULL, 'M', MASK_SHIFT|MASK_ALT ));
-#endif
- menu->createJumpKeys();
+ bool new_value = gGLManager.mHasOcclusionQuery; // && LLFeatureManager::getInstance()->isFeatureAvailable(userdata.asString());
+ return new_value;
}
+};
+
+/////////////////////////////////////
+// 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 = gSavedSettings.getBOOL("RenderUseFBO") && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT > 0) &&
+ LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0;
+ return new_value;
+ }
+};
+
+/////////////////////////////////////
+// Enable Global Illumination ///
+/////////////////////////////////////
+class LLAdvancedEnableRenderDeferredGI: public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = gSavedSettings.getBOOL("RenderUseFBO") && gSavedSettings.getBOOL("RenderDeferred");
+ return new_value;
+ }
+};
+
+
+
+//////////////////
+// ADMIN STATUS //
+//////////////////
+
+
+class LLAdvancedRequestAdminStatus : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_god_mode(NULL);
+ return true;
+ }
+};
+
+class LLAdvancedLeaveAdminStatus : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_leave_god_mode(NULL);
+ return true;
+ }
+};
+
+//////////////////////////
+// Advanced > Debugging //
+//////////////////////////
+
+
+class LLAdvancedForceErrorBreakpoint : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ force_error_breakpoint(NULL);
+ return true;
+ }
+};
+
+class LLAdvancedForceErrorLlerror : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ force_error_llerror(NULL);
+ return true;
+ }
+};
+class LLAdvancedForceErrorBadMemoryAccess : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ force_error_bad_memory_access(NULL);
+ return true;
+ }
+};
+
+class LLAdvancedForceErrorInfiniteLoop : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ force_error_infinite_loop(NULL);
+ return true;
+ }
+};
+
+class LLAdvancedForceErrorSoftwareException : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ force_error_software_exception(NULL);
+ return true;
+ }
+};
+
+class LLAdvancedForceErrorDriverCrash : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ force_error_driver_crash(NULL);
+ return true;
+ }
+};
-void init_debug_baked_texture_menu(LLMenuGL* menu)
+class LLAdvancedForceErrorDisconnectViewer : public view_listener_t
{
- menu->append(new LLMenuItemCallGL("Iris", handle_grab_texture, enable_grab_texture, (void*) TEX_EYES_BAKED));
- menu->append(new LLMenuItemCallGL("Head", handle_grab_texture, enable_grab_texture, (void*) TEX_HEAD_BAKED));
- menu->append(new LLMenuItemCallGL("Upper Body", handle_grab_texture, enable_grab_texture, (void*) TEX_UPPER_BAKED));
- menu->append(new LLMenuItemCallGL("Lower Body", handle_grab_texture, enable_grab_texture, (void*) TEX_LOWER_BAKED));
- menu->append(new LLMenuItemCallGL("Skirt", handle_grab_texture, enable_grab_texture, (void*) TEX_SKIRT_BAKED));
- menu->append(new LLMenuItemCallGL("Hair", handle_grab_texture, enable_grab_texture, (void*) TEX_HAIR_BAKED));
- menu->createJumpKeys();
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_disconnect_viewer(NULL);
+ return true;
}
+};
+
+
+#ifdef TOGGLE_HACKED_GODLIKE_VIEWER
+
+class LLAdvancedHandleToggleHackedGodmode : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_toggle_hacked_godmode(NULL);
+ return true;
+ }
+};
-void init_server_menu(LLMenuGL* menu)
+class LLAdvancedCheckToggleHackedGodmode : public view_listener_t
{
+ bool handleEvent(const LLSD& userdata)
{
- LLMenuGL* sub = new LLMenuGL("Object");
- menu->appendMenu(sub);
+ check_toggle_hacked_godmode(NULL);
+ return true;
+ }
+};
- sub->append(new LLMenuItemCallGL( "Take Copy",
- &force_take_copy, &enable_god_customer_service, NULL,
- 'O', MASK_SHIFT | MASK_ALT | MASK_CONTROL));
-#ifdef _CORY_TESTING
- sub->append(new LLMenuItemCallGL( "Export Copy",
- &force_export_copy, NULL, NULL));
- sub->append(new LLMenuItemCallGL( "Import Geometry",
- &force_import_geometry, NULL, NULL));
+class LLAdvancedEnableToggleHackedGodmode : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = enable_toggle_hacked_godmode(NULL);
+ return new_value;
+ }
+};
#endif
- //sub->append(new LLMenuItemCallGL( "Force Public",
- // &handle_object_owner_none, NULL, NULL));
- //sub->append(new LLMenuItemCallGL( "Force Ownership/Permissive",
- // &handle_object_owner_self_and_permissive, NULL, NULL, 'K', MASK_SHIFT | MASK_ALT | MASK_CONTROL));
- sub->append(new LLMenuItemCallGL( "Force Owner To Me",
- &handle_object_owner_self, &enable_god_customer_service));
- sub->append(new LLMenuItemCallGL( "Force Owner Permissive",
- &handle_object_owner_permissive, &enable_god_customer_service));
- //sub->append(new LLMenuItemCallGL( "Force Totally Permissive",
- // &handle_object_permissive));
- sub->append(new LLMenuItemCallGL( "Delete",
- &handle_force_delete, &enable_god_customer_service, NULL, KEY_DELETE, MASK_SHIFT | MASK_ALT | MASK_CONTROL));
- sub->append(new LLMenuItemCallGL( "Lock",
- &handle_object_lock, &enable_god_customer_service, NULL, 'L', MASK_SHIFT | MASK_ALT | MASK_CONTROL));
- sub->append(new LLMenuItemCallGL( "Get Asset IDs",
- &handle_object_asset_ids, &enable_god_customer_service, NULL, 'I', MASK_SHIFT | MASK_ALT | MASK_CONTROL));
- sub->createJumpKeys();
- }
- {
- LLMenuGL* sub = new LLMenuGL("Parcel");
- menu->appendMenu(sub);
-
- sub->append(new LLMenuItemCallGL("Owner To Me",
- &handle_force_parcel_owner_to_me,
- &enable_god_customer_service, NULL));
- sub->append(new LLMenuItemCallGL("Set to Linden Content",
- &handle_force_parcel_to_content,
- &enable_god_customer_service, NULL,
- 'C', MASK_SHIFT | MASK_ALT | MASK_CONTROL));
- sub->appendSeparator();
- sub->append(new LLMenuItemCallGL("Claim Public Land",
- &handle_claim_public_land, &enable_god_customer_service));
-
- sub->createJumpKeys();
- }
- {
- LLMenuGL* sub = new LLMenuGL("Region");
- menu->appendMenu(sub);
- sub->append(new LLMenuItemCallGL("Dump Temp Asset Data",
- &handle_region_dump_temp_asset_data,
- &enable_god_customer_service, NULL));
- sub->createJumpKeys();
+
+
+//
+////-------------------------------------------------------------------
+//// Advanced menu
+////-------------------------------------------------------------------
+
+//////////////////
+// ADMIN MENU //
+//////////////////
+
+// Admin > Object
+class LLAdminForceTakeCopy : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ force_take_copy(NULL);
+ return true;
+ }
+};
+
+class LLAdminHandleObjectOwnerSelf : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_object_owner_self(NULL);
+ return true;
+ }
+};
+class LLAdminHandleObjectOwnerPermissive : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_object_owner_permissive(NULL);
+ return true;
+ }
+};
+
+class LLAdminHandleForceDelete : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_force_delete(NULL);
+ return true;
+ }
+};
+
+class LLAdminHandleObjectLock : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_object_lock(NULL);
+ return true;
+ }
+};
+
+class LLAdminHandleObjectAssetIDs: public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_object_asset_ids(NULL);
+ return true;
}
- menu->append(new LLMenuItemCallGL( "God Tools...",
- &LLFloaterGodTools::show, &enable_god_basic, NULL));
+};
- menu->appendSeparator();
+//Admin >Parcel
+class LLAdminHandleForceParcelOwnerToMe: public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_force_parcel_owner_to_me(NULL);
+ return true;
+ }
+};
+class LLAdminHandleForceParcelToContent: public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_force_parcel_to_content(NULL);
+ return true;
+ }
+};
+class LLAdminHandleClaimPublicLand: public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_claim_public_land(NULL);
+ return true;
+ }
+};
- menu->append(new LLMenuItemCallGL("Save Region State",
- &LLPanelRegionTools::onSaveState, &enable_god_customer_service, NULL));
+// Admin > Region
+class LLAdminHandleRegionDumpTempAssetData: public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ handle_region_dump_temp_asset_data(NULL);
+ return true;
+ }
+};
+//Admin (Top Level)
-// menu->append(new LLMenuItemCallGL("Force Join Group", handle_force_join_group));
-//
-// menu->appendSeparator();
-//
-// menu->append(new LLMenuItemCallGL( "OverlayTitle",
-// &handle_show_overlay_title, &enable_god_customer_service, NULL));
- menu->createJumpKeys();
+class LLAdminOnSaveState: public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLPanelRegionTools::onSaveState(NULL);
+ return true;
}
+};
-static std::vector<LLPointer<view_listener_t> > sMenus;
//-----------------------------------------------------------------------------
// cleanup_menus()
@@ -1489,20 +2282,23 @@ void cleanup_menus()
delete gMenuParcelObserver;
gMenuParcelObserver = NULL;
- delete gPieSelf;
- gPieSelf = NULL;
+ delete gMenuAvatarSelf;
+ gMenuAvatarSelf = NULL;
- delete gPieAvatar;
- gPieAvatar = NULL;
+ delete gMenuAvatarOther;
+ gMenuAvatarOther = NULL;
- delete gPieObject;
- gPieObject = NULL;
+ delete gMenuObject;
+ gMenuObject = NULL;
- delete gPieAttachment;
- gPieAttachment = NULL;
+ delete gMenuAttachmentSelf;
+ gMenuAttachmentSelf = NULL;
- delete gPieLand;
- gPieLand = NULL;
+ delete gMenuAttachmentOther;
+ gMenuAttachmentSelf = NULL;
+
+ delete gMenuLand;
+ gMenuLand = NULL;
delete gMenuBarView;
gMenuBarView = NULL;
@@ -1512,8 +2308,6 @@ void cleanup_menus()
delete gMenuHolder;
gMenuHolder = NULL;
-
- sMenus.clear();
}
//-----------------------------------------------------------------------------
@@ -1522,7 +2316,7 @@ void cleanup_menus()
class LLObjectReportAbuse : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
if (objectp)
@@ -1536,20 +2330,17 @@ class LLObjectReportAbuse : public view_listener_t
// Enabled it you clicked an object
class LLObjectEnableReportAbuse : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = LLSelectMgr::getInstance()->getSelection()->getObjectCount() != 0;
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
-class LLObjectTouch : public view_listener_t
+void handle_object_touch()
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (!object) return true;
+ if (!object) return;
LLPickInfo pick = LLToolPie::getInstance()->getPick();
@@ -1588,175 +2379,74 @@ class LLObjectTouch : public view_listener_t
msg->addVector3("Normal", pick.mNormal);
msg->addVector3("Binormal", pick.mBinormal);
msg->sendMessage(object->getRegion()->getHost());
+}
- return true;
- }
-};
-
+bool enable_object_touch()
+{
+ LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ return obj && obj->flagHandleTouch();
+}
// One object must have touch sensor
class LLObjectEnableTouch : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- bool new_value = obj && obj->flagHandleTouch();
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
+ bool new_value = enable_object_touch();
// Update label based on the node touch name if available.
- LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
-
std::string touch_text;
+ LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
if (node && node->mValid && !node->mTouchName.empty())
{
- touch_text = node->mTouchName;
+ touch_text = node->mTouchName;
}
else
{
- touch_text = userdata["data"].asString();
+ touch_text = userdata.asString();
}
-
gMenuHolder->childSetText("Object Touch", touch_text);
gMenuHolder->childSetText("Attachment Object Touch", touch_text);
- return true;
+ return new_value;
}
};
-void label_touch(std::string& label, void*)
-{
- LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
- if (node && node->mValid && !node->mTouchName.empty())
- {
- label.assign(node->mTouchName);
- }
- else
- {
- label.assign("Touch");
- }
-}
+//void label_touch(std::string& label, void*)
+//{
+// LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
+// if (node && node->mValid && !node->mTouchName.empty())
+// {
+// label.assign(node->mTouchName);
+// }
+// else
+// {
+// label.assign("Touch");
+// }
+//}
-bool handle_object_open()
+void handle_object_open()
{
- LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if(!obj) return true;
-
- LLFloaterOpenObject::show();
- return true;
+ LLFloaterReg::showInstance("openobject");
}
-class LLObjectOpen : public view_listener_t
-{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- return handle_object_open();
- }
-};
-
-class LLObjectEnableOpen : public view_listener_t
-{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- // Look for contents in root object, which is all the LLFloaterOpenObject
- // understands.
- LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- bool new_value = (obj != NULL);
- if (new_value)
- {
- LLViewerObject* root = obj->getRootEdit();
- if (!root) new_value = false;
- else new_value = root->allowOpen();
- }
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
- }
-};
-
-
-class LLViewCheckBuildMode : public view_listener_t
+bool enable_object_open()
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- bool new_value = LLToolMgr::getInstance()->inEdit();
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
- }
-};
-
-bool toggle_build_mode()
-{
- if (LLToolMgr::getInstance()->inBuildMode())
- {
- if (gSavedSettings.getBOOL("EditCameraMovement"))
- {
- // just reset the view, will pull us out of edit mode
- handle_reset_view();
- }
- else
- {
- // manually disable edit mode, but do not affect the camera
- gAgent.resetView(false);
- gFloaterTools->close();
- gViewerWindow->showCursor();
- }
- // avoid spurious avatar movements pulling out of edit mode
- LLViewerJoystick::getInstance()->setNeedsReset();
- }
- else
- {
- ECameraMode camMode = gAgent.getCameraMode();
- if (CAMERA_MODE_MOUSELOOK == camMode || CAMERA_MODE_CUSTOMIZE_AVATAR == camMode)
- {
- // pull the user out of mouselook or appearance mode when entering build mode
- handle_reset_view();
- }
-
- if (gSavedSettings.getBOOL("EditCameraMovement"))
- {
- // camera should be set
- if (LLViewerJoystick::getInstance()->getOverrideCamera())
- {
- handle_toggle_flycam();
- }
-
- if (gAgent.getFocusOnAvatar())
- {
- // zoom in if we're looking at the avatar
- gAgent.setFocusOnAvatar(FALSE, ANIMATE);
- gAgent.setFocusGlobal(gAgent.getPositionGlobal() + 2.0 * LLVector3d(gAgent.getAtAxis()));
- gAgent.cameraZoomIn(0.666f);
- gAgent.cameraOrbitOver( 30.f * DEG_TO_RAD );
- }
- }
-
-
- LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
- LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() );
-
- // Could be first use
- LLFirstUse::useBuild();
-
- gAgent.resetView(false);
+ // Look for contents in root object, which is all the LLFloaterOpenObject
+ // understands.
+ LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if (!obj) return false;
- // avoid spurious avatar movements
- LLViewerJoystick::getInstance()->setNeedsReset();
+ LLViewerObject* root = obj->getRootEdit();
+ if (!root) return false;
- }
- return true;
+ return root->allowOpen();
}
-class LLViewBuildMode : public view_listener_t
-{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- return toggle_build_mode();
- }
-};
-
class LLViewJoystickFlycam : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
handle_toggle_flycam();
return true;
@@ -1765,31 +2455,13 @@ class LLViewJoystickFlycam : public view_listener_t
class LLViewCheckJoystickFlycam : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- bool new_val = LLViewerJoystick::getInstance()->getOverrideCamera();
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_val);
- return true;
- }
-};
-
-class LLViewCommunicate : public view_listener_t
-{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- if (LLFloaterChatterBox::getInstance()->getFloaterCount() == 0)
- {
- LLFloaterMyFriends::toggleInstance();
- }
- else
- {
- LLFloaterChatterBox::toggleInstance();
- }
- return true;
+ bool new_value = LLViewerJoystick::getInstance()->getOverrideCamera();
+ return new_value;
}
};
-
void handle_toggle_flycam()
{
LLViewerJoystick::getInstance()->toggleFlycam();
@@ -1797,7 +2469,7 @@ void handle_toggle_flycam()
class LLObjectBuild : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
if (gAgent.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit() && gSavedSettings.getBOOL("EditCameraMovement") )
{
@@ -1818,73 +2490,78 @@ class LLObjectBuild : public view_listener_t
LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() );
// Could be first use
- LLFirstUse::useBuild();
+ //LLFirstUse::useBuild();
return true;
}
};
-class LLObjectEdit : public view_listener_t
+
+void handle_object_edit()
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ LLViewerParcelMgr::getInstance()->deselectLand();
+
+ if (gAgent.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit())
{
- LLViewerParcelMgr::getInstance()->deselectLand();
+ LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
- if (gAgent.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit())
+ if (selection->getSelectType() == SELECT_TYPE_HUD || !gSavedSettings.getBOOL("EditCameraMovement"))
{
- LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
-
- if (selection->getSelectType() == SELECT_TYPE_HUD || !gSavedSettings.getBOOL("EditCameraMovement"))
- {
- // always freeze camera in space, even if camera doesn't move
- // so, for example, follow cam scripts can't affect you when in build mode
- gAgent.setFocusGlobal(gAgent.calcFocusPositionTargetGlobal(), LLUUID::null);
- gAgent.setFocusOnAvatar(FALSE, ANIMATE);
- }
- else
+ // always freeze camera in space, even if camera doesn't move
+ // so, for example, follow cam scripts can't affect you when in build mode
+ gAgent.setFocusGlobal(gAgent.calcFocusPositionTargetGlobal(), LLUUID::null);
+ gAgent.setFocusOnAvatar(FALSE, ANIMATE);
+ }
+ else
+ {
+ gAgent.setFocusOnAvatar(FALSE, ANIMATE);
+ LLViewerObject* selected_objectp = selection->getFirstRootObject();
+ if (selected_objectp)
{
- gAgent.setFocusOnAvatar(FALSE, ANIMATE);
- LLViewerObject* selected_objectp = selection->getFirstRootObject();
- if (selected_objectp)
- {
- // zoom in on object center instead of where we clicked, as we need to see the manipulator handles
- gAgent.setFocusGlobal(selected_objectp->getPositionGlobal(), selected_objectp->getID());
- gAgent.cameraZoomIn(0.666f);
- gAgent.cameraOrbitOver( 30.f * DEG_TO_RAD );
- gViewerWindow->moveCursorToCenter();
+ // zoom in on object center instead of where we clicked, as we need to see the manipulator handles
+ gAgent.setFocusGlobal(selected_objectp->getPositionGlobal(), selected_objectp->getID());
+ gAgent.cameraZoomIn(0.666f);
+ gAgent.cameraOrbitOver( 30.f * DEG_TO_RAD );
+ gViewerWindow->moveCursorToCenter();
}
}
- }
-
- gFloaterTools->open(); /* Flawfinder: ignore */
-
- LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
- gFloaterTools->setEditTool( LLToolCompTranslate::getInstance() );
-
- LLViewerJoystick::getInstance()->moveObjects(true);
- LLViewerJoystick::getInstance()->setNeedsReset(true);
-
- // Could be first use
- LLFirstUse::useBuild();
- return true;
}
-};
+
+ LLFloaterReg::showInstance("build");
+
+ LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
+ gFloaterTools->setEditTool( LLToolCompTranslate::getInstance() );
+
+ LLViewerJoystick::getInstance()->moveObjects(true);
+ LLViewerJoystick::getInstance()->setNeedsReset(true);
+
+ // Could be first use
+ //LLFirstUse::useBuild();
+ return;
+}
-class LLObjectInspect : public view_listener_t
+void handle_object_inspect()
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+ LLViewerObject* selected_objectp = selection->getFirstRootObject();
+ if (selected_objectp)
{
- LLFloaterInspect::show();
- return true;
+ LLSD key;
+ key["task"] = "task";
+ LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
}
-};
+ /*
+ // Old floater properties
+ LLFloaterReg::showInstance("inspect", LLSD());
+ */
+}
//---------------------------------------------------------------------------
// Land pie menu
//---------------------------------------------------------------------------
class LLLandBuild : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
LLViewerParcelMgr::getInstance()->deselectLand();
@@ -1909,14 +2586,14 @@ class LLLandBuild : public view_listener_t
LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() );
// Could be first use
- LLFirstUse::useBuild();
+ //LLFirstUse::useBuild();
return true;
}
};
class LLLandBuyPass : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
LLPanelLandGeneral::onClickBuyPass((void *)FALSE);
return true;
@@ -1925,11 +2602,10 @@ class LLLandBuyPass : public view_listener_t
class LLLandEnableBuyPass : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = LLPanelLandGeneral::enableBuyPass(NULL);
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
@@ -1963,38 +2639,45 @@ BOOL enable_object_build(void*)
return can_build;
}
-class LLEnableEdit : public view_listener_t
+bool enable_object_edit()
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ // *HACK: The new "prelude" Help Islands have a build sandbox area,
+ // so users need the Edit and Create pie menu options when they are
+ // there. Eventually this needs to be replaced with code that only
+ // lets you edit objects if you have permission to do so (edit perms,
+ // group edit, god). See also lltoolbar.cpp. JC
+ bool enable = false;
+ if (gAgent.inPrelude())
{
- // *HACK: The new "prelude" Help Islands have a build sandbox area,
- // so users need the Edit and Create pie menu options when they are
- // there. Eventually this needs to be replaced with code that only
- // lets you edit objects if you have permission to do so (edit perms,
- // group edit, god). See also lltoolbar.cpp. JC
- bool enable = true;
- if (gAgent.inPrelude())
- {
- enable = LLViewerParcelMgr::getInstance()->agentCanBuild()
- || LLSelectMgr::getInstance()->getSelection()->isAttachment();
- }
- gMenuHolder->findControl(userdata["control"].asString())->setValue(enable);
- return true;
+ enable = LLViewerParcelMgr::getInstance()->allowAgentBuild()
+ || LLSelectMgr::getInstance()->getSelection()->isAttachment();
+ }
+ else if (LLSelectMgr::getInstance()->selectGetAllValidAndObjectsFound())
+ {
+ enable = true;
}
-};
+
+ return enable;
+}
+
+// mutually exclusive - show either edit option or build in menu
+bool enable_object_build()
+{
+ return !enable_object_edit();
+}
class LLSelfRemoveAllAttachments : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- LLAgent::userRemoveAllAttachments(NULL);
+ LLAgentWearables::userRemoveAllAttachments();
return true;
}
};
class LLSelfEnableRemoveAllAttachments : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = false;
if (gAgent.getAvatarObject())
@@ -2005,15 +2688,14 @@ class LLSelfEnableRemoveAllAttachments : public view_listener_t
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getObject())
+ if (attachment->getNumObjects() > 0)
{
new_value = true;
break;
}
}
}
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
@@ -2026,42 +2708,42 @@ BOOL enable_has_attachments(void*)
//---------------------------------------------------------------------------
// Avatar pie menu
//---------------------------------------------------------------------------
-void handle_follow(void *userdata)
+//void handle_follow(void *userdata)
+//{
+// // follow a given avatar by ID
+// LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+// if (objectp)
+// {
+// gAgent.startFollowPilot(objectp->getID());
+// }
+//}
+
+bool enable_object_mute()
{
- // follow a given avatar by ID
- LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (objectp)
+ LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if (!object) return false;
+
+ LLVOAvatar* avatar = find_avatar_from_object(object);
+ if (avatar)
{
- gAgent.startFollowPilot(objectp->getID());
+ // It's an avatar
+ LLNameValue *lastname = avatar->getNVPair("LastName");
+ bool is_linden =
+ lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden");
+ bool is_self = avatar->isSelf();
+ return !is_linden && !is_self;
}
-}
-
-class LLObjectEnableMute : public view_listener_t
-{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ else
{
- LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- bool new_value = (object != NULL);
- if (new_value)
- {
- LLVOAvatar* avatar = find_avatar_from_object(object);
- if (avatar)
- {
- // It's an avatar
- LLNameValue *lastname = avatar->getNVPair("LastName");
- BOOL is_linden = lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden");
- BOOL is_self = avatar->isSelf();
- new_value = !is_linden && !is_self;
- }
- }
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ // Just a regular object
+ return LLSelectMgr::getInstance()->getSelection()->
+ contains( object, SELECT_ALL_TES );
}
-};
+}
class LLObjectMute : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
if (!object) return true;
@@ -2107,7 +2789,7 @@ class LLObjectMute : public view_listener_t
else
{
LLMuteList::getInstance()->add(mute);
- LLFloaterMute::showInstance();
+ LLPanelBlockedList::showPanelAndSelect(mute.mID);
}
return true;
@@ -2116,7 +2798,7 @@ class LLObjectMute : public view_listener_t
bool handle_go_to()
{
- // JAMESDEBUG try simulator autopilot
+ // try simulator autopilot
std::vector<std::string> strings;
std::string val;
LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal;
@@ -2141,25 +2823,39 @@ bool handle_go_to()
}
// Could be first use
- LLFirstUse::useGoTo();
+ //LLFirstUse::useGoTo();
return true;
}
class LLGoToObject : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
return handle_go_to();
}
};
+class LLAvatarReportAbuse : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+ if(avatar)
+ {
+ LLFloaterReporter::showFromObject(avatar->getID());
+ }
+ return true;
+ }
+};
+
+
//---------------------------------------------------------------------------
// Parcel freeze, eject, etc.
//---------------------------------------------------------------------------
bool callback_freeze(const LLSD& notification, const LLSD& response)
{
LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option || 1 == option)
{
@@ -2189,11 +2885,20 @@ bool callback_freeze(const LLSD& notification, const LLSD& response)
}
-class LLAvatarFreeze : public view_listener_t
+void handle_avatar_freeze(const LLSD& avatar_id)
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+ // Use avatar_id if available, otherwise default to right-click avatar
+ LLVOAvatar* avatar = NULL;
+ if (avatar_id.asUUID().notNull())
+ {
+ avatar = find_avatar_from_object(avatar_id.asUUID());
+ }
+ else
+ {
+ avatar = find_avatar_from_object(
+ LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
+ }
+
if( avatar )
{
std::string fullname = avatar->getFullname();
@@ -2204,57 +2909,46 @@ class LLAvatarFreeze : public view_listener_t
{
LLSD args;
args["AVATAR_NAME"] = fullname;
- LLNotifications::instance().add("FreezeAvatarFullname",
+ LLNotificationsUtil::add("FreezeAvatarFullname",
args,
payload,
callback_freeze);
}
else
{
- LLNotifications::instance().add("FreezeAvatar",
+ LLNotificationsUtil::add("FreezeAvatar",
LLSD(),
payload,
callback_freeze);
}
}
- return true;
- }
-};
+}
class LLAvatarVisibleDebug : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- bool new_value = gAgent.isGodlike();
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
- }
-};
-
-class LLAvatarEnableDebug : public view_listener_t
-{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- bool new_value = gAgent.isGodlike();
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return gAgent.isGodlike();
}
};
class LLAvatarDebug : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
if( avatar )
{
- avatar->dumpLocalTextures();
+ if (avatar->isSelf())
+ {
+ ((LLVOAvatarSelf *)avatar)->dumpLocalTextures();
+ }
llinfos << "Dumping temporary asset data to simulator logs for avatar " << avatar->getID() << llendl;
std::vector<std::string> strings;
strings.push_back(avatar->getID().asString());
LLUUID invoice;
send_generic_message("dumptempassetdata", strings, invoice);
- LLFloaterAvatarTextures::show( avatar->getID() );
+ LLFloaterReg::showInstance( "avatar_textures", LLSD(avatar->getID()) );
}
return true;
}
@@ -2262,7 +2956,7 @@ class LLAvatarDebug : public view_listener_t
bool callback_eject(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (2 == option)
{
// Cancel button.
@@ -2314,11 +3008,20 @@ bool callback_eject(const LLSD& notification, const LLSD& response)
return false;
}
-class LLAvatarEject : public view_listener_t
+void handle_avatar_eject(const LLSD& avatar_id)
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+ // Use avatar_id if available, otherwise default to right-click avatar
+ LLVOAvatar* avatar = NULL;
+ if (avatar_id.asUUID().notNull())
+ {
+ avatar = find_avatar_from_object(avatar_id.asUUID());
+ }
+ else
+ {
+ avatar = find_avatar_from_object(
+ LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
+ }
+
if( avatar )
{
LLSD payload;
@@ -2335,14 +3038,14 @@ class LLAvatarEject : public view_listener_t
{
LLSD args;
args["AVATAR_NAME"] = fullname;
- LLNotifications::instance().add("EjectAvatarFullname",
+ LLNotificationsUtil::add("EjectAvatarFullname",
args,
payload,
callback_eject);
}
else
{
- LLNotifications::instance().add("EjectAvatarFullname",
+ LLNotificationsUtil::add("EjectAvatarFullname",
LLSD(),
payload,
callback_eject);
@@ -2355,57 +3058,59 @@ class LLAvatarEject : public view_listener_t
{
LLSD args;
args["AVATAR_NAME"] = fullname;
- LLNotifications::instance().add("EjectAvatarFullnameNoBan",
+ LLNotificationsUtil::add("EjectAvatarFullnameNoBan",
args,
payload,
callback_eject);
}
else
{
- LLNotifications::instance().add("EjectAvatarNoBan",
+ LLNotificationsUtil::add("EjectAvatarNoBan",
LLSD(),
payload,
callback_eject);
}
}
}
- return true;
- }
-};
+}
-class LLAvatarEnableFreezeEject : public view_listener_t
+bool enable_freeze_eject(const LLSD& avatar_id)
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ // Use avatar_id if available, otherwise default to right-click avatar
+ LLVOAvatar* avatar = NULL;
+ if (avatar_id.asUUID().notNull())
{
- LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
- bool new_value = (avatar != NULL);
+ avatar = find_avatar_from_object(avatar_id.asUUID());
+ }
+ else
+ {
+ avatar = find_avatar_from_object(
+ LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
+ }
+ if (!avatar) return false;
- if (new_value)
- {
- const LLVector3& pos = avatar->getPositionRegion();
- const LLVector3d& pos_global = avatar->getPositionGlobal();
- LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos_global)->getParcel();
- LLViewerRegion* region = avatar->getRegion();
- new_value = (region != NULL);
-
- if (new_value)
- {
- new_value = region->isOwnedSelf(pos);
- if (!new_value || region->isOwnedGroup(pos))
- {
- new_value = LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_ADMIN);
- }
- }
- }
+ // Gods can always freeze
+ if (gAgent.isGodlike()) return true;
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ // Estate owners / managers can freeze
+ // Parcel owners can also freeze
+ const LLVector3& pos = avatar->getPositionRegion();
+ const LLVector3d& pos_global = avatar->getPositionGlobal();
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos_global)->getParcel();
+ LLViewerRegion* region = avatar->getRegion();
+ if (!region) return false;
+
+ bool new_value = region->isOwnedSelf(pos);
+ if (!new_value || region->isOwnedGroup(pos))
+ {
+ new_value = LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_ADMIN);
}
-};
+ return new_value;
+}
class LLAvatarGiveCard : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
llinfos << "handle_give_card()" << llendl;
LLViewerObject* dest = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
@@ -2443,11 +3148,11 @@ class LLAvatarGiveCard : public view_listener_t
transaction_id.generate();
msg->addUUIDFast(_PREHASH_TransactionID, transaction_id);
msg->sendReliable(dest_host);
- LLNotifications::instance().add("OfferedCard", args);
+ LLNotificationsUtil::add("OfferedCard", args);
}
else
{
- LLNotifications::instance().add("CantOfferCallingCard", old_args);
+ LLNotificationsUtil::add("CantOfferCallingCard", old_args);
}
}
return true;
@@ -2460,13 +3165,13 @@ void login_done(S32 which, void *user)
{
llinfos << "Login done " << which << llendl;
- LLPanelLogin::close();
+ LLPanelLogin::closePanel();
}
bool callback_leave_group(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0)
{
LLMessageSystem *msg = gMessageSystem;
@@ -2476,22 +3181,12 @@ bool callback_leave_group(const LLSD& notification, const LLSD& response)
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->nextBlockFast(_PREHASH_GroupData);
- msg->addUUIDFast(_PREHASH_GroupID, gAgent.mGroupID );
+ msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID() );
gAgent.sendReliableMessage();
}
return false;
}
-void handle_leave_group(void *)
-{
- if (gAgent.getGroupID() != LLUUID::null)
- {
- LLSD args;
- args["GROUP"] = gAgent.mGroupName;
- LLNotifications::instance().add("GroupLeaveConfirmMember", args, LLSD(), callback_leave_group);
- }
-}
-
void append_aggregate(std::string& string, const LLAggregatePermissions& ag_perm, PermissionBit bit, const char* txt)
{
LLAggregatePermissions::EValue val = ag_perm.getValue(bit);
@@ -2514,44 +3209,36 @@ void append_aggregate(std::string& string, const LLAggregatePermissions& ag_perm
string.append(buffer);
}
-BOOL enable_buy(void*)
+bool enable_buy_object()
{
// In order to buy, there must only be 1 purchaseable object in
// the selection manger.
- if(LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() != 1) return FALSE;
+ if(LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() != 1) return false;
LLViewerObject* obj = NULL;
LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
if(node)
{
obj = node->getObject();
- if(!obj) return FALSE;
+ if(!obj) return false;
- if(node->mSaleInfo.isForSale() && node->mPermissions->getMaskOwner() & PERM_TRANSFER &&
- (node->mPermissions->getMaskOwner() & PERM_COPY || node->mSaleInfo.getSaleType() != LLSaleInfo::FS_COPY))
+ if( for_sale_selection(node) )
{
- if(obj->permAnyOwner()) return TRUE;
+ // *NOTE: Is this needed? This checks to see if anyone owns the
+ // object, dating back to when we had "public" objects owned by
+ // no one. JC
+ if(obj->permAnyOwner()) return true;
}
}
- return FALSE;
+ return false;
}
-class LLObjectEnableBuy : public view_listener_t
-{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- bool new_value = enable_buy(NULL);
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
- }
-};
-
// Note: This will only work if the selected object's data has been
// received by the viewer and cached in the selection manager.
void handle_buy_object(LLSaleInfo sale_info)
{
if(!LLSelectMgr::getInstance()->selectGetAllRootsValid())
{
- LLNotifications::instance().add("UnableToBuyWhileDownloading");
+ LLNotificationsUtil::add("UnableToBuyWhileDownloading");
return;
}
@@ -2560,7 +3247,7 @@ void handle_buy_object(LLSaleInfo sale_info)
BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name);
if (!owners_identical)
{
- LLNotifications::instance().add("CannotBuyObjectsFromDifferentOwners");
+ LLNotificationsUtil::add("CannotBuyObjectsFromDifferentOwners");
return;
}
@@ -2570,7 +3257,7 @@ void handle_buy_object(LLSaleInfo sale_info)
valid &= LLSelectMgr::getInstance()->selectGetAggregatePermissions(ag_perm);
if(!valid || !sale_info.isForSale() || !perm.allowTransferTo(gAgent.getID()))
{
- LLNotifications::instance().add("ObjectNotForSale");
+ LLNotificationsUtil::add("ObjectNotForSale");
return;
}
@@ -2623,18 +3310,9 @@ void handle_region_dump_settings(void*)
}
}
-void handle_show_notifications_console(void *)
-{
- LLFloaterNotificationConsole::showInstance();
-}
-
void handle_dump_group_info(void *)
{
- llinfos << "group " << gAgent.mGroupName << llendl;
- llinfos << "ID " << gAgent.mGroupID << llendl;
- llinfos << "powers " << gAgent.mGroupPowers << llendl;
- llinfos << "title " << gAgent.mGroupTitle << llendl;
- //llinfos << "insig " << gAgent.mGroupInsigniaID << llendl;
+ gAgent.dumpGroupInfo();
}
void handle_dump_capabilities_info(void *)
@@ -2655,7 +3333,7 @@ void handle_dump_region_object_cache(void*)
}
}
-void handle_dump_focus(void *)
+void handle_dump_focus()
{
LLUICtrl *ctrl = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
@@ -2664,19 +3342,71 @@ void handle_dump_focus(void *)
class LLSelfStandUp : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
+ gAgent.standUp();
return true;
}
};
-class LLSelfEnableStandUp : public view_listener_t
+bool enable_standup_self()
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool new_value = gAgent.getAvatarObject() && gAgent.getAvatarObject()->isSitting();
+ return new_value;
+}
+
+// Used from the login screen to aid in UI work on side tray
+void handle_show_side_tray()
+{
+ LLSideTray* side_tray = LLSideTray::getInstance();
+ LLView* root = gViewerWindow->getRootView();
+ // automatically removes and re-adds if there already
+ root->addChild(side_tray);
+}
+
+// Toggle one of "People" panel tabs in side tray.
+class LLTogglePanelPeopleTab : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string panel_name = userdata.asString();
+
+ LLSD param;
+ param["people_panel_tab_name"] = panel_name;
+
+ static LLPanel* friends_panel = NULL;
+ static LLPanel* groups_panel = NULL;
+ static LLPanel* nearby_panel = NULL;
+
+ if (panel_name == "friends_panel")
+ {
+ return togglePeoplePanel(friends_panel, panel_name, param);
+ }
+ else if (panel_name == "groups_panel")
+ {
+ return togglePeoplePanel(groups_panel, panel_name, param);
+ }
+ else if (panel_name == "nearby_panel")
+ {
+ return togglePeoplePanel(nearby_panel, panel_name, param);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ static bool togglePeoplePanel(LLPanel* &panel, const std::string& panel_name, const LLSD& param)
{
- bool new_value = gAgent.getAvatarObject() && gAgent.getAvatarObject()->mIsSitting;
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
+ if(!panel)
+ {
+ panel = LLSideTray::getInstance()->getPanel(panel_name);
+ if(!panel)
+ return false;
+ }
+
+ LLSideTray::getInstance()->togglePanel(panel, "panel_people", param);
+
return true;
}
};
@@ -2708,15 +3438,10 @@ void set_god_level(U8 god_level)
{
U8 old_god_level = gAgent.getGodLevel();
gAgent.setGodLevel( god_level );
- gIMMgr->refresh();
LLViewerParcelMgr::getInstance()->notifyObservers();
- // Some classifieds change visibility on god mode
- LLFloaterDirectory::requestClassifieds();
-
- // God mode changes sim visibility
- LLWorldMap::getInstance()->reset();
- LLWorldMap::getInstance()->setCurrentLayer(0);
+ // God mode changes region visibility
+ LLWorldMap::getInstance()->reloadItems(true);
// inventory in items may change in god mode
gObjectList.dirtyAllObjectInventory();
@@ -2731,17 +3456,23 @@ void set_god_level(U8 god_level)
if(god_level > GOD_NOT)
{
args["LEVEL"] = llformat("%d",(S32)god_level);
- LLNotifications::instance().add("EnteringGodMode", args);
+ LLNotificationsUtil::add("EnteringGodMode", args);
}
else
{
args["LEVEL"] = llformat("%d",(S32)old_god_level);
- LLNotifications::instance().add("LeavingGodMode", args);
+ LLNotificationsUtil::add("LeavingGodMode", args);
}
-
// changing god-level can affect which menus we see
show_debug_menus();
+
+ // changing god-level can invalidate search results
+ LLFloaterSearch *search = dynamic_cast<LLFloaterSearch*>(LLFloaterReg::getInstance("search"));
+ if (search)
+ {
+ search->godLevelChanged(god_level);
+ }
}
#ifdef TOGGLE_HACKED_GODLIKE_VIEWER
@@ -2755,6 +3486,11 @@ BOOL check_toggle_hacked_godmode(void*)
{
return gHackGodmode;
}
+
+bool enable_toggle_hacked_godmode(void*)
+{
+ return !LLViewerLogin::getInstance()->isInProductionGrid();
+}
#endif
void process_grant_godlike_powers(LLMessageSystem* msg, void**)
@@ -2810,48 +3546,23 @@ bool LLHaveCallingcard::operator()(LLInventoryCategory* cat,
}
*/
-BOOL is_agent_friend(const LLUUID& agent_id)
-{
- return (LLAvatarTracker::instance().getBuddyInfo(agent_id) != NULL);
-}
-
BOOL is_agent_mappable(const LLUUID& agent_id)
{
- return (is_agent_friend(agent_id) &&
+ return (LLAvatarActions::isFriend(agent_id) &&
LLAvatarTracker::instance().getBuddyInfo(agent_id)->isOnline() &&
LLAvatarTracker::instance().getBuddyInfo(agent_id)->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION)
);
}
-// Enable a menu item when you have someone's card.
-/*
-BOOL enable_have_card(void *userdata)
-{
- LLUUID* avatar_id = (LLUUID *)userdata;
- if (gAgent.isGodlike())
- {
- return TRUE;
- }
- else if(avatar_id)
- {
- return is_agent_friend(*avatar_id);
- }
- else
- {
- return FALSE;
- }
-}
-*/
// Enable a menu item when you don't have someone's card.
class LLAvatarEnableAddFriend : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
- bool new_value = avatar && !is_agent_friend(avatar->getID());
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ bool new_value = avatar && !LLAvatarActions::isFriend(avatar->getID());
+ return new_value;
}
};
@@ -2874,11 +3585,11 @@ void request_friendship(const LLUUID& dest_id)
}
if (!fullname.empty())
{
- LLPanelFriends::requestFriendshipDialog(dest_id, fullname);
+ LLAvatarActions::requestFriendshipDialog(dest_id, fullname);
}
else
{
- LLNotifications::instance().add("CantOfferFriendship");
+ LLNotificationsUtil::add("CantOfferFriendship");
}
}
}
@@ -2886,36 +3597,49 @@ void request_friendship(const LLUUID& dest_id)
class LLEditEnableCustomizeAvatar : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- bool new_value = (gAgent.getAvatarObject() &&
- gAgent.getAvatarObject()->isFullyLoaded() &&
- gAgent.areWearablesLoaded());
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ bool new_value = gAgentWearables.areWearablesLoaded();
+ return new_value;
}
};
+bool enable_sit_object()
+{
+ LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+
+ if (object && object->getPCode() == LL_PCODE_VOLUME)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
// only works on pie menu
-bool handle_sit_or_stand()
+void handle_object_sit_or_stand()
{
LLPickInfo pick = LLToolPie::getInstance()->getPick();
LLViewerObject *object = pick.getObject();;
if (!object || pick.mPickType == LLPickInfo::PICK_FLORA)
{
- return true;
+ return;
}
if (sitting_on_selection())
{
- gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
- return true;
+ gAgent.standUp();
+ return;
}
// get object selection offset
if (object && object->getPCode() == LL_PCODE_VOLUME)
{
+
gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit);
gMessageSystem->nextBlockFast(_PREHASH_AgentData);
gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
@@ -2926,17 +3650,8 @@ bool handle_sit_or_stand()
object->getRegion()->sendReliableMessage();
}
- return true;
}
-class LLObjectSitOrStand : public view_listener_t
-{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- return handle_sit_or_stand();
- }
-};
-
void near_sit_down_point(BOOL success, void *)
{
if (success)
@@ -2945,15 +3660,15 @@ void near_sit_down_point(BOOL success, void *)
gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
// Might be first sit
- LLFirstUse::useSit();
+ //LLFirstUse::useSit();
}
}
class LLLandSit : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
+ gAgent.standUp();
LLViewerParcelMgr::getInstance()->deselectLand();
LLVector3d posGlobal = LLToolPie::getInstance()->getPick().mPosGlobal;
@@ -2972,137 +3687,6 @@ class LLLandSit : public view_listener_t
}
};
-void show_permissions_control(void*)
-{
- LLFloaterPermissionsMgr* floaterp = LLFloaterPermissionsMgr::show();
- floaterp->mPermissions->addPermissionsData("foo1", LLUUID::null, 0);
- floaterp->mPermissions->addPermissionsData("foo2", LLUUID::null, 0);
- floaterp->mPermissions->addPermissionsData("foo3", LLUUID::null, 0);
-}
-
-
-class LLCreateLandmarkCallback : public LLInventoryCallback
-{
-public:
- /*virtual*/ void fire(const LLUUID& inv_item)
- {
- llinfos << "Created landmark with inventory id " << inv_item
- << llendl;
- }
-};
-
-void reload_ui(void *)
-{
- LLUICtrlFactory::getInstance()->rebuild();
-}
-
-class LLWorldFly : public view_listener_t
-{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- gAgent.toggleFlying();
- return true;
- }
-};
-
-class LLWorldEnableFly : public view_listener_t
-{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- BOOL sitting = FALSE;
- if (gAgent.getAvatarObject())
- {
- sitting = gAgent.getAvatarObject()->mIsSitting;
- }
- gMenuHolder->findControl(userdata["control"].asString())->setValue(!sitting);
- return true;
- }
-};
-
-
-void handle_agent_stop_moving(void*)
-{
- // stop agent
- gAgent.setControlFlags(AGENT_CONTROL_STOP);
-
- // cancel autopilot
- gAgent.stopAutoPilot();
-}
-
-void print_packets_lost(void*)
-{
- LLWorld::getInstance()->printPacketsLost();
-}
-
-
-void drop_packet(void*)
-{
- gMessageSystem->mPacketRing.dropPackets(1);
-}
-
-
-void velocity_interpolate( void* data )
-{
- BOOL toggle = gSavedSettings.getBOOL("VelocityInterpolate");
- LLMessageSystem* msg = gMessageSystem;
- if ( !toggle )
- {
- msg->newMessageFast(_PREHASH_VelocityInterpolateOn);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- gAgent.sendReliableMessage();
- llinfos << "Velocity Interpolation On" << llendl;
- }
- else
- {
- msg->newMessageFast(_PREHASH_VelocityInterpolateOff);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- gAgent.sendReliableMessage();
- llinfos << "Velocity Interpolation Off" << llendl;
- }
- // BUG this is a hack because of the change in menu behavior. The
- // old menu system would automatically change a control's value,
- // but the new LLMenuGL system doesn't know what a control
- // is. However, it's easy to distinguish between the two callers
- // because LLMenuGL passes in the name of the user data (the
- // control name) to the callback function, and the user data goes
- // unused in the old menu code. Thus, if data is not null, then we
- // need to swap the value of the control.
- if( data )
- {
- gSavedSettings.setBOOL( static_cast<char*>(data), !toggle );
- }
-}
-
-
-void toggle_wind_audio(void)
-{
- if (gAudiop)
- {
- gAudiop->enableWind(!(gAudiop->isWindEnabled()));
- }
-}
-
-
-// Callback for enablement
-BOOL is_inventory_visible( void* user_data )
-{
- LLInventoryView* iv = reinterpret_cast<LLInventoryView*>(user_data);
- if( iv )
- {
- return iv->getVisible();
- }
- return FALSE;
-}
-
-void handle_show_newest_map(void*)
-{
- LLFloaterWorldMap::show(NULL, FALSE);
-}
-
//-------------------------------------------------------------------
// Help menu functions
//-------------------------------------------------------------------
@@ -3110,24 +3694,26 @@ void handle_show_newest_map(void*)
//
// Major mode switching
//
-void reset_view_final( BOOL proceed, void* );
+void reset_view_final( BOOL proceed );
void handle_reset_view()
{
if( (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgent.getCameraMode()) && gFloaterCustomize )
{
// Show dialog box if needed.
- gFloaterCustomize->askToSaveIfDirty( reset_view_final, NULL );
+ gFloaterCustomize->askToSaveIfDirty( reset_view_final );
}
else
{
- reset_view_final( TRUE, NULL );
+ gAgent.switchCameraPreset(CAMERA_PRESET_REAR_VIEW);
+ reset_view_final( TRUE );
+ LLFloaterCamera::resetCameraMode();
}
}
class LLViewResetView : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
handle_reset_view();
return true;
@@ -3135,7 +3721,7 @@ class LLViewResetView : public view_listener_t
};
// Note: extra parameters allow this function to be called from dialog.
-void reset_view_final( BOOL proceed, void* )
+void reset_view_final( BOOL proceed )
{
if( !proceed )
{
@@ -3143,11 +3729,12 @@ void reset_view_final( BOOL proceed, void* )
}
gAgent.resetView(TRUE, TRUE);
+ gAgent.setLookAt(LOOKAT_TARGET_CLEAR);
}
class LLViewLookAtLastChatter : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
gAgent.lookAtLastChat();
return true;
@@ -3156,7 +3743,7 @@ class LLViewLookAtLastChatter : public view_listener_t
class LLViewMouselook : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
if (!gAgent.cameraMouselook())
{
@@ -3172,7 +3759,7 @@ class LLViewMouselook : public view_listener_t
class LLViewFullscreen : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
gViewerWindow->toggleFullscreen(TRUE);
return true;
@@ -3181,18 +3768,18 @@ class LLViewFullscreen : public view_listener_t
class LLViewDefaultUISize : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
gSavedSettings.setF32("UIScaleFactor", 1.0f);
gSavedSettings.setBOOL("UIAutoScale", FALSE);
- gViewerWindow->reshape(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight());
+ gViewerWindow->reshape(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
return true;
}
};
class LLEditDuplicate : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
if(LLEditMenuHandler::gEditMenuHandler)
{
@@ -3204,23 +3791,13 @@ class LLEditDuplicate : public view_listener_t
class LLEditEnableDuplicate : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDuplicate();
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
-
-void disabled_duplicate(void*)
-{
- if (LLSelectMgr::getInstance()->getSelection()->getPrimaryObject())
- {
- LLNotifications::instance().add("CopyFailed");
- }
-}
-
void handle_duplicate_in_place(void*)
{
llinfos << "handle_duplicate_in_place" << llendl;
@@ -3229,11 +3806,6 @@ void handle_duplicate_in_place(void*)
LLSelectMgr::getInstance()->selectDuplicate(offset, TRUE);
}
-void handle_repeat_duplicate(void*)
-{
- LLSelectMgr::getInstance()->repeatDuplicate();
-}
-
/* dead code 30-apr-2008
void handle_deed_object_to_group(void*)
{
@@ -3278,8 +3850,7 @@ void god_force_inv_owner_permissive(LLViewerObject* object,
InventoryObjectList::const_iterator inv_end = inventory->end();
for ( ; inv_it != inv_end; ++inv_it)
{
- if(((*inv_it)->getType() != LLAssetType::AT_CATEGORY)
- && ((*inv_it)->getType() != LLAssetType::AT_ROOT_CATEGORY))
+ if(((*inv_it)->getType() != LLAssetType::AT_CATEGORY))
{
LLInventoryObject* obj = *inv_it;
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem((LLViewerInventoryItem*)obj);
@@ -3350,7 +3921,7 @@ void handle_claim_public_land(void*)
{
if (LLViewerParcelMgr::getInstance()->getSelectionRegion() != gAgent.getRegion())
{
- LLNotifications::instance().add("ClaimPublicLand");
+ LLNotificationsUtil::add("ClaimPublicLand");
return;
}
@@ -3385,37 +3956,6 @@ void handle_claim_public_land(void*)
gAgent.sendReliableMessage();
}
-void handle_god_request_havok(void *)
-{
- if (gAgent.isGodlike())
- {
- LLSelectMgr::getInstance()->sendGodlikeRequest("havok", "infoverbose");
- }
-}
-
-//void handle_god_request_foo(void *)
-//{
-// if (gAgent.isGodlike())
-// {
-// LLSelectMgr::getInstance()->sendGodlikeRequest(GOD_WANTS_FOO);
-// }
-//}
-
-//void handle_god_request_terrain_save(void *)
-//{
-// if (gAgent.isGodlike())
-// {
-// LLSelectMgr::getInstance()->sendGodlikeRequest("terrain", "save");
-// }
-//}
-
-//void handle_god_request_terrain_load(void *)
-//{
-// if (gAgent.isGodlike())
-// {
-// LLSelectMgr::getInstance()->sendGodlikeRequest("terrain", "load");
-// }
-//}
// HACK for easily testing new avatar geometry
@@ -3423,17 +3963,11 @@ void handle_god_request_avatar_geometry(void *)
{
if (gAgent.isGodlike())
{
- LLSelectMgr::getInstance()->sendGodlikeRequest("avatar toggle", NULL);
+ LLSelectMgr::getInstance()->sendGodlikeRequest("avatar toggle", "");
}
}
-void handle_show_overlay_title(void*)
-{
- gShowOverlayTitle = !gShowOverlayTitle;
- gSavedSettings.setBOOL("ShowOverlayTitle", gShowOverlayTitle);
-}
-
void derez_objects(EDeRezDestination dest, const LLUUID& dest_id)
{
if(gAgent.cameraMouselook())
@@ -3583,40 +4117,34 @@ void derez_objects(EDeRezDestination dest, const LLUUID& dest_id)
}
else if(!error.empty())
{
- LLNotifications::instance().add(error);
+ LLNotificationsUtil::add(error);
}
}
-class LLToolsTakeCopy : public view_listener_t
+void handle_take_copy()
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true;
-
- const LLUUID& category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT);
- derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id);
-
- return true;
- }
-};
+ if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return;
+ const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
+ derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id);
+}
// You can return an object to its owner if it is on your land.
class LLObjectReturn : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true;
mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
- LLNotifications::instance().add("ReturnToOwner", LLSD(), LLSD(), boost::bind(&LLObjectReturn::onReturnToOwner, this, _1, _2));
+ LLNotificationsUtil::add("ReturnToOwner", LLSD(), LLSD(), boost::bind(&LLObjectReturn::onReturnToOwner, this, _1, _2));
return true;
}
bool onReturnToOwner(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
// Ignore category ID for this derez destination.
@@ -3637,7 +4165,7 @@ protected:
// over land you own.
class LLObjectEnableReturn : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
#ifdef HACKED_GODLIKE_VIEWER
bool new_value = true;
@@ -3674,15 +4202,14 @@ class LLObjectEnableReturn : public view_listener_t
}
}
#endif
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
void force_take_copy(void*)
{
if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return;
- const LLUUID& category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT);
+ const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
derez_objects(DRD_FORCE_TO_GOD_INVENTORY, category_id);
}
@@ -3743,15 +4270,14 @@ void handle_take()
if(category_id.notNull())
{
// check trash
- LLUUID trash;
- trash = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
if(category_id == trash || gInventory.isObjectDescendentOf(category_id, trash))
{
category_id.setNull();
}
// check library
- if(gInventory.isObjectDescendentOf(category_id, gInventoryLibraryRoot))
+ if(gInventory.isObjectDescendentOf(category_id, gInventory.getLibraryRootFolderID()))
{
category_id.setNull();
}
@@ -3760,14 +4286,14 @@ void handle_take()
}
if(category_id.isNull())
{
- category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT);
+ category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
}
LLSD payload;
payload["folder_id"] = category_id;
LLNotification::Params params("ConfirmObjectTakeLock");
- params.payload(payload)
- .functor(confirm_take);
+ params.payload(payload);
+ params.functor.function(confirm_take);
if(locked_but_takeable_object ||
!you_own_everything)
@@ -3775,7 +4301,6 @@ void handle_take()
if(locked_but_takeable_object && you_own_everything)
{
params.name("ConfirmObjectTakeLock");
-
}
else if(!locked_but_takeable_object && !you_own_everything)
{
@@ -3796,7 +4321,7 @@ void handle_take()
bool confirm_take(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if(enable_take() && (option == 0))
{
derez_objects(DRD_TAKE_INTO_AGENT_INVENTORY, notification["payload"]["folder_id"].asUUID());
@@ -3846,50 +4371,56 @@ BOOL enable_take()
return FALSE;
}
-class LLToolsBuyOrTake : public view_listener_t
+
+void handle_buy_or_take()
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
{
- if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
- {
- return true;
- }
+ return;
+ }
- if (is_selection_buy_not_take())
- {
- S32 total_price = selection_price();
+ if (is_selection_buy_not_take())
+ {
+ S32 total_price = selection_price();
- if (total_price <= gStatusBar->getBalance() || total_price == 0)
- {
- handle_buy(NULL);
- }
- else
- {
- LLFloaterBuyCurrency::buyCurrency(
- "Buying this costs", total_price);
- }
+ if (total_price <= gStatusBar->getBalance() || total_price == 0)
+ {
+ handle_buy();
}
else
{
- handle_take();
+ LLFloaterBuyCurrency::buyCurrency(
+ "Buying this costs", total_price);
}
- return true;
}
-};
+ else
+ {
+ handle_take();
+ }
+}
+
+bool visible_buy_object()
+{
+ return is_selection_buy_not_take() && enable_buy_object();
+}
+
+bool visible_take_object()
+{
+ return !is_selection_buy_not_take() && enable_take();
+}
class LLToolsEnableBuyOrTake : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool is_buy = is_selection_buy_not_take();
- bool new_value = is_buy ? enable_buy(NULL) : enable_take();
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
+ bool new_value = is_buy ? enable_buy_object() : enable_take();
// Update label
std::string label;
std::string buy_text;
std::string take_text;
- std::string param = userdata["data"].asString();
+ std::string param = userdata.asString();
std::string::size_type offset = param.find(",");
if (offset != param.npos)
{
@@ -3907,7 +4438,7 @@ class LLToolsEnableBuyOrTake : public view_listener_t
gMenuHolder->childSetText("Pie Object Take", label);
gMenuHolder->childSetText("Menu Object Take", label);
- return true;
+ return new_value;
}
};
@@ -3962,45 +4493,39 @@ S32 selection_price()
return total_price;
}
-
+/*
bool callback_show_buy_currency(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
- llinfos << "Loading page " << BUY_CURRENCY_URL << llendl;
- LLWeb::loadURL(BUY_CURRENCY_URL);
+ llinfos << "Loading page " << LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL") << llendl;
+ LLWeb::loadURL(LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL"));
}
return false;
}
-
+*/
void show_buy_currency(const char* extra)
{
// Don't show currency web page for branded clients.
-
+/*
std::ostringstream mesg;
if (extra != NULL)
{
mesg << extra << "\n \n";
}
- mesg << "Go to " << BUY_CURRENCY_URL << "\nfor information on purchasing currency?";
-
+ mesg << "Go to " << LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL")<< "\nfor information on purchasing currency?";
+*/
LLSD args;
if (extra != NULL)
{
args["EXTRA"] = extra;
}
- args["URL"] = BUY_CURRENCY_URL;
- LLNotifications::instance().add("PromptGoToCurrencyPage", args, LLSD(), callback_show_buy_currency);
+ LLNotificationsUtil::add("PromptGoToCurrencyPage", args);//, LLSD(), callback_show_buy_currency);
}
-void handle_buy_currency(void*)
-{
-// LLFloaterBuyCurrency::buyCurrency();
-}
-
-void handle_buy(void*)
+void handle_buy()
{
if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return;
@@ -4018,14 +4543,20 @@ void handle_buy(void*)
}
}
-class LLObjectBuy : public view_listener_t
+bool anyone_copy_selection(LLSelectNode* nodep)
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- handle_buy(NULL);
- return true;
- }
-};
+ bool perm_copy = (bool)(nodep->getObject()->permCopy());
+ bool all_copy = (bool)(nodep->mPermissions->getMaskEveryone() & PERM_COPY);
+ return perm_copy && all_copy;
+}
+
+bool for_sale_selection(LLSelectNode* nodep)
+{
+ return nodep->mSaleInfo.isForSale()
+ && nodep->mPermissions->getMaskOwner() & PERM_TRANSFER
+ && (nodep->mPermissions->getMaskOwner() & PERM_COPY
+ || nodep->mSaleInfo.getSaleType() != LLSaleInfo::FS_COPY);
+}
BOOL sitting_on_selection()
{
@@ -4053,12 +4584,24 @@ BOOL sitting_on_selection()
return FALSE;
}
- return (avatar->mIsSitting && avatar->getRoot() == root_object);
+ return (avatar->isSitting() && avatar->getRoot() == root_object);
}
+class LLToolsSaveToInventory : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ if(enable_save_into_inventory(NULL))
+ {
+ derez_objects(DRD_SAVE_INTO_AGENT_INVENTORY, LLUUID::null);
+ }
+ return true;
+ }
+};
+
class LLToolsSaveToObjectInventory : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
if(node && (node->mValid) && (!node->mFromTaskID.isNull()))
@@ -4073,7 +4616,7 @@ class LLToolsSaveToObjectInventory : public view_listener_t
// Round the position of all root objects to the grid
class LLToolsSnapObjectXY : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
F64 snap_size = (F64)gSavedSettings.getF32("GridResolution");
@@ -4117,6 +4660,96 @@ class LLToolsSnapObjectXY : public view_listener_t
}
};
+// Determine if the option to cycle between linked prims is shown
+class LLToolsEnableSelectNextPart : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = (gSavedSettings.getBOOL("EditLinkedParts") &&
+ !LLSelectMgr::getInstance()->getSelection()->isEmpty());
+ return new_value;
+ }
+};
+
+// Cycle selection through linked children in selected object.
+// FIXME: Order of children list is not always the same as sim's idea of link order. This may confuse
+// resis. Need link position added to sim messages to address this.
+class LLToolsSelectNextPart : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ S32 object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
+ if (gSavedSettings.getBOOL("EditLinkedParts") && object_count)
+ {
+ LLViewerObject* selected = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+ if (selected && selected->getRootEdit())
+ {
+ bool fwd = (userdata.asString() == "next");
+ bool prev = (userdata.asString() == "previous");
+ bool ifwd = (userdata.asString() == "includenext");
+ bool iprev = (userdata.asString() == "includeprevious");
+ LLViewerObject* to_select = NULL;
+ LLViewerObject::child_list_t children = selected->getRootEdit()->getChildren();
+ children.push_front(selected->getRootEdit()); // need root in the list too
+
+ for (LLViewerObject::child_list_t::iterator iter = children.begin(); iter != children.end(); ++iter)
+ {
+ if ((*iter)->isSelected())
+ {
+ if (object_count > 1 && (fwd || prev)) // multiple selection, find first or last selected if not include
+ {
+ to_select = *iter;
+ if (fwd)
+ {
+ // stop searching if going forward; repeat to get last hit if backward
+ break;
+ }
+ }
+ else if ((object_count == 1) || (ifwd || iprev)) // single selection or include
+ {
+ if (fwd || ifwd)
+ {
+ ++iter;
+ while (iter != children.end() && ((*iter)->isAvatar() || (ifwd && (*iter)->isSelected())))
+ {
+ ++iter; // skip sitting avatars and selected if include
+ }
+ }
+ else // backward
+ {
+ iter = (iter == children.begin() ? children.end() : iter);
+ --iter;
+ while (iter != children.begin() && ((*iter)->isAvatar() || (iprev && (*iter)->isSelected())))
+ {
+ --iter; // skip sitting avatars and selected if include
+ }
+ }
+ iter = (iter == children.end() ? children.begin() : iter);
+ to_select = *iter;
+ break;
+ }
+ }
+ }
+
+ if (to_select)
+ {
+ if (gFocusMgr.childHasKeyboardFocus(gFloaterTools))
+ {
+ gFocusMgr.setKeyboardFocus(NULL); // force edit toolbox to commit any changes
+ }
+ if (fwd || prev)
+ {
+ LLSelectMgr::getInstance()->deselectAll();
+ }
+ LLSelectMgr::getInstance()->selectObjectOnly(to_select);
+ return true;
+ }
+ }
+ }
+ return true;
+ }
+};
+
// in order to link, all objects must have the same owner, and the
// agent must have the ability to modify all of the objects. However,
// we're not answering that question with this method. The question
@@ -4127,7 +4760,7 @@ class LLToolsSnapObjectXY : public view_listener_t
// reasonable expectation for the link to work, but it will fail.
class LLToolsEnableLink : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = false;
// check if there are at least 2 objects selected, and that the
@@ -4149,18 +4782,17 @@ class LLToolsEnableLink : public view_listener_t
new_value = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly);
}
}
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
class LLToolsLink : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
if(!LLSelectMgr::getInstance()->selectGetAllRootsValid())
{
- LLNotifications::instance().add("UnableToLinkWhileDownloading");
+ LLNotificationsUtil::add("UnableToLinkWhileDownloading");
return true;
}
@@ -4171,18 +4803,18 @@ class LLToolsLink : public view_listener_t
args["COUNT"] = llformat("%d", object_count);
int max = MAX_CHILDREN_PER_TASK+1;
args["MAX"] = llformat("%d", max);
- LLNotifications::instance().add("UnableToLinkObjects", args);
+ LLNotificationsUtil::add("UnableToLinkObjects", args);
return true;
}
if(LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() < 2)
{
- LLNotifications::instance().add("CannotLinkIncompleteSet");
+ LLNotificationsUtil::add("CannotLinkIncompleteSet");
return true;
}
if(!LLSelectMgr::getInstance()->selectGetRootsModify())
{
- LLNotifications::instance().add("CannotLinkModify");
+ LLNotificationsUtil::add("CannotLinkModify");
return true;
}
LLUUID owner_id;
@@ -4192,7 +4824,7 @@ class LLToolsLink : public view_listener_t
// we don't actually care if you're the owner, but novices are
// the most likely to be stumped by this one, so offer the
// easiest and most likely solution.
- LLNotifications::instance().add("CannotLinkDifferentOwners");
+ LLNotificationsUtil::add("CannotLinkDifferentOwners");
return true;
}
LLSelectMgr::getInstance()->sendLink();
@@ -4202,19 +4834,18 @@ class LLToolsLink : public view_listener_t
class LLToolsEnableUnlink : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = LLSelectMgr::getInstance()->selectGetAllRootsValid() &&
LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() &&
!LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject()->isAttachment();
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
class LLToolsUnlink : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
LLSelectMgr::getInstance()->sendDelink();
return true;
@@ -4224,7 +4855,7 @@ class LLToolsUnlink : public view_listener_t
class LLToolsStopAllAnimations : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
gAgent.stopCurrentAnimations();
return true;
@@ -4233,7 +4864,7 @@ class LLToolsStopAllAnimations : public view_listener_t
class LLToolsReleaseKeys : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
gAgent.forceReleaseControls();
@@ -4243,58 +4874,25 @@ class LLToolsReleaseKeys : public view_listener_t
class LLToolsEnableReleaseKeys : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- gMenuHolder->findControl(userdata["control"].asString())->setValue( gAgent.anyControlGrabbed() );
- return true;
+ return gAgent.anyControlGrabbed();
}
};
-//void handle_hinge(void*)
-//{
-// LLSelectMgr::getInstance()->sendHinge(1);
-//}
-
-//void handle_ptop(void*)
-//{
-// LLSelectMgr::getInstance()->sendHinge(2);
-//}
-
-//void handle_lptop(void*)
-//{
-// LLSelectMgr::getInstance()->sendHinge(3);
-//}
-
-//void handle_wheel(void*)
-//{
-// LLSelectMgr::getInstance()->sendHinge(4);
-//}
-
-//void handle_dehinge(void*)
-//{
-// LLSelectMgr::getInstance()->sendDehinge();
-//}
-
-//BOOL enable_dehinge(void*)
-//{
-// LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject();
-// return obj && !obj->isAttachment();
-//}
-
class LLEditEnableCut : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canCut();
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
class LLEditCut : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
if( LLEditMenuHandler::gEditMenuHandler )
{
@@ -4306,17 +4904,16 @@ class LLEditCut : public view_listener_t
class LLEditEnableCopy : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canCopy();
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
class LLEditCopy : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
if( LLEditMenuHandler::gEditMenuHandler )
{
@@ -4328,17 +4925,16 @@ class LLEditCopy : public view_listener_t
class LLEditEnablePaste : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canPaste();
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
class LLEditPaste : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
if( LLEditMenuHandler::gEditMenuHandler )
{
@@ -4350,17 +4946,16 @@ class LLEditPaste : public view_listener_t
class LLEditEnableDelete : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete();
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
class LLEditDelete : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
// If a text field can do a deletion, it gets precedence over deleting
// an object in the world.
@@ -4374,43 +4969,29 @@ class LLEditDelete : public view_listener_t
// When deleting an object we may not actually be done
// Keep selection so we know what to delete when confirmation is needed about the delete
- gPieObject->hide(TRUE);
+ gMenuObject->hide();
return true;
}
};
-class LLObjectEnableDelete : public view_listener_t
+bool enable_object_delete()
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- bool new_value =
+ bool new_value =
#ifdef HACKED_GODLIKE_VIEWER
- TRUE;
+ TRUE;
#else
# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
- (!LLViewerLogin::getInstance()->isInProductionGrid()
- && gAgent.isGodlike()) ||
+ (!LLViewerLogin::getInstance()->isInProductionGrid()
+ && gAgent.isGodlike()) ||
# endif
- LLSelectMgr::getInstance()->canDoDelete();
+ LLSelectMgr::getInstance()->canDoDelete();
#endif
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
- }
-};
+ return new_value;
+}
-class LLEditSearch : public view_listener_t
+void handle_object_delete()
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- LLFloaterDirectory::toggleFind(NULL);
- return true;
- }
-};
-class LLObjectDelete : public view_listener_t
-{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
if (LLSelectMgr::getInstance())
{
LLSelectMgr::getInstance()->doDelete();
@@ -4421,10 +5002,9 @@ class LLObjectDelete : public view_listener_t
// When deleting an object we may not actually be done
// Keep selection so we know what to delete when confirmation is needed about the delete
- gPieObject->hide(TRUE);
- return true;
- }
-};
+ gMenuObject->hide();
+ return;
+}
void handle_force_delete(void*)
{
@@ -4433,38 +5013,35 @@ void handle_force_delete(void*)
class LLViewEnableJoystickFlycam : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = (gSavedSettings.getBOOL("JoystickEnabled") && gSavedSettings.getBOOL("JoystickFlycamEnabled"));
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
class LLViewEnableLastChatter : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
// *TODO: add check that last chatter is in range
bool new_value = (gAgent.cameraThirdPerson() && gAgent.getLastChatter().notNull());
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
class LLEditEnableDeselect : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDeselect();
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
class LLEditDeselect : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
if( LLEditMenuHandler::gEditMenuHandler )
{
@@ -4476,18 +5053,17 @@ class LLEditDeselect : public view_listener_t
class LLEditEnableSelectAll : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canSelectAll();
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
class LLEditSelectAll : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
if( LLEditMenuHandler::gEditMenuHandler )
{
@@ -4500,17 +5076,16 @@ class LLEditSelectAll : public view_listener_t
class LLEditEnableUndo : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canUndo();
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
class LLEditUndo : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canUndo() )
{
@@ -4522,17 +5097,16 @@ class LLEditUndo : public view_listener_t
class LLEditEnableRedo : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canRedo();
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
class LLEditRedo : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canRedo() )
{
@@ -4570,35 +5144,42 @@ void print_agent_nvpairs(void*)
void show_debug_menus()
{
- // this can get called at login screen where there is no menu so only toggle it if one exists
+ // this might get called at login screen where there is no menu so only toggle it if one exists
if ( gMenuBarView )
{
BOOL debug = gSavedSettings.getBOOL("UseDebugMenus");
+ BOOL qamode = gSavedSettings.getBOOL("QAMode");
+
+ gMenuBarView->setItemVisible("Advanced", debug);
+// gMenuBarView->setItemEnabled("Advanced", debug); // Don't disable Advanced keyboard shortcuts when hidden
- if(debug)
- {
- LLFirstUse::useDebugMenus();
- }
+ gMenuBarView->setItemVisible("Debug", qamode);
+ gMenuBarView->setItemEnabled("Debug", qamode);
- gMenuBarView->setItemVisible(CLIENT_MENU_NAME, debug);
- gMenuBarView->setItemEnabled(CLIENT_MENU_NAME, debug);
+ gMenuBarView->setItemVisible("Develop", qamode);
+ gMenuBarView->setItemEnabled("Develop", qamode);
// Server ('Admin') menu hidden when not in godmode.
- const bool show_server_menu = debug && (gAgent.getGodLevel() > GOD_NOT);
- gMenuBarView->setItemVisible(SERVER_MENU_NAME, show_server_menu);
- gMenuBarView->setItemEnabled(SERVER_MENU_NAME, show_server_menu);
-
- //gMenuBarView->setItemVisible("DebugOptions", visible);
- //gMenuBarView->setItemVisible(std::string(AVI_TOOLS), visible);
-
- gMenuBarView->arrange(); // clean-up positioning
- };
+ const bool show_server_menu = (gAgent.getGodLevel() > GOD_NOT || (debug && gAgent.getAdminOverride()));
+ gMenuBarView->setItemVisible("Admin", show_server_menu);
+ gMenuBarView->setItemEnabled("Admin", show_server_menu);
+ }
+ if (gLoginMenuBarView)
+ {
+ BOOL debug = gSavedSettings.getBOOL("UseDebugMenus");
+ gLoginMenuBarView->setItemVisible("Debug", debug);
+ gLoginMenuBarView->setItemEnabled("Debug", debug);
+ }
}
void toggle_debug_menus(void*)
{
BOOL visible = ! gSavedSettings.getBOOL("UseDebugMenus");
gSavedSettings.setBOOL("UseDebugMenus", visible);
+ if(visible)
+ {
+ //LLFirstUse::useDebugMenus();
+ }
show_debug_menus();
}
@@ -4640,27 +5221,12 @@ void toggle_debug_menus(void*)
// gExportDialog = LLUploadDialog::modalUploadDialog("Exporting selected objects...");
// }
+//
-BOOL menu_check_build_tool( void* user_data )
-{
- S32 index = (intptr_t) user_data;
- return LLToolMgr::getInstance()->getCurrentToolset()->isToolSelected( index );
-}
-
-void handle_reload_settings(void*)
-{
- gSavedSettings.resetToDefaults();
- gSavedSettings.loadFromFile(gSavedSettings.getString("ClientSettingsFile"));
-
- llinfos << "Loading colors from colors.xml" << llendl;
- std::string color_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"colors.xml");
- gColors.resetToDefaults();
- gColors.loadFromFileLegacy(color_file, FALSE, TYPE_COL4U);
-}
class LLWorldSetHomeLocation : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
// we just send the message and let the server check for failure cases
// server will echo back a "Home position set." alert if it succeeds
@@ -4672,7 +5238,7 @@ class LLWorldSetHomeLocation : public view_listener_t
class LLWorldTeleportHome : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
gAgent.teleportHome();
return true;
@@ -4681,7 +5247,7 @@ class LLWorldTeleportHome : public view_listener_t
class LLWorldAlwaysRun : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
// as well as altering the default walk-vs-run state,
// we also change the *current* walk-vs-run state.
@@ -4699,23 +5265,25 @@ class LLWorldAlwaysRun : public view_listener_t
// tell the simulator.
gAgent.sendWalkRun(gAgent.getAlwaysRun());
+ // Update Movement Controls according to AlwaysRun mode
+ LLFloaterMove::setAlwaysRunMode(gAgent.getAlwaysRun());
+
return true;
}
};
class LLWorldCheckAlwaysRun : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = gAgent.getAlwaysRun();
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
class LLWorldSetAway : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
if (gAgent.getAFK())
{
@@ -4731,7 +5299,7 @@ class LLWorldSetAway : public view_listener_t
class LLWorldSetBusy : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
if (gAgent.getBusy())
{
@@ -4740,125 +5308,89 @@ class LLWorldSetBusy : public view_listener_t
else
{
gAgent.setBusy();
- LLNotifications::instance().add("BusyModeSet");
+ LLNotificationsUtil::add("BusyModeSet");
}
return true;
}
};
-bool can_create_landmark()
-{
- BOOL can = FALSE;
-
- LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
- if (agent_parcel)
- {
-
- if (agent_parcel->getAllowLandmark()
- || LLViewerParcelMgr::isParcelOwnedByAgent(agent_parcel, GP_LAND_ALLOW_LANDMARK))
- {
- can = TRUE;
- }
- }
-
- return can;
-}
-
class LLWorldCreateLandmark : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- if (!can_create_landmark())
- {
- LLNotifications::instance().add("CannotCreateLandmarkNotOwner");
- return true;
- }
+ LLSideTray::getInstance()->showPanel("panel_places", LLSD().with("type", "create_landmark"));
- LLUUID folder_id;
- folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK);
- std::string pos_string;
- gAgent.buildLocationString(pos_string);
-
- create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
- folder_id, LLTransactionID::tnull,
- pos_string, pos_string, // name, desc
- LLAssetType::AT_LANDMARK,
- LLInventoryType::IT_LANDMARK,
- NOT_WEARABLE, PERM_ALL,
- new LLCreateLandmarkCallback);
return true;
}
};
-class LLToolsLookAtSelection : public view_listener_t
+void handle_look_at_selection(const LLSD& param)
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ const F32 PADDING_FACTOR = 2.f;
+ BOOL zoom = (param.asString() == "zoom");
+ if (!LLSelectMgr::getInstance()->getSelection()->isEmpty())
{
- const F32 PADDING_FACTOR = 2.f;
- BOOL zoom = (userdata.asString() == "zoom");
- if (!LLSelectMgr::getInstance()->getSelection()->isEmpty())
- {
- gAgent.setFocusOnAvatar(FALSE, ANIMATE);
+ gAgent.setFocusOnAvatar(FALSE, ANIMATE);
- LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection();
- F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView());
- F32 distance = selection_bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view);
+ LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection();
+ F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView());
+ F32 distance = selection_bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view);
- LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - selection_bbox.getCenterAgent();
- obj_to_cam.normVec();
+ LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - selection_bbox.getCenterAgent();
+ obj_to_cam.normVec();
- LLUUID object_id;
- if (LLSelectMgr::getInstance()->getSelection()->getPrimaryObject())
- {
- object_id = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()->mID;
- }
- if (zoom)
- {
- gAgent.setCameraPosAndFocusGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal() + LLVector3d(obj_to_cam * distance),
- LLSelectMgr::getInstance()->getSelectionCenterGlobal(),
- object_id );
- }
- else
- {
- gAgent.setFocusGlobal( LLSelectMgr::getInstance()->getSelectionCenterGlobal(), object_id );
- }
+ LLUUID object_id;
+ if (LLSelectMgr::getInstance()->getSelection()->getPrimaryObject())
+ {
+ object_id = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()->mID;
+ }
+ if (zoom)
+ {
+ gAgent.setCameraPosAndFocusGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal() + LLVector3d(obj_to_cam * distance),
+ LLSelectMgr::getInstance()->getSelectionCenterGlobal(),
+ object_id );
+ }
+ else
+ {
+ gAgent.setFocusGlobal( LLSelectMgr::getInstance()->getSelectionCenterGlobal(), object_id );
}
- return true;
}
-};
-
-void callback_invite_to_group(LLUUID group_id, void *user_data)
-{
- std::vector<LLUUID> agent_ids;
- agent_ids.push_back(*(LLUUID *)user_data);
-
- LLFloaterGroupInvite::showForGroup(group_id, &agent_ids);
}
-void invite_to_group(const LLUUID& dest_id)
+void handle_zoom_to_object(LLUUID object_id)
{
- LLViewerObject* dest = gObjectList.findObject(dest_id);
- if(dest && dest->isAvatar())
+ const F32 PADDING_FACTOR = 2.f;
+
+ LLViewerObject* object = gObjectList.findObject(object_id);
+
+ if (object)
{
- LLFloaterGroupPicker* widget;
- widget = LLFloaterGroupPicker::showInstance(LLSD(gAgent.getID()));
- if (widget)
- {
- widget->center();
- widget->setPowersMask(GP_MEMBER_INVITE);
- widget->setSelectCallback(callback_invite_to_group, (void *)&dest_id);
- }
+ gAgent.setFocusOnAvatar(FALSE, ANIMATE);
+
+ LLBBox bbox = object->getBoundingBoxAgent() ;
+ F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView());
+ F32 distance = bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view);
+
+ LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - bbox.getCenterAgent();
+ obj_to_cam.normVec();
+
+
+ LLVector3d object_center_global = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent());
+
+ gAgent.setCameraPosAndFocusGlobal(object_center_global + LLVector3d(obj_to_cam * distance),
+ object_center_global,
+ object_id );
}
}
class LLAvatarInviteToGroup : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
if(avatar)
{
- invite_to_group(avatar->getID());
+ LLAvatarActions::inviteToGroup(avatar->getID());
}
return true;
}
@@ -4866,10 +5398,10 @@ class LLAvatarInviteToGroup : public view_listener_t
class LLAvatarAddFriend : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
- if(avatar && !is_agent_friend(avatar->getID()))
+ if(avatar && !LLAvatarActions::isFriend(avatar->getID()))
{
request_friendship(avatar->getID());
}
@@ -4877,15 +5409,28 @@ class LLAvatarAddFriend : public view_listener_t
}
};
-bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle)
+class LLAvatarAddContact : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+ if(avatar)
+ {
+ create_inventory_callingcard(avatar->getID());
+ }
+ return true;
+ }
+};
+
+bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0)
{
gAgent.clearBusy();
}
- LLViewerObject* objectp = handle->getPrimaryObject();
+ LLViewerObject* objectp = selection->getPrimaryObject();
// Show avatar's name if paying attachment
if (objectp && objectp->isAttachment())
@@ -4900,23 +5445,23 @@ bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjec
{
if (objectp->isAvatar())
{
- const BOOL is_group = FALSE;
- LLFloaterPay::payDirectly(&give_money,
+ const bool is_group = false;
+ LLFloaterPayUtil::payDirectly(&give_money,
objectp->getID(),
is_group);
}
else
{
- LLFloaterPay::payViaObject(&give_money, objectp->getID());
+ LLFloaterPayUtil::payViaObject(&give_money, selection);
}
}
return false;
}
-bool handle_give_money_dialog()
+void handle_give_money_dialog()
{
LLNotification::Params params("BusyModePay");
- params.functor(boost::bind(complete_give_money, _1, _2, LLSelectMgr::getInstance()->getSelection()));
+ params.functor.function(boost::bind(complete_give_money, _1, _2, LLSelectMgr::getInstance()->getSelection()));
if (gAgent.getBusy())
{
@@ -4927,43 +5472,32 @@ bool handle_give_money_dialog()
{
LLNotifications::instance().forceResponse(params, 1);
}
- return true;
}
-class LLPayObject : public view_listener_t
+bool enable_pay_avatar()
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- return handle_give_money_dialog();
- }
-};
+ LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ LLVOAvatar* avatar = find_avatar_from_object(obj);
+ return (avatar != NULL);
+}
-class LLEnablePayObject : public view_listener_t
+bool enable_pay_object()
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if( object )
{
- LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
- bool new_value = (avatar != NULL);
- if (!new_value)
+ LLViewerObject *parent = (LLViewerObject *)object->getParent();
+ if((object->flagTakesMoney()) || (parent && parent->flagTakesMoney()))
{
- LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if( object )
- {
- LLViewerObject *parent = (LLViewerObject *)object->getParent();
- if((object->flagTakesMoney()) || (parent && parent->flagTakesMoney()))
- {
- new_value = true;
- }
- }
+ return true;
}
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
}
-};
+ return false;
+}
class LLObjectEnableSitOrStand : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = false;
LLViewerObject* dest_object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
@@ -4975,13 +5509,11 @@ class LLObjectEnableSitOrStand : public view_listener_t
new_value = true;
}
}
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
-
// Update label
std::string label;
std::string sit_text;
std::string stand_text;
- std::string param = userdata["data"].asString();
+ std::string param = userdata.asString();
std::string::size_type offset = param.find(",");
if (offset != param.npos)
{
@@ -5006,15 +5538,10 @@ class LLObjectEnableSitOrStand : public view_listener_t
}
gMenuHolder->childSetText("Object Sit", label);
- return true;
+ return new_value;
}
};
-void edit_ui(void*)
-{
- LLFloater::setEditModeEnabled(!LLFloater::getEditModeEnabled());
-}
-
void dump_select_mgr(void*)
{
LLSelectMgr::getInstance()->dump();
@@ -5025,29 +5552,6 @@ void dump_inventory(void*)
gInventory.dumpInventory();
}
-// forcibly unlock an object
-void handle_force_unlock(void*)
-{
- // First, make it public.
- LLSelectMgr::getInstance()->sendOwner(LLUUID::null, LLUUID::null, TRUE);
-
- // Second, lie to the viewer and mark it editable and unowned
-
- struct f : public LLSelectedObjectFunctor
- {
- virtual bool apply(LLViewerObject* object)
- {
- object->mFlags |= FLAGS_OBJECT_MOVE;
- object->mFlags |= FLAGS_OBJECT_MODIFY;
- object->mFlags |= FLAGS_OBJECT_COPY;
-
- object->mFlags &= ~FLAGS_OBJECT_ANY_OWNER;
- object->mFlags &= ~FLAGS_OBJECT_YOU_OWNER;
- return true;
- }
- } func;
- LLSelectMgr::getInstance()->getSelection()->applyToObjects(&func);
-}
void handle_dump_followcam(void*)
{
@@ -5064,224 +5568,73 @@ void handle_viewer_disable_message_log(void*)
gMessageSystem->stopLogging();
}
-// TomY TODO: Move!
-class LLShowFloater : public view_listener_t
+void handle_customize_avatar()
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ if (gAgentWearables.areWearablesLoaded())
+ {
+ gAgent.changeCameraToCustomizeAvatar();
+ }
+}
+
+void handle_report_abuse()
+{
+ // Prevent menu from appearing in screen shot.
+ gMenuHolder->hideMenus();
+ LLFloaterReporter::showFromMenu(COMPLAINT_REPORT);
+}
+
+void handle_buy_currency()
+{
+ LLFloaterBuyCurrency::buyCurrency();
+}
+
+
+
+class LLFloaterVisible : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
{
std::string floater_name = userdata.asString();
- if (floater_name == "gestures")
- {
- LLFloaterGesture::toggleVisibility();
- }
- else if (floater_name == "appearance")
- {
- if (gAgent.areWearablesLoaded())
- {
- gAgent.changeCameraToCustomizeAvatar();
- }
- }
- else if (floater_name == "friends")
- {
- LLFloaterMyFriends::toggleInstance(0);
- }
- else if (floater_name == "preferences")
- {
- LLFloaterPreference::show(NULL);
- }
- else if (floater_name == "toolbar")
- {
- LLToolBar::toggle(NULL);
- }
- else if (floater_name == "chat history")
- {
- LLFloaterChat::toggleInstance(LLSD());
- }
- else if (floater_name == "im")
- {
- LLFloaterChatterBox::toggleInstance(LLSD());
- }
- else if (floater_name == "inventory")
- {
- LLInventoryView::toggleVisibility(NULL);
- }
- else if (floater_name == "mute list")
- {
- LLFloaterMute::toggleInstance();
- }
- else if (floater_name == "camera controls")
- {
- LLFloaterCamera::toggleInstance();
- }
- else if (floater_name == "movement controls")
- {
- LLFloaterMove::toggleInstance();
- }
- else if (floater_name == "world map")
- {
- LLFloaterWorldMap::toggle(NULL);
- }
- else if (floater_name == "mini map")
- {
- LLFloaterMap::toggleInstance();
- }
- else if (floater_name == "stat bar")
- {
- LLFloaterStats::toggleInstance();
- }
- else if (floater_name == "my land")
+ bool new_value = false;
{
- LLFloaterLandHoldings::show(NULL);
+ new_value = LLFloaterReg::instanceVisible(floater_name);
}
- else if (floater_name == "about land")
- {
- if (LLViewerParcelMgr::getInstance()->selectionEmpty())
- {
- LLViewerParcelMgr::getInstance()->selectParcelAt(gAgent.getPositionGlobal());
- }
+ return new_value;
+ }
+};
- LLFloaterLand::showInstance();
- }
- else if (floater_name == "buy land")
- {
- if (LLViewerParcelMgr::getInstance()->selectionEmpty())
- {
- LLViewerParcelMgr::getInstance()->selectParcelAt(gAgent.getPositionGlobal());
- }
-
- LLViewerParcelMgr::getInstance()->startBuyLand();
- }
- else if (floater_name == "about region")
- {
- LLFloaterRegionInfo::showInstance();
- }
- else if (floater_name == "grid options")
- {
- LLFloaterBuildOptions::show(NULL);
- }
- else if (floater_name == "script errors")
- {
- LLFloaterScriptDebug::show(LLUUID::null);
- }
- else if (floater_name == "help f1")
- {
- gViewerHtmlHelp.show();
- }
- else if (floater_name == "help tutorial")
- {
- LLFloaterHUD::showHUD();
- }
- else if (floater_name == "complaint reporter")
- {
- // Prevent menu from appearing in screen shot.
- gMenuHolder->hideMenus();
- LLFloaterReporter::showFromMenu(COMPLAINT_REPORT);
- }
- else if (floater_name == "mean events")
- {
- if (!gNoRender)
- {
- LLFloaterBump::show(NULL);
- }
- }
- else if (floater_name == "lag meter")
- {
- LLFloaterLagMeter::showInstance();
- }
- else if (floater_name == "bug reporter")
- {
- // Prevent menu from appearing in screen shot.
- gMenuHolder->hideMenus();
- LLFloaterReporter::showFromMenu(BUG_REPORT);
- }
- else if (floater_name == "buy currency")
- {
- LLFloaterBuyCurrency::buyCurrency();
- }
- else if (floater_name == "about")
- {
- LLFloaterAbout::show(NULL);
- }
- else if (floater_name == "active speakers")
- {
- LLFloaterActiveSpeakers::toggleInstance(LLSD());
- }
- else if (floater_name == "beacons")
- {
- LLFloaterBeacons::toggleInstance(LLSD());
- }
- else if (floater_name == "perm prefs")
- {
- LLFloaterPerms::toggleInstance(LLSD());
- }
+class LLShowHelp : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string help_topic = userdata.asString();
+ LLViewerHelp* vhelp = LLViewerHelp::getInstance();
+ vhelp->showTopic(help_topic);
return true;
}
};
-class LLFloaterVisible : public view_listener_t
+class LLShowSidetrayPanel : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- std::string control_name = userdata["control"].asString();
- std::string floater_name = userdata["data"].asString();
- bool new_value = false;
- if (floater_name == "friends")
- {
- new_value = LLFloaterMyFriends::instanceVisible(0);
- }
- else if (floater_name == "communicate")
- {
- new_value = LLFloaterChatterBox::instanceVisible();
- }
- else if (floater_name == "toolbar")
- {
- new_value = LLToolBar::visible(NULL);
- }
- else if (floater_name == "chat history")
- {
- new_value = LLFloaterChat::instanceVisible();
- }
- else if (floater_name == "im")
- {
- new_value = LLFloaterMyFriends::instanceVisible(0);
- }
- else if (floater_name == "mute list")
- {
- new_value = LLFloaterMute::instanceVisible();
- }
- else if (floater_name == "camera controls")
+ std::string panel_name = userdata.asString();
+ // Open up either the sidepanel or new floater.
+ if (LLSideTray::getInstance()->isPanelActive(panel_name))
{
- new_value = LLFloaterCamera::instanceVisible();
+ LLFloaterInventory::showAgentInventory();
}
- else if (floater_name == "movement controls")
- {
- new_value = LLFloaterMove::instanceVisible();
- }
- else if (floater_name == "stat bar")
- {
- new_value = LLFloaterStats::instanceVisible();
- }
- else if (floater_name == "active speakers")
- {
- new_value = LLFloaterActiveSpeakers::instanceVisible(LLSD());
- }
- else if (floater_name == "beacons")
- {
- new_value = LLFloaterBeacons::instanceVisible(LLSD());
- }
- else if (floater_name == "inventory")
+ else
{
- LLInventoryView* iv = LLInventoryView::getActiveInventory();
- new_value = (NULL != iv && TRUE == iv->getVisible());
+ LLSideTray::getInstance()->showPanel(panel_name, LLSD());
}
- gMenuHolder->findControl(control_name)->setValue(new_value);
return true;
}
};
bool callback_show_url(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
LLWeb::loadURL(notification["payload"]["url"].asString());
@@ -5291,7 +5644,7 @@ bool callback_show_url(const LLSD& notification, const LLSD& response)
class LLPromptShowURL : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
std::string param = userdata.asString();
std::string::size_type offset = param.find(",");
@@ -5304,7 +5657,7 @@ class LLPromptShowURL : public view_listener_t
{
LLSD payload;
payload["url"] = url;
- LLNotifications::instance().add(alert, LLSD(), payload, callback_show_url);
+ LLNotificationsUtil::add(alert, LLSD(), payload, callback_show_url);
}
else
{
@@ -5321,7 +5674,7 @@ class LLPromptShowURL : public view_listener_t
bool callback_show_file(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
LLWeb::loadURL(notification["payload"]["url"]);
@@ -5331,7 +5684,7 @@ bool callback_show_file(const LLSD& notification, const LLSD& response)
class LLPromptShowFile : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
std::string param = userdata.asString();
std::string::size_type offset = param.find(",");
@@ -5342,7 +5695,7 @@ class LLPromptShowFile : public view_listener_t
LLSD payload;
payload["url"] = file;
- LLNotifications::instance().add(alert, LLSD(), payload, callback_show_file);
+ LLNotificationsUtil::add(alert, LLSD(), payload, callback_show_file);
}
else
{
@@ -5354,7 +5707,7 @@ class LLPromptShowFile : public view_listener_t
class LLShowAgentProfile : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
LLUUID agent_id;
if (userdata.asString() == "agent")
@@ -5377,50 +5730,15 @@ class LLShowAgentProfile : public view_listener_t
LLVOAvatar* avatar = find_avatar_from_object(agent_id);
if (avatar)
{
- LLFloaterAvatarInfo::show( avatar->getID() );
+ LLAvatarActions::showProfile(avatar->getID());
}
return true;
}
};
-class LLShowAgentGroups : public view_listener_t
-{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- LLFloaterMyFriends::toggleInstance(1);
- return true;
- }
-};
-
-void handle_focus(void *)
-{
- if (gDisconnected)
- {
- return;
- }
-
- if (gAgent.getFocusOnAvatar())
- {
- // zoom in if we're looking at the avatar
- gAgent.setFocusOnAvatar(FALSE, ANIMATE);
- gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick());
- gAgent.cameraZoomIn(0.666f);
- }
- else
- {
- gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick());
- }
-
- gViewerWindow->moveCursorToCenter();
-
- // Switch to camera toolset
-// LLToolMgr::getInstance()->setCurrentToolset(gCameraToolset);
- LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCamera::getInstance() );
-}
-
class LLLandEdit : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
if (gAgent.getFocusOnAvatar() && gSavedSettings.getBOOL("EditCameraMovement") )
{
@@ -5440,7 +5758,7 @@ class LLLandEdit : public view_listener_t
LLViewerParcelMgr::getInstance()->selectParcelAt( LLToolPie::getInstance()->getPick().mPosGlobal );
- gFloaterView->bringToFront( gFloaterTools );
+ LLFloaterReg::showInstance("build");
// Switch to land edit toolset
LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolSelectLand::getInstance() );
@@ -5450,15 +5768,14 @@ class LLLandEdit : public view_listener_t
class LLWorldEnableBuyLand : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = LLViewerParcelMgr::getInstance()->canAgentBuyParcel(
LLViewerParcelMgr::getInstance()->selectionEmpty()
? LLViewerParcelMgr::getInstance()->getAgentParcel()
: LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(),
false);
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
@@ -5468,26 +5785,14 @@ BOOL enable_buy_land(void*)
LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(), false);
}
-
-void handle_move(void*)
+void handle_buy_land()
{
- if (gAgent.getFocusOnAvatar())
- {
- // zoom in if we're looking at the avatar
- gAgent.setFocusOnAvatar(FALSE, ANIMATE);
- gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick());
-
- gAgent.cameraZoomIn(0.666f);
- }
- else
+ LLViewerParcelMgr* vpm = LLViewerParcelMgr::getInstance();
+ if (vpm->selectionEmpty())
{
- gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick());
+ vpm->selectParcelAt(gAgent.getPositionGlobal());
}
-
- gViewerWindow->moveCursorToCenter();
-
- LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
- LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolGrab::getInstance() );
+ vpm->startBuyLand();
}
class LLObjectAttachToAvatar : public view_listener_t
@@ -5496,7 +5801,7 @@ public:
static void setObjectSelection(LLObjectSelectionHandle selection) { sObjectSelection = selection; }
private:
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
setObjectSelection(LLSelectMgr::getInstance()->getSelection());
LLViewerObject* selectedObject = sObjectSelection->getFirstRootObject();
@@ -5521,12 +5826,12 @@ void near_attach_object(BOOL success, void *user_data)
{
if (success)
{
- LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data;
+ const LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data;
U8 attachment_id = 0;
if (attachment)
{
- for (LLVOAvatar::attachment_map_t::iterator iter = gAgent.getAvatarObject()->mAttachmentPoints.begin();
+ for (LLVOAvatar::attachment_map_t::const_iterator iter = gAgent.getAvatarObject()->mAttachmentPoints.begin();
iter != gAgent.getAvatarObject()->mAttachmentPoints.end(); ++iter)
{
if (iter->second == attachment)
@@ -5577,109 +5882,137 @@ void confirm_replace_attachment(S32 option, void* user_data)
}
}
-class LLAttachmentDrop : public view_listener_t
+void callback_attachment_drop(const LLSD& notification, const LLSD& response)
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ // Ensure user confirmed the drop
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option != 0) return;
+
+ // Called when the user clicked on an object attached to them
+ // and selected "Drop".
+ LLUUID object_id = notification["payload"]["object_id"].asUUID();
+ LLViewerObject *object = gObjectList.findObject(object_id);
+
+ if (!object)
{
- // Called when the user clicked on an object attached to them
- // and selected "Drop".
- LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (!object)
- {
- llwarns << "handle_drop_attachment() - no object to drop" << llendl;
- return true;
- }
+ llwarns << "handle_drop_attachment() - no object to drop" << llendl;
+ return;
+ }
- LLViewerObject *parent = (LLViewerObject*)object->getParent();
- while (parent)
+ LLViewerObject *parent = (LLViewerObject*)object->getParent();
+ while (parent)
+ {
+ if(parent->isAvatar())
{
- if(parent->isAvatar())
- {
- break;
- }
- object = parent;
- parent = (LLViewerObject*)parent->getParent();
+ break;
}
+ object = parent;
+ parent = (LLViewerObject*)parent->getParent();
+ }
- if (!object)
+ if (!object)
+ {
+ llwarns << "handle_detach() - no object to detach" << llendl;
+ return;
+ }
+
+ if (object->isAvatar())
+ {
+ llwarns << "Trying to detach avatar from avatar." << llendl;
+ return;
+ }
+
+ // reselect the object
+ LLSelectMgr::getInstance()->selectObjectAndFamily(object);
+
+ LLSelectMgr::getInstance()->sendDropAttachment();
+
+ return;
+}
+
+class LLAttachmentDrop : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLSD payload;
+ LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+
+ if (object)
{
- llwarns << "handle_detach() - no object to detach" << llendl;
- return true;
+ payload["object_id"] = object->getID();
}
-
- if (object->isAvatar())
+ else
{
- llwarns << "Trying to detach avatar from avatar." << llendl;
+ llwarns << "Drop object not found" << llendl;
return true;
}
- // The sendDropAttachment() method works on the list of selected
- // objects. Thus we need to clear the list, make sure it only
- // contains the object the user clicked, send the message,
- // then clear the list.
- LLSelectMgr::getInstance()->sendDropAttachment();
+ LLNotificationsUtil::add("AttachmentDrop", LLSD(), payload, &callback_attachment_drop);
return true;
}
};
// called from avatar pie menu
-void handle_detach_from_avatar(void* user_data)
-{
- LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data;
-
- LLViewerObject* attached_object = attachment->getObject();
-
- if (attached_object)
- {
- gMessageSystem->newMessage("ObjectDetach");
- gMessageSystem->nextBlockFast(_PREHASH_AgentData);
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
- gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-
- gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
- gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, attached_object->getLocalID());
- gMessageSystem->sendReliable( gAgent.getRegionHost() );
- }
-}
-
-void attach_label(std::string& label, void* user_data)
+class LLAttachmentDetachFromPoint : public view_listener_t
{
- LLViewerJointAttachment* attachmentp = (LLViewerJointAttachment*)user_data;
- if (attachmentp)
+ bool handleEvent(const LLSD& user_data)
{
- label = attachmentp->getName();
- if (attachmentp->getObject())
+ const LLViewerJointAttachment *attachment = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, user_data.asInteger(), (LLViewerJointAttachment*)NULL);
+ if (attachment->getNumObjects() > 0)
{
- LLViewerInventoryItem* itemp = gInventory.getItem(attachmentp->getItemID());
- if (itemp)
+ gMessageSystem->newMessage("ObjectDetach");
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+
+ for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator iter = attachment->mAttachedObjects.begin();
+ iter != attachment->mAttachedObjects.end();
+ iter++)
{
- label += std::string(" (") + itemp->getName() + std::string(")");
+ LLViewerObject *attached_object = (*iter);
+ gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
+ gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, attached_object->getLocalID());
}
+ gMessageSystem->sendReliable( gAgent.getRegionHost() );
}
+ return true;
}
-}
+};
-void detach_label(std::string& label, void* user_data)
+static bool onEnableAttachmentLabel(LLUICtrl* ctrl, const LLSD& data)
{
- LLViewerJointAttachment* attachmentp = (LLViewerJointAttachment*)user_data;
- if (attachmentp)
+ std::string label;
+ LLMenuItemGL* menu = dynamic_cast<LLMenuItemGL*>(ctrl);
+ if (menu)
{
- label = attachmentp->getName();
- if (attachmentp->getObject())
+ const LLViewerJointAttachment *attachment = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, data["index"].asInteger(), (LLViewerJointAttachment*)NULL);
+ if (attachment)
{
- LLViewerInventoryItem* itemp = gInventory.getItem(attachmentp->getItemID());
- if (itemp)
+ label = data["label"].asString();
+ for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- label += std::string(" (") + itemp->getName() + std::string(")");
+ const LLViewerObject* attached_object = (*attachment_iter);
+ if (attached_object)
+ {
+ LLViewerInventoryItem* itemp = gInventory.getItem(attached_object->getItemID());
+ if (itemp)
+ {
+ label += std::string(" (") + itemp->getName() + std::string(")");
+ break;
+ }
+ }
}
}
+ menu->setLabel(label);
}
+ return true;
}
-
class LLAttachmentDetach : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
// Called when the user clicked on an object attached to them
// and selected "Detach".
@@ -5739,7 +6072,7 @@ public:
protected:
virtual void done()
{
- gPieAttachment->buildDrawLabels();
+ gMenuAttachmentSelf->buildDrawLabels();
gInventory.removeObserver(this);
delete this;
}
@@ -5748,9 +6081,9 @@ protected:
// You can only drop items on parcels where you can build.
class LLAttachmentEnableDrop : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- BOOL can_build = gAgent.isGodlike() || (LLViewerParcelMgr::getInstance()->agentCanBuild());
+ BOOL can_build = gAgent.isGodlike() || (LLViewerParcelMgr::getInstance()->allowAgentBuild());
//Add an inventory observer to only allow dropping the newly attached item
//once it exists in your inventory. Look at Jira 2422.
@@ -5763,50 +6096,60 @@ class LLAttachmentEnableDrop : public view_listener_t
// item is in your inventory
LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- LLViewerJointAttachment* attachment_pt = NULL;
+ LLViewerJointAttachment* attachment = NULL;
LLInventoryItem* item = NULL;
- if ( object )
+ // Do not enable drop if all faces of object are not enabled
+ if (object && LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES ))
{
S32 attachmentID = ATTACHMENT_ID_FROM_STATE(object->getState());
- attachment_pt = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL);
+ attachment = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL);
- if ( attachment_pt )
+ if (attachment)
{
- // make sure item is in your inventory (it could be a delayed attach message being sent from the sim)
- // so check to see if the item is in the inventory already
- item = gInventory.getItem(attachment_pt->getItemID());
-
- if ( !item )
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- // Item does not exist, make an observer to enable the pie menu
- // when the item finishes fetching worst case scenario
- // if a fetch is already out there (being sent from a slow sim)
- // we refetch and there are 2 fetches
- LLWornItemFetchedObserver* wornItemFetched = new LLWornItemFetchedObserver();
- LLInventoryFetchObserver::item_ref_t items; //add item to the inventory item to be fetched
-
- items.push_back(attachment_pt->getItemID());
-
- wornItemFetched->fetchItems(items);
- gInventory.addObserver(wornItemFetched);
+ // make sure item is in your inventory (it could be a delayed attach message being sent from the sim)
+ // so check to see if the item is in the inventory already
+ item = gInventory.getItem((*attachment_iter)->getItemID());
+ if (!item)
+ {
+ // Item does not exist, make an observer to enable the pie menu
+ // when the item finishes fetching worst case scenario
+ // if a fetch is already out there (being sent from a slow sim)
+ // we refetch and there are 2 fetches
+ LLWornItemFetchedObserver* wornItemFetched = new LLWornItemFetchedObserver();
+ LLInventoryFetchObserver::item_ref_t items; //add item to the inventory item to be fetched
+
+ items.push_back((*attachment_iter)->getItemID());
+
+ wornItemFetched->fetchItems(items);
+ gInventory.addObserver(wornItemFetched);
+ }
}
}
}
//now check to make sure that the item is actually in the inventory before we enable dropping it
- bool new_value = enable_detach(NULL) && can_build && item;
+ bool new_value = enable_detach() && can_build && item;
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
-BOOL enable_detach(void*)
+BOOL enable_detach(const LLSD&)
{
LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (!object) return FALSE;
- if (!object->isAttachment()) return FALSE;
+
+ // Only enable detach if all faces of object are selected
+ if (!object ||
+ !object->isAttachment() ||
+ !LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES ))
+ {
+ return FALSE;
+ }
// Find the avatar who owns this attachment
LLViewerObject* avatar = object;
@@ -5826,18 +6169,16 @@ BOOL enable_detach(void*)
class LLAttachmentEnableDetach : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- bool new_value = enable_detach(NULL);
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ bool new_value = enable_detach();
+ return new_value;
}
};
// Used to tell if the selected object can be attached to your avatar.
-BOOL object_selected_and_point_valid(void *user_data)
+BOOL object_selected_and_point_valid()
{
- //LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data;
LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
for (LLObjectSelection::root_iterator iter = selection->root_begin();
iter != selection->root_end(); iter++)
@@ -5859,6 +6200,7 @@ BOOL object_selected_and_point_valid(void *user_data)
return (selection->getRootObjectCount() == 1) &&
(selection->getFirstRootObject()->getPCode() == LL_PCODE_VOLUME) &&
selection->getFirstRootObject()->permYouOwner() &&
+ selection->getFirstRootObject()->flagObjectMove() &&
!((LLViewerObject*)selection->getFirstRootObject()->getRoot())->isAvatar() &&
(selection->getFirstRootObject()->getNVPair("AssetContainer") == NULL);
}
@@ -5866,7 +6208,7 @@ BOOL object_selected_and_point_valid(void *user_data)
BOOL object_is_wearable()
{
- if (!object_selected_and_point_valid(NULL))
+ if (!object_selected_and_point_valid())
{
return FALSE;
}
@@ -5888,62 +6230,45 @@ BOOL object_is_wearable()
}
-// Also for seeing if object can be attached. See above.
-class LLObjectEnableWear : public view_listener_t
+class LLAttachmentPointFilled : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& user_data)
{
- bool is_wearable = object_selected_and_point_valid(NULL);
- gMenuHolder->findControl(userdata["control"].asString())->setValue(is_wearable);
- return TRUE;
+ bool enable = false;
+ LLVOAvatar::attachment_map_t::iterator found_it = gAgent.getAvatarObject()->mAttachmentPoints.find(user_data.asInteger());
+ if (found_it != gAgent.getAvatarObject()->mAttachmentPoints.end())
+ {
+ enable = found_it->second->getNumObjects() > 0;
+ }
+ return enable;
}
};
-
-BOOL object_attached(void *user_data)
-{
- LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data;
-
- return attachment->getObject() != NULL;
-}
-
class LLAvatarSendIM : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
if(avatar)
{
- std::string name("IM");
- LLNameValue *first = avatar->getNVPair("FirstName");
- LLNameValue *last = avatar->getNVPair("LastName");
- if (first && last)
- {
- name.assign( first->getString() );
- name.append(" ");
- name.append( last->getString() );
- }
-
- gIMMgr->setFloaterOpen(TRUE);
- //EInstantMessage type = have_agent_callingcard(gLastHitObjectID)
- // ? IM_SESSION_ADD : IM_SESSION_CARDLESS_START;
- gIMMgr->addSession(name,
- IM_NOTHING_SPECIAL,
- avatar->getID());
+ LLAvatarActions::startIM(avatar->getID());
}
return true;
}
};
-
-void handle_activate(void*)
-{
-}
-
-BOOL enable_activate(void*)
+class LLAvatarCall : public view_listener_t
{
- return FALSE;
-}
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+ if(avatar)
+ {
+ LLAvatarActions::startCall(avatar->getID());
+ }
+ return true;
+ }
+};
namespace
{
@@ -5971,7 +6296,7 @@ namespace
};
}
-void queue_actions(LLFloaterScriptQueue* q, const std::string& noscriptmsg, const std::string& nomodmsg)
+void queue_actions(LLFloaterScriptQueue* q, const std::string& msg)
{
QueueObjects func(q);
LLSelectMgr *mgr = LLSelectMgr::getInstance();
@@ -5981,11 +6306,13 @@ void queue_actions(LLFloaterScriptQueue* q, const std::string& noscriptmsg, cons
{
if ( !func.scripted )
{
- LLNotifications::instance().add(noscriptmsg);
+ std::string noscriptmsg = std::string("Cannot") + msg + "SelectObjectsNoScripts";
+ LLNotificationsUtil::add(noscriptmsg);
}
else if ( !func.modifiable )
{
- LLNotifications::instance().add(nomodmsg);
+ std::string nomodmsg = std::string("Cannot") + msg + "SelectObjectsNoPermission";
+ LLNotificationsUtil::add(nomodmsg);
}
else
{
@@ -6001,62 +6328,51 @@ void queue_actions(LLFloaterScriptQueue* q, const std::string& noscriptmsg, cons
}
}
-void handle_compile_queue(std::string to_lang)
-{
- LLFloaterCompileQueue* queue;
- if (to_lang == "mono")
- {
- queue = LLFloaterCompileQueue::create(TRUE);
- }
- else
- {
- queue = LLFloaterCompileQueue::create(FALSE);
- }
- queue_actions(queue, "CannotRecompileSelectObjectsNoScripts", "CannotRecompileSelectObjectsNoPermission");
-}
-
-void handle_reset_selection(void)
-{
- LLFloaterResetQueue* queue = LLFloaterResetQueue::create();
- queue_actions(queue, "CannotResetSelectObjectsNoScripts", "CannotResetSelectObjectsNoPermission");
-}
-
-void handle_set_run_selection(void)
-{
- LLFloaterRunQueue* queue = LLFloaterRunQueue::create();
- queue_actions(queue, "CannotSetRunningSelectObjectsNoScripts", "CannotSerRunningSelectObjectsNoPermission");
-}
-
-void handle_set_not_run_selection(void)
-{
- LLFloaterNotRunQueue* queue = LLFloaterNotRunQueue::create();
- queue_actions(queue, "CannotSetRunningNotSelectObjectsNoScripts", "CannotSerRunningNotSelectObjectsNoPermission");
-}
-
class LLToolsSelectedScriptAction : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
std::string action = userdata.asString();
+ bool mono = false;
+ std::string msg, name;
if (action == "compile mono")
{
- handle_compile_queue("mono");
+ name = "compile_queue";
+ mono = true;
+ msg = "Recompile";
}
if (action == "compile lsl")
{
- handle_compile_queue("lsl");
+ name = "compile_queue";
+ msg = "Recompile";
}
else if (action == "reset")
{
- handle_reset_selection();
+ name = "reset_queue";
+ msg = "Reset";
}
else if (action == "start")
{
- handle_set_run_selection();
+ name = "start_queue";
+ msg = "Running";
}
else if (action == "stop")
{
- handle_set_not_run_selection();
+ name = "stop_queue";
+ msg = "RunningNot";
+ }
+ LLUUID id; id.generate();
+
+ LLFloaterScriptQueue* queue =LLFloaterReg::getTypedInstance<LLFloaterScriptQueue>(name, LLSD(id));
+ if (queue)
+ {
+ queue->setMono(mono);
+ queue_actions(queue, msg);
+ }
+ else
+ {
+ llwarns << "Failed to generate LLFloaterScriptQueue with action: " << action << llendl;
+ delete queue;
}
return true;
}
@@ -6065,66 +6381,67 @@ class LLToolsSelectedScriptAction : public view_listener_t
void handle_selected_texture_info(void*)
{
for (LLObjectSelection::valid_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_begin();
- iter != LLSelectMgr::getInstance()->getSelection()->valid_end(); iter++)
+ iter != LLSelectMgr::getInstance()->getSelection()->valid_end(); iter++)
{
LLSelectNode* node = *iter;
-
- std::string msg;
- msg.assign("Texture info for: ");
- msg.append(node->mName);
- LLChat chat(msg);
- LLFloaterChat::addChat(chat);
-
- U8 te_count = node->getObject()->getNumTEs();
- // map from texture ID to list of faces using it
- typedef std::map< LLUUID, std::vector<U8> > map_t;
- map_t faces_per_texture;
- for (U8 i = 0; i < te_count; i++)
- {
- if (!node->isTESelected(i)) continue;
-
- LLViewerImage* img = node->getObject()->getTEImage(i);
- LLUUID image_id = img->getID();
- faces_per_texture[image_id].push_back(i);
- }
- // Per-texture, dump which faces are using it.
- map_t::iterator it;
- for (it = faces_per_texture.begin(); it != faces_per_texture.end(); ++it)
- {
- LLUUID image_id = it->first;
- U8 te = it->second[0];
- LLViewerImage* img = node->getObject()->getTEImage(te);
- S32 height = img->getHeight();
- S32 width = img->getWidth();
- S32 components = img->getComponents();
- msg = llformat("%dx%d %s on face ",
- width,
- height,
- (components == 4 ? "alpha" : "opaque"));
- for (U8 i = 0; i < it->second.size(); ++i)
- {
- msg.append( llformat("%d ", (S32)(it->second[i])));
- }
- LLChat chat(msg);
- LLFloaterChat::addChat(chat);
- }
+
+ std::string msg;
+ msg.assign("Texture info for: ");
+ msg.append(node->mName);
+
+ //TODO* CHAT: how to show this?
+ //LLSD args;
+ //args["MESSAGE"] = msg;
+ //LLNotificationsUtil::add("SystemMessage", args);
+
+ U8 te_count = node->getObject()->getNumTEs();
+ // map from texture ID to list of faces using it
+ typedef std::map< LLUUID, std::vector<U8> > map_t;
+ map_t faces_per_texture;
+ for (U8 i = 0; i < te_count; i++)
+ {
+ if (!node->isTESelected(i)) continue;
+
+ LLViewerTexture* img = node->getObject()->getTEImage(i);
+ LLUUID image_id = img->getID();
+ faces_per_texture[image_id].push_back(i);
+ }
+ // Per-texture, dump which faces are using it.
+ map_t::iterator it;
+ for (it = faces_per_texture.begin(); it != faces_per_texture.end(); ++it)
+ {
+ LLUUID image_id = it->first;
+ U8 te = it->second[0];
+ LLViewerTexture* img = node->getObject()->getTEImage(te);
+ S32 height = img->getHeight();
+ S32 width = img->getWidth();
+ S32 components = img->getComponents();
+ msg = llformat("%dx%d %s on face ",
+ width,
+ height,
+ (components == 4 ? "alpha" : "opaque"));
+ for (U8 i = 0; i < it->second.size(); ++i)
+ {
+ msg.append( llformat("%d ", (S32)(it->second[i])));
+ }
+
+ //TODO* CHAT: how to show this?
+ //LLSD args;
+ //args["MESSAGE"] = msg;
+ //LLNotificationsUtil::add("SystemMessage", args);
+ }
}
}
-void handle_dump_image_list(void*)
-{
- gImageList.dump();
-}
-
void handle_test_male(void*)
{
- wear_outfit_by_name("Male Shape & Outfit");
+ LLAppearanceManager::instance().wearOutfitByName("Male Shape & Outfit");
//gGestureList.requestResetFromServer( TRUE );
}
void handle_test_female(void*)
{
- wear_outfit_by_name("Female Shape & Outfit");
+ LLAppearanceManager::instance().wearOutfitByName("Female Shape & Outfit");
//gGestureList.requestResetFromServer( FALSE );
}
@@ -6152,121 +6469,102 @@ void handle_dump_attachments(void*)
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
S32 key = curiter->first;
- BOOL visible = (attachment->getObject() != NULL &&
- attachment->getObject()->mDrawable.notNull() &&
- !attachment->getObject()->mDrawable->isRenderType(0));
- LLVector3 pos;
- if (visible) pos = attachment->getObject()->mDrawable->getPosition();
- llinfos << "ATTACHMENT " << key << ": item_id=" << attachment->getItemID()
- << (attachment->getObject() ? " present " : " absent ")
- << (visible ? "visible " : "invisible ")
- << " at " << pos
- << " and " << (visible ? attachment->getObject()->getPosition() : LLVector3::zero)
- << llendl;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject *attached_object = (*attachment_iter);
+ BOOL visible = (attached_object != NULL &&
+ attached_object->mDrawable.notNull() &&
+ !attached_object->mDrawable->isRenderType(0));
+ LLVector3 pos;
+ if (visible) pos = attached_object->mDrawable->getPosition();
+ llinfos << "ATTACHMENT " << key << ": item_id=" << attached_object->getItemID()
+ << (attached_object ? " present " : " absent ")
+ << (visible ? "visible " : "invisible ")
+ << " at " << pos
+ << " and " << (visible ? attached_object->getPosition() : LLVector3::zero)
+ << llendl;
+ }
}
}
-//---------------------------------------------------------------------
-// Callbacks for enabling/disabling items
-//---------------------------------------------------------------------
-
-BOOL menu_ui_enabled(void *user_data)
-{
- BOOL high_res = gSavedSettings.getBOOL( "HighResSnapshot" );
- return !high_res;
-}
-
-// TomY TODO DEPRECATE & REMOVE
-void menu_toggle_control( void* user_data )
-{
- BOOL checked = gSavedSettings.getBOOL( static_cast<char*>(user_data) );
- if (std::string(static_cast<char*>(user_data)) == "HighResSnapshot" && !checked)
- {
- // High Res Snapshot active, must uncheck RenderUIInSnapshot
- gSavedSettings.setBOOL( "RenderUIInSnapshot", FALSE );
- }
- gSavedSettings.setBOOL( static_cast<char*>(user_data), !checked );
-}
-
// these are used in the gl menus to set control values.
class LLToggleControl : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
std::string control_name = userdata.asString();
BOOL checked = gSavedSettings.getBOOL( control_name );
- if (control_name == "HighResSnapshot" && !checked)
- {
- // High Res Snapshot active, must uncheck RenderUIInSnapshot
- gSavedSettings.setBOOL( "RenderUIInSnapshot", FALSE );
- }
gSavedSettings.setBOOL( control_name, !checked );
return true;
}
};
-BOOL menu_check_control( void* user_data)
-{
- return gSavedSettings.getBOOL((char*)user_data);
-}
-
-//
-void menu_toggle_variable( void* user_data )
+class LLCheckControl : public view_listener_t
{
- BOOL checked = *(BOOL*)user_data;
- *(BOOL*)user_data = !checked;
-}
-
-BOOL menu_check_variable( void* user_data)
-{
- return *(BOOL*)user_data;
+ bool handleEvent( const LLSD& userdata)
+ {
+ std::string callback_data = userdata.asString();
+ bool new_value = gSavedSettings.getBOOL(callback_data);
+ return new_value;
}
-
-BOOL enable_land_selected( void* )
-{
- return !(LLViewerParcelMgr::getInstance()->selectionEmpty());
-}
+};
void menu_toggle_attached_lights(void* user_data)
{
- menu_toggle_control(user_data);
LLPipeline::sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights");
}
void menu_toggle_attached_particles(void* user_data)
{
- menu_toggle_control(user_data);
LLPipeline::sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles");
}
+class LLAdvancedHandleAttachedLightParticles: public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string control_name = userdata.asString();
+
+ // toggle the control
+ gSavedSettings.setBOOL(control_name,
+ !gSavedSettings.getBOOL(control_name));
+
+ // update internal flags
+ if (control_name == "RenderAttachedLights")
+ {
+ menu_toggle_attached_lights(NULL);
+ }
+ else if (control_name == "RenderAttachedParticles")
+ {
+ menu_toggle_attached_particles(NULL);
+ }
+ return true;
+ }
+};
+
class LLSomethingSelected : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = !(LLSelectMgr::getInstance()->getSelection()->isEmpty());
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
class LLSomethingSelectedNoHUD : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
bool new_value = !(selection->isEmpty()) && !(selection->getSelectType() == SELECT_TYPE_HUD);
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
-BOOL enable_more_than_one_selected(void* )
-{
- return (LLSelectMgr::getInstance()->getSelection()->getObjectCount() > 1);
-}
-
static bool is_editable_selected()
{
return (LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() != NULL);
@@ -6274,106 +6572,59 @@ static bool is_editable_selected()
class LLEditableSelected : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- gMenuHolder->findControl(userdata["control"].asString())->setValue(is_editable_selected());
- return true;
+ return is_editable_selected();
}
};
class LLEditableSelectedMono : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
+ bool new_value = false;
LLViewerRegion* region = gAgent.getRegion();
- if(region && gMenuHolder && gMenuHolder->findControl(userdata["control"].asString()))
+ if(region && gMenuHolder)
{
bool have_cap = (! region->getCapability("UpdateScriptTask").empty());
- bool selected = is_editable_selected() && have_cap;
- gMenuHolder->findControl(userdata["control"].asString())->setValue(selected);
- return true;
+ new_value = is_editable_selected() && have_cap;
}
- return false;
+ return new_value;
}
};
-class LLToolsEnableTakeCopy : public view_listener_t
+bool enable_object_take_copy()
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool all_valid = false;
+ if (LLSelectMgr::getInstance())
{
- bool all_valid = false;
- if (LLSelectMgr::getInstance())
+ if (!LLSelectMgr::getInstance()->getSelection()->isEmpty())
{
- if (!LLSelectMgr::getInstance()->getSelection()->isEmpty())
- {
- all_valid = true;
+ all_valid = true;
#ifndef HACKED_GODLIKE_VIEWER
# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
- if (LLViewerLogin::getInstance()->isInProductionGrid()
- || !gAgent.isGodlike())
+ if (LLViewerLogin::getInstance()->isInProductionGrid()
+ || !gAgent.isGodlike())
# endif
+ {
+ struct f : public LLSelectedObjectFunctor
+ {
+ virtual bool apply(LLViewerObject* obj)
{
- struct f : public LLSelectedObjectFunctor
- {
- virtual bool apply(LLViewerObject* obj)
- {
- return (!obj->permCopy() || obj->isAttachment());
- }
- } func;
- const bool firstonly = true;
- bool any_invalid = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly);
- all_valid = !any_invalid;
+ return (!obj->permCopy() || obj->isAttachment());
}
+ } func;
+ const bool firstonly = true;
+ bool any_invalid = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly);
+ all_valid = !any_invalid;
+ }
#endif // HACKED_GODLIKE_VIEWER
- }
}
-
- gMenuHolder->findControl(userdata["control"].asString())->setValue(all_valid);
- return true;
}
-};
-BOOL enable_selection_you_own_all(void*)
-{
- if (LLSelectMgr::getInstance())
- {
- struct f : public LLSelectedObjectFunctor
- {
- virtual bool apply(LLViewerObject* obj)
- {
- return (!obj->permYouOwner());
- }
- } func;
- const bool firstonly = true;
- bool no_perms = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly);
- if (no_perms)
- {
- return FALSE;
- }
- }
- return TRUE;
+ return all_valid;
}
-BOOL enable_selection_you_own_one(void*)
-{
- if (LLSelectMgr::getInstance())
- {
- struct f : public LLSelectedObjectFunctor
- {
- virtual bool apply(LLViewerObject* obj)
- {
- return (obj->permYouOwner());
- }
- } func;
- const bool firstonly = true;
- bool any_perms = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly);
- if (!any_perms)
- {
- return FALSE;
- }
- }
- return TRUE;
-}
class LLHasAsset : public LLInventoryCollectFunctor
{
@@ -6435,6 +6686,15 @@ BOOL enable_save_into_inventory(void*)
return FALSE;
}
+class LLToolsEnableSaveToInventory : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = enable_save_into_inventory(NULL);
+ return new_value;
+ }
+};
+
BOOL enable_save_into_task_inventory(void*)
{
LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
@@ -6452,101 +6712,63 @@ BOOL enable_save_into_task_inventory(void*)
class LLToolsEnableSaveToObjectInventory : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = enable_save_into_task_inventory(NULL);
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
-BOOL enable_not_thirdperson(void*)
-{
- return !gAgent.cameraThirdPerson();
-}
-
-
-// BOOL enable_export_selected(void *)
-// {
-// if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
-// {
-// return FALSE;
-// }
-// if (!gExporterRequestID.isNull())
-// {
-// return FALSE;
-// }
-// if (!LLUploadDialog::modalUploadIsFinished())
-// {
-// return FALSE;
-// }
-// return TRUE;
-// }
class LLViewEnableMouselook : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
// You can't go directly from customize avatar to mouselook.
// TODO: write code with appropriate dialogs to handle this transition.
bool new_value = (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgent.getCameraMode() && !gSavedSettings.getBOOL("FreezeTime"));
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
class LLToolsEnableToolNotPie : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = ( LLToolMgr::getInstance()->getBaseTool() != LLToolPie::getInstance() );
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
class LLWorldEnableCreateLandmark : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- bool new_value = can_create_landmark();
-
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
-
- return true;
+ return !LLLandmarkActions::landmarkAlreadyExists();
}
};
class LLWorldEnableSetHomeLocation : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = gAgent.isGodlike() ||
(gAgent.getRegion() && gAgent.getRegion()->getAllowSetHome());
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
class LLWorldEnableTeleportHome : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
LLViewerRegion* regionp = gAgent.getRegion();
bool agent_on_prelude = (regionp && regionp->isPrelude());
bool enable_teleport_home = gAgent.isGodlike() || !agent_on_prelude;
- gMenuHolder->findControl(userdata["control"].asString())->setValue(enable_teleport_home);
- return true;
+ return enable_teleport_home;
}
};
-BOOL enable_region_owner(void*)
-{
- if(gAgent.getRegion() && gAgent.getRegion()->getOwner() == gAgent.getID())
- return TRUE;
- return enable_god_customer_service(NULL);
-}
-
BOOL enable_god_full(void*)
{
return gAgent.getGodLevel() >= GOD_FULL;
@@ -6557,7 +6779,7 @@ BOOL enable_god_liaison(void*)
return gAgent.getGodLevel() >= GOD_LIAISON;
}
-BOOL enable_god_customer_service(void*)
+bool is_god_customer_service()
{
return gAgent.getGodLevel() >= GOD_CUSTOMER_SERVICE;
}
@@ -6567,44 +6789,20 @@ BOOL enable_god_basic(void*)
return gAgent.getGodLevel() > GOD_NOT;
}
-#if 0 // 1.9.2
-void toggle_vertex_shaders(void *)
-{
- BOOL use_shaders = gPipeline.getUseVertexShaders();
- gPipeline.setUseVertexShaders(use_shaders);
-}
-
-BOOL check_vertex_shaders(void *)
-{
- return gPipeline.getUseVertexShaders();
-}
-#endif
void toggle_show_xui_names(void *)
{
- BOOL showXUINames = gSavedSettings.getBOOL("ShowXUINames");
-
- showXUINames = !showXUINames;
- gSavedSettings.setBOOL("ShowXUINames", showXUINames);
+ gSavedSettings.setBOOL("DebugShowXUINames", !gSavedSettings.getBOOL("DebugShowXUINames"));
}
BOOL check_show_xui_names(void *)
{
- return gSavedSettings.getBOOL("ShowXUINames");
-}
-
-
-
-void toggle_cull_small(void *)
-{
-// gPipeline.mCullBySize = !gPipeline.mCullBySize;
-//
-// gSavedSettings.setBOOL("RenderCullBySize", gPipeline.mCullBySize);
+ return gSavedSettings.getBOOL("DebugShowXUINames");
}
class LLToolsSelectOnlyMyObjects : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
BOOL cur_val = gSavedSettings.getBOOL("SelectOwnedOnly");
@@ -6616,7 +6814,7 @@ class LLToolsSelectOnlyMyObjects : public view_listener_t
class LLToolsSelectOnlyMovableObjects : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
BOOL cur_val = gSavedSettings.getBOOL("SelectMovableOnly");
@@ -6628,7 +6826,7 @@ class LLToolsSelectOnlyMovableObjects : public view_listener_t
class LLToolsSelectBySurrounding : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
LLSelectMgr::sRectSelectInclusive = !LLSelectMgr::sRectSelectInclusive;
@@ -6639,7 +6837,7 @@ class LLToolsSelectBySurrounding : public view_listener_t
class LLToolsShowHiddenSelection : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
// TomY TODO Merge these
LLSelectMgr::sRenderHiddenSelections = !LLSelectMgr::sRenderHiddenSelections;
@@ -6651,7 +6849,7 @@ class LLToolsShowHiddenSelection : public view_listener_t
class LLToolsShowSelectionLightRadius : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
// TomY TODO merge these
LLSelectMgr::sRenderLightRadius = !LLSelectMgr::sRenderLightRadius;
@@ -6663,7 +6861,7 @@ class LLToolsShowSelectionLightRadius : public view_listener_t
class LLToolsEditLinkedParts : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
BOOL select_individuals = gSavedSettings.getBOOL("EditLinkedParts");
if (select_individuals)
@@ -6678,40 +6876,19 @@ class LLToolsEditLinkedParts : public view_listener_t
}
};
-void reload_personal_settings_overrides(void *)
-{
- llinfos << "Loading overrides from " << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT,"overrides.xml") << llendl;
-
- gSavedSettings.loadFromFile(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT,"overrides.xml"));
-}
-
void reload_vertex_shader(void *)
{
//THIS WOULD BE AN AWESOME PLACE TO RELOAD SHADERS... just a thought - DaveP
}
-void slow_mo_animations(void*)
+void handle_dump_avatar_local_textures(void*)
{
- static BOOL slow_mo = FALSE;
- if (slow_mo)
- {
- gAgent.getAvatarObject()->setAnimTimeFactor(1.f);
- slow_mo = FALSE;
- }
- else
- {
- gAgent.getAvatarObject()->setAnimTimeFactor(0.2f);
- slow_mo = TRUE;
- }
+ gAgent.getAvatarObject()->dumpLocalTextures();
}
-void handle_dump_avatar_local_textures(void*)
+void handle_dump_timers()
{
- LLVOAvatar* avatar = gAgent.getAvatarObject();
- if( avatar )
- {
- avatar->dumpLocalTextures();
- }
+ LLFastTimer::dumpCurTimes();
}
void handle_debug_avatar_textures(void*)
@@ -6719,49 +6896,32 @@ void handle_debug_avatar_textures(void*)
LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
if (objectp)
{
- LLFloaterAvatarTextures::show(objectp->getID());
+ LLFloaterReg::showInstance( "avatar_textures", LLSD(objectp->getID()) );
}
}
void handle_grab_texture(void* data)
{
- ETextureIndex index = (ETextureIndex)((intptr_t)data);
- LLVOAvatar* avatar = gAgent.getAvatarObject();
+ ETextureIndex tex_index = (ETextureIndex)((intptr_t)data);
+ const LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
if ( avatar )
{
- const LLUUID& asset_id = avatar->grabLocalTexture(index);
+ // MULTI-WEARABLE: change to support an index
+ const LLUUID& asset_id = avatar->grabLocalTexture(tex_index, 0);
LL_INFOS("texture") << "Adding baked texture " << asset_id << " to inventory." << llendl;
LLAssetType::EType asset_type = LLAssetType::AT_TEXTURE;
LLInventoryType::EType inv_type = LLInventoryType::IT_TEXTURE;
- LLUUID folder_id(gInventory.findCategoryUUIDForType(asset_type));
+ const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(asset_type));
if(folder_id.notNull())
{
- std::string name = "Baked ";
- switch (index)
+ std::string name = "Unknown";
+ const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(tex_index);
+ if (texture_dict->mIsBakedTexture)
{
- case TEX_EYES_BAKED:
- name.append("Iris");
- break;
- case TEX_HEAD_BAKED:
- name.append("Head");
- break;
- case TEX_UPPER_BAKED:
- name.append("Upper Body");
- break;
- case TEX_LOWER_BAKED:
- name.append("Lower Body");
- break;
- case TEX_SKIRT_BAKED:
- name.append("Skirt");
- break;
- case TEX_HAIR_BAKED:
- name.append("Hair");
- break;
- default:
- name.append("Unknown");
- break;
+ EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
+ name = "Baked " + LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index)->mNameCapitalized;
}
- name.append(" Texture");
+ name += " Texture";
LLUUID item_id;
item_id.generate();
@@ -6794,17 +6954,16 @@ void handle_grab_texture(void* data)
gInventory.updateItem(item);
gInventory.notifyObservers();
- LLInventoryView* view = LLInventoryView::getActiveInventory();
-
// Show the preview panel for textures to let
// user know that the image is now in inventory.
- if(view)
+ LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel();
+ if(active_panel)
{
- LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus();
+ LLFocusableElement* focus_ctrl = gFocusMgr.getKeyboardFocus();
- view->getPanel()->setSelection(item_id, TAKE_FOCUS_NO);
- view->getPanel()->openSelected();
- //LLInventoryView::dumpSelectionInformation((void*)view);
+ active_panel->setSelection(item_id, TAKE_FOCUS_NO);
+ active_panel->openSelected();
+ //LLFloaterInventory::dumpSelectionInformation((void*)view);
// restore keyboard focus
gFocusMgr.setKeyboardFocus(focus_ctrl);
}
@@ -6819,10 +6978,11 @@ void handle_grab_texture(void* data)
BOOL enable_grab_texture(void* data)
{
ETextureIndex index = (ETextureIndex)((intptr_t)data);
- LLVOAvatar* avatar = gAgent.getAvatarObject();
+ const LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
if ( avatar )
{
- return avatar->canGrabLocalTexture(index);
+ // MULTI-WEARABLE:
+ return avatar->canGrabLocalTexture(index,0);
}
return FALSE;
}
@@ -6841,8 +7001,7 @@ LLVOAvatar* find_avatar_from_object( LLViewerObject* object )
}
while( object && !object->isAvatar() );
}
- else
- if( !object->isAvatar() )
+ else if( !object->isAvatar() )
{
object = NULL;
}
@@ -6882,7 +7041,7 @@ void force_error_bad_memory_access(void *)
void force_error_infinite_loop(void *)
{
- LLAppViewer::instance()->forceErrorInifiniteLoop();
+ LLAppViewer::instance()->forceErrorInfiniteLoop();
}
void force_error_software_exception(void *)
@@ -6897,7 +7056,7 @@ void force_error_driver_crash(void *)
class LLToolsUseSelectionForGrid : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
LLSelectMgr::getInstance()->clearGridObjects();
struct f : public LLSelectedObjectFunctor
@@ -6929,10 +7088,11 @@ void handle_test_load_url(void*)
//
// LLViewerMenuHolderGL
//
+static LLDefaultChildRegistry::Register<LLViewerMenuHolderGL> r("menu_holder");
-LLViewerMenuHolderGL::LLViewerMenuHolderGL() : LLMenuHolderGL()
-{
-}
+LLViewerMenuHolderGL::LLViewerMenuHolderGL(const LLViewerMenuHolderGL::Params& p)
+: LLMenuHolderGL(p)
+{}
BOOL LLViewerMenuHolderGL::hideMenus()
{
@@ -6942,8 +7102,11 @@ BOOL LLViewerMenuHolderGL::hideMenus()
mParcelSelection = NULL;
mObjectSelection = NULL;
- gMenuBarView->clearHoverItem();
- gMenuBarView->resetMenuTrigger();
+ if (gMenuBarView)
+ {
+ gMenuBarView->clearHoverItem();
+ gMenuBarView->resetMenuTrigger();
+ }
return handled;
}
@@ -6969,7 +7132,7 @@ void handle_save_to_xml(void*)
LLFloater* frontmost = gFloaterView->getFrontmost();
if (!frontmost)
{
- LLNotifications::instance().add("NoFrontmostFloater");
+ LLNotificationsUtil::add("NoFrontmostFloater");
return;
}
@@ -6997,20 +7160,19 @@ void handle_load_from_xml(void*)
if (picker.getOpenFile(LLFilePicker::FFLOAD_XML))
{
std::string filename = picker.getFirstFile();
- LLFloater* floater = new LLFloater("sample_floater");
- LLUICtrlFactory::getInstance()->buildFloater(floater, filename);
+ LLFloater* floater = new LLFloater(LLSD());
+ LLUICtrlFactory::getInstance()->buildFloater(floater, filename, NULL);
}
}
-void handle_web_browser_test(void*)
+void handle_web_browser_test(const LLSD& param)
{
- const bool open_links_externally = false;
- const bool open_app_slurls = true;
- LLFloaterHtml::getInstance()->show(
- "http://secondlife.com/app/search/slurls.html",
- "Web Browser Test",
- open_links_externally,
- open_app_slurls);
+ std::string url = param.asString();
+ if (url.empty())
+ {
+ url = "about:blank";
+ }
+ LLWeb::loadURL(url);
}
void handle_buy_currency_test(void*)
@@ -7024,7 +7186,7 @@ void handle_buy_currency_test(void*)
// *TODO: Replace with call to LLUI::getLanguage() after windows-setup
// branch merges in. JC
- std::string language = "en-us";
+ std::string language = "en";
language = gSavedSettings.getString("Language");
if (language.empty() || language == "default")
{
@@ -7036,7 +7198,7 @@ void handle_buy_currency_test(void*)
}
if (language.empty() || language == "default")
{
- language = "en-us";
+ language = "en";
}
replace["[LANGUAGE]"] = language;
@@ -7044,15 +7206,12 @@ void handle_buy_currency_test(void*)
llinfos << "buy currency url " << url << llendl;
- LLFloaterHtmlCurrency* floater = LLFloaterHtmlCurrency::showInstance(url);
- // Needed so we can use secondlife:///app/floater/self/close SLURLs
- floater->setTrusted(true);
- floater->center();
+ LLFloaterReg::showInstance("buy_currency_html", LLSD(url));
}
void handle_rebake_textures(void*)
{
- LLVOAvatar* avatar = gAgent.getAvatarObject();
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
if (!avatar) return;
// Slam pending upload count to "unstick" things
@@ -7075,27 +7234,26 @@ BOOL get_visibility(void* user_data)
// TomY TODO: Get rid of these?
class LLViewShowHoverTips : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- LLHoverView::sShowHoverTips = !LLHoverView::sShowHoverTips;
+ gSavedSettings.setBOOL("ShowHoverTips", !gSavedSettings.getBOOL("ShowHoverTips"));
return true;
}
};
class LLViewCheckShowHoverTips : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- bool new_value = LLHoverView::sShowHoverTips;
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ bool new_value = gSavedSettings.getBOOL("ShowHoverTips");
+ return new_value;
}
};
// TomY TODO: Get rid of these?
class LLViewHighlightTransparent : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
LLDrawPoolAlpha::sShowDebugAlpha = !LLDrawPoolAlpha::sShowDebugAlpha;
return true;
@@ -7104,170 +7262,236 @@ class LLViewHighlightTransparent : public view_listener_t
class LLViewCheckHighlightTransparent : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = LLDrawPoolAlpha::sShowDebugAlpha;
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
-class LLViewToggleRenderType : public view_listener_t
+class LLViewBeaconWidth : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- std::string type = userdata.asString();
- if (type == "hideparticles")
+ std::string width = userdata.asString();
+ if(width == "1")
{
- LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
+ gSavedSettings.setS32("DebugBeaconLineWidth", 1);
}
- return true;
- }
-};
-
-class LLViewCheckRenderType : public view_listener_t
-{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- std::string type = userdata["data"].asString();
- bool new_value = false;
- if (type == "hideparticles")
+ else if(width == "4")
{
- new_value = LLPipeline::toggleRenderTypeControlNegated((void *)LLPipeline::RENDER_TYPE_PARTICLES);
+ gSavedSettings.setS32("DebugBeaconLineWidth", 4);
+ }
+ else if(width == "16")
+ {
+ gSavedSettings.setS32("DebugBeaconLineWidth", 16);
+ }
+ else if(width == "32")
+ {
+ gSavedSettings.setS32("DebugBeaconLineWidth", 32);
}
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
- }
-};
-class LLViewShowHUDAttachments : public view_listener_t
-{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- LLPipeline::sShowHUDAttachments = !LLPipeline::sShowHUDAttachments;
return true;
}
};
-class LLViewCheckHUDAttachments : public view_listener_t
-{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- bool new_value = LLPipeline::sShowHUDAttachments;
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
- }
-};
-class LLEditEnableTakeOff : public view_listener_t
+class LLViewToggleBeacon : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- std::string control_name = userdata["control"].asString();
- std::string clothing = userdata["data"].asString();
- bool new_value = false;
- if (clothing == "shirt")
+ std::string beacon = userdata.asString();
+ if (beacon == "scriptsbeacon")
{
- new_value = LLAgent::selfHasWearable((void *)WT_SHIRT);
- }
- if (clothing == "pants")
- {
- new_value = LLAgent::selfHasWearable((void *)WT_PANTS);
- }
- if (clothing == "shoes")
- {
- new_value = LLAgent::selfHasWearable((void *)WT_SHOES);
+ LLPipeline::toggleRenderScriptedBeacons(NULL);
+ gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons(NULL) );
+ // toggle the other one off if it's on
+ if (LLPipeline::getRenderScriptedBeacons(NULL) && LLPipeline::getRenderScriptedTouchBeacons(NULL))
+ {
+ LLPipeline::toggleRenderScriptedTouchBeacons(NULL);
+ gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons(NULL) );
+ }
}
- if (clothing == "socks")
+ else if (beacon == "physicalbeacon")
{
- new_value = LLAgent::selfHasWearable((void *)WT_SOCKS);
+ LLPipeline::toggleRenderPhysicalBeacons(NULL);
+ gSavedSettings.setBOOL( "physicalbeacon", LLPipeline::getRenderPhysicalBeacons(NULL) );
}
- if (clothing == "jacket")
+ else if (beacon == "soundsbeacon")
{
- new_value = LLAgent::selfHasWearable((void *)WT_JACKET);
+ LLPipeline::toggleRenderSoundBeacons(NULL);
+ gSavedSettings.setBOOL( "soundsbeacon", LLPipeline::getRenderSoundBeacons(NULL) );
}
- if (clothing == "gloves")
+ else if (beacon == "particlesbeacon")
{
- new_value = LLAgent::selfHasWearable((void *)WT_GLOVES);
+ LLPipeline::toggleRenderParticleBeacons(NULL);
+ gSavedSettings.setBOOL( "particlesbeacon", LLPipeline::getRenderParticleBeacons(NULL) );
}
- if (clothing == "undershirt")
+ else if (beacon == "scripttouchbeacon")
{
- new_value = LLAgent::selfHasWearable((void *)WT_UNDERSHIRT);
+ LLPipeline::toggleRenderScriptedTouchBeacons(NULL);
+ gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons(NULL) );
+ // toggle the other one off if it's on
+ if (LLPipeline::getRenderScriptedBeacons(NULL) && LLPipeline::getRenderScriptedTouchBeacons(NULL))
+ {
+ LLPipeline::toggleRenderScriptedBeacons(NULL);
+ gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons(NULL) );
+ }
}
- if (clothing == "underpants")
+ else if (beacon == "renderbeacons")
{
- new_value = LLAgent::selfHasWearable((void *)WT_UNDERPANTS);
+ LLPipeline::toggleRenderBeacons(NULL);
+ gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons(NULL) );
+ // toggle the other one on if it's not
+ if (!LLPipeline::getRenderBeacons(NULL) && !LLPipeline::getRenderHighlights(NULL))
+ {
+ LLPipeline::toggleRenderHighlights(NULL);
+ gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights(NULL) );
+ }
}
- if (clothing == "skirt")
+ else if (beacon == "renderhighlights")
{
- new_value = LLAgent::selfHasWearable((void *)WT_SKIRT);
+ LLPipeline::toggleRenderHighlights(NULL);
+ gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights(NULL) );
+ // toggle the other one on if it's not
+ if (!LLPipeline::getRenderBeacons(NULL) && !LLPipeline::getRenderHighlights(NULL))
+ {
+ LLPipeline::toggleRenderBeacons(NULL);
+ gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons(NULL) );
+ }
}
- gMenuHolder->findControl(control_name)->setValue(new_value);
+
return true;
}
};
-class LLEditTakeOff : public view_listener_t
+class LLViewCheckBeaconEnabled : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- std::string clothing = userdata.asString();
- if (clothing == "shirt")
- {
- LLAgent::userRemoveWearable((void*)WT_SHIRT);
- }
- else if (clothing == "pants")
+ std::string beacon = userdata.asString();
+ bool new_value = false;
+ if (beacon == "scriptsbeacon")
{
- LLAgent::userRemoveWearable((void*)WT_PANTS);
+ new_value = gSavedSettings.getBOOL( "scriptsbeacon");
+ LLPipeline::setRenderScriptedBeacons(new_value);
}
- else if (clothing == "shoes")
+ else if (beacon == "physicalbeacon")
{
- LLAgent::userRemoveWearable((void*)WT_SHOES);
+ new_value = gSavedSettings.getBOOL( "physicalbeacon");
+ LLPipeline::setRenderPhysicalBeacons(new_value);
}
- else if (clothing == "socks")
+ else if (beacon == "soundsbeacon")
{
- LLAgent::userRemoveWearable((void*)WT_SOCKS);
+ new_value = gSavedSettings.getBOOL( "soundsbeacon");
+ LLPipeline::setRenderSoundBeacons(new_value);
}
- else if (clothing == "jacket")
+ else if (beacon == "particlesbeacon")
{
- LLAgent::userRemoveWearable((void*)WT_JACKET);
+ new_value = gSavedSettings.getBOOL( "particlesbeacon");
+ LLPipeline::setRenderParticleBeacons(new_value);
}
- else if (clothing == "gloves")
+ else if (beacon == "scripttouchbeacon")
{
- LLAgent::userRemoveWearable((void*)WT_GLOVES);
+ new_value = gSavedSettings.getBOOL( "scripttouchbeacon");
+ LLPipeline::setRenderScriptedTouchBeacons(new_value);
}
- else if (clothing == "undershirt")
+ else if (beacon == "renderbeacons")
{
- LLAgent::userRemoveWearable((void*)WT_UNDERSHIRT);
+ new_value = gSavedSettings.getBOOL( "renderbeacons");
+ LLPipeline::setRenderBeacons(new_value);
}
- else if (clothing == "underpants")
+ else if (beacon == "renderhighlights")
{
- LLAgent::userRemoveWearable((void*)WT_UNDERPANTS);
+ new_value = gSavedSettings.getBOOL( "renderhighlights");
+ LLPipeline::setRenderHighlights(new_value);
}
- else if (clothing == "skirt")
+ return new_value;
+ }
+};
+
+class LLViewToggleRenderType : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string type = userdata.asString();
+ if (type == "hideparticles")
{
- LLAgent::userRemoveWearable((void*)WT_SKIRT);
+ LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
}
- else if (clothing == "all")
+ return true;
+ }
+};
+
+class LLViewCheckRenderType : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string type = userdata.asString();
+ bool new_value = false;
+ if (type == "hideparticles")
{
- LLAgent::userRemoveAllClothes(NULL);
+ new_value = LLPipeline::toggleRenderTypeControlNegated((void *)LLPipeline::RENDER_TYPE_PARTICLES);
}
+ return new_value;
+ }
+};
+
+class LLViewShowHUDAttachments : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLPipeline::sShowHUDAttachments = !LLPipeline::sShowHUDAttachments;
return true;
}
};
-class LLWorldChat : public view_listener_t
+class LLViewCheckHUDAttachments : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool new_value = LLPipeline::sShowHUDAttachments;
+ return new_value;
+ }
+};
+
+class LLEditEnableTakeOff : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string clothing = userdata.asString();
+ EWearableType type = LLWearableDictionary::typeNameToType(clothing);
+ if (type >= WT_SHAPE && type < WT_COUNT)
+ return LLAgentWearables::selfHasWearable(type);
+ return false;
+ }
+};
+
+class LLEditTakeOff : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- handle_chat(NULL);
+ std::string clothing = userdata.asString();
+ if (clothing == "all")
+ LLWearableBridge::removeAllClothesFromAvatar();
+ else
+ {
+ EWearableType type = LLWearableDictionary::typeNameToType(clothing);
+ if (type >= WT_SHAPE && type < WT_COUNT)
+ {
+ // MULTI-WEARABLES
+ LLViewerInventoryItem *item = dynamic_cast<LLViewerInventoryItem*>(gAgentWearables.getWearableInventoryItem(type,0));
+ LLWearableBridge::removeItemFromAvatar(item);
+ }
+
+ }
return true;
}
};
class LLToolsSelectTool : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
std::string tool_name = userdata.asString();
if (tool_name == "focus")
@@ -7297,7 +7521,7 @@ class LLToolsSelectTool : public view_listener_t
/// WINDLIGHT callbacks
class LLWorldEnvSettings : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
std::string tod = userdata.asString();
LLVector3 sun_direction;
@@ -7305,16 +7529,7 @@ class LLWorldEnvSettings : public view_listener_t
if (tod == "editor")
{
// if not there or is hidden, show it
- if( !LLFloaterEnvSettings::isOpen() ||
- !LLFloaterEnvSettings::instance()->getVisible()) {
- LLFloaterEnvSettings::show();
-
- // otherwise, close it button acts like a toggle
- }
- else
- {
- LLFloaterEnvSettings::instance()->close();
- }
+ LLFloaterReg::toggleInstance("env_settings");
return true;
}
@@ -7374,19 +7589,9 @@ class LLWorldEnvSettings : public view_listener_t
/// Water Menu callbacks
class LLWorldWaterSettings : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- // if not there or is hidden, show it
- if( !LLFloaterWater::isOpen() ||
- !LLFloaterWater::instance()->getVisible()) {
- LLFloaterWater::show();
-
- // otherwise, close it button acts like a toggle
- }
- else
- {
- LLFloaterWater::instance()->close();
- }
+ LLFloaterReg::toggleInstance("env_water");
return true;
}
};
@@ -7394,9 +7599,9 @@ class LLWorldWaterSettings : public view_listener_t
/// Post-Process callbacks
class LLWorldPostProcess : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- LLFloaterPostProcess::show();
+ LLFloaterReg::showInstance("env_post_process");
return true;
}
};
@@ -7404,19 +7609,24 @@ class LLWorldPostProcess : public view_listener_t
/// Day Cycle callbacks
class LLWorldDayCycle : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
- LLFloaterDayCycle::show();
+ LLFloaterReg::showInstance("env_day_cycle");
return true;
}
};
-
-
-static void addMenu(view_listener_t *menu, const std::string& name)
+void show_navbar_context_menu(LLView* ctrl, S32 x, S32 y)
{
- sMenus.push_back(menu);
- menu->registerListener(gMenuHolder, name);
+ static LLMenuGL* show_navbar_context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_hide_navbar.xml",
+ gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if(gMenuHolder->hasVisibleMenu())
+ {
+ gMenuHolder->hideMenus();
+ }
+ show_navbar_context_menu->buildDrawLabels();
+ show_navbar_context_menu->updateParent(LLMenuGL::sMenuContainer);
+ LLMenuGL::showPopup(ctrl, show_navbar_context_menu, x, y);
}
void initialize_menus()
@@ -7427,7 +7637,7 @@ void initialize_menus()
public:
// The "mult" parameter says whether "val" is a multiplier or used to set the value.
LLZoomer(F32 val, bool mult=true) : mVal(val), mMult(mult) {}
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
F32 new_fov_rad = mMult ? LLViewerCamera::getInstance()->getDefaultFOV() * mVal : mVal;
LLViewerCamera::getInstance()->setDefaultFOV(new_fov_rad);
@@ -7439,217 +7649,395 @@ void initialize_menus()
bool mMult;
};
- class LLAvatarReportAbuse : public view_listener_t
- {
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
- if(avatar)
- {
- LLFloaterReporter::showFromObject(avatar->getID());
- }
- return true;
- }
- };
+ LLUICtrl::EnableCallbackRegistry::Registrar& enable = LLUICtrl::EnableCallbackRegistry::currentRegistrar();
+ LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar();
+
+ // Generic enable and visible
+ // Don't prepend MenuName.Foo because these can be used in any menu.
+ enable.add("IsGodCustomerService", boost::bind(&is_god_customer_service));
+ enable.add("IsGodCustomerService", boost::bind(&is_god_customer_service));
+
+ // Agent
+ commit.add("Agent.toggleFlying", boost::bind(&LLAgent::toggleFlying));
+ enable.add("Agent.enableFlying", boost::bind(&LLAgent::enableFlying));
// File menu
init_menu_file();
// Edit menu
- addMenu(new LLEditUndo(), "Edit.Undo");
- addMenu(new LLEditRedo(), "Edit.Redo");
- addMenu(new LLEditCut(), "Edit.Cut");
- addMenu(new LLEditCopy(), "Edit.Copy");
- addMenu(new LLEditPaste(), "Edit.Paste");
- addMenu(new LLEditDelete(), "Edit.Delete");
- addMenu(new LLEditSearch(), "Edit.Search");
- addMenu(new LLEditSelectAll(), "Edit.SelectAll");
- addMenu(new LLEditDeselect(), "Edit.Deselect");
- addMenu(new LLEditDuplicate(), "Edit.Duplicate");
- addMenu(new LLEditTakeOff(), "Edit.TakeOff");
-
- addMenu(new LLEditEnableUndo(), "Edit.EnableUndo");
- addMenu(new LLEditEnableRedo(), "Edit.EnableRedo");
- addMenu(new LLEditEnableCut(), "Edit.EnableCut");
- addMenu(new LLEditEnableCopy(), "Edit.EnableCopy");
- addMenu(new LLEditEnablePaste(), "Edit.EnablePaste");
- addMenu(new LLEditEnableDelete(), "Edit.EnableDelete");
- addMenu(new LLEditEnableSelectAll(), "Edit.EnableSelectAll");
- addMenu(new LLEditEnableDeselect(), "Edit.EnableDeselect");
- addMenu(new LLEditEnableDuplicate(), "Edit.EnableDuplicate");
- addMenu(new LLEditEnableTakeOff(), "Edit.EnableTakeOff");
- addMenu(new LLEditEnableCustomizeAvatar(), "Edit.EnableCustomizeAvatar");
+ view_listener_t::addMenu(new LLEditUndo(), "Edit.Undo");
+ view_listener_t::addMenu(new LLEditRedo(), "Edit.Redo");
+ view_listener_t::addMenu(new LLEditCut(), "Edit.Cut");
+ view_listener_t::addMenu(new LLEditCopy(), "Edit.Copy");
+ view_listener_t::addMenu(new LLEditPaste(), "Edit.Paste");
+ view_listener_t::addMenu(new LLEditDelete(), "Edit.Delete");
+ view_listener_t::addMenu(new LLEditSelectAll(), "Edit.SelectAll");
+ view_listener_t::addMenu(new LLEditDeselect(), "Edit.Deselect");
+ view_listener_t::addMenu(new LLEditDuplicate(), "Edit.Duplicate");
+ view_listener_t::addMenu(new LLEditTakeOff(), "Edit.TakeOff");
+
+ view_listener_t::addMenu(new LLEditEnableUndo(), "Edit.EnableUndo");
+ view_listener_t::addMenu(new LLEditEnableRedo(), "Edit.EnableRedo");
+ view_listener_t::addMenu(new LLEditEnableCut(), "Edit.EnableCut");
+ view_listener_t::addMenu(new LLEditEnableCopy(), "Edit.EnableCopy");
+ view_listener_t::addMenu(new LLEditEnablePaste(), "Edit.EnablePaste");
+ view_listener_t::addMenu(new LLEditEnableDelete(), "Edit.EnableDelete");
+ view_listener_t::addMenu(new LLEditEnableSelectAll(), "Edit.EnableSelectAll");
+ view_listener_t::addMenu(new LLEditEnableDeselect(), "Edit.EnableDeselect");
+ view_listener_t::addMenu(new LLEditEnableDuplicate(), "Edit.EnableDuplicate");
+ view_listener_t::addMenu(new LLEditEnableTakeOff(), "Edit.EnableTakeOff");
+ view_listener_t::addMenu(new LLEditEnableCustomizeAvatar(), "Edit.EnableCustomizeAvatar");
+ commit.add("CustomizeAvatar", boost::bind(&handle_customize_avatar));
// View menu
- addMenu(new LLViewMouselook(), "View.Mouselook");
- addMenu(new LLViewBuildMode(), "View.BuildMode");
- addMenu(new LLViewJoystickFlycam(), "View.JoystickFlycam");
- addMenu(new LLViewCommunicate(), "View.Communicate");
- addMenu(new LLViewResetView(), "View.ResetView");
- addMenu(new LLViewLookAtLastChatter(), "View.LookAtLastChatter");
- addMenu(new LLViewShowHoverTips(), "View.ShowHoverTips");
- addMenu(new LLViewHighlightTransparent(), "View.HighlightTransparent");
- addMenu(new LLViewToggleRenderType(), "View.ToggleRenderType");
- addMenu(new LLViewShowHUDAttachments(), "View.ShowHUDAttachments");
- addMenu(new LLZoomer(1.2f), "View.ZoomOut");
- addMenu(new LLZoomer(1/1.2f), "View.ZoomIn");
- addMenu(new LLZoomer(DEFAULT_FIELD_OF_VIEW, false), "View.ZoomDefault");
- addMenu(new LLViewFullscreen(), "View.Fullscreen");
- addMenu(new LLViewDefaultUISize(), "View.DefaultUISize");
-
- addMenu(new LLViewEnableMouselook(), "View.EnableMouselook");
- addMenu(new LLViewEnableJoystickFlycam(), "View.EnableJoystickFlycam");
- addMenu(new LLViewEnableLastChatter(), "View.EnableLastChatter");
-
- addMenu(new LLViewCheckBuildMode(), "View.CheckBuildMode");
- addMenu(new LLViewCheckJoystickFlycam(), "View.CheckJoystickFlycam");
- addMenu(new LLViewCheckShowHoverTips(), "View.CheckShowHoverTips");
- addMenu(new LLViewCheckHighlightTransparent(), "View.CheckHighlightTransparent");
- addMenu(new LLViewCheckRenderType(), "View.CheckRenderType");
- addMenu(new LLViewCheckHUDAttachments(), "View.CheckHUDAttachments");
+ view_listener_t::addMenu(new LLViewMouselook(), "View.Mouselook");
+ view_listener_t::addMenu(new LLViewJoystickFlycam(), "View.JoystickFlycam");
+ view_listener_t::addMenu(new LLViewResetView(), "View.ResetView");
+ view_listener_t::addMenu(new LLViewLookAtLastChatter(), "View.LookAtLastChatter");
+ view_listener_t::addMenu(new LLViewShowHoverTips(), "View.ShowHoverTips");
+ view_listener_t::addMenu(new LLViewHighlightTransparent(), "View.HighlightTransparent");
+ view_listener_t::addMenu(new LLViewToggleRenderType(), "View.ToggleRenderType");
+ view_listener_t::addMenu(new LLViewShowHUDAttachments(), "View.ShowHUDAttachments");
+ view_listener_t::addMenu(new LLZoomer(1.2f), "View.ZoomOut");
+ view_listener_t::addMenu(new LLZoomer(1/1.2f), "View.ZoomIn");
+ view_listener_t::addMenu(new LLZoomer(DEFAULT_FIELD_OF_VIEW, false), "View.ZoomDefault");
+ view_listener_t::addMenu(new LLViewFullscreen(), "View.Fullscreen");
+ view_listener_t::addMenu(new LLViewDefaultUISize(), "View.DefaultUISize");
+
+ view_listener_t::addMenu(new LLViewEnableMouselook(), "View.EnableMouselook");
+ view_listener_t::addMenu(new LLViewEnableJoystickFlycam(), "View.EnableJoystickFlycam");
+ view_listener_t::addMenu(new LLViewEnableLastChatter(), "View.EnableLastChatter");
+
+ view_listener_t::addMenu(new LLViewCheckJoystickFlycam(), "View.CheckJoystickFlycam");
+ view_listener_t::addMenu(new LLViewCheckShowHoverTips(), "View.CheckShowHoverTips");
+ view_listener_t::addMenu(new LLViewCheckHighlightTransparent(), "View.CheckHighlightTransparent");
+ view_listener_t::addMenu(new LLViewCheckRenderType(), "View.CheckRenderType");
+ view_listener_t::addMenu(new LLViewCheckHUDAttachments(), "View.CheckHUDAttachments");
// World menu
- addMenu(new LLWorldChat(), "World.Chat");
- addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun");
- addMenu(new LLWorldFly(), "World.Fly");
- addMenu(new LLWorldEnableFly(), "World.EnableFly");
- addMenu(new LLWorldCreateLandmark(), "World.CreateLandmark");
- addMenu(new LLWorldSetHomeLocation(), "World.SetHomeLocation");
- addMenu(new LLWorldTeleportHome(), "World.TeleportHome");
- addMenu(new LLWorldSetAway(), "World.SetAway");
- addMenu(new LLWorldSetBusy(), "World.SetBusy");
-
- addMenu(new LLWorldEnableCreateLandmark(), "World.EnableCreateLandmark");
- addMenu(new LLWorldEnableSetHomeLocation(), "World.EnableSetHomeLocation");
- addMenu(new LLWorldEnableTeleportHome(), "World.EnableTeleportHome");
- addMenu(new LLWorldEnableBuyLand(), "World.EnableBuyLand");
-
- addMenu(new LLWorldCheckAlwaysRun(), "World.CheckAlwaysRun");
+ commit.add("World.Chat", boost::bind(&handle_chat, (void*)NULL));
+ view_listener_t::addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun");
+ view_listener_t::addMenu(new LLWorldCreateLandmark(), "World.CreateLandmark");
+ view_listener_t::addMenu(new LLWorldSetHomeLocation(), "World.SetHomeLocation");
+ view_listener_t::addMenu(new LLWorldTeleportHome(), "World.TeleportHome");
+ view_listener_t::addMenu(new LLWorldSetAway(), "World.SetAway");
+ view_listener_t::addMenu(new LLWorldSetBusy(), "World.SetBusy");
+
+ view_listener_t::addMenu(new LLWorldEnableCreateLandmark(), "World.EnableCreateLandmark");
+ view_listener_t::addMenu(new LLWorldEnableSetHomeLocation(), "World.EnableSetHomeLocation");
+ view_listener_t::addMenu(new LLWorldEnableTeleportHome(), "World.EnableTeleportHome");
+ view_listener_t::addMenu(new LLWorldEnableBuyLand(), "World.EnableBuyLand");
+
+ view_listener_t::addMenu(new LLWorldCheckAlwaysRun(), "World.CheckAlwaysRun");
- (new LLWorldEnvSettings())->registerListener(gMenuHolder, "World.EnvSettings");
- (new LLWorldWaterSettings())->registerListener(gMenuHolder, "World.WaterSettings");
- (new LLWorldPostProcess())->registerListener(gMenuHolder, "World.PostProcess");
- (new LLWorldDayCycle())->registerListener(gMenuHolder, "World.DayCycle");
+ view_listener_t::addMenu(new LLWorldEnvSettings(), "World.EnvSettings");
+ view_listener_t::addMenu(new LLWorldWaterSettings(), "World.WaterSettings");
+ view_listener_t::addMenu(new LLWorldPostProcess(), "World.PostProcess");
+ view_listener_t::addMenu(new LLWorldDayCycle(), "World.DayCycle");
// Tools menu
- addMenu(new LLToolsSelectTool(), "Tools.SelectTool");
- addMenu(new LLToolsSelectOnlyMyObjects(), "Tools.SelectOnlyMyObjects");
- addMenu(new LLToolsSelectOnlyMovableObjects(), "Tools.SelectOnlyMovableObjects");
- addMenu(new LLToolsSelectBySurrounding(), "Tools.SelectBySurrounding");
- addMenu(new LLToolsShowHiddenSelection(), "Tools.ShowHiddenSelection");
- addMenu(new LLToolsShowSelectionLightRadius(), "Tools.ShowSelectionLightRadius");
- addMenu(new LLToolsEditLinkedParts(), "Tools.EditLinkedParts");
- addMenu(new LLToolsSnapObjectXY(), "Tools.SnapObjectXY");
- addMenu(new LLToolsUseSelectionForGrid(), "Tools.UseSelectionForGrid");
- addMenu(new LLToolsLink(), "Tools.Link");
- addMenu(new LLToolsUnlink(), "Tools.Unlink");
- addMenu(new LLToolsStopAllAnimations(), "Tools.StopAllAnimations");
- addMenu(new LLToolsReleaseKeys(), "Tools.ReleaseKeys");
- addMenu(new LLToolsEnableReleaseKeys(), "Tools.EnableReleaseKeys");
- addMenu(new LLToolsLookAtSelection(), "Tools.LookAtSelection");
- addMenu(new LLToolsBuyOrTake(), "Tools.BuyOrTake");
- addMenu(new LLToolsTakeCopy(), "Tools.TakeCopy");
- addMenu(new LLToolsSaveToObjectInventory(), "Tools.SaveToObjectInventory");
- addMenu(new LLToolsSelectedScriptAction(), "Tools.SelectedScriptAction");
-
- addMenu(new LLToolsEnableToolNotPie(), "Tools.EnableToolNotPie");
- addMenu(new LLToolsEnableLink(), "Tools.EnableLink");
- addMenu(new LLToolsEnableUnlink(), "Tools.EnableUnlink");
- addMenu(new LLToolsEnableBuyOrTake(), "Tools.EnableBuyOrTake");
- addMenu(new LLToolsEnableTakeCopy(), "Tools.EnableTakeCopy");
- addMenu(new LLToolsEnableSaveToObjectInventory(), "Tools.EnableSaveToObjectInventory");
-
- /*addMenu(new LLToolsVisibleBuyObject(), "Tools.VisibleBuyObject");
- addMenu(new LLToolsVisibleTakeObject(), "Tools.VisibleTakeObject");*/
+ view_listener_t::addMenu(new LLToolsSelectTool(), "Tools.SelectTool");
+ view_listener_t::addMenu(new LLToolsSelectOnlyMyObjects(), "Tools.SelectOnlyMyObjects");
+ view_listener_t::addMenu(new LLToolsSelectOnlyMovableObjects(), "Tools.SelectOnlyMovableObjects");
+ view_listener_t::addMenu(new LLToolsSelectBySurrounding(), "Tools.SelectBySurrounding");
+ view_listener_t::addMenu(new LLToolsShowHiddenSelection(), "Tools.ShowHiddenSelection");
+ view_listener_t::addMenu(new LLToolsShowSelectionLightRadius(), "Tools.ShowSelectionLightRadius");
+ view_listener_t::addMenu(new LLToolsEditLinkedParts(), "Tools.EditLinkedParts");
+ view_listener_t::addMenu(new LLToolsSnapObjectXY(), "Tools.SnapObjectXY");
+ view_listener_t::addMenu(new LLToolsUseSelectionForGrid(), "Tools.UseSelectionForGrid");
+ view_listener_t::addMenu(new LLToolsSelectNextPart(), "Tools.SelectNextPart");
+ view_listener_t::addMenu(new LLToolsLink(), "Tools.Link");
+ view_listener_t::addMenu(new LLToolsUnlink(), "Tools.Unlink");
+ view_listener_t::addMenu(new LLToolsStopAllAnimations(), "Tools.StopAllAnimations");
+ view_listener_t::addMenu(new LLToolsReleaseKeys(), "Tools.ReleaseKeys");
+ view_listener_t::addMenu(new LLToolsEnableReleaseKeys(), "Tools.EnableReleaseKeys");
+ commit.add("Tools.LookAtSelection", boost::bind(&handle_look_at_selection, _2));
+ commit.add("Tools.BuyOrTake", boost::bind(&handle_buy_or_take));
+ commit.add("Tools.TakeCopy", boost::bind(&handle_take_copy));
+ view_listener_t::addMenu(new LLToolsSaveToInventory(), "Tools.SaveToInventory");
+ view_listener_t::addMenu(new LLToolsSaveToObjectInventory(), "Tools.SaveToObjectInventory");
+ view_listener_t::addMenu(new LLToolsSelectedScriptAction(), "Tools.SelectedScriptAction");
+
+ view_listener_t::addMenu(new LLToolsEnableToolNotPie(), "Tools.EnableToolNotPie");
+ view_listener_t::addMenu(new LLToolsEnableSelectNextPart(), "Tools.EnableSelectNextPart");
+ view_listener_t::addMenu(new LLToolsEnableLink(), "Tools.EnableLink");
+ view_listener_t::addMenu(new LLToolsEnableUnlink(), "Tools.EnableUnlink");
+ view_listener_t::addMenu(new LLToolsEnableBuyOrTake(), "Tools.EnableBuyOrTake");
+ enable.add("Tools.EnableTakeCopy", boost::bind(&enable_object_take_copy));
+ view_listener_t::addMenu(new LLToolsEnableSaveToInventory(), "Tools.EnableSaveToInventory");
+ view_listener_t::addMenu(new LLToolsEnableSaveToObjectInventory(), "Tools.EnableSaveToObjectInventory");
+
+ /*view_listener_t::addMenu(new LLToolsVisibleBuyObject(), "Tools.VisibleBuyObject");
+ view_listener_t::addMenu(new LLToolsVisibleTakeObject(), "Tools.VisibleTakeObject");*/
// Help menu
// most items use the ShowFloater method
+ // Advance menu
+ view_listener_t::addMenu(new LLAdvancedToggleConsole(), "Advanced.ToggleConsole");
+ view_listener_t::addMenu(new LLAdvancedCheckConsole(), "Advanced.CheckConsole");
+ view_listener_t::addMenu(new LLAdvancedDumpInfoToConsole(), "Advanced.DumpInfoToConsole");
+ // Advanced > HUD Info
+ view_listener_t::addMenu(new LLAdvancedToggleHUDInfo(), "Advanced.ToggleHUDInfo");
+ view_listener_t::addMenu(new LLAdvancedCheckHUDInfo(), "Advanced.CheckHUDInfo");
+
+ // Advanced Other Settings
+ view_listener_t::addMenu(new LLAdvancedClearGroupCache(), "Advanced.ClearGroupCache");
+
+ // Advanced > Shortcuts
+ view_listener_t::addMenu(new LLAdvancedAgentFlyingInfo(), "Agent.getFlying");
+
+ // Advanced > Render > Types
+ view_listener_t::addMenu(new LLAdvancedToggleRenderType(), "Advanced.ToggleRenderType");
+ view_listener_t::addMenu(new LLAdvancedCheckRenderType(), "Advanced.CheckRenderType");
+
+ //// Advanced > Render > Features
+ view_listener_t::addMenu(new LLAdvancedToggleFeature(), "Advanced.ToggleFeature");
+ view_listener_t::addMenu(new LLAdvancedCheckFeature(), "Advanced.CheckFeature");
+ // Advanced > Render > Info Displays
+ view_listener_t::addMenu(new LLAdvancedToggleInfoDisplay(), "Advanced.ToggleInfoDisplay");
+ view_listener_t::addMenu(new LLAdvancedCheckInfoDisplay(), "Advanced.CheckInfoDisplay");
+ view_listener_t::addMenu(new LLAdvancedSelectedTextureInfo(), "Advanced.SelectedTextureInfo");
+ view_listener_t::addMenu(new LLAdvancedToggleWireframe(), "Advanced.ToggleWireframe");
+ view_listener_t::addMenu(new LLAdvancedCheckWireframe(), "Advanced.CheckWireframe");
+ view_listener_t::addMenu(new LLAdvancedToggleTextureAtlas(), "Advanced.ToggleTextureAtlas");
+ view_listener_t::addMenu(new LLAdvancedCheckTextureAtlas(), "Advanced.CheckTextureAtlas");
+ 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 LLAdvancedEnableRenderDeferredGI(), "Advanced.EnableRenderDeferredGI");
+ view_listener_t::addMenu(new LLAdvancedToggleRandomizeFramerate(), "Advanced.ToggleRandomizeFramerate");
+ view_listener_t::addMenu(new LLAdvancedCheckRandomizeFramerate(), "Advanced.CheckRandomizeFramerate");
+ view_listener_t::addMenu(new LLAdvancedTogglePeriodicSlowFrame(), "Advanced.TogglePeriodicSlowFrame");
+ view_listener_t::addMenu(new LLAdvancedCheckPeriodicSlowFrame(), "Advanced.CheckPeriodicSlowFrame");
+ view_listener_t::addMenu(new LLAdvancedVectorizePerfTest(), "Advanced.VectorizePerfTest");
+ view_listener_t::addMenu(new LLAdvancedToggleFrameTest(), "Advanced.ToggleFrameTest");
+ view_listener_t::addMenu(new LLAdvancedCheckFrameTest(), "Advanced.CheckFrameTest");
+ view_listener_t::addMenu(new LLAdvancedHandleAttachedLightParticles(), "Advanced.HandleAttachedLightParticles");
+
+
+ #ifdef TOGGLE_HACKED_GODLIKE_VIEWER
+ view_listener_t::addMenu(new LLAdvancedHandleToggleHackedGodmode(), "Advanced.HandleToggleHackedGodmode");
+ view_listener_t::addMenu(new LLAdvancedCheckToggleHackedGodmode(), "Advanced.CheckToggleHackedGodmode");
+ view_listener_t::addMenu(new LLAdvancedEnableToggleHackedGodmode(), "Advanced.EnableToggleHackedGodmode");
+ #endif
+
+ // Advanced > World
+ view_listener_t::addMenu(new LLAdvancedDumpScriptedCamera(), "Advanced.DumpScriptedCamera");
+ view_listener_t::addMenu(new LLAdvancedDumpRegionObjectCache(), "Advanced.DumpRegionObjectCache");
+
+ // Advanced > UI
+ commit.add("Advanced.WebBrowserTest", boost::bind(&handle_web_browser_test, _2));
+ view_listener_t::addMenu(new LLAdvancedBuyCurrencyTest(), "Advanced.BuyCurrencyTest");
+ view_listener_t::addMenu(new LLAdvancedDumpSelectMgr(), "Advanced.DumpSelectMgr");
+ view_listener_t::addMenu(new LLAdvancedDumpInventory(), "Advanced.DumpInventory");
+ commit.add("Advanced.DumpTimers", boost::bind(&handle_dump_timers) );
+ commit.add("Advanced.DumpFocusHolder", boost::bind(&handle_dump_focus) );
+ view_listener_t::addMenu(new LLAdvancedPrintSelectedObjectInfo(), "Advanced.PrintSelectedObjectInfo");
+ view_listener_t::addMenu(new LLAdvancedPrintAgentInfo(), "Advanced.PrintAgentInfo");
+ view_listener_t::addMenu(new LLAdvancedPrintTextureMemoryStats(), "Advanced.PrintTextureMemoryStats");
+ view_listener_t::addMenu(new LLAdvancedToggleDebugClicks(), "Advanced.ToggleDebugClicks");
+ view_listener_t::addMenu(new LLAdvancedCheckDebugClicks(), "Advanced.CheckDebugClicks");
+ view_listener_t::addMenu(new LLAdvancedCheckDebugViews(), "Advanced.CheckDebugViews");
+ view_listener_t::addMenu(new LLAdvancedToggleDebugViews(), "Advanced.ToggleDebugViews");
+ view_listener_t::addMenu(new LLAdvancedToggleXUINameTooltips(), "Advanced.ToggleXUINameTooltips");
+ view_listener_t::addMenu(new LLAdvancedCheckXUINameTooltips(), "Advanced.CheckXUINameTooltips");
+ view_listener_t::addMenu(new LLAdvancedToggleDebugMouseEvents(), "Advanced.ToggleDebugMouseEvents");
+ view_listener_t::addMenu(new LLAdvancedCheckDebugMouseEvents(), "Advanced.CheckDebugMouseEvents");
+ view_listener_t::addMenu(new LLAdvancedToggleDebugKeys(), "Advanced.ToggleDebugKeys");
+ view_listener_t::addMenu(new LLAdvancedCheckDebugKeys(), "Advanced.CheckDebugKeys");
+ view_listener_t::addMenu(new LLAdvancedToggleDebugWindowProc(), "Advanced.ToggleDebugWindowProc");
+ view_listener_t::addMenu(new LLAdvancedCheckDebugWindowProc(), "Advanced.CheckDebugWindowProc");
+ commit.add("Advanced.ShowSideTray", boost::bind(&handle_show_side_tray));
+
+ // Advanced > XUI
+ commit.add("Advanced.ReloadColorSettings", boost::bind(&LLUIColorTable::loadFromSettings, LLUIColorTable::getInstance()));
+ view_listener_t::addMenu(new LLAdvancedLoadUIFromXML(), "Advanced.LoadUIFromXML");
+ view_listener_t::addMenu(new LLAdvancedSaveUIToXML(), "Advanced.SaveUIToXML");
+ view_listener_t::addMenu(new LLAdvancedToggleXUINames(), "Advanced.ToggleXUINames");
+ view_listener_t::addMenu(new LLAdvancedCheckXUINames(), "Advanced.CheckXUINames");
+ view_listener_t::addMenu(new LLAdvancedSendTestIms(), "Advanced.SendTestIMs");
+
+ // Advanced > Character > Grab Baked Texture
+ view_listener_t::addMenu(new LLAdvancedGrabBakedTexture(), "Advanced.GrabBakedTexture");
+ view_listener_t::addMenu(new LLAdvancedEnableGrabBakedTexture(), "Advanced.EnableGrabBakedTexture");
+
+ // Advanced > Character > Character Tests
+ view_listener_t::addMenu(new LLAdvancedAppearanceToXML(), "Advanced.AppearanceToXML");
+ view_listener_t::addMenu(new LLAdvancedToggleCharacterGeometry(), "Advanced.ToggleCharacterGeometry");
+
+ view_listener_t::addMenu(new LLAdvancedTestMale(), "Advanced.TestMale");
+ view_listener_t::addMenu(new LLAdvancedTestFemale(), "Advanced.TestFemale");
+ view_listener_t::addMenu(new LLAdvancedTogglePG(), "Advanced.TogglePG");
+
+ // Advanced > Character (toplevel)
+ view_listener_t::addMenu(new LLAdvancedForceParamsToDefault(), "Advanced.ForceParamsToDefault");
+ view_listener_t::addMenu(new LLAdvancedReloadVertexShader(), "Advanced.ReloadVertexShader");
+ view_listener_t::addMenu(new LLAdvancedToggleAnimationInfo(), "Advanced.ToggleAnimationInfo");
+ view_listener_t::addMenu(new LLAdvancedCheckAnimationInfo(), "Advanced.CheckAnimationInfo");
+ view_listener_t::addMenu(new LLAdvancedToggleShowLookAt(), "Advanced.ToggleShowLookAt");
+ view_listener_t::addMenu(new LLAdvancedCheckShowLookAt(), "Advanced.CheckShowLookAt");
+ view_listener_t::addMenu(new LLAdvancedToggleShowPointAt(), "Advanced.ToggleShowPointAt");
+ view_listener_t::addMenu(new LLAdvancedCheckShowPointAt(), "Advanced.CheckShowPointAt");
+ view_listener_t::addMenu(new LLAdvancedToggleDebugJointUpdates(), "Advanced.ToggleDebugJointUpdates");
+ view_listener_t::addMenu(new LLAdvancedCheckDebugJointUpdates(), "Advanced.CheckDebugJointUpdates");
+ view_listener_t::addMenu(new LLAdvancedToggleDisableLOD(), "Advanced.ToggleDisableLOD");
+ view_listener_t::addMenu(new LLAdvancedCheckDisableLOD(), "Advanced.CheckDisableLOD");
+ view_listener_t::addMenu(new LLAdvancedToggleDebugCharacterVis(), "Advanced.ToggleDebugCharacterVis");
+ view_listener_t::addMenu(new LLAdvancedCheckDebugCharacterVis(), "Advanced.CheckDebugCharacterVis");
+ view_listener_t::addMenu(new LLAdvancedDumpAttachments(), "Advanced.DumpAttachments");
+ view_listener_t::addMenu(new LLAdvancedRebakeTextures(), "Advanced.RebakeTextures");
+ view_listener_t::addMenu(new LLAdvancedDebugAvatarTextures(), "Advanced.DebugAvatarTextures");
+ view_listener_t::addMenu(new LLAdvancedDumpAvatarLocalTextures(), "Advanced.DumpAvatarLocalTextures");
+ // Advanced > Network
+ view_listener_t::addMenu(new LLAdvancedEnableMessageLog(), "Advanced.EnableMessageLog");
+ view_listener_t::addMenu(new LLAdvancedDisableMessageLog(), "Advanced.DisableMessageLog");
+ view_listener_t::addMenu(new LLAdvancedDropPacket(), "Advanced.DropPacket");
+
+ // Advanced > Recorder
+ view_listener_t::addMenu(new LLAdvancedAgentPilot(), "Advanced.AgentPilot");
+ view_listener_t::addMenu(new LLAdvancedToggleAgentPilotLoop(), "Advanced.ToggleAgentPilotLoop");
+ view_listener_t::addMenu(new LLAdvancedCheckAgentPilotLoop(), "Advanced.CheckAgentPilotLoop");
+
+ // Advanced > Debugging
+ 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 LLAdvancedForceErrorInfiniteLoop(), "Advanced.ForceErrorInfiniteLoop");
+ view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareException(), "Advanced.ForceErrorSoftwareException");
+ view_listener_t::addMenu(new LLAdvancedForceErrorDriverCrash(), "Advanced.ForceErrorDriverCrash");
+ view_listener_t::addMenu(new LLAdvancedForceErrorDisconnectViewer(), "Advanced.ForceErrorDisconnectViewer");
+
+ // Advanced (toplevel)
+ view_listener_t::addMenu(new LLAdvancedToggleShowObjectUpdates(), "Advanced.ToggleShowObjectUpdates");
+ view_listener_t::addMenu(new LLAdvancedCheckShowObjectUpdates(), "Advanced.CheckShowObjectUpdates");
+ view_listener_t::addMenu(new LLAdvancedCompressImage(), "Advanced.CompressImage");
+ view_listener_t::addMenu(new LLAdvancedShowDebugSettings(), "Advanced.ShowDebugSettings");
+ view_listener_t::addMenu(new LLAdvancedToggleViewAdminOptions(), "Advanced.ToggleViewAdminOptions");
+ view_listener_t::addMenu(new LLAdvancedCheckViewAdminOptions(), "Advanced.CheckViewAdminOptions");
+ view_listener_t::addMenu(new LLAdvancedRequestAdminStatus(), "Advanced.RequestAdminStatus");
+ view_listener_t::addMenu(new LLAdvancedLeaveAdminStatus(), "Advanced.LeaveAdminStatus");
+
+
+ // Admin >Object
+ view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy");
+ view_listener_t::addMenu(new LLAdminHandleObjectOwnerSelf(), "Admin.HandleObjectOwnerSelf");
+ view_listener_t::addMenu(new LLAdminHandleObjectOwnerPermissive(), "Admin.HandleObjectOwnerPermissive");
+ view_listener_t::addMenu(new LLAdminHandleForceDelete(), "Admin.HandleForceDelete");
+ view_listener_t::addMenu(new LLAdminHandleObjectLock(), "Admin.HandleObjectLock");
+ view_listener_t::addMenu(new LLAdminHandleObjectAssetIDs(), "Admin.HandleObjectAssetIDs");
+
+ // Admin >Parcel
+ view_listener_t::addMenu(new LLAdminHandleForceParcelOwnerToMe(), "Admin.HandleForceParcelOwnerToMe");
+ view_listener_t::addMenu(new LLAdminHandleForceParcelToContent(), "Admin.HandleForceParcelToContent");
+ view_listener_t::addMenu(new LLAdminHandleClaimPublicLand(), "Admin.HandleClaimPublicLand");
+
+ // Admin >Region
+ view_listener_t::addMenu(new LLAdminHandleRegionDumpTempAssetData(), "Admin.HandleRegionDumpTempAssetData");
+ // Admin top level
+ view_listener_t::addMenu(new LLAdminOnSaveState(), "Admin.OnSaveState");
+
// Self pie menu
- addMenu(new LLSelfStandUp(), "Self.StandUp");
- addMenu(new LLSelfRemoveAllAttachments(), "Self.RemoveAllAttachments");
+ view_listener_t::addMenu(new LLSelfStandUp(), "Self.StandUp");
+ view_listener_t::addMenu(new LLSelfRemoveAllAttachments(), "Self.RemoveAllAttachments");
+
+ enable.add("Self.EnableStandUp", boost::bind(&enable_standup_self));
+ view_listener_t::addMenu(new LLSelfEnableRemoveAllAttachments(), "Self.EnableRemoveAllAttachments");
- addMenu(new LLSelfEnableStandUp(), "Self.EnableStandUp");
- addMenu(new LLSelfEnableRemoveAllAttachments(), "Self.EnableRemoveAllAttachments");
+ // we don't use boost::bind directly to delay side tray construction
+ view_listener_t::addMenu( new LLTogglePanelPeopleTab(), "SideTray.PanelPeopleTab");
// Avatar pie menu
- addMenu(new LLObjectMute(), "Avatar.Mute");
- addMenu(new LLAvatarAddFriend(), "Avatar.AddFriend");
- addMenu(new LLAvatarFreeze(), "Avatar.Freeze");
- addMenu(new LLAvatarDebug(), "Avatar.Debug");
- addMenu(new LLAvatarVisibleDebug(), "Avatar.VisibleDebug");
- addMenu(new LLAvatarEnableDebug(), "Avatar.EnableDebug");
- addMenu(new LLAvatarInviteToGroup(), "Avatar.InviteToGroup");
- addMenu(new LLAvatarGiveCard(), "Avatar.GiveCard");
- addMenu(new LLAvatarEject(), "Avatar.Eject");
- addMenu(new LLAvatarSendIM(), "Avatar.SendIM");
- addMenu(new LLAvatarReportAbuse(), "Avatar.ReportAbuse");
+ view_listener_t::addMenu(new LLObjectMute(), "Avatar.Mute");
+ view_listener_t::addMenu(new LLAvatarAddFriend(), "Avatar.AddFriend");
+ view_listener_t::addMenu(new LLAvatarAddContact(), "Avatar.AddContact");
+ commit.add("Avatar.Freeze", boost::bind(&handle_avatar_freeze, LLSD()));
+ view_listener_t::addMenu(new LLAvatarDebug(), "Avatar.Debug");
+ view_listener_t::addMenu(new LLAvatarVisibleDebug(), "Avatar.VisibleDebug");
+ view_listener_t::addMenu(new LLAvatarInviteToGroup(), "Avatar.InviteToGroup");
+ view_listener_t::addMenu(new LLAvatarGiveCard(), "Avatar.GiveCard");
+ commit.add("Avatar.Eject", boost::bind(&handle_avatar_eject, LLSD()));
+ view_listener_t::addMenu(new LLAvatarSendIM(), "Avatar.SendIM");
+ view_listener_t::addMenu(new LLAvatarCall(), "Avatar.Call");
+ view_listener_t::addMenu(new LLAvatarReportAbuse(), "Avatar.ReportAbuse");
- addMenu(new LLObjectEnableMute(), "Avatar.EnableMute");
- addMenu(new LLAvatarEnableAddFriend(), "Avatar.EnableAddFriend");
- addMenu(new LLAvatarEnableFreezeEject(), "Avatar.EnableFreezeEject");
+ view_listener_t::addMenu(new LLAvatarEnableAddFriend(), "Avatar.EnableAddFriend");
+ enable.add("Avatar.EnableFreezeEject", boost::bind(&enable_freeze_eject, _2));
+ enable.add("Avatar.EnableFreezeEject", boost::bind(&enable_freeze_eject, _2));
// Object pie menu
- addMenu(new LLObjectOpen(), "Object.Open");
- addMenu(new LLObjectBuild(), "Object.Build");
- addMenu(new LLObjectTouch(), "Object.Touch");
- addMenu(new LLObjectSitOrStand(), "Object.SitOrStand");
- addMenu(new LLObjectDelete(), "Object.Delete");
- addMenu(new LLObjectAttachToAvatar(), "Object.AttachToAvatar");
- addMenu(new LLObjectReturn(), "Object.Return");
- addMenu(new LLObjectReportAbuse(), "Object.ReportAbuse");
- addMenu(new LLObjectMute(), "Object.Mute");
- addMenu(new LLObjectBuy(), "Object.Buy");
- addMenu(new LLObjectEdit(), "Object.Edit");
- addMenu(new LLObjectInspect(), "Object.Inspect");
-
- addMenu(new LLObjectEnableOpen(), "Object.EnableOpen");
- addMenu(new LLObjectEnableTouch(), "Object.EnableTouch");
- addMenu(new LLObjectEnableSitOrStand(), "Object.EnableSitOrStand");
- addMenu(new LLObjectEnableDelete(), "Object.EnableDelete");
- addMenu(new LLObjectEnableWear(), "Object.EnableWear");
- addMenu(new LLObjectEnableReturn(), "Object.EnableReturn");
- addMenu(new LLObjectEnableReportAbuse(), "Object.EnableReportAbuse");
- addMenu(new LLObjectEnableMute(), "Object.EnableMute");
- addMenu(new LLObjectEnableBuy(), "Object.EnableBuy");
-
- /*addMenu(new LLObjectVisibleTouch(), "Object.VisibleTouch");
- addMenu(new LLObjectVisibleCustomTouch(), "Object.VisibleCustomTouch");
- addMenu(new LLObjectVisibleStandUp(), "Object.VisibleStandUp");
- addMenu(new LLObjectVisibleSitHere(), "Object.VisibleSitHere");
- addMenu(new LLObjectVisibleCustomSit(), "Object.VisibleCustomSit");*/
+ view_listener_t::addMenu(new LLObjectBuild(), "Object.Build");
+ commit.add("Object.Touch", boost::bind(&handle_object_touch));
+ commit.add("Object.SitOrStand", boost::bind(&handle_object_sit_or_stand));
+ enable.add("Object.EnableSit", boost::bind(&enable_sit_object));
+ commit.add("Object.Delete", boost::bind(&handle_object_delete));
+ view_listener_t::addMenu(new LLObjectAttachToAvatar(), "Object.AttachToAvatar");
+ view_listener_t::addMenu(new LLObjectReturn(), "Object.Return");
+ view_listener_t::addMenu(new LLObjectReportAbuse(), "Object.ReportAbuse");
+ view_listener_t::addMenu(new LLObjectMute(), "Object.Mute");
+
+ enable.add("Object.VisibleTake", boost::bind(&visible_take_object));
+ enable.add("Object.VisibleBuy", boost::bind(&visible_buy_object));
+
+ commit.add("Object.Buy", boost::bind(&handle_buy));
+ commit.add("Object.Edit", boost::bind(&handle_object_edit));
+ commit.add("Object.Inspect", boost::bind(&handle_object_inspect));
+ commit.add("Object.Open", boost::bind(&handle_object_open));
+ commit.add("Object.Take", boost::bind(&handle_take));
+ enable.add("Object.EnableOpen", boost::bind(&enable_object_open));
+ enable.add("Object.EnableTouch", boost::bind(&enable_object_touch));
+ view_listener_t::addMenu(new LLObjectEnableTouch(), "Object.EnableTouch");
+ view_listener_t::addMenu(new LLObjectEnableSitOrStand(), "Object.EnableSitOrStand");
+ enable.add("Object.EnableDelete", boost::bind(&enable_object_delete));
+ enable.add("Object.EnableWear", boost::bind(&object_selected_and_point_valid));
+
+ view_listener_t::addMenu(new LLObjectEnableReturn(), "Object.EnableReturn");
+ view_listener_t::addMenu(new LLObjectEnableReportAbuse(), "Object.EnableReportAbuse");
+
+ enable.add("Avatar.EnableMute", boost::bind(&enable_object_mute));
+ enable.add("Object.EnableMute", boost::bind(&enable_object_mute));
+ enable.add("Object.EnableBuy", boost::bind(&enable_buy_object));
+ commit.add("Object.ZoomIn", boost::bind(&handle_look_at_selection, "zoom"));
// Attachment pie menu
- addMenu(new LLAttachmentDrop(), "Attachment.Drop");
- addMenu(new LLAttachmentDetach(), "Attachment.Detach");
-
- addMenu(new LLAttachmentEnableDrop(), "Attachment.EnableDrop");
- addMenu(new LLAttachmentEnableDetach(), "Attachment.EnableDetach");
+ enable.add("Attachment.Label", boost::bind(&onEnableAttachmentLabel, _1, _2));
+ view_listener_t::addMenu(new LLAttachmentDrop(), "Attachment.Drop");
+ view_listener_t::addMenu(new LLAttachmentDetachFromPoint(), "Attachment.DetachFromPoint");
+ view_listener_t::addMenu(new LLAttachmentDetach(), "Attachment.Detach");
+ view_listener_t::addMenu(new LLAttachmentPointFilled(), "Attachment.PointFilled");
+ view_listener_t::addMenu(new LLAttachmentEnableDrop(), "Attachment.EnableDrop");
+ view_listener_t::addMenu(new LLAttachmentEnableDetach(), "Attachment.EnableDetach");
// Land pie menu
- addMenu(new LLLandBuild(), "Land.Build");
- addMenu(new LLLandSit(), "Land.Sit");
- addMenu(new LLLandBuyPass(), "Land.BuyPass");
- addMenu(new LLLandEdit(), "Land.Edit");
+ view_listener_t::addMenu(new LLLandBuild(), "Land.Build");
+ view_listener_t::addMenu(new LLLandSit(), "Land.Sit");
+ view_listener_t::addMenu(new LLLandBuyPass(), "Land.BuyPass");
+ view_listener_t::addMenu(new LLLandEdit(), "Land.Edit");
- addMenu(new LLLandEnableBuyPass(), "Land.EnableBuyPass");
+ view_listener_t::addMenu(new LLLandEnableBuyPass(), "Land.EnableBuyPass");
+ commit.add("Land.Buy", boost::bind(&handle_buy_land));
// Generic actions
- addMenu(new LLShowFloater(), "ShowFloater");
- addMenu(new LLPromptShowURL(), "PromptShowURL");
- addMenu(new LLShowAgentProfile(), "ShowAgentProfile");
- addMenu(new LLShowAgentGroups(), "ShowAgentGroups");
- addMenu(new LLToggleControl(), "ToggleControl");
-
- addMenu(new LLGoToObject(), "GoToObject");
- addMenu(new LLPayObject(), "PayObject");
-
- addMenu(new LLEnablePayObject(), "EnablePayObject");
- addMenu(new LLEnableEdit(), "EnableEdit");
-
- addMenu(new LLFloaterVisible(), "FloaterVisible");
- addMenu(new LLSomethingSelected(), "SomethingSelected");
- addMenu(new LLSomethingSelectedNoHUD(), "SomethingSelectedNoHUD");
- addMenu(new LLEditableSelected(), "EditableSelected");
- addMenu(new LLEditableSelectedMono(), "EditableSelectedMono");
+ commit.add("ReportAbuse", boost::bind(&handle_report_abuse));
+ commit.add("BuyCurrency", boost::bind(&handle_buy_currency));
+ view_listener_t::addMenu(new LLShowHelp(), "ShowHelp");
+ view_listener_t::addMenu(new LLPromptShowURL(), "PromptShowURL");
+ view_listener_t::addMenu(new LLShowAgentProfile(), "ShowAgentProfile");
+ view_listener_t::addMenu(new LLToggleControl(), "ToggleControl");
+ view_listener_t::addMenu(new LLCheckControl(), "CheckControl");
+ view_listener_t::addMenu(new LLGoToObject(), "GoToObject");
+ commit.add("PayObject", boost::bind(&handle_give_money_dialog));
+
+ enable.add("EnablePayObject", boost::bind(&enable_pay_object));
+ enable.add("EnablePayAvatar", boost::bind(&enable_pay_avatar));
+ enable.add("EnableEdit", boost::bind(&enable_object_edit));
+ enable.add("VisibleBuild", boost::bind(&enable_object_build));
+
+ view_listener_t::addMenu(new LLFloaterVisible(), "FloaterVisible");
+ view_listener_t::addMenu(new LLShowSidetrayPanel(), "ShowSidetrayPanel");
+ view_listener_t::addMenu(new LLSomethingSelected(), "SomethingSelected");
+ view_listener_t::addMenu(new LLSomethingSelectedNoHUD(), "SomethingSelectedNoHUD");
+ view_listener_t::addMenu(new LLEditableSelected(), "EditableSelected");
+ view_listener_t::addMenu(new LLEditableSelectedMono(), "EditableSelectedMono");
+
}
diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h
index e9fedf37d8..d3c34f0de4 100644
--- a/indra/newview/llviewermenu.h
+++ b/indra/newview/llviewermenu.h
@@ -34,23 +34,24 @@
#define LL_LLVIEWERMENU_H
#include "llmenugl.h"
+#include "llsafehandle.h"
-//newview includes
-#include "llfilepicker.h"
-
+class LLMessageSystem;
+class LLSD;
class LLUICtrl;
class LLView;
class LLParcelSelection;
class LLObjectSelection;
+class LLSelectNode;
-
-void pre_init_menus();
void init_menus();
void cleanup_menus();
void show_debug_menus(); // checks for if menus should be shown first.
+void toggle_debug_menus(void*);
void show_context_menu( S32 x, S32 y, MASK mask );
void show_build_mode_context_menu(S32 x, S32 y, MASK mask);
+void show_navbar_context_menu(LLView* ctrl, S32 x, S32 y);
BOOL enable_save_into_inventory(void*);
void handle_reset_view();
void handle_cut(void*);
@@ -75,51 +76,70 @@ BOOL enable_deselect(void*);
BOOL enable_undo(void*);
BOOL enable_redo(void*);
-// returns TRUE if we have a friend relationship with agent_id
-BOOL is_agent_friend(const LLUUID& agent_id);
BOOL is_agent_mappable(const LLUUID& agent_id);
-void menu_toggle_control( void* user_data );
void confirm_replace_attachment(S32 option, void* user_data);
-void handle_detach_from_avatar(void* user_data);
-void attach_label(std::string& label, void* user_data);
-void detach_label(std::string& label, void* user_data);
-BOOL object_selected_and_point_valid(void* user_data);
-BOOL object_attached(void* user_data);
+void handle_detach_from_avatar(const LLSD& user_data);
+void attach_label(std::string& label, const LLSD&);
+void detach_label(std::string& label, const LLSD&);
void handle_detach(void*);
BOOL enable_god_full(void* user_data);
BOOL enable_god_liaison(void* user_data);
-BOOL enable_god_customer_service(void* user_data);
BOOL enable_god_basic(void* user_data);
-void handle_show_newest_map(void*);
void set_underclothes_menu_options();
void exchange_callingcard(const LLUUID& dest_id);
void handle_gestures(void*);
void handle_sit_down(void*);
-bool toggle_build_mode();
void handle_object_build(void*);
+void handle_object_touch();
+bool enable_object_open();
+void handle_object_open();
+
+// Buy either contents or object itself
+void handle_buy();
+void handle_take_copy();
+void handle_look_at_selection(const LLSD& param);
+void handle_zoom_to_object(LLUUID object_id);
+
+void handle_buy_land();
+
+// Takes avatar UUID, or if no UUID passed, uses last selected object
+void handle_avatar_freeze(const LLSD& avatar_id);
+
+// Takes avatar UUID, or if no UUID passed, uses last selected object
+void handle_avatar_eject(const LLSD& avatar_id);
+
+bool enable_freeze_eject(const LLSD& avatar_id);
+
+// Can anyone take a free copy of the object?
+// *TODO: Move to separate file
+bool anyone_copy_selection(LLSelectNode* nodep);
+
+// Is this selected object for sale?
+// *TODO: Move to separate file
+bool for_sale_selection(LLSelectNode* nodep);
+
void handle_save_snapshot(void *);
void handle_toggle_flycam();
-bool handle_sit_or_stand();
-bool handle_give_money_dialog();
-bool handle_object_open();
+void handle_object_sit_or_stand();
+void handle_give_money_dialog();
+bool enable_pay_object();
+bool enable_buy_object();
bool handle_go_to();
// Export to XML or Collada
void handle_export_selected( void * );
-// Pass in an empty string and this function will build a string that
-// describes buyer permissions.
-class LLSaleInfo;
-class LLPermissions;
-
class LLViewerMenuHolderGL : public LLMenuHolderGL
{
public:
- LLViewerMenuHolderGL();
+ struct Params : public LLInitParam::Block<Params, LLMenuHolderGL::Params>
+ {};
+
+ LLViewerMenuHolderGL(const Params& p);
virtual BOOL hideMenus();
@@ -141,31 +161,24 @@ extern LLMenuGL* gPopupMenuView;
extern LLViewerMenuHolderGL* gMenuHolder;
extern LLMenuBarGL* gLoginMenuBarView;
-// Pie menus
-extern LLPieMenu *gPieSelf;
-extern LLPieMenu *gPieAvatar;
-extern LLPieMenu *gPieObject;
-extern LLPieMenu *gPieAttachment;
-extern LLPieMenu *gPieLand;
-extern LLPieMenu* gPieRate;
-
-// Pie menus
-extern LLPieMenu *gPieSelfSimple;
-extern LLPieMenu *gPieAvatarSimple;
-extern LLPieMenu *gPieObjectSimple;
-extern LLPieMenu *gPieAttachmentSimple;
-extern LLPieMenu *gPieLandSimple;
+// Context menus in 3D scene
+extern LLContextMenu *gMenuAvatarSelf;
+extern LLContextMenu *gMenuAvatarOther;
+extern LLContextMenu *gMenuObject;
+extern LLContextMenu *gMenuAttachmentSelf;
+extern LLContextMenu *gMenuAttachmentOther;
+extern LLContextMenu *gMenuLand;
// Needed to build menus when attachment site list available
extern LLMenuGL* gAttachSubMenu;
extern LLMenuGL* gDetachSubMenu;
extern LLMenuGL* gTakeOffClothes;
-extern LLPieMenu* gAttachScreenPieMenu;
-extern LLPieMenu* gDetachScreenPieMenu;
-extern LLPieMenu* gAttachPieMenu;
-extern LLPieMenu* gDetachPieMenu;
-extern LLPieMenu* gAttachBodyPartPieMenus[8];
-extern LLPieMenu* gDetachBodyPartPieMenus[8];
+extern LLContextMenu* gAttachScreenPieMenu;
+extern LLContextMenu* gDetachScreenPieMenu;
+extern LLContextMenu* gAttachPieMenu;
+extern LLContextMenu* gDetachPieMenu;
+extern LLContextMenu* gAttachBodyPartPieMenus[8];
+extern LLContextMenu* gDetachBodyPartPieMenus[8];
extern LLMenuItemCallGL* gAFKMenu;
extern LLMenuItemCallGL* gBusyMenu;
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 5240fd3211..6bad8843fd 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -37,60 +37,55 @@
// project includes
#include "llagent.h"
#include "llfilepicker.h"
-#include "llfloateranimpreview.h"
+#include "llfloaterreg.h"
#include "llfloaterbuycurrency.h"
-#include "llfloaterimagepreview.h"
-#include "llfloaternamedesc.h"
#include "llfloatersnapshot.h"
+#include "llimage.h"
+#include "llimagebmp.h"
+#include "llimagepng.h"
+#include "llimagej2c.h"
+#include "llimagejpeg.h"
+#include "llimagetga.h"
#include "llinventorymodel.h" // gInventory
#include "llresourcedata.h"
#include "llfloaterperms.h"
#include "llstatusbar.h"
#include "llviewercontrol.h" // gSavedSettings
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "lluictrlfactory.h"
+#include "llvfile.h"
+#include "llvfs.h"
+#include "llviewerinventory.h"
#include "llviewermenu.h" // gMenuHolder
#include "llviewerregion.h"
#include "llviewerstats.h"
#include "llviewerwindow.h"
#include "llappviewer.h"
#include "lluploaddialog.h"
+#include "lltrans.h"
// linden libraries
#include "llassetuploadresponders.h"
#include "lleconomy.h"
#include "llhttpclient.h"
-#include "llmemberlistener.h"
+#include "llnotificationsutil.h"
#include "llsdserialize.h"
#include "llstring.h"
#include "lltransactiontypes.h"
#include "lluuid.h"
-#include "vorbisencode.h"
+#include "llvorbisencode.h"
+#include "message.h"
// system libraries
#include <boost/tokenizer.hpp>
-typedef LLMemberListener<LLView> view_listener_t;
-
-
-class LLFileEnableSaveAs : public view_listener_t
-{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- bool new_value = gFloaterView->getFrontmost() && gFloaterView->getFrontmost()->canSaveAs();
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
- }
-};
-
class LLFileEnableUpload : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = gStatusBar && LLGlobalEconomy::Singleton::getInstance() && (gStatusBar->getBalance() >= LLGlobalEconomy::Singleton::getInstance()->getPriceUpload());
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
@@ -181,7 +176,7 @@ const std::string upload_pick(void* data)
// No extension
LLSD args;
args["FILE"] = short_name;
- LLNotifications::instance().add("NoFileExtension", args);
+ LLNotificationsUtil::add("NoFileExtension", args);
return std::string();
}
else
@@ -224,8 +219,8 @@ const std::string upload_pick(void* data)
LLSD args;
args["EXTENSION"] = ext;
args["VALIDS"] = valid_extensions;
- LLNotifications::instance().add("InvalidFileExtension", args);
- return NULL;
+ LLNotificationsUtil::add("InvalidFileExtension", args);
+ return std::string();
}
}//end else (non-null extension)
@@ -242,7 +237,7 @@ const std::string upload_pick(void* data)
llinfos << error_msg << ": " << filename << llendl;
LLSD args;
args["FILE"] = filename;
- LLNotifications::instance().add( error_msg, args );
+ LLNotificationsUtil::add( error_msg, args );
return std::string();
}
}//end if a wave/sound file
@@ -253,13 +248,12 @@ const std::string upload_pick(void* data)
class LLFileUploadImage : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
std::string filename = upload_pick((void *)LLFilePicker::FFLOAD_IMAGE);
if (!filename.empty())
{
- LLFloaterImagePreview* floaterp = new LLFloaterImagePreview(filename);
- LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_image_preview.xml");
+ LLFloaterReg::showInstance("upload_image", LLSD(filename));
}
return TRUE;
}
@@ -267,14 +261,12 @@ class LLFileUploadImage : public view_listener_t
class LLFileUploadSound : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
std::string filename = upload_pick((void*)LLFilePicker::FFLOAD_WAV);
if (!filename.empty())
{
- LLFloaterNameDesc* floaterp = new LLFloaterNameDesc(filename);
- LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_sound_preview.xml");
- floaterp->childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload() ));
+ LLFloaterReg::showInstance("upload_sound", LLSD(filename));
}
return true;
}
@@ -282,13 +274,12 @@ class LLFileUploadSound : public view_listener_t
class LLFileUploadAnim : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
const std::string filename = upload_pick((void*)LLFilePicker::FFLOAD_ANIM);
if (!filename.empty())
{
- LLFloaterAnimPreview* floaterp = new LLFloaterAnimPreview(filename);
- LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_animation_preview.xml");
+ LLFloaterReg::showInstance("upload_anim", LLSD(filename));
}
return true;
}
@@ -296,7 +287,7 @@ class LLFileUploadAnim : public view_listener_t
class LLFileUploadBulk : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
if( gAgent.cameraMouselook() )
{
@@ -329,7 +320,7 @@ class LLFileUploadBulk : public view_listener_t
LLAssetStorage::LLStoreAssetCallback callback = NULL;
S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
void *userdata = NULL;
- upload_new_resource(filename, asset_name, asset_name, 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE,
+ upload_new_resource(filename, asset_name, asset_name, 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(),
display_name,
callback, expected_upload_cost, userdata);
@@ -348,7 +339,7 @@ class LLFileUploadBulk : public view_listener_t
void upload_error(const std::string& error_message, const std::string& label, const std::string& filename, const LLSD& args)
{
llwarns << error_message << llendl;
- LLNotifications::instance().add(label, args);
+ LLNotificationsUtil::add(label, args);
if(LLFile::remove(filename) == -1)
{
lldebugs << "unable to remove temp file" << llendl;
@@ -358,19 +349,16 @@ void upload_error(const std::string& error_message, const std::string& label, co
class LLFileEnableCloseWindow : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool new_value = NULL != LLFloater::getClosableFloaterFromFocus();
-
- // horrendously opaque, this code
- gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
- return true;
+ return new_value;
}
};
class LLFileCloseWindow : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
LLFloater::closeFocusedFloater();
@@ -380,17 +368,16 @@ class LLFileCloseWindow : public view_listener_t
class LLFileEnableCloseAllWindows : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool open_children = gFloaterView->allChildrenClosed();
- gMenuHolder->findControl(userdata["control"].asString())->setValue(!open_children);
- return true;
+ return !open_children;
}
};
class LLFileCloseAllWindows : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
bool app_quitting = false;
gFloaterView->closeAllChildren(app_quitting);
@@ -399,36 +386,14 @@ class LLFileCloseAllWindows : public view_listener_t
}
};
-class LLFileSaveTexture : public view_listener_t
-{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- LLFloater* top = gFloaterView->getFrontmost();
- if (top)
- {
- top->saveAs();
- }
- return true;
- }
-};
-
-class LLFileTakeSnapshot : public view_listener_t
-{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
- {
- LLFloaterSnapshot::show(NULL);
- return true;
- }
-};
-
class LLFileTakeSnapshotToDisk : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
LLPointer<LLImageRaw> raw = new LLImageRaw;
- S32 width = gViewerWindow->getWindowDisplayWidth();
- S32 height = gViewerWindow->getWindowDisplayHeight();
+ S32 width = gViewerWindow->getWindowWidthRaw();
+ S32 height = gViewerWindow->getWindowHeightRaw();
if (gSavedSettings.getBOOL("HighResSnapshot"))
{
@@ -475,23 +440,13 @@ class LLFileTakeSnapshotToDisk : public view_listener_t
class LLFileQuit : public view_listener_t
{
- bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ bool handleEvent(const LLSD& userdata)
{
LLAppViewer::instance()->userQuit();
return true;
}
};
-void handle_upload(void* data)
-{
- const std::string filename = upload_pick(data);
- if (!filename.empty())
- {
- LLFloaterNameDesc* floaterp = new LLFloaterNameDesc(filename);
- LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_name_description.xml");
- floaterp->childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload() ));
- }
-}
void handle_compress_image(void*)
{
@@ -508,7 +463,7 @@ void handle_compress_image(void*)
BOOL success;
- success = LLViewerImageList::createUploadFile(infile, outfile, IMG_CODEC_TGA);
+ success = LLViewerTextureList::createUploadFile(infile, outfile, IMG_CODEC_TGA);
if (success)
{
@@ -526,7 +481,7 @@ void handle_compress_image(void*)
void upload_new_resource(const std::string& src_filename, std::string name,
std::string desc, S32 compression_info,
- LLAssetType::EType destination_folder_type,
+ LLFolderType::EType destination_folder_type,
LLInventoryType::EType inv_type,
U32 next_owner_perms,
U32 group_perms,
@@ -564,7 +519,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
else if( exten == "bmp")
{
asset_type = LLAssetType::AT_TEXTURE;
- if (!LLViewerImageList::createUploadFile(src_filename,
+ if (!LLViewerTextureList::createUploadFile(src_filename,
filename,
IMG_CODEC_BMP ))
{
@@ -579,7 +534,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
else if( exten == "tga")
{
asset_type = LLAssetType::AT_TEXTURE;
- if (!LLViewerImageList::createUploadFile(src_filename,
+ if (!LLViewerTextureList::createUploadFile(src_filename,
filename,
IMG_CODEC_TGA ))
{
@@ -594,7 +549,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
else if( exten == "jpg" || exten == "jpeg")
{
asset_type = LLAssetType::AT_TEXTURE;
- if (!LLViewerImageList::createUploadFile(src_filename,
+ if (!LLViewerTextureList::createUploadFile(src_filename,
filename,
IMG_CODEC_JPEG ))
{
@@ -609,7 +564,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
else if( exten == "png")
{
asset_type = LLAssetType::AT_TEXTURE;
- if (!LLViewerImageList::createUploadFile(src_filename,
+ if (!LLViewerTextureList::createUploadFile(src_filename,
filename,
IMG_CODEC_PNG ))
{
@@ -775,8 +730,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
else
{
// Unknown extension
- // *TODO: Translate?
- error_message = llformat("Unknown file extension .%s\nExpected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh", exten.c_str());
+ error_message = llformat(LLTrans::getString("UnknownFileExtension").c_str(), exten.c_str());
error = TRUE;;
}
@@ -826,7 +780,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
llwarns << error_message << llendl;
LLSD args;
args["ERROR_MESSAGE"] = error_message;
- LLNotifications::instance().add("ErrorMessage", args);
+ LLNotificationsUtil::add("ErrorMessage", args);
if(LLFile::remove(filename) == -1)
{
lldebugs << "unable to remove temp file" << llendl;
@@ -844,7 +798,7 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt
if(result >= 0)
{
- LLAssetType::EType dest_loc = (data->mPreferredLocation == LLAssetType::AT_NONE) ? data->mAssetInfo.mType : data->mPreferredLocation;
+ LLFolderType::EType dest_loc = (data->mPreferredLocation == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(data->mAssetInfo.mType) : data->mPreferredLocation;
if (LLAssetType::AT_SOUND == data->mAssetInfo.mType ||
LLAssetType::AT_TEXTURE == data->mAssetInfo.mType ||
@@ -856,9 +810,9 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt
if(!(can_afford_transaction(expected_upload_cost)))
{
LLFloaterBuyCurrency::buyCurrency(
- llformat("Uploading %s costs",
- data->mAssetInfo.getName().c_str()), // *TODO: Translate
- expected_upload_cost);
+ llformat(LLTrans::getString("UploadingCosts").c_str(),
+ data->mAssetInfo.getName().c_str()),
+ expected_upload_cost);
is_balance_sufficient = FALSE;
}
else if(region)
@@ -890,7 +844,7 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt
{
// Actually add the upload to inventory
llinfos << "Adding " << uuid << " to inventory." << llendl;
- LLUUID folder_id(gInventory.findCategoryUUIDForType(dest_loc));
+ const LLUUID folder_id = gInventory.findCategoryUUIDForType(dest_loc);
if(folder_id.notNull())
{
U32 next_owner_perms = data->mNextOwnerPerm;
@@ -915,7 +869,7 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt
LLSD args;
args["FILE"] = LLInventoryType::lookupHumanReadable(data->mInventoryType);
args["REASON"] = std::string(LLAssetStorage::getErrorString(result));
- LLNotifications::instance().add("CannotUploadReason", args);
+ LLNotificationsUtil::add("CannotUploadReason", args);
}
LLUploadDialog::modalUploadFinished();
@@ -937,7 +891,7 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt
LLAssetStorage::LLStoreAssetCallback callback = NULL;
void *userdata = NULL;
upload_new_resource(next_file, asset_name, asset_name, // file
- 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE,
+ 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
PERM_NONE, PERM_NONE, PERM_NONE,
display_name,
callback,
@@ -949,7 +903,7 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt
void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_type,
std::string name,
std::string desc, S32 compression_info,
- LLAssetType::EType destination_folder_type,
+ LLFolderType::EType destination_folder_type,
LLInventoryType::EType inv_type,
U32 next_owner_perms,
U32 group_perms,
@@ -1007,14 +961,14 @@ void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ty
llinfos << "Name: " << name << llendl;
llinfos << "Desc: " << desc << llendl;
llinfos << "Expected Upload Cost: " << expected_upload_cost << llendl;
- lldebugs << "Folder: " << gInventory.findCategoryUUIDForType((destination_folder_type == LLAssetType::AT_NONE) ? asset_type : destination_folder_type) << llendl;
+ lldebugs << "Folder: " << gInventory.findCategoryUUIDForType((destination_folder_type == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(asset_type) : destination_folder_type) << llendl;
lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl;
std::string url = gAgent.getRegion()->getCapability("NewFileAgentInventory");
if (!url.empty())
{
llinfos << "New Agent Inventory via capability" << llendl;
LLSD body;
- body["folder_id"] = gInventory.findCategoryUUIDForType((destination_folder_type == LLAssetType::AT_NONE) ? asset_type : destination_folder_type);
+ body["folder_id"] = gInventory.findCategoryUUIDForType((destination_folder_type == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(asset_type) : destination_folder_type);
body["asset_type"] = LLAssetType::lookup(asset_type);
body["inventory_type"] = LLInventoryType::lookup(inv_type);
body["name"] = name;
@@ -1073,22 +1027,20 @@ void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ty
}
}
-
void init_menu_file()
{
- (new LLFileUploadImage())->registerListener(gMenuHolder, "File.UploadImage");
- (new LLFileUploadSound())->registerListener(gMenuHolder, "File.UploadSound");
- (new LLFileUploadAnim())->registerListener(gMenuHolder, "File.UploadAnim");
- (new LLFileUploadBulk())->registerListener(gMenuHolder, "File.UploadBulk");
- (new LLFileCloseWindow())->registerListener(gMenuHolder, "File.CloseWindow");
- (new LLFileCloseAllWindows())->registerListener(gMenuHolder, "File.CloseAllWindows");
- (new LLFileEnableCloseWindow())->registerListener(gMenuHolder, "File.EnableCloseWindow");
- (new LLFileEnableCloseAllWindows())->registerListener(gMenuHolder, "File.EnableCloseAllWindows");
- (new LLFileSaveTexture())->registerListener(gMenuHolder, "File.SaveTexture");
- (new LLFileTakeSnapshot())->registerListener(gMenuHolder, "File.TakeSnapshot");
- (new LLFileTakeSnapshotToDisk())->registerListener(gMenuHolder, "File.TakeSnapshotToDisk");
- (new LLFileQuit())->registerListener(gMenuHolder, "File.Quit");
-
- (new LLFileEnableUpload())->registerListener(gMenuHolder, "File.EnableUpload");
- (new LLFileEnableSaveAs())->registerListener(gMenuHolder, "File.EnableSaveAs");
+ view_listener_t::addCommit(new LLFileUploadImage(), "File.UploadImage");
+ view_listener_t::addCommit(new LLFileUploadSound(), "File.UploadSound");
+ view_listener_t::addCommit(new LLFileUploadAnim(), "File.UploadAnim");
+ view_listener_t::addCommit(new LLFileUploadBulk(), "File.UploadBulk");
+ view_listener_t::addCommit(new LLFileCloseWindow(), "File.CloseWindow");
+ view_listener_t::addCommit(new LLFileCloseAllWindows(), "File.CloseAllWindows");
+ view_listener_t::addEnable(new LLFileEnableCloseWindow(), "File.EnableCloseWindow");
+ view_listener_t::addEnable(new LLFileEnableCloseAllWindows(), "File.EnableCloseAllWindows");
+ view_listener_t::addCommit(new LLFileTakeSnapshotToDisk(), "File.TakeSnapshotToDisk");
+ view_listener_t::addCommit(new LLFileQuit(), "File.Quit");
+
+ view_listener_t::addEnable(new LLFileEnableUpload(), "File.EnableUpload");
+
+ // "File.SaveTexture" moved to llpanelmaininventory so that it can be properly handled.
}
diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h
index bf21292082..1e6d13f1c6 100644
--- a/indra/newview/llviewermenufile.h
+++ b/indra/newview/llviewermenufile.h
@@ -33,7 +33,8 @@
#ifndef LLVIEWERMENUFILE_H
#define LLVIEWERMENUFILE_H
-#include "llassettype.h"
+#include "llfoldertype.h"
+#include "llassetstorage.h"
#include "llinventorytype.h"
class LLTransactionID;
@@ -45,7 +46,7 @@ void upload_new_resource(const std::string& src_filename,
std::string name,
std::string desc,
S32 compression_info,
- LLAssetType::EType destination_folder_type,
+ LLFolderType::EType destination_folder_type,
LLInventoryType::EType inv_type,
U32 next_owner_perms,
U32 group_perms,
@@ -60,7 +61,7 @@ void upload_new_resource(const LLTransactionID &tid,
std::string name,
std::string desc,
S32 compression_info,
- LLAssetType::EType destination_folder_type,
+ LLFolderType::EType destination_folder_type,
LLInventoryType::EType inv_type,
U32 next_owner_perms,
U32 group_perms,
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index bbfd480e0b..0358efc0af 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -1,4 +1,3 @@
-
/**
* @file llviewermessage.cpp
* @brief Dumping ground for viewer-side message system callbacks.
@@ -32,115 +31,86 @@
*/
#include "llviewerprecompiledheaders.h"
-
#include "llviewermessage.h"
-#include <deque>
-
-#include "audioengine.h"
-#include "indra_constants.h"
+#include "llanimationstates.h"
+#include "llaudioengine.h"
+#include "llavataractions.h"
#include "lscript_byteformat.h"
-#include "mean_collision_data.h"
-#include "llfloaterbump.h"
-#include "llassetstorage.h"
-#include "llcachename.h"
-#include "llchat.h"
-#include "lldbstrings.h"
#include "lleconomy.h"
-#include "llfilepicker.h"
-#include "llfocusmgr.h"
+#include "llfloaterreg.h"
#include "llfollowcamparams.h"
-#include "llinstantmessage.h"
-#include "llquantize.h"
-#include "llregionflags.h"
#include "llregionhandle.h"
#include "llsdserialize.h"
-#include "llstring.h"
#include "llteleportflags.h"
-#include "lltracker.h"
#include "lltransactionflags.h"
+#include "llvfile.h"
+#include "llvfs.h"
#include "llxfermanager.h"
-#include "message.h"
-#include "sound_ids.h"
-#include "lltimer.h"
-#include "llmd5.h"
+#include "mean_collision_data.h"
#include "llagent.h"
#include "llcallingcard.h"
-#include "llconsole.h"
-#include "llvieweraudio.h"
-#include "llviewercontrol.h"
-#include "lldrawpool.h"
-#include "llfirstuse.h"
-#include "llfloateractivespeakers.h"
-#include "llfloateranimpreview.h"
+//#include "llfirstuse.h"
#include "llfloaterbuycurrency.h"
#include "llfloaterbuyland.h"
-#include "llfloaterchat.h"
-#include "llfloatergroupinfo.h"
-#include "llfloaterimagepreview.h"
#include "llfloaterland.h"
#include "llfloaterregioninfo.h"
#include "llfloaterlandholdings.h"
-#include "llurldispatcher.h"
-#include "llfloatermute.h"
#include "llfloaterpostcard.h"
#include "llfloaterpreference.h"
-#include "llfollowcam.h"
-#include "llgroupnotify.h"
-#include "llhudeffect.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
-#include "llimpanel.h"
-#include "llinventorymodel.h"
-#include "llinventoryview.h"
-#include "llmenugl.h"
-#include "llmutelist.h"
+#include "llinventoryobserver.h"
+#include "llinventorypanel.h"
+#include "llnearbychat.h"
#include "llnotifications.h"
-#include "llnotify.h"
+#include "llnotificationsutil.h"
#include "llpanelgrouplandmoney.h"
+#include "llpanelplaces.h"
+#include "llrecentpeople.h"
+#include "llscriptfloater.h"
#include "llselectmgr.h"
+#include "llsidetray.h"
#include "llstartup.h"
#include "llsky.h"
+#include "llslurl.h"
#include "llstatenums.h"
#include "llstatusbar.h"
#include "llimview.h"
-#include "lltool.h"
-#include "lltoolbar.h"
-#include "lltoolmgr.h"
+#include "llspeakers.h"
#include "lltrans.h"
-#include "llui.h" // for make_ui_sound
-#include "lluploaddialog.h"
-#include "llviewercamera.h"
+#include "llviewerfoldertype.h"
+#include "lluri.h"
#include "llviewergenericmessage.h"
-#include "llviewerinventory.h"
#include "llviewermenu.h"
-#include "llviewerobject.h"
#include "llviewerobjectlist.h"
#include "llviewerparcelmgr.h"
-#include "llviewerpartsource.h"
-#include "llviewerregion.h"
#include "llviewerstats.h"
#include "llviewertexteditor.h"
#include "llviewerthrottle.h"
#include "llviewerwindow.h"
#include "llvlmanager.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "llvotextbubble.h"
-#include "llweb.h"
#include "llworld.h"
#include "pipeline.h"
-#include "llappviewer.h"
#include "llfloaterworldmap.h"
#include "llviewerdisplay.h"
#include "llkeythrottle.h"
+#include "llgroupactions.h"
+#include "llagentui.h"
+#include "llpanelblockedlist.h"
+#include "llpanelplaceprofile.h"
-#include <boost/tokenizer.hpp>
+#include <boost/algorithm/string/split.hpp> //
#if LL_WINDOWS // For Windows specific error handler
#include "llwindebug.h" // For the invalid message handler
#endif
+#include "llnotificationmanager.h" //
+
//
// Constants
//
@@ -156,11 +126,7 @@ static const F32 LLREQUEST_PERMISSION_THROTTLE_INTERVAL = 10.0f; // seconds
extern BOOL gDebugClicks;
// function prototypes
-void open_offer(const std::vector<LLUUID>& items, const std::string& from_name);
bool check_offer_throttle(const std::string& from_name, bool check_only);
-void callbackCacheEstateOwnerName(const LLUUID& id,
- const std::string& first, const std::string& last,
- BOOL is_group, void*);
//inventory offer throttle globals
LLFrameTimer gThrottleTimer;
@@ -200,17 +166,21 @@ const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] =
bool friendship_offer_callback(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
- LLUUID fid;
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLMessageSystem* msg = gMessageSystem;
const LLSD& payload = notification["payload"];
+
+ // add friend to recent people list
+ LLRecentPeople::instance().add(payload["from_id"]);
+
switch(option)
{
case 0:
+ {
// accept
LLAvatarTracker::formFriendship(payload["from_id"]);
- fid = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD);
+ const LLUUID fid = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD);
// This will also trigger an onlinenotification if the user is online
msg->newMessageFast(_PREHASH_AcceptFriendship);
@@ -223,18 +193,27 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)
msg->addUUIDFast(_PREHASH_FolderID, fid);
msg->sendReliable(LLHost(payload["sender"].asString()));
break;
- case 1:
- // decline
- // We no longer notify other viewers, but we DO still send
- // the rejection to the simulator to delete the pending userop.
- msg->newMessageFast(_PREHASH_DeclineFriendship);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_TransactionBlock);
- msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]);
- msg->sendReliable(LLHost(payload["sender"].asString()));
- break;
+ }
+ case 1: // Decline
+ case 2: // Send IM - decline and start IM session
+ {
+ // decline
+ // We no longer notify other viewers, but we DO still send
+ // the rejection to the simulator to delete the pending userop.
+ msg->newMessageFast(_PREHASH_DeclineFriendship);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_TransactionBlock);
+ msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]);
+ msg->sendReliable(LLHost(payload["sender"].asString()));
+
+ // start IM session
+ if(2 == option)
+ {
+ LLAvatarActions::startIM(payload["from_id"].asUUID());
+ }
+ }
default:
// close button probably, possibly timed out
break;
@@ -618,7 +597,7 @@ void send_sound_trigger(const LLUUID& sound_id, F32 gain)
bool join_group_response(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
BOOL delete_context_data = TRUE;
bool accept_invite = false;
@@ -630,10 +609,10 @@ bool join_group_response(const LLSD& notification, const LLSD& response)
if (option == 2 && !group_id.isNull())
{
- LLFloaterGroupInfo::showFromUUID(group_id);
+ LLGroupActions::show(group_id);
LLSD args;
args["MESSAGE"] = message;
- LLNotifications::instance().add("JoinGroup", args, notification["payload"]);
+ LLNotificationsUtil::add("JoinGroup", args, notification["payload"]);
return false;
}
if(option == 0 && !group_id.isNull())
@@ -652,7 +631,7 @@ bool join_group_response(const LLSD& notification, const LLSD& response)
LLSD args;
args["NAME"] = name;
args["INVITE"] = message;
- LLNotifications::instance().add("JoinedTooManyGroupsMember", args, notification["payload"]);
+ LLNotificationsUtil::add("JoinedTooManyGroupsMember", args, notification["payload"]);
}
}
@@ -669,7 +648,7 @@ bool join_group_response(const LLSD& notification, const LLSD& response)
// asking about a fee.
LLSD next_payload = notification["payload"];
next_payload["fee"] = 0;
- LLNotifications::instance().add("JoinGroupCanAfford",
+ LLNotificationsUtil::add("JoinGroupCanAfford",
args,
next_payload);
}
@@ -709,7 +688,7 @@ public:
LLOpenAgentOffer(const std::string& from_name) : mFromName(from_name) {}
/*virtual*/ void done()
{
- open_offer(mComplete, mFromName);
+ open_inventory_offer(mComplete, mFromName);
gInventory.removeObserver(this);
delete this;
}
@@ -727,11 +706,23 @@ class LLOpenTaskOffer : public LLInventoryAddedObserver
protected:
/*virtual*/ void done()
{
- open_offer(mAdded, "");
+ open_inventory_offer(mAdded, "");
mAdded.clear();
}
};
+class LLOpenTaskGroupOffer : public LLInventoryAddedObserver
+{
+protected:
+ /*virtual*/ void done()
+ {
+ open_inventory_offer(mAdded, "group_offer");
+ mAdded.clear();
+ gInventory.removeObserver(this);
+ delete this;
+ }
+};
+
//one global instance to bind them
LLOpenTaskOffer* gNewInventoryObserver=NULL;
@@ -747,6 +738,7 @@ void start_new_inventory_observer()
class LLDiscardAgentOffer : public LLInventoryFetchComboObserver
{
+ LOG_CLASS(LLDiscardAgentOffer);
public:
LLDiscardAgentOffer(const LLUUID& folder_id, const LLUUID& object_id) :
mFolderID(folder_id),
@@ -755,8 +747,7 @@ public:
virtual void done()
{
LL_DEBUGS("Messaging") << "LLDiscardAgentOffer::done()" << LL_ENDL;
- LLUUID trash_id;
- trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
bool notify = false;
if(trash_id.notNull() && mObjectID.notNull())
{
@@ -844,9 +835,13 @@ bool check_offer_throttle(const std::string& from_name, bool check_only)
}
message << ", automatic preview disabled for "
<< OFFER_THROTTLE_TIME << " seconds.";
- chat.mText = message.str();
+
//this is kinda important, so actually put it on screen
- LLFloaterChat::addChat(chat, FALSE, FALSE);
+ std::string log_msg = message.str();
+ LLSD args;
+ args["MESSAGE"] = log_msg;
+ LLNotificationsUtil::add("SystemMessage", args);
+
throttle_logged=true;
}
return false;
@@ -859,127 +854,171 @@ bool check_offer_throttle(const std::string& from_name, bool check_only)
}
}
-void open_offer(const std::vector<LLUUID>& items, const std::string& from_name)
+void open_inventory_offer(const std::vector<LLUUID>& items, const std::string& from_name)
{
- std::vector<LLUUID>::const_iterator it = items.begin();
- std::vector<LLUUID>::const_iterator end = items.end();
- LLUUID trash_id(gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH));
- LLInventoryItem* item;
- for(; it != end; ++it)
+ for (std::vector<LLUUID>::const_iterator item_iter = items.begin();
+ item_iter != items.end();
+ ++item_iter)
{
- item = gInventory.getItem(*it);
+ const LLUUID& item_id = (*item_iter);
+ LLInventoryItem* item = gInventory.getItem(item_id);
if(!item)
{
- LL_WARNS("Messaging") << "Unable to show inventory item: " << *it << LL_ENDL;
+ LL_WARNS("Messaging") << "Unable to show inventory item: " << item_id << LL_ENDL;
continue;
}
- if(gInventory.isObjectDescendentOf(*it, trash_id))
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Don't highlight if it's in certain "quiet" folders which don't need UI
+ // notification (e.g. trash, cof, lost-and-found).
+ const BOOL user_is_away = gAwayTimer.getStarted();
+ if(!user_is_away)
{
- continue;
+ const LLViewerInventoryCategory *parent = gInventory.getFirstNondefaultParent(item_id);
+ if (parent)
+ {
+ const LLFolderType::EType parent_type = parent->getPreferredType();
+ if (LLViewerFolderType::lookupIsQuietType(parent_type))
+ {
+ continue;
+ }
+ }
}
- LLAssetType::EType asset_type = item->getType();
- //if we are throttled, don't display them
- if (check_offer_throttle(from_name, false))
+ ////////////////////////////////////////////////////////////////////////////////
+ // Special handling for various types.
+ const LLAssetType::EType asset_type = item->getType();
+ if (check_offer_throttle(from_name, false)) // If we are throttled, don't display
{
- // I'm not sure this is a good idea.
- bool show_keep_discard = item->getPermissions().getCreator() != gAgent.getID();
- //bool show_keep_discard = true;
+ LL_DEBUGS("Messaging") << "Highlighting inventory item: " << item->getUUID() << LL_ENDL;
+ // If we opened this ourselves, focus it
+ const BOOL take_focus = from_name.empty() ? TAKE_FOCUS_YES : TAKE_FOCUS_NO;
switch(asset_type)
{
- case LLAssetType::AT_NOTECARD:
- open_notecard((LLViewerInventoryItem*)item, std::string("Note: ") + item->getName(), LLUUID::null, show_keep_discard, LLUUID::null, FALSE);
- break;
- case LLAssetType::AT_LANDMARK:
- open_landmark((LLViewerInventoryItem*)item, std::string("Landmark: ") + item->getName(), show_keep_discard, LLUUID::null, FALSE);
- break;
- case LLAssetType::AT_TEXTURE:
- open_texture(*it, std::string("Texture: ") + item->getName(), show_keep_discard, LLUUID::null, FALSE);
+ case LLAssetType::AT_NOTECARD:
+ {
+ LLFloaterReg::showInstance("preview_notecard", LLSD(item_id), take_focus);
+ break;
+ }
+ case LLAssetType::AT_LANDMARK:
+ {
+ LLInventoryCategory* parent_folder = gInventory.getCategory(item->getParentUUID());
+ if ("inventory_handler" == from_name)
+ {
+ //we have to filter inventory_handler messages to avoid notification displaying
+ LLSideTray::getInstance()->showPanel("panel_places",
+ LLSD().with("type", "landmark").with("id", item->getUUID()));
+ }
+ else if("group_offer" == from_name)
+ {
+ // do not open inventory when we open group notice attachment because
+ // we already opened landmark info panel
+ // "group_offer" is passed by LLOpenTaskGroupOffer
+
+ continue;
+ }
+ else if(from_name.empty())
+ {
+ // we receive a message from LLOpenTaskOffer, it mean that new landmark has been added.
+ LLSD args;
+ args["LANDMARK_NAME"] = item->getName();
+ args["FOLDER_NAME"] = std::string(parent_folder ? parent_folder->getName() : "unknown");
+ LLNotificationsUtil::add("LandmarkCreated", args);
+ // Created landmark is passed to Places panel to allow its editing. In fact panel should be already displayed.
+ //TODO*:: dserduk(7/12/09) remove LLPanelPlaces dependency from here
+ LLPanelPlaces *places_panel = dynamic_cast<LLPanelPlaces*>(LLSideTray::getInstance()->showPanel("panel_places", LLSD()));
+ if (places_panel)
+ {
+ // we are creating a landmark
+ if("create_landmark" == places_panel->getPlaceInfoType() && !places_panel->getItem())
+ {
+ places_panel->setItem(item);
+ }
+ // we are opening a group notice attachment
+ else
+ {
+ LLSD args;
+ args["type"] = "landmark";
+ args["id"] = item_id;
+ LLSideTray::getInstance()->showPanel("panel_places", args);
+ }
+ }
+ }
+ }
break;
- default:
+ case LLAssetType::AT_TEXTURE:
+ {
+ LLFloaterReg::showInstance("preview_texture", LLSD(item_id), take_focus);
+ break;
+ }
+ case LLAssetType::AT_ANIMATION:
+ LLFloaterReg::showInstance("preview_anim", LLSD(item_id), take_focus);
+ break;
+ case LLAssetType::AT_SCRIPT:
+ LLFloaterReg::showInstance("preview_script", LLSD(item_id), take_focus);
+ break;
+ case LLAssetType::AT_SOUND:
+ LLFloaterReg::showInstance("preview_sound", LLSD(item_id), take_focus);
+ break;
+ default:
break;
}
}
- //highlight item, if it's not in the trash or lost+found
- // Don't auto-open the inventory floater
- LLInventoryView* view = LLInventoryView::getActiveInventory();
- if(!view)
- {
- return;
- }
-
- if(gSavedSettings.getBOOL("ShowInInventory") &&
- asset_type != LLAssetType::AT_CALLINGCARD &&
- item->getInventoryType() != LLInventoryType::IT_ATTACHMENT &&
- !from_name.empty())
- {
- LLInventoryView::showAgentInventory(TRUE);
- }
- //Trash Check
- LLUUID trash_id;
- trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
- if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id))
- {
- return;
- }
- LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
- //BOOL inventory_has_focus = gFocusMgr.childHasKeyboardFocus(view);
- BOOL user_is_away = gAwayTimer.getStarted();
-
- // don't select lost and found items if the user is active
- if (gInventory.isObjectDescendentOf(item->getUUID(), lost_and_found_id)
- && !user_is_away)
+ ////////////////////////////////////////////////////////////////////////////////
+ // Highlight item if it's not in the trash, lost+found, or COF
+ const BOOL auto_open = gSavedSettings.getBOOL("ShowInInventory") &&
+ (asset_type != LLAssetType::AT_CALLINGCARD) &&
+ (item->getInventoryType() != LLInventoryType::IT_ATTACHMENT) &&
+ !from_name.empty();
+ LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(auto_open);
+ if(active_panel)
{
- return;
+ LL_DEBUGS("Messaging") << "Highlighting" << item_id << LL_ENDL;
+ LLFocusableElement* focus_ctrl = gFocusMgr.getKeyboardFocus();
+ active_panel->setSelection(item_id, TAKE_FOCUS_NO);
+ gFocusMgr.setKeyboardFocus(focus_ctrl);
}
-
- //Not sure about this check. Could make it easy to miss incoming items.
- //don't dick with highlight while the user is working
- //if(inventory_has_focus && !user_is_away)
- // break;
- LL_DEBUGS("Messaging") << "Highlighting" << item->getUUID() << LL_ENDL;
- //highlight item
-
- LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus();
- view->getPanel()->setSelection(item->getUUID(), TAKE_FOCUS_NO);
- gFocusMgr.setKeyboardFocus(focus_ctrl);
}
}
void inventory_offer_mute_callback(const LLUUID& blocked_id,
const std::string& first_name,
const std::string& last_name,
- BOOL is_group,
- void* user_data)
+ BOOL is_group, LLOfferInfo* offer = NULL)
{
std::string from_name;
LLMute::EType type;
-
if (is_group)
{
type = LLMute::GROUP;
from_name = first_name;
}
+ else if(offer && offer->mFromObject)
+ {
+ //we have to block object by name because blocked_id is an id of owner
+ type = LLMute::BY_NAME;
+ from_name = offer->mFromName;
+ }
else
{
type = LLMute::AGENT;
from_name = first_name + " " + last_name;
}
- LLMute mute(blocked_id, from_name, type);
+ // id should be null for BY_NAME mute, see LLMuteList::add for details
+ LLMute mute(type == LLMute::BY_NAME ? LLUUID::null : blocked_id, from_name, type);
if (LLMuteList::getInstance()->add(mute))
{
- LLFloaterMute::showInstance();
- LLFloaterMute::getInstance()->selectMute(blocked_id);
+ LLPanelBlockedList::showPanelAndSelect(blocked_id);
}
// purge the message queue of any previously queued inventory offers from the same source.
- class OfferMatcher : public LLNotifyBoxView::Matcher
+ class OfferMatcher : public LLNotificationsUI::LLScreenChannel::Matcher
{
public:
OfferMatcher(const LLUUID& to_block) : blocked_id(to_block) {}
- BOOL matches(const LLNotificationPtr notification) const
+ bool matches(const LLNotificationPtr notification) const
{
if(notification->getName() == "ObjectGiveItem"
|| notification->getName() == "ObjectGiveItemUnknownUser"
@@ -992,7 +1031,9 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id,
private:
const LLUUID& blocked_id;
};
- gNotifyBoxView->purgeMessagesMatching(OfferMatcher(blocked_id));
+
+ LLNotificationsUI::LLChannelManager::getInstance()->killToastsFromChannel(LLUUID(
+ gSavedSettings.getString("NotificationChannelUUID")), OfferMatcher(blocked_id));
}
LLOfferInfo::LLOfferInfo(const LLSD& sd)
@@ -1027,22 +1068,8 @@ LLSD LLOfferInfo::asLLSD()
return sd;
}
-bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& response)
- {
- LLChat chat;
- std::string log_message;
- S32 button = LLNotification::getSelectedOption(notification, response);
-
- // For muting, we need to add the mute, then decline the offer.
- // This must be done here because:
- // * callback may be called immediately,
- // * adding the mute sends a message,
- // * we can't build two messages at once.
- if (2 == button)
- {
- gCacheName->get(mFromID, mFromGroup, inventory_offer_mute_callback, this);
- }
-
+void LLOfferInfo::send_auto_receive_response(void)
+{
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
msg->nextBlockFast(_PREHASH_AgentData);
@@ -1055,12 +1082,37 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
msg->addUUIDFast(_PREHASH_ID, mTransactionID);
msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary
std::string name;
- gAgent.buildFullname(name);
+ LLAgentUI::buildFullname(name);
msg->addStringFast(_PREHASH_FromAgentName, name);
msg->addStringFast(_PREHASH_Message, "");
msg->addU32Fast(_PREHASH_ParentEstateID, 0);
msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null);
msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent());
+
+ // Auto Receive Message. The math for the dialog works, because the accept
+ // for inventory_offered, task_inventory_offer or
+ // group_notice_inventory is 1 greater than the offer integer value.
+ // Generates IM_INVENTORY_ACCEPTED, IM_TASK_INVENTORY_ACCEPTED,
+ // or IM_GROUP_NOTICE_INVENTORY_ACCEPTED
+ msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1));
+ msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(mFolderID.mData),
+ sizeof(mFolderID.mData));
+ // send the message
+ msg->sendReliable(mHost);
+
+ if(IM_INVENTORY_OFFERED == mIM)
+ {
+ // add buddy to recent people list
+ LLRecentPeople::instance().add(mFromID);
+ }
+}
+
+bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& response)
+{
+ LLChat chat;
+ std::string log_message;
+ S32 button = LLNotificationsUtil::getSelectedOption(notification, response);
+
LLInventoryObserver* opener = NULL;
LLViewerInventoryCategory* catp = NULL;
catp = (LLViewerInventoryCategory*)gInventory.getCategory(mObjectID);
@@ -1069,108 +1121,79 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
{
itemp = (LLViewerInventoryItem*)gInventory.getItem(mObjectID);
}
+
+ // For muting, we need to add the mute, then decline the offer.
+ // This must be done here because:
+ // * callback may be called immediately,
+ // * adding the mute sends a message,
+ // * we can't build two messages at once.
+ if (2 == button) // Block
+ {
+ gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback,_1,_2,_3,_4,this));
+ }
- // *TODO:translate
std::string from_string; // Used in the pop-up.
std::string chatHistory_string; // Used in chat history.
- if (mFromObject == TRUE)
- {
- if (mFromGroup)
- {
- std::string group_name;
- if (gCacheName->getGroupName(mFromID, group_name))
- {
- from_string = std::string("An object named '") + mFromName + "' owned by the group '" + group_name + "'";
- chatHistory_string = mFromName + " owned by the group '" + group_name + "'";
- }
- else
- {
- from_string = std::string("An object named '") + mFromName + "' owned by an unknown group";
- chatHistory_string = mFromName + " owned by an unknown group";
- }
- }
- else
- {
- std::string first_name, last_name;
- if (gCacheName->getName(mFromID, first_name, last_name))
- {
- from_string = std::string("An object named '") + mFromName + "' owned by " + first_name + " " + last_name;
- chatHistory_string = mFromName + " owned by " + first_name + " " + last_name;
- }
- else
- {
- from_string = std::string("An object named '") + mFromName + "' owned by an unknown user";
- chatHistory_string = mFromName + " owned by an unknown user";
- }
- }
- }
- else
- {
- from_string = chatHistory_string = mFromName;
- }
+
+ // TODO: when task inventory offers can also be handled the new way, migrate the code that sets these strings here:
+ from_string = chatHistory_string = mFromName;
bool busy=FALSE;
switch(button)
{
- case IOR_ACCEPT:
- // ACCEPT. The math for the dialog works, because the accept
- // for inventory_offered, task_inventory_offer or
- // group_notice_inventory is 1 greater than the offer integer value.
- // Generates IM_INVENTORY_ACCEPTED, IM_TASK_INVENTORY_ACCEPTED,
- // or IM_GROUP_NOTICE_INVENTORY_ACCEPTED
- msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1));
- msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(mFolderID.mData),
- sizeof(mFolderID.mData));
- // send the message
- msg->sendReliable(mHost);
-
- //don't spam them if they are getting flooded
- if (check_offer_throttle(mFromName, true))
- {
- log_message = chatHistory_string + " gave you " + mDesc + ".";
- chat.mText = log_message;
- LLFloaterChat::addChatHistory(chat);
- }
-
+ case IOR_SHOW:
// we will want to open this item when it comes back.
LL_DEBUGS("Messaging") << "Initializing an opener for tid: " << mTransactionID
<< LL_ENDL;
switch (mIM)
{
case IM_INVENTORY_OFFERED:
- {
- // This is an offer from an agent. In this case, the back
- // end has already copied the items into your inventory,
- // so we can fetch it out of our inventory.
- LLInventoryFetchObserver::item_ref_t items;
- items.push_back(mObjectID);
- LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer(from_string);
- open_agent_offer->fetchItems(items);
- if(catp || (itemp && itemp->isComplete()))
{
- open_agent_offer->done();
- }
- else
- {
- opener = open_agent_offer;
+ // This is an offer from an agent. In this case, the back
+ // end has already copied the items into your inventory,
+ // so we can fetch it out of our inventory.
+ LLInventoryFetchObserver::item_ref_t items;
+ items.push_back(mObjectID);
+ LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer(from_string);
+ open_agent_offer->fetchItems(items);
+ if(catp || (itemp && itemp->isComplete()))
+ {
+ open_agent_offer->done();
+ }
+ else
+ {
+ opener = open_agent_offer;
+ }
}
- }
break;
- case IM_TASK_INVENTORY_OFFERED:
case IM_GROUP_NOTICE:
+ opener = new LLOpenTaskGroupOffer;
+ send_auto_receive_response();
+ break;
+ case IM_TASK_INVENTORY_OFFERED:
case IM_GROUP_NOTICE_REQUESTED:
- {
// This is an offer from a task or group.
// We don't use a new instance of an opener
// We instead use the singular observer gOpenTaskOffer
// Since it already exists, we don't need to actually do anything
- }
- break;
+ break;
default:
LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL;
break;
- } // end switch (mIM)
+ }
+ break;
+ // end switch (mIM)
+
+ case IOR_ACCEPT:
+ //don't spam them if they are getting flooded
+ if (check_offer_throttle(mFromName, true))
+ {
+ log_message = chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + mDesc + LLTrans::getString(".");
+ LLSD args;
+ args["MESSAGE"] = log_message;
+ LLNotificationsUtil::add("SystemMessage", args);
+ }
break;
case IOR_BUSY:
@@ -1179,31 +1202,18 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
case IOR_MUTE:
// MUTE falls through to decline
case IOR_DECLINE:
- // DECLINE. The math for the dialog works, because the decline
- // for inventory_offered, task_inventory_offer or
- // group_notice_inventory is 2 greater than the offer integer value.
- // Generates IM_INVENTORY_DECLINED, IM_TASK_INVENTORY_DECLINED,
- // or IM_GROUP_NOTICE_INVENTORY_DECLINED
- default:
- // close button probably (or any of the fall-throughs from above)
- msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 2));
- msg->addBinaryDataFast(_PREHASH_BinaryBucket, EMPTY_BINARY_BUCKET, EMPTY_BINARY_BUCKET_SIZE);
- // send the message
- msg->sendReliable(mHost);
-
- log_message = "You decline " + mDesc + " from " + mFromName + ".";
- chat.mText = log_message;
- if( LLMuteList::getInstance()->isMuted(mFromID ) && ! LLMuteList::getInstance()->isLinden(mFromName) ) // muting for SL-42269
{
- chat.mMuted = TRUE;
- }
- LLFloaterChat::addChatHistory(chat);
+ log_message = LLTrans::getString("InvOfferYouDecline") + " " + mDesc + " " + LLTrans::getString("InvOfferFrom") + " " + mFromName +".";
+ chat.mText = log_message;
+ if( LLMuteList::getInstance()->isMuted(mFromID ) && ! LLMuteList::getInstance()->isLinden(mFromName) ) // muting for SL-42269
+ {
+ chat.mMuted = TRUE;
+ }
- // If it's from an agent, we have to fetch the item to throw
- // it away. If it's from a task or group, just denying the
- // request will suffice to discard the item.
- if(IM_INVENTORY_OFFERED == mIM)
- {
+ // *NOTE dzaporozhan
+ // Disabled logging to old chat floater to fix crash in group notices - EXT-4149
+ // LLFloaterChat::addChatHistory(chat);
+
LLInventoryFetchComboObserver::folder_ref_t folders;
LLInventoryFetchComboObserver::item_ref_t items;
items.push_back(mObjectID);
@@ -1219,11 +1229,18 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
opener = discard_agent_offer;
}
+
+ if (busy && (!mFromGroup && !mFromObject))
+ {
+ busy_message(gMessageSystem, mFromID);
+ }
+ break;
}
- if (busy && (!mFromGroup && !mFromObject))
- {
- busy_message(msg,mFromID);
- }
+ default:
+ // close button probably
+ // The item has already been fetched and is in your inventory, we simply won't highlight it
+ // OR delete it if the notification gets killed, since we don't want that to be a vector for
+ // losing inventory offers.
break;
}
@@ -1232,16 +1249,194 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
gInventory.addObserver(opener);
}
- // Allow these to stack up, but once you deal with one, reset the
- // position.
- gFloaterView->resetStartingFloaterPosition();
+ // Remove script dialog because there is no need in it no more.
+ LLUUID object_id = notification["payload"]["object_id"].asUUID();
+ LLScriptFloaterManager::instance().removeNotificationByObjectId(object_id);
delete this;
return false;
}
+bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const LLSD& response)
+{
+ LLChat chat;
+ std::string log_message;
+ S32 button = LLNotification::getSelectedOption(notification, response);
+
+ // For muting, we need to add the mute, then decline the offer.
+ // This must be done here because:
+ // * callback may be called immediately,
+ // * adding the mute sends a message,
+ // * we can't build two messages at once.
+ if (2 == button)
+ {
+ gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback,_1,_2,_3,_4,this));
+ }
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_MessageBlock);
+ msg->addBOOLFast(_PREHASH_FromGroup, FALSE);
+ msg->addUUIDFast(_PREHASH_ToAgentID, mFromID);
+ msg->addU8Fast(_PREHASH_Offline, IM_ONLINE);
+ msg->addUUIDFast(_PREHASH_ID, mTransactionID);
+ msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary
+ std::string name;
+ LLAgentUI::buildFullname(name);
+ msg->addStringFast(_PREHASH_FromAgentName, name);
+ msg->addStringFast(_PREHASH_Message, "");
+ msg->addU32Fast(_PREHASH_ParentEstateID, 0);
+ msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null);
+ msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent());
+ LLInventoryObserver* opener = NULL;
+ LLViewerInventoryCategory* catp = NULL;
+ catp = (LLViewerInventoryCategory*)gInventory.getCategory(mObjectID);
+ LLViewerInventoryItem* itemp = NULL;
+ if(!catp)
+ {
+ itemp = (LLViewerInventoryItem*)gInventory.getItem(mObjectID);
+ }
+
+ std::string from_string; // Used in the pop-up.
+ std::string chatHistory_string; // Used in chat history.
+ if (mFromObject == TRUE)
+ {
+ if (mFromGroup)
+ {
+ std::string group_name;
+ if (gCacheName->getGroupName(mFromID, group_name))
+ {
+ from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+"'"
+ + mFromName + LLTrans::getString("'") +" " + LLTrans::getString("InvOfferOwnedByGroup")
+ + " "+ "'" + group_name + "'";
+
+ chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByGroup")
+ + " " + group_name + "'";
+ }
+ else
+ {
+ from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+"'"
+ + mFromName +"'"+ " " + LLTrans::getString("InvOfferOwnedByUnknownGroup");
+ chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByUnknownGroup");
+ }
+ }
+ else
+ {
+ std::string first_name, last_name;
+ if (gCacheName->getName(mFromID, first_name, last_name))
+ {
+ from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+ LLTrans::getString("'") + mFromName
+ + LLTrans::getString("'")+" " + LLTrans::getString("InvOfferOwnedBy") + first_name + " " + last_name;
+ chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedBy") + " " + first_name + " " + last_name;
+ }
+ else
+ {
+ from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+LLTrans::getString("'")
+ + mFromName + LLTrans::getString("'")+" " + LLTrans::getString("InvOfferOwnedByUnknownUser");
+ chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByUnknownUser");
+ }
+ }
+ }
+ else
+ {
+ from_string = chatHistory_string = mFromName;
+ }
+
+ bool busy=FALSE;
+
+ switch(button)
+ {
+ case IOR_ACCEPT:
+ // ACCEPT. The math for the dialog works, because the accept
+ // for inventory_offered, task_inventory_offer or
+ // group_notice_inventory is 1 greater than the offer integer value.
+ // Generates IM_INVENTORY_ACCEPTED, IM_TASK_INVENTORY_ACCEPTED,
+ // or IM_GROUP_NOTICE_INVENTORY_ACCEPTED
+ msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1));
+ msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(mFolderID.mData),
+ sizeof(mFolderID.mData));
+ // send the message
+ msg->sendReliable(mHost);
+
+ //don't spam them if they are getting flooded
+ if (check_offer_throttle(mFromName, true))
+ {
+ log_message = chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + mDesc + LLTrans::getString(".");
+ //TODO* CHAT: how to show this?
+ //LLSD args;
+ //args["MESSAGE"] = log_message;
+ //LLNotificationsUtil::add("SystemMessage", args);
+ }
+
+ // we will want to open this item when it comes back.
+ LL_DEBUGS("Messaging") << "Initializing an opener for tid: " << mTransactionID
+ << LL_ENDL;
+ switch (mIM)
+ {
+ case IM_TASK_INVENTORY_OFFERED:
+ case IM_GROUP_NOTICE:
+ case IM_GROUP_NOTICE_REQUESTED:
+ {
+ // This is an offer from a task or group.
+ // We don't use a new instance of an opener
+ // We instead use the singular observer gOpenTaskOffer
+ // Since it already exists, we don't need to actually do anything
+ }
+ break;
+ default:
+ LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL;
+ break;
+ } // end switch (mIM)
+ break;
+
+ case IOR_BUSY:
+ //Busy falls through to decline. Says to make busy message.
+ busy=TRUE;
+ case IOR_MUTE:
+ // MUTE falls through to decline
+ case IOR_DECLINE:
+ // DECLINE. The math for the dialog works, because the decline
+ // for inventory_offered, task_inventory_offer or
+ // group_notice_inventory is 2 greater than the offer integer value.
+ // Generates IM_INVENTORY_DECLINED, IM_TASK_INVENTORY_DECLINED,
+ // or IM_GROUP_NOTICE_INVENTORY_DECLINED
+ default:
+ // close button probably (or any of the fall-throughs from above)
+ msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 2));
+ msg->addBinaryDataFast(_PREHASH_BinaryBucket, EMPTY_BINARY_BUCKET, EMPTY_BINARY_BUCKET_SIZE);
+ // send the message
+ msg->sendReliable(mHost);
+
+ //TODO* CHAT: how to show this?
+ //log_message = LLTrans::getString("InvOfferYouDecline") + " " + mDesc + " " + LLTrans::getString("InvOfferFrom") + " " + mFromName +".";
+ //LLSD args;
+ //args["MESSAGE"] = log_message;
+ //LLNotificationsUtil::add("SystemMessage", args);
+
+ if (busy && (!mFromGroup && !mFromObject))
+ {
+ busy_message(msg,mFromID);
+ }
+ break;
+ }
+
+ if(opener)
+ {
+ gInventory.addObserver(opener);
+ }
-void inventory_offer_handler(LLOfferInfo* info, BOOL from_task)
+ // Remove script dialog because there is no need in it no more.
+ LLUUID object_id = notification["payload"]["object_id"].asUUID();
+ LLScriptFloaterManager::instance().removeNotificationByObjectId(object_id);
+
+ delete this;
+ return false;
+}
+
+void inventory_offer_handler(LLOfferInfo* info)
{
//Until throttling is implmented, busy mode should reject inventory instead of silently
//accepting it. SEE SL-39554
@@ -1277,7 +1472,12 @@ void inventory_offer_handler(LLOfferInfo* info, BOOL from_task)
{
LLStringUtil::truncate(msg, indx);
}
-
+
+ if(LLAssetType::AT_LANDMARK == info->mType)
+ {
+ msg = LLViewerInventoryItem::getDisplayName(msg);
+ }
+
LLSD args;
args["[OBJECTNAME]"] = msg;
@@ -1324,23 +1524,67 @@ void inventory_offer_handler(LLOfferInfo* info, BOOL from_task)
}
}
+ // If mObjectID is null then generate the object_id based on msg to prevent
+ // multiple creation of chiclets for same object.
+ LLUUID object_id = info->mObjectID;
+ if (object_id.isNull())
+ object_id.generate(msg);
+
payload["from_id"] = info->mFromID;
+ // Needed by LLScriptFloaterManager to bind original notification with
+ // faked for toast one.
+ payload["object_id"] = object_id;
+ // Flag indicating that this notification is faked for toast.
+ payload["give_inventory_notification"] = FALSE;
args["OBJECTFROMNAME"] = info->mFromName;
args["NAME"] = info->mFromName;
+ args["NAME_SLURL"] = LLSLURL::buildCommand("agent", info->mFromID, "about");
+ std::string verb = "select?name=" + LLURI::escape(msg);
+ args["ITEM_SLURL"] = LLSLURL::buildCommand("inventory", info->mObjectID, verb.c_str());
LLNotification::Params p("ObjectGiveItem");
- p.substitutions(args).payload(payload).functor(boost::bind(&LLOfferInfo::inventory_offer_callback, info, _1, _2));
- if (from_task)
+ // Object -> Agent Inventory Offer
+ if (info->mFromObject)
{
+ // Inventory Slurls don't currently work for non agent transfers, so only display the object name.
+ args["ITEM_SLURL"] = msg;
+ // Note: sets inventory_task_offer_callback as the callback
+ p.substitutions(args).payload(payload).functor.function(boost::bind(&LLOfferInfo::inventory_task_offer_callback, info, _1, _2));
p.name = name_found ? "ObjectGiveItem" : "ObjectGiveItemUnknownUser";
+ // Pop up inv offer chiclet and let the user accept (keep), or reject (and silently delete) the inventory.
+ LLNotifications::instance().add(p);
}
- else
+ else // Agent -> Agent Inventory Offer
{
+ // Note: sets inventory_offer_callback as the callback
+ p.substitutions(args).payload(payload).functor.function(boost::bind(&LLOfferInfo::inventory_offer_callback, info, _1, _2));
p.name = "UserGiveItem";
- }
+
+ // Prefetch the item into your local inventory.
+ LLInventoryFetchObserver::item_ref_t items;
+ items.push_back(info->mObjectID);
+ LLInventoryFetchObserver* fetch_item = new LLInventoryFetchObserver();
+ fetch_item->fetchItems(items);
+ if(fetch_item->isEverythingComplete())
+ {
+ fetch_item->done();
+ }
+ else
+ {
+ gInventory.addObserver(fetch_item);
+ }
+
+ // In viewer 2 we're now auto receiving inventory offers and messaging as such (not sending reject messages).
+ info->send_auto_receive_response();
- LLNotifications::instance().add(p);
+ // Inform user that there is a script floater via toast system
+ {
+ payload["give_inventory_notification"] = TRUE;
+ LLNotificationPtr notification = LLNotifications::instance().add(p.payload(payload));
+ LLScriptFloaterManager::getInstance()->setNotificationToastId(object_id, notification->getID());
+ }
+ }
}
bool lure_callback(const LLSD& notification, const LLSD& response)
@@ -1352,7 +1596,7 @@ bool lure_callback(const LLSD& notification, const LLSD& response)
}
else
{
- option = LLNotification::getSelectedOption(notification, response);
+ option = LLNotificationsUtil::getSelectedOption(notification, response);
}
LLUUID from_id = notification["payload"]["from_id"].asUUID();
@@ -1383,7 +1627,7 @@ static LLNotificationFunctorRegistration lure_callback_reg("TeleportOffered", lu
bool goto_url_callback(const LLSD& notification, const LLSD& response)
{
std::string url = notification["payload"]["url"].asString();
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if(1 == option)
{
LLWeb::loadURL(url);
@@ -1392,6 +1636,17 @@ bool goto_url_callback(const LLSD& notification, const LLSD& response)
}
static LLNotificationFunctorRegistration goto_url_callback_reg("GotoURL", goto_url_callback);
+bool inspect_remote_object_callback(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (0 == option)
+ {
+ LLFloaterReg::showInstance("inspect_remote_object", notification["payload"]);
+ }
+ return false;
+}
+static LLNotificationFunctorRegistration inspect_remote_object_callback_reg("ServerObjectMessage", inspect_remote_object_callback);
+
void process_improved_im(LLMessageSystem *msg, void **user_data)
{
if (gNoRender)
@@ -1415,7 +1670,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
LLChat chat;
std::string buffer;
- // *TODO:translate - need to fix the full name to first/last (maybe)
+ // *TODO: Translate - need to fix the full name to first/last (maybe)
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, from_id);
msg->getBOOLFast(_PREHASH_MessageBlock, _PREHASH_FromGroup, from_group);
msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ToAgentID, to_id);
@@ -1433,10 +1688,19 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
binary_bucket_size = msg->getSizeFast(_PREHASH_MessageBlock, _PREHASH_BinaryBucket);
EInstantMessage dialog = (EInstantMessage)d;
+ // make sure that we don't have an empty or all-whitespace name
+ LLStringUtil::trim(name);
+ if (name.empty())
+ {
+ name = LLTrans::getString("Unnamed");
+ }
+
BOOL is_busy = gAgent.getBusy();
BOOL is_muted = LLMuteList::getInstance()->isMuted(from_id, name, LLMute::flagTextChat);
BOOL is_linden = LLMuteList::getInstance()->isLinden(name);
BOOL is_owned_by_me = FALSE;
+ BOOL is_friend = (LLAvatarTracker::instance().getBuddyInfo(from_id) == NULL) ? false : true;
+ BOOL accept_im_from_only_friend = gSavedSettings.getBOOL("VoiceCallsFriendsOnly");
chat.mMuted = is_muted && !is_linden;
chat.mFromID = from_id;
@@ -1450,15 +1714,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
}
std::string separator_string(": ");
- int message_offset = 0;
-
- //Handle IRC styled /me messages.
- std::string prefix = message.substr(0, 4);
- if (prefix == "/me " || prefix == "/me'")
- {
- separator_string = "";
- message_offset = 3;
- }
LLSD args;
switch(dialog)
@@ -1466,12 +1721,12 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
case IM_CONSOLE_AND_CHAT_HISTORY:
// These are used for system messages, hence don't need the name,
// as it is always "Second Life".
- // *TODO:translate
+ // *TODO: Translate
args["MESSAGE"] = message;
// Note: don't put the message in the IM history, even though was sent
// via the IM mechanism.
- LLNotifications::instance().add("SystemMessageTip",args);
+ LLNotificationsUtil::add("SystemMessageTip",args);
break;
case IM_NOTHING_SPECIAL:
@@ -1492,7 +1747,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
// if there is not a panel for this conversation (i.e. it is a new IM conversation
// initiated by the other party) then...
std::string my_name;
- gAgent.buildFullname(my_name);
+ LLAgentUI::buildFullname(my_name);
std::string response = gSavedPerAccountSettings.getString("BusyModeResponse2");
pack_instant_message(
gMessageSystem,
@@ -1510,7 +1765,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
// now store incoming IM in chat history
- buffer = separator_string + message.substr(message_offset);
+ buffer = message;
LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;
@@ -1526,31 +1781,30 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
region_id,
position,
true);
-
- // pretend this is chat generated by self, so it does not show up on screen
- chat.mText = std::string("IM: ") + name + separator_string + message.substr(message_offset);
- LLFloaterChat::addChat( chat, TRUE, TRUE );
}
else if (from_id.isNull())
{
- // Messages from "Second Life" ID don't go to IM history
- // messages which should be routed to IM window come from a user ID with name=SYSTEM_NAME
- chat.mText = name + ": " + message;
- LLFloaterChat::addChat(chat, FALSE, FALSE);
+ LLSD args;
+ args["MESSAGE"] = message;
+ LLNotificationsUtil::add("SystemMessage", args);
}
else if (to_id.isNull())
{
// Message to everyone from GOD
args["NAME"] = name;
args["MESSAGE"] = message;
- LLNotifications::instance().add("GodMessage", args);
+ LLNotificationsUtil::add("GodMessage", args);
// Treat like a system message and put in chat history.
// Claim to be from a local agent so it doesn't go into
// console.
- chat.mText = name + separator_string + message.substr(message_offset);
- BOOL local_agent = TRUE;
- LLFloaterChat::addChat(chat, FALSE, local_agent);
+ chat.mText = name + separator_string + message;
+
+ LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
+ if(nearby_chat)
+ {
+ nearby_chat->addMessage(chat);
+ }
}
else
{
@@ -1560,11 +1814,16 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
{
saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str());
}
- buffer = separator_string + saved + message.substr(message_offset);
+ buffer = saved + message;
LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;
- if (!is_muted || is_linden)
+ bool mute_im = is_muted;
+ if(accept_im_from_only_friend&&!is_friend)
+ {
+ mute_im = true;
+ }
+ if (!mute_im || is_linden)
{
gIMMgr->addMessage(
session_id,
@@ -1577,19 +1836,18 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
region_id,
position,
true);
- chat.mText = std::string("IM: ") + name + separator_string + saved + message.substr(message_offset);
-
- BOOL local_agent = FALSE;
- LLFloaterChat::addChat( chat, TRUE, local_agent );
}
else
{
// muted user, so don't start an IM session, just record line in chat
// history. Pretend the chat is from a local agent,
// so it will go into the history but not be shown on screen.
- chat.mText = buffer;
- BOOL local_agent = TRUE;
- LLFloaterChat::addChat( chat, TRUE, local_agent );
+
+ //TODO* CHAT: how to show this?
+ //and this is not system message...
+ //LLSD args;
+ //args["MESSAGE"] = buffer;
+ //LLNotificationsUtil::add("SystemMessage", args);
}
}
break;
@@ -1611,9 +1869,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
case IM_MESSAGEBOX:
{
// This is a block, modeless dialog.
- //*TODO:translate
+ //*TODO: Translate
args["MESSAGE"] = message;
- LLNotifications::instance().add("SystemMessage", args);
+ LLNotificationsUtil::add("SystemMessageTip", args);
}
break;
case IM_GROUP_NOTICE:
@@ -1660,7 +1918,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
info->mFromGroup = from_group;
info->mTransactionID = session_id;
info->mType = (LLAssetType::EType) asset_type;
- info->mFolderID = gInventory.findCategoryUUIDForType(info->mType);
+ info->mFolderID = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(info->mType));
std::string from_name;
from_name += "A group member named ";
@@ -1698,13 +1956,14 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
LLSD args;
args["SUBJECT"] = subj;
args["MESSAGE"] = mes;
- LLNotifications::instance().add(LLNotification::Params("GroupNotice").substitutions(args).payload(payload).timestamp(timestamp));
+ LLNotifications::instance().add(LLNotification::Params("GroupNotice").substitutions(args).payload(payload).time_stamp(timestamp));
}
// Also send down the old path for now.
if (IM_GROUP_NOTICE_REQUESTED == dialog)
{
- LLFloaterGroupInfo::showNotice(subj,mes,group_id,has_inventory,item_name,info);
+
+ LLPanelGroup::showNotice(subj,mes,group_id,has_inventory,item_name,info);
}
}
break;
@@ -1745,7 +2004,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
LLSD args;
args["MESSAGE"] = message;
- LLNotifications::instance().add("JoinGroup", args, payload, join_group_response);
+ LLNotificationsUtil::add("JoinGroup", args, payload, join_group_response);
}
}
break;
@@ -1755,7 +2014,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
// Someone has offered us some inventory.
{
LLOfferInfo* info = new LLOfferInfo;
-
if (IM_INVENTORY_OFFERED == dialog)
{
struct offer_agent_bucket_t
@@ -1788,7 +2046,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
info->mFromID = from_id;
info->mFromGroup = from_group;
info->mTransactionID = session_id;
- info->mFolderID = gInventory.findCategoryUUIDForType(info->mType);
+ info->mFolderID = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(info->mType));
if (dialog == IM_TASK_INVENTORY_OFFERED)
{
@@ -1802,14 +2060,21 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
info->mDesc = message;
info->mHost = msg->getSender();
//if (((is_busy && !is_owned_by_me) || is_muted))
- if ( is_muted )
+ if (is_muted)
{
+ // Prefetch the offered item so that it can be discarded by the appropriate observer. (EXT-4331)
+ LLInventoryFetchObserver::item_ref_t items;
+ items.push_back(info->mObjectID);
+ LLInventoryFetchObserver* fetch_item = new LLInventoryFetchObserver();
+ fetch_item->fetchItems(items);
+ delete fetch_item;
+
// Same as closing window
info->forceResponse(IOR_DECLINE);
}
else
{
- inventory_offer_handler(info, dialog == IM_TASK_INVENTORY_OFFERED);
+ inventory_offer_handler(info);
}
}
break;
@@ -1817,13 +2082,17 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
case IM_INVENTORY_ACCEPTED:
{
args["NAME"] = name;
- LLNotifications::instance().add("InventoryAccepted", args);
+ LLSD payload;
+ payload["from_id"] = from_id;
+ LLNotificationsUtil::add("InventoryAccepted", args, payload);
break;
}
case IM_INVENTORY_DECLINED:
{
args["NAME"] = name;
- LLNotifications::instance().add("InventoryDeclined", args);
+ LLSD payload;
+ payload["from_id"] = from_id;
+ LLNotificationsUtil::add("InventoryDeclined", args, payload);
break;
}
// TODO: _DEPRECATED suffix as part of vote removal - DEV-24856
@@ -1859,7 +2128,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
{
saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str());
}
- buffer = separator_string + saved + message.substr(message_offset);
+ buffer = saved + message;
BOOL is_this_agent = FALSE;
if(from_id == gAgentID)
{
@@ -1876,9 +2145,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
region_id,
position,
true);
-
- chat.mText = std::string("IM: ") + name + separator_string + saved + message.substr(message_offset);
- LLFloaterChat::addChat(chat, TRUE, is_this_agent);
}
break;
@@ -1888,20 +2154,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
{
return;
}
- chat.mText = name + separator_string + message.substr(message_offset);
- chat.mFromName = name;
// Build a link to open the object IM info window.
- std::string location = ll_safe_string((char*)binary_bucket,binary_bucket_size);
-
- LLSD query_string;
- query_string["owner"] = from_id;
- query_string["slurl"] = location.c_str();
- query_string["name"] = name;
- if (from_group)
- {
- query_string["groupowned"] = "true";
- }
+ std::string location = ll_safe_string((char*)binary_bucket, binary_bucket_size-1);
if (session_id.notNull())
{
@@ -1917,17 +2172,52 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
chat.mFromID = from_id ^ gAgent.getSessionID();
}
+ LLSD query_string;
+ query_string["owner"] = from_id;
+ query_string["slurl"] = location;
+ query_string["name"] = name;
+ if (from_group)
+ {
+ query_string["groupowned"] = "true";
+ }
+
std::ostringstream link;
- link << "secondlife:///app/objectim/" << session_id
- << LLURI::mapToQueryString(query_string);
+ link << "secondlife:///app/objectim/" << session_id << LLURI::mapToQueryString(query_string);
chat.mURL = link.str();
- chat.mText = name + separator_string + message.substr(message_offset);
-
- // Note: lie to LLFloaterChat::addChat(), pretending that this is NOT an IM, because
- // IMs from objcts don't open IM sessions.
+ chat.mText = message;
chat.mSourceType = CHAT_SOURCE_OBJECT;
- LLFloaterChat::addChat(chat, FALSE, FALSE);
+
+ // Note: lie to Nearby Chat, pretending that this is NOT an IM, because
+ // IMs from obejcts don't open IM sessions.
+ LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
+ if(nearby_chat)
+ {
+ nearby_chat->addMessage(chat);
+ }
+
+
+ //Object IMs send with from name: 'Second Life' need to be displayed also in notification toasts (EXT-1590)
+ if (SYSTEM_FROM != name) break;
+
+ LLSD substitutions;
+ substitutions["NAME"] = name;
+ substitutions["MSG"] = message;
+
+ LLSD payload;
+ payload["object_id"] = session_id;
+ payload["owner_id"] = from_id;
+ payload["from_id"] = from_id;
+ payload["slurl"] = location;
+ payload["name"] = name;
+ std::string session_name;
+ gCacheName->getFullName(from_id, session_name);
+ payload["SESSION_NAME"] = session_name;
+ if (from_group)
+ {
+ payload["groupowned"] = "true";
+ }
+ LLNotificationsUtil::add("ServerObjectMessage", substitutions, payload);
}
break;
case IM_FROM_TASK_AS_ALERT:
@@ -1939,7 +2229,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
// Construct a viewer alert for this message.
args["NAME"] = name;
args["MESSAGE"] = message;
- LLNotifications::instance().add("ObjectMessage", args);
+ LLNotificationsUtil::add("ObjectMessage", args);
}
break;
case IM_BUSY_AUTO_RESPONSE:
@@ -1951,7 +2241,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
else
{
// TODO: after LLTrans hits release, get "busy response" into translatable file
- buffer = llformat("%s (%s): %s", name.c_str(), "busy response", message.substr(message_offset).c_str());
+ buffer = llformat("%s (%s): %s", name.c_str(), "busy response", message.c_str());
gIMMgr->addMessage(session_id, from_id, name, buffer);
}
break;
@@ -1969,14 +2259,14 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
else
{
LLSD args;
- // *TODO:translate -> [FIRST] [LAST] (maybe)
+ // *TODO: Translate -> [FIRST] [LAST] (maybe)
args["NAME"] = name;
args["MESSAGE"] = message;
LLSD payload;
payload["from_id"] = from_id;
payload["lure_id"] = session_id;
payload["godlike"] = FALSE;
- LLNotifications::instance().add("TeleportOffered", args, payload);
+ LLNotificationsUtil::add("TeleportOffered", args, payload);
}
}
break;
@@ -2013,7 +2303,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
args["URL"] = url;
LLSD payload;
payload["url"] = url;
- LLNotifications::instance().add("GotoURL", args, payload );
+ LLNotificationsUtil::add("GotoURL", args, payload );
}
break;
@@ -2040,12 +2330,12 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
if(message.empty())
{
//support for frienship offers from clients before July 2008
- LLNotifications::instance().add("OfferFriendshipNoMessage", args, payload);
+ LLNotificationsUtil::add("OfferFriendshipNoMessage", args, payload);
}
else
{
args["[MESSAGE]"] = message;
- LLNotifications::instance().add("OfferFriendship", args, payload);
+ LLNotificationsUtil::add("OfferFriendship", args, payload);
}
}
}
@@ -2063,7 +2353,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
send_generic_message("requestonlinenotification", strings);
args["NAME"] = name;
- LLNotifications::instance().add("FriendshipAccepted", args);
+ LLSD payload;
+ payload["from_id"] = from_id;
+ LLNotificationsUtil::add("FriendshipAccepted", args, payload);
}
break;
@@ -2086,7 +2378,7 @@ void busy_message (LLMessageSystem* msg, LLUUID from_id)
if (gAgent.getBusy())
{
std::string my_name;
- gAgent.buildFullname(my_name);
+ LLAgentUI::buildFullname(my_name);
std::string response = gSavedPerAccountSettings.getString("BusyModeResponse2");
pack_instant_message(
gMessageSystem,
@@ -2104,7 +2396,7 @@ void busy_message (LLMessageSystem* msg, LLUUID from_id)
bool callingcard_offer_callback(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLUUID fid;
LLUUID from_id;
LLMessageSystem* msg = gMessageSystem;
@@ -2118,7 +2410,7 @@ bool callingcard_offer_callback(const LLSD& notification, const LLSD& response)
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->nextBlockFast(_PREHASH_TransactionBlock);
msg->addUUIDFast(_PREHASH_TransactionID, notification["payload"]["transaction_id"].asUUID());
- fid = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD);
+ fid = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD);
msg->nextBlockFast(_PREHASH_FolderData);
msg->addUUIDFast(_PREHASH_FolderID, fid);
msg->sendReliable(LLHost(notification["payload"]["sender"].asString()));
@@ -2183,7 +2475,7 @@ void process_offer_callingcard(LLMessageSystem* msg, void**)
}
else
{
- LLNotifications::instance().add("OfferCallingCard", args, payload);
+ LLNotificationsUtil::add("OfferCallingCard", args, payload);
}
}
else
@@ -2194,18 +2486,18 @@ void process_offer_callingcard(LLMessageSystem* msg, void**)
void process_accept_callingcard(LLMessageSystem* msg, void**)
{
- LLNotifications::instance().add("CallingCardAccepted");
+ LLNotificationsUtil::add("CallingCardAccepted");
}
void process_decline_callingcard(LLMessageSystem* msg, void**)
{
- LLNotifications::instance().add("CallingCardDeclined");
+ LLNotificationsUtil::add("CallingCardDeclined");
}
void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
{
- LLChat chat;
+ LLChat chat;
std::string mesg;
std::string from_name;
U8 source_temp;
@@ -2296,14 +2588,9 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
std::string prefix = mesg.substr(0, 4);
if (prefix == "/me " || prefix == "/me'")
{
- chat.mText = from_name;
- chat.mText += mesg.substr(3);
ircstyle = TRUE;
}
- else
- {
- chat.mText = mesg;
- }
+ chat.mText = mesg;
// Look for the start of typing so we can put "..." in the bubbles.
if (CHAT_TYPE_START == chat.mChatType)
@@ -2329,22 +2616,12 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
return;
}
- // We have a real utterance now, so can stop showing "..." and proceed.
- if (chatter && chatter->isAvatar())
- {
- LLLocalSpeakerMgr::getInstance()->setSpeakerTyping(from_id, FALSE);
- ((LLVOAvatar*)chatter)->stopTyping();
-
- if (!is_muted && !is_busy)
- {
- visible_in_chat_bubble = gSavedSettings.getBOOL("UseChatBubbles");
- ((LLVOAvatar*)chatter)->addChat(chat);
- }
- }
-
// Look for IRC-style emotes
if (ircstyle)
{
+ // set CHAT_STYLE_IRC to avoid adding Avatar Name as author of message. See EXT-656
+ chat.mChatStyle = CHAT_STYLE_IRC;
+
// Do nothing, ircstyle is fixed above for chat bubbles
}
else
@@ -2352,15 +2629,15 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
switch(chat.mChatType)
{
case CHAT_TYPE_WHISPER:
- verb = " " + LLTrans::getString("whisper") + " ";
+ verb = LLTrans::getString("whisper") + " ";
break;
case CHAT_TYPE_DEBUG_MSG:
case CHAT_TYPE_OWNER:
case CHAT_TYPE_NORMAL:
- verb = ": ";
+ verb = "";
break;
case CHAT_TYPE_SHOUT:
- verb = " " + LLTrans::getString("shout") + " ";
+ verb = LLTrans::getString("shout") + " ";
break;
case CHAT_TYPE_START:
case CHAT_TYPE_STOP:
@@ -2368,16 +2645,33 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
break;
default:
LL_WARNS("Messaging") << "Unknown type " << chat.mChatType << " in chat!" << LL_ENDL;
- verb = " say, ";
+ verb = "";
break;
}
- chat.mText = from_name;
+ chat.mText = "";
chat.mText += verb;
chat.mText += mesg;
}
+ // We have a real utterance now, so can stop showing "..." and proceed.
+ if (chatter && chatter->isAvatar())
+ {
+ LLLocalSpeakerMgr::getInstance()->setSpeakerTyping(from_id, FALSE);
+ ((LLVOAvatar*)chatter)->stopTyping();
+
+ if (!is_muted && !is_busy)
+ {
+ visible_in_chat_bubble = gSavedSettings.getBOOL("UseChatBubbles");
+ std::string formated_msg = "";
+ LLViewerChat::formatChatMsg(chat, formated_msg);
+ LLChat chat_bubble = chat;
+ chat_bubble.mText = formated_msg;
+ ((LLVOAvatar*)chatter)->addChat(chat_bubble);
+ }
+ }
+
if (chatter)
{
chat.mPosAgent = chatter->getPositionAgent();
@@ -2396,19 +2690,9 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
// T * * * F Yes Yes
chat.mMuted = is_muted && !is_linden;
-
-
- if (!visible_in_chat_bubble
- && (is_linden || !is_busy || is_owned_by_me))
- {
- // show on screen and add to history
- LLFloaterChat::addChat(chat, FALSE, FALSE);
- }
- else
- {
- // just add to chat history
- LLFloaterChat::addChatHistory(chat);
- }
+
+ LLNotificationsUI::LLNotificationManager::instance().onChat(
+ chat, LLNotificationsUI::NT_NEARBYCHAT);
}
}
@@ -2430,7 +2714,7 @@ void process_teleport_start(LLMessageSystem *msg, void**)
}
else
{
- gViewerWindow->setProgressCancelButtonVisible(TRUE, std::string("Cancel")); // *TODO: Translate
+ gViewerWindow->setProgressCancelButtonVisible(TRUE, LLTrans::getString("Cancel"));
}
// Freeze the UI and show progress bar
@@ -2465,7 +2749,7 @@ void process_teleport_progress(LLMessageSystem* msg, void**)
}
else
{
- gViewerWindow->setProgressCancelButtonVisible(TRUE, std::string("Cancel")); //TODO: Translate
+ gViewerWindow->setProgressCancelButtonVisible(TRUE, LLTrans::getString("Cancel"));
}
std::string buffer;
msg->getString("Info", "Message", buffer);
@@ -2520,13 +2804,13 @@ public:
{ // Show notification that they can now teleport to landmarks. Use a random landmark from the inventory
S32 random_land = ll_rand( land_items.count() - 1 );
args["NAME"] = land_items[random_land]->getName();
- LLNotifications::instance().add("TeleportToLandmark",args);
+ LLNotificationsUtil::add("TeleportToLandmark",args);
}
if ( card_items.count() > 0 )
{ // Show notification that they can now contact people. Use a random calling card from the inventory
S32 random_card = ll_rand( card_items.count() - 1 );
args["NAME"] = card_items[random_card]->getName();
- LLNotifications::instance().add("TeleportToPerson",args);
+ LLNotificationsUtil::add("TeleportToPerson",args);
}
gInventory.removeObserver(this);
@@ -2561,11 +2845,10 @@ BOOL LLPostTeleportNotifiers::tick()
{
// get callingcards and landmarks available to the user arriving.
LLInventoryFetchDescendentsObserver::folder_ref_t folders;
- LLUUID folder_id;
- folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD);
- if(folder_id.notNull())
- folders.push_back(folder_id);
- folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK);
+ const LLUUID callingcard_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD);
+ if(callingcard_id.notNull())
+ folders.push_back(callingcard_id);
+ const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
if(folder_id.notNull())
folders.push_back(folder_id);
if(!folders.empty())
@@ -2794,9 +3077,11 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**)
if (avatarp)
{
// Chat the "back" SLURL. (DEV-4907)
- LLChat chat("Teleport completed from " + gAgent.getTeleportSourceSLURL());
- chat.mSourceType = CHAT_SOURCE_SYSTEM;
- LLFloaterChat::addChatHistory(chat);
+
+ //TODO* CHAT: how to show this?
+ //LLSD args;
+ //args["MESSAGE"] = message;
+ //LLNotificationsUtil::add("SystemMessage", args);
// Set the new position
avatarp->setPositionAgent(agent_pos);
@@ -2878,9 +3163,33 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**)
if (!gLastVersionChannel.empty())
{
- LLSD payload;
- payload["message"] = version_channel;
- LLNotifications::instance().add("ServerVersionChanged", LLSD(), payload);
+ // work out the URL for this server's Release Notes
+ std::string url ="http://wiki.secondlife.com/wiki/Release_Notes/";
+ std::string server_version = version_channel;
+ std::vector<std::string> s_vect;
+ boost::algorithm::split(s_vect, server_version, isspace);
+ for(U32 i = 0; i < s_vect.size(); i++)
+ {
+ if (i != (s_vect.size() - 1))
+ {
+ if(i != (s_vect.size() - 2))
+ {
+ url += s_vect[i] + "_";
+ }
+ else
+ {
+ url += s_vect[i] + "/";
+ }
+ }
+ else
+ {
+ url += s_vect[i].substr(0,4);
+ }
+ }
+
+ LLSD args;
+ args["URL"] = url;
+ LLNotificationsUtil::add("ServerVersionChanged", args);
}
gLastVersionChannel = version_channel;
@@ -3010,6 +3319,10 @@ void send_agent_update(BOOL force_send, BOOL send_reliable)
{
flags |= AU_FLAGS_HIDETITLE;
}
+ if (gAgent.getAutoPilot())
+ {
+ flags |= AU_FLAGS_CLIENT_AUTOPILOT;
+ }
flag_change = last_flags ^ flags;
@@ -3162,7 +3475,6 @@ void process_object_update(LLMessageSystem *mesgsys, void **user_data)
// Update the object...
gObjectList.processObjectUpdate(mesgsys, user_data, OUT_FULL);
- stop_glerror();
}
void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data)
@@ -3180,7 +3492,6 @@ void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data
// Update the object...
gObjectList.processCompressedObjectUpdate(mesgsys, user_data, OUT_FULL_COMPRESSED);
- stop_glerror();
}
void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data)
@@ -3198,7 +3509,6 @@ void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data)
// Update the object...
gObjectList.processCachedObjectUpdate(mesgsys, user_data, OUT_FULL_CACHED);
- stop_glerror();
}
@@ -3217,11 +3527,12 @@ void process_terse_object_update_improved(LLMessageSystem *mesgsys, void **user_
gObjectList.processCompressedObjectUpdate(mesgsys, user_data, OUT_TERSE_IMPROVED);
}
+static LLFastTimer::DeclareTimer FTM_PROCESS_OBJECTS("Process Objects");
void process_kill_object(LLMessageSystem *mesgsys, void **user_data)
{
- LLFastTimer t(LLFastTimer::FTM_PROCESS_OBJECTS);
+ LLFastTimer t(FTM_PROCESS_OBJECTS);
LLUUID id;
U32 local_id;
@@ -3677,6 +3988,17 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data)
avatarp->mSignaledAnimations[animation_id] = anim_sequence_id;
+ // *HACK: Disabling flying mode if it has been enabled shortly before the agent
+ // stand up animation is signaled. In this case we don't get a signal to start
+ // flying animation from server, the AGENT_CONTROL_FLY flag remains set but the
+ // avatar does not play flying animation, so we switch flying mode off.
+ // See LLAgent::setFlying(). This may cause "Stop Flying" button to blink.
+ // See EXT-2781.
+ if (animation_id == ANIM_AGENT_STANDUP && gAgent.getFlying())
+ {
+ gAgent.setFlying(FALSE);
+ }
+
if (i < num_source_blocks)
{
mesgsys->getUUIDFast(_PREHASH_AnimationSourceList, _PREHASH_ObjectID, object_id, i);
@@ -3782,13 +4104,13 @@ void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data)
gAgent.setSitCamera(sitObjectID, camera_eye, camera_at);
}
- gAgent.mForceMouselook = force_mouselook;
+ gAgent.setForceMouselook(force_mouselook);
LLViewerObject* object = gObjectList.findObject(sitObjectID);
if (object)
{
LLVector3 sit_spot = object->getPositionAgent() + (sitPosition * object->getRotation());
- if (!use_autopilot || (avatar && avatar->mIsSitting && avatar->getRoot() == object->getRoot()))
+ if (!use_autopilot || (avatar && avatar->isSitting() && avatar->getRoot() == object->getRoot()))
{
//we're already sitting on this object, so don't autopilot
}
@@ -4065,10 +4387,10 @@ void process_money_balance_reply( LLMessageSystem* msg, void** )
if (gStatusBar)
{
- S32 old_balance = gStatusBar->getBalance();
+ // S32 old_balance = gStatusBar->getBalance();
// This is an update, not the first transmission of balance
- if (old_balance != 0)
+ /* if (old_balance != 0)
{
// this is actually an update
if (balance > old_balance)
@@ -4080,7 +4402,7 @@ void process_money_balance_reply( LLMessageSystem* msg, void** )
LLFirstUse::useBalanceDecrease(balance - old_balance);
}
}
-
+ */
gStatusBar->setBalance(balance);
gStatusBar->setLandCredit(credit);
gStatusBar->setLandCommitted(committed);
@@ -4094,10 +4416,31 @@ void process_money_balance_reply( LLMessageSystem* msg, void** )
{
// Make the user confirm the transaction, since they might
// have missed something during an event.
- // *TODO:translate
+ // *TODO: Translate
LLSD args;
args["MESSAGE"] = desc;
- LLNotifications::instance().add("SystemMessage", args);
+
+ // this is a marker to retrieve avatar name from server message:
+ // "<avatar name> paid you L$"
+ const std::string marker = "paid you L$";
+
+ // extract avatar name from system message
+ std::string name = desc.substr(0, desc.find(marker, 0));
+ LLStringUtil::trim(name);
+
+ // if name extracted and name cache contains avatar id send loggable notification
+ LLUUID from_id;
+ if(name.size() > 0 && gCacheName->getUUID(name, from_id))
+ {
+ args["NAME"] = name;
+ LLSD payload;
+ payload["from_id"] = from_id;
+ LLNotificationsUtil::add("PaymentRecived", args, payload);
+ }
+ else
+ {
+ LLNotificationsUtil::add("SystemMessage", args);
+ }
// Once the 'recent' container gets large enough, chop some
// off the beginning.
@@ -4115,7 +4458,7 @@ void process_money_balance_reply( LLMessageSystem* msg, void** )
bool handle_special_notification_callback(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
@@ -4136,18 +4479,18 @@ bool handle_special_notification(std::string notificationID, LLSD& llsdBlock)
llsdBlock["REGIONMATURITY"] = LLViewerRegion::accessToString(regionAccess);
// we're going to throw the LLSD in there in case anyone ever wants to use it
- LLNotifications::instance().add(notificationID+"_Notify", llsdBlock);
+ LLNotificationsUtil::add(notificationID+"_Notify", llsdBlock);
if (regionAccess == SIM_ACCESS_MATURE)
{
if (gAgent.isTeen())
{
- LLNotifications::instance().add(notificationID+"_KB", llsdBlock);
+ LLNotificationsUtil::add(notificationID+"_KB", llsdBlock);
return true;
}
else if (gAgent.prefersPG())
{
- LLNotifications::instance().add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback);
+ LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback);
return true;
}
}
@@ -4155,12 +4498,12 @@ bool handle_special_notification(std::string notificationID, LLSD& llsdBlock)
{
if (!gAgent.isAdult())
{
- LLNotifications::instance().add(notificationID+"_KB", llsdBlock);
+ LLNotificationsUtil::add(notificationID+"_KB", llsdBlock);
return true;
}
else if (gAgent.prefersPG() || gAgent.prefersMature())
{
- LLNotifications::instance().add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback);
+ LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback);
return true;
}
}
@@ -4170,7 +4513,7 @@ bool handle_special_notification(std::string notificationID, LLSD& llsdBlock)
bool attempt_standard_notification(LLMessageSystem* msgsystem)
{
// if we have additional alert data
- if (msgsystem->getNumberOfBlocksFast(_PREHASH_AlertInfo) > 0)
+ if (msgsystem->has(_PREHASH_AlertInfo) && msgsystem->getNumberOfBlocksFast(_PREHASH_AlertInfo) > 0)
{
// notification was specified using the new mechanism, so we can just handle it here
std::string notificationID;
@@ -4220,7 +4563,7 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem)
}
}
- LLNotifications::instance().add(notificationID, llsdBlock);
+ LLNotificationsUtil::add(notificationID, llsdBlock);
return true;
}
return false;
@@ -4276,7 +4619,7 @@ void process_alert_core(const std::string& message, BOOL modal)
std::string snap_filename = gDirUtilp->getLindenUserDir();
snap_filename += gDirUtilp->getDirDelimiter();
snap_filename += SCREEN_HOME_FILENAME;
- gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight(), FALSE, FALSE);
+ gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw(), FALSE, FALSE);
}
const std::string ALERT_PREFIX("ALERT: ");
@@ -4286,14 +4629,14 @@ void process_alert_core(const std::string& message, BOOL modal)
// Allow the server to spawn a named alert so that server alerts can be
// translated out of English.
std::string alert_name(message.substr(ALERT_PREFIX.length()));
- LLNotifications::instance().add(alert_name);
+ LLNotificationsUtil::add(alert_name);
}
else if (message.find(NOTIFY_PREFIX) == 0)
{
// Allow the server to spawn a named notification so that server notifications can be
// translated out of English.
std::string notify_name(message.substr(NOTIFY_PREFIX.length()));
- LLNotifications::instance().add(notify_name);
+ LLNotificationsUtil::add(notify_name);
}
else if (message[0] == '/')
{
@@ -4305,35 +4648,35 @@ void process_alert_core(const std::string& message, BOOL modal)
S32 mins = 0;
LLStringUtil::convertToS32(text.substr(18), mins);
args["MINUTES"] = llformat("%d",mins);
- LLNotifications::instance().add("RegionRestartMinutes", args);
+ LLNotificationsUtil::add("RegionRestartMinutes", args);
}
else if (text.substr(0,17) == "RESTART_X_SECONDS")
{
S32 secs = 0;
LLStringUtil::convertToS32(text.substr(18), secs);
args["SECONDS"] = llformat("%d",secs);
- LLNotifications::instance().add("RegionRestartSeconds", args);
+ LLNotificationsUtil::add("RegionRestartSeconds", args);
}
else
{
- // *TODO:translate
- args["MESSAGE"] = text;
- LLNotifications::instance().add("SystemMessage", args);
+ std::string new_msg =LLNotifications::instance().getGlobalString(text);
+ args["MESSAGE"] = new_msg;
+ LLNotificationsUtil::add("SystemMessage", args);
}
}
else if (modal)
{
- // *TODO:translate
LLSD args;
- args["ERROR_MESSAGE"] = message;
- LLNotifications::instance().add("ErrorMessage", args);
+ std::string new_msg =LLNotifications::instance().getGlobalString(message);
+ args["ERROR_MESSAGE"] = new_msg;
+ LLNotificationsUtil::add("ErrorMessage", args);
}
else
{
- // *TODO:translate
LLSD args;
- args["MESSAGE"] = message;
- LLNotifications::instance().add("SystemMessageTip", args);
+ std::string new_msg =LLNotifications::instance().getGlobalString(message);
+ args["MESSAGE"] = new_msg;
+ LLNotificationsUtil::add("SystemMessageTip", args);
}
}
@@ -4346,11 +4689,11 @@ void handle_show_mean_events(void *)
{
return;
}
-
- LLFloaterBump::show(NULL);
+ LLFloaterReg::showInstance("bumps");
+ //LLFloaterBump::showInstance();
}
-void mean_name_callback(const LLUUID &id, const std::string& first, const std::string& last, BOOL always_false, void* data)
+void mean_name_callback(const LLUUID &id, const std::string& first, const std::string& last, BOOL always_false)
{
if (gNoRender)
{
@@ -4428,7 +4771,7 @@ void process_mean_collision_alert_message(LLMessageSystem *msgsystem, void **use
LLMeanCollisionData *mcd = new LLMeanCollisionData(gAgentID, perp, time, type, mag);
gMeanCollisionList.push_front(mcd);
const BOOL is_group = FALSE;
- gCacheName->get(perp, is_group, mean_name_callback);
+ gCacheName->get(perp, is_group, &mean_name_callback);
}
}
}
@@ -4460,9 +4803,6 @@ void process_economy_data(LLMessageSystem *msg, void** /*user_data*/)
LL_INFOS_ONCE("Messaging") << "EconomyData message arrived; upload cost is L$" << upload_cost << LL_ENDL;
- LLFloaterImagePreview::setUploadAmount(upload_cost);
- LLFloaterAnimPreview::setUploadAmount(upload_cost);
-
gMenuHolder->childSetLabelArg("Upload Image", "[COST]", llformat("%d", upload_cost));
gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", llformat("%d", upload_cost));
gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", llformat("%d", upload_cost));
@@ -4480,7 +4820,7 @@ void notify_cautioned_script_question(const LLSD& notification, const LLSD& resp
// located in [REGIONNAME] at [REGIONPOS],
// has been <granted|denied> permission to: [PERMISSIONS]."
- LLUIString notice(LLFloaterChat::getInstance()->getString(granted ? "ScriptQuestionCautionChatGranted" : "ScriptQuestionCautionChatDenied"));
+ LLUIString notice(LLTrans::getString(granted ? "ScriptQuestionCautionChatGranted" : "ScriptQuestionCautionChatDenied"));
// always include the object name and owner name
notice.setArg("[OBJECTNAME]", notification["payload"]["object_name"].asString());
@@ -4534,7 +4874,7 @@ void notify_cautioned_script_question(const LLSD& notification, const LLSD& resp
perms.append(", ");
}
- perms.append(LLFloaterChat::getInstance()->getString(SCRIPT_QUESTIONS[i]));
+ perms.append(LLTrans::getString(SCRIPT_QUESTIONS[i]));
}
}
@@ -4545,14 +4885,14 @@ void notify_cautioned_script_question(const LLSD& notification, const LLSD& resp
if (caution)
{
LLChat chat(notice.getString());
- LLFloaterChat::addChat(chat, FALSE, FALSE);
+ // LLFloaterChat::addChat(chat, FALSE, FALSE);
}
}
}
bool script_question_cb(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLMessageSystem *msg = gMessageSystem;
S32 orig = notification["payload"]["questions"].asInteger();
S32 new_questions = orig;
@@ -4593,33 +4933,34 @@ bool script_question_cb(const LLSD& notification, const LLSD& response)
LLMuteList::getInstance()->add(LLMute(item_id, notification["payload"]["object_name"].asString(), LLMute::OBJECT));
// purge the message queue of any previously queued requests from the same source. DEV-4879
- class OfferMatcher : public LLNotifyBoxView::Matcher
+ class OfferMatcher : public LLNotificationsUI::LLScreenChannel::Matcher
{
public:
OfferMatcher(const LLUUID& to_block) : blocked_id(to_block) {}
- BOOL matches(const LLNotificationPtr notification) const
+ bool matches(const LLNotificationPtr notification) const
{
if (notification->getName() == "ScriptQuestionCaution"
|| notification->getName() == "ScriptQuestion")
{
return (notification->getPayload()["item_id"].asUUID() == blocked_id);
}
- return FALSE;
+ return false;
}
private:
const LLUUID& blocked_id;
};
- // should do this via the channel
- gNotifyBoxView->purgeMessagesMatching(OfferMatcher(item_id));
+
+ LLNotificationsUI::LLChannelManager::getInstance()->killToastsFromChannel(LLUUID(
+ gSavedSettings.getString("NotificationChannelUUID")), OfferMatcher(item_id));
}
if (response["Details"])
{
// respawn notification...
- LLNotifications::instance().add(notification["name"], notification["substitutions"], notification["payload"]);
+ LLNotificationsUtil::add(notification["name"], notification["substitutions"], notification["payload"]);
// ...with description on top
- LLNotifications::instance().add("DebitPermissionDetails");
+ LLNotificationsUtil::add("DebitPermissionDetails");
}
return false;
}
@@ -4628,7 +4969,7 @@ static LLNotificationFunctorRegistration script_question_cb_reg_2("ScriptQuestio
void process_script_question(LLMessageSystem *msg, void **user_data)
{
- // *TODO:translate owner name -> [FIRST] [LAST]
+ // *TODO: Translate owner name -> [FIRST] [LAST]
LLHost sender = msg->getSender();
@@ -4652,7 +4993,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
// so we'll reuse the same namespace for both throttle types.
std::string throttle_name = owner_name;
std::string self_name;
- gAgent.getName( self_name );
+ LLAgentUI::buildName( self_name );
if( owner_name == self_name )
{
throttle_name = taskid.getString();
@@ -4696,7 +5037,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
if (questions & LSCRIPTRunTimePermissionBits[i])
{
count++;
- script_question += " " + LLFloaterChat::getInstance()->getString(SCRIPT_QUESTIONS[i]) + "\n";
+ script_question += " " + LLTrans::getString(SCRIPT_QUESTIONS[i]) + "\n";
// check whether permission question should cause special caution dialog
caution |= (SCRIPT_QUESTION_IS_CAUTION[i]);
@@ -4716,12 +5057,12 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
if (gSavedSettings.getBOOL("PermissionsCautionEnabled"))
{
// display the caution permissions prompt
- LLNotifications::instance().add(caution ? "ScriptQuestionCaution" : "ScriptQuestion", args, payload);
+ LLNotificationsUtil::add(caution ? "ScriptQuestionCaution" : "ScriptQuestion", args, payload);
}
else
{
// fall back to default behavior if cautions are entirely disabled
- LLNotifications::instance().add("ScriptQuestion", args, payload);
+ LLNotificationsUtil::add("ScriptQuestion", args, payload);
}
}
@@ -4744,22 +5085,21 @@ void container_inventory_arrived(LLViewerObject* object,
gAgent.changeCameraToDefault();
}
- LLInventoryView* view = LLInventoryView::getActiveInventory();
+ LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel();
if (inventory->size() > 2)
{
// create a new inventory category to put this in
LLUUID cat_id;
- cat_id = gInventory.createNewCategory(gAgent.getInventoryRootID(),
- LLAssetType::AT_NONE,
- std::string("Acquired Items")); //TODO: Translate
+ cat_id = gInventory.createNewCategory(gInventory.getRootFolderID(),
+ LLFolderType::FT_NONE,
+ LLTrans::getString("AcquiredItems"));
InventoryObjectList::const_iterator it = inventory->begin();
InventoryObjectList::const_iterator end = inventory->end();
for ( ; it != end; ++it)
{
- if ((*it)->getType() != LLAssetType::AT_CATEGORY &&
- (*it)->getType() != LLAssetType::AT_ROOT_CATEGORY)
+ if ((*it)->getType() != LLAssetType::AT_CATEGORY)
{
LLInventoryObject* obj = (LLInventoryObject*)(*it);
LLInventoryItem* item = (LLInventoryItem*)(obj);
@@ -4783,9 +5123,9 @@ void container_inventory_arrived(LLViewerObject* object,
}
}
gInventory.notifyObservers();
- if(view)
+ if(active_panel)
{
- view->getPanel()->setSelection(cat_id, TAKE_FOCUS_NO);
+ active_panel->setSelection(cat_id, TAKE_FOCUS_NO);
}
}
else if (inventory->size() == 2)
@@ -4794,14 +5134,13 @@ void container_inventory_arrived(LLViewerObject* object,
// one actual object
InventoryObjectList::iterator it = inventory->begin();
- if ((*it)->getType() == LLAssetType::AT_CATEGORY ||
- (*it)->getType() == LLAssetType::AT_ROOT_CATEGORY)
+ if ((*it)->getType() == LLAssetType::AT_CATEGORY)
{
++it;
}
LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it));
- LLUUID category = gInventory.findCategoryUUIDForType(item->getType());
+ const LLUUID category = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(item->getType()));
LLUUID item_id;
item_id.generate();
@@ -4820,9 +5159,9 @@ void container_inventory_arrived(LLViewerObject* object,
new_item->updateServer(TRUE);
gInventory.updateItem(new_item);
gInventory.notifyObservers();
- if(view)
+ if(active_panel)
{
- view->getPanel()->setSelection(item_id, TAKE_FOCUS_NO);
+ active_panel->setSelection(item_id, TAKE_FOCUS_NO);
}
}
@@ -4846,10 +5185,18 @@ void container_inventory_arrived(LLViewerObject* object,
// method to format the time.
std::string formatted_time(const time_t& the_time)
{
- char buffer[30]; /* Flawfinder: ignore */
- LLStringUtil::copy(buffer, ctime(&the_time), 30);
- buffer[24] = '\0';
- return std::string(buffer);
+ std::string dateStr = "["+LLTrans::getString("LTimeWeek")+"] ["
+ +LLTrans::getString("LTimeMonth")+"] ["
+ +LLTrans::getString("LTimeDay")+"] ["
+ +LLTrans::getString("LTimeHour")+"]:["
+ +LLTrans::getString("LTimeMin")+"]:["
+ +LLTrans::getString("LTimeSec")+"] ["
+ +LLTrans::getString("LTimeYear")+"]";
+
+ LLSD substitution;
+ substitution["datetime"] = (S32) the_time;
+ LLStringUtil::format (dateStr, substitution);
+ return dateStr;
}
@@ -4860,7 +5207,7 @@ void process_teleport_failed(LLMessageSystem *msg, void**)
LLSD args;
// if we have additional alert data
- if (msg->getNumberOfBlocksFast(_PREHASH_AlertInfo) > 0)
+ if (msg->has(_PREHASH_AlertInfo) && msg->getSizeFast(_PREHASH_AlertInfo, _PREHASH_Message) > 0)
{
// Get the message ID
msg->getStringFast(_PREHASH_AlertInfo, _PREHASH_Message, reason);
@@ -4915,7 +5262,10 @@ void process_teleport_failed(LLMessageSystem *msg, void**)
}
}
- LLNotifications::instance().add("CouldNotTeleportReason", args);
+ LLNotificationsUtil::add("CouldNotTeleportReason", args);
+
+ // Let the interested parties know that teleport failed.
+ LLViewerParcelMgr::getInstance()->onTeleportFailed();
if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE )
{
@@ -4966,6 +5316,11 @@ void process_teleport_local(LLMessageSystem *msg,void**)
gAgent.updateCamera();
send_agent_update(TRUE, TRUE);
+
+ // Let the interested parties know we've teleported.
+ // Vadim *HACK: Agent position seems to get reset (to render position?)
+ // on each frame, so we have to pass the new position manually.
+ LLViewerParcelMgr::getInstance()->onTeleportFinished(true, gAgent.getPosGlobalFromAgent(pos));
}
void send_simple_im(const LLUUID& to_id,
@@ -4974,7 +5329,7 @@ void send_simple_im(const LLUUID& to_id,
const LLUUID& id)
{
std::string my_name;
- gAgent.buildFullname(my_name);
+ LLAgentUI::buildFullname(my_name);
send_improved_im(to_id,
my_name,
message,
@@ -4995,7 +5350,7 @@ void send_group_notice(const LLUUID& group_id,
// This will mean converting the item to a binary bucket,
// and the subject/message into a single field.
std::string my_name;
- gAgent.buildFullname(my_name);
+ LLAgentUI::buildFullname(my_name);
// Combine subject + message into a single string.
std::ostringstream subject_and_message;
@@ -5040,7 +5395,8 @@ void send_group_notice(const LLUUID& group_id,
bool handle_lure_callback(const LLSD& notification, const LLSD& response)
{
std::string text = response["message"].asString();
- S32 option = LLNotification::getSelectedOption(notification, response);
+ text.append("\r\n").append(LLAgentUI::buildSLURL());
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if(0 == option)
{
@@ -5056,8 +5412,24 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response)
it != notification["payload"]["ids"].endArray();
++it)
{
+ LLUUID target_id = it->asUUID();
+
msg->nextBlockFast(_PREHASH_TargetData);
- msg->addUUIDFast(_PREHASH_TargetID, it->asUUID());
+ msg->addUUIDFast(_PREHASH_TargetID, target_id);
+
+ // Record the offer.
+ {
+ std::string target_name;
+ gCacheName->getFullName(target_id, target_name);
+ LLSD args;
+ args["TO_NAME"] = target_name;
+
+ LLSD payload;
+ payload["from_id"] = target_id;
+ payload["SESSION_NAME"] = target_name;
+ payload["SUPPRESS_TOAST"] = true;
+ LLNotificationsUtil::add("TeleportOfferSent", args, payload);
+ }
}
gAgent.sendReliableMessage();
}
@@ -5073,13 +5445,13 @@ void handle_lure(const LLUUID& invitee)
}
// Prompt for a message to the invited user.
-void handle_lure(LLDynamicArray<LLUUID>& ids)
+void handle_lure(const std::vector<LLUUID>& ids)
{
LLSD edit_args;
edit_args["REGION"] = gAgent.getRegion()->getName();
LLSD payload;
- for (LLDynamicArray<LLUUID>::iterator it = ids.begin();
+ for (LLDynamicArray<LLUUID>::const_iterator it = ids.begin();
it != ids.end();
++it)
{
@@ -5087,11 +5459,11 @@ void handle_lure(LLDynamicArray<LLUUID>& ids)
}
if (gAgent.isGodlike())
{
- LLNotifications::instance().add("OfferTeleportFromGod", edit_args, payload, handle_lure_callback);
+ LLNotificationsUtil::add("OfferTeleportFromGod", edit_args, payload, handle_lure_callback);
}
else
{
- LLNotifications::instance().add("OfferTeleport", edit_args, payload, handle_lure_callback);
+ LLNotificationsUtil::add("OfferTeleport", edit_args, payload, handle_lure_callback);
}
}
@@ -5284,7 +5656,7 @@ std::vector<LLSD> gLoadUrlList;
bool callback_load_url(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
@@ -5298,7 +5670,7 @@ static LLNotificationFunctorRegistration callback_load_url_reg("LoadWebPage", ca
// We've got the name of the person who owns the object hurling the url.
// Display confirmation dialog.
-void callback_load_url_name(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* data)
+void callback_load_url_name(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
{
std::vector<LLSD>::iterator it;
for (it = gLoadUrlList.begin(); it != gLoadUrlList.end(); )
@@ -5311,7 +5683,7 @@ void callback_load_url_name(const LLUUID& id, const std::string& first, const st
std::string owner_name;
if (is_group)
{
- owner_name = first + " (group)";
+ owner_name = first + LLTrans::getString("Group");
}
else
{
@@ -5329,7 +5701,7 @@ void callback_load_url_name(const LLUUID& id, const std::string& first, const st
args["OBJECTNAME"] = load_url_info["object_name"].asString();
args["NAME"] = owner_name;
- LLNotifications::instance().add("LoadWebPage", args, load_url_info);
+ LLNotificationsUtil::add("LoadWebPage", args, load_url_info);
}
else
{
@@ -5375,7 +5747,7 @@ void process_load_url(LLMessageSystem* msg, void**)
// Add to list of pending name lookups
gLoadUrlList.push_back(payload);
- gCacheName->get(owner_id, owner_is_group, callback_load_url_name);
+ gCacheName->get(owner_id, owner_is_group, &callback_load_url_name);
}
@@ -5384,7 +5756,7 @@ void callback_download_complete(void** data, S32 result, LLExtStat ext_status)
std::string* filepath = (std::string*)data;
LLSD args;
args["DOWNLOAD_PATH"] = *filepath;
- LLNotifications::instance().add("FinishedRawDownload", args);
+ LLNotificationsUtil::add("FinishedRawDownload", args);
delete filepath;
}
@@ -5431,12 +5803,17 @@ void process_script_teleport_request(LLMessageSystem* msg, void**)
msg->getVector3("Data", "SimPosition", pos);
msg->getVector3("Data", "LookAt", look_at);
- gFloaterWorldMap->trackURL(sim_name, (S32)pos.mV[VX], (S32)pos.mV[VY], (S32)pos.mV[VZ]);
- LLFloaterWorldMap::show(NULL, TRUE);
-
+ LLFloaterWorldMap* instance = LLFloaterWorldMap::getInstance();
+ if(instance)
+ {
+ instance->trackURL(
+ sim_name, (S32)pos.mV[VX], (S32)pos.mV[VY], (S32)pos.mV[VZ]);
+ LLFloaterReg::showInstance("world_map", "center");
+ }
+
// remove above two lines and replace with below line
// to re-enable parcel browser for llMapDestination()
- // LLURLDispatcher::dispatch(LLURLDispatcher::buildSLURL(sim_name, (S32)pos.mV[VX], (S32)pos.mV[VY], (S32)pos.mV[VZ]), FALSE);
+ // LLURLDispatcher::dispatch(LLSLURL::buildSLURL(sim_name, (S32)pos.mV[VX], (S32)pos.mV[VY], (S32)pos.mV[VZ]), FALSE);
}
@@ -5454,23 +5831,44 @@ void process_covenant_reply(LLMessageSystem* msg, void**)
LLPanelLandCovenant::updateEstateName(estate_name);
LLFloaterBuyLand::updateEstateName(estate_name);
+ std::string owner_name =
+ LLSLURL::buildCommand("agent", estate_owner_id, "inspect");
+ LLPanelEstateCovenant::updateEstateOwnerName(owner_name);
+ LLPanelLandCovenant::updateEstateOwnerName(owner_name);
+ LLFloaterBuyLand::updateEstateOwnerName(owner_name);
+
+ LLPanelPlaceProfile* panel = LLSideTray::getInstance()->findChild<LLPanelPlaceProfile>("panel_place_profile");
+ if (panel)
+ {
+ panel->updateEstateName(estate_name);
+ panel->updateEstateOwnerName(owner_name);
+ }
+
// standard message, not from system
std::string last_modified;
if (covenant_timestamp == 0)
{
- last_modified = LLTrans::getString("covenant_never_modified");
+ last_modified = LLTrans::getString("covenant_last_modified")+LLTrans::getString("never_text");
}
else
{
- last_modified = LLTrans::getString("covenant_modified") + " " + formatted_time((time_t)covenant_timestamp);
+ last_modified = LLTrans::getString("covenant_last_modified")+"["
+ +LLTrans::getString("LTimeWeek")+"] ["
+ +LLTrans::getString("LTimeMonth")+"] ["
+ +LLTrans::getString("LTimeDay")+"] ["
+ +LLTrans::getString("LTimeHour")+"]:["
+ +LLTrans::getString("LTimeMin")+"]:["
+ +LLTrans::getString("LTimeSec")+"] ["
+ +LLTrans::getString("LTimeYear")+"]";
+ LLSD substitution;
+ substitution["datetime"] = (S32) covenant_timestamp;
+ LLStringUtil::format (last_modified, substitution);
}
LLPanelEstateCovenant::updateLastModified(last_modified);
LLPanelLandCovenant::updateLastModified(last_modified);
LLFloaterBuyLand::updateLastModified(last_modified);
- gCacheName->getName(estate_owner_id, callbackCacheEstateOwnerName);
-
// load the actual covenant asset data
const BOOL high_priority = TRUE;
if (covenant_id.notNull())
@@ -5491,37 +5889,22 @@ void process_covenant_reply(LLMessageSystem* msg, void**)
if (estate_owner_id.isNull())
{
// mainland
- covenant_text = "There is no Covenant provided for this Estate.";
+ covenant_text = LLTrans::getString("RegionNoCovenant");
}
else
{
- covenant_text = "There is no Covenant provided for this Estate. The land on this estate is being sold by the Estate owner, not Linden Lab. Please contact the Estate Owner for sales details.";
+ covenant_text = LLTrans::getString("RegionNoCovenantOtherOwner");
}
LLPanelEstateCovenant::updateCovenantText(covenant_text, covenant_id);
LLPanelLandCovenant::updateCovenantText(covenant_text);
LLFloaterBuyLand::updateCovenantText(covenant_text, covenant_id);
+ if (panel)
+ {
+ panel->updateCovenantText(covenant_text);
+ }
}
}
-void callbackCacheEstateOwnerName(const LLUUID& id,
- const std::string& first, const std::string& last,
- BOOL is_group, void*)
-{
- std::string name;
-
- if (id.isNull())
- {
- name = "(none)";
- }
- else
- {
- name = first + " " + last;
- }
- LLPanelEstateCovenant::updateEstateOwnerName(name);
- LLPanelLandCovenant::updateEstateOwnerName(name);
- LLFloaterBuyLand::updateEstateOwnerName(name);
-}
-
void onCovenantLoadComplete(LLVFS *vfs,
const LLUUID& asset_uuid,
LLAssetType::EType type,
@@ -5542,10 +5925,10 @@ void onCovenantLoadComplete(LLVFS *vfs,
if( (file_length > 19) && !strncmp( &buffer[0], "Linden text version", 19 ) )
{
- LLViewerTextEditor* editor =
- new LLViewerTextEditor(std::string("temp"),
- LLRect(0,0,0,0),
- file_length+1);
+ LLViewerTextEditor::Params params;
+ params.name("temp");
+ params.max_text_length(file_length+1);
+ LLViewerTextEditor * editor = LLUICtrlFactory::create<LLViewerTextEditor> (params);
if( !editor->importBuffer( &buffer[0], file_length+1 ) )
{
LL_WARNS("Messaging") << "Problem importing estate covenant." << LL_ENDL;
@@ -5587,6 +5970,12 @@ void onCovenantLoadComplete(LLVFS *vfs,
LLPanelEstateCovenant::updateCovenantText(covenant_text, asset_uuid);
LLPanelLandCovenant::updateCovenantText(covenant_text);
LLFloaterBuyLand::updateCovenantText(covenant_text, asset_uuid);
+
+ LLPanelPlaceProfile* panel = LLSideTray::getInstance()->findChild<LLPanelPlaceProfile>("panel_place_profile");
+ if (panel)
+ {
+ panel->updateCovenantText(covenant_text);
+ }
}
@@ -5620,6 +6009,6 @@ void invalid_message_callback(LLMessageSystem* msg,
void LLOfferInfo::forceResponse(InventoryOfferResponse response)
{
LLNotification::Params params("UserGiveItem");
- params.functor(boost::bind(&LLOfferInfo::inventory_offer_callback, this, _1, _2));
+ params.functor.function(boost::bind(&LLOfferInfo::inventory_offer_callback, this, _1, _2));
LLNotifications::instance().forceResponse(params, response);
}
diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h
index e7a4303a8e..8404d6fde0 100644
--- a/indra/newview/llviewermessage.h
+++ b/indra/newview/llviewermessage.h
@@ -33,19 +33,24 @@
#ifndef LL_LLVIEWERMESSAGE_H
#define LL_LLVIEWERMESSAGE_H
+#include "llassettype.h"
#include "llinstantmessage.h"
+#include "llpointer.h"
#include "lltransactiontypes.h"
#include "lluuid.h"
+#include "message.h"
#include "stdenums.h"
//
// Forward declarations
//
class LLColor4;
-class LLViewerObject;
class LLInventoryObject;
class LLInventoryItem;
+class LLMeanCollisionData;
class LLMessageSystem;
+class LLVFS;
+class LLViewerObject;
class LLViewerRegion;
//
@@ -57,7 +62,8 @@ enum InventoryOfferResponse
IOR_ACCEPT,
IOR_DECLINE,
IOR_MUTE,
- IOR_BUSY
+ IOR_BUSY,
+ IOR_SHOW
};
BOOL can_afford_transaction(S32 cost);
@@ -151,7 +157,7 @@ void send_group_notice(const LLUUID& group_id,
const LLInventoryItem* item);
void handle_lure(const LLUUID& invitee);
-void handle_lure(LLDynamicArray<LLUUID>& ids);
+void handle_lure(const std::vector<LLUUID>& ids);
// always from gAgent and
// routes through the gAgent's current simulator
@@ -195,6 +201,7 @@ void invalid_message_callback(LLMessageSystem*, void*, EMessageException);
void process_initiate_download(LLMessageSystem* msg, void**);
void start_new_inventory_observer();
+void open_inventory_offer(const std::vector<LLUUID>& items, const std::string& from_name);
struct LLOfferInfo
{
@@ -216,7 +223,9 @@ struct LLOfferInfo
LLHost mHost;
LLSD asLLSD();
+ void send_auto_receive_response(void);
bool inventory_offer_callback(const LLSD& notification, const LLSD& response);
+ bool inventory_task_offer_callback(const LLSD& notification, const LLSD& response);
};
diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp
index 8719557cbc..d7b55d7e97 100644
--- a/indra/newview/llviewernetwork.cpp
+++ b/indra/newview/llviewernetwork.cpp
@@ -34,7 +34,12 @@
#include "llviewerprecompiledheaders.h"
#include "llviewernetwork.h"
+
+#include "llevents.h"
+#include "net.h"
+
#include "llviewercontrol.h"
+#include "lllogin.h"
struct LLGridData
{
@@ -155,6 +160,10 @@ LLViewerLogin::LLViewerLogin() :
{
}
+ LLViewerLogin::~LLViewerLogin()
+ {
+ }
+
void LLViewerLogin::setGridChoice(EGridInfo grid)
{
if(grid < 0 || grid >= GRID_INFO_COUNT)
@@ -218,7 +227,7 @@ void LLViewerLogin::setGridChoice(const std::string& grid_name)
void LLViewerLogin::resetURIs()
{
// Clear URIs when picking a new server
- gSavedSettings.setValue("CmdLineLoginURI", LLSD::emptyArray());
+ gSavedSettings.setLLSD("CmdLineLoginURI", LLSD::emptyArray());
gSavedSettings.setString("CmdLineHelperURI", "");
}
diff --git a/indra/newview/llviewernetwork.h b/indra/newview/llviewernetwork.h
index 4001ed05c1..edae6dc47b 100644
--- a/indra/newview/llviewernetwork.h
+++ b/indra/newview/llviewernetwork.h
@@ -34,7 +34,10 @@
#ifndef LL_LLVIEWERNETWORK_H
#define LL_LLVIEWERNETWORK_H
+#include <boost/scoped_ptr.hpp>
+
class LLHost;
+class LLLogin;
enum EGridInfo
{
@@ -74,6 +77,7 @@ class LLViewerLogin : public LLSingleton<LLViewerLogin>
{
public:
LLViewerLogin();
+ ~LLViewerLogin();
void setGridChoice(EGridInfo grid);
void setGridChoice(const std::string& grid_name);
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index d4e594656b..3c79045cc5 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -34,7 +34,7 @@
#include "llviewerobject.h"
-#include "audioengine.h"
+#include "llaudioengine.h"
#include "imageids.h"
#include "indra_constants.h"
#include "llmath.h"
@@ -42,6 +42,7 @@
#include "llviewercontrol.h"
#include "lldatapacker.h"
#include "llfasttimer.h"
+#include "llfloaterreg.h"
#include "llfontgl.h"
#include "llframetimer.h"
#include "llinventory.h"
@@ -70,7 +71,7 @@
#include "llrendersphere.h"
#include "lltooldraganddrop.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewerinventory.h"
#include "llviewerobjectlist.h"
#include "llviewerparceloverlay.h"
@@ -79,6 +80,7 @@
#include "llviewertextureanim.h"
#include "llviewerwindow.h" // For getSpinAxis
#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "llvoclouds.h"
#include "llvograss.h"
#include "llvoground.h"
@@ -97,6 +99,9 @@
#include "llviewernetwork.h"
#include "llvowlsky.h"
#include "llmanip.h"
+#include "lltrans.h"
+#include "llsdutil.h"
+#include "llmediaentry.h"
//#define DEBUG_UPDATE_TYPE
@@ -112,18 +117,31 @@ S32 LLViewerObject::sAxisArrowLength(50);
BOOL LLViewerObject::sPulseEnabled(FALSE);
BOOL LLViewerObject::sUseSharedDrawables(FALSE); // TRUE
+static LLFastTimer::DeclareTimer FTM_CREATE_OBJECT("Create Object");
+
// static
LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
{
LLViewerObject *res = NULL;
- LLFastTimer t1(LLFastTimer::FTM_CREATE_OBJECT);
+ LLFastTimer t1(FTM_CREATE_OBJECT);
switch (pcode)
{
case LL_PCODE_VOLUME:
res = new LLVOVolume(id, pcode, regionp); break;
case LL_PCODE_LEGACY_AVATAR:
- res = new LLVOAvatar(id, pcode, regionp); break;
+ {
+ if (id == gAgentID)
+ {
+ res = new LLVOAvatarSelf(id, pcode, regionp);
+ }
+ else
+ {
+ res = new LLVOAvatar(id, pcode, regionp);
+ }
+ static_cast<LLVOAvatar*>(res)->initInstance();
+ break;
+ }
case LL_PCODE_LEGACY_GRASS:
res = new LLVOGrass(id, pcode, regionp); break;
case LL_PCODE_LEGACY_PART_SYS:
@@ -201,7 +219,8 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
mJointInfo(NULL),
mState(0),
mMedia(NULL),
- mClickAction(0)
+ mClickAction(0),
+ mAttachmentItemID(LLUUID::null)
{
if(!is_global)
{
@@ -454,6 +473,7 @@ void LLViewerObject::cleanupVOClasses()
LLVOWater::cleanupClass();
LLVOTree::cleanupClass();
LLVOAvatar::cleanupClass();
+ LLVOVolume::cleanupClass();
}
// Replaces all name value pairs with data from \n delimited list
@@ -499,15 +519,24 @@ BOOL LLViewerObject::isOverGroupOwnedLand() const
&& mRegionp->getParcelOverlay()->isOwnedGroup(getPositionRegion());
}
-void LLViewerObject::setParent(LLViewerObject* parent)
+BOOL LLViewerObject::setParent(LLViewerObject* parent)
{
- LLPrimitive::setParent(parent);
+ if(mParent != parent)
+ {
+ LLViewerObject* old_parent = (LLViewerObject*)mParent ;
+ BOOL ret = LLPrimitive::setParent(parent);
+ if(ret && old_parent && parent)
+ {
+ old_parent->removeChild(this) ;
+ }
+ return ret ;
+ }
+
+ return FALSE ;
}
void LLViewerObject::addChild(LLViewerObject *childp)
{
- BOOL result = TRUE;
-
for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i)
{
if (*i == childp)
@@ -522,18 +551,9 @@ void LLViewerObject::addChild(LLViewerObject *childp)
childp->mbCanSelect = mbCanSelect;
}
- childp->setParent(this);
- mChildList.push_back(childp);
-
- if (!result)
+ if(childp->setParent(this))
{
- llwarns << "Failed to attach child " << childp->getID() << " to object " << getID() << llendl;
- removeChild(childp);
- if (mJointInfo)
- {
- delete mJointInfo;
- mJointInfo = NULL;
- }
+ mChildList.push_back(childp);
}
}
@@ -549,7 +569,11 @@ void LLViewerObject::removeChild(LLViewerObject *childp)
}
mChildList.erase(i);
- childp->setParent(NULL);
+
+ if(childp->getParent() == this)
+ {
+ childp->setParent(NULL);
+ }
break;
}
}
@@ -562,9 +586,9 @@ void LLViewerObject::removeChild(LLViewerObject *childp)
}
}
-void LLViewerObject::addThisAndAllChildren(LLDynamicArray<LLViewerObject*>& objects)
+void LLViewerObject::addThisAndAllChildren(std::vector<LLViewerObject*>& objects)
{
- objects.put(this);
+ objects.push_back(this);
for (child_list_t::iterator iter = mChildList.begin();
iter != mChildList.end(); iter++)
{
@@ -576,9 +600,9 @@ void LLViewerObject::addThisAndAllChildren(LLDynamicArray<LLViewerObject*>& obje
}
}
-void LLViewerObject::addThisAndNonJointChildren(LLDynamicArray<LLViewerObject*>& objects)
+void LLViewerObject::addThisAndNonJointChildren(std::vector<LLViewerObject*>& objects)
{
- objects.put(this);
+ objects.push_back(this);
// don't add any attachments when temporarily selecting avatar
if (isAvatar())
{
@@ -631,14 +655,17 @@ BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp)
return FALSE;
}
+ BOOL ret = mDrawable->mXform.setParent(parentp ? &parentp->mXform : NULL);
+ if(!ret)
+ {
+ return FALSE ;
+ }
LLDrawable* old_parent = mDrawable->mParent;
-
mDrawable->mParent = parentp;
-
- BOOL ret = mDrawable->mXform.setParent(parentp ? &parentp->mXform : NULL);
+
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
- if( old_parent != parentp &&
- old_parent || (parentp && parentp->isActive()))
+ if( (old_parent != parentp && old_parent)
+ || (parentp && parentp->isActive()))
{
// *TODO we should not be relying on setDrawable parent to call markMoved
gPipeline.markMoved(mDrawable, FALSE);
@@ -677,6 +704,42 @@ void LLViewerObject::hideExtraDisplayItems( BOOL hidden )
}
}
+U32 LLViewerObject::checkMediaURL(const std::string &media_url)
+{
+ U32 retval = (U32)0x0;
+ if (!mMedia && !media_url.empty())
+ {
+ retval |= MEDIA_URL_ADDED;
+ mMedia = new LLViewerObjectMedia;
+ mMedia->mMediaURL = media_url;
+ mMedia->mMediaType = LLViewerObject::MEDIA_SET;
+ mMedia->mPassedWhitelist = FALSE;
+ }
+ else if (mMedia)
+ {
+ if (media_url.empty())
+ {
+ retval |= MEDIA_URL_REMOVED;
+ delete mMedia;
+ mMedia = NULL;
+ }
+ else if (mMedia->mMediaURL != media_url) // <-- This is an optimization. If they are equal don't bother with below's test.
+ {
+ /*if (! (LLTextureEntry::getAgentIDFromMediaVersionString(media_url) == gAgent.getID() &&
+ LLTextureEntry::getVersionFromMediaVersionString(media_url) ==
+ LLTextureEntry::getVersionFromMediaVersionString(mMedia->mMediaURL) + 1))
+ */
+ {
+ // If the media URL is different and WE were not the one who
+ // changed it, mark dirty.
+ retval |= MEDIA_URL_UPDATED;
+ }
+ mMedia->mMediaURL = media_url;
+ mMedia->mPassedWhitelist = FALSE;
+ }
+ }
+ return retval;
+}
U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
void **user_data,
@@ -1022,35 +1085,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
std::string media_url;
mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_MediaURL, media_url, block_num);
- //if (!media_url.empty())
- //{
- // llinfos << "WEBONPRIM media_url " << media_url << llendl;
- //}
- if (!mMedia && !media_url.empty())
- {
- retval |= MEDIA_URL_ADDED;
- mMedia = new LLViewerObjectMedia;
- mMedia->mMediaURL = media_url;
- mMedia->mMediaType = LLViewerObject::MEDIA_TYPE_WEB_PAGE;
- mMedia->mPassedWhitelist = FALSE;
- }
- else if (mMedia)
- {
- if (media_url.empty())
- {
- retval |= MEDIA_URL_REMOVED;
- delete mMedia;
- mMedia = NULL;
- }
- else if (mMedia->mMediaURL != media_url)
- {
- // We just added or changed a web page.
- retval |= MEDIA_URL_UPDATED;
- mMedia->mMediaURL = media_url;
- mMedia->mPassedWhitelist = FALSE;
- }
- }
-
+ retval |= checkMediaURL(media_url);
+
//
// Unpack particle system data
//
@@ -1433,31 +1469,12 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
mText = NULL;
}
+ std::string media_url;
if (value & 0x200)
{
- std::string media_url;
dp->unpackString(media_url, "MediaURL");
- if (!mMedia)
- {
- retval |= MEDIA_URL_ADDED;
- mMedia = new LLViewerObjectMedia;
- mMedia->mMediaURL = media_url;
- mMedia->mMediaType = LLViewerObject::MEDIA_TYPE_WEB_PAGE;
- mMedia->mPassedWhitelist = FALSE;
- }
- else if (mMedia->mMediaURL != media_url)
- {
- retval |= MEDIA_URL_UPDATED;
- mMedia->mMediaURL = media_url;
- mMedia->mPassedWhitelist = FALSE;
- }
- }
- else if (mMedia)
- {
- retval |= MEDIA_URL_REMOVED;
- delete mMedia;
- mMedia = NULL;
}
+ retval |= checkMediaURL(media_url);
//
// Unpack particle system data
@@ -2461,7 +2478,7 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
LLPointer<LLInventoryObject> obj;
obj = new LLInventoryObject(object->mID, LLUUID::null,
LLAssetType::AT_CATEGORY,
- std::string("Contents"));
+ LLTrans::getString("ViewerObjectContents").c_str());
object->mInventory->push_front(obj);
object->doInventoryCallback();
delete ft;
@@ -2528,6 +2545,7 @@ void LLViewerObject::loadTaskInvFile(const std::string& filename)
{
LLPointer<LLInventoryObject> inv = new LLInventoryObject;
inv->importLegacyStream(ifs);
+ inv->rename(LLTrans::getString("ViewerObjectContents").c_str());
mInventory->push_front(inv);
}
else
@@ -2574,7 +2592,7 @@ void LLViewerObject::doInventoryCallback()
void LLViewerObject::removeInventory(const LLUUID& item_id)
{
// close any associated floater properties
- LLFloaterProperties::closeByID(item_id, mID);
+ LLFloaterReg::hideInstance("properties", item_id);
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_RemoveTaskInventory);
@@ -2587,11 +2605,6 @@ void LLViewerObject::removeInventory(const LLUUID& item_id)
msg->sendReliable(mRegionp->getHost());
deleteInventoryItem(item_id);
++mInventorySerialNum;
-
- // The viewer object should not refresh UI since this is a utility
- // function. The UI functionality that called this method should
- // refresh the views if necessary.
- //gBuildView->refresh();
}
void LLViewerObject::updateInventory(
@@ -2748,28 +2761,29 @@ void LLViewerObject::setPixelAreaAndAngle(LLAgent &agent)
F32 mid_scale = getMidScale();
F32 min_scale = getMinScale();
- // IW: esitmate - when close to large objects, computing range based on distance from center is no good
+ // IW: estimate - when close to large objects, computing range based on distance from center is no good
// to try to get a min distance from face, subtract min_scale/2 from the range.
// This means we'll load too much detail sometimes, but that's better than not enough
// I don't think there's a better way to do this without calculating distance per-poly
F32 range = sqrt(dx*dx + dy*dy + dz*dz) - min_scale/2;
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
if (range < 0.001f || isHUDAttachment()) // range == zero
{
mAppAngle = 180.f;
- mPixelArea = (F32)LLViewerCamera::getInstance()->getScreenPixelArea();
+ mPixelArea = (F32)camera->getScreenPixelArea();
}
else
{
mAppAngle = (F32) atan2( max_scale, range) * RAD_TO_DEG;
- F32 pixels_per_meter = LLViewerCamera::getInstance()->getPixelMeterRatio() / range;
+ F32 pixels_per_meter = camera->getPixelMeterRatio() / range;
mPixelArea = (pixels_per_meter * max_scale) * (pixels_per_meter * mid_scale);
- if (mPixelArea > LLViewerCamera::getInstance()->getScreenPixelArea())
+ if (mPixelArea > camera->getScreenPixelArea())
{
mAppAngle = 180.f;
- mPixelArea = (F32)LLViewerCamera::getInstance()->getScreenPixelArea();
+ mPixelArea = (F32)camera->getScreenPixelArea();
}
}
}
@@ -2784,6 +2798,11 @@ BOOL LLViewerObject::updateGeometry(LLDrawable *drawable)
return TRUE;
}
+void LLViewerObject::updateGL()
+{
+
+}
+
void LLViewerObject::updateFaceSize(S32 idx)
{
@@ -2888,7 +2907,7 @@ F32 LLViewerObject::getMidScale() const
}
-void LLViewerObject::updateTextures(LLAgent &agent)
+void LLViewerObject::updateTextures()
{
}
@@ -2903,14 +2922,14 @@ void LLViewerObject::boostTexturePriority(BOOL boost_children /* = TRUE */)
S32 tex_count = getNumTEs();
for (i = 0; i < tex_count; i++)
{
- getTEImage(i)->setBoostLevel(LLViewerImage::BOOST_SELECTED);
+ getTEImage(i)->setBoostLevel(LLViewerTexture::BOOST_SELECTED);
}
if (isSculpted())
{
LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
LLUUID sculpt_id = sculpt_params->getSculptTexture();
- gImageList.getImage(sculpt_id)->setBoostLevel(LLViewerImage::BOOST_SELECTED);
+ LLViewerTextureManager::getFetchedTexture(sculpt_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLViewerTexture::BOOST_SELECTED);
}
if (boost_children)
@@ -3448,7 +3467,7 @@ U8 LLViewerObject::getMediaType() const
}
else
{
- return LLViewerObject::MEDIA_TYPE_NONE;
+ return LLViewerObject::MEDIA_NONE;
}
}
@@ -3456,7 +3475,7 @@ void LLViewerObject::setMediaType(U8 media_type)
{
if (!mMedia)
{
- // JAMESDEBUG TODO what if we don't have a media pointer?
+ // TODO what if we don't have a media pointer?
}
else if (mMedia->mMediaType != media_type)
{
@@ -3538,8 +3557,8 @@ void LLViewerObject::setNumTEs(const U8 num_tes)
{
if (num_tes)
{
- LLPointer<LLViewerImage> *new_images;
- new_images = new LLPointer<LLViewerImage>[num_tes];
+ LLPointer<LLViewerTexture> *new_images;
+ new_images = new LLPointer<LLViewerTexture>[num_tes];
for (i = 0; i < num_tes; i++)
{
if (i < getNumTEs())
@@ -3658,7 +3677,7 @@ void LLViewerObject::sendTEUpdate() const
msg->addString("MediaURL", NULL);
}
- // JAMESDEBUG TODO send media type
+ // TODO send media type
packTEMessage(msg);
@@ -3669,15 +3688,15 @@ void LLViewerObject::sendTEUpdate() const
void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry)
{
LLPrimitive::setTE(te, texture_entry);
-// JAMESDEBUG This doesn't work, don't get any textures.
+// This doesn't work, don't get any textures.
// if (mDrawable.notNull() && mDrawable->isVisible())
// {
const LLUUID& image_id = getTE(te)->getID();
- mTEImages[te] = gImageList.getImage(image_id);
+ mTEImages[te] = LLViewerTextureManager::getFetchedTexture(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
// }
}
-void LLViewerObject::setTEImage(const U8 te, LLViewerImage *imagep)
+void LLViewerObject::setTEImage(const U8 te, LLViewerTexture *imagep)
{
if (mTEImages[te] != imagep)
{
@@ -3699,7 +3718,7 @@ S32 LLViewerObject::setTETextureCore(const U8 te, const LLUUID& uuid, LLHost hos
uuid == LLUUID::null)
{
retval = LLPrimitive::setTETexture(te, uuid);
- mTEImages[te] = gImageList.getImageFromHost(uuid, host);
+ mTEImages[te] = LLViewerTextureManager::getFetchedTexture(uuid, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host);
setChanged(TEXTURE);
if (mDrawable.notNull())
{
@@ -3710,6 +3729,15 @@ S32 LLViewerObject::setTETextureCore(const U8 te, const LLUUID& uuid, LLHost hos
}
+void LLViewerObject::changeTEImage(S32 index, LLViewerTexture* new_image)
+{
+ if(index < 0 || index >= getNumTEs())
+ {
+ return ;
+ }
+ mTEImages[index] = new_image ;
+}
+
S32 LLViewerObject::setTETexture(const U8 te, const LLUUID& uuid)
{
// Invalid host == get from the agent's sim
@@ -3733,7 +3761,6 @@ S32 LLViewerObject::setTEColor(const U8 te, const LLColor4& color)
else if (color != tep->getColor())
{
retval = LLPrimitive::setTEColor(te, color);
- //setChanged(TEXTURE);
if (mDrawable.notNull() && retval)
{
// These should only happen on updates which are not the initial update.
@@ -3780,6 +3807,22 @@ S32 LLViewerObject::setTETexGen(const U8 te, const U8 texgen)
return retval;
}
+S32 LLViewerObject::setTEMediaTexGen(const U8 te, const U8 media)
+{
+ S32 retval = 0;
+ const LLTextureEntry *tep = getTE(te);
+ if (!tep)
+ {
+ llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl;
+ }
+ else if (media != tep->getMediaTexGen())
+ {
+ retval = LLPrimitive::setTEMediaTexGen(te, media);
+ setChanged(TEXTURE);
+ }
+ return retval;
+}
+
S32 LLViewerObject::setTEShiny(const U8 te, const U8 shiny)
{
S32 retval = 0;
@@ -3819,7 +3862,7 @@ S32 LLViewerObject::setTEFullbright(const U8 te, const U8 fullbright)
S32 LLViewerObject::setTEMediaFlags(const U8 te, const U8 media_flags)
{
- // JAMESDEBUG this might need work for media type
+ // this might need work for media type
S32 retval = 0;
const LLTextureEntry *tep = getTE(te);
if (!tep)
@@ -3939,20 +3982,20 @@ S32 LLViewerObject::setTERotation(const U8 te, const F32 r)
}
-LLViewerImage *LLViewerObject::getTEImage(const U8 face) const
+LLViewerTexture *LLViewerObject::getTEImage(const U8 face) const
{
// llassert(mTEImages);
if (face < getNumTEs())
{
- LLViewerImage* image = mTEImages[face];
+ LLViewerTexture* image = mTEImages[face];
if (image)
{
return image;
}
else
{
- return (LLViewerImage*)((LLImageGL*)LLViewerImage::sDefaultImagep);
+ return (LLViewerTexture*)(LLViewerFetchedTexture::sDefaultImagep);
}
}
@@ -4073,7 +4116,7 @@ void LLViewerObject::setDebugText(const std::string &utf8text)
updateText();
}
-void LLViewerObject::setIcon(LLViewerImage* icon_image)
+void LLViewerObject::setIcon(LLViewerTexture* icon_image)
{
if (!mIcon)
{
@@ -4142,6 +4185,11 @@ void LLViewerObject::updateText()
}
}
+LLVOAvatar* LLViewerObject::asAvatar()
+{
+ return NULL;
+}
+
BOOL LLViewerObject::isParticleSource() const
{
return !mPartSourcep.isNull() && !mPartSourcep->isDead();
@@ -4163,14 +4211,14 @@ void LLViewerObject::setParticleSource(const LLPartSysData& particle_parameters,
if (mPartSourcep->getImage()->getID() != mPartSourcep->mPartSysData.mPartImageID)
{
- LLViewerImage* image;
+ LLViewerTexture* image;
if (mPartSourcep->mPartSysData.mPartImageID == LLUUID::null)
{
- image = gImageList.getImageFromFile("pixiesmall.tga");
+ image = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.tga");
}
else
{
- image = gImageList.getImage(mPartSourcep->mPartSysData.mPartImageID);
+ image = LLViewerTextureManager::getFetchedTexture(mPartSourcep->mPartSysData.mPartImageID);
}
mPartSourcep->setImage(image);
}
@@ -4212,14 +4260,14 @@ void LLViewerObject::unpackParticleSource(const S32 block_num, const LLUUID& own
{
if (mPartSourcep->getImage()->getID() != mPartSourcep->mPartSysData.mPartImageID)
{
- LLViewerImage* image;
+ LLViewerTexture* image;
if (mPartSourcep->mPartSysData.mPartImageID == LLUUID::null)
{
- image = gImageList.getImageFromFile("pixiesmall.j2c");
+ image = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
}
else
{
- image = gImageList.getImage(mPartSourcep->mPartSysData.mPartImageID);
+ image = LLViewerTextureManager::getFetchedTexture(mPartSourcep->mPartSysData.mPartImageID);
}
mPartSourcep->setImage(image);
}
@@ -4259,14 +4307,14 @@ void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_
{
if (mPartSourcep->getImage()->getID() != mPartSourcep->mPartSysData.mPartImageID)
{
- LLViewerImage* image;
+ LLViewerTexture* image;
if (mPartSourcep->mPartSysData.mPartImageID == LLUUID::null)
{
- image = gImageList.getImageFromFile("pixiesmall.j2c");
+ image = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
}
else
{
- image = gImageList.getImage(mPartSourcep->mPartSysData.mPartImageID);
+ image = LLViewerTextureManager::getFetchedTexture(mPartSourcep->mPartSysData.mPartImageID);
}
mPartSourcep->setImage(image);
}
@@ -4448,7 +4496,11 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para
new_block = new LLSculptParams();
break;
}
-
+ case LLNetworkData::PARAMS_LIGHT_IMAGE:
+ {
+ new_block = new LLLightImageParams();
+ break;
+ }
default:
{
llinfos << "Unknown param type." << llendl;
@@ -4539,7 +4591,7 @@ bool LLViewerObject::setParameterEntry(U16 param_type, const LLNetworkData& new_
bool LLViewerObject::setParameterEntryInUse(U16 param_type, BOOL in_use, bool local_origin)
{
ExtraParameter* param = getExtraParameterEntryCreate(param_type);
- if (param->in_use != in_use)
+ if (param && param->in_use != in_use)
{
param->in_use = in_use;
parameterChanged(param_type, param->data, in_use, local_origin);
@@ -4952,7 +5004,7 @@ U32 LLViewerObject::getPartitionType() const
return LLViewerRegion::PARTITION_NONE;
}
-void LLViewerObject::dirtySpatialGroup() const
+void LLViewerObject::dirtySpatialGroup(BOOL priority) const
{
if (mDrawable)
{
@@ -4960,6 +5012,7 @@ void LLViewerObject::dirtySpatialGroup() const
if (group)
{
group->dirtyGeom();
+ gPipeline.markRebuild(group, priority);
}
}
}
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 16a3b98d12..266c40d493 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -40,7 +40,7 @@
#include "llhudtext.h"
#include "llhudicon.h"
#include "llinventory.h"
-#include "llmemory.h"
+#include "llrefcount.h"
#include "llmemtype.h"
#include "llprimitive.h"
#include "lluuid.h"
@@ -64,16 +64,18 @@ class LLWorld;
class LLNameValue;
class LLNetMap;
class LLMessageSystem;
+class LLPartSysData;
class LLPrimitive;
class LLPipeline;
class LLTextureEntry;
-class LLViewerImage;
+class LLViewerTexture;
class LLViewerInventoryItem;
class LLViewerObject;
class LLViewerPartSourceScript;
class LLViewerRegion;
class LLViewerObjectMedia;
class LLVOInventoryListener;
+class LLVOAvatar;
typedef enum e_object_update_type
{
@@ -116,7 +118,7 @@ public:
//============================================================================
-class LLViewerObject : public LLPrimitive, public LLRefCount
+class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate
{
protected:
~LLViewerObject(); // use unref()
@@ -143,6 +145,8 @@ public:
BOOL isOrphaned() const { return mOrphaned; }
BOOL isParticleSource() const;
+ virtual LLVOAvatar* asAvatar();
+
static void initVOClasses();
static void cleanupVOClasses();
@@ -154,10 +158,16 @@ public:
virtual BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);
// Types of media we can associate
- enum { MEDIA_TYPE_NONE = 0, MEDIA_TYPE_WEB_PAGE = 1 };
+ enum { MEDIA_NONE = 0, MEDIA_SET = 1 };
// Return codes for processUpdateMessage
- enum { MEDIA_URL_REMOVED = 0x1, MEDIA_URL_ADDED = 0x2, MEDIA_URL_UPDATED = 0x4, INVALID_UPDATE = 0x80000000 };
+ enum {
+ MEDIA_URL_REMOVED = 0x1,
+ MEDIA_URL_ADDED = 0x2,
+ MEDIA_URL_UPDATED = 0x4,
+ MEDIA_FLAGS_CHANGED = 0x8,
+ INVALID_UPDATE = 0x80000000
+ };
virtual U32 processUpdateMessage(LLMessageSystem *mesgsys,
void **user_data,
@@ -189,11 +199,12 @@ public:
S32 getNumFaces() const { return mNumFaces; }
// Graphical stuff for objects - maybe broken out into render class later?
- virtual void updateTextures(LLAgent &agent);
+ virtual void updateTextures();
virtual void boostTexturePriority(BOOL boost_children = TRUE); // When you just want to boost priority of this object
virtual LLDrawable* createDrawable(LLPipeline *pipeline);
virtual BOOL updateGeometry(LLDrawable *drawable);
+ virtual void updateGL();
virtual void updateFaceSize(S32 idx);
virtual BOOL updateLOD();
virtual BOOL setDrawableParent(LLDrawable* parentp);
@@ -218,6 +229,7 @@ public:
virtual BOOL isFlexible() const { return FALSE; }
virtual BOOL isSculpted() const { return FALSE; }
+ virtual BOOL hasLightTexture() const { return FALSE; }
// This method returns true if the object is over land owned by
// the agent.
@@ -236,13 +248,13 @@ public:
BOOL isProbablyModifiable() const;
*/
- virtual void setParent(LLViewerObject* parent);
+ virtual BOOL setParent(LLViewerObject* parent);
virtual void addChild(LLViewerObject *childp);
virtual void removeChild(LLViewerObject *childp);
const_child_list_t& getChildren() const { return mChildList; }
S32 numChildren() const { return mChildList.size(); }
- void addThisAndAllChildren(LLDynamicArray<LLViewerObject*>& objects);
- void addThisAndNonJointChildren(LLDynamicArray<LLViewerObject*>& objects);
+ void addThisAndAllChildren(std::vector<LLViewerObject*>& objects);
+ void addThisAndNonJointChildren(std::vector<LLViewerObject*>& objects);
BOOL isChild(LLViewerObject *childp) const;
BOOL isSeat() const;
@@ -305,13 +317,15 @@ public:
/*virtual*/ S32 setTERotation(const U8 te, const F32 r);
/*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump );
/*virtual*/ S32 setTETexGen(const U8 te, const U8 texgen );
+ /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media ); // *FIXME: this confusingly acts upon a superset of setTETexGen's flags without absorbing its semantics
/*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny );
/*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright );
/*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags );
/*virtual*/ S32 setTEGlow(const U8 te, const F32 glow);
/*virtual*/ BOOL setMaterial(const U8 material);
- virtual void setTEImage(const U8 te, LLViewerImage *imagep); // Not derived from LLPrimitive
- LLViewerImage *getTEImage(const U8 te) const;
+ virtual void setTEImage(const U8 te, LLViewerTexture *imagep); // Not derived from LLPrimitive
+ void changeTEImage(S32 index, LLViewerTexture* new_image) ;
+ LLViewerTexture *getTEImage(const U8 te) const;
void fitFaceTexture(const U8 face);
void sendTEUpdate() const; // Sends packed representation of all texture entry information
@@ -352,7 +366,7 @@ public:
void setCanSelect(BOOL canSelect);
void setDebugText(const std::string &utf8text);
- void setIcon(LLViewerImage* icon_image);
+ void setIcon(LLViewerTexture* icon_image);
void clearIcon();
void markForUpdate(BOOL priority);
@@ -443,6 +457,7 @@ public:
inline BOOL flagAnimSource() const { return ((mFlags & FLAGS_ANIM_SOURCE) != 0); }
inline BOOL flagCameraSource() const { return ((mFlags & FLAGS_CAMERA_SOURCE) != 0); }
inline BOOL flagCameraDecoupled() const { return ((mFlags & FLAGS_CAMERA_DECOUPLED) != 0); }
+ inline BOOL flagObjectMove() const { return ((mFlags & FLAGS_OBJECT_MOVE) != 0); }
bool getIncludeInSearch() const;
void setIncludeInSearch(bool include_in_search);
@@ -467,7 +482,7 @@ public:
virtual S32 getLOD() const { return 3; }
virtual U32 getPartitionType() const;
- virtual void dirtySpatialGroup() const;
+ virtual void dirtySpatialGroup(BOOL priority = FALSE) const;
virtual void dirtyMesh();
virtual LLNetworkData* getParameterEntry(U16 param_type) const;
@@ -496,6 +511,10 @@ private:
ExtraParameter* getExtraParameterEntry(U16 param_type) const;
ExtraParameter* getExtraParameterEntryCreate(U16 param_type);
bool unpackParameterEntry(U16 param_type, LLDataPacker *dp);
+
+ // This function checks to see if the given media URL has changed its version
+ // and the update wasn't due to this agent's last action.
+ U32 checkMediaURL(const std::string &media_url);
public:
//
@@ -525,7 +544,7 @@ public:
// Last total CRC received from sim, used for caching
U32 mTotalCRC;
- LLPointer<LLViewerImage> *mTEImages;
+ LLPointer<LLViewerTexture> *mTEImages;
// Selection, picking and rendering variables
U32 mGLName; // GL "name" used by selection code
@@ -658,6 +677,12 @@ protected:
private:
static S32 sNumObjects;
+
+public:
+ const LLUUID &getItemID() const { return mAttachmentItemID; }
+ void setItemID(const LLUUID &id) { mAttachmentItemID = id; }
+private:
+ LLUUID mAttachmentItemID; // ItemID when item is in user inventory.
};
///////////////////
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index e0741e7233..96828ee1b6 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -38,6 +38,7 @@
#include "timing.h"
#include "llfasttimer.h"
#include "llrender.h"
+#include "llwindow.h" // decBusyCount()
#include "llviewercontrol.h"
#include "llface.h"
@@ -48,7 +49,7 @@
#include "llagent.h"
#include "pipeline.h"
#include "llspatialpartition.h"
-#include "llhoverview.h"
+#include "lltooltip.h"
#include "llworld.h"
#include "llstring.h"
#include "llhudtext.h"
@@ -60,11 +61,12 @@
#include "llresmgr.h"
#include "llviewerregion.h"
#include "llviewerstats.h"
+#include "llvoavatarself.h"
#include "lltoolmgr.h"
#include "lltoolpie.h"
#include "llkeyboard.h"
#include "u64.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "lldatapacker.h"
#ifdef LL_STANDALONE
#include <zlib.h>
@@ -172,11 +174,28 @@ BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject &object)
U32 port = region_host.getPort();
U64 ipport = (((U64)ip) << 32) | (U64)port;
U32 index = sIPAndPortToIndex[ipport];
-
+
+ // llinfos << "Removing object from table, local ID " << local_id << ", ip " << ip << ":" << port << llendl;
+
U64 indexid = (((U64)index) << 32) | (U64)local_id;
- return sIndexAndLocalIDToUUID.erase(indexid) > 0 ? TRUE : FALSE;
+
+ std::map<U64, LLUUID>::iterator iter = sIndexAndLocalIDToUUID.find(indexid);
+ if (iter == sIndexAndLocalIDToUUID.end())
+ {
+ return FALSE;
+ }
+
+ // Found existing entry
+ if (iter->second == object.getID())
+ { // Full UUIDs match, so remove the entry
+ sIndexAndLocalIDToUUID.erase(iter);
+ return TRUE;
+ }
+ // UUIDs did not match - this would zap a valid entry, so don't erase it
+ //llinfos << "Tried to erase entry where id in table ("
+ // << iter->second << ") did not match object " << object.getID() << llendl;
}
-
+
return FALSE ;
}
@@ -198,6 +217,9 @@ void LLViewerObjectList::setUUIDAndLocal(const LLUUID &id,
U64 indexid = (((U64)index) << 32) | (U64)local_id;
sIndexAndLocalIDToUUID[indexid] = id;
+
+ //llinfos << "Adding object to table, full ID " << id
+ // << ", local ID " << local_id << ", ip " << ip << ":" << port << llendl;
}
S32 gFullObjectUpdates = 0;
@@ -210,6 +232,7 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp,
LLDataPacker* dpp,
BOOL just_created)
{
+ LLMemType mt(LLMemType::MTYPE_OBJECT_PROCESS_UPDATE_CORE);
LLMessageSystem* msg = gMessageSystem;
// ignore returned flags
@@ -243,24 +266,27 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp,
{
if ( LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance() )
{
- //llinfos << "DEBUG selecting " << objectp->mID << " "
- // << objectp->mLocalID << llendl;
+ // llinfos << "DEBUG selecting " << objectp->mID << " "
+ // << objectp->mLocalID << llendl;
LLSelectMgr::getInstance()->selectObjectAndFamily(objectp);
dialog_refresh_all();
}
objectp->mCreateSelected = false;
gViewerWindow->getWindow()->decBusyCount();
- gViewerWindow->getWindow()->setCursor( UI_CURSOR_ARROW );
+ gViewerWindow->setCursor( UI_CURSOR_ARROW );
}
}
+static LLFastTimer::DeclareTimer FTM_PROCESS_OBJECTS("Process Objects");
+
void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
void **user_data,
const EObjectUpdateType update_type,
bool cached, bool compressed)
{
- LLFastTimer t(LLFastTimer::FTM_PROCESS_OBJECTS);
+ LLMemType mt(LLMemType::MTYPE_OBJECT_PROCESS_UPDATE);
+ LLFastTimer t(FTM_PROCESS_OBJECTS);
LLVector3d camera_global = gAgent.getCameraPositionGlobal();
LLViewerObject *objectp;
@@ -288,7 +314,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
{
size = mesgsys->getReceiveSize();
}
-// llinfos << "Received terse " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl;
+ // llinfos << "Received terse " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl;
}
else
{
@@ -302,7 +328,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
size = mesgsys->getReceiveSize();
}
-// llinfos << "Received " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl;
+ // llinfos << "Received " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl;
gFullObjectUpdates += num_objects;
}
@@ -312,7 +338,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
if (!regionp)
{
- llwarns << "Object update from unknown region!" << llendl;
+ llwarns << "Object update from unknown region! " << region_handle << llendl;
return;
}
@@ -351,7 +377,6 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
U8 compbuffer[2048];
S32 uncompressed_length = 2048;
S32 compressed_length;
-
compressed_dp.reset();
U32 flags = 0;
@@ -392,7 +417,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
gMessageSystem->getSenderPort());
if (fullid.isNull())
{
- //llwarns << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << llendl;
+ // llwarns << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << ":" << gMessageSystem->getSenderPort() << llendl;
mNumUnknownUpdates++;
}
}
@@ -406,7 +431,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
gMessageSystem->getSenderPort());
if (fullid.isNull())
{
- //llwarns << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << llendl;
+ // llwarns << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << llendl;
mNumUnknownUpdates++;
}
}
@@ -414,19 +439,43 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
{
mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i);
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);
- // llinfos << "Full Update, obj " << local_id << ", global ID" << fullid << "from " << mesgsys->getSender() << llendl;
+ // llinfos << "Full Update, obj " << local_id << ", global ID" << fullid << "from " << mesgsys->getSender() << llendl;
}
objectp = findObject(fullid);
// This looks like it will break if the local_id of the object doesn't change
// upon boundary crossing, but we check for region id matching later...
- if (objectp && (objectp->mLocalID != local_id))
+ // Reset object local id and region pointer if things have changed
+ if (objectp &&
+ ((objectp->mLocalID != local_id) ||
+ (objectp->getRegion() != regionp)))
{
+ //if (objectp->getRegion())
+ //{
+ // llinfos << "Local ID change: Removing object from table, local ID " << objectp->mLocalID
+ // << ", id from message " << local_id << ", from "
+ // << LLHost(objectp->getRegion()->getHost().getAddress(), objectp->getRegion()->getHost().getPort())
+ // << ", full id " << fullid
+ // << ", objects id " << objectp->getID()
+ // << ", regionp " << (U32) regionp << ", object region " << (U32) objectp->getRegion()
+ // << llendl;
+ //}
removeFromLocalIDTable(*objectp);
setUUIDAndLocal(fullid,
local_id,
gMessageSystem->getSenderIP(),
gMessageSystem->getSenderPort());
+
+ if (objectp->mLocalID != local_id)
+ { // Update local ID in object with the one sent from the region
+ objectp->mLocalID = local_id;
+ }
+
+ if (objectp->getRegion() != regionp)
+ { // Object changed region, so update it
+ objectp->setRegion(regionp);
+ objectp->updateRegion(regionp); // for LLVOAvatar
+ }
}
if (!objectp)
@@ -435,7 +484,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
{
if (update_type == OUT_TERSE_IMPROVED)
{
- // llinfos << "terse update for an unknown object:" << fullid << llendl;
+ // llinfos << "terse update for an unknown object:" << fullid << llendl;
continue;
}
}
@@ -446,7 +495,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
{
if (update_type != OUT_FULL)
{
-// llinfos << "terse update for an unknown object:" << fullid << llendl;
+ // llinfos << "terse update for an unknown object:" << fullid << llendl;
continue;
}
@@ -456,7 +505,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
if (mDeadObjects.find(fullid) != mDeadObjects.end())
{
mNumDeadObjectUpdates++;
- //llinfos << "update for a dead object:" << fullid << llendl;
+ // llinfos << "update for a dead object:" << fullid << llendl;
continue;
}
#endif
@@ -469,20 +518,6 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
justCreated = TRUE;
mNumNewObjects++;
}
- else
- {
- if (objectp->getRegion() != regionp)
- {
- // Object has changed region! Update lookup tables, set region pointer.
- removeFromLocalIDTable(*objectp);
- setUUIDAndLocal(fullid,
- local_id,
- gMessageSystem->getSenderIP(),
- gMessageSystem->getSenderPort());
- objectp->setRegion(regionp);
- }
- objectp->updateRegion(regionp); // for LLVOAvatar
- }
if (objectp->isDead())
@@ -554,7 +589,7 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
{
num_updates = mObjects.count() - mCurLazyUpdateIndex;
max_value = mObjects.count();
- gImageList.setUpdateStats(TRUE);
+ gTextureList.setUpdateStats(TRUE);
}
else
{
@@ -568,10 +603,14 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
// Slam priorities for textures that we care about (hovered, selected, and focused)
// Hovered
// Assumes only one level deep of parenting
- objectp = gHoverView->getLastHoverObject();
- if (objectp)
+ LLSelectNode* nodep = LLSelectMgr::instance().getHoverNode();
+ if (nodep)
{
- objectp->boostTexturePriority();
+ objectp = nodep->getObject();
+ if (objectp)
+ {
+ objectp->boostTexturePriority();
+ }
}
}
@@ -603,7 +642,7 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
// Update distance & gpw
objectp->setPixelAreaAndAngle(agent); // Also sets the approx. pixel area
- objectp->updateTextures(agent); // Update the image levels of textures for this object.
+ objectp->updateTextures(); // Update the image levels of textures for this object.
}
}
@@ -613,7 +652,7 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
mCurLazyUpdateIndex = 0;
}
- mCurBin = (++mCurBin) % NUM_BINS;
+ mCurBin = (mCurBin + 1) % NUM_BINS;
LLVOAvatar::cullAvatarsByPixelArea();
}
@@ -768,10 +807,10 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
}
*/
- mNumObjectsStat.addValue(mObjects.count());
- mNumActiveObjectsStat.addValue(num_active_objects);
- mNumSizeCulledStat.addValue(mNumSizeCulled);
- mNumVisCulledStat.addValue(mNumVisCulled);
+ LLViewerStats::getInstance()->mNumObjectsStat.addValue(mObjects.count());
+ LLViewerStats::getInstance()->mNumActiveObjectsStat.addValue(num_active_objects);
+ LLViewerStats::getInstance()->mNumSizeCulledStat.addValue(mNumSizeCulled);
+ LLViewerStats::getInstance()->mNumVisCulledStat.addValue(mNumVisCulled);
}
void LLViewerObjectList::clearDebugText()
@@ -798,6 +837,14 @@ void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp)
// Remove from object map so noone can look it up.
mUUIDObjectMap.erase(objectp->mID);
+
+ //if (objectp->getRegion())
+ //{
+ // llinfos << "cleanupReferences removing object from table, local ID " << objectp->mLocalID << ", ip "
+ // << objectp->getRegion()->getHost().getAddress() << ":"
+ // << objectp->getRegion()->getHost().getPort() << llendl;
+ //}
+
removeFromLocalIDTable(*objectp);
if (objectp->onActiveList())
@@ -1016,17 +1063,18 @@ void LLViewerObjectList::shiftObjects(const LLVector3 &offset)
void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap)
{
- LLColor4 above_water_color = gColors.getColor( "NetMapOtherOwnAboveWater" );
- LLColor4 below_water_color = gColors.getColor( "NetMapOtherOwnBelowWater" );
+ LLColor4 above_water_color = LLUIColorTable::instance().getColor( "NetMapOtherOwnAboveWater" );
+ LLColor4 below_water_color = LLUIColorTable::instance().getColor( "NetMapOtherOwnBelowWater" );
LLColor4 you_own_above_water_color =
- gColors.getColor( "NetMapYouOwnAboveWater" );
+ LLUIColorTable::instance().getColor( "NetMapYouOwnAboveWater" );
LLColor4 you_own_below_water_color =
- gColors.getColor( "NetMapYouOwnBelowWater" );
+ LLUIColorTable::instance().getColor( "NetMapYouOwnBelowWater" );
LLColor4 group_own_above_water_color =
- gColors.getColor( "NetMapGroupOwnAboveWater" );
+ LLUIColorTable::instance().getColor( "NetMapGroupOwnAboveWater" );
LLColor4 group_own_below_water_color =
- gColors.getColor( "NetMapGroupOwnBelowWater" );
+ LLUIColorTable::instance().getColor( "NetMapGroupOwnBelowWater" );
+ F32 max_radius = gSavedSettings.getF32("MiniMapPrimMaxRadius");
for (S32 i = 0; i < mMapObjects.count(); i++)
{
@@ -1042,6 +1090,11 @@ void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap)
F32 approx_radius = (scale.mV[VX] + scale.mV[VY]) * 0.5f * 0.5f * 1.3f; // 1.3 is a fudge
+ // Limit the size of megaprims so they don't blot out everything on the minimap.
+ // Attempting to draw very large megaprims also causes client lag.
+ // See DEV-17370 and DEV-29869/SNOW-79 for details.
+ approx_radius = llmin(approx_radius, max_radius);
+
LLColor4U color = above_water_color;
if( objectp->permYouOwner() )
{
@@ -1169,21 +1222,25 @@ void LLViewerObjectList::generatePickList(LLCamera &camera)
iter != avatarp->mAttachmentPoints.end(); )
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachmentp = curiter->second;
- if (attachmentp->getIsHUDAttachment())
+ LLViewerJointAttachment* attachment = curiter->second;
+ if (attachment->getIsHUDAttachment())
{
- LLViewerObject* objectp = attachmentp->getObject();
- if (objectp)
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- mSelectPickList.insert(objectp);
- LLViewerObject::const_child_list_t& child_list = objectp->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
+ if (LLViewerObject* attached_object = (*attachment_iter))
{
- LLViewerObject* childp = *iter;
- if (childp)
+ mSelectPickList.insert(attached_object);
+ LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
+ for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
+ iter != child_list.end(); iter++)
{
- mSelectPickList.insert(childp);
+ LLViewerObject* childp = *iter;
+ if (childp)
+ {
+ mSelectPickList.insert(childp);
+ }
}
}
}
@@ -1300,12 +1357,13 @@ LLViewerObject *LLViewerObjectList::createObjectViewer(const LLPCode pcode, LLVi
}
+static LLFastTimer::DeclareTimer FTM_CREATE_OBJECT("Create Object");
LLViewerObject *LLViewerObjectList::createObject(const LLPCode pcode, LLViewerRegion *regionp,
const LLUUID &uuid, const U32 local_id, const LLHost &sender)
{
LLMemType mt(LLMemType::MTYPE_OBJECT);
- LLFastTimer t(LLFastTimer::FTM_CREATE_OBJECT);
+ LLFastTimer t(FTM_CREATE_OBJECT);
LLUUID fullid;
if (uuid == LLUUID::null)
diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h
index ba31f70c3d..ace5c5038e 100644
--- a/indra/newview/llviewerobjectlist.h
+++ b/indra/newview/llviewerobjectlist.h
@@ -39,11 +39,13 @@
// common includes
#include "llstat.h"
#include "lldarrayptr.h"
+#include "llmap.h" // *TODO: switch to std::map
#include "llstring.h"
// project includes
#include "llviewerobject.h"
+class LLCamera;
class LLNetMap;
class LLDebugBeacon;
@@ -150,19 +152,8 @@ public:
U32 mCurBin; // Current bin we're working on...
- //////////////////////
- //
- // Statistics data
- //
- //
- LLStat mNumObjectsStat;
- LLStat mNumActiveObjectsStat;
- LLStat mNumNewObjectsStat;
- LLStat mNumSizeCulledStat;
- LLStat mNumVisCulledStat;
-
+ // Statistics data (see also LLViewerStats)
S32 mNumNewObjects;
-
S32 mNumSizeCulled;
S32 mNumVisCulled;
diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp
index b98f418d49..c4fc2e5cab 100644
--- a/indra/newview/llviewerparcelmedia.cpp
+++ b/indra/newview/llviewerparcelmedia.cpp
@@ -34,6 +34,7 @@
#include "llviewerparcelmedia.h"
#include "llagent.h"
+#include "llaudioengine.h"
#include "llviewercontrol.h"
#include "llviewermedia.h"
#include "llviewerregion.h"
@@ -41,47 +42,19 @@
#include "llviewerparcelmgr.h"
#include "lluuid.h"
#include "message.h"
+#include "llviewermediafocus.h"
#include "llviewerparcelmediaautoplay.h"
-#include "llviewerwindow.h"
-#include "llfirstuse.h"
+#include "llnotificationsutil.h"
+//#include "llfirstuse.h"
+#include "llpluginclassmedia.h"
+#include "llviewertexture.h"
// Static Variables
S32 LLViewerParcelMedia::sMediaParcelLocalID = 0;
LLUUID LLViewerParcelMedia::sMediaRegionID;
+viewer_media_t LLViewerParcelMedia::sMediaImpl;
-// Local functions
-bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel);
-
-// Move this to its own file.
-// helper class that tries to download a URL from a web site and calls a method
-// on the Panel Land Media and to discover the MIME type
-class LLMimeDiscoveryResponder : public LLHTTPClient::Responder
-{
-public:
- LLMimeDiscoveryResponder( )
- {}
-
-
-
- virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content)
- {
- std::string media_type = content["content-type"].asString();
- std::string::size_type idx1 = media_type.find_first_of(";");
- std::string mime_type = media_type.substr(0, idx1);
- completeAny(status, mime_type);
- }
-
- virtual void error( U32 status, const std::string& reason )
- {
- completeAny(status, "none/none");
- }
-
- void completeAny(U32 status, const std::string& mime_type)
- {
- LLViewerMedia::setMimeType(mime_type);
- }
-};
// static
void LLViewerParcelMedia::initClass()
@@ -92,6 +65,13 @@ void LLViewerParcelMedia::initClass()
LLViewerParcelMediaAutoPlay::initClass();
}
+//static
+void LLViewerParcelMedia::cleanupClass()
+{
+ // This needs to be destroyed before global destructor time.
+ sMediaImpl = NULL;
+}
+
//////////////////////////////////////////////////////////////////////////////////////////
// static
void LLViewerParcelMedia::update(LLParcel* parcel)
@@ -105,6 +85,7 @@ void LLViewerParcelMedia::update(LLParcel* parcel)
{
sMediaRegionID = LLUUID() ;
stop() ;
+ LL_DEBUGS("Media") << "no agent region, bailing out." << LL_ENDL;
return ;
}
@@ -115,64 +96,54 @@ void LLViewerParcelMedia::update(LLParcel* parcel)
LLUUID regionid = gAgent.getRegion()->getRegionID();
if (parcelid != sMediaParcelLocalID || regionid != sMediaRegionID)
{
+ LL_DEBUGS("Media") << "New parcel, parcel id = " << parcelid << ", region id = " << regionid << LL_ENDL;
sMediaParcelLocalID = parcelid;
sMediaRegionID = regionid;
new_parcel = true;
}
std::string mediaUrl = std::string ( parcel->getMediaURL () );
+ std::string mediaCurrentUrl = std::string( parcel->getMediaCurrentURL());
+
+ // First use warning
+ if( (!mediaUrl.empty() ||
+ !parcel->getMusicURL().empty())
+ && LLViewerMedia::needsMediaFirstRun())
+ {
+ LLViewerMedia::displayMediaFirstRun();
+ return;
+ }
+
+ // if we have a current (link sharing) url, use it instead
+ if (mediaCurrentUrl != "" && parcel->getMediaType() == "text/html")
+ {
+ mediaUrl = mediaCurrentUrl;
+ }
+
LLStringUtil::trim(mediaUrl);
+
+ // If no parcel media is playing, nothing left to do
+ if(sMediaImpl.isNull())
- // has something changed?
- if ( ( LLViewerMedia::getMediaURL() != mediaUrl )
- || ( LLViewerMedia::getMediaTextureID() != parcel->getMediaID () ) )
{
- bool video_was_playing = FALSE;
- bool same_media_id = LLViewerMedia::getMediaTextureID() == parcel->getMediaID ();
+ return;
+ }
- if (LLViewerMedia::isMediaPlaying())
+ // Media is playing...has something changed?
+ else if (( sMediaImpl->getMediaURL() != mediaUrl )
+ || ( sMediaImpl->getMediaTextureID() != parcel->getMediaID() )
+ || ( sMediaImpl->getMimeType() != parcel->getMediaType() ))
+ {
+ // Only play if the media types are the same.
+ if(sMediaImpl->getMimeType() == parcel->getMediaType())
{
- video_was_playing = TRUE;
+ play(parcel);
}
- if ( !mediaUrl.empty() && same_media_id && ! new_parcel)
- {
- // Someone has "changed the channel", changing the URL of a video
- // you were already watching. Automatically play provided the texture ID is the same
- if (video_was_playing)
- {
- // Poke the mime type in before calling play.
- // This is necessary because in this instance we are not waiting
- // for the results of a header curl. In order to change the channel
- // a mime type MUST be provided.
- LLViewerMedia::setMimeType(parcel->getMediaType());
- play(parcel);
- }
- }
else
{
stop();
}
-
- // Discover the MIME type
- // Disabled for the time being. Get the mime type from the parcel.
- if(gSavedSettings.getBOOL("AutoMimeDiscovery"))
- {
- LLHTTPClient::getHeaderOnly( mediaUrl, new LLMimeDiscoveryResponder());
- }
- else
- {
- LLViewerMedia::setMimeType(parcel->getMediaType());
- }
-
- // First use warning
- if( gSavedSettings.getWarning("FirstStreamingVideo") )
- {
- LLNotifications::instance().add("ParcelCanPlayMedia", LLSD(), LLSD(),
- boost::bind(callback_play_media, _1, _2, parcel));
-
- }
-
}
}
else
@@ -183,17 +154,17 @@ void LLViewerParcelMedia::update(LLParcel* parcel)
/*
else
{
- // no audio player, do a first use dialog if their is media here
+ // no audio player, do a first use dialog if there is media here
if (parcel)
{
std::string mediaUrl = std::string ( parcel->getMediaURL () );
if (!mediaUrl.empty ())
{
- if (gSavedSettings.getWarning("QuickTimeInstalled"))
+ if (gWarningSettings.getBOOL("QuickTimeInstalled"))
{
- gSavedSettings.setWarning("QuickTimeInstalled", FALSE);
+ gWarningSettings.setBOOL("QuickTimeInstalled", FALSE);
- LLNotifications::instance().add("NoQuickTime" );
+ LLNotificationsUtil::add("NoQuickTime" );
};
}
}
@@ -208,20 +179,63 @@ void LLViewerParcelMedia::play(LLParcel* parcel)
if (!parcel) return;
- if (!gSavedSettings.getBOOL("AudioStreamingVideo"))
+ if (!gSavedSettings.getBOOL("AudioStreamingMedia"))
return;
std::string media_url = parcel->getMediaURL();
+ std::string media_current_url = parcel->getMediaCurrentURL();
std::string mime_type = parcel->getMediaType();
LLUUID placeholder_texture_id = parcel->getMediaID();
U8 media_auto_scale = parcel->getMediaAutoScale();
U8 media_loop = parcel->getMediaLoop();
S32 media_width = parcel->getMediaWidth();
S32 media_height = parcel->getMediaHeight();
- LLViewerMedia::play(media_url, mime_type, placeholder_texture_id,
- media_width, media_height, media_auto_scale,
- media_loop);
- LLFirstUse::useMedia();
+
+ if(sMediaImpl)
+ {
+ // If the url and mime type are the same, call play again
+ if(sMediaImpl->getMediaURL() == media_url
+ && sMediaImpl->getMimeType() == mime_type
+ && sMediaImpl->getMediaTextureID() == placeholder_texture_id)
+ {
+ LL_DEBUGS("Media") << "playing with existing url " << media_url << LL_ENDL;
+
+ sMediaImpl->play();
+ }
+ // Else if the texture id's are the same, navigate and rediscover type
+ // MBW -- This causes other state from the previous parcel (texture size, autoscale, and looping) to get re-used incorrectly.
+ // It's also not really necessary -- just creating a new instance is fine.
+// else if(sMediaImpl->getMediaTextureID() == placeholder_texture_id)
+// {
+// sMediaImpl->navigateTo(media_url, mime_type, true);
+// }
+ else
+ {
+ // Since the texture id is different, we need to generate a new impl
+
+ // Delete the old one first so they don't fight over the texture.
+ sMediaImpl = NULL;
+
+ // A new impl will be created below.
+ }
+ }
+
+ if(!sMediaImpl)
+ {
+ LL_DEBUGS("Media") << "new media impl with mime type " << mime_type << ", url " << media_url << LL_ENDL;
+
+ // There is no media impl, make a new one
+ sMediaImpl = LLViewerMedia::newMediaImpl(
+ placeholder_texture_id,
+ media_width,
+ media_height,
+ media_auto_scale,
+ media_loop);
+ sMediaImpl->setIsParcelMedia(true);
+ sMediaImpl->navigateTo(media_url, mime_type, true);
+ }
+
+ //LLFirstUse::useMedia();
LLViewerParcelMediaAutoPlay::playStarted();
}
@@ -229,21 +243,38 @@ void LLViewerParcelMedia::play(LLParcel* parcel)
// static
void LLViewerParcelMedia::stop()
{
+ if(sMediaImpl.isNull())
+ {
+ return;
+ }
+
+ // We need to remove the media HUD if it is up.
+ LLViewerMediaFocus::getInstance()->clearFocus();
- LLViewerMedia::stop();
+ // This will unload & kill the media instance.
+ sMediaImpl = NULL;
}
// static
void LLViewerParcelMedia::pause()
{
- LLViewerMedia::pause();
+ if(sMediaImpl.isNull())
+ {
+ return;
+ }
+ sMediaImpl->pause();
}
// static
void LLViewerParcelMedia::start()
{
- LLViewerMedia::start();
- LLFirstUse::useMedia();
+ if(sMediaImpl.isNull())
+ {
+ return;
+ }
+ sMediaImpl->start();
+
+ //LLFirstUse::useMedia();
LLViewerParcelMediaAutoPlay::playStarted();
}
@@ -251,14 +282,65 @@ void LLViewerParcelMedia::start()
// static
void LLViewerParcelMedia::seek(F32 time)
{
- LLViewerMedia::seek(time);
+ if(sMediaImpl.isNull())
+ {
+ return;
+ }
+ sMediaImpl->seek(time);
+}
+
+// static
+void LLViewerParcelMedia::focus(bool focus)
+{
+ sMediaImpl->focus(focus);
}
+// static
+LLPluginClassMediaOwner::EMediaStatus LLViewerParcelMedia::getStatus()
+{
+ LLPluginClassMediaOwner::EMediaStatus result = LLPluginClassMediaOwner::MEDIA_NONE;
+
+ if(sMediaImpl.notNull() && sMediaImpl->hasMedia())
+ {
+ result = sMediaImpl->getMediaPlugin()->getStatus();
+ }
+
+ return result;
+}
// static
-LLMediaBase::EStatus LLViewerParcelMedia::getStatus()
+std::string LLViewerParcelMedia::getMimeType()
{
- return LLViewerMedia::getStatus();
+ return sMediaImpl.notNull() ? sMediaImpl->getMimeType() : "none/none";
+}
+
+//static
+std::string LLViewerParcelMedia::getURL()
+{
+ std::string url;
+ if(sMediaImpl.notNull())
+ url = sMediaImpl->getMediaURL();
+
+ if (url.empty())
+ url = LLViewerParcelMgr::getInstance()->getAgentParcel()->getMediaCurrentURL();
+
+ if (url.empty())
+ url = LLViewerParcelMgr::getInstance()->getAgentParcel()->getMediaURL();
+
+ return url;
+}
+
+//static
+std::string LLViewerParcelMedia::getName()
+{
+ if(sMediaImpl.notNull())
+ return sMediaImpl->getName();
+ return "";
+}
+
+viewer_media_t LLViewerParcelMedia::getParcelMedia()
+{
+ return sMediaImpl;
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -298,7 +380,7 @@ void LLViewerParcelMedia::processParcelMediaCommandMessage( LLMessageSystem *msg
if(( command == PARCEL_MEDIA_COMMAND_PLAY ) ||
( command == PARCEL_MEDIA_COMMAND_LOOP ))
{
- if (LLViewerMedia::isMediaPaused())
+ if (getStatus() == LLViewerMediaImpl::MEDIA_PAUSED)
{
start();
}
@@ -318,7 +400,7 @@ void LLViewerParcelMedia::processParcelMediaCommandMessage( LLMessageSystem *msg
if (flags & (1<<PARCEL_MEDIA_COMMAND_TIME))
{
- if(! LLViewerMedia::hasMedia())
+ if(sMediaImpl.isNull())
{
LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
play(parcel);
@@ -382,20 +464,133 @@ void LLViewerParcelMedia::processParcelMediaUpdate( LLMessageSystem *msg, void *
}
}
}
-
-bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel)
+// Static
+/////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerParcelMedia::sendMediaNavigateMessage(const std::string& url)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
- if (option == 0)
+ std::string region_url = gAgent.getRegion()->getCapability("ParcelNavigateMedia");
+ if (!region_url.empty())
{
- gSavedSettings.setBOOL("AudioStreamingVideo", TRUE);
- LLViewerParcelMedia::play(parcel);
+ // send navigate event to sim for link sharing
+ LLSD body;
+ body["agent-id"] = gAgent.getID();
+ body["local-id"] = LLViewerParcelMgr::getInstance()->getAgentParcel()->getLocalID();
+ body["url"] = url;
+ LLHTTPClient::post(region_url, body, new LLHTTPClient::Responder);
}
else
{
- gSavedSettings.setBOOL("AudioStreamingVideo", FALSE);
+ llwarns << "can't get ParcelNavigateMedia capability" << llendl;
}
- gSavedSettings.setWarning("FirstStreamingVideo", FALSE);
- return false;
+
}
+/////////////////////////////////////////////////////////////////////////////////////////
+// inherited from LLViewerMediaObserver
+// virtual
+void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
+{
+ switch(event)
+ {
+ case MEDIA_EVENT_CONTENT_UPDATED:
+ {
+ // LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CONTENT_UPDATED " << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_TIME_DURATION_UPDATED:
+ {
+ // LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_TIME_DURATION_UPDATED, time is " << self->getCurrentTime() << " of " << self->getDuration() << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_SIZE_CHANGED:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_SIZE_CHANGED " << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_CURSOR_CHANGED:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_NAVIGATE_BEGIN:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_BEGIN " << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_NAVIGATE_COMPLETE:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_PROGRESS_UPDATED:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PROGRESS_UPDATED, loading at " << self->getProgressPercent() << "%" << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_STATUS_TEXT_CHANGED:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_STATUS_TEXT_CHANGED, new status text is: " << self->getStatusText() << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_LOCATION_CHANGED:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_LOCATION_CHANGED, new uri is: " << self->getLocation() << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_CLICK_LINK_HREF:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_CLICK_LINK_NOFOLLOW:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is " << self->getClickURL() << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_PLUGIN_FAILED:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED" << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL;
+ };
+ break;
+
+ case MEDIA_EVENT_NAME_CHANGED:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAME_CHANGED" << LL_ENDL;
+ };
+ break;
+ };
+}
+
+// TODO: observer
+/*
+void LLViewerParcelMediaNavigationObserver::onNavigateComplete( const EventType& event_in )
+{
+ std::string url = event_in.getStringValue();
+
+ if (mCurrentURL != url && ! mFromMessage)
+ {
+ LLViewerParcelMedia::sendMediaNavigateMessage(url);
+ }
+
+ mCurrentURL = url;
+ mFromMessage = false;
+
+}
+*/
diff --git a/indra/newview/llviewerparcelmedia.h b/indra/newview/llviewerparcelmedia.h
index 18988704d8..19e1ef78d4 100644
--- a/indra/newview/llviewerparcelmedia.h
+++ b/indra/newview/llviewerparcelmedia.h
@@ -33,18 +33,22 @@
#ifndef LLVIEWERPARCELMEDIA_H
#define LLVIEWERPARCELMEDIA_H
-#include "llmediabase.h"
+#include "llviewermedia.h"
class LLMessageSystem;
class LLParcel;
+class LLViewerParcelMediaNavigationObserver;
+
// This class understands land parcels, network traffic, LSL media
// transport commands, and talks to the LLViewerMedia class to actually
// do playback. It allows us to remove code from LLViewerParcelMgr.
-class LLViewerParcelMedia
+class LLViewerParcelMedia : public LLViewerMediaObserver
{
+ LOG_CLASS(LLViewerParcelMedia);
public:
static void initClass();
+ static void cleanupClass();
static void update(LLParcel* parcel);
// called when the agent's parcel has a new URL, or the agent has
@@ -60,17 +64,40 @@ class LLViewerParcelMedia
static void start();
// restart after pause - no need for all the setup
+ static void focus(bool focus);
+
static void seek(F32 time);
// jump to timecode time
- static LLMediaBase::EStatus getStatus();
+ static LLPluginClassMediaOwner::EMediaStatus getStatus();
+ static std::string getMimeType();
+ static std::string getURL();
+ static std::string getName();
+ static viewer_media_t getParcelMedia();
static void processParcelMediaCommandMessage( LLMessageSystem *msg, void ** );
static void processParcelMediaUpdate( LLMessageSystem *msg, void ** );
+ static void sendMediaNavigateMessage(const std::string& url);
+
+ // inherited from LLViewerMediaObserver
+ virtual void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
public:
static S32 sMediaParcelLocalID;
static LLUUID sMediaRegionID;
+ // HACK: this will change with Media on a Prim
+ static viewer_media_t sMediaImpl;
+};
+
+
+class LLViewerParcelMediaNavigationObserver
+{
+public:
+ std::string mCurrentURL;
+ bool mFromMessage;
+
+ // void onNavigateComplete( const EventType& event_in );
+
};
#endif
diff --git a/indra/newview/llviewerparcelmediaautoplay.cpp b/indra/newview/llviewerparcelmediaautoplay.cpp
index dbb9c32008..ad2723b66b 100644
--- a/indra/newview/llviewerparcelmediaautoplay.cpp
+++ b/indra/newview/llviewerparcelmediaautoplay.cpp
@@ -35,11 +35,12 @@
#include "llviewerparcelmedia.h"
#include "llviewercontrol.h"
#include "llviewermedia.h"
+#include "llviewerregion.h"
#include "llparcel.h"
#include "llviewerparcelmgr.h"
#include "lluuid.h"
#include "message.h"
-#include "llviewerimagelist.h" // for texture stats
+#include "llviewertexturelist.h" // for texture stats
#include "llagent.h"
const F32 AUTOPLAY_TIME = 5; // how many seconds before we autoplay
@@ -48,6 +49,8 @@ const F32 AUTOPLAY_SPEED = 0.1f; // how slow should the agent be moving t
LLViewerParcelMediaAutoPlay::LLViewerParcelMediaAutoPlay() :
LLEventTimer(1),
+
+ mLastParcelID(-1),
mPlayed(FALSE),
mTimeInParcel(0)
{
@@ -81,9 +84,18 @@ void LLViewerParcelMediaAutoPlay::playStarted()
BOOL LLViewerParcelMediaAutoPlay::tick()
{
LLParcel *this_parcel = NULL;
+ LLViewerRegion *this_region = NULL;
std::string this_media_url;
LLUUID this_media_texture_id;
S32 this_parcel_id = 0;
+ LLUUID this_region_id;
+
+ this_region = gAgent.getRegion();
+
+ if (this_region)
+ {
+ this_region_id = this_region->getRegionID();
+ }
this_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
@@ -96,12 +108,14 @@ BOOL LLViewerParcelMediaAutoPlay::tick()
this_parcel_id = this_parcel->getLocalID();
}
- if (this_parcel_id != mLastParcelID)
+ if (this_parcel_id != mLastParcelID ||
+ this_region_id != mLastRegionID)
{
// we've entered a new parcel
mPlayed = FALSE; // we haven't autoplayed yet
mTimeInParcel = 0; // reset our timer
mLastParcelID = this_parcel_id;
+ mLastRegionID = this_region_id;
}
mTimeInParcel += mPeriod; // increase mTimeInParcel by the amount of time between ticks
@@ -109,17 +123,17 @@ BOOL LLViewerParcelMediaAutoPlay::tick()
if ((!mPlayed) && // if we've never played
(mTimeInParcel > AUTOPLAY_TIME) && // and if we've been here for so many seconds
(this_media_url.size() != 0) && // and if the parcel has media
- (!LLViewerMedia::isMediaPlaying())) // and if the media is not already playing
+ (LLViewerParcelMedia::sMediaImpl.isNull())) // and if the media is not already playing
{
if (this_media_texture_id.notNull()) // and if the media texture is good
{
- LLViewerImage *image = gImageList.getImage(this_media_texture_id, FALSE);
+ LLViewerMediaTexture *image = LLViewerTextureManager::getMediaTexture(this_media_texture_id, FALSE) ;
F32 image_size = 0;
if (image)
{
- image_size = image->mMaxVirtualSize;
+ image_size = image->getMaxVirtualSize() ;
}
if (gAgent.getVelocity().magVec() < AUTOPLAY_SPEED) // and if the agent is stopped (slow enough)
diff --git a/indra/newview/llviewerparcelmediaautoplay.h b/indra/newview/llviewerparcelmediaautoplay.h
index cc2e70b1b9..1d80b4756c 100644
--- a/indra/newview/llviewerparcelmediaautoplay.h
+++ b/indra/newview/llviewerparcelmediaautoplay.h
@@ -33,8 +33,8 @@
#ifndef LLVIEWERPARCELMEDIAAUTOPLAY_H
#define LLVIEWERPARCELMEDIAAUTOPLAY_H
-#include "llmediabase.h"
#include "lltimer.h"
+#include "lluuid.h"
// timer to automatically play media
class LLViewerParcelMediaAutoPlay : LLEventTimer
@@ -48,6 +48,7 @@ class LLViewerParcelMediaAutoPlay : LLEventTimer
private:
S32 mLastParcelID;
+ LLUUID mLastRegionID;
BOOL mPlayed;
F32 mTimeInParcel;
};
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index 193dfaae96..10a95443f1 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -35,33 +35,35 @@
#include "llviewerparcelmgr.h"
// Library includes
-#include "audioengine.h"
+#include "llaudioengine.h"
#include "indra_constants.h"
#include "llcachename.h"
#include "llgl.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
#include "llparcel.h"
#include "llsecondlifeurls.h"
#include "message.h"
+#include "llfloaterreg.h"
// Viewer includes
#include "llagent.h"
-#include "llfloatergroupinfo.h"
#include "llviewerwindow.h"
#include "llviewercontrol.h"
-#include "llfirstuse.h"
+//#include "llfirstuse.h"
#include "llfloaterbuyland.h"
#include "llfloatergroups.h"
-//#include "llfloaterhtml.h"
+#include "llfloaternearbymedia.h"
#include "llfloatersellland.h"
#include "llfloatertools.h"
-#include "llnotify.h"
#include "llparcelselection.h"
#include "llresmgr.h"
#include "llsdutil.h"
+#include "llsdutil_math.h"
#include "llstatusbar.h"
#include "llui.h"
-#include "llviewerimage.h"
-#include "llviewerimagelist.h"
+#include "llviewertexture.h"
+#include "llviewertexturelist.h"
#include "llviewermenu.h"
#include "llviewerparcelmedia.h"
#include "llviewerparceloverlay.h"
@@ -80,8 +82,8 @@ U8* LLViewerParcelMgr::sPackedOverlay = NULL;
LLUUID gCurrentMovieID = LLUUID::null;
-LLPointer<LLViewerImage> sBlockedImage;
-LLPointer<LLViewerImage> sPassImage;
+LLPointer<LLViewerTexture> sBlockedImage;
+LLPointer<LLViewerTexture> sPassImage;
// Local functions
void optionally_start_music(const std::string& music_url);
@@ -143,8 +145,11 @@ LLViewerParcelMgr::LLViewerParcelMgr()
mCollisionSegments = new U8[(mParcelsPerEdge+1)*(mParcelsPerEdge+1)];
resetSegments(mCollisionSegments);
- mBlockedImage = gImageList.getImageFromFile("noentrylines.j2c");
- mPassImage = gImageList.getImageFromFile("noentrypasslines.j2c");
+ // JC: Resolved a merge conflict here, eliminated
+ // mBlockedImage->setAddressMode(LLTexUnit::TAM_WRAP);
+ // because it is done in llviewertexturelist.cpp
+ mBlockedImage = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryLines.png");
+ mPassImage = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryPassLines.png");
S32 overlay_size = mParcelsPerEdge * mParcelsPerEdge / PARCEL_OVERLAY_CHUNKS;
sPackedOverlay = new U8[overlay_size];
@@ -155,6 +160,8 @@ LLViewerParcelMgr::LLViewerParcelMgr()
{
mAgentParcelOverlay[i] = 0;
}
+
+ mTeleportInProgress = TRUE; // the initial parcel update is treated like teleport
}
@@ -516,7 +523,7 @@ LLParcelSelectionHandle LLViewerParcelMgr::selectLand(const LLVector3d &corner1,
if (region != region_other)
{
- LLNotifications::instance().add("CantSelectLandFromMultipleRegions");
+ LLNotificationsUtil::add("CantSelectLandFromMultipleRegions");
mSelected = FALSE;
notifyObservers();
return NULL;
@@ -646,7 +653,7 @@ LLParcel *LLViewerParcelMgr::getAgentParcel() const
}
// Return whether the agent can build on the land they are on
-BOOL LLViewerParcelMgr::agentCanBuild() const
+bool LLViewerParcelMgr::allowAgentBuild() const
{
if (mAgentParcel)
{
@@ -660,19 +667,47 @@ BOOL LLViewerParcelMgr::agentCanBuild() const
}
}
-BOOL LLViewerParcelMgr::agentCanTakeDamage() const
+bool LLViewerParcelMgr::allowAgentVoice() const
+{
+ LLViewerRegion* region = gAgent.getRegion();
+ return region && region->isVoiceEnabled()
+ && mAgentParcel && mAgentParcel->getParcelFlagAllowVoice();
+}
+
+bool LLViewerParcelMgr::allowAgentFly() const
+{
+ LLViewerRegion* region = gAgent.getRegion();
+ return region && !region->getBlockFly()
+ && mAgentParcel && mAgentParcel->getAllowFly();
+}
+
+// Can the agent be pushed around by LLPushObject?
+bool LLViewerParcelMgr::allowAgentPush() const
{
- return mAgentParcel->getAllowDamage();
+ LLViewerRegion* region = gAgent.getRegion();
+ return region && !region->getRestrictPushObject()
+ && mAgentParcel && !mAgentParcel->getRestrictPushObject();
}
-BOOL LLViewerParcelMgr::agentCanFly() const
+bool LLViewerParcelMgr::allowAgentScripts() const
{
- return TRUE;
+ LLViewerRegion* region = gAgent.getRegion();
+ // *NOTE: This code does not take into account group-owned parcels
+ // and the flag to allow group-owned scripted objects to run.
+ // This mirrors the traditional menu bar parcel icon code, but is not
+ // technically correct.
+ return region
+ && !(region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS)
+ && !(region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS)
+ && mAgentParcel
+ && mAgentParcel->getAllowOtherScripts();
}
-F32 LLViewerParcelMgr::agentDrawDistance() const
+bool LLViewerParcelMgr::allowAgentDamage() const
{
- return 512.f;
+ LLViewerRegion* region = gAgent.getRegion();
+ return region && region->getAllowDamage()
+ && mAgentParcel && mAgentParcel->getAllowDamage();
}
BOOL LLViewerParcelMgr::isOwnedAt(const LLVector3d& pos_global) const
@@ -760,13 +795,17 @@ BOOL LLViewerParcelMgr::canHearSound(const LLVector3d &pos_global) const
BOOL LLViewerParcelMgr::inAgentParcel(const LLVector3d &pos_global) const
{
LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal(pos_global);
- if (region != gAgent.getRegion())
+ LLViewerRegion* agent_region = gAgent.getRegion();
+ if (!region || !agent_region)
+ return FALSE;
+
+ if (region != agent_region)
{
// Can't be in the agent parcel if you're not in the same region.
return FALSE;
}
- LLVector3 pos_region = gAgent.getRegion()->getPosRegionFromGlobal(pos_global);
+ LLVector3 pos_region = agent_region->getPosRegionFromGlobal(pos_global);
S32 row = S32(pos_region.mV[VY] / PARCEL_GRID_STEP_METERS);
S32 column = S32(pos_region.mV[VX] / PARCEL_GRID_STEP_METERS);
@@ -835,8 +874,11 @@ void LLViewerParcelMgr::renderParcelCollision()
if (mRenderCollision && gSavedSettings.getBOOL("ShowBanLines"))
{
LLViewerRegion* regionp = gAgent.getRegion();
- BOOL use_pass = mCollisionParcel->getParcelFlag(PF_USE_PASS_LIST);
- renderCollisionSegments(mCollisionSegments, use_pass, regionp);
+ if (regionp)
+ {
+ BOOL use_pass = mCollisionParcel->getParcelFlag(PF_USE_PASS_LIST);
+ renderCollisionSegments(mCollisionSegments, use_pass, regionp);
+ }
}
}
@@ -904,7 +946,7 @@ void LLViewerParcelMgr::sendParcelGodForceOwner(const LLUUID& owner_id)
{
if (!mSelected)
{
- LLNotifications::instance().add("CannotSetLandOwnerNothingSelected");
+ LLNotificationsUtil::add("CannotSetLandOwnerNothingSelected");
return;
}
@@ -919,7 +961,7 @@ void LLViewerParcelMgr::sendParcelGodForceOwner(const LLUUID& owner_id)
if (!region)
{
// TODO: Add a force owner version of this alert.
- LLNotifications::instance().add("CannotContentifyNoRegion");
+ LLNotificationsUtil::add("CannotContentifyNoRegion");
return;
}
@@ -927,7 +969,7 @@ void LLViewerParcelMgr::sendParcelGodForceOwner(const LLUUID& owner_id)
LLViewerRegion *region2 = LLWorld::getInstance()->getRegionFromPosGlobal( east_north_region_check );
if (region != region2)
{
- LLNotifications::instance().add("CannotSetLandOwnerMultipleRegions");
+ LLNotificationsUtil::add("CannotSetLandOwnerMultipleRegions");
return;
}
@@ -938,7 +980,7 @@ void LLViewerParcelMgr::sendParcelGodForceOwner(const LLUUID& owner_id)
payload["parcel_local_id"] = mCurrentParcel->getLocalID();
payload["region_host"] = region->getHost().getIPandPort();
LLNotification::Params params("ForceOwnerAuctionWarning");
- params.payload(payload).functor(callback_god_force_owner);
+ params.payload(payload).functor.function(callback_god_force_owner);
if(mCurrentParcel->getAuctionID())
{
@@ -952,7 +994,7 @@ void LLViewerParcelMgr::sendParcelGodForceOwner(const LLUUID& owner_id)
bool callback_god_force_owner(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if(0 == option)
{
LLMessageSystem* msg = gMessageSystem;
@@ -972,13 +1014,13 @@ void LLViewerParcelMgr::sendParcelGodForceToContent()
{
if (!mSelected)
{
- LLNotifications::instance().add("CannotContentifyNothingSelected");
+ LLNotificationsUtil::add("CannotContentifyNothingSelected");
return;
}
LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
if (!region)
{
- LLNotifications::instance().add("CannotContentifyNoRegion");
+ LLNotificationsUtil::add("CannotContentifyNoRegion");
return;
}
@@ -996,14 +1038,14 @@ void LLViewerParcelMgr::sendParcelRelease()
{
if (!mSelected)
{
- LLNotifications::instance().add("CannotReleaseLandNothingSelected");
+ LLNotificationsUtil::add("CannotReleaseLandNothingSelected");
return;
}
LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
if (!region)
{
- LLNotifications::instance().add("CannotReleaseLandNoRegion");
+ LLNotificationsUtil::add("CannotReleaseLandNoRegion");
return;
}
@@ -1058,14 +1100,14 @@ LLViewerParcelMgr::ParcelBuyInfo* LLViewerParcelMgr::setupParcelBuy(
{
if (!mSelected || !mCurrentParcel)
{
- LLNotifications::instance().add("CannotBuyLandNothingSelected");
+ LLNotificationsUtil::add("CannotBuyLandNothingSelected");
return NULL;
}
LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
if (!region)
{
- LLNotifications::instance().add("CannotBuyLandNoRegion");
+ LLNotificationsUtil::add("CannotBuyLandNoRegion");
return NULL;
}
@@ -1083,7 +1125,7 @@ LLViewerParcelMgr::ParcelBuyInfo* LLViewerParcelMgr::setupParcelBuy(
if (region != region2)
{
- LLNotifications::instance().add("CantBuyLandAcrossMultipleRegions");
+ LLNotificationsUtil::add("CantBuyLandAcrossMultipleRegions");
return NULL;
}
}
@@ -1154,28 +1196,29 @@ void LLViewerParcelMgr::sendParcelBuy(ParcelBuyInfo* info)
msg->sendReliable(info->mHost);
}
-void LLViewerParcelMgr::deleteParcelBuy(ParcelBuyInfo*& info)
+void LLViewerParcelMgr::deleteParcelBuy(ParcelBuyInfo* *info)
{
- delete info;
- info = NULL;
+ // Must be here because ParcelBuyInfo is local to this .cpp file
+ delete *info;
+ *info = NULL;
}
void LLViewerParcelMgr::sendParcelDeed(const LLUUID& group_id)
{
if (!mSelected || !mCurrentParcel)
{
- LLNotifications::instance().add("CannotDeedLandNothingSelected");
+ LLNotificationsUtil::add("CannotDeedLandNothingSelected");
return;
}
if(group_id.isNull())
{
- LLNotifications::instance().add("CannotDeedLandNoGroup");
+ LLNotificationsUtil::add("CannotDeedLandNoGroup");
return;
}
LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
if (!region)
{
- LLNotifications::instance().add("CannotDeedLandNoRegion");
+ LLNotificationsUtil::add("CannotDeedLandNoRegion");
return;
}
@@ -1275,14 +1318,39 @@ void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel, bool use_ag
}
-void LLViewerParcelMgr::requestHoverParcelProperties(const LLVector3d& pos)
+void LLViewerParcelMgr::setHoverParcel(const LLVector3d& pos)
{
+ static U32 last_west, last_south;
+
+
+ // only request parcel info when tooltip is shown
+ if (!gSavedSettings.getBOOL("ShowLandHoverTip"))
+ {
+ return;
+ }
+
+ // only request parcel info if position has changed outside of the
+ // last parcel grid step
+ U32 west_parcel_step = (U32) floor( pos.mdV[VX] / PARCEL_GRID_STEP_METERS );
+ U32 south_parcel_step = (U32) floor( pos.mdV[VY] / PARCEL_GRID_STEP_METERS );
+
+ if ((west_parcel_step == last_west) && (south_parcel_step == last_south))
+ {
+ return;
+ }
+ else
+ {
+ last_west = west_parcel_step;
+ last_south = south_parcel_step;
+ }
+
LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( pos );
if (!region)
{
return;
}
+
// Send a rectangle around the point.
// This means the parcel sent back is at least a rectangle around the point,
// which is more efficient for public land. Fewer requests are sent. JC
@@ -1513,6 +1581,17 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
LLViewerParcelMgr::getInstance()->writeAgentParcelFromBitmap(bitmap);
delete[] bitmap;
+
+ // Let interesting parties know about agent parcel change.
+ LLViewerParcelMgr* instance = LLViewerParcelMgr::getInstance();
+
+ instance->mAgentParcelChangedSignal();
+
+ if (instance->mTeleportInProgress)
+ {
+ instance->mTeleportInProgress = FALSE;
+ instance->mTeleportFinishedSignal(gAgent.getPositionGlobal());
+ }
}
}
@@ -1584,6 +1663,9 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
// Request access list information for this land
LLViewerParcelMgr::getInstance()->sendParcelAccessListRequest(AL_ACCESS | AL_BAN);
+ // Request the media url filter list for this land
+ LLViewerParcelMgr::getInstance()->requestParcelMediaURLFilter();
+
// Request dwell for this land, if it's not public land.
LLViewerParcelMgr::getInstance()->mSelectedDwell = 0.f;
if (0 != local_id)
@@ -1678,7 +1760,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
}
else if (!gAudiop->getInternetStreamURL().empty())
{
- llinfos << "Stopping parcel music" << llendl;
+ llinfos << "Stopping parcel music (parcel stream URL is empty)" << llendl;
gAudiop->startInternetStream(LLStringUtil::null);
}
}
@@ -1697,15 +1779,19 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
void optionally_start_music(const std::string& music_url)
{
- if (gSavedSettings.getBOOL("AudioStreamingMusic"))
- {
- // Make the user click the start button on the overlay bar. JC
- // llinfos << "Starting parcel music " << music_url << llendl;
-
- // now only play music when you enter a new parcel if the control is in PLAY state
- // changed as part of SL-4878
- if ( gOverlayBar && gOverlayBar->musicPlaying())
+ if (gSavedSettings.getBOOL("AudioStreamingMusic") &&
+ gSavedSettings.getBOOL("AudioStreamingMedia"))
+ {
+ // only play music when you enter a new parcel if the UI control for this
+ // was not *explicitly* stopped by the user. (part of SL-4878)
+ LLFloaterNearbyMedia *nearby_media_floater = LLFloaterReg::findTypedInstance<LLFloaterNearbyMedia>("nearby_media");
+ if ((nearby_media_floater &&
+ nearby_media_floater->getParcelAudioAutoStart()) ||
+ // or they have expressed no opinion in the UI, but have autoplay on...
+ (!nearby_media_floater &&
+ gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING)))
{
+ llinfos << "Starting parcel music " << music_url << llendl;
gAudiop->startInternetStream(music_url);
}
}
@@ -1907,6 +1993,66 @@ void LLViewerParcelMgr::sendParcelAccessListUpdate(U32 which)
}
}
+class LLParcelMediaURLFilterResponder : public LLHTTPClient::Responder
+{
+ virtual void result(const LLSD& content)
+ {
+ LLViewerParcelMgr::getInstance()->receiveParcelMediaURLFilter(content);
+ }
+};
+
+void LLViewerParcelMgr::requestParcelMediaURLFilter()
+{
+ if (!mSelected)
+ {
+ return;
+ }
+
+ LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
+ if (!region)
+ {
+ return;
+ }
+
+ LLParcel* parcel = mCurrentParcel;
+ if (!parcel)
+ {
+ llwarns << "no parcel" << llendl;
+ return;
+ }
+
+ LLSD body;
+ body["local-id"] = parcel->getLocalID();
+ body["list"] = parcel->getMediaURLFilterList();
+
+ std::string url = region->getCapability("ParcelMediaURLFilterList");
+ if (!url.empty())
+ {
+ LLHTTPClient::post(url, body, new LLParcelMediaURLFilterResponder);
+ }
+ else
+ {
+ llwarns << "can't get ParcelMediaURLFilterList cap" << llendl;
+ }
+}
+
+
+void LLViewerParcelMgr::receiveParcelMediaURLFilter(const LLSD &content)
+{
+ if (content.has("list"))
+ {
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->mCurrentParcel;
+ if (!parcel) return;
+
+ if (content["local-id"].asInteger() == parcel->getLocalID())
+ {
+ parcel->setMediaURLFilterList(content["list"]);
+
+ LLViewerParcelMgr::getInstance()->notifyObservers();
+ }
+ }
+}
+
void LLViewerParcelMgr::deedLandToGroup()
{
@@ -1921,18 +2067,18 @@ void LLViewerParcelMgr::deedLandToGroup()
gCacheName->getName(mCurrentParcel->getOwnerID(), first_name, last_name);
args["FIRST_NAME"] = first_name;
args["LAST_NAME"] = last_name;
- LLNotifications::instance().add("DeedLandToGroupWithContribution",args, LLSD(), deedAlertCB);
+ LLNotificationsUtil::add("DeedLandToGroupWithContribution",args, LLSD(), deedAlertCB);
}
else
{
- LLNotifications::instance().add("DeedLandToGroup",args, LLSD(), deedAlertCB);
+ LLNotificationsUtil::add("DeedLandToGroup",args, LLSD(), deedAlertCB);
}
}
// static
bool LLViewerParcelMgr::deedAlertCB(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0)
{
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel();
@@ -1951,26 +2097,26 @@ void LLViewerParcelMgr::startReleaseLand()
{
if (!mSelected)
{
- LLNotifications::instance().add("CannotReleaseLandNothingSelected");
+ LLNotificationsUtil::add("CannotReleaseLandNothingSelected");
return;
}
if (mRequestResult == PARCEL_RESULT_NO_DATA)
{
- LLNotifications::instance().add("CannotReleaseLandWatingForServer");
+ LLNotificationsUtil::add("CannotReleaseLandWatingForServer");
return;
}
if (mRequestResult == PARCEL_RESULT_MULTIPLE)
{
- LLNotifications::instance().add("CannotReleaseLandSelected");
+ LLNotificationsUtil::add("CannotReleaseLandSelected");
return;
}
if (!isParcelOwnedByAgent(mCurrentParcel, GP_LAND_RELEASE)
&& !(gAgent.canManageEstate()))
{
- LLNotifications::instance().add("CannotReleaseLandDontOwn");
+ LLNotificationsUtil::add("CannotReleaseLandDontOwn");
return;
}
@@ -1978,7 +2124,7 @@ void LLViewerParcelMgr::startReleaseLand()
LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal(parcel_center);
if (!region)
{
- LLNotifications::instance().add("CannotReleaseLandRegionNotFound");
+ LLNotificationsUtil::add("CannotReleaseLandRegionNotFound");
return;
}
/*
@@ -1987,21 +2133,21 @@ void LLViewerParcelMgr::startReleaseLand()
{
LLSD args;
args["REGION"] = region->getName();
- LLNotifications::instance().add("CannotReleaseLandNoTransfer", args);
+ LLNotificationsUtil::add("CannotReleaseLandNoTransfer", args);
return;
}
*/
if (!mCurrentParcelSelection->mWholeParcelSelected)
{
- LLNotifications::instance().add("CannotReleaseLandPartialSelection");
+ LLNotificationsUtil::add("CannotReleaseLandPartialSelection");
return;
}
// Compute claim price
LLSD args;
args["AREA"] = llformat("%d",mCurrentParcel->getArea());
- LLNotifications::instance().add("ReleaseLandWarning", args, LLSD(), releaseAlertCB);
+ LLNotificationsUtil::add("ReleaseLandWarning", args, LLSD(), releaseAlertCB);
}
bool LLViewerParcelMgr::canAgentBuyParcel(LLParcel* parcel, bool forGroup) const
@@ -2076,13 +2222,13 @@ void LLViewerParcelMgr::startDivideLand()
{
if (!mSelected)
{
- LLNotifications::instance().add("CannotDivideLandNothingSelected");
+ LLNotificationsUtil::add("CannotDivideLandNothingSelected");
return;
}
if (mCurrentParcelSelection->mWholeParcelSelected)
{
- LLNotifications::instance().add("CannotDivideLandPartialSelection");
+ LLNotificationsUtil::add("CannotDivideLandPartialSelection");
return;
}
@@ -2090,13 +2236,13 @@ void LLViewerParcelMgr::startDivideLand()
payload["west_south_border"] = ll_sd_from_vector3d(mWestSouth);
payload["east_north_border"] = ll_sd_from_vector3d(mEastNorth);
- LLNotifications::instance().add("LandDivideWarning", LLSD(), payload, callbackDivideLand);
+ LLNotificationsUtil::add("LandDivideWarning", LLSD(), payload, callbackDivideLand);
}
// static
bool LLViewerParcelMgr::callbackDivideLand(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLVector3d west_south_d = ll_vector3d_from_sd(notification["payload"]["west_south_border"]);
LLVector3d east_north_d = ll_vector3d_from_sd(notification["payload"]["east_north_border"]);
LLVector3d parcel_center = (west_south_d + east_north_d) / 2.0;
@@ -2104,7 +2250,7 @@ bool LLViewerParcelMgr::callbackDivideLand(const LLSD& notification, const LLSD&
LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal(parcel_center);
if (!region)
{
- LLNotifications::instance().add("CannotDivideLandNoRegion");
+ LLNotificationsUtil::add("CannotDivideLandNoRegion");
return false;
}
@@ -2133,19 +2279,19 @@ void LLViewerParcelMgr::startJoinLand()
{
if (!mSelected)
{
- LLNotifications::instance().add("CannotJoinLandNothingSelected");
+ LLNotificationsUtil::add("CannotJoinLandNothingSelected");
return;
}
if (mCurrentParcelSelection->mWholeParcelSelected)
{
- LLNotifications::instance().add("CannotJoinLandEntireParcelSelected");
+ LLNotificationsUtil::add("CannotJoinLandEntireParcelSelected");
return;
}
if (!mCurrentParcelSelection->mSelectedMultipleOwners)
{
- LLNotifications::instance().add("CannotJoinLandSelection");
+ LLNotificationsUtil::add("CannotJoinLandSelection");
return;
}
@@ -2153,13 +2299,13 @@ void LLViewerParcelMgr::startJoinLand()
payload["west_south_border"] = ll_sd_from_vector3d(mWestSouth);
payload["east_north_border"] = ll_sd_from_vector3d(mEastNorth);
- LLNotifications::instance().add("JoinLandWarning", LLSD(), payload, callbackJoinLand);
+ LLNotificationsUtil::add("JoinLandWarning", LLSD(), payload, callbackJoinLand);
}
// static
bool LLViewerParcelMgr::callbackJoinLand(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLVector3d west_south_d = ll_vector3d_from_sd(notification["payload"]["west_south_border"]);
LLVector3d east_north_d = ll_vector3d_from_sd(notification["payload"]["east_north_border"]);
LLVector3d parcel_center = (west_south_d + east_north_d) / 2.0;
@@ -2167,7 +2313,7 @@ bool LLViewerParcelMgr::callbackJoinLand(const LLSD& notification, const LLSD& r
LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal(parcel_center);
if (!region)
{
- LLNotifications::instance().add("CannotJoinLandNoRegion");
+ LLNotificationsUtil::add("CannotJoinLandNoRegion");
return false;
}
@@ -2196,19 +2342,19 @@ void LLViewerParcelMgr::startDeedLandToGroup()
{
if (!mSelected || !mCurrentParcel)
{
- LLNotifications::instance().add("CannotDeedLandNothingSelected");
+ LLNotificationsUtil::add("CannotDeedLandNothingSelected");
return;
}
if (mRequestResult == PARCEL_RESULT_NO_DATA)
{
- LLNotifications::instance().add("CannotDeedLandWaitingForServer");
+ LLNotificationsUtil::add("CannotDeedLandWaitingForServer");
return;
}
if (mRequestResult == PARCEL_RESULT_MULTIPLE)
{
- LLNotifications::instance().add("CannotDeedLandMultipleSelected");
+ LLNotificationsUtil::add("CannotDeedLandMultipleSelected");
return;
}
@@ -2216,7 +2362,7 @@ void LLViewerParcelMgr::startDeedLandToGroup()
LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal(parcel_center);
if (!region)
{
- LLNotifications::instance().add("CannotDeedLandNoRegion");
+ LLNotificationsUtil::add("CannotDeedLandNoRegion");
return;
}
@@ -2228,7 +2374,7 @@ void LLViewerParcelMgr::startDeedLandToGroup()
{
LLSD args;
args["REGION"] = region->getName();
- LLNotifications::instance().add("CannotDeedLandNoTransfer", args);
+ LLNotificationsUtil::add("CannotDeedLandNoTransfer", args);
return;
}
}
@@ -2258,7 +2404,7 @@ void LLViewerParcelMgr::reclaimParcel()
// static
bool LLViewerParcelMgr::releaseAlertCB(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0)
{
// Send the release message, not a force
@@ -2369,12 +2515,61 @@ void LLViewerParcelMgr::cleanupGlobals()
LLParcelSelection::sNullSelection = NULL;
}
-LLViewerImage* LLViewerParcelMgr::getBlockedImage() const
+LLViewerTexture* LLViewerParcelMgr::getBlockedImage() const
{
return sBlockedImage;
}
-LLViewerImage* LLViewerParcelMgr::getPassImage() const
+LLViewerTexture* LLViewerParcelMgr::getPassImage() const
{
return sPassImage;
}
+
+boost::signals2::connection LLViewerParcelMgr::addAgentParcelChangedCallback(parcel_changed_callback_t cb)
+{
+ return mAgentParcelChangedSignal.connect(cb);
+}
+/*
+ * Set finish teleport callback. You can use it to observe all teleport events.
+ * NOTE:
+ * After local( in one region) teleports we
+ * cannot rely on gAgent.getPositionGlobal(),
+ * so the new position gets passed explicitly.
+ * Use args of this callback to get global position of avatar after teleport event.
+ */
+boost::signals2::connection LLViewerParcelMgr::setTeleportFinishedCallback(teleport_finished_callback_t cb)
+{
+ return mTeleportFinishedSignal.connect(cb);
+}
+
+boost::signals2::connection LLViewerParcelMgr::setTeleportFailedCallback(parcel_changed_callback_t cb)
+{
+ return mTeleportFailedSignal.connect(cb);
+}
+
+/* Ok, we're notified that teleport has been finished.
+ * We should now propagate the notification via mTeleportFinishedSignal
+ * to all interested parties.
+ */
+void LLViewerParcelMgr::onTeleportFinished(bool local, const LLVector3d& new_pos)
+{
+ // Treat only teleports within the same parcel as local (EXT-3139).
+ if (local && LLViewerParcelMgr::getInstance()->inAgentParcel(new_pos))
+ {
+ // Local teleport. We already have the agent parcel data.
+ // Emit the signal immediately.
+ getInstance()->mTeleportFinishedSignal(new_pos);
+ }
+ else
+ {
+ // Non-local teleport (inter-region or between different parcels of the same region).
+ // The agent parcel data has not been updated yet.
+ // Let's wait for the update and then emit the signal.
+ mTeleportInProgress = TRUE;
+ }
+}
+
+void LLViewerParcelMgr::onTeleportFailed()
+{
+ mTeleportFailedSignal();
+}
diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h
index 9f762a186c..379190789b 100644
--- a/indra/newview/llviewerparcelmgr.h
+++ b/indra/newview/llviewerparcelmgr.h
@@ -36,14 +36,17 @@
#include "v3dmath.h"
#include "lldarray.h"
#include "llframetimer.h"
-#include "llmemory.h"
+#include "llsingleton.h"
#include "llparcelselection.h"
#include "llui.h"
+#include <boost/function.hpp>
+#include <boost/signals2.hpp>
+
class LLUUID;
class LLMessageSystem;
class LLParcel;
-class LLViewerImage;
+class LLViewerTexture;
class LLViewerRegion;
// Constants for sendLandOwner
@@ -53,9 +56,6 @@ class LLViewerRegion;
// | EAST_MASK
// | WEST_MASK);
-const F32 PARCEL_POST_HEIGHT = 0.666f;
-//const F32 PARCEL_POST_HEIGHT = 20.f;
-
// Specify the type of land transfer taking place
//enum ELandTransferType
//{
@@ -68,6 +68,9 @@ const F32 PARCEL_POST_HEIGHT = 0.666f;
// Base class for people who want to "observe" changes in the viewer
// parcel selection.
+
+//FIXME: this should be done by grabbing a floating parcel selection and observing changes on it, not the parcel mgr
+//--RN
class LLParcelObserver
{
public:
@@ -79,6 +82,11 @@ class LLViewerParcelMgr : public LLSingleton<LLViewerParcelMgr>
{
public:
+ typedef boost::function<void (const LLVector3d&)> teleport_finished_callback_t;
+ typedef boost::signals2::signal<void (const LLVector3d&)> teleport_finished_signal_t;
+ typedef boost::function<void()> parcel_changed_callback_t;
+ typedef boost::signals2::signal<void()> parcel_changed_signal_t;
+
LLViewerParcelMgr();
~LLViewerParcelMgr();
@@ -160,10 +168,29 @@ public:
LLParcel* getCollisionParcel() const;
- BOOL agentCanTakeDamage() const;
- BOOL agentCanFly() const;
- F32 agentDrawDistance() const;
- BOOL agentCanBuild() const;
+ // Can this agent build on the parcel he is on?
+ // Used for parcel property icons in nav bar.
+ bool allowAgentBuild() const;
+
+ // Can this agent speak on the parcel he is on?
+ // Used for parcel property icons in nav bar.
+ bool allowAgentVoice() const;
+
+ // Can this agent start flying on this parcel?
+ // Used for parcel property icons in nav bar.
+ bool allowAgentFly() const;
+
+ // Can this agent be pushed by llPushObject() on this parcel?
+ // Used for parcel property icons in nav bar.
+ bool allowAgentPush() const;
+
+ // Can scripts written by non-parcel-owners run on the agent's current
+ // parcel? Used for parcel property icons in nav bar.
+ bool allowAgentScripts() const;
+
+ // Can the agent be damaged here?
+ // Used for parcel property icons in nav bar.
+ bool allowAgentDamage() const;
F32 getHoverParcelWidth() const
{ return F32(mHoverEastNorth.mdV[VX] - mHoverWestSouth.mdV[VX]); }
@@ -198,13 +225,18 @@ public:
// Takes an Access List flag, like AL_ACCESS or AL_BAN
void sendParcelAccessListRequest(U32 flags);
+ // asks for the parcel's media url filter list
+ void requestParcelMediaURLFilter();
+ // receive the response
+ void receiveParcelMediaURLFilter(const LLSD &content);
+
// Dwell is not part of the usual parcel update information because the
// simulator doesn't actually know the per-parcel dwell. Ack! We have
// to get it out of the database.
void sendParcelDwellRequest();
// If the point is outside the current hover parcel, request more data
- void requestHoverParcelProperties(const LLVector3d& pos_global);
+ void setHoverParcel(const LLVector3d& pos_global);
bool canAgentBuyParcel(LLParcel*, bool forGroup) const;
@@ -230,7 +262,7 @@ public:
BOOL remove_contribution);
// callers responsibility to call deleteParcelBuy() on return value
void sendParcelBuy(ParcelBuyInfo*);
- void deleteParcelBuy(ParcelBuyInfo*&);
+ void deleteParcelBuy(ParcelBuyInfo* *info);
void sendParcelDeed(const LLUUID& group_id);
@@ -256,6 +288,12 @@ public:
// the agent is banned or not in the allowed group
BOOL isCollisionBanned();
+ boost::signals2::connection addAgentParcelChangedCallback(parcel_changed_callback_t cb);
+ boost::signals2::connection setTeleportFinishedCallback(teleport_finished_callback_t cb);
+ boost::signals2::connection setTeleportFailedCallback(parcel_changed_callback_t cb);
+ void onTeleportFinished(bool local, const LLVector3d& new_pos);
+ void onTeleportFailed();
+
static BOOL isParcelOwnedByAgent(const LLParcel* parcelp, U64 group_proxy_power);
static BOOL isParcelModifiableByAgent(const LLParcel* parcelp, U64 group_proxy_power);
@@ -279,8 +317,8 @@ private:
static bool callbackJoinLand(const LLSD& notification, const LLSD& response);
//void finishClaim(BOOL user_to_user_sale, U32 join);
- LLViewerImage* getBlockedImage() const;
- LLViewerImage* getPassImage() const;
+ LLViewerTexture* getBlockedImage() const;
+ LLViewerTexture* getPassImage() const;
private:
BOOL mSelected;
@@ -303,6 +341,11 @@ private:
LLDynamicArray<LLParcelObserver*> mObservers;
+ BOOL mTeleportInProgress;
+ teleport_finished_signal_t mTeleportFinishedSignal;
+ parcel_changed_signal_t mTeleportFailedSignal;
+ parcel_changed_signal_t mAgentParcelChangedSignal;
+
// Array of pieces of parcel edges to potentially draw
// Has (parcels_per_edge + 1) * (parcels_per_edge + 1) elements so
// we can represent edges of the grid.
@@ -324,8 +367,8 @@ private:
BOOL mRenderSelection;
S32 mCollisionBanned;
LLFrameTimer mCollisionTimer;
- LLImageGL* mBlockedImage;
- LLImageGL* mPassImage;
+ LLViewerTexture* mBlockedImage;
+ LLViewerTexture* mPassImage;
// Media
S32 mMediaParcelId;
diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp
index 866c2a91eb..9de1ef7190 100644
--- a/indra/newview/llviewerparceloverlay.cpp
+++ b/indra/newview/llviewerparceloverlay.cpp
@@ -36,22 +36,25 @@
// indra includes
#include "llparcel.h"
+#include "llfloaterreg.h"
#include "llgl.h"
#include "llrender.h"
#include "v4color.h"
#include "v2math.h"
// newview includes
-#include "llviewerimage.h"
+#include "llviewertexture.h"
#include "llviewercontrol.h"
#include "llsurface.h"
#include "llviewerregion.h"
#include "llagent.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llselectmgr.h"
#include "llfloatertools.h"
#include "llglheaders.h"
+#include "pipeline.h"
+
const U8 OVERLAY_IMG_COMPONENTS = 4;
@@ -68,12 +71,9 @@ LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_
{
// Create a texture to hold color information.
// 4 components
- // Use mipmaps = FALSE, clamped, NEAREST filter, for sharp edges
- mTexture = new LLImageGL(FALSE);
+ // Use mipmaps = FALSE, clamped, NEAREST filter, for sharp edges
mImageRaw = new LLImageRaw(mParcelGridsPerEdge, mParcelGridsPerEdge, OVERLAY_IMG_COMPONENTS);
- mTexture->createGLTexture(0, mImageRaw);
- gGL.getTexUnit(0)->activate();
- gGL.getTexUnit(0)->bind(mTexture);
+ mTexture = LLViewerTextureManager::getLocalTexture(mImageRaw.get(), FALSE);
mTexture->setAddressMode(LLTexUnit::TAM_CLAMP);
mTexture->setFilteringOption(LLTexUnit::TFO_POINT);
@@ -87,7 +87,7 @@ LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_
{
raw[i] = 0;
}
- mTexture->setSubImage(mImageRaw, 0, 0, mParcelGridsPerEdge, mParcelGridsPerEdge);
+ //mTexture->setSubImage(mImageRaw, 0, 0, mParcelGridsPerEdge, mParcelGridsPerEdge);
// Create storage for ownership information from simulator
// and initialize it.
@@ -97,8 +97,7 @@ LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_
mOwnership[i] = PARCEL_PUBLIC;
}
- // Make sure the texture matches the ownership information.
- updateOverlayTexture();
+ gPipeline.markGLRebuild(this);
}
@@ -205,13 +204,12 @@ void LLViewerParcelOverlay::updateOverlayTexture()
{
return;
}
- // Can do this because gColors are actually stored as LLColor4U
- const LLColor4U avail = gColors.getColor4U("PropertyColorAvail");
- const LLColor4U owned = gColors.getColor4U("PropertyColorOther");
- const LLColor4U group = gColors.getColor4U("PropertyColorGroup");
- const LLColor4U self = gColors.getColor4U("PropertyColorSelf");
- const LLColor4U for_sale = gColors.getColor4U("PropertyColorForSale");
- const LLColor4U auction = gColors.getColor4U("PropertyColorAuction");
+ const LLColor4U avail = LLUIColorTable::instance().getColor("PropertyColorAvail").get();
+ const LLColor4U owned = LLUIColorTable::instance().getColor("PropertyColorOther").get();
+ const LLColor4U group = LLUIColorTable::instance().getColor("PropertyColorGroup").get();
+ const LLColor4U self = LLUIColorTable::instance().getColor("PropertyColorSelf").get();
+ const LLColor4U for_sale = LLUIColorTable::instance().getColor("PropertyColorForSale").get();
+ const LLColor4U auction = LLUIColorTable::instance().getColor("PropertyColorAuction").get();
// Create the base texture.
U8 *raw = mImageRaw->getData();
@@ -224,7 +222,7 @@ void LLViewerParcelOverlay::updateOverlayTexture()
{
U8 ownership = mOwnership[i];
- U8 r,g,b,a;
+ F32 r,g,b,a;
// Color stored in low three bits
switch( ownership & 0x7 )
@@ -273,10 +271,10 @@ void LLViewerParcelOverlay::updateOverlayTexture()
break;
}
- raw[pixel_index + 0] = r;
- raw[pixel_index + 1] = g;
- raw[pixel_index + 2] = b;
- raw[pixel_index + 3] = a;
+ raw[pixel_index + 0] = (U8)r;
+ raw[pixel_index + 1] = (U8)g;
+ raw[pixel_index + 2] = (U8)b;
+ raw[pixel_index + 3] = (U8)a;
pixel_index += OVERLAY_IMG_COMPONENTS;
}
@@ -284,6 +282,10 @@ void LLViewerParcelOverlay::updateOverlayTexture()
// Copy data into GL texture from raw data
if (i >= COUNT)
{
+ if (!mTexture->hasGLTexture())
+ {
+ mTexture->createGLTexture(0, mImageRaw);
+ }
mTexture->setSubImage(mImageRaw, 0, 0, mParcelGridsPerEdge, mParcelGridsPerEdge);
mOverlayTextureIdx = -1;
}
@@ -314,12 +316,11 @@ void LLViewerParcelOverlay::updatePropertyLines()
S32 row, col;
- // Can do this because gColors are actually stored as LLColor4U
- const LLColor4U self_coloru = gColors.getColor4U("PropertyColorSelf");
- const LLColor4U other_coloru = gColors.getColor4U("PropertyColorOther");
- const LLColor4U group_coloru = gColors.getColor4U("PropertyColorGroup");
- const LLColor4U for_sale_coloru = gColors.getColor4U("PropertyColorForSale");
- const LLColor4U auction_coloru = gColors.getColor4U("PropertyColorAuction");
+ const LLColor4U self_coloru = LLUIColorTable::instance().getColor("PropertyColorSelf").get();
+ const LLColor4U other_coloru = LLUIColorTable::instance().getColor("PropertyColorOther").get();
+ const LLColor4U group_coloru = LLUIColorTable::instance().getColor("PropertyColorGroup").get();
+ const LLColor4U for_sale_coloru = LLUIColorTable::instance().getColor("PropertyColorForSale").get();
+ const LLColor4U auction_coloru = LLUIColorTable::instance().getColor("PropertyColorAuction").get();
// Build into dynamic arrays, then copy into static arrays.
LLDynamicArray<LLVector3, 256> new_vertex_array;
@@ -711,8 +712,14 @@ void LLViewerParcelOverlay::setDirty()
mDirty = TRUE;
}
+void LLViewerParcelOverlay::updateGL()
+{
+ updateOverlayTexture();
+}
+
void LLViewerParcelOverlay::idleUpdate(bool force_update)
{
+ LLMemType mt_iup(LLMemType::MTYPE_IDLE_UPDATE_PARCEL_OVERLAY);
if (gGLManager.mIsDisabled)
{
return;
@@ -720,7 +727,7 @@ void LLViewerParcelOverlay::idleUpdate(bool force_update)
if (mOverlayTextureIdx >= 0 && (!(mDirty && force_update)))
{
// We are in the middle of updating the overlay texture
- updateOverlayTexture();
+ gPipeline.markGLRebuild(this);
return;
}
// Only if we're dirty and it's been a while since the last update.
@@ -801,6 +808,7 @@ S32 LLViewerParcelOverlay::renderPropertyLines ()
S32 drawn = 0;
F32* vertexp;
U8* colorp;
+ bool render_hidden = LLSelectMgr::sRenderHiddenSelections && LLFloaterReg::instanceVisible("build");
const F32 PROPERTY_LINE_CLIP_DIST = 256.f;
@@ -841,8 +849,8 @@ S32 LLViewerParcelOverlay::renderPropertyLines ()
drawn += vertex_per_edge;
gGL.end();
-
- if (LLSelectMgr::sRenderHiddenSelections && gFloaterTools && gFloaterTools->getVisible())
+
+ if (render_hidden)
{
LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER);
diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h
index 9bed1dde34..161b7a386b 100644
--- a/indra/newview/llviewerparceloverlay.h
+++ b/indra/newview/llviewerparceloverlay.h
@@ -39,21 +39,22 @@
#include "lldarray.h"
#include "llframetimer.h"
#include "lluuid.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
+#include "llgl.h"
class LLViewerRegion;
class LLVector3;
class LLColor4U;
class LLVector2;
-class LLViewerParcelOverlay
+class LLViewerParcelOverlay : public LLGLUpdate
{
public:
LLViewerParcelOverlay(LLViewerRegion* region, F32 region_width_meters);
~LLViewerParcelOverlay();
// ACCESS
- LLImageGL* getTexture() const { return mTexture; }
+ LLViewerTexture* getTexture() const { return mTexture; }
BOOL isOwned(const LLVector3& pos) const;
BOOL isOwnedSelf(const LLVector3& pos) const;
@@ -76,6 +77,7 @@ public:
void setDirty();
void idleUpdate(bool update_now = false);
+ void updateGL();
private:
// This is in parcel rows and columns, not grid rows and columns
@@ -99,7 +101,7 @@ private:
S32 mParcelGridsPerEdge;
- LLPointer<LLImageGL> mTexture;
+ LLPointer<LLViewerTexture> mTexture;
LLPointer<LLImageRaw> mImageRaw;
// Size: mParcelGridsPerEdge * mParcelGridsPerEdge
diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp
index b74f9e9f2c..841a7ccc5e 100644
--- a/indra/newview/llviewerpartsim.cpp
+++ b/indra/newview/llviewerpartsim.cpp
@@ -71,9 +71,9 @@ const F32 LLViewerPartSim::PART_ADAPT_RATE_MULT_RECIP = 1.0f/PART_ADAPT_RATE_MUL
U32 LLViewerPart::sNextPartID = 1;
-F32 calc_desired_size(LLVector3 pos, LLVector2 scale)
+F32 calc_desired_size(LLViewerCamera* camera, LLVector3 pos, LLVector2 scale)
{
- F32 desired_size = (pos-LLViewerCamera::getInstance()->getOrigin()).magVec();
+ F32 desired_size = (pos - camera->getOrigin()).magVec();
desired_size /= 4;
return llclamp(desired_size, scale.magVec()*0.5f, PART_SIM_BOX_SIDE*2);
}
@@ -98,7 +98,7 @@ LLViewerPart::~LLViewerPart()
--LLViewerPartSim::sParticleCount2 ;
}
-void LLViewerPart::init(LLPointer<LLViewerPartSource> sourcep, LLViewerImage *imagep, LLVPCallback cb)
+void LLViewerPart::init(LLPointer<LLViewerPartSource> sourcep, LLViewerTexture *imagep, LLVPCallback cb)
{
LLMemType mt(LLMemType::MTYPE_PARTICLES);
mPartID = LLViewerPart::sNextPartID;
@@ -273,6 +273,7 @@ void LLViewerPartGroup::updateParticles(const F32 lastdt)
LLViewerPartSim::checkParticleCount(mParticles.size());
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
LLViewerRegion *regionp = getRegion();
S32 end = (S32) mParticles.size();
for (S32 i = 0 ; i < (S32)mParticles.size();)
@@ -394,7 +395,7 @@ void LLViewerPartGroup::updateParticles(const F32 lastdt)
}
else
{
- F32 desired_size = calc_desired_size(part->mPosAgent, part->mScale);
+ F32 desired_size = calc_desired_size(camera, part->mPosAgent, part->mScale);
if (!posInGroup(part->mPosAgent, desired_size))
{
// Transfer particles between groups
@@ -557,7 +558,8 @@ LLViewerPartGroup *LLViewerPartSim::put(LLViewerPart* part)
}
else
{
- F32 desired_size = calc_desired_size(part->mPosAgent, part->mScale);
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
+ F32 desired_size = calc_desired_size(camera, part->mPosAgent, part->mScale);
S32 count = (S32) mViewerPartGroups.size();
for (S32 i = 0; i < count; i++)
@@ -631,6 +633,8 @@ void LLViewerPartSim::shift(const LLVector3 &offset)
}
}
+static LLFastTimer::DeclareTimer FTM_SIMULATE_PARTICLES("Simulate Particles");
+
void LLViewerPartSim::updateSimulation()
{
LLMemType mt(LLMemType::MTYPE_PARTICLES);
@@ -644,7 +648,7 @@ void LLViewerPartSim::updateSimulation()
return;
}
- LLFastTimer ftm(LLFastTimer::FTM_SIMULATE_PARTICLES);
+ LLFastTimer ftm(FTM_SIMULATE_PARTICLES);
// Start at a random particle system so the same
// particle system doesn't always get first pick at the
diff --git a/indra/newview/llviewerpartsim.h b/indra/newview/llviewerpartsim.h
index 21bc37f891..8f1f72518a 100644
--- a/indra/newview/llviewerpartsim.h
+++ b/indra/newview/llviewerpartsim.h
@@ -35,14 +35,14 @@
#include "lldarrayptr.h"
#include "llframetimer.h"
-#include "llmemory.h"
+#include "llpointer.h"
#include "llpartdata.h"
#include "llviewerpartsource.h"
-class LLViewerImage;
+class LLViewerTexture;
class LLViewerPart;
class LLViewerRegion;
-class LLViewerImage;
+class LLViewerTexture;
class LLVOPartGroup;
typedef void (*LLVPCallback)(LLViewerPart &part, const F32 dt);
@@ -60,7 +60,7 @@ public:
public:
LLViewerPart();
- void init(LLPointer<LLViewerPartSource> sourcep, LLViewerImage *imagep, LLVPCallback cb);
+ void init(LLPointer<LLViewerPartSource> sourcep, LLViewerTexture *imagep, LLVPCallback cb);
U32 mPartID; // Particle ID used primarily for moving between groups
@@ -72,7 +72,7 @@ public:
// Current particle state (possibly used for rendering)
- LLPointer<LLViewerImage> mImagep;
+ LLPointer<LLViewerTexture> mImagep;
LLVector3 mPosAgent;
LLVector3 mVelocity;
LLVector3 mAccel;
diff --git a/indra/newview/llviewerpartsource.cpp b/indra/newview/llviewerpartsource.cpp
index 38c75a84d1..4752bf1a85 100644
--- a/indra/newview/llviewerpartsource.cpp
+++ b/indra/newview/llviewerpartsource.cpp
@@ -39,7 +39,7 @@
#include "llagent.h"
#include "lldrawable.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewerobject.h"
#include "llviewerobjectlist.h"
#include "llvoavatar.h"
@@ -78,7 +78,7 @@ void LLViewerPartSource::update(const F32 dt)
LLUUID LLViewerPartSource::getImageUUID() const
{
- LLViewerImage* imagep = mImagep;
+ LLViewerTexture* imagep = mImagep;
if(imagep)
{
return imagep->getID();
@@ -100,8 +100,8 @@ LLViewerPartSourceScript::LLViewerPartSourceScript(LLViewerObject *source_objp)
llassert(source_objp);
mSourceObjectp = source_objp;
mPosAgent = mSourceObjectp->getPositionAgent();
- mImagep = gImageList.getImageFromFile("pixiesmall.j2c");
- gGL.getTexUnit(0)->bind(mImagep.get());
+ mImagep = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
+
mImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
}
@@ -491,7 +491,7 @@ LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::createPSS(LLViewer
}
-void LLViewerPartSourceScript::setImage(LLViewerImage *imagep)
+void LLViewerPartSourceScript::setImage(LLViewerTexture *imagep)
{
LLMemType mt(LLMemType::MTYPE_PARTICLES);
mImagep = imagep;
@@ -551,7 +551,7 @@ void LLViewerPartSourceSpiral::update(const F32 dt)
LLMemType mt(LLMemType::MTYPE_PARTICLES);
if (!mImagep)
{
- mImagep = gImageList.getImageFromFile("pixiesmall.j2c");
+ mImagep = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
}
const F32 RATE = 0.025f;
@@ -720,7 +720,7 @@ void LLViewerPartSourceBeam::update(const F32 dt)
if (!mImagep)
{
- mImagep = gImageList.getImageFromFile("pixiesmall.j2c");
+ mImagep = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
}
LLViewerPart* part = new LLViewerPart();
@@ -806,7 +806,7 @@ void LLViewerPartSourceChat::update(const F32 dt)
LLMemType mt(LLMemType::MTYPE_PARTICLES);
if (!mImagep)
{
- mImagep = gImageList.getImageFromFile("pixiesmall.j2c");
+ mImagep = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
}
diff --git a/indra/newview/llviewerpartsource.h b/indra/newview/llviewerpartsource.h
index 4258b9170f..540e30eb19 100644
--- a/indra/newview/llviewerpartsource.h
+++ b/indra/newview/llviewerpartsource.h
@@ -33,8 +33,9 @@
#ifndef LL_LLVIEWERPARTSOURCE_H
#define LL_LLVIEWERPARTSOURCE_H
-#include "llmemory.h"
+#include "llrefcount.h"
#include "llpartdata.h"
+#include "llpointer.h"
#include "llquaternion.h"
#include "v3math.h"
@@ -44,7 +45,7 @@
//
//
-class LLViewerImage;
+class LLViewerTexture;
class LLViewerObject;
class LLViewerPart;
@@ -89,7 +90,7 @@ protected:
F32 mLastUpdateTime;
F32 mLastPartTime;
LLUUID mOwnerUUID;
- LLPointer<LLViewerImage> mImagep;
+ LLPointer<LLViewerTexture> mImagep;
// Particle information
U32 mPartFlags; // Flags for the particle
@@ -122,8 +123,8 @@ public:
static LLPointer<LLViewerPartSourceScript> unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp);
static LLPointer<LLViewerPartSourceScript> createPSS(LLViewerObject *source_objp, const LLPartSysData& particle_parameters);
- LLViewerImage *getImage() const { return mImagep; }
- void setImage(LLViewerImage *imagep);
+ LLViewerTexture *getImage() const { return mImagep; }
+ void setImage(LLViewerTexture *imagep);
LLPartSysData mPartSysData;
void setTargetObject(LLViewerObject *objp);
diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h
index 49319b13b1..50f905416c 100644
--- a/indra/newview/llviewerprecompiledheaders.h
+++ b/indra/newview/llviewerprecompiledheaders.h
@@ -41,17 +41,6 @@
#include "linden_common.h"
-// We may want to take the windows.h include out, but it used to be in
-// linden_common.h, and hence in all the libraries. This is better. JC
-#if LL_WINDOWS
- // Limit Windows API to small and manageable set.
- // If you get undefined symbols, find the appropriate
- // Windows header file and include that in your .cpp file.
- #define WIN32_LEAN_AND_MEAN
- #include <winsock2.h>
- #include <windows.h>
-#endif
-
// Work around stupid Microsoft STL warning
#ifdef LL_WINDOWS
#pragma warning (disable : 4702) // warning C4702: unreachable code
@@ -69,42 +58,38 @@
// Library headers from llcommon project:
#include "bitpack.h"
+#include "lldeleteutils.h"
#include "imageids.h"
#include "indra_constants.h"
//#include "linden_common.h"
//#include "llpreprocessor.h"
+#include "llallocator.h"
#include "llapp.h"
-#include "llapr.h"
#include "llcriticaldamp.h"
-#include "lldarray.h"
-#include "lldarrayptr.h"
#include "lldefs.h"
#include "lldepthstack.h"
-#include "lldqueueptr.h"
-#include "llendianswizzle.h"
#include "llerror.h"
#include "llfasttimer.h"
-#include "llfixedbuffer.h"
#include "llframetimer.h"
#include "llhash.h"
#include "lllocalidhashmap.h"
-#include "llmap.h"
-#include "llmemory.h"
#include "llnametable.h"
+#include "llpointer.h"
#include "llpriqueuemap.h"
#include "llprocessor.h"
+#include "llrefcount.h"
+#include "llsafehandle.h"
//#include "llsecondlifeurls.h"
-#include "llstack.h"
+#include "llsd.h"
+#include "llsingleton.h"
#include "llstat.h"
#include "llstl.h"
#include "llstrider.h"
#include "llstring.h"
-#include "llstringtable.h"
#include "llsys.h"
#include "llthread.h"
#include "lltimer.h"
#include "lluuidhashmap.h"
-//#include "llversionviewer.h"
//#include "processor.h"
#include "stdenums.h"
#include "stdtypes.h"
@@ -113,26 +98,7 @@
#include "timing.h"
#include "u64.h"
-// Library includes from llimage
-//#include "kdc_flow_control.h"
-//#include "kde_flow_control.h"
-//#include "kdu_image.h"
-//#include "kdu_image_local.h"
-//#include "llblockdata.h"
-//#include "llblockdecoder.h"
-//#include "llblockencoder.h"
-#include "llimage.h"
-#include "llimagebmp.h"
-#include "llimagepng.h"
-#include "llimagej2c.h"
-#include "llimagejpeg.h"
-#include "llimagetga.h"
-//#include "llkdumem.h"
-#include "llmapimagetype.h"
-
// Library includes from llmath project
-//#include "camera.h"
-//#include "coordframe.h"
#include "llmath.h"
#include "llbboxlocal.h"
#include "llcamera.h"
@@ -160,76 +126,13 @@
////#include "vmath.h"
#include "xform.h"
+// Library includes from llvfs
+#include "lldir.h"
+
// Library includes from llmessage project
-//#include "llassetstorage.h"
#include "llcachename.h"
-#include "llcircuit.h"
-#include "lldatapacker.h"
-#include "lldbstrings.h"
-#include "lldispatcher.h"
-#include "lleventflags.h"
-#include "llhost.h"
-#include "llinstantmessage.h"
-#include "llinvite.h"
-//#include "llloginflags.h"
-#include "llmail.h"
-#include "llmessagethrottle.h"
-#include "llnamevalue.h"
-#include "llpacketack.h"
-#include "llpacketbuffer.h"
-#include "llpacketring.h"
-#include "llpartdata.h"
-//#include "llqueryflags.h"
-//#include "llregionflags.h"
-#include "llregionhandle.h"
-#include "lltaskname.h"
-#include "llteleportflags.h"
-#include "llthrottle.h"
-#include "lltransfermanager.h"
-#include "lltransfersourceasset.h"
-#include "lltransfersourcefile.h"
-#include "lltransfertargetfile.h"
-#include "lltransfertargetvfile.h"
-#include "lluseroperation.h"
-#include "llvehicleparams.h"
-#include "llxfer.h"
-#include "llxfer_file.h"
-#include "llxfer_mem.h"
-#include "llxfer_vfile.h"
-#include "llxfermanager.h"
-#include "machine.h"
-#include "mean_collision_data.h"
-#include "message.h"
-#include "message_prehash.h"
-#include "net.h"
-//#include "network.h"
-#include "partsyspacket.h"
-#include "patch_code.h"
-#include "patch_dct.h"
-#include "sound_ids.h"
-// Library includes from llprimitive
-#include "imageids.h"
-#include "legacy_object_types.h"
-#include "llmaterialtable.h"
-//#include "llprimitive.h"
-#include "lltextureanim.h"
-//#include "lltextureentry.h"
-#include "lltreeparams.h"
-//#include "llvolume.h"
-#include "llvolumemgr.h"
-#include "material_codes.h"
-
-// Library includes from llxml
-#include "llxmlnode.h"
-
-// Library includes from llvfs
-#include "llassettype.h"
-#include "lldir.h"
-//#include "lldir_linux.h"
-//#include "lldir_mac.h"
-//#include "lldir_win32.h"
-#include "llvfile.h"
-#include "llvfs.h"
+// llxuixml
+#include "llinitparam.h"
#endif
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 12d9c1a992..77d2d493bd 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -35,6 +35,7 @@
#include "llviewerregion.h"
#include "indra_constants.h"
+#include "llfloaterreg.h"
#include "llmath.h"
#include "llhttpclient.h"
#include "llregionflags.h"
@@ -65,6 +66,11 @@
#include "llvoclouds.h"
#include "llworld.h"
#include "llspatialpartition.h"
+#include "stringize.h"
+
+#ifdef LL_WINDOWS
+ #pragma warning(disable:4355)
+#endif
// Viewer object cache version, change if object update
// format changes. JC
@@ -172,7 +178,18 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
mCacheEntriesCount(0),
mCacheID(),
mEventPoll(NULL),
- mReleaseNotesRequested(FALSE)
+ mReleaseNotesRequested(FALSE),
+ // I'd prefer to set the LLCapabilityListener name to match the region
+ // name -- it's disappointing that's not available at construction time.
+ // We could instead store an LLCapabilityListener*, making
+ // setRegionNameAndZone() replace the instance. Would that pose
+ // consistency problems? Can we even request a capability before calling
+ // setRegionNameAndZone()?
+ // For testability -- the new Michael Feathers paradigm --
+ // LLCapabilityListener binds all the globals it expects to need at
+ // construction time.
+ mCapabilityListener(host.getString(), gMessageSystem, *this,
+ gAgent.getID(), gAgent.getSessionID())
{
mWidth = region_width_meters;
mOriginGlobal = from_region_handle(handle);
@@ -223,7 +240,6 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
mObjectPartition.push_back(new LLBridgePartition()); //PARTITION_BRIDGE
mObjectPartition.push_back(new LLHUDParticlePartition());//PARTITION_HUD_PARTICLE
mObjectPartition.push_back(NULL); //PARTITION_NONE
-
}
@@ -623,6 +639,7 @@ void LLViewerRegion::dirtyHeights()
BOOL LLViewerRegion::idleUpdate(F32 max_update_time)
{
+ LLMemType mt_ivr(LLMemType::MTYPE_IDLE_UPDATE_VIEWER_REGION);
// did_update returns TRUE if we did at least one significant update
BOOL did_update = mLandp->idleUpdate(max_update_time);
@@ -764,16 +781,20 @@ void LLViewerRegion::calculateCameraDistance()
mCameraDistanceSquared = (F32)(gAgent.getCameraPositionGlobal() - getCenterGlobal()).magVecSquared();
}
-U32 LLViewerRegion::getNetDetailsForLCD()
-{
- return mPingDelay;
-}
-
std::ostream& operator<<(std::ostream &s, const LLViewerRegion &region)
{
s << "{ ";
s << region.mHost;
s << " mOriginGlobal = " << region.getOriginGlobal()<< "\n";
+ std::string name(region.getName()), zone(region.getZoning());
+ if (! name.empty())
+ {
+ s << " mName = " << name << '\n';
+ }
+ if (! zone.empty())
+ {
+ s << " mZoning = " << zone << '\n';
+ }
s << "}";
return s;
}
@@ -1400,21 +1421,28 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
setCapability("Seed", url);
LLSD capabilityNames = LLSD::emptyArray();
+
+ capabilityNames.append("AttachmentResources");
capabilityNames.append("ChatSessionRequest");
capabilityNames.append("CopyInventoryFromNotecard");
capabilityNames.append("DispatchRegionInfo");
capabilityNames.append("EstateChangeInfo");
capabilityNames.append("EventQueueGet");
capabilityNames.append("FetchInventory");
- capabilityNames.append("WebFetchInventoryDescendents");
+ capabilityNames.append("ObjectMedia");
+ capabilityNames.append("ObjectMediaNavigate");
capabilityNames.append("FetchLib");
capabilityNames.append("FetchLibDescendents");
+ capabilityNames.append("GetTexture");
capabilityNames.append("GroupProposalBallot");
capabilityNames.append("HomeLocation");
+ capabilityNames.append("LandResources");
capabilityNames.append("MapLayer");
capabilityNames.append("MapLayerGod");
capabilityNames.append("NewFileAgentInventory");
capabilityNames.append("ParcelPropertiesUpdate");
+ capabilityNames.append("ParcelMediaURLFilterList");
+ capabilityNames.append("ParcelNavigateMedia");
capabilityNames.append("ParcelVoiceInfoRequest");
capabilityNames.append("ProductInfoRequest");
capabilityNames.append("ProvisionVoiceAccountRequest");
@@ -1427,6 +1455,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("SendUserReportWithScreenshot");
capabilityNames.append("ServerReleaseNotes");
capabilityNames.append("StartGroupProposal");
+ capabilityNames.append("TextureStats");
capabilityNames.append("UntrustedSimulatorMessage");
capabilityNames.append("UpdateAgentInformation");
capabilityNames.append("UpdateAgentLanguage");
@@ -1439,6 +1468,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("UploadBakedTexture");
capabilityNames.append("ViewerStartAuction");
capabilityNames.append("ViewerStats");
+ capabilityNames.append("WebFetchInventoryDescendents");
// Please add new capabilities alphabetically to reduce
// merge conflicts.
@@ -1518,3 +1548,8 @@ void LLViewerRegion::showReleaseNotes()
LLWeb::loadURL(url);
mReleaseNotesRequested = FALSE;
}
+
+std::string LLViewerRegion::getDescription() const
+{
+ return stringize(*this);
+}
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index b0a98a99b8..49d0900f2a 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -49,6 +49,9 @@
#include "lldatapacker.h"
#include "llvocache.h"
#include "llweb.h"
+#include "llcapabilityprovider.h"
+#include "llcapabilitylistener.h"
+#include "m4math.h" // LLMatrix4
// Surface id's
#define LAND 1
@@ -66,8 +69,9 @@ class LLSurface;
class LLVOCache;
class LLVOCacheEntry;
class LLSpatialPartition;
+class LLEventPump;
-class LLViewerRegion
+class LLViewerRegion: public LLCapabilityProvider // implements this interface
{
public:
//MUST MATCH THE ORDER OF DECLARATION IN CONSTRUCTOR
@@ -226,11 +230,19 @@ public:
// Get/set named capability URLs for this region.
void setSeedCapability(const std::string& url);
void setCapability(const std::string& name, const std::string& url);
- std::string getCapability(const std::string& name) const;
+ // implements LLCapabilityProvider
+ virtual std::string getCapability(const std::string& name) const;
static bool isSpecialCapabilityName(const std::string &name);
void logActiveCapabilities() const;
- const LLHost &getHost() const { return mHost; }
+ /// Capability-request exception
+ typedef LLCapabilityListener::ArgError ArgError;
+ /// Get LLEventPump on which we listen for capability requests
+ /// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities)
+ LLEventPump& getCapAPI() { return mCapabilityListener.getCapAPI(); }
+
+ /// implements LLCapabilityProvider
+ virtual LLHost getHost() const { return mHost; }
const U64 &getHandle() const { return mHandle; }
LLSurface &getLand() const { return *mLandp; }
@@ -274,9 +286,8 @@ public:
void calculateCameraDistance();
friend std::ostream& operator<<(std::ostream &s, const LLViewerRegion &region);
-
- // used by LCD to get details for debug screen
- U32 getNetDetailsForLCD();
+ /// implements LLCapabilityProvider
+ virtual std::string getDescription() const;
LLSpatialPartition* getSpatialPartition(U32 type);
public:
@@ -394,6 +405,11 @@ private:
LLEventPoll* mEventPoll;
+ /// Post an event to this LLCapabilityListener to invoke a capability message on
+ /// this LLViewerRegion's server
+ /// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities)
+ LLCapabilityListener mCapabilityListener;
+
private:
bool mAlive; // can become false if circuit disconnects
@@ -461,5 +477,3 @@ inline BOOL LLViewerRegion::getReleaseNotesRequested() const
}
#endif
-
-
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index b5bd2f93af..6dc9f5c465 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -104,6 +104,7 @@ LLGLSLShader gPostNightVisionProgram;
// Deferred rendering shaders
LLGLSLShader gDeferredImpostorProgram;
+LLGLSLShader gDeferredEdgeProgram;
LLGLSLShader gDeferredWaterProgram;
LLGLSLShader gDeferredDiffuseProgram;
LLGLSLShader gDeferredBumpProgram;
@@ -113,6 +114,8 @@ LLGLSLShader gDeferredAvatarProgram;
LLGLSLShader gDeferredAvatarAlphaProgram;
LLGLSLShader gDeferredLightProgram;
LLGLSLShader gDeferredMultiLightProgram;
+LLGLSLShader gDeferredSpotLightProgram;
+LLGLSLShader gDeferredMultiSpotLightProgram;
LLGLSLShader gDeferredSunProgram;
LLGLSLShader gDeferredBlurLightProgram;
LLGLSLShader gDeferredSoftenProgram;
@@ -120,6 +123,13 @@ LLGLSLShader gDeferredShadowProgram;
LLGLSLShader gDeferredAvatarShadowProgram;
LLGLSLShader gDeferredAlphaProgram;
LLGLSLShader gDeferredFullbrightProgram;
+LLGLSLShader gDeferredGIProgram;
+LLGLSLShader gDeferredGIFinalProgram;
+LLGLSLShader gDeferredPostGIProgram;
+LLGLSLShader gDeferredPostProgram;
+
+LLGLSLShader gLuminanceGatherProgram;
+
//current avatar shader parameter pointer
GLint gAvatarMatrixParam;
@@ -151,6 +161,11 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
mShaderList.push_back(&gDeferredMultiLightProgram);
mShaderList.push_back(&gDeferredAlphaProgram);
mShaderList.push_back(&gDeferredFullbrightProgram);
+ mShaderList.push_back(&gDeferredPostGIProgram);
+ mShaderList.push_back(&gDeferredEdgeProgram);
+ mShaderList.push_back(&gDeferredPostProgram);
+ mShaderList.push_back(&gDeferredGIProgram);
+ mShaderList.push_back(&gDeferredGIFinalProgram);
mShaderList.push_back(&gDeferredWaterProgram);
mShaderList.push_back(&gDeferredAvatarAlphaProgram);
}
@@ -220,13 +235,35 @@ void LLViewerShaderMgr::initAttribsAndUniforms(void)
mReservedUniforms.push_back("shadowMap1");
mReservedUniforms.push_back("shadowMap2");
mReservedUniforms.push_back("shadowMap3");
+ mReservedUniforms.push_back("shadowMap4");
+ mReservedUniforms.push_back("shadowMap5");
+
mReservedUniforms.push_back("normalMap");
mReservedUniforms.push_back("positionMap");
mReservedUniforms.push_back("diffuseRect");
mReservedUniforms.push_back("specularRect");
mReservedUniforms.push_back("noiseMap");
+ mReservedUniforms.push_back("lightFunc");
mReservedUniforms.push_back("lightMap");
-
+ mReservedUniforms.push_back("luminanceMap");
+ mReservedUniforms.push_back("giLightMap");
+ mReservedUniforms.push_back("giMip");
+ mReservedUniforms.push_back("edgeMap");
+ mReservedUniforms.push_back("bloomMap");
+ mReservedUniforms.push_back("sunLightMap");
+ mReservedUniforms.push_back("localLightMap");
+ mReservedUniforms.push_back("projectionMap");
+ mReservedUniforms.push_back("diffuseGIMap");
+ mReservedUniforms.push_back("specularGIMap");
+ mReservedUniforms.push_back("normalGIMap");
+ mReservedUniforms.push_back("minpGIMap");
+ mReservedUniforms.push_back("maxpGIMap");
+ mReservedUniforms.push_back("depthGIMap");
+ mReservedUniforms.push_back("lastDiffuseGIMap");
+ mReservedUniforms.push_back("lastNormalGIMap");
+ mReservedUniforms.push_back("lastMinpGIMap");
+ mReservedUniforms.push_back("lastMaxpGIMap");
+
mWLUniforms.push_back("camPosLocal");
mTerrainUniforms.reserve(5);
@@ -340,7 +377,21 @@ void LLViewerShaderMgr::setShaders()
if (LLPipeline::sRenderDeferred)
{
- deferred_class = 1;
+ if (gSavedSettings.getBOOL("RenderDeferredShadow"))
+ {
+ if (gSavedSettings.getBOOL("RenderDeferredGI"))
+ { //shadows + gi
+ deferred_class = 3;
+ }
+ else
+ { //shadows
+ deferred_class = 2;
+ }
+ }
+ else
+ { //no shadows
+ deferred_class = 1;
+ }
}
if(!gSavedSettings.getBOOL("EnableRippleWater"))
@@ -814,6 +865,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredTerrainProgram.unload();
gDeferredLightProgram.unload();
gDeferredMultiLightProgram.unload();
+ gDeferredSpotLightProgram.unload();
+ gDeferredMultiSpotLightProgram.unload();
gDeferredSunProgram.unload();
gDeferredBlurLightProgram.unload();
gDeferredSoftenProgram.unload();
@@ -823,6 +876,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredAvatarAlphaProgram.unload();
gDeferredAlphaProgram.unload();
gDeferredFullbrightProgram.unload();
+ gDeferredPostGIProgram.unload();
+ gDeferredEdgeProgram.unload();
+ gDeferredPostProgram.unload();
+ gLuminanceGatherProgram.unload();
+ gDeferredGIProgram.unload();
+ gDeferredGIFinalProgram.unload();
gDeferredWaterProgram.unload();
return FALSE;
}
@@ -893,6 +952,26 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (success)
{
+ gDeferredSpotLightProgram.mName = "Deferred SpotLight Shader";
+ gDeferredSpotLightProgram.mShaderFiles.clear();
+ gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredSpotLightProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gDeferredMultiSpotLightProgram.mName = "Deferred MultiSpotLight Shader";
+ gDeferredMultiSpotLightProgram.mShaderFiles.clear();
+ gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredMultiSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredMultiSpotLightProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
gDeferredSunProgram.mName = "Deferred Sun Shader";
gDeferredSunProgram.mShaderFiles.clear();
gDeferredSunProgram.mShaderFiles.push_back(make_pair("deferred/sunLightV.glsl", GL_VERTEX_SHADER_ARB));
@@ -1022,6 +1101,72 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
success = gDeferredAvatarAlphaProgram.createShader(&mAvatarAttribs, &mAvatarUniforms);
}
+ if (mVertexShaderLevel[SHADER_DEFERRED] > 1)
+ {
+ if (success)
+ {
+ gDeferredEdgeProgram.mName = "Deferred Edge Shader";
+ gDeferredEdgeProgram.mShaderFiles.clear();
+ gDeferredEdgeProgram.mShaderFiles.push_back(make_pair("deferred/edgeV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredEdgeProgram.mShaderFiles.push_back(make_pair("deferred/edgeF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredEdgeProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredEdgeProgram.createShader(NULL, NULL);
+ }
+ }
+
+ if (mVertexShaderLevel[SHADER_DEFERRED] > 2)
+ {
+ if (success)
+ {
+ gDeferredPostProgram.mName = "Deferred Post Shader";
+ gDeferredPostProgram.mShaderFiles.clear();
+ gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredPostProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredPostProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gDeferredPostGIProgram.mName = "Deferred Post GI Shader";
+ gDeferredPostGIProgram.mShaderFiles.clear();
+ gDeferredPostGIProgram.mShaderFiles.push_back(make_pair("deferred/postgiV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredPostGIProgram.mShaderFiles.push_back(make_pair("deferred/postgiF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredPostGIProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredPostGIProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gDeferredGIProgram.mName = "Deferred GI Shader";
+ gDeferredGIProgram.mShaderFiles.clear();
+ gDeferredGIProgram.mShaderFiles.push_back(make_pair("deferred/giV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredGIProgram.mShaderFiles.push_back(make_pair("deferred/giF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredGIProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredGIProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gDeferredGIFinalProgram.mName = "Deferred GI Final Shader";
+ gDeferredGIFinalProgram.mShaderFiles.clear();
+ gDeferredGIFinalProgram.mShaderFiles.push_back(make_pair("deferred/giFinalV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredGIFinalProgram.mShaderFiles.push_back(make_pair("deferred/giFinalF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredGIFinalProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredGIFinalProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gLuminanceGatherProgram.mName = "Luminance Gather Shader";
+ gLuminanceGatherProgram.mShaderFiles.clear();
+ gLuminanceGatherProgram.mShaderFiles.push_back(make_pair("deferred/luminanceV.glsl", GL_VERTEX_SHADER_ARB));
+ gLuminanceGatherProgram.mShaderFiles.push_back(make_pair("deferred/luminanceF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gLuminanceGatherProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gLuminanceGatherProgram.createShader(NULL, NULL);
+ }
+ }
+
return success;
}
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index a743966d93..ac2b4624e0 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -116,12 +116,33 @@ public:
DEFERRED_SHADOW1,
DEFERRED_SHADOW2,
DEFERRED_SHADOW3,
+ DEFERRED_SHADOW4,
+ DEFERRED_SHADOW5,
DEFERRED_NORMAL,
DEFERRED_POSITION,
DEFERRED_DIFFUSE,
DEFERRED_SPECULAR,
DEFERRED_NOISE,
+ DEFERRED_LIGHTFUNC,
DEFERRED_LIGHT,
+ DEFERRED_LUMINANCE,
+ DEFERRED_GI_LIGHT,
+ DEFERRED_GI_MIP,
+ DEFERRED_EDGE,
+ DEFERRED_BLOOM,
+ DEFERRED_SUN_LIGHT,
+ DEFERRED_LOCAL_LIGHT,
+ DEFERRED_PROJECTION,
+ DEFERRED_GI_DIFFUSE,
+ DEFERRED_GI_SPECULAR,
+ DEFERRED_GI_NORMAL,
+ DEFERRED_GI_MIN_POS,
+ DEFERRED_GI_MAX_POS,
+ DEFERRED_GI_DEPTH,
+ DEFERRED_GI_LAST_DIFFUSE,
+ DEFERRED_GI_LAST_NORMAL,
+ DEFERRED_GI_LAST_MIN_POS,
+ DEFERRED_GI_LAST_MAX_POS,
END_RESERVED_UNIFORMS
} eGLSLReservedUniforms;
@@ -319,6 +340,7 @@ extern LLGLSLShader gPostNightVisionProgram;
// Deferred rendering shaders
extern LLGLSLShader gDeferredImpostorProgram;
+extern LLGLSLShader gDeferredEdgeProgram;
extern LLGLSLShader gDeferredWaterProgram;
extern LLGLSLShader gDeferredDiffuseProgram;
extern LLGLSLShader gDeferredBumpProgram;
@@ -326,16 +348,24 @@ extern LLGLSLShader gDeferredTerrainProgram;
extern LLGLSLShader gDeferredTreeProgram;
extern LLGLSLShader gDeferredLightProgram;
extern LLGLSLShader gDeferredMultiLightProgram;
+extern LLGLSLShader gDeferredSpotLightProgram;
+extern LLGLSLShader gDeferredMultiSpotLightProgram;
extern LLGLSLShader gDeferredSunProgram;
+extern LLGLSLShader gDeferredGIProgram;
+extern LLGLSLShader gDeferredGIFinalProgram;
extern LLGLSLShader gDeferredBlurLightProgram;
extern LLGLSLShader gDeferredAvatarProgram;
extern LLGLSLShader gDeferredSoftenProgram;
extern LLGLSLShader gDeferredShadowProgram;
+extern LLGLSLShader gDeferredPostGIProgram;
+extern LLGLSLShader gDeferredPostProgram;
extern LLGLSLShader gDeferredAvatarShadowProgram;
extern LLGLSLShader gDeferredAlphaProgram;
extern LLGLSLShader gDeferredFullbrightProgram;
extern LLGLSLShader gDeferredAvatarAlphaProgram;
+extern LLGLSLShader gLuminanceGatherProgram;
+
//current avatar shader parameter pointer
extern GLint gAvatarMatrixParam;
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 648fbd4714..8059f866ba 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -36,33 +36,33 @@
#include "llviewerthrottle.h"
#include "message.h"
+#include "llfloaterreg.h"
+#include "llmemory.h"
#include "lltimer.h"
+#include "llvfile.h"
#include "llappviewer.h"
#include "pipeline.h"
#include "lltexturefetch.h"
#include "llviewerobjectlist.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "lltexlayer.h"
+#include "lltexlayerparams.h"
#include "llsurface.h"
#include "llvlmanager.h"
#include "llagent.h"
#include "llviewercontrol.h"
-#include "llfloaterdirectory.h"
#include "llfloatertools.h"
#include "lldebugview.h"
#include "llfasttimerview.h"
#include "llviewerregion.h"
#include "llvoavatar.h"
-#include "llfloaterhtml.h"
+#include "llvoavatarself.h"
#include "llviewerwindow.h" // *TODO: remove, only used for width/height
#include "llworld.h"
#include "llfeaturemanager.h"
#include "llviewernetwork.h"
-#if LL_LCD_COMPILE
-#include "lllcd.h"
-#endif
class StatAttributes
@@ -199,16 +199,76 @@ const StatAttributes STAT_INFO[LLViewerStats::ST_COUNT] =
// ST_TEX_BAKES
StatAttributes("Texture Bakes", FALSE, FALSE),
// ST_TEX_REBAKES
- StatAttributes("Texture Rebakes", FALSE, FALSE),
-
- // ST_LOGITECH_KEYBOARD
- StatAttributes("Logitech LCD", FALSE, FALSE)
+ StatAttributes("Texture Rebakes", FALSE, FALSE)
};
-LLViewerStats::LLViewerStats()
- : mPacketsLostPercentStat(64),
- mLastTimeDiff(0.0)
+LLViewerStats::LLViewerStats() :
+ mKBitStat("kbitstat"),
+ mLayersKBitStat("layerskbitstat"),
+ mObjectKBitStat("objectkbitstat"),
+ mAssetKBitStat("assetkbitstat"),
+ mTextureKBitStat("texturekbitstat"),
+ mVFSPendingOperations("vfspendingoperations"),
+ mObjectsDrawnStat("objectsdrawnstat"),
+ mObjectsCulledStat("objectsculledstat"),
+ mObjectsTestedStat("objectstestedstat"),
+ mObjectsComparedStat("objectscomparedstat"),
+ mObjectsOccludedStat("objectsoccludedstat"),
+ mFPSStat("fpsstat"),
+ mPacketsInStat("packetsinstat"),
+ mPacketsLostStat("packetsloststat"),
+ mPacketsOutStat("packetsoutstat"),
+ mPacketsLostPercentStat("packetslostpercentstat", 64),
+ mTexturePacketsStat("texturepacketsstat"),
+ mActualInKBitStat("actualinkbitstat"),
+ mActualOutKBitStat("actualoutkbitstat"),
+ mTrianglesDrawnStat("trianglesdrawnstat"),
+ mSimTimeDilation("simtimedilation"),
+ mSimFPS("simfps"),
+ mSimPhysicsFPS("simphysicsfps"),
+ mSimAgentUPS("simagentups"),
+ mSimScriptEPS("simscripteps"),
+ mSimFrameMsec("simframemsec"),
+ mSimNetMsec("simnetmsec"),
+ mSimSimOtherMsec("simsimothermsec"),
+ mSimSimPhysicsMsec("simsimphysicsmsec"),
+ mSimSimPhysicsStepMsec("simsimphysicsstepmsec"),
+ mSimSimPhysicsShapeUpdateMsec("simsimphysicsshapeupdatemsec"),
+ mSimSimPhysicsOtherMsec("simsimphysicsothermsec"),
+ mSimAgentMsec("simagentmsec"),
+ mSimImagesMsec("simimagesmsec"),
+ mSimScriptMsec("simscriptmsec"),
+ mSimSpareMsec("simsparemsec"),
+ mSimSleepMsec("simsleepmsec"),
+ mSimPumpIOMsec("simpumpiomsec"),
+ mSimMainAgents("simmainagents"),
+ mSimChildAgents("simchildagents"),
+ mSimObjects("simobjects"),
+ mSimActiveObjects("simactiveobjects"),
+ mSimActiveScripts("simactivescripts"),
+ mSimInPPS("siminpps"),
+ mSimOutPPS("simoutpps"),
+ mSimPendingDownloads("simpendingdownloads"),
+ mSimPendingUploads("simpendinguploads"),
+ mSimPendingLocalUploads("simpendinglocaluploads"),
+ mSimTotalUnackedBytes("simtotalunackedbytes"),
+ mPhysicsPinnedTasks("physicspinnedtasks"),
+ mPhysicsLODTasks("physicslodtasks"),
+ mPhysicsMemoryAllocated("physicsmemoryallocated"),
+ mSimPingStat("simpingstat"),
+ mNumImagesStat("numimagesstat", 32, TRUE),
+ mNumRawImagesStat("numrawimagesstat", 32, TRUE),
+ mGLTexMemStat("gltexmemstat", 32, TRUE),
+ mGLBoundMemStat("glboundmemstat", 32, TRUE),
+ mRawMemStat("rawmemstat", 32, TRUE),
+ mFormattedMemStat("formattedmemstat", 32, TRUE),
+ mNumObjectsStat("numobjectsstat"),
+ mNumActiveObjectsStat("numactiveobjectsstat"),
+ mNumNewObjectsStat("numnewobjectsstat"),
+ mNumSizeCulledStat("numsizeculledstat"),
+ mNumVisCulledStat("numvisculledstat"),
+ mLastTimeDiff(0.0)
{
for (S32 i = 0; i < ST_COUNT; i++)
{
@@ -353,7 +413,6 @@ void reset_statistics()
{
if (LLSurface::sTextureUpdateTime)
{
- LLSurface::sTexelsUpdatedPerSecStat.addValue(0.001f*(LLSurface::sTexelsUpdated / LLSurface::sTextureUpdateTime));
LLSurface::sTexelsUpdated = 0;
LLSurface::sTextureUpdateTime = 0.f;
}
@@ -364,9 +423,9 @@ void output_statistics(void*)
{
llinfos << "Number of orphans: " << gObjectList.getOrphanCount() << llendl;
llinfos << "Number of dead objects: " << gObjectList.mNumDeadObjects << llendl;
- llinfos << "Num images: " << gImageList.getNumImages() << llendl;
- llinfos << "Texture usage: " << LLImageGL::sGlobalTextureMemory << llendl;
- llinfos << "Texture working set: " << LLImageGL::sBoundTextureMemory << llendl;
+ llinfos << "Num images: " << gTextureList.getNumImages() << llendl;
+ llinfos << "Texture usage: " << LLImageGL::sGlobalTextureMemoryInBytes << llendl;
+ llinfos << "Texture working set: " << LLImageGL::sBoundTextureMemoryInBytes << llendl;
llinfos << "Raw usage: " << LLImageRaw::sGlobalRawMemory << llendl;
llinfos << "Formatted usage: " << LLImageFormatted::sGlobalFormattedMemory << llendl;
llinfos << "Zombie Viewer Objects: " << LLViewerObject::getNumZombieObjects() << llendl;
@@ -449,10 +508,10 @@ void output_statistics(void*)
llinfos << "--------------------------------" << llendl;
llinfos << "Avatar Memory (partly overlaps with above stats):" << llendl;
- gTexStaticImageList.dumpByteCount();
- LLVOAvatar::dumpScratchTextureByteCount();
+ LLTexLayerStaticImageList::getInstance()->dumpByteCount();
+ LLVOAvatarSelf::dumpScratchTextureByteCount();
LLTexLayerSetBuffer::dumpTotalByteCount();
- LLVOAvatar::dumpTotalLocalTextureByteCount();
+ LLVOAvatarSelf::dumpTotalLocalTextureByteCount();
LLTexLayerParamAlpha::dumpCacheByteCount();
LLVOAvatar::dumpBakedStatus();
@@ -502,12 +561,18 @@ extern U32 gVisCompared;
extern U32 gVisTested;
std::map<S32,LLFrameTimer> gDebugTimers;
+std::map<S32,std::string> gDebugTimerLabel;
+
+void init_statistics()
+{
+ // Label debug timers
+ gDebugTimerLabel[0] = "Texture";
+}
void update_statistics(U32 frame_count)
{
gTotalWorldBytes += gVLManager.getTotalBytes();
gTotalObjectBytes += gObjectBits / 8;
- gTotalTextureBytes += LLViewerImageList::sTextureBits / 8;
// make sure we have a valid time delta for this frame
if (gFrameIntervalSeconds > 0.f)
@@ -520,7 +585,7 @@ void update_statistics(U32 frame_count)
{
LLViewerStats::getInstance()->incStat(LLViewerStats::ST_AVATAR_EDIT_SECONDS, gFrameIntervalSeconds);
}
- else if (gFloaterTools && gFloaterTools->getVisible())
+ else if (LLFloaterReg::instanceVisible("build"))
{
LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TOOLBOX_SECONDS, gFrameIntervalSeconds);
}
@@ -534,14 +599,14 @@ void update_statistics(U32 frame_count)
LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_AVATAR, (F64)gSavedSettings.getBOOL("VertexShaderLevelAvatar"));
LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_ENVIRONMENT, (F64)gSavedSettings.getBOOL("VertexShaderLevelEnvironment"));
#endif
- LLViewerStats::getInstance()->setStat(LLViewerStats::ST_FRAME_SECS, gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_FRAME));
- F64 idle_secs = gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_IDLE);
- F64 network_secs = gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_NETWORK);
+ LLViewerStats::getInstance()->setStat(LLViewerStats::ST_FRAME_SECS, gDebugView->mFastTimerView->getTime("Frame"));
+ F64 idle_secs = gDebugView->mFastTimerView->getTime("Idle");
+ F64 network_secs = gDebugView->mFastTimerView->getTime("Network");
LLViewerStats::getInstance()->setStat(LLViewerStats::ST_UPDATE_SECS, idle_secs - network_secs);
LLViewerStats::getInstance()->setStat(LLViewerStats::ST_NETWORK_SECS, network_secs);
- LLViewerStats::getInstance()->setStat(LLViewerStats::ST_IMAGE_SECS, gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_IMAGE_UPDATE));
- LLViewerStats::getInstance()->setStat(LLViewerStats::ST_REBUILD_SECS, gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_STATESORT ));
- LLViewerStats::getInstance()->setStat(LLViewerStats::ST_RENDER_SECS, gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_RENDER_GEOMETRY));
+ LLViewerStats::getInstance()->setStat(LLViewerStats::ST_IMAGE_SECS, gDebugView->mFastTimerView->getTime("Update Images"));
+ LLViewerStats::getInstance()->setStat(LLViewerStats::ST_REBUILD_SECS, gDebugView->mFastTimerView->getTime("Sort Draw State"));
+ LLViewerStats::getInstance()->setStat(LLViewerStats::ST_RENDER_SECS, gDebugView->mFastTimerView->getTime("Geometry"));
LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost());
if (cdp)
@@ -559,7 +624,6 @@ void update_statistics(U32 frame_count)
F32 layer_bits = (F32)(gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits());
LLViewerStats::getInstance()->mLayersKBitStat.addValue(layer_bits/1024.f);
LLViewerStats::getInstance()->mObjectKBitStat.addValue(gObjectBits/1024.f);
- LLViewerStats::getInstance()->mTextureKBitStat.addValue(LLViewerImageList::sTextureBits/1024.f);
LLViewerStats::getInstance()->mVFSPendingOperations.addValue(LLVFile::getVFSThread()->getPending());
LLViewerStats::getInstance()->mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET)/1024.f);
gTransferManager.resetTransferBitsIn(LLTCT_ASSET);
@@ -573,8 +637,6 @@ void update_statistics(U32 frame_count)
gDebugTimers[0].unpause();
}
- LLViewerStats::getInstance()->mTexturePacketsStat.addValue(LLViewerImageList::sTexturePackets);
-
{
static F32 visible_avatar_frames = 0.f;
static F32 avg_visible_avatars = 0;
@@ -594,15 +656,21 @@ void update_statistics(U32 frame_count)
gObjectBits = 0;
// gDecodedBits = 0;
- LLViewerImageList::sTextureBits = 0;
- LLViewerImageList::sTexturePackets = 0;
+ // Only update texture stats periodically so that they are less noisy
+ {
+ static const F32 texture_stats_freq = 10.f;
+ static LLFrameTimer texture_stats_timer;
+ if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq)
+ {
+ LLViewerStats::getInstance()->mTextureKBitStat.addValue(LLViewerTextureList::sTextureBits/1024.f);
+ LLViewerStats::getInstance()->mTexturePacketsStat.addValue(LLViewerTextureList::sTexturePackets);
+ gTotalTextureBytes += LLViewerTextureList::sTextureBits / 8;
+ LLViewerTextureList::sTextureBits = 0;
+ LLViewerTextureList::sTexturePackets = 0;
+ texture_stats_timer.reset();
+ }
+ }
-#if LL_LCD_COMPILE
- bool LCDenabled = gLcdScreen->Enabled();
- LLViewerStats::getInstance()->setStat(LLViewerStats::ST_LOGITECH_LCD, LCDenabled);
-#else
- LLViewerStats::getInstance()->setStat(LLViewerStats::ST_LOGITECH_LCD, false);
-#endif
}
class ViewerStatsResponder : public LLHTTPClient::Responder
@@ -692,7 +760,7 @@ void send_stats()
agent["ping"] = gAvgSimPing;
agent["meters_traveled"] = gAgent.getDistanceTraveled();
agent["regions_visited"] = gAgent.getRegionsVisited();
- agent["mem_use"] = getCurrentRSS() / 1024.0;
+ agent["mem_use"] = LLMemory::getCurrentRSS() / 1024.0;
LLSD &system = body["system"];
@@ -755,13 +823,11 @@ void send_stats()
// Screen size so the UI team can figure out how big the widgets
// appear and use a "typical" size for end user tests.
- S32 window_width = gViewerWindow->getWindowDisplayWidth();
- S32 window_height = gViewerWindow->getWindowDisplayHeight();
+ S32 window_width = gViewerWindow->getWindowWidthRaw();
+ S32 window_height = gViewerWindow->getWindowHeightRaw();
S32 window_size = (window_width * window_height) / 1024;
misc["string_1"] = llformat("%d", window_size);
// misc["string_2"] =
-// misc["int_1"] = LLFloaterDirectory::sOldSearchCount; // Steve: 1.18.6
-// misc["int_2"] = LLFloaterDirectory::sNewSearchCount; // Steve: 1.18.6
// misc["int_1"] = LLSD::Integer(gSavedSettings.getU32("RenderQualityPerformance")); // Steve: 1.21
// misc["int_2"] = LLSD::Integer(gFrameStalls); // Steve: 1.21
@@ -776,3 +842,4 @@ void send_stats()
LLViewerStats::getInstance()->addToMessage(body);
LLHTTPClient::post(url, body, new ViewerStatsResponder());
}
+
diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h
index d3fd4f2466..13d73000d2 100644
--- a/indra/newview/llviewerstats.h
+++ b/indra/newview/llviewerstats.h
@@ -34,6 +34,7 @@
#define LL_LLVIEWERSTATS_H
#include "llstat.h"
+#include "lltextureinfo.h"
class LLViewerStats : public LLSingleton<LLViewerStats>
{
@@ -57,6 +58,7 @@ public:
LLStat mTexturePacketsStat;
LLStat mActualInKBitStat; // From the packet ring (when faking a bad connection)
LLStat mActualOutKBitStat; // From the packet ring (when faking a bad connection)
+ LLStat mTrianglesDrawnStat;
// Simulator stats
LLStat mSimTimeDilation;
@@ -98,15 +100,22 @@ public:
LLStat mPhysicsPinnedTasks;
LLStat mPhysicsLODTasks;
LLStat mPhysicsMemoryAllocated;
- /*
- LLStat mSimCPUUsageStat;
- LLStat mSimMemTotalStat;
- LLStat mSimMemRSSStat;
- */
-
LLStat mSimPingStat;
+ LLStat mNumImagesStat;
+ LLStat mNumRawImagesStat;
+ LLStat mGLTexMemStat;
+ LLStat mGLBoundMemStat;
+ LLStat mRawMemStat;
+ LLStat mFormattedMemStat;
+
+ LLStat mNumObjectsStat;
+ LLStat mNumActiveObjectsStat;
+ LLStat mNumNewObjectsStat;
+ LLStat mNumSizeCulledStat;
+ LLStat mNumVisCulledStat;
+
void resetStats();
public:
// If you change this, please also add a corresponding text label
@@ -171,9 +180,8 @@ public:
ST_WINDOW_HEIGHT = 55,
ST_TEX_BAKES = 56,
ST_TEX_REBAKES = 57,
- ST_LOGITECH_LCD = 58,
- ST_COUNT = 59
+ ST_COUNT = 58
};
@@ -198,10 +206,13 @@ private:
static const F32 SEND_STATS_PERIOD = 300.0f;
// The following are from (older?) statistics code found in appviewer.
+void init_statistics();
void reset_statistics();
void output_statistics(void*);
void update_statistics(U32 frame_count);
void send_stats();
extern std::map<S32,LLFrameTimer> gDebugTimers;
+extern std::map<S32,std::string> gDebugTimerLabel;
+
#endif // LL_LLVIEWERSTATS_H
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index d64700b523..2e92512b31 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -32,38 +32,82 @@
#include "llviewerprecompiledheaders.h"
-#include "llfocusmgr.h"
-#include "audioengine.h"
-#include "llagent.h"
-#include "llinventory.h"
-#include "llinventorymodel.h"
-#include "llinventoryview.h"
-#include "llinventorybridge.h" // for landmark prefix string
-
#include "llviewertexteditor.h"
-#include "llfloaterchat.h"
+#include "llagent.h"
+#include "llaudioengine.h"
+#include "llavataractions.h"
+#include "llfloaterreg.h"
#include "llfloaterworldmap.h"
-#include "llnotify.h"
+#include "llfocusmgr.h"
+#include "llinventory.h"
+#include "llinventorybridge.h"
+#include "llinventorymodel.h"
+#include "lllandmark.h"
+#include "lllandmarkactions.h"
+#include "lllandmarklist.h"
+#include "llmemorystream.h"
+#include "llmenugl.h"
+#include "llnotecard.h"
+#include "llnotificationsutil.h"
+#include "llpanelplaces.h"
#include "llpreview.h"
-#include "llpreviewtexture.h"
#include "llpreviewnotecard.h"
-#include "llpreviewlandmark.h"
+#include "llpreviewtexture.h"
#include "llscrollbar.h"
+#include "llscrollcontainer.h"
+#include "llsidetray.h"
#include "lltooldraganddrop.h"
+#include "lltooltip.h"
+#include "lltrans.h"
+#include "lluictrlfactory.h"
+#include "llviewerassettype.h"
#include "llviewercontrol.h"
-#include "llviewerimagelist.h"
-#include "llviewerwindow.h"
#include "llviewerinventory.h"
-#include "lluictrlfactory.h"
-#include "llnotecard.h"
-#include "llmemorystream.h"
-#include "llmenugl.h"
+#include "llviewertexturelist.h"
+#include "llviewerwindow.h"
-#include "llappviewer.h" // for gPacificDaylightTime
+static LLDefaultChildRegistry::Register<LLViewerTextEditor> r("text_editor");
+
+///-----------------------------------------------------------------------
+/// Class LLEmbeddedLandmarkCopied
+///-----------------------------------------------------------------------
+class LLEmbeddedLandmarkCopied: public LLInventoryCallback
+{
+public:
-static LLRegisterWidget<LLViewerTextEditor> r("text_editor");
+ LLEmbeddedLandmarkCopied(){}
+ void fire(const LLUUID& inv_item)
+ {
+ showInfo(inv_item);
+ }
+ static void showInfo(const LLUUID& landmark_inv_id)
+ {
+ LLSD key;
+ key["type"] = "landmark";
+ key["id"] = landmark_inv_id;
+ LLSideTray::getInstance()->showPanel("panel_places", key);
+ }
+ static void processForeignLandmark(LLLandmark* landmark,
+ const LLUUID& object_id, const LLUUID& notecard_inventory_id,
+ LLInventoryItem* item)
+ {
+ LLVector3d global_pos;
+ landmark->getGlobalPos(global_pos);
+ LLViewerInventoryItem* agent_lanmark =
+ LLLandmarkActions::findLandmarkForGlobalPos(global_pos);
+ if (agent_lanmark)
+ {
+ showInfo(agent_lanmark->getUUID());
+ }
+ else
+ {
+ LLPointer<LLEmbeddedLandmarkCopied> cb = new LLEmbeddedLandmarkCopied();
+ copy_inventory_from_notecard(object_id, notecard_inventory_id, item, gInventoryCallbacks.registerCB(cb));
+ }
+ }
+};
///----------------------------------------------------------------------------
/// Class LLEmbeddedNotecardOpener
///----------------------------------------------------------------------------
@@ -96,36 +140,127 @@ public:
}
else
{
- // See if we can bring an existing preview to the front
- if(!LLPreview::show(item->getUUID(), true))
+ if(!gSavedSettings.getBOOL("ShowNewInventory"))
{
- if(!gSavedSettings.getBOOL("ShowNewInventory"))
- {
- // There isn't one, so make a new preview
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- LLRect rect = gSavedSettings.getRect("NotecardEditorRect");
- rect.translate(left - rect.mLeft, top - rect.mTop);
- LLPreviewNotecard* preview;
- preview = new LLPreviewNotecard("preview notecard",
- rect,
- std::string("Embedded Note: ") + item->getName(),
- item->getUUID(),
- LLUUID::null,
- item->getAssetUUID(),
- true,
- (LLViewerInventoryItem*)item);
- preview->setSourceID(LLUUID::null);
- preview->setFocus(TRUE);
-
- // Force to be entirely onscreen.
- gFloaterView->adjustToFitScreen(preview, FALSE);
- }
+ LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES);
}
}
}
};
+//
+// class LLEmbeddedItemSegment
+//
+
+const S32 EMBEDDED_ITEM_LABEL_PADDING = 2;
+
+class LLEmbeddedItemSegment : public LLTextSegment
+{
+public:
+ LLEmbeddedItemSegment(S32 pos, LLUIImagePtr image, LLPointer<LLInventoryItem> inv_item, LLTextEditor& editor)
+ : LLTextSegment(pos, pos + 1),
+ mImage(image),
+ mLabel(utf8str_to_wstring(inv_item->getName())),
+ mItem(inv_item),
+ mEditor(editor),
+ mHasMouseHover(false)
+ {
+
+ mStyle = new LLStyle(LLStyle::Params().font(LLFontGL::getFontSansSerif()));
+ mToolTip = inv_item->getName() + '\n' + inv_item->getDescription();
+ }
+
+ /*virtual*/ bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const
+ {
+ if (num_chars == 0)
+ {
+ width = 0;
+ height = 0;
+ }
+ else
+ {
+ width = EMBEDDED_ITEM_LABEL_PADDING + mImage->getWidth() + mStyle->getFont()->getWidth(mLabel.c_str());
+ height = llmax(mImage->getHeight(), llceil(mStyle->getFont()->getLineHeight()));
+ }
+ return false;
+ }
+
+ /*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const
+ {
+ // always draw at beginning of line
+ if (line_offset == 0)
+ {
+ return 1;
+ }
+ else
+ {
+ S32 width, height;
+ getDimensions(mStart, 1, width, height);
+ if (width > num_pixels)
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+ }
+ /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
+ {
+ LLRect image_rect = draw_rect;
+ image_rect.mRight = image_rect.mLeft + mImage->getWidth();
+ image_rect.mTop = image_rect.mBottom + mImage->getHeight();
+ mImage->draw(image_rect);
+
+ LLColor4 color;
+ if (mEditor.getReadOnly())
+ {
+ color = LLUIColorTable::instance().getColor("TextEmbeddedItemReadOnlyColor");
+ }
+ else
+ {
+ color = LLUIColorTable::instance().getColor("TextEmbeddedItemColor");
+ }
+
+ F32 right_x;
+ mStyle->getFont()->render(mLabel, 0, image_rect.mRight + EMBEDDED_ITEM_LABEL_PADDING, draw_rect.mTop, color, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::UNDERLINE, LLFontGL::NO_SHADOW, mLabel.length(), S32_MAX, &right_x);
+ return right_x;
+ }
+
+ /*virtual*/ bool canEdit() const { return false; }
+
+
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask)
+ {
+ LLUI::getWindow()->setCursor(UI_CURSOR_HAND);
+ return TRUE;
+ }
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask )
+ {
+ if (!mToolTip.empty())
+ {
+ LLToolTipMgr::instance().show(mToolTip);
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ /*virtual*/ const LLStyleSP getStyle() const { return mStyle; }
+
+private:
+ LLUIImagePtr mImage;
+ LLWString mLabel;
+ LLStyleSP mStyle;
+ std::string mToolTip;
+ LLPointer<LLInventoryItem> mItem;
+ LLTextEditor& mEditor;
+ bool mHasMouseHover;
+
+};
+
+
+
////////////////////////////////////////////////////////////
// LLEmbeddedItems
//
@@ -148,13 +283,11 @@ public:
// return true if there are no embedded items.
bool empty();
- void bindEmbeddedChars(const LLFontGL* font) const;
- void unbindEmbeddedChars(const LLFontGL* font) const;
-
BOOL insertEmbeddedItem(LLInventoryItem* item, llwchar* value, bool is_new);
BOOL removeEmbeddedItem( llwchar ext_char );
BOOL hasEmbeddedItem(llwchar ext_char); // returns TRUE if /this/ editor has an entry for this item
+ LLUIImagePtr getItemImage(llwchar ext_char) const;
void getEmbeddedItemList( std::vector<LLPointer<LLInventoryItem> >& items );
void addItems(const std::vector<LLPointer<LLInventoryItem> >& items);
@@ -369,88 +502,44 @@ BOOL LLEmbeddedItems::hasEmbeddedItem(llwchar ext_char)
return FALSE;
}
-void LLEmbeddedItems::bindEmbeddedChars( const LLFontGL* font ) const
-{
- if( sEntries.empty() )
- {
- return;
- }
- for (std::set<llwchar>::const_iterator iter1 = mEmbeddedUsedChars.begin(); iter1 != mEmbeddedUsedChars.end(); ++iter1)
+LLUIImagePtr LLEmbeddedItems::getItemImage(llwchar ext_char) const
+{
+ LLInventoryItem* item = getEmbeddedItem(ext_char);
+ if (item)
{
- llwchar wch = *iter1;
- item_map_t::iterator iter2 = sEntries.find(wch);
- if (iter2 == sEntries.end())
- {
- continue;
- }
- LLInventoryItem* item = iter2->second.mItem;
- if (!item)
- {
- continue;
- }
- const char* img_name;
+ const char* img_name = "";
switch( item->getType() )
{
- case LLAssetType::AT_TEXTURE:
- if(item->getInventoryType() == LLInventoryType::IT_SNAPSHOT)
- {
- img_name = "inv_item_snapshot.tga";
- }
- else
- {
- img_name = "inv_item_texture.tga";
- }
+ case LLAssetType::AT_TEXTURE:
+ if(item->getInventoryType() == LLInventoryType::IT_SNAPSHOT)
+ {
+ img_name = "Inv_Snapshot";
+ }
+ else
+ {
+ img_name = "Inv_Texture";
+ }
- break;
- case LLAssetType::AT_SOUND: img_name = "inv_item_sound.tga"; break;
- case LLAssetType::AT_LANDMARK:
- if (item->getFlags() & LLInventoryItem::II_FLAGS_LANDMARK_VISITED)
- {
- img_name = "inv_item_landmark_visited.tga";
- }
- else
- {
- img_name = "inv_item_landmark.tga";
- }
- break;
- case LLAssetType::AT_CLOTHING: img_name = "inv_item_clothing.tga"; break;
- case LLAssetType::AT_OBJECT:
- if (item->getFlags() & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS)
- {
- img_name = "inv_item_object_multi.tga";
- }
- else
- {
- img_name = "inv_item_object.tga";
- }
- break;
- case LLAssetType::AT_NOTECARD: img_name = "inv_item_notecard.tga"; break;
- case LLAssetType::AT_LSL_TEXT: img_name = "inv_item_script.tga"; break;
- case LLAssetType::AT_BODYPART: img_name = "inv_item_skin.tga"; break;
- case LLAssetType::AT_ANIMATION: img_name = "inv_item_animation.tga";break;
- case LLAssetType::AT_GESTURE: img_name = "inv_item_gesture.tga"; break;
- default: llassert(0); continue;
+ break;
+ case LLAssetType::AT_SOUND: img_name = "Inv_Sound"; break;
+ case LLAssetType::AT_CLOTHING: img_name = "Inv_Clothing"; break;
+ case LLAssetType::AT_OBJECT: img_name = "Inv_Object"; break;
+ case LLAssetType::AT_CALLINGCARD: img_name = "Inv_CallingCard"; break;
+ case LLAssetType::AT_LANDMARK: img_name = "Inv_Landmark"; break;
+ case LLAssetType::AT_NOTECARD: img_name = "Inv_Notecard"; break;
+ case LLAssetType::AT_LSL_TEXT: img_name = "Inv_Script"; break;
+ case LLAssetType::AT_BODYPART: img_name = "Inv_Skin"; break;
+ case LLAssetType::AT_ANIMATION: img_name = "Inv_Animation"; break;
+ case LLAssetType::AT_GESTURE: img_name = "Inv_Gesture"; break;
+ default: llassert(0);
}
- LLUIImagePtr image = LLUI::getUIImage(img_name);
-
- font->addEmbeddedChar( wch, image->getImage(), item->getName() );
+ return LLUI::getUIImage(img_name);
}
+ return LLUIImagePtr();
}
-void LLEmbeddedItems::unbindEmbeddedChars( const LLFontGL* font ) const
-{
- if( sEntries.empty() )
- {
- return;
- }
-
- for (std::set<llwchar>::const_iterator iter1 = mEmbeddedUsedChars.begin(); iter1 != mEmbeddedUsedChars.end(); ++iter1)
- {
- font->removeEmbeddedChar(*iter1);
- }
-}
void LLEmbeddedItems::addItems(const std::vector<LLPointer<LLInventoryItem> >& items)
{
@@ -494,17 +583,17 @@ void LLEmbeddedItems::markSaved()
///////////////////////////////////////////////////////////////////
-class LLViewerTextEditor::LLTextCmdInsertEmbeddedItem : public LLTextEditor::LLTextCmd
+class LLViewerTextEditor::TextCmdInsertEmbeddedItem : public LLTextBase::TextCmd
{
public:
- LLTextCmdInsertEmbeddedItem( S32 pos, LLInventoryItem* item )
- : LLTextCmd(pos, FALSE),
+ TextCmdInsertEmbeddedItem( S32 pos, LLInventoryItem* item )
+ : TextCmd(pos, FALSE),
mExtCharValue(0)
{
mItem = item;
}
- virtual BOOL execute( LLTextEditor* editor, S32* delta )
+ virtual BOOL execute( LLTextBase* editor, S32* delta )
{
LLViewerTextEditor* viewer_editor = (LLViewerTextEditor*)editor;
// Take this opportunity to remove any unused embedded items from this editor
@@ -519,13 +608,13 @@ public:
return FALSE;
}
- virtual S32 undo( LLTextEditor* editor )
+ virtual S32 undo( LLTextBase* editor )
{
remove(editor, getPosition(), 1);
return getPosition();
}
- virtual S32 redo( LLTextEditor* editor )
+ virtual S32 redo( LLTextBase* editor )
{
LLWString ws;
ws += mExtCharValue;
@@ -561,33 +650,14 @@ struct LLNotecardCopyInfo
//
// Member functions
//
-
-LLViewerTextEditor::LLViewerTextEditor(const std::string& name,
- const LLRect& rect,
- S32 max_length,
- const std::string& default_text,
- const LLFontGL* font,
- BOOL allow_embedded_items)
- : LLTextEditor(name, rect, max_length, default_text, font, allow_embedded_items),
- mDragItemChar(0),
- mDragItemSaved(FALSE),
- mInventoryCallback(new LLEmbeddedNotecardOpener)
+LLViewerTextEditor::LLViewerTextEditor(const LLViewerTextEditor::Params& p)
+: LLTextEditor(p),
+ mDragItemChar(0),
+ mDragItemSaved(FALSE),
+ mInventoryCallback(new LLEmbeddedNotecardOpener)
{
mEmbeddedItemList = new LLEmbeddedItems(this);
mInventoryCallback->setEditor(this);
-
- // *TODO: Add right click menus for SLURLs
- // Build the right click menu
- // make the popup menu available
-
- //LLMenuGL* menu = LLUICtrlFactory::getInstance()->buildMenu("menu_slurl.xml", this);
- //if (!menu)
- //{
- // menu = new LLMenuGL(LLStringUtil::null);
- //}
- //menu->setBackgroundColor(gColors.getColor("MenuPopupBgColor"));
- //// menu->setVisible(FALSE);
- //mPopupMenuHandle = menu->getHandle();
}
LLViewerTextEditor::~LLViewerTextEditor()
@@ -608,59 +678,6 @@ void LLViewerTextEditor::makePristine()
LLTextEditor::makePristine();
}
-///////////////////////////////////////////////////////////////////
-
-BOOL LLViewerTextEditor::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
-{
- for (child_list_const_iter_t child_iter = getChildList()->begin();
- child_iter != getChildList()->end(); ++child_iter)
- {
- LLView *viewp = *child_iter;
- S32 local_x = x - viewp->getRect().mLeft;
- S32 local_y = y - viewp->getRect().mBottom;
- if( viewp->pointInView(local_x, local_y)
- && viewp->getVisible()
- && viewp->getEnabled()
- && viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ) )
- {
- return TRUE;
- }
- }
-
- if( mSegments.empty() )
- {
- return TRUE;
- }
-
- const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
- if( cur_segment )
- {
- BOOL has_tool_tip = FALSE;
- if( cur_segment->getStyle()->getIsEmbeddedItem() )
- {
- LLWString wtip;
- has_tool_tip = getEmbeddedItemToolTipAtPos(cur_segment->getStart(), wtip);
- msg = wstring_to_utf8str(wtip);
- }
- else
- {
- has_tool_tip = cur_segment->getToolTip( msg );
- }
- if( has_tool_tip )
- {
- // Just use a slop area around the cursor
- // Convert rect local to screen coordinates
- S32 SLOP = 8;
- localPointToScreen(
- x - SLOP, y - SLOP,
- &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
- sticky_rect_screen->mRight = sticky_rect_screen->mLeft + 2 * SLOP;
- sticky_rect_screen->mTop = sticky_rect_screen->mBottom + 2 * SLOP;
- }
- }
- return TRUE;
-}
-
BOOL LLViewerTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
@@ -668,28 +685,15 @@ BOOL LLViewerTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
// Let scrollbar have first dibs
handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL;
- // enable I Agree checkbox if the user scrolled through entire text
- BOOL was_scrolled_to_bottom = (mScrollbar->getDocPos() == mScrollbar->getDocPosMax());
- if (mOnScrollEndCallback && was_scrolled_to_bottom)
+ if( !handled)
{
- mOnScrollEndCallback(mOnScrollEndData);
- }
-
- if( !handled && mTakesNonScrollClicks)
- {
- if (!(mask & MASK_SHIFT))
- {
- deselect();
- }
-
- BOOL start_select = TRUE;
if( allowsEmbeddedItems() )
{
setCursorAtLocalPos( x, y, FALSE );
llwchar wc = 0;
if (mCursorPos < getLength())
{
- wc = getWChar(mCursorPos);
+ wc = getWText()[mCursorPos];
}
LLInventoryItem* item_at_pos = LLEmbeddedItems::getEmbeddedItem(wc);
if (item_at_pos)
@@ -705,191 +709,54 @@ BOOL LLViewerTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
localPointToScreen(x, y, &screen_x, &screen_y );
LLToolDragAndDrop::getInstance()->setDragStart( screen_x, screen_y );
- start_select = FALSE;
- }
- else
- {
- mDragItem = NULL;
- }
- }
-
- if( start_select )
- {
- // If we're not scrolling (handled by child), then we're selecting
- if (mask & MASK_SHIFT)
- {
- S32 old_cursor_pos = mCursorPos;
- setCursorAtLocalPos( x, y, TRUE );
-
- if (hasSelection())
+ if (hasTabStop())
{
- /* Mac-like behavior - extend selection towards the cursor
- if (mCursorPos < mSelectionStart
- && mCursorPos < mSelectionEnd)
- {
- // ...left of selection
- mSelectionStart = llmax(mSelectionStart, mSelectionEnd);
- mSelectionEnd = mCursorPos;
- }
- else if (mCursorPos > mSelectionStart
- && mCursorPos > mSelectionEnd)
- {
- // ...right of selection
- mSelectionStart = llmin(mSelectionStart, mSelectionEnd);
- mSelectionEnd = mCursorPos;
- }
- else
- {
- mSelectionEnd = mCursorPos;
- }
- */
- // Windows behavior
- mSelectionEnd = mCursorPos;
- }
- else
- {
- mSelectionStart = old_cursor_pos;
- mSelectionEnd = mCursorPos;
+ setFocus( TRUE );
}
- // assume we're starting a drag select
- mIsSelecting = TRUE;
+ handled = TRUE;
}
else
{
- setCursorAtLocalPos( x, y, TRUE );
- startSelection();
+ mDragItem = NULL;
}
- gFocusMgr.setMouseCapture( this );
}
- handled = TRUE;
- }
-
- if (hasTabStop())
- {
- setFocus(TRUE);
- handled = TRUE;
+ if (!handled)
+ {
+ handled = LLTextEditor::handleMouseDown(x, y, mask);
+ }
}
- // Delay cursor flashing
- resetKeystrokeTimer();
-
return handled;
}
BOOL LLViewerTextEditor::handleHover(S32 x, S32 y, MASK mask)
{
- BOOL handled = FALSE;
+ BOOL handled = LLTextEditor::handleHover(x, y, mask);
- if (!mDragItem)
+ if(hasMouseCapture() && mDragItem)
{
- // leave hover segment active during drag and drop
- mHoverSegment = NULL;
- }
- if(hasMouseCapture() )
- {
- if( mIsSelecting )
- {
- if (x != mLastSelectionX || y != mLastSelectionY)
- {
- mLastSelectionX = x;
- mLastSelectionY = y;
- }
+ S32 screen_x;
+ S32 screen_y;
+ localPointToScreen(x, y, &screen_x, &screen_y );
- if( y > getTextRect().mTop )
- {
- mScrollbar->setDocPos( mScrollbar->getDocPos() - 1 );
- }
- else
- if( y < getTextRect().mBottom )
- {
- mScrollbar->setDocPos( mScrollbar->getDocPos() + 1 );
- }
+ mScroller->autoScroll(x, y);
- setCursorAtLocalPos( x, y, TRUE );
- mSelectionEnd = mCursorPos;
-
- updateScrollFromCursor();
- getWindow()->setCursor(UI_CURSOR_IBEAM);
- }
- else if( mDragItem )
+ if( LLToolDragAndDrop::getInstance()->isOverThreshold( screen_x, screen_y ) )
{
- S32 screen_x;
- S32 screen_y;
- localPointToScreen(x, y, &screen_x, &screen_y );
- if( LLToolDragAndDrop::getInstance()->isOverThreshold( screen_x, screen_y ) )
- {
- LLToolDragAndDrop::getInstance()->beginDrag(
- LLAssetType::lookupDragAndDropType( mDragItem->getType() ),
- mDragItem->getUUID(),
- LLToolDragAndDrop::SOURCE_NOTECARD,
- getSourceID(), mObjectID);
-
- return LLToolDragAndDrop::getInstance()->handleHover( x, y, mask );
- }
- getWindow()->setCursor(UI_CURSOR_HAND);
+ LLToolDragAndDrop::getInstance()->beginDrag(
+ LLViewerAssetType::lookupDragAndDropType( mDragItem->getType() ),
+ mDragItem->getUUID(),
+ LLToolDragAndDrop::SOURCE_NOTECARD,
+ mPreviewID, mObjectID);
+ return LLToolDragAndDrop::getInstance()->handleHover( x, y, mask );
}
-
- lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" << llendl;
+ getWindow()->setCursor(UI_CURSOR_HAND);
handled = TRUE;
}
- if( !handled )
- {
- // Pass to children
- handled = LLView::childrenHandleHover(x, y, mask) != NULL;
- }
-
- if( handled )
- {
- // Delay cursor flashing
- resetKeystrokeTimer();
- }
-
- // Opaque
- if( !handled && mTakesNonScrollClicks)
- {
- // Check to see if we're over an HTML-style link
- if( !mSegments.empty() )
- {
- const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
- if( cur_segment )
- {
- if(cur_segment->getStyle()->isLink())
- {
- lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (over link, inactive)" << llendl;
- getWindow()->setCursor(UI_CURSOR_HAND);
- handled = TRUE;
- }
- else
- if(cur_segment->getStyle()->getIsEmbeddedItem())
- {
- lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (over embedded item, inactive)" << llendl;
- getWindow()->setCursor(UI_CURSOR_HAND);
- //getWindow()->setCursor(UI_CURSOR_ARROW);
- handled = TRUE;
- }
- mHoverSegment = cur_segment;
- }
- }
-
- if( !handled )
- {
- lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (inactive)" << llendl;
- if (!mScrollbar->getVisible() || x < getRect().getWidth() - SCROLLBAR_SIZE)
- {
- getWindow()->setCursor(UI_CURSOR_IBEAM);
- }
- else
- {
- getWindow()->setCursor(UI_CURSOR_ARROW);
- }
- handled = TRUE;
- }
- }
-
return handled;
}
@@ -922,67 +789,6 @@ BOOL LLViewerTextEditor::handleMouseUp(S32 x, S32 y, MASK mask)
handled = LLTextEditor::handleMouseUp(x,y,mask);
- // Used to enable I Agree checkbox if the user scrolled through entire text
- BOOL was_scrolled_to_bottom = (mScrollbar->getDocPos() == mScrollbar->getDocPosMax());
- if (mOnScrollEndCallback && was_scrolled_to_bottom)
- {
- mOnScrollEndCallback(mOnScrollEndData);
- }
-
- return handled;
-}
-
-BOOL LLViewerTextEditor::handleRightMouseDown(S32 x, S32 y, MASK mask)
-{
- BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL;
-
- // *TODO: Add right click menus for SLURLs
-// if(! handled)
-// {
-// const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
-// if( cur_segment )
-// {
-// if(cur_segment->getStyle()->isLink())
-// {
-// handled = TRUE;
-// mHTML = cur_segment->getStyle()->getLinkHREF();
-// }
-// }
-// }
-// LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
-// if(handled && menu && mParseHTML && mHTML.length() > 0)
-// {
-// menu->setVisible(TRUE);
-// menu->arrange();
-// menu->updateParent(LLMenuGL::sMenuContainer);
-// LLMenuGL::showPopup(this, menu, x, y);
-// mHTML = "";
-// }
-// else
-// {
-// if(menu && menu->getVisible())
-// {
-// menu->setVisible(FALSE);
-// }
-// }
- return handled;
-}
-
-BOOL LLViewerTextEditor::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
-{
- BOOL handled = FALSE;
- handled = childrenHandleMiddleMouseDown(x, y, mask) != NULL;
- if (!handled)
- {
- handled = LLTextEditor::handleMiddleMouseDown(x, y, mask);
- }
- return handled;
-}
-
-BOOL LLViewerTextEditor::handleMiddleMouseUp(S32 x, S32 y, MASK mask)
-{
- BOOL handled = childrenHandleMiddleMouseUp(x, y, mask) != NULL;
-
return handled;
}
@@ -993,14 +799,15 @@ BOOL LLViewerTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
// let scrollbar have first dibs
handled = LLView::childrenHandleDoubleClick(x, y, mask) != NULL;
- if( !handled && mTakesNonScrollClicks)
+ if( !handled)
{
if( allowsEmbeddedItems() )
{
- const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
- if( cur_segment && cur_segment->getStyle()->getIsEmbeddedItem() )
+ S32 doc_index = getDocIndexFromLocalCoord(x, y, FALSE);
+ llwchar doc_char = getWText()[doc_index];
+ if (mEmbeddedItemList->hasEmbeddedItem(doc_char))
{
- if( openEmbeddedItemAtPos( cur_segment->getStart() ) )
+ if( openEmbeddedItemAtPos( doc_index ))
{
deselect();
setFocus( FALSE );
@@ -1008,54 +815,12 @@ BOOL LLViewerTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
}
}
}
-
- setCursorAtLocalPos( x, y, FALSE );
- deselect();
-
- const LLWString &text = getWText();
-
- if( isPartOfWord( text[mCursorPos] ) )
- {
- // Select word the cursor is over
- while ((mCursorPos > 0) && isPartOfWord(text[mCursorPos-1]))
- {
- mCursorPos--;
- }
- startSelection();
-
- while ((mCursorPos < (S32)text.length()) && isPartOfWord( text[mCursorPos] ) )
- {
- mCursorPos++;
- }
-
- mSelectionEnd = mCursorPos;
- }
- else if ((mCursorPos < (S32)text.length()) && !iswspace( text[mCursorPos]) )
- {
- // Select the character the cursor is over
- startSelection();
- mCursorPos++;
- mSelectionEnd = mCursorPos;
- }
-
- // We don't want handleMouseUp() to "finish" the selection (and thereby
- // set mSelectionEnd to where the mouse is), so we finish the selection here.
- mIsSelecting = FALSE;
-
- // delay cursor flashing
- resetKeystrokeTimer();
-
- // take selection to 'primary' clipboard
- updatePrimary();
-
- handled = TRUE;
+ handled = LLTextEditor::handleDoubleClick(x, y, mask);
}
return handled;
}
-// Allow calling cards to be dropped onto text fields. Append the name and
-// a carriage return.
// virtual
BOOL LLViewerTextEditor::handleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL drop, EDragAndDropType cargo_type, void *cargo_data,
@@ -1072,95 +837,78 @@ BOOL LLViewerTextEditor::handleDragAndDrop(S32 x, S32 y, MASK mask,
return FALSE;
}
- if (mTakesNonScrollClicks)
+ if (getEnabled() && acceptsTextInput())
{
- if (getEnabled() && acceptsTextInput())
+ switch( cargo_type )
{
- switch( cargo_type )
+ case DAD_CALLINGCARD:
+ case DAD_TEXTURE:
+ case DAD_SOUND:
+ case DAD_LANDMARK:
+ case DAD_SCRIPT:
+ case DAD_CLOTHING:
+ case DAD_OBJECT:
+ case DAD_NOTECARD:
+ case DAD_BODYPART:
+ case DAD_ANIMATION:
+ case DAD_GESTURE:
{
- case DAD_CALLINGCARD:
- if(acceptsCallingCardNames())
+ LLInventoryItem *item = (LLInventoryItem *)cargo_data;
+ if( item && allowsEmbeddedItems() )
{
- if (drop)
+ U32 mask_next = item->getPermissions().getMaskNextOwner();
+ if((mask_next & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
{
- LLInventoryItem *item = (LLInventoryItem *)cargo_data;
- std::string name = item->getName();
- appendText(name, true, true);
- }
- *accept = ACCEPT_YES_COPY_SINGLE;
- }
- else
- {
- *accept = ACCEPT_NO;
- }
- break;
-
- case DAD_TEXTURE:
- case DAD_SOUND:
- case DAD_LANDMARK:
- case DAD_SCRIPT:
- case DAD_CLOTHING:
- case DAD_OBJECT:
- case DAD_NOTECARD:
- case DAD_BODYPART:
- case DAD_ANIMATION:
- case DAD_GESTURE:
- {
- LLInventoryItem *item = (LLInventoryItem *)cargo_data;
- if( item && allowsEmbeddedItems() )
- {
- U32 mask_next = item->getPermissions().getMaskNextOwner();
- if((mask_next & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
- {
- if( drop )
- {
- deselect();
- S32 old_cursor = mCursorPos;
- setCursorAtLocalPos( x, y, TRUE );
- S32 insert_pos = mCursorPos;
- setCursorPos(old_cursor);
- BOOL inserted = insertEmbeddedItem( insert_pos, item );
- if( inserted && (old_cursor > mCursorPos) )
- {
- setCursorPos(mCursorPos + 1);
- }
-
- updateLineStartList();
- }
- *accept = ACCEPT_YES_COPY_MULTI;
- }
- else
+ if( drop )
{
- *accept = ACCEPT_NO;
- if (tooltip_msg.empty())
+ deselect();
+ S32 old_cursor = mCursorPos;
+ setCursorAtLocalPos( x, y, TRUE );
+ S32 insert_pos = mCursorPos;
+ setCursorPos(old_cursor);
+ BOOL inserted = insertEmbeddedItem( insert_pos, item );
+ if( inserted && (old_cursor > mCursorPos) )
{
- tooltip_msg.assign("Only items with unrestricted\n"
- "'next owner' permissions \n"
- "can be attached to notecards.");
+ setCursorPos(mCursorPos + 1);
}
+
+ needsReflow();
+
}
+ *accept = ACCEPT_YES_COPY_MULTI;
}
else
{
*accept = ACCEPT_NO;
+ if (tooltip_msg.empty())
+ {
+ // *TODO: Translate
+ tooltip_msg.assign("Only items with unrestricted\n"
+ "'next owner' permissions \n"
+ "can be attached to notecards.");
+ }
}
- break;
}
-
- default:
- *accept = ACCEPT_NO;
+ else
+ {
+ *accept = ACCEPT_NO;
+ }
break;
}
- }
- else
- {
- // Not enabled
+
+ default:
*accept = ACCEPT_NO;
+ break;
}
-
- handled = TRUE;
- lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLViewerTextEditor " << getName() << llendl;
}
+ else
+ {
+ // Not enabled
+ *accept = ACCEPT_NO;
+ }
+
+ handled = TRUE;
+ lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLViewerTextEditor " << getName() << llendl;
return handled;
}
@@ -1210,7 +958,7 @@ std::string LLViewerTextEditor::getEmbeddedText()
LLWString outtextw;
for (S32 i=0; i<(S32)getWText().size(); i++)
{
- llwchar wch = getWChar(i);
+ llwchar wch = getWText()[i];
if( wch >= FIRST_EMBEDDED_CHAR && wch <= LAST_EMBEDDED_CHAR )
{
S32 index = mEmbeddedItemList->getIndexFromEmbeddedChar(wch);
@@ -1246,18 +994,17 @@ std::string LLViewerTextEditor::appendTime(bool prepend_newline)
{
time_t utc_time;
utc_time = time_corrected();
+ std::string timeStr ="[["+ LLTrans::getString("TimeHour")+"]:["
+ +LLTrans::getString("TimeMin")+"]] ";
- // There's only one internal tm buffer.
- struct tm* timep;
-
- // Convert to Pacific, based on server's opinion of whether
- // it's daylight savings time there.
- timep = utc_to_pacific_time(utc_time, gPacificDaylightTime);
+ LLSD substitution;
- std::string text = llformat("[%d:%02d] ", timep->tm_hour, timep->tm_min);
- appendColoredText(text, false, prepend_newline, LLColor4::grey);
+ substitution["datetime"] = (S32) utc_time;
+ LLStringUtil::format (timeStr, substitution);
+ appendText(timeStr, prepend_newline, LLStyle::Params().color(LLColor4::grey));
+ blockUndo();
- return text;
+ return timeStr;
}
//----------------------------------------------------------------------------
@@ -1282,38 +1029,39 @@ llwchar LLViewerTextEditor::pasteEmbeddedItem(llwchar ext_char)
return LL_UNKNOWN_CHAR; // item not found or list full
}
-void LLViewerTextEditor::bindEmbeddedChars(const LLFontGL* font) const
+void LLViewerTextEditor::onValueChange(S32 start, S32 end)
{
- mEmbeddedItemList->bindEmbeddedChars( font );
+ updateSegments();
+ updateLinkSegments();
+ findEmbeddedItemSegments(start, end);
}
-void LLViewerTextEditor::unbindEmbeddedChars(const LLFontGL* font) const
+void LLViewerTextEditor::findEmbeddedItemSegments(S32 start, S32 end)
{
- mEmbeddedItemList->unbindEmbeddedChars( font );
-}
+ LLWString text = getWText();
-BOOL LLViewerTextEditor::getEmbeddedItemToolTipAtPos(S32 pos, LLWString &msg) const
-{
- if (pos < getLength())
+ LLColor4 text_color = ( mReadOnly ? mReadOnlyFgColor.get() : mFgColor.get() );
+
+ // Start with i just after the first embedded item
+ for(S32 idx = start; idx < end; idx++ )
{
- LLInventoryItem* item = LLEmbeddedItems::getEmbeddedItem(getWChar(pos));
- if( item )
+ llwchar embedded_char = text[idx];
+ if( embedded_char >= FIRST_EMBEDDED_CHAR
+ && embedded_char <= LAST_EMBEDDED_CHAR
+ && mEmbeddedItemList->hasEmbeddedItem(embedded_char) )
{
- msg = utf8str_to_wstring(item->getName());
- msg += '\n';
- msg += utf8str_to_wstring(item->getDescription());
- return TRUE;
+ LLInventoryItem* itemp = mEmbeddedItemList->getEmbeddedItem(embedded_char);
+ LLUIImagePtr image = mEmbeddedItemList->getItemImage(embedded_char);
+ insertSegment(new LLEmbeddedItemSegment(idx, image, itemp, *this));
}
}
- return FALSE;
}
-
BOOL LLViewerTextEditor::openEmbeddedItemAtPos(S32 pos)
{
if( pos < getLength())
{
- llwchar wc = getWChar(pos);
+ llwchar wc = getWText()[pos];
LLInventoryItem* item = LLEmbeddedItems::getEmbeddedItem( wc );
if( item )
{
@@ -1337,32 +1085,36 @@ BOOL LLViewerTextEditor::openEmbeddedItem(LLInventoryItem* item, llwchar wc)
switch( item->getType() )
{
- case LLAssetType::AT_TEXTURE:
- openEmbeddedTexture( item, wc );
- return TRUE;
+ case LLAssetType::AT_TEXTURE:
+ openEmbeddedTexture( item, wc );
+ return TRUE;
- case LLAssetType::AT_SOUND:
- openEmbeddedSound( item, wc );
- return TRUE;
+ case LLAssetType::AT_SOUND:
+ openEmbeddedSound( item, wc );
+ return TRUE;
- case LLAssetType::AT_NOTECARD:
- openEmbeddedNotecard( item, wc );
- return TRUE;
+ case LLAssetType::AT_NOTECARD:
+ openEmbeddedNotecard( item, wc );
+ return TRUE;
- case LLAssetType::AT_LANDMARK:
- openEmbeddedLandmark( item, wc );
- return TRUE;
+ case LLAssetType::AT_LANDMARK:
+ openEmbeddedLandmark( item, wc );
+ return TRUE;
- case LLAssetType::AT_LSL_TEXT:
- case LLAssetType::AT_CLOTHING:
- case LLAssetType::AT_OBJECT:
- case LLAssetType::AT_BODYPART:
- case LLAssetType::AT_ANIMATION:
- case LLAssetType::AT_GESTURE:
- showCopyToInvDialog( item, wc );
- return TRUE;
- default:
- return FALSE;
+ case LLAssetType::AT_CALLINGCARD:
+ openEmbeddedCallingcard( item, wc );
+ return TRUE;
+
+ case LLAssetType::AT_LSL_TEXT:
+ case LLAssetType::AT_CLOTHING:
+ case LLAssetType::AT_OBJECT:
+ case LLAssetType::AT_BODYPART:
+ case LLAssetType::AT_ANIMATION:
+ case LLAssetType::AT_GESTURE:
+ showCopyToInvDialog( item, wc );
+ return TRUE;
+ default:
+ return FALSE;
}
}
@@ -1370,29 +1122,16 @@ BOOL LLViewerTextEditor::openEmbeddedItem(LLInventoryItem* item, llwchar wc)
void LLViewerTextEditor::openEmbeddedTexture( LLInventoryItem* item, llwchar wc )
{
- // See if we can bring an existing preview to the front
// *NOTE: Just for embedded Texture , we should use getAssetUUID(),
// not getUUID(), because LLPreviewTexture pass in AssetUUID into
// LLPreview constructor ItemUUID parameter.
-
- if( !LLPreview::show( item->getAssetUUID() ) )
+ if (!item)
+ return;
+ LLPreviewTexture* preview = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", LLSD(item->getAssetUUID()), TAKE_FOCUS_YES);
+ if (preview)
{
- // There isn't one, so make a new preview
- if(item)
- {
- S32 left, top;
- gFloaterView->getNewFloaterPosition(&left, &top);
- LLRect rect = gSavedSettings.getRect("PreviewTextureRect");
- rect.translate( left - rect.mLeft, top - rect.mTop );
-
- LLPreviewTexture* preview = new LLPreviewTexture("preview texture",
- rect,
- item->getName(),
- item->getAssetUUID(),
- TRUE);
- preview->setAuxItem( item );
- preview->setNotecardInfo(mNotecardInventoryID, mObjectID);
- }
+ preview->setAuxItem( item );
+ preview->setNotecardInfo(mNotecardInventoryID, mObjectID);
}
}
@@ -1411,9 +1150,16 @@ void LLViewerTextEditor::openEmbeddedSound( LLInventoryItem* item, llwchar wc )
void LLViewerTextEditor::openEmbeddedLandmark( LLInventoryItem* item, llwchar wc )
{
- std::string title =
- std::string(" ") + LLLandmarkBridge::prefix() + item->getName();
- open_landmark((LLViewerInventoryItem*)item, title, FALSE, item->getUUID(), TRUE);
+ if (!item)
+ return;
+
+ LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID(),
+ boost::bind(&LLEmbeddedLandmarkCopied::processForeignLandmark, _1, mObjectID, mNotecardInventoryID, item));
+ if (landmark)
+ {
+ LLEmbeddedLandmarkCopied::processForeignLandmark(landmark, mObjectID,
+ mNotecardInventoryID, item);
+ }
}
void LLViewerTextEditor::openEmbeddedNotecard( LLInventoryItem* item, llwchar wc )
@@ -1421,23 +1167,33 @@ void LLViewerTextEditor::openEmbeddedNotecard( LLInventoryItem* item, llwchar wc
copyInventory(item, gInventoryCallbacks.registerCB(mInventoryCallback));
}
+void LLViewerTextEditor::openEmbeddedCallingcard( LLInventoryItem* item, llwchar wc )
+{
+ if(item && !item->getCreatorUUID().isNull())
+ {
+ LLAvatarActions::showProfile(item->getCreatorUUID());
+ }
+}
+
void LLViewerTextEditor::showUnsavedAlertDialog( LLInventoryItem* item )
{
LLSD payload;
payload["item_id"] = item->getUUID();
payload["notecard_id"] = mNotecardInventoryID;
- LLNotifications::instance().add( "ConfirmNotecardSave", LLSD(), payload, LLViewerTextEditor::onNotecardDialog);
+ LLNotificationsUtil::add( "ConfirmNotecardSave", LLSD(), payload, LLViewerTextEditor::onNotecardDialog);
}
// static
bool LLViewerTextEditor::onNotecardDialog(const LLSD& notification, const LLSD& response )
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if( option == 0 )
{
- // itemptr is deleted by LLPreview::save
- LLPointer<LLInventoryItem>* itemptr = new LLPointer<LLInventoryItem>(gInventory.getItem(notification["payload"]["item_id"].asUUID()));
- LLPreview::save( notification["payload"]["notecard_id"].asUUID() , itemptr);
+ LLPreviewNotecard* preview = LLFloaterReg::findTypedInstance<LLPreviewNotecard>("preview_notecard", notification["payload"]["notecard_id"]);;
+ if (preview)
+ {
+ preview->saveItem();
+ }
}
return false;
}
@@ -1450,13 +1206,13 @@ void LLViewerTextEditor::showCopyToInvDialog( LLInventoryItem* item, llwchar wc
LLUUID item_id = item->getUUID();
payload["item_id"] = item_id;
payload["item_wc"] = LLSD::Integer(wc);
- LLNotifications::instance().add( "ConfirmItemCopy", LLSD(), payload,
+ LLNotificationsUtil::add( "ConfirmItemCopy", LLSD(), payload,
boost::bind(&LLViewerTextEditor::onCopyToInvDialog, this, _1, _2));
}
bool LLViewerTextEditor::onCopyToInvDialog(const LLSD& notification, const LLSD& response)
{
- S32 option = LLNotification::getSelectedOption(notification, response);
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if( 0 == option )
{
LLUUID item_id = notification["payload"]["item_id"].asUUID();
@@ -1473,7 +1229,7 @@ bool LLViewerTextEditor::onCopyToInvDialog(const LLSD& notification, const LLSD&
// Returns change in number of characters in mWText
S32 LLViewerTextEditor::insertEmbeddedItem( S32 pos, LLInventoryItem* item )
{
- return execute( new LLTextCmdInsertEmbeddedItem( pos, item ) );
+ return execute( new TextCmdInsertEmbeddedItem( pos, item ) );
}
bool LLViewerTextEditor::importStream(std::istream& str)
@@ -1541,61 +1297,3 @@ BOOL LLViewerTextEditor::exportBuffer( std::string& buffer )
return TRUE;
}
-LLView* LLViewerTextEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
-{
- std::string name("text_editor");
- node->getAttributeString("name", name);
-
- LLRect rect;
- createRect(node, rect, parent, LLRect());
-
- U32 max_text_length = 255;
- node->getAttributeU32("max_length", max_text_length);
-
- BOOL allow_embedded_items = FALSE;
- node->getAttributeBOOL("embedded_items", allow_embedded_items);
-
- LLFontGL* font = LLView::selectFont(node);
-
- // std::string text = node->getValue();
- std::string text = node->getTextContents().substr(0, max_text_length - 1);
-
- if (text.size() > max_text_length)
- {
- // Erase everything from max_text_length on.
- text.erase(max_text_length);
- }
-
- LLViewerTextEditor* text_editor = new LLViewerTextEditor(name,
- rect,
- max_text_length,
- LLStringUtil::null,
- font,
- allow_embedded_items);
-
- BOOL ignore_tabs = text_editor->tabsToNextField();
- node->getAttributeBOOL("ignore_tab", ignore_tabs);
- text_editor->setTabsToNextField(ignore_tabs);
-
- text_editor->setTextEditorParameters(node);
-
- BOOL hide_scrollbar = FALSE;
- node->getAttributeBOOL("hide_scrollbar",hide_scrollbar);
- text_editor->setHideScrollbarForShortDocs(hide_scrollbar);
-
- BOOL hide_border = !text_editor->isBorderVisible();
- node->getAttributeBOOL("hide_border", hide_border);
- text_editor->setBorderVisible(!hide_border);
-
- BOOL parse_html = text_editor->mParseHTML;
- node->getAttributeBOOL("allow_html", parse_html);
- text_editor->setParseHTML(parse_html);
- text_editor->setParseHighlights(TRUE);
-
- text_editor->initFromXML(node, parent);
-
- // add text after all parameters have been set
- text_editor->appendStyledText(text, FALSE, FALSE);
-
- return text_editor;
-}
diff --git a/indra/newview/llviewertexteditor.h b/indra/newview/llviewertexteditor.h
index f29caee602..ba0c40cb2e 100644
--- a/indra/newview/llviewertexteditor.h
+++ b/indra/newview/llviewertexteditor.h
@@ -35,37 +35,35 @@
#include "lltexteditor.h"
-
//
// Classes
//
class LLViewerTextEditor : public LLTextEditor
{
-
public:
- LLViewerTextEditor(const std::string& name,
- const LLRect& rect,
- S32 max_length,
- const std::string& default_text = std::string(),
- const LLFontGL* glfont = NULL,
- BOOL allow_embedded_items = FALSE);
+ struct Params : public LLInitParam::Block<Params, LLTextEditor::Params>
+ {
+ Params()
+ {
+ name = "text_editor";
+ }
+ };
+
+protected:
+ LLViewerTextEditor(const Params&);
+ friend class LLUICtrlFactory;
+public:
virtual ~LLViewerTextEditor();
virtual void makePristine();
- static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
-
// mousehandler overrides
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask);
- virtual BOOL handleMiddleMouseUp(S32 x, S32 y, MASK mask);
- virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask );
- virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect);
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL drop, EDragAndDropType cargo_type,
void *cargo_data, EAcceptance *accept, std::string& tooltip_msg);
@@ -74,10 +72,13 @@ public:
virtual BOOL importBuffer(const char* buffer, S32 length);
virtual bool importStream(std::istream& str);
virtual BOOL exportBuffer(std::string& buffer);
- void setNotecardInfo(const LLUUID& notecard_item_id, const LLUUID& object_id)
+ virtual void onValueChange(S32 start, S32 end);
+
+ void setNotecardInfo(const LLUUID& notecard_item_id, const LLUUID& object_id, const LLUUID& preview_id)
{
mNotecardInventoryID = notecard_item_id;
mObjectID = object_id;
+ mPreviewID = preview_id;
}
void setASCIIEmbeddedText(const std::string& instr);
@@ -99,11 +100,9 @@ public:
private:
// Embedded object operations
+ void findEmbeddedItemSegments(S32 start, S32 end);
virtual llwchar pasteEmbeddedItem(llwchar ext_char);
- virtual void bindEmbeddedChars(const LLFontGL* font) const;
- virtual void unbindEmbeddedChars(const LLFontGL* font) const;
- BOOL getEmbeddedItemToolTipAtPos(S32 pos, LLWString &wmsg) const;
BOOL openEmbeddedItemAtPos( S32 pos );
BOOL openEmbeddedItem(LLInventoryItem* item, llwchar wc);
@@ -113,6 +112,7 @@ private:
void openEmbeddedSound( LLInventoryItem* item, llwchar wc );
void openEmbeddedLandmark( LLInventoryItem* item, llwchar wc );
void openEmbeddedNotecard( LLInventoryItem* item, llwchar wc);
+ void openEmbeddedCallingcard( LLInventoryItem* item, llwchar wc);
void showCopyToInvDialog( LLInventoryItem* item, llwchar wc );
void showUnsavedAlertDialog( LLInventoryItem* item );
@@ -120,23 +120,22 @@ private:
static bool onNotecardDialog(const LLSD& notification, const LLSD& response );
LLPointer<LLInventoryItem> mDragItem;
+ LLTextSegment* mDragSegment;
llwchar mDragItemChar;
BOOL mDragItemSaved;
class LLEmbeddedItems* mEmbeddedItemList;
LLUUID mObjectID;
LLUUID mNotecardInventoryID;
+ LLUUID mPreviewID;
LLPointer<class LLEmbeddedNotecardOpener> mInventoryCallback;
- // *TODO: Add right click menus for SLURLs
- //LLViewHandle mPopupMenuHandle;
-
//
// Inner classes
//
- class LLTextCmdInsertEmbeddedItem;
+ class TextCmdInsertEmbeddedItem;
};
#endif // LL_VIEWERTEXTEDITOR_H
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
new file mode 100644
index 0000000000..b80dc7d902
--- /dev/null
+++ b/indra/newview/llviewertexture.cpp
@@ -0,0 +1,3656 @@
+/**
+ * @file llviewertexture.cpp
+ * @brief Object which handles a received image (and associated texture(s))
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llviewertexture.h"
+
+// Library includes
+#include "imageids.h"
+#include "llmath.h"
+#include "llerror.h"
+#include "llgl.h"
+#include "llglheaders.h"
+#include "llhost.h"
+#include "llimage.h"
+#include "llimagebmp.h"
+#include "llimagej2c.h"
+#include "llimagetga.h"
+#include "llmemtype.h"
+#include "llstl.h"
+#include "llvfile.h"
+#include "llvfs.h"
+#include "message.h"
+#include "lltimer.h"
+
+// viewer includes
+#include "llimagegl.h"
+#include "lldrawpool.h"
+#include "lltexturefetch.h"
+#include "llviewertexturelist.h"
+#include "llviewercontrol.h"
+#include "pipeline.h"
+#include "llappviewer.h"
+#include "llface.h"
+#include "llviewercamera.h"
+#include "lltextureatlas.h"
+#include "lltextureatlasmanager.h"
+#include "lltextureentry.h"
+#include "llmediaentry.h"
+#include "llvovolume.h"
+#include "llviewermedia.h"
+///////////////////////////////////////////////////////////////////////////////
+
+// statics
+LLPointer<LLViewerTexture> LLViewerTexture::sNullImagep = NULL;
+LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sMissingAssetImagep = NULL;
+LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sWhiteImagep = NULL;
+LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultImagep = NULL;
+LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sSmokeImagep = NULL;
+LLViewerMediaTexture::media_map_t LLViewerMediaTexture::sMediaMap ;
+LLTexturePipelineTester* LLViewerTextureManager::sTesterp = NULL ;
+
+S32 LLViewerTexture::sImageCount = 0;
+S32 LLViewerTexture::sRawCount = 0;
+S32 LLViewerTexture::sAuxCount = 0;
+LLTimer LLViewerTexture::sEvaluationTimer;
+F32 LLViewerTexture::sDesiredDiscardBias = 0.f;
+F32 LLViewerTexture::sDesiredDiscardScale = 1.1f;
+S32 LLViewerTexture::sBoundTextureMemoryInBytes = 0;
+S32 LLViewerTexture::sTotalTextureMemoryInBytes = 0;
+S32 LLViewerTexture::sMaxBoundTextureMemInMegaBytes = 0;
+S32 LLViewerTexture::sMaxTotalTextureMemInMegaBytes = 0;
+S32 LLViewerTexture::sMaxDesiredTextureMemInBytes = 0 ;
+S8 LLViewerTexture::sCameraMovingDiscardBias = 0 ;
+S32 LLViewerTexture::sMaxSculptRez = 128 ; //max sculpt image size
+const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64 ;
+const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez ;
+const S32 MAX_CACHED_RAW_TERRAIN_IMAGE_AREA = 128 * 128 ;
+S32 LLViewerTexture::sMinLargeImageSize = 65536 ; //256 * 256.
+S32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA ;
+BOOL LLViewerTexture::sFreezeImageScalingDown = FALSE ;
+F32 LLViewerTexture::sCurrentTime = 0.0f ;
+BOOL LLViewerTexture::sUseTextureAtlas = FALSE ;
+
+const F32 desired_discard_bias_min = -2.0f; // -max number of levels to improve image quality by
+const F32 desired_discard_bias_max = 1.5f; // max number of levels to reduce image quality by
+const F64 log_2 = log(2.0);
+
+//----------------------------------------------------------------------------------------------
+//namespace: LLViewerTextureAccess
+//----------------------------------------------------------------------------------------------
+
+LLLoadedCallbackEntry::LLLoadedCallbackEntry(loaded_callback_func cb,
+ S32 discard_level,
+ BOOL need_imageraw, // Needs image raw for the callback
+ void* userdata )
+ : mCallback(cb),
+ mLastUsedDiscard(MAX_DISCARD_LEVEL+1),
+ mDesiredDiscard(discard_level),
+ mNeedsImageRaw(need_imageraw),
+ mUserData(userdata)
+{
+}
+
+LLViewerMediaTexture* LLViewerTextureManager::createMediaTexture(const LLUUID &media_id, BOOL usemipmaps, LLImageGL* gl_image)
+{
+ return new LLViewerMediaTexture(media_id, usemipmaps, gl_image) ;
+}
+
+LLViewerTexture* LLViewerTextureManager::findTexture(const LLUUID& id)
+{
+ LLViewerTexture* tex ;
+ //search fetched texture list
+ tex = gTextureList.findImage(id) ;
+
+ //search media texture list
+ if(!tex)
+ {
+ tex = LLViewerTextureManager::findMediaTexture(id) ;
+ }
+ return tex ;
+}
+
+LLViewerMediaTexture* LLViewerTextureManager::findMediaTexture(const LLUUID &media_id)
+{
+ return LLViewerMediaTexture::findMediaTexture(media_id) ;
+}
+
+LLViewerMediaTexture* LLViewerTextureManager::getMediaTexture(const LLUUID& id, BOOL usemipmaps, LLImageGL* gl_image)
+{
+ LLViewerMediaTexture* tex = LLViewerMediaTexture::findMediaTexture(id) ;
+ if(!tex)
+ {
+ tex = LLViewerTextureManager::createMediaTexture(id, usemipmaps, gl_image) ;
+ }
+
+ tex->initVirtualSize() ;
+
+ return tex ;
+}
+
+LLViewerFetchedTexture* LLViewerTextureManager::staticCastToFetchedTexture(LLTexture* tex, BOOL report_error)
+{
+ if(!tex)
+ {
+ return NULL ;
+ }
+
+ S8 type = tex->getType() ;
+ if(type == LLViewerTexture::FETCHED_TEXTURE || type == LLViewerTexture::LOD_TEXTURE)
+ {
+ return static_cast<LLViewerFetchedTexture*>(tex) ;
+ }
+
+ if(report_error)
+ {
+ llerrs << "not a fetched texture type: " << type << llendl ;
+ }
+
+ return NULL ;
+}
+
+LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(BOOL usemipmaps, BOOL generate_gl_tex)
+{
+ LLPointer<LLViewerTexture> tex = new LLViewerTexture(usemipmaps) ;
+ if(generate_gl_tex)
+ {
+ tex->generateGLTexture() ;
+ tex->setCategory(LLViewerTexture::LOCAL) ;
+ }
+ return tex ;
+}
+LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const LLUUID& id, BOOL usemipmaps, BOOL generate_gl_tex)
+{
+ LLPointer<LLViewerTexture> tex = new LLViewerTexture(id, usemipmaps) ;
+ if(generate_gl_tex)
+ {
+ tex->generateGLTexture() ;
+ tex->setCategory(LLViewerTexture::LOCAL) ;
+ }
+ return tex ;
+}
+LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const LLImageRaw* raw, BOOL usemipmaps)
+{
+ LLPointer<LLViewerTexture> tex = new LLViewerTexture(raw, usemipmaps) ;
+ tex->setCategory(LLViewerTexture::LOCAL) ;
+ return tex ;
+}
+LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex)
+{
+ LLPointer<LLViewerTexture> tex = new LLViewerTexture(width, height, components, usemipmaps) ;
+ if(generate_gl_tex)
+ {
+ tex->generateGLTexture() ;
+ tex->setCategory(LLViewerTexture::LOCAL) ;
+ }
+ return tex ;
+}
+
+LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(
+ const LLUUID &image_id,
+ BOOL usemipmaps,
+ LLViewerTexture::EBoostLevel boost_priority,
+ S8 texture_type,
+ LLGLint internal_format,
+ LLGLenum primary_format,
+ LLHost request_from_host)
+{
+ return gTextureList.getImage(image_id, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ;
+}
+
+LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromFile(
+ const std::string& filename,
+ BOOL usemipmaps,
+ LLViewerTexture::EBoostLevel boost_priority,
+ S8 texture_type,
+ LLGLint internal_format,
+ LLGLenum primary_format,
+ const LLUUID& force_id)
+{
+ return gTextureList.getImageFromFile(filename, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ;
+}
+
+//static
+LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string& url,
+ BOOL usemipmaps,
+ LLViewerTexture::EBoostLevel boost_priority,
+ S8 texture_type,
+ LLGLint internal_format,
+ LLGLenum primary_format,
+ const LLUUID& force_id
+ )
+{
+ return gTextureList.getImageFromUrl(url, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ;
+}
+
+LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const LLUUID& image_id, LLHost host)
+{
+ return gTextureList.getImageFromHost(image_id, host) ;
+}
+
+void LLViewerTextureManager::init()
+{
+ LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,3);
+ raw->clear(0x77, 0x77, 0x77, 0xFF);
+ LLViewerTexture::sNullImagep = LLViewerTextureManager::getLocalTexture(raw.get(), TRUE) ;
+
+#if 1
+ LLPointer<LLViewerFetchedTexture> imagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT);
+ LLViewerFetchedTexture::sDefaultImagep = imagep;
+
+ const S32 dim = 128;
+ LLPointer<LLImageRaw> image_raw = new LLImageRaw(dim,dim,3);
+ U8* data = image_raw->getData();
+ for (S32 i = 0; i<dim; i++)
+ {
+ for (S32 j = 0; j<dim; j++)
+ {
+#if 0
+ const S32 border = 2;
+ if (i<border || j<border || i>=(dim-border) || j>=(dim-border))
+ {
+ *data++ = 0xff;
+ *data++ = 0xff;
+ *data++ = 0xff;
+ }
+ else
+#endif
+ {
+ *data++ = 0x7f;
+ *data++ = 0x7f;
+ *data++ = 0x7f;
+ }
+ }
+ }
+ imagep->createGLTexture(0, image_raw);
+ image_raw = NULL;
+#else
+ LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI);
+#endif
+ LLViewerFetchedTexture::sDefaultImagep->dontDiscard();
+ LLViewerFetchedTexture::sDefaultImagep->setCategory(LLViewerTexture::OTHER) ;
+
+ LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, TRUE, LLViewerTexture::BOOST_UI);
+ LLViewerFetchedTexture::sSmokeImagep->setNoDelete() ;
+
+ LLViewerTexture::initClass() ;
+
+ if(LLFastTimer::sMetricLog)
+ {
+ LLViewerTextureManager::sTesterp = new LLTexturePipelineTester() ;
+ }
+}
+
+void LLViewerTextureManager::cleanup()
+{
+ stop_glerror();
+
+ LLImageGL::sDefaultGLTexture = NULL ;
+ LLViewerTexture::sNullImagep = NULL;
+ LLViewerFetchedTexture::sDefaultImagep = NULL;
+ LLViewerFetchedTexture::sSmokeImagep = NULL;
+ LLViewerFetchedTexture::sMissingAssetImagep = NULL;
+ LLViewerFetchedTexture::sWhiteImagep = NULL;
+
+ LLViewerMediaTexture::cleanup() ;
+
+ LLViewerTexture::cleanupClass() ;
+}
+
+//----------------------------------------------------------------------------------------------
+//----------------------------------------------------------------------------------------------
+//start of LLViewerTexture
+//----------------------------------------------------------------------------------------------
+// static
+void LLViewerTexture::initClass()
+{
+ LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture() ;
+
+ if(gAuditTexture)
+ {
+ LLImageGL::setHighlightTexture(LLViewerTexture::OTHER) ;
+ }
+}
+
+// static
+void LLViewerTexture::cleanupClass()
+{
+}
+
+// static
+S32 LLViewerTexture::getTotalNumOfCategories()
+{
+ return MAX_GL_IMAGE_CATEGORY - (BOOST_HIGH - BOOST_SCULPTED) + 2 ;
+}
+
+// static
+//index starts from zero.
+S32 LLViewerTexture::getIndexFromCategory(S32 category)
+{
+ return (category < BOOST_HIGH) ? category : category - (BOOST_HIGH - BOOST_SCULPTED) + 1 ;
+}
+
+//static
+S32 LLViewerTexture::getCategoryFromIndex(S32 index)
+{
+ return (index < BOOST_HIGH) ? index : index + (BOOST_HIGH - BOOST_SCULPTED) - 1 ;
+}
+
+// tuning params
+const F32 discard_bias_delta = .05f;
+const F32 discard_delta_time = 0.5f;
+const S32 min_non_tex_system_mem = (128<<20); // 128 MB
+// non-const (used externally
+F32 texmem_lower_bound_scale = 0.85f;
+F32 texmem_middle_bound_scale = 0.925f;
+
+//static
+void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity)
+{
+ sCurrentTime = gFrameTimeSeconds ;
+
+ if(LLViewerTextureManager::sTesterp)
+ {
+ LLViewerTextureManager::sTesterp->update() ;
+ }
+ LLViewerMediaTexture::updateClass() ;
+
+ sBoundTextureMemoryInBytes = LLImageGL::sBoundTextureMemoryInBytes;//in bytes
+ sTotalTextureMemoryInBytes = LLImageGL::sGlobalTextureMemoryInBytes;//in bytes
+ sMaxBoundTextureMemInMegaBytes = gTextureList.getMaxResidentTexMem();//in MB
+ sMaxTotalTextureMemInMegaBytes = gTextureList.getMaxTotalTextureMem() ;//in MB
+ sMaxDesiredTextureMemInBytes = MEGA_BYTES_TO_BYTES(sMaxTotalTextureMemInMegaBytes) ; //in Bytes, by default and when total used texture memory is small.
+
+ if (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) >= sMaxBoundTextureMemInMegaBytes ||
+ BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) >= sMaxTotalTextureMemInMegaBytes)
+ {
+ //when texture memory overflows, lower down the threashold to release the textures more aggressively.
+ sMaxDesiredTextureMemInBytes = llmin((S32)(sMaxDesiredTextureMemInBytes * 0.75f) , MEGA_BYTES_TO_BYTES(MAX_VIDEO_RAM_IN_MEGA_BYTES)) ;//512 MB
+
+ // If we are using more texture memory than we should,
+ // scale up the desired discard level
+ if (sEvaluationTimer.getElapsedTimeF32() > discard_delta_time)
+ {
+ sDesiredDiscardBias += discard_bias_delta;
+ sEvaluationTimer.reset();
+ }
+ }
+ else if (sDesiredDiscardBias > 0.0f &&
+ BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < sMaxBoundTextureMemInMegaBytes * texmem_lower_bound_scale &&
+ BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < sMaxTotalTextureMemInMegaBytes * texmem_lower_bound_scale)
+ {
+ // If we are using less texture memory than we should,
+ // scale down the desired discard level
+ if (sEvaluationTimer.getElapsedTimeF32() > discard_delta_time)
+ {
+ sDesiredDiscardBias -= discard_bias_delta;
+ sEvaluationTimer.reset();
+ }
+ }
+ sDesiredDiscardBias = llclamp(sDesiredDiscardBias, desired_discard_bias_min, desired_discard_bias_max);
+ LLViewerTexture::sUseTextureAtlas = gSavedSettings.getBOOL("EnableTextureAtlas") ;
+
+ F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ;
+ F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed();
+ sCameraMovingDiscardBias = (S8)llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1) ;
+
+ LLViewerTexture::sFreezeImageScalingDown = (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < 0.75f * sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) &&
+ (BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < 0.75f * sMaxTotalTextureMemInMegaBytes * texmem_middle_bound_scale) ;
+}
+
+//end of static functions
+//-------------------------------------------------------------------------------------------
+const U32 LLViewerTexture::sCurrentFileVersion = 1;
+
+LLViewerTexture::LLViewerTexture(BOOL usemipmaps)
+{
+ init(true);
+ mUseMipMaps = usemipmaps ;
+
+ mID.generate();
+ sImageCount++;
+}
+
+LLViewerTexture::LLViewerTexture(const LLUUID& id, BOOL usemipmaps)
+ : mID(id)
+{
+ init(true);
+ mUseMipMaps = usemipmaps ;
+
+ sImageCount++;
+}
+
+LLViewerTexture::LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps)
+{
+ init(true);
+
+ mFullWidth = width ;
+ mFullHeight = height ;
+ mUseMipMaps = usemipmaps ;
+ mComponents = components ;
+
+ mID.generate();
+ sImageCount++;
+}
+
+LLViewerTexture::LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps)
+{
+ init(true);
+ mUseMipMaps = usemipmaps ;
+ mGLTexturep = new LLImageGL(raw, usemipmaps) ;
+
+ // Create an empty image of the specified size and width
+ mID.generate();
+ sImageCount++;
+}
+
+LLViewerTexture::~LLViewerTexture()
+{
+ sImageCount--;
+}
+
+void LLViewerTexture::init(bool firstinit)
+{
+ mBoostLevel = LLViewerTexture::BOOST_NONE;
+
+ mFullWidth = 0;
+ mFullHeight = 0;
+ mUseMipMaps = FALSE ;
+ mComponents = 0 ;
+
+ mTextureState = NO_DELETE ;
+ mDontDiscard = FALSE;
+ mMaxVirtualSize = 0.f;
+ mNeedsGLTexture = FALSE ;
+ mNeedsResetMaxVirtualSize = FALSE ;
+ mAdditionalDecodePriority = 0.f ;
+ mParcelMedia = NULL ;
+ mNumFaces = 0 ;
+ mFaceList.clear() ;
+}
+
+//virtual
+S8 LLViewerTexture::getType() const
+{
+ return LLViewerTexture::LOCAL_TEXTURE ;
+}
+
+void LLViewerTexture::cleanup()
+{
+ mFaceList.clear() ;
+
+ if(mGLTexturep)
+ {
+ mGLTexturep->cleanup();
+ }
+}
+
+// virtual
+void LLViewerTexture::dump()
+{
+ if(mGLTexturep)
+ {
+ mGLTexturep->dump();
+ }
+
+ llinfos << "LLViewerTexture"
+ << " mID " << mID
+ << llendl;
+}
+
+void LLViewerTexture::setBoostLevel(S32 level)
+{
+ if(mBoostLevel != level)
+ {
+ mBoostLevel = level ;
+ if(mBoostLevel != LLViewerTexture::BOOST_NONE)
+ {
+ setNoDelete() ;
+ }
+ if(gAuditTexture)
+ {
+ setCategory(mBoostLevel);
+ }
+ }
+}
+
+
+bool LLViewerTexture::bindDefaultImage(S32 stage)
+{
+ if (stage < 0) return false;
+
+ bool res = true;
+ if (LLViewerFetchedTexture::sDefaultImagep.notNull() && (this != LLViewerFetchedTexture::sDefaultImagep.get()))
+ {
+ // use default if we've got it
+ res = gGL.getTexUnit(stage)->bind(LLViewerFetchedTexture::sDefaultImagep);
+ }
+ if (!res && LLViewerTexture::sNullImagep.notNull() && (this != LLViewerTexture::sNullImagep))
+ {
+ res = gGL.getTexUnit(stage)->bind(LLViewerTexture::sNullImagep) ;
+ }
+ if (!res)
+ {
+ llwarns << "LLViewerTexture::bindDefaultImage failed." << llendl;
+ }
+ stop_glerror();
+
+ //check if there is cached raw image and switch to it if possible
+ switchToCachedImage() ;
+
+ if(LLViewerTextureManager::sTesterp)
+ {
+ LLViewerTextureManager::sTesterp->updateGrayTextureBinding() ;
+ }
+ return res;
+}
+
+//virtual
+BOOL LLViewerTexture::isMissingAsset()const
+{
+ return FALSE;
+}
+
+//virtual
+void LLViewerTexture::forceImmediateUpdate()
+{
+}
+
+void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) const
+{
+ if(needs_gltexture)
+ {
+ mNeedsGLTexture = TRUE ;
+ }
+
+ if(mNeedsResetMaxVirtualSize)
+ {
+ //flag to reset the values because the old values are used.
+ mNeedsResetMaxVirtualSize = FALSE ;
+ mMaxVirtualSize = virtual_size;
+ mAdditionalDecodePriority = 0.f ;
+ mNeedsGLTexture = needs_gltexture ;
+ }
+ else if (virtual_size > mMaxVirtualSize)
+ {
+ mMaxVirtualSize = virtual_size;
+ }
+}
+
+void LLViewerTexture::resetTextureStats()
+{
+ mMaxVirtualSize = 0.0f;
+ mAdditionalDecodePriority = 0.f ;
+ mNeedsResetMaxVirtualSize = FALSE ;
+}
+
+//virtual
+F32 LLViewerTexture::getMaxVirtualSize()
+{
+ return mMaxVirtualSize ;
+}
+
+//virtual
+void LLViewerTexture::setKnownDrawSize(S32 width, S32 height)
+{
+ //nothing here.
+}
+
+//virtual
+void LLViewerTexture::addFace(LLFace* facep)
+{
+ if(mNumFaces >= mFaceList.size())
+ {
+ mFaceList.resize(2 * mNumFaces + 1) ;
+ }
+ mFaceList[mNumFaces] = facep ;
+ facep->setIndexInTex(mNumFaces) ;
+ mNumFaces++ ;
+ mLastFaceListUpdateTimer.reset() ;
+}
+
+//virtual
+void LLViewerTexture::removeFace(LLFace* facep)
+{
+ if(mNumFaces > 1)
+ {
+ S32 index = facep->getIndexInTex() ;
+ mFaceList[index] = mFaceList[--mNumFaces] ;
+ mFaceList[index]->setIndexInTex(index) ;
+ }
+ else
+ {
+ mFaceList.clear() ;
+ mNumFaces = 0 ;
+ }
+ mLastFaceListUpdateTimer.reset() ;
+}
+
+S32 LLViewerTexture::getNumFaces() const
+{
+ return mNumFaces ;
+}
+
+void LLViewerTexture::reorganizeFaceList()
+{
+ static const F32 MAX_WAIT_TIME = 20.f; // seconds
+ static const U32 MAX_EXTRA_BUFFER_SIZE = 4 ;
+
+ if(mNumFaces + MAX_EXTRA_BUFFER_SIZE > mFaceList.size())
+ {
+ return ;
+ }
+
+ if(mLastFaceListUpdateTimer.getElapsedTimeF32() < MAX_WAIT_TIME)
+ {
+ return ;
+ }
+
+ mLastFaceListUpdateTimer.reset() ;
+ mFaceList.erase(mFaceList.begin() + mNumFaces, mFaceList.end());
+}
+
+//virtual
+void LLViewerTexture::switchToCachedImage()
+{
+ //nothing here.
+}
+
+void LLViewerTexture::forceActive()
+{
+ mTextureState = ACTIVE ;
+}
+
+void LLViewerTexture::setActive()
+{
+ if(mTextureState != NO_DELETE)
+ {
+ mTextureState = ACTIVE ;
+ }
+}
+
+//set the texture to stay in memory
+void LLViewerTexture::setNoDelete()
+{
+ mTextureState = NO_DELETE ;
+}
+
+void LLViewerTexture::generateGLTexture()
+{
+ if(mGLTexturep.isNull())
+ {
+ mGLTexturep = new LLImageGL(mFullWidth, mFullHeight, mComponents, mUseMipMaps) ;
+ }
+}
+
+LLImageGL* LLViewerTexture::getGLTexture() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep ;
+}
+
+BOOL LLViewerTexture::createGLTexture()
+{
+ if(mGLTexturep.isNull())
+ {
+ generateGLTexture() ;
+ }
+
+ return mGLTexturep->createGLTexture() ;
+}
+
+BOOL LLViewerTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename, BOOL to_create, S32 category)
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category) ;
+
+ if(ret)
+ {
+ mFullWidth = mGLTexturep->getCurrentWidth() ;
+ mFullHeight = mGLTexturep->getCurrentHeight() ;
+ mComponents = mGLTexturep->getComponents() ;
+ }
+
+ return ret ;
+}
+
+void LLViewerTexture::setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes)
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ mGLTexturep->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes) ;
+}
+void LLViewerTexture::setAddressMode(LLTexUnit::eTextureAddressMode mode)
+{
+ llassert_always(mGLTexturep.notNull()) ;
+ mGLTexturep->setAddressMode(mode) ;
+}
+void LLViewerTexture::setFilteringOption(LLTexUnit::eTextureFilterOptions option)
+{
+ llassert_always(mGLTexturep.notNull()) ;
+ mGLTexturep->setFilteringOption(option) ;
+}
+
+//virtual
+S32 LLViewerTexture::getWidth(S32 discard_level) const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+ return mGLTexturep->getWidth(discard_level) ;
+}
+
+//virtual
+S32 LLViewerTexture::getHeight(S32 discard_level) const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+ return mGLTexturep->getHeight(discard_level) ;
+}
+
+S32 LLViewerTexture::getMaxDiscardLevel() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+ return mGLTexturep->getMaxDiscardLevel() ;
+}
+S32 LLViewerTexture::getDiscardLevel() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+ return mGLTexturep->getDiscardLevel() ;
+}
+S8 LLViewerTexture::getComponents() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getComponents() ;
+}
+
+LLGLuint LLViewerTexture::getTexName() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getTexName() ;
+}
+
+BOOL LLViewerTexture::hasGLTexture() const
+{
+ if(mGLTexturep.notNull())
+ {
+ return mGLTexturep->getHasGLTexture() ;
+ }
+ return FALSE ;
+}
+
+BOOL LLViewerTexture::getBoundRecently() const
+{
+ if(mGLTexturep.notNull())
+ {
+ return mGLTexturep->getBoundRecently() ;
+ }
+ return FALSE ;
+}
+
+LLTexUnit::eTextureType LLViewerTexture::getTarget(void) const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+ return mGLTexturep->getTarget() ;
+}
+
+BOOL LLViewerTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height)
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height) ;
+}
+
+BOOL LLViewerTexture::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height)
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height) ;
+}
+
+void LLViewerTexture::setGLTextureCreated (bool initialized)
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ mGLTexturep->setGLTextureCreated (initialized) ;
+}
+
+void LLViewerTexture::setCategory(S32 category)
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ mGLTexturep->setCategory(category) ;
+}
+
+LLTexUnit::eTextureAddressMode LLViewerTexture::getAddressMode(void) const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getAddressMode() ;
+}
+
+S32 LLViewerTexture::getTextureMemory() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->mTextureMemory ;
+}
+
+LLGLenum LLViewerTexture::getPrimaryFormat() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getPrimaryFormat() ;
+}
+
+BOOL LLViewerTexture::getIsAlphaMask() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getIsAlphaMask() ;
+}
+
+BOOL LLViewerTexture::getMask(const LLVector2 &tc)
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getMask(tc) ;
+}
+
+F32 LLViewerTexture::getTimePassedSinceLastBound()
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getTimePassedSinceLastBound() ;
+}
+BOOL LLViewerTexture::getMissed() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getMissed() ;
+}
+
+BOOL LLViewerTexture::isJustBound() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->isJustBound() ;
+}
+
+void LLViewerTexture::forceUpdateBindStats(void) const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->forceUpdateBindStats() ;
+}
+
+U32 LLViewerTexture::getTexelsInAtlas() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getTexelsInAtlas() ;
+}
+
+U32 LLViewerTexture::getTexelsInGLTexture() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getTexelsInGLTexture() ;
+}
+
+BOOL LLViewerTexture::isGLTextureCreated() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->isGLTextureCreated() ;
+}
+
+S32 LLViewerTexture::getDiscardLevelInAtlas() const
+{
+ llassert_always(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getDiscardLevelInAtlas() ;
+}
+
+void LLViewerTexture::destroyGLTexture()
+{
+ if(mGLTexturep.notNull() && mGLTexturep->getHasGLTexture())
+ {
+ mGLTexturep->destroyGLTexture() ;
+ mTextureState = DELETED ;
+ }
+}
+
+BOOL LLViewerTexture::isLargeImage()
+{
+ return mFullWidth * mFullHeight > LLViewerTexture::sMinLargeImageSize ;
+}
+
+//virtual
+void LLViewerTexture::updateBindStatsForTester()
+{
+ if(LLViewerTextureManager::sTesterp)
+ {
+ LLViewerTextureManager::sTesterp->updateTextureBindingStats(this) ;
+ }
+}
+
+//----------------------------------------------------------------------------------------------
+//end of LLViewerTexture
+//----------------------------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------------------------
+//start of LLViewerFetchedTexture
+//----------------------------------------------------------------------------------------------
+
+//static
+F32 LLViewerFetchedTexture::maxDecodePriority()
+{
+ return 6000000.f;
+}
+
+LLViewerFetchedTexture::LLViewerFetchedTexture(const LLUUID& id, const LLHost& host, BOOL usemipmaps)
+ : LLViewerTexture(id, usemipmaps),
+ mTargetHost(host)
+{
+ init(TRUE) ;
+ generateGLTexture() ;
+}
+
+LLViewerFetchedTexture::LLViewerFetchedTexture(const LLImageRaw* raw, BOOL usemipmaps)
+ : LLViewerTexture(raw, usemipmaps)
+{
+ init(TRUE) ;
+}
+
+LLViewerFetchedTexture::LLViewerFetchedTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps)
+ : LLViewerTexture(id, usemipmaps),
+ mUrl(url)
+{
+ init(TRUE) ;
+ generateGLTexture() ;
+}
+
+void LLViewerFetchedTexture::init(bool firstinit)
+{
+ mOrigWidth = 0;
+ mOrigHeight = 0;
+ mNeedsAux = FALSE;
+ mRequestedDiscardLevel = -1;
+ mRequestedDownloadPriority = 0.f;
+ mFullyLoaded = FALSE;
+ mDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1;
+ mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1;
+
+ mDecodingAux = FALSE;
+
+ mKnownDrawWidth = 0;
+ mKnownDrawHeight = 0;
+ mKnownDrawSizeChanged = FALSE ;
+
+ if (firstinit)
+ {
+ mDecodePriority = 0.f;
+ mInImageList = 0;
+ }
+
+ // Only set mIsMissingAsset true when we know for certain that the database
+ // does not contain this image.
+ mIsMissingAsset = FALSE;
+
+ mNeedsCreateTexture = FALSE;
+
+ mIsRawImageValid = FALSE;
+ mRawDiscardLevel = INVALID_DISCARD_LEVEL;
+ mMinDiscardLevel = 0;
+
+ mHasFetcher = FALSE;
+ mIsFetching = FALSE;
+ mFetchState = 0;
+ mFetchPriority = 0;
+ mDownloadProgress = 0.f;
+ mFetchDeltaTime = 999999.f;
+ mForSculpt = FALSE ;
+ mIsFetched = FALSE ;
+
+ mCachedRawImage = NULL ;
+ mCachedRawDiscardLevel = -1 ;
+ mCachedRawImageReady = FALSE ;
+
+ mSavedRawImage = NULL ;
+ mForceToSaveRawImage = FALSE ;
+ mSavedRawDiscardLevel = -1 ;
+ mDesiredSavedRawDiscardLevel = -1 ;
+ mLastReferencedSavedRawImageTime = 0.0f ;
+}
+
+LLViewerFetchedTexture::~LLViewerFetchedTexture()
+{
+ //*NOTE getTextureFetch can return NULL when Viewer is shutting down.
+ // This is due to LLWearableList is singleton and is destroyed after
+ // LLAppViewer::cleanup() was called. (see ticket EXT-177)
+ if (mHasFetcher && LLAppViewer::getTextureFetch())
+ {
+ LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
+ }
+ cleanup();
+}
+
+//virtual
+S8 LLViewerFetchedTexture::getType() const
+{
+ return LLViewerTexture::FETCHED_TEXTURE ;
+}
+
+void LLViewerFetchedTexture::cleanup()
+{
+ for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
+ iter != mLoadedCallbackList.end(); )
+ {
+ LLLoadedCallbackEntry *entryp = *iter++;
+ // We never finished loading the image. Indicate failure.
+ // Note: this allows mLoadedCallbackUserData to be cleaned up.
+ entryp->mCallback( FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData );
+ delete entryp;
+ }
+ mLoadedCallbackList.clear();
+ mNeedsAux = FALSE;
+
+ // Clean up image data
+ destroyRawImage();
+ mCachedRawImage = NULL ;
+ mCachedRawDiscardLevel = -1 ;
+ mCachedRawImageReady = FALSE ;
+ mSavedRawImage = NULL ;
+}
+
+void LLViewerFetchedTexture::setForSculpt()
+{
+ mForSculpt = TRUE ;
+ if(isForSculptOnly() && !getBoundRecently())
+ {
+ destroyGLTexture() ; //sculpt image does not need gl texture.
+ }
+ checkCachedRawSculptImage() ;
+}
+
+BOOL LLViewerFetchedTexture::isForSculptOnly() const
+{
+ return mForSculpt && !mNeedsGLTexture ;
+}
+
+BOOL LLViewerFetchedTexture::isDeleted()
+{
+ return mTextureState == DELETED ;
+}
+
+BOOL LLViewerFetchedTexture::isInactive()
+{
+ return mTextureState == INACTIVE ;
+}
+
+BOOL LLViewerFetchedTexture::isDeletionCandidate()
+{
+ return mTextureState == DELETION_CANDIDATE ;
+}
+
+void LLViewerFetchedTexture::setDeletionCandidate()
+{
+ if(mGLTexturep.notNull() && mGLTexturep->getTexName() && (mTextureState == INACTIVE))
+ {
+ mTextureState = DELETION_CANDIDATE ;
+ }
+}
+
+//set the texture inactive
+void LLViewerFetchedTexture::setInactive()
+{
+ if(mTextureState == ACTIVE && mGLTexturep.notNull() && mGLTexturep->getTexName() && !mGLTexturep->getBoundRecently())
+ {
+ mTextureState = INACTIVE ;
+ }
+}
+
+BOOL LLViewerFetchedTexture::isFullyLoaded() const
+{
+ // Unfortunately, the boolean "mFullyLoaded" is never updated correctly so we use that logic
+ // to check if the texture is there and completely downloaded
+ return (mFullWidth != 0) && (mFullHeight != 0) && !mIsFetching && !mHasFetcher;
+}
+
+
+// virtual
+void LLViewerFetchedTexture::dump()
+{
+ LLViewerTexture::dump();
+
+ llinfos << "Dump : " << mID
+ << ", mIsMissingAsset = " << (S32)mIsMissingAsset
+ << ", mFullWidth = " << (S32)mFullWidth
+ << ", mFullHeight = " << (S32)mFullHeight
+ << ", mOrigWidth = " << (S32)mOrigWidth
+ << ", mOrigHeight = " << (S32)mOrigHeight
+ << llendl;
+ llinfos << " : "
+ << " mFullyLoaded = " << (S32)mFullyLoaded
+ << ", mFetchState = " << (S32)mFetchState
+ << ", mFetchPriority = " << (S32)mFetchPriority
+ << ", mDownloadProgress = " << (F32)mDownloadProgress
+ << llendl;
+ llinfos << " : "
+ << " mHasFetcher = " << (S32)mHasFetcher
+ << ", mIsFetching = " << (S32)mIsFetching
+ << ", mIsFetched = " << (S32)mIsFetched
+ << ", mBoostLevel = " << (S32)mBoostLevel
+ << llendl;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// ONLY called from LLViewerFetchedTextureList
+void LLViewerFetchedTexture::destroyTexture()
+{
+ if(LLImageGL::sGlobalTextureMemoryInBytes < sMaxDesiredTextureMemInBytes)//not ready to release unused memory.
+ {
+ return ;
+ }
+ if (mNeedsCreateTexture)//return if in the process of generating a new texture.
+ {
+ return ;
+ }
+
+ destroyGLTexture() ;
+ mFullyLoaded = FALSE ;
+}
+
+//
+//do not change the discard level of the loaded texture image.
+BOOL LLViewerFetchedTexture::keepReuestedDiscardLevel()
+{
+ if (!mLoadedCallbackList.empty())
+ {
+ return TRUE ;
+ }
+
+ return FALSE ;
+}
+
+void LLViewerFetchedTexture::addToCreateTexture()
+{
+ if(isForSculptOnly())
+ {
+ //just update some variables, not to create a real GL texture.
+ createGLTexture(mRawDiscardLevel, mRawImage, 0, FALSE) ;
+ mNeedsCreateTexture = FALSE ;
+ destroyRawImage();
+ }
+ else
+ {
+#if 1
+ //
+ //if mRequestedDiscardLevel > mDesiredDiscardLevel, we assume the required image res keep going up,
+ //so do not scale down the over qualified image.
+ //Note: scaling down image is expensensive. Do it only when very necessary.
+ //
+ if(mRequestedDiscardLevel <= mDesiredDiscardLevel && !keepReuestedDiscardLevel())
+ {
+ S32 w = mFullWidth >> mRawDiscardLevel;
+ S32 h = mFullHeight >> mRawDiscardLevel;
+
+ //if big image, do not load extra data
+ //scale it down to size >= LLViewerTexture::sMinLargeImageSize
+ if(w * h > LLViewerTexture::sMinLargeImageSize)
+ {
+ S32 d_level = llmin(mRequestedDiscardLevel, (S32)mDesiredDiscardLevel) - mRawDiscardLevel ;
+
+ if(d_level > 0)
+ {
+ S32 i = 0 ;
+ while((d_level > 0) && ((w >> i) * (h >> i) > LLViewerTexture::sMinLargeImageSize))
+ {
+ i++;
+ d_level--;
+ }
+ if(i > 0)
+ {
+ mRawDiscardLevel += i ;
+ if(mRawDiscardLevel >= getDiscardLevel() && getDiscardLevel() > 0)
+ {
+ mNeedsCreateTexture = FALSE ;
+ destroyRawImage();
+ return ;
+ }
+ mRawImage->scale(w >> i, h >> i) ;
+ }
+ }
+ }
+ }
+#endif
+ mNeedsCreateTexture = TRUE;
+ gTextureList.mCreateTextureList.insert(this);
+ }
+ return ;
+}
+
+// ONLY called from LLViewerTextureList
+BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/)
+{
+ if (!mNeedsCreateTexture)
+ {
+ destroyRawImage();
+ return FALSE;
+ }
+ mNeedsCreateTexture = FALSE;
+ if (mRawImage.isNull())
+ {
+ llerrs << "LLViewerTexture trying to create texture with no Raw Image" << llendl;
+ }
+// llinfos << llformat("IMAGE Creating (%d) [%d x %d] Bytes: %d ",
+// mRawDiscardLevel,
+// mRawImage->getWidth(), mRawImage->getHeight(),mRawImage->getDataSize())
+// << mID.getString() << llendl;
+ BOOL res = TRUE;
+ if (!gNoRender)
+ {
+ // store original size only for locally-sourced images
+ if (mUrl.compare(0, 7, "file://") == 0)
+ {
+ mOrigWidth = mRawImage->getWidth();
+ mOrigHeight = mRawImage->getHeight();
+
+ // leave black border, do not scale image content
+ mRawImage->expandToPowerOfTwo(MAX_IMAGE_SIZE, FALSE);
+
+ mFullWidth = mRawImage->getWidth();
+ mFullHeight = mRawImage->getHeight();
+ }
+ else
+ {
+ mOrigWidth = mFullWidth;
+ mOrigHeight = mFullHeight;
+ }
+
+ bool size_okay = true;
+
+ U32 raw_width = mRawImage->getWidth() << mRawDiscardLevel;
+ U32 raw_height = mRawImage->getHeight() << mRawDiscardLevel;
+ if( raw_width > MAX_IMAGE_SIZE || raw_height > MAX_IMAGE_SIZE )
+ {
+ llinfos << "Width or height is greater than " << MAX_IMAGE_SIZE << ": (" << raw_width << "," << raw_height << ")" << llendl;
+ size_okay = false;
+ }
+
+ if (!LLImageGL::checkSize(mRawImage->getWidth(), mRawImage->getHeight()))
+ {
+ // A non power-of-two image was uploaded (through a non standard client)
+ llinfos << "Non power of two width or height: (" << mRawImage->getWidth() << "," << mRawImage->getHeight() << ")" << llendl;
+ size_okay = false;
+ }
+
+ if( !size_okay )
+ {
+ // An inappropriately-sized image was uploaded (through a non standard client)
+ // We treat these images as missing assets which causes them to
+ // be renderd as 'missing image' and to stop requesting data
+ setIsMissingAsset();
+ destroyRawImage();
+ return FALSE;
+ }
+
+ if(!(res = insertToAtlas()))
+ {
+ res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename, TRUE, mBoostLevel);
+ resetFaceAtlas() ;
+ }
+ setActive() ;
+ }
+
+ //
+ // Iterate through the list of image loading callbacks to see
+ // what sort of data they need.
+ //
+ // *TODO: Fix image callback code
+ BOOL imageraw_callbacks = FALSE;
+ for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
+ iter != mLoadedCallbackList.end(); )
+ {
+ LLLoadedCallbackEntry *entryp = *iter++;
+ if (entryp->mNeedsImageRaw)
+ {
+ imageraw_callbacks = TRUE;
+ break;
+ }
+ }
+
+ if (!imageraw_callbacks)
+ {
+ mNeedsAux = FALSE;
+ destroyRawImage();
+ }
+ return res;
+}
+
+// Call with 0,0 to turn this feature off.
+//virtual
+void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height)
+{
+ if(mKnownDrawWidth != width || mKnownDrawHeight != height)
+ {
+ mKnownDrawWidth = width;
+ mKnownDrawHeight = height;
+
+ mKnownDrawSizeChanged = TRUE ;
+ mFullyLoaded = FALSE ;
+ }
+ addTextureStats((F32)(width * height));
+}
+
+//virtual
+void LLViewerFetchedTexture::processTextureStats()
+{
+ if(mFullyLoaded)//already loaded
+ {
+ return ;
+ }
+
+ updateVirtualSize() ;
+
+ static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes");
+
+ if (textures_fullres)
+ {
+ mDesiredDiscardLevel = 0;
+ }
+ else if(!mFullWidth || !mFullHeight)
+ {
+ mDesiredDiscardLevel = getMaxDiscardLevel() ;
+ }
+ else
+ {
+ if(!mKnownDrawWidth || !mKnownDrawHeight || mFullWidth <= mKnownDrawWidth || mFullHeight <= mKnownDrawHeight)
+ {
+ if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
+ {
+ mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
+ }
+ else
+ {
+ mDesiredDiscardLevel = 0;
+ }
+ }
+ else if(mKnownDrawSizeChanged)//known draw size is set
+ {
+ mDesiredDiscardLevel = (S8)llmin(log((F32)mFullWidth / mKnownDrawWidth) / log_2,
+ log((F32)mFullHeight / mKnownDrawHeight) / log_2) ;
+ mDesiredDiscardLevel = llclamp(mDesiredDiscardLevel, (S8)0, (S8)getMaxDiscardLevel()) ;
+ }
+ mKnownDrawSizeChanged = FALSE ;
+
+ if(getDiscardLevel() >= 0 && (getDiscardLevel() <= mDesiredDiscardLevel))
+ {
+ mFullyLoaded = TRUE ;
+ }
+ }
+}
+
+F32 LLViewerFetchedTexture::calcDecodePriority()
+{
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+ if (mID == LLAppViewer::getTextureFetch()->mDebugID)
+ {
+ LLAppViewer::getTextureFetch()->mDebugCount++; // for setting breakpoints
+ }
+#endif
+
+ if(mFullyLoaded)//already loaded for static texture
+ {
+ return -4.0f ; //alreay fetched
+ }
+
+ if (mNeedsCreateTexture)
+ {
+ return mDecodePriority; // no change while waiting to create
+ }
+ if(mForceToSaveRawImage)
+ {
+ return maxDecodePriority() ;
+ }
+
+ S32 cur_discard = getDiscardLevel();
+ bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel));
+ F32 pixel_priority = fsqrtf(mMaxVirtualSize);
+
+ F32 priority;
+ if (mIsMissingAsset)
+ {
+ priority = 0.0f;
+ }
+ else if(mDesiredDiscardLevel >= cur_discard && cur_discard > -1)
+ {
+ priority = -1.0f ;
+ }
+ else if(mCachedRawDiscardLevel > -1 && mDesiredDiscardLevel >= mCachedRawDiscardLevel)
+ {
+ priority = -1.0f;
+ }
+ else if (mDesiredDiscardLevel > getMaxDiscardLevel())
+ {
+ // Don't decode anything we don't need
+ priority = -1.0f;
+ }
+ else if ((mBoostLevel == LLViewerTexture::BOOST_UI || mBoostLevel == LLViewerTexture::BOOST_ICON) && !have_all_data)
+ {
+ priority = 1.f;
+ }
+ else if (pixel_priority <= 0.f && !have_all_data)
+ {
+ // Not on screen but we might want some data
+ if (mBoostLevel > BOOST_HIGH)
+ {
+ // Always want high boosted images
+ priority = 1.f;
+ }
+ else
+ {
+ // Leave the priority as-is
+ return mDecodePriority;
+ }
+ }
+ else if (cur_discard < 0)
+ {
+ //texture does not have any data, so we don't know the size of the image, treat it like 32 * 32.
+ // priority range = 100,000 - 500,000
+ static const F64 log_2 = log(2.0);
+ F32 desired = (F32)(log(32.0/pixel_priority) / log_2);
+ S32 ddiscard = MAX_DISCARD_LEVEL - (S32)desired;
+ ddiscard = llclamp(ddiscard, 0, 4);
+ priority = (ddiscard+1)*100000.f;
+ }
+ else if ((mMinDiscardLevel > 0) && (cur_discard <= mMinDiscardLevel))
+ {
+ // larger mips are corrupted
+ priority = -3.0f;
+ }
+ else if (cur_discard <= mDesiredDiscardLevel)
+ {
+ priority = -4.0f;
+ }
+ else
+ {
+ // priority range = 100,000 - 500,000
+ S32 desired_discard = mDesiredDiscardLevel;
+ if (getDontDiscard())
+ {
+ desired_discard -= 2;
+ }
+ else if (!isJustBound() && mCachedRawImageReady)
+ {
+ if(mBoostLevel < BOOST_HIGH)
+ {
+ // We haven't rendered this in a while, de-prioritize it
+ desired_discard += 2;
+ }
+ //else
+ //{
+ // // We haven't rendered this in the last half second, and we have a cached raw image, leave the desired discard as-is
+ // desired_discard = cur_discard;
+ //}
+ }
+
+ S32 ddiscard = cur_discard - desired_discard;
+ ddiscard = llclamp(ddiscard, 0, 4);
+ priority = (ddiscard+1)*100000.f;
+ }
+
+ // Priority Formula:
+ // BOOST_HIGH + ADDITIONAL PRI + DELTA DISCARD + BOOST LEVEL + PIXELS
+ // [10,000,000] + [1-9,000,000] + [1-400,000] + [1-20,000] + [0-999]
+ if (priority > 0.0f)
+ {
+ pixel_priority = llclamp(pixel_priority, 0.0f, 999.f);
+
+ priority = pixel_priority + 1000.f * mBoostLevel;
+
+ if ( mBoostLevel > BOOST_HIGH)
+ {
+ priority += 10000000.f;
+ }
+
+ if(mAdditionalDecodePriority > 0.0f)
+ {
+ // 1-9
+ S32 additional_priority = (S32)(1.0f + mAdditionalDecodePriority*8.0f + .5f); // round
+ // priority range += 0-9,000,000
+ priority += 1000000.f * (F32)additional_priority;
+ }
+ }
+ return priority;
+}
+//============================================================================
+
+void LLViewerFetchedTexture::setDecodePriority(F32 priority)
+{
+ //llassert(!mInImageList); // firing a lot, figure out why
+ if (mInImageList) // above llassert() softened to a warning
+ {
+ llwarns << "BAD STUFF! mInImageList" << llendl;
+ }
+ mDecodePriority = priority;
+}
+
+void LLViewerFetchedTexture::setAdditionalDecodePriority(F32 priority)
+{
+ priority = llclamp(priority, 0.f, 1.f);
+ if(mAdditionalDecodePriority < priority)
+ {
+ mAdditionalDecodePriority = priority;
+ }
+}
+
+void LLViewerFetchedTexture::updateVirtualSize()
+{
+ if(mNeedsResetMaxVirtualSize)
+ {
+ addTextureStats(0.f, FALSE) ;//reset
+ }
+
+ for(U32 i = 0 ; i < mNumFaces ; i++)
+ {
+ LLFace* facep = mFaceList[i] ;
+ if(facep->getDrawable()->isRecentlyVisible())
+ {
+ addTextureStats(facep->getVirtualSize()) ;
+ setAdditionalDecodePriority(facep->getImportanceToCamera()) ;
+ }
+ }
+ mNeedsResetMaxVirtualSize = TRUE ;
+ reorganizeFaceList() ;
+}
+
+bool LLViewerFetchedTexture::updateFetch()
+{
+ static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled");
+ if(textures_decode_disabled)
+ {
+ return false ;
+ }
+
+ mFetchState = 0;
+ mFetchPriority = 0;
+ mFetchDeltaTime = 999999.f;
+ mRequestDeltaTime = 999999.f;
+
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+ if (mID == LLAppViewer::getTextureFetch()->mDebugID)
+ {
+ LLAppViewer::getTextureFetch()->mDebugCount++; // for setting breakpoints
+ }
+#endif
+
+ if (mNeedsCreateTexture)
+ {
+ // We may be fetching still (e.g. waiting on write)
+ // but don't check until we've processed the raw data we have
+ return false;
+ }
+ if (mIsMissingAsset)
+ {
+ llassert_always(!mHasFetcher);
+ return false; // skip
+ }
+ if (!mLoadedCallbackList.empty() && mRawImage.notNull())
+ {
+ return false; // process any raw image data in callbacks before replacing
+ }
+
+ S32 current_discard = getDiscardLevel() ;
+ S32 desired_discard = getDesiredDiscardLevel();
+ F32 decode_priority = getDecodePriority();
+ decode_priority = llmax(decode_priority, 0.0f);
+
+ if (mIsFetching)
+ {
+ // Sets mRawDiscardLevel, mRawImage, mAuxRawImage
+ S32 fetch_discard = current_discard;
+
+ if(mForceToSaveRawImage)
+ {
+ if(fetch_discard >= 0)
+ {
+ fetch_discard = llmax(fetch_discard, mSavedRawDiscardLevel) ;
+ }
+ }
+
+ if (mRawImage.notNull()) sRawCount--;
+ if (mAuxRawImage.notNull()) sAuxCount--;
+ bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage);
+ if (mRawImage.notNull()) sRawCount++;
+ if (mAuxRawImage.notNull()) sAuxCount++;
+ if (finished)
+ {
+ mIsFetching = FALSE;
+ }
+ else
+ {
+ mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority,
+ mFetchPriority, mFetchDeltaTime, mRequestDeltaTime);
+ }
+
+ // We may have data ready regardless of whether or not we are finished (e.g. waiting on write)
+ if (mRawImage.notNull())
+ {
+ if(LLViewerTextureManager::sTesterp)
+ {
+ mIsFetched = TRUE ;
+ LLViewerTextureManager::sTesterp->updateTextureLoadingStats(this, mRawImage, LLAppViewer::getTextureFetch()->isFromLocalCache(mID)) ;
+ }
+ mRawDiscardLevel = fetch_discard;
+ if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) &&
+ (current_discard < 0 || mRawDiscardLevel < current_discard))
+ {
+ if (getComponents() != mRawImage->getComponents())
+ {
+ // We've changed the number of components, so we need to move any
+ // objects using this pool to a different pool.
+ mComponents = mRawImage->getComponents();
+ mGLTexturep->setComponents(mComponents) ;
+
+ for(U32 i = 0 ; i < mNumFaces ; i++)
+ {
+ mFaceList[i]->dirtyTexture() ;
+ }
+ }
+ mFullWidth = mRawImage->getWidth() << mRawDiscardLevel;
+ mFullHeight = mRawImage->getHeight() << mRawDiscardLevel;
+
+ if(mFullWidth > MAX_IMAGE_SIZE || mFullHeight > MAX_IMAGE_SIZE)
+ {
+ //discard all oversized textures.
+ destroyRawImage();
+ setIsMissingAsset();
+ mRawDiscardLevel = INVALID_DISCARD_LEVEL ;
+ mIsFetching = FALSE ;
+ }
+ else
+ {
+ mIsRawImageValid = TRUE;
+ addToCreateTexture() ;
+ }
+
+ return TRUE ;
+ }
+ else
+ {
+ // Data is ready but we don't need it
+ // (received it already while fetcher was writing to disk)
+ destroyRawImage();
+ return false; // done
+ }
+ }
+
+ if (!mIsFetching)
+ {
+ if ((decode_priority > 0) && (mRawDiscardLevel < 0 || mRawDiscardLevel == INVALID_DISCARD_LEVEL))
+ {
+ // We finished but received no data
+ if (current_discard < 0)
+ {
+ setIsMissingAsset();
+ desired_discard = -1;
+ }
+ else
+ {
+ //llwarns << mID << ": Setting min discard to " << current_discard << llendl;
+ mMinDiscardLevel = current_discard;
+ desired_discard = current_discard;
+ }
+ destroyRawImage();
+ }
+ else if (mRawImage.notNull())
+ {
+ // We have data, but our fetch failed to return raw data
+ // *TODO: FIgure out why this is happening and fix it
+ destroyRawImage();
+ }
+ }
+ else
+ {
+// // Useful debugging code for undesired deprioritization of textures.
+// if (decode_priority <= 0.0f && desired_discard >= 0 && desired_discard < current_discard)
+// {
+// llinfos << "Calling updateRequestPriority() with decode_priority = 0.0f" << llendl;
+// calcDecodePriority();
+// }
+ LLAppViewer::getTextureFetch()->updateRequestPriority(mID, decode_priority);
+ }
+ }
+
+ if (!mDontDiscard)
+ {
+ if (mBoostLevel == 0)
+ {
+ desired_discard = llmax(desired_discard, current_discard-1);
+ }
+ else
+ {
+ desired_discard = llmax(desired_discard, current_discard-2);
+ }
+ }
+
+ bool make_request = true;
+ if (decode_priority <= 0)
+ {
+ make_request = false;
+ }
+ else if (mNeedsCreateTexture || mIsMissingAsset)
+ {
+ make_request = false;
+ }
+ else if (current_discard >= 0 && current_discard <= mMinDiscardLevel)
+ {
+ make_request = false;
+ }
+ //else if (!isJustBound() && mCachedRawImageReady)
+ //{
+ // make_request = false;
+ //}
+ else
+ {
+ if (mIsFetching)
+ {
+ if (mRequestedDiscardLevel <= desired_discard)
+ {
+ make_request = false;
+ }
+ }
+ else
+ {
+ if (current_discard >= 0 && current_discard <= desired_discard)
+ {
+ make_request = false;
+ }
+ }
+ }
+
+ if (make_request)
+ {
+ S32 w=0, h=0, c=0;
+ if (current_discard >= 0)
+ {
+ w = mGLTexturep->getWidth(0);
+ h = mGLTexturep->getHeight(0);
+ c = mComponents;
+ }
+
+ // bypass texturefetch directly by pulling from LLTextureCache
+ bool fetch_request_created = false;
+ fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mUrl, getID(),getTargetHost(), decode_priority,
+ w, h, c, desired_discard, needsAux());
+
+ if (fetch_request_created)
+ {
+ mHasFetcher = TRUE;
+ mIsFetching = TRUE;
+ mRequestedDiscardLevel = desired_discard;
+ mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority,
+ mFetchPriority, mFetchDeltaTime, mRequestDeltaTime);
+ }
+
+ // if createRequest() failed, we're finishing up a request for this UUID,
+ // wait for it to complete
+ }
+ else if (mHasFetcher && !mIsFetching)
+ {
+ // Only delete requests that haven't receeived any network data for a while
+ const F32 FETCH_IDLE_TIME = 5.f;
+ if (mLastPacketTimer.getElapsedTimeF32() > FETCH_IDLE_TIME)
+ {
+// llinfos << "Deleting request: " << getID() << " Discard: " << current_discard << " <= min:" << mMinDiscardLevel << " or priority == 0: " << decode_priority << llendl;
+ LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
+ mHasFetcher = FALSE;
+ }
+ }
+
+ llassert_always(mRawImage.notNull() || (!mNeedsCreateTexture && !mIsRawImageValid));
+
+ return mIsFetching ? true : false;
+}
+
+//
+//force to fetch a new raw image for this texture
+//
+BOOL LLViewerFetchedTexture::forceFetch()
+{
+ if(!mForceToSaveRawImage)
+ {
+ return false ;
+ }
+ //if(mDesiredSavedRawDiscardLevel < getDiscardLevel())
+ {
+ //no need to force fetching. normal fetching flow will do the work.
+ //return false ;
+ }
+ //if (mNeedsCreateTexture)
+ {
+ // We may be fetching still (e.g. waiting on write)
+ // but don't check until we've processed the raw data we have
+ //return false;
+ }
+ if(mIsFetching)
+ {
+ return false ;
+ }
+ if (mIsMissingAsset)
+ {
+ mForceToSaveRawImage = false ;
+ llassert_always(!mHasFetcher);
+ return false; // skip
+ }
+ if (!mLoadedCallbackList.empty() && mRawImage.notNull())
+ {
+ return false; // process any raw image data in callbacks before replacing
+ }
+ if(mRawImage.notNull() && mRawDiscardLevel <= mDesiredSavedRawDiscardLevel)
+ {
+ return false ; // mRawImage is enough
+ }
+
+ S32 desired_discard = mDesiredSavedRawDiscardLevel ;
+ S32 current_discard = getDiscardLevel();
+
+ bool fetch_request_created = false;
+ S32 w=0, h=0, c=0;
+ if (current_discard >= 0)
+ {
+ w = getWidth(0);
+ h = getHeight(0);
+ c = getComponents();
+ }
+ setDecodePriority(maxDecodePriority()) ;
+ fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mUrl, getID(),getTargetHost(), getDecodePriority(),
+ w, h, c, desired_discard, needsAux());
+
+ if (fetch_request_created)
+ {
+ mHasFetcher = TRUE;
+ mIsFetching = TRUE;
+ mRequestedDiscardLevel = desired_discard ;
+
+ mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority,
+ mFetchPriority, mFetchDeltaTime, mRequestDeltaTime);
+ }
+
+ return mIsFetching ? true : false;
+}
+
+void LLViewerFetchedTexture::setIsMissingAsset()
+{
+ if (mUrl.empty())
+ {
+ llwarns << mID << ": Marking image as missing" << llendl;
+ }
+ else
+ {
+ llwarns << mUrl << ": Marking image as missing" << llendl;
+ }
+ if (mHasFetcher)
+ {
+ LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
+ mHasFetcher = FALSE;
+ mIsFetching = FALSE;
+ mFetchState = 0;
+ mFetchPriority = 0;
+ }
+ mIsMissingAsset = TRUE;
+}
+
+void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_callback,
+ S32 discard_level, BOOL keep_imageraw, BOOL needs_aux, void* userdata)
+{
+ //
+ // Don't do ANYTHING here, just add it to the global callback list
+ //
+ if (mLoadedCallbackList.empty())
+ {
+ // Put in list to call this->doLoadedCallbacks() periodically
+ gTextureList.mCallbackList.insert(this);
+ mLoadedCallbackDesiredDiscardLevel = (S8)discard_level;
+ }
+ else
+ {
+ mLoadedCallbackDesiredDiscardLevel = llmin(mLoadedCallbackDesiredDiscardLevel, (S8)discard_level) ;
+ }
+
+ LLLoadedCallbackEntry* entryp = new LLLoadedCallbackEntry(loaded_callback, discard_level, keep_imageraw, userdata);
+ mLoadedCallbackList.push_back(entryp);
+ mNeedsAux |= needs_aux;
+ if (mNeedsAux && mAuxRawImage.isNull() && getDiscardLevel() >= 0)
+ {
+ // We need aux data, but we've already loaded the image, and it didn't have any
+ llwarns << "No aux data available for callback for image:" << getID() << llendl;
+ }
+}
+
+bool LLViewerFetchedTexture::doLoadedCallbacks()
+{
+ if (mNeedsCreateTexture)
+ {
+ return false;
+ }
+
+ bool res = false;
+
+ if (isMissingAsset())
+ {
+ for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
+ iter != mLoadedCallbackList.end(); )
+ {
+ LLLoadedCallbackEntry *entryp = *iter++;
+ // We never finished loading the image. Indicate failure.
+ // Note: this allows mLoadedCallbackUserData to be cleaned up.
+ entryp->mCallback(FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData);
+ delete entryp;
+ }
+ mLoadedCallbackList.clear();
+
+ // Remove ourself from the global list of textures with callbacks
+ gTextureList.mCallbackList.erase(this);
+ }
+
+ S32 gl_discard = getDiscardLevel();
+
+ // If we don't have a legit GL image, set it to be lower than the worst discard level
+ if (gl_discard == -1)
+ {
+ gl_discard = MAX_DISCARD_LEVEL + 1;
+ }
+
+ //
+ // Determine the quality levels of textures that we can provide to callbacks
+ // and whether we need to do decompression/readback to get it
+ //
+ S32 current_raw_discard = MAX_DISCARD_LEVEL + 1; // We can always do a readback to get a raw discard
+ S32 best_raw_discard = gl_discard; // Current GL quality level
+ S32 current_aux_discard = MAX_DISCARD_LEVEL + 1;
+ S32 best_aux_discard = MAX_DISCARD_LEVEL + 1;
+
+ if (mIsRawImageValid)
+ {
+ // If we have an existing raw image, we have a baseline for the raw and auxiliary quality levels.
+ best_raw_discard = llmin(best_raw_discard, mRawDiscardLevel);
+ best_aux_discard = llmin(best_aux_discard, mRawDiscardLevel); // We always decode the aux when we decode the base raw
+ current_aux_discard = llmin(current_aux_discard, best_aux_discard);
+ }
+ else
+ {
+ // We have no data at all, we need to get it
+ // Do this by forcing the best aux discard to be 0.
+ best_aux_discard = 0;
+ }
+
+
+ //
+ // See if any of the callbacks would actually run using the data that we can provide,
+ // and also determine if we need to perform any readbacks or decodes.
+ //
+ bool run_gl_callbacks = false;
+ bool run_raw_callbacks = false;
+ bool need_readback = false;
+
+ for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
+ iter != mLoadedCallbackList.end(); )
+ {
+ LLLoadedCallbackEntry *entryp = *iter++;
+ if (entryp->mNeedsImageRaw)
+ {
+ if (mNeedsAux)
+ {
+ //
+ // Need raw and auxiliary channels
+ //
+ if (entryp->mLastUsedDiscard > current_aux_discard)
+ {
+ // We have useful data, run the callbacks
+ run_raw_callbacks = true;
+ }
+ }
+ else
+ {
+ if (entryp->mLastUsedDiscard > current_raw_discard)
+ {
+ // We have useful data, just run the callbacks
+ run_raw_callbacks = true;
+ }
+ else if (entryp->mLastUsedDiscard > best_raw_discard)
+ {
+ // We can readback data, and then run the callbacks
+ need_readback = true;
+ run_raw_callbacks = true;
+ }
+ }
+ }
+ else
+ {
+ // Needs just GL
+ if (entryp->mLastUsedDiscard > gl_discard)
+ {
+ // We have enough data, run this callback requiring GL data
+ run_gl_callbacks = true;
+ }
+ }
+ }
+
+ //
+ // Do a readback if required, OR start off a texture decode
+ //
+ if (need_readback && (getMaxDiscardLevel() > gl_discard))
+ {
+ // Do a readback to get the GL data into the raw image
+ // We have GL data.
+
+ destroyRawImage();
+ reloadRawImage(mLoadedCallbackDesiredDiscardLevel);
+ llassert_always(mRawImage.notNull());
+ llassert_always(!mNeedsAux || mAuxRawImage.notNull());
+ }
+
+ //
+ // Run raw/auxiliary data callbacks
+ //
+ if (run_raw_callbacks && mIsRawImageValid && (mRawDiscardLevel <= getMaxDiscardLevel()))
+ {
+ // Do callbacks which require raw image data.
+ //llinfos << "doLoadedCallbacks raw for " << getID() << llendl;
+
+ // Call each party interested in the raw data.
+ for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
+ iter != mLoadedCallbackList.end(); )
+ {
+ callback_list_t::iterator curiter = iter++;
+ LLLoadedCallbackEntry *entryp = *curiter;
+ if (entryp->mNeedsImageRaw && (entryp->mLastUsedDiscard > mRawDiscardLevel))
+ {
+ // If we've loaded all the data there is to load or we've loaded enough
+ // to satisfy the interested party, then this is the last time that
+ // we're going to call them.
+
+ llassert_always(mRawImage.notNull());
+ if(mNeedsAux && mAuxRawImage.isNull())
+ {
+ llwarns << "Raw Image with no Aux Data for callback" << llendl;
+ }
+ BOOL final = mRawDiscardLevel <= entryp->mDesiredDiscard ? TRUE : FALSE;
+ //llinfos << "Running callback for " << getID() << llendl;
+ //llinfos << mRawImage->getWidth() << "x" << mRawImage->getHeight() << llendl;
+ if (final)
+ {
+ //llinfos << "Final!" << llendl;
+ }
+ entryp->mLastUsedDiscard = mRawDiscardLevel;
+ entryp->mCallback(TRUE, this, mRawImage, mAuxRawImage, mRawDiscardLevel, final, entryp->mUserData);
+ if (final)
+ {
+ iter = mLoadedCallbackList.erase(curiter);
+ delete entryp;
+ }
+ res = true;
+ }
+ }
+ }
+
+ //
+ // Run GL callbacks
+ //
+ if (run_gl_callbacks && (gl_discard <= getMaxDiscardLevel()))
+ {
+ //llinfos << "doLoadedCallbacks GL for " << getID() << llendl;
+
+ // Call the callbacks interested in GL data.
+ for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
+ iter != mLoadedCallbackList.end(); )
+ {
+ callback_list_t::iterator curiter = iter++;
+ LLLoadedCallbackEntry *entryp = *curiter;
+ if (!entryp->mNeedsImageRaw && (entryp->mLastUsedDiscard > gl_discard))
+ {
+ BOOL final = gl_discard <= entryp->mDesiredDiscard ? TRUE : FALSE;
+ entryp->mLastUsedDiscard = gl_discard;
+ entryp->mCallback(TRUE, this, NULL, NULL, gl_discard, final, entryp->mUserData);
+ if (final)
+ {
+ iter = mLoadedCallbackList.erase(curiter);
+ delete entryp;
+ }
+ res = true;
+ }
+ }
+ }
+
+ //
+ // If we have no callbacks, take us off of the image callback list.
+ //
+ if (mLoadedCallbackList.empty())
+ {
+ gTextureList.mCallbackList.erase(this);
+ }
+
+ // Done with any raw image data at this point (will be re-created if we still have callbacks)
+ destroyRawImage();
+
+ return res;
+}
+
+//virtual
+void LLViewerFetchedTexture::forceImmediateUpdate()
+{
+ //only immediately update a deleted texture which is now being re-used.
+ if(!isDeleted())
+ {
+ return ;
+ }
+ //if already called forceImmediateUpdate()
+ if(mInImageList && mDecodePriority == LLViewerFetchedTexture::maxDecodePriority())
+ {
+ return ;
+ }
+
+ gTextureList.forceImmediateUpdate(this) ;
+ return ;
+}
+
+LLImageRaw* LLViewerFetchedTexture::reloadRawImage(S8 discard_level)
+{
+ llassert_always(mGLTexturep.notNull()) ;
+ llassert_always(discard_level >= 0);
+ llassert_always(mComponents > 0);
+
+ if (mRawImage.notNull())
+ {
+ //mRawImage is in use by somebody else, do not delete it.
+ return NULL ;
+ }
+
+ if(mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= discard_level)
+ {
+ mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()) ;
+ mRawImage->copy(getSavedRawImage()) ;
+ mRawDiscardLevel = discard_level ;
+ }
+ else
+ {
+ //force to fetch raw image again if cached raw image is not good enough.
+ if(mCachedRawDiscardLevel > discard_level)
+ {
+ mRawImage = mCachedRawImage ;
+ mRawDiscardLevel = mCachedRawDiscardLevel;
+
+ forceToSaveRawImage(discard_level) ;
+ }
+ else //cached raw image is good enough, copy it.
+ {
+ mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()) ;
+ mRawImage->copy(mCachedRawImage) ;
+ mRawDiscardLevel = discard_level ;
+ }
+ }
+ mIsRawImageValid = TRUE ;
+ sRawCount++;
+
+ return mRawImage;
+}
+
+void LLViewerFetchedTexture::destroyRawImage()
+{
+ if (mAuxRawImage.notNull()) sAuxCount--;
+
+ if (mRawImage.notNull())
+ {
+ sRawCount--;
+ setCachedRawImage() ;
+
+ if(mForceToSaveRawImage)
+ {
+ saveRawImage() ;
+ }
+ }
+
+ mRawImage = NULL;
+ mAuxRawImage = NULL;
+ mIsRawImageValid = FALSE;
+ mRawDiscardLevel = INVALID_DISCARD_LEVEL;
+
+ if(mForceToSaveRawImage)
+ {
+ forceFetch() ;
+ }
+}
+
+//use the mCachedRawImage to (re)generate the gl texture.
+//virtual
+void LLViewerFetchedTexture::switchToCachedImage()
+{
+ if(mCachedRawImage.notNull())
+ {
+ mRawImage = mCachedRawImage ;
+
+ if (getComponents() != mRawImage->getComponents())
+ {
+ // We've changed the number of components, so we need to move any
+ // objects using this pool to a different pool.
+ mComponents = mRawImage->getComponents();
+ mGLTexturep->setComponents(mComponents) ;
+ gTextureList.dirtyImage(this);
+ }
+
+ mIsRawImageValid = TRUE;
+ mRawDiscardLevel = mCachedRawDiscardLevel ;
+ gTextureList.mCreateTextureList.insert(this);
+ mNeedsCreateTexture = TRUE;
+ }
+}
+
+void LLViewerFetchedTexture::setCachedRawImage()
+{
+ if(mRawImage == mCachedRawImage)
+ {
+ return ;
+ }
+ if(!mIsRawImageValid)
+ {
+ return ;
+ }
+
+ if(mCachedRawImageReady)
+ {
+ return ;
+ }
+
+ if(mCachedRawDiscardLevel < 0 || mCachedRawDiscardLevel > mRawDiscardLevel)
+ {
+ S32 i = 0 ;
+ S32 w = mRawImage->getWidth() ;
+ S32 h = mRawImage->getHeight() ;
+
+ S32 max_size = MAX_CACHED_RAW_IMAGE_AREA ;
+ if(LLViewerTexture::BOOST_TERRAIN == mBoostLevel)
+ {
+ max_size = MAX_CACHED_RAW_TERRAIN_IMAGE_AREA ;
+ }
+ if(mForSculpt)
+ {
+ max_size = MAX_CACHED_RAW_SCULPT_IMAGE_AREA ;
+ mCachedRawImageReady = !mRawDiscardLevel ;
+ }
+ else
+ {
+ mCachedRawImageReady = (!mRawDiscardLevel || ((w * h) >= max_size)) ;
+ }
+
+ while(((w >> i) * (h >> i)) > max_size)
+ {
+ ++i ;
+ }
+
+ if(i)
+ {
+ if(!(w >> i) || !(h >> i))
+ {
+ --i ;
+ }
+ //if(mForSculpt)
+ //{
+ // mRawImage->scaleDownWithoutBlending(w >> i, h >> i) ;
+ //}
+ //else
+ {
+ mRawImage->scale(w >> i, h >> i) ;
+ }
+ }
+ mCachedRawImage = mRawImage ;
+ mCachedRawDiscardLevel = mRawDiscardLevel + i ;
+ }
+}
+
+void LLViewerFetchedTexture::checkCachedRawSculptImage()
+{
+ if(mCachedRawImageReady && mCachedRawDiscardLevel > 0)
+ {
+ if(getDiscardLevel() != 0)
+ {
+ mCachedRawImageReady = FALSE ;
+ }
+ else if(isForSculptOnly())
+ {
+ resetTextureStats() ; //do not update this image any more.
+ }
+ }
+}
+
+void LLViewerFetchedTexture::saveRawImage()
+{
+ if(mRawImage.isNull() || mSavedRawDiscardLevel == mRawDiscardLevel)
+ {
+ return ;
+ }
+
+ mSavedRawDiscardLevel = mRawDiscardLevel ;
+ mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents()) ;
+
+ if(mSavedRawDiscardLevel <= mDesiredSavedRawDiscardLevel)
+ {
+ mForceToSaveRawImage = FALSE ;
+ }
+
+ mLastReferencedSavedRawImageTime = sCurrentTime ;
+}
+
+void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard)
+{
+ if(!mForceToSaveRawImage && (mDesiredSavedRawDiscardLevel < 0 || mDesiredSavedRawDiscardLevel > desired_discard))
+ {
+ mForceToSaveRawImage = TRUE ;
+ mDesiredSavedRawDiscardLevel = desired_discard ;
+
+ forceFetch() ;
+ }
+}
+void LLViewerFetchedTexture::destroySavedRawImage()
+{
+ mSavedRawImage = NULL ;
+ mForceToSaveRawImage = FALSE ;
+ mSavedRawDiscardLevel = -1 ;
+ mDesiredSavedRawDiscardLevel = -1 ;
+ mLastReferencedSavedRawImageTime = 0.0f ;
+}
+
+LLImageRaw* LLViewerFetchedTexture::getSavedRawImage()
+{
+ mLastReferencedSavedRawImageTime = sCurrentTime ;
+
+ return mSavedRawImage ;
+}
+
+BOOL LLViewerFetchedTexture::hasSavedRawImage() const
+{
+ return mSavedRawImage.notNull() ;
+}
+
+F32 LLViewerFetchedTexture::getElapsedLastReferencedSavedRawImageTime() const
+{
+ return mLastReferencedSavedRawImageTime - sCurrentTime ;
+}
+//----------------------------------------------------------------------------------------------
+//atlasing
+//----------------------------------------------------------------------------------------------
+void LLViewerFetchedTexture::resetFaceAtlas()
+{
+ //Nothing should be done here.
+}
+
+//invalidate all atlas slots for this image.
+void LLViewerFetchedTexture::invalidateAtlas(BOOL rebuild_geom)
+{
+ for(U32 i = 0 ; i < mNumFaces ; i++)
+ {
+ LLFace* facep = mFaceList[i] ;
+ facep->removeAtlas() ;
+ if(rebuild_geom && facep->getDrawable() && facep->getDrawable()->getSpatialGroup())
+ {
+ facep->getDrawable()->getSpatialGroup()->setState(LLSpatialGroup::GEOM_DIRTY);
+ }
+ }
+}
+
+BOOL LLViewerFetchedTexture::insertToAtlas()
+{
+ if(!LLViewerTexture::sUseTextureAtlas)
+ {
+ return FALSE ;
+ }
+ if(getNumFaces() < 1)
+ {
+ return FALSE ;
+ }
+ if(mGLTexturep->getDiscardLevelInAtlas() > 0 && mRawDiscardLevel >= mGLTexturep->getDiscardLevelInAtlas())
+ {
+ return FALSE ;
+ }
+ if(!LLTextureAtlasManager::getInstance()->canAddToAtlas(mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents(), mGLTexturep->getTexTarget()))
+ {
+ return FALSE ;
+ }
+
+ BOOL ret = TRUE ;//if ret is set to false, will generate a gl texture for this image.
+ S32 raw_w = mRawImage->getWidth() ;
+ S32 raw_h = mRawImage->getHeight() ;
+ F32 xscale = 1.0f, yscale = 1.0f ;
+ LLPointer<LLTextureAtlasSlot> slot_infop;
+ LLTextureAtlasSlot* cur_slotp ;//no need to be smart pointer.
+ LLSpatialGroup* groupp ;
+ LLFace* facep;
+
+ //if the atlas slot pointers for some faces are null, process them later.
+ ll_face_list_t waiting_list ;
+ for(U32 i = 0 ; i < mNumFaces ; i++)
+ {
+ {
+ facep = mFaceList[i] ;
+
+ //face can not use atlas.
+ if(!facep->canUseAtlas())
+ {
+ if(facep->getAtlasInfo())
+ {
+ facep->removeAtlas() ;
+ }
+ ret = FALSE ;
+ continue ;
+ }
+
+ //the atlas slot is updated
+ slot_infop = facep->getAtlasInfo() ;
+ groupp = facep->getDrawable()->getSpatialGroup() ;
+
+ if(slot_infop)
+ {
+ if(slot_infop->getSpatialGroup() != groupp)
+ {
+ if((cur_slotp = groupp->getCurUpdatingSlot(this))) //switch slot
+ {
+ facep->setAtlasInfo(cur_slotp) ;
+ facep->setAtlasInUse(TRUE) ;
+ continue ;
+ }
+ else //do not forget to update slot_infop->getSpatialGroup().
+ {
+ LLSpatialGroup* gp = slot_infop->getSpatialGroup() ;
+ gp->setCurUpdatingTime(gFrameCount) ;
+ gp->setCurUpdatingTexture(this) ;
+ gp->setCurUpdatingSlot(slot_infop) ;
+ }
+ }
+ else //same group
+ {
+ if(gFrameCount && slot_infop->getUpdatedTime() == gFrameCount)//slot is just updated
+ {
+ facep->setAtlasInUse(TRUE) ;
+ continue ;
+ }
+ }
+ }
+ else
+ {
+ //if the slot is null, wait to process them later.
+ waiting_list.push_back(facep) ;
+ continue ;
+ }
+
+ //----------
+ //insert to atlas
+ if(!slot_infop->getAtlas()->insertSubTexture(mGLTexturep, mRawDiscardLevel, mRawImage, slot_infop->getSlotCol(), slot_infop->getSlotRow()))
+ {
+
+ //the texture does not qualify to add to atlas, do not bother to try for other faces.
+ //invalidateAtlas();
+ return FALSE ;
+ }
+
+ //update texture scale
+ slot_infop->getAtlas()->getTexCoordScale(raw_w, raw_h, xscale, yscale) ;
+ slot_infop->setTexCoordScale(xscale, yscale) ;
+ slot_infop->setValid() ;
+ slot_infop->setUpdatedTime(gFrameCount) ;
+
+ //update spatial group atlas info
+ groupp->setCurUpdatingTime(gFrameCount) ;
+ groupp->setCurUpdatingTexture(this) ;
+ groupp->setCurUpdatingSlot(slot_infop) ;
+
+ //make the face to switch to the atlas.
+ facep->setAtlasInUse(TRUE) ;
+ }
+ }
+
+ //process the waiting_list
+ for(ll_face_list_t::iterator iter = waiting_list.begin(); iter != waiting_list.end(); ++iter)
+ {
+ facep = (LLFace*)*iter ;
+ groupp = facep->getDrawable()->getSpatialGroup() ;
+
+ //check if this texture already inserted to atlas for this group
+ if((cur_slotp = groupp->getCurUpdatingSlot(this)))
+ {
+ facep->setAtlasInfo(cur_slotp) ;
+ facep->setAtlasInUse(TRUE) ;
+ continue ;
+ }
+
+ //need to reserve a slot from atlas
+ slot_infop = LLTextureAtlasManager::getInstance()->reserveAtlasSlot(llmax(mFullWidth, mFullHeight), getComponents(), groupp, this) ;
+
+ facep->setAtlasInfo(slot_infop) ;
+
+ groupp->setCurUpdatingTime(gFrameCount) ;
+ groupp->setCurUpdatingTexture(this) ;
+ groupp->setCurUpdatingSlot(slot_infop) ;
+
+ //slot allocation failed.
+ if(!slot_infop || !slot_infop->getAtlas())
+ {
+ ret = FALSE ;
+ facep->setAtlasInUse(FALSE) ;
+ continue ;
+ }
+
+ //insert to atlas
+ if(!slot_infop->getAtlas()->insertSubTexture(mGLTexturep, mRawDiscardLevel, mRawImage, slot_infop->getSlotCol(), slot_infop->getSlotRow()))
+ {
+ //the texture does not qualify to add to atlas, do not bother to try for other faces.
+ ret = FALSE ;
+ //invalidateAtlas();
+ break ;
+ }
+
+ //update texture scale
+ slot_infop->getAtlas()->getTexCoordScale(raw_w, raw_h, xscale, yscale) ;
+ slot_infop->setTexCoordScale(xscale, yscale) ;
+ slot_infop->setValid() ;
+ slot_infop->setUpdatedTime(gFrameCount) ;
+
+ //make the face to switch to the atlas.
+ facep->setAtlasInUse(TRUE) ;
+ }
+
+ return ret ;
+}
+
+//----------------------------------------------------------------------------------------------
+//end of LLViewerFetchedTexture
+//----------------------------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------------------------
+//start of LLViewerLODTexture
+//----------------------------------------------------------------------------------------------
+LLViewerLODTexture::LLViewerLODTexture(const LLUUID& id, const LLHost& host, BOOL usemipmaps)
+ : LLViewerFetchedTexture(id, host, usemipmaps)
+{
+ init(TRUE) ;
+}
+
+LLViewerLODTexture::LLViewerLODTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps)
+ : LLViewerFetchedTexture(url, id, usemipmaps)
+{
+ init(TRUE) ;
+}
+
+void LLViewerLODTexture::init(bool firstinit)
+{
+ mTexelsPerImage = 64.f*64.f;
+ mDiscardVirtualSize = 0.f;
+ mCalculatedDiscardLevel = -1.f;
+}
+
+//virtual
+S8 LLViewerLODTexture::getType() const
+{
+ return LLViewerTexture::LOD_TEXTURE ;
+}
+
+BOOL LLViewerLODTexture::isUpdateFrozen()
+{
+ return LLViewerTexture::sFreezeImageScalingDown && !getDiscardLevel() ;
+}
+
+// This is gauranteed to get called periodically for every texture
+//virtual
+void LLViewerLODTexture::processTextureStats()
+{
+ updateVirtualSize() ;
+
+ static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes");
+
+ if (textures_fullres)
+ {
+ mDesiredDiscardLevel = 0;
+ }
+ // Generate the request priority and render priority
+ else if (mDontDiscard || !mUseMipMaps)
+ {
+ mDesiredDiscardLevel = 0;
+ if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
+ mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
+ }
+ else if (mBoostLevel < LLViewerTexture::BOOST_HIGH && mMaxVirtualSize <= 10.f)
+ {
+ // If the image has not been significantly visible in a while, we don't want it
+ mDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel, (S8)(MAX_DISCARD_LEVEL + 1));
+ }
+ else if (!mFullWidth || !mFullHeight)
+ {
+ mDesiredDiscardLevel = getMaxDiscardLevel() ;
+ }
+ else
+ {
+ //static const F64 log_2 = log(2.0);
+ static const F64 log_4 = log(4.0);
+
+ S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT);
+ S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT);
+ mTexelsPerImage = (F32)fullwidth * fullheight;
+
+ F32 discard_level = 0.f;
+
+ // If we know the output width and height, we can force the discard
+ // level to the correct value, and thus not decode more texture
+ // data than we need to.
+ if (mKnownDrawWidth && mKnownDrawHeight)
+ {
+ S32 draw_texels = mKnownDrawWidth * mKnownDrawHeight;
+
+ // Use log_4 because we're in square-pixel space, so an image
+ // with twice the width and twice the height will have mTexelsPerImage
+ // 4 * draw_size
+ discard_level = (F32)(log(mTexelsPerImage/draw_texels) / log_4);
+ }
+ else
+ {
+ if(isLargeImage() && !isJustBound() && mAdditionalDecodePriority < 1.0f)
+ {
+ //if is a big image and not being used recently, nor close to the view point, do not load hi-res data.
+ mMaxVirtualSize = llmin(mMaxVirtualSize, (F32)LLViewerTexture::sMinLargeImageSize) ;
+ }
+
+ if ((mCalculatedDiscardLevel >= 0.f) &&
+ (llabs(mMaxVirtualSize - mDiscardVirtualSize) < mMaxVirtualSize*.20f))
+ {
+ // < 20% change in virtual size = no change in desired discard
+ discard_level = mCalculatedDiscardLevel;
+ }
+ else
+ {
+ // Calculate the required scale factor of the image using pixels per texel
+ discard_level = (F32)(log(mTexelsPerImage/mMaxVirtualSize) / log_4);
+ mDiscardVirtualSize = mMaxVirtualSize;
+ mCalculatedDiscardLevel = discard_level;
+ }
+ }
+ if (mBoostLevel < LLViewerTexture::BOOST_HIGH)
+ {
+ discard_level += sDesiredDiscardBias;
+ discard_level *= sDesiredDiscardScale; // scale
+ discard_level += sCameraMovingDiscardBias ;
+ }
+ discard_level = floorf(discard_level);
+
+ F32 min_discard = 0.f;
+ if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
+ min_discard = 1.f; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
+
+ discard_level = llclamp(discard_level, min_discard, (F32)MAX_DISCARD_LEVEL);
+
+ // Can't go higher than the max discard level
+ mDesiredDiscardLevel = llmin(getMaxDiscardLevel() + 1, (S32)discard_level);
+ // Clamp to min desired discard
+ mDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel, mDesiredDiscardLevel);
+
+ //
+ // At this point we've calculated the quality level that we want,
+ // if possible. Now we check to see if we have it, and take the
+ // proper action if we don't.
+ //
+
+ S32 current_discard = getDiscardLevel();
+ if ((sDesiredDiscardBias > 0.0f) &&
+ (current_discard >= 0 && mDesiredDiscardLevel >= current_discard))
+ {
+ // Limit the amount of GL memory bound each frame
+ if ( BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale &&
+ (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel))
+ {
+ scaleDown() ;
+ }
+ // Only allow GL to have 2x the video card memory
+ else if ( BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) > sMaxTotalTextureMemInMegaBytes*texmem_middle_bound_scale &&
+ (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel))
+ {
+ scaleDown() ;
+
+ }
+ }
+ }
+}
+
+void LLViewerLODTexture::scaleDown()
+{
+ if(hasGLTexture() && mCachedRawDiscardLevel > getDiscardLevel())
+ {
+ switchToCachedImage() ;
+
+ if(LLViewerTextureManager::sTesterp)
+ {
+ LLViewerTextureManager::sTesterp->setStablizingTime() ;
+ }
+ }
+}
+//----------------------------------------------------------------------------------------------
+//end of LLViewerLODTexture
+//----------------------------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------------------------
+//start of LLViewerMediaTexture
+//----------------------------------------------------------------------------------------------
+//static
+void LLViewerMediaTexture::updateClass()
+{
+ static const F32 MAX_INACTIVE_TIME = 30.f ;
+
+#if 0
+ //force to play media.
+ gSavedSettings.setBOOL("AudioStreamingMedia", true) ;
+#endif
+
+ for(media_map_t::iterator iter = sMediaMap.begin() ; iter != sMediaMap.end(); )
+ {
+ LLViewerMediaTexture* mediap = iter->second;
+
+ if(mediap->getNumRefs() == 1) //one reference by sMediaMap
+ {
+ //
+ //Note: delay some time to delete the media textures to stop endlessly creating and immediately removing media texture.
+ //
+ if(mediap->getLastReferencedTimer()->getElapsedTimeF32() > MAX_INACTIVE_TIME)
+ {
+ media_map_t::iterator cur = iter++ ;
+ sMediaMap.erase(cur) ;
+ continue ;
+ }
+ }
+ ++iter ;
+ }
+}
+
+//static
+void LLViewerMediaTexture::removeMediaImplFromTexture(const LLUUID& media_id)
+{
+ LLViewerMediaTexture* media_tex = findMediaTexture(media_id) ;
+ if(media_tex)
+ {
+ media_tex->invalidateMediaImpl() ;
+ }
+}
+
+//static
+void LLViewerMediaTexture::cleanup()
+{
+ sMediaMap.clear() ;
+}
+
+//static
+LLViewerMediaTexture* LLViewerMediaTexture::findMediaTexture(const LLUUID& media_id)
+{
+ media_map_t::iterator iter = sMediaMap.find(media_id);
+ if(iter == sMediaMap.end())
+ {
+ return NULL;
+ }
+
+ LLViewerMediaTexture* media_tex = iter->second ;
+ media_tex->setMediaImpl() ;
+ media_tex->getLastReferencedTimer()->reset() ;
+
+ return media_tex;
+}
+
+LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LLImageGL* gl_image)
+ : LLViewerTexture(id, usemipmaps),
+ mMediaImplp(NULL),
+ mUpdateVirtualSizeTime(0)
+{
+ sMediaMap.insert(std::make_pair(id, this));
+
+ mGLTexturep = gl_image ;
+ if(mGLTexturep.isNull())
+ {
+ generateGLTexture() ;
+ }
+ mGLTexturep->setNeedsAlphaAndPickMask(FALSE) ;
+
+ mIsPlaying = FALSE ;
+
+ setMediaImpl() ;
+
+ setCategory(LLViewerTexture::MEDIA) ;
+
+ LLViewerTexture* tex = gTextureList.findImage(mID) ;
+ if(tex) //this media is a parcel media for tex.
+ {
+ tex->setParcelMedia(this) ;
+ }
+}
+
+//virtual
+LLViewerMediaTexture::~LLViewerMediaTexture()
+{
+ LLViewerTexture* tex = gTextureList.findImage(mID) ;
+ if(tex) //this media is a parcel media for tex.
+ {
+ tex->setParcelMedia(NULL) ;
+ }
+}
+
+void LLViewerMediaTexture::reinit(BOOL usemipmaps /* = TRUE */)
+{
+ mGLTexturep = NULL ;
+ init(false);
+ mUseMipMaps = usemipmaps ;
+ getLastReferencedTimer()->reset() ;
+
+ generateGLTexture() ;
+ mGLTexturep->setNeedsAlphaAndPickMask(FALSE) ;
+}
+
+void LLViewerMediaTexture::setUseMipMaps(BOOL mipmap)
+{
+ mUseMipMaps = mipmap;
+
+ if(mGLTexturep.notNull())
+ {
+ mGLTexturep->setUseMipMaps(mipmap) ;
+ }
+}
+
+//virtual
+S8 LLViewerMediaTexture::getType() const
+{
+ return LLViewerTexture::MEDIA_TEXTURE ;
+}
+
+void LLViewerMediaTexture::invalidateMediaImpl()
+{
+ mMediaImplp = NULL ;
+}
+
+void LLViewerMediaTexture::setMediaImpl()
+{
+ if(!mMediaImplp)
+ {
+ mMediaImplp = LLViewerMedia::getMediaImplFromTextureID(mID) ;
+ }
+}
+
+//return true if all faces to reference to this media texture are found
+//Note: mMediaFaceList is valid only for the current instant
+// because it does not check the face validity after the current frame.
+BOOL LLViewerMediaTexture::findFaces()
+{
+ mMediaFaceList.clear() ;
+
+ BOOL ret = TRUE ;
+
+ LLViewerTexture* tex = gTextureList.findImage(mID) ;
+ if(tex) //this media is a parcel media for tex.
+ {
+ const ll_face_list_t* face_list = tex->getFaceList() ;
+ U32 end = tex->getNumFaces() ;
+ for(U32 i = 0 ; i < end ; i++)
+ {
+ mMediaFaceList.push_back((*face_list)[i]) ;
+ }
+ }
+
+ if(!mMediaImplp)
+ {
+ return TRUE ;
+ }
+
+ //for media on a face.
+ const std::list< LLVOVolume* >* obj_list = mMediaImplp->getObjectList() ;
+ std::list< LLVOVolume* >::const_iterator iter = obj_list->begin() ;
+ for(; iter != obj_list->end(); ++iter)
+ {
+ LLVOVolume* obj = *iter ;
+ if(obj->mDrawable.isNull())
+ {
+ ret = FALSE ;
+ continue ;
+ }
+
+ S32 face_id = -1 ;
+ S32 num_faces = obj->mDrawable->getNumFaces() ;
+ while((face_id = obj->getFaceIndexWithMediaImpl(mMediaImplp, face_id)) > -1 && face_id < num_faces)
+ {
+ LLFace* facep = obj->mDrawable->getFace(face_id) ;
+ if(facep)
+ {
+ mMediaFaceList.push_back(facep) ;
+ }
+ else
+ {
+ ret = FALSE ;
+ }
+ }
+ }
+
+ return ret ;
+}
+
+void LLViewerMediaTexture::initVirtualSize()
+{
+ if(mIsPlaying)
+ {
+ return ;
+ }
+
+ findFaces() ;
+ for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter)
+ {
+ addTextureStats((*iter)->getVirtualSize()) ;
+ }
+}
+
+void LLViewerMediaTexture::addMediaToFace(LLFace* facep)
+{
+ if(!mIsPlaying)
+ {
+ return ; //no need to add the face because the media is not in playing.
+ }
+
+ switchTexture(facep) ;
+}
+
+void LLViewerMediaTexture::removeMediaFromFace(LLFace* facep)
+{
+ if(!mIsPlaying)
+ {
+ return ; //no need to remove the face because the media is not in playing.
+ }
+ if(!facep)
+ {
+ return ;
+ }
+
+ mIsPlaying = FALSE ; //set to remove the media from the face.
+ switchTexture(facep) ;
+ mIsPlaying = TRUE ; //set the flag back.
+
+ if(getNumFaces() < 1) //no face referencing to this media
+ {
+ stopPlaying() ;
+ }
+}
+
+//virtual
+void LLViewerMediaTexture::addFace(LLFace* facep)
+{
+ LLViewerTexture::addFace(facep) ;
+
+ const LLTextureEntry* te = facep->getTextureEntry() ;
+ if(te && te->getID().notNull())
+ {
+ LLViewerTexture* tex = gTextureList.findImage(te->getID()) ;
+ if(tex)
+ {
+ mTextureList.push_back(tex) ;//increase the reference number by one for tex to avoid deleting it.
+ return ;
+ }
+ }
+
+ //check if it is a parcel media
+ if(facep->getTexture() && facep->getTexture() != this && facep->getTexture()->getID() == mID)
+ {
+ mTextureList.push_back(facep->getTexture()) ; //a parcel media.
+ return ;
+ }
+
+ if(te && te->getID().notNull()) //should have a texture
+ {
+ llerrs << "The face does not have a valid texture before media texture." << llendl ;
+ }
+}
+
+//virtual
+void LLViewerMediaTexture::removeFace(LLFace* facep)
+{
+ LLViewerTexture::removeFace(facep) ;
+
+ const LLTextureEntry* te = facep->getTextureEntry() ;
+ if(te && te->getID().notNull())
+ {
+ LLViewerTexture* tex = gTextureList.findImage(te->getID()) ;
+ if(tex)
+ {
+ for(std::list< LLPointer<LLViewerTexture> >::iterator iter = mTextureList.begin();
+ iter != mTextureList.end(); ++iter)
+ {
+ if(*iter == tex)
+ {
+ mTextureList.erase(iter) ; //decrease the reference number for tex by one.
+ return ;
+ }
+ }
+
+ //
+ //we have some trouble here: the texture of the face is changed.
+ //we need to find the former texture, and remove it from the list to avoid memory leaking.
+ if(!mNumFaces)
+ {
+ mTextureList.clear() ;
+ return ;
+ }
+ S32 end = getNumFaces() ;
+ std::vector<const LLTextureEntry*> te_list(end) ;
+ S32 i = 0 ;
+ for(U32 j = 0 ; j < mNumFaces ; j++)
+ {
+ te_list[i++] = mFaceList[j]->getTextureEntry() ;//all textures are in use.
+ }
+ for(std::list< LLPointer<LLViewerTexture> >::iterator iter = mTextureList.begin();
+ iter != mTextureList.end(); ++iter)
+ {
+ for(i = 0 ; i < end ; i++)
+ {
+ if(te_list[i] && te_list[i]->getID() == (*iter)->getID())//the texture is in use.
+ {
+ te_list[i] = NULL ;
+ break ;
+ }
+ }
+ if(i == end) //no hit for this texture, remove it.
+ {
+ mTextureList.erase(iter) ; //decrease the reference number for tex by one.
+ return ;
+ }
+ }
+ }
+ }
+
+ //check if it is a parcel media
+ for(std::list< LLPointer<LLViewerTexture> >::iterator iter = mTextureList.begin();
+ iter != mTextureList.end(); ++iter)
+ {
+ if((*iter)->getID() == mID)
+ {
+ mTextureList.erase(iter) ; //decrease the reference number for tex by one.
+ return ;
+ }
+ }
+
+ if(te && te->getID().notNull()) //should have a texture
+ {
+ llerrs << "mTextureList texture reference number is corrupted." << llendl ;
+ }
+}
+
+void LLViewerMediaTexture::stopPlaying()
+{
+ // Don't stop the media impl playing here -- this breaks non-inworld media (login screen, search, and media browser).
+// if(mMediaImplp)
+// {
+// mMediaImplp->stop() ;
+// }
+ mIsPlaying = FALSE ;
+}
+
+void LLViewerMediaTexture::switchTexture(LLFace* facep)
+{
+ if(facep)
+ {
+ //check if another media is playing on this face.
+ if(facep->getTexture() && facep->getTexture() != this
+ && facep->getTexture()->getType() == LLViewerTexture::MEDIA_TEXTURE)
+ {
+ if(mID == facep->getTexture()->getID()) //this is a parcel media
+ {
+ return ; //let the prim media win.
+ }
+ }
+
+ if(mIsPlaying) //old textures switch to the media texture
+ {
+ facep->switchTexture(this) ;
+ }
+ else //switch to old textures.
+ {
+ const LLTextureEntry* te = facep->getTextureEntry() ;
+ if(te)
+ {
+ LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID()) : NULL ;
+ if(!tex && te->getID() != mID)//try parcel media.
+ {
+ tex = gTextureList.findImage(mID) ;
+ }
+ if(!tex)
+ {
+ tex = LLViewerFetchedTexture::sDefaultImagep ;
+ }
+ facep->switchTexture(tex) ;
+ }
+ }
+ }
+}
+
+void LLViewerMediaTexture::setPlaying(BOOL playing)
+{
+ if(!mMediaImplp)
+ {
+ return ;
+ }
+ if(!playing && !mIsPlaying)
+ {
+ return ; //media is already off
+ }
+
+ if(playing == mIsPlaying && !mMediaImplp->isUpdated())
+ {
+ return ; //nothing has changed since last time.
+ }
+
+ mIsPlaying = playing ;
+ if(mIsPlaying) //is about to play this media
+ {
+ if(findFaces())
+ {
+ //about to update all faces.
+ mMediaImplp->setUpdated(FALSE) ;
+ }
+
+ if(mMediaFaceList.empty())//no face pointing to this media
+ {
+ stopPlaying() ;
+ return ;
+ }
+
+ for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter)
+ {
+ switchTexture(*iter) ;
+ }
+ }
+ else //stop playing this media
+ {
+ for(U32 i = mNumFaces ; i ; i--)
+ {
+ switchTexture(mFaceList[i - 1]) ; //current face could be removed in this function.
+ }
+ }
+ return ;
+}
+
+//virtual
+F32 LLViewerMediaTexture::getMaxVirtualSize()
+{
+ if(LLFrameTimer::getFrameCount() == mUpdateVirtualSizeTime)
+ {
+ return mMaxVirtualSize ;
+ }
+ mUpdateVirtualSizeTime = LLFrameTimer::getFrameCount() ;
+
+ if(mNeedsResetMaxVirtualSize)
+ {
+ addTextureStats(0.f, FALSE) ;//reset
+ }
+
+ if(mIsPlaying) //media is playing
+ {
+ for(U32 i = 0 ; i < mNumFaces ; i++)
+ {
+ LLFace* facep = mFaceList[i] ;
+ if(facep->getDrawable()->isRecentlyVisible())
+ {
+ addTextureStats(facep->getVirtualSize()) ;
+ }
+ }
+ }
+ else //media is not in playing
+ {
+ findFaces() ;
+
+ if(!mMediaFaceList.empty())
+ {
+ for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter)
+ {
+ LLFace* facep = *iter ;
+ if(facep->getDrawable()->isRecentlyVisible())
+ {
+ addTextureStats(facep->getVirtualSize()) ;
+ }
+ }
+ }
+ }
+
+ mNeedsResetMaxVirtualSize = TRUE ;
+ reorganizeFaceList() ;
+
+ return mMaxVirtualSize ;
+}
+//----------------------------------------------------------------------------------------------
+//end of LLViewerMediaTexture
+//----------------------------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------------------------
+//start of LLTexturePipelineTester
+//----------------------------------------------------------------------------------------------
+LLTexturePipelineTester::LLTexturePipelineTester() :
+ LLMetricPerformanceTester("TextureTester", FALSE)
+{
+ addMetricString("TotalBytesLoaded") ;
+ addMetricString("TotalBytesLoadedFromCache") ;
+ addMetricString("TotalBytesLoadedForLargeImage") ;
+ addMetricString("TotalBytesLoadedForSculpties") ;
+ addMetricString("StartFetchingTime") ;
+ addMetricString("TotalGrayTime") ;
+ addMetricString("TotalStablizingTime") ;
+ addMetricString("StartTimeLoadingSculpties") ;
+ addMetricString("EndTimeLoadingSculpties") ;
+
+ addMetricString("Time") ;
+ addMetricString("TotalBytesBound") ;
+ addMetricString("TotalBytesBoundForLargeImage") ;
+ addMetricString("PercentageBytesBound") ;
+
+ mTotalBytesLoaded = 0 ;
+ mTotalBytesLoadedFromCache = 0 ;
+ mTotalBytesLoadedForLargeImage = 0 ;
+ mTotalBytesLoadedForSculpties = 0 ;
+
+ reset() ;
+}
+
+LLTexturePipelineTester::~LLTexturePipelineTester()
+{
+ LLViewerTextureManager::sTesterp = NULL ;
+}
+
+void LLTexturePipelineTester::update()
+{
+ mLastTotalBytesUsed = mTotalBytesUsed ;
+ mLastTotalBytesUsedForLargeImage = mTotalBytesUsedForLargeImage ;
+ mTotalBytesUsed = 0 ;
+ mTotalBytesUsedForLargeImage = 0 ;
+
+ if(LLAppViewer::getTextureFetch()->getNumRequests() > 0) //fetching list is not empty
+ {
+ if(mPause)
+ {
+ //start a new fetching session
+ reset() ;
+ mStartFetchingTime = LLImageGL::sLastFrameTime ;
+ mPause = FALSE ;
+ }
+
+ //update total gray time
+ if(mUsingDefaultTexture)
+ {
+ mUsingDefaultTexture = FALSE ;
+ mTotalGrayTime = LLImageGL::sLastFrameTime - mStartFetchingTime ;
+ }
+
+ //update the stablizing timer.
+ updateStablizingTime() ;
+
+ outputTestResults() ;
+ }
+ else if(!mPause)
+ {
+ //stop the current fetching session
+ mPause = TRUE ;
+ outputTestResults() ;
+ reset() ;
+ }
+}
+
+void LLTexturePipelineTester::reset()
+{
+ mPause = TRUE ;
+
+ mUsingDefaultTexture = FALSE ;
+ mStartStablizingTime = 0.0f ;
+ mEndStablizingTime = 0.0f ;
+
+ mTotalBytesUsed = 0 ;
+ mTotalBytesUsedForLargeImage = 0 ;
+ mLastTotalBytesUsed = 0 ;
+ mLastTotalBytesUsedForLargeImage = 0 ;
+
+ mStartFetchingTime = 0.0f ;
+
+ mTotalGrayTime = 0.0f ;
+ mTotalStablizingTime = 0.0f ;
+
+ mStartTimeLoadingSculpties = 1.0f ;
+ mEndTimeLoadingSculpties = 0.0f ;
+}
+
+//virtual
+void LLTexturePipelineTester::outputTestRecord(LLSD *sd)
+{
+ (*sd)[mCurLabel]["TotalBytesLoaded"] = (LLSD::Integer)mTotalBytesLoaded ;
+ (*sd)[mCurLabel]["TotalBytesLoadedFromCache"] = (LLSD::Integer)mTotalBytesLoadedFromCache ;
+ (*sd)[mCurLabel]["TotalBytesLoadedForLargeImage"] = (LLSD::Integer)mTotalBytesLoadedForLargeImage ;
+ (*sd)[mCurLabel]["TotalBytesLoadedForSculpties"] = (LLSD::Integer)mTotalBytesLoadedForSculpties ;
+
+ (*sd)[mCurLabel]["StartFetchingTime"] = (LLSD::Real)mStartFetchingTime ;
+ (*sd)[mCurLabel]["TotalGrayTime"] = (LLSD::Real)mTotalGrayTime ;
+ (*sd)[mCurLabel]["TotalStablizingTime"] = (LLSD::Real)mTotalStablizingTime ;
+
+ (*sd)[mCurLabel]["StartTimeLoadingSculpties"] = (LLSD::Real)mStartTimeLoadingSculpties ;
+ (*sd)[mCurLabel]["EndTimeLoadingSculpties"] = (LLSD::Real)mEndTimeLoadingSculpties ;
+
+ (*sd)[mCurLabel]["Time"] = LLImageGL::sLastFrameTime ;
+ (*sd)[mCurLabel]["TotalBytesBound"] = (LLSD::Integer)mLastTotalBytesUsed ;
+ (*sd)[mCurLabel]["TotalBytesBoundForLargeImage"] = (LLSD::Integer)mLastTotalBytesUsedForLargeImage ;
+ (*sd)[mCurLabel]["PercentageBytesBound"] = (LLSD::Real)(100.f * mLastTotalBytesUsed / mTotalBytesLoaded) ;
+}
+
+void LLTexturePipelineTester::updateTextureBindingStats(const LLViewerTexture* imagep)
+{
+ U32 mem_size = (U32)imagep->getTextureMemory() ;
+ mTotalBytesUsed += mem_size ;
+
+ if(MIN_LARGE_IMAGE_AREA <= (U32)(mem_size / (U32)imagep->getComponents()))
+ {
+ mTotalBytesUsedForLargeImage += mem_size ;
+ }
+}
+
+void LLTexturePipelineTester::updateTextureLoadingStats(const LLViewerFetchedTexture* imagep, const LLImageRaw* raw_imagep, BOOL from_cache)
+{
+ U32 data_size = (U32)raw_imagep->getDataSize() ;
+ mTotalBytesLoaded += data_size ;
+
+ if(from_cache)
+ {
+ mTotalBytesLoadedFromCache += data_size ;
+ }
+
+ if(MIN_LARGE_IMAGE_AREA <= (U32)(data_size / (U32)raw_imagep->getComponents()))
+ {
+ mTotalBytesLoadedForLargeImage += data_size ;
+ }
+
+ if(imagep->forSculpt())
+ {
+ mTotalBytesLoadedForSculpties += data_size ;
+
+ if(mStartTimeLoadingSculpties > mEndTimeLoadingSculpties)
+ {
+ mStartTimeLoadingSculpties = LLImageGL::sLastFrameTime ;
+ }
+ mEndTimeLoadingSculpties = LLImageGL::sLastFrameTime ;
+ }
+}
+
+void LLTexturePipelineTester::updateGrayTextureBinding()
+{
+ mUsingDefaultTexture = TRUE ;
+}
+
+void LLTexturePipelineTester::setStablizingTime()
+{
+ if(mStartStablizingTime <= mStartFetchingTime)
+ {
+ mStartStablizingTime = LLImageGL::sLastFrameTime ;
+ }
+ mEndStablizingTime = LLImageGL::sLastFrameTime ;
+}
+
+void LLTexturePipelineTester::updateStablizingTime()
+{
+ if(mStartStablizingTime > mStartFetchingTime)
+ {
+ F32 t = mEndStablizingTime - mStartStablizingTime ;
+
+ if(t > 0.0001f && (t - mTotalStablizingTime) < 0.0001f)
+ {
+ //already stablized
+ mTotalStablizingTime = LLImageGL::sLastFrameTime - mStartStablizingTime ;
+
+ //cancel the timer
+ mStartStablizingTime = 0.f ;
+ mEndStablizingTime = 0.f ;
+ }
+ else
+ {
+ mTotalStablizingTime = t ;
+ }
+ }
+ mTotalStablizingTime = 0.f ;
+}
+
+//virtual
+void LLTexturePipelineTester::compareTestSessions(std::ofstream* os)
+{
+ LLTexturePipelineTester::LLTextureTestSession* base_sessionp = dynamic_cast<LLTexturePipelineTester::LLTextureTestSession*>(mBaseSessionp) ;
+ LLTexturePipelineTester::LLTextureTestSession* current_sessionp = dynamic_cast<LLTexturePipelineTester::LLTextureTestSession*>(mCurrentSessionp) ;
+ if(!base_sessionp || !current_sessionp)
+ {
+ llerrs << "type of test session does not match!" << llendl ;
+ }
+
+ //compare and output the comparison
+ *os << llformat("%s\n", mName.c_str()) ;
+ *os << llformat("AggregateResults\n") ;
+
+ compareTestResults(os, "TotalFetchingTime", base_sessionp->mTotalFetchingTime, current_sessionp->mTotalFetchingTime) ;
+ compareTestResults(os, "TotalGrayTime", base_sessionp->mTotalGrayTime, current_sessionp->mTotalGrayTime) ;
+ compareTestResults(os, "TotalStablizingTime", base_sessionp->mTotalStablizingTime, current_sessionp->mTotalStablizingTime);
+ compareTestResults(os, "StartTimeLoadingSculpties", base_sessionp->mStartTimeLoadingSculpties, current_sessionp->mStartTimeLoadingSculpties) ;
+ compareTestResults(os, "TotalTimeLoadingSculpties", base_sessionp->mTotalTimeLoadingSculpties, current_sessionp->mTotalTimeLoadingSculpties) ;
+
+ compareTestResults(os, "TotalBytesLoaded", base_sessionp->mTotalBytesLoaded, current_sessionp->mTotalBytesLoaded) ;
+ compareTestResults(os, "TotalBytesLoadedFromCache", base_sessionp->mTotalBytesLoadedFromCache, current_sessionp->mTotalBytesLoadedFromCache) ;
+ compareTestResults(os, "TotalBytesLoadedForLargeImage", base_sessionp->mTotalBytesLoadedForLargeImage, current_sessionp->mTotalBytesLoadedForLargeImage) ;
+ compareTestResults(os, "TotalBytesLoadedForSculpties", base_sessionp->mTotalBytesLoadedForSculpties, current_sessionp->mTotalBytesLoadedForSculpties) ;
+
+ *os << llformat("InstantResults\n") ;
+ S32 size = llmin(base_sessionp->mInstantPerformanceListCounter, current_sessionp->mInstantPerformanceListCounter) ;
+ for(S32 i = 0 ; i < size ; i++)
+ {
+ *os << llformat("Time(B-T)-%.4f-%.4f\n", base_sessionp->mInstantPerformanceList[i].mTime, current_sessionp->mInstantPerformanceList[i].mTime) ;
+
+ compareTestResults(os, "AverageBytesUsedPerSecond", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond,
+ current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond) ;
+
+ compareTestResults(os, "AverageBytesUsedForLargeImagePerSecond", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond,
+ current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond) ;
+
+ compareTestResults(os, "AveragePercentageBytesUsedPerSecond", base_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond,
+ current_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond) ;
+ }
+
+ if(size < base_sessionp->mInstantPerformanceListCounter)
+ {
+ for(S32 i = size ; i < base_sessionp->mInstantPerformanceListCounter ; i++)
+ {
+ *os << llformat("Time(B-T)-%.4f- \n", base_sessionp->mInstantPerformanceList[i].mTime) ;
+
+ *os << llformat(", AverageBytesUsedPerSecond, %d, N/A \n", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond) ;
+ *os << llformat(", AverageBytesUsedForLargeImagePerSecond, %d, N/A \n", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond) ;
+ *os << llformat(", AveragePercentageBytesUsedPerSecond, %.4f, N/A \n", base_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond) ;
+ }
+ }
+ else if(size < current_sessionp->mInstantPerformanceListCounter)
+ {
+ for(S32 i = size ; i < current_sessionp->mInstantPerformanceListCounter ; i++)
+ {
+ *os << llformat("Time(B-T)- -%.4f\n", current_sessionp->mInstantPerformanceList[i].mTime) ;
+
+ *os << llformat(", AverageBytesUsedPerSecond, N/A, %d\n", current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond) ;
+ *os << llformat(", AverageBytesUsedForLargeImagePerSecond, N/A, %d\n", current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond) ;
+ *os << llformat(", AveragePercentageBytesUsedPerSecond, N/A, %.4f\n", current_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond) ;
+ }
+ }
+}
+
+//virtual
+LLMetricPerformanceTester::LLTestSession* LLTexturePipelineTester::loadTestSession(LLSD* log)
+{
+ LLTexturePipelineTester::LLTextureTestSession* sessionp = new LLTexturePipelineTester::LLTextureTestSession() ;
+ if(!sessionp)
+ {
+ return NULL ;
+ }
+
+ F32 total_fetching_time = 0.f ;
+ F32 total_gray_time = 0.f ;
+ F32 total_stablizing_time = 0.f ;
+ F32 total_loading_sculpties_time = 0.f ;
+
+ F32 start_fetching_time = -1.f ;
+ F32 start_fetching_sculpties_time = 0.f ;
+
+ F32 last_time = 0.0f ;
+ S32 frame_count = 0 ;
+
+ sessionp->mInstantPerformanceListCounter = 0 ;
+ sessionp->mInstantPerformanceList.resize(128) ;
+ sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond = 0 ;
+ sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond = 0 ;
+ sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond = 0.f ;
+ sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = 0.f ;
+
+ //load a session
+ BOOL in_log = (*log).has(mCurLabel) ;
+ while(in_log)
+ {
+ LLSD::String label = mCurLabel ;
+ incLabel() ;
+ in_log = (*log).has(mCurLabel) ;
+
+ if(sessionp->mInstantPerformanceListCounter >= (S32)sessionp->mInstantPerformanceList.size())
+ {
+ sessionp->mInstantPerformanceList.resize(sessionp->mInstantPerformanceListCounter + 128) ;
+ }
+
+ //time
+ F32 start_time = (*log)[label]["StartFetchingTime"].asReal() ;
+ F32 cur_time = (*log)[label]["Time"].asReal() ;
+ if(start_time - start_fetching_time > 0.0001f) //fetching has paused for a while
+ {
+ sessionp->mTotalFetchingTime += total_fetching_time ;
+ sessionp->mTotalGrayTime += total_gray_time ;
+ sessionp->mTotalStablizingTime += total_stablizing_time ;
+
+ sessionp->mStartTimeLoadingSculpties = start_fetching_sculpties_time ;
+ sessionp->mTotalTimeLoadingSculpties += total_loading_sculpties_time ;
+
+ start_fetching_time = start_time ;
+ total_fetching_time = 0.0f ;
+ total_gray_time = 0.f ;
+ total_stablizing_time = 0.f ;
+ total_loading_sculpties_time = 0.f ;
+ }
+ else
+ {
+ total_fetching_time = cur_time - start_time ;
+ total_gray_time = (*log)[label]["TotalGrayTime"].asReal() ;
+ total_stablizing_time = (*log)[label]["TotalStablizingTime"].asReal() ;
+
+ total_loading_sculpties_time = (*log)[label]["EndTimeLoadingSculpties"].asReal() - (*log)[label]["StartTimeLoadingSculpties"].asReal() ;
+ if(start_fetching_sculpties_time < 0.f && total_loading_sculpties_time > 0.f)
+ {
+ start_fetching_sculpties_time = (*log)[label]["StartTimeLoadingSculpties"].asReal() ;
+ }
+ }
+
+ //total loaded bytes
+ sessionp->mTotalBytesLoaded = (*log)[label]["TotalBytesLoaded"].asInteger() ;
+ sessionp->mTotalBytesLoadedFromCache = (*log)[label]["TotalBytesLoadedFromCache"].asInteger() ;
+ sessionp->mTotalBytesLoadedForLargeImage = (*log)[label]["TotalBytesLoadedForLargeImage"].asInteger() ;
+ sessionp->mTotalBytesLoadedForSculpties = (*log)[label]["TotalBytesLoadedForSculpties"].asInteger() ;
+
+ //instant metrics
+ sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond +=
+ (*log)[label]["TotalBytesBound"].asInteger() ;
+ sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond +=
+ (*log)[label]["TotalBytesBoundForLargeImage"].asInteger() ;
+ sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond +=
+ (*log)[label]["PercentageBytesBound"].asReal() ;
+ frame_count++ ;
+ if(cur_time - last_time >= 1.0f)
+ {
+ sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond /= frame_count ;
+ sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond /= frame_count ;
+ sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond /= frame_count ;
+ sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = last_time ;
+
+ frame_count = 0 ;
+ last_time = cur_time ;
+ sessionp->mInstantPerformanceListCounter++ ;
+ sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond = 0 ;
+ sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond = 0 ;
+ sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond = 0.f ;
+ sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = 0.f ;
+ }
+ }
+
+ sessionp->mTotalFetchingTime += total_fetching_time ;
+ sessionp->mTotalGrayTime += total_gray_time ;
+ sessionp->mTotalStablizingTime += total_stablizing_time ;
+
+ if(sessionp->mStartTimeLoadingSculpties < 0.f)
+ {
+ sessionp->mStartTimeLoadingSculpties = start_fetching_sculpties_time ;
+ }
+ sessionp->mTotalTimeLoadingSculpties += total_loading_sculpties_time ;
+
+ return sessionp;
+}
+
+LLTexturePipelineTester::LLTextureTestSession::LLTextureTestSession()
+{
+ reset() ;
+}
+LLTexturePipelineTester::LLTextureTestSession::~LLTextureTestSession()
+{
+}
+void LLTexturePipelineTester::LLTextureTestSession::reset()
+{
+ mTotalFetchingTime = 0.0f ;
+
+ mTotalGrayTime = 0.0f ;
+ mTotalStablizingTime = 0.0f ;
+
+ mStartTimeLoadingSculpties = 0.0f ;
+ mTotalTimeLoadingSculpties = 0.0f ;
+
+ mTotalBytesLoaded = 0 ;
+ mTotalBytesLoadedFromCache = 0 ;
+ mTotalBytesLoadedForLargeImage = 0 ;
+ mTotalBytesLoadedForSculpties = 0 ;
+
+ mInstantPerformanceListCounter = 0 ;
+}
+//----------------------------------------------------------------------------------------------
+//end of LLTexturePipelineTester
+//----------------------------------------------------------------------------------------------
+
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
new file mode 100644
index 0000000000..79d9c4e7bb
--- /dev/null
+++ b/indra/newview/llviewertexture.h
@@ -0,0 +1,794 @@
+/**
+ * @file llviewertexture.h
+ * @brief Object for managing images and their textures
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLVIEWERTEXTURE_H
+#define LL_LLVIEWERTEXTURE_H
+
+#include "lltexture.h"
+#include "lltimer.h"
+#include "llframetimer.h"
+#include "llhost.h"
+#include "llgltypes.h"
+#include "llrender.h"
+#include "llmetricperformancetester.h"
+
+#include <map>
+#include <list>
+
+#define MIN_VIDEO_RAM_IN_MEGA_BYTES 32
+#define MAX_VIDEO_RAM_IN_MEGA_BYTES 512 // 512MB max for performance reasons.
+
+class LLFace;
+class LLImageGL ;
+class LLImageRaw;
+class LLViewerObject;
+class LLViewerTexture;
+class LLViewerFetchedTexture ;
+class LLViewerMediaTexture ;
+class LLTexturePipelineTester ;
+
+
+typedef void (*loaded_callback_func)( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata );
+
+class LLVFile;
+class LLMessageSystem;
+class LLViewerMediaImpl ;
+class LLVOVolume ;
+
+class LLLoadedCallbackEntry
+{
+public:
+ LLLoadedCallbackEntry(loaded_callback_func cb,
+ S32 discard_level,
+ BOOL need_imageraw, // Needs image raw for the callback
+ void* userdata );
+
+ loaded_callback_func mCallback;
+ S32 mLastUsedDiscard;
+ S32 mDesiredDiscard;
+ BOOL mNeedsImageRaw;
+ void* mUserData;
+};
+
+class LLTextureBar;
+
+class LLViewerTexture : public LLTexture
+{
+public:
+ enum
+ {
+ MAX_IMAGE_SIZE_DEFAULT = 1024,
+ INVALID_DISCARD_LEVEL = 0x7fff
+ };
+ enum
+ {
+ LOCAL_TEXTURE,
+ MEDIA_TEXTURE,
+ DYNAMIC_TEXTURE,
+ FETCHED_TEXTURE,
+ LOD_TEXTURE,
+ ATLAS_TEXTURE,
+ INVALID_TEXTURE_TYPE
+ };
+
+ enum EBoostLevel
+ {
+ BOOST_NONE = 0,
+ BOOST_AVATAR_BAKED = 1,
+ BOOST_AVATAR = 2,
+ BOOST_CLOUDS = 3,
+ BOOST_SCULPTED = 4,
+
+ BOOST_HIGH = 10,
+ BOOST_TERRAIN = 11, // has to be high priority for minimap / low detail
+ BOOST_SELECTED = 12,
+ BOOST_HUD = 13,
+ BOOST_AVATAR_BAKED_SELF = 14,
+ BOOST_ICON = 15,
+ BOOST_UI = 16,
+ BOOST_PREVIEW = 17,
+ BOOST_MAP = 18,
+ BOOST_MAP_VISIBLE = 19,
+ BOOST_AVATAR_SELF = 20, // needed for baking avatar
+ BOOST_MAX_LEVEL,
+
+ //other texture Categories
+ LOCAL = BOOST_MAX_LEVEL,
+ AVATAR_SCRATCH_TEX,
+ DYNAMIC_TEX,
+ MEDIA,
+ ATLAS,
+ OTHER,
+ MAX_GL_IMAGE_CATEGORY
+ };
+ static S32 getTotalNumOfCategories() ;
+ static S32 getIndexFromCategory(S32 category) ;
+ static S32 getCategoryFromIndex(S32 index) ;
+
+ typedef std::vector<LLFace*> ll_face_list_t ;
+
+protected:
+ virtual ~LLViewerTexture();
+ LOG_CLASS(LLViewerTexture);
+
+public:
+ static void initClass();
+ static void cleanupClass();
+ static void updateClass(const F32 velocity, const F32 angular_velocity) ;
+
+ LLViewerTexture(BOOL usemipmaps = TRUE);
+ LLViewerTexture(const LLUUID& id, BOOL usemipmaps) ;
+ LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps) ;
+ LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) ;
+
+ virtual S8 getType() const;
+ virtual BOOL isMissingAsset()const ;
+ virtual void dump(); // debug info to llinfos
+
+ /*virtual*/ bool bindDefaultImage(const S32 stage = 0) ;
+ /*virtual*/ void forceImmediateUpdate() ;
+
+ const LLUUID& getID() const { return mID; }
+
+ void setBoostLevel(S32 level);
+ S32 getBoostLevel() { return mBoostLevel; }
+
+ void addTextureStats(F32 virtual_size, BOOL needs_gltexture = TRUE) const;
+ void resetTextureStats();
+
+ virtual F32 getMaxVirtualSize() ;
+
+ LLFrameTimer* getLastReferencedTimer() {return &mLastReferencedTimer ;}
+
+ S32 getFullWidth() const { return mFullWidth; }
+ S32 getFullHeight() const { return mFullHeight; }
+ /*virtual*/ void setKnownDrawSize(S32 width, S32 height);
+
+ virtual void addFace(LLFace* facep) ;
+ virtual void removeFace(LLFace* facep) ;
+ S32 getNumFaces() const;
+ const ll_face_list_t* getFaceList() const {return &mFaceList;}
+
+ void generateGLTexture() ;
+ void destroyGLTexture() ;
+
+ //---------------------------------------------------------------------------------------------
+ //functions to access LLImageGL
+ //---------------------------------------------------------------------------------------------
+ /*virtual*/S32 getWidth(S32 discard_level = -1) const;
+ /*virtual*/S32 getHeight(S32 discard_level = -1) const;
+
+ BOOL hasGLTexture() const ;
+ LLGLuint getTexName() const ;
+ BOOL createGLTexture() ;
+ BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = LLViewerTexture::OTHER);
+
+ void setFilteringOption(LLTexUnit::eTextureFilterOptions option);
+ void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE);
+ void setAddressMode(LLTexUnit::eTextureAddressMode mode);
+ BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height);
+ BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height);
+ void setGLTextureCreated (bool initialized);
+ void setCategory(S32 category) ;
+
+ LLTexUnit::eTextureAddressMode getAddressMode(void) const ;
+ S32 getMaxDiscardLevel() const;
+ S32 getDiscardLevel() const;
+ S8 getComponents() const ;
+ BOOL getBoundRecently() const;
+ S32 getTextureMemory() const ;
+ LLGLenum getPrimaryFormat() const;
+ BOOL getIsAlphaMask() const ;
+ LLTexUnit::eTextureType getTarget(void) const ;
+ BOOL getMask(const LLVector2 &tc);
+ F32 getTimePassedSinceLastBound();
+ BOOL getMissed() const ;
+ BOOL isJustBound()const ;
+ void forceUpdateBindStats(void) const;
+
+ U32 getTexelsInAtlas() const ;
+ U32 getTexelsInGLTexture() const ;
+ BOOL isGLTextureCreated() const ;
+ S32 getDiscardLevelInAtlas() const ;
+ //---------------------------------------------------------------------------------------------
+ //end of functions to access LLImageGL
+ //---------------------------------------------------------------------------------------------
+
+ //-----------------
+ /*virtual*/ void setActive() ;
+ void forceActive() ;
+ void setNoDelete() ;
+ void dontDiscard() { mDontDiscard = 1; mTextureState = NO_DELETE; }
+ BOOL getDontDiscard() const { return mDontDiscard; }
+ //-----------------
+
+ BOOL isLargeImage() ;
+
+ void setParcelMedia(LLViewerMediaTexture* media) {mParcelMedia = media;}
+ BOOL hasParcelMedia() const { return mParcelMedia != NULL;}
+ LLViewerMediaTexture* getParcelMedia() const { return mParcelMedia;}
+
+ /*virtual*/ void updateBindStatsForTester() ;
+protected:
+ void cleanup() ;
+ void init(bool firstinit) ;
+ void reorganizeFaceList() ;
+
+private:
+ //note: do not make this function public.
+ /*virtual*/ LLImageGL* getGLTexture() const ;
+ virtual void switchToCachedImage();
+
+protected:
+ LLUUID mID;
+ S32 mBoostLevel; // enum describing priority level
+ S32 mFullWidth;
+ S32 mFullHeight;
+ BOOL mUseMipMaps ;
+ S8 mComponents;
+ mutable F32 mMaxVirtualSize; // The largest virtual size of the image, in pixels - how much data to we need?
+ mutable S8 mNeedsGLTexture;
+ mutable BOOL mNeedsResetMaxVirtualSize ;
+ mutable F32 mAdditionalDecodePriority; // priority add to mDecodePriority.
+ LLFrameTimer mLastReferencedTimer;
+
+ //GL texture
+ LLPointer<LLImageGL> mGLTexturep ;
+ S8 mDontDiscard; // Keep full res version of this image (for UI, etc)
+
+ ll_face_list_t mFaceList ; //reverse pointer pointing to the faces using this image as texture
+ U32 mNumFaces ;
+ LLFrameTimer mLastFaceListUpdateTimer ;
+
+ //do not use LLPointer here.
+ LLViewerMediaTexture* mParcelMedia ;
+
+protected:
+ typedef enum
+ {
+ DELETED = 0, //removed from memory
+ DELETION_CANDIDATE, //ready to be removed from memory
+ INACTIVE, //not be used for the last certain period (i.e., 30 seconds).
+ ACTIVE, //just being used, can become inactive if not being used for a certain time (10 seconds).
+ NO_DELETE = 99 //stay in memory, can not be removed.
+ } LLGLTexureState;
+ LLGLTexureState mTextureState ;
+
+public:
+ static const U32 sCurrentFileVersion;
+ static S32 sImageCount;
+ static S32 sRawCount;
+ static S32 sAuxCount;
+ static LLTimer sEvaluationTimer;
+ static F32 sDesiredDiscardBias;
+ static F32 sDesiredDiscardScale;
+ static S32 sBoundTextureMemoryInBytes;
+ static S32 sTotalTextureMemoryInBytes;
+ static S32 sMaxBoundTextureMemInMegaBytes;
+ static S32 sMaxTotalTextureMemInMegaBytes;
+ static S32 sMaxDesiredTextureMemInBytes ;
+ static S8 sCameraMovingDiscardBias;
+ static S32 sMaxSculptRez ;
+ static S32 sMinLargeImageSize ;
+ static S32 sMaxSmallImageSize ;
+ static BOOL sFreezeImageScalingDown ;//do not scale down image res if set.
+ static F32 sCurrentTime ;
+ static BOOL sUseTextureAtlas ;
+
+ static LLPointer<LLViewerTexture> sNullImagep; // Null texture for non-textured objects.
+};
+
+
+//
+//textures are managed in gTextureList.
+//raw image data is fetched from remote or local cache
+//but the raw image this texture pointing to is fixed.
+//
+class LLViewerFetchedTexture : public LLViewerTexture
+{
+ friend class LLTextureBar; // debug info only
+ friend class LLTextureView; // debug info only
+
+protected:
+ /*virtual*/ ~LLViewerFetchedTexture();
+public:
+ LLViewerFetchedTexture(const LLUUID& id, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE);
+ LLViewerFetchedTexture(const LLImageRaw* raw, BOOL usemipmaps);
+ LLViewerFetchedTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps = TRUE);
+
+public:
+ static F32 maxDecodePriority();
+
+ struct Compare
+ {
+ // lhs < rhs
+ bool operator()(const LLPointer<LLViewerFetchedTexture> &lhs, const LLPointer<LLViewerFetchedTexture> &rhs) const
+ {
+ const LLViewerFetchedTexture* lhsp = (const LLViewerFetchedTexture*)lhs;
+ const LLViewerFetchedTexture* rhsp = (const LLViewerFetchedTexture*)rhs;
+ // greater priority is "less"
+ const F32 lpriority = lhsp->getDecodePriority();
+ const F32 rpriority = rhsp->getDecodePriority();
+ if (lpriority > rpriority) // higher priority
+ return true;
+ if (lpriority < rpriority)
+ return false;
+ return lhsp < rhsp;
+ }
+ };
+
+public:
+ /*virtual*/ S8 getType() const ;
+ /*virtual*/ void forceImmediateUpdate() ;
+ /*virtual*/ void dump() ;
+
+ // Set callbacks to get called when the image gets updated with higher
+ // resolution versions.
+ void setLoadedCallback(loaded_callback_func cb,
+ S32 discard_level, BOOL keep_imageraw, BOOL needs_aux,
+ void* userdata);
+ bool hasCallbacks() { return mLoadedCallbackList.empty() ? false : true; }
+ bool doLoadedCallbacks();
+
+ void addToCreateTexture();
+
+ // ONLY call from LLViewerTextureList
+ BOOL createTexture(S32 usename = 0);
+ void destroyTexture() ;
+
+ virtual void processTextureStats() ;
+ F32 calcDecodePriority() ;
+
+ BOOL needsAux() const { return mNeedsAux; }
+
+ // Host we think might have this image, used for baked av textures.
+ void setTargetHost(LLHost host) { mTargetHost = host; }
+ LLHost getTargetHost() const { return mTargetHost; }
+
+ // Set the decode priority for this image...
+ // DON'T CALL THIS UNLESS YOU KNOW WHAT YOU'RE DOING, it can mess up
+ // the priority list, and cause horrible things to happen.
+ void setDecodePriority(F32 priority = -1.0f);
+ F32 getDecodePriority() const { return mDecodePriority; };
+
+ void setAdditionalDecodePriority(F32 priority) ;
+
+ void updateVirtualSize() ;
+
+ S32 getDesiredDiscardLevel() { return mDesiredDiscardLevel; }
+ void setMinDiscardLevel(S32 discard) { mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel,(S8)discard); }
+
+ bool updateFetch();
+
+ // Override the computation of discard levels if we know the exact output
+ // size of the image. Used for UI textures to not decode, even if we have
+ // more data.
+ /*virtual*/ void setKnownDrawSize(S32 width, S32 height);
+
+ void setIsMissingAsset();
+ /*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; }
+
+ // returns dimensions of original image for local files (before power of two scaling)
+ // and returns 0 for all asset system images
+ S32 getOriginalWidth() { return mOrigWidth; }
+ S32 getOriginalHeight() { return mOrigHeight; }
+
+ BOOL isInImageList() const {return mInImageList ;}
+ void setInImageList(BOOL flag) {mInImageList = flag ;}
+
+ LLFrameTimer* getLastPacketTimer() {return &mLastPacketTimer;}
+
+ U32 getFetchPriority() const { return mFetchPriority ;}
+ F32 getDownloadProgress() const {return mDownloadProgress ;}
+
+ LLImageRaw* reloadRawImage(S8 discard_level) ;
+ void destroyRawImage();
+
+ const std::string& getUrl() const {return mUrl;}
+ //---------------
+ BOOL isDeleted() ;
+ BOOL isInactive() ;
+ BOOL isDeletionCandidate();
+ void setDeletionCandidate() ;
+ void setInactive() ;
+ BOOL getUseDiscard() const { return mUseMipMaps && !mDontDiscard; }
+ //---------------
+
+ void setForSculpt();
+ BOOL forSculpt() const {return mForSculpt;}
+ BOOL isForSculptOnly() const;
+
+ //raw image management
+ void checkCachedRawSculptImage() ;
+ LLImageRaw* getRawImage()const { return mRawImage ;}
+ S32 getRawImageLevel() const {return mRawDiscardLevel;}
+ LLImageRaw* getCachedRawImage() const { return mCachedRawImage ;}
+ S32 getCachedRawImageLevel() const {return mCachedRawDiscardLevel;}
+ BOOL isCachedRawImageReady() const {return mCachedRawImageReady ;}
+ BOOL isRawImageValid()const { return mIsRawImageValid ; }
+ void forceToSaveRawImage(S32 desired_discard = 0) ;
+ void destroySavedRawImage() ;
+ LLImageRaw* getSavedRawImage() ;
+ BOOL hasSavedRawImage() const ;
+ F32 getElapsedLastReferencedSavedRawImageTime() const ;
+ BOOL isFullyLoaded() const;
+
+protected:
+ /*virtual*/ void switchToCachedImage();
+
+private:
+ void init(bool firstinit) ;
+ void cleanup() ;
+
+ void saveRawImage() ;
+ BOOL forceFetch() ;
+ void setCachedRawImage() ;
+ BOOL keepReuestedDiscardLevel();
+
+ //for atlas
+ void resetFaceAtlas() ;
+ void invalidateAtlas(BOOL rebuild_geom) ;
+ BOOL insertToAtlas() ;
+
+private:
+ BOOL mFullyLoaded;
+
+protected:
+ std::string mLocalFileName;
+
+ S32 mOrigWidth;
+ S32 mOrigHeight;
+
+ // Override the computation of discard levels if we know the exact output size of the image.
+ // Used for UI textures to not decode, even if we have more data.
+ S32 mKnownDrawWidth;
+ S32 mKnownDrawHeight;
+ BOOL mKnownDrawSizeChanged ;
+ std::string mUrl;
+
+ S32 mRequestedDiscardLevel;
+ F32 mRequestedDownloadPriority;
+ S32 mFetchState;
+ U32 mFetchPriority;
+ F32 mDownloadProgress;
+ F32 mFetchDeltaTime;
+ F32 mRequestDeltaTime;
+ F32 mDecodePriority; // The priority for decoding this image.
+ S32 mMinDiscardLevel;
+ S8 mDesiredDiscardLevel; // The discard level we'd LIKE to have - if we have it and there's space
+ S8 mMinDesiredDiscardLevel; // The minimum discard level we'd like to have
+
+ S8 mNeedsAux; // We need to decode the auxiliary channels
+ S8 mDecodingAux; // Are we decoding high components
+ S8 mIsRawImageValid;
+ S8 mHasFetcher; // We've made a fecth request
+ S8 mIsFetching; // Fetch request is active
+
+ mutable S8 mIsMissingAsset; // True if we know that there is no image asset with this image id in the database.
+
+ typedef std::list<LLLoadedCallbackEntry*> callback_list_t;
+ S8 mLoadedCallbackDesiredDiscardLevel;
+ callback_list_t mLoadedCallbackList;
+
+ LLPointer<LLImageRaw> mRawImage;
+ S32 mRawDiscardLevel;
+
+ // Used ONLY for cloth meshes right now. Make SURE you know what you're
+ // doing if you use it for anything else! - djs
+ LLPointer<LLImageRaw> mAuxRawImage;
+
+ //keep a copy of mRawImage for some special purposes
+ //when mForceToSaveRawImage is set.
+ BOOL mForceToSaveRawImage ;
+ LLPointer<LLImageRaw> mSavedRawImage;
+ S32 mSavedRawDiscardLevel;
+ S32 mDesiredSavedRawDiscardLevel;
+ F32 mLastReferencedSavedRawImageTime ;
+
+ //a small version of the copy of the raw image (<= 64 * 64)
+ LLPointer<LLImageRaw> mCachedRawImage;
+ S32 mCachedRawDiscardLevel;
+ BOOL mCachedRawImageReady; //the rez of the mCachedRawImage reaches the upper limit.
+
+ LLHost mTargetHost; // if LLHost::invalid, just request from agent's simulator
+
+ // Timers
+ LLFrameTimer mLastPacketTimer; // Time since last packet.
+
+ BOOL mInImageList; // TRUE if image is in list (in which case don't reset priority!)
+ BOOL mNeedsCreateTexture;
+
+ BOOL mForSculpt ; //a flag if the texture is used as sculpt data.
+ BOOL mIsFetched ; //is loaded from remote or from cache, not generated locally.
+
+public:
+ static LLPointer<LLViewerFetchedTexture> sMissingAssetImagep; // Texture to show for an image asset that is not in the database
+ static LLPointer<LLViewerFetchedTexture> sWhiteImagep; // Texture to show NOTHING (whiteness)
+ static LLPointer<LLViewerFetchedTexture> sDefaultImagep; // "Default" texture for error cases, the only case of fetched texture which is generated in local.
+ static LLPointer<LLViewerFetchedTexture> sSmokeImagep; // Old "Default" translucent texture
+};
+
+//
+//the image data is fetched from remote or from local cache
+//the resolution of the texture is adjustable: depends on the view-dependent parameters.
+//
+class LLViewerLODTexture : public LLViewerFetchedTexture
+{
+protected:
+ /*virtual*/ ~LLViewerLODTexture(){}
+
+public:
+ LLViewerLODTexture(const LLUUID& id, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE);
+ LLViewerLODTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps = TRUE);
+
+ /*virtual*/ S8 getType() const;
+ // Process image stats to determine priority/quality requirements.
+ /*virtual*/ void processTextureStats();
+ BOOL isUpdateFrozen() ;
+
+private:
+ void init(bool firstinit) ;
+ void scaleDown() ;
+
+private:
+
+ F32 mTexelsPerImage; // Texels per image.
+ F32 mDiscardVirtualSize; // Virtual size used to calculate desired discard
+ F32 mCalculatedDiscardLevel; // Last calculated discard level
+};
+
+//
+//the image data is fetched from the media pipeline periodically
+//the resolution of the texture is also adjusted by the media pipeline
+//
+class LLViewerMediaTexture : public LLViewerTexture
+{
+protected:
+ /*virtual*/ ~LLViewerMediaTexture() ;
+
+public:
+ LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ;
+
+ /*virtual*/ S8 getType() const;
+ void reinit(BOOL usemipmaps = TRUE);
+
+ BOOL getUseMipMaps() {return mUseMipMaps ; }
+ void setUseMipMaps(BOOL mipmap) ;
+
+ void setPlaying(BOOL playing) ;
+ BOOL isPlaying() const {return mIsPlaying;}
+ void setMediaImpl() ;
+
+ void initVirtualSize() ;
+ void invalidateMediaImpl() ;
+
+ void addMediaToFace(LLFace* facep) ;
+ void removeMediaFromFace(LLFace* facep) ;
+
+ /*virtual*/ void addFace(LLFace* facep) ;
+ /*virtual*/ void removeFace(LLFace* facep) ;
+
+ /*virtual*/ F32 getMaxVirtualSize() ;
+private:
+ void switchTexture(LLFace* facep) ;
+ BOOL findFaces() ;
+ void stopPlaying() ;
+
+private:
+ //
+ //an instant list, recording all faces referencing or can reference to this media texture.
+ //NOTE: it is NOT thread safe.
+ //
+ std::list< LLFace* > mMediaFaceList ;
+
+ //an instant list keeping all textures which are replaced by the current media texture,
+ //is only used to avoid the removal of those textures from memory.
+ std::list< LLPointer<LLViewerTexture> > mTextureList ;
+
+ LLViewerMediaImpl* mMediaImplp ;
+ BOOL mIsPlaying ;
+ U32 mUpdateVirtualSizeTime ;
+
+public:
+ static void updateClass() ;
+ static void cleanup() ;
+
+ static LLViewerMediaTexture* findMediaTexture(const LLUUID& media_id) ;
+ static void removeMediaImplFromTexture(const LLUUID& media_id) ;
+
+private:
+ typedef std::map< LLUUID, LLPointer<LLViewerMediaTexture> > media_map_t ;
+ static media_map_t sMediaMap ;
+};
+
+//just an interface class, do not create instance from this class.
+class LLViewerTextureManager
+{
+private:
+ //make the constructor private to preclude creating instances from this class.
+ LLViewerTextureManager(){}
+
+public:
+ //texture pipeline tester
+ static LLTexturePipelineTester* sTesterp ;
+
+ //returns NULL if tex is not a LLViewerFetchedTexture nor derived from LLViewerFetchedTexture.
+ static LLViewerFetchedTexture* staticCastToFetchedTexture(LLTexture* tex, BOOL report_error = FALSE) ;
+
+ //
+ //"find-texture" just check if the texture exists, if yes, return it, otherwise return null.
+ //
+ static LLViewerTexture* findTexture(const LLUUID& id) ;
+ static LLViewerMediaTexture* findMediaTexture(const LLUUID& id) ;
+
+ static LLViewerMediaTexture* createMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ;
+
+ //
+ //"get-texture" will create a new texture if the texture does not exist.
+ //
+ static LLViewerMediaTexture* getMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ;
+
+ static LLPointer<LLViewerTexture> getLocalTexture(BOOL usemipmaps = TRUE, BOOL generate_gl_tex = TRUE);
+ static LLPointer<LLViewerTexture> getLocalTexture(const LLUUID& id, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) ;
+ static LLPointer<LLViewerTexture> getLocalTexture(const LLImageRaw* raw, BOOL usemipmaps) ;
+ static LLPointer<LLViewerTexture> getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) ;
+
+ static LLViewerFetchedTexture* getFetchedTexture(const LLUUID &image_id,
+ BOOL usemipmap = TRUE,
+ LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation.
+ S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
+ LLGLint internal_format = 0,
+ LLGLenum primary_format = 0,
+ LLHost request_from_host = LLHost()
+ );
+
+ static LLViewerFetchedTexture* getFetchedTextureFromFile(const std::string& filename,
+ BOOL usemipmap = TRUE,
+ LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE,
+ S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
+ LLGLint internal_format = 0,
+ LLGLenum primary_format = 0,
+ const LLUUID& force_id = LLUUID::null
+ );
+
+ static LLViewerFetchedTexture* getFetchedTextureFromUrl(const std::string& url,
+ BOOL usemipmap = TRUE,
+ LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE,
+ S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
+ LLGLint internal_format = 0,
+ LLGLenum primary_format = 0,
+ const LLUUID& force_id = LLUUID::null
+ );
+
+ static LLViewerFetchedTexture* getFetchedTextureFromHost(const LLUUID& image_id, LLHost host) ;
+
+ static void init() ;
+ static void cleanup() ;
+};
+//
+//this class is used for test/debug only
+//it tracks the activities of the texture pipeline
+//records them, and outputs them to log files
+//
+class LLTexturePipelineTester : public LLMetricPerformanceTester
+{
+ enum
+ {
+ MIN_LARGE_IMAGE_AREA = 262144 //512 * 512
+ };
+public:
+ LLTexturePipelineTester() ;
+ ~LLTexturePipelineTester() ;
+
+ void update();
+ void updateTextureBindingStats(const LLViewerTexture* imagep) ;
+ void updateTextureLoadingStats(const LLViewerFetchedTexture* imagep, const LLImageRaw* raw_imagep, BOOL from_cache) ;
+ void updateGrayTextureBinding() ;
+ void setStablizingTime() ;
+
+ /*virtual*/ void analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) ;
+
+private:
+ void reset() ;
+ void updateStablizingTime() ;
+
+ /*virtual*/ void outputTestRecord(LLSD* sd) ;
+
+private:
+ BOOL mPause ;
+private:
+ BOOL mUsingDefaultTexture; //if set, some textures are still gray.
+
+ U32 mTotalBytesUsed ; //total bytes of textures bound/used for the current frame.
+ U32 mTotalBytesUsedForLargeImage ; //total bytes of textures bound/used for the current frame for images larger than 256 * 256.
+ U32 mLastTotalBytesUsed ; //total bytes of textures bound/used for the previous frame.
+ U32 mLastTotalBytesUsedForLargeImage ; //total bytes of textures bound/used for the previous frame for images larger than 256 * 256.
+
+ //
+ //data size
+ //
+ U32 mTotalBytesLoaded ; //total bytes fetched by texture pipeline
+ U32 mTotalBytesLoadedFromCache ; //total bytes fetched by texture pipeline from local cache
+ U32 mTotalBytesLoadedForLargeImage ; //total bytes fetched by texture pipeline for images larger than 256 * 256.
+ U32 mTotalBytesLoadedForSculpties ; //total bytes fetched by texture pipeline for sculpties
+
+ //
+ //time
+ //NOTE: the error tolerances of the following timers is one frame time.
+ //
+ F32 mStartFetchingTime ;
+ F32 mTotalGrayTime ; //total loading time when no gray textures.
+ F32 mTotalStablizingTime ; //total stablizing time when texture memory overflows
+ F32 mStartTimeLoadingSculpties ; //the start moment of loading sculpty images.
+ F32 mEndTimeLoadingSculpties ; //the end moment of loading sculpty images.
+ F32 mStartStablizingTime ;
+ F32 mEndStablizingTime ;
+
+private:
+ //
+ //The following members are used for performance analyzing
+ //
+ class LLTextureTestSession : public LLTestSession
+ {
+ public:
+ LLTextureTestSession() ;
+ /*virtual*/ ~LLTextureTestSession() ;
+
+ void reset() ;
+
+ F32 mTotalFetchingTime ;
+ F32 mTotalGrayTime ;
+ F32 mTotalStablizingTime ;
+ F32 mStartTimeLoadingSculpties ;
+ F32 mTotalTimeLoadingSculpties ;
+
+ S32 mTotalBytesLoaded ;
+ S32 mTotalBytesLoadedFromCache ;
+ S32 mTotalBytesLoadedForLargeImage ;
+ S32 mTotalBytesLoadedForSculpties ;
+
+ typedef struct _texture_instant_preformance_t
+ {
+ S32 mAverageBytesUsedPerSecond ;
+ S32 mAverageBytesUsedForLargeImagePerSecond ;
+ F32 mAveragePercentageBytesUsedPerSecond ;
+ F32 mTime ;
+ }texture_instant_preformance_t ;
+ std::vector<texture_instant_preformance_t> mInstantPerformanceList ;
+ S32 mInstantPerformanceListCounter ;
+ };
+
+ /*virtual*/ LLMetricPerformanceTester::LLTestSession* loadTestSession(LLSD* log) ;
+ /*virtual*/ void compareTestSessions(std::ofstream* os) ;
+};
+
+#endif
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
new file mode 100644
index 0000000000..ee934ab9c5
--- /dev/null
+++ b/indra/newview/llviewertexturelist.cpp
@@ -0,0 +1,1582 @@
+/**
+ * @file llviewertexturelist.cpp
+ * @brief Object for managing the list of images within a region
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include <sys/stat.h>
+
+#include "llviewertexturelist.h"
+
+#include "imageids.h"
+#include "llgl.h" // fot gathering stats from GL
+#include "llimagegl.h"
+#include "llimagebmp.h"
+#include "llimagej2c.h"
+#include "llimagetga.h"
+#include "llimagejpeg.h"
+#include "llimagepng.h"
+#include "llimageworker.h"
+
+#include "llsdserialize.h"
+#include "llsys.h"
+#include "llvfs.h"
+#include "llvfile.h"
+#include "llvfsthread.h"
+#include "llxmltree.h"
+#include "message.h"
+
+#include "lltexturecache.h"
+#include "lltexturefetch.h"
+#include "llviewercontrol.h"
+#include "llviewertexture.h"
+#include "llviewermedia.h"
+#include "llviewerregion.h"
+#include "llviewerstats.h"
+#include "pipeline.h"
+#include "llappviewer.h"
+#include "llxuiparser.h"
+
+////////////////////////////////////////////////////////////////////////////
+
+void (*LLViewerTextureList::sUUIDCallback)(void **, const LLUUID&) = NULL;
+
+U32 LLViewerTextureList::sTextureBits = 0;
+U32 LLViewerTextureList::sTexturePackets = 0;
+S32 LLViewerTextureList::sNumImages = 0;
+LLStat LLViewerTextureList::sNumImagesStat(32, TRUE);
+LLStat LLViewerTextureList::sNumRawImagesStat(32, TRUE);
+LLStat LLViewerTextureList::sGLTexMemStat(32, TRUE);
+LLStat LLViewerTextureList::sGLBoundMemStat(32, TRUE);
+LLStat LLViewerTextureList::sRawMemStat(32, TRUE);
+LLStat LLViewerTextureList::sFormattedMemStat(32, TRUE);
+
+LLViewerTextureList gTextureList;
+static LLFastTimer::DeclareTimer FTM_PROCESS_IMAGES("Process Images");
+
+///////////////////////////////////////////////////////////////////////////////
+
+LLViewerTextureList::LLViewerTextureList()
+ : mForceResetTextureStats(FALSE),
+ mUpdateStats(FALSE),
+ mMaxResidentTexMemInMegaBytes(0),
+ mMaxTotalTextureMemInMegaBytes(0)
+{
+}
+
+void LLViewerTextureList::init()
+{
+ sNumImages = 0;
+ mMaxResidentTexMemInMegaBytes = 0;
+ mMaxTotalTextureMemInMegaBytes = 0 ;
+ if (gNoRender)
+ {
+ // Don't initialize GL stuff if we're not rendering.
+ return;
+ }
+
+ mUpdateStats = TRUE;
+
+ // Update how much texture RAM we're allowed to use.
+ updateMaxResidentTexMem(0); // 0 = use current
+
+ doPreloadImages();
+}
+
+
+void LLViewerTextureList::doPreloadImages()
+{
+ LL_DEBUGS("ViewerImages") << "Preloading images..." << LL_ENDL;
+
+ // Set the "missing asset" image
+ LLViewerFetchedTexture::sMissingAssetImagep = LLViewerTextureManager::getFetchedTextureFromFile("missing_asset.tga", MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI);
+
+ // Set the "white" image
+ LLViewerFetchedTexture::sWhiteImagep = LLViewerTextureManager::getFetchedTextureFromFile("white.tga", MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI);
+
+ LLUIImageList* image_list = LLUIImageList::getInstance();
+
+ image_list->initFromFile();
+
+ // turn off clamping and bilinear filtering for uv picking images
+ //LLViewerFetchedTexture* uv_test = preloadUIImage("uv_test1.tga", LLUUID::null, FALSE);
+ //uv_test->setClamp(FALSE, FALSE);
+ //uv_test->setMipFilterNearest(TRUE, TRUE);
+ //uv_test = preloadUIImage("uv_test2.tga", LLUUID::null, FALSE);
+ //uv_test->setClamp(FALSE, FALSE);
+ //uv_test->setMipFilterNearest(TRUE, TRUE);
+
+ // prefetch specific UUIDs
+ LLViewerTextureManager::getFetchedTexture(IMG_SHOT, TRUE);
+ LLViewerTextureManager::getFetchedTexture(IMG_SMOKE_POOF, TRUE);
+ LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI);
+ if (image)
+ {
+ image->setAddressMode(LLTexUnit::TAM_WRAP);
+ mImagePreloads.insert(image);
+ }
+ image = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryLines.png", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI);
+ if (image)
+ {
+ image->setAddressMode(LLTexUnit::TAM_WRAP);
+ mImagePreloads.insert(image);
+ }
+ image = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryPassLines.png", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI);
+ if (image)
+ {
+ image->setAddressMode(LLTexUnit::TAM_WRAP);
+ mImagePreloads.insert(image);
+ }
+ image = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI);
+ if (image)
+ {
+ image->setAddressMode(LLTexUnit::TAM_WRAP);
+ mImagePreloads.insert(image);
+ }
+ image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE,
+ 0,0,LLUUID("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"));
+ if (image)
+ {
+ image->setAddressMode(LLTexUnit::TAM_WRAP);
+ mImagePreloads.insert(image);
+ }
+
+}
+
+static std::string get_texture_list_name()
+{
+ return std::string("texture_list_") + gSavedSettings.getString("LoginLocation") + ".xml";
+}
+
+void LLViewerTextureList::doPrefetchImages()
+{
+ if (LLAppViewer::instance()->getPurgeCache())
+ {
+ // cache was purged, no point
+ return;
+ }
+
+ // Pre-fetch textures from last logout
+ LLSD imagelist;
+ std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, get_texture_list_name());
+ llifstream file;
+ file.open(filename);
+ if (file.is_open())
+ {
+ LLSDSerialize::fromXML(imagelist, file);
+ }
+ for (LLSD::array_iterator iter = imagelist.beginArray();
+ iter != imagelist.endArray(); ++iter)
+ {
+ LLSD imagesd = *iter;
+ LLUUID uuid = imagesd["uuid"];
+ S32 pixel_area = imagesd["area"];
+ S32 texture_type = imagesd["type"];
+
+ if(LLViewerTexture::FETCHED_TEXTURE == texture_type || LLViewerTexture::LOD_TEXTURE == texture_type)
+ {
+ LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(uuid, MIPMAP_TRUE, LLViewerTexture::BOOST_NONE, texture_type);
+ if (image)
+ {
+ image->addTextureStats((F32)pixel_area);
+ }
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+LLViewerTextureList::~LLViewerTextureList()
+{
+}
+
+void LLViewerTextureList::shutdown()
+{
+ // clear out preloads
+ mImagePreloads.clear();
+
+ // Write out list of currently loaded textures for precaching on startup
+ typedef std::set<std::pair<S32,LLViewerFetchedTexture*> > image_area_list_t;
+ image_area_list_t image_area_list;
+ for (image_priority_list_t::iterator iter = mImageList.begin();
+ iter != mImageList.end(); ++iter)
+ {
+ LLViewerFetchedTexture* image = *iter;
+ if (!image->hasGLTexture() ||
+ !image->getUseDiscard() ||
+ image->needsAux() ||
+ image->getTargetHost() != LLHost::invalid)
+ {
+ continue; // avoid UI, baked, and other special images
+ }
+ if(!image->getBoundRecently())
+ {
+ continue ;
+ }
+ S32 desired = image->getDesiredDiscardLevel();
+ if (desired >= 0 && desired < MAX_DISCARD_LEVEL)
+ {
+ S32 pixel_area = image->getWidth(desired) * image->getHeight(desired);
+ image_area_list.insert(std::make_pair(pixel_area, image));
+ }
+ }
+
+ LLSD imagelist;
+ const S32 max_count = 1000;
+ S32 count = 0;
+ S32 image_type ;
+ for (image_area_list_t::reverse_iterator riter = image_area_list.rbegin();
+ riter != image_area_list.rend(); ++riter)
+ {
+ LLViewerFetchedTexture* image = riter->second;
+ image_type = (S32)image->getType() ;
+ imagelist[count]["area"] = riter->first;
+ imagelist[count]["uuid"] = image->getID();
+ imagelist[count]["type"] = image_type;
+ if (++count >= max_count)
+ break;
+ }
+
+ if (count > 0 && !gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "").empty())
+ {
+ std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, get_texture_list_name());
+ llofstream file;
+ file.open(filename);
+ LLSDSerialize::toPrettyXML(imagelist, file);
+ }
+
+ //
+ // Clean up "loaded" callbacks.
+ //
+ mCallbackList.clear();
+
+ // Flush all of the references
+ mLoadingStreamList.clear();
+ mCreateTextureList.clear();
+
+ mUUIDMap.clear();
+
+ mImageList.clear();
+}
+
+void LLViewerTextureList::dump()
+{
+ llinfos << "LLViewerTextureList::dump()" << llendl;
+ for (image_priority_list_t::iterator it = mImageList.begin(); it != mImageList.end(); ++it)
+ {
+ LLViewerFetchedTexture* image = *it;
+
+ llinfos << "priority " << image->getDecodePriority()
+ << " boost " << image->getBoostLevel()
+ << " size " << image->getWidth() << "x" << image->getHeight()
+ << " discard " << image->getDiscardLevel()
+ << " desired " << image->getDesiredDiscardLevel()
+ << " http://asset.siva.lindenlab.com/" << image->getID() << ".texture"
+ << llendl;
+ }
+}
+
+void LLViewerTextureList::destroyGL(BOOL save_state)
+{
+ LLImageGL::destroyGL(save_state);
+}
+
+void LLViewerTextureList::restoreGL()
+{
+ LLImageGL::restoreGL();
+}
+
+/* Vertical tab container button image IDs
+ Seem to not decode when running app in debug.
+
+ const LLUUID BAD_IMG_ONE("1097dcb3-aef9-8152-f471-431d840ea89e");
+ const LLUUID BAD_IMG_TWO("bea77041-5835-1661-f298-47e2d32b7a70");
+ */
+
+///////////////////////////////////////////////////////////////////////////////
+
+LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& filename,
+ BOOL usemipmaps,
+ LLViewerTexture::EBoostLevel boost_priority,
+ S8 texture_type,
+ LLGLint internal_format,
+ LLGLenum primary_format,
+ const LLUUID& force_id)
+{
+ std::string full_path = gDirUtilp->findSkinnedFilename("textures", filename);
+ if (full_path.empty())
+ {
+ llwarns << "Failed to find local image file: " << filename << llendl;
+ return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI);
+ }
+
+ std::string url = "file://" + full_path;
+
+ return getImageFromUrl(url, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id);
+}
+
+LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& url,
+ BOOL usemipmaps,
+ LLViewerTexture::EBoostLevel boost_priority,
+ S8 texture_type,
+ LLGLint internal_format,
+ LLGLenum primary_format,
+ const LLUUID& force_id)
+{
+ if (gNoRender)
+ {
+ // Never mind that this ignores image_set_id;
+ // getImage() will handle that later.
+ return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI);
+ }
+
+ // generate UUID based on hash of filename
+ LLUUID new_id;
+ if (force_id.notNull())
+ {
+ new_id = force_id;
+ }
+ else
+ {
+ new_id.generate(url);
+ }
+
+ LLPointer<LLViewerFetchedTexture> imagep = findImage(new_id);
+
+ if (imagep.isNull())
+ {
+ switch(texture_type)
+ {
+ case LLViewerTexture::FETCHED_TEXTURE:
+ imagep = new LLViewerFetchedTexture(url, new_id, usemipmaps);
+ break ;
+ case LLViewerTexture::LOD_TEXTURE:
+ imagep = new LLViewerLODTexture(url, new_id, usemipmaps);
+ break ;
+ default:
+ llerrs << "Invalid texture type " << texture_type << llendl ;
+ }
+
+ if (internal_format && primary_format)
+ {
+ imagep->setExplicitFormat(internal_format, primary_format);
+ }
+
+ addImage(imagep);
+
+ if (boost_priority != 0)
+ {
+ if (boost_priority == LLViewerFetchedTexture::BOOST_UI ||
+ boost_priority == LLViewerFetchedTexture::BOOST_ICON)
+ {
+ imagep->dontDiscard();
+ }
+ imagep->setBoostLevel(boost_priority);
+ }
+ }
+
+ imagep->setGLTextureCreated(true);
+
+ return imagep;
+}
+
+
+LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id,
+ BOOL usemipmaps,
+ LLViewerTexture::EBoostLevel boost_priority,
+ S8 texture_type,
+ LLGLint internal_format,
+ LLGLenum primary_format,
+ LLHost request_from_host)
+{
+ // Return the image with ID image_id
+ // If the image is not found, creates new image and
+ // enqueues a request for transmission
+
+ if ((&image_id == NULL) || image_id.isNull())
+ {
+ return (LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI));
+ }
+
+ LLPointer<LLViewerFetchedTexture> imagep = findImage(image_id);
+
+ if (imagep.isNull())
+ {
+ imagep = createImage(image_id, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ;
+ }
+
+ imagep->setGLTextureCreated(true);
+
+ return imagep;
+}
+
+//when this function is called, there is no such texture in the gTextureList with image_id.
+LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id,
+ BOOL usemipmaps,
+ LLViewerTexture::EBoostLevel boost_priority,
+ S8 texture_type,
+ LLGLint internal_format,
+ LLGLenum primary_format,
+ LLHost request_from_host)
+{
+ LLPointer<LLViewerFetchedTexture> imagep ;
+ switch(texture_type)
+ {
+ case LLViewerTexture::FETCHED_TEXTURE:
+ imagep = new LLViewerFetchedTexture(image_id, request_from_host, usemipmaps);
+ break ;
+ case LLViewerTexture::LOD_TEXTURE:
+ imagep = new LLViewerLODTexture(image_id, request_from_host, usemipmaps);
+ break ;
+ default:
+ llerrs << "Invalid texture type " << texture_type << llendl ;
+ }
+
+ if (internal_format && primary_format)
+ {
+ imagep->setExplicitFormat(internal_format, primary_format);
+ }
+
+ addImage(imagep);
+
+ if (boost_priority != 0)
+ {
+ if (boost_priority == LLViewerFetchedTexture::BOOST_UI ||
+ boost_priority == LLViewerFetchedTexture::BOOST_ICON)
+ {
+ imagep->dontDiscard();
+ }
+ imagep->setBoostLevel(boost_priority);
+ }
+ else
+ {
+ //by default, the texure can not be removed from memory even if it is not used.
+ //here turn this off
+ //if this texture should be set to NO_DELETE, call setNoDelete() afterwards.
+ imagep->forceActive() ;
+ }
+
+ return imagep ;
+}
+
+LLViewerFetchedTexture *LLViewerTextureList::findImage(const LLUUID &image_id)
+{
+ uuid_map_t::iterator iter = mUUIDMap.find(image_id);
+ if(iter == mUUIDMap.end())
+ return NULL;
+ return iter->second;
+}
+
+void LLViewerTextureList::addImageToList(LLViewerFetchedTexture *image)
+{
+ llassert(image);
+ if (image->isInImageList())
+ {
+ llerrs << "LLViewerTextureList::addImageToList - Image already in list" << llendl;
+ }
+ if ((mImageList.insert(image)).second != true)
+ {
+ llwarns << "BAD STUFF! (mImageList.insert(image)).second != true" << llendl;
+ }
+ image->setInImageList(TRUE) ;
+}
+
+void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)
+{
+ llassert(image);
+ if (!image->isInImageList())
+ {
+ llinfos << "RefCount: " << image->getNumRefs() << llendl ;
+ uuid_map_t::iterator iter = mUUIDMap.find(image->getID());
+ if(iter == mUUIDMap.end() || iter->second != image)
+ {
+ llinfos << "Image is not in mUUIDMap!" << llendl ;
+ }
+ llerrs << "LLViewerTextureList::removeImageFromList - Image not in list" << llendl;
+ }
+ if (mImageList.erase(image) != 1)
+ {
+ llwarns << "BAD STUFF! mImageList.erase(image) != 1" << llendl;
+ }
+ image->setInImageList(FALSE) ;
+}
+
+void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image)
+{
+ if (!new_image)
+ {
+ llwarning("No image to add to image list", 0);
+ return;
+ }
+ LLUUID image_id = new_image->getID();
+
+ LLViewerFetchedTexture *image = findImage(image_id);
+ if (image)
+ {
+ llwarns << "Image with ID " << image_id << " already in list" << llendl;
+ }
+ sNumImages++;
+
+ addImageToList(new_image);
+ mUUIDMap[image_id] = new_image;
+}
+
+
+void LLViewerTextureList::deleteImage(LLViewerFetchedTexture *image)
+{
+ if( image)
+ {
+ if (image->hasCallbacks())
+ {
+ mCallbackList.erase(image);
+ }
+
+ llverify(mUUIDMap.erase(image->getID()) == 1);
+ sNumImages--;
+ removeImageFromList(image);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////
+
+void LLViewerTextureList::dirtyImage(LLViewerFetchedTexture *image)
+{
+ mDirtyTextureList.insert(image);
+}
+
+////////////////////////////////////////////////////////////////////////////
+static LLFastTimer::DeclareTimer FTM_IMAGE_MARK_DIRTY("Dirty Images");
+
+void LLViewerTextureList::updateImages(F32 max_time)
+{
+ LLAppViewer::getTextureFetch()->setTextureBandwidth(LLViewerStats::getInstance()->mTextureKBitStat.getMeanPerSec());
+
+ LLViewerStats::getInstance()->mNumImagesStat.addValue(sNumImages);
+ LLViewerStats::getInstance()->mNumRawImagesStat.addValue(LLImageRaw::sRawImageCount);
+ LLViewerStats::getInstance()->mGLTexMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sGlobalTextureMemoryInBytes));
+ LLViewerStats::getInstance()->mGLBoundMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sBoundTextureMemoryInBytes));
+ LLViewerStats::getInstance()->mRawMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageRaw::sGlobalRawMemory));
+ LLViewerStats::getInstance()->mFormattedMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageFormatted::sGlobalFormattedMemory));
+
+ updateImagesDecodePriorities();
+
+ F32 total_max_time = max_time;
+ max_time -= updateImagesFetchTextures(max_time);
+
+ max_time = llmax(max_time, total_max_time*.50f); // at least 50% of max_time
+ max_time -= updateImagesCreateTextures(max_time);
+
+ if (!mDirtyTextureList.empty())
+ {
+ LLFastTimer t(FTM_IMAGE_MARK_DIRTY);
+ gPipeline.dirtyPoolObjectTextures(mDirtyTextureList);
+ mDirtyTextureList.clear();
+ }
+ bool didone = false;
+ for (image_list_t::iterator iter = mCallbackList.begin();
+ iter != mCallbackList.end(); )
+ {
+ //trigger loaded callbacks on local textures immediately
+ LLViewerFetchedTexture* image = *iter++;
+ if (!image->getUrl().empty())
+ {
+ // Do stuff to handle callbacks, update priorities, etc.
+ didone = image->doLoadedCallbacks();
+ }
+ else if (!didone)
+ {
+ // Do stuff to handle callbacks, update priorities, etc.
+ didone = image->doLoadedCallbacks();
+ }
+ }
+ updateImagesUpdateStats();
+}
+
+void LLViewerTextureList::updateImagesDecodePriorities()
+{
+ // Update the decode priority for N images each frame
+ {
+ const size_t max_update_count = llmin((S32) (1024*gFrameIntervalSeconds) + 1, 32); //target 1024 textures per second
+ S32 update_counter = llmin(max_update_count, mUUIDMap.size()/10);
+ uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateUUID);
+ while(update_counter > 0 && !mUUIDMap.empty())
+ {
+ if (iter == mUUIDMap.end())
+ {
+ iter = mUUIDMap.begin();
+ }
+ mLastUpdateUUID = iter->first;
+ LLPointer<LLViewerFetchedTexture> imagep = iter->second;
+ ++iter; // safe to incrament now
+
+ //
+ // Flush formatted images using a lazy flush
+ //
+ const F32 LAZY_FLUSH_TIMEOUT = 30.f; // stop decoding
+ const F32 MAX_INACTIVE_TIME = 50.f; // actually delete
+ S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference
+ if (imagep->hasCallbacks())
+ {
+ min_refs++; // Add an extra reference if we're on the loaded callback list
+ }
+ S32 num_refs = imagep->getNumRefs();
+ if (num_refs == min_refs)
+ {
+ if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > LAZY_FLUSH_TIMEOUT)
+ {
+ // Remove the unused image from the image list
+ deleteImage(imagep);
+ imagep = NULL; // should destroy the image
+ }
+ continue;
+ }
+ else
+ {
+ if(imagep->hasSavedRawImage())
+ {
+ if(imagep->getElapsedLastReferencedSavedRawImageTime() > MAX_INACTIVE_TIME)
+ {
+ imagep->destroySavedRawImage() ;
+ }
+ }
+
+ if(imagep->isDeleted())
+ {
+ continue ;
+ }
+ else if(imagep->isDeletionCandidate())
+ {
+ imagep->destroyTexture() ;
+ continue ;
+ }
+ else if(imagep->isInactive())
+ {
+ if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > MAX_INACTIVE_TIME)
+ {
+ imagep->setDeletionCandidate() ;
+ }
+ continue ;
+ }
+ else
+ {
+ imagep->getLastReferencedTimer()->reset();
+
+ //reset texture state.
+ imagep->setInactive() ;
+ }
+ }
+
+ imagep->processTextureStats();
+ F32 old_priority = imagep->getDecodePriority();
+ F32 old_priority_test = llmax(old_priority, 0.0f);
+ F32 decode_priority = imagep->calcDecodePriority();
+ F32 decode_priority_test = llmax(decode_priority, 0.0f);
+ // Ignore < 20% difference
+ if ((decode_priority_test < old_priority_test * .8f) ||
+ (decode_priority_test > old_priority_test * 1.25f))
+ {
+ removeImageFromList(imagep);
+ imagep->setDecodePriority(decode_priority);
+ addImageToList(imagep);
+ }
+ update_counter--;
+ }
+ }
+}
+
+/*
+ static U8 get_image_type(LLViewerFetchedTexture* imagep, LLHost target_host)
+ {
+ // Having a target host implies this is a baked image. I don't
+ // believe that boost level has been set at this point. JC
+ U8 type_from_host = (target_host.isOk()
+ ? LLImageBase::TYPE_AVATAR_BAKE
+ : LLImageBase::TYPE_NORMAL);
+ S32 boost_level = imagep->getBoostLevel();
+ U8 type_from_boost = ( (boost_level == LLViewerFetchedTexture::BOOST_AVATAR_BAKED
+ || boost_level == LLViewerFetchedTexture::BOOST_AVATAR_BAKED_SELF)
+ ? LLImageBase::TYPE_AVATAR_BAKE
+ : LLImageBase::TYPE_NORMAL);
+ if (type_from_host == LLImageBase::TYPE_NORMAL
+ && type_from_boost == LLImageBase::TYPE_AVATAR_BAKE)
+ {
+ llwarns << "TAT: get_image_type() type_from_host doesn't match type_from_boost"
+ << " host " << target_host
+ << " boost " << imagep->getBoostLevel()
+ << " imageid " << imagep->getID()
+ << llendl;
+ imagep->dump();
+ }
+ return type_from_host;
+ }
+ */
+static LLFastTimer::DeclareTimer FTM_IMAGE_CREATE("Create Images");
+
+F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time)
+{
+ if (gNoRender || gGLManager.mIsDisabled) return 0.0f;
+
+ //
+ // Create GL textures for all textures that need them (images which have been
+ // decoded, but haven't been pushed into GL).
+ //
+ LLFastTimer t(FTM_IMAGE_CREATE);
+
+ LLTimer create_timer;
+ image_list_t::iterator enditer = mCreateTextureList.begin();
+ for (image_list_t::iterator iter = mCreateTextureList.begin();
+ iter != mCreateTextureList.end();)
+ {
+ image_list_t::iterator curiter = iter++;
+ enditer = iter;
+ LLViewerFetchedTexture *imagep = *curiter;
+ imagep->createTexture();
+ if (create_timer.getElapsedTimeF32() > max_time)
+ {
+ break;
+ }
+ }
+ mCreateTextureList.erase(mCreateTextureList.begin(), enditer);
+ return create_timer.getElapsedTimeF32();
+}
+
+void LLViewerTextureList::forceImmediateUpdate(LLViewerFetchedTexture* imagep)
+{
+ if(!imagep)
+ {
+ return ;
+ }
+ if(imagep->isInImageList())
+ {
+ removeImageFromList(imagep);
+ }
+
+ imagep->processTextureStats();
+ F32 decode_priority = LLViewerFetchedTexture::maxDecodePriority() ;
+ imagep->setDecodePriority(decode_priority);
+ mImageList.insert(imagep);
+ imagep->setInImageList(TRUE) ;
+
+ return ;
+}
+
+F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)
+{
+ LLTimer image_op_timer;
+
+ // Update the decode priority for N images each frame
+ // Make a list with 32 high priority entries + 256 cycled entries
+ const size_t max_priority_count = llmin((S32) (256*10.f*gFrameIntervalSeconds)+1, 32);
+ const size_t max_update_count = llmin((S32) (1024*10.f*gFrameIntervalSeconds)+1, 256);
+
+ // 32 high priority entries
+ typedef std::vector<LLViewerFetchedTexture*> entries_list_t;
+ entries_list_t entries;
+ size_t update_counter = llmin(max_priority_count, mImageList.size());
+ image_priority_list_t::iterator iter1 = mImageList.begin();
+ while(update_counter > 0)
+ {
+ entries.push_back(*iter1);
+
+ ++iter1;
+ update_counter--;
+ }
+
+ // 256 cycled entries
+ update_counter = llmin(max_update_count, mUUIDMap.size());
+ if(update_counter > 0)
+ {
+ uuid_map_t::iterator iter2 = mUUIDMap.upper_bound(mLastFetchUUID);
+ uuid_map_t::iterator iter2p = iter2;
+ while(update_counter > 0)
+ {
+ if (iter2 == mUUIDMap.end())
+ {
+ iter2 = mUUIDMap.begin();
+ }
+ entries.push_back(iter2->second);
+ iter2p = iter2++;
+ update_counter--;
+ }
+
+ mLastFetchUUID = iter2p->first;
+ }
+
+ S32 fetch_count = 0;
+ S32 min_count = max_priority_count + max_update_count/4;
+ for (entries_list_t::iterator iter3 = entries.begin();
+ iter3 != entries.end(); )
+ {
+ LLPointer<LLViewerFetchedTexture> imagep = *iter3++;
+
+ bool fetching = imagep->updateFetch();
+ if (fetching)
+ {
+ fetch_count++;
+ }
+ if (min_count <= 0 && image_op_timer.getElapsedTimeF32() > max_time)
+ {
+ break;
+ }
+ min_count--;
+ }
+ if (fetch_count == 0)
+ {
+ gDebugTimers[0].pause();
+ }
+ else
+ {
+ gDebugTimers[0].unpause();
+ }
+ return image_op_timer.getElapsedTimeF32();
+}
+
+void LLViewerTextureList::updateImagesUpdateStats()
+{
+ if (mUpdateStats && mForceResetTextureStats)
+ {
+ for (image_priority_list_t::iterator iter = mImageList.begin();
+ iter != mImageList.end(); )
+ {
+ LLViewerFetchedTexture* imagep = *iter++;
+ imagep->resetTextureStats();
+ }
+ mUpdateStats = FALSE;
+ mForceResetTextureStats = FALSE;
+ }
+}
+
+void LLViewerTextureList::decodeAllImages(F32 max_time)
+{
+ LLTimer timer;
+ if(gNoRender) return;
+
+ // Update texture stats and priorities
+ std::vector<LLPointer<LLViewerFetchedTexture> > image_list;
+ for (image_priority_list_t::iterator iter = mImageList.begin();
+ iter != mImageList.end(); )
+ {
+ LLViewerFetchedTexture* imagep = *iter++;
+ image_list.push_back(imagep);
+ imagep->setInImageList(FALSE) ;
+ }
+ mImageList.clear();
+ for (std::vector<LLPointer<LLViewerFetchedTexture> >::iterator iter = image_list.begin();
+ iter != image_list.end(); ++iter)
+ {
+ LLViewerFetchedTexture* imagep = *iter;
+ imagep->processTextureStats();
+ F32 decode_priority = imagep->calcDecodePriority();
+ imagep->setDecodePriority(decode_priority);
+ mImageList.insert(imagep);
+ imagep->setInImageList(TRUE) ;
+ }
+ image_list.clear();
+
+ // Update fetch (decode)
+ for (image_priority_list_t::iterator iter = mImageList.begin();
+ iter != mImageList.end(); )
+ {
+ LLViewerFetchedTexture* imagep = *iter++;
+ imagep->updateFetch();
+ }
+ // Run threads
+ S32 fetch_pending = 0;
+ while (1)
+ {
+ LLAppViewer::instance()->getTextureCache()->update(1); // unpauses the texture cache thread
+ LLAppViewer::instance()->getImageDecodeThread()->update(1); // unpauses the image thread
+ fetch_pending = LLAppViewer::instance()->getTextureFetch()->update(1); // unpauses the texture fetch thread
+ if (fetch_pending == 0 || timer.getElapsedTimeF32() > max_time)
+ {
+ break;
+ }
+ }
+ // Update fetch again
+ for (image_priority_list_t::iterator iter = mImageList.begin();
+ iter != mImageList.end(); )
+ {
+ LLViewerFetchedTexture* imagep = *iter++;
+ imagep->updateFetch();
+ }
+ max_time -= timer.getElapsedTimeF32();
+ max_time = llmax(max_time, .001f);
+ F32 create_time = updateImagesCreateTextures(max_time);
+
+ LL_DEBUGS("ViewerImages") << "decodeAllImages() took " << timer.getElapsedTimeF32() << " seconds. "
+ << " fetch_pending " << fetch_pending
+ << " create_time " << create_time
+ << LL_ENDL;
+}
+
+
+BOOL LLViewerTextureList::createUploadFile(const std::string& filename,
+ const std::string& out_filename,
+ const U8 codec)
+{
+ // First, load the image.
+ LLPointer<LLImageRaw> raw_image = new LLImageRaw;
+
+ switch (codec)
+ {
+ case IMG_CODEC_BMP:
+ {
+ LLPointer<LLImageBMP> bmp_image = new LLImageBMP;
+
+ if (!bmp_image->load(filename))
+ {
+ return FALSE;
+ }
+
+ if (!bmp_image->decode(raw_image, 0.0f))
+ {
+ return FALSE;
+ }
+ }
+ break;
+ case IMG_CODEC_TGA:
+ {
+ LLPointer<LLImageTGA> tga_image = new LLImageTGA;
+
+ if (!tga_image->load(filename))
+ {
+ return FALSE;
+ }
+
+ if (!tga_image->decode(raw_image))
+ {
+ return FALSE;
+ }
+
+ if( (tga_image->getComponents() != 3) &&
+ (tga_image->getComponents() != 4) )
+ {
+ tga_image->setLastError( "Image files with less than 3 or more than 4 components are not supported." );
+ return FALSE;
+ }
+ }
+ break;
+ case IMG_CODEC_JPEG:
+ {
+ LLPointer<LLImageJPEG> jpeg_image = new LLImageJPEG;
+
+ if (!jpeg_image->load(filename))
+ {
+ return FALSE;
+ }
+
+ if (!jpeg_image->decode(raw_image, 0.0f))
+ {
+ return FALSE;
+ }
+ }
+ break;
+ case IMG_CODEC_PNG:
+ {
+ LLPointer<LLImagePNG> png_image = new LLImagePNG;
+
+ if (!png_image->load(filename))
+ {
+ return FALSE;
+ }
+
+ if (!png_image->decode(raw_image, 0.0f))
+ {
+ return FALSE;
+ }
+ }
+ break;
+ default:
+ return FALSE;
+ }
+
+ LLPointer<LLImageJ2C> compressedImage = convertToUploadFile(raw_image);
+
+ if( !compressedImage->save(out_filename) )
+ {
+ llinfos << "Couldn't create output file " << out_filename << llendl;
+ return FALSE;
+ }
+
+ // test to see if the encode and save worked.
+ LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C;
+ if( !integrity_test->loadAndValidate( out_filename ) )
+ {
+ llinfos << "Image: " << out_filename << " is corrupt." << llendl;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// note: modifies the argument raw_image!!!!
+LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImageRaw> raw_image)
+{
+ raw_image->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT);
+ LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C();
+ compressedImage->setRate(0.f);
+
+ if (gSavedSettings.getBOOL("LosslessJ2CUpload") &&
+ (raw_image->getWidth() * raw_image->getHeight() <= LL_IMAGE_REZ_LOSSLESS_CUTOFF * LL_IMAGE_REZ_LOSSLESS_CUTOFF))
+ compressedImage->setReversible(TRUE);
+
+ compressedImage->encode(raw_image, 0.0f);
+
+ return compressedImage;
+}
+
+const S32 MIN_VIDEO_RAM = 32;
+const S32 MAX_VIDEO_RAM = 512; // 512MB max for performance reasons.
+
+// Returns min setting for TextureMemory (in MB)
+S32 LLViewerTextureList::getMinVideoRamSetting()
+{
+ S32 system_ram = (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped());
+ //min texture mem sets to 64M if total physical mem is more than 1.5GB
+ return (system_ram > 1500) ? 64 : MIN_VIDEO_RAM_IN_MEGA_BYTES ;
+}
+
+//static
+// Returns max setting for TextureMemory (in MB)
+S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended)
+{
+ S32 max_texmem;
+ if (gGLManager.mVRAM != 0)
+ {
+ // Treat any card with < 32 MB (shudder) as having 32 MB
+ // - it's going to be swapping constantly regardless
+ S32 max_vram = gGLManager.mVRAM;
+ max_vram = llmax(max_vram, getMinVideoRamSetting());
+ max_texmem = max_vram;
+ if (!get_recommended)
+ max_texmem *= 2;
+ }
+ else
+ {
+ if (get_recommended)
+ max_texmem = 128;
+ else
+ max_texmem = 512;
+ llwarns << "VRAM amount not detected, defaulting to " << max_texmem << " MB" << llendl;
+ }
+
+ S32 system_ram = (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped()); // In MB
+ //llinfos << "*** DETECTED " << system_ram << " MB of system memory." << llendl;
+ if (get_recommended)
+ max_texmem = llmin(max_texmem, (S32)(system_ram/2));
+ else
+ max_texmem = llmin(max_texmem, (S32)(system_ram));
+
+ max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), MAX_VIDEO_RAM_IN_MEGA_BYTES);
+
+ return max_texmem;
+}
+
+const S32 VIDEO_CARD_FRAMEBUFFER_MEM = 12; // MB
+const S32 MIN_MEM_FOR_NON_TEXTURE = 512 ; //MB
+void LLViewerTextureList::updateMaxResidentTexMem(S32 mem)
+{
+ // Initialize the image pipeline VRAM settings
+ S32 cur_mem = gSavedSettings.getS32("TextureMemory");
+ F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple");
+ S32 default_mem = getMaxVideoRamSetting(true); // recommended default
+ if (mem == 0)
+ {
+ mem = cur_mem > 0 ? cur_mem : default_mem;
+ }
+ else if (mem < 0)
+ {
+ mem = default_mem;
+ }
+
+ // limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise
+ mem = llmin(mem, (S32) (mem_multiplier * (F32) default_mem));
+
+ mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting());
+ if (mem != cur_mem)
+ {
+ gSavedSettings.setS32("TextureMemory", mem);
+ return; //listener will re-enter this function
+ }
+
+ // TODO: set available resident texture mem based on use by other subsystems
+ // currently max(12MB, VRAM/4) assumed...
+
+ S32 vb_mem = mem;
+ S32 fb_mem = llmax(VIDEO_CARD_FRAMEBUFFER_MEM, vb_mem/4);
+ mMaxResidentTexMemInMegaBytes = (vb_mem - fb_mem) ; //in MB
+
+ mMaxTotalTextureMemInMegaBytes = mMaxResidentTexMemInMegaBytes * 2;
+ if (mMaxResidentTexMemInMegaBytes > 640)
+ {
+ mMaxTotalTextureMemInMegaBytes -= (mMaxResidentTexMemInMegaBytes >> 2);
+ }
+
+ //system mem
+ S32 system_ram = (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped()); // In MB
+
+ //minimum memory reserved for non-texture use.
+ //if system_raw >= 1GB, reserve at least 512MB for non-texture use;
+ //otherwise reserve half of the system_ram for non-texture use.
+ S32 min_non_texture_mem = llmin(system_ram / 2, MIN_MEM_FOR_NON_TEXTURE) ;
+
+ if (mMaxTotalTextureMemInMegaBytes > system_ram - min_non_texture_mem)
+ {
+ mMaxTotalTextureMemInMegaBytes = system_ram - min_non_texture_mem ;
+ }
+
+ llinfos << "Total Video Memory set to: " << vb_mem << " MB" << llendl;
+ llinfos << "Available Texture Memory set to: " << (vb_mem - fb_mem) << " MB" << llendl;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// static
+void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_data)
+{
+ LLFastTimer t(FTM_PROCESS_IMAGES);
+
+ // Receive image header, copy into image object and decompresses
+ // if this is a one-packet image.
+
+ LLUUID id;
+
+ char ip_string[256];
+ u32_to_ip_string(msg->getSenderIP(),ip_string);
+
+ if (msg->getReceiveCompressedSize())
+ {
+ gTextureList.sTextureBits += msg->getReceiveCompressedSize() * 8;
+ }
+ else
+ {
+ gTextureList.sTextureBits += msg->getReceiveSize() * 8;
+ }
+ gTextureList.sTexturePackets++;
+
+ U8 codec;
+ U16 packets;
+ U32 totalbytes;
+ msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id);
+ msg->getU8Fast(_PREHASH_ImageID, _PREHASH_Codec, codec);
+ msg->getU16Fast(_PREHASH_ImageID, _PREHASH_Packets, packets);
+ msg->getU32Fast(_PREHASH_ImageID, _PREHASH_Size, totalbytes);
+
+ S32 data_size = msg->getSizeFast(_PREHASH_ImageData, _PREHASH_Data);
+ if (!data_size)
+ {
+ return;
+ }
+ if (data_size < 0)
+ {
+ // msg->getSizeFast() is probably trying to tell us there
+ // was an error.
+ llerrs << "image header chunk size was negative: "
+ << data_size << llendl;
+ return;
+ }
+
+ // this buffer gets saved off in the packet list
+ U8 *data = new U8[data_size];
+ msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size);
+
+ LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+ if (!image)
+ {
+ delete [] data;
+ return;
+ }
+ image->getLastPacketTimer()->reset();
+ bool res = LLAppViewer::getTextureFetch()->receiveImageHeader(msg->getSender(), id, codec, packets, totalbytes, data_size, data);
+ if (!res)
+ {
+ delete[] data;
+ }
+}
+
+// static
+void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_data)
+{
+ LLMemType mt1(LLMemType::MTYPE_APPFMTIMAGE);
+ LLFastTimer t(FTM_PROCESS_IMAGES);
+
+ // Receives image packet, copy into image object,
+ // checks if all packets received, decompresses if so.
+
+ LLUUID id;
+ U16 packet_num;
+
+ char ip_string[256];
+ u32_to_ip_string(msg->getSenderIP(),ip_string);
+
+ if (msg->getReceiveCompressedSize())
+ {
+ gTextureList.sTextureBits += msg->getReceiveCompressedSize() * 8;
+ }
+ else
+ {
+ gTextureList.sTextureBits += msg->getReceiveSize() * 8;
+ }
+ gTextureList.sTexturePackets++;
+
+ //llprintline("Start decode, image header...");
+ msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id);
+ msg->getU16Fast(_PREHASH_ImageID, _PREHASH_Packet, packet_num);
+ S32 data_size = msg->getSizeFast(_PREHASH_ImageData, _PREHASH_Data);
+
+ if (!data_size)
+ {
+ return;
+ }
+ if (data_size < 0)
+ {
+ // msg->getSizeFast() is probably trying to tell us there
+ // was an error.
+ llerrs << "image data chunk size was negative: "
+ << data_size << llendl;
+ return;
+ }
+ if (data_size > MTUBYTES)
+ {
+ llerrs << "image data chunk too large: " << data_size << " bytes" << llendl;
+ return;
+ }
+ U8 *data = new U8[data_size];
+ msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size);
+
+ LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+ if (!image)
+ {
+ delete [] data;
+ return;
+ }
+ image->getLastPacketTimer()->reset();
+ bool res = LLAppViewer::getTextureFetch()->receiveImagePacket(msg->getSender(), id, packet_num, data_size, data);
+ if (!res)
+ {
+ delete[] data;
+ }
+}
+
+
+// We've been that the asset server does not contain the requested image id.
+// static
+void LLViewerTextureList::processImageNotInDatabase(LLMessageSystem *msg,void **user_data)
+{
+ LLFastTimer t(FTM_PROCESS_IMAGES);
+ LLUUID image_id;
+ msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, image_id);
+
+ LLViewerFetchedTexture* image = gTextureList.findImage( image_id );
+ if( image )
+ {
+ image->setIsMissingAsset();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+//static
+const U32 SIXTEEN_MEG = 0x1000000;
+S32 LLViewerTextureList::calcMaxTextureRAM()
+{
+ // Decide the maximum amount of RAM we should allow the user to allocate to texture cache
+ LLMemoryInfo memory_info;
+ U32 available_memory = memory_info.getPhysicalMemoryClamped();
+
+ clamp_rescale((F32)available_memory,
+ (F32)(SIXTEEN_MEG * 16),
+ (F32)U32_MAX,
+ (F32)(SIXTEEN_MEG * 4),
+ (F32)(U32_MAX >> 1));
+ return available_memory;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// explicitly cleanup resources, as this is a singleton class with process
+// lifetime so ability to perform std::map operations in destructor is not
+// guaranteed.
+void LLUIImageList::cleanUp()
+{
+ mUIImages.clear();
+ mUITextureList.clear() ;
+}
+
+LLUIImagePtr LLUIImageList::getUIImageByID(const LLUUID& image_id, S32 priority)
+{
+ // use id as image name
+ std::string image_name = image_id.asString();
+
+ // look for existing image
+ uuid_ui_image_map_t::iterator found_it = mUIImages.find(image_name);
+ if (found_it != mUIImages.end())
+ {
+ return found_it->second;
+ }
+
+ const BOOL use_mips = FALSE;
+ const LLRect scale_rect = LLRect::null;
+ return loadUIImageByID(image_id, use_mips, scale_rect, (LLViewerTexture::EBoostLevel)priority);
+}
+
+LLUIImagePtr LLUIImageList::getUIImage(const std::string& image_name, S32 priority)
+{
+ // look for existing image
+ uuid_ui_image_map_t::iterator found_it = mUIImages.find(image_name);
+ if (found_it != mUIImages.end())
+ {
+ return found_it->second;
+ }
+
+ const BOOL use_mips = FALSE;
+ const LLRect scale_rect = LLRect::null;
+ return loadUIImageByName(image_name, image_name, use_mips, scale_rect, (LLViewerTexture::EBoostLevel)priority);
+}
+
+LLUIImagePtr LLUIImageList::loadUIImageByName(const std::string& name, const std::string& filename,
+ BOOL use_mips, const LLRect& scale_rect, LLViewerTexture::EBoostLevel boost_priority )
+{
+ if (boost_priority == LLViewerTexture::BOOST_NONE)
+ {
+ boost_priority = LLViewerTexture::BOOST_UI;
+ }
+ LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTextureFromFile(filename, MIPMAP_NO, boost_priority);
+ return loadUIImage(imagep, name, use_mips, scale_rect);
+}
+
+LLUIImagePtr LLUIImageList::loadUIImageByID(const LLUUID& id,
+ BOOL use_mips, const LLRect& scale_rect, LLViewerTexture::EBoostLevel boost_priority)
+{
+ if (boost_priority == LLViewerTexture::BOOST_NONE)
+ {
+ boost_priority = LLViewerTexture::BOOST_UI;
+ }
+ LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(id, MIPMAP_NO, boost_priority);
+ return loadUIImage(imagep, id.asString(), use_mips, scale_rect);
+}
+
+LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep, const std::string& name, BOOL use_mips, const LLRect& scale_rect)
+{
+ if (!imagep) return NULL;
+
+ imagep->setAddressMode(LLTexUnit::TAM_CLAMP);
+
+ //all UI images are non-deletable
+ imagep->setNoDelete();
+
+ LLUIImagePtr new_imagep = new LLUIImage(name, imagep);
+ mUIImages.insert(std::make_pair(name, new_imagep));
+ mUITextureList.push_back(imagep);
+
+ LLUIImageLoadData* datap = new LLUIImageLoadData;
+ datap->mImageName = name;
+ datap->mImageScaleRegion = scale_rect;
+
+ imagep->setLoadedCallback(onUIImageLoaded, 0, FALSE, FALSE, datap);
+
+ return new_imagep;
+}
+
+LLUIImagePtr LLUIImageList::preloadUIImage(const std::string& name, const std::string& filename, BOOL use_mips, const LLRect& scale_rect)
+{
+ // look for existing image
+ uuid_ui_image_map_t::iterator found_it = mUIImages.find(name);
+ if (found_it != mUIImages.end())
+ {
+ // image already loaded!
+ llerrs << "UI Image " << name << " already loaded." << llendl;
+ }
+
+ return loadUIImageByName(name, filename, use_mips, scale_rect);
+}
+
+//static
+void LLUIImageList::onUIImageLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* user_data )
+{
+ if(!success || !user_data)
+ {
+ return;
+ }
+
+ LLUIImageLoadData* image_datap = (LLUIImageLoadData*)user_data;
+ std::string ui_image_name = image_datap->mImageName;
+ LLRect scale_rect = image_datap->mImageScaleRegion;
+ if (final)
+ {
+ delete image_datap;
+ }
+
+ LLUIImageList* instance = getInstance();
+
+ uuid_ui_image_map_t::iterator found_it = instance->mUIImages.find(ui_image_name);
+ if (found_it != instance->mUIImages.end())
+ {
+ LLUIImagePtr imagep = found_it->second;
+
+ // for images grabbed from local files, apply clipping rectangle to restore original dimensions
+ // from power-of-2 gl image
+ if (success && imagep.notNull() && src_vi && (src_vi->getUrl().compare(0, 7, "file://")==0))
+ {
+ F32 clip_x = (F32)src_vi->getOriginalWidth() / (F32)src_vi->getFullWidth();
+ F32 clip_y = (F32)src_vi->getOriginalHeight() / (F32)src_vi->getFullHeight();
+ imagep->setClipRegion(LLRectf(0.f, clip_y, clip_x, 0.f));
+ if (scale_rect != LLRect::null)
+ {
+ imagep->setScaleRegion(
+ LLRectf(llclamp((F32)scale_rect.mLeft / (F32)imagep->getWidth(), 0.f, 1.f),
+ llclamp((F32)scale_rect.mTop / (F32)imagep->getHeight(), 0.f, 1.f),
+ llclamp((F32)scale_rect.mRight / (F32)imagep->getWidth(), 0.f, 1.f),
+ llclamp((F32)scale_rect.mBottom / (F32)imagep->getHeight(), 0.f, 1.f)));
+ }
+
+ imagep->onImageLoaded();
+ }
+ }
+}
+
+struct UIImageDeclaration : public LLInitParam::Block<UIImageDeclaration>
+{
+ Mandatory<std::string> name;
+ Optional<std::string> file_name;
+ Optional<bool> preload;
+ Optional<LLRect> scale;
+ Optional<bool> use_mips;
+
+ UIImageDeclaration()
+ : name("name"),
+ file_name("file_name"),
+ preload("preload", false),
+ scale("scale"),
+ use_mips("use_mips", false)
+ {}
+};
+
+struct UIImageDeclarations : public LLInitParam::Block<UIImageDeclarations>
+{
+ Mandatory<S32> version;
+ Multiple<UIImageDeclaration> textures;
+
+ UIImageDeclarations()
+ : version("version"),
+ textures("texture")
+ {}
+};
+
+bool LLUIImageList::initFromFile()
+{
+ // construct path to canonical textures.xml in default skin dir
+ std::string base_file_path = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, "default", "textures", "textures.xml");
+
+ LLXMLNodePtr root;
+
+ if (!LLXMLNode::parseFile(base_file_path, root, NULL))
+ {
+ llwarns << "Unable to parse UI image list file " << base_file_path << llendl;
+ return false;
+ }
+ if (!root->hasAttribute("version"))
+ {
+ llwarns << "No valid version number in UI image list file " << base_file_path << llendl;
+ return false;
+ }
+
+ std::vector<std::string> paths;
+ // path to current selected skin
+ paths.push_back(gDirUtilp->getSkinDir()
+ + gDirUtilp->getDirDelimiter()
+ + "textures"
+ + gDirUtilp->getDirDelimiter()
+ + "textures.xml");
+ // path to user overrides on current skin
+ paths.push_back(gDirUtilp->getUserSkinDir()
+ + gDirUtilp->getDirDelimiter()
+ + "textures"
+ + gDirUtilp->getDirDelimiter()
+ + "textures.xml");
+
+ // apply skinned xml files incrementally
+ for(std::vector<std::string>::iterator path_it = paths.begin();
+ path_it != paths.end();
+ ++path_it)
+ {
+ // don't reapply base file to itself
+ if (!path_it->empty() && (*path_it) != base_file_path)
+ {
+ LLXMLNodePtr update_root;
+ if (LLXMLNode::parseFile(*path_it, update_root, NULL))
+ {
+ LLXMLNode::updateNode(root, update_root);
+ }
+ }
+ }
+
+ UIImageDeclarations images;
+ LLXUIParser::instance().readXUI(root, images, base_file_path);
+
+ if (!images.validateBlock()) return false;
+
+ enum e_decode_pass
+ {
+ PASS_DECODE_NOW,
+ PASS_DECODE_LATER,
+ NUM_PASSES
+ };
+
+ for (S32 cur_pass = PASS_DECODE_NOW; cur_pass < NUM_PASSES; cur_pass++)
+ {
+ for (LLInitParam::ParamIterator<UIImageDeclaration>::const_iterator image_it = images.textures().begin();
+ image_it != images.textures().end();
+ ++image_it)
+ {
+ std::string file_name = image_it->file_name.isProvided() ? image_it->file_name() : image_it->name();
+
+ // load high priority textures on first pass (to kick off decode)
+ enum e_decode_pass decode_pass = image_it->preload ? PASS_DECODE_NOW : PASS_DECODE_LATER;
+ if (decode_pass != cur_pass)
+ {
+ continue;
+ }
+ preloadUIImage(image_it->name, file_name, image_it->use_mips, image_it->scale);
+ }
+
+ if (cur_pass == PASS_DECODE_NOW && !gSavedSettings.getBOOL("NoPreload"))
+ {
+ gTextureList.decodeAllImages(10.f); // decode preloaded images
+ }
+ }
+ return true;
+}
+
+
diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
new file mode 100644
index 0000000000..ab55bfd04d
--- /dev/null
+++ b/indra/newview/llviewertexturelist.h
@@ -0,0 +1,263 @@
+/**
+ * @file llviewertexturelist.h
+ * @brief Object for managing the list of images within a region
+ *
+ * $LicenseInfo:firstyear=2000&license=viewergpl$
+ *
+ * Copyright (c) 2000-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLVIEWERTEXTURELIST_H
+#define LL_LLVIEWERTEXTURELIST_H
+
+#include "lluuid.h"
+//#include "message.h"
+#include "llgl.h"
+#include "llstat.h"
+#include "llviewertexture.h"
+#include "llui.h"
+#include <list>
+#include <set>
+
+const U32 LL_IMAGE_REZ_LOSSLESS_CUTOFF = 128;
+
+const BOOL MIPMAP_YES = TRUE;
+const BOOL MIPMAP_NO = FALSE;
+
+const BOOL GL_TEXTURE_YES = TRUE;
+const BOOL GL_TEXTURE_NO = FALSE;
+
+const BOOL IMMEDIATE_YES = TRUE;
+const BOOL IMMEDIATE_NO = FALSE;
+
+class LLImageJ2C;
+class LLMessageSystem;
+class LLTextureView;
+
+typedef void (*LLImageCallback)(BOOL success,
+ LLViewerFetchedTexture *src_vi,
+ LLImageRaw* src,
+ LLImageRaw* src_aux,
+ S32 discard_level,
+ BOOL final,
+ void* userdata);
+
+class LLViewerTextureList
+{
+ LOG_CLASS(LLViewerTextureList);
+
+ friend class LLTextureView;
+ friend class LLViewerTextureManager;
+
+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 void processImageNotInDatabase( LLMessageSystem *msg, void **user_data );
+ static S32 calcMaxTextureRAM();
+ static void receiveImageHeader(LLMessageSystem *msg, void **user_data);
+ static void receiveImagePacket(LLMessageSystem *msg, void **user_data);
+
+public:
+ LLViewerTextureList();
+ ~LLViewerTextureList();
+
+ void init();
+ void shutdown();
+ void dump();
+ void destroyGL(BOOL save_state = TRUE);
+ void restoreGL();
+
+ LLViewerFetchedTexture *findImage(const LLUUID &image_id);
+
+ void dirtyImage(LLViewerFetchedTexture *image);
+
+ // Using image stats, determine what images are necessary, and perform image updates.
+ void updateImages(F32 max_time);
+ void forceImmediateUpdate(LLViewerFetchedTexture* imagep) ;
+
+ // Decode and create textures for all images currently in list.
+ void decodeAllImages(F32 max_decode_time);
+
+ void handleIRCallback(void **data, const S32 number);
+
+ void setUpdateStats(BOOL b) { mUpdateStats = b; }
+
+ S32 getMaxResidentTexMem() const { return mMaxResidentTexMemInMegaBytes; }
+ S32 getMaxTotalTextureMem() const { return mMaxTotalTextureMemInMegaBytes;}
+ S32 getNumImages() { return mImageList.size(); }
+
+ void updateMaxResidentTexMem(S32 mem);
+
+ void doPreloadImages();
+ void doPrefetchImages();
+
+ static S32 getMinVideoRamSetting();
+ static S32 getMaxVideoRamSetting(bool get_recommended = false);
+
+private:
+ void updateImagesDecodePriorities();
+ F32 updateImagesCreateTextures(F32 max_time);
+ F32 updateImagesFetchTextures(F32 max_time);
+ void updateImagesUpdateStats();
+
+ void addImage(LLViewerFetchedTexture *image);
+ void deleteImage(LLViewerFetchedTexture *image);
+
+ void addImageToList(LLViewerFetchedTexture *image);
+ void removeImageFromList(LLViewerFetchedTexture *image);
+
+ LLViewerFetchedTexture * getImage(const LLUUID &image_id,
+ BOOL usemipmap = TRUE,
+ LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation.
+ S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
+ LLGLint internal_format = 0,
+ LLGLenum primary_format = 0,
+ LLHost request_from_host = LLHost()
+ );
+
+ LLViewerFetchedTexture * getImageFromFile(const std::string& filename,
+ BOOL usemipmap = TRUE,
+ LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation.
+ S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
+ LLGLint internal_format = 0,
+ LLGLenum primary_format = 0,
+ const LLUUID& force_id = LLUUID::null
+ );
+
+ LLViewerFetchedTexture* getImageFromUrl(const std::string& url,
+ BOOL usemipmap = TRUE,
+ LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation.
+ S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
+ LLGLint internal_format = 0,
+ LLGLenum primary_format = 0,
+ const LLUUID& force_id = LLUUID::null
+ );
+
+ LLViewerFetchedTexture* createImage(const LLUUID &image_id,
+ BOOL usemipmap = TRUE,
+ LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation.
+ S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
+ LLGLint internal_format = 0,
+ LLGLenum primary_format = 0,
+ LLHost request_from_host = LLHost()
+ );
+
+ // Request image from a specific host, used for baked avatar textures.
+ // Implemented in header in case someone changes default params above. JC
+ LLViewerFetchedTexture* getImageFromHost(const LLUUID& image_id, LLHost host)
+ { return getImage(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); }
+
+public:
+ typedef std::set<LLPointer<LLViewerFetchedTexture> > image_list_t;
+ image_list_t mLoadingStreamList;
+ image_list_t mCreateTextureList;
+ image_list_t mCallbackList;
+
+ // Note: just raw pointers because they are never referenced, just compared against
+ std::set<LLViewerFetchedTexture*> mDirtyTextureList;
+
+ BOOL mForceResetTextureStats;
+
+private:
+ typedef std::map< LLUUID, LLPointer<LLViewerFetchedTexture> > uuid_map_t;
+ uuid_map_t mUUIDMap;
+ LLUUID mLastUpdateUUID;
+ LLUUID mLastFetchUUID;
+
+ typedef std::set<LLPointer<LLViewerFetchedTexture>, LLViewerFetchedTexture::Compare> image_priority_list_t;
+ image_priority_list_t mImageList;
+
+ // simply holds on to LLViewerFetchedTexture references to stop them from being purged too soon
+ std::set<LLPointer<LLViewerFetchedTexture> > mImagePreloads;
+
+ BOOL mUpdateStats;
+ S32 mMaxResidentTexMemInMegaBytes;
+ S32 mMaxTotalTextureMemInMegaBytes;
+ LLFrameTimer mForceDecodeTimer;
+
+public:
+ static U32 sTextureBits;
+ static U32 sTexturePackets;
+
+ static LLStat sNumImagesStat;
+ static LLStat sNumRawImagesStat;
+ static LLStat sGLTexMemStat;
+ static LLStat sGLBoundMemStat;
+ static LLStat sRawMemStat;
+ static LLStat sFormattedMemStat;
+
+private:
+ static S32 sNumImages;
+ static void (*sUUIDCallback)(void**, const LLUUID &);
+};
+
+class LLUIImageList : public LLImageProviderInterface, public LLSingleton<LLUIImageList>
+{
+public:
+ // LLImageProviderInterface
+ /*virtual*/ LLUIImagePtr getUIImageByID(const LLUUID& id, S32 priority);
+ /*virtual*/ LLUIImagePtr getUIImage(const std::string& name, S32 priority);
+ void cleanUp();
+
+ bool initFromFile();
+
+ LLUIImagePtr preloadUIImage(const std::string& name, const std::string& filename, BOOL use_mips, const LLRect& scale_rect);
+
+ static void onUIImageLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata );
+private:
+ LLUIImagePtr loadUIImageByName(const std::string& name, const std::string& filename,
+ BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null,
+ LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_UI);
+ LLUIImagePtr loadUIImageByID(const LLUUID& id,
+ BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null,
+ LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_UI);
+
+ LLUIImagePtr loadUIImage(LLViewerFetchedTexture* imagep, const std::string& name, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null);
+
+
+ struct LLUIImageLoadData
+ {
+ std::string mImageName;
+ LLRect mImageScaleRegion;
+ };
+
+ typedef std::map< std::string, LLPointer<LLUIImage> > uuid_ui_image_map_t;
+ uuid_ui_image_map_t mUIImages;
+
+ //
+ //keep a copy of UI textures to prevent them to be deleted.
+ //mGLTexturep of each UI texture equals to some LLUIImage.mImage.
+ std::list< LLPointer<LLViewerFetchedTexture> > mUITextureList ;
+};
+
+const BOOL GLTEXTURE_TRUE = TRUE;
+const BOOL GLTEXTURE_FALSE = FALSE;
+const BOOL MIPMAP_TRUE = TRUE;
+const BOOL MIPMAP_FALSE = FALSE;
+
+extern LLViewerTextureList gTextureList;
+
+#endif
diff --git a/indra/newview/llviewerthrottle.cpp b/indra/newview/llviewerthrottle.cpp
index bf779c427a..73065c5c00 100644
--- a/indra/newview/llviewerthrottle.cpp
+++ b/indra/newview/llviewerthrottle.cpp
@@ -40,6 +40,8 @@
#include "llviewerstats.h"
#include "lldatapacker.h"
+using namespace LLOldEvents;
+
// consts
// The viewer is allowed to set the under-the-hood bandwidth to 50%
diff --git a/indra/newview/llviewervisualparam.cpp b/indra/newview/llviewervisualparam.cpp
index 8c7700eb65..b088ef0730 100644
--- a/indra/newview/llviewervisualparam.cpp
+++ b/indra/newview/llviewervisualparam.cpp
@@ -76,7 +76,7 @@ BOOL LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node)
static LLStdStringHandle wearable_string = LLXmlTree::addAttributeString("wearable");
if( node->getFastAttributeString( wearable_string, wearable) )
{
- mWearableType = LLWearable::typeNameToType( wearable );
+ mWearableType = LLWearableDictionary::typeNameToType( wearable );
}
static LLStdStringHandle edit_group_string = LLXmlTree::addAttributeString("edit_group");
@@ -85,6 +85,12 @@ BOOL LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node)
mEditGroup = "";
}
+ static LLStdStringHandle cross_wearable_string = LLXmlTree::addAttributeString("cross_wearable");
+ if (!node->getFastAttributeBOOL(cross_wearable_string, mCrossWearable))
+ {
+ mCrossWearable = FALSE;
+ }
+
// Optional camera offsets from the current joint center. Used for generating "hints" (thumbnails).
static LLStdStringHandle camera_distance_string = LLXmlTree::addAttributeString("camera_distance");
node->getFastAttributeF32( camera_distance_string, mCamDist );
@@ -112,6 +118,15 @@ BOOL LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node)
return TRUE;
}
+/*virtual*/ void LLViewerVisualParamInfo::toStream(std::ostream &out)
+{
+ LLVisualParamInfo::toStream(out);
+
+ out << mWearableType << "\t";
+ out << mEditGroup << "\t";
+ out << mEditGroupDisplayOrder << "\t";
+}
+
//-----------------------------------------------------------------------------
// LLViewerVisualParam()
//-----------------------------------------------------------------------------
@@ -119,12 +134,6 @@ LLViewerVisualParam::LLViewerVisualParam()
{
}
-/*
-//=============================================================================
-// These virtual functions should always be overridden,
-// but are included here for use as templates
-//=============================================================================
-
//-----------------------------------------------------------------------------
// setInfo()
//-----------------------------------------------------------------------------
@@ -140,6 +149,12 @@ BOOL LLViewerVisualParam::setInfo(LLViewerVisualParamInfo *info)
return TRUE;
}
+/*
+//=============================================================================
+// These virtual functions should always be overridden,
+// but are included here for use as templates
+//=============================================================================
+
//-----------------------------------------------------------------------------
// parseData()
//-----------------------------------------------------------------------------
diff --git a/indra/newview/llviewervisualparam.h b/indra/newview/llviewervisualparam.h
index 48d28cebf3..3550a46fbf 100644
--- a/indra/newview/llviewervisualparam.h
+++ b/indra/newview/llviewervisualparam.h
@@ -37,6 +37,8 @@
#include "llstring.h"
#include "llvisualparam.h"
+class LLWearable;
+
//-----------------------------------------------------------------------------
// LLViewerVisualParamInfo
//-----------------------------------------------------------------------------
@@ -49,8 +51,11 @@ public:
/*virtual*/ BOOL parseXml(LLXmlTreeNode* node);
+ /*virtual*/ void toStream(std::ostream &out);
+
protected:
S32 mWearableType;
+ BOOL mCrossWearable;
std::string mEditGroup;
F32 mCamDist;
F32 mCamAngle; // degrees
@@ -77,6 +82,8 @@ public:
LLViewerVisualParamInfo *getInfo() const { return (LLViewerVisualParamInfo*)mInfo; };
// This sets mInfo and calls initialization functions
BOOL setInfo(LLViewerVisualParamInfo *info);
+
+ virtual LLViewerVisualParam* cloneParam(LLWearable* wearable) const = 0;
// LLVisualParam Virtual functions
///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
@@ -90,7 +97,7 @@ public:
virtual const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **mesh) = 0;
// interface methods
- F32 getDisplayOrder() { return getInfo()->mEditGroupDisplayOrder; }
+ F32 getDisplayOrder() const { return getInfo()->mEditGroupDisplayOrder; }
S32 getWearableType() const { return getInfo()->mWearableType; }
const std::string& getEditGroup() const { return getInfo()->mEditGroup; }
@@ -102,6 +109,8 @@ public:
BOOL getShowSimple() const { return getInfo()->mShowSimple; }
F32 getSimpleMin() const { return getInfo()->mSimpleMin; }
F32 getSimpleMax() const { return getInfo()->mSimpleMax; }
+
+ BOOL getCrossWearable() const { return getInfo()->mCrossWearable; }
};
#endif // LL_LLViewerVisualParam_H
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index f2fcad8861..c1817496b1 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -32,14 +32,22 @@
#include "llviewerprecompiledheaders.h"
+#include "llviewerwindow.h"
+
+#if LL_WINDOWS
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
+#endif
+
// system library includes
#include <stdio.h>
#include <iostream>
#include <fstream>
+#include <algorithm>
+#include "llfloaterreg.h"
#include "llpanellogin.h"
#include "llviewerkeyboard.h"
-#include "llviewerwindow.h"
+#include "llviewermenu.h"
#include "llviewquery.h"
#include "llxmltree.h"
@@ -48,15 +56,15 @@
#include "llvoiceclient.h" // for push-to-talk button handling
-
//
// TODO: Many of these includes are unnecessary. Remove them.
//
// linden library includes
-#include "audioengine.h" // mute on minimize
+#include "llaudioengine.h" // mute on minimize
#include "indra_constants.h"
#include "llassetstorage.h"
+#include "llerrorcontrol.h"
#include "llfontgl.h"
#include "llmousehandler.h"
#include "llrect.h"
@@ -71,12 +79,11 @@
#include "lltimer.h"
#include "timing.h"
#include "llviewermenu.h"
+#include "lltooltip.h"
// newview includes
#include "llagent.h"
-#include "llalertdialog.h"
#include "llbox.h"
-#include "llchatbar.h"
#include "llconsole.h"
#include "llviewercontrol.h"
#include "llcylinder.h"
@@ -91,51 +98,49 @@
#include "llfeaturemanager.h"
#include "llfilepicker.h"
#include "llfloater.h"
-#include "llfloateractivespeakers.h"
#include "llfloaterbuildoptions.h"
#include "llfloaterbuyland.h"
#include "llfloatercamera.h"
-#include "llfloaterchat.h"
#include "llfloaterchatterbox.h"
#include "llfloatercustomize.h"
-#include "llfloatereditui.h" // HACK JAMESDEBUG for ui editor
#include "llfloaterland.h"
#include "llfloaterinspect.h"
+#include "llfloatermap.h"
#include "llfloaternamedesc.h"
#include "llfloaterpreference.h"
#include "llfloatersnapshot.h"
#include "llfloatertools.h"
#include "llfloaterworldmap.h"
#include "llfocusmgr.h"
-#include "llframestatview.h"
+#include "llfontfreetype.h"
#include "llgesturemgr.h"
#include "llglheaders.h"
-#include "llhoverview.h"
+#include "lltooltip.h"
#include "llhudmanager.h"
#include "llhudview.h"
#include "llimagebmp.h"
#include "llimagej2c.h"
-#include "llinventoryview.h"
+#include "llimageworker.h"
#include "llkeyboard.h"
#include "lllineeditor.h"
#include "llmenugl.h"
#include "llmodaldialog.h"
#include "llmorphview.h"
#include "llmoveview.h"
-#include "llnotify.h"
+#include "llnavigationbar.h"
#include "lloverlaybar.h"
#include "llpreviewtexture.h"
#include "llprogressview.h"
#include "llresmgr.h"
-#include "llrootview.h"
+#include "llsidetray.h"
#include "llselectmgr.h"
+#include "llrootview.h"
#include "llrendersphere.h"
#include "llstartup.h"
#include "llstatusbar.h"
#include "llstatview.h"
#include "llsurface.h"
#include "llsurfacepatch.h"
-#include "llimview.h"
#include "lltexlayer.h"
#include "lltextbox.h"
#include "lltexturecache.h"
@@ -151,18 +156,18 @@
#include "lltoolmgr.h"
#include "lltoolmorph.h"
#include "lltoolpie.h"
-#include "lltoolplacer.h"
#include "lltoolselectland.h"
-#include "lltoolview.h"
+#include "lltrans.h"
#include "lluictrlfactory.h"
-#include "lluploaddialog.h"
#include "llurldispatcher.h" // SLURL from other app instance
#include "llvieweraudio.h"
#include "llviewercamera.h"
#include "llviewergesture.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewerinventory.h"
#include "llviewerkeyboard.h"
+#include "llviewermedia.h"
+#include "llviewermediafocus.h"
#include "llviewermenu.h"
#include "llviewermessage.h"
#include "llviewerobjectlist.h"
@@ -170,22 +175,31 @@
#include "llviewerregion.h"
#include "llviewershadermgr.h"
#include "llviewerstats.h"
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "llvovolume.h"
#include "llworld.h"
#include "llworldmapview.h"
#include "pipeline.h"
#include "llappviewer.h"
-#include "llurlsimstring.h"
#include "llviewerdisplay.h"
#include "llspatialpartition.h"
#include "llviewerjoystick.h"
#include "llviewernetwork.h"
#include "llpostprocess.h"
+#include "llbottomtray.h"
+#include "llnearbychatbar.h"
+#include "llagentui.h"
+#include "llwearablelist.h"
+
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+#include "llnotificationmanager.h"
-#include "llfloatertest.h" // HACK!
#include "llfloaternotificationsconsole.h"
+#include "llnearbychat.h"
+#include "llviewerwindowlistener.h"
+
#if LL_WINDOWS
#include <tchar.h> // For Unicode conversion methods
#endif
@@ -194,29 +208,19 @@
// Globals
//
void render_ui(F32 zoom_factor = 1.f, int subfield = 0);
-LLBottomPanel* gBottomPanel = NULL;
extern BOOL gDebugClicks;
extern BOOL gDisplaySwapBuffers;
extern BOOL gDepthDirty;
extern BOOL gResizeScreenTexture;
-extern S32 gJamesInt;
LLViewerWindow *gViewerWindow = NULL;
-LLVelocityBar *gVelocityBar = NULL;
-
-BOOL gDebugSelect = FALSE;
-
-LLFrameTimer gMouseIdleTimer;
LLFrameTimer gAwayTimer;
LLFrameTimer gAwayTriggerTimer;
-LLFrameTimer gAlphaFadeTimer;
BOOL gShowOverlayTitle = FALSE;
-BOOL gPickTransparent = TRUE;
-BOOL gDebugFastUIRender = FALSE;
LLViewerObject* gDebugRaycastObject = NULL;
LLVector3 gDebugRaycastIntersection;
LLVector2 gDebugRaycastTexCoord;
@@ -227,7 +231,6 @@ S32 gDebugRaycastFaceHit;
// HUD display lines in lower right
BOOL gDisplayWindInfo = FALSE;
BOOL gDisplayCameraPos = FALSE;
-BOOL gDisplayNearestWater = FALSE;
BOOL gDisplayFOV = FALSE;
S32 CHAT_BAR_HEIGHT = 28;
@@ -247,9 +250,29 @@ std::string LLViewerWindow::sSnapshotDir;
std::string LLViewerWindow::sMovieBaseName;
-extern void toggle_debug_menus(void*);
-
+class RecordToChatConsole : public LLError::Recorder, public LLSingleton<RecordToChatConsole>
+{
+public:
+ virtual void recordMessage(LLError::ELevel level,
+ const std::string& message)
+ {
+ //FIXME: this is NOT thread safe, and will do bad things when a warning is issued from a non-UI thread
+ // only log warnings to chat console
+ //if (level == LLError::LEVEL_WARN)
+ //{
+ //LLFloaterChat* chat_floater = LLFloaterReg::findTypedInstance<LLFloaterChat>("chat");
+ //if (chat_floater && gSavedSettings.getBOOL("WarningsAsChat"))
+ //{
+ // LLChat chat;
+ // chat.mText = message;
+ // chat.mSourceType = CHAT_SOURCE_SYSTEM;
+
+ // chat_floater->addChat(chat, FALSE, FALSE);
+ //}
+ //}
+ }
+};
////////////////////////////////////////////////////////////////////////////
//
@@ -293,7 +316,7 @@ public:
mTextColor = LLColor4( 0.86f, 0.86f, 0.86f, 1.f );
// Draw stuff growing up from right lower corner of screen
- U32 xpos = mWindow->getWindowWidth() - 350;
+ U32 xpos = mWindow->getWindowWidthScaled() - 350;
U32 ypos = 64;
const U32 y_inc = 20;
@@ -309,7 +332,9 @@ public:
S32 hours = (S32)(time / (60*60));
S32 mins = (S32)((time - hours*(60*60)) / 60);
S32 secs = (S32)((time - hours*(60*60) - mins*60));
- addText(xpos, ypos, llformat(" Debug %d: %d:%02d:%02d", idx, hours,mins,secs)); ypos += y_inc2;
+ std::string label = gDebugTimerLabel[idx];
+ if (label.empty()) label = llformat("Debug: %d", idx);
+ addText(xpos, ypos, llformat(" %s: %d:%02d:%02d", label.c_str(), hours,mins,secs)); ypos += y_inc2;
}
F32 time = gFrameTimeSeconds;
@@ -513,7 +538,7 @@ public:
ypos += y_inc;
}
// only display these messages if we are actually rendering beacons at this moment
- if (LLPipeline::getRenderBeacons(NULL) && gSavedSettings.getBOOL("BeaconAlwaysOn"))
+ if (LLPipeline::getRenderBeacons(NULL) && LLFloaterReg::instanceVisible("beacons"))
{
if (LLPipeline::getRenderParticleBeacons(NULL))
{
@@ -557,7 +582,7 @@ public:
const Line& line = *iter;
LLFontGL::getFontMonospace()->renderUTF8(line.text, 0, (F32)line.x, (F32)line.y, mTextColor,
LLFontGL::LEFT, LLFontGL::TOP,
- LLFontGL::NORMAL, S32_MAX, S32_MAX, NULL, FALSE);
+ LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
}
mLineList.clear();
}
@@ -574,26 +599,10 @@ void LLViewerWindow::updateDebugText()
// LLViewerWindow
//
-bool LLViewerWindow::shouldShowToolTipFor(LLMouseHandler *mh)
-{
- if (mToolTip && mh)
- {
- LLMouseHandler::EShowToolTip showlevel = mh->getShowToolTip();
-
- return (
- showlevel == LLMouseHandler::SHOW_ALWAYS ||
- (showlevel == LLMouseHandler::SHOW_IF_NOT_BLOCKED &&
- !mToolTipBlocked)
- );
- }
- return false;
-}
-
BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down)
{
- std::string buttonname;
- std::string buttonstatestr;
- BOOL handled = FALSE;
+ const char* buttonname = "";
+ const char* buttonstatestr = "";
S32 x = pos.mX;
S32 y = pos.mY;
x = llround((F32)x / mDisplayScale.mV[VX]);
@@ -648,16 +657,7 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK
mWindow->releaseMouse();
// Indicate mouse was active
- gMouseIdleTimer.reset();
-
- // Hide tooltips on mousedown
- mToolTipBlocked = down;
-
- // Also hide hover info on mousedown/mouseup
- if (gHoverView)
- {
- gHoverView->cancelHover();
- }
+ LLUI::resetMouseIdleTimer();
// Don't let the user move the mouse out of the window until mouse up.
if( LLToolMgr::getInstance()->getCurrentTool()->clipMouseWhenDown() )
@@ -697,7 +697,10 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK
}
else
{
- handled = top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleMouseUp(local_x, local_y, mask);
+ if (top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleMouseUp(local_x, local_y, mask))
+ {
+ return TRUE;
+ }
}
}
@@ -715,38 +718,12 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK
llinfos << buttonname << " Mouse " << buttonstatestr << " not handled by view" << llendl;
}
- if (down)
+ // Do not allow tool manager to handle mouseclicks if we have disconnected
+ if(!gDisconnected && LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) )
{
- if (gDisconnected)
- {
- return FALSE;
- }
-
- if(LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) )
- {
- // This is necessary to force clicks in the world to cause edit
- // boxes that might have keyboard focus to relinquish it, and hence
- // cause a commit to update their value. JC
- gFocusMgr.setKeyboardFocus(NULL);
- return TRUE;
- }
+ return TRUE;
}
- else
- {
- if( !handled )
- {
- handled = mRootView->handleAnyMouseClick(x, y, mask, clicktype, down);
- }
- if( !handled )
- {
- LLTool *tool = LLToolMgr::getInstance()->getCurrentTool();
- if (tool)
- {
- handled = tool->handleAnyMouseClick(x, y, mask, clicktype, down);
- }
- }
- }
// If we got this far on a down-click, it wasn't handled.
// Up-clicks, though, are always handled as far as the OS is concerned.
@@ -845,13 +822,14 @@ void LLViewerWindow::handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask
// Save mouse point for access during idle() and display()
- LLCoordGL prev_saved_mouse_point = mCurrentMousePoint;
LLCoordGL mouse_point(x, y);
- saveLastMouse(mouse_point);
- BOOL mouse_actually_moved = !gFocusMgr.getMouseCapture() && // mouse is not currenty captured
- ((prev_saved_mouse_point.mX != mCurrentMousePoint.mX) || (prev_saved_mouse_point.mY != mCurrentMousePoint.mY)); // mouse moved from last recorded position
- gMouseIdleTimer.reset();
+ if (mouse_point != mCurrentMousePoint)
+ {
+ LLUI::resetMouseIdleTimer();
+ }
+
+ saveLastMouse(mouse_point);
mWindow->showCursorFromMouseMove();
@@ -859,17 +837,6 @@ void LLViewerWindow::handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask
{
gAgent.clearAFK();
}
-
- if(mouse_actually_moved)
- {
- mToolTipBlocked = FALSE;
- }
-
- // Activate the hover picker on mouse move.
- if (gHoverView)
- {
- gHoverView->setTyping(FALSE);
- }
}
void LLViewerWindow::handleMouseLeave(LLWindow *window)
@@ -877,10 +844,6 @@ void LLViewerWindow::handleMouseLeave(LLWindow *window)
// Note: we won't get this if we have captured the mouse.
llassert( gFocusMgr.getMouseCapture() == NULL );
mMouseInWindow = FALSE;
- if (mToolTip)
- {
- mToolTip->setVisible( FALSE );
- }
}
BOOL LLViewerWindow::handleCloseRequest(LLWindow *window)
@@ -912,8 +875,6 @@ void LLViewerWindow::handleFocus(LLWindow *window)
gAgent.onAppFocusGained();
LLToolMgr::getInstance()->onAppFocusGained();
- gShowTextEditCursor = TRUE;
-
// See if we're coming in with modifier keys held down
if (gKeyboard)
{
@@ -943,11 +904,6 @@ void LLViewerWindow::handleFocusLost(LLWindow *window)
showCursor();
getWindow()->setMouseClipping(FALSE);
- // JC - Leave keyboard focus, so if you're popping in and out editing
- // a script, you don't have to click in the editor again and again.
- // gFocusMgr.setKeyboardFocus( NULL );
- gShowTextEditCursor = FALSE;
-
// If losing focus while keys are down, reset them.
if (gKeyboard)
{
@@ -1034,13 +990,17 @@ BOOL LLViewerWindow::handleActivate(LLWindow *window, BOOL activated)
else
{
mActive = FALSE;
- if (gSavedSettings.getBOOL("AllowIdleAFK"))
+
+ if (gSavedSettings.getS32("AFKTimeout"))
{
gAgent.setAFK();
}
// SL-53351: Make sure we're not in mouselook when minimised, to prevent control issues
- gAgent.changeCameraToDefault();
+ if (gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK)
+ {
+ gAgent.changeCameraToDefault();
+ }
send_agent_pause();
@@ -1089,7 +1049,7 @@ BOOL LLViewerWindow::handlePaint(LLWindow *window, S32 x, S32 y, S32 width, S
FillRect(hdc, &wnd_rect, CreateSolidBrush(RGB(255, 255, 255)));
std::string name_str;
- gAgent.getName(name_str);
+ LLAgentUI::buildName(name_str);
std::string temp_str;
temp_str = llformat( "%s FPS %3.1f Phy FPS %2.1f Time Dil %1.3f", /* Flawfinder: ignore */
@@ -1138,7 +1098,7 @@ void LLViewerWindow::handleDataCopy(LLWindow *window, S32 data_type, void *data)
case SLURL_MESSAGE_TYPE:
// received URL
std::string url = (const char*)data;
- LLWebBrowserCtrl* web = NULL;
+ LLMediaCtrl* web = NULL;
const bool trusted_browser = false;
if (LLURLDispatcher::dispatch(url, web, trusted_browser))
{
@@ -1186,6 +1146,27 @@ void LLViewerWindow::handlePauseWatchdog(LLWindow *window)
LLAppViewer::instance()->pauseMainloopTimeout();
}
+//virtual
+std::string LLViewerWindow::translateString(const char* tag)
+{
+ return LLTrans::getString( std::string(tag) );
+}
+
+//virtual
+std::string LLViewerWindow::translateString(const char* tag,
+ const std::map<std::string, std::string>& args)
+{
+ // LLTrans uses a special subclass of std::string for format maps,
+ // but we must use std::map<> in these callbacks, otherwise we create
+ // a dependency between LLWindow and LLFormatMapString. So copy the data.
+ LLStringUtil::format_map_t args_copy;
+ std::map<std::string,std::string>::const_iterator it = args.begin();
+ for ( ; it != args.end(); ++it)
+ {
+ args_copy[it->first] = it->second;
+ }
+ return LLTrans::getString( std::string(tag), args_copy);
+}
//
// Classes
@@ -1196,34 +1177,35 @@ LLViewerWindow::LLViewerWindow(
S32 width, S32 height,
BOOL fullscreen, BOOL ignore_pixel_depth)
:
+ mWindow(NULL),
mActive(TRUE),
mWantFullscreen(fullscreen),
mShowFullscreenProgress(FALSE),
- mWindowRect(0, height, width, 0),
- mVirtualWindowRect(0, height, width, 0),
+ mWindowRectRaw(0, height, width, 0),
+ mWindowRectScaled(0, height, width, 0),
+ mWorldViewRectRaw(0, height, width, 0),
mLeftMouseDown(FALSE),
mMiddleMouseDown(FALSE),
mRightMouseDown(FALSE),
- mToolTip(NULL),
- mToolTipBlocked(FALSE),
mMouseInWindow( FALSE ),
mLastMask( MASK_NONE ),
mToolStored( NULL ),
- mSuppressToolbox( FALSE ),
mHideCursorPermanent( FALSE ),
mCursorHidden(FALSE),
mIgnoreActivate( FALSE ),
- mHoverPick(),
mResDirty(false),
mStatesDirty(false),
mIsFullscreenChecked(false),
- mCurrResolutionIndex(0)
+ mCurrResolutionIndex(0),
+ mViewerWindowListener(new LLViewerWindowListener(this))
{
LLNotificationChannel::buildChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"));
LLNotificationChannel::buildChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal"));
LLNotifications::instance().getChannel("VW_alerts")->connectChanged(&LLViewerWindow::onAlert);
LLNotifications::instance().getChannel("VW_alertmodal")->connectChanged(&LLViewerWindow::onAlert);
+ LLNotifications::instance().setIgnoreAllNotifications(gSavedSettings.getBOOL("IgnoreAllNotifications"));
+ llinfos << "NOTE: ALL NOTIFICATIONS THAT OCCUR WILL GET ADDED TO IGNORE LIST FOR LATER RUNS." << llendl;
// Default to application directory.
LLViewerWindow::sSnapshotBaseName = "Snapshot";
@@ -1231,7 +1213,7 @@ LLViewerWindow::LLViewerWindow(
resetSnapshotLoc();
// create window
- mWindow = LLWindowManager::createWindow(
+ mWindow = LLWindowManager::createWindow(this,
title, name, x, y, width, height, 0,
fullscreen,
gNoRender,
@@ -1270,8 +1252,8 @@ LLViewerWindow::LLViewerWindow(
{
LLCoordWindow size;
mWindow->getSize(&size);
- mWindowRect.set(0, size.mY, size.mX, 0);
- mVirtualWindowRect.set(0, llround((F32)size.mY / mDisplayScale.mV[VY]), llround((F32)size.mX / mDisplayScale.mV[VX]), 0);
+ mWindowRectRaw.set(0, size.mY, size.mX, 0);
+ mWindowRectScaled.set(0, llround((F32)size.mY / mDisplayScale.mV[VY]), llround((F32)size.mX / mDisplayScale.mV[VX]), 0);
}
LLFontManager::initClass();
@@ -1306,30 +1288,36 @@ LLViewerWindow::LLViewerWindow(
mInitAlert = "DisplaySettingsNoShaders";
LLFeatureManager::getInstance()->setGraphicsLevel(0, false);
gSavedSettings.setU32("RenderQualityPerformance", 0);
-
}
- // set callbacks
- mWindow->setCallbacks(this);
-
// Init the image list. Must happen after GL is initialized and before the images that
// LLViewerWindow needs are requested.
- gImageList.init();
- LLViewerImage::initClass();
+ LLImageGL::initClass(LLViewerTexture::MAX_GL_IMAGE_CATEGORY) ;
+ gTextureList.init();
+ LLViewerTextureManager::init() ;
gBumpImageList.init();
-
+
+ // Init font system, but don't actually load the fonts yet
+ // because our window isn't onscreen and they take several
+ // seconds to parse.
+ LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"),
+ mDisplayScale.mV[VX],
+ mDisplayScale.mV[VY],
+ gDirUtilp->getAppRODataDir(),
+ LLUI::getXUIPaths());
+
// Create container for all sub-views
- mRootView = new LLRootView("root", mVirtualWindowRect, FALSE);
-
- if (!gNoRender)
- {
- // Init default fonts
- initFonts();
- }
+ LLView::Params rvp;
+ rvp.name("root");
+ rvp.rect(mWindowRectScaled);
+ rvp.mouse_opaque(false);
+ rvp.follows.flags(FOLLOWS_NONE);
+ mRootView = LLUICtrlFactory::create<LLRootView>(rvp);
+ LLUI::setRootView(mRootView);
// Make avatar head look forward at start
- mCurrentMousePoint.mX = getWindowWidth() / 2;
- mCurrentMousePoint.mY = getWindowHeight() / 2;
+ mCurrentMousePoint.mX = getWindowWidthScaled() / 2;
+ mCurrentMousePoint.mY = getWindowHeightScaled() / 2;
gShowOverlayTitle = gSavedSettings.getBOOL("ShowOverlayTitle");
mOverlayTitle = gSavedSettings.getString("OverlayTitle");
@@ -1341,6 +1329,7 @@ LLViewerWindow::LLViewerWindow(
mDebugText = new LLDebugText(this);
+ mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale);
}
void LLViewerWindow::initGLDefaults()
@@ -1374,15 +1363,17 @@ void LLViewerWindow::initGLDefaults()
gCylinder.prerender();
}
+struct MainPanel : public LLPanel
+{
+};
+
void LLViewerWindow::initBase()
{
- S32 height = getWindowHeight();
- S32 width = getWindowWidth();
+ S32 height = getWindowHeightScaled();
+ S32 width = getWindowWidthScaled();
LLRect full_window(0, height, width, 0);
- adjustRectanglesForFirstUse(full_window);
-
////////////////////
//
// Set the gamma
@@ -1399,348 +1390,222 @@ void LLViewerWindow::initBase()
// Create the floater view at the start so that other views can add children to it.
// (But wait to add it as a child of the root view so that it will be in front of the
// other views.)
+ MainPanel* main_view = new MainPanel();
+ LLUICtrlFactory::instance().buildPanel(main_view, "main_view.xml");
+ main_view->setShape(full_window);
+ getRootView()->addChild(main_view);
- // Constrain floaters to inside the menu and status bar regions.
- LLRect floater_view_rect = full_window;
- // make space for menu bar if we have one
- floater_view_rect.mTop -= MENU_BAR_HEIGHT;
-
- // TODO: Eliminate magic constants - please used named constants if changing this
- floater_view_rect.mBottom += STATUS_BAR_HEIGHT + 12 + 16 + 2;
+ // placeholder widget that controls where "world" is rendered
+ mWorldViewPlaceholder = main_view->getChildView("world_view_rect")->getHandle();
+ mNonSideTrayView = main_view->getChildView("non_side_tray_view")->getHandle();
+ mFloaterViewHolder = main_view->getChildView("floater_view_holder")->getHandle();
- // Check for non-first startup
- S32 floater_view_bottom = gSavedSettings.getS32("FloaterViewBottom");
- if (floater_view_bottom >= 0)
+ // Constrain floaters to inside the menu and status bar regions.
+ gFloaterView = main_view->getChild<LLFloaterView>("Floater View");
+ gSnapshotFloaterView = main_view->getChild<LLSnapshotFloaterView>("Snapshot Floater View");
+
+ // Console
+ llassert( !gConsole );
+ LLConsole::Params cp;
+ cp.name("console");
+ cp.max_lines(gSavedSettings.getS32("ConsoleBufferSize"));
+ cp.rect(getChatConsoleRect());
+ cp.persist_time(gSavedSettings.getF32("ChatPersistTime"));
+ cp.font_size_index(gSavedSettings.getS32("ChatFontSize"));
+ cp.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
+ gConsole = LLUICtrlFactory::create<LLConsole>(cp);
+ getRootView()->addChild(gConsole);
+
+ // optionally forward warnings to chat console/chat floater
+ // for qa runs and dev builds
+#if !LL_RELEASE_FOR_DOWNLOAD
+ LLError::addRecorder(RecordToChatConsole::getInstance());
+#else
+ if(gSavedSettings.getBOOL("QAMode"))
{
- floater_view_rect.mBottom = floater_view_bottom;
+ LLError::addRecorder(RecordToChatConsole::getInstance());
}
- gFloaterView = new LLFloaterView("Floater View", floater_view_rect );
- gFloaterView->setVisible(TRUE);
+#endif
- gSnapshotFloaterView = new LLSnapshotFloaterView("Snapshot Floater View", full_window);
- // Snapshot floater must start invisible otherwise it eats all
- // the tooltips. JC
- gSnapshotFloaterView->setVisible(FALSE);
-
- // Console
- llassert( !gConsole );
- gConsole = new LLConsole(
- "console",
- gSavedSettings.getS32("ConsoleBufferSize"),
- getChatConsoleRect(),
- gSavedSettings.getS32("ChatFontSize"),
- gSavedSettings.getF32("ChatPersistTime") );
- gConsole->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
- mRootView->addChild(gConsole);
-
- // Debug view over the console
- gDebugView = new LLDebugView("gDebugView", full_window);
- gDebugView->setFollowsAll();
- gDebugView->setVisible(TRUE);
- mRootView->addChild(gDebugView);
-
- // Add floater view at the end so it will be on top, and give it tab priority over others
- mRootView->addChild(gFloaterView, -1);
- mRootView->addChild(gSnapshotFloaterView);
-
- // notify above floaters!
- LLRect notify_rect = full_window;
- //notify_rect.mTop -= 24;
- notify_rect.mBottom += STATUS_BAR_HEIGHT;
- gNotifyBoxView = new LLNotifyBoxView("notify_container", notify_rect, FALSE, FOLLOWS_ALL);
- mRootView->addChild(gNotifyBoxView, -2);
-
- // Tooltips go above floaters
- mToolTip = new LLTextBox( std::string("tool tip"), LLRect(0, 1, 1, 0 ) );
- mToolTip->setHPad( 4 );
- mToolTip->setVPad( 2 );
- mToolTip->setColor( gColors.getColor( "ToolTipTextColor" ) );
- mToolTip->setBorderColor( gColors.getColor( "ToolTipBorderColor" ) );
- mToolTip->setBorderVisible( FALSE );
- mToolTip->setBackgroundColor( gColors.getColor( "ToolTipBgColor" ) );
- mToolTip->setBackgroundVisible( TRUE );
- mToolTip->setFontStyle(LLFontGL::NORMAL);
- mToolTip->setBorderDropshadowVisible( TRUE );
- mToolTip->setVisible( FALSE );
+ gDebugView = getRootView()->getChild<LLDebugView>("DebugView");
+ gDebugView->init();
+ gToolTipView = getRootView()->getChild<LLToolTipView>("tooltip view");
// Add the progress bar view (startup view), which overrides everything
- mProgressView = new LLProgressView(std::string("ProgressView"), full_window);
- mRootView->addChild(mProgressView);
+ mProgressView = new LLProgressView(full_window);
+ getRootView()->addChild(mProgressView);
setShowProgress(FALSE);
setProgressCancelButtonVisible(FALSE);
-}
+ gMenuHolder = getRootView()->getChild<LLViewerMenuHolderGL>("Menu Holder");
-void adjust_rect_top_left(const std::string& control, const LLRect& window)
-{
- LLRect r = gSavedSettings.getRect(control);
- if (r.mLeft == 0 && r.mBottom == 0)
- {
- r.setLeftTopAndSize(0, window.getHeight(), r.getWidth(), r.getHeight());
- gSavedSettings.setRect(control, r);
- }
-}
-
-void adjust_rect_top_center(const std::string& control, const LLRect& window)
-{
- LLRect r = gSavedSettings.getRect(control);
- if (r.mLeft == 0 && r.mBottom == 0)
- {
- r.setLeftTopAndSize( window.getWidth()/2 - r.getWidth()/2,
- window.getHeight(),
- r.getWidth(),
- r.getHeight() );
- gSavedSettings.setRect(control, r);
- }
-}
-
-void adjust_rect_top_right(const std::string& control, const LLRect& window)
-{
- LLRect r = gSavedSettings.getRect(control);
- if (r.mLeft == 0 && r.mBottom == 0)
- {
- r.setLeftTopAndSize(window.getWidth() - r.getWidth(),
- window.getHeight(),
- r.getWidth(),
- r.getHeight());
- gSavedSettings.setRect(control, r);
- }
-}
-
-// *TODO: Adjust based on XUI XML
-const S32 TOOLBAR_HEIGHT = 64;
-
-void adjust_rect_bottom_left(const std::string& control, const LLRect& window)
-{
- LLRect r = gSavedSettings.getRect(control);
- if (r.mLeft == 0 && r.mBottom == 0)
- {
- r.setOriginAndSize(0, TOOLBAR_HEIGHT, r.getWidth(), r.getHeight());
- gSavedSettings.setRect(control, r);
- }
-}
-
-void adjust_rect_bottom_center(const std::string& control, const LLRect& window)
-{
- LLRect r = gSavedSettings.getRect(control);
- if (r.mLeft == 0 && r.mBottom == 0)
- {
- r.setOriginAndSize(
- window.getWidth()/2 - r.getWidth()/2,
- TOOLBAR_HEIGHT,
- r.getWidth(),
- r.getHeight());
- gSavedSettings.setRect(control, r);
- }
-}
+ LLMenuGL::sMenuContainer = gMenuHolder;
-void adjust_rect_centered_partial_zoom(const std::string& control,
- const LLRect& window)
-{
- LLRect rect = gSavedSettings.getRect(control);
- // Only adjust on first use
- if (rect.mLeft == 0 && rect.mBottom == 0)
- {
- S32 width = window.getWidth();
- S32 height = window.getHeight();
- rect.set(0, height-STATUS_BAR_HEIGHT, width, TOOL_BAR_HEIGHT);
- // Make floater fill 80% of window, leaving 20% padding on
- // the sides.
- const F32 ZOOM_FRACTION = 0.8f;
- S32 dx = (S32)(width * (1.f - ZOOM_FRACTION));
- S32 dy = (S32)(height * (1.f - ZOOM_FRACTION));
- rect.stretch(-dx/2, -dy/2);
- gSavedSettings.setRect(control, rect);
- }
}
-
-// Many rectangles can't be placed until we know the screen size.
-// These rectangles have their bottom-left corner as 0,0
-void LLViewerWindow::adjustRectanglesForFirstUse(const LLRect& window)
+void LLViewerWindow::initWorldUI()
{
- LLRect r;
+ S32 height = mRootView->getRect().getHeight();
+ S32 width = mRootView->getRect().getWidth();
+ LLRect full_window(0, height, width, 0);
- // *NOTE: The width and height of these floaters must be
- // identical in settings.xml and their relevant floater.xml
- // files, otherwise the window construction will get
- // confused. JC
- adjust_rect_bottom_center("FloaterMoveRect2", window);
- adjust_rect_top_center("FloaterCameraRect3", window);
+ gIMMgr = LLIMMgr::getInstance();
- adjust_rect_top_left("FloaterCustomizeAppearanceRect", window);
+ getRootView()->sendChildToFront(gFloaterView);
+ getRootView()->sendChildToFront(gSnapshotFloaterView);
- adjust_rect_top_left("FloaterLandRect5", window);
+ // new bottom panel
+ LLPanel* bottom_tray_container = getRootView()->getChild<LLPanel>("bottom_tray_container");
+ LLBottomTray* bottom_tray = LLBottomTray::getInstance();
+ bottom_tray->setShape(bottom_tray_container->getLocalRect());
+ bottom_tray->setFollowsAll();
+ bottom_tray_container->addChild(bottom_tray);
+ bottom_tray_container->setVisible(TRUE);
- adjust_rect_top_left("FloaterFindRect2", window);
+ // Pre initialize instance communicate instance;
+ // currently needs to happen before initializing chat or IM
+ LLFloaterReg::getInstance("communicate");
- adjust_rect_top_left("FloaterGestureRect2", window);
+ LLRect morph_view_rect = full_window;
+ morph_view_rect.stretch( -STATUS_BAR_HEIGHT );
+ morph_view_rect.mTop = full_window.mTop - 32;
+ LLMorphView::Params mvp;
+ mvp.name("MorphView");
+ mvp.rect(morph_view_rect);
+ mvp.visible(false);
+ gMorphView = LLUICtrlFactory::create<LLMorphView>(mvp);
+ getRootView()->addChild(gMorphView);
- adjust_rect_top_right("FloaterMiniMapRect", window);
+ LLWorldMapView::initClass();
- adjust_rect_top_right("FloaterLagMeter", window);
-
- adjust_rect_top_left("FloaterBuildOptionsRect", window);
-
- adjust_rect_bottom_left("FloaterActiveSpeakersRect", window);
-
- adjust_rect_bottom_left("FloaterBumpRect", window);
-
- adjust_rect_bottom_left("FloaterRegionInfo", window);
-
- adjust_rect_bottom_left("FloaterEnvRect", window);
-
- adjust_rect_bottom_left("FloaterAdvancedSkyRect", window);
-
- adjust_rect_bottom_left("FloaterAdvancedWaterRect", window);
-
- adjust_rect_bottom_left("FloaterDayCycleRect", window);
-
- adjust_rect_top_right("FloaterStatisticsRect", window);
-
-
- // bottom-right
- r = gSavedSettings.getRect("FloaterInventoryRect");
- if (r.mLeft == 0 && r.mBottom == 0)
+ // Force gFloaterWorldMap to initialize
+ LLFloaterReg::getInstance("world_map");
+
+ // Force gFloaterTools to initialize
+ LLFloaterReg::getInstance("build");
+ LLFloaterReg::hideInstance("build");
+
+ // Status bar
+ LLPanel* status_bar_container = getRootView()->getChild<LLPanel>("status_bar_container");
+ gStatusBar = new LLStatusBar(status_bar_container->getLocalRect());
+ gStatusBar->setFollowsAll();
+ gStatusBar->setShape(status_bar_container->getLocalRect());
+ // sync bg color with menu bar
+ gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor().get() );
+ status_bar_container->addChild(gStatusBar);
+ status_bar_container->setVisible(TRUE);
+
+ // Navigation bar
+ LLPanel* nav_bar_container = getRootView()->getChild<LLPanel>("nav_bar_container");
+
+ LLNavigationBar* navbar = LLNavigationBar::getInstance();
+ navbar->setShape(nav_bar_container->getLocalRect());
+ navbar->setBackgroundColor(gMenuBarView->getBackgroundColor().get());
+ nav_bar_container->addChild(navbar);
+ nav_bar_container->setVisible(TRUE);
+
+ if (!gSavedSettings.getBOOL("ShowNavbarNavigationPanel"))
{
- r.setOriginAndSize(
- window.getWidth() - r.getWidth(),
- 0,
- r.getWidth(),
- r.getHeight());
- gSavedSettings.setRect("FloaterInventoryRect", r);
+ navbar->showNavigationPanel(FALSE);
}
-
-// adjust_rect_top_left("FloaterHUDRect2", window);
- // slightly off center to be left of the avatar.
- r = gSavedSettings.getRect("FloaterHUDRect2");
- if (r.mLeft == 0 && r.mBottom == 0)
+ if (!gSavedSettings.getBOOL("ShowNavbarFavoritesPanel"))
{
- r.setOriginAndSize(
- window.getWidth()/4 - r.getWidth()/2,
- 2*window.getHeight()/3 - r.getHeight()/2,
- r.getWidth(),
- r.getHeight());
- gSavedSettings.setRect("FloaterHUDRect2", r);
+ navbar->showFavoritesPanel(FALSE);
}
-}
-//Rectangles need to be adjusted after the window is constructed
-//in order for proper centering to take place
-void LLViewerWindow::adjustControlRectanglesForFirstUse(const LLRect& window)
-{
- adjust_rect_bottom_center("FloaterMoveRect2", window);
- adjust_rect_top_center("FloaterCameraRect3", window);
-}
-
-void LLViewerWindow::initWorldUI()
-{
- pre_init_menus();
+ if (!gSavedSettings.getBOOL("ShowCameraButton"))
+ {
+ LLBottomTray::getInstance()->showCameraButton(FALSE);
+ }
- S32 height = mRootView->getRect().getHeight();
- S32 width = mRootView->getRect().getWidth();
- LLRect full_window(0, height, width, 0);
+ if (!gSavedSettings.getBOOL("ShowSnapshotButton"))
+ {
+ LLBottomTray::getInstance()->showSnapshotButton(FALSE);
+ }
- if ( gBottomPanel == NULL ) // Don't re-enter if objects are alreay created
+ if (!gSavedSettings.getBOOL("ShowMoveButton"))
{
- // panel containing chatbar, toolbar, and overlay, over floaters
- gBottomPanel = new LLBottomPanel(mRootView->getRect());
- mRootView->addChild(gBottomPanel);
+ LLBottomTray::getInstance()->showMoveButton(FALSE);
+ }
- // View for hover information
- gHoverView = new LLHoverView(std::string("gHoverView"), full_window);
- gHoverView->setVisible(TRUE);
- mRootView->addChild(gHoverView);
-
- gIMMgr = LLIMMgr::getInstance();
+ if (!gSavedSettings.getBOOL("ShowGestureButton"))
+ {
+ LLBottomTray::getInstance()->showGestureButton(FALSE);
+ }
- if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
+ if ( gHUDView == NULL )
+ {
+ LLRect hud_rect = full_window;
+ hud_rect.mBottom += 50;
+ if (gMenuBarView)
{
- LLFloaterChat::getInstance(LLSD())->loadHistory();
+ hud_rect.mTop -= gMenuBarView->getRect().getHeight();
}
-
- LLRect morph_view_rect = full_window;
- morph_view_rect.stretch( -STATUS_BAR_HEIGHT );
- morph_view_rect.mTop = full_window.mTop - 32;
- gMorphView = new LLMorphView(std::string("gMorphView"), morph_view_rect );
- mRootView->addChild(gMorphView);
- gMorphView->setVisible(FALSE);
-
- // *Note: this is where gFloaterMute used to be initialized.
-
- LLWorldMapView::initClass();
-
- adjust_rect_centered_partial_zoom("FloaterWorldMapRect2", full_window);
-
- gFloaterWorldMap = new LLFloaterWorldMap();
- gFloaterWorldMap->setVisible(FALSE);
-
- //
- // Tools for building
- //
-
- // Toolbox floater
- init_menus();
-
- gFloaterTools = new LLFloaterTools();
- gFloaterTools->setVisible(FALSE);
-
- // Status bar
- S32 menu_bar_height = gMenuBarView->getRect().getHeight();
- LLRect root_rect = getRootView()->getRect();
- LLRect status_rect(0, root_rect.getHeight(), root_rect.getWidth(), root_rect.getHeight() - menu_bar_height);
- gStatusBar = new LLStatusBar(std::string("status"), status_rect);
- gStatusBar->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP);
-
- gStatusBar->reshape(root_rect.getWidth(), gStatusBar->getRect().getHeight(), TRUE);
- gStatusBar->translate(0, root_rect.getHeight() - gStatusBar->getRect().getHeight());
- // sync bg color with menu bar
- gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor() );
-
- LLFloaterChatterBox::createInstance(LLSD());
-
- getRootView()->addChild(gStatusBar);
-
- // menu holder appears on top to get first pass at all mouse events
- getRootView()->sendChildToFront(gMenuHolder);
- }
+ gHUDView = new LLHUDView(hud_rect);
+ // put behind everything else in the UI
+ getRootView()->addChildInBack(gHUDView);
+ }
+
+ LLPanel* panel_ssf_container = getRootView()->getChild<LLPanel>("stand_stop_flying_container");
+ LLPanelStandStopFlying* panel_stand_stop_flying = LLPanelStandStopFlying::getInstance();
+ panel_ssf_container->addChild(panel_stand_stop_flying);
+ panel_ssf_container->setVisible(TRUE);
+
+ // put sidetray in container
+ LLPanel* side_tray_container = getRootView()->getChild<LLPanel>("side_tray_container");
+ LLSideTray* sidetrayp = LLSideTray::getInstance();
+ sidetrayp->setShape(side_tray_container->getLocalRect());
+ // don't follow right edge to avoid spurious resizes, since we are using a fixed width layout
+ sidetrayp->setFollows(FOLLOWS_LEFT|FOLLOWS_TOP|FOLLOWS_BOTTOM);
+ side_tray_container->addChild(sidetrayp);
+ side_tray_container->setVisible(FALSE);
+
+ // put sidetray buttons in their own panel
+ LLPanel* buttons_panel = sidetrayp->getButtonsPanel();
+ LLPanel* buttons_panel_container = getRootView()->getChild<LLPanel>("side_bar_tabs");
+ buttons_panel->setShape(buttons_panel_container->getLocalRect());
+ buttons_panel->setFollowsAll();
+ buttons_panel_container->addChild(buttons_panel);
}
// Destroy the UI
void LLViewerWindow::shutdownViews()
{
+ // clean up warning logger
+ LLError::removeRecorder(RecordToChatConsole::getInstance());
+
delete mDebugText;
mDebugText = NULL;
- gSavedSettings.setS32("FloaterViewBottom", gFloaterView->getRect().mBottom);
-
// Cleanup global views
if (gMorphView)
{
gMorphView->setVisible(FALSE);
}
+
+ // DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open
+ // will crump with LL_ERRS.
+ LLModalDialog::shutdownModals();
+
+ // destroy the nav bar, not currently part of gViewerWindow
+ // *TODO: Make LLNavigationBar part of gViewerWindow
+ delete LLNavigationBar::getInstance();
// Delete all child views.
delete mRootView;
mRootView = NULL;
// Automatically deleted as children of mRootView. Fix the globals.
- gFloaterTools = NULL;
gStatusBar = NULL;
gIMMgr = NULL;
- gHoverView = NULL;
+ gToolTipView = NULL;
- gFloaterView = NULL;
- gMorphView = NULL;
+ gFloaterView = NULL;
+ gMorphView = NULL;
gHUDView = NULL;
-
- gNotifyBoxView = NULL;
-
- delete mToolTip;
- mToolTip = NULL;
}
void LLViewerWindow::shutdownGL()
@@ -1755,7 +1620,9 @@ void LLViewerWindow::shutdownGL()
gSky.cleanup();
stop_glerror();
- gImageList.shutdown();
+ LLWearableList::instance().cleanup() ;
+
+ gTextureList.shutdown();
stop_glerror();
gBumpImageList.shutdown();
@@ -1767,8 +1634,11 @@ void LLViewerWindow::shutdownGL()
gPipeline.cleanup();
stop_glerror();
- LLViewerImage::cleanupClass();
-
+ LLViewerTextureManager::cleanup() ;
+ LLImageGL::cleanupClass() ;
+
+ llinfos << "All textures and llimagegl images are destroyed!" << llendl ;
+
llinfos << "Cleaning up select manager" << llendl;
LLSelectMgr::getInstance()->cleanup();
@@ -1806,12 +1676,6 @@ void LLViewerWindow::showCursor()
void LLViewerWindow::hideCursor()
{
- // Hide tooltips
- if(mToolTip ) mToolTip->setVisible( FALSE );
-
- // Also hide hover info
- if (gHoverView) gHoverView->cancelHover();
-
// And hide the cursor
mWindow->hideCursor();
@@ -1829,8 +1693,8 @@ void LLViewerWindow::sendShapeToSim()
msg->addU32Fast(_PREHASH_CircuitCode, gMessageSystem->mOurCircuitCode);
msg->nextBlockFast(_PREHASH_HeightWidthBlock);
msg->addU32Fast(_PREHASH_GenCounter, 0);
- U16 height16 = (U16) mWindowRect.getHeight();
- U16 width16 = (U16) mWindowRect.getWidth();
+ U16 height16 = (U16) mWorldViewRectRaw.getHeight();
+ U16 width16 = (U16) mWorldViewRectRaw.getWidth();
msg->addU16Fast(_PREHASH_Height, height16);
msg->addU16Fast(_PREHASH_Width, width16);
gAgent.sendReliableMessage();
@@ -1851,35 +1715,28 @@ void LLViewerWindow::reshape(S32 width, S32 height)
return;
}
- glViewport(0, 0, width, height );
+ // update our window rectangle
+ mWindowRectRaw.mRight = mWindowRectRaw.mLeft + width;
+ mWindowRectRaw.mTop = mWindowRectRaw.mBottom + height;
+
+ //glViewport(0, 0, width, height );
if (height > 0)
{
- LLViewerCamera::getInstance()->setViewHeightInPixels( height );
- if (mWindow->getFullscreen())
- {
- // force to 4:3 aspect for odd resolutions
- LLViewerCamera::getInstance()->setAspect( getDisplayAspectRatio() );
- }
- else
- {
- LLViewerCamera::getInstance()->setAspect( width / (F32) height);
- }
+ LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() );
+ LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() );
}
- // update our window rectangle
- mWindowRect.mRight = mWindowRect.mLeft + width;
- mWindowRect.mTop = mWindowRect.mBottom + height;
calcDisplayScale();
BOOL display_scale_changed = mDisplayScale != LLUI::sGLScaleFactor;
LLUI::setScaleFactor(mDisplayScale);
// update our window rectangle
- mVirtualWindowRect.mRight = mVirtualWindowRect.mLeft + llround((F32)width / mDisplayScale.mV[VX]);
- mVirtualWindowRect.mTop = mVirtualWindowRect.mBottom + llround((F32)height / mDisplayScale.mV[VY]);
+ mWindowRectScaled.mRight = mWindowRectScaled.mLeft + llround((F32)width / mDisplayScale.mV[VX]);
+ mWindowRectScaled.mTop = mWindowRectScaled.mBottom + llround((F32)height / mDisplayScale.mV[VY]);
- setupViewport();
+ setup2DViewport();
// Inform lower views of the change
// round up when converting coordinates to make sure there are no gaps at edge of window
@@ -1897,7 +1754,7 @@ void LLViewerWindow::reshape(S32 width, S32 height)
// store the mode the user wants (even if not there yet)
- gSavedSettings.setBOOL("FullScreen", mWantFullscreen);
+ gSavedSettings.setBOOL("WindowFullScreen", mWantFullscreen);
// store new settings for the mode we are in, regardless
if (!mWindow->getFullscreen())
@@ -1917,7 +1774,6 @@ void LLViewerWindow::reshape(S32 width, S32 height)
LLViewerStats::getInstance()->setStat(LLViewerStats::ST_WINDOW_WIDTH, (F64)width);
LLViewerStats::getInstance()->setStat(LLViewerStats::ST_WINDOW_HEIGHT, (F64)height);
- gResizeScreenTexture = TRUE;
}
}
@@ -1925,10 +1781,10 @@ void LLViewerWindow::reshape(S32 width, S32 height)
// Hide normal UI when a logon fails
void LLViewerWindow::setNormalControlsVisible( BOOL visible )
{
- if ( gBottomPanel )
+ if(LLBottomTray::instanceExists())
{
- gBottomPanel->setVisible( visible );
- gBottomPanel->setEnabled( visible );
+ LLBottomTray::getInstance()->setVisible(visible);
+ LLBottomTray::getInstance()->setEnabled(visible);
}
if ( gMenuBarView )
@@ -1946,6 +1802,12 @@ void LLViewerWindow::setNormalControlsVisible( BOOL visible )
gStatusBar->setVisible( visible );
gStatusBar->setEnabled( visible );
}
+
+ LLNavigationBar* navbarp = LLUI::getRootView()->findChild<LLNavigationBar>("navigation_bar");
+ if (navbarp)
+ {
+ navbarp->setVisible( visible );
+ }
}
void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid)
@@ -1955,19 +1817,19 @@ void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid)
if(god_mode && LLViewerLogin::getInstance()->isInProductionGrid())
{
- new_bg_color = gColors.getColor( "MenuBarGodBgColor" );
+ new_bg_color = LLUIColorTable::instance().getColor( "MenuBarGodBgColor" );
}
else if(god_mode && !LLViewerLogin::getInstance()->isInProductionGrid())
{
- new_bg_color = gColors.getColor( "MenuNonProductionGodBgColor" );
+ new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionGodBgColor" );
}
else if(!god_mode && !LLViewerLogin::getInstance()->isInProductionGrid())
{
- new_bg_color = gColors.getColor( "MenuNonProductionBgColor" );
+ new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" );
}
else
{
- new_bg_color = gColors.getColor( "MenuBarBgColor" );
+ new_bg_color = LLUIColorTable::instance().getColor( "MenuBarBgColor" );
}
if(gMenuBarView)
@@ -2012,6 +1874,11 @@ void LLViewerWindow::draw()
//S32 screen_x, screen_y;
+ if (!gSavedSettings.getBOOL("RenderUIBuffer"))
+ {
+ LLUI::sDirtyRect = getWindowRectScaled();
+ }
+
// HACK for timecode debugging
if (gSavedSettings.getBOOL("DisplayTimecode"))
{
@@ -2021,10 +1888,10 @@ void LLViewerWindow::draw()
glLoadIdentity();
microsecondsToTimecodeString(gFrameTime,text);
- const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF );
+ const LLFontGL* font = LLFontGL::getFontSansSerif();
font->renderUTF8(text, 0,
- llround((getWindowWidth()/2)-100.f),
- llround((getWindowHeight()-60.f)),
+ llround((getWindowWidthScaled()/2)-100.f),
+ llround((getWindowHeightScaled()-60.f)),
LLColor4( 1.f, 1.f, 1.f, 1.f ),
LLFontGL::LEFT, LLFontGL::TOP);
}
@@ -2047,8 +1914,8 @@ void LLViewerWindow::draw()
int pos_y = sub_region / llceil(zoom_factor);
int pos_x = sub_region - (pos_y*llceil(zoom_factor));
// offset for this tile
- glTranslatef((F32)getWindowWidth() * -(F32)pos_x,
- (F32)getWindowHeight() * -(F32)pos_y,
+ glTranslatef((F32)getWindowWidthScaled() * -(F32)pos_x,
+ (F32)getWindowHeightScaled() * -(F32)pos_y,
0.f);
glScalef(zoom_factor, zoom_factor, 1.f);
LLUI::sGLScaleFactor *= zoom_factor;
@@ -2067,6 +1934,11 @@ void LLViewerWindow::draw()
// No translation needed, this view is glued to 0,0
mRootView->draw();
+ if (LLView::sDebugRects)
+ {
+ gToolTipView->drawStickyRect();
+ }
+
// Draw optional on-top-of-everyone view
LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
if (top_ctrl && top_ctrl->getVisible())
@@ -2081,31 +1953,6 @@ void LLViewerWindow::draw()
LLUI::popMatrix();
}
- // Draw tooltips
- // Adjust their rectangle so they don't go off the top or bottom
- // of the screen.
- if( mToolTip && mToolTip->getVisible() )
- {
- glMatrixMode(GL_MODELVIEW);
- LLUI::pushMatrix();
- {
- S32 tip_height = mToolTip->getRect().getHeight();
-
- S32 screen_x, screen_y;
- mToolTip->localPointToScreen(0, -24 - tip_height,
- &screen_x, &screen_y);
-
- // If tooltip would draw off the bottom of the screen,
- // show it from the cursor tip position.
- if (screen_y < tip_height)
- {
- mToolTip->localPointToScreen(0, 0, &screen_x, &screen_y);
- }
- LLUI::translate( (F32) screen_x, (F32) screen_y, 0);
- mToolTip->draw();
- }
- LLUI::popMatrix();
- }
if( gShowOverlayTitle && !mOverlayTitle.empty() )
{
@@ -2113,8 +1960,8 @@ void LLViewerWindow::draw()
const S32 DIST_FROM_TOP = 20;
LLFontGL::getFontSansSerifBig()->renderUTF8(
mOverlayTitle, 0,
- llround( getWindowWidth() * 0.5f),
- getWindowHeight() - DIST_FROM_TOP,
+ llround( getWindowWidthScaled() * 0.5f),
+ getWindowHeightScaled() - DIST_FROM_TOP,
LLColor4(1, 1, 1, 0.4f),
LLFontGL::HCENTER, LLFontGL::TOP);
}
@@ -2140,30 +1987,13 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
if (key < 0x80)
{
// Not a special key, so likely (we hope) to generate a character. Let it fall through to character handler first.
- return gFocusMgr.childHasKeyboardFocus(mRootView);
- }
- }
-
- // HACK look for UI editing keys
- if (LLView::sEditingUI)
- {
- if (LLFloaterEditUI::processKeystroke(key, mask))
- {
- return TRUE;
+ return (gFocusMgr.getKeyboardFocus() != NULL);
}
}
- // Hide tooltips on keypress
- mToolTipBlocked = TRUE; // block until next time mouse is moved
-
- // Also hide hover info on keypress
- if (gHoverView)
- {
- gHoverView->cancelHover();
-
- gHoverView->setTyping(TRUE);
- }
-
+ // hide tooltips on keypress
+ LLToolTipMgr::instance().blockToolTips();
+
// Explicit hack for debug menu.
if ((MASK_ALT & mask) &&
(MASK_CONTROL & mask) &&
@@ -2193,7 +2023,8 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
&& (MASK_CONTROL & mask)
&& ('5' == key))
{
- LLFloaterNotificationConsole::showInstance();
+ //LLFloaterNotificationConsole::showInstance();
+ LLFloaterReg::showInstance("notifications_console");
return TRUE;
}
@@ -2220,39 +2051,44 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
{
return TRUE;
}
+ //some of context menus use this container, let context menu handle navigation keys
+ if(gMenuHolder && gMenuHolder->handleKey(key, mask, TRUE))
+ {
+ return TRUE;
+ }
// Traverses up the hierarchy
- LLUICtrl* keyboard_focus = gFocusMgr.getKeyboardFocus();
+ LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
if( keyboard_focus )
{
+ LLLineEditor* chat_editor = LLBottomTray::instanceExists() ? LLBottomTray::getInstance()->getNearbyChatBar()->getChatBox() : NULL;
// arrow keys move avatar while chatting hack
- if (gChatBar && gChatBar->inputEditorHasFocus())
+ if (chat_editor && chat_editor->hasFocus())
{
- if (gChatBar->getCurrentChat().empty() || gSavedSettings.getBOOL("ArrowKeysMoveAvatar"))
+ // If text field is empty, there's no point in trying to move
+ // cursor with arrow keys, so allow movement
+ if (chat_editor->getText().empty()
+ || gSavedSettings.getBOOL("ArrowKeysAlwaysMove"))
{
- switch(key)
+ // let Control-Up and Control-Down through for chat line history,
+ if (!(key == KEY_UP && mask == MASK_CONTROL)
+ && !(key == KEY_DOWN && mask == MASK_CONTROL))
{
- case KEY_LEFT:
- case KEY_RIGHT:
- case KEY_UP:
- // let CTRL UP through for chat line history
- if( MASK_CONTROL == mask )
- {
- break;
- }
- case KEY_DOWN:
- // let CTRL DOWN through for chat line history
- if( MASK_CONTROL == mask )
+ switch(key)
{
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ case KEY_UP:
+ case KEY_DOWN:
+ case KEY_PAGE_UP:
+ case KEY_PAGE_DOWN:
+ case KEY_HOME:
+ // when chatbar is empty or ArrowKeysAlwaysMove set,
+ // pass arrow keys on to avatar...
+ return FALSE;
+ default:
break;
}
- case KEY_PAGE_UP:
- case KEY_PAGE_DOWN:
- case KEY_HOME:
- // when chatbar is empty or ArrowKeysMoveAvatar set, pass arrow keys on to avatar...
- return FALSE;
- default:
- break;
}
}
}
@@ -2269,7 +2105,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
}
// Try for a new-format gesture
- if (gGestureManager.triggerGesture(key, mask))
+ if (LLGestureManager::instance().triggerGesture(key, mask))
{
return TRUE;
}
@@ -2356,7 +2192,7 @@ BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)
}
// Traverses up the hierarchy
- LLView* keyboard_focus = gFocusMgr.getKeyboardFocus();
+ LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
if( keyboard_focus )
{
if (keyboard_focus->handleUnicodeChar(uni_char, FALSE))
@@ -2382,14 +2218,8 @@ void LLViewerWindow::handleScrollWheel(S32 clicks)
{
LLView::sMouseHandlerMessage.clear();
- gMouseIdleTimer.reset();
-
- // Hide tooltips
- if( mToolTip )
- {
- mToolTip->setVisible( FALSE );
- }
-
+ LLUI::resetMouseIdleTimer();
+
LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
if( mouse_captor )
{
@@ -2427,128 +2257,226 @@ void LLViewerWindow::handleScrollWheel(S32 clicks)
}
// Zoom the camera in and out behavior
- gAgent.handleScrollWheel(clicks);
+
+ if(top_ctrl == 0 && getWorldViewRectScaled().pointInRect(mCurrentMousePoint.mX, mCurrentMousePoint.mY) )
+ gAgent.handleScrollWheel(clicks);
return;
}
void LLViewerWindow::moveCursorToCenter()
{
- S32 x = mVirtualWindowRect.getWidth() / 2;
- S32 y = mVirtualWindowRect.getHeight() / 2;
+ S32 x = getWorldViewWidthScaled() / 2;
+ S32 y = getWorldViewHeightScaled() / 2;
//on a forced move, all deltas get zeroed out to prevent jumping
mCurrentMousePoint.set(x,y);
mLastMousePoint.set(x,y);
mCurrentMouseDelta.set(0,0);
- LLUI::setCursorPositionScreen(x, y);
+ LLUI::setMousePositionScreen(x, y);
}
+
//////////////////////////////////////////////////////////////////////
//
// Hover handlers
//
+void append_xui_tooltip(LLView* viewp, LLToolTip::Params& params)
+{
+ if (viewp)
+ {
+ if (!params.styled_message().empty())
+ {
+ params.styled_message.add().text("\n---------\n");
+ }
+ LLView::root_to_view_iterator_t end_tooltip_it = viewp->endRootToView();
+ // NOTE: we skip "root" since it is assumed
+ for (LLView::root_to_view_iterator_t tooltip_it = ++viewp->beginRootToView();
+ tooltip_it != end_tooltip_it;
+ ++tooltip_it)
+ {
+ LLView* viewp = *tooltip_it;
+
+ params.styled_message.add().text(viewp->getName());
+
+ LLPanel* panelp = dynamic_cast<LLPanel*>(viewp);
+ if (panelp && !panelp->getXMLFilename().empty())
+ {
+ params.styled_message.add()
+ .text("(" + panelp->getXMLFilename() + ")")
+ .style.color(LLColor4(0.7f, 0.7f, 1.f, 1.f));
+ }
+ params.styled_message.add().text("/");
+ }
+ }
+}
+
// Update UI based on stored mouse position from mouse-move
// event processing.
-BOOL LLViewerWindow::handlePerFrameHover()
+void LLViewerWindow::updateUI()
{
static std::string last_handle_msg;
+ // animate layout stacks so we have up to date rect for world view
+ LLLayoutStack::updateClass();
+
+ updateWorldViewRect();
+
LLView::sMouseHandlerMessage.clear();
S32 x = mCurrentMousePoint.mX;
S32 y = mCurrentMousePoint.mY;
MASK mask = gKeyboard->currentMask(TRUE);
- //RN: fix for asynchronous notification of mouse leaving window not working
- LLCoordWindow mouse_pos;
- mWindow->getCursorPosition(&mouse_pos);
- if (mouse_pos.mX < 0 ||
- mouse_pos.mY < 0 ||
- mouse_pos.mX > mWindowRect.getWidth() ||
- mouse_pos.mY > mWindowRect.getHeight())
+ if (gNoRender)
{
- mMouseInWindow = FALSE;
+ return;
}
- else
+
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))
{
- mMouseInWindow = TRUE;
+ gDebugRaycastFaceHit = -1;
+ gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE,
+ &gDebugRaycastFaceHit,
+ &gDebugRaycastIntersection,
+ &gDebugRaycastTexCoord,
+ &gDebugRaycastNormal,
+ &gDebugRaycastBinormal);
}
+ updateMouseDelta();
+ updateKeyboardFocus();
- S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]);
- S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]);
+ BOOL handled = FALSE;
- LLVector2 mouse_vel;
+ BOOL handled_by_top_ctrl = FALSE;
+ LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
+ LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
+ LLView* captor_view = dynamic_cast<LLView*>(mouse_captor);
- if (gSavedSettings.getBOOL("MouseSmooth"))
- {
- static F32 fdx = 0.f;
- static F32 fdy = 0.f;
+ //FIXME: only include captor and captor's ancestors if mouse is truly over them --RN
- F32 amount = 16.f;
- fdx = fdx + ((F32) dx - fdx) * llmin(gFrameIntervalSeconds*amount,1.f);
- fdy = fdy + ((F32) dy - fdy) * llmin(gFrameIntervalSeconds*amount,1.f);
+ //build set of views containing mouse cursor by traversing UI hierarchy and testing
+ //screen rect against mouse cursor
+ view_handle_set_t mouse_hover_set;
- mCurrentMouseDelta.set(llround(fdx), llround(fdy));
- mouse_vel.setVec(fdx,fdy);
- }
- else
+ // constraint mouse enter events to children of mouse captor
+ LLView* root_view = captor_view;
+
+ // if mouse captor doesn't exist or isn't a LLView
+ // then allow mouse enter events on entire UI hierarchy
+ if (!root_view)
{
- mCurrentMouseDelta.set(dx, dy);
- mouse_vel.setVec((F32) dx, (F32) dy);
+ root_view = mRootView;
}
-
- mMouseVelocityStat.addValue(mouse_vel.magVec());
- if (gNoRender)
+ // include all ancestors of captor_view as automatically having mouse
+ if (captor_view)
{
- return TRUE;
+ LLView* captor_parent_view = captor_view->getParent();
+ while(captor_parent_view)
+ {
+ mouse_hover_set.insert(captor_parent_view->getHandle());
+ captor_parent_view = captor_parent_view->getParent();
+ }
}
- // clean up current focus
- LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus();
- if (cur_focus)
+ // aggregate visible views that contain mouse cursor in display order
+
+ // while the top_ctrl contains the mouse cursor, only it and its descendants will receive onMouseEnter events
+ if (top_ctrl && top_ctrl->calcScreenBoundingRect().pointInRect(x, y))
{
- if (!cur_focus->isInVisibleChain() || !cur_focus->isInEnabledChain())
+ // iterator over contents of top_ctrl, and throw into mouse_hover_set
+ for (LLView::tree_iterator_t it = top_ctrl->beginTreeDFS();
+ it != top_ctrl->endTreeDFS();
+ ++it)
{
- gFocusMgr.releaseFocusIfNeeded(cur_focus);
-
- LLUICtrl* parent = cur_focus->getParentUICtrl();
- const LLUICtrl* focus_root = cur_focus->findRootMostFocusRoot();
- while(parent)
+ LLView* viewp = *it;
+ if (viewp->getVisible()
+ && viewp->calcScreenBoundingRect().pointInRect(x, y))
{
- if (parent->isCtrl() &&
- (parent->hasTabStop() || parent == focus_root) &&
- !parent->getIsChrome() &&
- parent->isInVisibleChain() &&
- parent->isInEnabledChain())
+ // we have a view that contains the mouse, add it to the set
+ mouse_hover_set.insert(viewp->getHandle());
+ }
+ else
+ {
+ // skip this view and all of its children
+ it.skipDescendants();
+ }
+ }
+ }
+ else
+ {
+ // walk UI tree in depth-first order
+ for (LLView::tree_iterator_t it = root_view->beginTreeDFS();
+ it != root_view->endTreeDFS();
+ ++it)
+ {
+ LLView* viewp = *it;
+ // calculating the screen rect involves traversing the parent, so this is less than optimal
+ if (viewp->getVisible()
+ && viewp->calcScreenBoundingRect().pointInRect(x, y))
+ {
+
+ // if this view is mouse opaque, nothing behind it should be in mouse_hover_set
+ if (viewp->getMouseOpaque())
{
- if (!parent->focusFirstItem())
- {
- parent->setFocus(TRUE);
- }
- break;
+ // constrain further iteration to children of this widget
+ it = viewp->beginTreeDFS();
}
- parent = parent->getParentUICtrl();
+
+ // we have a view that contains the mouse, add it to the set
+ mouse_hover_set.insert(viewp->getHandle());
+ }
+ else
+ {
+ // skip this view and all of its children
+ it.skipDescendants();
}
}
- else if (cur_focus->isFocusRoot())
+ }
+
+ typedef std::vector<LLHandle<LLView> > view_handle_list_t;
+
+ // call onMouseEnter() on all views which contain the mouse cursor but did not before
+ view_handle_list_t mouse_enter_views;
+ std::set_difference(mouse_hover_set.begin(), mouse_hover_set.end(),
+ mMouseHoverViews.begin(), mMouseHoverViews.end(),
+ std::back_inserter(mouse_enter_views));
+ for (view_handle_list_t::iterator it = mouse_enter_views.begin();
+ it != mouse_enter_views.end();
+ ++it)
+ {
+ LLView* viewp = it->get();
+ if (viewp)
{
- // focus roots keep trying to delegate focus to their first valid descendant
- // this assumes that focus roots are not valid focus holders on their own
- cur_focus->focusFirstItem();
+ LLRect view_screen_rect = viewp->calcScreenRect();
+ viewp->onMouseEnter(x - view_screen_rect.mLeft, y - view_screen_rect.mBottom, mask);
}
}
- BOOL handled = FALSE;
+ // call onMouseLeave() on all views which no longer contain the mouse cursor
+ view_handle_list_t mouse_leave_views;
+ std::set_difference(mMouseHoverViews.begin(), mMouseHoverViews.end(),
+ mouse_hover_set.begin(), mouse_hover_set.end(),
+ std::back_inserter(mouse_leave_views));
+ for (view_handle_list_t::iterator it = mouse_leave_views.begin();
+ it != mouse_leave_views.end();
+ ++it)
+ {
+ LLView* viewp = it->get();
+ if (viewp)
+ {
+ LLRect view_screen_rect = viewp->calcScreenRect();
+ viewp->onMouseLeave(x - view_screen_rect.mLeft, y - view_screen_rect.mBottom, mask);
+ }
+ }
- BOOL handled_by_top_ctrl = FALSE;
- LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
+ // store resulting hover set for next frame
+ swap(mMouseHoverViews, mouse_hover_set);
- LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
if( mouse_captor )
{
// Pass hover events to object capturing mouse events.
@@ -2599,207 +2527,266 @@ BOOL LLViewerWindow::handlePerFrameHover()
}
}
- if( !handled )
+ if (!handled)
{
- lldebugst(LLERR_USER_INPUT) << "hover not handled by top view or root" << llendl;
- }
- }
-
- // *NOTE: sometimes tools handle the mouse as a captor, so this
- // logic is a little confusing
- LLTool *tool = NULL;
- if (gHoverView)
- {
- tool = LLToolMgr::getInstance()->getCurrentTool();
-
- if(!handled && tool)
- {
- handled = tool->handleHover(x, y, mask);
+ LLTool *tool = LLToolMgr::getInstance()->getCurrentTool();
- if (!mWindow->isCursorHidden())
+ if(mMouseInWindow && tool)
{
- gHoverView->updateHover(tool);
+ handled = tool->handleHover(x, y, mask);
}
}
- else
- {
- // Cancel hovering if any UI element handled the event.
- gHoverView->cancelHover();
- }
-
- // Suppress the toolbox view if our source tool was the pie tool,
- // and we've overridden to something else.
- mSuppressToolbox =
- (LLToolMgr::getInstance()->getBaseTool() == LLToolPie::getInstance()) &&
- (LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance());
-
}
- // Show a new tool tip (or update one that is alrady shown)
+ // Show a new tool tip (or update one that is already shown)
BOOL tool_tip_handled = FALSE;
std::string tool_tip_msg;
- F32 tooltip_delay = gSavedSettings.getF32( "ToolTipDelay" );
- //HACK: hack for tool-based tooltips which need to pop up more quickly
- //Also for show xui names as tooltips debug mode
- if ((mouse_captor && !mouse_captor->isView()) || LLUI::sShowXUINames)
- {
- tooltip_delay = gSavedSettings.getF32( "DragAndDropToolTipDelay" );
- }
- if( handled &&
- gMouseIdleTimer.getElapsedTimeF32() > tooltip_delay &&
- !mWindow->isCursorHidden() )
+ if( handled
+ && !mWindow->isCursorHidden())
{
- LLRect screen_sticky_rect;
- LLMouseHandler *mh;
+ LLRect screen_sticky_rect = mRootView->getLocalRect();
S32 local_x, local_y;
- if (mouse_captor)
- {
- mouse_captor->screenPointToLocal(x, y, &local_x, &local_y);
- mh = mouse_captor;
- }
- else if (handled_by_top_ctrl)
+
+ if (gSavedSettings.getBOOL("DebugShowXUINames"))
{
- top_ctrl->screenPointToLocal(x, y, &local_x, &local_y);
- mh = top_ctrl;
+ LLToolTip::Params params;
+
+ LLView* tooltip_view = mRootView;
+ LLView::tree_iterator_t end_it = mRootView->endTreeDFS();
+ for (LLView::tree_iterator_t it = mRootView->beginTreeDFS(); it != end_it; ++it)
+ {
+ LLView* viewp = *it;
+ LLRect screen_rect;
+ viewp->localRectToScreen(viewp->getLocalRect(), &screen_rect);
+ if (!(viewp->getVisible()
+ && screen_rect.pointInRect(x, y)))
+ {
+ it.skipDescendants();
+ }
+ // only report xui names for LLUICtrls,
+ // and blacklist the various containers we don't care about
+ else if (dynamic_cast<LLUICtrl*>(viewp)
+ && viewp != gMenuHolder
+ && viewp != gFloaterView
+ && viewp != gConsole)
+ {
+ if (dynamic_cast<LLFloater*>(viewp))
+ {
+ // constrain search to descendants of this (frontmost) floater
+ // by resetting iterator
+ it = viewp->beginTreeDFS();
+ }
+
+ // if we are in a new part of the tree (not a descendent of current tooltip_view)
+ // then push the results for tooltip_view and start with a new potential view
+ // NOTE: this emulates visiting only the leaf nodes that meet our criteria
+ if (!viewp->hasAncestor(tooltip_view))
+ {
+ append_xui_tooltip(tooltip_view, params);
+ screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect());
+ }
+ tooltip_view = viewp;
+ }
+ }
+
+ append_xui_tooltip(tooltip_view, params);
+ screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect());
+
+ params.sticky_rect = screen_sticky_rect;
+ params.max_width = 400;
+
+ LLToolTipMgr::instance().show(params);
}
- else
+ // if there is a mouse captor, nothing else gets a tooltip
+ else if (mouse_captor)
{
- local_x = x; local_y = y;
- mh = mRootView;
+ mouse_captor->screenPointToLocal(x, y, &local_x, &local_y);
+ tool_tip_handled = mouse_captor->handleToolTip(local_x, local_y, mask);
}
-
- BOOL tooltip_vis = FALSE;
- if (shouldShowToolTipFor(mh))
+ else
{
- tool_tip_handled = mh->handleToolTip(local_x, local_y, tool_tip_msg, &screen_sticky_rect );
-
- if( tool_tip_handled && !tool_tip_msg.empty() )
+ // next is top_ctrl
+ if (!tool_tip_handled && top_ctrl)
{
- mToolTipStickyRect = screen_sticky_rect;
- mToolTip->setWrappedText( tool_tip_msg, 200 );
- mToolTip->reshapeToFitText();
- mToolTip->setOrigin( x, y );
- LLRect virtual_window_rect(0, getWindowHeight(), getWindowWidth(), 0);
- mToolTip->translateIntoRect( virtual_window_rect, FALSE );
- tooltip_vis = TRUE;
+ top_ctrl->screenPointToLocal(x, y, &local_x, &local_y);
+ tool_tip_handled = top_ctrl->handleToolTip(local_x, local_y, mask );
+ }
+
+ if (!tool_tip_handled)
+ {
+ local_x = x; local_y = y;
+ tool_tip_handled = mRootView->handleToolTip(local_x, local_y, mask );
}
- }
- if (mToolTip)
- {
- mToolTip->setVisible( tooltip_vis );
+ LLTool* current_tool = LLToolMgr::getInstance()->getCurrentTool();
+ if (!tool_tip_handled && current_tool)
+ {
+ current_tool->screenPointToLocal(x, y, &local_x, &local_y);
+ tool_tip_handled = current_tool->handleToolTip(local_x, local_y, mask );
+ }
}
}
- if (tool && tool != gToolNull && tool != LLToolCompInspect::getInstance() && tool != LLToolDragAndDrop::getInstance() && !gSavedSettings.getBOOL("FreezeTime"))
+ updateLayout();
+
+ mLastMousePoint = mCurrentMousePoint;
+
+ // cleanup unused selections when no modal dialogs are open
+ if (LLModalDialog::activeCount() == 0)
+ {
+ LLViewerParcelMgr::getInstance()->deselectUnused();
+ }
+
+ if (LLModalDialog::activeCount() == 0)
+ {
+ LLSelectMgr::getInstance()->deselectUnused();
+ }
+}
+
+
+void LLViewerWindow::updateLayout()
+{
+ LLTool* tool = LLToolMgr::getInstance()->getCurrentTool();
+ if (gFloaterTools != NULL
+ && tool != NULL
+ && tool != gToolNull
+ && tool != LLToolCompInspect::getInstance()
+ && tool != LLToolDragAndDrop::getInstance()
+ && !gSavedSettings.getBOOL("FreezeTime"))
{
+ // Suppress the toolbox view if our source tool was the pie tool,
+ // and we've overridden to something else.
+ bool suppress_toolbox =
+ (LLToolMgr::getInstance()->getBaseTool() == LLToolPie::getInstance()) &&
+ (LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance());
+
LLMouseHandler *captor = gFocusMgr.getMouseCapture();
// With the null, inspect, or drag and drop tool, don't muck
// with visibility.
- if (gFloaterTools->isMinimized() ||
- (tool != LLToolPie::getInstance() // not default tool
- && tool != LLToolCompGun::getInstance() // not coming out of mouselook
- && !mSuppressToolbox // not override in third person
- && LLToolMgr::getInstance()->getCurrentToolset() != gFaceEditToolset // not special mode
- && LLToolMgr::getInstance()->getCurrentToolset() != gMouselookToolset
- && (!captor || captor->isView())) // not dragging
- )
+ if (gFloaterTools->isMinimized()
+ || (tool != LLToolPie::getInstance() // not default tool
+ && tool != LLToolCompGun::getInstance() // not coming out of mouselook
+ && !suppress_toolbox // not override in third person
+ && LLToolMgr::getInstance()->getCurrentToolset() != gFaceEditToolset // not special mode
+ && LLToolMgr::getInstance()->getCurrentToolset() != gMouselookToolset
+ && (!captor || dynamic_cast<LLView*>(captor) != NULL))) // not dragging
{
// Force floater tools to be visible (unless minimized)
if (!gFloaterTools->getVisible())
{
- gFloaterTools->open(); /* Flawfinder: ignore */
+ gFloaterTools->openFloater();
}
// Update the location of the blue box tool popup
LLCoordGL select_center_screen;
- gFloaterTools->updatePopup( select_center_screen, mask );
+ gFloaterTools->updatePopup( select_center_screen, gKeyboard->currentMask(TRUE) );
}
else
{
gFloaterTools->setVisible(FALSE);
}
- // In the future we may wish to hide the tools menu unless you
- // are building. JC
- //gMenuBarView->setItemVisible("Tools", gFloaterTools->getVisible());
- //gMenuBarView->arrange();
+ //gMenuBarView->setItemVisible("BuildTools", gFloaterTools->getVisible());
}
- if (gToolBar)
+
+ // Always update console
+ if(gConsole)
{
- gToolBar->refresh();
+ LLRect console_rect = getChatConsoleRect();
+ gConsole->reshape(console_rect.getWidth(), console_rect.getHeight());
+ gConsole->setRect(console_rect);
}
+}
- if (gChatBar)
+void LLViewerWindow::updateMouseDelta()
+{
+ S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]);
+ S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]);
+
+ //RN: fix for asynchronous notification of mouse leaving window not working
+ LLCoordWindow mouse_pos;
+ mWindow->getCursorPosition(&mouse_pos);
+ if (mouse_pos.mX < 0 ||
+ mouse_pos.mY < 0 ||
+ mouse_pos.mX > mWindowRectRaw.getWidth() ||
+ mouse_pos.mY > mWindowRectRaw.getHeight())
{
- gChatBar->refresh();
+ mMouseInWindow = FALSE;
}
-
- if (gOverlayBar)
+ else
{
- gOverlayBar->refresh();
+ mMouseInWindow = TRUE;
}
- // Update rectangles for the various toolbars
- if (gOverlayBar && gNotifyBoxView && gConsole && gToolBar)
+ LLVector2 mouse_vel;
+
+ if (gSavedSettings.getBOOL("MouseSmooth"))
{
- LLRect bar_rect(-1, STATUS_BAR_HEIGHT, getWindowWidth()+1, -1);
+ static F32 fdx = 0.f;
+ static F32 fdy = 0.f;
- LLRect notify_box_rect = gNotifyBoxView->getRect();
- notify_box_rect.mBottom = bar_rect.mBottom;
- gNotifyBoxView->reshape(notify_box_rect.getWidth(), notify_box_rect.getHeight());
- gNotifyBoxView->setRect(notify_box_rect);
+ F32 amount = 16.f;
+ fdx = fdx + ((F32) dx - fdx) * llmin(gFrameIntervalSeconds*amount,1.f);
+ fdy = fdy + ((F32) dy - fdy) * llmin(gFrameIntervalSeconds*amount,1.f);
- // make sure floaters snap to visible rect by adjusting floater view rect
- LLRect floater_rect = gFloaterView->getRect();
- if (floater_rect.mBottom != bar_rect.mBottom+1)
- {
- floater_rect.mBottom = bar_rect.mBottom+1;
- // Don't bounce the floaters up and down.
- gFloaterView->reshapeFloater(floater_rect.getWidth(), floater_rect.getHeight(),
- TRUE, ADJUST_VERTICAL_NO);
- gFloaterView->setRect(floater_rect);
- }
+ mCurrentMouseDelta.set(llround(fdx), llround(fdy));
+ mouse_vel.setVec(fdx,fdy);
+ }
+ else
+ {
+ mCurrentMouseDelta.set(dx, dy);
+ mouse_vel.setVec((F32) dx, (F32) dy);
+ }
+
+ mMouseVelocityStat.addValue(mouse_vel.magVec());
+}
- // snap floaters to top of chat bar/button strip
- LLView* chatbar_and_buttons = gOverlayBar->getChild<LLView>("chatbar_and_buttons", TRUE);
- // find top of chatbar and state buttons, if either are visible
- if (chatbar_and_buttons && !chatbar_and_buttons->getLocalBoundingRect().isNull())
- {
- // convert top/left corner of chatbar/buttons container to gFloaterView-relative coordinates
- S32 top, left;
- chatbar_and_buttons->localPointToOtherView(
- chatbar_and_buttons->getLocalBoundingRect().mLeft,
- chatbar_and_buttons->getLocalBoundingRect().mTop,
- &left,
- &top,
- gFloaterView);
- gFloaterView->setSnapOffsetBottom(top);
- }
- else if (gToolBar->getVisible())
+void LLViewerWindow::updateKeyboardFocus()
+{
+ // clean up current focus
+ LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
+ if (cur_focus)
+ {
+ if (!cur_focus->isInVisibleChain() || !cur_focus->isInEnabledChain())
{
- S32 top, left;
- gToolBar->localPointToOtherView(
- gToolBar->getLocalBoundingRect().mLeft,
- gToolBar->getLocalBoundingRect().mTop,
- &left,
- &top,
- gFloaterView);
- gFloaterView->setSnapOffsetBottom(top);
+ // don't release focus, just reassign so that if being given
+ // to a sibling won't call onFocusLost on all the ancestors
+ // gFocusMgr.releaseFocusIfNeeded(cur_focus);
+
+ LLUICtrl* parent = cur_focus->getParentUICtrl();
+ const LLUICtrl* focus_root = cur_focus->findRootMostFocusRoot();
+ while(parent)
+ {
+ if (parent->isCtrl() &&
+ (parent->hasTabStop() || parent == focus_root) &&
+ !parent->getIsChrome() &&
+ parent->isInVisibleChain() &&
+ parent->isInEnabledChain())
+ {
+ if (!parent->focusFirstItem())
+ {
+ parent->setFocus(TRUE);
+ }
+ break;
+ }
+ parent = parent->getParentUICtrl();
+ }
+
+ // if we didn't find a better place to put focus, just release it
+ // hasFocus() will return true if and only if we didn't touch focus since we
+ // are only moving focus higher in the hierarchy
+ if (cur_focus->hasFocus())
+ {
+ cur_focus->setFocus(FALSE);
+ }
}
- else
+ else if (cur_focus->isFocusRoot())
{
- gFloaterView->setSnapOffsetBottom(0);
+ // focus roots keep trying to delegate focus to their first valid descendant
+ // this assumes that focus roots are not valid focus holders on their own
+ cur_focus->focusFirstItem();
}
-
- // Always update console
- LLRect console_rect = getChatConsoleRect();
- console_rect.mBottom = gHUDView->getRect().mBottom + getChatConsoleBottomPad();
- gConsole->reshape(console_rect.getWidth(), console_rect.getHeight());
- gConsole->setRect(console_rect);
}
- mLastMousePoint = mCurrentMousePoint;
-
// last ditch force of edit menu to selection manager
if (LLEditMenuHandler::gEditMenuHandler == NULL && LLSelectMgr::getInstance()->getSelection()->getObjectCount())
{
@@ -2832,85 +2819,47 @@ BOOL LLViewerWindow::handlePerFrameHover()
gFloaterView->syncFloaterTabOrder();
}
- if (gSavedSettings.getBOOL("ChatBarStealsFocus")
- && gChatBar
- && gFocusMgr.getKeyboardFocus() == NULL
- && gChatBar->isInVisibleChain())
- {
- gChatBar->startChat(NULL);
- }
+ if(LLSideTray::instanceCreated())//just getInstance will create sidetray. we don't want this
+ LLSideTray::getInstance()->highlightFocused();
+}
- // cleanup unused selections when no modal dialogs are open
- if (LLModalDialog::activeCount() == 0)
- {
- LLViewerParcelMgr::getInstance()->deselectUnused();
- }
+static LLFastTimer::DeclareTimer FTM_UPDATE_WORLD_VIEW("Update World View");
+void LLViewerWindow::updateWorldViewRect(bool use_full_window)
+{
+ LLFastTimer ft(FTM_UPDATE_WORLD_VIEW);
- if (LLModalDialog::activeCount() == 0)
- {
- LLSelectMgr::getInstance()->deselectUnused();
- }
+ // start off using whole window to render world
+ LLRect new_world_rect = mWindowRectRaw;
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))
+ if (use_full_window == false && mWorldViewPlaceholder.get())
{
- gDebugRaycastFaceHit = -1;
- gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE,
- &gDebugRaycastFaceHit,
- &gDebugRaycastIntersection,
- &gDebugRaycastTexCoord,
- &gDebugRaycastNormal,
- &gDebugRaycastBinormal);
- }
-
-
- // per frame picking - for tooltips and changing cursor over interactive objects
- static S32 previous_x = -1;
- static S32 previous_y = -1;
- static BOOL mouse_moved_since_pick = FALSE;
+ new_world_rect = mWorldViewPlaceholder.get()->calcScreenRect();
+ // clamp to at least a 1x1 rect so we don't try to allocate zero width gl buffers
+ new_world_rect.mTop = llmax(new_world_rect.mTop, new_world_rect.mBottom + 1);
+ new_world_rect.mRight = llmax(new_world_rect.mRight, new_world_rect.mLeft + 1);
- if ((previous_x != x) || (previous_y != y))
- mouse_moved_since_pick = TRUE;
-
- BOOL do_pick = FALSE;
-
- F32 picks_moving = gSavedSettings.getF32("PicksPerSecondMouseMoving");
- if ((mouse_moved_since_pick) && (picks_moving > 0.0) && (mPickTimer.getElapsedTimeF32() > 1.0f / picks_moving))
- {
- do_pick = TRUE;
+ new_world_rect.mLeft = llround((F32)new_world_rect.mLeft * mDisplayScale.mV[VX]);
+ new_world_rect.mRight = llround((F32)new_world_rect.mRight * mDisplayScale.mV[VX]);
+ new_world_rect.mBottom = llround((F32)new_world_rect.mBottom * mDisplayScale.mV[VY]);
+ new_world_rect.mTop = llround((F32)new_world_rect.mTop * mDisplayScale.mV[VY]);
}
- F32 picks_stationary = gSavedSettings.getF32("PicksPerSecondMouseStationary");
- if ((!mouse_moved_since_pick) && (picks_stationary > 0.0) && (mPickTimer.getElapsedTimeF32() > 1.0f / picks_stationary))
+ if (mWorldViewRectRaw != new_world_rect)
{
- do_pick = TRUE;
- }
+ LLRect old_world_rect = mWorldViewRectRaw;
+ mWorldViewRectRaw = new_world_rect;
+ gResizeScreenTexture = TRUE;
+ LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() );
+ LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() );
- if (getCursorHidden())
- {
- do_pick = FALSE;
- }
+ mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale);
- if (do_pick)
- {
- mouse_moved_since_pick = FALSE;
- mPickTimer.reset();
- pickAsync(getCurrentMouseX(), getCurrentMouseY(), mask, hoverPickCallback, TRUE);
+ // sending a signal with a new WorldView rect
+ old_world_rect = calcScaledRect(old_world_rect, mDisplayScale);
+ mOnWorldViewRectUpdated(old_world_rect, mWorldViewRectScaled);
}
-
- previous_x = x;
- previous_y = y;
-
- return handled;
}
-
-/* static */
-void LLViewerWindow::hoverPickCallback(const LLPickInfo& pick_info)
-{
- gViewerWindow->mHoverPick = pick_info;
-}
-
-
void LLViewerWindow::saveLastMouse(const LLCoordGL &point)
{
// Store last mouse location.
@@ -2919,9 +2868,9 @@ void LLViewerWindow::saveLastMouse(const LLCoordGL &point)
{
mCurrentMousePoint.mX = 0;
}
- else if (point.mX > getWindowWidth())
+ else if (point.mX > getWindowWidthScaled())
{
- mCurrentMousePoint.mX = getWindowWidth();
+ mCurrentMousePoint.mX = getWindowWidthScaled();
}
else
{
@@ -2932,9 +2881,9 @@ void LLViewerWindow::saveLastMouse(const LLCoordGL &point)
{
mCurrentMousePoint.mY = 0;
}
- else if (point.mY > getWindowHeight() )
+ else if (point.mY > getWindowHeightScaled() )
{
- mCurrentMousePoint.mY = getWindowHeight();
+ mCurrentMousePoint.mY = getWindowHeightScaled();
}
else
{
@@ -3156,15 +3105,14 @@ BOOL LLViewerWindow::clickPointOnSurfaceGlobal(const S32 x, const S32 y, LLViewe
return intersect;
}
-void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& info), BOOL pick_transparent, BOOL get_surface_info)
+void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& info), BOOL pick_transparent)
{
if (gNoRender)
{
return;
}
- // push back pick info object
- BOOL in_build_mode = gFloaterTools && gFloaterTools->getVisible();
+ BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
{
// build mode allows interaction with all transparent objects
@@ -3172,27 +3120,8 @@ void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback
pick_transparent = TRUE;
}
- // center initial pick frame buffer region under mouse cursor
- // since that area is guaranteed to be onscreen and hence a valid
- // part of the framebuffer
- if (mPicks.empty())
- {
- mPickScreenRegion.setCenterAndSize(x, y_from_bot, PICK_DIAMETER, PICK_DIAMETER);
-
- if (mPickScreenRegion.mLeft < 0) mPickScreenRegion.translate(-mPickScreenRegion.mLeft, 0);
- if (mPickScreenRegion.mBottom < 0) mPickScreenRegion.translate(0, -mPickScreenRegion.mBottom);
- if (mPickScreenRegion.mRight > mWindowRect.getWidth() ) mPickScreenRegion.translate(mWindowRect.getWidth() - mPickScreenRegion.mRight, 0);
- if (mPickScreenRegion.mTop > mWindowRect.getHeight() ) mPickScreenRegion.translate(0, mWindowRect.getHeight() - mPickScreenRegion.mTop);
- }
-
- // set frame buffer region for picking results
- // stack multiple picks left to right
- LLRect screen_region = mPickScreenRegion;
- screen_region.translate(mPicks.size() * PICK_DIAMETER, 0);
-
- LLPickInfo pick(LLCoordGL(x, y_from_bot), screen_region, mask, pick_transparent, get_surface_info, callback);
-
- schedulePick(pick);
+ LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, TRUE, callback);
+ schedulePick(pick_info);
}
void LLViewerWindow::schedulePick(LLPickInfo& pick_info)
@@ -3207,81 +3136,11 @@ void LLViewerWindow::schedulePick(LLPickInfo& pick_info)
return;
}
- llassert_always(pick_info.mScreenRegion.notNull());
mPicks.push_back(pick_info);
- /*S32 scaled_x = llround((F32)pick_info.mMousePt.mX * mDisplayScale.mV[VX]);
- S32 scaled_y = llround((F32)pick_info.mMousePt.mY * mDisplayScale.mV[VY]);
-
- // Default to not hitting anything
- LLCamera pick_camera;
- pick_camera.setOrigin(LLViewerCamera::getInstance()->getOrigin());
- pick_camera.setOriginAndLookAt(LLViewerCamera::getInstance()->getOrigin(),
- LLViewerCamera::getInstance()->getUpAxis(),
- LLViewerCamera::getInstance()->getOrigin() + mouseDirectionGlobal(pick_info.mMousePt.mX, pick_info.mMousePt.mY));
- pick_camera.setView(0.5f*DEG_TO_RAD);
- pick_camera.setNear(LLViewerCamera::getInstance()->getNear());
- pick_camera.setFar(LLViewerCamera::getInstance()->getFar());
- pick_camera.setAspect(1.f);
-
- // save our drawing state
- // *TODO: should we be saving using the new method here using
- // glh_get_current_projection/glh_set_current_projection? -brad
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
-
- // clear work area
- {
- LLGLState scissor_state(GL_SCISSOR_TEST);
- scissor_state.enable();
- glScissor(pick_info.mScreenRegion.mLeft, pick_info.mScreenRegion.mBottom, pick_info.mScreenRegion.getWidth(), pick_info.mScreenRegion.getHeight());
- glClearColor(0.f, 0.f, 0.f, 0.f);
- glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- //glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- }
-
- // build perspective transform and picking viewport
- // Perform pick on a PICK_DIAMETER x PICK_DIAMETER pixel region around cursor point.
- // Don't limit the select distance for this pick.
- LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - PICK_HALF_WIDTH, scaled_y - PICK_HALF_WIDTH, PICK_DIAMETER, PICK_DIAMETER, FALSE);
-
- // render for object picking
-
- // make viewport big enough to handle antialiased frame buffers
- gGLViewport[0] = pick_info.mScreenRegion.mLeft;
- gGLViewport[1] = pick_info.mScreenRegion.mBottom;
- gGLViewport[2] = pick_info.mScreenRegion.getWidth();
- gGLViewport[3] = pick_info.mScreenRegion.getHeight();
-
- glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
- LLViewerCamera::updateFrustumPlanes(pick_camera);
- stop_glerror();
-
- // Draw the objects so the user can select them.
- // The starting ID is 1, since land is zero.
- LLRect pick_region;
- pick_region.setOriginAndSize(pick_info.mMousePt.mX - PICK_HALF_WIDTH,
- pick_info.mMousePt.mY - PICK_HALF_WIDTH, PICK_DIAMETER, PICK_DIAMETER);
- gObjectList.renderObjectsForSelect(pick_camera, pick_region, FALSE, pick_info.mPickTransparent);
-
- stop_glerror();
-
- // restore drawing state
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
-
- setup3DRender();
- setup2DRender();
- setupViewport();*/
-
// delay further event processing until we receive results of pick
+ // only do this for async picks so that handleMouseUp won't be called
+ // until the pick triggered in handleMouseDown has been processed, for example
mWindow->delayInputProcessing();
}
@@ -3329,11 +3188,17 @@ LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_trans
return LLPickInfo();
}
- pickAsync(x, y_from_bot, gKeyboard->currentMask(TRUE), NULL, pick_transparent);
- // assume that pickAsync put the results in the back of the mPicks list
- mLastPick = mPicks.back();
+ BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
+ if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
+ {
+ // build mode allows interaction with all transparent objects
+ // "Show Debug Alpha" means no object actually transparent
+ pick_transparent = TRUE;
+ }
+
+ // shortcut queueing in mPicks and just update mLastPick in place
+ mLastPick = LLPickInfo(LLCoordGL(x, y_from_bot), gKeyboard->currentMask(TRUE), pick_transparent, TRUE, NULL);
mLastPick.fetchResults();
- mPicks.pop_back();
return mLastPick;
}
@@ -3449,16 +3314,16 @@ LLVector3 LLViewerWindow::mouseDirectionGlobal(const S32 x, const S32 y) const
// find vertical field of view
F32 fov = LLViewerCamera::getInstance()->getView();
- // find screen resolution
- S32 height = getWindowHeight();
- S32 width = getWindowWidth();
+ // find world view center in scaled ui coordinates
+ F32 center_x = getWorldViewRectScaled().getCenterX();
+ F32 center_y = getWorldViewRectScaled().getCenterY();
// calculate pixel distance to screen
- F32 distance = (height / 2.f) / (tan(fov / 2.f));
+ F32 distance = ((F32)getWorldViewHeightScaled() * 0.5f) / (tan(fov / 2.f));
// calculate click point relative to middle of screen
- F32 click_x = x - width / 2.f;
- F32 click_y = y - height / 2.f;
+ F32 click_x = x - center_x;
+ F32 click_y = y - center_y;
// compute mouse vector
LLVector3 mouse_vector = distance * LLViewerCamera::getInstance()->getAtAxis()
@@ -3473,12 +3338,15 @@ LLVector3 LLViewerWindow::mouseDirectionGlobal(const S32 x, const S32 y) const
LLVector3 LLViewerWindow::mousePointHUD(const S32 x, const S32 y) const
{
// find screen resolution
- S32 height = getWindowHeight();
- S32 width = getWindowWidth();
+ S32 height = getWorldViewHeightScaled();
+
+ // find world view center
+ F32 center_x = getWorldViewRectScaled().getCenterX();
+ F32 center_y = getWorldViewRectScaled().getCenterY();
// remap with uniform scale (1/height) so that top is -0.5, bottom is +0.5
- F32 hud_x = -((F32)x - (F32)width/2.f) / height;
- F32 hud_y = ((F32)y - (F32)height/2.f) / height;
+ F32 hud_x = -((F32)x - center_x) / height;
+ F32 hud_y = ((F32)y - center_y) / height;
return LLVector3(0.f, hud_x/gAgent.mHUDCurZoom, hud_y/gAgent.mHUDCurZoom);
}
@@ -3492,12 +3360,16 @@ LLVector3 LLViewerWindow::mouseDirectionCamera(const S32 x, const S32 y) const
F32 fov_width = fov_height * LLViewerCamera::getInstance()->getAspect();
// find screen resolution
- S32 height = getWindowHeight();
- S32 width = getWindowWidth();
+ S32 height = getWorldViewHeightScaled();
+ S32 width = getWorldViewWidthScaled();
+
+ // find world view center
+ F32 center_x = getWorldViewRectScaled().getCenterX();
+ F32 center_y = getWorldViewRectScaled().getCenterY();
// calculate click point relative to middle of screen
- F32 click_x = (((F32)x / (F32)width) - 0.5f) * fov_width * -1.f;
- F32 click_y = (((F32)y / (F32)height) - 0.5f) * fov_height;
+ F32 click_x = (((F32)x - center_x) / (F32)width) * fov_width * -1.f;
+ F32 click_y = (((F32)y - center_y) / (F32)height) * fov_height;
// compute mouse vector
LLVector3 mouse_vector = LLVector3(0.f, 0.f, -1.f);
@@ -3733,8 +3605,8 @@ void LLViewerWindow::movieSize(S32 new_width, S32 new_height)
||(size.mY != new_height + BORDERHEIGHT))
{
// use actual display dimensions, not virtual UI dimensions
- S32 x = gViewerWindow->getWindowDisplayWidth();
- S32 y = gViewerWindow->getWindowDisplayHeight();
+ S32 x = gViewerWindow->getWindowWidthRaw();
+ S32 y = gViewerWindow->getWindowHeightRaw();
BORDERWIDTH = size.mX - x;
BORDERHEIGHT = size.mY- y;
LLCoordScreen new_size(new_width + BORDERWIDTH,
@@ -3832,22 +3704,21 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p
S32 w = preview_width ;
S32 h = preview_height ;
LLVector2 display_scale = mDisplayScale ;
- mDisplayScale.setVec((F32)w / mWindowRect.getWidth(), (F32)h / mWindowRect.getHeight()) ;
- LLRect window_rect = mWindowRect;
- mWindowRect.set(0, h, w, 0);
+ mDisplayScale.setVec((F32)w / mWindowRectRaw.getWidth(), (F32)h / mWindowRectRaw.getHeight()) ;
+ LLRect window_rect = mWindowRectRaw;
+ mWindowRectRaw.set(0, h, w, 0);
gDisplaySwapBuffers = FALSE;
gDepthDirty = TRUE;
glClearColor(0.f, 0.f, 0.f, 0.f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
setup3DRender();
- setupViewport();
LLFontGL::setFontDisplay(FALSE) ;
LLHUDText::setDisplayText(FALSE) ;
if (type == SNAPSHOT_TYPE_OBJECT_ID)
{
- gObjectList.renderPickList(gViewerWindow->getVirtualWindowRect(), FALSE, FALSE);
+ gObjectList.renderPickList(gViewerWindow->getWindowRectScaled(), FALSE, FALSE);
}
else
{
@@ -3900,9 +3771,8 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p
LLFontGL::setFontDisplay(TRUE) ;
LLHUDText::setDisplayText(TRUE) ;
mDisplayScale.setVec(display_scale) ;
- mWindowRect = window_rect;
+ mWindowRectRaw = window_rect;
setup3DRender();
- setupViewport();
gDisplaySwapBuffers = FALSE;
gDepthDirty = TRUE;
@@ -3946,6 +3816,9 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
// PRE SNAPSHOT
gDisplaySwapBuffers = FALSE;
+ // if not showing ui, use full window to render world view
+ updateWorldViewRect(!show_ui);
+
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
setCursor(UI_CURSOR_WAIT);
@@ -3966,12 +3839,12 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
// Copy screen to a buffer
// crop sides or top and bottom, if taking a snapshot of different aspect ratio
// from window
- S32 snapshot_width = mWindowRect.getWidth();
- S32 snapshot_height = mWindowRect.getHeight();
+ S32 snapshot_width = mWindowRectRaw.getWidth();
+ S32 snapshot_height = mWindowRectRaw.getHeight();
// SNAPSHOT
- S32 window_width = mWindowRect.getWidth();
- S32 window_height = mWindowRect.getHeight();
- LLRect window_rect = mWindowRect;
+ S32 window_width = mWindowRectRaw.getWidth();
+ S32 window_height = mWindowRectRaw.getHeight();
+ LLRect window_rect = mWindowRectRaw;
BOOL use_fbo = FALSE;
LLRenderTarget target;
@@ -3987,7 +3860,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
{
if(image_width > window_width || image_height > window_height) //need to enlarge the scene
{
- if (gGLManager.mHasFramebufferObject && !show_ui)
+ if (!LLPipeline::sRenderDeferred && gGLManager.mHasFramebufferObject && !show_ui)
{
GLint max_size = 0;
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &max_size);
@@ -4002,7 +3875,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
window_width = snapshot_width;
window_height = snapshot_height;
scale_factor = 1.f;
- mWindowRect.set(0, snapshot_height, snapshot_width, 0);
+ mWindowRectRaw.set(0, snapshot_height, snapshot_width, 0);
target.bindTarget();
}
}
@@ -4035,7 +3908,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
return FALSE ;
}
- BOOL high_res = scale_factor > 1.f;
+ BOOL high_res = scale_factor >= 2.f; // Font scaling is slow, only do so if rez is much higher
if (high_res)
{
send_agent_pause();
@@ -4070,15 +3943,22 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
LLViewerCamera::getInstance()->setZoomParameters(scale_factor, subimage_x+(subimage_y*llceil(scale_factor)));
setup3DRender();
- setupViewport();
- gObjectList.renderPickList(gViewerWindow->getVirtualWindowRect(), FALSE, FALSE);
+ gObjectList.renderPickList(gViewerWindow->getWindowRectScaled(), FALSE, FALSE);
}
else
{
const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor));
- display(do_rebuild, scale_factor, subfield, TRUE);
- // Required for showing the GUI in snapshots? See DEV-16350 for details. JC
- render_ui(scale_factor, subfield);
+
+ if (LLPipeline::sRenderDeferred)
+ {
+ display(do_rebuild, scale_factor, subfield, FALSE);
+ }
+ else
+ {
+ display(do_rebuild, scale_factor, subfield, TRUE);
+ // Required for showing the GUI in snapshots? See DEV-16350 for details. JC
+ render_ui(scale_factor, subfield);
+ }
}
S32 subimage_x_offset = llclamp(buffer_x_offset - (subimage_x * window_width), 0, window_width);
@@ -4142,7 +4022,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
if (use_fbo)
{
- mWindowRect = window_rect;
+ mWindowRectRaw = window_rect;
target.flush();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
@@ -4214,74 +4094,130 @@ void LLViewerWindow::destroyWindow()
void LLViewerWindow::drawMouselookInstructions()
{
- // Draw instructions for mouselook ("Press ESC to leave Mouselook" in a box at the top of the screen.)
- const std::string instructions = "Press ESC to leave Mouselook.";
- const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF );
-
- const S32 INSTRUCTIONS_PAD = 5;
- LLRect instructions_rect;
- instructions_rect.setLeftTopAndSize(
- INSTRUCTIONS_PAD,
- getWindowHeight() - INSTRUCTIONS_PAD,
- font->getWidth( instructions ) + 2 * INSTRUCTIONS_PAD,
- llround(font->getLineHeight() + 2 * INSTRUCTIONS_PAD));
-
- {
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.color4f( 0.9f, 0.9f, 0.9f, 1.0f );
- gl_rect_2d( instructions_rect );
- }
+ // Draw instructions for mouselook ("Press ESC to return to World View" partially transparent at the bottom of the screen.)
+ const std::string instructions = LLTrans::getString("LeaveMouselook");
+ const LLFontGL* font = LLFontGL::getFont(LLFontDescriptor("SansSerif", "Large", LLFontGL::BOLD));
+ //to be on top of Bottom bar when it is opened
+ const S32 INSTRUCTIONS_PAD = 50;
+
font->renderUTF8(
instructions, 0,
- instructions_rect.mLeft + INSTRUCTIONS_PAD,
- instructions_rect.mTop - INSTRUCTIONS_PAD,
- LLColor4( 0.0f, 0.0f, 0.0f, 1.f ),
- LLFontGL::LEFT, LLFontGL::TOP);
+ getWorldViewRectScaled().getCenterX(),
+ getWorldViewRectScaled().mBottom + INSTRUCTIONS_PAD,
+ LLColor4( 1.0f, 1.0f, 1.0f, 0.5f ),
+ LLFontGL::HCENTER, LLFontGL::TOP,
+ LLFontGL::NORMAL,LLFontGL::DROP_SHADOW);
}
+void* LLViewerWindow::getPlatformWindow() const
+{
+ return mWindow->getPlatformWindow();
+}
+
+void* LLViewerWindow::getMediaWindow() const
+{
+ return mWindow->getMediaWindow();
+}
+
+void LLViewerWindow::focusClient() const
+{
+ return mWindow->focusClient();
+}
+
+LLRootView* LLViewerWindow::getRootView() const
+{
+ return mRootView;
+}
+
+LLRect LLViewerWindow::getWorldViewRectScaled() const
+{
+ return mWorldViewRectScaled;
+}
+
+S32 LLViewerWindow::getWorldViewHeightScaled() const
+{
+ return mWorldViewRectScaled.getHeight();
+}
+
+S32 LLViewerWindow::getWorldViewWidthScaled() const
+{
+ return mWorldViewRectScaled.getWidth();
+}
+
+
+S32 LLViewerWindow::getWorldViewHeightRaw() const
+{
+ return mWorldViewRectRaw.getHeight();
+}
+
+S32 LLViewerWindow::getWorldViewWidthRaw() const
+{
+ return mWorldViewRectRaw.getWidth();
+}
-S32 LLViewerWindow::getWindowHeight() const
+S32 LLViewerWindow::getWindowHeightScaled() const
{
- return mVirtualWindowRect.getHeight();
+ return mWindowRectScaled.getHeight();
}
-S32 LLViewerWindow::getWindowWidth() const
+S32 LLViewerWindow::getWindowWidthScaled() const
{
- return mVirtualWindowRect.getWidth();
+ return mWindowRectScaled.getWidth();
}
-S32 LLViewerWindow::getWindowDisplayHeight() const
+S32 LLViewerWindow::getWindowHeightRaw() const
{
- return mWindowRect.getHeight();
+ return mWindowRectRaw.getHeight();
}
-S32 LLViewerWindow::getWindowDisplayWidth() const
+S32 LLViewerWindow::getWindowWidthRaw() const
{
- return mWindowRect.getWidth();
+ return mWindowRectRaw.getWidth();
+}
+
+void LLViewerWindow::setup2DRender()
+{
+ // setup ortho camera
+ gl_state_for_2d(mWindowRectRaw.getWidth(), mWindowRectRaw.getHeight());
+ setup2DViewport();
}
-void LLViewerWindow::setupViewport(S32 x_offset, S32 y_offset)
+void LLViewerWindow::setup2DViewport(S32 x_offset, S32 y_offset)
{
- gGLViewport[0] = x_offset;
- gGLViewport[1] = y_offset;
- gGLViewport[2] = mWindowRect.getWidth();
- gGLViewport[3] = mWindowRect.getHeight();
+ gGLViewport[0] = mWindowRectRaw.mLeft + x_offset;
+ gGLViewport[1] = mWindowRectRaw.mBottom + y_offset;
+ gGLViewport[2] = mWindowRectRaw.getWidth();
+ gGLViewport[3] = mWindowRectRaw.getHeight();
glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
}
+
void LLViewerWindow::setup3DRender()
{
- LLViewerCamera::getInstance()->setPerspective(NOT_FOR_SELECTION, 0, 0, mWindowRect.getWidth(), mWindowRect.getHeight(), FALSE, LLViewerCamera::getInstance()->getNear(), MAX_FAR_CLIP*2.f);
+ // setup perspective camera
+ LLViewerCamera::getInstance()->setPerspective(NOT_FOR_SELECTION, mWorldViewRectRaw.mLeft, mWorldViewRectRaw.mBottom, mWorldViewRectRaw.getWidth(), mWorldViewRectRaw.getHeight(), FALSE, LLViewerCamera::getInstance()->getNear(), MAX_FAR_CLIP*2.f);
+ setup3DViewport();
}
-void LLViewerWindow::setup2DRender()
+void LLViewerWindow::setup3DViewport(S32 x_offset, S32 y_offset)
{
- gl_state_for_2d(mWindowRect.getWidth(), mWindowRect.getHeight());
+ if (LLRenderTarget::getCurrentBoundTarget() != NULL)
+ {
+ // don't use translation component of mWorldViewRectRaw, as we are already in a properly sized render target
+ gGLViewport[0] = x_offset;
+ gGLViewport[1] = y_offset;
+ }
+ else
+ {
+ gGLViewport[0] = mWorldViewRectRaw.mLeft + x_offset;
+ gGLViewport[1] = mWorldViewRectRaw.mBottom + y_offset;
+ }
+ gGLViewport[2] = mWorldViewRectRaw.getWidth();
+ gGLViewport[3] = mWorldViewRectRaw.getHeight();
+ glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
}
-
-
void LLViewerWindow::setShowProgress(const BOOL show)
{
if (mProgressView)
@@ -4295,13 +4231,11 @@ BOOL LLViewerWindow::getShowProgress() const
return (mProgressView && mProgressView->getVisible());
}
-
void LLViewerWindow::moveProgressViewToFront()
{
if( mProgressView && mRootView )
{
- mRootView->removeChild( mProgressView );
- mRootView->addChild( mProgressView );
+ mRootView->sendChildToFront(mProgressView);
}
}
@@ -4356,7 +4290,7 @@ void LLViewerWindow::stopGL(BOOL save_state)
//Note: --bao
//if not necessary, do not change the order of the function calls in this function.
//if change something, make sure it will not break anything.
- //especially be careful to put anything behind gImageList.destroyGL(save_state);
+ //especially be careful to put anything behind gTextureList.destroyGL(save_state);
if (!gGLManager.mIsDisabled)
{
llinfos << "Shutting down GL..." << llendl;
@@ -4381,7 +4315,7 @@ void LLViewerWindow::stopGL(BOOL save_state)
LLVOAvatar::destroyGL();
stop_glerror();
- LLDynamicTexture::destroyGL();
+ LLViewerDynamicTexture::destroyGL();
stop_glerror();
if (gPipeline.isInit())
@@ -4399,13 +4333,13 @@ void LLViewerWindow::stopGL(BOOL save_state)
gPostProcess->invalidate();
}
- gImageList.destroyGL(save_state);
+ gTextureList.destroyGL(save_state);
stop_glerror();
-
+
gGLManager.mIsDisabled = TRUE;
stop_glerror();
- llinfos << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemory << " bytes" << llendl;
+ llinfos << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemoryInBytes << " bytes" << llendl;
}
}
@@ -4414,7 +4348,7 @@ void LLViewerWindow::restoreGL(const std::string& progress_message)
//Note: --bao
//if not necessary, do not change the order of the function calls in this function.
//if change something, make sure it will not break anything.
- //especially, be careful to put something before gImageList.restoreGL();
+ //especially, be careful to put something before gTextureList.restoreGL();
if (gGLManager.mIsDisabled)
{
llinfos << "Restoring GL..." << llendl;
@@ -4422,8 +4356,9 @@ void LLViewerWindow::restoreGL(const std::string& progress_message)
initGLDefaults();
LLGLState::restoreGL();
- gImageList.restoreGL();
-
+
+ gTextureList.restoreGL();
+
// for future support of non-square pixels, and fonts that are properly stretched
//LLFontGL::destroyDefaultFonts();
initFonts();
@@ -4434,7 +4369,7 @@ void LLViewerWindow::restoreGL(const std::string& progress_message)
LLManipTranslate::restoreGL();
gBumpImageList.restoreGL();
- LLDynamicTexture::restoreGL();
+ LLViewerDynamicTexture::restoreGL();
LLVOAvatar::restoreGL();
gResizeScreenTexture = TRUE;
@@ -4463,12 +4398,16 @@ void LLViewerWindow::restoreGL(const std::string& progress_message)
void LLViewerWindow::initFonts(F32 zoom_factor)
{
LLFontGL::destroyAllGL();
- LLFontGL::initDefaultFonts( gSavedSettings.getF32("FontScreenDPI"),
+ // Initialize with possibly different zoom factor
+ LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"),
mDisplayScale.mV[VX] * zoom_factor,
mDisplayScale.mV[VY] * zoom_factor,
gDirUtilp->getAppRODataDir(),
- LLUICtrlFactory::getXUIPaths());
+ LLUI::getXUIPaths());
+ // Force font reloads, which can be very slow
+ LLFontGL::loadDefaultFonts();
}
+
void LLViewerWindow::toggleFullscreen(BOOL show_progress)
{
if (mWindow)
@@ -4486,8 +4425,8 @@ void LLViewerWindow::getTargetWindow(BOOL& fullscreen, S32& width, S32& height)
if (mWindow
&& mWindow->getFullscreen() == mWantFullscreen)
{
- width = getWindowDisplayWidth();
- height = getWindowDisplayHeight();
+ width = getWindowWidthRaw();
+ height = getWindowHeightRaw();
}
else if (mWantFullscreen)
{
@@ -4501,6 +4440,11 @@ void LLViewerWindow::getTargetWindow(BOOL& fullscreen, S32& width, S32& height)
}
}
+void LLViewerWindow::requestResolutionUpdate()
+{
+ mResDirty = true;
+}
+
void LLViewerWindow::requestResolutionUpdate(bool fullscreen_checked)
{
mResDirty = true;
@@ -4529,12 +4473,12 @@ BOOL LLViewerWindow::checkSettings()
getWindow()->setNativeAspectRatio(gSavedSettings.getF32("FullScreenAspectRatio"));
}
- reshape(getWindowDisplayWidth(), getWindowDisplayHeight());
+ reshape(getWindowWidthRaw(), getWindowHeightRaw());
// force aspect ratio
if (mIsFullscreenChecked)
{
- LLViewerCamera::getInstance()->setAspect( getDisplayAspectRatio() );
+ LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() );
}
mResDirty = false;
@@ -4605,9 +4549,9 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size,
BOOL was_maximized = gSavedSettings.getBOOL("WindowMaximized");
mWantFullscreen = fullscreen;
mShowFullscreenProgress = show_progress_bar;
- gSavedSettings.setBOOL("FullScreen", mWantFullscreen);
+ gSavedSettings.setBOOL("WindowFullScreen", mWantFullscreen);
- gResizeScreenTexture = TRUE;
+ //gResizeScreenTexture = TRUE;
BOOL old_fullscreen = mWindow->getFullscreen();
if (!old_fullscreen && fullscreen && !LLStartUp::canGoFullscreen())
@@ -4635,12 +4579,12 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size,
}
// Close floaters that don't handle settings change
- LLFloaterSnapshot::hide(0);
+ LLFloaterReg::hideInstance("snapshot");
BOOL result_first_try = FALSE;
BOOL result_second_try = FALSE;
- LLUICtrl* keyboard_focus = gFocusMgr.getKeyboardFocus();
+ LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
send_agent_pause();
llinfos << "Stopping GL during changeDisplaySettings" << llendl;
stopGL();
@@ -4691,7 +4635,7 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size,
LLSD args;
args["RESX"] = llformat("%d",size.mX);
args["RESY"] = llformat("%d",size.mY);
- LLNotifications::instance().add("ResolutionSwitchFail", args);
+ LLNotificationsUtil::add("ResolutionSwitchFail", args);
size = old_size; // for reshape below
}
@@ -4753,9 +4697,18 @@ F32 LLViewerWindow::getDisplayAspectRatio() const
}
-void LLViewerWindow::drawPickBuffer() const
+F32 LLViewerWindow::getWorldViewAspectRatio() const
{
- mHoverPick.drawPickBuffer();
+ F32 world_aspect = (F32)mWorldViewRectRaw.getWidth() / (F32)mWorldViewRectRaw.getHeight();
+ //F32 window_aspect = (F32)mWindowRectRaw.getWidth() / (F32)mWindowRectRaw.getHeight();
+ if (mWindow->getFullscreen())
+ {
+ return world_aspect * mWindow->getPixelAspectRatio();
+ }
+ else
+ {
+ return world_aspect;
+ }
}
void LLViewerWindow::calcDisplayScale()
@@ -4763,7 +4716,7 @@ void LLViewerWindow::calcDisplayScale()
F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor");
LLVector2 display_scale;
display_scale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f));
- F32 height_normalization = gSavedSettings.getBOOL("UIAutoScale") ? ((F32)mWindowRect.getHeight() / display_scale.mV[VY]) / 768.f : 1.f;
+ F32 height_normalization = gSavedSettings.getBOOL("UIAutoScale") ? ((F32)mWindowRectRaw.getHeight() / display_scale.mV[VY]) / 768.f : 1.f;
if(mWindow->getFullscreen())
{
display_scale *= (ui_scale_factor * height_normalization);
@@ -4781,8 +4734,8 @@ void LLViewerWindow::calcDisplayScale()
if (mWindow->getFullscreen())
{
- display_scale.mV[0] = llround(display_scale.mV[0], 2.0f/(F32) mWindowRect.getWidth());
- display_scale.mV[1] = llround(display_scale.mV[1], 2.0f/(F32) mWindowRect.getHeight());
+ display_scale.mV[0] = llround(display_scale.mV[0], 2.0f/(F32) mWindowRectRaw.getWidth());
+ display_scale.mV[1] = llround(display_scale.mV[1], 2.0f/(F32) mWindowRectRaw.getHeight());
}
if (display_scale != mDisplayScale)
@@ -4795,18 +4748,31 @@ void LLViewerWindow::calcDisplayScale()
}
}
+//static
+LLRect LLViewerWindow::calcScaledRect(const LLRect & rect, const LLVector2& display_scale)
+{
+ LLRect res = rect;
+ res.mLeft = llround((F32)res.mLeft / display_scale.mV[VX]);
+ res.mRight = llround((F32)res.mRight / display_scale.mV[VX]);
+ res.mBottom = llround((F32)res.mBottom / display_scale.mV[VY]);
+ res.mTop = llround((F32)res.mTop / display_scale.mV[VY]);
+
+ return res;
+}
+
S32 LLViewerWindow::getChatConsoleBottomPad()
{
S32 offset = 0;
- if( gToolBar && gToolBar->getVisible() )
- offset += TOOL_BAR_HEIGHT;
+
+ if(LLBottomTray::instanceExists())
+ offset += LLBottomTray::getInstance()->getRect().getHeight();
return offset;
}
LLRect LLViewerWindow::getChatConsoleRect()
{
- LLRect full_window(0, getWindowHeight(), getWindowWidth(), 0);
+ LLRect full_window(0, getWindowHeightScaled(), getWindowWidthScaled(), 0);
LLRect console_rect = full_window;
const S32 CONSOLE_PADDING_TOP = 24;
@@ -4818,7 +4784,9 @@ LLRect LLViewerWindow::getChatConsoleRect()
console_rect.mLeft += CONSOLE_PADDING_LEFT;
- if (gSavedSettings.getBOOL("ChatFullWidth"))
+ static const BOOL CHAT_FULL_WIDTH = gSavedSettings.getBOOL("ChatFullWidth");
+
+ if (CHAT_FULL_WIDTH)
{
console_rect.mRight -= CONSOLE_PADDING_RIGHT;
}
@@ -4826,7 +4794,7 @@ LLRect LLViewerWindow::getChatConsoleRect()
{
// Make console rect somewhat narrow so having inventory open is
// less of a problem.
- console_rect.mRight = console_rect.mLeft + 2 * getWindowWidth() / 3;
+ console_rect.mRight = console_rect.mLeft + 2 * getWindowWidthScaled() / 3;
}
return console_rect;
@@ -4857,63 +4825,6 @@ bool LLViewerWindow::onAlert(const LLSD& notify)
}
////////////////////////////////////////////////////////////////////////////
-
-LLBottomPanel::LLBottomPanel(const LLRect &rect) :
- LLPanel(LLStringUtil::null, rect, FALSE),
- mIndicator(NULL)
-{
- // bottom panel is focus root, so Tab moves through the toolbar and button bar, and overlay
- setFocusRoot(TRUE);
- // flag this panel as chrome so buttons don't grab keyboard focus
- setIsChrome(TRUE);
-
- mFactoryMap["toolbar"] = LLCallbackMap(createToolBar, NULL);
- mFactoryMap["overlay"] = LLCallbackMap(createOverlayBar, NULL);
- mFactoryMap["hud"] = LLCallbackMap(createHUD, NULL);
- LLUICtrlFactory::getInstance()->buildPanel(this, "panel_bars.xml", &getFactoryMap());
-
- setOrigin(rect.mLeft, rect.mBottom);
- reshape(rect.getWidth(), rect.getHeight());
-}
-
-void LLBottomPanel::setFocusIndicator(LLView * indicator)
-{
- mIndicator = indicator;
-}
-
-void LLBottomPanel::draw()
-{
- if(mIndicator)
- {
- BOOL hasFocus = gFocusMgr.childHasKeyboardFocus(this);
- mIndicator->setVisible(hasFocus);
- mIndicator->setEnabled(hasFocus);
- }
- LLPanel::draw();
-}
-
-void* LLBottomPanel::createHUD(void* data)
-{
- delete gHUDView;
- gHUDView = new LLHUDView();
- return gHUDView;
-}
-
-
-void* LLBottomPanel::createOverlayBar(void* data)
-{
- delete gOverlayBar;
- gOverlayBar = new LLOverlayBar();
- return gOverlayBar;
-}
-
-void* LLBottomPanel::createToolBar(void* data)
-{
- delete gToolBar;
- gToolBar = new LLToolBar();
- return gToolBar;
-}
-
//
// LLPickInfo
//
@@ -4935,13 +4846,11 @@ LLPickInfo::LLPickInfo()
}
LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos,
- const LLRect& screen_region,
MASK keyboard_mask,
BOOL pick_transparent,
BOOL pick_uv_coords,
void (*pick_callback)(const LLPickInfo& pick_info))
: mMousePt(mouse_pos),
- mScreenRegion(screen_region),
mKeyMask(keyboard_mask),
mPickCallback(pick_callback),
mPickType(PICK_INVALID),
@@ -4957,10 +4866,6 @@ LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos,
{
}
-LLPickInfo::~LLPickInfo()
-{
-}
-
void LLPickInfo::fetchResults()
{
@@ -4979,59 +4884,14 @@ void LLPickInfo::fetchResults()
NULL, -1, mPickTransparent, &face_hit,
&intersection, &uv, &normal, &binormal);
- // read back colors and depth values from buffer
- //glReadPixels(mScreenRegion.mLeft, mScreenRegion.mBottom, mScreenRegion.getWidth(), mScreenRegion.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer);
- //glReadPixels(mScreenRegion.mLeft, mScreenRegion.mBottom, mScreenRegion.getWidth(), mScreenRegion.getHeight(), GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, mPickDepthBuffer );
-
- // find pick region that is fully onscreen
- LLCoordGL scaled_pick_point;;
- scaled_pick_point.mX = llclamp(llround((F32)mMousePt.mX * gViewerWindow->getDisplayScale().mV[VX]), PICK_HALF_WIDTH, gViewerWindow->getWindowDisplayWidth() - PICK_HALF_WIDTH);
- scaled_pick_point.mY = llclamp(llround((F32)mMousePt.mY * gViewerWindow->getDisplayScale().mV[VY]), PICK_HALF_WIDTH, gViewerWindow->getWindowDisplayHeight() - PICK_HALF_WIDTH);
- //S32 pixel_index = PICK_HALF_WIDTH * PICK_DIAMETER + PICK_HALF_WIDTH;
- //S32 pick_id = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2];
- //F32 depth = mPickDepthBuffer[pixel_index];
-
- //S32 x_offset = mMousePt.mX - llround((F32)scaled_pick_point.mX / gViewerWindow->getDisplayScale().mV[VX]);
- //S32 y_offset = mMousePt.mY - llround((F32)scaled_pick_point.mY / gViewerWindow->getDisplayScale().mV[VY]);
-
mPickPt = mMousePt;
- // we hit nothing, scan surrounding pixels for something useful
- /*if (!pick_id)
- {
- S32 closest_distance = 10000;
- //S32 closest_pick_name = 0;
- for (S32 col = 0; col < PICK_DIAMETER; col++)
- {
- for (S32 row = 0; row < PICK_DIAMETER; row++)
- {
- S32 distance_squared = (llabs(col - x_offset - PICK_HALF_WIDTH) * llabs(col - x_offset - PICK_HALF_WIDTH)) + (llabs(row - y_offset - PICK_HALF_WIDTH) * llabs(row - y_offset - PICK_HALF_WIDTH));
- pixel_index = row * PICK_DIAMETER + col;
- S32 test_name = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2];
- if (test_name && distance_squared < closest_distance)
- {
- closest_distance = distance_squared;
- pick_id = test_name;
- depth = mPickDepthBuffer[pixel_index];
- mPickPt.mX = mMousePt.mX + (col - PICK_HALF_WIDTH);
- mPickPt.mY = mMousePt.mY + (row - PICK_HALF_WIDTH);
- }
- }
- }
- }*/
-
-
U32 te_offset = face_hit > -1 ? face_hit : 0;
- //pick_id &= 0x000fffff;
//unproject relative clicked coordinate from window coordinate using GL
LLViewerObject* objectp = hit_object;
- //if (pick_id == (S32)GL_NAME_PARCEL_WALL)
- //{
- // mPickType = PICK_PARCEL_WALL;
- //}
if (hit_icon &&
(!objectp ||
icon_dist < (LLViewerCamera::getInstance()->getOrigin()-intersection).magVec()))
@@ -5075,20 +4935,6 @@ void LLPickInfo::fetchResults()
mObjectID = objectp->mID;
mObjectFace = (te_offset == NO_FACE) ? -1 : (S32)te_offset;
- /*glh::matrix4f newModel((F32*)LLViewerCamera::getInstance()->getModelview().mMatrix);
-
- for(U32 i = 0; i < 16; ++i)
- {
- modelview[i] = newModel.m[i];
- projection[i] = LLViewerCamera::getInstance()->getProjection().mMatrix[i/4][i%4];
- }
- glGetIntegerv( GL_VIEWPORT, viewport );
-
- winX = ((F32)mPickPt.mX) * gViewerWindow->getDisplayScale().mV[VX];
- winY = ((F32)mPickPt.mY) * gViewerWindow->getDisplayScale().mV[VY];
-
- gluUnProject( winX, winY, depth, modelview, projection, viewport, &posX, &posY, &posZ);*/
-
mPosGlobal = gAgent.getPosGlobalFromAgent(intersection);
if (mWantSurfaceInfo)
@@ -5114,62 +4960,15 @@ void LLPickInfo::updateXYCoords()
if (mObjectFace > -1)
{
const LLTextureEntry* tep = getObject()->getTE(mObjectFace);
- LLPointer<LLViewerImage> imagep = gImageList.getImage(tep->getID());
+ LLPointer<LLViewerTexture> imagep = LLViewerTextureManager::getFetchedTexture(tep->getID());
if(mUVCoords.mV[VX] >= 0.f && mUVCoords.mV[VY] >= 0.f && imagep.notNull())
{
- LLCoordGL coords;
-
- coords.mX = llround(mUVCoords.mV[VX] * (F32)imagep->getWidth());
- coords.mY = llround(mUVCoords.mV[VY] * (F32)imagep->getHeight());
-
- gViewerWindow->getWindow()->convertCoords(coords, &mXYCoords);
+ mXYCoords.mX = llround(mUVCoords.mV[VX] * (F32)imagep->getWidth());
+ mXYCoords.mY = llround((1.f - mUVCoords.mV[VY]) * (F32)imagep->getHeight());
}
}
}
-void LLPickInfo::drawPickBuffer() const
-{
- if (mPickBuffer)
- {
- gGL.pushMatrix();
- LLGLDisable no_blend(GL_BLEND);
- LLGLDisable no_alpha_test(GL_ALPHA_TEST);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- glPixelZoom(10.f, 10.f);
- LLVector2 display_scale = gViewerWindow->getDisplayScale();
- glRasterPos2f(((F32)mMousePt.mX * display_scale.mV[VX] + 10.f),
- ((F32)mMousePt.mY * display_scale.mV[VY] + 10.f));
- glDrawPixels(PICK_DIAMETER, PICK_DIAMETER, GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer);
- glPixelZoom(1.f, 1.f);
- gGL.color4fv(LLColor4::white.mV);
- gl_rect_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] - (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mY * display_scale.mV[VY] - (F32)(PICK_HALF_WIDTH)),
- FALSE);
- gl_line_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] - (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mX * display_scale.mV[VX] + 10.f),
- llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f + 10.f));
- gl_line_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mY * display_scale.mV[VY] - (F32)(PICK_HALF_WIDTH)),
- llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f + 10.f),
- llround((F32)mMousePt.mY * display_scale.mV[VY] + 10.f));
- gGL.translatef(10.f, 10.f, 0.f);
- gl_rect_2d(llround((F32)mPickPt.mX * display_scale.mV[VX]),
- llround((F32)mPickPt.mY * display_scale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f),
- llround((F32)mPickPt.mX * display_scale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f),
- llround((F32)mPickPt.mY * display_scale.mV[VY]),
- FALSE);
- gl_rect_2d(llround((F32)mPickPt.mX * display_scale.mV[VX]),
- llround((F32)mPickPt.mY * display_scale.mV[VY] + 10.f),
- llround((F32)mPickPt.mX * display_scale.mV[VX] + 10.f),
- llround((F32)mPickPt.mY * display_scale.mV[VY]),
- FALSE);
- gGL.popMatrix();
- }
-}
-
void LLPickInfo::getSurfaceInfo()
{
// set values to uninitialized - this is what we return if no intersection is found
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 509a7c4884..b488276a18 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -44,12 +44,18 @@
#include "v3dmath.h"
#include "v2math.h"
-#include "llwindow.h"
+#include "llwindowcallbacks.h"
#include "lltimer.h"
#include "llstat.h"
-#include "llalertdialog.h"
-#include "llnotifications.h"
#include "llmousehandler.h"
+#include "llcursortypes.h"
+#include "llhandle.h"
+#include "llimage.h"
+
+#include <boost/function.hpp>
+#include <boost/signals2.hpp>
+#include <boost/scoped_ptr.hpp>
+
class LLView;
class LLViewerObject;
@@ -57,9 +63,12 @@ class LLUUID;
class LLProgressView;
class LLTool;
class LLVelocityBar;
-class LLTextBox;
+class LLPanel;
class LLImageRaw;
class LLHUDIcon;
+class LLWindow;
+class LLRootView;
+class LLViewerWindowListener;
#define PICK_HALF_WIDTH 5
#define PICK_DIAMETER (2 * PICK_HALF_WIDTH + 1)
@@ -67,32 +76,31 @@ class LLHUDIcon;
class LLPickInfo
{
public:
+ typedef enum
+ {
+ PICK_OBJECT,
+ PICK_FLORA,
+ PICK_LAND,
+ PICK_ICON,
+ PICK_PARCEL_WALL,
+ PICK_INVALID
+ } EPickType;
+
+public:
LLPickInfo();
LLPickInfo(const LLCoordGL& mouse_pos,
- const LLRect& screen_region,
MASK keyboard_mask,
BOOL pick_transparent,
BOOL pick_surface_info,
void (*pick_callback)(const LLPickInfo& pick_info));
- ~LLPickInfo();
void fetchResults();
LLPointer<LLViewerObject> getObject() const;
LLUUID getObjectID() const { return mObjectID; }
- void drawPickBuffer() const;
+ bool isValid() const { return mPickType != PICK_INVALID; }
static bool isFlora(LLViewerObject* object);
- typedef enum
- {
- PICK_OBJECT,
- PICK_FLORA,
- PICK_LAND,
- PICK_ICON,
- PICK_PARCEL_WALL,
- PICK_INVALID
- } EPickType;
-
public:
LLCoordGL mMousePt;
MASK mKeyMask;
@@ -112,7 +120,6 @@ public:
LLVector3 mNormal;
LLVector3 mBinormal;
BOOL mPickTransparent;
- LLRect mScreenRegion;
void getSurfaceInfo();
private:
@@ -145,6 +152,8 @@ public:
void adjustControlRectanglesForFirstUse(const LLRect& window);
void initWorldUI();
+ BOOL handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down);
+
//
// LLWindowCallback interface implementation
//
@@ -152,7 +161,6 @@ public:
/*virtual*/ BOOL handleTranslatedKeyUp(KEY key, MASK mask);
/*virtual*/ void handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level);
/*virtual*/ BOOL handleUnicodeChar(llwchar uni_char, MASK mask); // NOT going to handle extended
- /*virtual*/ BOOL handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down);
/*virtual*/ BOOL handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
/*virtual*/ BOOL handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
/*virtual*/ BOOL handleCloseRequest(LLWindow *window);
@@ -181,28 +189,50 @@ public:
/*virtual*/ void handlePingWatchdog(LLWindow *window, const char * msg);
/*virtual*/ void handlePauseWatchdog(LLWindow *window);
/*virtual*/ void handleResumeWatchdog(LLWindow *window);
-
+ /*virtual*/ std::string translateString(const char* tag);
+ /*virtual*/ std::string translateString(const char* tag,
+ const std::map<std::string, std::string>& args);
+
+ // signal on bottom tray width changed
+ typedef boost::function<void (void)> bottom_tray_callback_t;
+ typedef boost::signals2::signal<void (void)> bottom_tray_signal_t;
+ bottom_tray_signal_t mOnBottomTrayWidthChanged;
+ boost::signals2::connection setOnBottomTrayWidthChanged(bottom_tray_callback_t cb) { return mOnBottomTrayWidthChanged.connect(cb); }
+ // signal on update of WorldView rect
+ typedef boost::function<void (LLRect old_world_rect, LLRect new_world_rect)> world_rect_callback_t;
+ typedef boost::signals2::signal<void (LLRect old_world_rect, LLRect new_world_rect)> world_rect_signal_t;
+ world_rect_signal_t mOnWorldViewRectUpdated;
+ boost::signals2::connection setOnWorldViewRectUpdated(world_rect_callback_t cb) { return mOnWorldViewRectUpdated.connect(cb); }
//
// ACCESSORS
//
- LLView* getRootView() const { return mRootView; }
+ LLRootView* getRootView() const;
- // Window in raw pixels as seen on screen.
- const LLRect& getWindowRect() const { return mWindowRect; };
- S32 getWindowDisplayHeight() const;
- S32 getWindowDisplayWidth() const;
+ // 3D world area in scaled pixels (via UI scale), use for most UI computations
+ LLRect getWorldViewRectScaled() const;
+ S32 getWorldViewHeightScaled() const;
+ S32 getWorldViewWidthScaled() const;
- // Window in scaled pixels (via UI scale), use this for
- // UI elements checking size.
- const LLRect& getVirtualWindowRect() const { return mVirtualWindowRect; };
- S32 getWindowHeight() const;
- S32 getWindowWidth() const;
+ // 3D world area, in raw unscaled pixels
+ LLRect getWorldViewRectRaw() const { return mWorldViewRectRaw; }
+ S32 getWorldViewHeightRaw() const;
+ S32 getWorldViewWidthRaw() const;
+
+ // Window in scaled pixels (via UI scale), use for most UI computations
+ LLRect getWindowRectScaled() const { return mWindowRectScaled; }
+ S32 getWindowHeightScaled() const;
+ S32 getWindowWidthScaled() const;
+
+ // Window in raw pixels as seen on screen.
+ LLRect getWindowRectRaw() const { return mWindowRectRaw; }
+ S32 getWindowHeightRaw() const;
+ S32 getWindowWidthRaw() const;
LLWindow* getWindow() const { return mWindow; }
- void* getPlatformWindow() const { return mWindow->getPlatformWindow(); }
- void* getMediaWindow() const { return mWindow->getMediaWindow(); }
- void focusClient() const { return mWindow->focusClient(); };
+ void* getPlatformWindow() const;
+ void* getMediaWindow() const;
+ void focusClient() const;
LLCoordGL getLastMouse() const { return mLastMousePoint; }
S32 getLastMouseX() const { return mLastMousePoint.mX; }
@@ -219,9 +249,9 @@ public:
BOOL getRightMouseDown() const { return mRightMouseDown; }
const LLPickInfo& getLastPick() const { return mLastPick; }
- const LLPickInfo& getHoverPick() const { return mHoverPick; }
- void setupViewport(S32 x_offset = 0, S32 y_offset = 0);
+ void setup2DViewport(S32 x_offset = 0, S32 y_offset = 0);
+ void setup3DViewport(S32 x_offset = 0, S32 y_offset = 0);
void setup3DRender();
void setup2DRender();
@@ -261,8 +291,14 @@ public:
void updateObjectUnderCursor();
- BOOL handlePerFrameHover(); // Once per frame, update UI based on mouse position
+ void updateUI(); // Once per frame, update UI based on mouse position, calls following update* functions
+ void updateLayout();
+ void updateMouseDelta();
+ void updateKeyboardFocus();
+ void updateWorldViewRect(bool use_full_window=false);
+ LLView* getNonSideTrayView() { return mNonSideTrayView.get(); }
+ LLView* getFloaterViewHolder() { return mFloaterViewHolder.get(); }
BOOL handleKey(KEY key, MASK mask);
void handleScrollWheel (S32 clicks);
@@ -291,7 +327,7 @@ public:
} ESnapshotType;
BOOL saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR);
BOOL rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect = TRUE, BOOL is_texture = FALSE,
- BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_IMAGE_SIZE );
+ BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE );
BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) ;
BOOL isSnapshotLocSet() const { return ! sSnapshotDir.empty(); }
void resetSnapshotLoc() const { sSnapshotDir.clear(); }
@@ -308,12 +344,8 @@ public:
void performPick();
void returnEmptyPicks();
-
- void pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& pick_info),
- BOOL pick_transparent = FALSE, BOOL get_surface_info = FALSE);
+ void pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& pick_info), BOOL pick_transparent = FALSE);
LLPickInfo pickImmediate(S32 x, S32 y, BOOL pick_transparent);
- static void hoverPickCallback(const LLPickInfo& pick_info);
-
LLHUDIcon* cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth,
LLVector3* intersection);
@@ -349,20 +381,21 @@ public:
// handle shutting down GL and bringing it back up
void requestResolutionUpdate(bool fullscreen_checked);
+ void requestResolutionUpdate(); // doesn't affect fullscreen
BOOL checkSettings();
void restartDisplay(BOOL show_progress_bar);
BOOL changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, BOOL disable_vsync, BOOL show_progress_bar);
BOOL getIgnoreDestroyWindow() { return mIgnoreActivate; }
F32 getDisplayAspectRatio() const;
+ F32 getWorldViewAspectRatio() const;
const LLVector2& getDisplayScale() const { return mDisplayScale; }
void calcDisplayScale();
-
- void drawPickBuffer() const;
+ static LLRect calcScaledRect(const LLRect & rect, const LLVector2& display_scale);
private:
bool shouldShowToolTipFor(LLMouseHandler *mh);
static bool onAlert(const LLSD& notify);
-
+
void switchToolByMask(MASK mask);
void destroyWindow();
void drawMouselookInstructions();
@@ -380,9 +413,12 @@ protected:
BOOL mActive;
BOOL mWantFullscreen;
BOOL mShowFullscreenProgress;
- LLRect mWindowRect;
- LLRect mVirtualWindowRect;
- LLView* mRootView; // a view of size mWindowRect, containing all child views
+
+ LLRect mWindowRectRaw; // whole window, including UI
+ LLRect mWindowRectScaled; // whole window, scaled by UI size
+ LLRect mWorldViewRectRaw; // area of screen for 3D world
+ LLRect mWorldViewRectScaled; // area of screen for 3D world scaled by UI size
+ LLRootView* mRootView; // a view of size mWindowRectRaw, containing all child views
LLVector2 mDisplayScale;
LLCoordGL mCurrentMousePoint; // last mouse position in GL coords
@@ -395,22 +431,22 @@ protected:
LLProgressView *mProgressView;
- LLTextBox* mToolTip;
- BOOL mToolTipBlocked; // True after a key press or a mouse button event. False once the mouse moves again.
+ LLFrameTimer mToolTipFadeTimer;
+ LLPanel* mToolTip;
+ std::string mLastToolTipMessage;
LLRect mToolTipStickyRect; // Once a tool tip is shown, it will stay visible until the mouse leaves this rect.
BOOL mMouseInWindow; // True if the mouse is over our window or if we have captured the mouse.
BOOL mFocusCycleMode;
+ typedef std::set<LLHandle<LLView> > view_handle_set_t;
+ view_handle_set_t mMouseHoverViews;
// Variables used for tool override switching based on modifier keys. JC
MASK mLastMask; // used to detect changes in modifier mask
LLTool* mToolStored; // the tool we're overriding
- BOOL mSuppressToolbox; // sometimes hide the toolbox, despite
- // having a camera tool selected
BOOL mHideCursorPermanent; // true during drags, mouselook
BOOL mCursorHidden;
LLPickInfo mLastPick;
- LLPickInfo mHoverPick;
std::vector<LLPickInfo> mPicks;
LLRect mPickScreenRegion; // area of frame buffer for rendering pick frames (generally follows mouse to avoid going offscreen)
LLTimer mPickTimer; // timer for scheduling n picks per second
@@ -420,6 +456,10 @@ protected:
BOOL mIgnoreActivate;
std::string mInitAlert; // Window / GL initialization requires an alert
+
+ LLHandle<LLView> mWorldViewPlaceholder; // widget that spans the portion of screen dedicated to rendering the 3d world
+ LLHandle<LLView> mNonSideTrayView; // parent of world view + bottom bar, etc...everything but the side tray
+ LLHandle<LLView> mFloaterViewHolder; // container for floater_view
class LLDebugText* mDebugText; // Internal class for debug text
@@ -428,6 +468,8 @@ protected:
bool mIsFullscreenChecked; // Did the user check the fullscreen checkbox in the display settings
U32 mCurrResolutionIndex;
+ boost::scoped_ptr<LLViewerWindowListener> mViewerWindowListener;
+
protected:
static std::string sSnapshotBaseName;
static std::string sSnapshotDir;
@@ -435,45 +477,21 @@ protected:
static std::string sMovieBaseName;
};
-class LLBottomPanel : public LLPanel
-{
-public:
- LLBottomPanel(const LLRect& rect);
- void setFocusIndicator(LLView * indicator);
- LLView * getFocusIndicator() { return mIndicator; }
- /*virtual*/ void draw();
-
- static void* createHUD(void* data);
- static void* createOverlayBar(void* data);
- static void* createToolBar(void* data);
-
-protected:
- LLView * mIndicator;
-};
-extern LLBottomPanel * gBottomPanel;
-
void toggle_flying(void*);
void toggle_first_person();
void toggle_build(void*);
void reset_viewer_state_on_sim(void);
void update_saved_window_size(const std::string& control,S32 delta_width, S32 delta_height);
-
-
//
// Globals
//
-extern LLVelocityBar* gVelocityBar;
extern LLViewerWindow* gViewerWindow;
-extern LLFrameTimer gMouseIdleTimer; // how long has it been since the mouse last moved?
extern LLFrameTimer gAwayTimer; // tracks time before setting the avatar away state to true
extern LLFrameTimer gAwayTriggerTimer; // how long the avatar has been away
-extern BOOL gDebugSelect;
-
-extern BOOL gDebugFastUIRender;
extern LLViewerObject* gDebugRaycastObject;
extern LLVector3 gDebugRaycastIntersection;
extern LLVector2 gDebugRaycastTexCoord;
@@ -485,7 +503,6 @@ extern S32 CHAT_BAR_HEIGHT;
extern BOOL gDisplayCameraPos;
extern BOOL gDisplayWindInfo;
-extern BOOL gDisplayNearestWater;
extern BOOL gDisplayFOV;
#endif
diff --git a/indra/newview/llviewerwindowlistener.cpp b/indra/newview/llviewerwindowlistener.cpp
new file mode 100644
index 0000000000..de57788271
--- /dev/null
+++ b/indra/newview/llviewerwindowlistener.cpp
@@ -0,0 +1,95 @@
+/**
+ * @file llviewerwindowlistener.cpp
+ * @author Nat Goodspeed
+ * @date 2009-06-30
+ * @brief Implementation for llviewerwindowlistener.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "llviewerprecompiledheaders.h"
+// associated header
+#include "llviewerwindowlistener.h"
+// STL headers
+#include <map>
+// std headers
+// external library headers
+// other Linden headers
+#include "llviewerwindow.h"
+
+LLViewerWindowListener::LLViewerWindowListener(LLViewerWindow* llviewerwindow):
+ LLEventAPI("LLViewerWindow",
+ "LLViewerWindow listener to (e.g.) save a screenshot"),
+ mViewerWindow(llviewerwindow)
+{
+ // add() every method we want to be able to invoke via this event API.
+ LLSD saveSnapshotArgs;
+ saveSnapshotArgs["filename"] = LLSD::String();
+ saveSnapshotArgs["reply"] = LLSD::String();
+ // The following are optional, so don't build them into required prototype.
+// saveSnapshotArgs["width"] = LLSD::Integer();
+// saveSnapshotArgs["height"] = LLSD::Integer();
+// saveSnapshotArgs["showui"] = LLSD::Boolean();
+// saveSnapshotArgs["rebuild"] = LLSD::Boolean();
+// saveSnapshotArgs["type"] = LLSD::String();
+ add("saveSnapshot",
+ "Save screenshot: [\"filename\"], [\"width\"], [\"height\"], [\"showui\"], [\"rebuild\"], [\"type\"]\n"
+ "type: \"COLOR\", \"DEPTH\", \"OBJECT_ID\"\n"
+ "Post on [\"reply\"] an event containing [\"ok\"]",
+ &LLViewerWindowListener::saveSnapshot,
+ saveSnapshotArgs);
+ add("requestReshape",
+ "Resize the window: [\"w\"], [\"h\"]",
+ &LLViewerWindowListener::requestReshape);
+}
+
+void LLViewerWindowListener::saveSnapshot(const LLSD& event) const
+{
+ LLReqID reqid(event);
+ typedef std::map<LLSD::String, LLViewerWindow::ESnapshotType> TypeMap;
+ TypeMap types;
+#define tp(name) types[#name] = LLViewerWindow::SNAPSHOT_TYPE_##name
+ tp(COLOR);
+ tp(DEPTH);
+ tp(OBJECT_ID);
+#undef tp
+ // Our add() call should ensure that the incoming LLSD does in fact
+ // contain our required arguments. Deal with the optional ones.
+ S32 width (mViewerWindow->getWindowWidthRaw());
+ S32 height(mViewerWindow->getWindowHeightRaw());
+ if (event.has("width"))
+ width = event["width"].asInteger();
+ if (event.has("height"))
+ height = event["height"].asInteger();
+ // showui defaults to true, requiring special treatment
+ bool showui = true;
+ if (event.has("showui"))
+ showui = event["showui"].asBoolean();
+ bool rebuild(event["rebuild"]); // defaults to false
+ LLViewerWindow::ESnapshotType type(LLViewerWindow::SNAPSHOT_TYPE_COLOR);
+ if (event.has("type"))
+ {
+ TypeMap::const_iterator found = types.find(event["type"]);
+ if (found == types.end())
+ {
+ LL_ERRS("LLViewerWindowListener") << "LLViewerWindowListener::saveSnapshot(): "
+ << "unrecognized type " << event["type"] << LL_ENDL;
+ }
+ type = found->second;
+ }
+ bool ok = mViewerWindow->saveSnapshot(event["filename"], width, height, showui, rebuild, type);
+ LLSD response(reqid.makeResponse());
+ response["ok"] = ok;
+ LLEventPumps::instance().obtain(event["reply"]).post(response);
+}
+
+void LLViewerWindowListener::requestReshape(LLSD const & event_data) const
+{
+ if(event_data.has("w") && event_data.has("h"))
+ {
+ mViewerWindow->reshape(event_data["w"].asInteger(), event_data["h"].asInteger());
+ }
+}
diff --git a/indra/newview/llviewerwindowlistener.h b/indra/newview/llviewerwindowlistener.h
new file mode 100644
index 0000000000..699f7907af
--- /dev/null
+++ b/indra/newview/llviewerwindowlistener.h
@@ -0,0 +1,34 @@
+/**
+ * @file llviewerwindowlistener.h
+ * @author Nat Goodspeed
+ * @date 2009-06-30
+ * @brief Event API for subset of LLViewerWindow methods
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLVIEWERWINDOWLISTENER_H)
+#define LL_LLVIEWERWINDOWLISTENER_H
+
+#include "lleventapi.h"
+
+class LLViewerWindow;
+class LLSD;
+
+/// Listen on an LLEventPump with specified name for LLViewerWindow request events.
+class LLViewerWindowListener: public LLEventAPI
+{
+public:
+ /// Bind the LLViewerWindow instance to use (e.g. gViewerWindow).
+ LLViewerWindowListener(LLViewerWindow* llviewerwindow);
+
+private:
+ void saveSnapshot(const LLSD& event) const;
+ void requestReshape(LLSD const & event_data) const;
+
+ LLViewerWindow* mViewerWindow;
+};
+
+#endif /* ! defined(LL_LLVIEWERWINDOWLISTENER_H) */
diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp
index e52fec7909..6340189c93 100644
--- a/indra/newview/llvlcomposition.cpp
+++ b/indra/newview/llvlcomposition.cpp
@@ -39,8 +39,8 @@
#include "v3math.h"
#include "llsurface.h"
#include "lltextureview.h"
-#include "llviewerimage.h"
-#include "llviewerimagelist.h"
+#include "llviewertexture.h"
+#include "llviewertexturelist.h"
#include "llviewerregion.h"
#include "noise.h"
#include "llregionhandle.h" // for from_region_handle
@@ -106,7 +106,7 @@ void LLVLComposition::setDetailTextureID(S32 corner, const LLUUID& id)
{
return;
}
- mDetailTextures[corner] = gImageList.getImage(id);
+ mDetailTextures[corner] = LLViewerTextureManager::getFetchedTexture(id);
mDetailTextures[corner]->setNoDelete() ;
mRawImages[corner] = NULL;
}
@@ -229,7 +229,7 @@ BOOL LLVLComposition::generateComposition()
{
if (mDetailTextures[i]->getDiscardLevel() < 0)
{
- mDetailTextures[i]->setBoostLevel(LLViewerImage::BOOST_TERRAIN); // in case we are at low detail
+ mDetailTextures[i]->setBoostLevel(LLViewerTexture::BOOST_TERRAIN); // in case we are at low detail
mDetailTextures[i]->addTextureStats(BASE_SIZE*BASE_SIZE);
return FALSE;
}
@@ -237,8 +237,8 @@ BOOL LLVLComposition::generateComposition()
(mDetailTextures[i]->getWidth() < BASE_SIZE ||
mDetailTextures[i]->getHeight() < BASE_SIZE)))
{
- S32 width = mDetailTextures[i]->getWidth(0);
- S32 height = mDetailTextures[i]->getHeight(0);
+ S32 width = mDetailTextures[i]->getFullWidth();
+ S32 height = mDetailTextures[i]->getFullHeight();
S32 min_dim = llmin(width, height);
S32 ddiscard = 0;
while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL)
@@ -246,7 +246,7 @@ BOOL LLVLComposition::generateComposition()
ddiscard++;
min_dim /= 2;
}
- mDetailTextures[i]->setBoostLevel(LLViewerImage::BOOST_TERRAIN); // in case we are at low detail
+ mDetailTextures[i]->setBoostLevel(LLViewerTexture::BOOST_TERRAIN); // in case we are at low detail
mDetailTextures[i]->setMinDiscardLevel(ddiscard);
return FALSE;
}
@@ -279,20 +279,30 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
if (mRawImages[i].isNull())
{
// Read back a raw image for this discard level, if it exists
- mRawImages[i] = new LLImageRaw;
- S32 min_dim = llmin(mDetailTextures[i]->getWidth(0), mDetailTextures[i]->getHeight(0));
+ S32 min_dim = llmin(mDetailTextures[i]->getFullWidth(), mDetailTextures[i]->getFullHeight());
S32 ddiscard = 0;
while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL)
{
ddiscard++;
min_dim /= 2;
}
- if (!mDetailTextures[i]->readBackRaw(ddiscard, mRawImages[i], false))
+
+ BOOL delete_raw = (mDetailTextures[i]->reloadRawImage(ddiscard) != NULL) ;
+ if(mDetailTextures[i]->getRawImageLevel() != ddiscard)//raw iamge is not ready, will enter here again later.
{
- llwarns << "Unable to read raw data for terrain detail texture: " << mDetailTextures[i]->getID() << llendl;
- mRawImages[i] = NULL;
+ if(delete_raw)
+ {
+ mDetailTextures[i]->destroyRawImage() ;
+ }
+ lldebugs << "cached raw data for terrain detail texture is not ready yet: " << mDetailTextures[i]->getID() << llendl;
return FALSE;
}
+
+ mRawImages[i] = mDetailTextures[i]->getRawImage() ;
+ if(delete_raw)
+ {
+ mDetailTextures[i]->destroyRawImage() ;
+ }
if (mDetailTextures[i]->getWidth(ddiscard) != BASE_SIZE ||
mDetailTextures[i]->getHeight(ddiscard) != BASE_SIZE ||
mDetailTextures[i]->getComponents() != 3)
@@ -336,7 +346,7 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
//
//
- LLViewerImage *texturep;
+ LLViewerTexture *texturep;
U32 tex_width, tex_height, tex_comps;
U32 tex_stride;
F32 tex_x_scalef, tex_y_scalef;
@@ -448,6 +458,10 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
}
}
+ if (!texturep->hasGLTexture())
+ {
+ texturep->createGLTexture(0, raw);
+ }
texturep->setSubImage(raw, tex_x_begin, tex_y_begin, tex_x_end - tex_x_begin, tex_y_end - tex_y_begin);
LLSurface::sTextureUpdateTime += gen_timer.getElapsedTimeF32();
LLSurface::sTexelsUpdated += (tex_x_end - tex_x_begin) * (tex_y_end - tex_y_begin);
@@ -455,7 +469,7 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
for (S32 i = 0; i < 4; i++)
{
// Un-boost detatil textures (will get re-boosted if rendering in high detail)
- mDetailTextures[i]->setBoostLevel(LLViewerImage::BOOST_NONE);
+ mDetailTextures[i]->setBoostLevel(LLViewerTexture::BOOST_NONE);
mDetailTextures[i]->setMinDiscardLevel(MAX_DISCARD_LEVEL + 1);
}
@@ -467,7 +481,7 @@ LLUUID LLVLComposition::getDetailTextureID(S32 corner)
return mDetailTextures[corner]->getID();
}
-LLViewerImage* LLVLComposition::getDetailTexture(S32 corner)
+LLViewerFetchedTexture* LLVLComposition::getDetailTexture(S32 corner)
{
return mDetailTextures[corner];
}
diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h
index 6d5db3c050..d1b3dc4495 100644
--- a/indra/newview/llvlcomposition.h
+++ b/indra/newview/llvlcomposition.h
@@ -34,7 +34,7 @@
#define LL_LLVLCOMPOSITION_H
#include "llviewerlayer.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
class LLSurface;
@@ -62,7 +62,7 @@ public:
CORNER_COUNT = 4
};
LLUUID getDetailTextureID(S32 corner);
- LLViewerImage* getDetailTexture(S32 corner);
+ LLViewerFetchedTexture* getDetailTexture(S32 corner);
F32 getStartHeight(S32 corner);
F32 getHeightRange(S32 corner);
@@ -79,7 +79,7 @@ protected:
LLSurface *mSurfacep;
BOOL mTexturesLoaded;
- LLPointer<LLViewerImage> mDetailTextures[CORNER_COUNT];
+ LLPointer<LLViewerFetchedTexture> mDetailTextures[CORNER_COUNT];
LLPointer<LLImageRaw> mRawImages[CORNER_COUNT];
F32 mStartHeight[CORNER_COUNT];
diff --git a/indra/newview/llvlmanager.cpp b/indra/newview/llvlmanager.cpp
index 177093c4d1..07ef262668 100644
--- a/indra/newview/llvlmanager.cpp
+++ b/indra/newview/llvlmanager.cpp
@@ -40,7 +40,6 @@
#include "patch_dct.h"
#include "llviewerregion.h"
#include "llframetimer.h"
-#include "llagent.h"
#include "llsurface.h"
LLVLManager gVLManager;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 168b0056e5..4235f97eab 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1,5 +1,5 @@
/**
- * @file llvoavatar.cpp
+ * @File llvoavatar.cpp
* @brief Implementation of LLVOAvatar class which is a derivation fo LLViewerObject
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
@@ -30,6 +30,12 @@
* $/LicenseInfo$
*/
+#if LL_MSVC
+// disable warning about boost::lexical_cast returning uninitialized data
+// when it fails to parse the string
+#pragma warning (disable:4701)
+#endif
+
#include "llviewerprecompiledheaders.h"
#include "llvoavatar.h"
@@ -37,25 +43,28 @@
#include <stdio.h>
#include <ctype.h>
-#include "audioengine.h"
+#include "llaudioengine.h"
#include "noise.h"
+#include "sound_ids.h"
#include "llagent.h" // Get state values from here
+#include "llagentwearables.h"
+#include "llanimationstates.h"
+#include "llavatarpropertiesprocessor.h"
#include "llviewercontrol.h"
#include "lldrawpoolavatar.h"
#include "lldriverparam.h"
#include "lleditingmotion.h"
#include "llemote.h"
-#include "llfirstuse.h"
+//#include "llfirstuse.h"
#include "llheadrotmotion.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
-#include "llinventoryview.h"
#include "llkeyframefallmotion.h"
#include "llkeyframestandmotion.h"
#include "llkeyframewalkmotion.h"
#include "llmutelist.h"
-#include "llnotify.h"
+#include "llmoveview.h"
#include "llquantize.h"
#include "llregionhandle.h"
#include "llresmgr.h"
@@ -63,26 +72,33 @@
#include "llsprite.h"
#include "lltargetingmotion.h"
#include "lltexlayer.h"
-#include "lltoolgrab.h" // for needsRenderBeam
-#include "lltoolmgr.h" // for needsRenderBeam
#include "lltoolmorph.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewermenu.h"
#include "llviewerobjectlist.h"
#include "llviewerparcelmgr.h"
#include "llviewerstats.h"
+#include "llvoavatarself.h"
#include "llvovolume.h"
#include "llworld.h"
#include "pipeline.h"
#include "llviewershadermgr.h"
#include "llsky.h"
#include "llanimstatelabels.h"
+#include "lltrans.h"
+#include "llappearancemgr.h"
+
#include "llgesturemgr.h" //needed to trigger the voice gesticulations
#include "llvoiceclient.h"
#include "llvoicevisualizer.h" // Ventrella
-#include "boost/lexical_cast.hpp"
+#if LL_MSVC
+// disable boost::lexical_cast warning
+#pragma warning (disable:4702)
+#endif
+
+#include <boost/lexical_cast.hpp>
using namespace LLVOAvatarDefines;
@@ -136,8 +152,7 @@ const S32 MIN_REQUIRED_PIXEL_AREA_PELVIS_FIX = 40;
const S32 TEX_IMAGE_SIZE_SELF = 512;
const S32 TEX_IMAGE_AREA_SELF = TEX_IMAGE_SIZE_SELF * TEX_IMAGE_SIZE_SELF;
-const S32 TEX_IMAGE_SIZE_OTHER = TEX_IMAGE_SIZE_SELF / 4; // The size of local textures for other (!mIsSelf) avatars
-const S32 TEX_IMAGE_AREA_OTHER = TEX_IMAGE_SIZE_OTHER * TEX_IMAGE_SIZE_OTHER;
+const S32 TEX_IMAGE_SIZE_OTHER = 512 / 4; // The size of local textures for other (!isSelf()) avatars
const F32 HEAD_MOVEMENT_AVG_TIME = 0.9f;
@@ -168,32 +183,27 @@ const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0);
enum ERenderName
{
RENDER_NAME_NEVER,
- RENDER_NAME_FADE,
- RENDER_NAME_ALWAYS
+ RENDER_NAME_ALWAYS,
+ RENDER_NAME_FADE
};
//-----------------------------------------------------------------------------
// Callback data
//-----------------------------------------------------------------------------
-struct LLAvatarTexData
-{
- LLAvatarTexData( const LLUUID& id, ETextureIndex index )
- : mAvatarID(id), mIndex(index) {}
- LLUUID mAvatarID;
- ETextureIndex mIndex;
-};
struct LLTextureMaskData
{
- LLTextureMaskData( const LLUUID& id )
- : mAvatarID(id), mLastDiscardLevel(S32_MAX) {}
+ LLTextureMaskData( const LLUUID& id ) :
+ mAvatarID(id),
+ mLastDiscardLevel(S32_MAX)
+ {}
LLUUID mAvatarID;
S32 mLastDiscardLevel;
};
/*********************************************************************************
** **
- ** Begin LLVOAvatar Support classes
+ ** Begin private LLVOAvatar Support classes
**
**/
@@ -249,85 +259,6 @@ private:
bone_info_list_t mBoneInfoList;
};
-
-//------------------------------------------------------------------------
-// LLVOAvatarXmlInfo
-// One instance (in LLVOAvatar) with common data parsed from the XML files
-//------------------------------------------------------------------------
-class LLVOAvatarXmlInfo
-{
- friend class LLVOAvatar;
-public:
- LLVOAvatarXmlInfo();
- ~LLVOAvatarXmlInfo();
-
-private:
- BOOL parseXmlSkeletonNode(LLXmlTreeNode* root);
- BOOL parseXmlMeshNodes(LLXmlTreeNode* root);
- BOOL parseXmlColorNodes(LLXmlTreeNode* root);
- BOOL parseXmlLayerNodes(LLXmlTreeNode* root);
- BOOL parseXmlDriverNodes(LLXmlTreeNode* root);
-
- struct LLVOAvatarMeshInfo
- {
- typedef std::pair<LLPolyMorphTargetInfo*,BOOL> morph_info_pair_t;
- typedef std::vector<morph_info_pair_t> morph_info_list_t;
-
- LLVOAvatarMeshInfo() : mLOD(0), mMinPixelArea(.1f) {}
- ~LLVOAvatarMeshInfo()
- {
- morph_info_list_t::iterator iter;
- for (iter = mPolyMorphTargetInfoList.begin(); iter != mPolyMorphTargetInfoList.end(); iter++)
- {
- delete iter->first;
- }
- mPolyMorphTargetInfoList.clear();
- }
-
- std::string mType;
- S32 mLOD;
- std::string mMeshFileName;
- std::string mReferenceMeshName;
- F32 mMinPixelArea;
- morph_info_list_t mPolyMorphTargetInfoList;
- };
- typedef std::vector<LLVOAvatarMeshInfo*> mesh_info_list_t;
- mesh_info_list_t mMeshInfoList;
-
- typedef std::vector<LLPolySkeletalDistortionInfo*> skeletal_distortion_info_list_t;
- skeletal_distortion_info_list_t mSkeletalDistortionInfoList;
-
- struct LLVOAvatarAttachmentInfo
- {
- LLVOAvatarAttachmentInfo()
- : mGroup(-1), mAttachmentID(-1), mPieMenuSlice(-1), mVisibleFirstPerson(FALSE),
- mIsHUDAttachment(FALSE), mHasPosition(FALSE), mHasRotation(FALSE) {}
- std::string mName;
- std::string mJointName;
- LLVector3 mPosition;
- LLVector3 mRotationEuler;
- S32 mGroup;
- S32 mAttachmentID;
- S32 mPieMenuSlice;
- BOOL mVisibleFirstPerson;
- BOOL mIsHUDAttachment;
- BOOL mHasPosition;
- BOOL mHasRotation;
- };
- typedef std::vector<LLVOAvatarAttachmentInfo*> attachment_info_list_t;
- attachment_info_list_t mAttachmentInfoList;
-
- LLTexGlobalColorInfo *mTexSkinColorInfo;
- LLTexGlobalColorInfo *mTexHairColorInfo;
- LLTexGlobalColorInfo *mTexEyeColorInfo;
-
- typedef std::vector<LLTexLayerSetInfo*> layer_info_list_t;
- layer_info_list_t mLayerInfoList;
-
- typedef std::vector<LLDriverParamInfo*> driver_info_list_t;
- driver_info_list_t mDriverInfoList;
-};
-
//-----------------------------------------------------------------------------
// class LLBodyNoiseMotion
//-----------------------------------------------------------------------------
@@ -492,7 +423,7 @@ public:
virtual LLMotionInitStatus onInitialize(LLCharacter *character)
{
mCharacter = character;
- bool success = true;
+ BOOL success = true;
if ( !mChestState->setJoint( character->getJoint( "mChest" ) ) ) { success = false; }
@@ -651,15 +582,11 @@ private:
//-----------------------------------------------------------------------------
LLXmlTree LLVOAvatar::sXMLTree;
LLXmlTree LLVOAvatar::sSkeletonXMLTree;
-BOOL LLVOAvatar::sDebugAvatarRotation = FALSE;
LLVOAvatarSkeletonInfo* LLVOAvatar::sAvatarSkeletonInfo = NULL;
-LLVOAvatarXmlInfo* LLVOAvatar::sAvatarXmlInfo = NULL;
+LLVOAvatar::LLVOAvatarXmlInfo* LLVOAvatar::sAvatarXmlInfo = NULL;
LLVOAvatarDictionary *LLVOAvatar::sAvatarDictionary = NULL;
S32 LLVOAvatar::sFreezeCounter = 0;
S32 LLVOAvatar::sMaxVisible = 50;
-LLMap< LLGLenum, LLGLuint*> LLVOAvatar::sScratchTexNames;
-LLMap< LLGLenum, F32*> LLVOAvatar::sScratchTexLastBindTime;
-S32 LLVOAvatar::sScratchTexBytes = 0;
F32 LLVOAvatar::sRenderDistance = 256.f;
S32 LLVOAvatar::sNumVisibleAvatars = 0;
S32 LLVOAvatar::sNumLODChangesThisFrame = 0;
@@ -697,7 +624,6 @@ F32 LLVOAvatar::sGreyUpdateTime = 0.f;
// Helper functions
//-----------------------------------------------------------------------------
static F32 calc_bouncy_animation(F32 x);
-static U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures);
//-----------------------------------------------------------------------------
// LLVOAvatar()
@@ -720,7 +646,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mWindFreq(0.f),
mRipplePhase( 0.f ),
mBelowWater(FALSE),
- mAppearanceAnimSetByUser(FALSE),
mLastAppearanceBlendTime(0.f),
mAppearanceAnimating(FALSE),
mNameString(),
@@ -730,8 +655,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mNameMute(FALSE),
mRenderGroupTitles(sRenderGroupTitles),
mNameAppearance(FALSE),
- mLastRegionHandle(0),
- mRegionCrossingCount(0),
mFirstTEMessageReceived( FALSE ),
mFirstAppearanceMessageReceived( FALSE ),
mCulled( FALSE ),
@@ -742,39 +665,32 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mNeedsSkin(FALSE),
mUpdatePeriod(1),
mFullyLoadedInitialized(FALSE),
- mHasBakedHair( FALSE )
+ mSupportsAlphaLayers(FALSE)
{
LLMemType mt(LLMemType::MTYPE_AVATAR);
//VTResume(); // VTune
// mVoiceVisualizer is created by the hud effects manager and uses the HUD Effects pipeline
- const bool needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job
+ const BOOL needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job
mVoiceVisualizer = ( LLVoiceVisualizer *)LLHUDManager::getInstance()->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim );
lldebugs << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << llendl;
mPelvisp = NULL;
- for( S32 i=0; i<TEX_NUM_INDICES; i++ )
- {
- if (isIndexLocalTexture((ETextureIndex)i))
- {
- mLocalTextureData[(ETextureIndex)i] = LocalTextureData();
- }
- }
-
- mBakedTextureData.resize(BAKED_NUM_INDICES);
- for (U32 i = 0; i < mBakedTextureData.size(); i++ )
+ mBakedTextureDatas.resize(BAKED_NUM_INDICES);
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++ )
{
- mBakedTextureData[i].mLastTextureIndex = IMG_DEFAULT_AVATAR;
- mBakedTextureData[i].mTexLayerSet = NULL;
- mBakedTextureData[i].mIsLoaded = false;
- mBakedTextureData[i].mIsUsed = false;
- mBakedTextureData[i].mMaskTexName = 0;
- mBakedTextureData[i].mTextureIndex = getTextureIndex((EBakedTextureIndex)i);
+ mBakedTextureDatas[i].mLastTextureIndex = IMG_DEFAULT_AVATAR;
+ mBakedTextureDatas[i].mTexLayerSet = NULL;
+ mBakedTextureDatas[i].mIsLoaded = false;
+ mBakedTextureDatas[i].mIsUsed = false;
+ mBakedTextureDatas[i].mMaskTexName = 0;
+ mBakedTextureDatas[i].mTextureIndex = LLVOAvatarDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)i);
}
mDirtyMesh = TRUE; // Dirty geometry, need to regenerate.
+ mMeshTexturesDirty = FALSE;
mShadow0Facep = NULL;
mShadow1Facep = NULL;
mHeadp = NULL;
@@ -783,7 +699,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mNumJoints = 0;
mSkeleton = NULL;
- mScreenp = NULL;
mNumCollisionVolumes = 0;
mCollisionVolumes = NULL;
@@ -792,17 +707,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mSpeed = 0.f;
setAnimationData("Speed", &mSpeed);
- if (id == gAgentID)
- {
- mIsSelf = TRUE;
- gAgent.setAvatarObject(this);
- lldebugs << "Marking avatar as self " << id << llendl;
- }
- else
- {
- mIsSelf = FALSE;
- }
-
mNeedsImpostorUpdate = TRUE;
mNeedsAnimUpdate = TRUE;
@@ -824,9 +728,11 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mRippleTimeLast = 0.f;
- mShadowImagep = gImageList.getImageFromFile("foot_shadow.j2c");
- gGL.getTexUnit(0)->bind(mShadowImagep.get());
- mShadowImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
+ mShadowImagep = LLViewerTextureManager::getFetchedTextureFromFile("foot_shadow.j2c");
+
+ // GL NOT ACTIVE HERE
+ //gGL.getTexUnit(0)->bind(mShadowImagep.get());
+ //mShadowImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
mInAir = FALSE;
@@ -837,146 +743,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mOohMorph = NULL;
mAahMorph = NULL;
- //-------------------------------------------------------------------------
- // initialize joint, mesh and shape members
- //-------------------------------------------------------------------------
- mRoot.setName( "mRoot" );
-
- for (LLVOAvatarDictionary::mesh_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin();
- iter != LLVOAvatarDictionary::getInstance()->getMeshes().end();
- iter++)
- {
- const EMeshIndex mesh_index = iter->first;
- const LLVOAvatarDictionary::MeshDictionaryEntry *mesh_dict = iter->second;
-
- LLViewerJoint* joint = new LLViewerJoint();
- joint->setName(mesh_dict->mName);
- joint->setMeshID(mesh_index);
- mMeshLOD.push_back(joint);
-
- /* mHairLOD.setName("mHairLOD");
- mHairMesh0.setName("mHairMesh0");
- mHairMesh0.setMeshID(MESH_ID_HAIR);
- mHairMesh1.setName("mHairMesh1"); */
- for (U32 lod = 0; lod < mesh_dict->mLOD; lod++)
- {
- LLViewerJointMesh* mesh = new LLViewerJointMesh();
- std::string mesh_name = "m" + mesh_dict->mName + boost::lexical_cast<std::string>(lod);
- // We pre-pended an m - need to capitalize first character for camelCase
- mesh_name[1] = toupper(mesh_name[1]);
- mesh->setName(mesh_name);
- mesh->setMeshID(mesh_index);
- mesh->setPickName(mesh_dict->mPickName);
- switch((int)mesh_index)
- {
- case MESH_ID_HAIR:
- mesh->setIsTransparent(TRUE);
- break;
- case MESH_ID_SKIRT:
- mesh->setIsTransparent(TRUE);
- break;
- case MESH_ID_EYEBALL_LEFT:
- case MESH_ID_EYEBALL_RIGHT:
- mesh->setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f );
- break;
- }
-
- joint->mMeshParts.push_back(mesh);
- }
- }
-
- //-------------------------------------------------------------------------
- // associate baked textures with meshes
- //-------------------------------------------------------------------------
- for (LLVOAvatarDictionary::mesh_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin();
- iter != LLVOAvatarDictionary::getInstance()->getMeshes().end();
- iter++)
- {
- const EMeshIndex mesh_index = iter->first;
- const LLVOAvatarDictionary::MeshDictionaryEntry *mesh_dict = iter->second;
- const EBakedTextureIndex baked_texture_index = mesh_dict->mBakedID;
-
- // Skip it if there's no associated baked texture.
- if (baked_texture_index == BAKED_NUM_INDICES) continue;
-
- for (std::vector<LLViewerJointMesh* >::iterator iter = mMeshLOD[mesh_index]->mMeshParts.begin();
- iter != mMeshLOD[mesh_index]->mMeshParts.end(); iter++)
- {
- LLViewerJointMesh* mesh = (LLViewerJointMesh*) *iter;
- mBakedTextureData[(int)baked_texture_index].mMeshes.push_back(mesh);
- }
- }
-
-
- //-------------------------------------------------------------------------
- // register motions
- //-------------------------------------------------------------------------
- if (LLCharacter::sInstances.size() == 1)
- {
- LLKeyframeMotion::setVFS(gStaticVFS);
- registerMotion( ANIM_AGENT_BUSY, LLNullMotion::create );
- registerMotion( ANIM_AGENT_CROUCH, LLKeyframeStandMotion::create );
- registerMotion( ANIM_AGENT_CROUCHWALK, LLKeyframeWalkMotion::create );
- registerMotion( ANIM_AGENT_EXPRESS_AFRAID, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_ANGER, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_BORED, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_CRY, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_DISDAIN, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_EMBARRASSED, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_FROWN, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_KISS, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_LAUGH, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_OPEN_MOUTH, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_REPULSED, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_SAD, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_SHRUG, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_SMILE, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_SURPRISE, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_TONGUE_OUT, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_TOOTHSMILE, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_WINK, LLEmote::create );
- registerMotion( ANIM_AGENT_EXPRESS_WORRY, LLEmote::create );
- registerMotion( ANIM_AGENT_RUN, LLKeyframeWalkMotion::create );
- registerMotion( ANIM_AGENT_STAND, LLKeyframeStandMotion::create );
- registerMotion( ANIM_AGENT_STAND_1, LLKeyframeStandMotion::create );
- registerMotion( ANIM_AGENT_STAND_2, LLKeyframeStandMotion::create );
- registerMotion( ANIM_AGENT_STAND_3, LLKeyframeStandMotion::create );
- registerMotion( ANIM_AGENT_STAND_4, LLKeyframeStandMotion::create );
- registerMotion( ANIM_AGENT_STANDUP, LLKeyframeFallMotion::create );
- registerMotion( ANIM_AGENT_TURNLEFT, LLKeyframeWalkMotion::create );
- registerMotion( ANIM_AGENT_TURNRIGHT, LLKeyframeWalkMotion::create );
- registerMotion( ANIM_AGENT_WALK, LLKeyframeWalkMotion::create );
-
- // motions without a start/stop bit
- registerMotion( ANIM_AGENT_BODY_NOISE, LLBodyNoiseMotion::create );
- registerMotion( ANIM_AGENT_BREATHE_ROT, LLBreatheMotionRot::create );
- registerMotion( ANIM_AGENT_EDITING, LLEditingMotion::create );
- registerMotion( ANIM_AGENT_EYE, LLEyeMotion::create );
- registerMotion( ANIM_AGENT_FEMALE_WALK, LLKeyframeWalkMotion::create );
- registerMotion( ANIM_AGENT_FLY_ADJUST, LLFlyAdjustMotion::create );
- registerMotion( ANIM_AGENT_HAND_MOTION, LLHandMotion::create );
- registerMotion( ANIM_AGENT_HEAD_ROT, LLHeadRotMotion::create );
- registerMotion( ANIM_AGENT_PELVIS_FIX, LLPelvisFixMotion::create );
- registerMotion( ANIM_AGENT_SIT_FEMALE, LLKeyframeMotion::create );
- registerMotion( ANIM_AGENT_TARGET, LLTargetingMotion::create );
- registerMotion( ANIM_AGENT_WALK_ADJUST, LLWalkAdjustMotion::create );
-
- }
-
- if (gNoRender)
- {
- return;
- }
- buildCharacter();
-
- // preload specific motions here
- createMotion( ANIM_AGENT_CUSTOMIZE);
- createMotion( ANIM_AGENT_CUSTOMIZE_DONE);
-
- //VTPause(); // VTune
-
- mVoiceVisualizer->setVoiceEnabled( gVoiceClient->getVoiceEnabled( mID ) );
mCurrentGesticulationLevel = 0;
+
}
//------------------------------------------------------------------------
@@ -986,46 +754,44 @@ LLVOAvatar::~LLVOAvatar()
{
lldebugs << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << llendl;
- if (mIsSelf)
+ if (isSelf())
{
gAgent.setAvatarObject(NULL);
}
mRoot.removeAllChildren();
- delete [] mSkeleton;
- mSkeleton = NULL;
-
- delete mScreenp;
- mScreenp = NULL;
-
- delete [] mCollisionVolumes;
- mCollisionVolumes = NULL;
-
+ deleteAndClearArray(mSkeleton);
+ deleteAndClearArray(mCollisionVolumes);
mNumJoints = 0;
- for (U32 i = 0; i < mBakedTextureData.size(); i++)
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
{
- delete mBakedTextureData[i].mTexLayerSet;
- mBakedTextureData[i].mTexLayerSet = NULL;
+ deleteAndClear(mBakedTextureDatas[i].mTexLayerSet);
+ mBakedTextureDatas[i].mMeshes.clear();
+
+ for (morph_list_t::iterator iter2 = mBakedTextureDatas[i].mMaskedMorphs.begin();
+ iter2 != mBakedTextureDatas[i].mMaskedMorphs.end(); iter2++)
+ {
+ LLMaskedMorph* masked_morph = (*iter2);
+ delete masked_morph;
+ }
}
std::for_each(mAttachmentPoints.begin(), mAttachmentPoints.end(), DeletePairedPointer());
mAttachmentPoints.clear();
- delete mTexSkinColor;
- mTexSkinColor = NULL;
- delete mTexHairColor;
- mTexHairColor = NULL;
- delete mTexEyeColor;
- mTexEyeColor = NULL;
+ deleteAndClear(mTexSkinColor);
+ deleteAndClear(mTexHairColor);
+ deleteAndClear(mTexEyeColor);
std::for_each(mMeshes.begin(), mMeshes.end(), DeletePairedPointer());
mMeshes.clear();
for (std::vector<LLViewerJoint*>::iterator jointIter = mMeshLOD.begin();
- jointIter != mMeshLOD.end(); jointIter++)
+ jointIter != mMeshLOD.end();
+ ++jointIter)
{
LLViewerJoint* joint = (LLViewerJoint *) *jointIter;
std::for_each(joint->mMeshParts.begin(), joint->mMeshParts.end(), DeletePointer());
@@ -1036,9 +802,6 @@ LLVOAvatar::~LLVOAvatar()
mDead = TRUE;
- // Clean up class data
- LLVOAvatar::cullAvatarsByPixelArea();
-
mAnimationSources.clear();
lldebugs << "LLVOAvatar Destructor end" << llendl;
@@ -1052,10 +815,7 @@ void LLVOAvatar::markDead()
mNameText = NULL;
sNumVisibleChatBubbles--;
}
-
mVoiceVisualizer->markDead();
-
- mBeam = NULL;
LLViewerObject::markDead();
}
@@ -1065,9 +825,9 @@ BOOL LLVOAvatar::isFullyBaked()
if (mIsDummy) return TRUE;
if (getNumTEs() == 0) return FALSE;
- for (U32 i = 0; i < mBakedTextureData.size(); i++)
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
{
- if (!isTextureDefined(mBakedTextureData[i].mTextureIndex)
+ if (!isTextureDefined(mBakedTextureDatas[i].mTextureIndex)
&& ( (i != BAKED_SKIRT) || isWearingWearableType(WT_SKIRT) ) )
{
return FALSE;
@@ -1078,19 +838,21 @@ BOOL LLVOAvatar::isFullyBaked()
void LLVOAvatar::deleteLayerSetCaches(bool clearAll)
{
- for (U32 i = 0; i < mBakedTextureData.size(); i++)
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
{
- if (mBakedTextureData[i].mTexLayerSet)
+ if (mBakedTextureDatas[i].mTexLayerSet)
{
- if ((i != BAKED_HAIR || mIsSelf) && !clearAll) // Backwards compatibility - can be removed after hair baking is mandatory on the grid
+ // ! BACKWARDS COMPATIBILITY !
+ // Can be removed after hair baking is mandatory on the grid
+ if ((i != BAKED_HAIR || isSelf()) && !clearAll)
{
- mBakedTextureData[i].mTexLayerSet->deleteCaches();
+ mBakedTextureDatas[i].mTexLayerSet->deleteCaches();
}
}
- if (mBakedTextureData[i].mMaskTexName)
+ if (mBakedTextureDatas[i].mMaskTexName)
{
- glDeleteTextures(1, (GLuint*)&(mBakedTextureData[i].mMaskTexName));
- mBakedTextureData[i].mMaskTexName = 0 ;
+ glDeleteTextures(1, (GLuint*)&(mBakedTextureDatas[i].mMaskTexName));
+ mBakedTextureDatas[i].mMaskTexName = 0 ;
}
}
}
@@ -1101,20 +863,14 @@ BOOL LLVOAvatar::areAllNearbyInstancesBaked(S32& grey_avatars)
BOOL res = TRUE;
grey_avatars = 0;
for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
+ iter != LLCharacter::sInstances.end(); ++iter)
{
LLVOAvatar* inst = (LLVOAvatar*) *iter;
if( inst->isDead() )
{
continue;
}
-// else
-// if( inst->getPixelArea() < MIN_PIXEL_AREA_FOR_COMPOSITE )
-// {
-// return res; // Assumes sInstances is sorted by pixel area.
-// }
- else
- if( !inst->isFullyBaked() )
+ else if( !inst->isFullyBaked() )
{
res = FALSE;
if (inst->mHasGrey)
@@ -1126,19 +882,13 @@ BOOL LLVOAvatar::areAllNearbyInstancesBaked(S32& grey_avatars)
return res;
}
-// static
-void LLVOAvatar::dumpScratchTextureByteCount()
-{
- llinfos << "Scratch Texture GL: " << (sScratchTexBytes/1024) << "KB" << llendl;
-}
-
// static
void LLVOAvatar::dumpBakedStatus()
{
LLVector3d camera_pos_global = gAgent.getCameraPositionGlobal();
for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
+ iter != LLCharacter::sInstances.end(); ++iter)
{
LLVOAvatar* inst = (LLVOAvatar*) *iter;
llinfos << "Avatar ";
@@ -1190,18 +940,17 @@ void LLVOAvatar::dumpBakedStatus()
{
llcont << " Unbaked (";
- for (LLVOAvatarDictionary::baked_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
+ for (LLVOAvatarDictionary::BakedTextures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end();
- iter++)
+ ++iter)
{
- const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = iter->second;
+ const LLVOAvatarDictionary::BakedEntry *baked_dict = iter->second;
const ETextureIndex index = baked_dict->mTextureIndex;
if (!inst->isTextureDefined(index))
{
llcont << " " << LLVOAvatarDictionary::getInstance()->getTexture(index)->mName;
}
}
-
llcont << " ) " << inst->getUnbakedPixelAreaRank();
if( inst->isCulled() )
{
@@ -1215,17 +964,15 @@ void LLVOAvatar::dumpBakedStatus()
//static
void LLVOAvatar::restoreGL()
{
- for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
+ LLVOAvatar* self = gAgent.getAvatarObject();
+ if (!self)
+ return;
+ self->setCompositeUpdatesEnabled(TRUE);
+ for (U32 i = 0; i < self->mBakedTextureDatas.size(); i++)
{
- LLVOAvatar* inst = (LLVOAvatar*) *iter;
- inst->setCompositeUpdatesEnabled( TRUE );
- for (U32 i = 0; i < inst->mBakedTextureData.size(); i++)
- {
- inst->invalidateComposite( inst->mBakedTextureData[i].mTexLayerSet, FALSE );
- }
- inst->updateMeshTextures();
+ self->invalidateComposite(self->mBakedTextureDatas[i].mTexLayerSet, FALSE);
}
+ self->updateMeshTextures();
}
//static
@@ -1240,7 +987,7 @@ void LLVOAvatar::destroyGL()
void LLVOAvatar::resetImpostors()
{
for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
+ iter != LLCharacter::sInstances.end(); ++iter)
{
LLVOAvatar* avatar = (LLVOAvatar*) *iter;
avatar->mImpostor.release();
@@ -1249,38 +996,20 @@ void LLVOAvatar::resetImpostors()
// static
void LLVOAvatar::deleteCachedImages(bool clearAll)
-{
+{
if (LLTexLayerSet::sHasCaches)
{
lldebugs << "Deleting layer set caches" << llendl;
for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
+ iter != LLCharacter::sInstances.end(); ++iter)
{
LLVOAvatar* inst = (LLVOAvatar*) *iter;
inst->deleteLayerSetCaches(clearAll);
}
LLTexLayerSet::sHasCaches = FALSE;
}
-
- for( LLGLuint* namep = sScratchTexNames.getFirstData();
- namep;
- namep = sScratchTexNames.getNextData() )
- {
- LLImageGL::deleteTextures(1, (U32 *)namep );
- stop_glerror();
- }
-
- if( sScratchTexBytes )
- {
- lldebugs << "Clearing Scratch Textures " << (sScratchTexBytes/1024) << "KB" << llendl;
-
- sScratchTexNames.deleteAllData();
- LLVOAvatar::sScratchTexLastBindTime.deleteAllData();
- LLImageGL::sGlobalTextureMemory -= sScratchTexBytes;
- sScratchTexBytes = 0;
- }
-
- gTexStaticImageList.deleteCachedImages();
+ LLVOAvatarSelf::deleteScratchTextures();
+ LLTexLayerStaticImageList::getInstance()->deleteCachedImages();
}
@@ -1382,20 +1111,169 @@ void LLVOAvatar::initClass()
{
llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
}
-
+ if (!sAvatarXmlInfo->parseXmlMorphNodes(root))
+ {
+ llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
+ }
}
void LLVOAvatar::cleanupClass()
{
- delete sAvatarXmlInfo;
- sAvatarXmlInfo = NULL;
- delete sAvatarSkeletonInfo;
- sAvatarSkeletonInfo = NULL;
+ deleteAndClear(sAvatarXmlInfo);
sSkeletonXMLTree.cleanup();
sXMLTree.cleanup();
}
+void LLVOAvatar::initInstance(void)
+{
+ //-------------------------------------------------------------------------
+ // initialize joint, mesh and shape members
+ //-------------------------------------------------------------------------
+ mRoot.setName( "mRoot" );
+
+ for (LLVOAvatarDictionary::Meshes::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin();
+ iter != LLVOAvatarDictionary::getInstance()->getMeshes().end();
+ ++iter)
+ {
+ const EMeshIndex mesh_index = iter->first;
+ const LLVOAvatarDictionary::MeshEntry *mesh_dict = iter->second;
+ LLViewerJoint* joint = new LLViewerJoint();
+ joint->setName(mesh_dict->mName);
+ joint->setMeshID(mesh_index);
+ mMeshLOD.push_back(joint);
+
+ /* mHairLOD.setName("mHairLOD");
+ mHairMesh0.setName("mHairMesh0");
+ mHairMesh0.setMeshID(MESH_ID_HAIR);
+ mHairMesh1.setName("mHairMesh1"); */
+ for (U32 lod = 0; lod < mesh_dict->mLOD; lod++)
+ {
+ LLViewerJointMesh* mesh = new LLViewerJointMesh();
+ std::string mesh_name = "m" + mesh_dict->mName + boost::lexical_cast<std::string>(lod);
+ // We pre-pended an m - need to capitalize first character for camelCase
+ mesh_name[1] = toupper(mesh_name[1]);
+ mesh->setName(mesh_name);
+ mesh->setMeshID(mesh_index);
+ mesh->setPickName(mesh_dict->mPickName);
+ mesh->setIsTransparent(FALSE);
+ switch((int)mesh_index)
+ {
+ case MESH_ID_HAIR:
+ mesh->setIsTransparent(TRUE);
+ break;
+ case MESH_ID_SKIRT:
+ mesh->setIsTransparent(TRUE);
+ break;
+ case MESH_ID_EYEBALL_LEFT:
+ case MESH_ID_EYEBALL_RIGHT:
+ mesh->setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f );
+ break;
+ }
+
+ joint->mMeshParts.push_back(mesh);
+ }
+ }
+
+ //-------------------------------------------------------------------------
+ // associate baked textures with meshes
+ //-------------------------------------------------------------------------
+ for (LLVOAvatarDictionary::Meshes::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin();
+ iter != LLVOAvatarDictionary::getInstance()->getMeshes().end();
+ ++iter)
+ {
+ const EMeshIndex mesh_index = iter->first;
+ const LLVOAvatarDictionary::MeshEntry *mesh_dict = iter->second;
+ const EBakedTextureIndex baked_texture_index = mesh_dict->mBakedID;
+ // Skip it if there's no associated baked texture.
+ if (baked_texture_index == BAKED_NUM_INDICES) continue;
+
+ for (std::vector<LLViewerJointMesh* >::iterator iter = mMeshLOD[mesh_index]->mMeshParts.begin();
+ iter != mMeshLOD[mesh_index]->mMeshParts.end();
+ ++iter)
+ {
+ LLViewerJointMesh* mesh = (LLViewerJointMesh*) *iter;
+ mBakedTextureDatas[(int)baked_texture_index].mMeshes.push_back(mesh);
+ }
+ }
+
+
+ //-------------------------------------------------------------------------
+ // register motions
+ //-------------------------------------------------------------------------
+ if (LLCharacter::sInstances.size() == 1)
+ {
+ LLKeyframeMotion::setVFS(gStaticVFS);
+ registerMotion( ANIM_AGENT_BUSY, LLNullMotion::create );
+ registerMotion( ANIM_AGENT_CROUCH, LLKeyframeStandMotion::create );
+ registerMotion( ANIM_AGENT_CROUCHWALK, LLKeyframeWalkMotion::create );
+ registerMotion( ANIM_AGENT_EXPRESS_AFRAID, LLEmote::create );
+ registerMotion( ANIM_AGENT_EXPRESS_ANGER, LLEmote::create );
+ registerMotion( ANIM_AGENT_EXPRESS_BORED, LLEmote::create );
+ registerMotion( ANIM_AGENT_EXPRESS_CRY, LLEmote::create );
+ registerMotion( ANIM_AGENT_EXPRESS_DISDAIN, LLEmote::create );
+ registerMotion( ANIM_AGENT_EXPRESS_EMBARRASSED, LLEmote::create );
+ registerMotion( ANIM_AGENT_EXPRESS_FROWN, LLEmote::create );
+ registerMotion( ANIM_AGENT_EXPRESS_KISS, LLEmote::create );
+ registerMotion( ANIM_AGENT_EXPRESS_LAUGH, LLEmote::create );
+ registerMotion( ANIM_AGENT_EXPRESS_OPEN_MOUTH, LLEmote::create );
+ registerMotion( ANIM_AGENT_EXPRESS_REPULSED, LLEmote::create );
+ registerMotion( ANIM_AGENT_EXPRESS_SAD, LLEmote::create );
+ registerMotion( ANIM_AGENT_EXPRESS_SHRUG, LLEmote::create );
+ registerMotion( ANIM_AGENT_EXPRESS_SMILE, LLEmote::create );
+ registerMotion( ANIM_AGENT_EXPRESS_SURPRISE, LLEmote::create );
+ registerMotion( ANIM_AGENT_EXPRESS_TONGUE_OUT, LLEmote::create );
+ registerMotion( ANIM_AGENT_EXPRESS_TOOTHSMILE, LLEmote::create );
+ registerMotion( ANIM_AGENT_EXPRESS_WINK, LLEmote::create );
+ registerMotion( ANIM_AGENT_EXPRESS_WORRY, LLEmote::create );
+ registerMotion( ANIM_AGENT_RUN, LLKeyframeWalkMotion::create );
+ registerMotion( ANIM_AGENT_STAND, LLKeyframeStandMotion::create );
+ registerMotion( ANIM_AGENT_STAND_1, LLKeyframeStandMotion::create );
+ registerMotion( ANIM_AGENT_STAND_2, LLKeyframeStandMotion::create );
+ registerMotion( ANIM_AGENT_STAND_3, LLKeyframeStandMotion::create );
+ registerMotion( ANIM_AGENT_STAND_4, LLKeyframeStandMotion::create );
+ registerMotion( ANIM_AGENT_STANDUP, LLKeyframeFallMotion::create );
+ registerMotion( ANIM_AGENT_TURNLEFT, LLKeyframeWalkMotion::create );
+ registerMotion( ANIM_AGENT_TURNRIGHT, LLKeyframeWalkMotion::create );
+ registerMotion( ANIM_AGENT_WALK, LLKeyframeWalkMotion::create );
+
+ // motions without a start/stop bit
+ registerMotion( ANIM_AGENT_BODY_NOISE, LLBodyNoiseMotion::create );
+ registerMotion( ANIM_AGENT_BREATHE_ROT, LLBreatheMotionRot::create );
+ registerMotion( ANIM_AGENT_EDITING, LLEditingMotion::create );
+ registerMotion( ANIM_AGENT_EYE, LLEyeMotion::create );
+ registerMotion( ANIM_AGENT_FEMALE_WALK, LLKeyframeWalkMotion::create );
+ registerMotion( ANIM_AGENT_FLY_ADJUST, LLFlyAdjustMotion::create );
+ registerMotion( ANIM_AGENT_HAND_MOTION, LLHandMotion::create );
+ registerMotion( ANIM_AGENT_HEAD_ROT, LLHeadRotMotion::create );
+ registerMotion( ANIM_AGENT_PELVIS_FIX, LLPelvisFixMotion::create );
+ registerMotion( ANIM_AGENT_SIT_FEMALE, LLKeyframeMotion::create );
+ registerMotion( ANIM_AGENT_TARGET, LLTargetingMotion::create );
+ registerMotion( ANIM_AGENT_WALK_ADJUST, LLWalkAdjustMotion::create );
+
+ }
+
+ if (gNoRender)
+ {
+ return;
+ }
+
+ buildCharacter();
+
+ if (gNoRender)
+ {
+ return;
+ }
+
+ // preload specific motions here
+ createMotion( ANIM_AGENT_CUSTOMIZE);
+ createMotion( ANIM_AGENT_CUSTOMIZE_DONE);
+
+ //VTPause(); // VTune
+
+ mVoiceVisualizer->setVoiceEnabled( gVoiceClient->getVoiceEnabled( mID ) );
+}
+
const LLVector3 LLVOAvatar::getRenderPosition() const
{
if (mDrawable.isNull() || mDrawable->getGeneration() < 0)
@@ -1461,7 +1339,7 @@ void LLVOAvatar::getSpatialExtents(LLVector3& newMin, LLVector3& newMax)
for (S32 joint_num = 0; joint_num < mesh->mJointRenderData.count(); joint_num++)
{
update_min_max(newMin, newMax,
- mesh->mJointRenderData[joint_num]->mWorldMatrix->getTranslation());
+ mesh->mJointRenderData[joint_num]->mWorldMatrix->getTranslation());
}
}
@@ -1469,8 +1347,8 @@ void LLVOAvatar::getSpatialExtents(LLVector3& newMin, LLVector3& newMax)
//stretch bounding box by attachments
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end();
- ++iter)
+ iter != mAttachmentPoints.end();
+ ++iter)
{
LLViewerJointAttachment* attachment = iter->second;
@@ -1479,27 +1357,32 @@ void LLVOAvatar::getSpatialExtents(LLVector3& newMin, LLVector3& newMax)
continue ;
}
- LLViewerObject* object = attachment->getObject();
- if (object && !object->isHUDAttachment())
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- LLDrawable* drawable = object->mDrawable;
- if (drawable)
+ const LLViewerObject* attached_object = (*attachment_iter);
+ if (attached_object && !attached_object->isHUDAttachment())
{
- LLSpatialBridge* bridge = drawable->getSpatialBridge();
- if (bridge)
+ LLDrawable* drawable = attached_object->mDrawable;
+ if (drawable)
{
- const LLVector3* ext = bridge->getSpatialExtents();
- LLVector3 distance = (ext[1] - ext[0]);
-
- // Only add the prim to spatial extents calculations if it isn't a megaprim.
- // max_attachment_span calculated at the start of the function
- // (currently 5 times our max prim size)
- if (distance.mV[0] < max_attachment_span
- && distance.mV[1] < max_attachment_span
- && distance.mV[2] < max_attachment_span)
+ LLSpatialBridge* bridge = drawable->getSpatialBridge();
+ if (bridge)
{
- update_min_max(newMin,newMax,ext[0]);
- update_min_max(newMin,newMax,ext[1]);
+ const LLVector3* ext = bridge->getSpatialExtents();
+ LLVector3 distance = (ext[1] - ext[0]);
+
+ // Only add the prim to spatial extents calculations if it isn't a megaprim.
+ // max_attachment_span calculated at the start of the function
+ // (currently 5 times our max prim size)
+ if (distance.mV[0] < max_attachment_span
+ && distance.mV[1] < max_attachment_span
+ && distance.mV[2] < max_attachment_span)
+ {
+ update_min_max(newMin,newMax,ext[0]);
+ update_min_max(newMin,newMax,ext[1]);
+ }
}
}
}
@@ -1535,11 +1418,9 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
LLVector3* intersection,
LLVector2* tex_coord,
LLVector3* normal,
- LLVector3* bi_normal
- )
+ LLVector3* bi_normal)
{
-
- if (mIsSelf && !gAgent.needsRenderAvatar() || !LLPipeline::sPickAvatar)
+ if ((isSelf() && !gAgent.needsRenderAvatar()) || !LLPipeline::sPickAvatar)
{
return FALSE;
}
@@ -1668,7 +1549,6 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent
return FALSE;
}
joint = (LLViewerJoint*)(&mCollisionVolumes[volume_num]);
-
joint->setName( info->mName );
}
@@ -1679,10 +1559,8 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent
}
joint->setPosition(info->mPos);
-
joint->setRotation(mayaQ(info->mRot.mV[VX], info->mRot.mV[VY],
info->mRot.mV[VZ], LLQuaternion::XYZ));
-
joint->setScale(info->mScale);
@@ -1698,7 +1576,7 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent
// setup children
LLVOAvatarBoneInfo::child_list_t::const_iterator iter;
- for (iter = info->mChildList.begin(); iter != info->mChildList.end(); iter++)
+ for (iter = info->mChildList.begin(); iter != info->mChildList.end(); ++iter)
{
LLVOAvatarBoneInfo *child_info = *iter;
if (!setupBone(child_info, joint, volume_num, joint_num))
@@ -1741,7 +1619,7 @@ BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info)
S32 current_joint_num = 0;
S32 current_volume_num = 0;
LLVOAvatarSkeletonInfo::bone_info_list_t::const_iterator iter;
- for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); iter++)
+ for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); ++iter)
{
LLVOAvatarBoneInfo *info = *iter;
if (!setupBone(info, NULL, current_volume_num, current_joint_num))
@@ -1751,21 +1629,14 @@ BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info)
}
}
- // add special-purpose "screen" joint
- if (mIsSelf)
- {
- mScreenp = new LLViewerJoint("mScreen", NULL);
- // for now, put screen at origin, as it is only used during special
- // HUD rendering mode
- F32 aspect = LLViewerCamera::getInstance()->getAspect();
- LLVector3 scale(1.f, aspect, 1.f);
- mScreenp->setScale(scale);
- mScreenp->setWorldPosition(LLVector3::zero);
- }
-
return TRUE;
}
+LLVOAvatar* LLVOAvatar::asAvatar()
+{
+ return this;
+}
+
//-----------------------------------------------------------------------------
// LLVOAvatar::startDefaultMotions()
//-----------------------------------------------------------------------------
@@ -1811,11 +1682,11 @@ void LLVOAvatar::buildCharacter()
// clear mesh data
//-------------------------------------------------------------------------
for (std::vector<LLViewerJoint*>::iterator jointIter = mMeshLOD.begin();
- jointIter != mMeshLOD.end(); jointIter++)
+ jointIter != mMeshLOD.end(); ++jointIter)
{
LLViewerJoint* joint = (LLViewerJoint*) *jointIter;
for (std::vector<LLViewerJointMesh*>::iterator meshIter = joint->mMeshParts.begin();
- meshIter != joint->mMeshParts.end(); meshIter++)
+ meshIter != joint->mMeshParts.end(); ++meshIter)
{
LLViewerJointMesh * mesh = (LLViewerJointMesh *) *meshIter;
mesh->setMesh(NULL);
@@ -1839,9 +1710,9 @@ void LLVOAvatar::buildCharacter()
// gPrintMessagesThisFrame = TRUE;
lldebugs << "Avatar load took " << timer.getElapsedTimeF32() << " seconds." << llendl;
- if ( ! status )
+ if (!status)
{
- if ( mIsSelf )
+ if (isSelf())
{
llerrs << "Unable to load user's avatar" << llendl;
}
@@ -1878,23 +1749,23 @@ void LLVOAvatar::buildCharacter()
// Make sure "well known" pointers exist
//-------------------------------------------------------------------------
if (!(mPelvisp &&
- mTorsop &&
- mChestp &&
- mNeckp &&
- mHeadp &&
- mSkullp &&
- mHipLeftp &&
- mHipRightp &&
- mKneeLeftp &&
- mKneeRightp &&
- mAnkleLeftp &&
- mAnkleRightp &&
- mFootLeftp &&
- mFootRightp &&
- mWristLeftp &&
- mWristRightp &&
- mEyeLeftp &&
- mEyeRightp))
+ mTorsop &&
+ mChestp &&
+ mNeckp &&
+ mHeadp &&
+ mSkullp &&
+ mHipLeftp &&
+ mHipRightp &&
+ mKneeLeftp &&
+ mKneeRightp &&
+ mAnkleLeftp &&
+ mAnkleRightp &&
+ mFootLeftp &&
+ mFootRightp &&
+ mWristLeftp &&
+ mWristRightp &&
+ mEyeLeftp &&
+ mEyeRightp))
{
llerrs << "Failed to create avatar." << llendl;
return;
@@ -1940,197 +1811,6 @@ void LLVOAvatar::buildCharacter()
mIsBuilt = TRUE;
stop_glerror();
- //-------------------------------------------------------------------------
- // build the attach and detach menus
- //-------------------------------------------------------------------------
- if (mIsSelf)
- {
- // *TODO: Translate
- gAttachBodyPartPieMenus[0] = NULL;
- gAttachBodyPartPieMenus[1] = new LLPieMenu(std::string("Right Arm >"));
- gAttachBodyPartPieMenus[2] = new LLPieMenu(std::string("Head >"));
- gAttachBodyPartPieMenus[3] = new LLPieMenu(std::string("Left Arm >"));
- gAttachBodyPartPieMenus[4] = NULL;
- gAttachBodyPartPieMenus[5] = new LLPieMenu(std::string("Left Leg >"));
- gAttachBodyPartPieMenus[6] = new LLPieMenu(std::string("Torso >"));
- gAttachBodyPartPieMenus[7] = new LLPieMenu(std::string("Right Leg >"));
-
- gDetachBodyPartPieMenus[0] = NULL;
- gDetachBodyPartPieMenus[1] = new LLPieMenu(std::string("Right Arm >"));
- gDetachBodyPartPieMenus[2] = new LLPieMenu(std::string("Head >"));
- gDetachBodyPartPieMenus[3] = new LLPieMenu(std::string("Left Arm >"));
- gDetachBodyPartPieMenus[4] = NULL;
- gDetachBodyPartPieMenus[5] = new LLPieMenu(std::string("Left Leg >"));
- gDetachBodyPartPieMenus[6] = new LLPieMenu(std::string("Torso >"));
- gDetachBodyPartPieMenus[7] = new LLPieMenu(std::string("Right Leg >"));
-
- for (S32 i = 0; i < 8; i++)
- {
- if (gAttachBodyPartPieMenus[i])
- {
- gAttachPieMenu->appendPieMenu( gAttachBodyPartPieMenus[i] );
- }
- else
- {
- BOOL attachment_found = FALSE;
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
- {
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getGroup() == i)
- {
- LLMenuItemCallGL* item;
- item = new LLMenuItemCallGL(attachment->getName(),
- NULL,
- object_selected_and_point_valid);
- item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", curiter->first);
-
- gAttachPieMenu->append(item);
-
- attachment_found = TRUE;
- break;
-
- }
- }
-
- if (!attachment_found)
- {
- gAttachPieMenu->appendSeparator();
- }
- }
-
- if (gDetachBodyPartPieMenus[i])
- {
- gDetachPieMenu->appendPieMenu( gDetachBodyPartPieMenus[i] );
- }
- else
- {
- BOOL attachment_found = FALSE;
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
- {
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getGroup() == i)
- {
- gDetachPieMenu->append(new LLMenuItemCallGL(attachment->getName(),
- &handle_detach_from_avatar, object_attached, attachment));
-
- attachment_found = TRUE;
- break;
- }
- }
-
- if (!attachment_found)
- {
- gDetachPieMenu->appendSeparator();
- }
- }
- }
-
- // add screen attachments
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
- {
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getGroup() == 8)
- {
- LLMenuItemCallGL* item;
- item = new LLMenuItemCallGL(attachment->getName(),
- NULL,
- object_selected_and_point_valid);
- item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", curiter->first);
- gAttachScreenPieMenu->append(item);
- gDetachScreenPieMenu->append(new LLMenuItemCallGL(attachment->getName(),
- &handle_detach_from_avatar, object_attached, attachment));
- }
- }
-
- for (S32 pass = 0; pass < 2; pass++)
- {
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
- {
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getIsHUDAttachment() != (pass == 1))
- {
- continue;
- }
- LLMenuItemCallGL* item = new LLMenuItemCallGL(attachment->getName(),
- NULL, &object_selected_and_point_valid,
- &attach_label, attachment);
- item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", curiter->first);
- gAttachSubMenu->append(item);
-
- gDetachSubMenu->append(new LLMenuItemCallGL(attachment->getName(),
- &handle_detach_from_avatar, object_attached, &detach_label, attachment));
-
- }
- if (pass == 0)
- {
- // put separator between non-hud and hud attachments
- gAttachSubMenu->appendSeparator();
- gDetachSubMenu->appendSeparator();
- }
- }
-
- for (S32 group = 0; group < 8; group++)
- {
- // skip over groups that don't have sub menus
- if (!gAttachBodyPartPieMenus[group] || !gDetachBodyPartPieMenus[group])
- {
- continue;
- }
-
- std::multimap<S32, S32> attachment_pie_menu_map;
-
- // gather up all attachment points assigned to this group, and throw into map sorted by pie slice number
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
- {
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if(attachment->getGroup() == group)
- {
- // use multimap to provide a partial order off of the pie slice key
- S32 pie_index = attachment->getPieSlice();
- attachment_pie_menu_map.insert(std::make_pair(pie_index, curiter->first));
- }
- }
-
- // add in requested order to pie menu, inserting separators as necessary
- S32 cur_pie_slice = 0;
- for (std::multimap<S32, S32>::iterator attach_it = attachment_pie_menu_map.begin();
- attach_it != attachment_pie_menu_map.end(); ++attach_it)
- {
- S32 requested_pie_slice = attach_it->first;
- S32 attach_index = attach_it->second;
- while (cur_pie_slice < requested_pie_slice)
- {
- gAttachBodyPartPieMenus[group]->appendSeparator();
- gDetachBodyPartPieMenus[group]->appendSeparator();
- cur_pie_slice++;
- }
-
- LLViewerJointAttachment* attachment = get_if_there(mAttachmentPoints, attach_index, (LLViewerJointAttachment*)NULL);
- if (attachment)
- {
- LLMenuItemCallGL* item = new LLMenuItemCallGL(attachment->getName(),
- NULL, object_selected_and_point_valid);
- gAttachBodyPartPieMenus[group]->append(item);
- item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", attach_index);
- gDetachBodyPartPieMenus[group]->append(new LLMenuItemCallGL(attachment->getName(),
- &handle_detach_from_avatar,
- object_attached, attachment));
- cur_pie_slice++;
- }
- }
- }
- }
-
mMeshValid = TRUE;
}
@@ -2151,7 +1831,8 @@ void LLVOAvatar::releaseMeshData()
// cleanup mesh data
for (std::vector<LLViewerJoint*>::iterator iter = mMeshLOD.begin();
- iter != mMeshLOD.end(); iter++)
+ iter != mMeshLOD.end();
+ ++iter)
{
LLViewerJoint* joint = (LLViewerJoint*) *iter;
joint->setValid(FALSE, TRUE);
@@ -2170,10 +1851,10 @@ void LLVOAvatar::releaseMeshData()
}
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
+ iter != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
+ LLViewerJointAttachment* attachment = iter->second;
if (!attachment->getIsHUDAttachment())
{
attachment->setAttachmentVisibility(FALSE);
@@ -2185,29 +1866,24 @@ void LLVOAvatar::releaseMeshData()
//-----------------------------------------------------------------------------
// restoreMeshData()
//-----------------------------------------------------------------------------
+// virtual
void LLVOAvatar::restoreMeshData()
{
+ llassert(!isSelf());
LLMemType mt(LLMemType::MTYPE_AVATAR);
//llinfos << "Restoring" << llendl;
mMeshValid = TRUE;
updateJointLODs();
- if (mIsSelf)
- {
- updateAttachmentVisibility(gAgent.getCameraMode());
- }
- else
+ for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ ++iter)
{
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
+ LLViewerJointAttachment* attachment = iter->second;
+ if (!attachment->getIsHUDAttachment())
{
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if (!attachment->getIsHUDAttachment())
- {
- attachment->setAttachmentVisibility(TRUE);
- }
+ attachment->setAttachmentVisibility(TRUE);
}
}
@@ -2393,9 +2069,9 @@ void LLVOAvatar::computeBodySize()
// LLVOAvatar::processUpdateMessage()
//------------------------------------------------------------------------
U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys,
- void **user_data,
- U32 block_num, const EObjectUpdateType update_type,
- LLDataPacker *dp)
+ void **user_data,
+ U32 block_num, const EObjectUpdateType update_type,
+ LLDataPacker *dp)
{
LLMemType mt(LLMemType::MTYPE_AVATAR);
@@ -2434,8 +2110,8 @@ S32 LLVOAvatar::setTETexture(const U8 te, const LLUUID& uuid)
}
}
-
-// setTEImage
+static LLFastTimer::DeclareTimer FTM_AVATAR_UPDATE("Update Avatar");
+static LLFastTimer::DeclareTimer FTM_JOINT_UPDATE("Update Joints");
//------------------------------------------------------------------------
// idleUpdate()
@@ -2443,7 +2119,7 @@ S32 LLVOAvatar::setTETexture(const U8 te, const LLUUID& uuid)
BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
{
LLMemType mt(LLMemType::MTYPE_AVATAR);
- LLFastTimer t(LLFastTimer::FTM_AVATAR_UPDATE);
+ LLFastTimer t(FTM_AVATAR_UPDATE);
if (isDead())
{
@@ -2462,7 +2138,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
// force asynchronous drawable update
if(mDrawable.notNull() && !gNoRender)
{
- LLFastTimer t(LLFastTimer::FTM_JOINT_UPDATE);
+ LLFastTimer t(FTM_JOINT_UPDATE);
if (mIsSitting && getParent())
{
@@ -2491,7 +2167,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
// set alpha flag depending on state
//--------------------------------------------------------------------
- if (mIsSelf)
+ if (isSelf())
{
LLViewerObject::idleUpdate(agent, world, time);
@@ -2515,8 +2191,8 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
// animate the character
// store off last frame's root position to be consistent with camera position
LLVector3 root_pos_last = mRoot.getWorldPosition();
- bool detailed_update = updateCharacter(agent);
- bool voice_enabled = gVoiceClient->getVoiceEnabled( mID ) && gVoiceClient->inProximalChannel();
+ BOOL detailed_update = updateCharacter(agent);
+ BOOL voice_enabled = gVoiceClient->getVoiceEnabled( mID ) && gVoiceClient->inProximalChannel();
if (gNoRender)
{
@@ -2526,10 +2202,14 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
idleUpdateVoiceVisualizer( voice_enabled );
idleUpdateMisc( detailed_update );
idleUpdateAppearanceAnimation();
- idleUpdateLipSync( voice_enabled );
- idleUpdateLoadingEffect();
- idleUpdateBelowWater(); // wind effect uses this
- idleUpdateWindEffect();
+ if (detailed_update)
+ {
+ idleUpdateLipSync( voice_enabled );
+ idleUpdateLoadingEffect();
+ idleUpdateBelowWater(); // wind effect uses this
+ idleUpdateWindEffect();
+ }
+
idleUpdateNameTag( root_pos_last );
idleUpdateRenderCost();
idleUpdateTractorBeam();
@@ -2539,13 +2219,13 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
{
// disable voice visualizer when in mouselook
- mVoiceVisualizer->setVoiceEnabled( voice_enabled && !(mIsSelf && gAgent.cameraMouselook()) );
+ mVoiceVisualizer->setVoiceEnabled( voice_enabled && !(isSelf() && gAgent.cameraMouselook()) );
if ( voice_enabled )
{
//----------------------------------------------------------------
// Only do gesture triggering for your own avatar, and only when you're in a proximal channel.
//----------------------------------------------------------------
- if( mIsSelf )
+ if( isSelf() )
{
//----------------------------------------------------------------------------------------
// The following takes the voice signal and uses that to trigger gesticulations.
@@ -2567,11 +2247,11 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
else { llinfos << "oops - CurrentGesticulationLevel can be only 0, 1, or 2" << llendl; }
// this is the call that Karl S. created for triggering gestures from within the code.
- gGestureManager.triggerAndReviseString( gestureString );
+ LLGestureManager::instance().triggerAndReviseString( gestureString );
}
}
- } //if( mIsSelf )
+ } //if( isSelf() )
//-----------------------------------------------------------------------------------------------------------------
// If the avatar is speaking, then the voice amplitude signal is passed to the voice visualizer.
@@ -2580,9 +2260,9 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
// Notice the calls to "gAwayTimer.reset()". This resets the timer that determines how long the avatar has been
// "away", so that the avatar doesn't lapse into away-mode (and slump over) while the user is still talking.
//-----------------------------------------------------------------------------------------------------------------
- if ( gVoiceClient->getIsSpeaking( mID ) )
+ if (gVoiceClient->getIsSpeaking( mID ))
{
- if ( ! mVoiceVisualizer->getCurrentlySpeaking() )
+ if (!mVoiceVisualizer->getCurrentlySpeaking())
{
mVoiceVisualizer->setStartSpeaking();
@@ -2591,7 +2271,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
mVoiceVisualizer->setSpeakingAmplitude( gVoiceClient->getCurrentPower( mID ) );
- if( mIsSelf )
+ if( isSelf() )
{
gAgent.clearAFK();
}
@@ -2624,6 +2304,8 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
}//if ( voiceEnabled )
}
+static LLFastTimer::DeclareTimer FTM_ATTACHMENT_UPDATE("Update Attachments");
+
void LLVOAvatar::idleUpdateMisc(bool detailed_update)
{
if (LLVOAvatar::sJointDebug)
@@ -2645,36 +2327,41 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)
// update attachments positions
if (detailed_update || !sUseImpostors)
{
- LLFastTimer t(LLFastTimer::FTM_ATTACHMENT_UPDATE);
+ LLFastTimer t(FTM_ATTACHMENT_UPDATE);
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
+ iter != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- LLViewerObject *attached_object = attachment->getObject();
-
- BOOL visibleAttachment = visible || (attached_object &&
- !(attached_object->mDrawable->getSpatialBridge() &&
- attached_object->mDrawable->getSpatialBridge()->getRadius() < 2.0));
+ LLViewerJointAttachment* attachment = iter->second;
- if (visibleAttachment && attached_object && !attached_object->isDead() && attachment->getValid())
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- // if selecting any attachments, update all of them as non-damped
- if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() && LLSelectMgr::getInstance()->getSelection()->isAttachment())
- {
- gPipeline.updateMoveNormalAsync(attached_object->mDrawable);
- }
- else
- {
- gPipeline.updateMoveDampedAsync(attached_object->mDrawable);
- }
-
- LLSpatialBridge* bridge = attached_object->mDrawable->getSpatialBridge();
- if (bridge)
+ LLViewerObject* attached_object = (*attachment_iter);
+ BOOL visibleAttachment = visible || (attached_object &&
+ !(attached_object->mDrawable->getSpatialBridge() &&
+ attached_object->mDrawable->getSpatialBridge()->getRadius() < 2.0));
+
+ if (visibleAttachment && attached_object && !attached_object->isDead() && attachment->getValid())
{
- gPipeline.updateMoveNormalAsync(bridge);
+ // if selecting any attachments, update all of them as non-damped
+ if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() && LLSelectMgr::getInstance()->getSelection()->isAttachment())
+ {
+ gPipeline.updateMoveNormalAsync(attached_object->mDrawable);
+ }
+ else
+ {
+ gPipeline.updateMoveDampedAsync(attached_object->mDrawable);
+ }
+
+ LLSpatialBridge* bridge = attached_object->mDrawable->getSpatialBridge();
+ if (bridge)
+ {
+ gPipeline.updateMoveNormalAsync(bridge);
+ }
+ attached_object->updateText();
}
- attached_object->updateText();
}
}
}
@@ -2695,7 +2382,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)
F32 old_angle = mImpostorAngle.mV[i];
F32 angle_diff = fabsf(cur_angle-old_angle);
- if (angle_diff > 3.14159f/512.f*distance*mUpdatePeriod)
+ if (angle_diff > F_PI/512.f*distance*mUpdatePeriod)
{
mNeedsImpostorUpdate = TRUE;
}
@@ -2747,39 +2434,31 @@ void LLVOAvatar::idleUpdateAppearanceAnimation()
{
if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE)
{
- param->stopAnimating(mAppearanceAnimSetByUser);
+ param->stopAnimating(FALSE);
}
}
updateVisualParams();
- if (mIsSelf)
+ if (isSelf())
{
gAgent.sendAgentSetAppearance();
}
}
else
{
- F32 blend_frac = calc_bouncy_animation(appearance_anim_time / APPEARANCE_MORPH_TIME);
- F32 last_blend_frac = calc_bouncy_animation(mLastAppearanceBlendTime / APPEARANCE_MORPH_TIME);
- F32 morph_amt;
- if (last_blend_frac == 1.f)
- {
- morph_amt = 1.f;
- }
- else
- {
- morph_amt = (blend_frac - last_blend_frac) / (1.f - last_blend_frac);
- }
-
+ F32 morph_amt = calcMorphAmount();
LLVisualParam *param;
- // animate only top level params
- for (param = getFirstVisualParam();
- param;
- param = getNextVisualParam())
+ if (!isSelf())
{
- if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE)
+ // animate only top level params for non-self avatars
+ for (param = getFirstVisualParam();
+ param;
+ param = getNextVisualParam())
{
- param->animate(morph_amt, mAppearanceAnimSetByUser);
+ if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE)
+ {
+ param->animate(morph_amt, FALSE);
+ }
}
}
@@ -2797,6 +2476,25 @@ void LLVOAvatar::idleUpdateAppearanceAnimation()
}
}
+F32 LLVOAvatar::calcMorphAmount()
+{
+ F32 appearance_anim_time = mAppearanceMorphTimer.getElapsedTimeF32();
+ F32 blend_frac = calc_bouncy_animation(appearance_anim_time / APPEARANCE_MORPH_TIME);
+ F32 last_blend_frac = calc_bouncy_animation(mLastAppearanceBlendTime / APPEARANCE_MORPH_TIME);
+
+ F32 morph_amt;
+ if (last_blend_frac == 1.f)
+ {
+ morph_amt = 1.f;
+ }
+ else
+ {
+ morph_amt = (blend_frac - last_blend_frac) / (1.f - last_blend_frac);
+ }
+
+ return morph_amt;
+}
+
void LLVOAvatar::idleUpdateLipSync(bool voice_enabled)
{
// Use the Lipsync_Ooh and Lipsync_Aah morphs for lip sync
@@ -2837,6 +2535,7 @@ void LLVOAvatar::idleUpdateLoadingEffect()
if (isFullyLoaded())
{
deleteParticleSource();
+ updateLOD();
}
else
{
@@ -2852,11 +2551,11 @@ void LLVOAvatar::idleUpdateLoadingEffect()
particle_parameters.mPartData.mStartColor = LLColor4(1, 1, 1, 0.5f);
particle_parameters.mPartData.mEndColor = LLColor4(1, 1, 1, 0.0f);
particle_parameters.mPartData.mStartScale.mV[VX] = 0.8f;
- LLViewerImage* cloud = gImageList.getImageFromFile("cloud-particle.j2c");
+ LLViewerTexture* cloud = LLViewerTextureManager::getFetchedTextureFromFile("cloud-particle.j2c");
particle_parameters.mPartImageID = cloud->getID();
particle_parameters.mMaxAge = 0.f;
particle_parameters.mPattern = LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE;
- particle_parameters.mInnerAngle = 3.14159f;
+ particle_parameters.mInnerAngle = F_PI;
particle_parameters.mOuterAngle = 0.f;
particle_parameters.mBurstRate = 0.02f;
particle_parameters.mBurstRadius = 0.0f;
@@ -2947,16 +2646,17 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
BOOL visible_avatar = isVisible() || mNeedsAnimUpdate;
BOOL visible_chat = gSavedSettings.getBOOL("UseChatBubbles") && (mChats.size() || mTyping);
BOOL render_name = visible_chat ||
- (visible_avatar &&
- ((sRenderName == RENDER_NAME_ALWAYS) ||
- (sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME)));
+ (visible_avatar &&
+ ((sRenderName == RENDER_NAME_ALWAYS) ||
+ (sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME)));
// If it's your own avatar, don't draw in mouselook, and don't
// draw if we're specifically hiding our own name.
- if (mIsSelf)
+ if (isSelf())
{
render_name = render_name
- && !gAgent.cameraMouselook()
- && (visible_chat || !gSavedSettings.getBOOL("RenderNameHideSelf"));
+ && !gAgent.cameraMouselook()
+ && (visible_chat || (gSavedSettings.getBOOL("RenderNameShowSelf")
+ && gSavedSettings.getS32("AvatarNameTagMode") ));
}
if ( render_name )
@@ -3013,7 +2713,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
new_name = TRUE;
}
- LLColor4 avatar_name_color = gColors.getColor( "AvatarNameColor" );
+ LLColor4 avatar_name_color = LLUIColorTable::instance().getColor( "AvatarNameColor" );
avatar_name_color.setAlpha(alpha);
mNameText->setColor(avatar_name_color);
@@ -3056,7 +2756,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
BOOL is_busy = mSignaledAnimations.find(ANIM_AGENT_BUSY) != mSignaledAnimations.end();
BOOL is_appearance = mSignaledAnimations.find(ANIM_AGENT_CUSTOMIZE) != mSignaledAnimations.end();
BOOL is_muted;
- if (mIsSelf)
+ if (isSelf())
{
is_muted = FALSE;
}
@@ -3101,7 +2801,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
line += " (";
if (is_away)
{
- line += "Away";
+ line += LLTrans::getString("AvatarAway");
need_comma = TRUE;
}
if (is_busy)
@@ -3110,7 +2810,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
{
line += ", ";
}
- line += "Busy";
+ line += LLTrans::getString("AvatarBusy");
need_comma = TRUE;
}
if (is_muted)
@@ -3119,7 +2819,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
{
line += ", ";
}
- line += "Muted";
+ line += LLTrans::getString("AvatarMuted");
need_comma = TRUE;
}
line += ")";
@@ -3127,7 +2827,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
if (is_appearance)
{
line += "\n";
- line += "(Editing Appearance)";
+ line += LLTrans::getString("AvatarEditingAppearance");
}
mNameAway = is_away;
mNameBusy = is_busy;
@@ -3155,7 +2855,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
std::deque<LLChat>::iterator chat_iter = mChats.begin();
mNameText->clearString();
- LLColor4 new_chat = gColors.getColor( "AvatarNameColor" );
+ LLColor4 new_chat = LLUIColorTable::instance().getColor( "AvatarNameColor" );
LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f);
LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f);
if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES)
@@ -3169,15 +2869,15 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
LLFontGL::StyleFlags style;
switch(chat_iter->mChatType)
{
- case CHAT_TYPE_WHISPER:
- style = LLFontGL::ITALIC;
- break;
- case CHAT_TYPE_SHOUT:
- style = LLFontGL::BOLD;
- break;
- default:
- style = LLFontGL::NORMAL;
- break;
+ case CHAT_TYPE_WHISPER:
+ style = LLFontGL::ITALIC;
+ break;
+ case CHAT_TYPE_SHOUT:
+ style = LLFontGL::BOLD;
+ break;
+ default:
+ style = LLFontGL::NORMAL;
+ break;
}
if (chat_fade_amt < 1.f)
{
@@ -3202,15 +2902,15 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1;
switch(dot_count)
{
- case 1:
- mNameText->addLine(".", new_chat);
- break;
- case 2:
- mNameText->addLine("..", new_chat);
- break;
- case 3:
- mNameText->addLine("...", new_chat);
- break;
+ case 1:
+ mNameText->addLine(".", new_chat);
+ break;
+ case 2:
+ mNameText->addLine("..", new_chat);
+ break;
+ case 3:
+ mNameText->addLine("...", new_chat);
+ break;
}
}
@@ -3244,75 +2944,12 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
}
}
+//--------------------------------------------------------------------
+// draw tractor beam when editing objects
+//--------------------------------------------------------------------
+// virtual
void LLVOAvatar::idleUpdateTractorBeam()
{
- //--------------------------------------------------------------------
- // draw tractor beam when editing objects
- //--------------------------------------------------------------------
- if (!mIsSelf)
- {
- return;
- }
-
- // This is only done for yourself (maybe it should be in the agent?)
- if (!needsRenderBeam() || !mIsBuilt)
- {
- mBeam = NULL;
- }
- else if (!mBeam || mBeam->isDead())
- {
- // VEFFECT: Tractor Beam
- mBeam = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM);
- mBeam->setColor(LLColor4U(gAgent.getEffectColor()));
- mBeam->setSourceObject(this);
- mBeamTimer.reset();
- }
-
- if (!mBeam.isNull())
- {
- LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
-
- if (gAgent.mPointAt.notNull())
- {
- // get point from pointat effect
- mBeam->setPositionGlobal(gAgent.mPointAt->getPointAtPosGlobal());
- mBeam->triggerLocal();
- }
- else if (selection->getFirstRootObject() &&
- selection->getSelectType() != SELECT_TYPE_HUD)
- {
- LLViewerObject* objectp = selection->getFirstRootObject();
- mBeam->setTargetObject(objectp);
- }
- else
- {
- mBeam->setTargetObject(NULL);
- LLTool *tool = LLToolMgr::getInstance()->getCurrentTool();
- if (tool->isEditing())
- {
- if (tool->getEditingObject())
- {
- mBeam->setTargetObject(tool->getEditingObject());
- }
- else
- {
- mBeam->setPositionGlobal(tool->getEditingPointGlobal());
- }
- }
- else
- {
- const LLPickInfo& pick = gViewerWindow->getLastPick();
- mBeam->setPositionGlobal(pick.mPosGlobal);
- }
-
- }
- if (mBeamTimer.getElapsedTimeF32() > 0.25f)
- {
- mBeam->setColor(LLColor4U(gAgent.getEffectColor()));
- mBeam->setNeedsSendToSim(TRUE);
- mBeamTimer.reset();
- }
- }
}
void LLVOAvatar::idleUpdateBelowWater()
@@ -3344,16 +2981,6 @@ void LLVOAvatar::slamPosition()
BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
{
LLMemType mt(LLMemType::MTYPE_AVATAR);
- // update screen joint size
-
- if (mScreenp)
- {
- F32 aspect = LLViewerCamera::getInstance()->getAspect();
- LLVector3 scale(1.f, aspect, 1.f);
- mScreenp->setScale(scale);
- mScreenp->updateWorldMatrixChildren();
- resetHUDAttachments();
- }
// clear debug text
mDebugText.clear();
@@ -3386,7 +3013,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
if (gNoRender)
{
// Hack if we're running drones...
- if (mIsSelf)
+ if (isSelf())
{
gAgent.setPositionAgent(getPositionAgent());
}
@@ -3415,7 +3042,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
// the rest should only be done occasionally for far away avatars
//--------------------------------------------------------------------
- if (visible && !mIsSelf && !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter)
+ if (visible && !isSelf() && !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter)
{
F32 impostor_area = 256.f*512.f*(8.125f - LLVOAvatar::sLODFactor*8.f);
if (LLMuteList::getInstance()->isMuted(getID()))
@@ -3452,12 +3079,12 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
if (!visible)
{
- updateMotions(LLCharacter::HIDDEN_UPDATE);
+ //updateMotions(LLCharacter::HIDDEN_UPDATE);
return FALSE;
}
// change animation time quanta based on avatar render load
- if (!mIsSelf && !mIsDummy)
+ if (!isSelf() && !mIsDummy)
{
F32 time_quantum = clamp_rescale((F32)sInstances.size(), 10.f, 35.f, 0.f, 0.25f);
F32 pixel_area_scale = clamp_rescale(mPixelArea, 100, 5000, 1.f, 0.f);
@@ -3526,7 +3153,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
LLVector3d root_pos;
LLVector3d ground_under_pelvis;
- if (mIsSelf)
+ if (isSelf())
{
gAgent.setPositionAgent(getRenderPosition());
}
@@ -3535,8 +3162,8 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
resolveHeightGlobal(root_pos, ground_under_pelvis, normal);
F32 foot_to_ground = (F32) (root_pos.mdV[VZ] - mPelvisToFoot - ground_under_pelvis.mdV[VZ]);
- BOOL in_air = ( (!LLWorld::getInstance()->getRegionFromPosGlobal(ground_under_pelvis)) ||
- foot_to_ground > FOOT_GROUND_COLLISION_TOLERANCE);
+ BOOL in_air = ((!LLWorld::getInstance()->getRegionFromPosGlobal(ground_under_pelvis)) ||
+ foot_to_ground > FOOT_GROUND_COLLISION_TOLERANCE);
if (in_air && !mInAir)
{
@@ -3571,7 +3198,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
// more than 90 from the view, if necessary, flip the velocity vector.
LLVector3 primDir;
- if (mIsSelf)
+ if (isSelf())
{
primDir = agent.getAtAxis() - projected_vec(agent.getAtAxis(), agent.getReferenceUpVector());
primDir.normalize();
@@ -3591,7 +3218,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
}
}
LLVector3 fwdDir = lerp(primDir, velDir, clamp_rescale(speed, 0.5f, 2.0f, 0.0f, 1.0f));
- if (mIsSelf && gAgent.cameraMouselook())
+ if (isSelf() && gAgent.cameraMouselook())
{
// make sure fwdDir stays in same general direction as primdir
if (gAgent.getFlying())
@@ -3619,18 +3246,10 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
F32 root_roll, root_pitch, root_yaw;
root_rotation.getEulerAngles(&root_roll, &root_pitch, &root_yaw);
- if (sDebugAvatarRotation)
- {
- llinfos << "root_roll " << RAD_TO_DEG * root_roll
- << " root_pitch " << RAD_TO_DEG * root_pitch
- << " root_yaw " << RAD_TO_DEG * root_yaw
- << llendl;
- }
-
// When moving very slow, the pelvis is allowed to deviate from the
// forward direction to allow it to hold it's position while the torso
// and head turn. Once in motion, it must conform however.
- BOOL self_in_mouselook = mIsSelf && gAgent.cameraMouselook();
+ BOOL self_in_mouselook = isSelf() && gAgent.cameraMouselook();
LLVector3 pelvisDir( mRoot.getWorldMatrix().getFwdRow4().mV );
F32 pelvis_rot_threshold = clamp_rescale(speed, 0.1f, 1.0f, PELVIS_ROT_THRESHOLD_SLOW, PELVIS_ROT_THRESHOLD_FAST);
@@ -3647,7 +3266,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
// from the forward direction, but if roll or pitch are off even
// a little bit we need to correct the rotation.
if(root_roll < 1.f * DEG_TO_RAD
- && root_pitch < 5.f * DEG_TO_RAD)
+ && root_pitch < 5.f * DEG_TO_RAD)
{
// smaller correction vector means pelvis follows prim direction more closely
if (!mTurning && angle > pelvis_rot_threshold*0.75f)
@@ -3681,7 +3300,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
fwdDir = leftDir % upDir;
LLQuaternion wQv( fwdDir, leftDir, upDir );
- if (mIsSelf && mTurning)
+ if (isSelf() && mTurning)
{
if ((fwdDir % pelvisDir) * upDir > 0.f)
{
@@ -3890,9 +3509,9 @@ void LLVOAvatar::updateVisibility()
visible = FALSE;
}
- if( mIsSelf )
+ if(isSelf())
{
- if( !gAgent.areWearablesLoaded())
+ if (!gAgentWearables.areWearablesLoaded())
{
visible = FALSE;
}
@@ -3948,19 +3567,25 @@ void LLVOAvatar::updateVisibility()
/*llinfos << "SPA: " << sel_pos_agent << llendl;
llinfos << "WPA: " << wrist_right_pos_agent << llendl;*/
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
+ iter != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getObject())
+ LLViewerJointAttachment* attachment = iter->second;
+
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- if(attachment->getObject()->mDrawable->isVisible())
- {
- llinfos << attachment->getName() << " visible" << llendl;
- }
- else
+ if (LLViewerObject *attached_object = (*attachment_iter))
{
- llinfos << attachment->getName() << " not visible at " << mDrawable->getWorldPosition() << " and radius " << mDrawable->getRadius() << llendl;
+ if(attached_object->mDrawable->isVisible())
+ {
+ llinfos << attachment->getName() << " visible" << llendl;
+ }
+ else
+ {
+ llinfos << attachment->getName() << " not visible at " << mDrawable->getWorldPosition() << " and radius " << mDrawable->getRadius() << llendl;
+ }
}
}
}
@@ -3997,25 +3622,14 @@ void LLVOAvatar::updateVisibility()
mVisible = visible;
}
-//------------------------------------------------------------------------
-// needsRenderBeam()
-//------------------------------------------------------------------------
-BOOL LLVOAvatar::needsRenderBeam()
+// private
+bool LLVOAvatar::shouldAlphaMask()
{
- if (gNoRender)
- {
- return FALSE;
- }
- LLTool *tool = LLToolMgr::getInstance()->getCurrentTool();
+ const bool should_alpha_mask = mSupportsAlphaLayers && !LLDrawPoolAlpha::sShowDebugAlpha // Don't alpha mask if "Highlight Transparent" checked
+ && !LLDrawPoolAvatar::sSkipTransparent;
+
+ return should_alpha_mask;
- BOOL is_touching_or_grabbing = (tool == LLToolGrab::getInstance() && LLToolGrab::getInstance()->isEditing());
- if (LLToolGrab::getInstance()->getEditingObject() &&
- LLToolGrab::getInstance()->getEditingObject()->isAttachment())
- {
- // don't render selection beam on hud objects
- is_touching_or_grabbing = FALSE;
- }
- return is_touching_or_grabbing || (mState & AGENT_STATE_EDITING && LLSelectMgr::getInstance()->shouldShowSelection());
}
//-----------------------------------------------------------------------------
@@ -4051,7 +3665,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
mMeshLOD[MESH_ID_SKIRT]->updateJointGeometry();
}
- if (!mIsSelf || gAgent.needsRenderHead() || LLPipeline::sShadowRender)
+ if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender)
{
mMeshLOD[MESH_ID_EYELASH]->updateJointGeometry();
mMeshLOD[MESH_ID_HEAD]->updateJointGeometry();
@@ -4101,7 +3715,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
return num_indices;
}
- if (mIsSelf && !gAgent.needsRenderAvatar())
+ if (isSelf() && !gAgent.needsRenderAvatar())
{
return num_indices;
}
@@ -4151,17 +3765,10 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
if (pass == AVATAR_RENDER_PASS_SINGLE)
{
- const bool should_alpha_mask = mHasBakedHair && isTextureDefined(TEX_HEAD_BAKED) && isTextureDefined(TEX_UPPER_BAKED)
- && isTextureDefined(TEX_LOWER_BAKED)
- && mBakedTextureData[BAKED_HEAD].mIsLoaded
- && mBakedTextureData[BAKED_UPPER].mIsLoaded && mBakedTextureData[BAKED_LOWER].mIsLoaded
- && mBakedTextureData[BAKED_HEAD].mIsUsed
- && mBakedTextureData[BAKED_UPPER].mIsUsed && mBakedTextureData[BAKED_LOWER].mIsUsed
- && !LLDrawPoolAlpha::sShowDebugAlpha // Don't alpha mask if "Highlight Transparent" checked
- && !(isSelf() && gAgent.cameraCustomizeAvatar()); // don't alpha mask if in customize mode
+ bool should_alpha_mask = shouldAlphaMask();
LLGLState test(GL_ALPHA_TEST, should_alpha_mask);
-
+
if (should_alpha_mask)
{
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
@@ -4170,7 +3777,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
BOOL first_pass = TRUE;
if (!LLDrawPoolAvatar::sSkipOpaque)
{
- if (!mIsSelf || gAgent.needsRenderHead() || LLPipeline::sShadowRender)
+ if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender)
{
if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy)
{
@@ -4221,7 +3828,7 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass)
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
}
- if (!mIsSelf || gAgent.needsRenderHead() || LLPipeline::sShadowRender)
+ if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender)
{
if (LLPipeline::sImpostorRender)
{
@@ -4235,7 +3842,7 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass)
}
// Can't test for baked hair being defined, since that won't always be the case (not all viewers send baked hair)
// TODO: 1.25 will be able to switch this logic back to calling isTextureVisible();
- if (getTEImage(TEX_HAIR_BAKED)->getID() != IMG_INVISIBLE || LLDrawPoolAlpha::sShowDebugAlpha)
+ if (getImage(TEX_HAIR_BAKED, 0)->getID() != IMG_INVISIBLE || LLDrawPoolAlpha::sShowDebugAlpha)
{
num_indices += mMeshLOD[MESH_ID_HAIR]->render(mAdjustedPixelArea, first_pass, mIsDummy);
first_pass = FALSE;
@@ -4261,7 +3868,7 @@ U32 LLVOAvatar::renderRigid()
return 0;
}
- if (mIsSelf && (!gAgent.needsRenderAvatar() || !gAgent.needsRenderHead()))
+ if (isSelf() && (!gAgent.needsRenderAvatar() || !gAgent.needsRenderHead()))
{
return 0;
}
@@ -4271,26 +3878,21 @@ U32 LLVOAvatar::renderRigid()
return 0;
}
- if (isTextureVisible(TEX_EYES_BAKED) || mIsDummy)
- {
- // If the meshes need to be drawn, enable alpha masking but not blending
- bool should_alpha_mask = mHasBakedHair
- && mBakedTextureData[BAKED_EYES].mIsLoaded
- && mBakedTextureData[BAKED_EYES].mIsUsed
- && !(isSelf() && gAgent.cameraCustomizeAvatar());
+ bool should_alpha_mask = shouldAlphaMask();
+ LLGLState test(GL_ALPHA_TEST, should_alpha_mask);
- LLGLState test(GL_ALPHA_TEST, should_alpha_mask);
-
- if (should_alpha_mask)
- {
- gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
- }
+ if (should_alpha_mask)
+ {
+ gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
+ }
+ if (isTextureVisible(TEX_EYES_BAKED) || mIsDummy)
+ {
num_indices += mMeshLOD[MESH_ID_EYEBALL_LEFT]->render(mAdjustedPixelArea, TRUE, mIsDummy);
num_indices += mMeshLOD[MESH_ID_EYEBALL_RIGHT]->render(mAdjustedPixelArea, TRUE, mIsDummy);
-
- gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
}
+
+ gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
return num_indices;
}
@@ -4304,7 +3906,7 @@ U32 LLVOAvatar::renderFootShadows()
return 0;
}
- if (mIsSelf && (!gAgent.needsRenderAvatar() || !gAgent.needsRenderHead()))
+ if (isSelf() && (!gAgent.needsRenderAvatar() || !gAgent.needsRenderHead()))
{
return 0;
}
@@ -4316,7 +3918,7 @@ U32 LLVOAvatar::renderFootShadows()
// Don't render foot shadows if your lower body is completely invisible.
// (non-humanoid avatars rule!)
- if (! isTextureVisible(TEX_LOWER_BAKED))
+ if (!isTextureVisible(TEX_LOWER_BAKED))
{
return 0;
}
@@ -4334,7 +3936,7 @@ U32 LLVOAvatar::renderFootShadows()
LLGLDepthTest test(GL_TRUE, GL_FALSE);
//render foot shadows
LLGLEnable blend(GL_BLEND);
- gGL.getTexUnit(0)->bind(mShadowImagep.get());
+ gGL.getTexUnit(0)->bind(mShadowImagep, TRUE);
glColor4fv(mShadow0Facep->getRenderColor().mV);
mShadow0Facep->renderIndexed(foot_mask);
glColor4fv(mShadow1Facep->getRenderColor().mV);
@@ -4343,7 +3945,7 @@ U32 LLVOAvatar::renderFootShadows()
return num_indices;
}
-U32 LLVOAvatar::renderImpostor(LLColor4U color)
+U32 LLVOAvatar::renderImpostor(LLColor4U color, S32 diffuse_channel)
{
if (!mImpostor.isComplete())
{
@@ -4363,7 +3965,7 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color)
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f);
gGL.color4ubv(color.mV);
- gGL.getTexUnit(0)->bind(&mImpostor);
+ gGL.getTexUnit(diffuse_channel)->bind(&mImpostor);
gGL.begin(LLRender::QUADS);
gGL.texCoord2f(0,0);
gGL.vertex3fv((pos+left-up).mV);
@@ -4382,7 +3984,7 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color)
//------------------------------------------------------------------------
// LLVOAvatar::updateTextures()
//------------------------------------------------------------------------
-void LLVOAvatar::updateTextures(LLAgent &agent)
+void LLVOAvatar::updateTextures()
{
BOOL render_avatar = TRUE;
@@ -4391,7 +3993,7 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
return;
}
- if( mIsSelf )
+ if( isSelf() )
{
render_avatar = TRUE;
}
@@ -4400,97 +4002,61 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
render_avatar = isVisible() && !mCulled;
}
- std::vector<bool> layer_baked;
- for (U32 i = 0; i < mBakedTextureData.size(); i++)
+ std::vector<BOOL> layer_baked;
+ // GL NOT ACTIVE HERE - *TODO
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
{
- layer_baked.push_back(isTextureDefined(mBakedTextureData[i].mTextureIndex));
+ layer_baked.push_back(isTextureDefined(mBakedTextureDatas[i].mTextureIndex));
// bind the texture so that they'll be decoded slightly
// inefficient, we can short-circuit this if we have to
- if( render_avatar && !gGLManager.mIsDisabled )
+ if (render_avatar && !gGLManager.mIsDisabled)
{
- if (layer_baked[i] && !mBakedTextureData[i].mIsLoaded)
+ if (layer_baked[i] && !mBakedTextureDatas[i].mIsLoaded)
{
- gGL.getTexUnit(0)->bind(getTEImage( mBakedTextureData[i].mTextureIndex ));
+ gGL.getTexUnit(0)->bind(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ));
}
}
}
- /*
- // JAMESDEBUG
- if (mIsSelf)
+ mMaxPixelArea = 0.f;
+ mMinPixelArea = 99999999.f;
+ mHasGrey = FALSE; // debug
+ for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++)
{
- S32 null_count = 0;
- S32 default_count = 0;
- for (U32 i = 0; i < getNumTEs(); i++)
+ EWearableType wearable_type = LLVOAvatarDictionary::getTEWearableType((ETextureIndex)texture_index);
+ U32 num_wearables = gAgentWearables.getWearableCount(wearable_type);
+ const LLTextureEntry *te = getTE(texture_index);
+ const F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT);
+ LLViewerFetchedTexture *imagep = NULL;
+ for (U32 wearable_index = 0; wearable_index < num_wearables; wearable_index++)
{
- const LLTextureEntry* te = getTE(i);
- if (te)
+ imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index, wearable_index), TRUE);
+ if (imagep)
{
- if (te->getID() == LLUUID::null)
- {
- null_count++;
- }
- else if (te->getID() == IMG_DEFAULT_AVATAR)
+ const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)texture_index);
+ const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
+ if (texture_dict->mIsLocalTexture)
{
- default_count++;
+ addLocalTextureStats((ETextureIndex)texture_index, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]);
}
}
}
- llinfos << "JAMESDEBUG my avatar TE null " << null_count << " default " << default_count << llendl;
- }
- */
-
- mMaxPixelArea = 0.f;
- mMinPixelArea = 99999999.f;
- mHasGrey = FALSE; // debug
- for (U32 index = 0; index < getNumTEs(); index++)
- {
- LLViewerImage *imagep = getTEImage(index);
- if (imagep)
- {
- // Debugging code - maybe non-self avatars are downloading textures?
- //llinfos << "avatar self " << mIsSelf << " tex " << i
- // << " decode " << imagep->getDecodePriority()
- // << " boost " << boost_avatar
- // << " size " << imagep->getWidth() << "x" << imagep->getHeight()
- // << " discard " << imagep->getDiscardLevel()
- // << " desired " << imagep->getDesiredDiscardLevel()
- // << llendl;
-
- const LLTextureEntry *te = getTE(index);
- F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT);
- S32 boost_level = mIsSelf ? LLViewerImage::BOOST_AVATAR_BAKED_SELF : LLViewerImage::BOOST_AVATAR_BAKED;
-
+ if (isIndexBakedTexture((ETextureIndex) texture_index))
+ {
+ const S32 boost_level = getAvatarBakedBoostLevel();
+ imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index,0), TRUE);
// Spam if this is a baked texture, not set to default image, without valid host info
- if (isIndexBakedTexture((ETextureIndex)index)
+ if (isIndexBakedTexture((ETextureIndex)texture_index)
&& imagep->getID() != IMG_DEFAULT_AVATAR
&& !imagep->getTargetHost().isOk())
{
LL_WARNS_ONCE("Texture") << "LLVOAvatar::updateTextures No host for texture "
- << imagep->getID() << " for avatar "
- << (mIsSelf ? "<myself>" : getID().asString())
- << " on host " << getRegion()->getHost() << llendl;
+ << imagep->getID() << " for avatar "
+ << (isSelf() ? "<myself>" : getID().asString())
+ << " on host " << getRegion()->getHost() << llendl;
}
- /* switch(index)
- case TEX_HEAD_BODYPAINT:
- addLocalTextureStats( LOCTEX_HEAD_BODYPAINT, imagep, texel_area_ratio, render_avatar, head_baked ); */
- const LLVOAvatarDictionary::TextureDictionaryEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)index);
- if (texture_dict->mIsUsedByBakedTexture)
- {
- const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
- if (texture_dict->mIsLocalTexture)
- {
- addLocalTextureStats((ETextureIndex)index, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]);
- }
- else if (texture_dict->mIsBakedTexture)
- {
- if (layer_baked[baked_index])
- {
- addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );
- }
- }
- }
+ addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );
}
}
@@ -4506,42 +4072,15 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
}
-void LLVOAvatar::addLocalTextureStats( ETextureIndex idx, LLViewerImage* imagep,
- F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked )
+void LLVOAvatar::addLocalTextureStats( ETextureIndex idx, LLViewerFetchedTexture* imagep,
+ F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked, U32 index )
{
- if (!isIndexLocalTexture(idx)) return;
-
- if (!covered_by_baked && render_avatar) // render_avatar is always true if mIsSelf
- {
- if (getLocalTextureID(idx) != IMG_DEFAULT_AVATAR)
- {
- F32 desired_pixels;
- if( mIsSelf )
- {
- desired_pixels = llmin(mPixelArea, (F32)TEX_IMAGE_AREA_SELF );
- imagep->setBoostLevel(LLViewerImage::BOOST_AVATAR_SELF);
- }
- else
- {
- desired_pixels = llmin(mPixelArea, (F32)TEX_IMAGE_AREA_OTHER );
- imagep->setBoostLevel(LLViewerImage::BOOST_AVATAR);
- }
- imagep->addTextureStats( desired_pixels / texel_area_ratio );
- if (imagep->getDiscardLevel() < 0)
- {
- mHasGrey = TRUE; // for statistics gathering
- }
- }
- else
- {
- // texture asset is missing
- mHasGrey = TRUE; // for statistics gathering
- }
- }
+ // No local texture stats for non-self avatars
+ return;
}
-void LLVOAvatar::addBakedTextureStats( LLViewerImage* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level)
+void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level)
{
mMaxPixelArea = llmax(pixel_area, mMaxPixelArea);
mMinPixelArea = llmin(pixel_area, mMinPixelArea);
@@ -4549,6 +4088,29 @@ void LLVOAvatar::addBakedTextureStats( LLViewerImage* imagep, F32 pixel_area, F3
imagep->setBoostLevel(boost_level);
}
+//virtual
+void LLVOAvatar::setImage(const U8 te, LLViewerTexture *imagep, const U32 index)
+{
+ setTEImage(te, imagep);
+}
+
+//virtual
+LLViewerTexture* LLVOAvatar::getImage(const U8 te, const U32 index) const
+{
+ return getTEImage(te);
+}
+//virtual
+const LLTextureEntry* LLVOAvatar::getTexEntry(const U8 te_num) const
+{
+ return getTE(te_num);
+}
+
+//virtual
+void LLVOAvatar::setTexEntry(const U8 index, const LLTextureEntry &te)
+{
+ setTE(index, te);
+}
+
//-----------------------------------------------------------------------------
// resolveHeight()
//-----------------------------------------------------------------------------
@@ -4690,7 +4252,7 @@ void LLVOAvatar::processAnimationStateChanges()
}
// clear source information for animations which have been stopped
- if (mIsSelf)
+ if (isSelf())
{
AnimSourceIterator source_it = mAnimationSources.begin();
@@ -4732,7 +4294,7 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL
{
// RN: uncomment this to play on typing sound at fixed volume once sound engine is fixed
// to support both spatialized and non-spatialized instances of the same sound
- //if (mIsSelf)
+ //if (isSelf())
//{
// gAudiop->triggerSound(LLUUID(gSavedSettings.getString("UISndTyping")), 1.0f, LLAudioEngine::AUDIO_TYPE_UI);
//}
@@ -4746,7 +4308,7 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL
}
else if (anim_id == ANIM_AGENT_SIT_GROUND_CONSTRAINED)
{
- mIsSitting = TRUE;
+ sitDown(TRUE);
}
@@ -4763,7 +4325,7 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL
{
if (anim_id == ANIM_AGENT_SIT_GROUND_CONSTRAINED)
{
- mIsSitting = FALSE;
+ sitDown(FALSE);
}
stopMotion(anim_id);
result = TRUE;
@@ -4775,7 +4337,7 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL
//-----------------------------------------------------------------------------
// isAnyAnimationSignaled()
//-----------------------------------------------------------------------------
-BOOL LLVOAvatar::isAnyAnimationSignaled(const LLUUID *anim_array, const S32 num_anims)
+BOOL LLVOAvatar::isAnyAnimationSignaled(const LLUUID *anim_array, const S32 num_anims) const
{
for (S32 i = 0; i < num_anims; i++)
{
@@ -4818,7 +4380,7 @@ BOOL LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset)
}
}
- if (mIsSelf && id == ANIM_AGENT_AWAY)
+ if (isSelf() && id == ANIM_AGENT_AWAY)
{
gAgent.setAFK();
}
@@ -4831,7 +4393,7 @@ BOOL LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset)
//-----------------------------------------------------------------------------
BOOL LLVOAvatar::stopMotion(const LLUUID& id, BOOL stop_immediate)
{
- if (mIsSelf)
+ if (isSelf())
{
gAgent.onAnimStop(id);
}
@@ -4851,25 +4413,9 @@ BOOL LLVOAvatar::stopMotion(const LLUUID& id, BOOL stop_immediate)
//-----------------------------------------------------------------------------
// stopMotionFromSource()
//-----------------------------------------------------------------------------
+// virtual
void LLVOAvatar::stopMotionFromSource(const LLUUID& source_id)
{
- if (!mIsSelf)
- {
- return;
- }
- AnimSourceIterator motion_it;
-
- for(motion_it = mAnimationSources.find(source_id); motion_it != mAnimationSources.end();)
- {
- gAgent.sendAnimationRequest( motion_it->second, ANIM_REQUEST_STOP );
- mAnimationSources.erase(motion_it++);
- }
-
- LLViewerObject* object = gObjectList.findObject(source_id);
- if (object)
- {
- object->mFlags &= ~FLAGS_ANIM_SOURCE;
- }
}
//-----------------------------------------------------------------------------
@@ -4917,7 +4463,7 @@ S32 LLVOAvatar::getCollisionVolumeID(std::string &name)
//-----------------------------------------------------------------------------
// addDebugText()
//-----------------------------------------------------------------------------
- void LLVOAvatar::addDebugText(const std::string& text)
+void LLVOAvatar::addDebugText(const std::string& text)
{
mDebugText.append(1, '\n');
mDebugText.append(text);
@@ -4937,15 +4483,7 @@ const LLUUID& LLVOAvatar::getID()
// RN: avatar joints are multi-rooted to include screen-based attachments
LLJoint *LLVOAvatar::getJoint( const std::string &name )
{
- LLJoint* jointp = NULL;
- if (mScreenp)
- {
- jointp = mScreenp->findJoint(name);
- }
- if (!jointp)
- {
- jointp = mRoot.findJoint(name);
- }
+ LLJoint* jointp = mRoot.findJoint(name);
return jointp;
}
@@ -5075,8 +4613,7 @@ LLVector3 LLVOAvatar::getPosAgentFromGlobal(const LLVector3d &position)
//-----------------------------------------------------------------------------
BOOL LLVOAvatar::allocateCharacterJoints( U32 num )
{
- delete [] mSkeleton;
- mSkeleton = NULL;
+ deleteAndClearArray(mSkeleton);
mNumJoints = 0;
mSkeleton = new LLViewerJoint[num];
@@ -5100,8 +4637,7 @@ BOOL LLVOAvatar::allocateCharacterJoints( U32 num )
//-----------------------------------------------------------------------------
BOOL LLVOAvatar::allocateCollisionVolumes( U32 num )
{
- delete [] mCollisionVolumes;
- mCollisionVolumes = NULL;
+ deleteAndClearArray(mCollisionVolumes);
mNumCollisionVolumes = 0;
mCollisionVolumes = new LLViewerJointCollisionVolume[num];
@@ -5131,22 +4667,20 @@ LLJoint *LLVOAvatar::getCharacterJoint( U32 num )
//-----------------------------------------------------------------------------
// requestStopMotion()
//-----------------------------------------------------------------------------
+// virtual
void LLVOAvatar::requestStopMotion( LLMotion* motion )
{
// Only agent avatars should handle the stop motion notifications.
- if ( mIsSelf )
- {
- // Notify agent that motion has stopped
- gAgent.requestStopMotion( motion );
- }
}
//-----------------------------------------------------------------------------
// loadAvatar()
//-----------------------------------------------------------------------------
+static LLFastTimer::DeclareTimer FTM_LOAD_AVATAR("Load Avatar");
+
BOOL LLVOAvatar::loadAvatar()
{
-// LLFastTimer t(LLFastTimer::FTM_LOAD_AVATAR);
+// LLFastTimer t(FTM_LOAD_AVATAR);
// avatar_skeleton.xml
if( !buildSkeleton(sAvatarSkeletonInfo) )
@@ -5217,64 +4751,76 @@ BOOL LLVOAvatar::loadAvatar()
if (sAvatarXmlInfo->mLayerInfoList.empty())
{
llwarns << "avatar file: missing <layer_set> node" << llendl;
+ return FALSE;
}
- else
+
+ if (sAvatarXmlInfo->mMorphMaskInfoList.empty())
+ {
+ llwarns << "avatar file: missing <morph_masks> node" << llendl;
+ return FALSE;
+ }
+
+ // avatar_lad.xml : <morph_masks>
+ for (LLVOAvatarXmlInfo::morph_info_list_t::iterator iter = sAvatarXmlInfo->mMorphMaskInfoList.begin();
+ iter != sAvatarXmlInfo->mMorphMaskInfoList.end();
+ ++iter)
{
- LLVOAvatarXmlInfo::layer_info_list_t::iterator iter;
- for (iter = sAvatarXmlInfo->mLayerInfoList.begin();
- iter != sAvatarXmlInfo->mLayerInfoList.end(); iter++)
+ LLVOAvatarXmlInfo::LLVOAvatarMorphInfo *info = *iter;
+
+ EBakedTextureIndex baked = LLVOAvatarDictionary::findBakedByRegionName(info->mRegion);
+ if (baked != BAKED_NUM_INDICES)
{
- LLTexLayerSetInfo *info = *iter;
- LLTexLayerSet* layer_set = new LLTexLayerSet( this );
- if (!layer_set->setInfo(info))
- {
- stop_glerror();
- delete layer_set;
- llwarns << "avatar file: layer_set->parseData() failed" << llendl;
- return FALSE;
- }
- bool found_baked_entry = false;
- for (LLVOAvatarDictionary::baked_map_t::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
- baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end();
- baked_iter++)
- {
- const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = baked_iter->second;
- if (layer_set->isBodyRegion(baked_dict->mName))
- {
- mBakedTextureData[baked_iter->first].mTexLayerSet = layer_set;
- found_baked_entry = true;
- break;
- }
- }
- if (!found_baked_entry)
+ LLPolyMorphTarget *morph_param;
+ const std::string *name = &info->mName;
+ morph_param = (LLPolyMorphTarget *)(getVisualParam(name->c_str()));
+ if (morph_param)
{
- llwarns << "<layer_set> has invalid body_region attribute" << llendl;
- delete layer_set;
- return FALSE;
+ BOOL invert = info->mInvert;
+ addMaskedMorph(baked, morph_param, invert, info->mLayer);
}
}
+
}
+
+ loadLayersets();
// avatar_lad.xml : <driver_parameters>
+ for (LLVOAvatarXmlInfo::driver_info_list_t::iterator iter = sAvatarXmlInfo->mDriverInfoList.begin();
+ iter != sAvatarXmlInfo->mDriverInfoList.end();
+ ++iter)
{
- LLVOAvatarXmlInfo::driver_info_list_t::iterator iter;
- for (iter = sAvatarXmlInfo->mDriverInfoList.begin();
- iter != sAvatarXmlInfo->mDriverInfoList.end(); iter++)
+ LLDriverParamInfo *info = *iter;
+ LLDriverParam* driver_param = new LLDriverParam( this );
+ if (driver_param->setInfo(info))
{
- LLDriverParamInfo *info = *iter;
- LLDriverParam* driver_param = new LLDriverParam( this );
- if (driver_param->setInfo(info))
+ addVisualParam( driver_param );
+ LLVisualParam*(LLVOAvatar::*avatar_function)(S32)const = &LLVOAvatar::getVisualParam;
+ if( !driver_param->linkDrivenParams(boost::bind(avatar_function,(LLVOAvatar*)this,_1 ), false))
{
- addVisualParam( driver_param );
- }
- else
- {
- delete driver_param;
- llwarns << "avatar file: driver_param->parseData() failed" << llendl;
- return FALSE;
+ llwarns << "could not link driven params for avatar " << this->getFullname() << " id: " << driver_param->getID() << llendl;
+ continue;
}
}
+ else
+ {
+ delete driver_param;
+ llwarns << "avatar file: driver_param->parseData() failed" << llendl;
+ return FALSE;
+ }
}
+
+ // Uncomment to enable avatar_lad.xml debugging.
+/* std::ofstream file;
+ file.open("avatar_lad.log");
+ for( LLViewerVisualParam* param = (LLViewerVisualParam*) getFirstVisualParam();
+ param;
+ param = (LLViewerVisualParam*) getNextVisualParam() )
+ {
+ param->getInfo()->toStream(file);
+ file << std::endl;
+ }
+
+ file.close();*/
return TRUE;
}
@@ -5287,7 +4833,8 @@ BOOL LLVOAvatar::loadSkeletonNode ()
mRoot.addChild( &mSkeleton[0] );
for (std::vector<LLViewerJoint *>::iterator iter = mMeshLOD.begin();
- iter != mMeshLOD.end(); iter++)
+ iter != mMeshLOD.end();
+ ++iter)
{
LLViewerJoint *joint = (LLViewerJoint *) *iter;
joint->mUpdateXform = FALSE;
@@ -5323,7 +4870,8 @@ BOOL LLVOAvatar::loadSkeletonNode ()
{
LLVOAvatarXmlInfo::skeletal_distortion_info_list_t::iterator iter;
for (iter = sAvatarXmlInfo->mSkeletalDistortionInfoList.begin();
- iter != sAvatarXmlInfo->mSkeletalDistortionInfoList.end(); iter++)
+ iter != sAvatarXmlInfo->mSkeletalDistortionInfoList.end();
+ ++iter)
{
LLPolySkeletalDistortionInfo *info = *iter;
LLPolySkeletalDistortion *param = new LLPolySkeletalDistortion(this);
@@ -5343,7 +4891,8 @@ BOOL LLVOAvatar::loadSkeletonNode ()
{
LLVOAvatarXmlInfo::attachment_info_list_t::iterator iter;
for (iter = sAvatarXmlInfo->mAttachmentInfoList.begin();
- iter != sAvatarXmlInfo->mAttachmentInfoList.end(); iter++)
+ iter != sAvatarXmlInfo->mAttachmentInfoList.end();
+ ++iter)
{
LLVOAvatarXmlInfo::LLVOAvatarAttachmentInfo *info = *iter;
if (!isSelf() && info->mJointName == "mScreen")
@@ -5424,7 +4973,7 @@ BOOL LLVOAvatar::loadMeshNodes()
{
for (LLVOAvatarXmlInfo::mesh_info_list_t::const_iterator meshinfo_iter = sAvatarXmlInfo->mMeshInfoList.begin();
meshinfo_iter != sAvatarXmlInfo->mMeshInfoList.end();
- meshinfo_iter++)
+ ++meshinfo_iter)
{
const LLVOAvatarXmlInfo::LLVOAvatarMeshInfo *info = *meshinfo_iter;
const std::string &type = info->mType;
@@ -5438,12 +4987,12 @@ BOOL LLVOAvatar::loadMeshNodes()
switch(lod)
case 0:
mesh = &mHairMesh0; */
- for (LLVOAvatarDictionary::mesh_map_t::const_iterator mesh_iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin();
+ for (LLVOAvatarDictionary::Meshes::const_iterator mesh_iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin();
mesh_iter != LLVOAvatarDictionary::getInstance()->getMeshes().end();
- mesh_iter++)
+ ++mesh_iter)
{
const EMeshIndex mesh_index = mesh_iter->first;
- const LLVOAvatarDictionary::MeshDictionaryEntry *mesh_dict = mesh_iter->second;
+ const LLVOAvatarDictionary::MeshEntry *mesh_dict = mesh_iter->second;
if (type.compare(mesh_dict->mName) == 0)
{
mesh_id = mesh_index;
@@ -5512,7 +5061,7 @@ BOOL LLVOAvatar::loadMeshNodes()
for (LLVOAvatarXmlInfo::LLVOAvatarMeshInfo::morph_info_list_t::const_iterator xmlinfo_iter = info->mPolyMorphTargetInfoList.begin();
xmlinfo_iter != info->mPolyMorphTargetInfoList.end();
- xmlinfo_iter++)
+ ++xmlinfo_iter)
{
const LLVOAvatarXmlInfo::LLVOAvatarMeshInfo::morph_info_pair_t *info_pair = &(*xmlinfo_iter);
LLPolyMorphTarget *param = new LLPolyMorphTarget(mesh->getMesh());
@@ -5539,6 +5088,23 @@ BOOL LLVOAvatar::loadMeshNodes()
}
//-----------------------------------------------------------------------------
+// loadLayerSets()
+//-----------------------------------------------------------------------------
+BOOL LLVOAvatar::loadLayersets()
+{
+ BOOL success = TRUE;
+ for (LLVOAvatarXmlInfo::layer_info_list_t::const_iterator layerset_iter = sAvatarXmlInfo->mLayerInfoList.begin();
+ layerset_iter != sAvatarXmlInfo->mLayerInfoList.end();
+ ++layerset_iter)
+ {
+ // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such.
+ LLTexLayerSetInfo *layerset_info = *layerset_iter;
+ layerset_info->createVisualParams(this);
+ }
+ return success;
+}
+
+//-----------------------------------------------------------------------------
// updateVisualParams()
//-----------------------------------------------------------------------------
void LLVOAvatar::updateVisualParams()
@@ -5602,9 +5168,9 @@ void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent)
}
// We always want to look good to ourselves
- if( mIsSelf )
+ if( isSelf() )
{
- mPixelArea = llmax( mPixelArea, F32(TEX_IMAGE_SIZE_SELF / 16) );
+ mPixelArea = llmax( mPixelArea, F32(getTexImageSize() / 16) );
}
}
@@ -5620,7 +5186,7 @@ BOOL LLVOAvatar::updateJointLODs()
F32 area_scale = 0.16f;
{
- if (mIsSelf)
+ if (isSelf())
{
if(gAgent.cameraCustomizeAvatar() || gAgent.cameraMouselook())
{
@@ -5686,12 +5252,22 @@ LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline)
}
+void LLVOAvatar::updateGL()
+{
+ if (mMeshTexturesDirty)
+ {
+ updateMeshTextures();
+ mMeshTexturesDirty = FALSE;
+ }
+}
+
//-----------------------------------------------------------------------------
// updateGeometry()
//-----------------------------------------------------------------------------
+static LLFastTimer::DeclareTimer FTM_UPDATE_AVATAR("Update Avatar");
BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable)
{
- LLFastTimer ftm(LLFastTimer::FTM_UPDATE_AVATAR);
+ LLFastTimer ftm(FTM_UPDATE_AVATAR);
if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_AVATAR)))
{
return TRUE;
@@ -5736,7 +5312,7 @@ void LLVOAvatar::updateShadowFaces()
sprite.setSize(0.4f + cos_elev * 0.8f, 0.3f);
LLVector3 sun_vec = gSky.mVOSkyp ? gSky.mVOSkyp->getToSun() : LLVector3(0.f, 0.f, 0.f);
- if (mShadowImagep->getHasGLTexture())
+ if (mShadowImagep->hasGLTexture())
{
LLVector3 normal;
LLVector3d shadow_pos;
@@ -5749,7 +5325,7 @@ void LLVOAvatar::updateShadowFaces()
// this only does a ray straight down from the foot, as our client-side ray-tracing is very limited now
// but we make an explicit ray trace call in expectation of future improvements
resolveRayCollisionAgent(gAgent.getPosGlobalFromAgent(joint_world_pos),
- gAgent.getPosGlobalFromAgent(gSky.getSunDirection() + joint_world_pos), shadow_pos, normal);
+ gAgent.getPosGlobalFromAgent(gSky.getSunDirection() + joint_world_pos), shadow_pos, normal);
shadow_pos_agent = gAgent.getPosAgentFromGlobal(shadow_pos);
foot_height = joint_world_pos.mV[VZ] - shadow_pos_agent.mV[VZ];
@@ -5758,7 +5334,7 @@ void LLVOAvatar::updateShadowFaces()
// Render sprite
sprite.setNormal(normal);
- if (mIsSelf && gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK)
+ if (isSelf() && gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK)
{
sprite.setColor(0.f, 0.f, 0.f, 0.f);
}
@@ -5782,7 +5358,7 @@ void LLVOAvatar::updateShadowFaces()
// this only does a ray straight down from the foot, as our client-side ray-tracing is very limited now
// but we make an explicit ray trace call in expectation of future improvements
resolveRayCollisionAgent(gAgent.getPosGlobalFromAgent(joint_world_pos),
- gAgent.getPosGlobalFromAgent(gSky.getSunDirection() + joint_world_pos), shadow_pos, normal);
+ gAgent.getPosGlobalFromAgent(gSky.getSunDirection() + joint_world_pos), shadow_pos, normal);
shadow_pos_agent = gAgent.getPosAgentFromGlobal(shadow_pos);
foot_height = joint_world_pos.mV[VZ] - shadow_pos_agent.mV[VZ];
@@ -5791,7 +5367,7 @@ void LLVOAvatar::updateShadowFaces()
// Render sprite
sprite.setNormal(normal);
- if (mIsSelf && gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK)
+ if (isSelf() && gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK)
{
sprite.setColor(0.f, 0.f, 0.f, 0.f);
}
@@ -5814,12 +5390,11 @@ void LLVOAvatar::updateShadowFaces()
//-----------------------------------------------------------------------------
// updateSexDependentLayerSets()
//-----------------------------------------------------------------------------
-void LLVOAvatar::updateSexDependentLayerSets( BOOL set_by_user )
+void LLVOAvatar::updateSexDependentLayerSets( BOOL upload_bake )
{
- invalidateComposite( mBakedTextureData[BAKED_HEAD].mTexLayerSet, set_by_user );
- invalidateComposite( mBakedTextureData[BAKED_UPPER].mTexLayerSet, set_by_user );
- invalidateComposite( mBakedTextureData[BAKED_LOWER].mTexLayerSet, set_by_user );
- updateMeshTextures();
+ invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, upload_bake );
+ invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet, upload_bake );
+ invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet, upload_bake );
}
//-----------------------------------------------------------------------------
@@ -5838,33 +5413,13 @@ void LLVOAvatar::hideSkirt()
mMeshLOD[MESH_ID_SKIRT]->setVisible(FALSE, TRUE);
}
-
-//-----------------------------------------------------------------------------
-// requestLayerSetUpdate()
-//-----------------------------------------------------------------------------
-void LLVOAvatar::requestLayerSetUpdate(ETextureIndex index )
-{
- /* switch(index)
- case LOCTEX_UPPER_BODYPAINT:
- case LOCTEX_UPPER_SHIRT:
- if( mUpperBodyLayerSet )
- mUpperBodyLayerSet->requestUpdate(); */
- const LLVOAvatarDictionary::TextureDictionaryEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(index);
- if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture)
- return;
- const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
- if (mBakedTextureData[baked_index].mTexLayerSet)
- {
- mBakedTextureData[baked_index].mTexLayerSet->requestUpdate();
- }
-}
-
-void LLVOAvatar::setParent(LLViewerObject* parent)
+BOOL LLVOAvatar::setParent(LLViewerObject* parent)
{
+ BOOL ret ;
if (parent == NULL)
{
getOffObject();
- LLViewerObject::setParent(parent);
+ ret = LLViewerObject::setParent(parent);
if (isSelf())
{
gAgent.resetCamera();
@@ -5872,9 +5427,13 @@ void LLVOAvatar::setParent(LLViewerObject* parent)
}
else
{
- LLViewerObject::setParent(parent);
- sitOnObject(parent);
+ ret = LLViewerObject::setParent(parent);
+ if(ret)
+ {
+ sitOnObject(parent);
+ }
}
+ return ret ;
}
void LLVOAvatar::addChild(LLViewerObject *childp)
@@ -5893,7 +5452,10 @@ void LLVOAvatar::addChild(LLViewerObject *childp)
void LLVOAvatar::removeChild(LLViewerObject *childp)
{
LLViewerObject::removeChild(childp);
- detachObject(childp);
+ if (!detachObject(childp))
+ {
+ llwarns << "Calling detach on non-attached object " << llendl;
+ }
}
LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* viewer_object)
@@ -5913,13 +5475,13 @@ LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* vi
//-----------------------------------------------------------------------------
// attachObject()
//-----------------------------------------------------------------------------
-BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object)
+const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_object)
{
LLViewerJointAttachment* attachment = getTargetAttachmentPoint(viewer_object);
if (!attachment || !attachment->addObject(viewer_object))
{
- return FALSE;
+ return 0;
}
if (viewer_object->isSelected())
@@ -5928,16 +5490,31 @@ BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object)
LLSelectMgr::getInstance()->updatePointAt();
}
- if (mIsSelf)
+ return attachment;
+}
+
+//-----------------------------------------------------------------------------
+// attachObject()
+//-----------------------------------------------------------------------------
+U32 LLVOAvatar::getNumAttachments() const
+{
+ U32 num_attachments = 0;
+ for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ ++iter)
{
- updateAttachmentVisibility(gAgent.getCameraMode());
-
- // Then make sure the inventory is in sync with the avatar.
- gInventory.addChangedMask( LLInventoryObserver::LABEL, attachment->getItemID() );
- gInventory.notifyObservers();
+ const LLViewerJointAttachment *attachment_pt = (*iter).second;
+ num_attachments += attachment_pt->getNumObjects();
}
+ return num_attachments;
+}
- return TRUE;
+//-----------------------------------------------------------------------------
+// canAttachMoreObjects()
+//-----------------------------------------------------------------------------
+BOOL LLVOAvatar::canAttachMoreObjects() const
+{
+ return (getNumAttachments() < MAX_AGENT_ATTACHMENTS);
}
//-----------------------------------------------------------------------------
@@ -5965,16 +5542,21 @@ void LLVOAvatar::lazyAttach()
void LLVOAvatar::resetHUDAttachments()
{
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
+ iter != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
+ LLViewerJointAttachment* attachment = iter->second;
if (attachment->getIsHUDAttachment())
{
- LLViewerObject* obj = attachment->getObject();
- if (obj && obj->mDrawable.notNull())
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- gPipeline.markMoved(obj->mDrawable);
+ const LLViewerObject* attached_object = (*attachment_iter);
+ if (attached_object && attached_object->mDrawable.notNull())
+ {
+ gPipeline.markMoved(attached_object->mDrawable);
+ }
}
}
}
@@ -5986,56 +5568,57 @@ void LLVOAvatar::resetHUDAttachments()
BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)
{
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
+ iter != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- // only one object per attachment point for now
- if (attachment->getObject() == viewer_object)
+ LLViewerJointAttachment* attachment = iter->second;
+
+ if (attachment->isObjectAttached(viewer_object))
{
- LLUUID item_id = attachment->getItemID();
attachment->removeObject(viewer_object);
- if (mIsSelf)
- {
- // the simulator should automatically handle
- // permission revocation
-
- stopMotionFromSource(viewer_object->getID());
- LLFollowCamMgr::setCameraActive(viewer_object->getID(), FALSE);
-
- LLViewerObject::const_child_list_t& child_list = viewer_object->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
- {
- LLViewerObject* child_objectp = *iter;
- // the simulator should automatically handle
- // permissions revocation
-
- stopMotionFromSource(child_objectp->getID());
- LLFollowCamMgr::setCameraActive(child_objectp->getID(), FALSE);
- }
-
- }
lldebugs << "Detaching object " << viewer_object->mID << " from " << attachment->getName() << llendl;
- if (mIsSelf)
- {
- // Then make sure the inventory is in sync with the avatar.
- gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
- gInventory.notifyObservers();
- }
return TRUE;
}
}
-
-
return FALSE;
}
//-----------------------------------------------------------------------------
+// sitDown()
+//-----------------------------------------------------------------------------
+void LLVOAvatar::sitDown(BOOL bSitting)
+{
+ mIsSitting = bSitting;
+ if (isSelf())
+ {
+ // Update Movement Controls according to own Sitting mode
+ LLFloaterMove::setSittingMode(bSitting);
+ }
+}
+
+//-----------------------------------------------------------------------------
// sitOnObject()
//-----------------------------------------------------------------------------
void LLVOAvatar::sitOnObject(LLViewerObject *sit_object)
{
+ if (isSelf())
+ {
+ // Might be first sit
+ //LLFirstUse::useSit();
+
+ gAgent.setFlying(FALSE);
+ gAgent.setThirdPersonHeadOffset(LLVector3::zero);
+ //interpolate to new camera position
+ gAgent.startCameraAnimation();
+ // make sure we are not trying to autopilot
+ gAgent.stopAutoPilot();
+ gAgent.setupSitCamera();
+ if (gAgent.getForceMouselook())
+ {
+ gAgent.changeCameraToMouselook();
+ }
+ }
+
if (mDrawable.isNull())
{
return;
@@ -6050,27 +5633,13 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object)
mDrawable->mXform.setRotation(mDrawable->getWorldRotation() * inv_obj_rot);
gPipeline.markMoved(mDrawable, TRUE);
- mIsSitting = TRUE;
+ sitDown(TRUE);
mRoot.getXform()->setParent(&sit_object->mDrawable->mXform); // LLVOAvatar::sitOnObject
mRoot.setPosition(getPosition());
mRoot.updateWorldMatrixChildren();
stopMotion(ANIM_AGENT_BODY_NOISE);
- if (mIsSelf)
- {
- // Might be first sit
- LLFirstUse::useSit();
-
- gAgent.setFlying(FALSE);
- gAgent.setThirdPersonHeadOffset(LLVector3::zero);
- //interpolate to new camera position
- gAgent.startCameraAnimation();
- // make sure we are not trying to autopilot
- gAgent.stopAutoPilot();
- gAgent.setupSitCamera();
- if (gAgent.mForceMouselook) gAgent.changeCameraToMouselook();
- }
}
//-----------------------------------------------------------------------------
@@ -6092,7 +5661,7 @@ void LLVOAvatar::getOffObject()
LLViewerObject::const_child_list_t& child_list = sit_object->getChildren();
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
+ iter != child_list.end(); ++iter)
{
LLViewerObject* child_objectp = *iter;
@@ -6111,7 +5680,8 @@ void LLVOAvatar::getOffObject()
gPipeline.markMoved(mDrawable, TRUE);
- mIsSitting = FALSE;
+ sitDown(FALSE);
+
mRoot.getXform()->setParent(NULL); // LLVOAvatar::getOffObject
mRoot.setPosition(cur_position_world);
mRoot.setRotation(cur_rotation_world);
@@ -6119,7 +5689,7 @@ void LLVOAvatar::getOffObject()
startMotion(ANIM_AGENT_BODY_NOISE);
- if (mIsSelf)
+ if (isSelf())
{
LLQuaternion av_rot = gAgent.getFrameAgent().getQuaternion();
LLQuaternion obj_rot = sit_object ? sit_object->getRenderRotation() : LLQuaternion::DEFAULT;
@@ -6160,146 +5730,24 @@ LLVOAvatar* LLVOAvatar::findAvatarFromAttachment( LLViewerObject* obj )
return NULL;
}
-//-----------------------------------------------------------------------------
-// isWearingAttachment()
-//-----------------------------------------------------------------------------
-BOOL LLVOAvatar::isWearingAttachment( const LLUUID& inv_item_id )
-{
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
- {
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if( attachment->getItemID() == inv_item_id )
- {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-//-----------------------------------------------------------------------------
-// getWornAttachment()
-//-----------------------------------------------------------------------------
-LLViewerObject* LLVOAvatar::getWornAttachment( const LLUUID& inv_item_id )
-{
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
- {
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if( attachment->getItemID() == inv_item_id )
- {
- return attachment->getObject();
- }
- }
- return NULL;
-}
-
-const std::string LLVOAvatar::getAttachedPointName(const LLUUID& inv_item_id)
-{
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
- {
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if( attachment->getItemID() == inv_item_id )
- {
- return attachment->getName();
- }
- }
-
- return LLStringUtil::null;
-}
-
-
-//-----------------------------------------------------------------------------
-// static
-// onLocalTextureLoaded()
-//-----------------------------------------------------------------------------
-
-void LLVOAvatar::onLocalTextureLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src_raw, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
-{
- //llinfos << "onLocalTextureLoaded: " << src_vi->getID() << llendl;
-
- const LLUUID& src_id = src_vi->getID();
- LLAvatarTexData *data = (LLAvatarTexData *)userdata;
- if (success)
- {
- LLVOAvatar *self = (LLVOAvatar *)gObjectList.findObject(data->mAvatarID);
- if (self)
- {
- ETextureIndex index = data->mIndex;
- if (!self->isIndexLocalTexture(index)) return;
- LocalTextureData &local_tex_data = self->mLocalTextureData[index];
- if(!local_tex_data.mIsBakedReady &&
- local_tex_data.mImage.notNull() &&
- (local_tex_data.mImage->getID() == src_id) &&
- discard_level < local_tex_data.mDiscard)
- {
- local_tex_data.mDiscard = discard_level;
- if ( self->isSelf() && !gAgent.cameraCustomizeAvatar() )
- {
- self->requestLayerSetUpdate( index );
- }
- else if( self->isSelf() && gAgent.cameraCustomizeAvatar() )
- {
- LLVisualParamHint::requestHintUpdates();
- }
- self->updateMeshTextures();
- }
- }
- }
- else if (final)
- {
- LLVOAvatar *self = (LLVOAvatar *)gObjectList.findObject(data->mAvatarID);
- if (self)
- {
- ETextureIndex index = data->mIndex;
- if (!self->isIndexLocalTexture(index)) return;
- LocalTextureData &local_tex_data = self->mLocalTextureData[index];
- // Failed: asset is missing
- if(!local_tex_data.mIsBakedReady &&
- local_tex_data.mImage.notNull() &&
- local_tex_data.mImage->getID() == src_id)
- {
- local_tex_data.mDiscard = 0;
- self->requestLayerSetUpdate( index );
- self->updateMeshTextures();
- }
- }
- }
-
- if( final || !success )
- {
- delete data;
- }
-}
-
-void LLVOAvatar::updateComposites()
+// warning: order(N) not order(1)
+S32 LLVOAvatar::getAttachmentCount()
{
- for (U32 i = 0; i < mBakedTextureData.size(); i++)
- {
- if ( mBakedTextureData[i].mTexLayerSet
- && ((i != BAKED_SKIRT) || isWearingWearableType( WT_SKIRT )) )
- {
- mBakedTextureData[i].mTexLayerSet->updateComposite();
- }
- }
+ S32 count = mAttachmentPoints.size();
+ return count;
}
-LLColor4 LLVOAvatar::getGlobalColor( const std::string& color_name )
+LLColor4 LLVOAvatar::getGlobalColor( const std::string& color_name ) const
{
- if( color_name=="skin_color" && mTexSkinColor )
+ if (color_name=="skin_color" && mTexSkinColor)
{
return mTexSkinColor->getColor();
}
- else
- if( color_name=="hair_color" && mTexHairColor )
+ else if(color_name=="hair_color" && mTexHairColor)
{
return mTexHairColor->getColor();
}
- if( color_name=="eye_color" && mTexEyeColor )
+ if(color_name=="eye_color" && mTexEyeColor)
{
return mTexEyeColor->getColor();
}
@@ -6310,282 +5758,64 @@ LLColor4 LLVOAvatar::getGlobalColor( const std::string& color_name )
}
}
-
-void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL set_by_user )
+// virtual
+void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_result )
{
- if( !layerset || !layerset->getUpdatesEnabled() )
- {
- return;
- }
-
- /* Debug spam. JC
- const char* layer_name = "";
- if (layerset == mHeadLayerSet)
- {
- layer_name = "head";
- }
- else if (layerset == mUpperBodyLayerSet)
- {
- layer_name = "upperbody";
- }
- else if (layerset == mLowerBodyLayerSet)
- {
- layer_name = "lowerbody";
- }
- else if (layerset == mEyesLayerSet)
- {
- layer_name = "eyes";
- }
- else if (layerset == mHairLayerSet)
- {
- layer_name = "hair";
- }
- else if (layerset == mSkirtLayerSet)
- {
- layer_name = "skirt";
- }
- else
- {
- layer_name = "unknown";
- }
- llinfos << "LLVOAvatar::invalidComposite() " << layer_name << llendl;
- */
-
- layerset->requestUpdate();
-
- if( set_by_user )
- {
- llassert( mIsSelf );
-
- ETextureIndex baked_te = getBakedTE( layerset );
- setTEImage( baked_te, gImageList.getImage(IMG_DEFAULT_AVATAR) );
- layerset->requestUpload();
- }
}
void LLVOAvatar::invalidateAll()
{
- for (U32 i = 0; i < mBakedTextureData.size(); i++)
- {
- invalidateComposite(mBakedTextureData[i].mTexLayerSet, TRUE);
- }
- updateMeshTextures();
}
-void LLVOAvatar::onGlobalColorChanged( LLTexGlobalColor* global_color, BOOL set_by_user )
+// virtual
+void LLVOAvatar::setCompositeUpdatesEnabled( BOOL b )
+{
+}
+
+void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake )
{
- if( global_color == mTexSkinColor )
+ if (global_color == mTexSkinColor)
{
-// llinfos << "invalidateComposite cause: onGlobalColorChanged( skin color )" << llendl;
- invalidateComposite( mBakedTextureData[BAKED_HEAD].mTexLayerSet, set_by_user );
- invalidateComposite( mBakedTextureData[BAKED_UPPER].mTexLayerSet, set_by_user );
- invalidateComposite( mBakedTextureData[BAKED_LOWER].mTexLayerSet, set_by_user );
+ invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, upload_bake );
+ invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet, upload_bake );
+ invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet, upload_bake );
}
- else
- if( global_color == mTexHairColor )
+ else if (global_color == mTexHairColor)
{
-// llinfos << "invalidateComposite cause: onGlobalColorChanged( hair color )" << llendl;
- invalidateComposite( mBakedTextureData[BAKED_HEAD].mTexLayerSet, set_by_user );
- invalidateComposite( mBakedTextureData[BAKED_HAIR].mTexLayerSet, set_by_user );
+ invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, upload_bake );
+ invalidateComposite( mBakedTextureDatas[BAKED_HAIR].mTexLayerSet, upload_bake );
// ! BACKWARDS COMPATIBILITY !
// Fix for dealing with avatars from viewers that don't bake hair.
- if (!isTextureDefined(mBakedTextureData[BAKED_HAIR].mTextureIndex))
+ if (!isTextureDefined(mBakedTextureDatas[BAKED_HAIR].mTextureIndex))
{
LLColor4 color = mTexHairColor->getColor();
- for (U32 i = 0; i < mBakedTextureData[BAKED_HAIR].mMeshes.size(); i++)
+ for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++)
{
- mBakedTextureData[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
+ mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
}
}
- }
- else
- if( global_color == mTexEyeColor )
+ }
+ else if (global_color == mTexEyeColor)
{
// llinfos << "invalidateComposite cause: onGlobalColorChanged( eyecolor )" << llendl;
- invalidateComposite( mBakedTextureData[BAKED_EYES].mTexLayerSet, set_by_user );
+ invalidateComposite( mBakedTextureDatas[BAKED_EYES].mTexLayerSet, upload_bake );
}
updateMeshTextures();
}
-void LLVOAvatar::forceBakeAllTextures(bool slam_for_debug)
-{
- llinfos << "TAT: forced full rebake. " << llendl;
-
- for (U32 i = 0; i < mBakedTextureData.size(); i++)
- {
- ETextureIndex baked_index = mBakedTextureData[i].mTextureIndex;
- LLTexLayerSet* layer_set = getLayerSet(baked_index);
- if (layer_set)
- {
- if (slam_for_debug)
- {
- layer_set->setUpdatesEnabled(TRUE);
- layer_set->cancelUpload();
- }
-
- BOOL set_by_user = TRUE;
- invalidateComposite(layer_set, set_by_user);
- LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_REBAKES);
- }
- else
- {
- llwarns << "TAT: NO LAYER SET FOR " << (S32)baked_index << llendl;
- }
- }
-
- // Don't know if this is needed
- updateMeshTextures();
-}
-
-
-// static
-void LLVOAvatar::processRebakeAvatarTextures(LLMessageSystem* msg, void**)
-{
- LLUUID texture_id;
- msg->getUUID("TextureData", "TextureID", texture_id);
-
- LLVOAvatar* self = gAgent.getAvatarObject();
- if (!self) return;
-
- // If this is a texture corresponding to one of our baked entries,
- // just rebake that layer set.
- BOOL found = FALSE;
-
- /* ETextureIndex baked_texture_indices[BAKED_NUM_INDICES] =
- TEX_HEAD_BAKED,
- TEX_UPPER_BAKED, */
- for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
- iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
- iter++)
- {
- const ETextureIndex index = iter->first;
- const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second;
- if (text_dict->mIsBakedTexture)
- {
- if (texture_id == self->getTEImage(index)->getID())
- {
- LLTexLayerSet* layer_set = self->getLayerSet(index);
- if (layer_set)
- {
- llinfos << "TAT: rebake - matched entry " << (S32)index << llendl;
- // Apparently set_by_user == force upload
- BOOL set_by_user = TRUE;
- self->invalidateComposite(layer_set, set_by_user);
- found = TRUE;
- LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_REBAKES);
- }
- }
- }
- }
-
- // If texture not found, rebake all entries.
- if (!found)
- {
- self->forceBakeAllTextures();
- }
- else
- {
- // Not sure if this is necessary, but forceBakeAllTextures() does it.
- self->updateMeshTextures();
- }
-}
-
-
-BOOL LLVOAvatar::getLocalTextureRaw(ETextureIndex index, LLImageRaw* image_raw)
-{
- if (!isIndexLocalTexture(index)) return FALSE;
-
- BOOL success = FALSE;
-
- if (getLocalTextureID(index) == IMG_DEFAULT_AVATAR)
- {
- success = TRUE;
- }
- else
- {
- LocalTextureData &local_tex_data = mLocalTextureData[index];
- if(local_tex_data.mImage->readBackRaw(-1, image_raw, false))
- {
- success = TRUE;
- }
- else
- {
- // No data loaded yet
- setLocalTexture( (ETextureIndex)index, getTEImage( index ), FALSE );
- }
- }
- return success;
-}
-
-BOOL LLVOAvatar::getLocalTextureGL(ETextureIndex index, LLImageGL** image_gl_pp)
-{
- if (!isIndexLocalTexture(index)) return FALSE;
-
- BOOL success = FALSE;
- *image_gl_pp = NULL;
-
- if (getLocalTextureID(index) == IMG_DEFAULT_AVATAR)
- {
- success = TRUE;
- }
- else
- {
- LocalTextureData &local_tex_data = mLocalTextureData[index];
- *image_gl_pp = local_tex_data.mImage;
- success = TRUE;
- }
-
- if( !success )
- {
-// llinfos << "getLocalTextureGL(" << index << ") had no data" << llendl;
- }
- return success;
-}
-
-const LLUUID& LLVOAvatar::getLocalTextureID(ETextureIndex index)
-{
- if (!isIndexLocalTexture(index)) return IMG_DEFAULT_AVATAR;
-
- if (mLocalTextureData[index].mImage.notNull())
- {
- return mLocalTextureData[index].mImage->getID();
- }
- else
- {
- return IMG_DEFAULT_AVATAR;
- }
-}
-
-// static
-void LLVOAvatar::dumpTotalLocalTextureByteCount()
-{
- S32 total_gl_bytes = 0;
- for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
- {
- LLVOAvatar* cur = (LLVOAvatar*) *iter;
- S32 gl_bytes = 0;
- cur->getLocalTextureByteCount(&gl_bytes );
- total_gl_bytes += gl_bytes;
- }
- llinfos << "Total Avatar LocTex GL:" << (total_gl_bytes/1024) << "KB" << llendl;
-}
-
-BOOL LLVOAvatar::isVisible()
+BOOL LLVOAvatar::isVisible() const
{
return mDrawable.notNull()
&& (mDrawable->isVisible() || mIsDummy);
}
-
// call periodically to keep isFullyLoaded up to date.
// returns true if the value has changed.
BOOL LLVOAvatar::updateIsFullyLoaded()
{
// a "heuristic" to determine if we have enough avatar data to render
// (to avoid rendering a "Ruth" - DEV-3168)
-
BOOL loading = FALSE;
// do we have a shape?
@@ -6594,48 +5824,47 @@ BOOL LLVOAvatar::updateIsFullyLoaded()
loading = TRUE;
}
- //
- if (mIsSelf)
- {
- if (!isTextureDefined(TEX_HAIR))
- {
- loading = TRUE;
- }
- }
- else if (!isTextureDefined(TEX_LOWER_BAKED) || !isTextureDefined(TEX_UPPER_BAKED) || !isTextureDefined(TEX_HEAD_BAKED))
+ if (!isTextureDefined(TEX_LOWER_BAKED) ||
+ !isTextureDefined(TEX_UPPER_BAKED) ||
+ !isTextureDefined(TEX_HEAD_BAKED))
{
loading = TRUE;
}
- // special case to keep nudity off orientation island -
- // this is fragilely dependent on the compositing system,
- // which gets available textures in the following order:
- //
- // 1) use the baked texture
- // 2) use the layerset
- // 3) use the previously baked texture
- //
- // on orientation island case (3) can show naked skin.
- // so we test for that here:
- //
- // if we were previously unloaded, and we don't have enough
- // texture info for our shirt/pants, stay unloaded:
- if (!mPreviousFullyLoaded)
- {
- if ((!isLocalTextureDataAvailable(mBakedTextureData[BAKED_LOWER].mTexLayerSet)) &&
- (!isTextureDefined(TEX_LOWER_BAKED)))
- {
- loading = TRUE;
- }
+ updateRuthTimer(loading);
+ return processFullyLoadedChange(loading);
+}
- if ((!isLocalTextureDataAvailable(mBakedTextureData[BAKED_UPPER].mTexLayerSet)) &&
- (!isTextureDefined(TEX_UPPER_BAKED)))
- {
- loading = TRUE;
- }
+void LLVOAvatar::updateRuthTimer(bool loading)
+{
+ if (isSelf() || !loading)
+ {
+ return;
}
+ if (mPreviousFullyLoaded)
+ {
+ mRuthTimer.reset();
+ }
+ const F32 LOADING_TIMEOUT = 120.f;
+ if (mRuthTimer.getElapsedTimeF32() > LOADING_TIMEOUT)
+ {
+ /*
+ llinfos << "Ruth Timer timeout: Missing texture data for '" << getFullname() << "' "
+ << "( Params loaded : " << !visualParamWeightsAreDefault() << " ) "
+ << "( Lower : " << isTextureDefined(TEX_LOWER_BAKED) << " ) "
+ << "( Upper : " << isTextureDefined(TEX_UPPER_BAKED) << " ) "
+ << "( Head : " << isTextureDefined(TEX_HEAD_BAKED) << " )."
+ << llendl;
+ */
+ LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(getID());
+ mRuthTimer.reset();
+ }
+}
+
+BOOL LLVOAvatar::processFullyLoadedChange(bool loading)
+{
// we wait a little bit before giving the all clear,
// to let textures settle down
const F32 PAUSE = 1.f;
@@ -6659,8 +5888,7 @@ BOOL LLVOAvatar::updateIsFullyLoaded()
return changed;
}
-
-BOOL LLVOAvatar::isFullyLoaded()
+BOOL LLVOAvatar::isFullyLoaded() const
{
if (gSavedSettings.getBOOL("RenderUnloadedAvatar"))
return TRUE;
@@ -6672,177 +5900,11 @@ BOOL LLVOAvatar::isFullyLoaded()
//-----------------------------------------------------------------------------
// findMotion()
//-----------------------------------------------------------------------------
-LLMotion* LLVOAvatar::findMotion(const LLUUID& id)
+LLMotion* LLVOAvatar::findMotion(const LLUUID& id) const
{
return mMotionController.findMotion(id);
}
-// Counts the memory footprint of local textures.
-void LLVOAvatar::getLocalTextureByteCount( S32* gl_bytes )
-{
- *gl_bytes = 0;
- for( S32 i = 0; i < TEX_NUM_INDICES; i++ )
- {
- if (!isIndexLocalTexture((ETextureIndex)i)) continue;
- LLViewerImage* image_gl = mLocalTextureData[(ETextureIndex)i].mImage;
- if( image_gl )
- {
- S32 bytes = (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents();
-
- if( image_gl->getHasGLTexture() )
- {
- *gl_bytes += bytes;
- }
- }
- }
-}
-
-
-BOOL LLVOAvatar::bindScratchTexture( LLGLenum format )
-{
- U32 texture_bytes = 0;
- GLuint gl_name = getScratchTexName( format, &texture_bytes );
- if( gl_name )
- {
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, gl_name);
- stop_glerror();
-
- F32* last_bind_time = LLVOAvatar::sScratchTexLastBindTime.getIfThere( format );
- if( last_bind_time )
- {
- if( *last_bind_time != LLImageGL::sLastFrameTime )
- {
- *last_bind_time = LLImageGL::sLastFrameTime;
- LLImageGL::updateBoundTexMem(texture_bytes);
- }
- }
- else
- {
- LLImageGL::updateBoundTexMem(texture_bytes);
- LLVOAvatar::sScratchTexLastBindTime.addData( format, new F32(LLImageGL::sLastFrameTime) );
- }
-
-
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-}
-
-
-LLGLuint LLVOAvatar::getScratchTexName( LLGLenum format, U32* texture_bytes )
-{
- S32 components;
- GLenum internal_format;
- switch( format )
- {
- case GL_LUMINANCE: components = 1; internal_format = GL_LUMINANCE8; break;
- case GL_ALPHA: components = 1; internal_format = GL_ALPHA8; break;
- case GL_COLOR_INDEX: components = 1; internal_format = GL_COLOR_INDEX8_EXT; break;
- case GL_LUMINANCE_ALPHA: components = 2; internal_format = GL_LUMINANCE8_ALPHA8; break;
- case GL_RGB: components = 3; internal_format = GL_RGB8; break;
- case GL_RGBA: components = 4; internal_format = GL_RGBA8; break;
- default: llassert(0); components = 4; internal_format = GL_RGBA8; break;
- }
-
- *texture_bytes = components * SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT;
-
- if( LLVOAvatar::sScratchTexNames.checkData( format ) )
- {
- return *( LLVOAvatar::sScratchTexNames.getData( format ) );
- }
- else
- {
-
- LLGLSUIDefault gls_ui;
-
- U32 name = 0;
- LLImageGL::generateTextures(1, &name );
- stop_glerror();
-
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, name);
- stop_glerror();
-
- LLImageGL::setManualImage(
- GL_TEXTURE_2D, 0, internal_format,
- SCRATCH_TEX_WIDTH, SCRATCH_TEX_HEIGHT,
- format, GL_UNSIGNED_BYTE, NULL );
- stop_glerror();
-
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
- stop_glerror();
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- stop_glerror();
-
- LLVOAvatar::sScratchTexNames.addData( format, new LLGLuint( name ) );
-
- LLVOAvatar::sScratchTexBytes += *texture_bytes;
- LLImageGL::sGlobalTextureMemory += *texture_bytes;
- return name;
- }
-}
-
-
-
-//-----------------------------------------------------------------------------
-// setLocalTextureTE()
-//-----------------------------------------------------------------------------
-void LLVOAvatar::setLocTexTE( U8 te, LLViewerImage* image, BOOL set_by_user )
-{
- if( !mIsSelf )
- {
- llassert( 0 );
- return;
- }
-
- if( te >= TEX_NUM_INDICES )
- {
- llassert(0);
- return;
- }
-
- if( getTEImage( te )->getID() == image->getID() )
- {
- return;
- }
-
- if (isIndexBakedTexture((ETextureIndex)te))
- {
- llassert(0);
- return;
- }
-
- LLTexLayerSet* layer_set = getLayerSet((ETextureIndex)te);
- if (layer_set)
- {
- invalidateComposite(layer_set, set_by_user);
- }
-
- setTEImage( te, image );
- updateMeshTextures();
-
- if( gAgent.cameraCustomizeAvatar() )
- {
- LLVisualParamHint::requestHintUpdates();
- }
-}
-
-void LLVOAvatar::setupComposites()
-{
- for (U32 i = 0; i < mBakedTextureData.size(); i++)
- {
- bool layer_baked = isTextureDefined(mBakedTextureData[i].mTextureIndex);
- if (mBakedTextureData[i].mTexLayerSet)
- {
- mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled( !layer_baked );
- }
- }
-}
-
//-----------------------------------------------------------------------------
// updateMeshTextures()
// Uses the current TE values to set the meshes' and layersets' textures.
@@ -6855,25 +5917,25 @@ void LLVOAvatar::updateMeshTextures()
// if user has never specified a texture, assign the default
for (U32 i=0; i < getNumTEs(); i++)
{
- const LLViewerImage* te_image = getTEImage(i);
+ const LLViewerTexture* te_image = getImage(i, 0);
if(!te_image || te_image->getID().isNull() || (te_image->getID() == IMG_DEFAULT))
{
- setTEImage(i, gImageList.getImage(i == TEX_HAIR ? IMG_DEFAULT : IMG_DEFAULT_AVATAR)); // IMG_DEFAULT_AVATAR = a special texture that's never rendered.
+ setImage(i, LLViewerTextureManager::getFetchedTexture(i == TEX_HAIR ? IMG_DEFAULT : IMG_DEFAULT_AVATAR), 0); // IMG_DEFAULT_AVATAR = a special texture that's never rendered.
}
}
- const BOOL self_customizing = mIsSelf && gAgent.cameraCustomizeAvatar(); // During face edit mode, we don't use baked textures
- const BOOL other_culled = !mIsSelf && mCulled;
+ const BOOL self_customizing = isSelf() && gAgent.cameraCustomizeAvatar(); // During face edit mode, we don't use baked textures
+ const BOOL other_culled = !isSelf() && mCulled;
- std::vector<bool> is_layer_baked;
- is_layer_baked.resize(mBakedTextureData.size(), false);
+ std::vector<BOOL> is_layer_baked;
+ is_layer_baked.resize(mBakedTextureDatas.size(), false);
- std::vector<bool> use_lkg_baked_layer; // lkg = "last known good"
- use_lkg_baked_layer.resize(mBakedTextureData.size(), false);
+ std::vector<BOOL> use_lkg_baked_layer; // lkg = "last known good"
+ use_lkg_baked_layer.resize(mBakedTextureDatas.size(), false);
- for (U32 i=0; i < mBakedTextureData.size(); i++)
+ for (U32 i=0; i < mBakedTextureDatas.size(); i++)
{
- is_layer_baked[i] = isTextureDefined(mBakedTextureData[i].mTextureIndex);
+ is_layer_baked[i] = isTextureDefined(mBakedTextureDatas[i].mTextureIndex);
if (!other_culled)
{
@@ -6881,26 +5943,29 @@ void LLVOAvatar::updateMeshTextures()
// use the last-known good baked texture until it finish the first
// render of the new layerset.
use_lkg_baked_layer[i] = (!is_layer_baked[i]
- && (mBakedTextureData[i].mLastTextureIndex != IMG_DEFAULT_AVATAR)
- && mBakedTextureData[i].mTexLayerSet
- && !mBakedTextureData[i].mTexLayerSet->getComposite()->isInitialized());
+ && (mBakedTextureDatas[i].mLastTextureIndex != IMG_DEFAULT_AVATAR)
+ && mBakedTextureDatas[i].mTexLayerSet
+ && !mBakedTextureDatas[i].mTexLayerSet->getComposite()->isInitialized());
if (use_lkg_baked_layer[i])
{
- mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled(TRUE);
+ mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled(TRUE);
}
}
else
{
use_lkg_baked_layer[i] = (!is_layer_baked[i]
- && mBakedTextureData[i].mLastTextureIndex != IMG_DEFAULT_AVATAR);
- if (mBakedTextureData[i].mTexLayerSet)
+ && mBakedTextureDatas[i].mLastTextureIndex != IMG_DEFAULT_AVATAR);
+ if (mBakedTextureDatas[i].mTexLayerSet)
{
- mBakedTextureData[i].mTexLayerSet->destroyComposite();
+ mBakedTextureDatas[i].mTexLayerSet->destroyComposite();
}
}
}
+ // Turn on alpha masking correctly for yourself and other avatars on 1.23+
+ mSupportsAlphaLayers = isSelf() || is_layer_baked[BAKED_HAIR];
+
// Baked textures should be requested from the sim this avatar is on. JC
const LLHost target_host = getObjectHost();
if (!target_host.isOk())
@@ -6908,162 +5973,100 @@ void LLVOAvatar::updateMeshTextures()
llwarns << "updateMeshTextures: invalid host for object: " << getID() << llendl;
}
- for (U32 i=0; i < mBakedTextureData.size(); i++)
+ for (U32 i=0; i < mBakedTextureDatas.size(); i++)
{
if (use_lkg_baked_layer[i] && !self_customizing )
{
- LLViewerImage* baked_img = gImageList.getImageFromHost( mBakedTextureData[i].mLastTextureIndex, target_host );
- mBakedTextureData[i].mIsUsed = TRUE;
- for (U32 k=0; k < mBakedTextureData[i].mMeshes.size(); k++)
+ LLViewerFetchedTexture* baked_img = LLViewerTextureManager::getFetchedTextureFromHost( mBakedTextureDatas[i].mLastTextureIndex, target_host );
+ mBakedTextureDatas[i].mIsUsed = TRUE;
+ for (U32 k=0; k < mBakedTextureDatas[i].mMeshes.size(); k++)
{
- mBakedTextureData[i].mMeshes[k]->setTexture( baked_img );
+ mBakedTextureDatas[i].mMeshes[k]->setTexture( baked_img );
}
}
else if (!self_customizing && is_layer_baked[i])
{
- LLViewerImage* baked_img = getTEImage( mBakedTextureData[i].mTextureIndex );
- if( baked_img->getID() == mBakedTextureData[i].mLastTextureIndex )
+ LLViewerFetchedTexture* baked_img = LLViewerTextureManager::staticCastToFetchedTexture(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ;
+ if( baked_img->getID() == mBakedTextureDatas[i].mLastTextureIndex )
{
// Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing).
useBakedTexture( baked_img->getID() );
}
else
{
- mBakedTextureData[i].mIsLoaded = FALSE;
- if ( (i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER) )
+ mBakedTextureDatas[i].mIsLoaded = FALSE;
+ if ( (baked_img->getID() != IMG_INVISIBLE) && ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) )
{
baked_img->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ));
}
baked_img->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) );
}
}
- else if (mBakedTextureData[i].mTexLayerSet
- && !other_culled
- && (i != BAKED_HAIR || is_layer_baked[i] || mIsSelf)) // ! BACKWARDS COMPATIBILITY ! workaround for old viewers.
+ else if (mBakedTextureDatas[i].mTexLayerSet
+ && !other_culled)
{
- mBakedTextureData[i].mTexLayerSet->createComposite();
- mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled( TRUE );
- mBakedTextureData[i].mIsUsed = FALSE;
- for (U32 k=0; k < mBakedTextureData[i].mMeshes.size(); k++)
+ mBakedTextureDatas[i].mTexLayerSet->createComposite();
+ mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled( TRUE );
+ mBakedTextureDatas[i].mIsUsed = FALSE;
+ for (U32 k=0; k < mBakedTextureDatas[i].mMeshes.size(); k++)
{
- mBakedTextureData[i].mMeshes[k]->setLayerSet( mBakedTextureData[i].mTexLayerSet );
+ mBakedTextureDatas[i].mMeshes[k]->setLayerSet( mBakedTextureDatas[i].mTexLayerSet );
}
}
}
-
- // ! BACKWARDS COMPATIBILITY !
- // Workaround for viewing avatars from old viewers that haven't baked hair textures.
- // if (!isTextureDefined(mBakedTextureData[BAKED_HAIR].mTextureIndex))
+
+ // set texture and color of hair manually if we are not using a baked image.
+ // This can happen while loading hair for yourself, or for clients that did not
+ // bake a hair texture. Still needed for yourself after 1.22 is depricated.
if (!is_layer_baked[BAKED_HAIR] || self_customizing)
{
const LLColor4 color = mTexHairColor ? mTexHairColor->getColor() : LLColor4(1,1,1,1);
- LLViewerImage* hair_img = getTEImage( TEX_HAIR );
- for (U32 i = 0; i < mBakedTextureData[BAKED_HAIR].mMeshes.size(); i++)
+ LLViewerTexture* hair_img = getImage( TEX_HAIR, 0 );
+ for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++)
{
- mBakedTextureData[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
- mBakedTextureData[BAKED_HAIR].mMeshes[i]->setTexture( hair_img );
+ mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
+ mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setTexture( hair_img );
}
- mHasBakedHair = FALSE;
}
- else
- {
- mHasBakedHair = TRUE;
- }
- /* // Head
- BOOL head_baked_ready = (is_layer_baked[BAKED_HEAD] && mBakedTextureData[BAKED_HEAD].mIsLoaded) || other_culled;
- setLocalTexture( TEX_HEAD_BODYPAINT, getTEImage( TEX_HEAD_BODYPAINT ), head_baked_ready ); */
- for (LLVOAvatarDictionary::baked_map_t::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
+
+ for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end();
- baked_iter++)
+ ++baked_iter)
{
const EBakedTextureIndex baked_index = baked_iter->first;
- const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = baked_iter->second;
+ const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second;
for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin();
local_tex_iter != baked_dict->mLocalTextures.end();
- local_tex_iter++)
+ ++local_tex_iter)
{
const ETextureIndex texture_index = *local_tex_iter;
- const BOOL is_baked_ready = (is_layer_baked[baked_index] && mBakedTextureData[baked_index].mIsLoaded) || other_culled;
- setLocalTexture(texture_index, getTEImage(texture_index), is_baked_ready );
- }
- }
- removeMissingBakedTextures();
-}
-
-//-----------------------------------------------------------------------------
-// setLocalTexture()
-//-----------------------------------------------------------------------------
-void LLVOAvatar::setLocalTexture( ETextureIndex index, LLViewerImage* tex, BOOL baked_version_ready )
-{
- if (!isIndexLocalTexture(index)) return;
-
- S32 desired_discard = mIsSelf ? 0 : 2;
- LocalTextureData &local_tex_data = mLocalTextureData[index];
- if (!baked_version_ready)
- {
- if (tex != local_tex_data.mImage || local_tex_data.mIsBakedReady)
- {
- local_tex_data.mDiscard = MAX_DISCARD_LEVEL+1;
- }
- if (tex->getID() != IMG_DEFAULT_AVATAR)
- {
- if (local_tex_data.mDiscard > desired_discard)
+ const BOOL is_baked_ready = (is_layer_baked[baked_index] && mBakedTextureDatas[baked_index].mIsLoaded) || other_culled;
+ if (isSelf())
{
- S32 tex_discard = tex->getDiscardLevel();
- if (tex_discard >= 0 && tex_discard <= desired_discard)
- {
- local_tex_data.mDiscard = tex_discard;
- if( mIsSelf && !gAgent.cameraCustomizeAvatar() )
- {
- requestLayerSetUpdate( index );
- }
- else if( mIsSelf && gAgent.cameraCustomizeAvatar() )
- {
- LLVisualParamHint::requestHintUpdates();
- }
- }
- else
- {
- tex->setLoadedCallback( onLocalTextureLoaded, desired_discard, TRUE, FALSE, new LLAvatarTexData(getID(), index) );
- }
+ setBakedReady(texture_index, is_baked_ready);
}
- tex->setMinDiscardLevel(desired_discard);
}
}
- local_tex_data.mIsBakedReady = baked_version_ready;
- local_tex_data.mImage = tex;
+ removeMissingBakedTextures();
}
+// virtual
//-----------------------------------------------------------------------------
-// requestLayerSetUploads()
+// setLocalTexture()
//-----------------------------------------------------------------------------
-void LLVOAvatar::requestLayerSetUploads()
+void LLVOAvatar::setLocalTexture( ETextureIndex type, LLViewerTexture* in_tex, BOOL baked_version_ready, U32 index )
{
- for (U32 i = 0; i < mBakedTextureData.size(); i++)
- {
- bool layer_baked = isTextureDefined(mBakedTextureData[i].mTextureIndex);
- if ( !layer_baked && mBakedTextureData[i].mTexLayerSet )
- {
- mBakedTextureData[i].mTexLayerSet->requestUpload();
- }
- }
+ // invalid for anyone but self
+ llassert(0);
}
-
-//-----------------------------------------------------------------------------
-// setCompositeUpdatesEnabled()
-//-----------------------------------------------------------------------------
-void LLVOAvatar::setCompositeUpdatesEnabled( BOOL b )
+//virtual
+void LLVOAvatar::setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index)
{
- for (U32 i = 0; i < mBakedTextureData.size(); i++)
- {
- if (mBakedTextureData[i].mTexLayerSet )
- {
- mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled( b );
- }
- }
+ // invalid for anyone but self
+ llassert(0);
}
void LLVOAvatar::addChat(const LLChat& chat)
@@ -7095,184 +6098,74 @@ void LLVOAvatar::clearChat()
mChats.clear();
}
-S32 LLVOAvatar::getLocalDiscardLevel( ETextureIndex index )
+// adds a morph mask to the appropriate baked texture structure
+void LLVOAvatar::addMaskedMorph(EBakedTextureIndex index, LLPolyMorphTarget* morph_target, BOOL invert, std::string layer)
{
- if (!isIndexLocalTexture(index)) return FALSE;
-
- LocalTextureData &local_tex_data = mLocalTextureData[index];
- if (index >= 0
- && getLocalTextureID(index) != IMG_DEFAULT_AVATAR
- && !local_tex_data.mImage->isMissingAsset())
- {
- return local_tex_data.mImage->getDiscardLevel();
- }
- else
+ if (index < BAKED_NUM_INDICES)
{
- // We don't care about this (no image associated with the layer) treat as fully loaded.
- return 0;
+ LLMaskedMorph *morph = new LLMaskedMorph(morph_target, invert, layer);
+ mBakedTextureDatas[index].mMaskedMorphs.push_front(morph);
}
}
-//-----------------------------------------------------------------------------
-// isLocalTextureDataFinal()
-// Returns true if the highest quality discard level exists for every texture
-// in the layerset.
-//-----------------------------------------------------------------------------
-BOOL LLVOAvatar::isLocalTextureDataFinal( LLTexLayerSet* layerset )
+// returns TRUE if morph masks are present and not valid for a given baked texture, FALSE otherwise
+BOOL LLVOAvatar::morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex index)
{
- for (U32 i = 0; i < mBakedTextureData.size(); i++)
+ if (index >= BAKED_NUM_INDICES)
{
- if (layerset == mBakedTextureData[i].mTexLayerSet)
- {
- const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i);
- for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin();
- local_tex_iter != baked_dict->mLocalTextures.end();
- local_tex_iter++)
- {
- if (getLocalDiscardLevel(*local_tex_iter) != 0)
- {
- return FALSE;
- }
- }
- return TRUE;
- }
+ return FALSE;
}
- llassert(0);
- return FALSE;
-}
-
-//-----------------------------------------------------------------------------
-// isLocalTextureDataAvailable()
-// Returns true if at least the lowest quality discard level exists for every texture
-// in the layerset.
-//-----------------------------------------------------------------------------
-BOOL LLVOAvatar::isLocalTextureDataAvailable( LLTexLayerSet* layerset )
-{
- /* if( layerset == mBakedTextureData[BAKED_HEAD].mTexLayerSet )
- return getLocalDiscardLevel( TEX_HEAD_BODYPAINT ) >= 0; */
- for (LLVOAvatarDictionary::baked_map_t::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
- baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end();
- baked_iter++)
+ if (!mBakedTextureDatas[index].mMaskedMorphs.empty())
{
- const EBakedTextureIndex baked_index = baked_iter->first;
- if (layerset == mBakedTextureData[baked_index].mTexLayerSet)
+ if (isSelf())
{
- bool ret = true;
- const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = baked_iter->second;
- for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin();
- local_tex_iter != baked_dict->mLocalTextures.end();
- local_tex_iter++)
+ LLTexLayerSet *layer_set = mBakedTextureDatas[index].mTexLayerSet;
+ if (layer_set)
{
- ret &= (getLocalDiscardLevel(*local_tex_iter) >= 0);
+ return !layer_set->isMorphValid();
}
- return ret;
}
- }
- llassert(0);
- return FALSE;
-}
-
-
-//-----------------------------------------------------------------------------
-// getBakedTE()
-// Used by the LayerSet. (Layer sets don't in general know what textures depend on them.)
-//-----------------------------------------------------------------------------
-ETextureIndex LLVOAvatar::getBakedTE( LLTexLayerSet* layerset )
-{
- for (U32 i = 0; i < mBakedTextureData.size(); i++)
- {
- if (layerset == mBakedTextureData[i].mTexLayerSet )
+ else
{
- return mBakedTextureData[i].mTextureIndex;
+ return FALSE;
}
}
- llassert(0);
- return TEX_HEAD_BAKED;
+ return FALSE;
}
-//-----------------------------------------------------------------------------
-// setNewBakedTexture()
-// A new baked texture has been successfully uploaded and we can start using it now.
-//-----------------------------------------------------------------------------
-void LLVOAvatar::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid )
+void LLVOAvatar::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLVOAvatarDefines::EBakedTextureIndex index)
{
- // Baked textures live on other sims.
- LLHost target_host = getObjectHost();
- setTEImage( te, gImageList.getImageFromHost( uuid, target_host ) );
- updateMeshTextures();
- dirtyMesh();
-
-
- LLVOAvatar::cullAvatarsByPixelArea();
-
- /* switch(te)
- case TEX_HEAD_BAKED:
- llinfos << "New baked texture: HEAD" << llendl; */
- const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = LLVOAvatarDictionary::getInstance()->getTexture(te);
- if (text_dict->mIsBakedTexture)
- {
- llinfos << "New baked texture: " << text_dict->mName << " UUID: " << uuid <<llendl;
- mBakedTextureData[text_dict->mBakedTextureIndex].mTexLayerSet->requestUpdate();
- }
- else
- {
- llwarns << "New baked texture: unknown te " << te << llendl;
- }
-
- // dumpAvatarTEs( "setNewBakedTexture() send" );
- // RN: throttle uploads
- if (!hasPendingBakedUploads())
+ if (index >= BAKED_NUM_INDICES)
{
- gAgent.sendAgentSetAppearance();
+ llwarns << "invalid baked texture index passed to applyMorphMask" << llendl;
+ return;
}
-}
-bool LLVOAvatar::hasPendingBakedUploads()
-{
- for (U32 i = 0; i < mBakedTextureData.size(); i++)
+ for (morph_list_t::const_iterator iter = mBakedTextureDatas[index].mMaskedMorphs.begin();
+ iter != mBakedTextureDatas[index].mMaskedMorphs.end(); ++iter)
{
- bool upload_pending = (mBakedTextureData[i].mTexLayerSet && mBakedTextureData[i].mTexLayerSet->getComposite()->uploadPending());
- if (upload_pending)
- {
- return true;
- }
+ const LLMaskedMorph* maskedMorph = (*iter);
+ maskedMorph->mMorphTarget->applyMask(tex_data, width, height, num_components, maskedMorph->mInvert);
}
- return false;
}
-//-----------------------------------------------------------------------------
-// setCachedBakedTexture()
-// A baked texture id was received from a cache query, make it active
-//-----------------------------------------------------------------------------
-void LLVOAvatar::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid )
-{
- setTETexture( te, uuid );
-
- /* switch(te)
- case TEX_HEAD_BAKED:
- if( mHeadLayerSet )
- mHeadLayerSet->cancelUpload(); */
- for (U32 i = 0; i < mBakedTextureData.size(); i++)
- {
- if ( mBakedTextureData[i].mTextureIndex == te && mBakedTextureData[i].mTexLayerSet)
- {
- mBakedTextureData[i].mTexLayerSet->cancelUpload();
- }
- }
-}
//-----------------------------------------------------------------------------
-// releaseUnneccesaryTextures()
+// releaseComponentTextures()
// release any component texture UUIDs for which we have a baked texture
+// ! BACKWARDS COMPATIBILITY !
+// This is only called for non-self avatars, it can be taken out once component
+// textures aren't communicated by non-self avatars.
//-----------------------------------------------------------------------------
-void LLVOAvatar::releaseUnnecessaryTextures()
+void LLVOAvatar::releaseComponentTextures()
{
- // Backwards Compat: detect if the baked hair texture actually wasn't sent, and if so set to default
- if (isTextureDefined(TEX_HAIR_BAKED) && getTEImage(TEX_HAIR_BAKED)->getID() == getTEImage(TEX_SKIRT_BAKED)->getID())
+ // ! BACKWARDS COMPATIBILITY !
+ // Detect if the baked hair texture actually wasn't sent, and if so set to default
+ if (isTextureDefined(TEX_HAIR_BAKED) && getImage(TEX_HAIR_BAKED,0)->getID() == getImage(TEX_SKIRT_BAKED,0)->getID())
{
- if (getTEImage(TEX_HAIR_BAKED)->getID() != IMG_INVISIBLE)
+ if (getImage(TEX_HAIR_BAKED,0)->getID() != IMG_INVISIBLE)
{
// Regression case of messaging system. Expected 21 textures, received 20. last texture is not valid so set to default
setTETexture(TEX_HAIR_BAKED, IMG_DEFAULT_AVATAR);
@@ -7281,7 +6174,7 @@ void LLVOAvatar::releaseUnnecessaryTextures()
for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
{
- const LLVOAvatarDictionary::BakedDictionaryEntry * bakedDicEntry = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index);
+ const LLVOAvatarDictionary::BakedEntry * bakedDicEntry = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index);
// skip if this is a skirt and av is not wearing one, or if we don't have a baked texture UUID
if (!isTextureDefined(bakedDicEntry->mTextureIndex)
&& ( (baked_index != BAKED_SKIRT) || isWearingWearableType(WT_SKIRT) ))
@@ -7297,131 +6190,89 @@ void LLVOAvatar::releaseUnnecessaryTextures()
}
}
-//-----------------------------------------------------------------------------
-// static
-// onCustomizeStart()
-//-----------------------------------------------------------------------------
-void LLVOAvatar::onCustomizeStart()
-{
- // We're no longer doing any baking or invalidating on entering
- // appearance editing mode. Leaving function in place in case
- // further changes require us to do something at this point - Nyx
-}
-
-//-----------------------------------------------------------------------------
-// static
-// onCustomizeEnd()
-//-----------------------------------------------------------------------------
-void LLVOAvatar::onCustomizeEnd()
-{
- LLVOAvatar *avatarp = gAgent.getAvatarObject();
- if (avatarp)
- {
- avatarp->invalidateAll();
- avatarp->requestLayerSetUploads();
- }
-}
-
-void LLVOAvatar::onChangeSelfInvisible(BOOL newvalue)
-{
- LLVOAvatar *avatarp = gAgent.getAvatarObject();
- if (avatarp)
- {
- if (newvalue)
- {
- // we have just requested to set the avatar's baked textures to invisible
- avatarp->setInvisible(TRUE);
- }
- else
- {
- avatarp->setInvisible(FALSE);
- }
- }
-}
-
-
-BOOL LLVOAvatar::teToColorParams( ETextureIndex te, const char* param_name[3] )
+//static
+BOOL LLVOAvatar::teToColorParams( ETextureIndex te, U32 *param_name )
{
switch( te )
{
- case TEX_UPPER_SHIRT:
- param_name[0] = "shirt_red";
- param_name[1] = "shirt_green";
- param_name[2] = "shirt_blue";
- break;
-
- case TEX_LOWER_PANTS:
- param_name[0] = "pants_red";
- param_name[1] = "pants_green";
- param_name[2] = "pants_blue";
- break;
-
- case TEX_LOWER_SHOES:
- param_name[0] = "shoes_red";
- param_name[1] = "shoes_green";
- param_name[2] = "shoes_blue";
- break;
-
- case TEX_LOWER_SOCKS:
- param_name[0] = "socks_red";
- param_name[1] = "socks_green";
- param_name[2] = "socks_blue";
- break;
-
- case TEX_UPPER_JACKET:
- case TEX_LOWER_JACKET:
- param_name[0] = "jacket_red";
- param_name[1] = "jacket_green";
- param_name[2] = "jacket_blue";
- break;
-
- case TEX_UPPER_GLOVES:
- param_name[0] = "gloves_red";
- param_name[1] = "gloves_green";
- param_name[2] = "gloves_blue";
- break;
-
- case TEX_UPPER_UNDERSHIRT:
- param_name[0] = "undershirt_red";
- param_name[1] = "undershirt_green";
- param_name[2] = "undershirt_blue";
- break;
+ case TEX_UPPER_SHIRT:
+ param_name[0] = 803; //"shirt_red";
+ param_name[1] = 804; //"shirt_green";
+ param_name[2] = 805; //"shirt_blue";
+ break;
+
+ case TEX_LOWER_PANTS:
+ param_name[0] = 806; //"pants_red";
+ param_name[1] = 807; //"pants_green";
+ param_name[2] = 808; //"pants_blue";
+ break;
+
+ case TEX_LOWER_SHOES:
+ param_name[0] = 812; //"shoes_red";
+ param_name[1] = 813; //"shoes_green";
+ param_name[2] = 817; //"shoes_blue";
+ break;
+
+ case TEX_LOWER_SOCKS:
+ param_name[0] = 818; //"socks_red";
+ param_name[1] = 819; //"socks_green";
+ param_name[2] = 820; //"socks_blue";
+ break;
+
+ case TEX_UPPER_JACKET:
+ case TEX_LOWER_JACKET:
+ param_name[0] = 834; //"jacket_red";
+ param_name[1] = 835; //"jacket_green";
+ param_name[2] = 836; //"jacket_blue";
+ break;
+
+ case TEX_UPPER_GLOVES:
+ param_name[0] = 827; //"gloves_red";
+ param_name[1] = 829; //"gloves_green";
+ param_name[2] = 830; //"gloves_blue";
+ break;
+
+ case TEX_UPPER_UNDERSHIRT:
+ param_name[0] = 821; //"undershirt_red";
+ param_name[1] = 822; //"undershirt_green";
+ param_name[2] = 823; //"undershirt_blue";
+ break;
- case TEX_LOWER_UNDERPANTS:
- param_name[0] = "underpants_red";
- param_name[1] = "underpants_green";
- param_name[2] = "underpants_blue";
- break;
-
- case TEX_SKIRT:
- param_name[0] = "skirt_red";
- param_name[1] = "skirt_green";
- param_name[2] = "skirt_blue";
- break;
-
- default:
- llassert(0);
- return FALSE;
+ case TEX_LOWER_UNDERPANTS:
+ param_name[0] = 824; //"underpants_red";
+ param_name[1] = 825; //"underpants_green";
+ param_name[2] = 826; //"underpants_blue";
+ break;
+
+ case TEX_SKIRT:
+ param_name[0] = 921; //"skirt_red";
+ param_name[1] = 922; //"skirt_green";
+ param_name[2] = 923; //"skirt_blue";
+ break;
+
+ default:
+ llassert(0);
+ return FALSE;
}
return TRUE;
}
-void LLVOAvatar::setClothesColor( ETextureIndex te, const LLColor4& new_color, BOOL set_by_user )
+void LLVOAvatar::setClothesColor( ETextureIndex te, const LLColor4& new_color, BOOL upload_bake )
{
- const char* param_name[3];
+ U32 param_name[3];
if( teToColorParams( te, param_name ) )
{
- setVisualParamWeight( param_name[0], new_color.mV[VX], set_by_user );
- setVisualParamWeight( param_name[1], new_color.mV[VY], set_by_user );
- setVisualParamWeight( param_name[2], new_color.mV[VZ], set_by_user );
+ setVisualParamWeight( param_name[0], new_color.mV[VX], upload_bake );
+ setVisualParamWeight( param_name[1], new_color.mV[VY], upload_bake );
+ setVisualParamWeight( param_name[2], new_color.mV[VZ], upload_bake );
}
}
LLColor4 LLVOAvatar::getClothesColor( ETextureIndex te )
{
LLColor4 color;
- const char* param_name[3];
+ U32 param_name[3];
if( teToColorParams( te, param_name ) )
{
color.mV[VX] = getVisualParamWeight( param_name[0] );
@@ -7431,140 +6282,54 @@ LLColor4 LLVOAvatar::getClothesColor( ETextureIndex te )
return color;
}
+// static
+LLColor4 LLVOAvatar::getDummyColor()
+{
+ return DUMMY_COLOR;
+}
-
-
-void LLVOAvatar::dumpAvatarTEs( const std::string& context )
+void LLVOAvatar::dumpAvatarTEs( const std::string& context ) const
{
/* const char* te_name[] = {
"TEX_HEAD_BODYPAINT ",
"TEX_UPPER_SHIRT ", */
- llinfos << (mIsSelf ? "Self: " : "Other: ") << context << llendl;
- for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
+ llinfos << (isSelf() ? "Self: " : "Other: ") << context << llendl;
+ for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
- iter++)
+ ++iter)
{
- const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second;
- const LLViewerImage* te_image = getTEImage(iter->first);
+ const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
+ // TODO: handle multiple textures for self
+ const LLViewerTexture* te_image = getImage(iter->first,0);
if( !te_image )
{
- llinfos << " " << text_dict->mName << ": null ptr" << llendl;
+ llinfos << " " << texture_dict->mName << ": null ptr" << llendl;
}
else if( te_image->getID().isNull() )
{
- llinfos << " " << text_dict->mName << ": null UUID" << llendl;
+ llinfos << " " << texture_dict->mName << ": null UUID" << llendl;
}
else if( te_image->getID() == IMG_DEFAULT )
{
- llinfos << " " << text_dict->mName << ": IMG_DEFAULT" << llendl;
+ llinfos << " " << texture_dict->mName << ": IMG_DEFAULT" << llendl;
}
else if( te_image->getID() == IMG_DEFAULT_AVATAR )
{
- llinfos << " " << text_dict->mName << ": IMG_DEFAULT_AVATAR" << llendl;
+ llinfos << " " << texture_dict->mName << ": IMG_DEFAULT_AVATAR" << llendl;
}
else
{
- llinfos << " " << text_dict->mName << ": " << te_image->getID() << llendl;
+ llinfos << " " << texture_dict->mName << ": " << te_image->getID() << llendl;
}
}
}
-//-----------------------------------------------------------------------------
-// updateAttachmentVisibility()
-//-----------------------------------------------------------------------------
-void LLVOAvatar::updateAttachmentVisibility(U32 camera_mode)
-{
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
- {
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getIsHUDAttachment())
- {
- attachment->setAttachmentVisibility(TRUE);
- }
- else
- {
- switch (camera_mode)
- {
- case CAMERA_MODE_MOUSELOOK:
- if (LLVOAvatar::sVisibleInFirstPerson && attachment->getVisibleInFirstPerson())
- {
- attachment->setAttachmentVisibility(TRUE);
- }
- else
- {
- attachment->setAttachmentVisibility(FALSE);
- }
- break;
- default:
- attachment->setAttachmentVisibility(TRUE);
- break;
- }
- }
- }
-}
-
-// Given a texture entry, determine which wearable type owns it.
-// static
-LLUUID LLVOAvatar::getDefaultTEImageID(ETextureIndex index )
-{
- /* switch( index )
- case TEX_UPPER_SHIRT: return LLUUID( gSavedSettings.getString("UIImgDefaultShirtUUID") ); */
- const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = LLVOAvatarDictionary::getInstance()->getTexture(index);
- const std::string &default_image_name = text_dict->mDefaultImageName;
- if (default_image_name == "")
- {
- return IMG_DEFAULT_AVATAR;
- }
- else
- {
- return LLUUID(gSavedSettings.getString(default_image_name));
- }
-}
-
-
-void LLVOAvatar::setInvisible(BOOL newvalue)
-{
- if (newvalue)
- {
- setCompositeUpdatesEnabled(FALSE);
- for (U32 i = 0; i < mBakedTextureData.size(); i++ )
- {
- setNewBakedTexture(mBakedTextureData[i].mTextureIndex, IMG_INVISIBLE);
- }
- gAgent.sendAgentSetAppearance();
- }
- else
- {
- setCompositeUpdatesEnabled(TRUE);
- invalidateAll();
- requestLayerSetUploads();
- gAgent.sendAgentSetAppearance();
- }
-}
-
-LLColor4 LLVOAvatar::getDummyColor()
-{
- return DUMMY_COLOR;
-}
-
-// Given a texture entry, determine which wearable type owns it.
-// static
-EWearableType LLVOAvatar::getTEWearableType(ETextureIndex index )
-{
- /* switch(index)
- case TEX_UPPER_SHIRT:
- return WT_SHIRT; */
- return LLVOAvatarDictionary::getInstance()->getTexture(index)->mWearableType;
-}
-
// Unlike most wearable functions, this works for both self and other.
-BOOL LLVOAvatar::isWearingWearableType( EWearableType type )
+BOOL LLVOAvatar::isWearingWearableType(EWearableType type) const
{
if (mIsDummy) return TRUE;
- switch( type )
+ switch(type)
{
case WT_SHAPE:
case WT_SKIN:
@@ -7578,49 +6343,22 @@ BOOL LLVOAvatar::isWearingWearableType( EWearableType type )
/* switch(type)
case WT_SHIRT:
indicator_te = TEX_UPPER_SHIRT; */
- for (LLVOAvatarDictionary::texture_map_t::const_iterator tex_iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
+ for (LLVOAvatarDictionary::Textures::const_iterator tex_iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
tex_iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
- tex_iter++)
+ ++tex_iter)
{
- const LLVOAvatarDefines::ETextureIndex index = tex_iter->first;
- const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = tex_iter->second;
- if (text_dict->mWearableType == type)
+ const LLVOAvatarDictionary::TextureEntry *texture_dict = tex_iter->second;
+ if (texture_dict->mWearableType == type)
{
- // If you're checking your own clothing, check the component texture
- if (mIsSelf)
- {
- if (isTextureDefined(index))
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- }
-
// If you're checking another avatar's clothing, you don't have component textures.
// Thus, you must check to see if the corresponding baked texture is defined.
// NOTE: this is a poor substitute if you actually want to know about individual pieces of clothing
// this works for detecting a skirt (most important), but is ineffective at any piece of clothing that
// gets baked into a texture that always exists (upper or lower).
- const std::string name = text_dict->mName;
- for (LLVOAvatarDictionary::baked_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
- iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end();
- iter++)
+ if (texture_dict->mIsUsedByBakedTexture)
{
- const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = iter->second;
- if (baked_dict->mName == name)
- {
- if (isTextureDefined(baked_dict->mTextureIndex))
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- }
+ const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
+ return isTextureDefined(LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex);
}
return FALSE;
}
@@ -7629,41 +6367,6 @@ BOOL LLVOAvatar::isWearingWearableType( EWearableType type )
}
//-----------------------------------------------------------------------------
-// updatedWearable( EWearableType type )
-// forces an update to any baked textures relevant to type.
-// Should be called only on saving the wearable
-//-----------------------------------------------------------------------------
-void LLVOAvatar::wearableUpdated( EWearableType type )
-{
- for (LLVOAvatarDictionary::wearable_map_t::const_iterator wearable_iter = LLVOAvatarDictionary::getInstance()->getWearables().begin();
- wearable_iter != LLVOAvatarDictionary::getInstance()->getWearables().end();
- wearable_iter++)
- {
- const LLVOAvatarDictionary::WearableDictionaryEntry *wearable_dict = wearable_iter->second;
- const LLVOAvatarDefines::EBakedTextureIndex index = wearable_iter->first;
- if (wearable_dict)
- {
- for (LLVOAvatarDefines::wearables_vec_t::const_iterator type_iter = wearable_dict->mWearablesVec.begin();
- type_iter != wearable_dict->mWearablesVec.end();
- type_iter++)
- {
- const EWearableType comp_type = *type_iter;
- if (comp_type == type)
- {
- if (mBakedTextureData[index].mTexLayerSet)
- {
- mBakedTextureData[index].mTexLayerSet->requestUpdate();
- mBakedTextureData[index].mTexLayerSet->requestUpload();
- }
- break;
- }
- }
- }
- }
-}
-
-
-//-----------------------------------------------------------------------------
// clampAttachmentPositions()
//-----------------------------------------------------------------------------
void LLVOAvatar::clampAttachmentPositions()
@@ -7673,10 +6376,10 @@ void LLVOAvatar::clampAttachmentPositions()
return;
}
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
+ iter != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
+ LLViewerJointAttachment* attachment = iter->second;
if (attachment)
{
attachment->clampObjectPosition();
@@ -7687,11 +6390,11 @@ void LLVOAvatar::clampAttachmentPositions()
BOOL LLVOAvatar::hasHUDAttachment() const
{
for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
+ iter != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::const_iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getIsHUDAttachment() && attachment->getObject())
+ LLViewerJointAttachment* attachment = iter->second;
+ if (attachment->getIsHUDAttachment() && attachment->getNumObjects() > 0)
{
return TRUE;
}
@@ -7703,24 +6406,34 @@ LLBBox LLVOAvatar::getHUDBBox() const
{
LLBBox bbox;
for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
+ iter != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::const_iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getIsHUDAttachment() && attachment->getObject())
+ LLViewerJointAttachment* attachment = iter->second;
+ if (attachment->getIsHUDAttachment())
{
- LLViewerObject* hud_object = attachment->getObject();
-
- // initialize bounding box to contain identity orientation and center point for attached object
- bbox.addPointLocal(hud_object->getPosition());
- // add rotated bounding box for attached object
- bbox.addBBoxAgent(hud_object->getBoundingBoxAgent());
- LLViewerObject::const_child_list_t& child_list = hud_object->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- LLViewerObject* child_objectp = *iter;
- bbox.addBBoxAgent(child_objectp->getBoundingBoxAgent());
+ const LLViewerObject* attached_object = (*attachment_iter);
+ if (attached_object == NULL)
+ {
+ llwarns << "HUD attached object is NULL!" << llendl;
+ continue;
+ }
+ // initialize bounding box to contain identity orientation and center point for attached object
+ bbox.addPointLocal(attached_object->getPosition());
+ // add rotated bounding box for attached object
+ bbox.addBBoxAgent(attached_object->getBoundingBoxAgent());
+ LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
+ for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
+ iter != child_list.end();
+ ++iter)
+ {
+ const LLViewerObject* child_objectp = *iter;
+ bbox.addBBoxAgent(child_objectp->getBoundingBoxAgent());
+ }
}
}
}
@@ -7741,18 +6454,18 @@ void LLVOAvatar::onFirstTEMessageReceived()
{
mFirstTEMessageReceived = TRUE;
- for (U32 i = 0; i < mBakedTextureData.size(); i++)
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
{
- bool layer_baked = isTextureDefined(mBakedTextureData[i].mTextureIndex);
+ const BOOL layer_baked = isTextureDefined(mBakedTextureDatas[i].mTextureIndex);
// Use any baked textures that we have even if they haven't downloaded yet.
// (That is, don't do a transition from unbaked to baked.)
if (layer_baked)
{
- LLViewerImage* image = getTEImage( mBakedTextureData[i].mTextureIndex );
- mBakedTextureData[i].mLastTextureIndex = image->getID();
+ LLViewerFetchedTexture* image = LLViewerTextureManager::staticCastToFetchedTexture(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ;
+ mBakedTextureDatas[i].mLastTextureIndex = image->getID();
// If we have more than one texture for the other baked layers, we'll want to call this for them too.
- if ( (i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER) )
+ if ( (image->getID() != IMG_INVISIBLE) && ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) )
{
image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ));
}
@@ -7760,7 +6473,8 @@ void LLVOAvatar::onFirstTEMessageReceived()
}
}
- updateMeshTextures();
+ mMeshTexturesDirty = TRUE;
+ gPipeline.markGLRebuild(this);
}
}
@@ -7782,7 +6496,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
mFirstAppearanceMessageReceived = TRUE;
- if( mIsSelf )
+ if( isSelf() )
{
llwarns << "Received AvatarAppearance for self" << llendl;
if( mFirstTEMessageReceived )
@@ -7799,45 +6513,41 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
ESex old_sex = getSex();
-// llinfos << "ady LLVOAvatar::processAvatarAppearance()" << llendl;
+// llinfos << "LLVOAvatar::processAvatarAppearance()" << llendl;
// dumpAvatarTEs( "PRE processAvatarAppearance()" );
unpackTEMessage(mesgsys, _PREHASH_ObjectData);
// dumpAvatarTEs( "POST processAvatarAppearance()" );
// prevent the overwriting of valid baked textures with invalid baked textures
- for (U8 baked_index = 0; baked_index < mBakedTextureData.size(); baked_index++)
+ for (U8 baked_index = 0; baked_index < mBakedTextureDatas.size(); baked_index++)
{
- if (!isTextureDefined(mBakedTextureData[baked_index].mTextureIndex)
- && mBakedTextureData[baked_index].mLastTextureIndex != IMG_DEFAULT
+ if (!isTextureDefined(mBakedTextureDatas[baked_index].mTextureIndex)
+ && mBakedTextureDatas[baked_index].mLastTextureIndex != IMG_DEFAULT
&& baked_index != BAKED_SKIRT)
{
- setTEImage(mBakedTextureData[baked_index].mTextureIndex, gImageList.getImage(mBakedTextureData[baked_index].mLastTextureIndex));
+ setTEImage(mBakedTextureDatas[baked_index].mTextureIndex,
+ LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
}
}
- //llinfos << "Received AvatarAppearance: " << (mIsSelf ? "(self): " : "(other): ") << std::endl <<
- // (isTextureDefined(TEX_HEAD_BAKED) ? "HEAD " : "head " ) << (getTEImage(TEX_HEAD_BAKED)->getID()) << std::endl <<
- // (isTextureDefined(TEX_UPPER_BAKED) ? "UPPER " : "upper " ) << (getTEImage(TEX_UPPER_BAKED)->getID()) << std::endl <<
- // (isTextureDefined(TEX_LOWER_BAKED) ? "LOWER " : "lower " ) << (getTEImage(TEX_LOWER_BAKED)->getID()) << std::endl <<
- // (isTextureDefined(TEX_SKIRT_BAKED) ? "SKIRT " : "skirt " ) << (getTEImage(TEX_SKIRT_BAKED)->getID()) << std::endl <<
- // (isTextureDefined(TEX_HAIR_BAKED) ? "HAIR" : "hair " ) << (getTEImage(TEX_HAIR_BAKED)->getID()) << std::endl <<
- // (isTextureDefined(TEX_EYES_BAKED) ? "EYES" : "eyes" ) << (getTEImage(TEX_EYES_BAKED)->getID()) << llendl ;
-
- if( !mFirstTEMessageReceived )
+ if( !is_first_appearance_message )
{
onFirstTEMessageReceived();
}
setCompositeUpdatesEnabled( FALSE );
+ mMeshTexturesDirty = TRUE;
+ gPipeline.markGLRebuild(this);
- if (!mIsSelf)
+ // ! BACKWARDS COMPATIBILITY !
+ // Non-self avatars will no longer have component textures
+ if (!isSelf())
{
- releaseUnnecessaryTextures();
+ releaseComponentTextures();
}
- updateMeshTextures(); // enables updates for laysets without baked textures.
-
+
// parse visual params
S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam);
if( num_blocks > 1 )
@@ -7901,7 +6611,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
{
if (interp_params)
{
- startAppearanceAnimation(FALSE, FALSE);
+ startAppearanceAnimation();
}
updateVisualParams();
@@ -7954,7 +6664,7 @@ void LLVOAvatar::getAnimNames( LLDynamicArray<std::string>* names )
names->put( "enter_away_from_keyboard_state" );
}
-void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
+void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
{
if (!userdata) return;
@@ -7993,39 +6703,31 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi,
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
/* if( id == head_baked->getID() )
- if (self->mBakedTextureData[BAKED_HEAD].mTexLayerSet)
+ if (self->mBakedTextureDatas[BAKED_HEAD].mTexLayerSet)
//llinfos << "onBakedTextureMasksLoaded for head " << id << " discard = " << discard_level << llendl;
- self->mBakedTextureData[BAKED_HEAD].mTexLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1);
+ self->mBakedTextureDatas[BAKED_HEAD].mTexLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1);
maskData->mLastDiscardLevel = discard_level; */
- bool found_texture_id = false;
- for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
+ BOOL found_texture_id = false;
+ for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
- iter++)
+ ++iter)
{
- const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second;
- if (text_dict->mIsUsedByBakedTexture)
+ const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
+ if (texture_dict->mIsUsedByBakedTexture)
{
const ETextureIndex texture_index = iter->first;
- const LLViewerImage *baked_img = self->getTEImage(texture_index);
- if (id == baked_img->getID())
+ const LLViewerTexture *baked_img = self->getImage(texture_index, 0);
+ if (baked_img && id == baked_img->getID())
{
- const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex;
- if (self->mBakedTextureData[baked_index].mTexLayerSet)
- {
- //llinfos << "onBakedTextureMasksLoaded for " << text_dict->mName << " " << id << " discard = " << discard_level << llendl;
- self->mBakedTextureData[baked_index].mTexLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1);
- maskData->mLastDiscardLevel = discard_level;
- if (self->mBakedTextureData[baked_index].mMaskTexName)
- {
- LLImageGL::deleteTextures(1, &(self->mBakedTextureData[baked_index].mMaskTexName));
- }
- self->mBakedTextureData[baked_index].mMaskTexName = gl_name;
- }
- else
+ const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
+ self->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1, baked_index);
+ maskData->mLastDiscardLevel = discard_level;
+ if (self->mBakedTextureDatas[baked_index].mMaskTexName)
{
- llwarns << "onBakedTextureMasksLoaded: no LayerSet for " << text_dict->mName << "." << llendl;
+ LLImageGL::deleteTextures(1, &(self->mBakedTextureDatas[baked_index].mMaskTexName));
}
+ self->mBakedTextureDatas[baked_index].mMaskTexName = gl_name;
found_texture_id = true;
break;
}
@@ -8052,7 +6754,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi,
}
// static
-void LLVOAvatar::onInitialBakedTextureLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
+void LLVOAvatar::onInitialBakedTextureLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
{
LLUUID *avatar_idp = (LLUUID *)userdata;
LLVOAvatar *selfp = (LLVOAvatar *)gObjectList.findObject(*avatar_idp);
@@ -8067,7 +6769,7 @@ void LLVOAvatar::onInitialBakedTextureLoaded( BOOL success, LLViewerImage *src_v
}
}
-void LLVOAvatar::onBakedTextureLoaded(BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata)
+void LLVOAvatar::onBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata)
{
//llinfos << "onBakedTextureLoaded: " << src_vi->getID() << llendl;
@@ -8100,28 +6802,28 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id )
mLastHeadBakedID = id;
mHeadMesh0.setTexture( head_baked );
mHeadMesh1.setTexture( head_baked ); */
- for (U32 i = 0; i < mBakedTextureData.size(); i++)
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
{
- LLViewerImage* image_baked = getTEImage( mBakedTextureData[i].mTextureIndex );
+ LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 );
if (id == image_baked->getID())
{
- mBakedTextureData[i].mIsLoaded = true;
- mBakedTextureData[i].mIsUsed = true;
- mBakedTextureData[i].mLastTextureIndex = id;
- for (U32 k = 0; k < mBakedTextureData[i].mMeshes.size(); k++)
+ mBakedTextureDatas[i].mIsLoaded = true;
+ mBakedTextureDatas[i].mLastTextureIndex = id;
+ mBakedTextureDatas[i].mIsUsed = true;
+ for (U32 k = 0; k < mBakedTextureDatas[i].mMeshes.size(); k++)
{
- mBakedTextureData[i].mMeshes[k]->setTexture( image_baked );
+ mBakedTextureDatas[i].mMeshes[k]->setTexture( image_baked );
}
- if (mBakedTextureData[i].mTexLayerSet)
+ if (mBakedTextureDatas[i].mTexLayerSet)
{
- mBakedTextureData[i].mTexLayerSet->destroyComposite();
+ //mBakedTextureDatas[i].mTexLayerSet->destroyComposite();
}
- const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i);
+ const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i);
for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin();
local_tex_iter != baked_dict->mLocalTextures.end();
- local_tex_iter++)
+ ++local_tex_iter)
{
- setLocalTexture(*local_tex_iter, getTEImage(*local_tex_iter), TRUE);
+ if (isSelf()) setBakedReady(*local_tex_iter, TRUE);
}
// ! BACKWARDS COMPATIBILITY !
@@ -8129,9 +6831,9 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id )
// This is paired with similar code in updateMeshTextures that sets hair mesh color.
if (i == BAKED_HAIR)
{
- for (U32 i = 0; i < mBakedTextureData[BAKED_HAIR].mMeshes.size(); i++)
+ for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++)
{
- mBakedTextureData[BAKED_HAIR].mMeshes[i]->setColor( 1.f, 1.f, 1.f, 1.f );
+ mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( 1.f, 1.f, 1.f, 1.f );
}
}
}
@@ -8147,7 +6849,7 @@ void LLVOAvatar::dumpArchetypeXML( void* )
LLAPRFile outfile ;
outfile.open(gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,"new archetype.xml"), LL_APR_WB );
apr_file_t* file = outfile.getFileHandle() ;
- if( !file )
+ if (!file)
{
return;
}
@@ -8157,27 +6859,28 @@ void LLVOAvatar::dumpArchetypeXML( void* )
apr_file_printf( file, "\n\t<archetype name=\"???\">\n" );
// only body parts, not clothing.
- for( S32 type = WT_SHAPE; type <= WT_EYES; type++ )
+ for (S32 type = WT_SHAPE; type <= WT_EYES; type++)
{
- const std::string& wearable_name = LLWearable::typeToTypeName( (EWearableType) type );
+ const std::string& wearable_name = LLWearableDictionary::getTypeName((EWearableType)type);
apr_file_printf( file, "\n\t\t<!-- wearable: %s -->\n", wearable_name.c_str() );
- for( LLVisualParam* param = avatar->getFirstVisualParam(); param; param = avatar->getNextVisualParam() )
+ for (LLVisualParam* param = avatar->getFirstVisualParam(); param; param = avatar->getNextVisualParam())
{
LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param;
if( (viewer_param->getWearableType() == type) &&
(viewer_param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE) )
{
- apr_file_printf( file, "\t\t<param id=\"%d\" name=\"%s\" value=\"%.3f\"/>\n",
- viewer_param->getID(), viewer_param->getName().c_str(), viewer_param->getWeight() );
+ apr_file_printf(file, "\t\t<param id=\"%d\" name=\"%s\" value=\"%.3f\"/>\n",
+ viewer_param->getID(), viewer_param->getName().c_str(), viewer_param->getWeight());
}
}
- for(U8 te = 0; te < TEX_NUM_INDICES; te++)
+ for (U8 te = 0; te < TEX_NUM_INDICES; te++)
{
- if( LLVOAvatar::getTEWearableType((ETextureIndex)te) == type )
+ if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex)te) == type)
{
- LLViewerImage* te_image = avatar->getTEImage((ETextureIndex)te);
+ // MULTIPLE_WEARABLES: extend to multiple wearables?
+ LLViewerTexture* te_image = avatar->getImage((ETextureIndex)te, 0);
if( te_image )
{
std::string uuid_str;
@@ -8192,18 +6895,13 @@ void LLVOAvatar::dumpArchetypeXML( void* )
}
-U32 LLVOAvatar::getVisibilityRank()
-{
- return mVisibilityRank;
-}
-
void LLVOAvatar::setVisibilityRank(U32 rank)
{
if (mDrawable.isNull() || mDrawable->isDead())
- { //do nothing
+ {
+ // do nothing
return;
}
-
mVisibilityRank = rank;
}
@@ -8212,15 +6910,14 @@ S32 LLVOAvatar::getUnbakedPixelAreaRank()
{
S32 rank = 1;
for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
+ iter != LLCharacter::sInstances.end(); ++iter)
{
LLVOAvatar* inst = (LLVOAvatar*) *iter;
- if( inst == this )
+ if (inst == this)
{
return rank;
}
- else
- if( !inst->isDead() && !inst->isFullyBaked() )
+ else if (!inst->isDead() && !inst->isFullyBaked())
{
rank++;
}
@@ -8232,7 +6929,7 @@ S32 LLVOAvatar::getUnbakedPixelAreaRank()
struct CompareScreenAreaGreater
{
- bool operator()(const LLCharacter* const& lhs, const LLCharacter* const& rhs)
+ BOOL operator()(const LLCharacter* const& lhs, const LLCharacter* const& rhs)
{
return lhs->getPixelArea() > rhs->getPixelArea();
}
@@ -8246,7 +6943,7 @@ void LLVOAvatar::cullAvatarsByPixelArea()
// Update the avatars that have changed status
U32 rank = 0;
for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
+ iter != LLCharacter::sInstances.end(); ++iter)
{
LLVOAvatar* inst = (LLVOAvatar*) *iter;
BOOL culled;
@@ -8277,7 +6974,7 @@ void LLVOAvatar::cullAvatarsByPixelArea()
}
S32 grey_avatars = 0;
- if ( LLVOAvatar::areAllNearbyInstancesBaked(grey_avatars) )
+ if (LLVOAvatar::areAllNearbyInstancesBaked(grey_avatars))
{
LLVOAvatar::deleteCachedImages(false);
}
@@ -8299,202 +6996,41 @@ void LLVOAvatar::cullAvatarsByPixelArea()
}
}
-const LLUUID& LLVOAvatar::grabLocalTexture(ETextureIndex index)
-{
- if (canGrabLocalTexture(index))
- {
- return getTEImage( index )->getID();
- }
- return LLUUID::null;
-}
-
-BOOL LLVOAvatar::canGrabLocalTexture(ETextureIndex index)
-{
- // Check if the texture hasn't been baked yet.
- if (!isTextureDefined(index))
- {
- lldebugs << "getTEImage( " << (U32) index << " )->getID() == IMG_DEFAULT_AVATAR" << llendl;
- return FALSE;
- }
-
- if (gAgent.isGodlike())
- return TRUE;
-
- // Check permissions of textures that show up in the
- // baked texture. We don't want people copying people's
- // work via baked textures.
- /* switch(index)
- case TEX_EYES_BAKED:
- textures.push_back(TEX_EYES_IRIS); */
- const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = LLVOAvatarDictionary::getInstance()->getTexture(index);
- if (!text_dict->mIsUsedByBakedTexture) return FALSE;
-
- const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex;
- const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index);
- for (texture_vec_t::const_iterator iter = baked_dict->mLocalTextures.begin();
- iter != baked_dict->mLocalTextures.end();
- iter++)
- {
- const ETextureIndex t_index = (*iter);
- lldebugs << "Checking index " << (U32) t_index << llendl;
- const LLUUID& texture_id = getTEImage( t_index )->getID();
- if (texture_id != IMG_DEFAULT_AVATAR)
- {
- // Search inventory for this texture.
- LLViewerInventoryCategory::cat_array_t cats;
- LLViewerInventoryItem::item_array_t items;
- LLAssetIDMatches asset_id_matches(texture_id);
- gInventory.collectDescendentsIf(LLUUID::null,
- cats,
- items,
- LLInventoryModel::INCLUDE_TRASH,
- asset_id_matches);
-
- BOOL can_grab = FALSE;
- lldebugs << "item count for asset " << texture_id << ": " << items.count() << llendl;
- if (items.count())
- {
- // search for full permissions version
- for (S32 i = 0; i < items.count(); i++)
- {
- LLInventoryItem* itemp = items[i];
- LLPermissions item_permissions = itemp->getPermissions();
- if ( item_permissions.allowOperationBy(
- PERM_MODIFY, gAgent.getID(), gAgent.getGroupID()) &&
- item_permissions.allowOperationBy(
- PERM_COPY, gAgent.getID(), gAgent.getGroupID()) &&
- item_permissions.allowOperationBy(
- PERM_TRANSFER, gAgent.getID(), gAgent.getGroupID()) )
- {
- can_grab = TRUE;
- break;
- }
- }
- }
- if (!can_grab) return FALSE;
- }
- }
-
- return TRUE;
-}
-
-void LLVOAvatar::dumpLocalTextures()
-{
- llinfos << "Local Textures:" << llendl;
-
- /* ETextureIndex baked_equiv[] = {
- TEX_UPPER_BAKED,
- if (isTextureDefined(baked_equiv[i])) */
- for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
- iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
- iter++)
- {
- const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second;
- if (!text_dict->mIsLocalTexture || !text_dict->mIsUsedByBakedTexture)
- continue;
-
- const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex;
- const ETextureIndex baked_equiv = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex;
-
- const std::string &name = text_dict->mName;
- const LocalTextureData &local_tex_data = mLocalTextureData[iter->first];
- if (isTextureDefined(baked_equiv))
- {
-#if LL_RELEASE_FOR_DOWNLOAD
- // End users don't get to trivially see avatar texture IDs, makes textures
- // easier to steal. JC
- llinfos << "LocTex " << name << ": Baked " << llendl;
-#else
- llinfos << "LocTex " << name << ": Baked " << getTEImage( baked_equiv )->getID() << llendl;
-#endif
- }
- else if (local_tex_data.mImage.notNull())
- {
- if( local_tex_data.mImage->getID() == IMG_DEFAULT_AVATAR )
- {
- llinfos << "LocTex " << name << ": None" << llendl;
- }
- else
- {
- const LLViewerImage* image = local_tex_data.mImage;
-
- llinfos << "LocTex " << name << ": "
- << "Discard " << image->getDiscardLevel() << ", "
- << "(" << image->getWidth() << ", " << image->getHeight() << ") "
-#if !LL_RELEASE_FOR_DOWNLOAD
- // End users don't get to trivially see avatar texture IDs,
- // makes textures easier to steal
- << image->getID() << " "
-#endif
- << "Priority: " << image->getDecodePriority()
- << llendl;
- }
- }
- else
- {
- llinfos << "LocTex " << name << ": No LLViewerImage" << llendl;
- }
- }
-}
-
-void LLVOAvatar::startAppearanceAnimation(BOOL set_by_user, BOOL play_sound)
+void LLVOAvatar::startAppearanceAnimation()
{
if(!mAppearanceAnimating)
{
- mAppearanceAnimSetByUser = set_by_user;
mAppearanceAnimating = TRUE;
mAppearanceMorphTimer.reset();
mLastAppearanceBlendTime = 0.f;
}
}
-
+// virtual
void LLVOAvatar::removeMissingBakedTextures()
{
- if (!mIsSelf) return;
-
- BOOL removed = FALSE;
- for (U32 i = 0; i < mBakedTextureData.size(); i++)
- {
- const S32 te = mBakedTextureData[i].mTextureIndex;
- if (getTEImage(te)->isMissingAsset())
- {
- setTEImage(te, gImageList.getImage(IMG_DEFAULT_AVATAR));
- removed = TRUE;
- }
- }
-
- if (removed)
- {
- for(U32 i = 0; i < mBakedTextureData.size(); i++)
- {
- invalidateComposite(mBakedTextureData[i].mTexLayerSet, FALSE);
- }
- updateMeshTextures();
- requestLayerSetUploads();
- }
}
-
//-----------------------------------------------------------------------------
// LLVOAvatarXmlInfo
//-----------------------------------------------------------------------------
-LLVOAvatarXmlInfo::LLVOAvatarXmlInfo()
+LLVOAvatar::LLVOAvatarXmlInfo::LLVOAvatarXmlInfo()
: mTexSkinColorInfo(0), mTexHairColorInfo(0), mTexEyeColorInfo(0)
{
}
-LLVOAvatarXmlInfo::~LLVOAvatarXmlInfo()
+LLVOAvatar::LLVOAvatarXmlInfo::~LLVOAvatarXmlInfo()
{
std::for_each(mMeshInfoList.begin(), mMeshInfoList.end(), DeletePointer());
std::for_each(mSkeletalDistortionInfoList.begin(), mSkeletalDistortionInfoList.end(), DeletePointer());
std::for_each(mAttachmentInfoList.begin(), mAttachmentInfoList.end(), DeletePointer());
- delete mTexSkinColorInfo;
- delete mTexHairColorInfo;
- delete mTexEyeColorInfo;
+ deleteAndClear(mTexSkinColorInfo);
+ deleteAndClear(mTexHairColorInfo);
+ deleteAndClear(mTexEyeColorInfo);
std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer());
- std::for_each(mDriverInfoList.begin(), mDriverInfoList.end(), DeletePointer());
+ std::for_each(mDriverInfoList.begin(), mDriverInfoList.end(), DeletePointer());
+ std::for_each(mMorphMaskInfoList.begin(), mMorphMaskInfoList.end(), DeletePointer());
}
//-----------------------------------------------------------------------------
@@ -8606,7 +7142,7 @@ BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node)
//-----------------------------------------------------------------------------
// parseXmlSkeletonNode(): parses <skeleton> nodes from XML tree
//-----------------------------------------------------------------------------
-BOOL LLVOAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root)
+BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root)
{
LLXmlTreeNode* node = root->getChildByName( "skeleton" );
if( !node )
@@ -8712,7 +7248,7 @@ BOOL LLVOAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root)
//-----------------------------------------------------------------------------
// parseXmlMeshNodes(): parses <mesh> nodes from XML tree
//-----------------------------------------------------------------------------
-BOOL LLVOAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root)
+BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root)
{
for (LLXmlTreeNode* node = root->getChildByName( "mesh" );
node;
@@ -8802,7 +7338,7 @@ BOOL LLVOAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root)
//-----------------------------------------------------------------------------
// parseXmlColorNodes(): parses <global_color> nodes from XML tree
//-----------------------------------------------------------------------------
-BOOL LLVOAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root)
+BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root)
{
for (LLXmlTreeNode* color_node = root->getChildByName( "global_color" );
color_node;
@@ -8822,7 +7358,7 @@ BOOL LLVOAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root)
mTexSkinColorInfo = new LLTexGlobalColorInfo;
if( !mTexSkinColorInfo->parseXml( color_node ) )
{
- delete mTexSkinColorInfo; mTexSkinColorInfo = 0;
+ deleteAndClear(mTexSkinColorInfo);
llwarns << "avatar file: mTexSkinColor->parseXml() failed" << llendl;
return FALSE;
}
@@ -8837,7 +7373,7 @@ BOOL LLVOAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root)
mTexHairColorInfo = new LLTexGlobalColorInfo;
if( !mTexHairColorInfo->parseXml( color_node ) )
{
- delete mTexHairColorInfo; mTexHairColorInfo = 0;
+ deleteAndClear(mTexHairColorInfo);
llwarns << "avatar file: mTexHairColor->parseXml() failed" << llendl;
return FALSE;
}
@@ -8864,7 +7400,7 @@ BOOL LLVOAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root)
//-----------------------------------------------------------------------------
// parseXmlLayerNodes(): parses <layer_set> nodes from XML tree
//-----------------------------------------------------------------------------
-BOOL LLVOAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root)
+BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root)
{
for (LLXmlTreeNode* layer_node = root->getChildByName( "layer_set" );
layer_node;
@@ -8888,7 +7424,7 @@ BOOL LLVOAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root)
//-----------------------------------------------------------------------------
// parseXmlDriverNodes(): parses <driver_parameters> nodes from XML tree
//-----------------------------------------------------------------------------
-BOOL LLVOAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root)
+BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root)
{
LLXmlTreeNode* driver = root->getChildByName( "driver_parameters" );
if( driver )
@@ -8916,36 +7452,60 @@ BOOL LLVOAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root)
return TRUE;
}
-// warning: order(N) not order(1)
-S32 LLVOAvatar::getAttachmentCount()
+//-----------------------------------------------------------------------------
+// parseXmlDriverNodes(): parses <driver_parameters> nodes from XML tree
+//-----------------------------------------------------------------------------
+BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root)
{
- S32 count = mAttachmentPoints.size();
- return count;
-}
+ LLXmlTreeNode* masks = root->getChildByName( "morph_masks" );
+ if( !masks )
+ {
+ return FALSE;
+ }
-//virtual
-void LLVOAvatar::updateRegion(LLViewerRegion *regionp)
-{
- if (mIsSelf)
+ for (LLXmlTreeNode* grand_child = masks->getChildByName( "mask" );
+ grand_child;
+ grand_child = masks->getNextNamedChild())
{
- if (regionp->getHandle() != mLastRegionHandle)
+ LLVOAvatarMorphInfo* info = new LLVOAvatarMorphInfo();
+
+ static LLStdStringHandle name_string = LLXmlTree::addAttributeString("morph_name");
+ if (!grand_child->getFastAttributeString(name_string, info->mName))
{
- if (mLastRegionHandle != 0)
- {
- ++mRegionCrossingCount;
- F64 delta = (F64)mRegionCrossingTimer.getElapsedTimeF32();
- F64 avg = (mRegionCrossingCount == 1) ? 0 : LLViewerStats::getInstance()->getStat(LLViewerStats::ST_CROSSING_AVG);
- F64 delta_avg = (delta + avg*(mRegionCrossingCount-1)) / mRegionCrossingCount;
- LLViewerStats::getInstance()->setStat(LLViewerStats::ST_CROSSING_AVG, delta_avg);
+ llwarns << "No name supplied for morph mask." << llendl;
+ delete info;
+ continue;
+ }
- F64 max = (mRegionCrossingCount == 1) ? 0 : LLViewerStats::getInstance()->getStat(LLViewerStats::ST_CROSSING_MAX);
- max = llmax(delta, max);
- LLViewerStats::getInstance()->setStat(LLViewerStats::ST_CROSSING_MAX, max);
- }
- mLastRegionHandle = regionp->getHandle();
+ static LLStdStringHandle region_string = LLXmlTree::addAttributeString("body_region");
+ if (!grand_child->getFastAttributeString(region_string, info->mRegion))
+ {
+ llwarns << "No region supplied for morph mask." << llendl;
+ delete info;
+ continue;
+ }
+
+ static LLStdStringHandle layer_string = LLXmlTree::addAttributeString("layer");
+ if (!grand_child->getFastAttributeString(layer_string, info->mLayer))
+ {
+ llwarns << "No layer supplied for morph mask." << llendl;
+ delete info;
+ continue;
}
- mRegionCrossingTimer.reset();
+
+ // optional parameter. don't throw a warning if not present.
+ static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert");
+ grand_child->getFastAttributeBOOL(invert_string, info->mInvert);
+
+ mMorphMaskInfoList.push_back(info);
}
+
+ return TRUE;
+}
+
+//virtual
+void LLVOAvatar::updateRegion(LLViewerRegion *regionp)
+{
}
std::string LLVOAvatar::getFullname() const
@@ -8964,21 +7524,6 @@ std::string LLVOAvatar::getFullname() const
return name;
}
-LLTexLayerSet* LLVOAvatar::getLayerSet(ETextureIndex index) const
-{
- /* switch(index)
- case TEX_HEAD_BAKED:
- case TEX_HEAD_BODYPAINT:
- return mHeadLayerSet; */
- const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = LLVOAvatarDictionary::getInstance()->getTexture(index);
- if (text_dict->mIsUsedByBakedTexture)
- {
- const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex;
- return mBakedTextureData[baked_index].mTexLayerSet;
- }
- return NULL;
-}
-
LLHost LLVOAvatar::getObjectHost() const
{
LLViewerRegion* region = getRegion();
@@ -9011,13 +7556,18 @@ void LLVOAvatar::updateFreezeCounter(S32 counter)
BOOL LLVOAvatar::updateLOD()
{
+ if (isImpostor())
+ {
+ return TRUE;
+ }
+
BOOL res = updateJointLODs();
LLFace* facep = mDrawable->getFace(0);
if (facep->mVertexBuffer.isNull() ||
- LLVertexBuffer::sEnableVBOs &&
+ (LLVertexBuffer::sEnableVBOs &&
((facep->mVertexBuffer->getUsage() == GL_STATIC_DRAW ? TRUE : FALSE) !=
- (facep->getPool()->getVertexShaderLevel() > 0 ? TRUE : FALSE)))
+ (facep->getPool()->getVertexShaderLevel() > 0 ? TRUE : FALSE))))
{
mDirtyMesh = TRUE;
}
@@ -9036,7 +7586,8 @@ BOOL LLVOAvatar::updateLOD()
}
U32 LLVOAvatar::getPartitionType() const
-{ //avatars merely exist as drawables in the bridge partition
+{
+ // Avatars merely exist as drawables in the bridge partition
return LLViewerRegion::PARTITION_BRIDGE;
}
@@ -9044,10 +7595,9 @@ U32 LLVOAvatar::getPartitionType() const
void LLVOAvatar::updateImpostors()
{
for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
+ iter != LLCharacter::sInstances.end(); ++iter)
{
LLVOAvatar* avatar = (LLVOAvatar*) *iter;
-
if (!avatar->isDead() && avatar->needsImpostorUpdate() && avatar->isVisible() && avatar->isImpostor())
{
gPipeline.generateImpostor(avatar);
@@ -9102,42 +7652,60 @@ void LLVOAvatar::getImpostorValues(LLVector3* extents, LLVector3& angle, F32& di
void LLVOAvatar::idleUpdateRenderCost()
{
+ static const U32 ARC_BODY_PART_COST = 20;
+ static const U32 ARC_LIMIT = 2048;
+
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME))
{
return;
}
- U32 shame = 1;
-
+ U32 cost = 0;
std::set<LLUUID> textures;
- attachment_map_t::const_iterator iter;
- for (iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end();
- ++iter)
+ for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
+ {
+ const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index);
+ ETextureIndex tex_index = baked_dict->mTextureIndex;
+ if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(WT_SKIRT)))
+ {
+ if (isTextureVisible(tex_index))
+ {
+ cost +=ARC_BODY_PART_COST;
+ }
+ }
+ }
+
+ for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ ++iter)
{
LLViewerJointAttachment* attachment = iter->second;
- LLViewerObject* object = attachment->getObject();
- if (object && !object->isHUDAttachment())
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- LLDrawable* drawable = object->mDrawable;
- if (drawable)
+ const LLViewerObject* attached_object = (*attachment_iter);
+ if (attached_object && !attached_object->isHUDAttachment())
{
- shame += 10;
- LLVOVolume* volume = drawable->getVOVolume();
- if (volume)
+ const LLDrawable* drawable = attached_object->mDrawable;
+ if (drawable)
{
- shame += calc_shame(volume, textures);
+ const LLVOVolume* volume = drawable->getVOVolume();
+ if (volume)
+ {
+ cost += volume->getRenderCost(textures);
+ }
}
}
}
- }
+ }
- shame += textures.size() * 5;
+ cost += textures.size() * LLVOVolume::ARC_TEXTURE_COST;
- setDebugText(llformat("%d", shame));
- F32 green = 1.f-llclamp(((F32) shame-1024.f)/1024.f, 0.f, 1.f);
- F32 red = llmin((F32) shame/1024.f, 1.f);
+ setDebugText(llformat("%d", cost));
+ F32 green = 1.f-llclamp(((F32) cost-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f);
+ F32 red = llmin((F32) cost/(F32)ARC_LIMIT, 1.f);
mText->setColor(LLColor4(red,green,0,1));
}
@@ -9159,15 +7727,15 @@ const std::string LLVOAvatar::getBakedStatusForPrintout() const
{
std::string line;
- for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
+ for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
- iter++)
+ ++iter)
{
const ETextureIndex index = iter->first;
- const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second;
- if (text_dict->mIsBakedTexture)
+ const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
+ if (texture_dict->mIsBakedTexture)
{
- line += text_dict->mName;
+ line += texture_dict->mName;
if (isTextureDefined(index))
{
line += "_baked";
@@ -9179,108 +7747,11 @@ const std::string LLVOAvatar::getBakedStatusForPrintout() const
}
-U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures)
-{
- if (!volume)
- {
- return 0;
- }
-
- U32 shame = 0;
- U32 invisi = 0;
- U32 shiny = 0;
- U32 glow = 0;
- U32 alpha = 0;
- U32 flexi = 0;
- U32 animtex = 0;
- U32 particles = 0;
- U32 scale = 0;
- U32 bump = 0;
- U32 planar = 0;
-
- if (volume->isFlexible())
- {
- flexi = 1;
- }
- if (volume->isParticleSource())
- {
- particles = 1;
- }
-
- const LLVector3& sc = volume->getScale();
- scale += (U32) sc.mV[0] + (U32) sc.mV[1] + (U32) sc.mV[2];
-
- LLDrawable* drawablep = volume->mDrawable;
-
- if (volume->isSculpted())
- {
- LLSculptParams *sculpt_params = (LLSculptParams *) volume->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
- LLUUID sculpt_id = sculpt_params->getSculptTexture();
- textures.insert(sculpt_id);
- }
-
- for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
- {
- LLFace* face = drawablep->getFace(i);
- const LLTextureEntry* te = face->getTextureEntry();
- LLViewerImage* img = face->getTexture();
-
- textures.insert(img->getID());
-
- if (face->getPoolType() == LLDrawPool::POOL_ALPHA)
- {
- alpha++;
- }
- else if (img->getPrimaryFormat() == GL_ALPHA)
- {
- invisi = 1;
- }
-
- if (te)
- {
- if (te->getBumpmap())
- {
- bump = 1;
- }
- if (te->getShiny())
- {
- shiny = 1;
- }
- if (te->getGlow() > 0.f)
- {
- glow = 1;
- }
- if (face->mTextureMatrix != NULL)
- {
- animtex++;
- }
- if (te->getTexGen())
- {
- planar++;
- }
- }
- }
-
- shame += invisi + shiny + glow + alpha*4 + flexi*8 + animtex*4 + particles*16+bump*4+scale+planar;
-
- LLViewerObject::const_child_list_t& child_list = volume->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
- {
- LLViewerObject* child_objectp = *iter;
- LLDrawable* child_drawablep = child_objectp->mDrawable;
- if (child_drawablep)
- {
- LLVOVolume* child_volumep = child_drawablep->getVOVolume();
- if (child_volumep)
- {
- shame += calc_shame(child_volumep, textures);
- }
- }
- }
-
- return shame;
+//virtual
+S32 LLVOAvatar::getTexImageSize() const
+{
+ return TEX_IMAGE_SIZE_OTHER;
}
//-----------------------------------------------------------------------------
@@ -9291,3 +7762,16 @@ F32 calc_bouncy_animation(F32 x)
{
return -(cosf(x * F_PI * 2.5f - F_PI_BY_TWO))*(0.4f + x * -0.1f) + x * 1.3f;
}
+
+//virtual
+BOOL LLVOAvatar::isTextureDefined(LLVOAvatarDefines::ETextureIndex te, U32 index ) const
+{
+ if (isIndexLocalTexture(te))
+ {
+ return FALSE;
+ }
+
+ return (getImage(te, index)->getID() != IMG_DEFAULT_AVATAR &&
+ getImage(te, index)->getID() != IMG_DEFAULT);
+}
+
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index f8b2c068ff..a5815df20a 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -39,6 +39,7 @@
#include <string>
#include <vector>
+#include "imageids.h" // IMG_INVISIBLE
#include "llchat.h"
#include "lldrawpoolalpha.h"
#include "llviewerobject.h"
@@ -46,8 +47,10 @@
#include "llviewerjointmesh.h"
#include "llviewerjointattachment.h"
#include "llrendertarget.h"
-#include "llwearable.h"
#include "llvoavatardefines.h"
+#include "lltexglobalcolor.h"
+#include "lldriverparam.h"
+#include "material_codes.h" // LL_MCODE_END
extern const LLUUID ANIM_AGENT_BODY_NOISE;
extern const LLUUID ANIM_AGENT_BREATHE_ROT;
@@ -65,10 +68,8 @@ class LLVoiceVisualizer;
class LLHUDText;
class LLHUDEffectSpiral;
class LLTexGlobalColor;
-
class LLVOAvatarBoneInfo;
class LLVOAvatarSkeletonInfo;
-class LLVOAvatarXmlInfo;
//------------------------------------------------------------------------
// LLVOAvatar
@@ -77,686 +78,955 @@ class LLVOAvatar :
public LLViewerObject,
public LLCharacter
{
+public:
+ friend class LLVOAvatarSelf;
protected:
- virtual ~LLVOAvatar();
+ struct LLVOAvatarXmlInfo;
+ struct LLMaskedMorph;
+
+/********************************************************************************
+ ** **
+ ** INITIALIZATION
+ **/
public:
LLVOAvatar(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
- /*virtual*/ void markDead();
- void startDefaultMotions();
-
- static void updateImpostors();
-
- //--------------------------------------------------------------------
- // LLViewerObject interface
- //--------------------------------------------------------------------
-public:
- static void initClass(); // Initialize data that's only init'd once per class.
- static void cleanupClass(); // Cleanup data that's only init'd once per class.
- static BOOL parseSkeletonFile(const std::string& filename);
- virtual U32 processUpdateMessage(LLMessageSystem *mesgsys,
- void **user_data,
- U32 block_num,
- const EObjectUpdateType update_type,
- LLDataPacker *dp);
- /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);
- void idleUpdateVoiceVisualizer(bool voice_enabled);
- void idleUpdateMisc(bool detailed_update);
- void idleUpdateAppearanceAnimation();
- void idleUpdateLipSync(bool voice_enabled);
- void idleUpdateLoadingEffect();
- void idleUpdateWindEffect();
- void idleUpdateNameTag(const LLVector3& root_pos_last);
- void idleUpdateRenderCost();
- void idleUpdateTractorBeam();
- void idleUpdateBelowWater();
-
-public:
- virtual BOOL updateLOD();
- /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate.
-
- // Graphical stuff for objects - maybe broken out into render class later?
- U32 renderFootShadows();
- U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255));
- U32 renderRigid();
- U32 renderSkinned(EAvatarRenderPass pass);
- U32 renderTransparent(BOOL first_pass);
- void renderCollisionVolumes();
-
- /*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
- S32 face = -1, // which face to check, -1 = ALL_SIDES
- BOOL pick_transparent = FALSE,
- S32* face_hit = NULL, // which face was hit
- LLVector3* intersection = NULL, // return the intersection point
- LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
- LLVector3* normal = NULL, // return the surface normal at the intersection point
- LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point
- );
-
- /*virtual*/ void updateTextures(LLAgent &agent);
- // If setting a baked texture, need to request it from a non-local sim.
- /*virtual*/ S32 setTETexture(const U8 te, const LLUUID& uuid);
- /*virtual*/ void onShift(const LLVector3& shift_vector);
- virtual U32 getPartitionType() const;
-
- void updateVisibility();
- void updateAttachmentVisibility(U32 camera_mode);
- void clampAttachmentPositions();
- S32 getAttachmentCount(); // Warning: order(N) not order(1)
-
- // HUD functions
- BOOL hasHUDAttachment() const;
- LLBBox getHUDBBox() const;
- void rebuildHUD();
+ virtual void markDead();
+ static void initClass(); // Initialize data that's only init'd once per class.
+ static void cleanupClass(); // Cleanup data that's only init'd once per class.
+ virtual void initInstance(); // Called after construction to initialize the class.
+protected:
+ virtual ~LLVOAvatar();
+ BOOL loadSkeletonNode();
+ BOOL loadMeshNodes();
+ virtual BOOL loadLayersets();
- /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
- /*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
+/** Initialization
+ ** **
+ *******************************************************************************/
- /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent);
- BOOL updateJointLODs();
+/********************************************************************************
+ ** **
+ ** INHERITED
+ **/
- virtual void updateRegion(LLViewerRegion *regionp);
-
- virtual const LLVector3 getRenderPosition() const;
- virtual void updateDrawable(BOOL force_damped);
- void updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax);
- void getSpatialExtents(LLVector3& newMin, LLVector3& newMax);
- BOOL isImpostor() const;
- BOOL needsImpostorUpdate() const;
- const LLVector3& getImpostorOffset() const;
- const LLVector2& getImpostorDim() const;
- void getImpostorValues(LLVector3* extents, LLVector3& angle, F32& distance) const;
- void cacheImpostorValues();
- void setImpostorDim(const LLVector2& dim);
-
- //--------------------------------------------------------------------
- // LLCharacter interface
- //--------------------------------------------------------------------
-public:
- virtual const char *getAnimationPrefix() { return "avatar"; }
- virtual LLJoint *getRootJoint() { return &mRoot; }
- virtual LLVector3 getCharacterPosition();
- virtual LLQuaternion getCharacterRotation();
- virtual LLVector3 getCharacterVelocity();
- virtual LLVector3 getCharacterAngularVelocity();
- virtual F32 getTimeDilation();
- virtual void getGround(const LLVector3 &inPos, LLVector3 &outPos, LLVector3 &outNorm);
- virtual BOOL allocateCharacterJoints( U32 num );
- virtual LLJoint *getCharacterJoint( U32 num );
- virtual void requestStopMotion( LLMotion* motion );
- virtual F32 getPixelArea() const;
- virtual LLPolyMesh* getHeadMesh();
- virtual LLPolyMesh* getUpperBodyMesh();
- virtual LLVector3d getPosGlobalFromAgent(const LLVector3 &position);
- virtual LLVector3 getPosAgentFromGlobal(const LLVector3d &position);
- virtual void updateVisualParams();
- virtual BOOL startMotion(const LLUUID& id, F32 time_offset = 0.f);
- virtual BOOL stopMotion(const LLUUID& id, BOOL stop_immediate = FALSE);
- virtual void stopMotionFromSource(const LLUUID& source_id);
- virtual LLVector3 getVolumePos(S32 joint_index, LLVector3& volume_offset);
- virtual LLJoint* findCollisionVolume(U32 volume_id);
- virtual S32 getCollisionVolumeID(std::string &name);
- virtual void addDebugText(const std::string& text);
- virtual const LLUUID& getID();
- virtual LLJoint *getJoint( const std::string &name );
-
- //--------------------------------------------------------------------
- // Other public functions
- //--------------------------------------------------------------------
-public:
- static void onCustomizeStart();
- static void onCustomizeEnd();
-
-public:
- static void dumpTotalLocalTextureByteCount();
-protected:
- void getLocalTextureByteCount( S32* gl_byte_count );
+ //--------------------------------------------------------------------
+ // LLViewerObject interface and related
+ //--------------------------------------------------------------------
+public:
+ virtual void updateGL();
+ virtual LLVOAvatar* asAvatar();
+ virtual U32 processUpdateMessage(LLMessageSystem *mesgsys,
+ void **user_data,
+ U32 block_num,
+ const EObjectUpdateType update_type,
+ LLDataPacker *dp);
+ virtual BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);
+ virtual BOOL updateLOD();
+ BOOL updateJointLODs();
+ virtual BOOL isActive() const; // Whether this object needs to do an idleUpdate.
+ virtual void updateTextures();
+ virtual S32 setTETexture(const U8 te, const LLUUID& uuid); // If setting a baked texture, need to request it from a non-local sim.
+ virtual void onShift(const LLVector3& shift_vector);
+ virtual U32 getPartitionType() const;
+ virtual const LLVector3 getRenderPosition() const;
+ virtual void updateDrawable(BOOL force_damped);
+ virtual LLDrawable* createDrawable(LLPipeline *pipeline);
+ virtual BOOL updateGeometry(LLDrawable *drawable);
+ virtual void setPixelAreaAndAngle(LLAgent &agent);
+ virtual void updateRegion(LLViewerRegion *regionp);
+ virtual void updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax);
+ virtual void getSpatialExtents(LLVector3& newMin, LLVector3& newMax);
+ virtual BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
+ S32 face = -1, // which face to check, -1 = ALL_SIDES
+ BOOL pick_transparent = FALSE,
+ S32* face_hit = NULL, // which face was hit
+ LLVector3* intersection = NULL, // return the intersection point
+ LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
+ LLVector3* normal = NULL, // return the surface normal at the intersection point
+ LLVector3* bi_normal = NULL); // return the surface bi-normal at the intersection point
+ //--------------------------------------------------------------------
+ // LLCharacter interface and related
+ //--------------------------------------------------------------------
public:
- LLMotion* findMotion(const LLUUID& id);
+ virtual LLVector3 getCharacterPosition();
+ virtual LLQuaternion getCharacterRotation();
+ virtual LLVector3 getCharacterVelocity();
+ virtual LLVector3 getCharacterAngularVelocity();
+ virtual LLJoint* getCharacterJoint(U32 num);
+ virtual BOOL allocateCharacterJoints(U32 num);
+
+ virtual BOOL startMotion(const LLUUID& id, F32 time_offset = 0.f);
+ virtual BOOL stopMotion(const LLUUID& id, BOOL stop_immediate = FALSE);
+ virtual void stopMotionFromSource(const LLUUID& source_id);
+ virtual void requestStopMotion(LLMotion* motion);
+ LLMotion* findMotion(const LLUUID& id) const;
+ void startDefaultMotions();
+
+ virtual LLJoint* getJoint(const std::string &name);
+ virtual LLJoint* getRootJoint() { return &mRoot; }
+
+ virtual const char* getAnimationPrefix() { return "avatar"; }
+ virtual const LLUUID& getID();
+ virtual LLVector3 getVolumePos(S32 joint_index, LLVector3& volume_offset);
+ virtual LLJoint* findCollisionVolume(U32 volume_id);
+ virtual S32 getCollisionVolumeID(std::string &name);
+ virtual void addDebugText(const std::string& text);
+ virtual F32 getTimeDilation();
+ virtual void getGround(const LLVector3 &inPos, LLVector3 &outPos, LLVector3 &outNorm);
+ virtual F32 getPixelArea() const;
+ virtual LLPolyMesh* getHeadMesh();
+ virtual LLPolyMesh* getUpperBodyMesh();
+ virtual LLVector3d getPosGlobalFromAgent(const LLVector3 &position);
+ virtual LLVector3 getPosAgentFromGlobal(const LLVector3d &position);
+ virtual void updateVisualParams();
+
+
+/** Inherited
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** STATE
+ **/
- BOOL isVisible();
- BOOL isSelf() const { return mIsSelf; }
- BOOL isCulled() const { return mCulled; }
+public:
+ virtual bool isSelf() const { return false; } // True if this avatar is for this viewer's agent
+ bool isBuilt() const { return mIsBuilt; }
+private:
+ BOOL mSupportsAlphaLayers; // For backwards compatibility, TRUE for 1.23+ clients
+ //--------------------------------------------------------------------
+ // Updates
+ //--------------------------------------------------------------------
public:
- static void cullAvatarsByPixelArea();
- void setVisibilityRank(U32 rank);
- U32 getVisibilityRank(); // unused
-protected:
- S32 getUnbakedPixelAreaRank();
+ virtual BOOL updateCharacter(LLAgent &agent);
+ void idleUpdateVoiceVisualizer(bool voice_enabled);
+ void idleUpdateMisc(bool detailed_update);
+ virtual void idleUpdateAppearanceAnimation();
+ void idleUpdateLipSync(bool voice_enabled);
+ void idleUpdateLoadingEffect();
+ void idleUpdateWindEffect();
+ void idleUpdateNameTag(const LLVector3& root_pos_last);
+ void idleUpdateRenderCost();
+ void idleUpdateTractorBeam();
+ void idleUpdateBelowWater();
+ //--------------------------------------------------------------------
+ // Static preferences (controlled by user settings/menus)
+ //--------------------------------------------------------------------
public:
- void dumpLocalTextures();
- const LLUUID& grabLocalTexture(LLVOAvatarDefines::ETextureIndex index);
- BOOL canGrabLocalTexture(LLVOAvatarDefines::ETextureIndex index);
- BOOL isTextureDefined(U8 te) const;
- BOOL isTextureVisible(U8 te) const;
- void startAppearanceAnimation(BOOL set_by_user, BOOL play_sound);
+ static S32 sRenderName;
+ static BOOL sRenderGroupTitles;
+ static S32 sMaxVisible;
+ static F32 sRenderDistance; //distance at which avatars will render (affected by control "RenderAvatarMaxVisible")
+ static BOOL sShowAnimationDebug; // show animation debug info
+ static BOOL sUseImpostors; //use impostors for far away avatars
+ static BOOL sShowFootPlane; // show foot collision plane reported by server
+ static BOOL sShowCollisionVolumes; // show skeletal collision volumes
+ static BOOL sVisibleInFirstPerson;
+ static S32 sNumLODChangesThisFrame;
+ static S32 sNumVisibleChatBubbles;
+ static BOOL sDebugInvisible;
+ static BOOL sShowAttachmentPoints;
+ static F32 sLODFactor; // user-settable LOD factor
+ static BOOL sJointDebug; // output total number of joints being touched for each avatar
+ static BOOL sDebugAvatarRotation;
- void setCompositeUpdatesEnabled(BOOL b);
+ //--------------------------------------------------------------------
+ // Region state
+ //--------------------------------------------------------------------
+public:
+ LLHost getObjectHost() const;
- void addChat(const LLChat& chat);
- void clearChat();
- void startTyping() { mTyping = TRUE; mTypingTimer.reset(); }
- void stopTyping() { mTyping = FALSE; }
+ //--------------------------------------------------------------------
+ // Loading state
+ //--------------------------------------------------------------------
+public:
+ BOOL isFullyLoaded() const;
+protected:
+ virtual BOOL updateIsFullyLoaded();
+ BOOL processFullyLoadedChange(bool loading);
+ void updateRuthTimer(bool loading);
+ F32 calcMorphAmount();
+private:
+ BOOL mFullyLoaded;
+ BOOL mPreviousFullyLoaded;
+ BOOL mFullyLoadedInitialized;
+ S32 mFullyLoadedFrameCounter;
+ LLFrameTimer mFullyLoadedTimer;
+ LLFrameTimer mRuthTimer;
+
+/** State
+ ** **
+ *******************************************************************************/
- // Returns "FirstName LastName"
- std::string getFullname() const;
+/********************************************************************************
+ ** **
+ ** SKELETON
+ **/
- BOOL updateCharacter(LLAgent &agent);
- void updateHeadOffset();
+public:
+ void updateHeadOffset();
+ F32 getPelvisToFoot() const { return mPelvisToFoot; }
- F32 getPelvisToFoot() const { return mPelvisToFoot; }
+ LLVector3 mHeadOffset; // current head position
+ LLViewerJoint mRoot;
+protected:
+ static BOOL parseSkeletonFile(const std::string& filename);
+ void buildCharacter();
+ virtual BOOL loadAvatar();
+ BOOL setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 &current_volume_num, S32 &current_joint_num);
+ BOOL buildSkeleton(const LLVOAvatarSkeletonInfo *info);
+private:
+ BOOL mIsBuilt; // state of deferred character building
+ S32 mNumJoints;
+ LLViewerJoint* mSkeleton;
+
+ //--------------------------------------------------------------------
+ // Pelvis height adjustment members.
+ //--------------------------------------------------------------------
public:
- BOOL isAnyAnimationSignaled(const LLUUID *anim_array, const S32 num_anims);
- void processAnimationStateChanges();
-protected:
- BOOL processSingleAnimationStateChange(const LLUUID &anim_id, BOOL start);
- void resetAnimations();
+ LLVector3 mBodySize;
+ S32 mLastSkeletonSerialNum;
+private:
+ F32 mPelvisToFoot;
+ //--------------------------------------------------------------------
+ // Cached pointers to well known joints
+ //--------------------------------------------------------------------
public:
- void resolveHeightGlobal(const LLVector3d &inPos, LLVector3d &outPos, LLVector3 &outNorm);
- void resolveHeightAgent(const LLVector3 &inPos, LLVector3 &outPos, LLVector3 &outNorm);
- void resolveRayCollisionAgent(const LLVector3d start_pt, const LLVector3d end_pt, LLVector3d &out_pos, LLVector3 &out_norm);
-
- void slamPosition(); // Slam position to transmitted position (for teleport);
+ LLViewerJoint* mPelvisp;
+ LLViewerJoint* mTorsop;
+ LLViewerJoint* mChestp;
+ LLViewerJoint* mNeckp;
+ LLViewerJoint* mHeadp;
+ LLViewerJoint* mSkullp;
+ LLViewerJoint* mEyeLeftp;
+ LLViewerJoint* mEyeRightp;
+ LLViewerJoint* mHipLeftp;
+ LLViewerJoint* mHipRightp;
+ LLViewerJoint* mKneeLeftp;
+ LLViewerJoint* mKneeRightp;
+ LLViewerJoint* mAnkleLeftp;
+ LLViewerJoint* mAnkleRightp;
+ LLViewerJoint* mFootLeftp;
+ LLViewerJoint* mFootRightp;
+ LLViewerJoint* mWristLeftp;
+ LLViewerJoint* mWristRightp;
- // morph targets and such
- void processAvatarAppearance( LLMessageSystem* mesgsys );
- void onFirstTEMessageReceived();
- void updateSexDependentLayerSets( BOOL set_by_user );
- void dirtyMesh(); // Dirty the avatar mesh
- void hideSkirt();
+ //--------------------------------------------------------------------
+ // XML parse tree
+ //--------------------------------------------------------------------
+private:
+ static LLXmlTree sXMLTree; // avatar config file
+ static LLXmlTree sSkeletonXMLTree; // avatar skeleton file
- virtual void setParent(LLViewerObject* parent);
- virtual void addChild(LLViewerObject *childp);
- virtual void removeChild(LLViewerObject *childp);
+/** Skeleton
+ ** **
+ *******************************************************************************/
- LLViewerJointAttachment* getTargetAttachmentPoint(LLViewerObject* viewer_object);
- BOOL attachObject(LLViewerObject *viewer_object);
- BOOL detachObject(LLViewerObject *viewer_object);
- void lazyAttach();
-
- void sitOnObject(LLViewerObject *sit_object);
- void getOffObject();
-
- BOOL isWearingAttachment( const LLUUID& inv_item_id );
- LLViewerObject* getWornAttachment( const LLUUID& inv_item_id );
- const std::string getAttachedPointName(const LLUUID& inv_item_id);
-
- static LLVOAvatar* findAvatarFromAttachment( LLViewerObject* obj );
-
- void updateMeshTextures();
-
- //--------------------------------------------------------------------
- // texture compositing (used only by the LLTexLayer series of classes)
- //--------------------------------------------------------------------
-public:
- LLColor4 getGlobalColor( const std::string& color_name );
- BOOL isLocalTextureDataAvailable( LLTexLayerSet* layerset );
- BOOL isLocalTextureDataFinal( LLTexLayerSet* layerset );
- LLVOAvatarDefines::ETextureIndex getBakedTE( LLTexLayerSet* layerset );
- void updateComposites();
- void onGlobalColorChanged( LLTexGlobalColor* global_color, BOOL set_by_user );
- BOOL getLocalTextureRaw( LLVOAvatarDefines::ETextureIndex index, LLImageRaw* image_raw_pp );
- BOOL getLocalTextureGL( LLVOAvatarDefines::ETextureIndex index, LLImageGL** image_gl_pp );
- const LLUUID& getLocalTextureID( LLVOAvatarDefines::ETextureIndex index );
- LLGLuint getScratchTexName( LLGLenum format, U32* texture_bytes );
- BOOL bindScratchTexture( LLGLenum format );
- void invalidateComposite( LLTexLayerSet* layerset, BOOL set_by_user );
- void invalidateAll();
- void forceBakeAllTextures(bool slam_for_debug = false);
- static void processRebakeAvatarTextures(LLMessageSystem* msg, void**);
- void setNewBakedTexture( LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid );
- void setCachedBakedTexture( LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid );
- void releaseUnnecessaryTextures();
- void requestLayerSetUploads();
- bool hasPendingBakedUploads();
- static void onLocalTextureLoaded( BOOL succcess, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata );
- static void dumpArchetypeXML( void* );
- static void dumpScratchTextureByteCount();
- static void dumpBakedStatus();
- static void deleteCachedImages(bool clearAll=true);
- static void destroyGL();
- static void restoreGL();
- static void resetImpostors();
- static enum EWearableType getTEWearableType(LLVOAvatarDefines::ETextureIndex te );
- static LLUUID getDefaultTEImageID(LLVOAvatarDefines::ETextureIndex te );
- static void onChangeSelfInvisible(BOOL newvalue);
- void setInvisible(BOOL newvalue);
- static LLColor4 getDummyColor();
+/********************************************************************************
+ ** **
+ ** RENDERING
+ **/
+public:
+ U32 renderFootShadows();
+ U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0);
+ U32 renderRigid();
+ U32 renderSkinned(EAvatarRenderPass pass);
+ U32 renderTransparent(BOOL first_pass);
+ void renderCollisionVolumes();
+ static void deleteCachedImages(bool clearAll=true);
+ static void destroyGL();
+ static void restoreGL();
+ BOOL mIsDummy; // for special views
+ S32 mSpecialRenderMode; // special lighting
+private:
+ bool shouldAlphaMask();
+ BOOL mNeedsSkin; // avatar has been animated and verts have not been updated
+ S32 mUpdatePeriod;
+ S32 mNumInitFaces; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer.
//--------------------------------------------------------------------
- // Clothing colors (conventience functions to access visual parameters
+ // Morph masks
//--------------------------------------------------------------------
public:
- void setClothesColor( LLVOAvatarDefines::ETextureIndex te, const LLColor4& new_color, BOOL set_by_user );
- LLColor4 getClothesColor( LLVOAvatarDefines::ETextureIndex te );
- BOOL teToColorParams( LLVOAvatarDefines::ETextureIndex te, const char* param_name[3] );
-
- BOOL isWearingWearableType( EWearableType type );
- void wearableUpdated( EWearableType type );
+ BOOL morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES);
+ void addMaskedMorph(LLVOAvatarDefines::EBakedTextureIndex index, LLPolyMorphTarget* morph_target, BOOL invert, std::string layer);
+ void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES);
//--------------------------------------------------------------------
- // texture compositing
+ // Visibility
//--------------------------------------------------------------------
-public:
- void setLocTexTE( U8 te, LLViewerImage* image, BOOL set_by_user );
- void setupComposites();
-
+protected:
+ void updateVisibility();
+private:
+ U32 mVisibilityRank;
+ BOOL mVisible;
+
//--------------------------------------------------------------------
- // Handling partially loaded avatars (Ruth)
+ // Shadowing
//--------------------------------------------------------------------
public:
- BOOL isFullyLoaded();
- BOOL updateIsFullyLoaded();
+ void updateShadowFaces();
+ LLDrawable* mShadow;
private:
- BOOL mFullyLoaded;
- BOOL mPreviousFullyLoaded;
- BOOL mFullyLoadedInitialized;
- S32 mFullyLoadedFrameCounter;
- LLFrameTimer mFullyLoadedTimer;
+ LLFace* mShadow0Facep;
+ LLFace* mShadow1Facep;
+ LLPointer<LLViewerTexture> mShadowImagep;
//--------------------------------------------------------------------
- // Collision Volumes
+ // Impostors
//--------------------------------------------------------------------
public:
- S32 mNumCollisionVolumes;
- LLViewerJointCollisionVolume* mCollisionVolumes;
+ BOOL isImpostor() const;
+ BOOL needsImpostorUpdate() const;
+ const LLVector3& getImpostorOffset() const;
+ const LLVector2& getImpostorDim() const;
+ void getImpostorValues(LLVector3* extents, LLVector3& angle, F32& distance) const;
+ void cacheImpostorValues();
+ void setImpostorDim(const LLVector2& dim);
+ static void resetImpostors();
+ static void updateImpostors();
+ LLRenderTarget mImpostor;
+ BOOL mNeedsImpostorUpdate;
+private:
+ LLVector3 mImpostorOffset;
+ LLVector2 mImpostorDim;
+ BOOL mNeedsAnimUpdate;
+ LLVector3 mImpostorExtents[2];
+ LLVector3 mImpostorAngle;
+ F32 mImpostorDistance;
+ F32 mImpostorPixelArea;
+ LLVector3 mLastAnimExtents[2];
//--------------------------------------------------------------------
- // cached pointers to well known joints
+ // Wind rippling in clothes
//--------------------------------------------------------------------
public:
- LLViewerJoint* mPelvisp;
- LLViewerJoint* mTorsop;
- LLViewerJoint* mChestp;
- LLViewerJoint* mNeckp;
- LLViewerJoint* mHeadp;
- LLViewerJoint* mSkullp;
- LLViewerJoint* mEyeLeftp;
- LLViewerJoint* mEyeRightp;
- LLViewerJoint* mHipLeftp;
- LLViewerJoint* mHipRightp;
- LLViewerJoint* mKneeLeftp;
- LLViewerJoint* mKneeRightp;
- LLViewerJoint* mAnkleLeftp;
- LLViewerJoint* mAnkleRightp;
- LLViewerJoint* mFootLeftp;
- LLViewerJoint* mFootRightp;
- LLViewerJoint* mWristLeftp;
- LLViewerJoint* mWristRightp;
+ LLVector4 mWindVec;
+ F32 mRipplePhase;
+ BOOL mBelowWater;
+private:
+ F32 mWindFreq;
+ LLFrameTimer mRippleTimer;
+ F32 mRippleTimeLast;
+ LLVector3 mRippleAccel;
+ LLVector3 mLastVel;
//--------------------------------------------------------------------
- // impostor state
+ // Culling
//--------------------------------------------------------------------
public:
- LLRenderTarget mImpostor;
- BOOL mNeedsImpostorUpdate;
+ static void cullAvatarsByPixelArea();
+ BOOL isCulled() const { return mCulled; }
private:
- LLVector3 mImpostorOffset;
- LLVector2 mImpostorDim;
- BOOL mNeedsAnimUpdate;
- LLVector3 mImpostorExtents[2];
- LLVector3 mImpostorAngle;
- F32 mImpostorDistance;
- F32 mImpostorPixelArea;
- LLVector3 mLastAnimExtents[2];
+ BOOL mCulled;
//--------------------------------------------------------------------
- // Misc Render State
+ // Freeze counter
//--------------------------------------------------------------------
public:
- BOOL mIsDummy; // For special views
- S32 mSpecialRenderMode; // Special lighting
+ static void updateFreezeCounter(S32 counter = 0);
+private:
+ static S32 sFreezeCounter;
//--------------------------------------------------------------------
- // animation state data
+ // Constants
//--------------------------------------------------------------------
public:
- typedef std::map<LLUUID, S32>::iterator AnimIterator;
+ virtual LLViewerTexture::EBoostLevel getAvatarBoostLevel() const { return LLViewerTexture::BOOST_AVATAR; }
+ virtual LLViewerTexture::EBoostLevel getAvatarBakedBoostLevel() const { return LLViewerTexture::BOOST_AVATAR_BAKED; }
+ virtual S32 getTexImageSize() const;
+ virtual S32 getTexImageArea() const { return getTexImageSize()*getTexImageSize(); }
- std::map<LLUUID, S32> mSignaledAnimations; // requested state of Animation name/value
- std::map<LLUUID, S32> mPlayingAnimations; // current state of Animation name/value
+/** Rendering
+ ** **
+ *******************************************************************************/
- typedef std::multimap<LLUUID, LLUUID> AnimationSourceMap;
- typedef AnimationSourceMap::iterator AnimSourceIterator;
- AnimationSourceMap mAnimationSources; // object ids that triggered anim ids
+/********************************************************************************
+ ** **
+ ** TEXTURES
+ **/
//--------------------------------------------------------------------
- // Shadowing
+ // Loading status
//--------------------------------------------------------------------
public:
- void updateShadowFaces();
- LLDrawable* mShadow;
-private:
- LLFace* mShadow0Facep;
- LLFace* mShadow1Facep;
- LLPointer<LLViewerImage> mShadowImagep;
+ virtual BOOL isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const;
+ BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex index) const;
+protected:
+ BOOL isFullyBaked();
+ static BOOL areAllNearbyInstancesBaked(S32& grey_avatars);
//--------------------------------------------------------------------
- // Keeps track of foot step state for generating sounds
+ // Baked textures
//--------------------------------------------------------------------
public:
- void setFootPlane(const LLVector4 &plane) { mFootPlane = plane; }
- LLVector4 mFootPlane;
+ void releaseComponentTextures(); // ! BACKWARDS COMPATIBILITY !
+protected:
+ static void onBakedTextureMasksLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata);
+ static void onInitialBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata);
+ static void onBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata);
+ virtual void removeMissingBakedTextures();
+ void useBakedTexture(const LLUUID& id);
+
+ typedef std::deque<LLMaskedMorph *> morph_list_t;
+ struct BakedTextureData
+ {
+ LLUUID mLastTextureIndex;
+ LLTexLayerSet* mTexLayerSet; // Only exists for self
+ bool mIsLoaded;
+ bool mIsUsed;
+ LLVOAvatarDefines::ETextureIndex mTextureIndex;
+ U32 mMaskTexName;
+ // Stores pointers to the joint meshes that this baked texture deals with
+ std::vector< LLViewerJointMesh * > mMeshes; // std::vector<LLViewerJointMesh> mJoints[i]->mMeshParts
+ morph_list_t mMaskedMorphs;
+ };
+ typedef std::vector<BakedTextureData> bakedtexturedata_vec_t;
+ bakedtexturedata_vec_t mBakedTextureDatas;
+
+ //--------------------------------------------------------------------
+ // Local Textures
+ //--------------------------------------------------------------------
+protected:
+ virtual void setLocalTexture(LLVOAvatarDefines::ETextureIndex type, LLViewerTexture* tex, BOOL baked_version_exits, U32 index = 0);
+ virtual void addLocalTextureStats(LLVOAvatarDefines::ETextureIndex type, LLViewerFetchedTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked, U32 index = 0);
+ // MULTI-WEARABLE: make self-only?
+ virtual void setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index = 0);
+
+ //--------------------------------------------------------------------
+ // Texture accessors
+ //--------------------------------------------------------------------
private:
- BOOL mWasOnGroundLeft;
- BOOL mWasOnGroundRight;
+ virtual void setImage(const U8 te, LLViewerTexture *imagep, const U32 index);
+ virtual LLViewerTexture* getImage(const U8 te, const U32 index) const;
+
+ virtual const LLTextureEntry* getTexEntry(const U8 te_num) const;
+ virtual void setTexEntry(const U8 index, const LLTextureEntry &te);
+
//--------------------------------------------------------------------
- // Pelvis height adjustment members.
+ // Layers
+ //--------------------------------------------------------------------
+protected:
+ void deleteLayerSetCaches(bool clearAll = true);
+ void addBakedTextureStats(LLViewerFetchedTexture* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level);
+
+ //--------------------------------------------------------------------
+ // Composites
//--------------------------------------------------------------------
public:
- LLVector3 mBodySize;
- S32 mLastSkeletonSerialNum;
-private:
- F32 mPelvisToFoot;
+ virtual void invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result);
+ virtual void invalidateAll();
+ virtual void setCompositeUpdatesEnabled(BOOL b);
//--------------------------------------------------------------------
- // Display the name, then optionally fade it out
+ // Static texture/mesh/baked dictionary
//--------------------------------------------------------------------
public:
- LLFrameTimer mChatTimer;
- LLPointer<LLHUDText> mNameText;
+ static BOOL isIndexLocalTexture(LLVOAvatarDefines::ETextureIndex i);
+ static BOOL isIndexBakedTexture(LLVOAvatarDefines::ETextureIndex i);
private:
- LLFrameTimer mTimeVisible;
- std::deque<LLChat> mChats;
- BOOL mTyping;
- LLFrameTimer mTypingTimer;
+ static const LLVOAvatarDefines::LLVOAvatarDictionary *getDictionary() { return sAvatarDictionary; }
+ static LLVOAvatarDefines::LLVOAvatarDictionary* sAvatarDictionary;
+ static LLVOAvatarSkeletonInfo* sAvatarSkeletonInfo;
+ static LLVOAvatarXmlInfo* sAvatarXmlInfo;
//--------------------------------------------------------------------
- // wind rippling in clothes
+ // Messaging
//--------------------------------------------------------------------
public:
- LLVector4 mWindVec;
- F32 mRipplePhase;
- BOOL mBelowWater;
+ void onFirstTEMessageReceived();
+private:
+ BOOL mFirstTEMessageReceived;
+ BOOL mFirstAppearanceMessageReceived;
+
+/** Textures
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** MESHES
+ **/
+
+public:
+ void updateMeshTextures();
+ void updateSexDependentLayerSets(BOOL upload_bake);
+ void dirtyMesh(); // Dirty the avatar mesh
+ void updateMeshData();
+protected:
+ void releaseMeshData();
+ /*virtual*/ void restoreMeshData();
private:
- F32 mWindFreq;
- LLFrameTimer mRippleTimer;
- F32 mRippleTimeLast;
- LLVector3 mRippleAccel;
- LLVector3 mLastVel;
+ BOOL mDirtyMesh;
+ BOOL mMeshTexturesDirty;
+
+ typedef std::multimap<std::string, LLPolyMesh*> polymesh_map_t;
+ polymesh_map_t mMeshes;
+ std::vector<LLViewerJoint *> mMeshLOD;
//--------------------------------------------------------------------
- // appearance morphing
+ // Destroy invisible mesh
+ //--------------------------------------------------------------------
+protected:
+ BOOL mMeshValid;
+ LLFrameTimer mMeshInvisibleTime;
+
+/** Meshes
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** APPEARANCE
+ **/
+
+public:
+ void processAvatarAppearance(LLMessageSystem* mesgsys);
+ void hideSkirt();
+ void startAppearanceAnimation();
+
+ //--------------------------------------------------------------------
+ // Appearance morphing
//--------------------------------------------------------------------
public:
BOOL mAppearanceAnimating;
private:
LLFrameTimer mAppearanceMorphTimer;
- BOOL mAppearanceAnimSetByUser;
F32 mLastAppearanceBlendTime;
//--------------------------------------------------------------------
- // Attachments
+ // Clothing colors (convenience functions to access visual parameters)
//--------------------------------------------------------------------
public:
- // map of attachment points, by ID
- typedef std::map<S32, LLViewerJointAttachment*> attachment_map_t;
- attachment_map_t mAttachmentPoints;
- std::vector<LLPointer<LLViewerObject> > mPendingAttachment;
+ void setClothesColor(LLVOAvatarDefines::ETextureIndex te, const LLColor4& new_color, BOOL upload_bake);
+ LLColor4 getClothesColor(LLVOAvatarDefines::ETextureIndex te);
+ static BOOL teToColorParams(LLVOAvatarDefines::ETextureIndex te, U32 *param_name);
//--------------------------------------------------------------------
- // static preferences that are controlled by user settings/menus
+ // Global colors
//--------------------------------------------------------------------
public:
- static S32 sRenderName;
- static BOOL sRenderGroupTitles;
- static S32 sMaxVisible;
- static F32 sRenderDistance; //distance at which avatars will render (affected by control "RenderAvatarMaxVisible")
- static BOOL sShowAnimationDebug; // show animation debug info
- static BOOL sUseImpostors; //use impostors for far away avatars
- static BOOL sShowFootPlane; // show foot collision plane reported by server
- static BOOL sVisibleInFirstPerson;
- static S32 sNumLODChangesThisFrame;
- static S32 sNumVisibleChatBubbles;
- static BOOL sDebugInvisible;
- static BOOL sShowAttachmentPoints;
- static F32 sLODFactor; // user-settable LOD factor
- static BOOL sJointDebug; // output total number of joints being touched for each avatar
- static BOOL sDebugAvatarRotation;
+ LLColor4 getGlobalColor(const std::string& color_name ) const;
+ void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake);
+private:
+ LLTexGlobalColor* mTexSkinColor;
+ LLTexGlobalColor* mTexHairColor;
+ LLTexGlobalColor* mTexEyeColor;
+
+ //--------------------------------------------------------------------
+ // Visibility
+ //--------------------------------------------------------------------
+public:
+ BOOL isVisible() const;
+ void setVisibilityRank(U32 rank);
+ U32 getVisibilityRank() const { return mVisibilityRank; } // unused
+ static S32 sNumVisibleAvatars; // Number of instances of this class
+ static LLColor4 getDummyColor();
+/** Appearance
+ ** **
+ *******************************************************************************/
- static S32 sNumVisibleAvatars; // Number of instances of this class
+/********************************************************************************
+ ** **
+ ** WEARABLES
+ **/
+
+public:
+ virtual BOOL isWearingWearableType(EWearableType type ) const;
//--------------------------------------------------------------------
- // Miscellaneous public variables.
+ // Attachments
//--------------------------------------------------------------------
public:
- BOOL mInAir;
- LLFrameTimer mTimeInAir;
- LLVector3 mHeadOffset; // current head position
- LLViewerJoint mRoot; // avatar skeleton
- BOOL mIsSitting; // sitting state
+ void clampAttachmentPositions();
+ virtual const LLViewerJointAttachment* attachObject(LLViewerObject *viewer_object);
+ virtual BOOL detachObject(LLViewerObject *viewer_object);
+ static LLVOAvatar* findAvatarFromAttachment(LLViewerObject* obj);
+protected:
+ LLViewerJointAttachment* getTargetAttachmentPoint(LLViewerObject* viewer_object);
+ void lazyAttach();
//--------------------------------------------------------------------
- // Private member variables.
+ // Map of attachment points, by ID
//--------------------------------------------------------------------
+public:
+ S32 getAttachmentCount(); // Warning: order(N) not order(1) // currently used only by -self
+ typedef std::map<S32, LLViewerJointAttachment*> attachment_map_t;
+ attachment_map_t mAttachmentPoints;
+ std::vector<LLPointer<LLViewerObject> > mPendingAttachment;
+
+ //--------------------------------------------------------------------
+ // HUD functions
+ //--------------------------------------------------------------------
+public:
+ BOOL hasHUDAttachment() const;
+ LLBBox getHUDBBox() const;
+ void rebuildHUD();
+ void resetHUDAttachments();
+ BOOL canAttachMoreObjects() const;
+protected:
+ U32 getNumAttachments() const; // O(N), not O(1)
+
+/** Wearables
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** ACTIONS
+ **/
+
+ //--------------------------------------------------------------------
+ // Animations
+ //--------------------------------------------------------------------
+public:
+ BOOL isAnyAnimationSignaled(const LLUUID *anim_array, const S32 num_anims) const;
+ void processAnimationStateChanges();
+protected:
+ BOOL processSingleAnimationStateChange(const LLUUID &anim_id, BOOL start);
+ void resetAnimations();
private:
- BOOL mIsSelf; // True if this avatar is for this viewer's agent
+ LLTimer mAnimTimer;
+ F32 mTimeLast;
- LLViewerJoint *mScreenp; // special purpose joint for HUD attachments
- BOOL mIsBuilt; // state of deferred character building
- F32 mSpeedAccum; // measures speed (for diagnostics mostly).
+ //--------------------------------------------------------------------
+ // Animation state data
+ //--------------------------------------------------------------------
+public:
+ typedef std::map<LLUUID, S32>::iterator AnimIterator;
+ std::map<LLUUID, S32> mSignaledAnimations; // requested state of Animation name/value
+ std::map<LLUUID, S32> mPlayingAnimations; // current state of Animation name/value
-
- // LLFrameTimer mUpdateLODTimer; // controls frequency of LOD change calculations
- BOOL mDirtyMesh;
- BOOL mTurning; // controls hysteresis on avatar rotation
- F32 mSpeed; // misc. animation repeated state
+ typedef std::multimap<LLUUID, LLUUID> AnimationSourceMap;
+ typedef AnimationSourceMap::iterator AnimSourceIterator;
+ AnimationSourceMap mAnimationSources; // object ids that triggered anim ids
- // Keep track of the material being stepped on
- BOOL mStepOnLand;
- U8 mStepMaterial;
- LLVector3 mStepObjectVelocity;
+ //--------------------------------------------------------------------
+ // Chat
+ //--------------------------------------------------------------------
+public:
+ void addChat(const LLChat& chat);
+ void clearChat();
+ void startTyping() { mTyping = TRUE; mTypingTimer.reset(); }
+ void stopTyping() { mTyping = FALSE; }
+private:
+ BOOL mVisibleChat;
- // Destroy mesh data after being invisible for a while
- BOOL mMeshValid;
- BOOL mVisible;
- LLFrameTimer mMeshInvisibleTime;
+ //--------------------------------------------------------------------
+ // Lip synch morphs
+ //--------------------------------------------------------------------
+private:
+ bool mLipSyncActive; // we're morphing for lip sync
+ LLVisualParam* mOohMorph; // cached pointers morphs for lip sync
+ LLVisualParam* mAahMorph; // cached pointers morphs for lip sync
- // Lip synch morph stuff
- bool mLipSyncActive; // we're morphing for lip sync
- LLVisualParam* mOohMorph; // cached pointers morphs for lip sync
- LLVisualParam* mAahMorph; // cached pointers morphs for lip sync
+ //--------------------------------------------------------------------
+ // Flight
+ //--------------------------------------------------------------------
+public:
+ BOOL mInAir;
+ LLFrameTimer mTimeInAir;
- // Skeleton for skinned avatar
- S32 mNumJoints;
- LLViewerJoint* mSkeleton;
+/** Actions
+ ** **
+ *******************************************************************************/
- // Scratch textures used for compositing
- static LLMap< LLGLenum, LLGLuint*> sScratchTexNames;
- static LLMap< LLGLenum, F32*> sScratchTexLastBindTime;
- static S32 sScratchTexBytes;
+/********************************************************************************
+ ** **
+ ** PHYSICS
+ **/
- // Global table of sound ids per material, and the ground
- const static LLUUID sStepSounds[LL_MCODE_END];
- const static LLUUID sStepSoundOnLand;
+private:
+ F32 mSpeedAccum; // measures speed (for diagnostics mostly).
+ BOOL mTurning; // controls hysteresis on avatar rotation
+ F32 mSpeed; // misc. animation repeated state
+
+ //--------------------------------------------------------------------
+ // Collision volumes
+ //--------------------------------------------------------------------
+public:
+ S32 mNumCollisionVolumes;
+ LLViewerJointCollisionVolume* mCollisionVolumes;
+protected:
+ BOOL allocateCollisionVolumes(U32 num);
- // Xml parse tree of avatar config file
- static LLXmlTree sXMLTree;
- // Xml parse tree of avatar skeleton file
- static LLXmlTree sSkeletonXMLTree;
+ //--------------------------------------------------------------------
+ // Dimensions
+ //--------------------------------------------------------------------
+public:
+ void resolveHeightGlobal(const LLVector3d &inPos, LLVector3d &outPos, LLVector3 &outNorm);
+ void resolveHeightAgent(const LLVector3 &inPos, LLVector3 &outPos, LLVector3 &outNorm);
+ void resolveRayCollisionAgent(const LLVector3d start_pt, const LLVector3d end_pt, LLVector3d &out_pos, LLVector3 &out_norm);
+ void slamPosition(); // Slam position to transmitted position (for teleport);
+protected:
+ void computeBodySize();
- // Voice Visualizer is responsible for detecting the user's voice signal, and when the
- // user speaks, it puts a voice symbol over the avatar's head, and triggering gesticulations
- LLVoiceVisualizer* mVoiceVisualizer;
- int mCurrentGesticulationLevel;
-
- // Animation timer
- LLTimer mAnimTimer;
- F32 mTimeLast;
-
- LLPointer<LLHUDEffectSpiral> mBeam;
- LLFrameTimer mBeamTimer;
-
- F32 mAdjustedPixelArea;
-
- LLWString mNameString;
- std::string mTitle;
- BOOL mNameAway;
- BOOL mNameBusy;
- BOOL mNameMute;
- BOOL mNameAppearance;
- BOOL mVisibleChat;
- BOOL mRenderGroupTitles;
-
- std::string mDebugText;
- U64 mLastRegionHandle;
- LLFrameTimer mRegionCrossingTimer;
- S32 mRegionCrossingCount;
-
//--------------------------------------------------------------------
- // local textures for compositing.
+ // Material being stepped on
//--------------------------------------------------------------------
private:
- LLUUID mSavedTE[ LLVOAvatarDefines::TEX_NUM_INDICES ];
- BOOL mFirstTEMessageReceived;
- BOOL mFirstAppearanceMessageReceived;
- BOOL mHasBakedHair;
-
- BOOL mCulled;
- U32 mVisibilityRank;
- F32 mMinPixelArea; // debug
- F32 mMaxPixelArea; // debug
- BOOL mHasGrey; // debug
-
+ BOOL mStepOnLand;
+ U8 mStepMaterial;
+ LLVector3 mStepObjectVelocity;
+
+/** Physics
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** HIERARCHY
+ **/
+
+public:
+ virtual BOOL setParent(LLViewerObject* parent);
+ virtual void addChild(LLViewerObject *childp);
+ virtual void removeChild(LLViewerObject *childp);
+
//--------------------------------------------------------------------
- // Global Colors
+ // Sitting
//--------------------------------------------------------------------
+public:
+ void sitDown(BOOL bSitting);
+ BOOL isSitting(){return mIsSitting;}
+ void sitOnObject(LLViewerObject *sit_object);
+ void getOffObject();
private:
- LLTexGlobalColor* mTexSkinColor;
- LLTexGlobalColor* mTexHairColor;
- LLTexGlobalColor* mTexEyeColor;
+ // set this property only with LLVOAvatar::sitDown method
+ BOOL mIsSitting;
- BOOL mNeedsSkin; //if TRUE, avatar has been animated and verts have not been updated
- S32 mUpdatePeriod;
+/** Hierarchy
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** NAME
+ **/
+
+public:
+ std::string getFullname() const; // Returns "FirstName LastName"
+protected:
+ static void getAnimLabels(LLDynamicArray<std::string>* labels);
+ static void getAnimNames(LLDynamicArray<std::string>* names);
+private:
+ LLWString mNameString;
+ std::string mTitle;
+ BOOL mNameAway;
+ BOOL mNameBusy;
+ BOOL mNameMute;
+ BOOL mNameAppearance;
+ BOOL mRenderGroupTitles;
//--------------------------------------------------------------------
- // Internal functions
+ // Display the name (then optionally fade it out)
//--------------------------------------------------------------------
-protected:
- void buildCharacter();
- void releaseMeshData();
- void restoreMeshData();
- void updateMeshData();
- void computeBodySize();
- const LLUUID& getStepSound() const;
- BOOL needsRenderBeam();
+public:
+ LLFrameTimer mChatTimer;
+ LLPointer<LLHUDText> mNameText;
+private:
+ LLFrameTimer mTimeVisible;
+ std::deque<LLChat> mChats;
+ BOOL mTyping;
+ LLFrameTimer mTypingTimer;
+
+/** Name
+ ** **
+ *******************************************************************************/
- BOOL allocateCollisionVolumes( U32 num );
- void resetHUDAttachments();
- static void getAnimLabels( LLDynamicArray<std::string>* labels );
- static void getAnimNames( LLDynamicArray<std::string>* names );
+/********************************************************************************
+ ** **
+ ** SOUNDS
+ **/
//--------------------------------------------------------------------
- // Textures and Layers
+ // Voice visualizer
+ //--------------------------------------------------------------------
+public:
+ // Responsible for detecting the user's voice signal (and when the
+ // user speaks, it puts a voice symbol over the avatar's head) and gesticulations
+ LLVoiceVisualizer* mVoiceVisualizer;
+ int mCurrentGesticulationLevel;
+
+ //--------------------------------------------------------------------
+ // Step sound
//--------------------------------------------------------------------
protected:
- BOOL loadSkeletonNode();
- BOOL loadMeshNodes();
- BOOL isFullyBaked();
- void deleteLayerSetCaches(bool clearAll = true);
- static BOOL areAllNearbyInstancesBaked(S32& grey_avatars);
- static void onBakedTextureMasksLoaded(BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata);
- void setLocalTexture(LLVOAvatarDefines::ETextureIndex i, LLViewerImage* tex, BOOL baked_version_exits);
- void requestLayerSetUpdate(LLVOAvatarDefines::ETextureIndex i);
- void addLocalTextureStats(LLVOAvatarDefines::ETextureIndex i, LLViewerImage* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked);
- void addBakedTextureStats( LLViewerImage* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level);
- static void onInitialBakedTextureLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata );
- static void onBakedTextureLoaded(BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata);
- void useBakedTexture(const LLUUID& id);
- void dumpAvatarTEs(const std::string& context);
- void removeMissingBakedTextures();
- LLTexLayerSet* getLayerSet(LLVOAvatarDefines::ETextureIndex index) const;
- LLHost getObjectHost() const;
- S32 getLocalDiscardLevel(LLVOAvatarDefines::ETextureIndex index);
+ const LLUUID& getStepSound() const;
+private:
+ // Global table of sound ids per material, and the ground
+ const static LLUUID sStepSounds[LL_MCODE_END];
+ const static LLUUID sStepSoundOnLand;
+
+ //--------------------------------------------------------------------
+ // Foot step state (for generating sounds)
+ //--------------------------------------------------------------------
public:
- static void updateFreezeCounter(S32 counter = 0 );
+ void setFootPlane(const LLVector4 &plane) { mFootPlane = plane; }
+ LLVector4 mFootPlane;
private:
- static S32 sFreezeCounter;
+ BOOL mWasOnGroundLeft;
+ BOOL mWasOnGroundRight;
+
+/** Sounds
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** DIAGNOSTICS
+ **/
- //-----------------------------------------------------------------------------------------------
- // Avatar skeleton setup.
- //-----------------------------------------------------------------------------------------------
-private:
- BOOL loadAvatar();
- BOOL setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 &current_volume_num, S32 &current_joint_num);
- BOOL buildSkeleton(const LLVOAvatarSkeletonInfo *info);
-
- //-----------------------------------------------------------------------------------------------
- // Per-avatar information about texture data.
- // To-do: Move this to private implementation class
- //-----------------------------------------------------------------------------------------------
+public:
+ static void dumpArchetypeXML(void*);
+ static void dumpBakedStatus();
+ const std::string getBakedStatusForPrintout() const;
+ void dumpAvatarTEs(const std::string& context) const;
+
+ static F32 sUnbakedTime; // Total seconds with >=1 unbaked avatars
+ static F32 sUnbakedUpdateTime; // Last time stats were updated (to prevent multiple updates per frame)
+ static F32 sGreyTime; // Total seconds with >=1 grey avatars
+ static F32 sGreyUpdateTime; // Last time stats were updated (to prevent multiple updates per frame)
+protected:
+ S32 getUnbakedPixelAreaRank();
+ BOOL mHasGrey;
private:
- struct BakedTextureData
+ F32 mMinPixelArea;
+ F32 mMaxPixelArea;
+ F32 mAdjustedPixelArea;
+ std::string mDebugText;
+
+/** Diagnostics
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** SUPPORT CLASSES
+ **/
+
+protected: // Shared with LLVOAvatarSelf
+
+ struct LLVOAvatarXmlInfo
{
- LLUUID mLastTextureIndex;
- LLTexLayerSet* mTexLayerSet;
- bool mIsLoaded;
- bool mIsUsed;
- LLVOAvatarDefines::ETextureIndex mTextureIndex;
- U32 mMaskTexName;
- // Stores pointers to the joint meshes that this baked texture deals with
- std::vector< LLViewerJointMesh * > mMeshes; // std::vector<LLViewerJointMesh> mJoints[i]->mMeshParts
+ LLVOAvatarXmlInfo();
+ ~LLVOAvatarXmlInfo();
+
+ BOOL parseXmlSkeletonNode(LLXmlTreeNode* root);
+ BOOL parseXmlMeshNodes(LLXmlTreeNode* root);
+ BOOL parseXmlColorNodes(LLXmlTreeNode* root);
+ BOOL parseXmlLayerNodes(LLXmlTreeNode* root);
+ BOOL parseXmlDriverNodes(LLXmlTreeNode* root);
+ BOOL parseXmlMorphNodes(LLXmlTreeNode* root);
+
+ struct LLVOAvatarMeshInfo
+ {
+ typedef std::pair<LLPolyMorphTargetInfo*,BOOL> morph_info_pair_t;
+ typedef std::vector<morph_info_pair_t> morph_info_list_t;
+
+ LLVOAvatarMeshInfo() : mLOD(0), mMinPixelArea(.1f) {}
+ ~LLVOAvatarMeshInfo()
+ {
+ morph_info_list_t::iterator iter;
+ for (iter = mPolyMorphTargetInfoList.begin(); iter != mPolyMorphTargetInfoList.end(); iter++)
+ {
+ delete iter->first;
+ }
+ mPolyMorphTargetInfoList.clear();
+ }
+
+ std::string mType;
+ S32 mLOD;
+ std::string mMeshFileName;
+ std::string mReferenceMeshName;
+ F32 mMinPixelArea;
+ morph_info_list_t mPolyMorphTargetInfoList;
+ };
+ typedef std::vector<LLVOAvatarMeshInfo*> mesh_info_list_t;
+ mesh_info_list_t mMeshInfoList;
+
+ typedef std::vector<LLPolySkeletalDistortionInfo*> skeletal_distortion_info_list_t;
+ skeletal_distortion_info_list_t mSkeletalDistortionInfoList;
+
+ struct LLVOAvatarAttachmentInfo
+ {
+ LLVOAvatarAttachmentInfo()
+ : mGroup(-1), mAttachmentID(-1), mPieMenuSlice(-1), mVisibleFirstPerson(FALSE),
+ mIsHUDAttachment(FALSE), mHasPosition(FALSE), mHasRotation(FALSE) {}
+ std::string mName;
+ std::string mJointName;
+ LLVector3 mPosition;
+ LLVector3 mRotationEuler;
+ S32 mGroup;
+ S32 mAttachmentID;
+ S32 mPieMenuSlice;
+ BOOL mVisibleFirstPerson;
+ BOOL mIsHUDAttachment;
+ BOOL mHasPosition;
+ BOOL mHasRotation;
+ };
+ typedef std::vector<LLVOAvatarAttachmentInfo*> attachment_info_list_t;
+ attachment_info_list_t mAttachmentInfoList;
+
+ LLTexGlobalColorInfo *mTexSkinColorInfo;
+ LLTexGlobalColorInfo *mTexHairColorInfo;
+ LLTexGlobalColorInfo *mTexEyeColorInfo;
+
+ typedef std::vector<LLTexLayerSetInfo*> layer_info_list_t;
+ layer_info_list_t mLayerInfoList;
+
+ typedef std::vector<LLDriverParamInfo*> driver_info_list_t;
+ driver_info_list_t mDriverInfoList;
+
+ struct LLVOAvatarMorphInfo
+ {
+ LLVOAvatarMorphInfo()
+ : mInvert(FALSE) {}
+ std::string mName;
+ std::string mRegion;
+ std::string mLayer;
+ BOOL mInvert;
+ };
+
+ typedef std::vector<LLVOAvatarMorphInfo*> morph_info_list_t;
+ morph_info_list_t mMorphMaskInfoList;
};
- typedef std::vector<BakedTextureData> bakedtexturedata_vec_t;
- bakedtexturedata_vec_t mBakedTextureData;
- struct LocalTextureData
+ struct LLMaskedMorph
{
- LocalTextureData() : mIsBakedReady(FALSE), mDiscard(MAX_DISCARD_LEVEL+1), mImage(NULL)
- {}
- LLPointer<LLViewerImage> mImage;
- BOOL mIsBakedReady;
- S32 mDiscard;
+ LLMaskedMorph(LLPolyMorphTarget *morph_target, BOOL invert, std::string layer) :
+ mMorphTarget(morph_target),
+ mInvert(invert),
+ mLayer(layer)
+ {
+ morph_target->addPendingMorphMask();
+ }
+
+ LLPolyMorphTarget *mMorphTarget;
+ BOOL mInvert;
+ std::string mLayer;
};
- typedef std::map<LLVOAvatarDefines::ETextureIndex, LocalTextureData> localtexture_map_t;
- localtexture_map_t mLocalTextureData;
- typedef std::multimap<std::string, LLPolyMesh*> polymesh_map_t;
- polymesh_map_t mMeshes;
- std::vector<LLViewerJoint *> mMeshLOD;
- S32 mNumInitFaces ; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer.
+/** Support classes
+ ** **
+ *******************************************************************************/
- //-----------------------------------------------------------------------------------------------
- // Static texture/mesh/baked dictionary for avatars
- //-----------------------------------------------------------------------------------------------
-public:
- static BOOL isIndexLocalTexture(LLVOAvatarDefines::ETextureIndex i);
- static BOOL isIndexBakedTexture(LLVOAvatarDefines::ETextureIndex i);
-private:
- static const LLVOAvatarDefines::LLVOAvatarDictionary *getDictionary() { return sAvatarDictionary; }
- static LLVOAvatarDefines::LLVOAvatarDictionary *sAvatarDictionary;
- static LLVOAvatarSkeletonInfo* sAvatarSkeletonInfo;
- static LLVOAvatarXmlInfo* sAvatarXmlInfo;
+}; // LLVOAvatar
- //-----------------------------------------------------------------------------------------------
- // Diagnostics
- //-----------------------------------------------------------------------------------------------
-public:
- static F32 sUnbakedTime; // Total seconds with >=1 unbaked avatars
- static F32 sUnbakedUpdateTime; // Last time stats were updated (to prevent multiple updates per frame)
- static F32 sGreyTime; // Total seconds with >=1 grey avatars
- static F32 sGreyUpdateTime; // Last time stats were updated (to prevent multiple updates per frame)
-
- const std::string getBakedStatusForPrintout() const;
-};
-
-//-----------------------------------------------------------------------------------------------
+//------------------------------------------------------------------------
// Inlines
-//-----------------------------------------------------------------------------------------------
-inline BOOL LLVOAvatar::isTextureDefined(U8 te) const
-{
- return (getTEImage(te)->getID() != IMG_DEFAULT_AVATAR && getTEImage(te)->getID() != IMG_DEFAULT);
-}
-
-inline BOOL LLVOAvatar::isTextureVisible(U8 te) const
+//------------------------------------------------------------------------
+inline BOOL LLVOAvatar::isTextureVisible(LLVOAvatarDefines::ETextureIndex te) const
{
return ((isTextureDefined(te) || isSelf())
&& (getTEImage(te)->getID() != IMG_INVISIBLE
diff --git a/indra/newview/llvoavatardefines.cpp b/indra/newview/llvoavatardefines.cpp
index 19ad90a8e2..49c4a1a6c8 100644
--- a/indra/newview/llvoavatardefines.cpp
+++ b/indra/newview/llvoavatardefines.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
- * Copyright (c) 2001-2007, Linden Research, Inc.
+ * Copyright (c) 2001-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -12,12 +12,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
@@ -31,6 +32,7 @@
#include "llviewerprecompiledheaders.h"
#include "llvoavatardefines.h"
+#include "llviewercontrol.h" // gSavedSettings
const S32 LLVOAvatarDefines::SCRATCH_TEX_WIDTH = 512;
const S32 LLVOAvatarDefines::SCRATCH_TEX_HEIGHT = 512;
@@ -41,56 +43,90 @@ using namespace LLVOAvatarDefines;
/*********************************************************************************
* Edit this function to add/remove/change textures and mesh definitions for avatars.
*/
-void LLVOAvatarDictionary::initData()
+
+LLVOAvatarDictionary::Textures::Textures()
{
- // Textures
- mTextureMap[TEX_HEAD_BODYPAINT] = new TextureDictionaryEntry("head bodypaint", TRUE, BAKED_NUM_INDICES, "", WT_SKIN);
- mTextureMap[TEX_UPPER_SHIRT] = new TextureDictionaryEntry("shirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultShirtUUID", WT_SHIRT);
- mTextureMap[TEX_LOWER_PANTS] = new TextureDictionaryEntry("pants", TRUE, BAKED_NUM_INDICES, "UIImgDefaultPantsUUID", WT_PANTS);
- mTextureMap[TEX_EYES_IRIS] = new TextureDictionaryEntry("iris", TRUE, BAKED_NUM_INDICES, "UIImgDefaultEyesUUID", WT_EYES);
- mTextureMap[TEX_HAIR] = new TextureDictionaryEntry("hair", TRUE, BAKED_NUM_INDICES, "UIImgDefaultHairUUID", WT_HAIR);
- mTextureMap[TEX_UPPER_BODYPAINT] = new TextureDictionaryEntry("upper bodypaint", TRUE, BAKED_NUM_INDICES, "", WT_SKIN);
- mTextureMap[TEX_LOWER_BODYPAINT] = new TextureDictionaryEntry("lower bodypaint", TRUE, BAKED_NUM_INDICES, "", WT_SKIN);
- mTextureMap[TEX_LOWER_SHOES] = new TextureDictionaryEntry("shoes", TRUE, BAKED_NUM_INDICES, "UIImgDefaultShoesUUID", WT_SHOES);
- mTextureMap[TEX_LOWER_SOCKS] = new TextureDictionaryEntry("socks", TRUE, BAKED_NUM_INDICES, "UIImgDefaultSocksUUID", WT_SOCKS);
- mTextureMap[TEX_UPPER_JACKET] = new TextureDictionaryEntry("upper jacket", TRUE, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", WT_JACKET);
- mTextureMap[TEX_LOWER_JACKET] = new TextureDictionaryEntry("lower jacket", TRUE, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", WT_JACKET);
- mTextureMap[TEX_UPPER_GLOVES] = new TextureDictionaryEntry("gloves", TRUE, BAKED_NUM_INDICES, "UIImgDefaultGlovesUUID", WT_GLOVES);
- mTextureMap[TEX_UPPER_UNDERSHIRT] = new TextureDictionaryEntry("undershirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", WT_UNDERSHIRT);
- mTextureMap[TEX_LOWER_UNDERPANTS] = new TextureDictionaryEntry("underpants", TRUE, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", WT_UNDERPANTS);
- mTextureMap[TEX_SKIRT] = new TextureDictionaryEntry("skirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultSkirtUUID", WT_SKIRT);
- mTextureMap[TEX_HEAD_BAKED] = new TextureDictionaryEntry("head-baked", FALSE, BAKED_HEAD);
- mTextureMap[TEX_UPPER_BAKED] = new TextureDictionaryEntry("upper-baked", FALSE, BAKED_UPPER);
- mTextureMap[TEX_LOWER_BAKED] = new TextureDictionaryEntry("lower-baked", FALSE, BAKED_LOWER);
- mTextureMap[TEX_EYES_BAKED] = new TextureDictionaryEntry("eyes-baked", FALSE, BAKED_EYES);
- mTextureMap[TEX_HAIR_BAKED] = new TextureDictionaryEntry("hair-baked", FALSE, BAKED_HAIR);
- mTextureMap[TEX_SKIRT_BAKED] = new TextureDictionaryEntry("skirt-baked", FALSE, BAKED_SKIRT);
+ addEntry(TEX_HEAD_BODYPAINT, new TextureEntry("head_bodypaint", TRUE, BAKED_NUM_INDICES, "", WT_SKIN));
+ addEntry(TEX_UPPER_SHIRT, new TextureEntry("upper_shirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultShirtUUID", WT_SHIRT));
+ addEntry(TEX_LOWER_PANTS, new TextureEntry("lower_pants", TRUE, BAKED_NUM_INDICES, "UIImgDefaultPantsUUID", WT_PANTS));
+ addEntry(TEX_EYES_IRIS, new TextureEntry("eyes_iris", TRUE, BAKED_NUM_INDICES, "UIImgDefaultEyesUUID", WT_EYES));
+ addEntry(TEX_HAIR, new TextureEntry("hair_grain", TRUE, BAKED_NUM_INDICES, "UIImgDefaultHairUUID", WT_HAIR));
+ addEntry(TEX_UPPER_BODYPAINT, new TextureEntry("upper_bodypaint", TRUE, BAKED_NUM_INDICES, "", WT_SKIN));
+ addEntry(TEX_LOWER_BODYPAINT, new TextureEntry("lower_bodypaint", TRUE, BAKED_NUM_INDICES, "", WT_SKIN));
+ addEntry(TEX_LOWER_SHOES, new TextureEntry("lower_shoes", TRUE, BAKED_NUM_INDICES, "UIImgDefaultShoesUUID", WT_SHOES));
+ addEntry(TEX_LOWER_SOCKS, new TextureEntry("lower_socks", TRUE, BAKED_NUM_INDICES, "UIImgDefaultSocksUUID", WT_SOCKS));
+ addEntry(TEX_UPPER_JACKET, new TextureEntry("upper_jacket", TRUE, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", WT_JACKET));
+ addEntry(TEX_LOWER_JACKET, new TextureEntry("lower_jacket", TRUE, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", WT_JACKET));
+ addEntry(TEX_UPPER_GLOVES, new TextureEntry("upper_gloves", TRUE, BAKED_NUM_INDICES, "UIImgDefaultGlovesUUID", WT_GLOVES));
+ addEntry(TEX_UPPER_UNDERSHIRT, new TextureEntry("upper_undershirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", WT_UNDERSHIRT));
+ addEntry(TEX_LOWER_UNDERPANTS, new TextureEntry("lower_underpants", TRUE, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", WT_UNDERPANTS));
+ addEntry(TEX_SKIRT, new TextureEntry("skirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultSkirtUUID", WT_SKIRT));
+
+ addEntry(TEX_LOWER_ALPHA, new TextureEntry("lower_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", WT_ALPHA));
+ addEntry(TEX_UPPER_ALPHA, new TextureEntry("upper_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", WT_ALPHA));
+ addEntry(TEX_HEAD_ALPHA, new TextureEntry("head_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", WT_ALPHA));
+ addEntry(TEX_EYES_ALPHA, new TextureEntry("eyes_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", WT_ALPHA));
+ addEntry(TEX_HAIR_ALPHA, new TextureEntry("hair_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", WT_ALPHA));
+
+ addEntry(TEX_HEAD_TATTOO, new TextureEntry("head_tattoo", TRUE, BAKED_NUM_INDICES, "", WT_TATTOO));
+ addEntry(TEX_UPPER_TATTOO, new TextureEntry("upper_tattoo", TRUE, BAKED_NUM_INDICES, "", WT_TATTOO));
+ addEntry(TEX_LOWER_TATTOO, new TextureEntry("lower_tattoo", TRUE, BAKED_NUM_INDICES, "", WT_TATTOO));
+ addEntry(TEX_HEAD_BAKED, new TextureEntry("head-baked", FALSE, BAKED_HEAD));
+ addEntry(TEX_UPPER_BAKED, new TextureEntry("upper-baked", FALSE, BAKED_UPPER));
+ addEntry(TEX_LOWER_BAKED, new TextureEntry("lower-baked", FALSE, BAKED_LOWER));
+ addEntry(TEX_EYES_BAKED, new TextureEntry("eyes-baked", FALSE, BAKED_EYES));
+ addEntry(TEX_HAIR_BAKED, new TextureEntry("hair-baked", FALSE, BAKED_HAIR));
+ addEntry(TEX_SKIRT_BAKED, new TextureEntry("skirt-baked", FALSE, BAKED_SKIRT));
+}
+
+LLVOAvatarDictionary::BakedTextures::BakedTextures()
+{
// Baked textures
- mBakedTextureMap[BAKED_HEAD] = new BakedDictionaryEntry(TEX_HEAD_BAKED, "head", 1, TEX_HEAD_BODYPAINT);
- mBakedTextureMap[BAKED_UPPER] = new BakedDictionaryEntry(TEX_UPPER_BAKED, "upper_body", 5, TEX_UPPER_SHIRT,TEX_UPPER_BODYPAINT,TEX_UPPER_JACKET,TEX_UPPER_GLOVES,TEX_UPPER_UNDERSHIRT);
- mBakedTextureMap[BAKED_LOWER] = new BakedDictionaryEntry(TEX_LOWER_BAKED, "lower_body", 6, TEX_LOWER_PANTS,TEX_LOWER_BODYPAINT,TEX_LOWER_SHOES,TEX_LOWER_SOCKS,TEX_LOWER_JACKET,TEX_LOWER_UNDERPANTS);
- mBakedTextureMap[BAKED_EYES] = new BakedDictionaryEntry(TEX_EYES_BAKED, "eyes", 1, TEX_EYES_IRIS);
- mBakedTextureMap[BAKED_SKIRT] = new BakedDictionaryEntry(TEX_SKIRT_BAKED, "skirt", 1, TEX_SKIRT);
- mBakedTextureMap[BAKED_HAIR] = new BakedDictionaryEntry(TEX_HAIR_BAKED, "hair", 1, TEX_HAIR);
-
+ addEntry(BAKED_HEAD, new BakedEntry(TEX_HEAD_BAKED,
+ "head", "a4b9dc38-e13b-4df9-b284-751efb0566ff",
+ 3, TEX_HEAD_BODYPAINT, TEX_HEAD_TATTOO, TEX_HEAD_ALPHA,
+ 5, WT_SHAPE, WT_SKIN, WT_HAIR, WT_TATTOO, WT_ALPHA));
+
+ addEntry(BAKED_UPPER, new BakedEntry(TEX_UPPER_BAKED,
+ "upper_body", "5943ff64-d26c-4a90-a8c0-d61f56bd98d4",
+ 7, TEX_UPPER_SHIRT,TEX_UPPER_BODYPAINT, TEX_UPPER_JACKET,
+ TEX_UPPER_GLOVES, TEX_UPPER_UNDERSHIRT, TEX_UPPER_TATTOO, TEX_UPPER_ALPHA,
+ 8, WT_SHAPE, WT_SKIN, WT_SHIRT, WT_JACKET, WT_GLOVES, WT_UNDERSHIRT, WT_TATTOO, WT_ALPHA));
+
+ addEntry(BAKED_LOWER, new BakedEntry(TEX_LOWER_BAKED,
+ "lower_body", "2944ee70-90a7-425d-a5fb-d749c782ed7d",
+ 8, TEX_LOWER_PANTS,TEX_LOWER_BODYPAINT,TEX_LOWER_SHOES, TEX_LOWER_SOCKS,
+ TEX_LOWER_JACKET, TEX_LOWER_UNDERPANTS, TEX_LOWER_TATTOO, TEX_LOWER_ALPHA,
+ 9, WT_SHAPE, WT_SKIN, WT_PANTS, WT_SHOES, WT_SOCKS, WT_JACKET, WT_UNDERPANTS, WT_TATTOO, WT_ALPHA));
+
+ addEntry(BAKED_EYES, new BakedEntry(TEX_EYES_BAKED,
+ "eyes", "27b1bc0f-979f-4b13-95fe-b981c2ba9788",
+ 2, TEX_EYES_IRIS, TEX_EYES_ALPHA,
+ 2, WT_EYES, WT_ALPHA));
+
+ addEntry(BAKED_SKIRT, new BakedEntry(TEX_SKIRT_BAKED,
+ "skirt", "03e7e8cb-1368-483b-b6f3-74850838ba63",
+ 1, TEX_SKIRT,
+ 1, WT_SKIRT));
+
+ addEntry(BAKED_HAIR, new BakedEntry(TEX_HAIR_BAKED,
+ "hair", "a60e85a9-74e8-48d8-8a2d-8129f28d9b61",
+ 2, TEX_HAIR, TEX_HAIR_ALPHA,
+ 2, WT_HAIR, WT_ALPHA));
+}
+
+LLVOAvatarDictionary::Meshes::Meshes()
+{
// Meshes
- mMeshMap[MESH_ID_HAIR] = new MeshDictionaryEntry(BAKED_HAIR, "hairMesh", 6, LLViewerJoint::PN_4);
- mMeshMap[MESH_ID_HEAD] = new MeshDictionaryEntry(BAKED_HEAD, "headMesh", 5, LLViewerJoint::PN_5);
- mMeshMap[MESH_ID_EYELASH] = new MeshDictionaryEntry(BAKED_HEAD, "eyelashMesh", 1, LLViewerJoint::PN_0); // no baked mesh associated currently
- mMeshMap[MESH_ID_UPPER_BODY] = new MeshDictionaryEntry(BAKED_UPPER, "upperBodyMesh", 5, LLViewerJoint::PN_1);
- mMeshMap[MESH_ID_LOWER_BODY] = new MeshDictionaryEntry(BAKED_LOWER, "lowerBodyMesh", 5, LLViewerJoint::PN_2);
- mMeshMap[MESH_ID_EYEBALL_LEFT] = new MeshDictionaryEntry(BAKED_EYES, "eyeBallLeftMesh", 2, LLViewerJoint::PN_3);
- mMeshMap[MESH_ID_EYEBALL_RIGHT] = new MeshDictionaryEntry(BAKED_EYES, "eyeBallRightMesh", 2, LLViewerJoint::PN_3);
- mMeshMap[MESH_ID_SKIRT] = new MeshDictionaryEntry(BAKED_SKIRT, "skirtMesh", 5, LLViewerJoint::PN_5);
-
- // Wearables
- mWearableMap[BAKED_HEAD] = new WearableDictionaryEntry("18ded8d6-bcfc-e415-8539-944c0f5ea7a6", 3, WT_SHAPE, WT_SKIN, WT_HAIR);
- mWearableMap[BAKED_UPPER] = new WearableDictionaryEntry("338c29e3-3024-4dbb-998d-7c04cf4fa88f", 6, WT_SHAPE, WT_SKIN, WT_SHIRT, WT_JACKET, WT_GLOVES, WT_UNDERSHIRT);
- mWearableMap[BAKED_LOWER] = new WearableDictionaryEntry("91b4a2c7-1b1a-ba16-9a16-1f8f8dcc1c3f", 7, WT_SHAPE, WT_SKIN, WT_PANTS, WT_SHOES, WT_SOCKS, WT_JACKET, WT_UNDERPANTS);
- mWearableMap[BAKED_EYES] = new WearableDictionaryEntry("b2cf28af-b840-1071-3c6a-78085d8128b5", 1, WT_EYES);
- mWearableMap[BAKED_SKIRT] = new WearableDictionaryEntry("ea800387-ea1a-14e0-56cb-24f2022f969a", 1, WT_SKIRT);
- mWearableMap[BAKED_HAIR] = new WearableDictionaryEntry("0af1ef7c-ad24-11dd-8790-001f5bf833e8", 1, WT_HAIR);
+ addEntry(MESH_ID_HAIR, new MeshEntry(BAKED_HAIR, "hairMesh", 6, LLViewerJoint::PN_4));
+ addEntry(MESH_ID_HEAD, new MeshEntry(BAKED_HEAD, "headMesh", 5, LLViewerJoint::PN_5));
+ addEntry(MESH_ID_EYELASH, new MeshEntry(BAKED_HEAD, "eyelashMesh", 1, LLViewerJoint::PN_0)); // no baked mesh associated currently
+ addEntry(MESH_ID_UPPER_BODY, new MeshEntry(BAKED_UPPER, "upperBodyMesh", 5, LLViewerJoint::PN_1));
+ addEntry(MESH_ID_LOWER_BODY, new MeshEntry(BAKED_LOWER, "lowerBodyMesh", 5, LLViewerJoint::PN_2));
+ addEntry(MESH_ID_EYEBALL_LEFT, new MeshEntry(BAKED_EYES, "eyeBallLeftMesh", 2, LLViewerJoint::PN_3));
+ addEntry(MESH_ID_EYEBALL_RIGHT, new MeshEntry(BAKED_EYES, "eyeBallRightMesh", 2, LLViewerJoint::PN_3));
+ addEntry(MESH_ID_SKIRT, new MeshEntry(BAKED_SKIRT, "skirtMesh", 5, LLViewerJoint::PN_5));
}
/*
@@ -99,18 +135,22 @@ void LLVOAvatarDictionary::initData()
LLVOAvatarDictionary::LLVOAvatarDictionary()
{
- initData();
createAssociations();
}
+//virtual
+LLVOAvatarDictionary::~LLVOAvatarDictionary()
+{
+}
+
// Baked textures are composites of textures; for each such composited texture,
// map it to the baked texture.
void LLVOAvatarDictionary::createAssociations()
{
- for (baked_map_t::const_iterator iter = mBakedTextureMap.begin(); iter != mBakedTextureMap.end(); iter++)
+ for (BakedTextures::const_iterator iter = mBakedTextures.begin(); iter != mBakedTextures.end(); iter++)
{
const EBakedTextureIndex baked_index = (iter->first);
- const BakedDictionaryEntry *dict = (iter->second);
+ const BakedEntry *dict = (iter->second);
// For each texture that this baked texture index affects, associate those textures
// with this baked texture index.
@@ -119,19 +159,19 @@ void LLVOAvatarDictionary::createAssociations()
local_texture_iter++)
{
const ETextureIndex local_texture_index = (ETextureIndex) *local_texture_iter;
- mTextureMap[local_texture_index]->mIsUsedByBakedTexture = true;
- mTextureMap[local_texture_index]->mBakedTextureIndex = baked_index;
+ mTextures[local_texture_index]->mIsUsedByBakedTexture = true;
+ mTextures[local_texture_index]->mBakedTextureIndex = baked_index;
}
}
}
-LLVOAvatarDictionary::TextureDictionaryEntry::TextureDictionaryEntry(const std::string &name,
- bool is_local_texture,
- EBakedTextureIndex baked_texture_index,
- const std::string &default_image_name,
- EWearableType wearable_type) :
- mName(name),
+LLVOAvatarDictionary::TextureEntry::TextureEntry(const std::string &name,
+ bool is_local_texture,
+ EBakedTextureIndex baked_texture_index,
+ const std::string &default_image_name,
+ EWearableType wearable_type) :
+ LLDictionaryEntry(name),
mIsLocalTexture(is_local_texture),
mIsBakedTexture(!is_local_texture),
mIsUsedByBakedTexture(baked_texture_index != BAKED_NUM_INDICES),
@@ -141,87 +181,88 @@ LLVOAvatarDictionary::TextureDictionaryEntry::TextureDictionaryEntry(const std::
{
}
-LLVOAvatarDictionary::MeshDictionaryEntry::MeshDictionaryEntry(EBakedTextureIndex baked_index,
- const std::string &name,
- U8 level,
- LLViewerJoint::PickName pick) :
+LLVOAvatarDictionary::MeshEntry::MeshEntry(EBakedTextureIndex baked_index,
+ const std::string &name,
+ U8 level,
+ LLViewerJoint::PickName pick) :
+ LLDictionaryEntry(name),
mBakedID(baked_index),
- mName(name),
mLOD(level),
mPickName(pick)
{
}
-LLVOAvatarDictionary::BakedDictionaryEntry::BakedDictionaryEntry(ETextureIndex tex_index,
- const std::string &name,
- U32 num_local_textures, ... ) :
- mName(name),
+LLVOAvatarDictionary::BakedEntry::BakedEntry(ETextureIndex tex_index,
+ const std::string &name,
+ const std::string &hash_name,
+ U32 num_local_textures,
+ ... ) :
+ LLDictionaryEntry(name),
+ mWearablesHashID(LLUUID(hash_name)),
mTextureIndex(tex_index)
-
{
va_list argp;
+
va_start(argp, num_local_textures);
+
+ // Read in local textures
for (U8 i=0; i < num_local_textures; i++)
{
ETextureIndex t = (ETextureIndex)va_arg(argp,int);
mLocalTextures.push_back(t);
}
-}
-LLVOAvatarDictionary::WearableDictionaryEntry::WearableDictionaryEntry(const std::string &hash_name,
- U32 num_wearables, ... ) :
- mHashID(LLUUID(hash_name))
-{
- va_list argp;
- va_start(argp, num_wearables);
+ // Read in number of wearables
+ const U32 num_wearables = (U32)va_arg(argp,int);
+ // Read in wearables
for (U8 i=0; i < num_wearables; i++)
{
EWearableType t = (EWearableType)va_arg(argp,int);
- mWearablesVec.push_back(t);
+ mWearables.push_back(t);
}
}
-//virtual
-LLVOAvatarDictionary::~LLVOAvatarDictionary()
+// static
+ETextureIndex LLVOAvatarDictionary::bakedToLocalTextureIndex(EBakedTextureIndex index)
{
- for (mesh_map_t::iterator iter = mMeshMap.begin(); iter != mMeshMap.end(); iter++)
- delete (iter->second);
- for (baked_map_t::iterator iter = mBakedTextureMap.begin(); iter != mBakedTextureMap.end(); iter++)
- delete (iter->second);
- for (texture_map_t::iterator iter = mTextureMap.begin(); iter != mTextureMap.end(); iter++)
- delete (iter->second);
-}
-
-const LLVOAvatarDictionary::MeshDictionaryEntry *LLVOAvatarDictionary::getMesh(EMeshIndex index) const
-{
- mesh_map_t::const_iterator mesh_iter = mMeshMap.find(index);
- if (mesh_iter == mMeshMap.end()) return NULL;
- return mesh_iter->second;
+ return LLVOAvatarDictionary::getInstance()->getBakedTexture(index)->mTextureIndex;
}
-const LLVOAvatarDictionary::BakedDictionaryEntry *LLVOAvatarDictionary::getBakedTexture(EBakedTextureIndex index) const
+//static
+EBakedTextureIndex LLVOAvatarDictionary::findBakedByRegionName(std::string name)
{
- baked_map_t::const_iterator baked_iter = mBakedTextureMap.find(index);
- if (baked_iter == mBakedTextureMap.end()) return NULL;
- return baked_iter->second;
+ U8 index = 0;
+ while (index < BAKED_NUM_INDICES)
+ {
+ const BakedEntry *be = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex) index);
+ if (be && be->mName.compare(name) == 0)
+ {
+ // baked texture found
+ return (EBakedTextureIndex) index;
+ }
+ index++;
+ }
+ // baked texture could not be found
+ return BAKED_NUM_INDICES;
}
-const LLVOAvatarDictionary::TextureDictionaryEntry *LLVOAvatarDictionary::getTexture(ETextureIndex index) const
+//static
+const LLUUID LLVOAvatarDictionary::getDefaultTextureImageID(ETextureIndex index)
{
- texture_map_t::const_iterator texture_iter = mTextureMap.find(index);
- if (texture_iter == mTextureMap.end()) return NULL;
- return texture_iter->second;
+ const TextureEntry *texture_dict = getInstance()->getTexture(index);
+ const std::string &default_image_name = texture_dict->mDefaultImageName;
+ if (default_image_name == "")
+ {
+ return IMG_DEFAULT_AVATAR;
+ }
+ else
+ {
+ return LLUUID(gSavedSettings.getString(default_image_name));
+ }
}
-const LLVOAvatarDictionary::WearableDictionaryEntry *LLVOAvatarDictionary::getWearable(EBakedTextureIndex index) const
+// static
+EWearableType LLVOAvatarDictionary::getTEWearableType(ETextureIndex index )
{
- wearable_map_t::const_iterator wearable_iter = mWearableMap.find(index);
- if (wearable_iter == mWearableMap.end()) return NULL;
- return wearable_iter->second;
+ return getInstance()->getTexture(index)->mWearableType;
}
-
-
-ETextureIndex LLVOAvatarDefines::getTextureIndex(EBakedTextureIndex index)
-{
- return LLVOAvatarDictionary::getInstance()->getBakedTexture(index)->mTextureIndex;
-}
diff --git a/indra/newview/llvoavatardefines.h b/indra/newview/llvoavatardefines.h
index bc1a1f1c1f..cf3d318159 100644
--- a/indra/newview/llvoavatardefines.h
+++ b/indra/newview/llvoavatardefines.h
@@ -5,7 +5,7 @@
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
- * Copyright (c) 2001-2007, Linden Research, Inc.
+ * Copyright (c) 2001-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -13,12 +13,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
@@ -36,6 +37,7 @@
#include <vector>
#include "llwearable.h"
#include "llviewerjoint.h"
+#include "lldictionary.h"
namespace LLVOAvatarDefines
{
@@ -45,7 +47,7 @@ extern const S32 SCRATCH_TEX_HEIGHT;
extern const S32 IMPOSTOR_PERIOD;
//--------------------------------------------------------------------
-// texture entry assignment
+// Enums
//--------------------------------------------------------------------
enum ETextureIndex
{
@@ -57,9 +59,9 @@ enum ETextureIndex
TEX_UPPER_BODYPAINT,
TEX_LOWER_BODYPAINT,
TEX_LOWER_SHOES,
- TEX_HEAD_BAKED, // Pre-composited
- TEX_UPPER_BAKED, // Pre-composited
- TEX_LOWER_BAKED, // Pre-composited
+ TEX_HEAD_BAKED, // Pre-composited
+ TEX_UPPER_BAKED, // Pre-composited
+ TEX_LOWER_BAKED, // Pre-composited
TEX_EYES_BAKED, // Pre-composited
TEX_LOWER_SOCKS,
TEX_UPPER_JACKET,
@@ -68,14 +70,19 @@ enum ETextureIndex
TEX_UPPER_UNDERSHIRT,
TEX_LOWER_UNDERPANTS,
TEX_SKIRT,
- TEX_SKIRT_BAKED, // Pre-composited
+ TEX_SKIRT_BAKED, // Pre-composited
TEX_HAIR_BAKED, // Pre-composited
+ TEX_LOWER_ALPHA,
+ TEX_UPPER_ALPHA,
+ TEX_HEAD_ALPHA,
+ TEX_EYES_ALPHA,
+ TEX_HAIR_ALPHA,
+ TEX_HEAD_TATTOO,
+ TEX_UPPER_TATTOO,
+ TEX_LOWER_TATTOO,
TEX_NUM_INDICES
-}; // "Note: if TEX_NUM_ENTRIES changes, update AGENT_TEXTURES in llagentinfo.h, mTextureIndexBaked, and BAKED_TEXTURE_COUNT"
-// Seraph - Above comment about order is probably obsolete.
+};
-typedef std::vector<ETextureIndex> texture_vec_t;
-
enum EBakedTextureIndex
{
BAKED_HEAD = 0,
@@ -86,7 +93,6 @@ enum EBakedTextureIndex
BAKED_HAIR,
BAKED_NUM_INDICES
};
-typedef std::vector<EBakedTextureIndex> bakedtexture_vec_t;
// Reference IDs for each mesh. Used as indices for vector of joints
enum EMeshIndex
@@ -101,19 +107,15 @@ enum EMeshIndex
MESH_ID_SKIRT,
MESH_ID_NUM_INDICES
};
-typedef std::vector<EMeshIndex> mesh_vec_t;
+//--------------------------------------------------------------------
+// Vector Types
+//--------------------------------------------------------------------
+typedef std::vector<ETextureIndex> texture_vec_t;
+typedef std::vector<EBakedTextureIndex> bakedtexture_vec_t;
+typedef std::vector<EMeshIndex> mesh_vec_t;
typedef std::vector<EWearableType> wearables_vec_t;
-//--------------------------------------------------------------------------------
-// Convenience Functions
-//--------------------------------------------------------------------------------
-
-// Convert from baked texture to associated texture; e.g. BAKED_HEAD -> TEX_HEAD_BAKED
-ETextureIndex getTextureIndex(EBakedTextureIndex t);
-
-
-
//------------------------------------------------------------------------
// LLVOAvatarDictionary
//
@@ -124,86 +126,109 @@ ETextureIndex getTextureIndex(EBakedTextureIndex t);
//------------------------------------------------------------------------
class LLVOAvatarDictionary : public LLSingleton<LLVOAvatarDictionary>
{
+ //--------------------------------------------------------------------
+ // Constructors and Destructors
+ //--------------------------------------------------------------------
public:
LLVOAvatarDictionary();
virtual ~LLVOAvatarDictionary();
+private:
+ void createAssociations();
- struct TextureDictionaryEntry
+ //--------------------------------------------------------------------
+ // Local and baked textures
+ //--------------------------------------------------------------------
+public:
+ struct TextureEntry : public LLDictionaryEntry
{
- TextureDictionaryEntry(const std::string &name,
- bool is_local_texture,
- EBakedTextureIndex baked_texture_index = BAKED_NUM_INDICES,
- const std::string &default_image_name = "",
- EWearableType wearable_type = WT_INVALID);
- const std::string mName;
- const std::string mDefaultImageName;
+ TextureEntry(const std::string &name, // this must match the xml name used by LLTexLayerInfo::parseXml
+ bool is_local_texture,
+ EBakedTextureIndex baked_texture_index = BAKED_NUM_INDICES,
+ const std::string& default_image_name = "",
+ EWearableType wearable_type = WT_INVALID);
+ const std::string mDefaultImageName;
const EWearableType mWearableType;
// It's either a local texture xor baked
- BOOL mIsLocalTexture;
- BOOL mIsBakedTexture;
+ BOOL mIsLocalTexture;
+ BOOL mIsBakedTexture;
// If it's a local texture, it may be used by a baked texture
- BOOL mIsUsedByBakedTexture;
- EBakedTextureIndex mBakedTextureIndex;
+ BOOL mIsUsedByBakedTexture;
+ EBakedTextureIndex mBakedTextureIndex;
};
+
+ struct Textures : public LLDictionary<ETextureIndex, TextureEntry>
+ {
+ Textures();
+ } mTextures;
+ const TextureEntry* getTexture(ETextureIndex index) const { return mTextures.lookup(index); }
+ const Textures& getTextures() const { return mTextures; }
- struct MeshDictionaryEntry
+ //--------------------------------------------------------------------
+ // Meshes
+ //--------------------------------------------------------------------
+public:
+ struct MeshEntry : public LLDictionaryEntry
{
- MeshDictionaryEntry(EBakedTextureIndex baked_index,
- const std::string &name,
- U8 level,
- LLViewerJoint::PickName pick);
- const std::string mName; // names of mesh types as they are used in avatar_lad.xml
+ MeshEntry(EBakedTextureIndex baked_index,
+ const std::string &name, // names of mesh types as they are used in avatar_lad.xml
+ U8 level,
+ LLViewerJoint::PickName pick);
// Levels of Detail for each mesh. Must match levels of detail present in avatar_lad.xml
// Otherwise meshes will be unable to be found, or levels of detail will be ignored
- const U8 mLOD;
- const EBakedTextureIndex mBakedID;
- const LLViewerJoint::PickName mPickName;
+ const U8 mLOD;
+ const EBakedTextureIndex mBakedID;
+ const LLViewerJoint::PickName mPickName;
};
- struct BakedDictionaryEntry
+ struct Meshes : public LLDictionary<EMeshIndex, MeshEntry>
{
- BakedDictionaryEntry(ETextureIndex tex_index,
- const std::string &name,
- U32 num_local_textures, ... );
- const ETextureIndex mTextureIndex;
- const std::string mName;
- texture_vec_t mLocalTextures;
- };
-
- struct WearableDictionaryEntry
+ Meshes();
+ } mMeshes;
+ const MeshEntry* getMesh(EMeshIndex index) const { return mMeshes.lookup(index); }
+ const Meshes& getMeshes() const { return mMeshes; }
+
+ //--------------------------------------------------------------------
+ // Baked Textures
+ //--------------------------------------------------------------------
+public:
+ struct BakedEntry : public LLDictionaryEntry
{
- WearableDictionaryEntry(const std::string &hash_name,
- U32 num_wearables, ... );
- const LLUUID mHashID;
- wearables_vec_t mWearablesVec;
+ BakedEntry(ETextureIndex tex_index,
+ const std::string &name, // unused, but necessary for templating.
+ const std::string &hash_name,
+ U32 num_local_textures, ... ); // # local textures, local texture list, # wearables, wearable list
+ // Local Textures
+ const ETextureIndex mTextureIndex;
+ texture_vec_t mLocalTextures;
+ // Wearables
+ const LLUUID mWearablesHashID;
+ wearables_vec_t mWearables;
};
- typedef std::map<EBakedTextureIndex, BakedDictionaryEntry*> baked_map_t;
- typedef std::map<ETextureIndex, TextureDictionaryEntry*> texture_map_t;
- typedef std::map<EMeshIndex, MeshDictionaryEntry*> mesh_map_t;
- typedef std::map<EBakedTextureIndex, WearableDictionaryEntry*> wearable_map_t;
+ struct BakedTextures: public LLDictionary<EBakedTextureIndex, BakedEntry>
+ {
+ BakedTextures();
+ } mBakedTextures;
+ const BakedEntry* getBakedTexture(EBakedTextureIndex index) const { return mBakedTextures.lookup(index); }
+ const BakedTextures& getBakedTextures() const { return mBakedTextures; }
+
+ //--------------------------------------------------------------------
+ // Convenience Functions
+ //--------------------------------------------------------------------
+public:
+ // Convert from baked texture to associated texture; e.g. BAKED_HEAD -> TEX_HEAD_BAKED
+ static ETextureIndex bakedToLocalTextureIndex(EBakedTextureIndex t);
- const MeshDictionaryEntry *getMesh(EMeshIndex index) const;
- const BakedDictionaryEntry *getBakedTexture(EBakedTextureIndex index) const;
- const TextureDictionaryEntry *getTexture(ETextureIndex index) const;
- const WearableDictionaryEntry *getWearable(EBakedTextureIndex index) const;
+ // find a baked texture index based on its name
+ static EBakedTextureIndex findBakedByRegionName(std::string name);
- const texture_map_t &getTextures() const { return mTextureMap; }
- const baked_map_t &getBakedTextures() const { return mBakedTextureMap; }
- const mesh_map_t &getMeshes() const { return mMeshMap; }
- const wearable_map_t &getWearables() const { return mWearableMap; }
-
-private:
- void initData();
- void createAssociations();
+ static const LLUUID getDefaultTextureImageID(ETextureIndex index);
- texture_map_t mTextureMap;
- baked_map_t mBakedTextureMap;
- mesh_map_t mMeshMap;
- wearable_map_t mWearableMap;
+ // Given a texture entry, determine which wearable type owns it.
+ static EWearableType getTEWearableType(ETextureIndex index);
}; // End LLVOAvatarDictionary
} // End namespace LLVOAvatarDefines
-#endif
+#endif //LL_VO_AVATARDEFINES_H
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
new file mode 100644
index 0000000000..ecd6b05ded
--- /dev/null
+++ b/indra/newview/llvoavatarself.cpp
@@ -0,0 +1,2241 @@
+/**
+ * @file llvoavatar.cpp
+ * @brief Implementation of LLVOAvatar class which is a derivation fo LLViewerObject
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#if LL_MSVC
+// disable warning about boost::lexical_cast returning uninitialized data
+// when it fails to parse the string
+#pragma warning (disable:4701)
+#endif
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llvoavatarself.h"
+#include "llvoavatar.h"
+
+#include "pipeline.h"
+
+#include "llagent.h" // Get state values from here
+#include "llagentwearables.h"
+#include "llhudeffecttrail.h"
+#include "llhudmanager.h"
+#include "llselectmgr.h"
+#include "lltoolgrab.h" // for needsRenderBeam
+#include "lltoolmgr.h" // for needsRenderBeam
+#include "lltoolmorph.h"
+#include "lltrans.h"
+#include "llviewercamera.h"
+#include "llviewermenu.h"
+#include "llviewerobjectlist.h"
+#include "llviewerstats.h"
+#include "llviewerregion.h"
+#include "llappearancemgr.h"
+
+#if LL_MSVC
+// disable boost::lexical_cast warning
+#pragma warning (disable:4702)
+#endif
+
+#include <boost/lexical_cast.hpp>
+
+using namespace LLVOAvatarDefines;
+
+/*********************************************************************************
+ ** **
+ ** Begin private LLVOAvatarSelf Support classes
+ **
+ **/
+
+struct LocalTextureData
+{
+ LocalTextureData() :
+ mIsBakedReady(FALSE),
+ mDiscard(MAX_DISCARD_LEVEL+1),
+ mImage(NULL),
+ mWearableID(IMG_DEFAULT_AVATAR),
+ mTexEntry(NULL)
+ {}
+ LLPointer<LLViewerFetchedTexture> mImage;
+ BOOL mIsBakedReady;
+ S32 mDiscard;
+ LLUUID mWearableID; // UUID of the wearable that this texture belongs to, not of the image itself
+ LLTextureEntry *mTexEntry;
+};
+
+//-----------------------------------------------------------------------------
+// Callback data
+//-----------------------------------------------------------------------------
+struct LLAvatarTexData
+{
+ LLAvatarTexData(const LLUUID& id, ETextureIndex index) :
+ mAvatarID(id),
+ mIndex(index)
+ {}
+ LLUUID mAvatarID;
+ ETextureIndex mIndex;
+};
+
+/**
+ **
+ ** End LLVOAvatarSelf Support classes
+ ** **
+ *********************************************************************************/
+
+
+//-----------------------------------------------------------------------------
+// Static Data
+//-----------------------------------------------------------------------------
+S32 LLVOAvatarSelf::sScratchTexBytes = 0;
+LLMap< LLGLenum, LLGLuint*> LLVOAvatarSelf::sScratchTexNames;
+LLMap< LLGLenum, F32*> LLVOAvatarSelf::sScratchTexLastBindTime;
+
+
+/*********************************************************************************
+ ** **
+ ** Begin LLVOAvatarSelf Constructor routines
+ **
+ **/
+
+LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id,
+ const LLPCode pcode,
+ LLViewerRegion* regionp) :
+ LLVOAvatar(id, pcode, regionp),
+ mScreenp(NULL),
+ mLastRegionHandle(0),
+ mRegionCrossingCount(0)
+{
+ gAgent.setAvatarObject(this);
+ gAgentWearables.setAvatarObject(this);
+
+ lldebugs << "Marking avatar as self " << id << llendl;
+}
+
+void LLVOAvatarSelf::initInstance()
+{
+ BOOL status = TRUE;
+ // creates hud joint(mScreen) among other things
+ status &= loadAvatarSelf();
+
+ // adds attachment points to mScreen among other things
+ LLVOAvatar::initInstance();
+
+ status &= buildMenus();
+ if (!status)
+ {
+ llerrs << "Unable to load user's avatar" << llendl;
+ return;
+ }
+}
+
+// virtual
+void LLVOAvatarSelf::markDead()
+{
+ mBeam = NULL;
+ LLVOAvatar::markDead();
+}
+
+/*virtual*/ BOOL LLVOAvatarSelf::loadAvatar()
+{
+ BOOL success = LLVOAvatar::loadAvatar();
+
+ // set all parameters sotred directly in the avatar to have
+ // the isSelfParam to be TRUE - this is used to prevent
+ // them from being animated or trigger accidental rebakes
+ // when we copy params from the wearable to the base avatar.
+ for (LLViewerVisualParam* param = (LLViewerVisualParam*) getFirstVisualParam();
+ param;
+ param = (LLViewerVisualParam*) getNextVisualParam())
+ {
+ if (param->getWearableType() != WT_INVALID)
+ {
+ param->setIsDummy(TRUE);
+ }
+ }
+
+ return success;
+}
+
+
+BOOL LLVOAvatarSelf::loadAvatarSelf()
+{
+ BOOL success = TRUE;
+ // avatar_skeleton.xml
+ if (!buildSkeletonSelf(sAvatarSkeletonInfo))
+ {
+ llwarns << "avatar file: buildSkeleton() failed" << llendl;
+ return FALSE;
+ }
+ // TODO: make loadLayersets() called only by self.
+ //success &= loadLayersets();
+
+ return success;
+}
+
+BOOL LLVOAvatarSelf::buildSkeletonSelf(const LLVOAvatarSkeletonInfo *info)
+{
+ LLMemType mt(LLMemType::MTYPE_AVATAR);
+
+ // add special-purpose "screen" joint
+ mScreenp = new LLViewerJoint("mScreen", NULL);
+ // for now, put screen at origin, as it is only used during special
+ // HUD rendering mode
+ F32 aspect = LLViewerCamera::getInstance()->getAspect();
+ LLVector3 scale(1.f, aspect, 1.f);
+ mScreenp->setScale(scale);
+ mScreenp->setWorldPosition(LLVector3::zero);
+ return TRUE;
+}
+
+BOOL LLVOAvatarSelf::buildMenus()
+{
+ //-------------------------------------------------------------------------
+ // build the attach and detach menus
+ //-------------------------------------------------------------------------
+ gAttachBodyPartPieMenus[0] = NULL;
+
+ LLContextMenu::Params params;
+ params.label(LLTrans::getString("BodyPartsRightArm") + " >");
+ params.name(params.label);
+ params.visible(false);
+ gAttachBodyPartPieMenus[1] = LLUICtrlFactory::create<LLContextMenu> (params);
+
+ params.label(LLTrans::getString("BodyPartsHead") + " >");
+ params.name(params.label);
+ gAttachBodyPartPieMenus[2] = LLUICtrlFactory::create<LLContextMenu> (params);
+
+ params.label(LLTrans::getString("BodyPartsLeftArm") + " >");
+ params.name(params.label);
+ gAttachBodyPartPieMenus[3] = LLUICtrlFactory::create<LLContextMenu> (params);
+
+ gAttachBodyPartPieMenus[4] = NULL;
+
+ params.label(LLTrans::getString("BodyPartsLeftLeg") + " >");
+ params.name(params.label);
+ gAttachBodyPartPieMenus[5] = LLUICtrlFactory::create<LLContextMenu> (params);
+
+ params.label(LLTrans::getString("BodyPartsTorso") + " >");
+ params.name(params.label);
+ gAttachBodyPartPieMenus[6] = LLUICtrlFactory::create<LLContextMenu> (params);
+
+ params.label(LLTrans::getString("BodyPartsRightLeg") + " >");
+ params.name(params.label);
+ gAttachBodyPartPieMenus[7] = LLUICtrlFactory::create<LLContextMenu> (params);
+
+ gDetachBodyPartPieMenus[0] = NULL;
+
+ params.label(LLTrans::getString("BodyPartsRightArm") + " >");
+ params.name(params.label);
+ gDetachBodyPartPieMenus[1] = LLUICtrlFactory::create<LLContextMenu> (params);
+
+ params.label(LLTrans::getString("BodyPartsHead") + " >");
+ params.name(params.label);
+ gDetachBodyPartPieMenus[2] = LLUICtrlFactory::create<LLContextMenu> (params);
+
+ params.label(LLTrans::getString("BodyPartsLeftArm") + " >");
+ params.name(params.label);
+ gDetachBodyPartPieMenus[3] = LLUICtrlFactory::create<LLContextMenu> (params);
+
+ gDetachBodyPartPieMenus[4] = NULL;
+
+ params.label(LLTrans::getString("BodyPartsLeftLeg") + " >");
+ params.name(params.label);
+ gDetachBodyPartPieMenus[5] = LLUICtrlFactory::create<LLContextMenu> (params);
+
+ params.label(LLTrans::getString("BodyPartsTorso") + " >");
+ params.name(params.label);
+ gDetachBodyPartPieMenus[6] = LLUICtrlFactory::create<LLContextMenu> (params);
+
+ params.label(LLTrans::getString("BodyPartsRightLeg") + " >");
+ params.name(params.label);
+ gDetachBodyPartPieMenus[7] = LLUICtrlFactory::create<LLContextMenu> (params);
+
+ for (S32 i = 0; i < 8; i++)
+ {
+ if (gAttachBodyPartPieMenus[i])
+ {
+ gAttachPieMenu->appendContextSubMenu( gAttachBodyPartPieMenus[i] );
+ }
+ else
+ {
+ BOOL attachment_found = FALSE;
+ for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+ if (attachment->getGroup() == i)
+ {
+ LLMenuItemCallGL::Params item_params;
+
+ std::string sub_piemenu_name = attachment->getName();
+ if (LLTrans::getString(sub_piemenu_name) != "")
+ {
+ item_params.label = LLTrans::getString(sub_piemenu_name);
+ }
+ else
+ {
+ item_params.label = sub_piemenu_name;
+ }
+ item_params.name =(item_params.label );
+ item_params.on_click.function_name = "Object.AttachToAvatar";
+ item_params.on_click.parameter = iter->first;
+ item_params.on_enable.function_name = "Object.EnableWear";
+ item_params.on_enable.parameter = iter->first;
+ LLMenuItemCallGL* item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params);
+
+ gAttachPieMenu->addChild(item);
+
+ attachment_found = TRUE;
+ break;
+
+ }
+ }
+ }
+
+ if (gDetachBodyPartPieMenus[i])
+ {
+ gDetachPieMenu->appendContextSubMenu( gDetachBodyPartPieMenus[i] );
+ }
+ else
+ {
+ BOOL attachment_found = FALSE;
+ for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+ if (attachment->getGroup() == i)
+ {
+ LLMenuItemCallGL::Params item_params;
+ std::string sub_piemenu_name = attachment->getName();
+ if (LLTrans::getString(sub_piemenu_name) != "")
+ {
+ item_params.label = LLTrans::getString(sub_piemenu_name);
+ }
+ else
+ {
+ item_params.label = sub_piemenu_name;
+ }
+ item_params.name =(item_params.label );
+ item_params.on_click.function_name = "Attachment.Detach";
+ item_params.on_click.parameter = iter->first;
+ item_params.on_enable.function_name = "Attachment.EnableDetach";
+ item_params.on_enable.parameter = iter->first;
+ LLMenuItemCallGL* item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params);
+
+ gDetachPieMenu->addChild(item);
+
+ attachment_found = TRUE;
+ break;
+ }
+ }
+ }
+ }
+
+ // add screen attachments
+ for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+ if (attachment->getGroup() == 8)
+ {
+ LLMenuItemCallGL::Params item_params;
+ std::string sub_piemenu_name = attachment->getName();
+ if (LLTrans::getString(sub_piemenu_name) != "")
+ {
+ item_params.label = LLTrans::getString(sub_piemenu_name);
+ }
+ else
+ {
+ item_params.label = sub_piemenu_name;
+ }
+ item_params.name =(item_params.label );
+ item_params.on_click.function_name = "Object.AttachToAvatar";
+ item_params.on_click.parameter = iter->first;
+ item_params.on_enable.function_name = "Object.EnableWear";
+ item_params.on_enable.parameter = iter->first;
+ LLMenuItemCallGL* item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params);
+ gAttachScreenPieMenu->addChild(item);
+
+ item_params.on_click.function_name = "Attachment.DetachFromPoint";
+ item_params.on_click.parameter = iter->first;
+ item_params.on_enable.function_name = "Attachment.PointFilled";
+ item_params.on_enable.parameter = iter->first;
+ item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params);
+ gDetachScreenPieMenu->addChild(item);
+ }
+ }
+
+ for (S32 pass = 0; pass < 2; pass++)
+ {
+ // *TODO: Skinning - gAttachSubMenu is an awful, awful hack
+ if (!gAttachSubMenu)
+ {
+ break;
+ }
+ for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+ if (attachment->getIsHUDAttachment() != (pass == 1))
+ {
+ continue;
+ }
+ LLMenuItemCallGL::Params item_params;
+ std::string sub_piemenu_name = attachment->getName();
+ if (LLTrans::getString(sub_piemenu_name) != "")
+ {
+ item_params.label = LLTrans::getString(sub_piemenu_name);
+ }
+ else
+ {
+ item_params.label = sub_piemenu_name;
+ }
+ item_params.name =(item_params.label );
+ item_params.on_click.function_name = "Object.AttachToAvatar";
+ item_params.on_click.parameter = iter->first;
+ item_params.on_enable.function_name = "Object.EnableWear";
+ item_params.on_enable.parameter = iter->first;
+ //* TODO: Skinning:
+ //LLSD params;
+ //params["index"] = iter->first;
+ //params["label"] = attachment->getName();
+ //item->addEventHandler("on_enable", LLMenuItemCallGL::MenuCallback().function_name("Attachment.Label").parameter(params));
+
+ LLMenuItemCallGL* item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params);
+ gAttachSubMenu->addChild(item);
+
+ item_params.on_click.function_name = "Attachment.DetachFromPoint";
+ item_params.on_click.parameter = iter->first;
+ item_params.on_enable.function_name = "Attachment.PointFilled";
+ item_params.on_enable.parameter = iter->first;
+ //* TODO: Skinning: item->addEventHandler("on_enable", LLMenuItemCallGL::MenuCallback().function_name("Attachment.Label").parameter(params));
+
+ item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params);
+ gDetachSubMenu->addChild(item);
+ }
+ if (pass == 0)
+ {
+ // put separator between non-hud and hud attachments
+ gAttachSubMenu->addSeparator();
+ gDetachSubMenu->addSeparator();
+ }
+ }
+
+ for (S32 group = 0; group < 8; group++)
+ {
+ // skip over groups that don't have sub menus
+ if (!gAttachBodyPartPieMenus[group] || !gDetachBodyPartPieMenus[group])
+ {
+ continue;
+ }
+
+ std::multimap<S32, S32> attachment_pie_menu_map;
+
+ // gather up all attachment points assigned to this group, and throw into map sorted by pie slice number
+ for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+ if(attachment->getGroup() == group)
+ {
+ // use multimap to provide a partial order off of the pie slice key
+ S32 pie_index = attachment->getPieSlice();
+ attachment_pie_menu_map.insert(std::make_pair(pie_index, iter->first));
+ }
+ }
+
+ // add in requested order to pie menu, inserting separators as necessary
+ for (std::multimap<S32, S32>::iterator attach_it = attachment_pie_menu_map.begin();
+ attach_it != attachment_pie_menu_map.end(); ++attach_it)
+ {
+ S32 attach_index = attach_it->second;
+
+ LLViewerJointAttachment* attachment = get_if_there(mAttachmentPoints, attach_index, (LLViewerJointAttachment*)NULL);
+ if (attachment)
+ {
+ LLMenuItemCallGL::Params item_params;
+ item_params.name = attachment->getName();
+ item_params.label = attachment->getName();
+ item_params.on_click.function_name = "Object.AttachToAvatar";
+ item_params.on_click.parameter = attach_index;
+ item_params.on_enable.function_name = "Object.EnableWear";
+ item_params.on_enable.parameter = attach_index;
+
+ LLMenuItemCallGL* item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params);
+ gAttachBodyPartPieMenus[group]->addChild(item);
+
+ item_params.on_click.function_name = "Attachment.DetachFromPoint";
+ item_params.on_click.parameter = attach_index;
+ item_params.on_enable.function_name = "Attachment.PointFilled";
+ item_params.on_enable.parameter = attach_index;
+ item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params);
+ gDetachBodyPartPieMenus[group]->addChild(item);
+ }
+ }
+ }
+ return TRUE;
+}
+
+LLVOAvatarSelf::~LLVOAvatarSelf()
+{
+ gAgent.setAvatarObject(NULL);
+ gAgentWearables.setAvatarObject(NULL);
+ delete mScreenp;
+ mScreenp = NULL;
+}
+
+/**
+ **
+ ** End LLVOAvatarSelf Constructor routines
+ ** **
+ *********************************************************************************/
+
+//virtual
+BOOL LLVOAvatarSelf::loadLayersets()
+{
+ BOOL success = TRUE;
+ for (LLVOAvatarXmlInfo::layer_info_list_t::const_iterator iter = sAvatarXmlInfo->mLayerInfoList.begin();
+ iter != sAvatarXmlInfo->mLayerInfoList.end();
+ ++iter)
+ {
+ // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such.
+ const LLTexLayerSetInfo *info = *iter;
+ LLTexLayerSet* layer_set = new LLTexLayerSet( this );
+
+ if (!layer_set->setInfo(info))
+ {
+ stop_glerror();
+ delete layer_set;
+ llwarns << "avatar file: layer_set->parseData() failed" << llendl;
+ return FALSE;
+ }
+
+ // scan baked textures and associate the layerset with the appropriate one
+ EBakedTextureIndex baked_index = BAKED_NUM_INDICES;
+ for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
+ baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end();
+ ++baked_iter)
+ {
+ const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second;
+ if (layer_set->isBodyRegion(baked_dict->mName))
+ {
+ baked_index = baked_iter->first;
+ // ensure both structures are aware of each other
+ mBakedTextureDatas[baked_index].mTexLayerSet = layer_set;
+ layer_set->setBakedTexIndex(baked_index);
+ break;
+ }
+ }
+ // if no baked texture was found, warn and cleanup
+ if (baked_index == BAKED_NUM_INDICES)
+ {
+ llwarns << "<layer_set> has invalid body_region attribute" << llendl;
+ delete layer_set;
+ return FALSE;
+ }
+
+ // scan morph masks and let any affected layers know they have an associated morph
+ for (LLVOAvatar::morph_list_t::const_iterator morph_iter = mBakedTextureDatas[baked_index].mMaskedMorphs.begin();
+ morph_iter != mBakedTextureDatas[baked_index].mMaskedMorphs.end();
+ ++morph_iter)
+ {
+ LLMaskedMorph *morph = *morph_iter;
+ LLTexLayerInterface* layer = layer_set->findLayerByName(morph->mLayer);
+ if (layer)
+ {
+ layer->setHasMorph(TRUE);
+ }
+ else
+ {
+ llwarns << "Could not find layer named " << morph->mLayer << " to set morph flag" << llendl;
+ success = FALSE;
+ }
+ }
+ }
+ return success;
+}
+// virtual
+BOOL LLVOAvatarSelf::updateCharacter(LLAgent &agent)
+{
+ LLMemType mt(LLMemType::MTYPE_AVATAR);
+
+ // update screen joint size
+ if (mScreenp)
+ {
+ F32 aspect = LLViewerCamera::getInstance()->getAspect();
+ LLVector3 scale(1.f, aspect, 1.f);
+ mScreenp->setScale(scale);
+ mScreenp->updateWorldMatrixChildren();
+ resetHUDAttachments();
+ }
+ return LLVOAvatar::updateCharacter(agent);
+}
+
+// virtual
+LLJoint *LLVOAvatarSelf::getJoint(const std::string &name)
+{
+ if (mScreenp)
+ {
+ LLJoint* jointp = mScreenp->findJoint(name);
+ if (jointp) return jointp;
+ }
+ return LLVOAvatar::getJoint(name);
+}
+
+/*virtual*/ BOOL LLVOAvatarSelf::setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL upload_bake )
+{
+ if (!which_param)
+ {
+ return FALSE;
+ }
+ LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(which_param->getID());
+ return setParamWeight(param,weight,upload_bake);
+}
+
+/*virtual*/ BOOL LLVOAvatarSelf::setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake )
+{
+ if (!param_name)
+ {
+ return FALSE;
+ }
+ LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(param_name);
+ return setParamWeight(param,weight,upload_bake);
+}
+
+/*virtual*/ BOOL LLVOAvatarSelf::setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake )
+{
+ LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(index);
+ return setParamWeight(param,weight,upload_bake);
+}
+
+BOOL LLVOAvatarSelf::setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL upload_bake )
+{
+ if (!param)
+ {
+ return FALSE;
+ }
+
+ if (param->getCrossWearable())
+ {
+ EWearableType type = (EWearableType)param->getWearableType();
+ U32 size = gAgentWearables.getWearableCount(type);
+ for (U32 count = 0; count < size; ++count)
+ {
+ LLWearable *wearable = gAgentWearables.getWearable(type,count);
+ if (wearable)
+ {
+ wearable->setVisualParamWeight(param->getID(), weight, upload_bake);
+ }
+ }
+ }
+
+ return LLCharacter::setVisualParamWeight(param,weight,upload_bake);
+}
+
+/*virtual*/
+void LLVOAvatarSelf::updateVisualParams()
+{
+ for (U32 type = 0; type < WT_COUNT; type++)
+ {
+ LLWearable *wearable = gAgentWearables.getTopWearable((EWearableType)type);
+ if (wearable)
+ {
+ wearable->writeToAvatar();
+ }
+ }
+
+ LLVOAvatar::updateVisualParams();
+}
+
+/*virtual*/
+void LLVOAvatarSelf::idleUpdateAppearanceAnimation()
+{
+ // Animate all top-level wearable visual parameters
+ gAgentWearables.animateAllWearableParams(calcMorphAmount(), FALSE);
+
+ // apply wearable visual params to avatar
+ updateVisualParams();
+
+ //allow avatar to process updates
+ LLVOAvatar::idleUpdateAppearanceAnimation();
+
+}
+
+// virtual
+void LLVOAvatarSelf::requestStopMotion(LLMotion* motion)
+{
+ // Only agent avatars should handle the stop motion notifications.
+
+ // Notify agent that motion has stopped
+ gAgent.requestStopMotion(motion);
+}
+
+// virtual
+void LLVOAvatarSelf::stopMotionFromSource(const LLUUID& source_id)
+{
+ for (AnimSourceIterator motion_it = mAnimationSources.find(source_id); motion_it != mAnimationSources.end(); )
+ {
+ gAgent.sendAnimationRequest(motion_it->second, ANIM_REQUEST_STOP);
+ mAnimationSources.erase(motion_it++);
+ }
+
+ LLViewerObject* object = gObjectList.findObject(source_id);
+ if (object)
+ {
+ object->mFlags &= ~FLAGS_ANIM_SOURCE;
+ }
+}
+
+void LLVOAvatarSelf::setLocalTextureTE(U8 te, LLViewerTexture* image, U32 index)
+{
+ if (te >= TEX_NUM_INDICES)
+ {
+ llassert(0);
+ return;
+ }
+
+ if (getTEImage(te)->getID() == image->getID())
+ {
+ return;
+ }
+
+ if (isIndexBakedTexture((ETextureIndex)te))
+ {
+ llassert(0);
+ return;
+ }
+
+ setTEImage(te, image);
+}
+
+//virtual
+void LLVOAvatarSelf::removeMissingBakedTextures()
+{
+ BOOL removed = FALSE;
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
+ {
+ const S32 te = mBakedTextureDatas[i].mTextureIndex;
+ LLViewerTexture* tex = getTEImage(te) ;
+ if (!tex || tex->isMissingAsset())
+ {
+ setTEImage(te, LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR));
+ removed = TRUE;
+ }
+ }
+
+ if (removed)
+ {
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
+ {
+ invalidateComposite(mBakedTextureDatas[i].mTexLayerSet, FALSE);
+ }
+ updateMeshTextures();
+ requestLayerSetUploads();
+ }
+}
+
+//virtual
+void LLVOAvatarSelf::updateRegion(LLViewerRegion *regionp)
+{
+ if (regionp->getHandle() != mLastRegionHandle)
+ {
+ if (mLastRegionHandle != 0)
+ {
+ ++mRegionCrossingCount;
+ F64 delta = (F64)mRegionCrossingTimer.getElapsedTimeF32();
+ F64 avg = (mRegionCrossingCount == 1) ? 0 : LLViewerStats::getInstance()->getStat(LLViewerStats::ST_CROSSING_AVG);
+ F64 delta_avg = (delta + avg*(mRegionCrossingCount-1)) / mRegionCrossingCount;
+ LLViewerStats::getInstance()->setStat(LLViewerStats::ST_CROSSING_AVG, delta_avg);
+
+ F64 max = (mRegionCrossingCount == 1) ? 0 : LLViewerStats::getInstance()->getStat(LLViewerStats::ST_CROSSING_MAX);
+ max = llmax(delta, max);
+ LLViewerStats::getInstance()->setStat(LLViewerStats::ST_CROSSING_MAX, max);
+ }
+ mLastRegionHandle = regionp->getHandle();
+ }
+ mRegionCrossingTimer.reset();
+}
+
+//--------------------------------------------------------------------
+// draw tractor beam when editing objects
+//--------------------------------------------------------------------
+//virtual
+void LLVOAvatarSelf::idleUpdateTractorBeam()
+{
+ // This is only done for yourself (maybe it should be in the agent?)
+ if (!needsRenderBeam() || !mIsBuilt)
+ {
+ mBeam = NULL;
+ }
+ else if (!mBeam || mBeam->isDead())
+ {
+ // VEFFECT: Tractor Beam
+ mBeam = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM);
+ mBeam->setColor(LLColor4U(gAgent.getEffectColor()));
+ mBeam->setSourceObject(this);
+ mBeamTimer.reset();
+ }
+
+ if (!mBeam.isNull())
+ {
+ LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+
+ if (gAgent.mPointAt.notNull())
+ {
+ // get point from pointat effect
+ mBeam->setPositionGlobal(gAgent.mPointAt->getPointAtPosGlobal());
+ mBeam->triggerLocal();
+ }
+ else if (selection->getFirstRootObject() &&
+ selection->getSelectType() != SELECT_TYPE_HUD)
+ {
+ LLViewerObject* objectp = selection->getFirstRootObject();
+ mBeam->setTargetObject(objectp);
+ }
+ else
+ {
+ mBeam->setTargetObject(NULL);
+ LLTool *tool = LLToolMgr::getInstance()->getCurrentTool();
+ if (tool->isEditing())
+ {
+ if (tool->getEditingObject())
+ {
+ mBeam->setTargetObject(tool->getEditingObject());
+ }
+ else
+ {
+ mBeam->setPositionGlobal(tool->getEditingPointGlobal());
+ }
+ }
+ else
+ {
+ const LLPickInfo& pick = gViewerWindow->getLastPick();
+ mBeam->setPositionGlobal(pick.mPosGlobal);
+ }
+
+ }
+ if (mBeamTimer.getElapsedTimeF32() > 0.25f)
+ {
+ mBeam->setColor(LLColor4U(gAgent.getEffectColor()));
+ mBeam->setNeedsSendToSim(TRUE);
+ mBeamTimer.reset();
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// restoreMeshData()
+//-----------------------------------------------------------------------------
+// virtual
+void LLVOAvatarSelf::restoreMeshData()
+{
+ LLMemType mt(LLMemType::MTYPE_AVATAR);
+
+ //llinfos << "Restoring" << llendl;
+ mMeshValid = TRUE;
+ updateJointLODs();
+ updateAttachmentVisibility(gAgent.getCameraMode());
+
+ // force mesh update as LOD might not have changed to trigger this
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE);
+}
+
+
+
+//-----------------------------------------------------------------------------
+// updateAttachmentVisibility()
+//-----------------------------------------------------------------------------
+void LLVOAvatarSelf::updateAttachmentVisibility(U32 camera_mode)
+{
+ for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+ if (attachment->getIsHUDAttachment())
+ {
+ attachment->setAttachmentVisibility(TRUE);
+ }
+ else
+ {
+ switch (camera_mode)
+ {
+ case CAMERA_MODE_MOUSELOOK:
+ if (LLVOAvatar::sVisibleInFirstPerson && attachment->getVisibleInFirstPerson())
+ {
+ attachment->setAttachmentVisibility(TRUE);
+ }
+ else
+ {
+ attachment->setAttachmentVisibility(FALSE);
+ }
+ break;
+ default:
+ attachment->setAttachmentVisibility(TRUE);
+ break;
+ }
+ }
+ }
+}
+
+/*virtual*/ BOOL LLVOAvatarSelf::isWearingWearableType(EWearableType type ) const
+{
+ return gAgentWearables.getWearableCount(type) > 0;
+}
+
+//-----------------------------------------------------------------------------
+// updatedWearable( EWearableType type )
+// forces an update to any baked textures relevant to type.
+// will force an upload of the resulting bake if the second parameter is TRUE
+//-----------------------------------------------------------------------------
+void LLVOAvatarSelf::wearableUpdated( EWearableType type, BOOL upload_result )
+{
+ for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
+ baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end();
+ ++baked_iter)
+ {
+ const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second;
+ const LLVOAvatarDefines::EBakedTextureIndex index = baked_iter->first;
+ if (baked_dict)
+ {
+ for (LLVOAvatarDefines::wearables_vec_t::const_iterator type_iter = baked_dict->mWearables.begin();
+ type_iter != baked_dict->mWearables.end();
+ ++type_iter)
+ {
+ const EWearableType comp_type = *type_iter;
+ if (comp_type == type)
+ {
+ if (mBakedTextureDatas[index].mTexLayerSet)
+ {
+ invalidateComposite(mBakedTextureDatas[index].mTexLayerSet, upload_result);
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// isWearingAttachment()
+//-----------------------------------------------------------------------------
+BOOL LLVOAvatarSelf::isWearingAttachment(const LLUUID& inv_item_id) const
+{
+ const LLUUID& base_inv_item_id = gInventory.getLinkedItemID(inv_item_id);
+ for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ ++iter)
+ {
+ const LLViewerJointAttachment* attachment = iter->second;
+ if (attachment->getAttachedObject(base_inv_item_id))
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// getWornAttachment()
+//-----------------------------------------------------------------------------
+LLViewerObject* LLVOAvatarSelf::getWornAttachment(const LLUUID& inv_item_id)
+{
+ const LLUUID& base_inv_item_id = gInventory.getLinkedItemID(inv_item_id);
+ for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+ if (LLViewerObject *attached_object = attachment->getAttachedObject(base_inv_item_id))
+ {
+ return attached_object;
+ }
+ }
+ return NULL;
+}
+
+const std::string LLVOAvatarSelf::getAttachedPointName(const LLUUID& inv_item_id) const
+{
+ const LLUUID& base_inv_item_id = gInventory.getLinkedItemID(inv_item_id);
+ for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ ++iter)
+ {
+ const LLViewerJointAttachment* attachment = iter->second;
+ if (attachment->getAttachedObject(base_inv_item_id))
+ {
+ return attachment->getName();
+ }
+ }
+
+ return LLStringUtil::null;
+}
+
+//virtual
+const LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *viewer_object)
+{
+ const LLViewerJointAttachment *attachment = LLVOAvatar::attachObject(viewer_object);
+ if (!attachment)
+ {
+ return 0;
+ }
+
+ updateAttachmentVisibility(gAgent.getCameraMode());
+
+ // Then make sure the inventory is in sync with the avatar.
+
+ // Should just be the last object added
+ if (attachment->isObjectAttached(viewer_object))
+ {
+ const LLUUID& attachment_id = viewer_object->getItemID();
+ LLAppearanceManager::instance().registerAttachment(attachment_id);
+ }
+
+ return attachment;
+}
+
+//virtual
+BOOL LLVOAvatarSelf::detachObject(LLViewerObject *viewer_object)
+{
+ const LLUUID attachment_id = viewer_object->getItemID();
+ if (LLVOAvatar::detachObject(viewer_object))
+ {
+ // the simulator should automatically handle permission revocation
+
+ stopMotionFromSource(attachment_id);
+ LLFollowCamMgr::setCameraActive(viewer_object->getID(), FALSE);
+
+ LLViewerObject::const_child_list_t& child_list = viewer_object->getChildren();
+ for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
+ iter != child_list.end();
+ ++iter)
+ {
+ LLViewerObject* child_objectp = *iter;
+ // the simulator should automatically handle
+ // permissions revocation
+
+ stopMotionFromSource(child_objectp->getID());
+ LLFollowCamMgr::setCameraActive(child_objectp->getID(), FALSE);
+ }
+
+ // Make sure the inventory is in sync with the avatar.
+
+ // Update COF contents, don't trigger appearance update.
+ if (gAgent.getAvatarObject() == NULL)
+ {
+ llinfos << "removeItemLinks skipped, avatar is under destruction" << llendl;
+ }
+ else
+ {
+ LLAppearanceManager::instance().unregisterAttachment(attachment_id);
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+U32 LLVOAvatarSelf::getNumWearables(LLVOAvatarDefines::ETextureIndex i) const
+{
+ EWearableType type = LLVOAvatarDictionary::getInstance()->getTEWearableType(i);
+ return gAgentWearables.getWearableCount(type);
+}
+
+// virtual
+void LLVOAvatarSelf::localTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src_raw, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata)
+{
+ //llinfos << "onLocalTextureLoaded: " << src_vi->getID() << llendl;
+
+ const LLUUID& src_id = src_vi->getID();
+ LLAvatarTexData *data = (LLAvatarTexData *)userdata;
+ ETextureIndex index = data->mIndex;
+ if (!isIndexLocalTexture(index)) return;
+ LLLocalTextureObject *local_tex_obj = getLocalTextureObject(index, 0);
+
+ // fix for EXT-268. Preventing using of NULL pointer
+ if(NULL == local_tex_obj)
+ {
+ LL_WARNS("TAG") << "There is no Local Texture Object with index: " << index
+ << ", final: " << final
+ << LL_ENDL;
+ return;
+ }
+ if (success)
+ {
+ if (!local_tex_obj->getBakedReady() &&
+ local_tex_obj->getImage() != NULL &&
+ (local_tex_obj->getID() == src_id) &&
+ discard_level < local_tex_obj->getDiscard())
+ {
+ local_tex_obj->setDiscard(discard_level);
+ if (!gAgent.cameraCustomizeAvatar())
+ {
+ requestLayerSetUpdate(index);
+ }
+ else if (gAgent.cameraCustomizeAvatar())
+ {
+ LLVisualParamHint::requestHintUpdates();
+ }
+ updateMeshTextures();
+ }
+ }
+ else if (final)
+ {
+ // Failed: asset is missing
+ if (!local_tex_obj->getBakedReady() &&
+ local_tex_obj->getImage() != NULL &&
+ local_tex_obj->getImage()->getID() == src_id)
+ {
+ local_tex_obj->setDiscard(0);
+ requestLayerSetUpdate(index);
+ updateMeshTextures();
+ }
+ }
+}
+
+// virtual
+BOOL LLVOAvatarSelf::getLocalTextureGL(ETextureIndex type, LLViewerTexture** tex_pp, U32 index) const
+{
+ *tex_pp = NULL;
+
+ if (!isIndexLocalTexture(type)) return FALSE;
+ if (getLocalTextureID(type, index) == IMG_DEFAULT_AVATAR) return TRUE;
+
+ const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, index);
+ if (!local_tex_obj)
+ {
+ return FALSE;
+ }
+ *tex_pp = local_tex_obj->getImage();
+ return TRUE;
+}
+
+LLViewerFetchedTexture* LLVOAvatarSelf::getLocalTextureGL(LLVOAvatarDefines::ETextureIndex type, U32 index) const
+{
+ if (!isIndexLocalTexture(type))
+ {
+ return NULL;
+ }
+
+ const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, index);
+ if (!local_tex_obj)
+ {
+ return NULL;
+ }
+ if (local_tex_obj->getID() == IMG_DEFAULT_AVATAR)
+ {
+ return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR);
+ }
+ return local_tex_obj->getImage();
+}
+
+const LLUUID& LLVOAvatarSelf::getLocalTextureID(ETextureIndex type, U32 index) const
+{
+ if (!isIndexLocalTexture(type)) return IMG_DEFAULT_AVATAR;
+
+ const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, index);
+ if (local_tex_obj && local_tex_obj->getImage() != NULL)
+ {
+ return local_tex_obj->getImage()->getID();
+ }
+ return IMG_DEFAULT_AVATAR;
+}
+
+
+//-----------------------------------------------------------------------------
+// isLocalTextureDataAvailable()
+// Returns true if at least the lowest quality discard level exists for every texture
+// in the layerset.
+//-----------------------------------------------------------------------------
+BOOL LLVOAvatarSelf::isLocalTextureDataAvailable(const LLTexLayerSet* layerset) const
+{
+ /* if (layerset == mBakedTextureDatas[BAKED_HEAD].mTexLayerSet)
+ return getLocalDiscardLevel(TEX_HEAD_BODYPAINT) >= 0; */
+ for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
+ baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end();
+ ++baked_iter)
+ {
+ const EBakedTextureIndex baked_index = baked_iter->first;
+ if (layerset == mBakedTextureDatas[baked_index].mTexLayerSet)
+ {
+ BOOL ret = true;
+ const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second;
+ for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin();
+ local_tex_iter != baked_dict->mLocalTextures.end();
+ ++local_tex_iter)
+ {
+ const ETextureIndex tex_index = *local_tex_iter;
+ const EWearableType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index);
+ const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type);
+ for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++)
+ {
+ ret &= (getLocalDiscardLevel(tex_index, wearable_index) >= 0);
+ }
+ }
+ return ret;
+ }
+ }
+ llassert(0);
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// virtual
+// isLocalTextureDataFinal()
+// Returns true if the highest quality discard level exists for every texture
+// in the layerset.
+//-----------------------------------------------------------------------------
+BOOL LLVOAvatarSelf::isLocalTextureDataFinal(const LLTexLayerSet* layerset) const
+{
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
+ {
+ if (layerset == mBakedTextureDatas[i].mTexLayerSet)
+ {
+ const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i);
+ for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin();
+ local_tex_iter != baked_dict->mLocalTextures.end();
+ ++local_tex_iter)
+ {
+ const ETextureIndex tex_index = *local_tex_iter;
+ const EWearableType wearable_type = LLVOAvatarDictionary::getTEWearableType(tex_index);
+ const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type);
+ for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++)
+ {
+ if (getLocalDiscardLevel(*local_tex_iter, wearable_index) != 0)
+ {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+ }
+ }
+ llassert(0);
+ return FALSE;
+}
+
+BOOL LLVOAvatarSelf::isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index) const
+{
+ LLUUID id;
+ BOOL isDefined = TRUE;
+ if (isIndexLocalTexture(type))
+ {
+ const EWearableType wearable_type = LLVOAvatarDictionary::getTEWearableType(type);
+ const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type);
+ if (index >= wearable_count)
+ {
+ // invalid index passed in. check all textures of a given type
+ for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++)
+ {
+ id = getLocalTextureID(type, wearable_index);
+ isDefined &= (id != IMG_DEFAULT_AVATAR && id != IMG_DEFAULT);
+ }
+ }
+ else
+ {
+ id = getLocalTextureID(type, index);
+ isDefined &= (id != IMG_DEFAULT_AVATAR && id != IMG_DEFAULT);
+ }
+ }
+ else
+ {
+ id = getTEImage(type)->getID();
+ isDefined &= (id != IMG_DEFAULT_AVATAR && id != IMG_DEFAULT);
+ }
+
+ return isDefined;
+}
+
+//-----------------------------------------------------------------------------
+// virtual
+// requestLayerSetUploads()
+//-----------------------------------------------------------------------------
+void LLVOAvatarSelf::requestLayerSetUploads()
+{
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
+ {
+ ETextureIndex tex_index = mBakedTextureDatas[i].mTextureIndex;
+ BOOL layer_baked = isTextureDefined(tex_index, gAgentWearables.getWearableCount(tex_index));
+ if (!layer_baked && mBakedTextureDatas[i].mTexLayerSet)
+ {
+ mBakedTextureDatas[i].mTexLayerSet->requestUpload();
+ }
+ }
+}
+
+bool LLVOAvatarSelf::areTexturesCurrent() const
+{
+ return !hasPendingBakedUploads() && gAgentWearables.areWearablesLoaded();
+}
+
+// virtual
+bool LLVOAvatarSelf::hasPendingBakedUploads() const
+{
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
+ {
+ BOOL upload_pending = (mBakedTextureDatas[i].mTexLayerSet && mBakedTextureDatas[i].mTexLayerSet->getComposite()->uploadPending());
+ if (upload_pending)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_result )
+{
+ if( !layerset || !layerset->getUpdatesEnabled() )
+ {
+ return;
+ }
+ // llinfos << "LLVOAvatar::invalidComposite() " << layerset->getBodyRegion() << llendl;
+
+ layerset->requestUpdate();
+ layerset->invalidateMorphMasks();
+
+ if( upload_result )
+ {
+ llassert(isSelf());
+
+ ETextureIndex baked_te = getBakedTE( layerset );
+ setTEImage( baked_te, LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR) );
+ layerset->requestUpload();
+ updateMeshTextures();
+ }
+}
+
+void LLVOAvatarSelf::invalidateAll()
+{
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
+ {
+ invalidateComposite(mBakedTextureDatas[i].mTexLayerSet, TRUE);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// setCompositeUpdatesEnabled()
+//-----------------------------------------------------------------------------
+void LLVOAvatarSelf::setCompositeUpdatesEnabled( BOOL b )
+{
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
+ {
+ if (mBakedTextureDatas[i].mTexLayerSet )
+ {
+ mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled( b );
+ }
+ }
+}
+
+void LLVOAvatarSelf::setupComposites()
+{
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
+ {
+ ETextureIndex tex_index = mBakedTextureDatas[i].mTextureIndex;
+ BOOL layer_baked = isTextureDefined(tex_index, gAgentWearables.getWearableCount(tex_index));
+ if (mBakedTextureDatas[i].mTexLayerSet)
+ {
+ mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled(!layer_baked);
+ }
+ }
+}
+
+void LLVOAvatarSelf::updateComposites()
+{
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
+ {
+ if (mBakedTextureDatas[i].mTexLayerSet
+ && ((i != BAKED_SKIRT) || isWearingWearableType(WT_SKIRT)))
+ {
+ mBakedTextureDatas[i].mTexLayerSet->updateComposite();
+ }
+ }
+}
+
+// virtual
+S32 LLVOAvatarSelf::getLocalDiscardLevel(ETextureIndex type, U32 wearable_index) const
+{
+ if (!isIndexLocalTexture(type)) return FALSE;
+
+ const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, wearable_index);
+ if (local_tex_obj)
+ {
+ if (type >= 0
+ && local_tex_obj->getID() != IMG_DEFAULT_AVATAR
+ && !local_tex_obj->getImage()->isMissingAsset())
+ {
+ return local_tex_obj->getImage()->getDiscardLevel();
+ }
+ else
+ {
+ // We don't care about this (no image associated with the layer) treat as fully loaded.
+ return 0;
+ }
+ }
+ return 0;
+}
+
+// virtual
+// Counts the memory footprint of local textures.
+void LLVOAvatarSelf::getLocalTextureByteCount(S32* gl_bytes) const
+{
+ *gl_bytes = 0;
+ for (S32 type = 0; type < TEX_NUM_INDICES; type++)
+ {
+ if (!isIndexLocalTexture((ETextureIndex)type)) continue;
+ U32 max_tex = getNumWearables((ETextureIndex) type);
+ for (U32 num = 0; num < max_tex; num++)
+ {
+ const LLLocalTextureObject *local_tex_obj = getLocalTextureObject((ETextureIndex) type, num);
+ if (local_tex_obj)
+ {
+ const LLViewerFetchedTexture* image_gl = local_tex_obj->getImage();
+ if (image_gl)
+ {
+ S32 bytes = (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents();
+
+ if (image_gl->hasGLTexture())
+ {
+ *gl_bytes += bytes;
+ }
+ }
+ }
+ }
+ }
+}
+
+// virtual
+void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_tex, BOOL baked_version_ready, U32 index)
+{
+ if (!isIndexLocalTexture(type)) return;
+
+ LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(src_tex, TRUE) ;
+ if(!tex)
+ {
+ return ;
+ }
+
+ S32 desired_discard = isSelf() ? 0 : 2;
+ LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type,index);
+ if (!local_tex_obj)
+ {
+ if (type >= TEX_NUM_INDICES)
+ {
+ llerrs << "Tried to set local texture with invalid type: (" << (U32) type << ", " << index << ")" << llendl;
+ return;
+ }
+ EWearableType wearable_type = LLVOAvatarDictionary::getInstance()->getTEWearableType(type);
+ if (!gAgentWearables.getWearable(wearable_type,index))
+ {
+ // no wearable is loaded, cannot set the texture.
+ return;
+ }
+ gAgentWearables.addLocalTextureObject(wearable_type,type,index);
+ local_tex_obj = getLocalTextureObject(type,index);
+ if (!local_tex_obj)
+ {
+ llerrs << "Unable to create LocalTextureObject for wearable type & index: (" << (U32) wearable_type << ", " << index << ")" << llendl;
+ return;
+ }
+
+ LLTexLayerSet *layer_set = getLayerSet(type);
+ if (layer_set)
+ {
+ layer_set->cloneTemplates(local_tex_obj, type, gAgentWearables.getWearable(wearable_type,index));
+ }
+
+ }
+ if (!baked_version_ready)
+ {
+ if (tex != local_tex_obj->getImage() || local_tex_obj->getBakedReady())
+ {
+ local_tex_obj->setDiscard(MAX_DISCARD_LEVEL+1);
+ }
+ if (tex->getID() != IMG_DEFAULT_AVATAR)
+ {
+ if (local_tex_obj->getDiscard() > desired_discard)
+ {
+ S32 tex_discard = tex->getDiscardLevel();
+ if (tex_discard >= 0 && tex_discard <= desired_discard)
+ {
+ local_tex_obj->setDiscard(tex_discard);
+ if (isSelf() && !gAgent.cameraCustomizeAvatar())
+ {
+ requestLayerSetUpdate(type);
+ }
+ else if (isSelf() && gAgent.cameraCustomizeAvatar())
+ {
+ LLVisualParamHint::requestHintUpdates();
+ }
+ }
+ else
+ {
+ tex->setLoadedCallback(onLocalTextureLoaded, desired_discard, TRUE, FALSE, new LLAvatarTexData(getID(), type));
+ }
+ }
+ tex->setMinDiscardLevel(desired_discard);
+ }
+ }
+ local_tex_obj->setImage(tex);
+ local_tex_obj->setID(tex->getID());
+ setBakedReady(type,baked_version_ready,index);
+}
+//virtual
+void LLVOAvatarSelf::setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index)
+{
+ if (!isIndexLocalTexture(type)) return;
+ LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type,index);
+ if (local_tex_obj)
+ {
+ local_tex_obj->setBakedReady( baked_version_exists );
+ }
+}
+
+
+// virtual
+void LLVOAvatarSelf::dumpLocalTextures() const
+{
+ llinfos << "Local Textures:" << llendl;
+
+ /* ETextureIndex baked_equiv[] = {
+ TEX_UPPER_BAKED,
+ if (isTextureDefined(baked_equiv[i])) */
+ for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
+ iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
+ ++iter)
+ {
+ const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
+ if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture)
+ continue;
+
+ const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
+ const ETextureIndex baked_equiv = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex;
+
+ const std::string &name = texture_dict->mName;
+ const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(iter->first, 0);
+ // index is baked texture - index is not relevant. putting in 0 as placeholder
+ if (isTextureDefined(baked_equiv, 0))
+ {
+#if LL_RELEASE_FOR_DOWNLOAD
+ // End users don't get to trivially see avatar texture IDs, makes textures
+ // easier to steal. JC
+ llinfos << "LocTex " << name << ": Baked " << llendl;
+#else
+ llinfos << "LocTex " << name << ": Baked " << getTEImage(baked_equiv)->getID() << llendl;
+#endif
+ }
+ else if (local_tex_obj && local_tex_obj->getImage() != NULL)
+ {
+ if (local_tex_obj->getImage()->getID() == IMG_DEFAULT_AVATAR)
+ {
+ llinfos << "LocTex " << name << ": None" << llendl;
+ }
+ else
+ {
+ const LLViewerFetchedTexture* image = local_tex_obj->getImage();
+
+ llinfos << "LocTex " << name << ": "
+ << "Discard " << image->getDiscardLevel() << ", "
+ << "(" << image->getWidth() << ", " << image->getHeight() << ") "
+#if !LL_RELEASE_FOR_DOWNLOAD
+ // End users don't get to trivially see avatar texture IDs,
+ // makes textures easier to steal
+ << image->getID() << " "
+#endif
+ << "Priority: " << image->getDecodePriority()
+ << llendl;
+ }
+ }
+ else
+ {
+ llinfos << "LocTex " << name << ": No LLViewerTexture" << llendl;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// static
+// onLocalTextureLoaded()
+//-----------------------------------------------------------------------------
+
+void LLVOAvatarSelf::onLocalTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src_raw, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata)
+{
+ LLAvatarTexData *data = (LLAvatarTexData *)userdata;
+ LLVOAvatarSelf *self = (LLVOAvatarSelf *)gObjectList.findObject(data->mAvatarID);
+ if (self)
+ {
+ // We should only be handling local textures for ourself
+ self->localTextureLoaded(success, src_vi, src_raw, aux_src, discard_level, final, userdata);
+ }
+ // ensure data is cleaned up
+ if (final || !success)
+ {
+ delete data;
+ }
+}
+
+/*virtual*/ void LLVOAvatarSelf::setImage(const U8 te, LLViewerTexture *imagep, const U32 index)
+{
+ if (isIndexLocalTexture((ETextureIndex)te))
+ {
+ setLocalTexture((ETextureIndex)te, imagep, FALSE ,index);
+ }
+ else
+ {
+ setTEImage(te,imagep);
+ }
+}
+
+/*virtual*/ LLViewerTexture* LLVOAvatarSelf::getImage(const U8 te, const U32 index) const
+{
+ if (isIndexLocalTexture((ETextureIndex)te))
+ {
+ return getLocalTextureGL((ETextureIndex)te,index);
+ }
+ else
+ {
+ return getTEImage(te);
+ }
+}
+
+
+// static
+void LLVOAvatarSelf::dumpTotalLocalTextureByteCount()
+{
+ S32 gl_bytes = 0;
+ gAgent.getAvatarObject()->getLocalTextureByteCount(&gl_bytes);
+ llinfos << "Total Avatar LocTex GL:" << (gl_bytes/1024) << "KB" << llendl;
+}
+
+BOOL LLVOAvatarSelf::updateIsFullyLoaded()
+{
+ BOOL loading = FALSE;
+
+ // do we have a shape?
+ if (visualParamWeightsAreDefault())
+ {
+ loading = TRUE;
+ }
+
+ if (!isTextureDefined(TEX_HAIR, 0))
+ {
+ loading = TRUE;
+ }
+
+ if (!mPreviousFullyLoaded)
+ {
+ if (!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_LOWER].mTexLayerSet) &&
+ (!isTextureDefined(TEX_LOWER_BAKED, 0)))
+ {
+ loading = TRUE;
+ }
+
+ if (!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_UPPER].mTexLayerSet) &&
+ (!isTextureDefined(TEX_UPPER_BAKED, 0)))
+ {
+ loading = TRUE;
+ }
+
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
+ {
+ if (i == BAKED_SKIRT && !isWearingWearableType(WT_SKIRT))
+ continue;
+
+ BakedTextureData& texture_data = mBakedTextureDatas[i];
+ if (!isTextureDefined(texture_data.mTextureIndex, 0))
+ continue;
+
+ // Check for the case that texture is defined but not sufficiently loaded to display anything.
+ LLViewerTexture* baked_img = getImage( texture_data.mTextureIndex, 0 );
+ if (!baked_img || !baked_img->hasGLTexture())
+ {
+ loading = TRUE;
+ }
+
+ }
+
+ }
+ return processFullyLoadedChange(loading);
+}
+
+const LLUUID& LLVOAvatarSelf::grabLocalTexture(ETextureIndex type, U32 index) const
+{
+ if (canGrabLocalTexture(type, index))
+ {
+ return getTEImage( type )->getID();
+ }
+ return LLUUID::null;
+}
+
+BOOL LLVOAvatarSelf::canGrabLocalTexture(ETextureIndex type, U32 index) const
+{
+ // Check if the texture hasn't been baked yet.
+ if (!isTextureDefined(type, index))
+ {
+ lldebugs << "getTEImage( " << (U32) type << ", " << index << " )->getID() == IMG_DEFAULT_AVATAR" << llendl;
+ return FALSE;
+ }
+
+ if (gAgent.isGodlike())
+ return TRUE;
+
+ // Check permissions of textures that show up in the
+ // baked texture. We don't want people copying people's
+ // work via baked textures.
+ /* switch(type)
+ case TEX_EYES_BAKED:
+ textures.push_back(TEX_EYES_IRIS); */
+ const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(type);
+ if (!texture_dict->mIsUsedByBakedTexture) return FALSE;
+
+ const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
+ const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index);
+ for (texture_vec_t::const_iterator iter = baked_dict->mLocalTextures.begin();
+ iter != baked_dict->mLocalTextures.end();
+ ++iter)
+ {
+ const ETextureIndex t_index = (*iter);
+ lldebugs << "Checking index " << (U32) t_index << llendl;
+ // MULTI-WEARABLE: old method. replace.
+ const LLUUID& texture_id = getTEImage( t_index )->getID();
+ if (texture_id != IMG_DEFAULT_AVATAR)
+ {
+ // Search inventory for this texture.
+ LLViewerInventoryCategory::cat_array_t cats;
+ LLViewerInventoryItem::item_array_t items;
+ LLAssetIDMatches asset_id_matches(texture_id);
+ gInventory.collectDescendentsIf(LLUUID::null,
+ cats,
+ items,
+ LLInventoryModel::INCLUDE_TRASH,
+ asset_id_matches);
+
+ BOOL can_grab = FALSE;
+ lldebugs << "item count for asset " << texture_id << ": " << items.count() << llendl;
+ if (items.count())
+ {
+ // search for full permissions version
+ for (S32 i = 0; i < items.count(); i++)
+ {
+ LLInventoryItem* itemp = items[i];
+ LLPermissions item_permissions = itemp->getPermissions();
+ if ( item_permissions.allowOperationBy(
+ PERM_MODIFY, gAgent.getID(), gAgent.getGroupID()) &&
+ item_permissions.allowOperationBy(
+ PERM_COPY, gAgent.getID(), gAgent.getGroupID()) &&
+ item_permissions.allowOperationBy(
+ PERM_TRANSFER, gAgent.getID(), gAgent.getGroupID()) )
+ {
+ can_grab = TRUE;
+ break;
+ }
+ }
+ }
+ if (!can_grab) return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTexture* imagep,
+ F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked, U32 index )
+{
+ if (!isIndexLocalTexture(type)) return;
+
+ if (!covered_by_baked)
+ {
+ if (getLocalTextureID(type, index) != IMG_DEFAULT_AVATAR && imagep->getDiscardLevel() != 0)
+ {
+ F32 desired_pixels;
+ desired_pixels = llmin(mPixelArea, (F32)getTexImageArea());
+ imagep->setBoostLevel(getAvatarBoostLevel());
+ imagep->addTextureStats( desired_pixels / texel_area_ratio );
+ imagep->forceUpdateBindStats() ;
+ if (imagep->getDiscardLevel() < 0)
+ {
+ mHasGrey = TRUE; // for statistics gathering
+ }
+ }
+ else
+ {
+ // texture asset is missing
+ mHasGrey = TRUE; // for statistics gathering
+ }
+ }
+}
+
+LLLocalTextureObject* LLVOAvatarSelf::getLocalTextureObject(LLVOAvatarDefines::ETextureIndex i, U32 wearable_index) const
+{
+ EWearableType type = LLVOAvatarDictionary::getInstance()->getTEWearableType(i);
+ LLWearable* wearable = gAgentWearables.getWearable(type, wearable_index);
+ if (wearable)
+ {
+ return wearable->getLocalTextureObject(i);
+ }
+
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// getBakedTE()
+// Used by the LayerSet. (Layer sets don't in general know what textures depend on them.)
+//-----------------------------------------------------------------------------
+ETextureIndex LLVOAvatarSelf::getBakedTE( const LLTexLayerSet* layerset ) const
+{
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
+ {
+ if (layerset == mBakedTextureDatas[i].mTexLayerSet )
+ {
+ return mBakedTextureDatas[i].mTextureIndex;
+ }
+ }
+ llassert(0);
+ return TEX_HEAD_BAKED;
+}
+
+
+void LLVOAvatarSelf::setNewBakedTexture(LLVOAvatarDefines::EBakedTextureIndex i, const LLUUID &uuid)
+{
+ ETextureIndex index = LLVOAvatarDictionary::bakedToLocalTextureIndex(i);
+ setNewBakedTexture(index, uuid);
+}
+
+
+//-----------------------------------------------------------------------------
+// setNewBakedTexture()
+// A new baked texture has been successfully uploaded and we can start using it now.
+//-----------------------------------------------------------------------------
+void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid )
+{
+ // Baked textures live on other sims.
+ LLHost target_host = getObjectHost();
+ setTEImage( te, LLViewerTextureManager::getFetchedTextureFromHost( uuid, target_host ) );
+ updateMeshTextures();
+ dirtyMesh();
+
+ LLVOAvatar::cullAvatarsByPixelArea();
+
+ /* switch(te)
+ case TEX_HEAD_BAKED:
+ llinfos << "New baked texture: HEAD" << llendl; */
+ const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(te);
+ if (texture_dict->mIsBakedTexture)
+ {
+ llinfos << "New baked texture: " << texture_dict->mName << " UUID: " << uuid <<llendl;
+ }
+ else
+ {
+ llwarns << "New baked texture: unknown te " << te << llendl;
+ }
+
+ // dumpAvatarTEs( "setNewBakedTexture() send" );
+ // RN: throttle uploads
+ if (!hasPendingBakedUploads())
+ {
+ gAgent.sendAgentSetAppearance();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// setCachedBakedTexture()
+// A baked texture id was received from a cache query, make it active
+//-----------------------------------------------------------------------------
+void LLVOAvatarSelf::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid )
+{
+ setTETexture( te, uuid );
+
+ /* switch(te)
+ case TEX_HEAD_BAKED:
+ if( mHeadLayerSet )
+ mHeadLayerSet->cancelUpload(); */
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
+ {
+ if ( mBakedTextureDatas[i].mTextureIndex == te && mBakedTextureDatas[i].mTexLayerSet)
+ {
+ mBakedTextureDatas[i].mTexLayerSet->cancelUpload();
+ }
+ }
+}
+
+// static
+void LLVOAvatarSelf::processRebakeAvatarTextures(LLMessageSystem* msg, void**)
+{
+ LLUUID texture_id;
+ msg->getUUID("TextureData", "TextureID", texture_id);
+
+ LLVOAvatarSelf* self = gAgent.getAvatarObject();
+ if (!self) return;
+
+ // If this is a texture corresponding to one of our baked entries,
+ // just rebake that layer set.
+ BOOL found = FALSE;
+
+ /* ETextureIndex baked_texture_indices[BAKED_NUM_INDICES] =
+ TEX_HEAD_BAKED,
+ TEX_UPPER_BAKED, */
+ for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
+ iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
+ ++iter)
+ {
+ const ETextureIndex index = iter->first;
+ const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
+ if (texture_dict->mIsBakedTexture)
+ {
+ if (texture_id == self->getTEImage(index)->getID())
+ {
+ LLTexLayerSet* layer_set = self->getLayerSet(index);
+ if (layer_set)
+ {
+ llinfos << "TAT: rebake - matched entry " << (S32)index << llendl;
+ self->invalidateComposite(layer_set, TRUE);
+ found = TRUE;
+ LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_REBAKES);
+ }
+ }
+ }
+ }
+
+ // If texture not found, rebake all entries.
+ if (!found)
+ {
+ self->forceBakeAllTextures();
+ }
+ else
+ {
+ // Not sure if this is necessary, but forceBakeAllTextures() does it.
+ self->updateMeshTextures();
+ }
+}
+
+void LLVOAvatarSelf::forceBakeAllTextures(bool slam_for_debug)
+{
+ llinfos << "TAT: forced full rebake. " << llendl;
+
+ for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
+ {
+ ETextureIndex baked_index = mBakedTextureDatas[i].mTextureIndex;
+ LLTexLayerSet* layer_set = getLayerSet(baked_index);
+ if (layer_set)
+ {
+ if (slam_for_debug)
+ {
+ layer_set->setUpdatesEnabled(TRUE);
+ layer_set->cancelUpload();
+ }
+
+ invalidateComposite(layer_set, TRUE);
+ LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_REBAKES);
+ }
+ else
+ {
+ llwarns << "TAT: NO LAYER SET FOR " << (S32)baked_index << llendl;
+ }
+ }
+
+ // Don't know if this is needed
+ updateMeshTextures();
+}
+
+//-----------------------------------------------------------------------------
+// requestLayerSetUpdate()
+//-----------------------------------------------------------------------------
+void LLVOAvatarSelf::requestLayerSetUpdate(ETextureIndex index )
+{
+ /* switch(index)
+ case LOCTEX_UPPER_BODYPAINT:
+ case LOCTEX_UPPER_SHIRT:
+ if( mUpperBodyLayerSet )
+ mUpperBodyLayerSet->requestUpdate(); */
+ const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(index);
+ if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture)
+ return;
+ const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
+ if (mBakedTextureDatas[baked_index].mTexLayerSet)
+ {
+ mBakedTextureDatas[baked_index].mTexLayerSet->requestUpdate();
+ }
+}
+
+LLTexLayerSet* LLVOAvatarSelf::getLayerSet(ETextureIndex index) const
+{
+ /* switch(index)
+ case TEX_HEAD_BAKED:
+ case TEX_HEAD_BODYPAINT:
+ return mHeadLayerSet; */
+ const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(index);
+ if (texture_dict->mIsUsedByBakedTexture)
+ {
+ const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
+ return mBakedTextureDatas[baked_index].mTexLayerSet;
+ }
+ return NULL;
+}
+
+// static
+void LLVOAvatarSelf::onCustomizeStart()
+{
+ // We're no longer doing any baking or invalidating on entering
+ // appearance editing mode. Leaving function in place in case
+ // further changes require us to do something at this point - Nyx
+}
+
+// static
+void LLVOAvatarSelf::onCustomizeEnd()
+{
+ LLVOAvatarSelf *avatarp = gAgent.getAvatarObject();
+ if (avatarp)
+ {
+ avatarp->invalidateAll();
+ }
+}
+
+// HACK: this will null out the avatar's local texture IDs before the TE message is sent
+// to ensure local texture IDs are not sent to other clients in the area.
+// this is a short-term solution. The long term solution will be to not set the texture
+// IDs in the avatar object, and keep them only in the wearable.
+// This will involve further refactoring that is too risky for the initial release of 2.0.
+bool LLVOAvatarSelf::sendAppearanceMessage(LLMessageSystem *mesgsys) const
+{
+ LLUUID texture_id[TEX_NUM_INDICES];
+ // pack away current TEs to make sure we don't send them out
+ for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
+ iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
+ ++iter)
+ {
+ const ETextureIndex index = iter->first;
+ const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
+ if (!texture_dict->mIsBakedTexture)
+ {
+ LLTextureEntry* entry = getTE((U8) index);
+ texture_id[index] = entry->getID();
+ entry->setID(IMG_DEFAULT_AVATAR);
+ }
+ }
+
+ bool success = packTEMessage(mesgsys);
+
+ // unpack TEs to make sure we don't re-trigger a bake
+ for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
+ iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
+ ++iter)
+ {
+ const ETextureIndex index = iter->first;
+ const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
+ if (!texture_dict->mIsBakedTexture)
+ {
+ LLTextureEntry* entry = getTE((U8) index);
+ entry->setID(texture_id[index]);
+ }
+ }
+
+ return success;
+}
+
+
+//------------------------------------------------------------------------
+// needsRenderBeam()
+//------------------------------------------------------------------------
+BOOL LLVOAvatarSelf::needsRenderBeam()
+{
+ if (gNoRender)
+ {
+ return FALSE;
+ }
+ LLTool *tool = LLToolMgr::getInstance()->getCurrentTool();
+
+ BOOL is_touching_or_grabbing = (tool == LLToolGrab::getInstance() && LLToolGrab::getInstance()->isEditing());
+ if (LLToolGrab::getInstance()->getEditingObject() &&
+ LLToolGrab::getInstance()->getEditingObject()->isAttachment())
+ {
+ // don't render selection beam on hud objects
+ is_touching_or_grabbing = FALSE;
+ }
+ return is_touching_or_grabbing || (mState & AGENT_STATE_EDITING && LLSelectMgr::getInstance()->shouldShowSelection());
+}
+
+// static
+void LLVOAvatarSelf::deleteScratchTextures()
+{
+ if(gAuditTexture)
+ {
+ S32 total_tex_size = sScratchTexBytes ;
+ S32 tex_size = SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT ;
+
+ if( sScratchTexNames.checkData( GL_LUMINANCE ) )
+ {
+ LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
+ total_tex_size -= tex_size ;
+ }
+ if( sScratchTexNames.checkData( GL_ALPHA ) )
+ {
+ LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
+ total_tex_size -= tex_size ;
+ }
+ if( sScratchTexNames.checkData( GL_COLOR_INDEX ) )
+ {
+ LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
+ total_tex_size -= tex_size ;
+ }
+ if( sScratchTexNames.checkData( GL_LUMINANCE_ALPHA ) )
+ {
+ LLImageGL::decTextureCounter(tex_size, 2, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
+ total_tex_size -= 2 * tex_size ;
+ }
+ if( sScratchTexNames.checkData( GL_RGB ) )
+ {
+ LLImageGL::decTextureCounter(tex_size, 3, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
+ total_tex_size -= 3 * tex_size ;
+ }
+ if( sScratchTexNames.checkData( GL_RGBA ) )
+ {
+ LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
+ total_tex_size -= 4 * tex_size ;
+ }
+ //others
+ while(total_tex_size > 0)
+ {
+ LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
+ total_tex_size -= 4 * tex_size ;
+ }
+ }
+
+ for( LLGLuint* namep = sScratchTexNames.getFirstData();
+ namep;
+ namep = sScratchTexNames.getNextData() )
+ {
+ LLImageGL::deleteTextures(1, (U32 *)namep );
+ stop_glerror();
+ }
+
+ if( sScratchTexBytes )
+ {
+ lldebugs << "Clearing Scratch Textures " << (sScratchTexBytes/1024) << "KB" << llendl;
+
+ sScratchTexNames.deleteAllData();
+ sScratchTexLastBindTime.deleteAllData();
+ LLImageGL::sGlobalTextureMemoryInBytes -= sScratchTexBytes;
+ sScratchTexBytes = 0;
+ }
+}
+
+BOOL LLVOAvatarSelf::bindScratchTexture( LLGLenum format )
+{
+ U32 texture_bytes = 0;
+ S32 components = 0;
+ GLuint gl_name = getScratchTexName( format, components, &texture_bytes );
+ if( gl_name )
+ {
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, gl_name);
+ stop_glerror();
+
+ F32* last_bind_time = sScratchTexLastBindTime.getIfThere( format );
+ if( last_bind_time )
+ {
+ if( *last_bind_time != LLImageGL::sLastFrameTime )
+ {
+ *last_bind_time = LLImageGL::sLastFrameTime;
+ LLImageGL::updateBoundTexMem(texture_bytes, components, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
+ }
+ }
+ else
+ {
+ LLImageGL::updateBoundTexMem(texture_bytes, components, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
+ sScratchTexLastBindTime.addData( format, new F32(LLImageGL::sLastFrameTime) );
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+LLGLuint LLVOAvatarSelf::getScratchTexName( LLGLenum format, S32& components, U32* texture_bytes )
+{
+ GLenum internal_format;
+ switch( format )
+ {
+ case GL_LUMINANCE: components = 1; internal_format = GL_LUMINANCE8; break;
+ case GL_ALPHA: components = 1; internal_format = GL_ALPHA8; break;
+ case GL_COLOR_INDEX: components = 1; internal_format = GL_COLOR_INDEX8_EXT; break;
+ case GL_LUMINANCE_ALPHA: components = 2; internal_format = GL_LUMINANCE8_ALPHA8; break;
+ case GL_RGB: components = 3; internal_format = GL_RGB8; break;
+ case GL_RGBA: components = 4; internal_format = GL_RGBA8; break;
+ default: llassert(0); components = 4; internal_format = GL_RGBA8; break;
+ }
+
+ *texture_bytes = components * SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT;
+
+ if( sScratchTexNames.checkData( format ) )
+ {
+ return *( sScratchTexNames.getData( format ) );
+ }
+
+ LLGLSUIDefault gls_ui;
+
+ U32 name = 0;
+ LLImageGL::generateTextures(1, &name );
+ stop_glerror();
+
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, name);
+ stop_glerror();
+
+ LLImageGL::setManualImage(
+ GL_TEXTURE_2D, 0, internal_format,
+ SCRATCH_TEX_WIDTH, SCRATCH_TEX_HEIGHT,
+ format, GL_UNSIGNED_BYTE, NULL );
+ stop_glerror();
+
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+ stop_glerror();
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ stop_glerror();
+
+ sScratchTexNames.addData( format, new LLGLuint( name ) );
+
+ sScratchTexBytes += *texture_bytes;
+ LLImageGL::sGlobalTextureMemoryInBytes += *texture_bytes;
+
+ if(gAuditTexture)
+ {
+ LLImageGL::incTextureCounter(SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT, components, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
+ }
+ return name;
+}
+
+// static
+void LLVOAvatarSelf::dumpScratchTextureByteCount()
+{
+ llinfos << "Scratch Texture GL: " << (sScratchTexBytes/1024) << "KB" << llendl;
+}
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
new file mode 100644
index 0000000000..dc70996f0b
--- /dev/null
+++ b/indra/newview/llvoavatarself.h
@@ -0,0 +1,333 @@
+/**
+ * @file llvoavatarself.h
+ * @brief Declaration of LLVOAvatar class which is a derivation fo
+ * LLViewerObject
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLVOAVATARSELF_H
+#define LL_LLVOAVATARSELF_H
+
+#include "llviewertexture.h"
+#include "llvoavatar.h"
+
+struct LocalTextureData;
+
+//------------------------------------------------------------------------
+// LLVOAvatarSelf
+//------------------------------------------------------------------------
+class LLVOAvatarSelf :
+ public LLVOAvatar
+{
+
+/********************************************************************************
+ ** **
+ ** INITIALIZATION
+ **/
+
+public:
+ LLVOAvatarSelf(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
+ virtual ~LLVOAvatarSelf();
+ virtual void markDead();
+ virtual void initInstance(); // Called after construction to initialize the class.
+protected:
+ /*virtual*/ BOOL loadAvatar();
+ BOOL loadAvatarSelf();
+ BOOL buildSkeletonSelf(const LLVOAvatarSkeletonInfo *info);
+ BOOL buildMenus();
+ /*virtual*/ BOOL loadLayersets();
+
+/** Initialization
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** INHERITED
+ **/
+
+ //--------------------------------------------------------------------
+ // LLViewerObject interface and related
+ //--------------------------------------------------------------------
+public:
+ /*virtual*/ void updateRegion(LLViewerRegion *regionp);
+
+ //--------------------------------------------------------------------
+ // LLCharacter interface and related
+ //--------------------------------------------------------------------
+public:
+ /*virtual*/ void stopMotionFromSource(const LLUUID& source_id);
+ /*virtual*/ void requestStopMotion(LLMotion* motion);
+ /*virtual*/ LLJoint* getJoint(const std::string &name);
+
+ /*virtual*/ BOOL setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL upload_bake = FALSE );
+ /*virtual*/ BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake = FALSE );
+ /*virtual*/ BOOL setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake = FALSE );
+ /*virtual*/ void updateVisualParams();
+ /*virtual*/ void idleUpdateAppearanceAnimation();
+
+private:
+ // helper function. Passed in param is assumed to be in avatar's parameter list.
+ BOOL setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL upload_bake = FALSE );
+
+
+/** Initialization
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** STATE
+ **/
+
+public:
+ /*virtual*/ bool isSelf() const { return true; }
+
+ //--------------------------------------------------------------------
+ // Updates
+ //--------------------------------------------------------------------
+public:
+ /*virtual*/ BOOL updateCharacter(LLAgent &agent);
+ /*virtual*/ void idleUpdateTractorBeam();
+
+ //--------------------------------------------------------------------
+ // Loading state
+ //--------------------------------------------------------------------
+public:
+ /*virtual*/ BOOL updateIsFullyLoaded();
+private:
+ BOOL mIsBaked; // are the stored baked textures up to date?
+
+ //--------------------------------------------------------------------
+ // Region state
+ //--------------------------------------------------------------------
+private:
+ U64 mLastRegionHandle;
+ LLFrameTimer mRegionCrossingTimer;
+ S32 mRegionCrossingCount;
+
+/** State
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** RENDERING
+ **/
+
+ //--------------------------------------------------------------------
+ // Render beam
+ //--------------------------------------------------------------------
+protected:
+ BOOL needsRenderBeam();
+private:
+ LLPointer<LLHUDEffectSpiral> mBeam;
+ LLFrameTimer mBeamTimer;
+
+ //--------------------------------------------------------------------
+ // LLVOAvatar Constants
+ //--------------------------------------------------------------------
+public:
+ /*virtual*/ LLViewerTexture::EBoostLevel getAvatarBoostLevel() const { return LLViewerTexture::BOOST_AVATAR_SELF; }
+ /*virtual*/ LLViewerTexture::EBoostLevel getAvatarBakedBoostLevel() const { return LLViewerTexture::BOOST_AVATAR_BAKED_SELF; }
+ /*virtual*/ S32 getTexImageSize() const { return LLVOAvatar::getTexImageSize()*4; }
+
+/** Rendering
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** TEXTURES
+ **/
+
+ //--------------------------------------------------------------------
+ // Loading status
+ //--------------------------------------------------------------------
+public:
+ /*virtual*/ bool hasPendingBakedUploads() const;
+ S32 getLocalDiscardLevel(LLVOAvatarDefines::ETextureIndex type, U32 index) const;
+ bool areTexturesCurrent() const;
+ BOOL isLocalTextureDataAvailable(const LLTexLayerSet* layerset) const;
+ BOOL isLocalTextureDataFinal(const LLTexLayerSet* layerset) const;
+ // If you want to check all textures of a given type, pass gAgentWearables.getWearableCount() for index
+ /*virtual*/ BOOL isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index) const;
+
+ //--------------------------------------------------------------------
+ // Local Textures
+ //--------------------------------------------------------------------
+public:
+ BOOL getLocalTextureGL(LLVOAvatarDefines::ETextureIndex type, LLViewerTexture** image_gl_pp, U32 index) const;
+ LLViewerFetchedTexture* getLocalTextureGL(LLVOAvatarDefines::ETextureIndex type, U32 index) const;
+ const LLUUID& getLocalTextureID(LLVOAvatarDefines::ETextureIndex type, U32 index) const;
+ void setLocalTextureTE(U8 te, LLViewerTexture* image, U32 index);
+ const LLUUID& grabLocalTexture(LLVOAvatarDefines::ETextureIndex type, U32 index) const;
+ BOOL canGrabLocalTexture(LLVOAvatarDefines::ETextureIndex type, U32 index) const;
+ /*virtual*/ void setLocalTexture(LLVOAvatarDefines::ETextureIndex type, LLViewerTexture* tex, BOOL baked_version_exits, U32 index);
+protected:
+ /*virtual*/ void setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index);
+ void localTextureLoaded(BOOL succcess, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata);
+ void getLocalTextureByteCount(S32* gl_byte_count) const;
+ /*virtual*/ void addLocalTextureStats(LLVOAvatarDefines::ETextureIndex i, LLViewerFetchedTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked, U32 index);
+ LLLocalTextureObject* getLocalTextureObject(LLVOAvatarDefines::ETextureIndex i, U32 index) const;
+
+private:
+ static void onLocalTextureLoaded(BOOL succcess, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata);
+
+ /*virtual*/ void setImage(const U8 te, LLViewerTexture *imagep, const U32 index);
+ /*virtual*/ LLViewerTexture* getImage(const U8 te, const U32 index) const;
+
+
+ //--------------------------------------------------------------------
+ // Baked textures
+ //--------------------------------------------------------------------
+public:
+ LLVOAvatarDefines::ETextureIndex getBakedTE(const LLTexLayerSet* layerset ) const;
+ void setNewBakedTexture(LLVOAvatarDefines::EBakedTextureIndex i, const LLUUID &uuid);
+ void setNewBakedTexture(LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid);
+ void setCachedBakedTexture(LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid);
+ void forceBakeAllTextures(bool slam_for_debug = false);
+ static void processRebakeAvatarTextures(LLMessageSystem* msg, void**);
+protected:
+ /*virtual*/ void removeMissingBakedTextures();
+
+ //--------------------------------------------------------------------
+ // Layers
+ //--------------------------------------------------------------------
+public:
+ void requestLayerSetUploads();
+ void requestLayerSetUpdate(LLVOAvatarDefines::ETextureIndex i);
+ LLTexLayerSet* getLayerSet(LLVOAvatarDefines::ETextureIndex index) const;
+
+ //--------------------------------------------------------------------
+ // Composites
+ //--------------------------------------------------------------------
+public:
+ /* virtual */ void invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result);
+ /* virtual */ void invalidateAll();
+ /* virtual */ void setCompositeUpdatesEnabled(BOOL b); // only works for self
+ void setupComposites();
+ void updateComposites();
+
+ //--------------------------------------------------------------------
+ // Scratch textures (used for compositing)
+ //--------------------------------------------------------------------
+public:
+ BOOL bindScratchTexture(LLGLenum format);
+ static void deleteScratchTextures();
+protected:
+ LLGLuint getScratchTexName(LLGLenum format, S32& components, U32* texture_bytes);
+private:
+ static S32 sScratchTexBytes;
+ static LLMap< LLGLenum, LLGLuint*> sScratchTexNames;
+ static LLMap< LLGLenum, F32*> sScratchTexLastBindTime;
+
+/** Textures
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** MESHES
+ **/
+protected:
+ /*virtual*/ void restoreMeshData();
+
+/** Meshes
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** WEARABLES
+ **/
+
+public:
+ /*virtual*/ BOOL isWearingWearableType(EWearableType type) const;
+ void wearableUpdated(EWearableType type, BOOL upload_result);
+protected:
+ U32 getNumWearables(LLVOAvatarDefines::ETextureIndex i) const;
+
+ //--------------------------------------------------------------------
+ // Attachments
+ //--------------------------------------------------------------------
+public:
+ void updateAttachmentVisibility(U32 camera_mode);
+ BOOL isWearingAttachment(const LLUUID& inv_item_id) const;
+ LLViewerObject* getWornAttachment(const LLUUID& inv_item_id);
+ const std::string getAttachedPointName(const LLUUID& inv_item_id) const;
+ /*virtual*/ const LLViewerJointAttachment *attachObject(LLViewerObject *viewer_object);
+ /*virtual*/ BOOL detachObject(LLViewerObject *viewer_object);
+
+ //--------------------------------------------------------------------
+ // HUDs
+ //--------------------------------------------------------------------
+private:
+ LLViewerJoint* mScreenp; // special purpose joint for HUD attachments
+
+/** Attachments
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** APPEARANCE
+ **/
+
+public:
+ static void onCustomizeStart();
+ static void onCustomizeEnd();
+
+ //--------------------------------------------------------------------
+ // Visibility
+ //--------------------------------------------------------------------
+public:
+ bool sendAppearanceMessage(LLMessageSystem *mesgsys) const;
+
+/** Appearance
+ ** **
+ *******************************************************************************/
+
+/********************************************************************************
+ ** **
+ ** DIAGNOSTICS
+ **/
+
+public:
+ static void dumpTotalLocalTextureByteCount();
+ void dumpLocalTextures() const;
+ static void dumpScratchTextureByteCount();
+
+/** Diagnostics
+ ** **
+ *******************************************************************************/
+
+};
+
+#endif // LL_VO_AVATARSELF_H
diff --git a/indra/newview/llvoclouds.cpp b/indra/newview/llvoclouds.cpp
index 9095ee43c8..177cb16c50 100644
--- a/indra/newview/llvoclouds.cpp
+++ b/indra/newview/llvoclouds.cpp
@@ -44,7 +44,7 @@
#include "llprimitive.h"
#include "llsky.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "llvosky.h"
@@ -61,8 +61,8 @@ LLVOClouds::LLVOClouds(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re
mCloudGroupp = NULL;
mbCanSelect = FALSE;
setNumTEs(1);
- LLViewerImage* image = gImageList.getImage(gCloudTextureID);
- image->setBoostLevel(LLViewerImage::BOOST_CLOUDS);
+ LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(gCloudTextureID);
+ image->setBoostLevel(LLViewerTexture::BOOST_CLOUDS);
setTEImage(0, image);
}
@@ -101,7 +101,7 @@ void LLVOClouds::setPixelAreaAndAngle(LLAgent &agent)
mPixelArea = 1500*100;
}
-void LLVOClouds::updateTextures(LLAgent &agent)
+void LLVOClouds::updateTextures()
{
getTEImage(0)->addTextureStats(mPixelArea);
}
@@ -115,15 +115,20 @@ LLDrawable* LLVOClouds::createDrawable(LLPipeline *pipeline)
return mDrawable;
}
+static LLFastTimer::DeclareTimer FTM_UPDATE_CLOUDS("Update Clouds");
+
BOOL LLVOClouds::updateGeometry(LLDrawable *drawable)
{
- LLFastTimer ftm(LLFastTimer::FTM_UPDATE_CLOUDS);
+ LLFastTimer ftm(FTM_UPDATE_CLOUDS);
if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS)))
{
return TRUE;
}
- dirtySpatialGroup();
+ if (drawable->isVisible())
+ {
+ dirtySpatialGroup(TRUE);
+ }
LLFace *facep;
diff --git a/indra/newview/llvoclouds.h b/indra/newview/llvoclouds.h
index f70ea5b9e7..c4a75f5b5e 100644
--- a/indra/newview/llvoclouds.h
+++ b/indra/newview/llvoclouds.h
@@ -37,7 +37,7 @@
#include "lltable.h"
#include "v4coloru.h"
-class LLViewerImage;
+class LLViewerTexture;
class LLViewerCloudGroup;
class LLCloudGroup;
@@ -65,7 +65,7 @@ public:
/*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate.
F32 getPartSize(S32 idx);
- /*virtual*/ void updateTextures(LLAgent &agent);
+ /*virtual*/ void updateTextures();
/*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area
void updateFaceSize(S32 idx) { }
diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp
index fe4a2fdc76..e311f07912 100644
--- a/indra/newview/llvograss.cpp
+++ b/indra/newview/llvograss.cpp
@@ -38,7 +38,7 @@
#include "llviewercontrol.h"
#include "llagent.h"
-#include "llviewerwindow.h"
+#include "llnotificationsutil.h"
#include "lldrawable.h"
#include "llface.h"
#include "llsky.h"
@@ -46,7 +46,7 @@
#include "llsurfacepatch.h"
#include "llvosky.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewerregion.h"
#include "pipeline.h"
#include "llspatialpartition.h"
@@ -106,7 +106,7 @@ void LLVOGrass::updateSpecies()
SpeciesMap::const_iterator it = sSpeciesTable.begin();
mSpecies = (*it).first;
}
- setTEImage(0, gImageList.getImage(sSpeciesTable[mSpecies]->mTextureID));
+ setTEImage(0, LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
}
@@ -165,16 +165,6 @@ void LLVOGrass::initClass()
grass_def->getFastAttributeUUID(texture_id_string, id);
newGrass->mTextureID = id;
- if (newGrass->mTextureID.isNull())
- {
- std::string textureName;
-
- static LLStdStringHandle texture_name_string = LLXmlTree::addAttributeString("texture_name");
- success &= grass_def->getFastAttributeString(texture_name_string, textureName);
- LLViewerImage* grass_image = gImageList.getImageFromFile(textureName);
- newGrass->mTextureID = grass_image->getID();
- }
-
static LLStdStringHandle blade_sizex_string = LLXmlTree::addAttributeString("blade_size_x");
success &= grass_def->getFastAttributeF32(blade_sizex_string, F32_val);
newGrass->mBladeSizeX = F32_val;
@@ -221,7 +211,7 @@ void LLVOGrass::initClass()
{
LLSD args;
args["SPECIES"] = err;
- LLNotifications::instance().add("ErrorUndefinedGrasses", args);
+ LLNotificationsUtil::add("ErrorUndefinedGrasses", args);
}
for (S32 i = 0; i < GRASS_MAX_BLADES; ++i)
@@ -332,7 +322,7 @@ void LLVOGrass::setPixelAreaAndAngle(LLAgent &agent)
// BUG could speed this up by caching the relative_position and range calculations
-void LLVOGrass::updateTextures(LLAgent &agent)
+void LLVOGrass::updateTextures()
{
if (getTEImage(0))
{
@@ -392,9 +382,11 @@ LLDrawable* LLVOGrass::createDrawable(LLPipeline *pipeline)
return mDrawable;
}
+static LLFastTimer::DeclareTimer FTM_UPDATE_GRASS("Update Grass");
+
BOOL LLVOGrass::updateGeometry(LLDrawable *drawable)
{
- LLFastTimer ftm(LLFastTimer::FTM_UPDATE_GRASS);
+ LLFastTimer ftm(FTM_UPDATE_GRASS);
dirtySpatialGroup();
plantBlades();
return TRUE;
diff --git a/indra/newview/llvograss.h b/indra/newview/llvograss.h
index 11b79d519c..6a6fcc31c3 100644
--- a/indra/newview/llvograss.h
+++ b/indra/newview/llvograss.h
@@ -38,7 +38,7 @@
#include <map>
class LLSurfacePatch;
-class LLViewerImage;
+class LLViewerTexture;
class LLVOGrass : public LLAlphaObject
@@ -72,7 +72,7 @@ public:
LLStrider<U16>& indicesp);
void updateFaceSize(S32 idx) { }
- /*virtual*/ void updateTextures(LLAgent &agent);
+ /*virtual*/ void updateTextures();
/*virtual*/ BOOL updateLOD();
/*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area
diff --git a/indra/newview/llvoground.cpp b/indra/newview/llvoground.cpp
index fe19e18151..221c6b61ec 100644
--- a/indra/newview/llvoground.cpp
+++ b/indra/newview/llvoground.cpp
@@ -37,7 +37,6 @@
#include "llviewercontrol.h"
-#include "llagent.h"
#include "lldrawable.h"
#include "llface.h"
#include "llsky.h"
@@ -71,7 +70,7 @@ BOOL LLVOGround::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
}
-void LLVOGround::updateTextures(LLAgent &agent)
+void LLVOGround::updateTextures()
{
}
diff --git a/indra/newview/llvoground.h b/indra/newview/llvoground.h
index f485bd0aa4..0ccb0834a2 100644
--- a/indra/newview/llvoground.h
+++ b/indra/newview/llvoground.h
@@ -36,7 +36,7 @@
#include "stdtypes.h"
#include "v3color.h"
#include "v4coloru.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
#include "llviewerobject.h"
class LLVOGround : public LLStaticViewerObject
@@ -51,7 +51,7 @@ public:
// Graphical stuff for objects - maybe broken out into render class
// later?
- /*virtual*/ void updateTextures(LLAgent &agent);
+ /*virtual*/ void updateTextures();
/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp
new file mode 100644
index 0000000000..917d69fe16
--- /dev/null
+++ b/indra/newview/llvoicechannel.cpp
@@ -0,0 +1,907 @@
+/**
+ * @file llvoicechannel.cpp
+ * @brief Voice Channel related classes
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llagent.h"
+#include "llfloaterreg.h"
+#include "llimview.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+#include "llpanel.h"
+#include "llrecentpeople.h"
+#include "llviewercontrol.h"
+#include "llvoicechannel.h"
+
+
+LLVoiceChannel::voice_channel_map_t LLVoiceChannel::sVoiceChannelMap;
+LLVoiceChannel::voice_channel_map_uri_t LLVoiceChannel::sVoiceChannelURIMap;
+LLVoiceChannel* LLVoiceChannel::sCurrentVoiceChannel = NULL;
+LLVoiceChannel* LLVoiceChannel::sSuspendedVoiceChannel = NULL;
+LLVoiceChannel::channel_changed_signal_t LLVoiceChannel::sCurrentVoiceChannelChangedSignal;
+
+BOOL LLVoiceChannel::sSuspended = FALSE;
+
+//
+// Constants
+//
+const U32 DEFAULT_RETRIES_COUNT = 3;
+
+
+class LLVoiceCallCapResponder : public LLHTTPClient::Responder
+{
+public:
+ LLVoiceCallCapResponder(const LLUUID& session_id) : mSessionID(session_id) {};
+
+ virtual void error(U32 status, const std::string& reason); // called with bad status codes
+ virtual void result(const LLSD& content);
+
+private:
+ LLUUID mSessionID;
+};
+
+
+void LLVoiceCallCapResponder::error(U32 status, const std::string& reason)
+{
+ llwarns << "LLVoiceCallCapResponder::error("
+ << status << ": " << reason << ")"
+ << llendl;
+ LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
+ if ( channelp )
+ {
+ if ( 403 == status )
+ {
+ //403 == no ability
+ LLNotificationsUtil::add(
+ "VoiceNotAllowed",
+ channelp->getNotifyArgs());
+ }
+ else
+ {
+ LLNotificationsUtil::add(
+ "VoiceCallGenericError",
+ channelp->getNotifyArgs());
+ }
+ channelp->deactivate();
+ }
+}
+
+void LLVoiceCallCapResponder::result(const LLSD& content)
+{
+ LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
+ if (channelp)
+ {
+ //*TODO: DEBUG SPAM
+ LLSD::map_const_iterator iter;
+ for(iter = content.beginMap(); iter != content.endMap(); ++iter)
+ {
+ llinfos << "LLVoiceCallCapResponder::result got "
+ << iter->first << llendl;
+ }
+
+ channelp->setChannelInfo(
+ content["voice_credentials"]["channel_uri"].asString(),
+ content["voice_credentials"]["channel_credentials"].asString());
+ }
+}
+
+//
+// LLVoiceChannel
+//
+LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const std::string& session_name) :
+ mSessionID(session_id),
+ mState(STATE_NO_CHANNEL_INFO),
+ mSessionName(session_name),
+ mCallDirection(OUTGOING_CALL),
+ mIgnoreNextSessionLeave(FALSE)
+{
+ mNotifyArgs["VOICE_CHANNEL_NAME"] = mSessionName;
+
+ if (!sVoiceChannelMap.insert(std::make_pair(session_id, this)).second)
+ {
+ // a voice channel already exists for this session id, so this instance will be orphaned
+ // the end result should simply be the failure to make voice calls
+ llwarns << "Duplicate voice channels registered for session_id " << session_id << llendl;
+ }
+
+ LLVoiceClient::getInstance()->addObserver(this);
+}
+
+LLVoiceChannel::~LLVoiceChannel()
+{
+ // Don't use LLVoiceClient::getInstance() here -- this can get called during atexit() time and that singleton MAY have already been destroyed.
+ if(gVoiceClient)
+ {
+ gVoiceClient->removeObserver(this);
+ }
+
+ sVoiceChannelMap.erase(mSessionID);
+ sVoiceChannelURIMap.erase(mURI);
+}
+
+void LLVoiceChannel::setChannelInfo(
+ const std::string& uri,
+ const std::string& credentials)
+{
+ setURI(uri);
+
+ mCredentials = credentials;
+
+ if (mState == STATE_NO_CHANNEL_INFO)
+ {
+ if (mURI.empty())
+ {
+ LLNotificationsUtil::add("VoiceChannelJoinFailed", mNotifyArgs);
+ llwarns << "Received empty URI for channel " << mSessionName << llendl;
+ deactivate();
+ }
+ else if (mCredentials.empty())
+ {
+ LLNotificationsUtil::add("VoiceChannelJoinFailed", mNotifyArgs);
+ llwarns << "Received empty credentials for channel " << mSessionName << llendl;
+ deactivate();
+ }
+ else
+ {
+ setState(STATE_READY);
+
+ // if we are supposed to be active, reconnect
+ // this will happen on initial connect, as we request credentials on first use
+ if (sCurrentVoiceChannel == this)
+ {
+ // just in case we got new channel info while active
+ // should move over to new channel
+ activate();
+ }
+ }
+ }
+}
+
+void LLVoiceChannel::onChange(EStatusType type, const std::string &channelURI, bool proximal)
+{
+ if (channelURI != mURI)
+ {
+ return;
+ }
+
+ if (type < BEGIN_ERROR_STATUS)
+ {
+ handleStatusChange(type);
+ }
+ else
+ {
+ handleError(type);
+ }
+}
+
+void LLVoiceChannel::handleStatusChange(EStatusType type)
+{
+ // status updates
+ switch(type)
+ {
+ case STATUS_LOGIN_RETRY:
+ //mLoginNotificationHandle = LLNotifyBox::showXml("VoiceLoginRetry")->getHandle();
+ LLNotificationsUtil::add("VoiceLoginRetry");
+ break;
+ case STATUS_LOGGED_IN:
+ //if (!mLoginNotificationHandle.isDead())
+ //{
+ // LLNotifyBox* notifyp = (LLNotifyBox*)mLoginNotificationHandle.get();
+ // if (notifyp)
+ // {
+ // notifyp->close();
+ // }
+ // mLoginNotificationHandle.markDead();
+ //}
+ break;
+ case STATUS_LEFT_CHANNEL:
+ if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
+ {
+ // if forceably removed from channel
+ // update the UI and revert to default channel
+ deactivate();
+ }
+ mIgnoreNextSessionLeave = FALSE;
+ break;
+ case STATUS_JOINING:
+ if (callStarted())
+ {
+ setState(STATE_RINGING);
+ }
+ break;
+ case STATUS_JOINED:
+ if (callStarted())
+ {
+ setState(STATE_CONNECTED);
+ }
+ default:
+ break;
+ }
+}
+
+// default behavior is to just deactivate channel
+// derived classes provide specific error messages
+void LLVoiceChannel::handleError(EStatusType type)
+{
+ deactivate();
+ setState(STATE_ERROR);
+}
+
+BOOL LLVoiceChannel::isActive()
+{
+ // only considered active when currently bound channel matches what our channel
+ return callStarted() && LLVoiceClient::getInstance()->getCurrentChannel() == mURI;
+}
+
+BOOL LLVoiceChannel::callStarted()
+{
+ return mState >= STATE_CALL_STARTED;
+}
+
+void LLVoiceChannel::deactivate()
+{
+ if (mState >= STATE_RINGING)
+ {
+ // ignore session leave event
+ mIgnoreNextSessionLeave = TRUE;
+ }
+
+ if (callStarted())
+ {
+ setState(STATE_HUNG_UP);
+
+ //Default mic is OFF when leaving voice calls
+ if (gSavedSettings.getBOOL("AutoDisengageMic") &&
+ sCurrentVoiceChannel == this &&
+ gVoiceClient->getUserPTTState())
+ {
+ gSavedSettings.setBOOL("PTTCurrentlyEnabled", true);
+ gVoiceClient->inputUserControlState(true);
+ }
+ }
+
+ if (sCurrentVoiceChannel == this)
+ {
+ // default channel is proximal channel
+ sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
+ sCurrentVoiceChannel->activate();
+ }
+}
+
+void LLVoiceChannel::activate()
+{
+ if (callStarted())
+ {
+ return;
+ }
+
+ // deactivate old channel and mark ourselves as the active one
+ if (sCurrentVoiceChannel != this)
+ {
+ // mark as current before deactivating the old channel to prevent
+ // activating the proximal channel between IM calls
+ LLVoiceChannel* old_channel = sCurrentVoiceChannel;
+ sCurrentVoiceChannel = this;
+ mCallDialogPayload["old_channel_name"] = "";
+ if (old_channel)
+ {
+ mCallDialogPayload["old_channel_name"] = old_channel->getSessionName();
+ old_channel->deactivate();
+ }
+ }
+
+ if (mState == STATE_NO_CHANNEL_INFO)
+ {
+ // responsible for setting status to active
+ getChannelInfo();
+ }
+ else
+ {
+ setState(STATE_CALL_STARTED);
+ }
+
+ //do not send earlier, channel should be initialized, should not be in STATE_NO_CHANNEL_INFO state
+ sCurrentVoiceChannelChangedSignal(this->mSessionID);
+}
+
+void LLVoiceChannel::getChannelInfo()
+{
+ // pretend we have everything we need
+ if (sCurrentVoiceChannel == this)
+ {
+ setState(STATE_CALL_STARTED);
+ }
+}
+
+//static
+LLVoiceChannel* LLVoiceChannel::getChannelByID(const LLUUID& session_id)
+{
+ voice_channel_map_t::iterator found_it = sVoiceChannelMap.find(session_id);
+ if (found_it == sVoiceChannelMap.end())
+ {
+ return NULL;
+ }
+ else
+ {
+ return found_it->second;
+ }
+}
+
+//static
+LLVoiceChannel* LLVoiceChannel::getChannelByURI(std::string uri)
+{
+ voice_channel_map_uri_t::iterator found_it = sVoiceChannelURIMap.find(uri);
+ if (found_it == sVoiceChannelURIMap.end())
+ {
+ return NULL;
+ }
+ else
+ {
+ return found_it->second;
+ }
+}
+
+void LLVoiceChannel::updateSessionID(const LLUUID& new_session_id)
+{
+ sVoiceChannelMap.erase(sVoiceChannelMap.find(mSessionID));
+ mSessionID = new_session_id;
+ sVoiceChannelMap.insert(std::make_pair(mSessionID, this));
+}
+
+void LLVoiceChannel::setURI(std::string uri)
+{
+ sVoiceChannelURIMap.erase(mURI);
+ mURI = uri;
+ sVoiceChannelURIMap.insert(std::make_pair(mURI, this));
+}
+
+void LLVoiceChannel::setState(EState state)
+{
+ switch(state)
+ {
+ case STATE_RINGING:
+ gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
+ break;
+ case STATE_CONNECTED:
+ gIMMgr->addSystemMessage(mSessionID, "connected", mNotifyArgs);
+ break;
+ case STATE_HUNG_UP:
+ gIMMgr->addSystemMessage(mSessionID, "hang_up", mNotifyArgs);
+ break;
+ default:
+ break;
+ }
+
+ doSetState(state);
+}
+
+void LLVoiceChannel::doSetState(const EState& new_state)
+{
+ EState old_state = mState;
+ mState = new_state;
+ if (!mStateChangedCallback.empty())
+ mStateChangedCallback(old_state, mState, mCallDirection);
+}
+
+//static
+void LLVoiceChannel::initClass()
+{
+ sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
+}
+
+
+//static
+void LLVoiceChannel::suspend()
+{
+ if (!sSuspended)
+ {
+ sSuspendedVoiceChannel = sCurrentVoiceChannel;
+ sSuspended = TRUE;
+ }
+}
+
+//static
+void LLVoiceChannel::resume()
+{
+ if (sSuspended)
+ {
+ if (gVoiceClient->voiceEnabled())
+ {
+ if (sSuspendedVoiceChannel)
+ {
+ sSuspendedVoiceChannel->activate();
+ }
+ else
+ {
+ LLVoiceChannelProximal::getInstance()->activate();
+ }
+ }
+ sSuspended = FALSE;
+ }
+}
+
+boost::signals2::connection LLVoiceChannel::setCurrentVoiceChannelChangedCallback(channel_changed_callback_t cb, bool at_front)
+{
+ if (at_front)
+ {
+ return sCurrentVoiceChannelChangedSignal.connect(cb, boost::signals2::at_front);
+ }
+ else
+ {
+ return sCurrentVoiceChannelChangedSignal.connect(cb);
+ }
+}
+
+//
+// LLVoiceChannelGroup
+//
+
+LLVoiceChannelGroup::LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name) :
+ LLVoiceChannel(session_id, session_name)
+{
+ mRetries = DEFAULT_RETRIES_COUNT;
+ mIsRetrying = FALSE;
+}
+
+void LLVoiceChannelGroup::deactivate()
+{
+ if (callStarted())
+ {
+ LLVoiceClient::getInstance()->leaveNonSpatialChannel();
+ }
+ LLVoiceChannel::deactivate();
+}
+
+void LLVoiceChannelGroup::activate()
+{
+ if (callStarted()) return;
+
+ LLVoiceChannel::activate();
+
+ if (callStarted())
+ {
+ // we have the channel info, just need to use it now
+ LLVoiceClient::getInstance()->setNonSpatialChannel(
+ mURI,
+ mCredentials);
+
+#if 0 // *TODO
+ if (!gAgent.isInGroup(mSessionID)) // ad-hoc channel
+ {
+ // Add the party to the list of people with which we've recently interacted.
+ for (/*people in the chat*/)
+ LLRecentPeople::instance().add(buddy_id);
+ }
+#endif
+
+ //Mic default state is OFF on initiating/joining Ad-Hoc/Group calls
+ if (gVoiceClient->getUserPTTState() && gVoiceClient->getPTTIsToggle())
+ {
+ gVoiceClient->inputUserControlState(true);
+ }
+
+ }
+}
+
+void LLVoiceChannelGroup::getChannelInfo()
+{
+ LLViewerRegion* region = gAgent.getRegion();
+ if (region)
+ {
+ std::string url = region->getCapability("ChatSessionRequest");
+ LLSD data;
+ data["method"] = "call";
+ data["session-id"] = mSessionID;
+ LLHTTPClient::post(url,
+ data,
+ new LLVoiceCallCapResponder(mSessionID));
+ }
+}
+
+void LLVoiceChannelGroup::setChannelInfo(
+ const std::string& uri,
+ const std::string& credentials)
+{
+ setURI(uri);
+
+ mCredentials = credentials;
+
+ if (mState == STATE_NO_CHANNEL_INFO)
+ {
+ if(!mURI.empty() && !mCredentials.empty())
+ {
+ setState(STATE_READY);
+
+ // if we are supposed to be active, reconnect
+ // this will happen on initial connect, as we request credentials on first use
+ if (sCurrentVoiceChannel == this)
+ {
+ // just in case we got new channel info while active
+ // should move over to new channel
+ activate();
+ }
+ }
+ else
+ {
+ //*TODO: notify user
+ llwarns << "Received invalid credentials for channel " << mSessionName << llendl;
+ deactivate();
+ }
+ }
+ else if ( mIsRetrying )
+ {
+ // we have the channel info, just need to use it now
+ LLVoiceClient::getInstance()->setNonSpatialChannel(
+ mURI,
+ mCredentials);
+ }
+}
+
+void LLVoiceChannelGroup::handleStatusChange(EStatusType type)
+{
+ // status updates
+ switch(type)
+ {
+ case STATUS_JOINED:
+ mRetries = 3;
+ mIsRetrying = FALSE;
+ default:
+ break;
+ }
+
+ LLVoiceChannel::handleStatusChange(type);
+}
+
+void LLVoiceChannelGroup::handleError(EStatusType status)
+{
+ std::string notify;
+ switch(status)
+ {
+ case ERROR_CHANNEL_LOCKED:
+ case ERROR_CHANNEL_FULL:
+ notify = "VoiceChannelFull";
+ break;
+ case ERROR_NOT_AVAILABLE:
+ //clear URI and credentials
+ //set the state to be no info
+ //and activate
+ if ( mRetries > 0 )
+ {
+ mRetries--;
+ mIsRetrying = TRUE;
+ mIgnoreNextSessionLeave = TRUE;
+
+ getChannelInfo();
+ return;
+ }
+ else
+ {
+ notify = "VoiceChannelJoinFailed";
+ mRetries = DEFAULT_RETRIES_COUNT;
+ mIsRetrying = FALSE;
+ }
+
+ break;
+
+ case ERROR_UNKNOWN:
+ default:
+ break;
+ }
+
+ // notification
+ if (!notify.empty())
+ {
+ LLNotificationPtr notification = LLNotificationsUtil::add(notify, mNotifyArgs);
+ // echo to im window
+ gIMMgr->addMessage(mSessionID, LLUUID::null, SYSTEM_FROM, notification->getMessage());
+ }
+
+ LLVoiceChannel::handleError(status);
+}
+
+void LLVoiceChannelGroup::setState(EState state)
+{
+ switch(state)
+ {
+ case STATE_RINGING:
+ if ( !mIsRetrying )
+ {
+ gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
+ }
+
+ doSetState(state);
+ break;
+ default:
+ LLVoiceChannel::setState(state);
+ }
+}
+
+//
+// LLVoiceChannelProximal
+//
+LLVoiceChannelProximal::LLVoiceChannelProximal() :
+ LLVoiceChannel(LLUUID::null, LLStringUtil::null)
+{
+ activate();
+}
+
+BOOL LLVoiceChannelProximal::isActive()
+{
+ return callStarted() && LLVoiceClient::getInstance()->inProximalChannel();
+}
+
+void LLVoiceChannelProximal::activate()
+{
+ if (callStarted()) return;
+
+ LLVoiceChannel::activate();
+
+ if (callStarted())
+ {
+ // this implicitly puts you back in the spatial channel
+ LLVoiceClient::getInstance()->leaveNonSpatialChannel();
+ }
+}
+
+void LLVoiceChannelProximal::onChange(EStatusType type, const std::string &channelURI, bool proximal)
+{
+ if (!proximal)
+ {
+ return;
+ }
+
+ if (type < BEGIN_ERROR_STATUS)
+ {
+ handleStatusChange(type);
+ }
+ else
+ {
+ handleError(type);
+ }
+}
+
+void LLVoiceChannelProximal::handleStatusChange(EStatusType status)
+{
+ // status updates
+ switch(status)
+ {
+ case STATUS_LEFT_CHANNEL:
+ // do not notify user when leaving proximal channel
+ return;
+ case STATUS_VOICE_DISABLED:
+ gIMMgr->addSystemMessage(LLUUID::null, "unavailable", mNotifyArgs);
+ return;
+ default:
+ break;
+ }
+ LLVoiceChannel::handleStatusChange(status);
+}
+
+
+void LLVoiceChannelProximal::handleError(EStatusType status)
+{
+ std::string notify;
+ switch(status)
+ {
+ case ERROR_CHANNEL_LOCKED:
+ case ERROR_CHANNEL_FULL:
+ notify = "ProximalVoiceChannelFull";
+ break;
+ default:
+ break;
+ }
+
+ // notification
+ if (!notify.empty())
+ {
+ LLNotificationsUtil::add(notify, mNotifyArgs);
+ }
+
+ LLVoiceChannel::handleError(status);
+}
+
+void LLVoiceChannelProximal::deactivate()
+{
+ if (callStarted())
+ {
+ setState(STATE_HUNG_UP);
+ }
+}
+
+
+//
+// LLVoiceChannelP2P
+//
+LLVoiceChannelP2P::LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id) :
+ LLVoiceChannelGroup(session_id, session_name),
+ mOtherUserID(other_user_id),
+ 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));
+}
+
+void LLVoiceChannelP2P::handleStatusChange(EStatusType type)
+{
+ llinfos << "P2P CALL CHANNEL STATUS CHANGE: incoming=" << int(mReceivedCall) << " newstatus=" << LLVoiceClientStatusObserver::status2string(type) << " (mState=" << mState << ")" << llendl;
+
+ // status updates
+ switch(type)
+ {
+ case STATUS_LEFT_CHANNEL:
+ if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
+ {
+ // *TODO: use it to show DECLINE voice notification
+ if (mState == STATE_RINGING)
+ {
+ // other user declined call
+ LLNotificationsUtil::add("P2PCallDeclined", mNotifyArgs);
+ }
+ else
+ {
+ // other user hung up
+ }
+ deactivate();
+ }
+ mIgnoreNextSessionLeave = FALSE;
+ return;
+ default:
+ break;
+ }
+
+ LLVoiceChannel::handleStatusChange(type);
+}
+
+void LLVoiceChannelP2P::handleError(EStatusType type)
+{
+ switch(type)
+ {
+ case ERROR_NOT_AVAILABLE:
+ LLNotificationsUtil::add("P2PCallNoAnswer", mNotifyArgs);
+ break;
+ default:
+ break;
+ }
+
+ LLVoiceChannel::handleError(type);
+}
+
+void LLVoiceChannelP2P::activate()
+{
+ if (callStarted()) return;
+
+ LLVoiceChannel::activate();
+
+ if (callStarted())
+ {
+ // no session handle yet, we're starting the call
+ if (mSessionHandle.empty())
+ {
+ mReceivedCall = FALSE;
+ LLVoiceClient::getInstance()->callUser(mOtherUserID);
+ }
+ // otherwise answering the call
+ else
+ {
+ LLVoiceClient::getInstance()->answerInvite(mSessionHandle);
+
+ // using the session handle invalidates it. Clear it out here so we can't reuse it by accident.
+ mSessionHandle.clear();
+ }
+
+ // Add the party to the list of people with which we've recently interacted.
+ LLRecentPeople::instance().add(mOtherUserID);
+
+ //Default mic is ON on initiating/joining P2P calls
+ if (!gVoiceClient->getUserPTTState() && gVoiceClient->getPTTIsToggle())
+ {
+ gVoiceClient->inputUserControlState(true);
+ }
+ }
+}
+
+void LLVoiceChannelP2P::getChannelInfo()
+{
+ // pretend we have everything we need, since P2P doesn't use channel info
+ if (sCurrentVoiceChannel == this)
+ {
+ setState(STATE_CALL_STARTED);
+ }
+}
+
+// receiving session from other user who initiated call
+void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::string &inURI)
+{
+ BOOL needs_activate = FALSE;
+ if (callStarted())
+ {
+ // defer to lower agent id when already active
+ if (mOtherUserID < gAgent.getID())
+ {
+ // pretend we haven't started the call yet, so we can connect to this session instead
+ deactivate();
+ needs_activate = TRUE;
+ }
+ else
+ {
+ // we are active and have priority, invite the other user again
+ // under the assumption they will join this new session
+ mSessionHandle.clear();
+ LLVoiceClient::getInstance()->callUser(mOtherUserID);
+ return;
+ }
+ }
+
+ mSessionHandle = handle;
+
+ // The URI of a p2p session should always be the other end's SIP URI.
+ if(!inURI.empty())
+ {
+ setURI(inURI);
+ }
+ else
+ {
+ LL_WARNS("Voice") << "incoming SIP URL is not provided. Channel may not work properly." << LL_ENDL;
+ // In case of incoming AvaLine call generated URI will be differ from original one.
+ // This is because Avatar-2-Avatar URI is based on avatar UUID but Avaline is not.
+ // See LLVoiceClient::sessionAddedEvent() -> setUUIDFromStringHash()
+ setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID));
+ }
+
+ mReceivedCall = TRUE;
+
+ if (needs_activate)
+ {
+ activate();
+ }
+}
+
+void LLVoiceChannelP2P::setState(EState state)
+{
+ llinfos << "P2P CALL STATE CHANGE: incoming=" << int(mReceivedCall) << " oldstate=" << mState << " newstate=" << state << llendl;
+
+ if (mReceivedCall) // incoming call
+ {
+ // you only "answer" voice invites in p2p mode
+ // so provide a special purpose message here
+ if (mReceivedCall && state == STATE_RINGING)
+ {
+ gIMMgr->addSystemMessage(mSessionID, "answering", mNotifyArgs);
+ doSetState(state);
+ return;
+ }
+ }
+
+ LLVoiceChannel::setState(state);
+}
diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h
new file mode 100644
index 0000000000..cb86671305
--- /dev/null
+++ b/indra/newview/llvoicechannel.h
@@ -0,0 +1,199 @@
+/**
+ * @file llvoicechannel.h
+ * @brief Voice channel related classes
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_VOICECHANNEL_H
+#define LL_VOICECHANNEL_H
+
+#include "llhandle.h"
+#include "llvoiceclient.h"
+
+class LLPanel;
+
+class LLVoiceChannel : public LLVoiceClientStatusObserver
+{
+public:
+ typedef enum e_voice_channel_state
+ {
+ STATE_NO_CHANNEL_INFO,
+ STATE_ERROR,
+ STATE_HUNG_UP,
+ STATE_READY,
+ STATE_CALL_STARTED,
+ STATE_RINGING,
+ STATE_CONNECTED
+ } EState;
+
+ typedef enum e_voice_channel_direction
+ {
+ INCOMING_CALL,
+ OUTGOING_CALL
+ } EDirection;
+
+ typedef boost::signals2::signal<void(const EState& old_state, const EState& new_state, const EDirection& direction)> state_changed_signal_t;
+
+ // on current channel changed signal
+ typedef boost::function<void(const LLUUID& session_id)> channel_changed_callback_t;
+ typedef boost::signals2::signal<void(const LLUUID& session_id)> channel_changed_signal_t;
+ static channel_changed_signal_t sCurrentVoiceChannelChangedSignal;
+ static boost::signals2::connection setCurrentVoiceChannelChangedCallback(channel_changed_callback_t cb, bool at_front = false);
+
+
+ LLVoiceChannel(const LLUUID& session_id, const std::string& session_name);
+ virtual ~LLVoiceChannel();
+
+ /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
+
+ virtual void handleStatusChange(EStatusType status);
+ virtual void handleError(EStatusType status);
+ virtual void deactivate();
+ virtual void activate();
+ virtual void setChannelInfo(
+ const std::string& uri,
+ const std::string& credentials);
+ virtual void getChannelInfo();
+ virtual BOOL isActive();
+ virtual BOOL callStarted();
+ const std::string& getSessionName() const { return mSessionName; }
+
+ boost::signals2::connection setStateChangedCallback(const state_changed_signal_t::slot_type& callback)
+ { return mStateChangedCallback.connect(callback); }
+
+ const LLUUID getSessionID() { return mSessionID; }
+ EState getState() { return mState; }
+
+ void updateSessionID(const LLUUID& new_session_id);
+ const LLSD& getNotifyArgs() { return mNotifyArgs; }
+
+ void setCallDirection(EDirection direction) {mCallDirection = direction;}
+ EDirection getCallDirection() {return mCallDirection;}
+
+ static LLVoiceChannel* getChannelByID(const LLUUID& session_id);
+ static LLVoiceChannel* getChannelByURI(std::string uri);
+ static LLVoiceChannel* getCurrentVoiceChannel() { return sCurrentVoiceChannel; }
+ static void initClass();
+
+ static void suspend();
+ static void resume();
+
+protected:
+ virtual void setState(EState state);
+ /**
+ * Use this method if you want mStateChangedCallback to be executed while state is changed
+ */
+ void doSetState(const EState& state);
+ void setURI(std::string uri);
+
+ // there can be two directions ICOMING and OUTGOING
+ EDirection mCallDirection;
+
+ std::string mURI;
+ std::string mCredentials;
+ LLUUID mSessionID;
+ EState mState;
+ std::string mSessionName;
+ LLSD mNotifyArgs;
+ LLSD mCallDialogPayload;
+ BOOL mIgnoreNextSessionLeave;
+ LLHandle<LLPanel> mLoginNotificationHandle;
+
+ typedef std::map<LLUUID, LLVoiceChannel*> voice_channel_map_t;
+ static voice_channel_map_t sVoiceChannelMap;
+
+ typedef std::map<std::string, LLVoiceChannel*> voice_channel_map_uri_t;
+ static voice_channel_map_uri_t sVoiceChannelURIMap;
+
+ static LLVoiceChannel* sCurrentVoiceChannel;
+ static LLVoiceChannel* sSuspendedVoiceChannel;
+ static BOOL sSuspended;
+
+private:
+ state_changed_signal_t mStateChangedCallback;
+};
+
+class LLVoiceChannelGroup : public LLVoiceChannel
+{
+public:
+ LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name);
+
+ /*virtual*/ void handleStatusChange(EStatusType status);
+ /*virtual*/ void handleError(EStatusType status);
+ /*virtual*/ void activate();
+ /*virtual*/ void deactivate();
+ /*vritual*/ void setChannelInfo(
+ const std::string& uri,
+ const std::string& credentials);
+ /*virtual*/ void getChannelInfo();
+
+protected:
+ virtual void setState(EState state);
+
+private:
+ U32 mRetries;
+ BOOL mIsRetrying;
+};
+
+class LLVoiceChannelProximal : public LLVoiceChannel, public LLSingleton<LLVoiceChannelProximal>
+{
+public:
+ LLVoiceChannelProximal();
+
+ /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
+ /*virtual*/ void handleStatusChange(EStatusType status);
+ /*virtual*/ void handleError(EStatusType status);
+ /*virtual*/ BOOL isActive();
+ /*virtual*/ void activate();
+ /*virtual*/ void deactivate();
+
+};
+
+class LLVoiceChannelP2P : public LLVoiceChannelGroup
+{
+public:
+ LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id);
+
+ /*virtual*/ void handleStatusChange(EStatusType status);
+ /*virtual*/ void handleError(EStatusType status);
+ /*virtual*/ void activate();
+ /*virtual*/ void getChannelInfo();
+
+ void setSessionHandle(const std::string& handle, const std::string &inURI);
+
+protected:
+ virtual void setState(EState state);
+
+private:
+ std::string mSessionHandle;
+ LLUUID mOtherUserID;
+ BOOL mReceivedCall;
+};
+
+#endif // LL_VOICECHANNEL_H
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 94407ed08c..8ca0fd6ef6 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -35,8 +35,13 @@
#include <boost/tokenizer.hpp>
+// library includes
+#include "llnotificationsutil.h"
+#include "llsdserialize.h"
#include "llsdutil.h"
+
+// project includes
#include "llvoavatar.h"
#include "llbufferstream.h"
#include "llfile.h"
@@ -46,6 +51,7 @@
# include "expat/expat.h"
#endif
#include "llcallbacklist.h"
+#include "llcallingcard.h" // for LLFriendObserver
#include "llviewerregion.h"
#include "llviewernetwork.h" // for gGridChoice
#include "llbase64.h"
@@ -56,15 +62,17 @@
#include "llagent.h"
#include "llcachename.h"
#include "llimview.h" // for LLIMMgr
-#include "llimpanel.h" // for LLVoiceChannel
#include "llparcel.h"
#include "llviewerparcelmgr.h"
-#include "llfirstuse.h"
+//#include "llfirstuse.h"
+#include "llspeakers.h"
+#include "lltrans.h"
#include "llviewerwindow.h"
#include "llviewercamera.h"
+#include "llvoavatarself.h"
+#include "llvoicechannel.h"
#include "llfloaterfriends.h" //VIVOX, inorder to refresh communicate panel
-#include "llfloaterchat.h" // for LLFloaterChat::addChat()
// for base64 decoding
#include "apr_base64.h"
@@ -107,31 +115,15 @@ static void setUUIDFromStringHash(LLUUID &uuid, const std::string &str)
static int scale_mic_volume(float volume)
{
// incoming volume has the range [0.0 ... 2.0], with 1.0 as the default.
- // Map it as follows: 0.0 -> 40, 1.0 -> 44, 2.0 -> 75
-
- volume -= 1.0f; // offset volume to the range [-1.0 ... 1.0], with 0 at the default.
- int scaled_volume = 44; // offset scaled_volume by its default level
- if(volume < 0.0f)
- scaled_volume += ((int)(volume * 4.0f)); // (44 - 40)
- else
- scaled_volume += ((int)(volume * 31.0f)); // (75 - 44)
-
- return scaled_volume;
+ // Map it to Vivox levels as follows: 0.0 -> 30, 1.0 -> 50, 2.0 -> 70
+ return 30 + (int)(volume * 20.0f);
}
static int scale_speaker_volume(float volume)
{
// incoming volume has the range [0.0 ... 1.0], with 0.5 as the default.
- // Map it as follows: 0.0 -> 0, 0.5 -> 62, 1.0 -> 75
-
- volume -= 0.5f; // offset volume to the range [-0.5 ... 0.5], with 0 at the default.
- int scaled_volume = 62; // offset scaled_volume by its default level
- if(volume < 0.0f)
- scaled_volume += ((int)(volume * 124.0f)); // (62 - 0) * 2
- else
- scaled_volume += ((int)(volume * 26.0f)); // (75 - 62) * 2
-
- return scaled_volume;
+ // Map it to Vivox levels as follows: 0.0 -> 30, 0.5 -> 50, 1.0 -> 70
+ return 30 + (int)(volume * 40.0f);
}
class LLViewerVoiceAccountProvisionResponder :
@@ -249,6 +241,7 @@ protected:
std::string nameString;
std::string audioMediaString;
std::string displayNameString;
+ std::string deviceString;
int participantType;
bool isLocallyMuted;
bool isModeratorMuted;
@@ -480,6 +473,14 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)
{
gVoiceClient->clearRenderDevices();
}
+ else if (!stricmp("CaptureDevice", tag))
+ {
+ deviceString.clear();
+ }
+ else if (!stricmp("RenderDevice", tag))
+ {
+ deviceString.clear();
+ }
else if (!stricmp("Buddies", tag))
{
gVoiceClient->deleteAllBuddies();
@@ -503,7 +504,6 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)
void LLVivoxProtocolParser::EndTag(const char *tag)
{
const std::string& string = textBuffer;
- bool clearbuffer = true;
responseDepth--;
@@ -575,6 +575,8 @@ void LLVivoxProtocolParser::EndTag(const char *tag)
nameString = string;
else if (!stricmp("DisplayName", tag))
displayNameString = string;
+ else if (!stricmp("Device", tag))
+ deviceString = string;
else if (!stricmp("AccountName", tag))
nameString = string;
else if (!stricmp("ParticipantType", tag))
@@ -591,18 +593,13 @@ void LLVivoxProtocolParser::EndTag(const char *tag)
uriString = string;
else if (!stricmp("Presence", tag))
statusString = string;
- else if (!stricmp("Device", tag))
- {
- // This closing tag shouldn't clear the accumulated text.
- clearbuffer = false;
- }
else if (!stricmp("CaptureDevice", tag))
{
- gVoiceClient->addCaptureDevice(textBuffer);
+ gVoiceClient->addCaptureDevice(deviceString);
}
else if (!stricmp("RenderDevice", tag))
{
- gVoiceClient->addRenderDevice(textBuffer);
+ gVoiceClient->addRenderDevice(deviceString);
}
else if (!stricmp("Buddy", tag))
{
@@ -643,12 +640,8 @@ void LLVivoxProtocolParser::EndTag(const char *tag)
else if (!stricmp("SubscriptionType", tag))
subscriptionType = string;
-
- if(clearbuffer)
- {
- textBuffer.clear();
- accumulateText= false;
- }
+ textBuffer.clear();
+ accumulateText= false;
if (responseDepth == 0)
{
@@ -1101,61 +1094,179 @@ static void killGateway()
#endif
-///////////////////////////////////////////////////////////////////////////////////////////////
+class LLSpeakerVolumeStorage : public LLSingleton<LLSpeakerVolumeStorage>
+{
+ LOG_CLASS(LLSpeakerVolumeStorage);
+public:
-LLVoiceClient::LLVoiceClient()
-{
- gVoiceClient = this;
- mWriteInProgress = false;
- mAreaVoiceDisabled = false;
- mPTT = true;
- mUserPTTState = false;
- mMuteMic = false;
- mSessionTerminateRequested = false;
- mRelogRequested = false;
- mCommandCookie = 0;
- mCurrentParcelLocalID = 0;
- mLoginRetryCount = 0;
-
- mSpeakerVolume = 0;
- mMicVolume = 0;
-
- mAudioSession = NULL;
- mAudioSessionChanged = false;
-
- // Initial dirty state
- mSpatialCoordsDirty = false;
- mPTTDirty = true;
- mFriendsListDirty = true;
- mSpeakerVolumeDirty = true;
- mMicVolumeDirty = true;
- mBuddyListMapPopulated = false;
- mBlockRulesListReceived = false;
- mAutoAcceptRulesListReceived = false;
- mCaptureDeviceDirty = false;
- mRenderDeviceDirty = false;
+ /**
+ * Sets internal voluem level for specified user.
+ *
+ * @param[in] speaker_id - LLUUID of user to store volume level for
+ * @param[in] volume - internal volume level to be stored for user.
+ */
+ void storeSpeakerVolume(const LLUUID& speaker_id, S32 volume);
+
+ /**
+ * Gets stored internal volume level for specified speaker.
+ *
+ * If specified user is not found default level will be returned. It is equivalent of
+ * external level 0.5 from the 0.0..1.0 range.
+ * Default internal level is calculated as: internal = 400 * external^2
+ * Maps 0.0 to 1.0 to internal values 0-400 with default 0.5 == 100
+ *
+ * @param[in] speaker_id - LLUUID of user to get his volume level
+ */
+ S32 getSpeakerVolume(const LLUUID& speaker_id);
+
+private:
+ friend class LLSingleton<LLSpeakerVolumeStorage>;
+ LLSpeakerVolumeStorage();
+ ~LLSpeakerVolumeStorage();
+
+ const static std::string SETTINGS_FILE_NAME;
+
+ void load();
+ void save();
+
+ typedef std::map<LLUUID, S32> speaker_data_map_t;
+ speaker_data_map_t mSpeakersData;
+};
+
+const std::string LLSpeakerVolumeStorage::SETTINGS_FILE_NAME = "volume_settings.xml";
+
+LLSpeakerVolumeStorage::LLSpeakerVolumeStorage()
+{
+ load();
+}
- // Use default values for everything then call updateSettings() after preferences are loaded
- mVoiceEnabled = false;
- mUsePTT = true;
- mPTTIsToggle = false;
- mEarLocation = 0;
- mLipSyncEnabled = false;
+LLSpeakerVolumeStorage::~LLSpeakerVolumeStorage()
+{
+ save();
+}
+
+void LLSpeakerVolumeStorage::storeSpeakerVolume(const LLUUID& speaker_id, S32 volume)
+{
+ mSpeakersData[speaker_id] = volume;
+}
+
+S32 LLSpeakerVolumeStorage::getSpeakerVolume(const LLUUID& speaker_id)
+{
+ // default internal level of user voice.
+ const static LLUICachedControl<S32> DEFAULT_INTERNAL_VOLUME_LEVEL("VoiceDefaultInternalLevel", 100);
+ S32 ret_val = DEFAULT_INTERNAL_VOLUME_LEVEL;
+ speaker_data_map_t::const_iterator it = mSpeakersData.find(speaker_id);
- mTuningMode = false;
- mTuningEnergy = 0.0f;
- mTuningMicVolume = 0;
- mTuningMicVolumeDirty = true;
- mTuningSpeakerVolume = 0;
- mTuningSpeakerVolumeDirty = true;
-
- // gMuteListp isn't set up at this point, so we defer this until later.
-// gMuteListp->addObserver(&mutelist_listener);
+ if (it != mSpeakersData.end())
+ {
+ ret_val = it->second;
+ }
+ return ret_val;
+}
+
+void LLSpeakerVolumeStorage::load()
+{
+ // load per-resident voice volume information
+ std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SETTINGS_FILE_NAME);
+
+ LLSD settings_llsd;
+ llifstream file;
+ file.open(filename);
+ if (file.is_open())
+ {
+ LLSDSerialize::fromXML(settings_llsd, file);
+ }
+
+ for (LLSD::map_const_iterator iter = settings_llsd.beginMap();
+ iter != settings_llsd.endMap(); ++iter)
+ {
+ mSpeakersData.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger()));
+ }
+}
+
+void LLSpeakerVolumeStorage::save()
+{
+ // If we quit from the login screen we will not have an SL account
+ // name. Don't try to save, otherwise we'll dump a file in
+ // C:\Program Files\SecondLife\ or similar. JC
+ std::string user_dir = gDirUtilp->getLindenUserDir();
+ if (!user_dir.empty())
+ {
+ std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SETTINGS_FILE_NAME);
+ LLSD settings_llsd;
+
+ for(speaker_data_map_t::const_iterator iter = mSpeakersData.begin(); iter != mSpeakersData.end(); ++iter)
+ {
+ settings_llsd[iter->first.asString()] = iter->second;
+ }
+
+ llofstream file;
+ file.open(filename);
+ LLSDSerialize::toPrettyXML(settings_llsd, file);
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+LLVoiceClient::LLVoiceClient() :
+ mState(stateDisabled),
+ mSessionTerminateRequested(false),
+ mRelogRequested(false),
+ mConnected(false),
+ mPump(NULL),
+
+ mTuningMode(false),
+ mTuningEnergy(0.0f),
+ mTuningMicVolume(0),
+ mTuningMicVolumeDirty(true),
+ mTuningSpeakerVolume(0),
+ mTuningSpeakerVolumeDirty(true),
+ mTuningExitState(stateDisabled),
+
+ mAreaVoiceDisabled(false),
+ mAudioSession(NULL),
+ mAudioSessionChanged(false),
+ mNextAudioSession(NULL),
+
+ mCurrentParcelLocalID(0),
+ mNumberOfAliases(0),
+ mCommandCookie(0),
+ mLoginRetryCount(0),
+
+ mBuddyListMapPopulated(false),
+ mBlockRulesListReceived(false),
+ mAutoAcceptRulesListReceived(false),
+ mCaptureDeviceDirty(false),
+ mRenderDeviceDirty(false),
+ mSpatialCoordsDirty(false),
+
+ mPTTDirty(true),
+ mPTT(true),
+ mUsePTT(true),
+ mPTTIsMiddleMouse(false),
+ mPTTKey(0),
+ mPTTIsToggle(false),
+ mUserPTTState(false),
+ mMuteMic(false),
+ mFriendsListDirty(true),
+
+ mEarLocation(0),
+ mSpeakerVolumeDirty(true),
+ mSpeakerMuteDirty(true),
+ mSpeakerVolume(0),
+ mMicVolume(0),
+ mMicVolumeDirty(true),
- // stash the pump for later use
- // This now happens when init() is called instead.
- mPump = NULL;
+ mVoiceEnabled(false),
+ mWriteInProgress(false),
+ mLipSyncEnabled(false)
+{
+ gVoiceClient = this;
+
+ mAPIVersion = LLTrans::getString("NotConnected");
+
#if LL_DARWIN || LL_LINUX || LL_SOLARIS
// HACK: THIS DOES NOT BELONG HERE
// When the vivox daemon dies, the next write attempt on our socket generates a SIGPIPE, which kills us.
@@ -1503,6 +1614,7 @@ std::string LLVoiceClientStatusObserver::status2string(LLVoiceClientStatusObserv
CASE(STATUS_JOINED);
CASE(STATUS_LEFT_CHANNEL);
CASE(STATUS_VOICE_DISABLED);
+ CASE(STATUS_VOICE_ENABLED);
CASE(BEGIN_ERROR_STATUS);
CASE(ERROR_CHANNEL_FULL);
CASE(ERROR_CHANNEL_LOCKED);
@@ -1590,7 +1702,7 @@ void LLVoiceClient::stateMachine()
}
else
{
- LL_WARNS("Voice") << "region doesn't have ParcelVoiceInfoRequest capability. This is normal for a short time after teleporting, but bad if it persists for very long." << LL_ENDL;
+ LL_WARNS_ONCE("Voice") << "region doesn't have ParcelVoiceInfoRequest capability. This is normal for a short time after teleporting, but bad if it persists for very long." << LL_ENDL;
}
}
}
@@ -1655,7 +1767,6 @@ void LLVoiceClient::stateMachine()
// SLIM SDK: these arguments are no longer necessary.
// std::string args = " -p tcp -h -c";
std::string args;
- std::string cmd;
std::string loglevel = gSavedSettings.getString("VivoxDebugLevel");
if(loglevel.empty())
@@ -1670,17 +1781,18 @@ void LLVoiceClient::stateMachine()
#if LL_WINDOWS
PROCESS_INFORMATION pinfo;
- STARTUPINFOA sinfo;
+ STARTUPINFOW sinfo;
memset(&sinfo, 0, sizeof(sinfo));
- std::string exe_dir = gDirUtilp->getAppRODataDir();
- cmd = "SLVoice.exe";
- cmd += args;
-
- // So retarded. Windows requires that the second parameter to CreateProcessA be a writable (non-const) string...
- char *args2 = new char[args.size() + 1];
- strcpy(args2, args.c_str());
- if(!CreateProcessA(exe_path.c_str(), args2, NULL, NULL, FALSE, 0, NULL, exe_dir.c_str(), &sinfo, &pinfo))
+ std::string exe_dir = gDirUtilp->getExecutableDir();
+
+ llutf16string exe_path16 = utf8str_to_utf16str(exe_path);
+ llutf16string exe_dir16 = utf8str_to_utf16str(exe_dir);
+ llutf16string args16 = utf8str_to_utf16str(args);
+ // Create a writeable copy to keep Windows happy.
+ U16 *argscpy_16 = new U16[args16.size() + 1];
+ wcscpy_s(argscpy_16,args16.size()+1,args16.c_str());
+ if(!CreateProcessW(exe_path16.c_str(), argscpy_16, NULL, NULL, FALSE, 0, NULL, exe_dir16.c_str(), &sinfo, &pinfo))
{
// DWORD dwErr = GetLastError();
}
@@ -1692,7 +1804,7 @@ void LLVoiceClient::stateMachine()
CloseHandle(pinfo.hThread); // stops leaks - nothing else
}
- delete[] args2;
+ delete[] argscpy_16;
#else // LL_WINDOWS
// This should be the same for mac and linux
{
@@ -1859,7 +1971,7 @@ void LLVoiceClient::stateMachine()
}
else
{
- LL_WARNS("Voice") << "region doesn't have ProvisionVoiceAccountRequest capability!" << LL_ENDL;
+ LL_WARNS_ONCE("Voice") << "region doesn't have ProvisionVoiceAccountRequest capability!" << LL_ENDL;
}
}
}
@@ -3740,6 +3852,7 @@ void LLVoiceClient::connectorCreateResponse(int statusCode, std::string &statusS
{
// Connector created, move forward.
LL_INFOS("Voice") << "Connector.Create succeeded, Vivox SDK version is " << versionID << LL_ENDL;
+ mAPIVersion = versionID;
mConnectorHandle = connectorHandle;
if(getState() == stateConnectorStarting)
{
@@ -4264,7 +4377,7 @@ void LLVoiceClient::mediaStreamUpdatedEvent(
if(incoming)
{
// Send the voice chat invite to the GUI layer
- // TODO: Question: Should we correlate with the mute list here?
+ // *TODO: Question: Should we correlate with the mute list here?
session->mIMSessionID = LLIMMgr::computeSessionID(IM_SESSION_P2P_INVITE, session->mCallerID);
session->mVoiceInvitePending = true;
if(session->mName.empty())
@@ -4445,6 +4558,35 @@ void LLVoiceClient::participantUpdatedEvent(
participant->mPower = 0.0f;
}
participant->mVolume = volume;
+
+
+ // *HACK: mantipov: added while working on EXT-3544
+ /*
+ Sometimes LLVoiceClient::participantUpdatedEvent callback is called BEFORE
+ LLViewerChatterBoxSessionAgentListUpdates::post() sometimes AFTER.
+
+ participantUpdatedEvent updates voice participant state in particular participantState::mIsModeratorMuted
+ Originally we wanted to update session Speaker Manager to fire LLSpeakerVoiceModerationEvent to fix the EXT-3544 bug.
+ Calling of the LLSpeakerMgr::update() method was added into LLIMMgr::processAgentListUpdates.
+
+ But in case participantUpdatedEvent() is called after LLViewerChatterBoxSessionAgentListUpdates::post()
+ voice participant mIsModeratorMuted is changed after speakers are updated in Speaker Manager
+ and event is not fired.
+
+ So, we have to call LLSpeakerMgr::update() here. In any case it is better than call it
+ in LLCallFloater::draw()
+ */
+ LLVoiceChannel* voice_cnl = LLVoiceChannel::getCurrentVoiceChannel();
+
+ // ignore session ID of local chat
+ if (voice_cnl && voice_cnl->getSessionID().notNull())
+ {
+ LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(voice_cnl->getSessionID());
+ if (speaker_manager)
+ {
+ speaker_manager->update(true);
+ }
+ }
}
else
{
@@ -4547,7 +4689,7 @@ void LLVoiceClient::messageEvent(
if(messageHeader.find("text/html") != std::string::npos)
{
- std::string rawMessage;
+ std::string message;
{
const std::string startMarker = "<body";
@@ -4559,7 +4701,7 @@ void LLVoiceClient::messageEvent(
std::string::size_type end;
// Default to displaying the raw string, so the message gets through.
- rawMessage = messageBody;
+ message = messageBody;
// Find the actual message text within the XML fragment
start = messageBody.find(startMarker);
@@ -4573,7 +4715,7 @@ void LLVoiceClient::messageEvent(
if(end != std::string::npos)
end -= start;
- rawMessage.assign(messageBody, start, end);
+ message.assign(messageBody, start, end);
}
else
{
@@ -4589,24 +4731,24 @@ void LLVoiceClient::messageEvent(
if(end != std::string::npos)
end -= start;
- rawMessage.assign(messageBody, start, end);
+ message.assign(messageBody, start, end);
}
}
}
-// LL_DEBUGS("Voice") << " raw message = \n" << rawMessage << LL_ENDL;
+// LL_DEBUGS("Voice") << " raw message = \n" << message << LL_ENDL;
// strip formatting tags
{
std::string::size_type start;
std::string::size_type end;
- while((start = rawMessage.find('<')) != std::string::npos)
+ while((start = message.find('<')) != std::string::npos)
{
- if((end = rawMessage.find('>', start + 1)) != std::string::npos)
+ if((end = message.find('>', start + 1)) != std::string::npos)
{
// Strip out the tag
- rawMessage.erase(start, (end + 1) - start);
+ message.erase(start, (end + 1) - start);
}
else
{
@@ -4622,31 +4764,31 @@ void LLVoiceClient::messageEvent(
// The text may contain text encoded with &lt;, &gt;, and &amp;
mark = 0;
- while((mark = rawMessage.find("&lt;", mark)) != std::string::npos)
+ while((mark = message.find("&lt;", mark)) != std::string::npos)
{
- rawMessage.replace(mark, 4, "<");
+ message.replace(mark, 4, "<");
mark += 1;
}
mark = 0;
- while((mark = rawMessage.find("&gt;", mark)) != std::string::npos)
+ while((mark = message.find("&gt;", mark)) != std::string::npos)
{
- rawMessage.replace(mark, 4, ">");
+ message.replace(mark, 4, ">");
mark += 1;
}
mark = 0;
- while((mark = rawMessage.find("&amp;", mark)) != std::string::npos)
+ while((mark = message.find("&amp;", mark)) != std::string::npos)
{
- rawMessage.replace(mark, 5, "&");
+ message.replace(mark, 5, "&");
mark += 1;
}
}
// strip leading/trailing whitespace (since we always seem to get a couple newlines)
- LLStringUtil::trim(rawMessage);
+ LLStringUtil::trim(message);
-// LL_DEBUGS("Voice") << " stripped message = \n" << rawMessage << LL_ENDL;
+// LL_DEBUGS("Voice") << " stripped message = \n" << message << LL_ENDL;
sessionState *session = findSession(sessionHandle);
if(session)
@@ -4670,24 +4812,18 @@ void LLVoiceClient::messageEvent(
quiet_chat = true;
// TODO: Question: Return busy mode response here? Or maybe when session is started instead?
}
-
- std::string fullMessage = std::string(": ") + rawMessage;
-
+
LL_DEBUGS("Voice") << "adding message, name " << session->mName << " session " << session->mIMSessionID << ", target " << session->mCallerID << LL_ENDL;
gIMMgr->addMessage(session->mIMSessionID,
session->mCallerID,
session->mName.c_str(),
- fullMessage.c_str(),
+ message.c_str(),
LLStringUtil::null, // default arg
IM_NOTHING_SPECIAL, // default arg
0, // default arg
LLUUID::null, // default arg
LLVector3::zero, // default arg
true); // prepend name and make it a link to the user's profile
-
- chat.mText = std::string("IM: ") + session->mName + std::string(": ") + rawMessage;
- // If the chat should come in quietly (i.e. we're in busy mode), pretend it's from a local agent.
- LLFloaterChat::addChat( chat, TRUE, quiet_chat );
}
}
}
@@ -4893,7 +5029,9 @@ LLVoiceClient::participantState *LLVoiceClient::sessionState::addParticipant(con
}
mParticipantsByUUID.insert(participantUUIDMap::value_type(&(result->mAvatarID), result));
-
+
+ result->mUserVolume = LLSpeakerVolumeStorage::getInstance()->getSpeakerVolume(result->mAvatarID);
+
LL_DEBUGS("Voice") << "participant \"" << result->mURI << "\" added." << LL_ENDL;
}
@@ -4965,7 +5103,7 @@ void LLVoiceClient::sessionState::removeAllParticipants()
if(!mParticipantsByUUID.empty())
{
- LL_ERRS("Voice") << "Internal error: empty URI map, non-empty UUID map" << LL_ENDL
+ LL_ERRS("Voice") << "Internal error: empty URI map, non-empty UUID map" << LL_ENDL;
}
}
@@ -4979,6 +5117,17 @@ LLVoiceClient::participantMap *LLVoiceClient::getParticipantList(void)
return result;
}
+void LLVoiceClient::getParticipantsUUIDSet(std::set<LLUUID>& participant_uuids)
+{
+ if (NULL == mAudioSession) return;
+
+ participantUUIDMap::const_iterator it = mAudioSession->mParticipantsByUUID.begin(),
+ it_end = mAudioSession->mParticipantsByUUID.end();
+ for (; it != it_end; ++it)
+ {
+ participant_uuids.insert((*(*it).first));
+ }
+}
LLVoiceClient::participantState *LLVoiceClient::sessionState::findParticipant(const std::string &uri)
{
@@ -5773,6 +5922,11 @@ void LLVoiceClient::setMuteMic(bool muted)
mMuteMic = muted;
}
+bool LLVoiceClient::getMuteMic() const
+{
+ return mMuteMic;
+}
+
void LLVoiceClient::setUserPTTState(bool ptt)
{
mUserPTTState = ptt;
@@ -5793,15 +5947,21 @@ void LLVoiceClient::setVoiceEnabled(bool enabled)
if (enabled != mVoiceEnabled)
{
mVoiceEnabled = enabled;
+ LLVoiceClientStatusObserver::EStatusType status;
+
if (enabled)
{
LLVoiceChannel::getCurrentVoiceChannel()->activate();
+ status = LLVoiceClientStatusObserver::STATUS_VOICE_ENABLED;
}
else
{
// Turning voice off looses your current channel -- this makes sure the UI isn't out of sync when you re-enable it.
LLVoiceChannel::getCurrentVoiceChannel()->deactivate();
+ status = LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED;
}
+
+ notifyStatusObservers(status);
}
}
@@ -5810,6 +5970,11 @@ bool LLVoiceClient::voiceEnabled()
return gSavedSettings.getBOOL("EnableVoiceChat") && !gSavedSettings.getBOOL("CmdLineDisableVoice");
}
+bool LLVoiceClient::voiceWorking()
+{
+ return (stateLoggedIn <= mState) && (mState <= stateLeavingSession);
+}
+
void LLVoiceClient::setLipSyncEnabled(BOOL enabled)
{
mLipSyncEnabled = enabled;
@@ -5849,6 +6014,10 @@ void LLVoiceClient::setPTTIsToggle(bool PTTIsToggle)
mPTTIsToggle = PTTIsToggle;
}
+bool LLVoiceClient::getPTTIsToggle()
+{
+ return mPTTIsToggle;
+}
void LLVoiceClient::setPTTKey(std::string &key)
{
@@ -5907,8 +6076,6 @@ void LLVoiceClient::setMicGain(F32 volume)
void LLVoiceClient::keyDown(KEY key, MASK mask)
{
-// LL_DEBUGS("Voice") << "key is " << LLKeyboard::stringFromKey(key) << LL_ENDL;
-
if (gKeyboard->getKeyRepeated(key))
{
// ignore auto-repeat keys
@@ -5917,44 +6084,39 @@ void LLVoiceClient::keyDown(KEY key, MASK mask)
if(!mPTTIsMiddleMouse)
{
- if(mPTTIsToggle)
- {
- if(key == mPTTKey)
- {
- toggleUserPTTState();
- }
- }
- else if(mPTTKey != KEY_NONE)
- {
- setUserPTTState(gKeyboard->getKeyDown(mPTTKey));
- }
+ bool down = (mPTTKey != KEY_NONE)
+ && gKeyboard->getKeyDown(mPTTKey);
+ inputUserControlState(down);
}
}
void LLVoiceClient::keyUp(KEY key, MASK mask)
{
if(!mPTTIsMiddleMouse)
{
- if(!mPTTIsToggle && (mPTTKey != KEY_NONE))
+ bool down = (mPTTKey != KEY_NONE)
+ && gKeyboard->getKeyDown(mPTTKey);
+ inputUserControlState(down);
+ }
+}
+void LLVoiceClient::inputUserControlState(bool down)
+{
+ if(mPTTIsToggle)
+ {
+ if(down) // toggle open-mic state on 'down'
{
- setUserPTTState(gKeyboard->getKeyDown(mPTTKey));
+ toggleUserPTTState();
}
}
+ else // set open-mic state as an absolute
+ {
+ setUserPTTState(down);
+ }
}
void LLVoiceClient::middleMouseState(bool down)
{
if(mPTTIsMiddleMouse)
{
- if(mPTTIsToggle)
- {
- if(down)
- {
- toggleUserPTTState();
- }
- }
- else
- {
- setUserPTTState(down);
- }
+ inputUserControlState(down);
}
}
@@ -6118,6 +6280,9 @@ void LLVoiceClient::setUserVolume(const LLUUID& id, F32 volume)
participant->mUserVolume = llclamp(ivol, 0, 400);
participant->mVolumeDirty = TRUE;
mAudioSession->mVolumeDirty = TRUE;
+
+ // store this volume setting for future sessions
+ LLSpeakerVolumeStorage::getInstance()->storeSpeakerVolume(id, participant->mUserVolume);
}
}
}
@@ -6468,7 +6633,7 @@ void LLVoiceClient::deleteSession(sessionState *session)
{
if(iter->second != session)
{
- LL_ERRS("Voice") << "Internal error: session mismatch" << LL_ENDL
+ LL_ERRS("Voice") << "Internal error: session mismatch" << LL_ENDL;
}
mSessionsByHandle.erase(iter);
}
@@ -6508,7 +6673,7 @@ void LLVoiceClient::deleteAllSessions()
if(!mSessionsByHandle.empty())
{
- LL_ERRS("Voice") << "Internal error: empty session map, non-empty handle map" << LL_ENDL
+ LL_ERRS("Voice") << "Internal error: empty session map, non-empty handle map" << LL_ENDL;
}
}
@@ -6901,11 +7066,12 @@ void LLVoiceClient::notifyFriendObservers()
void LLVoiceClient::lookupName(const LLUUID &id)
{
- gCacheName->getName(id, onAvatarNameLookup);
+ BOOL is_group = FALSE;
+ gCacheName->get(id, is_group, &LLVoiceClient::onAvatarNameLookup);
}
//static
-void LLVoiceClient::onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* user_data)
+void LLVoiceClient::onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
{
if(gVoiceClient)
{
@@ -7039,7 +7205,7 @@ class LLViewerRequiredVoiceVersion : public LLHTTPNode
if (!sAlertedUser)
{
//sAlertedUser = TRUE;
- LLNotifications::instance().add("VoiceVersionMismatch");
+ LLNotificationsUtil::add("VoiceVersionMismatch");
gSavedSettings.setBOOL("EnableVoiceChat", FALSE); // toggles listener
}
}
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index cfc336b27d..8f668dff19 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -42,8 +42,9 @@ class LLVivoxProtocolParser;
#include "v3math.h"
#include "llframetimer.h"
#include "llviewerregion.h"
-#include "llcallingcard.h" // for LLFriendObserver
+#include "m3math.h" // LLMatrix3
+class LLFriendObserver;
class LLVoiceClientParticipantObserver
{
public:
@@ -64,6 +65,11 @@ public:
STATUS_JOINED,
STATUS_LEFT_CHANNEL,
STATUS_VOICE_DISABLED,
+
+ // Adding STATUS_VOICE_ENABLED as pair status for STATUS_VOICE_DISABLED
+ // See LLVoiceClient::setVoiceEnabled()
+ STATUS_VOICE_ENABLED,
+
BEGIN_ERROR_STATUS,
ERROR_CHANNEL_FULL,
ERROR_CHANNEL_LOCKED,
@@ -178,18 +184,23 @@ static void updatePosition(void);
void setMuteMic(bool muted); // Use this to mute the local mic (for when the client is minimized, etc), ignoring user PTT state.
+ bool getMuteMic() const;
void setUserPTTState(bool ptt);
bool getUserPTTState();
void toggleUserPTTState(void);
+ void inputUserControlState(bool down); // interpret any sort of up-down mic-open control input according to ptt-toggle prefs
void setVoiceEnabled(bool enabled);
static bool voiceEnabled();
+ // Checks is voice working judging from mState
+ bool voiceWorking();
void setUsePTT(bool usePTT);
void setPTTIsToggle(bool PTTIsToggle);
+ bool getPTTIsToggle();
void setPTTKey(std::string &key);
void setEarLocation(S32 loc);
void setVoiceVolume(F32 volume);
void setMicGain(F32 volume);
- void setUserVolume(const LLUUID& id, F32 volume); // set's volume for specified agent, from 0-1 (where .5 is nominal)
+ void setUserVolume(const LLUUID& id, F32 volume); // sets volume for specified agent, from 0-1 (where .5 is nominal)
void setLipSyncEnabled(BOOL enabled);
BOOL lipSyncEnabled();
@@ -197,6 +208,9 @@ static void updatePosition(void);
void keyDown(KEY key, MASK mask);
void keyUp(KEY key, MASK mask);
void middleMouseState(bool down);
+
+ // Return the version of the Vivox library
+ std::string getAPIVersion() const { return mAPIVersion; }
/////////////////////////////
// Accessors for data related to nearby speakers
@@ -342,6 +356,7 @@ static void updatePosition(void);
participantState *findParticipantByID(const LLUUID& id);
participantMap *getParticipantList(void);
+ void getParticipantsUUIDSet(std::set<LLUUID>& participant_uuids);
typedef std::map<const std::string*, sessionState*, stringMapComparitor> sessionMap;
typedef std::set<sessionState*> sessionSet;
@@ -461,7 +476,7 @@ static void updatePosition(void);
void removeObserver(LLFriendObserver* observer);
void lookupName(const LLUUID &id);
- static void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* user_data);
+ static void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
void avatarNameResolved(const LLUUID &id, const std::string &name);
typedef std::vector<std::string> deviceList;
@@ -727,12 +742,13 @@ static std::string nameFromsipURI(const std::string &uri);
bool mVoiceEnabled;
bool mWriteInProgress;
std::string mWriteString;
- size_t mWriteOffset;
LLTimer mUpdateTimer;
BOOL mLipSyncEnabled;
+ std::string mAPIVersion;
+
typedef std::set<LLVoiceClientParticipantObserver*> observer_set_t;
observer_set_t mParticipantObservers;
diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp
index 5606398aaf..4794cab32e 100644
--- a/indra/newview/llvoicevisualizer.cpp
+++ b/indra/newview/llvoicevisualizer.cpp
@@ -42,9 +42,8 @@
#include "llvoicevisualizer.h"
#include "llviewercamera.h"
#include "llviewerobject.h"
-#include "llimagegl.h"
-#include "llviewerimage.h"
-#include "llviewerimagelist.h"
+#include "llviewertexture.h"
+#include "llviewertexturelist.h"
#include "llvoiceclient.h"
#include "llrender.h"
@@ -131,19 +130,19 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type )
const char* sound_level_img[] =
{
- "041ee5a0-cb6a-9ac5-6e49-41e9320507d5.j2c",
- "29de489d-0491-fb00-7dab-f9e686d31e83.j2c",
- "29de489d-0491-fb00-7dab-f9e686d31e83.j2c",
- "29de489d-0491-fb00-7dab-f9e686d31e83.j2c",
- "29de489d-0491-fb00-7dab-f9e686d31e83.j2c",
- "29de489d-0491-fb00-7dab-f9e686d31e83.j2c",
- "29de489d-0491-fb00-7dab-f9e686d31e83.j2c"
+ "voice_meter_dot.j2c",
+ "voice_meter_rings.j2c",
+ "voice_meter_rings.j2c",
+ "voice_meter_rings.j2c",
+ "voice_meter_rings.j2c",
+ "voice_meter_rings.j2c",
+ "voice_meter_rings.j2c"
};
for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++)
{
mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime;
- mSoundSymbol.mTexture [i] = gImageList.getImageFromFile(sound_level_img[i], FALSE, TRUE);
+ mSoundSymbol.mTexture [i] = LLViewerTextureManager::getFetchedTextureFromFile(sound_level_img[i], FALSE, LLViewerTexture::BOOST_UI);
mSoundSymbol.mWaveActive [i] = false;
mSoundSymbol.mWaveOpacity [i] = 1.0f;
mSoundSymbol.mWaveExpansion [i] = 1.0f;
@@ -157,12 +156,12 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type )
setPreferences();
// Set up our listener to get updates on all prefs values we care about.
- gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _1));
- gSavedSettings.getControl("LipSyncOohAahRate")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _1));
- gSavedSettings.getControl("LipSyncOoh")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _1));
- gSavedSettings.getControl("LipSyncAah")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _1));
- gSavedSettings.getControl("LipSyncOohPowerTransfer")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _1));
- gSavedSettings.getControl("LipSyncAahPowerTransfer")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _1));
+ gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2));
+ gSavedSettings.getControl("LipSyncOohAahRate")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2));
+ gSavedSettings.getControl("LipSyncOoh")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2));
+ gSavedSettings.getControl("LipSyncAah")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2));
+ gSavedSettings.getControl("LipSyncOohPowerTransfer")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2));
+ gSavedSettings.getControl("LipSyncAahPowerTransfer")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2));
sPrefsInitialized = true;
}
@@ -370,8 +369,9 @@ void LLVoiceVisualizer::render()
//-------------------------------------------------------------
// create coordinates of the geometry for the dot
//-------------------------------------------------------------
- LLVector3 l = LLViewerCamera::getInstance()->getLeftAxis() * DOT_SIZE;
- LLVector3 u = LLViewerCamera::getInstance()->getUpAxis() * DOT_SIZE;
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
+ LLVector3 l = camera->getLeftAxis() * DOT_SIZE;
+ LLVector3 u = camera->getUpAxis() * DOT_SIZE;
LLVector3 bottomLeft = mSoundSymbol.mPosition + l - u;
LLVector3 bottomRight = mSoundSymbol.mPosition - l - u;
@@ -497,8 +497,8 @@ void LLVoiceVisualizer::render()
F32 width = i * WAVE_WIDTH_SCALE * mSoundSymbol.mWaveExpansion[i];
F32 height = i * WAVE_HEIGHT_SCALE * mSoundSymbol.mWaveExpansion[i];
- LLVector3 l = LLViewerCamera::getInstance()->getLeftAxis() * width;
- LLVector3 u = LLViewerCamera::getInstance()->getUpAxis() * height;
+ LLVector3 l = camera->getLeftAxis() * width;
+ LLVector3 u = camera->getUpAxis() * height;
LLVector3 bottomLeft = mSoundSymbol.mPosition + l - u;
LLVector3 bottomRight = mSoundSymbol.mPosition - l - u;
diff --git a/indra/newview/llvoicevisualizer.h b/indra/newview/llvoicevisualizer.h
index 0cbf24b786..1887849300 100644
--- a/indra/newview/llvoicevisualizer.h
+++ b/indra/newview/llvoicevisualizer.h
@@ -121,7 +121,7 @@ class LLVoiceVisualizer : public LLHUDEffect
bool mWaveActive [ NUM_VOICE_SYMBOL_WAVES ];
F64 mWaveFadeOutStartTime [ NUM_VOICE_SYMBOL_WAVES ];
F32 mWaveOpacity [ NUM_VOICE_SYMBOL_WAVES ];
- LLPointer<LLImageGL> mTexture [ NUM_VOICE_SYMBOL_WAVES ];
+ LLPointer<LLViewerFetchedTexture> mTexture [ NUM_VOICE_SYMBOL_WAVES ];
bool mActive;
LLVector3 mPosition;
};
diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp
index 29036f4947..139d2fbd88 100644
--- a/indra/newview/llvopartgroup.cpp
+++ b/indra/newview/llvopartgroup.cpp
@@ -108,7 +108,7 @@ void LLVOPartGroup::setPixelAreaAndAngle(LLAgent &agent)
}
}
-void LLVOPartGroup::updateTextures(LLAgent &agent)
+void LLVOPartGroup::updateTextures()
{
// Texture stats for particles need to be updated in a different way...
}
@@ -139,9 +139,10 @@ LLVector3 LLVOPartGroup::getCameraPosition() const
return gAgent.getCameraPositionAgent();
}
+static LLFastTimer::DeclareTimer FTM_UPDATE_PARTICLES("Update Particles");
BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)
{
- LLFastTimer ftm(LLFastTimer::FTM_UPDATE_PARTICLES);
+ LLFastTimer ftm(FTM_UPDATE_PARTICLES);
dirtySpatialGroup();
@@ -154,6 +155,11 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)
group = drawable->getSpatialGroup();
}
+ if (group && group->isVisible())
+ {
+ dirtySpatialGroup(TRUE);
+ }
+
if (!num_parts)
{
if (group && drawable->getNumFaces())
@@ -243,6 +249,12 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)
facep->mCenterLocal = part->mPosAgent;
facep->setFaceColor(part->mColor);
facep->setTexture(part->mImagep);
+
+ //check if this particle texture is replaced by a parcel media texture.
+ if(part->mImagep.notNull() && part->mImagep->hasParcelMedia())
+ {
+ part->mImagep->getParcelMedia()->addMediaToFace(facep) ;
+ }
mPixelArea = tot_area * pixel_meter_ratio;
const F32 area_scale = 10.f; // scale area to increase priority a bit
@@ -352,12 +364,11 @@ U32 LLVOPartGroup::getPartitionType() const
}
LLParticlePartition::LLParticlePartition()
-: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK)
+: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB)
{
mRenderPass = LLRenderPass::PASS_ALPHA;
mDrawableType = LLPipeline::RENDER_TYPE_PARTICLES;
mPartitionType = LLViewerRegion::PARTITION_PARTICLE;
- mBufferUsage = GL_DYNAMIC_DRAW_ARB;
mSlopRatio = 0.f;
mLODPeriod = 1;
}
@@ -375,6 +386,7 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co
mFaceList.clear();
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
{
LLDrawable* drawablep = *i;
@@ -404,7 +416,7 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co
}
count++;
- facep->mDistance = (facep->mCenterLocal - LLViewerCamera::getInstance()->getOrigin()) * LLViewerCamera::getInstance()->getAtAxis();
+ facep->mDistance = (facep->mCenterLocal - camera->getOrigin()) * camera->getAtAxis();
obj->mDepth += facep->mDistance;
mFaceList.push_back(facep);
@@ -416,12 +428,15 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co
}
}
+static LLFastTimer::DeclareTimer FTM_REBUILD_GRASS_VB("Grass VB");
+static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_VB("Particle VB");
+
void LLParticlePartition::getGeometry(LLSpatialGroup* group)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
LLFastTimer ftm(mDrawableType == LLPipeline::RENDER_TYPE_GRASS ?
- LLFastTimer::FTM_REBUILD_GRASS_VB :
- LLFastTimer::FTM_REBUILD_PARTICLE_VB);
+ FTM_REBUILD_GRASS_VB :
+ FTM_REBUILD_PARTICLE_VB);
std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater());
@@ -481,7 +496,9 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
U32 end = start + facep->getGeomCount()-1;
U32 offset = facep->getIndicesStart();
U32 count = facep->getIndicesCount();
- LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), buffer, fullbright);
+ LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(),
+ //facep->getTexture(),
+ buffer, fullbright);
info->mExtents[0] = group->mObjectExtents[0];
info->mExtents[1] = group->mObjectExtents[1];
info->mVSize = vsize;
diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h
index 3dc3292992..18583b4be9 100644
--- a/indra/newview/llvopartgroup.h
+++ b/indra/newview/llvopartgroup.h
@@ -61,7 +61,7 @@ public:
virtual U32 getPartitionType() const;
/*virtual*/ void setPixelAreaAndAngle(LLAgent &agent);
- /*virtual*/ void updateTextures(LLAgent &agent);
+ /*virtual*/ void updateTextures();
/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index c3366cad90..5ff8f0d267 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -49,7 +49,7 @@
#include "llglheaders.h"
#include "llsky.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "llworld.h"
@@ -212,8 +212,8 @@ void LLSkyTex::init()
for (S32 i = 0; i < 2; ++i)
{
- mImageGL[i] = new LLImageGL(FALSE);
- mImageGL[i]->setAddressMode(LLTexUnit::TAM_CLAMP);
+ mTexture[i] = LLViewerTextureManager::getLocalTexture(FALSE);
+ mTexture[i]->setAddressMode(LLTexUnit::TAM_CLAMP);
mImageRaw[i] = new LLImageRaw(sResolution, sResolution, sComponents);
initEmpty(i);
@@ -222,16 +222,16 @@ void LLSkyTex::init()
void LLSkyTex::cleanupGL()
{
- mImageGL[0] = NULL;
- mImageGL[1] = NULL;
+ mTexture[0] = NULL;
+ mTexture[1] = NULL;
}
void LLSkyTex::restoreGL()
{
for (S32 i = 0; i < 2; i++)
{
- mImageGL[i] = new LLImageGL(FALSE);
- mImageGL[i]->setAddressMode(LLTexUnit::TAM_CLAMP);
+ mTexture[i] = LLViewerTextureManager::getLocalTexture(FALSE);
+ mTexture[i]->setAddressMode(LLTexUnit::TAM_CLAMP);
}
}
@@ -289,13 +289,13 @@ void LLSkyTex::create(const F32 brightness)
void LLSkyTex::createGLImage(S32 which)
{
- mImageGL[which]->createGLTexture(0, mImageRaw[which]);
- mImageGL[which]->setAddressMode(LLTexUnit::TAM_CLAMP);
+ mTexture[which]->createGLTexture(0, mImageRaw[which], 0, TRUE, LLViewerTexture::LOCAL);
+ mTexture[which]->setAddressMode(LLTexUnit::TAM_CLAMP);
}
void LLSkyTex::bindTexture(BOOL curr)
{
- gGL.getTexUnit(0)->bind(mImageGL[getWhich(curr)]);
+ gGL.getTexUnit(0)->bind(mTexture[getWhich(curr)]);
}
/***************************************
@@ -376,11 +376,11 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
mSun.setIntensity(SUN_INTENSITY);
mMoon.setIntensity(0.1f * SUN_INTENSITY);
- mSunTexturep = gImageList.getImage(gSunTextureID, TRUE, TRUE);
+ mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLViewerTexture::BOOST_UI);
mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
- mMoonTexturep = gImageList.getImage(gMoonTextureID, TRUE, TRUE);
+ mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLViewerTexture::BOOST_UI);
mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
- mBloomTexturep = gImageList.getImage(IMG_BLOOM1);
+ mBloomTexturep = LLViewerTextureManager::getFetchedTexture(IMG_BLOOM1);
mBloomTexturep->setNoDelete() ;
mBloomTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
@@ -390,7 +390,7 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
LLVOSky::~LLVOSky()
{
- // Don't delete images - it'll get deleted by gImageList on shutdown
+ // Don't delete images - it'll get deleted by gTextureList on shutdown
// This needs to be done for each texture
mCubeMap = NULL;
@@ -472,11 +472,11 @@ void LLVOSky::restoreGL()
{
mSkyTex[i].restoreGL();
}
- mSunTexturep = gImageList.getImage(gSunTextureID, TRUE, TRUE);
+ mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLViewerTexture::BOOST_UI);
mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
- mMoonTexturep = gImageList.getImage(gMoonTextureID, TRUE, TRUE);
+ mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLViewerTexture::BOOST_UI);
mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
- mBloomTexturep = gImageList.getImage(IMG_BLOOM1);
+ mBloomTexturep = LLViewerTextureManager::getFetchedTexture(IMG_BLOOM1);
mBloomTexturep->setNoDelete() ;
mBloomTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
@@ -965,7 +965,7 @@ void LLVOSky::calcAtmospherics(void)
// and vary_sunlight will work properly with moon light
F32 lighty = unclamped_lightnorm[1];
- if(lighty < NIGHTTIME_ELEVATION_COS)
+ if(lighty < LLSky::NIGHTTIME_ELEVATION_COS)
{
lighty = -lighty;
}
@@ -1095,10 +1095,10 @@ BOOL LLVOSky::updateSky()
mLastTotalAmbient.mV[2] - mTotalAmbient.mV[2]);
if ( mForceUpdate
- || ((dot_lighting < LIGHT_DIRECTION_THRESHOLD)
+ || (((dot_lighting < LIGHT_DIRECTION_THRESHOLD)
|| (delta_color.length() > COLOR_CHANGE_THRESHOLD)
|| !mInitialized)
- && !direction.isExactlyZero())
+ && !direction.isExactlyZero()))
{
mLastLightingDirection = direction;
mLastTotalAmbient = mTotalAmbient;
@@ -1180,7 +1180,7 @@ BOOL LLVOSky::updateSky()
return TRUE;
}
-void LLVOSky::updateTextures(LLAgent &agent)
+void LLVOSky::updateTextures()
{
if (mSunTexturep)
{
@@ -1197,8 +1197,6 @@ LLDrawable *LLVOSky::createDrawable(LLPipeline *pipeline)
LLDrawPoolSky *poolp = (LLDrawPoolSky*) gPipeline.getPool(LLDrawPool::POOL_SKY);
poolp->setSkyTex(mSkyTex);
- poolp->setSun(&mSun);
- poolp->setMoon(&mMoon);
mDrawable->setRenderType(LLPipeline::RENDER_TYPE_SKY);
for (S32 i = 0; i < 6; ++i)
@@ -1215,7 +1213,7 @@ LLDrawable *LLVOSky::createDrawable(LLPipeline *pipeline)
//by bao
//fake vertex buffer updating
-//to guaranttee at least updating one VBO buffer every frame
+//to guarantee at least updating one VBO buffer every frame
//to walk around the bug caused by ATI card --> DEV-3855
//
void LLVOSky::createDummyVertexBuffer()
@@ -1233,6 +1231,8 @@ void LLVOSky::createDummyVertexBuffer()
}
}
+static LLFastTimer::DeclareTimer FTM_RENDER_FAKE_VBO_UPDATE("Fake VBO Update");
+
void LLVOSky::updateDummyVertexBuffer()
{
if(!LLVertexBuffer::sEnableVBOs)
@@ -1244,7 +1244,7 @@ void LLVOSky::updateDummyVertexBuffer()
return ;
}
- LLFastTimer t(LLFastTimer::FTM_RENDER_FAKE_VBO_UPDATE) ;
+ LLFastTimer t(FTM_RENDER_FAKE_VBO_UPDATE) ;
if(!mFace[FACE_DUMMY] || mFace[FACE_DUMMY]->mVertexBuffer.isNull())
createDummyVertexBuffer() ;
@@ -1257,10 +1257,11 @@ void LLVOSky::updateDummyVertexBuffer()
//----------------------------------
//end of fake vertex buffer updating
//----------------------------------
+static LLFastTimer::DeclareTimer FTM_GEO_SKY("Sky Geometry");
BOOL LLVOSky::updateGeometry(LLDrawable *drawable)
{
- LLFastTimer ftm(LLFastTimer::FTM_GEO_SKY);
+ LLFastTimer ftm(FTM_GEO_SKY);
if (mFace[FACE_REFLECTION] == NULL)
{
LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER);
diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h
index 5e23065153..ef74324e58 100644
--- a/indra/newview/llvosky.h
+++ b/indra/newview/llvosky.h
@@ -36,7 +36,7 @@
#include "stdtypes.h"
#include "v3color.h"
#include "v4coloru.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
#include "llviewerobject.h"
#include "llframetimer.h"
@@ -122,7 +122,7 @@ class LLSkyTex
private:
static S32 sResolution;
static S32 sComponents;
- LLPointer<LLImageGL> mImageGL[2];
+ LLPointer<LLViewerTexture> mTexture[2];
LLPointer<LLImageRaw> mImageRaw[2];
LLColor4 *mSkyData;
LLVector3 *mSkyDirs; // Cache of sky direction vectors
@@ -147,7 +147,7 @@ protected:
static S32 getResolution() { return sResolution; }
static S32 getCurrent() { return sCurrent; }
- static S32 stepCurrent() { return (sCurrent = ++sCurrent % 2); }
+ static S32 stepCurrent() { return (sCurrent = (sCurrent + 1) % 2); }
static S32 getNext() { return ((sCurrent+1) % 2); }
static S32 getWhich(const BOOL curr) { return curr ? sCurrent : getNext(); }
@@ -492,7 +492,7 @@ public:
// Graphical stuff for objects - maybe broken out into render class
// later?
- /*virtual*/ void updateTextures(LLAgent &agent);
+ /*virtual*/ void updateTextures();
/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
@@ -567,9 +567,9 @@ public:
BOOL isReflFace(const LLFace* face) const { return face == mFace[FACE_REFLECTION]; }
LLFace* getReflFace() const { return mFace[FACE_REFLECTION]; }
- LLViewerImage* getSunTex() const { return mSunTexturep; }
- LLViewerImage* getMoonTex() const { return mMoonTexturep; }
- LLViewerImage* getBloomTex() const { return mBloomTexturep; }
+ LLViewerTexture* getSunTex() const { return mSunTexturep; }
+ LLViewerTexture* getMoonTex() const { return mMoonTexturep; }
+ LLViewerTexture* getBloomTex() const { return mBloomTexturep; }
void forceSkyUpdate(void) { mForceUpdate = TRUE; }
public:
@@ -579,9 +579,9 @@ public:
protected:
~LLVOSky();
- LLPointer<LLViewerImage> mSunTexturep;
- LLPointer<LLViewerImage> mMoonTexturep;
- LLPointer<LLViewerImage> mBloomTexturep;
+ LLPointer<LLViewerFetchedTexture> mSunTexturep;
+ LLPointer<LLViewerFetchedTexture> mMoonTexturep;
+ LLPointer<LLViewerFetchedTexture> mBloomTexturep;
static S32 sResolution;
static S32 sTileResX;
diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp
index 4980b50de4..ef7b161003 100644
--- a/indra/newview/llvosurfacepatch.cpp
+++ b/indra/newview/llvosurfacepatch.cpp
@@ -134,7 +134,7 @@ void LLVOSurfacePatch::setPixelAreaAndAngle(LLAgent &agent)
}
-void LLVOSurfacePatch::updateTextures(LLAgent &agent)
+void LLVOSurfacePatch::updateTextures()
{
}
@@ -176,12 +176,21 @@ LLDrawable *LLVOSurfacePatch::createDrawable(LLPipeline *pipeline)
return mDrawable;
}
+static LLFastTimer::DeclareTimer FTM_UPDATE_TERRAIN("Update Terrain");
+
+void LLVOSurfacePatch::updateGL()
+{
+ if (mPatchp)
+ {
+ mPatchp->updateGL();
+ }
+}
BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable)
{
- LLFastTimer ftm(LLFastTimer::FTM_UPDATE_TERRAIN);
+ LLFastTimer ftm(FTM_UPDATE_TERRAIN);
- dirtySpatialGroup();
+ dirtySpatialGroup(TRUE);
S32 min_comp, max_comp, range;
min_comp = lltrunc(mPatchp->getMinComposition());
@@ -1013,12 +1022,10 @@ U32 LLVOSurfacePatch::getPartitionType() const
}
LLTerrainPartition::LLTerrainPartition()
-: LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK)
+: LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK, FALSE, GL_DYNAMIC_DRAW_ARB)
{
mOcclusionEnabled = FALSE;
- mRenderByGroup = FALSE;
mInfiniteFarClip = TRUE;
- mBufferUsage = GL_DYNAMIC_DRAW_ARB;
mDrawableType = LLPipeline::RENDER_TYPE_TERRAIN;
mPartitionType = LLViewerRegion::PARTITION_TERRAIN;
}
@@ -1028,9 +1035,10 @@ LLVertexBuffer* LLTerrainPartition::createVertexBuffer(U32 type_mask, U32 usage)
return new LLVertexBufferTerrain();
}
+static LLFastTimer::DeclareTimer FTM_REBUILD_TERRAIN_VB("Terrain VB");
void LLTerrainPartition::getGeometry(LLSpatialGroup* group)
{
- LLFastTimer ftm(LLFastTimer::FTM_REBUILD_TERRAIN_VB);
+ LLFastTimer ftm(FTM_REBUILD_TERRAIN_VB);
LLVertexBuffer* buffer = group->mVertexBuffer;
diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h
index 2dd8651899..10a5888526 100644
--- a/indra/newview/llvosurfacepatch.h
+++ b/indra/newview/llvosurfacepatch.h
@@ -64,6 +64,7 @@ public:
virtual U32 getPartitionType() const;
/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
+ /*virtual*/ void updateGL();
/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
/*virtual*/ BOOL updateLOD();
/*virtual*/ void updateFaceSize(S32 idx);
@@ -74,7 +75,7 @@ public:
LLStrider<LLVector2> &texCoords1p,
LLStrider<U16> &indicesp);
- /*virtual*/ void updateTextures(LLAgent &agent);
+ /*virtual*/ void updateTextures();
/*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area
/*virtual*/ void updateSpatialExtents(LLVector3& newMin, LLVector3& newMax);
diff --git a/indra/newview/llvotextbubble.cpp b/indra/newview/llvotextbubble.cpp
index de69aac037..75beab519e 100644
--- a/indra/newview/llvotextbubble.cpp
+++ b/indra/newview/llvotextbubble.cpp
@@ -39,11 +39,10 @@
#include "llprimitive.h"
#include "llrendersphere.h"
-#include "llagent.h"
#include "llbox.h"
#include "lldrawable.h"
#include "llface.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llvolume.h"
#include "pipeline.h"
#include "llviewerregion.h"
@@ -116,7 +115,7 @@ BOOL LLVOTextBubble::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
}
-void LLVOTextBubble::updateTextures(LLAgent &agent)
+void LLVOTextBubble::updateTextures()
{
// Update the image levels of all textures...
@@ -125,7 +124,7 @@ void LLVOTextBubble::updateTextures(LLAgent &agent)
const LLTextureEntry *te = getTE(i);
F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT);
texel_area_ratio = llclamp(texel_area_ratio, .125f, 16.f);
- LLViewerImage *imagep = getTEImage(i);
+ LLViewerTexture *imagep = getTEImage(i);
if (imagep)
{
imagep->addTextureStats(mPixelArea / texel_area_ratio);
@@ -142,9 +141,9 @@ LLDrawable *LLVOTextBubble::createDrawable(LLPipeline *pipeline)
for (U32 i = 0; i < getNumTEs(); i++)
{
- LLViewerImage *imagep;
+ LLViewerTexture *imagep;
const LLTextureEntry *texture_entry = getTE(i);
- imagep = gImageList.getImage(texture_entry->getID());
+ imagep = LLViewerTextureManager::getFetchedTexture(texture_entry->getID());
mDrawable->addFace((LLFacePool*) NULL, imagep);
}
@@ -194,7 +193,7 @@ BOOL LLVOTextBubble::updateGeometry(LLDrawable *drawable)
{
LLFace *face = drawable->getFace(i);
face->setTEOffset(i);
- face->setTexture(LLViewerImage::sSmokeImagep);
+ face->setTexture(LLViewerFetchedTexture::sSmokeImagep);
face->setState(LLFace::FULLBRIGHT);
}
diff --git a/indra/newview/llvotextbubble.h b/indra/newview/llvotextbubble.h
index 45d4df2a7e..7f84dbf631 100644
--- a/indra/newview/llvotextbubble.h
+++ b/indra/newview/llvotextbubble.h
@@ -44,7 +44,7 @@ public:
/*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate.
/*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);
- /*virtual*/ void updateTextures(LLAgent &agent);
+ /*virtual*/ void updateTextures();
/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
/*virtual*/ BOOL updateLOD();
diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp
index 3fd5054fd1..24f1c4bd24 100644
--- a/indra/newview/llvotree.cpp
+++ b/indra/newview/llvotree.cpp
@@ -48,14 +48,14 @@
#include "lldrawable.h"
#include "llface.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "llworld.h"
#include "noise.h"
#include "pipeline.h"
#include "llspatialpartition.h"
-#include "llviewerwindow.h"
+#include "llnotificationsutil.h"
extern LLPipeline gPipeline;
@@ -257,7 +257,7 @@ void LLVOTree::initClass()
{
LLSD args;
args["SPECIES"] = err;
- LLNotifications::instance().add("ErrorUndefinedTrees", args);
+ LLNotificationsUtil::add("ErrorUndefinedTrees", args);
}
};
@@ -311,11 +311,7 @@ U32 LLVOTree::processUpdateMessage(LLMessageSystem *mesgsys,
//
// Load Species-Specific data
//
- mTreeImagep = gImageList.getImage(sSpeciesTable[mSpecies]->mTextureID);
- if (mTreeImagep)
- {
- gGL.getTexUnit(0)->bind(mTreeImagep.get());
- }
+ mTreeImagep = LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
mBranchLength = sSpeciesTable[mSpecies]->mBranchLength;
mTrunkLength = sSpeciesTable[mSpecies]->mTrunkLength;
mLeafScale = sSpeciesTable[mSpecies]->mLeafScale;
@@ -467,7 +463,7 @@ void LLVOTree::setPixelAreaAndAngle(LLAgent &agent)
#endif
}
-void LLVOTree::updateTextures(LLAgent &agent)
+void LLVOTree::updateTextures()
{
if (mTreeImagep)
{
@@ -504,9 +500,11 @@ LLDrawable* LLVOTree::createDrawable(LLPipeline *pipeline)
const S32 LEAF_INDICES = 24;
const S32 LEAF_VERTICES = 16;
+static LLFastTimer::DeclareTimer FTM_UPDATE_TREE("Update Tree");
+
BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
{
- LLFastTimer ftm(LLFastTimer::FTM_UPDATE_TREE);
+ LLFastTimer ftm(FTM_UPDATE_TREE);
if (mReferenceBuffer.isNull() || mDrawable->getFace(0)->mVertexBuffer.isNull())
{
@@ -1303,9 +1301,8 @@ U32 LLVOTree::getPartitionType() const
}
LLTreePartition::LLTreePartition()
-: LLSpatialPartition(0)
+: LLSpatialPartition(0, FALSE, 0)
{
- mRenderByGroup = FALSE;
mDrawableType = LLPipeline::RENDER_TYPE_TREE;
mPartitionType = LLViewerRegion::PARTITION_TREE;
mSlopRatio = 0.f;
diff --git a/indra/newview/llvotree.h b/indra/newview/llvotree.h
index 42a6d54f62..feac9e0675 100644
--- a/indra/newview/llvotree.h
+++ b/indra/newview/llvotree.h
@@ -39,7 +39,7 @@
class LLFace;
class LLDrawPool;
-
+class LLViewerFetchedTexture;
class LLVOTree : public LLViewerObject
{
@@ -69,7 +69,7 @@ public:
// Graphical stuff for objects - maybe broken out into render class later?
/*virtual*/ void render(LLAgent &agent);
/*virtual*/ void setPixelAreaAndAngle(LLAgent &agent);
- /*virtual*/ void updateTextures(LLAgent &agent);
+ /*virtual*/ void updateTextures();
/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
@@ -160,7 +160,7 @@ protected:
LLVector3 mWind;
LLPointer<LLVertexBuffer> mReferenceBuffer; //reference geometry for generating tree mesh
- LLPointer<LLViewerImage> mTreeImagep; // Pointer to proper tree image
+ LLPointer<LLViewerFetchedTexture> mTreeImagep; // Pointer to proper tree image
U8 mSpecies; // Species of tree
F32 mBranchLength; // Scale (length) of tree branches
@@ -184,7 +184,7 @@ protected:
// complete rebuild when not animating
LLVector3 mLastPosition;
LLQuaternion mLastRotation;
-
+
U32 mFrameCount;
typedef std::map<U32, TreeSpeciesData*> SpeciesMap;
diff --git a/indra/newview/llvotreenew.h b/indra/newview/llvotreenew.h
index 02f6d3a056..426470101d 100644
--- a/indra/newview/llvotreenew.h
+++ b/indra/newview/llvotreenew.h
@@ -41,7 +41,7 @@
#include "llstrider.h"
#include "v2math.h"
#include "v3math.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
class LLFace;
class LLDrawPool;
@@ -156,7 +156,7 @@ public:
/*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);
/*virtual*/ void render(LLAgent &agent);
- /*virtual*/ void updateTextures(LLAgent &agent);
+ /*virtual*/ void updateTextures();
/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
@@ -187,7 +187,7 @@ public:
//LLTreeParams mParams;
U8 mSpecies;
- LLPointer<LLViewerImage> mTreeImagep;
+ LLPointer<LLViewerTexture> mTreeImagep;
LLMatrix4 mTrunkFlareFrames[MAX_FLARE];
F32 mSegSplitsError[3];
U32 mRandOffset[MAX_LEVELS];
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 8f11661b30..295c0c8010 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -46,38 +46,131 @@
#include "llvolumemessage.h"
#include "material_codes.h"
#include "message.h"
+#include "llpluginclassmedia.h" // for code in the mediaEvent handler
#include "object_flags.h"
-#include "llagent.h"
+#include "llagentconstants.h"
#include "lldrawable.h"
#include "lldrawpoolbump.h"
#include "llface.h"
#include "llspatialpartition.h"
-
-// TEMP HACK ventrella
#include "llhudmanager.h"
#include "llflexibleobject.h"
-
#include "llsky.h"
+#include "lltexturefetch.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewerregion.h"
#include "llviewertextureanim.h"
#include "llworld.h"
#include "llselectmgr.h"
#include "pipeline.h"
+#include "llsdutil.h"
+#include "llmediaentry.h"
+#include "llmediadataclient.h"
+#include "llagent.h"
+#include "llviewermediafocus.h"
const S32 MIN_QUIET_FRAMES_COALESCE = 30;
const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
const F32 FORCE_CULL_AREA = 8.f;
-const S32 MAX_SCULPT_REZ = 128;
+const F32 MAX_LOD_DISTANCE = 24.f;
+
BOOL gAnimateTextures = TRUE;
-extern BOOL gHideSelectedObjects;
+//extern BOOL gHideSelectedObjects;
F32 LLVOVolume::sLODFactor = 1.f;
F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop
F32 LLVOVolume::sDistanceFactor = 1.0f;
S32 LLVOVolume::sNumLODChanges = 0;
+LLPointer<LLObjectMediaDataClient> LLVOVolume::sObjectMediaClient = NULL;
+LLPointer<LLObjectMediaNavigateClient> LLVOVolume::sObjectMediaNavigateClient = NULL;
+
+static LLFastTimer::DeclareTimer FTM_GEN_TRIANGLES("Generate Triangles");
+static LLFastTimer::DeclareTimer FTM_GEN_VOLUME("Generate Volumes");
+
+// Implementation class of LLMediaDataClientObject. See llmediadataclient.h
+class LLMediaDataClientObjectImpl : public LLMediaDataClientObject
+{
+public:
+ LLMediaDataClientObjectImpl(LLVOVolume *obj, bool isNew) : mObject(obj), mNew(isNew) {}
+ LLMediaDataClientObjectImpl() { mObject = NULL; }
+
+ virtual U8 getMediaDataCount() const
+ { return mObject->getNumTEs(); }
+
+ virtual LLSD getMediaDataLLSD(U8 index) const
+ {
+ LLSD result;
+ LLTextureEntry *te = mObject->getTE(index);
+ if (NULL != te)
+ {
+ llassert((te->getMediaData() != NULL) == te->hasMedia());
+ if (te->getMediaData() != NULL)
+ {
+ result = te->getMediaData()->asLLSD();
+ // XXX HACK: workaround bug in asLLSD() where whitelist is not set properly
+ // See DEV-41949
+ if (!result.has(LLMediaEntry::WHITELIST_KEY))
+ {
+ result[LLMediaEntry::WHITELIST_KEY] = LLSD::emptyArray();
+ }
+ }
+ }
+ return result;
+ }
+
+ virtual LLUUID getID() const
+ { return mObject->getID(); }
+
+ virtual void mediaNavigateBounceBack(U8 index)
+ { mObject->mediaNavigateBounceBack(index); }
+
+ virtual bool hasMedia() const
+ { return mObject->hasMedia(); }
+
+ virtual void updateObjectMediaData(LLSD const &data, const std::string &version_string)
+ { mObject->updateObjectMediaData(data, version_string); }
+
+ virtual F64 getMediaInterest() const
+ {
+ F64 interest = mObject->getTotalMediaInterest();
+ if (interest < (F64)0.0)
+ {
+ // media interest not valid yet, try pixel area
+ interest = mObject->getPixelArea();
+ // HACK: force recalculation of pixel area if interest is the "magic default" of 1024.
+ if (interest == 1024.f)
+ {
+ const_cast<LLVOVolume*>(static_cast<LLVOVolume*>(mObject))->setPixelAreaAndAngle(gAgent);
+ interest = mObject->getPixelArea();
+ }
+ }
+ return interest;
+ }
+
+ virtual bool isInterestingEnough() const
+ {
+ return LLViewerMedia::isInterestingEnough(mObject, getMediaInterest());
+ }
+
+ virtual std::string getCapabilityUrl(const std::string &name) const
+ { return mObject->getRegion()->getCapability(name); }
+
+ virtual bool isDead() const
+ { return mObject->isDead(); }
+
+ virtual U32 getMediaVersion() const
+ { return LLTextureEntry::getVersionFromMediaVersionString(mObject->getMediaURL()); }
+
+ virtual bool isNew() const
+ { return mNew; }
+
+private:
+ LLPointer<LLVOVolume> mObject;
+ bool mNew;
+};
+
LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
: LLViewerObject(id, pcode, regionp),
@@ -88,12 +181,15 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re
mRelativeXformInvTrans.setIdentity();
mLOD = MIN_LOD;
- mSculptLevel = -2;
mTextureAnimp = NULL;
mVObjRadius = LLVector3(1,1,0.5f).length();
mNumFaces = 0;
mLODChanged = FALSE;
mSculptChanged = FALSE;
+ mSpotLightPriority = 0.f;
+
+ mMediaImplList.resize(getNumTEs());
+ mLastFetchedMediaVersion = -1;
}
LLVOVolume::~LLVOVolume()
@@ -102,14 +198,62 @@ LLVOVolume::~LLVOVolume()
mTextureAnimp = NULL;
delete mVolumeImpl;
mVolumeImpl = NULL;
+
+ if(!mMediaImplList.empty())
+ {
+ for(U32 i = 0 ; i < mMediaImplList.size() ; i++)
+ {
+ if(mMediaImplList[i].notNull())
+ {
+ mMediaImplList[i]->removeObject(this) ;
+ }
+ }
+ }
+}
+
+void LLVOVolume::markDead()
+{
+ if (!mDead)
+ {
+ LLMediaDataClientObject::ptr_t obj = new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false);
+ if (sObjectMediaClient) sObjectMediaClient->removeFromQueue(obj);
+ if (sObjectMediaNavigateClient) sObjectMediaNavigateClient->removeFromQueue(obj);
+
+ // Detach all media impls from this object
+ for(U32 i = 0 ; i < mMediaImplList.size() ; i++)
+ {
+ removeMediaImpl(i);
+ }
+ }
+
+ LLViewerObject::markDead();
}
// static
void LLVOVolume::initClass()
{
+ // gSavedSettings better be around
+ if (gSavedSettings.getBOOL("PrimMediaMasterEnabled"))
+ {
+ const F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay");
+ const F32 retry_timer_delay = gSavedSettings.getF32("PrimMediaRetryTimerDelay");
+ const U32 max_retries = gSavedSettings.getU32("PrimMediaMaxRetries");
+ const U32 max_sorted_queue_size = gSavedSettings.getU32("PrimMediaMaxSortedQueueSize");
+ const U32 max_round_robin_queue_size = gSavedSettings.getU32("PrimMediaMaxRoundRobinQueueSize");
+ sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries,
+ max_sorted_queue_size, max_round_robin_queue_size);
+ sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay,
+ max_retries, max_sorted_queue_size, max_round_robin_queue_size);
+ }
}
+// static
+void LLVOVolume::cleanupClass()
+{
+ sObjectMediaClient = NULL;
+ sObjectMediaNavigateClient = NULL;
+}
U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
void **user_data,
@@ -117,6 +261,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
LLDataPacker *dp)
{
LLColor4U color;
+ const S32 teDirtyBits = (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR|TEM_CHANGE_MEDIA);
// Do base class updates...
U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp);
@@ -184,10 +329,15 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
//
// Unpack texture entry data
//
- if (unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num) & (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR))
+ S32 result = unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num);
+ if (result & teDirtyBits)
{
updateTEData();
}
+ if (result & TEM_CHANGE_MEDIA)
+ {
+ retval |= MEDIA_FLAGS_CHANGED;
+ }
}
else
{
@@ -220,9 +370,16 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
// llerrs << "Bogus TE data in " << getID() << ", crashing!" << llendl;
llwarns << "Bogus TE data in " << getID() << llendl;
}
- else if (res2 & (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR))
+ else
{
- updateTEData();
+ if (res2 & teDirtyBits)
+ {
+ updateTEData();
+ }
+ if (res2 & TEM_CHANGE_MEDIA)
+ {
+ retval |= MEDIA_FLAGS_CHANGED;
+ }
}
U32 value = dp->getPassFlags();
@@ -260,14 +417,39 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
U8 tdpbuffer[1024];
LLDataPackerBinaryBuffer tdp(tdpbuffer, 1024);
mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureEntry, tdpbuffer, 0, block_num);
- if ( unpackTEMessage(tdp) & (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR))
+ S32 result = unpackTEMessage(tdp);
+ if (result & teDirtyBits)
{
updateTEData();
}
+ if (result & TEM_CHANGE_MEDIA)
+ {
+ retval |= MEDIA_FLAGS_CHANGED;
+ }
}
}
}
-
+ if (retval & (MEDIA_URL_REMOVED | MEDIA_URL_ADDED | MEDIA_URL_UPDATED | MEDIA_FLAGS_CHANGED))
+ {
+ // If only the media URL changed, and it isn't a media version URL,
+ // ignore it
+ if ( ! ( retval & (MEDIA_URL_ADDED | MEDIA_URL_UPDATED) &&
+ mMedia && ! mMedia->mMediaURL.empty() &&
+ ! LLTextureEntry::isMediaVersionString(mMedia->mMediaURL) ) )
+ {
+ // If the media changed at all, request new media data
+ LL_DEBUGS("MediaOnAPrim") << "Media update: " << getID() << ": retval=" << retval << " Media URL: " <<
+ ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL;
+ requestMediaDataUpdate(retval & MEDIA_FLAGS_CHANGED);
+ }
+ else {
+ LL_INFOS("MediaOnAPrim") << "Ignoring media update for: " << getID() << " Media URL: " <<
+ ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL;
+ }
+ }
+ // ...and clean up any media impls
+ cleanUpMediaImpls();
+
return retval;
}
@@ -317,11 +499,6 @@ void LLVOVolume::animateTextures()
te->getScale(&scale_s, &scale_t);
}
- LLVector3 scale(scale_s, scale_t, 1.f);
- LLVector3 trans(off_s+0.5f, off_t+0.5f, 0.f);
- LLQuaternion quat;
- quat.setQuat(rot, 0, 0, -1.f);
-
if (!facep->mTextureMatrix)
{
facep->mTextureMatrix = new LLMatrix4();
@@ -329,7 +506,43 @@ void LLVOVolume::animateTextures()
LLMatrix4& tex_mat = *facep->mTextureMatrix;
tex_mat.setIdentity();
- tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f));
+ LLVector3 trans ;
+
+ if(facep->isAtlasInUse())
+ {
+ //
+ //if use atlas for animated texture
+ //apply the following transform to the animation matrix.
+ //
+
+ F32 tcoord_xoffset = 0.f ;
+ F32 tcoord_yoffset = 0.f ;
+ F32 tcoord_xscale = 1.f ;
+ F32 tcoord_yscale = 1.f ;
+ if(facep->isAtlasInUse())
+ {
+ const LLVector2* tmp = facep->getTexCoordOffset() ;
+ tcoord_xoffset = tmp->mV[0] ;
+ tcoord_yoffset = tmp->mV[1] ;
+
+ tmp = facep->getTexCoordScale() ;
+ tcoord_xscale = tmp->mV[0] ;
+ tcoord_yscale = tmp->mV[1] ;
+ }
+ trans.set(LLVector3(tcoord_xoffset + tcoord_xscale * (off_s+0.5f), tcoord_yoffset + tcoord_yscale * (off_t+0.5f), 0.f));
+
+ tex_mat.translate(LLVector3(-(tcoord_xoffset + tcoord_xscale * 0.5f), -(tcoord_yoffset + tcoord_yscale * 0.5f), 0.f));
+ }
+ else //non atlas
+ {
+ trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f));
+ tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f));
+ }
+
+ LLVector3 scale(scale_s, scale_t, 1.f);
+ LLQuaternion quat;
+ quat.setQuat(rot, 0, 0, -1.f);
+
tex_mat.rotate(quat);
LLMatrix4 mat;
@@ -406,28 +619,32 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
return TRUE;
}
-void LLVOVolume::updateTextures(LLAgent &agent)
+void LLVOVolume::updateTextures()
{
const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds
- if (mDrawable.notNull() && mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME)
+ if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME)
{
- if (mDrawable->isVisible())
- {
- updateTextures();
- }
+ updateTextureVirtualSize();
}
}
-void LLVOVolume::updateTextures()
+void LLVOVolume::updateTextureVirtualSize()
{
// Update the pixel area of all faces
+ if(mDrawable.isNull() || !mDrawable->isVisible())
+ {
+ return ;
+ }
+
if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE))
{
return;
}
-
- if (LLViewerImage::sDontLoadVolumeTextures || mDrawable.isNull()) // || !mDrawable->isVisible())
+
+ static LLCachedControl<bool> dont_load_textures(gSavedSettings,"TextureDisable");
+
+ if (dont_load_textures || LLAppViewer::getTextureFetch()->mDebugPause) // || !mDrawable->isVisible())
{
return;
}
@@ -439,46 +656,45 @@ void LLVOVolume::updateTextures()
const S32 num_faces = mDrawable->getNumFaces();
F32 min_vsize=999999999.f, max_vsize=0.f;
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
for (S32 i = 0; i < num_faces; i++)
{
LLFace* face = mDrawable->getFace(i);
const LLTextureEntry *te = face->getTextureEntry();
- LLViewerImage *imagep = face->getTexture();
- if (!imagep || !te ||
+ LLViewerTexture *imagep = face->getTexture();
+ if (!imagep || !te ||
face->mExtents[0] == face->mExtents[1])
{
continue;
}
F32 vsize;
-
+ F32 old_size = face->getVirtualSize();
+
if (isHUDAttachment())
{
- F32 area = (F32) LLViewerCamera::getInstance()->getScreenPixelArea();
+ F32 area = (F32) camera->getScreenPixelArea();
vsize = area;
- imagep->setBoostLevel(LLViewerImage::BOOST_HUD);
+ imagep->setBoostLevel(LLViewerTexture::BOOST_HUD);
face->setPixelArea(area); // treat as full screen
}
else
{
- vsize = getTextureVirtualSize(face);
+ vsize = face->getTextureVirtualSize();
}
- mPixelArea = llmax(mPixelArea, face->getPixelArea());
-
- F32 old_size = face->getVirtualSize();
+ mPixelArea = llmax(mPixelArea, face->getPixelArea());
if (face->mTextureMatrix != NULL)
{
- if (vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE ||
- vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE)
+ if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) ||
+ (vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE))
{
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, FALSE);
}
}
face->setVirtualSize(vsize);
- imagep->addTextureStats(vsize);
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
{
if (vsize < min_vsize) min_vsize = vsize;
@@ -486,10 +702,14 @@ void LLVOVolume::updateTextures()
}
else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
{
- F32 pri = imagep->getDecodePriority();
- pri = llmax(pri, 0.0f);
- if (pri < min_vsize) min_vsize = pri;
- if (pri > max_vsize) max_vsize = pri;
+ LLViewerFetchedTexture* img = LLViewerTextureManager::staticCastToFetchedTexture(imagep) ;
+ if(img)
+ {
+ F32 pri = img->getDecodePriority();
+ pri = llmax(pri, 0.0f);
+ if (pri < min_vsize) min_vsize = pri;
+ if (pri > max_vsize) max_vsize = pri;
+ }
}
else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA))
{
@@ -503,45 +723,71 @@ void LLVOVolume::updateTextures()
{
LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
LLUUID id = sculpt_params->getSculptTexture();
- mSculptTexture = gImageList.getImage(id);
+ mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
if (mSculptTexture.notNull())
{
- S32 lod = llmin(mLOD, 3);
- F32 lodf = ((F32)(lod + 1.0f)/4.f);
- F32 tex_size = lodf * MAX_SCULPT_REZ;
- mSculptTexture->addTextureStats(2.f * tex_size * tex_size);
mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(),
- (S32)LLViewerImage::BOOST_SCULPTED));
- }
-
- S32 texture_discard = mSculptTexture->getDiscardLevel(); //try to match the texture
- S32 current_discard = mSculptLevel;
+ (S32)LLViewerTexture::BOOST_SCULPTED));
+ mSculptTexture->setForSculpt() ;
+
+ if(!mSculptTexture->isCachedRawImageReady())
+ {
+ S32 lod = llmin(mLOD, 3);
+ F32 lodf = ((F32)(lod + 1.0f)/4.f);
+ F32 tex_size = lodf * LLViewerTexture::sMaxSculptRez ;
+ mSculptTexture->addTextureStats(2.f * tex_size * tex_size, FALSE);
+
+ //if the sculpty very close to the view point, load first
+ {
+ LLVector3 lookAt = getPositionAgent() - camera->getOrigin();
+ F32 dist = lookAt.normVec() ;
+ F32 cos_angle_to_view_dir = lookAt * camera->getXAxis() ;
+ mSculptTexture->setAdditionalDecodePriority(0.8f * LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist)) ;
+ }
+ }
+
+ S32 texture_discard = mSculptTexture->getDiscardLevel(); //try to match the texture
+ S32 current_discard = getVolume() ? getVolume()->getSculptLevel() : -2 ;
- if (texture_discard >= 0 && //texture has some data available
- (texture_discard < current_discard || //texture has more data than last rebuild
- current_discard < 0)) //no previous rebuild
- {
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE);
- mSculptChanged = TRUE;
- }
+ if (texture_discard >= 0 && //texture has some data available
+ (texture_discard < current_discard || //texture has more data than last rebuild
+ current_discard < 0)) //no previous rebuild
+ {
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE);
+ mSculptChanged = TRUE;
+ }
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED))
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED))
{
setDebugText(llformat("T%d C%d V%d\n%dx%d",
- texture_discard, current_discard, getVolume()->getSculptLevel(),
- mSculptTexture->getHeight(), mSculptTexture->getWidth()));
+ texture_discard, current_discard, getVolume()->getSculptLevel(),
+ mSculptTexture->getHeight(), mSculptTexture->getWidth()));
}
+ }
}
-
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
+ if (getLightTextureID().notNull())
{
- setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize)));
+ LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
+ LLUUID id = params->getLightTexture();
+ mLightTexture = LLViewerTextureManager::getFetchedTexture(id);
+ if (mLightTexture.notNull())
+ {
+ F32 rad = getLightRadius();
+ mLightTexture->addTextureStats(gPipeline.calcPixelArea(getPositionAgent(),
+ LLVector3(rad,rad,rad),
+ *camera));
+ }
}
- else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
+
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
{
setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize)));
}
+ else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
+ {
+ setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize)));
+ }
else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA))
{
setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize)));
@@ -553,36 +799,6 @@ void LLVOVolume::updateTextures()
}
}
-F32 LLVOVolume::getTextureVirtualSize(LLFace* face)
-{
- //get area of circle around face
- LLVector3 center = face->getPositionAgent();
- LLVector3 size = (face->mExtents[1] - face->mExtents[0]) * 0.5f;
-
- F32 face_area = LLPipeline::calcPixelArea(center, size, *LLViewerCamera::getInstance());
-
- face->setPixelArea(face_area);
-
- if (face_area <= 0)
- {
- return 0.f;
- }
-
- //get area of circle in texture space
- LLVector2 tdim = face->mTexExtents[1] - face->mTexExtents[0];
- F32 texel_area = (tdim * 0.5f).lengthSquared()*3.14159f;
- if (texel_area <= 0)
- {
- // Probably animated, use default
- texel_area = 1.f;
- }
-
- //apply texel area to face area to get accurate ratio
- face_area /= llclamp(texel_area, 1.f/64.f, 16.f);
-
- return face_area;
-}
-
BOOL LLVOVolume::isActive() const
{
return !mStatic || mTextureAnimp || (mVolumeImpl && mVolumeImpl->isActive());
@@ -624,7 +840,7 @@ void LLVOVolume::setScale(const LLVector3 &scale, BOOL damped)
LLFace* LLVOVolume::addFace(S32 f)
{
const LLTextureEntry* te = getTE(f);
- LLViewerImage* imagep = getTEImage(f);
+ LLViewerTexture* imagep = getTEImage(f);
return mDrawable->addFace(te, imagep);
}
@@ -653,12 +869,12 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline)
}
updateRadius();
- mDrawable->updateDistance(*LLViewerCamera::getInstance());
+ bool force_update = true; // avoid non-alpha mDistance update being optimized away
+ mDrawable->updateDistance(*LLViewerCamera::getInstance(), force_update);
return mDrawable;
}
-
BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume)
{
// Check if we need to change implementations
@@ -699,11 +915,20 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail
if (isSculpted())
{
- mSculptTexture = gImageList.getImage(volume_params.getSculptID());
+ mSculptTexture = LLViewerTextureManager::getFetchedTexture(volume_params.getSculptID(), TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
if (mSculptTexture.notNull())
{
- sculpt();
- mSculptLevel = getVolume()->getSculptLevel();
+ //ignore sculpt GL usage since bao fixed this in a separate branch
+ if (!gGLActive)
+ {
+ gGLActive = TRUE;
+ sculpt();
+ gGLActive = FALSE;
+ }
+ else
+ {
+ sculpt();
+ }
}
}
else
@@ -718,32 +943,22 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail
// sculpt replaces generate() for sculpted surfaces
void LLVOVolume::sculpt()
-{
- U16 sculpt_height = 0;
- U16 sculpt_width = 0;
- S8 sculpt_components = 0;
- const U8* sculpt_data = NULL;
-
+{
if (mSculptTexture.notNull())
- {
- S32 discard_level;
- S32 desired_discard = 0; // lower discard levels have MUCH less resolution
-
- discard_level = desired_discard;
+ {
+ U16 sculpt_height = 0;
+ U16 sculpt_width = 0;
+ S8 sculpt_components = 0;
+ const U8* sculpt_data = NULL;
+
+ S32 discard_level = mSculptTexture->getDiscardLevel() ;
+ LLImageRaw* raw_image = mSculptTexture->getCachedRawImage() ;
S32 max_discard = mSculptTexture->getMaxDiscardLevel();
if (discard_level > max_discard)
discard_level = max_discard; // clamp to the best we can do
- S32 best_discard = mSculptTexture->getDiscardLevel();
- if (discard_level < best_discard)
- discard_level = best_discard; // clamp to what we have
-
- if (best_discard == -1)
- discard_level = -1; // and if we have nothing, set to nothing
-
-
- S32 current_discard = getVolume()->getSculptLevel();
+ S32 current_discard = getVolume()->getSculptLevel() ;
if(current_discard < -2)
{
llwarns << "WARNING!!: Current discard of sculpty at " << current_discard
@@ -764,30 +979,29 @@ void LLVOVolume::sculpt()
if (current_discard == discard_level) // no work to do here
return;
- LLPointer<LLImageRaw> raw_image = new LLImageRaw();
- BOOL is_valid = mSculptTexture->readBackRaw(discard_level, raw_image, FALSE);
-
- sculpt_height = raw_image->getHeight();
- sculpt_width = raw_image->getWidth();
- sculpt_components = raw_image->getComponents();
-
- if(is_valid)
- {
- is_valid = mSculptTexture->isValidForSculpt(discard_level, sculpt_width, sculpt_height, sculpt_components) ;
- }
- if(!is_valid)
+ if(!raw_image)
{
sculpt_width = 0;
sculpt_height = 0;
sculpt_data = NULL ;
+
+ if(LLViewerTextureManager::sTesterp)
+ {
+ LLViewerTextureManager::sTesterp->updateGrayTextureBinding();
+ }
}
else
- {
- if (raw_image->getDataSize() < sculpt_height * sculpt_width * sculpt_components)
- llerrs << "Sculpt: image data size = " << raw_image->getDataSize()
- << " < " << sculpt_height << " x " << sculpt_width << " x " <<sculpt_components << llendl;
+ {
+ sculpt_height = raw_image->getHeight();
+ sculpt_width = raw_image->getWidth();
+ sculpt_components = raw_image->getComponents();
sculpt_data = raw_image->getData();
+
+ if(LLViewerTextureManager::sTesterp)
+ {
+ mSculptTexture->updateBindStatsForTester() ;
+ }
}
getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level);
}
@@ -816,13 +1030,10 @@ BOOL LLVOVolume::calcLOD()
return FALSE;
}
- //update face texture sizes on lod calculation
- updateTextures();
-
S32 cur_detail = 0;
F32 radius = getVolume()->mLODScaleBias.scaledVec(getScale()).length();
- F32 distance = mDrawable->mDistanceWRTCamera;
+ F32 distance = llmin(mDrawable->mDistanceWRTCamera, MAX_LOD_DISTANCE);
distance *= sDistanceFactor;
F32 rampDist = LLVOVolume::sLODFactor * 2;
@@ -836,7 +1047,7 @@ BOOL LLVOVolume::calcLOD()
}
// DON'T Compensate for field of view changing on FOV zoom.
- distance *= 3.14159f/3.f;
+ distance *= F_PI/3.f;
cur_detail = computeLODDetail(llround(distance, 0.01f),
llround(radius, 0.01f));
@@ -922,17 +1133,20 @@ void LLVOVolume::updateFaceFlags()
}
}
-void LLVOVolume::setParent(LLViewerObject* parent)
+BOOL LLVOVolume::setParent(LLViewerObject* parent)
{
+ BOOL ret = FALSE ;
if (parent != getParent())
{
- LLViewerObject::setParent(parent);
- if (mDrawable)
+ ret = LLViewerObject::setParent(parent);
+ if (ret && mDrawable)
{
gPipeline.markMoved(mDrawable);
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
}
}
+
+ return ret ;
}
// NOTE: regenFaces() MUST be followed by genTriangles()!
@@ -954,6 +1168,20 @@ void LLVOVolume::regenFaces()
facep->setTEOffset(i);
facep->setTexture(getTEImage(i));
facep->setViewerObject(this);
+
+ // If the face had media on it, this will have broken the link between the LLViewerMediaTexture and the face.
+ // Re-establish the link.
+ if((int)mMediaImplList.size() > i)
+ {
+ if(mMediaImplList[i])
+ {
+ LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[i]->getMediaTextureID()) ;
+ if(media_tex)
+ {
+ media_tex->addMediaToFace(facep) ;
+ }
+ }
+ }
}
if (!count_changed)
@@ -1111,15 +1339,18 @@ void LLVOVolume::updateRelativeXform()
}
}
+static LLFastTimer::DeclareTimer FTM_GEN_FLEX("Generate Flexies");
+static LLFastTimer::DeclareTimer FTM_UPDATE_PRIMITIVES("Update Primitives");
+
BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
{
- LLFastTimer t(LLFastTimer::FTM_UPDATE_PRIMITIVES);
+ LLFastTimer t(FTM_UPDATE_PRIMITIVES);
if (mVolumeImpl != NULL)
{
BOOL res;
{
- LLFastTimer t(LLFastTimer::FTM_GEN_FLEX);
+ LLFastTimer t(FTM_GEN_FLEX);
res = mVolumeImpl->doUpdateGeometry(drawable);
}
updateFaceFlags();
@@ -1143,14 +1374,14 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
if (mVolumeChanged)
{
- LLFastTimer ftm(LLFastTimer::FTM_GEN_VOLUME);
+ LLFastTimer ftm(FTM_GEN_VOLUME);
LLVolumeParams volume_params = getVolume()->getParams();
setVolume(volume_params, 0);
drawable->setState(LLDrawable::REBUILD_VOLUME);
}
{
- LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES);
+ LLFastTimer t(FTM_GEN_TRIANGLES);
regenFaces();
genBBoxes(FALSE);
}
@@ -1167,7 +1398,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
old_volumep = NULL ;
{
- LLFastTimer ftm(LLFastTimer::FTM_GEN_VOLUME);
+ LLFastTimer ftm(FTM_GEN_VOLUME);
LLVolumeParams volume_params = getVolume()->getParams();
setVolume(volume_params, 0);
}
@@ -1185,7 +1416,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles()
{
- LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES);
+ LLFastTimer t(FTM_GEN_TRIANGLES);
if (new_num_faces != old_num_faces)
{
regenFaces();
@@ -1199,7 +1430,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
{
compiled = TRUE;
// All it did was move or we changed the texture coordinate offset
- LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES);
+ LLFastTimer t(FTM_GEN_TRIANGLES);
genBBoxes(FALSE);
}
@@ -1242,7 +1473,47 @@ BOOL LLVOVolume::isRootEdit() const
return TRUE;
}
-void LLVOVolume::setTEImage(const U8 te, LLViewerImage *imagep)
+//virtual
+void LLVOVolume::setNumTEs(const U8 num_tes)
+{
+ const U8 old_num_tes = getNumTEs() ;
+
+ if(old_num_tes && old_num_tes < num_tes) //new faces added
+ {
+ LLViewerObject::setNumTEs(num_tes) ;
+
+ if(mMediaImplList.size() >= old_num_tes && mMediaImplList[old_num_tes -1].notNull())//duplicate the last media textures if exists.
+ {
+ mMediaImplList.resize(num_tes) ;
+ const LLTextureEntry* te = getTE(old_num_tes - 1) ;
+ for(U8 i = old_num_tes; i < num_tes ; i++)
+ {
+ setTE(i, *te) ;
+ mMediaImplList[i] = mMediaImplList[old_num_tes -1] ;
+ }
+ mMediaImplList[old_num_tes -1]->setUpdated(TRUE) ;
+ }
+ }
+ else if(old_num_tes > num_tes && mMediaImplList.size() > num_tes) //old faces removed
+ {
+ U8 end = mMediaImplList.size() ;
+ for(U8 i = num_tes; i < end ; i++)
+ {
+ removeMediaImpl(i) ;
+ }
+ mMediaImplList.resize(num_tes) ;
+
+ LLViewerObject::setNumTEs(num_tes) ;
+ }
+ else
+ {
+ LLViewerObject::setNumTEs(num_tes) ;
+ }
+
+ return ;
+}
+
+void LLVOVolume::setTEImage(const U8 te, LLViewerTexture *imagep)
{
BOOL changed = (mTEImages[te] != imagep);
LLViewerObject::setTEImage(te, imagep);
@@ -1271,15 +1542,28 @@ S32 LLVOVolume::setTEColor(const U8 te, const LLColor3& color)
S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color)
{
- S32 res = LLViewerObject::setTEColor(te, color);
- if (res && mDrawable.notNull())
+ S32 retval = 0;
+ const LLTextureEntry *tep = getTE(te);
+ if (!tep)
{
- //gPipeline.markTextured(mDrawable);
- mDrawable->setState(LLDrawable::REBUILD_COLOR);
- dirtyMesh();
- //mFaceMappingChanged = TRUE;
+ llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl;
}
- return res;
+ else if (color != tep->getColor())
+ {
+ if (color.mV[3] != tep->getColor().mV[3])
+ {
+ gPipeline.markTextured(mDrawable);
+ }
+ retval = LLPrimitive::setTEColor(te, color);
+ if (mDrawable.notNull() && retval)
+ {
+ // These should only happen on updates which are not the initial update.
+ mDrawable->setState(LLDrawable::REBUILD_COLOR);
+ dirtyMesh();
+ }
+ }
+
+ return retval;
}
S32 LLVOVolume::setTEBumpmap(const U8 te, const U8 bumpmap)
@@ -1304,6 +1588,17 @@ S32 LLVOVolume::setTETexGen(const U8 te, const U8 texgen)
return res;
}
+S32 LLVOVolume::setTEMediaTexGen(const U8 te, const U8 media)
+{
+ S32 res = LLViewerObject::setTEMediaTexGen(te, media);
+ if (res)
+ {
+ gPipeline.markTextured(mDrawable);
+ mFaceMappingChanged = TRUE;
+ }
+ return res;
+}
+
S32 LLVOVolume::setTEShiny(const U8 te, const U8 shiny)
{
S32 res = LLViewerObject::setTEShiny(te, shiny);
@@ -1326,6 +1621,17 @@ S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright)
return res;
}
+S32 LLVOVolume::setTEBumpShinyFullbright(const U8 te, const U8 bump)
+{
+ S32 res = LLViewerObject::setTEBumpShinyFullbright(te, bump);
+ if (res)
+ {
+ gPipeline.markTextured(mDrawable);
+ mFaceMappingChanged = TRUE;
+ }
+ return res;
+}
+
S32 LLVOVolume::setTEMediaFlags(const U8 te, const U8 media_flags)
{
S32 res = LLViewerObject::setTEMediaFlags(te, media_flags);
@@ -1390,8 +1696,512 @@ void LLVOVolume::updateTEData()
}*/
}
+bool LLVOVolume::hasMedia() const
+{
+ bool result = false;
+ const U8 numTEs = getNumTEs();
+ for (U8 i = 0; i < numTEs; i++)
+ {
+ const LLTextureEntry* te = getTE(i);
+ if(te->hasMedia())
+ {
+ result = true;
+ break;
+ }
+ }
+ return result;
+}
+
+LLVector3 LLVOVolume::getApproximateFaceNormal(U8 face_id)
+{
+ LLVolume* volume = getVolume();
+ LLVector3 result;
+
+ if (volume && face_id < volume->getNumVolumeFaces())
+ {
+ const LLVolumeFace& face = volume->getVolumeFace(face_id);
+ for (S32 i = 0; i < (S32)face.mVertices.size(); ++i)
+ {
+ result += face.mVertices[i].mNormal;
+ }
+
+ result = volumeDirectionToAgent(result);
+ result.normVec();
+ }
+
+ return result;
+}
+
+void LLVOVolume::requestMediaDataUpdate(bool isNew)
+{
+ if (sObjectMediaClient)
+ sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this, isNew));
+}
+
+bool LLVOVolume::isMediaDataBeingFetched() const
+{
+ // I know what I'm doing by const_casting this away: this is just
+ // a wrapper class that is only going to do a lookup.
+ return (sObjectMediaClient) ? sObjectMediaClient->isInQueue(new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false)) : false;
+}
+
+void LLVOVolume::cleanUpMediaImpls()
+{
+ // Iterate through our TEs and remove any Impls that are no longer used
+ const U8 numTEs = getNumTEs();
+ for (U8 i = 0; i < numTEs; i++)
+ {
+ const LLTextureEntry* te = getTE(i);
+ if( ! te->hasMedia())
+ {
+ // Delete the media IMPL!
+ removeMediaImpl(i) ;
+ }
+ }
+}
+
+void LLVOVolume::updateObjectMediaData(const LLSD &media_data_array, const std::string &media_version)
+{
+ // media_data_array is an array of media entry maps
+ // media_version is the version string in the response.
+ U32 fetched_version = LLTextureEntry::getVersionFromMediaVersionString(media_version);
+
+ // Only update it if it is newer!
+ if ( (S32)fetched_version > mLastFetchedMediaVersion)
+ {
+ mLastFetchedMediaVersion = fetched_version;
+ //llinfos << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << llendl;
+
+ LLSD::array_const_iterator iter = media_data_array.beginArray();
+ LLSD::array_const_iterator end = media_data_array.endArray();
+ U8 texture_index = 0;
+ for (; iter != end; ++iter, ++texture_index)
+ {
+ syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/);
+ }
+ }
+}
+
+void LLVOVolume::syncMediaData(S32 texture_index, const LLSD &media_data, bool merge, bool ignore_agent)
+{
+ if(mDead)
+ {
+ // If the object has been marked dead, don't process media updates.
+ return;
+ }
+
+ LLTextureEntry *te = getTE(texture_index);
+ LL_DEBUGS("MediaOnAPrim") << "BEFORE: texture_index = " << texture_index
+ << " hasMedia = " << te->hasMedia() << " : "
+ << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << llendl;
+
+ std::string previous_url;
+ LLMediaEntry* mep = te->getMediaData();
+ if(mep)
+ {
+ // Save the "current url" from before the update so we can tell if
+ // it changes.
+ previous_url = mep->getCurrentURL();
+ }
+
+ if (merge)
+ {
+ te->mergeIntoMediaData(media_data);
+ }
+ else {
+ // XXX Question: what if the media data is undefined LLSD, but the
+ // update we got above said that we have media flags?? Here we clobber
+ // that, assuming the data from the service is more up-to-date.
+ te->updateMediaData(media_data);
+ }
+
+ mep = te->getMediaData();
+ if(mep)
+ {
+ bool update_from_self = false;
+ if (!ignore_agent)
+ {
+ LLUUID updating_agent = LLTextureEntry::getAgentIDFromMediaVersionString(getMediaURL());
+ update_from_self = (updating_agent == gAgent.getID());
+ }
+ viewer_media_t media_impl = LLViewerMedia::updateMediaImpl(mep, previous_url, update_from_self);
+
+ addMediaImpl(media_impl, texture_index) ;
+ }
+ else
+ {
+ removeMediaImpl(texture_index);
+ }
+
+ LL_DEBUGS("MediaOnAPrim") << "AFTER: texture_index = " << texture_index
+ << " hasMedia = " << te->hasMedia() << " : "
+ << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << llendl;
+}
+
+void LLVOVolume::mediaNavigateBounceBack(U8 texture_index)
+{
+ // Find the media entry for this navigate
+ const LLMediaEntry* mep = NULL;
+ viewer_media_t impl = getMediaImpl(texture_index);
+ LLTextureEntry *te = getTE(texture_index);
+ if(te)
+ {
+ mep = te->getMediaData();
+ }
+
+ if (mep && impl)
+ {
+ std::string url = mep->getCurrentURL();
+ // Look for a ":", if not there, assume "http://"
+ if (!url.empty() && std::string::npos == url.find(':'))
+ {
+ url = "http://" + url;
+ }
+ // If the url we're trying to "bounce back" to is either empty or not
+ // allowed by the whitelist, try the home url. If *that* doesn't work,
+ // set the media as failed and unload it
+ if (url.empty() || !mep->checkCandidateUrl(url))
+ {
+ url = mep->getHomeURL();
+ // Look for a ":", if not there, assume "http://"
+ if (!url.empty() && std::string::npos == url.find(':'))
+ {
+ url = "http://" + url;
+ }
+ }
+ if (url.empty() || !mep->checkCandidateUrl(url))
+ {
+ // The url to navigate back to is not good, and we have nowhere else
+ // to go.
+ LL_WARNS("MediaOnAPrim") << "FAILED to bounce back URL \"" << url << "\" -- unloading impl" << LL_ENDL;
+ impl->setMediaFailed(true);
+ }
+ else {
+ // Okay, navigate now
+ LL_INFOS("MediaOnAPrim") << "bouncing back to URL: " << url << LL_ENDL;
+ impl->navigateTo(url, "", false, true);
+ }
+ }
+}
+
+bool LLVOVolume::hasMediaPermission(const LLMediaEntry* media_entry, MediaPermType perm_type)
+{
+ // NOTE: This logic ALMOST duplicates the logic in the server (in particular, in llmediaservice.cpp).
+ if (NULL == media_entry ) return false; // XXX should we assert here?
+
+ // The agent has permissions if:
+ // - world permissions are on, or
+ // - group permissions are on, and agent_id is in the group, or
+ // - agent permissions are on, and agent_id is the owner
+
+ // *NOTE: We *used* to check for modify permissions here (i.e. permissions were
+ // granted if permModify() was true). However, this doesn't make sense in the
+ // viewer: we don't want to show controls or allow interaction if the author
+ // has deemed it so. See DEV-42115.
+
+ U8 media_perms = (perm_type == MEDIA_PERM_INTERACT) ? media_entry->getPermsInteract() : media_entry->getPermsControl();
+
+ // World permissions
+ if (0 != (media_perms & LLMediaEntry::PERM_ANYONE))
+ {
+ return true;
+ }
+
+ // Group permissions
+ else if (0 != (media_perms & LLMediaEntry::PERM_GROUP) && permGroupOwner())
+ {
+ return true;
+ }
+
+ // Owner permissions
+ else if (0 != (media_perms & LLMediaEntry::PERM_OWNER) && permYouOwner())
+ {
+ return true;
+ }
+
+ return false;
+
+}
+
+void LLVOVolume::mediaNavigated(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, std::string new_location)
+{
+ bool block_navigation = false;
+ // FIXME: if/when we allow the same media impl to be used by multiple faces, the logic here will need to be fixed
+ // to deal with multiple face indices.
+ int face_index = getFaceIndexWithMediaImpl(impl, -1);
+
+ // Find the media entry for this navigate
+ LLMediaEntry* mep = NULL;
+ LLTextureEntry *te = getTE(face_index);
+ if(te)
+ {
+ mep = te->getMediaData();
+ }
+
+ if(mep)
+ {
+ if(!mep->checkCandidateUrl(new_location))
+ {
+ block_navigation = true;
+ }
+ if (!block_navigation && !hasMediaPermission(mep, MEDIA_PERM_INTERACT))
+ {
+ block_navigation = true;
+ }
+ }
+ else
+ {
+ llwarns << "Couldn't find media entry!" << llendl;
+ }
+
+ if(block_navigation)
+ {
+ llinfos << "blocking navigate to URI " << new_location << llendl;
+
+ // "bounce back" to the current URL from the media entry
+ mediaNavigateBounceBack(face_index);
+ }
+ else if (sObjectMediaNavigateClient)
+ {
+
+ llinfos << "broadcasting navigate with URI " << new_location << llendl;
+
+ sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this, false), face_index, new_location);
+ }
+}
+
+void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event)
+{
+ switch(event)
+ {
+
+ case LLViewerMediaObserver::MEDIA_EVENT_LOCATION_CHANGED:
+ {
+ switch(impl->getNavState())
+ {
+ case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED:
+ {
+ // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back.
+ mediaNavigated(impl, plugin, plugin->getLocation());
+ }
+ break;
+
+ case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED:
+ // This is the first location changed event after the start of a server-directed nav. Don't broadcast it.
+ llinfos << " NOT broadcasting navigate (server-directed)" << llendl;
+ break;
+
+ default:
+ // This is a subsequent location-changed due to a redirect. Don't broadcast.
+ llinfos << " NOT broadcasting navigate (redirect)" << llendl;
+ break;
+ }
+ }
+ break;
+
+ case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE:
+ {
+ switch(impl->getNavState())
+ {
+ case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED:
+ {
+ // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back.
+ mediaNavigated(impl, plugin, plugin->getNavigateURI());
+ }
+ break;
+
+ case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED:
+ // This is the the navigate complete event from a server-directed nav. Don't broadcast it.
+ llinfos << " NOT broadcasting navigate (server-directed)" << llendl;
+ break;
+
+ default:
+ // For all other states, the navigate should have been handled by LOCATION_CHANGED events already.
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+}
+
+void LLVOVolume::sendMediaDataUpdate()
+{
+ if (sObjectMediaClient)
+ sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this, false));
+}
+
+void LLVOVolume::removeMediaImpl(S32 texture_index)
+{
+ if(mMediaImplList.size() <= (U32)texture_index || mMediaImplList[texture_index].isNull())
+ {
+ return ;
+ }
+
+ //make the face referencing to mMediaImplList[texture_index] to point back to the old texture.
+ if(mDrawable)
+ {
+ LLFace* facep = mDrawable->getFace(texture_index) ;
+ if(facep)
+ {
+ LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ;
+ if(media_tex)
+ {
+ media_tex->removeMediaFromFace(facep) ;
+ }
+ }
+ }
+
+ //check if some other face(s) of this object reference(s)to this media impl.
+ S32 i ;
+ S32 end = (S32)mMediaImplList.size() ;
+ for(i = 0; i < end ; i++)
+ {
+ if( i != texture_index && mMediaImplList[i] == mMediaImplList[texture_index])
+ {
+ break ;
+ }
+ }
+
+ if(i == end) //this object does not need this media impl.
+ {
+ mMediaImplList[texture_index]->removeObject(this) ;
+ }
+
+ mMediaImplList[texture_index] = NULL ;
+ return ;
+}
+
+void LLVOVolume::addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index)
+{
+ if((S32)mMediaImplList.size() < texture_index + 1)
+ {
+ mMediaImplList.resize(texture_index + 1) ;
+ }
+
+ if(mMediaImplList[texture_index].notNull())
+ {
+ if(mMediaImplList[texture_index] == media_impl)
+ {
+ return ;
+ }
+
+ removeMediaImpl(texture_index) ;
+ }
+
+ mMediaImplList[texture_index] = media_impl;
+ media_impl->addObject(this) ;
+
+ //add the face to show the media if it is in playing
+ if(mDrawable)
+ {
+ LLFace* facep = mDrawable->getFace(texture_index) ;
+ if(facep)
+ {
+ LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ;
+ if(media_tex)
+ {
+ media_tex->addMediaToFace(facep) ;
+ }
+ }
+ else //the face is not available now, start media on this face later.
+ {
+ media_impl->setUpdated(TRUE) ;
+ }
+ }
+ return ;
+}
+
+viewer_media_t LLVOVolume::getMediaImpl(U8 face_id) const
+{
+ if(mMediaImplList.size() > face_id)
+ {
+ return mMediaImplList[face_id];
+ }
+ return NULL;
+}
+
+F64 LLVOVolume::getTotalMediaInterest() const
+{
+ // If this object is currently focused, this object has "high" interest
+ if (LLViewerMediaFocus::getInstance()->getFocusedObjectID() == getID())
+ return F64_MAX;
+
+ F64 interest = (F64)-1.0; // means not interested;
+
+ // If this object is selected, this object has "high" interest, but since
+ // there can be more than one, we still add in calculated impl interest
+ // XXX Sadly, 'contains()' doesn't take a const :(
+ if (LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(this)))
+ interest = F64_MAX / 2.0;
+
+ int i = 0;
+ const int end = getNumTEs();
+ for ( ; i < end; ++i)
+ {
+ const viewer_media_t &impl = getMediaImpl(i);
+ if (!impl.isNull())
+ {
+ if (interest == (F64)-1.0) interest = (F64)0.0;
+ interest += impl->getInterest();
+ }
+ }
+ return interest;
+}
+
+S32 LLVOVolume::getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id)
+{
+ S32 end = (S32)mMediaImplList.size() ;
+ for(S32 face_id = start_face_id + 1; face_id < end; face_id++)
+ {
+ if(mMediaImplList[face_id] == media_impl)
+ {
+ return face_id ;
+ }
+ }
+ return -1 ;
+}
+
//----------------------------------------------------------------------------
+void LLVOVolume::setLightTextureID(LLUUID id)
+{
+ if (id.notNull())
+ {
+ if (!hasLightTexture())
+ {
+ setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, TRUE, true);
+ }
+ LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
+ if (param_block && param_block->getLightTexture() != id)
+ {
+ param_block->setLightTexture(id);
+ parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true);
+ }
+ }
+ else
+ {
+ if (hasLightTexture())
+ {
+ setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, FALSE, true);
+ mLightTexture = NULL;
+ }
+ }
+}
+
+void LLVOVolume::setSpotLightParams(LLVector3 params)
+{
+ LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
+ if (param_block && param_block->getParams() != params)
+ {
+ param_block->setParams(params);
+ parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true);
+ }
+}
+
void LLVOVolume::setIsLight(BOOL is_light)
{
if (is_light != getIsLight())
@@ -1518,6 +2328,83 @@ LLColor3 LLVOVolume::getLightColor() const
}
}
+LLUUID LLVOVolume::getLightTextureID() const
+{
+ if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE))
+ {
+ const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
+ if (param_block)
+ {
+ return param_block->getLightTexture();
+ }
+ }
+
+ return LLUUID::null;
+}
+
+
+LLVector3 LLVOVolume::getSpotLightParams() const
+{
+ if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE))
+ {
+ const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
+ if (param_block)
+ {
+ return param_block->getParams();
+ }
+ }
+
+ return LLVector3();
+}
+
+F32 LLVOVolume::getSpotLightPriority() const
+{
+ return mSpotLightPriority;
+}
+
+void LLVOVolume::updateSpotLightPriority()
+{
+ LLVector3 pos = mDrawable->getPositionAgent();
+ LLVector3 at(0,0,-1);
+ at *= getRenderRotation();
+
+ F32 r = getLightRadius()*0.5f;
+
+ pos += at * r;
+
+ at = LLViewerCamera::getInstance()->getAtAxis();
+
+ pos -= at * r;
+
+ mSpotLightPriority = gPipeline.calcPixelArea(pos, LLVector3(r,r,r), *LLViewerCamera::getInstance());
+
+ if (mLightTexture.notNull())
+ {
+ mLightTexture->addTextureStats(mSpotLightPriority);
+ mLightTexture->setBoostLevel(LLViewerTexture::BOOST_CLOUDS);
+ }
+}
+
+
+LLViewerTexture* LLVOVolume::getLightTexture()
+{
+ LLUUID id = getLightTextureID();
+
+ if (id.notNull())
+ {
+ if (mLightTexture.isNull() || id != mLightTexture->getID())
+ {
+ mLightTexture = LLViewerTextureManager::getFetchedTexture(id);
+ }
+ }
+ else
+ {
+ mLightTexture = NULL;
+ }
+
+ return mLightTexture;
+}
+
F32 LLVOVolume::getLightIntensity() const
{
const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
@@ -1609,6 +2496,16 @@ BOOL LLVOVolume::isSculpted() const
return FALSE;
}
+BOOL LLVOVolume::hasLightTexture() const
+{
+ if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
BOOL LLVOVolume::isVolumeGlobal() const
{
if (mVolumeImpl)
@@ -1699,7 +2596,7 @@ void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_p
trans_mat.translate(getRegion()->getOriginAgent());
}
- volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, nodep->mSilhouetteSegments, view_vector, trans_mat, mRelativeXformInvTrans);
+ volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, nodep->mSilhouetteSegments, view_vector, trans_mat, mRelativeXformInvTrans, nodep->getTESelectMask());
nodep->mSilhouetteExists = TRUE;
}
@@ -1759,6 +2656,139 @@ const LLMatrix4 LLVOVolume::getRenderMatrix() const
return mDrawable->getWorldMatrix();
}
+// Returns a base cost and adds textures to passed in set.
+// total cost is returned value + 5 * size of the resulting set.
+// Cannot include cost of textures, as they may be re-used in linked
+// children, and cost should only be increased for unique textures -Nyx
+U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const
+{
+ // base cost of each prim should be 10 points
+ static const U32 ARC_PRIM_COST = 10;
+ // per-prim costs
+ static const U32 ARC_INVISI_COST = 1;
+ static const U32 ARC_SHINY_COST = 1;
+ static const U32 ARC_GLOW_COST = 1;
+ static const U32 ARC_FLEXI_COST = 8;
+ static const U32 ARC_PARTICLE_COST = 16;
+ static const U32 ARC_BUMP_COST = 4;
+
+ // per-face costs
+ static const U32 ARC_PLANAR_COST = 1;
+ static const U32 ARC_ANIM_TEX_COST = 4;
+ static const U32 ARC_ALPHA_COST = 4;
+
+ U32 shame = ARC_PRIM_COST;
+
+ U32 invisi = 0;
+ U32 shiny = 0;
+ U32 glow = 0;
+ U32 alpha = 0;
+ U32 flexi = 0;
+ U32 animtex = 0;
+ U32 particles = 0;
+ U32 scale = 0;
+ U32 bump = 0;
+ U32 planar = 0;
+
+ if (isFlexible())
+ {
+ flexi = 1;
+ }
+ if (isParticleSource())
+ {
+ particles = 1;
+ }
+
+ const LLVector3& sc = getScale();
+ scale += (U32) sc.mV[0] + (U32) sc.mV[1] + (U32) sc.mV[2];
+
+ const LLDrawable* drawablep = mDrawable;
+
+ if (isSculpted())
+ {
+ const LLSculptParams *sculpt_params = (LLSculptParams *) getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ LLUUID sculpt_id = sculpt_params->getSculptTexture();
+ textures.insert(sculpt_id);
+ }
+
+ for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
+ {
+ const LLFace* face = drawablep->getFace(i);
+ const LLTextureEntry* te = face->getTextureEntry();
+ const LLViewerTexture* img = face->getTexture();
+
+ if (img)
+ {
+ textures.insert(img->getID());
+ }
+
+ if (face->getPoolType() == LLDrawPool::POOL_ALPHA)
+ {
+ alpha++;
+ }
+ else if (img && img->getPrimaryFormat() == GL_ALPHA)
+ {
+ invisi = 1;
+ }
+
+ if (te)
+ {
+ if (te->getBumpmap())
+ {
+ bump = 1;
+ }
+ if (te->getShiny())
+ {
+ shiny = 1;
+ }
+ if (te->getGlow() > 0.f)
+ {
+ glow = 1;
+ }
+ if (face->mTextureMatrix != NULL)
+ {
+ animtex++;
+ }
+ if (te->getTexGen())
+ {
+ planar++;
+ }
+ }
+ }
+
+
+ shame += invisi * ARC_INVISI_COST;
+ shame += shiny * ARC_SHINY_COST;
+ shame += glow * ARC_GLOW_COST;
+ shame += alpha * ARC_ALPHA_COST;
+ shame += flexi * ARC_FLEXI_COST;
+ shame += animtex * ARC_ANIM_TEX_COST;
+ shame += particles * ARC_PARTICLE_COST;
+ shame += bump * ARC_BUMP_COST;
+ shame += planar * ARC_PLANAR_COST;
+ shame += scale;
+
+ LLViewerObject::const_child_list_t& child_list = getChildren();
+ for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
+ iter != child_list.end();
+ ++iter)
+ {
+ const LLViewerObject* child_objectp = *iter;
+ const LLDrawable* child_drawablep = child_objectp->mDrawable;
+ if (child_drawablep)
+ {
+ const LLVOVolume* child_volumep = child_drawablep->getVOVolume();
+ if (child_volumep)
+ {
+ shame += child_volumep->getRenderCost(textures);
+ }
+ }
+ }
+
+ return shame;
+
+}
+
//static
void LLVOVolume::preUpdateGeom()
{
@@ -1941,10 +2971,9 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal)
{
- if (!mbCanSelect ||
- (gHideSelectedObjects && isSelected()) ||
- mDrawable->isDead() ||
- !gPipeline.hasRenderType(mDrawable->getRenderType()))
+ if (!mbCanSelect
+ || mDrawable->isDead()
+ || !gPipeline.hasRenderType(mDrawable->getRenderType()))
{
return FALSE;
}
@@ -1990,7 +3019,7 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
if (face == -1)
{
start_face = 0;
- end_face = volume->getNumFaces();
+ end_face = volume->getNumVolumeFaces();
}
else
{
@@ -2005,9 +3034,9 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
if (face_hit >= 0 && mDrawable->getNumFaces() > face_hit)
{
- LLFace* face = mDrawable->getFace(face_hit);
-
- if (pick_transparent || !face->getTexture() || face->getTexture()->getMask(face->surfaceToTexture(tc, p, n)))
+ LLFace* face = mDrawable->getFace(face_hit);
+
+ if (pick_transparent || !face->getTexture() || !face->getTexture()->hasGLTexture() || face->getTexture()->getMask(face->surfaceToTexture(tc, p, n)))
{
v_end = p;
if (face_hitp != NULL)
@@ -2057,9 +3086,9 @@ U32 LLVOVolume::getPartitionType() const
}
LLVolumePartition::LLVolumePartition()
-: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, FALSE)
+: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB)
{
- mLODPeriod = 16;
+ mLODPeriod = 32;
mDepthMask = FALSE;
mDrawableType = LLPipeline::RENDER_TYPE_VOLUME;
mPartitionType = LLViewerRegion::PARTITION_VOLUME;
@@ -2068,10 +3097,10 @@ LLVolumePartition::LLVolumePartition()
}
LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep)
-: LLSpatialBridge(drawablep, LLVOVolume::VERTEX_DATA_MASK)
+: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK)
{
mDepthMask = FALSE;
- mLODPeriod = 16;
+ mLODPeriod = 32;
mDrawableType = LLPipeline::RENDER_TYPE_VOLUME;
mPartitionType = LLViewerRegion::PARTITION_BRIDGE;
@@ -2084,7 +3113,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- if (facep->getViewerObject()->isSelected() && gHideSelectedObjects)
+ if (facep->getViewerObject()->isSelected() && LLSelectMgr::getInstance()->mHideSelectedObjects)
{
return;
}
@@ -2095,8 +3124,15 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
S32 idx = draw_vec.size()-1;
- BOOL fullbright = (type == LLRenderPass::PASS_FULLBRIGHT ||
- type == LLRenderPass::PASS_ALPHA) ? facep->isState(LLFace::FULLBRIGHT) : FALSE;
+ BOOL fullbright = (type == LLRenderPass::PASS_FULLBRIGHT) ||
+ (type == LLRenderPass::PASS_INVISIBLE) ||
+ (type == LLRenderPass::PASS_ALPHA ? facep->isState(LLFace::FULLBRIGHT) : FALSE);
+
+ if (!fullbright && type != LLRenderPass::PASS_GLOW && !facep->mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL))
+ {
+ llwarns << "Non fullbright face has no normals!" << llendl;
+ return;
+ }
const LLMatrix4* tex_mat = NULL;
if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE)
@@ -2118,7 +3154,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
U8 bump = (type == LLRenderPass::PASS_BUMP ? facep->getTextureEntry()->getBumpmap() : 0);
- LLViewerImage* tex = facep->getTexture();
+ LLViewerTexture* tex = facep->getTexture();
U8 glow = 0;
@@ -2159,7 +3195,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
U32 end = start + facep->getGeomCount()-1;
U32 offset = facep->getIndicesStart();
U32 count = facep->getIndicesCount();
- LLPointer<LLDrawInfo> draw_info = new LLDrawInfo(start,end,count,offset,tex,
+ LLPointer<LLDrawInfo> draw_info = new LLDrawInfo(start,end,count,offset, tex,
facep->mVertexBuffer, fullbright, bump);
draw_info->mGroup = group;
draw_info->mVSize = facep->getVirtualSize();
@@ -2182,13 +3218,12 @@ void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group)
}
+static LLFastTimer::DeclareTimer FTM_REBUILD_VOLUME_VB("Volume");
+static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt");
+
void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
{
- if (LLPipeline::sSkipUpdate)
- {
- return;
- }
-
+ llpushcallstacks ;
if (group->changeLOD())
{
group->mLastUpdateDistance = group->mDistance;
@@ -2200,8 +3235,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
{
if (group->isState(LLSpatialGroup::MESH_DIRTY) && !LLPipeline::sDelayVBUpdate)
{
- LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO);
- LLFastTimer ftm2(LLFastTimer::FTM_REBUILD_VOLUME_VB);
+ LLFastTimer ftm(FTM_REBUILD_VBO);
+ LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB);
rebuildMesh(group);
}
@@ -2209,9 +3244,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
}
group->mBuilt = 1.f;
- LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO);
+ LLFastTimer ftm(FTM_REBUILD_VBO);
- LLFastTimer ftm2(LLFastTimer::FTM_REBUILD_VOLUME_VB);
+ LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB);
group->clearDrawMap();
@@ -2247,9 +3282,11 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
LLVOVolume* vobj = drawablep->getVOVolume();
llassert_always(vobj);
- vobj->updateTextures();
+ vobj->updateTextureVirtualSize();
vobj->preRebuild();
+ drawablep->clearState(LLDrawable::HAS_ALPHA);
+
//for each face
for (S32 i = 0; i < drawablep->getNumFaces(); i++)
{
@@ -2269,7 +3306,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
if (facep->hasGeometry() && facep->mPixelArea > FORCE_CULL_AREA)
{
const LLTextureEntry* te = facep->getTextureEntry();
- LLViewerImage* tex = facep->getTexture();
+ LLViewerTexture* tex = facep->getTexture();
if (facep->isState(LLFace::TEXTURE_ANIM))
{
@@ -2311,13 +3348,15 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
if (type == LLDrawPool::POOL_ALPHA)
{
if (LLPipeline::sFastAlpha &&
- (te->getColor().mV[VW] == 1.0f) &&
- facep->getTexture()->getIsAlphaMask())
+ (te->getColor().mV[VW] == 1.0f) &&
+ (!te->getFullbright()) && // hack: alpha masking renders fullbright faces invisible, need to figure out why - for now, avoid
+ facep->getTexture()->getIsAlphaMask())
{ //can be treated as alpha mask
simple_faces.push_back(facep);
}
else
{
+ drawablep->setState(LLDrawable::HAS_ALPHA);
alpha_faces.push_back(facep);
}
}
@@ -2351,7 +3390,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
{ //needs normal + binormal
bump_faces.push_back(facep);
}
- else if (te->getShiny() && LLPipeline::sRenderBump ||
+ else if ((te->getShiny() && LLPipeline::sRenderBump) ||
!te->getFullbright())
{ //needs normal
simple_faces.push_back(facep);
@@ -2406,16 +3445,19 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
if (LLPipeline::sDelayVBUpdate)
{
- group->setState(LLSpatialGroup::MESH_DIRTY);
+ group->setState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO);
}
mFaceList.clear();
}
+static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM("Volume Geometry");
void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
{
- if (group->isState(LLSpatialGroup::MESH_DIRTY))
+ llpushcallstacks ;
+ if (group->isState(LLSpatialGroup::MESH_DIRTY) && !group->isState(LLSpatialGroup::GEOM_DIRTY))
{
+ LLFastTimer tm(FTM_VOLUME_GEOM);
S32 num_mapped_veretx_buffer = LLVertexBuffer::sMappedCount ;
group->mBuilt = 1.f;
@@ -2492,12 +3534,18 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
}
}
- group->clearState(LLSpatialGroup::MESH_DIRTY);
+ group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO);
+ }
+
+ if (group->isState(LLSpatialGroup::NEW_DRAWINFO))
+ {
+ llerrs << "WTF?" << llendl;
}
}
void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort)
{
+ llpushcallstacks ;
//calculate maximum number of vertices to store in a single buffer
U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcStride(group->mSpatialPartition->mVertexDataMask);
max_vertices = llmin(max_vertices, (U32) 65535);
@@ -2517,7 +3565,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
LLSpatialGroup::buffer_map_t buffer_map;
- LLViewerImage* last_tex = NULL;
+ LLViewerTexture* last_tex = NULL;
S32 buffer_index = 0;
if (distance_sort)
@@ -2529,7 +3577,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
{
//pull off next face
LLFace* facep = *face_iter;
- LLViewerImage* tex = facep->getTexture();
+ LLViewerTexture* tex = facep->getTexture();
if (distance_sort)
{
@@ -2637,6 +3685,11 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
BOOL force_simple = facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA;
BOOL fullbright = facep->isState(LLFace::FULLBRIGHT);
+ if ((mask & LLVertexBuffer::MAP_NORMAL) == 0)
+ { //paranoia check to make sure GL doesn't try to read non-existant normals
+ fullbright = TRUE;
+ }
+
const LLTextureEntry* te = facep->getTextureEntry();
BOOL is_alpha = facep->getPoolType() == LLDrawPool::POOL_ALPHA ? TRUE : FALSE;
@@ -2646,6 +3699,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
// can we safely treat this as an alpha mask?
if (LLPipeline::sFastAlpha &&
(te->getColor().mV[VW] == 1.0f) &&
+ (!te->getFullbright()) && // hack: alpha masking renders fullbright faces invisible, need to figure out why - for now, avoid
facep->getTexture()->getIsAlphaMask())
{
if (te->getFullbright())
@@ -2668,6 +3722,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
}
}
else if (gPipeline.canUseVertexShaders()
+ && group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD
&& LLPipeline::sRenderBump
&& te->getShiny())
{
@@ -2724,7 +3779,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
}
}
- if (!is_alpha && te->getShiny())
+ if (!is_alpha && te->getShiny() && LLPipeline::sRenderBump)
{
registerFace(group, facep, LLRenderPass::PASS_SHINY);
}
@@ -2735,7 +3790,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright);
facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE);
- if (!force_simple && te->getBumpmap())
+ if (!force_simple && te->getBumpmap() && LLPipeline::sRenderBump)
{
registerFace(group, facep, LLRenderPass::PASS_BUMP);
}
@@ -2812,7 +3867,7 @@ LLHUDPartition::LLHUDPartition()
mPartitionType = LLViewerRegion::PARTITION_HUD;
mDrawableType = LLPipeline::RENDER_TYPE_HUD;
mSlopRatio = 0.f;
- mLODPeriod = 16;
+ mLODPeriod = 1;
}
void LLHUDPartition::shift(const LLVector3 &offset)
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 155775510e..a287d34402 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -34,14 +34,20 @@
#define LL_LLVOVOLUME_H
#include "llviewerobject.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
+#include "llviewermedia.h"
#include "llframetimer.h"
-#include "llapr.h"
+#include "m3math.h" // LLMatrix3
+#include "m4math.h" // LLMatrix4
#include <map>
class LLViewerTextureAnim;
class LLDrawPool;
class LLSelectNode;
+class LLObjectMediaDataClient;
+class LLObjectMediaNavigateClient;
+
+typedef std::vector<viewer_media_t> media_list_t;
enum LLVolumeInterfaceType
{
@@ -73,12 +79,14 @@ public:
// Class which embodies all Volume objects (with pcode LL_PCODE_VOLUME)
class LLVOVolume : public LLViewerObject
{
+ LOG_CLASS(LLVOVolume);
protected:
virtual ~LLVOVolume();
public:
static void initClass();
- static void preUpdateGeom();
+ static void cleanupClass();
+ static void preUpdateGeom();
enum
{
@@ -91,6 +99,7 @@ public:
public:
LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
+ /*virtual*/ void markDead(); // Override (and call through to parent) to clean up media references
/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
@@ -105,13 +114,13 @@ public:
/*virtual*/ BOOL isHUDAttachment() const;
void generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point);
- /*virtual*/ void setParent(LLViewerObject* parent);
+ /*virtual*/ BOOL setParent(LLViewerObject* parent);
S32 getLOD() const { return mLOD; }
const LLVector3 getPivotPositionAgent() const;
const LLMatrix4& getRelativeXform() const { return mRelativeXform; }
const LLMatrix3& getRelativeXformInvTrans() const { return mRelativeXformInvTrans; }
/*virtual*/ const LLMatrix4 getRenderMatrix() const;
-
+ U32 getRenderCost(std::set<LLUUID> &textures) const;
/*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
S32 face = -1, // which face to check, -1 = ALL_SIDES
@@ -130,7 +139,7 @@ public:
BOOL getVolumeChanged() const { return mVolumeChanged; }
- F32 getTextureVirtualSize(LLFace* face);
+
/*virtual*/ F32 getRadius() const { return mVObjRadius; };
const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const;
@@ -151,19 +160,22 @@ public:
/*virtual*/ void setScale(const LLVector3 &scale, BOOL damped);
- /*virtual*/ void setTEImage(const U8 te, LLViewerImage *imagep);
+ /*virtual*/ void setNumTEs(const U8 num_tes);
+ /*virtual*/ void setTEImage(const U8 te, LLViewerTexture *imagep);
/*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid);
/*virtual*/ S32 setTEColor(const U8 te, const LLColor3 &color);
/*virtual*/ S32 setTEColor(const U8 te, const LLColor4 &color);
/*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump);
/*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny);
/*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright);
+ /*virtual*/ S32 setTEBumpShinyFullbright(const U8 te, const U8 bump);
/*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags);
/*virtual*/ S32 setTEGlow(const U8 te, const F32 glow);
/*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t);
/*virtual*/ S32 setTEScaleS(const U8 te, const F32 s);
/*virtual*/ S32 setTEScaleT(const U8 te, const F32 t);
/*virtual*/ S32 setTETexGen(const U8 te, const U8 texgen);
+ /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media);
/*virtual*/ BOOL setMaterial(const U8 material);
void setTexture(const S32 face);
@@ -175,8 +187,8 @@ public:
/*virtual*/ void updateFaceSize(S32 idx);
/*virtual*/ BOOL updateLOD();
void updateRadius();
- /*virtual*/ void updateTextures(LLAgent &agent);
- void updateTextures();
+ /*virtual*/ void updateTextures();
+ void updateTextureVirtualSize();
void updateFaceFlags();
void regenFaces();
@@ -194,9 +206,18 @@ public:
void setLightRadius(F32 radius);
void setLightFalloff(F32 falloff);
void setLightCutoff(F32 cutoff);
+ void setLightTextureID(LLUUID id);
+ void setSpotLightParams(LLVector3 params);
+
BOOL getIsLight() const;
LLColor3 getLightBaseColor() const; // not scaled by intensity
LLColor3 getLightColor() const; // scaled by intensity
+ LLUUID getLightTextureID() const;
+ LLVector3 getSpotLightParams() const;
+ void updateSpotLightPriority();
+ F32 getSpotLightPriority() const;
+
+ LLViewerTexture* getLightTexture();
F32 getLightIntensity() const;
F32 getLightRadius() const;
F32 getLightFalloff() const;
@@ -206,16 +227,61 @@ public:
U32 getVolumeInterfaceID() const;
virtual BOOL isFlexible() const;
virtual BOOL isSculpted() const;
+ virtual BOOL hasLightTexture() const;
+
BOOL isVolumeGlobal() const;
BOOL canBeFlexible() const;
BOOL setIsFlexible(BOOL is_flexible);
-
+
+ // Functions that deal with media, or media navigation
+
+ // Update this object's media data with the given media data array
+ // (typically this is only called upon a response from a server request)
+ void updateObjectMediaData(const LLSD &media_data_array, const std::string &media_version);
+
+ // Bounce back media at the given index to its current URL (or home URL, if current URL is empty)
+ void mediaNavigateBounceBack(U8 texture_index);
+
+ // Returns whether or not this object has permission to navigate or control
+ // the given media entry
+ enum MediaPermType {
+ MEDIA_PERM_INTERACT, MEDIA_PERM_CONTROL
+ };
+ bool hasMediaPermission(const LLMediaEntry* media_entry, MediaPermType perm_type);
+
+ void mediaNavigated(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, std::string new_location);
+ void mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event);
+
+ // Sync the given media data with the impl and the given te
+ void syncMediaData(S32 te, const LLSD &media_data, bool merge, bool ignore_agent);
+
+ // Send media data update to the simulator.
+ void sendMediaDataUpdate();
+
+ viewer_media_t getMediaImpl(U8 face_id) const;
+ S32 getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id);
+ F64 getTotalMediaInterest() const;
+
+ bool hasMedia() const;
+
+ LLVector3 getApproximateFaceNormal(U8 face_id);
+
+ // Returns 'true' iff the media data for this object is in flight
+ bool isMediaDataBeingFetched() const;
+
+ // Returns the "last fetched" media version, or -1 if not fetched yet
+ S32 getLastFetchedMediaVersion() const { return mLastFetchedMediaVersion; }
+
protected:
S32 computeLODDetail(F32 distance, F32 radius);
BOOL calcLOD();
LLFace* addFace(S32 face_index);
void updateTEData();
+ void requestMediaDataUpdate(bool isNew);
+ void cleanUpMediaImpls();
+ void addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) ;
+ void removeMediaImpl(S32 texture_index) ;
public:
LLViewerTextureAnim *mTextureAnimp;
U8 mTexAnimMode;
@@ -226,14 +292,17 @@ private:
LLFrameTimer mTextureUpdateTimer;
S32 mLOD;
BOOL mLODChanged;
- S32 mSculptLevel;
BOOL mSculptChanged;
+ F32 mSpotLightPriority;
LLMatrix4 mRelativeXform;
LLMatrix3 mRelativeXformInvTrans;
BOOL mVolumeChanged;
F32 mVObjRadius;
LLVolumeInterface *mVolumeImpl;
- LLPointer<LLViewerImage> mSculptTexture;
+ LLPointer<LLViewerFetchedTexture> mSculptTexture;
+ LLPointer<LLViewerFetchedTexture> mLightTexture;
+ media_list_t mMediaImplList;
+ S32 mLastFetchedMediaVersion; // as fetched from the server, starts as -1
// statics
public:
@@ -241,6 +310,11 @@ public:
static F32 sLODFactor; // LOD scale factor
static F32 sDistanceFactor; // LOD distance factor
+ static LLPointer<LLObjectMediaDataClient> sObjectMediaClient;
+ static LLPointer<LLObjectMediaNavigateClient> sObjectMediaNavigateClient;
+
+ static const U32 ARC_TEXTURE_COST = 5;
+
protected:
static S32 sNumLODChanges;
diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp
index d23c746b75..a8c4625f6e 100644
--- a/indra/newview/llvowater.cpp
+++ b/indra/newview/llvowater.cpp
@@ -37,7 +37,6 @@
#include "imageids.h"
#include "llviewercontrol.h"
-#include "llagent.h"
#include "lldrawable.h"
#include "lldrawpoolwater.h"
#include "llface.h"
@@ -45,7 +44,7 @@
#include "llsurface.h"
#include "llvosky.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewerregion.h"
#include "llworld.h"
#include "pipeline.h"
@@ -56,8 +55,6 @@ const BOOL gUseRoam = FALSE;
///////////////////////////////////
-#include "randgauss.h"
-
template<class T> inline T LERP(T a, T b, F32 factor)
{
return a + (b - a) * factor;
@@ -101,7 +98,7 @@ void LLVOWater::setPixelAreaAndAngle(LLAgent &agent)
// virtual
-void LLVOWater::updateTextures(LLAgent &agent)
+void LLVOWater::updateTextures()
{
}
@@ -139,9 +136,11 @@ LLDrawable *LLVOWater::createDrawable(LLPipeline *pipeline)
return mDrawable;
}
+static LLFastTimer::DeclareTimer FTM_UPDATE_WATER("Update Water");
+
BOOL LLVOWater::updateGeometry(LLDrawable *drawable)
{
- LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WATER);
+ LLFastTimer ftm(FTM_UPDATE_WATER);
LLFace *face;
if (drawable->getNumFaces() < 1)
@@ -276,9 +275,8 @@ U32 LLVOWater::getPartitionType() const
}
LLWaterPartition::LLWaterPartition()
-: LLSpatialPartition(0)
+: LLSpatialPartition(0, FALSE, 0)
{
- mRenderByGroup = FALSE;
mInfiniteFarClip = TRUE;
mDrawableType = LLPipeline::RENDER_TYPE_WATER;
mPartitionType = LLViewerRegion::PARTITION_WATER;
diff --git a/indra/newview/llvowater.h b/indra/newview/llvowater.h
index cdda48f6f2..3cc031e589 100644
--- a/indra/newview/llvowater.h
+++ b/indra/newview/llvowater.h
@@ -34,7 +34,7 @@
#define LL_VOWATER_H
#include "llviewerobject.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
#include "v2math.h"
const U32 N_RES = 16; //32 // number of subdivisions of wave tile
@@ -68,7 +68,7 @@ public:
/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
/*virtual*/ void updateSpatialExtents(LLVector3& newMin, LLVector3& newMax);
- /*virtual*/ void updateTextures(LLAgent &agent);
+ /*virtual*/ void updateTextures();
/*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area
virtual U32 getPartitionType() const;
diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp
index abd25e6598..0272a2ab34 100644
--- a/indra/newview/llvowlsky.cpp
+++ b/indra/newview/llvowlsky.cpp
@@ -49,12 +49,12 @@ const U32 LLVOWLSky::MAX_SKY_DETAIL = 180;
inline U32 LLVOWLSky::getNumStacks(void)
{
- return gSavedSettings.getU32("WLSkyDetail");
+ return llmin(MAX_SKY_DETAIL, llmax(MIN_SKY_DETAIL, gSavedSettings.getU32("WLSkyDetail")));
}
inline U32 LLVOWLSky::getNumSlices(void)
{
- return 2 * gSavedSettings.getU32("WLSkyDetail");
+ return 2 * llmin(MAX_SKY_DETAIL, llmax(MIN_SKY_DETAIL, gSavedSettings.getU32("WLSkyDetail")));
}
inline U32 LLVOWLSky::getFanNumVerts(void)
@@ -307,9 +307,11 @@ void LLVOWLSky::restoreGL()
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
}
+static LLFastTimer::DeclareTimer FTM_GEO_SKY("Sky Geometry");
+
BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable)
{
- LLFastTimer ftm(LLFastTimer::FTM_GEO_SKY);
+ LLFastTimer ftm(FTM_GEO_SKY);
LLStrider<LLVector3> vertices;
LLStrider<LLVector2> texCoords;
LLStrider<U16> indices;
@@ -489,7 +491,7 @@ void LLVOWLSky::drawStars(void)
if (mStarsVerts.notNull())
{
mStarsVerts->setBuffer(LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK);
- mStarsVerts->draw(LLRender::POINTS, getStarsNumIndices(), 0);
+ mStarsVerts->drawArrays(LLRender::QUADS, 0, getStarsNumVerts()*4);
}
}
@@ -544,6 +546,7 @@ void LLVOWLSky::initStars()
std::vector<F32>::iterator v_i = mStarIntensities.begin();
U32 i;
+
for (i = 0; i < getStarsNumVerts(); ++i)
{
v_p->mV[VX] = ll_frand() - 0.5f;
@@ -769,17 +772,17 @@ BOOL LLVOWLSky::updateStarGeometry(LLDrawable *drawable)
{
LLStrider<LLVector3> verticesp;
LLStrider<LLColor4U> colorsp;
- LLStrider<U16> indicesp;
+ LLStrider<LLVector2> texcoordsp;
if (mStarsVerts.isNull())
{
mStarsVerts = new LLVertexBuffer(LLDrawPoolWLSky::STAR_VERTEX_DATA_MASK, GL_DYNAMIC_DRAW);
- mStarsVerts->allocateBuffer(getStarsNumVerts(), getStarsNumIndices(), TRUE);
+ mStarsVerts->allocateBuffer(getStarsNumVerts()*4, 0, TRUE);
}
-
+
BOOL success = mStarsVerts->getVertexStrider(verticesp)
- && mStarsVerts->getIndexStrider(indicesp)
- && mStarsVerts->getColorStrider(colorsp);
+ && mStarsVerts->getColorStrider(colorsp)
+ && mStarsVerts->getTexCoord0Strider(texcoordsp);
if(!success)
{
@@ -789,11 +792,37 @@ BOOL LLVOWLSky::updateStarGeometry(LLDrawable *drawable)
// *TODO: fix LLStrider with a real prefix increment operator so it can be
// used as a model of OutputIterator. -Brad
// std::copy(mStarVertices.begin(), mStarVertices.end(), verticesp);
+
+ if (mStarVertices.size() < getStarsNumVerts())
+ {
+ llerrs << "Star reference geometry insufficient." << llendl;
+ }
+
for (U32 vtx = 0; vtx < getStarsNumVerts(); ++vtx)
{
+ LLVector3 at = mStarVertices[vtx];
+ at.normVec();
+ LLVector3 left = at%LLVector3(0,0,1);
+ LLVector3 up = at%left;
+
+ F32 sc = 0.5f+ll_frand()*1.25f;
+ left *= sc;
+ up *= sc;
+
*(verticesp++) = mStarVertices[vtx];
+ *(verticesp++) = mStarVertices[vtx]+left;
+ *(verticesp++) = mStarVertices[vtx]+left+up;
+ *(verticesp++) = mStarVertices[vtx]+up;
+
+ *(texcoordsp++) = LLVector2(0,0);
+ *(texcoordsp++) = LLVector2(0,1);
+ *(texcoordsp++) = LLVector2(1,1);
+ *(texcoordsp++) = LLVector2(1,0);
+
+ *(colorsp++) = LLColor4U(mStarColors[vtx]);
+ *(colorsp++) = LLColor4U(mStarColors[vtx]);
+ *(colorsp++) = LLColor4U(mStarColors[vtx]);
*(colorsp++) = LLColor4U(mStarColors[vtx]);
- *(indicesp++) = vtx;
}
mStarsVerts->setBuffer(0);
diff --git a/indra/newview/llwatchdog.h b/indra/newview/llwatchdog.h
index ed7d5bdcfb..79398c434a 100644
--- a/indra/newview/llwatchdog.h
+++ b/indra/newview/llwatchdog.h
@@ -64,9 +64,10 @@ public:
/* virtual */ bool isAlive() const;
/* virtual */ void reset();
- /* virtual */ void start(const std::string& state);
+ /* virtual */ void start() { start(""); }
/* virtual */ void stop();
+ void start(const std::string& state);
void setTimeout(F32 d);
void ping(const std::string& state);
const std::string& getState() {return mPingState; }
diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp
index 50e407739b..8be8f494da 100644
--- a/indra/newview/llwaterparammanager.cpp
+++ b/indra/newview/llwaterparammanager.cpp
@@ -39,6 +39,7 @@
#include "pipeline.h"
#include "llsky.h"
+#include "llfloaterreg.h"
#include "llsliderctrl.h"
#include "llspinctrl.h"
#include "llcheckboxctrl.h"
@@ -50,16 +51,13 @@
#include "llsdserialize.h"
#include "v4math.h"
-#include "llviewerdisplay.h"
#include "llviewercontrol.h"
-#include "llviewerwindow.h"
#include "lldrawpoolwater.h"
#include "llagent.h"
#include "llviewerregion.h"
#include "llwlparammanager.h"
#include "llwaterparamset.h"
-#include "llpostprocess.h"
#include "llfloaterwater.h"
#include "curl/curl.h"
@@ -90,7 +88,7 @@ LLWaterParamManager::~LLWaterParamManager()
void LLWaterParamManager::loadAllPresets(const std::string& file_name)
{
std::string path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", ""));
- LL_INFOS2("AppInit", "Shaders") << "Loading Default water settings from " << path_name << LL_ENDL;
+ LL_DEBUGS2("AppInit", "Shaders") << "Loading Default water settings from " << path_name << LL_ENDL;
bool found = true;
while(found)
@@ -116,7 +114,7 @@ void LLWaterParamManager::loadAllPresets(const std::string& file_name)
// And repeat for user presets, note the user presets will modify any system presets already loaded
std::string path_name2(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/water", ""));
- LL_INFOS2("AppInit", "Shaders") << "Loading User water settings from " << path_name2 << LL_ENDL;
+ LL_DEBUGS2("AppInit", "Shaders") << "Loading User water settings from " << path_name2 << LL_ENDL;
found = true;
while(found)
@@ -151,17 +149,18 @@ void LLWaterParamManager::loadPreset(const std::string & name,bool propagate)
escaped_filename += ".xml";
std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", escaped_filename));
- llinfos << "Loading water settings from " << pathName << llendl;
+ LL_DEBUGS2("AppInit", "Shaders") << "Loading water settings from " << pathName << LL_ENDL;
- std::ifstream presetsXML;
+ llifstream presetsXML;
presetsXML.open(pathName.c_str());
// That failed, try loading from the users area instead.
if(!presetsXML)
{
pathName=gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/water", escaped_filename);
- llinfos << "Loading User water setting from " << pathName << llendl;
- presetsXML.open(pathName.c_str());
+ LL_DEBUGS2("AppInit", "Shaders") << "Loading User water setting from " << pathName << LL_ENDL;
+ presetsXML.clear();
+ presetsXML.open(pathName.c_str());
}
if (presetsXML)
@@ -262,21 +261,22 @@ void LLWaterParamManager::updateShaderUniforms(LLGLSLShader * shader)
}
}
+static LLFastTimer::DeclareTimer FTM_UPDATE_WLPARAM("Update Windlight Params");
+
void LLWaterParamManager::update(LLViewerCamera * cam)
{
- LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WLPARAM);
+ LLFastTimer ftm(FTM_UPDATE_WLPARAM);
// update the shaders and the menu
propagateParameters();
// sync menus if they exist
- if(LLFloaterWater::isOpen())
+ LLFloaterWater* waterfloater = LLFloaterReg::findTypedInstance<LLFloaterWater>("env_water");
+ if(waterfloater)
{
- LLFloaterWater::instance()->syncMenu();
+ waterfloater->syncMenu();
}
- stop_glerror();
-
// only do this if we're dealing with shaders
if(gPipeline.canUseVertexShaders())
{
@@ -301,7 +301,7 @@ void LLWaterParamManager::update(LLViewerCamera * cam)
mWaterPlane = LLVector4(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm));
LLVector3 sunMoonDir;
- if (gSky.getSunDirection().mV[2] > NIGHTTIME_ELEVATION_COS)
+ if (gSky.getSunDirection().mV[2] > LLSky::NIGHTTIME_ELEVATION_COS)
{
sunMoonDir = gSky.getSunDirection();
}
diff --git a/indra/newview/llwaterparamset.cpp b/indra/newview/llwaterparamset.cpp
index a26ccedfb2..3e97f9dbef 100644
--- a/indra/newview/llwaterparamset.cpp
+++ b/indra/newview/llwaterparamset.cpp
@@ -39,7 +39,7 @@
#include "llwaterparammanager.h"
#include "lluictrlfactory.h"
#include "llsliderctrl.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewercontrol.h"
#include "lluuid.h"
diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp
index f705531723..b789bd3650 100644
--- a/indra/newview/llwearable.cpp
+++ b/indra/newview/llwearable.cpp
@@ -32,96 +32,37 @@
#include "llviewerprecompiledheaders.h"
-#include "imageids.h"
-#include "llassetstorage.h"
-#include "lldbstrings.h"
-#include "lldir.h"
-#include "llquantize.h"
-
#include "llagent.h"
-#include "llassetuploadresponders.h"
-#include "llviewerwindow.h"
+#include "llagentwearables.h"
#include "llfloatercustomize.h"
+#include "lllocaltextureobject.h"
+#include "llnotificationsutil.h"
+#include "llviewertexturelist.h"
#include "llinventorymodel.h"
-#include "llviewerimagelist.h"
-#include "llviewerinventory.h"
+#include "llinventoryobserver.h"
#include "llviewerregion.h"
#include "llvoavatar.h"
+#include "llvoavatarself.h"
+#include "llvoavatardefines.h"
#include "llwearable.h"
+#include "lldictionary.h"
+#include "lltrans.h"
+#include "lltexlayer.h"
+#include "llvisualparam.h"
+#include "lltexglobalcolor.h"
using namespace LLVOAvatarDefines;
// static
S32 LLWearable::sCurrentDefinitionVersion = 1;
-// static
-const std::string LLWearable::sTypeName[ WT_COUNT+1 ] =
-{
- "shape",
- "skin",
- "hair",
- "eyes",
- "shirt",
- "pants",
- "shoes",
- "socks",
- "jacket",
- "gloves",
- "undershirt",
- "underpants",
- "skirt",
- "invalid"
-};
-
-// static
-const std::string LLWearable::sTypeLabel[ WT_COUNT+1 ] =
-{
- "Shape",
- "Skin",
- "Hair",
- "Eyes",
- "Shirt",
- "Pants",
- "Shoes",
- "Socks",
- "Jacket",
- "Gloves",
- "Undershirt",
- "Underpants",
- "Skirt",
- "invalid"
-};
-
-
-// static
-LLAssetType::EType LLWearable::typeToAssetType(EWearableType wearable_type)
-{
- switch( wearable_type )
- {
- case WT_SHAPE:
- case WT_SKIN:
- case WT_HAIR:
- case WT_EYES:
- return LLAssetType::AT_BODYPART;
- case WT_SHIRT:
- case WT_PANTS:
- case WT_SHOES:
- case WT_SOCKS:
- case WT_JACKET:
- case WT_GLOVES:
- case WT_UNDERSHIRT:
- case WT_UNDERPANTS:
- case WT_SKIRT:
- return LLAssetType::AT_CLOTHING;
- default:
- return LLAssetType::AT_NONE;
- }
-}
-
+// Private local functions
+static std::string terse_F32_to_string(F32 f);
+static std::string asset_id_to_filename(const LLUUID &asset_id);
LLWearable::LLWearable(const LLTransactionID& transaction_id) :
mDefinitionVersion(LLWearable::sCurrentDefinitionVersion),
- mType(WT_SHAPE)
+ mType(WT_INVALID)
{
mTransactionID = transaction_id;
mAssetID = mTransactionID.makeAssetID(gAgent.getSecureSessionID());
@@ -129,7 +70,7 @@ LLWearable::LLWearable(const LLTransactionID& transaction_id) :
LLWearable::LLWearable(const LLAssetID& asset_id) :
mDefinitionVersion( LLWearable::sCurrentDefinitionVersion ),
- mType(WT_SHAPE)
+ mType(WT_INVALID)
{
mAssetID = asset_id;
mTransactionID.setNull();
@@ -139,56 +80,22 @@ LLWearable::~LLWearable()
{
}
-
-// static
-EWearableType LLWearable::typeNameToType( const std::string& type_name )
+const std::string& LLWearable::getTypeLabel() const
{
- for( S32 i = 0; i < WT_COUNT; i++ )
- {
- if( type_name == LLWearable::sTypeName[ i ] )
- {
- return (EWearableType)i;
- }
- }
- return WT_INVALID;
+ return LLWearableDictionary::getTypeLabel(mType);
}
-
-std::string terse_F32_to_string( F32 f )
+const std::string& LLWearable::getTypeName() const
{
- std::string r = llformat( "%.2f", f );
-
- // "1.20" -> "1.2"
- // "24.00" -> "24."
- S32 len = r.length();
- while( len > 0 && '0' == r[len - 1] )
- {
- r.erase(len-1, 1);
- len--;
- }
-
- if( '.' == r[len - 1] )
- {
- // "24." -> "24"
- r.erase(len-1, 1);
- }
- else
- if( ('-' == r[0]) && ('0' == r[1]) )
- {
- // "-0.59" -> "-.59"
- r.erase(1, 1);
- }
- else
- if( '0' == r[0] )
- {
- // "0.59" -> ".59"
- r.erase(0, 1);
- }
+ return LLWearableDictionary::getTypeName(mType);
+}
- return r;
+LLAssetType::EType LLWearable::getAssetType() const
+{
+ return LLWearableDictionary::getAssetType(mType);
}
-BOOL LLWearable::exportFile( LLFILE* file )
+BOOL LLWearable::exportFile(LLFILE* file) const
{
// header and version
if( fprintf( file, "LLWearable version %d\n", mDefinitionVersion ) < 0 )
@@ -228,17 +135,19 @@ BOOL LLWearable::exportFile( LLFILE* file )
}
// parameters
- S32 num_parameters = mVisualParamMap.size();
+ S32 num_parameters = mVisualParamIndexMap.size();
if( fprintf( file, "parameters %d\n", num_parameters ) < 0 )
{
return FALSE;
}
- for (param_map_t::iterator iter = mVisualParamMap.begin();
- iter != mVisualParamMap.end(); ++iter)
+ for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin();
+ iter != mVisualParamIndexMap.end();
+ ++iter)
{
S32 param_id = iter->first;
- F32 param_weight = iter->second;
+ const LLVisualParam* param = iter->second;
+ F32 param_weight = param->getWeight();
if( fprintf( file, "%d %s\n", param_id, terse_F32_to_string( param_weight ).c_str() ) < 0 )
{
return FALSE;
@@ -252,21 +161,52 @@ BOOL LLWearable::exportFile( LLFILE* file )
return FALSE;
}
- for (te_map_t::iterator iter = mTEMap.begin();
- iter != mTEMap.end(); ++iter)
+ for (te_map_t::const_iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter)
{
S32 te = iter->first;
- LLUUID& image_id = iter->second;
+ const LLUUID& image_id = iter->second->getID();
if( fprintf( file, "%d %s\n", te, image_id.asString().c_str()) < 0 )
{
return FALSE;
}
}
-
return TRUE;
}
+void LLWearable::createVisualParams()
+{
+ LLVOAvatar* avatar = gAgent.getAvatarObject();
+ for (LLViewerVisualParam* param = (LLViewerVisualParam*) avatar->getFirstVisualParam();
+ param;
+ param = (LLViewerVisualParam*) avatar->getNextVisualParam())
+ {
+ if (param->getWearableType() == mType)
+ {
+ addVisualParam(param->cloneParam(this));
+ }
+ }
+
+ // resync driver parameters to point to the newly cloned driven parameters
+ for (visual_param_index_map_t::iterator param_iter = mVisualParamIndexMap.begin();
+ param_iter != mVisualParamIndexMap.end();
+ ++param_iter)
+ {
+ LLVisualParam* param = param_iter->second;
+ LLVisualParam*(LLWearable::*wearable_function)(S32)const = &LLWearable::getVisualParam;
+ // need this line to disambiguate between versions of LLCharacter::getVisualParam()
+ LLVisualParam*(LLVOAvatarSelf::*avatar_function)(S32)const = &LLVOAvatarSelf::getVisualParam;
+ param->resetDrivenParams();
+ if(!param->linkDrivenParams(boost::bind(wearable_function,(LLWearable*)this, _1), false))
+ {
+ if( !param->linkDrivenParams(boost::bind(avatar_function,(LLVOAvatarSelf*)avatar,_1 ), true))
+ {
+ llwarns << "could not link driven params for wearable " << getName() << " id: " << param->getID() << llendl;
+ continue;
+ }
+ }
+ }
+}
BOOL LLWearable::importFile( LLFILE* file )
{
@@ -287,7 +227,13 @@ BOOL LLWearable::importFile( LLFILE* file )
return FALSE;
}
- if( mDefinitionVersion > LLWearable::sCurrentDefinitionVersion )
+
+ // Temoprary hack to allow wearables with definition version 24 to still load.
+ // This should only affect lindens and NDA'd testers who have saved wearables in 2.0
+ // the extra check for version == 24 can be removed before release, once internal testers
+ // have loaded these wearables again. See hack pt 2 at bottom of function to ensure that
+ // these wearables get re-saved with version definition 22.
+ if( mDefinitionVersion > LLWearable::sCurrentDefinitionVersion && mDefinitionVersion != 24 )
{
llwarns << "Wearable asset has newer version (" << mDefinitionVersion << ") than XML (" << LLWearable::sCurrentDefinitionVersion << ")" << llendl;
return FALSE;
@@ -390,7 +336,7 @@ BOOL LLWearable::importFile( LLFILE* file )
}
if( 0 <= type && type < WT_COUNT )
{
- mType = (EWearableType)type;
+ setType((EWearableType)type);
}
else
{
@@ -399,7 +345,6 @@ BOOL LLWearable::importFile( LLFILE* file )
return FALSE;
}
-
// parameters header
S32 num_parameters = 0;
fields_read = fscanf( file, "parameters %d\n", &num_parameters );
@@ -409,6 +354,11 @@ BOOL LLWearable::importFile( LLFILE* file )
return FALSE;
}
+ if( num_parameters != mVisualParamIndexMap.size() )
+ {
+ llwarns << "Wearable parameter mismatch. Reading in " << num_parameters << " from file, but created " << mVisualParamIndexMap.size() << " from avatar parameters. type: " << mType << llendl;
+ }
+
// parameters
S32 i;
for( i = 0; i < num_parameters; i++ )
@@ -421,7 +371,7 @@ BOOL LLWearable::importFile( LLFILE* file )
llwarns << "Bad Wearable asset: bad parameter, #" << i << llendl;
return FALSE;
}
- mVisualParamMap[param_id] = param_weight;
+ mSavedVisualParamMap[param_id] = param_weight;
}
// textures header
@@ -452,10 +402,26 @@ BOOL LLWearable::importFile( LLFILE* file )
llwarns << "Bad Wearable asset: bad texture uuid: " << text_buffer << llendl;
return FALSE;
}
+ LLUUID id = LLUUID(text_buffer);
+ LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( id );
+ if( mTEMap.find(te) != mTEMap.end() )
+ {
+ delete mTEMap[te];
+ }
+ if( mSavedTEMap.find(te) != mSavedTEMap.end() )
+ {
+ delete mSavedTEMap[te];
+ }
- mTEMap[te] = LLUUID(text_buffer );
+ LLUUID textureid(text_buffer);
+ mTEMap[te] = new LLLocalTextureObject(image, textureid);
+ mSavedTEMap[te] = new LLLocalTextureObject(image, textureid);
+ createLayers(te);
}
+ // copy all saved param values to working params
+ revertValues();
+
return TRUE;
}
@@ -463,7 +429,7 @@ BOOL LLWearable::importFile( LLFILE* file )
// Avatar parameter and texture definitions can change over time.
// This function returns true if parameters or textures have been added or removed
// since this wearable was created.
-BOOL LLWearable::isOldVersion()
+BOOL LLWearable::isOldVersion() const
{
LLVOAvatar* avatar = gAgent.getAvatarObject();
llassert( avatar );
@@ -491,13 +457,13 @@ BOOL LLWearable::isOldVersion()
if( (param->getWearableType() == mType) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
{
param_count++;
- if( !is_in_map(mVisualParamMap, param->getID() ) )
+ if( !is_in_map(mVisualParamIndexMap, param->getID() ) )
{
return TRUE;
}
}
}
- if( param_count != mVisualParamMap.size() )
+ if( param_count != mVisualParamIndexMap.size() )
{
return TRUE;
}
@@ -506,7 +472,7 @@ BOOL LLWearable::isOldVersion()
S32 te_count = 0;
for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
{
- if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == mType )
+ if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType)
{
te_count++;
if( !is_in_map(mTEMap, te ) )
@@ -530,7 +496,7 @@ BOOL LLWearable::isOldVersion()
// * If parameters or textures have been ADDED since the wearable was created,
// they are taken to have default values, so we consider the wearable clean
// only if those values are the same as the defaults.
-BOOL LLWearable::isDirty()
+BOOL LLWearable::isDirty() const
{
LLVOAvatar* avatar = gAgent.getAvatarObject();
llassert( avatar );
@@ -544,13 +510,17 @@ BOOL LLWearable::isDirty()
param;
param = (LLViewerVisualParam*) avatar->getNextVisualParam() )
{
- if( (param->getWearableType() == mType) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
+ if( (param->getWearableType() == mType)
+ && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE )
+ && !param->getCrossWearable())
{
- F32 weight = get_if_there(mVisualParamMap, param->getID(), param->getDefaultWeight());
- weight = llclamp( weight, param->getMinWeight(), param->getMaxWeight() );
+ F32 current_weight = getVisualParamWeight(param->getID());
+ current_weight = llclamp( current_weight, param->getMinWeight(), param->getMaxWeight() );
+ F32 saved_weight = get_if_there(mSavedVisualParamMap, param->getID(), param->getDefaultWeight());
+ saved_weight = llclamp( saved_weight, param->getMinWeight(), param->getMaxWeight() );
- U8 a = F32_to_U8( param->getWeight(), param->getMinWeight(), param->getMaxWeight() );
- U8 b = F32_to_U8( weight, param->getMinWeight(), param->getMaxWeight() );
+ U8 a = F32_to_U8( saved_weight, param->getMinWeight(), param->getMaxWeight() );
+ U8 b = F32_to_U8( current_weight, param->getMinWeight(), param->getMaxWeight() );
if( a != b )
{
return TRUE;
@@ -560,18 +530,27 @@ BOOL LLWearable::isDirty()
for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
{
- if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == mType )
+ if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType)
{
- LLViewerImage* avatar_image = avatar->getTEImage( te );
- if( !avatar_image )
+ te_map_t::const_iterator current_iter = mTEMap.find(te);
+ if(current_iter != mTEMap.end())
{
- llassert( 0 );
- continue;
- }
- const LLUUID& image_id = get_if_there(mTEMap, te, LLVOAvatar::getDefaultTEImageID((ETextureIndex) te ) );
- if( avatar_image->getID() != image_id )
- {
- return TRUE;
+ const LLUUID& current_image_id = current_iter->second->getID();
+ te_map_t::const_iterator saved_iter = mSavedTEMap.find(te);
+ if(saved_iter != mSavedTEMap.end())
+ {
+ const LLUUID& saved_image_id = saved_iter->second->getID();
+ if (saved_image_id != current_image_id)
+ {
+ // saved vs current images are different, wearable is dirty
+ return TRUE;
+ }
+ }
+ else
+ {
+ // image found in current image list but not saved image list
+ return TRUE;
+ }
}
}
}
@@ -597,35 +576,47 @@ void LLWearable::setParamsToDefaults()
return;
}
- mVisualParamMap.clear();
for( LLVisualParam* param = avatar->getFirstVisualParam(); param; param = avatar->getNextVisualParam() )
{
if( (((LLViewerVisualParam*)param)->getWearableType() == mType ) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
{
- mVisualParamMap[param->getID()] = param->getDefaultWeight();
+ setVisualParamWeight(param->getID(),param->getDefaultWeight(), FALSE);
}
}
}
void LLWearable::setTexturesToDefaults()
{
- mTEMap.clear();
for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
{
- if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == mType )
+ if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType)
{
- mTEMap[te] = LLVOAvatar::getDefaultTEImageID((ETextureIndex) te );
+ LLUUID id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te);
+ LLViewerFetchedTexture * image = LLViewerTextureManager::getFetchedTexture( id );
+ if( mTEMap.find(te) == mTEMap.end() )
+ {
+ mTEMap[te] = new LLLocalTextureObject(image, id);
+ createLayers(te);
+ }
+ else
+ {
+ // Local Texture Object already created, just set image and UUID
+ LLLocalTextureObject *lto = mTEMap[te];
+ lto->setID(id);
+ lto->setImage(image);
+ }
}
}
}
// Updates the user's avatar's appearance
-void LLWearable::writeToAvatar( BOOL set_by_user )
+void LLWearable::writeToAvatar()
{
- LLVOAvatar* avatar = gAgent.getAvatarObject();
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
llassert( avatar );
if( !avatar )
{
+ llerrs << "could not get avatar object to write to for wearable " << this->getName() << llendl;
return;
}
@@ -634,79 +625,54 @@ void LLWearable::writeToAvatar( BOOL set_by_user )
// Pull params
for( LLVisualParam* param = avatar->getFirstVisualParam(); param; param = avatar->getNextVisualParam() )
{
- if( (((LLViewerVisualParam*)param)->getWearableType() == mType) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
+ if( (((LLViewerVisualParam*)param)->getWearableType() == mType) )
{
S32 param_id = param->getID();
- F32 weight = get_if_there(mVisualParamMap, param_id, param->getDefaultWeight());
- // only animate with user-originated changes
- if (set_by_user)
- {
- param->setAnimationTarget(weight, set_by_user);
- }
- else
- {
- avatar->setVisualParamWeight( param_id, weight, set_by_user );
- }
- }
- }
+ F32 weight = getVisualParamWeight(param_id);
- // only interpolate with user-originated changes
- if (set_by_user)
- {
- avatar->startAppearanceAnimation(TRUE, TRUE);
+ avatar->setVisualParamWeight( param_id, weight, FALSE );
+ }
}
// Pull texture entries
for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
{
- if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == mType )
+ if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType)
{
- const LLUUID& image_id = get_if_there(mTEMap, te, LLVOAvatar::getDefaultTEImageID((ETextureIndex) te ) );
- LLViewerImage* image = gImageList.getImage( image_id );
- avatar->setLocTexTE( te, image, set_by_user );
- }
- }
-
- avatar->updateVisualParams();
-
- if( gFloaterCustomize )
- {
- LLViewerInventoryItem* item;
- item = (LLViewerInventoryItem*)gInventory.getItem(gAgent.getWearableItem(mType));
- U32 perm_mask = PERM_NONE;
- BOOL is_complete = FALSE;
- if(item)
- {
- perm_mask = item->getPermissions().getMaskOwner();
- is_complete = item->isComplete();
- if(!is_complete)
+ te_map_t::const_iterator iter = mTEMap.find(te);
+ LLUUID image_id;
+ if(iter != mTEMap.end())
{
- item->fetchFromServer();
+ image_id = iter->second->getID();
+ }
+ else
+ {
+ image_id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te);
}
+ LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE );
+ // MULTI-WEARABLE: replace hard-coded 0
+ avatar->setLocalTextureTE(te, image, 0);
}
- gFloaterCustomize->setWearable(mType, this, perm_mask, is_complete);
- LLFloaterCustomize::setCurrentWearableType( mType );
}
ESex new_sex = avatar->getSex();
if( old_sex != new_sex )
{
- avatar->updateSexDependentLayerSets( set_by_user );
+ avatar->updateSexDependentLayerSets( FALSE );
}
- avatar->updateMeshTextures();
-
-// if( set_by_user )
+// if( upload_bake )
// {
// gAgent.sendAgentSetAppearance();
// }
}
+
// Updates the user's avatar's appearance, replacing this wearables' parameters and textures with default values.
// static
-void LLWearable::removeFromAvatar( EWearableType type, BOOL set_by_user )
+void LLWearable::removeFromAvatar( EWearableType type, BOOL upload_bake )
{
- LLVOAvatar* avatar = gAgent.getAvatarObject();
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
llassert( avatar );
if( !avatar )
{
@@ -728,17 +694,7 @@ void LLWearable::removeFromAvatar( EWearableType type, BOOL set_by_user )
if( (((LLViewerVisualParam*)param)->getWearableType() == type) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
{
S32 param_id = param->getID();
- avatar->setVisualParamWeight( param_id, param->getDefaultWeight(), set_by_user );
- }
- }
-
- // Pull textures
- LLViewerImage* image = gImageList.getImage( IMG_DEFAULT_AVATAR );
- for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
- {
- if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == type )
- {
- avatar->setLocTexTE( te, image, set_by_user );
+ avatar->setVisualParamWeight( param_id, param->getDefaultWeight(), upload_bake );
}
}
@@ -748,20 +704,19 @@ void LLWearable::removeFromAvatar( EWearableType type, BOOL set_by_user )
}
avatar->updateVisualParams();
- avatar->updateMeshTextures();
+ avatar->wearableUpdated(type, TRUE);
-// if( set_by_user )
+// if( upload_bake )
// {
// gAgent.sendAgentSetAppearance();
// }
}
-
-
-// Updates asset from the user's avatar
-void LLWearable::readFromAvatar()
+// Does not copy mAssetID.
+// Definition version is current: removes obsolete enties and creates default values for new ones.
+void LLWearable::copyDataFrom(const LLWearable* src)
{
- LLVOAvatar* avatar = gAgent.getAvatarObject();
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
llassert( avatar );
if( !avatar )
{
@@ -770,91 +725,396 @@ void LLWearable::readFromAvatar()
mDefinitionVersion = LLWearable::sCurrentDefinitionVersion;
- mVisualParamMap.clear();
- for( LLVisualParam* param = avatar->getFirstVisualParam(); param; param = avatar->getNextVisualParam() )
+ mName = src->mName;
+ mDescription = src->mDescription;
+ mPermissions = src->mPermissions;
+ mSaleInfo = src->mSaleInfo;
+
+ setType(src->mType);
+
+ mSavedVisualParamMap.clear();
+ // Deep copy of mVisualParamMap (copies only those params that are current, filling in defaults where needed)
+ for( LLViewerVisualParam* param = (LLViewerVisualParam*) avatar->getFirstVisualParam();
+ param;
+ param = (LLViewerVisualParam*) avatar->getNextVisualParam() )
{
- if( (((LLViewerVisualParam*)param)->getWearableType() == mType) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
+ if( (param->getWearableType() == mType) )
{
- mVisualParamMap[param->getID()] = param->getWeight();
+ S32 id = param->getID();
+ F32 weight = src->getVisualParamWeight(id);
+ mSavedVisualParamMap[id] = weight;
}
}
- mTEMap.clear();
+ destroyTextures();
+ // Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed)
for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
{
- if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == mType )
+ if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType)
{
- LLViewerImage* image = avatar->getTEImage( te );
- if( image )
+ te_map_t::const_iterator iter = src->mTEMap.find(te);
+ LLUUID image_id;
+ LLViewerFetchedTexture *image = NULL;
+ if(iter != src->mTEMap.end())
+ {
+ image = src->getConstLocalTextureObject(te)->getImage();
+ image_id = src->getConstLocalTextureObject(te)->getID();
+ mTEMap[te] = new LLLocalTextureObject(image, image_id);
+ mSavedTEMap[te] = new LLLocalTextureObject(image, image_id);
+ mTEMap[te]->setBakedReady(src->getConstLocalTextureObject(te)->getBakedReady());
+ mTEMap[te]->setDiscard(src->getConstLocalTextureObject(te)->getDiscard());
+ }
+ else
{
- mTEMap[te] = image->getID();
+ image_id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te);
+ image = LLViewerTextureManager::getFetchedTexture( image_id );
+ mTEMap[te] = new LLLocalTextureObject(image, image_id);
+ mSavedTEMap[te] = new LLLocalTextureObject(image, image_id);
}
+ createLayers(te);
}
}
- //if( gFloaterCustomize )
- //{
- // mDescription = gFloaterCustomize->getWearableDescription( mType );
- //}
+ // Probably reduntant, but ensure that the newly created wearable is not dirty by setting current value of params in new wearable
+ // to be the same as the saved values (which were loaded from src at param->cloneParam(this))
+ revertValues();
}
-// Does not copy mAssetID.
-// Definition version is current: removes obsolete enties and creates default values for new ones.
-void LLWearable::copyDataFrom( LLWearable* src )
+void LLWearable::setItemID(const LLUUID& item_id)
{
- LLVOAvatar* avatar = gAgent.getAvatarObject();
- llassert( avatar );
- if( !avatar )
+ mItemID = item_id;
+}
+
+const LLUUID& LLWearable::getItemID() const
+{
+ return mItemID;
+}
+
+void LLWearable::setType(EWearableType type)
+{
+ mType = type;
+ createVisualParams();
+}
+
+LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index)
+{
+ te_map_t::iterator iter = mTEMap.find(index);
+ if( iter != mTEMap.end() )
{
- return;
+ LLLocalTextureObject* lto = iter->second;
+ return lto;
}
+ return NULL;
+}
- mDefinitionVersion = LLWearable::sCurrentDefinitionVersion;
+const LLLocalTextureObject* LLWearable::getConstLocalTextureObject(S32 index) const
+{
+ te_map_t::const_iterator iter = mTEMap.find(index);
+ if( iter != mTEMap.end() )
+ {
+ const LLLocalTextureObject* lto = iter->second;
+ return lto;
+ }
+ return NULL;
+}
- mName = src->mName;
- mDescription = src->mDescription;
- mPermissions = src->mPermissions;
- mSaleInfo = src->mSaleInfo;
- mType = src->mType;
+void LLWearable::setLocalTextureObject(S32 index, LLLocalTextureObject *lto)
+{
+ if( mTEMap.find(index) != mTEMap.end() )
+ {
+ mTEMap.erase(index);
+ }
+ if( lto )
+ {
+ mTEMap[index] = new LLLocalTextureObject(*lto);
+ }
+}
- // Deep copy of mVisualParamMap (copies only those params that are current, filling in defaults where needed)
- for( LLViewerVisualParam* param = (LLViewerVisualParam*) avatar->getFirstVisualParam();
- param;
- param = (LLViewerVisualParam*) avatar->getNextVisualParam() )
+
+void LLWearable::addVisualParam(LLVisualParam *param)
+{
+ if( mVisualParamIndexMap[param->getID()] )
{
- if( (param->getWearableType() == mType) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
+ delete mVisualParamIndexMap[param->getID()];
+ }
+ param->setIsDummy(FALSE);
+ mVisualParamIndexMap[param->getID()] = param;
+ mSavedVisualParamMap[param->getID()] = param->getDefaultWeight();
+}
+
+void LLWearable::setVisualParams()
+{
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+
+ for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); iter++)
+ {
+ S32 id = iter->first;
+ LLVisualParam *wearable_param = iter->second;
+ F32 value = wearable_param->getWeight();
+ avatar->setVisualParamWeight(id, value, FALSE);
+ }
+}
+
+
+void LLWearable::setVisualParamWeight(S32 param_index, F32 value, BOOL upload_bake)
+{
+ if( is_in_map(mVisualParamIndexMap, param_index ) )
+ {
+ LLVisualParam *wearable_param = mVisualParamIndexMap[param_index];
+ wearable_param->setWeight(value, upload_bake);
+ }
+ else
+ {
+ llerrs << "LLWearable::setVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << llendl;
+ }
+}
+
+F32 LLWearable::getVisualParamWeight(S32 param_index) const
+{
+ if( is_in_map(mVisualParamIndexMap, param_index ) )
+ {
+ const LLVisualParam *wearable_param = mVisualParamIndexMap.find(param_index)->second;
+ return wearable_param->getWeight();
+ }
+ else
+ {
+ llwarns << "LLWerable::getVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << llendl;
+ }
+ return (F32)-1.0;
+}
+
+LLVisualParam* LLWearable::getVisualParam(S32 index) const
+{
+ visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.find(index);
+ return (iter == mVisualParamIndexMap.end()) ? NULL : iter->second;
+}
+
+
+void LLWearable::getVisualParams(visual_param_vec_t &list)
+{
+ visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin();
+ visual_param_index_map_t::iterator end = mVisualParamIndexMap.end();
+
+ // add all visual params to the passed-in vector
+ for( ; iter != end; ++iter )
+ {
+ list.push_back(iter->second);
+ }
+}
+
+void LLWearable::animateParams(F32 delta, BOOL upload_bake)
+{
+ for(visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin();
+ iter != mVisualParamIndexMap.end();
+ ++iter)
+ {
+ LLVisualParam *param = (LLVisualParam*) iter->second;
+ param->animate(delta, upload_bake);
+ }
+}
+
+LLColor4 LLWearable::getClothesColor(S32 te) const
+{
+ LLColor4 color;
+ U32 param_name[3];
+ if( LLVOAvatar::teToColorParams( (LLVOAvatarDefines::ETextureIndex)te, param_name ) )
+ {
+ for( U8 index = 0; index < 3; index++ )
{
- S32 id = param->getID();
- F32 weight = get_if_there(src->mVisualParamMap, id, param->getDefaultWeight() );
- mVisualParamMap[id] = weight;
+ color.mV[index] = getVisualParamWeight(param_name[index]);
+ }
+ }
+ return color;
+}
+
+void LLWearable::setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake )
+{
+ U32 param_name[3];
+ if( LLVOAvatar::teToColorParams( (LLVOAvatarDefines::ETextureIndex)te, param_name ) )
+ {
+ for( U8 index = 0; index < 3; index++ )
+ {
+ setVisualParamWeight(param_name[index], new_color.mV[index], upload_bake);
+ }
+ }
+}
+
+void LLWearable::revertValues()
+{
+ //update saved settings so wearable is no longer dirty
+ // non-driver params first
+ for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++)
+ {
+ S32 id = iter->first;
+ F32 value = iter->second;
+ LLVisualParam *param = getVisualParam(id);
+ if(param && !dynamic_cast<LLDriverParam*>(param) )
+ {
+ setVisualParamWeight(id, value, TRUE);
+ }
+ }
+
+ //then driver params
+ for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++)
+ {
+ S32 id = iter->first;
+ F32 value = iter->second;
+ LLVisualParam *param = getVisualParam(id);
+ if(param && dynamic_cast<LLDriverParam*>(param) )
+ {
+ setVisualParamWeight(id, value, TRUE);
+ }
+ }
+
+ // make sure that saved values are sane
+ for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++)
+ {
+ S32 id = iter->first;
+ LLVisualParam *param = getVisualParam(id);
+ if( param )
+ {
+ mSavedVisualParamMap[id] = param->getWeight();
}
}
+ syncImages(mSavedTEMap, mTEMap);
+
+ if( gFloaterCustomize )
+ {
+ gFloaterCustomize->updateScrollingPanelList(TRUE);
+ }
+}
+
+BOOL LLWearable::isOnTop() const
+{
+ return (this == gAgentWearables.getTopWearable(mType));
+}
+
+void LLWearable::createLayers(S32 te)
+{
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ LLTexLayerSet *layer_set = avatar->getLayerSet((ETextureIndex)te);
+ if( layer_set )
+ {
+ layer_set->cloneTemplates(mTEMap[te], (ETextureIndex)te, this);
+ }
+ else
+ {
+ llerrs << "could not find layerset for LTO in wearable!" << llendl;
+ }
+}
+
+void LLWearable::saveValues()
+{
+ //update saved settings so wearable is no longer dirty
+ mSavedVisualParamMap.clear();
+ for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter)
+ {
+ S32 id = iter->first;
+ LLVisualParam *wearable_param = iter->second;
+ F32 value = wearable_param->getWeight();
+ mSavedVisualParamMap[id] = value;
+ }
+
// Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed)
+ syncImages(mTEMap, mSavedTEMap);
+
+ if( gFloaterCustomize )
+ {
+ gFloaterCustomize->updateScrollingPanelList(TRUE);
+ }
+}
+
+void LLWearable::syncImages(te_map_t &src, te_map_t &dst)
+{
+ // Deep copy of src (copies only those tes that are current, filling in defaults where needed)
for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
{
- if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == mType )
+ if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType)
{
- const LLUUID& image_id = get_if_there(src->mTEMap, te, LLVOAvatar::getDefaultTEImageID((ETextureIndex) te ) );
- mTEMap[te] = image_id;
+ te_map_t::const_iterator iter = src.find(te);
+ LLUUID image_id;
+ LLViewerFetchedTexture *image = NULL;
+ LLLocalTextureObject *lto = NULL;
+ if(iter != src.end())
+ {
+ // there's a Local Texture Object in the source image map. Use this to populate the values to store in the destination image map.
+ lto = iter->second;
+ image = lto->getImage();
+ image_id = lto->getID();
+ }
+ else
+ {
+ // there is no Local Texture Object in the source image map. Get defaults values for populating the destination image map.
+ image_id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te);
+ image = LLViewerTextureManager::getFetchedTexture( image_id );
+ }
+
+ if( dst.find(te) != dst.end() )
+ {
+ // there's already an entry in the destination map for the texture. Just update its values.
+ dst[te]->setImage(image);
+ dst[te]->setID(image_id);
+ }
+ else
+ {
+ // no entry found in the destination map, we need to create a new Local Texture Object
+ dst[te] = new LLLocalTextureObject(image, image_id);
+ }
+
+ if( lto )
+ {
+ // If we pulled values from a Local Texture Object in the source map, make sure the proper flags are set in the new (or updated) entry in the destination map.
+ dst[te]->setBakedReady(lto->getBakedReady());
+ dst[te]->setDiscard(lto->getDiscard());
+ }
}
}
}
+void LLWearable::destroyTextures()
+{
+ for( te_map_t::iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter )
+ {
+ LLLocalTextureObject *lto = iter->second;
+ delete lto;
+ }
+ mTEMap.clear();
+ for( te_map_t::iterator iter = mSavedTEMap.begin(); iter != mSavedTEMap.end(); ++iter )
+ {
+ LLLocalTextureObject *lto = iter->second;
+ delete lto;
+ }
+ mSavedTEMap.clear();
+}
+
+
+void LLWearable::setLabelUpdated() const
+{
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, getItemID());
+}
+
+void LLWearable::refreshName()
+{
+ LLUUID item_id = getItemID();
+ LLInventoryItem* item = gInventory.getItem(item_id);
+ if( item )
+ {
+ mName = item->getName();
+ }
+}
+
struct LLWearableSaveData
{
EWearableType mType;
};
-void LLWearable::saveNewAsset()
+void LLWearable::saveNewAsset() const
{
// llinfos << "LLWearable::saveNewAsset() type: " << getTypeName() << llendl;
//llinfos << *this << llendl;
- std::string new_asset_id_string;
- mAssetID.toString(new_asset_id_string);
- std::string filename;
- filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,new_asset_id_string) + ".wbl";
+ const std::string filename = asset_id_to_filename(mAssetID);
LLFILE* fp = LLFile::fopen(filename, "wb"); /* Flawfinder: ignore */
BOOL successful_save = FALSE;
if(fp && exportFile(fp))
@@ -873,7 +1133,7 @@ void LLWearable::saveNewAsset()
LLSD args;
args["NAME"] = mName;
- LLNotifications::instance().add("CannotSaveWearableOutOfSpace", args);
+ LLNotificationsUtil::add("CannotSaveWearableOutOfSpace", args);
return;
}
@@ -886,7 +1146,7 @@ void LLWearable::saveNewAsset()
{
llinfos << "Update Agent Inventory via capability" << llendl;
LLSD body;
- body["folder_id"] = gInventory.findCategoryUUIDForType(getAssetType());
+ body["folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::assetToFolderType(getAssetType()));
body["asset_type"] = LLAssetType::lookup(getAssetType());
body["inventory_type"] = LLInventoryType::lookup(LLInventoryType::IT_WEARABLE);
body["name"] = getName();
@@ -909,7 +1169,7 @@ void LLWearable::saveNewAsset()
void LLWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void* userdata, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed)
{
LLWearableSaveData* data = (LLWearableSaveData*)userdata;
- const std::string& type_name = LLWearable::typeToTypeName(data->mType);
+ const std::string& type_name = LLWearableDictionary::getTypeName(data->mType);
if(0 == status)
{
// Success
@@ -921,43 +1181,33 @@ void LLWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void* userda
llwarns << buffer << " Status: " << status << llendl;
LLSD args;
args["NAME"] = type_name;
- LLNotifications::instance().add("CannotSaveToAssetStore", args);
+ LLNotificationsUtil::add("CannotSaveToAssetStore", args);
}
// Delete temp file
- std::string new_asset_id_string;
- new_asset_id.toString(new_asset_id_string);
- std::string src_filename;
- src_filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,new_asset_id_string) + ".wbl";
+ const std::string src_filename = asset_id_to_filename(new_asset_id);
LLFile::remove(src_filename);
// delete the context data
delete data;
-}
-BOOL LLWearable::isMatchedToInventoryItem( LLViewerInventoryItem* item )
-{
- return
- ( mName == item->getName() ) &&
- ( mDescription == item->getDescription() ) &&
- ( mPermissions == item->getPermissions() ) &&
- ( mSaleInfo == item->getSaleInfo() );
}
std::ostream& operator<<(std::ostream &s, const LLWearable &w)
{
- s << "wearable " << LLWearable::typeToTypeName( w.mType ) << "\n";
+ s << "wearable " << LLWearableDictionary::getTypeName(w.mType) << "\n";
s << " Name: " << w.mName << "\n";
s << " Desc: " << w.mDescription << "\n";
//w.mPermissions
//w.mSaleInfo
s << " Params:" << "\n";
- for (LLWearable::param_map_t::const_iterator iter = w.mVisualParamMap.begin();
- iter != w.mVisualParamMap.end(); ++iter)
+ for (LLWearable::visual_param_index_map_t::const_iterator iter = w.mVisualParamIndexMap.begin();
+ iter != w.mVisualParamIndexMap.end(); ++iter)
{
S32 param_id = iter->first;
- F32 param_weight = iter->second;
+ LLVisualParam *wearable_param = iter->second;
+ F32 param_weight = wearable_param->getWeight();
s << " " << param_id << " " << param_weight << "\n";
}
@@ -966,10 +1216,47 @@ std::ostream& operator<<(std::ostream &s, const LLWearable &w)
iter != w.mTEMap.end(); ++iter)
{
S32 te = iter->first;
- const LLUUID& image_id = iter->second;
+ const LLUUID& image_id = iter->second->getID();
s << " " << te << " " << image_id << "\n";
}
return s;
}
+std::string terse_F32_to_string(F32 f)
+{
+ std::string r = llformat("%.2f", f);
+ S32 len = r.length();
+
+ // "1.20" -> "1.2"
+ // "24.00" -> "24."
+ while (len > 0 && ('0' == r[len - 1]))
+ {
+ r.erase(len-1, 1);
+ len--;
+ }
+ if ('.' == r[len - 1])
+ {
+ // "24." -> "24"
+ r.erase(len-1, 1);
+ }
+ else if (('-' == r[0]) && ('0' == r[1]))
+ {
+ // "-0.59" -> "-.59"
+ r.erase(1, 1);
+ }
+ else if ('0' == r[0])
+ {
+ // "0.59" -> ".59"
+ r.erase(0, 1);
+ }
+ return r;
+}
+
+std::string asset_id_to_filename(const LLUUID &asset_id)
+{
+ std::string asset_id_string;
+ asset_id.toString(asset_id_string);
+ std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id_string) + ".wbl";
+ return filename;
+}
diff --git a/indra/newview/llwearable.h b/indra/newview/llwearable.h
index 683a8fa928..7a579b248e 100644
--- a/indra/newview/llwearable.h
+++ b/indra/newview/llwearable.h
@@ -19,7 +19,7 @@
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
+ *
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
@@ -38,91 +38,114 @@
#include "llpermissions.h"
#include "llsaleinfo.h"
#include "llassetstorage.h"
+#include "llwearabledictionary.h"
+#include "llfile.h"
+#include "lllocaltextureobject.h"
class LLViewerInventoryItem;
-
-enum EWearableType // If you change this, update LLWearable::getTypeName(), getTypeLabel(), and LLVOAvatar::getTEWearableType()
-{
- WT_SHAPE = 0,
- WT_SKIN = 1,
- WT_HAIR = 2,
- WT_EYES = 3,
- WT_SHIRT = 4,
- WT_PANTS = 5,
- WT_SHOES = 6,
- WT_SOCKS = 7,
- WT_JACKET = 8,
- WT_GLOVES = 9,
- WT_UNDERSHIRT = 10,
- WT_UNDERPANTS = 11,
- WT_SKIRT = 12,
- WT_COUNT = 13,
- WT_INVALID = 255
-};
+class LLVisualParam;
+class LLTexGlobalColorInfo;
+class LLTexGlobalColor;
class LLWearable
{
friend class LLWearableList;
+
+ //--------------------------------------------------------------------
+ // Constructors and destructors
+ //--------------------------------------------------------------------
+private:
+ // Private constructors used by LLWearableList
+ LLWearable(const LLTransactionID& transactionID);
+ LLWearable(const LLAssetID& assetID);
public:
- ~LLWearable();
+ virtual ~LLWearable();
- const LLAssetID& getID() const { return mAssetID; }
+ //--------------------------------------------------------------------
+ // Accessors
+ //--------------------------------------------------------------------
+public:
+ const LLUUID& getItemID() const;
+ const LLAssetID& getAssetID() const { return mAssetID; }
const LLTransactionID& getTransactionID() const { return mTransactionID; }
+ EWearableType getType() const { return mType; }
+ void setType(EWearableType type);
+ const std::string& getName() const { return mName; }
+ void setName(const std::string& name) { mName = name; }
+ const std::string& getDescription() const { return mDescription; }
+ void setDescription(const std::string& desc) { mDescription = desc; }
+ const LLPermissions& getPermissions() const { return mPermissions; }
+ void setPermissions(const LLPermissions& p) { mPermissions = p; }
+ const LLSaleInfo& getSaleInfo() const { return mSaleInfo; }
+ void setSaleInfo(const LLSaleInfo& info) { mSaleInfo = info; }
+ const std::string& getTypeLabel() const;
+ const std::string& getTypeName() const;
+ LLAssetType::EType getAssetType() const;
+ LLLocalTextureObject* getLocalTextureObject(S32 index) const;
+ S32 getDefinitionVersion() const { return mDefinitionVersion; }
+ void setDefinitionVersion( S32 new_version ) { mDefinitionVersion = new_version; }
- BOOL isDirty();
- BOOL isOldVersion();
-
- void writeToAvatar( BOOL set_by_user );
- void readFromAvatar();
- void removeFromAvatar( BOOL set_by_user ) { LLWearable::removeFromAvatar( mType, set_by_user ); }
- static void removeFromAvatar( EWearableType type, BOOL set_by_user );
-
- BOOL exportFile(LLFILE* file);
- BOOL importFile(LLFILE* file);
+public:
+ typedef std::vector<LLVisualParam*> visual_param_vec_t;
- EWearableType getType() const { return mType; }
- void setType( EWearableType type ) { mType = type; }
+ BOOL isDirty() const;
+ BOOL isOldVersion() const;
- void setName( const std::string& name ) { mName = name; }
- const std::string& getName() const { return mName; }
+ void writeToAvatar();
+ void removeFromAvatar( BOOL upload_bake ) { LLWearable::removeFromAvatar( mType, upload_bake ); }
+ static void removeFromAvatar( EWearableType type, BOOL upload_bake );
- void setDescription( const std::string& desc ) { mDescription = desc; }
- const std::string& getDescription() const { return mDescription; }
+ BOOL exportFile(LLFILE* file) const;
+ BOOL importFile(LLFILE* file);
+
+ void setParamsToDefaults();
+ void setTexturesToDefaults();
- void setPermissions( const LLPermissions& p ) { mPermissions = p; }
- const LLPermissions& getPermissions() const { return mPermissions; }
+ void saveNewAsset() const;
+ static void onSaveNewAssetComplete( const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status );
- void setSaleInfo( const LLSaleInfo& info ) { mSaleInfo = info; }
- const LLSaleInfo& getSaleInfo() const { return mSaleInfo; }
+ void copyDataFrom(const LLWearable* src);
- const std::string& getTypeLabel() const { return LLWearable::sTypeLabel[ mType ]; }
- const std::string& getTypeName() const { return LLWearable::sTypeName[ mType ]; }
+ static void setCurrentDefinitionVersion( S32 version ) { LLWearable::sCurrentDefinitionVersion = version; }
- void setParamsToDefaults();
- void setTexturesToDefaults();
+ friend std::ostream& operator<<(std::ostream &s, const LLWearable &w);
+ void setItemID(const LLUUID& item_id);
- LLAssetType::EType getAssetType() const { return LLWearable::typeToAssetType( mType ); }
+ LLLocalTextureObject* getLocalTextureObject(S32 index);
+ const LLLocalTextureObject* getConstLocalTextureObject(S32 index) const;
- static EWearableType typeNameToType( const std::string& type_name );
- static const std::string& typeToTypeName( EWearableType type ) { return LLWearable::sTypeName[llmin(type,WT_COUNT)]; }
- static const std::string& typeToTypeLabel( EWearableType type ) { return LLWearable::sTypeLabel[llmin(type,WT_COUNT)]; }
- static LLAssetType::EType typeToAssetType( EWearableType wearable_type );
+ void setLocalTextureObject(S32 index, LLLocalTextureObject *lto);
+ void addVisualParam(LLVisualParam *param);
+ void setVisualParams();
+ void setVisualParamWeight(S32 index, F32 value, BOOL upload_bake);
+ F32 getVisualParamWeight(S32 index) const;
+ LLVisualParam* getVisualParam(S32 index) const;
+ void getVisualParams(visual_param_vec_t &list);
+ void animateParams(F32 delta, BOOL upload_bake);
- void saveNewAsset();
- static void onSaveNewAssetComplete( const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status );
+ LLColor4 getClothesColor(S32 te) const;
+ void setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake );
- BOOL isMatchedToInventoryItem( LLViewerInventoryItem* item );
+ void revertValues();
+ void saveValues();
- void copyDataFrom( LLWearable* src );
+ BOOL isOnTop() const;
- static void setCurrentDefinitionVersion( S32 version ) { LLWearable::sCurrentDefinitionVersion = version; }
+ // Something happened that requires the wearable's label to be updated (e.g. worn/unworn).
+ void setLabelUpdated() const;
- friend std::ostream& operator<<(std::ostream &s, const LLWearable &w);
+ // the wearable was worn. make sure the name of the wearable object matches the LLViewerInventoryItem,
+ // not the wearable asset itself.
+ void refreshName();
private:
- // Private constructor used by LLWearableList
- LLWearable(const LLTransactionID& transactionID);
- LLWearable(const LLAssetID& assetID);
+ typedef std::map<S32, LLLocalTextureObject*> te_map_t;
+ typedef std::map<S32, LLVisualParam *> visual_param_index_map_t;
+
+ void createLayers(S32 te);
+ void createVisualParams();
+ void syncImages(te_map_t &src, te_map_t &dst);
+ void destroyTextures();
static S32 sCurrentDefinitionVersion; // Depends on the current state of the avatar_lad.xml.
S32 mDefinitionVersion; // Depends on the state of the avatar_lad.xml when this asset was created.
@@ -135,12 +158,13 @@ private:
EWearableType mType;
typedef std::map<S32, F32> param_map_t;
- param_map_t mVisualParamMap; // maps visual param id to weight
- typedef std::map<S32, LLUUID> te_map_t;
- te_map_t mTEMap; // maps TE to Image ID
+ param_map_t mSavedVisualParamMap; // last saved version of visual params
+
+ visual_param_index_map_t mVisualParamIndexMap;
- static const std::string sTypeName[ WT_COUNT+1 ];
- static const std::string sTypeLabel[ WT_COUNT+1 ];
+ te_map_t mTEMap; // maps TE to LocalTextureObject
+ te_map_t mSavedTEMap; // last saved version of TEMap
+ LLUUID mItemID; // ID of the inventory item in the agent's inventory
};
#endif // LL_LLWEARABLE_H
diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp
index 512c03fa4d..5636256856 100644
--- a/indra/newview/llwearablelist.cpp
+++ b/indra/newview/llwearablelist.cpp
@@ -39,22 +39,18 @@
#include "llagent.h"
#include "llvoavatar.h"
#include "llviewerinventory.h"
-//#include "llfloaterchat.h"
#include "llviewerstats.h"
-#include "llnotify.h"
-
-// Globals
-LLWearableList gWearableList; // Globally constructed; be careful that there's no dependency with gAgent.
-
+#include "llnotificationsutil.h"
+#include "llinventorymodel.h"
+#include "lltrans.h"
+// Callback struct
struct LLWearableArrivedData
{
- LLWearableArrivedData(
- LLAssetType::EType asset_type,
+ LLWearableArrivedData(LLAssetType::EType asset_type,
const std::string& wearable_name,
void(*asset_arrived_callback)(LLWearable*, void* userdata),
- void* userdata )
- :
+ void* userdata) :
mAssetType( asset_type ),
mCallback( asset_arrived_callback ),
mUserdata( userdata ),
@@ -69,18 +65,21 @@ struct LLWearableArrivedData
S32 mRetries;
};
-
-
////////////////////////////////////////////////////////////////////////////
// LLWearableList
LLWearableList::~LLWearableList()
{
+ llassert_always(mList.empty()) ;
+}
+
+void LLWearableList::cleanup()
+{
for_each(mList.begin(), mList.end(), DeletePairedPointer());
mList.clear();
}
-void LLWearableList::getAsset( const LLAssetID& assetID, const std::string& wearable_name, LLAssetType::EType asset_type, void(*asset_arrived_callback)(LLWearable*, void* userdata), void* userdata )
+void LLWearableList::getAsset(const LLAssetID& assetID, const std::string& wearable_name, LLAssetType::EType asset_type, void(*asset_arrived_callback)(LLWearable*, void* userdata), void* userdata)
{
llassert( (asset_type == LLAssetType::AT_CLOTHING) || (asset_type == LLAssetType::AT_BODYPART) );
LLWearable* instance = get_if_there(mList, assetID, (LLWearable*)NULL );
@@ -90,8 +89,7 @@ void LLWearableList::getAsset( const LLAssetID& assetID, const std::string& wear
}
else
{
- gAssetStorage->getAssetData(
- assetID,
+ gAssetStorage->getAssetData(assetID,
asset_type,
LLWearableList::processGetAssetReply,
(void*)new LLWearableArrivedData( asset_type, wearable_name, asset_arrived_callback, userdata ),
@@ -110,8 +108,7 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID
{
LL_WARNS("Wearable") << "Bad Wearable Asset: missing file." << LL_ENDL;
}
- else
- if( status >= 0 )
+ else if (status >= 0)
{
// read the file
LLFILE* fp = LLFile::fopen(std::string(filename), "rb"); /*Flawfinder: ignore*/
@@ -180,27 +177,26 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID
if (wearable) // success
{
- gWearableList.mList[ uuid ] = wearable;
+ LLWearableList::instance().mList[ uuid ] = wearable;
LL_DEBUGS("Wearable") << "processGetAssetReply()" << LL_ENDL;
LL_DEBUGS("Wearable") << wearable << LL_ENDL;
}
else
{
LLSD args;
- // *TODO:translate
- args["TYPE"] = LLAssetType::lookupHumanReadable(data->mAssetType);
+ args["TYPE"] =LLTrans::getString(LLAssetType::lookupHumanReadable(data->mAssetType));
if (isNewWearable)
{
- LLNotifications::instance().add("InvalidWearable");
+ LLNotificationsUtil::add("InvalidWearable");
}
else if (data->mName.empty())
{
- LLNotifications::instance().add("FailedToFindWearableUnnamed", args);
+ LLNotificationsUtil::add("FailedToFindWearableUnnamed", args);
}
else
{
args["DESC"] = data->mName;
- LLNotifications::instance().add("FailedToFindWearable", args);
+ LLNotificationsUtil::add("FailedToFindWearable", args);
}
}
// Always call callback; wearable will be NULL if we failed
@@ -214,73 +210,18 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID
}
-// Creates a new wearable just like the old_wearable but with data copied over from item
-LLWearable* LLWearableList::createWearableMatchedToInventoryItem( LLWearable* old_wearable, LLViewerInventoryItem* item )
+LLWearable* LLWearableList::createCopy(const LLWearable* old_wearable, const std::string& new_name)
{
- lldebugs << "LLWearableList::createWearableMatchedToInventoryItem()" << llendl;
-
- LLTransactionID tid;
- LLAssetID new_asset_id;
- new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
-
- LLWearable* wearable = new LLWearable( tid );
- wearable->copyDataFrom( old_wearable );
-
- wearable->setName( item->getName() );
- wearable->setDescription( item->getDescription() );
- wearable->setPermissions( item->getPermissions() );
- wearable->setSaleInfo( item->getSaleInfo() );
-
- mList[ new_asset_id ] = wearable;
-
- // Send to the dataserver
- wearable->saveNewAsset();
-
- return wearable;
-}
+ lldebugs << "LLWearableList::createCopy()" << llendl;
-LLWearable* LLWearableList::createCopyFromAvatar( LLWearable* old_wearable, const std::string& new_name )
-{
- lldebugs << "LLWearableList::createCopyFromAvatar()" << llendl;
+ LLWearable *wearable = generateNewWearable();
+ wearable->copyDataFrom(old_wearable);
- LLTransactionID tid;
- LLAssetID new_asset_id;
- tid.generate();
- new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
-
- LLWearable* wearable = new LLWearable( tid );
- wearable->copyDataFrom( old_wearable );
LLPermissions perm(old_wearable->getPermissions());
perm.setOwnerAndGroup(LLUUID::null, gAgent.getID(), LLUUID::null, true);
wearable->setPermissions(perm);
- wearable->readFromAvatar(); // update from the avatar
-
- if (!new_name.empty()) wearable->setName(new_name);
- mList[ new_asset_id ] = wearable;
-
- // Send to the dataserver
- wearable->saveNewAsset();
-
- return wearable;
-}
-
-
-LLWearable* LLWearableList::createCopy( LLWearable* old_wearable )
-{
- lldebugs << "LLWearableList::createCopy()" << llendl;
-
- LLTransactionID tid;
- LLAssetID new_asset_id;
- tid.generate();
- new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
-
- LLWearable* wearable = new LLWearable( tid );
- wearable->copyDataFrom( old_wearable );
- LLPermissions perm(old_wearable->getPermissions());
- perm.setOwnerAndGroup(LLUUID::null, gAgent.getID(), LLUUID::null, true);
- wearable->setPermissions(perm);
- mList[ new_asset_id ] = wearable;
+ if (!new_name.empty()) wearable->setName(new_name);
// Send to the dataserver
wearable->saveNewAsset();
@@ -292,12 +233,7 @@ LLWearable* LLWearableList::createNewWearable( EWearableType type )
{
lldebugs << "LLWearableList::createNewWearable()" << llendl;
- LLTransactionID tid;
- LLAssetID new_asset_id;
- tid.generate();
- new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
-
- LLWearable* wearable = new LLWearable( tid );
+ LLWearable *wearable = generateNewWearable();
wearable->setType( type );
std::string name = "New ";
@@ -310,14 +246,26 @@ LLWearable* LLWearableList::createNewWearable( EWearableType type )
wearable->setPermissions(perm);
// Description and sale info have default values.
-
wearable->setParamsToDefaults();
wearable->setTexturesToDefaults();
- mList[ new_asset_id ] = wearable;
+ //mark all values (params & images) as saved
+ wearable->saveValues();
// Send to the dataserver
wearable->saveNewAsset();
+
+ return wearable;
+}
+
+LLWearable *LLWearableList::generateNewWearable()
+{
+ LLTransactionID tid;
+ tid.generate();
+ LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
+
+ LLWearable* wearable = new LLWearable(tid);
+ mList[new_asset_id] = wearable;
return wearable;
}
diff --git a/indra/newview/llwearablelist.h b/indra/newview/llwearablelist.h
index cda0cb11f9..cf1a9bddff 100644
--- a/indra/newview/llwearablelist.h
+++ b/indra/newview/llwearablelist.h
@@ -33,37 +33,37 @@
#ifndef LL_LLWEARABLELIST_H
#define LL_LLWEARABLELIST_H
+#include "llmemory.h"
#include "llwearable.h"
#include "lluuid.h"
#include "llassetstorage.h"
-class LLWearableList
+// Globally constructed; be careful that there's no dependency with gAgent.
+class LLWearableList : public LLSingleton<LLWearableList>
{
public:
LLWearableList() {}
~LLWearableList();
+ void cleanup() ;
- S32 getLength() { return mList.size(); }
+ S32 getLength() const { return mList.size(); }
- void getAsset(
- const LLAssetID& assetID,
- const std::string& wearable_name,
- LLAssetType::EType asset_type,
- void(*asset_arrived_callback)(LLWearable*, void* userdata),
- void* userdata );
+ void getAsset(const LLAssetID& assetID,
+ const std::string& wearable_name,
+ LLAssetType::EType asset_type,
+ void(*asset_arrived_callback)(LLWearable*, void* userdata),
+ void* userdata);
- LLWearable* createWearableMatchedToInventoryItem( LLWearable* old_wearable, LLViewerInventoryItem* item );
- LLWearable* createCopyFromAvatar( LLWearable* old_wearable, const std::string& new_name = std::string() );
- LLWearable* createCopy( LLWearable* old_wearable );
- LLWearable* createNewWearable( EWearableType type );
+ LLWearable* createCopy(const LLWearable* old_wearable, const std::string& new_name = std::string());
+ LLWearable* createNewWearable(EWearableType type);
// Callback
static void processGetAssetReply(const char* filename, const LLAssetID& assetID, void* user_data, S32 status, LLExtStat ext_status);
protected:
- std::map< LLUUID, LLWearable* > mList;
+ LLWearable* generateNewWearable(); // used for the create... functions
+private:
+ std::map<LLUUID, LLWearable*> mList;
};
-extern LLWearableList gWearableList;
-
#endif // LL_LLWEARABLELIST_H
diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp
index a5691d8a1c..7866f735c5 100644
--- a/indra/newview/llweb.cpp
+++ b/indra/newview/llweb.cpp
@@ -35,17 +35,50 @@
#include "llweb.h"
-#include "llviewerwindow.h"
+// Library includes
+#include "llwindow.h" // spawnWebBrowser()
+#include "llagent.h"
+#include "llappviewer.h"
+#include "llfloatermediabrowser.h"
+#include "llfloaterreg.h"
+#include "lllogininstance.h"
+#include "llparcel.h"
+#include "llsd.h"
+#include "lltoastalertpanel.h"
+#include "llui.h"
+#include "lluri.h"
+#include "llversioninfo.h"
#include "llviewercontrol.h"
-#include "llfloaterhtmlhelp.h"
+#include "llviewernetwork.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+#include "llviewerwindow.h"
+
+class URLLoader : public LLToastAlertPanel::URLLoader
+{
+ virtual void load(const std::string& url , bool force_open_externally)
+ {
+ if (force_open_externally)
+ {
+ LLWeb::loadURLExternal(url);
+ }
+ else
+ {
+ LLWeb::loadURL(url);
+ }
+ }
+};
+static URLLoader sAlertURLLoader;
+
// static
void LLWeb::initClass()
{
- LLAlertDialog::setURLLoader(&sAlertURLLoader);
+ LLToastAlertPanel::setURLLoader(&sAlertURLLoader);
}
+
// static
void LLWeb::loadURL(const std::string& url)
{
@@ -55,12 +88,19 @@ void LLWeb::loadURL(const std::string& url)
}
else
{
- LLFloaterMediaBrowser::showInstance(url);
+ loadURLInternal(url);
}
}
// static
+void LLWeb::loadURLInternal(const std::string &url)
+{
+ LLFloaterReg::showInstance("media_browser", url);
+}
+
+
+// static
void LLWeb::loadURLExternal(const std::string& url)
{
std::string escaped_url = escapeURL(url);
@@ -94,11 +134,43 @@ std::string LLWeb::escapeURL(const std::string& url)
return escaped_url;
}
-// virtual
-void LLWeb::URLLoader::load(const std::string& url)
+//static
+std::string LLWeb::expandURLSubstitutions(const std::string &url,
+ const LLSD &default_subs)
{
- loadURL(url);
-}
+ LLSD substitution = default_subs;
+ substitution["VERSION"] = LLVersionInfo::getVersion();
+ substitution["VERSION_MAJOR"] = LLVersionInfo::getMajor();
+ substitution["VERSION_MINOR"] = LLVersionInfo::getMinor();
+ substitution["VERSION_PATCH"] = LLVersionInfo::getPatch();
+ substitution["VERSION_BUILD"] = LLVersionInfo::getBuild();
+ substitution["CHANNEL"] = LLVersionInfo::getChannel();
+ substitution["LANGUAGE"] = LLUI::getLanguage();
+ substitution["GRID"] = LLViewerLogin::getInstance()->getGridLabel();
+ substitution["OS"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple();
+ substitution["SESSION_ID"] = gAgent.getSessionID();
-// static
-LLWeb::URLLoader LLWeb::sAlertURLLoader;
+ // find the region ID
+ LLUUID region_id;
+ LLViewerRegion *region = gAgent.getRegion();
+ if (region)
+ {
+ region_id = region->getRegionID();
+ }
+ substitution["REGION_ID"] = region_id;
+
+ // find the parcel ID
+ LLUUID parcel_id;
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ if (parcel)
+ {
+ parcel_id = parcel->getID();
+ }
+ substitution["PARCEL_ID"] = parcel_id;
+
+ // expand all of the substitution strings and escape the url
+ std::string expanded_url = url;
+ LLStringUtil::format(expanded_url, substitution);
+
+ return LLWeb::escapeURL(expanded_url);
+}
diff --git a/indra/newview/llweb.h b/indra/newview/llweb.h
index 278821bac5..f4666c9280 100644
--- a/indra/newview/llweb.h
+++ b/indra/newview/llweb.h
@@ -35,31 +35,33 @@
#define LL_LLWEB_H
#include <string>
-#include "llalertdialog.h"
+///
+/// The LLWeb class provides various static methods to display the
+/// contents of a Url in a web browser. Variations are provided to
+/// let you specifically use the Second Life internal browser, the
+/// operating system's default browser, or to respect the user's
+/// setting for which of these two they prefer to use with SL.
+///
class LLWeb
{
public:
static void initClass();
- // Loads unescaped url in either internal web browser or external
- // browser, depending on user settings.
+ /// Load the given url in the user's preferred web browser
static void loadURL(const std::string& url);
-
+ /// Load the given url in the user's preferred web browser
static void loadURL(const char* url) { loadURL( ll_safe_string(url) ); }
-
- // Loads unescaped url in external browser.
+ /// Load the given url in the Second Life internal web browser
+ static void loadURLInternal(const std::string &url);
+ /// Load the given url in the operating system's web browser
static void loadURLExternal(const std::string& url);
- // Returns escaped (eg, " " to "%20") url
+ /// Returns escaped url (eg, " " to "%20") - used by all loadURL methods
static std::string escapeURL(const std::string& url);
-
- class URLLoader : public LLAlertDialog::URLLoader
- {
- virtual void load(const std::string& url);
- };
-
- static URLLoader sAlertURLLoader;
+ /// Expands various strings like [LANG], [VERSION], etc. in a URL
+ static std::string expandURLSubstitutions(const std::string &url,
+ const LLSD &default_subs);
};
#endif
diff --git a/indra/newview/llwind.cpp b/indra/newview/llwind.cpp
index ae98bead98..cbee4ddae1 100644
--- a/indra/newview/llwind.cpp
+++ b/indra/newview/llwind.cpp
@@ -49,7 +49,6 @@
// viewer
#include "noise.h"
#include "v4color.h"
-#include "llagent.h"
#include "llworld.h"
diff --git a/indra/newview/llwldaycycle.cpp b/indra/newview/llwldaycycle.cpp
index 1d17c6047f..000d50795f 100644
--- a/indra/newview/llwldaycycle.cpp
+++ b/indra/newview/llwldaycycle.cpp
@@ -33,10 +33,12 @@
#include "llviewerprecompiledheaders.h"
#include "llwldaycycle.h"
+
+#include "llnotificationsutil.h"
#include "llsdserialize.h"
-#include "llwlparammanager.h"
+#include "llxmlnode.h"
-#include "llviewerwindow.h"
+#include "llwlparammanager.h"
#include <map>
@@ -85,7 +87,7 @@ void LLWLDayCycle::loadDayCycle(const std::string & fileName)
// alert the user
LLSD args;
args["SKY"] = day_data[i][1].asString();
- LLNotifications::instance().add("WLMissingSky", args);
+ LLNotificationsUtil::add("WLMissingSky", args);
continue;
}
diff --git a/indra/newview/llwldaycycle.h b/indra/newview/llwldaycycle.h
index f045a6d1b0..eed6a78c18 100644
--- a/indra/newview/llwldaycycle.h
+++ b/indra/newview/llwldaycycle.h
@@ -35,8 +35,6 @@
class LLWLDayCycle;
-#include "llfloater.h"
-
#include <vector>
#include <map>
#include <string>
diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp
index b8a2bf0bd2..7cac564619 100644
--- a/indra/newview/llwlparammanager.cpp
+++ b/indra/newview/llwlparammanager.cpp
@@ -37,22 +37,17 @@
#include "pipeline.h"
#include "llsky.h"
+#include "llfloaterreg.h"
#include "llsliderctrl.h"
#include "llspinctrl.h"
#include "llcheckboxctrl.h"
#include "lluictrlfactory.h"
-#include "llviewercamera.h"
#include "llcombobox.h"
#include "lllineeditor.h"
#include "llsdserialize.h"
#include "v4math.h"
-#include "llviewerdisplay.h"
#include "llviewercontrol.h"
-#include "llviewerwindow.h"
-#include "lldrawpoolwater.h"
-#include "llagent.h"
-#include "llviewerregion.h"
#include "llwlparamset.h"
#include "llpostprocess.h"
@@ -63,6 +58,7 @@
#include "curl/curl.h"
LLWLParamManager * LLWLParamManager::sInstance = NULL;
+static LLFastTimer::DeclareTimer FTM_UPDATE_WLPARAM("Update Windlight Params");
LLWLParamManager::LLWLParamManager() :
@@ -108,7 +104,7 @@ LLWLParamManager::~LLWLParamManager()
void LLWLParamManager::loadPresets(const std::string& file_name)
{
std::string path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/skies", ""));
- LL_INFOS2("AppInit", "Shaders") << "Loading Default WindLight settings from " << path_name << LL_ENDL;
+ LL_DEBUGS2("AppInit", "Shaders") << "Loading Default WindLight settings from " << path_name << LL_ENDL;
bool found = true;
while(found)
@@ -134,7 +130,7 @@ void LLWLParamManager::loadPresets(const std::string& file_name)
// And repeat for user presets, note the user presets will modify any system presets already loaded
std::string path_name2(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/skies", ""));
- LL_INFOS2("AppInit", "Shaders") << "Loading User WindLight settings from " << path_name2 << LL_ENDL;
+ LL_DEBUGS2("AppInit", "Shaders") << "Loading User WindLight settings from " << path_name2 << LL_ENDL;
found = true;
while(found)
@@ -195,7 +191,7 @@ void LLWLParamManager::loadPreset(const std::string & name,bool propagate)
escaped_filename += ".xml";
std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/skies", escaped_filename));
- llinfos << "Loading WindLight sky setting from " << pathName << llendl;
+ LL_DEBUGS2("AppInit", "Shaders") << "Loading WindLight sky setting from " << pathName << LL_ENDL;
llifstream presetsXML;
presetsXML.open(pathName.c_str());
@@ -204,8 +200,9 @@ void LLWLParamManager::loadPreset(const std::string & name,bool propagate)
if(!presetsXML)
{
pathName=gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/skies", escaped_filename);
- llinfos << "Loading User WindLight sky setting from " << pathName << llendl;
- presetsXML.open(pathName.c_str());
+ LL_DEBUGS2("AppInit", "Shaders") << "Loading User WindLight sky setting from " << pathName << LL_ENDL;
+ presetsXML.clear();
+ presetsXML.open(pathName.c_str());
}
if (presetsXML)
@@ -291,7 +288,7 @@ void LLWLParamManager::updateShaderUniforms(LLGLSLShader * shader)
void LLWLParamManager::propagateParameters(void)
{
- LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WLPARAM);
+ LLFastTimer ftm(FTM_UPDATE_WLPARAM);
LLVector4 sunDir;
LLVector4 moonDir;
@@ -315,7 +312,7 @@ void LLWLParamManager::propagateParameters(void)
{
mLightDir = sunDir;
}
- else if(sunDir.mV[1] < 0 && sunDir.mV[1] > NIGHTTIME_ELEVATION_COS)
+ else if(sunDir.mV[1] < 0 && sunDir.mV[1] > LLSky::NIGHTTIME_ELEVATION_COS)
{
// clamp v1 to 0 so sun never points up and causes weirdness on some machines
LLVector3 vec(sunDir.mV[0], sunDir.mV[1], sunDir.mV[2]);
@@ -362,7 +359,7 @@ void LLWLParamManager::propagateParameters(void)
void LLWLParamManager::update(LLViewerCamera * cam)
{
- LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WLPARAM);
+ LLFastTimer ftm(FTM_UPDATE_WLPARAM);
// update clouds, sun, and general
mCurParams.updateCloudScrolling();
@@ -377,23 +374,24 @@ void LLWLParamManager::update(LLViewerCamera * cam)
propagateParameters();
// sync menus if they exist
- if(LLFloaterWindLight::isOpen())
+ LLFloaterWindLight* wlfloater = LLFloaterReg::findTypedInstance<LLFloaterWindLight>("env_windlight");
+ if (wlfloater)
{
- LLFloaterWindLight::instance()->syncMenu();
+ wlfloater->syncMenu();
}
- if(LLFloaterDayCycle::isOpen())
+ LLFloaterDayCycle* dlfloater = LLFloaterReg::findTypedInstance<LLFloaterDayCycle>("env_day_cycle");
+ if (dlfloater)
{
- LLFloaterDayCycle::instance()->syncMenu();
+ dlfloater->syncMenu();
}
- if(LLFloaterEnvSettings::isOpen())
+ LLFloaterEnvSettings* envfloater = LLFloaterReg::findTypedInstance<LLFloaterEnvSettings>("env_settings");
+ if (envfloater)
{
- LLFloaterEnvSettings::instance()->syncMenu();
+ envfloater->syncMenu();
}
F32 camYaw = cam->getYaw();
- stop_glerror();
-
// *TODO: potential optimization - this block may only need to be
// executed some of the time. For example for water shaders only.
{
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 3fdef29540..118d7f8d08 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -46,8 +46,8 @@
#include "llregionhandle.h"
#include "llsurface.h"
#include "llviewercamera.h"
-#include "llviewerimage.h"
-#include "llviewerimagelist.h"
+#include "llviewertexture.h"
+#include "llviewertexturelist.h"
#include "llviewernetwork.h"
#include "llviewerobjectlist.h"
#include "llviewerparceloverlay.h"
@@ -109,8 +109,8 @@ LLWorld::LLWorld() :
*(default_texture++) = MAX_WATER_COLOR.mV[2];
*(default_texture++) = MAX_WATER_COLOR.mV[3];
- mDefaultWaterTexturep = new LLViewerImage(raw, FALSE);
- gGL.getTexUnit(0)->bind(mDefaultWaterTexturep.get());
+ mDefaultWaterTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
+ gGL.getTexUnit(0)->bind(mDefaultWaterTexturep);
mDefaultWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
}
@@ -118,6 +118,7 @@ LLWorld::LLWorld() :
void LLWorld::destroyClass()
{
+ mHoleWaterObjects.clear();
gObjectList.destroy();
for(region_list_t::iterator region_it = mRegionList.begin(); region_it != mRegionList.end(); )
{
@@ -632,6 +633,7 @@ void LLWorld::updateVisibilities()
void LLWorld::updateRegions(F32 max_update_time)
{
+ LLMemType mt_ur(LLMemType::MTYPE_IDLE_UPDATE_REGIONS);
LLTimer update_timer;
BOOL did_one = FALSE;
@@ -961,7 +963,7 @@ void LLWorld::shiftRegions(const LLVector3& offset)
LLViewerPartSim::getInstance()->shift(offset);
}
-LLViewerImage* LLWorld::getDefaultWaterTexture()
+LLViewerTexture* LLWorld::getDefaultWaterTexture()
{
return mDefaultWaterTexturep;
}
diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h
index ce83cbd97c..48025c700b 100644
--- a/indra/newview/llworld.h
+++ b/indra/newview/llworld.h
@@ -42,10 +42,10 @@
#include "llmath.h"
#include "v3math.h"
-#include "llmemory.h"
+#include "llsingleton.h"
#include "llstring.h"
#include "llviewerpartsim.h"
-#include "llviewerimage.h"
+#include "llviewertexture.h"
#include "llvowater.h"
class LLViewerRegion;
@@ -141,7 +141,7 @@ public:
F32 getLandFarClip() const;
void setLandFarClip(const F32 far_clip);
- LLViewerImage *getDefaultWaterTexture();
+ LLViewerTexture *getDefaultWaterTexture();
void updateWaterObjects();
void shiftRegions(const LLVector3& offset);
@@ -192,7 +192,7 @@ private:
std::list<LLVOWater*> mHoleWaterObjects;
LLPointer<LLVOWater> mEdgeWaterObjects[8];
- LLPointer<LLViewerImage> mDefaultWaterTexturep;
+ LLPointer<LLViewerTexture> mDefaultWaterTexturep;
};
diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp
index 572f31f566..66cb02ce99 100644
--- a/indra/newview/llworldmap.cpp
+++ b/indra/newview/llworldmap.cpp
@@ -34,57 +34,81 @@
#include "llworldmap.h"
-#include "llregionhandle.h"
+#include "llworldmapmessage.h"
#include "message.h"
-
-#include "llappviewer.h" // for gPacificDaylightTime
-#include "llagent.h"
-#include "llmapresponders.h"
-#include "llviewercontrol.h"
-#include "llfloaterworldmap.h"
#include "lltracker.h"
-#include "llviewerimagelist.h"
-#include "llviewerregion.h"
-#include "llregionflags.h"
-
-const F32 REQUEST_ITEMS_TIMER = 10.f * 60.f; // 10 minutes
-
-// For DEV-17507, do lazy image loading in llworldmapview.cpp instead,
-// limiting requests to currently visible regions and minimizing the
-// number of textures being requested simultaneously.
-//
-// Uncomment IMMEDIATE_IMAGE_LOAD to restore the old behavior
-//
-//#define IMMEDIATE_IMAGE_LOAD
+#include "llviewertexturelist.h"
+#include "lltrans.h"
+
+// Timers to temporise database requests
+const F32 AGENTS_UPDATE_TIMER = 60.0; // Seconds between 2 agent requests for a region
+const F32 REQUEST_ITEMS_TIMER = 10.f * 60.f; // Seconds before we consider re-requesting item data for the grid
+
+//---------------------------------------------------------------------------
+// LLItemInfo
+//---------------------------------------------------------------------------
+
LLItemInfo::LLItemInfo(F32 global_x, F32 global_y,
const std::string& name,
- LLUUID id,
- S32 extra, S32 extra2)
+ LLUUID id)
: mName(name),
mToolTip(""),
mPosGlobal(global_x, global_y, 40.0),
mID(id),
- mSelected(FALSE),
- mExtra(extra),
- mExtra2(extra2)
+ mCount(1)
+// mSelected(false)
+// mColor()
{
- mRegionHandle = to_region_handle(mPosGlobal);
}
-LLSimInfo::LLSimInfo()
-: mHandle(0),
+//---------------------------------------------------------------------------
+// LLSimInfo
+//---------------------------------------------------------------------------
+
+LLSimInfo::LLSimInfo(U64 handle)
+: mHandle(handle),
mName(),
mAgentsUpdateTime(0),
- mShowAgentLocations(FALSE),
mAccess(0x0),
mRegionFlags(0x0),
- mWaterHeight(0.f),
- mAlpha(-1.f)
+ mFirstAgentRequest(true)
+// mWaterHeight(0.f)
+{
+}
+
+void LLSimInfo::setLandForSaleImage (LLUUID image_id)
{
+ mMapImageID = image_id;
+
+ // Fetch the image
+ if (mMapImageID.notNull())
+ {
+ mOverlayImage = LLViewerTextureManager::getFetchedTexture(mMapImageID, MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE);
+ mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP);
+ }
+ else
+ {
+ mOverlayImage = NULL;
+ }
}
+LLPointer<LLViewerFetchedTexture> LLSimInfo::getLandForSaleImage ()
+{
+ if (mOverlayImage.isNull() && mMapImageID.notNull())
+ {
+ // Fetch the image if it hasn't been done yet (unlikely but...)
+ mOverlayImage = LLViewerTextureManager::getFetchedTexture(mMapImageID, MIPMAP_TRUE, LLViewerTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE);
+ mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP);
+ }
+ if (!mOverlayImage.isNull())
+ {
+ // Boost the fetch level when we try to access that image
+ mOverlayImage->setBoostLevel(LLViewerTexture::BOOST_MAP);
+ }
+ return mOverlayImage;
+}
-LLVector3d LLSimInfo::getGlobalPos(LLVector3 local_pos) const
+LLVector3d LLSimInfo::getGlobalPos(const LLVector3& local_pos) const
{
LLVector3d pos = from_region_handle(mHandle);
pos.mdV[VX] += local_pos.mV[VX];
@@ -93,121 +117,184 @@ LLVector3d LLSimInfo::getGlobalPos(LLVector3 local_pos) const
return pos;
}
+LLVector3d LLSimInfo::getGlobalOrigin() const
+{
+ return from_region_handle(mHandle);
+}
+LLVector3 LLSimInfo::getLocalPos(LLVector3d global_pos) const
+{
+ LLVector3d sim_origin = from_region_handle(mHandle);
+ return LLVector3(global_pos - sim_origin);
+}
-//---------------------------------------------------------------------------
-// World Map
-//---------------------------------------------------------------------------
+void LLSimInfo::clearImage()
+{
+ if (!mOverlayImage.isNull())
+ {
+ mOverlayImage->setBoostLevel(0);
+ mOverlayImage = NULL;
+ }
+}
-LLWorldMap::LLWorldMap() :
- mIsTrackingUnknownLocation( FALSE ),
- mInvalidLocation( FALSE ),
- mIsTrackingDoubleClick( FALSE ),
- mIsTrackingCommit( FALSE ),
- mUnknownLocation( 0, 0, 0 ),
- mRequestLandForSale(true),
- mCurrentMap(0),
- mMinX(U32_MAX),
- mMaxX(U32_MIN),
- mMinY(U32_MAX),
- mMaxY(U32_MIN),
- mNeighborMap(NULL),
- mTelehubCoverageMap(NULL),
- mNeighborMapWidth(0),
- mNeighborMapHeight(0),
- mSLURLRegionName(),
- mSLURLRegionHandle(0),
- mSLURL(),
- mSLURLCallback(0),
- mSLURLTeleport(false)
-{
- for (S32 map=0; map<MAP_SIM_IMAGE_TYPES; ++map)
+void LLSimInfo::dropImagePriority()
+{
+ if (!mOverlayImage.isNull())
{
- mMapLoaded[map] = FALSE;
- mMapBlockLoaded[map] = new BOOL[MAP_BLOCK_RES*MAP_BLOCK_RES];
- for (S32 idx=0; idx<MAP_BLOCK_RES*MAP_BLOCK_RES; ++idx)
- {
- mMapBlockLoaded[map][idx] = FALSE;
- }
+ mOverlayImage->setBoostLevel(0);
}
}
+// Update the agent count for that region
+void LLSimInfo::updateAgentCount(F64 time)
+{
+ if ((time - mAgentsUpdateTime > AGENTS_UPDATE_TIMER) || mFirstAgentRequest)
+ {
+ LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_AGENT_LOCATIONS, mHandle);
+ mAgentsUpdateTime = time;
+ mFirstAgentRequest = false;
+ }
+}
-LLWorldMap::~LLWorldMap()
+// Get the total agents count
+const S32 LLSimInfo::getAgentCount() const
{
- reset();
- for (S32 map=0; map<MAP_SIM_IMAGE_TYPES; ++map)
+ S32 total_agent_count = 0;
+ for (LLSimInfo::item_info_list_t::const_iterator it = mAgentLocations.begin(); it != mAgentLocations.end(); ++it)
{
- delete[] mMapBlockLoaded[map];
+ total_agent_count += it->getCount();
}
+ return total_agent_count;
}
+bool LLSimInfo::isName(const std::string& name) const
+{
+ return (LLStringUtil::compareInsensitive(name, mName) == 0);
+}
-void LLWorldMap::reset()
+void LLSimInfo::dump() const
{
- for_each(mSimInfoMap.begin(), mSimInfoMap.end(), DeletePairedPointer());
- mSimInfoMap.clear();
+ U32 x_pos, y_pos;
+ from_region_handle(mHandle, &x_pos, &y_pos);
+
+ LL_INFOS("World Map") << x_pos << "," << y_pos
+ << " " << mName
+ << " " << (S32)mAccess
+ << " " << std::hex << mRegionFlags << std::dec
+// << " " << mWaterHeight
+ << LL_ENDL;
+}
- for (S32 m=0; m<MAP_SIM_IMAGE_TYPES; ++m)
+void LLSimInfo::clearItems()
+{
+ mTelehubs.clear();
+ mInfohubs.clear();
+ mPGEvents.clear();
+ mMatureEvents.clear();
+ mAdultEvents.clear();
+ mLandForSale.clear();
+ mLandForSaleAdult.clear();
+// We persist the agent count though as it is updated on a frequent basis
+// mAgentLocations.clear();
+}
+
+void LLSimInfo::insertAgentLocation(const LLItemInfo& item)
+{
+ std::string name = item.getName();
+
+ // Find the last item in the list with a different name and erase them
+ item_info_list_t::iterator lastiter;
+ for (lastiter = mAgentLocations.begin(); lastiter != mAgentLocations.end(); ++lastiter)
{
- mMapLoaded[m] = FALSE;
+ LLItemInfo& info = *lastiter;
+ if (info.isName(name))
+ {
+ break;
+ }
}
+ if (lastiter != mAgentLocations.begin())
+ {
+ mAgentLocations.erase(mAgentLocations.begin(), lastiter);
+ }
+
+ // Now append the new location
+ mAgentLocations.push_back(item);
+}
+//---------------------------------------------------------------------------
+// World Map
+//---------------------------------------------------------------------------
+
+LLWorldMap::LLWorldMap() :
+ mIsTrackingLocation( false ),
+ mIsTrackingFound( false ),
+ mIsInvalidLocation( false ),
+ mIsTrackingDoubleClick( false ),
+ mIsTrackingCommit( false ),
+ mTrackingLocation( 0, 0, 0 ),
+ mFirstRequest(true)
+{
+ //LL_INFOS("World Map") << "Creating the World Map -> LLWorldMap::LLWorldMap()" << LL_ENDL;
+ mMapBlockLoaded = new bool[MAP_BLOCK_RES*MAP_BLOCK_RES];
clearSimFlags();
-
- eraseItems();
+}
- mMinX = U32_MAX;
- mMaxX = U32_MIN;
- mMinY = U32_MAX;
- mMaxY = U32_MIN;
+LLWorldMap::~LLWorldMap()
+{
+ //LL_INFOS("World Map") << "Destroying the World Map -> LLWorldMap::~LLWorldMap()" << LL_ENDL;
+ reset();
+ delete[] mMapBlockLoaded;
+}
- delete [] mNeighborMap;
- mNeighborMap = NULL;
- delete [] mTelehubCoverageMap;
- mTelehubCoverageMap = NULL;
- mNeighborMapWidth = 0;
- mNeighborMapHeight = 0;
+void LLWorldMap::reset()
+{
+ clearItems(true); // Clear the items lists
+ clearImageRefs(); // Clear the world mipmap and the land for sale tiles
+ clearSimFlags(); // Clear the block info flags array
- for (S32 i=0; i<MAP_SIM_IMAGE_TYPES; i++)
- {
- mMapLayers[i].clear();
- }
+ // Finally, clear the region map itself
+ for_each(mSimInfoMap.begin(), mSimInfoMap.end(), DeletePairedPointer());
+ mSimInfoMap.clear();
}
-void LLWorldMap::eraseItems()
+// Returns true if the items have been cleared
+bool LLWorldMap::clearItems(bool force)
{
- if (mRequestTimer.getElapsedTimeF32() > REQUEST_ITEMS_TIMER)
+ bool clear = false;
+ if ((mRequestTimer.getElapsedTimeF32() > REQUEST_ITEMS_TIMER) || mFirstRequest || force)
{
mRequestTimer.reset();
- mTelehubs.clear();
- mInfohubs.clear();
- mPGEvents.clear();
- mMatureEvents.clear();
- mAdultEvents.clear();
- mLandForSale.clear();
+ LLSimInfo* sim_info = NULL;
+ for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
+ {
+ sim_info = it->second;
+ if (sim_info)
+ {
+ sim_info->clearItems();
+ }
+ }
+ clear = true;
+ mFirstRequest = false;
}
-// mAgentLocationsMap.clear(); // persists
-// mNumAgents.clear(); // persists
+ return clear;
}
-
void LLWorldMap::clearImageRefs()
{
+ // We clear the reference to the images we're holding.
+ // Images hold by the world mipmap first
+ mWorldMipmap.reset();
+
+ // Images hold by the region map
+ LLSimInfo* sim_info = NULL;
for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
{
- LLSimInfo* info = (*it).second;
- if (info->mCurrentImage)
- {
- info->mCurrentImage->setBoostLevel(0);
- info->mCurrentImage = NULL;
- }
- if (info->mOverlayImage)
+ sim_info = it->second;
+ if (sim_info)
{
- info->mOverlayImage->setBoostLevel(0);
- info->mOverlayImage = NULL;
+ sim_info->clearImage();
}
}
}
@@ -215,15 +302,25 @@ void LLWorldMap::clearImageRefs()
// Doesn't clear the already-loaded sim infos, just re-requests them
void LLWorldMap::clearSimFlags()
{
- for (S32 map=0; map<MAP_SIM_IMAGE_TYPES; ++map)
+ for (S32 idx=0; idx<MAP_BLOCK_RES*MAP_BLOCK_RES; ++idx)
{
- for (S32 idx=0; idx<MAP_BLOCK_RES*MAP_BLOCK_RES; ++idx)
- {
- mMapBlockLoaded[map][idx] = FALSE;
- }
+ mMapBlockLoaded[idx] = false;
}
}
+LLSimInfo* LLWorldMap::createSimInfoFromHandle(const U64 handle)
+{
+ LLSimInfo* sim_info = new LLSimInfo(handle);
+ mSimInfoMap[handle] = sim_info;
+ return sim_info;
+}
+
+void LLWorldMap::equalizeBoostLevels()
+{
+ mWorldMipmap.equalizeBoostLevels();
+ return;
+}
+
LLSimInfo* LLWorldMap::simInfoFromPosGlobal(const LLVector3d& pos_global)
{
U64 handle = to_region_handle(pos_global);
@@ -235,11 +332,7 @@ LLSimInfo* LLWorldMap::simInfoFromHandle(const U64 handle)
sim_info_map_t::iterator it = mSimInfoMap.find(handle);
if (it != mSimInfoMap.end())
{
- LLSimInfo* sim_info = (*it).second;
- if (sim_info)
- {
- return sim_info;
- }
+ return it->second;
}
return NULL;
}
@@ -250,768 +343,273 @@ LLSimInfo* LLWorldMap::simInfoFromName(const std::string& sim_name)
LLSimInfo* sim_info = NULL;
if (!sim_name.empty())
{
- for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
+ // Iterate through the entire sim info map and compare the name
+ sim_info_map_t::iterator it;
+ for (it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
{
- sim_info = (*it).second;
- if (sim_info
- && (0 == LLStringUtil::compareInsensitive(sim_name, sim_info->mName)) )
+ sim_info = it->second;
+ if (sim_info && sim_info->isName(sim_name) )
{
+ // break out of loop if success
break;
}
- sim_info = NULL;
}
+ // If we got to the end, we haven't found the sim. Reset the ouput value to NULL.
+ if (it == mSimInfoMap.end())
+ sim_info = NULL;
}
return sim_info;
}
bool LLWorldMap::simNameFromPosGlobal(const LLVector3d& pos_global, std::string & outSimName )
{
- bool gotSimName = true;
-
- U64 handle = to_region_handle(pos_global);
+ LLSimInfo* sim_info = simInfoFromPosGlobal(pos_global);
- sim_info_map_t::iterator it = mSimInfoMap.find(handle);
- if (it != mSimInfoMap.end())
+ if (sim_info)
{
- LLSimInfo* info = (*it).second;
- outSimName = info->mName;
+ outSimName = sim_info->getName();
}
else
{
- gotSimName = false;
outSimName = "(unknown region)";
}
- return gotSimName;
+ return (sim_info != NULL);
}
-void LLWorldMap::setCurrentLayer(S32 layer, bool request_layer)
+void LLWorldMap::reloadItems(bool force)
{
- mCurrentMap = layer;
- if (!mMapLoaded[layer] || request_layer)
+ //LL_INFOS("World Map") << "LLWorldMap::reloadItems()" << LL_ENDL;
+ if (clearItems(force))
{
- sendMapLayerRequest();
+ LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_TELEHUB);
+ LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_PG_EVENT);
+ LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_MATURE_EVENT);
+ LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_ADULT_EVENT);
+ LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_LAND_FOR_SALE);
}
-
- if (mTelehubs.size() == 0 ||
- mInfohubs.size() == 0)
- {
- // Request for telehubs
- sendItemRequest(MAP_ITEM_TELEHUB);
- }
-
- if (mPGEvents.size() == 0)
- {
- // Request for events
- sendItemRequest(MAP_ITEM_PG_EVENT);
- }
-
- if (mMatureEvents.size() == 0)
- {
- // Request for events (mature)
- sendItemRequest(MAP_ITEM_MATURE_EVENT);
- }
-
- if (mAdultEvents.size() == 0)
- {
- // Request for events (adult)
- sendItemRequest(MAP_ITEM_ADULT_EVENT);
- }
-
- if (mLandForSale.size() == 0)
- {
- // Request for Land For Sale
- sendItemRequest(MAP_ITEM_LAND_FOR_SALE);
- }
-
- if (mLandForSaleAdult.size() == 0)
- {
- // Request for Land For Sale
- sendItemRequest(MAP_ITEM_LAND_FOR_SALE_ADULT);
- }
-
- clearImageRefs();
- clearSimFlags();
}
-void LLWorldMap::sendItemRequest(U32 type, U64 handle)
-{
- LLMessageSystem* msg = gMessageSystem;
- S32 layer = mCurrentMap;
-
- msg->newMessageFast(_PREHASH_MapItemRequest);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->addU32Fast(_PREHASH_Flags, layer);
- msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
- msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
-
- msg->nextBlockFast(_PREHASH_RequestData);
- msg->addU32Fast(_PREHASH_ItemType, type);
- msg->addU64Fast(_PREHASH_RegionHandle, handle); // If zero, filled in on sim
-
- gAgent.sendReliableMessage();
-}
-// public
-void LLWorldMap::sendMapLayerRequest()
+// static public
+// Insert a region in the region map
+// returns true if region inserted, false otherwise
+bool LLWorldMap::insertRegion(U32 x_world, U32 y_world, std::string& name, LLUUID& image_id, U32 accesscode, U32 region_flags)
{
- if (!gAgent.getRegion()) return;
-
- LLSD body;
- body["Flags"] = mCurrentMap;
- std::string url = gAgent.getRegion()->getCapability(
- gAgent.isGodlike() ? "MapLayerGod" : "MapLayer");
-
- if (!url.empty())
+ // This region doesn't exist
+ if (accesscode == 255)
{
- llinfos << "LLWorldMap::sendMapLayerRequest via capability" << llendl;
- LLHTTPClient::post(url, body, new LLMapLayerResponder());
+ // Checks if the track point is in it and invalidates it if it is
+ if (LLWorldMap::getInstance()->isTrackingInRectangle( x_world, y_world, x_world + REGION_WIDTH_UNITS, y_world + REGION_WIDTH_UNITS))
+ {
+ LLWorldMap::getInstance()->setTrackingInvalid();
+ }
+ // return failure to insert
+ return false;
}
else
{
- llinfos << "LLWorldMap::sendMapLayerRequest via message system" << llendl;
- LLMessageSystem* msg = gMessageSystem;
- S32 layer = mCurrentMap;
-
- // Request for layer
- msg->newMessageFast(_PREHASH_MapLayerRequest);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->addU32Fast(_PREHASH_Flags, layer);
- msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
- msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
- gAgent.sendReliableMessage();
-
- if (mRequestLandForSale)
+ U64 handle = to_region_handle(x_world, y_world);
+ //LL_INFOS("World Map") << "Map sim : " << name << ", ID : " << image_id.getString() << LL_ENDL;
+ // Insert the region in the region map of the world map
+ // Loading the LLSimInfo object with what we got and insert it in the map
+ LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle);
+ if (siminfo == NULL)
{
- msg->newMessageFast(_PREHASH_MapLayerRequest);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->addU32Fast(_PREHASH_Flags, 2);
- msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
- msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
- gAgent.sendReliableMessage();
+ siminfo = LLWorldMap::getInstance()->createSimInfoFromHandle(handle);
}
+ siminfo->setName(name);
+ siminfo->setAccess(accesscode);
+ siminfo->setRegionFlags(region_flags);
+ // siminfo->setWaterHeight((F32) water_height);
+ siminfo->setLandForSaleImage(image_id);
+
+ // Handle the location tracking (for teleport, UI feedback and info display)
+ if (LLWorldMap::getInstance()->isTrackingInRectangle( x_world, y_world, x_world + REGION_WIDTH_UNITS, y_world + REGION_WIDTH_UNITS))
+ {
+ if (siminfo->isDown())
+ {
+ // We were tracking this location, but it's no available
+ LLWorldMap::getInstance()->setTrackingInvalid();
+ }
+ else
+ {
+ // We were tracking this location, and it does exist and is available
+ LLWorldMap::getInstance()->setTrackingValid();
+ }
+ }
+ // return insert region success
+ return true;
}
}
-// public
-void LLWorldMap::sendNamedRegionRequest(std::string region_name)
-{
- LLMessageSystem* msg = gMessageSystem;
- S32 layer = mCurrentMap;
-
- // Request for layer
- msg->newMessageFast(_PREHASH_MapNameRequest);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->addU32Fast(_PREHASH_Flags, layer);
- msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
- msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
- msg->nextBlockFast(_PREHASH_NameData);
- msg->addStringFast(_PREHASH_Name, region_name);
- gAgent.sendReliableMessage();
-}
-// public
-void LLWorldMap::sendNamedRegionRequest(std::string region_name,
- url_callback_t callback,
- const std::string& callback_url,
- bool teleport) // immediately teleport when result returned
-{
- mSLURLRegionName = region_name;
- mSLURLRegionHandle = 0;
- mSLURL = callback_url;
- mSLURLCallback = callback;
- mSLURLTeleport = teleport;
-
- sendNamedRegionRequest(region_name);
-}
-
-void LLWorldMap::sendHandleRegionRequest(U64 region_handle,
- url_callback_t callback,
- const std::string& callback_url,
- bool teleport) // immediately teleport when result returned
-{
- mSLURLRegionName.clear();
- mSLURLRegionHandle = region_handle;
- mSLURL = callback_url;
- mSLURLCallback = callback;
- mSLURLTeleport = teleport;
-
- U32 global_x;
- U32 global_y;
- from_region_handle(region_handle, &global_x, &global_y);
- U16 grid_x = (U16)(global_x / REGION_WIDTH_UNITS);
- U16 grid_y = (U16)(global_y / REGION_WIDTH_UNITS);
-
- sendMapBlockRequest(grid_x, grid_y, grid_x, grid_y, true);
-}
-
-// public
-void LLWorldMap::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent)
-{
- S32 layer = mCurrentMap;
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_MapBlockRequest);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- U32 flags = layer;
- flags |= (return_nonexistent ? 0x10000 : 0);
- msg->addU32Fast(_PREHASH_Flags, flags);
- msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
- msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
- msg->nextBlockFast(_PREHASH_PositionData);
- msg->addU16Fast(_PREHASH_MinX, min_x);
- msg->addU16Fast(_PREHASH_MinY, min_y);
- msg->addU16Fast(_PREHASH_MaxX, max_x);
- msg->addU16Fast(_PREHASH_MaxY, max_y);
- gAgent.sendReliableMessage();
-
- if (mRequestLandForSale)
- {
- msg->newMessageFast(_PREHASH_MapBlockRequest);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->addU32Fast(_PREHASH_Flags, 2);
- msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
- msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
- msg->nextBlockFast(_PREHASH_PositionData);
- msg->addU16Fast(_PREHASH_MinX, min_x);
- msg->addU16Fast(_PREHASH_MinY, min_y);
- msg->addU16Fast(_PREHASH_MaxX, max_x);
- msg->addU16Fast(_PREHASH_MaxY, max_y);
- gAgent.sendReliableMessage();
- }
-}
-
-// public static
-void LLWorldMap::processMapLayerReply(LLMessageSystem* msg, void**)
+// static public
+// Insert an item in the relevant region map
+// returns true if item inserted, false otherwise
+bool LLWorldMap::insertItem(U32 x_world, U32 y_world, std::string& name, LLUUID& uuid, U32 type, S32 extra, S32 extra2)
{
- llinfos << "LLWorldMap::processMapLayerReply from message system" << llendl;
+ // Create an item record for the received object
+ LLItemInfo new_item((F32)x_world, (F32)y_world, name, uuid);
- U32 agent_flags;
- msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags);
+ // Compute a region handle based on the objects coordinates
+ LLVector3d pos((F32)x_world, (F32)y_world, 40.0);
+ U64 handle = to_region_handle(pos);
- if (agent_flags != (U32)LLWorldMap::getInstance()->mCurrentMap)
+ // Get the region record for that handle or NULL if we haven't browsed it yet
+ LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle);
+ if (siminfo == NULL)
{
- llwarns << "Invalid or out of date map image type returned!" << llendl;
- return;
+ siminfo = LLWorldMap::getInstance()->createSimInfoFromHandle(handle);
}
- LLUUID image_id;
- //U32 left, right, top, bottom;
-
- S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_LayerData);
-
- LLWorldMap::getInstance()->mMapLayers[agent_flags].clear();
-
- BOOL adjust = FALSE;
- for (S32 block=0; block<num_blocks; ++block)
+ //LL_INFOS("World Map") << "Process item : type = " << type << LL_ENDL;
+ switch (type)
{
- LLWorldMapLayer new_layer;
- new_layer.LayerDefined = TRUE;
- msg->getUUIDFast(_PREHASH_LayerData, _PREHASH_ImageID, new_layer.LayerImageID, block);
- new_layer.LayerImage = gImageList.getImage(new_layer.LayerImageID, MIPMAP_TRUE, FALSE);
-
- gGL.getTexUnit(0)->bind(new_layer.LayerImage.get());
- new_layer.LayerImage->setAddressMode(LLTexUnit::TAM_CLAMP);
-
- U32 left, right, top, bottom;
- msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Left, left, block);
- msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Right, right, block);
- msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Top, top, block);
- msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Bottom, bottom, block);
-
- new_layer.LayerExtents.mLeft = left;
- new_layer.LayerExtents.mRight = right;
- new_layer.LayerExtents.mBottom = bottom;
- new_layer.LayerExtents.mTop = top;
-
- F32 x_meters = F32(left*REGION_WIDTH_UNITS);
- F32 y_meters = F32(bottom*REGION_WIDTH_UNITS);
- adjust = LLWorldMap::getInstance()->extendAABB(U32(x_meters), U32(y_meters),
- U32(x_meters+REGION_WIDTH_UNITS*new_layer.LayerExtents.getWidth()),
- U32(y_meters+REGION_WIDTH_UNITS*new_layer.LayerExtents.getHeight())) || adjust;
-
- LLWorldMap::getInstance()->mMapLayers[agent_flags].push_back(new_layer);
- }
-
- LLWorldMap::getInstance()->mMapLoaded[agent_flags] = TRUE;
- if(adjust) gFloaterWorldMap->adjustZoomSliderBounds();
-}
-
-// public static
-void LLWorldMap::processMapBlockReply(LLMessageSystem* msg, void**)
-{
- U32 agent_flags;
- msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags);
-
- if ((S32)agent_flags < 0 || agent_flags >= MAP_SIM_IMAGE_TYPES)
- {
- llwarns << "Invalid map image type returned! " << agent_flags << llendl;
- return;
- }
-
- S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_Data);
-
- bool found_null_sim = false;
-
- BOOL adjust = FALSE;
- for (S32 block=0; block<num_blocks; ++block)
- {
- U16 x_regions;
- U16 y_regions;
- std::string name;
- U8 accesscode;
- U32 region_flags;
- U8 water_height;
- U8 agents;
- LLUUID image_id;
- msg->getU16Fast(_PREHASH_Data, _PREHASH_X, x_regions, block);
- msg->getU16Fast(_PREHASH_Data, _PREHASH_Y, y_regions, block);
- msg->getStringFast(_PREHASH_Data, _PREHASH_Name, name, block);
- msg->getU8Fast(_PREHASH_Data, _PREHASH_Access, accesscode, block);
- msg->getU32Fast(_PREHASH_Data, _PREHASH_RegionFlags, region_flags, block);
- msg->getU8Fast(_PREHASH_Data, _PREHASH_WaterHeight, water_height, block);
- msg->getU8Fast(_PREHASH_Data, _PREHASH_Agents, agents, block);
- msg->getUUIDFast(_PREHASH_Data, _PREHASH_MapImageID, image_id, block);
-
- U32 x_meters = x_regions * REGION_WIDTH_UNITS;
- U32 y_meters = y_regions * REGION_WIDTH_UNITS;
-
- U64 handle = to_region_handle(x_meters, y_meters);
-
- if (accesscode == 255)
- {
- // This region doesn't exist
- if (LLWorldMap::getInstance()->mIsTrackingUnknownLocation &&
- LLWorldMap::getInstance()->mUnknownLocation.mdV[0] >= x_meters &&
- LLWorldMap::getInstance()->mUnknownLocation.mdV[0] < x_meters + 256 &&
- LLWorldMap::getInstance()->mUnknownLocation.mdV[1] >= y_meters &&
- LLWorldMap::getInstance()->mUnknownLocation.mdV[1] < y_meters + 256)
- {
- // We were tracking this location, but it doesn't exist
- LLWorldMap::getInstance()->mInvalidLocation = TRUE;
- }
-
- found_null_sim = true;
- }
- else
+ case MAP_ITEM_TELEHUB: // telehubs
{
- adjust = LLWorldMap::getInstance()->extendAABB(x_meters,
- y_meters,
- x_meters+REGION_WIDTH_UNITS,
- y_meters+REGION_WIDTH_UNITS) || adjust;
-
-// llinfos << "Map sim " << name << " image layer " << agent_flags << " ID " << image_id.getString() << llendl;
+ /* Merov: we are not using the hub color anymore for display so commenting that out
+ // Telehub color
+ U32 X = x_world / REGION_WIDTH_UNITS;
+ U32 Y = y_world / REGION_WIDTH_UNITS;
+ F32 red = fmod((F32)X * 0.11f, 1.f) * 0.8f;
+ F32 green = fmod((F32)Y * 0.11f, 1.f) * 0.8f;
+ F32 blue = fmod(1.5f * (F32)(X + Y) * 0.11f, 1.f) * 0.8f;
+ F32 add_amt = (X % 2) ? 0.15f : -0.15f;
+ add_amt += (Y % 2) ? -0.15f : 0.15f;
+ LLColor4 color(red + add_amt, green + add_amt, blue + add_amt);
+ new_item.setColor(color);
+ */
- LLSimInfo* siminfo = new LLSimInfo();
- sim_info_map_t::iterator iter = LLWorldMap::getInstance()->mSimInfoMap.find(handle);
- if (iter != LLWorldMap::getInstance()->mSimInfoMap.end())
+ // extra2 specifies whether this is an infohub or a telehub.
+ if (extra2)
{
- LLSimInfo* oldinfo = iter->second;
- for (S32 image=0; image<MAP_SIM_IMAGE_TYPES; ++image)
- {
- siminfo->mMapImageID[image] = oldinfo->mMapImageID[image];
- }
- delete oldinfo;
- }
- LLWorldMap::getInstance()->mSimInfoMap[handle] = siminfo;
-
- siminfo->mHandle = handle;
- siminfo->mName.assign( name );
- siminfo->mAccess = accesscode;
- siminfo->mRegionFlags = region_flags;
- siminfo->mWaterHeight = (F32) water_height;
- siminfo->mMapImageID[agent_flags] = image_id;
-
-#ifdef IMMEDIATE_IMAGE_LOAD
- siminfo->mCurrentImage = gImageList.getImage(siminfo->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE);
- gGL.getTexUnit(0)->bind(siminfo->mCurrentImage.get());
- siminfo->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP);
-#endif
-
- if (siminfo->mMapImageID[2].notNull())
- {
-#ifdef IMMEDIATE_IMAGE_LOAD
- siminfo->mOverlayImage = gImageList.getImage(siminfo->mMapImageID[2], MIPMAP_TRUE, FALSE);
-#endif
+ siminfo->insertInfoHub(new_item);
}
else
{
- siminfo->mOverlayImage = NULL;
- }
-
- if (LLWorldMap::getInstance()->mIsTrackingUnknownLocation &&
- LLWorldMap::getInstance()->mUnknownLocation.mdV[0] >= x_meters &&
- LLWorldMap::getInstance()->mUnknownLocation.mdV[0] < x_meters + 256 &&
- LLWorldMap::getInstance()->mUnknownLocation.mdV[1] >= y_meters &&
- LLWorldMap::getInstance()->mUnknownLocation.mdV[1] < y_meters + 256)
- {
- if (siminfo->mAccess == SIM_ACCESS_DOWN)
- {
- // We were tracking this location, but it doesn't exist
- LLWorldMap::getInstance()->mInvalidLocation = true;
- }
- else
- {
- // We were tracking this location, and it does exist
- bool is_tracking_dbl = LLWorldMap::getInstance()->mIsTrackingDoubleClick == TRUE;
- gFloaterWorldMap->trackLocation(LLWorldMap::getInstance()->mUnknownLocation);
- if (is_tracking_dbl)
- {
- LLVector3d pos_global = LLTracker::getTrackedPositionGlobal();
- gAgent.teleportViaLocation( pos_global );
- }
- }
+ siminfo->insertTeleHub(new_item);
}
+ break;
}
-
- if(LLWorldMap::getInstance()->mSLURLCallback != NULL)
+ case MAP_ITEM_PG_EVENT: // events
+ case MAP_ITEM_MATURE_EVENT:
+ case MAP_ITEM_ADULT_EVENT:
{
- // Server returns definitive capitalization, SLURL might not have that.
- if ((LLStringUtil::compareInsensitive(LLWorldMap::getInstance()->mSLURLRegionName, name)==0)
- || (LLWorldMap::getInstance()->mSLURLRegionHandle == handle))
+ std::string timeStr = "["+ LLTrans::getString ("TimeHour")+"]:["
+ +LLTrans::getString ("TimeMin")+"] ["
+ +LLTrans::getString ("TimeAMPM")+"]";
+ LLSD substitution;
+ substitution["datetime"] = (S32) extra;
+ LLStringUtil::format (timeStr, substitution);
+ new_item.setTooltip(timeStr);
+
+ // HACK: store Z in extra2
+ new_item.setElevation((F64)extra2);
+ if (type == MAP_ITEM_PG_EVENT)
{
- url_callback_t callback = LLWorldMap::getInstance()->mSLURLCallback;
-
- LLWorldMap::getInstance()->mSLURLCallback = NULL;
- LLWorldMap::getInstance()->mSLURLRegionName.clear();
- LLWorldMap::getInstance()->mSLURLRegionHandle = 0;
-
- callback(handle, LLWorldMap::getInstance()->mSLURL, image_id, LLWorldMap::getInstance()->mSLURLTeleport);
+ siminfo->insertPGEvent(new_item);
}
- }
- }
-
- if(adjust) gFloaterWorldMap->adjustZoomSliderBounds();
- gFloaterWorldMap->updateSims(found_null_sim);
-}
-
-// public static
-void LLWorldMap::processMapItemReply(LLMessageSystem* msg, void**)
-{
- U32 type;
- msg->getU32Fast(_PREHASH_RequestData, _PREHASH_ItemType, type);
-
- S32 num_blocks = msg->getNumberOfBlocks("Data");
-
- for (S32 block=0; block<num_blocks; ++block)
- {
- U32 X, Y;
- std::string name;
- S32 extra, extra2;
- LLUUID uuid;
- msg->getU32Fast(_PREHASH_Data, _PREHASH_X, X, block);
- msg->getU32Fast(_PREHASH_Data, _PREHASH_Y, Y, block);
- msg->getStringFast(_PREHASH_Data, _PREHASH_Name, name, block);
- msg->getUUIDFast(_PREHASH_Data, _PREHASH_ID, uuid, block);
- msg->getS32Fast(_PREHASH_Data, _PREHASH_Extra, extra, block);
- msg->getS32Fast(_PREHASH_Data, _PREHASH_Extra2, extra2, block);
-
- F32 world_x = (F32)X;
- X /= REGION_WIDTH_UNITS;
- F32 world_y = (F32)Y;
- Y /= REGION_WIDTH_UNITS;
-
- LLItemInfo new_item(world_x, world_y, name, uuid, extra, extra2);
- LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(new_item.mRegionHandle);
-
- switch (type)
- {
- case MAP_ITEM_TELEHUB: // telehubs
+ else if (type == MAP_ITEM_MATURE_EVENT)
{
- // Telehub color, store in extra as 4 U8's
- U8 *color = (U8 *)&new_item.mExtra;
-
- F32 red = fmod((F32)X * 0.11f, 1.f) * 0.8f;
- F32 green = fmod((F32)Y * 0.11f, 1.f) * 0.8f;
- F32 blue = fmod(1.5f * (F32)(X + Y) * 0.11f, 1.f) * 0.8f;
- F32 add_amt = (X % 2) ? 0.15f : -0.15f;
- add_amt += (Y % 2) ? -0.15f : 0.15f;
- color[0] = U8((red + add_amt) * 255);
- color[1] = U8((green + add_amt) * 255);
- color[2] = U8((blue + add_amt) * 255);
- color[3] = 255;
-
- // extra2 specifies whether this is an infohub or a telehub.
- if (extra2)
- {
- LLWorldMap::getInstance()->mInfohubs.push_back(new_item);
- }
- else
- {
- LLWorldMap::getInstance()->mTelehubs.push_back(new_item);
- }
-
- break;
+ siminfo->insertMatureEvent(new_item);
}
- case MAP_ITEM_PG_EVENT: // events
- case MAP_ITEM_MATURE_EVENT:
- case MAP_ITEM_ADULT_EVENT:
+ else if (type == MAP_ITEM_ADULT_EVENT)
{
- struct tm* timep;
- // Convert to Pacific, based on server's opinion of whether
- // it's daylight savings time there.
- timep = utc_to_pacific_time(extra, gPacificDaylightTime);
-
- S32 display_hour = timep->tm_hour % 12;
- if (display_hour == 0) display_hour = 12;
-
- new_item.mToolTip = llformat( "%d:%02d %s",
- display_hour,
- timep->tm_min,
- (timep->tm_hour < 12 ? "AM" : "PM") );
-
- // HACK: store Z in extra2
- new_item.mPosGlobal.mdV[VZ] = (F64)extra2;
- if (type == MAP_ITEM_PG_EVENT)
- {
- LLWorldMap::getInstance()->mPGEvents.push_back(new_item);
- }
- else if (type == MAP_ITEM_MATURE_EVENT)
- {
- LLWorldMap::getInstance()->mMatureEvents.push_back(new_item);
- }
- else if (type == MAP_ITEM_ADULT_EVENT)
- {
- LLWorldMap::getInstance()->mAdultEvents.push_back(new_item);
- }
-
- break;
+ siminfo->insertAdultEvent(new_item);
}
- case MAP_ITEM_LAND_FOR_SALE: // land for sale
- case MAP_ITEM_LAND_FOR_SALE_ADULT: // adult land for sale
+ break;
+ }
+ case MAP_ITEM_LAND_FOR_SALE: // land for sale
+ case MAP_ITEM_LAND_FOR_SALE_ADULT: // adult land for sale
+ {
+ std::string tooltip = llformat("%d sq. m. L$%d", extra, extra2);
+ new_item.setTooltip(tooltip);
+ if (type == MAP_ITEM_LAND_FOR_SALE)
{
- new_item.mToolTip = llformat("%d sq. m. L$%d", new_item.mExtra, new_item.mExtra2);
- if (type == MAP_ITEM_LAND_FOR_SALE)
- {
- LLWorldMap::getInstance()->mLandForSale.push_back(new_item);
- }
- else if (type == MAP_ITEM_LAND_FOR_SALE_ADULT)
- {
- LLWorldMap::getInstance()->mLandForSaleAdult.push_back(new_item);
- }
- break;
+ siminfo->insertLandForSale(new_item);
}
- case MAP_ITEM_CLASSIFIED: // classifieds
+ else if (type == MAP_ITEM_LAND_FOR_SALE_ADULT)
{
- //DEPRECATED: no longer used
- break;
+ siminfo->insertLandForSaleAdult(new_item);
}
- case MAP_ITEM_AGENT_LOCATIONS: // agent locations
+ break;
+ }
+ case MAP_ITEM_CLASSIFIED: // classifieds
+ {
+ //DEPRECATED: no longer used
+ break;
+ }
+ case MAP_ITEM_AGENT_LOCATIONS: // agent locations
+ {
+// LL_INFOS("World Map") << "New Location " << new_item.mName << LL_ENDL;
+ if (extra > 0)
{
- if (!siminfo)
- {
- llinfos << "siminfo missing for " << new_item.mPosGlobal.mdV[0] << ", " << new_item.mPosGlobal.mdV[1] << llendl;
- break;
- }
-// llinfos << "New Location " << new_item.mName << llendl;
-
- item_info_list_t& agentcounts = LLWorldMap::getInstance()->mAgentLocationsMap[new_item.mRegionHandle];
-
- // Find the last item in the list with a different name and erase them
- item_info_list_t::iterator lastiter;
- for (lastiter = agentcounts.begin(); lastiter!=agentcounts.end(); ++lastiter)
- {
- const LLItemInfo& info = *lastiter;
- if (info.mName == new_item.mName)
- {
- break;
- }
- }
- if (lastiter != agentcounts.begin())
- {
- agentcounts.erase(agentcounts.begin(), lastiter);
- }
- // Now append the new location
- if (new_item.mExtra > 0)
- {
- agentcounts.push_back(new_item);
- }
- break;
+ new_item.setCount(extra);
+ siminfo->insertAgentLocation(new_item);
}
- default:
- break;
- };
- }
-}
-
-void LLWorldMap::dump()
-{
- for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
- {
- U64 handle = (*it).first;
- LLSimInfo* info = (*it).second;
-
- U32 x_pos, y_pos;
- from_region_handle(handle, &x_pos, &y_pos);
-
- llinfos << x_pos << "," << y_pos
- << " " << info->mName
- << " " << (S32)info->mAccess
- << " " << std::hex << info->mRegionFlags << std::dec
- << " " << info->mWaterHeight
- //<< " " << info->mTelehubName
- //<< " " << info->mTelehubPosition
- << llendl;
-
- if (info->mCurrentImage)
- {
- llinfos << "image discard " << (S32)info->mCurrentImage->getDiscardLevel()
- << " fullwidth " << info->mCurrentImage->getWidth(0)
- << " fullheight " << info->mCurrentImage->getHeight(0)
- << " maxvirt " << info->mCurrentImage->mMaxVirtualSize
- << " maxdisc " << (S32)info->mCurrentImage->getMaxDiscardLevel()
- << llendl;
+ break;
}
+ default:
+ break;
}
+ return true;
}
-
-BOOL LLWorldMap::extendAABB(U32 min_x, U32 min_y, U32 max_x, U32 max_y)
-{
- BOOL rv = FALSE;
- if (min_x < mMinX)
- {
- rv = TRUE;
- mMinX = min_x;
- }
- if (min_y < mMinY)
- {
- rv = TRUE;
- mMinY = min_y;
- }
- if (max_x > mMaxX)
- {
- rv = TRUE;
- mMaxX = max_x;
- }
- if (max_y > mMaxY)
- {
- rv = TRUE;
- mMaxY = max_y;
- }
- lldebugs << "World map aabb: (" << mMinX << ", " << mMinY << "), ("
- << mMaxX << ", " << mMaxY << ")" << llendl;
- return rv;
-}
-
-
-U32 LLWorldMap::getWorldWidth() const
-{
- return mMaxX - mMinX;
-}
-
-
-U32 LLWorldMap::getWorldHeight() const
+bool LLWorldMap::isTrackingInRectangle(F64 x0, F64 y0, F64 x1, F64 y1)
{
- return mMaxY - mMinY;
+ if (!mIsTrackingLocation)
+ return false;
+ return ((mTrackingLocation[0] >= x0) && (mTrackingLocation[0] < x1) && (mTrackingLocation[1] >= y0) && (mTrackingLocation[1] < y1));
}
-BOOL LLWorldMap::coveredByTelehub(LLSimInfo* infop)
+// Drop priority of all images being fetched by the map
+void LLWorldMap::dropImagePriorities()
{
- /*if (!mTelehubCoverageMap)
+ // Drop the download of tiles priority to nil
+ mWorldMipmap.dropBoostLevels();
+ // Same for the "land for sale" tiles per region
+ for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
{
- return FALSE;
+ LLSimInfo* info = it->second;
+ info->dropImagePriority();
}
- U32 x_pos, y_pos;
- from_region_handle(infop->mHandle, &x_pos, &y_pos);
- x_pos /= REGION_WIDTH_UNITS;
- y_pos /= REGION_WIDTH_UNITS;
-
- S32 index = x_pos - (mMinX / REGION_WIDTH_UNITS - 1) + (mNeighborMapWidth * (y_pos - (mMinY / REGION_WIDTH_UNITS - 1)));
- return mTelehubCoverageMap[index] != 0; */
- return FALSE;
}
-void LLWorldMap::updateTelehubCoverage()
+// Load all regions in a given rectangle (in region grid coordinates, i.e. world / 256 meters)
+void LLWorldMap::updateRegions(S32 x0, S32 y0, S32 x1, S32 y1)
{
- /*S32 neighbor_width = getWorldWidth() / REGION_WIDTH_UNITS + 2;
- S32 neighbor_height = getWorldHeight() / REGION_WIDTH_UNITS + 2;
- if (neighbor_width > mNeighborMapWidth || neighbor_height > mNeighborMapHeight)
- {
- mNeighborMapWidth = neighbor_width;
- mNeighborMapHeight = neighbor_height;
- delete mNeighborMap;
- delete mTelehubCoverageMap;
-
- mNeighborMap = new U8[mNeighborMapWidth * mNeighborMapHeight];
- mTelehubCoverageMap = new U8[mNeighborMapWidth * mNeighborMapHeight];
- }
-
- memset(mNeighborMap, 0, mNeighborMapWidth * mNeighborMapHeight * sizeof(U8));
- memset(mTelehubCoverageMap, 0, mNeighborMapWidth * mNeighborMapHeight * sizeof(U8));
+ // Convert those boundaries to the corresponding (MAP_BLOCK_SIZE x MAP_BLOCK_SIZE) block coordinates
+ x0 = x0 / MAP_BLOCK_SIZE;
+ x1 = x1 / MAP_BLOCK_SIZE;
+ y0 = y0 / MAP_BLOCK_SIZE;
+ y1 = y1 / MAP_BLOCK_SIZE;
- // leave 1 sim border
- S32 min_x = (mMinX / REGION_WIDTH_UNITS) - 1;
- S32 min_y = (mMinY / REGION_WIDTH_UNITS) - 1;
-
- std::map<U64, LLSimInfo*>::const_iterator it;
- for (it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
+ // Load the region info those blocks
+ for (S32 block_x = llmax(x0, 0); block_x <= llmin(x1, MAP_BLOCK_RES-1); ++block_x)
{
- U64 handle = (*it).first;
- //LLSimInfo* info = (*it).second;
-
- U32 x_pos, y_pos;
- from_region_handle(handle, &x_pos, &y_pos);
- x_pos /= REGION_WIDTH_UNITS;
- y_pos /= REGION_WIDTH_UNITS;
- x_pos -= min_x;
- y_pos -= min_y;
-
- S32 index = x_pos + (mNeighborMapWidth * y_pos);
- mNeighborMap[index - 1]++;
- mNeighborMap[index + 1]++;
- mNeighborMap[index - mNeighborMapWidth]++;
- mNeighborMap[index + mNeighborMapWidth]++;
- }
-
- for (it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
- {
- U64 handle = (*it).first;
- LLSimInfo* info = (*it).second;
-
- U32 x_pos, y_pos;
- from_region_handle(handle, &x_pos, &y_pos);
- x_pos /= REGION_WIDTH_UNITS;
- y_pos /= REGION_WIDTH_UNITS;
- x_pos -= min_x;
- y_pos -= min_y;
-
- S32 index = x_pos + (mNeighborMapWidth * y_pos);
-
- if (!info->mTelehubName.empty() && mNeighborMap[index])
+ for (S32 block_y = llmax(y0, 0); block_y <= llmin(y1, MAP_BLOCK_RES-1); ++block_y)
{
- S32 x_start = llmax(0, S32(x_pos - 5));
- S32 x_span = llmin(mNeighborMapWidth - 1, (S32)(x_pos + 5)) - x_start + 1;
- S32 y_start = llmax(0, (S32)y_pos - 5);
- S32 y_end = llmin(mNeighborMapHeight - 1, (S32)(y_pos + 5));
- for (S32 y_index = y_start; y_index <= y_end; y_index++)
+ S32 offset = block_x | (block_y * MAP_BLOCK_RES);
+ if (!mMapBlockLoaded[offset])
{
- memset(&mTelehubCoverageMap[x_start + y_index * mNeighborMapWidth], 0xff, sizeof(U8) * x_span);
+ //LL_INFOS("World Map") << "Loading Block (" << block_x << "," << block_y << ")" << LL_ENDL;
+ LLWorldMapMessage::getInstance()->sendMapBlockRequest(block_x * MAP_BLOCK_SIZE, block_y * MAP_BLOCK_SIZE, (block_x * MAP_BLOCK_SIZE) + MAP_BLOCK_SIZE - 1, (block_y * MAP_BLOCK_SIZE) + MAP_BLOCK_SIZE - 1);
+ mMapBlockLoaded[offset] = true;
}
}
}
+}
- for (it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
+void LLWorldMap::dump()
+{
+ LL_INFOS("World Map") << "LLWorldMap::dump()" << LL_ENDL;
+ for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
{
- U64 handle = (*it).first;
- //LLSimInfo* info = (*it).second;
-
- U32 x_pos, y_pos;
- from_region_handle(handle, &x_pos, &y_pos);
- x_pos /= REGION_WIDTH_UNITS;
- y_pos /= REGION_WIDTH_UNITS;
-
- S32 index = x_pos - min_x + (mNeighborMapWidth * (y_pos - min_y));
- mTelehubCoverageMap[index] *= mNeighborMap[index];
- }*/
+ LLSimInfo* info = it->second;
+ if (info)
+ {
+ info->dump();
+ }
+ }
}
+
diff --git a/indra/newview/llworldmap.h b/indra/newview/llworldmap.h
index bb3c97cfd9..7e37727b86 100644
--- a/indra/newview/llworldmap.h
+++ b/indra/newview/llworldmap.h
@@ -33,199 +33,243 @@
#ifndef LL_LLWORLDMAP_H
#define LL_LLWORLDMAP_H
-#include <map>
-#include <string>
-#include <vector>
+#include "llworldmipmap.h"
+#include <boost/function.hpp>
-#include "v3math.h"
#include "v3dmath.h"
-#include "llframetimer.h"
-#include "llmapimagetype.h"
#include "lluuid.h"
-#include "llmemory.h"
-#include "llviewerimage.h"
-#include "lleventinfo.h"
-#include "v3color.h"
-
-class LLMessageSystem;
-
-
+#include "llpointer.h"
+#include "llsingleton.h"
+#include "llviewerregion.h"
+#include "llviewertexture.h"
+
+// Description of objects like hubs, events, land for sale, people and more (TBD).
+// Note: we don't store a "type" in there so we need to store instances of this class in
+// well known objects (i.e. list of objects which type is "well known").
class LLItemInfo
{
public:
- LLItemInfo(F32 global_x, F32 global_y, const std::string& name, LLUUID id, S32 extra = 0, S32 extra2 = 0);
-
- std::string mName;
- std::string mToolTip;
- LLVector3d mPosGlobal;
- LLUUID mID;
- BOOL mSelected;
- S32 mExtra;
- S32 mExtra2;
- U64 mRegionHandle;
-};
+ LLItemInfo(F32 global_x, F32 global_y, const std::string& name, LLUUID id);
+
+ // Setters
+ void setTooltip(std::string& tooltip) { mToolTip = tooltip; }
+ void setElevation(F64 z) { mPosGlobal.mdV[VZ] = z; }
+ void setCount(S32 count) { mCount = count; }
+// void setSelected(bool selected) { mSelected = selected; }
+// void setColor(LLColor4 color) { mColor = color; }
+
+ // Accessors
+ const LLVector3d& getGlobalPosition() const { return mPosGlobal; }
+ const std::string& getName() const { return mName; }
+ const std::string& getToolTip() const { return mToolTip; }
+ const LLUUID& getUUID() const { return mID; }
+ S32 getCount() const { return mCount; }
+
+ U64 getRegionHandle() const { return to_region_handle(mPosGlobal); } // Build the handle on the fly
-// Map layers, see indra_constants.h
-// 0 - Prim
-// 1 - Terrain Only
-// 2 - Overlay: Land For Sale
+ bool isName(const std::string& name) const { return (mName == name); } // True if name same as item's name
+// bool isSelected() const { return mSelected; }
+private:
+ std::string mName; // Name of the individual item
+ std::string mToolTip; // Tooltip : typically, something to be displayed to the user when selecting this item
+ LLVector3d mPosGlobal; // Global world position
+ LLUUID mID; // UUID of the item
+ S32 mCount; // Number of elements in item (e.g. people count)
+ // Currently not used but might prove useful one day so we comment out
+// bool mSelected; // Selected or not: updated by the viewer UI, not the simulator or asset DB
+// LLColor4 mColor; // Color of the item
+};
+
+// Info per region
+// Such records are stored in a global map hold by the LLWorldMap and indexed by region handles.
+// To avoid creating too many of them, they are requested in "blocks" corresponding to areas covered by the screen.
+// Unfortunately, when the screen covers the whole world (zoomed out), that can translate in requesting info for
+// every sim on the grid... Not good...
+// To avoid this, the code implements a cut-off threshold for overlay graphics and, therefore, all LLSimInfo.
+// In other words, when zooming out too much, we simply stop requesting LLSimInfo and
+// LLItemInfo and just display the map tiles.
+// As they are stored in different structures (LLSimInfo and LLWorldMipmap), this strategy is now workable.
class LLSimInfo
{
public:
- LLSimInfo();
+ LLSimInfo(U64 handle);
- LLVector3d getGlobalPos(LLVector3 local_pos) const;
+ // Convert local region coordinates into world coordinates
+ LLVector3d getGlobalPos(const LLVector3& local_pos) const;
+ // Get the world coordinates of the SW corner of that region
+ LLVector3d getGlobalOrigin() const;
+ LLVector3 getLocalPos(LLVector3d global_pos) const;
-public:
- U64 mHandle;
- std::string mName;
-
- F64 mAgentsUpdateTime;
- BOOL mShowAgentLocations; // are agents visible?
+ void clearImage(); // Clears the reference to the Land for sale image for that region
+ void dropImagePriority(); // Drops the boost level of the Land for sale image for that region
+ void updateAgentCount(F64 time); // Send an item request for agent count on that region if time's up
- U8 mAccess;
- U32 mRegionFlags;
- F32 mWaterHeight;
+ // Setters
+ void setName(std::string& name) { mName = name; }
+ void setAccess (U32 accesscode) { mAccess = accesscode; }
+ void setRegionFlags (U32 region_flags) { mRegionFlags = region_flags; }
+ void setLandForSaleImage (LLUUID image_id);
+// void setWaterHeight (F32 water_height) { mWaterHeight = water_height; }
- F32 mAlpha;
+ // Accessors
+ std::string getName() const { return mName; }
+ const std::string getFlagsString() const { return LLViewerRegion::regionFlagsToString(mRegionFlags); }
+ const std::string getAccessString() const { return LLViewerRegion::accessToString((U8)mAccess); }
- // Image ID for the current overlay mode.
- LLUUID mMapImageID[MAP_SIM_IMAGE_TYPES];
+ const S32 getAgentCount() const; // Compute the total agents count
+ LLPointer<LLViewerFetchedTexture> getLandForSaleImage(); // Get the overlay image, fetch it if necessary
- // Hold a reference to the currently displayed image.
- LLPointer<LLViewerImage> mCurrentImage;
- LLPointer<LLViewerImage> mOverlayImage;
-};
+ bool isName(const std::string& name) const;
+ bool isDown() { return (mAccess == SIM_ACCESS_DOWN); }
+ bool isPG() { return (mAccess <= SIM_ACCESS_PG); }
-#define MAP_BLOCK_RES 256
+ // Debug only
+ void dump() const; // Print the region info to the standard output
-struct LLWorldMapLayer
-{
- BOOL LayerDefined;
- LLPointer<LLViewerImage> LayerImage;
- LLUUID LayerImageID;
- LLRect LayerExtents;
+ // Items lists handling
+ typedef std::vector<LLItemInfo> item_info_list_t;
+ void clearItems();
+
+ void insertTeleHub(const LLItemInfo& item) { mTelehubs.push_back(item); }
+ void insertInfoHub(const LLItemInfo& item) { mInfohubs.push_back(item); }
+ void insertPGEvent(const LLItemInfo& item) { mPGEvents.push_back(item); }
+ void insertMatureEvent(const LLItemInfo& item) { mMatureEvents.push_back(item); }
+ void insertAdultEvent(const LLItemInfo& item) { mAdultEvents.push_back(item); }
+ void insertLandForSale(const LLItemInfo& item) { mLandForSale.push_back(item); }
+ void insertLandForSaleAdult(const LLItemInfo& item) { mLandForSaleAdult.push_back(item); }
+ void insertAgentLocation(const LLItemInfo& item);
+
+ const LLSimInfo::item_info_list_t& getTeleHub() const { return mTelehubs; }
+ const LLSimInfo::item_info_list_t& getInfoHub() const { return mInfohubs; }
+ const LLSimInfo::item_info_list_t& getPGEvent() const { return mPGEvents; }
+ const LLSimInfo::item_info_list_t& getMatureEvent() const { return mMatureEvents; }
+ const LLSimInfo::item_info_list_t& getAdultEvent() const { return mAdultEvents; }
+ const LLSimInfo::item_info_list_t& getLandForSale() const { return mLandForSale; }
+ const LLSimInfo::item_info_list_t& getLandForSaleAdult() const { return mLandForSaleAdult; }
+ const LLSimInfo::item_info_list_t& getAgentLocation() const { return mAgentLocations; }
- LLWorldMapLayer() : LayerDefined(FALSE) { }
+private:
+ U64 mHandle; // This is a hash of the X and Y world coordinates of the SW corner of the sim
+ std::string mName; // Region name
+
+ F64 mAgentsUpdateTime; // Time stamp giving the last time the agents information was requested for that region
+ bool mFirstAgentRequest; // Init agent request flag
+
+ U32 mAccess; // Down/up and maturity rating of the region
+ U32 mRegionFlags; // Tell us if the siminfo has been received (if non 0) and what kind of region it is (Sandbox, allow damage)
+ // Currently not used but might prove useful one day so we comment out
+// F32 mWaterHeight; // Water height on the region (not actively used)
+
+ // Handling the "land for sale / land for auction" overlay image
+ LLUUID mMapImageID; // Image ID of the overlay image
+ LLPointer<LLViewerFetchedTexture> mOverlayImage; // Reference to the overlay image
+
+ // Items for this region
+ // Those are data received through item requests (as opposed to block requests for the rest of the data)
+ item_info_list_t mTelehubs; // List of tele hubs in the region
+ item_info_list_t mInfohubs; // List of info hubs in the region
+ item_info_list_t mPGEvents; // List of PG events in the region
+ item_info_list_t mMatureEvents; // List of Mature events in the region
+ item_info_list_t mAdultEvents; // List of Adult events in the region (AO)
+ item_info_list_t mLandForSale; // List of Land for sales in the region
+ item_info_list_t mLandForSaleAdult; // List of Adult Land for sales in the region (AO)
+ item_info_list_t mAgentLocations; // List of agents in the region
};
+// We request region data on the world by "blocks" of (MAP_BLOCK_SIZE x MAP_BLOCK_SIZE) regions
+// This is to reduce the number of requests to the asset DB and get things in big "blocks"
+const S32 MAP_MAX_SIZE = 2048;
+const S32 MAP_BLOCK_SIZE = 4;
+const S32 MAP_BLOCK_RES = (MAP_MAX_SIZE / MAP_BLOCK_SIZE);
class LLWorldMap : public LLSingleton<LLWorldMap>
{
public:
- typedef void(*url_callback_t)(U64 region_handle, const std::string& url, const LLUUID& snapshot_id, bool teleport);
-
LLWorldMap();
~LLWorldMap();
- // clears the list
+ // Clear all: list of region info, tiles, blocks and items
void reset();
- // clear the visible items
- void eraseItems();
+ void clearImageRefs(); // Clears the image references
+ void dropImagePriorities(); // Drops the priority of the images being fetched
+ void reloadItems(bool force = false); // Reload the items (people, hub, etc...)
- // Removes references to cached images
- void clearImageRefs();
+ // Region Map access
+ typedef std::map<U64, LLSimInfo*> sim_info_map_t;
+ const LLWorldMap::sim_info_map_t& getRegionMap() const { return mSimInfoMap; }
+ void updateRegions(S32 x0, S32 y0, S32 x1, S32 y1); // Requests region info for a rectangle of regions (in grid coordinates)
- // Clears the flags indicating that we've received sim infos
- // Causes a re-request of the sim info without erasing extisting info
- void clearSimFlags();
+ // Insert a region and items in the map global instance
+ // Note: x_world and y_world in world coordinates (meters)
+ static bool insertRegion(U32 x_world, U32 y_world, std::string& name, LLUUID& uuid, U32 accesscode, U32 region_flags);
+ static bool insertItem(U32 x_world, U32 y_world, std::string& name, LLUUID& uuid, U32 type, S32 extra, S32 extra2);
- // Returns simulator information, or NULL if out of range
+ // Get info on sims (region) : note that those methods only search the range of loaded sims (the one that are being browsed)
+ // *not* the entire world. So a NULL return does not mean a down or unexisting region, just an out of range region.
LLSimInfo* simInfoFromHandle(const U64 handle);
-
- // Returns simulator information, or NULL if out of range
LLSimInfo* simInfoFromPosGlobal(const LLVector3d& pos_global);
-
- // Returns simulator information for named sim, or NULL if non-existent
LLSimInfo* simInfoFromName(const std::string& sim_name);
- // Gets simulator name for a global position, returns true if it was found
+ // Gets simulator name from a global position, returns true if found
bool simNameFromPosGlobal(const LLVector3d& pos_global, std::string& outSimName );
- // Sets the current layer
- void setCurrentLayer(S32 layer, bool request_layer = false);
-
- void sendMapLayerRequest();
- void sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent = false);
- void sendNamedRegionRequest(std::string region_name);
- void sendNamedRegionRequest(std::string region_name,
- url_callback_t callback,
- const std::string& callback_url,
- bool teleport);
- void sendHandleRegionRequest(U64 region_handle,
- url_callback_t callback,
- const std::string& callback_url,
- bool teleport);
- void sendItemRequest(U32 type, U64 handle = 0);
-
- static void processMapLayerReply(LLMessageSystem*, void**);
- static void processMapBlockReply(LLMessageSystem*, void**);
- static void processMapItemReply(LLMessageSystem*, void**);
-
- void dump();
-
- // Extend the bounding box of the list of simulators. Returns true
- // if the extents changed.
- BOOL extendAABB(U32 x_min, U32 y_min, U32 x_max, U32 y_max);
-
- // build coverage maps for telehub region visualization
- void updateTelehubCoverage();
- BOOL coveredByTelehub(LLSimInfo* infop);
-
- // Bounds of the world, in meters
- U32 getWorldWidth() const;
- U32 getWorldHeight() const;
-public:
- // Map from region-handle to simulator info
- typedef std::map<U64, LLSimInfo*> sim_info_map_t;
- sim_info_map_t mSimInfoMap;
+ // Debug only
+ void dump(); // Print the world info to the standard output
- BOOL mIsTrackingUnknownLocation, mInvalidLocation, mIsTrackingDoubleClick, mIsTrackingCommit;
- LLVector3d mUnknownLocation;
+ // Track handling
+ void cancelTracking() { mIsTrackingLocation = false; mIsTrackingFound = false; mIsInvalidLocation = false; mIsTrackingDoubleClick = false; mIsTrackingCommit = false; }
- bool mRequestLandForSale;
+ void setTracking(const LLVector3d& loc) { mIsTrackingLocation = true; mTrackingLocation = loc; mIsTrackingFound = false; mIsInvalidLocation = false; mIsTrackingDoubleClick = false; mIsTrackingCommit = false;}
+ void setTrackingInvalid() { mIsTrackingFound = true; mIsInvalidLocation = true; }
+ void setTrackingValid() { mIsTrackingFound = true; mIsInvalidLocation = false; }
+ void setTrackingDoubleClick() { mIsTrackingDoubleClick = true; }
+ void setTrackingCommit() { mIsTrackingCommit = true; }
- typedef std::vector<LLItemInfo> item_info_list_t;
- item_info_list_t mTelehubs;
- item_info_list_t mInfohubs;
- item_info_list_t mPGEvents;
- item_info_list_t mMatureEvents;
- item_info_list_t mAdultEvents;
- item_info_list_t mLandForSale;
- item_info_list_t mLandForSaleAdult;
-
- std::map<U64,S32> mNumAgents;
-
- typedef std::map<U64, item_info_list_t> agent_list_map_t;
- agent_list_map_t mAgentLocationsMap;
-
- std::vector<LLWorldMapLayer> mMapLayers[MAP_SIM_IMAGE_TYPES];
- BOOL mMapLoaded[MAP_SIM_IMAGE_TYPES];
- BOOL * mMapBlockLoaded[MAP_SIM_IMAGE_TYPES];
- S32 mCurrentMap;
-
- // AABB of the list of simulators
- U32 mMinX;
- U32 mMaxX;
- U32 mMinY;
- U32 mMaxY;
-
- U8* mNeighborMap;
- U8* mTelehubCoverageMap;
- S32 mNeighborMapWidth;
- S32 mNeighborMapHeight;
+ bool isTracking() { return mIsTrackingLocation; }
+ bool isTrackingValidLocation() { return mIsTrackingFound && !mIsInvalidLocation; }
+ bool isTrackingInvalidLocation() { return mIsTrackingFound && mIsInvalidLocation; }
+ bool isTrackingDoubleClick() { return mIsTrackingDoubleClick; }
+ bool isTrackingCommit() { return mIsTrackingCommit; }
+ bool isTrackingInRectangle(F64 x0, F64 y0, F64 x1, F64 y1);
+
+ LLVector3d getTrackedPositionGlobal() const { return mTrackingLocation; }
+
+ // World Mipmap delegation: currently used when drawing the mipmap
+ void equalizeBoostLevels();
+ LLPointer<LLViewerFetchedTexture> getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load = true) { return mWorldMipmap.getObjectsTile(grid_x, grid_y, level, load); }
private:
- LLTimer mRequestTimer;
-
- // search for named region for url processing
- std::string mSLURLRegionName;
- U64 mSLURLRegionHandle;
- std::string mSLURL;
- url_callback_t mSLURLCallback;
- bool mSLURLTeleport;
+ bool clearItems(bool force = false); // Clears the item lists
+ void clearSimFlags(); // Clears the block flags indicating that we've already requested region infos
+
+ // Create a region record corresponding to the handle, insert it in the region map and returns a pointer
+ LLSimInfo* createSimInfoFromHandle(const U64 handle);
+
+ // Map from region-handle to region info
+ sim_info_map_t mSimInfoMap;
+
+ // Holds the tiled mipmap of the world. This is the structure that contains the images used for rendering.
+ LLWorldMipmap mWorldMipmap;
+
+ // The World is divided in "blocks" of (MAP_BLOCK_SIZE x MAP_BLOCK_SIZE) regions that get requested at once.
+ // This boolean table avoids "blocks" to be requested multiple times.
+ // Issue: Not sure this scheme is foolproof though as I've seen
+ // cases where a block is never retrieved and, because of this boolean being set, never re-requested
+ bool * mMapBlockLoaded; // Telling us if the block of regions has been requested or not
+
+ // Track location data : used while there's nothing tracked yet by LLTracker
+ bool mIsTrackingLocation; // True when we're tracking a point
+ bool mIsTrackingFound; // True when the tracking position has been found, valid or not
+ bool mIsInvalidLocation; // The region is down or the location does not correspond to an existing region
+ bool mIsTrackingDoubleClick; // User double clicked to set the location (i.e. teleport when found please...)
+ bool mIsTrackingCommit; // User used the search or landmark fields to set the location
+ LLVector3d mTrackingLocation; // World global position being tracked
+
+ // General grid items request timing flags (used for events,hubs and land for sale)
+ LLTimer mRequestTimer;
+ bool mFirstRequest;
};
#endif
diff --git a/indra/newview/llworldmapmessage.cpp b/indra/newview/llworldmapmessage.cpp
new file mode 100644
index 0000000000..06040a574c
--- /dev/null
+++ b/indra/newview/llworldmapmessage.cpp
@@ -0,0 +1,262 @@
+/**
+ * @file llworldmapmessage.cpp
+ * @brief Handling of the messages to the DB made by and for the world map.
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llworldmapmessage.h"
+#include "message.h"
+
+#include "llworldmap.h"
+#include "llagent.h"
+#include "llfloaterworldmap.h"
+
+const U32 LAYER_FLAG = 2;
+
+//---------------------------------------------------------------------------
+// World Map Message Handling
+//---------------------------------------------------------------------------
+
+LLWorldMapMessage::LLWorldMapMessage() :
+ mSLURLRegionName(),
+ mSLURLRegionHandle(0),
+ mSLURL(),
+ mSLURLCallback(0),
+ mSLURLTeleport(false)
+{
+}
+
+LLWorldMapMessage::~LLWorldMapMessage()
+{
+}
+
+void LLWorldMapMessage::sendItemRequest(U32 type, U64 handle)
+{
+ //LL_INFOS("World Map") << "Send item request : type = " << type << LL_ENDL;
+ LLMessageSystem* msg = gMessageSystem;
+
+ msg->newMessageFast(_PREHASH_MapItemRequest);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addU32Fast(_PREHASH_Flags, LAYER_FLAG);
+ msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
+ msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
+
+ msg->nextBlockFast(_PREHASH_RequestData);
+ msg->addU32Fast(_PREHASH_ItemType, type);
+ msg->addU64Fast(_PREHASH_RegionHandle, handle); // If zero, filled in on sim
+
+ gAgent.sendReliableMessage();
+}
+
+void LLWorldMapMessage::sendNamedRegionRequest(std::string region_name)
+{
+ //LL_INFOS("World Map") << "LLWorldMap::sendNamedRegionRequest()" << LL_ENDL;
+ LLMessageSystem* msg = gMessageSystem;
+
+ // Request for region data
+ msg->newMessageFast(_PREHASH_MapNameRequest);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addU32Fast(_PREHASH_Flags, LAYER_FLAG);
+ msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
+ msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
+ msg->nextBlockFast(_PREHASH_NameData);
+ msg->addStringFast(_PREHASH_Name, region_name);
+ gAgent.sendReliableMessage();
+}
+
+void LLWorldMapMessage::sendNamedRegionRequest(std::string region_name,
+ url_callback_t callback,
+ const std::string& callback_url,
+ bool teleport) // immediately teleport when result returned
+{
+ //LL_INFOS("World Map") << "LLWorldMap::sendNamedRegionRequest()" << LL_ENDL;
+ mSLURLRegionName = region_name;
+ mSLURLRegionHandle = 0;
+ mSLURL = callback_url;
+ mSLURLCallback = callback;
+ mSLURLTeleport = teleport;
+
+ sendNamedRegionRequest(region_name);
+}
+
+void LLWorldMapMessage::sendHandleRegionRequest(U64 region_handle,
+ url_callback_t callback,
+ const std::string& callback_url,
+ bool teleport) // immediately teleport when result returned
+{
+ //LL_INFOS("World Map") << "LLWorldMap::sendHandleRegionRequest()" << LL_ENDL;
+ mSLURLRegionName.clear();
+ mSLURLRegionHandle = region_handle;
+ mSLURL = callback_url;
+ mSLURLCallback = callback;
+ mSLURLTeleport = teleport;
+
+ U32 global_x;
+ U32 global_y;
+ from_region_handle(region_handle, &global_x, &global_y);
+ U16 grid_x = (U16)(global_x / REGION_WIDTH_UNITS);
+ U16 grid_y = (U16)(global_y / REGION_WIDTH_UNITS);
+
+ sendMapBlockRequest(grid_x, grid_y, grid_x, grid_y, true);
+}
+
+void LLWorldMapMessage::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent)
+{
+ //LL_INFOS("World Map") << "LLWorldMap::sendMapBlockRequest()" << ", min = (" << min_x << ", " << min_y << "), max = (" << max_x << ", " << max_y << "), nonexistent = " << return_nonexistent << LL_ENDL;
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_MapBlockRequest);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ U32 flags = LAYER_FLAG;
+ flags |= (return_nonexistent ? 0x10000 : 0);
+ msg->addU32Fast(_PREHASH_Flags, flags);
+ msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
+ msg->addBOOLFast(_PREHASH_Godlike, FALSE); // Filled in on sim
+ msg->nextBlockFast(_PREHASH_PositionData);
+ msg->addU16Fast(_PREHASH_MinX, min_x);
+ msg->addU16Fast(_PREHASH_MinY, min_y);
+ msg->addU16Fast(_PREHASH_MaxX, max_x);
+ msg->addU16Fast(_PREHASH_MaxY, max_y);
+ gAgent.sendReliableMessage();
+}
+
+// public static
+void LLWorldMapMessage::processMapBlockReply(LLMessageSystem* msg, void**)
+{
+ U32 agent_flags;
+ msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags);
+
+ // There's only one flag that we ever use here
+ if (agent_flags != LAYER_FLAG)
+ {
+ llwarns << "Invalid map image type returned! layer = " << agent_flags << llendl;
+ return;
+ }
+
+ S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_Data);
+ //LL_INFOS("World Map") << "LLWorldMap::processMapBlockReply(), num_blocks = " << num_blocks << LL_ENDL;
+
+ bool found_null_sim = false;
+
+ for (S32 block=0; block<num_blocks; ++block)
+ {
+ U16 x_regions;
+ U16 y_regions;
+ std::string name;
+ U8 accesscode;
+ U32 region_flags;
+// U8 water_height;
+// U8 agents;
+ LLUUID image_id;
+ msg->getU16Fast(_PREHASH_Data, _PREHASH_X, x_regions, block);
+ msg->getU16Fast(_PREHASH_Data, _PREHASH_Y, y_regions, block);
+ msg->getStringFast(_PREHASH_Data, _PREHASH_Name, name, block);
+ msg->getU8Fast(_PREHASH_Data, _PREHASH_Access, accesscode, block);
+ msg->getU32Fast(_PREHASH_Data, _PREHASH_RegionFlags, region_flags, block);
+// msg->getU8Fast(_PREHASH_Data, _PREHASH_WaterHeight, water_height, block);
+// msg->getU8Fast(_PREHASH_Data, _PREHASH_Agents, agents, block);
+ msg->getUUIDFast(_PREHASH_Data, _PREHASH_MapImageID, image_id, block);
+
+ U32 x_world = (U32)(x_regions) * REGION_WIDTH_UNITS;
+ U32 y_world = (U32)(y_regions) * REGION_WIDTH_UNITS;
+
+ // Insert that region in the world map, if failure, flag it as a "null_sim"
+ if (!(LLWorldMap::getInstance()->insertRegion(x_world, y_world, name, image_id, (U32)accesscode, region_flags)))
+ {
+ found_null_sim = true;
+ }
+
+ // If we hit a valid tracking location, do what needs to be done app level wise
+ if (LLWorldMap::getInstance()->isTrackingValidLocation())
+ {
+ LLVector3d pos_global = LLWorldMap::getInstance()->getTrackedPositionGlobal();
+ if (LLWorldMap::getInstance()->isTrackingDoubleClick())
+ {
+ // Teleport if the user double clicked
+ gAgent.teleportViaLocation(pos_global);
+ }
+ // Update the "real" tracker information
+ gFloaterWorldMap->trackLocation(pos_global);
+ }
+
+ // Handle the SLURL callback if any
+ if(LLWorldMapMessage::getInstance()->mSLURLCallback != NULL)
+ {
+ U64 handle = to_region_handle(x_world, y_world);
+ // Check if we reached the requested region
+ if ((LLStringUtil::compareInsensitive(LLWorldMapMessage::getInstance()->mSLURLRegionName, name)==0)
+ || (LLWorldMapMessage::getInstance()->mSLURLRegionHandle == handle))
+ {
+ url_callback_t callback = LLWorldMapMessage::getInstance()->mSLURLCallback;
+
+ LLWorldMapMessage::getInstance()->mSLURLCallback = NULL;
+ LLWorldMapMessage::getInstance()->mSLURLRegionName.clear();
+ LLWorldMapMessage::getInstance()->mSLURLRegionHandle = 0;
+
+ callback(handle, LLWorldMapMessage::getInstance()->mSLURL, image_id, LLWorldMapMessage::getInstance()->mSLURLTeleport);
+ }
+ }
+ }
+ // Tell the UI to update itself
+ gFloaterWorldMap->updateSims(found_null_sim);
+}
+
+// public static
+void LLWorldMapMessage::processMapItemReply(LLMessageSystem* msg, void**)
+{
+ //LL_INFOS("World Map") << "LLWorldMap::processMapItemReply()" << LL_ENDL;
+ U32 type;
+ msg->getU32Fast(_PREHASH_RequestData, _PREHASH_ItemType, type);
+
+ S32 num_blocks = msg->getNumberOfBlocks("Data");
+
+ for (S32 block=0; block<num_blocks; ++block)
+ {
+ U32 X, Y;
+ std::string name;
+ S32 extra, extra2;
+ LLUUID uuid;
+ msg->getU32Fast(_PREHASH_Data, _PREHASH_X, X, block);
+ msg->getU32Fast(_PREHASH_Data, _PREHASH_Y, Y, block);
+ msg->getStringFast(_PREHASH_Data, _PREHASH_Name, name, block);
+ msg->getUUIDFast(_PREHASH_Data, _PREHASH_ID, uuid, block);
+ msg->getS32Fast(_PREHASH_Data, _PREHASH_Extra, extra, block);
+ msg->getS32Fast(_PREHASH_Data, _PREHASH_Extra2, extra2, block);
+
+ LLWorldMap::getInstance()->insertItem(X, Y, name, uuid, type, extra, extra2);
+ }
+}
+
diff --git a/indra/newview/llworldmapmessage.h b/indra/newview/llworldmapmessage.h
new file mode 100644
index 0000000000..2c8fedcb10
--- /dev/null
+++ b/indra/newview/llworldmapmessage.h
@@ -0,0 +1,83 @@
+/**
+ * @file llworldmapmessage.h
+ * @brief Handling of the messages to the DB made by and for the world map.
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLWORLDMAPMESSAGE_H
+#define LL_LLWORLDMAPMESSAGE_H
+
+// Handling of messages (send and process) as well as SLURL callback if necessary
+class LLMessageSystem;
+
+class LLWorldMapMessage : public LLSingleton<LLWorldMapMessage>
+{
+public:
+ typedef boost::function<void(U64 region_handle, const std::string& url, const LLUUID& snapshot_id, bool teleport)>
+ url_callback_t;
+
+ LLWorldMapMessage();
+ ~LLWorldMapMessage();
+
+ // Process incoming answers to map stuff requests
+ static void processMapBlockReply(LLMessageSystem*, void**);
+ static void processMapItemReply(LLMessageSystem*, void**);
+
+ // Request data for all regions in a rectangular area. Coordinates in grids (i.e. meters / 256).
+ void sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent = false);
+
+ // Various methods to request LLSimInfo data to the simulator and asset DB
+ void sendNamedRegionRequest(std::string region_name);
+ void sendNamedRegionRequest(std::string region_name,
+ url_callback_t callback,
+ const std::string& callback_url,
+ bool teleport);
+ void sendHandleRegionRequest(U64 region_handle,
+ url_callback_t callback,
+ const std::string& callback_url,
+ bool teleport);
+
+ // Request item data for regions
+ // Note: the handle works *only* when requesting agent count (type = MAP_ITEM_AGENT_LOCATIONS). In that case,
+ // the request will actually be transitting through the spaceserver (all that is done on the sim).
+ // All other values of type do create a global grid request to the asset DB. So no need to try to get, say,
+ // the events for one particular region. For such a request, the handle is ignored.
+ void sendItemRequest(U32 type, U64 handle = 0);
+
+private:
+ // Search for region (by name or handle) for SLURL processing and teleport
+ // None of this relies explicitly on the LLWorldMap instance so better handle it here
+ std::string mSLURLRegionName;
+ U64 mSLURLRegionHandle;
+ std::string mSLURL;
+ url_callback_t mSLURLCallback;
+ bool mSLURLTeleport;
+};
+
+#endif // LL_LLWORLDMAPMESSAGE_H
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index 2e18b710a7..1940d65ae4 100644
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -39,42 +39,46 @@
#include "llmath.h" // clampf()
#include "llregionhandle.h"
#include "lleventflags.h"
+#include "llfloaterreg.h"
#include "llrender.h"
+#include "lltooltip.h"
#include "llagent.h"
#include "llcallingcard.h"
-#include "llcolorscheme.h"
#include "llviewercontrol.h"
-#include "llcylinder.h"
-#include "llfloaterdirectory.h"
#include "llfloatermap.h"
#include "llfloaterworldmap.h"
#include "llfocusmgr.h"
+#include "lllocalcliprect.h"
#include "lltextbox.h"
#include "lltextureview.h"
#include "lltracker.h"
#include "llviewercamera.h"
-#include "llviewerimage.h"
-#include "llviewerimagelist.h"
-#include "llviewermenu.h"
-#include "llviewerparceloverlay.h"
+#include "llviewertexture.h"
+#include "llviewertexturelist.h"
#include "llviewerregion.h"
#include "llviewerwindow.h"
-#include "llworldmap.h"
-#include "lltexturefetch.h"
-#include "llappviewer.h" // Only for constants!
#include "lltrans.h"
#include "llglheaders.h"
+// 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;
+const F32 OCEAN_BLUE = (F32)(0x5F)/255.f;
+
const F32 GODLY_TELEPORT_HEIGHT = 200.f;
const S32 SCROLL_HINT_WIDTH = 65;
const F32 BIG_DOT_RADIUS = 5.f;
BOOL LLWorldMapView::sHandledLastClick = FALSE;
-LLUIImagePtr LLWorldMapView::sAvatarYouSmallImage = NULL;
LLUIImagePtr LLWorldMapView::sAvatarSmallImage = NULL;
-LLUIImagePtr LLWorldMapView::sAvatarLargeImage = NULL;
+LLUIImagePtr LLWorldMapView::sAvatarYouImage = NULL;
+LLUIImagePtr LLWorldMapView::sAvatarYouLargeImage = NULL;
+LLUIImagePtr LLWorldMapView::sAvatarLevelImage = NULL;
LLUIImagePtr LLWorldMapView::sAvatarAboveImage = NULL;
LLUIImagePtr LLWorldMapView::sAvatarBelowImage = NULL;
@@ -92,35 +96,34 @@ LLUIImagePtr LLWorldMapView::sClassifiedsImage = NULL;
LLUIImagePtr LLWorldMapView::sForSaleImage = NULL;
LLUIImagePtr LLWorldMapView::sForSaleAdultImage = NULL;
-F32 LLWorldMapView::sThresholdA = 48.f;
-F32 LLWorldMapView::sThresholdB = 96.f;
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;
-F32 LLWorldMapView::sPixelsPerMeter = 1.f;
-F32 CONE_SIZE = 0.6f;
+bool LLWorldMapView::sVisibleTilesLoaded = false;
+F32 LLWorldMapView::sMapScale = 128.f;
std::map<std::string,std::string> LLWorldMapView::sStringsMap;
-#define SIM_NULL_MAP_SCALE 1 // width in pixels, where we start drawing "null" sims
-#define SIM_MAP_AGENT_SCALE 2 // width in pixels, where we start drawing agents
-#define SIM_MAP_SCALE 1 // width in pixels, where we start drawing sim tiles
-
-// Updates for agent locations.
-#define AGENTS_UPDATE_TIME 60.0 // in seconds
+// Fetch and draw info thresholds
+const F32 DRAW_TEXT_THRESHOLD = 96.f; // Don't draw text under that resolution value (res = width region in meters)
+const S32 DRAW_SIMINFO_THRESHOLD = 3; // Max level for which we load or display sim level information (level in LLWorldMipmap sense)
+const S32 DRAW_LANDFORSALE_THRESHOLD = 2; // Max level for which we load or display land for sale picture data (level in LLWorldMipmap sense)
+// When on, draw an outline for each mipmap tile gotten from S3
+#define DEBUG_DRAW_TILE 0
void LLWorldMapView::initClass()
{
- sAvatarYouSmallImage = LLUI::getUIImage("map_avatar_you_8.tga");
- sAvatarSmallImage = LLUI::getUIImage("map_avatar_8.tga");
- sAvatarLargeImage = LLUI::getUIImage("map_avatar_16.tga");
- sAvatarAboveImage = LLUI::getUIImage("map_avatar_above_8.tga");
- sAvatarBelowImage = LLUI::getUIImage("map_avatar_below_8.tga");
+ sAvatarSmallImage = LLUI::getUIImage("map_avatar_8.tga");
+ sAvatarYouImage = LLUI::getUIImage("map_avatar_16.tga");
+ sAvatarYouLargeImage = LLUI::getUIImage("map_avatar_you_32.tga");
+ sAvatarLevelImage = LLUI::getUIImage("map_avatar_32.tga");
+ sAvatarAboveImage = LLUI::getUIImage("map_avatar_above_32.tga");
+ sAvatarBelowImage = LLUI::getUIImage("map_avatar_below_32.tga");
sHomeImage = LLUI::getUIImage("map_home.tga");
sTelehubImage = LLUI::getUIImage("map_telehub.tga");
@@ -144,9 +147,10 @@ void LLWorldMapView::initClass()
// static
void LLWorldMapView::cleanupClass()
{
- sAvatarYouSmallImage = NULL;
sAvatarSmallImage = NULL;
- sAvatarLargeImage = NULL;
+ sAvatarYouImage = NULL;
+ sAvatarYouLargeImage = NULL;
+ sAvatarLevelImage = NULL;
sAvatarAboveImage = NULL;
sAvatarBelowImage = NULL;
@@ -164,9 +168,9 @@ void LLWorldMapView::cleanupClass()
sForSaleAdultImage = NULL;
}
-LLWorldMapView::LLWorldMapView(const std::string& name, const LLRect& rect )
-: LLPanel(name, rect, BORDER_NO),
- mBackgroundColor( LLColor4( 4.f/255.f, 4.f/255.f, 75.f/255.f, 1.f ) ),
+LLWorldMapView::LLWorldMapView()
+: LLPanel(),
+ mBackgroundColor( LLColor4( OCEAN_RED, OCEAN_GREEN, OCEAN_BLUE, 1.f ) ),
mItemPicked(FALSE),
mPanning( FALSE ),
mMouseDownPanX( 0 ),
@@ -175,54 +179,47 @@ LLWorldMapView::LLWorldMapView(const std::string& name, const LLRect& rect )
mMouseDownY( 0 ),
mSelectIDStart(0)
{
- sPixelsPerMeter = gMapScale / REGION_WIDTH_METERS;
- clearLastClick();
-
- const S32 DIR_WIDTH = 10;
- const S32 DIR_HEIGHT = 10;
- LLRect major_dir_rect( 0, DIR_HEIGHT, DIR_WIDTH, 0 );
- LLColor4 minor_color( 1.f, 1.f, 1.f, .7f );
-
- mTextBoxNorth = new LLTextBox( std::string("N"), major_dir_rect );
- mTextBoxNorth->setColor( minor_color );
- addChild( mTextBoxNorth );
-
- mTextBoxEast = new LLTextBox( std::string("E"), major_dir_rect );
- mTextBoxEast->setColor( minor_color );
- addChild( mTextBoxEast );
-
- major_dir_rect.mRight += 1 ;
- mTextBoxWest = new LLTextBox( std::string("W"), major_dir_rect );
- mTextBoxWest->setColor( minor_color );
- addChild( mTextBoxWest );
- major_dir_rect.mRight -= 1 ;
-
- mTextBoxSouth = new LLTextBox( std::string("S"), major_dir_rect );
- mTextBoxSouth->setColor( minor_color );
- addChild( mTextBoxSouth );
+ //LL_INFOS("World Map") << "Creating the Map -> LLWorldMapView::LLWorldMapView()" << LL_ENDL;
- LLRect minor_dir_rect( 0, DIR_HEIGHT, DIR_WIDTH * 2, 0 );
+ clearLastClick();
+}
- mTextBoxSouthEast = new LLTextBox( std::string("SE"), minor_dir_rect );
- mTextBoxSouthEast->setColor( minor_color );
- addChild( mTextBoxSouthEast );
+BOOL LLWorldMapView::postBuild()
+{
+ 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");
- mTextBoxNorthEast = new LLTextBox( std::string("NE"), minor_dir_rect );
- mTextBoxNorthEast->setColor( minor_color );
- addChild( mTextBoxNorthEast );
+ mTextBoxNorth->setText(getString("world_map_north"));
+ mTextBoxEast->setText(getString ("world_map_east"));
+ mTextBoxWest->setText(getString("world_map_west"));
+ mTextBoxSouth->setText(getString ("world_map_south"));
+ mTextBoxSouthEast ->setText(getString ("world_map_southeast"));
+ mTextBoxNorthEast ->setText(getString ("world_map_northeast"));
+ mTextBoxSouthWest->setText(getString ("world_map_southwest"));
+ mTextBoxNorthWest ->setText(getString("world_map_northwest"));
- mTextBoxSouthWest = new LLTextBox( std::string("SW"), minor_dir_rect );
- mTextBoxSouthWest->setColor( minor_color );
- addChild( mTextBoxSouthWest );
+ mTextBoxNorth->reshapeToFitText();
+ mTextBoxEast->reshapeToFitText();
+ mTextBoxWest->reshapeToFitText();
+ mTextBoxSouth->reshapeToFitText();
+ mTextBoxSouthEast ->reshapeToFitText();
+ mTextBoxNorthEast ->reshapeToFitText();
+ mTextBoxSouthWest->reshapeToFitText();
+ mTextBoxNorthWest ->reshapeToFitText();
- mTextBoxNorthWest = new LLTextBox( std::string("NW"), minor_dir_rect );
- mTextBoxNorthWest->setColor( minor_color );
- addChild( mTextBoxNorthWest );
+ return true;
}
LLWorldMapView::~LLWorldMapView()
{
+ //LL_INFOS("World Map") << "Destroying the map -> LLWorldMapView::~LLWorldMapView()" << LL_ENDL;
cleanupTextures();
}
@@ -236,14 +233,14 @@ void LLWorldMapView::cleanupTextures()
// static
void LLWorldMapView::setScale( F32 scale )
{
- if (scale != gMapScale)
+ if (scale != sMapScale)
{
- F32 old_scale = gMapScale;
+ F32 old_scale = sMapScale;
- gMapScale = scale;
- if (gMapScale == 0.f)
+ sMapScale = scale;
+ if (sMapScale <= 0.f)
{
- gMapScale = 0.1f;
+ sMapScale = 0.1f;
}
F32 ratio = (scale / old_scale);
@@ -251,8 +248,7 @@ void LLWorldMapView::setScale( F32 scale )
sPanY *= ratio;
sTargetPanX = sPanX;
sTargetPanY = sPanY;
-
- sPixelsPerMeter = gMapScale / REGION_WIDTH_METERS;
+ sVisibleTilesLoaded = false;
}
}
@@ -264,6 +260,7 @@ void LLWorldMapView::translatePan( S32 delta_x, S32 delta_y )
sPanY += delta_y;
sTargetPanX = sPanX;
sTargetPanY = sPanY;
+ sVisibleTilesLoaded = false;
}
@@ -277,28 +274,34 @@ void LLWorldMapView::setPan( S32 x, S32 y, BOOL snap )
sPanX = sTargetPanX;
sPanY = sTargetPanY;
}
+ sVisibleTilesLoaded = false;
}
+bool LLWorldMapView::showRegionInfo()
+{
+ return (LLWorldMipmap::scaleToLevel(sMapScale) <= DRAW_SIMINFO_THRESHOLD ? true : false);
+}
///////////////////////////////////////////////////////////////////////////////////
// HELPERS
BOOL is_agent_in_region(LLViewerRegion* region, LLSimInfo* info)
{
- return ((region && info) && (info->mName == region->getName()));
+ return (region && info && info->isName(region->getName()));
}
-
///////////////////////////////////////////////////////////////////////////////////
void LLWorldMapView::draw()
{
+ static LLUIColor map_track_color = LLUIColorTable::instance().getColor("MapTrackColor", LLColor4::white);
+
LLTextureView::clearDebugImages();
F64 current_time = LLTimer::getElapsedSeconds();
mVisibleRegions.clear();
-
+
// animate pan if necessary
sPanX = lerp(sPanX, sTargetPanX, LLCriticalDamp::getInterpolant(0.1f));
sPanY = lerp(sPanY, sTargetPanY, LLCriticalDamp::getInterpolant(0.1f));
@@ -309,10 +312,12 @@ void LLWorldMapView::draw()
const F32 half_height = F32(height) / 2.0f;
LLVector3d camera_global = gAgent.getCameraPositionGlobal();
+ S32 level = LLWorldMipmap::scaleToLevel(sMapScale);
+
LLLocalClipRect clip(getLocalRect());
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
+
glMatrixMode(GL_MODELVIEW);
// Clear the background alpha to 0
@@ -325,307 +330,58 @@ void LLWorldMapView::draw()
}
gGL.flush();
+
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
gGL.setColorMask(true, true);
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
-
- F32 layer_alpha = 1.f;
-
- // Draw one image per layer
- for (U32 layer_idx=0; layer_idx<LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap].size(); ++layer_idx)
- {
- if (!LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap][layer_idx].LayerDefined)
- {
- continue;
- }
- LLWorldMapLayer *layer = &LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap][layer_idx];
- LLViewerImage *current_image = layer->LayerImage;
-
- if (current_image->isMissingAsset())
- {
- continue; // better to draw nothing than the missing asset image
- }
-
- LLVector3d origin_global((F64)layer->LayerExtents.mLeft * REGION_WIDTH_METERS, (F64)layer->LayerExtents.mBottom * REGION_WIDTH_METERS, 0.f);
-
- // 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) * gMapScale;
- F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * gMapScale;
-
- F32 pix_width = gMapScale*(layer->LayerExtents.getWidth() + 1);
- F32 pix_height = gMapScale*(layer->LayerExtents.getHeight() + 1);
-
- // 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 + pix_height;
- F32 right = left + pix_width;
- F32 pixel_area = pix_width*pix_height;
- // discard layers that are outside the rectangle
- // and discard small layers
- if (top < 0.f ||
- bottom > height ||
- right < 0.f ||
- left > width ||
- (pixel_area < 4*4))
- {
- current_image->setBoostLevel(0);
- continue;
- }
-
- current_image->setBoostLevel(LLViewerImage::BOOST_MAP_LAYER);
- current_image->setKnownDrawSize(llround(pix_width * LLUI::sGLScaleFactor.mV[VX]), llround(pix_height * LLUI::sGLScaleFactor.mV[VY]));
-
- if (!current_image->getHasGLTexture())
- {
- continue; // better to draw nothing than the default image
- }
-
-// LLTextureView::addDebugImage(current_image);
-
- // Draw using the texture. If we don't clamp we get artifact at
- // the edge.
- gGL.getTexUnit(0)->bind(current_image);
-
- // Draw map image into RGB
- //gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- gGL.flush();
- gGL.setColorMask(true, false);
- gGL.color4f(1.f, 1.f, 1.f, layer_alpha);
-
- gGL.begin(LLRender::QUADS);
- gGL.texCoord2f(0.0f, 1.0f);
- gGL.vertex3f(left, top, -1.0f);
- gGL.texCoord2f(0.0f, 0.0f);
- gGL.vertex3f(left, bottom, -1.0f);
- gGL.texCoord2f(1.0f, 0.0f);
- gGL.vertex3f(right, bottom, -1.0f);
- gGL.texCoord2f(1.0f, 1.0f);
- gGL.vertex3f(right, top, -1.0f);
- gGL.end();
-
- // draw an alpha of 1 where the sims are visible
- gGL.flush();
- gGL.setColorMask(false, true);
- gGL.color4f(1.f, 1.f, 1.f, 1.f);
-
- gGL.begin(LLRender::QUADS);
- gGL.texCoord2f(0.0f, 1.0f);
- gGL.vertex2f(left, top);
- gGL.texCoord2f(0.0f, 0.0f);
- gGL.vertex2f(left, bottom);
- gGL.texCoord2f(1.0f, 0.0f);
- gGL.vertex2f(right, bottom);
- gGL.texCoord2f(1.0f, 1.0f);
- gGL.vertex2f(right, top);
- gGL.end();
- }
+ // Draw the image tiles
+ drawMipmap(width, height);
gGL.flush();
+
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
gGL.setColorMask(true, true);
- // there used to be an #if 1 here, but it was uncommented; perhaps marking a block of code?
- F32 sim_alpha = 1.f;
-
- // Draw one image per region, centered on the camera position.
- const S32 MAX_SIMULTANEOUS_TEX = 100;
- const S32 MAX_REQUEST_PER_TICK = 5;
- const S32 MIN_REQUEST_PER_TICK = 1;
- S32 textures_requested_this_tick = 0;
-
- for (LLWorldMap::sim_info_map_t::iterator it = LLWorldMap::getInstance()->mSimInfoMap.begin();
- it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it)
+ // Draw per sim overlayed information (names, mature, offline...)
+ for (LLWorldMap::sim_info_map_t::const_iterator it = LLWorldMap::getInstance()->getRegionMap().begin();
+ it != LLWorldMap::getInstance()->getRegionMap().end(); ++it)
{
- U64 handle = (*it).first;
- LLSimInfo* info = (*it).second;
+ U64 handle = it->first;
+ LLSimInfo* info = it->second;
- LLViewerImage* simimage = info->mCurrentImage;
- LLViewerImage* overlayimage = info->mOverlayImage;
-
- if (gMapScale < SIM_MAP_SCALE)
- {
- if (simimage != NULL) simimage->setBoostLevel(0);
- if (overlayimage != NULL) overlayimage->setBoostLevel(0);
- continue;
- }
-
LLVector3d origin_global = from_region_handle(handle);
- LLVector3d camera_global = gAgent.getCameraPositionGlobal();
// 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) * gMapScale;
- F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * gMapScale;
+ F32 relative_x = (rel_region_pos.mdV[0] / REGION_WIDTH_METERS) * sMapScale;
+ F32 relative_y = (rel_region_pos.mdV[1] / REGION_WIDTH_METERS) * sMapScale;
+ // 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 + gMapScale ;
- F32 right = left + gMapScale ;
-
- // Switch to world map texture (if available for this region) if either:
- // 1. Tiles are zoomed out small enough, or
- // 2. Sim's texture has not been loaded yet
- F32 map_scale_cutoff = SIM_MAP_SCALE;
- if ((info->mRegionFlags & REGION_FLAGS_NULL_LAYER) > 0)
- {
- map_scale_cutoff = SIM_NULL_MAP_SCALE;
- }
-
- info->mShowAgentLocations = (gMapScale >= SIM_MAP_AGENT_SCALE);
-
- bool sim_visible =
- (gMapScale >= map_scale_cutoff) &&
- (simimage != NULL) &&
- (simimage->getHasGLTexture());
-
- if (sim_visible)
+ F32 bottom = sPanY + half_height + relative_y;
+ F32 left = sPanX + half_width + relative_x;
+ F32 top = bottom + sMapScale ;
+ F32 right = left + sMapScale ;
+
+ // Discard if region is outside the screen rectangle (not visible on screen)
+ if ((top < 0.f) || (bottom > height) ||
+ (right < 0.f) || (left > width) )
{
- // Fade in
- if (info->mAlpha < 0.0f)
- info->mAlpha = 1.f; // don't fade initially
- else
- info->mAlpha = lerp(info->mAlpha, 1.f, LLCriticalDamp::getInterpolant(0.15f));
- }
- else
- {
- // Fade out
- if (info->mAlpha < 0.0f)
- info->mAlpha = 0.f; // don't fade initially
- else
- info->mAlpha = lerp(info->mAlpha, 0.f, LLCriticalDamp::getInterpolant(0.15f));
- }
-
- // discard regions that are outside the rectangle
- // and discard small regions
- if (top < 0.f ||
- bottom > height ||
- right < 0.f ||
- left > width )
- {
- if (simimage != NULL) simimage->setBoostLevel(0);
- if (overlayimage != NULL) overlayimage->setBoostLevel(0);
+ // Drop the "land for sale" fetching priority since it's outside the view rectangle
+ info->dropImagePriority();
continue;
}
- if (info->mCurrentImage.isNull())
- {
- if ((textures_requested_this_tick < MIN_REQUEST_PER_TICK) ||
- ((LLAppViewer::getTextureFetch()->getNumRequests() < MAX_SIMULTANEOUS_TEX) &&
- (textures_requested_this_tick < MAX_REQUEST_PER_TICK)))
- {
- textures_requested_this_tick++;
- info->mCurrentImage = gImageList.getImage(info->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE);
- info->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP);
- simimage = info->mCurrentImage;
- gGL.getTexUnit(0)->bind(simimage);
- }
- }
- if (info->mOverlayImage.isNull() && info->mMapImageID[2].notNull())
- {
- if ((textures_requested_this_tick < MIN_REQUEST_PER_TICK) ||
- ((LLAppViewer::getTextureFetch()->getNumRequests() < MAX_SIMULTANEOUS_TEX) &&
- (textures_requested_this_tick < MAX_REQUEST_PER_TICK)))
- {
- textures_requested_this_tick++;
- info->mOverlayImage = gImageList.getImage(info->mMapImageID[2], MIPMAP_TRUE, FALSE);
- info->mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP);
- overlayimage = info->mOverlayImage;
- gGL.getTexUnit(0)->bind(overlayimage);
- }
- }
+ // This list is used by other methods to know which regions are indeed displayed on screen
mVisibleRegions.push_back(handle);
- // See if the agents need updating
- if (current_time - info->mAgentsUpdateTime > AGENTS_UPDATE_TIME)
- {
- LLWorldMap::getInstance()->sendItemRequest(MAP_ITEM_AGENT_LOCATIONS, info->mHandle);
- info->mAgentsUpdateTime = current_time;
- }
-
- // Bias the priority escalation for images nearer
- LLVector3d center_global = origin_global;
- center_global.mdV[VX] += 128.0;
- center_global.mdV[VY] += 128.0;
- S32 draw_size = llround(gMapScale);
- if (simimage != NULL)
+ // Update the agent count for that region if we're not too zoomed out already
+ if (level <= DRAW_SIMINFO_THRESHOLD)
{
- simimage->setBoostLevel(LLViewerImage::BOOST_MAP);
- simimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY]));
+ info->updateAgentCount(current_time);
}
- if (overlayimage != NULL)
- {
- overlayimage->setBoostLevel(LLViewerImage::BOOST_MAP);
- overlayimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY]));
- }
-
-// LLTextureView::addDebugImage(simimage);
-
- if (sim_visible && info->mAlpha > 0.001f)
- {
- // Draw using the texture. If we don't clamp we get artifact at
- // the edge.
- LLGLSUIDefault gls_ui;
- if (simimage != NULL)
- gGL.getTexUnit(0)->bind(simimage);
-
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
- F32 alpha = sim_alpha * info->mAlpha;
- gGL.color4f(1.f, 1.0f, 1.0f, alpha);
-
- gGL.begin(LLRender::QUADS);
- gGL.texCoord2f(0.f, 1.f);
- gGL.vertex3f(left, top, 0.f);
- gGL.texCoord2f(0.f, 0.f);
- gGL.vertex3f(left, bottom, 0.f);
- gGL.texCoord2f(1.f, 0.f);
- gGL.vertex3f(right, bottom, 0.f);
- gGL.texCoord2f(1.f, 1.f);
- gGL.vertex3f(right, top, 0.f);
- gGL.end();
-
- if (gSavedSettings.getBOOL("MapShowLandForSale") && overlayimage && overlayimage->getHasGLTexture())
- {
- gGL.getTexUnit(0)->bind(overlayimage);
- gGL.color4f(1.f, 1.f, 1.f, alpha);
- gGL.begin(LLRender::QUADS);
- gGL.texCoord2f(0.f, 1.f);
- gGL.vertex3f(left, top, -0.5f);
- gGL.texCoord2f(0.f, 0.f);
- gGL.vertex3f(left, bottom, -0.5f);
- gGL.texCoord2f(1.f, 0.f);
- gGL.vertex3f(right, bottom, -0.5f);
- gGL.texCoord2f(1.f, 1.f);
- gGL.vertex3f(right, top, -0.5f);
- gGL.end();
- }
-
- if ((info->mRegionFlags & REGION_FLAGS_NULL_LAYER) == 0)
- {
- // draw an alpha of 1 where the sims are visible (except NULL sims)
- gGL.flush();
- gGL.setSceneBlendType(LLRender::BT_REPLACE);
- gGL.setColorMask(false, true);
- gGL.color4f(1.f, 1.f, 1.f, 1.f);
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.begin(LLRender::QUADS);
- gGL.vertex2f(left, top);
- gGL.vertex2f(left, bottom);
- gGL.vertex2f(right, bottom);
- gGL.vertex2f(right, top);
- gGL.end();
-
- gGL.flush();
- gGL.setColorMask(true, true);
- }
- }
-
- if (info->mAccess == SIM_ACCESS_DOWN)
+ if (info->isDown())
{
// Draw a transparent red square over down sims
gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_SOURCE_ALPHA);
@@ -639,18 +395,15 @@ void LLWorldMapView::draw()
gGL.vertex2f(right, top);
gGL.end();
}
-
- // As part of the AO project, we no longer want to draw access indicators;
- // it's too complicated to get all the rules straight and will only
+ // As part of the AO project, we no longer want to draw access indicators;
+ // it's too complicated to get all the rules straight and will only
// cause confusion.
/**********************
- // If this is mature, and you are not, draw a line across it
- if (info->mAccess != SIM_ACCESS_DOWN
- && info->mAccess > SIM_ACCESS_PG
- && gAgent.isTeen())
+ else if (!info->isPG() && gAgent.isTeen())
{
+ // If this is a mature region, and you are not, draw a line across it
gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO);
-
+
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.color3f(1.f, 0.f, 0.f);
gGL.begin(LLRender::LINES);
@@ -661,66 +414,66 @@ void LLWorldMapView::draw()
gGL.end();
}
**********************/
-
- // Draw the region name in the lower left corner
- LLFontGL* font = LLFontGL::getFontSansSerifSmall();
-
- std::string mesg;
- if (gMapScale < sThresholdA)
+ else if (gSavedSettings.getBOOL("MapShowLandForSale") && (level <= DRAW_LANDFORSALE_THRESHOLD))
{
+ // Draw the overlay image "Land for Sale / Land for Auction"
+ LLViewerFetchedTexture* overlayimage = info->getLandForSaleImage();
+ if (overlayimage)
+ {
+ // Inform the fetch mechanism of the size we need
+ S32 draw_size = llround(sMapScale);
+ overlayimage->setKnownDrawSize(llround(draw_size * LLUI::sGLScaleFactor.mV[VX]), llround(draw_size * LLUI::sGLScaleFactor.mV[VY]));
+ // Draw something whenever we have enough info
+ if (overlayimage->hasGLTexture())
+ {
+ gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO);
+ gGL.getTexUnit(0)->bind(overlayimage);
+ gGL.color4f(1.f, 1.f, 1.f, 1.f);
+ gGL.begin(LLRender::QUADS);
+ gGL.texCoord2f(0.f, 1.f);
+ gGL.vertex3f(left, top, -0.5f);
+ gGL.texCoord2f(0.f, 0.f);
+ gGL.vertex3f(left, bottom, -0.5f);
+ gGL.texCoord2f(1.f, 0.f);
+ gGL.vertex3f(right, bottom, -0.5f);
+ gGL.texCoord2f(1.f, 1.f);
+ gGL.vertex3f(right, top, -0.5f);
+ gGL.end();
+ }
+ }
}
- else if (gMapScale < sThresholdB)
+ else
{
- // mesg = llformat( info->mAgents);
+ // If we're not displaying the "land for sale", drop its fetching priority
+ info->dropImagePriority();
}
- else
+
+ // Draw the region name in the lower left corner
+ if (sMapScale >= DRAW_TEXT_THRESHOLD)
{
- //mesg = llformat("%d / %s (%s)",
- // info->mAgents,
- // info->mName.c_str(),
- // LLViewerRegion::accessToShortString(info->mAccess).c_str() );
- if (info->mAccess == SIM_ACCESS_DOWN)
+ LLFontGL* font = LLFontGL::getFont(LLFontDescriptor("SansSerif", "Small", LLFontGL::BOLD));
+ std::string mesg;
+ if (info->isDown())
{
- mesg = llformat( "%s (%s)", info->mName.c_str(), sStringsMap["offline"].c_str());
+ mesg = llformat( "%s (%s)", info->getName().c_str(), sStringsMap["offline"].c_str());
}
else
{
- mesg = info->mName;
+ mesg = info->getName();
}
- }
-
- if (!mesg.empty())
- {
- font->renderUTF8(
- mesg, 0,
- llfloor(left + 3),
- llfloor(bottom + 2),
- LLColor4::white,
- LLFontGL::LEFT,
- LLFontGL::BASELINE,
- LLFontGL::DROP_SHADOW);
-
- // If map texture is still loading,
- // display "Loading" placeholder text.
- if ((simimage != NULL) &&
- simimage->getDiscardLevel() != 1 &&
- simimage->getDiscardLevel() != 0)
+ if (!mesg.empty())
{
font->renderUTF8(
- sStringsMap["loading"], 0,
- llfloor(left + 18),
- llfloor(top - 25),
+ mesg, 0,
+ llfloor(left + 3), llfloor(bottom + 2),
LLColor4::white,
- LLFontGL::LEFT,
- LLFontGL::BASELINE,
- LLFontGL::DROP_SHADOW);
+ LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW);
}
}
}
- // #endif used to be here
- // there used to be an #if 1 here, but it was uncommented; perhaps marking a block of code?
+
// Draw background rectangle
LLGLSUIDefault gls_ui;
{
@@ -730,69 +483,49 @@ void LLWorldMapView::draw()
gGL.color4fv( mBackgroundColor.mV );
gl_rect_2d(0, height, width, 0);
}
-
+
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
- // Infohubs
- if (gSavedSettings.getBOOL("MapShowInfohubs")) //(gMapScale >= sThresholdB)
- {
- drawGenericItems(LLWorldMap::getInstance()->mInfohubs, sInfohubImage);
- }
-
- // Telehubs
- if (gSavedSettings.getBOOL("MapShowTelehubs")) //(gMapScale >= sThresholdB)
+ // Draw item infos if we're not zoomed out too much and there's something to draw
+ if ((level <= DRAW_SIMINFO_THRESHOLD) && (gSavedSettings.getBOOL("MapShowInfohubs") ||
+ gSavedSettings.getBOOL("MapShowTelehubs") ||
+ gSavedSettings.getBOOL("MapShowLandForSale") ||
+ gSavedSettings.getBOOL("MapShowEvents") ||
+ gSavedSettings.getBOOL("ShowMatureEvents") ||
+ gSavedSettings.getBOOL("ShowAdultEvents")))
{
- drawGenericItems(LLWorldMap::getInstance()->mTelehubs, sTelehubImage);
+ drawItems();
}
- // Home Sweet Home
+ // Draw the Home location (always)
LLVector3d home;
if (gAgent.getHomePosGlobal(&home))
{
drawImage(home, sHomeImage);
}
- if (gSavedSettings.getBOOL("MapShowLandForSale"))
- {
- drawGenericItems(LLWorldMap::getInstance()->mLandForSale, sForSaleImage);
- // for 1.23, we're showing normal land and adult land in the same UI; you don't
- // get a choice about which ones you want. If you're currently asking for adult
- // content and land you'll get the adult land.
- if (gAgent.canAccessAdult())
- {
- drawGenericItems(LLWorldMap::getInstance()->mLandForSaleAdult, sForSaleAdultImage);
- }
- }
-
- if (gSavedSettings.getBOOL("MapShowEvents") ||
- gSavedSettings.getBOOL("ShowMatureEvents") ||
- gSavedSettings.getBOOL("ShowAdultEvents") )
- {
- drawEvents();
- }
-
- // Now draw your avatar after all that other stuff.
+ // Draw the current agent after all that other stuff.
LLVector3d pos_global = gAgent.getPositionGlobal();
- drawImage(pos_global, sAvatarLargeImage);
+ drawImage(pos_global, sAvatarYouImage);
LLVector3 pos_map = globalPosToView(pos_global);
if (!pointInView(llround(pos_map.mV[VX]), llround(pos_map.mV[VY])))
{
- drawTracking(pos_global,
- lerp(LLColor4::yellow, LLColor4::orange, 0.4f),
- TRUE,
- "You are here",
- "",
- llround(LLFontGL::getFontSansSerifSmall()->getLineHeight())); // offset vertically by one line, to avoid overlap with target tracking
+ drawTracking(pos_global,
+ lerp(LLColor4::yellow, LLColor4::orange, 0.4f),
+ TRUE,
+ "You are here",
+ "",
+ llround(LLFontGL::getFontSansSerifSmall()->getLineHeight())); // offset vertically by one line, to avoid overlap with target tracking
}
- // Show your viewing angle
+ // Draw the current agent viewing angle
drawFrustum();
// Draw icons for the avatars in each region.
- // Drawn after your avatar so you can see nearby people.
- if (gSavedSettings.getBOOL("MapShowPeople"))
+ // Drawn this after the current agent avatar so one can see nearby people
+ if (gSavedSettings.getBOOL("MapShowPeople") && (level <= DRAW_SIMINFO_THRESHOLD))
{
drawAgents();
}
@@ -801,44 +534,46 @@ void LLWorldMapView::draw()
LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus();
if ( LLTracker::TRACKING_AVATAR == tracking_status )
{
- drawTracking( LLAvatarTracker::instance().getGlobalPos(), gTrackColor, TRUE, LLTracker::getLabel(), "" );
- }
- else if ( LLTracker::TRACKING_LANDMARK == tracking_status
- || LLTracker::TRACKING_LOCATION == tracking_status )
+ drawTracking( LLAvatarTracker::instance().getGlobalPos(), map_track_color, TRUE, LLTracker::getLabel(), "" );
+ }
+ else if ( LLTracker::TRACKING_LANDMARK == tracking_status
+ || LLTracker::TRACKING_LOCATION == tracking_status )
{
// While fetching landmarks, will have 0,0,0 location for a while,
// so don't draw. JC
LLVector3d pos_global = LLTracker::getTrackedPositionGlobal();
if (!pos_global.isExactlyZero())
{
- drawTracking( pos_global, gTrackColor, TRUE, LLTracker::getLabel(), LLTracker::getToolTip() );
+ drawTracking( pos_global, map_track_color, TRUE, LLTracker::getLabel(), LLTracker::getToolTip() );
}
}
- else if (LLWorldMap::getInstance()->mIsTrackingUnknownLocation)
+ else if (LLWorldMap::getInstance()->isTracking())
{
- if (LLWorldMap::getInstance()->mInvalidLocation)
+ if (LLWorldMap::getInstance()->isTrackingInvalidLocation())
{
- // We know this location to be invalid
+ // We know this location to be invalid, draw a blue circle
LLColor4 loading_color(0.0, 0.5, 1.0, 1.0);
- drawTracking( LLWorldMap::getInstance()->mUnknownLocation, loading_color, TRUE, "Invalid Location", "");
+ drawTracking( LLWorldMap::getInstance()->getTrackedPositionGlobal(), loading_color, TRUE, getString("InvalidLocation"), "");
}
else
{
+ // We don't know yet what that location is, draw a throbing blue circle
double value = fmod(current_time, 2);
- value = 0.5 + 0.5*cos(value * 3.14159f);
+ value = 0.5 + 0.5*cos(value * F_PI);
LLColor4 loading_color(0.0, F32(value/2), F32(value), 1.0);
- drawTracking( LLWorldMap::getInstance()->mUnknownLocation, loading_color, TRUE, "Loading...", "");
+ drawTracking( LLWorldMap::getInstance()->getTrackedPositionGlobal(), loading_color, TRUE, getString("Loading"), "");
}
}
- // #endif used to be here
-
+
+
// turn off the scissor
LLGLDisable no_scissor(GL_SCISSOR_TEST);
-
+
updateDirections();
LLView::draw();
+ // Get sim info for all sims in view
updateVisibleBlocks();
} // end draw()
@@ -849,36 +584,182 @@ void LLWorldMapView::setVisible(BOOL visible)
LLPanel::setVisible(visible);
if (!visible)
{
- for (S32 map = 0; map < MAP_SIM_IMAGE_TYPES; map++)
+ // Drop the download of tiles and images priority to nil if we hide the map
+ LLWorldMap::getInstance()->dropImagePriorities();
+ }
+}
+
+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);
+ // Set the tile boost level so that unused tiles get to 0
+ LLWorldMap::getInstance()->equalizeBoostLevels();
+
+ // Render whatever we already have loaded if we haven't the current level
+ // complete and use it as a background (scaled up or scaled down)
+ if (!sVisibleTilesLoaded)
+ {
+ // Note: the (load = false) parameter avoids missing tiles to be fetched (i.e. we render what we have, no more)
+ // Check all the lower res levels and render them in reverse order (worse to best)
+ // We need to traverse all the levels as the user can zoom in very fast
+ for (S32 l = LLWorldMipmap::MAP_LEVELS; l > level; l--)
{
- for (U32 layer_idx=0; layer_idx<LLWorldMap::getInstance()->mMapLayers[map].size(); ++layer_idx)
- {
- if (LLWorldMap::getInstance()->mMapLayers[map][layer_idx].LayerDefined)
- {
- LLWorldMapLayer *layer = &LLWorldMap::getInstance()->mMapLayers[map][layer_idx];
- layer->LayerImage->setBoostLevel(0);
- }
- }
+ drawMipmapLevel(width, height, l, false);
}
- for (LLWorldMap::sim_info_map_t::iterator it = LLWorldMap::getInstance()->mSimInfoMap.begin();
- it != LLWorldMap::getInstance()->mSimInfoMap.end(); ++it)
+ // Skip the current level, as we'll do it anyway here under...
+
+ // Just go one level down in res as it can really get too much stuff
+ // when zooming out and too small to see anyway...
+ if (level > 1)
+ {
+ drawMipmapLevel(width, height, level - 1, false);
+ }
+ }
+ else
+ {
+ //LL_INFOS("World Map") << "Render complete, don't draw background..." << LL_ENDL;
+ }
+
+ // Render the current level
+ sVisibleTilesLoaded = drawMipmapLevel(width, height, level);
+
+ return;
+}
+
+// Return true if all the tiles required to render that level have been fetched or are truly missing
+bool LLWorldMapView::drawMipmapLevel(S32 width, S32 height, S32 level, bool load)
+{
+ // Check input level
+ llassert (level > 0);
+ if (level <= 0)
+ return false;
+
+ // Count tiles hit and completed
+ S32 completed_tiles = 0;
+ S32 total_tiles = 0;
+
+ // Size in meters (global) of each tile of that level
+ S32 tile_width = LLWorldMipmap::MAP_TILE_SIZE * (1 << (level - 1));
+ // Dimension of the screen in meter at that scale
+ LLVector3d pos_SW = viewPosToGlobal(0, 0);
+ LLVector3d pos_NE = viewPosToGlobal(width, height);
+ // Add external band of tiles on the outskirt so to hit the partially displayed tiles right and top
+ pos_NE[VX] += tile_width;
+ pos_NE[VY] += tile_width;
+
+ // Iterate through the tiles on screen: we just need to ask for one tile every tile_width meters
+ U32 grid_x, grid_y;
+ for (F64 index_y = pos_SW[VY]; index_y < pos_NE[VY]; index_y += tile_width)
+ {
+ for (F64 index_x = pos_SW[VX]; index_x < pos_NE[VX]; index_x += tile_width)
{
- LLSimInfo* info = (*it).second;
- if (info->mCurrentImage.notNull())
+ // Compute the world coordinates of the current point
+ LLVector3d pos_global(index_x, index_y, pos_SW[VZ]);
+ // Convert to the mipmap level coordinates for that point (i.e. which tile to we hit)
+ LLWorldMipmap::globalToMipmap(pos_global[VX], pos_global[VY], level, &grid_x, &grid_y);
+ // Get the tile. Note: NULL means that the image does not exist (so it's considered "complete" as far as fetching is concerned)
+ LLPointer<LLViewerFetchedTexture> simimage = LLWorldMap::getInstance()->getObjectsTile(grid_x, grid_y, level, load);
+ if (simimage)
{
- info->mCurrentImage->setBoostLevel(0);
+ // Checks that the image has a valid texture
+ if (simimage->hasGLTexture())
+ {
+ // Increment the number of completly fetched tiles
+ completed_tiles++;
+
+ // Convert those coordinates (SW corner of the mipmap tile) into world (meters) coordinates
+ pos_global[VX] = grid_x * REGION_WIDTH_METERS;
+ pos_global[VY] = grid_y * REGION_WIDTH_METERS;
+ // Now to screen coordinates for SW corner of that tile
+ LLVector3 pos_screen = globalPosToView (pos_global);
+ F32 left = pos_screen[VX];
+ F32 bottom = pos_screen[VY];
+ // Compute the NE corner coordinates of the tile now
+ pos_global[VX] += tile_width;
+ pos_global[VY] += tile_width;
+ pos_screen = globalPosToView (pos_global);
+ F32 right = pos_screen[VX];
+ F32 top = pos_screen[VY];
+
+ // Draw the tile
+ LLGLSUIDefault gls_ui;
+ gGL.getTexUnit(0)->bind(simimage.get());
+ simimage->setAddressMode(LLTexUnit::TAM_CLAMP);
+
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ gGL.color4f(1.f, 1.0f, 1.0f, 1.0f);
+
+ gGL.begin(LLRender::QUADS);
+ gGL.texCoord2f(0.f, 1.f);
+ gGL.vertex3f(left, top, 0.f);
+ gGL.texCoord2f(0.f, 0.f);
+ gGL.vertex3f(left, bottom, 0.f);
+ gGL.texCoord2f(1.f, 0.f);
+ gGL.vertex3f(right, bottom, 0.f);
+ gGL.texCoord2f(1.f, 1.f);
+ gGL.vertex3f(right, top, 0.f);
+ gGL.end();
+#if DEBUG_DRAW_TILE
+ drawTileOutline(level, top, left, bottom, right);
+#endif // DEBUG_DRAW_TILE
+ }
+ //else
+ //{
+ // Waiting for a tile -> the level is not complete
+ // LL_INFOS("World Map") << "Unfetched tile. level = " << level << LL_ENDL;
+ //}
}
- if (info->mOverlayImage.notNull())
+ else
{
- info->mOverlayImage->setBoostLevel(0);
+ // Unexistent tiles are counted as "completed"
+ completed_tiles++;
}
+ // Increment the number of tiles in that level / screen
+ total_tiles++;
}
}
+ return (completed_tiles == total_tiles);
+}
+
+// Draw lines (rectangle outline and cross) to visualize the position of the tile
+// Used for debug only
+void LLWorldMapView::drawTileOutline(S32 level, F32 top, F32 left, F32 bottom, F32 right)
+{
+ gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO);
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ if (level == 1)
+ gGL.color3f(1.f, 0.f, 0.f); // red
+ else if (level == 2)
+ gGL.color3f(0.f, 1.f, 0.f); // green
+ else if (level == 3)
+ gGL.color3f(0.f, 0.f, 1.f); // blue
+ else if (level == 4)
+ gGL.color3f(1.f, 1.f, 0.f); // yellow
+ else if (level == 5)
+ gGL.color3f(1.f, 0.f, 1.f); // magenta
+ else if (level == 6)
+ gGL.color3f(0.f, 1.f, 1.f); // cyan
+ else if (level == 7)
+ gGL.color3f(1.f, 1.f, 1.f); // white
+ else
+ gGL.color3f(0.f, 0.f, 0.f); // black
+ gGL.begin(LLRender::LINE_STRIP);
+ gGL.vertex2f(left, top);
+ gGL.vertex2f(right, bottom);
+ gGL.vertex2f(left, bottom);
+ gGL.vertex2f(right, top);
+ gGL.vertex2f(left, top);
+ gGL.vertex2f(left, bottom);
+ gGL.vertex2f(right, bottom);
+ gGL.vertex2f(right, top);
+ gGL.end();
}
-void LLWorldMapView::drawGenericItems(const LLWorldMap::item_info_list_t& items, LLUIImagePtr image)
+void LLWorldMapView::drawGenericItems(const LLSimInfo::item_info_list_t& items, LLUIImagePtr image)
{
- LLWorldMap::item_info_list_t::const_iterator e;
+ LLSimInfo::item_info_list_t::const_iterator e;
for (e = items.begin(); e != items.end(); ++e)
{
drawGenericItem(*e, image);
@@ -887,7 +768,7 @@ void LLWorldMapView::drawGenericItems(const LLWorldMap::item_info_list_t& items,
void LLWorldMapView::drawGenericItem(const LLItemInfo& item, LLUIImagePtr image)
{
- drawImage(item.mPosGlobal, image);
+ drawImage(item.getGlobalPosition(), image);
}
@@ -910,137 +791,91 @@ void LLWorldMapView::drawImageStack(const LLVector3d& global_pos, LLUIImagePtr i
}
}
-
-void LLWorldMapView::drawAgents()
+void LLWorldMapView::drawItems()
{
- F32 agents_scale = (gMapScale * 0.9f) / 256.f;
-
- LLColor4 avatar_color = gColors.getColor( "MapAvatar" );
- // LLColor4 friend_color = gColors.getColor( "MapFriend" );
+ bool mature_enabled = gAgent.canAccessMature();
+ bool adult_enabled = gAgent.canAccessAdult();
+
+ BOOL show_mature = mature_enabled && gSavedSettings.getBOOL("ShowMatureEvents");
+ BOOL show_adult = adult_enabled && gSavedSettings.getBOOL("ShowAdultEvents");
for (handle_list_t::iterator iter = mVisibleRegions.begin(); iter != mVisibleRegions.end(); ++iter)
{
U64 handle = *iter;
- LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle);
- if (siminfo && (siminfo->mAccess == SIM_ACCESS_DOWN))
+ LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle);
+ if ((info == NULL) || (info->isDown()))
{
continue;
}
- LLWorldMap::agent_list_map_t::iterator counts_iter = LLWorldMap::getInstance()->mAgentLocationsMap.find(handle);
- if (siminfo && siminfo->mShowAgentLocations && counts_iter != LLWorldMap::getInstance()->mAgentLocationsMap.end())
+ // Infohubs
+ if (gSavedSettings.getBOOL("MapShowInfohubs"))
{
- // Show Individual agents (or little stacks where real agents are)
- LLWorldMap::item_info_list_t& agentcounts = counts_iter->second;
- S32 sim_agent_count = 0;
- for (LLWorldMap::item_info_list_t::iterator iter = agentcounts.begin();
- iter != agentcounts.end(); ++iter)
- {
- const LLItemInfo& info = *iter;
- S32 agent_count = info.mExtra;
- sim_agent_count += info.mExtra;
- // Here's how we'd choose the color if info.mID were available but it's not being sent:
- //LLColor4 color = (agent_count == 1 && is_agent_friend(info.mID)) ? friend_color : avatar_color;
- drawImageStack(info.mPosGlobal, sAvatarSmallImage, agent_count, 3.f, avatar_color);
- }
- LLWorldMap::getInstance()->mNumAgents[handle] = sim_agent_count; // override mNumAgents for this sim
+ drawGenericItems(info->getInfoHub(), sInfohubImage);
}
- else
+ // Telehubs
+ if (gSavedSettings.getBOOL("MapShowTelehubs"))
+ {
+ drawGenericItems(info->getTeleHub(), sTelehubImage);
+ }
+ // Land for sale
+ if (gSavedSettings.getBOOL("MapShowLandForSale"))
{
- // Show agent 'stack' at center of sim
- S32 num_agents = LLWorldMap::getInstance()->mNumAgents[handle];
- if (num_agents > 0)
+ drawGenericItems(info->getLandForSale(), sForSaleImage);
+ // for 1.23, we're showing normal land and adult land in the same UI; you don't
+ // get a choice about which ones you want. If you're currently asking for adult
+ // content and land you'll get the adult land.
+ if (gAgent.canAccessAdult())
{
- LLVector3d region_center = from_region_handle(handle);
- region_center[VX] += REGION_WIDTH_METERS / 2;
- region_center[VY] += REGION_WIDTH_METERS / 2;
- // Reduce the stack size as you zoom out - always display at lease one agent where there is one or more
- S32 agent_count = (S32)(((num_agents-1) * agents_scale + (num_agents-1) * 0.1f)+.1f) + 1;
- drawImageStack(region_center, sAvatarSmallImage, agent_count, 3.f, avatar_color);
+ drawGenericItems(info->getLandForSaleAdult(), sForSaleAdultImage);
}
}
+ // PG Events
+ if (gSavedSettings.getBOOL("MapShowEvents"))
+ {
+ drawGenericItems(info->getPGEvent(), sEventImage);
+ }
+ // Mature Events
+ if (show_mature)
+ {
+ drawGenericItems(info->getMatureEvent(), sEventMatureImage);
+ }
+ // Adult Events
+ if (show_adult)
+ {
+ drawGenericItems(info->getAdultEvent(), sEventAdultImage);
+ }
}
}
-
-void LLWorldMapView::drawEvents()
+void LLWorldMapView::drawAgents()
{
- bool mature_enabled = gAgent.canAccessMature();
- bool adult_enabled = gAgent.canAccessAdult();
+ static LLUIColor map_avatar_color = LLUIColorTable::instance().getColor("MapAvatarColor", LLColor4::white);
- BOOL show_pg = gSavedSettings.getBOOL("MapShowEvents");
- BOOL show_mature = mature_enabled && gSavedSettings.getBOOL("ShowMatureEvents");
- BOOL show_adult = adult_enabled && gSavedSettings.getBOOL("ShowAdultEvents");
-
- // First the non-selected events
- LLWorldMap::item_info_list_t::const_iterator e;
- if (show_pg)
+ for (handle_list_t::iterator iter = mVisibleRegions.begin(); iter != mVisibleRegions.end(); ++iter)
{
- for (e = LLWorldMap::getInstance()->mPGEvents.begin(); e != LLWorldMap::getInstance()->mPGEvents.end(); ++e)
+ U64 handle = *iter;
+ LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle);
+ if ((siminfo == NULL) || (siminfo->isDown()))
{
- if (!e->mSelected)
- {
- drawGenericItem(*e, sEventImage);
- }
+ continue;
}
- }
- if (show_mature)
- {
- for (e = LLWorldMap::getInstance()->mMatureEvents.begin(); e != LLWorldMap::getInstance()->mMatureEvents.end(); ++e)
- {
- if (!e->mSelected)
- {
- drawGenericItem(*e, sEventMatureImage);
- }
- }
- }
- if (show_adult)
- {
- for (e = LLWorldMap::getInstance()->mAdultEvents.begin(); e != LLWorldMap::getInstance()->mAdultEvents.end(); ++e)
- {
- if (!e->mSelected)
- {
- drawGenericItem(*e, sEventAdultImage);
- }
- }
- }
- // Then the selected events
- if (show_pg)
- {
- for (e = LLWorldMap::getInstance()->mPGEvents.begin(); e != LLWorldMap::getInstance()->mPGEvents.end(); ++e)
+ LLSimInfo::item_info_list_t::const_iterator it = siminfo->getAgentLocation().begin();
+ while (it != siminfo->getAgentLocation().end())
{
- if (e->mSelected)
- {
- drawGenericItem(*e, sEventImage);
- }
+ // Show Individual agents (or little stacks where real agents are)
+
+ // Here's how we'd choose the color if info.mID were available but it's not being sent:
+ // LLColor4 color = (agent_count == 1 && is_agent_friend(info.mID)) ? friend_color : avatar_color;
+ drawImageStack(it->getGlobalPosition(), sAvatarSmallImage, it->getCount(), 3.f, map_avatar_color);
+ ++it;
}
}
- if (show_mature)
- {
- for (e = LLWorldMap::getInstance()->mMatureEvents.begin(); e != LLWorldMap::getInstance()->mMatureEvents.end(); ++e)
- {
- if (e->mSelected)
- {
- drawGenericItem(*e, sEventMatureImage);
- }
- }
- }
- if (show_adult)
- {
- for (e = LLWorldMap::getInstance()->mAdultEvents.begin(); e != LLWorldMap::getInstance()->mAdultEvents.end(); ++e)
- {
- if (e->mSelected)
- {
- drawGenericItem(*e, sEventAdultImage);
- }
- }
- }
}
-
void LLWorldMapView::drawFrustum()
{
// Draw frustum
- F32 meters_to_pixels = gMapScale/ REGION_WIDTH_METERS;
+ F32 meters_to_pixels = sMapScale/ REGION_WIDTH_METERS;
F32 horiz_fov = LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect();
F32 far_clip_meters = LLViewerCamera::getInstance()->getFar();
@@ -1081,8 +916,8 @@ 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] *= sPixelsPerMeter;
- pos_local.mV[VY] *= sPixelsPerMeter;
+ pos_local.mV[VX] *= sMapScale / REGION_WIDTH_METERS;
+ pos_local.mV[VY] *= sMapScale / REGION_WIDTH_METERS;
// leave Z component in meters
@@ -1142,7 +977,7 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4&
text_x,
text_y,
LLColor4::white, LLFontGL::HCENTER,
- LLFontGL::BASELINE, LLFontGL::DROP_SHADOW);
+ LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW);
if (tooltip != "")
{
@@ -1153,7 +988,7 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4&
text_x,
text_y,
LLColor4::white, LLFontGL::HCENTER,
- LLFontGL::BASELINE, LLFontGL::DROP_SHADOW);
+ LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW);
}
}
}
@@ -1166,7 +1001,7 @@ LLVector3d LLWorldMapView::viewPosToGlobal( S32 x, S32 y )
LLVector3 pos_local( (F32)x, (F32)y, 0.f );
- pos_local *= ( REGION_WIDTH_METERS / gMapScale );
+ pos_local *= ( REGION_WIDTH_METERS / sMapScale );
LLVector3d pos_global;
pos_global.setVec( pos_local );
@@ -1184,24 +1019,23 @@ LLVector3d LLWorldMapView::viewPosToGlobal( S32 x, S32 y )
}
-BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen )
+BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, MASK mask )
{
LLVector3d pos_global = viewPosToGlobal(x, y);
+ U64 handle = to_region_handle(pos_global);
+ std::string tooltip_msg;
- LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global);
+ LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle);
if (info)
{
LLViewerRegion *region = gAgent.getRegion();
- std::string message =
- llformat("%s (%s)",
- info->mName.c_str(),
- LLViewerRegion::accessToString(info->mAccess).c_str());
+ std::string message = llformat("%s (%s)", info->getName().c_str(), info->getAccessString().c_str());
- if (info->mAccess != SIM_ACCESS_DOWN)
+ if (!info->isDown())
{
- S32 agent_count = LLWorldMap::getInstance()->mNumAgents[info->mHandle];
- if (region && region->getHandle() == info->mHandle)
+ S32 agent_count = info->getAgentCount();
+ if (region && (region->getHandle() == handle))
{
++agent_count; // Bump by 1 if we're here
}
@@ -1210,6 +1044,8 @@ BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* stic
// zoomed out, so don't display anything about the count. JC
if (agent_count > 0)
{
+ // Merov: i18n horror!!! Even using gettext(), concatenating strings is not localizable.
+ // The singular/plural switch form here under might make no sense in some languages. Don't do that.
message += llformat("\n%d ", agent_count);
if (agent_count == 1)
@@ -1222,23 +1058,27 @@ BOOL LLWorldMapView::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* stic
}
}
}
- msg.assign( message );
+ tooltip_msg.assign( message );
// Optionally show region flags
- std::string region_flags = LLViewerRegion::regionFlagsToString(info->mRegionFlags);
+ std::string region_flags = info->getFlagsString();
if (!region_flags.empty())
{
- msg += '\n';
- msg += region_flags;
+ tooltip_msg += '\n';
+ tooltip_msg += region_flags;
}
- S32 SLOP = 4;
- localPointToScreen(
- x - SLOP, y - SLOP,
- &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
- sticky_rect_screen->mRight = sticky_rect_screen->mLeft + 2 * SLOP;
- sticky_rect_screen->mTop = sticky_rect_screen->mBottom + 2 * SLOP;
+ const S32 SLOP = 9;
+ S32 screen_x, screen_y;
+
+ localPointToScreen(x, y, &screen_x, &screen_y);
+ LLRect sticky_rect_screen;
+ sticky_rect_screen.setCenterAndSize(screen_x, screen_y, SLOP, SLOP);
+
+ LLToolTipMgr::instance().show(LLToolTip::Params()
+ .message(tooltip_msg)
+ .sticky_rect(sticky_rect_screen));
}
return TRUE;
}
@@ -1261,6 +1101,9 @@ static void drawDot(F32 x_pixels, F32 y_pixels,
}
else
{
+ // Draw V indicator for above or below
+ // *TODO: Replace this vector drawing with icons
+
F32 left = x_pixels - dot_radius;
F32 right = x_pixels + dot_radius;
F32 center = (left + right) * 0.5f;
@@ -1269,13 +1112,14 @@ static void drawDot(F32 x_pixels, F32 y_pixels,
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.color4fv( color.mV );
- LLUI::setLineWidth(1.5f);
- F32 h_bar = relative_z > HEIGHT_THRESHOLD ? top : bottom; // horizontal bar Y
+ LLUI::setLineWidth(3.0f);
+ F32 point = relative_z > HEIGHT_THRESHOLD ? top : bottom; // Y pos of the point of the V
+ F32 back = relative_z > HEIGHT_THRESHOLD ? bottom : top; // Y pos of the ends of the V
gGL.begin( LLRender::LINES );
- gGL.vertex2f(center, top);
- gGL.vertex2f(left, h_bar);
- gGL.vertex2f(right, h_bar);
- gGL.vertex2f(right, bottom);
+ gGL.vertex2f(left, back);
+ gGL.vertex2f(center, point);
+ gGL.vertex2f(center, point);
+ gGL.vertex2f(right, back);
gGL.end();
LLUI::setLineWidth(1.0f);
}
@@ -1290,7 +1134,7 @@ void LLWorldMapView::drawAvatar(F32 x_pixels,
F32 dot_radius)
{
const F32 HEIGHT_THRESHOLD = 7.f;
- LLUIImagePtr dot_image = sAvatarSmallImage;
+ LLUIImagePtr dot_image = sAvatarLevelImage;
if(relative_z < -HEIGHT_THRESHOLD)
{
dot_image = sAvatarBelowImage;
@@ -1299,10 +1143,12 @@ void LLWorldMapView::drawAvatar(F32 x_pixels,
{
dot_image = sAvatarAboveImage;
}
- dot_image->draw(
- llround(x_pixels) - dot_image->getWidth()/2,
- llround(y_pixels) - dot_image->getHeight()/2,
- color);
+ S32 dot_width = llround(dot_radius * 2.f);
+ dot_image->draw(llround(x_pixels - dot_radius),
+ llround(y_pixels - dot_radius),
+ dot_width,
+ dot_width,
+ color);
}
// Pass relative Z of 0 to draw at same level.
@@ -1338,6 +1184,7 @@ void LLWorldMapView::drawIconName(F32 x_pixels,
color,
LLFontGL::HCENTER,
LLFontGL::TOP,
+ LLFontGL::NORMAL,
LLFontGL::DROP_SHADOW);
text_y -= llround(LLFontGL::getFontSansSerif()->getLineHeight());
@@ -1349,6 +1196,7 @@ void LLWorldMapView::drawIconName(F32 x_pixels,
color,
LLFontGL::HCENTER,
LLFontGL::TOP,
+ LLFontGL::NORMAL,
LLFontGL::DROP_SHADOW);
}
@@ -1561,7 +1409,7 @@ void LLWorldMapView::reshape( S32 width, S32 height, BOOL called_from_parent )
bool LLWorldMapView::checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bool track)
{
- LLVector3 pos_view = globalPosToView(item.mPosGlobal);
+ LLVector3 pos_view = globalPosToView(item.getGlobalPosition());
S32 item_x = llround(pos_view.mV[VX]);
S32 item_y = llround(pos_view.mV[VY]);
@@ -1570,12 +1418,12 @@ bool LLWorldMapView::checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bo
if (y < item_y - BIG_DOT_RADIUS) return false;
if (y > item_y + BIG_DOT_RADIUS) return false;
- LLSimInfo* sim_info = LLWorldMap::getInstance()->simInfoFromHandle(item.mRegionHandle);
+ LLSimInfo* sim_info = LLWorldMap::getInstance()->simInfoFromHandle(item.getRegionHandle());
if (sim_info)
{
if (track)
{
- gFloaterWorldMap->trackLocation(item.mPosGlobal);
+ gFloaterWorldMap->trackLocation(item.getGlobalPosition());
}
}
@@ -1584,8 +1432,8 @@ bool LLWorldMapView::checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bo
gFloaterWorldMap->trackGenericItem(item);
}
- item.mSelected = TRUE;
- *id = item.mID;
+// item.setSelected(true);
+ *id = item.getUUID();
return true;
}
@@ -1608,108 +1456,116 @@ void LLWorldMapView::handleClick(S32 x, S32 y, MASK mask,
*hit_type = 0; // hit nothing
- LLWorldMap::getInstance()->mIsTrackingUnknownLocation = FALSE;
- LLWorldMap::getInstance()->mIsTrackingDoubleClick = FALSE;
- LLWorldMap::getInstance()->mIsTrackingCommit = FALSE;
-
- LLWorldMap::item_info_list_t::iterator it;
+ LLWorldMap::getInstance()->cancelTracking();
- // clear old selected stuff
- for (it = LLWorldMap::getInstance()->mPGEvents.begin(); it != LLWorldMap::getInstance()->mPGEvents.end(); ++it)
+ S32 level = LLWorldMipmap::scaleToLevel(sMapScale);
+ // If the zoom level is not too far out already, test hits
+ if (level <= DRAW_SIMINFO_THRESHOLD)
{
- (*it).mSelected = FALSE;
- }
- for (it = LLWorldMap::getInstance()->mMatureEvents.begin(); it != LLWorldMap::getInstance()->mMatureEvents.end(); ++it)
- {
- (*it).mSelected = FALSE;
- }
- for (it = LLWorldMap::getInstance()->mAdultEvents.begin(); it != LLWorldMap::getInstance()->mAdultEvents.end(); ++it)
- {
- (*it).mSelected = FALSE;
- }
- for (it = LLWorldMap::getInstance()->mLandForSale.begin(); it != LLWorldMap::getInstance()->mLandForSale.end(); ++it)
- {
- (*it).mSelected = FALSE;
- }
+ bool show_mature = gAgent.canAccessMature() && gSavedSettings.getBOOL("ShowMatureEvents");
+ bool show_adult = gAgent.canAccessAdult() && gSavedSettings.getBOOL("ShowAdultEvents");
- // Select event you clicked on
- if (gSavedSettings.getBOOL("MapShowEvents"))
- {
- for (it = LLWorldMap::getInstance()->mPGEvents.begin(); it != LLWorldMap::getInstance()->mPGEvents.end(); ++it)
+ // Test hits if trackable data are displayed, otherwise, we don't even bother
+ if (gSavedSettings.getBOOL("MapShowEvents") || show_mature || show_adult || gSavedSettings.getBOOL("MapShowLandForSale"))
{
- LLItemInfo& event = *it;
-
- if (checkItemHit(x, y, event, id, false))
- {
- *hit_type = MAP_ITEM_PG_EVENT;
- mItemPicked = TRUE;
- gFloaterWorldMap->trackEvent(event);
- return;
- }
- }
- }
- if (gSavedSettings.getBOOL("ShowMatureEvents"))
- {
- for (it = LLWorldMap::getInstance()->mMatureEvents.begin(); it != LLWorldMap::getInstance()->mMatureEvents.end(); ++it)
- {
- LLItemInfo& event = *it;
-
- if (checkItemHit(x, y, event, id, false))
- {
- *hit_type = MAP_ITEM_MATURE_EVENT;
- mItemPicked = TRUE;
- gFloaterWorldMap->trackEvent(event);
- return;
- }
- }
- }
- if (gSavedSettings.getBOOL("ShowAdultEvents"))
- {
- for (it = LLWorldMap::getInstance()->mAdultEvents.begin(); it != LLWorldMap::getInstance()->mAdultEvents.end(); ++it)
- {
- LLItemInfo& event = *it;
-
- if (checkItemHit(x, y, event, id, false))
- {
- *hit_type = MAP_ITEM_ADULT_EVENT;
- mItemPicked = TRUE;
- gFloaterWorldMap->trackEvent(event);
- return;
- }
- }
- }
-
- if (gSavedSettings.getBOOL("MapShowLandForSale"))
- {
- for (it = LLWorldMap::getInstance()->mLandForSale.begin(); it != LLWorldMap::getInstance()->mLandForSale.end(); ++it)
- {
- LLItemInfo& land = *it;
-
- if (checkItemHit(x, y, land, id, true))
- {
- *hit_type = MAP_ITEM_LAND_FOR_SALE;
- mItemPicked = TRUE;
- return;
- }
- }
-
- for (it = LLWorldMap::getInstance()->mLandForSaleAdult.begin(); it != LLWorldMap::getInstance()->mLandForSaleAdult.end(); ++it)
- {
- LLItemInfo& land = *it;
-
- if (checkItemHit(x, y, land, id, true))
+ // Iterate through the visible regions
+ for (handle_list_t::iterator iter = mVisibleRegions.begin(); iter != mVisibleRegions.end(); ++iter)
{
- *hit_type = MAP_ITEM_LAND_FOR_SALE_ADULT;
- mItemPicked = TRUE;
- return;
+ U64 handle = *iter;
+ LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle);
+ if ((siminfo == NULL) || (siminfo->isDown()))
+ {
+ continue;
+ }
+ // If on screen check hits with the visible item lists
+ if (gSavedSettings.getBOOL("MapShowEvents"))
+ {
+ LLSimInfo::item_info_list_t::const_iterator it = siminfo->getPGEvent().begin();
+ while (it != siminfo->getPGEvent().end())
+ {
+ LLItemInfo event = *it;
+ if (checkItemHit(x, y, event, id, false))
+ {
+ *hit_type = MAP_ITEM_PG_EVENT;
+ mItemPicked = TRUE;
+ gFloaterWorldMap->trackEvent(event);
+ return;
+ }
+ ++it;
+ }
+ }
+ if (show_mature)
+ {
+ LLSimInfo::item_info_list_t::const_iterator it = siminfo->getMatureEvent().begin();
+ while (it != siminfo->getMatureEvent().end())
+ {
+ LLItemInfo event = *it;
+ if (checkItemHit(x, y, event, id, false))
+ {
+ *hit_type = MAP_ITEM_MATURE_EVENT;
+ mItemPicked = TRUE;
+ gFloaterWorldMap->trackEvent(event);
+ return;
+ }
+ ++it;
+ }
+ }
+ if (show_adult)
+ {
+ LLSimInfo::item_info_list_t::const_iterator it = siminfo->getAdultEvent().begin();
+ while (it != siminfo->getAdultEvent().end())
+ {
+ LLItemInfo event = *it;
+ if (checkItemHit(x, y, event, id, false))
+ {
+ *hit_type = MAP_ITEM_ADULT_EVENT;
+ mItemPicked = TRUE;
+ gFloaterWorldMap->trackEvent(event);
+ return;
+ }
+ ++it;
+ }
+ }
+ if (gSavedSettings.getBOOL("MapShowLandForSale"))
+ {
+ LLSimInfo::item_info_list_t::const_iterator it = siminfo->getLandForSale().begin();
+ while (it != siminfo->getLandForSale().end())
+ {
+ LLItemInfo event = *it;
+ if (checkItemHit(x, y, event, id, true))
+ {
+ *hit_type = MAP_ITEM_LAND_FOR_SALE;
+ mItemPicked = TRUE;
+ return;
+ }
+ ++it;
+ }
+ // for 1.23, we're showing normal land and adult land in the same UI; you don't
+ // get a choice about which ones you want. If you're currently asking for adult
+ // content and land you'll get the adult land.
+ if (gAgent.canAccessAdult())
+ {
+ LLSimInfo::item_info_list_t::const_iterator it = siminfo->getLandForSaleAdult().begin();
+ while (it != siminfo->getLandForSaleAdult().end())
+ {
+ LLItemInfo event = *it;
+ if (checkItemHit(x, y, event, id, true))
+ {
+ *hit_type = MAP_ITEM_LAND_FOR_SALE_ADULT;
+ mItemPicked = TRUE;
+ return;
+ }
+ ++it;
+ }
+ }
+ }
}
}
}
- // If we get here, we haven't clicked on an icon
+ // If we get here, we haven't clicked on anything
gFloaterWorldMap->trackLocation(pos_global);
mItemPicked = FALSE;
-
*id = LLUUID::null;
return;
}
@@ -1748,7 +1604,7 @@ BOOL LLWorldMapView::handleMouseUp( S32 x, S32 y, MASK mask )
LLRect clip_rect = getRect();
clip_rect.stretch(-8);
clip_rect.clipPointToRect(mMouseDownX, mMouseDownY, local_x, local_y);
- LLUI::setCursorPositionLocal(this, local_x, local_y);
+ LLUI::setMousePositionLocal(this, local_x, local_y);
// finish the pan
mPanning = FALSE;
@@ -1770,59 +1626,36 @@ BOOL LLWorldMapView::handleMouseUp( S32 x, S32 y, MASK mask )
return FALSE;
}
-U32 LLWorldMapView::updateBlock(S32 block_x, S32 block_y)
+void LLWorldMapView::updateVisibleBlocks()
{
- U32 blocks_requested = 0;
- S32 offset = block_x | (block_y * MAP_BLOCK_RES);
- if (!LLWorldMap::getInstance()->mMapBlockLoaded[LLWorldMap::getInstance()->mCurrentMap][offset])
+ if (LLWorldMipmap::scaleToLevel(sMapScale) > DRAW_SIMINFO_THRESHOLD)
{
-// llinfos << "Loading Block (" << block_x << "," << block_y << ")" << llendl;
- LLWorldMap::getInstance()->sendMapBlockRequest(block_x << 3, block_y << 3, (block_x << 3) + 7, (block_y << 3) + 7);
- LLWorldMap::getInstance()->mMapBlockLoaded[LLWorldMap::getInstance()->mCurrentMap][offset] = TRUE;
- blocks_requested++;
+ // If we're zoomed out too much, we just don't load all those sim info: too much!
+ return;
}
- return blocks_requested;
-}
-U32 LLWorldMapView::updateVisibleBlocks()
-{
- if (gMapScale < SIM_MAP_SCALE)
- {
- // We don't care what is loaded if we're zoomed out
- return 0;
- }
+ // Load the blocks visible in the current World Map view
+ // Get the World Map view coordinates and boundaries
LLVector3d camera_global = gAgent.getCameraPositionGlobal();
-
- F32 pixels_per_region = gMapScale;
const S32 width = getRect().getWidth();
const S32 height = getRect().getHeight();
- // Convert pan to sim coordinates
- S32 world_center_x_lo = S32(((-sPanX - width/2) / pixels_per_region) + (camera_global.mdV[0] / REGION_WIDTH_METERS));
- S32 world_center_x_hi = S32(((-sPanX + width/2) / pixels_per_region) + (camera_global.mdV[0] / REGION_WIDTH_METERS));
- S32 world_center_y_lo = S32(((-sPanY - height/2) / pixels_per_region) + (camera_global.mdV[1] / REGION_WIDTH_METERS));
- S32 world_center_y_hi = S32(((-sPanY + height/2)/ pixels_per_region) + (camera_global.mdV[1] / REGION_WIDTH_METERS));
-
- // Find the corresponding 8x8 block
- S32 world_block_x_lo = world_center_x_lo >> 3;
- S32 world_block_x_hi = world_center_x_hi >> 3;
- S32 world_block_y_lo = world_center_y_lo >> 3;
- S32 world_block_y_hi = world_center_y_hi >> 3;
-
- U32 blocks_requested = 0;
- const U32 max_blocks_requested = 9;
+ const F32 half_width = F32(width) / 2.0f;
+ const F32 half_height = F32(height) / 2.0f;
- for (S32 block_x = llmax(world_block_x_lo, 0); block_x <= llmin(world_block_x_hi, MAP_BLOCK_RES-1); ++block_x)
- {
- for (S32 block_y = llmax(world_block_y_lo, 0); block_y <= llmin(world_block_y_hi, MAP_BLOCK_RES-1); ++block_y)
- {
- blocks_requested += updateBlock(block_x, block_y);
- if (blocks_requested >= max_blocks_requested)
- return blocks_requested;
- }
- }
- return blocks_requested;
-}
+ // 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));
+
+ // 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;
+
+ //LL_INFOS("World Map") << "LLWorldMapView::updateVisibleBlocks() : sMapScale = " << sMapScale << ", 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);
+}
BOOL LLWorldMapView::handleHover( S32 x, S32 y, MASK mask )
{
@@ -1886,41 +1719,41 @@ BOOL LLWorldMapView::handleDoubleClick( S32 x, S32 y, MASK mask )
case MAP_ITEM_MATURE_EVENT:
case MAP_ITEM_ADULT_EVENT:
{
- gFloaterWorldMap->close();
+ LLFloaterReg::hideInstance("world_map");
// This is an ungainly hack
std::string uuid_str;
S32 event_id;
id.toString(uuid_str);
uuid_str = uuid_str.substr(28);
sscanf(uuid_str.c_str(), "%X", &event_id);
- LLFloaterDirectory::showEvents(event_id);
+ LLFloaterReg::showInstance("search", LLSD().with("category", "events").with("id", event_id));
break;
}
case MAP_ITEM_LAND_FOR_SALE:
case MAP_ITEM_LAND_FOR_SALE_ADULT:
{
- gFloaterWorldMap->close();
- LLFloaterDirectory::showLandForSale(id);
+ LLFloaterReg::hideInstance("world_map");
+ LLFloaterReg::showInstance("search", LLSD().with("category", "destinations").with("id", id));
break;
}
case MAP_ITEM_CLASSIFIED:
{
- gFloaterWorldMap->close();
- LLFloaterDirectory::showClassified(id);
+ LLFloaterReg::hideInstance("world_map");
+ LLFloaterReg::showInstance("search", LLSD().with("category", "classifieds").with("id", id));
break;
}
default:
{
- if (LLWorldMap::getInstance()->mIsTrackingUnknownLocation)
+ if (LLWorldMap::getInstance()->isTracking())
{
- LLWorldMap::getInstance()->mIsTrackingDoubleClick = TRUE;
+ LLWorldMap::getInstance()->setTrackingDoubleClick();
}
else
{
// Teleport if we got a valid location
LLVector3d pos_global = viewPosToGlobal(x,y);
LLSimInfo* sim_info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global);
- if (sim_info && sim_info->mAccess != SIM_ACCESS_DOWN)
+ if (sim_info && !sim_info->isDown())
{
gAgent.teleportViaLocation( pos_global );
}
diff --git a/indra/newview/llworldmapview.h b/indra/newview/llworldmapview.h
index 1717b76beb..9eecacb2d8 100644
--- a/indra/newview/llworldmapview.h
+++ b/indra/newview/llworldmapview.h
@@ -30,27 +30,23 @@
* $/LicenseInfo$
*/
-// Global map of the world.
+// View of the global map of the world
+
+// The data (model) for the global map (a singleton, unique to the application instance) is
+// in LLWorldMap and is typically accessed using LLWorldMap::getInstance()
#ifndef LL_LLWORLDMAPVIEW_H
#define LL_LLWORLDMAPVIEW_H
#include "llpanel.h"
-#include "v3math.h"
-#include "v3dmath.h"
-#include "v4color.h"
-#include "llviewerimage.h"
-#include "llmapimagetype.h"
#include "llworldmap.h"
-
-class LLItemInfo;
+#include "v4color.h"
const S32 DEFAULT_TRACKING_ARROW_SIZE = 16;
-class LLColor4;
-class LLColor4U;
-class LLCoordGL;
-class LLViewerImage;
+class LLUUID;
+class LLVector3d;
+class LLVector3;
class LLTextBox;
@@ -60,9 +56,11 @@ public:
static void initClass();
static void cleanupClass();
- LLWorldMapView(const std::string& name, const LLRect& rect );
+ LLWorldMapView();
virtual ~LLWorldMapView();
-
+
+ virtual BOOL postBuild();
+
virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE );
virtual void setVisible(BOOL visible);
@@ -70,27 +68,31 @@ public:
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask );
virtual BOOL handleHover( S32 x, S32 y, MASK mask );
- virtual BOOL handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen );
+ virtual BOOL handleToolTip( S32 x, S32 y, MASK mask);
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.
+ // 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 );
+ // Return true if the current scale level is above the threshold for accessing region info
+ static bool showRegionInfo();
LLVector3 globalPosToView(const LLVector3d& global_pos);
LLVector3d viewPosToGlobal(S32 x,S32 y);
virtual void draw();
- void drawGenericItems(const LLWorldMap::item_info_list_t& items, LLUIImagePtr image);
+ void drawGenericItems(const LLSimInfo::item_info_list_t& items, LLUIImagePtr image);
void drawGenericItem(const LLItemInfo& item, LLUIImagePtr image);
void drawImage(const LLVector3d& global_pos, LLUIImagePtr image, const LLColor4& color = LLColor4::white);
void drawImageStack(const LLVector3d& global_pos, LLUIImagePtr image, U32 count, F32 offset, const LLColor4& color);
void drawAgents();
- void drawEvents();
+ void drawItems();
void drawFrustum();
+ void drawMipmap(S32 width, S32 height);
+ bool drawMipmapLevel(S32 width, S32 height, S32 level, bool load = true);
static void cleanupTextures();
@@ -106,7 +108,7 @@ public:
F32 y_pixels,
const LLColor4& color,
F32 relative_z = 0.f,
- F32 dot_radius = 3.f);
+ F32 dot_radius = 5.f);
static void drawTrackingCircle( const LLRect& rect, S32 x, S32 y,
const LLColor4& color,
@@ -127,9 +129,7 @@ public:
static void clearLastClick() { sHandledLastClick = FALSE; }
// if the view changes, download additional sim info as needed
- // return value is number of blocks newly requested.
- U32 updateBlock(S32 block_x, S32 block_y);
- U32 updateVisibleBlocks();
+ void updateVisibleBlocks();
protected:
void setDirectionPos( LLTextBox* text_box, F32 rotation );
@@ -138,11 +138,13 @@ protected:
public:
LLColor4 mBackgroundColor;
- static LLUIImagePtr sAvatarYouSmallImage;
static LLUIImagePtr sAvatarSmallImage;
- static LLUIImagePtr sAvatarLargeImage;
+ static LLUIImagePtr sAvatarYouImage;
+ static LLUIImagePtr sAvatarYouLargeImage;
+ static LLUIImagePtr sAvatarLevelImage;
static LLUIImagePtr sAvatarAboveImage;
static LLUIImagePtr sAvatarBelowImage;
+
static LLUIImagePtr sTelehubImage;
static LLUIImagePtr sInfohubImage;
static LLUIImagePtr sHomeImage;
@@ -155,9 +157,7 @@ public:
static LLUIImagePtr sForSaleImage;
static LLUIImagePtr sForSaleAdultImage;
- static F32 sThresholdA;
- static F32 sThresholdB;
- static F32 sPixelsPerMeter; // world meters to map pixels
+ static F32 sMapScale; // scale = size of a region in pixels
BOOL mItemPicked;
@@ -167,6 +167,7 @@ public:
static F32 sTargetPanY; // in pixels
static S32 sTrackingArrowX;
static S32 sTrackingArrowY;
+ static bool sVisibleTilesLoaded;
// Are we mid-pan from a user drag?
BOOL mPanning;
@@ -189,10 +190,14 @@ public:
static BOOL sHandledLastClick;
S32 mSelectIDStart;
+ // Keep the list of regions that are displayed on screen. Avoids iterating through the whole region map after draw().
typedef std::vector<U64> handle_list_t;
handle_list_t mVisibleRegions; // set every frame
static std::map<std::string,std::string> sStringsMap;
+
+private:
+ void drawTileOutline(S32 level, F32 top, F32 left, F32 bottom, F32 right);
};
#endif
diff --git a/indra/newview/llworldmipmap.cpp b/indra/newview/llworldmipmap.cpp
new file mode 100644
index 0000000000..1cdccd2baa
--- /dev/null
+++ b/indra/newview/llworldmipmap.cpp
@@ -0,0 +1,274 @@
+/**
+ * @file llworldmipmap.cpp
+ * @brief Data storage for the S3 mipmap of the entire world.
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llworldmipmap.h"
+
+#include "llviewertexturelist.h"
+#include "math.h" // log()
+
+// Turn this on to output tile stats in the standard output
+#define DEBUG_TILES_STAT 0
+
+LLWorldMipmap::LLWorldMipmap() :
+ mCurrentLevel(0)
+{
+}
+
+LLWorldMipmap::~LLWorldMipmap()
+{
+ reset();
+}
+
+// Delete all sublevel maps and clean them
+void LLWorldMipmap::reset()
+{
+ for (int level = 0; level < MAP_LEVELS; level++)
+ {
+ mWorldObjectsMipMap[level].clear();
+ }
+}
+
+// This method should be called before each use of the mipmap (typically, before each draw), so that to let
+// the boost level of unused tiles to drop to 0 (BOOST_NONE).
+// Tiles that are accessed have had their boost level pushed to BOOST_MAP_VISIBLE so we can identify them.
+// The result of this strategy is that if a tile is not used during 2 consecutive loops, its boost level drops to 0.
+void LLWorldMipmap::equalizeBoostLevels()
+{
+#if DEBUG_TILES_STAT
+ S32 nb_missing = 0;
+ S32 nb_tiles = 0;
+ S32 nb_visible = 0;
+#endif // DEBUG_TILES_STAT
+ // For each level
+ for (S32 level = 0; level < MAP_LEVELS; level++)
+ {
+ sublevel_tiles_t& level_mipmap = mWorldObjectsMipMap[level];
+ // For each tile
+ for (sublevel_tiles_t::iterator iter = level_mipmap.begin(); iter != level_mipmap.end(); iter++)
+ {
+ LLPointer<LLViewerFetchedTexture> img = iter->second;
+ S32 current_boost_level = img->getBoostLevel();
+ if (current_boost_level == LLViewerTexture::BOOST_MAP_VISIBLE)
+ {
+ // If level was BOOST_MAP_VISIBLE, the tile has been used in the last draw so keep it high
+ img->setBoostLevel(LLViewerTexture::BOOST_MAP);
+ }
+ else
+ {
+ // If level was BOOST_MAP only (or anything else...), the tile wasn't used in the last draw
+ // so we drop its boost level to BOOST_NONE.
+ img->setBoostLevel(LLViewerTexture::BOOST_NONE);
+ }
+#if DEBUG_TILES_STAT
+ // Increment some stats if compile option on
+ nb_tiles++;
+ if (current_boost_level == LLViewerTexture::BOOST_MAP_VISIBLE)
+ {
+ nb_visible++;
+ }
+ if (img->isMissingAsset())
+ {
+ nb_missing++;
+ }
+#endif // DEBUG_TILES_STAT
+ }
+ }
+#if DEBUG_TILES_STAT
+ LL_INFOS("World Map") << "LLWorldMipmap tile stats : total requested = " << nb_tiles << ", visible = " << nb_visible << ", missing = " << nb_missing << LL_ENDL;
+#endif // DEBUG_TILES_STAT
+}
+
+// This method should be used when the mipmap is not actively used for a while, e.g., the map UI is hidden
+void LLWorldMipmap::dropBoostLevels()
+{
+ // For each level
+ for (S32 level = 0; level < MAP_LEVELS; level++)
+ {
+ sublevel_tiles_t& level_mipmap = mWorldObjectsMipMap[level];
+ // For each tile
+ for (sublevel_tiles_t::iterator iter = level_mipmap.begin(); iter != level_mipmap.end(); iter++)
+ {
+ LLPointer<LLViewerFetchedTexture> img = iter->second;
+ img->setBoostLevel(LLViewerTexture::BOOST_NONE);
+ }
+ }
+}
+
+LLPointer<LLViewerFetchedTexture> LLWorldMipmap::getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load)
+{
+ // Check the input data
+ llassert(level <= MAP_LEVELS);
+ llassert(level >= 1);
+
+ // If the *loading* level changed, cleared the new level from "missed" tiles
+ // so that we get a chance to reload them
+ if (load && (level != mCurrentLevel))
+ {
+ cleanMissedTilesFromLevel(level);
+ mCurrentLevel = level;
+ }
+
+ // Build the region handle
+ U64 handle = convertGridToHandle(grid_x, grid_y);
+
+ // Check if the image is around already
+ sublevel_tiles_t& level_mipmap = mWorldObjectsMipMap[level-1];
+ sublevel_tiles_t::iterator found = level_mipmap.find(handle);
+
+ // If not there and load on, go load it
+ if (found == level_mipmap.end())
+ {
+ if (load)
+ {
+ // Load it
+ LLPointer<LLViewerFetchedTexture> img = loadObjectsTile(grid_x, grid_y, level);
+ // Insert the image in the map
+ level_mipmap.insert(sublevel_tiles_t::value_type( handle, img ));
+ // Find the element again in the map (it's there now...)
+ found = level_mipmap.find(handle);
+ }
+ else
+ {
+ // Return with NULL if not found and we're not trying to load
+ return NULL;
+ }
+ }
+
+ // Get the image pointer and check if this asset is missing
+ LLPointer<LLViewerFetchedTexture> img = found->second;
+ if (img->isMissingAsset())
+ {
+ // Return NULL if asset missing
+ return NULL;
+ }
+ else
+ {
+ // Boost the tile level so to mark it's in use *if* load on
+ if (load)
+ {
+ img->setBoostLevel(LLViewerTexture::BOOST_MAP_VISIBLE);
+ }
+ return img;
+ }
+}
+
+LLPointer<LLViewerFetchedTexture> LLWorldMipmap::loadObjectsTile(U32 grid_x, U32 grid_y, S32 level)
+{
+ // Get the grid coordinates
+ std::string imageurl = llformat("http://map.secondlife.com.s3.amazonaws.com/map-%d-%d-%d-objects.jpg",
+ level, grid_x, grid_y);
+
+ // DO NOT COMMIT!! DEBUG ONLY!!!
+ // Use a local jpeg for every tile to test map speed without S3 access
+ //imageurl = "file://C:\\Develop\\mapserver-distribute-3\\indra\\build-vc80\\mapserver\\relwithdebinfo\\regions\\00995\\01001\\region-995-1001-prims.jpg";
+ // END DEBUG
+ //LL_INFOS("World Map") << "LLWorldMipmap::loadObjectsTile(), URL = " << imageurl << LL_ENDL;
+
+ LLPointer<LLViewerFetchedTexture> img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+ img->setBoostLevel(LLViewerTexture::BOOST_MAP);
+
+ // Return the smart pointer
+ return img;
+}
+
+// This method is used to clean up a level from tiles marked as "missing".
+// The idea is to allow tiles that have been improperly marked missing to be reloaded when retraversing the level again.
+// When zooming in and out rapidly, some tiles are never properly loaded and, eventually marked missing.
+// This creates "blue" areas in a subresolution that never got a chance to reload if we don't clean up the level.
+void LLWorldMipmap::cleanMissedTilesFromLevel(S32 level)
+{
+ // Check the input data
+ llassert(level <= MAP_LEVELS);
+ llassert(level >= 0);
+
+ // This happens when the object is first initialized
+ if (level == 0)
+ {
+ return;
+ }
+
+ // Iterate through the subresolution level and suppress the tiles that are marked as missing
+ // Note: erasing in a map while iterating through it is bug prone. Using a postfix increment is mandatory here.
+ sublevel_tiles_t& level_mipmap = mWorldObjectsMipMap[level-1];
+ sublevel_tiles_t::iterator it = level_mipmap.begin();
+ while (it != level_mipmap.end())
+ {
+ LLPointer<LLViewerFetchedTexture> img = it->second;
+ if (img->isMissingAsset())
+ {
+ level_mipmap.erase(it++);
+ }
+ else
+ {
+ ++it;
+ }
+ }
+ return;
+}
+
+// static methods
+// Compute the level in the world mipmap (between 1 and MAP_LEVELS, as in the URL) given the scale (size of a sim in screen pixels)
+S32 LLWorldMipmap::scaleToLevel(F32 scale)
+{
+ // If scale really small, picks up the higest level there is (lowest resolution)
+ if (scale <= F32_MIN)
+ return MAP_LEVELS;
+ // Compute the power of two resolution level knowing the base level
+ S32 level = llfloor((log(REGION_WIDTH_METERS/scale)/log(2.0f)) + 1.0f);
+ // Check bounds and return the value
+ if (level > MAP_LEVELS)
+ return MAP_LEVELS;
+ else if (level < 1)
+ return 1;
+ else
+ return level;
+}
+
+// Convert world coordinates to mipmap grid coordinates at a given level (between 1 and MAP_LEVELS)
+void LLWorldMipmap::globalToMipmap(F64 global_x, F64 global_y, S32 level, U32* grid_x, U32* grid_y)
+{
+ // Check the input data
+ llassert(level <= MAP_LEVELS);
+ llassert(level >= 1);
+
+ // Convert world coordinates into grid coordinates
+ *grid_x = lltrunc(global_x/REGION_WIDTH_METERS);
+ *grid_y = lltrunc(global_y/REGION_WIDTH_METERS);
+ // Compute the valid grid coordinates at that level of the mipmap
+ S32 regions_in_tile = 1 << (level - 1);
+ *grid_x = *grid_x - (*grid_x % regions_in_tile);
+ *grid_y = *grid_y - (*grid_y % regions_in_tile);
+}
+
+
diff --git a/indra/newview/llworldmipmap.h b/indra/newview/llworldmipmap.h
new file mode 100644
index 0000000000..ecf1003468
--- /dev/null
+++ b/indra/newview/llworldmipmap.h
@@ -0,0 +1,100 @@
+/**
+ * @file llworldmipmap.h
+ * @brief Data storage for the S3 mipmap of the entire world.
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLWORLDMIPMAP_H
+#define LL_LLWORLDMIPMAP_H
+
+#include <map>
+
+#include "llmemory.h" // LLPointer
+#include "indra_constants.h" // REGION_WIDTH_UNITS
+#include "llregionhandle.h" // to_region_handle()
+
+class LLViewerFetchedTexture;
+
+// LLWorldMipmap : Mipmap handling of all the tiles used to render the world at any resolution.
+// This class provides a clean structured access to the hierarchy of tiles stored in the
+// Amazon S3 repository and abstracts its directory/file structure.
+// The interface of this class though still assumes that the caller knows the general level/tiles
+// structure (at least, that it exists...) but doesn't requite the caller to know the details of it.
+// IOW, you need to know that rendering levels exists as well as grid coordinates for regions,
+// but you can ignore where those tiles are located, how to get them, etc...
+// The class API gives you back LLPointer<LLViewerFetchedTexture> per tile.
+
+// See llworldmipmapview.cpp for the implementation of a class who knows how to render an LLWorldMipmap.
+
+// Implementation notes:
+// - On the S3 servers, the tiles are rendered in 2 flavors: Objects and Terrain.
+// - For the moment, LLWorldMipmap implements access only to the Objects tiles.
+class LLWorldMipmap
+{
+public:
+ // Parameters of the mipmap
+ static const S32 MAP_LEVELS = 8; // Number of subresolution levels computed by the mapserver
+ static const S32 MAP_TILE_SIZE = 256; // Width in pixels of the tiles computed by the mapserver
+
+ LLWorldMipmap();
+ ~LLWorldMipmap();
+
+ // Clear up the maps and release all image handles
+ void reset();
+ // Manage the boost levels between loops (typically draw() loops)
+ void equalizeBoostLevels();
+ // Drop the boost levels to none (used when hiding the map)
+ void dropBoostLevels();
+ // Get the tile smart pointer, does the loading if necessary
+ LLPointer<LLViewerFetchedTexture> getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load = true);
+
+ // Helper functions: those are here as they depend solely on the topology of the mipmap though they don't access it
+ // Convert sim scale (given in sim width in display pixels) into a mipmap level
+ static S32 scaleToLevel(F32 scale);
+ // Convert world coordinates to mipmap grid coordinates at a given level
+ static void globalToMipmap(F64 global_x, F64 global_y, S32 level, U32* grid_x, U32* grid_y);
+
+private:
+ // Get a handle (key) from grid coordinates
+ U64 convertGridToHandle(U32 grid_x, U32 grid_y) { return to_region_handle(grid_x * REGION_WIDTH_UNITS, grid_y * REGION_WIDTH_UNITS); }
+ // Load the relevant tile from S3
+ LLPointer<LLViewerFetchedTexture> loadObjectsTile(U32 grid_x, U32 grid_y, S32 level);
+ // Clear a level from its "missing" tiles
+ void cleanMissedTilesFromLevel(S32 level);
+
+ // The mipmap is organized by resolution level (MAP_LEVELS of them). Each resolution level is an std::map
+ // using a region_handle as a key and storing a smart pointer to the image as a value.
+ typedef std::map<U64, LLPointer<LLViewerFetchedTexture> > sublevel_tiles_t;
+ sublevel_tiles_t mWorldObjectsMipMap[MAP_LEVELS];
+// sublevel_tiles_t mWorldTerrainMipMap[MAP_LEVELS];
+
+ S32 mCurrentLevel; // The level last accessed by a getObjectsTile()
+};
+
+#endif // LL_LLWORLDMIPMAP_H
diff --git a/indra/newview/llxmlrpclistener.cpp b/indra/newview/llxmlrpclistener.cpp
new file mode 100644
index 0000000000..15417614af
--- /dev/null
+++ b/indra/newview/llxmlrpclistener.cpp
@@ -0,0 +1,497 @@
+/**
+ * @file llxmlrpclistener.cpp
+ * @author Nat Goodspeed
+ * @date 2009-03-18
+ * @brief Implementation for llxmlrpclistener.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+
+// Precompiled header
+#include "llviewerprecompiledheaders.h"
+// associated header
+#include "llxmlrpclistener.h"
+// STL headers
+#include <map>
+#include <set>
+// std headers
+// external library headers
+#include <boost/scoped_ptr.hpp>
+#include <boost/range.hpp> // boost::begin(), boost::end()
+#include <xmlrpc-epi/xmlrpc.h>
+#include "curl/curl.h"
+
+// other Linden headers
+#include "llerror.h"
+#include "stringize.h"
+#include "llxmlrpctransaction.h"
+
+#if LL_WINDOWS
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
+#endif
+
+template <typename STATUS>
+class StatusMapperBase
+{
+ typedef std::map<STATUS, std::string> MapType;
+
+public:
+ StatusMapperBase(const std::string& desc):
+ mDesc(desc)
+ {}
+
+ std::string lookup(STATUS status) const
+ {
+ typename MapType::const_iterator found = mMap.find(status);
+ if (found != mMap.end())
+ {
+ return found->second;
+ }
+ return STRINGIZE("<unknown " << mDesc << " " << status << ">");
+ }
+
+protected:
+ std::string mDesc;
+ MapType mMap;
+};
+
+class StatusMapper: public StatusMapperBase<LLXMLRPCTransaction::EStatus>
+{
+public:
+ StatusMapper(): StatusMapperBase<LLXMLRPCTransaction::EStatus>("Status")
+ {
+ mMap[LLXMLRPCTransaction::StatusNotStarted] = "NotStarted";
+ mMap[LLXMLRPCTransaction::StatusStarted] = "Started";
+ mMap[LLXMLRPCTransaction::StatusDownloading] = "Downloading";
+ mMap[LLXMLRPCTransaction::StatusComplete] = "Complete";
+ mMap[LLXMLRPCTransaction::StatusCURLError] = "CURLError";
+ mMap[LLXMLRPCTransaction::StatusXMLRPCError] = "XMLRPCError";
+ mMap[LLXMLRPCTransaction::StatusOtherError] = "OtherError";
+ }
+};
+
+static const StatusMapper sStatusMapper;
+
+class CURLcodeMapper: public StatusMapperBase<CURLcode>
+{
+public:
+ CURLcodeMapper(): StatusMapperBase<CURLcode>("CURLcode")
+ {
+ // from curl.h
+// skip the "CURLE_" prefix for each of these strings
+#define def(sym) (mMap[sym] = #sym + 6)
+ def(CURLE_OK);
+ def(CURLE_UNSUPPORTED_PROTOCOL); /* 1 */
+ def(CURLE_FAILED_INIT); /* 2 */
+ def(CURLE_URL_MALFORMAT); /* 3 */
+ def(CURLE_URL_MALFORMAT_USER); /* 4 - NOT USED */
+ def(CURLE_COULDNT_RESOLVE_PROXY); /* 5 */
+ def(CURLE_COULDNT_RESOLVE_HOST); /* 6 */
+ def(CURLE_COULDNT_CONNECT); /* 7 */
+ def(CURLE_FTP_WEIRD_SERVER_REPLY); /* 8 */
+ def(CURLE_FTP_ACCESS_DENIED); /* 9 a service was denied by the FTP server
+ due to lack of access - when login fails
+ this is not returned. */
+ def(CURLE_FTP_USER_PASSWORD_INCORRECT); /* 10 - NOT USED */
+ def(CURLE_FTP_WEIRD_PASS_REPLY); /* 11 */
+ def(CURLE_FTP_WEIRD_USER_REPLY); /* 12 */
+ def(CURLE_FTP_WEIRD_PASV_REPLY); /* 13 */
+ def(CURLE_FTP_WEIRD_227_FORMAT); /* 14 */
+ def(CURLE_FTP_CANT_GET_HOST); /* 15 */
+ def(CURLE_FTP_CANT_RECONNECT); /* 16 */
+ def(CURLE_FTP_COULDNT_SET_BINARY); /* 17 */
+ def(CURLE_PARTIAL_FILE); /* 18 */
+ def(CURLE_FTP_COULDNT_RETR_FILE); /* 19 */
+ def(CURLE_FTP_WRITE_ERROR); /* 20 */
+ def(CURLE_FTP_QUOTE_ERROR); /* 21 */
+ def(CURLE_HTTP_RETURNED_ERROR); /* 22 */
+ def(CURLE_WRITE_ERROR); /* 23 */
+ def(CURLE_MALFORMAT_USER); /* 24 - NOT USED */
+ def(CURLE_UPLOAD_FAILED); /* 25 - failed upload "command" */
+ def(CURLE_READ_ERROR); /* 26 - could open/read from file */
+ def(CURLE_OUT_OF_MEMORY); /* 27 */
+ /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error
+ instead of a memory allocation error if CURL_DOES_CONVERSIONS
+ is defined
+ */
+ def(CURLE_OPERATION_TIMEOUTED); /* 28 - the timeout time was reached */
+ def(CURLE_FTP_COULDNT_SET_ASCII); /* 29 - TYPE A failed */
+ def(CURLE_FTP_PORT_FAILED); /* 30 - FTP PORT operation failed */
+ def(CURLE_FTP_COULDNT_USE_REST); /* 31 - the REST command failed */
+ def(CURLE_FTP_COULDNT_GET_SIZE); /* 32 - the SIZE command failed */
+ def(CURLE_HTTP_RANGE_ERROR); /* 33 - RANGE "command" didn't work */
+ def(CURLE_HTTP_POST_ERROR); /* 34 */
+ def(CURLE_SSL_CONNECT_ERROR); /* 35 - wrong when connecting with SSL */
+ def(CURLE_BAD_DOWNLOAD_RESUME); /* 36 - couldn't resume download */
+ def(CURLE_FILE_COULDNT_READ_FILE); /* 37 */
+ def(CURLE_LDAP_CANNOT_BIND); /* 38 */
+ def(CURLE_LDAP_SEARCH_FAILED); /* 39 */
+ def(CURLE_LIBRARY_NOT_FOUND); /* 40 */
+ def(CURLE_FUNCTION_NOT_FOUND); /* 41 */
+ def(CURLE_ABORTED_BY_CALLBACK); /* 42 */
+ def(CURLE_BAD_FUNCTION_ARGUMENT); /* 43 */
+ def(CURLE_BAD_CALLING_ORDER); /* 44 - NOT USED */
+ def(CURLE_INTERFACE_FAILED); /* 45 - CURLOPT_INTERFACE failed */
+ def(CURLE_BAD_PASSWORD_ENTERED); /* 46 - NOT USED */
+ def(CURLE_TOO_MANY_REDIRECTS ); /* 47 - catch endless re-direct loops */
+ def(CURLE_UNKNOWN_TELNET_OPTION); /* 48 - User specified an unknown option */
+ def(CURLE_TELNET_OPTION_SYNTAX ); /* 49 - Malformed telnet option */
+ def(CURLE_OBSOLETE); /* 50 - NOT USED */
+ def(CURLE_SSL_PEER_CERTIFICATE); /* 51 - peer's certificate wasn't ok */
+ def(CURLE_GOT_NOTHING); /* 52 - when this is a specific error */
+ def(CURLE_SSL_ENGINE_NOTFOUND); /* 53 - SSL crypto engine not found */
+ def(CURLE_SSL_ENGINE_SETFAILED); /* 54 - can not set SSL crypto engine as
+ default */
+ def(CURLE_SEND_ERROR); /* 55 - failed sending network data */
+ def(CURLE_RECV_ERROR); /* 56 - failure in receiving network data */
+ def(CURLE_SHARE_IN_USE); /* 57 - share is in use */
+ def(CURLE_SSL_CERTPROBLEM); /* 58 - problem with the local certificate */
+ def(CURLE_SSL_CIPHER); /* 59 - couldn't use specified cipher */
+ def(CURLE_SSL_CACERT); /* 60 - problem with the CA cert (path?) */
+ def(CURLE_BAD_CONTENT_ENCODING); /* 61 - Unrecognized transfer encoding */
+ def(CURLE_LDAP_INVALID_URL); /* 62 - Invalid LDAP URL */
+ def(CURLE_FILESIZE_EXCEEDED); /* 63 - Maximum file size exceeded */
+ def(CURLE_FTP_SSL_FAILED); /* 64 - Requested FTP SSL level failed */
+ def(CURLE_SEND_FAIL_REWIND); /* 65 - Sending the data requires a rewind
+ that failed */
+ def(CURLE_SSL_ENGINE_INITFAILED); /* 66 - failed to initialise ENGINE */
+ def(CURLE_LOGIN_DENIED); /* 67 - user); password or similar was not
+ accepted and we failed to login */
+ def(CURLE_TFTP_NOTFOUND); /* 68 - file not found on server */
+ def(CURLE_TFTP_PERM); /* 69 - permission problem on server */
+ def(CURLE_TFTP_DISKFULL); /* 70 - out of disk space on server */
+ def(CURLE_TFTP_ILLEGAL); /* 71 - Illegal TFTP operation */
+ def(CURLE_TFTP_UNKNOWNID); /* 72 - Unknown transfer ID */
+ def(CURLE_TFTP_EXISTS); /* 73 - File already exists */
+ def(CURLE_TFTP_NOSUCHUSER); /* 74 - No such user */
+ def(CURLE_CONV_FAILED); /* 75 - conversion failed */
+ def(CURLE_CONV_REQD); /* 76 - caller must register conversion
+ callbacks using curl_easy_setopt options
+ CURLOPT_CONV_FROM_NETWORK_FUNCTION);
+ CURLOPT_CONV_TO_NETWORK_FUNCTION); and
+ CURLOPT_CONV_FROM_UTF8_FUNCTION */
+ def(CURLE_SSL_CACERT_BADFILE); /* 77 - could not load CACERT file); missing
+ or wrong format */
+ def(CURLE_REMOTE_FILE_NOT_FOUND); /* 78 - remote file not found */
+ def(CURLE_SSH); /* 79 - error from the SSH layer); somewhat
+ generic so the error message will be of
+ interest when this has happened */
+
+ def(CURLE_SSL_SHUTDOWN_FAILED); /* 80 - Failed to shut down the SSL
+ connection */
+#undef def
+ }
+};
+
+static const CURLcodeMapper sCURLcodeMapper;
+
+LLXMLRPCListener::LLXMLRPCListener(const std::string& pumpname):
+ mBoundListener(LLEventPumps::instance().
+ obtain(pumpname).
+ listen("LLXMLRPCListener", boost::bind(&LLXMLRPCListener::process, this, _1)))
+{
+}
+
+/**
+ * Capture an outstanding LLXMLRPCTransaction and poll it periodically until
+ * done.
+ *
+ * The sequence is:
+ * # Instantiate Poller, which instantiates, populates and initiates an
+ * LLXMLRPCTransaction. Poller self-registers on the LLEventPump named
+ * "mainloop".
+ * # "mainloop" is conventionally pumped once per frame. On each such call,
+ * Poller checks its LLXMLRPCTransaction for completion.
+ * # When the LLXMLRPCTransaction completes, Poller collects results (if any)
+ * and sends notification.
+ * # The tricky part: Poller frees itself (and thus its LLXMLRPCTransaction)
+ * when done. The only external reference to it is the connection to the
+ * "mainloop" LLEventPump.
+ */
+class Poller
+{
+public:
+ /// Validate the passed request for required fields, then use it to
+ /// populate an XMLRPC_REQUEST and an associated LLXMLRPCTransaction. Send
+ /// the request.
+ Poller(const LLSD& command):
+ mReqID(command),
+ mUri(command["uri"]),
+ mMethod(command["method"]),
+ mReplyPump(command["reply"])
+ {
+ // LL_ERRS if any of these are missing
+ const char* required[] = { "uri", "method", "reply" };
+ // optional: "options" (array of string)
+ // Validate the request
+ std::set<std::string> missing;
+ for (const char** ri = boost::begin(required); ri != boost::end(required); ++ri)
+ {
+ // If the command does not contain this required entry, add it to 'missing'.
+ if (! command.has(*ri))
+ {
+ missing.insert(*ri);
+ }
+ }
+ if (! missing.empty())
+ {
+ LL_ERRS("LLXMLRPCListener") << mMethod << " request missing params: ";
+ const char* separator = "";
+ for (std::set<std::string>::const_iterator mi(missing.begin()), mend(missing.end());
+ mi != mend; ++mi)
+ {
+ LL_CONT << separator << *mi;
+ separator = ", ";
+ }
+ LL_CONT << LL_ENDL;
+ }
+
+ // Build the XMLRPC request.
+ XMLRPC_REQUEST request = XMLRPC_RequestNew();
+ XMLRPC_RequestSetMethodName(request, mMethod.c_str());
+ XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
+ XMLRPC_VALUE xparams = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
+ LLSD params(command["params"]);
+ if (params.isMap())
+ {
+ for (LLSD::map_const_iterator pi(params.beginMap()), pend(params.endMap());
+ pi != pend; ++pi)
+ {
+ std::string name(pi->first);
+ LLSD param(pi->second);
+ if (param.isString())
+ {
+ XMLRPC_VectorAppendString(xparams, name.c_str(), param.asString().c_str(), 0);
+ }
+ else if (param.isInteger() || param.isBoolean())
+ {
+ XMLRPC_VectorAppendInt(xparams, name.c_str(), param.asInteger());
+ }
+ else if (param.isReal())
+ {
+ XMLRPC_VectorAppendDouble(xparams, name.c_str(), param.asReal());
+ }
+ else
+ {
+ LL_ERRS("LLXMLRPCListener") << mMethod << " request param "
+ << name << " has unknown type: " << param << LL_ENDL;
+ }
+ }
+ }
+ LLSD options(command["options"]);
+ if (options.isArray())
+ {
+ XMLRPC_VALUE xoptions = XMLRPC_CreateVector("options", xmlrpc_vector_array);
+ for (LLSD::array_const_iterator oi(options.beginArray()), oend(options.endArray());
+ oi != oend; ++oi)
+ {
+ XMLRPC_VectorAppendString(xoptions, NULL, oi->asString().c_str(), 0);
+ }
+ XMLRPC_AddValueToVector(xparams, xoptions);
+ }
+ XMLRPC_RequestSetData(request, xparams);
+
+ mTransaction.reset(new LLXMLRPCTransaction(mUri, request));
+ mPreviousStatus = mTransaction->status(NULL);
+
+ // Free the XMLRPC_REQUEST object and the attached data values.
+ XMLRPC_RequestFree(request, 1);
+
+ // Now ensure that we get regular callbacks to poll for completion.
+ mBoundListener =
+ LLEventPumps::instance().
+ obtain("mainloop").
+ listen(LLEventPump::inventName(), boost::bind(&Poller::poll, this, _1));
+
+ LL_INFOS("LLXMLRPCListener") << mMethod << " request sent to " << mUri << LL_ENDL;
+ }
+
+ /// called by "mainloop" LLEventPump
+ bool poll(const LLSD&)
+ {
+ bool done = mTransaction->process();
+
+ CURLcode curlcode;
+ LLXMLRPCTransaction::EStatus status;
+ {
+ // LLXMLRPCTransaction::status() is defined to accept int* rather
+ // than CURLcode*. I don't feel the urge to fix the signature, but
+ // we want a CURLcode rather than an int. So fetch it as a local
+ // int, but then assign to a CURLcode for the remainder of this
+ // method.
+ int curlint;
+ status = mTransaction->status(&curlint);
+ curlcode = CURLcode(curlint);
+ }
+
+ LLSD data(mReqID.makeResponse());
+ data["status"] = sStatusMapper.lookup(status);
+ data["errorcode"] = sCURLcodeMapper.lookup(curlcode);
+ data["error"] = "";
+ data["transfer_rate"] = 0.0;
+ LLEventPump& replyPump(LLEventPumps::instance().obtain(mReplyPump));
+ if (! done)
+ {
+ // Not done yet, carry on.
+ if (status == LLXMLRPCTransaction::StatusDownloading
+ && status != mPreviousStatus)
+ {
+ // If a response has been received, send the
+ // 'downloading' status if it hasn't been sent.
+ replyPump.post(data);
+ }
+
+ mPreviousStatus = status;
+ return false;
+ }
+
+ // Here the transaction is complete. Check status.
+ data["error"] = mTransaction->statusMessage();
+ data["transfer_rate"] = mTransaction->transferRate();
+ LL_INFOS("LLXMLRPCListener") << mMethod << " result from " << mUri << ": status "
+ << data["status"].asString() << ", errorcode "
+ << data["errorcode"].asString()
+ << " (" << data["error"].asString() << ")"
+ << LL_ENDL;
+ // In addition to CURLE_OK, LLUserAuth distinguishes different error
+ // values of 'curlcode':
+ // CURLE_COULDNT_RESOLVE_HOST,
+ // CURLE_SSL_PEER_CERTIFICATE,
+ // CURLE_SSL_CACERT,
+ // CURLE_SSL_CONNECT_ERROR.
+ // Given 'message', need we care?
+ if (status == LLXMLRPCTransaction::StatusComplete)
+ {
+ // Success! Parse data.
+ std::string status_string(data["status"]);
+ data["responses"] = parseResponse(status_string);
+ data["status"] = status_string;
+ }
+
+ // whether successful or not, send reply on requested LLEventPump
+ replyPump.post(data);
+
+ // Because mTransaction is a boost::scoped_ptr, deleting this object
+ // frees our LLXMLRPCTransaction object.
+ // Because mBoundListener is an LLTempBoundListener, deleting this
+ // object disconnects it from "mainloop".
+ // *** MUST BE LAST ***
+ delete this;
+ return false;
+ }
+
+private:
+ /// Derived from LLUserAuth::parseResponse() and parseOptionInto()
+ LLSD parseResponse(std::string& status_string)
+ {
+ // Extract every member into data["responses"] (a map of string
+ // values).
+ XMLRPC_REQUEST response = mTransaction->response();
+ if (! response)
+ {
+ LL_DEBUGS("LLXMLRPCListener") << "No response" << LL_ENDL;
+ return LLSD();
+ }
+
+ XMLRPC_VALUE param = XMLRPC_RequestGetData(response);
+ if (! param)
+ {
+ LL_DEBUGS("LLXMLRPCListener") << "Response contains no data" << LL_ENDL;
+ return LLSD();
+ }
+
+ // Now, parse everything
+ return parseValues(status_string, "", param);
+ }
+
+ /**
+ * Parse key/value pairs from a given XMLRPC_VALUE into an LLSD map.
+ * @param key_pfx Used to describe a given key in log messages. At top
+ * level, pass "". When parsing an options array, pass the top-level key
+ * name of the array plus the index of the array entry; to this we'll
+ * append the subkey of interest.
+ * @param param XMLRPC_VALUE iterator. At top level, pass
+ * XMLRPC_RequestGetData(XMLRPC_REQUEST).
+ */
+ LLSD parseValues(std::string& status_string, const std::string& key_pfx, XMLRPC_VALUE param)
+ {
+ LLSD responses;
+ for (XMLRPC_VALUE current = XMLRPC_VectorRewind(param); current;
+ current = XMLRPC_VectorNext(param))
+ {
+ std::string key(XMLRPC_GetValueID(current));
+ LL_DEBUGS("LLXMLRPCListener") << "key: " << key_pfx << key << LL_ENDL;
+ XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(current);
+ if (xmlrpc_type_string == type)
+ {
+ LLSD::String val(XMLRPC_GetValueString(current));
+ LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL;
+ responses.insert(key, val);
+ }
+ else if (xmlrpc_type_int == type)
+ {
+ LLSD::Integer val(XMLRPC_GetValueInt(current));
+ LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL;
+ responses.insert(key, val);
+ }
+ else if (xmlrpc_type_double == type)
+ {
+ LLSD::Real val(XMLRPC_GetValueDouble(current));
+ LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL;
+ responses.insert(key, val);
+ }
+ else if (xmlrpc_type_array == type)
+ {
+ // We expect this to be an array of submaps. Walk the array,
+ // recursively parsing each submap and collecting them.
+ LLSD array;
+ int i = 0; // for descriptive purposes
+ for (XMLRPC_VALUE row = XMLRPC_VectorRewind(current); row;
+ row = XMLRPC_VectorNext(current), ++i)
+ {
+ // Recursive call. For the lower-level key_pfx, if 'key'
+ // is "foo", pass "foo[0]:", then "foo[1]:", etc. In the
+ // nested call, a subkey "bar" will then be logged as
+ // "foo[0]:bar", and so forth.
+ // Parse the scalar subkey/value pairs from this array
+ // entry into a temp submap. Collect such submaps in 'array'.
+ array.append(parseValues(status_string,
+ STRINGIZE(key_pfx << key << '[' << i << "]:"),
+ row));
+ }
+ // Having collected an 'array' of 'submap's, insert that whole
+ // 'array' as the value of this 'key'.
+ responses.insert(key, array);
+ }
+ else
+ {
+ // whoops - unrecognized type
+ LL_WARNS("LLXMLRPCListener") << "Unhandled xmlrpc type " << type << " for key "
+ << key_pfx << key << LL_ENDL;
+ responses.insert(key, STRINGIZE("<bad XMLRPC type " << type << '>'));
+ status_string = "BadType";
+ }
+ }
+ return responses;
+ }
+
+ const LLReqID mReqID;
+ const std::string mUri;
+ const std::string mMethod;
+ const std::string mReplyPump;
+ LLTempBoundListener mBoundListener;
+ boost::scoped_ptr<LLXMLRPCTransaction> mTransaction;
+ LLXMLRPCTransaction::EStatus mPreviousStatus; // To detect state changes.
+};
+
+bool LLXMLRPCListener::process(const LLSD& command)
+{
+ // Allocate a new heap Poller, but do not save a pointer to it. Poller
+ // will check its own status and free itself on completion of the request.
+ (new Poller(command));
+ // conventional event listener return
+ return false;
+}
diff --git a/indra/newview/llxmlrpclistener.h b/indra/newview/llxmlrpclistener.h
new file mode 100644
index 0000000000..120c2b329b
--- /dev/null
+++ b/indra/newview/llxmlrpclistener.h
@@ -0,0 +1,35 @@
+/**
+ * @file llxmlrpclistener.h
+ * @author Nat Goodspeed
+ * @date 2009-03-18
+ * @brief LLEventPump API for LLXMLRPCTransaction. This header doesn't
+ * actually define the API; the API is defined by the pump name on
+ * which this class listens, and by the expected content of LLSD it
+ * receives.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLXMLRPCLISTENER_H)
+#define LL_LLXMLRPCLISTENER_H
+
+#include "llevents.h"
+
+/// Listen on an LLEventPump with specified name for LLXMLRPCTransaction
+/// request events.
+class LLXMLRPCListener
+{
+public:
+ /// Specify the pump name on which to listen
+ LLXMLRPCListener(const std::string& pumpname);
+
+ /// Handle request events on the event pump specified at construction time
+ bool process(const LLSD& command);
+
+private:
+ LLTempBoundListener mBoundListener;
+};
+
+#endif /* ! defined(LL_LLXMLRPCLISTENER_H) */
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index a2fd0f0d9c..c19be37e75 100644
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -33,6 +33,7 @@
#include "llviewerprecompiledheaders.h"
#include "llxmlrpctransaction.h"
+#include "llxmlrpclistener.h"
#include "llcurl.h"
#include "llviewercontrol.h"
@@ -42,6 +43,13 @@
#include "llappviewer.h"
+// Static instance of LLXMLRPCListener declared here so that every time we
+// bring in this code, we instantiate a listener. If we put the static
+// instance of LLXMLRPCListener into llxmlrpclistener.cpp, the linker would
+// simply omit llxmlrpclistener.o, and shouting on the LLEventPump would do
+// nothing.
+static LLXMLRPCListener listener("LLXMLRPCTransaction");
+
LLXMLRPCValue LLXMLRPCValue::operator[](const char* id) const
{
return LLXMLRPCValue(XMLRPC_VectorGetValueWithID(mV, id));
@@ -150,11 +158,11 @@ XMLRPC_VALUE LLXMLRPCValue::getValue() const
class LLXMLRPCTransaction::Impl
{
public:
- typedef LLXMLRPCTransaction::Status Status;
+ typedef LLXMLRPCTransaction::EStatus EStatus;
LLCurlEasyRequest* mCurlRequest;
- Status mStatus;
+ EStatus mStatus;
CURLcode mCurlCode;
std::string mStatusMessage;
std::string mStatusURI;
@@ -176,7 +184,7 @@ public:
bool process();
- void setStatus(Status code,
+ void setStatus(EStatus code,
const std::string& message = "", const std::string& uri = "");
void setCurlStatus(CURLcode);
@@ -213,6 +221,11 @@ LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
XMLRPC_RequestSetData(request, params.getValue());
init(request, useGzip);
+ // DEV-28398: without this XMLRPC_RequestFree() call, it looks as though
+ // the 'request' object is simply leaked. It's less clear to me whether we
+ // should also ask to free request value data (second param 1), since the
+ // data come from 'params'.
+ XMLRPC_RequestFree(request, 1);
}
@@ -239,9 +252,8 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
// mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // usefull for debugging
mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);
mCurlRequest->setWriteCallback(&curlDownloadCallback, (void*)this);
- BOOL vefifySSLCert = !gSavedSettings.getBOOL("NoVerifySSLCert");
- mCurlRequest->setopt(CURLOPT_SSL_VERIFYPEER, vefifySSLCert);
- mCurlRequest->setopt(CURLOPT_SSL_VERIFYHOST, vefifySSLCert ? 2 : 0);
+ mCurlRequest->setopt(CURLOPT_SSL_VERIFYPEER, LLCurl::getSSLVerify());
+ mCurlRequest->setopt(CURLOPT_SSL_VERIFYHOST, LLCurl::getSSLVerify() ? 2 : 0);
// Be a little impatient about establishing connections.
mCurlRequest->setopt(CURLOPT_CONNECTTIMEOUT, 40L);
@@ -385,7 +397,7 @@ bool LLXMLRPCTransaction::Impl::process()
return false;
}
-void LLXMLRPCTransaction::Impl::setStatus(Status status,
+void LLXMLRPCTransaction::Impl::setStatus(EStatus status,
const std::string& message, const std::string& uri)
{
mStatus = status;
@@ -509,7 +521,7 @@ bool LLXMLRPCTransaction::process()
return impl.process();
}
-LLXMLRPCTransaction::Status LLXMLRPCTransaction::status(int* curlCode)
+LLXMLRPCTransaction::EStatus LLXMLRPCTransaction::status(int* curlCode)
{
if (curlCode)
{
diff --git a/indra/newview/llxmlrpctransaction.h b/indra/newview/llxmlrpctransaction.h
index 528451fcb2..c835423d67 100644
--- a/indra/newview/llxmlrpctransaction.h
+++ b/indra/newview/llxmlrpctransaction.h
@@ -100,7 +100,7 @@ public:
~LLXMLRPCTransaction();
- typedef enum {
+ typedef enum e_status {
StatusNotStarted,
StatusStarted,
StatusDownloading,
@@ -108,12 +108,12 @@ public:
StatusCURLError,
StatusXMLRPCError,
StatusOtherError
- } Status;
+ } EStatus;
bool process();
// run the request a little, returns true when done
- Status status(int* curlCode);
+ EStatus status(int* curlCode);
// return status, and extended CURL code, if code isn't null
std::string statusMessage();
// return a message string, suitable for showing the user
diff --git a/indra/newview/macview_Prefix.h b/indra/newview/macview_Prefix.h
index 8cbabb5103..a71362a139 100644
--- a/indra/newview/macview_Prefix.h
+++ b/indra/newview/macview_Prefix.h
@@ -63,20 +63,16 @@
#include "lldrawable.h"
#include "llfirstuse.h"
#include "llfloater.h"
-#include "llfloateravatarinfo.h"
#include "llfloaterbuildoptions.h"
#include "llfloaterchat.h"
#include "llfloatercustomize.h"
-#include "llfloaterdirectory.h"
#include "llfloatergroups.h"
-#include "llfloatermap.h"
#include "llfloaterworldmap.h"
#include "llfloatermute.h"
#include "llconversation.h"
#include "llfloatertools.h"
#include "llhudeffectlookat.h"
#include "llhudmanager.h"
-#include "llinventoryview.h"
#include "lljoystickbutton.h"
#include "llmenugl.h"
#include "llmorphview.h"
@@ -92,7 +88,6 @@
#include "lltoolgrab.h"
#include "lltoolmgr.h"
#include "lltoolpie.h"
-#include "lltoolview.h"
#include "llui.h" // for make_ui_sound
#include "llviewercamera.h"
#include "llviewermenu.h"
diff --git a/indra/newview/nl.lproj/language.txt b/indra/newview/nl.lproj/language.txt
new file mode 100644
index 0000000000..d5f5c2a19c
--- /dev/null
+++ b/indra/newview/nl.lproj/language.txt
@@ -0,0 +1 @@
+nl \ No newline at end of file
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 8dec9b9ba8..4f4fc83819 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -35,15 +35,15 @@
#include "pipeline.h"
// library includes
-#include "audioengine.h" // For MAX_BUFFERS for debugging.
+#include "llaudioengine.h" // For debugging.
#include "imageids.h"
#include "llerror.h"
#include "llviewercontrol.h"
#include "llfasttimer.h"
#include "llfontgl.h"
-#include "llmemory.h"
#include "llmemtype.h"
#include "llnamevalue.h"
+#include "llpointer.h"
#include "llprimitive.h"
#include "llvolume.h"
#include "material_codes.h"
@@ -52,6 +52,7 @@
#include "llui.h"
#include "llglheaders.h"
#include "llrender.h"
+#include "llwindow.h" // swapBuffers()
// newview includes
#include "llagent.h"
@@ -65,7 +66,7 @@
#include "llface.h"
#include "llfeaturemanager.h"
#include "llfloatertelehub.h"
-#include "llframestats.h"
+#include "llfloaterreg.h"
#include "llgldbg.h"
#include "llhudmanager.h"
#include "lllightconstants.h"
@@ -76,13 +77,13 @@
#include "lltool.h"
#include "lltoolmgr.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewerobject.h"
#include "llviewerobjectlist.h"
#include "llviewerparcelmgr.h"
#include "llviewerregion.h" // for audio debugging.
#include "llviewerwindow.h" // For getSpinAxis
-#include "llvoavatar.h"
+#include "llvoavatarself.h"
#include "llvoground.h"
#include "llvosky.h"
#include "llvotree.h"
@@ -93,14 +94,16 @@
#include "llvopartgroup.h"
#include "llworld.h"
#include "llcubemap.h"
-#include "lldebugmessagebox.h"
#include "llviewershadermgr.h"
+#include "llviewerstats.h"
#include "llviewerjoystick.h"
#include "llviewerdisplay.h"
#include "llwlparammanager.h"
#include "llwaterparammanager.h"
#include "llspatialpartition.h"
#include "llmutelist.h"
+#include "lltoolpie.h"
+
#ifdef _DEBUG
// Debug indices is disabled for now for debug performance - djs 4/24/02
@@ -121,8 +124,7 @@ const U32 REFLECTION_MAP_RES = 128;
const S32 MAX_OCCLUDER_COUNT = 2;
extern S32 gBoxFrame;
-extern BOOL gRenderLightGlows;
-extern BOOL gHideSelectedObjects;
+//extern BOOL gHideSelectedObjects;
extern BOOL gDisplaySwapBuffers;
extern BOOL gDebugGL;
@@ -138,6 +140,35 @@ BOOL gDebugPipeline = FALSE;
LLPipeline gPipeline;
const LLMatrix4* gGLLastMatrix = NULL;
+LLFastTimer::DeclareTimer FTM_RENDER_GEOMETRY("Geometry");
+LLFastTimer::DeclareTimer FTM_RENDER_GRASS("Grass");
+LLFastTimer::DeclareTimer FTM_RENDER_INVISIBLE("Invisible");
+LLFastTimer::DeclareTimer FTM_RENDER_OCCLUSION("Occlusion");
+LLFastTimer::DeclareTimer FTM_RENDER_SHINY("Shiny");
+LLFastTimer::DeclareTimer FTM_RENDER_SIMPLE("Simple");
+LLFastTimer::DeclareTimer FTM_RENDER_TERRAIN("Terrain");
+LLFastTimer::DeclareTimer FTM_RENDER_TREES("Trees");
+LLFastTimer::DeclareTimer FTM_RENDER_UI("UI");
+LLFastTimer::DeclareTimer FTM_RENDER_WATER("Water");
+LLFastTimer::DeclareTimer FTM_RENDER_WL_SKY("Windlight Sky");
+LLFastTimer::DeclareTimer FTM_RENDER_ALPHA("Alpha Objects");
+LLFastTimer::DeclareTimer FTM_RENDER_CHARACTERS("Avatars");
+LLFastTimer::DeclareTimer FTM_RENDER_BUMP("Bump");
+LLFastTimer::DeclareTimer FTM_RENDER_FULLBRIGHT("Fullbright");
+LLFastTimer::DeclareTimer FTM_RENDER_GLOW("Glow");
+LLFastTimer::DeclareTimer FTM_GEO_UPDATE("Geo Update");
+LLFastTimer::DeclareTimer FTM_POOLRENDER("RenderPool");
+LLFastTimer::DeclareTimer FTM_POOLS("Pools");
+LLFastTimer::DeclareTimer FTM_RENDER_BLOOM_FBO("First FBO");
+LLFastTimer::DeclareTimer FTM_STATESORT("Sort Draw State");
+LLFastTimer::DeclareTimer FTM_PIPELINE("Pipeline");
+LLFastTimer::DeclareTimer FTM_CLIENT_COPY("Client Copy");
+LLFastTimer::DeclareTimer FTM_RENDER_DEFERRED("Deferred Shading");
+
+
+static LLFastTimer::DeclareTimer FTM_STATESORT_DRAWABLE("Sort Drawables");
+static LLFastTimer::DeclareTimer FTM_STATESORT_POSTSORT("Post Sort");
+
//----------------------------------------
std::string gPoolNames[] =
{
@@ -159,6 +190,8 @@ std::string gPoolNames[] =
"POOL_ALPHA",
};
+void drawBox(const LLVector3& c, const LLVector3& r);
+
U32 nhpo2(U32 v)
{
U32 r = 1;
@@ -240,7 +273,6 @@ BOOL LLPipeline::sDisableShaders = FALSE;
BOOL LLPipeline::sRenderBump = TRUE;
BOOL LLPipeline::sUseFarClip = TRUE;
BOOL LLPipeline::sShadowRender = FALSE;
-BOOL LLPipeline::sSkipUpdate = FALSE;
BOOL LLPipeline::sWaterReflections = FALSE;
BOOL LLPipeline::sRenderGlow = FALSE;
BOOL LLPipeline::sReflectionRender = FALSE;
@@ -252,6 +284,8 @@ BOOL LLPipeline::sRenderAttachedLights = TRUE;
BOOL LLPipeline::sRenderAttachedParticles = TRUE;
BOOL LLPipeline::sRenderDeferred = FALSE;
S32 LLPipeline::sVisibleLightCount = 0;
+F32 LLPipeline::sMinRenderSize = 0.f;
+
static LLCullResult* sCull = NULL;
@@ -267,11 +301,11 @@ static const U32 gl_cube_face[] =
void validate_framebuffer_object();
+
void addDeferredAttachments(LLRenderTarget& target)
{
- target.addColorAttachment(GL_RGBA16F_ARB); //specular
- target.addColorAttachment(GL_RGBA16F_ARB); //normal+z
- target.addColorAttachment(GL_RGBA16F_ARB); //position
+ target.addColorAttachment(GL_RGBA); //specular
+ target.addColorAttachment(GL_RGBA); //normal+z
}
LLPipeline::LLPipeline() :
@@ -310,14 +344,18 @@ LLPipeline::LLPipeline() :
mWLSkyPool(NULL),
mLightMask(0),
mLightMovingMask(0),
- mLightingDetail(0)
+ mLightingDetail(0),
+ mScreenWidth(0),
+ mScreenHeight(0)
{
mNoiseMap = 0;
+ mTrueNoiseMap = 0;
+ mLightFunc = 0;
}
void LLPipeline::init()
{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_INIT);
sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD");
sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
@@ -337,7 +375,7 @@ void LLPipeline::init()
getPool(LLDrawPool::POOL_BUMP);
getPool(LLDrawPool::POOL_GLOW);
- mTrianglesDrawnStat.reset();
+ LLViewerStats::getInstance()->mTrianglesDrawnStat.reset();
resetFrameStats();
mRenderTypeMask = 0xffffffff; // All render types start on
@@ -362,6 +400,11 @@ void LLPipeline::init()
LLViewerShaderMgr::instance()->setShaders();
stop_glerror();
+
+ for (U32 i = 0; i < 2; ++i)
+ {
+ mSpotLightFade[i] = 1.f;
+ }
}
LLPipeline::~LLPipeline()
@@ -373,6 +416,9 @@ void LLPipeline::cleanup()
{
assertInitialized();
+ mGroupQ1.clear() ;
+ mGroupQ2.clear() ;
+
for(pool_set_t::iterator iter = mPools.begin();
iter != mPools.end(); )
{
@@ -462,40 +508,82 @@ void LLPipeline::destroyGL()
}
}
+static LLFastTimer::DeclareTimer FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture");
void LLPipeline::resizeScreenTexture()
{
+ LLFastTimer ft(FTM_RESIZE_SCREEN_TEXTURE);
if (gPipeline.canUseVertexShaders() && assertInitialized())
{
- GLuint resX = gViewerWindow->getWindowDisplayWidth();
- GLuint resY = gViewerWindow->getWindowDisplayHeight();
+ GLuint resX = gViewerWindow->getWorldViewWidthRaw();
+ GLuint resY = gViewerWindow->getWorldViewHeightRaw();
- U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor");
- if (res_mod > 1 && res_mod < resX && res_mod < resY)
- {
- resX /= res_mod;
- resY /= res_mod;
- }
-
allocateScreenBuffer(resX,resY);
-
- llinfos << "RESIZED SCREEN TEXTURE: " << resX << "x" << resY << llendl;
}
}
void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
{
+ // remember these dimensions
+ mScreenWidth = resX;
+ mScreenHeight = resY;
+
U32 samples = gSavedSettings.getU32("RenderFSAASamples");
+ U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor");
+
+ if (res_mod > 1 && res_mod < resX && res_mod < resY)
+ {
+ resX /= res_mod;
+ resY /= res_mod;
+ }
+
+ if (gSavedSettings.getBOOL("RenderUIBuffer"))
+ {
+ mUIScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+ }
+
if (LLPipeline::sRenderDeferred)
{
//allocate deferred rendering color buffers
- mDeferredScreen.allocate(resX, resY, GL_RGBA16F_ARB, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+ mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+ mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
addDeferredAttachments(mDeferredScreen);
- mScreen.allocate(resX, resY, GL_RGBA16F_ARB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
-
+
+ // always set viewport to desired size, since allocate resets the viewport
+
+ mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+ mEdgeMap.allocate(resX, resY, GL_ALPHA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+
+ for (U32 i = 0; i < 3; i++)
+ {
+ mDeferredLight[i].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+ }
+
for (U32 i = 0; i < 2; i++)
{
- mDeferredLight[i].allocate(resX, resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+ mGIMapPost[i].allocate(resX,resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+ }
+
+ F32 scale = gSavedSettings.getF32("RenderShadowResolutionScale");
+
+ for (U32 i = 0; i < 4; i++)
+ {
+ mShadow[i].allocate(U32(resX*scale),U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
}
+
+
+ U32 width = nhpo2(U32(resX*scale))/2;
+ U32 height = width;
+
+ for (U32 i = 4; i < 6; i++)
+ {
+ mShadow[i].allocate(width, height, 0, TRUE, FALSE);
+ }
+
+
+
+ width = nhpo2(resX)/2;
+ height = nhpo2(resY)/2;
+ mLuminanceMap.allocate(width,height, GL_RGBA, FALSE, FALSE);
}
else
{
@@ -505,25 +593,23 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
if (gGLManager.mHasFramebufferMultisample && samples > 1)
{
+ mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples);
if (LLPipeline::sRenderDeferred)
{
- mSampleBuffer.allocate(resX,resY,GL_RGBA16F_ARB,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples);
addDeferredAttachments(mSampleBuffer);
mDeferredScreen.setSampleBuffer(&mSampleBuffer);
}
- else
- {
- mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples);
- }
mScreen.setSampleBuffer(&mSampleBuffer);
+
stop_glerror();
}
- else if (LLPipeline::sRenderDeferred)
+
+ if (LLPipeline::sRenderDeferred)
{ //share depth buffer between deferred targets
mDeferredScreen.shareDepthBuffer(mScreen);
- for (U32 i = 0; i < 2; i++)
- {
+ for (U32 i = 0; i < 3; i++)
+ { //share stencil buffer with screen space lightmap to stencil out sky
mDeferredScreen.shareDepthBuffer(mDeferredLight[i]);
}
}
@@ -556,17 +642,42 @@ void LLPipeline::releaseGLBuffers()
mNoiseMap = 0;
}
+ if (mTrueNoiseMap)
+ {
+ LLImageGL::deleteTextures(1, &mTrueNoiseMap);
+ mTrueNoiseMap = 0;
+ }
+
+ if (mLightFunc)
+ {
+ LLImageGL::deleteTextures(1, &mLightFunc);
+ mLightFunc = 0;
+ }
+
mWaterRef.release();
mWaterDis.release();
mScreen.release();
+ mUIScreen.release();
mSampleBuffer.releaseSampleBuffer();
mDeferredScreen.release();
+ mDeferredDepth.release();
+ for (U32 i = 0; i < 3; i++)
+ {
+ mDeferredLight[i].release();
+ }
+
+ mEdgeMap.release();
+ mGIMap.release();
+ mGIMapPost[0].release();
+ mGIMapPost[1].release();
+ mHighlight.release();
+ mLuminanceMap.release();
-
- for (U32 i = 0; i < 4; i++)
+ for (U32 i = 0; i < 6; i++)
{
- mSunShadow[i].release();
+ mShadow[i].release();
}
+
for (U32 i = 0; i < 3; i++)
{
mGlow[i].release();
@@ -577,6 +688,7 @@ void LLPipeline::releaseGLBuffers()
void LLPipeline::createGLBuffers()
{
+ LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_CREATE_BUFFERS);
assertInitialized();
updateRenderDeferred();
@@ -589,9 +701,13 @@ void LLPipeline::createGLBuffers()
mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE);
}
+ mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE);
stop_glerror();
+ GLuint resX = gViewerWindow->getWorldViewWidthRaw();
+ GLuint resY = gViewerWindow->getWorldViewHeightRaw();
+
if (LLPipeline::sRenderGlow)
{ //screen space glow buffers
const U32 glow_res = llmax(1,
@@ -601,20 +717,15 @@ void LLPipeline::createGLBuffers()
{
mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE,FALSE);
}
- }
- GLuint resX = gViewerWindow->getWindowDisplayWidth();
- GLuint resY = gViewerWindow->getWindowDisplayHeight();
-
- allocateScreenBuffer(resX,resY);
+ allocateScreenBuffer(resX,resY);
+ mScreenWidth = 0;
+ mScreenHeight = 0;
+ }
+
if (sRenderDeferred)
{
- mSunShadow[0].allocate(1024,1024, 0, TRUE, FALSE);
- mSunShadow[1].allocate(1024,1024, 0, TRUE, FALSE);
- mSunShadow[2].allocate(1024,1024, 0, TRUE, FALSE);
- mSunShadow[3].allocate(1024,1024, 0, TRUE, FALSE);
-
if (!mNoiseMap)
{
const U32 noiseRes = 128;
@@ -634,11 +745,72 @@ void LLPipeline::createGLBuffers()
LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
+
+ if (!mTrueNoiseMap)
+ {
+ const U32 noiseRes = 128;
+ F32 noise[noiseRes*noiseRes*3];
+ for (U32 i = 0; i < noiseRes*noiseRes*3; i++)
+ {
+ noise[i] = ll_frand()*2.0-1.0;
+ }
+
+ LLImageGL::generateTextures(1, &mTrueNoiseMap);
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap);
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
+
+ if (!mLightFunc)
+ {
+ U32 lightResX = gSavedSettings.getU32("RenderSpecularResX");
+ U32 lightResY = gSavedSettings.getU32("RenderSpecularResY");
+ U8* lg = new U8[lightResX*lightResY];
+
+ for (U32 y = 0; y < lightResY; ++y)
+ {
+ for (U32 x = 0; x < lightResX; ++x)
+ {
+ //spec func
+ F32 sa = (F32) x/(lightResX-1);
+ F32 spec = (F32) y/(lightResY-1);
+ //lg[y*lightResX+x] = (U8) (powf(sa, 128.f*spec*spec)*255);
+
+ //F32 sp = acosf(sa)/(1.f-spec);
+
+ sa = powf(sa, gSavedSettings.getF32("RenderSpecularExponent"));
+ F32 a = acosf(sa*0.25f+0.75f);
+ F32 m = llmax(0.5f-spec*0.5f, 0.001f);
+ F32 t2 = tanf(a)/m;
+ t2 *= t2;
+
+ F32 c4a = (3.f+4.f*cosf(2.f*a)+cosf(4.f*a))/8.f;
+ F32 bd = 1.f/(4.f*m*m*c4a)*powf(F_E, -t2);
+
+ lg[y*lightResX+x] = (U8) (llclamp(bd, 0.f, 1.f)*255);
+ }
+ }
+
+ LLImageGL::generateTextures(1, &mLightFunc);
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_ALPHA, lightResX, lightResY, GL_ALPHA, GL_UNSIGNED_BYTE, lg);
+ gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
+
+ delete [] lg;
+ }
+
+ if (gSavedSettings.getBOOL("RenderDeferredGI"))
+ {
+ mGIMap.allocate(512,512,GL_RGBA, TRUE, FALSE);
+ addDeferredAttachments(mGIMap);
+ }
}
}
void LLPipeline::restoreGL()
{
+ LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_RESTORE_GL);
assertInitialized();
if (mVertexShadersEnabled)
@@ -693,6 +865,7 @@ BOOL LLPipeline::canUseWindLightShadersOnObjects() const
void LLPipeline::unloadShaders()
{
+ LLMemType mt_us(LLMemType::MTYPE_PIPELINE_UNLOAD_SHADERS);
LLViewerShaderMgr::instance()->unloadShaders();
mVertexShadersLoaded = 0;
@@ -724,6 +897,7 @@ S32 LLPipeline::getMaxLightingDetail() const
S32 LLPipeline::setLightingDetail(S32 level)
{
+ LLMemType mt_ld(LLMemType::MTYPE_PIPELINE_LIGHTING_DETAIL);
assertInitialized();
if (level < 0)
@@ -748,9 +922,9 @@ S32 LLPipeline::setLightingDetail(S32 level)
class LLOctreeDirtyTexture : public LLOctreeTraveler<LLDrawable>
{
public:
- const std::set<LLViewerImage*>& mTextures;
+ const std::set<LLViewerFetchedTexture*>& mTextures;
- LLOctreeDirtyTexture(const std::set<LLViewerImage*>& textures) : mTextures(textures) { }
+ LLOctreeDirtyTexture(const std::set<LLViewerFetchedTexture*>& textures) : mTextures(textures) { }
virtual void visit(const LLOctreeNode<LLDrawable>* node)
{
@@ -763,7 +937,8 @@ public:
for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
{
LLDrawInfo* params = *j;
- if (mTextures.find(params->mTexture) != mTextures.end())
+ LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(params->mTexture);
+ if (tex && mTextures.find(tex) != mTextures.end())
{
group->setState(LLSpatialGroup::GEOM_DIRTY);
}
@@ -780,7 +955,7 @@ public:
};
// Called when a texture changes # of channels (causes faces to move to alpha pool)
-void LLPipeline::dirtyPoolObjectTextures(const std::set<LLViewerImage*>& textures)
+void LLPipeline::dirtyPoolObjectTextures(const std::set<LLViewerFetchedTexture*>& textures)
{
assertInitialized();
@@ -812,7 +987,7 @@ void LLPipeline::dirtyPoolObjectTextures(const std::set<LLViewerImage*>& texture
}
}
-LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerImage *tex0)
+LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0)
{
assertInitialized();
@@ -884,7 +1059,7 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerImage *tex0)
}
-LLDrawPool *LLPipeline::getPool(const U32 type, LLViewerImage *tex0)
+LLDrawPool *LLPipeline::getPool(const U32 type, LLViewerTexture *tex0)
{
LLMemType mt(LLMemType::MTYPE_PIPELINE);
LLDrawPool *poolp = findPool(type, tex0);
@@ -901,7 +1076,7 @@ LLDrawPool *LLPipeline::getPool(const U32 type, LLViewerImage *tex0)
// static
-LLDrawPool* LLPipeline::getPoolFromTE(const LLTextureEntry* te, LLViewerImage* imagep)
+LLDrawPool* LLPipeline::getPoolFromTE(const LLTextureEntry* te, LLViewerTexture* imagep)
{
LLMemType mt(LLMemType::MTYPE_PIPELINE);
U32 type = getPoolTypeFromTE(te, imagep);
@@ -909,9 +1084,9 @@ LLDrawPool* LLPipeline::getPoolFromTE(const LLTextureEntry* te, LLViewerImage* i
}
//static
-U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerImage* imagep)
+U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* imagep)
{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLMemType mt_gpt(LLMemType::MTYPE_PIPELINE_GET_POOL_TYPE);
if (!te || !imagep)
{
@@ -921,7 +1096,7 @@ U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerImage* image
bool alpha = te->getColor().mV[3] < 0.999f;
if (imagep)
{
- alpha = alpha || (imagep->getComponents() == 4 && ! imagep->mIsMediaTexture) || (imagep->getComponents() == 2);
+ alpha = alpha || (imagep->getComponents() == 4 && imagep->getType() != LLViewerTexture::MEDIA_TEXTURE) || (imagep->getComponents() == 2);
}
if (alpha)
@@ -941,7 +1116,7 @@ U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerImage* image
void LLPipeline::addPool(LLDrawPool *new_poolp)
{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLMemType mt_a(LLMemType::MTYPE_PIPELINE_ADD_POOL);
assertInitialized();
mPools.insert(new_poolp);
addToQuickLookup( new_poolp );
@@ -949,7 +1124,7 @@ void LLPipeline::addPool(LLDrawPool *new_poolp)
void LLPipeline::allocDrawable(LLViewerObject *vobj)
{
- LLMemType mt(LLMemType::MTYPE_DRAWABLE);
+ LLMemType mt_ad(LLMemType::MTYPE_PIPELINE_ALLOCATE_DRAWABLE);
LLDrawable *drawable = new LLDrawable();
vobj->mDrawable = drawable;
@@ -968,7 +1143,7 @@ void LLPipeline::allocDrawable(LLViewerObject *vobj)
void LLPipeline::unlinkDrawable(LLDrawable *drawable)
{
- LLFastTimer t(LLFastTimer::FTM_PIPELINE);
+ LLFastTimer t(FTM_PIPELINE);
assertInitialized();
@@ -1006,10 +1181,36 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable)
break;
}
}
+
+ {
+ HighlightItem item(drawablep);
+ mHighlightSet.erase(item);
+
+ if (mHighlightObject == drawablep)
+ {
+ mHighlightObject = NULL;
+ }
+ }
+
+ for (U32 i = 0; i < 2; ++i)
+ {
+ if (mShadowSpotLight[i] == drawablep)
+ {
+ mShadowSpotLight[i] = NULL;
+ }
+
+ if (mTargetShadowSpotLight[i] == drawablep)
+ {
+ mTargetShadowSpotLight[i] = NULL;
+ }
+ }
+
+
}
U32 LLPipeline::addObject(LLViewerObject *vobj)
{
+ LLMemType mt_ao(LLMemType::MTYPE_PIPELINE_ADD_OBJECT);
if (gNoRender)
{
return 0;
@@ -1029,8 +1230,8 @@ U32 LLPipeline::addObject(LLViewerObject *vobj)
void LLPipeline::createObjects(F32 max_dtime)
{
- LLFastTimer ftm(LLFastTimer::FTM_GEO_UPDATE);
- LLMemType mt(LLMemType::MTYPE_DRAWABLE);
+ LLFastTimer ftm(FTM_GEO_UPDATE);
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_CREATE_OBJECTS);
LLTimer update_timer;
@@ -1093,7 +1294,7 @@ void LLPipeline::resetFrameStats()
{
assertInitialized();
- mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f);
+ LLViewerStats::getInstance()->mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f);
if (mBatchCount > 0)
{
@@ -1195,10 +1396,13 @@ void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list)
}
}
+static LLFastTimer::DeclareTimer FTM_OCTREE_BALANCE("Balance Octree");
+static LLFastTimer::DeclareTimer FTM_UPDATE_MOVE("Update Move");
+
void LLPipeline::updateMove()
{
- LLFastTimer t(LLFastTimer::FTM_UPDATE_MOVE);
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLFastTimer t(FTM_UPDATE_MOVE);
+ LLMemType mt_um(LLMemType::MTYPE_PIPELINE_UPDATE_MOVE);
if (gSavedSettings.getBOOL("FreezeTime"))
{
@@ -1243,7 +1447,7 @@ void LLPipeline::updateMove()
//balance octrees
{
- LLFastTimer ot(LLFastTimer::FTM_OCTREE_BALANCE);
+ LLFastTimer ot(FTM_OCTREE_BALANCE);
for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
@@ -1272,6 +1476,7 @@ F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera
F32 dist = lookAt.length();
//ramp down distance for nearby objects
+ //shrink dist by dist/16.
if (dist < 16.f)
{
dist /= 16.f;
@@ -1282,7 +1487,7 @@ F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera
//get area of circle around node
F32 app_angle = atanf(size.length()/dist);
F32 radius = app_angle*LLDrawable::sCurPixelAngle;
- return radius*radius * 3.14159f;
+ return radius*radius * F_PI;
}
void LLPipeline::grabReferences(LLCullResult& result)
@@ -1321,6 +1526,8 @@ BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3&
min = LLVector3(F32_MAX, F32_MAX, F32_MAX);
max = LLVector3(-F32_MAX, -F32_MAX, -F32_MAX);
+ U32 saved_camera_id = LLViewerCamera::sCurCameraID;
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
BOOL res = TRUE;
@@ -1345,14 +1552,17 @@ BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3&
}
}
+ LLViewerCamera::sCurCameraID = saved_camera_id;
+
return res;
}
+static LLFastTimer::DeclareTimer FTM_CULL("Object Culling");
void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip)
{
- LLFastTimer t(LLFastTimer::FTM_CULL);
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLFastTimer t(FTM_CULL);
+ LLMemType mt_uc(LLMemType::MTYPE_PIPELINE_UPDATE_CULL);
grabReferences(result);
@@ -1360,8 +1570,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
BOOL to_texture = LLPipeline::sUseOcclusion > 1 &&
!hasRenderType(LLPipeline::RENDER_TYPE_HUD) &&
- !sReflectionRender &&
- !sShadowRender &&
+ LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
gPipeline.canUseVertexShaders() &&
sRenderGlow;
@@ -1370,11 +1579,15 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
mScreen.bindTarget();
}
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadMatrixd(gGLLastProjection);
+ glMatrixMode(GL_MODELVIEW);
glPushMatrix();
gGLLastMatrix = NULL;
- //glLoadMatrixd(gGLModelView);
glLoadMatrixd(gGLLastModelView);
+
LLVertexBuffer::unbind();
LLGLDisable blend(GL_BLEND);
LLGLDisable test(GL_ALPHA_TEST);
@@ -1443,6 +1656,9 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
}
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
glPopMatrix();
if (sUseOcclusion > 1)
@@ -1454,10 +1670,6 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
{
mScreen.flush();
}
- else if (LLPipeline::sUseOcclusion > 1)
- {
- glFlush();
- }
}
void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
@@ -1469,7 +1681,7 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
group->setVisible();
- if (!sSkipUpdate)
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
{
group->updateDistance(camera);
}
@@ -1481,6 +1693,12 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
return;
}
+ if (sMinRenderSize > 0.f &&
+ llmax(llmax(group->mBounds[1].mV[0], group->mBounds[1].mV[1]), group->mBounds[1].mV[2]) < sMinRenderSize)
+ {
+ return;
+ }
+
assertInitialized();
if (!group->mSpatialPartition->mRenderByGroup)
@@ -1497,22 +1715,22 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
void LLPipeline::markOccluder(LLSpatialGroup* group)
{
- if (sUseOcclusion > 1 && group && !group->isState(LLSpatialGroup::ACTIVE_OCCLUSION))
+ if (sUseOcclusion > 1 && group && !group->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION))
{
LLSpatialGroup* parent = group->getParent();
- if (!parent || !parent->isState(LLSpatialGroup::OCCLUDED))
+ if (!parent || !parent->isOcclusionState(LLSpatialGroup::OCCLUDED))
{ //only mark top most occluders as active occlusion
sCull->pushOcclusionGroup(group);
- group->setState(LLSpatialGroup::ACTIVE_OCCLUSION);
+ group->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
if (parent &&
- !parent->isState(LLSpatialGroup::ACTIVE_OCCLUSION) &&
+ !parent->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION) &&
parent->getElementCount() == 0 &&
parent->needsUpdate())
{
sCull->pushOcclusionGroup(group);
- parent->setState(LLSpatialGroup::ACTIVE_OCCLUSION);
+ parent->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
}
}
}
@@ -1535,18 +1753,18 @@ void LLPipeline::doOcclusion(LLCamera& camera)
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ LLGLDisable cull(GL_CULL_FACE);
if (LLPipeline::sUseOcclusion > 1)
{
for (LLCullResult::sg_list_t::iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter)
{
LLSpatialGroup* group = *iter;
group->doOcclusion(&camera);
- group->clearState(LLSpatialGroup::ACTIVE_OCCLUSION);
+ group->clearOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
}
}
gGL.setColorMask(true, false);
- glFlush();
}
BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority)
@@ -1560,13 +1778,86 @@ BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority)
return update_complete;
}
-void LLPipeline::updateGeom(F32 max_dtime)
+void LLPipeline::updateGL()
+{
+ while (!LLGLUpdate::sGLQ.empty())
+ {
+ LLGLUpdate* glu = LLGLUpdate::sGLQ.front();
+ glu->updateGL();
+ glu->mInQ = FALSE;
+ LLGLUpdate::sGLQ.pop_front();
+ }
+}
+
+void LLPipeline::rebuildPriorityGroups()
{
LLTimer update_timer;
LLMemType mt(LLMemType::MTYPE_PIPELINE);
+
+ assertInitialized();
+
+ // Iterate through all drawables on the priority build queue,
+ for (LLSpatialGroup::sg_list_t::iterator iter = mGroupQ1.begin();
+ iter != mGroupQ1.end(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ group->rebuildGeom();
+ group->clearState(LLSpatialGroup::IN_BUILD_Q1);
+ }
+
+ mGroupQ1.clear();
+}
+
+void LLPipeline::rebuildGroups()
+{
+ llpushcallstacks ;
+ // Iterate through some drawables on the non-priority build queue
+ S32 size = (S32) mGroupQ2.size();
+ S32 min_count = llclamp((S32) ((F32) (size * size)/4096*0.25f), 1, size);
+
+ S32 count = 0;
+
+ std::sort(mGroupQ2.begin(), mGroupQ2.end(), LLSpatialGroup::CompareUpdateUrgency());
+
+ LLSpatialGroup::sg_vector_t::iterator iter;
+ for (iter = mGroupQ2.begin();
+ iter != mGroupQ2.end(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+
+ if (group->isDead())
+ {
+ continue;
+ }
+
+ group->rebuildGeom();
+
+ if (group->mSpatialPartition->mRenderByGroup)
+ {
+ count++;
+ }
+
+ group->clearState(LLSpatialGroup::IN_BUILD_Q2);
+
+ if (count > min_count)
+ {
+ ++iter;
+ break;
+ }
+ }
+
+ mGroupQ2.erase(mGroupQ2.begin(), iter);
+
+ updateMovedList(mMovedBridge);
+}
+
+void LLPipeline::updateGeom(F32 max_dtime)
+{
+ LLTimer update_timer;
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_UPDATE_GEOM);
LLPointer<LLDrawable> drawablep;
- LLFastTimer t(LLFastTimer::FTM_GEO_UPDATE);
+ LLFastTimer t(FTM_GEO_UPDATE);
assertInitialized();
@@ -1666,7 +1957,7 @@ void LLPipeline::updateGeom(F32 max_dtime)
void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_VISIBLE);
if(!drawablep || drawablep->isDead())
{
return;
@@ -1674,6 +1965,16 @@ void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
if (drawablep->isSpatialBridge())
{
+ LLDrawable* root = ((LLSpatialBridge*) drawablep)->mDrawable;
+
+ if (root && root->getParent() && root->getVObj() && root->getVObj()->isAttachment())
+ {
+ LLVOAvatar* av = root->getParent()->getVObj()->asAvatar();
+ if (av->isImpostor())
+ {
+ return;
+ }
+ }
sCull->pushBridge((LLSpatialBridge*) drawablep);
}
else
@@ -1686,7 +1987,7 @@ void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion)
{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLMemType mt_mm(LLMemType::MTYPE_PIPELINE_MARK_MOVED);
if (!drawablep)
{
@@ -1732,7 +2033,7 @@ void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion)
void LLPipeline::markShift(LLDrawable *drawablep)
{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_SHIFT);
if (!drawablep || drawablep->isDead())
{
@@ -1755,7 +2056,7 @@ void LLPipeline::markShift(LLDrawable *drawablep)
void LLPipeline::shiftObjects(const LLVector3 &offset)
{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_SHIFT_OBJECTS);
assertInitialized();
@@ -1795,7 +2096,7 @@ void LLPipeline::shiftObjects(const LLVector3 &offset)
void LLPipeline::markTextured(LLDrawable *drawablep)
{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_TEXTURED);
if (drawablep && !drawablep->isDead() && assertInitialized())
{
@@ -1803,9 +2104,62 @@ void LLPipeline::markTextured(LLDrawable *drawablep)
}
}
-void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag, BOOL priority)
+void LLPipeline::markGLRebuild(LLGLUpdate* glu)
+{
+ if (glu && !glu->mInQ)
+ {
+ LLGLUpdate::sGLQ.push_back(glu);
+ glu->mInQ = TRUE;
+ }
+}
+
+void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority)
{
LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ //assert_main_thread();
+
+ if (group && !group->isDead() && group->mSpatialPartition)
+ {
+ if (group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_HUD)
+ {
+ priority = TRUE;
+ }
+
+ if (priority)
+ {
+ if (!group->isState(LLSpatialGroup::IN_BUILD_Q1))
+ {
+ mGroupQ1.push_back(group);
+ group->setState(LLSpatialGroup::IN_BUILD_Q1);
+
+ if (group->isState(LLSpatialGroup::IN_BUILD_Q2))
+ {
+ LLSpatialGroup::sg_vector_t::iterator iter = std::find(mGroupQ2.begin(), mGroupQ2.end(), group);
+ if (iter != mGroupQ2.end())
+ {
+ mGroupQ2.erase(iter);
+ }
+ group->clearState(LLSpatialGroup::IN_BUILD_Q2);
+ }
+ }
+ }
+ else if (!group->isState(LLSpatialGroup::IN_BUILD_Q2 | LLSpatialGroup::IN_BUILD_Q1))
+ {
+ //llerrs << "Non-priority updates not yet supported!" << llendl;
+ if (std::find(mGroupQ2.begin(), mGroupQ2.end(), group) != mGroupQ2.end())
+ {
+ llerrs << "WTF?" << llendl;
+ }
+ mGroupQ2.push_back(group);
+ group->setState(LLSpatialGroup::IN_BUILD_Q2);
+
+ }
+ }
+}
+
+void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag, BOOL priority)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_REBUILD);
if (drawablep && !drawablep->isDead() && assertInitialized())
{
@@ -1834,6 +2188,8 @@ void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags f
}
}
+static LLFastTimer::DeclareTimer FTM_RESET_DRAWORDER("Reset Draw Order");
+
void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
{
const U32 face_mask = (1 << LLPipeline::RENDER_TYPE_AVATAR) |
@@ -1846,59 +2202,59 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
if (mRenderTypeMask & face_mask)
{
//clear faces from face pools
- LLFastTimer t(LLFastTimer::FTM_RESET_DRAWORDER);
+ LLFastTimer t(FTM_RESET_DRAWORDER);
gPipeline.resetDrawOrders();
}
- LLFastTimer ftm(LLFastTimer::FTM_STATESORT);
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLFastTimer ftm(FTM_STATESORT);
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
//LLVertexBuffer::unbind();
grabReferences(result);
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
{
- for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
+ LLSpatialGroup* group = *iter;
+ group->checkOcclusion();
+ if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED))
{
- LLSpatialGroup* group = *iter;
- group->checkOcclusion();
- if (sUseOcclusion && group->isState(LLSpatialGroup::OCCLUDED))
- {
- markOccluder(group);
- }
- else
+ markOccluder(group);
+ }
+ else
+ {
+ group->setVisible();
+ for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
{
- group->setVisible();
- for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
- {
- markVisible(*i, camera);
- }
+ markVisible(*i, camera);
}
}
+ }
- for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ group->checkOcclusion();
+ if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED))
{
- LLSpatialGroup* group = *iter;
- group->checkOcclusion();
- if (sUseOcclusion && group->isState(LLSpatialGroup::OCCLUDED))
- {
- markOccluder(group);
- }
- else
- {
- group->setVisible();
- stateSort(group, camera);
- }
+ markOccluder(group);
+ }
+ else
+ {
+ group->setVisible();
+ stateSort(group, camera);
}
}
+
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
{
for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
{
LLCullResult::bridge_list_t::iterator cur_iter = i;
LLSpatialBridge* bridge = *cur_iter;
LLSpatialGroup* group = bridge->getSpatialGroup();
- if (!bridge->isDead() && group && !group->isState(LLSpatialGroup::OCCLUDED))
+ if (!bridge->isDead() && group && !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
{
stateSort(bridge, camera);
}
@@ -1906,7 +2262,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
}
{
- LLFastTimer ftm(LLFastTimer::FTM_STATESORT_DRAWABLE);
+ LLFastTimer ftm(FTM_STATESORT_DRAWABLE);
for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList();
iter != sCull->endVisibleList(); ++iter)
{
@@ -1919,7 +2275,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
}
{
- LLFastTimer ftm(LLFastTimer::FTM_CLIENT_COPY);
+ LLFastTimer ftm(FTM_CLIENT_COPY);
LLVertexBuffer::clientCopy();
}
@@ -1928,8 +2284,8 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
- if (!sSkipUpdate && group->changeLOD())
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
+ if (group->changeLOD())
{
for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
{
@@ -1942,16 +2298,17 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera)
{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
- if (!sSkipUpdate && bridge->getSpatialGroup()->changeLOD())
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
+ if (!sShadowRender && bridge->getSpatialGroup()->changeLOD())
{
- bridge->updateDistance(camera);
+ bool force_update = false;
+ bridge->updateDistance(camera, force_update);
}
}
void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
if (!drawablep
|| drawablep->isDead()
@@ -1960,7 +2317,7 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
return;
}
- if (gHideSelectedObjects)
+ if (LLSelectMgr::getInstance()->mHideSelectedObjects)
{
if (drawablep->getVObj().notNull() &&
drawablep->getVObj()->isSelected())
@@ -1999,39 +2356,48 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
}
}
- LLSpatialGroup* group = drawablep->getSpatialGroup();
- if (!group || group->changeLOD())
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
{
- if (drawablep->isVisible() && !sSkipUpdate)
+ LLSpatialGroup* group = drawablep->getSpatialGroup();
+ if (!group || group->changeLOD())
{
- if (!drawablep->isActive())
+ if (drawablep->isVisible())
{
- drawablep->updateDistance(camera);
+ if (!drawablep->isActive())
+ {
+ bool force_update = false;
+ drawablep->updateDistance(camera, force_update);
+ }
+ else if (drawablep->isAvatar())
+ {
+ bool force_update = false;
+ drawablep->updateDistance(camera, force_update); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility()
+ }
}
- else if (drawablep->isAvatar())
- {
- drawablep->updateDistance(camera); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility()
- }
}
}
- for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin();
- iter != drawablep->mFaces.end(); iter++)
+ if (!drawablep->getVOVolume())
{
- LLFace* facep = *iter;
-
- if (facep->hasGeometry())
+ for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin();
+ iter != drawablep->mFaces.end(); iter++)
{
- if (facep->getPool())
- {
- facep->getPool()->enqueue(facep);
- }
- else
+ LLFace* facep = *iter;
+
+ if (facep->hasGeometry())
{
- break;
+ if (facep->getPool())
+ {
+ facep->getPool()->enqueue(facep);
+ }
+ else
+ {
+ break;
+ }
}
}
}
+
mNumVisibleFaces += drawablep->getNumFaces();
}
@@ -2178,8 +2544,8 @@ void renderSoundHighlights(LLDrawable* drawablep)
void LLPipeline::postSort(LLCamera& camera)
{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
- LLFastTimer ftm(LLFastTimer::FTM_STATESORT_POSTSORT);
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_POST_SORT);
+ LLFastTimer ftm(FTM_STATESORT_POSTSORT);
assertInitialized();
@@ -2188,7 +2554,7 @@ void LLPipeline::postSort(LLCamera& camera)
{
LLSpatialGroup* group = *i;
if (!sUseOcclusion ||
- !group->isState(LLSpatialGroup::OCCLUDED))
+ !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
{
group->rebuildGeom();
}
@@ -2197,7 +2563,7 @@ void LLPipeline::postSort(LLCamera& camera)
//rebuild groups
sCull->assertDrawMapsEmpty();
- LLSpatialGroup::sNoDelete = FALSE;
+ /*LLSpatialGroup::sNoDelete = FALSE;
for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
{
LLSpatialGroup* group = *i;
@@ -2209,9 +2575,11 @@ void LLPipeline::postSort(LLCamera& camera)
group->rebuildGeom();
}
- LLSpatialGroup::sNoDelete = TRUE;
+ LLSpatialGroup::sNoDelete = TRUE;*/
+ rebuildPriorityGroups();
+
const S32 bin_count = 1024*8;
static LLCullResult::drawinfo_list_t alpha_bins[bin_count];
@@ -2232,42 +2600,65 @@ void LLPipeline::postSort(LLCamera& camera)
{
LLSpatialGroup* group = *i;
if (sUseOcclusion &&
- group->isState(LLSpatialGroup::OCCLUDED))
+ group->isOcclusionState(LLSpatialGroup::OCCLUDED))
{
continue;
}
-
+
+ if (group->isState(LLSpatialGroup::NEW_DRAWINFO) && group->isState(LLSpatialGroup::GEOM_DIRTY))
+ { //no way this group is going to be drawable without a rebuild
+ group->rebuildGeom();
+ }
+
for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j)
{
LLSpatialGroup::drawmap_elem_t& src_vec = j->second;
-
- for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k)
+ if (!hasRenderType(j->first))
{
- sCull->pushDrawInfo(j->first, *k);
+ continue;
}
- }
-
- LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
-
- if (alpha != group->mDrawMap.end())
- { //store alpha groups for sorting
- LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
- if (!sSkipUpdate)
+
+ for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k)
{
- if (bridge)
+ if (sMinRenderSize > 0.f)
{
- LLCamera trans_camera = bridge->transformCamera(camera);
- group->updateDistance(trans_camera);
+ LLVector3 bounds = (*k)->mExtents[1]-(*k)->mExtents[0];
+ if (llmax(llmax(bounds.mV[0], bounds.mV[1]), bounds.mV[2]) > sMinRenderSize)
+ {
+ sCull->pushDrawInfo(j->first, *k);
+ }
}
else
{
- group->updateDistance(camera);
+ sCull->pushDrawInfo(j->first, *k);
}
}
+ }
+
+ if (hasRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA))
+ {
+ LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
- if (hasRenderType(LLDrawPool::POOL_ALPHA))
- {
- sCull->pushAlphaGroup(group);
+ if (alpha != group->mDrawMap.end())
+ { //store alpha groups for sorting
+ LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ {
+ if (bridge)
+ {
+ LLCamera trans_camera = bridge->transformCamera(camera);
+ group->updateDistance(trans_camera);
+ }
+ else
+ {
+ group->updateDistance(camera);
+ }
+ }
+
+ if (hasRenderType(LLDrawPool::POOL_ALPHA))
+ {
+ sCull->pushAlphaGroup(group);
+ }
}
}
}
@@ -2291,7 +2682,7 @@ void LLPipeline::postSort(LLCamera& camera)
}
// only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus
- if (gSavedSettings.getBOOL("BeaconAlwaysOn") && !sShadowRender)
+ if (LLFloaterReg::instanceVisible("beacons") && !sShadowRender)
{
if (sRenderScriptedTouchBeacons)
{
@@ -2366,13 +2757,14 @@ void LLPipeline::postSort(LLCamera& camera)
}
}
- LLSpatialGroup::sNoDelete = FALSE;
+ //LLSpatialGroup::sNoDelete = FALSE;
}
void render_hud_elements()
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_UI);
+ LLMemType mt_rhe(LLMemType::MTYPE_PIPELINE_RENDER_HUD_ELS);
+ LLFastTimer t(FTM_RENDER_UI);
gPipeline.disableLights();
LLGLDisable fog(GL_FOG);
@@ -2416,7 +2808,7 @@ void render_hud_elements()
void LLPipeline::renderHighlights()
{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_RENDER_HL);
assertInitialized();
@@ -2427,6 +2819,103 @@ void LLPipeline::renderHighlights()
LLGLEnable color_mat(GL_COLOR_MATERIAL);
disableLights();
+ if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD) && !mHighlightSet.empty())
+ { //draw blurry highlight image over screen
+ LLGLEnable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ LLGLDisable test(GL_ALPHA_TEST);
+
+ LLGLEnable stencil(GL_STENCIL_TEST);
+ gGL.flush();
+ glStencilMask(0xFFFFFFFF);
+ glClearStencil(1);
+ glClear(GL_STENCIL_BUFFER_BIT);
+
+ glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF);
+ glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+
+ gGL.setColorMask(false, false);
+ for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); ++iter)
+ {
+ renderHighlight(iter->mItem->getVObj(), 1.f);
+ }
+ gGL.setColorMask(true, false);
+
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF);
+
+ //gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
+
+ gGL.pushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ gGL.pushMatrix();
+ glLoadIdentity();
+
+ gGL.getTexUnit(0)->bind(&mHighlight);
+
+ LLVector2 tc1;
+ LLVector2 tc2;
+
+ tc1.setVec(0,0);
+ tc2.setVec(2,2);
+
+ gGL.begin(LLRender::TRIANGLES);
+
+ F32 scale = gSavedSettings.getF32("RenderHighlightBrightness");
+ LLColor4 color = gSavedSettings.getColor4("RenderHighlightColor");
+ F32 thickness = gSavedSettings.getF32("RenderHighlightThickness");
+
+ for (S32 pass = 0; pass < 2; ++pass)
+ {
+ if (pass == 0)
+ {
+ gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
+ }
+ else
+ {
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ }
+
+ for (S32 i = 0; i < 8; ++i)
+ {
+ for (S32 j = 0; j < 8; ++j)
+ {
+ LLVector2 tc(i-4+0.5f, j-4+0.5f);
+
+ F32 dist = 1.f-(tc.length()/sqrtf(32.f));
+ dist *= scale/64.f;
+
+ tc *= thickness;
+ tc.mV[0] = (tc.mV[0])/mHighlight.getWidth();
+ tc.mV[1] = (tc.mV[1])/mHighlight.getHeight();
+
+ gGL.color4f(color.mV[0],
+ color.mV[1],
+ color.mV[2],
+ color.mV[3]*dist);
+
+ gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc2.mV[1]);
+ gGL.vertex2f(-1,3);
+
+ gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc1.mV[1]);
+ gGL.vertex2f(-1,-1);
+
+ gGL.texCoord2f(tc.mV[0]+tc2.mV[0], tc.mV[1]+tc1.mV[1]);
+ gGL.vertex2f(3,-1);
+ }
+ }
+ }
+
+ gGL.end();
+
+ gGL.popMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ gGL.popMatrix();
+
+ //gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ }
+
if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
{
gHighlightProgram.bind();
@@ -2438,7 +2927,7 @@ void LLPipeline::renderHighlights()
// Make sure the selection image gets downloaded and decoded
if (!mFaceSelectImagep)
{
- mFaceSelectImagep = gImageList.getImage(IMG_FACE_SELECT);
+ mFaceSelectImagep = LLViewerTextureManager::getFetchedTexture(IMG_FACE_SELECT);
}
mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA);
@@ -2468,7 +2957,7 @@ void LLPipeline::renderHighlights()
for (S32 i = 0; i < count; i++)
{
LLFace* facep = mHighlightFaces[i];
- facep->renderSelected(LLViewerImage::sNullImagep, color);
+ facep->renderSelected(LLViewerTexture::sNullImagep, color);
}
}
@@ -2484,8 +2973,8 @@ void LLPipeline::renderHighlights()
void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
- LLFastTimer t(LLFastTimer::FTM_RENDER_GEOMETRY);
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_RENDER_GEOM);
+ LLFastTimer t(FTM_RENDER_GEOMETRY);
assertInitialized();
@@ -2509,7 +2998,6 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
//
stop_glerror();
- gFrameStats.start(LLFrameStats::RENDER_SYNC);
LLVertexBuffer::unbind();
@@ -2527,16 +3015,6 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
LLAppViewer::instance()->pingMainloopTimeout("Pipeline:ForceVBO");
- //by bao
- //fake vertex buffer updating
- //to guaranttee at least updating one VBO buffer every frame
- //to walk around the bug caused by ATI card --> DEV-3855
- //
- if(forceVBOUpdate)
- gSky.mVOSkyp->updateDummyVertexBuffer() ;
-
- gFrameStats.start(LLFrameStats::RENDER_GEOM);
-
// Initialize lots of GL state to "safe" values
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
@@ -2559,8 +3037,8 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
sUnderWaterRender = FALSE;
}
- gGL.getTexUnit(0)->bind(LLViewerImage::sDefaultImagep);
- LLViewerImage::sDefaultImagep->setAddressMode(LLTexUnit::TAM_WRAP);
+ gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sDefaultImagep);
+ LLViewerFetchedTexture::sDefaultImagep->setAddressMode(LLTexUnit::TAM_WRAP);
//////////////////////////////////////////////
//
@@ -2570,9 +3048,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
stop_glerror();
LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPools");
-
- LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderForSelect");
- LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDeferred");
+
for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
{
LLDrawPool *poolp = *iter;
@@ -2584,11 +3060,12 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PICKING))
{
- gObjectList.renderObjectsForSelect(camera, gViewerWindow->getVirtualWindowRect());
+ LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderForSelect");
+ gObjectList.renderObjectsForSelect(camera, gViewerWindow->getWindowRectScaled());
}
else
{
- LLFastTimer t(LLFastTimer::FTM_POOLS);
+ LLFastTimer t(FTM_POOLS);
// HACK: don't calculate local lights if we're rendering the HUD!
// Removing this check will cause bad flickering when there are
@@ -2620,7 +3097,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
pool_set_t::iterator iter2 = iter1;
if (hasRenderType(poolp->getType()) && poolp->getNumPasses() > 0)
{
- LLFastTimer t(LLFastTimer::FTM_POOLRENDER);
+ LLFastTimer t(FTM_POOLRENDER);
gGLLastMatrix = NULL;
glLoadMatrixd(gGLModelView);
@@ -2647,6 +3124,10 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
if (depth > 3)
{
+ if (gDebugSession)
+ {
+ ll_fail("GL matrix stack corrupted.");
+ }
llerrs << "GL matrix stack corrupted!" << llendl;
}
std::string msg = llformat("%s pass %d", gPoolNames[cur_type].c_str(), i);
@@ -2747,9 +3228,12 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
void LLPipeline::renderGeomDeferred(LLCamera& camera)
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_GEOMETRY);
+ LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred");
+
+ LLMemType mt_rgd(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED);
+ LLFastTimer t(FTM_RENDER_GEOMETRY);
- LLFastTimer t2(LLFastTimer::FTM_POOLS);
+ LLFastTimer t2(FTM_POOLS);
LLGLEnable cull(GL_CULL_FACE);
@@ -2791,7 +3275,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera)
pool_set_t::iterator iter2 = iter1;
if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0)
{
- LLFastTimer t(LLFastTimer::FTM_POOLRENDER);
+ LLFastTimer t(FTM_POOLRENDER);
gGLLastMatrix = NULL;
glLoadMatrixd(gGLModelView);
@@ -2813,15 +3297,18 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera)
poolp->endDeferredPass(i);
LLVertexBuffer::unbind();
- GLint depth;
- glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
- if (depth > 3)
+ if (gDebugGL || gDebugPipeline)
{
- llerrs << "GL matrix stack corrupted!" << llendl;
+ GLint depth;
+ glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
+ if (depth > 3)
+ {
+ llerrs << "GL matrix stack corrupted!" << llendl;
+ }
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
}
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
}
}
else
@@ -2848,7 +3335,8 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera)
void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
{
- LLFastTimer t(LLFastTimer::FTM_POOLS);
+ LLMemType mt_rgpd(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_POST_DEF);
+ LLFastTimer t(FTM_POOLS);
U32 cur_type = 0;
LLGLEnable cull(GL_CULL_FACE);
@@ -2881,7 +3369,7 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
pool_set_t::iterator iter2 = iter1;
if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0)
{
- LLFastTimer t(LLFastTimer::FTM_POOLRENDER);
+ LLFastTimer t(FTM_POOLRENDER);
gGLLastMatrix = NULL;
glLoadMatrixd(gGLModelView);
@@ -2903,15 +3391,18 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
poolp->endPostDeferredPass(i);
LLVertexBuffer::unbind();
- GLint depth;
- glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
- if (depth > 3)
+ if (gDebugGL || gDebugPipeline)
{
- llerrs << "GL matrix stack corrupted!" << llendl;
+ GLint depth;
+ glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
+ if (depth > 3)
+ {
+ llerrs << "GL matrix stack corrupted!" << llendl;
+ }
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
}
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
}
}
else
@@ -2959,6 +3450,7 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
void LLPipeline::renderGeomShadow(LLCamera& camera)
{
+ LLMemType mt_rgs(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_SHADOW);
U32 cur_type = 0;
LLGLEnable cull(GL_CULL_FACE);
@@ -3070,7 +3562,7 @@ void LLPipeline::renderDebug()
for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
{
LLSpatialBridge* bridge = *i;
- if (!bridge->isDead() && !bridge->isState(LLSpatialGroup::OCCLUDED) && hasRenderType(bridge->mDrawableType))
+ if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
{
glPushMatrix();
glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
@@ -3081,79 +3573,91 @@ void LLPipeline::renderDebug()
if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
{
+ LLGLEnable blend(GL_BLEND);
+ LLGLDepthTest depth(TRUE, FALSE);
+ LLGLDisable cull(GL_CULL_FACE);
+
gGL.color4f(1,1,1,1);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ F32 a = 0.1f;
+
F32 col[] =
{
- 1,1,0,
- 0,1,1,
- 1,0,1,
- 1,1,1,
- 1,0,0,
- 0,1,0,
- 0,0,1,
- 0,0,0
+ 1,0,0,a,
+ 0,1,0,a,
+ 0,0,1,a,
+ 1,0,1,a,
+
+ 1,1,0,a,
+ 0,1,1,a,
+ 1,1,1,a,
+ 1,0,1,a,
};
for (U32 i = 0; i < 8; i++)
{
- gGL.color3fv(col+i*3);
-
- gGL.begin(LLRender::LINES);
-
- LLVector3* frust = mShadowCamera[i].mAgentFrustum;
-
- gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[1].mV);
- gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[2].mV);
- gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[3].mV);
- gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[0].mV);
-
- gGL.vertex3fv(frust[4].mV); gGL.vertex3fv(frust[5].mV);
- gGL.vertex3fv(frust[5].mV); gGL.vertex3fv(frust[6].mV);
- gGL.vertex3fv(frust[6].mV); gGL.vertex3fv(frust[7].mV);
- gGL.vertex3fv(frust[7].mV); gGL.vertex3fv(frust[4].mV);
-
- gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
- gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV);
- gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV);
- gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV);
+ if (i > 3)
+ {
+ gGL.color4fv(col+(i-4)*4);
+ LLVector3* frust = mShadowCamera[i].mAgentFrustum;
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
+ gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV);
+ gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV);
+ gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV);
+ gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
+ gGL.end();
+
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.vertex3fv(frust[0].mV);
+ gGL.vertex3fv(frust[1].mV);
+ gGL.vertex3fv(frust[3].mV);
+ gGL.vertex3fv(frust[2].mV);
+ gGL.end();
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.vertex3fv(frust[4].mV);
+ gGL.vertex3fv(frust[5].mV);
+ gGL.vertex3fv(frust[7].mV);
+ gGL.vertex3fv(frust[6].mV);
+ gGL.end();
+ }
+
+
if (i < 4)
{
- LLVector3* ext = mShadowExtents[i];
+ gGL.begin(LLRender::LINES);
- LLVector3 box[] =
+ F32* c = col+i*4;
+ for (U32 j = 0; j < mShadowFrustPoints[i].size(); ++j)
{
- LLVector3(ext[0][0], ext[0][1], ext[0][2]),
- LLVector3(ext[1][0], ext[0][1], ext[0][2]),
- LLVector3(ext[1][0], ext[1][1], ext[0][2]),
- LLVector3(ext[0][0], ext[1][1], ext[0][2]),
- LLVector3(ext[0][0], ext[0][1], ext[1][2]),
- LLVector3(ext[1][0], ext[0][1], ext[1][2]),
- LLVector3(ext[1][0], ext[1][1], ext[1][2]),
- LLVector3(ext[0][0], ext[1][1], ext[1][2]),
- };
- gGL.vertex3fv(box[0].mV); gGL.vertex3fv(box[1].mV);
- gGL.vertex3fv(box[1].mV); gGL.vertex3fv(box[2].mV);
- gGL.vertex3fv(box[2].mV); gGL.vertex3fv(box[3].mV);
- gGL.vertex3fv(box[3].mV); gGL.vertex3fv(box[0].mV);
-
- gGL.vertex3fv(box[4].mV); gGL.vertex3fv(box[5].mV);
- gGL.vertex3fv(box[5].mV); gGL.vertex3fv(box[6].mV);
- gGL.vertex3fv(box[6].mV); gGL.vertex3fv(box[7].mV);
- gGL.vertex3fv(box[7].mV); gGL.vertex3fv(box[4].mV);
-
- gGL.vertex3fv(box[0].mV); gGL.vertex3fv(box[4].mV);
- gGL.vertex3fv(box[1].mV); gGL.vertex3fv(box[5].mV);
- gGL.vertex3fv(box[2].mV); gGL.vertex3fv(box[6].mV);
- gGL.vertex3fv(box[3].mV); gGL.vertex3fv(box[7].mV);
+ gGL.color3fv(c);
+
+ for (U32 k = 0; k < mShadowFrustPoints[i].size(); ++k)
+ {
+ if (j != k)
+ {
+ gGL.vertex3fv(mShadowFrustPoints[i][j].mV);
+ gGL.vertex3fv(mShadowFrustPoints[i][k].mV);
+ }
+ }
+
+ if (!mShadowFrustOrigin[i].isExactlyZero())
+ {
+ gGL.vertex3fv(mShadowFrustPoints[i][j].mV);
+ gGL.color4f(1,1,1,1);
+ gGL.vertex3fv(mShadowFrustOrigin[i].mV);
+ }
+ }
+ gGL.end();
}
- gGL.end();
-
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ /*for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
{
LLViewerRegion* region = *iter;
@@ -3168,7 +3672,7 @@ void LLPipeline::renderDebug()
}
}
}
- }
+ }*/
}
}
@@ -3205,6 +3709,55 @@ void LLPipeline::renderDebug()
}
}
+ if (mRenderDebugMask & LLPipeline::RENDER_DEBUG_BUILD_QUEUE)
+ {
+ U32 count = 0;
+ U32 size = mBuildQ2.size();
+ LLColor4 col;
+
+ LLGLEnable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
+
+ for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ2.begin(); iter != mGroupQ2.end(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ if (group->isDead())
+ {
+ continue;
+ }
+
+ LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
+
+ if (bridge && (!bridge->mDrawable || bridge->mDrawable->isDead()))
+ {
+ continue;
+ }
+
+ if (bridge)
+ {
+ gGL.pushMatrix();
+ glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
+ }
+
+ F32 alpha = (F32) (size-count)/size;
+
+
+ LLVector2 c(1.f-alpha, alpha);
+ c.normVec();
+
+
+ ++count;
+ col.set(c.mV[0], c.mV[1], 0, alpha*0.5f+0.1f);
+ group->drawObjectBox(col);
+
+ if (bridge)
+ {
+ gGL.popMatrix();
+ }
+ }
+ }
+
gGL.flush();
}
@@ -3215,12 +3768,13 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects, BOOL render
gGL.setColorMask(true, false);
gPipeline.resetDrawOrders();
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
for (std::set<LLViewerObject*>::iterator iter = objects.begin(); iter != objects.end(); ++iter)
{
- stateSort((*iter)->mDrawable, *LLViewerCamera::getInstance());
+ stateSort((*iter)->mDrawable, *camera);
}
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_RENDER_SELECT);
@@ -3295,7 +3849,7 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects, BOOL render
LLDrawable* drawable = vobj->mDrawable;
if (vobj->isDead() ||
vobj->isHUDAttachment() ||
- (gHideSelectedObjects && vobj->isSelected()) ||
+ (LLSelectMgr::getInstance()->mHideSelectedObjects && vobj->isSelected()) ||
drawable->isDead() ||
!hasRenderType(drawable->getRenderType()))
{
@@ -3324,44 +3878,48 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects, BOOL render
iter != avatarp->mAttachmentPoints.end(); )
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachmentp = curiter->second;
- if (attachmentp->getIsHUDAttachment())
+ LLViewerJointAttachment* attachment = curiter->second;
+ if (attachment->getIsHUDAttachment())
{
- LLViewerObject* objectp = attachmentp->getObject();
- if (objectp)
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- LLDrawable* drawable = objectp->mDrawable;
- if (drawable->isDead())
- {
- continue;
- }
-
- for (S32 j = 0; j < drawable->getNumFaces(); ++j)
+ if (LLViewerObject* attached_object = (*attachment_iter))
{
- LLFace* facep = drawable->getFace(j);
- if (!facep->getPool())
+ LLDrawable* drawable = attached_object->mDrawable;
+ if (drawable->isDead())
{
- facep->renderForSelect(prim_mask);
+ continue;
}
- }
-
- //render child faces
- LLViewerObject::const_child_list_t& child_list = objectp->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
- {
- LLViewerObject* child = *iter;
- LLDrawable* child_drawable = child->mDrawable;
- for (S32 l = 0; l < child_drawable->getNumFaces(); ++l)
+
+ for (S32 j = 0; j < drawable->getNumFaces(); ++j)
{
- LLFace* facep = child_drawable->getFace(l);
+ LLFace* facep = drawable->getFace(j);
if (!facep->getPool())
{
facep->renderForSelect(prim_mask);
}
}
+
+ //render child faces
+ LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
+ for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
+ iter != child_list.end(); iter++)
+ {
+ LLViewerObject* child = *iter;
+ LLDrawable* child_drawable = child->mDrawable;
+ for (S32 l = 0; l < child_drawable->getNumFaces(); ++l)
+ {
+ LLFace* facep = child_drawable->getFace(l);
+ if (!facep->getPool())
+ {
+ facep->renderForSelect(prim_mask);
+ }
+ }
+ }
}
- }
+ }
}
}
@@ -3385,7 +3943,7 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects, BOOL render
void LLPipeline::rebuildPools()
{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_REBUILD_POOLS);
assertInitialized();
@@ -3425,7 +3983,7 @@ void LLPipeline::rebuildPools()
void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_QUICK_LOOKUP);
assertInitialized();
@@ -3741,7 +4299,7 @@ void LLPipeline::setupAvatarLights(BOOL for_edit)
}
}
F32 backlight_mag;
- if (gSky.getSunDirection().mV[2] >= NIGHTTIME_ELEVATION_COS)
+ if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS)
{
backlight_mag = BACKLIGHT_DAY_MAGNITUDE_OBJECT;
}
@@ -3823,37 +4381,34 @@ void LLPipeline::calcNearbyLights(LLCamera& camera)
F32 max_dist = LIGHT_MAX_RADIUS * 4.f; // ignore enitrely lights > 4 * max light rad
// UPDATE THE EXISTING NEARBY LIGHTS
- if (!LLPipeline::sSkipUpdate)
+ light_set_t cur_nearby_lights;
+ for (light_set_t::iterator iter = mNearbyLights.begin();
+ iter != mNearbyLights.end(); iter++)
{
- light_set_t cur_nearby_lights;
- for (light_set_t::iterator iter = mNearbyLights.begin();
- iter != mNearbyLights.end(); iter++)
+ const Light* light = &(*iter);
+ LLDrawable* drawable = light->drawable;
+ LLVOVolume* volight = drawable->getVOVolume();
+ if (!volight || !drawable->isState(LLDrawable::LIGHT))
{
- const Light* light = &(*iter);
- LLDrawable* drawable = light->drawable;
- LLVOVolume* volight = drawable->getVOVolume();
- if (!volight || !drawable->isState(LLDrawable::LIGHT))
- {
- drawable->clearState(LLDrawable::NEARBY_LIGHT);
- continue;
- }
- if (light->fade <= -LIGHT_FADE_TIME)
- {
- drawable->clearState(LLDrawable::NEARBY_LIGHT);
- continue;
- }
- if (!sRenderAttachedLights && volight && volight->isAttachment())
- {
- drawable->clearState(LLDrawable::NEARBY_LIGHT);
- continue;
- }
-
- F32 dist = calc_light_dist(volight, cam_pos, max_dist);
- cur_nearby_lights.insert(Light(drawable, dist, light->fade));
+ drawable->clearState(LLDrawable::NEARBY_LIGHT);
+ continue;
}
- mNearbyLights = cur_nearby_lights;
+ if (light->fade <= -LIGHT_FADE_TIME)
+ {
+ drawable->clearState(LLDrawable::NEARBY_LIGHT);
+ continue;
+ }
+ if (!sRenderAttachedLights && volight && volight->isAttachment())
+ {
+ drawable->clearState(LLDrawable::NEARBY_LIGHT);
+ continue;
+ }
+
+ F32 dist = calc_light_dist(volight, cam_pos, max_dist);
+ cur_nearby_lights.insert(Light(drawable, dist, light->fade));
}
-
+ mNearbyLights = cur_nearby_lights;
+
// FIND NEW LIGHTS THAT ARE IN RANGE
light_set_t new_nearby_lights;
for (LLDrawable::drawable_set_t::iterator iter = mLights.begin();
@@ -3930,7 +4485,7 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
// Light 0 = Sun or Moon (All objects)
{
- if (gSky.getSunDirection().mV[2] >= NIGHTTIME_ELEVATION_COS)
+ if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS)
{
mSunDir.setVec(gSky.getSunDirection());
mSunDiffuse.setVec(gSky.getSunDiffuseColor());
@@ -4096,18 +4651,21 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
void LLPipeline::enableLights(U32 mask)
{
assertInitialized();
+
if (mLightingDetail == 0)
{
mask &= 0xf003; // sun and backlight only (and fullbright bit)
}
if (mLightMask != mask)
{
+ stop_glerror();
if (!mLightMask)
{
glEnable(GL_LIGHTING);
}
if (mask)
{
+ stop_glerror();
for (S32 i=0; i<8; i++)
{
if (mask & (1<<i))
@@ -4121,14 +4679,17 @@ void LLPipeline::enableLights(U32 mask)
glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, LLColor4::black.mV);
}
}
+ stop_glerror();
}
else
{
glDisable(GL_LIGHTING);
}
+ stop_glerror();
mLightMask = mask;
LLColor4 ambient = gSky.getTotalAmbientColor();
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient.mV);
+ stop_glerror();
}
}
@@ -4871,6 +5432,7 @@ void LLPipeline::resetVertexBuffers()
void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture)
{
+ LLMemType mt_ro(LLMemType::MTYPE_PIPELINE_RENDER_OBJECTS);
assertInitialized();
glLoadMatrixd(gGLModelView);
gGLLastMatrix = NULL;
@@ -4957,8 +5519,10 @@ void LLPipeline::bindScreenToTexture()
}
+static LLFastTimer::DeclareTimer FTM_RENDER_BLOOM("Bloom");
void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
{
+ LLMemType mt_ru(LLMemType::MTYPE_PIPELINE_RENDER_BLOOM);
if (!(gPipeline.canUseVertexShaders() &&
sRenderGlow))
{
@@ -4979,8 +5543,8 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor");
LLVector2 tc1(0,0);
- LLVector2 tc2((F32) gViewerWindow->getWindowDisplayWidth()*2,
- (F32) gViewerWindow->getWindowDisplayHeight()*2);
+ LLVector2 tc2((F32) gViewerWindow->getWorldViewWidthRaw()*2,
+ (F32) gViewerWindow->getWorldViewHeightRaw()*2);
if (res_mod > 1)
{
@@ -4989,7 +5553,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
gGL.setColorMask(true, true);
- LLFastTimer ftm(LLFastTimer::FTM_RENDER_BLOOM);
+ LLFastTimer ftm(FTM_RENDER_BLOOM);
gGL.color4f(1,1,1,1);
LLGLDepthTest depth(GL_FALSE);
LLGLDisable blend(GL_BLEND);
@@ -5064,7 +5628,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
{
{
- LLFastTimer ftm(LLFastTimer::FTM_RENDER_BLOOM_FBO);
+ LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
mGlow[2].bindTarget();
mGlow[2].clear();
}
@@ -5112,8 +5676,6 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
tc1.setVec(0,0);
tc2.setVec(2,2);
-
-
// power of two between 1 and 1024
U32 glowResPow = gSavedSettings.getS32("RenderGlowResolutionPow");
const U32 glow_res = llmax(1,
@@ -5136,7 +5698,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
{
- LLFastTimer ftm(LLFastTimer::FTM_RENDER_BLOOM_FBO);
+ LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
mGlow[i%2].bindTarget();
mGlow[i%2].clear();
}
@@ -5178,21 +5740,50 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
if (LLRenderTarget::sUseFBO)
{
- LLFastTimer ftm(LLFastTimer::FTM_RENDER_BLOOM_FBO);
+ LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
- gViewerWindow->setupViewport();
+ gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+ gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+ gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+ gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+ glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+
+ tc2.setVec((F32) gViewerWindow->getWorldViewWidthRaw(),
+ (F32) gViewerWindow->getWorldViewHeightRaw());
gGL.flush();
+ LLVertexBuffer::unbind();
+
+ if (LLPipeline::sRenderDeferred && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
{
- LLVertexBuffer::unbind();
+ LLGLDisable blend(GL_BLEND);
+ bindDeferredShader(gDeferredGIFinalProgram);
+ S32 channel = gDeferredGIFinalProgram.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE);
+ if (channel > -1)
+ {
+ mScreen.bindTexture(0, channel);
+ }
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1,-1);
+
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1,3);
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3,-1);
- tc2.setVec((F32) gViewerWindow->getWindowDisplayWidth(),
- (F32) gViewerWindow->getWindowDisplayHeight());
+ gGL.end();
+
+ unbindDeferredShader(gDeferredGIFinalProgram);
+ }
+ else
+ {
if (res_mod > 1)
{
@@ -5233,7 +5824,8 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
gGL.getTexUnit(0)->bind(&mGlow[1]);
gGL.getTexUnit(1)->activate();
gGL.getTexUnit(1)->enable(LLTexUnit::TT_RECT_TEXTURE);
-
+
+
//tex unit 1
gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR);
@@ -5252,6 +5844,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
}
+
gGL.setSceneBlendType(LLRender::BT_ALPHA);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
@@ -5265,46 +5858,194 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
}
-void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index)
+void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRenderTarget* gi_source, LLRenderTarget* last_gi_post, U32 noise_map)
{
+ if (noise_map == 0xFFFFFFFF)
+ {
+ noise_map = mNoiseMap;
+ }
+
+ LLGLState::checkTextureChannels();
+
shader.bind();
S32 channel = 0;
channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE);
if (channel > -1)
{
mDeferredScreen.bindTexture(0,channel);
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE);
if (channel > -1)
{
mDeferredScreen.bindTexture(1, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE);
if (channel > -1)
{
mDeferredScreen.bindTexture(2, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
- channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE);
+ if (gi_source)
+ {
+ BOOL has_gi = FALSE;
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_DIFFUSE);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ gi_source->bindTexture(0, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_SPECULAR);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ gi_source->bindTexture(1, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_NORMAL);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ gi_source->bindTexture(2, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_MIN_POS);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ gi_source->bindTexture(1, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_MAX_POS);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ gi_source->bindTexture(3, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_DIFFUSE);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ last_gi_post->bindTexture(0, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_NORMAL);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ last_gi_post->bindTexture(2, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MAX_POS);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ last_gi_post->bindTexture(1, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MIN_POS);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ last_gi_post->bindTexture(3, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_DEPTH);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ gGL.getTexUnit(channel)->bind(gi_source, TRUE);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ stop_glerror();
+
+ glTexParameteri(LLTexUnit::getInternalType(mGIMap.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
+ glTexParameteri(LLTexUnit::getInternalType(mGIMap.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);
+
+ stop_glerror();
+ }
+
+ if (has_gi)
+ {
+ F32 range_x = llmin(mGIRange.mV[0], 1.f);
+ F32 range_y = llmin(mGIRange.mV[1], 1.f);
+
+ LLVector2 scale(range_x,range_y);
+
+ LLVector2 kern[25];
+
+ for (S32 i = 0; i < 5; ++i)
+ {
+ for (S32 j = 0; j < 5; ++j)
+ {
+ S32 idx = i*5+j;
+ kern[idx].mV[0] = (i-2)*0.5f;
+ kern[idx].mV[1] = (j-2)*0.5f;
+ kern[idx].scaleVec(scale);
+ }
+ }
+
+ shader.uniform2fv("gi_kern", 25, (F32*) kern);
+ shader.uniformMatrix4fv("gi_mat", 1, FALSE, mGIMatrix.m);
+ shader.uniformMatrix4fv("gi_mat_proj", 1, FALSE, mGIMatrixProj.m);
+ shader.uniformMatrix4fv("gi_inv_proj", 1, FALSE, mGIInvProj.m);
+ shader.uniformMatrix4fv("gi_norm_mat", 1, FALSE, mGINormalMatrix.m);
+ }
+ }
+
+ /*channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE);
if (channel > -1)
{
mDeferredScreen.bindTexture(3, channel);
- }
+ }*/
channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE);
if (channel > -1)
{
- gGL.getTexUnit(channel)->bind(&mDeferredScreen, TRUE);
+ gGL.getTexUnit(channel)->bind(&mDeferredDepth, TRUE);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ stop_glerror();
+
+ glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
+ glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);
+
+ stop_glerror();
+
+ glh::matrix4f projection = glh_get_current_projection();
+ glh::matrix4f inv_proj = projection.inverse();
+
+ shader.uniformMatrix4fv("inv_proj", 1, FALSE, inv_proj.m);
+ shader.uniform4f("viewport", (F32) gGLViewport[0],
+ (F32) gGLViewport[1],
+ (F32) gGLViewport[2],
+ (F32) gGLViewport[3]);
}
channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NOISE);
if (channel > -1)
{
- gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap);
+ gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, noise_map);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LIGHTFUNC);
+ if (channel > -1)
+ {
+ gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
}
stop_glerror();
@@ -5313,19 +6054,81 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index)
if (channel > -1)
{
mDeferredLight[light_index].bindTexture(0, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LUMINANCE);
+ if (channel > -1)
+ {
+ gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLuminanceMap.getTexture(), true);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_BLOOM);
+ if (channel > -1)
+ {
+ mGlow[1].bindTexture(0, channel);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+ if (channel > -1)
+ {
+ gi_source->bindTexture(0, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_EDGE, LLTexUnit::TT_RECT_TEXTURE);
+ if (channel > -1)
+ {
+ mEdgeMap.bindTexture(0, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SUN_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+ if (channel > -1)
+ {
+ mDeferredLight[1].bindTexture(0, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LOCAL_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+ if (channel > -1)
+ {
+ mDeferredLight[2].bindTexture(0, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
+
stop_glerror();
for (U32 i = 0; i < 4; i++)
{
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE);
+ stop_glerror();
+ if (channel > -1)
+ {
+ stop_glerror();
+ gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+ stop_glerror();
+
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
+ stop_glerror();
+ }
+ }
+
+ for (U32 i = 4; i < 6; i++)
+ {
channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i);
stop_glerror();
if (channel > -1)
{
stop_glerror();
- gGL.getTexUnit(channel)->bind(&mSunShadow[i], TRUE);
+ gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE);
gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
stop_glerror();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
@@ -5336,17 +6139,19 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index)
stop_glerror();
- F32 mat[64];
+ F32 mat[16*6];
for (U32 i = 0; i < 16; i++)
{
mat[i] = mSunShadowMatrix[0].m[i];
mat[i+16] = mSunShadowMatrix[1].m[i];
mat[i+32] = mSunShadowMatrix[2].m[i];
mat[i+48] = mSunShadowMatrix[3].m[i];
+ mat[i+64] = mSunShadowMatrix[4].m[i];
+ mat[i+80] = mSunShadowMatrix[5].m[i];
}
- shader.uniformMatrix4fv("shadow_matrix[0]", 4, FALSE, mat);
- shader.uniformMatrix4fv("shadow_matrix", 4, FALSE, mat);
+ shader.uniformMatrix4fv("shadow_matrix[0]", 6, FALSE, mat);
+ shader.uniformMatrix4fv("shadow_matrix", 6, FALSE, mat);
stop_glerror();
@@ -5395,7 +6200,44 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index)
shader.uniform2f("screen_res", mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
shader.uniform1f("near_clip", LLViewerCamera::getInstance()->getNear()*2.f);
shader.uniform1f("alpha_soften", gSavedSettings.getF32("RenderDeferredAlphaSoften"));
-}
+ shader.uniform1f ("shadow_offset", gSavedSettings.getF32("RenderShadowOffset"));
+ shader.uniform1f("shadow_bias", gSavedSettings.getF32("RenderShadowBias"));
+ shader.uniform1f("lum_scale", gSavedSettings.getF32("RenderLuminanceScale"));
+ shader.uniform1f("sun_lum_scale", gSavedSettings.getF32("RenderSunLuminanceScale"));
+ shader.uniform1f("sun_lum_offset", gSavedSettings.getF32("RenderSunLuminanceOffset"));
+ shader.uniform1f("lum_lod", gSavedSettings.getF32("RenderLuminanceDetail"));
+ shader.uniform1f("gi_range", gSavedSettings.getF32("RenderGIRange"));
+ shader.uniform1f("gi_brightness", gSavedSettings.getF32("RenderGIBrightness"));
+ shader.uniform1f("gi_luminance", gSavedSettings.getF32("RenderGILuminance"));
+ shader.uniform1f("gi_edge_weight", gSavedSettings.getF32("RenderGIBlurEdgeWeight"));
+ shader.uniform1f("gi_blur_brightness", gSavedSettings.getF32("RenderGIBlurBrightness"));
+ shader.uniform1f("gi_sample_width", mGILightRadius);
+ shader.uniform1f("gi_noise", gSavedSettings.getF32("RenderGINoise"));
+ shader.uniform1f("gi_attenuation", gSavedSettings.getF32("RenderGIAttenuation"));
+ shader.uniform1f("gi_ambiance", gSavedSettings.getF32("RenderGIAmbiance"));
+ shader.uniform2f("shadow_res", mShadow[0].getWidth(), mShadow[0].getHeight());
+ shader.uniform2f("proj_shadow_res", mShadow[4].getWidth(), mShadow[4].getHeight());
+ shader.uniform1f("depth_cutoff", gSavedSettings.getF32("RenderEdgeDepthCutoff"));
+ shader.uniform1f("norm_cutoff", gSavedSettings.getF32("RenderEdgeNormCutoff"));
+
+ if (shader.getUniformLocation("norm_mat") >= 0)
+ {
+ glh::matrix4f norm_mat = glh_get_current_modelview().inverse().transpose();
+ shader.uniformMatrix4fv("norm_mat", 1, FALSE, norm_mat.m);
+ }
+}
+
+static LLFastTimer::DeclareTimer FTM_GI_TRACE("Trace");
+static LLFastTimer::DeclareTimer FTM_GI_GATHER("Gather");
+static LLFastTimer::DeclareTimer FTM_SUN_SHADOW("Shadow Map");
+static LLFastTimer::DeclareTimer FTM_SOFTEN_SHADOW("Shadow Soften");
+static LLFastTimer::DeclareTimer FTM_EDGE_DETECTION("Find Edges");
+static LLFastTimer::DeclareTimer FTM_LOCAL_LIGHTS("Local Lights");
+static LLFastTimer::DeclareTimer FTM_ATMOSPHERICS("Atmospherics");
+static LLFastTimer::DeclareTimer FTM_FULLSCREEN_LIGHTS("Fullscreen Lights");
+static LLFastTimer::DeclareTimer FTM_PROJECTORS("Projectors");
+static LLFastTimer::DeclareTimer FTM_POST("Post");
+
void LLPipeline::renderDeferredLighting()
{
@@ -5404,335 +6246,675 @@ void LLPipeline::renderDeferredLighting()
return;
}
- LLGLEnable multisample(GL_MULTISAMPLE_ARB);
-
- if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
{
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
- }
-
- //ati doesn't seem to love actually using the stencil buffer on FBO's
- LLGLEnable stencil(GL_STENCIL_TEST);
- glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ LLFastTimer ftm(FTM_RENDER_DEFERRED);
- gGL.setColorMask(true, true);
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
+ {
+ LLGLDepthTest depth(GL_TRUE);
+ mDeferredDepth.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
+ 0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+ }
- mDeferredLight[0].bindTarget();
+ LLGLEnable multisample(GL_MULTISAMPLE_ARB);
- //mDeferredLight[0].copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
- // 0, 0, mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
-
- //draw a cube around every light
- LLVertexBuffer::unbind();
+ if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+ {
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+ }
- glBlendFunc(GL_ONE, GL_ONE);
- LLGLEnable cull(GL_CULL_FACE);
- LLGLEnable blend(GL_BLEND);
+ //ati doesn't seem to love actually using the stencil buffer on FBO's
+ LLGLEnable stencil(GL_STENCIL_TEST);
+ glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- glh::matrix4f mat = glh_copy_matrix(gGLModelView);
+ gGL.setColorMask(true, true);
+
+ //draw a cube around every light
+ LLVertexBuffer::unbind();
- F32 vert[] =
- {
- -1,1,
- -1,-3,
- 3,1,
- };
+ LLGLEnable cull(GL_CULL_FACE);
+ LLGLEnable blend(GL_BLEND);
- bindDeferredShader(gDeferredSunProgram);
+ glh::matrix4f mat = glh_copy_matrix(gGLModelView);
- glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose();
+ F32 vert[] =
+ {
+ -1,1,
+ -1,-3,
+ 3,1,
+ };
+ glVertexPointer(2, GL_FLOAT, 0, vert);
+ glColor3f(1,1,1);
- const U32 slice = 32;
- F32 offset[slice*3];
- for (U32 i = 0; i < 4; i++)
- {
- for (U32 j = 0; j < 8; j++)
{
- glh::vec3f v;
- v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i);
- v.normalize();
- inv_trans.mult_matrix_vec(v);
- v.normalize();
- offset[(i*8+j)*3+0] = v.v[0];
- offset[(i*8+j)*3+1] = v.v[2];
- offset[(i*8+j)*3+2] = v.v[1];
+ setupHWLights(NULL); //to set mSunDir;
+ LLVector4 dir(mSunDir, 0.f);
+ glh::vec4f tc(dir.mV);
+ mat.mult_matrix_vec(tc);
+ glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], 0);
}
- }
- gDeferredSunProgram.uniform3fv("offset", slice, offset);
- gDeferredSunProgram.uniform2f("screenRes", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight());
-
- setupHWLights(NULL); //to set mSunDir;
+ if (gSavedSettings.getBOOL("RenderDeferredShadow"))
+ {
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
+ mDeferredLight[0].bindTarget();
+ if (gSavedSettings.getBOOL("RenderDeferredSun"))
+ { //paint shadow/SSAO light map (direct lighting lightmap)
+ LLFastTimer ftm(FTM_SUN_SHADOW);
+ bindDeferredShader(gDeferredSunProgram, 0);
- LLVector4 dir(mSunDir, 0.f);
+ glClearColor(1,1,1,1);
+ mDeferredLight[0].clear(GL_COLOR_BUFFER_BIT);
+ glClearColor(0,0,0,0);
- glh::vec4f tc(dir.mV);
- mat.mult_matrix_vec(tc);
- glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], 0);
- glColor3f(1,1,1);
+ glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose();
- glVertexPointer(2, GL_FLOAT, 0, vert);
- {
- LLGLDisable blend(GL_BLEND);
- LLGLDepthTest depth(GL_FALSE);
- stop_glerror();
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
- stop_glerror();
- }
-
- unbindDeferredShader(gDeferredSunProgram);
+ const U32 slice = 32;
+ F32 offset[slice*3];
+ for (U32 i = 0; i < 4; i++)
+ {
+ for (U32 j = 0; j < 8; j++)
+ {
+ glh::vec3f v;
+ v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i);
+ v.normalize();
+ inv_trans.mult_matrix_vec(v);
+ v.normalize();
+ offset[(i*8+j)*3+0] = v.v[0];
+ offset[(i*8+j)*3+1] = v.v[2];
+ offset[(i*8+j)*3+2] = v.v[1];
+ }
+ }
- mDeferredLight[0].flush();
+ gDeferredSunProgram.uniform3fv("offset", slice, offset);
+ gDeferredSunProgram.uniform2f("screenRes", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight());
+
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ stop_glerror();
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ stop_glerror();
+ }
+
+ unbindDeferredShader(gDeferredSunProgram);
+ }
+ else
+ {
+ mDeferredLight[0].clear(GL_COLOR_BUFFER_BIT);
+ }
- //blur lightmap
- mDeferredLight[1].bindTarget();
+ mDeferredLight[0].flush();
- //mDeferredLight[1].copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
- // 0, 0, mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
-
- bindDeferredShader(gDeferredBlurLightProgram);
+ if (gSavedSettings.getBOOL("RenderDeferredBlurLight") &&
+ gSavedSettings.getBOOL("RenderDeferredGI"))
+ {
+ LLFastTimer ftm(FTM_EDGE_DETECTION);
+ //get edge map
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable test(GL_ALPHA_TEST);
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLDisable stencil(GL_STENCIL_TEST);
- LLVector3 gauss[32]; // xweight, yweight, offset
+ {
+ gDeferredEdgeProgram.bind();
+ mEdgeMap.bindTarget();
+ bindDeferredShader(gDeferredEdgeProgram);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ unbindDeferredShader(gDeferredEdgeProgram);
+ mEdgeMap.flush();
+ }
+ }
- LLVector3 go = gSavedSettings.getVector3("RenderShadowGaussian");
- U32 kern_length = llclamp(gSavedSettings.getU32("RenderShadowBlurSamples"), (U32) 1, (U32) 16)*2 - 1;
- F32 blur_size = gSavedSettings.getF32("RenderShadowBlurSize");
+ if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
+ {
+ { //get luminance map from previous frame's light map
+ LLGLEnable blend(GL_BLEND);
+ LLGLDisable test(GL_ALPHA_TEST);
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLDisable stencil(GL_STENCIL_TEST);
- // sample symmetrically with the middle sample falling exactly on 0.0
- F32 x = -(kern_length/2.0f) + 0.5f;
+ //static F32 fade = 1.f;
- for (U32 i = 0; i < kern_length; i++)
- {
- gauss[i].mV[0] = llgaussian(x, go.mV[0]);
- gauss[i].mV[1] = llgaussian(x, go.mV[1]);
- gauss[i].mV[2] = x;
- x += 1.f;
- }
- /* swap the x=0 position to the start of gauss[] so we can
- treat it specially as an optimization. */
- LLVector3 swap;
- swap = gauss[kern_length/2];
- gauss[kern_length/2] = gauss[0];
- gauss[0] = swap;
- llassert(gauss[0].mV[2] == 0.0f);
+ {
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ gLuminanceGatherProgram.bind();
+ gLuminanceGatherProgram.uniform2f("screen_res", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight());
+ mLuminanceMap.bindTarget();
+ bindDeferredShader(gLuminanceGatherProgram);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ unbindDeferredShader(gLuminanceGatherProgram);
+ mLuminanceMap.flush();
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLuminanceMap.getTexture(), true);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
+ glGenerateMipmapEXT(GL_TEXTURE_2D);
+ }
+ }
- gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f);
- gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV);
- gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV);
- gDeferredBlurLightProgram.uniform1i("kern_length", kern_length);
- gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f));
+ { //paint noisy GI map (bounce lighting lightmap)
+ LLFastTimer ftm(FTM_GI_TRACE);
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLDisable test(GL_ALPHA_TEST);
- {
- LLGLDisable blend(GL_BLEND);
- LLGLDepthTest depth(GL_FALSE);
- stop_glerror();
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
- stop_glerror();
- }
-
- mDeferredLight[1].flush();
- unbindDeferredShader(gDeferredBlurLightProgram);
+ mGIMapPost[0].bindTarget();
- bindDeferredShader(gDeferredBlurLightProgram, 1);
- mDeferredLight[0].bindTarget();
+ bindDeferredShader(gDeferredGIProgram, 0, &mGIMap, 0, mTrueNoiseMap);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ unbindDeferredShader(gDeferredGIProgram);
+ mGIMapPost[0].flush();
+ }
- gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f);
- gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV);
- gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV);
- gDeferredBlurLightProgram.uniform1i("kern_length", kern_length);
- gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f));
+ U32 pass_count = 0;
+ if (gSavedSettings.getBOOL("RenderDeferredBlurLight"))
+ {
+ pass_count = llclamp(gSavedSettings.getU32("RenderGIBlurPasses"), (U32) 1, (U32) 128);
+ }
- {
- LLGLDisable blend(GL_BLEND);
- LLGLDepthTest depth(GL_FALSE);
- stop_glerror();
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- stop_glerror();
- }
- mDeferredLight[0].flush();
- unbindDeferredShader(gDeferredBlurLightProgram);
+ for (U32 i = 0; i < pass_count; ++i)
+ { //gather/soften indirect lighting map
+ LLFastTimer ftm(FTM_GI_GATHER);
+ bindDeferredShader(gDeferredPostGIProgram, 0, &mGIMapPost[0], NULL, mTrueNoiseMap);
+ F32 blur_size = gSavedSettings.getF32("RenderGIBlurSize")/((F32) i * gSavedSettings.getF32("RenderGIBlurIncrement")+1.f);
+ gDeferredPostGIProgram.uniform2f("delta", 1.f, 0.f);
+ gDeferredPostGIProgram.uniform1f("kern_scale", blur_size);
+ gDeferredPostGIProgram.uniform1f("gi_blur_brightness", gSavedSettings.getF32("RenderGIBlurBrightness"));
+
+ mGIMapPost[1].bindTarget();
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_FALSE);
+ stop_glerror();
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ stop_glerror();
+ }
+
+ mGIMapPost[1].flush();
+ unbindDeferredShader(gDeferredPostGIProgram);
+ bindDeferredShader(gDeferredPostGIProgram, 0, &mGIMapPost[1], NULL, mTrueNoiseMap);
+ mGIMapPost[0].bindTarget();
- stop_glerror();
- glPopMatrix();
- stop_glerror();
- glMatrixMode(GL_MODELVIEW);
- stop_glerror();
- glPopMatrix();
- stop_glerror();
+ gDeferredPostGIProgram.uniform2f("delta", 0.f, 1.f);
- //copy depth and stencil from deferred screen
- //mScreen.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
- // 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_FALSE);
+ stop_glerror();
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ stop_glerror();
+ }
+ mGIMapPost[0].flush();
+ unbindDeferredShader(gDeferredPostGIProgram);
+ }
+ }
- mScreen.bindTarget();
- mScreen.clear(GL_COLOR_BUFFER_BIT);
-
- bindDeferredShader(gDeferredSoftenProgram);
- {
- LLGLDepthTest depth(GL_FALSE);
- LLGLDisable blend(GL_BLEND);
- LLGLDisable test(GL_ALPHA_TEST);
+ if (gSavedSettings.getBOOL("RenderDeferredBlurLight"))
+ { //soften direct lighting lightmap
+ LLFastTimer ftm(FTM_SOFTEN_SHADOW);
+ //blur lightmap
+ mDeferredLight[1].bindTarget();
- //full screen blit
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
+ glClearColor(1,1,1,1);
+ mDeferredLight[1].clear(GL_COLOR_BUFFER_BIT);
+ glClearColor(0,0,0,0);
+
+ bindDeferredShader(gDeferredBlurLightProgram);
- glVertexPointer(2, GL_FLOAT, 0, vert);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
-
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- }
+ LLVector3 go = gSavedSettings.getVector3("RenderShadowGaussian");
+ const U32 kern_length = 4;
+ F32 blur_size = gSavedSettings.getF32("RenderShadowBlurSize");
+ F32 dist_factor = gSavedSettings.getF32("RenderShadowBlurDistFactor");
- unbindDeferredShader(gDeferredSoftenProgram);
+ // sample symmetrically with the middle sample falling exactly on 0.0
+ F32 x = 0.f;
- bindDeferredShader(gDeferredLightProgram);
+ LLVector3 gauss[32]; // xweight, yweight, offset
- std::list<LLVector4> fullscreen_lights;
- std::list<LLVector4> light_colors;
+ for (U32 i = 0; i < kern_length; i++)
+ {
+ gauss[i].mV[0] = llgaussian(x, go.mV[0]);
+ gauss[i].mV[1] = llgaussian(x, go.mV[1]);
+ gauss[i].mV[2] = x;
+ x += 1.f;
+ }
- F32 v[24];
- glVertexPointer(3, GL_FLOAT, 0, v);
- {
- LLGLDepthTest depth(GL_TRUE, GL_FALSE);
- for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter)
- {
- LLDrawable* drawablep = *iter;
+ gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f);
+ gDeferredBlurLightProgram.uniform1f("dist_factor", dist_factor);
+ gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV);
+ gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV);
+ gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f));
- LLVOVolume* volume = drawablep->getVOVolume();
- if (!volume)
- {
- continue;
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ stop_glerror();
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ stop_glerror();
+ }
+
+ mDeferredLight[1].flush();
+ unbindDeferredShader(gDeferredBlurLightProgram);
+
+ bindDeferredShader(gDeferredBlurLightProgram, 1);
+ mDeferredLight[0].bindTarget();
+
+ gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f);
+
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ stop_glerror();
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ stop_glerror();
+ }
+ mDeferredLight[0].flush();
+ unbindDeferredShader(gDeferredBlurLightProgram);
}
- LLVector3 center = drawablep->getPositionAgent();
- F32* c = center.mV;
- F32 s = volume->getLightRadius()*1.5f;
+ stop_glerror();
+ glPopMatrix();
+ stop_glerror();
+ glMatrixMode(GL_MODELVIEW);
+ stop_glerror();
+ glPopMatrix();
+ stop_glerror();
+ }
- if (LLViewerCamera::getInstance()->AABBInFrustumNoFarClip(center, LLVector3(s,s,s)) == 0)
+ //copy depth and stencil from deferred screen
+ //mScreen.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
+ // 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
+
+ if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
+ {
+ mDeferredLight[1].bindTarget();
+ mDeferredLight[1].clear(GL_COLOR_BUFFER_BIT);
+ }
+ else
+ {
+ mScreen.bindTarget();
+ mScreen.clear(GL_COLOR_BUFFER_BIT);
+ }
+
+ if (gSavedSettings.getBOOL("RenderDeferredAtmospheric"))
+ { //apply sunlight contribution
+ LLFastTimer ftm(FTM_ATMOSPHERICS);
+ bindDeferredShader(gDeferredSoftenProgram, 0, &mGIMapPost[0]);
{
- continue;
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable test(GL_ALPHA_TEST);
+
+ //full screen blit
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glVertexPointer(2, GL_FLOAT, 0, vert);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
}
- sVisibleLightCount++;
- glh::vec3f tc(c);
- mat.mult_matrix_vec(tc);
+ unbindDeferredShader(gDeferredSoftenProgram);
+ }
+
+ { //render sky
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable stencil(GL_STENCIL_TEST);
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
+ U32 render_mask = mRenderTypeMask;
+ mRenderTypeMask = mRenderTypeMask &
+ ((1 << LLPipeline::RENDER_TYPE_SKY) |
+ (1 << LLPipeline::RENDER_TYPE_CLOUDS) |
+ (1 << LLPipeline::RENDER_TYPE_WL_SKY));
+
- LLColor3 col = volume->getLightColor();
- col *= volume->getLightIntensity();
-
- //vertex positions are encoded so the 3 bits of their vertex index
- //correspond to their axis facing, with bit position 3,2,1 matching
- //axis facing x,y,z, bit set meaning positive facing, bit clear
- //meaning negative facing
- v[0] = c[0]-s; v[1] = c[1]-s; v[2] = c[2]-s; // 0 - 0000
- v[3] = c[0]-s; v[4] = c[1]-s; v[5] = c[2]+s; // 1 - 0001
- v[6] = c[0]-s; v[7] = c[1]+s; v[8] = c[2]-s; // 2 - 0010
- v[9] = c[0]-s; v[10] = c[1]+s; v[11] = c[2]+s; // 3 - 0011
-
- v[12] = c[0]+s; v[13] = c[1]-s; v[14] = c[2]-s; // 4 - 0100
- v[15] = c[0]+s; v[16] = c[1]-s; v[17] = c[2]+s; // 5 - 0101
- v[18] = c[0]+s; v[19] = c[1]+s; v[20] = c[2]-s; // 6 - 0110
- v[21] = c[0]+s; v[22] = c[1]+s; v[23] = c[2]+s; // 7 - 0111
-
- if (LLViewerCamera::getInstance()->getOrigin().mV[0] > c[0] + s + 0.2f ||
- LLViewerCamera::getInstance()->getOrigin().mV[0] < c[0] - s - 0.2f ||
- LLViewerCamera::getInstance()->getOrigin().mV[1] > c[1] + s + 0.2f ||
- LLViewerCamera::getInstance()->getOrigin().mV[1] < c[1] - s - 0.2f ||
- LLViewerCamera::getInstance()->getOrigin().mV[2] > c[2] + s + 0.2f ||
- LLViewerCamera::getInstance()->getOrigin().mV[2] < c[2] - s - 0.2f)
- { //draw box if camera is outside box
- glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s);
- glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);
- glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
- GL_UNSIGNED_BYTE, get_box_fan_indices(LLViewerCamera::getInstance(), center));
+ renderGeomPostDeferred(*LLViewerCamera::getInstance());
+ mRenderTypeMask = render_mask;
+ }
+
+ BOOL render_local = gSavedSettings.getBOOL("RenderDeferredLocalLights");
+ BOOL render_fullscreen = gSavedSettings.getBOOL("RenderDeferredFullscreenLights");
+
+
+ if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
+ {
+ mDeferredLight[1].flush();
+ mDeferredLight[2].bindTarget();
+ mDeferredLight[2].clear(GL_COLOR_BUFFER_BIT);
+ }
+
+ if (render_local || render_fullscreen)
+ {
+ gGL.setSceneBlendType(LLRender::BT_ADD);
+ std::list<LLVector4> fullscreen_lights;
+ LLDrawable::drawable_list_t spot_lights;
+ LLDrawable::drawable_list_t fullscreen_spot_lights;
+
+ for (U32 i = 0; i < 2; i++)
+ {
+ mTargetShadowSpotLight[i] = NULL;
}
- else
- {
- fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s));
- light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f));
+
+ std::list<LLVector4> light_colors;
+
+ F32 v[24];
+ glVertexPointer(3, GL_FLOAT, 0, v);
+ BOOL render_local = gSavedSettings.getBOOL("RenderDeferredLocalLights");
+
+ {
+ bindDeferredShader(gDeferredLightProgram);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter)
+ {
+ LLDrawable* drawablep = *iter;
+
+ LLVOVolume* volume = drawablep->getVOVolume();
+ if (!volume)
+ {
+ continue;
+ }
+
+ LLVector3 center = drawablep->getPositionAgent();
+ F32* c = center.mV;
+ F32 s = volume->getLightRadius()*1.5f;
+
+ LLColor3 col = volume->getLightColor();
+ col *= volume->getLightIntensity();
+
+ if (col.magVecSquared() < 0.001f)
+ {
+ continue;
+ }
+
+ if (s <= 0.001f)
+ {
+ continue;
+ }
+
+ if (camera->AABBInFrustumNoFarClip(center, LLVector3(s,s,s)) == 0)
+ {
+ continue;
+ }
+
+ sVisibleLightCount++;
+
+ glh::vec3f tc(c);
+ mat.mult_matrix_vec(tc);
+
+ //vertex positions are encoded so the 3 bits of their vertex index
+ //correspond to their axis facing, with bit position 3,2,1 matching
+ //axis facing x,y,z, bit set meaning positive facing, bit clear
+ //meaning negative facing
+ v[0] = c[0]-s; v[1] = c[1]-s; v[2] = c[2]-s; // 0 - 0000
+ v[3] = c[0]-s; v[4] = c[1]-s; v[5] = c[2]+s; // 1 - 0001
+ v[6] = c[0]-s; v[7] = c[1]+s; v[8] = c[2]-s; // 2 - 0010
+ v[9] = c[0]-s; v[10] = c[1]+s; v[11] = c[2]+s; // 3 - 0011
+
+ v[12] = c[0]+s; v[13] = c[1]-s; v[14] = c[2]-s; // 4 - 0100
+ v[15] = c[0]+s; v[16] = c[1]-s; v[17] = c[2]+s; // 5 - 0101
+ v[18] = c[0]+s; v[19] = c[1]+s; v[20] = c[2]-s; // 6 - 0110
+ v[21] = c[0]+s; v[22] = c[1]+s; v[23] = c[2]+s; // 7 - 0111
+
+ if (camera->getOrigin().mV[0] > c[0] + s + 0.2f ||
+ camera->getOrigin().mV[0] < c[0] - s - 0.2f ||
+ camera->getOrigin().mV[1] > c[1] + s + 0.2f ||
+ camera->getOrigin().mV[1] < c[1] - s - 0.2f ||
+ camera->getOrigin().mV[2] > c[2] + s + 0.2f ||
+ camera->getOrigin().mV[2] < c[2] - s - 0.2f)
+ { //draw box if camera is outside box
+ if (render_local)
+ {
+ if (volume->getLightTexture())
+ {
+ drawablep->getVOVolume()->updateSpotLightPriority();
+ spot_lights.push_back(drawablep);
+ continue;
+ }
+
+ LLFastTimer ftm(FTM_LOCAL_LIGHTS);
+ glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s);
+ glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_BYTE, get_box_fan_indices(camera, center));
+ stop_glerror();
+ }
+ }
+ else if (render_fullscreen)
+ {
+ if (volume->getLightTexture())
+ {
+ drawablep->getVOVolume()->updateSpotLightPriority();
+ fullscreen_spot_lights.push_back(drawablep);
+ continue;
+ }
+
+ fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s));
+ light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f));
+ }
+ }
+ unbindDeferredShader(gDeferredLightProgram);
}
- }
- }
- unbindDeferredShader(gDeferredLightProgram);
+ if (!spot_lights.empty())
+ {
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ bindDeferredShader(gDeferredSpotLightProgram);
- if (!fullscreen_lights.empty())
- {
- bindDeferredShader(gDeferredMultiLightProgram);
- LLGLDepthTest depth(GL_FALSE);
+ gDeferredSpotLightProgram.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
- //full screen blit
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
+ for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter)
+ {
+ LLFastTimer ftm(FTM_PROJECTORS);
+ LLDrawable* drawablep = *iter;
- U32 count = 0;
+ LLVOVolume* volume = drawablep->getVOVolume();
- LLVector4 light[16];
- LLVector4 col[16];
+ LLVector3 center = drawablep->getPositionAgent();
+ F32* c = center.mV;
+ F32 s = volume->getLightRadius()*1.5f;
- glVertexPointer(2, GL_FLOAT, 0, vert);
+ sVisibleLightCount++;
- while (!fullscreen_lights.empty())
- {
- light[count] = fullscreen_lights.front();
- fullscreen_lights.pop_front();
- col[count] = light_colors.front();
- light_colors.pop_front();
+ glh::vec3f tc(c);
+ mat.mult_matrix_vec(tc);
+
+ setupSpotLight(gDeferredSpotLightProgram, drawablep);
+
+ LLColor3 col = volume->getLightColor();
+ col *= volume->getLightIntensity();
+
+ //vertex positions are encoded so the 3 bits of their vertex index
+ //correspond to their axis facing, with bit position 3,2,1 matching
+ //axis facing x,y,z, bit set meaning positive facing, bit clear
+ //meaning negative facing
+ v[0] = c[0]-s; v[1] = c[1]-s; v[2] = c[2]-s; // 0 - 0000
+ v[3] = c[0]-s; v[4] = c[1]-s; v[5] = c[2]+s; // 1 - 0001
+ v[6] = c[0]-s; v[7] = c[1]+s; v[8] = c[2]-s; // 2 - 0010
+ v[9] = c[0]-s; v[10] = c[1]+s; v[11] = c[2]+s; // 3 - 0011
+
+ v[12] = c[0]+s; v[13] = c[1]-s; v[14] = c[2]-s; // 4 - 0100
+ v[15] = c[0]+s; v[16] = c[1]-s; v[17] = c[2]+s; // 5 - 0101
+ v[18] = c[0]+s; v[19] = c[1]+s; v[20] = c[2]-s; // 6 - 0110
+ v[21] = c[0]+s; v[22] = c[1]+s; v[23] = c[2]+s; // 7 - 0111
+
+ glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s);
+ glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_BYTE, get_box_fan_indices(camera, center));
+ }
+ gDeferredSpotLightProgram.disableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
+ unbindDeferredShader(gDeferredSpotLightProgram);
+ }
- count++;
- if (count == 16 || fullscreen_lights.empty())
{
- gDeferredMultiLightProgram.uniform1i("light_count", count);
- gDeferredMultiLightProgram.uniform4fv("light[0]", count, (GLfloat*) light);
- gDeferredMultiLightProgram.uniform4fv("light", count, (GLfloat*) light);
- gDeferredMultiLightProgram.uniform4fv("light_col[0]", count, (GLfloat*) col);
- gDeferredMultiLightProgram.uniform4fv("light_col", count, (GLfloat*) col);
- count = 0;
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ bindDeferredShader(gDeferredMultiLightProgram);
+
+ LLGLDepthTest depth(GL_FALSE);
+
+ //full screen blit
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+
+ U32 count = 0;
+
+ const U32 max_count = 8;
+ LLVector4 light[max_count];
+ LLVector4 col[max_count];
+
+ glVertexPointer(2, GL_FLOAT, 0, vert);
+
+ F32 far_z = 0.f;
+
+ while (!fullscreen_lights.empty())
+ {
+ LLFastTimer ftm(FTM_FULLSCREEN_LIGHTS);
+ light[count] = fullscreen_lights.front();
+ fullscreen_lights.pop_front();
+ col[count] = light_colors.front();
+ light_colors.pop_front();
+
+ far_z = llmin(light[count].mV[2]-sqrtf(light[count].mV[3]), far_z);
+
+ count++;
+ if (count == max_count || fullscreen_lights.empty())
+ {
+ gDeferredMultiLightProgram.uniform1i("light_count", count);
+ gDeferredMultiLightProgram.uniform4fv("light[0]", count, (GLfloat*) light);
+ gDeferredMultiLightProgram.uniform4fv("light", count, (GLfloat*) light);
+ gDeferredMultiLightProgram.uniform4fv("light_col[0]", count, (GLfloat*) col);
+ gDeferredMultiLightProgram.uniform4fv("light_col", count, (GLfloat*) col);
+ gDeferredMultiLightProgram.uniform1f("far_z", far_z);
+ far_z = 0.f;
+ count = 0;
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ }
+ }
+
+ unbindDeferredShader(gDeferredMultiLightProgram);
+
+ bindDeferredShader(gDeferredMultiSpotLightProgram);
+
+ gDeferredMultiSpotLightProgram.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
+
+ for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter)
+ {
+ LLFastTimer ftm(FTM_PROJECTORS);
+ LLDrawable* drawablep = *iter;
+
+ LLVOVolume* volume = drawablep->getVOVolume();
+
+ LLVector3 center = drawablep->getPositionAgent();
+ F32* c = center.mV;
+ F32 s = volume->getLightRadius()*1.5f;
+
+ sVisibleLightCount++;
+
+ glh::vec3f tc(c);
+ mat.mult_matrix_vec(tc);
+
+ setupSpotLight(gDeferredMultiSpotLightProgram, drawablep);
+
+ LLColor3 col = volume->getLightColor();
+ col *= volume->getLightIntensity();
+
+ glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s);
+ glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ }
+
+ gDeferredMultiSpotLightProgram.disableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
+ unbindDeferredShader(gDeferredMultiSpotLightProgram);
+
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
}
}
+
+ gGL.setColorMask(true, true);
+
+ if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
+ {
+ mDeferredLight[2].flush();
+
+ mScreen.bindTarget();
+ mScreen.clear(GL_COLOR_BUFFER_BIT);
-
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
+ { //mix various light maps (local, sun, gi)
+ LLFastTimer ftm(FTM_POST);
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable test(GL_ALPHA_TEST);
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLDisable stencil(GL_STENCIL_TEST);
+
+ bindDeferredShader(gDeferredPostProgram, 0, &mGIMapPost[0]);
+
+ gDeferredPostProgram.bind();
+
+ LLVertexBuffer::unbind();
+
+ glVertexPointer(2, GL_FLOAT, 0, vert);
+ glColor3f(1,1,1);
+
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glDrawArrays(GL_TRIANGLES, 0, 3);
- unbindDeferredShader(gDeferredMultiLightProgram);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ unbindDeferredShader(gDeferredPostProgram);
+ }
+ }
}
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- { //render non-deferred geometry
+ { //render non-deferred geometry (alpha, fullbright, glow)
LLGLDisable blend(GL_BLEND);
LLGLDisable stencil(GL_STENCIL_TEST);
U32 render_mask = mRenderTypeMask;
mRenderTypeMask = mRenderTypeMask &
- ((1 << LLPipeline::RENDER_TYPE_SKY) |
- (1 << LLPipeline::RENDER_TYPE_CLOUDS) |
- (1 << LLPipeline::RENDER_TYPE_WL_SKY) |
- (1 << LLPipeline::RENDER_TYPE_ALPHA) |
- (1 << LLPipeline::RENDER_TYPE_AVATAR) |
- (1 << LLPipeline::RENDER_TYPE_WATER) |
+ ((1 << LLPipeline::RENDER_TYPE_ALPHA) |
(1 << LLPipeline::RENDER_TYPE_FULLBRIGHT) |
(1 << LLPipeline::RENDER_TYPE_VOLUME) |
(1 << LLPipeline::RENDER_TYPE_GLOW) |
- (1 << LLPipeline::RENDER_TYPE_BUMP));
+ (1 << LLPipeline::RENDER_TYPE_BUMP) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_SIMPLE) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_ALPHA) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_BUMP) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_GLOW) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_GRASS) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_SHINY) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_INVISIBLE) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY) |
+ (1 << LLPipeline::RENDER_TYPE_AVATAR));
renderGeomPostDeferred(*LLViewerCamera::getInstance());
mRenderTypeMask = render_mask;
@@ -5742,6 +6924,136 @@ void LLPipeline::renderDeferredLighting()
}
+void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
+{
+ //construct frustum
+ LLVOVolume* volume = drawablep->getVOVolume();
+ LLVector3 params = volume->getSpotLightParams();
+
+ F32 fov = params.mV[0];
+ F32 focus = params.mV[1];
+
+ LLVector3 pos = drawablep->getPositionAgent();
+ LLQuaternion quat = volume->getRenderRotation();
+ LLVector3 scale = volume->getScale();
+
+ //get near clip plane
+ LLVector3 at_axis(0,0,-scale.mV[2]*0.5f);
+ at_axis *= quat;
+
+ LLVector3 np = pos+at_axis;
+ at_axis.normVec();
+
+ //get origin that has given fov for plane np, at_axis, and given scale
+ F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f);
+
+ LLVector3 origin = np - at_axis*dist;
+
+ //matrix from volume space to agent space
+ LLMatrix4 light_mat(quat, LLVector4(origin,1.f));
+
+ glh::matrix4f light_to_agent((F32*) light_mat.mMatrix);
+ glh::matrix4f light_to_screen = glh_get_current_modelview() * light_to_agent;
+
+ glh::matrix4f screen_to_light = light_to_screen.inverse();
+
+ F32 s = volume->getLightRadius()*1.5f;
+ F32 near_clip = dist;
+ F32 width = scale.mV[VX];
+ F32 height = scale.mV[VY];
+ F32 far_clip = s+dist-scale.mV[VZ];
+
+ F32 fovy = fov * RAD_TO_DEG;
+ F32 aspect = width/height;
+
+ glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
+ 0.f, 0.5f, 0.f, 0.5f,
+ 0.f, 0.f, 0.5f, 0.5f,
+ 0.f, 0.f, 0.f, 1.f);
+
+ glh::vec3f p1(0, 0, -(near_clip+0.01f));
+ glh::vec3f p2(0, 0, -(near_clip+1.f));
+
+ glh::vec3f screen_origin(0, 0, 0);
+
+ light_to_screen.mult_matrix_vec(p1);
+ light_to_screen.mult_matrix_vec(p2);
+ light_to_screen.mult_matrix_vec(screen_origin);
+
+ glh::vec3f n = p2-p1;
+ n.normalize();
+
+ F32 proj_range = far_clip - near_clip;
+ glh::matrix4f light_proj = gl_perspective(fovy, aspect, near_clip, far_clip);
+ screen_to_light = trans * light_proj * screen_to_light;
+ shader.uniformMatrix4fv("proj_mat", 1, FALSE, screen_to_light.m);
+ shader.uniform1f("proj_near", near_clip);
+ shader.uniform3fv("proj_p", 1, p1.v);
+ shader.uniform3fv("proj_n", 1, n.v);
+ shader.uniform3fv("proj_origin", 1, screen_origin.v);
+ shader.uniform1f("proj_range", proj_range);
+ shader.uniform1f("proj_ambiance", params.mV[2]);
+ S32 s_idx = -1;
+
+ for (U32 i = 0; i < 2; i++)
+ {
+ if (mShadowSpotLight[i] == drawablep)
+ {
+ s_idx = i;
+ }
+ }
+
+ shader.uniform1i("proj_shadow_idx", s_idx);
+
+ if (s_idx >= 0)
+ {
+ shader.uniform1f("shadow_fade", 1.f-mSpotLightFade[s_idx]);
+ }
+ else
+ {
+ shader.uniform1f("shadow_fade", 1.f);
+ }
+
+ {
+ LLDrawable* potential = drawablep;
+ //determine if this is a good light for casting shadows
+ F32 m_pri = volume->getSpotLightPriority();
+
+ for (U32 i = 0; i < 2; i++)
+ {
+ F32 pri = 0.f;
+
+ if (mTargetShadowSpotLight[i].notNull())
+ {
+ pri = mTargetShadowSpotLight[i]->getVOVolume()->getSpotLightPriority();
+ }
+
+ if (m_pri > pri)
+ {
+ LLDrawable* temp = mTargetShadowSpotLight[i];
+ mTargetShadowSpotLight[i] = potential;
+ potential = temp;
+ m_pri = pri;
+ }
+ }
+ }
+
+ LLViewerTexture* img = volume->getLightTexture();
+
+ S32 channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
+
+ if (channel > -1 && img)
+ {
+ gGL.getTexUnit(channel)->bind(img);
+
+ F32 lod_range = logf(img->getWidth())/logf(2.f);
+
+ shader.uniform1f("proj_focus", focus);
+ shader.uniform1f("proj_lod", lod_range);
+ shader.uniform1f("proj_ambient_lod", llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f));
+ }
+}
+
void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
{
stop_glerror();
@@ -5751,14 +7063,43 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
shader.disableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE);
shader.disableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE);
shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_EDGE, LLTexUnit::TT_RECT_TEXTURE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_SUN_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_LOCAL_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_LUMINANCE);
+ shader.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MIP);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_BLOOM);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_NORMAL);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_DIFFUSE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_SPECULAR);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_DEPTH);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MIN_POS);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MAX_POS);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_NORMAL);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_DIFFUSE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MIN_POS);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MAX_POS);
+
for (U32 i = 0; i < 4; i++)
{
+ if (shader.disableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE) > -1)
+ {
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
+ }
+ }
+
+ for (U32 i = 4; i < 6; i++)
+ {
if (shader.disableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i) > -1)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
}
}
+
shader.disableTexture(LLViewerShaderMgr::DEFERRED_NOISE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHTFUNC);
S32 channel = shader.disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
if (channel > -1)
@@ -5772,6 +7113,8 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(0)->activate();
shader.unbind();
+
+ LLGLState::checkTextureChannels();
}
inline float sgn(float a)
@@ -5785,15 +7128,15 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
{
if (LLPipeline::sWaterReflections && assertInitialized() && LLDrawPoolWater::sNeedsReflectionUpdate)
{
- LLVOAvatar* agent = gAgent.getAvatarObject();
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
if (gAgent.getCameraAnimating() || gAgent.getCameraMode() != CAMERA_MODE_MOUSELOOK)
{
- agent = NULL;
+ avatar = NULL;
}
- if (agent)
+ if (avatar)
{
- agent->updateAttachmentVisibility(CAMERA_MODE_THIRD_PERSON);
+ avatar->updateAttachmentVisibility(CAMERA_MODE_THIRD_PERSON);
}
LLVertexBuffer::unbind();
@@ -5805,6 +7148,9 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
camera.setFar(camera.getFar()*0.87654321f);
LLPipeline::sReflectionRender = TRUE;
S32 occlusion = LLPipeline::sUseOcclusion;
+
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+
LLPipeline::sUseOcclusion = llmin(occlusion, 1);
U32 type_mask = gPipeline.mRenderTypeMask;
@@ -5839,22 +7185,19 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
water_clip = 1;
}
-
-
if (!LLViewerCamera::getInstance()->cameraUnderWater())
{ //generate planar reflection map
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
glClearColor(0,0,0,0);
- gGL.setColorMask(true, true);
mWaterRef.bindTarget();
- mWaterRef.getViewport(gGLViewport);
+ gGL.setColorMask(true, true);
mWaterRef.clear();
gGL.setColorMask(true, false);
+ mWaterRef.getViewport(gGLViewport);
+
stop_glerror();
- LLVector3 origin = camera.getOrigin();
-
glPushMatrix();
mat.set_scale(glh::vec3f(1,1,-1));
@@ -5869,25 +7212,36 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
LLViewerCamera::updateFrustumPlanes(camera, FALSE, TRUE);
- glCullFace(GL_FRONT);
+ glh::matrix4f inv_mat = mat.inverse();
- //initial sky pass (no user clip plane)
- { //mask out everything but the sky
- U32 tmp = mRenderTypeMask;
- mRenderTypeMask = tmp & ((1 << LLPipeline::RENDER_TYPE_SKY) |
- (1 << LLPipeline::RENDER_TYPE_WL_SKY));
- static LLCullResult result;
- updateCull(camera, result);
- stateSort(camera, result);
- mRenderTypeMask = tmp & ((1 << LLPipeline::RENDER_TYPE_SKY) |
- (1 << LLPipeline::RENDER_TYPE_CLOUDS) |
- (1 << LLPipeline::RENDER_TYPE_WL_SKY));
- renderGeom(camera, TRUE);
- mRenderTypeMask = tmp;
- }
+ glh::vec3f origin(0,0,0);
+ inv_mat.mult_matrix_vec(origin);
+
+ camera.setOrigin(origin.v);
+
+ glCullFace(GL_FRONT);
+
+ static LLCullResult ref_result;
+ U32 ref_mask = 0;
if (LLDrawPoolWater::sNeedsDistortionUpdate)
{
+ //initial sky pass (no user clip plane)
+ { //mask out everything but the sky
+ U32 tmp = mRenderTypeMask;
+ mRenderTypeMask = tmp & ((1 << LLPipeline::RENDER_TYPE_SKY) |
+ (1 << LLPipeline::RENDER_TYPE_WL_SKY));
+ static LLCullResult result;
+ updateCull(camera, result);
+ stateSort(camera, result);
+ mRenderTypeMask = tmp & ((1 << LLPipeline::RENDER_TYPE_SKY) |
+ (1 << LLPipeline::RENDER_TYPE_CLOUDS) |
+ (1 << LLPipeline::RENDER_TYPE_WL_SKY));
+ renderGeom(camera, TRUE);
+ mRenderTypeMask = tmp;
+ }
+
+ U32 mask = mRenderTypeMask;
mRenderTypeMask &= ~((1<<LLPipeline::RENDER_TYPE_WATER) |
(1<<LLPipeline::RENDER_TYPE_GROUND) |
(1<<LLPipeline::RENDER_TYPE_SKY) |
@@ -5910,24 +7264,34 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
}
}
- LLSpatialPartition::sFreezeState = TRUE;
- LLPipeline::sSkipUpdate = TRUE;
LLGLUserClipPlane clip_plane(plane, mat, projection);
- static LLCullResult result;
- updateCull(camera, result, 1);
- stateSort(camera, result);
+ LLGLDisable cull(GL_CULL_FACE);
+ updateCull(camera, ref_result, 1);
+ stateSort(camera, ref_result);
+ }
+
+ ref_mask = mRenderTypeMask;
+ mRenderTypeMask = mask;
+ }
+
+ if (LLDrawPoolWater::sNeedsDistortionUpdate)
+ {
+ mRenderTypeMask = ref_mask;
+ if (gSavedSettings.getBOOL("RenderWaterReflections"))
+ {
+ gPipeline.grabReferences(ref_result);
+ LLGLUserClipPlane clip_plane(plane, mat, projection);
renderGeom(camera);
- LLSpatialPartition::sFreezeState = FALSE;
- LLPipeline::sSkipUpdate = FALSE;
}
}
glCullFace(GL_BACK);
glPopMatrix();
mWaterRef.flush();
-
glh_set_current_modelview(current);
}
+ camera.setOrigin(camera_in.getOrigin());
+
//render distortion map
static BOOL last_update = TRUE;
if (last_update)
@@ -5951,12 +7315,9 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
LLColor4& col = LLDrawPoolWater::sWaterFogColor;
glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
- gGL.setColorMask(true, true);
mWaterDis.bindTarget();
mWaterDis.getViewport(gGLViewport);
- mWaterDis.clear();
- gGL.setColorMask(true, false);
-
+
if (!LLPipeline::sUnderWaterRender || LLDrawPoolWater::sNeedsReflectionUpdate)
{
//clip out geometry on the same side of water as the camera
@@ -5965,6 +7326,11 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
static LLCullResult result;
updateCull(camera, result, water_clip);
stateSort(camera, result);
+
+ gGL.setColorMask(true, true);
+ mWaterDis.clear();
+ gGL.setColorMask(true, false);
+
renderGeom(camera);
}
@@ -5983,7 +7349,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
}
glClearColor(0.f, 0.f, 0.f, 0.f);
- gViewerWindow->setupViewport();
+ gViewerWindow->setup3DViewport();
mRenderTypeMask = type_mask;
LLDrawPoolWater::sNeedsReflectionUpdate = FALSE;
LLDrawPoolWater::sNeedsDistortionUpdate = FALSE;
@@ -5994,9 +7360,9 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
LLGLState::checkTextureChannels();
LLGLState::checkClientArrays();
- if (agent)
+ if (avatar)
{
- agent->updateAttachmentVisibility(gAgent.getCameraMode());
+ avatar->updateAttachmentVisibility(gAgent.getCameraMode());
}
}
}
@@ -6017,7 +7383,6 @@ glh::matrix4f look(const LLVector3 pos, const LLVector3 dir, const LLVector3 up)
dirN = dir;
dirN.normVec();
-
ret.m[ 0] = lftN[0];
ret.m[ 1] = upN[0];
@@ -6068,10 +7433,489 @@ glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max)
return ret;
}
-void LLPipeline::generateSunShadow(LLCamera& camera)
+static LLFastTimer::DeclareTimer FTM_SHADOW_RENDER("Render Shadows");
+static LLFastTimer::DeclareTimer FTM_SHADOW_ALPHA("Alpha Shadow");
+static LLFastTimer::DeclareTimer FTM_SHADOW_SIMPLE("Simple Shadow");
+
+void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion)
{
+ LLFastTimer t(FTM_SHADOW_RENDER);
+
+ //clip out geometry on the same side of water as the camera
+ S32 occlude = LLPipeline::sUseOcclusion;
+ if (!use_occlusion)
+ {
+ LLPipeline::sUseOcclusion = 0;
+ }
+ LLPipeline::sShadowRender = TRUE;
+
+ U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY, LLRenderPass::PASS_BUMP, LLRenderPass::PASS_FULLBRIGHT_SHINY };
+ LLGLEnable cull(GL_CULL_FACE);
+
+ if (use_shader)
+ {
+ gDeferredShadowProgram.bind();
+ }
+
+ updateCull(shadow_cam, result);
+ stateSort(shadow_cam, result);
+
+ //generate shadow map
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadMatrixf(proj.m);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadMatrixf(view.m);
+
+ stop_glerror();
+ gGLLastMatrix = NULL;
+
+ {
+ LLGLDepthTest depth(GL_TRUE);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ }
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ glColor4f(1,1,1,1);
+
+ stop_glerror();
+
+ gGL.setColorMask(false, false);
+
+ //glCullFace(GL_FRONT);
+
+ {
+ LLFastTimer ftm(FTM_SHADOW_SIMPLE);
+ LLGLDisable test(GL_ALPHA_TEST);
+ gGL.getTexUnit(0)->disable();
+ for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i)
+ {
+ renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE);
+ }
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+ }
+
+ if (use_shader)
+ {
+ gDeferredShadowProgram.unbind();
+ renderGeomShadow(shadow_cam);
+ gDeferredShadowProgram.bind();
+ }
+ else
+ {
+ renderGeomShadow(shadow_cam);
+ }
- if (!sRenderDeferred)
+ {
+ LLFastTimer ftm(FTM_SHADOW_ALPHA);
+ LLGLEnable test(GL_ALPHA_TEST);
+ gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.6f);
+ renderObjects(LLRenderPass::PASS_ALPHA_SHADOW, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR, TRUE);
+ glColor4f(1,1,1,1);
+ renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE);
+ gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
+ }
+
+ //glCullFace(GL_BACK);
+
+ gGLLastMatrix = NULL;
+ glLoadMatrixd(gGLModelView);
+ doOcclusion(shadow_cam);
+
+ if (use_shader)
+ {
+ gDeferredShadowProgram.unbind();
+ }
+
+ gGL.setColorMask(true, true);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ gGLLastMatrix = NULL;
+
+ LLPipeline::sUseOcclusion = occlude;
+ LLPipeline::sShadowRender = FALSE;
+}
+
+
+BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector3& max, std::vector<LLVector3>& fp, LLVector3 light_dir)
+{
+ //get point cloud of intersection of frust and min, max
+
+ //get set of planes
+ std::vector<LLPlane> ps;
+
+ if (getVisibleExtents(camera, min, max))
+ {
+ return FALSE;
+ }
+
+ ps.push_back(LLPlane(min, LLVector3(-1,0,0)));
+ ps.push_back(LLPlane(min, LLVector3(0,-1,0)));
+ ps.push_back(LLPlane(min, LLVector3(0,0,-1)));
+ ps.push_back(LLPlane(max, LLVector3(1,0,0)));
+ ps.push_back(LLPlane(max, LLVector3(0,1,0)));
+ ps.push_back(LLPlane(max, LLVector3(0,0,1)));
+
+ /*if (!light_dir.isExactlyZero())
+ {
+ LLPlane ucp;
+ LLPlane mcp;
+
+ F32 maxd = -1.f;
+ F32 mind = 1.f;
+
+ for (U32 i = 0; i < ps.size(); ++i)
+ { //pick the plane most aligned to lightDir for user clip plane
+ LLVector3 n(ps[i].mV);
+ F32 da = n*light_dir;
+ if (da > maxd)
+ {
+ maxd = da;
+ ucp = ps[i];
+ }
+
+ if (da < mind)
+ {
+ mind = da;
+ mcp = ps[i];
+ }
+ }
+
+ camera.setUserClipPlane(ucp);
+
+ ps.clear();
+ ps.push_back(ucp);
+ ps.push_back(mcp);
+ }*/
+
+ for (U32 i = 0; i < 6; i++)
+ {
+ ps.push_back(camera.getAgentPlane(i));
+ }
+
+ //get set of points where planes intersect and points are not above any plane
+ fp.clear();
+
+ for (U32 i = 0; i < ps.size(); ++i)
+ {
+ for (U32 j = 0; j < ps.size(); ++j)
+ {
+ for (U32 k = 0; k < ps.size(); ++k)
+ {
+ if (i == j ||
+ i == k ||
+ k == j)
+ {
+ continue;
+ }
+
+ LLVector3 n1,n2,n3;
+ F32 d1,d2,d3;
+
+ n1.setVec(ps[i].mV);
+ n2.setVec(ps[j].mV);
+ n3.setVec(ps[k].mV);
+
+ d1 = ps[i].mV[3];
+ d2 = ps[j].mV[3];
+ d3 = ps[k].mV[3];
+
+ //get point of intersection of 3 planes "p"
+ LLVector3 p = (-d1*(n2%n3)-d2*(n3%n1)-d3*(n1%n2))/(n1*(n2%n3));
+
+ if (llround(p*n1+d1, 0.0001f) == 0.f &&
+ llround(p*n2+d2, 0.0001f) == 0.f &&
+ llround(p*n3+d3, 0.0001f) == 0.f)
+ { //point is on all three planes
+ BOOL found = TRUE;
+ for (U32 l = 0; l < ps.size() && found; ++l)
+ {
+ if (llround(ps[l].dist(p), 0.0001f) > 0.0f)
+ { //point is above some plane, not contained
+ found = FALSE;
+ }
+ }
+
+ if (found)
+ {
+ fp.push_back(p);
+ }
+ }
+ }
+ }
+ }
+
+ if (fp.empty())
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void LLPipeline::generateGI(LLCamera& camera, LLVector3& lightDir, std::vector<LLVector3>& vpc)
+{
+ if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) < 3)
+ {
+ return;
+ }
+
+ LLVector3 up;
+
+ //LLGLEnable depth_clamp(GL_DEPTH_CLAMP_NV);
+
+ if (lightDir.mV[2] > 0.5f)
+ {
+ up = LLVector3(1,0,0);
+ }
+ else
+ {
+ up = LLVector3(0, 0, 1);
+ }
+
+
+ F32 gi_range = gSavedSettings.getF32("RenderGIRange");
+
+ U32 res = mGIMap.getWidth();
+
+ F32 atten = llmax(gSavedSettings.getF32("RenderGIAttenuation"), 0.001f);
+
+ //set radius to range at which distance attenuation of incoming photons is near 0
+
+ F32 lrad = sqrtf(1.f/(atten*0.01f));
+
+ F32 lrange = lrad+gi_range*0.5f;
+
+ LLVector3 pad(lrange,lrange,lrange);
+
+ glh::matrix4f view = look(LLVector3(128.f,128.f,128.f), lightDir, up);
+
+ LLVector3 cp = camera.getOrigin()+camera.getAtAxis()*(gi_range*0.5f);
+
+ glh::vec3f scp(cp.mV);
+ view.mult_matrix_vec(scp);
+ cp.setVec(scp.v);
+
+ F32 pix_width = lrange/(res*0.5f);
+
+ //move cp to the nearest pix_width
+ for (U32 i = 0; i < 3; i++)
+ {
+ cp.mV[i] = llround(cp.mV[i], pix_width);
+ }
+
+ LLVector3 min = cp-pad;
+ LLVector3 max = cp+pad;
+
+ //set mGIRange to range in tc space[0,1] that covers texture block of intersecting lights around a point
+ mGIRange.mV[0] = (max.mV[0]-min.mV[0])/res;
+ mGIRange.mV[1] = (max.mV[1]-min.mV[1])/res;
+ mGILightRadius = lrad/lrange*0.5f;
+
+ glh::matrix4f proj = gl_ortho(min.mV[0], max.mV[0],
+ min.mV[1], max.mV[1],
+ -max.mV[2], -min.mV[2]);
+
+ LLCamera sun_cam = camera;
+
+ glh::matrix4f eye_view = glh_get_current_modelview();
+
+ //get eye space to camera space matrix
+ mGIMatrix = view*eye_view.inverse();
+ mGINormalMatrix = mGIMatrix.inverse().transpose();
+ mGIInvProj = proj.inverse();
+ mGIMatrixProj = proj*mGIMatrix;
+
+ //translate and scale to [0,1]
+ glh::matrix4f trans(.5f, 0.f, 0.f, .5f,
+ 0.f, 0.5f, 0.f, 0.5f,
+ 0.f, 0.f, 0.5f, 0.5f,
+ 0.f, 0.f, 0.f, 1.f);
+
+ mGIMatrixProj = trans*mGIMatrixProj;
+
+ glh_set_current_modelview(view);
+ glh_set_current_projection(proj);
+
+ LLViewerCamera::updateFrustumPlanes(sun_cam, TRUE, FALSE, TRUE);
+
+ sun_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR);
+ static LLCullResult result;
+
+ U32 type_mask = mRenderTypeMask;
+
+ mRenderTypeMask = type_mask & ((1<<LLPipeline::RENDER_TYPE_SIMPLE) |
+ (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) |
+ (1<<LLPipeline::RENDER_TYPE_BUMP) |
+ (1<<LLPipeline::RENDER_TYPE_VOLUME) |
+ (1<<LLPipeline::RENDER_TYPE_TREE) |
+ (1<<LLPipeline::RENDER_TYPE_TERRAIN) |
+ (1<<LLPipeline::RENDER_TYPE_WATER) |
+ (1<<LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW) |
+ (1<<LLPipeline::RENDER_TYPE_AVATAR) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_SIMPLE) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_BUMP) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_SHINY));
+
+
+
+ S32 occlude = LLPipeline::sUseOcclusion;
+ //LLPipeline::sUseOcclusion = 0;
+ LLPipeline::sShadowRender = TRUE;
+
+ //only render large objects into GI map
+ sMinRenderSize = gSavedSettings.getF32("RenderGIMinRenderSize");
+
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_GI_SOURCE;
+ mGIMap.bindTarget();
+
+ F64 last_modelview[16];
+ F64 last_projection[16];
+ for (U32 i = 0; i < 16; i++)
+ {
+ last_modelview[i] = gGLLastModelView[i];
+ last_projection[i] = gGLLastProjection[i];
+ gGLLastModelView[i] = mGIModelview.m[i];
+ gGLLastProjection[i] = mGIProjection.m[i];
+ }
+
+ sun_cam.setOrigin(0.f, 0.f, 0.f);
+ updateCull(sun_cam, result);
+ stateSort(sun_cam, result);
+
+ for (U32 i = 0; i < 16; i++)
+ {
+ gGLLastModelView[i] = last_modelview[i];
+ gGLLastProjection[i] = last_projection[i];
+ }
+
+ mGIProjection = proj;
+ mGIModelview = view;
+
+ LLGLEnable cull(GL_CULL_FACE);
+
+ //generate GI map
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadMatrixf(proj.m);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadMatrixf(view.m);
+
+ stop_glerror();
+ gGLLastMatrix = NULL;
+
+ mGIMap.clear();
+
+ {
+ //LLGLEnable enable(GL_DEPTH_CLAMP_NV);
+ renderGeomDeferred(camera);
+ }
+
+ mGIMap.flush();
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ gGLLastMatrix = NULL;
+
+ LLPipeline::sUseOcclusion = occlude;
+ LLPipeline::sShadowRender = FALSE;
+ sMinRenderSize = 0.f;
+
+ mRenderTypeMask = type_mask;
+
+}
+
+void LLPipeline::renderHighlight(const LLViewerObject* obj, F32 fade)
+{
+ if (obj && obj->getVolume())
+ {
+ for (LLViewerObject::child_list_t::const_iterator iter = obj->getChildren().begin(); iter != obj->getChildren().end(); ++iter)
+ {
+ renderHighlight(*iter, fade);
+ }
+
+ LLDrawable* drawable = obj->mDrawable;
+ if (drawable)
+ {
+ for (S32 i = 0; i < drawable->getNumFaces(); ++i)
+ {
+ LLFace* face = drawable->getFace(i);
+ if (face)
+ {
+ face->renderSelected(LLViewerTexture::sNullImagep, LLColor4(1,1,1,fade));
+ }
+ }
+ }
+ }
+}
+
+void LLPipeline::generateHighlight(LLCamera& camera)
+{
+ //render highlighted object as white into offscreen render target
+
+ if (mHighlightObject.notNull())
+ {
+ mHighlightSet.insert(HighlightItem(mHighlightObject));
+ }
+
+ if (!mHighlightSet.empty())
+ {
+ F32 transition = gFrameIntervalSeconds/gSavedSettings.getF32("RenderHighlightFadeTime");
+
+ LLGLDisable test(GL_ALPHA_TEST);
+ LLGLDepthTest depth(GL_FALSE);
+ mHighlight.bindTarget();
+ disableLights();
+ gGL.setColorMask(true, true);
+ mHighlight.clear();
+
+ gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
+ for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); )
+ {
+ std::set<HighlightItem>::iterator cur_iter = iter++;
+
+ if (cur_iter->mItem.isNull())
+ {
+ mHighlightSet.erase(cur_iter);
+ continue;
+ }
+
+ if (cur_iter->mItem == mHighlightObject)
+ {
+ cur_iter->incrFade(transition);
+ }
+ else
+ {
+ cur_iter->incrFade(-transition);
+ if (cur_iter->mFade <= 0.f)
+ {
+ mHighlightSet.erase(cur_iter);
+ continue;
+ }
+ }
+
+ renderHighlight(cur_iter->mItem->getVObj(), cur_iter->mFade);
+ }
+
+ mHighlight.flush();
+ gGL.setColorMask(true, false);
+ gViewerWindow->setup3DViewport();
+ }
+}
+
+
+void LLPipeline::generateSunShadow(LLCamera& camera)
+{
+ if (!sRenderDeferred || !gSavedSettings.getBOOL("RenderDeferredShadow"))
{
return;
}
@@ -6084,98 +7928,173 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
if (clear)
{
clear = FALSE;
- for (U32 i = 0; i < 4; i++)
+ for (U32 i = 0; i < 6; i++)
{
- mSunShadow[i].bindTarget();
- mSunShadow[i].clear();
- mSunShadow[i].flush();
+ mShadow[i].bindTarget();
+ mShadow[i].clear();
+ mShadow[i].flush();
}
}
return;
}
clear = TRUE;
+ F64 last_modelview[16];
+ F64 last_projection[16];
+ for (U32 i = 0; i < 16; i++)
+ { //store last_modelview of world camera
+ last_modelview[i] = gGLLastModelView[i];
+ last_projection[i] = gGLLastProjection[i];
+ }
+
+ U32 type_mask = mRenderTypeMask;
+ mRenderTypeMask = type_mask & ((1<<LLPipeline::RENDER_TYPE_SIMPLE) |
+ (1<<LLPipeline::RENDER_TYPE_ALPHA) |
+ (1<<LLPipeline::RENDER_TYPE_GRASS) |
+ (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) |
+ (1<<LLPipeline::RENDER_TYPE_BUMP) |
+ (1<<LLPipeline::RENDER_TYPE_VOLUME) |
+ (1<<LLPipeline::RENDER_TYPE_AVATAR) |
+ (1<<LLPipeline::RENDER_TYPE_TREE) |
+ (1<<LLPipeline::RENDER_TYPE_TERRAIN) |
+ (1<<LLPipeline::RENDER_TYPE_WATER) |
+ (1<<LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_SIMPLE) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_BUMP) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_SHINY) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY));
+
gGL.setColorMask(false, false);
//get sun view matrix
- F32 range = 128.f;
-
//store current projection/modelview matrix
glh::matrix4f saved_proj = glh_get_current_projection();
glh::matrix4f saved_view = glh_get_current_modelview();
glh::matrix4f inv_view = saved_view.inverse();
- glh::matrix4f view[4];
- glh::matrix4f proj[4];
- LLVector3 up;
-
+ glh::matrix4f view[6];
+ glh::matrix4f proj[6];
+
//clip contains parallel split distances for 3 splits
LLVector3 clip = gSavedSettings.getVector3("RenderShadowClipPlanes");
+ //F32 slope_threshold = gSavedSettings.getF32("RenderShadowSlopeThreshold");
+
//far clip on last split is minimum of camera view distance and 128
mSunClipPlanes = LLVector4(clip, clip.mV[2] * clip.mV[2]/clip.mV[1]);
- const LLPickInfo& pick_info = gViewerWindow->getLastPick();
-
- if (!pick_info.mPosGlobal.isExactlyZero())
- { //squish nearest frustum based on alt-zoom (tighten up nearest frustum when focusing on tiny object
- F32 focus_dist = (F32) (pick_info.mPosGlobal + LLVector3d(pick_info.mObjectOffset) - gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin())).magVec();
- mSunClipPlanes.mV[0] = llclamp(focus_dist*focus_dist, 2.f, mSunClipPlanes.mV[0]);
- }
-
- // convenience array of 4 near clip plane distances
- F32 dist[] = { 0.1f, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] };
+ clip = gSavedSettings.getVector3("RenderShadowOrthoClipPlanes");
+ mSunOrthoClipPlanes = LLVector4(clip, clip.mV[2]*clip.mV[2]/clip.mV[1]);
//currently used for amount to extrude frusta corners for constructing shadow frusta
LLVector3 n = gSavedSettings.getVector3("RenderShadowNearDist");
- F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] };
+ //F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] };
- for (S32 j = 0; j < 4; j++)
- {
- //restore render matrices
- glh_set_current_modelview(saved_view);
- glh_set_current_projection(saved_proj);
+ LLVector3 lightDir = -mSunDir;
+ lightDir.normVec();
- //get center of far clip plane (for point of interest later)
- LLVector3 center = camera.getOrigin() + camera.getAtAxis() * range;
+ glh::vec3f light_dir(lightDir.mV);
- LLVector3 eye = camera.getOrigin();
+ //create light space camera matrix
+
+ LLVector3 at = lightDir;
- //camera used for shadow cull/render
- LLCamera shadow_cam;
-
- // perspective shadow map
- glh::vec3f p[16]; //point cloud to be contained by shadow projection (light camera space)
- glh::vec3f wp[16]; //point cloud to be contained by shadow projection (world space)
-
- LLVector3 lightDir = -mSunDir;
- glh::vec3f light_dir(lightDir.mV);
+ LLVector3 up = camera.getAtAxis();
+
+ if (fabsf(up*lightDir) > 0.75f)
+ {
+ up = camera.getUpAxis();
+ }
+
+ /*LLVector3 left = up%at;
+ up = at%left;*/
- //create light space camera matrix
- LLVector3 at;
- F32 dl = camera.getLeftAxis() * lightDir;
- F32 du = camera.getUpAxis() * lightDir;
+ up.normVec();
+ at.normVec();
+
+
+ F32 near_clip = 0.f;
+ {
+ //get visible point cloud
+ std::vector<LLVector3> fp;
- //choose an at axis such that up will be most aligned with lightDir
- if (dl*dl < du*du)
+ LLVector3 min,max;
+ getVisiblePointCloud(camera,min,max,fp);
+
+ if (fp.empty())
{
- at = lightDir%camera.getLeftAxis();
+ mRenderTypeMask = type_mask;
+ return;
}
- else
+
+ generateGI(camera, lightDir, fp);
+
+ //get good split distances for frustum
+ for (U32 i = 0; i < fp.size(); ++i)
{
- at = lightDir%camera.getUpAxis();
+ glh::vec3f v(fp[i].mV);
+ saved_view.mult_matrix_vec(v);
+ fp[i].setVec(v.v);
}
- if (at * camera.getAtAxis() < 0)
+ min = fp[0];
+ max = fp[0];
+
+ //get camera space bounding box
+ for (U32 i = 1; i < fp.size(); ++i)
{
- at = -at;
+ update_min_max(min, max, fp[i]);
}
+
+ near_clip = -max.mV[2];
+ F32 far_clip = -min.mV[2]*2.f;
+
+ far_clip = llmin(far_clip, 128.f);
+ far_clip = llmin(far_clip, camera.getFar());
+
+ F32 range = far_clip-near_clip;
+
+ LLVector3 split_exp = gSavedSettings.getVector3("RenderShadowSplitExponent");
+
+ F32 da = 1.f-llmax( fabsf(lightDir*up), fabsf(lightDir*camera.getLeftAxis()) );
- LLVector3 left = lightDir%at;
- up = left%lightDir;
- up.normVec();
+ da = powf(da, split_exp.mV[2]);
+
+
+ F32 sxp = split_exp.mV[1] + (split_exp.mV[0]-split_exp.mV[1])*da;
+
+
+ for (U32 i = 0; i < 4; ++i)
+ {
+ F32 x = (F32)(i+1)/4.f;
+ x = powf(x, sxp);
+ mSunClipPlanes.mV[i] = near_clip+range*x;
+ }
+ }
+
+ // convenience array of 4 near clip plane distances
+ F32 dist[] = { near_clip, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] };
+
+ for (S32 j = 0; j < 4; j++)
+ {
+ if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ mShadowFrustPoints[j].clear();
+ }
+
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+j;
+
+ //restore render matrices
+ glh_set_current_modelview(saved_view);
+ glh_set_current_projection(saved_proj);
+ LLVector3 eye = camera.getOrigin();
+
+ //camera used for shadow cull/render
+ LLCamera shadow_cam;
+
//create world space camera frustum for this split
shadow_cam = camera;
shadow_cam.setFar(16.f);
@@ -6186,8 +8105,6 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
LLVector3 pn = shadow_cam.getAtAxis();
- LLVector3 frust_center;
-
LLVector3 min, max;
//construct 8 corners of split frustum section
@@ -6198,21 +8115,19 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
F32 dp = delta*pn;
frust[i] = eye + (delta*dist[j])/dp;
frust[i+4] = eye + (delta*dist[j+1])/dp;
- frust_center += frust[i] + frust[i+4];
}
-
- //get frustum center
- frust_center /= 8.f;
shadow_cam.calcAgentFrustumPlanes(frust);
-
+ shadow_cam.mFrustumCornerDist = 0.f;
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
{
mShadowCamera[j] = shadow_cam;
}
- if (gPipeline.getVisibleExtents(shadow_cam, min, max))
+ std::vector<LLVector3> fp;
+
+ if (!gPipeline.getVisiblePointCloud(shadow_cam, min, max, fp, lightDir))
{
//no possible shadow receivers
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
@@ -6222,6 +8137,16 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
mShadowCamera[j+4] = shadow_cam;
}
+ mShadow[j].bindTarget();
+ {
+ LLGLDepthTest depth(GL_TRUE);
+ mShadow[j].clear();
+ }
+ mShadow[j].flush();
+
+ mShadowError.mV[j] = 0.f;
+ mShadowFOV.mV[j] = 0.f;
+
continue;
}
@@ -6229,53 +8154,263 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
{
mShadowExtents[j][0] = min;
mShadowExtents[j][1] = max;
+ mShadowFrustPoints[j] = fp;
}
- view[j] = look(frust_center-lightDir*nearDist[j], lightDir, up);
- F32 shadow_dist = nearDist[j];
- for (U32 i = 0; i < 8; i++)
+ //find a good origin for shadow projection
+ LLVector3 origin;
+
+ //get a temporary view projection
+ view[j] = look(camera.getOrigin(), lightDir, -up);
+
+ std::vector<LLVector3> wpf;
+
+ for (U32 i = 0; i < fp.size(); i++)
{
- //points in worldspace (wp) and light camera space (p)
- //that must be included in shadow generation
- wp[i] = glh::vec3f(frust[i].mV);
- wp[i+8] = wp[i] - light_dir*shadow_dist;
- view[j].mult_matrix_vec(wp[i], p[i]);
- view[j].mult_matrix_vec(wp[i+8], p[i+8]);
+ glh::vec3f p = glh::vec3f(fp[i].mV);
+ view[j].mult_matrix_vec(p);
+ wpf.push_back(LLVector3(p.v));
}
-
- min = LLVector3(p[0].v);
- max = LLVector3(p[0].v);
- LLVector3 fmin = min;
- LLVector3 fmax = max;
+ min = wpf[0];
+ max = wpf[0];
- for (U32 i = 1; i < 16; i++)
- { //find camera space AABB of frustum in light camera space
- update_min_max(min, max, LLVector3(p[i].v));
- if (i < 8)
- {
- update_min_max(fmin, fmax, LLVector3(p[i].v));
+ for (U32 i = 0; i < fp.size(); ++i)
+ { //get AABB in camera space
+ update_min_max(min, max, wpf[i]);
+ }
+
+ // Construct a perspective transform with perspective along y-axis that contains
+ // points in wpf
+ //Known:
+ // - far clip plane
+ // - near clip plane
+ // - points in frustum
+ //Find:
+ // - origin
+
+ //get some "interesting" points of reference
+ LLVector3 center = (min+max)*0.5f;
+ LLVector3 size = (max-min)*0.5f;
+ LLVector3 near_center = center;
+ near_center.mV[1] += size.mV[1]*2.f;
+
+
+ //put all points in wpf in quadrant 0, reletive to center of min/max
+ //get the best fit line using least squares
+ F32 bfm = 0.f;
+ F32 bfb = 0.f;
+
+ for (U32 i = 0; i < wpf.size(); ++i)
+ {
+ wpf[i] -= center;
+ wpf[i].mV[0] = fabsf(wpf[i].mV[0]);
+ wpf[i].mV[2] = fabsf(wpf[i].mV[2]);
+ }
+
+ if (!wpf.empty())
+ {
+ F32 sx = 0.f;
+ F32 sx2 = 0.f;
+ F32 sy = 0.f;
+ F32 sxy = 0.f;
+
+ for (U32 i = 0; i < wpf.size(); ++i)
+ {
+ sx += wpf[i].mV[0];
+ sx2 += wpf[i].mV[0]*wpf[i].mV[0];
+ sy += wpf[i].mV[1];
+ sxy += wpf[i].mV[0]*wpf[i].mV[1];
}
+
+ bfm = (sy*sx-wpf.size()*sxy)/(sx*sx-wpf.size()*sx2);
+ bfb = (sx*sxy-sy*sx2)/(sx*sx-bfm*sx2);
}
+
+ {
+ // best fit line is y=bfm*x+bfb
+
+ //find point that is furthest to the right of line
+ F32 off_x = -1.f;
+ LLVector3 lp;
+
+ for (U32 i = 0; i < wpf.size(); ++i)
+ {
+ //y = bfm*x+bfb
+ //x = (y-bfb)/bfm
+ F32 lx = (wpf[i].mV[1]-bfb)/bfm;
+
+ lx = wpf[i].mV[0]-lx;
+
+ if (off_x < lx)
+ {
+ off_x = lx;
+ lp = wpf[i];
+ }
+ }
+
+ //get line with slope bfm through lp
+ // bfb = y-bfm*x
+ bfb = lp.mV[1]-bfm*lp.mV[0];
+
+ //calculate error
+ mShadowError.mV[j] = 0.f;
+
+ for (U32 i = 0; i < wpf.size(); ++i)
+ {
+ F32 lx = (wpf[i].mV[1]-bfb)/bfm;
+ mShadowError.mV[j] += fabsf(wpf[i].mV[0]-lx);
+ }
+
+ mShadowError.mV[j] /= wpf.size();
+ mShadowError.mV[j] /= size.mV[0];
+
+ if (mShadowError.mV[j] > gSavedSettings.getF32("RenderShadowErrorCutoff"))
+ { //just use ortho projection
+ mShadowFOV.mV[j] = -1.f;
+ origin.clearVec();
+ proj[j] = gl_ortho(min.mV[0], max.mV[0],
+ min.mV[1], max.mV[1],
+ -max.mV[2], -min.mV[2]);
+ }
+ else
+ {
+ //origin is where line x = 0;
+ origin.setVec(0,bfb,0);
+
+ F32 fovz = 1.f;
+ F32 fovx = 1.f;
+
+ LLVector3 zp;
+ LLVector3 xp;
+
+ for (U32 i = 0; i < wpf.size(); ++i)
+ {
+ LLVector3 atz = wpf[i]-origin;
+ atz.mV[0] = 0.f;
+ atz.normVec();
+ if (fovz > -atz.mV[1])
+ {
+ zp = wpf[i];
+ fovz = -atz.mV[1];
+ }
+
+ LLVector3 atx = wpf[i]-origin;
+ atx.mV[2] = 0.f;
+ atx.normVec();
+ if (fovx > -atx.mV[1])
+ {
+ fovx = -atx.mV[1];
+ xp = wpf[i];
+ }
+ }
+
+ fovx = acos(fovx);
+ fovz = acos(fovz);
- //generate perspective matrix that contains frustum
- //proj[j] = matrix_perspective(min, max);
- proj[j] = gl_ortho(min.mV[0], max.mV[0],
+ F32 cutoff = llmin(gSavedSettings.getF32("RenderShadowFOVCutoff"), 1.4f);
+
+ mShadowFOV.mV[j] = fovx;
+
+ if (fovx < cutoff && fovz > cutoff)
+ {
+ //x is a good fit, but z is too big, move away from zp enough so that fovz matches cutoff
+ F32 d = zp.mV[2]/tan(cutoff);
+ F32 ny = zp.mV[1] + fabsf(d);
+
+ origin.mV[1] = ny;
+
+ fovz = 1.f;
+ fovx = 1.f;
+
+ for (U32 i = 0; i < wpf.size(); ++i)
+ {
+ LLVector3 atz = wpf[i]-origin;
+ atz.mV[0] = 0.f;
+ atz.normVec();
+ fovz = llmin(fovz, -atz.mV[1]);
+
+ LLVector3 atx = wpf[i]-origin;
+ atx.mV[2] = 0.f;
+ atx.normVec();
+ fovx = llmin(fovx, -atx.mV[1]);
+ }
+
+ fovx = acos(fovx);
+ fovz = acos(fovz);
+
+ if (fovx > cutoff || llround(fovz, 0.01f) > cutoff)
+ {
+ // llerrs << "WTF?" << llendl;
+ }
+
+ mShadowFOV.mV[j] = cutoff;
+ }
+
+
+ origin += center;
+
+ F32 ynear = -(max.mV[1]-origin.mV[1]);
+ F32 yfar = -(min.mV[1]-origin.mV[1]);
+
+ if (ynear < 0.1f) //keep a sensible near clip plane
+ {
+ F32 diff = 0.1f-ynear;
+ origin.mV[1] += diff;
+ ynear += diff;
+ yfar += diff;
+ }
+
+ if (fovx > cutoff)
+ { //just use ortho projection
+ origin.clearVec();
+ mShadowError.mV[j] = -1.f;
+ proj[j] = gl_ortho(min.mV[0], max.mV[0],
min.mV[1], max.mV[1],
-max.mV[2], -min.mV[2]);
-
+ }
+ else
+ {
+ //get perspective projection
+ view[j] = view[j].inverse();
+
+ glh::vec3f origin_agent(origin.mV);
+
+ //translate view to origin
+ view[j].mult_matrix_vec(origin_agent);
+
+ eye = LLVector3(origin_agent.v);
+
+ if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ mShadowFrustOrigin[j] = eye;
+ }
+
+ view[j] = look(LLVector3(origin_agent.v), lightDir, -up);
+
+ F32 fx = 1.f/tanf(fovx);
+ F32 fz = 1.f/tanf(fovz);
+
+ proj[j] = glh::matrix4f(-fx, 0, 0, 0,
+ 0, (yfar+ynear)/(ynear-yfar), 0, (2.f*yfar*ynear)/(ynear-yfar),
+ 0, 0, -fz, 0,
+ 0, -1.f, 0, 0);
+ }
+ }
+ }
+
shadow_cam.setFar(128.f);
shadow_cam.setOriginAndLookAt(eye, up, center);
+ shadow_cam.setOrigin(0,0,0);
+
glh_set_current_modelview(view[j]);
glh_set_current_projection(proj[j]);
LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
- proj[j] = gl_ortho(fmin.mV[0], fmax.mV[0],
- fmin.mV[1], fmax.mV[1],
- -fmax.mV[2], -fmin.mV[2]);
+ shadow_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR);
//translate and scale to from [-1, 1] to [0, 1]
glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
@@ -6286,113 +8421,168 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
glh_set_current_modelview(view[j]);
glh_set_current_projection(proj[j]);
+ for (U32 i = 0; i < 16; i++)
+ {
+ gGLLastModelView[i] = mShadowModelview[j].m[i];
+ gGLLastProjection[i] = mShadowProjection[j].m[i];
+ }
+
+ mShadowModelview[j] = view[j];
+ mShadowProjection[j] = proj[j];
+
+
mSunShadowMatrix[j] = trans*proj[j]*view[j]*inv_view;
- U32 type_mask = mRenderTypeMask;
- mRenderTypeMask = type_mask & ((1<<LLPipeline::RENDER_TYPE_SIMPLE) |
- (1<<LLPipeline::RENDER_TYPE_ALPHA) |
- (1<<LLPipeline::RENDER_TYPE_GRASS) |
- (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) |
- (1<<LLPipeline::RENDER_TYPE_BUMP) |
- (1<<LLPipeline::RENDER_TYPE_VOLUME) |
- (1<<LLPipeline::RENDER_TYPE_AVATAR) |
- (1<<LLPipeline::RENDER_TYPE_TREE) |
- (1<<LLPipeline::RENDER_TYPE_TERRAIN) |
- 0);
-
- //clip out geometry on the same side of water as the camera
- static LLCullResult result;
- S32 occlude = LLPipeline::sUseOcclusion;
- LLPipeline::sUseOcclusion = 1;
- LLPipeline::sShadowRender = TRUE;
- //hack to prevent LOD updates from using sun camera origin
- shadow_cam.setOrigin(camera.getOrigin());
- updateCull(shadow_cam, result);
- stateSort(shadow_cam, result);
-
+ stop_glerror();
+
+ mShadow[j].bindTarget();
+ mShadow[j].getViewport(gGLViewport);
+
+ {
+ static LLCullResult result[4];
+
+ //LLGLEnable enable(GL_DEPTH_CLAMP_NV);
+ renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE);
+ }
+
+ mShadow[j].flush();
+
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
{
LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
mShadowCamera[j+4] = shadow_cam;
}
+ }
- LLFastTimer t(LLFastTimer::FTM_SHADOW_RENDER);
+
- stop_glerror();
+ F32 fade_amt = gFrameIntervalSeconds * llmax(LLViewerCamera::getInstance()->getVelocityStat()->getCurrentPerSec(), 1.f);
+
+ //update shadow targets
+ for (U32 i = 0; i < 2; i++)
+ { //for each current shadow
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW4+i;
+
+ if (mShadowSpotLight[i].notNull() &&
+ (mShadowSpotLight[i] == mTargetShadowSpotLight[0] ||
+ mShadowSpotLight[i] == mTargetShadowSpotLight[1]))
+ { //keep this spotlight
+ mSpotLightFade[i] = llmin(mSpotLightFade[i]+fade_amt, 1.f);
+ }
+ else
+ { //fade out this light
+ mSpotLightFade[i] = llmax(mSpotLightFade[i]-fade_amt, 0.f);
+
+ if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull())
+ { //faded out, grab one of the pending spots (whichever one isn't already taken)
+ if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i+1)%2])
+ {
+ mShadowSpotLight[i] = mTargetShadowSpotLight[0];
+ }
+ else
+ {
+ mShadowSpotLight[i] = mTargetShadowSpotLight[1];
+ }
+ }
+ }
+ }
- mSunShadow[j].bindTarget();
- mSunShadow[j].getViewport(gGLViewport);
+ for (S32 i = 0; i < 2; i++)
+ {
+ glh_set_current_modelview(saved_view);
+ glh_set_current_projection(saved_proj);
+ if (mShadowSpotLight[i].isNull())
{
- LLGLDepthTest depth(GL_TRUE);
- mSunShadow[j].clear();
+ continue;
}
- U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY, LLRenderPass::PASS_BUMP };
- LLGLEnable cull(GL_CULL_FACE);
+ LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume();
- //generate sun shadow map
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadMatrixf(proj[j].m);
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadMatrixf(view[j].m);
+ if (!volume)
+ {
+ mShadowSpotLight[i] = NULL;
+ continue;
+ }
- stop_glerror();
- gGLLastMatrix = NULL;
+ LLDrawable* drawable = mShadowSpotLight[i];
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- glColor4f(1,1,1,1);
+ LLVector3 params = volume->getSpotLightParams();
+ F32 fov = params.mV[0];
+
+ //get agent->light space matrix (modelview)
+ LLVector3 center = drawable->getPositionAgent();
+ LLQuaternion quat = volume->getRenderRotation();
+
+ //get near clip plane
+ LLVector3 scale = volume->getScale();
+ LLVector3 at_axis(0,0,-scale.mV[2]*0.5f);
+ at_axis *= quat;
+
+ LLVector3 np = center+at_axis;
+ at_axis.normVec();
+
+ //get origin that has given fov for plane np, at_axis, and given scale
+ F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f);
+
+ LLVector3 origin = np - at_axis*dist;
+
+ LLMatrix4 mat(quat, LLVector4(origin, 1.f));
+
+ view[i+4] = glh::matrix4f((F32*) mat.mMatrix);
+
+ view[i+4] = view[i+4].inverse();
+
+ //get perspective matrix
+ F32 near_clip = dist+0.01f;
+ F32 width = scale.mV[VX];
+ F32 height = scale.mV[VY];
+ F32 far_clip = dist+volume->getLightRadius()*1.5f;
+
+ F32 fovy = fov * RAD_TO_DEG;
+ F32 aspect = width/height;
- glCullFace(GL_FRONT);
+ proj[i+4] = gl_perspective(fovy, aspect, near_clip, far_clip);
- stop_glerror();
+ //translate and scale to from [-1, 1] to [0, 1]
+ glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
+ 0.f, 0.5f, 0.f, 0.5f,
+ 0.f, 0.f, 0.5f, 0.5f,
+ 0.f, 0.f, 0.f, 1.f);
- gGL.setColorMask(false, false);
+ glh_set_current_modelview(view[i+4]);
+ glh_set_current_projection(proj[i+4]);
- gDeferredShadowProgram.bind();
- {
- LLFastTimer ftm(LLFastTimer::FTM_SHADOW_SIMPLE);
- LLGLDisable test(GL_ALPHA_TEST);
- gGL.getTexUnit(0)->disable();
- for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i)
- {
- renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE);
- }
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
- }
+ mSunShadowMatrix[i+4] = trans*proj[i+4]*view[i+4]*inv_view;
+ for (U32 j = 0; j < 16; j++)
{
- LLFastTimer ftm(LLFastTimer::FTM_SHADOW_ALPHA);
- LLGLEnable test(GL_ALPHA_TEST);
- gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.6f);
- renderObjects(LLRenderPass::PASS_ALPHA_SHADOW, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR, TRUE);
- glColor4f(1,1,1,1);
- renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE);
- gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
+ gGLLastModelView[j] = mShadowModelview[i+4].m[j];
+ gGLLastProjection[j] = mShadowProjection[i+4].m[j];
}
-
- gDeferredShadowProgram.unbind();
- renderGeomShadow(shadow_cam);
+ mShadowModelview[i+4] = view[i+4];
+ mShadowProjection[i+4] = proj[i+4];
- gGL.setColorMask(true, true);
+ LLCamera shadow_cam = camera;
+ shadow_cam.setFar(far_clip);
+ shadow_cam.setOrigin(origin);
- glCullFace(GL_BACK);
- LLPipeline::sUseOcclusion = occlude;
- LLPipeline::sShadowRender = FALSE;
- mRenderTypeMask = type_mask;
-
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- gGLLastMatrix = NULL;
+ LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
- mSunShadow[j].flush();
- }
+ stop_glerror();
+
+ mShadow[i+4].bindTarget();
+ mShadow[i+4].getViewport(gGLViewport);
+
+ static LLCullResult result[2];
+
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+i+4;
+
+ renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE);
+
+ mShadow[i+4].flush();
+ }
if (!gSavedSettings.getBOOL("CameraOffset"))
{
@@ -6409,6 +8599,14 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
glMatrixMode(GL_MODELVIEW);
}
gGL.setColorMask(true, false);
+
+ for (U32 i = 0; i < 16; i++)
+ {
+ gGLLastModelView[i] = last_modelview[i];
+ gGLLastProjection[i] = last_projection[i];
+ }
+
+ mRenderTypeMask = type_mask;
}
void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture)
@@ -6417,7 +8615,7 @@ void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL textu
{
LLSpatialGroup* group = *i;
if (!group->isDead() &&
- (!sUseOcclusion || !group->isState(LLSpatialGroup::OCCLUDED)) &&
+ (!sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) &&
gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) &&
group->mDrawMap.find(type) != group->mDrawMap.end())
{
@@ -6428,6 +8626,7 @@ void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL textu
void LLPipeline::generateImpostor(LLVOAvatar* avatar)
{
+ LLMemType mt_gi(LLMemType::MTYPE_PIPELINE_GENERATE_IMPOSTOR);
LLGLState::checkStates();
LLGLState::checkTextureChannels();
LLGLState::checkClientArrays();
@@ -6459,7 +8658,16 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
(1<<LLPipeline::RENDER_TYPE_SIMPLE) |
(1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) |
(1<<LLPipeline::RENDER_TYPE_ALPHA) |
- (1<<LLPipeline::RENDER_TYPE_INVISIBLE);
+ (1<<LLPipeline::RENDER_TYPE_INVISIBLE) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_SIMPLE) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_ALPHA) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_SHINY) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_INVISIBLE) |
+ (1 << LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY);
}
mask = mask & gPipeline.getRenderTypeMask();
@@ -6469,9 +8677,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
S32 occlusion = sUseOcclusion;
sUseOcclusion = 0;
sReflectionRender = sRenderDeferred ? FALSE : TRUE;
+ sShadowRender = TRUE;
sImpostorRender = TRUE;
- markVisible(avatar->mDrawable, *LLViewerCamera::getInstance());
+ LLViewerCamera* viewer_camera = LLViewerCamera::getInstance();
+ markVisible(avatar->mDrawable, *viewer_camera);
LLVOAvatar::sUseImpostors = FALSE;
LLVOAvatar::attachment_map_t::iterator iter;
@@ -6479,10 +8689,15 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
iter != avatar->mAttachmentPoints.end();
++iter)
{
- LLViewerObject* object = iter->second->getObject();
- if (object)
+ LLViewerJointAttachment *attachment = iter->second;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- markVisible(object->mDrawable->getSpatialBridge(), *LLViewerCamera::getInstance());
+ if (LLViewerObject* attached_object = (*attachment_iter))
+ {
+ markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera);
+ }
}
}
@@ -6491,9 +8706,9 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
const LLVector3* ext = avatar->mDrawable->getSpatialExtents();
LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset());
- LLCamera camera = *LLViewerCamera::getInstance();
+ LLCamera camera = *viewer_camera;
- camera.lookAt(LLViewerCamera::getInstance()->getOrigin(), pos, LLViewerCamera::getInstance()->getUpAxis());
+ camera.lookAt(viewer_camera->getOrigin(), pos, viewer_camera->getUpAxis());
LLVector2 tdim;
@@ -6536,7 +8751,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
glClearStencil(0);
// get the number of pixels per angle
- F32 pa = gViewerWindow->getWindowDisplayHeight() / (RAD_TO_DEG * LLViewerCamera::getInstance()->getView());
+ F32 pa = gViewerWindow->getWindowHeightRaw() / (RAD_TO_DEG * viewer_camera->getView());
//get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing)
U32 resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512);
@@ -6545,20 +8760,23 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
if (!avatar->mImpostor.isComplete() || resX != avatar->mImpostor.getWidth() ||
resY != avatar->mImpostor.getHeight())
{
+ avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,TRUE);
+
if (LLPipeline::sRenderDeferred)
{
- avatar->mImpostor.allocate(resX,resY,GL_RGBA16F_ARB,TRUE,TRUE);
addDeferredAttachments(avatar->mImpostor);
}
- else
- {
- avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,TRUE);
- }
+
gGL.getTexUnit(0)->bind(&avatar->mImpostor);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
+ LLGLEnable stencil(GL_STENCIL_TEST);
+ glStencilMask(0xFFFFFFFF);
+ glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+
{
LLGLEnable scissor(GL_SCISSOR_TEST);
glScissor(0, 0, resX, resY);
@@ -6566,15 +8784,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
avatar->mImpostor.clear();
}
- LLGLEnable stencil(GL_STENCIL_TEST);
-
- glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
- glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-
if (LLPipeline::sRenderDeferred)
{
stop_glerror();
renderGeomDeferred(camera);
+ renderGeomPostDeferred(camera);
}
else
{
@@ -6584,11 +8798,16 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_EQUAL, 1, 0xFFFFFF);
- if (!sRenderDeferred || muted)
- {
+ { //create alpha mask based on stencil buffer (grey out if muted)
LLVector3 left = camera.getLeftAxis()*tdim.mV[0]*2.f;
LLVector3 up = camera.getUpAxis()*tdim.mV[1]*2.f;
+ if (LLPipeline::sRenderDeferred)
+ {
+ GLuint buff = GL_COLOR_ATTACHMENT0_EXT;
+ glDrawBuffersARB(1, &buff);
+ }
+
LLGLEnable blend(muted ? 0 : GL_BLEND);
if (muted)
@@ -6627,6 +8846,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
sUseOcclusion = occlusion;
sReflectionRender = FALSE;
sImpostorRender = FALSE;
+ sShadowRender = FALSE;
gPipeline.mRenderTypeMask = saved_mask;
glMatrixMode(GL_PROJECTION);
@@ -6668,3 +8888,4 @@ LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups()
return sCull->endAlphaGroups();
}
+
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 1a32b30831..67004a5f2d 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -33,20 +33,20 @@
#ifndef LL_PIPELINE_H
#define LL_PIPELINE_H
+#include "llcamera.h"
#include "llerror.h"
#include "lldarrayptr.h"
#include "lldqueueptr.h"
-#include "llstat.h"
#include "lldrawpool.h"
#include "llspatialpartition.h"
#include "m4math.h"
-#include "llmemory.h"
+#include "llpointer.h"
#include "lldrawpool.h"
#include "llgl.h"
#include "lldrawable.h"
#include "llrendertarget.h"
-class LLViewerImage;
+class LLViewerTexture;
class LLEdge;
class LLFace;
class LLViewerObject;
@@ -78,6 +78,27 @@ glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar);
glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up);
+extern LLFastTimer::DeclareTimer FTM_RENDER_GEOMETRY;
+extern LLFastTimer::DeclareTimer FTM_RENDER_GRASS;
+extern LLFastTimer::DeclareTimer FTM_RENDER_INVISIBLE;
+extern LLFastTimer::DeclareTimer FTM_RENDER_OCCLUSION;
+extern LLFastTimer::DeclareTimer FTM_RENDER_SHINY;
+extern LLFastTimer::DeclareTimer FTM_RENDER_SIMPLE;
+extern LLFastTimer::DeclareTimer FTM_RENDER_TERRAIN;
+extern LLFastTimer::DeclareTimer FTM_RENDER_TREES;
+extern LLFastTimer::DeclareTimer FTM_RENDER_UI;
+extern LLFastTimer::DeclareTimer FTM_RENDER_WATER;
+extern LLFastTimer::DeclareTimer FTM_RENDER_WL_SKY;
+extern LLFastTimer::DeclareTimer FTM_RENDER_ALPHA;
+extern LLFastTimer::DeclareTimer FTM_RENDER_CHARACTERS;
+extern LLFastTimer::DeclareTimer FTM_RENDER_BUMP;
+extern LLFastTimer::DeclareTimer FTM_RENDER_FULLBRIGHT;
+extern LLFastTimer::DeclareTimer FTM_RENDER_GLOW;
+extern LLFastTimer::DeclareTimer FTM_STATESORT;
+extern LLFastTimer::DeclareTimer FTM_PIPELINE;
+extern LLFastTimer::DeclareTimer FTM_CLIENT_COPY;
+
+
class LLPipeline
{
public:
@@ -104,15 +125,15 @@ public:
/// @brief Get a draw pool from pool type (POOL_SIMPLE, POOL_MEDIA) and texture.
/// @return Draw pool, or NULL if not found.
- LLDrawPool *findPool(const U32 pool_type, LLViewerImage *tex0 = NULL);
+ LLDrawPool *findPool(const U32 pool_type, LLViewerTexture *tex0 = NULL);
/// @brief Get a draw pool for faces of the appropriate type and texture. Create if necessary.
/// @return Always returns a draw pool.
- LLDrawPool *getPool(const U32 pool_type, LLViewerImage *tex0 = NULL);
+ LLDrawPool *getPool(const U32 pool_type, LLViewerTexture *tex0 = NULL);
/// @brief Figures out draw pool type from texture entry. Creates pool if necessary.
- static LLDrawPool* getPoolFromTE(const LLTextureEntry* te, LLViewerImage* te_image);
- static U32 getPoolTypeFromTE(const LLTextureEntry* te, LLViewerImage* imagep);
+ static LLDrawPool* getPoolFromTE(const LLTextureEntry* te, LLViewerTexture* te_image);
+ static U32 getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* imagep);
void addPool(LLDrawPool *poolp); // Only to be used by LLDrawPool classes for splitting pools!
void removePool( LLDrawPool* poolp );
@@ -129,6 +150,8 @@ public:
void markMoved(LLDrawable *drawablep, BOOL damped_motion = FALSE);
void markShift(LLDrawable *drawablep);
void markTextured(LLDrawable *drawablep);
+ void markGLRebuild(LLGLUpdate* glu);
+ void markRebuild(LLSpatialGroup* group, BOOL priority = FALSE);
void markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag = LLDrawable::REBUILD_ALL, BOOL priority = FALSE);
//get the object between start and end that's closest to start.
@@ -150,7 +173,7 @@ public:
);
// Something about these textures has changed. Dirty them.
- void dirtyPoolObjectTextures(const std::set<LLViewerImage*>& textures);
+ void dirtyPoolObjectTextures(const std::set<LLViewerFetchedTexture*>& textures);
void resetDrawOrders();
@@ -179,10 +202,14 @@ public:
void updateMove();
BOOL visibleObjectsInFrustum(LLCamera& camera);
BOOL getVisibleExtents(LLCamera& camera, LLVector3 &min, LLVector3& max);
+ BOOL getVisiblePointCloud(LLCamera& camera, LLVector3 &min, LLVector3& max, std::vector<LLVector3>& fp, LLVector3 light_dir = LLVector3(0,0,0));
void updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip = 0); //if water_clip is 0, ignore water plane, 1, cull to above plane, -1, cull to below plane
void createObjects(F32 max_dtime);
void createObject(LLViewerObject* vobj);
void updateGeom(F32 max_dtime);
+ void updateGL();
+ void rebuildPriorityGroups();
+ void rebuildGroups();
//calculate pixel area of given box from vantage point of given camera
static F32 calcPixelArea(LLVector3 center, LLVector3 size, LLCamera& camera);
@@ -203,12 +230,21 @@ public:
void renderGeomDeferred(LLCamera& camera);
void renderGeomPostDeferred(LLCamera& camera);
void renderGeomShadow(LLCamera& camera);
- void bindDeferredShader(LLGLSLShader& shader, U32 light_index = 0);
+ void bindDeferredShader(LLGLSLShader& shader, U32 light_index = 0, LLRenderTarget* gi_source = NULL, LLRenderTarget* last_gi_post = NULL, U32 noise_map = 0xFFFFFFFF);
+ void setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep);
+
void unbindDeferredShader(LLGLSLShader& shader);
void renderDeferredLighting();
void generateWaterReflection(LLCamera& camera);
void generateSunShadow(LLCamera& camera);
+ void generateHighlight(LLCamera& camera);
+ void renderHighlight(const LLViewerObject* obj, F32 fade);
+ void setHighlightObject(LLDrawable* obj) { mHighlightObject = obj; }
+
+
+ void renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& camera, LLCullResult& result, BOOL use_shader = TRUE, BOOL use_occlusion = TRUE);
+ void generateGI(LLCamera& camera, LLVector3& lightDir, std::vector<LLVector3>& vpc);
void renderHighlights();
void renderDebug();
@@ -303,23 +339,35 @@ public:
enum LLRenderTypeMask
{
// Following are pool types (some are also object types)
- RENDER_TYPE_SKY = LLDrawPool::POOL_SKY,
- RENDER_TYPE_WL_SKY = LLDrawPool::POOL_WL_SKY,
- RENDER_TYPE_GROUND = LLDrawPool::POOL_GROUND,
- RENDER_TYPE_TERRAIN = LLDrawPool::POOL_TERRAIN,
- RENDER_TYPE_SIMPLE = LLDrawPool::POOL_SIMPLE,
- RENDER_TYPE_GRASS = LLDrawPool::POOL_GRASS,
- RENDER_TYPE_FULLBRIGHT = LLDrawPool::POOL_FULLBRIGHT,
- RENDER_TYPE_BUMP = LLDrawPool::POOL_BUMP,
- RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR,
- RENDER_TYPE_TREE = LLDrawPool::POOL_TREE,
- RENDER_TYPE_INVISIBLE = LLDrawPool::POOL_INVISIBLE,
- RENDER_TYPE_WATER = LLDrawPool::POOL_WATER,
- RENDER_TYPE_ALPHA = LLDrawPool::POOL_ALPHA,
- RENDER_TYPE_GLOW = LLDrawPool::POOL_GLOW,
-
+ RENDER_TYPE_SKY = LLDrawPool::POOL_SKY,
+ RENDER_TYPE_WL_SKY = LLDrawPool::POOL_WL_SKY,
+ RENDER_TYPE_GROUND = LLDrawPool::POOL_GROUND,
+ RENDER_TYPE_TERRAIN = LLDrawPool::POOL_TERRAIN,
+ RENDER_TYPE_SIMPLE = LLDrawPool::POOL_SIMPLE,
+ RENDER_TYPE_GRASS = LLDrawPool::POOL_GRASS,
+ RENDER_TYPE_FULLBRIGHT = LLDrawPool::POOL_FULLBRIGHT,
+ RENDER_TYPE_BUMP = LLDrawPool::POOL_BUMP,
+ RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR,
+ RENDER_TYPE_TREE = LLDrawPool::POOL_TREE,
+ RENDER_TYPE_INVISIBLE = LLDrawPool::POOL_INVISIBLE,
+ RENDER_TYPE_WATER = LLDrawPool::POOL_WATER,
+ RENDER_TYPE_ALPHA = LLDrawPool::POOL_ALPHA,
+ RENDER_TYPE_GLOW = LLDrawPool::POOL_GLOW,
+ RENDER_TYPE_PASS_SIMPLE = LLRenderPass::PASS_SIMPLE,
+ RENDER_TYPE_PASS_GRASS = LLRenderPass::PASS_GRASS,
+ RENDER_TYPE_PASS_FULLBRIGHT = LLRenderPass::PASS_FULLBRIGHT,
+ RENDER_TYPE_PASS_INVISIBLE = LLRenderPass::PASS_INVISIBLE,
+ RENDER_TYPE_PASS_INVISI_SHINY = LLRenderPass::PASS_INVISI_SHINY,
+ RENDER_TYPE_PASS_FULLBRIGHT_SHINY = LLRenderPass::PASS_FULLBRIGHT_SHINY,
+ RENDER_TYPE_PASS_SHINY = LLRenderPass::PASS_SHINY,
+ RENDER_TYPE_PASS_BUMP = LLRenderPass::PASS_BUMP,
+ RENDER_TYPE_PASS_GLOW = LLRenderPass::PASS_GLOW,
+ RENDER_TYPE_PASS_ALPHA = LLRenderPass::PASS_ALPHA,
+ RENDER_TYPE_PASS_ALPHA_MASK = LLRenderPass::PASS_ALPHA_MASK,
+ RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK = LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK,
+ RENDER_TYPE_PASS_ALPHA_SHADOW = LLRenderPass::PASS_ALPHA_SHADOW,
// Following are object types (only used in drawable mRenderType)
- RENDER_TYPE_HUD = LLDrawPool::NUM_POOL_TYPES,
+ RENDER_TYPE_HUD = LLRenderPass::NUM_RENDER_TYPES,
RENDER_TYPE_VOLUME,
RENDER_TYPE_PARTICLES,
RENDER_TYPE_CLOUDS,
@@ -362,7 +410,8 @@ public:
RENDER_DEBUG_SHADOW_FRUSTA = 0x0040000,
RENDER_DEBUG_SCULPTED = 0x0080000,
RENDER_DEBUG_AVATAR_VOLUME = 0x0100000,
- RENDER_DEBUG_AGENT_TARGET = 0x0200000,
+ RENDER_DEBUG_BUILD_QUEUE = 0x0200000,
+ RENDER_DEBUG_AGENT_TARGET = 0x0400000,
};
public:
@@ -383,7 +432,6 @@ public:
S32 mMeanBatchSize;
S32 mTrianglesDrawn;
S32 mNumVisibleNodes;
- LLStat mTrianglesDrawnStat;
S32 mVerticesRelit;
S32 mLightingChanges;
@@ -403,7 +451,6 @@ public:
static BOOL sUseFBO;
static BOOL sUseFarClip;
static BOOL sShadowRender;
- static BOOL sSkipUpdate; //skip lod updates
static BOOL sWaterReflections;
static BOOL sDynamicLOD;
static BOOL sPickAvatar;
@@ -417,19 +464,50 @@ public:
static BOOL sRenderAttachedParticles;
static BOOL sRenderDeferred;
static S32 sVisibleLightCount;
+ static F32 sMinRenderSize;
//screen texture
+ U32 mScreenWidth;
+ U32 mScreenHeight;
+
LLRenderTarget mScreen;
+ LLRenderTarget mUIScreen;
LLRenderTarget mDeferredScreen;
- LLRenderTarget mDeferredLight[2];
+ LLRenderTarget mEdgeMap;
+ LLRenderTarget mDeferredDepth;
+ LLRenderTarget mDeferredLight[3];
LLMultisampleBuffer mSampleBuffer;
+ LLRenderTarget mGIMap;
+ LLRenderTarget mGIMapPost[2];
+ LLRenderTarget mLuminanceMap;
+ LLRenderTarget mHighlight;
//sun shadow map
- LLRenderTarget mSunShadow[4];
+ LLRenderTarget mShadow[6];
+ std::vector<LLVector3> mShadowFrustPoints[4];
+ LLVector4 mShadowError;
+ LLVector4 mShadowFOV;
+ LLVector3 mShadowFrustOrigin[4];
LLCamera mShadowCamera[8];
LLVector3 mShadowExtents[4][2];
- glh::matrix4f mSunShadowMatrix[4];
+ glh::matrix4f mSunShadowMatrix[6];
+ glh::matrix4f mShadowModelview[6];
+ glh::matrix4f mShadowProjection[6];
+ glh::matrix4f mGIMatrix;
+ glh::matrix4f mGIMatrixProj;
+ glh::matrix4f mGIModelview;
+ glh::matrix4f mGIProjection;
+ glh::matrix4f mGINormalMatrix;
+ glh::matrix4f mGIInvProj;
+ LLVector2 mGIRange;
+ F32 mGILightRadius;
+
+ LLPointer<LLDrawable> mShadowSpotLight[2];
+ F32 mSpotLightFade[2];
+ LLPointer<LLDrawable> mTargetShadowSpotLight[2];
+
LLVector4 mSunClipPlanes;
+ LLVector4 mSunOrthoClipPlanes;
LLVector2 mScreenScale;
@@ -444,6 +522,8 @@ public:
//noise map
U32 mNoiseMap;
+ U32 mTrueNoiseMap;
+ U32 mLightFunc;
LLColor4 mSunDiffuse;
LLVector3 mSunDir;
@@ -504,12 +584,45 @@ protected:
//
LLDrawable::drawable_list_t mBuildQ1; // priority
LLDrawable::drawable_list_t mBuildQ2; // non-priority
+ LLSpatialGroup::sg_list_t mGroupQ1; //priority
+ LLSpatialGroup::sg_vector_t mGroupQ2; // non-priority
+
LLViewerObject::vobj_list_t mCreateQ;
LLDrawable::drawable_set_t mActiveQ;
LLDrawable::drawable_set_t mRetexturedList;
+ class HighlightItem
+ {
+ public:
+ const LLPointer<LLDrawable> mItem;
+ mutable F32 mFade;
+
+ HighlightItem(LLDrawable* item)
+ : mItem(item), mFade(0)
+ {
+ }
+
+ bool operator<(const HighlightItem& rhs) const
+ {
+ return mItem < rhs.mItem;
+ }
+
+ bool operator==(const HighlightItem& rhs) const
+ {
+ return mItem == rhs.mItem;
+ }
+
+ void incrFade(F32 val) const
+ {
+ mFade = llclamp(mFade+val, 0.f, 1.f);
+ }
+ };
+
+ std::set<HighlightItem> mHighlightSet;
+ LLPointer<LLDrawable> mHighlightObject;
+
//////////////////////////////////////////////////
//
// Draw pools are responsible for storing all rendered data,
@@ -562,9 +675,9 @@ public:
protected:
std::vector<LLFace*> mSelectedFaces;
- LLPointer<LLViewerImage> mFaceSelectImagep;
- LLPointer<LLViewerImage> mBloomImagep;
- LLPointer<LLViewerImage> mBloomImage2p;
+ LLPointer<LLViewerFetchedTexture> mFaceSelectImagep;
+ LLPointer<LLViewerTexture> mBloomImagep;
+ LLPointer<LLViewerTexture> mBloomImage2p;
U32 mLightMask;
U32 mLightMovingMask;
diff --git a/indra/newview/pl.lproj/language.txt b/indra/newview/pl.lproj/language.txt
new file mode 100644
index 0000000000..55239f3c18
--- /dev/null
+++ b/indra/newview/pl.lproj/language.txt
@@ -0,0 +1 @@
+pl \ No newline at end of file
diff --git a/indra/newview/pt.lproj/language.txt b/indra/newview/pt.lproj/language.txt
new file mode 100644
index 0000000000..9e3340eca2
--- /dev/null
+++ b/indra/newview/pt.lproj/language.txt
@@ -0,0 +1 @@
+pt \ No newline at end of file
diff --git a/indra/newview/res-sdl/arrow.BMP b/indra/newview/res-sdl/arrow.BMP
new file mode 100644
index 0000000000..a8f6da64b5
--- /dev/null
+++ b/indra/newview/res-sdl/arrow.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/arrowcop.BMP b/indra/newview/res-sdl/arrowcop.BMP
new file mode 100644
index 0000000000..1a26a0df34
--- /dev/null
+++ b/indra/newview/res-sdl/arrowcop.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/arrowcopmulti.BMP b/indra/newview/res-sdl/arrowcopmulti.BMP
new file mode 100644
index 0000000000..48f153cef6
--- /dev/null
+++ b/indra/newview/res-sdl/arrowcopmulti.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/arrowdrag.BMP b/indra/newview/res-sdl/arrowdrag.BMP
new file mode 100644
index 0000000000..cd868eec20
--- /dev/null
+++ b/indra/newview/res-sdl/arrowdrag.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/circleandline.BMP b/indra/newview/res-sdl/circleandline.BMP
new file mode 100644
index 0000000000..284ae8b7d5
--- /dev/null
+++ b/indra/newview/res-sdl/circleandline.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/cross.BMP b/indra/newview/res-sdl/cross.BMP
new file mode 100644
index 0000000000..0b4672d4d6
--- /dev/null
+++ b/indra/newview/res-sdl/cross.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/hand.BMP b/indra/newview/res-sdl/hand.BMP
new file mode 100644
index 0000000000..2a092fbb7f
--- /dev/null
+++ b/indra/newview/res-sdl/hand.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/ibeam.BMP b/indra/newview/res-sdl/ibeam.BMP
new file mode 100644
index 0000000000..820904a228
--- /dev/null
+++ b/indra/newview/res-sdl/ibeam.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/ll_icon.BMP b/indra/newview/res-sdl/ll_icon.BMP
new file mode 100644
index 0000000000..4a44aafbfa
--- /dev/null
+++ b/indra/newview/res-sdl/ll_icon.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/llarrow.BMP b/indra/newview/res-sdl/llarrow.BMP
new file mode 100644
index 0000000000..a8f6da64b5
--- /dev/null
+++ b/indra/newview/res-sdl/llarrow.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/llarrowdrag.BMP b/indra/newview/res-sdl/llarrowdrag.BMP
new file mode 100644
index 0000000000..cd868eec20
--- /dev/null
+++ b/indra/newview/res-sdl/llarrowdrag.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/llarrowdragmulti.BMP b/indra/newview/res-sdl/llarrowdragmulti.BMP
new file mode 100644
index 0000000000..fb528bc92d
--- /dev/null
+++ b/indra/newview/res-sdl/llarrowdragmulti.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/llarrowlocked.BMP b/indra/newview/res-sdl/llarrowlocked.BMP
new file mode 100644
index 0000000000..0aaa441ab1
--- /dev/null
+++ b/indra/newview/res-sdl/llarrowlocked.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/llgrablocked.BMP b/indra/newview/res-sdl/llgrablocked.BMP
new file mode 100644
index 0000000000..847439670f
--- /dev/null
+++ b/indra/newview/res-sdl/llgrablocked.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/llno.BMP b/indra/newview/res-sdl/llno.BMP
new file mode 100644
index 0000000000..284ae8b7d5
--- /dev/null
+++ b/indra/newview/res-sdl/llno.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/llnolocked.BMP b/indra/newview/res-sdl/llnolocked.BMP
new file mode 100644
index 0000000000..61f0170cb3
--- /dev/null
+++ b/indra/newview/res-sdl/llnolocked.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/lltoolcamera.BMP b/indra/newview/res-sdl/lltoolcamera.BMP
new file mode 100644
index 0000000000..c961d7a49c
--- /dev/null
+++ b/indra/newview/res-sdl/lltoolcamera.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/lltoolcreate.BMP b/indra/newview/res-sdl/lltoolcreate.BMP
new file mode 100644
index 0000000000..08a4a9322d
--- /dev/null
+++ b/indra/newview/res-sdl/lltoolcreate.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/lltoolfocus.BMP b/indra/newview/res-sdl/lltoolfocus.BMP
new file mode 100644
index 0000000000..afb90a95e3
--- /dev/null
+++ b/indra/newview/res-sdl/lltoolfocus.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/lltoolgrab.BMP b/indra/newview/res-sdl/lltoolgrab.BMP
new file mode 100644
index 0000000000..f2ac68bf3c
--- /dev/null
+++ b/indra/newview/res-sdl/lltoolgrab.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/lltoolland.BMP b/indra/newview/res-sdl/lltoolland.BMP
new file mode 100644
index 0000000000..64e6365625
--- /dev/null
+++ b/indra/newview/res-sdl/lltoolland.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/lltoolpan.BMP b/indra/newview/res-sdl/lltoolpan.BMP
new file mode 100644
index 0000000000..ffbef21ec7
--- /dev/null
+++ b/indra/newview/res-sdl/lltoolpan.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/lltoolpipette.BMP b/indra/newview/res-sdl/lltoolpipette.BMP
new file mode 100644
index 0000000000..2d27118289
--- /dev/null
+++ b/indra/newview/res-sdl/lltoolpipette.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/lltoolrotate.BMP b/indra/newview/res-sdl/lltoolrotate.BMP
new file mode 100644
index 0000000000..dd84673018
--- /dev/null
+++ b/indra/newview/res-sdl/lltoolrotate.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/lltoolscale.BMP b/indra/newview/res-sdl/lltoolscale.BMP
new file mode 100644
index 0000000000..882515e5e3
--- /dev/null
+++ b/indra/newview/res-sdl/lltoolscale.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/lltooltranslate.BMP b/indra/newview/res-sdl/lltooltranslate.BMP
new file mode 100644
index 0000000000..d084f6a026
--- /dev/null
+++ b/indra/newview/res-sdl/lltooltranslate.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/lltoolzoomin.BMP b/indra/newview/res-sdl/lltoolzoomin.BMP
new file mode 100644
index 0000000000..e4e46cc702
--- /dev/null
+++ b/indra/newview/res-sdl/lltoolzoomin.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/lltoolzoomout.BMP b/indra/newview/res-sdl/lltoolzoomout.BMP
new file mode 100644
index 0000000000..7f958383ab
--- /dev/null
+++ b/indra/newview/res-sdl/lltoolzoomout.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/sizenesw.BMP b/indra/newview/res-sdl/sizenesw.BMP
new file mode 100644
index 0000000000..559579f40e
--- /dev/null
+++ b/indra/newview/res-sdl/sizenesw.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/sizens.BMP b/indra/newview/res-sdl/sizens.BMP
new file mode 100644
index 0000000000..8373077dff
--- /dev/null
+++ b/indra/newview/res-sdl/sizens.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/sizenwse.BMP b/indra/newview/res-sdl/sizenwse.BMP
new file mode 100644
index 0000000000..6d069fa765
--- /dev/null
+++ b/indra/newview/res-sdl/sizenwse.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/sizewe.BMP b/indra/newview/res-sdl/sizewe.BMP
new file mode 100644
index 0000000000..878df453a4
--- /dev/null
+++ b/indra/newview/res-sdl/sizewe.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/toolmediaopen.BMP b/indra/newview/res-sdl/toolmediaopen.BMP
new file mode 100644
index 0000000000..ac4b231994
--- /dev/null
+++ b/indra/newview/res-sdl/toolmediaopen.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/toolpause.BMP b/indra/newview/res-sdl/toolpause.BMP
new file mode 100644
index 0000000000..dd2c6857d2
--- /dev/null
+++ b/indra/newview/res-sdl/toolpause.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/toolpickobject.BMP b/indra/newview/res-sdl/toolpickobject.BMP
new file mode 100644
index 0000000000..25469fc3a8
--- /dev/null
+++ b/indra/newview/res-sdl/toolpickobject.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/toolpickobject2.BMP b/indra/newview/res-sdl/toolpickobject2.BMP
new file mode 100644
index 0000000000..09df69e675
--- /dev/null
+++ b/indra/newview/res-sdl/toolpickobject2.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/toolpickobject3.BMP b/indra/newview/res-sdl/toolpickobject3.BMP
new file mode 100644
index 0000000000..fc28698050
--- /dev/null
+++ b/indra/newview/res-sdl/toolpickobject3.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/toolplay.BMP b/indra/newview/res-sdl/toolplay.BMP
new file mode 100644
index 0000000000..9c40d7dbec
--- /dev/null
+++ b/indra/newview/res-sdl/toolplay.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/wait.BMP b/indra/newview/res-sdl/wait.BMP
new file mode 100644
index 0000000000..26dec59afe
--- /dev/null
+++ b/indra/newview/res-sdl/wait.BMP
Binary files differ
diff --git a/indra/newview/res-sdl/working.BMP b/indra/newview/res-sdl/working.BMP
new file mode 100644
index 0000000000..26dec59afe
--- /dev/null
+++ b/indra/newview/res-sdl/working.BMP
Binary files differ
diff --git a/indra/newview/res/bitmap2.bmp b/indra/newview/res/bitmap2.bmp
new file mode 100644
index 0000000000..770b07558c
--- /dev/null
+++ b/indra/newview/res/bitmap2.bmp
Binary files differ
diff --git a/indra/newview/res/install_icon.BMP b/indra/newview/res/install_icon.BMP
new file mode 100644
index 0000000000..09df573870
--- /dev/null
+++ b/indra/newview/res/install_icon.BMP
Binary files differ
diff --git a/indra/newview/res/loginbackground.bmp b/indra/newview/res/loginbackground.bmp
new file mode 100644
index 0000000000..288a0b0398
--- /dev/null
+++ b/indra/newview/res/loginbackground.bmp
Binary files differ
diff --git a/indra/newview/res/toolbuy.cur b/indra/newview/res/toolbuy.cur
deleted file mode 100644
index c61cd76bef..0000000000
--- a/indra/newview/res/toolbuy.cur
+++ /dev/null
Binary files differ
diff --git a/indra/newview/res/toolopen.cur b/indra/newview/res/toolopen.cur
deleted file mode 100644
index 8408f7c7eb..0000000000
--- a/indra/newview/res/toolopen.cur
+++ /dev/null
Binary files differ
diff --git a/indra/newview/res/toolsit.cur b/indra/newview/res/toolsit.cur
deleted file mode 100644
index 60b0e773e5..0000000000
--- a/indra/newview/res/toolsit.cur
+++ /dev/null
Binary files differ
diff --git a/indra/newview/res/uninstall_icon.BMP b/indra/newview/res/uninstall_icon.BMP
new file mode 100644
index 0000000000..562b56676a
--- /dev/null
+++ b/indra/newview/res/uninstall_icon.BMP
Binary files differ
diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc
index a902a6dff0..38291e45c9 100644
--- a/indra/newview/res/viewerRes.rc
+++ b/indra/newview/res/viewerRes.rc
@@ -123,10 +123,6 @@ TOOLPICKOBJECT3 CURSOR "toolpickobject3.cur"
ARROWCOPY CURSOR "arrowcop.cur"
ARROWDRAGMULTI CURSOR "llarrowdragmulti.cur"
ARROWCOPYMULTI CURSOR "arrowcopmulti.cur"
-TOOLSIT CURSOR "toolsit.cur"
-TOOLBUY CURSOR "toolbuy.cur"
-TOOLPAY CURSOR "toolpay.cur"
-TOOLOPEN CURSOR "toolopen.cur"
TOOLPIPETTE CURSOR "toolpipette.cur"
TOOLPLAY CURSOR "toolplay.cur"
TOOLPAUSE CURSOR "toolpause.cur"
@@ -138,8 +134,8 @@ TOOLMEDIAOPEN CURSOR "toolmediaopen.cur"
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,24,0,0
- PRODUCTVERSION 1,24,0,0
+ FILEVERSION 2,0,0,200030
+ PRODUCTVERSION 2,0,0,200030
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -156,12 +152,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Linden Lab"
VALUE "FileDescription", "Second Life"
- VALUE "FileVersion", "1.24.0.0"
+ VALUE "FileVersion", "2.0.0.200030"
VALUE "InternalName", "Second Life"
VALUE "LegalCopyright", "Copyright © 2001-2008, Linden Research, Inc."
VALUE "OriginalFilename", "SecondLife.exe"
VALUE "ProductName", "Second Life"
- VALUE "ProductVersion", "1.24.0.0"
+ VALUE "ProductVersion", "2.0.0.200030"
END
END
BLOCK "VarFileInfo"
diff --git a/indra/newview/ru.lproj/language.txt b/indra/newview/ru.lproj/language.txt
new file mode 100644
index 0000000000..adc719b423
--- /dev/null
+++ b/indra/newview/ru.lproj/language.txt
@@ -0,0 +1 @@
+ru \ No newline at end of file
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index cf9466fad3..e248047930 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -1,3 +1,724 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<settings version = "101">
-</settings>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<colors>
+
+ <!-- Named Colors -->
+ <color
+ name="EmphasisColor"
+ value="0.38 0.694 0.573 1" />
+ <color
+ name="EmphasisColor_13"
+ value="0.38 0.694 0.573 0.13" />
+ <color
+ name="EmphasisColor_35"
+ value="0.38 0.694 0.573 0.35" />
+ <color
+ name="White"
+ value="1 1 1 1" />
+ <color
+ name="White_05"
+ value="1 1 1 0.05" />
+ <color
+ name="White_10"
+ value="1 1 1 0.1" />
+ <color
+ name="White_25"
+ value="1 1 1 0.25" />
+ <color
+ name="White_50"
+ value="1 1 1 0.5" />
+ <color
+ name="LtGray"
+ value="0.75 0.75 0.75 1" />
+ <color
+ name="LtGray_50"
+ value="0.75 0.75 0.75 0.50" />
+ <color
+ name="DkGray"
+ value="0.125 0.125 0.125 1" />
+ <color
+ name="DkGray_66"
+ value="0.125 0.125 0.125 .66" />
+ <color
+ name="DkGray2"
+ value="0.169 0.169 0.169 1" />
+ <color
+ name="MouseGray"
+ value="0.191 0.191 0.191 1" />
+ <color
+ name="Black"
+ value="0 0 0 1" />
+ <color
+ name="Black_10"
+ value="0 0 0 0.1" />
+ <color
+ name="Black_25"
+ value="0 0 0 0.25" />
+ <color
+ name="Black_50"
+ value="0 0 0 0.5" />
+ <color
+ name="FrogGreen"
+ value="0.26 0.345 0.263 1" />
+ <color
+ name="Red"
+ value="0.729 0 0.121 1" />
+ <color
+ name="Blue"
+ value="0 0 1 1" />
+ <color
+ name="Yellow"
+ value="1 1 0 1" />
+ <color
+ name="Green"
+ value="0 1 0 1" />
+ <color
+ name="Transparent"
+ value="0 0 0 0" />
+ <color
+ name="Purple"
+ value="1 0 1 1" />
+ <!-- This color name makes potentially unused colors show up bright purple.
+ Leave this here until all Unused? are removed below, otherwise
+ the viewer generates many warnings on startup. -->
+ <color
+ name="Unused?"
+ value=".831 1 0 1" />
+
+ <!-- UI Definitions -->
+
+ <color
+ name="AgentChatColor"
+ reference="White" />
+ <color
+ name="AlertBoxColor"
+ value="0.24 0.24 0.24 1" />
+ <color
+ name="AlertCautionBoxColor"
+ value="1 0.82 0.46 1" />
+ <color
+ name="AlertCautionTextColor"
+ reference="Black" />
+ <color
+ name="AgentLinkColor"
+ reference="White" />
+ <color
+ name="AlertTextColor"
+ value="0.58 0.66 0.84 1" />
+ <color
+ name="AvatarNameColor"
+ reference="White" />
+ <color
+ name="AvatarListItemIconDefaultColor"
+ reference="White" />
+ <color
+ name="AvatarListItemIconOnlineColor"
+ reference="White" />
+ <color
+ name="AvatarListItemIconOfflineColor"
+ value="0.5 0.5 0.5 0.5" />
+ <color
+ name="AvatarListItemIconVoiceInvitedColor"
+ reference="AvatarListItemIconOfflineColor" />
+ <color
+ name="AvatarListItemIconVoiceJoinedColor"
+ reference="AvatarListItemIconOnlineColor" />
+ <color
+ name="AvatarListItemIconVoiceLeftColor"
+ reference="AvatarListItemIconOfflineColor" />
+ <color
+ name="BackgroundChatColor"
+ reference="DkGray_66" />
+ <color
+ name="ButtonBorderColor"
+ reference="Unused?" />
+ <color
+ name="ButtonCautionImageColor"
+ reference="Unused?" />
+ <color
+ name="ButtonColor"
+ reference="Unused?" />
+ <color
+ name="ButtonFlashBgColor"
+ reference="Unused?" />
+ <color
+ name="ButtonImageColor"
+ reference="White" />
+ <color
+ name="ButtonLabelColor"
+ reference="LtGray" />
+ <color
+ name="ButtonLabelDisabledColor"
+ reference="White_25" />
+ <color
+ name="ButtonLabelSelectedColor"
+ reference="White" />
+ <color
+ name="ButtonLabelSelectedDisabledColor"
+ reference="White_25" />
+ <color
+ name="ButtonSelectedBgColor"
+ reference="Unused?" />
+ <color
+ name="ButtonSelectedColor"
+ reference="Unused?" />
+ <color
+ name="ButtonUnselectedBgColor"
+ reference="Unused?" />
+ <color
+ name="ButtonUnselectedFgColor"
+ reference="Unused?" />
+ <color
+ name="ChatHistoryBgColor"
+ reference="Transparent" />
+ <color
+ name="ChatHistoryTextColor"
+ reference="LtGray" />
+ <color
+ name="ChicletFlashColor"
+ value="0.114 0.65 0.1" />
+ <color
+ name="ColorDropShadow"
+ reference="Black_50" />
+ <color
+ name="ColorPaletteEntry01"
+ reference="Black" />
+ <color
+ name="ColorPaletteEntry02"
+ value="0.5 0.5 0.5 1" />
+ <color
+ name="ColorPaletteEntry03"
+ value="0.3344 0.5456 0.5159 1" />
+ <color
+ name="ColorPaletteEntry04"
+ value="0.5 0.5 0 1" />
+ <color
+ name="ColorPaletteEntry05"
+ value="0 0.5 0 1" />
+ <color
+ name="ColorPaletteEntry06"
+ value="0 0.5 0.5 1" />
+ <color
+ name="ColorPaletteEntry07"
+ value="0 0 0.5 1" />
+ <color
+ name="ColorPaletteEntry08"
+ value="0.5 0 0.5 1" />
+ <color
+ name="ColorPaletteEntry09"
+ value="0.5 0.5 0 1" />
+ <color
+ name="ColorPaletteEntry10"
+ value="0 0.25 0.25 1" />
+ <color
+ name="ColorPaletteEntry11"
+ value="0 0.5 1 1" />
+ <color
+ name="ColorPaletteEntry12"
+ value="0 0.25 0.5 1" />
+ <color
+ name="ColorPaletteEntry13"
+ value="0.5 0 1 1" />
+ <color
+ name="ColorPaletteEntry14"
+ value="0.5 0.25 0 1" />
+ <color
+ name="ColorPaletteEntry15"
+ reference="White" />
+ <color
+ name="ColorPaletteEntry16"
+ reference="White" />
+ <color
+ name="ColorPaletteEntry17"
+ reference="White" />
+ <color
+ name="ColorPaletteEntry18"
+ reference="LtGray" />
+ <color
+ name="ColorPaletteEntry19"
+ reference="Red" />
+ <color
+ name="ColorPaletteEntry20"
+ reference=".5 .5 1 0" />
+ <color
+ name="ColorPaletteEntry21"
+ reference="Green" />
+ <color
+ name="ColorPaletteEntry22"
+ value="0 1 1 1" />
+ <color
+ name="ColorPaletteEntry23"
+ reference="Blue" />
+ <color
+ name="ColorPaletteEntry24"
+ reference="Purple" />
+ <color
+ name="ColorPaletteEntry25"
+ value="1 1 0.5 1" />
+ <color
+ name="ColorPaletteEntry26"
+ value="0 1 0.5 1" />
+ <color
+ name="ColorPaletteEntry27"
+ value="0.5 1 1 1" />
+ <color
+ name="ColorPaletteEntry28"
+ value="0.5 0.5 1 1" />
+ <color
+ name="ColorPaletteEntry29"
+ value="1 0 0.5 1" />
+ <color
+ name="ColorPaletteEntry30"
+ value="1 0.5 0 1" />
+ <color
+ name="ColorPaletteEntry31"
+ reference="White" />
+ <color
+ name="ColorPaletteEntry32"
+ reference="White" />
+ <color
+ name="ConsoleBackground"
+ reference="Black" />
+ <color
+ name="ContextSilhouetteColor"
+ value="0.94 0.61 0 1" />
+ <color
+ name="DefaultHighlightDark"
+ reference="White_10" />
+ <color
+ name="DefaultHighlightLight"
+ reference="White_25" />
+ <color
+ name="DefaultShadowDark"
+ reference="Black_50" />
+ <color
+ name="DefaultShadowLight"
+ reference="Black_50" />
+ <color
+ name="EffectColor"
+ reference="White" />
+ <color
+ name="FilterBackgroundColor"
+ reference="Black" />
+ <color
+ name="FilterTextColor"
+ value="0.38 0.69 0.57 1" />
+ <color
+ name="FloaterButtonImageColor"
+ reference="LtGray" />
+ <color
+ name="FloaterDefaultBackgroundColor"
+ reference="DkGray_66" />
+ <color
+ name="FloaterFocusBackgroundColor"
+ reference="DkGray2" />
+ <color
+ name="FloaterFocusBorderColor"
+ reference="Black_50" />
+ <color
+ name="FloaterUnfocusBorderColor"
+ reference="Black_50" />
+ <color
+ name="FocusColor"
+ reference="EmphasisColor" />
+ <color
+ name="FolderViewLoadingMessageTextColor"
+ value="0.3344 0.5456 0.5159 1" />
+ <color
+ name="GridFocusPointColor"
+ reference="White_50" />
+ <color
+ name="GridlineBGColor"
+ value="0.92 0.92 1 0.78" />
+ <color
+ name="GridlineColor"
+ reference="Red" />
+ <color
+ name="GridlineShadowColor"
+ value="0 0 0 0.31" />
+ <color
+ name="GroupLinkColor"
+ reference="White" />
+ <color
+ name="GroupNotifyBoxColor"
+ value="0.3344 0.5456 0.5159 1" />
+ <color
+ name="GroupNotifyTextColor"
+ reference="White"/>
+ <color
+ name="GroupNotifyDimmedTextColor"
+ reference="DkGray" />
+ <color
+ name="GroupOverTierColor"
+ value="0.43 0.06 0.06 1" />
+ <color
+ name="HTMLLinkColor"
+ reference="EmphasisColor" />
+ <color
+ name="HealthTextColor"
+ reference="White" />
+ <color
+ name="HelpBgColor"
+ reference="Unused?" />
+ <color
+ name="HelpFgColor"
+ reference="Unused?" />
+ <color
+ name="HelpScrollHighlightColor"
+ reference="Unused?" />
+ <color
+ name="HelpScrollShadowColor"
+ reference="Unused?" />
+ <color
+ name="HelpScrollThumbColor"
+ reference="Unused?" />
+ <color
+ name="HelpScrollTrackColor"
+ reference="Unused?" />
+ <color
+ name="HighlightChildColor"
+ reference="Yellow" />
+ <color
+ name="HighlightInspectColor"
+ value="1 0.5 0 1" />
+ <color
+ name="HighlightParentColor"
+ value="0.67 0.83 0.96 1" />
+ <color
+ name="IMChatColor"
+ reference="LtGray" />
+ <color
+ name="IMHistoryBgColor"
+ reference="Unused?" />
+ <color
+ name="IMHistoryTextColor"
+ reference="Unused?" />
+ <color
+ name="IconDisabledColor"
+ reference="White_25" />
+ <color
+ name="IconEnabledColor"
+ reference="White" />
+ <color
+ name="InventoryBackgroundColor"
+ reference="DkGray2" />
+ <color
+ name="InventoryFocusOutlineColor"
+ reference="White_25" />
+ <color
+ name="InventoryItemSuffixColor"
+ reference="White_25" />
+ <color
+ name="InventorySearchStatusColor"
+ reference="EmphasisColor" />
+ <color
+ name="LabelDisabledColor"
+ reference="White_25" />
+ <color
+ name="LabelSelectedColor"
+ reference="White" />
+ <color
+ name="LabelSelectedDisabledColor"
+ reference="White_25" />
+ <color
+ name="LabelTextColor"
+ reference="LtGray" />
+ <color
+ name="LoginProgressBarBgColor"
+ reference="Unused?" />
+ <color
+ name="LoginProgressBarFgColor"
+ reference="Unused?" />
+ <color
+ name="LoginProgressBoxBorderColor"
+ value="0 0.12 0.24 0" />
+ <color
+ name="LoginProgressBoxCenterColor"
+ value="0 0 0 0.78" />
+ <color
+ name="LoginProgressBoxShadowColor"
+ value="0 0 0 0.78" />
+ <color
+ name="LoginProgressBoxTextColor"
+ reference="White" />
+ <color
+ name="MapAvatarColor"
+ reference="Green" />
+ <color
+ name="MapAvatarFriendColor"
+ reference="Yellow" />
+ <color
+ name="MapAvatarSelfColor"
+ value="0.53125 0 0.498047 1" />
+ <color
+ name="MapFrustumColor"
+ reference="White_10" />
+ <color
+ name="MapFrustumRotatingColor"
+ value="1 1 1 0.2" />
+ <color
+ name="MapTrackColor"
+ reference="Red" />
+ <color
+ name="MapTrackDisabledColor"
+ value="0.5 0 0 1" />
+ <color
+ name="MenuBarBgColor"
+ reference="DkGray" />
+ <color
+ name="MenuBarGodBgColor"
+ reference="FrogGreen" />
+ <color
+ name="MenuDefaultBgColor"
+ reference="DkGray2" />
+ <color
+ name="MenuItemDisabledColor"
+ reference="LtGray_50" />
+ <color
+ name="MenuItemEnabledColor"
+ reference="LtGray" />
+ <color
+ name="MenuItemHighlightBgColor"
+ reference="EmphasisColor_35" />
+ <color
+ name="MenuItemHighlightFgColor"
+ reference="White" />
+ <color
+ name="MenuNonProductionBgColor"
+ reference="Black" />
+ <color
+ name="MenuNonProductionGodBgColor"
+ value="0.263 0.325 0.345 1" />
+ <color
+ name="MenuPopupBgColor"
+ reference="DkGray2" />
+ <color
+ name="MultiSliderDisabledThumbColor"
+ reference="Unused?" />
+ <color
+ name="MultiSliderThumbCenterColor"
+ reference="Unused?" />
+ <color
+ name="MultiSliderThumbCenterSelectedColor"
+ reference="Unused?" />
+ <color
+ name="MultiSliderThumbOutlineColor"
+ reference="Unused?" />
+ <color
+ name="MultiSliderTrackColor"
+ reference="Unused?" />
+ <color
+ name="MultiSliderTriangleColor"
+ reference="Unused?" />
+ <color
+ name="NetMapBackgroundColor"
+ value="0 0 0 0.3" />
+ <color
+ name="NetMapGroupOwnAboveWater"
+ reference="Purple" />
+ <color
+ name="NetMapGroupOwnBelowWater"
+ value="0.78 0 0.78 1" />
+ <color
+ name="NetMapOtherOwnAboveWater"
+ value="0.24 0.24 0.24 1" />
+ <color
+ name="NetMapOtherOwnBelowWater"
+ value="0.12 0.12 0.12 1" />
+ <color
+ name="NetMapYouOwnAboveWater"
+ value="0 1 1 1" />
+ <color
+ name="NetMapYouOwnBelowWater"
+ value="0 0.78 0.78 1" />
+ <color
+ name="NotifyBoxColor"
+ value="LtGray" />
+ <color
+ name="NotifyCautionBoxColor"
+ value="1 0.82 0.46 1" />
+ <color
+ name="NotifyCautionWarnColor"
+ reference="White" />
+ <color
+ name="NotifyTextColor"
+ reference="White" />
+ <color
+ name="ObjectChatColor"
+ reference="EmphasisColor" />
+ <color
+ name="OverdrivenColor"
+ reference="Red" />
+ <color
+ name="PanelDefaultBackgroundColor"
+ reference="DkGray" />
+ <color
+ name="PanelDefaultHighlightLight"
+ reference="White_50" />
+ <color
+ name="PanelFocusBackgroundColor"
+ reference="DkGray2" />
+ <color
+ name="ParcelHoverColor"
+ reference="White" />
+ <color
+ name="PieMenuBgColor"
+ value="0.24 0.24 0.24 0.59" />
+ <color
+ name="PieMenuLineColor"
+ value="0 0 0 0.5" />
+ <color
+ name="PieMenuSelectedColor"
+ value="0.72 0.72 0.74 0.3" />
+ <color
+ name="PropertyColorAuction"
+ value="0.5 0 1 0.4" />
+ <color
+ name="PropertyColorAvail"
+ reference="Transparent" />
+ <color
+ name="PropertyColorForSale"
+ value="1 0.5 0 0.4" />
+ <color
+ name="PropertyColorGroup"
+ value="0 0.72 0.72 0.4" />
+ <color
+ name="PropertyColorOther"
+ value="1 0 0 0.4" />
+ <color
+ name="PropertyColorSelf"
+ value="0 1 0 0.4" />
+ <color
+ name="ScriptBgReadOnlyColor"
+ value="0.39 0.39 0.39 1" />
+ <color
+ name="ScriptErrorColor"
+ value="0.82 0.27 0.27 1" />
+ <color
+ name="ScrollBGStripeColor"
+ reference="Transparent" />
+ <color
+ name="ScrollBgReadOnlyColor"
+ reference="Transparent" />
+ <color
+ name="ScrollBgWriteableColor"
+ reference="White_05" />
+ <color
+ name="ScrollDisabledColor"
+ reference="White_25" />
+ <color
+ name="ScrollHighlightedColor"
+ reference="Unused?" />
+ <color
+ name="ScrollHoveredColor"
+ reference="EmphasisColor_13" />
+ <color
+ name="ScrollSelectedBGColor"
+ reference="EmphasisColor_35" />
+ <color
+ name="ScrollSelectedFGColor"
+ reference="White" />
+ <color
+ name="ScrollUnselectedColor"
+ reference="LtGray" />
+ <color
+ name="ScrollbarThumbColor"
+ reference="White" />
+ <color
+ name="ScrollbarTrackColor"
+ reference="Black" />
+ <color
+ name="SilhouetteChildColor"
+ value="0.13 0.42 0.77 1" />
+ <color
+ name="SilhouetteParentColor"
+ reference="Yellow" />
+ <color
+ name="SliderDisabledThumbColor"
+ reference="White_25" />
+ <color
+ name="SliderThumbCenterColor"
+ reference="White" />
+ <color
+ name="SliderThumbOutlineColor"
+ reference="White" />
+ <color
+ name="SliderTrackColor"
+ reference="Unused?" />
+ <color
+ name="SpeakingColor"
+ reference="FrogGreen" />
+ <color
+ name="SystemChatColor"
+ reference="White" />
+ <color
+ name="TextBgFocusColor"
+ reference="White" />
+ <color
+ name="TextBgReadOnlyColor"
+ reference="White_05" />
+ <color
+ name="TextBgWriteableColor"
+ reference="LtGray" />
+ <color
+ name="TextCursorColor"
+ reference="Black" />
+ <color
+ name="TextDefaultColor"
+ reference="Black" />
+ <color
+ name="TextEmbeddedItemColor"
+ value="0 0 0.5 1" />
+ <color
+ name="TextEmbeddedItemReadOnlyColor"
+ reference="Unused?" />
+ <color
+ name="TextFgColor"
+ value="0.102 0.102 0.102 1" />
+ <color
+ name="TextFgReadOnlyColor"
+ reference="LtGray" />
+ <color
+ name="TextFgTentativeColor"
+ value="0.4 0.4 0.4 1" />
+ <color
+ name="TimeTextColor"
+ reference="LtGray" />
+ <color
+ name="TitleBarFocusColor"
+ reference="White_10" />
+ <color
+ name="ToolTipBgColor"
+ value="0.937 0.89 0.655 1" />
+ <color
+ name="ToolTipBorderColor"
+ value="0.812 0.753 0.451 1" />
+ <color
+ name="ToolTipTextColor"
+ reference="DkGray2" />
+ <color
+ name="InspectorTipTextColor"
+ reference="LtGray" />
+ <color
+ name="UserChatColor"
+ reference="White" />
+ <color
+ name="llOwnerSayChatColor"
+ reference="LtGray" />
+
+ <!-- New Colors -->
+ <color
+ name="OutputMonitorMutedColor"
+ reference="DkGray2" />
+ <color
+ name="SysWellItemUnselected"
+ value="0 0 0 0" />
+ <color
+ name="SysWellItemSelected"
+ value="0.3 0.3 0.3 1.0" />
+ <color
+ name="ChatToastAgentNameColor"
+ reference="EmphasisColor" />
+ <color
+ name="ColorSwatchBorderColor"
+ value="0.45098 0.517647 0.607843 1"/>
+</colors>
diff --git a/indra/newview/skins/default/html/da/loading/loading.html b/indra/newview/skins/default/html/da/loading/loading.html
new file mode 100644
index 0000000000..cdad5702b9
--- /dev/null
+++ b/indra/newview/skins/default/html/da/loading/loading.html
@@ -0,0 +1,10 @@
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
+<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
+<table width="100%" height="100%" border="0">
+ <tr>
+ <td align="center" valign="middle" style="font-size:0.8em;">
+ <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/>&nbsp;&nbsp;&nbsp;Indlæser...
+ </td>
+ </tr>
+</table>
+</body>
diff --git a/indra/newview/skins/default/html/de/loading/loading.html b/indra/newview/skins/default/html/de/loading/loading.html
new file mode 100644
index 0000000000..3eddbc24f5
--- /dev/null
+++ b/indra/newview/skins/default/html/de/loading/loading.html
@@ -0,0 +1,10 @@
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
+<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
+<table width="100%" height="100%" border="0">
+ <tr>
+ <td align="center" valign="middle" style="font-size:0.8em;">
+ <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/>&nbsp;&nbsp;&nbsp;Wird geladen...
+ </td>
+ </tr>
+</table>
+</body>
diff --git a/indra/newview/skins/default/html/en-us/help-offline/index.html b/indra/newview/skins/default/html/en-us/help-offline/index.html
new file mode 100644
index 0000000000..bf3677603e
--- /dev/null
+++ b/indra/newview/skins/default/html/en-us/help-offline/index.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Offline Help</title>
+<style>
+body {background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;width:100%;padding:0px;margin:0px;}
+a {color:#93a9d5;}
+a:active {color:#50607C;text-decoration:underline;}
+a:hover {color:#ff7900;text-decoration:underline;}
+#infobox{position:absolute;top:40%;left:50%;z-index:1;padding:0;width:592px;margin-left:-296px;margin-top:-150px;text-align:center;font-size:1.2em; color:#ccc;}
+#infobox #submitbtn {padding:15px 3px 5px 15px;height:28px;width:127px;margin-left:244px;}
+#infobox #submitbtn input {text-transform:capitalize;color:#fff;font-size:1.0em;height:28px;width:127px;border:none;font-weight:normal;background:url(../../btn_purplepill_bg.png) bottom left no-repeat;vertical-align:text-bottom;font-weight:bold;}
+#infobox #submitbtn input:hover.input_over, #login_box #submitbtn input:hover.input_off {color:#fff;border:none;background:url(../../btn_purplepill_bg.png) bottom right no-repeat;}
+#infobox #submitbtn input:active.input_over {color:#fff;border:none;background:url(../../btn_purplepill_bg.png) top left no-repeat;}
+#infobox #submitbtn input.pressed {color:#888;border:none;background:url(../../btn_purplepill_bg.png) top right no-repeat;}
+</style>
+</head>
+<body>
+<div id="infobox">
+ <p>
+ Second Life Offline Help.
+ </p>
+ <p>
+ You are not online and are configured not to fetch help remotely. This is all the help that is available
+ until more stuff is done. Yeah.
+ </p>
+ </div>
+</div>
+</body>
diff --git a/indra/newview/skins/default/html/es/loading/loading.html b/indra/newview/skins/default/html/es/loading/loading.html
new file mode 100644
index 0000000000..f03284ba8c
--- /dev/null
+++ b/indra/newview/skins/default/html/es/loading/loading.html
@@ -0,0 +1,10 @@
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
+<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
+<table width="100%" height="100%" border="0">
+ <tr>
+ <td align="center" valign="middle" style="font-size:0.8em;">
+ <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/>&nbsp;&nbsp;&nbsp;Cargando...
+ </td>
+ </tr>
+</table>
+</body>
diff --git a/indra/newview/skins/default/html/fr/loading/loading.html b/indra/newview/skins/default/html/fr/loading/loading.html
new file mode 100644
index 0000000000..23c0ef03bc
--- /dev/null
+++ b/indra/newview/skins/default/html/fr/loading/loading.html
@@ -0,0 +1,10 @@
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
+<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
+<table width="100%" height="100%" border="0">
+ <tr>
+ <td align="center" valign="middle" style="font-size:0.8em;">
+ <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/>&nbsp;&nbsp;&nbsp;Chargement...
+ </td>
+ </tr>
+</table>
+</body>
diff --git a/indra/newview/skins/default/html/hu/loading/loading.html b/indra/newview/skins/default/html/hu/loading/loading.html
new file mode 100644
index 0000000000..ade91f76c2
--- /dev/null
+++ b/indra/newview/skins/default/html/hu/loading/loading.html
@@ -0,0 +1,10 @@
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
+<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
+<table width="100%" height="100%" border="0">
+ <tr>
+ <td align="center" valign="middle" style="font-size:0.8em;">
+ <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/>&nbsp;&nbsp;&nbsp;Betöltés folyamatban...
+ </td>
+ </tr>
+</table>
+</body>
diff --git a/indra/newview/skins/default/html/it/loading/loading.html b/indra/newview/skins/default/html/it/loading/loading.html
new file mode 100644
index 0000000000..0f9af31f6e
--- /dev/null
+++ b/indra/newview/skins/default/html/it/loading/loading.html
@@ -0,0 +1,10 @@
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
+<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
+<table width="100%" height="100%" border="0">
+ <tr>
+ <td align="center" valign="middle" style="font-size:0.8em;">
+ <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/>&nbsp;&nbsp;&nbsp;Attendi...
+ </td>
+ </tr>
+</table>
+</body>
diff --git a/indra/newview/skins/default/html/ja/loading-error/index.html b/indra/newview/skins/default/html/ja/loading-error/index.html
index e0bcc94b6b..d969c03098 100644
--- a/indra/newview/skins/default/html/ja/loading-error/index.html
+++ b/indra/newview/skins/default/html/ja/loading-error/index.html
@@ -18,7 +18,7 @@ a:hover {color:#ff7900;text-decoration:underline;}
<body> <div id="infobox"> <img src="../../unabletoconnect.png"><br/>
<p> Second Lifeã«ã‚ˆã‚‹ãƒ­ã‚°ã‚¤ãƒ³ã‚µãƒ¼ãƒãƒ¼ã¸ã®æŽ¥ç¶šãŒç¢ºç«‹ã§ãã¾ã›ã‚“。
</p>
- <p> インターãƒãƒƒãƒˆæŽ¥ç¶šã‚’確èªã—ã¦ãã ã•ã„。 ãŠä½¿ã„ã®ã‚³ãƒ³ãƒ”ュータやãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãŒãƒ•ã‚¡ã‚¤ãƒ¤ã‚¦ã‚©ãƒ¼ãƒ«ã¾ãŸã¯ãƒ—ロキシã«ã‚ˆã‚Šä¿è­·ã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€Second Lifeã«ã‚ˆã‚‹ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ãŒè¨±å¯ã•ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。
+ <p> インターãƒãƒƒãƒˆæŽ¥ç¶šã‚’確èªã—ã¦ãã ã•ã„。 ãŠä½¿ã„ã®ã‚³ãƒ³ãƒ”ュータやãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãŒãƒ•ã‚¡ã‚¤ãƒ¤ã‚¦ã‚©ãƒ¼ãƒ«ã¾ãŸã¯ãƒ—ロキシã«ã‚ˆã‚Šä¿è­·ã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€Second Lifeã«ã‚ˆã‚‹ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ãŒè¨±å¯ã•ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。
</p> <div id="submitbtn">
<input class="input_over" type="submit" value="ã‚‚ã†ä¸€åº¦è©¦ã™" onclick="document.location='secondlife:///app/login_refresh'; this.className='pressed';" onmouseover="this.className='input_over';" onmouseout="this.className='input_off';" /> </div> </div>
</div>
diff --git a/indra/newview/skins/default/html/ja/loading/loading.html b/indra/newview/skins/default/html/ja/loading/loading.html
new file mode 100644
index 0000000000..069dc5d12f
--- /dev/null
+++ b/indra/newview/skins/default/html/ja/loading/loading.html
@@ -0,0 +1,10 @@
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
+<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
+<table width="100%" height="100%" border="0">
+ <tr>
+ <td align="center" valign="middle" style="font-size:0.8em;">
+ <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/>&nbsp;&nbsp;&nbsp;ロード中...
+ </td>
+ </tr>
+</table>
+</body>
diff --git a/indra/newview/skins/default/html/nl/loading/loading.html b/indra/newview/skins/default/html/nl/loading/loading.html
new file mode 100644
index 0000000000..39a8691f3f
--- /dev/null
+++ b/indra/newview/skins/default/html/nl/loading/loading.html
@@ -0,0 +1,10 @@
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
+<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
+<table width="100%" height="100%" border="0">
+ <tr>
+ <td align="center" valign="middle" style="font-size:0.8em;">
+ <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/>&nbsp;&nbsp;&nbsp;Laden...
+ </td>
+ </tr>
+</table>
+</body>
diff --git a/indra/newview/skins/default/html/pl/loading/loading.html b/indra/newview/skins/default/html/pl/loading/loading.html
new file mode 100644
index 0000000000..515890c2d5
--- /dev/null
+++ b/indra/newview/skins/default/html/pl/loading/loading.html
@@ -0,0 +1,10 @@
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
+<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
+<table width="100%" height="100%" border="0">
+ <tr>
+ <td align="center" valign="middle" style="font-size:0.8em;">
+ <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/>&nbsp;&nbsp;&nbsp;Åadowanie...
+ </td>
+ </tr>
+</table>
+</body>
diff --git a/indra/newview/skins/default/html/pt/loading/loading.html b/indra/newview/skins/default/html/pt/loading/loading.html
new file mode 100644
index 0000000000..635ea62406
--- /dev/null
+++ b/indra/newview/skins/default/html/pt/loading/loading.html
@@ -0,0 +1,10 @@
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
+<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
+<table width="100%" height="100%" border="0">
+ <tr>
+ <td align="center" valign="middle" style="font-size:0.8em;">
+ <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/>&nbsp;&nbsp;&nbsp;Carregando...
+ </td>
+ </tr>
+</table>
+</body>
diff --git a/indra/newview/skins/default/html/ru/loading/loading.html b/indra/newview/skins/default/html/ru/loading/loading.html
new file mode 100644
index 0000000000..dcc0d73c1a
--- /dev/null
+++ b/indra/newview/skins/default/html/ru/loading/loading.html
@@ -0,0 +1,10 @@
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
+<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
+<table width="100%" height="100%" border="0">
+ <tr>
+ <td align="center" valign="middle" style="font-size:0.8em;">
+ <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/>&nbsp;&nbsp;&nbsp;Загрузка...
+ </td>
+ </tr>
+</table>
+</body>
diff --git a/indra/newview/skins/default/html/tr/loading/loading.html b/indra/newview/skins/default/html/tr/loading/loading.html
new file mode 100644
index 0000000000..e7812e7c8e
--- /dev/null
+++ b/indra/newview/skins/default/html/tr/loading/loading.html
@@ -0,0 +1,10 @@
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
+<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
+<table width="100%" height="100%" border="0">
+ <tr>
+ <td align="center" valign="middle" style="font-size:0.8em;">
+ <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/>&nbsp;&nbsp;&nbsp;Yükleniyor...
+ </td>
+ </tr>
+</table>
+</body>
diff --git a/indra/newview/skins/default/html/uk/loading/loading.html b/indra/newview/skins/default/html/uk/loading/loading.html
new file mode 100644
index 0000000000..0f67994635
--- /dev/null
+++ b/indra/newview/skins/default/html/uk/loading/loading.html
@@ -0,0 +1,10 @@
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
+<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
+<table width="100%" height="100%" border="0">
+ <tr>
+ <td align="center" valign="middle" style="font-size:0.8em;">
+ <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/>&nbsp;&nbsp;&nbsp;Завантаж...
+ </td>
+ </tr>
+</table>
+</body>
diff --git a/indra/newview/skins/default/html/zh/loading-error/index.html b/indra/newview/skins/default/html/zh/loading-error/index.html
index 01cdec94fe..97201318ff 100644
--- a/indra/newview/skins/default/html/zh/loading-error/index.html
+++ b/indra/newview/skins/default/html/zh/loading-error/index.html
@@ -16,9 +16,9 @@ a:hover {color:#ff7900;text-decoration:underline;}
</style>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
<body> <div id="infobox"> <img src="../../unabletoconnect.png"><br/>
- <p> 第二人生无法与登录æœåŠ¡å™¨è¿žæŽ¥ã€‚
+ <p> Second Life无法与登录æœåŠ¡å™¨è¿žæŽ¥ã€‚
</p>
- <p> 请检查您的因特网连接 如果您的计算机或网络由防ç«å¢™æˆ–代ç†å™¨ä¿æŠ¤ï¼Œè¯·ç¡®è®¤ç¬¬äºŒäººç”Ÿèƒ½åœ¨è¯¥ç½‘络里访问因特网。
+ <p> 请检查您的因特网连接 如果您的计算机或网络由防ç«å¢™æˆ–代ç†å™¨ä¿æŠ¤ï¼Œè¯·ç¡®è®¤Second Life能在该网络里访问因特网。
</p> <div id="submitbtn">
<input class="input_over" type="submit" value="请å†è¯•ä¸€æ¬¡" onclick="document.location='secondlife:///app/login_refresh'; this.className='pressed';" onmouseover="this.className='input_over';" onmouseout="this.className='input_off';" /> </div> </div>
</div>
diff --git a/indra/newview/skins/default/html/zh/loading/loading.html b/indra/newview/skins/default/html/zh/loading/loading.html
new file mode 100644
index 0000000000..462ea291d9
--- /dev/null
+++ b/indra/newview/skins/default/html/zh/loading/loading.html
@@ -0,0 +1,10 @@
+<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
+<body style="background-color:#000000;font-family:verdana,helvetica,sans-serif;font-size:62.5%;color:#e9f1f8;">
+<table width="100%" height="100%" border="0">
+ <tr>
+ <td align="center" valign="middle" style="font-size:0.8em;">
+ <img src="../../en-us/loading/sl_logo_rotate_black.gif" align="absmiddle"><br/>&nbsp;&nbsp;&nbsp;请等待...
+ </td>
+ </tr>
+</table>
+</body>
diff --git a/indra/newview/skins/default/textures/Blank.png b/indra/newview/skins/default/textures/Blank.png
new file mode 100644
index 0000000000..f38e9f9100
--- /dev/null
+++ b/indra/newview/skins/default/textures/Blank.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Avatar_Off.png b/indra/newview/skins/default/textures/bottomtray/Cam_Avatar_Off.png
new file mode 100644
index 0000000000..6b725e153a
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Avatar_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_FreeCam_Off.png b/indra/newview/skins/default/textures/bottomtray/Cam_FreeCam_Off.png
new file mode 100644
index 0000000000..9f22080d13
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_FreeCam_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Orbit_Off.png b/indra/newview/skins/default/textures/bottomtray/Cam_Orbit_Off.png
new file mode 100644
index 0000000000..5b2a8eb339
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Orbit_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Pan_Off.png b/indra/newview/skins/default/textures/bottomtray/Cam_Pan_Off.png
new file mode 100644
index 0000000000..9acf7053d5
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Pan_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Pan_Over.png b/indra/newview/skins/default/textures/bottomtray/Cam_Pan_Over.png
new file mode 100644
index 0000000000..b5781718ec
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Pan_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Back_Off.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Back_Off.png
new file mode 100644
index 0000000000..3cfe2e850e
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Back_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Back_On.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Back_On.png
new file mode 100644
index 0000000000..bb5d85e410
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Back_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Eye_Off.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Eye_Off.png
new file mode 100644
index 0000000000..2b50986780
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Eye_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Front_Off.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Front_Off.png
new file mode 100644
index 0000000000..9876aa456c
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Front_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Front_On.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Front_On.png
new file mode 100644
index 0000000000..f481fed88c
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Front_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Side_Off.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Side_Off.png
new file mode 100644
index 0000000000..d58b4ff990
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Side_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Side_On.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Side_On.png
new file mode 100644
index 0000000000..6e73898992
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Side_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_In.png b/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_In.png
new file mode 100644
index 0000000000..c8560c0869
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_In.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_Out.png b/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_Out.png
new file mode 100644
index 0000000000..b09f7c64d3
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_Out.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_In.png b/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_In.png
new file mode 100644
index 0000000000..ae2c57c207
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_In.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_Out.png b/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_Out.png
new file mode 100644
index 0000000000..c5cd8cca92
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_Out.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/CameraView_Press.png b/indra/newview/skins/default/textures/bottomtray/CameraView_Press.png
new file mode 100644
index 0000000000..5a9346fd39
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/CameraView_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/DownArrow.png b/indra/newview/skins/default/textures/bottomtray/DownArrow.png
new file mode 100644
index 0000000000..82f58b22b9
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/DownArrow.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Move_Fly_Off.png b/indra/newview/skins/default/textures/bottomtray/Move_Fly_Off.png
new file mode 100644
index 0000000000..28ff6ba976
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Move_Fly_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Move_Run_Off.png b/indra/newview/skins/default/textures/bottomtray/Move_Run_Off.png
new file mode 100644
index 0000000000..e2eb38e12d
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Move_Run_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Move_Walk_Off.png b/indra/newview/skins/default/textures/bottomtray/Move_Walk_Off.png
new file mode 100644
index 0000000000..f314d4e001
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Move_Walk_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Backward_Off.png b/indra/newview/skins/default/textures/bottomtray/Movement_Backward_Off.png
new file mode 100644
index 0000000000..4dddc2b391
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_Backward_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Backward_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_Backward_On.png
new file mode 100644
index 0000000000..9f31d461b5
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_Backward_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Down_Off.png b/indra/newview/skins/default/textures/bottomtray/Movement_Down_Off.png
new file mode 100644
index 0000000000..1b0192e685
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_Down_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Down_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_Down_On.png
new file mode 100644
index 0000000000..9f42b7d5b2
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_Down_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Forward_Off.png b/indra/newview/skins/default/textures/bottomtray/Movement_Forward_Off.png
new file mode 100644
index 0000000000..80d227b6a7
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_Forward_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Forward_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_Forward_On.png
new file mode 100644
index 0000000000..d0a825a682
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_Forward_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_TurnLeft_Off.png b/indra/newview/skins/default/textures/bottomtray/Movement_TurnLeft_Off.png
new file mode 100644
index 0000000000..282e8d62de
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_TurnLeft_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_TurnLeft_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_TurnLeft_On.png
new file mode 100644
index 0000000000..b211371e64
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_TurnLeft_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_TurnRight_Off.png b/indra/newview/skins/default/textures/bottomtray/Movement_TurnRight_Off.png
new file mode 100644
index 0000000000..5039e57c32
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_TurnRight_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_TurnRight_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_TurnRight_On.png
new file mode 100644
index 0000000000..e937c3f012
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_TurnRight_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Up_Off.png b/indra/newview/skins/default/textures/bottomtray/Movement_Up_Off.png
new file mode 100644
index 0000000000..9b9837cec1
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_Up_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Up_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_Up_On.png
new file mode 100644
index 0000000000..c71d4a7854
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Movement_Up_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png b/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png
new file mode 100644
index 0000000000..0ac5b72b8f
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Snapshot_Off.png b/indra/newview/skins/default/textures/bottomtray/Snapshot_Off.png
new file mode 100644
index 0000000000..d7ec04237b
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Snapshot_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Unread_Chiclet.png b/indra/newview/skins/default/textures/bottomtray/Unread_Chiclet.png
new file mode 100644
index 0000000000..6343ddf035
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Unread_Chiclet.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/Unread_IM.png b/indra/newview/skins/default/textures/bottomtray/Unread_IM.png
new file mode 100644
index 0000000000..5c0c85b864
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Unread_IM.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1.png
new file mode 100644
index 0000000000..cd18ae310d
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2.png
new file mode 100644
index 0000000000..b0ed6ee8eb
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl3.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl3.png
new file mode 100644
index 0000000000..14ec77b99a
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl3.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Off.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Off.png
new file mode 100644
index 0000000000..48be51e9af
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_On.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_On.png
new file mode 100644
index 0000000000..be4881b64c
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/VoicePTT_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/WellButton_Lit.png b/indra/newview/skins/default/textures/bottomtray/WellButton_Lit.png
new file mode 100644
index 0000000000..6cb33efb93
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/WellButton_Lit.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/WellButton_Lit_Selected.png b/indra/newview/skins/default/textures/bottomtray/WellButton_Lit_Selected.png
new file mode 100644
index 0000000000..6cb33efb93
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/WellButton_Lit_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Cone.png b/indra/newview/skins/default/textures/build/Object_Cone.png
new file mode 100644
index 0000000000..5167f1a820
--- /dev/null
+++ b/indra/newview/skins/default/textures/build/Object_Cone.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Cube.png b/indra/newview/skins/default/textures/build/Object_Cube.png
new file mode 100644
index 0000000000..e82af1ca82
--- /dev/null
+++ b/indra/newview/skins/default/textures/build/Object_Cube.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Cylinder.png b/indra/newview/skins/default/textures/build/Object_Cylinder.png
new file mode 100644
index 0000000000..fe1041d4c7
--- /dev/null
+++ b/indra/newview/skins/default/textures/build/Object_Cylinder.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Grass.png b/indra/newview/skins/default/textures/build/Object_Grass.png
new file mode 100644
index 0000000000..a88efd5f3e
--- /dev/null
+++ b/indra/newview/skins/default/textures/build/Object_Grass.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Hemi_Cone.png b/indra/newview/skins/default/textures/build/Object_Hemi_Cone.png
new file mode 100644
index 0000000000..595f64d480
--- /dev/null
+++ b/indra/newview/skins/default/textures/build/Object_Hemi_Cone.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Hemi_Cylinder.png b/indra/newview/skins/default/textures/build/Object_Hemi_Cylinder.png
new file mode 100644
index 0000000000..dd41d56fb3
--- /dev/null
+++ b/indra/newview/skins/default/textures/build/Object_Hemi_Cylinder.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Hemi_Sphere.png b/indra/newview/skins/default/textures/build/Object_Hemi_Sphere.png
new file mode 100644
index 0000000000..1489630624
--- /dev/null
+++ b/indra/newview/skins/default/textures/build/Object_Hemi_Sphere.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Prism.png b/indra/newview/skins/default/textures/build/Object_Prism.png
new file mode 100644
index 0000000000..51c6c161a0
--- /dev/null
+++ b/indra/newview/skins/default/textures/build/Object_Prism.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Pyramid.png b/indra/newview/skins/default/textures/build/Object_Pyramid.png
new file mode 100644
index 0000000000..a147b59553
--- /dev/null
+++ b/indra/newview/skins/default/textures/build/Object_Pyramid.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Ring.png b/indra/newview/skins/default/textures/build/Object_Ring.png
new file mode 100644
index 0000000000..a9790fd60c
--- /dev/null
+++ b/indra/newview/skins/default/textures/build/Object_Ring.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Sphere.png b/indra/newview/skins/default/textures/build/Object_Sphere.png
new file mode 100644
index 0000000000..8e2dd92a82
--- /dev/null
+++ b/indra/newview/skins/default/textures/build/Object_Sphere.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Tetrahedron.png b/indra/newview/skins/default/textures/build/Object_Tetrahedron.png
new file mode 100644
index 0000000000..23e22b1796
--- /dev/null
+++ b/indra/newview/skins/default/textures/build/Object_Tetrahedron.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Torus.png b/indra/newview/skins/default/textures/build/Object_Torus.png
new file mode 100644
index 0000000000..15c62423a9
--- /dev/null
+++ b/indra/newview/skins/default/textures/build/Object_Torus.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Tree.png b/indra/newview/skins/default/textures/build/Object_Tree.png
new file mode 100644
index 0000000000..82c422419b
--- /dev/null
+++ b/indra/newview/skins/default/textures/build/Object_Tree.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Object_Tube.png b/indra/newview/skins/default/textures/build/Object_Tube.png
new file mode 100644
index 0000000000..e47fce7511
--- /dev/null
+++ b/indra/newview/skins/default/textures/build/Object_Tube.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Tool_Create.png b/indra/newview/skins/default/textures/build/Tool_Create.png
new file mode 100644
index 0000000000..1f1097def5
--- /dev/null
+++ b/indra/newview/skins/default/textures/build/Tool_Create.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Tool_Dozer.png b/indra/newview/skins/default/textures/build/Tool_Dozer.png
new file mode 100644
index 0000000000..61744666f4
--- /dev/null
+++ b/indra/newview/skins/default/textures/build/Tool_Dozer.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Tool_Face.png b/indra/newview/skins/default/textures/build/Tool_Face.png
new file mode 100644
index 0000000000..5ab42a4ad6
--- /dev/null
+++ b/indra/newview/skins/default/textures/build/Tool_Face.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Tool_Grab.png b/indra/newview/skins/default/textures/build/Tool_Grab.png
new file mode 100644
index 0000000000..5c58288d5e
--- /dev/null
+++ b/indra/newview/skins/default/textures/build/Tool_Grab.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/build/Tool_Zoom.png b/indra/newview/skins/default/textures/build/Tool_Zoom.png
new file mode 100644
index 0000000000..ad493b0d66
--- /dev/null
+++ b/indra/newview/skins/default/textures/build/Tool_Zoom.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Accordion_ArrowClosed_Off.png b/indra/newview/skins/default/textures/containers/Accordion_ArrowClosed_Off.png
new file mode 100644
index 0000000000..19c842b816
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/Accordion_ArrowClosed_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Accordion_ArrowClosed_Over.png b/indra/newview/skins/default/textures/containers/Accordion_ArrowClosed_Over.png
new file mode 100644
index 0000000000..e47f913db1
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/Accordion_ArrowClosed_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Accordion_ArrowClosed_Press.png b/indra/newview/skins/default/textures/containers/Accordion_ArrowClosed_Press.png
new file mode 100644
index 0000000000..b9879dcc8a
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/Accordion_ArrowClosed_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Accordion_ArrowOpened_Off.png b/indra/newview/skins/default/textures/containers/Accordion_ArrowOpened_Off.png
new file mode 100644
index 0000000000..d506cda5c9
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/Accordion_ArrowOpened_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Accordion_ArrowOpened_Over.png b/indra/newview/skins/default/textures/containers/Accordion_ArrowOpened_Over.png
new file mode 100644
index 0000000000..e2c67de9c0
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/Accordion_ArrowOpened_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Accordion_ArrowOpened_Press.png b/indra/newview/skins/default/textures/containers/Accordion_ArrowOpened_Press.png
new file mode 100644
index 0000000000..08f7493a02
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/Accordion_ArrowOpened_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Accordion_Off.png b/indra/newview/skins/default/textures/containers/Accordion_Off.png
new file mode 100644
index 0000000000..414f4509c6
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/Accordion_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Accordion_Over.png b/indra/newview/skins/default/textures/containers/Accordion_Over.png
new file mode 100644
index 0000000000..5416d73310
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/Accordion_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Accordion_Press.png b/indra/newview/skins/default/textures/containers/Accordion_Press.png
new file mode 100644
index 0000000000..1578e0dfc5
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/Accordion_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Accordion_Selected.png b/indra/newview/skins/default/textures/containers/Accordion_Selected.png
new file mode 100644
index 0000000000..0616dea6a3
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/Accordion_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Container.png b/indra/newview/skins/default/textures/containers/Container.png
new file mode 100644
index 0000000000..511eb94386
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/Container.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/TabTop_Left_Off.png b/indra/newview/skins/default/textures/containers/TabTop_Left_Off.png
new file mode 100644
index 0000000000..1951413f8d
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/TabTop_Left_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/TabTop_Left_Over.png b/indra/newview/skins/default/textures/containers/TabTop_Left_Over.png
new file mode 100644
index 0000000000..295cd89a57
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/TabTop_Left_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/TabTop_Left_Selected.png b/indra/newview/skins/default/textures/containers/TabTop_Left_Selected.png
new file mode 100644
index 0000000000..8364716e02
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/TabTop_Left_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/TabTop_Middle_Off.png b/indra/newview/skins/default/textures/containers/TabTop_Middle_Off.png
new file mode 100644
index 0000000000..21f1c2d8a8
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/TabTop_Middle_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/TabTop_Middle_Over.png b/indra/newview/skins/default/textures/containers/TabTop_Middle_Over.png
new file mode 100644
index 0000000000..0758cbcf0d
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/TabTop_Middle_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/TabTop_Middle_Selected.png b/indra/newview/skins/default/textures/containers/TabTop_Middle_Selected.png
new file mode 100644
index 0000000000..3946917c7c
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/TabTop_Middle_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/TabTop_Right_Off.png b/indra/newview/skins/default/textures/containers/TabTop_Right_Off.png
new file mode 100644
index 0000000000..eeef28e5a5
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/TabTop_Right_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/TabTop_Right_Over.png b/indra/newview/skins/default/textures/containers/TabTop_Right_Over.png
new file mode 100644
index 0000000000..c2cbc2b1e5
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/TabTop_Right_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/TabTop_Right_Selected.png b/indra/newview/skins/default/textures/containers/TabTop_Right_Selected.png
new file mode 100644
index 0000000000..b0f1f16398
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/TabTop_Right_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Left_Off.png b/indra/newview/skins/default/textures/containers/Toolbar_Left_Off.png
new file mode 100644
index 0000000000..41b5d24d87
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Left_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Left_Over.png b/indra/newview/skins/default/textures/containers/Toolbar_Left_Over.png
new file mode 100644
index 0000000000..083acc0156
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Left_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Left_Selected.png b/indra/newview/skins/default/textures/containers/Toolbar_Left_Selected.png
new file mode 100644
index 0000000000..ee4649a8f9
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Left_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Middle_Off.png b/indra/newview/skins/default/textures/containers/Toolbar_Middle_Off.png
new file mode 100644
index 0000000000..55c02160e3
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Middle_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Middle_Over.png b/indra/newview/skins/default/textures/containers/Toolbar_Middle_Over.png
new file mode 100644
index 0000000000..2f6ea90196
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Middle_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Middle_Selected.png b/indra/newview/skins/default/textures/containers/Toolbar_Middle_Selected.png
new file mode 100644
index 0000000000..642113b135
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Middle_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Right_Off.png b/indra/newview/skins/default/textures/containers/Toolbar_Right_Off.png
new file mode 100644
index 0000000000..01fd765c3d
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Right_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Right_Over.png b/indra/newview/skins/default/textures/containers/Toolbar_Right_Over.png
new file mode 100644
index 0000000000..74e00635f1
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Right_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Right_Selected.png b/indra/newview/skins/default/textures/containers/Toolbar_Right_Selected.png
new file mode 100644
index 0000000000..8a0d98a780
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/Toolbar_Right_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/default_profile_picture.j2c b/indra/newview/skins/default/textures/default_profile_picture.j2c
index c53a22e816..f21742cf09 100644
--- a/indra/newview/skins/default/textures/default_profile_picture.j2c
+++ b/indra/newview/skins/default/textures/default_profile_picture.j2c
Binary files differ
diff --git a/indra/newview/skins/default/textures/icon_event_adult.tga b/indra/newview/skins/default/textures/icon_event_adult.tga
index c344fb1e78..f548126e5a 100644
--- a/indra/newview/skins/default/textures/icon_event_adult.tga
+++ b/indra/newview/skins/default/textures/icon_event_adult.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/icon_top_pick.tga b/indra/newview/skins/default/textures/icon_top_pick.tga
index 7fe119a818..0b34882d2f 100644
--- a/indra/newview/skins/default/textures/icon_top_pick.tga
+++ b/indra/newview/skins/default/textures/icon_top_pick.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/AddItem_Disabled.png b/indra/newview/skins/default/textures/icons/AddItem_Disabled.png
new file mode 100644
index 0000000000..cf88c89ae5
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/AddItem_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/AddItem_Off.png b/indra/newview/skins/default/textures/icons/AddItem_Off.png
new file mode 100644
index 0000000000..52d4f9bc80
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/AddItem_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/AddItem_Over.png b/indra/newview/skins/default/textures/icons/AddItem_Over.png
new file mode 100644
index 0000000000..cad6e8d52f
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/AddItem_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/AddItem_Press.png b/indra/newview/skins/default/textures/icons/AddItem_Press.png
new file mode 100644
index 0000000000..acc898e5f4
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/AddItem_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/AudioMute_Off.png b/indra/newview/skins/default/textures/icons/AudioMute_Off.png
new file mode 100644
index 0000000000..938aaef491
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/AudioMute_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/AudioMute_Over.png b/indra/newview/skins/default/textures/icons/AudioMute_Over.png
new file mode 100644
index 0000000000..7bd1b12aae
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/AudioMute_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Audio_Off.png b/indra/newview/skins/default/textures/icons/Audio_Off.png
new file mode 100644
index 0000000000..ef746aab92
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Audio_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Audio_Press.png b/indra/newview/skins/default/textures/icons/Audio_Press.png
new file mode 100644
index 0000000000..25a669224a
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Audio_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/BackArrow_Off.png b/indra/newview/skins/default/textures/icons/BackArrow_Off.png
new file mode 100644
index 0000000000..ff32192856
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/BackArrow_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/BackArrow_Over.png b/indra/newview/skins/default/textures/icons/BackArrow_Over.png
new file mode 100644
index 0000000000..b36e03a8cf
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/BackArrow_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/DragHandle.png b/indra/newview/skins/default/textures/icons/DragHandle.png
new file mode 100644
index 0000000000..c3cbc07a33
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/DragHandle.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/ExternalBrowser_Off.png b/indra/newview/skins/default/textures/icons/ExternalBrowser_Off.png
new file mode 100644
index 0000000000..69646ce473
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/ExternalBrowser_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/ForSale_Badge.png b/indra/newview/skins/default/textures/icons/ForSale_Badge.png
new file mode 100644
index 0000000000..5bee570cee
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/ForSale_Badge.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/ForwardArrow_Off.png b/indra/newview/skins/default/textures/icons/ForwardArrow_Off.png
new file mode 100644
index 0000000000..e9b72b0401
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/ForwardArrow_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/ForwardArrow_Press.png b/indra/newview/skins/default/textures/icons/ForwardArrow_Press.png
new file mode 100644
index 0000000000..c7b2c769ae
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/ForwardArrow_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Generic_Group.png b/indra/newview/skins/default/textures/icons/Generic_Group.png
new file mode 100644
index 0000000000..fdd65b49e1
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Generic_Group.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Generic_Group_Large.png b/indra/newview/skins/default/textures/icons/Generic_Group_Large.png
new file mode 100644
index 0000000000..4d4f1e1bee
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Generic_Group_Large.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Generic_Object.png b/indra/newview/skins/default/textures/icons/Generic_Object.png
new file mode 100644
index 0000000000..e3a80b2aef
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Generic_Object.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Generic_Object_Small.png b/indra/newview/skins/default/textures/icons/Generic_Object_Small.png
new file mode 100644
index 0000000000..223874e631
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Generic_Object_Small.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Generic_Person.png b/indra/newview/skins/default/textures/icons/Generic_Person.png
new file mode 100644
index 0000000000..45b491ab59
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Generic_Person.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Generic_Person_Large.png b/indra/newview/skins/default/textures/icons/Generic_Person_Large.png
new file mode 100644
index 0000000000..65b0ce8b67
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Generic_Person_Large.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Icon_For_Sale.png b/indra/newview/skins/default/textures/icons/Icon_For_Sale.png
new file mode 100644
index 0000000000..3dec6b989c
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Icon_For_Sale.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Info.png b/indra/newview/skins/default/textures/icons/Info.png
new file mode 100644
index 0000000000..e52560281b
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Info.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Info_Over.png b/indra/newview/skins/default/textures/icons/Info_Over.png
new file mode 100644
index 0000000000..be1cd0706f
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Info_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Info_Small.png b/indra/newview/skins/default/textures/icons/Info_Small.png
new file mode 100644
index 0000000000..81078c32dc
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Info_Small.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Alpha.png b/indra/newview/skins/default/textures/icons/Inv_Alpha.png
new file mode 100644
index 0000000000..b65dc1929d
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Alpha.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Animation.png b/indra/newview/skins/default/textures/icons/Inv_Animation.png
new file mode 100644
index 0000000000..ab42c61a92
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Animation.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_BodyShape.png b/indra/newview/skins/default/textures/icons/Inv_BodyShape.png
new file mode 100644
index 0000000000..97e874d70d
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_BodyShape.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_CallingCard.png b/indra/newview/skins/default/textures/icons/Inv_CallingCard.png
new file mode 100644
index 0000000000..1de96475f7
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_CallingCard.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Clothing.png b/indra/newview/skins/default/textures/icons/Inv_Clothing.png
new file mode 100644
index 0000000000..e8d246c6fa
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Clothing.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Eye.png b/indra/newview/skins/default/textures/icons/Inv_Eye.png
new file mode 100644
index 0000000000..e619f56c2b
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Eye.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_FolderClosed.png b/indra/newview/skins/default/textures/icons/Inv_FolderClosed.png
new file mode 100644
index 0000000000..342a973d00
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_FolderClosed.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_FolderOpen.png b/indra/newview/skins/default/textures/icons/Inv_FolderOpen.png
new file mode 100644
index 0000000000..0507c2cbaf
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_FolderOpen.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Gesture.png b/indra/newview/skins/default/textures/icons/Inv_Gesture.png
new file mode 100644
index 0000000000..52695ec19b
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Gesture.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Gloves.png b/indra/newview/skins/default/textures/icons/Inv_Gloves.png
new file mode 100644
index 0000000000..d6a2113aaf
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Gloves.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Hair.png b/indra/newview/skins/default/textures/icons/Inv_Hair.png
new file mode 100644
index 0000000000..ae941b0dd5
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Hair.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Jacket.png b/indra/newview/skins/default/textures/icons/Inv_Jacket.png
new file mode 100644
index 0000000000..3859666f7c
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Jacket.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Landmark.png b/indra/newview/skins/default/textures/icons/Inv_Landmark.png
new file mode 100644
index 0000000000..76df984596
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Landmark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_LinkFolder.png b/indra/newview/skins/default/textures/icons/Inv_LinkFolder.png
new file mode 100644
index 0000000000..73a708782c
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_LinkFolder.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_LinkItem.png b/indra/newview/skins/default/textures/icons/Inv_LinkItem.png
new file mode 100644
index 0000000000..73a708782c
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_LinkItem.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_LookFolderClosed.png b/indra/newview/skins/default/textures/icons/Inv_LookFolderClosed.png
new file mode 100644
index 0000000000..f2ae828efc
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_LookFolderClosed.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_LookFolderOpen.png b/indra/newview/skins/default/textures/icons/Inv_LookFolderOpen.png
new file mode 100644
index 0000000000..d454d4cd48
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_LookFolderOpen.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Notecard.png b/indra/newview/skins/default/textures/icons/Inv_Notecard.png
new file mode 100644
index 0000000000..4645ab8e91
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Notecard.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Object.png b/indra/newview/skins/default/textures/icons/Inv_Object.png
new file mode 100644
index 0000000000..f883696a82
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Object.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Pants.png b/indra/newview/skins/default/textures/icons/Inv_Pants.png
new file mode 100644
index 0000000000..fe2389f074
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Pants.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Script.png b/indra/newview/skins/default/textures/icons/Inv_Script.png
new file mode 100644
index 0000000000..0fba27a7aa
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Script.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Shirt.png b/indra/newview/skins/default/textures/icons/Inv_Shirt.png
new file mode 100644
index 0000000000..81c1538dd2
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Shirt.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Shoe.png b/indra/newview/skins/default/textures/icons/Inv_Shoe.png
new file mode 100644
index 0000000000..51e1c7bbb7
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Shoe.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Skin.png b/indra/newview/skins/default/textures/icons/Inv_Skin.png
new file mode 100644
index 0000000000..b7da922046
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Skin.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Skirt.png b/indra/newview/skins/default/textures/icons/Inv_Skirt.png
new file mode 100644
index 0000000000..246e9a87aa
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Skirt.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Snapshot.png b/indra/newview/skins/default/textures/icons/Inv_Snapshot.png
new file mode 100644
index 0000000000..39efd2be1b
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Snapshot.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Socks.png b/indra/newview/skins/default/textures/icons/Inv_Socks.png
new file mode 100644
index 0000000000..30d7d7c239
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Socks.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Sound.png b/indra/newview/skins/default/textures/icons/Inv_Sound.png
new file mode 100644
index 0000000000..44c271c868
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Sound.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Tattoo.png b/indra/newview/skins/default/textures/icons/Inv_Tattoo.png
new file mode 100644
index 0000000000..a632197eb5
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Tattoo.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Texture.png b/indra/newview/skins/default/textures/icons/Inv_Texture.png
new file mode 100644
index 0000000000..dbc41c5e99
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Texture.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Underpants.png b/indra/newview/skins/default/textures/icons/Inv_Underpants.png
new file mode 100644
index 0000000000..b1e7c2a55f
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Underpants.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Undershirt.png b/indra/newview/skins/default/textures/icons/Inv_Undershirt.png
new file mode 100644
index 0000000000..9340dbb975
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Undershirt.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Lock.png b/indra/newview/skins/default/textures/icons/Lock.png
new file mode 100644
index 0000000000..eb5b5ae7a9
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Lock.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Microphone_On.png b/indra/newview/skins/default/textures/icons/Microphone_On.png
new file mode 100644
index 0000000000..c96b500fa1
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Microphone_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/MinusItem_Disabled.png b/indra/newview/skins/default/textures/icons/MinusItem_Disabled.png
new file mode 100644
index 0000000000..75bd73cef1
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/MinusItem_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/MinusItem_Off.png b/indra/newview/skins/default/textures/icons/MinusItem_Off.png
new file mode 100644
index 0000000000..6f285f3546
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/MinusItem_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/MinusItem_Press.png b/indra/newview/skins/default/textures/icons/MinusItem_Press.png
new file mode 100644
index 0000000000..50f65765d5
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/MinusItem_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OptionsMenu_Disabled.png b/indra/newview/skins/default/textures/icons/OptionsMenu_Disabled.png
new file mode 100644
index 0000000000..fb341e9c83
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OptionsMenu_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OptionsMenu_Off.png b/indra/newview/skins/default/textures/icons/OptionsMenu_Off.png
new file mode 100644
index 0000000000..25b055bfc0
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OptionsMenu_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OptionsMenu_Over.png b/indra/newview/skins/default/textures/icons/OptionsMenu_Over.png
new file mode 100644
index 0000000000..fcabd4c6d3
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OptionsMenu_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OptionsMenu_Press.png b/indra/newview/skins/default/textures/icons/OptionsMenu_Press.png
new file mode 100644
index 0000000000..6e91dd7159
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OptionsMenu_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_BuildNo_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_BuildNo_Dark.png
new file mode 100644
index 0000000000..fb1f7d3a6d
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_BuildNo_Dark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_BuildNo_Light.png b/indra/newview/skins/default/textures/icons/Parcel_BuildNo_Light.png
new file mode 100644
index 0000000000..e6f614b844
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_BuildNo_Light.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_Build_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_Build_Dark.png
new file mode 100644
index 0000000000..84a96a60cb
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_Build_Dark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_DamageNo_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_DamageNo_Dark.png
new file mode 100644
index 0000000000..d55ebd7c67
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_DamageNo_Dark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_Damage_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_Damage_Dark.png
new file mode 100644
index 0000000000..ae4077488b
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_Damage_Dark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_Damage_Light_Alt.png b/indra/newview/skins/default/textures/icons/Parcel_Damage_Light_Alt.png
new file mode 100644
index 0000000000..d72f02f708
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_Damage_Light_Alt.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_Exp_Color.png b/indra/newview/skins/default/textures/icons/Parcel_Exp_Color.png
new file mode 100644
index 0000000000..4813d37198
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_Exp_Color.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_FlyNo_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_FlyNo_Dark.png
new file mode 100644
index 0000000000..0455a52fdc
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_FlyNo_Dark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_FlyNo_Light.png b/indra/newview/skins/default/textures/icons/Parcel_FlyNo_Light.png
new file mode 100644
index 0000000000..be0c379d84
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_FlyNo_Light.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_Fly_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_Fly_Dark.png
new file mode 100644
index 0000000000..ed4a512e04
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_Fly_Dark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_ForSale_Light.png b/indra/newview/skins/default/textures/icons/Parcel_ForSale_Light.png
new file mode 100644
index 0000000000..d28e5357df
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_ForSale_Light.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_Health_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_Health_Dark.png
new file mode 100644
index 0000000000..d72f02f708
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_Health_Dark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_M_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_M_Dark.png
new file mode 100644
index 0000000000..2f5871b8ff
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_M_Dark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_M_Light.png b/indra/newview/skins/default/textures/icons/Parcel_M_Light.png
new file mode 100644
index 0000000000..724ac22744
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_M_Light.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_NoScripts_Light.png b/indra/newview/skins/default/textures/icons/Parcel_NoScripts_Light.png
new file mode 100644
index 0000000000..f82354959e
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_NoScripts_Light.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_PG_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_PG_Dark.png
new file mode 100644
index 0000000000..f0565f02dd
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_PG_Dark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_PG_Light.png b/indra/newview/skins/default/textures/icons/Parcel_PG_Light.png
new file mode 100644
index 0000000000..f32b0570a1
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_PG_Light.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_PushNo_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_PushNo_Dark.png
new file mode 100644
index 0000000000..8f0fe6a04d
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_PushNo_Dark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_PushNo_Light.png b/indra/newview/skins/default/textures/icons/Parcel_PushNo_Light.png
new file mode 100644
index 0000000000..eba7070b4d
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_PushNo_Light.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_Push_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_Push_Dark.png
new file mode 100644
index 0000000000..08c2a18ac3
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_Push_Dark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_R_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_R_Dark.png
new file mode 100644
index 0000000000..e0e6e14cca
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_R_Dark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_R_Light.png b/indra/newview/skins/default/textures/icons/Parcel_R_Light.png
new file mode 100644
index 0000000000..efca6776da
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_R_Light.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_ScriptsNo_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_ScriptsNo_Dark.png
new file mode 100644
index 0000000000..8f9f37a1bf
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_ScriptsNo_Dark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_Scripts_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_Scripts_Dark.png
new file mode 100644
index 0000000000..8b1d6c5e14
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_Scripts_Dark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_VoiceNo_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_VoiceNo_Dark.png
new file mode 100644
index 0000000000..eace54ae79
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_VoiceNo_Dark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_VoiceNo_Light.png b/indra/newview/skins/default/textures/icons/Parcel_VoiceNo_Light.png
new file mode 100644
index 0000000000..0d07e552b1
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_VoiceNo_Light.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_Voice_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_Voice_Dark.png
new file mode 100644
index 0000000000..b36a9bd2f0
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_Voice_Dark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_Voice_Light.png b/indra/newview/skins/default/textures/icons/Parcel_Voice_Light.png
new file mode 100644
index 0000000000..86ce19474a
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_Voice_Light.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Pause_Off.png b/indra/newview/skins/default/textures/icons/Pause_Off.png
new file mode 100644
index 0000000000..77f6be569d
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Pause_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Pause_Over.png b/indra/newview/skins/default/textures/icons/Pause_Over.png
new file mode 100644
index 0000000000..580808bf7e
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Pause_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Pause_Press.png b/indra/newview/skins/default/textures/icons/Pause_Press.png
new file mode 100644
index 0000000000..859db34cae
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Pause_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Play_Off.png b/indra/newview/skins/default/textures/icons/Play_Off.png
new file mode 100644
index 0000000000..e594c1a4cb
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Play_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Play_Over.png b/indra/newview/skins/default/textures/icons/Play_Over.png
new file mode 100644
index 0000000000..70ab94e8c2
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Play_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Play_Press.png b/indra/newview/skins/default/textures/icons/Play_Press.png
new file mode 100644
index 0000000000..b52742c6da
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Play_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Progress_1.png b/indra/newview/skins/default/textures/icons/Progress_1.png
new file mode 100644
index 0000000000..58b56003c4
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Progress_1.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Progress_10.png b/indra/newview/skins/default/textures/icons/Progress_10.png
new file mode 100644
index 0000000000..07fe0be8a3
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Progress_10.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Progress_11.png b/indra/newview/skins/default/textures/icons/Progress_11.png
new file mode 100644
index 0000000000..215d68cc46
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Progress_11.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Progress_12.png b/indra/newview/skins/default/textures/icons/Progress_12.png
new file mode 100644
index 0000000000..d755588621
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Progress_12.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Progress_2.png b/indra/newview/skins/default/textures/icons/Progress_2.png
new file mode 100644
index 0000000000..6640ee227b
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Progress_2.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Progress_3.png b/indra/newview/skins/default/textures/icons/Progress_3.png
new file mode 100644
index 0000000000..5decbe977e
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Progress_3.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Progress_4.png b/indra/newview/skins/default/textures/icons/Progress_4.png
new file mode 100644
index 0000000000..56e81c17aa
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Progress_4.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Progress_5.png b/indra/newview/skins/default/textures/icons/Progress_5.png
new file mode 100644
index 0000000000..a89bf2ac62
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Progress_5.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Progress_6.png b/indra/newview/skins/default/textures/icons/Progress_6.png
new file mode 100644
index 0000000000..233c479540
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Progress_6.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Progress_7.png b/indra/newview/skins/default/textures/icons/Progress_7.png
new file mode 100644
index 0000000000..631d7a6819
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Progress_7.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Progress_8.png b/indra/newview/skins/default/textures/icons/Progress_8.png
new file mode 100644
index 0000000000..ac0e3f13f7
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Progress_8.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Progress_9.png b/indra/newview/skins/default/textures/icons/Progress_9.png
new file mode 100644
index 0000000000..17fb4a0335
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Progress_9.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Refresh_Off.png b/indra/newview/skins/default/textures/icons/Refresh_Off.png
new file mode 100644
index 0000000000..a8acfda741
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Refresh_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/SL_Logo.png b/indra/newview/skins/default/textures/icons/SL_Logo.png
new file mode 100644
index 0000000000..c9fbde987a
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/SL_Logo.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/SkipBackward_Off.png b/indra/newview/skins/default/textures/icons/SkipBackward_Off.png
new file mode 100644
index 0000000000..8fc10e6583
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/SkipBackward_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/SkipForward_Off.png b/indra/newview/skins/default/textures/icons/SkipForward_Off.png
new file mode 100644
index 0000000000..2892e3cfa9
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/SkipForward_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/StopReload_Off.png b/indra/newview/skins/default/textures/icons/StopReload_Off.png
new file mode 100644
index 0000000000..698569a540
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/StopReload_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/StopReload_Over.png b/indra/newview/skins/default/textures/icons/StopReload_Over.png
new file mode 100644
index 0000000000..251b38630a
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/StopReload_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Stop_Off.png b/indra/newview/skins/default/textures/icons/Stop_Off.png
new file mode 100644
index 0000000000..3ee215d36f
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Stop_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/TrashItem_Disabled.png b/indra/newview/skins/default/textures/icons/TrashItem_Disabled.png
new file mode 100644
index 0000000000..caaf45a99f
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/TrashItem_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/TrashItem_Off.png b/indra/newview/skins/default/textures/icons/TrashItem_Off.png
new file mode 100644
index 0000000000..bb64920ec4
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/TrashItem_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/TrashItem_Over.png b/indra/newview/skins/default/textures/icons/TrashItem_Over.png
new file mode 100644
index 0000000000..1a0eea6c67
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/TrashItem_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/TrashItem_Press.png b/indra/newview/skins/default/textures/icons/TrashItem_Press.png
new file mode 100644
index 0000000000..c62f833d86
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/TrashItem_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/UnZoom_Off.png b/indra/newview/skins/default/textures/icons/UnZoom_Off.png
new file mode 100644
index 0000000000..c794113755
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/UnZoom_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/VoicePTT_Lvl1.png b/indra/newview/skins/default/textures/icons/VoicePTT_Lvl1.png
new file mode 100644
index 0000000000..cd18ae310d
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/VoicePTT_Lvl1.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/VoicePTT_Lvl2.png b/indra/newview/skins/default/textures/icons/VoicePTT_Lvl2.png
new file mode 100644
index 0000000000..b0ed6ee8eb
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/VoicePTT_Lvl2.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/VoicePTT_Lvl3.png b/indra/newview/skins/default/textures/icons/VoicePTT_Lvl3.png
new file mode 100644
index 0000000000..14ec77b99a
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/VoicePTT_Lvl3.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/VoicePTT_Off.png b/indra/newview/skins/default/textures/icons/VoicePTT_Off.png
new file mode 100644
index 0000000000..48be51e9af
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/VoicePTT_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/VoicePTT_On.png b/indra/newview/skins/default/textures/icons/VoicePTT_On.png
new file mode 100644
index 0000000000..be4881b64c
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/VoicePTT_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/YouAreHere_Badge.png b/indra/newview/skins/default/textures/icons/YouAreHere_Badge.png
new file mode 100644
index 0000000000..c057e9743d
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/YouAreHere_Badge.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Zoom_Off.png b/indra/newview/skins/default/textures/icons/Zoom_Off.png
new file mode 100644
index 0000000000..d096720c9c
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Zoom_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/avaline_default_icon.jpg b/indra/newview/skins/default/textures/icons/avaline_default_icon.jpg
new file mode 100644
index 0000000000..3bb7f7183c
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/avaline_default_icon.jpg
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/parcel_color_EVRY.png b/indra/newview/skins/default/textures/icons/parcel_color_EVRY.png
new file mode 100644
index 0000000000..b5508423eb
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/parcel_color_EVRY.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/parcel_color_EXP.png b/indra/newview/skins/default/textures/icons/parcel_color_EXP.png
new file mode 100644
index 0000000000..4813d37198
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/parcel_color_EXP.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/parcel_color_M.png b/indra/newview/skins/default/textures/icons/parcel_color_M.png
new file mode 100644
index 0000000000..41984c43e4
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/parcel_color_M.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/image_edit_icon.tga b/indra/newview/skins/default/textures/image_edit_icon.tga
new file mode 100644
index 0000000000..8666f0bbe6
--- /dev/null
+++ b/indra/newview/skins/default/textures/image_edit_icon.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/inv_folder_inbox.tga b/indra/newview/skins/default/textures/inv_folder_inbox.tga
new file mode 100644
index 0000000000..04539c2cc4
--- /dev/null
+++ b/indra/newview/skins/default/textures/inv_folder_inbox.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/jump_left_in.tga b/indra/newview/skins/default/textures/jump_left_in.tga
new file mode 100644
index 0000000000..e0656c901d
--- /dev/null
+++ b/indra/newview/skins/default/textures/jump_left_in.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/jump_left_out.tga b/indra/newview/skins/default/textures/jump_left_out.tga
new file mode 100644
index 0000000000..fb6dac0c3d
--- /dev/null
+++ b/indra/newview/skins/default/textures/jump_left_out.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/jump_right_in.tga b/indra/newview/skins/default/textures/jump_right_in.tga
new file mode 100644
index 0000000000..010c748c2a
--- /dev/null
+++ b/indra/newview/skins/default/textures/jump_right_in.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/jump_right_out.tga b/indra/newview/skins/default/textures/jump_right_out.tga
new file mode 100644
index 0000000000..33355262d4
--- /dev/null
+++ b/indra/newview/skins/default/textures/jump_right_out.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/map_avatar_16.tga b/indra/newview/skins/default/textures/map_avatar_16.tga
index ce129e3590..f59e9e9193 100644
--- a/indra/newview/skins/default/textures/map_avatar_16.tga
+++ b/indra/newview/skins/default/textures/map_avatar_16.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/map_avatar_32.tga b/indra/newview/skins/default/textures/map_avatar_32.tga
new file mode 100644
index 0000000000..aebeab4093
--- /dev/null
+++ b/indra/newview/skins/default/textures/map_avatar_32.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/map_avatar_8.tga b/indra/newview/skins/default/textures/map_avatar_8.tga
index 28552f2237..8500eadeba 100644
--- a/indra/newview/skins/default/textures/map_avatar_8.tga
+++ b/indra/newview/skins/default/textures/map_avatar_8.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/map_avatar_above_32.tga b/indra/newview/skins/default/textures/map_avatar_above_32.tga
new file mode 100644
index 0000000000..65bd0561a7
--- /dev/null
+++ b/indra/newview/skins/default/textures/map_avatar_above_32.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/map_avatar_below_32.tga b/indra/newview/skins/default/textures/map_avatar_below_32.tga
new file mode 100644
index 0000000000..496c44b369
--- /dev/null
+++ b/indra/newview/skins/default/textures/map_avatar_below_32.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/map_avatar_you_32.tga b/indra/newview/skins/default/textures/map_avatar_you_32.tga
new file mode 100644
index 0000000000..782207efd6
--- /dev/null
+++ b/indra/newview/skins/default/textures/map_avatar_you_32.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/map_event.tga b/indra/newview/skins/default/textures/map_event.tga
index c229b379a2..2c06d08fd2 100644
--- a/indra/newview/skins/default/textures/map_event.tga
+++ b/indra/newview/skins/default/textures/map_event.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/map_event_adult.tga b/indra/newview/skins/default/textures/map_event_adult.tga
index c344fb1e78..f548126e5a 100644
--- a/indra/newview/skins/default/textures/map_event_adult.tga
+++ b/indra/newview/skins/default/textures/map_event_adult.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/map_event_mature.tga b/indra/newview/skins/default/textures/map_event_mature.tga
index 61c879bc92..71067c0dfd 100644
--- a/indra/newview/skins/default/textures/map_event_mature.tga
+++ b/indra/newview/skins/default/textures/map_event_mature.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/map_home.tga b/indra/newview/skins/default/textures/map_home.tga
index 7478de371a..acaaa3db44 100644
--- a/indra/newview/skins/default/textures/map_home.tga
+++ b/indra/newview/skins/default/textures/map_home.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/map_infohub.tga b/indra/newview/skins/default/textures/map_infohub.tga
index d0134fa5fe..545b8e532c 100644
--- a/indra/newview/skins/default/textures/map_infohub.tga
+++ b/indra/newview/skins/default/textures/map_infohub.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/map_telehub.tga b/indra/newview/skins/default/textures/map_telehub.tga
index ef63a3eb72..545b8e532c 100644
--- a/indra/newview/skins/default/textures/map_telehub.tga
+++ b/indra/newview/skins/default/textures/map_telehub.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/menu_separator.png b/indra/newview/skins/default/textures/menu_separator.png
new file mode 100644
index 0000000000..89dcdcdff5
--- /dev/null
+++ b/indra/newview/skins/default/textures/menu_separator.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Arrow_Left_Off.png b/indra/newview/skins/default/textures/navbar/Arrow_Left_Off.png
new file mode 100644
index 0000000000..19569501fe
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/Arrow_Left_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Arrow_Left_Over.png b/indra/newview/skins/default/textures/navbar/Arrow_Left_Over.png
new file mode 100644
index 0000000000..a91b74819f
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/Arrow_Left_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Arrow_Right_Off.png b/indra/newview/skins/default/textures/navbar/Arrow_Right_Off.png
new file mode 100644
index 0000000000..3648c42656
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/Arrow_Right_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Arrow_Right_Over.png b/indra/newview/skins/default/textures/navbar/Arrow_Right_Over.png
new file mode 100644
index 0000000000..a2caf227a7
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/Arrow_Right_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png b/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png
new file mode 100644
index 0000000000..41cb88628a
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png b/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png
new file mode 100644
index 0000000000..a02675502a
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Favorite_Link_Over.png b/indra/newview/skins/default/textures/navbar/Favorite_Link_Over.png
new file mode 100644
index 0000000000..d4f126f969
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/Favorite_Link_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Favorite_Star_Active.png b/indra/newview/skins/default/textures/navbar/Favorite_Star_Active.png
new file mode 100644
index 0000000000..e27dbe2cad
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/Favorite_Star_Active.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Favorite_Star_Off.png b/indra/newview/skins/default/textures/navbar/Favorite_Star_Off.png
new file mode 100644
index 0000000000..82d044d817
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/Favorite_Star_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Favorite_Star_Over.png b/indra/newview/skins/default/textures/navbar/Favorite_Star_Over.png
new file mode 100644
index 0000000000..7909d54f2b
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/Favorite_Star_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Favorite_Star_Press.png b/indra/newview/skins/default/textures/navbar/Favorite_Star_Press.png
new file mode 100644
index 0000000000..6670667022
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/Favorite_Star_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/FileMenu_Divider.png b/indra/newview/skins/default/textures/navbar/FileMenu_Divider.png
new file mode 100644
index 0000000000..5ab4abc5b8
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/FileMenu_Divider.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Flag.png b/indra/newview/skins/default/textures/navbar/Flag.png
new file mode 100644
index 0000000000..df53c89224
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/Flag.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Help_Over.png b/indra/newview/skins/default/textures/navbar/Help_Over.png
new file mode 100644
index 0000000000..b9bc0d0f87
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/Help_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Help_Press.png b/indra/newview/skins/default/textures/navbar/Help_Press.png
new file mode 100644
index 0000000000..ed3695f9d5
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/Help_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Home_Off.png b/indra/newview/skins/default/textures/navbar/Home_Off.png
new file mode 100644
index 0000000000..fe3bc63b77
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/Home_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Home_Over.png b/indra/newview/skins/default/textures/navbar/Home_Over.png
new file mode 100644
index 0000000000..d9c6b3842e
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/Home_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Info_Off.png b/indra/newview/skins/default/textures/navbar/Info_Off.png
new file mode 100644
index 0000000000..64722255a3
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/Info_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Info_Over.png b/indra/newview/skins/default/textures/navbar/Info_Over.png
new file mode 100644
index 0000000000..84f1d03129
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/Info_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Info_Press.png b/indra/newview/skins/default/textures/navbar/Info_Press.png
new file mode 100644
index 0000000000..169105829e
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/Info_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Lock.png b/indra/newview/skins/default/textures/navbar/Lock.png
new file mode 100644
index 0000000000..cf569d6ad2
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/Lock.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/NavBar_BG.png b/indra/newview/skins/default/textures/navbar/NavBar_BG.png
new file mode 100644
index 0000000000..38eea783e6
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/NavBar_BG.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Row_Selection.png b/indra/newview/skins/default/textures/navbar/Row_Selection.png
new file mode 100644
index 0000000000..fc4f0c07ef
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/Row_Selection.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/navbar/Search.png b/indra/newview/skins/default/textures/navbar/Search.png
new file mode 100644
index 0000000000..0d0e330bc7
--- /dev/null
+++ b/indra/newview/skins/default/textures/navbar/Search.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/places_rating_adult.tga b/indra/newview/skins/default/textures/places_rating_adult.tga
new file mode 100644
index 0000000000..c344fb1e78
--- /dev/null
+++ b/indra/newview/skins/default/textures/places_rating_adult.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/places_rating_mature.tga b/indra/newview/skins/default/textures/places_rating_mature.tga
new file mode 100644
index 0000000000..61c879bc92
--- /dev/null
+++ b/indra/newview/skins/default/textures/places_rating_mature.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/places_rating_pg.tga b/indra/newview/skins/default/textures/places_rating_pg.tga
new file mode 100644
index 0000000000..7805dbce60
--- /dev/null
+++ b/indra/newview/skins/default/textures/places_rating_pg.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/quick_tips/avatar_free_mode.png b/indra/newview/skins/default/textures/quick_tips/avatar_free_mode.png
new file mode 100644
index 0000000000..be7c87efb6
--- /dev/null
+++ b/indra/newview/skins/default/textures/quick_tips/avatar_free_mode.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/quick_tips/camera_free_mode.png b/indra/newview/skins/default/textures/quick_tips/camera_free_mode.png
new file mode 100644
index 0000000000..9a3f3703b2
--- /dev/null
+++ b/indra/newview/skins/default/textures/quick_tips/camera_free_mode.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/quick_tips/camera_orbit_mode.png b/indra/newview/skins/default/textures/quick_tips/camera_orbit_mode.png
new file mode 100644
index 0000000000..dd72cc0162
--- /dev/null
+++ b/indra/newview/skins/default/textures/quick_tips/camera_orbit_mode.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/quick_tips/camera_pan_mode.png b/indra/newview/skins/default/textures/quick_tips/camera_pan_mode.png
new file mode 100644
index 0000000000..b537dcbe46
--- /dev/null
+++ b/indra/newview/skins/default/textures/quick_tips/camera_pan_mode.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/quick_tips/camera_preset_front_view.png b/indra/newview/skins/default/textures/quick_tips/camera_preset_front_view.png
new file mode 100644
index 0000000000..7674a75ac3
--- /dev/null
+++ b/indra/newview/skins/default/textures/quick_tips/camera_preset_front_view.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/quick_tips/camera_preset_group_view.png b/indra/newview/skins/default/textures/quick_tips/camera_preset_group_view.png
new file mode 100644
index 0000000000..9c9b923a5a
--- /dev/null
+++ b/indra/newview/skins/default/textures/quick_tips/camera_preset_group_view.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/quick_tips/camera_preset_rear_view.png b/indra/newview/skins/default/textures/quick_tips/camera_preset_rear_view.png
new file mode 100644
index 0000000000..15c3053491
--- /dev/null
+++ b/indra/newview/skins/default/textures/quick_tips/camera_preset_rear_view.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/quick_tips/move_fly_first.png b/indra/newview/skins/default/textures/quick_tips/move_fly_first.png
new file mode 100644
index 0000000000..b6e2ce60e4
--- /dev/null
+++ b/indra/newview/skins/default/textures/quick_tips/move_fly_first.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/quick_tips/move_fly_second.png b/indra/newview/skins/default/textures/quick_tips/move_fly_second.png
new file mode 100644
index 0000000000..84b63cc338
--- /dev/null
+++ b/indra/newview/skins/default/textures/quick_tips/move_fly_second.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/quick_tips/move_run_first.png b/indra/newview/skins/default/textures/quick_tips/move_run_first.png
new file mode 100644
index 0000000000..16093dc683
--- /dev/null
+++ b/indra/newview/skins/default/textures/quick_tips/move_run_first.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/quick_tips/move_run_second.png b/indra/newview/skins/default/textures/quick_tips/move_run_second.png
new file mode 100644
index 0000000000..19fa43ec32
--- /dev/null
+++ b/indra/newview/skins/default/textures/quick_tips/move_run_second.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/quick_tips/move_walk_first.png b/indra/newview/skins/default/textures/quick_tips/move_walk_first.png
new file mode 100644
index 0000000000..92d120d53e
--- /dev/null
+++ b/indra/newview/skins/default/textures/quick_tips/move_walk_first.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/quick_tips/move_walk_second.png b/indra/newview/skins/default/textures/quick_tips/move_walk_second.png
new file mode 100644
index 0000000000..f8e28722be
--- /dev/null
+++ b/indra/newview/skins/default/textures/quick_tips/move_walk_second.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/show_btn.tga b/indra/newview/skins/default/textures/show_btn.tga
new file mode 100644
index 0000000000..5f05f377e3
--- /dev/null
+++ b/indra/newview/skins/default/textures/show_btn.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/show_btn_selected.tga b/indra/newview/skins/default/textures/show_btn_selected.tga
new file mode 100644
index 0000000000..00a2f34a37
--- /dev/null
+++ b/indra/newview/skins/default/textures/show_btn_selected.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/taskpanel/Activate_Checkmark.png b/indra/newview/skins/default/textures/taskpanel/Activate_Checkmark.png
new file mode 100644
index 0000000000..213acbe87b
--- /dev/null
+++ b/indra/newview/skins/default/textures/taskpanel/Activate_Checkmark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/taskpanel/TabIcon_Appearance_Off.png b/indra/newview/skins/default/textures/taskpanel/TabIcon_Appearance_Off.png
new file mode 100644
index 0000000000..0b91abfb0d
--- /dev/null
+++ b/indra/newview/skins/default/textures/taskpanel/TabIcon_Appearance_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/taskpanel/TabIcon_Appearance_Selected.png b/indra/newview/skins/default/textures/taskpanel/TabIcon_Appearance_Selected.png
new file mode 100644
index 0000000000..33a47236a5
--- /dev/null
+++ b/indra/newview/skins/default/textures/taskpanel/TabIcon_Appearance_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/taskpanel/TabIcon_Close_Off.png b/indra/newview/skins/default/textures/taskpanel/TabIcon_Close_Off.png
new file mode 100644
index 0000000000..bc4e00c646
--- /dev/null
+++ b/indra/newview/skins/default/textures/taskpanel/TabIcon_Close_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/taskpanel/TabIcon_Home_Off.png b/indra/newview/skins/default/textures/taskpanel/TabIcon_Home_Off.png
new file mode 100644
index 0000000000..1e7d7beafa
--- /dev/null
+++ b/indra/newview/skins/default/textures/taskpanel/TabIcon_Home_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/taskpanel/TabIcon_Home_Selected.png b/indra/newview/skins/default/textures/taskpanel/TabIcon_Home_Selected.png
new file mode 100644
index 0000000000..a70d3abbbf
--- /dev/null
+++ b/indra/newview/skins/default/textures/taskpanel/TabIcon_Home_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/taskpanel/TabIcon_Me_Off.png b/indra/newview/skins/default/textures/taskpanel/TabIcon_Me_Off.png
new file mode 100644
index 0000000000..760db9360d
--- /dev/null
+++ b/indra/newview/skins/default/textures/taskpanel/TabIcon_Me_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/taskpanel/TabIcon_Me_Selected.png b/indra/newview/skins/default/textures/taskpanel/TabIcon_Me_Selected.png
new file mode 100644
index 0000000000..905d4c973e
--- /dev/null
+++ b/indra/newview/skins/default/textures/taskpanel/TabIcon_Me_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/taskpanel/TabIcon_Open_Off.png b/indra/newview/skins/default/textures/taskpanel/TabIcon_Open_Off.png
new file mode 100644
index 0000000000..4556602f58
--- /dev/null
+++ b/indra/newview/skins/default/textures/taskpanel/TabIcon_Open_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/taskpanel/TabIcon_People_Off.png b/indra/newview/skins/default/textures/taskpanel/TabIcon_People_Off.png
new file mode 100644
index 0000000000..691b600510
--- /dev/null
+++ b/indra/newview/skins/default/textures/taskpanel/TabIcon_People_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/taskpanel/TabIcon_People_Selected.png b/indra/newview/skins/default/textures/taskpanel/TabIcon_People_Selected.png
new file mode 100644
index 0000000000..909f0d0a47
--- /dev/null
+++ b/indra/newview/skins/default/textures/taskpanel/TabIcon_People_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/taskpanel/TabIcon_Places_Large.png b/indra/newview/skins/default/textures/taskpanel/TabIcon_Places_Large.png
new file mode 100644
index 0000000000..cc505c4a30
--- /dev/null
+++ b/indra/newview/skins/default/textures/taskpanel/TabIcon_Places_Large.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/taskpanel/TabIcon_Places_Off.png b/indra/newview/skins/default/textures/taskpanel/TabIcon_Places_Off.png
new file mode 100644
index 0000000000..f5a5f7a846
--- /dev/null
+++ b/indra/newview/skins/default/textures/taskpanel/TabIcon_Places_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/taskpanel/TabIcon_Places_Selected.png b/indra/newview/skins/default/textures/taskpanel/TabIcon_Places_Selected.png
new file mode 100644
index 0000000000..8e0fb9661e
--- /dev/null
+++ b/indra/newview/skins/default/textures/taskpanel/TabIcon_Places_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/taskpanel/TabIcon_Things_Off.png b/indra/newview/skins/default/textures/taskpanel/TabIcon_Things_Off.png
new file mode 100644
index 0000000000..e56eda9802
--- /dev/null
+++ b/indra/newview/skins/default/textures/taskpanel/TabIcon_Things_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/taskpanel/TabIcon_Things_Selected.png b/indra/newview/skins/default/textures/taskpanel/TabIcon_Things_Selected.png
new file mode 100644
index 0000000000..d4ac451c8e
--- /dev/null
+++ b/indra/newview/skins/default/textures/taskpanel/TabIcon_Things_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/taskpanel/TaskPanel_Tab_Off.png b/indra/newview/skins/default/textures/taskpanel/TaskPanel_Tab_Off.png
new file mode 100644
index 0000000000..4ed7a2b183
--- /dev/null
+++ b/indra/newview/skins/default/textures/taskpanel/TaskPanel_Tab_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/taskpanel/TaskPanel_Tab_Selected.png b/indra/newview/skins/default/textures/taskpanel/TaskPanel_Tab_Selected.png
new file mode 100644
index 0000000000..b3316386b9
--- /dev/null
+++ b/indra/newview/skins/default/textures/taskpanel/TaskPanel_Tab_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 34c9dea7e6..60c1470b89 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -1,376 +1,753 @@
+<!--
+This file contains metadata about how to load, display, and scale textures for rendering in the UI.
+Images do *NOT* have to appear in this file in order to use them as textures in the UI...simply refer
+to them by filename (relative to textures directory).
+NOTE: if you want to reuse an image file with different metadata, simply create a new texture entry
+with the same filename but different name
+
+<texture
+ name="MyTexture" (mandatory)
+ - this is the name you reference the texture by in XUI. For example, <button image_unselected="MyTexture"/>
+ file_name="images/my_texture.png" (optional)
+ - this is the path to the actual file asset, relative to the current skins "textures" directory.
+ If not supplied, the filename will be taken from the texture name itself, "MyTexture" in this case.
+ NOTE: you need to provide an extension on the filename (".png", ".tga", ".jpg") for us to decode the image properly
+ preload="true" (optional, false by default)
+ - If true, we will attempt to load the image before displaying any UI.
+ If false, we will load in the background after initializing the UI.
+ use_mips="true" (currently unused)
+ scale.left="1"
+ scale.bottom="1"
+ scale.top="15"
+ scale.right="31"
+ - Specifies the segmentation for 9-slice image scaling. Specifically, the pixel offsets from the LOWER LEFT corner
+ that define the region of the image that is stretched to make the whole image fit in the required space.
+ In this example, if the source image is 32x16 pixels, we have defined a center region that starts one pixel up
+ and to the right from the bottom left corner and extends to 31 pixels right and 15 pixels up from the bottom left
+ corner. The end result is that the image will keep a 1 pixel border all around while stretching to fit the required
+ region.
+-->
+
<textures version="101">
+ <!-- Please add new files alphabetically to prevent merge conflicts. JC -->
+ <texture name="Accordion_ArrowClosed_Off" file_name="containers/Accordion_ArrowClosed_Off.png" preload="false" />
+ <texture name="Accordion_ArrowClosed_Press" file_name="containers/Accordion_ArrowClosed_Press.png" preload="false" />
+ <texture name="Accordion_ArrowOpened_Off" file_name="containers/Accordion_ArrowOpened_Off.png" preload="false" />
+ <texture name="Accordion_ArrowOpened_Press" file_name="containers/Accordion_ArrowOpened_Press.png" preload="false" />
+ <texture name="Accordion_Off" file_name="containers/Accordion_Off.png" preload="false" />
+ <texture name="Accordion_Press" file_name="containers/Accordion_Press.png" preload="false" />
+ <texture name="Accordion_Over" file_name="containers/Accordion_Over.png" preload="false" />
+ <texture name="Accordion_Selected" file_name="containers/Accordion_Selected.png" preload="false" />
+
+<texture name="Activate_Checkmark" file_name="taskpanel/Activate_Checkmark.png" preload="false" />
+
+ <texture name="AddItem_Disabled" file_name="icons/AddItem_Disabled.png" preload="false" />
+ <texture name="AddItem_Off" file_name="icons/AddItem_Off.png" preload="false" />
+ <texture name="AddItem_Press" file_name="icons/AddItem_Press.png" preload="false" />
+
+ <texture name="Arrow_Left_Off" file_name="navbar/Arrow_Left_Off.png" preload="true" />
+ <texture name="Arrow_Left_Press" file_name="navbar/Arrow_Left_Press.png" preload="true" />
+ <texture name="Arrow_Right_Off" file_name="navbar/Arrow_Right_Off.png" preload="true" />
+ <texture name="Arrow_Right_Press" file_name="navbar/Arrow_Right_Press.png" preload="true" />
+
+<!--
+ <texture name="Arrow_Left" file_name="widgets/Arrow_Left.png" preload="true" />
+ <texture name="Arrow_Right" file_name="widgets/Arrow_Right.png" preload="true" />
+-->
+
+ <texture name="Arrow_Small_Up" file_name="widgets/Arrow_Small_Up.png" preload="true" />
+ <texture name="Arrow_Small_Left" file_name="widgets/Arrow_Small_Left.png" preload="true" />
+ <texture name="Arrow_Small_Right" file_name="widgets/Arrow_Small_Right.png" preload="true" />
+
+ <texture name="Arrow_Down" file_name="widgets/Arrow_Down.png" preload="true" />
+ <texture name="Arrow_Up" file_name="widgets/Arrow_Up.png" preload="true" />
+
+ <texture name="AudioMute_Off" file_name="icons/AudioMute_Off.png" preload="false" />
+ <texture name="AudioMute_Over" file_name="icons/AudioMute_Over.png" preload="false" />
+ <texture name="AudioMute_Press" file_name="icons/AudioMute_Press.png" preload="false" />
+
+ <texture name="Audio_Off" file_name="icons/Audio_Off.png" preload="false" />
+ <texture name="Audio_Over" file_name="icons/Audio_Over.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_Disabled" file_name="icons/BackArrow_Disabled.png" preload="false" />
+ <texture name="BackArrow_Off" file_name="icons/BackArrow_Off.png" preload="false" />
+ <texture name="BackArrow_Press" file_name="icons/BackArrow_Press.png" preload="false" />
+
+ <texture name="Blank" file_name="Blank.png" preload="false" />
+
+ <texture name="BottomTray_BG" file_name="bottomtray/BottomTray_BG.png" preload="false" />
+ <texture name="BottomTray_Scroll_Right" file_name="navbar/Arrow_Right_Off.png" preload="false" />
+ <texture name="BottomTray_Scroll_Left" file_name="navbar/Arrow_Left_Off.png" preload="false" />
+
+ <texture name="BuyArrow_Off" file_name="navbar/BuyArrow_Off.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" />
+ <texture name="BuyArrow_Over" file_name="navbar/BuyArrow_Over.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" />
+ <texture name="BuyArrow_Press" file_name="navbar/BuyArrow_Press.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" />
+
+ <texture name="Cam_Avatar_Disabled" file_name="bottomtray/Cam_Avatar_Disabled.png" preload="false" />
+ <texture name="Cam_Avatar_Over" file_name="bottomtray/Cam_Avatar_Over.png" preload="false" />
+ <texture name="Cam_Avatar_Off" file_name="bottomtray/Cam_Avatar_Off.png" preload="false" />
+ <texture name="Cam_Avatar_Press" file_name="bottomtray/Cam_Avatar_Press.png" preload="false" />
+ <texture name="Cam_FreeCam_Disabled" file_name="bottomtray/Cam_FreeCam_Disabled.png" preload="false" />
+ <texture name="Cam_FreeCam_Off" file_name="bottomtray/Cam_FreeCam_Off.png" preload="false" />
+ <texture name="Cam_FreeCam_Over" file_name="bottomtray/Cam_FreeCam_Over.png" preload="false" />
+ <texture name="Cam_FreeCam_Press" file_name="bottomtray/Cam_FreeCam_Press.png" preload="false" />
+ <texture name="Cam_Orbit_Disabled" file_name="bottomtray/Cam_Orbit_Disabled.png" preload="false" />
+ <texture name="Cam_Orbit_Off" file_name="bottomtray/Cam_Orbit_Off.png" preload="false" />
+ <texture name="Cam_Orbit_Over" file_name="bottomtray/Cam_Orbit_Over.png" preload="false" />
+ <texture name="Cam_Orbit_Press" file_name="bottomtray/Cam_Orbit_Press.png" preload="false" />
+ <texture name="Cam_Pan_Disabled" file_name="bottomtray/Cam_Pan_Disabled.png" preload="false" />
+ <texture name="Cam_Pan_Off" file_name="bottomtray/Cam_Pan_Off.png" preload="false" />
+ <texture name="Cam_Pan_Over" file_name="bottomtray/CCam_Pan_Over.png" preload="false" />
+ <texture name="Cam_Pan_Press" file_name="bottomtray/Cam_Pan_Press.png" preload="false" />
+
+ <texture name="Cam_Preset_Back_Off" file_name="bottomtray/Cam_Preset_Back_Off.png" preload="false" />
+ <texture name="Cam_Preset_Back_On" file_name="bottomtray/Cam_Preset_Back_On.png" preload="false" />
+ <texture name="Cam_Preset_Eye_Off" file_name="bottomtray/Cam_Preset_Eye_Off.png" preload="false" />
+ <texture name="Cam_Preset_Eye_On" file_name="bottomtray/Cam_Preset_Eye_On.png" preload="false" />
+ <texture name="Cam_Preset_Front_Off" file_name="bottomtray/Cam_Preset_Front_Off.png" preload="false" />
+ <texture name="Cam_Preset_Front_On" file_name="bottomtray/Cam_Preset_Front_On.png" preload="false" />
+ <texture name="Cam_Preset_Side_Off" file_name="bottomtray/Cam_Preset_Side_Off.png" preload="false" />
+ <texture name="Cam_Preset_Side_On" file_name="bottomtray/Cam_Preset_Side_On.png" preload="false" />
+
+ <texture name="Cam_Rotate_In" file_name="bottomtray/Cam_Rotate_In.png" preload="false" />
+ <texture name="Cam_Rotate_Out" file_name="bottomtray/Cam_Rotate_Out.png" preload="false" />
+ <texture name="Cam_Tracking_In" file_name="bottomtray/Cam_Tracking_In.png" preload="false" />
+ <texture name="Cam_Tracking_Out" file_name="bottomtray/Cam_Tracking_Out.png" preload="false" />
+ <texture name="CameraView_Off" file_name="bottomtray/CameraView_Off.png" preload="false" />
+ <texture name="CameraView_Over" file_name="bottomtray/CameraView_Over.png" preload="false" />
+
+ <texture name="Checkbox_Off_Disabled" file_name="widgets/Checkbox_Disabled.png" preload="true" />
+ <texture name="Checkbox_On_Disabled" file_name="widgets/Checkbox_On_Disabled.png" preload="true" />
+ <texture name="Checkbox_Off" file_name="widgets/Checkbox_Off.png" preload="true" />
+ <texture name="Checkbox_On" file_name="widgets/Checkbox_On.png" preload="true" />
+ <texture name="Checkbox_On_Press" file_name="widgets/Checkbox_On_Press.png" preload="true" />
+ <texture name="Checkbox_Press" file_name="widgets/Checkbox_Press.png" preload="true" />
+
+ <texture name="ComboButton_Disabled" file_name="widgets/ComboButton_Disabled.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="ComboButton_Over" file_name="widgets/ComboButton_Over.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="ComboButton_Press" file_name="widgets/ComboButton_Press.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="ComboButton_Selected" file_name="widgets/ComboButton_Selected.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="ComboButton_UpSelected" file_name="widgets/ComboButton_UpSelected.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="ComboButton_Up_On_Selected" file_name="widgets/ComboButton_Up_On_Selected.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="ComboButton_Off" file_name="widgets/ComboButton_Off.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="ComboButton_UpOff" file_name="widgets/ComboButton_UpOff.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="Container" file_name="containers/Container.png" preload="false" />
+
+ <texture name="DisclosureArrow_Closed_Off" file_name="widgets/DisclosureArrow_Closed_Off.png" preload="true" />
+ <texture name="DisclosureArrow_Closed_Press" file_name="widgets/DisclosureArrow_Closed_Press.png" preload="true" />
+ <texture name="DisclosureArrow_Opened_Off" file_name="widgets/DisclosureArrow_Opened_Off.png" preload="true" />
+ <texture name="DisclosureArrow_Opened_Press" file_name="widgets/DisclosureArrow_Opened_Press.png" preload="true" />
+
+ <texture name="DownArrow" file_name="bottomtray/DownArrow.png" preload="false" />
+
+ <texture name="DropDown_Disabled" file_name="widgets/DropDown_Disabled.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="DropDown_Over" file_name="widgets/DropDown_Over.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="DropDown_Press" file_name="widgets/DropDown_Press.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="DropDown_Selected" file_name="widgets/DropDown_Selected.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="DropDown_On" file_name="widgets/DropDown_On.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="DropDown_Off" file_name="widgets/DropDown_Off.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+
+ <texture name="DropTarget" file_name="widgets/DropTarget.png" preload="false" />
+
+ <texture name="ExternalBrowser_Off" file_name="icons/ExternalBrowser_Off.png" preload="false" />
+ <texture name="ExternalBrowser_Over" file_name="icons/ExternalBrowser_Over.png" preload="false" />
+ <texture name="ExternalBrowser_Press" file_name="icons/ExternalBrowser_Press.png" preload="false" />
+
+ <texture name="Favorite_Star_Active" file_name="navbar/Favorite_Star_Active.png" preload="false" />
+ <texture name="Favorite_Star_Off" file_name="navbar/Favorite_Star_Off.png" preload="false" />
+ <texture name="Favorite_Star_Press" file_name="navbar/Favorite_Star_Press.png" preload="false" />
+ <texture name="Favorite_Star_Over" file_name="navbar/Favorite_Star_Over.png" preload="false" />
+ <texture name="Favorite_Link_Over" file_name="navbar/Favorite_Link_Over.png" preload="false" />
+
+ <texture name="FileMenu_BarSelect" file_name="navbar/FileMenu_BarSelect.png" preload="false" scale.left="2" scale.top="0" scale.right="2" scale.bottom="0" />
+ <texture name="FileMenu_BG" file_name="navbar/FileMenu_BG.png" preload="false" />
+
+ <texture name="Flag" file_name="navbar/Flag.png" preload="false" />
+
+ <texture name="Folder_Arrow" file_name="folder_arrow.tga" preload="false" />
+ <texture name="ForSale_Badge" file_name="icons/ForSale_Badge.png" preload="false" />
+ <texture name="ForwardArrow_Off" file_name="icons/ForwardArrow_Off.png" preload="false" />
+ <texture name="ForwardArrow_Press" file_name="icons/ForwardArrow_Press.png" preload="false" />
+
+ <texture name="Generic_Group" file_name="icons/Generic_Group.png" preload="false" />
+ <texture name="icon_group.tga" file_name="icons/Generic_Group.png" preload="false" />
+ <texture name="Generic_Group_Large" file_name="icons/Generic_Group_Large.png" preload="false" />
+ <texture name="Generic_Object_Medium" file_name="icons/Generic_Object_Medium.png" preload="false" />
+ <texture name="Generic_Object_Small" file_name="icons/Generic_Object_Small.png" preload="false" />
+ <texture name="Generic_Object_Large" file_name="icons/Generic_Object_Large.png" preload="false" />
+ <texture name="Generic_Person" file_name="icons/Generic_Person.png" preload="false" />
+ <texture name="Generic_Person_Large" file_name="icons/Generic_Person_Large.png" preload="false" />
+
+ <texture name="Health" file_name="icons/Health.png" preload="false" />
+
+ <texture name="Help_Off" file_name="navbar/Help_Off.png" preload="false" />
+ <texture name="Help_Press" file_name="navbar/Help_Press.png" preload="false" />
+
+ <texture name="History_Arrow" file_name="navbar/History_Arrow.png" preload="true" />
+
+ <texture name="Home_Off" file_name="navbar/Home_Off.png" preload="false" />
+ <texture name="Home_Press" file_name="navbar/Home_Press.png" preload="false" />
+
+ <texture name="Icon_Close_Foreground" file_name="windows/Icon_Close_Foreground.png" preload="true" />
+ <texture name="Icon_Close_Press" file_name="windows/Icon_Close_Press.png" preload="true" />
+ <texture name="Icon_Close_Toast" file_name="windows/Icon_Close_Toast.png" preload="true" />
+
+ <texture name="Icon_Dock_Foreground" file_name="windows/Icon_Dock_Foreground.png" preload="true" />
+ <texture name="Icon_Dock_Press" file_name="windows/Icon_Dock_Press.png" preload="true" />
+
+ <texture name="Icon_For_Sale" file_name="icons/Icon_For_sale.png" preload="false" />
+
+ <texture name="Icon_Gear_Background" file_name="windows/Icon_Gear_Background.png" preload="false" />
+ <texture name="Icon_Gear_Foreground" file_name="windows/Icon_Gear_Foreground.png" preload="false" />
+ <texture name="Icon_Gear_Press" file_name="windows/Icon_Gear_Press.png" preload="false" />
+
+ <texture name="Icon_Help_Foreground" file_name="windows/Icon_Help_Foreground.png" preload="true" />
+ <texture name="Icon_Help_Press" file_name="windows/Icon_Help_Press.png" preload="true" />
+ <texture name="Icon_Info" file_name="windows/Icon_Info.png" preload="false" />
+
+ <texture name="Icon_Minimize_Foreground" file_name="windows/Icon_Minimize_Foreground.png" preload="true" />
+ <texture name="Icon_Minimize_Press" file_name="windows/Icon_Minimize_Press.png" preload="true" />
+
+ <texture name="Icon_Restore_Foreground" file_name="windows/Icon_Restore_Foreground.png" preload="false" />
+ <texture name="Icon_Restore_Press" file_name="windows/Icon_Restore_Press.png" preload="false" />
+
+ <texture name="Info" file_name="icons/Info.png" preload="false" />
+ <texture name="Info_Small" file_name="icons/Info_Small.png" preload="false" />
+ <texture name="Info_Off" file_name="navbar/Info_Off.png" preload="false" />
+ <texture name="Info_Over" file_name="icons/Info_Over.png" preload="false" />
+ <texture name="Info_Press" file_name="navbar/Info_Press.png" preload="false" />
+
+ <texture name="Inspector_Background" file_name="windows/Inspector_Background.png" preload="false"
+ scale.left="4" scale.top="28" scale.right="60" scale.bottom="4" />
+ <texture name="Inspector_Hover" file_name="windows/Inspector_Hover.png" preload="false" />
+ <texture name="Inspector_I" file_name="windows/Inspector_I.png" preload="false" />
+
+ <texture name="Inv_Acessories" file_name="icons/Inv_Accessories.png" preload="false" />
+ <texture name="Inv_Alpha" file_name="icons/Inv_Alpha.png" preload="false" />
+ <texture name="Inv_Animation" file_name="icons/Inv_Animation.png" preload="false" />
+ <texture name="Inv_BodyShape" file_name="icons/Inv_BodyShape.png" preload="false" />
+ <texture name="Inv_CallingCard" file_name="icons/Inv_CallingCard.png" preload="false" />
+ <texture name="Inv_Clothing" file_name="icons/Inv_Clothing.png" preload="false" />
+ <texture name="Inv_DangerousScript" file_name="icons/Inv_DangerousScript.png" preload="false" />
+ <texture name="Inv_Eye" file_name="icons/Inv_Eye.png" preload="false" />
+ <texture name="Inv_FolderClosed" file_name="icons/Inv_FolderClosed.png" preload="false" />
+ <texture name="Inv_FolderOpen" file_name="icons/Inv_FolderOpen.png" preload="false" />
+ <texture name="Inv_Gesture" file_name="icons/Inv_Gesture.png" preload="false" />
+ <texture name="Inv_Gloves" file_name="icons/Inv_Gloves.png" preload="false" />
+ <texture name="Inv_Hair" file_name="icons/Inv_Hair.png" preload="false" />
+ <texture name="Inv_LinkItem" file_name="icons/Inv_LinkItem.png" preload="false" />
+ <texture name="Inv_LinkItem_Broken" file_name="icons/Inv_LinkItem_Broken.png" preload="false" />
+ <texture name="Inv_LinkFolder" file_name="icons/Inv_LinkFolder.png" preload="false" />
+ <texture name="Inv_Jacket" file_name="icons/Inv_Jacket.png" preload="false" />
+ <texture name="Inv_LookFolderOpen" file_name="icons/Inv_LookFolderOpen.png" preload="false" />
+ <texture name="Inv_LookFolderClosed" file_name="icons/Inv_LookFolderClosed.png" preload="false" />
+ <texture name="Inv_Landmark" file_name="icons/Inv_Landmark.png" preload="false" />
+ <texture name="Inv_Notecard" file_name="icons/Inv_Notecard.png" preload="false" />
+ <texture name="Inv_Object" file_name="icons/Inv_Object.png" preload="false" />
+ <texture name="Inv_Pants" file_name="icons/Inv_Pants.png" preload="false" />
+ <texture name="Inv_Script" file_name="icons/Inv_Script.png" preload="false" />
+ <texture name="Inv_Shirt" file_name="icons/Inv_Shirt.png" preload="false" />
+ <texture name="Inv_Shoe" file_name="icons/Inv_Shoe.png" preload="false" />
+ <texture name="Inv_Skin" file_name="icons/Inv_Skin.png" preload="false" />
+ <texture name="Inv_Skirt" file_name="icons/Inv_Skirt.png" preload="false" />
+ <texture name="Inv_Snapshot" file_name="icons/Inv_Snapshot.png" preload="false" />
+ <texture name="Inv_Socks" file_name="icons/Inv_Socks.png" preload="false" />
+ <texture name="Inv_Sound" file_name="icons/Inv_Sound.png" preload="false" />
+ <texture name="Inv_Tattoo" file_name="icons/Inv_Tattoo.png" preload="false" />
+ <texture name="Inv_Texture" file_name="icons/Inv_Texture.png" preload="false" />
+ <texture name="Inv_Trash" file_name="icons/Inv_Trash.png" preload="false" />
+ <texture name="Inv_Underpants" file_name="icons/Inv_Underpants.png" preload="false" />
+ <texture name="Inv_Undershirt" file_name="icons/Inv_Undershirt.png" preload="false" />
+
+ <texture name="Linden_Dollar_Alert" file_name="widgets/Linden_Dollar_Alert.png"/>
+ <texture name="Linden_Dollar_Background" file_name="widgets/Linden_Dollar_Background.png"/>
+
+ <texture name="ListItem_Select" file_name="widgets/ListItem_Select.png" preload="true" />
+ <texture name="ListItem_Over" file_name="widgets/ListItem_Over.png" preload="true" />
+
+ <texture name="Lock" file_name="icons/Lock.png" preload="false" />
+ <texture name="Lock2" file_name="navbar/Lock.png" preload="false" />
+
+ <texture name="Login_Pod" file_name="windows/Login_Pod.png" preload="true" />
+
+ <texture name="Microphone_Mute" file_name="icons/Microphone_Mute.png" preload="false" />
+ <texture name="Microphone_On" file_name="icons/Microphone_On.png" preload="false" />
+
+ <texture name="MinusItem_Disabled" file_name="icons/MinusItem_Disabled.png" preload="false" />
+ <texture name="MinusItem_Off" file_name="icons/MinusItem_Off.png" preload="false" />
+ <texture name="MinusItem_Press" file_name="icons/MinusItem_Press.png" preload="false" />
+
+ <texture name="menu_separator" file_name="navbar/FileMenu_Divider.png" scale.left="4" scale.top="166" scale.right="0" scale.bottom="0" />
+
+ <texture name="Move_Fly_Disabled" file_name="bottomtray/Move_Fly_Disabled.png" preload="false" />
+ <texture name="Move_Fly_Off" file_name="bottomtray/Move_Fly_Off.png" preload="false" />
+ <texture name="Move_Fly_Over" file_name="bottomtray/Move_Fly_Over.png" preload="false" />
+ <texture name="Move_Fly_Press" file_name="bottomtray/Move_Fly_Press.png" preload="false" />
+ <texture name="Move_Run_Disabled" file_name="bottomtray/Move_Run_Disabled.png" preload="false" />
+ <texture name="Move_Run_Off" file_name="bottomtray/Move_Run_Off.png" preload="false" />
+ <texture name="Move_Run_Over" file_name="bottomtray/Move_Run_Over.png" preload="false" />
+ <texture name="Move_Run_Press" file_name="bottomtray/Move_Run_Press.png" preload="false" />
+ <texture name="Move_Walk_Disabled" file_name="bottomtray/Move_Walk_Disabled.png" preload="false" />
+ <texture name="Move_Walk_Off" file_name="bottomtray/Move_Walk_Off.png" preload="false" />
+ <texture name="Move_Walk_Over" file_name="bottomtray/Move_Walk_Over.png" preload="false" />
+ <texture name="Move_Walk_Press" file_name="bottomtray/Move_Walk_Press.png" preload="false" />
+ <texture name="Movement_Backward_Off" file_name="bottomtray/Movement_Backward_Off.png" preload="false" />
+ <texture name="Movement_Backward_On" file_name="bottomtray/Movement_Backward_On.png" preload="false" />
+ <texture name="Movement_Down_Off" file_name="bottomtray/Movement_Down_Off.png" preload="false" />
+ <texture name="Movement_Down_On" file_name="bottomtray/Movement_Down_On.png" preload="false" />
+ <texture name="Movement_Forward_Off" file_name="bottomtray/Movement_Forward_Off.png" preload="false" />
+ <texture name="Movement_Forward_On" file_name="bottomtray/Movement_Forward_On.png" preload="false" />
+ <texture name="Movement_TurnLeft_Off" file_name="bottomtray/Movement_TurnLeft_Off.png" preload="false" />
+ <texture name="Movement_TurnLeft_On" file_name="bottomtray/Movement_TurnLeft_On.png" preload="false" />
+ <texture name="Movement_TurnRight_Off" file_name="bottomtray/Movement_TurnRight_Off.png" preload="false" />
+ <texture name="Movement_TurnRight_On" file_name="bottomtray/Movement_TurnRight_On.png" preload="false" />
+ <texture name="Movement_Up_Off" file_name="bottomtray/Movement_Up_Off.png" preload="false" />
+ <texture name="Movement_Up_On" file_name="bottomtray/Movement_Up_On.png" preload="false" />
+
+ <texture name="NavBar_BG_NoFav" file_name="navbar/NavBar_BG_NoFav.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" />
+ <texture name="NavBar_BG" file_name="navbar/NavBar_BG.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" />
+
+ <texture name="NearbyVoice_Lvl1" file_name="bottomtray/NearbyVoice_Lvl1.png" preload="false" />
+ <texture name="NearbyVoice_Lvl2" file_name="bottomtray/NearbyVoice_Lvl2.png" preload="false" />
+ <texture name="NearbyVoice_Lvl3" file_name="bottomtray/NearbyVoice_Lvl3.png" preload="false" />
+ <texture name="NearbyVoice_On" file_name="bottomtray/NearbyVoice_On.png" preload="false" />
+
+ <texture name="Notices_Unread" file_name="bottomtray/Notices_Unread.png" preload="true" />
+
+ <texture name="NoEntryLines" file_name="world/NoEntryLines.png" use_mips="true" preload="false" />
+ <texture name="NoEntryPassLines" file_name="world/NoEntryPassLines.png" use_mips="true" preload="false" />
+
+ <texture name="Object_Cone" file_name="build/Object_Cone.png" preload="false" />
+ <texture name="Object_Cube" file_name="build/Object_Cube.png" preload="false" />
+ <texture name="Object_Cylinder" file_name="build/Object_Cylinder.png" preload="false" />
+ <texture name="Object_Grass" file_name="build/Object_Grass.png" preload="false" />
+ <texture name="Object_Hemi_Cone" file_name="build/Object_Hemi_Cone.png" preload="false" />
+ <texture name="Object_Hemi_Cylinder" file_name="build/Object_Hemi_Cylinder.png" preload="false" />
+ <texture name="Object_Hemi_Sphere" file_name="build/Object_Hemi_Sphere.png" preload="false" />
+ <texture name="Object_Prism" file_name="build/Object_Prism.png" preload="false" />
+ <texture name="Object_Pyramid" file_name="build/Object_Pyramid.png" preload="false" />
+ <texture name="Object_Ring" file_name="build/Object_Ring.png" preload="false" />
+ <texture name="Object_Sphere" file_name="build/Object_Sphere.png" preload="false" />
+ <texture name="Object_Tetrahedron" file_name="build/Object_Tetrahedron.png" preload="false" />
+ <texture name="Object_Torus" file_name="build/Object_Torus.png" preload="false" />
+ <texture name="Object_Tree" file_name="build/Object_Tree.png" preload="false" />
+ <texture name="Object_Tube" file_name="build/Object_Tube.png" preload="false" />
+
+ <texture name="OptionsMenu_Disabled" file_name="icons/OptionsMenu_Disabled.png" preload="false" />
+ <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="Overhead_Arrow_L" file_name="world/Overhead_Arrow_L.png" preload="false" />
+ <texture name="Overhead_Arrow_M" file_name="world/Overhead_Arrow_M.png" preload="false" />
+ <texture name="Overhead_Arrow_S" file_name="world/Overhead_Arrow_S.png" preload="false" />
+ <texture name="Overhead_L" file_name="world/Overhead_L.png" preload="false" />
+ <texture name="Overhead_M" file_name="world/Overhead_M.png" preload="false" />
+ <texture name="Overhead_S" file_name="world/Overhead_S.png" preload="false" />
+
+ <texture name="Parcel_Evry_Color" file_name="icons/Parcel_Evry_Color.png" preload="false" />
+ <texture name="Parcel_Exp_Color" file_name="icons/Parcel_Exp_Color.png" preload="false" />
+ <texture name="Parcel_M_Color" file_name="icons/Parcel_M_Color.png" preload="false" />
+
+ <texture name="Parcel_Build_Dark" file_name="icons/Parcel_Build_Dark.png" preload="false" />
+ <texture name="Parcel_BuildNo_Dark" file_name="icons/Parcel_BuildNo_Dark.png" preload="false" />
+ <texture name="Parcel_Damage_Dark" file_name="icons/Parcel_Health_Dark.png" preload="false" />
+ <texture name="Parcel_DamageNo_Dark" file_name="icons/Parcel_DamageNo_Dark.png" preload="false" />
+ <texture name="Parcel_Evry_Dark" file_name="icons/Parcel_Evry_Dark.png" preload="false" />
+ <texture name="Parcel_Exp_Dark" file_name="icons/Parcel_Exp_Dark.png" preload="false" />
+ <texture name="Parcel_Fly_Dark" file_name="icons/Parcel_Fly_Dark.png" preload="false" />
+ <texture name="Parcel_FlyNo_Dark" file_name="icons/Parcel_FlyNo_Dark.png" preload="false" />
+ <texture name="Parcel_ForSale_Dark" file_name="icons/Parcel_ForSale_Dark.png" preload="false" />
+ <texture name="Parcel_ForSaleNo_Dark" file_name="icons/Parcel_ForSaleNo_Dark.png" preload="false" />
+ <texture name="Parcel_M_Dark" file_name="icons/Parcel_M_Dark.png" preload="false" />
+ <texture name="Parcel_PG_Dark" file_name="icons/Parcel_PG_Dark.png" preload="false" />
+ <texture name="Parcel_Push_Dark" file_name="icons/Parcel_Push_Dark.png" preload="false" />
+ <texture name="Parcel_PushNo_Dark" file_name="icons/Parcel_PushNo_Dark.png" preload="false" />
+ <texture name="Parcel_R_Dark" file_name="icons/Parcel_R_Dark.png" preload="false" />
+ <texture name="Parcel_Scripts_Dark" file_name="icons/Parcel_Scripts_Dark.png" preload="false" />
+ <texture name="Parcel_ScriptsNo_Dark" file_name="icons/Parcel_ScriptsNo_Dark.png" preload="false" />
+ <texture name="Parcel_Voice_Dark" file_name="icons/Parcel_Voice_Dark.png" preload="false" />
+ <texture name="Parcel_VoiceNo_Dark" file_name="icons/Parcel_VoiceNo_Dark.png" preload="false" />
+
+ <texture name="Parcel_Build_Light" file_name="icons/Parcel_Build_Light.png" preload="false" />
+ <texture name="Parcel_BuildNo_Light" file_name="icons/Parcel_BuildNo_Light.png" preload="false" />
+ <texture name="Parcel_Damage_Light" file_name="icons/Parcel_Damage_Light.png" preload="false" />
+ <texture name="Parcel_DamageNo_Light" file_name="icons/Parcel_DamageNo_Light.png" preload="false" />
+ <texture name="Parcel_Evry_Light" file_name="icons/Parcel_Evry_Light.png" preload="false" />
+ <texture name="Parcel_Exp_Light" file_name="icons/Parcel_Exp_Light.png" preload="false" />
+ <texture name="Parcel_Fly_Light" file_name="icons/Parcel_Fly_Light.png" preload="false" />
+ <texture name="Parcel_FlyNo_Light" file_name="icons/Parcel_FlyNo_Light.png" preload="false" />
+ <texture name="Parcel_ForSale_Light" file_name="icons/Parcel_ForSale_Light.png" preload="false" />
+ <texture name="Parcel_ForSaleNo_Light" file_name="icons/Parcel_ForSaleNo_Light.png" preload="false" />
+ <texture name="Parcel_M_Light" file_name="icons/Parcel_M_Light.png" preload="false" />
+ <texture name="Parcel_PG_Light" file_name="icons/Parcel_PG_Light.png" preload="false" />
+ <texture name="Parcel_Push_Light" file_name="icons/Parcel_Push_Light.png" preload="false" />
+ <texture name="Parcel_PushNo_Light" file_name="icons/Parcel_PushNo_Light.png" preload="false" />
+ <texture name="Parcel_R_Light" file_name="icons/Parcel_R_Light.png" preload="false" />
+ <texture name="Parcel_Scripts_Light" file_name="icons/Parcel_Scripts_Light.png" preload="false" />
+ <texture name="Parcel_ScriptsNo_Light" file_name="icons/Parcel_ScriptsNo_Dark.png" preload="false" />
+ <texture name="Parcel_Voice_Light" file_name="icons/Parcel_Voice_Light.png" preload="false" />
+ <texture name="Parcel_VoiceNo_Light" file_name="icons/Parcel_VoiceNo_Light.png" preload="false" />
+
+ <texture name="Pause_Off" file_name="icons/Pause_Off.png" preload="false" />
+ <texture name="Pause_Over" file_name="icons/Pause_Over.png" preload="false" />
+ <texture name="Pause_Press" file_name="icons/Pause_Press.png" preload="false" />
+ <texture name="Play_Off" file_name="icons/Play_Off.png" preload="false" />
+ <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="Progress_1" file_name="icons/Progress_1.png" preload="false" />
+ <texture name="Progress_2" file_name="icons/Progress_2.png" preload="false" />
+ <texture name="Progress_3" file_name="icons/Progress_3.png" preload="false" />
+ <texture name="Progress_4" file_name="icons/Progress_4.png" preload="false" />
+ <texture name="Progress_5" file_name="icons/Progress_5.png" preload="false" />
+ <texture name="Progress_6" file_name="icons/Progress_6.png" preload="false" />
+ <texture name="Progress_7" file_name="icons/Progress_7.png" preload="false" />
+ <texture name="Progress_8" file_name="icons/Progress_8.png" preload="false" />
+ <texture name="Progress_9" file_name="icons/Progress_9.png" preload="false" />
+ <texture name="Progress_10" file_name="icons/Progress_10.png" preload="false" />
+ <texture name="Progress_11" file_name="icons/Progress_11.png" preload="false" />
+ <texture name="Progress_12" file_name="icons/Progress_12.png" preload="false" />
+
+ <texture name="ProgressBar" file_name="widgets/ProgressBar.png" preload="true" scale.left="4" scale.top="10" scale.right="48" scale.bottom="2" />
+ <texture name="ProgressTrack" file_name="widgets/ProgressTrack.png" preload="true" scale.left="4" scale.top="13" scale.right="148" scale.bottom="2" />
+
+ <texture name="PushButton_Disabled" file_name="widgets/PushButton_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_Off" file_name="widgets/PushButton_Off.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_On" file_name="widgets/PushButton_On.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_On_Selected" file_name="widgets/PushButton_On_Selected.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_On_Disabled" file_name="widgets/PushButton_On_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_Press" file_name="widgets/PushButton_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_Selected" file_name="widgets/PushButton_Selected.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_Selected_Press" file_name="widgets/PushButton_Selected_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="PushButton_Selected_Disabled" file_name="widgets/PushButton_Selected_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+
+ <texture name="RadioButton_Press" file_name="widgets/RadioButton_Press.png" preload="true" />
+ <texture name="RadioButton_On_Press" file_name="widgets/RadioButton_On_Press.png" preload="true" />
+ <texture name="RadioButton_Off" file_name="widgets/RadioButton_Off.png" preload="true" />
+ <texture name="RadioButton_On" file_name="widgets/RadioButton_On.png" preload="true" />
+ <texture name="RadioButton_Disabled" file_name="widgets/RadioButton_Disabled.png" preload="true" />
+ <texture name="RadioButton_On_Disabled" file_name="widgets/RadioButton_On_Disabled.png" preload="true" />
+
+ <texture name="Rec_Off" file_name="icons/Rec_Off.png" preload="false" />
+ <texture name="Rec_On" file_name="icons/Rec_On.png" preload="false" />
+
+ <texture name="Refresh_Disabled" file_name="icons/Refresh_Disabled.png" preload="false" />
+ <texture name="Refresh_Off" file_name="icons/Refresh_Off.png" preload="false" />
+ <texture name="Refresh_Press" file_name="icons/Refresh_Press.png" preload="false" />
+
+ <texture name="Resize_Corner" file_name="windows/Resize_Corner.png" preload="true" />
+
+ <texture name="Rounded_Square" file_name="rounded_square.j2c" preload="true" scale.left="16" scale.top="16" scale.right="112" scale.bottom="16" />
+ <texture name="Row_Selection" file_name="navbar/Row_Selection.png" preload="false" />
+
+ <texture name="ScrollArrow_Down" file_name="widgets/ScrollArrow_Down.png" preload="true" scale.left="2" scale.top="13" scale.right="13" scale.bottom="2" />
+ <texture name="ScrollArrow_Left" file_name="widgets/ScrollArrow_Left.png" preload="true" scale.left="2" scale.top="13" scale.right="13" scale.bottom="2" />
+ <texture name="ScrollArrow_Right" file_name="widgets/ScrollArrow_Right.png" preload="true" scale.left="2" scale.top="13" scale.right="13" scale.bottom="2" />
+ <texture name="ScrollArrow_Up" file_name="widgets/ScrollArrow_Up.png" preload="true" scale.left="2" scale.top="13" scale.right="13" scale.bottom="2" />
+
+ <texture name="ScrollThumb_Horiz" file_name="widgets/ScrollThumb_Horiz.png" preload="true" scale.left="4" scale.top="0" scale.bottom="0" scale.right="2" />
+ <texture name="ScrollThumb_Vert" file_name="widgets/ScrollThumb_Vert.png" preload="true" scale.left="4" scale.top="53" scale.bottom="10" scale.right="4" />
+ <texture name="ScrollTrack_Vert" file_name="widgets/ScrollTrack_Vert.png" preload="true" scale.left="2" scale.top="40" scale.bottom="13" scale.right="0" />
+ <texture name="ScrollTrack_Horiz" file_name="widgets/ScrollTrack_Horiz.png" preload="true" scale.left="4" scale.top="0" scale.bottom="0" scale.right="2" />
+
+ <texture name="ScrubberThumb_Disabled" file_name="widgets/ScrubberThumb_Disabled.png" preload="false" />
+ <texture name="ScrubberThumb_Focus" file_name="widgets/ScrubberThumb_Focus.png" preload="false" />
+ <texture name="ScrubberThumb_Off" file_name="widgets/ScrubberThumb_Off.png" preload="false" />
+ <texture name="ScrubberThumb_Over" file_name="widgets/ScrubberThumb_Over.png" preload="false" />
+ <texture name="ScrubberThumb_Press" file_name="widgets/ScrubberThumb_Press.png" preload="false" />
+
+ <texture name="Search" file_name="navbar/Search.png" preload="false" />
+
+ <texture name="SegmentedBtn_Left_Off" file_name="widgets/SegmentedBtn_Left_Off.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Left_Over" file_name="widgets/SegmentedBtn_Left_Over.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Left_Press" file_name="widgets/SegmentedBtn_Left_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Left_Disabled" file_name="widgets/SegmentedBtn_Left_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Left_Selected" file_name="widgets/SegmentedBtn_Left_Selected.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Left_Selected_Over" file_name="widgets/SegmentedBtn_Left_Selected_Over.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Left_Selected_Press" file_name="widgets/SegmentedBtn_Left_Selected_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Left_Selected_Disabled" file_name="widgets/SegmentedBtn_Left_Selected_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+
+ <texture name="SegmentedBtn_Middle_Off" file_name="widgets/SegmentedBtn_Middle_Off.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Middle_Press" file_name="widgets/SegmentedBtn_Middle_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Middle_Disabled" file_name="widgets/SegmentedBtn_Middle_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Middle_Selected" file_name="widgets/SegmentedBtn_Middle_Selected.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Middle_Selected_Press" file_name="widgets/SegmentedBtn_Middle_Selected_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Middle_Selected_Disabled" file_name="widgets/SegmentedBtn_Middle_Selected_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+
+ <texture name="SegmentedBtn_Right_Off" file_name="widgets/SegmentedBtn_Right_Off.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Right_Over" file_name="widgets/SegmentedBtn_Right_Over.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Right_Press" file_name="widgets/SegmentedBtn_Right_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Right_Disabled" file_name="widgets/SegmentedBtn_Right_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Right_Selected" file_name="widgets/SegmentedBtn_Right_Selected.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Right_Selected_Press" file_name="widgets/SegmentedBtn_Right_Selected_Press.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="SegmentedBtn_Right_Selected_Disabled" file_name="widgets/SegmentedBtn_Right_Selected_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+
+ <texture name="SkipBackward_Off" file_name="icons/SkipBackward_Off.png" preload="false" />
+ <texture name="SkipBackward_Over" file_name="icons/SkipBackward_Over.png" preload="false" />
+ <texture name="SkipBackward_Press" file_name="icons/SkipBackward_Press.png" preload="false" />
+ <texture name="SkipForward_Off" file_name="icons/SkipForward_Off.png" preload="false" />
+ <texture name="SkipForward_Over" file_name="icons/SkipForward_Over.png" preload="false" />
+ <texture name="SkipForward_Press" file_name="icons/SkipForward_Press.png" preload="false" />
+
+ <texture name="SliderTrack_Horiz" file_name="widgets/SliderTrack_Horiz.png" scale.left="4" scale.top="4" scale.right="100" scale.bottom="2" />
+ <texture name="SliderTrack_Vert" file_name="widgets/SliderTrack_Vert.png" scale.left="2" scale.top="100" scale.right="4" scale.bottom="4" />
+ <texture name="SliderThumb_Off" file_name="widgets/SliderThumb_Off.png" />
+ <texture name="SliderThumb_Disabled" file_name="widgets/SliderThumb_Disabled.png" />
+ <texture name="SliderThumb_Press" file_name="widgets/SliderThumb_Press.png" />
+
+ <texture name="SL_Logo" file_name="icons/SL_Logo.png" preload="true" />
+
+ <texture name="Snapshot_Off" file_name="bottomtray/Snapshot_Off.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" />
+ <texture name="Snapshot_Over" file_name="bottomtray/Snapshot_Over.png" preload="false" />
+ <texture name="Snapshot_Press" file_name="bottomtray/Snapshot_Press.png" preload="false" />
+
+ <texture name="startup_logo" file_name="windows/startup_logo.png" preload="true" />
+
+ <texture name="Stepper_Down_Disabled" file_name="widgets/Stepper_Down_Disabled.png" preload="false" />
+ <texture name="Stepper_Down_Off" file_name="widgets/Stepper_Down_Off.png" preload="false" />
+ <texture name="Stepper_Down_Press" file_name="widgets/Stepper_Down_Press.png" preload="false" />
+ <texture name="Stepper_Up_Disabled" file_name="widgets/Stepper_Up_Disabled.png" preload="false" />
+ <texture name="Stepper_Up_Off" file_name="widgets/Stepper_Up_Off.png" preload="false" />
+ <texture name="Stepper_Up_Press" file_name="widgets/Stepper_Up_Press.png" preload="false" />
+
+ <texture name="Stop_Off" file_name="icons/Stop_Off.png" preload="false" />
+ <texture name="Stop_Over" file_name="icons/Stop_Over.png" preload="false" />
+ <texture name="Stop_Press" file_name="icons/Stop_Press.png" preload="false" />
+ <texture name="StopReload_Off" file_name="icons/StopReload_Off.png" preload="false" />
+ <texture name="StopReload_Over" file_name="icons/StopReload_Over.png" preload="false" />
+ <texture name="StopReload_Press" file_name="icons/StopReload_Press.png" preload="false" />
+
+ <texture name="TabIcon_Appearance_Large" file_name="taskpanel/TabIcon_Appearance_Large.png" preload="false" />
+ <texture name="TabIcon_Appearance_Off" file_name="taskpanel/TabIcon_Appearance_Off.png" preload="false" />
+ <texture name="TabIcon_Appearance_Over" file_name="taskpanel/TabIcon_Appearance_Over.png" preload="false" />
+ <texture name="TabIcon_Appearance_Selected" file_name="taskpanel/TabIcon_Appearance_Selected.png" preload="false" />
+ <texture name="TabIcon_Close_Off" file_name="taskpanel/TabIcon_Close_Off.png" preload="false" />
+ <texture name="TabIcon_Close_Over" file_name="taskpanel/TabIcon_Close_Over.png" preload="false" />
+ <texture name="TabIcon_Inventory_Large" file_name="taskpanel/TabIcon_Inventory_Large.png" preload="false" />
+ <texture name="TabIcon_Inventory_Off" file_name="taskpanel/TabIcon_Inventory_Off.png" preload="false" />
+ <texture name="TabIcon_Inventory_Over" file_name="taskpanel/TabIcon_Inventory_Over.png" preload="false" />
+ <texture name="TabIcon_Inventory_Selected" file_name="taskpanel/TabIcon_Inventory_Selected.png" preload="false" />
+ <texture name="TabIcon_Home_Large" file_name="taskpanel/TabIcon_Home_Large.png" preload="false" />
+ <texture name="TabIcon_Home_Off" file_name="taskpanel/TabIcon_Home_Off.png" preload="false" />
+ <texture name="TabIcon_Home_Over" file_name="taskpanel/TabIcon_Home_Over.png" preload="false" />
+ <texture name="TabIcon_Home_Selected" file_name="taskpanel/TabIcon_Home_Selected.png" preload="false" />
+ <texture name="TabIcon_Me_Large" file_name="taskpanel/TabIcon_Me_Large.png" preload="false" />
+ <texture name="TabIcon_Me_Off" file_name="taskpanel/TabIcon_Me_Off.png" preload="false" />
+ <texture name="TabIcon_Me_Over" file_name="taskpanel/TabIcon_Me_Over.png" preload="false" />
+ <texture name="TabIcon_Me_Selected" file_name="taskpanel/TabIcon_Me_Selected.png" preload="false" />
+ <texture name="TabIcon_Open_Off" file_name="taskpanel/TabIcon_Open_Off.png" preload="false" />
+ <texture name="TabIcon_Open_Over" file_name="taskpanel/TabIcon_Open_Over.png" preload="false" />
+ <texture name="TabIcon_People_Large" file_name="taskpanel/TabIcon_People_Large.png" preload="false" />
+ <texture name="TabIcon_People_Off" file_name="taskpanel/TabIcon_People_Off.png" preload="false" />
+ <texture name="TabIcon_People_Over" file_name="taskpanel/TabIcon_People_Over.png" preload="false" />
+ <texture name="TabIcon_People_Selected" file_name="taskpanel/TabIcon_People_Selected.png" preload="false" />
+ <texture name="TabIcon_Places_Large" file_name="taskpanel/TabIcon_Places_Large.png" preload="false" />
+ <texture name="TabIcon_Places_Off" file_name="taskpanel/TabIcon_Places_Off.png" preload="false" />
+ <texture name="TabIcon_Places_Over" file_name="taskpanel/TabIcon_Places_Over.png" preload="false" />
+ <texture name="TabIcon_Places_Selected" file_name="taskpanel/TabIcon_Places_Selected.png" preload="false" />
+ <texture name="TabIcon_Things_Large" file_name="taskpanel/TabIcon_Things_Large.png" preload="false" />
+ <texture name="TabIcon_Things_Off" file_name="taskpanel/TabIcon_Things_Off.png" preload="false" />
+ <texture name="TabIcon_Things_Over" file_name="taskpanel/TabIcon_Things_Over.png" preload="false" />
+ <texture name="TabIcon_Things_Selected" file_name="taskpanel/TabIcon_Things_Selected.png" preload="false" />
+
+ <texture name="TabTop_Divider" file_name="containers/TabTop_Divider.png" preload="false" />
+ <texture name="TabTop_Left_Press" file_name="containers/TabTop_Left_Press.png" preload="false" />
+ <texture name="TabTop_Middle_Press" file_name="containers/TabTop_Middle_Press.png" preload="false" />
+ <texture name="TabTop_Right_Off" file_name="containers/TabTop_Right_Off.png" preload="false" scale.left="8" scale.top="8" scale.right="62" scale.bottom="9" />
+ <texture name="TabTop_Right_Press" file_name="containers/TabTop_Right_Press.png" preload="false" />
+ <texture name="TabTop_Right_Selected" file_name="containers/TabTop_Right_Selected.png" preload="false" scale.left="8" scale.top="8" scale.right="62" scale.bottom="9" />
+ <texture name="TabTop_Middle_Off" file_name="containers/TabTop_Middle_Off.png" preload="false" scale.left="8" scale.top="8" scale.right="120" scale.bottom="9" />
+ <texture name="TabTop_Middle_Selected" file_name="containers/TabTop_Middle_Selected.png" preload="false" scale.left="8" scale.top="8" scale.right="96" scale.bottom="9" />
+ <texture name="TabTop_Left_Off" file_name="containers/TabTop_Left_Off.png" preload="false" scale.left="8" scale.top="8" scale.right="120" scale.bottom="9" />
+ <texture name="TabTop_Left_Selected" file_name="containers/TabTop_Left_Selected.png" preload="false" scale.left="8" scale.top="8" scale.right="96" scale.bottom="9" />
+
+ <texture name="TaskPanel_Tab_Off" file_name="taskpanel/TaskPanel_Tab_Off.png" preload="false" scale.left="4" scale.top="29" scale.right="36" scale.bottom="4" />
+ <texture name="TaskPanel_Tab_Selected" file_name="taskpanel/TaskPanel_Tab_Selected.png" preload="false" scale.left="5" scale.top="30" scale.right="36" scale.bottom="5" />
+ <texture name="TaskPanel_BG" file_name="taskpanel/TaskPanel_BG.png" preload="false" scale.left="4" scale.top="146" scale.right="146" scale.bottom="4" />
+ <texture name="TaskPanel_Tab_Unselected" file_name="taskpanel/TaskPanel_Tab_Over.png" preload="false" scale.left="5" scale.top="30" scale.right="36" scale.bottom="5" />
+
+ <texture name="TextField_Search_Disabled" file_name="widgets/TextField_Search_Disabled.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="TextField_Off" file_name="widgets/TextField_Off.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="TextField_Search_Active" file_name="widgets/TextField_Search_Active.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="TextField_Search_Off" file_name="widgets/TextField_Search_Off.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="TextField_Disabled" file_name="widgets/TextField_Disabled.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="TextField_Active" file_name="widgets/TextField_Active.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+
+ <texture name="TimeBasedMediaBackground" file_name="windows/TimeBasedMediaBackground.png" preload="false" />
+
+ <texture name="Toast_CloseBtn" file_name="windows/Toast_CloseBtn.png" preload="true" />
+ <texture name="Toast_Background" file_name="windows/Toast_Background.png" preload="true"
+ scale.left="4" scale.top="28" scale.right="60" scale.bottom="4" />
+ <texture name="Toast_Over" file_name="windows/Toast_Over.png" preload="true"
+ scale.left="4" scale.top="28" scale.right="60" scale.bottom="4" />
+
+ <texture name="Tool_Create" file_name="build/Tool_Create.png" preload="false" />
+ <texture name="Tool_Dozer" file_name="build/Tool_Dozer.png" preload="false" />
+ <texture name="Tool_Face" file_name="build/Tool_Face.png" preload="false" />
+ <texture name="Tool_Grab" file_name="build/Tool_Grab.png" preload="false" />
+ <texture name="Tool_Zoom" file_name="build/Tool_Zoom.png" preload="false" />
+
+ <texture name="Toolbar_Divider" file_name="containers/Toolbar_Divider.png" preload="false" />
+ <texture name="Toolbar_Left_Off" file_name="containers/Toolbar_Left_Off.png" preload="false" scale.left="5" scale.bottom="4" scale.top="24" scale.right="30" />
+ <texture name="Toolbar_Left_Press" file_name="containers/Toolbar_Left_Press.png" preload="false" scale.left="5" scale.bottom="4" scale.top="24" scale.right="30" />
+ <texture name="Toolbar_Left_Selected" file_name="containers/Toolbar_Left_Selected.png" preload="false" scale.left="5" scale.bottom="4" scale.top="24" scale.right="30" />
+ <texture name="Toolbar_Middle_Off" file_name="containers/Toolbar_Middle_Off.png" preload="false" scale.left="1" scale.bottom="2" scale.top="24" scale.right="30" />
+ <texture name="Toolbar_Middle_Press" file_name="containers/Toolbar_Middle_Press.png" preload="false" scale.left="1" scale.bottom="2" scale.top="24" scale.right="30" />
+ <texture name="Toolbar_Middle_Selected" file_name="containers/Toolbar_Middle_Selected.png" preload="false" scale.left="1" scale.bottom="2" scale.top="24" scale.right="30" />
+ <texture name="Toolbar_Right_Off" file_name="containers/Toolbar_Right_Off.png" preload="false" scale.left="1" scale.bottom="4" scale.top="24" scale.right="26" />
+ <texture name="Toolbar_Right_Press" file_name="containers/Toolbar_Right_Press.png" preload="false" scale.left="1" scale.bottom="4" scale.top="24" scale.right="26" />
+ <texture name="Toolbar_Right_Selected" file_name="containers/Toolbar_Right_Selected.png" preload="false" scale.left="1" scale.bottom="4" scale.top="24" scale.right="26" />
+
+ <texture name="Tooltip" file_name="widgets/Tooltip.png" preload="true" scale.left="2" scale.top="16" scale.right="100" scale.bottom="3" />
+
+ <texture name="TrashItem_Disabled" file_name="icons/TrashItem_Disabled.png" preload="false" />
+ <texture name="TrashItem_Off" file_name="icons/TrashItem_Off.png" preload="false" />
+ <texture name="TrashItem_Press" file_name="icons/TrashItem_Press.png" preload="false" />
+
+ <texture name="Unread_Chiclet" file_name="bottomtray/Unread_Chiclet.png" preload="false" />
+ <texture name="Unread_Msg" file_name="bottomtray/Unread_Msg.png" preload="false" />
+ <texture name="Unread_IM" file_name="bottomtray/Unread_IM.png" preload="false" />
+
+ <texture name="WellButton_Lit" file_name="bottomtray/WellButton_Lit.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+ <texture name="WellButton_Lit_Selected" file_name="bottomtray/WellButton_Lit_Selected.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
+
+ <texture name="VoicePTT_Lvl1" file_name="bottomtray/VoicePTT_Lvl1.png" preload="false" />
+ <texture name="VoicePTT_Lvl2" file_name="bottomtray/VoicePTT_Lvl2.png" preload="false" />
+ <texture name="VoicePTT_Lvl3" file_name="bottomtray/VoicePTT_Lvl3.png" preload="false" />
+ <texture name="VoicePTT_Off" file_name="bottomtray/VoicePTT_Off.png" preload="false" />
+ <texture name="VoicePTT_On" file_name="bottomtray/VoicePTT_On.png" preload="false" />
+
+ <texture name="WebBasedMediaBackground" file_name="windows/WebBasedMediaBackground.png" preload="false" />
+
+ <texture name="Widget_DownArrow" file_name="icons/Widget_DownArrow.png" preload="true" />
+ <texture name="Widget_UpArrow" file_name="icons/Widget_UpArrow.png" preload="true" />
+
+ <texture name="Window_Background" file_name="windows/Window_Background.png" preload="true"
+ scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" />
+ <texture name="Window_Foreground" file_name="windows/Window_Foreground.png" preload="true"
+ scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" />
+ <texture name="Window_NoTitle_Background" file_name="windows/Window_NoTitle_Background.png" preload="true"
+ scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" />
+ <texture name="Window_NoTitle_Foreground" file_name="windows/Window_NoTitle_Foreground.png" preload="true"
+ scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" />
+
+ <texture name="YouAreHere_Badge" file_name="icons/YouAreHere_Badge.png" preload="false" />
+
+ <texture name="Zoom_Off" file_name="icons/Zoom_Off.png" preload="false" />
+ <texture name="Zoom_Over" file_name="icons/Zoom_Over.png" preload="false" />
+ <texture name="Zoom_Press" file_name="icons/Zoom_Press.png" preload="false" />
+ <texture name="UnZoom_Off" file_name="icons/UnZoom_Off.png" preload="false" />
+ <texture name="UnZoom_Over" file_name="icons/UnZoom_Over.png" preload="false" />
+ <texture name="UnZoom_Press" file_name="icons/UnZoom_Press.png" preload="false" />
+ <texture name="PowerOn_Off" file_name="icons/PowerOn_Off.png" preload="false" />
+ <texture name="PowerOn_Over" file_name="icons/PowerOn_Over.png" preload="false" />
+ <texture name="PowerOn_Press" file_name="icons/PowerOn_Press.png" preload="false" />
+ <texture name="PowerOff_Off" file_name="icons/PowerOff_Off.png" preload="false" />
+ <texture name="PowerOff_Over" file_name="icons/PowerOff_Over.png" preload="false" />
+ <texture name="PowerOff_Press" file_name="icons/PowerOff_Press.png" preload="false" />
+
+ <texture name="pixiesmall.j2c" use_mips="true" />
+ <texture name="script_error.j2c" use_mips="true" />
+ <texture name="silhouette.j2c" use_mips="true" />
+ <texture name="foot_shadow.j2c" use_mips="true" />
+ <texture name="cloud-particle.j2c" use_mips="true" />
+
+ <!--WARNING OLD ART BELOW *do not use*-->
+ <texture name="icn_chatbar.tga" />
+ <texture name="icn_media_web.tga" preload="true" />
+ <texture name="icn_media_movie.tga" preload="true" />
+ <texture name="icn_speaker-muted_dark.tga" />
+ <texture name="icn_speaker_dark.tga" />
+ <texture name="icn_voice-localchat.tga" />
+ <texture name="icn_voice-groupfocus.tga" />
+ <texture name="icn_voice-pvtfocus.tga" />
+
+ <texture name="jump_left_out.tga" file_name="widgets/jump_left_out.png" />
+ <texture name="jump_left_in.tga" file_name="widgets/jump_left_in.png" />
+ <texture name="jump_right_out.tga" file_name="widgets/jump_right_out.png" />
+ <texture name="jump_right_in.tga" file_name="widgets/jump_right_in.png" />
+
+ <texture name="scrollbutton_left_out_blue.tga" file_name="widgets/ScrollArrow_Left_Opaque.png" />
+ <texture name="scrollbutton_left_in_blue.tga" file_name="widgets/ScrollArrow_Left_Over_Opaque.png" />
+ <texture name="scrollbutton_right_out_blue.tga" file_name="widgets/ScrollArrow_Right_Opaque.png" />
+ <texture name="scrollbutton_right_in_blue.tga" file_name="widgets/ScrollArrow_Right_Over_Opaque.png" />
+
+ <texture name="up_arrow.tga" file_name="up_arrow.png" />
+ <texture name="down_arrow.tga" file_name="down_arrow.png" />
+ <texture name="arrow_down.tga" />
+
+ <texture name="tearoffbox.tga" />
+ <texture name="tearoff_pressed.tga" />
+
+ <texture name="icn_label_music.tga" />
+ <texture name="icn_label_media.tga" />
+ <texture name="icn_rounded-text-field.tga" scale.left="14" scale.bottom="16" scale.top="16" scale.right="114" />
+
+ <texture name="toggle_button_off" file_name="toggle_button_off.png" preload="true" />
+ <texture name="toggle_button_selected" file_name="toggle_button_selected.png" preload="true" />
+ <texture name="color_swatch_alpha.tga" preload="true" />
+
+ <texture name="button_anim_pause.tga" />
+ <texture name="button_anim_pause_selected.tga" />
+ <texture name="button_anim_play.tga" />
+ <texture name="button_anim_play_selected.tga" />
+ <texture name="crosshairs.tga" />
+ <texture name="direction_arrow.tga" file_name="world/BeaconArrow.png" />
+
+ <texture name="icon_auction.tga" />
+ <texture name="icon_avatar_offline.tga" />
+ <texture name="icon_avatar_online.tga" />
+ <texture name="icon_day_cycle.tga" />
+ <texture name="icon_diurnal.tga" />
+ <texture name="icon_event.tga" />
+ <texture name="icon_event_mature.tga" />
+ <texture name="icon_for_sale.tga" />
+ <texture name="icon_place_for_sale.tga" />
+ <texture name="icon_top_pick.tga" />
+
+ <texture name="lag_status_critical.tga" />
+ <texture name="lag_status_good.tga" />
+ <texture name="lag_status_warning.tga" />
+
+ <texture name="legend.tga" />
+
+ <texture name="map_avatar_16.tga" />
+ <texture name="map_avatar_8.tga" />
+ <texture name="map_avatar_you_8.tga" />
+ <texture name="map_event.tga" />
+ <texture name="map_event_mature.tga" />
+ <texture name="map_home.tga" />
+ <texture name="map_infohub.tga" />
+ <texture name="map_telehub.tga" />
+ <texture name="map_track_16.tga" />
+
+ <texture name="notify_caution_icon.tga" />
+ <texture name="notify_next.png" preload="true" />
+ <texture name="notify_box_icon.tga" />
+
+ <texture name="icn_active-speakers-dot-lvl0.tga" />
+ <texture name="icn_active-speakers-dot-lvl1.tga" />
+ <texture name="icn_active-speakers-dot-lvl2.tga" />
+ <texture name="icn_active-speakers-typing1.tga" />
+ <texture name="icn_active-speakers-typing2.tga" />
+ <texture name="icn_active-speakers-typing3.tga" />
+
+ <texture name="icn_voice_ptt-off.tga" />
+ <texture name="icn_voice_ptt-on.tga" />
+ <texture name="icn_voice_ptt-on-lvl1.tga" />
+ <texture name="icn_voice_ptt-on-lvl2.tga" />
+ <texture name="icn_voice_ptt-on-lvl3.tga" />
+ <texture name="icn_voice-call-end.tga" />
+ <texture name="icn_voice-call-start.tga" />
+
+ <texture name="mute_icon.tga" />
+
+ <texture name="default_land_picture.j2c" />
+ <texture name="default_profile_picture.j2c" />
+ <texture name="locked_image.j2c" />
- <texture name="icn_scrollbar_thumb.tga" preload="true" scale_top="7" scale_left="4" scale_bottom="8" scale_right="4" />
- <texture name="icn_scrollbar_bg.tga" preload="true" scale_top="7" scale_left="4" scale_bottom="8" scale_right="4" />
- <texture name="sm_rounded_corners_simple.tga" scale_left="4" scale_top="4" scale_bottom="4" scale_right="4"/>
- <texture name="icn_textfield_enabled.tga" scale_left="5" scale_top="5" scale_bottom="5" scale_right="5"/>
-
- <texture name="button_disabled_32x128.tga" preload="true" scale_left="16" scale_top="16" scale_right="112" scale_bottom="16" />
-
- <texture name="button_enabled_32x128.tga" preload="true" scale_left="16" scale_top="16" scale_right="112" scale_bottom="16" />
-
- <texture name="toolbar_btn_enabled.tga" scale_left="7" scale_top="32" scale_right="121" scale_bottom="0" />
-
- <texture name="toolbar_btn_disabled.tga" scale_left="7" scale_top="32" scale_right="121" scale_bottom="0" />
-
- <texture name="toolbar_btn_selected.tga" scale_left="7" scale_top="32" scale_right="121" scale_bottom="0" />
-
- <texture name="button_enabled_selected_32x128.tga" preload="true" scale_left="16" scale_top="16" scale_right="112" scale_bottom="16" />
-
- <texture name="checkbox_disabled_false.tga" preload="true"/>
- <texture name="checkbox_disabled_true.tga" preload="true"/>
- <texture name="checkbox_enabled_false.tga" preload="true"/>
- <texture name="checkbox_enabled_true.tga" preload="true"/>
-
- <texture name="close_in_blue.tga" preload="true"/>
-
- <texture name="minimize.tga" preload="true"/>
- <texture name="minimize_pressed.tga" preload="true"/>
-
- <texture name="radio_active_false.tga" preload="true"/>
- <texture name="radio_active_true.tga" preload="true"/>
- <texture name="radio_inactive_false.tga" preload="true"/>
- <texture name="radio_inactive_true.tga" preload="true"/>
-
- <texture name="combobox_arrow.tga" preload="true"/>
-
- <texture name="resize_handle_bottom_right_blue.tga" preload="true"/>
-
- <texture name="rounded_square.tga" file_name="rounded_square.j2c" preload="true" scale_left="16" scale_top="16" scale_right="112" scale_bottom="16"/>
-
- <texture name="rounded_square_soft.tga" file_name="rounded_square_soft.j2c" preload="true" scale_left="16" scale_top="16" scale_right="112" scale_bottom="16"/>
-
- <texture name="toolbar_tab.tga" preload="true" scale_left="6" scale_top="42" scale_right="104" scale_bottom="8"/>
- <texture name="toolbar_bg.tga" preload="true" scale_left="6" scale_top="42" scale_right="96" scale_bottom="16"/>
-
- <texture name="progressbar_fill.tga" preload="true" scale_left="10" scale_top="7" scale_right="65" scale_bottom="7"/>
- <texture name="progressbar_track.tga" preload="true" scale_left="10" scale_top="7" scale_right="80" scale_bottom="7"/>
-
- <texture name="scrollbutton_down_in_blue.tga" preload="true"/>
- <texture name="scrollbutton_down_out_blue.tga" preload="true"/>
- <texture name="scrollbutton_left_in_blue.tga" preload="true"/>
- <texture name="scrollbutton_left_out_blue.tga" preload="true"/>
- <texture name="scrollbutton_right_in_blue.tga" preload="true"/>
- <texture name="scrollbutton_right_out_blue.tga" preload="true"/>
- <texture name="scrollbutton_up_in_blue.tga" preload="true"/>
- <texture name="scrollbutton_up_out_blue.tga" preload="true"/>
- <texture name="spin_down_in_blue.tga" preload="true"/>
- <texture name="spin_down_out_blue.tga" preload="true"/>
- <texture name="spin_up_in_blue.tga" preload="true"/>
- <texture name="spin_up_out_blue.tga" preload="true"/>
-
- <texture name="square_btn_32x128.tga" preload="true" scale_left="8" scale_top="10" scale_right="120" scale_bottom="10"/>
- <texture name="square_btn_selected_32x128.tga" preload="true" scale_left="2" scale_top="10" scale_right="126" scale_bottom="10"/>
-
- <texture name="tab_bottom_blue.tga" preload="true" scale_left="8" scale_top="8" scale_right="120" scale_bottom="9"/>
- <texture name="tab_bottom_selected_blue.tga" preload="true" scale_left="8" scale_top="8" scale_right="96" scale_bottom="9"/>
- <texture name="tab_left.tga" preload="true" scale_left="8" scale_top="8" scale_right="120" scale_bottom="9"/>
- <texture name="tab_left_selected.tga" preload="true" scale_left="8" scale_top="8" scale_right="96" scale_bottom="9"/>
- <texture name="tab_top_blue.tga" preload="true" scale_left="8" scale_top="8" scale_right="120" scale_bottom="9"/>
- <texture name="tab_top_selected_blue.tga" preload="true" scale_left="8" scale_top="8" scale_right="96" scale_bottom="9"/>
-
- <texture name="startup_logo.j2c" preload="true"/>
- <texture name="color_swatch_alpha.tga" preload="true"/>
-
- <texture name="active_voice_tab.tga"/>
- <texture name="button_anim_pause.tga"/>
- <texture name="button_anim_pause_selected.tga"/>
- <texture name="button_anim_play.tga"/>
- <texture name="button_anim_play_selected.tga"/>
- <texture name="button_anim_stop.tga"/>
- <texture name="button_anim_stop_selected.tga"/>
- <texture name="crosshairs.tga"/>
- <texture name="direction_arrow.tga"/>
- <texture name="foot_shadow.j2c" use_mips="true"/>
-
- <texture name="icon_auction.tga"/>
- <texture name="icon_avatar_offline.tga"/>
- <texture name="icon_avatar_online.tga"/>
- <texture name="icon_day_cycle.tga"/>
- <texture name="icon_diurnal.tga"/>
- <texture name="icon_event.tga"/>
- <texture name="icon_event_mature.tga"/>
- <texture name="icon_for_sale.tga"/>
- <texture name="icon_group.tga"/>
- <texture name="icon_groupnotice.tga"/>
- <texture name="icon_groupnoticeinventory.tga"/>
- <texture name="icon_lock.tga"/>
- <texture name="icon_place.tga"/>
- <texture name="icon_popular.tga"/>
- <texture name="icon_top_pick.tga"/>
-
- <texture name="inv_folder_animation.tga"/>
- <texture name="inv_folder_bodypart.tga"/>
- <texture name="inv_folder_callingcard.tga"/>
- <texture name="inv_folder_clothing.tga"/>
- <texture name="inv_folder_gesture.tga"/>
- <texture name="inv_folder_landmark.tga"/>
- <texture name="inv_folder_lostandfound.tga"/>
- <texture name="inv_folder_notecard.tga"/>
- <texture name="inv_folder_object.tga"/>
- <texture name="inv_folder_plain_closed.tga"/>
- <texture name="inv_folder_script.tga"/>
- <texture name="inv_folder_snapshot.tga"/>
- <texture name="inv_folder_sound.tga"/>
- <texture name="inv_folder_texture.tga"/>
- <texture name="inv_folder_trash.tga"/>
-
- <texture name="inv_item_animation.tga"/>
- <texture name="inv_item_skin.tga"/>
- <texture name="inv_item_callingcard_offline.tga"/>
- <texture name="inv_item_callingcard_online.tga"/>
- <texture name="inv_item_eyes.tga"/>
- <texture name="inv_item_gesture.tga"/>
- <texture name="inv_item_gloves.tga"/>
- <texture name="inv_item_hair.tga"/>
- <texture name="inv_item_jacket.tga"/>
- <texture name="inv_item_landmark.tga"/>
- <texture name="inv_item_landmark_visited.tga"/>
- <texture name="inv_item_notecard.tga"/>
- <texture name="inv_item_object.tga"/>
- <texture name="inv_item_object_multi.tga"/>
- <texture name="inv_item_pants.tga"/>
- <texture name="inv_item_script.tga"/>
- <texture name="inv_item_shape.tga"/>
- <texture name="inv_item_shirt.tga"/>
- <texture name="inv_item_shoes.tga"/>
- <texture name="inv_item_skirt.tga"/>
- <texture name="inv_item_snapshot.tga"/>
- <texture name="inv_item_socks.tga"/>
- <texture name="inv_item_sound.tga"/>
- <texture name="inv_item_texture.tga"/>
- <texture name="inv_item_underpants.tga"/>
- <texture name="inv_item_undershirt.tga"/>
-
- <texture name="lag_status_critical.tga"/>
- <texture name="lag_status_good.tga"/>
- <texture name="lag_status_warning.tga"/>
-
- <texture name="legend.tga"/>
-
- <texture name="map_avatar_16.tga"/>
- <texture name="map_avatar_8.tga"/>
- <texture name="map_avatar_you_8.tga"/>
- <texture name="map_event.tga"/>
- <texture name="map_event_mature.tga"/>
- <texture name="map_home.tga"/>
- <texture name="map_infohub.tga"/>
- <texture name="map_telehub.tga"/>
- <texture name="map_track_16.tga"/>
-
- <texture name="media_icon.tga" file_name="icn_label_media.tga" />
- <texture name="music_icon.tga" file_name="icn_label_music.tga" />
- <texture name="noentrylines.j2c" use_mips="true"/>
- <texture name="noentrypasslines.j2c" use_mips="true"/>
-
- <texture name="notify_tip_icon.tga"/>
- <texture name="notify_caution_icon.tga"/>
- <texture name="notify_next.png" preload="true"/>
- <texture name="notify_box_icon.tga"/>
-
- <texture name="object_cone.tga"/>
- <texture name="object_cone_active.tga"/>
- <texture name="object_cube.tga"/>
- <texture name="object_cube_active.tga"/>
- <texture name="object_cylinder.tga"/>
- <texture name="object_cylinder_active.tga"/>
- <texture name="object_grass.tga"/>
- <texture name="object_grass_active.tga"/>
- <texture name="object_hemi_cone.tga"/>
- <texture name="object_hemi_cone_active.tga"/>
- <texture name="object_hemi_cylinder.tga"/>
- <texture name="object_hemi_cylinder_active.tga"/>
- <texture name="object_hemi_sphere.tga"/>
- <texture name="object_hemi_sphere_active.tga"/>
- <texture name="object_prism.tga"/>
- <texture name="object_prism_active.tga"/>
- <texture name="object_pyramid.tga"/>
- <texture name="object_pyramid_active.tga"/>
- <texture name="object_ring.tga"/>
- <texture name="object_ring_active.tga"/>
- <texture name="object_sphere.tga"/>
- <texture name="object_sphere_active.tga"/>
- <texture name="object_tetrahedron.tga"/>
- <texture name="object_tetrahedron_active.tga"/>
- <texture name="object_torus.tga"/>
- <texture name="object_torus_active.tga"/>
- <texture name="object_tree.tga"/>
- <texture name="object_tree_active.tga"/>
- <texture name="object_tube.tga"/>
- <texture name="object_tube_active.tga"/>
-
- <texture name="pixiesmall.j2c" use_mips="true"/>
- <texture name="script_error.j2c" use_mips="true"/>
- <texture name="silhouette.j2c" use_mips="true"/>
-
- <texture name="status_no_build.tga"/>
- <texture name="status_voice.tga"/>
- <texture name="status_buy_currency.tga"/>
- <texture name="status_buy_currency_pressed.tga"/>
- <texture name="status_buy_land.tga"/>
- <texture name="status_buy_land_pressed.tga"/>
- <texture name="status_no_fly.tga"/>
- <texture name="status_health.tga"/>
- <texture name="status_no_push.tga"/>
- <texture name="status_no_scripts.tga"/>
-
- <texture name="tool_dozer.tga"/>
- <texture name="tool_dozer_active.tga"/>
- <texture name="tool_zoom.tga"/>
- <texture name="tool_zoom_active.tga"/>
-
- <texture name="icn_active-speakers-dot-lvl0.tga"/>
- <texture name="icn_active-speakers-dot-lvl1.tga"/>
- <texture name="icn_active-speakers-dot-lvl2.tga"/>
- <texture name="icn_active-speakers-typing1.tga"/>
- <texture name="icn_active-speakers-typing2.tga"/>
- <texture name="icn_active-speakers-typing3.tga"/>
-
- <texture name="icn_voice_ptt-off.tga"/>
- <texture name="icn_voice_ptt-on.tga"/>
- <texture name="icn_voice_ptt-on-lvl1.tga"/>
- <texture name="icn_voice_ptt-on-lvl2.tga"/>
- <texture name="icn_voice_ptt-on-lvl3.tga"/>
- <texture name="icn_voice-call-end.tga"/>
- <texture name="icn_voice-call-start.tga"/>
-
- <texture name="mute_icon.tga"/>
-
- <texture name="icn_slide-groove_dark.tga" scale_left="2" scale_top="5" scale_right="29" scale_bottom="4"/>
- <texture name="icn_slide-highlight.tga" scale_left="2" scale_top="5" scale_right="29" scale_bottom="4"/>
- <texture name="icn_slide-thumb_dark.tga" scale_left="2" scale_top="5" scale_right="29" scale_bottom="4"/>
-
- <texture name="icn_speaker-muted_dark.tga"/>
- <texture name="icn_speaker_dark.tga"/>
-
- <texture name="icn_voice-localchat.tga"/>
- <texture name="icn_voice-groupfocus.tga"/>
- <texture name="icn_voice-pvtfocus.tga"/>
-
- <texture name="icn_media-pause.tga"/>
- <texture name="icn_media-play.tga"/>
- <texture name="icn_music-play.tga"/>
- <texture name="icn_music-pause.tga"/>
- <texture name="icn_media_web.tga" preload="true"/>
- <texture name="icn_media_movie.tga" preload="true"/>
-
- <texture name="icn_chatbar.tga"/>
- <texture name="btn_chatbar.tga" scale_left="20" scale_top="24" scale_right="44" scale_bottom="0"/>
- <texture name="btn_chatbar_selected.tga" scale_left="20" scale_top="24" scale_right="44" scale_bottom="0"/>
-
- <texture name="icn_rounded-text-field.tga"/>
-
- <texture name="flyout_btn_right_selected.tga" scale_left="0" scale_top="30" scale_right="32" scale_bottom="0"/>
-
- <texture name="flyout_btn_right.tga" scale_left="0" scale_top="30" scale_right="32" scale_bottom="0"/>
-
- <texture name="flyout_btn_right_disabled.tga" scale_left="0" scale_top="30" scale_right="32" scale_bottom="0"/>
-
- <texture name="flyout_btn_left_selected.tga" scale_left="16" scale_top="15" scale_right="112" scale_bottom="15"/>
-
- <texture name="flyout_btn_left.tga" scale_left="16" scale_top="15" scale_right="112" scale_bottom="15"/>
-
- <texture name="flyout_btn_left_disabled.tga" scale_left="16" scale_top="15" scale_right="112" scale_bottom="15"/>
-
- <texture name="UIImgResizeBottomRightUUID" file_name="resize_handle_bottom_right_blue.tga"/>
-
- <texture name="UIImgBtnForwardOutUUID" file_name="move_forward_out.tga" preload="true"/>
- <texture name="UIImgBtnForwardInUUID" file_name="move_forward_in.tga" preload="true"/>
- <texture name="UIImgBtnSlideLeftOutUUID" file_name="move_left_out.tga" preload="true"/>
- <texture name="UIImgBtnSlideLeftInUUID" file_name="move_left_in.tga" preload="true"/>
- <texture name="UIImgBtnLeftOutUUID" file_name="move_turn_left_out.tga" preload="true"/>
- <texture name="UIImgBtnLeftInUUID" file_name="move_turn_left_in.tga" preload="true"/>
- <texture name="UIImgBtnRightOutUUID" file_name="move_turn_right_out.tga" preload="true"/>
- <texture name="UIImgBtnRightInUUID" file_name="move_turn_right_in.tga" preload="true"/>
- <texture name="UIImgBtnSlideRightOutUUID" file_name="move_right_out.tga" preload="true"/>
- <texture name="UIImgBtnSlideRightInUUID" file_name="move_right_in.tga" preload="true"/>
- <texture name="UIImgBtnMoveUpInUUID" file_name="move_up_in.tga" preload="true"/>
- <texture name="UIImgBtnMoveUpOutUUID" file_name="move_up_out.tga" preload="true"/>
- <texture name="UIImgBtnMoveDownInUUID" file_name="move_down_in.tga" preload="true"/>
- <texture name="UIImgBtnMoveDownOutUUID" file_name="move_down_out.tga" preload="true"/>
-
- <texture name="cam_rotate_out.tga" preload="true"/>
- <texture name="cam_rotate_in.tga" preload="true"/>
- <texture name="cam_zoom_out.tga" preload="true"/>
- <texture name="cam_zoom_plus_in.tga" preload="true"/>
- <texture name="cam_zoom_minus_in.tga" preload="true"/>
-
- <texture name="UIImgBtnScrollUpOutUUID" file_name="scrollbutton_up_out_blue.tga"/>
- <texture name="UIImgBtnScrollUpInUUID" file_name="scrollbutton_up_in_blue.tga"/>
- <texture name="UIImgBtnScrollDownOutUUID" file_name="scrollbutton_down_out_blue.tga"/>
- <texture name="UIImgBtnScrollDownInUUID" file_name="scrollbutton_down_in_blue.tga"/>
- <texture name="UIImgBtnScrollLeftOutUUID" file_name="scrollbutton_left_out_blue.tga"/>
- <texture name="UIImgBtnScrollLeftInUUID" file_name="scrollbutton_left_in_blue.tga"/>
- <texture name="UIImgBtnScrollRightOutUUID" file_name="scrollbutton_right_out_blue.tga"/>
- <texture name="UIImgBtnScrollRightInUUID" file_name="scrollbutton_right_in_blue.tga"/>
-
- <texture name="UIImgBtnJumpLeftOutUUID" file_name="3c18c87e-5f50-14e2-e744-f44734aa365f.tga"/>
- <texture name="UIImgBtnJumpLeftInUUID" file_name="9cad3e6d-2d6d-107d-f8ab-5ba272b5bfe1.tga"/>
- <texture name="UIImgBtnJumpRightOutUUID" file_name="ff9a71eb-7414-4cf8-866e-a701deb7c3cf.tga"/>
- <texture name="UIImgBtnJumpRightInUUID" file_name="7dabc040-ec13-2309-ddf7-4f161f6de2f4.tga"/>
-
- <texture name="UIImgBtnSpinUpOutUUID" file_name="spin_up_out_blue.tga"/>
- <texture name="UIImgBtnSpinUpInUUID" file_name="spin_up_in_blue.tga"/>
- <texture name="UIImgBtnSpinDownOutUUID" file_name="spin_down_out_blue.tga"/>
- <texture name="UIImgBtnSpinDownInUUID" file_name="spin_down_in_blue.tga"/>
-
- <texture name="UIImgRadioActiveUUID" file_name="radio_active_false.tga"/>
- <texture name="UIImgRadioActiveSelectedUUID" file_name="radio_active_true.tga"/>
- <texture name="UIImgRadioInactiveUUID" file_name="radio_inactive_false.tga"/>
- <texture name="UIImgRadioInactiveSelectedUUID" file_name="radio_inactive_true.tga"/>
-
- <texture name="UIImgCheckboxActiveUUID" file_name="checkbox_enabled_false.tga"/>
- <texture name="UIImgCheckboxActiveSelectedUUID" file_name="checkbox_enabled_true.tga"/>
- <texture name="UIImgCheckboxInactiveUUID" file_name="checkbox_disabled_false.tga"/>
- <texture name="UIImgCheckboxInactiveSelectedUUID" file_name="checkbox_disabled_true.tga"/>
-
- <texture name="UIImgBtnTabTopOutUUID" file_name="tab_top_blue.tga"/>
- <texture name="UIImgBtnTabTopInUUID" file_name="tab_top_selected_blue.tga"/>
- <texture name="UIImgBtnTabBottomOutUUID" file_name="tab_bottom_blue.tga"/>
- <texture name="UIImgBtnTabBottomInUUID" file_name="tab_bottom_selected_blue.tga"/>
-
- <texture name="UIImgGrabUUID" file_name="c63f124c-6340-4fbf-b59e-0869a44adb64.tga"/>
- <texture name="UIImgGrabSelectedUUID" file_name="c1e21504-f136-451d-b8e9-929037812f1d.tga"/>
-
- <!--<texture name="UIImgScaleUUID" file_name="88a90fef-b448-4883-9344-ecf378a60433.tga"/>-->
-
- <texture name="UIImgFaceUUID" file_name="ce15fd63-b0b6-463c-a37d-ea6393208b3e.tga"/>
- <texture name="UIImgFaceSelectedUUID" file_name="b4870163-6208-42a9-9801-93133bf9a6cd.tga"/>
-
- <texture name="UIImgCreateUUID" file_name="7a0b1bdb-b5d9-4df5-bac2-ba230da93b5b.tga"/>
- <texture name="UIImgCreateSelectedUUID" file_name="0098b015-3daf-4cfe-a72f-915369ea97c2.tga"/>
-
- <texture name="UIImgBtnCloseInactiveUUID" file_name="close_inactive_blue.tga"/>
- <texture name="UIImgBtnCloseActiveUUID" file_name="closebox.tga"/>
- <texture name="UIImgBtnClosePressedUUID" file_name="close_in_blue.tga"/>
- <texture name="icn_clear_lineeditor.tga" />
-
- <texture name="up_arrow.tga" file_name="up_arrow.png"/>
- <texture name="down_arrow.tga" file_name="down_arrow.png"/>
-
-
- <texture name="UIImgBtnMinimizeInactiveUUID" file_name="minimize_inactive.tga"/>
- <texture name="UIImgBtnMinimizeActiveUUID" file_name="minimize.tga"/>
- <texture name="UIImgBtnMinimizePressedUUID" file_name="minimize_pressed.tga"/>
-
- <texture name="UIImgBtnRestoreInactiveUUID" file_name="restore_inactive.tga"/>
- <texture name="UIImgBtnRestoreActiveUUID" file_name="restore.tga"/>
- <texture name="UIImgBtnRestorePressedUUID" file_name="restore_pressed.tga"/>
-
- <texture name="UIImgBtnTearOffInactiveUUID" file_name="tearoffbox.tga"/>
- <texture name="UIImgBtnTearOffActiveUUID" file_name="tearoffbox.tga"/>
- <texture name="UIImgBtnTearOffPressedUUID" file_name="tearoff_pressed.tga"/>
-
- <texture name="UIImgCrosshairsUUID" file_name="crosshairs.tga"/>
- <texture name="icn_label_music.tga"/>
- <texture name="icn_label_media.tga"/>
- <texture name="arrow_down.tga"/>
- <texture name="cloud-particle.j2c" use_mips="true"/>
-
- <texture name="skin_thumbnail_default.png" preload="true" />
- <texture name="skin_thumbnail_silver.png" preload="true" />
-
- <texture name="default_land_picture.j2c"/>
- <texture name="default_profile_picture.j2c"/>
- <texture name="locked_image.j2c"/>
+ <texture name="media_floater_border_16.png" scale_top="12" scale_left="4" scale_bottom="4" scale_right="12" />
</textures>
diff --git a/indra/newview/skins/default/textures/transparent.j2c b/indra/newview/skins/default/textures/transparent.j2c
new file mode 100644
index 0000000000..1068e940b9
--- /dev/null
+++ b/indra/newview/skins/default/textures/transparent.j2c
Binary files differ
diff --git a/indra/newview/skins/default/textures/voice_meter_dot.j2c b/indra/newview/skins/default/textures/voice_meter_dot.j2c
new file mode 100644
index 0000000000..e536c3338a
--- /dev/null
+++ b/indra/newview/skins/default/textures/voice_meter_dot.j2c
Binary files differ
diff --git a/indra/newview/skins/default/textures/voice_meter_rings.j2c b/indra/newview/skins/default/textures/voice_meter_rings.j2c
new file mode 100644
index 0000000000..17e7c6c6a1
--- /dev/null
+++ b/indra/newview/skins/default/textures/voice_meter_rings.j2c
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Arrow_Down.png b/indra/newview/skins/default/textures/widgets/Arrow_Down.png
new file mode 100644
index 0000000000..e10f6472eb
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Arrow_Down.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Arrow_Small_Left.png b/indra/newview/skins/default/textures/widgets/Arrow_Small_Left.png
new file mode 100644
index 0000000000..2d624c3779
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Arrow_Small_Left.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Arrow_Small_Right.png b/indra/newview/skins/default/textures/widgets/Arrow_Small_Right.png
new file mode 100644
index 0000000000..91c03c426e
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Arrow_Small_Right.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Arrow_Small_Up.png b/indra/newview/skins/default/textures/widgets/Arrow_Small_Up.png
new file mode 100644
index 0000000000..38aac0e5ca
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Arrow_Small_Up.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Arrow_Up.png b/indra/newview/skins/default/textures/widgets/Arrow_Up.png
new file mode 100644
index 0000000000..48df69d82e
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Arrow_Up.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Checkbox_Disabled.png b/indra/newview/skins/default/textures/widgets/Checkbox_Disabled.png
new file mode 100644
index 0000000000..c1ee210099
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Checkbox_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Checkbox_Off.png b/indra/newview/skins/default/textures/widgets/Checkbox_Off.png
new file mode 100644
index 0000000000..2525405f37
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Checkbox_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Checkbox_On.png b/indra/newview/skins/default/textures/widgets/Checkbox_On.png
new file mode 100644
index 0000000000..2d9dba1592
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Checkbox_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Checkbox_On_Disabled.png b/indra/newview/skins/default/textures/widgets/Checkbox_On_Disabled.png
new file mode 100644
index 0000000000..beaa7bcbf6
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Checkbox_On_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Checkbox_On_Over.png b/indra/newview/skins/default/textures/widgets/Checkbox_On_Over.png
new file mode 100644
index 0000000000..bc504d130e
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Checkbox_On_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Checkbox_On_Press.png b/indra/newview/skins/default/textures/widgets/Checkbox_On_Press.png
new file mode 100644
index 0000000000..5bced95a89
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Checkbox_On_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Checkbox_Over.png b/indra/newview/skins/default/textures/widgets/Checkbox_Over.png
new file mode 100644
index 0000000000..5a7162addf
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Checkbox_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Checkbox_Press.png b/indra/newview/skins/default/textures/widgets/Checkbox_Press.png
new file mode 100644
index 0000000000..44be193678
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Checkbox_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ComboButton_Disabled.png b/indra/newview/skins/default/textures/widgets/ComboButton_Disabled.png
new file mode 100644
index 0000000000..d0fff1b3c3
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ComboButton_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ComboButton_Off.png b/indra/newview/skins/default/textures/widgets/ComboButton_Off.png
new file mode 100644
index 0000000000..80402458b7
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ComboButton_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ComboButton_On.png b/indra/newview/skins/default/textures/widgets/ComboButton_On.png
new file mode 100644
index 0000000000..b42cc7542e
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ComboButton_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ComboButton_Selected.png b/indra/newview/skins/default/textures/widgets/ComboButton_Selected.png
new file mode 100644
index 0000000000..bbc0657487
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ComboButton_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ComboButton_UpOff.png b/indra/newview/skins/default/textures/widgets/ComboButton_UpOff.png
new file mode 100644
index 0000000000..2330cb420b
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ComboButton_UpOff.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ComboButton_UpSelected.png b/indra/newview/skins/default/textures/widgets/ComboButton_UpSelected.png
new file mode 100644
index 0000000000..b7b5c2e1d4
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ComboButton_UpSelected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ComboButton_Up_On_Selected.png b/indra/newview/skins/default/textures/widgets/ComboButton_Up_On_Selected.png
new file mode 100644
index 0000000000..fd1d11dd0b
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ComboButton_Up_On_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/DisclosureArrow_Closed_Over.png b/indra/newview/skins/default/textures/widgets/DisclosureArrow_Closed_Over.png
new file mode 100644
index 0000000000..45bcb0464e
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/DisclosureArrow_Closed_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/DisclosureArrow_Opened_Off.png b/indra/newview/skins/default/textures/widgets/DisclosureArrow_Opened_Off.png
new file mode 100644
index 0000000000..75057938d2
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/DisclosureArrow_Opened_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/DisclosureArrow_Opened_Over.png b/indra/newview/skins/default/textures/widgets/DisclosureArrow_Opened_Over.png
new file mode 100644
index 0000000000..dabbd85b34
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/DisclosureArrow_Opened_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/DropDown_Disabled.png b/indra/newview/skins/default/textures/widgets/DropDown_Disabled.png
new file mode 100644
index 0000000000..b295752ea9
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/DropDown_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/DropDown_Off.png b/indra/newview/skins/default/textures/widgets/DropDown_Off.png
new file mode 100644
index 0000000000..4764ed4ee2
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/DropDown_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/DropDown_On.png b/indra/newview/skins/default/textures/widgets/DropDown_On.png
new file mode 100644
index 0000000000..10262d3979
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/DropDown_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/DropDown_Press.png b/indra/newview/skins/default/textures/widgets/DropDown_Press.png
new file mode 100644
index 0000000000..16cb25cc77
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/DropDown_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/DropTarget.png b/indra/newview/skins/default/textures/widgets/DropTarget.png
new file mode 100644
index 0000000000..3740c98cbc
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/DropTarget.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Linden_Dollar_Alert.png b/indra/newview/skins/default/textures/widgets/Linden_Dollar_Alert.png
new file mode 100644
index 0000000000..a1f21e8194
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Linden_Dollar_Alert.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Linden_Dollar_Background.png b/indra/newview/skins/default/textures/widgets/Linden_Dollar_Background.png
new file mode 100644
index 0000000000..61f9b076ce
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Linden_Dollar_Background.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ListItem_Over.png b/indra/newview/skins/default/textures/widgets/ListItem_Over.png
new file mode 100644
index 0000000000..4b2b9ab3e5
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ListItem_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ListItem_Select.png b/indra/newview/skins/default/textures/widgets/ListItem_Select.png
new file mode 100644
index 0000000000..317c672441
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ListItem_Select.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ProgressBar.png b/indra/newview/skins/default/textures/widgets/ProgressBar.png
new file mode 100644
index 0000000000..edf11ac1f5
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ProgressBar.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ProgressTrack.png b/indra/newview/skins/default/textures/widgets/ProgressTrack.png
new file mode 100644
index 0000000000..bb6d9f4144
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ProgressTrack.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Disabled.png b/indra/newview/skins/default/textures/widgets/PushButton_Disabled.png
new file mode 100644
index 0000000000..04e91bdaab
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/PushButton_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Off.png b/indra/newview/skins/default/textures/widgets/PushButton_Off.png
new file mode 100644
index 0000000000..1ee0329e66
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/PushButton_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_On.png b/indra/newview/skins/default/textures/widgets/PushButton_On.png
new file mode 100644
index 0000000000..661d1c5611
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/PushButton_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_On_Over.png b/indra/newview/skins/default/textures/widgets/PushButton_On_Over.png
new file mode 100644
index 0000000000..064a4c4f7f
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/PushButton_On_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_On_Selected.png b/indra/newview/skins/default/textures/widgets/PushButton_On_Selected.png
new file mode 100644
index 0000000000..48e8aa2eab
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/PushButton_On_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Over.png b/indra/newview/skins/default/textures/widgets/PushButton_Over.png
new file mode 100644
index 0000000000..c227f07513
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/PushButton_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Press.png b/indra/newview/skins/default/textures/widgets/PushButton_Press.png
new file mode 100644
index 0000000000..0a4a3a6ad9
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/PushButton_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Selected.png b/indra/newview/skins/default/textures/widgets/PushButton_Selected.png
new file mode 100644
index 0000000000..0a4a3a6ad9
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/PushButton_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Selected_Disabled.png b/indra/newview/skins/default/textures/widgets/PushButton_Selected_Disabled.png
new file mode 100644
index 0000000000..661d1c5611
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/PushButton_Selected_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Selected_Over.png b/indra/newview/skins/default/textures/widgets/PushButton_Selected_Over.png
new file mode 100644
index 0000000000..064a4c4f7f
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/PushButton_Selected_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Selected_Press.png b/indra/newview/skins/default/textures/widgets/PushButton_Selected_Press.png
new file mode 100644
index 0000000000..48e8aa2eab
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/PushButton_Selected_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/RadioButton_Disabled.png b/indra/newview/skins/default/textures/widgets/RadioButton_Disabled.png
new file mode 100644
index 0000000000..a1052684b9
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/RadioButton_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/RadioButton_Off.png b/indra/newview/skins/default/textures/widgets/RadioButton_Off.png
new file mode 100644
index 0000000000..c58e0305ef
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/RadioButton_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/RadioButton_On.png b/indra/newview/skins/default/textures/widgets/RadioButton_On.png
new file mode 100644
index 0000000000..c09a2197c7
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/RadioButton_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/RadioButton_On_Disabled.png b/indra/newview/skins/default/textures/widgets/RadioButton_On_Disabled.png
new file mode 100644
index 0000000000..d7d444fd0c
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/RadioButton_On_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/RadioButton_On_Over.png b/indra/newview/skins/default/textures/widgets/RadioButton_On_Over.png
new file mode 100644
index 0000000000..3e7d803a28
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/RadioButton_On_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/RadioButton_On_Press.png b/indra/newview/skins/default/textures/widgets/RadioButton_On_Press.png
new file mode 100644
index 0000000000..a707e8ceb8
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/RadioButton_On_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/RadioButton_Over.png b/indra/newview/skins/default/textures/widgets/RadioButton_Over.png
new file mode 100644
index 0000000000..a5c8cbe293
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/RadioButton_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/RadioButton_Press.png b/indra/newview/skins/default/textures/widgets/RadioButton_Press.png
new file mode 100644
index 0000000000..33eaa14030
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/RadioButton_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ScrollArrow_Down.png b/indra/newview/skins/default/textures/widgets/ScrollArrow_Down.png
new file mode 100644
index 0000000000..186822da43
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ScrollArrow_Down.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ScrollArrow_Down_Over.png b/indra/newview/skins/default/textures/widgets/ScrollArrow_Down_Over.png
new file mode 100644
index 0000000000..605d159eaa
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ScrollArrow_Down_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ScrollArrow_Left.png b/indra/newview/skins/default/textures/widgets/ScrollArrow_Left.png
new file mode 100644
index 0000000000..42f999a451
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ScrollArrow_Left.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ScrollArrow_Left_Opaque.png b/indra/newview/skins/default/textures/widgets/ScrollArrow_Left_Opaque.png
new file mode 100644
index 0000000000..549b3980f6
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ScrollArrow_Left_Opaque.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ScrollArrow_Left_Over.png b/indra/newview/skins/default/textures/widgets/ScrollArrow_Left_Over.png
new file mode 100644
index 0000000000..c79547dffd
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ScrollArrow_Left_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ScrollArrow_Left_Over_Opaque.png b/indra/newview/skins/default/textures/widgets/ScrollArrow_Left_Over_Opaque.png
new file mode 100644
index 0000000000..a74abd5d8a
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ScrollArrow_Left_Over_Opaque.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ScrollArrow_Right.png b/indra/newview/skins/default/textures/widgets/ScrollArrow_Right.png
new file mode 100644
index 0000000000..176ffcdbb9
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ScrollArrow_Right.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ScrollArrow_Right_Opaque.png b/indra/newview/skins/default/textures/widgets/ScrollArrow_Right_Opaque.png
new file mode 100644
index 0000000000..36056d0ad9
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ScrollArrow_Right_Opaque.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ScrollArrow_Right_Over.png b/indra/newview/skins/default/textures/widgets/ScrollArrow_Right_Over.png
new file mode 100644
index 0000000000..e353542ad9
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ScrollArrow_Right_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ScrollArrow_Right_Over_Opaque.png b/indra/newview/skins/default/textures/widgets/ScrollArrow_Right_Over_Opaque.png
new file mode 100644
index 0000000000..0c1fd6956b
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ScrollArrow_Right_Over_Opaque.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ScrollArrow_Up.png b/indra/newview/skins/default/textures/widgets/ScrollArrow_Up.png
new file mode 100644
index 0000000000..4d245eb57a
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ScrollArrow_Up.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ScrollArrow_Up_Over.png b/indra/newview/skins/default/textures/widgets/ScrollArrow_Up_Over.png
new file mode 100644
index 0000000000..dd2fceb716
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ScrollArrow_Up_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ScrollThumb_Horiz.png b/indra/newview/skins/default/textures/widgets/ScrollThumb_Horiz.png
new file mode 100644
index 0000000000..8a085aa966
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ScrollThumb_Horiz.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ScrollThumb_Horiz_Over.png b/indra/newview/skins/default/textures/widgets/ScrollThumb_Horiz_Over.png
new file mode 100644
index 0000000000..cf78ea3924
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ScrollThumb_Horiz_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ScrollThumb_Vert.png b/indra/newview/skins/default/textures/widgets/ScrollThumb_Vert.png
new file mode 100644
index 0000000000..fc7fd93e7a
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ScrollThumb_Vert.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ScrollThumb_Vert_Over.png b/indra/newview/skins/default/textures/widgets/ScrollThumb_Vert_Over.png
new file mode 100644
index 0000000000..53587197da
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ScrollThumb_Vert_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ScrollTrack_Horiz.png b/indra/newview/skins/default/textures/widgets/ScrollTrack_Horiz.png
new file mode 100644
index 0000000000..4f31c48c02
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ScrollTrack_Horiz.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/ScrollTrack_Vert.png b/indra/newview/skins/default/textures/widgets/ScrollTrack_Vert.png
new file mode 100644
index 0000000000..f89ee3f68f
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/ScrollTrack_Vert.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Disabled.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Disabled.png
new file mode 100644
index 0000000000..3b39c51a77
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Off.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Off.png
new file mode 100644
index 0000000000..57ed79d733
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_On.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_On.png
new file mode 100644
index 0000000000..7afb9c99c3
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_On_Disabled.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_On_Disabled.png
new file mode 100644
index 0000000000..77c4224539
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_On_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_On_Over.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_On_Over.png
new file mode 100644
index 0000000000..8b93dd551e
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_On_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_On_Selected.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_On_Selected.png
new file mode 100644
index 0000000000..3f207cbea2
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_On_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Over.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Over.png
new file mode 100644
index 0000000000..5b8878e0cb
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Press.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Press.png
new file mode 100644
index 0000000000..379953216b
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected.png
new file mode 100644
index 0000000000..379953216b
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Disabled.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Disabled.png
new file mode 100644
index 0000000000..77c4224539
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Over.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Over.png
new file mode 100644
index 0000000000..8b93dd551e
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Press.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Press.png
new file mode 100644
index 0000000000..3f207cbea2
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Disabled.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Disabled.png
new file mode 100644
index 0000000000..deb87c8489
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_On.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_On.png
new file mode 100644
index 0000000000..220df9db25
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_On_Over.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_On_Over.png
new file mode 100644
index 0000000000..5bbcdcb0b4
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_On_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_On_Press.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_On_Press.png
new file mode 100644
index 0000000000..dde367f05e
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_On_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Over.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Over.png
new file mode 100644
index 0000000000..d4f30b9adb
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected.png
new file mode 100644
index 0000000000..ca7027da91
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Disabled.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Disabled.png
new file mode 100644
index 0000000000..220df9db25
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Over.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Over.png
new file mode 100644
index 0000000000..5bbcdcb0b4
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Press.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Press.png
new file mode 100644
index 0000000000..dde367f05e
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Disabled.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Disabled.png
new file mode 100644
index 0000000000..8e6b9c8c6f
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Off.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Off.png
new file mode 100644
index 0000000000..b1521199ff
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_On.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_On.png
new file mode 100644
index 0000000000..467c43fc90
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_On_Over.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_On_Over.png
new file mode 100644
index 0000000000..2049736897
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_On_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_On_Selected.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_On_Selected.png
new file mode 100644
index 0000000000..1574f48b28
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_On_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Over.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Over.png
new file mode 100644
index 0000000000..2717e7d7b0
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Press.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Press.png
new file mode 100644
index 0000000000..3883518033
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected.png
new file mode 100644
index 0000000000..3883518033
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected_Disabled.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected_Disabled.png
new file mode 100644
index 0000000000..ab31f6ded7
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected_Over.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected_Over.png
new file mode 100644
index 0000000000..2049736897
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected_Press.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected_Press.png
new file mode 100644
index 0000000000..1574f48b28
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SliderThumb_Disabled.png b/indra/newview/skins/default/textures/widgets/SliderThumb_Disabled.png
new file mode 100644
index 0000000000..b627232012
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SliderThumb_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SliderThumb_Off.png b/indra/newview/skins/default/textures/widgets/SliderThumb_Off.png
new file mode 100644
index 0000000000..b627232012
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SliderThumb_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SliderThumb_Over.png b/indra/newview/skins/default/textures/widgets/SliderThumb_Over.png
new file mode 100644
index 0000000000..b6f900d3bd
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SliderThumb_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SliderThumb_Press.png b/indra/newview/skins/default/textures/widgets/SliderThumb_Press.png
new file mode 100644
index 0000000000..7081f9cfe0
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SliderThumb_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SliderTrack_Horiz.png b/indra/newview/skins/default/textures/widgets/SliderTrack_Horiz.png
new file mode 100644
index 0000000000..232006ee5a
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SliderTrack_Horiz.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/SliderTrack_Vert.png b/indra/newview/skins/default/textures/widgets/SliderTrack_Vert.png
new file mode 100644
index 0000000000..cd002b3973
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/SliderTrack_Vert.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Stepper_Down_Off.png b/indra/newview/skins/default/textures/widgets/Stepper_Down_Off.png
new file mode 100644
index 0000000000..cf0d8ee2c1
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Stepper_Down_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Stepper_Down_Over.png b/indra/newview/skins/default/textures/widgets/Stepper_Down_Over.png
new file mode 100644
index 0000000000..01e0a2d9f1
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Stepper_Down_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Stepper_Down_Press.png b/indra/newview/skins/default/textures/widgets/Stepper_Down_Press.png
new file mode 100644
index 0000000000..fe3a7beafd
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Stepper_Down_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Stepper_Up_Off.png b/indra/newview/skins/default/textures/widgets/Stepper_Up_Off.png
new file mode 100644
index 0000000000..133589b8a6
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Stepper_Up_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Stepper_Up_Over.png b/indra/newview/skins/default/textures/widgets/Stepper_Up_Over.png
new file mode 100644
index 0000000000..2ce84ea5be
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Stepper_Up_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Stepper_Up_Press.png b/indra/newview/skins/default/textures/widgets/Stepper_Up_Press.png
new file mode 100644
index 0000000000..e83babc519
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Stepper_Up_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/TextField_Active.png b/indra/newview/skins/default/textures/widgets/TextField_Active.png
new file mode 100644
index 0000000000..ca6daab4e0
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/TextField_Active.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/TextField_Disabled.png b/indra/newview/skins/default/textures/widgets/TextField_Disabled.png
new file mode 100644
index 0000000000..3d205a3f2e
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/TextField_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/TextField_Off.png b/indra/newview/skins/default/textures/widgets/TextField_Off.png
new file mode 100644
index 0000000000..911d907acc
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/TextField_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/TextField_Search_Active.png b/indra/newview/skins/default/textures/widgets/TextField_Search_Active.png
new file mode 100644
index 0000000000..fa79cb6260
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/TextField_Search_Active.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/TextField_Search_Disabled.png b/indra/newview/skins/default/textures/widgets/TextField_Search_Disabled.png
new file mode 100644
index 0000000000..8b504af101
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/TextField_Search_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/TextField_Search_Off.png b/indra/newview/skins/default/textures/widgets/TextField_Search_Off.png
new file mode 100644
index 0000000000..862b13d219
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/TextField_Search_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Tooltip.png b/indra/newview/skins/default/textures/widgets/Tooltip.png
new file mode 100644
index 0000000000..f989ac9083
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Tooltip.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/jump_left_in.png b/indra/newview/skins/default/textures/widgets/jump_left_in.png
new file mode 100644
index 0000000000..a1425ccfa0
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/jump_left_in.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/jump_left_out.png b/indra/newview/skins/default/textures/widgets/jump_left_out.png
new file mode 100644
index 0000000000..38edf47d19
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/jump_left_out.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/jump_right_in.png b/indra/newview/skins/default/textures/widgets/jump_right_in.png
new file mode 100644
index 0000000000..39359ab2e2
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/jump_right_in.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/jump_right_out.png b/indra/newview/skins/default/textures/widgets/jump_right_out.png
new file mode 100644
index 0000000000..3f76bbffac
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/jump_right_out.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Flyout.png b/indra/newview/skins/default/textures/windows/Flyout.png
new file mode 100644
index 0000000000..5596b194c9
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Flyout.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Flyout_Pointer.png b/indra/newview/skins/default/textures/windows/Flyout_Pointer.png
new file mode 100644
index 0000000000..69fc08ceaa
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Flyout_Pointer.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Icon_Close_Foreground.png b/indra/newview/skins/default/textures/windows/Icon_Close_Foreground.png
new file mode 100644
index 0000000000..2292b79eda
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Close_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Icon_Close_Press.png b/indra/newview/skins/default/textures/windows/Icon_Close_Press.png
new file mode 100644
index 0000000000..ea547fca6f
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Close_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Icon_Close_Toast.png b/indra/newview/skins/default/textures/windows/Icon_Close_Toast.png
new file mode 100644
index 0000000000..ecf01c617a
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Close_Toast.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Icon_Dock_Foreground.png b/indra/newview/skins/default/textures/windows/Icon_Dock_Foreground.png
new file mode 100644
index 0000000000..4207ba68e5
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Dock_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Icon_Dock_Press.png b/indra/newview/skins/default/textures/windows/Icon_Dock_Press.png
new file mode 100644
index 0000000000..2d09475783
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Dock_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Icon_Gear_Background.png b/indra/newview/skins/default/textures/windows/Icon_Gear_Background.png
new file mode 100644
index 0000000000..db74b93afd
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Gear_Background.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Icon_Gear_Foreground.png b/indra/newview/skins/default/textures/windows/Icon_Gear_Foreground.png
new file mode 100644
index 0000000000..1032e45f7e
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Gear_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Icon_Gear_Over.png b/indra/newview/skins/default/textures/windows/Icon_Gear_Over.png
new file mode 100644
index 0000000000..01dbde102b
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Gear_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Icon_Gear_Press.png b/indra/newview/skins/default/textures/windows/Icon_Gear_Press.png
new file mode 100644
index 0000000000..6614bdd165
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Gear_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Icon_Help_Foreground.png b/indra/newview/skins/default/textures/windows/Icon_Help_Foreground.png
new file mode 100644
index 0000000000..1a514742d3
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Help_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Icon_Help_Press.png b/indra/newview/skins/default/textures/windows/Icon_Help_Press.png
new file mode 100644
index 0000000000..7478644b6a
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Help_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Icon_Minimize_Foreground.png b/indra/newview/skins/default/textures/windows/Icon_Minimize_Foreground.png
new file mode 100644
index 0000000000..9f72a5422b
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Minimize_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Icon_Minimize_Press.png b/indra/newview/skins/default/textures/windows/Icon_Minimize_Press.png
new file mode 100644
index 0000000000..07db8be1b0
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Minimize_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Icon_Restore_Foreground.png b/indra/newview/skins/default/textures/windows/Icon_Restore_Foreground.png
new file mode 100644
index 0000000000..1e753aaf1d
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Restore_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Icon_Restore_Press.png b/indra/newview/skins/default/textures/windows/Icon_Restore_Press.png
new file mode 100644
index 0000000000..be66b05230
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Restore_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Icon_Undock_Foreground.png b/indra/newview/skins/default/textures/windows/Icon_Undock_Foreground.png
new file mode 100644
index 0000000000..9a71d16a3f
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Undock_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Icon_Undock_Press.png b/indra/newview/skins/default/textures/windows/Icon_Undock_Press.png
new file mode 100644
index 0000000000..3ab8c3666a
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Icon_Undock_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Inspector_Background.png b/indra/newview/skins/default/textures/windows/Inspector_Background.png
new file mode 100644
index 0000000000..4c2a728ac5
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Inspector_Background.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Inspector_Hover.png b/indra/newview/skins/default/textures/windows/Inspector_Hover.png
new file mode 100644
index 0000000000..feeee78033
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Inspector_Hover.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Inspector_I.png b/indra/newview/skins/default/textures/windows/Inspector_I.png
new file mode 100644
index 0000000000..b4875fd638
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Inspector_I.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Resize_Corner.png b/indra/newview/skins/default/textures/windows/Resize_Corner.png
new file mode 100644
index 0000000000..16ed63e428
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Resize_Corner.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Toast_Background.png b/indra/newview/skins/default/textures/windows/Toast_Background.png
new file mode 100644
index 0000000000..f27d1a12ec
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Toast_Background.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Toast_CloseBtn.png b/indra/newview/skins/default/textures/windows/Toast_CloseBtn.png
new file mode 100644
index 0000000000..78b137cdaf
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Toast_CloseBtn.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Toast_Over.png b/indra/newview/skins/default/textures/windows/Toast_Over.png
new file mode 100644
index 0000000000..807e8e553c
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Toast_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Window_Background.png b/indra/newview/skins/default/textures/windows/Window_Background.png
new file mode 100644
index 0000000000..db253900af
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Window_Background.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Window_Foreground.png b/indra/newview/skins/default/textures/windows/Window_Foreground.png
new file mode 100644
index 0000000000..b81ec5b43c
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Window_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Window_NoTitle_Background.png b/indra/newview/skins/default/textures/windows/Window_NoTitle_Background.png
new file mode 100644
index 0000000000..a570ac06bd
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Window_NoTitle_Background.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/Window_NoTitle_Foreground.png b/indra/newview/skins/default/textures/windows/Window_NoTitle_Foreground.png
new file mode 100644
index 0000000000..d573e8c69a
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Window_NoTitle_Foreground.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/windows/startup_logo.png b/indra/newview/skins/default/textures/windows/startup_logo.png
new file mode 100644
index 0000000000..b89449692b
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/startup_logo.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/world/BeaconArrow.png b/indra/newview/skins/default/textures/world/BeaconArrow.png
new file mode 100644
index 0000000000..12dc246d51
--- /dev/null
+++ b/indra/newview/skins/default/textures/world/BeaconArrow.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/world/NoEntryLines.png b/indra/newview/skins/default/textures/world/NoEntryLines.png
new file mode 100644
index 0000000000..18e270bde5
--- /dev/null
+++ b/indra/newview/skins/default/textures/world/NoEntryLines.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/world/NoEntryPassLines.png b/indra/newview/skins/default/textures/world/NoEntryPassLines.png
new file mode 100644
index 0000000000..e4b8fc6ae2
--- /dev/null
+++ b/indra/newview/skins/default/textures/world/NoEntryPassLines.png
Binary files differ
diff --git a/indra/newview/skins/default/xui/da/floater_about.xml b/indra/newview/skins/default/xui/da/floater_about.xml
index 5795053a14..eb63b5c975 100644
--- a/indra/newview/skins/default/xui/da/floater_about.xml
+++ b/indra/newview/skins/default/xui/da/floater_about.xml
@@ -1,11 +1,60 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_about" title="Om Second Life">
- <text_editor name="credits_editor">
- Second Life er gjort muligt for dig af Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les and many others.
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_about" title="OM [CAPITALIZED_APP_NAME]">
+ <floater.string name="AboutHeader">
+ [APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL])
+[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]]
+ </floater.string>
+ <floater.string name="AboutCompiler">
+ Bygget med [COMPILER] version [COMPILER_VERSION]
+ </floater.string>
+ <floater.string name="AboutPosition">
+ Du er ved [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] i [REGION] lokaliseret på [HOSTNAME] ([HOSTIP])
+[SERVER_VERSION]
+[[SERVER_RELEASE_NOTES_URL] [ReleaseNotes]]
+ </floater.string>
+ <floater.string name="AboutSystem">
+ CPU: [CPU]
+Memory: [MEMORY_MB] MB
+OS Version: [OS_VERSION]
+Grafik kort mærke: [GRAPHICS_CARD_VENDOR]
+Grafik kort: [GRAPHICS_CARD]
+ </floater.string>
+ <floater.string name="AboutDriver">
+ Windows Graphics Driver Version: [GRAPHICS_DRIVER_VERSION]
+ </floater.string>
+ <floater.string name="AboutLibs">
+ OpenGL Version: [OPENGL_VERSION]
-Tak til følgende beboerne for at bidrage til at sikre, at dette er den bedste version til dato: afon shepherd, Aimee Trescothick, Alexandrea Fride, Alissa Sabre, Amber DeCuir, Asuka Neely, Auron Forcella, Blue Revolution, Bocan Undercroft, Boroondas Gupte, Brandon Shinobu, Bri Gufler, Buckaroo Mu, Celierra Darling, Christos Atlantis, Coder Kas, Cummere Mayo, dakota schwade, Dirk Talamasca, Dizzy Banjo, Drew Dwi, Duckling Kwak, Ellla McMahon, Erikah Jameson, Erinyse Planer, Eyana Yohkoh, Ezian Ecksol, Faron Karu, Fenoe Lowey, Fox Hwasung, Francisca Biedermann, Gally Young, Gellan Glenelg, Geneko Nemeth, Glenn Rotaru, Hagar Qinan, Harleen Gretzky, Holger Gilruth, hotrodjohnny gears, IAm Zabelin, Inigo Catteneo, Iustinian Tomsen, Jacek Antonell, James Benedek, Jim Kupferberg, Joeseph Albanese, JPT62089 Agnon, Kardargo Adamczyk, Kirstenlee Cinquetti, Latif Khalifa, lea Parnall, Lex Neva, Lillith Anatine, Lilly Zenovka, Lim Catteneo, Lindal Kidd, Mark Rosenbaum, MasterJ Chaplin, McCabe Maxsted, Melvin Starbrook, Meni Kaiousei, Mero Collas, Minakothegothicgeisha Kamachi, Moon Metty, neofilo aabye, Neutron Chesnokov, Nomad Ingwer, norritt Xi, Opensource Obscure, Oracle Weatherwax, Ourasi Ferraris, Pabl0 Roffo, Peyton Aleixandre, Phli Foxchase, Psi Merlin, r2d2 Wunderlich, Regi Yifu, Saijanai Kuhn, Sandor Balczo, Sarkan Dreamscape, Scree Raymaker, Sedona Mills, Selena Beale, Sheet Spotter, Shibari Twine, Silver Key, Simon Kline, SLB Wirefly, Stacy Wombat, Sugarcult Dagger, Tayra Dagostino, Tetsuryu Vlodovic, ThaBiGGDoGG Richez, Timo Gufler, tx Oh, wayfinder wishbringer, Wizzytoe McCullough, Wundur Primbee, Yann Dufaux, Yuu Nakamichi, Aminom Marvin, Andred Qinan, arminasx saiman, caroline apollo, Iskar Ariantho, Jenika Connolly, Maghnus Balogh, Nefertiti Nefarious, RodneyLee Jessop
+libcurl Version: [LIBCURL_VERSION]
+J2C Decoder Version: [J2C_VERSION]
+Audio Driver Version: [AUDIO_DRIVER_VERSION]
+Qt Webkit Version: [QT_WEBKIT_VERSION]
+Vivox Version: [VIVOX_VERSION]
+ </floater.string>
+ <floater.string name="none">
+ (ingen)
+ </floater.string>
+ <floater.string name="AboutTraffic">
+ Pakker tabt: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%)
+ </floater.string>
+ <tab_container name="about_tab">
+ <panel label="Info" name="support_panel">
+ <button label="Kopiér til udklipsholder" name="copy_btn"/>
+ </panel>
+ <panel label="Tak til" name="credits_panel">
+ <text_editor name="credits_editor">
+ Second Life er gjort muligt for dig af Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, Michon, Jenelle, Geo, Siz, Shapiro, Pete, Calyle, Selene, Allen, Phoebe, Goldin, Kimmora, Dakota, Slaton, Lindquist, Zoey, Hari, Othello, Rohit, Sheldon, Petra, Viale, Gordon, Kaye, Pink, Ferny, Emerson, Davy, Bri, Chan, Juan, Robert, Terrence, Nathan, Carl and many others.
- 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
+Tak til følgende beboerne for at bidrage til at sikre, at dette er den bedste version til dato: able whitman, Adeon Writer, adonaira aabye, Aeron Kohime, Agathos Frascati, Aimee Trescothick, Aleric Inglewood, Alissa Sabre, Aminom Marvin, Angela Talamasca, Aralara Rajal, Armin Weatherwax, Ashrilyn Hayashida, Athanasius Skytower, Aura Dirval, Barney Boomslang, Biancaluce Robbiani, Biker Offcourse, Borg Capalini, Bulli Schumann, catherine pfeffer, Chalice Yao, Corre Porta, Court Goodman, Cummere Mayo, Dale Innis, Darien Caldwell, Darjeeling Schoonhoven, Daten Thielt, dimentox travanti, Dirk Talamasca, Drew Dwi, Duckless Vandyke, Elanthius Flagstaff, Electro Burnstein, emiley tomsen, Escort DeFarge, Eva Rau, Ezian Ecksol, Fire Centaur, Fluf Fredriksson, Francisco Koolhoven, Frontera Thor, Frungi Stastny, Gally Young, gearsawe stonecutter, Gigs Taggart, Gordon Wendt, Gudmund Shepherd, Gypsy Paz, Harleen Gretzky, Henri Beauchamp, Inma Rau, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Jessicka Graves, Joeseph Albanese, Joshua Philgarlic, Khyota Wulluf, kirstenlee Cinquetti, Latif Khalifa, Lex Neva, Lilibeth Andree, Lisa Lowe, Lunita Savira, Loosey Demonia, lum pfohl, Marcos Fonzarelli, MartinRJ Fayray, Marusame Arai, Matthew Dowd, Maya Remblai, McCabe Maxsted, Meghan Dench, Melchoir Tokhes, Menos Short, Michelle2 Zenovka, Mimika Oh, Minerva Memel, Mm Alder, Ochi Wolfe, Omei Turnbull, Pesho Replacement, Phantom Ninetails, phoenixflames kukulcan, Polo Gufler, prez pessoa, princess niven, Prokofy Neva, Qie Niangao, Rem Beattie, RodneyLee Jessop, Saijanai Kuhn, Seg Baphomet, Sergen Davies, Shirley Marquez, SignpostMarv Martin, Sindy Tsure, Sira Arbizu, Skips Jigsaw, Sougent Harrop, Spritely Pixel, Squirrel Wood, StarSong Bright, Subversive Writer, Sugarcult Dagger, Sylumm Grigorovich, Tammy Nowotny, Tanooki Darkes, Tayra Dagostino, Theoretical Chemistry, Thickbrick Sleaford, valerie rosewood, Vex Streeter, Vixen Heron, Whoops Babii, Winter Ventura, Xiki Luik, Yann Dufaux, Yina Yao, Yukinoroh Kamachi, Zolute Infinity, Zwagoth Klaar
+
+
+
+I get by with a little help from my friends. --Richard Starkey
+ </text_editor>
+ </panel>
+ <panel label="Licenser" name="licenses_panel">
+ <text_editor name="credits_editor">
+ 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
APR Copyright (C) 2000-2004 The Apache Software Foundation
cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc.
@@ -26,11 +75,7 @@ Tak til følgende beboerne for at bidrage til at sikre, at dette er den bedste v
Alle rettigheder forbeholdes. Se licenses.txt for detaljer.
Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
-
-
-I get by with a little help from my friends. --Richard Starkey
- </text_editor>
- <string name="you_are_at">
- Du er ved [POSITION]
- </string>
+ </text_editor>
+ </panel>
+ </tab_container>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_about_land.xml b/indra/newview/skins/default/xui/da/floater_about_land.xml
index 8c1ed736a3..cb5d618dde 100644
--- a/indra/newview/skins/default/xui/da/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/da/floater_about_land.xml
@@ -1,461 +1,472 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floaterland" title="Om land">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floaterland" title="OM LAND">
<tab_container name="landtab">
<panel label="Generelt" name="land_general_panel">
- <text type="string" length="1" name="Name:">
+ <text name="Name:">
Navn:
</text>
- <text type="string" length="1" name="Description:">
+ <text name="Description:">
Beskrivelse:
</text>
- <text type="string" length="1" name="Owner:">
+ <text name="LandType">
+ Type:
+ </text>
+ <text name="LandTypeText">
+ Mainland / Homestead
+ </text>
+ <text name="ContentRating">
+ Rating:
+ </text>
+ <text name="ContentRatingText">
+ Adult
+ </text>
+ <text name="Owner:">
Ejer:
</text>
- <text type="string" length="1" name="OwnerText">
+ <text name="OwnerText">
Leyla Linden
</text>
- <button label="Profil..." label_selected="Profil..." name="Profile..." />
- <text type="string" length="1" name="Group:">
+ <button label="Profil..." label_selected="Profil..." name="Profile..."/>
+ <text name="Group:">
Gruppe:
</text>
- <button label="Vælg..." label_selected="Vælg..." name="Set..." />
- <check_box label="Tillad dedikering til gruppe" name="check deed"
- tool_tip="En gruppe administrator kan dedikere denne jord til gruppen, så det vil blive støttet af gruppen&apos;s jord tildeling." />
- <button label="Dedikér..." label_selected="Dedikér..." name="Deed..."
- tool_tip="Du kan kun dedikere jord, hvis du er en administrator i den valgte gruppe." />
- <check_box label="Ejer bidrager ved dedikering" name="check contrib"
- tool_tip="Når land dedikeres til gruppe, kan den tidligere bidrage med nok land til at dække krav." />
- <text type="string" length="1" name="For Sale:">
+ <button label="Vælg..." label_selected="Vælg..." name="Set..."/>
+ <check_box label="Tillad dedikering til gruppe" name="check deed" tool_tip="En gruppe administrator kan dedikere denne jord til gruppen, så det vil blive støttet af gruppen&apos;s jord tildeling."/>
+ <button label="Dedikér..." label_selected="Dedikér..." name="Deed..." tool_tip="Du kan kun dedikere jord, hvis du er en administrator i den valgte gruppe."/>
+ <check_box label="Ejer bidrager ved dedikering" name="check contrib" tool_tip="Når land dedikeres til gruppe, kan den tidligere bidrage med nok land til at dække krav."/>
+ <text name="For Sale:">
Til salg:
</text>
- <text type="string" length="1" name="Not for sale.">
+ <text name="Not for sale.">
Ikke til salg.
</text>
- <text type="string" length="1" name="For Sale: Price L$[PRICE].">
- Pris: L$[PRICE].
+ <text name="For Sale: Price L$[PRICE].">
+ Pris: L$[PRICE] (L$[PRICE_PER_SQM]/m²).
</text>
- <button label="Sælg land..." label_selected="Sælg land..." name="Sell Land..." />
- <text type="string" length="1" name="For sale to">
+ <button label="Sælg land..." label_selected="Sælg land..." name="Sell Land..."/>
+ <text name="For sale to">
Til salg til: [BUYER]
</text>
- <text type="string" length="1" name="Sell with landowners objects in parcel.">
+ <text name="Sell with landowners objects in parcel.">
Objekter er inkluderet i salg.
</text>
- <text type="string" length="1" name="Selling with no objects in parcel.">
+ <text name="Selling with no objects in parcel.">
Objekter er ikke inkluderet i salg.
</text>
- <button label="Annullér salg af land" label_selected="Annullér salg af land"
- name="Cancel Land Sale" />
- <text type="string" length="1" name="Claimed:">
+ <button label="Annullér salg af land" label_selected="Annullér salg af land" name="Cancel Land Sale"/>
+ <text name="Claimed:">
Købt:
</text>
- <text type="string" length="1" name="DateClaimText">
+ <text name="DateClaimText">
Tue Aug 15 13:47:25 2006
</text>
- <text type="string" length="1" name="PriceLabel">
+ <text name="PriceLabel">
Område:
</text>
- <text type="string" length="1" name="PriceText">
+ <text name="PriceText">
4048 m²
</text>
- <text type="string" length="1" name="Traffic:">
+ <text name="Traffic:">
Trafik:
</text>
- <text type="string" length="1" name="DwellText">
+ <text name="DwellText">
0
</text>
- <button label="Køb land..." label_selected="Køb land..." name="Buy Land..." />
- <button label="Køb til gruppe..." label_selected="Køb til gruppe..."
- name="Buy For Group..." />
- <button label="Køb adgang..." label_selected="Køb adgang..." name="Buy Pass..."
- tool_tip="Giver adgang til midlertidig adgang til dette område." />
- <button label="Efterlad land..." label_selected="Efterlad land..."
- name="Abandon Land..." />
- <button label="Kræv tilbage..." label_selected="Kræv tilbage..."
- name="Reclaim Land..." />
- <button label="Linden lalg..." label_selected="Linden lalg..." name="Linden salg..."
- tool_tip="Land skal være ejet og ikke allerede på auktion" />
- <string name="new users only">
+ <button label="Køb land..." label_selected="Køb land..." name="Buy Land..."/>
+ <button label="Køb til gruppe..." label_selected="Køb til gruppe..." name="Buy For Group..."/>
+ <button label="Køb adgang..." label_selected="Køb adgang..." name="Buy Pass..." tool_tip="Giver adgang til midlertidig adgang til dette område."/>
+ <button label="Efterlad land..." label_selected="Efterlad land..." name="Abandon Land..."/>
+ <button label="Kræv tilbage..." label_selected="Kræv tilbage..." name="Reclaim Land..."/>
+ <button label="Linden salg..." label_selected="Linden salg..." name="Linden Sale..." tool_tip="Land skal være ejet, indholdsrating sat og ikke allerede på auktion."/>
+ <panel.string name="new users only">
Kun nye brugere
- </string>
- <string name="anyone">
+ </panel.string>
+ <panel.string name="anyone">
Alle
- </string>
- <string name="area_text">
+ </panel.string>
+ <panel.string name="area_text">
Størrelse
- </string>
- <string name="area_size_text">
+ </panel.string>
+ <panel.string name="area_size_text">
[AREA] m²
- </string>
- <string name="auction_id_text">
+ </panel.string>
+ <panel.string name="auction_id_text">
Auktion nr: [ID]
- </string>
- <string name="need_tier_to_modify">
+ </panel.string>
+ <panel.string name="need_tier_to_modify">
Du skal godkende dit køb for at kunne æmdre på dette land.
- </string>
- <string name="group_owned_text">
+ </panel.string>
+ <panel.string name="group_owned_text">
(Gruppe ejet)
- </string>
- <string name="profile_text">
+ </panel.string>
+ <panel.string name="profile_text">
Profil...
- </string>
- <string name="info_text">
+ </panel.string>
+ <panel.string name="info_text">
Info...
- </string>
- <string name="public_text">
+ </panel.string>
+ <panel.string name="public_text">
(offentlig)
- </string>
- <string name="none_text">
+ </panel.string>
+ <panel.string name="none_text">
(ingen)
- </string>
- <string name="sale_pending_text">
+ </panel.string>
+ <panel.string name="sale_pending_text">
(Salg i gang)
- </string>
- <string name="no_selection_text">
+ </panel.string>
+ <panel.string name="no_selection_text">
Pacel ikke valgt.
Gå til &apos;Verden&apos; &gt; &apos;Om land&apos; eller vælg en anden parcel for at se detaljer.
- </string>
+ </panel.string>
</panel>
<panel label="Regler" name="land_covenant_panel">
- <text type="string" length="1" name="covenant_timestamp_text">
+ <text name="estate_section_lbl">
+ Estate:
+ </text>
+ <text name="estate_name_lbl">
+ Navn:
+ </text>
+ <text name="estate_name_text">
+ Hovedland
+ </text>
+ <text name="estate_owner_lbl">
+ Ejer:
+ </text>
+ <text name="estate_owner_text">
+ (ingen)
+ </text>
+ <text_editor name="covenant_editor">
+ Der er ikke angivet specielle regler for denne Estate
+ </text_editor>
+ <text name="covenant_timestamp_text">
Sidst rettet Wed Dec 31 16:00:00 1969
</text>
- <text type="string" length="1" name="region_name_lbl">
+ <text name="region_section_lbl">
Region:
</text>
- <text type="string" length="1" name="region_name_text">
+ <text name="region_name_lbl">
+ Navn:
+ </text>
+ <text name="region_name_text">
leyla
</text>
- <text type="string" length="1" name="estate_name_lbl">
- Estate:
+ <text name="region_landtype_lbl">
+ Type:
</text>
- <text type="string" length="1" name="estate_name_text">
- Hovedland
+ <text name="region_landtype_text">
+ Mainland / Homestead
</text>
- <text type="string" length="1" name="estate_owner_lbl">
- Estate ejer:
+ <text name="region_maturity_lbl">
+ Rating:
</text>
- <text type="string" length="1" name="estate_owner_text">
- (ingen)
+ <text name="region_maturity_text">
+ Adult
</text>
- <text type="string" length="1" name="resellable_clause">
- Købt jord i denne region må ikke videresælges.
+ <text name="resellable_lbl">
+ Videresalg:
</text>
- <text type="string" length="1" name="changeable_clause">
- Købt jord i denne region må gerne samles eller opdeles.
+ <text name="resellable_clause">
+ Land i denne region må ikke sælges videre.
</text>
- <text_editor type="string" length="1" name="covenant_editor">
- Der er ikke angivet specielle regler for denne Estate
- </text_editor>
- <string name="can_resell">
+ <text name="changeable_lbl">
+ Opdel:
+ </text>
+ <text name="changeable_clause">
+ Land i denne region må ikke samles/opdeles.
+ </text>
+ <panel.string name="can_resell">
Købt land i denne region må sælges videre
- </string>
- <string name="can_not_resell">
+ </panel.string>
+ <panel.string name="can_not_resell">
Købt land i denne region må ikke sælges videre
- </string>
- <string name="can_change">
+ </panel.string>
+ <panel.string name="can_change">
Købt jord i denne region må gerne samles eller opdeles.
- </string>
- <string name="can_not_change">
+ </panel.string>
+ <panel.string name="can_not_change">
Købt jord i denne region må íkke samles eller opdeles.
- </string>
+ </panel.string>
</panel>
<panel label="Objekter" name="land_objects_panel">
- <text type="string" length="1" name="parcel_object_bonus">
+ <text name="parcel_object_bonus">
Region objekt bonus faktor: [BONUS]
</text>
- <text type="string" length="1" name="Simulator primitive usage:">
+ <text name="Simulator primitive usage:">
Prims brugt i denne Sim:
</text>
- <text type="string" length="1" name="objects_available">
+ <text name="objects_available">
[COUNT] ud af [MAX] ([AVAILABLE] ledige)
</text>
- <string name="objects_available_text">
+ <panel.string name="objects_available_text">
[COUNT] ud af [MAX] ([AVAILABLE] ledige)
- </string>
- <string name="objects_deleted_text">
+ </panel.string>
+ <panel.string name="objects_deleted_text">
[COUNT] ud af [MAX] ([DELETED] bliver slettet)
- </string>
- <text type="string" length="1" name="Primitives parcel supports:">
+ </panel.string>
+ <text name="Primitives parcel supports:">
Prims til rådighed:
</text>
- <text type="string" length="1" name="object_contrib_text">
+ <text name="object_contrib_text">
[COUNT]
</text>
- <text type="string" length="1" name="Primitives on parcel:">
+ <text name="Primitives on parcel:">
Prims brugt på parcel:
</text>
- <text type="string" length="1" name="total_objects_text">
+ <text name="total_objects_text">
[COUNT]
</text>
- <text type="string" length="1" name="Owned by parcel owner:">
+ <text name="Owned by parcel owner:">
Ejet af Parcel ejer:
</text>
- <text type="string" length="1" name="owner_objects_text">
+ <text name="owner_objects_text">
[COUNT]
</text>
- <button label="Vis" label_selected="Vis" name="ShowOwner" />
- <button label="Returnér..." label_selected="Returnér..." name="ReturnOwner..."
- tool_tip="Returnér objekter til deres ejere." />
- <text type="string" length="1" name="Set to group:">
+ <button label="Vis" label_selected="Vis" name="ShowOwner"/>
+ <button label="Returnér..." label_selected="Returnér..." name="ReturnOwner..." tool_tip="Returnér objekter til deres ejere."/>
+ <text name="Set to group:">
Sat til gruppe:
</text>
- <text type="string" length="1" name="group_objects_text">
+ <text name="group_objects_text">
[COUNT]
</text>
- <button label="Vis" label_selected="Vis" name="ShowGroup" />
- <button label="Returnér..." label_selected="Returnér..." name="ReturnGroup..."
- tool_tip="Returnér objekter til deres ejere." />
- <text type="string" length="1" name="Owned by others:">
+ <button label="Vis" label_selected="Vis" name="ShowGroup"/>
+ <button label="Returnér..." label_selected="Returnér..." name="ReturnGroup..." tool_tip="Returnér objekter til deres ejere."/>
+ <text name="Owned by others:">
Ejet af andre:
</text>
- <text type="string" length="1" name="other_objects_text">
+ <text name="other_objects_text">
[COUNT]
</text>
- <button label="Vis" label_selected="Vis" name="ShowOther" />
- <button label="Returnér..." label_selected="Returnér..." name="ReturnOther..."
- tool_tip="Returnér objekter til deres ejere." />
- <text type="string" length="1" name="Selected / sat upon:">
+ <button label="Vis" label_selected="Vis" name="ShowOther"/>
+ <button label="Returnér..." label_selected="Returnér..." name="ReturnOther..." tool_tip="Returnér objekter til deres ejere."/>
+ <text name="Selected / sat upon:">
Valgt/siddet på:
</text>
- <text type="string" length="1" name="selected_objects_text">
+ <text name="selected_objects_text">
[COUNT]
</text>
- <text type="string" length="1" name="Autoreturn">
+ <text name="Autoreturn">
Autoreturnér andres objekter efter (minutter, 0 = aldrig):
</text>
- <text type="string" length="1" name="Object Owners:">
+ <text name="Object Owners:">
Objekt ejere:
</text>
- <button label="Gentegn liste" label_selected="Gentegn liste" name="Refresh List" />
- <button label="Returnér objekter..." label_selected="Returnér objekter..."
- name="Return objects..." />
+ <button label="Gentegn liste" label_selected="Gentegn liste" name="Refresh List"/>
+ <button label="Returnér objekter..." label_selected="Returnér objekter..." name="Return objects..."/>
<name_list name="owner list">
- <column label="Type" name="type" />
- <column label="Navn" name="name" />
- <column label="Antal" name="count" />
- <column label="Nyeste" name="mostrecent" />
+ <column label="Type" name="type"/>
+ <column label="Navn" name="name"/>
+ <column label="Antal" name="count"/>
+ <column label="Nyeste" name="mostrecent"/>
</name_list>
</panel>
<panel label="Indstillinger" name="land_options_panel">
- <text type="string" length="1" name="allow_label">
+ <text name="allow_label">
Tillad andre beboere at:
</text>
- <check_box label="Redigere terræn" name="edit land check"
- tool_tip="Hvis dette er valg, kan enhver redigere dit land. Det er bedst ikke at vælge her, da det altid er muligt for dig som ejer at ændre terræn på dit eget land." />
- <check_box label="Lave landemærker" name="check landmark" />
- <check_box label="Flyve" name="check fly"
- tool_tip="Hvis valgt, kan beboere flyve på dit land. Hvis ikke valgt kan beboere kun flyve ind på dit land og over dit land." />
- <text type="string" length="1" name="allow_label2">
+ <check_box label="Redigere terræn" name="edit land check" tool_tip="Hvis dette er valg, kan enhver redigere dit land. Det er bedst ikke at vælge her, da det altid er muligt for dig som ejer at ændre terræn på dit eget land."/>
+ <check_box label="Lave landemærker" name="check landmark"/>
+ <check_box label="Flyve" name="check fly" tool_tip="Hvis valgt, kan beboere flyve på dit land. Hvis ikke valgt kan beboere kun flyve ind på dit land og over dit land."/>
+ <text name="allow_label2" left="194">
Lave objekter:
</text>
- <check_box label="Alle beboere" name="edit objects check" />
- <check_box label="Gruppe" name="edit group objects check" />
- <text type="string" length="1" name="allow_label3">
+ <check_box label="Alle beboere" name="edit objects check"/>
+ <check_box label="Gruppe" name="edit group objects check"/>
+ <text name="allow_label3" left="170">
Anbringe objekter:
</text>
- <check_box label="Alle beboere" name="all object entry check" />
- <check_box label="Gruppe" name="group object entry check" />
- <text type="string" length="1" name="allow_label4">
+ <check_box label="Alle beboere" name="all object entry check"/>
+ <check_box label="Gruppe" name="group object entry check"/>
+ <text name="allow_label4" left="200">
Køre scripts:
</text>
- <check_box label="Alle beboere" name="check other scripts" />
- <check_box label="Gruppe" name="check group scripts" />
- <text type="string" length="1" name="land_options_label">
+ <check_box label="Alle beboere" name="check other scripts"/>
+ <check_box label="Gruppe" name="check group scripts"/>
+ <text name="land_options_label">
Land instillinger:
</text>
- <check_box label="Sikker (ingen skade)" name="check safe"
- tool_tip="Hvis valgt, er det ikke muligt at forårsage skade på andre beboere. Hvis fravalgt er det muligt at få skader (f.eks. ved kamp)." />
- <check_box label="Skub forbudt" name="PushRestrictCheck"
- tool_tip="Forhindrer scripts i at skubbe. Valg af denne mulighed, kan være nyttigt for at forhindre forstyrrende adfærd på dit land." />
- <check_box label="Vis sted i søgning (L$30/uge) i kategorien:" name="ShowDirectoryCheck"
- tool_tip="Lad dit parcel blive vist i søge resultaterne" />
+ <check_box label="Sikker (ingen skade)" name="check safe" tool_tip="Hvis valgt, er det ikke muligt at forårsage skade på andre beboere. Hvis fravalgt er det muligt at få skader (f.eks. ved kamp)."/>
+ <check_box label="Skub forbudt" name="PushRestrictCheck" tool_tip="Forhindrer scripts i at skubbe. Valg af denne mulighed, kan være nyttigt for at forhindre forstyrrende adfærd på dit land."/>
+ <check_box label="Vis sted i søgning (L$30/uge) i kategorien:" name="ShowDirectoryCheck" tool_tip="Lad dit parcel blive vist i søge resultaterne"/>
+ <panel.string name="search_enabled_tooltip">
+ Lad beboere se denne parcel i søgeresultater
+ </panel.string>
+ <panel.string name="search_disabled_small_tooltip">
+ Denne mulighed er ikke til stede da parcellens område er 128 m² eller mindre.
+Kun større parceller kan vises i søgning.
+ </panel.string>
+ <panel.string name="search_disabled_permissions_tooltip">
+ Dette valg er lukket da du ikke kan ændre på denne parcels opsætning.
+ </panel.string>
+ <combo_box name="land category with adult">
+ <combo_box.item name="item0" label="Enhver kategori"
+ />
+ <combo_box.item name="item1" label="Linden sted"
+ />
+ <combo_box.item name="item2" label="Adult"
+ />
+ <combo_box.item name="item3" label="Kunst &amp; kultur"
+ />
+ <combo_box.item name="item4" label="Business"
+ />
+ <combo_box.item name="item5" label="Uddannelse"
+ />
+ <combo_box.item name="item6" label="Spil"
+ />
+ <combo_box.item name="item7" label="Afslapning"
+ />
+ <combo_box.item name="item8" label="Nybegynder venligt"
+ />
+ <combo_box.item name="item9" label="Parker &amp; natur"
+ />
+ <combo_box.item name="item10" label="Beboelse"
+ />
+ <combo_box.item name="item11" label="Indkøb"
+ />
+ <combo_box.item name="item12" label="Andet"
+ />
+ </combo_box>
<combo_box name="land category">
- <combo_item name="AnyCategory">
- Alle kategorier
- </combo_item>
- <combo_item name="LindenLocation">
- Linden Location
- </combo_item>
-
-
- <combo_item name="Arts&amp;Culture">
- Kunst &amp; kultur
- </combo_item>
- <combo_item name="Business">
- Business
- </combo_item>
- <combo_item name="Educational">
- Uddannelse
- </combo_item>
- <combo_item name="Gaming">
- Spil
- </combo_item>
- <combo_item name="Hangout">
- Afslapning
- </combo_item>
- <combo_item name="NewcomerFriendly">
- Nybegynder venligt
- </combo_item>
- <combo_item name="Parks&amp;Nature">
- Parker &amp; natur
- </combo_item>
- <combo_item name="Residential">
- Beboelse
- </combo_item>
- <combo_item name="Shopping">
- Indkøb
- </combo_item>
- <combo_item name="Other">
- Andet
- </combo_item>
+ <combo_box.item name="item0" label="Enhver kategori" />
+ <combo_box.item name="item1" label="Linden sted" />
+ <combo_box.item name="item3" label="Kunst &amp; kultur" />
+ <combo_box.item name="item4" label="Business" />
+ <combo_box.item name="item5" label="Uddannelse" />
+ <combo_box.item name="item6" label="Spil" />
+ <combo_box.item name="item7" label="Afslapning" />
+ <combo_box.item name="item8" label="Nybegynder venligt" />
+ <combo_box.item name="item9" label="Parker &amp; natur" />
+ <combo_box.item name="item10" label="Beboelse" />
+ <combo_box.item name="item11" label="Indkøb" />
+ <combo_box.item name="item12" label="Andet" />
</combo_box>
- <button label="?" label_selected="?" name="?" />
- <check_box name="MatureCheck" />
- <text type="string" length="1" name="Snapshot:">
+ <button label="?" label_selected="?" name="?"/>
+ <check_box label="Mature indhold" name="MatureCheck" tool_tip=""/>
+ <panel.string name="mature_check_mature">
+ Mature indhold
+ </panel.string>
+ <panel.string name="mature_check_adult">
+ Adult indhold
+ </panel.string>
+ <panel.string name="mature_check_mature_tooltip">
+ Din parcel information eller indhold anses for at være &apos;adult&apos;.
+ </panel.string>
+ <panel.string name="mature_check_adult_tooltip">
+ Din parcel information eller indhold anses for at være &apos;adult&apos;.
+ </panel.string>
+ <text name="Snapshot:">
Foto:
</text>
- <texture_picker label="" name="snapshot_ctrl" tool_tip="Klik for at vælge et billede" />
- <text type="string" length="1" name="landing_point">
+ <texture_picker label="" name="snapshot_ctrl" tool_tip="Klik for at vælge et billede"/>
+ <text name="landing_point">
Landingspunkt: [LANDING]
</text>
- <string name="landing_point_none">
+ <panel.string name="landing_point_none">
(ingen)
- </string>
- <button label="Vælg" label_selected="Vælg" name="Set"
- tool_tip="Indstiller landingspunkt, hvor de besøgende ankommer. Sættes til din avatars aktuelle placering i denne parcel." />
- <button label="Fjern" label_selected="Fjern" name="Clear"
- tool_tip="Fjerner oplysning om landingspunkt." />
- <text type="string" length="1" name="Teleport Routing: ">
+ </panel.string>
+ <button label="Vælg" label_selected="Vælg" name="Set" tool_tip="Indstiller landingspunkt, hvor de besøgende ankommer. Sættes til din avatars aktuelle placering i denne parcel."/>
+ <button label="Fjern" label_selected="Fjern" name="Clear" tool_tip="Fjerner oplysning om landingspunkt."/>
+ <text name="Teleport Routing: ">
Teleport valg:
</text>
- <combo_box name="landing type"
- tool_tip="Vælg hvordan du vil håndtere teleporteringer til dit land.">
- <combo_item type="string" length="1" name="Blocked">
- Blokeret
- </combo_item>
- <combo_item type="string" length="1" name="LandingPoint">
- Landingspunkt
- </combo_item>
- <combo_item type="string" length="1" name="Anywhere">
- Hvor som helst
- </combo_item>
+ <combo_box name="landing type" tool_tip="Vælg hvordan du vil håndtere teleporteringer til dit land.">
+ <combo_box.item name="Blocked" label="Blokeret" />
+ <combo_box.item name="LandingPoint" label="Landingspunkt" />
+ <combo_box.item name="Anywhere" label="Hvor som helst" />
</combo_box>
- <string name="push_restrict_text">
+ <panel.string name="push_restrict_text">
Skub forbudt
- </string>
- <string name="push_restrict_region_text">
+ </panel.string>
+ <panel.string name="push_restrict_region_text">
Skub forbudt (Uanset region indstilling)
- </string>
+ </panel.string>
</panel>
<panel label="Medier" name="land_media_panel">
- <text type="string" length="1" name="with media:">
+ <text name="with media:" left="4">
Medie type:
</text>
- <combo_box name="media type"
- tool_tip="Specificer om URL-adressen er til en film, hjemmeside eller et andet medie." />
- <text type="string" length="1" name="at URL:">
+ <combo_box name="media type" tool_tip="Specificer om URL-adressen er til en film, hjemmeside eller et andet medie."/>
+ <text name="at URL:" left="4">
Medie URL:
</text>
- <button label="Vælg..." label_selected="Vælg..." name="set_media_url" />
- <text type="string" length="1" name="Description:">
+ <button label="Vælg..." label_selected="Vælg..." name="set_media_url"/>
+ <text name="Description:" left="4">
Beskrivelse:
</text>
- <line_editor name="url_description" tool_tip="Tekst vist ved siden af Afspil/Hent knappen" />
- <text type="string" length="1" name="Media texture:">
+ <line_editor name="url_description" tool_tip="Tekst vist ved siden af Afspil/Hent knappen"/>
+ <text name="Media texture:" left="4">
Erstat tekstur:
</text>
- <texture_picker label="" name="media texture" tool_tip="Klik for at vælge billede" />
- <text type="string" length="1" name="replace_texture_help">
+ <texture_picker label="" name="media texture" tool_tip="Klik for at vælge billede"/>
+ <text name="replace_texture_help">
(Objekter der har denne tekstur vil vise filmen eller
web-siden, efter du klikker på play knappen.)
</text>
- <text type="string" length="1" name="Options:">
+ <text name="Options:">
Medie valg:
</text>
- <check_box label="Auto skalér" name="media_auto_scale"
- tool_tip="Vælg denne mulighed for at skalere indholdet for dette parcel automatisk. Det kan være lidt langsommere og have lavere kvalitet, men ingen anden tekstur skalering eller tilpasning vil være nødvendigt." />
- <check_box label="Gentag afspil" name="media_loop"
- tool_tip="Gentager automatisk medie, når det er færdigt med at spille starter det automatisk forfra." />
- <check_box label="Skjul medie URL" name="hide_media_url"
- tool_tip="Klik her for at skjule medie adressen så det kun er dig og evt. parcel gruppens ejer/administratorer der kan se den." />
- <check_box label="Skjul musik URL" name="hide_music_url"
- tool_tip="Klik her for at skjule musik adressen så det kun er dig og evt. parcel gruppens ejer/administratorer der kan se den." />
- <text type="string" length="1" name="media_size"
- tool_tip="Størrelse for rendering af Web medie, benyt 0 for standard." width="105">
+ <check_box label="Auto skalér" name="media_auto_scale" tool_tip="Vælg denne mulighed for at skalere indholdet for dette parcel automatisk. Det kan være lidt langsommere og have lavere kvalitet, men ingen anden tekstur skalering eller tilpasning vil være nødvendigt."/>
+ <check_box label="Gentag afspil" name="media_loop" tool_tip="Gentager automatisk medie, når det er færdigt med at spille starter det automatisk forfra."/>
+ <check_box label="Skjul medie URL" name="hide_media_url" tool_tip="Klik her for at skjule medie adressen så det kun er dig og evt. parcel gruppens ejer/administratorer der kan se den."/>
+ <check_box label="Skjul musik URL" name="hide_music_url" tool_tip="Klik her for at skjule musik adressen så det kun er dig og evt. parcel gruppens ejer/administratorer der kan se den."/>
+ <text name="media_size" tool_tip="Størrelse for rendering af Web medie, benyt 0 for standard." width="105">
Medie Størrelse:
</text>
- <spinner name="media_size_width" left_delta="89"
- tool_tip="Størrelse for rendering af Web medie, benyt 0 for standard." />
- <spinner name="media_size_height"
- tool_tip="Størrelse for rendering af Web medie, benyt 0 for standard." />
- <text type="string" length="1" name="pixels">
+ <spinner left_delta="89" name="media_size_width" tool_tip="Størrelse for rendering af Web medie, benyt 0 for standard."/>
+ <spinner name="media_size_height" tool_tip="Størrelse for rendering af Web medie, benyt 0 for standard."/>
+ <text name="pixels">
pixels
</text>
- <text type="string" length="1" name="MusicURL:">
+ <text name="MusicURL:">
Musik URL:
</text>
- <text type="string" length="1" name="Sound:">
+ <text name="Sound:">
Lyd:
</text>
- <check_box label="Isolér lyde til denne parcel" name="check sound local" />
- <text type="string" length="1" name="Voice settings:">
+ <check_box label="Begræns lyde fra bevægelser og objekter til denne parcel" name="check sound local"/>
+ <button label="?" label_selected="?" name="?" left="400"/>
+ <text name="Voice settings:">
Stemme:
</text>
<radio_group name="parcel_voice_channel">
- <radio_item type="string" length="1" name="Estate">
- Brug Estate kanalen
- </radio_item>
- <radio_item type="string" length="1" name="Private">
- Brug en privat kanal
- </radio_item>
- <radio_item type="string" length="1" name="Disabled">
- Slå stemme chat fra på denne parcel
- </radio_item>
+ <radio_item name="Estate" label="Brug Estate kanalen" />
+ <radio_item name="Private" label="Brug en privat kanal" />
+ <radio_item name="Disabled" label="Slå stemme chat fra på denne parcel" />
</radio_group>
</panel>
<panel label="Adgang" name="land_access_panel">
- <text type="string" length="1" name="Limit access to this parcel to:">
+ <text name="Limit access to this parcel to:">
Adgang til denne parcel
</text>
- <check_box label="Tillad offentlig adgang" name="public_access" />
- <text type="string" length="1" name="Only Allow">
+ <check_box label="Tillad offentlig adgang" name="public_access"/>
+ <text name="Only Allow">
Blokér adgang for:
</text>
- <check_box label="Beboere der ikke har givet betalings oplysninger til Linden Lab"
- name="limit_payment"
- tool_tip="Blokér beboere der ikke har afgivet identifikationsoplysninger." />
- <check_box label="Beboere der ikke er godkendt som voksne" name="limit_age_verified"
- tool_tip="Blokér beboere der ikke har verificeret deres alder. Se support.secondlife.com for mere information." />
- <string name="estate_override">
+ <check_box label="Beboere der ikke har givet betalings oplysninger til Linden Lab" name="limit_payment" tool_tip="Blokér beboere der ikke har afgivet identifikationsoplysninger."/>
+ <check_box label="Beboere der ikke er godkendt som voksne" name="limit_age_verified" tool_tip="Blokér beboere der ikke har verificeret deres alder. Se support.secondlife.com for mere information."/>
+ <panel.string name="estate_override">
En eller flere af disse valg er indstillet på estate niveau
- </string>
- <check_box label="Tillad adgang til gruppen: [GROUP]" name="GroupCheck"
- tool_tip="Vælg gruppe under fanen &apos;generelt&apos;." />
- <check_box label="Sælg adgang til:" name="PassCheck"
- tool_tip="Tillader midlertidig adgang til denne parcel" />
+ </panel.string>
+ <check_box label="Tillad adgang til gruppen: [GROUP]" name="GroupCheck" tool_tip="Vælg gruppe under fanen &apos;generelt&apos;."/>
+ <check_box label="Sælg adgang til:" name="PassCheck" tool_tip="Tillader midlertidig adgang til denne parcel"/>
<combo_box name="pass_combo">
- <combo_item name="Anyone">
- Alle
- </combo_item>
- <combo_item name="Group">
- Gruppe
- </combo_item>
+ <combo_box.item name="Anyone" label="Alle" />
+ <combo_box.item name="Group" label="Gruppe" />
</combo_box>
- <spinner label="Pris i L$:" name="PriceSpin" />
- <spinner label="Timers adgang:" name="HoursSpin" />
+ <spinner label="Pris i L$:" name="PriceSpin"/>
+ <spinner label="Timers adgang:" name="HoursSpin"/>
<text label="Tillad altid" name="AllowedText">
Altid godkendte beboere
</text>
- <name_list name="AccessList" tool_tip="([LISTED] vist, [MAX] max)" />
- <button label="Tilføj..." label_selected="Tilføj..." name="add_allowed" />
- <button label="Fjern" label_selected="Fjern" name="remove_allowed" />
+ <name_list name="AccessList" tool_tip="([LISTED] vist, [MAX] max)"/>
+ <button label="Tilføj..." label_selected="Tilføj..." name="add_allowed"/>
+ <button label="Fjern" label_selected="Fjern" name="remove_allowed"/>
<text label="Blokér" name="BanCheck">
Blokerede beboere
</text>
- <name_list name="BannedList" tool_tip="([LISTED] vist, [MAX] max)" />
- <button label="Tilføj..." label_selected="Tilføj..." name="add_banned" />
- <button label="Fjern" label_selected="Fjern" name="remove_banned" />
+ <name_list name="BannedList" tool_tip="([LISTED] vist, [MAX] max)"/>
+ <button label="Tilføj..." label_selected="Tilføj..." name="add_banned"/>
+ <button label="Fjern" label_selected="Fjern" name="remove_banned"/>
</panel>
</tab_container>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_animation_preview.xml b/indra/newview/skins/default/xui/da/floater_animation_preview.xml
index 4ea7753457..8cb0eee601 100644
--- a/indra/newview/skins/default/xui/da/floater_animation_preview.xml
+++ b/indra/newview/skins/default/xui/da/floater_animation_preview.xml
@@ -9,138 +9,63 @@
<spinner label="Prioritet" name="priority"
tool_tip="Vælg hvilke andre animationer der har lavere prioritet end denne." />
<check_box label="Gentag" name="loop_check" tool_tip="Gentager animationen konstant." />
- <spinner label="Ind(%)" name="loop_in_point"
- tool_tip="Sætter punktet hvor gentagelsen genstarter fra." />
+ <spinner left="76" label_width="40" width="105" label="Ind(%)" name="loop_in_point" tool_tip="Sætter punktet hvor gentagelsen genstarter fra."/>
<spinner label="Ud (%)" name="loop_out_point"
tool_tip="Sætter punktet i animationen der afslutter gentagelsen." />
<text name="hand_label">
HÃ¥nd posering
</text>
<combo_box label="" name="hand_pose_combo"
- tool_tip="Kontrollerer hvad hænderne går i løbet af animationen.">
- <combo_item name="Spread">
- Spredt
- </combo_item>
- <combo_item name="Relaxed">
- Afslappet
- </combo_item>
- <combo_item name="PointBoth">
- Peg begge
- </combo_item>
- <combo_item name="Fist">
- Knytnæver
- </combo_item>
- <combo_item name="RelaxedLeft">
- Afslappet venstre
- </combo_item>
- <combo_item name="PointLeft">
- Peg venstre
- </combo_item>
- <combo_item name="FistLeft">
- Knytnæve venstre
- </combo_item>
- <combo_item name="RelaxedRight">
- Afslappet højre
- </combo_item>
- <combo_item name="PointRight">
- Peg højre
- </combo_item>
- <combo_item name="FistRight">
- Knytnæve højre
- </combo_item>
- <combo_item name="SaluteRight">
- Honnør højre
- </combo_item>
- <combo_item name="Typing">
- Skriver
- </combo_item>
- <combo_item name="PeaceRight">
- Fredstegn højre
- </combo_item>
+ tool_tip="Kontrollerer hvad hænderne går i løbet af animationen." width="140">
+ <combo_box.item name="Spread" label="Spredt" />
+ <combo_box.item name="Relaxed" label="Afslappet" />
+ <combo_box.item name="PointBoth" label="Peg begge" />
+ <combo_box.item name="Fist" label="Knytnæver" />
+ <combo_box.item name="RelaxedLeft" label="Afslappet venstre" />
+ <combo_box.item name="PointLeft" label="Peg venstre" />
+ <combo_box.item name="FistLeft" label="Knytnæve venstre" />
+ <combo_box.item name="RelaxedRight" label="Afslappet højre" />
+ <combo_box.item name="PointRight" label="Peg højre" />
+ <combo_box.item name="FistRight" label="Knytnæve højre" />
+ <combo_box.item name="SaluteRight" label="Honnør højre" />
+ <combo_box.item name="Typing" label="Skriver" />
+ <combo_box.item name="PeaceRight" label="Fredstegn højre" />
</combo_box>
<text name="emote_label">
Ansigtsudtryk
</text>
<combo_box label="" name="emote_combo"
- tool_tip="Angiver hvad ansigtet gør under animationen">
- <combo_item name="[None]">
- [Intet]
- </combo_item>
- <combo_item name="Aaaaah">
- Aaaaah
- </combo_item>
- <combo_item name="Afraid">
- Bange
- </combo_item>
- <combo_item name="Angry">
- Vred
- </combo_item>
- <combo_item name="BigSmile">
- Stort smil
- </combo_item>
- <combo_item name="Bored">
- Keder sig
- </combo_item>
- <combo_item name="Cry">
- Græder
- </combo_item>
- <combo_item name="Disdain">
- Forarget
- </combo_item>
- <combo_item name="Embarrassed">
- Flov
- </combo_item>
- <combo_item name="Frown">
- Skuler
- </combo_item>
- <combo_item name="Kiss">
- Kysser
- </combo_item>
- <combo_item name="Laugh">
- Griner
- </combo_item>
- <combo_item name="Plllppt">
- Plllppt
- </combo_item>
- <combo_item name="Repulsed">
- Frastødt
- </combo_item>
- <combo_item name="Sad">
- Ked af det
- </combo_item>
- <combo_item name="Shrug">
- Skuldertræk
- </combo_item>
- <combo_item name="Smile">
- Smiler
- </combo_item>
- <combo_item name="Surprise">
- Overrasket
- </combo_item>
- <combo_item name="Wink">
- Blinker
- </combo_item>
- <combo_item name="Worry">
- Bekymret
- </combo_item>
+ tool_tip="Angiver hvad ansigtet gør under animationen" width="140">
+ <combo_box.item name="[None]" label="Intet]" />
+ <combo_box.item name="Aaaaah" label="Aaaaah" />
+ <combo_box.item name="Afraid" label="Bange" />
+ <combo_box.item name="Angry" label="Vred" />
+ <combo_box.item name="BigSmile" label="Stort smil" />
+ <combo_box.item name="Bored" label="Keder sig" />
+ <combo_box.item name="Cry" label="Græder" />
+ <combo_box.item name="Disdain" label="Forarget" />
+ <combo_box.item name="Embarrassed" label="Flov" />
+ <combo_box.item name="Frown" label="Skuler" />
+ <combo_box.item name="Kiss" label="Kysser" />
+ <combo_box.item name="Laugh" label="Griner" />
+ <combo_box.item name="Plllppt" label="Plllppt" />
+ <combo_box.item name="Repulsed" label="Frastødt" />
+ <combo_box.item name="Sad" label="Ked af det" />
+ <combo_box.item name="Shrug" label="Skuldertræk" />
+ <combo_box.item name="Smile" label="Smiler" />
+ <combo_box.item name="Surprise" label="Overrasket" />
+ <combo_box.item name="Wink" label="Blinker" />
+ <combo_box.item name="Worry" label="Bekymret" />
</combo_box>
<text name="preview_label">
Vis mens
</text>
<combo_box label="" name="preview_base_anim"
- tool_tip="Se hvordan animation ser ud i forskellige typiske avatar-situationer.">
- <combo_item name="Standing">
- Står
- </combo_item>
- <combo_item name="Walking">
- GÃ¥r
- </combo_item>
- <combo_item name="Sitting">
- Sidder
- </combo_item>
- <combo_item name="Flying">
- Flyver
- </combo_item>
+ tool_tip="Se hvordan animation ser ud i forskellige typiske avatar-situationer." width="140">
+ <combo_box.item name="Standing" label="Står" />
+ <combo_box.item name="Walking" label="GÃ¥r" />
+ <combo_box.item name="Sitting" label="Sidder" />
+ <combo_box.item name="Flying" label="Flyver" />
</combo_box>
<spinner label="start (sec)" name="ease_in_time"
tool_tip="Tid i sekunder animationen bruger på at komme i gang." />
@@ -151,8 +76,8 @@
<slider label="" name="playback_slider" />
<text name="bad_animation_text">
Kan ikke læse animations fil.
-
- Vi anbefaler BVH filer der er exporteret fra Poser 4.
+
+Vi anbefaler BVH filer der er exporteret fra Poser 4.
</text>
<button label="Annullér" name="cancel_btn" />
<button label="Hent (L$[AMOUNT])" name="ok_btn" />
diff --git a/indra/newview/skins/default/xui/da/floater_auction.xml b/indra/newview/skins/default/xui/da/floater_auction.xml
index f981242f8a..8f793557be 100644
--- a/indra/newview/skins/default/xui/da/floater_auction.xml
+++ b/indra/newview/skins/default/xui/da/floater_auction.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_auction" title="Start Linden land salg">
+<floater name="floater_auction" title="START LINDEN LAND SALG">
<check_box label="Vis også gul aftegning af område" name="fence_check" />
<button label="Foto" label_selected="Foto" name="snapshot_btn" />
<button label="OK" label_selected="OK" name="ok_btn" />
diff --git a/indra/newview/skins/default/xui/da/floater_avatar_picker.xml b/indra/newview/skins/default/xui/da/floater_avatar_picker.xml
index d2c8f3a003..0ddb6e9dbe 100644
--- a/indra/newview/skins/default/xui/da/floater_avatar_picker.xml
+++ b/indra/newview/skins/default/xui/da/floater_avatar_picker.xml
@@ -1,15 +1,40 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="avatarpicker" title="Vælg beboer">
- <text name="instruct_search_resident_name">
- Skriv en del eller hele navnet på beboeren:
- </text>
- <button label="Find" label_selected="Find" name="Find" />
- <text name="Or select their calling card:">
- Eller vælg deres visitkort:
- </text>
- <button label="Luk" label_selected="Luk" name="Close" />
- <button label="Vælg" label_selected="Vælg" name="Select" />
- <string name="NotFound">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="avatarpicker" title="VÆLG BEBOER">
+ <tab_container name="ResidentChooserTabs">
+ <panel label="Søg" name="SearchPanel">
+ <text name="InstructSearchResidentName">
+ Indtast en del af beboerens navn:
+ </text>
+ <button label="Find" label_selected="Find" name="Find"/>
+ </panel>
+ <panel label="Visitkort" name="CallingCardsPanel">
+ <text name="InstructSelectCallingCard">
+ Vælg et visitkort:
+ </text>
+ </panel>
+ <panel label="Nær ved mig" name="NearMePanel">
+ <text name="InstructSelectResident">
+ Vælg beboere i nærheden:
+ </text>
+ <button label="Gentegn liste" label_selected="Gentegn liste" name="Refresh"/>
+ <slider label="Område" name="near_me_range"/>
+ <text name="meters">
+ meter
+ </text>
+ </panel>
+ </tab_container>
+ <button label="Vælg" label_selected="Vælg" name="Select"/>
+ <button label="Annullér" label_selected="Annullér" name="Cancel"/>
+ <string name="not_found">
&apos;[TEXT]&apos; ikke fundet
</string>
+ <string name="no_one_near">
+ Ingen i nærheden
+ </string>
+ <string name="no_results">
+ Ingen resultater
+ </string>
+ <string name="searching">
+ Søger...
+ </string>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_avatar_textures.xml b/indra/newview/skins/default/xui/da/floater_avatar_textures.xml
index e3a736b200..27bfa367f6 100644
--- a/indra/newview/skins/default/xui/da/floater_avatar_textures.xml
+++ b/indra/newview/skins/default/xui/da/floater_avatar_textures.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="avatar_texture_debug" title="Avatar teksturer">
+<floater name="avatar_texture_debug" title="AVATAR TEKSTURER">
<text name="baked_label">
Faste teksturer
</text>
diff --git a/indra/newview/skins/default/xui/da/floater_beacons.xml b/indra/newview/skins/default/xui/da/floater_beacons.xml
index 27422761d9..18bc7aeb31 100644
--- a/indra/newview/skins/default/xui/da/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/da/floater_beacons.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="beacons" title="Pejlelys">
+<floater name="beacons" title="PEJLELYS">
<panel name="beacons_panel">
<check_box label="Kun scriptede objekter med &quot;rør&quot;" name="touch_only" />
<check_box label="Scriptede objekter" name="scripted" />
@@ -8,7 +8,7 @@
<check_box label="Partikel kilder" name="particles" />
<check_box label="Rendér highlights" name="highlights" />
<check_box label="Rendér pejlelys" name="beacons" />
- <text type="string" length="1" name="beacon_width_label">
+ <text name="beacon_width_label">
Pejlelys bredde:
</text>
</panel>
diff --git a/indra/newview/skins/default/xui/da/floater_build_options.xml b/indra/newview/skins/default/xui/da/floater_build_options.xml
index 7e5b61bd84..7eb0d4c035 100644
--- a/indra/newview/skins/default/xui/da/floater_build_options.xml
+++ b/indra/newview/skins/default/xui/da/floater_build_options.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="build options floater" title="Gitter indstillinger">
- <spinner label="Gitter enhed (meter)" name="GridResolution" />
- <spinner label="Gitter rækkevidde (meter)" name="GridDrawSize" />
+<floater name="build options floater" title="GITTER INDSTILLINGER">
+ <spinner label="Gitter enhed (meter)" name="GridResolution" width="200" label_width="136"/>
+ <spinner label="Gitter rækkevidde (meter)" name="GridDrawSize" width="200" label_width="136"/>
<check_box label="Aktiver låsning til under-enheder" name="GridSubUnit" />
<check_box label="Vis &apos;cross sections&apos;" name="GridCrossSection" />
<slider label="Gitter synlighed" name="GridOpacity" />
diff --git a/indra/newview/skins/default/xui/da/floater_bulk_perms.xml b/indra/newview/skins/default/xui/da/floater_bulk_perms.xml
new file mode 100644
index 0000000000..9cf44d6479
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/floater_bulk_perms.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floaterbulkperms" title="MASSE-ÆNDRING AF RETTIGHEDER PÅ INDHOLD">
+ <text name="applyto">
+ Indholdstyper
+ </text>
+ <check_box label="Animationer" name="check_animation"/>
+ <check_box label="Kropsdele" name="check_bodypart"/>
+ <check_box label="Tøj" name="check_clothing"/>
+ <check_box label="Bevægelser" name="check_gesture"/>
+ <check_box label="Landemærker" name="check_landmark"/>
+ <check_box label="Noter" name="check_notecard"/>
+ <check_box label="Objekter" name="check_object"/>
+ <check_box label="Scripts" name="check_script"/>
+ <check_box label="Lyde" name="check_sound"/>
+ <check_box label="Teksturer" name="check_texture"/>
+ <button label="Vælg alle" label_selected="Alle" name="check_all"/>
+ <button label="Fravælg alle" label_selected="Ingen" name="check_none"/>
+ <text name="newperms">
+ Nye rettigheder
+ </text>
+ <check_box label="Del med gruppe" name="share_with_group"/>
+ <check_box label="Tillad enhver at kopiere" name="everyone_copy"/>
+ <text name="NextOwnerLabel">
+ Næste ejer kan:
+ </text>
+ <check_box label="Redigere" name="next_owner_modify"/>
+ <check_box label="Kopiére" name="next_owner_copy"/>
+ <check_box label="Sælge/Give væk" name="next_owner_transfer"/>
+ <button label="Hjælp" name="help"/>
+ <button label="Gem" name="apply"/>
+ <button label="Luk" name="close"/>
+ <string name="nothing_to_modify_text">
+ Valgte indeholder ikke noget som kan redigeres.
+ </string>
+ <string name="status_text">
+ Sætter rettigheder på [NAME]
+ </string>
+ <string name="start_text">
+ Påbegynder forespørgsel på rettighedsændringer...
+ </string>
+ <string name="done_text">
+ Afsluttet forespørgsel på rettighedsændringer.
+ </string>
+</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_bumps.xml b/indra/newview/skins/default/xui/da/floater_bumps.xml
index 62a1cd9e5c..704e6c3608 100644
--- a/indra/newview/skins/default/xui/da/floater_bumps.xml
+++ b/indra/newview/skins/default/xui/da/floater_bumps.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_bumps" title="Bump, skub &amp; slag">
+<floater name="floater_bumps" title="BUMP, SKUB &amp; SLAG">
<string name="none_detected">
Ingen registreret
</string>
diff --git a/indra/newview/skins/default/xui/da/floater_buy_contents.xml b/indra/newview/skins/default/xui/da/floater_buy_contents.xml
index c9df548747..8dccf32304 100644
--- a/indra/newview/skins/default/xui/da/floater_buy_contents.xml
+++ b/indra/newview/skins/default/xui/da/floater_buy_contents.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_buy_contents" title="Køb indhold">
+<floater name="floater_buy_contents" title="KØB INDHOLD">
<text name="contains_text">
[NAME] indeholder:
</text>
diff --git a/indra/newview/skins/default/xui/da/floater_buy_currency.xml b/indra/newview/skins/default/xui/da/floater_buy_currency.xml
index da2e7dbd66..d1fca8984d 100644
--- a/indra/newview/skins/default/xui/da/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/da/floater_buy_currency.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="buy currency" title="Køb valuta">
+<floater name="buy currency" title="KØB VALUTA">
<text name="info_buying">
Køber valuta:
</text>
@@ -29,7 +29,7 @@
1234
</line_editor>
<text name="currency_est">
- for ca. US$ [USD]
+ for ca. [LOCALAMOUNT]
</text>
<text name="getting_data">
Henter data...
@@ -63,6 +63,6 @@ og prøv igen.
<button label="Annullér" name="cancel_btn" />
<button label="Køb" name="buy_btn" />
<string name="buy_currency">
- Buy L$ [LINDENS] for approx. US$ [USD]
+ Køb L$ [LINDENS] for ca. [LOCALAMOUNT]
</string>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_buy_land.xml b/indra/newview/skins/default/xui/da/floater_buy_land.xml
index 9ca0c16bd3..71e6eaa7f7 100644
--- a/indra/newview/skins/default/xui/da/floater_buy_land.xml
+++ b/indra/newview/skins/default/xui/da/floater_buy_land.xml
@@ -1,11 +1,17 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="buy land" title="Køb land">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="buy land" title="KØB LAND">
<text name="region_name_label">
Region:
</text>
<text name="region_name_text">
(ukendt)
</text>
+ <text name="region_type_label">
+ Type:
+ </text>
+ <text name="region_type_text">
+ (ukendt)
+ </text>
<text name="estate_name_label">
Estate:
</text>
@@ -22,35 +28,38 @@
Købt land i denne region:
</text>
<text name="resellable_clause">
- Købt land i denne region kan eller kan ikke videresælges.
+ Kan eller kan ikke videresælges.
</text>
<text name="changeable_clause">
- kan eller kan ikke samles eller opdeles.
+ Må eller må ikke samles eller opdeles.
</text>
<text name="covenant_text">
Du skal acceptere Estate reglerne:
</text>
+ <text left="470" name="covenant_timestamp_text"/>
<text_editor name="covenant_editor">
Indlæser...
</text_editor>
- <check_box label="Jeg acceptere betingelserne der er beskrevet." name="agree_covenant" />
+ <check_box label="Jeg acceptere betingelserne der er beskrevet." name="agree_covenant"/>
<text name="info_parcel_label">
Parcel:
</text>
- <text name="info_parcel" left_delta="62">
+ <text left_delta="62" name="info_parcel">
Scotopteryx 138,204
</text>
<text name="info_size_label" width="60">
Størrelse:
</text>
- <text name="info_size" left_delta="62">
+ <text left_delta="62" name="info_size">
1024 m²
</text>
<text name="info_price_label">
Pris:
</text>
- <text name="info_price" left_delta="62">
- L$ 1500, objekter inkluderet
+ <text left_delta="62" name="info_price">
+ L$ 1500
+(L$ 1.1/m²)
+sælges med objekter
</text>
<text name="info_action">
Køb af dette land vil:
@@ -58,7 +67,7 @@
<text name="error_message">
Noget er ikke rigtigt.
</text>
- <button label="Go to website" name="error_web" />
+ <button label="Go to website" name="error_web"/>
<text name="account_action">
Opgrader dig til premium medlemsskab.
</text>
@@ -66,22 +75,16 @@
Kun premium medlemmer kan eje land.
</text>
<combo_box name="account_level">
- <combo_item name="US$9.95/month,billedmonthly">
- US$9.95/md, månedlig afregning
- </combo_item>
- <combo_item name="US$7.50/month,billedquarterly">
- US$7.50/md, kvartalsvis afregning
- </combo_item>
- <combo_item name="US$6.00/month,billedannually">
- US$6.00/md, årlig afregning
- </combo_item>
+ <combo_box.item name="US$9.95/month,billedmonthly" label="US$9.95/md, månedlig afregning" />
+ <combo_box.item name="US$7.50/month,billedquarterly" label="US$7.50/md, kvartalsvis afregning" />
+ <combo_box.item name="US$6.00/month,billedannually" label="US$6.00/md, årlig afregning" />
</combo_box>
<text name="land_use_action">
Forøg dine månedlige arealanvendelse gebyrer til US $ 40/måned.
</text>
<text name="land_use_reason">
- Du har 1.309 kvadratmeter jord.
-Dette parcel er på 512 kvadratmeter jord.
+ You hold 1309 m² of land.
+This parcel is 512 m² of land.
</text>
<text name="purchase_action">
Betal Joe Resident L$ 4000 dette areal
@@ -101,10 +104,9 @@ Dette parcel er på 512 kvadratmeter jord.
<text name="currency_balance">
Du har L$2,100.
</text>
- <check_box label="Fjern [AMOUNT] kvadratmeter af bidrag fra gruppe."
- name="remove_contribution" />
- <button label="K&#248;b" name="buy_btn" />
- <button label="Annullér" name="cancel_btn" />
+ <check_box label="Fjern [AMOUNT] kvadratmeter af bidrag fra gruppe." name="remove_contribution"/>
+ <button label="Køb" name="buy_btn"/>
+ <button label="Annullér" name="cancel_btn"/>
<string name="can_resell">
Kan videresælges.
</string>
@@ -161,7 +163,7 @@ Prøv at vælge et mindre område.
Køb af dette areal vil:
</string>
<string name="buying_for_group">
- Køb jord til gruppe:
+ Køb af dette areal vil:
</string>
<string name="cannot_buy_now">
Kan ikke købe nu:
@@ -179,30 +181,38 @@ Prøv at vælge et mindre område.
Din konto kan eje jord.
</string>
<string name="land_holdings">
- Du har [BUYER] kvadratmeter jord.
+ Du har [BUYER] m² jord.
</string>
<string name="pay_to_for_land">
Betal L$ [AMOUNT] til [SELLER] for dette stykke jord
</string>
<string name="buy_for_US">
- Køb L$ [AMOUNT] for omkring US$ [AMOUNT2] ,
+ Køb L$ [AMOUNT] for ca. US$ [AMOUNT2],
</string>
<string name="parcel_meters">
- Dette parcel er [AMOUNT] kvadratmeter.
+ Denne parcel er [AMOUNT] m².
</string>
<string name="premium_land">
- Dette stykke jord er premium, og vil tælle som [AMOUNT] kvadratmeter.
+ Dette stykke jord er premium, og vil tælle som [AMOUNT] m².
</string>
<string name="discounted_land">
- Dette stykke jord er på tilbud, og vil tælle som [AMOUNT] kvadratmeter.
+ Dette stykke jord er på tilbud, og vil tælle som [AMOUNT] m².
</string>
<string name="meters_supports_object">
[AMOUNT] m²
-indeholder [AMOUNT2] objekter
+kan indeholder [AMOUNT2] objekter
</string>
<string name="sold_with_objects">
solgt med objekter
</string>
+ <string name="sold_without_objects">
+ objekter ikke inkluderet
+ </string>
+ <string name="info_price_string">
+ L$ [PRICE]
+(L$ [PRICE_PER_SQM]/m²)
+[SOLD_WITH_OBJECTS]
+ </string>
<string name="insufficient_land_credits">
Gruppen [GROUP] skal bruge nok tildelt jord brugs
kredit for at dække dette parcel før købet vil blive
diff --git a/indra/newview/skins/default/xui/da/floater_buy_object.xml b/indra/newview/skins/default/xui/da/floater_buy_object.xml
index f0e22c8eee..266753902b 100644
--- a/indra/newview/skins/default/xui/da/floater_buy_object.xml
+++ b/indra/newview/skins/default/xui/da/floater_buy_object.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="contents" title="Køb kopi af objekt">
+<floater name="contents" title="KØB KOPI AF OBJEKT">
<text name="contents_text">
og dets indhold:
</text>
diff --git a/indra/newview/skins/default/xui/da/floater_camera.xml b/indra/newview/skins/default/xui/da/floater_camera.xml
index 0eb090d2e4..c52f7ab832 100644
--- a/indra/newview/skins/default/xui/da/floater_camera.xml
+++ b/indra/newview/skins/default/xui/da/floater_camera.xml
@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="move floater" title="">
- <string name="rotate_tooltip">
+<floater name="camera_floater" title="">
+ <floater.string name="rotate_tooltip">
Roter kamera omkring fokus
- </string>
- <string name="zoom_tooltip">
+ </floater.string>
+ <floater.string name="zoom_tooltip">
Zoom kamera mod fokus
- </string>
- <string name="move_tooltip">
+ </floater.string>
+ <floater.string name="move_tooltip">
Flyt kamera op og ned, til venstre og højre
- </string>
+ </floater.string>
+ <panel name="controls">
+ <joystick_track name="cam_track_stick" tool_tip="Flyt kamera op og ned, til venstre og højre"/>
+ <joystick_zoom name="zoom" tool_tip="Zoom kamera mod fokus"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_choose_group.xml b/indra/newview/skins/default/xui/da/floater_choose_group.xml
index 01c5bf3367..9f02f281db 100644
--- a/indra/newview/skins/default/xui/da/floater_choose_group.xml
+++ b/indra/newview/skins/default/xui/da/floater_choose_group.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="groups" title="Grupper">
+<floater name="groups" title="GRUPPER">
<text name="groupdesc">
Vælg en gruppe:
</text>
diff --git a/indra/newview/skins/default/xui/da/floater_color_picker.xml b/indra/newview/skins/default/xui/da/floater_color_picker.xml
index e6cc5774ed..d0a47b76e0 100644
--- a/indra/newview/skins/default/xui/da/floater_color_picker.xml
+++ b/indra/newview/skins/default/xui/da/floater_color_picker.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="ColorPicker" title="Farve vælger">
+<floater name="ColorPicker" title="FARVE VÆLGER">
<text name="r_val_text">
Rød:
</text>
@@ -26,6 +26,6 @@
Nuværende Farve:
</text>
<text name="(Drag below to save.)">
- (Træk ned og gem.)
+ (Træk ned og gem)
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_customize.xml b/indra/newview/skins/default/xui/da/floater_customize.xml
index 0f6a59eb4a..b2409f1682 100644
--- a/indra/newview/skins/default/xui/da/floater_customize.xml
+++ b/indra/newview/skins/default/xui/da/floater_customize.xml
@@ -1,447 +1,479 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater customize" title="Appearance">
- <tab_container name="customize tab container">
- <panel label="Krops Dele" name="body_parts_placeholder" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater customize" title="APPEARANCE" width="509">
+ <tab_container name="customize tab container" width="507">
+ <placeholder label="Krops Dele" name="body_parts_placeholder"/>
<panel label="Kropsbygning" name="Shape">
- <button label="Annullér" label_selected="Annullér" name="Revert" />
- <button label="Krop" label_selected="Krop" name="Body" />
- <button label="Hoved" label_selected="Hoved" name="Head" />
- <button label="Øjne" label_selected="Øjne" name="Eyes" />
- <button label="Ører" label_selected="Ører" name="Ears" />
- <button label="Næse" label_selected="Næse" name="Nose" />
- <button label="Mund" label_selected="Mund" name="Mouth" />
- <button label="Kinder" label_selected="Kinder" name="Chin" />
- <button label="Overkrop" label_selected="Overkrop" name="Torso" />
- <button label="Ben" label_selected="Ben" name="Legs" />
+ <button label="Annullér" label_selected="Annullér" name="Revert"/>
+ <button label="Krop" label_selected="Krop" name="Body"/>
+ <button label="Hoved" label_selected="Hoved" name="Head"/>
+ <button label="Øjne" label_selected="Øjne" name="Eyes"/>
+ <button label="Ører" label_selected="Ører" name="Ears"/>
+ <button label="Næse" label_selected="Næse" name="Nose"/>
+ <button label="Mund" label_selected="Mund" name="Mouth"/>
+ <button label="Kinder" label_selected="Kinder" name="Chin"/>
+ <button label="Overkrop" label_selected="Overkrop" name="Torso"/>
+ <button label="Ben" label_selected="Ben" name="Legs"/>
<radio_group name="sex radio">
- <radio_item type="string" length="1" name="radio">
- Kvinde
- </radio_item>
- <radio_item type="string" length="1" name="radio2">
- Mand
- </radio_item>
+ <radio_item name="radio" label="Kvinde" />
+ <radio_item name="radio2" label="Mand" />
</radio_group>
- <button label="Tilfældig" label_selected="Tilfældig" name="Randomize" />
- <text type="string" length="1" name="title">
+ <text name="title">
[DESC]
</text>
- <text type="string" length="1" name="title_no_modify">
+ <text name="title_no_modify">
[DESC]: Kan ikke redigeres
</text>
- <text type="string" length="1" name="title_loading">
+ <text name="title_loading">
[DESC]: indlæser...
</text>
- <text type="string" length="1" name="title_not_worn">
+ <text name="title_not_worn">
[DESC]: ikke båret
</text>
- <text type="string" length="1" name="path">
+ <text name="path">
Fundet i [PATH]
</text>
- <text type="string" length="1" name="not worn instructions">
+ <text name="not worn instructions">
Vælg en ny krop ved at trække en sådan fra din beholdning
-over på din avatar. Du kan også oprette en fra bunden og bagefter &apos;tage den på&apos;.
+over på din avatar. Du kan også oprette en fra bunden
+og bagefter &apos;tage den på&apos;.
</text>
- <text type="string" length="1" name="no modify instructions">
+ <text name="no modify instructions">
Du har ikke rettigheder til at redigere denne del.
</text>
- <button label="Lav ny krop" label_selected="Lav ny krop" name="Create New" />
- <button label="Tag af" label_selected="Tag af" name="Take Off" />
- <button label="Gem" label_selected="Gem" name="Save" />
- <button label="Gem som" label_selected="Gem som" name="Save As" />
+ <text name="Item Action Label">
+ Figur:
+ </text>
+ <button label="Lav ny krop" label_selected="Lav ny krop" name="Create New"/>
+ <button label="Gem" label_selected="Gem" name="Save"/>
+ <button label="Gem som..." label_selected="Gem som..." name="Save As"/>
</panel>
<panel label="Hud" name="Skin">
- <button label="Hudfarve" label_selected="Hudfarve" name="Skin Color" />
- <button label="Detaljer" label_selected="Detaljer" name="Face Detail" />
- <button label="Sminke" label_selected="Sminke" name="Makeup" />
- <button label="Kropsdetaljer" label_selected="Kropsdetaljer" name="Body Detail" />
- <text type="string" length="1" name="title">
+ <button label="Hudfarve" label_selected="Hudfarve" name="Skin Color"/>
+ <button label="Detaljer" label_selected="Detaljer" name="Face Detail"/>
+ <button label="Sminke" label_selected="Sminke" name="Makeup"/>
+ <button label="Kropsdetaljer" label_selected="Kropsdetaljer" name="Body Detail"/>
+ <text name="title">
[DESC]
</text>
- <text type="string" length="1" name="title_no_modify">
+ <text name="title_no_modify">
[DESC]: Kan ikke redigeres
</text>
- <text type="string" length="1" name="title_loading">
+ <text name="title_loading">
[DESC]: indlæser...
</text>
- <text type="string" length="1" name="title_not_worn">
+ <text name="title_not_worn">
[DESC]: ikke båret
</text>
- <text type="string" length="1" name="path">
+ <text name="path">
Fundet i [PATH]
</text>
- <text type="string" length="1" name="not worn instructions">
+ <text name="not worn instructions">
Tag en ny hud på ved at trække en sådan fra din beholdning
-over på din avatar. Du kan også oprette en hud fra bunden og bagefter &apos;tage den på&apos;.
+over på din avatar. Du kan også oprette en hud fra bunden
+og bagefter &apos;tage den på&apos;.
</text>
- <text type="string" length="1" name="no modify instructions">
+ <text name="no modify instructions">
Du har ikke rettigheder til at redigere denne del.
</text>
- <texture_picker label="Tatoveringer hoved" name="Head Tattoos" />
- <texture_picker label="Tatoveringer overkrop" name="Upper Tattoos" />
- <texture_picker label="Tatoveringer underkrop" name="Lower Tattoos" />
- <button label="Tilfældig" label_selected="Tilfældig" name="Randomize" />
- <button label="Lav ny hud" label_selected="Lav nyt hud" name="Create New" />
- <button label="Tag af" label_selected="Tag af" name="Take Off" />
- <button label="Gem" label_selected="Gem" name="Save" />
- <button label="Gem som" label_selected="Gem som" name="Save As" />
- <button label="Annullér" label_selected="Annullér" name="Revert" />
+ <text name="Item Action Label">
+ Hud:
+ </text>
+ <texture_picker width="98" label="Tatoveringer hoved" name="Head Tattoos" tool_tip="Klik for at vælge et billede"/>
+ <texture_picker width="98" label="Tatover. overkrop" name="Upper Tattoos" tool_tip="Klik for at vælge et billede"/>
+ <texture_picker width="98" label="Tatover. underkrop" name="Lower Tattoos" tool_tip="Klik for at vælge et billede"/>
+ <button label="Lav ny hud" label_selected="Lav nyt hud" name="Create New"/>
+ <button label="Gem" label_selected="Gem" name="Save"/>
+ <button label="Gem som..." label_selected="Gem som..." name="Save As"/>
+ <button label="Annullér" label_selected="Annullér" name="Revert"/>
</panel>
<panel label="HÃ¥r" name="Hair">
- <button label="Farve" label_selected="Farve" name="Color" />
- <button label="Stil" label_selected="Stil" name="Style" />
- <button label="Øjenbryn" label_selected="Øjenbryn" name="Eyebrows" />
- <button label="Skæg" label_selected="Skæg" name="Facial" />
- <text type="string" length="1" name="title">
+ <button label="Farve" label_selected="Farve" name="Color"/>
+ <button label="Stil" label_selected="Stil" name="Style"/>
+ <button label="Øjenbryn" label_selected="Øjenbryn" name="Eyebrows"/>
+ <button label="Skæg" label_selected="Skæg" name="Facial"/>
+ <text name="title">
[DESC]
</text>
- <text type="string" length="1" name="title_no_modify">
+ <text name="title_no_modify">
[DESC]: kan ikke redigeres
</text>
- <text type="string" length="1" name="title_loading">
+ <text name="title_loading">
[DESC]: indlæser...
</text>
- <text type="string" length="1" name="title_not_worn">
+ <text name="title_not_worn">
[DESC]: ikke båret
</text>
- <text type="string" length="1" name="path">
+ <text name="path">
Fundet i [PATH]
</text>
- <text type="string" length="1" name="not worn instructions">
+ <text name="not worn instructions">
Tag et ny hår på ved at trække et fra din beholdning
-over på din avatar. Du kan også oprette et nyt hår fra bunden og bagefter &apos;tage det på&apos;.
+over på din avatar. Du kan også oprette et nyt hår fra bunden
+og bagefter &apos;tage det på&apos;.
</text>
- <text type="string" length="1" name="no modify instructions">
+ <text name="no modify instructions">
Du har ikke rettigheder til at redigere denne del.
</text>
- <texture_picker label="Tekstur" name="Texture" />
- <button label="Tilfældig" label_selected="Tilfældig" name="Randomize" />
- <button label="Lav nyt hår" label_selected="Lav nyt hår" name="Create New" />
- <button label="Tag af" label_selected="Tag af" name="Take Off" />
- <button label="Gem" label_selected="Gem" name="Save" />
- <button label="Gem som" label_selected="Gem som" name="Save As" />
- <button label="Annullér" label_selected="Annullér" name="Revert" />
+ <text name="Item Action Label">
+ HÃ¥r:
+ </text>
+ <texture_picker label="Tekstur" name="Texture" tool_tip="Klik for at vælge et billede"/>
+ <button label="Lav nyt hår" label_selected="Lav nyt hår" name="Create New"/>
+ <button label="Gem" label_selected="Gem" name="Save"/>
+ <button label="Gem som..." label_selected="Gem som..." name="Save As"/>
+ <button label="Annullér" label_selected="Annullér" name="Revert"/>
</panel>
<panel label="Øjne" name="Eyes">
- <text type="string" length="1" name="title">
+ <text name="title">
[DESC]
</text>
- <text type="string" length="1" name="title_no_modify">
+ <text name="title_no_modify">
[DESC]: Kan ikke redigeres
</text>
- <text type="string" length="1" name="title_loading">
+ <text name="title_loading">
[DESC]: indlæser...
</text>
- <text type="string" length="1" name="title_not_worn">
+ <text name="title_not_worn">
[DESC]: ikke båret
</text>
- <text type="string" length="1" name="path">
+ <text name="path">
Fundet i [PATH]
</text>
- <text type="string" length="1" name="not worn instructions">
+ <text name="not worn instructions">
Tag et ny sæt øjne på ved at trække et sæt fra din beholdning
-over på din avatar. Du kan også oprette et nyt sæt øjne fra bunden og bagefter &apos;tage dem på&apos;.
+over på din avatar. Du kan også oprette et nyt sæt øjne fra bunden
+og bagefter &apos;tage dem på&apos;.
</text>
- <text type="string" length="1" name="no modify instructions">
+ <text name="no modify instructions">
Du har ikke rettigheder til at redigere denne del.
</text>
- <texture_picker label="Iris" name="Iris" />
- <button label="Tilfældig" label_selected="Tilfældig" name="Randomize" />
- <button label="Lav nye øjne" label_selected="Lav nye øjne" name="Create New" />
- <button label="Tag af" label_selected="Tag af" name="Take Off" />
- <button label="Gem" label_selected="Gem" name="Save" />
- <button label="Gem som" label_selected="Gem som" name="Save As" />
- <button label="Annullér" label_selected="Annullér" name="Revert" />
+ <text name="Item Action Label">
+ Øjne:
+ </text>
+ <texture_picker label="Iris" name="Iris" tool_tip="Klik for at vælge et billede"/>
+ <button label="Lav nye øjne" label_selected="Lav nye øjne" name="Create New"/>
+ <button label="Gem" label_selected="Gem" name="Save"/>
+ <button label="Gem som..." label_selected="Gem som..." name="Save As"/>
+ <button label="Annullér" label_selected="Annullér" name="Revert"/>
</panel>
- <panel label="Tøje" name="clothes_placeholder" />
+ <panel label="Tøje" name="clothes_placeholder"/>
<panel label="Trøje" name="Shirt">
- <texture_picker label="Stof" name="Fabric" />
- <color_swatch label="Farve" name="Color/Tint" />
- <button label="Lav ny trøje" label_selected="Lav ny trøje" name="Create New" />
- <button label="Tag af" label_selected="Tag af" name="Take Off" />
- <button label="Gem" label_selected="Gem" name="Save" />
- <button label="Gem som" label_selected="Gem som" name="Save As" />
- <button label="Annullér" label_selected="Annullér" name="Revert" />
- <text type="string" length="1" name="title">
+ <texture_picker label="Stof" name="Fabric" tool_tip="Klik for at vælge et billede"/>
+ <color_swatch label="Farve" name="Color/Tint" tool_tip="Klik for at åbne farvevælger"/>
+ <button label="Lav ny trøje" label_selected="Lav ny trøje" name="Create New"/>
+ <button label="Tag af" label_selected="Tag af" name="Take Off"/>
+ <button label="Gem" label_selected="Gem" name="Save"/>
+ <button label="Gem som..." label_selected="Gem som..." name="Save As"/>
+ <button label="Annullér" label_selected="Annullér" name="Revert"/>
+ <text name="title">
[DESC]
</text>
- <text type="string" length="1" name="title_no_modify">
+ <text name="title_no_modify">
[DESC]: Kan ikke redigeres
</text>
- <text type="string" length="1" name="title_loading">
+ <text name="title_loading">
[DESC]: indlæser...
</text>
- <text type="string" length="1" name="title_not_worn">
+ <text name="title_not_worn">
[DESC]: ikke båret
</text>
- <text type="string" length="1" name="path">
+ <text name="path">
Fundet i [PATH]
</text>
- <text type="string" length="1" name="not worn instructions">
- Tag en ny Tøje på ved at trække en fra din beholdning
-over på din avatar.
+ <text name="not worn instructions">
+ Tag en ny Tøje på ved at trække en fra din beholdning over på din avatar.
Du kan også oprette en ny Tøje fra bunden og bagefter &apos;tage den på&apos;.
</text>
- <text type="string" length="1" name="no modify instructions">
+ <text name="no modify instructions">
Du har ikke rettigheder til at redigere denne del.
</text>
+ <text name="Item Action Label">
+ Trøje:
+ </text>
</panel>
<panel label="Bukser" name="Pants">
- <texture_picker label="Stof" name="Fabric" />
- <color_swatch label="Farve" name="Color/Tint" />
- <button label="Lav nye bukser" label_selected="Lav nye bukser" name="Create New" />
- <button label="Tag af" label_selected="Tag af" name="Take Off" />
- <button label="Gem" label_selected="Gem" name="Save" />
- <button label="Gem som" label_selected="Gem som" name="Save As" />
- <button label="Annullér" label_selected="Annullér" name="Revert" />
- <text type="string" length="1" name="title">
+ <texture_picker label="Stof" name="Fabric" tool_tip="Klik for at vælge et billede"/>
+ <color_swatch label="Farve" name="Color/Tint" tool_tip="Klik for at åbne farvevælger"/>
+ <button label="Lav nye bukser" label_selected="Lav nye bukser" name="Create New"/>
+ <button label="Tag af" label_selected="Tag af" name="Take Off"/>
+ <button label="Gem" label_selected="Gem" name="Save"/>
+ <button label="Gem som..." label_selected="Gem som..." name="Save As"/>
+ <button label="Annullér" label_selected="Annullér" name="Revert"/>
+ <text name="title">
[DESC]
</text>
- <text type="string" length="1" name="title_no_modify">
+ <text name="title_no_modify">
[DESC]: Kan ikke redigeres
</text>
- <text type="string" length="1" name="title_loading">
+ <text name="title_loading">
[DESC]: indlæser...
</text>
- <text type="string" length="1" name="title_not_worn">
+ <text name="title_not_worn">
[DESC]: ikke båret
</text>
- <text type="string" length="1" name="path">
+ <text name="path">
Fundet i [PATH]
</text>
- <text type="string" length="1" name="not worn instructions">
- Tag nyr bukser på ved at trække dem fra din beholdning
-over på din avatar.
-Du kan også oprette ny bukser fra bunden og bagefter &apos;tage dem på&apos;.
+ <text name="not worn instructions">
+ Tag nyr bukser på ved at trække dem fra din beholdning over på
+din avatar. Du kan også oprette ny bukser fra bunden og bagefter
+&apos;tage dem på&apos;.
</text>
- <text type="string" length="1" name="no modify instructions">
+ <text name="no modify instructions">
Du har ikke rettigheder til at redigere denne del.
</text>
+ <text name="Item Action Label">
+ Bukser:
+ </text>
</panel>
<panel label="Sko" name="Shoes">
- <text type="string" length="1" name="title">
+ <text name="title">
[DESC]
</text>
- <text type="string" length="1" name="title_no_modify">
+ <text name="title_no_modify">
[DESC]: Kan ikke redigeres
</text>
- <text type="string" length="1" name="title_loading">
+ <text name="title_loading">
[DESC]: indlæser...
</text>
- <text type="string" length="1" name="title_not_worn">
+ <text name="title_not_worn">
[DESC]: ikke båret
</text>
- <text type="string" length="1" name="path">
+ <text name="path">
Fundet i [PATH]
</text>
- <text type="string" length="1" name="not worn instructions">
+ <text name="not worn instructions">
Tag et ny par sko på ved at trække dem fra din beholdning
-over på din avatar. Du kan også oprette et nyt par sko fra bunden og bagefter &apos;tage dem på&apos;.
+over på din avatar. Du kan også oprette et nyt par sko fra bunden
+og bagefter &apos;tage dem på&apos;.
</text>
- <text type="string" length="1" name="no modify instructions">
+ <text name="no modify instructions">
Du har ikke rettigheder til at redigere denne del.
</text>
- <texture_picker label="Stof" name="Fabric" />
- <color_swatch label="Farve" name="Color/Tint" />
- <button label="Lav nye sko" label_selected="Lav nye sko" name="Create New" />
- <button label="Tag af" label_selected="Tag af" name="Take Off" />
- <button label="Gem" label_selected="Gem" name="Save" />
- <button label="Gem som" label_selected="Gem som" name="Save As" />
- <button label="Annullér" label_selected="Annullér" name="Revert" />
+ <text name="Item Action Label">
+ Sko:
+ </text>
+ <texture_picker label="Stof" name="Fabric" tool_tip="Klik for at vælge et billede"/>
+ <color_swatch label="Farve" name="Color/Tint" tool_tip="Klik for at åbne farvevælger"/>
+ <button label="Lav nye sko" label_selected="Lav nye sko" name="Create New"/>
+ <button label="Tag af" label_selected="Tag af" name="Take Off"/>
+ <button label="Gem" label_selected="Gem" name="Save"/>
+ <button label="Gem som..." label_selected="Gem som..." name="Save As"/>
+ <button label="Annullér" label_selected="Annullér" name="Revert"/>
</panel>
<panel label="Strømper" name="Socks">
- <text type="string" length="1" name="title">
+ <text name="title">
[DESC]
</text>
- <text type="string" length="1" name="title_no_modify">
+ <text name="title_no_modify">
[DESC]: Kan ikke redigeres
</text>
- <text type="string" length="1" name="title_loading">
+ <text name="title_loading">
[DESC]: indlæser...
</text>
- <text type="string" length="1" name="title_not_worn">
+ <text name="title_not_worn">
[DESC]: ikke båret
</text>
- <text type="string" length="1" name="path">
+ <text name="path">
Fundet i [PATH]
</text>
- <text type="string" length="1" name="not worn instructions">
+ <text name="not worn instructions">
Tag et ny par Strømper på ved at trække dem fra din beholdning
-over på din avatar. Du kan også oprette et nyt par Strømper fra bunden og bagefter &apos;tage dem på&apos;.
+over på din avatar. Du kan også oprette et nyt par Strømper fra bunden
+og bagefter &apos;tage dem på&apos;.
</text>
- <text type="string" length="1" name="no modify instructions">
+ <text name="no modify instructions">
Du har ikke rettigheder til at redigere denne del.
</text>
- <texture_picker label="Stof" name="Fabric" />
- <color_swatch label="Farve" name="Color/Tint" />
- <button label="Lav nye strømper" label_selected="Lav nye strømper" name="Create New" />
- <button label="Tag af" label_selected="Tag af" name="Take Off" />
- <button label="Gem" label_selected="Gem" name="Save" />
- <button label="Gem som" label_selected="Gem som" name="Save As" />
- <button label="Annullér" label_selected="Annullér" name="Revert" />
+ <text name="Item Action Label">
+ Strømper:
+ </text>
+ <texture_picker label="Stof" name="Fabric" tool_tip="Klik for at vælge et billede"/>
+ <color_swatch label="Farve" name="Color/Tint" tool_tip="Klik for at åbne farvevælger"/>
+ <button label="Lav nye strømper" label_selected="Lav nye strømper" name="Create New"/>
+ <button label="Tag af" label_selected="Tag af" name="Take Off"/>
+ <button label="Gem" label_selected="Gem" name="Save"/>
+ <button label="Gem som..." label_selected="Gem som..." name="Save As"/>
+ <button label="Annullér" label_selected="Annullér" name="Revert"/>
</panel>
<panel label="Jakke" name="Jacket">
- <text type="string" length="1" name="title">
+ <text name="title">
[DESC]
</text>
- <text type="string" length="1" name="title_no_modify">
+ <text name="title_no_modify">
[DESC]: Kan ikke redigeres
</text>
- <text type="string" length="1" name="title_loading">
+ <text name="title_loading">
[DESC]: indlæser...
</text>
- <text type="string" length="1" name="title_not_worn">
+ <text name="title_not_worn">
[DESC]: ikke båret
</text>
- <text type="string" length="1" name="path">
+ <text name="path">
Fundet i [PATH]
</text>
- <text type="string" length="1" name="not worn instructions">
- Tag en ny jakke på ved at trække en fra din beholdning
-over på din avatar.
+ <text name="not worn instructions">
+ Tag en ny jakke på ved at trække en fra din beholdning over på din avatar.
Du kan også oprette en ny jakke fra bunden og bagefter &apos;tage den på&apos;.
</text>
- <text type="string" length="1" name="no modify instructions">
+ <text name="no modify instructions">
Du har ikke rettigheder til at redigere denne del.
</text>
- <texture_picker label="Stof øverst" name="Upper Fabric" />
- <texture_picker label="Stof nederst" name="Lower Fabric" />
- <color_swatch label="Farve" name="Color/Tint" />
- <button label="Lav ny jakke" label_selected="Lav ny jakke" name="Create New" />
- <button label="Tag af" label_selected="Tag af" name="Take Off" />
- <button label="Gem" label_selected="Gem" name="Save" />
- <button label="Gem som" label_selected="Gem som" name="Save As" />
- <button label="Annullér" label_selected="Annullér" name="Revert" />
+ <text name="Item Action Label">
+ Jakke:
+ </text>
+ <texture_picker label="Stof øverst" name="Upper Fabric" tool_tip="Klik for at vælge et billede"/>
+ <texture_picker label="Stof nederst" name="Lower Fabric" tool_tip="Klik for at vælge et billede"/>
+ <color_swatch label="Farve" name="Color/Tint" tool_tip="Klik for at åbne farvevælger"/>
+ <button label="Lav ny jakke" label_selected="Lav ny jakke" name="Create New"/>
+ <button label="Tag af" label_selected="Tag af" name="Take Off"/>
+ <button label="Gem" label_selected="Gem" name="Save"/>
+ <button label="Gem som..." label_selected="Gem som..." name="Save As"/>
+ <button label="Annullér" label_selected="Annullér" name="Revert"/>
</panel>
<panel label="Handsker" name="Gloves">
- <text type="string" length="1" name="title">
+ <text name="title">
[DESC]
</text>
- <text type="string" length="1" name="title_no_modify">
+ <text name="title_no_modify">
[DESC]: Kan ikke redigeres
</text>
- <text type="string" length="1" name="title_loading">
+ <text name="title_loading">
[DESC]: indlæser...
</text>
- <text type="string" length="1" name="title_not_worn">
+ <text name="title_not_worn">
[DESC]: ikke båret
</text>
- <text type="string" length="1" name="path">
+ <text name="path">
Fundet i [PATH]
</text>
- <text type="string" length="1" name="not worn instructions">
- Tag nye handsker på ved at trække et par fra din beholdning
-over på din avatar.
-Du kan også oprette nye handsker fra bunden og bagefter &apos;tage dem på&apos;.
+ <text name="not worn instructions">
+ Tag nye handsker på ved at trække et par fra din beholdning over på
+din avatar. Du kan også oprette nye handsker fra bunden
+og bagefter &apos;tage dem på&apos;.
</text>
- <text type="string" length="1" name="no modify instructions">
+ <text name="no modify instructions">
Du har ikke rettigheder til at redigere denne del.
</text>
- <texture_picker label="Stof" name="Fabric" />
- <color_swatch label="Farve" name="Color/Tint" />
- <button label="Lav nye handsker" label_selected="Lav nye handsker" name="Create New" />
- <button label="Tag af" label_selected="Tag af" name="Take Off" />
- <button label="Gem" label_selected="Gem" name="Save" />
- <button label="Gem som" label_selected="Gem som" name="Save As" />
- <button label="Annullér" label_selected="Annullér" name="Revert" />
+ <text name="Item Action Label">
+ Handsker:
+ </text>
+ <texture_picker label="Stof" name="Fabric" tool_tip="Klik for at vælge et billede"/>
+ <color_swatch label="Farve" name="Color/Tint" tool_tip="Klik for at åbne farvevælger"/>
+ <button label="Lav nye handsker" label_selected="Lav nye handsker" name="Create New"/>
+ <button label="Tag af" label_selected="Tag af" name="Take Off"/>
+ <button label="Gem" label_selected="Gem" name="Save"/>
+ <button label="Gem som..." label_selected="Gem som..." name="Save As"/>
+ <button label="Annullér" label_selected="Annullér" name="Revert"/>
</panel>
<panel label="Undertrøje" name="Undershirt">
- <text type="string" length="1" name="title">
+ <text name="title">
[DESC]
</text>
- <text type="string" length="1" name="title_no_modify">
+ <text name="title_no_modify">
[DESC]: Kan ikke redigeres
</text>
- <text type="string" length="1" name="title_loading">
+ <text name="title_loading">
[DESC]: indlæser...
</text>
- <text type="string" length="1" name="title_not_worn">
+ <text name="title_not_worn">
[DESC]: ikke båret
</text>
- <text type="string" length="1" name="path">
+ <text name="path">
Fundet i [PATH]
</text>
- <text type="string" length="1" name="not worn instructions">
- Tag en ny undertrøje på ved at trække en fra din beholdning
-over på din avatar.
-Du kan også oprette en ny undertrøje fra bunden og bagefter &apos;tage den på&apos;.
+ <text name="not worn instructions">
+ Tag en ny undertrøje på ved at trække en fra din beholdning over på
+din avatar. Du kan også oprette en ny undertrøje fra bunden
+og bagefter &apos;tage den på&apos;.
</text>
- <text type="string" length="1" name="no modify instructions">
+ <text name="no modify instructions">
Du har ikke rettigheder til at redigere denne del.
</text>
- <texture_picker label="Stof" name="Fabric" />
- <color_swatch label="Farve" name="Color/Tint" />
- <button label="Lav ny undertrøje" label_selected="Lav ny undertrøje" name="Create New" />
- <button label="Tag af" label_selected="Tag af" name="Take Off" />
- <button label="Gem" label_selected="Gem" name="Save" />
- <button label="Gem som" label_selected="Gem som" name="Save As" />
- <button label="Annullér" label_selected="Annullér" name="Revert" />
+ <text name="Item Action Label">
+ Undertrøje:
+ </text>
+ <texture_picker label="Stof" name="Fabric" tool_tip="Klik for at vælge et billede"/>
+ <color_swatch label="Farve" name="Color/Tint" tool_tip="Klik for at åbne farvevælger"/>
+ <button label="Lav ny undertrøje" label_selected="Lav ny undertrøje" name="Create New"/>
+ <button label="Tag af" label_selected="Tag af" name="Take Off"/>
+ <button label="Gem" label_selected="Gem" name="Save"/>
+ <button label="Gem som..." label_selected="Gem som..." name="Save As"/>
+ <button label="Annullér" label_selected="Annullér" name="Revert"/>
</panel>
<panel label="Underbukser" name="Underpants">
- <text type="string" length="1" name="title">
+ <text name="title">
[DESC]
</text>
- <text type="string" length="1" name="title_no_modify">
+ <text name="title_no_modify">
[DESC]: Kan ikke redigeres
</text>
- <text type="string" length="1" name="title_loading">
+ <text name="title_loading">
[DESC]: indlæser...
</text>
- <text type="string" length="1" name="title_not_worn">
+ <text name="title_not_worn">
[DESC]: ikke båret
</text>
- <text type="string" length="1" name="path">
+ <text name="path">
Fundet i [PATH]
</text>
- <text type="string" length="1" name="not worn instructions">
- Tag nye underbukser på ved at trække dem fra din beholdning
-over på din avatar.
-Du kan også oprette en par nye underbukser fra bunden og bagefter &apos;tage dem på&apos;.
+ <text name="not worn instructions">
+ Tag nye underbukser på ved at trække dem fra din beholdning over på
+din avatar. Du kan også oprette en par nye underbukser fra bunden
+og bagefter &apos;tage dem på&apos;.
</text>
- <text type="string" length="1" name="no modify instructions">
+ <text name="no modify instructions">
Du har ikke rettigheder til at redigere denne del.
</text>
- <texture_picker label="Stof" name="Fabric" />
- <color_swatch label="Farve" name="Color/Tint" />
- <button label="Lav nye underbukser" label_selected="Lav nye underbukser" name="Create New" />
- <button label="Tag af" label_selected="Tag af" name="Take Off" />
- <button label="Gem" label_selected="Gem" name="Save" />
- <button label="Gem som" label_selected="Gem som" name="Save As" />
- <button label="Annullér" label_selected="Annullér" name="Revert" />
+ <text name="Item Action Label">
+ Underbukser:
+ </text>
+ <texture_picker label="Stof" name="Fabric" tool_tip="Klik for at vælge et billede"/>
+ <color_swatch label="Farve" name="Color/Tint" tool_tip="Klik for at åbne farvevælger"/>
+ <button label="Lav nye underbukser" label_selected="Lav nye underbukser" name="Create New"/>
+ <button label="Tag af" label_selected="Tag af" name="Take Off"/>
+ <button label="Gem" label_selected="Gem" name="Save"/>
+ <button label="Gem som..." label_selected="Gem som..." name="Save As"/>
+ <button label="Annullér" label_selected="Annullér" name="Revert"/>
</panel>
<panel label="Nederdel" name="Skirt">
- <text type="string" length="1" name="title">
+ <text name="title">
[DESC]
</text>
- <text type="string" length="1" name="title_no_modify">
+ <text name="title_no_modify">
[DESC]: Kan ikke redigeres
</text>
- <text type="string" length="1" name="title_loading">
+ <text name="title_loading">
[DESC]: indlæser...
</text>
- <text type="string" length="1" name="title_not_worn">
+ <text name="title_not_worn">
[DESC]: ikke båret
</text>
- <text type="string" length="1" name="path">
+ <text name="path">
Fundet i [PATH]
</text>
- <text type="string" length="1" name="not worn instructions">
- Tag en ny nederdel på ved at trække en fra din beholdning
-over på din avatar.
-Du kan også oprette en ny nederdel fra bunden og bagefter &apos;tage den på&apos;.
+ <text name="not worn instructions">
+ Tag en ny nederdel på ved at trække en fra din beholdning over på
+din avatar. Du kan også oprette en ny nederdel fra bunden
+og bagefter &apos;tage den på&apos;.
</text>
- <text type="string" length="1" name="no modify instructions">
+ <text name="no modify instructions">
Du har ikke rettigheder til at redigere denne del.
</text>
- <texture_picker label="Stof" name="Fabric" />
- <color_swatch label="Farve" name="Color/Tint" />
- <button label="Lav ny nederdel" label_selected="Lav ny nederdel" name="Create New" />
- <button label="Tag af" label_selected="Tag af" name="Take Off" />
- <button label="Gem" label_selected="Gem" name="Save" />
- <button label="Gem som" label_selected="Gem som" name="Save As" />
- <button label="Annullér" label_selected="Annullér" name="Revert" />
+ <text name="Item Action Label">
+ Nederdel:
+ </text>
+ <texture_picker label="Stof" name="Fabric" tool_tip="Klik for at vælge et billede"/>
+ <color_swatch label="Farve" name="Color/Tint" tool_tip="Klik for at åbne farvevælger"/>
+ <button label="Lav ny nederdel" label_selected="Lav ny nederdel" name="Create New"/>
+ <button label="Tag af" label_selected="Tag af" name="Take Off"/>
+ <button label="Gem" label_selected="Gem" name="Save"/>
+ <button label="Gem som..." label_selected="Gem som..." name="Save As"/>
+ <button label="Annullér" label_selected="Annullér" name="Revert"/>
</panel>
</tab_container>
- <button label="Luk" label_selected="Luk" name="Close" />
- <button label="Gem alt" label_selected="Gem alt" name="Save All" />
- <button label="Opret sæt" label_selected="Opret sæt" name="Make Outfit" />
+ <scroll_container left="212" name="panel_container"/>
+ <button label="Annullér" label_selected="Annullér" name="Cancel"/>
+ <button label="OK" label_selected="OK" name="Ok"/>
+ <button label="Opret sæt..." label_selected="Opret sæt..." name="Make Outfit"/>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_day_cycle_options.xml b/indra/newview/skins/default/xui/da/floater_day_cycle_options.xml
index 140b3d47d6..94cf4546e3 100644
--- a/indra/newview/skins/default/xui/da/floater_day_cycle_options.xml
+++ b/indra/newview/skins/default/xui/da/floater_day_cycle_options.xml
@@ -1,89 +1,89 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Day Cycle Floater" title="Dag cyklus opsætning">
+<floater name="Day Cycle Floater" title="DAG CYKLUS OPSÆTNING">
<tab_container name="Day Cycle Tabs">
<panel label="Dag cyklus" name="Day Cycle">
<button label="?" name="WLDayCycleHelp" />
<multi_slider label="" name="WLTimeSlider" />
<multi_slider label="" name="WLDayCycleKeys" />
- <text type="string" length="1" name="WL12am">
+ <text name="WL12am">
00:00
</text>
- <text type="string" length="1" name="WL3am">
+ <text name="WL3am">
03:00
</text>
- <text type="string" length="1" name="WL6am">
+ <text name="WL6am">
06:00
</text>
- <text type="string" length="1" name="WL9amHash">
+ <text name="WL9amHash">
09:00
</text>
- <text type="string" length="1" name="WL12pmHash">
+ <text name="WL12pmHash">
12:00
</text>
- <text type="string" length="1" name="WL3pm">
+ <text name="WL3pm">
15:00
</text>
- <text type="string" length="1" name="WL6pm">
+ <text name="WL6pm">
18:00
</text>
- <text type="string" length="1" name="WL9pm">
+ <text name="WL9pm">
21:00
</text>
- <text type="string" length="1" name="WL12am2">
+ <text name="WL12am2">
00:00
</text>
- <text type="string" length="1" name="WL12amHash">
+ <text name="WL12amHash">
|
</text>
- <text type="string" length="1" name="WL3amHash">
+ <text name="WL3amHash">
I
</text>
- <text type="string" length="1" name="WL6amHash">
+ <text name="WL6amHash">
|
</text>
- <text type="string" length="1" name="WL9amHash2">
+ <text name="WL9amHash2">
I
</text>
- <text type="string" length="1" name="WL12pmHash2">
+ <text name="WL12pmHash2">
|
</text>
- <text type="string" length="1" name="WL3pmHash">
+ <text name="WL3pmHash">
I
</text>
- <text type="string" length="1" name="WL6pmHash">
+ <text name="WL6pmHash">
|
</text>
- <text type="string" length="1" name="WL9pmHash">
+ <text name="WL9pmHash">
I
</text>
- <text type="string" length="1" name="WL12amHash2">
+ <text name="WL12amHash2">
|
</text>
<button label="Tilføj key" label_selected="Tilføj key" name="WLAddKey" />
<button label="Slet key" label_selected="Slet key" name="WLDeleteKey" />
- <text type="string" length="1" name="WLCurKeyFrameText">
+ <text name="WLCurKeyFrameText">
Key-frame indstillinger:
</text>
- <text type="string" length="1" name="WLCurKeyTimeText">
+ <text name="WLCurKeyTimeText">
Key tid:
</text>
<spinner label="Timer" name="WLCurKeyHour" />
<spinner label="Min." name="WLCurKeyMin" />
- <text type="string" length="1" name="WLCurKeyTimeText2">
+ <text name="WLCurKeyTimeText2">
Key fast indstilling:
</text>
<combo_box label="Faste" name="WLKeyPresets" />
- <text type="string" length="1" name="DayCycleText">
+ <text name="DayCycleText">
Snap:
</text>
<combo_box label="5 min" name="WLSnapOptions" />
- <text type="string" length="1" name="DayCycleText2">
+ <text name="DayCycleText2">
Cycluslængde:
</text>
<spinner label="Timer" name="WLLengthOfDayHour" />
<spinner label="Min." name="WLLengthOfDayMin" />
<spinner label="Sek." name="WLLengthOfDaySec" />
- <text type="string" length="1" name="DayCycleText3">
+ <text name="DayCycleText3">
Vis:
</text>
<button label="Afspil" label_selected="Afspil" name="WLAnimSky" />
diff --git a/indra/newview/skins/default/xui/da/floater_device_settings.xml b/indra/newview/skins/default/xui/da/floater_device_settings.xml
index 28afd7c459..5e53a697f2 100644
--- a/indra/newview/skins/default/xui/da/floater_device_settings.xml
+++ b/indra/newview/skins/default/xui/da/floater_device_settings.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_device_settings" title="Stemme chat indstillinger" />
+<floater name="floater_device_settings" title="STEMME CHAT INDSTILLINGER" />
diff --git a/indra/newview/skins/default/xui/da/floater_env_settings.xml b/indra/newview/skins/default/xui/da/floater_env_settings.xml
index 04b804b362..6c5b6d3b6b 100644
--- a/indra/newview/skins/default/xui/da/floater_env_settings.xml
+++ b/indra/newview/skins/default/xui/da/floater_env_settings.xml
@@ -1,21 +1,21 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Environment Editor Floater" title="Redigering af omgivelser">
- <text type="string" length="1" name="EnvTimeText">
+<floater name="Environment Editor Floater" title="REDIGERING AF OMGIVELSER">
+ <text name="EnvTimeText">
Tid på dagen
</text>
- <text type="string" length="1" name="EnvTimeText2">
+ <text name="EnvTimeText2">
00:00
</text>
<slider label="" name="EnvTimeSlider" />
- <text type="string" length="1" name="EnvCloudText">
+ <text name="EnvCloudText">
Skydække
</text>
<slider label="" name="EnvCloudSlider" />
- <text type="string" length="1" name="EnvWaterColorText">
+ <text name="EnvWaterColorText">
Farve på vand
</text>
<color_swatch label="" name="EnvWaterColor" tool_tip="Klik for at åbne farvevælger" />
- <text type="string" length="1" name="EnvWaterFogText">
+ <text name="EnvWaterFogText">
Tåge på vand
</text>
<slider label="" name="EnvWaterFogSlider" />
diff --git a/indra/newview/skins/default/xui/da/floater_font_test.xml b/indra/newview/skins/default/xui/da/floater_font_test.xml
new file mode 100644
index 0000000000..591d07188c
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/floater_font_test.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="contents" title="FONT TEST">
+ <text name="linea">
+ OverrideTest, skal vises her som fonten &apos;Times&apos;. (Fra default/xui/en-us)
+ </text>
+</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_gesture.xml b/indra/newview/skins/default/xui/da/floater_gesture.xml
index 800693ea8c..11ecc8bd9a 100644
--- a/indra/newview/skins/default/xui/da/floater_gesture.xml
+++ b/indra/newview/skins/default/xui/da/floater_gesture.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="gestures" title="Aktive bevægelser">
+<floater name="gestures" title="AKTIVE BEVÆGELSER">
<text name="help_label">
Dobbelt-klik på en bevægelse for at afspille animation og lyd.
</text>
diff --git a/indra/newview/skins/default/xui/da/floater_hardware_settings.xml b/indra/newview/skins/default/xui/da/floater_hardware_settings.xml
index f255250389..fc1231ceef 100644
--- a/indra/newview/skins/default/xui/da/floater_hardware_settings.xml
+++ b/indra/newview/skins/default/xui/da/floater_hardware_settings.xml
@@ -1,34 +1,24 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Hardware Settings Floater" title="Hardware opsætning">
- <text type="string" length="1" name="Filtering:">
+<floater name="Hardware Settings Floater" title="HARDWARE OPSÆTNING">
+ <text name="Filtering:">
Filtrering:
</text>
<check_box label="Anisotropic filtrering (langsommere når aktiveret)" name="ani" />
- <text type="string" length="1" name="Antialiasing:">
+ <text name="Antialiasing:">
Antialiasing:
</text>
- <combo_box label="Antialiasing" name="fsaa">
- <combo_item name="FSAADisabled">
- Slået fra
- </combo_item>
- <combo_item name="2x">
- 2x
- </combo_item>
- <combo_item name="4x">
- 4x
- </combo_item>
- <combo_item name="8x">
- 8x
- </combo_item>
- <combo_item name="16x">
- 16x
- </combo_item>
+ <combo_box label="Antialiasing" name="fsaa" width="100">
+ <combo_box.item name="FSAADisabled" label="Slået fra"/>
+ <combo_box.item name="2x" label="2x"/>
+ <combo_box.item name="4x" label="4x"/>
+ <combo_box.item name="8x" label="8x"/>
+ <combo_box.item name="16x" label="16x"/>
</combo_box>
<spinner label="Gamma:" name="gamma" />
- <text type="string" length="1" name="(brightness, lower is brighter)">
+ <text name="(brightness, lower is brighter)">
(Lysstyrke, lavere er lysere, 0=benyt standard)
</text>
- <text type="string" length="1" name="Enable VBO:">
+ <text name="Enable VBO:">
Aktivér VBO:
</text>
<check_box label="Aktivér OpenGL Vertex Buffer objekter" name="vbo"
diff --git a/indra/newview/skins/default/xui/da/floater_hud.xml b/indra/newview/skins/default/xui/da/floater_hud.xml
index 0f11e2346d..18584e57ca 100644
--- a/indra/newview/skins/default/xui/da/floater_hud.xml
+++ b/indra/newview/skins/default/xui/da/floater_hud.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_hud" title="Tutorial" />
+<floater name="floater_hud" title="TUTORIAL" />
diff --git a/indra/newview/skins/default/xui/da/floater_image_preview.xml b/indra/newview/skins/default/xui/da/floater_image_preview.xml
index c7ce3d00b6..345c9aa6d1 100644
--- a/indra/newview/skins/default/xui/da/floater_image_preview.xml
+++ b/indra/newview/skins/default/xui/da/floater_image_preview.xml
@@ -10,36 +10,16 @@
Se billede som:
</text>
<combo_box label="Tøj type" name="clothing_type_combo">
- <combo_item name="Image">
- Billede
- </combo_item>
- <combo_item name="Hair">
- HÃ¥r
- </combo_item>
- <combo_item name="FemaleHead">
- Kvinde - hoved
- </combo_item>
- <combo_item name="FemaleUpperBody">
- Kvinde - overkrop
- </combo_item>
- <combo_item name="FemaleLowerBody">
- Kvinde - underkrop
- </combo_item>
- <combo_item name="MaleHead">
- Mand - hoved
- </combo_item>
- <combo_item name="MaleUpperBody">
- Mand - overkrop
- </combo_item>
- <combo_item name="MaleLowerBody">
- Mand - underkrop
- </combo_item>
- <combo_item name="Skirt">
- Nederdel
- </combo_item>
- <combo_item name="SculptedPrim">
- Sculpted prim
- </combo_item>
+ <combo_box.item name="Image" label="Billede"/>
+ <combo_box.item name="Hair" label="HÃ¥r"/>
+ <combo_box.item name="FemaleHead" label="Kvinde - hoved"/>
+ <combo_box.item name="FemaleUpperBody" label="Kvinde - overkrop"/>
+ <combo_box.item name="FemaleLowerBody" label="Kvinde - underkrop"/>
+ <combo_box.item name="MaleHead" label="Mand - hoved"/>
+ <combo_box.item name="MaleUpperBody" label="Mand - overkrop"/>
+ <combo_box.item name="MaleLowerBody" label="Mand - underkrop"/>
+ <combo_box.item name="Skirt" label="Nederdel"/>
+ <combo_box.item name="SculptedPrim" label="Sculpted prim"/>
</combo_box>
<text name="bad_image_text">
Kunne ikke læse billede.
diff --git a/indra/newview/skins/default/xui/da/floater_inspect.xml b/indra/newview/skins/default/xui/da/floater_inspect.xml
index 8361733e23..0610e9408f 100644
--- a/indra/newview/skins/default/xui/da/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/da/floater_inspect.xml
@@ -1,13 +1,11 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="inspect" >
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="inspect" title="INSPECÉR OBJEKTER">
<scroll_list name="object_list" tool_tip="Vælg et objekt fra listen for at markere det">
- <column label="Objekt navn" name="object_name" />
- <column label="Objekt ejer" name="owner_name" />
- <column label="Bygget af" name="creator_name" />
- <column label="Lavet den " name="creation_date" />
+ <column label="Objekt navn" name="object_name"/>
+ <column label="Objekt ejer" name="owner_name"/>
+ <column label="Bygget af" name="creator_name"/>
+ <column label="Lavet den " name="creation_date"/>
</scroll_list>
- <button label="Se profil for ejer..." label_selected="" name="button owner"
- tool_tip="Se profilen for ejeren af det markerede objekt på listen" />
- <button label="Se profil for bygger..." label_selected="" name="button creator"
- tool_tip="Se profilen for den beboer der har bygget det markerede objekt på listen" />
+ <button label="Se profil for ejer..." label_selected="" name="button owner" tool_tip="Se profilen for ejeren af det markerede objekt på listen"/>
+ <button label="Se profil for bygger..." label_selected="" name="button creator" tool_tip="Se profilen for den beboer der har bygget det markerede objekt på listen"/>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_inventory.xml b/indra/newview/skins/default/xui/da/floater_inventory.xml
index 0b931bd7f4..8bfe7164d0 100644
--- a/indra/newview/skins/default/xui/da/floater_inventory.xml
+++ b/indra/newview/skins/default/xui/da/floater_inventory.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Inventory" title="Beholdning">
+<floater name="Inventory" title="BEHOLDNING">
<search_editor label="Skriv her for at søge" name="inventory search editor" />
<tab_container name="inventory filter tabs">
<inventory_panel label="Alle ting" name="All Items" />
diff --git a/indra/newview/skins/default/xui/da/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/da/floater_inventory_item_properties.xml
index 96039c8444..fbcf202c54 100644
--- a/indra/newview/skins/default/xui/da/floater_inventory_item_properties.xml
+++ b/indra/newview/skins/default/xui/da/floater_inventory_item_properties.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="item properties" title="Egenskaber for Objekt i Beholdning">
+<floater name="item properties" title="EGENSKABER FOR OBJEKT I BEHOLDNING">
<text name="LabelItemNameTitle">
Navn:
</text>
@@ -60,12 +60,8 @@
</text>
<check_box label="Til salg" name="CheckPurchase" />
<radio_group name="RadioSaleType">
- <radio_item name="radio">
- Original
- </radio_item>
- <radio_item name="radio2">
- Kopi
- </radio_item>
+ <radio_item name="radio" label="Original" />
+ <radio_item name="radio2" label="Kopi" />
</radio_group>
<text name="TextPrice">
Pris: L$
diff --git a/indra/newview/skins/default/xui/da/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/da/floater_inventory_view_finder.xml
index 8eb39f2f79..af2910fe58 100644
--- a/indra/newview/skins/default/xui/da/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/da/floater_inventory_view_finder.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Inventory Finder" title="inventory_recent_items">
+<floater name="Inventory Finder" title="INVENTORY_RECENT_ITEMS">
<check_box label="Animation" name="check_animation" />
<check_box label="Visitkort" name="check_calling_card" />
<check_box label="Tøj" name="check_clothing" />
@@ -15,7 +15,7 @@
<button label="Ingen" label_selected="Ingen" name="None" />
<check_box label="Vis altid mapper" name="check_show_empty" />
<check_box label="Siden sidste logoff" name="check_since_logoff" />
- <text type="string" length="1" name="- OR -">
+ <text name="- OR -">
- ELLER -
</text>
<spinner label="Timer siden" name="spin_hours_ago" />
diff --git a/indra/newview/skins/default/xui/da/floater_joystick.xml b/indra/newview/skins/default/xui/da/floater_joystick.xml
index 72439ac4e0..4954b7b619 100644
--- a/indra/newview/skins/default/xui/da/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/da/floater_joystick.xml
@@ -1,30 +1,22 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Joystick" title="Joystick opsætning">
- <check_box name="enable_joystick">
- Aktiver Joystick:
- </check_box>
- <spinner label="X akse mapping" name="JoystickAxis1" />
- <spinner label="Y akse mapping" name="JoystickAxis2" />
- <spinner label="Z akse mapping" name="JoystickAxis0" />
- <spinner label="Hældning mapping" name="JoystickAxis4" />
- <spinner label="Drejning mapping" name="JoystickAxis5" />
- <spinner label="Rulning mapping" name="JoystickAxis3" />
- <spinner label="Zoom mapping" name="JoystickAxis6" />
- <check_box label="Direkte zoom" name="ZoomDirect" />
- <check_box label="3D Cursor" name="Cursor3D" />
- <check_box label="Auto opret" name="AutoLeveling" />
- <text type="string" length="1" name="Control Modes:">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Joystick" title="JOYSTICK OPSÆTNING">
+ <check_box name="enable_joystick" label="Aktiver Joystick:"/>
+ <spinner label="X akse mapping" name="JoystickAxis1"/>
+ <spinner label="Y akse mapping" name="JoystickAxis2"/>
+ <spinner label="Z akse mapping" name="JoystickAxis0"/>
+ <spinner label="Hældning mapping" name="JoystickAxis4"/>
+ <spinner label="Drejning mapping" name="JoystickAxis5"/>
+ <spinner label="Rulning mapping" name="JoystickAxis3"/>
+ <spinner label="Zoom mapping" name="JoystickAxis6"/>
+ <check_box label="Direkte zoom" name="ZoomDirect"/>
+ <check_box label="3D Cursor" name="Cursor3D"/>
+ <check_box label="Auto opret" name="AutoLeveling"/>
+ <text name="Control Modes:">
Kontrollér:
</text>
- <check_box name="JoystickAvatarEnabled">
- Avatar
- </check_box>
- <check_box name="JoystickBuildEnabled">
- Build
- </check_box>
- <check_box name="JoystickFlycamEnabled">
- Flycam
- </check_box>
+ <check_box name="JoystickAvatarEnabled" label="Avatar"/>
+ <check_box name="JoystickBuildEnabled" label="Build"/>
+ <check_box name="JoystickFlycamEnabled" label="Flycam"/>
<text name="XScale">
X følsomhed
</text>
@@ -64,24 +56,28 @@
<text name="Feathering">
Respons
</text>
- <slider label="" name="AvatarFeathering" />
- <slider label="" name="BuildFeathering" />
- <slider label="" name="FlycamFeathering" />
+ <slider label="" name="AvatarFeathering"/>
+ <slider label="" name="BuildFeathering"/>
+ <slider label="" name="FlycamFeathering"/>
<text name="ZoomScale2">
Zoom følsomhed
</text>
- <spinner label="" name="FlycamAxisScale6" />
+ <spinner label="" name="FlycamAxisScale6"/>
<text name="ZoomDeadZone">
Zoom min. udslag
</text>
- <spinner label="" name="FlycamAxisDeadZone6" />
- <button label="SpaceNavigator Defaults" name="SpaceNavigatorDefaults" />
- <string name="JoystickMonitor">
- Joystick Overvågning
- </string>
- <string name="Axis">
- Akse [NUM]
- </string>
+ <spinner label="" name="FlycamAxisDeadZone6"/>
+ <button label="SpaceNavigator Defaults" name="SpaceNavigatorDefaults"/>
+ <button label="OK" label_selected="OK" name="ok_btn"/>
+ <button label="Annullér" label_selected="Annullér" name="cancel_btn"/>
+ <stat_view label="Joystick Overvågning" name="axis_view">
+ <stat_bar label="Akse 0" name="axis0"/>
+ <stat_bar label="Akse 1" name="axis1"/>
+ <stat_bar label="Akse 2" name="axis2"/>
+ <stat_bar label="Akse 3" name="axis3"/>
+ <stat_bar label="Akse 4" name="axis4"/>
+ <stat_bar label="Akse 5" name="axis5"/>
+ </stat_view>
<string name="NoDevice">
intet joystick fundet
</string>
diff --git a/indra/newview/skins/default/xui/da/floater_lagmeter.xml b/indra/newview/skins/default/xui/da/floater_lagmeter.xml
index b2cbebfe52..bcf15ea926 100644
--- a/indra/newview/skins/default/xui/da/floater_lagmeter.xml
+++ b/indra/newview/skins/default/xui/da/floater_lagmeter.xml
@@ -1,29 +1,28 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_lagmeter" title="Lag måler">
- <button label="" label_selected="" name="client_lagmeter" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_lagmeter" title="LAG MÃ…LER">
+ <button label="" label_selected="" name="client_lagmeter" tool_tip="Status for klient lag"/>
<text name="client">
Klient:
</text>
<text name="client_text">
Normal
</text>
- <button label="" label_selected="" name="network_lagmeter"
- tool_tip="Network lag status" />
+ <button label="" label_selected="" name="network_lagmeter" tool_tip="Network lag status"/>
<text name="network">
Netværk:
</text>
<text name="network_text">
Normal
</text>
- <button label="" label_selected="" name="server_lagmeter" />
+ <button label="" label_selected="" name="server_lagmeter" tool_tip="Status for server lag"/>
<text name="server">
Server:
</text>
<text name="server_text">
Normal
</text>
- <button label="?" name="server_help" />
- <button label="&gt;&gt;" name="minimize" />
+ <button label="?" name="server_help"/>
+ <button label="&gt;&gt;" name="minimize"/>
<string name="max_title_msg">
Lag måler
</string>
@@ -126,9 +125,6 @@
<string name="server_frame_time_normal_msg">
Normal
</string>
- <string name="server_frame_time_normal_msg">
- Normal
- </string>
<string name="server_physics_cause_msg">
Mulig årsag: For mange fysiske objekter
</string>
diff --git a/indra/newview/skins/default/xui/da/floater_land_holdings.xml b/indra/newview/skins/default/xui/da/floater_land_holdings.xml
index fcb159664c..39c906eb18 100644
--- a/indra/newview/skins/default/xui/da/floater_land_holdings.xml
+++ b/indra/newview/skins/default/xui/da/floater_land_holdings.xml
@@ -1,19 +1,20 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="land holdings floater" title="Mit land">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="land holdings floater" title="MIT LAND">
<scroll_list name="parcel list">
- <column label="Navn" name="name" />
- <column label="Lokation" name="location" />
- <column label="Område" name="area" />
- <column label="" name="hidden" />
+ <column label="Navn" name="name"/>
+ <column label="Region" name="location"/>
+ <column label="Type" name="type"/>
+ <column label="Område" name="area"/>
+ <column label="" name="hidden"/>
</scroll_list>
- <button label="Teleport" label_selected="Teleport" name="Teleport" />
- <button label="Vis på kort" label_selected="Vis på kort" name="Show on Map" />
+ <button label="Teleport" label_selected="Teleport" name="Teleport" tool_tip="Teleport til centrum på dette land."/>
+ <button label="Vis på kort" label_selected="Vis på kort" name="Show on Map" tool_tip="Vis dette land på verdenskortet."/>
<text name="contrib_label">
Bidrag til dine grupper:
</text>
<scroll_list name="grant list">
- <column label="Gruppe" name="group" />
- <column label="Område" name="area" />
+ <column label="Gruppe" name="group"/>
+ <column label="Område" name="area"/>
</scroll_list>
<text name="allowed_label">
Tilladt land ifølge nuværende betalingsaftale:
diff --git a/indra/newview/skins/default/xui/da/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/da/floater_live_lsleditor.xml
index 112dc70e45..cfc5fb8860 100644
--- a/indra/newview/skins/default/xui/da/floater_live_lsleditor.xml
+++ b/indra/newview/skins/default/xui/da/floater_live_lsleditor.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script ed float" title="Script: Nyt script">
+<floater name="script ed float" title="SCRIPT: NYT SCRIPT">
<button label="Nulstil" label_selected="Reset" name="Reset" />
<check_box label="Kører" name="running" />
<check_box label="Mono" name="mono" />
diff --git a/indra/newview/skins/default/xui/da/floater_lsl_guide.xml b/indra/newview/skins/default/xui/da/floater_lsl_guide.xml
index 07ea6930ea..ebc86c5c73 100644
--- a/indra/newview/skins/default/xui/da/floater_lsl_guide.xml
+++ b/indra/newview/skins/default/xui/da/floater_lsl_guide.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script ed float" title="LSL Wiki">
+<floater name="script ed float" title="LSL WIKI">
<check_box label="Følg markøreren" name="lock_check" />
- <combo_box label="LÃ¥s" name="history_combo" />
+ <combo_box label="LÃ¥s" name="history_combo" left_delta="114" width="70"/>
<button label="Tilbage" name="back_btn" />
<button label="Frem" name="fwd_btn" />
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_map.xml b/indra/newview/skins/default/xui/da/floater_map.xml
new file mode 100644
index 0000000000..f618548908
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/floater_map.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Map">
+ <floater.string name="mini_map_north">
+ N
+ </floater.string>
+ <floater.string name="mini_map_east">
+ Ø
+ </floater.string>
+ <floater.string name="mini_map_west">
+ V
+ </floater.string>
+ <floater.string name="mini_map_south">
+ S
+ </floater.string>
+ <floater.string name="mini_map_southeast">
+ SØ
+ </floater.string>
+ <floater.string name="mini_map_northeast">
+ NØ
+ </floater.string>
+ <floater.string name="mini_map_southwest">
+ SV
+ </floater.string>
+ <floater.string name="mini_map_northwest">
+ NV
+ </floater.string>
+ <text label="N" name="floater_map_north" text="N">
+ N
+ </text>
+ <text label="Ø" name="floater_map_east" text="Ø">
+ Ø
+ </text>
+ <text label="V" name="floater_map_west" text="V">
+ V
+ </text>
+ <text label="S" name="floater_map_south" text="S">
+ S
+ </text>
+ <text label="SØ" name="floater_map_southeast" text="SØ">
+ SØ
+ </text>
+ <text label="NØ" name="floater_map_northeast" text="NØ">
+ NØ
+ </text>
+ <text label="SV" name="floater_map_southwest" text="SV">
+ SV
+ </text>
+ <text label="NV" name="floater_map_northwest" text="NV">
+ NV
+ </text>
+</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_media_browser.xml b/indra/newview/skins/default/xui/da/floater_media_browser.xml
index 50004cfa0c..47667973ba 100644
--- a/indra/newview/skins/default/xui/da/floater_media_browser.xml
+++ b/indra/newview/skins/default/xui/da/floater_media_browser.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_about" title="Medie vælger">
+<floater name="floater_about" title="MEDIE VÆLGER">
<layout_stack name="stack1">
<layout_panel name="nav_controls">
<button label="Tilbage" name="back" />
diff --git a/indra/newview/skins/default/xui/da/floater_mem_leaking.xml b/indra/newview/skins/default/xui/da/floater_mem_leaking.xml
index 6d5b5bc0ce..e7ad821d40 100644
--- a/indra/newview/skins/default/xui/da/floater_mem_leaking.xml
+++ b/indra/newview/skins/default/xui/da/floater_mem_leaking.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="MemLeak" title="Memory Leaking Simulation">
+<floater name="MemLeak" title="MEMORY LEAKING SIMULATION">
<spinner label="Leaking Speed (bytes per frame):" name="leak_speed" />
<spinner label="Max Leaked Memory (MB):" name="max_leak" />
<text name="total_leaked_label">
diff --git a/indra/newview/skins/default/xui/da/floater_moveview.xml b/indra/newview/skins/default/xui/da/floater_moveview.xml
index 70f3d9e3fd..2b50528881 100644
--- a/indra/newview/skins/default/xui/da/floater_moveview.xml
+++ b/indra/newview/skins/default/xui/da/floater_moveview.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="move floater" title="">
+<floater name="move_floater">
+<panel name="panel_actions">
<button label="" label_selected="" name="turn left btn" tool_tip="Drej til venstre" />
<button label="" label_selected="" name="turn right btn" tool_tip="Drej til højre" />
<button label="" label_selected="" name="move up btn" tool_tip="Hop eller flyv op" />
@@ -8,4 +9,5 @@
<joystick_slide name="slide right btn" tool_tip="Gå til højre" />
<joystick_turn name="forward btn" tool_tip="GÃ¥ fremad" />
<joystick_turn name="backward btn" tool_tip="GÃ¥ bagud" />
+</panel>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_mute_object.xml b/indra/newview/skins/default/xui/da/floater_mute_object.xml
index e64557b177..3b3f670792 100644
--- a/indra/newview/skins/default/xui/da/floater_mute_object.xml
+++ b/indra/newview/skins/default/xui/da/floater_mute_object.xml
@@ -1,12 +1,14 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="mute by name" title="Bloker objekt via navn">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="mute by name" title="BLOKÉR OBJEKT VIA NAVN">
<text name="message">
- Blokering via navn har ikke betydning for lyde.
-Du skal skrive det præcise navn på objektet.
+ Blokér et objekt:
</text>
<line_editor name="object_name">
Objekt navn
</line_editor>
- <button label="OK" name="OK" />
- <button label="Annullér" name="Cancel" />
+ <text name="note">
+ * Blokérer kun tekst fra objekt, ikke lyde
+ </text>
+ <button label="OK" name="OK"/>
+ <button label="Annullér" name="Cancel"/>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_my_friends.xml b/indra/newview/skins/default/xui/da/floater_my_friends.xml
index 687266a08a..54b401076c 100644
--- a/indra/newview/skins/default/xui/da/floater_my_friends.xml
+++ b/indra/newview/skins/default/xui/da/floater_my_friends.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_my_friends" title="Kontakter">
+<floater name="floater_my_friends" title="KONTAKTER">
<tab_container name="friends_and_groups">
<panel label="Venner" name="friends_panel" />
<panel label="Grupper" name="groups_panel" />
diff --git a/indra/newview/skins/default/xui/da/floater_openobject.xml b/indra/newview/skins/default/xui/da/floater_openobject.xml
index 12e4a95a5e..5875b7a967 100644
--- a/indra/newview/skins/default/xui/da/floater_openobject.xml
+++ b/indra/newview/skins/default/xui/da/floater_openobject.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="objectcontents" title="Objekt indhold">
- <text type="string" length="1" name="object_name">
+<floater name="objectcontents" title="OBJEKT INDHOLD">
+ <text name="object_name">
[DESC]:
</text>
<button label="Kopiér til beholdning" label_selected="Kopiér til beholdning"
diff --git a/indra/newview/skins/default/xui/da/floater_pay.xml b/indra/newview/skins/default/xui/da/floater_pay.xml
index cca4240934..f39cfa4871 100644
--- a/indra/newview/skins/default/xui/da/floater_pay.xml
+++ b/indra/newview/skins/default/xui/da/floater_pay.xml
@@ -6,16 +6,16 @@
<button label="L$20" label_selected="L$20" name="fastpay 20" />
<button label="Betal" label_selected="Betal" name="pay btn" />
<button label="Annullér" label_selected="Annullér" name="cancel btn" />
- <text type="string" length="1" name="payee_label" left="5" width="81">
+ <text name="payee_label" left="5" width="81">
Betal beboer:
</text>
- <text type="string" length="1" name="payee_name">
+ <text name="payee_name">
[FIRST] [LAST]
</text>
- <text type="string" length="1" name="fastpay text">
+ <text name="fastpay text">
Hurtig betal:
</text>
- <text type="string" length="1" name="amount text" left="4" >
+ <text name="amount text" left="4" >
Beløb:
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_pay_object.xml b/indra/newview/skins/default/xui/da/floater_pay_object.xml
index 465f7e8e3e..09e2e3f5d0 100644
--- a/indra/newview/skins/default/xui/da/floater_pay_object.xml
+++ b/indra/newview/skins/default/xui/da/floater_pay_object.xml
@@ -1,24 +1,24 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="Give Money" title="">
- <text type="string" length="1" name="payee_group">
+ <text name="payee_group">
Betal gruppe:
</text>
- <text type="string" length="1" name="payee_resident">
+ <text name="payee_resident">
Betal beboer:
</text>
- <text type="string" length="1" name="payee_name">
+ <text name="payee_name">
[FIRST] [LAST]
</text>
- <text type="string" length="1" name="object_name_label">
+ <text name="object_name_label">
Via objekt:
</text>
- <text type="string" length="1" name="object_name_text">
+ <text name="object_name_text">
...
</text>
- <text type="string" length="1" name="fastpay text">
+ <text name="fastpay text">
Hurtig betal:
</text>
- <text type="string" length="1" name="amount text">
+ <text name="amount text">
Beløb:
</text>
<button label="L$1" label_selected="L$1" name="fastpay 1" />
diff --git a/indra/newview/skins/default/xui/da/floater_perm_prefs.xml b/indra/newview/skins/default/xui/da/floater_perm_prefs.xml
new file mode 100644
index 0000000000..69a8d3af94
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/floater_perm_prefs.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="perm prefs" title="STANDARD TILLADELSER VED HENTNING">
+ <panel label="Tilladelser" name="permissions">
+ <button label="?" label_selected="?" name="help"/>
+ <check_box label="Del med gruppe" name="share_with_group"/>
+ <check_box label="Tillad enhver at kopiere" name="everyone_copy"/>
+ <text name="NextOwnerLabel">
+ Næste ejer kan:
+ </text>
+ <check_box label="Redigere" name="next_owner_modify"/>
+ <check_box label="Kopiére" name="next_owner_copy"/>
+ <check_box label="Sælge/Give væk" name="next_owner_transfer"/>
+ </panel>
+ <button label="OK" label_selected="OK" name="ok"/>
+ <button label="Annullér" label_selected="Annullér" name="cancel"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_postcard.xml b/indra/newview/skins/default/xui/da/floater_postcard.xml
index 6b02f43633..cd61e7ac97 100644
--- a/indra/newview/skins/default/xui/da/floater_postcard.xml
+++ b/indra/newview/skins/default/xui/da/floater_postcard.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Postcard" title="E-mail billede">
+<floater name="Postcard" title="E-MAIL BILLEDE">
<text name="to_label">
Send til:
</text>
@@ -25,7 +25,7 @@
<button label="Annullér" name="cancel_btn" />
<button label="Send" name="send_btn" />
<string name="default_subject">
- Postkort fra Second Life.
+ Postkort fra [SECOND_LIFE]
</string>
<string name="default_message">
Tjek det her ud!
diff --git a/indra/newview/skins/default/xui/da/floater_preferences.xml b/indra/newview/skins/default/xui/da/floater_preferences.xml
index 26e932e3cc..e251c9ad2c 100644
--- a/indra/newview/skins/default/xui/da/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/da/floater_preferences.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Preferences" title="Indstillinger">
+<floater name="Preferences" title="INDSTILLINGER">
<button label="OK" label_selected="OK" name="OK" />
<button label="Annullér" label_selected="Annullér" name="Cancel" />
<button label="Gem" label_selected="Gem" name="Apply" />
diff --git a/indra/newview/skins/default/xui/da/floater_preview_animation.xml b/indra/newview/skins/default/xui/da/floater_preview_animation.xml
index 14cf13e317..1494bf36d0 100644
--- a/indra/newview/skins/default/xui/da/floater_preview_animation.xml
+++ b/indra/newview/skins/default/xui/da/floater_preview_animation.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="preview_anim">
- <text type="string" length="1" name="desc txt">
+ <text name="desc txt">
Beskrivelse:
</text>
<button label="Afspil i verden" label_selected="Stop" name="Anim play btn"
diff --git a/indra/newview/skins/default/xui/da/floater_preview_classified.xml b/indra/newview/skins/default/xui/da/floater_preview_classified.xml
index 6cc4c139f1..cf2d14b80a 100644
--- a/indra/newview/skins/default/xui/da/floater_preview_classified.xml
+++ b/indra/newview/skins/default/xui/da/floater_preview_classified.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="classified_preview" title="Annonce information" />
+<floater name="classified_preview" title="ANNONCE INFORMATION" />
diff --git a/indra/newview/skins/default/xui/da/floater_preview_event.xml b/indra/newview/skins/default/xui/da/floater_preview_event.xml
index f1be35e1c3..584085fea0 100644
--- a/indra/newview/skins/default/xui/da/floater_preview_event.xml
+++ b/indra/newview/skins/default/xui/da/floater_preview_event.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="event_preview" title="Event information" />
+<floater name="event_preview" title="EVENT INFORMATION" />
diff --git a/indra/newview/skins/default/xui/da/floater_preview_gesture.xml b/indra/newview/skins/default/xui/da/floater_preview_gesture.xml
index cf3445e1a6..0053cb852f 100644
--- a/indra/newview/skins/default/xui/da/floater_preview_gesture.xml
+++ b/indra/newview/skins/default/xui/da/floater_preview_gesture.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="gesture_preview">
<string name="stop_txt">
Stop
@@ -15,42 +15,42 @@
<text name="trigger_label">
Udløser:
</text>
- <text name="replace_text"
- tool_tip="Replace the trigger word(s) with these words. For example, trigger &apos;hello&apos; replace with &apos;howdy&apos; will turn the chat &apos;I wanted to say hello&apos; into &apos;I wanted to say howdy&apos; as well as playing the gesture!">
+ <text name="replace_text" tool_tip="Replace the trigger word(s) with these words. For example, trigger &apos;hello&apos; replace with &apos;howdy&apos; will turn the chat &apos;I wanted to say hello&apos; into &apos;I wanted to say howdy&apos; as well as playing the gesture!">
Erstat med:
</text>
- <line_editor name="replace_editor"
- tool_tip="Replace the trigger word(s) with these words. For example, trigger &apos;hello&apos; replace with &apos;howdy&apos; will turn the chat &apos;I wanted to say hello&apos; into &apos;I wanted to say howdy&apos; as well as playing the gesture" />
+ <line_editor name="replace_editor" tool_tip="Replace the trigger word(s) with these words. For example, trigger &apos;hello&apos; replace with &apos;howdy&apos; will turn the chat &apos;I wanted to say hello&apos; into &apos;I wanted to say howdy&apos; as well as playing the gesture"/>
<text name="key_label">
Genvejstast:
</text>
- <combo_box label="Ingen" name="modifier_combo" />
- <combo_box label="Ingen" name="key_combo" />
+ <combo_box label="Ingen" name="modifier_combo" width="60"/>
+ <combo_box label="Ingen" name="key_combo" left_delta="70" width="60"/>
<text name="library_label">
Type:
</text>
<text name="steps_label">
Trin:
</text>
- <button label="Tilføj &gt;&gt;" name="add_btn" />
- <button label="Flyt op" name="up_btn" />
- <button label="Flyt ned" name="down_btn" />
- <button label="Fjern" name="delete_btn" />
+ <scroll_list name="library_list">
+ Animation
+Lyd
+Chat
+Vent
+ </scroll_list>
+ <button label="Tilføj &gt;&gt;" name="add_btn"/>
+ <button label="Flyt op" name="up_btn"/>
+ <button label="Flyt ned" name="down_btn"/>
+ <button label="Fjern" name="delete_btn"/>
<text name="help_label">
Alle trin vil ske samtidigt,
medmindre du tilføjer vente trin.
</text>
<radio_group name="animation_trigger_type">
- <radio_item name="start">
- Start
- </radio_item>
- <radio_item name="stop">
- Stop
- </radio_item>
+ <radio_item name="start" label="Start" />
+ <radio_item name="stop" label="Stop" />
</radio_group>
- <check_box label="Indtil animation er færdig" name="wait_anim_check" />
- <check_box label="tid i sekunder" name="wait_time_check" />
- <check_box label="Aktiv" name="active_check" />
- <button label="Vis" name="preview_btn" />
- <button label="Gem" name="save_btn" />
+ <check_box label="Indtil animation er færdig" name="wait_anim_check"/>
+ <check_box label="tid i sekunder" name="wait_time_check"/>
+ <check_box label="Aktiv" name="active_check" tool_tip="Aktive bevægelser kan blive aktiveret ved at skrive deress udløser tekst eller ved at trykke på genvejstaste. Bevægelser vil normalt være inaktive hvis der allerede findes en tilsvarende genvejstaste."/>
+ <button label="Vis" name="preview_btn"/>
+ <button label="Gem" name="save_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_preview_notecard.xml b/indra/newview/skins/default/xui/da/floater_preview_notecard.xml
index c9bee41b6a..7258824878 100644
--- a/indra/newview/skins/default/xui/da/floater_preview_notecard.xml
+++ b/indra/newview/skins/default/xui/da/floater_preview_notecard.xml
@@ -1,12 +1,15 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="preview notecard" title="Note:">
- <button label="Gem" label_selected="Gem" name="Save" />
- <text type="string" length="1" name="desc txt">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="preview notecard" title="NOTE:">
+ <button label="Gem" label_selected="Gem" name="Save"/>
+ <text name="desc txt">
Beskrivelse:
</text>
- <text_editor type="string" length="1" name="Notecard Editor">
+ <text_editor name="Notecard Editor">
Indlæser...
</text_editor>
+ <string name="no_object">
+ Kunne ikke finde objekt der indeholder denne note.
+ </string>
<string name="not_allowed">
Du har ikke tilladelse til at læse denne note.
</string>
diff --git a/indra/newview/skins/default/xui/da/floater_preview_sound.xml b/indra/newview/skins/default/xui/da/floater_preview_sound.xml
index 95a068ae65..9fbfba88b5 100644
--- a/indra/newview/skins/default/xui/da/floater_preview_sound.xml
+++ b/indra/newview/skins/default/xui/da/floater_preview_sound.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="preview_sound">
- <text type="string" length="1" name="desc txt">
+ <text name="desc txt">
Beskrivelse:
</text>
<button label="Afspil lokalt" label_selected="Afspil lokalt" name="Sound audition btn"
diff --git a/indra/newview/skins/default/xui/da/floater_preview_texture.xml b/indra/newview/skins/default/xui/da/floater_preview_texture.xml
index 593e32e4bf..250659f249 100644
--- a/indra/newview/skins/default/xui/da/floater_preview_texture.xml
+++ b/indra/newview/skins/default/xui/da/floater_preview_texture.xml
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="preview_texture">
- <text type="string" length="1" name="desc txt">
+ <text name="desc txt">
Beskrivelse:
</text>
- <text type="string" length="1" name="dimensions">
+ <text name="dimensions">
Størrelse: [WIDTH] x [HEIGHT]
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_region_info.xml b/indra/newview/skins/default/xui/da/floater_region_info.xml
index 9f6e326cf3..5c95c8ed5e 100644
--- a/indra/newview/skins/default/xui/da/floater_region_info.xml
+++ b/indra/newview/skins/default/xui/da/floater_region_info.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="regioninfo" title="Region/Estate" />
+<floater name="regioninfo" title="REGION/ESTATE" />
diff --git a/indra/newview/skins/default/xui/da/floater_report_abuse.xml b/indra/newview/skins/default/xui/da/floater_report_abuse.xml
index 64e39da8fe..9ef17a3cbb 100644
--- a/indra/newview/skins/default/xui/da/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/da/floater_report_abuse.xml
@@ -1,12 +1,14 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_report_abuse" title="Rapportér misbrug">
- <texture_picker label="" name="screenshot" />
- <check_box label="Inkludér billede" name="screen_check" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_report_abuse" title="RAPPORTÉR MISBRUG">
+ <floater.string name="Screenshot">
+ Screenshot
+ </floater.string>
+ <check_box label="Inkludér billede" name="screen_check"/>
<text name="reporter_title">
Anmelder:
</text>
<text name="reporter_field">
- Loremipsum Dolorsitamut
+ Loremipsum Dolorsitamut Longnamez
</text>
<text name="sim_title">
Region:
@@ -23,147 +25,64 @@
<text name="select_object_label">
Klik på knappen derefter objektet:
</text>
- <button label="" label_selected="" name="pick_btn"
- tool_tip="Objekt vælger - Identificér et objekt denne rapport omhandler" />
+ <button label="" label_selected="" name="pick_btn" tool_tip="Objekt vælger - Identificér et objekt denne rapport omhandler"/>
<text name="object_name_label">
Navn:
</text>
- <text name="object_name">
+ <text left_delta="64" name="object_name" width="140">
Consetetur Sadipscing
</text>
<text name="owner_name_label">
Ejer:
</text>
- <text name="owner_name">
- Hendrerit Vulputate
- </text>
- <combo_box name="category_combo"
- tool_tip="Kategori -- Vælg en kategori der passer bedst på denne rapport">
- <combo_item name="Select_category">
- Vælg kategori
- </combo_item>
- <combo_item name="Age__Age_play">
- Alder &gt; Falsk alder
- </combo_item>
- <combo_item name="Age__Adult_resident_on_Teen_Second_Life">
- Alder &gt; Voksen beboer på Teen Second Life
- </combo_item>
-
-
-
- <combo_item name="Assault__Combat_sandbox___unsafe_area">
- Overfald &gt; Kamp sandkasse / Usikkert område
- </combo_item>
- <combo_item name="Assault__Safe_area">
- Overfald &gt; Sikkert område
- </combo_item>
- <combo_item name="Assault__Weapons_testing_sandbox">
- Overfald &gt; Sandkasse til våbentest
- </combo_item>
- <combo_item name="Commerce__Failure_to_deliver_product_or_service">
- Handel &gt; Vare eller ydelse ikke leveret
- </combo_item>
- <combo_item name="Disclosure__Real_world_information">
- Offentliggørelse &gt; Om oplysninger i den virkelige verden
- </combo_item>
- <combo_item name="Disclosure__Remotely_monitoring chat">
- Offentliggørelse &gt; Fjernaflytning af chat
- </combo_item>
- <combo_item name="Disclosure__Second_Life_information_chat_IMs">
- Offentliggørelse &gt; Information/chat/IM fra Second Life
- </combo_item>
- <combo_item name="Disturbing_the_peace__Unfair_use_of_region_resources">
- Forstyrrelse af fred &gt; Unfair brug af region ressourcer
- </combo_item>
- <combo_item name="Disturbing_the_peace__Excessive_scripted_objects">
- Forstyrrelse af fred &gt; Overdreven brug af objekter med script
- </combo_item>
- <combo_item name="Disturbing_the_peace__Object_littering">
- Forstyrrelse af fred &gt; Object affald
- </combo_item>
- <combo_item name="Disturbing_the_peace__Repetitive_spam">
- Forstyrring af fred &gt; Gentagen spam
- </combo_item>
- <combo_item name="Disturbing_the_peace__Unwanted_advert_spam">
- Forstyrrelse af fred &gt; Uønsket reklame spam
- </combo_item>
- <combo_item name="Fraud__L$">
- Bedrageri &gt; L$
- </combo_item>
- <combo_item name="Fraud__Land">
- Bedrageri &gt; Land
- </combo_item>
- <combo_item name="Fraud__Pyramid_scheme_or_chain_letter">
- Bedrageri &gt; Pyramide spil eller kædebreve
- </combo_item>
- <combo_item name="Fraud__US$">
- Bedrageri &gt; US$
- </combo_item>
- <combo_item name="Harassment__Advert_farms___visual_spam">
- Chikane &gt; reklame farm / billedeligt spam
- </combo_item>
- <combo_item name="Harassment__Defaming_individuals_or_groups">
- Chikane &gt; Injurier/bagvask enkeltpersoner eller grupper
- </combo_item>
- <combo_item name="Harassment__Impeding_movement">
- Chikane &gt; Hindre bevægelse
- </combo_item>
- <combo_item name="Harassment__Sexual_harassment">
- Chikane &gt; Sex chikane
- </combo_item>
- <combo_item name="Harassment__Solicting_inciting_others_to_violate_ToS">
- Chikane &gt; Opfordrer/kræver at andre overtræder licensbetingelser
- </combo_item>
- <combo_item name="Harassment__Verbal_abuse">
- Chikane &gt; Verbalt chikane
- </combo_item>
- <combo_item name="Indecency__Broadly_offensive_content_or_conduct">
- Uanstændighed &gt; Meget stødende indhold eller adfærd
- </combo_item>
-
-
-
- <combo_item name="Indecency__Inappropriate_avatar_name">
- Uanstændighed &gt; Upassende avatar navn
- </combo_item>
-
-
-
- <combo_item name="Intellectual_property_infringement_Content_Removal">
- Krænkelse af intellektuelle ejendomsrettigheder &gt; Indholds fjernelse
- </combo_item>
- <combo_item name="Intellectual_property_infringement_CopyBot_or_Permissions_Exploit">
- Krænkelse af intellektuelle ejendomsrettigheder &gt; CopyBot eller omgåelse af rettighedsbeskyttelse
- </combo_item>
- <combo_item name="Intolerance">
- Intolerance
- </combo_item>
- <combo_item name="Land__Abuse_of_sandbox_resources">
- Land &gt; Misbrug af sandkasse resourcer
- </combo_item>
- <combo_item name="Land__Encroachment__Objects_textures">
- Land &gt; Overgreb &gt; Objekter/teksturer
- </combo_item>
- <combo_item name="Land__Encroachment__Particles">
- Land &gt; Overgreb &gt; Partikler
- </combo_item>
- <combo_item name="Land__Encroachment__Trees_plants">
- Land &gt; Overgreb &gt; Træer/planter
- </combo_item>
- <combo_item name="Wagering_gambling">
- Væddemål/gambling
- </combo_item>
- <combo_item name="Other">
- Andet
- </combo_item>
+ <text left_delta="64" name="owner_name">
+ Hendrerit Vulputate Kamawashi Longname
+ </text>
+ <combo_box name="category_combo" tool_tip="Kategori -- Vælg en kategori der passer bedst på denne rapport">
+ <combo_box.item label="Vælg kategori" name="Select_category"/>
+ <combo_box.item label="Alder &gt; Falsk alder" name="Age__Age_play"/>
+ <combo_box.item label="Alder &gt; Voksen beboer på Teen Second Life" name="Age__Adult_resident_on_Teen_Second_Life"/>
+ <combo_box.item label="Alder &gt; Mindreårig beboer udenfor Teen Second Life" name="Age__Underage_resident_outside_of_Teen_Second_Life"/>
+ <combo_box.item label="Overfald &gt; Kamp sandkasse / Usikkert område" name="Assault__Combat_sandbox___unsafe_area"/>
+ <combo_box.item label="Overfald &gt; Sikkert område" name="Assault__Safe_area"/>
+ <combo_box.item label="Overfald &gt; Sandkasse til våbentest" name="Assault__Weapons_testing_sandbox"/>
+ <combo_box.item label="Handel &gt; Vare eller ydelse ikke leveret" name="Commerce__Failure_to_deliver_product_or_service"/>
+ <combo_box.item label="Offentliggørelse &gt; Om oplysninger i den virkelige verden" name="Disclosure__Real_world_information"/>
+ <combo_box.item label="Offentliggørelse &gt; Fjernaflytning af chat" name="Disclosure__Remotely_monitoring chat"/>
+ <combo_box.item label="Offentliggørelse &gt; Information/chat/IM fra Second Life" name="Disclosure__Second_Life_information_chat_IMs"/>
+ <combo_box.item label="Forstyrrelse af fred &gt; Unfair brug af region ressourcer" name="Disturbing_the_peace__Unfair_use_of_region_resources"/>
+ <combo_box.item label="Forstyrrelse af fred &gt; Overdreven brug af objekter med script" name="Disturbing_the_peace__Excessive_scripted_objects"/>
+ <combo_box.item label="Forstyrrelse af fred &gt; Object affald" name="Disturbing_the_peace__Object_littering"/>
+ <combo_box.item label="Forstyrring af fred &gt; Gentagen spam" name="Disturbing_the_peace__Repetitive_spam"/>
+ <combo_box.item label="Forstyrrelse af fred &gt; Uønsket reklame spam" name="Disturbing_the_peace__Unwanted_advert_spam"/>
+ <combo_box.item label="Bedrageri &gt; L$" name="Fraud__L$"/>
+ <combo_box.item label="Bedrageri &gt; Land" name="Fraud__Land"/>
+ <combo_box.item label="Bedrageri &gt; Pyramide spil eller kædebreve" name="Fraud__Pyramid_scheme_or_chain_letter"/>
+ <combo_box.item label="Bedrageri &gt; US$" name="Fraud__US$"/>
+ <combo_box.item label="Chikane &gt; reklame farm / billedeligt spam" name="Harassment__Advert_farms___visual_spam"/>
+ <combo_box.item label="Chikane &gt; Injurier/bagvask enkeltpersoner eller grupper" name="Harassment__Defaming_individuals_or_groups"/>
+ <combo_box.item label="Chikane &gt; Hindre bevægelse" name="Harassment__Impeding_movement"/>
+ <combo_box.item label="Chikane &gt; Sex chikane" name="Harassment__Sexual_harassment"/>
+ <combo_box.item label="Chikane &gt; Opfordrer/kræver at andre overtræder licensbetingelser" name="Harassment__Solicting_inciting_others_to_violate_ToS"/>
+ <combo_box.item label="Chikane &gt; Verbalt chikane" name="Harassment__Verbal_abuse"/>
+ <combo_box.item label="Uanstændighed &gt; Meget stødende indhold eller adfærd" name="Indecency__Broadly_offensive_content_or_conduct"/>
+ <combo_box.item label="Uanstændighed &gt; Upassende avatar navn" name="Indecency__Inappropriate_avatar_name"/>
+ <combo_box.item label="Usømmelighed &gt; Upassende inhold eller opførsel i en &apos;PG&apos; region" name="Indecency__Mature_content_in_PG_region"/>
+ <combo_box.item label="Usømmelighed &gt; Upassende inhold eller opførsel i en &apos;Mature&apos; region" name="Indecency__Inappropriate_content_in_Mature_region"/>
+ <combo_box.item label="Krænkelse af intellektuelle ejendomsrettigheder &gt; Indholds fjernelse" name="Intellectual_property_infringement_Content_Removal"/>
+ <combo_box.item label="Krænkelse af intellektuelle ejendomsrettigheder &gt; CopyBot eller omgåelse af rettighedsbeskyttelse" name="Intellectual_property_infringement_CopyBot_or_Permissions_Exploit"/>
+ <combo_box.item label="Intolerance" name="Intolerance"/>
+ <combo_box.item label="Land &gt; Misbrug af sandkasse resourcer" name="Land__Abuse_of_sandbox_resources"/>
+ <combo_box.item label="Land &gt; Overgreb &gt; Objekter/teksturer" name="Land__Encroachment__Objects_textures"/>
+ <combo_box.item label="Land &gt; Overgreb &gt; Partikler" name="Land__Encroachment__Particles"/>
+ <combo_box.item label="Land &gt; Overgreb &gt; Træer/planter" name="Land__Encroachment__Trees_plants"/>
+ <combo_box.item label="Væddemål/gambling" name="Wagering_gambling"/>
+ <combo_box.item label="Andet" name="Other"/>
</combo_box>
<text name="abuser_name_title">
Udøvers navn:
</text>
- <button label="Vælg beboer" label_selected="" name="select_abuser"
- tool_tip="Vælg navnet på udøveren fra denne liste" />
- <check_box label="Kender ikke udøvers navn" name="omit_abuser_name"
- tool_tip="Afkryds her, hvis du ikke kender navn på udøvers" />
+ <button label="Vælg beboer" label_selected="" name="select_abuser" tool_tip="Vælg navnet på udøveren fra denne liste"/>
<text name="abuser_name_title2">
Sted for misbrug/overgreb:
</text>
@@ -174,11 +93,11 @@
Detaljer:
</text>
<text name="bug_aviso">
- Vær venligst præcis omkring dato, sted, overgrebets natur, relevant chat/IM og vælg objekt hvis muligt.
+ Vær venligst så præcis som muligt
</text>
<text name="incomplete_title">
- Note: Ufuldstændige rapporter vil ikke blive undersøgt.
+ * Note: Ufuldstændige rapporter vil ikke blive undersøgt.
</text>
- <button label="Annullér" label_selected="Annullér" name="cancel_btn" />
- <button label="Rapporter misbrug" label_selected="Rapporter misbrug" name="send_btn" />
+ <button label="Rapporter misbrug" label_selected="Rapporter misbrug" name="send_btn"/>
+ <button label="Annullér" label_selected="Annullér" name="cancel_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_script_debug.xml b/indra/newview/skins/default/xui/da/floater_script_debug.xml
index 17e14cd9b9..df60a2e23f 100644
--- a/indra/newview/skins/default/xui/da/floater_script_debug.xml
+++ b/indra/newview/skins/default/xui/da/floater_script_debug.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<multi_floater name="script debug floater" title="Script advarsel/fejl">
<tab_container name="Preview Tabs">
- <floater label="Script" name="all_scripts" title="[All scripts]" />
+ <floater label="Script" name="all_scripts" title="[ALL SCRIPTS]" />
</tab_container>
</multi_floater>
diff --git a/indra/newview/skins/default/xui/da/floater_script_preview.xml b/indra/newview/skins/default/xui/da/floater_script_preview.xml
index 26371d864f..ede277bbd2 100644
--- a/indra/newview/skins/default/xui/da/floater_script_preview.xml
+++ b/indra/newview/skins/default/xui/da/floater_script_preview.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="preview lsl text" title="Script: Rotation Script">
- <text type="string" length="1" name="desc txt">
+<floater name="preview lsl text" title="SCRIPT: ROTATION SCRIPT">
+ <text name="desc txt">
Beskrivelse:
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_script_queue.xml b/indra/newview/skins/default/xui/da/floater_script_queue.xml
index 47dbf534bd..3f54c92426 100644
--- a/indra/newview/skins/default/xui/da/floater_script_queue.xml
+++ b/indra/newview/skins/default/xui/da/floater_script_queue.xml
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="queue" title="Nulstil forløb">
+<floater name="queue" title="NULSTIL FORLØB">
<button label="Luk" label_selected="Luk" name="close" />
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_script_search.xml b/indra/newview/skins/default/xui/da/floater_script_search.xml
index 9f51d3bbfd..62f311be6e 100644
--- a/indra/newview/skins/default/xui/da/floater_script_search.xml
+++ b/indra/newview/skins/default/xui/da/floater_script_search.xml
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script search" title="Script søgning">
+<floater name="script search" title="SCRIPT SØGNING">
<check_box label="Store/små bogstaver har ingen betydning" name="case_text" />
<button label="Søg" label_selected="Søg" name="search_btn" />
<button label="Erstat" label_selected="Erstat" name="replace_btn" />
<button label="Erstat alle" label_selected="Erstat alle" name="replace_all_btn" />
- <text type="string" length="1" name="txt">
+ <text name="txt">
Søg
</text>
- <text type="string" length="1" name="txt2">
+ <text name="txt2">
Erstat
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_select_key.xml b/indra/newview/skins/default/xui/da/floater_select_key.xml
index 53bb7dd525..7fa868a3a9 100644
--- a/indra/newview/skins/default/xui/da/floater_select_key.xml
+++ b/indra/newview/skins/default/xui/da/floater_select_key.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="modal container" title="">
<button label="Annullér" label_selected="Annullér" name="Cancel" />
- <text type="string" length="1" name="Save item as:">
+ <text name="Save item as:">
Tryk på en taste for at vælge
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_sell_land.xml b/indra/newview/skins/default/xui/da/floater_sell_land.xml
index dbf9433872..fcbe0abe08 100644
--- a/indra/newview/skins/default/xui/da/floater_sell_land.xml
+++ b/indra/newview/skins/default/xui/da/floater_sell_land.xml
@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="sell land" title="Sælg land">
+<floater name="sell land" title="SÆLG LAND">
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
<text name="info_parcel_label">
Parcel:
</text>
@@ -34,15 +36,9 @@
Vælg om du vil sælge til hvem som helst eller en specifik køber.
</text>
<combo_box name="sell_to">
- <combo_item name="--selectone--">
- -- Vælg --
- </combo_item>
- <combo_item name="Anyone">
- Alle
- </combo_item>
- <combo_item name="Specificuser:">
- Specifik bruger:
- </combo_item>
+ <combo_box.item name="--selectone--" label="Vælg --" />
+ <combo_box.item name="Anyone" label="Alle" />
+ <combo_box.item name="Specificuser:" label="Specifik bruger:" />
</combo_box>
<button label="Vælg..." name="sell_to_select_agent" />
<text name="sell_objects_label">
@@ -52,12 +48,8 @@
Dine objekter der kan videregives sælges med jorden.
</text>
<radio_group name="sell_objects">
- <radio_item name="no">
- Nej, behold ejerskab til objekterne
- </radio_item>
- <radio_item name="yes">
- Ja, sælg objekter med jorden
- </radio_item>
+ <radio_item name="no" label="Nej, behold ejerskab til objekterne" />
+ <radio_item name="yes" label="Ja, sælg objekter med jorden" />
</radio_group>
<button label="Vis objekter" name="show_objects" />
<text name="nag_message_label">
@@ -65,4 +57,6 @@
</text>
<button label="Sæt land til salg" name="sell_btn" />
<button label="Annullér" name="cancel_btn" />
+ </panel>
+ </scroll_container>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_settings_debug.xml b/indra/newview/skins/default/xui/da/floater_settings_debug.xml
index f9cb4d0186..c1429ed3a3 100644
--- a/indra/newview/skins/default/xui/da/floater_settings_debug.xml
+++ b/indra/newview/skins/default/xui/da/floater_settings_debug.xml
@@ -1,12 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="settings_debug" title="Tekniske indstillinger">
+<floater name="settings_debug" title="TEKNISKE INDSTILLINGER">
<combo_box name="boolean_combo">
- <combo_item name="TRUE">
- TRUE (Valgt)
- </combo_item>
- <combo_item name="FALSE">
- FALSE (Fravalgt)
- </combo_item>
+ <combo_box.item name="TRUE" label="TRUE (Valgt)" />
+ <combo_box.item name="FALSE" label="FALSE (Fravalgt)" />
</combo_box>
<color_swatch label="Farve" name="color_swatch" />
<spinner label="x" name="val_spinner_1" />
diff --git a/indra/newview/skins/default/xui/da/floater_snapshot.xml b/indra/newview/skins/default/xui/da/floater_snapshot.xml
index 8fc98220db..3eed869db4 100644
--- a/indra/newview/skins/default/xui/da/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/da/floater_snapshot.xml
@@ -1,29 +1,26 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Snapshot" title="Se foto">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Snapshot" title="SE FOTO">
<text name="type_label">
Hvor skal foto hen?
</text>
<radio_group label="Snapshot type" name="snapshot_type_radio">
- <radio_item name="postcard">
- Send via e-mail
- </radio_item>
- <radio_item name="texture">
- Gem i din beholdning (L$[AMOUNT])
- </radio_item>
- <radio_item name="local">
- Gem på din computer
- </radio_item>
+ <radio_item name="postcard" label="Send via e-mail" />
+ <radio_item name="texture" label="Gem i din beholdning (L$[AMOUNT])" />
+ <radio_item name="local" label="Gem på din computer" />
</radio_group>
<text name="file_size_label">
Fil størrelse: [SIZE] KB
</text>
- <button label="Tag nyt foto" name="new_snapshot_btn" />
- <button label="Send" name="send_btn" />
- <button label="Gem (L$[AMOUNT])" name="upload_btn" />
- <flyout_button label="Gem" name="save_btn" />
- <button label="Annullér" name="discard_btn" />
- <button label="Mere &gt;&gt;" name="more_btn" />
- <button label="&lt;&lt; Mindre" name="less_btn" />
+ <button label="Tag nyt foto" name="new_snapshot_btn"/>
+ <button label="Send" name="send_btn"/>
+ <button label="Gem (L$[AMOUNT])" name="upload_btn"/>
+ <flyout_button label="Gem" name="save_btn" tool_tip="Gem billede i på din computer">
+ <flyout_button_item name="save_item" label="Gem"/>
+ <flyout_button_item name="saveas_item" label="Gem som..."/>
+ </flyout_button>
+ <button label="Annullér" name="discard_btn"/>
+ <button label="Mere &gt;&gt;" name="more_btn" tool_tip="Avancerede valg"/>
+ <button label="&lt;&lt; Mindre" name="less_btn" tool_tip="Avancerede valg"/>
<text name="type_label2">
Størrelse
</text>
@@ -31,97 +28,52 @@
Format
</text>
<combo_box label="Opløsning" name="postcard_size_combo">
- <combo_item name="CurrentWindow">
- Aktuelle vindue
- </combo_item>
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
- <combo_item name="Custom">
- Manuel
- </combo_item>
+ <combo_box.item name="CurrentWindow" label="Aktuelle vindue"/>
+ <combo_box.item name="640x480" label="640x480"/>
+ <combo_box.item name="800x600" label="800x600"/>
+ <combo_box.item name="1024x768" label="1024x768"/>
+ <combo_box.item name="Custom" label="Manuel"/>
</combo_box>
<combo_box label="Opløsning" name="texture_size_combo">
- <combo_item name="CurrentWindow">
- Aktuelle vindue
- </combo_item>
- <combo_item name="Small(128x128)">
- Lille (128x128)
- </combo_item>
- <combo_item name="Medium(256x256)">
- Medium (256x256)
- </combo_item>
- <combo_item name="Large(512x512)">
- Stor (512x512)
- </combo_item>
- <combo_item name="Custom">
- Manuel
- </combo_item>
+ <combo_box.item name="CurrentWindow" label="Aktuelle vindue"/>
+ <combo_box.item name="Small(128x128)" label="Lille (128x128)"/>
+ <combo_box.item name="Medium(256x256)" label="Medium (256x256)"/>
+ <combo_box.item name="Large(512x512)" label="Stor (512x512)"/>
+ <combo_box.item name="Custom" label="Manuel"/>
</combo_box>
<combo_box label="Opløsning" name="local_size_combo">
- <combo_item name="CurrentWindow">
- Aktuelle vindue
- </combo_item>
- <combo_item name="320x240">
- 320x240
- </combo_item>
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
- <combo_item name="1280x1024">
- 1280x1024
- </combo_item>
- <combo_item name="1600x1200">
- 1600x1200
- </combo_item>
- <combo_item name="Custom">
- Manuelt
- </combo_item>
+ <combo_box.item name="CurrentWindow" label="Aktuelle vindue"/>
+ <combo_box.item name="320x240" label="320x240"/>
+ <combo_box.item name="640x480" label="640x480"/>
+ <combo_box.item name="800x600" label="800x600"/>
+ <combo_box.item name="1024x768" label="1024x768"/>
+ <combo_box.item name="1280x1024" label="1280x1024"/>
+ <combo_box.item name="1600x1200" label="1600x1200"/>
+ <combo_box.item name="Custom" label="Manuelt"/>
</combo_box>
- <combo_box label="Fil-format" name="local_format_combo">
- <combo_item name="PNG">
- PNG
- </combo_item>
- <combo_item name="JPEG">
- JPEG
- </combo_item>
- <combo_item name="BMP">
- BMP
- </combo_item>
+ <combo_box label="Fil-format" name="local_format_combo" width="76">
+ <combo_box.item name="PNG" label="PNG"/>
+ <combo_box.item name="JPEG" label="JPEG"/>
+ <combo_box.item name="BMP" label="BMP"/>
</combo_box>
- <spinner label="Bredde" name="snapshot_width" />
- <spinner label="Højde" name="snapshot_height" />
- <check_box label="Fasthold proportioner" name="keep_aspect_check" />
- <slider label="Billed-kvalitet" name="image_quality_slider" />
+ <spinner label="Bredde" name="snapshot_width" label_width="41" width="101"/>
+ <spinner label="Højde" name="snapshot_height" label_width="32" width="92" left="117"/>
+ <check_box label="Fasthold proportioner" name="keep_aspect_check"/>
+ <slider label="Billed-kvalitet" name="image_quality_slider"/>
<text name="layer_type_label">
Benyt:
</text>
<combo_box label="Billedlag" name="layer_types">
- <combo_item name="Colors">
- Farver
- </combo_item>
- <combo_item name="Depth">
- Dybde
- </combo_item>
- <combo_item name="ObjectMattes">
- Materinger
- </combo_item>
+ <combo_box.item name="Colors" label="Farver"/>
+ <combo_box.item name="Depth" label="Dybde"/>
+ <combo_box.item name="ObjectMattes" label="Materinger"/>
</combo_box>
- <check_box label="Vis brugerflade på foto" name="ui_check" />
- <check_box label="Vis HUD objekter på foto" name="hud_check" />
- <check_box label="Luk ikke vindue ved gemning" name="keep_open_check" />
- <check_box label="Frys billede og vis" name="freeze_frame_check" />
- <check_box label="Auto-opdater" name="auto_snapshot_check" />
+ <check_box label="Vis brugerflade på foto" name="ui_check"/>
+ <check_box label="Vis HUD objekter på foto" name="hud_check"/>
+ <check_box label="Luk ikke vindue ved gemning" name="keep_open_check"/>
+ <check_box label="Frys billede og vis" name="freeze_frame_check"/>
+ <check_box label="Auto-opdater" name="auto_snapshot_check"/>
+ <string name="unknown">
+ ukendt
+ </string>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_sound_preview.xml b/indra/newview/skins/default/xui/da/floater_sound_preview.xml
index c0d2f76ea9..e54bdf4f42 100644
--- a/indra/newview/skins/default/xui/da/floater_sound_preview.xml
+++ b/indra/newview/skins/default/xui/da/floater_sound_preview.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Name/Description" title="sound.wav">
+<floater name="Sound Preview" title="SOUND.WAV">
<text name="name_label">
Navn:
</text>
diff --git a/indra/newview/skins/default/xui/da/floater_statistics.xml b/indra/newview/skins/default/xui/da/floater_statistics.xml
new file mode 100644
index 0000000000..8c33f3ecb3
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/floater_statistics.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="stats floater" title="STATISTIK"/>
diff --git a/indra/newview/skins/default/xui/da/floater_stats.xml b/indra/newview/skins/default/xui/da/floater_stats.xml
new file mode 100644
index 0000000000..fe3fa9626e
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/floater_stats.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Statistics" title="STATISTIK">
+ <scroll_container name="statistics_scroll">
+ <container_view name="statistics_view">
+ <stat_view label="Grundlæggende" name="basic">
+ <stat_bar label="FPS" name="fps"/>
+ <stat_bar label="BÃ¥ndbredde" name="bandwidth"/>
+ <stat_bar label="Pakketab" name="packet_loss"/>
+ <stat_bar label="Ping Sim" name="ping"/>
+ </stat_view>
+ <stat_view label="Avanceret" name="advanced">
+ <stat_view label="Render" name="render">
+ <stat_bar label="KTris tegnet" name="ktrisframe"/>
+ <stat_bar label="KTris tegnet" name="ktrissec"/>
+ <stat_bar label="Total antal objekter" name="objs"/>
+ <stat_bar label="Nye objekter" name="newobjs"/>
+ </stat_view>
+ <stat_view label="Texture" name="texture">
+ <stat_bar label="Count" name="numimagesstat"/>
+ <stat_bar label="Raw Count" name="numrawimagesstat"/>
+ <stat_bar label="GL Mem" name="gltexmemstat"/>
+ <stat_bar label="Formatted Mem" name="formattedmemstat"/>
+ <stat_bar label="Raw Mem" name="rawmemstat"/>
+ <stat_bar label="Bound Mem" name="glboundmemstat"/>
+ </stat_view>
+ <stat_view label="Netværk" name="network">
+ <stat_bar label="Packets In" name="packetsinstat"/>
+ <stat_bar label="Packets Out" name="packetsoutstat"/>
+ <stat_bar label="Objekter" name="objectkbitstat"/>
+ <stat_bar label="Texture" name="texturekbitstat"/>
+ <stat_bar label="Asset" name="assetkbitstat"/>
+ <stat_bar label="Layers" name="layerskbitstat"/>
+ <stat_bar label="Actual In" name="actualinkbitstat"/>
+ <stat_bar label="Actual Out" name="actualoutkbitstat"/>
+ <stat_bar label="VFS Pending Ops" name="vfspendingoperations"/>
+ </stat_view>
+ </stat_view>
+ <stat_view label="Simulator" name="sim">
+ <stat_bar label="Time Dilation" name="simtimedilation"/>
+ <stat_bar label="Sim FPS" name="simfps"/>
+ <stat_bar label="Physics FPS" name="simphysicsfps"/>
+ <stat_view label="Physics Details" name="physicsdetail">
+ <stat_bar label="Pinned Objects" name="physicspinnedtasks"/>
+ <stat_bar label="Low LOD Objects" name="physicslodtasks"/>
+ <stat_bar label="Memory Allocated" name="physicsmemoryallocated"/>
+ <stat_bar label="Agent Updates/Sec" name="simagentups"/>
+ <stat_bar label="Main Agents" name="simmainagents"/>
+ <stat_bar label="Child Agents" name="simchildagents"/>
+ <stat_bar label="Objects" name="simobjects"/>
+ <stat_bar label="Active Objects" name="simactiveobjects"/>
+ <stat_bar label="Active Scripts" name="simactivescripts"/>
+ <stat_bar label="Script Events" name="simscripteps"/>
+ <stat_bar label="Packets In" name="siminpps"/>
+ <stat_bar label="Packets Out" name="simoutpps"/>
+ <stat_bar label="Pending Downloads" name="simpendingdownloads"/>
+ <stat_bar label="Pending Uploads" name="simpendinguploads"/>
+ <stat_bar label="Total Unacked Bytes" name="simtotalunackedbytes"/>
+ </stat_view>
+ <stat_view label="Time (ms)" name="simperf">
+ <stat_bar label="Total Frame Time" name="simframemsec"/>
+ <stat_bar label="Net Time" name="simnetmsec"/>
+ <stat_bar label="Physics Time" name="simsimphysicsmsec"/>
+ <stat_bar label="Simulation Time" name="simsimothermsec"/>
+ <stat_bar label="Agent Time" name="simagentmsec"/>
+ <stat_bar label="Images Time" name="simimagesmsec"/>
+ <stat_bar label="Script Time" name="simscriptmsec"/>
+ </stat_view>
+ </stat_view>
+ </container_view>
+ </scroll_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_telehub.xml b/indra/newview/skins/default/xui/da/floater_telehub.xml
index 32c5448508..bf31da9515 100644
--- a/indra/newview/skins/default/xui/da/floater_telehub.xml
+++ b/indra/newview/skins/default/xui/da/floater_telehub.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="telehub" title="Telehub">
+<floater name="telehub" title="TELEHUB">
<text name="status_text_connected">
Telehub forbundet til objekt [OBJECT]
</text>
@@ -14,15 +14,15 @@
</text>
<button label="Forbind telehub" name="connect_btn" />
<button label="Afslut" name="disconnect_btn" />
- <text name="spawn_points_text">
+ <text name="spawn_points_text" width="300">
Ankomst punkter (positioner, ikke objekter):
</text>
<button label="Tilføj punkt" name="add_spawn_point_btn" />
<button label="Fjern punkt" name="remove_spawn_point_btn" />
<text name="spawn_point_help">
- Vælg objekt og klik på &apos;Tilføj punkt&apos;for at angive position.
-Du kan derefter flytte eller slette objektet.
-Positioner er i forhold til telehub center.
+ Vælg objekt og klik på &apos;Tilføj punkt&apos;for at angive
+position. Du kan derefter flytte eller slette
+objektet. Positioner er i forhold til telehub center.
Vælg emne i listen for at vise position i verden.
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/da/floater_texture_ctrl.xml
index 513a629bfa..4167e2938a 100644
--- a/indra/newview/skins/default/xui/da/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/da/floater_texture_ctrl.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="texture picker" title="Vælg: Tekstur">
+<floater name="texture picker" title="VÆLG: TEKSTUR">
<string name="choose_picture">
Klik for at vælge et billede
</string>
- <text type="string" length="1" name="Multiple">
+ <text name="Multiple">
Flere
</text>
- <text type="string" length="1" name="unknown">
+ <text name="unknown">
Størrelse: [DIMENSIONS]
</text>
<button label="Standard" label_selected="Standard" name="Default" />
diff --git a/indra/newview/skins/default/xui/da/floater_tools.xml b/indra/newview/skins/default/xui/da/floater_tools.xml
index bc15db0e25..c3287bac84 100644
--- a/indra/newview/skins/default/xui/da/floater_tools.xml
+++ b/indra/newview/skins/default/xui/da/floater_tools.xml
@@ -1,39 +1,39 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="toolbox floater" title="">
- <button label="" label_selected="" name="button focus" tool_tip="Fokus" />
- <button label="" label_selected="" name="button move" tool_tip="Flyt" />
- <button label="" label_selected="" name="button edit" tool_tip="Redigér" />
- <button label="" label_selected="" name="button create" tool_tip="Opret" />
- <button label="" label_selected="" name="button land" tool_tip="Land" />
- <check_box label="Zoom" name="radio zoom" />
- <check_box label="Kredsløb (Ctrl)" name="radio orbit" />
- <check_box label="Panorér (Ctrl-Shift)" name="radio pan" />
- <check_box label="Flyt" name="radio move" />
- <check_box label="Løft (Ctrl)" name="radio lift" />
- <check_box label="Spin (Ctrl-Shift)" name="radio spin" />
- <check_box label="Position" name="radio position" />
- <check_box label="Rotér (Ctrl)" name="radio rotate" />
- <check_box label="Stræk (Ctrl-Shift)" name="radio stretch" />
- <check_box label="Vælg tekstur" name="radio select face" />
- <check_box label="Redigér sammenlænkede dele" name="checkbox edit linked parts" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="toolbox floater" title="" short_title="BYG">
+ <button label="" label_selected="" name="button focus" tool_tip="Fokus"/>
+ <button label="" label_selected="" name="button move" tool_tip="Flyt"/>
+ <button label="" label_selected="" name="button edit" tool_tip="Redigér"/>
+ <button label="" label_selected="" name="button create" tool_tip="Opret"/>
+ <button label="" label_selected="" name="button land" tool_tip="Land"/>
+ <radio_group name="focus_radio_group">
+ <radio_item label="Zoom" name="radio zoom"/>
+ <radio_item label="Kredsløb (Ctrl)" name="radio orbit"/>
+ <radio_item label="Panorér (Ctrl-Shift)" name="radio pan"/>
+ </radio_group>
+ <radio_group name="move_radio_group">
+ <radio_item label="Flyt" name="radio move"/>
+ <radio_item label="Løft (Ctrl)" name="radio lift"/>
+ <radio_item label="Spin (Ctrl-Shift)" name="radio spin"/>
+ </radio_group>
+ <radio_group name="edit_radio_group">
+ <radio_item label="Position" name="radio position"/>
+ <radio_item label="Rotér (Ctrl)" name="radio rotate"/>
+ <radio_item label="Stræk (Ctrl-Shift)" name="radio stretch"/>
+ <radio_item label="Vælg tekstur" name="radio select face"/>
+ </radio_group>
+ <check_box label="Redigér sammenlænkede dele" name="checkbox edit linked parts"/>
<text name="text ruler mode">
Lineal:
</text>
<combo_box name="combobox grid mode">
- <combo_item name="World">
- Verden
- </combo_item>
- <combo_item name="Local">
- Lokal
- </combo_item>
- <combo_item name="Reference">
- Reference
- </combo_item>
+ <combo_box.item name="World" label="Verden"/>
+ <combo_box.item name="Local" label="Lokal"/>
+ <combo_box.item name="Reference" label="Reference"/>
</combo_box>
- <check_box label="Stræk begge sider" name="checkbox uniform" />
- <check_box label="Stræk teksturer" name="checkbox stretch textures" />
- <check_box label="Benyt gitter" name="checkbox snap to grid" />
- <button label="Valg..." label_selected="Valg..." name="Options..." />
+ <check_box label="Stræk begge sider" name="checkbox uniform"/>
+ <check_box label="Stræk teksturer" name="checkbox stretch textures"/>
+ <check_box label="Benyt gitter" name="checkbox snap to grid"/>
+ <button label="Valg..." label_selected="Valg..." name="Options..." height="18" bottom_delta="-15"/>
<text name="text status">
Træk for at flytte, shift+træk for at kopiere
</text>
@@ -54,34 +54,37 @@
<button label="" label_selected="" name="ToolGrass" tool_tip="Græs" />
<check_box label="Hold værktøjet valgt" name="checkbox sticky" />
<check_box label="Kopiér valgte" name="checkbox copy selection" />
- <check_box label="Centréret kopi" name="checkbox copy centers" />
- <check_box label="Rotér kopi" name="checkbox copy rotates" />
- <check_box label="Vælg land" name="radio select land" />
- <check_box label="Udflad land" name="radio flatten" />
- <check_box label="Hæv land" name="radio raise" />
- <check_box label="Sænk land" name="radio lower" />
- <check_box label="Udjævn land" name="radio smooth" />
- <check_box label="Gør land ujævnt" name="radio noise" />
- <check_box label="Tilbagefør" name="radio revert" />
+ <check_box label="Centreret kopi" name="checkbox copy centers" />
+ <check_box label="Rotér" name="checkbox copy rotates" />
+ <radio_group name="land_radio_group">
+ <radio_item label="Vælg" name="radio select land" />
+ <radio_item label="Udflad" name="radio flatten" />
+ <radio_item label="Hæv" name="radio raise" />
+ <radio_item label="Sænk" name="radio lower" />
+ <radio_item label="Udjævn" name="radio smooth" />
+ <radio_item label="Gør ujævnt" name="radio noise" />
+ <radio_item label="Tilbagefør" name="radio revert" />
+ </radio_group>
<combo_box name="combobox brush size">
- <combo_item name="Small">
- Lille
- </combo_item>
- <combo_item name="Medium">
- Mellem
- </combo_item>
- <combo_item name="Large">
- Stor
- </combo_item>
+ <combo_box.item name="Small" label="Lille"/>
+ <combo_box.item name="Medium" label="Mellem"/>
+ <combo_box.item name="Large" label="Stor"/>
</combo_box>
- <text type="string" length="1" name="Strength:">
+ <text name="Strength:">
Styrke:
</text>
- <button label="Anvend på valgte" label_selected="Anvend på valgte"
- name="button apply to selection" tool_tip="Redigér valgt land" />
- <check_box label="Vis ejere" name="checkbox show owners" />
- <button label="Mere &gt;&gt;" name="button more" tool_tip="Adancerede valgmuligheder" />
- <button label="&lt;&lt; Mindre" name="button less" tool_tip="Adancerede valgmuligheder" />
+ <text name="Dozer Size:">
+ Størrelse
+ </text>
+ <text name="Strength:">
+ Styrke
+ </text>
+ <text name="obj_count">
+ Valgte objekter: [COUNT]
+ </text>
+ <text name="prim_count">
+ prims: [COUNT]
+ </text>
<tab_container name="Object Info Tabs">
<panel label="Generelt" name="General">
<text name="Name:">
@@ -96,91 +99,62 @@
<text name="Creator Name">
Thrax Linden
</text>
- <button label="Profil..." label_selected="Profil..." name="button creator profile" />
+ <button label="Profil..." label_selected="Profil..." name="button creator profile"/>
<text name="Owner:">
Ejer:
</text>
<text name="Owner Name">
Thrax Linden
</text>
- <button label="Profil..." label_selected="Profil..." name="button owner profile" />
+ <button label="Profil..." label_selected="Profil..." name="button owner profile"/>
<text name="Group:">
Gruppe:
</text>
<text name="Group Name Proxy">
The Lindens
</text>
- <button label="Sæt..." label_selected="Sæt..." name="button set group" />
- <text name="prim info">
- 1 Objekt, 1 Prim
- </text>
+ <button label="Sæt..." label_selected="Sæt..." name="button set group"/>
<text name="Permissions:">
Tilladelser:
</text>
- <text name="perm_modify">
- Du kan redigére dette objekt.
- </text>
- <check_box label="Del med gruppe" name="checkbox share with group"
- tool_tip="Tillad gruppemedlemmer at flytte, ændre, kopiere og slette." />
+
+ <check_box label="Del med gruppe" name="checkbox share with group" tool_tip="Tillad gruppemedlemmer at flytte, ændre, kopiere og slette."/>
<string name="text deed continued">
Deed...
</string>
<string name="text deed">
Deed
</string>
- <button label="Dedikér..." label_selected="Dedikér..." name="button deed"
- tool_tip="Gruppedelte genstande kan dedikeres af en gruppeadministrator." />
- <check_box label="Tillad enhver at flytte" name="checkbox allow everyone move" />
- <check_box label="Tillad enhver at kopiére" name="checkbox allow everyone copy" />
- <check_box label="Vis i søgning" name="search_check"
- tool_tip="Lad folk se dette objekt i søgeresultater" />
- <check_box label="Til salg" name="checkbox for sale" />
+ <button label="Dedikér..." label_selected="Dedikér..." name="button deed" tool_tip="Gruppedelte genstande kan dedikeres af en gruppeadministrator."/>
+ <check_box label="Tillad enhver at flytte" name="checkbox allow everyone move"/>
+ <check_box label="Tillad enhver at kopiére" name="checkbox allow everyone copy"/>
+ <check_box label="Vis i søgning" name="search_check" tool_tip="Lad folk se dette objekt i søgeresultater"/>
+ <check_box label="Til salg" name="checkbox for sale"/>
<text name="Cost">
Pris: L$
</text>
- <radio_group name="sale type">
- <radio_item name="Original">
- Original
- </radio_item>
- <radio_item name="Copy">
- Kopi
- </radio_item>
- <radio_item name="Contents">
- Indhold
- </radio_item>
- </radio_group>
- <text name="Next owner can:">
- Næste ejer kan:
- </text>
- <check_box label="Redigére" name="checkbox next owner can modify" />
- <check_box label="Kopiére" name="checkbox next owner can copy" />
- <check_box label="Sælge/Give væk" name="checkbox next owner can transfer" />
+ <combo_box name="sale type">
+ <combo_box.item label="Kopi" name="Copy"/>
+ <combo_box.item label="Indhold" name="Contents"/>
+ <combo_box.item label="Original" name="Original"/>
+ </combo_box>
+
<text name="label click action">
NÃ¥r der venstreklikkes:
</text>
<combo_box name="clickaction">
- <combo_item name="Touch/grab(default)">
- Rør/tag (standard)
- </combo_item>
- <combo_item name="Sitonobject">
- Sid på objekt
- </combo_item>
- <combo_item name="Buyobject">
- Køb objekt
- </combo_item>
- <combo_item name="Payobject">
- Betal objekt
- </combo_item>
- <combo_item name="Open">
- Ã…ben
- </combo_item>
- <combo_item name="Play">
- Afspil medie på parcel
- </combo_item>
- <combo_item name="Opemmedia">
- Åben media på parcel
- </combo_item>
+ <combo_box.item name="Touch/grab(default)" label="Rør/tag (standard)"/>
+ <combo_box.item name="Sitonobject" label="Sid på objekt"/>
+ <combo_box.item name="Buyobject" label="Køb objekt"/>
+ <combo_box.item name="Payobject" label="Betal objekt"/>
+ <combo_box.item name="Open" label="Ã…ben"/>
+ <combo_box.item name="Play" label="Afspil medie på parcel"/>
+ <combo_box.item name="Opemmedia" label="Åben media på parcel"/>
</combo_box>
+ <panel name="perms_build">
+ <text name="perm_modify">
+ Du kan redigére dette objekt
+ </text>
<text name="B:">
B:
</text>
@@ -199,6 +173,43 @@
<text name="F:">
F:
</text>
+ <text name="Next owner can:">
+ Næste ejer kan:
+ </text>
+ <check_box label="Redigére" name="checkbox next owner can modify"/>
+ <check_box label="Kopiére" name="checkbox next owner can copy" left_delta="80"/>
+ <check_box name="checkbox next owner can transfer" left_delta="67"/>
+ </panel>
+ <string name="text modify info 1">
+ Du kan redigere dette objekt
+ </string>
+ <string name="text modify info 2">
+ Du kan redigere disse objekter
+ </string>
+ <string name="text modify info 3">
+ Du kan ikke redigere dette objekt
+ </string>
+ <string name="text modify info 4">
+ Du kan ikke redigere disse objekter
+ </string>
+ <string name="text modify warning">
+ Du skal vælge hele objektet for at sætte rettigheder
+ </string>
+ <string name="Cost Default">
+ Pris: L$
+ </string>
+ <string name="Cost Total">
+ Total pris: L$
+ </string>
+ <string name="Cost Per Unit">
+ Pris Pr: L$
+ </string>
+ <string name="Cost Mixed">
+ Blandet pris
+ </string>
+ <string name="Sale Mixed">
+ Blandet salg
+ </string>
</panel>
<panel label="Objekt" name="Object">
<text name="select_single">
@@ -207,92 +218,58 @@
<text name="edit_object">
Ret objektets indstillinger:
</text>
- <check_box label="LÃ¥st" name="checkbox locked"
- tool_tip="Forhindrer objektet i at blive flyttet eller slettet. Ofte brugbar under byggeri for at forhindre utilsigtet ændring." />
- <check_box label="Fysisk" name="Physical Checkbox Ctrl"
- tool_tip="Tillader objekter at blive skubbet og at være påvirkelig af tyngdekraften" />
- <check_box label="Temporær" name="Temporary Checkbox Ctrl"
- tool_tip="Medfårer at objekter bliver slettet 1 minut efter de er skabt." />
- <check_box label="Uden masse" name="Phantom Checkbox Ctrl"
- tool_tip="FÃ¥r objektet til ikke at kollidere med andre objekter eller personer" />
+ <check_box label="Låst" name="checkbox locked" tool_tip="Forhindrer objektet i at blive flyttet eller slettet. Ofte brugbar under byggeri for at forhindre utilsigtet ændring."/>
+ <check_box label="Fysisk" name="Physical Checkbox Ctrl" tool_tip="Tillader objekter at blive skubbet og at være påvirkelig af tyngdekraften"/>
+ <check_box label="Temporær" name="Temporary Checkbox Ctrl" tool_tip="Medfårer at objekter bliver slettet 1 minut efter de er skabt."/>
+ <check_box label="Uden masse" name="Phantom Checkbox Ctrl" tool_tip="FÃ¥r objektet til ikke at kollidere med andre objekter eller personer"/>
<text name="label position">
Position (meter)
</text>
- <spinner label="X" name="Pos X" />
- <spinner label="Y" name="Pos Y" />
- <spinner label="Z" name="Pos Z" />
+ <spinner label="X" name="Pos X"/>
+ <spinner label="Y" name="Pos Y"/>
+ <spinner label="Z" name="Pos Z"/>
<text name="label size">
Størrelse (meter)
</text>
- <spinner label="X" name="Scale X" />
- <spinner label="Y" name="Scale Y" />
- <spinner label="Z" name="Scale Z" />
+ <spinner label="X" name="Scale X"/>
+ <spinner label="Y" name="Scale Y"/>
+ <spinner label="Z" name="Scale Z"/>
<text name="label rotation">
Rotation (grader)
</text>
- <spinner label="X" name="Rot X" />
- <spinner label="Y" name="Rot Y" />
- <spinner label="Z" name="Rot Z" />
+ <spinner label="X" name="Rot X"/>
+ <spinner label="Y" name="Rot Y"/>
+ <spinner label="Z" name="Rot Z"/>
<text name="label material">
Materiale
</text>
<combo_box name="material">
- <combo_item name="Stone">
- Sten
- </combo_item>
- <combo_item name="Metal">
- Metal
- </combo_item>
- <combo_item name="Glass">
- Glas
- </combo_item>
- <combo_item name="Wood">
- Træ
- </combo_item>
- <combo_item name="Flesh">
- Kød
- </combo_item>
- <combo_item name="Plastic">
- Plastik
- </combo_item>
- <combo_item name="Rubber">
- Gummi
- </combo_item>
+ <combo_box.item name="Stone" label="Sten"/>
+ <combo_box.item name="Metal" label="Metal"/>
+ <combo_box.item name="Glass" label="Glas"/>
+ <combo_box.item name="Wood" label="Træ"/>
+ <combo_box.item name="Flesh" label="Kød"/>
+ <combo_box.item name="Plastic" label="Plastik"/>
+ <combo_box.item name="Rubber" label="Gummi"/>
</combo_box>
<text name="label basetype">
Byggegeometrisk figur
</text>
<combo_box name="comboBaseType">
- <combo_item name="Box">
- Terning
- </combo_item>
- <combo_item name="Cylinder">
- Cylinder
- </combo_item>
- <combo_item name="Prism">
- Prisme
- </combo_item>
- <combo_item name="Sphere">
- Spfære
- </combo_item>
- <combo_item name="Torus">
- Kuglering
- </combo_item>
- <combo_item name="Tube">
- Rør
- </combo_item>
- <combo_item name="Ring">
- Ring
- </combo_item>
- <combo_item name="Sculpted">
- Sculpted
- </combo_item>
+ <combo_box.item name="Box" label="Terning"/>
+ <combo_box.item name="Cylinder" label="Cylinder"/>
+ <combo_box.item name="Prism" label="Prisme"/>
+ <combo_box.item name="Sphere" label="Spfære"/>
+ <combo_box.item name="Torus" label="Kuglering"/>
+ <combo_box.item name="Tube" label="Rør"/>
+ <combo_box.item name="Ring" label="Ring"/>
+ <combo_box.item name="Sculpted" label="Sculpted"/>
</combo_box>
<text name="text cut">
Snit begynd og slut
</text>
- <spinner label="B" name="cut begin" />
- <spinner label="E" name="cut end" />
+ <spinner label="B" name="cut begin"/>
+ <spinner label="S" name="cut end"/>
<text name="text hollow">
Hul
</text>
@@ -303,81 +280,63 @@
Form på hul
</text>
<combo_box name="hole">
- <combo_item name="Default">
- Standard
- </combo_item>
- <combo_item name="Circle">
- Cirkel
- </combo_item>
- <combo_item name="Square">
- Firkant
- </combo_item>
- <combo_item name="Triangle">
- Trekant
- </combo_item>
+ <combo_box.item name="Default" label="Standard"/>
+ <combo_box.item name="Circle" label="Cirkel"/>
+ <combo_box.item name="Square" label="Firkant"/>
+ <combo_box.item name="Triangle" label="Trekant"/>
</combo_box>
<text name="text twist">
- Vrid - start og slut
+ Vrid begynd og slut
</text>
- <spinner label="B" name="Twist Begin" />
- <spinner label="E" name="Twist End" />
+ <spinner label="B" name="Twist Begin"/>
+ <spinner label="S" name="Twist End"/>
<text name="scale_taper">
Konus
</text>
<text name="scale_hole">
Hulstørrelse
</text>
- <spinner label="X" name="Taper Scale X" />
- <spinner label="Y" name="Taper Scale Y" />
+ <spinner label="X" name="Taper Scale X"/>
+ <spinner label="Y" name="Taper Scale Y"/>
<text name="text topshear">
Topforskydning
</text>
- <spinner label="X" name="Shear X" />
- <spinner label="Y" name="Shear Y" />
+ <spinner label="X" name="Shear X"/>
+ <spinner label="Y" name="Shear Y"/>
<text name="advanced_cut">
- Profilsnit - begynd og slut
+ Profilsnit begynd og slut
</text>
<text name="advanced_dimple">
- Fordybning - begynd og slut
+ Fordybning begynd og slut
+ </text>
+ <text name="advanced_slice">
+ Snit begynd og slut
</text>
- <spinner label="B" name="Path Limit Begin" />
- <spinner label="E" name="Path Limit End" />
+ <spinner label="B" name="Path Limit Begin"/>
+ <spinner label="S" name="Path Limit End"/>
<text name="text taper2">
Konus
</text>
- <spinner label="X" name="Taper X" />
- <spinner label="Y" name="Taper Y" />
+ <spinner label="X" name="Taper X"/>
+ <spinner label="Y" name="Taper Y"/>
<text name="text radius delta">
Radius
</text>
<text name="text revolutions">
Omdrejninger
</text>
- <texture_picker label="Sculpt tekstur" name="sculpt texture control"
- tool_tip="Klik her for at vælge billede" />
- <check_box label="Spejlet" name="sculpt mirror control"
- tool_tip="Spejler sculpted prim omkring X aksen." />
- <check_box label="Vrangen ud" name="sculpt invert control"
- tool_tip="Vender &apos;vrangen&apos; ud på sculpted prim." />
+ <texture_picker label="Sculpt tekstur" name="sculpt texture control" tool_tip="Klik her for at vælge billede"/>
+ <check_box label="Spejlet" name="sculpt mirror control" tool_tip="Spejler sculpted prim omkring X aksen."/>
+ <check_box label="Vrangen ud" name="sculpt invert control" tool_tip="Vender &apos;vrangen&apos; ud på sculpted prim."/>
<text name="label sculpt type">
Sting type
</text>
<combo_box name="sculpt type control">
- <combo_item name="None">
- (ingen)
- </combo_item>
- <combo_item name="Sphere">
- Sfære
- </combo_item>
- <combo_item name="Torus">
- Kuglering
- </combo_item>
- <combo_item name="Plane">
- Plan
- </combo_item>
- <combo_item name="Cylinder">
- Cylinder
- </combo_item>
+ <combo_box.item name="None" label="(ingen)"/>
+ <combo_box.item name="Sphere" label="Sfære"/>
+ <combo_box.item name="Torus" label="Kuglering"/>
+ <combo_box.item name="Plane" label="Plan"/>
+ <combo_box.item name="Cylinder" label="Cylinder"/>
</combo_box>
</panel>
<panel label="Features" name="Features">
@@ -387,130 +346,82 @@
<text name="edit_object">
Redigér objektets egenskaber:
</text>
- <check_box label="Fleksibel/blød" name="Flexible1D Checkbox Ctrl"
- tool_tip="Tillader objektet at ændre form omkring Z-aksen. (Kun på klient-siden)" />
- <spinner label="Blødhed" name="FlexNumSections" />
- <spinner label="Tyngdekraft" name="FlexGravity" />
- <spinner label="Træk" name="FlexFriction" />
- <spinner label="Vind" name="FlexWind" />
- <spinner label="Spændstighed" name="FlexTension" />
- <spinner label="Kraft X" name="FlexForceX" />
- <spinner label="Kraft Y" name="FlexForceY" />
- <spinner label="Kraft Z" name="FlexForceZ" />
- <check_box label="Lys" name="Light Checkbox Ctrl"
- tool_tip="Medfårer at objektet afgiver lys" />
+ <check_box label="Fleksibel/blød" name="Flexible1D Checkbox Ctrl" tool_tip="Tillader objektet at ændre form omkring Z-aksen. (Kun på klient-siden)"/>
+ <spinner label_width="78" width="141" label="Blødhed" name="FlexNumSections"/>
+ <spinner label_width="78" width="141" label="Tyngdekraft" name="FlexGravity"/>
+ <spinner label_width="78" width="141" label="Træk" name="FlexFriction"/>
+ <spinner label_width="78" width="141" label="Vind" name="FlexWind"/>
+ <spinner label_width="78" width="141" label="Spændstighed" name="FlexTension"/>
+ <spinner label_width="78" width="141" label="Kraft X" name="FlexForceX"/>
+ <spinner label_width="78" width="141" label="Kraft Y" name="FlexForceY"/>
+ <spinner label_width="78" width="141" label="Kraft Z" name="FlexForceZ"/>
+ <check_box label="Lys" name="Light Checkbox Ctrl" tool_tip="Medfårer at objektet afgiver lys"/>
<text name="label color">
Farve
</text>
- <color_swatch label="" name="colorswatch" tool_tip="Klik for at åbne farvevælger" />
- <spinner label="Intensitet" name="Light Intensity" />
- <spinner label="Radius" name="Light Radius" />
- <spinner label="Udfasning" name="Light Falloff" />
+ <color_swatch label="" name="colorswatch" tool_tip="Klik for at åbne farvevælger"/>
+ <spinner label="Intensitet" name="Light Intensity"/>
+ <spinner label="Radius" name="Light Radius"/>
+ <spinner label="Udfasning" name="Light Falloff"/>
</panel>
<panel label="Tekstur" name="Texture">
- <texture_picker label="Tekstur" name="texture control" tool_tip="Klik for at vælge billede" />
- <color_swatch label="Farve" name="colorswatch" tool_tip="Klik for at åbne farvevælger" />
- <text name="color trans">
- Gennemsigtighed %
+ <texture_picker label="Tekstur" name="texture control" tool_tip="Klik for at vælge billede"/>
+ <color_swatch label="Farve" name="colorswatch" tool_tip="Klik for at åbne farvevælger"/>
+ <text name="color trans" left="170" width="105">
+ Gennemsigtighed%
</text>
- <text name="glow label">
+ <spinner left="171" name="ColorTrans"/>
+ <text name="glow label" left="170">
Glød
</text>
- <check_box label="Selvlysende" name="checkbox fullbright" />
+ <spinner left="170" name="glow"/>
+ <check_box label="Selvlysende" name="checkbox fullbright" left="170"/>
<text name="tex gen">
Afbildning
</text>
<combo_box name="combobox texgen">
- <combo_item name="Default">
- Standard
- </combo_item>
- <combo_item name="Planar">
- Plan
- </combo_item>
+ <combo_box.item name="Default" label="Standard"/>
+ <combo_box.item name="Planar" label="Plan"/>
</combo_box>
<text name="label shininess">
Blankhed
</text>
<combo_box name="combobox shininess">
- <combo_item name="None">
- Ingen
- </combo_item>
- <combo_item name="Low">
- Lav
- </combo_item>
- <combo_item name="Medium">
- Mellem
- </combo_item>
- <combo_item name="High">
- Høj
- </combo_item>
+ <combo_box.item name="None" label="Ingen"/>
+ <combo_box.item name="Low" label="Lav"/>
+ <combo_box.item name="Medium" label="Mellem"/>
+ <combo_box.item name="High" label="Høj"/>
</combo_box>
<text name="label bumpiness">
Struktur
</text>
<combo_box name="combobox bumpiness">
- <combo_item name="None">
- Ingen
- </combo_item>
- <combo_item name="Brightness">
- Lysintensitet
- </combo_item>
- <combo_item name="Darkness">
- Mørke
- </combo_item>
- <combo_item name="woodgrain">
- træårer
- </combo_item>
- <combo_item name="bark">
- bark
- </combo_item>
- <combo_item name="bricks">
- mursten
- </combo_item>
- <combo_item name="checker">
- tern
- </combo_item>
- <combo_item name="concrete">
- beton
- </combo_item>
- <combo_item name="crustytile">
- rustik flise
- </combo_item>
- <combo_item name="cutstone">
- Skåret sten
- </combo_item>
- <combo_item name="discs">
- plader
- </combo_item>
- <combo_item name="gravel">
- grus
- </combo_item>
- <combo_item name="petridish">
- petriskål
- </combo_item>
- <combo_item name="siding">
- udvendig beklædning
- </combo_item>
- <combo_item name="stonetile">
- stenflise
- </combo_item>
- <combo_item name="stucco">
- puds
- </combo_item>
- <combo_item name="suction">
- rør
- </combo_item>
- <combo_item name="weave">
- væv
- </combo_item>
+ <combo_box.item name="None" label="Ingen"/>
+ <combo_box.item name="Brightness" label="Lysintensitet"/>
+ <combo_box.item name="Darkness" label="Mørke"/>
+ <combo_box.item name="woodgrain" label="træårer"/>
+ <combo_box.item name="bark" label="bark"/>
+ <combo_box.item name="bricks" label="mursten"/>
+ <combo_box.item name="checker" label="tern"/>
+ <combo_box.item name="concrete" label="beton"/>
+ <combo_box.item name="crustytile" label="rustik flise"/>
+ <combo_box.item name="cutstone" label="Skåret sten"/>
+ <combo_box.item name="discs" label="plader"/>
+ <combo_box.item name="gravel" label="grus"/>
+ <combo_box.item name="petridish" label="petriskål"/>
+ <combo_box.item name="siding" label="udvendig beklædning"/>
+ <combo_box.item name="stonetile" label="stenflise"/>
+ <combo_box.item name="stucco" label="puds"/>
+ <combo_box.item name="suction" label="rør"/>
+ <combo_box.item name="weave" label="væv"/>
</combo_box>
<text name="tex scale">
Gentagelser pr. overflade
</text>
- <spinner label="Vandret (U)" name="TexScaleU" />
- <check_box label="Vend" name="checkbox flip s" />
- <spinner label="Lodret (V)" name="TexScaleV" />
- <check_box label="Vend" name="checkbox flip t" />
+ <spinner label="Vandret (U)" name="TexScaleU"/>
+ <check_box label="Vend" name="checkbox flip s"/>
+ <spinner label="Lodret (V)" name="TexScaleV"/>
+ <check_box label="Vend" name="checkbox flip t"/>
<text name="tex rotate">
Rotation (grader)
</text>
@@ -523,34 +434,86 @@
<text name="rpt">
Gentagelser pr. meter
</text>
- <button label="Gem" label_selected="Gem" name="button apply" />
+ <spinner left="125" name="TexRot" width="55" />
+ <spinner left="125" name="rptctrl" width="55" />
+ <button label="Gem" label_selected="Gem" name="button apply" left_delta="62"/>
<text name="tex offset">
Offset
</text>
- <spinner label="Vandret (U)" name="TexOffsetU" />
- <spinner label="Lodret (V)" name="TexOffsetV" />
+ <spinner label="Vandret (U)" name="TexOffsetU"/>
+ <spinner label="Lodret (V)" name="TexOffsetV"/>
<text name="textbox autofix">
Rette medie tekstur ind
(skal indlæses først)
</text>
- <button label="Ret ind" label_selected="Ret ind" name="button align" />
+ <button label="Ret ind" label_selected="Ret ind" name="button align" left="160"/>
</panel>
<panel label="Indhold" name="Contents">
- <button label="Nyt script..." label_selected="Nyt script..." name="button new script" />
+ <button label="Nyt script" label_selected="Nyt script" name="button new script"/>
+ <button label="Rettigheder" name="button permissions"/>
</panel>
</tab_container>
<panel name="land info panel">
+ <text name="label_parcel_info">
+ Parcel information
+ </text>
<text name="label_area_price">
Pris: L$[PRICE] for [AREA] m².
</text>
<text name="label_area">
Område: [AREA] m².
</text>
- <button label="Køb land..." label_selected="Køb land..." name="button buy land" />
- <button label="Flyt fra land..." label_selected="Flyt fra land..."
- name="button abandon land" />
- <button label="Opdel..." label_selected="Opdel..." name="button subdivide land" />
- <button label="Saml..." label_selected="Saml..." name="button join land" />
- <button label="Om land..." label_selected="Om land..." name="button about land" />
+ <button label="Om land..." label_selected="Om land..." name="button about land"/>
+ <check_box label="Vis ejere" name="checkbox show owners" tool_tip="Farver grunde afhængigt af ejerskab: &#10;&#10;Grøn = Dit land &#10;Turkis = Din gruppes land &#10;Rød = Ejet af andre &#10;Gul = Til salg &#10;Lilla = På auktion &#10;Grå = Offentligt ejet"/>
+ <button label="?" label_selected="?" name="button show owners help"/>
+ <text name="label_parcel_modify">
+ Redigere grund
+ </text>
+ <button label="Opdel" label_selected="Opdel" name="button subdivide land"/>
+ <button label="Saml" label_selected="Saml" name="button join land"/>
+ <text name="label_parcel_trans">
+ Transaktioner for land
+ </text>
+ <button label="Køb land" label_selected="Køb land" name="button buy land"/>
+ <button label="Flyt fra land" label_selected="Flyt fra land" name="button abandon land"/>
</panel>
+ <floater.string name="status_rotate">
+ Træk i de farvede bånd for at rotere objekt
+ </floater.string>
+ <floater.string name="status_scale">
+ Klik og træk for at strække valgte side
+ </floater.string>
+ <floater.string name="status_move">
+ Træk for at flytte, hold shift nede for at kopiere
+ </floater.string>
+ <floater.string name="status_modifyland">
+ Klik og hold for at redigere land
+ </floater.string>
+ <floater.string name="status_camera">
+ Klik og træk for at ændre synsvinkel
+ </floater.string>
+ <floater.string name="status_grab">
+ Træk for at flytte objekter, Ctrl for at løfte, Ctrl-Shift for at rotere
+ </floater.string>
+ <floater.string name="status_place">
+ Klik et sted i verden for at bygge
+ </floater.string>
+ <floater.string name="status_selectland">
+ Klik og træk for at vælge land
+ </floater.string>
+ <floater.string name="grid_screen_text">
+ Skærm
+ </floater.string>
+ <floater.string name="grid_local_text">
+ Lokalt
+ </floater.string>
+ <floater.string name="grid_world_text">
+ Verden
+ </floater.string>
+ <floater.string name="grid_reference_text">
+ Reference
+ </floater.string>
+ <floater.string name="grid_attachment_text">
+ Vedhæng
+ </floater.string>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_top_objects.xml b/indra/newview/skins/default/xui/da/floater_top_objects.xml
index dc4605cc12..0cfbe77def 100644
--- a/indra/newview/skins/default/xui/da/floater_top_objects.xml
+++ b/indra/newview/skins/default/xui/da/floater_top_objects.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="top_objects" title="Indlæser...">
+<floater name="top_objects" title="INDLÆSER...">
<text name="title_text">
Henter...
</text>
diff --git a/indra/newview/skins/default/xui/da/floater_tos.xml b/indra/newview/skins/default/xui/da/floater_tos.xml
index 8d341f6a12..9a348ca7bf 100644
--- a/indra/newview/skins/default/xui/da/floater_tos.xml
+++ b/indra/newview/skins/default/xui/da/floater_tos.xml
@@ -4,7 +4,8 @@
<button label="Annullér" label_selected="Annullér" name="Cancel" />
<check_box label="Jeg accepterer vilkårene for brug af tjenesten" name="agree_chk" />
<text name="tos_heading">
- Læs venligst de almindelige bestemmelser og vilkår igennem, for at fortsætte til Second Life skal du acceptere vilkårene.
+ Læs venligst de almindelige bestemmelser og vilkår igennem, for at fortsætte til [SECOND_LIFE]
+skal du acceptere vilkårene.
</text>
<text_editor name="tos_text">
TOS_TEXT
diff --git a/indra/newview/skins/default/xui/da/floater_water.xml b/indra/newview/skins/default/xui/da/floater_water.xml
index aa04fd805a..63880b4a69 100644
--- a/indra/newview/skins/default/xui/da/floater_water.xml
+++ b/indra/newview/skins/default/xui/da/floater_water.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Water Floater" title="Avanceret opsætning af vand">
- <text type="string" length="1" name="KeyFramePresetsText">
+<floater name="Water Floater" title="AVANCERET OPSÆTNING AF VAND">
+ <text name="KeyFramePresetsText">
Vand opsætninger:
</text>
<button label="Ny" label_selected="Ny" name="WaterNewPreset" />
@@ -8,89 +8,89 @@
<button label="Slet" label_selected="Slet" name="WaterDeletePreset" />
<tab_container name="Water Tabs">
<panel label="Opsætning" name="Settings">
- <text type="string" length="1" name="BHText">
+ <text name="BHText">
Vandtåge farve
</text>
<button label="?" name="WaterFogColorHelp" />
<color_swatch label="" name="WaterFogColor" tool_tip="Click to open Color Picker" />
- <text type="string" length="1" name="WaterFogDensText">
+ <text name="WaterFogDensText">
Tåge tæthedskarakteristik
</text>
<button label="?" name="WaterFogDensityHelp" />
<slider label="" name="WaterFogDensity" />
- <text type="string" length="1" name="WaterUnderWaterFogModText">
+ <text name="WaterUnderWaterFogModText">
Tilretning undervandståge
</text>
<button label="?" name="WaterUnderWaterFogModHelp" />
<slider label="" name="WaterUnderWaterFogMod" />
- <text type="string" length="1" name="BDensText">
+ <text name="BDensText">
Lille bølge reflektionsskala
</text>
<button label="?" name="WaterNormalScaleHelp" />
- <text type="string" length="1" name="BHText2">
+ <text name="BHText2">
1
</text>
- <text type="string" length="1" name="BHText3">
+ <text name="BHText3">
2
</text>
- <text type="string" length="1" name="BHText4">
+ <text name="BHText4">
3
</text>
<slider label="" name="WaterNormalScaleX" />
<slider label="" name="WaterNormalScaleY" />
<slider label="" name="WaterNormalScaleZ" />
- <text type="string" length="1" name="HDText">
+ <text name="HDText">
Spredningsskala
</text>
<button label="?" name="WaterFresnelScaleHelp" />
<slider label="" name="WaterFresnelScale" />
- <text type="string" length="1" name="FresnelOffsetText">
+ <text name="FresnelOffsetText">
Spredning offset
</text>
<button label="?" name="WaterFresnelOffsetHelp" />
<slider label="" name="WaterFresnelOffset" />
- <text type="string" length="1" name="DensMultText">
+ <text name="DensMultText">
Lysbrydning fra oven
</text>
<button label="?" name="WaterScaleAboveHelp" />
<slider label="" name="WaterScaleAbove" />
- <text type="string" length="1" name="WaterScaleBelowText">
+ <text name="WaterScaleBelowText">
Lysbrydning fra neden
</text>
<button label="?" name="WaterScaleBelowHelp" />
<slider label="" name="WaterScaleBelow" />
- <text type="string" length="1" name="MaxAltText">
+ <text name="MaxAltText">
Udviskning
</text>
<button label="?" name="WaterBlurMultiplierHelp" />
<slider label="" name="WaterBlurMult" />
</panel>
<panel label="Billede" name="Waves">
- <text type="string" length="1" name="BHText">
+ <text name="BHText">
Retning for store bølger
</text>
<button label="?" name="WaterWave1Help" />
- <text type="string" length="1" name="WaterWave1DirXText">
+ <text name="WaterWave1DirXText">
X
</text>
- <text type="string" length="1" name="WaterWave1DirYText">
+ <text name="WaterWave1DirYText">
Y
</text>
<slider label="" name="WaterWave1DirX" />
<slider label="" name="WaterWave1DirY" />
- <text type="string" length="1" name="BHText2">
+ <text name="BHText2">
Retning for små bølger
</text>
<button label="?" name="WaterWave2Help" />
- <text type="string" length="1" name="WaterWave2DirXText">
+ <text name="WaterWave2DirXText">
X
</text>
- <text type="string" length="1" name="WaterWave2DirYText">
+ <text name="WaterWave2DirYText">
Y
</text>
<slider label="" name="WaterWave2DirX" />
<slider label="" name="WaterWave2DirY" />
- <text type="string" length="1" name="BHText3">
+ <text name="BHText3">
Tekstur map
</text>
<button label="?" name="WaterNormalMapHelp" />
diff --git a/indra/newview/skins/default/xui/da/floater_wearable_save_as.xml b/indra/newview/skins/default/xui/da/floater_wearable_save_as.xml
index 145768a7e3..a70db6a6f1 100644
--- a/indra/newview/skins/default/xui/da/floater_wearable_save_as.xml
+++ b/indra/newview/skins/default/xui/da/floater_wearable_save_as.xml
@@ -2,7 +2,7 @@
<floater name="modal container" title="">
<button label="Gem" label_selected="Gem" name="Save" />
<button label="Annullér" label_selected="Annullér" name="Cancel" />
- <text type="string" length="1" name="Save item as:">
+ <text name="Save item as:">
Gem ting som::
</text>
<line_editor name="name ed">
diff --git a/indra/newview/skins/default/xui/da/floater_windlight_options.xml b/indra/newview/skins/default/xui/da/floater_windlight_options.xml
index ecb8b77c52..4786609b53 100644
--- a/indra/newview/skins/default/xui/da/floater_windlight_options.xml
+++ b/indra/newview/skins/default/xui/da/floater_windlight_options.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="WindLight floater" title="Avanceret opsætning for himmel">
- <text type="string" length="1" name="KeyFramePresetsText">
+<floater name="WindLight floater" title="AVANCERET OPSÆTNING FOR HIMMEL">
+ <text name="KeyFramePresetsText">
Faste indstillinger:
</text>
<button label="Ny" label_selected="Ny" name="WLNewPreset" />
@@ -9,210 +9,210 @@
<button label="Dags cyklus" label_selected="Dags cyklus" name="WLDayCycleMenuButton" />
<tab_container name="WindLight Tabs">
<panel label="Atmosfære" name="Atmosphere">
- <text type="string" length="1" name="BHText">
+ <text name="BHText">
Blå - horisont
</text>
<button label="?" name="WLBlueHorizonHelp" />
- <text type="string" length="1" name="BHText2">
+ <text name="BHText2">
R
</text>
- <text type="string" length="1" name="BHText3">
+ <text name="BHText3">
G
</text>
- <text type="string" length="1" name="BHText4">
+ <text name="BHText4">
B
</text>
- <text type="string" length="1" name="BHText5">
+ <text name="BHText5">
I
</text>
<slider label="" name="WLBlueHorizonR" />
<slider label="" name="WLBlueHorizonG" />
<slider label="" name="WLBlueHorizonB" />
<slider label="" name="WLBlueHorizonI" />
- <text type="string" length="1" name="BDensText">
+ <text name="BDensText">
Dis - horisont
</text>
<button label="?" name="WLHazeHorizonHelp" />
<slider label="" name="WLHazeHorizon" />
- <text type="string" length="1" name="BDensText2">
+ <text name="BDensText2">
Blå - tæthed
</text>
<button label="?" name="WLBlueDensityHelp" />
- <text type="string" length="1" name="BHText6">
+ <text name="BHText6">
R
</text>
- <text type="string" length="1" name="BHText7">
+ <text name="BHText7">
G
</text>
- <text type="string" length="1" name="BHText8">
+ <text name="BHText8">
B
</text>
- <text type="string" length="1" name="BHText9">
+ <text name="BHText9">
I
</text>
<slider label="" name="WLBlueDensityR" />
<slider label="" name="WLBlueDensityG" />
<slider label="" name="WLBlueDensityB" />
<slider label="" name="WLBlueDensityI" />
- <text type="string" length="1" name="HDText">
+ <text name="HDText">
Dis - intensitet
</text>
<button label="?" name="WLHazeDensityHelp" />
<slider label="" name="WLHazeDensity" />
- <text type="string" length="1" name="DensMultText">
+ <text name="DensMultText">
Densitet faktor
</text>
<button label="?" name="WLDensityMultHelp" />
<slider label="" name="WLDensityMult" />
- <text type="string" length="1" name="WLDistanceMultText">
+ <text name="WLDistanceMultText">
Distance faktor
</text>
<button label="?" name="WLDistanceMultHelp" />
<slider label="" name="WLDistanceMult" />
- <text type="string" length="1" name="MaxAltText">
+ <text name="MaxAltText">
Maximum højde
</text>
<button label="?" name="WLMaxAltitudeHelp" />
<slider label="" name="WLMaxAltitude" />
</panel>
<panel label="Lys" name="Lighting">
- <text type="string" length="1" name="SLCText">
+ <text name="SLCText">
Sol/MÃ¥ne farve
</text>
<button label="?" name="WLSunlightColorHelp" />
- <text type="string" length="1" name="BHText">
+ <text name="BHText">
R
</text>
- <text type="string" length="1" name="BHText2">
+ <text name="BHText2">
G
</text>
- <text type="string" length="1" name="BHText3">
+ <text name="BHText3">
B
</text>
- <text type="string" length="1" name="BHText4">
+ <text name="BHText4">
I
</text>
<slider label="" name="WLSunlightR" />
<slider label="" name="WLSunlightG" />
<slider label="" name="WLSunlightB" />
<slider label="" name="WLSunlightI" />
- <text type="string" length="1" name="TODText">
+ <text name="TODText">
Sol/MÃ¥ne position
</text>
<button label="?" name="WLTimeOfDayHelp" />
<slider label="" name="WLSunAngle" />
- <text type="string" length="1" name="WLAmbientText">
+ <text name="WLAmbientText">
Omgivende
</text>
<button label="?" name="WLAmbientHelp" />
- <text type="string" length="1" name="BHText5">
+ <text name="BHText5">
R
</text>
- <text type="string" length="1" name="BHText6">
+ <text name="BHText6">
G
</text>
- <text type="string" length="1" name="BHText7">
+ <text name="BHText7">
B
</text>
- <text type="string" length="1" name="BHText8">
+ <text name="BHText8">
I
</text>
<slider label="" name="WLAmbientR" />
<slider label="" name="WLAmbientG" />
<slider label="" name="WLAmbientB" />
<slider label="" name="WLAmbientI" />
- <text type="string" length="1" name="WLEastAngleText">
+ <text name="WLEastAngleText">
Øst vinkel
</text>
<button label="?" name="WLEastAngleHelp" />
<slider label="" name="WLEastAngle" />
- <text type="string" length="1" name="SunGlowText">
+ <text name="SunGlowText">
Sol glød
</text>
<button label="?" name="WLSunGlowHelp" />
<slider label="Fokus " name="WLGlowB" />
<slider label="Størr. " name="WLGlowR" />
- <text type="string" length="1" name="SceneGammaText">
+ <text name="SceneGammaText">
Lysintensitet (gamma)
</text>
<button label="?" name="WLSceneGammaHelp" />
<slider label="" name="WLGamma" />
- <text type="string" length="1" name="WLStarText">
+ <text name="WLStarText">
Stjerne intensitet
</text>
<button label="?" name="WLStarBrightnessHelp" />
<slider label="" name="WLStarAlpha" />
</panel>
<panel label="Skyer" name="Clouds">
- <text type="string" length="1" name="WLCloudColorText">
+ <text name="WLCloudColorText">
Farve på skyer
</text>
<button label="?" name="WLCloudColorHelp" />
- <text type="string" length="1" name="BHText">
+ <text name="BHText">
R
</text>
- <text type="string" length="1" name="BHText2">
+ <text name="BHText2">
G
</text>
- <text type="string" length="1" name="BHText3">
+ <text name="BHText3">
B
</text>
- <text type="string" length="1" name="BHText4">
+ <text name="BHText4">
I
</text>
<slider label="" name="WLCloudColorR" />
<slider label="" name="WLCloudColorG" />
<slider label="" name="WLCloudColorB" />
<slider label="" name="WLCloudColorI" />
- <text type="string" length="1" name="WLCloudColorText2">
+ <text name="WLCloudColorText2">
Skyer XY/Tæthed
</text>
<button label="?" name="WLCloudDensityHelp" />
- <text type="string" length="1" name="BHText5">
+ <text name="BHText5">
X
</text>
- <text type="string" length="1" name="BHText6">
+ <text name="BHText6">
Y
</text>
- <text type="string" length="1" name="BHText7">
+ <text name="BHText7">
T
</text>
<slider label="" name="WLCloudX" />
<slider label="" name="WLCloudY" />
<slider label="" name="WLCloudDensity" />
- <text type="string" length="1" name="WLCloudCoverageText">
+ <text name="WLCloudCoverageText">
Skydække
</text>
<button label="?" name="WLCloudCoverageHelp" />
<slider label="" name="WLCloudCoverage" />
- <text type="string" length="1" name="WLCloudScaleText">
+ <text name="WLCloudScaleText">
Skystørrelse
</text>
<button label="?" name="WLCloudScaleHelp" />
<slider label="" name="WLCloudScale" />
- <text type="string" length="1" name="WLCloudDetailText">
+ <text name="WLCloudDetailText">
Sky detaljer(XY/tæthed)
</text>
<button label="?" name="WLCloudDetailHelp" />
- <text type="string" length="1" name="BHText8">
+ <text name="BHText8">
X
</text>
- <text type="string" length="1" name="BHText9">
+ <text name="BHText9">
Y
</text>
- <text type="string" length="1" name="BHText10">
+ <text name="BHText10">
T
</text>
<slider label="" name="WLCloudDetailX" />
<slider label="" name="WLCloudDetailY" />
<slider label="" name="WLCloudDetailDensity" />
- <text type="string" length="1" name="WLCloudScrollXText">
+ <text name="WLCloudScrollXText">
Sky drift X
</text>
<button label="?" name="WLCloudScrollXHelp" />
<check_box label="LÃ¥s" name="WLCloudLockX" />
<slider label="" name="WLCloudScrollX" />
- <text type="string" length="1" name="WLCloudScrollYText">
+ <text name="WLCloudScrollYText">
Sky drift Y
</text>
<button label="?" name="WLCloudScrollYHelp" />
diff --git a/indra/newview/skins/default/xui/da/floater_world_map.xml b/indra/newview/skins/default/xui/da/floater_world_map.xml
index 20dfe55406..62930716ce 100644
--- a/indra/newview/skins/default/xui/da/floater_world_map.xml
+++ b/indra/newview/skins/default/xui/da/floater_world_map.xml
@@ -1,81 +1,57 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="worldmap" title="Verdenskort">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="worldmap" title="VERDENSKORT">
<tab_container name="maptab">
- <panel label="Objekter" name="objects_mapview" />
- <panel label="Terræn" name="terrain_mapview" />
+ <panel label="Objekter" name="objects_mapview"/>
+ <panel label="Terræn" name="terrain_mapview"/>
</tab_container>
- <text name="land_for_sale_label">
- Land til salg
- </text>
- <text name="auction_label">
- Auktion
- </text>
<text name="you_label">
Dig
</text>
<text name="home_label">
Hjem
</text>
- <button label="Tag hjem" label_selected="Tag hjem" name="Go Home"
- tool_tip="Teleporter til dit hjem" />
- <text name="person_label">
- Person
- </text>
- <check_box label=" " name="people_chk" />
- <text name="infohub_label">
- Infohub
- </text>
- <check_box label="" name="infohub_chk" />
- <text name="telehub_label">
- Telehub
+ <text name="auction_label">
+ Auktion
</text>
- <check_box label="" name="telehubchk" />
- <text name="land_for_sale_label2">
+ <text name="land_for_sale_label">
Land til salg
</text>
- <check_box label="" name="land_for_sale_chk" />
+ <button label="Tag hjem" label_selected="Tag hjem" name="Go Home" tool_tip="Teleporter til dit hjem"/>
+ <check_box label="Beboer" name="people_chk"/>
+ <check_box label="Infohub" name="infohub_chk"/>
+ <check_box label="Telehub" name="telehubchk"/>
+ <check_box label="Land til salg" name="land_for_sale_chk"/>
<text name="events_label">
- Events
+ Events:
</text>
- <check_box label="" name="event_chk" />
- <text name="events_mature_label" />
- <check_box label="" name="event_mature_chk" />
- <combo_box label="Venner online" name="friend combo"
- tool_tip="Ven der skal vises på kortet">
- <combo_item name="none_selected">
- Venner online
- </combo_item>
+ <check_box label="PG" name="event_chk"/>
+ <check_box label="Mature" name="event_mature_chk"/>
+ <check_box label="Adult" name="event_adult_chk"/>
+ <combo_box label="Venner online" name="friend combo" tool_tip="Ven der skal vises på kortet">
+ <combo_box.item name="item1" label="Venner online" />
</combo_box>
- <combo_box label="Landemærker" name="landmark combo"
- tool_tip="Landemærke der skal vises på kortet">
- <combo_item name="none_selected">
- Landemærker
- </combo_item>
+ <combo_box label="Landemærker" name="landmark combo" tool_tip="Landemærke der skal vises på kortet">
+ <combo_box.item name="item1" label="Landemærker" />
</combo_box>
- <line_editor label="Søg på region navn" name="location"
- tool_tip="Skriv navnet på en region" />
- <button label="Søg" name="DoSearch" tool_tip="Søg efter en region" />
+ <line_editor label="Søg på region navn" name="location" tool_tip="Skriv navnet på en region"/>
+ <button label="Søg" name="DoSearch" tool_tip="Søg efter en region"/>
<text name="search_label">
Søgeresultater:
</text>
<scroll_list name="search_results">
- <column label="" name="icon" />
- <column label="" name="sim_name" />
+ <column label="" name="icon"/>
+ <column label="" name="sim_name"/>
</scroll_list>
<text name="location_label">
Lokation:
</text>
- <spinner name="spin x" tool_tip="X koordinat for lokation der skal vises på kortet" />
- <spinner name="spin y" tool_tip="Y koordinat for lokation der skal vises på kortet" />
- <spinner name="spin z" tool_tip="Z koordinat for lokation der skal vises på kortet" />
- <button label="Teleport" label_selected="Teleport" name="Teleport"
- tool_tip="Teleportér til den valgte lokation" />
- <button label="Vis destination" label_selected="Vis destination"
- name="Show Destination" tool_tip="Centrér kortet på valgte lokation" />
- <button label="Slet" label_selected="Slet" name="Clear" tool_tip="Stop søg" />
- <button label="Vis min position" label_selected="Vis min position"
- name="Show My Location" tool_tip="Centrer kortet på din avatars lokation" />
- <button label="Kopiér SLURL til udklipsholder" name="copy_slurl"
- tool_tip="Kopierer den nuværende lokation som et SLURL, så det kan bruges på nettet." />
- <slider label="Zoom" name="zoom slider" />
+ <spinner name="spin x" tool_tip="X koordinat for lokation der skal vises på kortet"/>
+ <spinner name="spin y" tool_tip="Y koordinat for lokation der skal vises på kortet"/>
+ <spinner name="spin z" tool_tip="Z koordinat for lokation der skal vises på kortet"/>
+ <button label="Teleport" label_selected="Teleport" name="Teleport" tool_tip="Teleportér til den valgte lokation"/>
+ <button label="Vis destination" label_selected="Vis destination" name="Show Destination" tool_tip="Centrér kortet på valgte lokation"/>
+ <button label="Slet" label_selected="Slet" name="Clear" tool_tip="Stop søg"/>
+ <button label="Vis min position" label_selected="Vis min position" name="Show My Location" tool_tip="Centrer kortet på din avatars lokation"/>
+ <button label="Kopiér SLurl til udklipsholder" name="copy_slurl" tool_tip="Kopierer den nuværende lokation som et SLurl, så det kan bruges på nettet."/>
+ <slider label="Zoom" name="zoom slider"/>
</floater>
diff --git a/indra/newview/skins/default/xui/da/language_settings.xml b/indra/newview/skins/default/xui/da/language_settings.xml
new file mode 100644
index 0000000000..71418d446a
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/language_settings.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- This file contains strings that used to be hardcoded in the source.-->
+<strings>
+
+ <!-- Locale Information -->
+ <string name="MicrosoftLocale">english</string>
+ <string name="DarwinLocale">C</string>
+ <string name="LinuxLocale">C</string>
+
+ <!--
+ datetimeToCodes["wkday"] = "%a"; // Thu
+ datetimeToCodes["weekday"] = "%A"; // Thursday
+ datetimeToCodes["year4"] = "%Y"; // 2009
+ datetimeToCodes["year"] = "%Y"; // 2009
+ datetimeToCodes["year2"] = "%y"; // 09
+ datetimeToCodes["mth"] = "%b"; // Aug
+ datetimeToCodes["month"] = "%B"; // August
+ datetimeToCodes["mthnum"] = "%m"; // 08
+ datetimeToCodes["day"] = "%d"; // 31
+ datetimeToCodes["hour24"] = "%H"; // 14
+ datetimeToCodes["hour"] = "%H"; // 14
+ datetimeToCodes["hour12"] = "%I"; // 02
+ datetimeToCodes["min"] = "%M"; // 59
+ datetimeToCodes["ampm"] = "%p"; // AM
+ datetimeToCodes["second"] = "%S"; // 59
+ datetimeToCodes["timezone"] = "%Z"; // PST
+ -->
+
+ <string name="TimeHour">hour,datetime,slt</string>
+ <string name="TimeMin">min,datetime,slt</string>
+ <string name="TimeYear">year,datetime,slt</string>
+ <string name="TimeDay">day,datetime,slt</string>
+ <string name="TimeMonth">mthnum,datetime,slt</string>
+ <string name="TimeWeek">wkday,datetime,slt</string>
+ <string name="TimeAMPM">ampm,datetime,slt</string>
+ <string name="TimeHour12">hour12,datetime,slt</string>
+
+ <string name="LTimeMthNum">mthnum,datetime,local</string>
+ <string name="LTimeWeek">wkday,datetime,local</string>
+ <string name="LTimeMonth">mth,datetime,local</string>
+ <string name="LTimeDay">day,datetime,local</string>
+ <string name="LTimeSec">second,datetime,local</string>
+ <string name="LTimeHour">hour,datetime,local</string>
+ <string name="LTimeMin">min,datetime,local</string>
+ <string name="LTimeYear">year,datetime,local</string>
+
+ <string name="UTCTimeWeek">weekday,datetime,utc</string>
+ <string name="UTCTimeDay">day,datetime,utc</string>
+ <string name="UTCTimeMth">mth,datetime,utc</string>
+ <string name="UTCTimeYr">year,datetime,utc</string>
+ <string name="UTCTimeHr">hour,datetime,utc</string>
+ <string name="UTCTimeMin">min,datetime,utc</string>
+ <string name="UTCTimeSec">second,datetime,utc</string>
+ <string name="UTCTimeTimezone">timezone,datetime,utc</string>
+</strings>
diff --git a/indra/newview/skins/default/xui/da/menu_inventory.xml b/indra/newview/skins/default/xui/da/menu_inventory.xml
index 2c47703ef2..376af507d0 100644
--- a/indra/newview/skins/default/xui/da/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/da/menu_inventory.xml
@@ -1,65 +1,82 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<menu name="Popup">
- <menu_item_call label="Køb" name="Task Buy" />
- <menu_item_call label="Ã¥ben" name="Task Open" />
- <menu_item_call label="Afspil" name="Task Play" />
- <menu_item_call label="Egenskaber" name="Task Properties" />
- <menu_item_call label="Omdøb" name="Task Rename" />
- <menu_item_call label="Slet" name="Task Remove" />
- <menu_item_call label="Tøm papirkurv" name="Empty Trash" />
- <menu_item_call label="Tøm &apos;Lost and found&apos;" name="Empty Lost And Found" />
- <menu_item_call label="Ny mappe" name="New Folder" />
- <menu_item_call label="Nyt script" name="New Script" />
- <menu_item_call label="Ny note" name="New Note" />
- <menu_item_call label="Ny bevægelse" name="New Gesture" />
- <menu name="New Clothes">
- <menu_item_call label="Ny trøje" name="New Shirt" />
- <menu_item_call label="Nye bukser" name="New Pants" />
- <menu_item_call label="Nye sko" name="New Shoes" />
- <menu_item_call label="Nye strømper" name="New Socks" />
- <menu_item_call label="Ny jakke" name="New Jacket" />
- <menu_item_call label="Ny nederdel" name="New Skirt" />
- <menu_item_call label="Nye handsker" name="New Gloves" />
- <menu_item_call label="Ny undertrøje" name="New Undershirt" />
- <menu_item_call label="Nye underbukser" name="New Underpants" />
+ <menu_item_call label="Køb" name="Task Buy"/>
+ <menu_item_call label="Ã¥ben" name="Task Open"/>
+ <menu_item_call label="Afspil" name="Task Play"/>
+ <menu_item_call label="Egenskaber" name="Task Properties"/>
+ <menu_item_call label="Omdøb" name="Task Rename"/>
+ <menu_item_call label="Slet" name="Task Remove"/>
+ <menu_item_call label="Tøm papirkurv" name="Empty Trash"/>
+ <menu_item_call label="Tøm &apos;Lost and found&apos;" name="Empty Lost And Found"/>
+ <menu_item_call label="Ny mappe" name="New Folder"/>
+ <menu_item_call label="Nyt script" name="New Script"/>
+ <menu_item_call label="Ny note" name="New Note"/>
+ <menu_item_call label="Ny bevægelse" name="New Gesture"/>
+ <menu label="Nyt tøj" name="New Clothes">
+ <menu_item_call label="Ny trøje" name="New Shirt"/>
+ <menu_item_call label="Nye bukser" name="New Pants"/>
+ <menu_item_call label="Nye sko" name="New Shoes"/>
+ <menu_item_call label="Nye strømper" name="New Socks"/>
+ <menu_item_call label="Ny jakke" name="New Jacket"/>
+ <menu_item_call label="Ny nederdel" name="New Skirt"/>
+ <menu_item_call label="Nye handsker" name="New Gloves"/>
+ <menu_item_call label="Ny undertrøje" name="New Undershirt"/>
+ <menu_item_call label="Nye underbukser" name="New Underpants"/>
+ <menu_item_call label="Nyt alpha lag" name="New Alpha Mask"/>
+ <menu_item_call label="Ny tatovering" name="New Tattoo"/>
</menu>
- <menu name="New Body Parts">
- <menu_item_call label="Ny figur" name="New Shape" />
- <menu_item_call label="Nyt hud" name="New Skin" />
- <menu_item_call label="Nyt hår" name="New Hair" />
- <menu_item_call label="Nye øjne" name="New Eyes" />
+ <menu label="Nye kropsdele" name="New Body Parts">
+ <menu_item_call label="Ny figur" name="New Shape"/>
+ <menu_item_call label="Nyt hud" name="New Skin"/>
+ <menu_item_call label="Nyt hår" name="New Hair"/>
+ <menu_item_call label="Nye øjne" name="New Eyes"/>
</menu>
- <menu_item_call label="Teleport" name="Landmark Open" />
- <menu_item_call label="Ã¥ben" name="Animation Open" />
- <menu_item_call label="Ã¥ben" name="Sound Open" />
- <menu_item_call label="Slet ting" name="Purge Item" />
- <menu_item_call label="Genskab ting" name="Restore Item" />
- <menu_item_call label="Ã¥ben" name="Open" />
- <menu_item_call label="Egenskaber" name="Properties" />
- <menu_item_call label="Omdøb" name="Rename" />
- <menu_item_call label="Kopiér asset UUID" name="Copy Asset UUID" />
- <menu_item_call label="Kopiér" name="Copy" />
- <menu_item_call label="Indsæt" name="Paste" />
- <menu_item_call label="Slet" name="Delete" />
- <menu_item_call label="Tag ting af" name="Take Off Items" />
- <menu_item_call label="Tilføj til påklædning" name="Add To Outfit" />
- <menu_item_call label="Erstat påklædning" name="Replace Outfit" />
- <menu_item_call label="start konference chat" name="Conference Chat Folder" />
- <menu_item_call label="Afspil" name="Sound Play" />
- <menu_item_call label="Om landemærke" name="Teleport To Landmark" />
- <menu_item_call label="Afspil offentligt" name="Animation Play" />
- <menu_item_call label="Afspil lokalt" name="Animation Audition" />
- <menu_item_call label="Send privat besked (IM)" name="Send Instant Message" />
- <menu_item_call label="Tilbyd teleport..." name="Offer Teleport..." />
- <menu_item_call label="start konference Chat" name="Conference Chat" />
- <menu_item_call label="Aktivér" name="Activate" />
- <menu_item_call label="Deaktivér" name="Deactivate" />
- <menu_item_call label="Tag af dig selv" name="Detach From Yourself" />
- <menu_item_call label="Tag på" name="Object Wear" />
- <menu label="Vedhæft" name="Attach To" />
- <menu label="Vedhæft til HUD" name="Attach To HUD" />
- <menu_item_call label="Redigér" name="Wearable Edit" />
- <menu_item_call label="Tag på" name="Wearable Wear" />
- <menu_item_call label="Tag af" name="Take Off" />
- <menu_item_call label="--ingen valg--" name="--no options--" />
+ <menu label="Ændre type" name="Change Type">
+ <menu_item_call label="Standard" name="Default"/>
+ <menu_item_call label="Handsker" name="Gloves"/>
+ <menu_item_call label="Jakke" name="Jacket"/>
+ <menu_item_call label="Bukser" name="Pants"/>
+ <menu_item_call label="Kropsbygning" name="Shape"/>
+ <menu_item_call label="Sko" name="Shoes"/>
+ <menu_item_call label="Trøje" name="Shirt"/>
+ <menu_item_call label="Nederdel" name="Skirt"/>
+ <menu_item_call label="Underbukser" name="Underpants"/>
+ <menu_item_call label="Undertrøje" name="Undershirt"/>
+ </menu>
+ <menu_item_call label="Teleport" name="Landmark Open"/>
+ <menu_item_call label="Ã¥ben" name="Animation Open"/>
+ <menu_item_call label="Ã¥ben" name="Sound Open"/>
+ <menu_item_call label="Slet ting" name="Purge Item"/>
+ <menu_item_call label="Genskab ting" name="Restore Item"/>
+ <menu_item_call label="GÃ¥ til link" name="Goto Link"/>
+ <menu_item_call label="Ã¥ben" name="Open"/>
+ <menu_item_call label="Egenskaber" name="Properties"/>
+ <menu_item_call label="Omdøb" name="Rename"/>
+ <menu_item_call label="Kopiér asset UUID" name="Copy Asset UUID"/>
+ <menu_item_call label="Kopiér" name="Copy"/>
+ <menu_item_call label="Indsæt" name="Paste"/>
+ <menu_item_call label="Sæt ind som link" name="Paste As Link"/>
+ <menu_item_call label="Slet" name="Delete"/>
+ <menu_item_call label="Tag ting af" name="Take Off Items"/>
+ <menu_item_call label="Tilføj til påklædning" name="Add To Outfit"/>
+ <menu_item_call label="Erstat påklædning" name="Replace Outfit"/>
+ <menu_item_call label="start konference chat" name="Conference Chat Folder"/>
+ <menu_item_call label="Afspil" name="Sound Play"/>
+ <menu_item_call label="Om landemærke" name="About Landmark"/>
+ <menu_item_call label="Afspil offentligt" name="Animation Play"/>
+ <menu_item_call label="Afspil lokalt" name="Animation Audition"/>
+ <menu_item_call label="Send privat besked (IM)" name="Send Instant Message"/>
+ <menu_item_call label="Tilbyd teleport..." name="Offer Teleport..."/>
+ <menu_item_call label="start konference Chat" name="Conference Chat"/>
+ <menu_item_call label="Aktivér" name="Activate"/>
+ <menu_item_call label="Deaktivér" name="Deactivate"/>
+ <menu_item_call label="Gem som" name="Save As"/>
+ <menu_item_call label="Tag af dig selv" name="Detach From Yourself"/>
+ <menu_item_call label="Tag på" name="Object Wear"/>
+ <menu label="Vedhæft" name="Attach To"/>
+ <menu label="Vedhæft til HUD" name="Attach To HUD"/>
+ <menu_item_call label="Redigér" name="Wearable Edit"/>
+ <menu_item_call label="Tag på" name="Wearable Wear"/>
+ <menu_item_call label="Tag af" name="Take Off"/>
+ <menu_item_call label="--ingen valg--" name="--no options--"/>
</menu>
diff --git a/indra/newview/skins/default/xui/da/menu_inventory_add.xml b/indra/newview/skins/default/xui/da/menu_inventory_add.xml
new file mode 100644
index 0000000000..dc79e4109e
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/menu_inventory_add.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_inventory_add">
+ <menu label="Hent" name="upload">
+ <menu_item_call label="Billede (L$[COST])..." name="Upload Image"/>
+ <menu_item_call label="Lyd (L$[COST])..." name="Upload Sound"/>
+ <menu_item_call label="Animation (L$[COST])..." name="Upload Animation"/>
+ <menu_item_call label="Hent mange (L$[COST] pr. fil)..." name="Bulk Upload"/>
+ </menu>
+ <menu_item_call label="Ny mappe" name="New Folder"/>
+ <menu_item_call label="Nyt script" name="New Script"/>
+ <menu_item_call label="Ny note" name="New Note"/>
+ <menu_item_call label="Ny bevægelse" name="New Gesture"/>
+ <menu label="Nyt tøj" name="New Clothes">
+ <menu_item_call label="Ny trøje" name="New Shirt"/>
+ <menu_item_call label="Nye bukser" name="New Pants"/>
+ <menu_item_call label="Nye sko" name="New Shoes"/>
+ <menu_item_call label="Nye strømper" name="New Socks"/>
+ <menu_item_call label="Ny jakke" name="New Jacket"/>
+ <menu_item_call label="Ny nederdel" name="New Skirt"/>
+ <menu_item_call label="Nye handsker" name="New Gloves"/>
+ <menu_item_call label="Ny undertrøje" name="New Undershirt"/>
+ <menu_item_call label="Nye underbukser" name="New Underpants"/>
+ <menu_item_call label="Nyt alpha lag" name="New Alpha"/>
+ <menu_item_call label="Ny tatovering" name="New Tattoo"/>
+ </menu>
+ <menu label="Nye kropsdele" name="New Body Parts">
+ <menu_item_call label="Ny kropsbygning" name="New Shape"/>
+ <menu_item_call label="Ny hud" name="New Skin"/>
+ <menu_item_call label="Nyt hår" name="New Hair"/>
+ <menu_item_call label="Nye øjne" name="New Eyes"/>
+ </menu>
+</menu>
diff --git a/indra/newview/skins/default/xui/da/menu_login.xml b/indra/newview/skins/default/xui/da/menu_login.xml
index 26276ff3eb..9d9dcd4b2e 100644
--- a/indra/newview/skins/default/xui/da/menu_login.xml
+++ b/indra/newview/skins/default/xui/da/menu_login.xml
@@ -7,7 +7,7 @@
<menu_item_call label="Indstillinger..." name="Preferences..." />
</menu>
<menu label="Hjælp" name="Help">
- <menu_item_call label="Second Life hjælp" name="Second Life Help" />
- <menu_item_call label="Om Second Life..." name="About Second Life..." />
+ <menu_item_call label="[SECOND_LIFE] hjælp" name="Second Life Help" />
+ <menu_item_call label="Om [APP_NAME]..." name="About Second Life..." />
</menu>
</menu_bar>
diff --git a/indra/newview/skins/default/xui/da/menu_mini_map.xml b/indra/newview/skins/default/xui/da/menu_mini_map.xml
new file mode 100644
index 0000000000..2a711dc5be
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/menu_mini_map.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="popup">
+ <menu_item_call label="Zoom tæt" name="Zoom Close"/>
+ <menu_item_call label="Zoom mellem" name="Zoom Medium"/>
+ <menu_item_call label="Zoom langt" name="Zoom Far"/>
+ <menu_item_call label="Stop Tracking" name="Stop Tracking"/>
+ <menu_item_call label="Profil..." name="Profile"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/da/menu_picks.xml b/indra/newview/skins/default/xui/da/menu_picks.xml
new file mode 100644
index 0000000000..81ee900773
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/menu_picks.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Picks">
+ <menu_item_call label="Info" name="pick_info"/>
+ <menu_item_call label="Redigér" name="pick_edit"/>
+ <menu_item_call label="Teleportér" name="pick_teleport"/>
+ <menu_item_call label="Vis på kort" name="pick_map"/>
+ <menu_item_call label="Slet" name="pick_delete"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/da/menu_places_gear_landmark.xml b/indra/newview/skins/default/xui/da/menu_places_gear_landmark.xml
new file mode 100644
index 0000000000..21f425c49d
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/menu_places_gear_landmark.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_ladmark_gear">
+ <menu_item_call label="Teleportér" name="teleport"/>
+ <menu_item_call label="Mere information" name="more_info"/>
+ <menu_item_call label="Vis på kort" name="show_on_map"/>
+ <menu_item_call label="Tilføj landemærke" name="add_landmark"/>
+ <menu_item_call label="Tilføj mappe" name="add_folder"/>
+ <menu_item_call label="Klip" name="cut"/>
+ <menu_item_call label="Kopiér landemærke" name="copy_landmark"/>
+ <menu_item_call label="Kopiér SLurl" name="copy_slurl"/>
+ <menu_item_call label="Sæt ind" name="paste"/>
+ <menu_item_call label="Omdøb" name="rename"/>
+ <menu_item_call label="Slet" name="delete"/>
+ <menu_item_call label="Ã…ben alle mapper" name="expand_all"/>
+ <menu_item_call label="Luk alle mapper" name="collapse_all"/>
+ <menu_item_check label="Sortér efter dato" name="sort_by_date"/>
+ <menu_item_call label="Opret favorit" name="create_pick"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/da/menu_viewer.xml b/indra/newview/skins/default/xui/da/menu_viewer.xml
index 8ac2718353..6a75e27381 100644
--- a/indra/newview/skins/default/xui/da/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/da/menu_viewer.xml
@@ -1,211 +1,207 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<menu_bar name="Main Menu">
<menu label="Filer" name="File">
- <tearoff_menu label="~~~~~~~~~~~" name="~~~~~~~~~~~" />
+ <tearoff_menu label="~~~~~~~~~~~" name="~~~~~~~~~~~"/>
<menu label="Hent" name="upload">
- <menu_item_call label="Hent billede (L$[COST])..." name="Upload Image" />
- <menu_item_call label="Hent lyd (L$[COST])..." name="Upload Sound" />
- <menu_item_call label="Hent animation (L$[COST])..." name="Upload Animation" />
- <menu_item_call label="Hent mange (L$[COST] per file)..." name="Bulk Upload" />
+ <menu_item_call label="Billede (L$[COST])..." name="Upload Image"/>
+ <menu_item_call label="Lyd (L$[COST])..." name="Upload Sound"/>
+ <menu_item_call label="Animation (L$[COST])..." name="Upload Animation"/>
+ <menu_item_call label="Hent mange (L$[COST] per file)..." name="Bulk Upload"/>
+ <menu_item_separator label="-----------" name="separator"/>
+ <menu_item_call label="Sæt standard rettigheder..." name="perm prefs"/>
</menu>
- <menu_item_separator label="-----------" name="separator" />
- <menu_item_call label="Luk vindue" name="Close Window" />
- <menu_item_call label="Luk alle vinduer" name="Close All Windows" />
- <menu_item_separator label="-----------" name="separator2" />
- <menu_item_call label="Gem tekstur som..." name="Save Texture As..." />
- <menu_item_separator label="-----------" name="separator3" />
- <menu_item_call label="Tag foto" name="Take Snapshot" />
- <menu_item_call label="Tag foto til disk" name="Snapshot to Disk" />
- <menu_item_separator label="-----------" name="separator4" />
- <menu_item_call label="Afslut" name="Quit" />
+ <menu_item_separator label="-----------" name="separator"/>
+ <menu_item_call label="Luk vindue" name="Close Window"/>
+ <menu_item_call label="Luk alle vinduer" name="Close All Windows"/>
+ <menu_item_separator label="-----------" name="separator2"/>
+ <menu_item_call label="Gem tekstur som..." name="Save Texture As..."/>
+ <menu_item_separator label="-----------" name="separator3"/>
+ <menu_item_call label="Tag foto" name="Take Snapshot"/>
+ <menu_item_call label="Tag foto til disk" name="Snapshot to Disk"/>
+ <menu_item_separator label="-----------" name="separator4"/>
+ <menu_item_call label="Afslut" name="Quit"/>
</menu>
<menu label="Redigér" name="Edit">
- <menu_item_call label="Annullér" name="Undo" />
- <menu_item_call label="Gentag" name="Redo" />
- <menu_item_separator label="-----------" name="separator" />
- <menu_item_call label="Klip" name="Cut" />
- <menu_item_call label="Kopier" name="Copy" />
- <menu_item_call label="Sæt ind" name="Paste" />
- <menu_item_call label="Slet" name="Delete" />
- <menu_item_separator label="-----------" name="separator2" />
- <menu_item_call label="Søg..." name="Search..." />
- <menu_item_separator label="-----------" name="separator3" />
- <menu_item_call label="Vælg alt" name="Select All" />
- <menu_item_call label="Vælg intet" name="Deselect" />
- <menu_item_separator label="-----------" name="separator4" />
- <menu_item_call label="Duplikér" name="Duplicate" />
- <menu_item_separator label="-----------" name="separator5" />
- <menu label="Vedhæft objekt" name="Attach Object" />
- <menu label="Tag objekt af" name="Detach Object" />
+ <menu_item_call label="Annullér" name="Undo"/>
+ <menu_item_call label="Gentag" name="Redo"/>
+ <menu_item_separator label="-----------" name="separator"/>
+ <menu_item_call label="Klip" name="Cut"/>
+ <menu_item_call label="Kopier" name="Copy"/>
+ <menu_item_call label="Sæt ind" name="Paste"/>
+ <menu_item_call label="Slet" name="Delete"/>
+ <menu_item_separator label="-----------" name="separator2"/>
+ <menu_item_call label="Søg..." name="Search..."/>
+ <menu_item_separator label="-----------" name="separator3"/>
+ <menu_item_call label="Vælg alt" name="Select All"/>
+ <menu_item_call label="Vælg intet" name="Deselect"/>
+ <menu_item_separator label="-----------" name="separator4"/>
+ <menu_item_call label="Duplikér" name="Duplicate"/>
+ <menu_item_separator label="-----------" name="separator5"/>
+ <menu label="Vedhæft objekt" name="Attach Object"/>
+ <menu label="Tag objekt af" name="Detach Object"/>
<menu label="Tag tøj af" name="Take Off Clothing">
- <menu_item_call label="Trøje" name="Shirt" />
- <menu_item_call label="Bukser" name="Pants" />
- <menu_item_call label="Sko" name="Shoes" />
- <menu_item_call label="Strømper" name="Socks" />
- <menu_item_call label="Jakke" name="Jacket" />
- <menu_item_call label="Handsker" name="Gloves" />
- <menu_item_call label="Undertrøje" name="Menu Undershirt" />
- <menu_item_call label="Underbukser" name="Menu Underpants" />
- <menu_item_call label="Nederdel" name="Skirt" />
- <menu_item_call label="Alt tøj" name="All Clothes" />
+ <menu_item_call label="Trøje" name="Shirt"/>
+ <menu_item_call label="Bukser" name="Pants"/>
+ <menu_item_call label="Sko" name="Shoes"/>
+ <menu_item_call label="Strømper" name="Socks"/>
+ <menu_item_call label="Jakke" name="Jacket"/>
+ <menu_item_call label="Handsker" name="Gloves"/>
+ <menu_item_call label="Undertrøje" name="Menu Undershirt"/>
+ <menu_item_call label="Underbukser" name="Menu Underpants"/>
+ <menu_item_call label="Nederdel" name="Skirt"/>
+ <menu_item_call label="Alt tøj" name="All Clothes"/>
</menu>
- <menu_item_separator label="-----------" name="separator6" />
- <menu_item_call label="Bevægelser..." name="Gestures..." />
- <menu_item_call label="Profil..." name="Profile..." />
- <menu_item_call label="Udseende..." name="Appearance..." />
- <menu_item_separator label="-----------" name="separator7" />
- <menu_item_check label="Venner..." name="Friends..." />
- <menu_item_call label="Grupper..." name="Groups..." />
- <menu_item_separator label="-----------" name="separator8" />
- <menu_item_call label="Indstillinger..." name="Preferences..." />
+ <menu_item_separator label="-----------" name="separator6"/>
+ <menu_item_call label="Bevægelser..." name="Gestures..."/>
+ <menu_item_call label="Profil..." name="Profile..."/>
+ <menu_item_call label="Udseende..." name="Appearance..."/>
+ <menu_item_separator label="-----------" name="separator7"/>
+ <menu_item_check label="Venner..." name="Friends..."/>
+ <menu_item_call label="Grupper..." name="Groups..."/>
+ <menu_item_separator label="-----------" name="separator8"/>
+ <menu_item_call label="Indstillinger..." name="Preferences..."/>
</menu>
<menu label="Vis" name="View">
- <tearoff_menu label="~~~~~~~~~~~" name="~~~~~~~~~~~" />
- <menu_item_call label="Første person" name="Mouselook" />
- <menu_item_check label="Byg" name="Build" />
- <menu_item_check label="Flyv via joystick" name="Joystick Flycam" />
- <menu_item_call label="Nulstil kamera" name="Reset View" />
- <menu_item_call label="Se på sidste chatter" name="Look at Last Chatter" />
- <menu_item_separator label="-----------" name="separator" />
- <menu_item_check label="Værktøjslinie" name="Toolbar" />
- <menu_item_check label="Local chat" name="Chat History" />
- <menu_item_check label="Kommunikér" name="Instant Message" />
- <menu_item_check label="Beholdning" name="Inventory" />
- <menu_item_check label="Aktive talere" name="Active Speakers" />
- <menu_item_check label="Vis blokerede avatarer" name="Mute List" />
- <menu_item_separator label="-----------" name="separator2" />
- <menu_item_check label="Kamera kontrol" name="Camera Controls" />
- <menu_item_check label="Bevægelses kontrol" name="Movement Controls" />
- <menu_item_check label="Verdenskort" name="World Map" />
- <menu_item_check label="Lokalt kort" name="Mini-Map" />
- <menu_item_separator label="-----------" name="separator3" />
- <menu_item_check label="Teknisk info" name="Statistics Bar" />
- <menu_item_check label="Parcel skel" name="Property Lines" />
- <menu_item_check label="Grundejere" name="Land Owners" />
- <menu_item_separator label="-----------" name="separator4" />
+ <tearoff_menu label="~~~~~~~~~~~" name="~~~~~~~~~~~"/>
+ <menu_item_call label="Første person" name="Mouselook"/>
+ <menu_item_check label="Byg" name="Build"/>
+ <menu_item_check label="Flyv via joystick" name="Joystick Flycam"/>
+ <menu_item_call label="Nulstil kamera" name="Reset View"/>
+ <menu_item_call label="Se på sidste chatter" name="Look at Last Chatter"/>
+ <menu_item_separator label="-----------" name="separator"/>
+ <menu_item_check label="Værktøjslinie" name="Toolbar"/>
+ <menu_item_check label="Local chat" name="Chat History"/>
+ <menu_item_check label="Kommunikér" name="Instant Message"/>
+ <menu_item_check label="Beholdning" name="Inventory"/>
+ <menu_item_check label="Aktive talere" name="Active Speakers"/>
+ <menu_item_check label="Vis blokerede avatarer" name="Mute List"/>
+ <menu_item_separator label="-----------" name="separator2"/>
+ <menu_item_check label="Kamera kontrol" name="Camera Controls"/>
+ <menu_item_check label="Bevægelses kontrol" name="Movement Controls"/>
+ <menu_item_check label="Verdenskort" name="World Map"/>
+ <menu_item_check label="Lokalt kort" name="Mini-Map"/>
+ <menu_item_separator label="-----------" name="separator3"/>
+ <menu_item_check label="Teknisk info" name="Statistics Bar"/>
+ <menu_item_check label="Parcel skel" name="Property Lines"/>
+ <menu_item_check label="Visning af ingen adgang" name="Banlines"/>
+ <menu_item_check label="Grundejere" name="Land Owners"/>
+ <menu_item_separator label="-----------" name="separator4"/>
<menu label="Tips visning" name="Hover Tips">
- <menu_item_check label="Vis tips" name="Show Tips" />
- <menu_item_separator label="-----------" name="separator" />
- <menu_item_check label="Tips om land" name="Land Tips" />
- <menu_item_check label="Tips på alle objekter" name="Tips On All Objects" />
+ <menu_item_check label="Vis tips" name="Show Tips"/>
+ <menu_item_separator label="-----------" name="separator"/>
+ <menu_item_check label="Tips om land" name="Land Tips"/>
+ <menu_item_check label="Tips på alle objekter" name="Tips On All Objects"/>
</menu>
- <menu_item_check label="Fremhæv gennemsigtigt" name="Highlight Transparent" />
- <menu_item_check label="Pejlelys" name="beacons" />
- <menu_item_check label="Skjul partikler" name="Hide Particles" />
- <menu_item_check label="Vis HUD vedhæftninger" name="Show HUD Attachments" />
- <menu_item_separator label="-----------" name="separator5" />
- <menu_item_call label="Zoom ind" name="Zoom In" />
- <menu_item_call label="Zoom standard" name="Zoom Default" />
- <menu_item_call label="Zoom ud" name="Zoom Out" />
- <menu_item_separator label="-----------" name="separator6" />
- <menu_item_call label="Skift fuld skærm/vindue" name="Toggle Fullscreen" />
- <menu_item_call label="Sæt brugerfladestørrelse til normal" name="Set UI Size to Default" />
+ <menu_item_check label="Fremhæv gennemsigtigt" name="Highlight Transparent"/>
+ <menu_item_check label="Pejlelys" name="beacons"/>
+ <menu_item_check label="Skjul partikler" name="Hide Particles"/>
+ <menu_item_check label="Vis HUD vedhæftninger" name="Show HUD Attachments"/>
+ <menu_item_separator label="-----------" name="separator5"/>
+ <menu_item_call label="Zoom ind" name="Zoom In"/>
+ <menu_item_call label="Zoom standard" name="Zoom Default"/>
+ <menu_item_call label="Zoom ud" name="Zoom Out"/>
+ <menu_item_separator label="-----------" name="separator6"/>
+ <menu_item_call label="Skift fuld skærm/vindue" name="Toggle Fullscreen"/>
+ <menu_item_call label="Sæt brugerfladestørrelse til normal" name="Set UI Size to Default"/>
</menu>
<menu label="Verden" name="World">
- <menu_item_call label="Chat" name="Chat" />
- <menu_item_check label="Løb" name="Always Run" />
- <menu_item_check label="Flyv" name="Fly" />
- <menu_item_separator label="-----------" name="separator" />
- <menu_item_call label="Opret landemærke her" name="Create Landmark Here" />
- <menu_item_call label="Sæt hjem til her" name="Set Home to Here" />
- <menu_item_separator label="-----------" name="separator2" />
- <menu_item_call label="Teleporter hjem" name="Teleport Home" />
- <menu_item_separator label="-----------" name="separator3" />
- <menu_item_call label="Sæt &apos;ikke til stede&apos;" name="Set Away" />
- <menu_item_call label="Sæt &apos;optaget&apos;" name="Set Busy" />
- <menu_item_call label="Stop all animationer" name="Stop All Animations" />
- <menu_item_call label="Frigiv taster" name="Release Keys" />
- <menu_item_separator label="-----------" name="separator4" />
- <menu_item_call label="Konto historik..." name="Account History..." />
- <menu_item_call label="Vedligehold konto..." name="Manage My Account..." />
- <menu_item_call label="Køb L$..." name="Buy and Sell L$..." />
- <menu_item_separator label="-----------" name="separator5" />
- <menu_item_call label="Mit land..." name="My Land..." />
- <menu_item_call label="Om land..." name="About Land..." />
- <menu_item_call label="Køb land..." name="Buy Land..." />
- <menu_item_call label="Region/Estate..." name="Region/Estate..." />
- <menu_item_separator label="-----------" name="separator6" />
+ <menu_item_call label="Chat" name="Chat"/>
+ <menu_item_check label="Løb" name="Always Run"/>
+ <menu_item_check label="Flyv" name="Fly"/>
+ <menu_item_separator label="-----------" name="separator"/>
+ <menu_item_call label="Opret landemærke her" name="Create Landmark Here"/>
+ <menu_item_call label="Sæt hjem til her" name="Set Home to Here"/>
+ <menu_item_separator label="-----------" name="separator2"/>
+ <menu_item_call label="Teleporter hjem" name="Teleport Home"/>
+ <menu_item_separator label="-----------" name="separator3"/>
+ <menu_item_call label="Sæt &apos;ikke til stede&apos;" name="Set Away"/>
+ <menu_item_call label="Sæt &apos;optaget&apos;" name="Set Busy"/>
+ <menu_item_call label="Stop animering af min avatar" name="Stop Animating My Avatar"/>
+ <menu_item_call label="Frigiv taster" name="Release Keys"/>
+ <menu_item_separator label="-----------" name="separator4"/>
+ <menu_item_call label="Konto historik..." name="Account History..."/>
+ <menu_item_call label="Vedligehold konto..." name="Manage My Account..."/>
+ <menu_item_call label="Køb L$..." name="Buy and Sell L$..."/>
+ <menu_item_separator label="-----------" name="separator5"/>
+ <menu_item_call label="Mit land..." name="My Land..."/>
+ <menu_item_call label="Om land..." name="About Land..."/>
+ <menu_item_call label="Køb land..." name="Buy Land..."/>
+ <menu_item_call label="Region/Estate..." name="Region/Estate..."/>
+ <menu_item_separator label="-----------" name="separator6"/>
<menu label="Indstillinger for omgivelser" name="Environment Settings">
- <menu_item_call label="Solopgang" name="Sunrise" />
- <menu_item_call label="Middag" name="Noon" />
- <menu_item_call label="Solnedgang" name="Sunset" />
- <menu_item_call label="Midnat" name="Midnight" />
- <menu_item_call label="Gendan til standard for region" name="Revert to Region Default" />
- <menu_item_separator label="-----------" name="separator" />
- <menu_item_call label="Redigering af omgivelser" name="Environment Editor" />
+ <menu_item_call label="Solopgang" name="Sunrise"/>
+ <menu_item_call label="Middag" name="Noon"/>
+ <menu_item_call label="Solnedgang" name="Sunset"/>
+ <menu_item_call label="Midnat" name="Midnight"/>
+ <menu_item_call label="Gendan til standard for region" name="Revert to Region Default"/>
+ <menu_item_separator label="-----------" name="separator"/>
+ <menu_item_call label="Redigering af omgivelser" name="Environment Editor"/>
</menu>
</menu>
<menu label="Funktioner" name="Tools">
<menu label="Vælg værktøj" name="Select Tool">
- <menu_item_call label="Fokus" name="Focus" />
- <menu_item_call label="Flyt" name="Move" />
- <menu_item_call label="Rediger" name="Edit" />
- <menu_item_call label="Byg" name="Create" />
- <menu_item_call label="Land" name="Land" />
+ <menu_item_call label="Fokus" name="Focus"/>
+ <menu_item_call label="Flyt" name="Move"/>
+ <menu_item_call label="Rediger" name="Edit"/>
+ <menu_item_call label="Byg" name="Create"/>
+ <menu_item_call label="Land" name="Land"/>
</menu>
- <menu_item_separator label="-----------" name="separator" />
- <menu_item_check label="Vælg kun egne objekter" name="Select Only My Objects" />
- <menu_item_check label="Vælg kun flytbare objekter" name="Select Only Movable Objects" />
- <menu_item_check label="Vælg ved at omkrandse" name="Select By Surrounding" />
- <menu_item_check label="Vis skjulte objekter" name="Show Hidden Selection" />
- <menu_item_check label="Vis lys-radius for valgte" name="Show Light Radius for Selection" />
- <menu_item_check label="Vis guidelys for valgte" name="Show Selection Beam" />
- <menu_item_separator label="-----------" name="separator2" />
- <menu_item_check label="Ret ind til gitter" name="Snap to Grid" />
- <menu_item_call label="Ret XY for objekt ind til gitter" name="Snap Object XY to Grid" />
- <menu_item_call label="Benyt valgte som grundlag for gitter" name="Use Selection for Grid" />
- <menu_item_call label="Gitter indstillinger..." name="Grid Options..." />
- <menu_item_separator label="-----------" name="separator3" />
- <menu_item_check label="Rediger sammekædede objekter" name="Edit Linked Parts" />
- <menu_item_call label="Sammenkæd" name="Link" />
- <menu_item_call label="Adskil" name="Unlink" />
- <menu_item_separator label="-----------" name="separator4" />
- <menu_item_call label="Fokusér på valgte" name="Focus on Selection" />
- <menu_item_call label="Zoom på valgte" name="Zoom to Selection" />
- <menu_item_call label="Køb objekt" name="Menu Object Take" />
- <menu_item_call label="Tag kopi" name="Take Copy" />
- <menu_item_call label="Opdatér objekt i beholdning med ændringer"
- name="Save Object Back to My Inventory" />
- <menu_item_call label="Opdatér ændringer i indhold på objekt"
- name="Save Object Back to Object Contents" />
- <menu_item_separator label="-----------" name="separator6" />
- <menu_item_call label="Vis vindue med advarsler/fejl fra scripts"
- name="Show Script Warning/Error Window" />
- <menu label="Rekompilér scripts i valgte objekter"
- name="Recompile Scripts in Selection">
- <menu_item_call label="Mono" name="Mono" />
- <menu_item_call label="LSL" name="LSL" />
+ <menu_item_separator label="-----------" name="separator"/>
+ <menu_item_check label="Vælg kun egne objekter" name="Select Only My Objects"/>
+ <menu_item_check label="Vælg kun flytbare objekter" name="Select Only Movable Objects"/>
+ <menu_item_check label="Vælg ved at omkrandse" name="Select By Surrounding"/>
+ <menu_item_check label="Vis skjulte objekter" name="Show Hidden Selection"/>
+ <menu_item_check label="Vis lys-radius for valgte" name="Show Light Radius for Selection"/>
+ <menu_item_check label="Vis guidelys for valgte" name="Show Selection Beam"/>
+ <menu_item_separator label="-----------" name="separator2"/>
+ <menu_item_check label="Ret ind til gitter" name="Snap to Grid"/>
+ <menu_item_call label="Ret XY for objekt ind til gitter" name="Snap Object XY to Grid"/>
+ <menu_item_call label="Benyt valgte som grundlag for gitter" name="Use Selection for Grid"/>
+ <menu_item_call label="Gitter indstillinger..." name="Grid Options..."/>
+ <menu_item_separator label="-----------" name="separator3"/>
+ <menu_item_check label="Rediger sammekædede objekter" name="Edit Linked Parts"/>
+ <menu_item_call label="Sammenkæd" name="Link"/>
+ <menu_item_call label="Adskil" name="Unlink"/>
+ <menu_item_separator label="-----------" name="separator4"/>
+ <menu_item_call label="Fokusér på valgte" name="Focus on Selection"/>
+ <menu_item_call label="Zoom på valgte" name="Zoom to Selection"/>
+ <menu_item_call label="Køb objekt" name="Menu Object Take">
+ <on_enable userdata="Køb,Tag" name="EnableBuyOrTake"/>
+ </menu_item_call>
+ <menu_item_call label="Tag kopi" name="Take Copy"/>
+ <menu_item_call label="Opdatér ændringer i indhold på objekt" name="Save Object Back to Object Contents"/>
+ <menu_item_separator label="-----------" name="separator6"/>
+ <menu_item_call label="Vis vindue med advarsler/fejl fra scripts" name="Show Script Warning/Error Window"/>
+ <menu label="Rekompilér scripts i valgte objekter" name="Recompile Scripts in Selection">
+ <menu_item_call label="Mono" name="Mono"/>
+ <menu_item_call label="LSL" name="LSL"/>
</menu>
- <menu_item_call label="Genstart scripts i valgte objekter" name="Reset Scripts in Selection" />
- <menu_item_call label="Sæt scripts til &apos;Running&apos; i valgte objekter"
- name="Set Scripts to Running in Selection" />
- <menu_item_call label="Sæt scripts til &apos; Not running&apos; i valgte objekter"
- name="Set Scripts to Not Running in Selection" />
+ <menu_item_call label="Genstart scripts i valgte objekter" name="Reset Scripts in Selection"/>
+ <menu_item_call label="Sæt scripts til &apos;Running&apos; i valgte objekter" name="Set Scripts to Running in Selection"/>
+ <menu_item_call label="Sæt scripts til &apos; Not running&apos; i valgte objekter" name="Set Scripts to Not Running in Selection"/>
</menu>
<menu label="Hjælp" name="Help">
- <menu_item_call label="Second Life Hjælp" name="Second Life Help" />
- <menu_item_call label="Tutorial" name="Tutorial" />
- <menu_item_separator label="-----------" name="separator" />
- <menu_item_call label="Officiel Linden Blog..." name="Official Linden Blog..." />
- <menu_item_separator label="-----------" name="separator2" />
- <menu_item_call label="Portal om scripts..." name="Scripting Portal..." />
- <menu_item_separator label="-----------" name="separator3" />
- <menu_item_call label="Rapporter misbrug..." name="Report Abuse..." />
- <menu_item_call label="Stød, skub &amp; slag..." name="Bumps, Pushes &amp;amp; Hits..." />
- <menu_item_call label="Lag meter" name="Lag Meter" />
- <menu_item_separator label="-----------" name="separator7" />
+ <menu_item_call label="[SECOND_LIFE] Hjælp" name="Second Life Help"/>
+ <menu_item_call label="Tutorial" name="Tutorial"/>
+ <menu_item_separator label="-----------" name="separator"/>
+ <menu_item_call label="Officiel Linden Blog..." name="Official Linden Blog..."/>
+ <menu_item_separator label="-----------" name="separator2"/>
+ <menu_item_call label="Portal om scripts..." name="Scripting Portal..."/>
+ <menu_item_separator label="-----------" name="separator3"/>
+ <menu_item_call label="Rapporter misbrug..." name="Report Abuse..."/>
+ <menu_item_call label="Stød, skub &amp; slag..." name="Bumps, Pushes &amp;amp; Hits..."/>
+ <menu_item_call label="Lag meter" name="Lag Meter"/>
+ <menu_item_separator label="-----------" name="separator7"/>
<menu label="Fejlrapport" name="Bug Reporting">
- <menu_item_call label="Second Life sagsstyring..." name="Public Issue Tracker..." />
- <menu_item_call label="Hjælp til Second Life sagsstyring..."
- name="Publc Issue Tracker Help..." />
- <menu_item_separator label="-----------" name="separator7" />
- <menu_item_call label="Om fejlrapportering..." name="Bug Reporing 101..." />
- <menu_item_call label="Anmeld sikkerhedshændelser..." name="Security Issues..." />
- <menu_item_call label="QA Wiki..." name="QA Wiki..." />
- <menu_item_separator label="-----------" name="separator9" />
- <menu_item_call label="Anmeld fejl..." name="Report Bug..." />
+ <menu_item_call label="[SECOND_LIFE] sagsstyring..." name="Public Issue Tracker..."/>
+ <menu_item_call label="Hjælp til [SECOND_LIFE] sagsstyring..." name="Publc Issue Tracker Help..."/>
+ <menu_item_separator label="-----------" name="separator7"/>
+ <menu_item_call label="Om fejlrapportering..." name="Bug Reporing 101..."/>
+ <menu_item_call label="Anmeld sikkerhedshændelser..." name="Security Issues..."/>
+ <menu_item_call label="QA Wiki..." name="QA Wiki..."/>
+ <menu_item_separator label="-----------" name="separator9"/>
+ <menu_item_call label="Anmeld fejl..." name="Report Bug..."/>
</menu>
- <menu_item_call label="Om Second Life..." name="About Second Life..." />
- ,
+ <menu_item_call label="Om [APP_NAME]..." name="About Second Life..."/>
</menu>
</menu_bar>
diff --git a/indra/newview/skins/default/xui/da/notifications.xml b/indra/newview/skins/default/xui/da/notifications.xml
index eedc588449..42f55d4678 100644
--- a/indra/newview/skins/default/xui/da/notifications.xml
+++ b/indra/newview/skins/default/xui/da/notifications.xml
@@ -1,15 +1,14 @@
-<?xml version="1.0" ?><notifications>
-
- <global name="skipnexttime">
-
+<?xml version="1.0" encoding="utf-8"?>
+<notifications>
+ <global name="skipnexttime">
Vis ikke dette igen
- </global>
-
- <global name="alwayschoose">
-
+ </global>
+ <global name="alwayschoose">
Vælg altid dette
- </global>
-
+ </global>
+ <global name="implicitclosebutton">
+ Luk
+ </global>
<template name="okbutton">
<form>
<button
@@ -74,421 +73,438 @@
text="$canceltext"/>
</form>
</template>
+ <notification functor="GenericAcknowledge" label="Ukendt advarsels-besked" name="MissingAlert">
+ Din version af [APP_NAME] kan ikke vise den advarselsbesked den modtog.
- <notification
- functor="GenericAcknowledge"
-
- name="MissingAlert"
- >
-&apos;[_NAME]&apos; mangler fra notifications.xml.
- <usetemplate
- name="okbutton"
- yestext="OK"/>
- </notification>
-
- <notification
-
- name="FloaterNotFound"
- >
-Floater error: Kunne ikke finde følgende kontrol:
+Fejl detaljer: Advarslen &apos;[_NAME]&apos; blev ikke fundet i notifications.xml.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="FloaterNotFound">
+ Floater error: Kunne ikke finde følgende kontrol:
[CONTROLS]
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="TutorialNotFound">
+ Der er i øjeblikket ingen tilgængelig guide.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="GenericAlert">
+ [MESSAGE]
+ </notification>
+ <notification name="GenericAlertYesCancel">
+ [MESSAGE]
+ <usetemplate name="okcancelbuttons" notext="Annullér" yestext="Ja"/>
+ </notification>
+ <notification name="BadInstallation">
+ Der opstod en fejl ved opdatering af [APP_NAME]. Hent venligst den nyeste version fra secondlife.com.
<usetemplate
name="okbutton"
yestext="OK"/>
- </notification>
-
- <notification
-
- name="TutorialNotFound"
- >
-Der er i øjeblikket ingen tilgængelig guide.
- <usetemplate
+ </notification>
+ <notification name="LoginFailedNoNetwork">
+ Netværksfejl: Kunne ikke oprette forbindelse.
+&apos;[DIAGNOSTIC]&apos;
+Check venligst din netværksforbindelse.
+ <usetemplate
name="okbutton"
yestext="OK"/>
- </notification>
-
- <notification
-
- name="GenericAlert"
- >
-[MESSAGE]
- </notification>
-
- <notification
-
- name="GenericAlertYesCancel"
- >
-[MESSAGE]
- <usetemplate
- name="okcancelbuttons"
- notext="Annullér"
- yestext="Ja"/>
- </notification>
-
- <notification
-
- name="WearableSave"
- >
-Gem ændringer til nuværende tøj/krops del?
- <usetemplate
- canceltext="Annullér"
- name="yesnocancelbuttons"
- notext="Gem ikke"
- yestext="Gem"/>
- </notification>
-
- <notification
-
- name="CompileQueueSaveText"
- >
-Der var problemer med upload af teksten til et script af følgende årsager: [REASON]. Prøv igen senere.
- </notification>
-
- <notification
-
- name="CompileQueueSaveBytecode"
- >
-Der var problemer med at uploade den kompileret script af følgende årsager: [REASON]. Prøv igen senere.
- </notification>
-
- <notification
-
- name="WriteAnimationFail"
- >
-Der var et problem med skrivning af animations data. Prøv igen senere.
- </notification>
-
- <notification
-
- name="UploadAuctionSnapshotFail"
- >
-Der var problemer med at uploade billedet til auktionen af følgende årsager: [REASON]
- </notification>
-
- <notification
-
- name="UnableToViewContentsMoreThanOne"
- >
-Ude af stand til at se indholdet af mere end ét element ad gangen.
+ </notification>
+ <notification name="MessageTemplateNotFound">
+ Besked template [PATH] kunne ikke findes.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+ <notification name="WearableSave">
+ Gem ændringer til nuværende tøj/krops del?
+ <usetemplate canceltext="Annullér" name="yesnocancelbuttons" notext="Gem ikke" yestext="Gem"/>
+ </notification>
+ <notification name="CompileQueueSaveText">
+ Der var problemer med upload af teksten til et script af følgende årsager: [REASON]. Prøv igen senere.
+ </notification>
+ <notification name="CompileQueueSaveBytecode">
+ Der var problemer med at uploade den kompileret script af følgende årsager: [REASON]. Prøv igen senere.
+ </notification>
+ <notification name="WriteAnimationFail">
+ Der var et problem med skrivning af animations data. Prøv igen senere.
+ </notification>
+ <notification name="UploadAuctionSnapshotFail">
+ Der var problemer med at uploade billedet til auktionen af følgende årsager: [REASON]
+ </notification>
+ <notification name="UnableToViewContentsMoreThanOne">
+ Ude af stand til at se indholdet af mere end ét element ad gangen.
Vælg kun en genstand, og prøv igen.
- </notification>
-
- <notification
-
- name="SaveClothingBodyChanges"
- >
-Gem alle ændringer til tøj/krops dele?
- <usetemplate
- canceltext="Annullér"
- name="yesnocancelbuttons"
- notext="Gem Ikke"
- yestext="Gem Alt"/>
- </notification>
-
- <notification
-
- name="GrantModifyRights"
- >
-At give redigerings rettigheder til en anden beboer, giver dem mulighed for at ændre, slette eller tage alle genstande, du måtte have i verden. Vær meget forsigtig når uddeler denne tilladelse.
+ </notification>
+ <notification name="SaveClothingBodyChanges">
+ Gem alle ændringer til tøj/krops dele?
+ <usetemplate canceltext="Annullér" name="yesnocancelbuttons" notext="Gem Ikke" yestext="Gem Alt"/>
+ </notification>
+ <notification name="GrantModifyRights">
+ At give redigerings rettigheder til en anden beboer, giver dem mulighed for at ændre, slette eller tage alle genstande, du måtte have i verden. Vær meget forsigtig når uddeler denne tilladelse.
Ønsker du at ændre rettigheder for [FIRST_NAME] [LAST_NAME]?
- <usetemplate
- name="okcancelbuttons"
- notext="Nej"
- yestext="Ja"/>
- </notification>
-
- <notification
-
- name="GrantModifyRightsMultiple"
- >
-At give redigerings rettigheder til en anden beboer, giver dem mulighed for at ændre, slette eller tage alle genstande, du måtte have i verden. Vær meget forsigtig når uddeler denne tilladelse.
+ <usetemplate name="okcancelbuttons" notext="Nej" yestext="Ja"/>
+ </notification>
+ <notification name="GrantModifyRightsMultiple">
+ At give redigerings rettigheder til en anden beboer, giver dem mulighed for at ændre, slette eller tage alle genstande, du måtte have i verden. Vær meget forsigtig når uddeler denne tilladelse.
Ønsker du at ændre rettigheder for de valgte beboere?
- <usetemplate
- name="okcancelbuttons"
- notext="Nej"
- yestext="Ja"/>
- </notification>
-
- <notification
-
- name="RevokeModifyRights"
- >
-Vil du tilbagekalde rettighederne for [FIRST_NAME] [LAST_NAME]?
- <usetemplate
- name="okcancelbuttons"
- notext="Nej"
- yestext="Ja"/>
- </notification>
-
- <notification
-
- name="RevokeModifyRightsMultiple"
- >
-Vil du tilbagekalde rettighederne for de valgte beboere?
- <usetemplate
- name="okcancelbuttons"
- notext="Nej"
- yestext="Ja"/>
- </notification>
-
- <notification
-
- name="UnableToCreateGroup"
- >
-Kunne ikke oprette gruppe.
+ <usetemplate name="okcancelbuttons" notext="Nej" yestext="Ja"/>
+ </notification>
+ <notification name="RevokeModifyRights">
+ Vil du tilbagekalde rettighederne for [FIRST_NAME] [LAST_NAME]?
+ <usetemplate name="okcancelbuttons" notext="Nej" yestext="Ja"/>
+ </notification>
+ <notification name="RevokeModifyRightsMultiple">
+ Vil du tilbagekalde rettighederne for de valgte beboere?
+ <usetemplate name="okcancelbuttons" notext="Nej" yestext="Ja"/>
+ </notification>
+ <notification name="UnableToCreateGroup">
+ Kunne ikke oprette gruppe.
[MESSAGE]
- <usetemplate
- name="okbutton"
- yestext="OK"/>
- </notification>
-
- <notification
-
- name="PanelGroupApply"
- >
-[NEEDS_APPLY_MESSAGE]
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="PanelGroupApply">
+ [NEEDS_APPLY_MESSAGE]
[WANT_APPLY_MESSAGE]
- <usetemplate
- canceltext="Annullér"
- name="yesnocancelbuttons"
- notext="Ignorer Ændringer"
- yestext="Godkend Ændringer"/>
- </notification>
-
- <notification
-
- name="MustSpecifyGroupNoticeSubject"
- >
-Du skal angive et emne for at sende en gruppe besked.
- <usetemplate
- name="okbutton"
- yestext="OK"/>
- </notification>
-
- <notification
-
- name="AddGroupOwnerWarning"
- >
-Du er ved at tilføje medlemmer til rollen som [ROLE_NAME].
+ <usetemplate canceltext="Annullér" name="yesnocancelbuttons" notext="Ignorer Ændringer" yestext="Godkend Ændringer"/>
+ </notification>
+ <notification name="MustSpecifyGroupNoticeSubject">
+ Du skal angive et emne for at sende en gruppe besked.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="AddGroupOwnerWarning">
+ Du er ved at tilføje medlemmer til rollen som [ROLE_NAME].
Medlemmer ikke kan fjernes fra denne rolle.
Medlemmerne skal fratræde sin rolle selv.
Er du sikker på du vil fortsætte?
- <usetemplate
- ignoretext="Når du tilføjer medlemmer til ejer rollen"
- name="okcancelignore"
- notext="Nej"
- yestext="Ja"/>
- </notification>
-
- <notification
-
- name="AssignDangerousActionWarning"
- >
-Du er ved at tilføje muligheden for &apos;[ACTION_NAME]&apos; til
+ <usetemplate ignoretext="Når du tilføjer medlemmer til ejer rollen" name="okcancelignore" notext="Nej" yestext="Ja"/>
+ </notification>
+ <notification name="AssignDangerousActionWarning">
+ Du er ved at tilføje muligheden for &apos;[ACTION_NAME]&apos; til
rollen &apos;[ROLE_NAME]&apos;.
*ADVARSEL*
Ethvert medlem i en rolle med denne evne kan tildele sig selv -- og et andet medlem - roller med flere beføjelser, end de har i øjeblikket, potentielt kan de ophøje sig selv til nær-Ejer magt. Være sikker på, at du ved, hvad du laver, før tildeling af denne evne.
Add this Ability to &apos;[ROLE_NAME]&apos;?
+ <usetemplate name="okcancelbuttons" notext="Nej" yestext="Ja"/>
+ </notification>
+ <notification name="ClickSoundHelpLand">
+ Media og musik kan kun ses og høres indenfor parcellen. Lyd og stemme valg muligheder kan begrænses til parcellen eller de kan høres af beboere udenfor parcellen, afhængigt af deres indholdsrating. Gå til &apos;Knowledge Base&apos; for at lære hvordan disse valg opsættes.
+ <url name="url">
+ https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=5046
+ </url>
<usetemplate
name="okcancelbuttons"
- notext="Nej"
- yestext="Ja"/>
- </notification>
-
- <notification
-
- name="ClickPublishHelpAvatar"
- >
-Hvis du vælger &quot;Vis i Søgning&quot; Vises:
+ yestext="GÃ¥ til &apos;Knowledge Base&apos;"
+ notext="Luk" />
+ </notification>
+ <notification name="ClickSearchHelpAll">
+ Søgeresultater er organiseret baseret på den fane du står på, din indholdsrating, den valgte kategori og andre faktorer. for yderligere detaljer se i &apos;Knowledge Base&apos;.
+ <url name="url">
+ https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=4722
+ </url>
+ <usetemplate
+ name="okcancelbuttons"
+ yestext="GÃ¥ til &apos;Knowledge Base&apos;"
+ notext="Luk" />
+ </notification>
+ <notification name="ClickPublishHelpAvatar">
+ Hvis du vælger &quot;Vis i Søgning&quot; Vises:
- Din profil i søgeresultater
- Et link til din profile i de offentlige gruppe sider
- </notification>
-
- <notification
-
- name="ClickWebProfileHelpAvatar"
- >
-Hvis en beboer har en hjemmeside adresse kan du:
+ </notification>
+ <notification name="ClickUploadHelpPermissions">
+ Dinne standard rettigheder virker muligvis ikke i ældre regioner.
+ </notification>
+ <notification name="ClickWebProfileHelpAvatar">
+ Hvis en beboer har en hjemmeside adresse kan du:
* Klikke &apos;Load&apos; for at side deres side her.
* Klikke Load &gt; &apos;I ekstern browser&apos; for at se siden i din standard browser.
* Klikke Load &gt; &apos;Hjemme URL&apos; for at returnere til denne beboers side hvis du har navigeret væk.
Når du ser din egen profil, kan du skrive hvilken som helst adresse og klikke ok for at få den vist i din egen profil.
Andre beboere kan besøge den adresse du har sat, når de besøger din profil.
- </notification>
-
- <notification
-
- name="JoinGroupCannotAfford"
- >
-Tilmelding til denne gruppe koster L$[COST].
+ </notification>
+ <notification name="JoinGroupCannotAfford">
+ Tilmelding til denne gruppe koster L$[COST].
Du har ikke nok L$ til denne tilmelding.
- </notification>
-
- <notification
-
- name="PromptMissingSubjMsg"
- >
-E-mail dette billede med standard emne eller besked?
- <usetemplate
- name="okcancelbuttons"
- notext="Annullér"
- yestext="OK"/>
- </notification>
-
- <notification
-
- name="ErrorUploadingPostcard"
- >
-Der var et problem med at sende billedet på grund af følgende: [REASON]
- </notification>
-
- <notification
-
- name="MustHaveAccountToLogIn"
- >
-Ups! Noget var tomt.
+ </notification>
+ <notification name="PromptMissingSubjMsg">
+ E-mail dette billede med standard emne eller besked?
+ <usetemplate name="okcancelbuttons" notext="Annullér" yestext="OK"/>
+ </notification>
+ <notification name="ErrorUploadingPostcard">
+ Der var et problem med at sende billedet på grund af følgende: [REASON]
+ </notification>
+ <notification name="MustHaveAccountToLogIn">
+ Ups! Noget var tomt.
Du skal skrive både fornavn og efternavn på din figur.
Du har brug for en konto for at logge ind i [SECOND_LIFE]. Vil du oprette en nu?
- <usetemplate
- name="okcancelbuttons"
- notext="Prøv igen"
- yestext="Lav ny konto"/>
- </notification>
-
- <notification
-
- name="ResetShowNextTimeDialogs"
- >
-Vil du gerne genaktivere alle disse popups, som du tidligere har bedt om ikke at få vist?
- <usetemplate
- name="okcancelbuttons"
- notext="Annullér"
- yestext="OK"/>
- </notification>
-
- <notification
-
- name="SkipShowNextTimeDialogs"
- >
-Vil du deaktivere alle popups som kan undværes?
- <usetemplate
- name="okcancelbuttons"
- notext="Annullér"
- yestext="OK"/>
- </notification>
-
- <notification
-
- name="ChangeSkin"
- >
-Det nye udseende vil vises efter du har genstartet [SECOND_LIFE].
- </notification>
-
- <notification
-
- name="UnsupportedHardware"
- >
- <form name="form">
- <ignore name="ignore"
- text="Ved opdagelse af ikke supporteret hardware"/>
- </form>
- </notification>
-
- <notification
-
- name="UnknownGPU"
- >
- <form name="form">
- <ignore name="ignore"
- text="Ved opdagelse af et ukendt grafikkort"/>
- </form>
- </notification>
-
- <notification
-
- name="CannotGiveCategory"
- >
-Du har ikke tilladelse til at videreføre den valgte mappe.
- </notification>
-
- <notification
-
- name="CannotBuyLandNoRegion"
- >
-Ikke i stand til at købe land:
+ <usetemplate name="okcancelbuttons" notext="Prøv igen" yestext="Lav ny konto"/>
+ </notification>
+ <notification name="ResetShowNextTimeDialogs">
+ Vil du gerne genaktivere alle disse popups, som du tidligere har bedt om ikke at få vist?
+ <usetemplate name="okcancelbuttons" notext="Annullér" yestext="OK"/>
+ </notification>
+ <notification name="SkipShowNextTimeDialogs">
+ Vil du deaktivere alle popups som kan undværes?
+ <usetemplate name="okcancelbuttons" notext="Annullér" yestext="OK"/>
+ </notification>
+ <notification name="ChangeSkin">
+ Det nye udseende vil vises efter du har genstartet [APP_NAME].
+ </notification>
+ <notification name="UnsupportedHardware"/>
+ <notification name="UnknownGPU">
+ <form name="form">
+ <ignore name="ignore" text="Ved opdagelse af et ukendt grafikkort"/>
+ </form>
+ </notification>
+
+ <notification name="invalid_tport">
+Der er problemer med at håndtere din teleport. Det kan være nødvendigt at logge ud og ind for at kunne skifte teleportere.
+Hvis du bliver ved med at have problemet kan du checke teknisk support på:
+www.secondlife.com/support
+ </notification>
+ <notification name="invalid_region_handoff">
+Problem registreret i forbindelse med skift til ny region. Det kan være nødvendigt at logge ud og ind for at kunne skifte regioner.
+Hvis du bliver ved med at have problemet kan du checke teknisk support på:
+www.secondlife.com/support
+ </notification>
+ <notification name="blocked_tport">
+Beklager, teleport er blokeret lige nu. Prøv igen senere.
+Hvis du stadig ikke kan teleporte, prøv venligst at logge ud og ligge ind for at løse dette problem.
+ </notification>
+ <notification name="nolandmark_tport">
+Beklager, systemet kunne ikke finde landmærke destinationen.
+ </notification>
+ <notification name="timeout_tport">
+Beklager, systemet kunne ikke fuldføre teleport forbindelse.
+Prøv igen om lidt.
+ </notification>
+ <notification name="noaccess_tport">
+Beklager, du har ikke adgang til denne teleport destination.
+ </notification>
+ <notification name="missing_attach_tport">
+Dine vedhæng er ikke ankommet endnu. Prøv at vente lidt endnu eller log ud og ind igen før du prøver at teleporte igen.
+ </notification>
+ <notification name="too_many_uploads_tport">
+Tekniske problemer hindrer at din teleport kan gennemføres.
+Prøv venligst igen om lidt eller vælg et mindre travlt område.
+ </notification>
+ <notification name="expired_tport">
+Beklager, men systemet kunne ikke fuldføre din teleport i rimelig tid. Prøv venligst igen om lidt.
+ </notification>
+ <notification name="expired_region_handoff">
+Beklager, men systemet kunne ikke fuldføre skift til anden region i rimelig tid. Prøv venligst igen om lidt.
+ </notification>
+ <notification name="no_host">
+Ikke muligt at fine teleport destination. Destinationen kan være midlertidig utilgængelig eller findes ikke mere.
+Prøv evt. igen om lidt.
+ </notification>
+ <notification name="no_inventory_host">
+Beholdningssystemet er ikke tilgængelig lige nu.
+ </notification>
+
+ <notification name="CannotGiveCategory">
+ Du har ikke tilladelse til at videreføre den valgte mappe.
+ </notification>
+ <notification name="CannotEncodeFile">
+ Kunne ikke &apos;forstå&apos; filen: [FILE]
+ </notification>
+ <notification name="CannotBuyLandNoRegion">
+ Ikke i stand til at købe land:
Kan ikke finde region som dette land er i.
- </notification>
-
- <notification
-
- name="YouHaveBeenLoggedOut"
- >
-Du er blevet logget ud af [SECOND_LIFE]:
+ </notification>
+ <notification name="ShowOwnersHelp">
+ Vis ejere:
+Farver på parceller viser ejer-type.
+
+Grøn = Dit land
+Turkis = Din gruppes land
+Rød = Ejet af andre
+Gul = Til salg
+Lilla = PÃ¥ auktion
+Grå = Offentligt ejet
+ </notification>
+ <notification name="YouHaveBeenLoggedOut">
+ Du er blevet logget ud af [SECOND_LIFE]:
[MESSAGE]
-Du kan stadig se eksiterende PB&apos;er og chat ved at klikke&apos;Se PB &amp; Chat&apos;. Ellers, klik &apos;Afslut&apos; for at afslutte [SECOND_LIFE] nu.
- <usetemplate
- name="okcancelbuttons"
- notext="Quit"
- yestext="Se IM &amp; Chat"/>
- </notification>
-
- <notification
-
- label="Add Friend"
- name="AddFriend"
- >
-Venner kan give tilladelse til at følge hinanden
+Du kan stadig se eksiterende PB&apos;er og chat ved at klikke&apos;Se PB &amp; Chat&apos;. Ellers, klik &apos;Afslut&apos; for at afslutte [APP_NAME] nu.
+ <usetemplate name="okcancelbuttons" notext="Afslut" yestext="Se PB &amp; Chat"/>
+ </notification>
+ <notification label="Tilføj ven" name="AddFriend">
+ Venner kan give tilladelse til at følge hinanden
på Verdenskortet eller modtage status opdateringer.
Tilbyd venskab til [NAME]?
- <usetemplate
- name="okcancelbuttons"
- notext="Annullér"
- yestext="OK"/>
- </notification>
-
- <notification
-
- label="Add Friend"
- name="AddFriendWithMessage"
- >
-Venner kan give tilladelse til at følge hinanden
+ <usetemplate name="okcancelbuttons" notext="Annullér" yestext="OK"/>
+ </notification>
+ <notification label="Tilføj ven" name="AddFriendWithMessage">
+ Venner kan give tilladelse til at følge hinanden
på Verdenskortet eller modtage status opdateringer.
Tilbyd venskab til [NAME]?
- <form name="form">
- <input name="message" type="text">
-Vil du være min ven?
- </input>
+ <form name="form">
+ <input name="message">
+ Vil du være min ven?
+ </input>
+ <button name="Offer" text="OK"/>
+ <button name="Cancel" text="Annullér"/>
+ </form>
+ </notification>
+ <notification name="NotEnoughCurrency">
+ [NAME] L$ [PRICE] Du har ikke nok L$ til dette.
+ </notification>
+ <notification name="BuyOneObjectOnly">
+ Ikke muligt at købe mere end et objekt ad gangen. Vælg kun ét objekt og prøv igen.
+ </notification>
+ <notification name="CannotStartAuctionAlreadyForSale">
+ Du kan ikke starte en auktion på en parcel som allerede er sat til salg. Fjern &apos;til salg&apos; muligheden hvis du ønsker at starte en auktion.
+ </notification>
+ <notification name="OfferTeleport">
+ <form name="form">
+ <input name="message">
+ Mød mig i [REGION]
+ </input>
+ <button name="OK" text="OK"/>
+ <button name="Cancel" text="Annullér"/>
+ </form>
+ </notification>
+ <notification name="RegionEntryAccessBlocked">
+ Du har ikke adgang til denne region på grund af din valgte indholdsrating. Dette kan skyldes manglende validering af din alder.
+
+Undersøg venligst om du har installeret den nyeste [APP_NAME] klient, og gå til &apos;Knowledge Base&apos; for yderligere detaljer om adgang til områder med denne indholdsrating.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+ <notification name="RegionEntryAccessBlocked_KB">
+ Du har ikke adgang til denne region på grund af din valgte indholdsrating.
+
+GÃ¥ til &apos;Knowledge Base&apos; for mere information om indholdsratings.
+ <url name="url">
+ https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=6010
+ </url>
+ <usetemplate
+ name="okcancelignore"
+ yestext="GÃ¥ til &apos;Knowledge Base&apos;"
+ notext="Luk"
+ ignoretext="Når regionen er blokeret på grund af indholdsrating"/>
+ </notification>
+ <notification name="RegionEntryAccessBlocked_Notify">
+ Du har ikke adgang til denne region på grund af din valgte indholdsrating.
+ </notification>
+ <notification name="RegionEntryAccessBlocked_Change">
+ Du har ikke adgang til denne region på grund af din nuværende indholdsrating opsætning.
+
+Du kan vælge &apos;Indstillinger&apos; for at hæve din indholdsrating nu og dermed få adgang. Du vil så få mulighed for at søge og få adgang til områder med indhold af typen [REGIONMATURITY]. Hvis du senere ønsker at skifte tilbage, kan du skifte tilbage i &apos;Indstillinger&apos;.
+ <form name="form">
<button
-
-
- name="Offer"
- text="OK"/>
+ name="OK"
+ text="Ændre præferencer"/>
<button
-
name="Cancel"
- text="Annullér"/>
+ text="Luk"/>
+ <ignore name="ignore" text="Når regionen er blokeret på grund af indholdsrating"/>
</form>
- </notification>
+ </notification>
+ <notification name="LandClaimAccessBlocked">
+ Du kan ikke kræve dette land på grund af din nuværende indholdsrating indstillinge . Dette kan skyldes manglende validering af din alder.
- <notification
-
- name="NotEnoughCurrency"
- >
-[NAME] L$ [PRICE] Du har ikke nok L$ til dette.
- </notification>
+Undersøg om du har den nyeste [APP_NAME] klient og gå venligst til &apos;Knowledge Base&apos; for yderligere detaljer om adgang til områder med denne indholdsrating.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+ <notification name="LandClaimAccessBlocked_KB">
+ Du kan ikke kræve dette land på grund af din nuværende indholdsrating indstilling..
+
+GÃ¥ venligst til &apos;Knowledge Base&apos; for yderligere information om indholdsrating.
+ <url name="url">
+ https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=6010
+ </url>
+ <usetemplate
+ name="okcancelignore"
+ yestext="GÃ¥ til &apos;Knowledge Base&apos;"
+ notext="Luk"
+ ignoretext="Når land ikke kan kræves på grund af indholdsrating"/>
+ </notification>
+ <notification name="LandClaimAccessBlocked_Notify">
+ Du kan ikke kræve dette land på grund af din indholdsrating.
+ </notification>
+ <notification name="LandClaimAccessBlocked_Change">
+ Du kan ikke kræve dette land på grund af din nuværende indholdsrating indstilling..
+
+Du kan vælge &apos;Indstillinger&apos; for at hæve din indholdsrating nu og dermed få adgang. Du vil så få mulighed for at søge og få adgang til områder med indhold af typen [REGIONMATURITY]. Hvis du senere ønsker at skifte tilbage, kan du skifte tilbage i &apos;Indstillinger&apos;.
+ <usetemplate
+ name="okcancelignore"
+ yestext="Ændre præferencer"
+ notext="Luk"
+ ignoretext="Når land ikke kan kræves på grund af indholdsrating"/>
+ </notification>
+ <notification name="LandBuyAccessBlocked">
+ Du kan ikke købe dette land på grund af din nuværende indholdsrating indstillinge . Dette kan skyldes manglende validering af din alder.
+
+Undersøg om du har den nyeste [APP_NAME] klient og gå venligst til &apos;Knowledge Base&apos; for yderligere detaljer om adgang til områder med denne indholdsrating.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+ <notification name="LandBuyAccessBlocked_KB">
+ Du kan ikke købe dette land på grund af din nuværende indholdsrating.
+
+GÃ¥ til &apos;Knowledge Base&apos; for yderligere detaljer om indholdsrating.
+ <url name="url">
+ https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=6010
+ </url>
+ <usetemplate
+ name="okcancelignore"
+ yestext="GÃ¥ til &apos;Knowledge Base&apos;"
+ notext="Luk"
+ ignoretext="Når land ikke kan købes på grund af indholdsrating"/>
+ </notification>
+ <notification name="LandBuyAccessBlocked_Notify">
+ Du kan ikke købe dette land på grund af din nuværende indholdsrating indstilling.
+ </notification>
+ <notification name="LandBuyAccessBlocked_Change">
+ Du kan ikke købe dette land på grund af din valgte inholdsrating.
+
+Du kan vælge &apos;Indstillinger&apos; for at hæve din indholdsrating nu og dermed få adgang. Du vil så få mulighed for at søge og få adgang til områder med indhold af typen [REGIONMATURITY]. Hvis du senere ønsker at skifte tilbage, kan du skifte tilbage i &apos;Indstillinger&apos;.
+ <usetemplate
+ name="okcancelignore"
+ yestext="Ændre præferencer"
+ notext="Luk"
+ ignoretext="Når land ikke kan købes på grund af indholdsrating"/>
+ </notification>
+ <notification name="UnableToLoadNotecardAsset">
+ Kunne ikke hente notecard indhold.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="SetClassifiedMature">
+ Indeholder denne annonce &apos;Mature&apos; indhold?
+ <usetemplate
+ canceltext="Annullér"
+ name="yesnocancelbuttons"
+ notext="Nej"
+ yestext="Ja"/>
+ </notification>
+ <notification name="SetGroupMature">
+ Indeholder denne gruppe &apos;Mature&apos; indhold?
+ <usetemplate
+ canceltext="Annullér"
+ name="yesnocancelbuttons"
+ notext="Nej"
+ yestext="Ja"/>
+ </notification>
+ <notification label="Indholdsrating" name="HelpRegionMaturity">
+ Sætter indholdsrating for regionen, som den vises øverst på menu-bjælken i beboernes klient, og i tooltips på verdenskortet når cursoren placeres over denne region. Denne indstilling har også betydning for adgangen til regionen og for søgeresultater. Andre beboere må kun få adgang til regionen eller se regionen i søgeresultater hvis de har valgt samme eller højere indholdsrating i deres opsætning.
- <notification
-
- name="HelpReportAbuseEmailLL"
- >
-Brug dette værktøj for at rapportere brud på de almindelige bestemmelser og fællesskabs Standarder. Se:
+Det kan tage noget tid inden en ændring af indholdsrating er synligt på kortet.
+ </notification>
+ <notification name="HelpReportAbuseEmailLL">
+ Brug dette værktøj for at rapportere brud på de almindelige bestemmelser og fællesskabs Standarder. Se:
http://secondlife.com/corporate/tos.php
http://secondlife.com/corporate/cs.php
@@ -496,1287 +512,674 @@ http://secondlife.com/corporate/cs.php
Alle rapporterede brud på almindelige bestemmelser og fællesskabs Standarder bliver undersøgt og løst. Du kan følge løsningen på din anmeldselse på:
http://secondlife.com/support/incidentreport.php
- </notification>
-
- <notification
-
- name="HelpReportAbuseContainsCopyright"
- >
-Dear Resident,
+ </notification>
+ <notification name="HelpReportAbuseContainsCopyright">
+ Dear Resident,
Du ser ud til at være ved at rapportere noget vedr. krænkelse af intellektuelle ejendomsrettigheder. Sørg for, at du rapporterer dette korrekt:
-(1) Misbrugs processen. Du kan indsende en misbrugs rapport, hvis du mener, at en Beboer udnytter Second Life&apos;s rettigheds system, for eksempel ved hjælp af en CopyBot eller lignende kopierings værktøjer, at de krænker intellektuelle ejendomsrettigheder. Det team vil undersøge og spørgsmål passende disciplinære sanktioner for adfærd, der overtræder Second Life EF-standarderne eller Servicevilkår. Men det team vil ikke håndtere og vil ikke reagere på anmodninger om at fjerne indhold fra Second Life&apos;s verden.
+(1) Misbrugs processen. Du kan indsende en misbrugs rapport, hvis du mener, at en Beboer udnytter [SECOND_LIFE]&apos;s rettigheds system, for eksempel ved hjælp af en CopyBot eller lignende kopierings værktøjer, at de krænker intellektuelle ejendomsrettigheder. Det team vil undersøge og spørgsmål passende disciplinære sanktioner for adfærd, der overtræder [SECOND_LIFE] EF-standarderne eller Servicevilkår. Men det team vil ikke håndtere og vil ikke reagere på anmodninger om at fjerne indhold fra [SECOND_LIFE]&apos;s verden.
-(2) DMCA eller Indholds fjernelses processen. For at anmode om fjernelse af indhold fra Second Life, skal du sende en gyldig anmeldelse af overtrædelsen som beskrevet i vores DMCA-politik på http://secondlife.com/corporate/dmca.php.
+(2) DMCA eller Indholds fjernelses processen. For at anmode om fjernelse af indhold fra [SECOND_LIFE], skal du sende en gyldig anmeldelse af overtrædelsen som beskrevet i vores DMCA-politik på http://secondlife.com/corporate/dmca.php.
Hvis du stadig ønsker at fortsætte med misbrugs processen, luk da venligst dette vindue og færdiggør indsendelsen af din rapport. Du kan være nødt til at vælge den særlige kategori »CopyBot eller Tilladelses Ydnyttelse.
Mange tak,
Linden Lab
- </notification>
-
- <notification
-
- name="ConfirmClearCookies"
- >
-Er du sikker på du vil slette alle cookies?
- </notification>
-
- <notification
-
- name="ChatterBoxSessionStartError"
- >
-Ikke i stand til at start chat med [RECIPIENT].
+ </notification>
+ <notification name="ConfirmClearCookies">
+ Er du sikker på du vil slette alle cookies?
+ </notification>
+ <notification name="NewSkyPreset">
+ <form name="form">
+ <input name="message">
+ Ny forudindstilling
+ </input>
+ <button name="OK" text="OK"/>
+ <button name="Cancel" text="Annullér"/>
+ </form>
+ </notification>
+ <notification name="NewWaterPreset">
+ <form name="form">
+ <input name="message">
+ Ny forudindstilling
+ </input>
+ <button name="OK" text="OK"/>
+ <button name="Cancel" text="Annullér"/>
+ </form>
+ </notification>
+ <notification name="ChatterBoxSessionStartError">
+ Ikke i stand til at start chat med [RECIPIENT].
[REASON]
- <usetemplate
- name="okbutton"
- yestext="OK"/>
- </notification>
-
- <notification
-
- name="Cannot_Purchase_an_Attachment"
- >
-Ting kan ikke købes imens de er en del af tilbehør.
- </notification>
-
- <notification
-
- name="NewWaterPreset"
- >
- <form name="form">
- <input name="message" type="text">
-Ny forudindstilling
- </input>
- <button
-
-
- name="OK"
- text="OK"/>
- <button
-
- name="Cancel"
- text="Annullér"/>
- </form>
- </notification>
-
- <notification
-
- name="NewSkyPreset"
- >
- <form name="form">
- <input name="message" type="text">
-Ny forudindstilling
- </input>
- <button
-
-
- name="OK"
- text="OK"/>
- <button
-
- name="Cancel"
- text="Annullér"/>
- </form>
- </notification>
-
- <notification
-
- name="OfferTeleport"
- >
- <form name="form">
- <input name="message" type="text">
-Mød mig i [REGION]
- </input>
- <button
-
-
- name="OK"
- text="OK"/>
- <button
-
- name="Cancel"
- text="Annullér"/>
- </form>
- </notification>
-
- <notification
-
- name="SystemMessageTip"
- >
-[MESSAGE]
- </notification>
-
- <notification
-
- name="Cancelled"
- >
-Annulléret
- </notification>
-
- <notification
-
- name="CancelledSit"
- >
-Annulléret sid
- </notification>
-
- <notification
-
- name="CancelledAttach"
- >
-Annulléreret vedhæft
- </notification>
-
- <notification
-
- name="ReplacedMissingWearable"
- >
-Erstattet manglende tøj/kropsdele med standard.
- </notification>
-
- <notification
-
- name="FriendOnline"
- >
-[FIRST] [LAST] er Online
- </notification>
-
- <notification
-
- name="FriendOffline"
- >
-[FIRST] [LAST] er Offline
- </notification>
-
- <notification
-
- name="AddSelfFriend"
- >
-Du kan ikke tilføje dig selv som ven.
- </notification>
-
- <notification
-
- name="UploadingAuctionSnapshot"
- >
-Uploader billeder fra verdenen og www...
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="Cannot_Purchase_an_Attachment">
+ Ting kan ikke købes imens de er en del af tilbehør.
+ </notification>
+ <notification name="SystemMessageTip">
+ [MESSAGE]
+ </notification>
+ <notification name="Cancelled">
+ Annulléret
+ </notification>
+ <notification name="CancelledSit">
+ Annulléret sid
+ </notification>
+ <notification name="CancelledAttach">
+ Annulléreret vedhæft
+ </notification>
+ <notification name="ReplacedMissingWearable">
+ Erstattet manglende tøj/kropsdele med standard.
+ </notification>
+ <notification name="FriendOnline">
+ [FIRST] [LAST] er Online
+ </notification>
+ <notification name="FriendOffline">
+ [FIRST] [LAST] er Offline
+ </notification>
+ <notification name="AddSelfFriend">
+ Du kan ikke tilføje dig selv som ven.
+ </notification>
+ <notification name="UploadingAuctionSnapshot">
+ Uploader billeder fra verdenen og www...
(Tager omkring 5 minutter.)
- </notification>
-
- <notification
-
- name="UploadPayment"
- >
-Du betalte L$[AMOUNT] for at uploade.
- </notification>
-
- <notification
-
- name="UploadWebSnapshotDone"
- >
-Billeder fra www er uploadet.
- </notification>
-
- <notification
-
- name="UploadSnapshotDone"
- >
-Billeder fra verdenen er uploadet
- </notification>
-
- <notification
-
- name="TerrainDownloaded"
- >
-Terrain.raw downloadet
- </notification>
-
- <notification
-
- name="GestureMissing"
- >
-Gestus [NAME] mangler i databasen.
- </notification>
-
- <notification
-
- name="UnableToLoadGesture"
- >
-Ikke muligt at indlæse gestus [NAME].
+ </notification>
+ <notification name="UploadPayment">
+ Du betalte L$[AMOUNT] for at uploade.
+ </notification>
+ <notification name="UploadWebSnapshotDone">
+ Billeder fra www er uploadet.
+ </notification>
+ <notification name="UploadSnapshotDone">
+ Billeder fra verdenen er uploadet
+ </notification>
+ <notification name="TerrainDownloaded">
+ Terrain.raw downloadet
+ </notification>
+ <notification name="GestureMissing">
+ Gestus [NAME] mangler i databasen.
+ </notification>
+ <notification name="UnableToLoadGesture">
+ Ikke muligt at indlæse gestus [NAME].
Prøv venligst igen.
- </notification>
-
- <notification
-
- name="LandmarkMissing"
- >
-Landmærke mangler i databasen.
- </notification>
-
- <notification
-
- name="UnableToLoadLandmark"
- >
-Ikke muligt at indlæse landmærke. Prøv venligst igen.
- </notification>
-
- <notification
-
- name="CapsKeyOn"
- >
-Du har slået store bogstaver til.
+ </notification>
+ <notification name="LandmarkMissing">
+ Landmærke mangler i databasen.
+ </notification>
+ <notification name="UnableToLoadLandmark">
+ Ikke muligt at indlæse landmærke. Prøv venligst igen.
+ </notification>
+ <notification name="CapsKeyOn">
+ Du har slået store bogstaver til.
Da det vil have betydning når du indtaster kodeordet, vil du højest sandsynlig slå dem fra.
- </notification>
-
- <notification
-
- name="NotecardMissing"
- >
-Note mangler i databasen.
- </notification>
-
- <notification
-
- name="NotecardNoPermissions"
- >
-Utilstrækkelige tilladelser til at se note.
- </notification>
-
- <notification
-
- name="RezItemNoPermissions"
- >
-Utilstrækkelige tilladelser til at danne genstanden.
- </notification>
-
- <notification
-
- name="UnableToLoadNotecard"
- >
-Ikke muligt at indlæse note.
+ </notification>
+ <notification name="NotecardMissing">
+ Note mangler i databasen.
+ </notification>
+ <notification name="NotecardNoPermissions">
+ Utilstrækkelige tilladelser til at se note.
+ </notification>
+ <notification name="RezItemNoPermissions">
+ Utilstrækkelige tilladelser til at danne genstanden.
+ </notification>
+ <notification name="UnableToLoadNotecard">
+ Ikke muligt at indlæse note.
Prøv venligst igen.
- </notification>
-
- <notification
-
- name="ScriptMissing"
- >
-Script mangler i databasen.
- </notification>
-
- <notification
-
- name="ScriptNoPermissions"
- >
-Utilstrækkelige tilladelser til at se script.
- </notification>
-
- <notification
-
- name="UnableToLoadScript"
- >
-Ikke muligt at indlæse script. Prøv venligst igen.
- </notification>
-
- <notification
-
- name="IncompleteInventory"
- >
-Det komplette indhold, du tilbyder, er ikke endnu tilgængelig lokalt. Prøv venligst at tilbyde tingene igen om lidt.
- </notification>
-
- <notification
-
- name="CannotModifyProtectedCategories"
- >
-Du kan ikke ændre beskyttede kategorier.
- </notification>
-
- <notification
-
- name="CannotRemoveProtectedCategories"
- >
-Du kan ikke fjerne beskyttede kategorier.
- </notification>
-
- <notification
-
- name="OfferedCard"
- >
-Du har tilbudt et visitkort til [FIRST] [LAST]
- </notification>
-
- <notification
-
- name="OfferedFriendship"
- >
-Du har tilbudt venskab til [FIRST] [LAST]
- </notification>
-
- <notification
-
- name="UnableToBuyWhileDownloading"
- >
-Ikke muligt at købe, imens genstandens data hentes.
+ </notification>
+ <notification name="ScriptMissing">
+ Script mangler i databasen.
+ </notification>
+ <notification name="ScriptNoPermissions">
+ Utilstrækkelige tilladelser til at se script.
+ </notification>
+ <notification name="UnableToLoadScript">
+ Ikke muligt at indlæse script. Prøv venligst igen.
+ </notification>
+ <notification name="IncompleteInventory">
+ Det komplette indhold, du tilbyder, er ikke endnu tilgængelig lokalt. Prøv venligst at tilbyde tingene igen om lidt.
+ </notification>
+ <notification name="CannotModifyProtectedCategories">
+ Du kan ikke ændre beskyttede kategorier.
+ </notification>
+ <notification name="CannotRemoveProtectedCategories">
+ Du kan ikke fjerne beskyttede kategorier.
+ </notification>
+ <notification name="OfferedCard">
+ Du har tilbudt et visitkort til [FIRST] [LAST]
+ </notification>
+ <notification name="UnableToBuyWhileDownloading">
+ Ikke muligt at købe, imens genstandens data hentes.
Prøv venligst igen.
- </notification>
-
- <notification
-
- name="UnableToLinkWhileDownloading"
- >
-Ikke muligt at lænke imens genstandens data hentes.
+ </notification>
+ <notification name="UnableToLinkWhileDownloading">
+ Ikke muligt at lænke imens genstandens data hentes.
Prøv venligst igen.
- </notification>
-
- <notification
-
- name="CannotBuyObjectsFromDifferentOwners"
- >
-Kan ikke købe genstande fra forskellige ejere på samme tid.
+ </notification>
+ <notification name="CannotBuyObjectsFromDifferentOwners">
+ Kan ikke købe genstande fra forskellige ejere på samme tid.
Prøv venligst at vælge en enkelt genstand.
- </notification>
-
- <notification
-
- name="ObjectNotForSale"
- >
-Genstanden ser ikke ud til at være til salg.
- </notification>
-
- <notification
-
- name="EnteringGodMode"
- >
-Starter gud-tilstand, niveau [LEVEL]
- </notification>
-
- <notification
-
- name="LeavingGodMode"
- >
-Stopper gud-tilstand, niveau [LEVEL]
- </notification>
-
- <notification
-
- name="CopyFailed"
- >
-Kopiering lykkedes ikke fordi du ikke har nok tilladelser til at kopiere
- </notification>
-
- <notification
-
- name="InventoryAccepted"
- >
-[NAME] accepterede det du tilbød fra din beholdning.
- </notification>
-
- <notification
-
- name="InventoryDeclined"
- >
-[NAME] afviste det du tilbød fra din beholdning.
- </notification>
-
- <notification
-
- name="ObjectMessage"
- >
-[NAME]: [MESSAGE]
- </notification>
-
- <notification
-
- name="CallingCardAccepted"
- >
-Dit visitkort blev accepteret.
- </notification>
-
- <notification
-
- name="CallingCardDeclined"
- >
-Dit visitkort blev afvist.
- </notification>
-
- <notification
-
- name="TeleportToLandmark"
- >
-Nu hvor du er nået frem til hovedlandet, kan du teleportere til steder som &apos;[NAME]&apos; ved at klikke på Beholdning-knappen i nederste højre side af skærmen hvorefter du vælger Landmærke-mappen.
+ </notification>
+ <notification name="ObjectNotForSale">
+ Genstanden ser ikke ud til at være til salg.
+ </notification>
+ <notification name="EnteringGodMode">
+ Starter gud-tilstand, niveau [LEVEL]
+ </notification>
+ <notification name="LeavingGodMode">
+ Stopper gud-tilstand, niveau [LEVEL]
+ </notification>
+ <notification name="CopyFailed">
+ Kopiering lykkedes ikke fordi du ikke har nok tilladelser til at kopiere
+ </notification>
+ <notification name="InventoryAccepted">
+ [NAME] accepterede det du tilbød fra din beholdning.
+ </notification>
+ <notification name="InventoryDeclined">
+ [NAME] afviste det du tilbød fra din beholdning.
+ </notification>
+ <notification name="ObjectMessage">
+ [NAME]: [MESSAGE]
+ </notification>
+ <notification name="CallingCardAccepted">
+ Dit visitkort blev accepteret.
+ </notification>
+ <notification name="CallingCardDeclined">
+ Dit visitkort blev afvist.
+ </notification>
+ <notification name="TeleportToLandmark">
+ Nu hvor du er nået frem til hovedlandet, kan du teleportere til steder som &apos;[NAME]&apos; ved at klikke på Beholdning-knappen i nederste højre side af skærmen hvorefter du vælger Landmærke-mappen.
Dobbeltklik på landmærket og klik på Teleportér, for at rejse derhen.
- </notification>
-
- <notification
-
- name="TeleportToPerson"
- >
-Nu hvor du har nået frem til hovedlandet, kan du kontakte indbyggere som &apos;[NAME]&apos; ved at klikke på Beholdning-knappen i nederste højre side af skærmen, hvorefter du vælger Visitkort-mappen.
+ </notification>
+ <notification name="TeleportToPerson">
+ Nu hvor du har nået frem til hovedlandet, kan du kontakte indbyggere som &apos;[NAME]&apos; ved at klikke på Beholdning-knappen i nederste højre side af skærmen, hvorefter du vælger Visitkort-mappen.
Dobbeltklik på kortet, klik på IM og skriv beskeden.
- </notification>
-
- <notification
-
- name="CantSelectLandFromMultipleRegions"
- >
-Kan ikke vælge land på tværs af grænser.
+ </notification>
+ <notification name="CantSelectLandFromMultipleRegions">
+ Kan ikke vælge land på tværs af grænser.
Prøv at vælge mindre stykker land.
- </notification>
-
- <notification
-
- name="GroupVote"
- >
-[NAME] har forslået at stemme for:
+ </notification>
+ <notification name="SearchWordBanned">
+ Visse ord er fjernet fra din søge-sætning på grund af at disse strider mod de generelle &apos;Community Standards&apos;.
+ </notification>
+ <notification name="NoContentToSearch">
+ Vælg venligst mindst en indholdstype for at søge (PG, Mature, or Adult).
+ </notification>
+ <notification name="GroupVote">
+ [NAME] har forslået at stemme for:
[MESSAGE]
- <form name="form">
- <button
-
- name="VoteNow"
- text="Stem nu"/>
- <button
-
- name="Later"
- text="Senere"/>
- </form>
- </notification>
-
- <notification
-
- name="SystemMessage"
- >
-[MESSAGE]
- </notification>
-
- <notification
-
- name="EventNotification"
- >
-Besked om begivenhed:
+ <form name="form">
+ <button name="VoteNow" text="Stem nu"/>
+ <button name="Later" text="Senere"/>
+ </form>
+ </notification>
+ <notification name="SystemMessage">
+ [MESSAGE]
+ </notification>
+ <notification name="EventNotification">
+ Besked om begivenhed:
[NAME]
[DATE]
- <form name="form">
- <button
-
- name="Teleport"
- text="Teleportér"/>
- <button
-
- name="Description"
- text="Beskrivelse"/>
- <button
-
- name="Cancel"
- text="Annullér"/>
- </form>
- </notification>
-
- <notification
-
- name="TransferObjectsHighlighted"
- >
-Alle genstande på denne grund, som vil blive overført til køberen af denne grund, er nu oplyst.
+ <form name="form">
+ <button name="Teleport" text="Teleportér"/>
+ <button name="Description" text="Beskrivelse"/>
+ <button name="Cancel" text="Annullér"/>
+ </form>
+ </notification>
+ <notification name="TransferObjectsHighlighted">
+ Alle genstande på denne grund, som vil blive overført til køberen af denne grund, er nu oplyst.
* Træer og græs, der vil blive overført, er ikke fremhævet.
- <form name="form">
- <button
-
- name="Done"
- text="Færdig"/>
- </form>
- </notification>
-
- <notification
-
- name="DeactivatedGesturesTrigger"
- >
-Deaktiverede bevægelser med samme udløser: [NAMES]
- </notification>
-
- <notification
-
- name="NoQuickTime"
- >
-Apple&apos;s QuickTime ser ikke ud til at være installeret på computeren.
+ <form name="form">
+ <button name="Done" text="Færdig"/>
+ </form>
+ </notification>
+ <notification name="DeactivatedGesturesTrigger">
+ Deaktiverede bevægelser med samme udløser: [NAMES]
+ </notification>
+ <notification name="NoQuickTime">
+ Apple&apos;s QuickTime ser ikke ud til at være installeret på computeren.
Hvis du vil se live transmitteret medie på grunde, der understøtter det, skal du gå ind på QuickTime-siden (http://www.apple.dk/quicktime) og installere QuickTime afspilleren.
- </notification>
-
- <notification
-
- name="OwnedObjectsReturned"
- >
-De genstande du ejer på det valgte stykke land er blevet returneret til din beholdning.
- </notification>
-
- <notification
-
- name="OtherObjectsReturned"
- >
-Genstandene på det valgte stykke land der er ejet af [FIRST] [LAST] er blevet returneret til hans eller hendes beholdning.
- </notification>
-
- <notification
-
- name="OtherObjectsReturned2"
- >
-Genstandene på det valgte stykke land der er ejet af beboeren &apos;[NAME]&apos; er blevet returneret til deres ejere.
- </notification>
-
- <notification
-
- name="GroupObjectsReturned"
- >
-Genstandene på det valgte stykke land, delt med gruppen [GROUPNAME], er blevet returneret til deres ejeres beholdninger.
+ </notification>
+ <notification name="OwnedObjectsReturned">
+ De genstande du ejer på det valgte stykke land er blevet returneret til din beholdning.
+ </notification>
+ <notification name="OtherObjectsReturned">
+ Genstandene på det valgte stykke land der er ejet af [FIRST] [LAST] er blevet returneret til hans eller hendes beholdning.
+ </notification>
+ <notification name="OtherObjectsReturned2">
+ Genstandene på det valgte stykke land der er ejet af beboeren &apos;[NAME]&apos; er blevet returneret til deres ejere.
+ </notification>
+ <notification name="GroupObjectsReturned">
+ Genstandene på det valgte stykke land, delt med gruppen [GROUPNAME], er blevet returneret til deres ejeres beholdninger.
Genstande, som er dedikerede og som kan overføres, er blevet returneret til deres forrige ejere.
Genstande, der ikke kan overføres og som er dedikeret til gruppen, er blevet slettet.
- </notification>
-
- <notification
-
- name="UnOwnedObjectsReturned"
- >
-Genstandene på det valgte stykke land, der IKKE er ejet af dig, er blevet returneret til deres ejere.
- </notification>
-
- <notification
-
- name="NotSafe"
- >
-Dette land har sat skade til (&apos;ikke sikker&apos;).
+ </notification>
+ <notification name="UnOwnedObjectsReturned">
+ Genstandene på det valgte stykke land, der IKKE er ejet af dig, er blevet returneret til deres ejere.
+ </notification>
+ <notification name="NotSafe">
+ Dette land har sat skade til (&apos;ikke sikker&apos;).
Du kan komme til skade her. Hvis du dør, vil du blive teleporteret til din hjem-lokalitet.
- </notification>
-
- <notification
-
- name="NoFly"
- >
-Dette land har slået flyvning fra (&apos;ingen flyvning&apos;).
+ </notification>
+ <notification name="NoFly">
+ Dette land har slået flyvning fra (&apos;ingen flyvning&apos;).
Du kan ikke flyve her.
- </notification>
-
- <notification
-
- name="PushRestricted"
- >
-Dette land giver ikke mulighed for at &apos;skubbe&apos; andre, med mindre du ejer landet.
- </notification>
-
- <notification
-
- name="NoVoice"
- >
-Dette land har ikke mulighed for at bruge stemme.
- </notification>
-
- <notification
-
- name="NoBuild"
- >
-Dette land giver ikke mulighed for at bygge (&apos;byggeri forbudt&apos;).
+ </notification>
+ <notification name="PushRestricted">
+ Dette land giver ikke mulighed for at &apos;skubbe&apos; andre, med mindre du ejer landet.
+ </notification>
+ <notification name="NoVoice">
+ Dette land har ikke mulighed for at bruge stemme.
+ </notification>
+ <notification name="NoBuild">
+ Dette land giver ikke mulighed for at bygge (&apos;byggeri forbudt&apos;).
Du kan ikke skabe genstande her.
- </notification>
-
- <notification
-
- name="ScriptsStopped"
- >
-En administrator har midlertidig stoppet scripts i denne region.
- </notification>
-
- <notification
-
- name="ScriptsNotRunning"
- >
-Denne region kører ikke nogen scripts.
- </notification>
-
- <notification
-
- name="NoOutsideScripts"
- >
-Dette land har eksterne scripts slået fra
+ </notification>
+ <notification name="ScriptsStopped">
+ En administrator har midlertidig stoppet scripts i denne region.
+ </notification>
+ <notification name="ScriptsNotRunning">
+ Denne region kører ikke nogen scripts.
+ </notification>
+ <notification name="NoOutsideScripts">
+ Dette land har eksterne scripts slået fra
(&apos;ingen eksterne scripts&apos;).
Ingen scripts vil køre på nær dem, som tilhører ejeren af landet.
- </notification>
-
- <notification
-
- name="ClaimPublicLand"
- >
-Du kan kun gøre krav på offentlig land i den region, du befinder dig i.
- </notification>
-
- <notification
-
- name="ObjectGiveItem"
- >
-En genstand med navnet [OBJECTFROMNAME], ejet af [FIRST] [LAST], har givet dig en/et [OBJECTTYPE] med navnet [OBJECTNAME].
- <form name="form">
- <button
-
- name="Keep"
- text="Behold"/>
- <button
-
- name="Discard"
- text="Smid væk"/>
- <button
-
- name="Mute"
- text="Blokér"/>
- </form>
- </notification>
-
- <notification
-
- name="ObjectGiveItemUnknownUser"
- >
-En genstand med navnet [OBJECTFROMNAME], ejet af (en ukendt bruger), har givet dig en/et [OBJECTTYPE] med navnet [OBJECTNAME].
- <form name="form">
- <button
-
- name="Keep"
- text="Behold"/>
- <button
-
- name="Discard"
- text="Smid væk"/>
- <button
-
- name="Mute"
- text="Blokér"/>
- </form>
- </notification>
-
- <notification
-
- name="UserGiveItem"
- >
-[NAME] har givet dig en/et [OBJECTTYPE] med navnet &apos;[OBJECTNAME]&apos;.
- <form name="form">
- <button
-
- name="Keep"
- text="Behold"/>
- <button
-
- name="Discard"
- text="Smid væk"/>
- <button
-
- name="Mute"
- text="Blokér"/>
- </form>
- </notification>
-
- <notification
-
- name="GodMessage"
- >
-[NAME]
+ </notification>
+ <notification name="ClaimPublicLand">
+ Du kan kun gøre krav på offentlig land i den region, du befinder dig i.
+ </notification>
+ <notification name="RegionTPAccessBlocked">
+ Du har ikke adgang til denne region på grund af din valgte indholdsrating. Dette kan skyldes manglende validering af din alder eller at du ikke benytter den nyeste [APP_NAME] klient.
+
+Gå venligst til &apos;Knowledge Base&apos; for yderligere detaljer om adgang til områder med denne indholdsrating.
+ </notification>
+ <notification name="URBannedFromRegion">
+ Du er blokeret i denne region.
+ </notification>
+ <notification name="NoTeenGridAccess">
+ Du kan ikke tilslutte dig denne &apos;Teen&apos; region.
+ </notification>
+ <notification name="NoHelpIslandTP">
+ Du kan ikke teleportere tilbage til Help Island.
+Gå til &apos;Help Island Puclic&apos; for at prøve tutorial igen.
+ </notification>
+ <notification name="ImproperPaymentStatus">
+ Du har ikke de rette betalingsoplysninger til at komme ind i denne region.
+ </notification>
+ <notification name="MustGetAgeRegion">
+ Du skal være aldersgodkendt for at komme ind i denne region.
+ </notification>
+ <notification name="MustGetAgeParcel">
+ Du skal være aldersgodkendt for at komme ind på denne parcel.
+ </notification>
+ <notification name="NoDestRegion">
+ Destinations region ikke fundet.
+ </notification>
+ <notification name="NotAllowedInDest">
+ Du har ikke adgang til denne destination.
+ </notification>
+ <notification name="RegionParcelBan">
+ Kan ikke skifte til ny region via en blokeret parcel. Prøv en anden vej ind.
+ </notification>
+ <notification name="TelehubRedirect">
+ Du er blevet omdirigeret til en telehub.
+ </notification>
+ <notification name="CouldntTPCloser">
+ Kunne ikke teleportere nærmere til destination.
+ </notification>
+ <notification name="TPCancelled">
+ Teleport afbrudt.
+ </notification>
+ <notification name="FullRegionTryAgain">
+ Den region du prøver at komme ind i er fuld for øjeblikket.
+Prøv igen om lidt.
+ </notification>
+ <notification name="GeneralFailure">
+ Generel fejl.
+ </notification>
+ <notification name="RoutedWrongRegion">
+ Du blev sendt til en forkert region. Prøv igen.
+ </notification>
+ <notification name="NoValidAgentID">
+ Ikke en gyldig agent ID.
+ </notification>
+ <notification name="NoValidSession">
+ Ikke noget gyldig sessions-ID
+ </notification>
+ <notification name="NoValidCircuit">
+ Ingen gyldig kode for kredsløb.
+ </notification>
+ <notification name="NoValidTimestamp">
+ Ikke et gyldigt klokkeslæt.
+ </notification>
+ <notification name="NoPendingConnection">
+ Kunne ikke skabe fast forbindelse.
+ </notification>
+ <notification name="InternalUsherError">
+ Der opstod en intern fejl ved teleportering til din teleport destination.. Der kan være generelle problemer med [SECOND_LIFE] lige nu.
+ </notification>
+ <notification name="NoGoodTPDestination">
+ Kunne ikke finde et egnet teleport sted i denne region.
+ </notification>
+ <notification name="InternalErrorRegionResolver">
+ Der opstod en intern fejl ved beregning af globale koordinater for din teleport forespørgsel. Der kan være generelle problemer med [SECOND_LIFE] lige nu.
+ </notification>
+ <notification name="NoValidLanding">
+ Kunne ikke finde et gyldigt landingspunkt.
+ </notification>
+ <notification name="NoValidParcel">
+ No valid parcel could be found.
+ </notification>
+ <notification name="ObjectGiveItem">
+ En genstand med navnet [OBJECTFROMNAME], ejet af [FIRST] [LAST], har givet dig en/et [OBJECTTYPE] med navnet [OBJECTNAME].
+ <form name="form">
+ <button name="Keep" text="Behold"/>
+ <button name="Discard" text="Smid væk"/>
+ <button name="Mute" text="Blokér"/>
+ </form>
+ </notification>
+ <notification name="ObjectGiveItemUnknownUser">
+ En genstand med navnet [OBJECTFROMNAME], ejet af (en ukendt bruger), har givet dig en/et [OBJECTTYPE] med navnet [OBJECTNAME].
+ <form name="form">
+ <button name="Keep" text="Behold"/>
+ <button name="Discard" text="Smid væk"/>
+ <button name="Mute" text="Blokér"/>
+ </form>
+ </notification>
+ <notification name="UserGiveItem">
+ [NAME] har givet dig en/et [OBJECTTYPE] med navnet &apos;[OBJECTNAME]&apos;.
+ <form name="form">
+ <button name="Keep" text="Behold"/>
+ <button name="Discard" text="Smid væk"/>
+ <button name="Mute" text="Blokér"/>
+ </form>
+ </notification>
+ <notification name="GodMessage">
+ [NAME]
[MESSAGE]
- </notification>
+ </notification>
+ <notification name="JoinGroup">
+ [MESSAGE]
+ <form name="form">
+ <button name="Join" text="Indmeld"/>
+ <button name="Decline" text="Afvis"/>
+ <button name="Info" text="Information"/>
+ </form>
+ </notification>
+ <notification name="TeleportOffered">
+ [NAME] har tilbudt at teleportere dig til hans eller hendes lokalitet:
- <notification
-
- name="JoinGroup"
- >
-[MESSAGE]
- <form name="form">
- <button
-
- name="Join"
- text="Indmeld"/>
- <button
-
- name="Decline"
- text="Afvis"/>
- <button
-
- name="Info"
- text="Information"/>
- </form>
- </notification>
-
- <notification
-
- name="TeleportOffered"
- >
-[NAME] har tilbudt at teleportere dig til hans eller hendes lokalitet:
-
-[MESSAGE]
- <form name="form">
- <button
-
- name="Teleport"
- text="Teleportér"/>
- <button
-
- name="Cancel"
- text="Annullér"/>
- </form>
- </notification>
-
- <notification
-
- name="GotoURL"
- >
[MESSAGE]
+ <form name="form">
+ <button name="Teleport" text="Teleportér"/>
+ <button name="Cancel" text="Annullér"/>
+ </form>
+ </notification>
+ <notification name="GotoURL">
+ [MESSAGE]
[URL]
- <form name="form">
- <button
-
- name="Later"
- text="Senere"/>
- <button
-
- name="GoNow..."
- text="GÃ¥ nu..."/>
- </form>
- </notification>
-
- <notification
-
- name="OfferFriendship"
- >
-[NAME] tilbyder venskab.
+ <form name="form">
+ <button name="Later" text="Senere"/>
+ <button name="GoNow..." text="GÃ¥ nu..."/>
+ </form>
+ </notification>
+ <notification name="OfferFriendship">
+ [NAME] tilbyder venskab.
Som standard vil du kunne se andres onlinestatus.
- <form name="form">
- <button
-
- name="Accept"
- text="Acceptér"/>
- <button
-
- name="Decline"
- text="Afvis"/>
- </form>
- </notification>
-
- <notification
-
- name="FriendshipAccepted"
- >
-[NAME] accepterede dit tilbud om venskab.
- </notification>
-
- <notification
-
- name="FriendshipDeclined"
- >
-[NAME] afviste dit tilbud om venskab.
- </notification>
-
- <notification
-
- name="OfferCallingCard"
- >
-[FIRST] [LAST] tilbyder vedkommendes visitkort.
+ <form name="form">
+ <button name="Accept" text="Acceptér"/>
+ <button name="Decline" text="Afvis"/>
+ </form>
+ </notification>
+ <notification name="FriendshipAccepted">
+ [NAME] accepterede dit tilbud om venskab.
+ </notification>
+ <notification name="FriendshipDeclined">
+ [NAME] afviste dit tilbud om venskab.
+ </notification>
+ <notification name="OfferCallingCard">
+ [FIRST] [LAST] tilbyder vedkommendes visitkort.
Dette vil tilføje et bogmærke i din beholdning, så du hurtigt kan sende en personlig besked (IM) til denne beboer.
- <form name="form">
- <button
-
- name="Accept"
- text="Acceptér"/>
- <button
-
- name="Decline"
- text="Afvis"/>
- </form>
- </notification>
-
- <notification
-
- name="RegionRestartMinutes"
-
-
- >
-Regionen genstarter om [MINUTES] minutter.
+ <form name="form">
+ <button name="Accept" text="Acceptér"/>
+ <button name="Decline" text="Afvis"/>
+ </form>
+ </notification>
+ <notification name="RegionRestartMinutes">
+ Regionen genstarter om [MINUTES] minutter.
Hvis du bliver i denne region, vil du blive logget af.
- </notification>
-
- <notification
-
- name="RegionRestartSeconds"
-
-
- >
-Regionen genstarter om [SECONDS] sekunder.
+ </notification>
+ <notification name="RegionRestartSeconds">
+ Regionen genstarter om [SECONDS] sekunder.
Hvis du bliver i denne region, vil du blive logget af.
- </notification>
-
- <notification
-
- name="LoadWebPage"
- >
-Indlæs internetside [URL]?
+ </notification>
+ <notification name="LoadWebPage">
+ Indlæs internetside [URL]?
[MESSAGE]
Fra genstand: [OBJECTNAME], ejer: [NAME]?
- <form name="form">
- <button
-
- name="Gotopage"
- text="GÃ¥ til side"/>
- <button
-
- name="Cancel"
- text="Afbryd"/>
- </form>
- </notification>
-
- <notification
-
- name="FailedToFindWearableUnnamed"
- >
-Det lykkedes ikke at finde [TYPE] i databasen.
- </notification>
-
- <notification
-
- name="FailedToFindWearable"
- >
-Det lykkedes ikke at finde [TYPE] med navnet [DESC] i databasen.
- </notification>
-
- <notification
-
- name="ScriptQuestion"
- >
-&apos;[OBJECTNAME]&apos;, en genstand, ejet af &apos;[NAME]&apos;, vil gerne:
+ <form name="form">
+ <button name="Gotopage" text="GÃ¥ til side"/>
+ <button name="Cancel" text="Afbryd"/>
+ </form>
+ </notification>
+ <notification name="FailedToFindWearableUnnamed">
+ Det lykkedes ikke at finde [TYPE] i databasen.
+ </notification>
+ <notification name="FailedToFindWearable">
+ Det lykkedes ikke at finde [TYPE] med navnet [DESC] i databasen.
+ </notification>
+ <notification name="InvalidWearable">
+ Den genstand du prøver at tage på benytter funktioner som din klient ikke kan forstå. Opdatér din version af [APP_NAME] for at tage genstanden på.
+ </notification>
+ <notification name="ScriptQuestion">
+ &apos;[OBJECTNAME]&apos;, en genstand, ejet af &apos;[NAME]&apos;, vil gerne:
[QUESTIONS]
Er det iorden?
- <form name="form">
- <button
-
- name="Yes"
- text="Ja"/>
- <button
-
- name="No"
- text="Nej"/>
- <button
-
- name="Mute"
- text="Blokér"/>
- </form>
- </notification>
-
- <notification
-
- name="ScriptQuestionCaution"
- >
-&apos;[OBJECTNAME]&apos;, en genstand, ejet af &apos;[NAME]&apos;, vil gerne:
+ <form name="form">
+ <button name="Yes" text="Ja"/>
+ <button name="No" text="Nej"/>
+ <button name="Mute" text="Blokér"/>
+ </form>
+ </notification>
+ <notification name="ScriptQuestionCaution">
+ &apos;[OBJECTNAME]&apos;, en genstand, ejet af &apos;[NAME]&apos;, vil gerne:
[QUESTIONS]
Hvis du ikke har tillid til denne genstand og dens skaber, bør du afvise denne forespørgsel. For yderligere information klik på Detaljer-knappen.
Imødekom denne forespørgsel?
- <form name="form">
- <button
-
- name="Grant"
- text="Imødekom"/>
- <button
-
- name="Deny"
- text="Afvis"/>
- <button
-
- name="Details"
- text="Detaljer..."/>
- </form>
- </notification>
-
- <notification
-
- name="ScriptDialog"
- >
-[FIRST] [LAST]&apos;s &apos;[TITLE]&apos;
+ <form name="form">
+ <button name="Grant" text="Imødekom"/>
+ <button name="Deny" text="Afvis"/>
+ <button name="Details" text="Detaljer..."/>
+ </form>
+ </notification>
+ <notification name="ScriptDialog">
+ [FIRST] [LAST]&apos;s &apos;[TITLE]&apos;
[MESSAGE]
- <form name="form">
- <button
-
- name="Ignore"
- text="Ignorér"/>
- </form>
- </notification>
-
- <notification
-
- name="ScriptDialogGroup"
- >
-[GROUPNAME]&apos;s &apos;[TITLE]&apos;
+ <form name="form">
+ <button name="Ignore" text="Ignorér"/>
+ </form>
+ </notification>
+ <notification name="ScriptDialogGroup">
+ [GROUPNAME]&apos;s &apos;[TITLE]&apos;
[MESSAGE]
- <form name="form">
- <button
-
- name="Ignore"
- text="Ignorér"/>
- </form>
- </notification>
-
- <notification
-
- name="FirstBalanceIncrease"
- >
-Du har lige modtaget L$[AMOUNT].
+ <form name="form">
+ <button name="Ignore" text="Ignorér"/>
+ </form>
+ </notification>
+ <notification name="FirstBalanceIncrease">
+ Du har lige modtaget L$[AMOUNT].
Genstande og andre brugere kan give dig L$.
Din saldo er vist i øverste højre hjørne af skærmen.
- </notification>
-
- <notification
-
- name="FirstBalanceDecrease"
- >
-Du har lige modtaget L$[AMOUNT].
+ </notification>
+ <notification name="FirstBalanceDecrease">
+ Du har lige modtaget L$[AMOUNT].
Din saldo er vist i øverste højre hjørne af skærmen.
- </notification>
-
- <notification
-
- name="FirstSit"
- >
-Du sidder.
+ </notification>
+ <notification name="FirstSit">
+ Du sidder.
Brug piletasterne (eller AWSD) for at ændre hvilken vej du ser.
Klik på &apos;Stå op&apos;-knappen for at rejse dig op.
- </notification>
-
- <notification
-
- name="FirstMap"
- >
-Klik og træk for at flytte kortvisningen.
+ </notification>
+ <notification name="FirstMap">
+ Klik og træk for at flytte kortvisningen.
Dobbelt-klik for at teleportere.
Brug kontrollerne til højre for at finde ting og se forskellige baggrunde.
- </notification>
-
- <notification
-
- name="FirstBuild"
- >
-Du kan bygge nye genstande i nogle områder af [SECOND_LIFE].
+ </notification>
+ <notification name="FirstBuild">
+ Du kan bygge nye genstande i nogle områder af [SECOND_LIFE].
Brug værktøjet øverst til venstre for at bygge, og prøv at holde Ctrl eller Alt nede for hurtigt at skifte imellem værktøjerne.
Tryk Esc for at stoppe med at bygge.
- </notification>
-
- <notification
-
- name="FirstLeftClickNoHit"
- >
-Venstre-klik interagerer med specielle genstande.
+ </notification>
+ <notification name="FirstLeftClickNoHit">
+ Venstre-klik interagerer med specielle genstande.
Hvis musemarkøren ændrer sig til en hånd, kan du interagere med genstanden.
Højre-klik viser altid en menu med ting du kan gøre.
- </notification>
-
- <notification
-
- name="FirstTeleport"
- >
-Du har lige teleporteret.
+ </notification>
+ <notification name="FirstTeleport">
+ Du har lige teleporteret.
Du er ved info-standen nærmest ved din destination.
Din destination er markeret med en stor rød lyskegle.
- </notification>
-
- <notification
-
- name="FirstOverrideKeys"
- >
-Dine bevælgelsestaster bliver nu håndteret af et objekt.
+ </notification>
+ <notification name="FirstOverrideKeys">
+ Dine bevælgelsestaster bliver nu håndteret af et objekt.
Brug piletasterne eller AWSD for at se, hvad de gør.
Nogle genstande (som skydevåben) kræver at du går ind i musevisning for at bruge dem.
Tryk på &apos;M&apos; for at gåre det.
- </notification>
-
- <notification
-
- name="FirstAppearance"
- >
-Du tilretter dit udseende.
+ </notification>
+ <notification name="FirstAppearance">
+ Du tilretter dit udseende.
For at rotere og zoome brug piletasterne.
Når du er færdig, tryk på &apos;Gem alt&apos; for at gemme dit udseende og lukke.
Du kan rette dit udseende så tit du vil.
- </notification>
-
- <notification
-
- name="FirstInventory"
- >
-Dette er din beholdning, der indeholder objekter, noter, tøj og andre ting du ejer.
+ </notification>
+ <notification name="FirstInventory">
+ Dette er din beholdning, der indeholder objekter, noter, tøj og andre ting du ejer.
* For at bære et objekt eller en mappe med tøj, træk den over på dig selv.
* For at få et objekt frem i verdenen, træk den ud på jorden.
* For at læse en note, dobbeltklik på den.
- </notification>
-
- <notification
-
- name="FirstSandbox"
- >
-Dette er sandkasseområdet.
+ </notification>
+ <notification name="FirstSandbox">
+ Dette er sandkasseområdet.
Genstande, der er skabt her, vil blive slettet efter du har forladt området. Sandkasser renses jævnligt. Se venligst informationen øverst på skærmen, lige ved siden af områdenavnet.
Sandkasseområder er ikke almindelige. De er mærket med skilte.
- </notification>
-
- <notification
-
- name="FirstFlexible"
- >
-Denne genstand er fleksibel.
+ </notification>
+ <notification name="FirstFlexible">
+ Denne genstand er fleksibel.
Fleksible genstande er ikke fysiske og man kan gå igennem dem, indtil fleksibel-punktet ikke er afkrydset.
- </notification>
-
- <notification
-
- name="FirstDebugMenus"
- >
-Du har sat avanceret menu til.
-Denne menu indeholder funktioner brugbare for udviklere, der udbedrer fejl i Second Life.
-For at vise denne menu, skal man i Windows trykke Ctrl-Alt-D. PÃ¥ Mac tryk Cmd-Opt-Shift-D.
- </notification>
-
- <notification
-
- name="FirstSculptedPrim"
- >
-Du retter en sculpted prim.
+ </notification>
+ <notification name="FirstDebugMenus">
+ Du har sat avanceret menu til.
+Denne menu indeholder funktioner brugbare for udviklere, der udbedrer fejl i [SECOND_LIFE].
+For at vise denne menu, skal man i Windows trykke Ctrl+Alt+D. PÃ¥ Mac tryk &#8997;&#8984;D.
+ </notification>
+ <notification name="FirstSculptedPrim">
+ Du retter en sculpted prim.
Sculpted prims kræver et specielt tekstur for at specificere deres form.
Du kan finde eksempler på sculptede teksturer i din beholdning.
- </notification>
-
- <notification
-
- name="FirstMedia"
- >
-Du er begyndt at afspille medie. Medie kan sættes til automatisk af blive afspillet under Indstillinger, Lyd / Video. Vær opmærksom på, at der kan være en sikkerhedsrisiko for medie-steder, du ikke stoler på.
- </notification>
-
- <notification
-
- name="MaxListSelectMessage"
- >
-Du må kun vælge op til [MAX_SELECT] genstande på denne liste.
- </notification>
-
- <notification
-
- name="VoiceInviteP2P"
- >
-[NAME] inviterer dig til en stemme-chat.
+ </notification>
+ <notification name="FirstMedia">
+ Du er begyndt at afspille medie. Medie kan sættes til automatisk af blive afspillet under Indstillinger, Lyd / Video. Vær opmærksom på, at der kan være en sikkerhedsrisiko for medie-steder, du ikke stoler på.
+ </notification>
+ <notification name="MaxListSelectMessage">
+ Du må kun vælge op til [MAX_SELECT] genstande på denne liste.
+ </notification>
+ <notification name="VoiceInviteP2P">
+ [NAME] inviterer dig til en stemme-chat.
Klik for at acceptere at koble dig på samtalen eller Afvis for at afvise invitationen. Klik på Slå fra for at blokere denne opkalder.
- <form name="form">
- <button
-
- name="Accept"
- text="Acceptér"/>
- <button
-
- name="Decline"
- text="Afvis"/>
- <button
-
- name="Mute"
- text="Blokér"/>
- </form>
- </notification>
-
- <notification
-
- name="AutoUnmuteByIM"
- >
-[FIRST] [LAST] har fået en personlig besked (IM) og er automatisk ikke blokeret mere.
- </notification>
-
- <notification
-
- name="AutoUnmuteByMoney"
- >
-[FIRST] [LAST] har fået penge og er automatisk ikke blokeret mere.
- </notification>
-
- <notification
-
- name="AutoUnmuteByInventory"
- >
-[FIRST] [LAST] har fået tilbudt genstande og er automatisk ikke blokeret mere.
- </notification>
-
- <notification
-
- name="VoiceInviteGroup"
- >
-[NAME] har tilsluttet sig stemme-chat med gruppen [GROUP].
+ <form name="form">
+ <button name="Accept" text="Acceptér"/>
+ <button name="Decline" text="Afvis"/>
+ <button name="Mute" text="Blokér"/>
+ </form>
+ </notification>
+ <notification name="AutoUnmuteByIM">
+ [FIRST] [LAST] har fået en personlig besked (IM) og er automatisk ikke blokeret mere.
+ </notification>
+ <notification name="AutoUnmuteByMoney">
+ [FIRST] [LAST] har fået penge og er automatisk ikke blokeret mere.
+ </notification>
+ <notification name="AutoUnmuteByInventory">
+ [FIRST] [LAST] har fået tilbudt genstande og er automatisk ikke blokeret mere.
+ </notification>
+ <notification name="VoiceInviteGroup">
+ [NAME] har tilsluttet sig stemme-chat med gruppen [GROUP].
Klik Acceptér for at slutte dig til samtalen eller Afvis for at afvise invitationen. Klik Slå fra for at blokere denne opkalder.
- <form name="form">
- <button
-
- name="Accept"
- text="Acceptér"/>
- <button
-
- name="Decline"
- text="Afvis"/>
- <button
-
- name="Mute"
- text="Blokér"/>
- </form>
- </notification>
-
- <notification
-
- name="VoiceInviteAdHoc"
- >
-[NAME] har tilsluttet sig stemme-chat med en konference-chat.
+ <form name="form">
+ <button name="Accept" text="Acceptér"/>
+ <button name="Decline" text="Afvis"/>
+ <button name="Mute" text="Blokér"/>
+ </form>
+ </notification>
+ <notification name="VoiceInviteAdHoc">
+ [NAME] har tilsluttet sig stemme-chat med en konference-chat.
Klik Acceptér for at slutte dig til samtalen eller Afvis for at afvise invitationen. Klik Slå fra for at blokere denne opkalder.
- <form name="form">
- <button
-
- name="Accept"
- text="Acceptér"/>
- <button
-
- name="Decline"
- text="Afvis"/>
- <button
-
- name="Mute"
- text="Blokér"/>
- </form>
- </notification>
-
- <notification
-
- name="InviteAdHoc"
- >
-[NAME] inviterer dig til en konference-chat.
+ <form name="form">
+ <button name="Accept" text="Acceptér"/>
+ <button name="Decline" text="Afvis"/>
+ <button name="Mute" text="Blokér"/>
+ </form>
+ </notification>
+ <notification name="InviteAdHoc">
+ [NAME] inviterer dig til en konference-chat.
Klik Acceptér for at slutte dig til samtalen eller Afvis for at afvise invitationen. Klik Slå fra for at blokere denne opkalder.
- <form name="form">
- <button
-
- name="Accept"
- text="Acceptér"/>
- <button
-
- name="Decline"
- text="Afvis"/>
- <button
-
- name="Mute"
- text="Blokeret"/>
- </form>
- </notification>
-
- <notification
-
- name="VoiceChannelFull"
- >
-Den stemme-chat, du prøver at tilslutte dig, [VOICE_CHANNEL_NAME], har nået maksiumum kapacitet. Prøv venligst igen senere.
- </notification>
-
- <notification
-
- name="ProximalVoiceChannelFull"
- >
-Vi beklager. Dette område har nået sin maksimale kapacitet for stemme-chat. Prøv venligst at benytte stemme i et andet område.
- </notification>
-
- <notification
-
- name="VoiceChannelDisconnected"
- >
-Du er blevet koblet af [VOICE_CHANNEL_NAME]. Du vil nu blive koblet op på en lokal stemme-chat.
- </notification>
-
- <notification
-
- name="VoiceChannelDisconnectedP2P"
- >
-[VOICE_CHANNEL_NAME] har afsluttet opkaldet. Du vil nu blive koblet op på en lokal stemme-chat.
- </notification>
-
- <notification
-
- name="P2PCallDeclined"
- >
-[VOICE_CHANNEL_NAME] har afvist dit opkald. Du vil nu blive koblet op på en lokal stemme-chat.
- </notification>
-
- <notification
-
- name="P2PCallNoAnswer"
- >
-[VOICE_CHANNEL_NAME] har ikke mulighed for at besvare dit opkald. Du vil nu blive koblet op på en lokal chat.
- </notification>
-
- <notification
-
- name="VoiceChannelJoinFailed"
- >
-Det lykkedes ikke at koble op til [VOICE_CHANNEL_NAME]. Prøv venligst igen senere.
- </notification>
-
- <notification
-
- name="VoiceLoginRetry"
- >
-Vi laver en stemmekanal til dig. Det kan tage op til et minut.
- </notification>
-
- <notification
-
- name="Cannot enter parcel: not a group member"
- >
-Du kan ikke komme ind på området. Du er ikke medlem af den nødvendige gruppe.
- </notification>
-
- <notification
-
- name="Cannot enter parcel: banned"
- >
-Du kan ikke komme ind på området. Du er blevet udelukket.
- </notification>
-
- <notification
-
- name="Cannot enter parcel: not on access list"
- >
-Du kan ikke komme ind på området. Du er ikke på adgangslisten.
- </notification>
-
- <notification
-
- name="VoiceNotAllowed"
- >
-Du har ikke tilladelse til at tilslutte dig stemme-chat på [VOICE_CHANNEL_NAME].
- </notification>
-
- <notification
-
- name="VoiceCallGenericError"
- >
-En fejl er opstået under forsøget på at koble sig på stemme chatten [VOICE_CHANNEL_NAME]. Pråv venligst senere.
- </notification>
-
- <notification
-
- name="ServerVersionChanged"
- >
-Det område, du er kommet ind på, kører en anden simulatorversion. Klik på denne besked for detaljer.
- </notification>
-
- <notification
-
- name="UnableToOpenCommandURL"
- >
-Www-adressen, du har klikket på, kan ikke åbnes fra denne internetbrowser.
- </notification>
+ <form name="form">
+ <button name="Accept" text="Acceptér"/>
+ <button name="Decline" text="Afvis"/>
+ <button name="Mute" text="Blokeret"/>
+ </form>
+ </notification>
+ <notification name="VoiceChannelFull">
+ Den stemme-chat, du prøver at tilslutte dig, [VOICE_CHANNEL_NAME], har nået maksiumum kapacitet. Prøv venligst igen senere.
+ </notification>
+ <notification name="ProximalVoiceChannelFull">
+ Vi beklager. Dette område har nået sin maksimale kapacitet for stemme-chat. Prøv venligst at benytte stemme i et andet område.
+ </notification>
+ <notification name="VoiceChannelDisconnected">
+ Du er blevet koblet af [VOICE_CHANNEL_NAME]. Du vil nu blive koblet op på en lokal stemme-chat.
+ </notification>
+ <notification name="VoiceChannelDisconnectedP2P">
+ [VOICE_CHANNEL_NAME] har afsluttet opkaldet. Du vil nu blive koblet op på en lokal stemme-chat.
+ </notification>
+ <notification name="P2PCallDeclined">
+ [VOICE_CHANNEL_NAME] har afvist dit opkald. Du vil nu blive koblet op på en lokal stemme-chat.
+ </notification>
+ <notification name="P2PCallNoAnswer">
+ [VOICE_CHANNEL_NAME] har ikke mulighed for at besvare dit opkald. Du vil nu blive koblet op på en lokal chat.
+ </notification>
+ <notification name="VoiceChannelJoinFailed">
+ Det lykkedes ikke at koble op til [VOICE_CHANNEL_NAME]. Prøv venligst igen senere.
+ </notification>
+ <notification name="VoiceLoginRetry">
+ Vi laver en stemmekanal til dig. Det kan tage op til et minut.
+ </notification>
+ <notification name="Cannot enter parcel: not a group member">
+ Du kan ikke komme ind på området. Du er ikke medlem af den nødvendige gruppe.
+ </notification>
+ <notification name="Cannot enter parcel: banned">
+ Du kan ikke komme ind på området. Du er blevet udelukket.
+ </notification>
+ <notification name="Cannot enter parcel: not on access list">
+ Du kan ikke komme ind på området. Du er ikke på adgangslisten.
+ </notification>
+ <notification name="VoiceNotAllowed">
+ Du har ikke tilladelse til at tilslutte dig stemme-chat på [VOICE_CHANNEL_NAME].
+ </notification>
+ <notification name="VoiceCallGenericError">
+ En fejl er opstået under forsøget på at koble sig på stemme chatten [VOICE_CHANNEL_NAME]. Pråv venligst senere.
+ </notification>
+ <notification name="ServerVersionChanged">
+ Det område, du er kommet ind på, kører en anden simulatorversion. Klik på denne besked for detaljer.
+ </notification>
+ <notification name="UnableToOpenCommandURL">
+ Www-adressen, du har klikket på, kan ikke åbnes fra denne internetbrowser.
+ </notification>
</notifications>
-
diff --git a/indra/newview/skins/default/xui/da/panel_audio_device.xml b/indra/newview/skins/default/xui/da/panel_audio_device.xml
index 6e6bfe39ff..f6d817540e 100644
--- a/indra/newview/skins/default/xui/da/panel_audio_device.xml
+++ b/indra/newview/skins/default/xui/da/panel_audio_device.xml
@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="device_settings">
- <text type="string" length="1" name="Audio Devices">
+ <text name="Audio Devices">
Lydenheder
</text>
- <text type="string" length="1" name="Input device (microphone):">
+ <text name="Input device (microphone):">
Input enhed (mikrofon):
</text>
- <text type="string" length="1" name="Output device (speakers):">
+ <text name="Output device (speakers):">
Output enhed (højtalere):
</text>
- <text type="string" length="1" name="Input level:">
+ <text name="Input level:">
Input niveau
</text>
- <text_editor type="string" length="1" name="voice_intro_text1">
+ <text_editor name="voice_intro_text1">
Med denne skyder kan du regulere hvor højt du lyder i forhold til andre beboere. for at test input niveau kan du blot tale i mikrofon.
</text_editor>
<volume_slider name="mic_volume_slider" tool_tip="Ændre lydstyrke med denne skyder" />
diff --git a/indra/newview/skins/default/xui/da/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/da/panel_block_list_sidetray.xml
new file mode 100644
index 0000000000..986a4131de
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/panel_block_list_sidetray.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="block_list_panel">
+ <text name="title_text">
+ Blokérede avatarer
+ </text>
+ <scroll_list name="blocked" tool_tip="Vis liste over blokerede avatarer"/>
+ <button label="Blokér beboer..." label_selected="Blokér beboer..." name="Block resident..." tool_tip="Vælg en beboer der skal blokeres"/>
+ <button label="Blokér objekt via navn..." label_selected="Blokér objekt via navn..." name="Block object by name..."/>
+ <button label="Fjern blokering" label_selected="Fjern blokering" name="Unblock" tool_tip="Fjern beboer fra liste med blokeringer"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/da/panel_edit_profile.xml b/indra/newview/skins/default/xui/da/panel_edit_profile.xml
new file mode 100644
index 0000000000..a8a02a34b7
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/panel_edit_profile.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel name="edit_profile_panel">
+ <string name="CaptionTextAcctInfo">
+ [ACCTTYPE]
+[PAYMENTINFO] [AGEVERIFICATION]
+ </string>
+ <string name="AcctTypeResident"
+ value="Beboer" />
+ <string name="AcctTypeTrial"
+ value="På prøve" />
+ <string name="AcctTypeCharterMember"
+ value="æresmedlem" />
+ <string name="AcctTypeEmployee"
+ value="Linden Lab medarbejder" />
+ <string name="PaymentInfoUsed"
+ value="Betalende medlem" />
+ <string name="PaymentInfoOnFile"
+ value="Registreret betalende" />
+ <string name="NoPaymentInfoOnFile"
+ value="Ingen betalingsinfo" />
+ <string name="AgeVerified"
+ value="Alders-checket" />
+ <string name="NotAgeVerified"
+ value="Ikke alders-checket" />
+ <string name="partner_edit_link_url">
+ http://www.secondlife.com/account/partners.php?lang=da
+ </string>
+ <panel name="scroll_content_panel">
+ <panel name="data_panel" >
+ <panel name="lifes_images_panel">
+ <panel name="second_life_image_panel">
+ <text name="second_life_photo_title_text">
+ [SECOND_LIFE]:
+ </text>
+ </panel>
+ </panel>
+ <text name="title_partner_text" value="Partner:"/>
+ <panel name="partner_data_panel">
+ <text name="partner_text" value="[FIRST] [LAST]"/>
+ </panel>
+ <text name="text_box3">
+ Optaget autosvar:
+ </text>
+ </panel>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/da/panel_group_general.xml b/indra/newview/skins/default/xui/da/panel_group_general.xml
index 393ac49725..4e98ca2bc2 100644
--- a/indra/newview/skins/default/xui/da/panel_group_general.xml
+++ b/indra/newview/skins/default/xui/da/panel_group_general.xml
@@ -1,37 +1,33 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Generelt" name="general_tab">
<string name="help_text">
- Generel-fanen indeholder generel information om
-denne gruppe, en liste med ejere og synlige medlemmer,
-generel-gruppeindstillinger og medlemsmuligheder.
+ Generel-fanen indeholder generel information om denne gruppe, en liste med ejere og synlige medlemmer, generel-gruppeindstillinger og medlemsmuligheder.
Bevæg din mus over mulighederne for mere hjælp.
</string>
<string name="group_info_unchanged">
Generel gruppeinformation er ændret.
</string>
- <button label="?" label_selected="?" name="help_button" />
- <line_editor label="Indtast nyt gruppenavn her" name="group_name_editor" />
+ <button label="?" label_selected="?" name="help_button"/>
+ <line_editor label="Indtast nyt gruppenavn her" name="group_name_editor"/>
<text name="group_name">
Skriv det nye gruppenavn her
</text>
<text name="prepend_founded_by">
Grundlagt af
</text>
- <text name="founder_name">
+ <text name="founder_name" left_delta="70" >
(venter)
</text>
<text name="group_charter_label">
Gruppens formål
</text>
- <texture_picker label="Gruppe distinktioner" name="insignia"
- tool_tip="Klik for at vælge et billede" />
+ <texture_picker label="Gruppe distinktioner" name="insignia" tool_tip="Klik for at vælge et billede"/>
<text_editor name="charter">
Gruppens formål
</text_editor>
- <button label="Tilmeld (L$0)" label_selected="Tilmeld (L$0)" name="join_button" />
- <button label="Detaljeret visning" label_selected="Detaljeret visning"
- name="info_button" />
+ <button label="Tilmeld (L$0)" label_selected="Tilmeld (L$0)" name="join_button"/>
+ <button label="Detaljeret visning" label_selected="Detaljeret visning" name="info_button"/>
<text name="text_owners_and_visible_members">
Ejere &amp; synlige medlemmer
</text>
@@ -39,34 +35,31 @@ Bevæg din mus over mulighederne for mere hjælp.
(Ejere er vist med fed skrift)
</text>
<name_list name="visible_members">
- <column label="Medlemsnavn" name="name" />
- <column label="Titel" name="title" />
- <column label="Senest på d." name="online" />
+ <name_list.columns label="Medlemsnavn" name="name"/>
+ <name_list.columns label="Titel" name="title"/>
+ <name_list.columns label="Senest på d." name="online"/>
</name_list>
<text name="text_group_preferences">
Gruppeindstillinger
</text>
<panel name="preferences_container">
- <check_box label="Vis i søgning" name="show_in_group_list"
- tool_tip="Lad folk se denne gruppe i søgeresultater." />
- <check_box label="Ã…ben tilmelding" name="open_enrollement"
- tool_tip="Angiver om denne gruppe tillader nye medlemmer at tilmelde sig, uden de er inviteret." />
- <check_box label="Tilmeldingsgebyr: L$" name="check_enrollment_fee"
- tool_tip="Angiver om der kræves et gebyr, for at tilmelde sig gruppen." />
- <spinner name="spin_enrollment_fee"
- tool_tip="Nye medlemmer skal betale dette gebyr for at tilmelde sig gruppen, når Tilmeldingsgebyr er valgt." />
-
+ <check_box label="Vis i søgning" name="show_in_group_list" tool_tip="Lad folk se denne gruppe i søgeresultater."/>
+ <check_box label="Ã…ben tilmelding" name="open_enrollement" tool_tip="Angiver om denne gruppe tillader nye medlemmer at tilmelde sig, uden de er inviteret."/>
+ <check_box label="Tilmeldingsgebyr:" name="check_enrollment_fee" tool_tip="Angiver om der kræves et gebyr, for at tilmelde sig gruppen."/>
+ <spinner name="spin_enrollment_fee" tool_tip="Nye medlemmer skal betale dette gebyr for at tilmelde sig gruppen, når Tilmeldingsgebyr er valgt." width="60" left_delta="130"/>
+ <combo_box name="group_mature_check" tool_tip="Angiver om din gruppes information anses som &apos;mature&apos;." width="150">
+ <combo_box.item name="select_mature" label="- Vælg indholdsrating -"/>
+ <combo_box.item name="mature" label="Mature indhold"/>
+ <combo_box.item name="pg" label="PG indhold"/>
+ </combo_box>
<panel name="title_container">
<text name="active_title_label">
Min aktive titel
</text>
- <combo_box length="150" name="active_title"
- tool_tip="Angiver den titel der vises i din avatars navnefelt, når denne gruppe er aktiv." />
+ <combo_box name="active_title" tool_tip="Angiver den titel der vises i din avatars navnefelt, når denne gruppe er aktiv."/>
</panel>
- <check_box label="Modtag gruppeinformationer" name="receive_notices"
- tool_tip="Angiver om du vil modtage informationer fra denne gruppe. Fjern markeringen i boksen hvis gruppen spammer dig." />
- <check_box label="Vis gruppen i min profil" name="list_groups_in_profile"
- tool_tip="Angiver om du vil vise denne gruppe i dine profilinformationer" />
+ <check_box label="Modtag gruppeinformationer" name="receive_notices" tool_tip="Angiver om du vil modtage informationer fra denne gruppe. Fjern markeringen i boksen hvis gruppen spammer dig."/>
+ <check_box label="Vis gruppen i min profil" name="list_groups_in_profile" tool_tip="Angiver om du vil vise denne gruppe i dine profilinformationer"/>
</panel>
<string name="incomplete_member_data_str">
Henter medlemsinformationer
diff --git a/indra/newview/skins/default/xui/da/panel_group_invite.xml b/indra/newview/skins/default/xui/da/panel_group_invite.xml
index 6efc93daac..813007aee0 100644
--- a/indra/newview/skins/default/xui/da/panel_group_invite.xml
+++ b/indra/newview/skins/default/xui/da/panel_group_invite.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel label="Invitér et medlem" name="invite_panel">
<text name="help_text">
- Du kan invitere flere beboere til at
-blive medlem af din gruppe. Klik &apos;Ã…ben
-personvælger&apos; for at begynde.
+ Du kan invitere flere beboere ad
+gangen til at blive medlem af din
+gruppe. Klik &apos;Åben personvælger&apos; for
+at begynde.
</text>
- <button label="Åben personvælger" name="add_button" />
+ <button label="Åben personvælger" name="add_button" bottom_delta="-30"/>
<name_list name="invitee_list"
tool_tip="Hold Ctrl-tasten nede og klik på beboere for at vælge flere." />
<button label="Fjern valgte fra listen" name="remove_button"
diff --git a/indra/newview/skins/default/xui/da/panel_group_land_money.xml b/indra/newview/skins/default/xui/da/panel_group_land_money.xml
index 2ab8935609..636a16f97b 100644
--- a/indra/newview/skins/default/xui/da/panel_group_land_money.xml
+++ b/indra/newview/skins/default/xui/da/panel_group_land_money.xml
@@ -1,10 +1,9 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Land &amp; L$" name="land_money_tab">
<string name="help_text">
- Grunde ejet af gruppen er vist sammen med bidragsdetaljer. En advarsel vises indtil Total land i brug er mindre end eller lig med det totale
-bidrag. Planlægning, detaljer og salgsfaneblade viser information om gruppens økonomi.
+ Grunde ejet af gruppen er vist sammen med bidragsdetaljer. En advarsel vises indtil Total land i brug er mindre end eller lig med det totale bidrag. Planlægning, detaljer og salgsfaneblade viser information om gruppens økonomi.
</string>
- <button label="?" name="help_button" />
+ <button label="?" name="help_button"/>
<string name="cant_view_group_land_text">
Du har ikke tilladelse til at se gruppeejet land.
</string>
@@ -18,29 +17,30 @@ bidrag. Planlægning, detaljer og salgsfaneblade viser information om gruppens Ã
Gruppeejet land
</text>
<scroll_list name="group_parcel_list">
- <column label="Grundens navn" name="name" />
- <column label="Region" name="location" />
- <column label="Område" name="area" />
- <column label="" name="hidden" />
+ <column label="Grundens navn" name="name"/>
+ <column label="Region" name="location"/>
+ <column label="Type" name="type"/>
+ <column label="Område" name="area"/>
+ <column label="" name="hidden"/>
</scroll_list>
- <button label="Vis på kort" label_selected="Vis på kort" name="map_button" />
+ <button label="Vis på kort" label_selected="Vis på kort" name="map_button"/>
<text name="total_contributed_land_label">
Total bidrag:
</text>
<text name="total_contributed_land_value">
- [AREA] kvadratmeter
+ [AREA] m²
</text>
<text name="total_land_in_use_label">
Total land i brug:
</text>
<text name="total_land_in_use_value">
- [AREA] kvadratmeter
+ [AREA] m²
</text>
<text name="land_available_label">
Tilgængeligt land:
</text>
<text name="land_available_value">
- [AREA] kvadratmeter
+ [AREA] m²
</text>
<text name="your_contribution_label">
Dit bidrag:
@@ -48,33 +48,38 @@ bidrag. Planlægning, detaljer og salgsfaneblade viser information om gruppens Ã
<string name="land_contrib_error">
Ikke muligt at lave dit bidrag til landet.
</string>
+ <text name="your_contribution_units">
+ ( m² )
+ </text>
<text name="your_contribution_max_value">
- kvadratmeter ([AMOUNT] maks.)
+ ([AMOUNT] maks.)
</text>
<text name="group_over_limit_text">
- Gruppemedlemmer må bidrag med mere, for at understøtte med det land der bliver brugt.
+ Gruppemedlemmer må bidrag med mere, for at understøtte
+med det land der bliver brugt.
</text>
<text name="group_money_heading">
Gruppe L$
</text>
<tab_container name="group_money_tab_container">
+ <panel label="Planlægning" name="group_money_planning_tab">
+ <text_editor name="group_money_planning_text">
+ Beregner...
+ </text_editor>
+ </panel>
<panel label="Detaljer" name="group_money_details_tab">
<text_editor name="group_money_details_text">
Beregner...
</text_editor>
- <button label="&lt; Før" label_selected="&lt; Før" name="earlier_details_button"
- tool_tip="GÃ¥ tilbage i tid" />
- <button label="Efter &gt;" label_selected="Efter &gt;" name="later_details_button"
- tool_tip="GÃ¥ frem i tid" />
+ <button label="&lt; Før" label_selected="&lt; Før" name="earlier_details_button" tool_tip="Gå tilbage i tid"/>
+ <button label="Efter &gt;" label_selected="Efter &gt;" name="later_details_button" tool_tip="GÃ¥ frem i tid"/>
</panel>
<panel label="Salg" name="group_money_sales_tab">
<text_editor name="group_money_sales_text">
Beregner...
</text_editor>
- <button label="&lt; Før" label_selected="&lt; Før" name="earlier_sales_button"
- tool_tip="GÃ¥ tilbage i tid" />
- <button label="Efter &gt;" label_selected="Efter &gt;" name="later_sales_button"
- tool_tip="GÃ¥ frem i tid" />
+ <button label="&lt; Før" label_selected="&lt; Før" name="earlier_sales_button" tool_tip="Gå tilbage i tid"/>
+ <button label="Efter &gt;" label_selected="Efter &gt;" name="later_sales_button" tool_tip="GÃ¥ frem i tid"/>
</panel>
</tab_container>
</panel>
diff --git a/indra/newview/skins/default/xui/da/panel_group_notices.xml b/indra/newview/skins/default/xui/da/panel_group_notices.xml
index 103404e47b..9e6aa9eb7c 100644
--- a/indra/newview/skins/default/xui/da/panel_group_notices.xml
+++ b/indra/newview/skins/default/xui/da/panel_group_notices.xml
@@ -16,8 +16,7 @@ Generel-fanebladet.
Arkiv med gruppebeskeder
</text>
<text name="lbl2">
- Beskeder er gemt i 14 dage. Klik på den besked herunder, du ønsker at se.
-Klik på &apos;Genopfrisk&apos;-knappen for at se, om nye beskeder er modtaget.
+ Beskeder er gemt i 14 dage.
Listen er begrænset til 200 beskeder pr. gruppe hver dag.
</text>
<scroll_list name="notice_list">
@@ -36,10 +35,7 @@ Listen er begrænset til 200 beskeder pr. gruppe hver dag.
Lav en besked
</text>
<text name="lbl2">
- Du skal skrive et emne for at sende beskeden. Du kan tilføje et
-bilag til beskeden ved at trække den fra beholdningen til
-dette felt. Vedhæftede objekter skal være sat til at kunne
-kopieres og overføres, og du kan ikke sende en mappe.
+ Du kan tilføje et bilag til beskeden ved at trække den fra beholdningen til dette felt. Vedhæftede objekter skal være sat til at kunne kopieres og overføres, og du kan ikke sende en mappe.
</text>
<text name="lbl3">
Emne:
diff --git a/indra/newview/skins/default/xui/da/panel_group_roles.xml b/indra/newview/skins/default/xui/da/panel_group_roles.xml
index 2af84858a1..2cb57b4e87 100644
--- a/indra/newview/skins/default/xui/da/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/da/panel_group_roles.xml
@@ -1,121 +1,81 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Medlemmer &amp; roller" name="roles_tab">
- <string name="default_needs_apply_text">
+ <panel.string name="default_needs_apply_text">
Der er ændringer her, der ikke er gemt.
- </string>
- <string name="want_apply_text">
+ </panel.string>
+ <panel.string name="want_apply_text">
Vil du gemme disse ændringer?
- </string>
- <button label="?" name="help_button" />
- <panel name="members_header">
- <text name="static">
- Medlemmer &amp; roller
- </text>
- <text name="static2">
- Gruppemedlemmer får tildelt roller med rettigheder. Disse indstillinger kan
-let tilpasses efter ønske, så gruppen kan vokse og blive mere fleksibel.
- </text>
- </panel>
- <panel name="roles_header">
- <text name="static">
- Roller
- </text>
- <text name="role_properties_modifiable">
- Vælg en rolle nedenfor. Du kan ændre dens navn, beskrivelse og medlemstitel.
- </text>
- <text name="role_properties_not_modifiable">
- Vælg rolle forneden for at se dens egenskaber, medlemmer og rettigheder.
- </text>
- <text name="role_actions_modifiable">
- Du kan også tildele rettigheder til rollen.
- </text>
- <text name="role_actions_not_modifiable">
- Du kan se, men ikke ændre, tildelte rettigheder.
- </text>
- </panel>
- <panel name="actions_header">
- <text name="static">
- Rettigheder
- </text>
- <text name="static2">
- Du kan se en rettigheds beskrivelse og hvilke roller og medlemmer,
-der har denne rettighed.
- </text>
- </panel>
+ </panel.string>
<tab_container name="roles_tab_container">
- <panel label="Medlemmer" name="members_sub_tab" tool_tip="Medlemmer">
- <button label="Søg" name="search_button" />
- <button label="Vis alle" name="show_all_button" />
- <name_list name="member_list">
- <column label="Medlemsnavn" name="name" />
- <column label="Doneret leje" name="donated" />
- <column label="Sidst på den" name="online" />
- </name_list>
- <button label="Inviter ny person ..." name="member_invite" />
- <button label="Udmeld" name="member_eject" />
- <string name="help_text">
+ <panel label="MEDLEMMER" name="members_sub_tab" tool_tip="Medlemmer">
+ <panel.string name="help_text">
Du kan tilføje eller fjerne roller, der er tildelt medlemmerne.
Vælg flere medlemmer ved at holde Ctrl-tasten nede og
klik på deres navne.
- </string>
+ </panel.string>
+ <filter_editor label="Filtrér medlemmer" name="filter_input"/>
+ <name_list name="member_list">
+ <name_list.columns label="Medlemsnavn" name="name"/>
+ <name_list.columns label="Doneret leje" name="donated"/>
+ <name_list.columns label="Sidst på den" name="online"/>
+ </name_list>
+ <button label="Invitér nyt medlem" name="member_invite"/>
+ <button label="Udmeld" name="member_eject"/>
</panel>
- <panel label="Roller" name="roles_sub_tab">
- <button label="Søg" name="search_button" />
- <button label="Vis alle" name="show_all_button" />
- <scroll_list name="role_list">
- <column label="Rollenavn" name="name" />
- <column label="Titel" name="title" />
- <column label="Medlemmer" name="members" />
- </scroll_list>
- <button label="Opret ny rolle ..." name="role_create" />
- <button label="Slet rolle" name="role_delete" />
- <string name="help_text">
+ <panel label="ROLLER" name="roles_sub_tab">
+ <panel.string name="help_text">
Roller har en titel og en tilladelsesliste med rettigheder,
som medlemmerne kan bruge. Medlemmer kan høre til
en eller flere roller. En gruppe kan have op til 10 roller,
inkluderet alle- og ejerroller.
- </string>
- <string name="cant_delete_role">
+ </panel.string>
+ <panel.string name="cant_delete_role">
&apos;Alle-&apos; og &apos;Ejerroller&apos; er specielle og kan ikke slettes.
- </string>
- </panel>
- <panel label="Rettigheder" name="actions_sub_tab">
- <button label="Søg" name="search_button" />
- <button label="Vis alle" name="show_all_button" />
- <scroll_list name="action_list" tool_tip="Vælg en rettighed for at se flere detaljer">
- <column label="" name="icon" />
- <column label="" name="action" />
+ </panel.string>
+ <panel.string name="power_folder_icon">
+ Inv_FolderClosed
+ </panel.string>
+ <filter_editor label="Filtrér roller" name="filter_input"/>
+ <scroll_list name="role_list">
+ <scroll_list.columns label="Rollenavn" name="name"/>
+ <scroll_list.columns label="Titel" name="title"/>
+ <scroll_list.columns label="Medlemmer" name="members"/>
</scroll_list>
- <string name="help_text">
+ <button label="Opret ny rolle" name="role_create"/>
+ <button label="Slet rolle" name="role_delete"/>
+ </panel>
+ <panel label="RETTIGHEDER" name="actions_sub_tab" tool_tip="Du kan se beskrivelse af rettighed og hvilke roller og medlemmer der har denne rettighed.">
+ <panel.string name="help_text">
Rettigheder giver medlemmer i roller mulighed for at gøre specifikke
ting i denne gruppe. Der er en bred vifte af rettigheder.
- </string>
+ </panel.string>
+ <filter_editor label="Filtrér rettigheder" name="filter_input"/>
+ <scroll_list name="action_list" tool_tip="Vælg en rettighed for at se flere detaljer">
+ <scroll_list.columns label="" name="icon"/>
+ <scroll_list.columns label="" name="action"/>
+ </scroll_list>
</panel>
</tab_container>
<panel name="members_footer">
<text name="static">
Tildelte roller
</text>
+ <scroll_list name="member_assigned_roles">
+ <scroll_list.columns label="" name="checkbox"/>
+ <scroll_list.columns label="" name="role"/>
+ </scroll_list>
<text name="static2">
Tilladte rettigheder
</text>
- <scroll_list name="member_assigned_roles">
- <column label="" name="checkbox" />
- <column label="" name="role" />
- </scroll_list>
- <scroll_list name="member_allowed_actions"
- tool_tip="For detaljer om hver tilladte rettighed, se rettighedsfanebladet.">
- <column label="" name="icon" />
- <column label="" name="action" />
+ <scroll_list name="member_allowed_actions" tool_tip="For detaljer om hver tilladte rettighed, se rettighedsfanebladet.">
+ <scroll_list.columns label="" name="icon"/>
+ <scroll_list.columns label="" name="action"/>
</scroll_list>
</panel>
<panel name="roles_footer">
<text name="static">
Navn
</text>
- <text name="static2">
- Beskrivelse
- </text>
<line_editor name="role_name">
Ansatte
</line_editor>
@@ -125,23 +85,23 @@ ting i denne gruppe. Der er en bred vifte af rettigheder.
<line_editor name="role_title">
(venter)
</line_editor>
+ <text name="static2">
+ Beskrivelse
+ </text>
<text_editor name="role_description">
(venter)
</text_editor>
<text name="static4">
- Tildelte medlemmer
+ Tildelte roller
</text>
- <text name="static5"
- tool_tip="A list of Abilities the currently selected role can perform.">
+ <check_box label="Medlemmer er synlige" name="role_visible_in_list" tool_tip="Angiver om medlemmer med denne rolle er synlige i fanen &apos;Generelt&apos; for avatarer uden for gruppen."/>
+ <text name="static5" tool_tip="A list of Abilities the currently selected role can perform.">
Tilladte rettigheder
</text>
- <check_box label="Medlemmer er synlige" name="role_visible_in_list"
- tool_tip=" Angiver om medlemmer med denne rolle er synlige i fanen &apos;Generelt&apos; for avatarer uden for gruppen." />
- <scroll_list name="role_allowed_actions"
- tool_tip="For detaljer om hver rettighed se under rettigheder fanebladet.">
- <column label="" name="icon" />
- <column label="" name="checkbox" />
- <column label="" name="action" />
+ <scroll_list name="role_allowed_actions" tool_tip="For detaljer om hver rettighed se under rettigheder fanebladet.">
+ <scroll_list.columns label="" name="icon"/>
+ <scroll_list.columns label="" name="checkbox"/>
+ <scroll_list.columns label="" name="action"/>
</scroll_list>
</panel>
<panel name="actions_footer">
diff --git a/indra/newview/skins/default/xui/da/panel_groups.xml b/indra/newview/skins/default/xui/da/panel_groups.xml
index b3a09b0082..5877226e57 100644
--- a/indra/newview/skins/default/xui/da/panel_groups.xml
+++ b/indra/newview/skins/default/xui/da/panel_groups.xml
@@ -3,10 +3,10 @@
<scroll_list name="group list">
<column label="" name="name" />
</scroll_list>
- <text type="string" length="1" name="groupdesc">
+ <text name="groupdesc" width="300">
Din nuværende aktive gruppe er fremhævet i listen.
</text>
- <text type="string" length="1" name="groupcount">
+ <text name="groupcount" width="300">
Du er medlem i [COUNT] grupper (ud af maksimalt [MAX]).
</text>
<button label="IM/Opkald" name="IM" tool_tip="Ã…bner IM session" />
diff --git a/indra/newview/skins/default/xui/da/panel_login.xml b/indra/newview/skins/default/xui/da/panel_login.xml
index 48d58ae8f7..3b1b717c46 100644
--- a/indra/newview/skins/default/xui/da/panel_login.xml
+++ b/indra/newview/skins/default/xui/da/panel_login.xml
@@ -1,43 +1,38 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="panel_login">
- <string name="real_url">
+ <panel.string name="real_url">
http://secondlife.com/app/login/
- </string>
- <string name="forgot_password_url">
+ </panel.string>
+ <panel.string name="forgot_password_url">
http://secondlife.com/account/request.php
- </string>
- <text name="first_name_text">
- Fornavn:
- </text>
- <text name="last_name_text">
- Efternavn:
- </text>
- <text name="password_text">
- Password:
- </text>
- <text name="start_location_text">
- Start lokation:
- </text>
- <combo_box name="start_location_combo">
- <combo_item name="MyHome">
- Hjem
- </combo_item>
- <combo_item name="MyLastLocation">
- Min sidste lokation
- </combo_item>
- <combo_item name="Typeregionname">
- &lt;Skriv navn på region&gt;
- </combo_item>
- </combo_box>
- <check_box label="Husk password" name="remember_check" />
- <button label="Log ind" label_selected="Log ind" name="connect_btn" />
- <text name="create_new_account_text">
- Opret bruger
- </text>
- <text name="forgot_password_text">
- Glemt navn eller password?
- </text>
- <text name="channel_text">
- [VERSION]
- </text>
+ </panel.string>
+ <panel name="login_widgets">
+ <text name="first_name_text">
+ Fornavn:
+ </text>
+ <line_editor name="first_name_edit" tool_tip="[SECOND_LIFE] Fornavn"/>
+ <text name="last_name_text">
+ Efternavn:
+ </text>
+ <line_editor name="last_name_edit" tool_tip="[SECOND_LIFE] Efternavn"/>
+ <text name="password_text">
+ Password:
+ </text>
+ <button label="Log Ind" label_selected="Log Ind" name="connect_btn"/>
+ <text name="start_location_text">
+ Start lokation:
+ </text>
+ <combo_box name="start_location_combo">
+ <combo_box.item label="Min sidste lokation" name="MyLastLocation"/>
+ <combo_box.item label="Hjem" name="MyHome"/>
+ <combo_box.item label="&lt;Skriv navn på region&gt;" name="Typeregionname"/>
+ </combo_box>
+ <check_box label="Husk password" name="remember_check"/>
+ <text name="create_new_account_text">
+ Opret bruger
+ </text>
+ <text name="forgot_password_text">
+ Glemt navn eller password?
+ </text>
+ </panel>
</panel>
diff --git a/indra/newview/skins/default/xui/da/panel_main_inventory.xml b/indra/newview/skins/default/xui/da/panel_main_inventory.xml
new file mode 100644
index 0000000000..ac3a2844db
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/panel_main_inventory.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Ting" name="main inventory panel">
+ <panel.string name="Title">
+ Ting
+ </panel.string>
+ <filter_editor label="Filter" name="inventory search editor"/>
+ <tab_container name="inventory filter tabs">
+ <inventory_panel label="Alle ting" name="All Items"/>
+ <inventory_panel label="Nye ting" name="Recent Items"/>
+ </tab_container>
+ <panel name="bottom_panel">
+ <button name="options_gear_btn" tool_tip="Vis flere valgmuligheder"/>
+ <button name="add_btn" tool_tip="Opret ny genstand"/>
+ <dnd_button name="trash_btn" tool_tip="Fjern valgt genstand"/>
+ </panel>
+ <menu_bar name="Inventory Menu">
+ <menu label="Filer" name="File">
+ <menu_item_call label="Ã…ben" name="Open"/>
+ <menu label="Send fil" name="upload">
+ <menu_item_call label="Billede (L$[COST])..." name="Upload Image"/>
+ <menu_item_call label="Lyd (L$[COST])..." name="Upload Sound"/>
+ <menu_item_call label="Animation (L$[COST])..." name="Upload Animation"/>
+ <menu_item_call label="Flere filer (L$[COST] pr. fil)..." name="Bulk Upload"/>
+ </menu>
+ <menu_item_call label="Nyt vindue" name="New Window"/>
+ <menu_item_call label="Vis filtre" name="Show Filters"/>
+ <menu_item_call label="Nulstil filtre" name="Reset Current"/>
+ <menu_item_call label="Luk alle mapper" name="Close All Folders"/>
+ <menu_item_call label="Tøm papirkurv" name="Empty Trash"/>
+ <menu_item_call label="Tøm fundne genstande" name="Empty Lost And Found"/>
+ </menu>
+ <menu label="Opret" name="Create">
+ <menu_item_call label="Ny mappe" name="New Folder"/>
+ <menu_item_call label="Nyt script" name="New Script"/>
+ <menu_item_call label="Ny note" name="New Note"/>
+ <menu_item_call label="Ny bevægelse" name="New Gesture"/>
+ <menu label="Nyt tøj" name="New Clothes">
+ <menu_item_call label="Ny trøje" name="New Shirt"/>
+ <menu_item_call label="Nye bukser" name="New Pants"/>
+ <menu_item_call label="Nye sko" name="New Shoes"/>
+ <menu_item_call label="Nye strømper" name="New Socks"/>
+ <menu_item_call label="Ny jakke" name="New Jacket"/>
+ <menu_item_call label="Ny nederdel" name="New Skirt"/>
+ <menu_item_call label="Nye handsker" name="New Gloves"/>
+ <menu_item_call label="Ny undertrøje" name="New Undershirt"/>
+ <menu_item_call label="Nye underbukser" name="New Underpants"/>
+ <menu_item_call label="Nyt alpha lag" name="New Alpha"/>
+ <menu_item_call label="Ny tatovering" name="New Tattoo"/>
+ </menu>
+ <menu label="Nye kropsdele" name="New Body Parts">
+ <menu_item_call label="Ny kropsbygning" name="New Shape"/>
+ <menu_item_call label="Ny hud" name="New Skin"/>
+ <menu_item_call label="Nyt hår" name="New Hair"/>
+ <menu_item_call label="Nye øjne" name="New Eyes"/>
+ </menu>
+ </menu>
+ <menu label="Sortér" name="Sort">
+ <menu_item_check label="Efter navn" name="By Name"/>
+ <menu_item_check label="Efter dato" name="By Date"/>
+ <menu_item_check label="Altid mapper efter navn" name="Folders Always By Name"/>
+ <menu_item_check label="System-mapper i toppen" name="System Folders To Top"/>
+ </menu>
+ </menu_bar>
+</panel>
diff --git a/indra/newview/skins/default/xui/da/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/da/panel_preferences_advanced.xml
new file mode 100644
index 0000000000..87b749b4eb
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/panel_preferences_advanced.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<panel name="advanced">
+ <panel.string name="resolution_format">
+ [RES_X] x [RES_Y]
+ </panel.string>
+ <panel.string name="aspect_ratio_text">
+ [NUM]:[DEN]
+ </panel.string>
+ <check_box label="Talebobler" name="bubble_text_chat"/>
+ <color_swatch name="background" tool_tip="Vælg farve for talebobler"/>
+ <slider label="Gennemsigtighed" name="bubble_chat_opacity"/>
+ <text name="AspectRatioLabel1" tool_tip="bredde / højde">
+ Format
+ </text>
+ <combo_box name="aspect_ratio" tool_tip="bredde/ højde">
+ <combo_box.item label="4:3 (Standard CRT)" name="item1"/>
+ <combo_box.item label="5:4 (1280x1024 LCD)" name="item2"/>
+ <combo_box.item label="8:5 (Widescreen)" name="item3"/>
+ <combo_box.item label="16:9 (Widescreen)" name="item4"/>
+ </combo_box>
+ <check_box label="Registrér automatisk" name="aspect_auto_detect"/>
+ <text name="heading1">
+ Kamera:
+ </text>
+ <slider label="Synsvinkel" name="camera_fov"/>
+ <slider label="Distance" name="camera_offset_scale"/>
+ <text name="heading2">
+ Automatisk positionering for:
+ </text>
+ <check_box label="Byg/Redigér" name="edit_camera_movement" tool_tip="Benyt automatisk kamera positionering ved start og slut af editerings modus"/>
+ <check_box label="Udseende" name="appearance_camera_movement" tool_tip="Benyt automatisk kamera positionering ved redigering"/>
+ <text name="heading3">
+ Avatarer:
+ </text>
+ <check_box label="Vis avatar i førsteperson" name="first_person_avatar_visible"/>
+ <check_box label="Piletaster bruges altid til bevægelse" name="arrow_keys_move_avatar_check"/>
+ <check_box label="Tast-tast-hold for at løbe" name="tap_tap_hold_to_run"/>
+ <check_box label="Bevæg avatarlæber når der tales" name="enable_lip_sync"/>
+ <check_box label="Vis scriptfejl" name="show_script_errors"/>
+ <radio_group name="show_location">
+ <radio_item label="I chat" name="0"/>
+ <radio_item label="I et vindue" name="1"/>
+ </radio_group>
+ <check_box label="Knap til aktivering af mikrofon:" name="push_to_talk_toggle_check" tool_tip="I walkie-talkie-modus sendes stemme kun når knappen er trykket ned, ellers vil tryk på knap tænde og slukke mikrofon."/>
+ <line_editor label="Brug walkie-talkie modus" name="modifier_combo"/>
+ <button label="Angiv taste" name="set_voice_hotkey_button"/>
+ <button label="Midterste museknap" name="set_voice_middlemouse_button"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/da/panel_preferences_alerts.xml b/indra/newview/skins/default/xui/da/panel_preferences_alerts.xml
new file mode 100644
index 0000000000..4791033757
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/panel_preferences_alerts.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Popups" name="popups" title="Popups">
+ <text name="tell_me_label">
+ Vis mig når:
+ </text>
+ <check_box label="Når jeg bruger eller får L$" name="notify_money_change_checkbox"/>
+ <check_box label="Når mine venner logger af eller på" name="friends_online_notify_checkbox"/>
+ <text name="show_label">
+ Vis altid disse beskeder:
+ </text>
+ <text name="dont_show_label">
+ Vis aldrig disse beskeder:
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/da/panel_preferences_chat.xml b/indra/newview/skins/default/xui/da/panel_preferences_chat.xml
index 254cd6ddb9..c8602d3119 100644
--- a/indra/newview/skins/default/xui/da/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/da/panel_preferences_chat.xml
@@ -1,61 +1,42 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Tekst chat" name="chat">
- <text type="string" length="1" name="text_box">
- Chat skriftstørrelse:
- </text>
<radio_group name="chat_font_size">
- <radio_item type="string" length="1" name="radio">
- Lille
- </radio_item>
- <radio_item type="string" length="1" name="radio2">
- Mellem
- </radio_item>
- <radio_item type="string" length="1" name="radio3">
- Stor
- </radio_item>
+ <radio_item label="Lille" name="radio"/>
+ <radio_item label="Mellem" name="radio2"/>
+ <radio_item label="Stor" name="radio3"/>
</radio_group>
- <text type="string" length="1" name="text_box2">
- Chat farve:
- </text>
- <color_swatch label="Dig" name="user" />
- <color_swatch label="Andre" name="agent" />
- <color_swatch label="IM" name="im" />
- <color_swatch label="System" name="system" />
- <color_swatch label="Fejl" name="script_error" />
- <color_swatch label="Objekter" name="objects" />
- <color_swatch label="Ejer" name="owner" />
- <color_swatch label="Bobler" name="background" />
- <color_swatch label="URL&apos;er" name="links" />
- <text type="string" length="1" name="text_box8">
- Script fejl:
- </text>
- <check_box label="Vis script fejl og advarsler i almindelig chat"
- name="script_errors_as_chat" />
- <text type="string" length="1" name="text_box3">
- Chat vindue:
- </text>
- <spinner label="Udfas chat efter" name="fade_chat_time" label_width="90" width="140" />
- <text type="string" length="1" name="text_box4" left="292" >
- (sekunder)
- </text>
- <spinner left="350" name="max_chat_count"/>
- <text type="string" length="1" name="text_box5" left="415">
- (linier)
- </text>
- <slider label="Gennemsigtighed" name="console_opacity" />
- <check_box label="Brug fuldskærms bredde (Kræver genstart)"
- name="chat_full_width_check" />
- <text type="string" length="1" name="text_box6">
- Chat indstillinger:
- </text>
- <check_box label="Luk chat efter tryk på enter" name="close_chat_on_return_check" />
- <check_box label="Piletaster flytter altid figur under chat"
- name="arrow_keys_move_avatar_check" />
- <check_box label="Vis klokkeslæt i lokal chat" name="show_timestamps_check" />
- <check_box label="Afspil skrive animation ved chat" name="play_typing_animation" />
- <text type="string" length="1" name="text_box7">
- Chat talebobler:
- </text>
- <check_box label="Vis chat bobler" name="bubble_text_chat" />
- <slider label="Gennemsigtighed" name="bubble_chat_opacity" />
+ <color_swatch label="Dig" name="user"/>
+ <text name="text_box1">
+ Dig
+ </text>
+ <color_swatch label="Andre" name="agent"/>
+ <text name="text_box2">
+ Andre
+ </text>
+ <color_swatch label="IM" name="im"/>
+ <text name="text_box3">
+ IM
+ </text>
+ <color_swatch label="System" name="system"/>
+ <text name="text_box4">
+ System
+ </text>
+ <color_swatch label="Fejl" name="script_error"/>
+ <text name="text_box5">
+ Fejl
+ </text>
+ <color_swatch label="Objekter" name="objects"/>
+ <text name="text_box6">
+ Objekter
+ </text>
+ <color_swatch label="Ejer" name="owner"/>
+ <text name="text_box7">
+ Ejer
+ </text>
+ <color_swatch label="URL&apos;er" name="links"/>
+ <text name="text_box9">
+ URL&apos;er
+ </text>
+ <check_box initial_value="true" label="Afspil skrive animation ved chat" name="play_typing_animation"/>
+ <check_box label="Send e-mail til mig når jeg modtager IM og er offline" name="send_im_to_email"/>
</panel>
diff --git a/indra/newview/skins/default/xui/da/panel_preferences_general.xml b/indra/newview/skins/default/xui/da/panel_preferences_general.xml
index 74a1ab1d7a..ed23a9a706 100644
--- a/indra/newview/skins/default/xui/da/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/da/panel_preferences_general.xml
@@ -1,118 +1,85 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Generelt" name="general_panel">
- <radio_group name="default_start_location">
- <radio_item name="MyHome" tool_tip="Log ind til min hjemme lokation som standard.">
- Mit hjem
- </radio_item>
- <radio_item name="MyLastLocation" tool_tip="Log ind til min sidste lokation som standard.">
- Min sidste lokation
- </radio_item>
- </radio_group>
- <check_box label="Vis start lokation på login billedet" name="show_location_checkbox" />
+ <combo_box name="start_location_combo">
+ <combo_box.item name="MyHome" tool_tip="Log ind til min hjemme lokation som standard." label="Mit hjem" />
+ <combo_box.item name="MyLastLocation" tool_tip="Log ind til min sidste lokation som standard." label="Min sidste lokation" />
+ </combo_box>
+ <check_box label="Vis start lokation på login billedet" name="show_location_checkbox"/>
<combo_box name="fade_out_combobox">
- <combo_item name="Never">
- Aldrig
- </combo_item>
- <combo_item name="Show Temporarily">
- Vis midlertidigt
- </combo_item>
- <combo_item name="Always">
- Altid
- </combo_item>
+ <combo_box.item name="Never" label="Aldrig"/>
+ <combo_box.item name="Show Temporarily" label="Vis midlertidigt"/>
+ <combo_box.item name="Always" label="Altid"/>
</combo_box>
- <check_box label="Små avatar navne" name="small_avatar_names_checkbox" />
- <check_box label="Skjul mit navn på min skærm" name="show_my_name_checkbox" />
- <text type="string" length="1" name="group_titles_textbox">
+ <check_box label="Små avatar navne" name="small_avatar_names_checkbox"/>
+ <check_box label="Skjul mit navn på min skærm" name="show_my_name_checkbox"/>
+ <text name="group_titles_textbox">
Gruppe titler:
</text>
- <check_box label="Skjul alle gruppe titler" name="show_all_title_checkbox" />
- <check_box label="Gem min gruppe titel" name="show_my_title_checkbox" />
- <color_swatch label="" name="effect_color_swatch" tool_tip="Klik for at åbne farvevælger" />
- <text type="string" length="1" name="UI Size:">
+ <check_box label="Skjul alle gruppe titler" name="show_all_title_checkbox"/>
+ <check_box label="Gem min gruppe titel" name="show_my_title_checkbox"/>
+ <color_swatch label="" name="effect_color_swatch" tool_tip="Klik for at åbne farvevælger"/>
+ <text name="UI Size:">
UI Størrelse:
</text>
- <check_box label="Brug opløsnings uafhængig skalering" name="ui_auto_scale" />
- <spinner label="Tid før inaktiv:" name="afk_timeout_spinner" />
- <check_box label="Rotér mini-kort" name="rotate_mini_map_checkbox" />
- <check_box label="Giv besked når Linden dollars (L$) bliver brugt eller modtaget"
- name="notify_money_change_checkbox" />
- <check_box label="Brug standard farve vælger" name="use_system_color_picker_checkbox"
- tool_tip="Brug dit systems standard farve vælger i stedet for den der er indbygget i Second Life." />
- <check_box label="Vis Søg i øverste højre hjørne" name="show_search_panel"
- tool_tip="Vis indbygget søgepanel." />
- <text type="string" length="1" name="start_location_textbox">
+ <check_box label="Brug opløsnings uafhængig skalering" name="ui_auto_scale"/>
+ <spinner label="Tid før inaktiv:" name="afk_timeout_spinner"/>
+ <check_box label="Giv besked når Linden dollars (L$) bliver brugt eller modtaget" name="notify_money_change_checkbox"/>
+ <text name="maturity_desired_label">
+ Rating:
+ </text>
+ <text name="maturity_desired_prompt">
+ Jeg ønsker adgang til inhold med rating:
+ </text>
+ <combo_box name="maturity_desired_combobox">
+ <combo_box.item name="Desired_Adult" label="PG, Mature og Adult"/>
+ <combo_box.item name="Desired_Mature" label="PG and Mature"/>
+ <combo_box.item name="Desired_PG" label="PG"/>
+ </combo_box>
+ <text name="maturity_desired_textbox">
+ PG
+ </text>
+ <text name="start_location_textbox">
Start lokation:
</text>
- <text type="string" length="1" name="show_names_textbox">
+ <text name="show_names_textbox">
Vis navne:
</text>
- <text type="string" length="1" name="effects_color_textbox">
+ <text name="effects_color_textbox">
Farve til mine effekter:
</text>
- <text type="string" length="1" name="seconds_textbox">
+ <text name="seconds_textbox">
sekunder
</text>
- <text type="string" length="1" name="crash_report_textbox">
+ <text name="crash_report_textbox">
Nedbrudsrapporter:
</text>
- <text type="string" length="1" name="language_textbox">
+ <text name="language_textbox">
Sprog:
</text>
- <text type="string" length="1" name="language_textbox2">
+ <text name="language_textbox2">
(Kræver genstart for at virke optimalt)
</text>
<string name="region_name_prompt">
&lt;Skriv regions navn&gt;
</string>
<combo_box name="crash_behavior_combobox">
- <combo_item type="string" length="1" name="Askbeforesending">
- Bed om bekræftigelse
- </combo_item>
- <combo_item type="string" length="1" name="Alwayssend">
- Send altid
- </combo_item>
- <combo_item type="string" length="1" name="Neversend">
- Send aldrig
- </combo_item>
+ <combo_box.item name="Askbeforesending" label="Bed om bekræftigelse"/>
+ <combo_box.item name="Alwayssend" label="Send altid"/>
+ <combo_box.item name="Neversend" label="Send aldrig"/>
</combo_box>
<combo_box name="language_combobox">
- <combo_item type="string" length="1" name="System Default Language">
- System standard
- </combo_item>
- <combo_item type="string" length="1" name="English">
- English (Engelsk)
- </combo_item>
- <combo_item type="string" length="1" name="Danish">
- Dansk - Beta
- </combo_item>
- <combo_item type="string" length="1" name="Deutsch(German)">
- Deutsch (Tysk) - Beta
- </combo_item>
- <combo_item type="string" length="1" name="Spanish">
- Español (Spansk) - Beta
- </combo_item>
- <combo_item type="string" length="1" name="French">
- Français (Fransk) - Beta
- </combo_item>
- <combo_item type="string" length="1" name="Hungarian">
- Magyar (Ungarsk) - Beta
- </combo_item>
- <combo_item type="string" length="1" name="Polish">
- Polski (Polsk) - Beta
- </combo_item>
- <combo_item type="string" length="1" name="Portugese">
- Portugués (Portugisisk) - Beta
- </combo_item>
- <combo_item type="string" length="1" name="Chinese">
- 中文 (简体) (Kinesisk) - Beta
- </combo_item>
- <combo_item type="string" length="1" name="(Japanese)">
- 日本語 (Japansk) - Beta
- </combo_item>
- <combo_item type="string" length="1" name="(Korean)">
- 한국어 (Koreansk) - Beta
- </combo_item>
+ <combo_box.item name="System Default Language" label="System standard"/>
+ <combo_box.item name="English" label="English (Engelsk)"/>
+ <combo_box.item name="Danish" label="Dansk - Beta"/>
+ <combo_box.item name="Deutsch(German)" label="Deutsch (Tysk) - Beta"/>
+ <combo_box.item name="Spanish" label="Español (Spansk) - Beta"/>
+ <combo_box.item name="French" label="Français (Fransk) - Beta"/>
+ <combo_box.item name="Hungarian" label="Magyar (Ungarsk) - Beta"/>
+ <combo_box.item name="Polish" label="Polski (Polsk) - Beta"/>
+ <combo_box.item name="Portugese" label="Portugués (Portugisisk) - Beta"/>
+ <combo_box.item name="Chinese" label="中文 (简体) (Kinesisk) - Beta"/>
+ <combo_box.item name="(Japanese)" label="日本語 (Japansk) - Beta"/>
+ <combo_box.item name="(Korean)" label="한국어 (Koreansk) - Beta"/>
</combo_box>
- <check_box label="Del sprog med objekter" name="language_is_public"
- tool_tip="Dette lader objekter i verden vide hvad dit foretrukne sprog er." />
+ <check_box label="Del sprog med objekter" name="language_is_public" tool_tip="Dette lader objekter i verden vide hvad dit foretrukne sprog er."/>
</panel>
diff --git a/indra/newview/skins/default/xui/da/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/da/panel_preferences_graphics1.xml
index 5ebab1778f..4dac7be413 100644
--- a/indra/newview/skins/default/xui/da/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/da/panel_preferences_graphics1.xml
@@ -2,80 +2,63 @@
<panel label="Grafik" name="Display panel">
<button label="?" name="GraphicsPreferencesHelpButton" />
<check_box label="Kør Second Life i et vindue" name="windowed mode" />
- <text_editor type="string" length="1" name="FullScreenInfo">
+ <text_editor name="FullScreenInfo">
Hvis dette ikke er valgt kører Second Life i Fuld skærm.
</text_editor>
- <text type="string" length="1" name="WindowSizeLabel">
+ <text name="WindowSizeLabel">
Opløsning:
</text>
<combo_box name="windowsize combo">
- <combo_item type="string" length="1" name="640x480">
- 640x480
- </combo_item>
- <combo_item type="string" length="1" name="800x600">
- 800x600
- </combo_item>
- <combo_item type="string" length="1" name="720x480">
- 720x480 (NTSC)
- </combo_item>
- <combo_item type="string" length="1" name="768x576">
- 768x576 (PAL)
- </combo_item>
- <combo_item type="string" length="1" name="1024x768">
- 1024x768
- </combo_item>
+ <combo_box.item name="640x480" label="640x480" />
+ <combo_box.item name="800x600" label="800x600" />
+ <combo_box.item name="720x480" label="720x480 (NTSC)" />
+ <combo_box.item name="768x576" label="768x576 (PAL)" />
+ <combo_box.item name="1024x768" label="1024x768" />
</combo_box>
- <text type="string" length="1" name="DisplayResLabel">
+ <text name="DisplayResLabel">
Skærm opløsning:
</text>
- <text type="string" length="1" name="AspectRatioLabel1" tool_tip="bredde / højde">
+ <text name="AspectRatioLabel1" tool_tip="bredde / højde">
Format:
</text>
<combo_box name="aspect_ratio" tool_tip="bredde/ højde">
- <combo_item type="string" length="1" name="4:3(StandardCRT)">
- 4:3 (Standard CRT)
- </combo_item>
- <combo_item type="string" length="1" name="5:4(1280x1024LCD)">
- 5:4 (1280x1024 LCD)
- </combo_item>
- <combo_item type="string" length="1" name="8:5(Widescreen)">
- 8:5 (Widescreen)
- </combo_item>
- <combo_item type="string" length="1" name="16:9(Widescreen)">
- 16:9 (Widescreen)
- </combo_item>
+ <combo_box.item name="4:3(StandardCRT)" label="4:3 (Standard CRT)" />
+ <combo_box.item name="5:4(1280x1024LCD)" label="5:4 (1280x1024 LCD)" />
+ <combo_box.item name="8:5(Widescreen)" label="8:5 (Widescreen)" />
+ <combo_box.item name="16:9(Widescreen)" label="16:9 (Widescreen)" />
</combo_box>
<check_box label="Auto-detect format" name="aspect_auto_detect" />
- <text type="string" length="1" name="HigherText">
+ <text name="HigherText">
Kvalitet og
</text>
- <text type="string" length="1" name="QualityText">
+ <text name="QualityText">
Ydelse:
</text>
- <text type="string" length="1" name="FasterText">
+ <text name="FasterText">
Hurtigere
</text>
- <text type="string" length="1" name="ShadersPrefText">
+ <text name="ShadersPrefText">
Lav
</text>
- <text type="string" length="1" name="ShadersPrefText2">
+ <text name="ShadersPrefText2">
Middel
</text>
- <text type="string" length="1" name="ShadersPrefText3">
+ <text name="ShadersPrefText3">
Høj
</text>
- <text type="string" length="1" name="ShadersPrefText4">
+ <text name="ShadersPrefText4">
Ultra
</text>
- <text type="string" length="1" name="HigherText2">
+ <text name="HigherText2">
Højere
</text>
- <text type="string" length="1" name="QualityText2">
+ <text name="QualityText2">
Kvalitet
</text>
<slider label="" name="QualityPerformanceSelection" />
<check_box label="Manuelt" name="CustomSettings" />
- <text type="string" length="1" name="ShadersText">
+ <panel name="CustomGraphics Panel">
+ <text name="ShadersText">
Overflader:
</text>
<check_box label="Glatte flader og skin" name="BumpShiny" />
@@ -83,39 +66,31 @@
tool_tip="Ved at slå dette valg fra, kan det forhindres at visse grafikkort drivere crasher." />
<check_box label="Atmosfæriske flader" name="WindLightUseAtmosShaders" />
<check_box label="Reflektioner i vand" name="Reflections" />
- <text type="string" length="1" name="ReflectionDetailText">
+ <text name="ReflectionDetailText">
Spejlnings detaljer:
</text>
<radio_group name="ReflectionDetailRadio">
- <radio_item type="string" length="1" name="0">
- Terræn og træer
- </radio_item>
- <radio_item type="string" length="1" name="1">
- Alle statiske objekter
- </radio_item>
- <radio_item type="string" length="1" name="2">
- Alle avatarer og objekter
- </radio_item>
- <radio_item type="string" length="1" name="3">
- Alt
- </radio_item>
+ <radio_item name="0" label="Terræn og træer" />
+ <radio_item name="1" label="Alle statiske objekter" />
+ <radio_item name="2" label="Alle avatarer og objekter" />
+ <radio_item name="3" label="Alt" />
</radio_group>
- <text type="string" length="1" name="AvatarRenderingText">
+ <text name="AvatarRenderingText">
Avatar gengivelse
</text>
<check_box label="Mini-figurer på lang afstand" name="AvatarImpostors" />
<check_box label="Hardware Skinning" name="AvatarVertexProgram" />
<check_box label="Avatar tøj" name="AvatarCloth" />
- <text type="string" length="1" name="DrawDistanceMeterText1">
+ <text name="DrawDistanceMeterText1">
m
</text>
- <text type="string" length="1" name="DrawDistanceMeterText2">
+ <text name="DrawDistanceMeterText2">
m
</text>
<slider label="Maks. visnings-afstand:" name="DrawDistance" />
<slider label="Maks. antal partikler:" name="MaxParticleCount" />
<slider label="Efterbehandlingskvalitet:" name="RenderPostProcess" />
- <text type="string" length="1" name="MeshDetailText">
+ <text name="MeshDetailText">
Netmaske detaljer:
</text>
<slider label=" Objekter:" name="ObjectMeshDetail" />
@@ -124,56 +99,49 @@
<slider label=" Avatarer:" name="AvatarMeshDetail" />
<slider label=" Terræn:" name="TerrainMeshDetail" />
<slider label=" Himmel:" name="SkyMeshDetail" />
- <text type="string" length="1" name="PostProcessText">
+ <text name="PostProcessText">
Lav
</text>
- <text type="string" length="1" name="ObjectMeshDetailText">
+ <text name="ObjectMeshDetailText">
Lav
</text>
- <text type="string" length="1" name="FlexibleMeshDetailText">
+ <text name="FlexibleMeshDetailText">
Lav
</text>
- <text type="string" length="1" name="TreeMeshDetailText">
+ <text name="TreeMeshDetailText">
Lav
</text>
- <text type="string" length="1" name="AvatarMeshDetailText">
+ <text name="AvatarMeshDetailText">
Lav
</text>
- <text type="string" length="1" name="TerrainMeshDetailText">
+ <text name="TerrainMeshDetailText">
Lav
</text>
- <text type="string" length="1" name="SkyMeshDetailText">
+ <text name="SkyMeshDetailText">
Lav
</text>
- <text type="string" length="1" name="LightingDetailText">
+ <text name="LightingDetailText">
Lys detaljer:
</text>
<radio_group name="LightingDetailRadio">
- <radio_item type="string" length="1" name="SunMoon">
- Kun sol og måne
- </radio_item>
- <radio_item type="string" length="1" name="LocalLights">
- Lys i nærheden
- </radio_item>
+ <radio_item name="SunMoon" label="Kun sol og måne" />
+ <radio_item name="LocalLights" label="Lys i nærheden" />
</radio_group>
- <text type="string" length="1" name="TerrainDetailText">
+ <text name="TerrainDetailText">
Terræn detaljer:
</text>
<radio_group name="TerrainDetailRadio">
- <radio_item type="string" length="1" name="0">
- Lav
- </radio_item>
- <radio_item type="string" length="1" name="2">
- Høj
- </radio_item>
+ <radio_item name="0" label="Lav" />
+ <radio_item name="2" label="Høj" />
</radio_group>
+ </panel>
<button label="Anbefalede indstillinger" name="Defaults" />
<button label="Hardware valg" label_selected="Hardware Options"
name="GraphicsHardwareButton" />
- <string name="resolution_format">
+ <panel.string name="resolution_format">
[RES_X] x [RES_Y]
- </string>
- <string name="aspect_ratio_text">
+ </panel.string>
+ <panel.string name="aspect_ratio_text">
[NUM]:[DEN]
- </string>
+ </panel.string>
</panel>
diff --git a/indra/newview/skins/default/xui/da/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/da/panel_preferences_privacy.xml
new file mode 100644
index 0000000000..c62beac899
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/panel_preferences_privacy.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel label="Kommunikation" name="im">
+ <text name="text_box">
+ Min online status:
+ </text>
+ <check_box label="Kun mine venner og grupper kan se når jeg er online"
+ name="online_visibility" />
+ <text name="text_box2">
+ IM valg:
+ </text>
+ <string name="log_in_to_change">
+ Log ind for at ændre
+ </string>
+ <check_box label="Send IM til E-mail ([EMAIL])" name="send_im_to_email" />
+ <check_box label="Inkludér IM i chat vindue" name="include_im_in_chat_console" />
+ <check_box label="Vis tidslinje i private beskeder (IM)" name="show_timestamps_check" />
+ <check_box label="Vis når venner logger på" name="friends_online_notify_checkbox" />
+ <text name="text_box3">
+ Optaget autosvar:
+ </text>
+ <text name="text_box4">
+ Log funktioner:
+ </text>
+ <check_box label="Gem en log af privat beskeder (IM) på min computer"
+ name="log_instant_messages" />
+ <check_box label="Vis klokkeslæt i log" name="log_instant_messages_timestamp" />
+ <check_box label="Vis slutningen af sidste samtale i beskeder" name="log_show_history" />
+ <check_box label="Gem log af lokal chat på min computer" name="log_chat" />
+ <check_box label="Vis klokkeslæt i lokat chat log" name="log_chat_timestamp" />
+ <check_box label="Vis indkommende IM i lokal chat log" name="log_chat_IM" />
+ <check_box label="Inkludér dato med klokkeslæt" name="log_date_timestamp" />
+ <button label="Ændre sti" label_selected="Ændre sti" name="log_path_button" left="150"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/da/panel_preferences_setup.xml b/indra/newview/skins/default/xui/da/panel_preferences_setup.xml
new file mode 100644
index 0000000000..e826e65315
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/panel_preferences_setup.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Input &amp; kamera" name="Input panel">
+ <text name=" Mouselook Options:">
+ Førstepersons valg:
+ </text>
+ <text name=" Mouse Sensitivity:">
+ Mus følsomhed:
+ </text>
+ <check_box label="Omvendt mus" name="invert_mouse"/>
+ <text name=" Auto Fly Options:">
+ Auto flyv valg:
+ </text>
+ <check_box label="Flyv/Land ved at holde Page Up/Down nede" name="automatic_fly"/>
+ <text name=" Camera Options:">
+ Kamera valg:
+ </text>
+ <text name="camera_fov_label">
+ Camera synsvinkel:
+ </text>
+ <text name="Camera Follow Distance:">
+ Kamera følge-afstand:
+ </text>
+ <check_box label="Fokusér kamera automatisk ved redigering" name="edit_camera_movement" tool_tip="Fokusér kamera automatisk når du går ind og ud af redigering."/>
+ <check_box label="Fokusér kamera automatisk ved udseende" name="appearance_camera_movement" tool_tip="Lad kameraet automatisk placere sig når du er i redigering"/>
+ <text name="text2">
+ Avatar skærm funktioner:
+ </text>
+ <check_box label="Vis avatar i førsteperson" name="first_person_avatar_visible"/>
+ <button label="Joystick opsætning" name="joystick_setup_button"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/da/panel_preferences_sound.xml b/indra/newview/skins/default/xui/da/panel_preferences_sound.xml
new file mode 100644
index 0000000000..ce77018f72
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/panel_preferences_sound.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Lyde" name="Preference Media panel">
+ <slider label="Generel" name="System Volume"/>
+ <check_box initial_value="true" label="Sluk lyd når vinduet er minimeret" name="mute_when_minimized"/>
+ <slider label="Omgivelser" name="Wind Volume"/>
+ <slider label="Knapper" name="UI Volume"/>
+ <slider label="Media" name="Media Volume"/>
+ <slider label="Effekter" name="SFX Volume"/>
+ <slider label="Musik" name="Music Volume"/>
+ <check_box label="Tale" name="enable_voice_check"/>
+ <slider label="Tale" name="Voice Volume"/>
+ <text name="Listen from">
+ Hør stemmer fra:
+ </text>
+ <radio_group name="ear_location">
+ <radio_item label="Kamera position" name="0"/>
+ <radio_item label="Avatar position" name="1"/>
+ </radio_group>
+ <button label="Input/Output enheder" name="device_settings_btn"/>
+ <panel label="Enhedsopsætning" name="device_settings_panel">
+ <panel.string name="default_text">
+ Standard
+ </panel.string>
+ <text name="Input">
+ Input
+ </text>
+ <text name="My volume label">
+ Min lydstyrke:
+ </text>
+ <slider_bar initial_value="1.0" name="mic_volume_slider" tool_tip="Ændre lydstyrke med denne skyder"/>
+ <text name="wait_text">
+ Vent venligst
+ </text>
+ <text name="Output">
+ Output
+ </text>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/da/panel_region_covenant.xml b/indra/newview/skins/default/xui/da/panel_region_covenant.xml
index 63a2f90e36..394664f1f1 100644
--- a/indra/newview/skins/default/xui/da/panel_region_covenant.xml
+++ b/indra/newview/skins/default/xui/da/panel_region_covenant.xml
@@ -1,39 +1,67 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Covenant" name="Covenant">
+ <text name="estate_section_lbl">
+ Estate:
+ </text>
+ <text name="estate_name_lbl">
+ Navn:
+ </text>
+ <text name="estate_name_text">
+ mainland
+ </text>
+ <text name="estate_owner_lbl">
+ Ejer:
+ </text>
+ <text name="estate_owner_text">
+ (ingen)
+ </text>
+ <text name="covenant_timestamp_text">
+ Sidst ændret Ons Dec 31 16:00:00 1969
+ </text>
+ <button label="?" name="covenant_help"/>
+ <text_editor name="covenant_editor">
+ Der er ikke angivet nogen regler for denne estate.
+ </text_editor>
+ <button label="Reset" name="reset_covenant"/>
<text name="covenant_help_text">
- Ændringer i regel information vil blive vist i alle parceller til denne estate.
+ Ændringer i regler vil blive vist i alle parceller til denne estate.
</text>
- <text name="region_name_lbl">
+ <text name="covenant_instructions">
+ Træk og slip et notecard her for at ændre regler for denne estate.
+ </text>
+ <text name="region_section_lbl">
Region:
</text>
+ <text name="region_name_lbl">
+ Navn:
+ </text>
<text name="region_name_text">
- (ukendt)
+ leyla
</text>
- <text name="estate_name_lbl">
- Estate:
+ <text name="region_landtype_lbl">
+ Type:
</text>
- <text name="estate_name_text">
- (ukendt)
+ <text name="region_landtype_text">
+ Mainland / Homestead
</text>
- <text name="estate_owner_lbl">
- Estate ejer:
+ <text name="region_maturity_lbl">
+ Rating:
</text>
- <text name="estate_owner_text">
- (ukendt)
+ <text name="region_maturity_text">
+ Adult
+ </text>
+ <text name="resellable_lbl">
+ Videresalg:
</text>
<text name="resellable_clause">
- Valgfrit om købt land i denne region må sælges videre
+ Land i denne region må ikke sælges videre.
</text>
- <text name="changeable_clause">
- Valgfrit om købt land i denne region må deles eller samles.
+ <text name="changeable_lbl">
+ Opdel:
</text>
- <text name="covenent_instructions">
- Træk og slip et notecard her for at ændre regler for dette estate.
+ <text name="changeable_clause">
+ Land i denne region må ikke deles eller samles.
</text>
- <text_editor name="covenant_editor">
- Henter...
- </text_editor>
- <button label="Reset" name="reset_covenant" />
<string name="can_resell">
Købt land i denne region må sælges videre
</string>
@@ -46,5 +74,4 @@
<string name="can_not_change">
Købt land i denne region må ikke deles eller samles.
</string>
- <button label="?" name="covenant_help" />
</panel>
diff --git a/indra/newview/skins/default/xui/da/panel_region_estate.xml b/indra/newview/skins/default/xui/da/panel_region_estate.xml
index 108763d544..5d0799cab9 100644
--- a/indra/newview/skins/default/xui/da/panel_region_estate.xml
+++ b/indra/newview/skins/default/xui/da/panel_region_estate.xml
@@ -23,7 +23,7 @@ regioner i dette estate.
<slider label="Fase" name="sun_hour_slider" />
<check_box label="Tillad offentlig adgang" name="externally_visible_check" />
<button label="?" name="externally_visible_help" />
- <text type="string" length="1" name="Only Allow">
+ <text name="Only Allow">
Begræns adgang til:
</text>
<check_box label="Beboere med betalingsoplysninger" name="limit_payment"
@@ -34,7 +34,7 @@ regioner i dette estate.
<button label="?" name="voice_chat_help" />
<check_box label="Tillad direkte teleport" name="allow_direct_teleport" />
<button label="?" name="allow_direct_teleport_help" />
- <text name="abuse_email_text">
+ <text name="abuse_email_text" width="260">
Send beskeder misbrug til email adresse:
</text>
<string name="email_unsupported">
diff --git a/indra/newview/skins/default/xui/da/panel_region_general.xml b/indra/newview/skins/default/xui/da/panel_region_general.xml
index 5f0e71f63d..6ffe1f34f3 100644
--- a/indra/newview/skins/default/xui/da/panel_region_general.xml
+++ b/indra/newview/skins/default/xui/da/panel_region_general.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Region" name="General">
<text name="region_text_lbl">
Region:
@@ -12,35 +12,42 @@
<text name="version_channel_text">
ukendt
</text>
- <check_box label="Blokér for redigering af terræn" name="block_terraform_check" />
- <button label="?" name="terraform_help" />
- <check_box label="Blokér for flyvning" name="block_fly_check" />
- <button label="?" name="fly_help" />
- <check_box label="Tillad skader" name="allow_damage_check" />
- <button label="?" name="damage_help" />
- <check_box label="Begræns skubning" name="restrict_pushobject" />
- <button label="?" name="restrict_pushobject_help" />
- <check_box label="Tillad at sælge land" name="allow_land_resell_check" />
- <button label="?" name="land_resell_help" />
- <check_box label="Tillad at samle/dele land" name="allow_parcel_changes_check" />
- <button label="?" name="parcel_changes_help" />
- <check_box label="Blokér visning af land i Søgning" name="block_parcel_search_check"
- tool_tip="Lad beboere se denne region og dens parceller i søgeresultater" />
- <button label="?" name="parcel_search_help" />
- <spinner label="Max besøgende" name="agent_limit_spin" />
- <button label="?" name="agent_limit_help" />
- <spinner label="Objekt bonus" name="object_bonus_spin" />
- <button label="?" name="object_bonus_help" />
+ <text name="region_type_lbl">
+ Type:
+ </text>
+ <text name="region_type">
+ ukendt
+ </text>
+ <check_box label="Blokér for redigering af terræn" name="block_terraform_check"/>
+ <button label="?" name="terraform_help"/>
+ <check_box label="Blokér for flyvning" name="block_fly_check"/>
+ <button label="?" name="fly_help"/>
+ <check_box label="Tillad skader" name="allow_damage_check"/>
+ <button label="?" name="damage_help"/>
+ <check_box label="Begræns skubning" name="restrict_pushobject"/>
+ <button label="?" name="restrict_pushobject_help"/>
+ <check_box label="Tillad at sælge land" name="allow_land_resell_check"/>
+ <button label="?" name="land_resell_help"/>
+ <check_box label="Tillad at samle/dele land" name="allow_parcel_changes_check"/>
+ <button label="?" name="parcel_changes_help"/>
+ <check_box label="Blokér visning af land i Søgning" name="block_parcel_search_check" tool_tip="Lad beboere se denne region og dens parceller i søgeresultater"/>
+ <button label="?" name="parcel_search_help"/>
+ <spinner label="Max besøgende" name="agent_limit_spin"/>
+ <button label="?" name="agent_limit_help"/>
+ <spinner label="Objekt bonus" name="object_bonus_spin"/>
+ <button label="?" name="object_bonus_help"/>
<text label="Indhold" name="access_text">
- Indhold:
+ Rating:
</text>
-
-
-
- <button label="?" name="access_help" />
- <button label="Gem" name="apply_btn" />
- <button label="Send en beboer hjem ..." name="kick_btn" />
- <button label="Send alle beboere hjem..." name="kick_all_btn" />
- <button label="Send besked til region..." name="im_btn" />
- <button label="Vedligehold telehub..." name="manage_telehub_btn" />
+ <combo_box label="Mature" name="access_combo">
+ <combo_box.item label="Adult" name="Adult"/>
+ <combo_box.item label="Mature" name="Mature"/>
+ <combo_box.item label="PG" name="PG"/>
+ </combo_box>
+ <button label="?" name="access_help"/>
+ <button label="Gem" name="apply_btn"/>
+ <button label="Send en beboer hjem ..." name="kick_btn"/>
+ <button label="Send alle beboere hjem..." name="kick_all_btn"/>
+ <button label="Send besked til region..." name="im_btn"/>
+ <button label="Vedligehold telehub..." name="manage_telehub_btn"/>
</panel>
diff --git a/indra/newview/skins/default/xui/da/panel_region_terrain.xml b/indra/newview/skins/default/xui/da/panel_region_terrain.xml
index 4ff81112d3..14ef0060b1 100644
--- a/indra/newview/skins/default/xui/da/panel_region_terrain.xml
+++ b/indra/newview/skins/default/xui/da/panel_region_terrain.xml
@@ -13,9 +13,9 @@
<spinner label="Max sænkning af land" name="terrain_lower_spin" />
<button label="?" name="terrain_lower_help" />
<check_box label="Benyt solopsætning fra estate" name="use_estate_sun_check" />
- <button label="?" name="use_estate_sun_help" />
+ <button label="?" name="use_estate_sun_help" left="430"/>
<check_box label="Fast sol-position" name="fixed_sun_check" />
- <button label="?" name="fixed_sun_help" />
+ <button label="?" name="fixed_sun_help" left="430"/>
<slider label="Fase" name="sun_hour_slider" />
<button label="Gem" name="apply_btn" />
<button label="Download RAW terræn fil..." name="download_raw_btn"
diff --git a/indra/newview/skins/default/xui/da/panel_scrolling_param.xml b/indra/newview/skins/default/xui/da/panel_scrolling_param.xml
index 5309ca589f..99f61b938b 100644
--- a/indra/newview/skins/default/xui/da/panel_scrolling_param.xml
+++ b/indra/newview/skins/default/xui/da/panel_scrolling_param.xml
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="LLScrollingPanelParam">
- <text type="string" length="1" name="Loading...">
+ <text name="Loading...">
Henter...
</text>
- <text type="string" length="1" name="Loading...2">
+ <text name="Loading...2">
Henter...
</text>
<button label="" label_selected="" name="less" />
diff --git a/indra/newview/skins/default/xui/da/panel_status_bar.xml b/indra/newview/skins/default/xui/da/panel_status_bar.xml
index 7bc66b1101..20e72827f2 100644
--- a/indra/newview/skins/default/xui/da/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/da/panel_status_bar.xml
@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="status">
- <text type="string" length="1" name="ParcelNameText"
+ <text name="ParcelNameText"
tool_tip="Navn på det land/parcel som du står på. Klik på teksten for yderligere info.">
parcel name goes here
</text>
- <text type="string" length="1" name="BalanceText" tool_tip="Konto balance">
+ <text name="BalanceText" tool_tip="Konto balance">
Henter...
</text>
<button label="" label_selected="" name="buycurrency" tool_tip="Køb valuta" />
- <text type="string" length="12" name="TimeText" tool_tip="Nuværende Second Life tid">
+ <text name="TimeText" tool_tip="Nuværende [SECOND_LIFE] tid">
12:00
</text>
<string name="StatBarDaysOfWeek">
@@ -19,7 +19,7 @@
</string>
<button label="" label_selected="" name="scriptout" tool_tip="Script advarsler og fejl" />
<button label="" label_selected="" name="health" tool_tip="Helbred" />
- <text type="string" length="1" name="HealthText" tool_tip="Helbred">
+ <text name="HealthText" tool_tip="Helbred">
100%
</text>
<button label="" label_selected="" name="no_fly" tool_tip="Flyvning ikke tilladt" />
@@ -33,8 +33,8 @@
tool_tip="Stemme chat ikke tilgængelig" />
<button label="" label_selected="" name="buyland" tool_tip="Køb denne parcel" />
<button label="" name="menubar_search_bevel_bg" />
- <line_editor label="Søg" name="search_editor" tool_tip="Søg Second Life" />
- <button label="" label_selected="" name="search_btn" tool_tip="Søg Second Life" />
+ <line_editor label="Søg" name="search_editor" tool_tip="Søg [SECOND_LIFE]" />
+ <button label="" label_selected="" name="search_btn" tool_tip="Søg [SECOND_LIFE]" />
<string name="packet_loss_tooltip">
Packet Loss
</string>
diff --git a/indra/newview/skins/default/xui/da/panel_world_map.xml b/indra/newview/skins/default/xui/da/panel_world_map.xml
new file mode 100644
index 0000000000..bea5ea6b36
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/panel_world_map.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="world_map">
+ <panel.string name="Loading">
+ Henter...
+ </panel.string>
+ <panel.string name="InvalidLocation">
+ Ugyldig lokation
+ </panel.string>
+ <panel.string name="world_map_north">
+ N
+ </panel.string>
+ <panel.string name="world_map_east">
+ Ø
+ </panel.string>
+ <panel.string name="world_map_west">
+ V
+ </panel.string>
+ <panel.string name="world_map_south">
+ S
+ </panel.string>
+ <panel.string name="world_map_southeast">
+ SØ
+ </panel.string>
+ <panel.string name="world_map_northeast">
+ NØ
+ </panel.string>
+ <panel.string name="world_map_southwest">
+ SV
+ </panel.string>
+ <panel.string name="world_map_northwest">
+ NV
+ </panel.string>
+ <text label="N" name="floater_map_north" text="N">
+ N
+ </text>
+ <text label="Ø" name="floater_map_east" text="Ø">
+ Ø
+ </text>
+ <text label="V" name="floater_map_west" text="V">
+ V
+ </text>
+ <text label="S" name="floater_map_south" text="S">
+ S
+ </text>
+ <text label="SØ" name="floater_map_southeast" text="SØ">
+ SØ
+ </text>
+ <text label="NØ" name="floater_map_northeast" text="NØ">
+ NØ
+ </text>
+ <text label="SV" name="floater_map_southwest" text="SV">
+ SV
+ </text>
+ <text label="NV" name="floater_map_northwest" text="NV">
+ NV
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/da/strings.xml b/indra/newview/skins/default/xui/da/strings.xml
index bd34d39993..fda01d2f59 100644
--- a/indra/newview/skins/default/xui/da/strings.xml
+++ b/indra/newview/skins/default/xui/da/strings.xml
@@ -1,8 +1,24 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- This file contains strings that used to be hardcoded in the source.
+ It is only for those strings which do not belong in a floater.
+ For example, the strings used in avatar chat bubbles, and strings
+ that are returned from one component and may appear in many places-->
<strings>
+ <string name="SUPPORT_SITE">
+ Second Life Support Portal
+ </string>
+ <string name="StartupDetectingHardware">
+ Detekterer hardware...
+ </string>
+ <string name="StartupLoading">
+ Indlæser
+ </string>
<string name="LoginInProgress">
Logger p. [APP_NAME] kan virke laast. Vent venligst.
</string>
+ <string name="LoginInProgressNoFrozen">
+ Logger på...
+ </string>
<string name="LoginAuthenticating">
Validerer adgang
</string>
@@ -21,11 +37,14 @@
<string name="LoginInitializingMultimedia">
Klargør multimedia...
</string>
+ <string name="LoginInitializingFonts">
+ Indlæser fonts...
+ </string>
<string name="LoginVerifyingCache">
- Verificérer cache filer (kan tage 60-90 sekunder)...
+ Checker cache filer (kan tage 60-90 sekunder)...
</string>
<string name="LoginProcessingResponse">
- Behandler svar...
+ Behandler svar ...
</string>
<string name="LoginInitializingWorld">
Initialiserer verden...
@@ -52,11 +71,20 @@
Henter tøj...
</string>
<string name="LoginFailedNoNetwork">
- Netværks fejl: Kunne ikke oprette forbindelse, tjek venligst din netværksforbindelse.
+ Netværksfejl: Kunne ikke etablere forbindelse, check venligst din netværksforbindelse.
+ </string>
+ <string name="Quit">
+ Afslut
</string>
<string name="AgentLostConnection">
Denne region kan have problemer. Tjek venligst din forbindelse til internettet.
</string>
+ <string name="TooltipPerson">
+ Person
+ </string>
+ <string name="TooltipNoName">
+ (intet navn)
+ </string>
<string name="TooltipOwner">
Ejer:
</string>
@@ -66,33 +94,9 @@
<string name="TooltipIsGroup">
(Gruppe)
</string>
- <string name="TooltipFlagScript">
- Script
- </string>
- <string name="TooltipFlagPhysics">
- Fysik
- </string>
- <string name="TooltipFlagTouch">
- Rør
- </string>
- <string name="TooltipFlagL$">
- L$
- </string>
- <string name="TooltipFlagPhantom">
- Fantom
- </string>
- <string name="TooltipFlagTemporary">
- Temporær
- </string>
- <string name="TooltipFreeToCopy">
- Kan kopieres
- </string>
<string name="TooltipForSaleL$">
Til salg: L$[AMOUNT]
</string>
- <string name="TooltipForSaleMsg">
- Til salg: [MESSAGE]
- </string>
<string name="TooltipFlagGroupBuild">
Gruppe byg
</string>
@@ -120,6 +124,76 @@
<string name="TooltipMustSingleDrop">
Kun et enkelt element kan trækkes ind her
</string>
+ <string name="TooltipHttpUrl">
+ Klik for at se denne hjemmeside
+ </string>
+ <string name="TooltipSLURL">
+ Klik for at se information om denne lokation
+ </string>
+ <string name="TooltipAgentUrl">
+ Klik for at denne beboers profil
+ </string>
+ <string name="TooltipGroupUrl">
+ Klik for at se denne gruppes beskrivelse
+ </string>
+ <string name="TooltipEventUrl">
+ Klik for at se beskrivelse af denne event
+ </string>
+ <string name="TooltipClassifiedUrl">
+ Klik for at se denne annonce
+ </string>
+ <string name="TooltipParcelUrl">
+ Klik for at se beskrivelse for denne parcel
+ </string>
+ <string name="TooltipTeleportUrl">
+ Klik for at teleportere til denne lokation
+ </string>
+ <string name="TooltipObjectIMUrl">
+ Klik for at se beskrivelse for dette objekt
+ </string>
+ <string name="TooltipMapUrl">
+ Klik for at se denne lokation på kortet
+ </string>
+ <string name="TooltipSLAPP">
+ Klik for at starte secondlife:// kommando
+ </string>
+ <string name="CurrentURL" value=" Nuværende URL: [CurrentURL]"/>
+ <string name="SLurlLabelTeleport">
+ Teleportér til
+ </string>
+ <string name="SLurlLabelShowOnMap">
+ Vis kort for
+ </string>
+ <string name="BUTTON_CLOSE_DARWIN">
+ Luk (&#8984;W)
+ </string>
+ <string name="BUTTON_CLOSE_WIN">
+ Luk (Ctrl+W)
+ </string>
+ <string name="BUTTON_RESTORE">
+ Gendan
+ </string>
+ <string name="BUTTON_MINIMIZE">
+ Minimér
+ </string>
+ <string name="BUTTON_TEAR_OFF">
+ Løsriv
+ </string>
+ <string name="BUTTON_DOCK">
+ Fastgør
+ </string>
+ <string name="BUTTON_UNDOCK">
+ Frigør
+ </string>
+ <string name="BUTTON_HELP">
+ Vis hjælp
+ </string>
+ <string name="Searching">
+ Søger...
+ </string>
+ <string name="NoneFound">
+ Intet fundet.
+ </string>
<string name="RetrievingData">
Henter...
</string>
@@ -168,11 +242,83 @@
<string name="AssetErrorCircuitGone">
Forbindelsen mistet
</string>
+ <string name="AssetErrorPriceMismatch">
+ [APP_NAME] klient og server er uenige om prisen
+ </string>
<string name="AssetErrorUnknownStatus">
Ukendt status
</string>
- <string name="AvatarEditingApparance">
- (Ændrer udseende)
+ <string name="texture">
+ tekstur
+ </string>
+ <string name="sound">
+ lyd
+ </string>
+ <string name="calling card">
+ visitkort
+ </string>
+ <string name="landmark">
+ landemærke
+ </string>
+ <string name="legacy script">
+ ældre script
+ </string>
+ <string name="clothing">
+ tøj
+ </string>
+ <string name="object">
+ objekt
+ </string>
+ <string name="note card">
+ note
+ </string>
+ <string name="folder">
+ mappe
+ </string>
+ <string name="root">
+ rod
+ </string>
+ <string name="lsl2 script">
+ LSL2 script
+ </string>
+ <string name="lsl bytecode">
+ LSL bytecode
+ </string>
+ <string name="tga texture">
+ tga texture
+ </string>
+ <string name="body part">
+ kropsdel
+ </string>
+ <string name="snapshot">
+ foto
+ </string>
+ <string name="lost and found">
+ Fundne genstande
+ </string>
+ <string name="targa image">
+ targa billede
+ </string>
+ <string name="trash">
+ Papirkurv
+ </string>
+ <string name="jpeg image">
+ jpeg billede
+ </string>
+ <string name="animation">
+ animation
+ </string>
+ <string name="gesture">
+ bevægelse
+ </string>
+ <string name="simstate">
+ simstate
+ </string>
+ <string name="favorite">
+ favorit
+ </string>
+ <string name="symbolic link">
+ link
</string>
<string name="AvatarAway">
Væk
@@ -391,15 +537,2706 @@
Ja
</string>
<string name="texture_loading">
- Henter...
+ Indlæser...
</string>
<string name="worldmap_offline">
Offline
</string>
+ <string name="worldmap_results_none_found">
+ Ingen fundet.
+ </string>
+ <string name="Ok">
+ OK
+ </string>
+ <string name="Premature end of file">
+ Fil slutter for tidligt
+ </string>
+ <string name="ST_NO_JOINT">
+ Kan ikke funde ROOT eller JOINT.
+ </string>
<string name="whisper">
hvisker:
</string>
<string name="shout">
råber:
</string>
+ <string name="ringing">
+ Forbinder til stemmechat...
+ </string>
+ <string name="connected">
+ Forbundet
+ </string>
+ <string name="unavailable">
+ Stemmechat er ikke tilladt hvor du befinder dig
+ </string>
+ <string name="hang_up">
+ Stemme chat er afbrudt
+ </string>
+ <string name="ScriptQuestionCautionChatGranted">
+ &apos;[OBJECTNAME]&apos;, en genstand, ejet af &apos;[OWNERNAME]&apos;, lokaliseret i [REGIONNAME] på [REGIONPOS], har fået tilladelse til: [PERMISSIONS].
+ </string>
+ <string name="ScriptQuestionCautionChatDenied">
+ &apos;[OBJECTNAME]&apos;, en genstand, ejet af &apos;[OWNERNAME]&apos;, lokaliseret i [REGIONNAME] på [REGIONPOS], er afvist tilladelse til: [PERMISSIONS].
+ </string>
+ <string name="ScriptTakeMoney">
+ Tag Linden dollars (L$) fra dig
+ </string>
+ <string name="ActOnControlInputs">
+ Reagér på dine kontrol-taster
+ </string>
+ <string name="RemapControlInputs">
+ Ændre dine kontrol-taster
+ </string>
+ <string name="AnimateYourAvatar">
+ Animér din avatar
+ </string>
+ <string name="AttachToYourAvatar">
+ Sæt på din avatar
+ </string>
+ <string name="ReleaseOwnership">
+ Fjern ejerskabet og sæt til offentlig
+ </string>
+ <string name="LinkAndDelink">
+ Sammenkæd og adskil andre genstande
+ </string>
+ <string name="AddAndRemoveJoints">
+ Tilføj og fjern sammenkødninger med andre genstande
+ </string>
+ <string name="ChangePermissions">
+ Ændre dens tilladelser
+ </string>
+ <string name="TrackYourCamera">
+ Spor dit kamera
+ </string>
+ <string name="ControlYourCamera">
+ Kontrollér dit kamera
+ </string>
+ <string name="SIM_ACCESS_PG">
+ PG
+ </string>
+ <string name="SIM_ACCESS_MATURE">
+ Mature
+ </string>
+ <string name="SIM_ACCESS_ADULT">
+ Adult
+ </string>
+ <string name="SIM_ACCESS_DOWN">
+ logget af
+ </string>
+ <string name="SIM_ACCESS_MIN">
+ Ukendt
+ </string>
+ <string name="land_type_unknown">
+ (ukendt)
+ </string>
+ <string name="all_files">
+ Alle filer
+ </string>
+ <string name="sound_files">
+ Lyde
+ </string>
+ <string name="animation_files">
+ Animationer
+ </string>
+ <string name="image_files">
+ Billeder
+ </string>
+ <string name="save_file_verb">
+ Gem
+ </string>
+ <string name="load_file_verb">
+ Hent
+ </string>
+ <string name="targa_image_files">
+ Targa billeder
+ </string>
+ <string name="bitmap_image_files">
+ Bitmap billeder
+ </string>
+ <string name="avi_movie_file">
+ AVI film fil
+ </string>
+ <string name="xaf_animation_file">
+ XAF Anim Fil
+ </string>
+ <string name="xml_file">
+ XML Fil
+ </string>
+ <string name="dot_raw_file">
+ RAW Fil
+ </string>
+ <string name="compressed_image_files">
+ Komprimerede billeder
+ </string>
+ <string name="load_files">
+ Hent filer
+ </string>
+ <string name="choose_the_directory">
+ Vælg bibliotek
+ </string>
+ <string name="AvatarSetNotAway">
+ Sæt &quot;til stede&quot;
+ </string>
+ <string name="AvatarSetAway">
+ Sæt &quot;væk&quot;
+ </string>
+ <string name="AvatarSetNotBusy">
+ Sæt &quot;ledig&quot;
+ </string>
+ <string name="AvatarSetBusy">
+ Sæt &quot;optaget&quot;
+ </string>
+ <string name="shape">
+ Form
+ </string>
+ <string name="skin">
+ Hud
+ </string>
+ <string name="hair">
+ HÃ¥r
+ </string>
+ <string name="eyes">
+ Øjne
+ </string>
+ <string name="shirt">
+ Trøje
+ </string>
+ <string name="pants">
+ Bukser
+ </string>
+ <string name="shoes">
+ Sko
+ </string>
+ <string name="socks">
+ Strømper
+ </string>
+ <string name="jacket">
+ Jakke
+ </string>
+ <string name="gloves">
+ Handsker
+ </string>
+ <string name="undershirt">
+ Undertrøje
+ </string>
+ <string name="underpants">
+ Underbukser
+ </string>
+ <string name="skirt">
+ Nederdel
+ </string>
+ <string name="alpha">
+ Alpha
+ </string>
+ <string name="tattoo">
+ Tatovering
+ </string>
+ <string name="invalid">
+ ugyldig
+ </string>
+ <string name="next">
+ Næste
+ </string>
+ <string name="ok">
+ OK
+ </string>
+ <string name="GroupNotifyGroupNotice">
+ Gruppe besked
+ </string>
+ <string name="GroupNotifyGroupNotices">
+ Gruppe besked
+ </string>
+ <string name="GroupNotifySentBy">
+ Sendt af
+ </string>
+ <string name="GroupNotifyAttached">
+ Vedhæftet:
+ </string>
+ <string name="GroupNotifyViewPastNotices">
+ Se tidligere beskeder eller slå modtagelse af beskeder fra her.
+ </string>
+ <string name="GroupNotifyOpenAttachment">
+ Åben vedhæng
+ </string>
+ <string name="GroupNotifySaveAttachment">
+ Gem vedhæng
+ </string>
+ <string name="TeleportOffer">
+ Teleport tilbud
+ </string>
+ <string name="StartUpNotification">
+ %d nye besked modtaget mens du var væk...
+ </string>
+ <string name="StartUpNotifications">
+ %d nye beskeder modtaget mens du var væk......
+ </string>
+ <string name="OverflowInfoChannelString">
+ Du har %d mere besked(er)
+ </string>
+ <string name="BodyPartsRightArm">
+ Højre arm
+ </string>
+ <string name="BodyPartsHead">
+ Hoved
+ </string>
+ <string name="BodyPartsLeftArm">
+ Venstre arm
+ </string>
+ <string name="BodyPartsLeftLeg">
+ Venstre ben
+ </string>
+ <string name="BodyPartsTorso">
+ Overkrop
+ </string>
+ <string name="BodyPartsRightLeg">
+ Højre ben
+ </string>
+ <string name="GraphicsQualityLow">
+ Lav
+ </string>
+ <string name="GraphicsQualityMid">
+ Middel
+ </string>
+ <string name="GraphicsQualityHigh">
+ Høj
+ </string>
+ <string name="LeaveMouselook">
+ Tryk ESC for at skift til normalt udsyn
+ </string>
+ <string name="InventoryNoMatchingItems">
+ No matching items found in inventory.
+ </string>
+ <string name="InventoryNoTexture">
+ Du har ikke en kopi af denne
+tekstur i din beholdning.
+ </string>
+ <string name="no_transfer" value=" (ikke overdragbar)"/>
+ <string name="no_modify" value=" (ikke redigere)"/>
+ <string name="no_copy" value=" (ikke kopiere)"/>
+ <string name="worn" value=" (båret)"/>
+ <string name="link" value=" (sammenkæde)"/>
+ <string name="broken_link" value=" (brudt_kæde)&quot;"/>
+ <string name="LoadingContents">
+ Henter indhold...
+ </string>
+ <string name="NoContents">
+ Intet indhold
+ </string>
+ <string name="WornOnAttachmentPoint" value=" (båret på [ATTACHMENT_POINT])"/>
+ <string name="Chat" value=" Chat : "/>
+ <string name="Sound" value=" Lyd : "/>
+ <string name="Wait" value=" --- Vent : "/>
+ <string name="AnimFlagStop" value=" Stop Animation : "/>
+ <string name="AnimFlagStart" value=" Start Animation : "/>
+ <string name="Wave" value=" Vink "/>
+ <string name="HelloAvatar" value=" Hej, avatar! "/>
+ <string name="ViewAllGestures" value=" Se alle &gt;&gt;"/>
+ <string name="Animations" value=" Animationer,"/>
+ <string name="Calling Cards" value=" Visitkort,"/>
+ <string name="Clothing" value=" Tøj,"/>
+ <string name="Gestures" value=" Bevægelser,"/>
+ <string name="Landmarks" value=" Landemærker,"/>
+ <string name="Notecards" value=" Note,"/>
+ <string name="Objects" value=" Objekter,"/>
+ <string name="Scripts" value=" Scripts,"/>
+ <string name="Sounds" value=" Lyde,"/>
+ <string name="Textures" value=" Teksturer,"/>
+ <string name="Snapshots" value=" Fotos,"/>
+ <string name="No Filters" value="Nej "/>
+ <string name="Since Logoff" value=" - Siden log ud"/>
+ <string name="InvFolder My Inventory">
+ Min beholdning
+ </string>
+ <string name="InvFolder My Favorites">
+ Mine favoritter
+ </string>
+ <string name="InvFolder Library">
+ Bibliotek
+ </string>
+ <string name="InvFolder Textures">
+ Teksturer
+ </string>
+ <string name="InvFolder Sounds">
+ Lyde
+ </string>
+ <string name="InvFolder Calling Cards">
+ Visitkort
+ </string>
+ <string name="InvFolder Landmarks">
+ Landemærker
+ </string>
+ <string name="InvFolder Scripts">
+ Scripts
+ </string>
+ <string name="InvFolder Clothing">
+ Tøj
+ </string>
+ <string name="InvFolder Objects">
+ Objekter
+ </string>
+ <string name="InvFolder Notecards">
+ Noter
+ </string>
+ <string name="InvFolder New Folder">
+ Ny mappe
+ </string>
+ <string name="InvFolder Inventory">
+ Beholdning
+ </string>
+ <string name="InvFolder Uncompressed Images">
+ Ukomprimerede billeder
+ </string>
+ <string name="InvFolder Body Parts">
+ Kropsdele
+ </string>
+ <string name="InvFolder Trash">
+ Papirkurv
+ </string>
+ <string name="InvFolder Photo Album">
+ Fotoalbum
+ </string>
+ <string name="InvFolder Lost And Found">
+ Fundne genstande
+ </string>
+ <string name="InvFolder Uncompressed Sounds">
+ Ukomprimerede lyde
+ </string>
+ <string name="InvFolder Animations">
+ Animationer
+ </string>
+ <string name="InvFolder Gestures">
+ Bevægelser
+ </string>
+ <string name="InvFolder favorite">
+ Favoritter
+ </string>
+ <string name="InvFolder Current Outfit">
+ Nuværende sæt
+ </string>
+ <string name="InvFolder My Outfits">
+ Mine sæt
+ </string>
+ <string name="InvFolder Friends">
+ Venner
+ </string>
+ <string name="InvFolder All">
+ Alle
+ </string>
+ <string name="Buy">
+ Køb
+ </string>
+ <string name="BuyforL$">
+ Køb for L$
+ </string>
+ <string name="Stone">
+ Sten
+ </string>
+ <string name="Metal">
+ Metal
+ </string>
+ <string name="Glass">
+ Glas
+ </string>
+ <string name="Wood">
+ Træ
+ </string>
+ <string name="Flesh">
+ Kød
+ </string>
+ <string name="Plastic">
+ Plastik
+ </string>
+ <string name="Rubber">
+ Gummi
+ </string>
+ <string name="Light">
+ Lys
+ </string>
+ <string name="KBShift">
+ Shift
+ </string>
+ <string name="KBCtrl">
+ Ctrl
+ </string>
+ <string name="Chest">
+ Bryst
+ </string>
+ <string name="Skull">
+ Hovedskal
+ </string>
+ <string name="Left Shoulder">
+ Venstre skulder
+ </string>
+ <string name="Right Shoulder">
+ Højre skulder
+ </string>
+ <string name="Left Hand">
+ Venstre hånd
+ </string>
+ <string name="Right Hand">
+ Højre hånd
+ </string>
+ <string name="Left Foot">
+ Venstre fod
+ </string>
+ <string name="Right Foot">
+ Højre fod
+ </string>
+ <string name="Spine">
+ Rygsøjle
+ </string>
+ <string name="Pelvis">
+ Bækken
+ </string>
+ <string name="Mouth">
+ Mund
+ </string>
+ <string name="Chin">
+ Hage
+ </string>
+ <string name="Left Ear">
+ Venstre øre
+ </string>
+ <string name="Right Ear">
+ Højre øre
+ </string>
+ <string name="Left Eyeball">
+ Venstre øje
+ </string>
+ <string name="Right Eyeball">
+ Højre øje
+ </string>
+ <string name="Nose">
+ Næse
+ </string>
+ <string name="R Upper Arm">
+ H overarm
+ </string>
+ <string name="R Forearm">
+ H underarm
+ </string>
+ <string name="L Upper Arm">
+ V overarm
+ </string>
+ <string name="L Forearm">
+ V underarm
+ </string>
+ <string name="Right Hip">
+ Højre hofte
+ </string>
+ <string name="R Upper Leg">
+ Højre lår
+ </string>
+ <string name="R Lower Leg">
+ H underben
+ </string>
+ <string name="Left Hip">
+ Venstre hofte
+ </string>
+ <string name="L Upper Leg">
+ Venstre lår
+ </string>
+ <string name="L Lower Leg">
+ V underben
+ </string>
+ <string name="Stomach">
+ Mave
+ </string>
+ <string name="Left Pec">
+ Venstre bryst
+ </string>
+ <string name="Right Pec">
+ Højre bryst
+ </string>
+ <string name="YearsMonthsOld">
+ [AGEYEARS] [AGEMONTHS] gammel
+ </string>
+ <string name="YearsOld">
+ [AGEYEARS] gammel
+ </string>
+ <string name="MonthsOld">
+ [AGEMONTHS] gammel
+ </string>
+ <string name="WeeksOld">
+ [AGEWEEKS] gammel
+ </string>
+ <string name="DaysOld">
+ [AGEDAYS] gammel
+ </string>
+ <string name="TodayOld">
+ Med fra i dag
+ </string>
+ <string name="AgeYearsA">
+ [COUNT] år
+ </string>
+ <string name="AgeYearsB">
+ [COUNT] år
+ </string>
+ <string name="AgeYearsC">
+ [COUNT] år
+ </string>
+ <string name="AgeMonthsA">
+ [COUNT] måned
+ </string>
+ <string name="AgeMonthsB">
+ [COUNT] måneder
+ </string>
+ <string name="AgeMonthsC">
+ [COUNT] måneder
+ </string>
+ <string name="AgeWeeksA">
+ [COUNT] uge
+ </string>
+ <string name="AgeWeeksB">
+ [COUNT] uger
+ </string>
+ <string name="AgeWeeksC">
+ [COUNT] uger
+ </string>
+ <string name="AgeDaysA">
+ [COUNT] dag
+ </string>
+ <string name="AgeDaysB">
+ [COUNT] dage
+ </string>
+ <string name="AgeDaysC">
+ [COUNT] dage
+ </string>
+ <string name="GroupMembersA">
+ [COUNT] medlem
+ </string>
+ <string name="GroupMembersB">
+ [COUNT] medlemmer
+ </string>
+ <string name="GroupMembersC">
+ [COUNT] medlemmer
+ </string>
+ <string name="AcctTypeResident">
+ Beboer
+ </string>
+ <string name="AcctTypeTrial">
+ På prøve
+ </string>
+ <string name="AcctTypeCharterMember">
+ Æresmedlemmer
+ </string>
+ <string name="AcctTypeEmployee">
+ Linden Lab medarbejder
+ </string>
+ <string name="PaymentInfoUsed">
+ Betalende medlem
+ </string>
+ <string name="PaymentInfoOnFile">
+ Betalingsinfo registreret
+ </string>
+ <string name="NoPaymentInfoOnFile">
+ Ingen betalingsinfo
+ </string>
+ <string name="AgeVerified">
+ Alders-checket
+ </string>
+ <string name="NotAgeVerified">
+ Ikke alders-checket
+ </string>
+ <string name="Center 2">
+ Center 2
+ </string>
+ <string name="Top Right">
+ Øverst højre
+ </string>
+ <string name="Top">
+ Top
+ </string>
+ <string name="Top Left">
+ Øverst venstre
+ </string>
+ <string name="Center">
+ Centrum
+ </string>
+ <string name="Bottom Left">
+ Nederst venstre
+ </string>
+ <string name="Bottom">
+ Nederst midt
+ </string>
+ <string name="Bottom Right">
+ nederst højre
+ </string>
+ <string name="CompileQueueDownloadedCompiling">
+ Hentet, kompilerer nu
+ </string>
+ <string name="CompileQueueScriptNotFound">
+ Script ikke fundet på server.
+ </string>
+ <string name="CompileQueueProblemDownloading">
+ Problem ved download
+ </string>
+ <string name="CompileQueueInsufficientPermDownload">
+ Ikke rettigheder til at downloade script.
+ </string>
+ <string name="CompileQueueInsufficientPermFor">
+ Ikke nok rettigheder til at
+ </string>
+ <string name="CompileQueueUnknownFailure">
+ Ukendt fejl ved download
+ </string>
+ <string name="CompileQueueTitle">
+ Rekompilering fremskridt
+ </string>
+ <string name="CompileQueueStart">
+ Rekompilér
+ </string>
+ <string name="ResetQueueTitle">
+ Nulstil fremskridt
+ </string>
+ <string name="ResetQueueStart">
+ nulstil
+ </string>
+ <string name="RunQueueTitle">
+ Sæt &quot;running&quot; fremskridt
+ </string>
+ <string name="RunQueueStart">
+ sæt til &quot;running&quot;
+ </string>
+ <string name="NotRunQueueTitle">
+ Sæt &quot;Not Running&quot; fremskridt
+ </string>
+ <string name="NotRunQueueStart">
+ sæt til &quot;not running&quot;
+ </string>
+ <string name="CompileSuccessful">
+ Kompleret uden fejl!
+ </string>
+ <string name="CompileSuccessfulSaving">
+ Kompileret uden fejl, gemmer...
+ </string>
+ <string name="SaveComplete">
+ Gemt.
+ </string>
+ <string name="ObjectOutOfRange">
+ Script (&quot;object out of range&quot;)
+ </string>
+ <string name="GodToolsObjectOwnedBy">
+ Objekt [OBJECT] ejet af [OWNER]
+ </string>
+ <string name="GroupsNone">
+ ingen
+ </string>
+ <string name="Group" value=" (gruppe)"/>
+ <string name="Unknown">
+ (ukendt)
+ </string>
+ <string name="SummaryForTheWeek" value="Opsummering for denne uge, begyndende med "/>
+ <string name="NextStipendDay" value="Næste stipendie dag er "/>
+ <string name="GroupIndividualShare" value=" Gruppe Individuel Delt"/>
+ <string name="Balance">
+ Balance
+ </string>
+ <string name="Credits">
+ Kredit
+ </string>
+ <string name="Debits">
+ Debet
+ </string>
+ <string name="Total">
+ Total
+ </string>
+ <string name="NoGroupDataFound">
+ Ingen gruppedata fundet for gruppe
+ </string>
+ <string name="IMParentEstate">
+ overordnet estate
+ </string>
+ <string name="IMMainland">
+ mainland
+ </string>
+ <string name="IMTeen">
+ teen
+ </string>
+ <string name="RegionInfoError">
+ fejl
+ </string>
+ <string name="RegionInfoAllEstatesOwnedBy">
+ alle estates ejet af [OWNER]
+ </string>
+ <string name="RegionInfoAllEstatesYouOwn">
+ alle estates du ejer
+ </string>
+ <string name="RegionInfoAllEstatesYouManage">
+ alle estates du administrerer for [OWNER]
+ </string>
+ <string name="RegionInfoAllowedResidents">
+ Godkendte beboere: ([ALLOWEDAGENTS], max. [MAXACCESS])
+ </string>
+ <string name="RegionInfoAllowedGroups">
+ Godkendte grupper: ([ALLOWEDGROUPS], max. [MAXACCESS])
+ </string>
+ <string name="CursorPos">
+ Linie [LINE], Kolonne [COLUMN]
+ </string>
+ <string name="PanelDirCountFound">
+ [COUNT] fundet
+ </string>
+ <string name="PanelContentsNewScript">
+ Nyt script
+ </string>
+ <string name="MuteByName">
+ (efter navn)
+ </string>
+ <string name="MuteAgent">
+ (beboer)
+ </string>
+ <string name="MuteObject">
+ (objekt)
+ </string>
+ <string name="MuteGroup">
+ (gruppe)
+ </string>
+ <string name="RegionNoCovenant">
+ Der er ingen regler for dette estate.
+ </string>
+ <string name="RegionNoCovenantOtherOwner">
+ Der er ingen regler for dette estate. Land på dette estate sælges af estate ejeren, ikke af Linden Lab. Kontakt venligst estate ejeren for detaljer om salg.
+ </string>
+ <string name="covenant_last_modified">
+ Sidst ændret:
+ </string>
+ <string name="none_text" value=" (ingen) "/>
+ <string name="never_text" value=" (aldrig) "/>
+ <string name="GroupOwned">
+ Gruppe ejet
+ </string>
+ <string name="Public">
+ Offentlig
+ </string>
+ <string name="ClassifiedClicksTxt">
+ Klik: [TELEPORT] teleport, [MAP] kort, [PROFILE] profil
+ </string>
+ <string name="ClassifiedUpdateAfterPublish">
+ (vil blive opdateret efter offentliggørelse)
+ </string>
+ <string name="MultiPreviewTitle">
+ Vis først
+ </string>
+ <string name="MultiPropertiesTitle">
+ Egenskaber
+ </string>
+ <string name="InvOfferAnObjectNamed">
+ Et objekt med navnet
+ </string>
+ <string name="InvOfferOwnedByGroup">
+ ejet af gruppen
+ </string>
+ <string name="InvOfferOwnedByUnknownGroup">
+ ejet af en ukendt gruppe
+ </string>
+ <string name="InvOfferOwnedBy">
+ ejet af
+ </string>
+ <string name="InvOfferOwnedByUnknownUser">
+ ejet af en ukendt bruger
+ </string>
+ <string name="InvOfferGaveYou">
+ gav dig
+ </string>
+ <string name="InvOfferYouDecline">
+ Du afslår
+ </string>
+ <string name="InvOfferFrom">
+ fra
+ </string>
+ <string name="GroupMoneyTotal">
+ Total
+ </string>
+ <string name="GroupMoneyBought">
+ købt
+ </string>
+ <string name="GroupMoneyPaidYou">
+ betalte dig
+ </string>
+ <string name="GroupMoneyPaidInto">
+ betalt til
+ </string>
+ <string name="GroupMoneyBoughtPassTo">
+ købte adgang til
+ </string>
+ <string name="GroupMoneyPaidFeeForEvent">
+ betalte gebyr for event
+ </string>
+ <string name="GroupMoneyPaidPrizeForEvent">
+ betalte prisen for event
+ </string>
+ <string name="GroupMoneyBalance">
+ Balance
+ </string>
+ <string name="GroupMoneyCredits">
+ Kredit
+ </string>
+ <string name="GroupMoneyDebits">
+ Debet
+ </string>
+ <string name="ViewerObjectContents">
+ Indhold
+ </string>
+ <string name="AcquiredItems">
+ Anskaffede genstande
+ </string>
+ <string name="Cancel">
+ Annullér
+ </string>
+ <string name="UploadingCosts">
+ Uploader [%s] omkostninger
+ </string>
+ <string name="UnknownFileExtension">
+ Ukendt fil efternavn [.%s]
+Forventet .wav, .tga, .bmp, .jpg, .jpeg, or .bvh
+ </string>
+ <string name="AddLandmarkNavBarMenu">
+ Tilføj landemærke...
+ </string>
+ <string name="EditLandmarkNavBarMenu">
+ Redigér landemærke...
+ </string>
+ <string name="accel-mac-control">&#8963;</string>
+ <string name="accel-mac-command">&#8984;</string>
+ <string name="accel-mac-option">&#8997;</string>
+ <string name="accel-mac-shift">&#8679;</string>
+ <string name="accel-win-control">
+ Ctrl+
+ </string>
+ <string name="accel-win-alt">
+ Alt+
+ </string>
+ <string name="accel-win-shift">
+ Shift+
+ </string>
+ <string name="FileSaved">
+ Fil gemt
+ </string>
+ <string name="Receiving">
+ Modtager
+ </string>
+ <string name="AM">
+ AM
+ </string>
+ <string name="PM">
+ PM
+ </string>
+ <string name="PST">
+ PST
+ </string>
+ <string name="PDT">
+ PDT
+ </string>
+ <string name="Forward">
+ Fremad
+ </string>
+ <string name="Left">
+ Venstre
+ </string>
+ <string name="Right">
+ Højre
+ </string>
+ <string name="Back">
+ Bagud
+ </string>
+ <string name="North">
+ Nord
+ </string>
+ <string name="South">
+ Syd
+ </string>
+ <string name="West">
+ Vest
+ </string>
+ <string name="East">
+ Øst
+ </string>
+ <string name="Up">
+ Op
+ </string>
+ <string name="Down">
+ Ned
+ </string>
+ <string name="Any Category">
+ Enhver kategori
+ </string>
+ <string name="Shopping">
+ Shopping
+ </string>
+ <string name="Land Rental">
+ Land til leje
+ </string>
+ <string name="Property Rental">
+ Grunde til leje
+ </string>
+ <string name="Special Attraction">
+ Speciel attraktion
+ </string>
+ <string name="New Products">
+ Nye produkter
+ </string>
+ <string name="Employment">
+ Jobs
+ </string>
+ <string name="Wanted">
+ Søges
+ </string>
+ <string name="Service">
+ Service
+ </string>
+ <string name="Personal">
+ Personlig
+ </string>
+ <string name="None">
+ Ingen
+ </string>
+ <string name="Linden Location">
+ Linden sted
+ </string>
+ <string name="Adult">
+ Adult
+ </string>
+ <string name="Arts&amp;Culture">
+ Kunst &amp; kultur
+ </string>
+ <string name="Business">
+ Business
+ </string>
+ <string name="Educational">
+ Uddannelse
+ </string>
+ <string name="Gaming">
+ Spil
+ </string>
+ <string name="Hangout">
+ Afslapning
+ </string>
+ <string name="Newcomer Friendly">
+ Nybegynder venligt
+ </string>
+ <string name="Parks&amp;Nature">
+ Parker &amp; natur
+ </string>
+ <string name="Residential">
+ Beboelse
+ </string>
+ <string name="Stage">
+ Fase
+ </string>
+ <string name="Other">
+ Andet
+ </string>
+ <string name="Any">
+ Enhver
+ </string>
+ <string name="You">
+ Dig
+ </string>
+ <string name="Multiple Media">
+ Flere medietyper
+ </string>
+ <string name="Play Media">
+ Afspil/Pause medie
+ </string>
+ <string name="MBCmdLineError">
+ Der opstod en fejl ved afvikling af kommandolinie.
+Se venligst: http://wiki.secondlife.com/wiki/Client_parameters
+Fejl:
+ </string>
+ <string name="MBCmdLineUsg">
+ [APP_NAME] Kommando linie brug:
+ </string>
+ <string name="MBUnableToAccessFile">
+ [APP_NAME] kan ikke få adgang til fil den/det skal bruge.
+
+Dette kan skyldes at du har flere kopier kørende eller operativsystemet tror at filen allerede er åben.
+Hvis fejlen bliver ved, genstart computer og prøv igen.
+Hvis fejlen stadig bliver ved, kan det være nødvendigt at afinstallere [APP_NAME] og installere igen.
+ </string>
+ <string name="MBFatalError">
+ Fatal fejl
+ </string>
+ <string name="MBRequiresAltiVec">
+ [APP_NAME] kræver en processor med AltiVec (G4 eller nyere).
+ </string>
+ <string name="MBAlreadyRunning">
+ [APP_NAME] kører allerede.
+Undersøg din &quot;task bar&quot; for at se efter minimeret version af programmet.
+Hvis fejlen fortsætter, prøv at genstarte din computer.
+ </string>
+ <string name="MBFrozenCrashed">
+ [APP_NAME] ser ud til at være &quot;frosset&quot; eller gået ned tidligere.
+Ønsker du at sende en fejlrapport?
+ </string>
+ <string name="MBAlert">
+ Besked
+ </string>
+ <string name="MBNoDirectX">
+ [APP_NAME] kan ikke detektere DirectX 9.0b eller nyere.
+[APP_NAME] benytte DirectX til at detektere hardware og/eller forældede drivere der kan give problemer med stabilitet, dårlig hastighed eller nedbrud. Selvom du kan køre [APP_NAME] uden det, anbefaler vi meget at køre med DirectX 9.0b.
+
+Ønsker du at fortsætte?
+ </string>
+ <string name="MBWarning">
+ Advarsel
+ </string>
+ <string name="MBNoAutoUpdate">
+ Automatisk opdatering er endnu ikke implementeret på Linux.
+Hent venligst den nyeste version på www.secondlife.com.
+ </string>
+ <string name="MBRegClassFailed">
+ RegisterClass fejlede
+ </string>
+ <string name="MBError">
+ Fejl
+ </string>
+ <string name="MBFullScreenErr">
+ Ikke muligt at køre i fuldskærm med [WIDTH] x [HEIGHT].
+Afvikler i vindue.
+ </string>
+ <string name="MBDestroyWinFailed">
+ Nedlukningsfejl ved lukning af vindue (DestroyWindow() fejlede)
+ </string>
+ <string name="MBShutdownErr">
+ Fejl ved nedlukning
+ </string>
+ <string name="MBDevContextErr">
+ Kan ikke oprette &quot;GL device context&quot;
+ </string>
+ <string name="MBPixelFmtErr">
+ Kan ikke finde passende &quot;pixel format&quot;
+ </string>
+ <string name="MBPixelFmtDescErr">
+ Kan ikke finde &quot;pixel format&quot; beskrivelse
+ </string>
+ <string name="MBTrueColorWindow">
+ [APP_NAME] kræver &quot;True Color (32-bit)&quot; for at kunne køre.
+Gå venligst til din computers skærmopsætning og sæt &quot;color mode&quot; til 32-bit.
+ </string>
+ <string name="MBAlpha">
+ [APP_NAME] kan ikke køre, da den ikke kan finde en &quot;8 bit alpha channel&quot;. Normalt skyldes dette et problem med en video driver.
+Venligst undersøg om du har de nyeste drivere til dit videokort installeret.
+Din skærm skal også være sat op til at køre &quot;True Color (32-bit)&quot; i din displayopsætning.
+Hvis du bliver ved med at modtage denne besked, kontakt [SUPPORT_SITE].
+ </string>
+ <string name="MBPixelFmtSetErr">
+ Kan ikke sætte &quot;pixel format&quot;
+ </string>
+ <string name="MBGLContextErr">
+ Kan ikke oprette &quot;GL rendering context&quot;
+ </string>
+ <string name="MBGLContextActErr">
+ Kan ikke aktivere &quot;GL rendering context&quot;
+ </string>
+ <string name="MBVideoDrvErr">
+ [APP_NAME] kan ikke afvikles da driverne til dit videokort ikke blev installeret korrekt, er forældede, eller du benytter hardware der ikke er supporteret. Undersøg venligst om du har installeret de nyeste drivere til dit grafikkort, og selv om du har de nyeste, prøv at geninstallere dem.
+
+Hvis du bliver ved med at modtage denne besked, kontakt venligst [SUPPORT_SITE].
+ </string>
+ <string name="5 O&apos;Clock Shadow">
+ Skægstubbe
+ </string>
+ <string name="All White">
+ Helt hvidt
+ </string>
+ <string name="Anime Eyes">
+ Store øjne
+ </string>
+ <string name="Arced">
+ Spidst
+ </string>
+ <string name="Arm Length">
+ Armængde
+ </string>
+ <string name="Attached">
+ Vedhæftet
+ </string>
+ <string name="Attached Earlobes">
+ Vedhæftede øreflipper
+ </string>
+ <string name="Back Bangs">
+ Nakkehår
+ </string>
+ <string name="Back Bangs Down">
+ Nakkehår langt
+ </string>
+ <string name="Back Bangs Up">
+ Nakkehår kort
+ </string>
+ <string name="Back Fringe">
+ Nakkehår
+ </string>
+ <string name="Back Hair">
+ Volumen
+ </string>
+ <string name="Back Hair Down">
+ Volumen nedad
+ </string>
+ <string name="Back Hair Up">
+ Volumen op
+ </string>
+ <string name="Baggy">
+ Posede
+ </string>
+ <string name="Bangs">
+ Pandehår
+ </string>
+ <string name="Bangs Down">
+ Pandehår ned
+ </string>
+ <string name="Bangs Up">
+ Pandehår op
+ </string>
+ <string name="Beady Eyes">
+ Stikkende øjne
+ </string>
+ <string name="Belly Size">
+ Mave størrelse
+ </string>
+ <string name="Big">
+ Stor
+ </string>
+ <string name="Big Butt">
+ Stor bagdel
+ </string>
+ <string name="Big Eyeball">
+ Store øjenæbler
+ </string>
+ <string name="Big Hair Back">
+ Stort hår: Bag
+ </string>
+ <string name="Big Hair Front">
+ Stort hår: Foran
+ </string>
+ <string name="Big Hair Top">
+ Stort hår: Top
+ </string>
+ <string name="Big Head">
+ Stort hovede
+ </string>
+ <string name="Big Pectorals">
+ Store brystmuskler
+ </string>
+ <string name="Big Spikes">
+ Store spikes
+ </string>
+ <string name="Black">
+ Sort
+ </string>
+ <string name="Blonde">
+ Blond
+ </string>
+ <string name="Blonde Hair">
+ Blondt hår
+ </string>
+ <string name="Blush">
+ Rødmen
+ </string>
+ <string name="Blush Color">
+ Rødme farve
+ </string>
+ <string name="Blush Opacity">
+ Rødme gennemsigtighed
+ </string>
+ <string name="Body Definition">
+ Kropskontur
+ </string>
+ <string name="Body Fat">
+ Kropsfedt
+ </string>
+ <string name="Body Freckles">
+ Fregner på kroppen
+ </string>
+ <string name="Body Thick">
+ Tyk krop
+ </string>
+ <string name="Body Thickness">
+ Kropstykkelse
+ </string>
+ <string name="Body Thin">
+ Tynd krop
+ </string>
+ <string name="Bow Legged">
+ Hjulbenet
+ </string>
+ <string name="Breast Buoyancy">
+ Bryst tyngdepåvirkning
+ </string>
+ <string name="Breast Cleavage">
+ Kavalergang
+ </string>
+ <string name="Breast Size">
+ Bryststørrelse
+ </string>
+ <string name="Bridge Width">
+ Bredde næseryg
+ </string>
+ <string name="Broad">
+ Bred
+ </string>
+ <string name="Brow Size">
+ Størrelse øjenbryn
+ </string>
+ <string name="Bug Eyes">
+ Udstående øjne
+ </string>
+ <string name="Bugged Eyes">
+ Udstående øjne
+ </string>
+ <string name="Bulbous">
+ Kartoffelnæse
+ </string>
+ <string name="Bulbous Nose">
+ Kartoffelnæse
+ </string>
+ <string name="Bushy Eyebrows">
+ Buskede øjenbryn
+ </string>
+ <string name="Bushy Hair">
+ Busket hår
+ </string>
+ <string name="Butt Size">
+ Størrelse bagdel
+ </string>
+ <string name="bustle skirt">
+ Tournure
+ </string>
+ <string name="no bustle">
+ Ingen tournure
+ </string>
+ <string name="more bustle">
+ Mere tournure
+ </string>
+ <string name="Chaplin">
+ Chaplin
+ </string>
+ <string name="Cheek Bones">
+ Kindben
+ </string>
+ <string name="Chest Size">
+ Bryst størrelse
+ </string>
+ <string name="Chin Angle">
+ Hage form
+ </string>
+ <string name="Chin Cleft">
+ Hagekløft
+ </string>
+ <string name="Chin Curtains">
+ Hageskæg
+ </string>
+ <string name="Chin Depth">
+ Hage dybde
+ </string>
+ <string name="Chin Heavy">
+ Stort forneden
+ </string>
+ <string name="Chin In">
+ Vigende hage
+ </string>
+ <string name="Chin Out">
+ Hage frem
+ </string>
+ <string name="Chin-Neck">
+ Hals under hage
+ </string>
+ <string name="Clear">
+ Slet
+ </string>
+ <string name="Cleft">
+ Kløft
+ </string>
+ <string name="Close Set Eyes">
+ Tætsiddende øjne
+ </string>
+ <string name="Closed">
+ Lukket
+ </string>
+ <string name="Closed Back">
+ Lukket bagtil
+ </string>
+ <string name="Closed Front">
+ Lukket foran
+ </string>
+ <string name="Closed Left">
+ Lukket til venstre
+ </string>
+ <string name="Closed Right">
+ Lukket til højre
+ </string>
+ <string name="Coin Purse">
+ Lille
+ </string>
+ <string name="Collar Back">
+ Krave bagtil
+ </string>
+ <string name="Collar Front">
+ Krave foran
+ </string>
+ <string name="Corner Down">
+ Nedadvendt
+ </string>
+ <string name="Corner Normal">
+ Normalt
+ </string>
+ <string name="Corner Up">
+ Opadvendt
+ </string>
+ <string name="Creased">
+ Rynket
+ </string>
+ <string name="Crooked Nose">
+ Skæv næse
+ </string>
+ <string name="Cropped Hair">
+ Kort hår
+ </string>
+ <string name="Cuff Flare">
+ Svaj
+ </string>
+ <string name="Dark">
+ Mørk
+ </string>
+ <string name="Dark Green">
+ Mørkegrøn
+ </string>
+ <string name="Darker">
+ Mørkere
+ </string>
+ <string name="Deep">
+ Dyb
+ </string>
+ <string name="Default Heels">
+ Standard hæle
+ </string>
+ <string name="Default Toe">
+ Standard snude
+ </string>
+ <string name="Dense">
+ Tæt
+ </string>
+ <string name="Dense hair">
+ Tæt hår
+ </string>
+ <string name="Double Chin">
+ Dobbelthage
+ </string>
+ <string name="Downturned">
+ Peger nedad
+ </string>
+ <string name="Duffle Bag">
+ Stort
+ </string>
+ <string name="Ear Angle">
+ Øre vinkel
+ </string>
+ <string name="Ear Size">
+ Øre størrelse
+ </string>
+ <string name="Ear Tips">
+ Ørespidser
+ </string>
+ <string name="Egg Head">
+ Ovalt hovede
+ </string>
+ <string name="Eye Bags">
+ Poser under øjne
+ </string>
+ <string name="Eye Color">
+ Øjenfarve
+ </string>
+ <string name="Eye Depth">
+ Øjendybde
+ </string>
+ <string name="Eye Lightness">
+ Øjennuance
+ </string>
+ <string name="Eye Opening">
+ Øjenåbning
+ </string>
+ <string name="Eye Pop">
+ Øjensymmetri
+ </string>
+ <string name="Eye Size">
+ Øjenstørrelse
+ </string>
+ <string name="Eye Spacing">
+ Øjenafstand
+ </string>
+ <string name="Eyeball Size">
+ Størrelse øjenæble
+ </string>
+ <string name="Eyebrow Arc">
+ Bue på øjenbryn
+ </string>
+ <string name="Eyebrow Density">
+ Tæthed øjenbryn
+ </string>
+ <string name="Eyebrow Height">
+ Højde på øjenbryn
+ </string>
+ <string name="Eyebrow Points">
+ Løftede øjenbryn
+ </string>
+ <string name="Eyebrow Size">
+ Størrelse øjenbryn
+ </string>
+ <string name="Eyelash Length">
+ Længde øjenvipper
+ </string>
+ <string name="Eyeliner">
+ Eyeliner
+ </string>
+ <string name="Eyeliner Color">
+ Eyeliner farve
+ </string>
+ <string name="Eyes Back">
+ Dybtliggende øjne
+ </string>
+ <string name="Eyes Bugged">
+ Udstående øjne
+ </string>
+ <string name="Eyes Forward">
+ Øjne fremme
+ </string>
+ <string name="Eyes Long Head">
+ Eyes Long Head
+ </string>
+ <string name="Eyes Shear Left Up">
+ Eyes Shear Left Up
+ </string>
+ <string name="Eyes Shear Right Up">
+ Eyes Shear Right Up
+ </string>
+ <string name="Eyes Short Head">
+ Eyes Short Head
+ </string>
+ <string name="Eyes Spread">
+ Stor afstand
+ </string>
+ <string name="Eyes Sunken">
+ Indsunkne øjne
+ </string>
+ <string name="Eyes Together">
+ Tætsiddende
+ </string>
+ <string name="Face Shear">
+ Ansigts symmetri
+ </string>
+ <string name="Facial Definition">
+ Ansigtskonturer
+ </string>
+ <string name="Far Set Eyes">
+ Stor afstand mellem øjne
+ </string>
+ <string name="Fat">
+ Tyk
+ </string>
+ <string name="Fat Head">
+ Tykt hovede
+ </string>
+ <string name="Fat Lips">
+ Tykke læber
+ </string>
+ <string name="Fat Lower">
+ Tyk nedre
+ </string>
+ <string name="Fat Lower Lip">
+ Tyk underlæbe
+ </string>
+ <string name="Fat Torso">
+ Tyk overkrop
+ </string>
+ <string name="Fat Upper">
+ Tyk øvre
+ </string>
+ <string name="Fat Upper Lip">
+ Tyk overlæbe
+ </string>
+ <string name="Female">
+ Kvinde
+ </string>
+ <string name="Fingerless">
+ Fingerløse
+ </string>
+ <string name="Fingers">
+ Fingre
+ </string>
+ <string name="Flared Cuffs">
+ Stor vidde
+ </string>
+ <string name="Flat">
+ Flad
+ </string>
+ <string name="Flat Butt">
+ Flad bagdel
+ </string>
+ <string name="Flat Head">
+ Fladt hovede
+ </string>
+ <string name="Flat Toe">
+ Flad snude
+ </string>
+ <string name="Foot Size">
+ Størrelse fod
+ </string>
+ <string name="Forehead Angle">
+ Pande vinkel
+ </string>
+ <string name="Forehead Heavy">
+ Stort foroven
+ </string>
+ <string name="Freckles">
+ Fregner
+ </string>
+ <string name="Front Bangs Down">
+ Pandehår - ned
+ </string>
+ <string name="Front Bangs Up">
+ Pandehår - op
+ </string>
+ <string name="Front Fringe">
+ Frynser foran
+ </string>
+ <string name="Front Hair">
+ HÃ¥r foran
+ </string>
+ <string name="Front Hair Down">
+ HÃ¥r foran - ned
+ </string>
+ <string name="Front Hair Up">
+ HÃ¥r foran - op
+ </string>
+ <string name="Full Back">
+ Langt ud bagtil
+ </string>
+ <string name="Full Eyeliner">
+ Meget eyeliner
+ </string>
+ <string name="Full Front">
+ Langt frem fortil
+ </string>
+ <string name="Full Hair Sides">
+ HÃ¥r i siderne
+ </string>
+ <string name="Full Sides">
+ Meget hår
+ </string>
+ <string name="Glossy">
+ Skinnende
+ </string>
+ <string name="Glove Fingers">
+ Fingre i handsker
+ </string>
+ <string name="Glove Length">
+ Handskelængde
+ </string>
+ <string name="Hair">
+ HÃ¥r
+ </string>
+ <string name="Hair Back">
+ HÃ¥r: Bagtil
+ </string>
+ <string name="Hair Front">
+ HÃ¥r: Foran
+ </string>
+ <string name="Hair Sides">
+ HÃ¥r: Siderne
+ </string>
+ <string name="Hair Sweep">
+ Strøget hår
+ </string>
+ <string name="Hair Thickess">
+ HÃ¥r tykkelse
+ </string>
+ <string name="Hair Thickness">
+ HÃ¥r tykkelse
+ </string>
+ <string name="Hair Tilt">
+ Hældning
+ </string>
+ <string name="Hair Tilted Left">
+ mest hår venstre
+ </string>
+ <string name="Hair Tilted Right">
+ Mest hår højre
+ </string>
+ <string name="Hair Volume">
+ HÃ¥r: Volumen
+ </string>
+ <string name="Hand Size">
+ Størrelse hånd
+ </string>
+ <string name="Handlebars">
+ Cykelstyr
+ </string>
+ <string name="Head Length">
+ Længde på hovede
+ </string>
+ <string name="Head Shape">
+ Hovedform
+ </string>
+ <string name="Head Size">
+ Hovedstørrelse
+ </string>
+ <string name="Head Stretch">
+ Hovedhøjde
+ </string>
+ <string name="Heel Height">
+ Hælhøjde
+ </string>
+ <string name="Heel Shape">
+ Hælform
+ </string>
+ <string name="Height">
+ Højde
+ </string>
+ <string name="High">
+ Høj
+ </string>
+ <string name="High Heels">
+ Hæje hæle
+ </string>
+ <string name="High Jaw">
+ Høj kæbe
+ </string>
+ <string name="High Platforms">
+ Høje såle
+ </string>
+ <string name="High and Tight">
+ Høj og tæt
+ </string>
+ <string name="Higher">
+ Højere
+ </string>
+ <string name="Hip Length">
+ Hoftelængde
+ </string>
+ <string name="Hip Width">
+ Hoftebredde
+ </string>
+ <string name="In">
+ Inde
+ </string>
+ <string name="In Shdw Color">
+ Indre skygge farve
+ </string>
+ <string name="In Shdw Opacity">
+ Indre skygge gennemsigtighed
+ </string>
+ <string name="Inner Eye Corner">
+ Inderste del af øje
+ </string>
+ <string name="Inner Eye Shadow">
+ Inderste øjenskygge
+ </string>
+ <string name="Inner Shadow">
+ Indre skygge
+ </string>
+ <string name="Jacket Length">
+ Jakkelængde
+ </string>
+ <string name="Jacket Wrinkles">
+ Jakkerynker
+ </string>
+ <string name="Jaw Angle">
+ Kæbevinkel
+ </string>
+ <string name="Jaw Jut">
+ Kæbefremspring
+ </string>
+ <string name="Jaw Shape">
+ Kæbeform
+ </string>
+ <string name="Join">
+ Saml
+ </string>
+ <string name="Jowls">
+ Kindehud
+ </string>
+ <string name="Knee Angle">
+ Knævinkel
+ </string>
+ <string name="Knock Kneed">
+ Kalveknæet
+ </string>
+ <string name="Large">
+ Stor
+ </string>
+ <string name="Large Hands">
+ Store hænder
+ </string>
+ <string name="Left Part">
+ Venstre side
+ </string>
+ <string name="Leg Length">
+ Benlængde
+ </string>
+ <string name="Leg Muscles">
+ Benmuskler
+ </string>
+ <string name="Less">
+ Mindre
+ </string>
+ <string name="Less Body Fat">
+ Mindre kropsfedt
+ </string>
+ <string name="Less Curtains">
+ Mindre
+ </string>
+ <string name="Less Freckles">
+ Færre fregner
+ </string>
+ <string name="Less Full">
+ Mindre
+ </string>
+ <string name="Less Gravity">
+ Mindre
+ </string>
+ <string name="Less Love">
+ Mindre bildæk
+ </string>
+ <string name="Less Muscles">
+ Færre muskler
+ </string>
+ <string name="Less Muscular">
+ Mindre muskuløs
+ </string>
+ <string name="Less Rosy">
+ Mindre rosa
+ </string>
+ <string name="Less Round">
+ Mindre rund
+ </string>
+ <string name="Less Saddle">
+ Mindre
+ </string>
+ <string name="Less Square">
+ Mindre
+ </string>
+ <string name="Less Volume">
+ Mindre
+ </string>
+ <string name="Less soul">
+ Mindre
+ </string>
+ <string name="Lighter">
+ Lettere
+ </string>
+ <string name="Lip Cleft">
+ Læbekløft
+ </string>
+ <string name="Lip Cleft Depth">
+ Dybde læbekløft
+ </string>
+ <string name="Lip Fullness">
+ Fyldige læber
+ </string>
+ <string name="Lip Pinkness">
+ Lyserøde læber
+ </string>
+ <string name="Lip Ratio">
+ Læbeproportioner
+ </string>
+ <string name="Lip Thickness">
+ Læbetykkelse
+ </string>
+ <string name="Lip Width">
+ Læbebredde
+ </string>
+ <string name="Lipgloss">
+ Lipgloss
+ </string>
+ <string name="Lipstick">
+ Læbestift
+ </string>
+ <string name="Lipstick Color">
+ Læbestift farve
+ </string>
+ <string name="Long">
+ Lang
+ </string>
+ <string name="Long Head">
+ Langt hovede
+ </string>
+ <string name="Long Hips">
+ Lange hofter
+ </string>
+ <string name="Long Legs">
+ Bange ben
+ </string>
+ <string name="Long Neck">
+ Lang hals
+ </string>
+ <string name="Long Pigtails">
+ Lange rottehaler
+ </string>
+ <string name="Long Ponytail">
+ Lang hestehale
+ </string>
+ <string name="Long Torso">
+ Lang overkrop
+ </string>
+ <string name="Long arms">
+ Lange arme
+ </string>
+ <string name="Longcuffs">
+ Longcuffs
+ </string>
+ <string name="Loose Pants">
+ Løse bukser
+ </string>
+ <string name="Loose Shirt">
+ Løs trøje
+ </string>
+ <string name="Loose Sleeves">
+ Løse ærmer
+ </string>
+ <string name="Love Handles">
+ Bildæk
+ </string>
+ <string name="Low">
+ Lav
+ </string>
+ <string name="Low Heels">
+ Flade hæle
+ </string>
+ <string name="Low Jaw">
+ Lav kæbe
+ </string>
+ <string name="Low Platforms">
+ Flade såler
+ </string>
+ <string name="Low and Loose">
+ Lav og løs
+ </string>
+ <string name="Lower">
+ Nedre
+ </string>
+ <string name="Lower Bridge">
+ Nedre næseryg
+ </string>
+ <string name="Lower Cheeks">
+ Nedre kinder
+ </string>
+ <string name="Male">
+ Mand
+ </string>
+ <string name="Middle Part">
+ Midterste del
+ </string>
+ <string name="More">
+ Mere
+ </string>
+ <string name="More Blush">
+ Mere rødmen
+ </string>
+ <string name="More Body Fat">
+ Mere kropsfedt
+ </string>
+ <string name="More Curtains">
+ Mere
+ </string>
+ <string name="More Eyeshadow">
+ Mere øjenskygge
+ </string>
+ <string name="More Freckles">
+ Flere fregner
+ </string>
+ <string name="More Full">
+ Mere
+ </string>
+ <string name="More Gravity">
+ More
+ </string>
+ <string name="More Lipstick">
+ Mere læbestift
+ </string>
+ <string name="More Love">
+ Mere bildæk
+ </string>
+ <string name="More Lower Lip">
+ Mere underlæbe
+ </string>
+ <string name="More Muscles">
+ Flere muskler
+ </string>
+ <string name="More Muscular">
+ Mere muskuløs
+ </string>
+ <string name="More Rosy">
+ Mere rosa
+ </string>
+ <string name="More Round">
+ Mere rund
+ </string>
+ <string name="More Saddle">
+ Mere
+ </string>
+ <string name="More Sloped">
+ Mere skrå
+ </string>
+ <string name="More Square">
+ Mere firkantet
+ </string>
+ <string name="More Upper Lip">
+ Mere overlæbe
+ </string>
+ <string name="More Vertical">
+ Mere lodret
+ </string>
+ <string name="More Volume">
+ Mere
+ </string>
+ <string name="More soul">
+ Mere
+ </string>
+ <string name="Moustache">
+ Overskæg
+ </string>
+ <string name="Mouth Corner">
+ Mundvige
+ </string>
+ <string name="Mouth Position">
+ Position mund
+ </string>
+ <string name="Mowhawk">
+ Intet hår
+ </string>
+ <string name="Muscular">
+ Muskuløs
+ </string>
+ <string name="Mutton Chops">
+ Lange
+ </string>
+ <string name="Nail Polish">
+ Neglelak
+ </string>
+ <string name="Nail Polish Color">
+ Neglelak farve
+ </string>
+ <string name="Narrow">
+ Smal
+ </string>
+ <string name="Narrow Back">
+ Smal bagtil
+ </string>
+ <string name="Narrow Front">
+ Smal fortil
+ </string>
+ <string name="Narrow Lips">
+ Smalle læber
+ </string>
+ <string name="Natural">
+ Naturlig
+ </string>
+ <string name="Neck Length">
+ Halslængde
+ </string>
+ <string name="Neck Thickness">
+ Halstykkelse
+ </string>
+ <string name="No Blush">
+ Ingen rødmen
+ </string>
+ <string name="No Eyeliner">
+ Ingen eyeliner
+ </string>
+ <string name="No Eyeshadow">
+ Ingen øjenskygge
+ </string>
+ <string name="No Heels">
+ Ingen hæle
+ </string>
+ <string name="No Lipgloss">
+ Ingen lipgloss
+ </string>
+ <string name="No Lipstick">
+ Ingen læbestift
+ </string>
+ <string name="No Part">
+ Ingen dele
+ </string>
+ <string name="No Polish">
+ Ingen lak
+ </string>
+ <string name="No Red">
+ Ingen rød
+ </string>
+ <string name="No Spikes">
+ Ingen spikes
+ </string>
+ <string name="No White">
+ Ingen hvid
+ </string>
+ <string name="No Wrinkles">
+ Ingen rynker
+ </string>
+ <string name="Normal Lower">
+ Normal nedre
+ </string>
+ <string name="Normal Upper">
+ Normal øvre
+ </string>
+ <string name="Nose Left">
+ Højre
+ </string>
+ <string name="Nose Right">
+ Venstre
+ </string>
+ <string name="Nose Size">
+ Næse størrelse
+ </string>
+ <string name="Nose Thickness">
+ Næse tykkelse
+ </string>
+ <string name="Nose Tip Angle">
+ Næsetip vinkel
+ </string>
+ <string name="Nose Tip Shape">
+ Næsetip form
+ </string>
+ <string name="Nose Width">
+ Næse bredde
+ </string>
+ <string name="Nostril Division">
+ Næsebor adskillelse
+ </string>
+ <string name="Nostril Width">
+ Næsebor bredde
+ </string>
+ <string name="Old">
+ Gammel
+ </string>
+ <string name="Opaque">
+ Uigennemsigtig
+ </string>
+ <string name="Open">
+ Ã…ben
+ </string>
+ <string name="Open Back">
+ Ã…ben bagtil
+ </string>
+ <string name="Open Front">
+ Ã…ben foran
+ </string>
+ <string name="Open Left">
+ Ã…ben til venstre
+ </string>
+ <string name="Open Right">
+ Åben til højre
+ </string>
+ <string name="Orange">
+ Orange
+ </string>
+ <string name="Out">
+ Ud
+ </string>
+ <string name="Out Shdw Color">
+ Ydre skygge farve
+ </string>
+ <string name="Out Shdw Opacity">
+ Ydre skygge uigennemsigtighed
+ </string>
+ <string name="Outer Eye Corner">
+ Yderste del af øje
+ </string>
+ <string name="Outer Eye Shadow">
+ Ydre øjenskygge
+ </string>
+ <string name="Outer Shadow">
+ Ydre skygge
+ </string>
+ <string name="Overbite">
+ Overbid
+ </string>
+ <string name="Package">
+ Skridt
+ </string>
+ <string name="Painted Nails">
+ Malede negle
+ </string>
+ <string name="Pale">
+ Bleg
+ </string>
+ <string name="Pants Crotch">
+ Bukser skridt
+ </string>
+ <string name="Pants Fit">
+ Pasform bukser
+ </string>
+ <string name="Pants Length">
+ Bukser - længde
+ </string>
+ <string name="Pants Waist">
+ Bukser - vidde
+ </string>
+ <string name="Pants Wrinkles">
+ Bukser - rynker
+ </string>
+ <string name="Part">
+ Skilning
+ </string>
+ <string name="Part Bangs">
+ Skilning
+ </string>
+ <string name="Pectorals">
+ Brystmuskler
+ </string>
+ <string name="Pigment">
+ Pigmentering
+ </string>
+ <string name="Pigtails">
+ Rottehaler
+ </string>
+ <string name="Pink">
+ Pink
+ </string>
+ <string name="Pinker">
+ Mere pink
+ </string>
+ <string name="Platform Height">
+ Højde sål
+ </string>
+ <string name="Platform Width">
+ Bredde sål
+ </string>
+ <string name="Pointy">
+ Spids
+ </string>
+ <string name="Pointy Heels">
+ Spidse hæle
+ </string>
+ <string name="Pointy Toe">
+ Spids snude
+ </string>
+ <string name="Ponytail">
+ Hestehale
+ </string>
+ <string name="Poofy Skirt">
+ Strutskørt
+ </string>
+ <string name="Pop Left Eye">
+ Forstør venstre øje
+ </string>
+ <string name="Pop Right Eye">
+ Forstør højre øje
+ </string>
+ <string name="Puffy">
+ Posede
+ </string>
+ <string name="Puffy Eyelids">
+ Posede øjenlåg
+ </string>
+ <string name="Rainbow Color">
+ Regnbue farver
+ </string>
+ <string name="Red Hair">
+ Rødt hår
+ </string>
+ <string name="Red Skin">
+ Rød hud
+ </string>
+ <string name="Regular">
+ Almindelig
+ </string>
+ <string name="Regular Muscles">
+ Almindelige muskler
+ </string>
+ <string name="Right Part">
+ Højre skildning
+ </string>
+ <string name="Rosy Complexion">
+ Rosa teint
+ </string>
+ <string name="Round">
+ Rund
+ </string>
+ <string name="Round Forehead">
+ Rund pande
+ </string>
+ <string name="Ruddiness">
+ Rødmossethed
+ </string>
+ <string name="Ruddy">
+ Rødmosset
+ </string>
+ <string name="Rumpled Hair">
+ Krøllet hår
+ </string>
+ <string name="Saddle Bags">
+ Ridebukselår
+ </string>
+ <string name="Saddlebags">
+ Ridebukselår
+ </string>
+ <string name="Scrawny">
+ Radmager
+ </string>
+ <string name="Scrawny Leg">
+ Magert ben
+ </string>
+ <string name="Separate">
+ Separat
+ </string>
+ <string name="Shading">
+ Skygger
+ </string>
+ <string name="Shadow hair">
+ Skygge hår
+ </string>
+ <string name="Shallow">
+ Lille
+ </string>
+ <string name="Shear Back">
+ Afklippet bagi
+ </string>
+ <string name="Shear Face">
+ Skævt ansigt
+ </string>
+ <string name="Shear Front">
+ &quot;MÃ¥ne&quot;
+ </string>
+ <string name="Shear Left">
+ Venstre
+ </string>
+ <string name="Shear Left Up">
+ Venstre op
+ </string>
+ <string name="Shear Right">
+ Højre
+ </string>
+ <string name="Shear Right Up">
+ Højre op
+ </string>
+ <string name="Sheared Back">
+ Afklippet bagtil
+ </string>
+ <string name="Sheared Front">
+ MÃ¥ne
+ </string>
+ <string name="Shift Left">
+ Mod venstre
+ </string>
+ <string name="Shift Mouth">
+ Flyt mund
+ </string>
+ <string name="Shift Right">
+ Mod højre
+ </string>
+ <string name="Shirt Bottom">
+ Trøje - bund
+ </string>
+ <string name="Shirt Fit">
+ Trøje - pasform
+ </string>
+ <string name="Shirt Wrinkles">
+ Trøje - rynker
+ </string>
+ <string name="Shoe Height">
+ Sko højde
+ </string>
+ <string name="Short">
+ Kort
+ </string>
+ <string name="Short Arms">
+ Korte arme
+ </string>
+ <string name="Short Legs">
+ Korte ben
+ </string>
+ <string name="Short Neck">
+ Kort hals
+ </string>
+ <string name="Short Pigtails">
+ Korte rottehaler
+ </string>
+ <string name="Short Ponytail">
+ Kort hestehale
+ </string>
+ <string name="Short Sideburns">
+ Korte
+ </string>
+ <string name="Short Torso">
+ Kort overkrop
+ </string>
+ <string name="Short hips">
+ Korte hofter
+ </string>
+ <string name="Shoulders">
+ Skuldre
+ </string>
+ <string name="Side Bangs">
+ Sidehår
+ </string>
+ <string name="Side Bangs Down">
+ Ned
+ </string>
+ <string name="Side Bangs Up">
+ Op
+ </string>
+ <string name="Side Fringe">
+ Side frynser
+ </string>
+ <string name="Sideburns">
+ Bakkenbarter
+ </string>
+ <string name="Sides Hair">
+ Sidehår
+ </string>
+ <string name="Sides Hair Down">
+ Ned
+ </string>
+ <string name="Sides Hair Up">
+ Op
+ </string>
+ <string name="Skinny">
+ Tynd
+ </string>
+ <string name="Skinny Neck">
+ Tynd hals
+ </string>
+ <string name="Skirt Fit">
+ Omfang
+ </string>
+ <string name="Skirt Length">
+ Længde nederdel
+ </string>
+ <string name="Slanted Forehead">
+ Skrånende pande
+ </string>
+ <string name="Sleeve Length">
+ Ærmelængde
+ </string>
+ <string name="Sleeve Looseness">
+ Ærmer - stramhed
+ </string>
+ <string name="Slit Back">
+ Slids: Bag
+ </string>
+ <string name="Slit Front">
+ Slids: Foran
+ </string>
+ <string name="Slit Left">
+ Slids: Venstre
+ </string>
+ <string name="Slit Right">
+ Slids: Højre
+ </string>
+ <string name="Small">
+ Lille
+ </string>
+ <string name="Small Hands">
+ Små hænder
+ </string>
+ <string name="Small Head">
+ Lille hovede
+ </string>
+ <string name="Smooth">
+ Glat
+ </string>
+ <string name="Smooth Hair">
+ Glat hår
+ </string>
+ <string name="Socks Length">
+ Strømper - længde
+ </string>
+ <string name="Some">
+ Nogen
+ </string>
+ <string name="Soulpatch">
+ Soulpatch
+ </string>
+ <string name="Sparse">
+ Sparsomt
+ </string>
+ <string name="Spiked Hair">
+ HÃ¥r med &quot;spikes&quot;
+ </string>
+ <string name="Square">
+ Firkantet
+ </string>
+ <string name="Square Toe">
+ Firkantet snude
+ </string>
+ <string name="Squash Head">
+ Bredt hovede
+ </string>
+ <string name="Squash/Stretch Head">
+ Sammentryk/stræk hovede
+ </string>
+ <string name="Stretch Head">
+ Stræk hovede
+ </string>
+ <string name="Sunken">
+ Indsunket
+ </string>
+ <string name="Sunken Chest">
+ Indsunket bryst
+ </string>
+ <string name="Sunken Eyes">
+ Dybtliggende øjne
+ </string>
+ <string name="Sweep Back">
+ Stryge tilbage
+ </string>
+ <string name="Sweep Forward">
+ Stryge fremad
+ </string>
+ <string name="Swept Back">
+ Tilbagestrøget
+ </string>
+ <string name="Swept Back Hair">
+ Tilbagestrøget hår
+ </string>
+ <string name="Swept Forward">
+ Fremadstrøget
+ </string>
+ <string name="Swept Forward Hair">
+ Fremadstrøget hår
+ </string>
+ <string name="Tall">
+ Høj
+ </string>
+ <string name="Taper Back">
+ Indsnævring bag
+ </string>
+ <string name="Taper Front">
+ Indsnævring foran
+ </string>
+ <string name="Thick Heels">
+ Brede hæle
+ </string>
+ <string name="Thick Neck">
+ Bred nakke
+ </string>
+ <string name="Thick Toe">
+ Bred snude
+ </string>
+ <string name="Thickness">
+ Tykkelse
+ </string>
+ <string name="Thin">
+ Tynd
+ </string>
+ <string name="Thin Eyebrows">
+ Tynde øjenbryn
+ </string>
+ <string name="Thin Lips">
+ Tynde læber
+ </string>
+ <string name="Thin Nose">
+ Tynd næse
+ </string>
+ <string name="Tight Chin">
+ Stram hage
+ </string>
+ <string name="Tight Cuffs">
+ Smalle bukseben
+ </string>
+ <string name="Tight Pants">
+ Stramme bukser
+ </string>
+ <string name="Tight Shirt">
+ Stram trøje
+ </string>
+ <string name="Tight Skirt">
+ Stram nederdel
+ </string>
+ <string name="Tight Sleeves">
+ Stramme ærmer
+ </string>
+ <string name="Tilt Left">
+ Hæld til venstre
+ </string>
+ <string name="Tilt Right">
+ Hæld til højre
+ </string>
+ <string name="Toe Shape">
+ Sko form
+ </string>
+ <string name="Toe Thickness">
+ Tykkelse af snud
+ </string>
+ <string name="Torso Length">
+ Overkrop - længde
+ </string>
+ <string name="Torso Muscles">
+ Overkrop - muskler
+ </string>
+ <string name="Torso Scrawny">
+ Overkrop - mager
+ </string>
+ <string name="Unattached">
+ Ikke vedhæftet
+ </string>
+ <string name="Uncreased">
+ Glat
+ </string>
+ <string name="Underbite">
+ Underbid
+ </string>
+ <string name="Unnatural">
+ Unaturlig
+ </string>
+ <string name="Upper Bridge">
+ Øverste næseryg
+ </string>
+ <string name="Upper Cheeks">
+ Øvre kinder
+ </string>
+ <string name="Upper Chin Cleft">
+ Øvre hagekløft
+ </string>
+ <string name="Upper Eyelid Fold">
+ Øvre øjenlåg
+ </string>
+ <string name="Upturned">
+ Opadvendt
+ </string>
+ <string name="Very Red">
+ Meget rød
+ </string>
+ <string name="Waist Height">
+ Talje højde
+ </string>
+ <string name="Well-Fed">
+ Velnæret
+ </string>
+ <string name="White Hair">
+ Hvidt hår
+ </string>
+ <string name="Wide">
+ Bred
+ </string>
+ <string name="Wide Back">
+ Bredt
+ </string>
+ <string name="Wide Front">
+ Bredt
+ </string>
+ <string name="Wide Lips">
+ Brede læber
+ </string>
+ <string name="Wild">
+ Vildt
+ </string>
+ <string name="Wrinkles">
+ Rynker
+ </string>
+ <string name="LocationCtrlAddLandmarkTooltip">
+ Tilføj til mine landemærker
+ </string>
+ <string name="LocationCtrlEditLandmarkTooltip">
+ Rediger mit landemærke
+ </string>
+ <string name="LocationCtrlInfoBtnTooltip">
+ Se yderligere information om nuværende lokation
+ </string>
+ <string name="LocationCtrlComboBtnTooltip">
+ Min lokationshistorik
+ </string>
+ <string name="UpdaterWindowTitle">
+ [APP_NAME] Opdatér
+ </string>
+ <string name="UpdaterNowUpdating">
+ Opdaterer nu [APP_NAME]...
+ </string>
+ <string name="UpdaterNowInstalling">
+ Installerer [APP_NAME]...
+ </string>
+ <string name="UpdaterUpdatingDescriptive">
+ Din [APP_NAME] klient bliver opdateret til nyeste version. Dette kan tage noget tid, så venligst vær tålmodig.
+ </string>
+ <string name="UpdaterProgressBarTextWithEllipses">
+ Download færdig...
+ </string>
+ <string name="UpdaterProgressBarText">
+ Downloader opdatering
+ </string>
+ <string name="UpdaterFailDownloadTitle">
+ Download af opdatering fejlede
+ </string>
+ <string name="UpdaterFailUpdateDescriptive">
+ Der opstod en fejl ved opdatering af [APP_NAME]. Hent venligst den nyeste version fra www.secondlife.com.
+ </string>
+ <string name="UpdaterFailInstallTitle">
+ Installation af opdatering fejlede
+ </string>
+ <string name="UpdaterFailStartTitle">
+ Opstart af klient fejlede
+ </string>
+ <string name="IM_logging_string">
+ -- Logning af IM aktiveret --
+ </string>
+ <string name="IM_typing_start_string">
+ [NAME] skriver...
+ </string>
+ <string name="Unnamed">
+ (Uden navn)
+ </string>
+ <string name="IM_moderated_chat_label">
+ (Modereret: Stemmer deaktiveret)
+ </string>
+ <string name="IM_unavailable_text_label">
+ Tekst chat er ikke tilgængelig i denne samtale.
+ </string>
+ <string name="IM_muted_text_label">
+ Din tekst chat er blevet deaktiveret af en gruppe moderator.
+ </string>
+ <string name="IM_default_text_label">
+ Klik her for privat besked (IM).
+ </string>
+ <string name="IM_to_label">
+ Til
+ </string>
+ <string name="IM_moderator_label">
+ (Moderator)
+ </string>
+ <string name="only_user_message">
+ Du er den eneste deltager i denne samtale
+ </string>
+ <string name="offline_message">
+ [FIRST] [LAST] er ikke logget på.
+ </string>
+ <string name="invite_message">
+ Tryk på [BUTTON NAME] knappen for at acceptére/tilslutte til denne stemme chat.
+ </string>
+ <string name="muted_message">
+ Du har blokeret denne beboer. Hvis du starter en samtale vil denne blokering automatisk blive fjernet.
+ </string>
+ <string name="generic_request_error">
+ Kunne ikke etablere forbindelse, prøv igen senere
+ </string>
+ <string name="insufficient_perms_error">
+ Du har ikke de fornødne rettigheder.
+ </string>
+ <string name="session_does_not_exist_error">
+ Denne samtale er lukket ned
+ </string>
+ <string name="no_ability_error">
+ Du har ikke den mulighed.
+ </string>
+ <string name="no_ability">
+ Du har ikke den mulighed.
+ </string>
+ <string name="not_a_mod_error">
+ Du er ikke moderator for denne samtale.
+ </string>
+ <string name="muted_error">
+ Du er blevet &quot;blokeret&quot;.
+ </string>
+ <string name="add_session_event">
+ Ikke muligt at tilføge brugere til samtale med [RECIPIENT].
+ </string>
+ <string name="message_session_event">
+ Ikke muligt at sende din besked til samtalen med [RECIPIENT].
+ </string>
+ <string name="removed_from_group">
+ Du er blevet fjernet fra gruppen.
+ </string>
+ <string name="close_on_no_ability">
+ Du har ikke længere mulighed for at deltage i samtalen
+ </string>
</strings>
diff --git a/indra/newview/skins/default/xui/da/teleport_strings.xml b/indra/newview/skins/default/xui/da/teleport_strings.xml
index 78052b4ef5..43f8e5144d 100644
--- a/indra/newview/skins/default/xui/da/teleport_strings.xml
+++ b/indra/newview/skins/default/xui/da/teleport_strings.xml
@@ -1,22 +1,17 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<teleport_messages>
<message_set name="errors">
<message name="invalid_tport">
- Der er problemer med at håndtere din teleport.
-Det kan være nødvendigt at logge ud og ind for at kunne skifte teleportere.
-Hvis du bliver ved med at have problemet kan du checke teknisk support på:
-www.secondlife.com/support.
+ Der er problemer med at håndtere din teleport. Det kan være nødvendigt at logge ud og ind for at kunne skifte teleportere.
+Hvis du bliver ved med at have problemet kan du checke teknisk support på: [SUPPORT_SITE].
</message>
<message name="invalid_region_handoff">
- Problem registreret i forbindelse med skift til ny region.
-Det kan være nødvendigt at logge ud og ind for at kunne skifte regioner.
-Hvis du bliver ved med at have problemet kan du checke teknisk support på:
-www.secondlife.com/support.
+ Problem registreret i forbindelse med skift til ny region. Det kan være nødvendigt at logge ud og ind for at kunne skifte regioner.
+Hvis du bliver ved med at have problemet kan du checke teknisk support på: [SUPPORT_SITE].
</message>
<message name="blocked_tport">
Beklager, teleport er blokeret lige nu. Prøv igen senere.
-Hvis du stadig ikke kan teleporte, prøv venligst at logge ud og ligge
-ind for at løse dette problem.
+Hvis du stadig ikke kan teleporte, prøv venligst at logge ud og ligge ind for at løse dette problem.
</message>
<message name="nolandmark_tport">
Beklager, systemet kunne ikke finde landmærke destinationen.
@@ -29,24 +24,20 @@ Prøv igen om lidt.
Beklager, du har ikke adgang til denne teleport destination.
</message>
<message name="missing_attach_tport">
- Dine vedhæng er ikke ankommet endnu. Prøv at vente lidt endnu
-eller log ud og ind igen før du prøver at teleporte igen.
+ Dine vedhæng er ikke ankommet endnu. Prøv at vente lidt endnu eller log ud og ind igen før du prøver at teleporte igen.
</message>
<message name="too_many_uploads_tport">
Tekniske problemer hindrer at din teleport kan gennemføres.
Prøv venligst igen om lidt eller vælg et mindre travlt område.
</message>
<message name="expired_tport">
- Beklager, men systemet kunne ikke fuldføre din teleport
-i rimelig tid. Prøv venligst igen om lidt.
+ Beklager, men systemet kunne ikke fuldføre din teleport i rimelig tid. Prøv venligst igen om lidt.
</message>
<message name="expired_region_handoff">
- Beklager, men systemet kunne ikke fuldføre skift til anden region
-i rimelig tid. Prøv venligst igen om lidt.
+ Beklager, men systemet kunne ikke fuldføre skift til anden region i rimelig tid. Prøv venligst igen om lidt.
</message>
<message name="no_host">
- Ikke muligt at fine teleport destination. Destinationen kan
-være midlertidig utilgængelig eller findes ikke mere.
+ Ikke muligt at fine teleport destination. Destinationen kan være midlertidig utilgængelig eller findes ikke mere.
Prøv evt. igen om lidt.
</message>
<message name="no_inventory_host">
diff --git a/indra/newview/skins/default/xui/de/floater_about.xml b/indra/newview/skins/default/xui/de/floater_about.xml
index c3935882af..0beb54032f 100644
--- a/indra/newview/skins/default/xui/de/floater_about.xml
+++ b/indra/newview/skins/default/xui/de/floater_about.xml
@@ -1,11 +1,60 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_about" title="Ãœber Second Life">
- <text_editor name="credits_editor">
- Second Life wird Ihnen präsentiert von Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les und vielen anderen.
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_about" title="INFO ÃœBER [CAPITALIZED_APP_NAME]">
+ <floater.string name="AboutHeader">
+ [APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL])
+[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]]
+ </floater.string>
+ <floater.string name="AboutCompiler">
+ Kompiliert mit [COMPILER] version [COMPILER_VERSION]
+ </floater.string>
+ <floater.string name="AboutPosition">
+ Sie befinden sich in [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] in [REGION] auf [HOSTNAME] ([HOSTIP])
+[SERVER_VERSION]
+[[SERVER_RELEASE_NOTES_URL] [ReleaseNotes]]
+ </floater.string>
+ <floater.string name="AboutSystem">
+ CPU: [CPU]
+Speicher: [MEMORY_MB] MB
+Betriebssystem, Version: [OS_VERSION]
+Grafikkarten-Hersteller: [GRAPHICS_CARD_VENDOR]
+Grafikkarten: [GRAPHICS_CARD]
+ </floater.string>
+ <floater.string name="AboutDriver">
+ Windows Grafiktreiber-Version: [GRAPHICS_DRIVER_VERSION]
+ </floater.string>
+ <floater.string name="AboutLibs">
+ OpenGL Version: [OPENGL_VERSION]
-Vielen Dank den folgenden Einwohnern, die uns geholfen haben, dies zur bisher besten Version zu machen: afon shepherd, Aimee Trescothick, Alexandrea Fride, Alissa Sabre, Amber DeCuir, Asuka Neely, Auron Forcella, Blue Revolution, Bocan Undercroft, Boroondas Gupte, Brandon Shinobu, Bri Gufler, Buckaroo Mu, Celierra Darling, Christos Atlantis, Coder Kas, Cummere Mayo, dakota schwade, Dirk Talamasca, Dizzy Banjo, Drew Dwi, Duckling Kwak, Ellla McMahon, Erikah Jameson, Erinyse Planer, Eyana Yohkoh, Ezian Ecksol, Faron Karu, Fenoe Lowey, Fox Hwasung, Francisca Biedermann, Gally Young, Gellan Glenelg, Geneko Nemeth, Glenn Rotaru, Hagar Qinan, Harleen Gretzky, Holger Gilruth, hotrodjohnny gears, IAm Zabelin, Inigo Catteneo, Iustinian Tomsen, Jacek Antonell, James Benedek, Jim Kupferberg, Joeseph Albanese, JPT62089 Agnon, Kardargo Adamczyk, Kirstenlee Cinquetti, Latif Khalifa, lea Parnall, Lex Neva, Lillith Anatine, Lilly Zenovka, Lim Catteneo, Lindal Kidd, Mark Rosenbaum, MasterJ Chaplin, McCabe Maxsted, Melvin Starbrook, Meni Kaiousei, Mero Collas, Minakothegothicgeisha Kamachi, Moon Metty, neofilo aabye, Neutron Chesnokov, Nomad Ingwer, norritt Xi, Opensource Obscure, Oracle Weatherwax, Ourasi Ferraris, Pabl0 Roffo, Peyton Aleixandre, Phli Foxchase, Psi Merlin, r2d2 Wunderlich, Regi Yifu, Saijanai Kuhn, Sandor Balczo, Sarkan Dreamscape, Scree Raymaker, Sedona Mills, Selena Beale, Sheet Spotter, Shibari Twine, Silver Key, Simon Kline, SLB Wirefly, Stacy Wombat, Sugarcult Dagger, Tayra Dagostino, Tetsuryu Vlodovic, ThaBiGGDoGG Richez, Timo Gufler, tx Oh, wayfinder wishbringer, Wizzytoe McCullough, Wundur Primbee, Yann Dufaux, Yuu Nakamichi, Aminom Marvin, Andred Qinan, arminasx saiman, caroline apollo, Iskar Ariantho, Jenika Connolly, Maghnus Balogh, Nefertiti Nefarious, RodneyLee Jessop
+libcurl-Version: [LIBCURL_VERSION]
+J2C-Decoderversion: [J2C_VERSION]
+Audio-Treiberversion: [AUDIO_DRIVER_VERSION]
+Qt Webkit Version: [QT_WEBKIT_VERSION]
+Vivox-Version: [VIVOX_VERSION]
+ </floater.string>
+ <floater.string name="none">
+ (keiner)
+ </floater.string>
+ <floater.string name="AboutTraffic">
+ Paketverlust: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%)
+ </floater.string>
+ <tab_container name="about_tab">
+ <panel label="Info" name="support_panel">
+ <button label="In Zwischenablage kopieren" name="copy_btn"/>
+ </panel>
+ <panel label="Danksagung" name="credits_panel">
+ <text_editor name="credits_editor">
+ Second Life wird Ihnen präsentiert von Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, Michon, Jenelle, Geo, Siz, Shapiro, Pete, Calyle, Selene, Allen, Phoebe, Goldin, Kimmora, Dakota, Slaton, Lindquist, Zoey, Hari, Othello, Rohit, Sheldon, Petra, Viale, Gordon, Kaye, Pink, Ferny, Emerson, Davy, Bri, Chan, Juan, Robert, Terrence, Nathan, Carl und vielen anderen.
-3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
+Vielen Dank den folgenden Einwohnern, die uns geholfen haben, dies zur bisher besten Version zu machen: able whitman, Adeon Writer, adonaira aabye, Aeron Kohime, Agathos Frascati, Aimee Trescothick, Aleric Inglewood, Alissa Sabre, Aminom Marvin, Angela Talamasca, Aralara Rajal, Armin Weatherwax, Ashrilyn Hayashida, Athanasius Skytower, Aura Dirval, Barney Boomslang, Biancaluce Robbiani, Biker Offcourse, Borg Capalini, Bulli Schumann, catherine pfeffer, Chalice Yao, Corre Porta, Court Goodman, Cummere Mayo, Dale Innis, Darien Caldwell, Darjeeling Schoonhoven, Daten Thielt, dimentox travanti, Dirk Talamasca, Drew Dwi, Duckless Vandyke, Elanthius Flagstaff, Electro Burnstein, emiley tomsen, Escort DeFarge, Eva Rau, Ezian Ecksol, Fire Centaur, Fluf Fredriksson, Francisco Koolhoven, Frontera Thor, Frungi Stastny, Gally Young, gearsawe stonecutter, Gigs Taggart, Gordon Wendt, Gudmund Shepherd, Gypsy Paz, Harleen Gretzky, Henri Beauchamp, Inma Rau, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Jessicka Graves, Joeseph Albanese, Joshua Philgarlic, Khyota Wulluf, kirstenlee Cinquetti, Latif Khalifa, Lex Neva, Lilibeth Andree, Lisa Lowe, Lunita Savira, Loosey Demonia, lum pfohl, Marcos Fonzarelli, MartinRJ Fayray, Marusame Arai, Matthew Dowd, Maya Remblai, McCabe Maxsted, Meghan Dench, Melchoir Tokhes, Menos Short, Michelle2 Zenovka, Mimika Oh, Minerva Memel, Mm Alder, Ochi Wolfe, Omei Turnbull, Pesho Replacement, Phantom Ninetails, phoenixflames kukulcan, Polo Gufler, prez pessoa, princess niven, Prokofy Neva, Qie Niangao, Rem Beattie, RodneyLee Jessop, Saijanai Kuhn, Seg Baphomet, Sergen Davies, Shirley Marquez, SignpostMarv Martin, Sindy Tsure, Sira Arbizu, Skips Jigsaw, Sougent Harrop, Spritely Pixel, Squirrel Wood, StarSong Bright, Subversive Writer, Sugarcult Dagger, Sylumm Grigorovich, Tammy Nowotny, Tanooki Darkes, Tayra Dagostino, Theoretical Chemistry, Thickbrick Sleaford, valerie rosewood, Vex Streeter, Vixen Heron, Whoops Babii, Winter Ventura, Xiki Luik, Yann Dufaux, Yina Yao, Yukinoroh Kamachi, Zolute Infinity, Zwagoth Klaar
+
+
+
+Um im Geschäftsleben erfolreich zu sein, sei kühn, sei schnell, sei anders. --Henry Marchant
+ </text_editor>
+ </panel>
+ <panel label="Lizenzen" name="licenses_panel">
+ <text_editor name="credits_editor">
+ 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
APR Copyright (C) 2000-2004 The Apache Software Foundation
cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
@@ -25,11 +74,7 @@ google-perftools Copyright (c) 2005, Google Inc.
Alle Rechte vorbehalten. Details siehe licenses.txt.
Voice-Chat-Audiocoding: Polycom(R) Siren14(TM) (ITU-T Empf.G.722.1 Anhang C)
-
-
-Um im Geschäftsleben erfolreich zu sein, sei kühn, sei schnell, sei anders. --Henry Marchant
- </text_editor>
- <text name="you_are_at">
- Sie befinden sich in [POSITION]
- </text>
+ </text_editor>
+ </panel>
+ </tab_container>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_about_land.xml b/indra/newview/skins/default/xui/de/floater_about_land.xml
index 93e7297fd2..af489d39d2 100644
--- a/indra/newview/skins/default/xui/de/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/de/floater_about_land.xml
@@ -1,7 +1,59 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterland" title="Land-Info">
+<floater name="floaterland" title="LAND-INFO">
+ <floater.string name="Minutes">
+ [MINUTES] Minuten
+ </floater.string>
+ <floater.string name="Minute">
+ Minute
+ </floater.string>
+ <floater.string name="Seconds">
+ [SECONDS] Sekunden
+ </floater.string>
+ <floater.string name="Remaining">
+ Restzeit
+ </floater.string>
<tab_container name="landtab">
<panel label="Allgemein" name="land_general_panel">
+ <panel.string name="new users only">
+ Nur neue Benutzer
+ </panel.string>
+ <panel.string name="anyone">
+ Jeder
+ </panel.string>
+ <panel.string name="area_text">
+ Gebiet:
+ </panel.string>
+ <panel.string name="area_size_text">
+ [AREA] m².
+ </panel.string>
+ <panel.string name="auction_id_text">
+ Auktions-ID: [ID]
+ </panel.string>
+ <panel.string name="need_tier_to_modify">
+ Bestätigen Sie den Kauf, um dieses Land zu bearbeiten.
+ </panel.string>
+ <panel.string name="group_owned_text">
+ (In Gruppenbesitz)
+ </panel.string>
+ <panel.string name="profile_text">
+ Profil...
+ </panel.string>
+ <panel.string name="info_text">
+ Info...
+ </panel.string>
+ <panel.string name="public_text">
+ (öffentlich)
+ </panel.string>
+ <panel.string name="none_text">
+ (keiner)
+ </panel.string>
+ <panel.string name="sale_pending_text">
+ (Wird verkauft)
+ </panel.string>
+ <panel.string name="no_selection_text">
+ Keine Parzelle ausgewählt.
+Öffnen Sie „Welt“ &gt; „Land-Info“ oder wählen Sie eine andere Parzelle aus, um Informationen darüber anzuzeigen.
+ </panel.string>
<text name="Name:">
Name:
</text>
@@ -41,7 +93,7 @@
Nicht zu verkaufen.
</text>
<text name="For Sale: Price L$[PRICE].">
- Preis: [PRICE] L$ ([PRICE_PER_SQM] L$/qm.).
+ Preis: [PRICE] L$ ([PRICE_PER_SQM]L$/m²).
</text>
<text name="SalePending"/>
<button bottom="-222" label="Land verkaufen..." label_selected="Land verkaufen..." name="Sell Land..."/>
@@ -65,7 +117,7 @@
Gebiet:
</text>
<text name="PriceText">
- 4048 qm.
+ 4.048 m²
</text>
<text name="Traffic:">
Traffic:
@@ -79,48 +131,22 @@
<button label="Land aufgeben..." label_selected="Land aufgeben..." name="Abandon Land..."/>
<button label="Land in Besitz nehmen..." label_selected="Land in Besitz nehmen..." name="Reclaim Land..."/>
<button label="Linden-Verkauf..." label_selected="Linden-Verkauf..." name="Linden Sale..." tool_tip="Land muss Eigentum und auf Inhalt gesetzt sein und nicht zur Auktion stehen."/>
- <string name="new users only">
- Nur neue Benutzer
- </string>
- <string name="anyone">
- Jeder
- </string>
- <string name="area_text">
- Gebiet:
- </string>
- <string name="area_size_text">
- [AREA] qm.
- </string>
- <string name="auction_id_text">
- Auktions-ID: [ID]
- </string>
- <string name="need_tier_to_modify">
- Bestätigen Sie den Kauf, um dieses Land zu bearbeiten.
- </string>
- <string name="group_owned_text">
- (In Gruppenbesitz)
- </string>
- <string name="profile_text">
- Profil...
- </string>
- <string name="info_text">
- Info...
- </string>
- <string name="public_text">
- (öffentlich)
- </string>
- <string name="none_text">
- (keiner)
- </string>
- <string name="sale_pending_text">
- (Wird verkauft)
- </string>
- <string name="no_selection_text">
- Keine Parzelle ausgewählt.
-Öffnen Sie „Welt“ &gt; „Land-Info“ oder wählen Sie eine andere Parzelle aus, um Informationen darüber anzuzeigen.
- </string>
</panel>
<panel label="Vertrag" name="land_covenant_panel">
+ <panel.string name="can_resell">
+ Gekauftes Land in dieser Region kann wiederverkauft werden.
+ </panel.string>
+ <panel.string name="can_not_resell">
+ Gekauftes Land in dieser Region kann nicht wiederverkauft werden.
+ </panel.string>
+ <panel.string name="can_change">
+ Gekauftes Land in dieser Region kann zusammengelegt und
+geteilt werden.
+ </panel.string>
+ <panel.string name="can_not_change">
+ Gekauftes Land in dieser Region kann nicht zusammengelegt
+und geteilt werden.
+ </panel.string>
<text name="estate_section_lbl">
Grundstück:
</text>
@@ -176,22 +202,14 @@
Land in dieser Region kann nicht zusammengelegt/geteilt
werden.
</text>
- <string name="can_resell">
- Gekauftes Land in dieser Region kann wiederverkauft werden.
- </string>
- <string name="can_not_resell">
- Gekauftes Land in dieser Region kann nicht wiederverkauft werden.
- </string>
- <string name="can_change">
- Gekauftes Land in dieser Region kann zusammengelegt und
-geteilt werden.
- </string>
- <string name="can_not_change">
- Gekauftes Land in dieser Region kann nicht zusammengelegt
-und geteilt werden.
- </string>
</panel>
<panel label="Objekte" name="land_objects_panel">
+ <panel.string name="objects_available_text">
+ [COUNT] von [MAX] ([AVAILABLE] verfügbar)
+ </panel.string>
+ <panel.string name="objects_deleted_text">
+ [COUNT] von [MAX] ([DELETED] werden gelöscht)
+ </panel.string>
<text name="parcel_object_bonus">
Objektbonusfaktor in Region: [BONUS]
</text>
@@ -201,12 +219,6 @@ und geteilt werden.
<text name="objects_available">
[COUNT] von [MAX] ([AVAILABLE] verfügbar)
</text>
- <string name="objects_available_text">
- [COUNT] von [MAX] ([AVAILABLE] verfügbar)
- </string>
- <string name="objects_deleted_text">
- [COUNT] von [MAX] ([DELETED] werden gelöscht)
- </string>
<text name="Primitives parcel supports:" width="200">
Von Parzelle unterstützte Primitiva:
</text>
@@ -259,18 +271,48 @@ und geteilt werden.
<button label="Liste aktualisieren" label_selected="Liste aktualisieren" name="Refresh List"/>
<button label="Objekte zurückgeben..." label_selected="Objekte zurückgeben..." name="Return objects..."/>
<name_list name="owner list">
- <column label="Typ" name="type"/>
- <column label="Name" name="name"/>
- <column label="Zählen" name="count"/>
- <column label="Aktuellster" name="mostrecent"/>
+ <name_list.columns label="Typ" name="type"/>
+ <name_list.columns label="Name" name="name"/>
+ <name_list.columns label="Zählen" name="count"/>
+ <name_list.columns label="Aktuellster" name="mostrecent"/>
</name_list>
</panel>
<panel label="Optionen" name="land_options_panel">
+ <panel.string name="search_enabled_tooltip">
+ Diese Parzelle in Suchergebnissen anzeigen.
+ </panel.string>
+ <panel.string name="search_disabled_small_tooltip">
+ Diese Option ist nicht aktiviert, weil die Parzelle 128 m² oder kleiner ist.
+Nur große Parzellen können in der Suche aufgeführt werden.
+ </panel.string>
+ <panel.string name="search_disabled_permissions_tooltip">
+ Diese Option ist nicht aktiviert, da Sie die Parzellenoptionen nicht verändern können.
+ </panel.string>
+ <panel.string name="mature_check_mature">
+ Mature-Inhalt
+ </panel.string>
+ <panel.string name="mature_check_adult">
+ Adult-Inhalt
+ </panel.string>
+ <panel.string name="mature_check_mature_tooltip">
+ Die Informationen oder Inhalte Ihrer Parzelle sind „Mature“.
+ </panel.string>
+ <panel.string name="mature_check_adult_tooltip">
+ Die Informationen oder Inhalte Ihrer Parzelle sind „Adult“.
+ </panel.string>
+ <panel.string name="landing_point_none">
+ (keiner)
+ </panel.string>
+ <panel.string name="push_restrict_text">
+ Kein Stoßen
+ </panel.string>
+ <panel.string name="push_restrict_region_text">
+ Kein Stoßen (regional)
+ </panel.string>
<text name="allow_label">
Anderen Einwohnern gestatten:
</text>
<check_box label="Terrain bearbeiten" name="edit land check" tool_tip="Falls aktiviert, kann jeder Ihr Land terraformen. Am besten ist es, wenn Sie diese Option deaktiviert lassen. Sie können Ihr eigenes Land jederzeit bearbeiten."/>
- <check_box label="Landmarken erstellen" name="check landmark"/>
<check_box label="Fliegen" name="check fly" tool_tip="Falls aktiviert, können Einwohner auf Ihrem Land fliegen. Falls nicht aktiviert, können Einwohner lediglich auf Ihr Land fliegen und dort landen (dann jedoch nicht wieder weiterfliegen) oder über Ihr Land hinweg fliegen."/>
<text name="allow_label2">
Objekte erstellen:
@@ -293,109 +335,36 @@ und geteilt werden.
<check_box label="Sicher (kein Schaden)" name="check safe" tool_tip="Falls aktiviert, wird Land auf Option „Sicher“ eingestellt, Kampfschäden sind deaktiviert. Falls nicht aktiviert, sind Kampfschäden aktiviert."/>
<check_box label="Kein Stoßen" name="PushRestrictCheck" tool_tip="Verhindert Skripte am Stoßen. Durch Aktivieren dieser Option verhindern Sie störendes Verhalten auf Ihrem Land."/>
<check_box label="Ort in Suche anzeigen (30 L$/Woche) unter" name="ShowDirectoryCheck" tool_tip="Diese Parzelle in Suchergebnissen anzeigen."/>
- <string name="search_enabled_tooltip">
- Diese Parzelle in Suchergebnissen anzeigen.
- </string>
- <string name="search_disabled_small_tooltip">
- Diese Option ist nicht aktiviert, da diese Parzelle nicht größer als 128 qm ist.
-Nur große Parzellen können in der Suche aufgeführt werden.
- </string>
- <string name="search_disabled_permissions_tooltip">
- Diese Option ist nicht aktiviert, da Sie die Parzellenoptionen nicht verändern können.
- </string>
<combo_box name="land category with adult">
- <combo_item name="AnyCategory">
- Alle Kategorien
- </combo_item>
- <combo_item name="LindenLocation">
- Lindenort
- </combo_item>
- <combo_item name="Adult">
- Adult
- </combo_item>
- <combo_item name="Arts&amp;Culture">
- Kunst &amp; Kultur
- </combo_item>
- <combo_item name="Business">
- Business
- </combo_item>
- <combo_item name="Educational">
- Bildung
- </combo_item>
- <combo_item name="Gaming">
- Spielen
- </combo_item>
- <combo_item name="Hangout">
- Treffpunkt
- </combo_item>
- <combo_item name="NewcomerFriendly">
- Anfängergerecht
- </combo_item>
- <combo_item name="Parks&amp;Nature">
- Parks und Natur
- </combo_item>
- <combo_item name="Residential">
- Wohngebiet
- </combo_item>
- <combo_item name="Shopping">
- Shopping
- </combo_item>
- <combo_item name="Other">
- Sonstige
- </combo_item>
+ <combo_box.item label="Alle Kategorien" name="item0"/>
+ <combo_box.item label="Lindenort" name="item1"/>
+ <combo_box.item label="Adult" name="item2"/>
+ <combo_box.item label="Kunst &amp; Kultur" name="item3"/>
+ <combo_box.item label="Business" name="item4"/>
+ <combo_box.item label="Bildung" name="item5"/>
+ <combo_box.item label="Spielen" name="item6"/>
+ <combo_box.item label="Treffpunkt" name="item7"/>
+ <combo_box.item label="Anfängergerecht" name="item8"/>
+ <combo_box.item label="Parks und Natur" name="item9"/>
+ <combo_box.item label="Wohngebiet" name="item10"/>
+ <combo_box.item label="Shopping" name="item11"/>
+ <combo_box.item label="Sonstige" name="item12"/>
</combo_box>
<combo_box left="266" name="land category" width="130">
- <combo_item name="AnyCategory">
- Alle Kategorien
- </combo_item>
- <combo_item name="LindenLocation">
- Lindenort
- </combo_item>
- <combo_item name="Arts&amp;Culture">
- Kunst und Kultur
- </combo_item>
- <combo_item name="Business">
- Business
- </combo_item>
- <combo_item name="Educational">
- Bildung
- </combo_item>
- <combo_item name="Gaming">
- Spielen
- </combo_item>
- <combo_item name="Hangout">
- Treffpunkt
- </combo_item>
- <combo_item name="NewcomerFriendly">
- Anfängergerecht
- </combo_item>
- <combo_item name="Parks&amp;Nature">
- Parks und Natur
- </combo_item>
- <combo_item name="Residential">
- Wohngebiet
- </combo_item>
- <combo_item name="Shopping">
- Shopping
- </combo_item>
- <combo_item name="Other">
- Sonstige
- </combo_item>
+ <combo_box.item label="Alle Kategorien" name="item0"/>
+ <combo_box.item label="Lindenort" name="item1"/>
+ <combo_box.item label="Kunst und Kultur" name="item3"/>
+ <combo_box.item label="Business" name="item4"/>
+ <combo_box.item label="Bildung" name="item5"/>
+ <combo_box.item label="Spielen" name="item6"/>
+ <combo_box.item label="Treffpunkt" name="item7"/>
+ <combo_box.item label="Anfängergerecht" name="item8"/>
+ <combo_box.item label="Parks und Natur" name="item9"/>
+ <combo_box.item label="Wohngebiet" name="item10"/>
+ <combo_box.item label="Shopping" name="item11"/>
+ <combo_box.item label="Sonstige" name="item12"/>
</combo_box>
- <button label="?" label_selected="?" name="?"/>
<check_box label="Mature-Inhalt" name="MatureCheck" tool_tip=""/>
- <string name="mature_check_mature">
- Mature-Inhalt
- </string>
- <string name="mature_check_adult">
- Adult-Inhalt
- </string>
- <string name="mature_check_mature_tooltip">
- Die Informationen oder Inhalte Ihrer Parzelle sind „Mature“.
- </string>
- <string name="mature_check_adult_tooltip">
- Die Informationen oder Inhalte Ihrer Parzelle sind „Adult“.
- </string>
<text name="Snapshot:">
Foto:
</text>
@@ -403,41 +372,31 @@ Nur große Parzellen können in der Suche aufgeführt werden.
<text name="landing_point">
Landepunkt: [LANDING]
</text>
- <string name="landing_point_none">
- (keiner)
- </string>
<button label="Festlegen" label_selected="Festlegen" left="234" name="Set" tool_tip="Legt den Landepunkt fest, an dem Besucher ankommen. Legt die Position Ihres Avatars innerhalb dieser Parzelle fest." width="70"/>
- <button label="Löschen" label_selected="Löschen" left="312" name="Clear" tool_tip="Landepunkt löschen." width="70"/>
+ <button label="Löschen" label_selected="Löschen" left="312" name="Clear" tool_tip="Landepunkt löschen" width="70"/>
<text name="Teleport Routing: ">
Teleport-Route:
</text>
- <combo_box name="landing type" tool_tip="Teleport-Route -- festlegen, wie Teleports auf Ihrem Land gehandhabt werden sollen.">
- <combo_item name="Blocked">
- Blockiert
- </combo_item>
- <combo_item name="LandingPoint">
- Landepunkt
- </combo_item>
- <combo_item name="Anywhere">
- Ãœberall
- </combo_item>
+ <combo_box name="landing type" tool_tip="Teleport-Route -- festlegen, wie Teleports auf Ihrem Land gehandhabt werden sollen">
+ <combo_box.item label="Blockiert" name="Blocked"/>
+ <combo_box.item label="Landepunkt" name="LandingPoint"/>
+ <combo_box.item label="Ãœberall" name="Anywhere"/>
</combo_box>
- <string name="push_restrict_text">
- Kein Stoßen
- </string>
- <string name="push_restrict_region_text">
- Kein Stoßen (regional)
- </string>
</panel>
<panel label="Medien" name="land_media_panel">
<text name="with media:">
- Medientyp:
+ Typ:
</text>
<combo_box name="media type" tool_tip="Geben Sie einen URL für den Film, die Webseite oder ein anderes Medium ein"/>
<text name="at URL:">
- Medien-URL:
+ Start URL:
</text>
<button label="Einstellen..." label_selected="Einstellen..." name="set_media_url"/>
+ <text name="CurrentURL:">
+ Aktuelle URL:
+ </text>
+ <button label="Zurücksetzen..." label_selected="Zurücksetzen..." name="reset_media_url"/>
+ <check_box label="URL ausblenden" name="hide_media_url" tool_tip="Aktivieren Sie diese Option, wenn Sie nicht möchten, dass unautorisierte Personen die Medien-URL sehen können. Diese Option ist für HTML-Medien nicht verfügbar."/>
<text name="Description:">
Inhalt:
</text>
@@ -448,17 +407,11 @@ ersetzen:
</text>
<texture_picker label="" name="media texture" tool_tip="Klicken Sie hier, um ein Bild auszuwählen"/>
<text name="replace_texture_help">
- (Objekte mit dieser Textur zeigen nach Anklicken
-des Abspielen-Pfeils den Film oder die Webseite an.)
- </text>
- <text name="Options:">
- Medien-
-Optionen:
+ Objekte, die diese Textur verwenden, werden den Film oder die Webseite anzeigen, nachdem Sie auf den Pfeil (Wiedergabe) klicken.
+
+Wählen Sie das kleine Bild aus, um eine andere Textur auszuwählen.
</text>
<check_box label="Automatisch skalieren" name="media_auto_scale" tool_tip="Aktivieren Sie diese Option, um den Inhalt für diese Parzelle automatisch zu skalieren. Dies ist eventuell langsamer und die Qualität ist schlechter, aber Sie müssen keine weitere Texturskalierung oder -anpassung vornehmen."/>
- <check_box label="Als Schleife wiedergeben" name="media_loop" tool_tip="Spielt das Medium in einer Schleife ab. Der Abspielvorgang wird immer wieder von vorne fortgesetzt."/>
- <check_box label="Medien-URL verstecken" name="hide_media_url" tool_tip="Aktivieren Sie diese Option, wenn Sie nicht möchten, dass unautorisierte Personen die Medien-URL sehen können. Diese Option ist für HTML-Medien nicht verfügbar."/>
- <check_box label="Musik-URL verstecken" name="hide_music_url" tool_tip="Aktivieren Sie diese Option, wenn Sie nicht möchten, dass unautorisierte Personen die Musik-URL sehen können."/>
<text name="media_size" tool_tip="Darstellungsgröße von Webmedien, für Standard bei 0 belassen.">
Größe:
</text>
@@ -467,6 +420,12 @@ Optionen:
<text name="pixels">
Pixel
</text>
+ <text name="Options:">
+ Optionen:
+ </text>
+ <check_box label="Schleife" name="media_loop" tool_tip="Spielt das Medium in einer Schleife ab. Der Abspielvorgang wird immer wieder von vorne fortgesetzt."/>
+ </panel>
+ <panel label="Audio" name="land_audio_panel">
<text name="MusicURL:">
Musik-URL:
</text>
@@ -474,15 +433,17 @@ Optionen:
Sound:
</text>
<check_box label="Gesten- und Objektgeräusche auf diese Parzelle beschränken" name="check sound local"/>
- <button label="?" label_selected="?" left="418" name="?"/>
<text name="Voice settings:">
Voice:
</text>
- <check_box label="Voice-Chat aktivieren" name="parcel_enable_voice_channel"/>
- <check_box label="Voice-Chat aktivieren (vom Grundstück festgelegt)" name="parcel_enable_voice_channel_is_estate_disabled"/>
- <check_box label="Voice-Chat auf diese Parzelle beschränken" name="parcel_enable_voice_channel_parcel"/>
+ <check_box label="Voice aktivieren" name="parcel_enable_voice_channel"/>
+ <check_box label="Voice aktivieren (vom Grundstück eingerichtet)" name="parcel_enable_voice_channel_is_estate_disabled"/>
+ <check_box label="Voice auf diese Parzelle beschränken" name="parcel_enable_voice_channel_parcel"/>
</panel>
<panel label="Zugang" name="land_access_panel">
+ <panel.string name="estate_override">
+ Eine oder mehrere dieser Optionen gelten auf Grundstücksebene
+ </panel.string>
<text name="Limit access to this parcel to:">
Zugang zu dieser Parzelle
</text>
@@ -491,19 +452,12 @@ Optionen:
Zugang verweigern für:
</text>
<check_box label="Einwohner, die keine Zahlungsinformationen bei Linden Lab hinterlegt haben" name="limit_payment" tool_tip="Nicht identifizierte Einwohner verbannen."/>
- <check_box label="Einwohner, die keine altersgeprüften Erwachsenen sind" name="limit_age_verified" tool_tip="Einwohner ohne Altersprüfung verbannen. Weitere Informationen finden Sie auf support.secondlife.com."/>
- <string name="estate_override">
- Eine oder mehrere dieser Optionen gelten auf Grundstücksebene
- </string>
+ <check_box label="Einwohner, die keine altersgeprüften Erwachsenen sind" name="limit_age_verified" tool_tip="Einwohner ohne Altersüberprüfung verbannen. Weitere Informationen finden Sie auf [SUPPORT_SITE]."/>
<check_box label="Gruppenzugang erlauben: [GROUP]" name="GroupCheck" tool_tip="Gruppe im Register „Allgemein“ festlegen."/>
<check_box label="Pässe verkaufen an:" name="PassCheck" tool_tip="Ermöglicht befristeten Zugang zu dieser Parzelle"/>
<combo_box name="pass_combo">
- <combo_item name="Anyone">
- Jeden
- </combo_item>
- <combo_item name="Group">
- Gruppe
- </combo_item>
+ <combo_box.item label="Jeden" name="Anyone"/>
+ <combo_box.item label="Gruppe" name="Group"/>
</combo_box>
<spinner label="Preis in L$:" name="PriceSpin"/>
<spinner label="Online-Zeit:" name="HoursSpin"/>
diff --git a/indra/newview/skins/default/xui/de/floater_activeim.xml b/indra/newview/skins/default/xui/de/floater_activeim.xml
new file mode 100644
index 0000000000..416e31b2d6
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_activeim.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_activeim" title="AKTIVE IM"/>
diff --git a/indra/newview/skins/default/xui/de/floater_animation_preview.xml b/indra/newview/skins/default/xui/de/floater_animation_preview.xml
index 299b6a7f7e..4b4067f186 100644
--- a/indra/newview/skins/default/xui/de/floater_animation_preview.xml
+++ b/indra/newview/skins/default/xui/de/floater_animation_preview.xml
@@ -1,5 +1,111 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Animation Preview" title="">
+ <floater.string name="failed_to_initialize">
+ Bewegung konnte nicht initialisiert werden
+ </floater.string>
+ <floater.string name="anim_too_long">
+ Animationsdatei ist [LENGTH] Sekunden lang.
+
+Maximal erlaubt sind [MAX_LENGTH] Sekunden.
+ </floater.string>
+ <floater.string name="failed_file_read">
+ Animationsdatei konnte nicht gelesen werden.
+
+[STATUS]
+ </floater.string>
+ <floater.string name="E_ST_OK">
+ OK
+ </floater.string>
+ <floater.string name="E_ST_EOF">
+ Unvollständige Datei
+ </floater.string>
+ <floater.string name="E_ST_NO_CONSTRAINT">
+ Constraint-Definition kann nicht gelesen werden.
+ </floater.string>
+ <floater.string name="E_ST_NO_FILE">
+ BVH-Datei kann nicht geöffnet werden
+ </floater.string>
+ <floater.string name="E_ST_NO_HIER">
+ Ungültiger HIERARCHY-Titel.
+ </floater.string>
+ <floater.string name="E_ST_NO_JOINT">
+ ROOT oder JOINT nicht gefunden.
+ </floater.string>
+ <floater.string name="E_ST_NO_NAME">
+ JOINT-Name nicht erfasst.
+ </floater.string>
+ <floater.string name="E_ST_NO_OFFSET">
+ VERSATZ nicht gefunden.
+ </floater.string>
+ <floater.string name="E_ST_NO_CHANNELS">
+ CHANNELS nicht gefunden.
+ </floater.string>
+ <floater.string name="E_ST_NO_ROTATION">
+ Kann Rotations-Reihenfolge nicht erfassen.
+ </floater.string>
+ <floater.string name="E_ST_NO_AXIS">
+ Kann Rotations-Achse nicht erfassen.
+ </floater.string>
+ <floater.string name="E_ST_NO_MOTION">
+ MOTION nicht gefunden.
+ </floater.string>
+ <floater.string name="E_ST_NO_FRAMES">
+ Anzahl der Bilder kann nicht erfasst werden.
+ </floater.string>
+ <floater.string name="E_ST_NO_FRAME_TIME">
+ Bildzeit kann nicht erfasst werden.
+ </floater.string>
+ <floater.string name="E_ST_NO_POS">
+ Positions-Werte können nicht erfasst werden.
+ </floater.string>
+ <floater.string name="E_ST_NO_ROT">
+ Kann Rotations-Werte nicht erfassen.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_FILE">
+ Datei kann nicht geöffnet werden
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_HEADER">
+ Ãœbersetzungstitel kann nicht gelesen werden.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_NAME">
+ Übersetzungsnamen können nicht geladen werden.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_IGNORE">
+ Ignorier-Wert kann nicht gelesen werden.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_RELATIVE">
+ Ãœbersetzungs-Wert kann nicht gelesen werden.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_OUTNAME">
+ Outname-Wert kann nicht gelesen werden.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_MATRIX">
+ Ãœbersetzungsmatrix kann nicht geladen werden.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_MERGECHILD">
+ Mergechild-Name nicht erfasst.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_MERGEPARENT">
+ Mergeparent-Name nicht erfasst.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_PRIORITY">
+ Prioritätswert kann nicht erfasst werden.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_LOOP">
+ Loop-Wert kann nicht erfasst werden.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_EASEIN">
+ Easeln-Wert kann nicht erfasst werden.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_EASEOUT">
+ easeOut-Wert kann nicht erfasst werden.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_HAND">
+ Hand-Morph-Wert nicht erfasst.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_EMOTE">
+ Emote-Name kann nicht gelesen werden.
+ </floater.string>
<text name="name_label">
Name:
</text>
@@ -7,139 +113,65 @@
<text name="description_label">
Beschreibung:
</text>
- <spinner label="Priorität" name="priority" tool_tip="Steuert, welche Animationen von dieser Animation überschrieben werden können."/>
- <check_box bottom_delta="-18" label="Schleife" name="loop_check" tool_tip="Erzeugt eine Animationsschleife."/>
- <spinner label="In (%)" name="loop_in_point" tool_tip="Anfang einer Animationsschleife festlegen."/>
- <spinner label="Aus (%)" name="loop_out_point" tool_tip="Ende einer Animationsschleife festlegen."/>
+ <spinner label="Priorität" name="priority" tool_tip="Steuert, welche Animationen von dieser Animation überschrieben werden können"/>
+ <check_box bottom_delta="-18" label="Schleife" name="loop_check" tool_tip="Erzeugt eine Animationsschleife"/>
+ <spinner label="In (%)" name="loop_in_point" tool_tip="Anfang einer Animationsschleife festlegen"/>
+ <spinner label="Aus (%)" name="loop_out_point" tool_tip="Ende einer Animationsschleife festlegen"/>
<text name="hand_label">
Handhaltung
</text>
- <combo_box label="" name="hand_pose_combo" tool_tip="Steuert während der Animation die Bewegung der Hände.">
- <combo_item name="Spread">
- Dehnen
- </combo_item>
- <combo_item name="Relaxed">
- Entspannt
- </combo_item>
- <combo_item name="PointBoth">
- Beide zeigen
- </combo_item>
- <combo_item name="Fist">
- Faust
- </combo_item>
- <combo_item name="RelaxedLeft">
- Links entspannt
- </combo_item>
- <combo_item name="PointLeft">
- Nach links zeigen
- </combo_item>
- <combo_item name="FistLeft">
- Linke Faust
- </combo_item>
- <combo_item name="RelaxedRight">
- Rechts entspannt
- </combo_item>
- <combo_item name="PointRight">
- Nach rechts zeigen
- </combo_item>
- <combo_item name="FistRight">
- Rechte Faust
- </combo_item>
- <combo_item name="SaluteRight">
- Rechts salutieren
- </combo_item>
- <combo_item name="Typing">
- Tippt
- </combo_item>
- <combo_item name="PeaceRight">
- Friedensrecht
- </combo_item>
+ <combo_box label="" name="hand_pose_combo" tool_tip="Steuert während der Animation die Bewegung der Hände">
+ <combo_box.item label="Dehnen" name="Spread"/>
+ <combo_box.item label="Entspannt" name="Relaxed"/>
+ <combo_box.item label="Beide zeigen" name="PointBoth"/>
+ <combo_box.item label="Faust" name="Fist"/>
+ <combo_box.item label="Links entspannt" name="RelaxedLeft"/>
+ <combo_box.item label="Nach links zeigen" name="PointLeft"/>
+ <combo_box.item label="Linke Faust" name="FistLeft"/>
+ <combo_box.item label="Rechts entspannt" name="RelaxedRight"/>
+ <combo_box.item label="Nach rechts zeigen" name="PointRight"/>
+ <combo_box.item label="Rechte Faust" name="FistRight"/>
+ <combo_box.item label="Rechts salutieren" name="SaluteRight"/>
+ <combo_box.item label="Tippt" name="Typing"/>
+ <combo_box.item label="Friedensrecht" name="PeaceRight"/>
</combo_box>
<text name="emote_label">
Ausdruck
</text>
- <combo_box label="" name="emote_combo" tool_tip="Steuert Gesichtsregungen während der Animation.">
- <combo_item name="[None]">
- [Keine]
- </combo_item>
- <combo_item name="Aaaaah">
- Aaaaah
- </combo_item>
- <combo_item name="Afraid">
- Ängstlich
- </combo_item>
- <combo_item name="Angry">
- Verärgert
- </combo_item>
- <combo_item name="BigSmile">
- Grinst
- </combo_item>
- <combo_item name="Bored">
- Gelangweilt
- </combo_item>
- <combo_item name="Cry">
- Weinen
- </combo_item>
- <combo_item name="Disdain">
- Verachten
- </combo_item>
- <combo_item name="Embarrassed">
- Verlegen
- </combo_item>
- <combo_item name="Frown">
- Stirnrunzeln
- </combo_item>
- <combo_item name="Kiss">
- Küssen
- </combo_item>
- <combo_item name="Laugh">
- Lachen
- </combo_item>
- <combo_item name="Plllppt">
- Bäääh
- </combo_item>
- <combo_item name="Repulsed">
- Zurückgestoßen
- </combo_item>
- <combo_item name="Sad">
- Traurig
- </combo_item>
- <combo_item name="Shrug">
- Schulterzucken
- </combo_item>
- <combo_item name="Smile">
- Lächeln
- </combo_item>
- <combo_item name="Surprise">
- Ãœberraschung
- </combo_item>
- <combo_item name="Wink">
- Zwinkern
- </combo_item>
- <combo_item name="Worry">
- Sorgenvoll
- </combo_item>
+ <combo_box label="" name="emote_combo" tool_tip="Steuert Gesichtsregungen während der Animation">
+ <combo_box.item label="(Keiner)" name="[None]"/>
+ <combo_box.item label="Aaaaah" name="Aaaaah"/>
+ <combo_box.item label="Ängstlich" name="Afraid"/>
+ <combo_box.item label="Verärgert" name="Angry"/>
+ <combo_box.item label="Grinst" name="BigSmile"/>
+ <combo_box.item label="Gelangweilt" name="Bored"/>
+ <combo_box.item label="Weinen" name="Cry"/>
+ <combo_box.item label="Verachten" name="Disdain"/>
+ <combo_box.item label="Verlegen" name="Embarrassed"/>
+ <combo_box.item label="Stirnrunzeln" name="Frown"/>
+ <combo_box.item label="Küssen" name="Kiss"/>
+ <combo_box.item label="Lachen" name="Laugh"/>
+ <combo_box.item label="Bäääh" name="Plllppt"/>
+ <combo_box.item label="Angewidert" name="Repulsed"/>
+ <combo_box.item label="Traurig" name="Sad"/>
+ <combo_box.item label="Schulterzucken" name="Shrug"/>
+ <combo_box.item label="Lächeln" name="Smile"/>
+ <combo_box.item label="Ãœberraschung" name="Surprise"/>
+ <combo_box.item label="Zwinkern" name="Wink"/>
+ <combo_box.item label="Sorgenvoll" name="Worry"/>
</combo_box>
<text name="preview_label" width="97">
Vorschau während:
</text>
<combo_box label="" left_delta="107" name="preview_base_anim" tool_tip="Hiermit können Sie das Verhalten Ihres Avatars testen, während Ihr Avatar normale Bewegungen ausführt.">
- <combo_item name="Standing">
- Stehend
- </combo_item>
- <combo_item name="Walking">
- Geht
- </combo_item>
- <combo_item name="Sitting">
- Sitzt
- </combo_item>
- <combo_item name="Flying">
- Fliegend
- </combo_item>
+ <combo_box.item label="Stehend" name="Standing"/>
+ <combo_box.item label="Geht" name="Walking"/>
+ <combo_box.item label="Sitzt" name="Sitting"/>
+ <combo_box.item label="Fliegen" name="Flying"/>
</combo_box>
- <spinner label="Eingang glätten (s)" label_width="105" name="ease_in_time" tool_tip="Einblendungsgeschwindigkeit von Animationen (in Sekunden)." width="175"/>
- <spinner bottom_delta="-20" label="Ausgang glätten (s)" label_width="105" left="10" name="ease_out_time" tool_tip="Ausblendungsgeschwindigkeit von Animationen (in Sekunden)." width="175"/>
- <button bottom_delta="-32" label="" name="play_btn" tool_tip="Animation stoppen/wiedergeben."/>
+ <spinner label="Eingang glätten (s)" label_width="105" name="ease_in_time" tool_tip="Einblendungsgeschwindigkeit von Animationen (in Sekunden)" width="175"/>
+ <spinner bottom_delta="-20" label="Ausgang glätten (s)" label_width="105" left="10" name="ease_out_time" tool_tip="Ausblendegeschwindigkeit von Animationen (in Sekunden)" width="175"/>
+ <button bottom_delta="-32" label="" name="play_btn" tool_tip="Animation stoppen/wiedergeben"/>
<button label="" name="stop_btn" tool_tip="Animation anhalten"/>
<slider label="" name="playback_slider"/>
<text name="bad_animation_text">
@@ -149,17 +181,4 @@ Wir empfehlen exportierte BVH-Dateien aus Poser 4.
</text>
<button label="Abbrechen" name="cancel_btn"/>
<button label="Hochladen ([AMOUNT] L$)" name="ok_btn"/>
- <string name="failed_to_initialize">
- Bewegung konnte nicht initialisiert werden
- </string>
- <string name="anim_too_long">
- Animationsdatei ist [LENGTH] Sekunden lang.
-
-Maximal erlaubt sind [MAX_LENGTH] Sekunden.
- </string>
- <string name="failed_file_read">
- Animationsdatei konnte nicht gelesen werden.
-
-[STATUS]
- </string>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_auction.xml b/indra/newview/skins/default/xui/de/floater_auction.xml
index 42f6a07dc3..8ededff319 100644
--- a/indra/newview/skins/default/xui/de/floater_auction.xml
+++ b/indra/newview/skins/default/xui/de/floater_auction.xml
@@ -1,9 +1,11 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_auction" title="Linden-Landverkauf starten">
- <check_box label="Gelben Auswahlrahmen einschließen" name="fence_check" />
- <button label="Foto" label_selected="Foto" name="snapshot_btn" />
- <button label="OK" label_selected="OK" name="ok_btn" />
- <text name="already for sale">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_auction" title="LINDEN LAND VERKAUF STARTEN">
+ <floater.string name="already for sale">
Parzellen, die bereits zum Verkauf stehen, können nicht auktioniert werden.
- </text>
+ </floater.string>
+ <check_box initial_value="true" label="Gelben Auswahlrahmen einschließen" name="fence_check"/>
+ <button label="Foto" label_selected="Foto" name="snapshot_btn"/>
+ <button label="An jeden verkaufen" label_selected="An jeden verkaufen" name="sell_to_anyone_btn"/>
+ <button label="Einstellungen löschen" label_selected="Einstellungen löschen" name="reset_parcel_btn"/>
+ <button label="Auktion beginnen" label_selected="Auktion beginnen" name="start_auction_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_avatar_picker.xml b/indra/newview/skins/default/xui/de/floater_avatar_picker.xml
index c546d91d72..ed8de62b69 100644
--- a/indra/newview/skins/default/xui/de/floater_avatar_picker.xml
+++ b/indra/newview/skins/default/xui/de/floater_avatar_picker.xml
@@ -1,45 +1,49 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="avatarpicker" title="Einwohner auswählen">
+<floater name="avatarpicker" title="EINWOHNER AUSWÄHLEN">
+ <floater.string name="not_found">
+ „[TEXT]“ nicht gefunden
+ </floater.string>
+ <floater.string name="no_one_near">
+ Keiner in der Nähe
+ </floater.string>
+ <floater.string name="no_results">
+ Keine Ergebnisse
+ </floater.string>
+ <floater.string name="searching">
+ Suchen...
+ </floater.string>
+ <string label="OK" label_selected="OK" name="Select">
+ Auswählen
+ </string>
+ <string name="Close">
+ Schließen
+ </string>
<tab_container name="ResidentChooserTabs">
<panel label="Suchen" name="SearchPanel">
<text name="InstructSearchResidentName">
- Geben Sie einen Teil des Namens des
-Einwohners ein:
+ Geben Sie einen Teil des Namens einer Person ein:
</text>
- <line_editor bottom_delta="-36" name="Edit" />
- <button label="Suchen" label_selected="Suchen" name="Find"/>
- <scroll_list height="74" name="SearchResults" bottom_delta="-79"/>
+ <line_editor bottom_delta="-36" name="Edit"/>
+ <button label="Los" label_selected="Los" name="Find"/>
+ <scroll_list bottom_delta="-79" height="74" name="SearchResults"/>
</panel>
- <panel label="Visitenkarten" name="CallingCardsPanel">
- <text name="InstructSelectCallingCard">
- Wählen Sie eine Visitenkarte:
+ <panel label="Freunde" name="FriendsPanel">
+ <text name="InstructSelectFriend">
+ Wählen Sie eine Person aus:
</text>
</panel>
<panel label="In meiner Nähe" name="NearMePanel">
<text name="InstructSelectResident">
- Einwohner in der Nähe
-auswählen:
+ Wählen Sie eine Person aus, die sich in der Nähe befindet:
</text>
- <button font="SansSerifSmall" label="Liste aktualisieren" label_selected="Liste aktualisieren" name="Refresh" left_delta="10" width="105"/>
- <slider label="Bereich" name="near_me_range" bottom_delta="-36"/>
+ <slider bottom_delta="-36" label="Bereich" name="near_me_range"/>
<text name="meters">
Meter
</text>
- <scroll_list bottom_delta="-169" height="159" name="NearMe" />
+ <button font="SansSerifSmall" label="Liste aktualisieren" label_selected="Liste aktualisieren" left_delta="10" name="Refresh" width="105"/>
+ <scroll_list bottom_delta="-169" height="159" name="NearMe"/>
</panel>
</tab_container>
- <button label="Auswählen" label_selected="Auswählen" name="Select"/>
- <button label="Abbrechen" label_selected="Abbrechen" name="Cancel"/>
- <string name="not_found">
- „[TEXT]“ nicht gefunden
- </string>
- <string name="no_one_near">
- Niemand in der Nähe
- </string>
- <string name="no_results">
- Keine Ergebnisse
- </string>
- <string name="searching">
- Suchen...
- </string>
+ <button label="OK" label_selected="OK" name="ok_btn"/>
+ <button label="Abbrechen" label_selected="Abbrechen" name="cancel_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_avatar_textures.xml b/indra/newview/skins/default/xui/de/floater_avatar_textures.xml
index 823d6de78b..6f5fe23d4c 100644
--- a/indra/newview/skins/default/xui/de/floater_avatar_textures.xml
+++ b/indra/newview/skins/default/xui/de/floater_avatar_textures.xml
@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="avatar_texture_debug" title="Avatar-Texturen">
+<floater name="avatar_texture_debug" title="AVATAR-TEXTUREN">
+ <floater.string name="InvalidAvatar">
+ UNGÃœLTIGER AVATAR
+ </floater.string>
<text name="label">
Gebackene Texturen
</text>
@@ -8,24 +11,32 @@
</text>
<button label="Läd IDs in Konsole ab" label_selected="Abladen" name="Dump"/>
<texture_picker label="Haare" name="hair-baked"/>
- <texture_picker label="Haar" name="hair"/>
+ <texture_picker label="Haare" name="hair_grain"/>
+ <texture_picker label="Alpha: Haare" name="hair_alpha"/>
<texture_picker label="Kopf" name="head-baked"/>
- <texture_picker label="Make-Uup" name="head bodypaint"/>
+ <texture_picker label="Make-Uup" name="head_bodypaint"/>
+ <texture_picker label="Kopf: Alpha" name="head_alpha"/>
+ <texture_picker label="Kopftattoo" name="head_tattoo"/>
<texture_picker label="Augen" name="eyes-baked"/>
- <texture_picker label="Auge" name="iris"/>
+ <texture_picker label="Auge" name="eyes_iris"/>
+ <texture_picker label="Alpha: Augen" name="eyes_alpha"/>
<texture_picker label="Oberkörper" name="upper-baked"/>
- <texture_picker label="Oberkörpertattoo" name="upper bodypaint"/>
- <texture_picker label="Unterhemd" name="undershirt"/>
- <texture_picker label="Handschuhe" name="gloves"/>
- <texture_picker label="Hemd" name="shirt"/>
- <texture_picker label="Oberjacke" name="upper jacket"/>
+ <texture_picker label="Oberkörper: Körperfarbe" name="upper_bodypaint"/>
+ <texture_picker label="Unterhemd" name="upper_undershirt"/>
+ <texture_picker label="Handschuhe" name="upper_gloves"/>
+ <texture_picker label="Hemd" name="upper_shirt"/>
+ <texture_picker label="Oberjacke" name="upper_jacket"/>
+ <texture_picker label="Alpha: Oben" name="upper_alpha"/>
+ <texture_picker label="Obere Tattoos" name="upper_tattoo"/>
<texture_picker label="Unterkörper" name="lower-baked"/>
- <texture_picker label="Unterkörper-Tätowierung" name="lower bodypaint"/>
- <texture_picker label="Unterhose" name="underpants"/>
- <texture_picker label="Socken" name="socks"/>
- <texture_picker label="Schuhe" name="shoes"/>
- <texture_picker label="Hose" name="pants"/>
- <texture_picker label="Jacke" name="lower jacket"/>
+ <texture_picker label="Unterkörper: Körperfarbe" name="lower_bodypaint"/>
+ <texture_picker label="Unterhose" name="lower_underpants"/>
+ <texture_picker label="Socken" name="lower_socks"/>
+ <texture_picker label="Schuhe" name="lower_shoes"/>
+ <texture_picker label="Hose" name="lower_pants"/>
+ <texture_picker label="Jacke" name="lower_jacket"/>
+ <texture_picker label="Alpha: Unten" name="lower_alpha"/>
+ <texture_picker label="Untere Tattoos" name="lower_tattoo"/>
<texture_picker label="Rock" name="skirt-baked"/>
<texture_picker label="Rock" name="skirt"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_beacons.xml b/indra/newview/skins/default/xui/de/floater_beacons.xml
index 0992727e73..50a4555ae0 100644
--- a/indra/newview/skins/default/xui/de/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/de/floater_beacons.xml
@@ -1,15 +1,21 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="beacons" title="Beacons">
+<floater name="beacons" title="STRAHLEN">
<panel name="beacons_panel">
- <check_box label="Auf Berührung beschränkte Skriptobjekte" name="touch_only"/>
- <check_box label="Skripting-Objekte" name="scripted"/>
- <check_box label="Physische Objekte" name="physical"/>
+ <text name="label_show">
+ Anzeigen:
+ </text>
+ <check_box label="Strahlen" name="beacons"/>
+ <check_box label="Glanzlichter" name="highlights"/>
+ <text name="beacon_width_label" tool_tip="Strahlbreite">
+ Breite:
+ </text>
+ <text name="label_objects">
+ Für diese Objekte:
+ </text>
+ <check_box label="Physisch" name="physical"/>
+ <check_box label="Skriptobjekte" name="scripted"/>
+ <check_box label="Nur berühren" name="touch_only"/>
<check_box label="Soundquellen" name="sounds"/>
<check_box label="Partikelquellen" name="particles"/>
- <check_box label="Glanzlichter anzeigen" name="highlights"/>
- <check_box label="Beacons anzeigen" name="beacons"/>
- <text name="beacon_width_label">
- Beacon-Breite:
- </text>
</panel>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_build_options.xml b/indra/newview/skins/default/xui/de/floater_build_options.xml
index de3617ed25..b70c859490 100644
--- a/indra/newview/skins/default/xui/de/floater_build_options.xml
+++ b/indra/newview/skins/default/xui/de/floater_build_options.xml
@@ -1,8 +1,11 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="build options floater" title="Rasteroptionen">
- <spinner label="Rastereinheit (Meter)" name="GridResolution" />
- <spinner label="Rastergröße (Meter)" name="GridDrawSize" />
- <check_box label="Einrasten von Untereinheiten aktivieren" name="GridSubUnit" />
- <check_box label="Querschnitte anzeigen" name="GridCrossSection" />
- <slider label="Rasterdeckkraft" name="GridOpacity" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="build options floater" title="RASTER-OPTIONEN">
+ <spinner label="Raster-Einheiten (Meter)" name="GridResolution"/>
+ <spinner label="Rastergröße (Meter)" name="GridDrawSize"/>
+ <check_box label="Einrasten von Untereinheiten aktivieren" name="GridSubUnit"/>
+ <check_box label="Ãœberschneidungen anzeigen" name="GridCrossSection"/>
+ <text name="grid_opacity_label" tool_tip="Raster-Deckkraft">
+ Deckkraft:
+ </text>
+ <slider label="Rasterdeckkraft" name="GridOpacity"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_bulk_perms.xml b/indra/newview/skins/default/xui/de/floater_bulk_perms.xml
index f058a0ed96..218c66d298 100644
--- a/indra/newview/skins/default/xui/de/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/de/floater_bulk_perms.xml
@@ -1,44 +1,54 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterbulkperms" title="Mehrere Inhaltsberechtigungen ändern">
- <text name="applyto">
- Inhaltsarten
- </text>
+<floater name="floaterbulkperms" title="INHALTS-BERECHTIGUNGEN BEARBEITEN">
+ <floater.string name="nothing_to_modify_text">
+ Auswahl enthält keinen Inhalt, der bearbeitet werden kann.
+ </floater.string>
+ <floater.string name="status_text">
+ Berechtigungen werden eingestellt auf [NAME]
+ </floater.string>
+ <floater.string name="start_text">
+ Start: Anforderung auf Änderung der Berechtigung...
+ </floater.string>
+ <floater.string name="done_text">
+ Ende: Anforderung auf Änderung der Berechtigung.
+ </floater.string>
<check_box label="Animation" name="check_animation"/>
+ <icon name="icon_animation" tool_tip="Animation"/>
<check_box label="Körperteile" name="check_bodypart"/>
+ <icon name="icon_bodypart" tool_tip="Körperteile"/>
<check_box label="Kleidung" name="check_clothing"/>
+ <icon name="icon_clothing" tool_tip="Kleidung"/>
<check_box label="Gesten" name="check_gesture"/>
- <check_box label="Landmarken" name="check_landmark"/>
+ <icon name="icon_gesture" tool_tip="Gesten"/>
<check_box label="Notizkarten" name="check_notecard"/>
+ <icon name="icon_notecard" tool_tip="Notizkarten"/>
<check_box label="Objekte" name="check_object"/>
+ <icon name="icon_object" tool_tip="Objekte"/>
<check_box label="Skripts" name="check_script"/>
+ <icon name="icon_script" tool_tip="Skripts"/>
<check_box label="Sounds" name="check_sound"/>
+ <icon name="icon_sound" tool_tip="Sounds"/>
<check_box label="Texturen" name="check_texture"/>
- <button label="Alle auswählen" label_selected="Alle" name="check_all"/>
- <button label="Keine" label_selected="Keine" name="check_none"/>
+ <icon name="icon_texture" tool_tip="Texturen"/>
+ <button label="√ Alle" label_selected="Alle" name="check_all"/>
+ <button label="Löschen" label_selected="Keine" name="check_none"/>
<text name="newperms">
- Neue Berechtigungen
+ Neue Inhalts-Berechtigungen
+ </text>
+ <text name="GroupLabel">
+ Gruppe:
</text>
- <check_box label="Mit Gruppe teilen" name="share_with_group"/>
- <check_box label="Kopieren allen erlauben" name="everyone_copy"/>
+ <check_box label="Teilen" name="share_with_group"/>
+ <text name="AnyoneLabel">
+ Jeder:
+ </text>
+ <check_box label="Kopieren" name="everyone_copy"/>
<text name="NextOwnerLabel">
- Nächster Eigentümer kann:
+ Nächster Eigentümer:
</text>
<check_box label="Bearbeiten" name="next_owner_modify"/>
<check_box label="Kopieren" name="next_owner_copy"/>
- <check_box label="Verkaufen/Weggeben" name="next_owner_transfer"/>
- <button label="Hilfe" name="help"/>
- <button label="Ãœbernehmen" name="apply"/>
- <button label="Schließen" name="close"/>
- <string name="nothing_to_modify_text">
- Auswahl enthält keinen Inhalt, der bearbeitet werden kann.
- </string>
- <string name="status_text">
- Berechtigungen werden eingestellt auf [NAME]
- </string>
- <string name="start_text">
- Start: Anforderung auf Änderung der Berechtigung...
- </string>
- <string name="done_text">
- Ende: Anforderung auf Änderung der Berechtigung.
- </string>
+ <check_box initial_value="true" label="Transferieren" name="next_owner_transfer" tool_tip="Nächster Eigentümer kann dieses Objekt weitergeben oder -verkaufen"/>
+ <button label="OK" name="apply"/>
+ <button label="Abbrechen" name="close"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_bumps.xml b/indra/newview/skins/default/xui/de/floater_bumps.xml
index 7b21042c2b..dafca44fa3 100644
--- a/indra/newview/skins/default/xui/de/floater_bumps.xml
+++ b/indra/newview/skins/default/xui/de/floater_bumps.xml
@@ -1,21 +1,24 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_bumps" title="Rempler, Stöße und Schläge">
- <text name="none_detected">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_bumps" title="REMPLER, STÖSSE &amp; SCHLÄGE">
+ <floater.string name="none_detected">
Nicht erkannt
- </text>
- <text name="bump">
+ </floater.string>
+ <floater.string name="bump">
[TIME] [FIRST] [LAST] hat Sie gestoßen
- </text>
- <text name="llpushobject">
+ </floater.string>
+ <floater.string name="llpushobject">
[TIME] [FIRST] [LAST] hat Sie mit einem Skript gestoßen
- </text>
- <text name="selected_object_collide">
+ </floater.string>
+ <floater.string name="selected_object_collide">
[TIME] [FIRST] [LAST] hat Sie mit einem Objekt getroffen
- </text>
- <text name="scripted_object_collide">
+ </floater.string>
+ <floater.string name="scripted_object_collide">
[TIME] [FIRST] [LAST] hat Sie mit einem Skript-Objekt getroffen
- </text>
- <text name="physical_object_collide">
+ </floater.string>
+ <floater.string name="physical_object_collide">
[TIME] [FIRST] [LAST] hat Sie mit einem physischen Objekt getroffen
- </text>
+ </floater.string>
+ <floater.string name="timeStr">
+ [[hour,datetime,slt]:[min,datetime,slt]]
+ </floater.string>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_buy_contents.xml b/indra/newview/skins/default/xui/de/floater_buy_contents.xml
index 01858b3c36..ccafa11cf4 100644
--- a/indra/newview/skins/default/xui/de/floater_buy_contents.xml
+++ b/indra/newview/skins/default/xui/de/floater_buy_contents.xml
@@ -1,14 +1,14 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_buy_contents" title="Inhalte kaufen" min_width="300">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater min_width="300" name="floater_buy_contents" title="INHALT KAUFEN">
<text name="contains_text">
[NAME] enthält:
</text>
<text name="buy_text">
[AMOUNT] L$ von [NAME] kaufen?
</text>
- <button label="Abbrechen" label_selected="Abbrechen" name="cancel_btn" width="73" />
- <button label="Kaufen" label_selected="Kaufen" name="buy_btn" />
- <check_box label="Kleidung jetzt anziehen" name="wear_check" />
+ <button label="Abbrechen" label_selected="Abbrechen" name="cancel_btn" width="73"/>
+ <button label="Kaufen" label_selected="Kaufen" name="buy_btn"/>
+ <check_box label="Kleidung jetzt anziehen" name="wear_check"/>
<text name="no_copy_text">
(kein Kopieren)
</text>
diff --git a/indra/newview/skins/default/xui/de/floater_buy_currency.xml b/indra/newview/skins/default/xui/de/floater_buy_currency.xml
index 787f469854..287b16273a 100644
--- a/indra/newview/skins/default/xui/de/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/de/floater_buy_currency.xml
@@ -1,68 +1,66 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="buy currency" title="Geld kaufen">
- <text name="info_buying">
- Kaufe Geld:
- </text>
- <text name="info_cannot_buy">
- Kaufen jetzt nicht möglich:
- </text>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="buy currency" title="L$ kaufen">
+ <floater.string name="buy_currency">
+ [LINDENS] L$ für ca. [LOCALAMOUNT] kaufen
+ </floater.string>
<text name="info_need_more">
- Sie brauchen mehr Geld:
+ Sie brauchen mehr Geld
</text>
- <text name="error_message">
- Irgendetwas stimmt nicht.
- </text>
- <button label="Gehe zu Website" name="error_web" />
<text name="contacting">
LindeX wird kontaktiert...
</text>
- <text name="buy_action_unknown">
- L$ an der LindeX kaufen
+ <text name="info_buying">
+ L$ kaufen
</text>
- <text name="buy_action">
- [NAME] L$ [PRICE]
+ <text name="balance_label">
+ Ich habe
+ </text>
+ <text name="balance_amount">
+ [AMT] L$
</text>
<text name="currency_action" width="90">
- L$ kaufen
+ Ich möchte kaufen
+ </text>
+ <text name="currency_label">
+ L$
</text>
- <line_editor left_delta="55" name="currency_amt">
+ <line_editor label="L$" left_delta="55" name="currency_amt">
1234
</line_editor>
+ <text name="buying_label">
+ Zum Preis von
+ </text>
<text name="currency_est">
- für ca. [USD] US$
+ ca. [LOCALAMOUNT]
</text>
<text name="getting_data">
- Daten werden geladen...
- </text>
- <text name="balance_label">
- Sie haben zurzeit
+ Schätzung erfolgt...
</text>
- <text name="balance_amount">
- [AMT] L$
- </text>
- <text name="buying_label">
- Sie kaufen
- </text>
- <text name="buying_amount">
- [AMT] L$
+ <text name="buy_action">
+ [NAME] L$ [PRICE]
</text>
<text name="total_label">
- Ihr neuer Kontostand:
+ Mein neuer Kontostand wird sein
</text>
<text name="total_amount">
[AMT] L$
</text>
+ <text name="currency_links">
+ [http://www.secondlife.com/my/account/payment_method_management.php?lang=de-DE payment method] | [http://www.secondlife.com/my/account/currency.php?lang=de-DE currency] | [http://www.secondlife.com/my/account/exchange_rates.php?lang=de-DE exchange rate]
+ </text>
+ <text name="exchange_rate_note">
+ Geben Sie den Betrag erneut ein, um die aktuellste Umtauschrate anzuzeigen.
+ </text>
<text name="purchase_warning_repurchase">
- Dieser Einkauf betrifft ausschließlich Geld.
-Wiederholen Sie den Vorgang.
+ Nach Bestätigung dieses Kaufs werden nur L$ gekauft, nicht das Objekt.
</text>
<text name="purchase_warning_notenough">
- Sie kaufen nicht genügend Geld.
-Kaufen Sie mehr.
+ Sie kaufen nicht genügend L$. Bitte erhöhen Sie den Betrag.
</text>
- <button label="Kaufen" name="buy_btn" />
- <button label="Abbrechen" name="cancel_btn" />
- <text name="buy_currency">
- [LINDENS] L$ für ca. [USD] US$ kaufen
+ <button label="Jetzt kaufen" name="buy_btn"/>
+ <button label="Abbrechen" name="cancel_btn"/>
+ <text name="info_cannot_buy">
+ Kauf nicht möglich
</text>
+ <button label="Weiter zum Internet" name="error_web"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_buy_land.xml b/indra/newview/skins/default/xui/de/floater_buy_land.xml
index 1dbc066914..4c59f1e8e6 100644
--- a/indra/newview/skins/default/xui/de/floater_buy_land.xml
+++ b/indra/newview/skins/default/xui/de/floater_buy_land.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="buy land" title="Land kaufen">
+<floater name="buy land" title="LAND KAUFEN">
<text name="region_name_label">
Region:
</text>
@@ -36,6 +36,7 @@
<text name="covenant_text">
Sie müssen dem Grundstücksvertrag zustimmen:
</text>
+ <text left="470" name="covenant_timestamp_text"/>
<text_editor name="covenant_editor">
Wird geladen...
</text_editor>
@@ -50,14 +51,14 @@
Größe:
</text>
<text name="info_size">
- 1024 qm.
+ 1.024 m²
</text>
<text name="info_price_label">
Preis:
</text>
<text name="info_price">
1500 L$
-(L$ 1,1 L$/qm)
+(1,1 L$/m²)
Objekte im Verkauf eingeschlossen
</text>
<text name="info_action">
@@ -74,22 +75,16 @@ Objekte im Verkauf eingeschlossen
Landbesitz ist Premium-Mitgliedern vorbehalten.
</text>
<combo_box name="account_level">
- <combo_item name="US$9.95/month,billedmonthly">
- 9,95 US$/Monat, monatliche Abrechnung
- </combo_item>
- <combo_item name="US$7.50/month,billedquarterly">
- 7,50 US$/Monat, vierteljährliche Abrechnung
- </combo_item>
- <combo_item name="US$6.00/month,billedannually">
- 6,00 US$/Monat, jährliche Abrechnung
- </combo_item>
+ <combo_box.item label="9,95 US$/Monat, monatliche Abrechnung" name="US$9.95/month,billedmonthly"/>
+ <combo_box.item label="7,50 US$/Monat, vierteljährliche Abrechnung" name="US$7.50/month,billedquarterly"/>
+ <combo_box.item label="6,00 US$/Monat, jährliche Abrechnung" name="US$6.00/month,billedannually"/>
</combo_box>
<text name="land_use_action">
Erhöhen Sie Ihre monatlichen Landnutzungsgebühren auf 40 US$/month.
</text>
<text name="land_use_reason">
- Sie besitzen 1309 qm Land.
-Diese Parzelle ist 512 qm groß.
+ Sie besitzen 1309 m² Land.
+Diese Parzelle ist 512 m² gross.
</text>
<text name="purchase_action">
Joe Resident 4000 L$ für das Land bezahlen
@@ -104,12 +99,12 @@ Diese Parzelle ist 512 qm groß.
1000
</line_editor>
<text name="currency_est">
- für ca. [AMOUNT2] US$
+ für ca. [LOCAL_AMOUNT]
</text>
<text name="currency_balance">
Sie haben 2.100 L$.
</text>
- <check_box label="[AMOUNT] Quadratmeter des Beitrags von Gruppe nehmen." name="remove_contribution"/>
+ <check_box label="[AMOUNT] m² Beitrag von der Gruppe entfernen." name="remove_contribution"/>
<button label="Kaufen" name="buy_btn"/>
<button label="Abbrechen" name="cancel_btn"/>
<string name="can_resell">
@@ -186,25 +181,25 @@ Verkleinern Sie Ihre Auswahl.
Mit Ihrem Konto können Sie Land kaufen.
</string>
<string name="land_holdings">
- Sie besitzen [BUYER] qm Land.
+ Sie besitzen [BUYER] m² Land.
</string>
<string name="pay_to_for_land">
[SELLER] [AMOUNT] L$ für das Land bezahlen
</string>
<string name="buy_for_US">
- [AMOUNT] L$ für circa [AMOUNT2] US$ kaufen,
+ Kaufen Sie [AMOUNT] L$ für ca. [LOCAL_AMOUNT],
</string>
<string name="parcel_meters">
- Diese Parzelle ist [AMOUNT] qm groß.
+ Diese Parzelle ist [AMOUNT] m².
</string>
<string name="premium_land">
- Dieses Land ist eine Premium-Immobilie. Es wird mit [AMOUNT] qm angesetzt.
+ Dieses Land ist eine Premium-Immobilie. Es wird mit [AMOUNT] m² angesetzt.
</string>
<string name="discounted_land">
- Dieses Land ist im Angebot. Es wird mit [AMOUNT] qm angesetzt.
+ Dieses Land ist im Angebot. Es wird mit [AMOUNT] m² angesetzt.
</string>
<string name="meters_supports_object">
- [AMOUNT] qm.
+ [AMOUNT] m²
unterstützt [AMOUNT2] Objekte
</string>
<string name="sold_with_objects">
@@ -215,7 +210,7 @@ unterstützt [AMOUNT2] Objekte
</string>
<string name="info_price_string">
[PRICE] L$
-([PRICE_PER_SQM] L$/qm)
+([PRICE_PER_SQM] L$/m²)
[SOLD_WITH_OBJECTS]
</string>
<string name="insufficient_land_credits">
diff --git a/indra/newview/skins/default/xui/de/floater_buy_object.xml b/indra/newview/skins/default/xui/de/floater_buy_object.xml
index 3cfa59ff06..b23163b4a3 100644
--- a/indra/newview/skins/default/xui/de/floater_buy_object.xml
+++ b/indra/newview/skins/default/xui/de/floater_buy_object.xml
@@ -1,13 +1,13 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="contents" title="Objektkopie kaufen">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="contents" title="KOPIE DES OBJEKTES KAUFEN">
<text name="contents_text">
- samt Inhalt:
+ Inhalt:
</text>
<text name="buy_text">
[AMOUNT] L$ von [NAME] kaufen?
</text>
- <button label="Abbrechen" label_selected="Abbrechen" name="cancel_btn" width="73" />
- <button label="Kaufen" label_selected="Kaufen" name="buy_btn" />
+ <button label="Abbrechen" label_selected="Abbrechen" name="cancel_btn" width="73"/>
+ <button label="Kaufen" label_selected="Kaufen" name="buy_btn"/>
<text name="title_buy_text">
Kaufen
</text>
diff --git a/indra/newview/skins/default/xui/de/floater_camera.xml b/indra/newview/skins/default/xui/de/floater_camera.xml
index 198b5b07f2..b8616ea128 100644
--- a/indra/newview/skins/default/xui/de/floater_camera.xml
+++ b/indra/newview/skins/default/xui/de/floater_camera.xml
@@ -1,12 +1,31 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="move floater">
- <string name="rotate_tooltip">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="camera_floater">
+ <floater.string name="rotate_tooltip">
Kamera um Fokus drehen
- </string>
- <string name="zoom_tooltip">
+ </floater.string>
+ <floater.string name="zoom_tooltip">
Kamera auf Fokus zoomen
- </string>
- <string name="move_tooltip">
+ </floater.string>
+ <floater.string name="move_tooltip">
Kamera nach oben, unten, links und rechts bewegen
- </string>
+ </floater.string>
+ <panel name="controls">
+ <joystick_track name="cam_track_stick" tool_tip="Kamera nach oben, unten, links und rechts bewegen"/>
+ <panel name="zoom" tool_tip="Kamera auf Fokus zoomen">
+ <slider_bar name="zoom_slider" tool_tip="Kamera auf Fokus zoomen"/>
+ </panel>
+ <joystick_rotate name="cam_rotate_stick" tool_tip="Kamera um Fokus kreisen"/>
+ <panel name="camera_presets">
+ <button name="rear_view" tool_tip="Hinteransicht"/>
+ <button name="group_view" tool_tip="Gruppen-Ansicht"/>
+ <button name="front_view" tool_tip="Vorderansicht"/>
+ <button name="mouselook_view" tool_tip="Mouselook"/>
+ </panel>
+ </panel>
+ <panel name="buttons">
+ <button label="" name="orbit_btn" tool_tip="Kamera kreisen"/>
+ <button label="" name="pan_btn" tool_tip="Kamera schwenken"/>
+ <button label="" name="avatarview_btn" tool_tip="Avatarsicht"/>
+ <button label="" name="freecamera_btn" tool_tip="Objekt ansehen"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_choose_group.xml b/indra/newview/skins/default/xui/de/floater_choose_group.xml
index dd29aa7550..3d76b645fe 100644
--- a/indra/newview/skins/default/xui/de/floater_choose_group.xml
+++ b/indra/newview/skins/default/xui/de/floater_choose_group.xml
@@ -1,8 +1,8 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="groups" title="Gruppen">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="groups" title="GRUPPEN">
<text name="groupdesc">
Gruppe wählen:
</text>
- <button label="OK" label_selected="OK" name="OK" />
- <button label="Abbrechen" label_selected="Abbrechen" name="Cancel" />
+ <button label="OK" label_selected="OK" name="OK"/>
+ <button label="Abbrechen" label_selected="Abbrechen" name="Cancel"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_color_picker.xml b/indra/newview/skins/default/xui/de/floater_color_picker.xml
index f53a1135dc..552bd2e2bf 100644
--- a/indra/newview/skins/default/xui/de/floater_color_picker.xml
+++ b/indra/newview/skins/default/xui/de/floater_color_picker.xml
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="ColorPicker" title="Farbauswahl">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="ColorPicker" title="FARBAUSWAHL">
<text name="r_val_text">
Rot:
</text>
@@ -18,15 +18,14 @@
<text name="l_val_text">
Hell.:
</text>
- <check_box label="Sofort übernehmen" name="apply_immediate" />
- <button label="" label_selected="" name="color_pipette" />
- <button label="Abbrechen" label_selected="Abbrechen" name="cancel_btn" />
- <button label="Auswählen" label_selected="Auswählen" name="select_btn" />
+ <check_box label="Jetzt übernehmen" name="apply_immediate"/>
+ <button label="" label_selected="" name="color_pipette"/>
+ <button label="Abbrechen" label_selected="Abbrechen" name="cancel_btn"/>
+ <button label="OK" label_selected="OK" name="select_btn"/>
<text name="Current color:">
Aktuelle Farbe:
</text>
<text name="(Drag below to save.)">
-(Nach unten ziehen,
- um zu speichern.)
+ (Zum Speichern nach unten ziehen.)
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_customize.xml b/indra/newview/skins/default/xui/de/floater_customize.xml
index b27e5d22b4..34aa17bbe0 100644
--- a/indra/newview/skins/default/xui/de/floater_customize.xml
+++ b/indra/newview/skins/default/xui/de/floater_customize.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater customize" title="Aussehen">
+<floater name="floater customize" title="AUSSEHEN">
<tab_container name="customize tab container">
- <panel label="Körperteile" name="body_parts_placeholder"/>
+ <placeholder label="Körperteile" name="body_parts_placeholder"/>
<panel label="Form" name="Shape">
<button font="SansSerifSmall" label="Zurücksetzen" label_selected="Zurücksetzen" name="Revert"/>
<button label="Körper" label_selected="Körper" name="Body"/>
@@ -14,34 +14,30 @@
<button label="Oberkörper" label_selected="Oberkörper" name="Torso"/>
<button label="Beine" label_selected="Beine" name="Legs"/>
<radio_group name="sex radio">
- <radio_item length="1" name="radio" type="string">
- Weiblich
- </radio_item>
- <radio_item length="1" name="radio2" type="string">
- Männlich
- </radio_item>
+ <radio_item label="Weiblich" name="radio"/>
+ <radio_item label="Männlich" name="radio2"/>
</radio_group>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: bearbeiten nicht möglich
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: wird geladen...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: nicht getragen
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
In [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Ziehen Sie eine Körperform aus dem Inventar auf Ihren Avatar,
um sie zu tragen. Sie können auch eine neue Körperform erstellen
und diese anziehen.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Sie sind nicht berechtigt, diese Kleidung zu bearbeiten.
</text>
<text name="Item Action Label" right="100">
@@ -56,27 +52,27 @@ und diese anziehen.
<button label="Gesichtsdetails" label_selected="Gesichtsdetails" left="2" name="Face Detail" width="92"/>
<button label="Make-Uup" label_selected="Make-Uup" left="2" name="Makeup" width="92"/>
<button label="Körperdetails" label_selected="Körperdetails" left="2" name="Body Detail" width="92"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: bearbeiten nicht möglich
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: wird geladen...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: nicht getragen
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
In [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Ziehen Sie eine Haut aus dem Inventar auf Ihren Avatar,
um sie zu tragen. Sie können auch eine neue Haut erstellen
und diese anziehen.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Sie sind nicht berechtigt, diese Kleidung zu bearbeiten.
</text>
<text name="Item Action Label" right="100">
@@ -95,27 +91,27 @@ und diese anziehen.
<button label="Stil" label_selected="Stil" name="Style"/>
<button label="Augenbrauen" label_selected="Augenbrauen" name="Eyebrows"/>
<button label="Gesichtshaar" label_selected="Gesichtshaar" name="Facial"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: bearbeiten nicht möglich
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: wird geladen...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: nicht getragen
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
In [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Ziehen Sie Haare aus dem Inventar auf Ihren Avatar,
um sie zu tragen. Sie können auch neue Haare erstellen
und diese anziehen.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Sie sind nicht berechtigt, diese Kleidung zu bearbeiten.
</text>
<text name="Item Action Label" right="100">
@@ -128,27 +124,27 @@ und diese anziehen.
<button font="SansSerifSmall" label="Zurücksetzen" label_selected="Zurücksetzen" name="Revert"/>
</panel>
<panel label="Augen" name="Eyes">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: bearbeiten nicht möglich
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: wird geladen...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: nicht getragen
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
In [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Ziehen Sie Augen aus dem Inventar auf Ihren Avatar,
um sie zu tragen. Sie können auch neue Augen erstellen
und diese anziehen.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Sie sind nicht berechtigt, diese Kleidung zu bearbeiten.
</text>
<text name="Item Action Label" right="100">
@@ -160,7 +156,7 @@ und diese anziehen.
<button font="SansSerifSmall" label="Speichern unter..." label_selected="Speichern unter..." left="194" name="Save As" width="105"/>
<button font="SansSerifSmall" label="Zurücksetzen" label_selected="Zurücksetzen" name="Revert"/>
</panel>
- <panel label="Kleidung" name="clothes_placeholder"/>
+ <placeholder label="Kleidung" name="clothes_placeholder"/>
<panel label="Hemd" name="Shirt">
<texture_picker label="Stoff" name="Fabric" tool_tip="Klicken Sie hier, um ein Bild auszuwählen"/>
<color_swatch label="Farbe/Ton" name="Color/Tint" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen"/>
@@ -169,27 +165,27 @@ und diese anziehen.
<button font="SansSerifSmall" label="Speichern" label_selected="Speichern" left="107" name="Save"/>
<button font="SansSerifSmall" label="Speichern unter..." label_selected="Speichern unter..." left="194" name="Save As" width="105"/>
<button font="SansSerifSmall" label="Zurücksetzen" label_selected="Zurücksetzen" name="Revert"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: bearbeiten nicht möglich
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: wird geladen...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: nicht getragen
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
In [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Ziehen Sie ein Hemd aus dem Inventar auf Ihren Avatar,
um es zu tragen. Sie können auch ein neues Hemd erstellen
und dieses anziehen.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Sie sind nicht berechtigt, diese Kleidung zu bearbeiten.
</text>
<text name="Item Action Label" right="100">
@@ -204,27 +200,27 @@ und dieses anziehen.
<button font="SansSerifSmall" label="Speichern" label_selected="Speichern" left="107" name="Save"/>
<button font="SansSerifSmall" label="Speichern unter..." label_selected="Speichern unter..." left="194" name="Save As" width="105"/>
<button font="SansSerifSmall" label="Zurücksetzen" label_selected="Zurücksetzen" name="Revert"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: bearbeiten nicht möglich
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: wird geladen...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: nicht getragen
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
In [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Ziehen Sie eine Hose aus dem Inventar auf Ihren Avatar,
um sie zu tragen. Sie können auch eine neue Hose erstellen
und diese anziehen.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Sie sind nicht berechtigt, diese Kleidung zu bearbeiten.
</text>
<text name="Item Action Label" right="100">
@@ -232,27 +228,27 @@ und diese anziehen.
</text>
</panel>
<panel label="Schuhe" name="Shoes">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: bearbeiten nicht möglich
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: wird geladen...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: nicht getragen
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
In [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Ziehen Sie Schuhe aus dem Inventar auf Ihren Avatar,
um sie zu tragen. Sie können auch neue Schuhe erstellen
und diese anziehen.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Sie sind nicht berechtigt, diese Kleidung zu bearbeiten.
</text>
<text name="Item Action Label" right="100">
@@ -267,27 +263,27 @@ und diese anziehen.
<button font="SansSerifSmall" label="Zurücksetzen" label_selected="Zurücksetzen" name="Revert"/>
</panel>
<panel label="Socken" name="Socks">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: bearbeiten nicht möglich
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: wird geladen...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: nicht getragen
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
In [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Ziehen Sie Socken aus dem Inventar auf Ihren Avatar,
um sie zu tragen. Sie können auch neue Socken erstellen
und diese anziehen.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Sie sind nicht berechtigt, diese Kleidung zu bearbeiten.
</text>
<text name="Item Action Label" right="100">
@@ -302,27 +298,27 @@ und diese anziehen.
<button font="SansSerifSmall" label="Zurücksetzen" label_selected="Zurücksetzen" name="Revert"/>
</panel>
<panel label="Jacke" name="Jacket">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: bearbeiten nicht möglich
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: wird geladen...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: nicht getragen
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
In [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Ziehen Sie eine Jacke aus dem Inventar auf Ihren Avatar,
um sie zu tragen. Sie können auch eine neue Jacke erstellen
und diese anziehen.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Sie sind nicht berechtigt, diese Kleidung zu bearbeiten.
</text>
<text name="Item Action Label" right="100">
@@ -338,27 +334,27 @@ und diese anziehen.
<button font="SansSerifSmall" label="Zurücksetzen" label_selected="Zurücksetzen" name="Revert"/>
</panel>
<panel label="Handschuhe" name="Gloves">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: bearbeiten nicht möglich
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: wird geladen...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: nicht getragen
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
In [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Ziehen Sie Handschuhe aus dem Inventar auf Ihren Avatar,
um sie zu tragen. Sie können auch neue Handschuhe erstellen
und diese anziehen.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Sie sind nicht berechtigt, diese Kleidung zu bearbeiten.
</text>
<text name="Item Action Label" right="100">
@@ -373,27 +369,27 @@ und diese anziehen.
<button font="SansSerifSmall" label="Zurücksetzen" label_selected="Zurücksetzen" name="Revert"/>
</panel>
<panel label="Unterhemd" name="Undershirt">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: bearbeiten nicht möglich
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: wird geladen...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: nicht getragen
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
In [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Ziehen Sie ein Unterhemd aus dem Inventar auf Ihren Avatar,
um es zu tragen. Sie können auch ein neues Unterhemd erstellen
und dieses anziehen.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Sie sind nicht berechtigt, diese Kleidung zu bearbeiten.
</text>
<text name="Item Action Label" right="100">
@@ -408,27 +404,27 @@ und dieses anziehen.
<button font="SansSerifSmall" label="Zurücksetzen" label_selected="Zurücksetzen" name="Revert"/>
</panel>
<panel label="Unterhose" name="Underpants">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: bearbeiten nicht möglich
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: wird geladen...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: nicht getragen
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
In [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Ziehen Sie eine Unterhose aus dem Inventar auf Ihren Avatar,
um sie zu tragen. Sie können auch eine neue Unterhose erstellen
und diese anziehen.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Sie sind nicht berechtigt, diese Kleidung zu bearbeiten.
</text>
<text name="Item Action Label" right="100">
@@ -443,27 +439,27 @@ und diese anziehen.
<button font="SansSerifSmall" label="Zurücksetzen" label_selected="Zurücksetzen" name="Revert"/>
</panel>
<panel label="Rock" name="Skirt">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: bearbeiten nicht möglich
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: wird geladen...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: nicht getragen
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
In [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Ziehen Sie einen Rock aus dem Inventar auf Ihren Avatar,
um ihn zu tragen. Sie können auch einen neuen Rock erstellen
und diesen anziehen.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Sie sind nicht berechtigt, diese Kleidung zu bearbeiten.
</text>
<text name="Item Action Label" right="100">
@@ -477,8 +473,80 @@ und diesen anziehen.
<button font="SansSerifSmall" label="Speichern unter..." label_selected="Speichern unter..." left="194" name="Save As" width="105"/>
<button font="SansSerifSmall" label="Zurücksetzen" label_selected="Zurücksetzen" name="Revert"/>
</panel>
+ <panel label="Alpha" name="Alpha">
+ <text name="title">
+ [BESCHR]
+ </text>
+ <text name="title_no_modify">
+ [BESCHR]: bearbeiten nicht möglich
+ </text>
+ <text name="title_loading">
+ [BESCHR]: wird geladen...
+ </text>
+ <text name="title_not_worn">
+ [BESCHR]: nicht getragen
+ </text>
+ <text name="path">
+ Befindet sich in [PATH]
+ </text>
+ <text name="not worn instructions">
+ Sie können eine neue Alpha-Maske anlegen, indem Sie eine von Ihrem Inventar auf Ihren Avatar ziehen.
+Sie können aber auch eine neue erstellen und diese anlegen.
+ </text>
+ <text name="no modify instructions">
+ Sie sind nicht berechtigt, diese Kleidung zu bearbeiten.
+ </text>
+ <text name="Item Action Label">
+ Alpha:
+ </text>
+ <texture_picker label="Alpha: Unten" name="Lower Alpha" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <texture_picker label="Alpha: Oben" name="Upper Alpha" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <texture_picker label="Kopf: Alpha" name="Head Alpha" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <texture_picker label="Alpha: Augen" name="Eye Alpha" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <texture_picker label="Alpha: Haare" name="Hair Alpha" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <button label="Neue Alpha erstellen" label_selected="Neue Alpha erstellen" name="Create New"/>
+ <button label="Ausziehen" label_selected="Ausziehen" name="Take Off"/>
+ <button label="Speichern" label_selected="Speichern" name="Save"/>
+ <button label="Speichern unter..." label_selected="Speichern unter..." name="Save As"/>
+ <button label="Zurücksetzen" label_selected="Zurücksetzen" name="Revert"/>
+ </panel>
+ <panel label="Tätowierung" name="Tattoo">
+ <text name="title">
+ [BESCHR]
+ </text>
+ <text name="title_no_modify">
+ [BESCHR]: bearbeiten nicht möglich
+ </text>
+ <text name="title_loading">
+ [BESCHR]: wird geladen...
+ </text>
+ <text name="title_not_worn">
+ [BESCHR]: nicht getragen
+ </text>
+ <text name="path">
+ Befindet sich in [PATH]
+ </text>
+ <text name="not worn instructions">
+ Ziehen Sie eine neue Tätowierung aus dem Inventar auf Ihren Avatar, um diese anzulegen.
+Sie können aber auch eine neue erstellen und diese anlegen.
+ </text>
+ <text name="no modify instructions">
+ Sie sind nicht berechtigt, diese Kleidung zu bearbeiten.
+ </text>
+ <text name="Item Action Label">
+ Tätowierung:
+ </text>
+ <texture_picker label="Kopftattoo" name="Head Tattoo" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <texture_picker label="Obere Tattoos" name="Upper Tattoo" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <texture_picker label="Untere Tattoos" name="Lower Tattoo" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <button label="Neue Tätowierung erstellen" label_selected="Neue Tätowierung erstellen" name="Create New"/>
+ <button label="Ausziehen" label_selected="Ausziehen" name="Take Off"/>
+ <button label="Speichern" label_selected="Speichern" name="Save"/>
+ <button label="Speichern unter..." label_selected="Speichern unter..." name="Save As"/>
+ <button label="Zurücksetzen" label_selected="Zurücksetzen" name="Revert"/>
+ </panel>
</tab_container>
+ <button label="Outfit erstellen" label_selected="Outfit erstellen" name="make_outfit_btn"/>
<button label="Abbrechen" label_selected="Abbrechen" name="Cancel"/>
<button label="OK" label_selected="OK" name="Ok"/>
- <button label="Outfit erstellen..." label_selected="Outfit erstellen..." name="Make Outfit" width="115"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_day_cycle_options.xml b/indra/newview/skins/default/xui/de/floater_day_cycle_options.xml
index d5a216a0b5..7f4dc4a79e 100644
--- a/indra/newview/skins/default/xui/de/floater_day_cycle_options.xml
+++ b/indra/newview/skins/default/xui/de/floater_day_cycle_options.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Day Cycle Floater" title="Tageszyklus-Editor">
+<floater name="Day Cycle Floater" title="TAGESZYKLUS-EDITOR">
<tab_container name="Day Cycle Tabs">
<panel label="Tageszyklus" name="Day Cycle">
<button label=" ?" name="WLDayCycleHelp" />
diff --git a/indra/newview/skins/default/xui/de/floater_device_settings.xml b/indra/newview/skins/default/xui/de/floater_device_settings.xml
index 734f4e942c..3d7e9c96c1 100644
--- a/indra/newview/skins/default/xui/de/floater_device_settings.xml
+++ b/indra/newview/skins/default/xui/de/floater_device_settings.xml
@@ -1,2 +1,2 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_device_settings" title="Geräte-Einstellungen für Voice-Chat" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_device_settings" title="EINSTELLUNGEN FÃœR VOICE-CHAT"/>
diff --git a/indra/newview/skins/default/xui/de/floater_env_settings.xml b/indra/newview/skins/default/xui/de/floater_env_settings.xml
index 3717ff6a48..0f2370771f 100644
--- a/indra/newview/skins/default/xui/de/floater_env_settings.xml
+++ b/indra/newview/skins/default/xui/de/floater_env_settings.xml
@@ -1,5 +1,8 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Environment Editor Floater" title="Umwelt-Editor">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Environment Editor Floater" title="UMWELT-EDITOR">
+ <floater.string name="timeStr">
+ [hour12,datetime,utc]:[min,datetime,utc] [ampm,datetime,utc]
+ </floater.string>
<text name="EnvTimeText">
Tageszeit
</text>
@@ -12,13 +15,12 @@
<text name="EnvWaterColorText">
Wasserfarbe
</text>
- <color_swatch name="EnvWaterColor" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen" />
+ <color_swatch name="EnvWaterColor" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen"/>
<text name="EnvWaterFogText">
Wasser-
trübung
</text>
- <button label="Grundstückszeit verw." name="EnvUseEstateTimeButton" />
- <button label="Himmel (erweitert)" name="EnvAdvancedSkyButton" />
- <button label="Wasser (erweitert)" name="EnvAdvancedWaterButton" />
- <button label=" ?" name="EnvSettingsHelpButton" />
+ <button label="Grundstückszeit verw." name="EnvUseEstateTimeButton"/>
+ <button label="Himmel (erweitert)" name="EnvAdvancedSkyButton"/>
+ <button label="Wasser (erweitert)" name="EnvAdvancedWaterButton"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_first_time_tip.xml b/indra/newview/skins/default/xui/de/floater_first_time_tip.xml
new file mode 100644
index 0000000000..9546cc2c42
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_first_time_tip.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="set_name_in_the_cladd">
+ <check_box label="Turn off Quick Tips" name="DontShowFirstTimeTip_checkbox"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_font_test.xml b/indra/newview/skins/default/xui/de/floater_font_test.xml
index 54278fc094..29357b8ee0 100644
--- a/indra/newview/skins/default/xui/de/floater_font_test.xml
+++ b/indra/newview/skins/default/xui/de/floater_font_test.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="contents" title="Schriftart-Test">
+<floater name="contents" title="TEST DER SCHRIFTART">
<text name="linea">
OverrideTest, sollte hier als Times angezeigt werden. (Aus default/xui/en-us)
</text>
diff --git a/indra/newview/skins/default/xui/de/floater_gesture.xml b/indra/newview/skins/default/xui/de/floater_gesture.xml
index bdee3b8664..0b27b362c3 100644
--- a/indra/newview/skins/default/xui/de/floater_gesture.xml
+++ b/indra/newview/skins/default/xui/de/floater_gesture.xml
@@ -1,17 +1,27 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="gestures" title="Aktive Gesten">
- <text name="help_label">
- Doppelklicken Sie auf eine Geste, um Animationen und Sound &#10;abzuspielen.
- </text>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater label="Orte" name="gestures" title="GESTEN">
+ <floater.string name="loading">
+ Wird geladen...
+ </floater.string>
+ <floater.string name="playing">
+ (Wird abgespielt)
+ </floater.string>
+ <floater.string name="copy_name">
+ Kopie von [COPY_NAME]
+ </floater.string>
<scroll_list bottom_delta="-385" height="360" name="gesture_list">
- <column label="Trigger" name="trigger" />
- <column label="Key" name="shortcut" />
- <column label="" name="key" />
- <column label="Name" name="name" />
+ <scroll_list.columns label="Name" name="name"/>
+ <scroll_list.columns label="Chat" name="trigger"/>
+ <scroll_list.columns label="" name="key"/>
+ <scroll_list.columns label="Key" name="shortcut"/>
</scroll_list>
- <button label="Neu" name="new_gesture_btn" />
- <button label="Inventar" name="inventory_btn" />
- <button label="Bearbeiten" name="edit_btn" />
- <button label="Abspielen" name="play_btn" />
- <button label="Stopp" name="stop_btn" />
+ <panel label="bottom_panel" name="bottom_panel">
+ <menu_button name="gear_btn" tool_tip="Mehr Möglichkeiten"/>
+ <button name="new_gesture_btn" tool_tip="Neue Geste erstellen"/>
+ <button name="activate_btn" tool_tip="Ausgewählte Geste aktivieren/deaktivieren"/>
+ <button name="del_btn" tool_tip="Diese Geste löschen"/>
+ </panel>
+ <button label="Bearbeiten" name="edit_btn"/>
+ <button label="Abspielen" name="play_btn"/>
+ <button label="Stopp" name="stop_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_god_tools.xml b/indra/newview/skins/default/xui/de/floater_god_tools.xml
index dcb6982588..e790420efb 100644
--- a/indra/newview/skins/default/xui/de/floater_god_tools.xml
+++ b/indra/newview/skins/default/xui/de/floater_god_tools.xml
@@ -1,148 +1,102 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="godtools floater" title="Gott-Werkzeuge">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="godtools floater" title="GOTT-WERKZEUGE">
<tab_container name="GodTools Tabs">
<panel label="Raster" name="grid">
- <button label="Alle Benutzer hinauswerfen" label_selected="Alle Benutzer hinauswerfen"
- name="Kick all users" width="175" />
- <button label="Sichtbarkeits-Cache dieser Regionskarte leeren"
- label_selected="Sichtbarkeits-Cache dieser Regionskarte leeren"
- name="Flush This Region&apos;s Map Visibility Caches" width="285" />
+ <button label="Alle Benutzer hinauswerfen" label_selected="Alle Benutzer hinauswerfen" name="Kick all users" width="175"/>
+ <button label="Sichtbarkeits-Cache dieser Regionskarte leeren" label_selected="Sichtbarkeits-Cache dieser Regionskarte leeren" name="Flush This Region&apos;s Map Visibility Caches" width="285"/>
</panel>
<panel label="Region" name="region">
<text name="Sim Name:" width="55">
Sim-Name:
</text>
- <check_box label="Startbereich Einleitung" name="check prelude"
- tool_tip="Diese Region zu einem Startbereich machen." />
- <check_box label="Sonne fest" name="check fixed sun"
- tool_tip="Fixiert den Sonnenstand (wie in „Region/Grundstück“ &gt; „Terrain“." />
- <check_box label="Zuhause auf Teleport &#10;zurücksetzen" name="check reset home"
- tool_tip="Wenn Einwohner wegteleportieren, ihr Zuhause auf Zielposition setzen." height="32" />
- <check_box label="Sichtbar" name="check visible"
- tool_tip="Diese Region für Nicht-Götter sichtbar machen." bottom_delta="-32" />
- <check_box label="Schaden" name="check damage"
- tool_tip="Schaden in dieser Region aktivieren." />
- <check_box label="Trafficüberwachung blockieren" name="block dwell"
- tool_tip="In dieser Region die Traffic-Berechnung abschalten." />
- <check_box label="Terraformen blockieren" name="block terraform"
- tool_tip="Das Terraformen von Land verbieten (Benutzen Sie dies um Leuten das Terraformen ihres Landes zu verbieten)" />
- <check_box label="Sandkasten" name="is sandbox"
- tool_tip="Sandkastenregion ein-/ausschalten." />
- <button label="Terrain formen" label_selected="Terrain formen" name="Bake Terrain"
- tool_tip="Das aktuelle Terrain als Standard speichern." width="118" />
- <button label="Terrain zurücksetzen" label_selected="Terrain zurücksetzen"
- name="Revert Terrain"
- tool_tip="Das aktuelle Terrain mit dem Standard ersetzen." width="118" />
- <button label="Terrain tauschen" label_selected="Terrain tauschen" name="Swap Terrain"
- tool_tip="Aktuelles Terrain gegen Standard austauschen." width="118" />
+ <check_box label="Startbereich Einleitung" name="check prelude" tool_tip="Diese Region zu einem Startbereich machen."/>
+ <check_box label="Sonne fest" name="check fixed sun" tool_tip="Fixiert den Sonnenstand (wie in „Region/Grundstück“ &gt; „Terrain“."/>
+ <check_box height="32" label="Zuhause auf Teleport
+zurücksetzen" name="check reset home" tool_tip="Wenn Einwohner wegteleportieren, ihr Zuhause auf Zielposition setzen."/>
+ <check_box bottom_delta="-32" label="Sichtbar" name="check visible" tool_tip="Diese Region für Nicht-Götter sichtbar machen."/>
+ <check_box label="Schaden" name="check damage" tool_tip="Schaden in dieser Region aktivieren."/>
+ <check_box label="Trafficüberwachung blockieren" name="block dwell" tool_tip="In dieser Region die Traffic-Berechnung abschalten."/>
+ <check_box label="Terraformen blockieren" name="block terraform" tool_tip="Das Terraformen von Land verbieten (Benutzen Sie dies um Leuten das Terraformen ihres Landes zu verbieten)"/>
+ <check_box label="Sandkasten" name="is sandbox" tool_tip="Sandkastenregion ein-/ausschalten."/>
+ <button label="Terrain formen" label_selected="Terrain formen" name="Bake Terrain" tool_tip="Das aktuelle Terrain als Standard speichern." width="118"/>
+ <button label="Terrain zurücksetzen" label_selected="Terrain zurücksetzen" name="Revert Terrain" tool_tip="Das aktuelle Terrain mit dem Standard ersetzen." width="118"/>
+ <button label="Terrain tauschen" label_selected="Terrain tauschen" name="Swap Terrain" tool_tip="Aktuelles Terrain gegen Standard austauschen." width="118"/>
<text name="estate id">
Grundstücks-ID:
</text>
<text name="parent id">
Parent ID:
</text>
- <line_editor name="parentestate" tool_tip="Das übergeordnete Grundstück dieser Region" />
+ <line_editor name="parentestate" tool_tip="Das übergeordnete Grundstück dieser Region"/>
<text name="Grid Pos: ">
Raster-Pos.:
</text>
- <line_editor name="gridposx" tool_tip="Die X-Rasterposition dieser Region" left_delta="110" width="35" />
- <line_editor name="gridposy" tool_tip="Die Y-Rasterposition dieser Region" left_delta="45" width="35" />
- <text name="Redirect to Grid: " >
+ <line_editor left_delta="110" name="gridposx" tool_tip="Die X-Rasterposition dieser Region" width="35"/>
+ <line_editor left_delta="45" name="gridposy" tool_tip="Die Y-Rasterposition dieser Region" width="35"/>
+ <text name="Redirect to Grid: ">
Auf Raster umleiten:
</text>
- <line_editor left_delta="110" name="redirectx" width="35" />
- <line_editor left_delta="45" name="redirecty" width="35" />
- <text name="billable factor text" font="SansSerifSmall" >
+ <line_editor left_delta="110" name="redirectx" width="35"/>
+ <line_editor left_delta="45" name="redirecty" width="35"/>
+ <text font="SansSerifSmall" name="billable factor text">
Abrechnungsfaktor:
</text>
<text name="land cost text">
L$ pro qm:
</text>
- <button label="Aktualisieren" label_selected="Aktualisieren" name="Refresh"
- tool_tip="Klicken Sie hier, um die obigen Informationen zu aktualisieren." />
- <button label="Ãœbernehmen" label_selected="Ãœbernehmen" name="Apply"
- tool_tip="Klicken Sie hier, um die obigen Änderungen zu übernehmen." />
- <button label="Region auswählen" label_selected="Region auswählen"
- name="Select Region"
- tool_tip="Die gesamte Region mit dem Landwerkzeug auswählen." width="130" left="136"/>
- <button label="Automatisch speichern" label_selected="Automatisch speichern"
- name="Autosave now"
- tool_tip="gzipped-Status im Autosave-Verzeichnis speichern." width="130" left="136"/>
+ <button label="Aktualisieren" label_selected="Aktualisieren" name="Refresh" tool_tip="Klicken Sie hier, um die obigen Informationen zu aktualisieren."/>
+ <button label="Übernehmen" label_selected="Übernehmen" name="Apply" tool_tip="Klicken Sie hier, um die obigen Änderungen zu übernehmen."/>
+ <button label="Region auswählen" label_selected="Region auswählen" left="136" name="Select Region" tool_tip="Die gesamte Region mit dem Landwerkzeug auswählen." width="130"/>
+ <button label="Automatisch speichern" label_selected="Automatisch speichern" left="136" name="Autosave now" tool_tip="gzipped-Status im Autosave-Verzeichnis speichern." width="130"/>
</panel>
<panel label="Objekte" name="objects">
+ <panel.string name="no_target">
+ (kein Ziel)
+ </panel.string>
<text name="Sim Name:" width="55">
Sim-Name:
</text>
<text name="region name">
Welsh
</text>
- <check_box label="Skripts &#10;deaktivieren" name="disable scripts"
- tool_tip="Skripts in dieser Region komplett abschalten" />
- <check_box label="Kollisionen &#10;deaktivieren" name="disable collisions"
- tool_tip="Nicht-Avatar-Kollisionen in dieser Region komplett abschalten" />
- <check_box label="Physik deaktivieren" name="disable physics"
- tool_tip="Die Physik in dieser Region komplett abschalten" />
- <button label="Ãœbernehmen" label_selected="Ãœbernehmen" name="Apply"
- tool_tip="Klicken Sie hier, um die obigen Änderungen zu übernehmen." />
- <button label="Ziel festlegen" label_selected="Ziel festlegen" name="Set Target"
- tool_tip="Den Ziel-Avatar für das Löschen von Objekten auswählen." />
+ <check_box label="Skripts
+deaktivieren" name="disable scripts" tool_tip="Skripts in dieser Region komplett abschalten"/>
+ <check_box label="Kollisionen
+deaktivieren" name="disable collisions" tool_tip="Nicht-Avatar-Kollisionen in dieser Region komplett abschalten"/>
+ <check_box label="Physik deaktivieren" name="disable physics" tool_tip="Die Physik in dieser Region komplett abschalten"/>
+ <button label="Übernehmen" label_selected="Übernehmen" name="Apply" tool_tip="Klicken Sie hier, um die obigen Änderungen zu übernehmen."/>
+ <button label="Ziel festlegen" label_selected="Ziel festlegen" name="Set Target" tool_tip="Den Ziel-Avatar für das Löschen von Objekten auswählen."/>
<text name="target_avatar_name">
(kein Ziel)
</text>
- <button label="Geskriptete Objekte des Ziels auf anderen Ländern löschen"
- label_selected="Geskriptete Objekte des Ziels auf anderen Ländern löschen"
- name="Delete Target&apos;s Scripted Objects On Others Land"
- tool_tip="Alle dem Ziel gehörenden geskripteten Objekte auf Land, das dem Ziel nicht gehört, löschen. Objekte (nicht kopierfähig) werden zurückgegeben." />
- <button label="Geskriptete Objekte des Ziels auf *allen* Ländern löschen"
- label_selected="Geskriptete Objekte des Ziels auf *allen* Ländern löschen"
- name="Delete Target&apos;s Scripted Objects On *Any* Land"
- tool_tip="Alle dem Ziel gehörenden geskripteten Objekte in dieser Region löschen. Objekte (nicht kopierfähig) werden zurückgegeben." />
- <button label="*ALLE* Objekte des Ziels löschen"
- label_selected="*ALLE* Objekte des Ziels löschen"
- name="Delete *ALL* Of Target&apos;s Objects"
- tool_tip="Alle dem Ziel gehörenden Objekte in dieser Region löschen. Objekte (nicht kopierfähig) werden zurückgegeben." />
- <button label="Top-Kollisionsobjekte" label_selected="Top-Kollisionsobjekte"
- name="Get Top Colliders"
- tool_tip="Zeigt eine Liste der Objekte mit den meisten Callbacks in der nahen Phase an." width="130" />
- <button label="Top-Skripts" label_selected="Top-Skripts" name="Get Top Scripts"
- tool_tip="Zeigt eine Liste der Objekte an, die die meiste Zeit über Skripts ausführen." width="130" />
- <button label="Scripting-Ãœbersicht" label_selected="Scripting-Ãœbersicht"
- name="Scripts digest"
- tool_tip="Zeigt eine Liste aller Skripts mit Häufigkeit an." width="130" />
+ <button label="Geskriptete Objekte des Ziels auf anderen Ländern löschen" label_selected="Geskriptete Objekte des Ziels auf anderen Ländern löschen" name="Delete Target&apos;s Scripted Objects On Others Land" tool_tip="Alle dem Ziel gehörenden geskripteten Objekte auf Land, das dem Ziel nicht gehört, löschen. Objekte (nicht kopierfähig) werden zurückgegeben."/>
+ <button label="Geskriptete Objekte des Ziels auf *allen* Ländern löschen" label_selected="Geskriptete Objekte des Ziels auf *allen* Ländern löschen" name="Delete Target&apos;s Scripted Objects On *Any* Land" tool_tip="Alle dem Ziel gehörenden geskripteten Objekte in dieser Region löschen. Objekte (nicht kopierfähig) werden zurückgegeben."/>
+ <button label="*ALLE* Objekte des Ziels löschen" label_selected="*ALLE* Objekte des Ziels löschen" name="Delete *ALL* Of Target&apos;s Objects" tool_tip="Alle dem Ziel gehörenden Objekte in dieser Region löschen. Objekte (nicht kopierfähig) werden zurückgegeben."/>
+ <button label="Top-Kollisionsobjekte" label_selected="Top-Kollisionsobjekte" name="Get Top Colliders" tool_tip="Zeigt eine Liste der Objekte mit den meisten Callbacks in der nahen Phase an." width="130"/>
+ <button label="Top-Skripts" label_selected="Top-Skripts" name="Get Top Scripts" tool_tip="Zeigt eine Liste der Objekte an, die die meiste Zeit über Skripts ausführen." width="130"/>
+ <button label="Scripting-Übersicht" label_selected="Scripting-Übersicht" name="Scripts digest" tool_tip="Zeigt eine Liste aller Skripts mit Häufigkeit an." width="130"/>
</panel>
<panel label="Anfrage" name="request">
<text name="Destination:">
Ziel:
</text>
<combo_box name="destination">
- <combo_item name="Selection">
- Auswahl
- </combo_item>
- <combo_item name="AgentRegion">
- Avatar-Region
- </combo_item>
+ <combo_box.item label="Auswahl" name="item1"/>
+ <combo_box.item label="Avatar-Region" name="item2"/>
</combo_box>
<text name="Request:">
Anfrage:
</text>
<combo_box name="request">
- <combo_item name="colliders&lt;steps&gt;">
- Kollisionsobjekte &lt;Schritte&gt;
- </combo_item>
- <combo_item name="scripts&lt;count&gt;,&lt;optionalpattern&gt;">
- Skripts &lt;Zähler&gt;,&lt;Optionales Muster&gt;
- </combo_item>
- <combo_item name="objects&lt;pattern&gt;">
- Objekte &lt;Muster&gt;
- </combo_item>
- <combo_item name="rez&lt;asset_id&gt;">
- &lt;asset_id&gt; erstellen
- </combo_item>
+ <combo_box.item label="Kollisionsobjekte &lt;Schritte&gt;" name="item1"/>
+ <combo_box.item label="Skripts &lt;Zähler&gt;,&lt;Optionales Muster&gt;" name="item2"/>
+ <combo_box.item label="Objekte &lt;Muster&gt;" name="item3"/>
+ <combo_box.item label="lt;asset_id&gt; erstellen" name="item4"/>
</combo_box>
<text name="Parameter:">
Parameter:
</text>
- <button label="Anfrage" label_selected="Anfrage" name="Make Request" />
+ <button label="Anfrage" label_selected="Anfrage" name="Make Request"/>
</panel>
</tab_container>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_hardware_settings.xml b/indra/newview/skins/default/xui/de/floater_hardware_settings.xml
index a90e726392..d01ea145f1 100644
--- a/indra/newview/skins/default/xui/de/floater_hardware_settings.xml
+++ b/indra/newview/skins/default/xui/de/floater_hardware_settings.xml
@@ -1,40 +1,28 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Hardware Settings Floater" title="Hardware-Einstellungen">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Hardware Settings Floater" title="HARDWARE-EINSTELLUNGEN">
<text name="Filtering:">
Filtern:
</text>
- <check_box label="Anisotropische Filterung (langsamer, wenn aktiviert)" name="ani" />
+ <check_box label="Anisotropische Filterung (langsamer, wenn aktiviert)" name="ani"/>
<text name="Antialiasing:">
Antialiasing:
</text>
<combo_box label="Antialiasing" name="fsaa">
- <combo_item name="FSAADisabled">
- Deaktiviert
- </combo_item>
- <combo_item name="2x">
- 2x
- </combo_item>
- <combo_item name="4x">
- 4x
- </combo_item>
- <combo_item name="8x">
- 8x
- </combo_item>
- <combo_item name="16x">
- 16x
- </combo_item>
+ <combo_box.item label="Deaktiviert" name="FSAADisabled"/>
+ <combo_box.item label="2x" name="2x"/>
+ <combo_box.item label="4x" name="4x"/>
+ <combo_box.item label="8x" name="8x"/>
+ <combo_box.item label="16x" name="16x"/>
</combo_box>
- <spinner label="Gamma:" name="gamma" />
+ <spinner label="Gamma:" name="gamma"/>
<text name="(brightness, lower is brighter)">
- (Helligkeit, niedriger ist heller, 0=Standard)
+ (0 = Standard-Helligkeit, weniger = heller)
</text>
<text name="Enable VBO:">
VBO aktivieren:
</text>
- <check_box label="OpenGL Vertex-Buffer-Objekte aktivieren" name="vbo"
- tool_tip="Wenn Sie über moderne Grafikhardware verfügen, können Sie durch Aktivieren dieser Option die Geschwindigkeit verbessern. Bei alter Hardware sind die VBO oft schlecht implementiert, was zu Abstürzen führen kann, wenn diese Option aktiviert ist." />
- <slider label="Texturspeicher (MB):" name="GrapicsCardTextureMemory"
- tool_tip="Speicherplatz, der für Texturen zur Verfügung steht. In der Regel handelt es sich um Grafikkartenspeicher. Ein kleinerer Wert kann die Geschwindigkeit erhöhen, aber auch zu Texturunschärfen führen." />
- <spinner label="Nebeldistanzverhältnis:" name="fog" />
- <button label="OK" label_selected="OK" name="OK" />
+ <check_box initial_value="true" label="OpenGL Vertex-Buffer-Objekte aktivieren" name="vbo" tool_tip="Wenn Sie über moderne Grafikhardware verfügen, können Sie durch Aktivieren dieser Option die Geschwindigkeit verbessern. Bei alter Hardware sind die VBO oft schlecht implementiert, was zu Abstürzen führen kann, wenn diese Option aktiviert ist."/>
+ <slider label="Texturspeicher (MB):" name="GraphicsCardTextureMemory" tool_tip="Speicherplatz, der für Texturen zur Verfügung steht. In der Regel handelt es sich um Grafikkartenspeicher. Ein kleinerer Wert kann die Geschwindigkeit erhöhen, aber auch zu Texturunschärfen führen."/>
+ <spinner label="Nebeldistanzverhältnis:" name="fog"/>
+ <button label="OK" label_selected="OK" name="OK"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_help_browser.xml b/indra/newview/skins/default/xui/de/floater_help_browser.xml
new file mode 100644
index 0000000000..bfefa57731
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_help_browser.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_help_browser" title="HILFE-BROWSER">
+ <floater.string name="home_page_url">
+ http://de.secondlife.com
+ </floater.string>
+ <floater.string name="support_page_url">
+ http://de.secondlife.com/support
+ </floater.string>
+ <layout_stack name="stack1">
+ <layout_panel name="external_controls">
+ <button label="In meinem Browser öffnen" name="open_browser"/>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_hud.xml b/indra/newview/skins/default/xui/de/floater_hud.xml
index 0f11e2346d..8a10eccabe 100644
--- a/indra/newview/skins/default/xui/de/floater_hud.xml
+++ b/indra/newview/skins/default/xui/de/floater_hud.xml
@@ -1,2 +1,2 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_hud" title="Tutorial" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_hud" title="ANLEITUNG"/>
diff --git a/indra/newview/skins/default/xui/de/floater_im.xml b/indra/newview/skins/default/xui/de/floater_im.xml
index 9b9bbd0c64..6aa35f2900 100644
--- a/indra/newview/skins/default/xui/de/floater_im.xml
+++ b/indra/newview/skins/default/xui/de/floater_im.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<multi_floater name="im_floater" title="Instant Message">
<string name="only_user_message">
Sie sind der einzige Benutzer in dieser Sitzung.
@@ -10,7 +10,7 @@
Klicken Sie auf [BUTTON NAME], um eine Verbindung zu diesem Voice-Chat herzustellen.
</string>
<string name="muted_message">
- Sie haben diesen Einwohner stummgeschaltet.Wenn Sie ihm eine Nachricht senden, wird die Stummschaltung automatisch aufgehoben.
+ Sie haben diesen Einwohner ignoriert. Wenn Sie eine Nachricht senden, wird dieser freigeschaltet.
</string>
<string name="generic_request_error">
Fehler bei Anfrage, bitte versuchen Sie es später.
diff --git a/indra/newview/skins/default/xui/de/floater_im_container.xml b/indra/newview/skins/default/xui/de/floater_im_container.xml
new file mode 100644
index 0000000000..62578c00d5
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_im_container.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<multi_floater name="floater_im_box" title="Sofortnachrichten"/>
diff --git a/indra/newview/skins/default/xui/de/floater_im_session.xml b/indra/newview/skins/default/xui/de/floater_im_session.xml
new file mode 100644
index 0000000000..7bde3a3453
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_im_session.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="panel_im">
+ <layout_stack name="im_panels">
+ <layout_panel label="IM Steuerkonsole" name="panel_im_control_panel"/>
+ <layout_panel>
+ <line_editor label="Bis" name="chat_editor"/>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_image_preview.xml b/indra/newview/skins/default/xui/de/floater_image_preview.xml
index 145e0bbc33..7f66234dab 100644
--- a/indra/newview/skins/default/xui/de/floater_image_preview.xml
+++ b/indra/newview/skins/default/xui/de/floater_image_preview.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Image Preview" title="">
<text name="name_label">
Name:
@@ -10,43 +10,23 @@
Bildvorschau als:
</text>
<combo_box label="Kleidungstyp" name="clothing_type_combo">
- <combo_item name="Image">
- Bild
- </combo_item>
- <combo_item name="Hair">
- Haar
- </combo_item>
- <combo_item name="FemaleHead">
- Kopf (Frau)
- </combo_item>
- <combo_item name="FemaleUpperBody">
- Oberkörper (Frau)
- </combo_item>
- <combo_item name="FemaleLowerBody">
- Unterkörper (Frau)
- </combo_item>
- <combo_item name="MaleHead">
- Kopf (Mann)
- </combo_item>
- <combo_item name="MaleUpperBody">
- Oberkörper (Mann)
- </combo_item>
- <combo_item name="MaleLowerBody">
- Unterkörper (Mann)
- </combo_item>
- <combo_item name="Skirt">
- Rock
- </combo_item>
- <combo_item name="SculptedPrim">
- Geformtes Primitiv
- </combo_item>
+ <combo_box.item label="Bild" name="Image"/>
+ <combo_box.item label="Haare" name="Hair"/>
+ <combo_box.item label="Kopf (Frau)" name="FemaleHead"/>
+ <combo_box.item label="Oberkörper (Frau)" name="FemaleUpperBody"/>
+ <combo_box.item label="Unterkörper (Frau)" name="FemaleLowerBody"/>
+ <combo_box.item label="Kopf (Mann)" name="MaleHead"/>
+ <combo_box.item label="Oberkörper (Mann)" name="MaleUpperBody"/>
+ <combo_box.item label="Unterkörper (Mann)" name="MaleLowerBody"/>
+ <combo_box.item label="Rock" name="Skirt"/>
+ <combo_box.item label="Geformtes Primitiv" name="SculptedPrim"/>
</combo_box>
<text name="bad_image_text">
Bild kann nicht gelesen werden.
Speichern Sie das Bild als 24 Bit Targa (.tga).
</text>
- <check_box label="Verlustfreie Komprimierung verwenden" name="lossless_check" />
- <button label="Abbrechen" name="cancel_btn" />
- <button label="Hochladen ([AMOUNT] L$)" name="ok_btn" />
+ <check_box label="Verlustfreie Komprimierung verwenden" name="lossless_check"/>
+ <button label="Abbrechen" name="cancel_btn"/>
+ <button label="Hochladen ([AMOUNT] L$)" name="ok_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_incoming_call.xml b/indra/newview/skins/default/xui/de/floater_incoming_call.xml
new file mode 100644
index 0000000000..e40d57976f
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_incoming_call.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="incoming call" title="ANRUF VON UNBEKANNT">
+ <floater.string name="localchat">
+ Voice-Chat in der Nähe
+ </floater.string>
+ <floater.string name="anonymous">
+ Anonym
+ </floater.string>
+ <floater.string name="VoiceInviteP2P">
+ ruft an.
+ </floater.string>
+ <floater.string name="VoiceInviteAdHoc">
+ ist einem Voice-Konferenz-Chat beigetreten.
+ </floater.string>
+ <text name="question">
+ Möchten Sie [CURRENT_CHAT] verlassen und diesem Voice-Chat beitreten?
+ </text>
+ <button label="Akzeptieren" label_selected="Akzeptieren" name="Accept"/>
+ <button label="Ablehnen" label_selected="Ablehnen" name="Reject"/>
+ <button label="IM starten" name="Start IM"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_inspect.xml b/indra/newview/skins/default/xui/de/floater_inspect.xml
index f8c9b62824..939aa964c0 100644
--- a/indra/newview/skins/default/xui/de/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/de/floater_inspect.xml
@@ -1,14 +1,14 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="inspect" title="Objekt prüfen" min_width="450" >
- <scroll_list name="object_list"
- tool_tip="Wählen Sie ein Objekt aus dieser Liste, um es in der Second Life-Welt zu markieren">
- <column label="Objektname" name="object_name" />
- <column label="Besitzer" name="owner_name" />
- <column label="Ersteller" name="creator_name" />
- <column label="Erstellungsdatum" name="creation_date" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater min_width="450" name="inspect" title="OBJEKTE UNTERSUCHEN">
+ <floater.string name="timeStamp">
+ [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+ </floater.string>
+ <scroll_list name="object_list" tool_tip="Wählen Sie ein Objekt aus dieser Liste, um es in der Second Life-Welt zu markieren">
+ <scroll_list.columns label="Objektname" name="object_name"/>
+ <scroll_list.columns label="Besitzer" name="owner_name"/>
+ <scroll_list.columns label="Ersteller" name="creator_name"/>
+ <scroll_list.columns label="Erstellungsdatum" name="creation_date"/>
</scroll_list>
- <button label="Besitzerprofil einsehen..." name="button owner"
- tool_tip="Profil des Besitzers des markierten Objekts einsehen" width="155" />
- <button label="Erstellerprofil einsehen..." name="button creator"
- tool_tip="Profil des ursprünglichen Erstellers des markierten Objekts einsehen" width="155" left="175"/>
+ <button label="Besitzerprofil einsehen..." name="button owner" tool_tip="Profil des Besitzers des markierten Objekts einsehen" width="155"/>
+ <button label="Erstellerprofil einsehen..." left="175" name="button creator" tool_tip="Profil des ursprünglichen Erstellers des markierten Objekts einsehen" width="155"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_inventory.xml b/indra/newview/skins/default/xui/de/floater_inventory.xml
index c8c67240d8..d9014fc0ef 100644
--- a/indra/newview/skins/default/xui/de/floater_inventory.xml
+++ b/indra/newview/skins/default/xui/de/floater_inventory.xml
@@ -1,47 +1,16 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Inventory" title="Inventar">
- <search_editor label="Suchanfrage hier eintippen" name="inventory search editor" />
- <tab_container name="inventory filter tabs">
- <inventory_panel label="Alle Objekte" name="All Items" />
- <inventory_panel label="Letzte Objekte" name="Recent Items" />
- </tab_container>
- <menu_bar name="Inventory Menu">
- <menu label="Datei" name="File">
- <menu_item_call label="Öffnen" name="Open" />
- <menu_item_call label="Neues Fenster" name="New Window" />
- <menu_item_call label="Filter anzeigen" name="Show Filters" />
- <menu_item_call label="Filter zurücksetzen" name="Reset Current" />
- <menu_item_call label="Alle Ordner schließen" name="Close All Folders" />
- <menu_item_call label="Papierkorb ausleeren" name="Empty Trash" />
- </menu>
- <menu label="Erstellen" name="Create">
- <menu_item_call label="Neuer Ordner" name="New Folder" />
- <menu_item_call label="Neues Skript" name="New Script" />
- <menu_item_call label="Neue Notiz" name="New Note" />
- <menu_item_call label="Neue Geste" name="New Gesture" />
- <menu name="New Clothes">
- <menu_item_call label="Neues Hemd" name="New Shirt" />
- <menu_item_call label="Neue Hose" name="New Pants" />
- <menu_item_call label="Neue Schuhe" name="New Shoes" />
- <menu_item_call label="Neue Socken" name="New Socks" />
- <menu_item_call label="Neue Jacke" name="New Jacket" />
- <menu_item_call label="Neuer Rock" name="New Skirt" />
- <menu_item_call label="Neue Handschuhe" name="New Gloves" />
- <menu_item_call label="Neues Unterhemd" name="New Undershirt" />
- <menu_item_call label="Neue Unterhose" name="New Underpants" />
- </menu>
- <menu name="New Body Parts">
- <menu_item_call label="Neue Form/Gestalt" name="New Shape" />
- <menu_item_call label="Neue Haut" name="New Skin" />
- <menu_item_call label="Neues Haar" name="New Hair" />
- <menu_item_call label="Neue Augen" name="New Eyes" />
- </menu>
- </menu>
- <menu label="Sortieren" name="Sort">
- <menu_item_check label="Nach Name" name="By Name" />
- <menu_item_check label="Nach Datum" name="By Date" />
- <menu_item_check label="Ordner immer nach Name" name="Folders Always By Name" />
- <menu_item_check label="Systemordner nach oben" name="System Folders To Top" />
- </menu>
- </menu_bar>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Inventory" title="INVENTAR">
+ <floater.string name="Title">
+ Inventar
+ </floater.string>
+ <floater.string name="TitleFetching">
+ Inventar ([ITEM_COUNT] Artikel werden abgerufen...) [FILTER]
+ </floater.string>
+ <floater.string name="TitleCompleted">
+ Inventar ([ITEM_COUNT] Artikel) [FILTER]
+ </floater.string>
+ <floater.string name="Fetched">
+ Abgerufen
+ </floater.string>
+ <panel label="Inventar" name="Inventory Panel"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/de/floater_inventory_item_properties.xml
index 0028f1da13..e894f666c9 100644
--- a/indra/newview/skins/default/xui/de/floater_inventory_item_properties.xml
+++ b/indra/newview/skins/default/xui/de/floater_inventory_item_properties.xml
@@ -1,5 +1,20 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="item properties" title="Inventarobjekt-Eigenschaften">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="item properties" title="EIGENSCHAFTEN: INVENTAROBJEKT">
+ <floater.string name="unknown">
+ (unbekannt)
+ </floater.string>
+ <floater.string name="public">
+ (öffentlich)
+ </floater.string>
+ <floater.string name="you_can">
+ Sie können:
+ </floater.string>
+ <floater.string name="owner_can">
+ Eigentümer kann:
+ </floater.string>
+ <floater.string name="acquiredDate">
+ [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+ </floater.string>
<text name="LabelItemNameTitle">
Name:
</text>
@@ -12,14 +27,14 @@
<text name="LabelCreatorName">
Nicole Linden
</text>
- <button label="Profil..." label_selected="" name="BtnCreator" />
+ <button label="Profil..." label_selected="" name="BtnCreator"/>
<text name="LabelOwnerTitle">
Eigentümer:
</text>
<text name="LabelOwnerName">
Thrax Linden
</text>
- <button label="Profil..." label_selected="" name="BtnOwner" />
+ <button label="Profil..." label_selected="" name="BtnOwner"/>
<text name="LabelAcquiredTitle">
Erworben:
</text>
@@ -27,59 +42,32 @@
Mittwoch, 24. Mai 2006, 12:50:46
</text>
<text name="OwnerLabel">
- Sie können:
+ Sie:
</text>
- <check_box label="Bearbeiten" name="CheckOwnerModify" />
- <check_box label="Kopieren" name="CheckOwnerCopy" left_delta="85" />
- <check_box label="Verkaufen/Weggeben" name="CheckOwnerTransfer" />
- <text name="BaseMaskDebug">
- B:
+ <check_box label="Bearbeiten" name="CheckOwnerModify"/>
+ <check_box label="Kopieren" left_delta="85" name="CheckOwnerCopy"/>
+ <check_box label="Wiederverkaufen" name="CheckOwnerTransfer"/>
+ <text name="AnyoneLabel">
+ Jeder:
</text>
- <text name="OwnerMaskDebug">
- O:
+ <check_box label="Kopieren" name="CheckEveryoneCopy"/>
+ <text name="GroupLabel">
+ Gruppe:
</text>
- <text name="GroupMaskDebug">
- G:
- </text>
- <text name="EveryoneMaskDebug">
- E:
- </text>
- <text name="NextMaskDebug">
- N:
- </text>
- <check_box label="Mit Gruppe teilen" name="CheckShareWithGroup" />
- <check_box label="Kopieren allen erlauben" name="CheckEveryoneCopy" />
+ <check_box label="Teilen" name="CheckShareWithGroup"/>
<text name="NextOwnerLabel" width="150">
- Nächster Eigentümer kann:
- </text>
- <check_box label="Bearbeiten" name="CheckNextOwnerModify" />
- <check_box label="Kopieren" name="CheckNextOwnerCopy" left_delta="85" />
- <check_box label="Verkaufen/Weggeben" name="CheckNextOwnerTransfer" />
- <text name="SaleLabel">
- Objekt markieren:
- </text>
- <check_box label="Zum Verkauf" name="CheckPurchase" />
- <radio_group name="RadioSaleType" left_delta="85" width="245" >
- <radio_item name="radio">
- Original
- </radio_item>
- <radio_item name="radio2">
- Kopieren
- </radio_item>
- </radio_group>
- <text name="TextPrice">
- Preis: L$
- </text>
- <text name="unknown">
- (unbekannt)
- </text>
- <text name="public">
- (öffentlich)
- </text>
- <text name="you_can">
- Sie können:
- </text>
- <text name="owner_can">
- Eigentümer kann:
+ Nächster Eigentümer:
+ </text>
+ <check_box label="Bearbeiten" name="CheckNextOwnerModify"/>
+ <check_box label="Kopieren" left_delta="85" name="CheckNextOwnerCopy"/>
+ <check_box label="Wiederverkaufen" name="CheckNextOwnerTransfer"/>
+ <check_box label="Zum Verkauf" name="CheckPurchase"/>
+ <combo_box name="combobox sale copy">
+ <combo_box.item label="Kopieren" name="Copy"/>
+ <combo_box.item label="Original" name="Original"/>
+ </combo_box>
+ <spinner label="Preis:" name="Edit Cost"/>
+ <text name="CurrencySymbol">
+ L$
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/de/floater_inventory_view_finder.xml
index aa24231e33..9cc5b92daf 100644
--- a/indra/newview/skins/default/xui/de/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/de/floater_inventory_view_finder.xml
@@ -1,24 +1,24 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Inventory Finder" title="inventar_letzte_objekte">
- <check_box label="Animation" name="check_animation" />
- <check_box label="Visitenkarten" name="check_calling_card" />
- <check_box label="Kleidung" name="check_clothing" />
- <check_box label="Gesten" name="check_gesture" />
- <check_box label="Landmarken" name="check_landmark" />
- <check_box label="Notizkarten" name="check_notecard" />
- <check_box label="Objekte" name="check_object" />
- <check_box label="Skripts" name="check_script" />
- <check_box label="Sounds" name="check_sound" />
- <check_box label="Texturen" name="check_texture" />
- <check_box label="Fotos" name="check_snapshot" />
- <button label="Alle" label_selected="Alle" name="All" />
- <button label="Keine" label_selected="Keine" name="None" />
- <check_box label="Ordner immer anzeigen" name="check_show_empty" />
- <check_box label="Seit Abmeldung" name="check_since_logoff" />
- <text type="string" length="1" name="- OR -">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Inventory Finder" title="INVENTORY_RECENT_ITEMS">
+ <check_box label="Animation" name="check_animation"/>
+ <check_box label="Visitenkarten" name="check_calling_card"/>
+ <check_box label="Kleidung" name="check_clothing"/>
+ <check_box label="Gesten" name="check_gesture"/>
+ <check_box label="Landmarken" name="check_landmark"/>
+ <check_box label="Notizkarten" name="check_notecard"/>
+ <check_box label="Objekte" name="check_object"/>
+ <check_box label="Skripts" name="check_script"/>
+ <check_box label="Sounds" name="check_sound"/>
+ <check_box label="Texturen" name="check_texture"/>
+ <check_box label="Fotos" name="check_snapshot"/>
+ <button label="Alle" label_selected="Alle" name="All"/>
+ <button label="Keine" label_selected="Keine" name="None"/>
+ <check_box label="Ordner immer anzeigen" name="check_show_empty"/>
+ <check_box label="Seit Abmeldung" name="check_since_logoff"/>
+ <text name="- OR -">
- ODER -
</text>
- <spinner label="Stunden zuvor" label_width="80" name="spin_hours_ago" />
- <spinner label="Tage zuvor" name="spin_days_ago" />
- <button label="Schließen" label_selected="Schließen" name="Close" />
+ <spinner label="Stunden zuvor" label_width="80" name="spin_hours_ago"/>
+ <spinner label="Tage zuvor" name="spin_days_ago"/>
+ <button label="Schließen" label_selected="Schließen" name="Close"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_joystick.xml b/indra/newview/skins/default/xui/de/floater_joystick.xml
index 407556bf2c..2efc11df29 100644
--- a/indra/newview/skins/default/xui/de/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/de/floater_joystick.xml
@@ -1,8 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Joystick" title="Joystick-Konfiguration">
- <check_box name="enable_joystick" width="80">
- Joystick aktivieren:
- </check_box>
+<floater name="Joystick" title="JOYSTICK-KONFIGURATION">
+ <check_box label="Joystick aktivieren:" name="enable_joystick" width="80"/>
<text left="140" name="joystick_type" width="360"/>
<spinner label="X-Achse" name="JoystickAxis1"/>
<spinner label="Y-Achse" name="JoystickAxis2"/>
@@ -17,15 +15,9 @@
<text name="Control Modes:">
Steuermodi:
</text>
- <check_box name="JoystickAvatarEnabled">
- Avatar
- </check_box>
- <check_box name="JoystickBuildEnabled">
- Bauen
- </check_box>
- <check_box name="JoystickFlycamEnabled">
- Flycam
- </check_box>
+ <check_box label="Avatar" name="JoystickAvatarEnabled"/>
+ <check_box label="Bauen" name="JoystickBuildEnabled"/>
+ <check_box label="Flycam" name="JoystickFlycamEnabled"/>
<text name="XScale">
X-Skala
</text>
@@ -74,12 +66,14 @@
<button label="SpaceNavigator-Standards" name="SpaceNavigatorDefaults"/>
<button label="OK" label_selected="OK" name="ok_btn"/>
<button label="Abbrechen" label_selected="Abbrechen" name="cancel_btn"/>
- <string name="JoystickMonitor">
- Joystick-Monitor
- </string>
- <string name="Axis">
- Achse [NUM]
- </string>
+ <stat_view label="Joystick-Monitor" name="axis_view">
+ <stat_bar label="Achse 0" name="axis0"/>
+ <stat_bar label="Achse 1" name="axis1"/>
+ <stat_bar label="Achse 2" name="axis2"/>
+ <stat_bar label="Achse 3" name="axis3"/>
+ <stat_bar label="Achse 4" name="axis4"/>
+ <stat_bar label="Achse 5" name="axis5"/>
+ </stat_view>
<string name="NoDevice">
Kein Gerät erkannt
</string>
diff --git a/indra/newview/skins/default/xui/de/floater_lagmeter.xml b/indra/newview/skins/default/xui/de/floater_lagmeter.xml
index 4dd9fd6c76..45ff37c147 100644
--- a/indra/newview/skins/default/xui/de/floater_lagmeter.xml
+++ b/indra/newview/skins/default/xui/de/floater_lagmeter.xml
@@ -1,152 +1,151 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_lagmeter" title="Lag-Anzeige">
- <button name="client_lagmeter" tool_tip="Client-Lag-Status" />
- <text name="client">
- Client:
- </text>
- <text name="client_text">
- Normal
- </text>
- <button name="network_lagmeter" tool_tip="Netzwerk-Lag-Status" />
- <text name="network">
- Netzwerk:
- </text>
- <text name="network_text">
- Normal
- </text>
- <button name="server_lagmeter" tool_tip="Server-Lag-Status" />
- <text name="server">
- Server:
- </text>
- <text name="server_text">
- Normal
- </text>
- <button label="?" name="server_help" />
- <button label="&gt;&gt; " name="minimize" />
- <text name="max_title_msg">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_lagmeter" title="LAG METER">
+ <floater.string name="max_title_msg">
Lag-Anzeige
- </text>
- <text name="max_width_px">
+ </floater.string>
+ <floater.string name="max_width_px">
350
- </text>
- <text name="min_title_msg">
+ </floater.string>
+ <floater.string name="min_title_msg">
Lag
- </text>
- <text name="min_width_px">
+ </floater.string>
+ <floater.string name="min_width_px">
90
- </text>
- <text name="client_text_msg">
+ </floater.string>
+ <floater.string name="client_text_msg">
Client
- </text>
- <text name="client_frame_rate_critical_fps">
+ </floater.string>
+ <floater.string name="client_frame_rate_critical_fps">
10
- </text>
- <text name="client_frame_rate_warning_fps">
+ </floater.string>
+ <floater.string name="client_frame_rate_warning_fps">
15
- </text>
- <text name="client_frame_time_window_bg_msg">
+ </floater.string>
+ <floater.string name="client_frame_time_window_bg_msg">
Normal, Fenster im Hintergrund
- </text>
- <text name="client_frame_time_critical_msg">
+ </floater.string>
+ <floater.string name="client_frame_time_critical_msg">
Client-Frame-Rate unter [CLIENT_FRAME_RATE_CRITICAL]
- </text>
- <text name="client_frame_time_warning_msg">
+ </floater.string>
+ <floater.string name="client_frame_time_warning_msg">
Client-Frame-Rate zwischen [CLIENT_FRAME_RATE_CRITICAL] und [CLIENT_FRAME_RATE_WARNING]
- </text>
- <text name="client_frame_time_normal_msg">
+ </floater.string>
+ <floater.string name="client_frame_time_normal_msg">
Normal
- </text>
- <text name="client_draw_distance_cause_msg">
+ </floater.string>
+ <floater.string name="client_draw_distance_cause_msg">
Mögliche Ursache: Sichtweite zu groß
- </text>
- <text name="client_texture_loading_cause_msg">
+ </floater.string>
+ <floater.string name="client_texture_loading_cause_msg">
Mögliche Ursache: Bilder werden geladen
- </text>
- <text name="client_texture_memory_cause_msg">
+ </floater.string>
+ <floater.string name="client_texture_memory_cause_msg">
Mögliche Ursache: Zu viele Bilder im Speicher
- </text>
- <text name="client_complex_objects_cause_msg">
+ </floater.string>
+ <floater.string name="client_complex_objects_cause_msg">
Mögliche Ursache: Zu viele komplexe Objekte in der Szene
- </text>
- <text name="network_text_msg">
+ </floater.string>
+ <floater.string name="network_text_msg">
Netzwerk
- </text>
- <text name="network_packet_loss_critical_pct">
+ </floater.string>
+ <floater.string name="network_packet_loss_critical_pct">
10
- </text>
- <text name="network_packet_loss_warning_pct">
+ </floater.string>
+ <floater.string name="network_packet_loss_warning_pct">
5
- </text>
- <text name="network_packet_loss_critical_msg">
+ </floater.string>
+ <floater.string name="network_packet_loss_critical_msg">
Paketverlust der Verbindung übersteigt [NETWORK_PACKET_LOSS_CRITICAL]%
- </text>
- <text name="network_packet_loss_warning_msg">
+ </floater.string>
+ <floater.string name="network_packet_loss_warning_msg">
Paketverlust der Verbindung liegt bei [NETWORK_PACKET_LOSS_WARNING]%-[NETWORK_PACKET_LOSS_CRITICAL]%
- </text>
- <text name="network_performance_normal_msg">
+ </floater.string>
+ <floater.string name="network_performance_normal_msg">
Normal
- </text>
- <text name="network_ping_critical_ms">
+ </floater.string>
+ <floater.string name="network_ping_critical_ms">
600
- </text>
- <text name="network_ping_warning_ms">
+ </floater.string>
+ <floater.string name="network_ping_warning_ms">
300
- </text>
- <text name="network_ping_critical_msg">
+ </floater.string>
+ <floater.string name="network_ping_critical_msg">
Ping-Zeit der Verbindung übersteigt [NETWORK_PING_CRITICAL] ms
- </text>
- <text name="network_ping_warning_msg">
+ </floater.string>
+ <floater.string name="network_ping_warning_msg">
Ping-Zeit der Verbindung liegt bei [NETWORK_PING_WARNING]-[NETWORK_PING_CRITICAL] ms
- </text>
- <text name="network_packet_loss_cause_msg">
+ </floater.string>
+ <floater.string name="network_packet_loss_cause_msg">
Möglicherweise schlechte Verbindung oder zu hoher Wert für „Bandbreite“.
- </text>
- <text name="network_ping_cause_msg">
+ </floater.string>
+ <floater.string name="network_ping_cause_msg">
Möglicherweise schlechte Verbindung oder File-Sharing-Anwendung.
- </text>
- <text name="server_text_msg">
+ </floater.string>
+ <floater.string name="server_text_msg">
Server
- </text>
- <text name="server_frame_rate_critical_fps">
+ </floater.string>
+ <floater.string name="server_frame_rate_critical_fps">
20
- </text>
- <text name="server_frame_rate_warning_fps">
+ </floater.string>
+ <floater.string name="server_frame_rate_warning_fps">
30
- </text>
- <text name="server_single_process_max_time_ms">
+ </floater.string>
+ <floater.string name="server_single_process_max_time_ms">
20
- </text>
- <text name="server_frame_time_critical_msg">
+ </floater.string>
+ <floater.string name="server_frame_time_critical_msg">
Simulator-Frame-Rate liegt unter [SERVER_FRAME_RATE_CRITICAL]
- </text>
- <text name="server_frame_time_warning_msg">
+ </floater.string>
+ <floater.string name="server_frame_time_warning_msg">
Simulator-Frame-Rate liegt zwischen [SERVER_FRAME_RATE_CRITICAL] und [SERVER_FRAME_RATE_WARNING]
- </text>
- <text name="server_frame_time_normal_msg">
+ </floater.string>
+ <floater.string name="server_frame_time_normal_msg">
Normal
- </text>
- <text name="server_physics_cause_msg">
+ </floater.string>
+ <floater.string name="server_physics_cause_msg">
Mögliche Ursache: Zu viele physische Objekte
- </text>
- <text name="server_scripts_cause_msg">
+ </floater.string>
+ <floater.string name="server_scripts_cause_msg">
Mögliche Ursache: Zu viele geskriptete Objekte
- </text>
- <text name="server_net_cause_msg">
+ </floater.string>
+ <floater.string name="server_net_cause_msg">
Mögliche Ursache: Zu viel Netzwerktraffic
- </text>
- <text name="server_agent_cause_msg">
+ </floater.string>
+ <floater.string name="server_agent_cause_msg">
Mögliche Ursache: Zu viele Personen in Bewegung in der Region
- </text>
- <text name="server_images_cause_msg">
+ </floater.string>
+ <floater.string name="server_images_cause_msg">
Mögliche Ursache: Zu viele Bildberechnungen
- </text>
- <text name="server_generic_cause_msg">
+ </floater.string>
+ <floater.string name="server_generic_cause_msg">
Mögliche Ursache: Zu hohe Simulator-Last
+ </floater.string>
+ <floater.string name="smaller_label">
+ &gt;&gt;
+ </floater.string>
+ <floater.string name="bigger_label">
+ &lt;&lt;
+ </floater.string>
+ <button name="client_lagmeter" tool_tip="Client-Lag-Status"/>
+ <text name="client">
+ Client
</text>
- <text name="smaller_label">
- &gt;&gt; 
+ <text name="client_text">
+ Normal
+ </text>
+ <button name="network_lagmeter" tool_tip="Netzwerk-Lag-Status"/>
+ <text name="network">
+ Netzwerk
</text>
- <text name="bigger_label">
- &lt;&lt; 
+ <text name="network_text">
+ Normal
+ </text>
+ <button name="server_lagmeter" tool_tip="Server-Lag-Status"/>
+ <text name="server">
+ Server
+ </text>
+ <text name="server_text">
+ Normal
</text>
+ <button label="&gt;&gt; " name="minimize" tool_tip="Fenstergröße ändern"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_land_holdings.xml b/indra/newview/skins/default/xui/de/floater_land_holdings.xml
index 6854903382..73559407a9 100644
--- a/indra/newview/skins/default/xui/de/floater_land_holdings.xml
+++ b/indra/newview/skins/default/xui/de/floater_land_holdings.xml
@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="land holdings floater" title="Mein Land">
+<floater name="land holdings floater" title="MEIN LAND">
<scroll_list name="parcel list">
- <column label="Parzellenname" name="name"/>
+ <column label="Parzelle" name="name"/>
<column label="Region" name="location"/>
<column label="Typ" name="type"/>
<column label="Gebiet" name="area"/>
<column label="" name="hidden"/>
</scroll_list>
<button label="Teleportieren" label_selected="Teleportieren" name="Teleport" tool_tip="Zum Mittelpunkt dieses Landes teleportieren."/>
- <button label="Auf Karte" label_selected="Auf Karte" name="Show on Map" tool_tip="Dieses Land auf der Weltkarte anzeigen."/>
+ <button label="Karte" label_selected="Karte" name="Show on Map" tool_tip="Dieses Land auf der Weltkarte anzeigen."/>
<text name="contrib_label">
Beiträge zu Ihren Gruppen:
</text>
@@ -20,21 +20,21 @@
Zulässiger Landbesitz bei aktuellem Zahlungsplan:
</text>
<text name="allowed_text">
- [AREA] qm
+ [AREA] m².
</text>
<text name="current_label">
Aktueller Landbesitz:
</text>
<text name="current_text">
- [AREA] qm
+ [AREA] m².
</text>
<text name="available_label">
Für Landkäufe verfügbar:
</text>
<text name="available_text">
- [AREA] qm
+ [AREA] m².
</text>
<string name="area_string">
- [AREA] qm
+ [AREA] m².
</string>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/de/floater_live_lsleditor.xml
index 8d499bc300..248460af82 100644
--- a/indra/newview/skins/default/xui/de/floater_live_lsleditor.xml
+++ b/indra/newview/skins/default/xui/de/floater_live_lsleditor.xml
@@ -1,12 +1,15 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script ed float" title="Skript: Neues Skript">
- <button label="Zurücksetzen" label_selected="Zurücksetzen" name="Reset" />
- <check_box label="Läuft" name="running" />
- <check_box label="Mono" name="mono" />
- <text name="not_allowed">
- Sie können dieses Skript nicht anzeigen.
- </text>
- <string name="script_running">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="script ed float" title="SKRIPT: NEUES SKRIPT">
+ <floater.string name="not_allowed">
+ Dieses Skript kann nicht angezeigt oder bearbeitet werden, da als Berechtigung „kein kopieren&quot; festgelegt wurde. Um ein Skript innerhalb eines Objektes anzuzeigen oder zu bearbeiten, benötigen Sie die vollständige Berechtigung.
+ </floater.string>
+ <floater.string name="script_running">
Läuft
- </string>
+ </floater.string>
+ <floater.string name="Title">
+ Skript: [NAME]
+ </floater.string>
+ <button label="Zurücksetzen" label_selected="Zurücksetzen" name="Reset"/>
+ <check_box initial_value="true" label="Läuft" name="running"/>
+ <check_box initial_value="true" label="Mono" name="mono"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_lsl_guide.xml b/indra/newview/skins/default/xui/de/floater_lsl_guide.xml
index d7f56b302d..5e90076487 100644
--- a/indra/newview/skins/default/xui/de/floater_lsl_guide.xml
+++ b/indra/newview/skins/default/xui/de/floater_lsl_guide.xml
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script ed float" title="LSL-Wiki">
- <check_box label="Cursor folgen" name="lock_check" />
- <combo_box label="Sperren" name="history_combo" />
- <button label="Zurück" name="back_btn" />
- <button label="Weiter" name="fwd_btn" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="script ed float" title="LSL-WIKI">
+ <check_box label="Cursor folgen" name="lock_check"/>
+ <combo_box label="Sperren" name="history_combo"/>
+ <button label="Zurück" name="back_btn"/>
+ <button label="Weiter" name="fwd_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_map.xml b/indra/newview/skins/default/xui/de/floater_map.xml
new file mode 100644
index 0000000000..b985d1d187
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_map.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Map">
+ <floater.string name="mini_map_north">
+ N
+ </floater.string>
+ <floater.string name="mini_map_east">
+ O
+ </floater.string>
+ <floater.string name="mini_map_west">
+ W
+ </floater.string>
+ <floater.string name="mini_map_south">
+ S
+ </floater.string>
+ <floater.string name="mini_map_southeast">
+ SO
+ </floater.string>
+ <floater.string name="mini_map_northeast">
+ NO
+ </floater.string>
+ <floater.string name="mini_map_southwest">
+ SW
+ </floater.string>
+ <floater.string name="mini_map_northwest">
+ NW
+ </floater.string>
+ <floater.string name="ToolTipMsg">
+ [AGENT][REGION](Karte mit Doppelklick öffnen)
+ </floater.string>
+ <text label="N" name="floater_map_north" text="N">
+ N
+ </text>
+ <text label="O" name="floater_map_east" text="O">
+ O
+ </text>
+ <text label="W" name="floater_map_west" text="W">
+ W
+ </text>
+ <text label="S" name="floater_map_south" text="S">
+ S
+ </text>
+ <text label="SO" name="floater_map_southeast" text="SO">
+ SO
+ </text>
+ <text label="NO" name="floater_map_northeast" text="NO">
+ NO
+ </text>
+ <text label="SW" name="floater_map_southwest" text="SW">
+ SW
+ </text>
+ <text label="NW" name="floater_map_northwest" text="NW">
+ NW
+ </text>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_media_browser.xml b/indra/newview/skins/default/xui/de/floater_media_browser.xml
index ee2532127e..62a047b8fe 100644
--- a/indra/newview/skins/default/xui/de/floater_media_browser.xml
+++ b/indra/newview/skins/default/xui/de/floater_media_browser.xml
@@ -1,19 +1,30 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_about" title="Medienbrowser">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_about" title="MEDIEN-BROWSER">
+ <floater.string name="home_page_url">
+ http://de.secondlife.com
+ </floater.string>
+ <floater.string name="support_page_url">
+ http://de.secondlife.com/support
+ </floater.string>
<layout_stack name="stack1">
<layout_panel name="nav_controls">
- <button label="Zurück" name="back" />
- <button label="Weiter" name="forward" />
- <button label="Neu laden" name="reload" />
- <button label="Los" name="go" />
+ <button label="Zurück" name="back"/>
+ <button label="Weiter" name="forward"/>
+ <button label="Neu laden" name="reload"/>
+ <button label="Los" name="go"/>
+ </layout_panel>
+ <layout_panel name="time_controls">
+ <button label="zurückspulen" name="rewind"/>
+ <button label="anhalten" name="stop"/>
+ <button label="vorwärts" name="seek"/>
</layout_panel>
<layout_panel name="parcel_owner_controls">
- <button label="Aktuelle URL an Parzelle senden" name="assign" />
+ <button label="Aktuelle URL an Parzelle senden" name="assign"/>
</layout_panel>
<layout_panel name="external_controls">
- <button label="In meinem Browser öffnen" name="open_browser" />
- <check_box label="Immer in meinem Browser öffnen" name="open_always" />
- <button label="Schließen" name="close" />
+ <button label="In meinem Browser öffnen" name="open_browser"/>
+ <check_box label="Immer in meinem Browser öffnen" name="open_always"/>
+ <button label="Schließen" name="close"/>
</layout_panel>
</layout_stack>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_media_settings.xml b/indra/newview/skins/default/xui/de/floater_media_settings.xml
new file mode 100644
index 0000000000..1b98ed7973
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_media_settings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="media_settings" title="MEDIEN-EINSTELLUNGEN">
+ <button label="OK" label_selected="OK" name="OK"/>
+ <button label="Abbrechen" label_selected="Abbrechen" name="Cancel"/>
+ <button label="Ãœbernehmen" label_selected="Ãœbernehmen" name="Apply"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_mem_leaking.xml b/indra/newview/skins/default/xui/de/floater_mem_leaking.xml
index 0b77a7fe9d..b730146aa6 100644
--- a/indra/newview/skins/default/xui/de/floater_mem_leaking.xml
+++ b/indra/newview/skins/default/xui/de/floater_mem_leaking.xml
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="MemLeak" title="Speicherverlust-Simulation">
- <spinner label="Verlustgeschwindigkeit (Bytes pro Frame):" name="leak_speed" />
- <spinner label="Max. Speicherverlust (MB):" name="max_leak" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="MemLeak" title="SPEICHERVERLUST SIMULIEREN">
+ <spinner label="Verlustgeschwindigkeit (Bytes pro Frame):" name="leak_speed"/>
+ <spinner label="Max. Speicherverlust (MB):" name="max_leak"/>
<text name="total_leaked_label">
Aktueller Speicherverlust:[SIZE] KB
</text>
@@ -11,8 +11,8 @@
<text name="note_label_2">
[NOTE2]
</text>
- <button label="Start" name="start_btn" />
- <button label="Stopp" name="stop_btn" />
- <button label="Freigeben" name="release_btn" />
- <button label="Schließen" name="close_btn" />
+ <button label="Start" name="start_btn"/>
+ <button label="Stopp" name="stop_btn"/>
+ <button label="Freigeben" name="release_btn"/>
+ <button label="Schließen" name="close_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_moveview.xml b/indra/newview/skins/default/xui/de/floater_moveview.xml
index 01431ee51a..03930c8ed6 100644
--- a/indra/newview/skins/default/xui/de/floater_moveview.xml
+++ b/indra/newview/skins/default/xui/de/floater_moveview.xml
@@ -1,14 +1,35 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="move floater" title="">
- <button label="" label_selected="" name="turn left btn" tool_tip="Nach links" />
- <button label="" label_selected="" name="turn right btn" tool_tip="Nach rechts" />
- <button label="" label_selected="" name="move up btn"
- tool_tip="Springen oder Steigflug" />
- <button label="" label_selected="" name="move down btn" tool_tip="Ducken oder Sinkflug" />
- <button label="Fliegen" label_selected="Fliegen" name="fly btn"
- tool_tip="Fliegen/Landen" />
- <joystick_slide name="slide left btn" tool_tip="Nach links" />
- <joystick_slide name="slide right btn" tool_tip="Nach rechts" />
- <joystick_turn name="forward btn" tool_tip="Nach vorn" />
- <joystick_turn name="backward btn" tool_tip="Nach hinten" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="move_floater">
+ <string name="walk_forward_tooltip">
+ Vorwärts gehen (Nach-oben-Pfeil oder W drücken)
+ </string>
+ <string name="walk_back_tooltip">
+ Rückwärts gehen (Nach-Unten-Pfeil oder S drücken)
+ </string>
+ <string name="run_forward_tooltip">
+ Vorwärts rennen (Nach-oben-Pfeil oder W drücken)
+ </string>
+ <string name="run_back_tooltip">
+ Rückwärts rennen (Nach-Unten-Pfeil oder S drücken)
+ </string>
+ <string name="fly_forward_tooltip">
+ Vorwärts fliegen (Nach-oben-Pfeil oder W drücken)
+ </string>
+ <string name="fly_back_tooltip">
+ Rückwärts fliegen (Nach-Unten-Pfeil oder S drücken)
+ </string>
+ <panel name="panel_actions">
+ <button label="" label_selected="" name="turn left btn" tool_tip="Nach links (Links-Pfeil oder A drücken)"/>
+ <button label="" label_selected="" name="turn right btn" tool_tip="Nach rechts (Rechts-Pfeil oder D drücken)"/>
+ <button label="" label_selected="" name="move up btn" tool_tip="Nach oben fliegen, „E&quot; drücken"/>
+ <button label="" label_selected="" name="move down btn" tool_tip="Nach unten fliegen, „C&quot; drücken"/>
+ <joystick_turn name="forward btn" tool_tip="Vorwärts gehen (Nach-oben-Pfeil oder W drücken)"/>
+ <joystick_turn name="backward btn" tool_tip="Rückwärts gehen (Nach-Unten-Pfeil oder S drücken)"/>
+ </panel>
+ <panel name="panel_modes">
+ <button label="" name="mode_walk_btn" tool_tip="Gehen"/>
+ <button label="" name="mode_run_btn" tool_tip="Rennen"/>
+ <button label="" name="mode_fly_btn" tool_tip="Fliegen"/>
+ <button label="Landen" name="stop_fly_btn" tool_tip="Landen"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_mute_object.xml b/indra/newview/skins/default/xui/de/floater_mute_object.xml
index 02eafbcb68..3f1af3dc63 100644
--- a/indra/newview/skins/default/xui/de/floater_mute_object.xml
+++ b/indra/newview/skins/default/xui/de/floater_mute_object.xml
@@ -1,12 +1,14 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="mute by name" title="Objekt nach Name stummschalten">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="mute by name" title="OBJEKT NACH NAMEN IGNORIEREN">
<text name="message">
- Stummschalten nach Name betrifft nur Chat und IM, keine Sounds.
-Sie müssen den Objektnamen exakt angeben.
+ Objekt ignorieren:
</text>
<line_editor name="object_name">
Objektname
</line_editor>
- <button label="OK" name="OK" />
- <button label="Abbrechen" name="Cancel" />
+ <text name="note">
+ * Ignoriert nur Objekttext, nicht die Geräusche
+ </text>
+ <button label="OK" name="OK"/>
+ <button label="Abbrechen" name="Cancel"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_my_friends.xml b/indra/newview/skins/default/xui/de/floater_my_friends.xml
index fc24bcece4..61cb0d5c14 100644
--- a/indra/newview/skins/default/xui/de/floater_my_friends.xml
+++ b/indra/newview/skins/default/xui/de/floater_my_friends.xml
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_my_friends" title="Kontakte">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_my_friends" title="KONTAKTE">
<tab_container name="friends_and_groups">
- <panel label="Freunde" name="friends_panel" />
- <panel label="Gruppen" name="groups_panel" />
+ <panel label="Freunde" name="friends_panel"/>
+ <panel label="Gruppen" name="groups_panel"/>
</tab_container>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_nearby_chat.xml b/indra/newview/skins/default/xui/de/floater_nearby_chat.xml
new file mode 100644
index 0000000000..e362273396
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_nearby_chat.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="nearby_chat" title="CHAT IN DER NÄHE"/>
diff --git a/indra/newview/skins/default/xui/de/floater_notification.xml b/indra/newview/skins/default/xui/de/floater_notification.xml
index 48ff900d5a..c0806ef50c 100644
--- a/indra/newview/skins/default/xui/de/floater_notification.xml
+++ b/indra/newview/skins/default/xui/de/floater_notification.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="notification" title="Konsole: Meldungen">
+<floater name="notification" title="BENACHRICHTIGUNGEN">
<text_editor name="payload">
Wird geladen...
</text_editor>
diff --git a/indra/newview/skins/default/xui/de/floater_notifications_console.xml b/indra/newview/skins/default/xui/de/floater_notifications_console.xml
index a1cd69899c..e271cdace2 100644
--- a/indra/newview/skins/default/xui/de/floater_notifications_console.xml
+++ b/indra/newview/skins/default/xui/de/floater_notifications_console.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="notifications_console" title="Konsole: Meldungen">
- <combo_box label="Meldungsart auswählen" name="notification_types" width="412" />
- <button label="Hinzufügen" name="add_notification" left="417" width="78" />
+<floater name="notifications_console" title="BENACHRICHTIGUNGEN">
+ <combo_box label="Meldungsart auswählen" name="notification_types" width="412"/>
+ <button label="Hinzufügen" left="417" name="add_notification" width="78"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_openobject.xml b/indra/newview/skins/default/xui/de/floater_openobject.xml
index 0b5a36578e..f0b6aa498b 100644
--- a/indra/newview/skins/default/xui/de/floater_openobject.xml
+++ b/indra/newview/skins/default/xui/de/floater_openobject.xml
@@ -1,10 +1,8 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="objectcontents" title="Objektinhalte">
- <text type="string" length="1" name="object_name">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="objectcontents" title="INHALT DES OBJEKTS">
+ <text name="object_name">
[DESC]:
</text>
- <button label="In Inventar kopieren" label_selected="In Inventar kopieren"
- name="copy_to_inventory_button" width="132" />
- <button label="Kopieren und anziehen" label_selected="Kopieren und anziehen"
- name="copy_and_wear_button" width="132" left="150" />
+ <button label="In Inventar kopieren" label_selected="In Inventar kopieren" name="copy_to_inventory_button" width="132"/>
+ <button label="Kopieren und anziehen" label_selected="Kopieren und anziehen" left="150" name="copy_and_wear_button" width="132"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_outgoing_call.xml b/indra/newview/skins/default/xui/de/floater_outgoing_call.xml
new file mode 100644
index 0000000000..65f2fe10e2
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_outgoing_call.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="outgoing call" title="ANRUF">
+ <floater.string name="localchat">
+ Voice-Chat in der Nähe
+ </floater.string>
+ <floater.string name="anonymous">
+ Anonym
+ </floater.string>
+ <floater.string name="VoiceInviteP2P">
+ ruft an.
+ </floater.string>
+ <floater.string name="VoiceInviteAdHoc">
+ ist einem Voice-Konferenz-Chat beigetreten.
+ </floater.string>
+ <text name="connecting">
+ Verbindung mit [CALLEE_NAME] wird hergestellt.
+ </text>
+ <text name="calling">
+ [CALLEE_NAME] wird angerufen
+ </text>
+ <text name="noanswer">
+ Der Anruf wurde nicht entgegengenommen. Bitte versuchen Sie es später erneut.
+ </text>
+ <text name="leaving">
+ [CURRENT_CHAT] wird verlassen.
+ </text>
+ <button label="Abbrechen" label_selected="Abbrechen" name="Cancel"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_pay.xml b/indra/newview/skins/default/xui/de/floater_pay.xml
index 5d0dbffc22..6eb1d9472d 100644
--- a/indra/newview/skins/default/xui/de/floater_pay.xml
+++ b/indra/newview/skins/default/xui/de/floater_pay.xml
@@ -1,21 +1,25 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Give Money" title="">
- <button label="1 L$" label_selected="1 L$" name="fastpay 1" />
- <button label="5 L$" label_selected="5 L$" name="fastpay 5" />
- <button label="10 L$" label_selected="10 L$" name="fastpay 10" />
- <button label="20 L$" label_selected="20 L$" name="fastpay 20" />
- <button label="Zahlen" label_selected="Zahlen" name="pay btn" />
- <button label="Abbrechen" label_selected="Abbrechen" name="cancel btn" />
- <text type="string" length="1" name="payee_label" width="130">
- Einwohner bezahlen:
+ <string name="payee_group">
+ Gruppe bezahlen
+ </string>
+ <string name="payee_resident">
+ Einwohner bezahlen
+ </string>
+ <text name="payee_label" width="130">
+ Zahlen:
</text>
- <text type="string" length="1" name="payee_name" left="130">
+ <icon name="icon_person" tool_tip="Person"/>
+ <text left="130" name="payee_name">
[FIRST] [LAST]
</text>
- <text type="string" length="1" name="fastpay text">
- Schnellzahlung:
- </text>
- <text type="string" length="1" name="amount text">
- Betrag:
+ <button label="1 L$" label_selected="1 L$" name="fastpay 1"/>
+ <button label="5 L$" label_selected="5 L$" name="fastpay 5"/>
+ <button label="10 L$" label_selected="10 L$" name="fastpay 10"/>
+ <button label="20 L$" label_selected="20 L$" name="fastpay 20"/>
+ <text name="amount text">
+ Oder Betrag auswählen:
</text>
+ <button label="Zahlen" label_selected="Zahlen" name="pay btn"/>
+ <button label="Abbrechen" label_selected="Abbrechen" name="cancel btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_pay_object.xml b/indra/newview/skins/default/xui/de/floater_pay_object.xml
index eaf95a9e9e..92f5ea415e 100644
--- a/indra/newview/skins/default/xui/de/floater_pay_object.xml
+++ b/indra/newview/skins/default/xui/de/floater_pay_object.xml
@@ -1,30 +1,29 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Give Money" title="">
- <text type="string" length="1" name="payee_group" width="105">
- Gruppe bezahlen:
- </text>
- <text type="string" length="1" name="payee_resident" width="118">
- Einwohner bezahlen:
- </text>
- <text type="string" length="1" name="payee_name" left="128" width="168">
+ <string name="payee_group" width="105">
+ Gruppe bezahlen
+ </string>
+ <string name="payee_resident" width="118">
+ Einwohner bezahlen
+ </string>
+ <icon name="icon_person" tool_tip="Person"/>
+ <text left="128" name="payee_name" width="168">
[FIRST] [LAST]
</text>
- <text type="string" length="1" name="object_name_label" halign="left">
+ <text halign="left" name="object_name_label">
Ãœber Objekt:
</text>
- <text type="string" length="1" name="object_name_text" left="105">
+ <icon name="icon_object" tool_tip="Objekte"/>
+ <text left="105" name="object_name_text">
...
</text>
- <text type="string" length="1" name="fastpay text" width="95" halign="left">
- Schnellzahlung:
- </text>
- <text type="string" length="1" name="amount text">
- Betrag:
+ <button label="1 L$" label_selected="1 L$" left="105" name="fastpay 1"/>
+ <button label="5 L$" label_selected="5 L$" left="190" name="fastpay 5"/>
+ <button label="10 L$" label_selected="10 L$" left="105" name="fastpay 10"/>
+ <button label="20 L$" label_selected="20 L$" left="190" name="fastpay 20"/>
+ <text name="amount text">
+ Oder Betrag auswählen:
</text>
- <button label="1 L$" label_selected="1 L$" name="fastpay 1" left="105" />
- <button label="5 L$" label_selected="5 L$" name="fastpay 5" left="190" />
- <button label="10 L$" label_selected="10 L$" name="fastpay 10" left="105" />
- <button label="20 L$" label_selected="20 L$" name="fastpay 20" left="190" />
- <button label="Zahlen" label_selected="Zahlen" name="pay btn" />
- <button label="Abbrechen" label_selected="Abbrechen" name="cancel btn" width="76" />
+ <button label="Zahlen" label_selected="Zahlen" name="pay btn"/>
+ <button label="Abbrechen" label_selected="Abbrechen" name="cancel btn" width="76"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_perm_prefs.xml b/indra/newview/skins/default/xui/de/floater_perm_prefs.xml
index 83ec725487..fd65987aa9 100644
--- a/indra/newview/skins/default/xui/de/floater_perm_prefs.xml
+++ b/indra/newview/skins/default/xui/de/floater_perm_prefs.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="perm prefs" title="Hochlade-Berechtigungen (Standard)">
+<floater name="perm prefs" title="STANDARD-BERECHTIGUNGEN FÃœR HOCHLADEN">
<panel label="Berechtigungen" name="permissions">
<button label="?" label_selected="?" name="help"/>
<check_box label="Mit Gruppe teilen" name="share_with_group"/>
@@ -9,7 +9,7 @@
</text>
<check_box label="Bearbeiten" name="next_owner_modify"/>
<check_box label="Kopieren" name="next_owner_copy"/>
- <check_box label="Verkaufen/Weggeben" name="next_owner_transfer" left_delta="80"/>
+ <check_box label="Verkaufen/Weggeben" left_delta="80" name="next_owner_transfer"/>
</panel>
<button label="OK" label_selected="OK" name="ok"/>
<button label="Abbrechen" label_selected="Abbrechen" name="cancel"/>
diff --git a/indra/newview/skins/default/xui/de/floater_post_process.xml b/indra/newview/skins/default/xui/de/floater_post_process.xml
index e10806d255..a6ed8cc3df 100644
--- a/indra/newview/skins/default/xui/de/floater_post_process.xml
+++ b/indra/newview/skins/default/xui/de/floater_post_process.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Post-Process Floater" title="Post-Processing-Einstellungen">
+<floater name="Post-Process Floater" title="POST-PROCESSING-EINSTELLUNGEN">
<tab_container name="Post-Process Tabs">
<panel label="Farbfilter" name="wmiColorFilterPanel">
<check_box label="Ein" name="wmiColorFilterToggle" />
diff --git a/indra/newview/skins/default/xui/de/floater_postcard.xml b/indra/newview/skins/default/xui/de/floater_postcard.xml
index 639a8ffdd1..37a0a0ad1d 100644
--- a/indra/newview/skins/default/xui/de/floater_postcard.xml
+++ b/indra/newview/skins/default/xui/de/floater_postcard.xml
@@ -1,39 +1,37 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Postcard" title="Foto per E-Mail senden">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Postcard" title="FOTO EMAILEN">
<text name="to_label">
E-Mail des Empfängers:
</text>
- <line_editor left="145" name="to_form" width="125" />
+ <line_editor left="145" name="to_form" width="125"/>
<text name="from_label">
Ihre E-Mail:
</text>
- <line_editor left="145" name="from_form" width="125" />
+ <line_editor left="145" name="from_form" width="125"/>
<text name="name_label">
Ihr Name:
</text>
- <line_editor left="145" name="name_form" width="125" />
+ <line_editor left="145" name="name_form" width="125"/>
<text name="subject_label">
Betreff:
</text>
- <line_editor label="Betreff hier eingeben." left="145" name="subject_form" width="125" />
+ <line_editor label="Betreff hier eingeben." left="145" name="subject_form" width="125"/>
<text name="msg_label">
Nachricht:
</text>
<text_editor name="msg_form">
Nachricht hier eingeben.
</text_editor>
- <check_box label="Im Web veröffentlichen" name="allow_publish_check"
- tool_tip="Veröffentlicht diese Postkarte im Web." />
- <check_box label="Ab-18-Inhalt" name="mature_check"
- tool_tip="Diese Postkarte enthält nicht jugendfreie Inhalte." />
- <button label="?" name="publish_help_btn" />
+ <check_box label="Im Web veröffentlichen" name="allow_publish_check" tool_tip="Veröffentlicht diese Postkarte im Web."/>
+ <check_box label="Ab-18-Inhalt" name="mature_check" tool_tip="Diese Postkarte enthält nicht jugendfreie Inhalte."/>
+ <button label="?" name="publish_help_btn"/>
<text name="fine_print">
Wenn sich der Empfänger bei SL anmeldet, erhalten Sie einen Empfehlungsbonus.
</text>
- <button label="Abbrechen" name="cancel_btn" />
- <button label="Senden" name="send_btn" />
+ <button label="Abbrechen" name="cancel_btn"/>
+ <button label="Senden" name="send_btn"/>
<text name="default_subject">
- Postkarte aus Second Life.
+ Postkarte aus [SECOND_LIFE].
</text>
<text name="default_message">
Sehen Sie hier!
diff --git a/indra/newview/skins/default/xui/de/floater_preferences.xml b/indra/newview/skins/default/xui/de/floater_preferences.xml
index 5f68282b9f..106fd6dfd3 100644
--- a/indra/newview/skins/default/xui/de/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/de/floater_preferences.xml
@@ -1,8 +1,15 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Preferences" title="Einstellungen">
- <button label="OK" label_selected="OK" name="OK" />
- <button label="Abbrechen" label_selected="Abbrechen" name="Cancel" />
- <button label="Ãœbernehmen" label_selected="Ãœbernehmen" name="Apply" />
- <button label="Info" label_selected="Info" name="About..." />
- <button label="Hilfe" label_selected="Hilfe" name="Help" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Preferences" title="EINSTELLUNGEN">
+ <button label="OK" label_selected="OK" name="OK"/>
+ <button label="Abbrechen" label_selected="Abbrechen" name="Cancel"/>
+ <tab_container name="pref core">
+ <panel label="Allgemein" name="general"/>
+ <panel label="Grafik" name="display"/>
+ <panel label="Privatsphäre" name="im"/>
+ <panel label="Sound" name="audio"/>
+ <panel label="Chat" name="chat"/>
+ <panel label="Benachrichtigungen" name="msgs"/>
+ <panel label="Setup" name="input"/>
+ <panel label="Erweitert" name="advanced1"/>
+ </tab_container>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_preview_animation.xml b/indra/newview/skins/default/xui/de/floater_preview_animation.xml
index c807556a9b..e98faeb1f4 100644
--- a/indra/newview/skins/default/xui/de/floater_preview_animation.xml
+++ b/indra/newview/skins/default/xui/de/floater_preview_animation.xml
@@ -1,11 +1,12 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="preview_anim">
- <text type="string" length="1" name="desc txt">
+ <floater.string name="Title">
+ Animation: [NAME]
+ </floater.string>
+ <text name="desc txt">
Beschreibung:
</text>
-<line_editor left="98" name="desc" width="189" />
- <button label="In Welt abspielen" label_selected="Stopp" name="Anim play btn"
- tool_tip="Gibt diese Animation so wieder, dass andere sie sehen können." width="116" />
- <button label="Lokal wiedergeben" label_selected="Stopp" name="Anim audition btn"
- tool_tip="Gibt diese Animation so wieder, dass nur Sie sie sehen." left="171" width="116" />
+ <line_editor left="98" name="desc" width="189"/>
+ <button label="In Welt abspielen" label_selected="Stopp" name="Anim play btn" tool_tip="Diese Animation so wiedergeben, dass andere sie sehen können." width="116"/>
+ <button label="Lokal wiedergeben" label_selected="Stopp" left="171" name="Anim audition btn" tool_tip="Diese Animation so wiedergeben, dass nur Sie sie sehen." width="116"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_preview_classified.xml b/indra/newview/skins/default/xui/de/floater_preview_classified.xml
index 2257785fda..401758769d 100644
--- a/indra/newview/skins/default/xui/de/floater_preview_classified.xml
+++ b/indra/newview/skins/default/xui/de/floater_preview_classified.xml
@@ -1,2 +1,6 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="classified_preview" title="Vertrauliche Informationen" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="classified_preview" title="INFORMATIONEN ÃœBER ANZEIGE">
+ <floater.string name="Title">
+ Anzeige: [NAME]
+ </floater.string>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_preview_event.xml b/indra/newview/skins/default/xui/de/floater_preview_event.xml
index 75e1113eff..7e46bbab54 100644
--- a/indra/newview/skins/default/xui/de/floater_preview_event.xml
+++ b/indra/newview/skins/default/xui/de/floater_preview_event.xml
@@ -1,2 +1,6 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="event_preview" title="Event-Informationen" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="event_preview" title="EVENT-INFORMATION">
+ <floater.string name="Title">
+ Veranstaltung: [NAME]
+ </floater.string>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_preview_gesture.xml b/indra/newview/skins/default/xui/de/floater_preview_gesture.xml
index 327d0b70f1..16e2fc18cb 100644
--- a/indra/newview/skins/default/xui/de/floater_preview_gesture.xml
+++ b/indra/newview/skins/default/xui/de/floater_preview_gesture.xml
@@ -1,14 +1,29 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="gesture_preview">
- <string name="stop_txt">
+ <floater.string name="step_anim">
+ Animation abspielen:
+ </floater.string>
+ <floater.string name="step_sound">
+ Sound abspielen:
+ </floater.string>
+ <floater.string name="step_chat">
+ Chat sprechen:
+ </floater.string>
+ <floater.string name="step_wait">
+ Warten:
+ </floater.string>
+ <floater.string name="stop_txt">
Stopp
- </string>
- <string name="preview_txt">
+ </floater.string>
+ <floater.string name="preview_txt">
Vorschau
- </string>
- <string name="none_text">
+ </floater.string>
+ <floater.string name="none_text">
– Keine –
- </string>
+ </floater.string>
+ <floater.string name="Title">
+ Gesten: [NAME]
+ </floater.string>
<text name="desc_label">
Beschreibung:
</text>
@@ -27,34 +42,23 @@
<text name="library_label">
Bibliothek:
</text>
+ <scroll_list name="library_list"/>
+ <button label="Hinzufügen &gt;&gt;" name="add_btn"/>
<text name="steps_label">
Schritte:
</text>
- <scroll_list name="library_list">
- Animation
-Ton
-Chat
-Warten
- </scroll_list>
- <button label="Hinzufügen &gt;&gt;" name="add_btn"/>
<button label="Nach oben" name="up_btn"/>
<button label="Nach unten" name="down_btn"/>
<button label="Entfernen" name="delete_btn"/>
- <text name="help_label">
- Alle Schritte erfolgen zur selben
-Zeit, außer Sie fügen Warteschritte
-ein.
- </text>
<radio_group name="animation_trigger_type">
- <radio_item name="start">
- Start
- </radio_item>
- <radio_item name="stop">
- Stopp
- </radio_item>
+ <radio_item label="Start" name="start"/>
+ <radio_item label="Stopp" name="stop"/>
</radio_group>
<check_box label="bis alle Animationen beendet sind" name="wait_anim_check"/>
<check_box label="Zeit in Sekunden" name="wait_time_check"/>
+ <text name="help_label">
+ Alle Schritte werden gleichzeitig ausgeführt, wenn keine Pausen hinzugefügt wurden.
+ </text>
<check_box label="Aktiv" name="active_check" tool_tip="Aktive Gesten werden durch Chat-Eingabe ihrer Auslösephrasen oder Drücken von Tastenkürzeln ausgelöst. Bei doppelten Tastenzuweisungen funktionieren Gesten in der Regel nicht."/>
<button label="Vorschau" name="preview_btn"/>
<button label="Speichern" name="save_btn"/>
diff --git a/indra/newview/skins/default/xui/de/floater_preview_gesture_info.xml b/indra/newview/skins/default/xui/de/floater_preview_gesture_info.xml
new file mode 100644
index 0000000000..0d0d28f96f
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_preview_gesture_info.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Gesture" title="GESTE - SCHNELLTASTE"/>
diff --git a/indra/newview/skins/default/xui/de/floater_preview_gesture_shortcut.xml b/indra/newview/skins/default/xui/de/floater_preview_gesture_shortcut.xml
new file mode 100644
index 0000000000..0b5df13395
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_preview_gesture_shortcut.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Gesture" title="GESTE - SCHNELLTASTE">
+ <text name="trigger_label">
+ Chat:
+ </text>
+ <text name="key_label">
+ Tastatur:
+ </text>
+ <combo_box label="Keiner" name="modifier_combo"/>
+ <combo_box label="Keiner" name="key_combo"/>
+ <text name="replace_text" tool_tip="Ersetzt den Auslösertext mit diesem Text. Wenn Sie zum Beispiel den Auslöser „hallo“ durch „wie geht&apos;s“ ersetzen, erscheint im Chat anstelle von „Ich wollte nur hallo sagen“ der Text „Ich wollte nur wie geht&apos;s sagen“ und die zugehörige Geste wird abgespielt.">
+ Ersetzen:
+ </text>
+ <line_editor name="replace_editor" tool_tip="Ersetzt den Auslösertext mit diesem Text. Wenn Sie zum Beispiel den Auslöser „hallo“ durch „wie geht&apos;s“ ersetzen, erscheint im Chat anstelle von „Ich wollte nur hallo sagen“ der Text „Ich wollte nur wie geht&apos;s sagen“ und die zugehörige Geste wird abgespielt."/>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_preview_gesture_steps.xml b/indra/newview/skins/default/xui/de/floater_preview_gesture_steps.xml
new file mode 100644
index 0000000000..0d0d28f96f
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_preview_gesture_steps.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Gesture" title="GESTE - SCHNELLTASTE"/>
diff --git a/indra/newview/skins/default/xui/de/floater_preview_notecard.xml b/indra/newview/skins/default/xui/de/floater_preview_notecard.xml
index 370f242ddb..a02a58ee0e 100644
--- a/indra/newview/skins/default/xui/de/floater_preview_notecard.xml
+++ b/indra/newview/skins/default/xui/de/floater_preview_notecard.xml
@@ -1,16 +1,22 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="preview notecard" title="Hinweis:">
- <button label="Speichern" label_selected="Speichern" name="Save" />
- <text type="string" length="1" name="desc txt">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="preview notecard" title="HINWEIS:">
+ <floater.string name="no_object">
+ Es wurde kein Objekt gefunden, das diese Notiz enthält.
+ </floater.string>
+ <floater.string name="not_allowed">
+ Ihnen fehlt die Berechtigung zur Anzeige dieser Notizkarte.
+ </floater.string>
+ <floater.string name="Title">
+ Notizkarte: [NAME]
+ </floater.string>
+ <floater.string label="Speichern" label_selected="Speichern" name="Save">
+ Speichern
+ </floater.string>
+ <text name="desc txt">
Beschreibung:
</text>
- <text_editor type="string" length="1" name="Notecard Editor">
+ <text_editor name="Notecard Editor">
Wird geladen...
</text_editor>
- <text name="no_object">
- Es wurde kein Objekt gefunden, das diese Notiz enthält.
- </text>
- <text name="not_allowed">
- Sie können diese Notiz nicht anzeigen.
- </text>
+ <button label="Speichern" label_selected="Speichern" name="Save"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_preview_sound.xml b/indra/newview/skins/default/xui/de/floater_preview_sound.xml
index fd0a824c03..17419548bc 100644
--- a/indra/newview/skins/default/xui/de/floater_preview_sound.xml
+++ b/indra/newview/skins/default/xui/de/floater_preview_sound.xml
@@ -1,12 +1,11 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="preview_sound">
- <text type="string" length="1" name="desc txt">
+ <floater.string name="Title">
+ Sound: [NAME]
+ </floater.string>
+ <text name="desc txt">
Beschreibung:
</text>
- <button label="In Welt abspielen" label_selected="In Welt abspielen"
- name="Sound play btn"
- tool_tip="Gibt diesen Sound so wieder, dass andere ihn hören können." />
- <button label="Lokal wiedergeben" label_selected="Lokal wiedergeben"
- name="Sound audition btn"
- tool_tip="Gibt diesen Sound so wieder, dass nur Sie ihn hören." />
+ <button label="In Welt abspielen" label_selected="In Welt abspielen" name="Sound play btn" tool_tip="Gibt diesen Sound so wieder, dass andere ihn hören können."/>
+ <button label="Lokal wiedergeben" label_selected="Lokal wiedergeben" name="Sound audition btn" tool_tip="Gibt diesen Sound so wieder, dass nur Sie ihn hören."/>
</floater>
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 6828da99eb..95d1db1877 100644
--- a/indra/newview/skins/default/xui/de/floater_preview_texture.xml
+++ b/indra/newview/skins/default/xui/de/floater_preview_texture.xml
@@ -1,9 +1,46 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="preview_texture">
- <text type="string" length="1" name="desc txt">
+ <floater.string name="Title">
+ Textur: [NAME]
+ </floater.string>
+ <floater.string name="Copy">
+ In Inventar kopieren
+ </floater.string>
+ <text name="desc txt">
Beschreibung:
</text>
- <text type="string" length="1" name="dimensions">
- Maße: [WIDTH] x [HEIGHT]
+ <button label="OK" name="Keep"/>
+ <button label="Abbrechen" name="Discard"/>
+ <text name="dimensions">
+ [WIDTH]px x [HEIGHT]px
</text>
+ <text name="aspect_ratio">
+ Seitenverhältnis anzeigen
+ </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>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_region_info.xml b/indra/newview/skins/default/xui/de/floater_region_info.xml
index 4c28c7f5b0..354cdaa272 100644
--- a/indra/newview/skins/default/xui/de/floater_region_info.xml
+++ b/indra/newview/skins/default/xui/de/floater_region_info.xml
@@ -1,2 +1,2 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="regioninfo" title="Region/Grundstück" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="regioninfo" title="REGION/GRUNDSTÃœCK"/>
diff --git a/indra/newview/skins/default/xui/de/floater_report_abuse.xml b/indra/newview/skins/default/xui/de/floater_report_abuse.xml
index 6a7246d1e6..3e4cf86a75 100644
--- a/indra/newview/skins/default/xui/de/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/de/floater_report_abuse.xml
@@ -1,12 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_report_abuse" title="Missbrauch melden">
- <texture_picker label="" name="screenshot"/>
- <check_box bottom_delta="-20" label="Screenshot einschließen" name="screen_check"/>
+<floater name="floater_report_abuse" title="MISSBRAUCH MELDEN">
+ <floater.string name="Screenshot">
+ Foto
+ </floater.string>
+ <check_box bottom_delta="-20" label="Dieses Foto verwenden" name="screen_check"/>
<text name="reporter_title">
Melder:
</text>
<text name="reporter_field">
- Loremipsum Dolorsitamut
+ Loremipsum Dolorsitamut Longnamez
</text>
<text name="sim_title">
Region:
@@ -21,12 +23,11 @@
{128.1, 128.1, 15.4}
</text>
<text bottom_delta="-38" height="32" name="select_object_label">
- Klicken Sie auf die Schaltfläche,
-dann auf das Objekt:
+ Klicken Sie auf die Schaltfläche, dann auf das entsprechende Objekt:
</text>
<button label="" label_selected="" name="pick_btn" tool_tip="Objektauswahl – Wählen Sie ein Objekt als Thema dieses Berichts aus"/>
<text name="object_name_label">
- Name:
+ Objekt:
</text>
<text name="object_name">
Consetetur Sadipscing
@@ -35,132 +36,53 @@ dann auf das Objekt:
Eigentümer:
</text>
<text name="owner_name">
- Hendrerit Vulputate
+ Hendrerit Vulputate Kamawashi Longname
</text>
<combo_box name="category_combo" tool_tip="Kategorie -- wählen Sie die Kategorie aus, die am besten auf diesen Bericht zutrifft">
- <combo_item name="Select_category">
- Kategorie auswählen
- </combo_item>
- <combo_item name="Age__Age_play">
- Alter&gt; Age-Play
- </combo_item>
- <combo_item name="Age__Adult_resident_on_Teen_Second_Life">
- Alter&gt; Erwachsener Einwohner in Teen Second Life
- </combo_item>
- <combo_item name="Age__Underage_resident_outside_of_Teen_Second_Life">
- Alter &gt; Minderjähriger Einwohner außerhalb Teen Second Life
- </combo_item>
- <combo_item name="Assault__Combat_sandbox___unsafe_area">
- Angriff&gt; Kampf-Sandbox / unsichere Region
- </combo_item>
- <combo_item name="Assault__Safe_area">
- Angriff&gt; Sichere Region
- </combo_item>
- <combo_item name="Assault__Weapons_testing_sandbox">
- Angriff &gt; Sandbox für Waffentest
- </combo_item>
- <combo_item name="Commerce__Failure_to_deliver_product_or_service">
- Handel &gt; Produkt nicht geliefert oder Dienstleistung nicht erbracht
- </combo_item>
- <combo_item name="Disclosure__Real_world_information">
- Offenlegung &gt; Informationen aus realer Welt
- </combo_item>
- <combo_item name="Disclosure__Remotely_monitoring chat">
- Offenlegung &gt; Abhören eines Chats aus der Ferne
- </combo_item>
- <combo_item name="Disclosure__Second_Life_information_chat_IMs">
- Offenlegung &gt; Second Life-Informationen/Chat/IMs
- </combo_item>
- <combo_item name="Disturbing_the_peace__Unfair_use_of_region_resources">
- Ruhestörung &gt; Unfaire Nutzung von Regionsressourcen
- </combo_item>
- <combo_item name="Disturbing_the_peace__Excessive_scripted_objects">
- Ruhestörung &gt; Exzessive Nutzung geskripteter Objekte
- </combo_item>
- <combo_item name="Disturbing_the_peace__Object_littering">
- Ruhestörung &gt; Wildes Erzeugen von Objekten
- </combo_item>
- <combo_item name="Disturbing_the_peace__Repetitive_spam">
- Ruhestörung &gt; Ständige Spam-Wiederholung
- </combo_item>
- <combo_item name="Disturbing_the_peace__Unwanted_advert_spam">
- Ruhestörung &gt; Unerwünschte Spam-Werbung
- </combo_item>
- <combo_item name="Fraud__L$">
- Betrug &gt; L$
- </combo_item>
- <combo_item name="Fraud__Land">
- Betrug&gt; Land
- </combo_item>
- <combo_item name="Fraud__Pyramid_scheme_or_chain_letter">
- Betrug &gt; Schneeballsystem oder Kettenbrief
- </combo_item>
- <combo_item name="Fraud__US$">
- Betrug &gt; US$
- </combo_item>
- <combo_item name="Harassment__Advert_farms___visual_spam">
- Belästigung &gt; Werbefarmen / visueller Spam
- </combo_item>
- <combo_item name="Harassment__Defaming_individuals_or_groups">
- Belästigung &gt; Diffamieren von Einzelpersonen/Gruppen
- </combo_item>
- <combo_item name="Harassment__Impeding_movement">
- Belästigung &gt; Bewegungseinschränkung
- </combo_item>
- <combo_item name="Harassment__Sexual_harassment">
- Belästigung &gt; Sexuelle Belästigung
- </combo_item>
- <combo_item name="Harassment__Solicting_inciting_others_to_violate_ToS">
- Belästigung &gt; Anstiften Dritter zur Missachtung der Nutzungsbedingungen
- </combo_item>
- <combo_item name="Harassment__Verbal_abuse">
- Belästigung &gt; Beschimpfung
- </combo_item>
- <combo_item name="Indecency__Broadly_offensive_content_or_conduct">
- Unanständigkeit &gt; Anstößige Inhalte oder Handlungen in der Öffentlichkeit
- </combo_item>
- <combo_item name="Indecency__Inappropriate_avatar_name">
- Unanständigkeit &gt; Anstößiger Avatarname
- </combo_item>
- <combo_item name="Indecency__Mature_content_in_PG_region">
- Unanständigkeit &gt; Unangemessener Inhalt oder unangemessenes Verhalten in PG-Region
- </combo_item>
- <combo_item name="Indecency__Inappropriate_content_in_Mature_region">
- Unanständigkeit &gt; Unangemessener Inhalt oder unangemessenes Verhalten in Mature-Region
- </combo_item>
- <combo_item name="Intellectual_property_infringement_Content_Removal">
- Urheberrechtsverletzung &gt; Entfernen von Inhalten
- </combo_item>
- <combo_item name="Intellectual_property_infringement_CopyBot_or_Permissions_Exploit">
- Urheberrechtsverletzung &gt; CopyBot oder Berechtigungs-Exploit
- </combo_item>
- <combo_item name="Intolerance">
- Intoleranz
- </combo_item>
- <combo_item name="Land__Abuse_of_sandbox_resources">
- Land &gt; Missbrauch der Sandbox-Ressourcen
- </combo_item>
- <combo_item name="Land__Encroachment__Objects_textures">
- Land &gt; Unbefugte Nutzung &gt; Objekte/Texturen
- </combo_item>
- <combo_item name="Land__Encroachment__Particles">
- Land &gt; Unbefugte Nutzung &gt; Partikel
- </combo_item>
- <combo_item name="Land__Encroachment__Trees_plants">
- Land &gt; Unbefugte Nutzung &gt; Bäume/Pflanzen
- </combo_item>
- <combo_item name="Wagering_gambling">
- Wetten/Glücksspiel
- </combo_item>
- <combo_item name="Other">
- Sonstige
- </combo_item>
+ <combo_box.item label="Kategorie auswählen" name="Select_category"/>
+ <combo_box.item label="Alter&gt; Age-Play" name="Age__Age_play"/>
+ <combo_box.item label="Alter&gt; Erwachsener Einwohner in Teen Second Life" name="Age__Adult_resident_on_Teen_Second_Life"/>
+ <combo_box.item label="Alter &gt; Minderjähriger Einwohner außerhalb Teen Second Life" name="Age__Underage_resident_outside_of_Teen_Second_Life"/>
+ <combo_box.item label="Angriff&gt; Kampf-Sandbox / unsichere Region" name="Assault__Combat_sandbox___unsafe_area"/>
+ <combo_box.item label="Angriff&gt; Sichere Region" name="Assault__Safe_area"/>
+ <combo_box.item label="Angriff &gt; Sandbox für Waffentest" name="Assault__Weapons_testing_sandbox"/>
+ <combo_box.item label="Handel &gt; Produkt nicht geliefert oder Dienstleistung nicht erbracht" name="Commerce__Failure_to_deliver_product_or_service"/>
+ <combo_box.item label="Offenlegung &gt; Informationen aus realer Welt" name="Disclosure__Real_world_information"/>
+ <combo_box.item label="Offenlegung &gt; Abhören eines Chats aus der Ferne" name="Disclosure__Remotely_monitoring chat"/>
+ <combo_box.item label="Offenlegung &gt; Second Life-Informationen/Chat/IMs" name="Disclosure__Second_Life_information_chat_IMs"/>
+ <combo_box.item label="Ruhestörung &gt; Unfaire Nutzung von Regionsressourcen" name="Disturbing_the_peace__Unfair_use_of_region_resources"/>
+ <combo_box.item label="Ruhestörung &gt; Exzessive Nutzung geskripteter Objekte" name="Disturbing_the_peace__Excessive_scripted_objects"/>
+ <combo_box.item label="Ruhestörung &gt; Wildes Erzeugen von Objekten" name="Disturbing_the_peace__Object_littering"/>
+ <combo_box.item label="Ruhestörung &gt; Ständige Spam-Wiederholung" name="Disturbing_the_peace__Repetitive_spam"/>
+ <combo_box.item label="Ruhestörung &gt; Unerwünschte Spam-Werbung" name="Disturbing_the_peace__Unwanted_advert_spam"/>
+ <combo_box.item label="Betrug &gt; L$" name="Fraud__L$"/>
+ <combo_box.item label="Betrug&gt; Land" name="Fraud__Land"/>
+ <combo_box.item label="Betrug &gt; Schneeballsystem oder Kettenbrief" name="Fraud__Pyramid_scheme_or_chain_letter"/>
+ <combo_box.item label="Betrug &gt; US$" name="Fraud__US$"/>
+ <combo_box.item label="Belästigung &gt; Werbefarmen / visueller Spam" name="Harassment__Advert_farms___visual_spam"/>
+ <combo_box.item label="Belästigung &gt; Diffamieren von Einzelpersonen/Gruppen" name="Harassment__Defaming_individuals_or_groups"/>
+ <combo_box.item label="Belästigung &gt; Bewegungseinschränkung" name="Harassment__Impeding_movement"/>
+ <combo_box.item label="Belästigung &gt; Sexuelle Belästigung" name="Harassment__Sexual_harassment"/>
+ <combo_box.item label="Belästigung &gt; Anstiften Dritter zur Missachtung der Nutzungsbedingungen" name="Harassment__Solicting_inciting_others_to_violate_ToS"/>
+ <combo_box.item label="Belästigung &gt; Beschimpfung" name="Harassment__Verbal_abuse"/>
+ <combo_box.item label="Unanständigkeit &gt; Anstößige Inhalte oder Handlungen in der Öffentlichkeit" name="Indecency__Broadly_offensive_content_or_conduct"/>
+ <combo_box.item label="Unanständigkeit &gt; Anstößiger Avatarname" name="Indecency__Inappropriate_avatar_name"/>
+ <combo_box.item label="Unanständigkeit &gt; Unangemessener Inhalt oder unangemessenes Verhalten in PG-Region" name="Indecency__Mature_content_in_PG_region"/>
+ <combo_box.item label="Unanständigkeit &gt; Unangemessener Inhalt oder unangemessenes Verhalten in Mature-Region" name="Indecency__Inappropriate_content_in_Mature_region"/>
+ <combo_box.item label="Urheberrechtsverletzung &gt; Entfernen von Inhalten" name="Intellectual_property_infringement_Content_Removal"/>
+ <combo_box.item label="Urheberrechtsverletzung &gt; CopyBot oder Berechtigungs-Exploit" name="Intellectual_property_infringement_CopyBot_or_Permissions_Exploit"/>
+ <combo_box.item label="Intoleranz" name="Intolerance"/>
+ <combo_box.item label="Land &gt; Missbrauch der Sandbox-Ressourcen" name="Land__Abuse_of_sandbox_resources"/>
+ <combo_box.item label="Land &gt; Unbefugte Nutzung &gt; Objekte/Texturen" name="Land__Encroachment__Objects_textures"/>
+ <combo_box.item label="Land &gt; Unbefugte Nutzung &gt; Partikel" name="Land__Encroachment__Particles"/>
+ <combo_box.item label="Land &gt; Unbefugte Nutzung &gt; Bäume/Pflanzen" name="Land__Encroachment__Trees_plants"/>
+ <combo_box.item label="Wetten/Glücksspiel" name="Wagering_gambling"/>
+ <combo_box.item label="Sonstige" name="Other"/>
</combo_box>
<text name="abuser_name_title">
Name des Beschuldigten:
</text>
- <button label="Einwohner auswählen" label_selected="" name="select_abuser" tool_tip="Den Namen des Beschuldigten aus einer Liste wählen"/>
- <check_box label="Name des Täters ist nicht bekannt" name="omit_abuser_name" tool_tip="Wählen Sie diese Option, wenn Ihnen der Name des Täters unbekannt ist"/>
+ <button label="Auswählen" label_selected="" name="select_abuser" tool_tip="Den Namen des Beschuldigten aus einer Liste wählen"/>
<text name="abuser_name_title2">
Ort des Missbrauchs:
</text>
@@ -171,14 +93,12 @@ dann auf das Objekt:
Details:
</text>
<text name="bug_aviso">
- Machen Sie genaue Angaben zu Datum, Ort und Art des
-Missbrauchs, relevantem Chat/IM und wählen Sie das
-Objekt, wenn möglich.
+ Bitte beschreiben Sie alles so genau wie möglich.
</text>
<text_editor bottom_delta="-136" height="130" name="details_edit"/>
<text bottom_delta="-20" name="incomplete_title">
- Hinweis: Unvollständige Meldungen werden nicht bearbeitet.
+ * Unvollständige Berichte werden nicht bearbeitet
</text>
- <button label="Abbrechen" label_selected="Abbrechen" name="cancel_btn"/>
<button label="Missbrauch melden" label_selected="Missbrauch melden" name="send_btn"/>
+ <button label="Abbrechen" label_selected="Abbrechen" name="cancel_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_script_debug.xml b/indra/newview/skins/default/xui/de/floater_script_debug.xml
index f8c1543fdd..585a6c36ea 100644
--- a/indra/newview/skins/default/xui/de/floater_script_debug.xml
+++ b/indra/newview/skins/default/xui/de/floater_script_debug.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<multi_floater name="script debug floater" title="Skriptwarnung/Fehler">
<tab_container name="Preview Tabs">
- <floater label="Skript" name="all_scripts" title="[All scripts]" />
+ <floater label="Skript" name="all_scripts" title="[ALL SCRIPTS]" />
</tab_container>
</multi_floater>
diff --git a/indra/newview/skins/default/xui/de/floater_script_debug_panel.xml b/indra/newview/skins/default/xui/de/floater_script_debug_panel.xml
new file mode 100644
index 0000000000..e70a30fa24
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_script_debug_panel.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="script" short_title="[ALL SCRIPTS]" title="[ALL SCRIPTS]"/>
diff --git a/indra/newview/skins/default/xui/de/floater_script_preview.xml b/indra/newview/skins/default/xui/de/floater_script_preview.xml
index b5312e370a..27c40aff07 100644
--- a/indra/newview/skins/default/xui/de/floater_script_preview.xml
+++ b/indra/newview/skins/default/xui/de/floater_script_preview.xml
@@ -1,6 +1,9 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="preview lsl text" title="Skript: Rotationsskript">
- <text type="string" length="1" name="desc txt">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="preview lsl text" title="SKRIPT: ROTATIONS-SKRIPT">
+ <floater.string name="Title">
+ Skript: [NAME]
+ </floater.string>
+ <text name="desc txt">
Beschreibung:
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_script_queue.xml b/indra/newview/skins/default/xui/de/floater_script_queue.xml
index 63d5ef2478..f267fe4b7c 100644
--- a/indra/newview/skins/default/xui/de/floater_script_queue.xml
+++ b/indra/newview/skins/default/xui/de/floater_script_queue.xml
@@ -1,4 +1,19 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="queue" title="Rückgängig">
- <button label="Schließen" label_selected="Schließen" name="close" left="215" width="72"/>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="queue" title="ZURÃœCKSETZEN">
+ <floater.string name="Starting">
+ [START] von [COUNT] Artikeln.
+ </floater.string>
+ <floater.string name="Done">
+ Fertig.
+ </floater.string>
+ <floater.string name="Resetting">
+ Wird zurückgesetzt
+ </floater.string>
+ <floater.string name="Running">
+ Läuft
+ </floater.string>
+ <floater.string name="NotRunning">
+ Läuft nicht
+ </floater.string>
+ <button label="Schließen" label_selected="Schließen" left="215" name="close" width="72"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_script_search.xml b/indra/newview/skins/default/xui/de/floater_script_search.xml
index 54045ed83a..de959cbb28 100644
--- a/indra/newview/skins/default/xui/de/floater_script_search.xml
+++ b/indra/newview/skins/default/xui/de/floater_script_search.xml
@@ -1,13 +1,13 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script search" title="Skriptsuche">
- <check_box label="Groß-/Kleinschreibung irrelevant" name="case_text" />
- <button label="Suchen" label_selected="Suchen" name="search_btn" />
- <button label="Ersetzen" label_selected="Ersetzen" name="replace_btn" />
- <button label="Alle ersetzen" label_selected="Alle ersetzen" name="replace_all_btn" />
- <text type="string" length="1" name="txt">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="script search" title="SKRIPT-SUCHE">
+ <check_box label="Groß-/Kleinschreibung irrelevant" name="case_text"/>
+ <button label="Suchen" label_selected="Suchen" name="search_btn"/>
+ <button label="Ersetzen" label_selected="Ersetzen" name="replace_btn"/>
+ <button label="Alle ersetzen" label_selected="Alle ersetzen" name="replace_all_btn"/>
+ <text name="txt">
Suchen
</text>
- <text type="string" length="1" name="txt2">
+ <text name="txt2">
Ersetzen
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_search.xml b/indra/newview/skins/default/xui/de/floater_search.xml
new file mode 100644
index 0000000000..3401db1a39
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_search.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_search" title="SUCHEN">
+ <floater.string name="loading_text">
+ Wird geladen...
+ </floater.string>
+ <floater.string name="done_text">
+ Fertig
+ </floater.string>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_sell_land.xml b/indra/newview/skins/default/xui/de/floater_sell_land.xml
index d4ec0fa729..c9e21a6c4f 100644
--- a/indra/newview/skins/default/xui/de/floater_sell_land.xml
+++ b/indra/newview/skins/default/xui/de/floater_sell_land.xml
@@ -1,73 +1,65 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="sell land" title="Land verkaufen">
- <text name="info_parcel_label">
- Parzelle:
- </text>
- <text bottom_delta="-5" height="16" name="info_parcel">
- PARZELLENNAME
- </text>
- <text name="info_size_label">
- Größe:
- </text>
- <text bottom_delta="-21" height="32" name="info_size">
- [AREA] qm
- </text>
- <text height="28" name="info_action" bottom_delta="-57">
- Zum Verkauf
-dieser Parzelle:
- </text>
- <icon bottom_delta="-80" name="step_price" />
- <text name="price_label">
- Preis festlegen:
- </text>
- <text name="price_text">
- Geben Sie einen angemessenen Preis für dieses Land ein.
- </text>
- <text name="price_ld">
- L$
- </text>
- <text name="price_per_m">
- ([PER_METER] L$ pro Quadratmeter)
- </text>
- <icon height="64" left="0" name="step_sell_to" width="64" />
- <text bottom_delta="38" left="72" name="sell_to_label" right="-20">
- Land verkaufen an:
- </text>
- <text height="16" left="72" name="sell_to_text" bottom_delta="-16" right="-10">
- Wählen Sie, ob der Verkauf offen oder auf eine bestimmte Person
-beschränkt ist.
- </text>
- <combo_box height="16" left="72" name="sell_to" bottom_delta="-32" width="140">
- <combo_item name="--selectone--">
- -- select one --
- </combo_item>
- <combo_item name="Anyone">
- Jeder
- </combo_item>
- <combo_item name="Specificuser:">
- Bestimmter Benutzer:
- </combo_item>
- </combo_box>
- <button label="Auswählen..." name="sell_to_select_agent" />
- <text name="sell_objects_label">
- Die Objekte mit dem Land verkaufen?
- </text>
- <text name="sell_objects_text">
- Die transferierbaren Landeigentümer-Objekte auf der Parzelle
-wechseln den Eigentümer.
- </text>
- <radio_group bottom_delta="-58" name="sell_objects">
- <radio_item name="no">
- Nein, Objekte behalten
- </radio_item>
- <radio_item name="yes">
- Ja, Objekte mit Land verkaufen
- </radio_item>
- </radio_group>
- <button label="Objekte anzeigen" name="show_objects" width="116"/>
- <text name="nag_message_label">
- ACHTUNG: Verkäufe sind endgültig.
- </text>
- <button label="Land zum Verkauf freigeben" width="180" name="sell_btn" />
- <button label="Abbrechen" name="cancel_btn" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="sell land" title="LAND VERKAUFEN">
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <text name="info_parcel_label">
+ Parzelle:
+ </text>
+ <text bottom_delta="-5" height="16" name="info_parcel">
+ PARZELLENNAME
+ </text>
+ <text name="info_size_label">
+ Größe:
+ </text>
+ <text bottom_delta="-21" height="32" name="info_size">
+ [AREA] m².
+ </text>
+ <text bottom_delta="-57" height="28" name="info_action">
+ Zum Verkauf dieser Parzelle:
+ </text>
+ <text name="price_label">
+ 1. Preis festlegen:
+ </text>
+ <text name="price_text">
+ Einen angemessenen Preis auswählen.
+ </text>
+ <text name="price_ld">
+ L$
+ </text>
+ <line_editor name="price">
+ 0
+ </line_editor>
+ <text name="price_per_m">
+ ([PER_METER] L$ pro m²)
+ </text>
+ <text bottom_delta="38" left="72" name="sell_to_label" right="-20">
+ 2. Land verkaufen an:
+ </text>
+ <text bottom_delta="-16" height="16" left="72" name="sell_to_text" right="-10">
+ Wählen Sie, ob der Verkauf offen oder auf eine bestimmte Person beschränkt ist.
+ </text>
+ <combo_box bottom_delta="-32" height="16" left="72" name="sell_to" width="140">
+ <combo_box.item label="-- Wählen --" name="--selectone--"/>
+ <combo_box.item label="Jeder" name="Anyone"/>
+ <combo_box.item label="Bestimmte Person:" name="Specificuser:"/>
+ </combo_box>
+ <button label="Auswählen" name="sell_to_select_agent"/>
+ <text name="sell_objects_label">
+ 3. Die Objekte mit dem Land verkaufen?
+ </text>
+ <text name="sell_objects_text">
+ Die transferierbaren Landeigentümer-Objekte auf der Parzelle wechseln den Eigentümer.
+ </text>
+ <radio_group bottom_delta="-58" name="sell_objects">
+ <radio_item label="Nein, Objekte behalten" name="no"/>
+ <radio_item label="Ja, Objekte mit Land verkaufen" name="yes"/>
+ </radio_group>
+ <button label="Objekte anzeigen" name="show_objects" width="116"/>
+ <text name="nag_message_label">
+ ACHTUNG: Verkäufe sind endgültig.
+ </text>
+ <button label="Land zum Verkauf freigeben" name="sell_btn" width="180"/>
+ <button label="Abbrechen" name="cancel_btn"/>
+ </panel>
+ </scroll_container>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_settings_debug.xml b/indra/newview/skins/default/xui/de/floater_settings_debug.xml
index d64b9dccf9..004e54a339 100644
--- a/indra/newview/skins/default/xui/de/floater_settings_debug.xml
+++ b/indra/newview/skins/default/xui/de/floater_settings_debug.xml
@@ -1,17 +1,13 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="settings_debug" title="Debug-Einstellungen">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="settings_debug" title="DEBUG-EINSTELLUNGEN">
<combo_box name="boolean_combo">
- <combo_item name="TRUE">
- WAHR
- </combo_item>
- <combo_item name="FALSE">
- FALSCH
- </combo_item>
+ <combo_box.item label="WAHR" name="TRUE"/>
+ <combo_box.item label="FALSCH" name="FALSE"/>
</combo_box>
- <color_swatch label="Farbe" name="color_swatch" />
- <spinner label="x" name="val_spinner_1" />
- <spinner label="x" name="val_spinner_2" />
- <spinner label="x" name="val_spinner_3" />
- <spinner label="x" name="val_spinner_4" />
- <button label="Standard wiederherstellen" name="default_btn" width="170" />
+ <color_swatch label="Farbe" name="val_color_swatch"/>
+ <spinner label="x" name="val_spinner_1"/>
+ <spinner label="x" name="val_spinner_2"/>
+ <spinner label="x" name="val_spinner_3"/>
+ <spinner label="x" name="val_spinner_4"/>
+ <button label="Standard wiederherstellen" name="default_btn" width="170"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_snapshot.xml b/indra/newview/skins/default/xui/de/floater_snapshot.xml
index 401aa74084..8aa1ef5497 100644
--- a/indra/newview/skins/default/xui/de/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/de/floater_snapshot.xml
@@ -1,18 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Snapshot" title="Foto-Vorschau">
+<floater name="Snapshot" title="FOTO-ANZEIGE">
<text name="type_label">
Zweck des Fotos
</text>
<radio_group label="Fototyp" name="snapshot_type_radio">
- <radio_item name="postcard">
- Per E-Mail senden
- </radio_item>
- <radio_item name="texture">
- Im Inventar speichern ([AMOUNT] L$)
- </radio_item>
- <radio_item name="local">
- Auf Festplatte speichern
- </radio_item>
+ <radio_item label="Per E-Mail senden" name="postcard"/>
+ <radio_item label="Im Inventar speichern ([AMOUNT] L$)" name="texture"/>
+ <radio_item label="Auf Festplatte speichern" name="local"/>
</radio_group>
<text name="file_size_label">
Dateigröße: [SIZE] KB
@@ -21,12 +15,8 @@
<button label="Senden" name="send_btn"/>
<button label="Speichern ([AMOUNT] L$)" name="upload_btn"/>
<flyout_button label="Speichern" name="save_btn" tool_tip="Bild als Datei speichern">
- <flyout_button_item name="save_item">
- Speichern
- </flyout_button_item>
- <flyout_button_item name="saveas_item">
- Speichern unter...
- </flyout_button_item>
+ <flyout_button_item label="Speichern" name="save_item"/>
+ <flyout_button_item label="Speichern unter..." name="saveas_item"/>
</flyout_button>
<button label="Abbrechen" name="discard_btn"/>
<button label="Mehr &gt;&gt;" name="more_btn" tool_tip="Erweiterte Optionen"/>
@@ -38,75 +28,33 @@
Format
</text>
<combo_box label="Auflösung" name="postcard_size_combo">
- <combo_item name="CurrentWindow">
- Aktuelles Fenster
- </combo_item>
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
- <combo_item name="Custom">
- Benutzerdefiniert
- </combo_item>
+ <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="Benutzerdefiniert" name="Custom"/>
</combo_box>
<combo_box label="Auflösung" name="texture_size_combo">
- <combo_item name="CurrentWindow">
- Aktuelles Fenster
- </combo_item>
- <combo_item name="Small(128x128)">
- Klein (128x128)
- </combo_item>
- <combo_item name="Medium(256x256)">
- Mittel (256x256)
- </combo_item>
- <combo_item name="Large(512x512)">
- Groß (512x512)
- </combo_item>
- <combo_item name="Custom">
- Benutzerdefiniert
- </combo_item>
+ <combo_box.item label="Aktuelles Fenster" name="CurrentWindow"/>
+ <combo_box.item label="Klein (128x128)" name="Small(128x128)"/>
+ <combo_box.item label="Mittel (256x256)" name="Medium(256x256)"/>
+ <combo_box.item label="Groß (512x512)" name="Large(512x512)"/>
+ <combo_box.item label="Benutzerdefiniert" name="Custom"/>
</combo_box>
<combo_box label="Auflösung" name="local_size_combo">
- <combo_item name="CurrentWindow">
- Aktuelles Fenster
- </combo_item>
- <combo_item name="320x240">
- 320x240
- </combo_item>
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
- <combo_item name="1280x1024">
- 1280x1024
- </combo_item>
- <combo_item name="1600x1200">
- 1600x1200
- </combo_item>
- <combo_item name="Custom">
- Benutzerdefiniert
- </combo_item>
+ <combo_box.item label="Aktuelles Fenster" name="CurrentWindow"/>
+ <combo_box.item label="320x240" name="320x240"/>
+ <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="1280x1024" name="1280x1024"/>
+ <combo_box.item label="1600x1200" name="1600x1200"/>
+ <combo_box.item label="Benutzerdefiniert" name="Custom"/>
</combo_box>
<combo_box label="Format" name="local_format_combo">
- <combo_item name="PNG">
- PNG
- </combo_item>
- <combo_item name="JPEG">
- JPEG
- </combo_item>
- <combo_item name="BMP">
- BMP
- </combo_item>
+ <combo_box.item label="PNG" name="PNG"/>
+ <combo_box.item label="JPEG" name="JPEG"/>
+ <combo_box.item label="BMP" name="BMP"/>
</combo_box>
<spinner label="Breite" name="snapshot_width"/>
<spinner label="Höhe" name="snapshot_height"/>
@@ -115,16 +63,10 @@
<text name="layer_type_label" width="63">
Aufnehmen:
</text>
- <combo_box label="Bildlayer" name="layer_types" width="132" left="73">
- <combo_item name="Colors">
- Farben
- </combo_item>
- <combo_item name="Depth">
- Tiefe
- </combo_item>
- <combo_item name="ObjectMattes">
- Objektmasken
- </combo_item>
+ <combo_box label="Bildlayer" left="73" name="layer_types" width="132">
+ <combo_box.item label="Farben" name="Colors"/>
+ <combo_box.item label="Tiefe" name="Depth"/>
+ <combo_box.item label="Objektmasken" name="ObjectMattes"/>
</combo_box>
<check_box label="Interface auf Foto anzeigen" name="ui_check"/>
<check_box label="HUD-Objekte auf Foto anzeigen" name="hud_check"/>
diff --git a/indra/newview/skins/default/xui/de/floater_sound_preview.xml b/indra/newview/skins/default/xui/de/floater_sound_preview.xml
index 552b4b0f27..1070c93405 100644
--- a/indra/newview/skins/default/xui/de/floater_sound_preview.xml
+++ b/indra/newview/skins/default/xui/de/floater_sound_preview.xml
@@ -1,28 +1,20 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Sound Preview" title="sound.wav">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Sound Preview" title="SOUND.WAV">
<text name="name_label">
Name:
</text>
<text name="description_label">
Beschreibung:
</text>
- <button label="Abbrechen" label_selected="Abbrechen" name="cancel_btn" />
- <button label="Hochladen ([AMOUNT] L$)" label_selected="Hochladen ([AMOUNT] L$)" name="ok_btn" />
+ <button label="Abbrechen" label_selected="Abbrechen" name="cancel_btn"/>
+ <button label="Hochladen ([AMOUNT] L$)" label_selected="Hochladen ([AMOUNT] L$)" name="ok_btn"/>
<text name="text">
Bitrate (kbit/s):
</text>
<radio_group name="bitrate">
- <radio_item name="32">
- 32
- </radio_item>
- <radio_item name="64">
- 64
- </radio_item>
- <radio_item name="96">
- 96
- </radio_item>
- <radio_item name="128">
- 128
- </radio_item>
+ <radio_item label="32" name="32"/>
+ <radio_item label="64" name="64"/>
+ <radio_item label="96" name="96"/>
+ <radio_item label="128" name="128"/>
</radio_group>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_statistics.xml b/indra/newview/skins/default/xui/de/floater_statistics.xml
index 26e976a59c..72a87a9566 100644
--- a/indra/newview/skins/default/xui/de/floater_statistics.xml
+++ b/indra/newview/skins/default/xui/de/floater_statistics.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="stats floater" title="Statistikleiste"/>
+<floater name="stats floater" title="STATISTIKEN"/>
diff --git a/indra/newview/skins/default/xui/de/floater_stats.xml b/indra/newview/skins/default/xui/de/floater_stats.xml
new file mode 100644
index 0000000000..dcea484e13
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_stats.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Statistics" title="STATISTIKEN">
+ <scroll_container name="statistics_scroll">
+ <container_view name="statistics_view">
+ <stat_view label="Basic" name="basic">
+ <stat_bar label="FPS" name="fps"/>
+ <stat_bar label="Bandbreite" name="bandwidth"/>
+ <stat_bar label="Paketverlust" name="packet_loss"/>
+ <stat_bar label="Ping Sim" name="ping"/>
+ </stat_view>
+ <stat_view label="Erweitert" name="advanced">
+ <stat_view label="Darstellung" name="render">
+ <stat_bar label="Gezeichnete KTris" name="ktrisframe"/>
+ <stat_bar label="Gezeichnete KTris" name="ktrissec"/>
+ <stat_bar label="Objektanzahl" name="objs"/>
+ <stat_bar label="Neue Objekte" name="newobjs"/>
+ </stat_view>
+ <stat_view label="Textur" name="texture">
+ <stat_bar label="Zählen" name="numimagesstat"/>
+ <stat_bar label="Rohanzahl" name="numrawimagesstat"/>
+ <stat_bar label="GL Sp" name="gltexmemstat"/>
+ <stat_bar label="Formattierter Sp:" name="formattedmemstat"/>
+ <stat_bar label="Rohsp" name="rawmemstat"/>
+ <stat_bar label="Zugeteilter Sp" name="glboundmemstat"/>
+ </stat_view>
+ <stat_view label="Netzwerk" name="network">
+ <stat_bar label="Paketeingang" name="packetsinstat"/>
+ <stat_bar label="Paketausgang" name="packetsoutstat"/>
+ <stat_bar label="Objekte" name="objectkbitstat"/>
+ <stat_bar label="Textur" name="texturekbitstat"/>
+ <stat_bar label="Bestand" name="assetkbitstat"/>
+ <stat_bar label="Ebenen" name="layerskbitstat"/>
+ <stat_bar label="Tatsächlicher Eingang" name="actualinkbitstat"/>
+ <stat_bar label="Tatsächlicher Ausgang" name="actualoutkbitstat"/>
+ <stat_bar label="VFS Ausstehende Ops" name="vfspendingoperations"/>
+ </stat_view>
+ </stat_view>
+ <stat_view label="Simulator" name="sim">
+ <stat_bar label="Zeitdilation" name="simtimedilation"/>
+ <stat_bar label="Sim FPS" name="simfps"/>
+ <stat_bar label="Physik FPS" name="simphysicsfps"/>
+ <stat_view label="Physikdetails" name="physicsdetail">
+ <stat_bar label="Eingerastete Objekte" name="physicspinnedtasks"/>
+ <stat_bar label="Niedrig LOD-Objekte" name="physicslodtasks"/>
+ <stat_bar label="Zugeordneter Speicher" name="physicsmemoryallocated"/>
+ </stat_view>
+ <stat_bar label="Agent-Aktualisierungen/Sek" name="simagentups"/>
+ <stat_bar label="Haupt-Agenten" name="simmainagents"/>
+ <stat_bar label="Child-Agenten" name="simchildagents"/>
+ <stat_bar label="Objekte" name="simobjects"/>
+ <stat_bar label="Aktive Objekte" name="simactiveobjects"/>
+ <stat_bar label="Aktive Skripts" name="simactivescripts"/>
+ <stat_bar label="Skript-Events" name="simscripteps"/>
+ <stat_bar label="Paketeingang" name="siminpps"/>
+ <stat_bar label="Paketausgang" name="simoutpps"/>
+ <stat_bar label="Ausstehende Downloads" name="simpendingdownloads"/>
+ <stat_bar label="Ausstehende Uploads" name="simpendinguploads"/>
+ <stat_bar label="Gesamtanzahl „Unacked&quot; Bytes" name="simtotalunackedbytes"/>
+ <stat_view label="Zeit (ms)" name="simperf">
+ <stat_bar label="Gesamtzeit Frame" name="simframemsec"/>
+ <stat_bar label="Netto-Zeit" name="simnetmsec"/>
+ <stat_bar label="Physik-Zeit" name="simsimphysicsmsec"/>
+ <stat_bar label="Simulationszeit" name="simsimothermsec"/>
+ <stat_bar label="Agent-Zeit" name="simagentmsec"/>
+ <stat_bar label="Bilder-Zeit" name="simimagesmsec"/>
+ <stat_bar label="Skript-Zeit" name="simscriptmsec"/>
+ </stat_view>
+ </stat_view>
+ </container_view>
+ </scroll_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_sys_well.xml b/indra/newview/skins/default/xui/de/floater_sys_well.xml
new file mode 100644
index 0000000000..bcf0cbd419
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_sys_well.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="notification_chiclet" title="BENACHRICHTIGUNGEN"/>
diff --git a/indra/newview/skins/default/xui/de/floater_telehub.xml b/indra/newview/skins/default/xui/de/floater_telehub.xml
index 264411c166..f348371e4d 100644
--- a/indra/newview/skins/default/xui/de/floater_telehub.xml
+++ b/indra/newview/skins/default/xui/de/floater_telehub.xml
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="telehub" title="Telehub" min_height="310" height="310" >
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater height="310" min_height="310" name="telehub" title="TELEHUB">
<text name="status_text_connected">
Telehub verbunden mit Objekt [OBJECT]
</text>
@@ -9,17 +9,17 @@
<text name="help_text_connected">
Klicken Sie zum Entfernen auf „Trennen“.
</text>
- <text name="help_text_not_connected" height="38" bottom_delta="-18" >
+ <text bottom_delta="-18" height="38" name="help_text_not_connected">
Wählen Sie ein Objekt und klicken Sie auf
„Mit Telehub verbinden“.
</text>
- <button label="Mit Telehub verbinden" name="connect_btn" width="122" />
- <button label="Trennen" name="disconnect_btn" left="142" width="98" />
+ <button label="Mit Telehub verbinden" name="connect_btn" width="122"/>
+ <button label="Trennen" left="142" name="disconnect_btn" width="98"/>
<text name="spawn_points_text" width="230">
Spawn-Punkte (Positionen, nicht Objekte):
</text>
- <button label="Spawn hinzufügen" name="add_spawn_point_btn" />
- <button label="Spawn entfernen" name="remove_spawn_point_btn" />
+ <button label="Spawn hinzufügen" name="add_spawn_point_btn"/>
+ <button label="Spawn entfernen" name="remove_spawn_point_btn"/>
<text name="spawn_point_help">
Wählen Sie ein Objekt und klicken zur
Positionsangabe auf „Hinzufügen“. Anschließend
diff --git a/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml
index 4aa7db4d33..4e2d8a9274 100644
--- a/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml
@@ -1,23 +1,23 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="texture picker" title="Auswählen: Textur">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="texture picker" title="AUSWÄHLEN: TEXTUR">
<string name="choose_picture">
Zum Auswählen eines Bildes hier klicken
</string>
- <text type="string" length="1" name="Multiple">
- Mehrfach
+ <text name="Multiple">
+ Mehrer Texturen
</text>
- <text type="string" length="1" name="unknown">
- Maße: [DIMENSIONS]
+ <text name="unknown">
+ Größe: [DIMENSIONS]
</text>
- <button label="Standard" label_selected="Standard" name="Default" />
- <button label="Keine" label_selected="Keine" name="None" />
- <button label="Leer" label_selected="Leer" name="Blank" />
- <check_box label="Ordner anzeigen" name="show_folders_check" />
- <search_editor label="Suchanfrage hier eintippen" name="inventory search editor" />
- <check_box label="Sofort übernehmen" name="apply_immediate_check" />
- <button label="" label_selected="" name="Pipette" />
- <button label="Abbrechen" label_selected="Abbrechen" name="Cancel" />
- <button label="Auswählen" label_selected="Auswählen" name="Select" />
+ <button label="Standard" label_selected="Standard" name="Default"/>
+ <button label="Keine" label_selected="Keine" name="None"/>
+ <button label="Leer" label_selected="Leer" name="Blank"/>
+ <check_box label="Ordner anzeigen" name="show_folders_check"/>
+ <search_editor label="Texturen filtern" name="inventory search editor"/>
+ <check_box label="Jetzt übernehmen" name="apply_immediate_check"/>
+ <button label="" label_selected="" name="Pipette"/>
+ <button label="Abbrechen" label_selected="Abbrechen" name="Cancel"/>
+ <button label="OK" label_selected="OK" name="Select"/>
<text name="pick title">
Auswählen:
</text>
diff --git a/indra/newview/skins/default/xui/de/floater_tools.xml b/indra/newview/skins/default/xui/de/floater_tools.xml
index cef204eb5f..48887191e0 100644
--- a/indra/newview/skins/default/xui/de/floater_tools.xml
+++ b/indra/newview/skins/default/xui/de/floater_tools.xml
@@ -1,42 +1,81 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="toolbox floater" title="">
+<floater name="toolbox floater" short_title="BAU-WERKZEUGE" title="">
+ <floater.string name="status_rotate">
+ An den farbigen Bändern ziehen, um das Objekt zu drehen
+ </floater.string>
+ <floater.string name="status_scale">
+ Klicken und ziehen, um die ausgewählte Seite zu dehnen
+ </floater.string>
+ <floater.string name="status_move">
+ Maus verschiebt, Umschalt-Taste und Maus kopiert
+ </floater.string>
+ <floater.string name="status_modifyland">
+ Klicken und halten, um das Land zu bearbeiten
+ </floater.string>
+ <floater.string name="status_camera">
+ Klicken und ziehen, um Kamera zu bewegen
+ </floater.string>
+ <floater.string name="status_grab">
+ Ziehen, um Objekte zu verschieben, Strg zum Heben, Strg + Umschalt zum Drehen
+ </floater.string>
+ <floater.string name="status_place">
+ Inworld klicken, um zu bauen.
+ </floater.string>
+ <floater.string name="status_selectland">
+ Klicken und ziehen, um Land auszuwählen
+ </floater.string>
+ <floater.string name="grid_screen_text">
+ Bildschirm
+ </floater.string>
+ <floater.string name="grid_local_text">
+ Lokal
+ </floater.string>
+ <floater.string name="grid_world_text">
+ Welt
+ </floater.string>
+ <floater.string name="grid_reference_text">
+ Referenz
+ </floater.string>
+ <floater.string name="grid_attachment_text">
+ Anhang
+ </floater.string>
<button label="" label_selected="" name="button focus" tool_tip="Fokus"/>
<button label="" label_selected="" name="button move" tool_tip="Verschieben"/>
<button label="" label_selected="" name="button edit" tool_tip="Bearbeiten"/>
<button label="" label_selected="" name="button create" tool_tip="Erstellen"/>
<button label="" label_selected="" name="button land" tool_tip="Land"/>
- <check_box label="Zoom" name="radio zoom"/>
- <check_box label="Orbit (Strg)" name="radio orbit"/>
- <check_box label="Schwenken (Strg-Umschalt)" name="radio pan"/>
- <check_box label="Verschieben" name="radio move"/>
- <check_box label="Heben (Strg)" name="radio lift"/>
- <check_box label="Rotieren (Strg-Umschalt)" name="radio spin"/>
- <check_box label="Position" name="radio position"/>
- <check_box label="Drehen (Strg)" name="radio rotate"/>
- <check_box label="Dehnen (Strg-Umschalt)" name="radio stretch"/>
- <check_box label="Textur auswählen" name="radio select face"/>
- <check_box label="Verknüpfte Teile bearbeiten" name="checkbox edit linked parts"/>
- <text name="text ruler mode">
- Lineal:
- </text>
- <combo_box name="combobox grid mode">
- <combo_item name="World">
- Welt
- </combo_item>
- <combo_item name="Local">
- Lokal
- </combo_item>
- <combo_item name="Reference">
- Referenz
- </combo_item>
- </combo_box>
- <check_box label="Beide Seiten dehnen" name="checkbox uniform"/>
- <check_box label="Texturen dehnen" name="checkbox stretch textures"/>
- <check_box label="Raster verwenden" name="checkbox snap to grid"/>
- <button label="Optionen..." label_selected="Optionen..." name="Options..."/>
<text name="text status">
Zum Verschieben ziehen, zum Kopieren Umschalttaste-Ziehen
</text>
+ <radio_group name="focus_radio_group">
+ <radio_item label="Zoom" name="radio zoom"/>
+ <radio_item label="Orbit (Strg)" name="radio orbit"/>
+ <radio_item label="Schwenken (Strg+Umschalt)" name="radio pan"/>
+ </radio_group>
+ <radio_group name="move_radio_group">
+ <radio_item label="Verschieben" name="radio move"/>
+ <radio_item label="Heben (Strg)" name="radio lift"/>
+ <radio_item label="Drehen (Strg+Umschalt)" name="radio spin"/>
+ </radio_group>
+ <radio_group name="edit_radio_group">
+ <radio_item label="Bewegen" name="radio position"/>
+ <radio_item label="Drehen (Strg)" name="radio rotate"/>
+ <radio_item label="Dehnen (Strg+Umschalt)" name="radio stretch"/>
+ <radio_item label="Fläche auswählen" name="radio select face"/>
+ </radio_group>
+ <check_box label="Verknüpfte Teile bearbeiten" name="checkbox edit linked parts"/>
+ <text name="RenderingCost" tool_tip="Zeigt die errechneten Wiedergabekosten für diesen Objekt">
+ þ: [COUNT]
+ </text>
+ <check_box label="Beide Seiten dehnen" name="checkbox uniform"/>
+ <check_box initial_value="true" label="Texturen dehnen" name="checkbox stretch textures"/>
+ <check_box initial_value="true" label="An Raster ausrichten" name="checkbox snap to grid"/>
+ <combo_box name="combobox grid mode" tool_tip="Wählen Sie das Rasterlineal aus, um das Objekt zu positionieren.">
+ <combo_box.item label="Globales Raster" name="World"/>
+ <combo_box.item label="Lokales Raster" name="Local"/>
+ <combo_box.item label="Referenzraster" name="Reference"/>
+ </combo_box>
+ <button label="Optionen..." label_selected="Optionen..." name="Options..." tool_tip="Mehr Raster-Optionen anzeigen"/>
<button label="" label_selected="" name="ToolCube" tool_tip="Würfel"/>
<button label="" label_selected="" name="ToolPrism" tool_tip="Prisma"/>
<button label="" label_selected="" name="ToolPyramid" tool_tip="Pyramide"/>
@@ -52,18 +91,19 @@
<button label="" label_selected="" name="ToolRing" tool_tip="Ring"/>
<button label="" label_selected="" name="ToolTree" tool_tip="Baum"/>
<button label="" label_selected="" name="ToolGrass" tool_tip="Gras"/>
- <check_box label="Auswahl behalten" name="checkbox sticky"/>
+ <check_box label="Ausgewähltes Werkzeug beibehalten" name="checkbox sticky"/>
<check_box label="Auswahl kopieren" name="checkbox copy selection"/>
- <check_box label="Zentrieren" name="checkbox copy centers"/>
- <check_box label="Drehen" name="checkbox copy rotates"/>
- <check_box label="Land auswählen" name="radio select land"/>
- <check_box label="Einebnen" name="radio flatten"/>
- <check_box label="Anheben" name="radio raise"/>
- <check_box label="Absenken" name="radio lower"/>
- <check_box label="Glätten" name="radio smooth"/>
- <check_box label="Aufrauen" name="radio noise"/>
- <check_box label="Zurücksetzen" name="radio revert"/>
- <button label="Übernehmen" label_selected="Übernehmen" name="button apply to selection" tool_tip="Ausgewähltes Land ändern"/>
+ <check_box initial_value="true" label="Kopie zentrieren" name="checkbox copy centers"/>
+ <check_box label="Kopie drehen" name="checkbox copy rotates"/>
+ <radio_group name="land_radio_group">
+ <radio_item label="Land auswählen" name="radio select land"/>
+ <radio_item label="Einebnen" name="radio flatten"/>
+ <radio_item label="Anheben" name="radio raise"/>
+ <radio_item label="Absenken" name="radio lower"/>
+ <radio_item label="Glätten" name="radio smooth"/>
+ <radio_item label="Aufrauen" name="radio noise"/>
+ <radio_item label="Zurücksetzen" name="radio revert"/>
+ </radio_group>
<text name="Bulldozer:">
Planierraupe:
</text>
@@ -73,14 +113,51 @@
<text name="Strength:">
Stärke
</text>
+ <button label="Übernehmen" label_selected="Übernehmen" name="button apply to selection" tool_tip="Ausgewähltes Land bearbeiten"/>
<text name="obj_count">
- Ausgewählte Objekte: [COUNT]
+ Objekte: [COUNT]
</text>
<text name="prim_count">
Primitive: [COUNT]
</text>
- <tab_container name="Object Info Tabs" tab_max_width="150" tab_min_width="30">
+ <tab_container name="Object Info Tabs">
<panel label="Allgemein" name="General">
+ <panel.string name="text deed continued">
+ Ãœbertragung
+ </panel.string>
+ <panel.string name="text deed">
+ Ãœbertragung
+ </panel.string>
+ <panel.string name="text modify info 1">
+ Sie können dieses Objekt bearbeiten.
+ </panel.string>
+ <panel.string name="text modify info 2">
+ Sie können diese Objekte bearbeiten.
+ </panel.string>
+ <panel.string name="text modify info 3">
+ Sie können dieses Objekt nicht bearbeiten.
+ </panel.string>
+ <panel.string name="text modify info 4">
+ Sie können diese Objekte nicht bearbeiten.
+ </panel.string>
+ <panel.string name="text modify warning">
+ Gesamtes Objekt wählen, um Berechtigungen festzulegen.
+ </panel.string>
+ <panel.string name="Cost Default">
+ Preis: L$
+ </panel.string>
+ <panel.string name="Cost Total">
+ Summe: L$
+ </panel.string>
+ <panel.string name="Cost Per Unit">
+ Stückpreis: L$
+ </panel.string>
+ <panel.string name="Cost Mixed">
+ Mischpreis
+ </panel.string>
+ <panel.string name="Sale Mixed">
+ Mischverkauf
+ </panel.string>
<text name="Name:">
Name:
</text>
@@ -91,146 +168,79 @@
Ersteller:
</text>
<text name="Creator Name">
- Thrax Linden
+ Esbee Linden
</text>
- <button label="Profil..." label_selected="Profil..." name="button creator profile"/>
<text name="Owner:">
Eigentümer:
</text>
<text name="Owner Name">
- Thrax Linden
+ Erica Linden
</text>
- <button label="Profil..." label_selected="Profil..." name="button owner profile"/>
<text name="Group:">
Gruppe:
</text>
- <text name="Group Name Proxy">
- Die Lindens
- </text>
- <button label="Festlegen..." label_selected="Festlegen..." name="button set group"/>
- <text name="Permissions:">
- Berechtigungen:
- </text>
- <text name="perm_modify">
- Sie können dieses Objekt ändern.
- </text>
- <check_box label="Mit Gruppe teilen" left="6" name="checkbox share with group" tool_tip="Allen Mitgliedern der zugeordneten Gruppe die Erlaubnis erteilen, Ihre Berechtigungen für dieses Objekt zu teilen und zu verwenden. Sie müssen Übereignen, um Rollenbeschränkungen zu aktivieren."/>
- <string name="text deed continued">
- Ãœbertragung...
- </string>
- <string name="text deed">
- Ãœbertragung
- </string>
- <button label="Übertragung..." label_selected="Übertragung..." name="button deed" tool_tip="In der Gruppe gemeinsam verwendete Objekte können von einem Gruppenfunktionär übertragen werden."/>
- <check_box label="Verschieben durch beliebige Personen zulassen" left="6" name="checkbox allow everyone move"/>
- <check_box label="Kopieren durch beliebige Personen zulassen" left="6" name="checkbox allow everyone copy"/>
- <check_box label="In Suche anzeigen" left="6" name="search_check" tool_tip="Dieses Objekt in Suchergebnissen anzeigen"/>
- <check_box label="Zu verkaufen" left="6" name="checkbox for sale"/>
- <text name="Cost">
- Preis:L$
- </text>
- <radio_group name="sale type">
- <radio_item name="Original">
- Original
- </radio_item>
- <radio_item name="Copy">
- Kopieren
- </radio_item>
- <radio_item name="Contents">
- Inhalt
- </radio_item>
- </radio_group>
- <text name="Next owner can:">
- Nächster Eigentümer kann:
- </text>
- <check_box label="Ändern" name="checkbox next owner can modify"/>
- <check_box label="Kopieren" name="checkbox next owner can copy"/>
- <check_box label="Wiederverkaufen" left_delta="75" name="checkbox next owner can transfer"/>
+ <button label="Festlegen..." label_selected="Festlegen..." name="button set group" tool_tip="Eine Gruppe auswählen, um die Berechtigungen des Objekts zu teilen."/>
+ <name_box initial_value="Wird geladen..." name="Group Name Proxy"/>
+ <button label="Übertragung" label_selected="Übertragung" name="button deed" tool_tip="Eine Übertragung bedeutet, dass das Objekt mit den Berechtigungen „Nächster Eigentümer“ weitergegeben wird. Mit der Gruppe geteilte Objekte können von einem Gruppen-Officer übertragen werden."/>
+ <check_box label="Teilen" name="checkbox share with group" tool_tip="Mit allen Mitgliedern der zugeordneten Gruppe, Ihre Berechtigungen dieses Objekt zu ändern teilen. Sie müssen Übereignen, um Rollenbeschränkungen zu aktivieren."/>
<text name="label click action">
- Bei Linksklicken:
- </text>
- <combo_box name="clickaction" width="178">
- <combo_item name="Touch/grab(default)">
- Berühren/Greifen (Standard)
- </combo_item>
- <combo_item name="Sitonobject">
- Auf Objekt sitzen
- </combo_item>
- <combo_item name="Buyobject">
- Objekt kaufen
- </combo_item>
- <combo_item name="Payobject">
- Objekt bezahlen
- </combo_item>
- <combo_item name="Open">
- Öffnen
- </combo_item>
- <combo_item name="Play">
- Parzellenmedien wiedergeben
- </combo_item>
- <combo_item name="Opemmedia">
- Parzellenmedien öffnen
- </combo_item>
+ Bei Linksklick:
+ </text>
+ <combo_box name="clickaction">
+ <combo_box.item label="Berühren (Standard)" name="Touch/grab(default)"/>
+ <combo_box.item label="Auf Objekt sitzen" name="Sitonobject"/>
+ <combo_box.item label="Objekt kaufen" name="Buyobject"/>
+ <combo_box.item label="Objekt bezahlen" name="Payobject"/>
+ <combo_box.item label="Öffnen" name="Open"/>
+ <combo_box.item label="Zoom" name="Zoom"/>
</combo_box>
- <text name="B:">
- B:
- </text>
- <text name="O:">
- O;
- </text>
- <text name="G:">
- G:
- </text>
- <text name="E:">
- E:
- </text>
- <text name="N:">
- N:
- </text>
- <text name="F:">
- F:
- </text>
- <string name="text modify info 1">
- Sie können dieses Objekt ändern.
- </string>
- <string name="text modify info 2">
- Sie können diese Objekte ändern.
- </string>
- <string name="text modify info 3">
- Sie können dieses Objekt nicht ändern.
- </string>
- <string name="text modify info 4">
- Sie können diese Objekte nicht ändern.
- </string>
- <string name="text modify warning">
- Gesamtes Objekt muss gewählt werden, um Berechtigungen festzulegen.
- </string>
- <string name="Cost Default">
- Preis:L$
- </string>
- <string name="Cost Total">
- Summe:L$
- </string>
- <string name="Cost Per Unit">
- Stückpreis:L$
- </string>
- <string name="Cost Mixed">
- Mischpreis
- </string>
- <string name="Sale Mixed">
- Mischverkauf
- </string>
+ <check_box label="Zum Verkauf:" name="checkbox for sale"/>
+ <combo_box name="sale type">
+ <combo_box.item label="Kopieren" name="Copy"/>
+ <combo_box.item label="Inhalt" name="Contents"/>
+ <combo_box.item label="Original" name="Original"/>
+ </combo_box>
+ <spinner label="Preis: L$" name="Edit Cost"/>
+ <check_box label="In Suche anzeigen" name="search_check" tool_tip="Dieses Objekt in Suchergebnissen anzeigen"/>
+ <panel name="perms_build">
+ <text name="perm_modify">
+ Sie können dieses Objekt bearbeiten.
+ </text>
+ <text name="Anyone can:">
+ Jeder:
+ </text>
+ <check_box label="Bewegen" name="checkbox allow everyone move"/>
+ <check_box label="Kopieren" name="checkbox allow everyone copy"/>
+ <text name="Next owner can:">
+ Nächster Eigentümer:
+ </text>
+ <check_box label="Ändern" name="checkbox next owner can modify"/>
+ <check_box label="Kopieren" name="checkbox next owner can copy"/>
+ <check_box label="Transferieren" name="checkbox next owner can transfer" tool_tip="Nächster Eigentümer kann dieses Objekt weitergeben oder -verkaufen"/>
+ <text name="B:">
+ B:
+ </text>
+ <text name="O:">
+ O:
+ </text>
+ <text name="G:">
+ G:
+ </text>
+ <text name="E:">
+ E:
+ </text>
+ <text name="N:">
+ N:
+ </text>
+ <text name="F:">
+ F:
+ </text>
+ </panel>
</panel>
<panel label="Objekt" name="Object">
- <text name="select_single">
- Wählen Sie nur ein Primitivum aus, um Parameter zu bearbeiten.
- </text>
- <text name="edit_object">
- Objektparameter bearbeiten:
- </text>
<check_box label="Gesperrt" name="checkbox locked" tool_tip="Verhindert, dass Objekt verschoben oder gelöscht wird. Oft beim Bauen nützlich, um unbeabsichtigte Bearbeitungen zu vermeiden."/>
<check_box label="Physisch" name="Physical Checkbox Ctrl" tool_tip="Gestattet, das Objekt geschoben und von Schwerkraft beeinflusst wird"/>
- <check_box label="Temporär" name="Temporary Checkbox Ctrl" tool_tip="Verursacht, dass Objekt 1 Minute nach Erstellung gelöscht wird."/>
+ <check_box label="Temporär" name="Temporary Checkbox Ctrl" tool_tip="Bewirkt, dass das Objekt 1 Minute nach seiner Erstellung gelöscht wird."/>
<check_box label="Phantom" name="Phantom Checkbox Ctrl" tool_tip="Verursacht, dass Objekt nicht mit anderen Objekten oder Avataren kollidiert"/>
<text name="label position">
Position (Meter)
@@ -250,155 +260,100 @@
<spinner label="X" name="Rot X"/>
<spinner label="Y" name="Rot Y"/>
<spinner label="Z" name="Rot Z"/>
- <text name="label material">
- Material
- </text>
- <combo_box name="material">
- <combo_item name="Stone">
- Stein
- </combo_item>
- <combo_item name="Metal">
- Metall
- </combo_item>
- <combo_item name="Glass">
- Glas
- </combo_item>
- <combo_item name="Wood">
- Holz
- </combo_item>
- <combo_item name="Flesh">
- Fleisch
- </combo_item>
- <combo_item name="Plastic">
- Kunststoff
- </combo_item>
- <combo_item name="Rubber">
- Gummi
- </combo_item>
+ <combo_box name="comboBaseType">
+ <combo_box.item label="Quader" name="Box"/>
+ <combo_box.item label="Zylinder" name="Cylinder"/>
+ <combo_box.item label="Prisma" name="Prism"/>
+ <combo_box.item label="Kugel" name="Sphere"/>
+ <combo_box.item label="Torus" name="Torus"/>
+ <combo_box.item label="Rohr" name="Tube"/>
+ <combo_box.item label="Ring" name="Ring"/>
+ <combo_box.item label="Geformt" name="Sculpted"/>
</combo_box>
- <text left="115" name="label basetype">
- Bausteintyp
- </text>
- <combo_box left="115" name="comboBaseType">
- <combo_item name="Box">
- Quader
- </combo_item>
- <combo_item name="Cylinder">
- Zylinder
- </combo_item>
- <combo_item name="Prism">
- Prisma
- </combo_item>
- <combo_item name="Sphere">
- Kugel
- </combo_item>
- <combo_item name="Torus">
- Torus
- </combo_item>
- <combo_item name="Tube">
- Rohr
- </combo_item>
- <combo_item name="Ring">
- Ring
- </combo_item>
- <combo_item name="Sculpted">
- Geformt
- </combo_item>
+ <combo_box name="material">
+ <combo_box.item label="Stein" name="Stone"/>
+ <combo_box.item label="Metall" name="Metal"/>
+ <combo_box.item label="Glas" name="Glass"/>
+ <combo_box.item label="Holz" name="Wood"/>
+ <combo_box.item label="Fleisch" name="Flesh"/>
+ <combo_box.item label="Kunststoff" name="Plastic"/>
+ <combo_box.item label="Gummi" name="Rubber"/>
</combo_box>
- <text left="115" name="text cut" width="146">
- Pfadschnitt Beginn und Ende
+ <text name="text cut">
+ Pfadschnitt (Anfang/Ende)
</text>
- <spinner label="B" left="115" name="cut begin"/>
- <spinner label="E" left="115" name="cut end"/>
- <text left="115" name="text hollow">
+ <spinner label="B" name="cut begin"/>
+ <spinner label="E" name="cut end"/>
+ <text name="text hollow">
Hohl
</text>
- <text left="115" name="text skew">
+ <text name="text skew">
Versatz
</text>
- <spinner left="115" name="Scale 1"/>
- <spinner left="115" name="Skew"/>
- <text left="115" name="Hollow Shape">
+ <spinner name="Scale 1"/>
+ <spinner name="Skew"/>
+ <text name="Hollow Shape">
Hohlform
</text>
- <combo_box left="115" name="hole">
- <combo_item name="Default">
- Standard
- </combo_item>
- <combo_item name="Circle">
- Kreis
- </combo_item>
- <combo_item name="Square">
- Quadrat
- </combo_item>
- <combo_item name="Triangle">
- Dreieck
- </combo_item>
+ <combo_box name="hole">
+ <combo_box.item label="Standard" name="Default"/>
+ <combo_box.item label="Kreis" name="Circle"/>
+ <combo_box.item label="Quadrat" name="Square"/>
+ <combo_box.item label="Dreieck" name="Triangle"/>
</combo_box>
- <text left="115" name="text twist">
- Torsion
+ <text name="text twist">
+ Torsion (Anfang/Ende)
</text>
- <spinner label="B" left="115" name="Twist Begin"/>
- <spinner label="E" left="115" name="Twist End"/>
- <text left="115" name="scale_taper">
+ <spinner label="B" name="Twist Begin"/>
+ <spinner label="E" name="Twist End"/>
+ <text name="scale_taper">
Verjüngung
</text>
- <text left="115" name="scale_hole">
+ <text name="scale_hole">
Lochgröße
</text>
- <spinner label="X" left="115" name="Taper Scale X"/>
- <spinner label="Y" left="115" name="Taper Scale Y"/>
- <text left="115" name="text topshear">
+ <spinner label="X" name="Taper Scale X"/>
+ <spinner label="Y" name="Taper Scale Y"/>
+ <text name="text topshear">
Verscherung
</text>
- <spinner label="X" left="115" name="Shear X"/>
- <spinner label="Y" left="115" name="Shear Y"/>
- <text left="115" name="advanced_cut" width="153">
- Profilschnitt-Beginn und Ende
+ <spinner label="X" name="Shear X"/>
+ <spinner label="Y" name="Shear Y"/>
+ <text name="advanced_cut">
+ Profilschnitt (Anfang/Ende)
</text>
- <text left="115" name="advanced_dimple">
- Vertiefung-Beginn und Ende
+ <text name="advanced_dimple">
+ Vertiefung (Anfang/Ende)
</text>
<text name="advanced_slice">
- Anfang/Ende abschneiden
+ Abschneiden (Anfang/Ende)
</text>
- <spinner label="B" left="115" name="Path Limit Begin"/>
+ <spinner label="B" name="Path Limit Begin"/>
<spinner label="E" name="Path Limit End"/>
- <text left="115" name="text taper2">
+ <text name="text taper2">
Verjüngung
</text>
- <spinner label="X" left="115" name="Taper X"/>
+ <spinner label="X" name="Taper X"/>
<spinner label="Y" name="Taper Y"/>
- <text left="115" name="text radius delta">
+ <text name="text radius delta">
Radius
</text>
- <text name="text revolutions" width="74">
+ <text name="text revolutions">
Umdrehungen
</text>
- <spinner left="115" name="Radius Offset"/>
- <texture_picker label="Textur für gestaltetes
-Primitiv" name="sculpt texture control" tool_tip="Klicken Sie hier, um ein Bild auszuwählen"/>
- <check_box bottom_delta="-34" label="Spiegeln" name="sculpt mirror control" tool_tip="Geformtes Primitiv entlang der X-Achse spiegeln."/>
+ <spinner name="Radius Offset"/>
+ <texture_picker label="Textur für gestaltetes Primitiv" name="sculpt texture control" tool_tip="Klicken Sie hier, um ein Bild auszuwählen"/>
+ <check_box label="Spiegeln" name="sculpt mirror control" tool_tip="Geformtes Primitiv entlang der X-Achse spiegeln."/>
<check_box label="Wenden" name="sculpt invert control" tool_tip="Dreht die Normalen des geformten Primitivs von innen nach außen."/>
<text name="label sculpt type">
Naht
</text>
<combo_box name="sculpt type control">
- <combo_item name="None">
- (keiner)
- </combo_item>
- <combo_item name="Sphere">
- Kugel
- </combo_item>
- <combo_item name="Torus">
- Torus
- </combo_item>
- <combo_item name="Plane">
- Fläche
- </combo_item>
- <combo_item name="Cylinder">
- Zylinder
- </combo_item>
+ <combo_box.item label="(keiner)" name="None"/>
+ <combo_box.item label="Kugel" name="Sphere"/>
+ <combo_box.item label="Torus" name="Torus"/>
+ <combo_box.item label="Fläche" name="Plane"/>
+ <combo_box.item label="Zylinder" name="Cylinder"/>
</combo_box>
</panel>
<panel label="Eigenschaften" name="Features">
@@ -408,7 +363,7 @@ Primitiv" name="sculpt texture control" tool_tip="Klicken Sie hier, um ein Bild
<text name="edit_object">
Objekteigenschaften bearbeiten:
</text>
- <check_box label="Flexibler Weg" name="Flexible1D Checkbox Ctrl" tool_tip="Gestattet, dass Objekt um die Z-Achse gebogen wird. (nur Client-Seite)"/>
+ <check_box label="Flexibler Weg" name="Flexible1D Checkbox Ctrl" tool_tip="Bewirkt, dass sich das Objekt um die Z-Achse biegen kann. (Nur Client-Seite)"/>
<spinner label="Weichheit" name="FlexNumSections"/>
<spinner label="Schwerkraft" name="FlexGravity"/>
<spinner label="Ziehen" name="FlexFriction"/>
@@ -418,17 +373,24 @@ Primitiv" name="sculpt texture control" tool_tip="Klicken Sie hier, um ein Bild
<spinner label="Erzwingen Y" name="FlexForceY"/>
<spinner label="Erzwingen Z" name="FlexForceZ"/>
<check_box label="Licht" name="Light Checkbox Ctrl" tool_tip="Verursacht, dass Objekt Licht emittiert"/>
- <text name="label color">
- Farbe
- </text>
- <color_swatch label="" name="colorswatch" tool_tip="Klicken, um Farbauswahl zu öffnen"/>
+ <color_swatch label="" name="colorswatch" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen"/>
+ <texture_picker label="" name="light texture control" tool_tip="Klicken, um eine Bild auszuwählen (dieser Effekt funktioniert nur, wenn zeitversetzte Wiedergabe aktiviert ist)"/>
<spinner label="Intensität" name="Light Intensity"/>
+ <spinner label="FOV" name="Light FOV"/>
<spinner label="Radius" name="Light Radius"/>
+ <spinner label="Fokus" name="Light Focus"/>
<spinner label="Abnehmend" name="Light Falloff"/>
+ <spinner label="Ambiente" name="Light Ambiance"/>
</panel>
<panel label="Textur" name="Texture">
+ <panel.string name="string repeats per meter">
+ Kacheln pro Meter
+ </panel.string>
+ <panel.string name="string repeats per face">
+ Wiederholungen pro Fläche
+ </panel.string>
<texture_picker label="Textur" name="texture control" tool_tip="Klicken, um ein Bild zu wählen"/>
- <color_swatch label="Farbe" name="colorswatch" tool_tip="Klicken, um Farbauswahl zu öffnen"/>
+ <color_swatch label="Farbe" name="colorswatch" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen"/>
<text name="color trans">
Transparenz %
</text>
@@ -440,123 +402,69 @@ Primitiv" name="sculpt texture control" tool_tip="Klicken Sie hier, um ein Bild
Zuordnung
</text>
<combo_box name="combobox texgen">
- <combo_item name="Default">
- Standard
- </combo_item>
- <combo_item name="Planar">
- Eben
- </combo_item>
+ <combo_box.item label="Standard" name="Default"/>
+ <combo_box.item label="Eben" name="Planar"/>
</combo_box>
<text name="label shininess">
Glanz
</text>
<combo_box name="combobox shininess">
- <combo_item name="None">
- Kein
- </combo_item>
- <combo_item name="Low">
- Niedrig
- </combo_item>
- <combo_item name="Medium">
- Mittel
- </combo_item>
- <combo_item name="High">
- Hoch
- </combo_item>
+ <combo_box.item label="Kein" name="None"/>
+ <combo_box.item label="Niedrig" name="Low"/>
+ <combo_box.item label="Mittel" name="Medium"/>
+ <combo_box.item label="Hoch" name="High"/>
</combo_box>
<text name="label bumpiness">
Holprigkeit
</text>
<combo_box name="combobox bumpiness">
- <combo_item name="None">
- Keine
- </combo_item>
- <combo_item name="Brightness">
- Helligkeit
- </combo_item>
- <combo_item name="Darkness">
- Dunkelheit
- </combo_item>
- <combo_item name="woodgrain">
- Holzmaserung
- </combo_item>
- <combo_item name="bark">
- Rinde
- </combo_item>
- <combo_item name="bricks">
- Ziegel
- </combo_item>
- <combo_item name="checker">
- Karo
- </combo_item>
- <combo_item name="concrete">
- Beton
- </combo_item>
- <combo_item name="crustytile">
- verkrustete Fliesen
- </combo_item>
- <combo_item name="cutstone">
- Steinplatten
- </combo_item>
- <combo_item name="discs">
- Scheiben
- </combo_item>
- <combo_item name="gravel">
- Kies
- </combo_item>
- <combo_item name="petridish">
- Petrischale
- </combo_item>
- <combo_item name="siding">
- Verkleidung
- </combo_item>
- <combo_item name="stonetile">
- Steinfliesen
- </combo_item>
- <combo_item name="stucco">
- Stuck
- </combo_item>
- <combo_item name="suction">
- Saugen
- </combo_item>
- <combo_item name="weave">
- gewoben
- </combo_item>
+ <combo_box.item label="Keine" name="None"/>
+ <combo_box.item label="Helligkeit" name="Brightness"/>
+ <combo_box.item label="Dunkelheit" name="Darkness"/>
+ <combo_box.item label="Holzmaserung" name="woodgrain"/>
+ <combo_box.item label="Rinde" name="bark"/>
+ <combo_box.item label="Ziegel" name="bricks"/>
+ <combo_box.item label="Karo" name="checker"/>
+ <combo_box.item label="Beton" name="concrete"/>
+ <combo_box.item label="verkrustete Fliesen" name="crustytile"/>
+ <combo_box.item label="Steinplatten" name="cutstone"/>
+ <combo_box.item label="Scheiben" name="discs"/>
+ <combo_box.item label="Kies" name="gravel"/>
+ <combo_box.item label="Petrischale" name="petridish"/>
+ <combo_box.item label="Verkleidung" name="siding"/>
+ <combo_box.item label="Steinfliesen" name="stonetile"/>
+ <combo_box.item label="Stuck" name="stucco"/>
+ <combo_box.item label="Saugen" name="suction"/>
+ <combo_box.item label="gewoben" name="weave"/>
</combo_box>
<text name="tex scale">
- Wiederholungen
+ Wiederholungen / Fläche
</text>
<spinner label="Horizontal (U)" name="TexScaleU"/>
<check_box label="Umkehren" name="checkbox flip s"/>
<spinner label="Vertikal (V)" name="TexScaleV"/>
<check_box label="Umkehren" name="checkbox flip t"/>
- <text name="tex rotate">
- Rotation (Grad)
- </text>
- <string name="string repeats per meter">
- Kacheln pro Meter
- </string>
- <string name="string repeats per face">
- Wiederholungen pro Fläche
- </string>
- <text name="rpt">
- Kacheln pro Meter
- </text>
+ <spinner label="RotationËš" name="TexRot"/>
+ <spinner label="Wiederholungen / Meter" name="rptctrl"/>
<button label="Ãœbernehmen" label_selected="Ãœbernehmen" name="button apply"/>
<text name="tex offset">
- Versatz
+ Texture-Versatz
</text>
<spinner label="Horizontal (U)" name="TexOffsetU"/>
<spinner label="Vertikal (V)" name="TexOffsetV"/>
- <text name="textbox autofix">
- Medientextur ausrichten
-(zuerst laden)
- </text>
- <button label="Ausrichten" label_selected="Ausrichten" name="button align"/>
+ <panel name="Add_Media">
+ <text name="media_tex">
+ Medien-URL
+ </text>
+ <button name="add_media" tool_tip="Medien hinzufügen"/>
+ <button name="delete_media" tool_tip="Diese Medien-Textur löschen"/>
+ <button name="edit_media" tool_tip="Diese Medien bearbeiten"/>
+ <button label="Ausrichten" label_selected="Medien angleichen" name="button align"/>
+ </panel>
</panel>
<panel label="Inhalt" name="Contents">
- <button label="Neues Skript" label_selected="Neues Skript..." name="button new script"/>
- <button label="Berechtigungen..." name="button permissions" width="118"/>
+ <button label="Neues Skript" label_selected="Neues Skript" name="button new script"/>
+ <button label="Berechtigungen" name="button permissions"/>
</panel>
</tab_container>
<panel name="land info panel">
@@ -564,62 +472,29 @@ Primitiv" name="sculpt texture control" tool_tip="Klicken Sie hier, um ein Bild
Parzelleninformation
</text>
<text name="label_area_price">
- Preis: L$ [PRICE] für [AREA] m2.
+ Preis: [PRICE] L$ für [AREA] m²
</text>
<text name="label_area">
- Fläche: [AREA] m2
+ Gebiet: [AREA] m².
</text>
- <button label="Info zu Land..." label_selected="Info zu Land..." name="button about land" width="110"/>
- <check_box label="Eigentümer anzeigen" name="checkbox show owners" tool_tip="Parzellen nach Eigentümer farbig kennzeichnen"/>
- <button label="?" label_selected="?" name="button show owners help" left_delta="130"/>
+ <button label="Ãœber Land" label_selected="Ãœber Land" name="button about land"/>
+ <check_box label="Eigentümer anzeigen" name="checkbox show owners" tool_tip="Die Parzellen farblich nach Eigentümtertyp anzeigen
+
+Grün = Ihr Land
+Blau = Das Land Ihrer Gruppe
+Rot = Im Eigentum anderer
+Geld = Zum Verkauf
+Lila = Zur Auktion
+Grau = Öffentlich"/>
<text name="label_parcel_modify">
Parzelle ändern
</text>
- <button label="Unterteilen..." label_selected="Unterteilen..." name="button subdivide land" width="110"/>
- <button label="Zusammenlegen" label_selected="Zusammenlegen" name="button join land" width="110"/>
+ <button label="Unterteilen" label_selected="Unterteilen" name="button subdivide land"/>
+ <button label="Zusammenlegen" label_selected="Zusammenlegen" name="button join land"/>
<text name="label_parcel_trans">
Land-Transaktionen
</text>
- <button label="Land kaufen..." label_selected="Land kaufen..." name="button buy land" width="110"/>
- <button label="Land aufgeben..." label_selected="Land aufgeben..." name="button abandon land" width="110"/>
+ <button label="Land kaufen" label_selected="Land kaufen" name="button buy land"/>
+ <button label="Land aufgeben" label_selected="Land aufgeben" name="button abandon land"/>
</panel>
- <string name="status_rotate">
- An den farbigen Bändern ziehen, um das Objekt zu drehen
- </string>
- <string name="status_scale">
- Klicken und ziehen, um die ausgewählte Seite zu dehnen
- </string>
- <string name="status_move">
- Maus verschiebt, Umschalt-Taste und Maus kopiert
- </string>
- <string name="status_modifyland">
- Klicken und halten, um das Land zu bearbeiten
- </string>
- <string name="status_camera">
- Klicken und ziehen, um die Ansicht zu ändern
- </string>
- <string name="status_grab">
- Ziehen, um Objekte zu verschieben, Strg zum Heben, Strg-Umschalt zum Drehen
- </string>
- <string name="status_place">
- Inworld klicken, um zu bauen.
- </string>
- <string name="status_selectland">
- Klicken und ziehen, um Land auszuwählen
- </string>
- <string name="grid_screen_text">
- Bildschirm
- </string>
- <string name="grid_local_text">
- Lokal
- </string>
- <string name="grid_world_text">
- Welt
- </string>
- <string name="grid_reference_text">
- Referenz
- </string>
- <string name="grid_attachment_text">
- Anhang
- </string>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_top_objects.xml b/indra/newview/skins/default/xui/de/floater_top_objects.xml
index f9e7becee1..579e5cbe7e 100644
--- a/indra/newview/skins/default/xui/de/floater_top_objects.xml
+++ b/indra/newview/skins/default/xui/de/floater_top_objects.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="top_objects" title="wird geladen...">
+<floater name="top_objects" title="WIRD GELDADEN...">
<text name="title_text">
Wird geladen...
</text>
diff --git a/indra/newview/skins/default/xui/de/floater_tos.xml b/indra/newview/skins/default/xui/de/floater_tos.xml
index 42f48fad4d..e11b453b41 100644
--- a/indra/newview/skins/default/xui/de/floater_tos.xml
+++ b/indra/newview/skins/default/xui/de/floater_tos.xml
@@ -1,22 +1,17 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="modal container" title=" ">
- <button label="Weiter" label_selected="Weiter" name="Continue" />
- <button label="Abbrechen" label_selected="Abbrechen" name="Cancel" />
+ <button label="Weiter" label_selected="Weiter" name="Continue"/>
+ <button label="Abbrechen" label_selected="Abbrechen" name="Cancel"/>
<radio_group name="tos_agreement">
- <radio_item name="radio_disagree">
- Ich stimme den Nutzungsbedingungen nicht zu
- </radio_item>
- <radio_item name="radio_agree">
- Ich stimme den Nutzungsbedingungen zu
- </radio_item>
+ <radio_item label="Ich stimme den Nutzungsbedingungen nicht zu" name="radio_disagree"/>
+ <radio_item label="Ich stimme den Nutzungsbedingungen zu" name="radio_agree"/>
</radio_group>
<text name="tos_title">
Nutzungsvereinbarung
</text>
- <check_box label="Ich stimme den Nutzungsbedingungen zu" name="agree_chk" />
+ <check_box label="Ich stimme den Nutzungsbedingungen zu" name="agree_chk"/>
<text name="tos_heading">
- Lesen Sie die folgenden Nutzungsbedingungen sorgfältig durch. Sie müssen dieser Vereinbarung
-zustimmen, um Second Life benutzen zu können.
+ Lesen Sie die folgenden Servicebedingungen sorgfältig durch. Sie müssen den Servicebedinungen zustimmen, um [SECOND_LIFE] weiterhin verwenden zu können.
</text>
<text_editor name="tos_text">
TOS_TEXT
diff --git a/indra/newview/skins/default/xui/de/floater_voice_controls.xml b/indra/newview/skins/default/xui/de/floater_voice_controls.xml
new file mode 100644
index 0000000000..39675beb45
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_voice_controls.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_voice_controls" title="Voice-Steuerung">
+ <panel name="control_panel">
+ <panel name="my_panel">
+ <text name="user_text" value="Mein Avatar:"/>
+ </panel>
+ <layout_stack>
+ <layout_panel>
+ <slider_bar name="volume_slider_bar" tool_tip="Master-Lautstärke"/>
+ </layout_panel>
+ </layout_stack>
+ </panel>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_water.xml b/indra/newview/skins/default/xui/de/floater_water.xml
index 95b469434a..ed18dfdfff 100644
--- a/indra/newview/skins/default/xui/de/floater_water.xml
+++ b/indra/newview/skins/default/xui/de/floater_water.xml
@@ -1,66 +1,53 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Water Floater" title="Erweiterter Wasser-Editor">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Water Floater" title="ERWEITERTER WASSER-EDITOR">
+ <floater.string name="WLDefaultWaterNames">
+ Default:Glassy:Pond:Murky:Second Plague:SNAKE!!!:Valdez
+ </floater.string>
<text name="KeyFramePresetsText">
Voreinstellungen:
</text>
- <button label="Neu" label_selected="Neu" name="WaterNewPreset" />
- <button label="Speichern" label_selected="Speichern" name="WaterSavePreset" />
- <button label="Löschen" label_selected="Löschen" name="WaterDeletePreset" />
+ <button label="Neu" label_selected="Neu" name="WaterNewPreset"/>
+ <button label="Speichern" label_selected="Speichern" name="WaterSavePreset"/>
+ <button label="Löschen" label_selected="Löschen" name="WaterDeletePreset"/>
<tab_container name="Water Tabs">
<panel label="Einstellungen" name="Settings">
<text name="BHText">
Wassertrübungsfarbe
</text>
- <button label=" ?" name="WaterFogColorHelp" left="175" />
- <color_swatch name="WaterFogColor" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen" />
+ <color_swatch name="WaterFogColor" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen"/>
<text name="WaterFogDensText">
Wassertrübungsdichte
</text>
- <button label=" ?" name="WaterFogDensityHelp" left="175" />
<text name="WaterUnderWaterFogModText">
Wassertrübungs-Modifikator
</text>
- <button label=" ?" name="WaterUnderWaterFogModHelp" left="175" />
- <slider bottom_delta="-34" name="WaterUnderWaterFogMod" />
+ <slider bottom_delta="-34" name="WaterUnderWaterFogMod"/>
<text name="BDensText">
Reflexionswellengröße
</text>
- <button label=" ?" name="WaterNormalScaleHelp" />
- <text name="BHText2">
- 1
- </text>
- <text name="BHText3">
- 2
- </text>
- <text name="BHText4">
- 3
- </text>
+ <slider label="1" name="WaterNormalScaleX"/>
+ <slider label="2" name="WaterNormalScaleY"/>
+ <slider label="3" name="WaterNormalScaleZ"/>
<text name="HDText">
Fresnel-Skalierung
</text>
- <button label=" ?" name="WaterFresnelScaleHelp" />
<text name="FresnelOffsetText">
Fresnel-Versatz
</text>
- <button label=" ?" name="WaterFresnelOffsetHelp" />
<text name="DensMultText">
Brechungsstärke oben
</text>
- <button label=" ?" name="WaterScaleAboveHelp" />
<text name="WaterScaleBelowText">
Brechungsstärke unten
</text>
- <button label=" ?" name="WaterScaleBelowHelp" />
<text name="MaxAltText">
Mischungsmultiplikator
</text>
- <button label=" ?" name="WaterBlurMultiplierHelp" />
</panel>
<panel label="Bild" name="Waves">
<text name="BHText">
Richtung große Welle
</text>
- <button label=" ?" name="WaterWave1Help" />
<text name="WaterWave1DirXText">
X
</text>
@@ -70,7 +57,6 @@
<text name="BHText2">
Richtung kleine Welle
</text>
- <button label=" ?" name="WaterWave2Help" />
<text name="WaterWave2DirXText">
X
</text>
@@ -80,10 +66,6 @@
<text name="BHText3">
Normal-Map
</text>
- <button label=" ?" name="WaterNormalMapHelp" />
</panel>
</tab_container>
- <string name="WLDefaultWaterNames">
- Default:Glassy:Pond:Murky:Second Plague:SNAKE!!!:Valdez
- </string>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_wearable_save_as.xml b/indra/newview/skins/default/xui/de/floater_wearable_save_as.xml
index 89e351e493..dad1b62975 100644
--- a/indra/newview/skins/default/xui/de/floater_wearable_save_as.xml
+++ b/indra/newview/skins/default/xui/de/floater_wearable_save_as.xml
@@ -2,7 +2,7 @@
<floater name="modal container" title=" ">
<button label="Speichern" label_selected="Speichern" name="Save" />
<button label="Abbrechen" label_selected="Abbrechen" name="Cancel" />
- <text type="string" length="1" name="Save item as:">
+ <text name="Save item as:">
Objekt speichern als:
</text>
<line_editor name="name ed">
diff --git a/indra/newview/skins/default/xui/de/floater_whitelist_entry.xml b/indra/newview/skins/default/xui/de/floater_whitelist_entry.xml
new file mode 100644
index 0000000000..a0bfc57e42
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_whitelist_entry.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="whitelist_entry">
+ <text name="media_label">
+ Eine URL oder URL
+ </text>
+ <line_editor name="whitelist_entry" tool_tip="Eine URL oder URL-Patten in die Whitelist eingeben"/>
+ <button label="OK" name="ok_btn"/>
+ <button label="Abbrechen" name="cancel_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_windlight_options.xml b/indra/newview/skins/default/xui/de/floater_windlight_options.xml
index 8df412dab6..3e06d8f06b 100644
--- a/indra/newview/skins/default/xui/de/floater_windlight_options.xml
+++ b/indra/newview/skins/default/xui/de/floater_windlight_options.xml
@@ -1,19 +1,18 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="WindLight floater" title="Erweiterter Himmel-Editor">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="WindLight floater" title="ERWEITERTER HIMMEL-EDITOR">
<text name="KeyFramePresetsText">
Voreinstellungen:
</text>
- <button label="Neu" label_selected="Neu" name="WLNewPreset" />
- <button label="Speichern" label_selected="Speichern" name="WLSavePreset" />
- <button label="Löschen" label_selected="Löschen" name="WLDeletePreset" />
- <button label="Tageszyklus-Editor" label_selected="Tageszyklus-Editor"
- name="WLDayCycleMenuButton" />
+ <button label="Neu" label_selected="Neu" name="WLNewPreset"/>
+ <button label="Speichern" label_selected="Speichern" name="WLSavePreset"/>
+ <button label="Löschen" label_selected="Löschen" name="WLDeletePreset"/>
+ <button label="Tageszyklus-Editor" label_selected="Tageszyklus-Editor" name="WLDayCycleMenuButton"/>
<tab_container name="WindLight Tabs">
<panel label="Atmosphäre" name="Atmosphere">
<text name="BHText">
Horizontfarbe
</text>
- <button label=" ?" name="WLBlueHorizonHelp" />
+ <button label=" ?" name="WLBlueHorizonHelp"/>
<text name="BHText2">
R
</text>
@@ -29,11 +28,11 @@
<text name="BDensText">
Horizonttrübung
</text>
- <button label=" ?" name="WLHazeHorizonHelp" />
+ <button label=" ?" name="WLHazeHorizonHelp"/>
<text name="BDensText2">
Farbintensität
</text>
- <button label=" ?" name="WLBlueDensityHelp" />
+ <button label=" ?" name="WLBlueDensityHelp"/>
<text name="BHText6">
R
</text>
@@ -49,25 +48,25 @@
<text name="HDText">
Trübungsintensität
</text>
- <button label=" ?" name="WLHazeDensityHelp" />
+ <button label=" ?" name="WLHazeDensityHelp"/>
<text name="DensMultText">
Dichtemultiplikator
</text>
- <button label=" ?" name="WLDensityMultHelp" />
+ <button label=" ?" name="WLDensityMultHelp"/>
<text name="WLDistanceMultText">
Entfernungsmultiplikator
</text>
- <button label=" ?" name="WLDistanceMultHelp" />
+ <button label=" ?" name="WLDistanceMultHelp"/>
<text name="MaxAltText">
Max. Höhe
</text>
- <button label=" ?" name="WLMaxAltitudeHelp" />
+ <button label=" ?" name="WLMaxAltitudeHelp"/>
</panel>
<panel label="Licht" name="Lighting">
<text name="SLCText">
Sonne/Mond-Farbe
</text>
- <button label=" ?" name="WLSunlightColorHelp" />
+ <button label=" ?" name="WLSunlightColorHelp"/>
<text name="BHText">
R
</text>
@@ -83,11 +82,11 @@
<text name="TODText">
Sonne/Mond-Stand
</text>
- <button label=" ?" name="WLTimeOfDayHelp" />
+ <button label=" ?" name="WLTimeOfDayHelp"/>
<text name="WLAmbientText">
Umgebung
</text>
- <button label=" ?" name="WLAmbientHelp" />
+ <button label=" ?" name="WLAmbientHelp"/>
<text name="BHText5">
R
</text>
@@ -103,27 +102,27 @@
<text name="WLEastAngleText">
Ostausrichtung
</text>
- <button label=" ?" name="WLEastAngleHelp" />
+ <button label=" ?" name="WLEastAngleHelp"/>
<text name="SunGlowText">
Sonnenleuchtkraft
</text>
- <button label=" ?" name="WLSunGlowHelp" />
- <slider label="Fokus " name="WLGlowB" />
- <slider label="Größe " name="WLGlowR" />
+ <button label=" ?" name="WLSunGlowHelp"/>
+ <slider label="Fokus " name="WLGlowB"/>
+ <slider label="Größe " name="WLGlowR"/>
<text name="SceneGammaText">
Gamma in Szene
</text>
- <button label=" ?" name="WLSceneGammaHelp" />
+ <button label=" ?" name="WLSceneGammaHelp"/>
<text name="WLStarText">
Sternenleuchtkraft
</text>
- <button label=" ?" name="WLStarBrightnessHelp" />
+ <button label=" ?" name="WLStarBrightnessHelp"/>
</panel>
<panel label="Wolken" name="Clouds">
<text name="WLCloudColorText">
Wolkenfarbe
</text>
- <button label=" ?" name="WLCloudColorHelp" />
+ <button label=" ?" name="WLCloudColorHelp"/>
<text name="BHText">
R
</text>
@@ -139,7 +138,7 @@
<text name="WLCloudColorText2">
Wolken-XY/Dichte
</text>
- <button label=" ?" name="WLCloudDensityHelp" />
+ <button label=" ?" name="WLCloudDensityHelp"/>
<text name="BHText5">
X
</text>
@@ -152,15 +151,15 @@
<text name="WLCloudCoverageText">
Wolkendichte
</text>
- <button label=" ?" name="WLCloudCoverageHelp" />
+ <button label=" ?" name="WLCloudCoverageHelp"/>
<text name="WLCloudScaleText">
Wolkenskalierung
</text>
- <button label=" ?" name="WLCloudScaleHelp" />
+ <button label=" ?" name="WLCloudScaleHelp"/>
<text name="WLCloudDetailText">
Wolkendetails (XY/Dichte)
</text>
- <button label=" ?" name="WLCloudDetailHelp" />
+ <button label=" ?" name="WLCloudDetailHelp"/>
<text name="BHText8">
X
</text>
@@ -173,15 +172,15 @@
<text name="WLCloudScrollXText">
Wolkenbewegung X
</text>
- <button label=" ?" name="WLCloudScrollXHelp" />
- <check_box label="Fest" name="WLCloudLockX" />
+ <button label=" ?" name="WLCloudScrollXHelp"/>
+ <check_box label="Fest" name="WLCloudLockX"/>
<text name="WLCloudScrollYText">
Wolkenbewegung Y
</text>
- <button label=" ?" name="WLCloudScrollYHelp" />
- <check_box label="Fest" name="WLCloudLockY" />
- <check_box label="Klassische Wolken" name="DrawClassicClouds" />
- <button label=" ?" name="WLClassicCloudsHelp" />
+ <button label=" ?" name="WLCloudScrollYHelp"/>
+ <check_box label="Fest" name="WLCloudLockY"/>
+ <check_box label="Klassische Wolken" name="DrawClassicClouds"/>
+ <button label=" ?" name="WLClassicCloudsHelp"/>
</panel>
</tab_container>
<string name="WLDefaultSkyNames">
diff --git a/indra/newview/skins/default/xui/de/floater_world_map.xml b/indra/newview/skins/default/xui/de/floater_world_map.xml
index d28b55e8a8..dd13623f91 100644
--- a/indra/newview/skins/default/xui/de/floater_world_map.xml
+++ b/indra/newview/skins/default/xui/de/floater_world_map.xml
@@ -1,9 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="worldmap" title="Weltkarte">
- <tab_container name="maptab">
- <panel label="Objekte" name="objects_mapview"/>
- <panel label="Terrain" name="terrain_mapview"/>
- </tab_container>
+<floater name="worldmap" title="KARTE">
<text name="you_label">
Sie
</text>
@@ -14,28 +10,24 @@
Auktion
</text>
<text font="SansSerifSmall" name="land_for_sale_label">
- Land erhaeltlich
+ Land zum Verkauf
</text>
<button label="Nach Hause" label_selected="Nach Hause" name="Go Home" tool_tip="Nach Hause teleportieren"/>
<check_box label="Einwohner" name="people_chk"/>
<check_box label="Infohub" name="infohub_chk"/>
- <check_box label="Telehub" name="telehubchk"/>
+ <check_box label="Telehub" name="telehub_chk"/>
<check_box label="Land zu verkaufen" name="land_for_sale_chk"/>
<text name="events_label">
Events:
</text>
<check_box label="PG" name="event_chk"/>
- <check_box label="Mature" name="event_mature_chk"/>
+ <check_box initial_value="true" label="Mature" name="event_mature_chk"/>
<check_box label="Adult" name="event_adult_chk"/>
<combo_box label="Online-Freunde" name="friend combo" tool_tip="Freund, der auf Karte angezeigt werden soll">
- <combo_item name="none_selected">
- Online-Freunde
- </combo_item>
+ <combo_box.item label="Online-Freunde" name="item1"/>
</combo_box>
<combo_box label="Landmarken" name="landmark combo" tool_tip="Landmarke, die auf Karte angezeigt werden soll">
- <combo_item name="none_selected">
- Landmarken
- </combo_item>
+ <combo_box.item label="Landmarken" name="item1"/>
</combo_box>
<line_editor label="Nach Regionsname suchen" name="location" tool_tip="Geben Sie den Namen einer Region ein"/>
<button label="Suchen" name="DoSearch" tool_tip="Nach einer Region suchen"/>
@@ -43,8 +35,8 @@
Suchergebnisse:
</text>
<scroll_list name="search_results">
- <column label="" name="icon"/>
- <column label="" name="sim_name"/>
+ <scroll_list.columns label="" name="icon"/>
+ <scroll_list.columns label="" name="sim_name"/>
</scroll_list>
<text name="location_label">
Standort:
@@ -56,6 +48,6 @@
<button label="Gesuchte Position" label_selected="Ziel anzeigen" name="Show Destination" tool_tip="Karte auf ausgewählte Position zentrieren"/>
<button label="Löschen" label_selected="Löschen" name="Clear" tool_tip="Verfolgung abschalten"/>
<button label="Meine Position" label_selected="Wo bin ich?" name="Show My Location" tool_tip="Karte auf Position Ihres Avatars zentrieren"/>
- <button font="SansSerifSmall" label="SLURL in die Zwischenablage kopieren" name="copy_slurl" tool_tip="Kopiert die aktuelle Position als SLURL zur Verwendung im Web."/>
+ <button font="SansSerifSmall" label="SLurl in die Zwischenablage kopieren" name="copy_slurl" tool_tip="Kopiert die aktuelle Position als SLurl zur Verwendung im Web."/>
<slider label="Zoom" name="zoom slider"/>
</floater>
diff --git a/indra/newview/skins/default/xui/de/inspect_avatar.xml b/indra/newview/skins/default/xui/de/inspect_avatar.xml
new file mode 100644
index 0000000000..91b7650376
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/inspect_avatar.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater name="inspect_avatar">
+ <string name="Subtitle">
+ [AGE]
+ </string>
+ <string name="Details">
+ [SL_PROFILE]
+ </string>
+ <string name="Partner">
+ Partner: [PARTNER]
+ </string>
+ <text name="user_name" value="Grumpity ProductEngine"/>
+ <text name="user_subtitle" value="11 Monate und 3 Tage alt"/>
+ <text name="user_details">
+ Dies ist meine Beschreibung und ich finde sie wirklich gut!
+ </text>
+ <text name="user_partner">
+ Erica Linden
+ </text>
+ <slider name="volume_slider" tool_tip="Lautstärke" value="0.5"/>
+ <button label="Freund hinzufügen" name="add_friend_btn"/>
+ <button label="IM" name="im_btn"/>
+ <button label="Mehr" name="view_profile_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/inspect_group.xml b/indra/newview/skins/default/xui/de/inspect_group.xml
new file mode 100644
index 0000000000..fa9764e420
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/inspect_group.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater name="inspect_group">
+ <string name="PrivateGroup">
+ Private Gruppe
+ </string>
+ <string name="FreeToJoin">
+ Mitgliedschaft kostenlos
+ </string>
+ <string name="CostToJoin">
+ Mitgliedschaft: [AMOUNT] L$
+ </string>
+ <string name="YouAreMember">
+ Sie sind Mitglied
+ </string>
+ <text name="group_name">
+ Grumpitys schlecht gelaunte Elche
+ </text>
+ <text name="group_subtitle">
+ 123 Mitglieder
+ </text>
+ <text name="group_details">
+ Eine Gruppe für Leute, die sich gerne mit Elchen unterhält.
+Hoch solln sie leben! Elche forever! Und auch Mungos!
+ </text>
+ <text name="group_cost">
+ Mitgliedschaft: 123 L$
+ </text>
+ <button label="Zusammen" name="join_btn"/>
+ <button label="Verlassen" name="leave_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/inspect_object.xml b/indra/newview/skins/default/xui/de/inspect_object.xml
new file mode 100644
index 0000000000..61f2cc8dc9
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/inspect_object.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater name="inspect_object">
+ <string name="Creator">
+ Von [CREATOR]
+ </string>
+ <string name="CreatorAndOwner">
+ von [CREATOR]
+Besitzer [OWNER]
+ </string>
+ <string name="Price">
+ [AMOUNT] L$
+ </string>
+ <string name="PriceFree">
+ Kostenlos!
+ </string>
+ <string name="Touch">
+ Berühren
+ </string>
+ <string name="Sit">
+ Sitzen
+ </string>
+ <text name="object_name" value="Wirklich langen Objektnamen als Test eingeben"/>
+ <text name="object_creator">
+ von secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
+Besitzer secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
+ </text>
+ <text name="price_text">
+ 300.000 L$
+ </text>
+ <text name="object_description">
+ Dies ist eine wirklich lange Beschreibung für ein Objekt, mindestens 80 Zeichen lang oder jetzt schon 120 Zeichen. Niemand weiß es genau.
+ </text>
+ <text name="object_media_url">
+ http://www.superdupertest.com
+ </text>
+ <button label="Kaufen" name="buy_btn"/>
+ <button label="Zahlen" name="pay_btn"/>
+ <button label="Kopie nehmen" name="take_free_copy_btn"/>
+ <button label="Berühren" name="touch_btn"/>
+ <button label="Sitzen" name="sit_btn"/>
+ <button label="Öffnen" name="open_btn"/>
+ <icon name="secure_browsing" tool_tip="Sicheres Browsen"/>
+ <button label="Mehr" name="more_info_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/inspect_remote_object.xml b/indra/newview/skins/default/xui/de/inspect_remote_object.xml
new file mode 100644
index 0000000000..9fe05455eb
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/inspect_remote_object.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater name="inspect_remote_object">
+ <text name="object_name">
+ Wirklich langen Objektnamen als Test eingeben
+ </text>
+ <text name="object_owner_label">
+ Eigentümer:
+ </text>
+ <text name="object_owner">
+ Langeravatarname Schmidtmeyermülllermuster
+ </text>
+ <text name="object_slurl_label">
+ Standort:
+ </text>
+ <text name="object_slurl">
+ http://slurl.com/Ahern/50/50/50
+ </text>
+ <button label="Karte" name="map_btn"/>
+ <button label="Ignorieren" name="block_btn"/>
+ <button label="Schließen" name="close_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/language_settings.xml b/indra/newview/skins/default/xui/de/language_settings.xml
new file mode 100644
index 0000000000..71418d446a
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/language_settings.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- This file contains strings that used to be hardcoded in the source.-->
+<strings>
+
+ <!-- Locale Information -->
+ <string name="MicrosoftLocale">english</string>
+ <string name="DarwinLocale">C</string>
+ <string name="LinuxLocale">C</string>
+
+ <!--
+ datetimeToCodes["wkday"] = "%a"; // Thu
+ datetimeToCodes["weekday"] = "%A"; // Thursday
+ datetimeToCodes["year4"] = "%Y"; // 2009
+ datetimeToCodes["year"] = "%Y"; // 2009
+ datetimeToCodes["year2"] = "%y"; // 09
+ datetimeToCodes["mth"] = "%b"; // Aug
+ datetimeToCodes["month"] = "%B"; // August
+ datetimeToCodes["mthnum"] = "%m"; // 08
+ datetimeToCodes["day"] = "%d"; // 31
+ datetimeToCodes["hour24"] = "%H"; // 14
+ datetimeToCodes["hour"] = "%H"; // 14
+ datetimeToCodes["hour12"] = "%I"; // 02
+ datetimeToCodes["min"] = "%M"; // 59
+ datetimeToCodes["ampm"] = "%p"; // AM
+ datetimeToCodes["second"] = "%S"; // 59
+ datetimeToCodes["timezone"] = "%Z"; // PST
+ -->
+
+ <string name="TimeHour">hour,datetime,slt</string>
+ <string name="TimeMin">min,datetime,slt</string>
+ <string name="TimeYear">year,datetime,slt</string>
+ <string name="TimeDay">day,datetime,slt</string>
+ <string name="TimeMonth">mthnum,datetime,slt</string>
+ <string name="TimeWeek">wkday,datetime,slt</string>
+ <string name="TimeAMPM">ampm,datetime,slt</string>
+ <string name="TimeHour12">hour12,datetime,slt</string>
+
+ <string name="LTimeMthNum">mthnum,datetime,local</string>
+ <string name="LTimeWeek">wkday,datetime,local</string>
+ <string name="LTimeMonth">mth,datetime,local</string>
+ <string name="LTimeDay">day,datetime,local</string>
+ <string name="LTimeSec">second,datetime,local</string>
+ <string name="LTimeHour">hour,datetime,local</string>
+ <string name="LTimeMin">min,datetime,local</string>
+ <string name="LTimeYear">year,datetime,local</string>
+
+ <string name="UTCTimeWeek">weekday,datetime,utc</string>
+ <string name="UTCTimeDay">day,datetime,utc</string>
+ <string name="UTCTimeMth">mth,datetime,utc</string>
+ <string name="UTCTimeYr">year,datetime,utc</string>
+ <string name="UTCTimeHr">hour,datetime,utc</string>
+ <string name="UTCTimeMin">min,datetime,utc</string>
+ <string name="UTCTimeSec">second,datetime,utc</string>
+ <string name="UTCTimeTimezone">timezone,datetime,utc</string>
+</strings>
diff --git a/indra/newview/skins/default/xui/de/menu_avatar_icon.xml b/indra/newview/skins/default/xui/de/menu_avatar_icon.xml
new file mode 100644
index 0000000000..b1e119c66a
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_avatar_icon.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Avatar Icon Menu">
+ <menu_item_call label="Profil anzeigen..." name="Show Profile"/>
+ <menu_item_call label="IM senden..." name="Send IM"/>
+ <menu_item_call label="Freund hinzufügen..." name="Add Friend"/>
+ <menu_item_call label="Freund entfernen..." name="Remove Friend"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_bottomtray.xml b/indra/newview/skins/default/xui/de/menu_bottomtray.xml
new file mode 100644
index 0000000000..246275bee1
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_bottomtray.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="hide_camera_move_controls_menu">
+ <menu_item_check label="Schaltfläche Gesten" name="ShowGestureButton"/>
+ <menu_item_check label="Schaltfläche Bewegungssteuerung" name="ShowMoveButton"/>
+ <menu_item_check label="Schaltfläche Ansicht" name="ShowCameraButton"/>
+ <menu_item_check label="Schaltfläche Foto" name="ShowSnapshotButton"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_favorites.xml b/indra/newview/skins/default/xui/de/menu_favorites.xml
new file mode 100644
index 0000000000..0d0491d2eb
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_favorites.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Popup">
+ <menu_item_call label="Teleportieren" name="Teleport To Landmark"/>
+ <menu_item_call label="Landmarken anzeigen/bearbeiten" name="Landmark Open"/>
+ <menu_item_call label="SLurl kopieren" name="Copy slurl"/>
+ <menu_item_call label="Auf Karte zeigen" name="Show On Map"/>
+ <menu_item_call label="Kopieren" name="Landmark Copy"/>
+ <menu_item_call label="Einfügen" name="Landmark Paste"/>
+ <menu_item_call label="Löschen" name="Delete"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_gesture_gear.xml b/indra/newview/skins/default/xui/de/menu_gesture_gear.xml
new file mode 100644
index 0000000000..953c0eeed5
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_gesture_gear.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_gesture_gear">
+ <menu_item_call label="Zu Favoriten hinzufügen/daraus entfernen" name="activate"/>
+ <menu_item_call label="Kopieren" name="copy_gesture"/>
+ <menu_item_call label="Einfügen" name="paste"/>
+ <menu_item_call label="UUID kopieren" name="copy_uuid"/>
+ <menu_item_call label="Aktuelles Outfit speichern" name="save_to_outfit"/>
+ <menu_item_call label="Bearbeiten" name="edit_gesture"/>
+ <menu_item_call label="Untersuchen" name="inspect"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_group_plus.xml b/indra/newview/skins/default/xui/de/menu_group_plus.xml
new file mode 100644
index 0000000000..583ee793be
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_group_plus.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_call label="Werden Sie Mitglied..." name="item_join"/>
+ <menu_item_call label="Neue Gruppe..." name="item_new"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_hide_navbar.xml b/indra/newview/skins/default/xui/de/menu_hide_navbar.xml
new file mode 100644
index 0000000000..32a6823b35
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_hide_navbar.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="hide_navbar_menu">
+ <menu_item_check label="Navigationsleiste anzeigen" name="ShowNavbarNavigationPanel"/>
+ <menu_item_check label="Favoritenleiste anzeigen" name="ShowNavbarFavoritesPanel"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_imchiclet_group.xml b/indra/newview/skins/default/xui/de/menu_imchiclet_group.xml
new file mode 100644
index 0000000000..81ef3b6569
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_imchiclet_group.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="IMChiclet Group Menu">
+ <menu_item_call label="Gruppeninfo" name="Show Profile"/>
+ <menu_item_call label="Sitzung anzeigen" name="Chat"/>
+ <menu_item_call label="Sitzung beenden" name="End Session"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_imchiclet_p2p.xml b/indra/newview/skins/default/xui/de/menu_imchiclet_p2p.xml
new file mode 100644
index 0000000000..d123238246
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_imchiclet_p2p.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="IMChiclet P2P Menu">
+ <menu_item_call label="Profil anzeigen" name="Show Profile"/>
+ <menu_item_call label="Freund hinzufügen" name="Add Friend"/>
+ <menu_item_call label="Sitzung anzeigen" name="Send IM"/>
+ <menu_item_call label="Sitzung beenden" name="End Session"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_inspect_avatar_gear.xml b/indra/newview/skins/default/xui/de/menu_inspect_avatar_gear.xml
new file mode 100644
index 0000000000..128bcdb86a
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_inspect_avatar_gear.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu name="Gear Menu">
+ <menu_item_call label="Profil anzeigen" name="view_profile"/>
+ <menu_item_call label="Freund hinzufügen" name="add_friend"/>
+ <menu_item_call label="IM" name="im"/>
+ <menu_item_call label="Anrufen" name="call"/>
+ <menu_item_call label="Teleportieren" name="teleport"/>
+ <menu_item_call label="In Gruppe einladen" name="invite_to_group"/>
+ <menu_item_call label="Ignorieren" name="block"/>
+ <menu_item_call label="Melden" name="report"/>
+ <menu_item_call label="Einfrieren" name="freeze"/>
+ <menu_item_call label="Hinauswerfen" name="eject"/>
+ <menu_item_call label="Debug" name="debug"/>
+ <menu_item_call label="Auf Karte anzeigen" name="find_on_map"/>
+ <menu_item_call label="Hineinzoomen" name="zoom_in"/>
+ <menu_item_call label="Zahlen" name="pay"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/de/menu_inspect_object_gear.xml
new file mode 100644
index 0000000000..5efee8617b
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_inspect_object_gear.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu name="Gear Menu">
+ <menu_item_call label="Berühren" name="touch"/>
+ <menu_item_call label="Sitzen" name="sit"/>
+ <menu_item_call label="Zahlen" name="pay"/>
+ <menu_item_call label="Kaufen" name="buy"/>
+ <menu_item_call label="Nehmen" name="take"/>
+ <menu_item_call label="Kopie nehmen" name="take_copy"/>
+ <menu_item_call label="Öffnen" name="open"/>
+ <menu_item_call label="Bearbeiten" name="edit"/>
+ <menu_item_call label="Anziehen" name="wear"/>
+ <menu_item_call label="Melden" name="report"/>
+ <menu_item_call label="Ignorieren" name="block"/>
+ <menu_item_call label="Hineinzoomen" name="zoom_in"/>
+ <menu_item_call label="Entfernen" name="remove"/>
+ <menu_item_call label="Weitere Infos" name="more_info"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_inspect_self_gear.xml b/indra/newview/skins/default/xui/de/menu_inspect_self_gear.xml
new file mode 100644
index 0000000000..383ee7831e
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_inspect_self_gear.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu name="Gear Menu">
+ <menu_item_call label="Aufstehen" name="stand_up"/>
+ <menu_item_call label="Mein Aussehen" name="my_appearance"/>
+ <menu_item_call label="Mein Profil" name="my_profile"/>
+ <menu_item_call label="Meine Freunde" name="my_friends"/>
+ <menu_item_call label="Meine Gruppen" name="my_groups"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_inventory.xml b/indra/newview/skins/default/xui/de/menu_inventory.xml
index e05b2e9f1a..fcdfc8b9e0 100644
--- a/indra/newview/skins/default/xui/de/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/de/menu_inventory.xml
@@ -12,7 +12,7 @@
<menu_item_call label="Neues Skript" name="New Script"/>
<menu_item_call label="Neue Notiz" name="New Note"/>
<menu_item_call label="Neue Geste" name="New Gesture"/>
- <menu name="New Clothes">
+ <menu label="Neue Kleider" name="New Clothes">
<menu_item_call label="Neues Hemd" name="New Shirt"/>
<menu_item_call label="Neue Hose" name="New Pants"/>
<menu_item_call label="Neue Schuhe" name="New Shoes"/>
@@ -22,31 +22,47 @@
<menu_item_call label="Neue Handschuhe" name="New Gloves"/>
<menu_item_call label="Neues Unterhemd" name="New Undershirt"/>
<menu_item_call label="Neue Unterhose" name="New Underpants"/>
+ <menu_item_call label="Neue Alpha-Maske" name="New Alpha Mask"/>
+ <menu_item_call label="Neue Tätowierung" name="New Tattoo"/>
</menu>
- <menu name="New Body Parts">
+ <menu label="Neue Körperteile" name="New Body Parts">
<menu_item_call label="Neue Form/Gestalt" name="New Shape"/>
<menu_item_call label="Neue Haut" name="New Skin"/>
<menu_item_call label="Neues Haar" name="New Hair"/>
<menu_item_call label="Neue Augen" name="New Eyes"/>
</menu>
+ <menu label="Typ ändern" name="Change Type">
+ <menu_item_call label="Standard" name="Default"/>
+ <menu_item_call label="Handschuhe" name="Gloves"/>
+ <menu_item_call label="Jacke" name="Jacket"/>
+ <menu_item_call label="Hose" name="Pants"/>
+ <menu_item_call label="Form" name="Shape"/>
+ <menu_item_call label="Schuhe" name="Shoes"/>
+ <menu_item_call label="Hemd" name="Shirt"/>
+ <menu_item_call label="Rock" name="Skirt"/>
+ <menu_item_call label="Unterhose" name="Underpants"/>
+ <menu_item_call label="Unterhemd" name="Undershirt"/>
+ </menu>
<menu_item_call label="Teleportieren" name="Landmark Open"/>
<menu_item_call label="Öffnen" name="Animation Open"/>
<menu_item_call label="Öffnen" name="Sound Open"/>
<menu_item_call label="Objekt löschen" name="Purge Item"/>
<menu_item_call label="Objekt wiederherstellen" name="Restore Item"/>
+ <menu_item_call label="Original suchen" name="Find Original"/>
<menu_item_call label="Öffnen" name="Open"/>
<menu_item_call label="Eigenschaften" name="Properties"/>
<menu_item_call label="Umbenennen" name="Rename"/>
<menu_item_call label="Asset-UUID kopieren" name="Copy Asset UUID"/>
<menu_item_call label="Kopieren" name="Copy"/>
<menu_item_call label="Einfügen" name="Paste"/>
+ <menu_item_call label="Als Link einfügen" name="Paste As Link"/>
<menu_item_call label="Löschen" name="Delete"/>
- <menu_item_call label="Objekte abnehmen" name="Take Off Items"/>
+ <menu_item_call label="Von Outfit entfernen" name="Remove From Outfit"/>
<menu_item_call label="Zum Outfit hinzufügen" name="Add To Outfit"/>
<menu_item_call label="Outfit ersetzen" name="Replace Outfit"/>
<menu_item_call label="Konferenz-Chat starten" name="Conference Chat Folder"/>
<menu_item_call label="Wiedergeben/Abspielen" name="Sound Play"/>
- <menu_item_call label="Landmarken-Info" name="Teleport To Landmark"/>
+ <menu_item_call label="Landmarken-Info" name="About Landmark"/>
<menu_item_call label="In Welt abspielen" name="Animation Play"/>
<menu_item_call label="Lokal wiedergeben" name="Animation Audition"/>
<menu_item_call label="Instant Message senden" name="Send Instant Message"/>
@@ -54,8 +70,8 @@
<menu_item_call label="Konferenz-Chat starten" name="Conference Chat"/>
<menu_item_call label="Aktivieren" name="Activate"/>
<menu_item_call label="Deaktivieren" name="Deactivate"/>
+ <menu_item_call label="Speichern unter" name="Save As"/>
<menu_item_call label="Von Körper abnehmen" name="Detach From Yourself"/>
- <menu_item_call label="Zu letzter Position zurücksetzen" name="Restore to Last Position"/>
<menu_item_call label="Anziehen" name="Object Wear"/>
<menu label="Anhängen an" name="Attach To"/>
<menu label="An HUD hängen" name="Attach To HUD"/>
diff --git a/indra/newview/skins/default/xui/de/menu_inventory_add.xml b/indra/newview/skins/default/xui/de/menu_inventory_add.xml
new file mode 100644
index 0000000000..f6b7e51325
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_inventory_add.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_inventory_add">
+ <menu label="Hochladen" name="upload">
+ <menu_item_call label="Bild ([COST] L$)..." name="Upload Image"/>
+ <menu_item_call label="Sound ([COST] L$)..." name="Upload Sound"/>
+ <menu_item_call label="Animation ([COST] L$)..." name="Upload Animation"/>
+ <menu_item_call label="Mehrfach-Upload ([COST] L$ pro Datei)..." name="Bulk Upload"/>
+ </menu>
+ <menu_item_call label="Neuer Ordner" name="New Folder"/>
+ <menu_item_call label="Neues Skript" name="New Script"/>
+ <menu_item_call label="Neue Notiz" name="New Note"/>
+ <menu_item_call label="Neue Geste" name="New Gesture"/>
+ <menu label="Neue Kleider" name="New Clothes">
+ <menu_item_call label="Neues Hemd" name="New Shirt"/>
+ <menu_item_call label="Neue Hose" name="New Pants"/>
+ <menu_item_call label="Neue Schuhe" name="New Shoes"/>
+ <menu_item_call label="Neue Socken" name="New Socks"/>
+ <menu_item_call label="Neue Jacke" name="New Jacket"/>
+ <menu_item_call label="Neuer Rock" name="New Skirt"/>
+ <menu_item_call label="Neue Handschuhe" name="New Gloves"/>
+ <menu_item_call label="Neues Unterhemd" name="New Undershirt"/>
+ <menu_item_call label="Neue Unterhose" name="New Underpants"/>
+ <menu_item_call label="Alpha: Neu" name="New Alpha"/>
+ <menu_item_call label="Neue Tätowierung" name="New Tattoo"/>
+ </menu>
+ <menu label="Neue Körperteile" name="New Body Parts">
+ <menu_item_call label="Neue Form/Gestalt" name="New Shape"/>
+ <menu_item_call label="Neue Haut" name="New Skin"/>
+ <menu_item_call label="Neues Haar" name="New Hair"/>
+ <menu_item_call label="Neue Augen" name="New Eyes"/>
+ </menu>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_inventory_gear_default.xml b/indra/newview/skins/default/xui/de/menu_inventory_gear_default.xml
new file mode 100644
index 0000000000..69f9b86d75
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_inventory_gear_default.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_gear_default">
+ <menu_item_call label="Fenster: Neues Inventar" name="new_window"/>
+ <menu_item_call label="Nach Name sortieren" name="sort_by_name"/>
+ <menu_item_call label="Nach aktuellesten Objekten sortieren" name="sort_by_recent"/>
+ <menu_item_call label="Filter anzeigen" name="show_filters"/>
+ <menu_item_call label="Filter zurücksetzen" name="reset_filters"/>
+ <menu_item_call label="Alle Ordner schließen" name="close_folders"/>
+ <menu_item_call label="Papierkorb ausleeren" name="empty_trash"/>
+ <menu_item_call label="Fundbüro ausleeren" name="empty_lostnfound"/>
+ <menu_item_call label="Textur speichern als" name="Save Texture As"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_landmark.xml b/indra/newview/skins/default/xui/de/menu_landmark.xml
new file mode 100644
index 0000000000..2aff0eec95
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_landmark.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="landmark_overflow_menu">
+ <menu_item_call label="SLurl kopieren" name="copy"/>
+ <menu_item_call label="Löschen" name="delete"/>
+ <menu_item_call label="Auswahl erstellen" name="pick"/>
+ <menu_item_call label="Zu Favoritenleiste hinzufügen" name="add_to_favbar"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_login.xml b/indra/newview/skins/default/xui/de/menu_login.xml
index 29330d894a..26c2a4c2f4 100644
--- a/indra/newview/skins/default/xui/de/menu_login.xml
+++ b/indra/newview/skins/default/xui/de/menu_login.xml
@@ -1,13 +1,34 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<menu_bar name="Login Menu">
- <menu label="Datei" name="File">
- <menu_item_call label="Beenden" name="Quit" />
- </menu>
- <menu label="Bearbeiten" name="Edit">
- <menu_item_call label="Einstellungen..." name="Preferences..." />
+ <menu label="Ich" name="File">
+ <menu_item_call label="Einstellungen" name="Preferences..."/>
+ <menu_item_call label="[APP_NAME] schließen" name="Quit"/>
</menu>
<menu label="Hilfe" name="Help">
- <menu_item_call label="Hilfe zu Second Life" name="Second Life Help" />
- <menu_item_call label="Ãœber Second Life..." name="About Second Life..." />
+ <menu_item_call label="[SECOND_LIFE]-Hilfe" name="Second Life Help"/>
+ <menu_item_call label="INFO ÃœBER [APP_NAME]" name="About Second Life"/>
+ </menu>
+ <menu label="Debug" name="Debug">
+ <menu label="Bearbeiten" name="Edit">
+ <menu_item_call label="Rückgängig" name="Undo"/>
+ <menu_item_call label="Wiederherstellen" name="Redo"/>
+ <menu_item_call label="Ausschneiden" name="Cut"/>
+ <menu_item_call label="Kopieren" name="Copy"/>
+ <menu_item_call label="Einfügen" name="Paste"/>
+ <menu_item_call label="Löschen" name="Delete"/>
+ <menu_item_call label="Duplizieren" name="Duplicate"/>
+ <menu_item_call label="Alle auswählen" name="Select All"/>
+ <menu_item_call label="Auswahl aufheben" name="Deselect"/>
+ </menu>
+ <menu_item_call label="Debug-Einstellungen anzeigen" name="Debug Settings"/>
+ <menu_item_call label="UI/Farb-Einstellungen" name="UI/Color Settings"/>
+ <menu_item_call label="XUI-Editor" name="UI Preview Tool"/>
+ <menu_item_call label="Seitenleiste anzeigen" name="Show Side Tray"/>
+ <menu_item_call label="Widget testen" name="Widget Test"/>
+ <menu_item_call label="Inspektor-Test" name="Inspectors Test"/>
+ <menu_item_check label="Reg In Client Test (Neustart)" name="Reg In Client Test (restart)"/>
+ <menu_item_call label="Servicebedingungen anzeigen" name="TOS"/>
+ <menu_item_call label="Wichtige Meldung anzeigen" name="Critical"/>
+ <menu_item_call label="Web-Browser-Test" name="Web Browser Test"/>
</menu>
</menu_bar>
diff --git a/indra/newview/skins/default/xui/de/menu_mini_map.xml b/indra/newview/skins/default/xui/de/menu_mini_map.xml
index 9b7117cf42..a3ebfb3b10 100644
--- a/indra/newview/skins/default/xui/de/menu_mini_map.xml
+++ b/indra/newview/skins/default/xui/de/menu_mini_map.xml
@@ -3,6 +3,7 @@
<menu_item_call label="Zoom Nah" name="Zoom Close"/>
<menu_item_call label="Zoom Mittel" name="Zoom Medium"/>
<menu_item_call label="Zoom Weit" name="Zoom Far"/>
+ <menu_item_check label="Karte drehen" name="Rotate Map"/>
<menu_item_call label="Verfolgung abschalten" name="Stop Tracking"/>
- <menu_item_call label="Profil..." name="Profile"/>
+ <menu_item_call label="Weltkarte" name="World Map"/>
</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_navbar.xml b/indra/newview/skins/default/xui/de/menu_navbar.xml
new file mode 100644
index 0000000000..5175f34b41
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_navbar.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Navbar Menu">
+ <menu_item_check label="Koordinaten anzeigen" name="Show Coordinates"/>
+ <menu_item_check label="Parzelleneigenschaften anzeigen" name="Show Parcel Properties"/>
+ <menu_item_call label="Landmarke" name="Landmark"/>
+ <menu_item_call label="Ausschneiden" name="Cut"/>
+ <menu_item_call label="Kopieren" name="Copy"/>
+ <menu_item_call label="Einfügen" name="Paste"/>
+ <menu_item_call label="Löschen" name="Delete"/>
+ <menu_item_call label="Alle auswählen" name="Select All"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_nearby_chat.xml b/indra/newview/skins/default/xui/de/menu_nearby_chat.xml
new file mode 100644
index 0000000000..99d6428c3f
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_nearby_chat.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="NearBy Chat Menu">
+ <menu_item_call label="Leute in der Nähe anzeigen..." name="nearby_people"/>
+ <menu_item_check label="Ignorierten Text anzeigen" name="muted_text"/>
+ <menu_item_check label="Bilder von Freunden anzeigen" name="show_buddy_icons"/>
+ <menu_item_check label="Namen anzeigen" name="show_names"/>
+ <menu_item_check label="Namen und Symbole anzeigen" name="show_icons_and_names"/>
+ <menu_item_call label="Schriftgröße" name="font_size"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_object_icon.xml b/indra/newview/skins/default/xui/de/menu_object_icon.xml
new file mode 100644
index 0000000000..8b6c558416
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_object_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Object Icon Menu">
+ <menu_item_call label="Objektprofil..." name="Object Profile"/>
+ <menu_item_call label="Ignorieren..." name="Block"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_participant_list.xml b/indra/newview/skins/default/xui/de/menu_participant_list.xml
new file mode 100644
index 0000000000..042123cde4
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_participant_list.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Participant List Context Menu">
+ <menu_item_check label="Text stummschalten" name="MuteText"/>
+ <menu_item_check label="Text-Chat zulassen" name="AllowTextChat"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_people_friends_view_sort.xml b/indra/newview/skins/default/xui/de/menu_people_friends_view_sort.xml
new file mode 100644
index 0000000000..9d50a42ed4
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_people_friends_view_sort.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Nach Name sortieren" name="sort_name"/>
+ <menu_item_check label="Nach Status sortieren" name="sort_status"/>
+ <menu_item_check label="Symbole für Personen anzeigen" name="view_icons"/>
+ <menu_item_call label="Ignorierte Einwohner &amp; Objekte anzeigen" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_people_groups_view_sort.xml b/indra/newview/skins/default/xui/de/menu_people_groups_view_sort.xml
new file mode 100644
index 0000000000..b68597d8aa
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_people_groups_view_sort.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Gruppensymbole anzeigen" name="Display Group Icons"/>
+ <menu_item_call label="Ausgewählte Gruppe verlassen" name="Leave Selected Group"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_people_nearby.xml b/indra/newview/skins/default/xui/de/menu_people_nearby.xml
new file mode 100644
index 0000000000..ef58b4136e
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_people_nearby.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Avatar Context Menu">
+ <menu_item_call label="Profil anzeigen" name="View Profile"/>
+ <menu_item_call label="Freund hinzufügen" name="Add Friend"/>
+ <menu_item_call label="IM" name="IM"/>
+ <menu_item_call label="Anrufen" name="Call"/>
+ <menu_item_call label="Teilen" name="Share"/>
+ <menu_item_call label="Zahlen" name="Pay"/>
+ <menu_item_check label="Ignorieren/Freischalten" name="Block/Unblock"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_people_nearby_multiselect.xml b/indra/newview/skins/default/xui/de/menu_people_nearby_multiselect.xml
new file mode 100644
index 0000000000..d572a8ca1c
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_people_nearby_multiselect.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Multi-Selected People Context Menu">
+ <menu_item_call label="Freunde hinzufügen" name="Add Friends"/>
+ <menu_item_call label="IM" name="IM"/>
+ <menu_item_call label="Anrufen" name="Call"/>
+ <menu_item_call label="Teilen" name="Share"/>
+ <menu_item_call label="Zahlen" name="Pay"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_people_nearby_view_sort.xml b/indra/newview/skins/default/xui/de/menu_people_nearby_view_sort.xml
new file mode 100644
index 0000000000..d0881ddd05
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_people_nearby_view_sort.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Nach letzten Sprechern sortieren" name="sort_by_recent_speakers"/>
+ <menu_item_check label="Nach Name sortieren" name="sort_name"/>
+ <menu_item_check label="Nach Entfernung sortieren" name="sort_distance"/>
+ <menu_item_check label="Profilbilder anzeigen" name="view_icons"/>
+ <menu_item_call label="Zeige geblockte Einwohner &amp; Objekte" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_people_recent_view_sort.xml b/indra/newview/skins/default/xui/de/menu_people_recent_view_sort.xml
new file mode 100644
index 0000000000..837983b716
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_people_recent_view_sort.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Nach aktuellesten Objekten sortieren" name="sort_most"/>
+ <menu_item_check label="Nach Name sortieren" name="sort_name"/>
+ <menu_item_check label="Symbole für Personen anzeigen" name="view_icons"/>
+ <menu_item_call label="Ignorierte Einwohner &amp; Objekte anzeigen" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_picks.xml b/indra/newview/skins/default/xui/de/menu_picks.xml
new file mode 100644
index 0000000000..9aec4c83b0
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_picks.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Picks">
+ <menu_item_call label="Info" name="pick_info"/>
+ <menu_item_call label="Bearbeiten" name="pick_edit"/>
+ <menu_item_call label="Teleportieren" name="pick_teleport"/>
+ <menu_item_call label="Karte" name="pick_map"/>
+ <menu_item_call label="Löschen" name="pick_delete"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_picks_plus.xml b/indra/newview/skins/default/xui/de/menu_picks_plus.xml
new file mode 100644
index 0000000000..385ff25b95
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_picks_plus.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="picks_plus_menu">
+ <menu_item_call label="Neue Auswahl" name="create_pick"/>
+ <menu_item_call label="Neue Anzeige" name="create_classified"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_place.xml b/indra/newview/skins/default/xui/de/menu_place.xml
new file mode 100644
index 0000000000..d9c85f5b92
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_place.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="place_overflow_menu">
+ <menu_item_call label="Eine Landmarke setzen" name="landmark"/>
+ <menu_item_call label="Auswahl erstellen" name="pick"/>
+ <menu_item_call label="Pass kaufen" name="pass"/>
+ <menu_item_call label="Bearbeiten" name="edit"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_place_add_button.xml b/indra/newview/skins/default/xui/de/menu_place_add_button.xml
new file mode 100644
index 0000000000..7c0ff4a46a
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_place_add_button.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_folder_gear">
+ <menu_item_call label="Ordner hinzufügen" name="add_folder"/>
+ <menu_item_call label="Landmarke hinzufügen" name="add_landmark"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_places_gear_folder.xml b/indra/newview/skins/default/xui/de/menu_places_gear_folder.xml
new file mode 100644
index 0000000000..132d3f6466
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_places_gear_folder.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_folder_gear">
+ <menu_item_call label="Landmarke hinzufügen" name="add_landmark"/>
+ <menu_item_call label="Ordner hinzufügen" name="add_folder"/>
+ <menu_item_call label="Ausschneiden" name="cut"/>
+ <menu_item_call label="Kopieren" name="copy_folder"/>
+ <menu_item_call label="Einfügen" name="paste"/>
+ <menu_item_call label="Umbenennen" name="rename"/>
+ <menu_item_call label="Löschen" name="delete"/>
+ <menu_item_call label="Erweitern Sie sich" name="expand"/>
+ <menu_item_call label="Zuklappen" name="collapse"/>
+ <menu_item_call label="Alle Ordner aufklappen" name="expand_all"/>
+ <menu_item_call label="Alle Ordner schließen" name="collapse_all"/>
+ <menu_item_check label="Nach Datum sortieren" name="sort_by_date"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_places_gear_landmark.xml b/indra/newview/skins/default/xui/de/menu_places_gear_landmark.xml
new file mode 100644
index 0000000000..6af4d644af
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_places_gear_landmark.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_ladmark_gear">
+ <menu_item_call label="Teleportieren" name="teleport"/>
+ <menu_item_call label="Weitere Informationen" name="more_info"/>
+ <menu_item_call label="Auf Karte zeigen" name="show_on_map"/>
+ <menu_item_call label="Landmarke hinzufügen" name="add_landmark"/>
+ <menu_item_call label="Ordner hinzufügen" name="add_folder"/>
+ <menu_item_call label="Ausschneiden" name="cut"/>
+ <menu_item_call label="Landmarke kopieren" name="copy_landmark"/>
+ <menu_item_call label="SLurl kopieren" name="copy_slurl"/>
+ <menu_item_call label="Einfügen" name="paste"/>
+ <menu_item_call label="Umbenennen" name="rename"/>
+ <menu_item_call label="Löschen" name="delete"/>
+ <menu_item_call label="Alle Ordner aufklappen" name="expand_all"/>
+ <menu_item_call label="Alle Ordner schließen" name="collapse_all"/>
+ <menu_item_check label="Nach Datum sortieren" name="sort_by_date"/>
+ <menu_item_call label="Auswahl erstellen" name="create_pick"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_profile_overflow.xml b/indra/newview/skins/default/xui/de/menu_profile_overflow.xml
new file mode 100644
index 0000000000..89b56d1571
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_profile_overflow.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="profile_overflow_menu">
+ <menu_item_call label="Zahlen" name="pay"/>
+ <menu_item_call label="Teilen" name="share"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_slurl.xml b/indra/newview/skins/default/xui/de/menu_slurl.xml
index d9793e5906..b2ec017f9f 100644
--- a/indra/newview/skins/default/xui/de/menu_slurl.xml
+++ b/indra/newview/skins/default/xui/de/menu_slurl.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<menu name="Popup">
- <menu_item_call label="URL-Info" name="about_url" />
- <menu_item_call label="Zu URL teleportieren" name="teleport_to_url" />
- <menu_item_call label="Auf Karte" name="show_on_map" />
+ <menu_item_call label="URL-Info" name="about_url"/>
+ <menu_item_call label="Zu URL teleportieren" name="teleport_to_url"/>
+ <menu_item_call label="Karte" name="show_on_map"/>
</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_teleport_history_gear.xml b/indra/newview/skins/default/xui/de/menu_teleport_history_gear.xml
new file mode 100644
index 0000000000..2bfdadf22a
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_teleport_history_gear.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Teleport History Gear Context Menu">
+ <menu_item_call label="Alle Ordner aufklappen" name="Expand all folders"/>
+ <menu_item_call label="Alle Ordner schließen" name="Collapse all folders"/>
+ <menu_item_call label="Teleport-Verlauf löschen" name="Clear Teleport History"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/de/menu_teleport_history_item.xml
new file mode 100644
index 0000000000..ff8fb0b181
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_teleport_history_item.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Teleport History Item Context Menu">
+ <menu_item_call label="Teleportieren" name="Teleport"/>
+ <menu_item_call label="Weitere Informationen" name="More Information"/>
+ <menu_item_call label="In Zwischenablage kopieren" name="CopyToClipboard"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_teleport_history_tab.xml b/indra/newview/skins/default/xui/de/menu_teleport_history_tab.xml
new file mode 100644
index 0000000000..194dd16fd1
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_teleport_history_tab.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Teleport History Item Context Menu">
+ <menu_item_call label="Öffnen" name="TabOpen"/>
+ <menu_item_call label="Schließen" name="TabClose"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_text_editor.xml b/indra/newview/skins/default/xui/de/menu_text_editor.xml
new file mode 100644
index 0000000000..c00186c13e
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_text_editor.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Text editor context menu">
+ <menu_item_call label="Ausschneiden" name="Cut"/>
+ <menu_item_call label="Kopieren" name="Copy"/>
+ <menu_item_call label="Einfügen" name="Paste"/>
+ <menu_item_call label="Löschen" name="Delete"/>
+ <menu_item_call label="Alle auswählen" name="Select All"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_url_agent.xml b/indra/newview/skins/default/xui/de/menu_url_agent.xml
new file mode 100644
index 0000000000..9a808088fb
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_url_agent.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Einwohnerprofil anzeigen" name="show_agent"/>
+ <menu_item_call label="Name in Zwischenablage kopieren" name="url_copy_label"/>
+ <menu_item_call label="SLurl in die Zwischenablage kopieren" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_url_group.xml b/indra/newview/skins/default/xui/de/menu_url_group.xml
new file mode 100644
index 0000000000..6bd86414bc
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_url_group.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Gruppeninformation anzeigen" name="show_group"/>
+ <menu_item_call label="Gruppe in Zwischenablage kopieren" name="url_copy_label"/>
+ <menu_item_call label="SLurl in die Zwischenablage kopieren" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_url_http.xml b/indra/newview/skins/default/xui/de/menu_url_http.xml
new file mode 100644
index 0000000000..30eb1668a5
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_url_http.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Webseite öffnen" name="url_open"/>
+ <menu_item_call label="Im internen Browser öffnen" name="url_open_internal"/>
+ <menu_item_call label="Im externen Browser öffnen" name="url_open_external"/>
+ <menu_item_call label="URL in Zwischenablage kopieren" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_url_inventory.xml b/indra/newview/skins/default/xui/de/menu_url_inventory.xml
new file mode 100644
index 0000000000..dc069df02b
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_url_inventory.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Inventarobjekte anzeigen" name="show_item"/>
+ <menu_item_call label="Name in Zwischenablage kopieren" name="url_copy_label"/>
+ <menu_item_call label="SLurl in die Zwischenablage kopieren" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_url_map.xml b/indra/newview/skins/default/xui/de/menu_url_map.xml
new file mode 100644
index 0000000000..2f6ffcd450
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_url_map.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Auf Karte zeigen" name="show_on_map"/>
+ <menu_item_call label="Zu Position teleportieren" name="teleport_to_location"/>
+ <menu_item_call label="SLurl in die Zwischenablage kopieren" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_url_objectim.xml b/indra/newview/skins/default/xui/de/menu_url_objectim.xml
new file mode 100644
index 0000000000..90d3763d9c
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_url_objectim.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Objektinformationen anzeigen" name="show_object"/>
+ <menu_item_call label="Auf Karte zeigen" name="show_on_map"/>
+ <menu_item_call label="Zu Objekt-Position teleportieren" name="teleport_to_object"/>
+ <menu_item_call label="Objektname in Zwischenablage kopieren" name="url_copy_label"/>
+ <menu_item_call label="SLurl in die Zwischenablage kopieren" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_url_parcel.xml b/indra/newview/skins/default/xui/de/menu_url_parcel.xml
new file mode 100644
index 0000000000..9169bca24f
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_url_parcel.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Parzelleninformationen anzeigen" name="show_parcel"/>
+ <menu_item_call label="Auf Karte zeigen" name="show_on_map"/>
+ <menu_item_call label="SLurl in die Zwischenablage kopieren" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_url_slapp.xml b/indra/newview/skins/default/xui/de/menu_url_slapp.xml
new file mode 100644
index 0000000000..72e916b902
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_url_slapp.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Diesen Befehl ausführen" name="run_slapp"/>
+ <menu_item_call label="SLurl in die Zwischenablage kopieren" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_url_slurl.xml b/indra/newview/skins/default/xui/de/menu_url_slurl.xml
new file mode 100644
index 0000000000..5d48230ebf
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_url_slurl.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Ortsinformationen anzeigen" name="show_place"/>
+ <menu_item_call label="Auf Karte zeigen" name="show_on_map"/>
+ <menu_item_call label="Zu Position teleportieren" name="teleport_to_location"/>
+ <menu_item_call label="SLurl in die Zwischenablage kopieren" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_url_teleport.xml b/indra/newview/skins/default/xui/de/menu_url_teleport.xml
new file mode 100644
index 0000000000..4cc1ecc70e
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_url_teleport.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="An diesen Standort teleportieren" name="teleport"/>
+ <menu_item_call label="Auf Karte zeigen" name="show_on_map"/>
+ <menu_item_call label="SLurl in die Zwischenablage kopieren" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_viewer.xml b/indra/newview/skins/default/xui/de/menu_viewer.xml
index 279024616a..ee2f1ee7c9 100644
--- a/indra/newview/skins/default/xui/de/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/de/menu_viewer.xml
@@ -1,217 +1,426 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<menu_bar name="Main Menu">
- <menu label="Datei" name="File">
- <tearoff_menu label="~~~~~~~~~~~" name="~~~~~~~~~~~"/>
- <menu label="Hochladen" name="upload">
- <menu_item_call label="Bild ([COST] L$)..." name="Upload Image"/>
- <menu_item_call label="Sound ([COST] L$)..." name="Upload Sound"/>
- <menu_item_call label="Animation ([COST] L$)..." name="Upload Animation"/>
- <menu_item_call label="Mehrfach-Upload ([COST] L$ pro Datei)..." name="Bulk Upload"/>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_call label="Standard-Berechtigungen einstellen..." name="perm prefs"/>
- </menu>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_call label="Fenster schließen" name="Close Window"/>
- <menu_item_call label="Alle Fenster schließen" name="Close All Windows"/>
- <menu_item_separator label="-----------" name="separator2"/>
- <menu_item_call label="Textur speichern unter..." name="Save Texture As..."/>
- <menu_item_separator label="-----------" name="separator3"/>
- <menu_item_call label="Foto machen" name="Take Snapshot"/>
- <menu_item_call label="Foto auf Datenträger" name="Snapshot to Disk"/>
- <menu_item_separator label="-----------" name="separator4"/>
- <menu_item_call label="Beenden" name="Quit"/>
- </menu>
- <menu label="Bearbeiten" name="Edit">
- <menu_item_call label="Rückgängig" name="Undo"/>
- <menu_item_call label="Wiederherstellen" name="Redo"/>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_call label="Ausschneiden" name="Cut"/>
- <menu_item_call label="Kopieren" name="Copy"/>
- <menu_item_call label="Einfügen" name="Paste"/>
- <menu_item_call label="Löschen" name="Delete"/>
- <menu_item_separator label="-----------" name="separator2"/>
- <menu_item_call label="Suchen..." name="Search..."/>
- <menu_item_separator label="-----------" name="separator3"/>
- <menu_item_call label="Alle auswählen" name="Select All"/>
- <menu_item_call label="Auswahl aufheben" name="Deselect"/>
- <menu_item_separator label="-----------" name="separator4"/>
- <menu_item_call label="Duplizieren" name="Duplicate"/>
- <menu_item_separator label="-----------" name="separator5"/>
- <menu label="Objekt anhängen" name="Attach Object"/>
- <menu label="Objekt abnehmen" name="Detach Object"/>
- <menu label="Kleider ausziehen" name="Take Off Clothing">
- <menu_item_call label="Hemd" name="Shirt"/>
- <menu_item_call label="Hose" name="Pants"/>
- <menu_item_call label="Schuhe" name="Shoes"/>
- <menu_item_call label="Socken" name="Socks"/>
- <menu_item_call label="Jacke" name="Jacket"/>
- <menu_item_call label="Handschuhe" name="Gloves"/>
- <menu_item_call label="Unterhemd" name="Menu Undershirt"/>
- <menu_item_call label="Unterhose" name="Menu Underpants"/>
- <menu_item_call label="Rock" name="Skirt"/>
- <menu_item_call label="Alle Kleider" name="All Clothes"/>
+ <menu label="Ich" name="Me">
+ <menu_item_call label="Einstellungen" name="Preferences"/>
+ <menu_item_call label="Meine Startseite" name="Manage My Account">
+ <menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=de"/>
+ </menu_item_call>
+ <menu_item_call label="L$ kaufen" name="Buy and Sell L$"/>
+ <menu_item_call label="Mein Profil" name="Profile"/>
+ <menu_item_call label="Mein Aussehen" name="Appearance"/>
+ <menu_item_check label="Mein Inventar" name="Inventory"/>
+ <menu_item_call label="Inventar in Seitenleiste anzeigen" name="ShowSidetrayInventory"/>
+ <menu_item_call label="Meine Gesten" name="Gestures"/>
+ <menu label="Mein Status" name="Status">
+ <menu_item_call label="Abwesend" name="Set Away"/>
+ <menu_item_call label="Beschäftigt" name="Set Busy"/>
</menu>
- <menu_item_separator label="-----------" name="separator6"/>
- <menu_item_call label="Gesten..." name="Gestures..."/>
- <menu_item_call label="Profil..." name="Profile..."/>
- <menu_item_call label="Aussehen..." name="Appearance..."/>
- <menu_item_separator label="-----------" name="separator7"/>
- <menu_item_check label="Freunde..." name="Friends..."/>
- <menu_item_call label="Gruppen..." name="Groups..."/>
- <menu_item_separator label="-----------" name="separator8"/>
- <menu_item_call label="Einstellungen..." name="Preferences..."/>
+ <menu_item_call label="Admin-Status anfordern" name="Request Admin Options"/>
+ <menu_item_call label="Admin-Status verlassen" name="Leave Admin Options"/>
+ <menu_item_call label="[APP_NAME] schließen" name="Quit"/>
</menu>
- <menu label="Ansicht" name="View">
- <tearoff_menu label="~~~~~~~~~~~" name="~~~~~~~~~~~"/>
- <menu_item_call label="Mouselook" name="Mouselook"/>
- <menu_item_check label="Bauen" name="Build"/>
- <menu_item_check label="Joystick-Flycam" name="Joystick Flycam"/>
- <menu_item_call label="Ansicht zurücksetzen" name="Reset View"/>
- <menu_item_call label="Letzten Chatter ansehen" name="Look at Last Chatter"/>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_check label="Symbolleiste" name="Toolbar"/>
- <menu_item_check label="Lokaler Chat" name="Chat History"/>
- <menu_item_check label="Unterhalten" name="Instant Message"/>
- <menu_item_check label="Inventar" name="Inventory"/>
- <menu_item_check label="Aktive Sprecher" name="Active Speakers"/>
- <menu_item_check label="Stummschalten-Liste" name="Mute List"/>
- <menu_item_separator label="-----------" name="separator2"/>
- <menu_item_check label="Kamerasteuerung" name="Camera Controls"/>
- <menu_item_check label="Bewegungssteuerung" name="Movement Controls"/>
- <menu_item_check label="Weltkarte" name="World Map"/>
- <menu_item_check label="Minikarte" name="Mini-Map"/>
- <menu_item_separator label="-----------" name="separator3"/>
- <menu_item_check label="Statistikleiste" name="Statistics Bar"/>
- <menu_item_check label="Grundstücksgrenzen" name="Property Lines"/>
- <menu_item_check label="Absperrungen" name="Banlines"/>
- <menu_item_check label="Landeigentümer" name="Land Owners"/>
- <menu_item_separator label="-----------" name="separator4"/>
- <menu label="Schwebe-Tipps" name="Hover Tips">
- <menu_item_check label="Tipps anzeigen" name="Show Tips"/>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_check label="Landtipps" name="Land Tips"/>
- <menu_item_check label="Tipps zu allen Objekten" name="Tips On All Objects"/>
- </menu>
- <menu_item_check label="Durchsichtig hervorheben" name="Highlight Transparent"/>
- <menu_item_check label="Beacons" name="beacons"/>
- <menu_item_check label="Partikel ausblenden" name="Hide Particles"/>
- <menu_item_check label="HUD-Anhänge anzeigen" name="Show HUD Attachments"/>
- <menu_item_separator label="-----------" name="separator5"/>
- <menu_item_call label="Hinein zoomen" name="Zoom In"/>
- <menu_item_call label="Zoom-Standard" name="Zoom Default"/>
- <menu_item_call label="Wegzoomen" name="Zoom Out"/>
- <menu_item_separator label="-----------" name="separator6"/>
- <menu_item_call label="Vollbild" name="Toggle Fullscreen"/>
- <menu_item_call label="UI-Größe auf Standard setzen" name="Set UI Size to Default"/>
+ <menu label="Unterhalten" name="Communicate">
+ <menu_item_call label="Meine Freunde" name="My Friends"/>
+ <menu_item_call label="Meine Gruppen" name="My Groups"/>
+ <menu_item_check label="Lokaler Chat" name="Nearby Chat"/>
+ <menu_item_call label="Leute in dern Nähe" name="Active Speakers"/>
+ <menu_item_check label="Medien in der Nähe" name="Nearby Media"/>
+ <menu_item_check label="(Legacy) Kommunikation" name="Instant Message"/>
+ <menu_item_call label="(Temp) Mediensteuerung" name="Preferences"/>
</menu>
<menu label="Welt" name="World">
- <menu_item_call label="Chat" name="Chat"/>
- <menu_item_check label="Immer rennen" name="Always Run"/>
- <menu_item_check label="Fliegen" name="Fly"/>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_call label="Landmarke hier setzen" name="Create Landmark Here"/>
- <menu_item_call label="Hier als Zuhause wählen" name="Set Home to Here"/>
- <menu_item_separator label="-----------" name="separator2"/>
- <menu_item_call label="Teleport nach Hause" name="Teleport Home"/>
- <menu_item_separator label="-----------" name="separator3"/>
- <menu_item_call label="Als abwesend anzeigen" name="Set Away"/>
- <menu_item_call label="Als beschäftigt anzeigen" name="Set Busy"/>
- <menu_item_call label="Avatar nicht mehr animieren" name="Stop Animating My Avatar"/>
- <menu_item_call label="Tasten freigeben" name="Release Keys"/>
- <menu_item_separator label="-----------" name="separator4"/>
- <menu_item_call label="Kontostatistik..." name="Account History...">
- <on_click name="AccountHistory_url" userdata="WebLaunchAccountHistory,http://secondlife.com/account/transactions.php?lang=de"/>
- </menu_item_call>
- <menu_item_call label="Mein Konto verwalten..." name="Manage My Account...">
- <on_click name="ManageMyAccount_url" userdata="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=de"/>
- </menu_item_call>
- <menu_item_call label="L$ kaufen..." name="Buy and Sell L$..."/>
- <menu_item_separator label="-----------" name="separator5"/>
- <menu_item_call label="Mein Land..." name="My Land..."/>
- <menu_item_call label="Land-Info..." name="About Land..."/>
- <menu_item_call label="Land kaufen..." name="Buy Land..."/>
- <menu_item_call label="Region/Grundstück..." name="Region/Estate..."/>
- <menu_item_separator label="-----------" name="separator6"/>
- <menu label="Umwelt-Einstellungen" name="Environment Settings">
+ <menu_item_check label="Bewegen" name="Movement Controls"/>
+ <menu_item_check label="Ansicht" name="Camera Controls"/>
+ <menu_item_call label="Ãœber Land" name="About Land"/>
+ <menu_item_call label="Region/Grundstück" name="Region/Estate"/>
+ <menu_item_call label="Land kaufen" name="Buy Land"/>
+ <menu_item_call label="Mein Land" name="My Land"/>
+ <menu label="Anzeigen" name="Land">
+ <menu_item_check label="Bannlinien" name="Ban Lines"/>
+ <menu_item_check label="Strahlen" name="beacons"/>
+ <menu_item_check label="Grundstücksgrenzen" name="Property Lines"/>
+ <menu_item_check label="Landeigentümer" name="Land Owners"/>
+ </menu>
+ <menu label="Landmarken" name="Landmarks">
+ <menu_item_call label="Landmarke hier setzen" name="Create Landmark Here"/>
+ <menu_item_call label="Hier als Zuhause wählen" name="Set Home to Here"/>
+ </menu>
+ <menu_item_call label="Startseite" name="Teleport Home"/>
+ <menu_item_check label="Minikarte" name="Mini-Map"/>
+ <menu_item_check label="Weltkarte" name="World Map"/>
+ <menu_item_call label="Foto" name="Take Snapshot"/>
+ <menu label="Sonne" name="Environment Settings">
<menu_item_call label="Sonnenaufgang" name="Sunrise"/>
<menu_item_call label="Mittag" name="Noon"/>
<menu_item_call label="Sonnenuntergang" name="Sunset"/>
<menu_item_call label="Mitternacht" name="Midnight"/>
- <menu_item_call label="Auf Regionsstandard zurücksetzen" name="Revert to Region Default"/>
- <menu_item_separator label="-----------" name="separator"/>
+ <menu_item_call label="Grundstückszeit verwenden" name="Revert to Region Default"/>
<menu_item_call label="Umwelt-Editor" name="Environment Editor"/>
</menu>
</menu>
- <menu label="Werkzeug" name="Tools">
- <menu label="Fehlermeldungen" name="Select Tool">
- <menu_item_call label="Fokus" name="Focus"/>
- <menu_item_call label="Verschieben" name="Move"/>
+ <menu label="Bauen" name="BuildTools">
+ <menu_item_check label="Bauen" name="Show Build Tools"/>
+ <menu label="Bauwerkzeug auswählen" name="Select Tool">
+ <menu_item_call label="Fokus-Werkzeug" name="Focus"/>
+ <menu_item_call label="Werkzeug „Bewegen“" name="Move"/>
<menu_item_call label="Bearbeiten" name="Edit"/>
- <menu_item_call label="Erstellen" name="Create"/>
- <menu_item_call label="Land" name="Land"/>
- </menu>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_check label="Nur meine Objekte auswählen" name="Select Only My Objects"/>
- <menu_item_check label="Nur bewegliche Objekte auswählen" name="Select Only Movable Objects"/>
- <menu_item_check label="Nach Umgebung auswählen" name="Select By Surrounding"/>
- <menu_item_check label="Ausgeblendete Auswahl anzeigen" name="Show Hidden Selection"/>
- <menu_item_check label="Lichtradius für Auswahl anzeigen" name="Show Light Radius for Selection"/>
- <menu_item_check label="Auswahlstrahl anzeigen" name="Show Selection Beam"/>
- <menu_item_separator label="-----------" name="separator2"/>
- <menu_item_check label="An Raster ausrichten" name="Snap to Grid"/>
- <menu_item_call label="Objekt-XY an Raster ausrichten" name="Snap Object XY to Grid"/>
- <menu_item_call label="Auswahl für Raster verwenden" name="Use Selection for Grid"/>
- <menu_item_call label="Rasteroptionen..." name="Grid Options..."/>
- <menu_item_separator label="-----------" name="separator3"/>
- <menu_item_check label="Verknüpfte Teile bearbeiten" name="Edit Linked Parts"/>
+ <menu_item_call label="Werkzeug „Erstellen&quot;" name="Create"/>
+ <menu_item_call label="Land-Werkzeug" name="Land"/>
+ </menu>
+ <menu label="Bearbeiten" name="Edit">
+ <menu_item_call label="Rückgängig" name="Undo"/>
+ <menu_item_call label="Wiederherstellen" name="Redo"/>
+ <menu_item_call label="Ausschneiden" name="Cut"/>
+ <menu_item_call label="Kopieren" name="Copy"/>
+ <menu_item_call label="Einfügen" name="Paste"/>
+ <menu_item_call label="Löschen" name="Delete"/>
+ <menu_item_call label="Duplizieren" name="Duplicate"/>
+ <menu_item_call label="Alle auswählen" name="Select All"/>
+ <menu_item_call label="Auswahl aufheben" name="Deselect"/>
+ </menu>
<menu_item_call label="Verknüpfung" name="Link"/>
- <menu_item_call label="Verknüpfung aufheben" name="Unlink"/>
- <menu_item_separator label="-----------" name="separator4"/>
+ <menu_item_call label="Verknüpfung auflösen" name="Unlink"/>
<menu_item_call label="Fokus auf Auswahl" name="Focus on Selection"/>
<menu_item_call label="Auf Auswahl zoomen" name="Zoom to Selection"/>
- <menu_item_call label="Objekt kaufen" name="Menu Object Take"/>
- <menu_item_call label="Kopie nehmen/machen" name="Take Copy"/>
- <menu_item_call label="Objekt wieder in Objektinhalt speichern" name="Save Object Back to Object Contents"/>
- <menu_item_separator label="-----------" name="separator6"/>
- <menu_item_call label="Skriptwarnung/Fehlerfenster anzeigen" name="Show Script Warning/Error Window"/>
- <menu label="Skripte in Auswahl neu kompilieren" name="Recompile Scripts in Selection">
- <menu_item_call label="Mono" name="Mono"/>
- <menu_item_call label="LSL" name="LSL"/>
- </menu>
- <menu_item_call label="Skripte in Auswahl zurücksetzen" name="Reset Scripts in Selection"/>
- <menu_item_call label="Skripte in Auswahl so einstellen, dass sie ausgeführt werden" name="Set Scripts to Running in Selection"/>
- <menu_item_call label="Skripte in Auswahl so einstellen, dass sie nicht ausgeführt werden" name="Set Scripts to Not Running in Selection"/>
+ <menu label="Objekt" name="Object">
+ <menu_item_call label="Kaufen" name="Menu Object Take"/>
+ <menu_item_call label="Kopie nehmen" name="Take Copy"/>
+ <menu_item_call label="Objekt wieder in meinem Inventar speichern" name="Save Object Back to My Inventory"/>
+ <menu_item_call label="Wieder in Objektinhalt speichern" name="Save Object Back to Object Contents"/>
+ </menu>
+ <menu label="Skripts" name="Scripts">
+ <menu_item_call label="Skripts rekompilieren (Mono)" name="Mono"/>
+ <menu_item_call label="Skripts rekompilieren (LSL)" name="LSL"/>
+ <menu_item_call label="Skripts zurücksetzen" name="Reset Scripts"/>
+ <menu_item_call label="Skripts auf ausführen einstellen" name="Set Scripts to Running"/>
+ <menu_item_call label="Skripts auf nicht ausführen einstellen" name="Set Scripts to Not Running"/>
+ </menu>
+ <menu label="Optionen" name="Options">
+ <menu_item_check label="Verknüpfte Teile bearbeiten" name="Edit Linked Parts"/>
+ <menu_item_call label="Hochlade-Berechtigungen (Standard) festlegen" name="perm prefs"/>
+ <menu_item_check label="Erweiterte Berechtigungen anzeigen" name="DebugPermissions"/>
+ <menu label="Auswahl" name="Selection">
+ <menu_item_check label="Nur meine Objekte auswählen" name="Select Only My Objects"/>
+ <menu_item_check label="Nur bewegliche Objekte auswählen" name="Select Only Movable Objects"/>
+ <menu_item_check label="Nach Umgebung auswählen" name="Select By Surrounding"/>
+ </menu>
+ <menu label="Anzeigen" name="Show">
+ <menu_item_check label="Ausgeblendete Auswahl anzeigen" name="Show Hidden Selection"/>
+ <menu_item_check label="Lichtradius für Auswahl anzeigen" name="Show Light Radius for Selection"/>
+ <menu_item_check label="Auswahlstrahl anzeigen" name="Show Selection Beam"/>
+ </menu>
+ <menu label="Raster" name="Grid">
+ <menu_item_check label="An Raster ausrichten" name="Snap to Grid"/>
+ <menu_item_call label="Objekt-XY an Raster ausrichten" name="Snap Object XY to Grid"/>
+ <menu_item_call label="Auswahl für Raster verwenden" name="Use Selection for Grid"/>
+ <menu_item_call label="Rasteroptionen" name="Grid Options"/>
+ </menu>
+ </menu>
+ <menu label="Verknüpfte Teile auswählen" name="Select Linked Parts">
+ <menu_item_call label="Nächstes Teil auswählen" name="Select Next Part"/>
+ <menu_item_call label="Vorheriges Teil auswählen" name="Select Previous Part"/>
+ <menu_item_call label="Nächsten Teil mit einsschließen" name="Include Next Part"/>
+ <menu_item_call label="Vorherige Teile mit einschließen" name="Include Previous Part"/>
+ </menu>
</menu>
<menu label="Hilfe" name="Help">
- <menu_item_call label="Hilfe zu Second Life" name="Second Life Help"/>
+ <menu_item_call label="[SECOND_LIFE]-Hilfe" name="Second Life Help"/>
<menu_item_call label="Tutorial" name="Tutorial"/>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_call label="Offizielles Linden-Blog..." name="Official Linden Blog..."/>
- <menu_item_separator label="-----------" name="separator2"/>
- <menu_item_call label="Scripting-Portal..." name="Scripting Portal...">
- <on_click name="ScriptingPortal_url" userdata="WebLaunchLSLWiki,http://wiki.secondlife.com/wiki/LSL_Portal/de" />
- </menu_item_call>
- <menu_item_separator label="-----------" name="separator3"/>
- <menu_item_call label="Missbrauch melden..." name="Report Abuse..."/>
- <menu_item_call label="Rempler, Stöße und Schläge..." name="Bumps, Pushes &amp;amp; Hits..."/>
- <menu_item_call label="Lag-Anzeige" name="Lag Meter"/>
- <menu_item_separator label="-----------" name="separator7"/>
- <menu label="Fehlermeldungen" name="Bug Reporting">
- <menu_item_call label="Allgemeiner Probleme-Tracker..." name="Public Issue Tracker..."/>
- <menu_item_call label="Hilfe zum Allgemeinen Probleme-Tracker..." name="Publc Issue Tracker Help...">
- <on_click name="PublicIssueTrackerHelp_url" userdata="WebLaunchPublicIssueHelp,http://wiki.secondlife.com/wiki/Issue_tracker/de" />
- </menu_item_call>
- <menu_item_separator label="-----------" name="separator7"/>
- <menu_item_call label="Fehlermeldungs-1x1..." name="Bug Reporing 101...">
- <on_click name="BugReporting101_url" userdata="WebLaunchBugReport101,http://wiki.secondlife.com/wiki/Bug_Reporting_101/de"/>
- </menu_item_call>
- <menu_item_call label="Sicherheitsfragen..." name="Security Issues...">
- <on_click name="SecurityIssues_url" userdata="WebLaunchSecurityIssues,http://wiki.secondlife.com/wiki/Security_issues/de"/>
- </menu_item_call>
- <menu_item_call label="QA-Wiki..." name="QA Wiki..."/>
- <menu_item_separator label="-----------" name="separator9"/>
- <menu_item_call label="Fehler melden..." name="Report Bug..."/>
- </menu>
- <menu_item_call label="Ãœber Second Life..." name="About Second Life..."/>
+ <menu_item_call label="Missbrauch melden" name="Report Abuse"/>
+ <menu_item_call label="INFO ÃœBER [APP_NAME]" name="About Second Life"/>
+ </menu>
+ <menu label="Erweitert" name="Advanced">
+ <menu_item_check label="Nach 30 Min auf Abwesend stellen" name="Go Away/AFK When Idle"/>
+ <menu_item_call label="Animation meines Avatars stoppen" name="Stop Animating My Avatar"/>
+ <menu_item_call label="Textur neu laden" name="Rebake Texture"/>
+ <menu_item_call label="UI-Größe auf Standard setzen" name="Set UI Size to Default"/>
+ <menu_item_check label="Auswahldistanz einschränken" name="Limit Select Distance"/>
+ <menu_item_check label="Kamerabeschränkungen deaktivieren" name="Disable Camera Distance"/>
+ <menu_item_check label="Foto (hohe Auflösung)" name="HighResSnapshot"/>
+ <menu_item_check label="Fotos auf Festplatte leise speichern" name="QuietSnapshotsToDisk"/>
+ <menu_item_check label="Fotos auf Festplatte komprimieren" name="CompressSnapshotsToDisk"/>
+ <menu_item_call label="Textur speichern als" name="Save Texture As"/>
+ <menu label="Performance Tools" name="Performance Tools">
+ <menu_item_call label="Lag-Anzeige" name="Lag Meter"/>
+ <menu_item_check label="Statistikleiste" name="Statistics Bar"/>
+ <menu_item_check label="Avatar-Darstellungskosten anzeigen" name="Avatar Rendering Cost"/>
+ </menu>
+ <menu label="Hervorhebung und Sichtbarkeit" name="Highlighting and Visibility">
+ <menu_item_check label="Pulsierender Strahl" name="Cheesy Beacon"/>
+ <menu_item_check label="Partikel ausblenden" name="Hide Particles"/>
+ <menu_item_check label="Auswahl ausblenden" name="Hide Selected"/>
+ <menu_item_check label="Durchsichtig hervorheben" name="Highlight Transparent"/>
+ <menu_item_check label="HUD-Anhänge anzeigen" name="Show HUD Attachments"/>
+ <menu_item_check label="Fadenkreuz für Mouselook anzeigen" name="ShowCrosshairs"/>
+ <menu_item_check label="Land-Kurzinfos anzeigen" name="Land Tips"/>
+ </menu>
+ <menu label="Darstellungstypen" name="Rendering Types">
+ <menu_item_check label="Einfach" name="Simple"/>
+ <menu_item_check label="Alpha" name="Alpha"/>
+ <menu_item_check label="Baum" name="Tree"/>
+ <menu_item_check label="Avatare" name="Character"/>
+ <menu_item_check label="SurfacePath" name="SurfacePath"/>
+ <menu_item_check label="Himmel" name="Sky"/>
+ <menu_item_check label="Wasser" name="Water"/>
+ <menu_item_check label="Boden" name="Ground"/>
+ <menu_item_check label="Volumen" name="Volume"/>
+ <menu_item_check label="Gras" name="Grass"/>
+ <menu_item_check label="Wolken" name="Clouds"/>
+ <menu_item_check label="Partikel" name="Particles"/>
+ <menu_item_check label="Unebenheiten" name="Bump"/>
+ </menu>
+ <menu label="Rederning-Eigenschaften" name="Rendering Features">
+ <menu_item_check label="UI" name="UI"/>
+ <menu_item_check label="Ausgewählt" name="Selected"/>
+ <menu_item_check label="Farblich hervorgehoben" name="Highlighted"/>
+ <menu_item_check label="Dynamische Texturen" name="Dynamic Textures"/>
+ <menu_item_check label="Fußschatten" name="Foot Shadows"/>
+ <menu_item_check label="Nebel" name="Fog"/>
+ <menu_item_check label="FRInfo testen" name="Test FRInfo"/>
+ <menu_item_check label="Flexible Objekte" name="Flexible Objects"/>
+ </menu>
+ <menu_item_check label="Mehrer Threads ausführen" name="Run Multiple Threads"/>
+ <menu_item_call label="Gruppen-Cache löschen" name="ClearGroupCache"/>
+ <menu_item_check label="Weiche Mausbewegung" name="Mouse Smoothing"/>
+ <menu_item_check label="IMs in lokalem Chat anzeigen" name="IMInChat"/>
+ <menu label="Tastaturkürzel" name="Shortcuts">
+ <menu_item_check label="Suchen" name="Search"/>
+ <menu_item_call label="Tasten freigeben" name="Release Keys"/>
+ <menu_item_call label="UI-Größe auf Standard setzen" name="Set UI Size to Default"/>
+ <menu_item_check label="Immer rennen" name="Always Run"/>
+ <menu_item_check label="Fliegen" name="Fly"/>
+ <menu_item_call label="Fenster schließen" name="Close Window"/>
+ <menu_item_call label="Alle Fenster schließen" name="Close All Windows"/>
+ <menu_item_call label="Foto auf Datenträger" name="Snapshot to Disk"/>
+ <menu_item_call label="Mouselook" name="Mouselook"/>
+ <menu_item_check label="Joystick-Flycam" name="Joystick Flycam"/>
+ <menu_item_call label="Ansicht zurücksetzen" name="Reset View"/>
+ <menu_item_call label="Letzten Chatter ansehen" name="Look at Last Chatter"/>
+ <menu label="Bauwerkzeug auswählen" name="Select Tool">
+ <menu_item_call label="Fokus-Werkzeug" name="Focus"/>
+ <menu_item_call label="Werkzeug „Bewegen“" name="Move"/>
+ <menu_item_call label="Bearbeiten" name="Edit"/>
+ <menu_item_call label="Werkzeug „Erstellen&quot;" name="Create"/>
+ <menu_item_call label="Land-Werkzeug" name="Land"/>
+ </menu>
+ <menu_item_call label="Hineinzoomen" name="Zoom In"/>
+ <menu_item_call label="Zoom-Standard" name="Zoom Default"/>
+ <menu_item_call label="Wegzoomen" name="Zoom Out"/>
+ <menu_item_call label="Vollbild" name="Toggle Fullscreen"/>
+ </menu>
+ <menu_item_call label="Debug-Einstellungen anzeigen" name="Debug Settings"/>
+ <menu_item_check label="Menü „Entwickler“ anzeigen" name="Debug Mode"/>
+ </menu>
+ <menu label="Entwickler" name="Develop">
+ <menu label="Konsolen" name="Consoles">
+ <menu_item_check label="Textur" name="Texture Console"/>
+ <menu_item_check label="Fehler beseitigen" name="Debug Console"/>
+ <menu_item_call label="Konsole: Meldungen" name="Notifications"/>
+ <menu_item_check label="Texturgröße" name="Texture Size"/>
+ <menu_item_check label="Texture-Kategorie" name="Texture Category"/>
+ <menu_item_check label="Schnelle Timer" name="Fast Timers"/>
+ <menu_item_check label="Speicher" name="Memory"/>
+ <menu_item_call label="Info zu Region in Fenster Fehler beseitigen" name="Region Info to Debug Console"/>
+ <menu_item_call label="Gruppeninfo in Fenster Fehler beseitigen" name="Group Info to Debug Console"/>
+ <menu_item_call label="Info zu Fähigkeiten in Fenster Fehler beseitigen" name="Capabilities Info to Debug Console"/>
+ <menu_item_check label="Kamera" name="Camera"/>
+ <menu_item_check label="Wind" name="Wind"/>
+ <menu_item_check label="FOV" name="FOV"/>
+ </menu>
+ <menu label="Info anzeigen" name="Display Info">
+ <menu_item_check label="Zeit anzeigen" name="Show Time"/>
+ <menu_item_check label="Render-Info anzeigen" name="Show Render Info"/>
+ <menu_item_check label="Matrizen anzeigen" name="Show Matrices"/>
+ <menu_item_check label="Farbe unter Cursor anzeigen" name="Show Color Under Cursor"/>
+ <menu_item_check label="Akutalisierungen an Objekten anzeigen" name="Show Updates"/>
+ </menu>
+ <menu label="Fehler erzwingen" name="Force Errors">
+ <menu_item_call label="Haltepunkt erzwingen" name="Force Breakpoint"/>
+ <menu_item_call label="LLError erzwingen und abstürzen" name="Force LLError And Crash"/>
+ <menu_item_call label="Erzwinge fehlerhaften Speicherzugriff" name="Force Bad Memory Access"/>
+ <menu_item_call label="Endlosschleife erzwingen" name="Force Infinite Loop"/>
+ <menu_item_call label="Treiber-Crash erzwingen" name="Force Driver Carsh"/>
+ <menu_item_call label="Softwareausnahme erzwingen" name="Force Software Exception"/>
+ <menu_item_call label="Verbindungsabbruch erzwingen" name="Force Disconnect Viewer"/>
+ <menu_item_call label="Speicherverlust simulieren" name="Memory Leaking Simulation"/>
+ </menu>
+ <menu label="Render-Tests" name="Render Tests">
+ <menu_item_check label="Kamera-Versatz" name="Camera Offset"/>
+ <menu_item_check label="Framerate randomisieren" name="Randomize Framerate"/>
+ <menu_item_check label="Periodic Slow Frame" name="Periodic Slow Frame"/>
+ <menu_item_check label="Frame-Test" name="Frame Test"/>
+ </menu>
+ <menu label="Metadaten darstellen" name="Render Metadata">
+ <menu_item_check label="Bonding Boxes" name="Bounding Boxes"/>
+ <menu_item_check label="Octree" name="Octree"/>
+ <menu_item_check label="Shadow Frusta" name="Shadow Frusta"/>
+ <menu_item_check label="Okklusion" name="Occlusion"/>
+ <menu_item_check label="Bündel rendern" name="Render Batches"/>
+ <menu_item_check label="Texture-Anim" name="Texture Anim"/>
+ <menu_item_check label="Textur-Priorität" name="Texture Priority"/>
+ <menu_item_check label="Texturbereich" name="Texture Area"/>
+ <menu_item_check label="Oberflächenbereich" name="Face Area"/>
+ <menu_item_check label="Lichter" name="Lights"/>
+ <menu_item_check label="Gelenkpunkte" name="Collision Skeleton"/>
+ <menu_item_check label="Raycast" name="Raycast"/>
+ </menu>
+ <menu label="Rendering" name="Rendering">
+ <menu_item_check label="Achsen" name="Axes"/>
+ <menu_item_check label="Tangentenbasis" name="Tangent Basis"/>
+ <menu_item_call label="Texturinfo für ausgewähltes Objekt" name="Selected Texture Info Basis"/>
+ <menu_item_check label="Wireframe" name="Wireframe"/>
+ <menu_item_check label="Objekt-Objekt Okklusion" name="Object-Object Occlusion"/>
+ <menu_item_check label="Framebuffer-Objekte" name="Framebuffer Objects"/>
+ <menu_item_check label="Deferred Rendering" name="Deferred Rendering"/>
+ <menu_item_check label="Globale Beleuchtung" name="Global Illumination"/>
+ <menu_item_check label="Fehler in GL beseitigen" name="Debug GL"/>
+ <menu_item_check label="Fehler in Pipeline beseitigen" name="Debug Pipeline"/>
+ <menu_item_check label="Schnelles Alpha" name="Fast Alpha"/>
+ <menu_item_check label="Animationstexturen" name="Animation Textures"/>
+ <menu_item_check label="Texturen deaktivieren" name="Disable Textures"/>
+ <menu_item_check label="Voll-Res-Texturen" name="Rull Res Textures"/>
+ <menu_item_check label="Texturen prüfen" name="Audit Textures"/>
+ <menu_item_check label="Textur-Atlas" name="Texture Atlas"/>
+ <menu_item_check label="Angehängte Lichter rendern" name="Render Attached Lights"/>
+ <menu_item_check label="Angehängte Partikel rendern" name="Render Attached Particles"/>
+ <menu_item_check label="Leucht-Objekte schweben lassen" name="Hover Glow Objects"/>
+ </menu>
+ <menu label="Netzwerk" name="Network">
+ <menu_item_check label="Agent pausieren" name="AgentPause"/>
+ <menu_item_call label="Meldungsprotokoll aktivieren" name="Enable Message Log"/>
+ <menu_item_call label="Meldungs-Protokoll deaktivieren" name="Disable Message Log"/>
+ <menu_item_check label="Objektposition laut Geschwindigkeit interpolieren" name="Velocity Interpolate Objects"/>
+ <menu_item_check label="Positionen der interpolierten Objekte anfragen" name="Ping Interpolate Object Positions"/>
+ <menu_item_call label="Ein Paket fallenlassen" name="Drop a Packet"/>
+ </menu>
+ <menu_item_call label="Geskriptete Kamera ausgeben" name="Dump Scripted Camera"/>
+ <menu_item_call label="Rempler, Stöße &amp; Schläge" name="Bumps, Pushes &amp;amp; Hits"/>
+ <menu label="Rekorder" name="Recorder">
+ <menu_item_call label="Wiedergabe starten" name="Start Playback"/>
+ <menu_item_call label="Wiedergabe stoppen" name="Stop Playback"/>
+ <menu_item_check label="Wiedergabeschleife" name="Loop Playback"/>
+ <menu_item_call label="Aufnahme starten" name="Start Record"/>
+ <menu_item_call label="Aufnahme stoppen" name="Stop Record"/>
+ </menu>
+ <menu label="Welt" name="World">
+ <menu_item_check label="Sonnen-Override für Sim" name="Sim Sun Override"/>
+ <menu_item_check label="Pulsierender Strahl" name="Cheesy Beacon"/>
+ <menu_item_check label="Festgelegtes Wetter" name="Fixed Weather"/>
+ <menu_item_call label="Regionsobjekt-Cache ausgeben" name="Dump Region Object Cache"/>
+ </menu>
+ <menu label="UI" name="UI">
+ <menu_item_call label="Web-Browser-Test" name="Web Browser Test"/>
+ <menu_item_call label="SelectMgr ausgeben" name="Dump SelectMgr"/>
+ <menu_item_call label="Inventarinfo ausgeben" name="Dump Inventory"/>
+ <menu_item_call label="Timer ausgeben" name="Dump Timers"/>
+ <menu_item_call label="Fokus ausgeben" name="Dump Focus Holder"/>
+ <menu_item_call label="Ausgewählte Objektinfo drucken" name="Print Selected Object Info"/>
+ <menu_item_call label="Agent-Info drucken" name="Print Agent Info"/>
+ <menu_item_call label="Speicher-Stats" name="Memory Stats"/>
+ <menu_item_check label="Double-ClickAuto-Pilot" name="Double-ClickAuto-Pilot"/>
+ <menu_item_check label="Fehler in SelectMgr beseitigen" name="Debug SelectMgr"/>
+ <menu_item_check label="Fehler in Klicks beseitigen" name="Debug Clicks"/>
+ <menu_item_check label="Debug-Ansichten" name="Debug Views"/>
+ <menu_item_check label="Kurzinfos: Debug-Namen" name="Debug Name Tooltips"/>
+ <menu_item_check label="Fehler in Maus-Events beseitigen" name="Debug Mouse Events"/>
+ <menu_item_check label="Fehler in Keys beseitigen" name="Debug Keys"/>
+ <menu_item_check label="Fehler in WindowProc beseitigen" name="Debug WindowProc"/>
+ </menu>
+ <menu label="XUI" name="XUI">
+ <menu_item_call label="Farbeinstellungen neu laden" name="Reload Color Settings"/>
+ <menu_item_call label="Schriftarttest anzeigen" name="Show Font Test"/>
+ <menu_item_call label="Von XML laden" name="Load from XML"/>
+ <menu_item_call label="Als XML speichern" name="Save to XML"/>
+ <menu_item_check label="XUI-Namen anzeigen" name="Show XUI Names"/>
+ <menu_item_call label="Test-IMs senden" name="Send Test IMs"/>
+ <menu_item_call label="Inspektoren testen" name="Test Inspectors"/>
+ </menu>
+ <menu label="Avatar" name="Character">
+ <menu label="Geladene Textur nehmen" name="Grab Baked Texture">
+ <menu_item_call label="Iris" name="Iris"/>
+ <menu_item_call label="Kopf" name="Head"/>
+ <menu_item_call label="Oberkörper" name="Upper Body"/>
+ <menu_item_call label="Unterkörper" name="Lower Body"/>
+ <menu_item_call label="Rock" name="Skirt"/>
+ </menu>
+ <menu label="Avatar-Tests" name="Character Tests">
+ <menu_item_call label="Aussehen als XML speichern" name="Appearance To XML"/>
+ <menu_item_call label="Avatargeometry ein-/ausschalten" name="Toggle Character Geometry"/>
+ <menu_item_call label="Männlich testen" name="Test Male"/>
+ <menu_item_call label="Weiblich testen" name="Test Female"/>
+ <menu_item_call label="PG ein-/ausschalten" name="Toggle PG"/>
+ <menu_item_check label="Avatarauswahl zulassen" name="Allow Select Avatar"/>
+ </menu>
+ <menu_item_call label="Param auf Standard erzwingen" name="Force Params to Default"/>
+ <menu_item_check label="Animations-Info" name="Animation Info"/>
+ <menu_item_check label="Zeitlupen-Animationen" name="Slow Motion Animations"/>
+ <menu_item_check label="Kamerafokus anzeigen" name="Show Look At"/>
+ <menu_item_check label="Klickpunkt anzeigen??" name="Show Point At"/>
+ <menu_item_check label="Fehler in Landaktualisierung beseitigen" name="Debug Joint Updates"/>
+ <menu_item_check label="LOD deaktiveren" name="Disable LOD"/>
+ <menu_item_check label="Fehler für sichtbare Agenten beseitigen" name="Debug Character Vis"/>
+ <menu_item_check label="Gelenkpunkte anzeigen" name="Show Collision Skeleton"/>
+ <menu_item_check label="Agent-Ziel anzeigen" name="Display Agent Target"/>
+ --&gt;
+ <menu_item_call label="Anhänge ausgeben" name="Dump Attachments"/>
+ <menu_item_call label="Fehler in Avatar-Texturen beseitigen" name="Debug Avatar Textures"/>
+ <menu_item_call label="Lokale Texturen ausgeben" name="Dump Local Textures"/>
+ </menu>
+ <menu_item_call label="Bilder komprimieren" name="Compress Images"/>
+ <menu_item_check label="Ausgabe Fehlerbeseitigung ausgeben" name="Output Debug Minidump"/>
+ <menu_item_check label="Bei nächster Ausführung Fenster öffnen" name="Console Window"/>
+ <menu_item_check label="Admin-Menü anzeigen" name="View Admin Options"/>
+ <menu_item_call label="Admin-Status anfordern" name="Request Admin Options"/>
+ <menu_item_call label="Admin-Status verlassen" name="Leave Admin Options"/>
+ </menu>
+ <menu label="Admin" name="Admin">
+ <menu label="Object">
+ <menu_item_call label="Kopie nehmen" name="Take Copy"/>
+ <menu_item_call label="Besitzer zu mir zwingen" name="Force Owner To Me"/>
+ <menu_item_call label="Erlaubnis des Besitzers erzwingen" name="Force Owner Permissive"/>
+ <menu_item_call label="Löschen" name="Delete"/>
+ <menu_item_call label="Fest" name="Lock"/>
+ <menu_item_call label="Asset-ID zulassen" name="Get Assets IDs"/>
+ </menu>
+ <menu label="Parzelle" name="Parcel">
+ <menu_item_call label="Besitzer zu mir" name="Owner To Me"/>
+ <menu_item_call label="Auf Linden-Inhalt festlegen" name="Set to Linden Content"/>
+ <menu_item_call label="Öffentiches Land in Besitz nehmen" name="Claim Public Land"/>
+ </menu>
+ <menu label="Region" name="Region">
+ <menu_item_call label="Temp-Asset-Daten ausgeben" name="Dump Temp Asset Data"/>
+ <menu_item_call label="Regions-Status speichern" name="Save Region State"/>
+ </menu>
+ <menu_item_call label="Gott-Tools" name="God Tools"/>
+ </menu>
+ <menu label="Admin" name="Deprecated">
+ <menu label="Objekt anhängen" name="Attach Object"/>
+ <menu label="Objekt abnehmen" name="Detach Object"/>
+ <menu label="Kleider ausziehen" name="Take Off Clothing">
+ <menu_item_call label="Hemd" name="Shirt"/>
+ <menu_item_call label="Hose" name="Pants"/>
+ <menu_item_call label="Schuhe" name="Shoes"/>
+ <menu_item_call label="Socken" name="Socks"/>
+ <menu_item_call label="Jacke" name="Jacket"/>
+ <menu_item_call label="Handschuhe" name="Gloves"/>
+ <menu_item_call label="Unterhemd" name="Menu Undershirt"/>
+ <menu_item_call label="Unterhose" name="Menu Underpants"/>
+ <menu_item_call label="Rock" name="Skirt"/>
+ <menu_item_call label="Alpha" name="Alpha"/>
+ <menu_item_call label="Tätowierung" name="Tattoo"/>
+ <menu_item_call label="Alle Kleider" name="All Clothes"/>
+ </menu>
+ <menu_item_check label="Werkzeugleiste anzeigen" name="Show Toolbar"/>
+ <menu label="Hilfe" name="Help">
+ <menu_item_call label="Offizielles Linden-Blog" name="Official Linden Blog"/>
+ <menu_item_call label="Scripting-Portal" name="Scripting Portal"/>
+ <menu label="Fehlermeldungen" name="Bug Reporting">
+ <menu_item_call label="Allgemeine Probleme-Tracker" name="Public Issue Tracker"/>
+ <menu_item_call label="Hilfe zum Allgemeinen Probleme-Tracker" name="Publc Issue Tracker Help"/>
+ <menu_item_call label="Fehlermeldungs-1x1" name="Bug Reporing 101"/>
+ <menu_item_call label="Sicherheitsfragen" name="Security Issues"/>
+ <menu_item_call label="QA-Wiki" name="QA Wiki"/>
+ </menu>
+ </menu>
</menu>
</menu_bar>
diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml
index e920b2451f..7f5a561f74 100644
--- a/indra/newview/skins/default/xui/de/notifications.xml
+++ b/indra/newview/skins/default/xui/de/notifications.xml
@@ -6,74 +6,36 @@
<global name="alwayschoose">
Diese Option immer auswählen
</global>
- <template name="okbutton">
- <form>
- <button
- name="OK"
- text="$yestext"/>
- </form>
- </template>
-
- <template name="okignore">
- <form>
- <button
- name="OK"
- text="$yestext"/>
- <ignore text="$ignoretext"/>
- </form>
- </template>
-
- <template name="okcancelbuttons">
- <form>
- <button
- name="OK"
- text="$yestext"/>
- <button
- name="Cancel"
- text="$notext"/>
- </form>
- </template>
-
- <template name="okcancelignore">
- <form>
- <button
- name="OK"
- text="$yestext"/>
- <button
- name="Cancel"
- text="$notext"/>
- <ignore text="$ignoretext"/>
- </form>
- </template>
-
- <template name="okhelpbuttons">
- <form>
- <button
- name="OK"
- text="$yestext"/>
- <button
- name="Help"
- text="$helptext"/>
- </form>
- </template>
-
- <template name="yesnocancelbuttons">
- <form>
- <button
- name="Yes"
- text="$yestext"/>
- <button
- name="No"
- text="$notext"/>
- <button
- name="Cancel"
- text="$canceltext"/>
- </form>
- </template>
+ <global name="implicitclosebutton">
+ Schließen
+ </global>
+ <template name="okbutton">
+ <form>
+ <button name="OK" text="$yestext"/>
+ </form>
+ </template>
+ <template name="okignore"/>
+ <template name="okcancelbuttons">
+ <form>
+ <button name="Cancel" text="$notext"/>
+ </form>
+ </template>
+ <template name="okcancelignore"/>
+ <template name="okhelpbuttons">
+ <form>
+ <button name="Help" text="$helptext"/>
+ </form>
+ </template>
+ <template name="yesnocancelbuttons">
+ <form>
+ <button name="Yes" text="$yestext"/>
+ <button name="No" text="$notext"/>
+ </form>
+ </template>
<notification functor="GenericAcknowledge" label="Unbekannter Warnhinweis" name="MissingAlert">
- Ihre Version von Second Life kann den gerade empfangenen Warnhinweis nicht anzeigen.
+ Ihre Version von [APP_NAME] kann den gerade empfangenen Warnhinweis nicht anzeigen. Bitte vergewissern Sie sich, dass Sie den aktuellsten Viewer installiert haben.
-Fehlerdetails: Der Warnhinweis „[_NAME]“ wurde in notifications.xml nicht gefunden.
+Fehlerdetails: Der Warnhinweis &apos;[_NAME]&apos; wurde in notifications.xml nicht gefunden.
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="FloaterNotFound">
@@ -94,13 +56,13 @@ Fehlerdetails: Der Warnhinweis „[_NAME]“ wurde in notifications.xml nicht ge
<usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="Ja"/>
</notification>
<notification name="BadInstallation">
- Beim Aktualisieren von Second Life ist ein Fehler aufgetreten. Bitte laden Sie die aktuellste Version von secondlife.com herunter.
+ Beim Aktualisieren von [APP_NAME] ist ein Fehler aufgetreten. Bitte [http://get.secondlife.com laden Sie die aktuellste Version des Viewers herunter].
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="LoginFailedNoNetwork">
- Netzwerk Fehler: Eine Verbindung konnte nicht hergestellt werden.
-„[DIAGNOSTIC]“
-Bitte überprüfen Sie Ihre Netzwerkverbindung.
+ Eine Verbindung zum [SECOND_LIFE_GRID] konnte nicht hergestellt werden.
+&apos;[DIAGNOSTIC]&apos;
+Bitte vergewissern Sie sich, dass Ihre Internetverbindung funktioniert.
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="MessageTemplateNotFound">
@@ -132,12 +94,12 @@ Wählen Sie ein einzelnes Objekt aus und versuchen Sie es erneut.
<usetemplate canceltext="Abbrechen" name="yesnocancelbuttons" notext="Nicht speichern" yestext="Alles speichern"/>
</notification>
<notification name="GrantModifyRights">
- Die Gewährung von Änderungsrechten an andere Einwohner ermöglicht es diesen, JEDES BELIEBIGE Objekt zu ändern oder an sich zu nehmen, das Sie in der Second Life-Welt besitzen. Seien Sie SEHR vorsichtig beim Erteilen dieser Erlaubnis.
+ Die Gewährung von Änderungsrechten an andere Einwohner ermöglicht es diesen, JEDES BELIEBIGE Objekt zu ändern oder an sich zu nehmen, das Sie in der [SECOND_LIFE]-Welt besitzen. Seien Sie SEHR vorsichtig beim Erteilen dieser Erlaubnis.
Möchten Sie [FIRST_NAME] [LAST_NAME] Änderungsrechte gewähren?
<usetemplate name="okcancelbuttons" notext="Nein" yestext="Ja"/>
</notification>
<notification name="GrantModifyRightsMultiple">
- Die Gewährung von Änderungsrechten an andere Einwohner ermöglicht es diesen, JEDES BELIEBIGE Objekt zu ändern, das Sie in der Second Life-Welt besitzen. Seien Sie SEHR vorsichtig beim Erteilen dieser Erlaubnis.
+ Die Gewährung von Änderungsrechten an andere Einwohner ermöglicht es diesen, JEDES BELIEBIGE Objekt zu ändern, das Sie in der [SECOND_LIFE]-Welt besitzen. Seien Sie SEHR vorsichtig beim Erteilen dieser Erlaubnis.
Möchten Sie den ausgewählten Einwohnern Änderungsrechte gewähren?
<usetemplate name="okcancelbuttons" notext="Nein" yestext="Ja"/>
</notification>
@@ -168,7 +130,7 @@ Möchten Sie den ausgewählten Einwohnern Änderungsrechte gewähren?
Diese Rolle kann Mitgliedern nicht mehr entzogen werden.
Sie müssen die Rolle selbst niederlegen.
Möchten Sie fortfahren?
- <usetemplate ignoretext="Beim Hinzufügen von Gruppenmitgliedern zur Eigentümerrolle" name="okcancelignore" notext="Nein" yestext="Ja"/>
+ <usetemplate ignoretext="Bestätigen, bevor ich einen neuen Gruppeneigentümer hinzufüge" name="okcancelignore" notext="Nein" yestext="Ja"/>
</notification>
<notification name="AssignDangerousActionWarning">
Sie sind im Begriff, der Rolle „[ROLE_NAME]“ die Fähigkeit „[ACTION_NAME]“ zuzuweisen.
@@ -194,52 +156,8 @@ Der Rolle „[ROLE_NAME]“ diese Fähigkeit zuweisen?
Der Rolle „[ROLE_NAME]“ diese Fähigkeit zuweisen?
<usetemplate name="okcancelbuttons" notext="Nein" yestext="Ja"/>
</notification>
- <notification name="ClickPublishHelpLand">
- Auswahl von „In Suche veröffentlichen“
-Dieses Kontrollkästchen zeigt Folgendes an:
-- diese Parzelle in den Suchergebnissen
-- die öffentlichen Objekte dieser Parzelle
-- diese Parzelle in der Websuche
- </notification>
- <notification name="ClickSoundHelpLand">
- Medien und Musik können nur innerhalb der Parzelle abgespielt werden. Sound- und Voice-Chat-Optionen können auf die Parzelle beschränkt werden oder von Einwohnern außerhalb der Parzelle, entsprechend ihrer Alterseinstufung, gehört werden. Möchten Sie unsere Knowledgebase besuchen, um mehr darüber zu erfahren, wie diese Optionen eingestellt werden können?
- <url name="url">
- http://wiki.secondlife.com/wiki/Medien_auf_Parzellen_(KB)
- </url>
- <usetemplate name="okcancelbuttons" notext="Schließen" yestext="Zur Knowledgbase"/>
- </notification>
- <notification name="ClickSearchHelpAll">
- Die Suchergebnisse wurde aufgrund der entsprechenden Registerkarte, Ihrer Alterseinstufung, der gewählten Kategorie und anderen Faktoren geordnet. Bitte besuchen Sie unsere Knowledgebase, um weitere Informationen zu erhalten.
- <url name="url">
- http://wiki.secondlife.com/wiki/FAQ_zur_Suchfunktion_(KB)
- </url>
- <usetemplate name="okcancelbuttons" notext="Schließen" yestext="Zur Knowledgbase"/>
- </notification>
- <notification name="ClickPublishHelpLandDisabled">
- Diese Parzelle kann nicht in der Suche angezeigt werden, da sie sich in einer Region befindet, die das verbietet.
- </notification>
- <notification name="ClickPublishHelpAvatar">
- Auswahl von „In Suche anzeigen“ zeigt Folgendes an:
-- Ihr Profil in den Suchergebnissen
-- einen Link auf Ihr Profil in den öffentlichen Gruppenseiten
- </notification>
- <notification name="ClickPartnerHelpAvatar">
- Auf der [SECOND_LIFE] Website können Sie anderen Einwohnern eine Partnerschaft vorschlagen und bestehende Partnerschaften lösen.
-
-Die Second Life Website für weitere Informationen über Partnerschaften öffnen?
- <usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="Gehe zu Seite"/>
- </notification>
- <notification name="ClickUploadHelpPermissions">
- Ihre Standardberechtigung funktionieren in älteren Regionen möglicherweise nicht.
- </notification>
- <notification name="ClickWebProfileHelpAvatar">
- Wenn dieser Einwohner einen Webprofil-URL angegeben hat, können Sie:
- * Auf „Laden“ klicken und die Seite in dieser Web-Registerkarte anzeigen.
- * Auf Laden &gt; „In externem Browser“ klicken und die Seite im Standard-Browser anzeigen.
- * Auf Laden &gt; „Start-URL“ klicken und zum Webprofil des Bewohners zurückkehren.
-
-In Ihrem eigenen Profil können Sie jeden beliebigen URL als Ihr Webprofil eingeben und mit OK übernehmen.
-Wenn sich andere Einwohner Ihr Profil ansehen, können sie diesen URL besuchen.
+ <notification name="ClickUnimplemented">
+ Leider ist diese Funktion noch nicht implementiert.
</notification>
<notification name="JoinGroupCanAfford">
Der Beitritt zu dieser Gruppe kostet [COST] L$.
@@ -250,6 +168,12 @@ Fortfahren?
Der Beitritt zu dieser Gruppe kostet [COST] L$.
Sie haben nicht genug L$, um dieser Gruppe beizutreten.
</notification>
+ <notification name="CreateGroupCost">
+ Die Gründung dieser Gruppe kostet 100 L$.
+Gruppen müssen mehr als ein Mitglied haben oder sie werden gelöscht.
+Bitte laden Sie innerhalb von 48 Stunden Mitglieder in Ihre Gruppe ein.
+ <usetemplate canceltext="Abbrechen" name="okcancelbuttons" notext="Abbrechen" yestext="Gruppe für 100 L$ erstellen"/>
+ </notification>
<notification name="LandBuyPass">
Sie können dieses Land („[PARCEL_NAME]“) für [COST] L$
[TIME] Stunden lang betreten. Pass kaufen?
@@ -265,9 +189,9 @@ Der Verkaufspreis beträgt [SALE_PRICE] L$ und wird automatisch für den Verkauf
<usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/>
</notification>
<notification name="ConfirmLandSaleToAnyoneChange">
- ACHTUNG: Wenn Sie auf „An jeden verkaufen“ klicken, kann jeder in Second Life Ihr Land kaufen, auch Einwohner in anderen Regionen.
+ ACHTUNG: Wenn Sie auf An jeden verkaufen klicken, kann jeder in [SECOND_LIFE] Ihr Land kaufen, auch Einwohner in anderen Regionen.
-Die ausgewählten [LAND_SIZE] qm Land werden zum Verkauf freigegeben.
+Die ausgewählten [LAND_SIZE] m² Land werden zum Verkauf freigegeben.
Der Verkaufspreis beträgt [SALE_PRICE] L$ und wird automatisch für den Verkauf an [NAME] autorisiert.
<usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/>
</notification>
@@ -328,6 +252,16 @@ Objekte: [N]
Für die gesamte Region ist Schaden aktiviert.
Damit Waffen funktionieren, müssen Skripts erlaubt sein.
</notification>
+ <notification name="MultipleFacesSelected">
+ Momentan sind mehrere Seiten ausgewählt. Wenn Sie fortfahren, werden einzelne Medien auf mehreren Seiten des Objektes dargestellt. Um die Medien auf einer einzigen Seite darzustellen, wählen Sie Textur auswählen und klicken Sie auf die gewünschte Seite. Danach klicken Sie Hinzufügen.
+ <usetemplate ignoretext="Die Medien werden auf mehrere ausgewählte Seiten übertragen" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
+ </notification>
+ <notification name="WhiteListInvalidatesHomeUrl">
+ Wenn Sie diesen Eintrag zur Whitelist hinzufügen, dann wird die URL,
+die Sie für diese Medien-Instanz festgelegt haben, ungültig. Dies ist nicht zulässig.
+Der Eintrag kann nicht zur Whitelist hinzugefügt werden.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
<notification name="MustBeInParcel">
Sie müssen auf einer Landparzelle stehen, um ihren Landepunkt festzulegen.
</notification>
@@ -363,6 +297,10 @@ Der Outfit-Ordner enthält keine Kleidung, Körperteile oder Anhänge.
<notification name="CannotWearTrash">
Kleider oder Körperteile im Papierkorb können nicht getragen werden
</notification>
+ <notification name="MaxAttachmentsOnOutfit">
+ Objekt konnte nicht angehängt werden.
+Überschreitet die maximale Anzahl an Objekten [MAX_ATTACHMENTS], die angehängt werden können. Bitte nehmen Sie zunächst ein anderes Objekt ab.
+ </notification>
<notification name="CannotWearInfoNotComplete">
Sie können das Objekt nicht anziehen, weil es noch nicht geladen wurde. Warten Sie kurz und versuchen Sie es dann noch einmal.
</notification>
@@ -371,17 +309,28 @@ Der Outfit-Ordner enthält keine Kleidung, Körperteile oder Anhänge.
Geben Sie bitte den Vor- und den Nachnamen Ihres Avatars ein.
Sie benötigen ein Benutzerkonto, um [SECOND_LIFE] betreten zu können. Möchten Sie jetzt ein Benutzerkonto anlegen?
+ <url name="url">
+ https://join.secondlife.com/index.php?lang=de-DE
+ </url>
<usetemplate name="okcancelbuttons" notext="Erneut versuchen" yestext="Neues Benutzerkonto anlegen"/>
</notification>
<notification name="AddClassified">
- Anzeigen erscheinen für eine Woche unter „Anzeigen“ im Suchverzeichnis. Füllen Sie Ihre Anzeige aus und klicken Sie auf „Veröffentlichen...“, um sie zum Verzeichnis hinzuzufügen. Sie werden gebeten, einen Preis zu bezahlen, wenn Sie auf „Veröffentlichen“ klicken. Wenn Sie mehr bezahlen oder ein Benutzer nach Ihren Suchbegriffen sucht, erscheint Ihre Anzeige weiter oben in der Liste.
- <usetemplate ignoretext="Beim Hinzufügen einer neuen Anzeige" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
+ Anzeigen werden im Suchverzeichnis im Abschnitt „Anzeigen&quot; und auf [http://secondlife.com/community/classifieds secondlife.com] für eine Woche angezeigt.
+Füllen Sie Ihre Anzeige aus und klicken Sie auf &apos;Veröffentlichen...&apos;, um sie zum Verzeichnis hinzuzufügen.
+Sie werden gebeten, einen Preis zu bezahlen, wenn Sie auf &apos;Veröffentlichen&apos; klicken.
+Wenn Sie mehr bezahlen, erscheint Ihre Anzeige weiter oben in der Liste, ebenso wenn ein Benutzer nach Ihren Suchbegriffen sucht.
+ <usetemplate ignoretext="So wird eine neue Anzeige erstellt" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
</notification>
<notification name="DeleteClassified">
Anzeige „[NAME]“ löschen?
Gebühren werden nicht rückerstattet.
<usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/>
</notification>
+ <notification name="DeleteMedia">
+ Sie haben sich entschieden, die Medien auf dieser Seite zu löschen.
+Sind Sie sicher, dass Sie fortfahren wollen?
+ <usetemplate ignoretext="Bestätigen, bevor ich Medien von einem Objekt entferne." name="okcancelignore" notext="Nein" yestext="Ja"/>
+ </notification>
<notification name="ClassifiedSave">
Änderung an Anzeige [NAME] speichern?
<usetemplate canceltext="Abbrechen" name="yesnocancelbuttons" notext="Nicht speichern" yestext="Speichern"/>
@@ -392,6 +341,9 @@ Gebühren werden nicht rückerstattet.
</notification>
<notification name="PromptGoToEventsPage">
Zur [SECOND_LIFE] Events-Webseite?
+ <url name="url">
+ http://secondlife.com/events/?lang=de-DE
+ </url>
<usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/>
</notification>
<notification name="SelectProposalToView">
@@ -409,20 +361,23 @@ Gebühren werden nicht rückerstattet.
<usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/>
</notification>
<notification name="CacheWillClear">
- Der Cache wird nach einem Neustart von [SECOND_LIFE] geleert.
+ Der Cache wird nach einem Neustart von [APP_NAME] geleert.
</notification>
<notification name="CacheWillBeMoved">
- Der Cache wird nach einem Neustart von [SECOND_LIFE] verschoben.
+ Der Cache wird nach einem Neustart von [APP_NAME] verschoben.
Hinweis: Der Cache wird dabei gelöscht/geleert.
</notification>
<notification name="ChangeConnectionPort">
- Die Port-Einstellungen werden nach einem Neustart von [SECOND_LIFE] wirksam.
+ Die Port-Einstellungen werden nach einem Neustart von [APP_NAME] wirksam.
</notification>
<notification name="ChangeSkin">
- Die neue Benutzeroberfläche wird nach einem Neustart von [SECOND_LIFE] angewendet.
+ Die neue Benutzeroberfläche wird nach einem Neustart von [APP_NAME] angezeigt.
</notification>
<notification name="GoToAuctionPage">
Zur [SECOND_LIFE]-Webseite, um Auktionen anzuzeigen oder ein Gebot abzugeben?
+ <url name="url">
+ http://secondlife.com/auctions/auction-detail.php?id=[AUCTION_ID]
+ </url>
<usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/>
</notification>
<notification name="SaveChanges">
@@ -467,6 +422,11 @@ Das Objekt ist möglicherweise außer Reichweite oder wurde gelöscht.
<notification name="SaveBytecodeFailReason">
Ein kompiliertes Skript konnte aus folgendem Grund nicht gespeichert werden: [REASON]. Speichern Sie das Skript bitte später.
</notification>
+ <notification name="StartRegionEmpty">
+ Sie haben keine Start-Region festgelegt.
+Bitte geben Sie den Namen der Region im Feld „Startposition“ ein oder wählen Sie „Mein letzter Standort“ oder „Mein Heimatort“ als Startposition aus.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
<notification name="CouldNotStartStopScript">
Skript konnte nicht gestartet oder beendet werden, weil das zugehörige Objekt nicht gefunden wurde.
Das Objekt ist möglicherweise außer Reichweite oder wurde gelöscht.
@@ -478,30 +438,28 @@ Das Objekt ist möglicherweise außer Reichweite oder wurde gelöscht.
Datei [[FILE]] kann nicht geschrieben werden
</notification>
<notification name="UnsupportedHardware">
- Achtung: Ihr System erfüllt nicht die Mindestanforderungen von Second Life. Dies kann eine schlechte Darstellungsleistung in Second Life zur Folge haben. Für nicht unterstützte Systemkonfigurationen bieten wir keinen technischen Support.
+ Achtung: Ihr System erfüllt nicht die Mindestanforderungen von [APP_NAME]. Dies kann eine schlechte Darstellungsleistung in [APP_NAME] zur Folge haben. Bei nicht unterstützten Systemkonfigurationen kann Ihnen unsere [SUPPORT_SITE] leider nicht helfen.
-MINSPECS
+MINDESTANF.
Die Seite [_URL] für weitere Informationen öffnen?
<url name="url" option="0">
http://secondlife.com/support/sysreqs.php?lang=de
</url>
- <usetemplate ignoretext="Bei Entdeckung nicht unterstützter Hardware" name="okcancelignore" notext="Nein" yestext="Ja"/>
+ <usetemplate ignoretext="Meine Hardware wird nicht unterstützt" name="okcancelignore" notext="Nein" yestext="Ja"/>
</notification>
<notification name="UnknownGPU">
Ihr System verwendet eine uns zurzeit unbekannte Grafikkarte.
-Dies ist häufig der Fall bei neuer Hardware, die wir noch nicht testen konnten.
-Second Life funktioniert aller Voraussicht nach normal, möglicherweise müssen Sie aber die Grafikeinstellungen anpassen.
-(Bearbeiten &gt; Einstellungen &gt; Grafik).
+Dies passiert dann, wenn die neue Hardware noch nicht mit [APP_NAME] getestet wurde. [APP_NAME] wird wahrscheinlich korrekt ausgeführt werden, jedoch sollten Sie Ihre Grafikeinstellungen anpassen, um eine bessere Darstellung zu erzielen.
+(Ich &gt; Einstellungen &gt; Grafik).
<form name="form">
- <ignore name="ignore" text="Bei Entdeckung einer unbekannten Grafikkarte"/>
+ <ignore name="ignore" text="Meine Grafikkarte konnte nicht identifiziert werden."/>
</form>
</notification>
<notification name="DisplaySettingsNoShaders">
- [SECOND_LIFE] ist bei der Initialisierung der Grafiktreiber abgestürzt.
-Die Grafikqualität wird auf eine niedrige Stufe zurückgesetzt, um einige typische Treiberfehler zu vermeiden.
-Einige Grafikfunktionen werden ausgeschaltet.
+ [APP_NAME] ist bei der Initialisierung der Grafiktreiber abgestürzt.
+Die Grafikqualität wird auf Niedrig gesetzt, um einige typische Treiberfehler zu vermeiden. Einige Grafikfunktionen werden ausgeschaltet.
Wir empfehlen die Aktualisierung Ihrer Grafikkartentreiber.
-Sie können die Grafikqualität unter „Einstellungen“ &gt; „Grafik“ wieder erhöhen.
+Sie können die Grafikqualität unter Einstellungen &gt; Grafik wieder erhöhen.
</notification>
<notification name="RegionNoTerraforming">
Die Region [REGION] erlaubt kein Terraforming.
@@ -552,6 +510,9 @@ Der Avatar wird außer Gefecht gesetzt und kann sich nicht mehr bewegen, chatten
[AVATAR_NAME] aus Ihrem Land werfen?
<usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="Hinauswerfen"/>
</notification>
+ <notification name="EjectAvatarFromGroup">
+ Sie haben [AVATAR_NAME] aus der Gruppe [GROUP_NAME] geworfen.
+ </notification>
<notification name="AcquireErrorTooManyObjects">
FEHLER: Zu viele Objekte ausgewählt.
</notification>
@@ -562,7 +523,10 @@ Verschieben Sie alle betreffenden Objekte in dieselbe Region.
<notification name="PromptGoToCurrencyPage">
[EXTRA]
-[URL] für Informationen zum Deviseneinkauf öffnen?
+[_URL] für Informationen zum Kauf von L$ öffnen?
+ <url name="url">
+ http://secondlife.com/app/currency/?lang=de-DE
+ </url>
<usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/>
</notification>
<notification name="UnableToLinkObjects">
@@ -648,12 +612,15 @@ Erwartet wurde [VALIDS]
Ausgabedatei konnte nicht erstellt werden: [FILE]
</notification>
<notification name="DoNotSupportBulkAnimationUpload">
- Der Mehrfach-Upload von Animationsdateien wird zurzeit nicht unterstützt.
+ Der Mehrfach-Upload von Animationsdateien wird zurzeit von [APP_NAME] nicht unterstützt.
</notification>
<notification name="CannotUploadReason">
Datei [FILE] kann aus folgendem Grund nicht hochgeladen werden: [REASON]
Bitte versuchen Sie es erneut.
</notification>
+ <notification name="LandmarkCreated">
+ „[LANDMARK_NAME]“ wurde zum Ordner „[FOLDER_NAME]“ hinzugefügt.
+ </notification>
<notification name="CannotCreateLandmarkNotOwner">
Sie können hier keine Landmarke erstellen, da der Landeigentümer dies verboten hat.
</notification>
@@ -676,6 +643,9 @@ Wählen Sie Objekte mit Skripts.
Wählen Sie Objekte mit Skripts, die Sie bearbeiten dürfen.
</notification>
+ <notification name="CannotOpenScriptObjectNoMod">
+ Das Skript im Objekt kann nicht geöffnet werden, da keine Änderungs-Berechtigungen vorliegen.
+ </notification>
<notification name="CannotSetRunningSelectObjectsNoScripts">
„Ausführen“ von Skripts nicht möglich.
@@ -704,12 +674,12 @@ Es wurde keine Suche durchgeführt.
[REASON]
</notification>
<notification name="invalid_tport">
- Bei der Bearbeitung Ihrer Teleport-Anfrage ist ein Problem aufgetreten. Sie müssen sich zum Teleportieren eventuell neu anmelden. Wenn Sie diese Nachricht weiterhin erhalten, konsultieren Sie bitte die Tech-Support-FAQ unter:
-www.secondlife.com/support
+ Bei der Bearbeitung Ihrer Teleport-Anfrage ist ein Problem aufgetreten. Sie müssen sich zum Teleportieren eventuell neu anmelden.
+Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich bitte an [SUPPORT_SITE].
</notification>
<notification name="invalid_region_handoff">
- Bei der Bearbeitung Ihres Regionswechsels ist ein Problem aufgetreten. Sie müssen sich zum Wechsel der Region eventuell neu anmelden. Wenn Sie diese Nachricht weiterhin erhalten, konsultieren Sie bitte die Tech-Support-FAQ unter:
-www.secondlife.com/support
+ Bei der Bearbeitung Ihres Regionswechsels ist ein Problem aufgetreten. Sie müssen eventuell neu anmelden, um die Region wechseln zu können.
+Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich bitte an [SUPPORT_SITE].
</notification>
<notification name="blocked_tport">
Teleportieren ist zurzeit leider nicht möglich. Versuchen Sie es später noch einmal.
@@ -780,8 +750,7 @@ Keine Parzelle ausgewählt.
Kann die Region nicht finden, in der sich dieses Land befindet.
</notification>
<notification name="CannotCloseFloaterBuyLand">
- Das Fenster „Land kaufen“ kann erst geschlossen werden,
-nachdem Second Life den Transaktionspreis geschätzt hat.
+ Das Fenster Land kaufen kann nicht geschlossen werden, bevor [APP_NAME] den Preis für diese Transaktion eingeschätzt hat.
</notification>
<notification name="CannotDeedLandNothingSelected">
Land kann nicht übertragen werden:
@@ -794,7 +763,6 @@ Keine Gruppe ausgewählt.
<notification name="CannotDeedLandNoRegion">
Land kann nicht übertragen werden:
Kann die Region nicht finden, in der sich dieses Land befindet.
-Bitte melden Sie dies über „Hilfe“ &gt; „Fehler melden“.
</notification>
<notification name="CannotDeedLandMultipleSelected">
Land kann nicht übertragen werden:
@@ -840,8 +808,6 @@ Parzellen, die Ihnen gehören, werden grün dargestellt.
<notification name="CannotReleaseLandRegionNotFound">
Land kann nicht aufgegeben werden:
Kann die Region nicht finden, in der sich dieses Land befindet.
-
-Bitte melden Sie dies über „Hilfe“ &gt; „Fehler melden“.
</notification>
<notification name="CannotReleaseLandNoTransfer">
Land kann nicht aufgegeben werden:
@@ -880,14 +846,10 @@ Land teilen?
<notification name="CannotDivideLandNoRegion">
Land kann nicht aufgeteilt werden:
Kann die Region nicht finden, in der sich dieses Land befindet.
-
-Bitte melden Sie dies über „Hilfe“ &gt; „Fehler melden“.
</notification>
<notification name="CannotJoinLandNoRegion">
Land kann nicht zusammengelegt werden:
Kann die Region nicht finden, in der sich dieses Land befindet.
-
-Bitte melden Sie dies über „Hilfe“ &gt; „Fehler melden“.
</notification>
<notification name="CannotJoinLandNothingSelected">
Land kann nicht zusammengelegt werden:
@@ -913,17 +875,6 @@ Sie müssen der neuen Parzelle einen Namen geben und ihre Optionen festlegen.
Land zusammenlegen?
<usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/>
</notification>
- <notification name="ShowOwnersHelp">
- Eigentümer anzeigen:
-Parzellen farblich kennzeichnen, um Eigentumsart anzuzeigen.
-
-Grün = Ihr Land
-Blau = Das Land Ihrer Gruppe
-Rot = Im Eigentum anderer
-Geld = Zum Verkauf
-Lila = Zur Auktion
-Grau = Öffentlich
- </notification>
<notification name="ConfirmNotecardSave">
Um das Objekt kopieren oder anzeigen zu können, müssen Sie zuerst diese Notizkarte speichern. Notizkarte speichern?
<usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/>
@@ -947,13 +898,11 @@ Grau = Öffentlich
<notification name="CannotSaveToAssetStore">
[NAME] kann nicht in Zentral-Asset-Speicher geladen werden.
Dies ist ein temporärer Fehler. Bitte passen Sie das Kleidungsstück in einigen Minuten noch einmal an und speichern Sie es erneut.
-
-Tritt dieses Problem wiederholt auf, klicken Sie auf das Pulldown-Menü „Hilfe“ &gt; „Fehler melden“ und geben Sie Details zu Ihrem Netzwerk-Setup an.
</notification>
<notification name="YouHaveBeenLoggedOut">
Sie wurden von [SECOND_LIFE] abgemeldet:
[MESSAGE]
-Klicken Sie auf „IM &amp; Chat anzeigen“, um vorhandene Nachrichten und Chat weiterhin anzuzeigen. Klicken Sie andernfalls auf „Beenden“, um [SECOND_LIFE] sofort zu beenden.
+Klicken Sie auf „IM &amp; Chat anzeigen“, um vorhandene Nachrichten und Chat weiterhin anzuzeigen. Um [APP_NAME] zu schließen, auf „Beenden“ klicken.
<usetemplate name="okcancelbuttons" notext="Beenden" yestext="IM &amp; Chat anzeigen"/>
</notification>
<notification name="OnlyOfficerCanBuyLand">
@@ -971,7 +920,7 @@ Sie sind nicht berechtigt, Land für die aktive Gruppe zu kaufen.
[NAME] Freundschaft anbieten?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Wollen wir Freunde sein?
</input>
<button name="Offer" text="OK"/>
@@ -1112,28 +1061,40 @@ Der Gruppe „[GROUP_NAME]“
<notification name="ErrorMessage">
[ERROR_MESSAGE]
</notification>
- <notification name="AvatarMoved">
- Ihr [TYPE]-Ort ist zurzeit nicht verfügbar. [HELP]
+ <notification name="AvatarMovedDesired">
+ Ihr gewünschter Zielort ist zurzeit nicht verfügbar.
+Sie wurden zur nächstgelegenen Region teleportiert.
+ </notification>
+ <notification name="AvatarMovedLast">
+ Ihr letzter Standort ist zurzeit nicht verfügbar.
+Sie wurden zur nächstgelegenen Region teleportiert.
+ </notification>
+ <notification name="AvatarMovedHome">
+ Ihr Heimatort ist zurzeit nicht verfügbar.
Sie wurden zur nächstgelegenen Region teleportiert.
+Sie müssen eventuell einen neuen Heimatort festlegen.
</notification>
<notification name="ClothingLoading">
Ihre Kleidung wird noch heruntergeladen.
Sie können [SECOND_LIFE] normal verwenden. Andere Benutzer können Sie korrekt dargestellt sehen.
<form name="form">
- <ignore name="ignore" text="Wenn das Herunterladen von Kleidung lange dauert"/>
+ <ignore name="ignore" text="Das Herunterladen der Kleidung dauert lange"/>
</form>
</notification>
<notification name="FirstRun">
- Die Installation von [SECOND_LIFE] ist abgeschlossen.
+ Installation von [APP_NAME] vollständig abgeschlossen.
-Wenn Sie [SECOND_LIFE] das erste Mal verwenden, müssen Sie ein Konto anlegen, bevor Sie sich anmelden können.
-Möchten Sie auf www.secondlife.com ein Konto erstellen?
+Falls Sie [SECOND_LIFE] zum ersten Mal verwenden, müssen Sie zuerst ein Konto erstellen, bevor Sie sich anmelden können.
+Zurück zu [http://join.secondlife.com secondlife.com], um ein neues Konto zu erstellen?
<usetemplate name="okcancelbuttons" notext="Weiter" yestext="Neues Konto..."/>
</notification>
<notification name="LoginPacketNeverReceived">
- Die Verbindung kann nicht hergestellt werden. Möglicherweise besteht ein Problem mit Ihrer Internetverbindung oder den Second Life-Servern.
+ Es gibt Probleme mit der Verbindung. Möglicherweise besteht ein Problem mit Ihrer Internetverbindung oder dem [SECOND_LIFE_GRID].
-Überprüfen Sie Ihre Internetverbindung und versuchen Sie es dann erneut, oder klicken Sie auf „Hilfe“, um zu unserer Supportseite zu gelangen, oder klicken Sie auf „Teleportieren“, um nach Hause zu teleportieren.
+Überprüfen Sie Ihre Internetverbindung und versuchen Sie es dann erneut, oder klicken Sie auf Hilfe, um zu [SUPPORT_SITE] zu gelangen, oder klicken Sie auf Teleportieren, um nach Hause zu teleportieren.
+ <url name="url">
+ http://de.secondlife.com/support/
+ </url>
<form name="form">
<button name="OK" text="OK"/>
<button name="Help" text="Hilfe"/>
@@ -1153,10 +1114,10 @@ Sie können sich später noch umentscheiden.
[NAME] [PRICE] L$ Sie haben nicht genügend L$, um diese Aktion auszuführen.
</notification>
<notification name="GrantedModifyRights">
- Sie verfügen über Änderungsrechte für die Objekte von [FIRST_NAME] [LAST_NAME].
+ [NAME] hat Ihnen die Erlaubnis erteilt, ihre/seine Objekte zu bearbeiten.
</notification>
<notification name="RevokedModifyRights">
- Ihnen wurden die Änderungsrechte für die Objekte von [FIRST_NAME] [LAST_NAME] entzogen.
+ Ihnen wurden die Änderungsrechte für die Objekte von [NAME] entzogen.
</notification>
<notification name="FlushMapVisibilityCaches">
Der Kartencache dieser Region wird geleert.
@@ -1234,33 +1195,51 @@ Geben Sie das Objekt zum Verkauf frei und versuchen Sie es erneut.
[DOWNLOAD_PATH].
</notification>
<notification name="DownloadWindowsMandatory">
- Eine neue Version von [SECOND_LIFE] ist verfügbar.
+ Eine neue Version von [SUPPORT_SITE] ist verfügbar.
[MESSAGE]
-Sie müssen das Update herunterladen, um [SECOND_LIFE] weiter verwenden zu können.
+Sie müssen das Update herunterladen, um [APP_NAME] weiter verwenden zu können.
<usetemplate name="okcancelbuttons" notext="Beenden" yestext="Herunterladen"/>
</notification>
<notification name="DownloadWindows">
- Eine aktualisierte Version von [SECOND_LIFE] ist verfügbar.
+ Eine neue Version von [APP_NAME] ist verfügbar.
[MESSAGE]
Dieses Update ist nicht erforderlich, für bessere Leistung und Stabilität sollte es jedoch installiert werden.
<usetemplate name="okcancelbuttons" notext="Weiter" yestext="Herunterladen"/>
</notification>
<notification name="DownloadWindowsReleaseForDownload">
- Eine aktualisierte Version von [SECOND_LIFE] ist verfügbar.
+ Eine neue Version von [APP_NAME] ist verfügbar.
+[MESSAGE]
+Dieses Update ist nicht erforderlich, für bessere Leistung und Stabilität sollte es jedoch installiert werden.
+ <usetemplate name="okcancelbuttons" notext="Weiter" yestext="Herunterladen"/>
+ </notification>
+ <notification name="DownloadLinuxMandatory">
+ Eine neue Version von [SUPPORT_SITE] ist verfügbar.
+[MESSAGE]
+Sie müssen das Update herunterladen, um [APP_NAME] weiter verwenden zu können.
+ <usetemplate name="okcancelbuttons" notext="Beenden" yestext="Herunterladen"/>
+ </notification>
+ <notification name="DownloadLinux">
+ Eine neue Version von [APP_NAME] ist verfügbar.
+[MESSAGE]
+Dieses Update ist nicht erforderlich, für bessere Leistung und Stabilität sollte es jedoch installiert werden.
+ <usetemplate name="okcancelbuttons" notext="Weiter" yestext="Herunterladen"/>
+ </notification>
+ <notification name="DownloadLinuxReleaseForDownload">
+ Eine neue Version von [APP_NAME] ist verfügbar.
[MESSAGE]
Dieses Update ist nicht erforderlich, für bessere Leistung und Stabilität sollte es jedoch installiert werden.
<usetemplate name="okcancelbuttons" notext="Weiter" yestext="Herunterladen"/>
</notification>
<notification name="DownloadMacMandatory">
- Eine neue Version von [SECOND_LIFE] ist verfügbar.
+ Eine neue Version von [SUPPORT_SITE] ist verfügbar.
[MESSAGE]
-Sie müssen das Update herunterladen, um [SECOND_LIFE] weiter verwenden zu können.
+Sie müssen das Update herunterladen, um [APP_NAME] weiter verwenden zu können.
In Ihren Anwendungsordner herunterladen?
<usetemplate name="okcancelbuttons" notext="Beenden" yestext="Herunterladen"/>
</notification>
<notification name="DownloadMac">
- Eine aktualisierte Version von [SECOND_LIFE] ist verfügbar.
+ Eine neue Version von [APP_NAME] ist verfügbar.
[MESSAGE]
Dieses Update ist nicht erforderlich, für bessere Leistung und Stabilität sollte es jedoch installiert werden.
@@ -1268,7 +1247,7 @@ In Ihren Anwendungsordner herunterladen?
<usetemplate name="okcancelbuttons" notext="Weiter" yestext="Herunterladen"/>
</notification>
<notification name="DownloadMacReleaseForDownload">
- Eine aktualisierte Version von [SECOND_LIFE] ist verfügbar.
+ Eine neue Version von [APP_NAME] ist verfügbar.
[MESSAGE]
Dieses Update ist nicht erforderlich, für bessere Leistung und Stabilität sollte es jedoch installiert werden.
@@ -1278,53 +1257,45 @@ In Ihren Anwendungsordner herunterladen?
<notification name="DeedObjectToGroup">
Bei Übertragung dieses Objekts erhält die Gruppe:
* An das Objekt bezahlte L$
- <usetemplate ignoretext="Beim Ãœbertragen von Objekten an Gruppen" name="okcancelignore" notext="Abbrechen" yestext="Ãœbertragung"/>
+ <usetemplate ignoretext="Bestätigen, bevor ich ein Objekt an eine Gruppe übertrage" name="okcancelignore" notext="Abbrechen" yestext="Übertragung"/>
</notification>
<notification name="WebLaunchExternalTarget">
- Den System-Webbrowser öffnen, um diesen Inhalt anzuzeigen?
- <usetemplate ignoretext="Wenn der System-Webbrowser zur Anzeige einer Webseite geöffnet wird" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
+ Möchten Sie Ihren Internetbrowser öffnen, um diesen Inhalt anzuzeigen?
+ <usetemplate ignoretext="Meinen Browser starten, um eine Webseite anzuzeigen" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
</notification>
<notification name="WebLaunchJoinNow">
- Zu www.secondlife.com, um Ihr Konto zu verwalten?
- <usetemplate ignoretext="Beim Starten eines Browsers, um Ihr Konto zu verwalten" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
- </notification>
- <notification name="WebLaunchBugReport101">
- Informieren Sie sich im [SECOND_LIFE] Wiki, wie man Fehler richtig meldet.
- <usetemplate ignoretext="Beim Starten eines Browsers, um das Fehlermeldungs-Wiki anzuzeigen" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
+ Möchten Sie Ihre [http://secondlife.com/account/ Startseite] aufrufen, um Ihr Konto zu verwalten?
+ <usetemplate ignoretext="Meinen Browser starten, um mein Konto zu verwalten" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
</notification>
<notification name="WebLaunchSecurityIssues">
Informieren Sie sich im [SECOND_LIFE] Wiki, wie man Sicherheitsprobleme richtig meldet.
- <usetemplate ignoretext="Beim Starten eines Browsers, um das Sicherheitsfragen-Wiki anzuzeigen" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
+ <usetemplate ignoretext="Meinen Browser starten, um anzuzeigen, wie ein Sicherheitsproblem gemeldet werden soll" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
</notification>
<notification name="WebLaunchQAWiki">
Besuchen Sie das [SECOND_LIFE] QA-Wiki.
- <usetemplate ignoretext="Beim Starten eines Browsers, um das QA-Wiki anzuzeigen" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
+ <usetemplate ignoretext="Meinen Browser starten, um das QA-Wiki anzuzeigen" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
</notification>
<notification name="WebLaunchPublicIssue">
Im [SECOND_LIFE] Allgemeine-Fragen-Tracker können Sie Fehler und andere Probleme melden.
- <usetemplate ignoretext="Beim Starten eines Browsers, um den Allgemeine Probleme Tracker anzuzeigen" name="okcancelignore" notext="Abbrechen" yestext="Gehe zu Seite"/>
- </notification>
- <notification name="WebLaunchPublicIssueHelp">
- Informieren Sie sich im [SECOND_LIFE] Wiki über den Allgemeine Fragen-Tracker.
- <usetemplate ignoretext="Beim Starten eines Browsers, um das Allgemeine Fragen-Wiki anzuzeigen" name="okcancelignore" notext="Abbrechen" yestext="Gehe zu Seite"/>
+ <usetemplate ignoretext="Meinen Browser starten, um die Datenbank für Fehler und Verbesserungsvorschläge anzuzeigen" name="okcancelignore" notext="Abbrechen" yestext="Gehe zu Seite"/>
</notification>
<notification name="WebLaunchSupportWiki">
Im offiziellen Linden-Blog finden Sie die neuesten Nachrichten und Informationen.
- <usetemplate ignoretext="Beim Starten eines Browsers, um das Blog anzuzeigen" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
+ <usetemplate ignoretext="Meinen Browser starten, um das Blog anzuzeigen" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
</notification>
<notification name="WebLaunchLSLGuide">
- Zur Scripting-Anleitung, um Scripting-Hilfe zu erhalten?
- <usetemplate ignoretext="Beim Starten eines Browsers, um die Scripting-Anleitung anzuzeigen" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
+ Möchten Sie den Scripting Guide öffnen?
+ <usetemplate ignoretext="Meinen Browser starten, um den Scripting Guide anzuzeigen" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
</notification>
<notification name="WebLaunchLSLWiki">
- Zum LSL-Portal, um Scripting-Hilfe zu erhalten?
- <usetemplate ignoretext="Beim Starten eines Browsers, um das LSL-Portal anzuzeigen" name="okcancelignore" notext="Abbrechen" yestext="Gehe zu Seite"/>
+ Möchten Sie das LSL-Portal besuchen?
+ <usetemplate ignoretext="Meinen Browser starten, um das LSL-Portal anzuzeigen" name="okcancelignore" notext="Abbrechen" yestext="Gehe zu Seite"/>
</notification>
<notification name="ReturnToOwner">
Möchten Sie die ausgewählten Objekte an ihre Eigentümer zurückgeben? Transferierbare übertragene Objekte werden ihren früheren Eigentümern zurückgegeben.
*WARNUNG* Nicht transferierbare übertragene Objekte werden dabei gelöscht!
- <usetemplate ignoretext="Beim Zurückgeben von Objekten an ihre Eigentümer" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
+ <usetemplate ignoretext="Bestätigen, bevor Objekte an Ihre Eigentümer zurückgegeben werden" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
</notification>
<notification name="GroupLeaveConfirmMember">
Sie sind Mitglied der Gruppe [GROUP].
@@ -1336,14 +1307,14 @@ Diese Gruppe verlassen?
<usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="Alle Benutzer hinauswerfen"/>
</notification>
<notification name="MuteLinden">
- Lindens können nicht stummgeschaltet werden.
+ Lindens können nicht ignoriert werden.
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="CannotStartAuctionAlreadyForSale">
Eine Parzelle, die bereits zum Verkauf freigegeben ist, kann nicht versteigert werden. Deaktivieren Sie den Landverkauf, wenn Sie das Land zur Versteigerung freigeben möchten.
</notification>
- <notification label="Objekt nach Name stummschalten fehlgeschlagen" name="MuteByNameFailed">
- Dieser Name ist bereits stummgeschaltet.
+ <notification label="Objekt nach Name ignorieren ist fehlgeschlagen" name="MuteByNameFailed">
+ Dieser Name wird bereits ignoriert.
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="RemoveItemWarn">
@@ -1359,21 +1330,20 @@ Diese Gruppe verlassen?
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="BusyModeSet">
- Beschäftigt-Modus aktiviert.
-Chat und Instant Messages werden ausgeblendet. Instant Messages erhalten Ihre Beschäftigt-Antwort. Alle Teleport-Angebote werden ausgeschlagen. Alle Inventar-Angebote werden in den Papierkorb verschoben.
- <usetemplate ignoretext="Beim Aktivieren des Beschäftigt-Modus" name="okignore" yestext="OK"/>
+ Beschäftigt-Modus ist aktiviert.
+Chat und Instant Messages werden ausgeblendet. Instant Messages (Sofortnachrichten) erhalten Ihre Beschäftigt-Antwort. Alle Teleport-Angebote werden abgelehnt. Alle Inventar-Angebote werden in Ihren Papierkorb geschoben.
+ <usetemplate ignoretext="Ich ändere meinen Status zu Beschäftigt" name="okignore" yestext="OK"/>
</notification>
<notification name="JoinedTooManyGroupsMember">
- Sie sind bereits in zu vielen Gruppen Mitglied und können keiner weiteren beitreten. Bitte verlassen Sie eine Gruppe, bevor Sie dieser beitreten oder lehnen Sie das Angebot ab.
-Die Option zum Austritt aus einer Gruppe finden Sie unter „Bearbeiten“ &gt; „Gruppen...“.
-[NAME] hat Sie eingeladen, einer Gruppe beizutreten.
+ Sie haben die maximale Anzahl an Gruppen erreicht. Bitte verlassen Sie eine andere Gruppe, um dieser beitreten zu können oder lehnen Sie das Angebot ab.
+[NAME] hat Sie eingeladen, einer Gruppe beizutreten.
[INVITE]
<usetemplate name="okcancelbuttons" notext="Ablehnen" yestext="Beitreten"/>
</notification>
<notification name="KickUser">
Beim Hinauswerfen dieses Benutzers welche Meldung anzeigen?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Sie wurden von einem Administrator abgemeldet.
</input>
<button name="OK" text="OK"/>
@@ -1383,7 +1353,7 @@ Die Option zum Austritt aus einer Gruppe finden Sie unter „Bearbeiten“ &gt;
<notification name="KickAllUsers">
Beim Hinauswerfen aller Personen vom Grid welche Meldung anzeigen?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Sie wurden von einem Administrator abgemeldet.
</input>
<button name="OK" text="OK"/>
@@ -1393,7 +1363,7 @@ Die Option zum Austritt aus einer Gruppe finden Sie unter „Bearbeiten“ &gt;
<notification name="FreezeUser">
Beim Einfrieren dieses Benutzers welche Meldung anzeigen?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Sie wurden eingefroren. Bewegen oder Chatten ist nicht mehr möglich. Ein Administrator wird sich über IM an Sie wenden
</input>
<button name="OK" text="OK"/>
@@ -1403,7 +1373,7 @@ Die Option zum Austritt aus einer Gruppe finden Sie unter „Bearbeiten“ &gt;
<notification name="UnFreezeUser">
Beim Auftauen dieses Benutzers welche Meldung anzeigen?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Sie sind nicht mehr eingefroren.
</input>
<button name="OK" text="OK"/>
@@ -1413,7 +1383,7 @@ Die Option zum Austritt aus einer Gruppe finden Sie unter „Bearbeiten“ &gt;
<notification name="OfferTeleport">
Teleport an Ihre Position mit der folgenden Meldung anbieten?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Triff mich in [REGION]
</input>
<button name="OK" text="OK"/>
@@ -1423,7 +1393,7 @@ Die Option zum Austritt aus einer Gruppe finden Sie unter „Bearbeiten“ &gt;
<notification name="OfferTeleportFromGod">
Benutzer an Ihrem Standort herbeirufen?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Triff mich in [REGION]
</input>
<button name="OK" text="OK"/>
@@ -1432,12 +1402,20 @@ Die Option zum Austritt aus einer Gruppe finden Sie unter „Bearbeiten“ &gt;
</notification>
<notification name="TeleportFromLandmark">
Möchten Sie sich wirklich teleportieren?
- <usetemplate ignoretext="Beim Teleportieren von einer Landmarke im Inventar" name="okcancelignore" notext="Abbrechen" yestext="Teleportieren"/>
+ <usetemplate ignoretext="Bestätigen, dass ich zu einer Landmarke teleportieren möchte" name="okcancelignore" notext="Abbrechen" yestext="Teleportieren"/>
+ </notification>
+ <notification name="TeleportToPick">
+ Nach [PICK] teleportieren?
+ <usetemplate ignoretext="Bestätigen, dass ich zu einer Position in Auswahl teleportieren möchte" name="okcancelignore" notext="Abbrechen" yestext="Teleportieren"/>
+ </notification>
+ <notification name="TeleportToClassified">
+ Zu [CLASSIFIED] teleportieren?
+ <usetemplate ignoretext="Bestätigen, dass ich zu einer Position in Anzeigen teleportieren möchte." name="okcancelignore" notext="Abbrechen" yestext="Teleportieren"/>
</notification>
<notification label="Nachricht an alle auf diesem Grundstück" name="MessageEstate">
Geben Sie eine kurze Nachricht ein, die an jede Person auf Ihrem Grundstück gesendet wird.
<form name="form">
- <input name="message" type="text"/>
+ <input name="message"/>
<button name="OK" text="OK"/>
<button name="Cancel" text="Abbrechen"/>
</form>
@@ -1508,9 +1486,9 @@ Bitte vergewissern Sie sich, dass Sie den aktuellsten Viewer installiert haben u
Möchten Sie unsere Knowledgebase besuchen, um mehr Informationen über Altereinstufung zu erhalten?
<url name="url">
- http://wiki.secondlife.com/wiki/Alterseinstufung:_Ein_%C3%9Cberblick_(KB)
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview/de
</url>
- <usetemplate ignoretext="Wenn Regionzugang aufgrund von Alterseinstufung gesperrt ist" name="okcancelignore" notext="Schließen" yestext="Zur Knowledgbase"/>
+ <usetemplate ignoretext="Ich kann diese Region aufgrund der Alterseinstufung nicht betreten" name="okcancelignore" notext="Schließen" yestext="Zur Knowledgbase"/>
</notification>
<notification name="RegionEntryAccessBlocked_Notify">
Aufgrund Ihrer Alterseinstufung dürfen Sie diese Region nicht betreten.
@@ -1518,16 +1496,12 @@ Möchten Sie unsere Knowledgebase besuchen, um mehr Informationen über Alterein
<notification name="RegionEntryAccessBlocked_Change">
Sie dürfen diese Region aufgrund der Einstellung Ihrer Alterseinstufung nicht betreten.
-Klicken Sie auf „Einstellung ändern“, um Ihre Einstellung für Altereinstufung sofort zu ändern und Zugang zu erhalten. Sie können ab sofort [REGIONMATURITY]-Inhalt suchen und auf diesen zugreifen. Falls Sie diese Einstellung später rückgängig machen möchten, gehen Sie zu Bearbeiten &gt; Einstellungen... &gt; Allgemein.
- <form name="form">
- <button
- name="OK"
- text="Einstellung ändern"/>
- <button
- name="Cancel"
- text="Schließen"/>
- <ignore name="ignore" text="Wenn Regionzugang aufgrund von Einstellung für Alterseinstufung gesperrt ist"/>
- </form>
+Klicken Sie auf „Einstellung ändern“, um Ihre Einstellung für Altereinstufung sofort zu ändern und Zugang zu erhalten. Sie können ab sofort [REGIONMATURITY]-Inhalt suchen und auf diesen zugreifen. Falls Sie diese Einstellung später rückgängig machen möchten, gehen Sie zu Bearbeiten &gt; Einstellungen &gt; Allgemein.
+ <form name="form">
+ <button name="OK" text="Einstellung ändern"/>
+ <button name="Cancel" text="Schließen"/>
+ <ignore name="ignore" text="Meine Alterseinstufung lässt nicht zu, dass ich eine Region betrete."/>
+ </form>
</notification>
<notification name="LandClaimAccessBlocked">
Sie haben aufgrund Ihrer Alterseinstufung keinen Anspruch auf dieses Land. Der Grund hierfür ist möglicherweise, dass Sie nicht altersüberprüft sind.
@@ -1540,9 +1514,9 @@ Bitte vergewissern Sie sich, dass Sie den aktuellsten Viewer installiert haben u
Möchten Sie unsere Knowledgebase besuchen, um mehr Informationen über Altereinstufung zu erhalten?
<url name="url">
- http://wiki.secondlife.com/wiki/Alterseinstufung:_Ein_%C3%9Cberblick_(KB)
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview/de
</url>
- <usetemplate ignoretext="Wenn Landanspruch aufgrund von Alterseinstufung gesperrt ist" name="okcancelignore" notext="Schließen" yestext="Zur Knowledgbase"/>
+ <usetemplate ignoretext="Ich habe aufgrund der Alterseinstufung keinen Anspruch auf dieses Land" name="okcancelignore" notext="Schließen" yestext="Zur Knowledgbase"/>
</notification>
<notification name="LandClaimAccessBlocked_Notify">
Sie haben aufgrund Ihrer Alterseinstufung keinen Anspruch auf dieses Land.
@@ -1550,8 +1524,8 @@ Möchten Sie unsere Knowledgebase besuchen, um mehr Informationen über Alterein
<notification name="LandClaimAccessBlocked_Change">
Sie haben aufgrund der Einstellung Ihrer Alterseinstufung keinen Anspruch auf dieses Land.
-Klicken Sie auf „Einstellung ändern“, um Ihre Einstellung für Altereinstufung sofort zu ändern und Zugang zu erhalten. Sie können ab sofort [REGIONMATURITY]-Inhalt suchen und auf diesen zugreifen. Falls Sie diese Einstellung später rückgängig machen möchten, gehen Sie zu Bearbeiten &gt; Einstellungen... &gt; Allgemein.
- <usetemplate ignoretext="Wenn Landanspruch aufgrund von Einstellung der Alterseinstufung gesperrt ist" name="okcancelignore" notext="Schließen" yestext="Einstellung ändern"/>
+Klicken Sie auf „Einstellung ändern“, um Ihre Einstellung für Altereinstufung sofort zu ändern und Zugang zu erhalten. Sie können ab sofort [REGIONMATURITY]-Inhalt suchen und auf diesen zugreifen. Falls Sie diese Einstellung später rückgängig machen möchten, gehen Sie zu Bearbeiten &gt; Einstellungen &gt; Allgemein.
+ <usetemplate ignoretext="Meine Alterseinstufung lässt nicht zu, dass ich auf Land Anspruch erhebe" name="okcancelignore" notext="Schließen" yestext="Einstellung ändern"/>
</notification>
<notification name="LandBuyAccessBlocked">
Sie können aufgrund Ihrer Alterseinstufung dieses Land nicht kaufen. Der Grund hierfür ist möglicherweise, dass Sie nicht altersüberprüft sind.
@@ -1564,9 +1538,9 @@ Bitte vergewissern Sie sich, dass Sie den aktuellsten Viewer installiert haben u
Möchten Sie unsere Knowledgebase besuchen, um mehr Informationen über Altereinstufung zu erhalten?
<url name="url">
- http://wiki.secondlife.com/wiki/Alterseinstufung:_Ein_%C3%9Cberblick_(KB)
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview/de
</url>
- <usetemplate ignoretext="Wenn Landkauf aufgrund von Alterseinstufung gesperrt ist" name="okcancelignore" notext="Schließen" yestext="Zur Knowledgbase"/>
+ <usetemplate ignoretext="Ich kann aufgrund der Alterseinstufung dieses Land nicht kaufen" name="okcancelignore" notext="Schließen" yestext="Zur Knowledgbase"/>
</notification>
<notification name="LandBuyAccessBlocked_Notify">
Sie können aufgrund Ihrer Alterseinstufung dieses Land nicht kaufen.
@@ -1574,11 +1548,12 @@ Möchten Sie unsere Knowledgebase besuchen, um mehr Informationen über Alterein
<notification name="LandBuyAccessBlocked_Change">
Sie können aufgrund Ihrer Einstellung für Alterseinstufung dieses Land nicht kaufen.
-Klicken Sie auf „Einstellung ändern“, um Ihre Einstellung für Altereinstufung sofort zu ändern und Zugang zu erhalten. Sie können ab sofort [REGIONMATURITY]-Inhalt suchen und auf diesen zugreifen. Falls Sie diese Einstellung später rückgängig machen möchten, gehen Sie zu Bearbeiten &gt; Einstellungen... &gt; Allgemein.
- <usetemplate ignoretext="Wenn Landkauf aufgrund von Einstellung für Alterseinstufung gesperrt ist" name="okcancelignore" notext="Schließen" yestext="Einstellung ändern"/>
+Klicken Sie auf „Einstellung ändern“, um Ihre Einstellung für Altereinstufung sofort zu ändern und Zugang zu erhalten. Sie können ab sofort [REGIONMATURITY]-Inhalt suchen und auf diesen zugreifen. Falls Sie diese Einstellung später rückgängig machen möchten, gehen Sie zu Bearbeiten &gt; Einstellungen &gt; Allgemein.
+ <usetemplate ignoretext="Meine Alterseinstufung lässt nicht zu, dass ich Land kaufe" name="okcancelignore" notext="Schließen" yestext="Einstellung ändern"/>
</notification>
<notification name="TooManyPrimsSelected">
- &quot;Zu viele Prims wurden ausgewählt. Bitte wählen Sie höchstens [MAX_PRIM_COUNT] Prims aus und versuchen Sie es erneut.&quot;
+ Zu viele Prims wurden ausgewählt. Bitte wählen Sie höchstens [MAX_PRIM_COUNT] Prims aus und versuchen Sie es erneut.
+ <usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="ProblemImportingEstateCovenant">
Problem beim Import des Grundstückvertrags.
@@ -1623,219 +1598,17 @@ Anzeige für [AMOUNT] L$ veröffentlichen?
<notification label="Nachricht an alle in dieser Region" name="MessageRegion">
Geben Sie eine kurze Nachricht ein, die an jede Person in dieser Region gesendet wird.
<form name="form">
- <input name="message" type="text"/>
+ <input name="message"/>
<button name="OK" text="OK"/>
<button name="Cancel" text="Abbrechen"/>
</form>
</notification>
- <notification label="Terraformen blockieren" name="HelpRegionBlockTerraform">
- Wenn diese Option aktiviert ist, können Landeigentümer Ihr Land nicht terraformen. Ausgenommen davon ist die parzelleneigene Einstellung „Terrain bearbeiten“.
-
-Standard: deaktiviert
- </notification>
- <notification label="Fliegen blockieren" name="HelpRegionBlockFly">
- Wenn diese Option aktiviert ist, ist Fliegen in dieser Region nicht möglich, auch wenn für die Parzelle eine andere Einstellung aktiv ist.
-
-Standard: deaktiviert
- </notification>
- <notification label="Mehrere Inhaltsberechtigungen ändern" name="HelpBulkPermission">
- Mit dem Werkzeug „Mehrere Berechtigungen“ können Sie Berechtigungen für mehrere Objekte in den Inhalten des ausgewählten Objekts schnell ändern. Bitte beachten Sie, dass Sie nur Berechtigungen an den Objekten im Inhalt der ausgewählten Objekte einstellen, nicht Berechtigungen an dem/den Container-Objekt(en=) selbst.
-
-Bitte beachten Sie auch, dass die Berechtigungen nicht auf eingebettete Inhalte der enthaltenen Objekte angewandt werden. Ihre Auftrag wird nur an Objekten ausgeführt, die sie sich in diesem Level befinden.
-
-Sie können auswählen, welche Objektarten Sie ändern möchten, indem Sie diese in der Liste unter „Inhaltsarten“ auswählen. Wenn Sie Texturen auswählen, sind Fotos mit eingeschlossen.
-
-* Mit diesem Werkzeug können Sie nur an Objekten, die Sie ändern dürfen, Änderungen vornehmen.
-* Sie können dem nächsten Eigentümer keine Berechtigungen geben, die Sie nicht besitzen.
-* Die Berechtigungen für den nächsten Eigentümer sind nur Anfragen. Wenn ein Objekt nicht alle Berechtigungen annehmen kann, dann werden keine seiner Berechtigungen geändert.
-
-Wenn Sie bereit sind, die Berechtigungen mehrfach zu ändern, klicken Sie auf Übernehmen und warten Sie, bis die Ergebnisse angezeigt werden.
-
-Wenn Sie das Fenster „Mehrfach-Berechtigungen“ schließen, während die Berechtigungen geändert werden, wird der Vorgang gestoppt.
- </notification>
- <notification label="Schaden zulassen" name="HelpRegionAllowDamage">
- Wenn diese Option aktiviert ist, ist das Gesundheitssystem auf allen Parzellen aktiviert, unabhängig von den Parzelleneinstellungen. Ist die Option links deaktiviert, können die Parzelleneigentümer das Gesundheitssystem individuell einschalten.
-
-Standard: deaktiviert
- </notification>
- <notification label="Avatar-Limit" name="HelpRegionAgentLimit">
- Legt die maximale Anzahl an Avataren für diese Region fest.
-Die Leistung hängt von der Anzahl der Avatare in der Region ab.
-
-Standard: 40
- </notification>
- <notification label="Objektbonus" name="HelpRegionObjectBonus">
- Der Objektbonus ist ein Multiplikator für die Anzahl an zulässigen Primitiven auf einer Parzelle. Gültig sind Werte zwischen 1 und 10. „1“ erlaubt auf einer 512 qm großen Parzelle 117 Objekte. „2“ erlaubt auf einer 512 qm großen Parzelle 234 Objekte, also die doppelte Menge. Die maximale Objektanzahl in einer Region beträgt unabhängig vom Objektbonus 15.000.
-Eine nachträglich Senkung des Objektbonus führt dazu, dass Objekte zurückgegeben oder gelöscht werden.
-
-Standard: 1.0
- </notification>
- <notification label="Alterseinstufung" name="HelpRegionMaturity">
- Legt die Alterseinstufung für die Region fest. Dies wird in der Menüleiste oben im Viewer angezeigt und auch in den Kurzinfos auf der Weltkarte, wenn der Cursor über diese Region schwebt. Diese Einstellung wirkt sich auch auf den Zugang zu dieser Region und die Suchergebnisse aus. Andere Einwohner können Regionen nur dann betreten oder Suchergebnisse anzeigen, wenn Ihre Alterseinstufung in Ihren Einstellungen der Alterseinstellung der Region bzw. Suchergebnisse entsprechen.
-
-Es kann eine Weile dauern, bis diese Änderung auf der Karte angezeigt wird.
- </notification>
- <notification label="Stoßen beschränken" name="HelpRegionRestrictPushObject">
- Aktivieren sie diese Option, um in der gesamten Region das Stoßen zu beschränken. Wenn aktiviert, können Einwohner nur von sich selbst oder vom Parzelleneigentümer gestoßen werden.
-(Stoßen meint die LSL-Funktion llPushObject().)
-
-Standard: deaktiviert
- </notification>
- <notification label="Parzelle zusammenlegen/teilen" name="HelpParcelChanges">
- Dieses Kontrollkästchen steuert, ob Parzellen des Grundstückseigentümers zusammengelegt bzw. unterteilt werden können. Wenn deaktiviert:
- * Nur Grundstückseigentümer bzw. –verwalter können Parzellen zusammenlegen/teilen. * Sie können nur Parzellen zusammenlegen/teilen, die dem Eigentümer oder einer Gruppe gehören, bei der sie entsprechende Gruppenrechte innehaben.
-Wenn aktiviert:
- * Die Parzelleneigentümer können ihre Parzellen selbst zusammenlegen/teilen.
- * Parzellen in Gruppeneigentum können von Mitgliedern mit den entsprechenden Rechten zusammengelegt bzw. unterteilt werden.
-
-Standard: aktiviert
- </notification>
- <notification label="Nicht in Suche anzeigen" name="HelpRegionSearch">
- Wenn Sie diese Option auswählen, können Parzelleneigentümer ihre Parzellen nicht in der Suche anzeigen lassen
-
-Standard: deaktiviert
- </notification>
<notification label="Alterseinstufung der Region ändern" name="RegionMaturityChange">
Die Alterseinstufung dieser Region wurde aktualisiert.
Es kann eine Weile dauern, bis sich die Änderung auf die Karte auswirkt.
</notification>
- <notification label="Landwiederverkauf" name="HelpRegionLandResell">
- Grundstückseigentümer und -verwalter können jedes Land im Besitz des Grundstückseigentümers verkaufen.
-Ist diese Option deaktiviert, können Käufer ihr Land in dieser Region nicht weiterverkaufen.
-Ist die Option aktiviert, können Käufer ihr Land in dieser Region weiterverkaufen.
-
-Standard: deaktiviert
- </notification>
- <notification label="Skripts deaktivieren" name="HelpRegionDisableScripts">
- Schlechte Sim-Performance ist oftmals auf ein Skript zurückzuführen. Öffnen Sie die Statistikleiste (Strg-Umschalt-1). Sehen Sie sich den Wert für „Simulator Physics FPS“ (Simulator Physik-FPS) an.
-Wenn der Wert unter 45 liegt, öffnen Sie den Bereich „Time“ (Zeit) ganz unten in der Statistikleiste. Wenn der Wert für „Script Time“ (Skriptzeit) 25 ms oder höher ist, klicken Sie auf „Top-Skripts“. Der Name und die Position der Skripts, die für die schlechte Performance verantwortlich sind, werden angezeigt.
-Wenn Sie das Kontrollkästchen „Skripts deaktivieren“ aktivieren und auf „Übernehmen“ klicken, werden alle Skripts in der Region zeitweilig deaktiviert. Dieser Schritt ist eventuell notwendig, damit Sie an die Position des gemeldeten „Top-Skripts“ reisen können. Sobald Sie dort angekommen sind, sollten Sie das Skript auf die Ursache des Problems hin untersuchen. Möglicherweise müssen Sie sich an den Skript-Eigentümer wenden oder das Objekt löschen bzw. zurückgeben. Um die Skripte in der Region wieder zu aktivieren, deaktivieren Sie „Skript deaktivieren“ und klicken Sie auf „Übernehmen“.
-
-Standard: deaktiviert
- </notification>
- <notification label="Kollisionen deaktivieren" name="HelpRegionDisableCollisions">
- Schlechte Sim-Performance ist oftmals auf physische Objekte zurückzuführen.
-Öffnen Sie die Statistikleiste (Strg-Umschalt-1). Sehen Sie sich den Wert „Simulator Physics FPS“ an. Liegt dieser unter 45, öffnen Sie unten in der Statistikleiste den „Time“-Bereich. Liegt die „Sim Time (Physics)“ bei 20 ms oder darüber, klicken Sie auf „Top-Kollisionsobjekte“.
-Der Name und der Standort der physischen Objekte, die das Problem verursachen, werden angezeigt.
-
-Wenn Sie das Kontrollkästchen „Kollisionen deaktivieren“ aktivieren und auf „Übernehmen“ klicken, werden alle Objekt-Objekt-Kollisionen in der Region zeitweilig deaktiviert. Dieser Schritt ist eventuell notwendig, damit Sie an die Position des gemeldeten „Top-Kollisionsobjekts“ reisen können. Überprüfen Sie das Objekt an der angegebenen Position.
-Kollidiert es ständig mit anderen Objekten? Wenden Sie sich eventuell an den Eigentümer des Objekts, löschen Sie es oder geben Sie es zurück.
-Deaktivieren Sie die Option „Kollisionen deaktivieren“ und klicken Sie auf „Übernehmen“, um Kollisionen in dieser Region wieder zu aktivieren.
-
-Standard: deaktiviert
- </notification>
- <notification label="Physik deaktivieren" name="HelpRegionDisablePhysics">
- Das Deaktivieren der Physik ähnelt dem Deaktivieren von Kollisionen, außer dass die gesamte Physiksimulation ausgeschaltet wird. Das hat nicht nur zur Folge, dass Objekte nicht mehr kollidieren, sondern dass Avatare sich nicht mehr bewegen können.
-
-Diese Option sollte nur verwendet werden, wenn das Deaktivieren von Kollisionen keine ausreichende Leistungssteigerung bringt, um Physikprobleme in der Region oder die Top-Kollisionsobjekte zu erkennen.
-
-Schalten Sie die Physiksimulation hinterher wieder ein. Andernfalls können sich Avatare nicht mehr bewegen.
-
-Standard: deaktiviert
- </notification>
- <notification label="Top-Kollisionsobjekte" name="HelpRegionTopColliders">
- Zeigt eine Liste der Objekte mit den potenziell meisten Objekt-Objekt-Kollisionen an. Diese Objekte können die Leistung beeinträchtigen. Wählen Sie „Ansicht“ &gt; „Statistikleiste“ aus und sehen Sie unter „Simulator“ &gt; „Time“ &gt; „Sim Time (Physics)“ nach, ob die Physikberechnung länger als 20 ms dauert.
- </notification>
- <notification label="Top-Skripts" name="HelpRegionTopScripts">
- Zeigt eine Liste der Objekte an, die die meiste Zeit benötigen, um LSL-Skripts auszuführen. Diese Objekte können die Leistung beeinträchtigen.
-Wählen Sie „Ansicht“ &gt; „Statistikleiste“ und sehen Sie unter „Simulator“ &gt; „Time“ &gt; „Script Time“ nach, ob mehr als 25 ms für Skripts benötigt werden.
- </notification>
- <notification label="Region neu starten" name="HelpRegionRestart">
- Starten Sie den Serverprozess für diese Region nach der 2-Minuten-Warnung neu. Die Verbindung aller Einwohner in dieser Region wird getrennt. Die Region wird gespeichert und sollte nach 90 Sekunden wieder verfügbar sein.
-
-Der Neustart der Region behebt die meisten Leistungs-probleme, sollte aber nur nach Anweisung erfolgen.
- </notification>
- <notification label="Wasserhöhe" name="HelpRegionWaterHeight">
- Die Höhe der Wasserlinie in Metern. Liegt dieser Wert unter 20 und haben Sie Wasser nahe am Rand der Welt oder „offenes“ Wasser definiert, wird eine deutliche Lücke sichtbar.
-
-Standard: 20
- </notification>
- <notification label="Obere Terraingrenze" name="HelpRegionTerrainRaise">
- Der maximale Betrag in Metern, um den Parzelleneigentümer ihr Terrain über die Standardhöhe des „geformten“ Terrains erhöhen können.
-
-Standard: 4
- </notification>
- <notification label="Untere Terraingrenze" name="HelpRegionTerrainLower">
- Der maximale Betrag in Metern, um den Parzelleneigentümer ihr Terrain unter die Standardhöhe des „geformten“ Terrains absenken können.
-
-Standard: -4
- </notification>
- <notification label="RAW-Terrain hochladen" name="HelpRegionUploadRaw">
- Mit dieser Schaltfläche laden Sie eine RAW-Datei in die Region hoch, in der Sie sich befinden.
-Die Datei muss die korrekten Maße (RGB, 256x256) und 13 Kanäle haben. Um eine neue Terraindatei zu erstellen, laden Sie am besten die vorhandene RAW-Datei herunter. Beginnen Sie damit, den Rot-Kanal (Höhe des Landes) zu bearbeiten und laden Sie die Datei wieder hoch.
-
-Der Ladevorgang kann bis zu 45 Sekunden dauern. Beachten Sie, dass beim Hochladen einer Terraindatei die Objekte auf dem Land *nicht* verschoben werden, sondern nur das Land und die mit den Parzellen verbundenen Berechtigungen. Dies kann dazu führen, dass Objekte unter dem Terrain verschwinden.
-
-Weitere Informationen zur Bearbeitung der Höhendaten der Region enthält die F1-Hilfe.
- </notification>
- <notification label="RAW-Terrain herunterladen" name="HelpRegionDownloadRaw">
- Mit dieser Schaltfläche laden Sie eine Datei herunter, welche die Höhendaten, Maße, den Verkaufsstatus der Parzelle und einige Parzellenrechte für diese Region enthält. Wenn Sie diese Datei in einem Programm wie Photoshop öffnen, müssen Sie die Bilddaten eingeben. Diese sind: RGB, 256x256 mit 13 Kanälen. Anders lässt sich diese Terraindatei nicht öffnen.
-
-Weitere Informationen zur Bearbeitung der Höhendaten der Region enthält die F1-Hilfe.
- </notification>
- <notification label="Grundstücksonne verwenden" name="HelpRegionUseEstateSun">
- Aktivieren Sie diese Option, um in dieser Region denselben Sonnenstand wie auf dem restlichen Grundstück einzustellen.
-
-Standard: aktiviert
- </notification>
- <notification label="Sonne fest" name="HelpRegionFixedSun">
- Aktivieren Sie diese Option, um den Sonnenstand auf die im Regler definierte Position festzulegen und die Animation auszuschalten.
-
-Standard: deaktiviert
- </notification>
- <notification label="Terrain formen" name="HelpRegionBakeTerrain">
- Mit dieser Schaltfläche speichern Sie die aktuelle Terrain-Form als neuen Standard für die Region. Nach der Formung können Sie und andere das Land mit der Option „Terrain bearbeiten“ &gt; „Zurücksetzen“ in den ursprünglichen Zustand zurückversetzen. Das geformte Terrain ist auch das Zentrum für die oberen und unteren Terraingrenzen.
- </notification>
- <notification label="Grundstücksverwalter" name="HelpEstateEstateManager">
- Ein Grundstücksverwalter ist ein Einwohner, dem Sie die Kontrolle über die Regions- und Grundstückseinstellungen übertragen haben. Ein Grundstücksverwalter kann alle Einstellungen ändern, außer das Hochladen, Herunterladen und Formen von Terrain. Vor allem kann er Einwohner auf dem Grundstück erlauben und davon verbannen.
-
-Nur der Eigentümer kann den Grundstücksverwalter bestimmen und entlassen. Der Verwalter hat dieses Recht nicht. Wählen Sie nur vertrauenswürdige Einwohner als Grundstücksverwalter, da Sie letztlich für deren Handlungen verantwortlich sind.
- </notification>
- <notification label="Globale Zeit verwenden" name="HelpEstateUseGlobalTime">
- Aktivieren Sie diese Option, um auf Ihrem Grundstück denselben Sonnenstand wie auf dem Linden-„Mainland“ einzustellen.
-
-Standard: aktiviert
- </notification>
- <notification label="Sonne fest" name="HelpEstateFixedSun">
- Aktivieren Sie diese Option, um den Sonnenstand auf die im Regler definierte Position festzulegen und die Animation auszuschalten.
- </notification>
- <notification label="Öffentlich" name="HelpEstateExternallyVisible">
- Aktivieren Sie diese Option, um Einwohnern den Zugang zu diesem Grundstück zu erlauben, ohne auf der Zugangsliste zu stehen.
-
-Standard: aktiviert
- </notification>
- <notification label="Direktteleport zulassen" name="HelpEstateAllowDirectTeleport">
- Wenn aktiviert, können sich Einwohner an jede Stelle auf Ihrem Grundstück teleportieren. Wenn deaktiviert, werden Einwohner zum nächstgelegenen Telehub teleportiert.
-
-Standard: deaktiviert
- </notification>
- <notification label="Zugang erlauben" name="HelpEstateAllowResident">
- Der Zugang zu diesem Grundstück wird auf die hier aufgeführten Einwohner und Gruppen beschränkt. Diese Einstellung ist nur verfügbar, wenn „Öffentlich“ deaktiviert ist.
- </notification>
- <notification label="Gruppenzugang erlauben" name="HelpEstateAllowGroup">
- Der Zugang zu diesem Grundstück wird auf die hier aufgeführten Einwohner und Gruppen beschränkt. Diese Einstellung ist nur verfügbar, wenn „Öffentlich“ deaktiviert ist.
- </notification>
- <notification label="E-Mail-Adresse für Missbrauchsmeldungen" name="HelpEstateAbuseEmailAddress">
- Geben Sie hier eine E-Mail-Adresse ein, an die Missbrauchsmeldungen von diesem Grundstück gesendet werden.
-Wenn dieses Feld leer ist, werden Missbrauchsmeldungen nur an Linden Lab gesendet.
- </notification>
- <notification label="Zugang verweigern" name="HelpEstateBanResident">
- Einwohnern auf dieser Liste wird der Zugang zum Grundstück verwehrt, unabhängig von etwaigen anderen Einstellungen.
- </notification>
- <notification label="Voice-Chat erlauben" name="HelpEstateVoiceChat">
- Die Parzellen auf diesem Grundstück können über eigene Voice-Channel verfügen, die es Einwohnern ermöglichen, sich mit anderen Personen in der Nähe zu unterhalten.
-
-Standard: deaktiviert
- </notification>
<notification label="Falsche Voice-Version" name="VoiceVersionMismatch">
- Diese Version von Second ist mit dem Voice-Chat-Feature in dieser Region nicht kompatibel. Damit Voice-Chat funktioniert, müssen Sie Second Life aktualisieren.
- </notification>
- <notification label="Grunstücksvertrag" name="HelpEstateCovenant">
- Ein Grundstücksvertrag ermöglicht es Ihnen, Grundstücksparzellen zu verkaufen. Ohne Vertrag können Sie kein Land verkaufen. Wenn Sie keine Regeln festlegen oder Käufern vor dem Kauf keine anderen Informationen über das Land bereitstellen möchten, können Sie die Vertrags-Notizkarte auch leer lassen.
-
-Ein Vertrag kann Regeln und Richtlinien, kulturelle Informationen oder einfach nur Ihre eigenen Erwartungen bezüglich der Landnutzung durch den Käufer enthalten. Das kann Zoning, Baubeschränkungen, Zahloptionen und alle möglichen anderen Informationen betreffen, die der neue Eigentümer Ihrer Meinung nach kennen und akzeptieren sollte.
-
-Der Käufer muss dem Vertrag durch Auswahl dieses Kontrollkästchens zustimmen, bevor der Kauf abgeschlossen werden kann. Grundstücksverträge sind jederzeit unter „Land-Info“ für jede Parzelle einsehbar, für die ein Vertrag definiert wurde.
+ Diese Version von [APP_NAME] ist mit der Voice-Chat-Funktion in dieser Region nicht kompatibel. Damit Voice-Chat funktioniert, müssen Sie [APP_NAME] aktualisieren.
</notification>
<notification label="Objekte können nicht gekauft werden" name="BuyObjectOneOwner">
Objekte können nicht von mehreren Eigentümern gleichzeitig gekauft werden.
@@ -1902,14 +1675,14 @@ Die Inhalte werden in Ihr Inventar kopiert.
Möchten Sie diesen Kauf fortsetzen?
<usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/>
</notification>
- <notification name="ConfirmPurchasePassword" type="password">
+ <notification name="ConfirmPurchasePassword">
Transaktion:
[ACTION]
Möchten Sie diesen Kauf fortsetzen?
Geben Sie Ihr Kennwort erneut ein und klicken Sie auf OK.
<form name="form">
- <input name="message" type="password"/>
+ <input name="message"/>
<button name="ConfirmPurchase" text="OK"/>
<button name="Cancel" text="Abbrechen"/>
</form>
@@ -1924,71 +1697,51 @@ Sie haben die Position dieser Auswahl aktualisiert, aber die anderen Daten behal
Diese Objekte werden nicht kopiert, sondern in Ihr Inventar verschoben.
Inventarobjekt(e) verschieben?
- <usetemplate ignoretext="Beim Verschieben von nicht-kopierfähigem Inventar von Objekten" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
+ <usetemplate ignoretext="Warnhinweis anzeigen, bevor ich nicht kopierbare Artikel aus einem Objekt verschiebe" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
</notification>
<notification name="MoveInventoryFromScriptedObject">
Sie haben „nicht kopierfähige“ Inventarobjekte ausgewählt. Diese Objekte werden nicht kopiert, sondern in Ihr Inventar verschoben.
Da es sich um ein geskriptetes Objekt handelt, geht die Skriptfunktion beim Verschieben in das Inventar möglicherweise verloren.
Inventarobjekt(e) verschieben?
- <usetemplate ignoretext="Beim Verschieben von nicht-kopierfähigem Inventar von geskripteten Objekten" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
+ <usetemplate ignoretext="Warnhinweis anzeigen, bevor ich nicht-kopierbare Artikel verschiebe, die ein geskriptetes Objekt beschädigen können" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
</notification>
<notification name="ClickActionNotPayable">
- Achtung: Die Klick-Aktion „Objekt bezahlen“ wurde definiert, sie funktioniert aber nur, wenn ein Skript mit einem money() Ereignis hinzugefügt wird.
+ Achtung: Die Klickaktion „Objekt bezahlen&quot; wurde eingestellt. Diese funktioniert jedoch nicht, wenn ein Skript mit einer Geldtransaktion () hinzugefügt wird.
<form name="form">
- <ignore name="ignore" text="Beim Einrichten von Events mit „Objektbezahlung“ ohne Geld"/>
+ <ignore name="ignore" text="I habe die Aktion „Objekt bezahlen&quot; eingestellt, während ich ein Objekt gebaut habe, dass kein Geld()-Skript enthält."/>
</form>
</notification>
<notification name="OpenObjectCannotCopy">
Sie haben keine Berechtigung zum Kopieren von Elementen in diesem Objekt.
</notification>
<notification name="WebLaunchAccountHistory">
- Zur Second Life-Website, um Ihre Kontostatistik anzuzeigen?
- <usetemplate ignoretext="Beim Laden der Kontostatistik-Website" name="okcancelignore" notext="Abbrechen" yestext="Gehe zu Seite"/>
- </notification>
- <notification name="ClickOpenF1Help">
- Die Support-Website von Second Life öffnen?
- <usetemplate ignoretext="Bei Besuch der Second Life Support-Website." name="okcancelignore" notext="Abbrechen" yestext="Los"/>
+ Möchten Sie Ihre [http://secondlife.com/account/ Startseite] aufrufen, um Ihre Konto-Statistik anzuzeigen?
+ <usetemplate ignoretext="Meinen Browser starten, um meine Konto-Statistik anzuzeigen" name="okcancelignore" notext="Abbrechen" yestext="Gehe zu Seite"/>
</notification>
<notification name="ConfirmQuit">
Wirklich beenden?
- <usetemplate ignoretext="Beim Beenden von Second Life." name="okcancelignore" notext="Weiter" yestext="Beenden"/>
+ <usetemplate ignoretext="Bestätigen, bevor Sitzung beendet wird" name="okcancelignore" notext="Nicht beenden" yestext="Beenden"/>
</notification>
<notification name="HelpReportAbuseEmailLL">
- Verwenden Sie dieses Tool, um Verletzungen der Servicebedingungen und Community-Standards zu melden. Siehe:
-
-http://secondlife.com/corporate/tos.php
-http://secondlife.com/corporate/cs.php
+ Mit dieser Funktion können Sie Verstöße gegen die [http://secondlife.com/corporate/tos.php Servicebedingungen (EN)] and [http://secondlife.com/corporate/cs.php Community-Standards] melden.
-Alle gemeldeten Verletzungen der Servicebedingungen und Community-Standards werden geprüft und geklärt Sie können den Prozess im Incident Report (Vorfallsbericht) verfolgen:
-
-http://secondlife.com/support/incidentreport.php
+Alle gemeldeten Verstöße werden bearbeitet. Sie können auf der Seite [http://secondlife.com/support/incidentreport.php Verstoßmeldungen] nachverfolgen, welche Verstoßmeldungen bearbeitet wurden.
</notification>
<notification name="HelpReportAbuseEmailEO">
WICHTIG: Diese Meldung wird an den Eigentümer der Region gesendet, in der Sie sich gerade befinden, nicht an Linden Lab.
--
-Als besonderen Service für Einwohner und Besucher übernimmt der Eigentümer dieser Region die Bearbeitung aller anfallenden Meldungen. Von diesem Standort aus eingereichte Meldungen werden nicht von Linden Lab bearbeitet. Der Eigentümer der Region bearbeitet Meldungen auf Grundlage der Richtlinien, die im für diese Region geltenden Grundstücksvertrag festgelegt sind.
-(Den Vertrag können Sie unter „Welt“ &gt; „Land-Info“ einsehen.)
--
-Das Resultat, das sich aus dieser Meldung ergibt, betrifft nur diese Region; der Einwohnerzugang zu anderen Bereichen von Second Life ist davon nicht betroffen. Nur Linden Lab kann den Zugang zu Second Life beschränken.
- </notification>
- <notification name="HelpReportBug">
- Verwenden Sie dieses Tool *nur*, um technische Features zu melden, die nicht wie beschrieben oder erwartet funktionieren. Bitte machen Sie so viele Angaben wie möglich. Sie können auf die automatische Antwort-E-Mail antworten, um Ihre Meldung noch zu ergänzen.
-Alle gemeldeten Fehler werden geprüft und bewertet. Sie erhalten keine persönliche Antwort auf Ihre E-Mail.
--
-Bei technischen Problemen wenden Sie sich bitte an den Support unter:
-http://secondlife.com/community/support.php
--
-Hinweis: Unvollständige Meldungen werden nicht bearbeitet.
+
+Als besonderen Service für Einwohner und Besucher übernimmt der Eigentümer dieser Region die Bearbeitung aller anfallenden Meldungen. Von diesem Standort aus eingereichte Meldungen werden nicht von Linden Lab bearbeitet.
+
+Der Eigentümer der Region bearbeitet Meldungen auf Grundlage der Richtlinien, die im für diese Region geltenden Grundstücksvertrag festgelegt sind.
+(Den Vertrag können Sie unter &apos;Welt &apos; &gt; &apos;Land-Info &apos; einsehen.)
+
+Die Klärung des gemeldeten Verstoßes bezieht sich nur auf diese Region. Der Zugang für Einwohner zu anderen Bereichen von [SECOND_LIFE] wird durch das Resultat dieser Meldung nicht beeinträchtigt. Nur Linden Lab kann den Zugang zu [SECOND_LIFE] beschränken.
</notification>
<notification name="HelpReportAbuseSelectCategory">
Wählen Sie eine Missbrauchskategorie aus.
Die Angabe einer Kategorie hilft uns bei der Bearbeitung des Berichts.
</notification>
- <notification name="HelpReportBugSelectCategory">
- Wählen Sie eine Fehler-Kategorie aus.
-Die Angabe einer Kategorie hilft uns bei der Bearbeitung des Berichts.
- </notification>
<notification name="HelpReportAbuseAbuserNameEmpty">
Geben Sie den Namen des Täters ein.
Eine genaue Angabe hilft uns, Fälle von Missbrauch zu ahnden.
@@ -2001,26 +1754,18 @@ Eine genaue Angabe hilft uns, Fälle von Missbrauch zu ahnden.
Bitte geben Sie eine Zusammenfassung des Vorfalls ein.
Eine genaue Zusammenfassung hilft uns, Fälle von Missbrauch zu ahnden.
</notification>
- <notification name="HelpReportBugSummaryEmpty">
- Bitte geben Sie eine Zusammenfassung des Fehlers ein.
-Eine genaue Zusammenfassung hilft uns, Fehler schneller zu beseitigen.
- </notification>
<notification name="HelpReportAbuseDetailsEmpty">
Bitte geben Sie eine ausführliche Beschreibung des Vorfalls ein.
Eine möglichst genaue Beschreibung mit Namen und Einzelheiten hilft uns, Fälle von Missbrauch zu ahnden.
</notification>
- <notification name="HelpReportBugDetailsEmpty">
- Bitte geben Sie eine ausführliche Fehlerbeschreibung ein.
-Eine möglichst genaue Beschreibung mit Schritten zur Reproduktion des Fehlers hilft uns, Fehler schneller zu beseitigen.
- </notification>
<notification name="HelpReportAbuseContainsCopyright">
Sehr geehrte(r) Einwohner(in),
Sie melden eine Urheberrechtsverletzung. Sind Sie wirklich sicher, dass Sie eine Verletzung des Urheberrechts melden möchten?
-1. Missbrauch melden. Wenn Sie der Meinung sind, ein Einwohner nutzt das Berechtigungssystem von Second Life auf unerlaubte Weise zu seinem Vorteil aus, indem er zum Beispiel einen CopyBot oder ähnliche Kopiertools verwendet und damit eine Urheberrechtsverletzung begeht, können Sie diesen Missbrauch melden. Das Missbrauchsteam untersucht etwaige Verstöße gegen die Second Life Community Standards oder die Nutzungsbedingungen und verhängt entsprechende Strafen. Das Missbrauchsteam ist jedoch nicht dafür zuständig, Inhalte aus der Second Life-Welt zu entfernen und reagiert auch nicht auf entsprechende Anfragen.
+1. Missbrauch melden. Wenn Sie der Meinung sind, ein Einwohner nutzt das Berechtigungssystem von [SECOND_LIFE] auf unerlaubte Weise zu seinem Vorteil aus, indem er zum Beispiel einen CopyBot oder ähnliche Kopiertools verwendet und damit eine Urheberrechtsverletzung begeht, können Sie diesen Missbrauch melden. Das Missbrauchsteam untersucht gemeldete Verstöße gegen die [SECOND_LIFE] [http://secondlife.com/corporate/tos.php Servicebedingungen] oder [http://secondlife.com/corporate/cs.php Community-Standards] und verhängt entsprechende Maßnahmen. Das Missbrauchsteam ist jedoch nicht dafür zuständig, Inhalte aus der [SECOND_LIFE]-Welt zu entfernen und reagiert auch nicht auf entsprechende Anfragen.
-2. Der DMCA oder das Entfernen von Inhalten. Sie können das Entfernen von Inhalten aus Second Life beantragen. Dazu MÜSSEN Sie eine Urheberrechtsverletzung gemäß den in unserer DMCA-Richtlinie unter http://secondlife.com/corporate/dmca.php dargelegten Anweisungen einreichen.
+2. Der DMCA oder das Entfernen von Inhalten. Sie können das Entfernen von Inhalten aus [SECOND_LIFE] beantragen. Dazu MÜSSEN Sie eine Urheberrechtsverletzung gemäß den in unserer DMCA-Richtlinie unter [http://secondlife.com/corporate/dmca.php] dargelegten Anweisungen einreichen.
Wenn Sie mit der Missbrauchmeldung jetzt fortfahren möchten, schließen Sie bitte dieses Fenster und senden Sie Ihren Bericht ein. Möglicherweise müssen Sie Kategorie „CopyBot oder Berechtigungs-Exploit“ auswählen.
@@ -2036,7 +1781,7 @@ Linden Lab
An dieser Körperstelle ist bereits ein Objekt angebracht.
Möchten Sie es mit dem ausgewählten Objekt ersetzen?
<form name="form">
- <ignore name="ignore" save_option="true" text="Beim Wechseln von Anhängen"/>
+ <ignore name="ignore" save_option="true" text="Einen bestehenden Anhang mit dem ausgewählten Artikel ersetzen"/>
<button ignore="Automatisch ersetzen" name="Yes" text="OK"/>
<button ignore="Nie ersetzen" name="No" text="Abbrechen"/>
</form>
@@ -2046,18 +1791,22 @@ Möchten Sie es mit dem ausgewählten Objekt ersetzen?
Möchten Sie den Bechäftigt-Modus verlassen, bevor Sie diese Transaktion abschließen?
<form name="form">
- <ignore name="ignore" save_option="true" text="Beim Bezahlen einer Person oder eines Objekts im Beschäftigt-Modus"/>
+ <ignore name="ignore" save_option="true" text="Ich bin im Begriff eine Person oder ein Objekt zu bezahlen, während ich im Modus Beschäftigt bin."/>
<button ignore="Beschäftigt-Modus immer deaktivieren" name="Yes" text="OK"/>
<button ignore="Beschäftigt-Modus aktiviert lassen" name="No" text="Abbrechen"/>
</form>
</notification>
+ <notification name="ConfirmDeleteProtectedCategory">
+ Der Ordner „[FOLDERNAME]“ ist ein Systemordner. Das Löschen von Systemordnern kann zu instabiler Leistung führen. Möchten Sie fortfahren?
+ <usetemplate ignoretext="Bestätigen, bevor ich einen Systemordner lösche." name="okcancelignore" notext="Abbrechen" yestext="OK"/>
+ </notification>
<notification name="ConfirmEmptyTrash">
- Möchten Sie den Inhalt Ihres Papierkorbs wirklich löschen?
- <usetemplate ignoretext="Beim Leeren des Inventar-Papierkorbs" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
+ Sind Sie sicher, dass Sie den Inhalt Ihres Papierkorbs löschen möchten?
+ <usetemplate ignoretext="Bestätigen, bevor der Ordner Papierkorb im Inventar geleert wird" name="okcancelignore" notext="Abbrechen" yestext="OK"/>
</notification>
<notification name="ConfirmClearBrowserCache">
- Möchten Sie Ihren Browser-Cache wirklich leeren?
- <usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="Ja"/>
+ Sind Sie sicher, dass Sie Ihren Reise-, Internet- und Suchverlauf löschen möchten?
+ <usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/>
</notification>
<notification name="ConfirmClearCookies">
Sind Sie sicher, dass Sie Ihre Cookies löschen möchten?
@@ -2068,39 +1817,18 @@ Möchten Sie den Bechäftigt-Modus verlassen, bevor Sie diese Transaktion abschl
<usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="Ja"/>
</notification>
<notification name="ConfirmEmptyLostAndFound">
- Möchten Sie den Inhalt Ihres Fundstücke-Ordners wirklich permanent löschen?
- <usetemplate ignoretext="Beim Leeren von Inventar und Fundstückeordner-" name="okcancelignore" notext="Nein" yestext="Ja"/>
+ Sind Sie sicher, dass Sie den Inhalt Ihres Ordners Fundbüro löschen möchten?
+ <usetemplate ignoretext="Bestätigen, bevor der Ordner Fundbüro im Inventar geleert wird" name="okcancelignore" notext="Nein" yestext="Ja"/>
</notification>
<notification name="CopySLURL">
- Die folgende SLURL wurde in die Zwischenablage kopiert:
+ Die folgende SLurl wurde in die Zwischenablage kopiert:
[SLURL]
-Veröffentlichen Sie sie auf einer Website, um anderen den Zugang zu diesem Ort zu erleichtern, oder testen Sie sie, indem Sie sie in die Adressleiste Ihres Browsers kopieren.
+Von einer Webseite zu diesem Formular linken, um anderen leichten Zugang zu dieser Position zu ermöglichen. Oder versuchen Sie es selbst: kopieren Sie die SLurl in die Adressleiste eines Webbrowsers.
<form name="form">
- <ignore name="ignore" text="Beim Kopieren einer SLURL in die Zwischenablage"/>
+ <ignore name="ignore" text="Slurl wurde in meine Zwischenablage kopiert"/>
</form>
</notification>
- <notification name="GraphicsPreferencesHelp">
- Die Optionen in diesem Dialog steuern Fenstergröße und Auflösung sowie die Qualität der Grafikdarstellung im Client. Im Fenster „Einstellungen“ &gt; „Grafik“ stehen vier Grafikeinstellungen zur Wahl: Niedrig, Mittel, Hoch und Ultra. Die Grafikeinstellungen lassen sich auch individuell anpassen; aktivieren Sie das Kontrollkästchen „Benutzerdefiniert“, um die folgenden Einstellungen zu bearbeiten:
-
-Shader: Aktivieren oder deaktivieren Sie die verschiedenen Pixel-Shader.
-
-Spiegelung: Legen Sie hier fest, welche Objekte sich in Wasser spiegeln.
-
-Avatar-Darstellung: Einige Optionen, die über die Darstellung Ihres Avatars bestimmen.
-
-Sichtweite: Legt fest, bis zu welcher Entfernung von Ihrem Avatar die Objekte in der Szene berechnet und dargestellt werden.
-
-Max. Partikelzahl: Legt fest, wie viele Partikel gleichzeitig berechnet und angezeigt werden.
-
-Post-Processing-Qualität: Legt fest, mit welcher Auflösung der Glüheffekt berechnet wird.
-
-Gitterdetails: Legt den Detailgrad bzw. die Anzahl an Dreiecken bei der Berechnung bestimmter Objekte fest. Höhere Werte führen zu einer genaueren Darstellung, dauern aber länger in der Berechnung.
-
-Beleuchtungsdetails: Legt fest, welche Lichtquellen berechnet werden.
-
-Terraindetails: Legt den Detailgrad bei der Berechnung der Terraintextur fest.
- </notification>
<notification name="WLSavePresetAlert">
Die gespeicherte Voreinstellung überschreiben?
<usetemplate name="okcancelbuttons" notext="Nein" yestext="Ja"/>
@@ -2119,154 +1847,10 @@ Terraindetails: Legt den Detailgrad bei der Berechnung der Terraintextur fest.
Post-Processing-Effekt bereits vorhanden. Möchten Sie ihn überschreiben?
<usetemplate name="okcancelbuttons" notext="Nein" yestext="Ja"/>
</notification>
- <notification name="HelpEditSky">
- Verschieben Sie die WindLight-Regler, um verschiedene Himmelsansichten zu erstellen und zu speichern.
- </notification>
- <notification name="HelpEditDayCycle">
- Wählen Sie für jede Tageszeit eine Himmelsansicht aus.
- </notification>
- <notification name="EnvSettingsHelpButton">
- Diese Einstellungen haben Auswirkung auf die lokale Darstellung der Umwelt auf Ihrem Computer. Zugriff auf alle Einstellungen haben Sie nur, wenn Ihre Grafikkarte Atmosphären-Shader unterstützt.
-
-Mit dem Regler „Tageszeit“ stellen Sie die lokal in Ihrem Viewer dargestellte Tageszeit ein.
-
-Mit dem Regler „Wolkendecke“ steuern Sie die Wolkendichte am Himmel.
-
-Unter „Wasserfarbe“ können Sie eine Farbe für die Wasserdarstellung auswählen.
-
-Mit dem Regler „Wassertrübung“ steuern Sie die Sichtweite unter Wasser.
-
-Klicken Sie auf „Grundstückszeit verw.“, um die aktuelle Zeit in der Region fest als Tageszeit einzustellen.
-
-Klicken Sie auf „Himmel (erweitert)“, um einen Editor mit erweiterten Einstellungen für die Himmeldarstellung anzuzeigen.
-
-Klicken Sie auf „Wasser (erweitert)“, um einen Editor mit erweiterten Einstellungen für die Wasserdarstellung anzuzeigen.
- </notification>
- <notification name="HelpDayCycle">
- Im Tageszyklus-Editor steuern Sie den Tag-/Nachtzyklus am Second Life Himmel. Dabei handelt es sich um den Zyklus, der mit dem Tageszeit-Regler im Umwelt-Basiseditor gesteuert wird.
-
-Der Tageszyklus-Editor verwendet sogenannte Keyframes zur Steuerung des Tag-/Nachtablaufs. Dabei handelt es sich um „Schlüsselbilder“ (die grauen Kreise auf der Zeitskala), für die bestimmte Himmelseinstellungen definiert wurden. Bei voranschreitender Tageszeit interpoliert WindLight den Übergang zwischen diesen Keyframes und erzeugt eine entsprechende Himmelsanimation.
-
-Der gelbe Pfeil über der Zeitskala repräsentiert die aktuelle Tageszeit-Darstellung. Ziehen Sie den Pfeil, um die Tagesanimation anzuzeigen. Mit „Key hinzu“ und „Key löschen“ rechts neben der Zeitskala können Sie neue Keys einfügen und vorhandene löschen.
-
-Keyframes lassen sich einfach entlang der Zeitskala verschieben, oder Sie geben die Werte manuell unter „Keyframe-Einstellungen“ ein. Hier wählen Sie auch eine WindLight-Voreinstellung für den Keyframe aus.
-
-„Zykluslänge“ bestimmt die Gesamtlänge eines „Tages“. Ein niedriger Wert (z.B. 2 Minuten) führt dazu, dass ein ganzer 24-Stunden-Tag innerhalb von zwei Minuten Echtzeit abgespult wird! Wenn Sie alle Einstellungen auf der Zeitskala und für die einzelnen Keyframes vorgenommen haben, können Sie mit „Start“ und „Stopp“ die Animation anzeigen. Das funktioniert natürlich genauso interaktiv, indem Sie den gelben Pfeil über der Zeitskala verschieben. Mit der Schaltfläche „Grundstückszeit verw.“ synchronisieren Sie die Tageszeit und -länge mit den auf dem Grundstück geltenden Einstellungen.
-
-Ihre Tageszyklus-Einstellungen lassen sich mit den Schaltflächen „Testtag speichern“ und „Testtag laden“ speichern bzw. laden. Bis dato kann nur ein Tageszyklus gleichzeitig in Verwendung sein.
- </notification>
- <notification name="HelpBlueHorizon">
- Mit den Reglern für Rot/Grün/Blau (RGB) steuern Sie die Farbe des Himmels. Verwenden Sie den Intensitätsregler (I), um alle drei RGB-Regler gleichzeitig zu verschieben.
- </notification>
- <notification name="HelpHazeHorizon">
- Horizonttrübung ist einer der wichtigsten Parameter, um die Gesamtlichtsituation in der Szene zu steuern. Damit lassen sich viele Belichtungseinstellungen simulieren, z.B. ein Überstrahlen durch die Sonne oder starker Dunst.
- </notification>
- <notification name="HelpBlueDensity">
- Farbintensität steuert die Gesamtfarbsättigung von Himmel und Nebel. Je weiter Sie den Intensitätsregler (I) nach rechts verschieben, desto heller und lebendiger werden die Farben. Wenn Sie ihn ganz nach links verschieben, verlieren die Farben an Intensität und gehen in Schwarz oder Weiß über. Volle Kontrolle über die Farbsättigung des Himmels bieten ihnen die Regler für Rot/Grün/Blau (RGB).
- </notification>
- <notification name="HelpHazeDensity">
- Trübungsintensität steuert die Stärke des grauen Dunsts in der Atmosphäre. Damit lassen sich zum Beispiel starker Rauch oder Luftverschmutzung simulieren. Auch für Nebel und Sprühregen geeignet.
- </notification>
- <notification name="HelpDensityMult">
- Der Dichtemultiplikator beeinflusst die Gesamtdichte der Atmosphäre. Niedrige Einstellungen erzeugen den Eindruck dünner, sauberer Luft, hohe Einstellungen erzeugen den Eindruck schweren Smogs.
- </notification>
- <notification name="HelpDistanceMult">
- Steuert die Entfernungswirkung von WindLight. Ein Wert von Null schaltet den Einfluss von WindLight auf Terrain und Objekte praktisch aus. Werte über 1 simulieren größere Entfernungen und verstärken den Atmosphäreneffekt.
- </notification>
- <notification name="HelpMaxAltitude">
- Max. Höhe steuert die Höhenberechnungen von WindLight bei der Berechnung der atmosphärischen Beleuchtung. Zu späteren Tageszeiten lässt sich damit zum Beispiel die „Intensität“ des Sonnenuntergangs beeinflussen.
- </notification>
- <notification name="HelpSunlightColor">
- Steuert Farbe und Intensität von direktem Licht in der Szene.
- </notification>
- <notification name="HelpSunAmbient">
- Steuert Farbe und Intensität von atmosphärischem Umgebungslicht in der Szene.
- </notification>
- <notification name="HelpSunGlow">
- Der Regler „Größe“ steuert die Größe der Sonne.
-Der Regler „Fokus“ steuert, wie unscharf die Sonne am Himmel erscheint.
- </notification>
- <notification name="HelpSceneGamma">
- Regelt den Hell/Dunkel-Wert des Bildschirms.
- </notification>
- <notification name="HelpStarBrightness">
- Regelt die Helligkeit der Sterne am Himmel.
- </notification>
- <notification name="HelpTimeOfDay">
- Steuert die Sonnenstellung am Himmel.
-Entspricht der Elevation.
- </notification>
- <notification name="HelpEastAngle">
- Steuert die Sonnenstellung am Himmel.
-Entspricht dem Azimut.
- </notification>
- <notification name="HelpCloudColor">
- Steuert die Wolkenfarbe. Generell empfiehlt sich hier ein Weißton, aber hey, warum nicht ein bisschen Spaß haben?
- </notification>
- <notification name="HelpCloudDetail">
- Steuert das Detailbild, welches über das Wolken-Hauptbild gelegt wird. X und Y bestimmen seine Position. D (Dichte) regelt, wie ausgebeult oder zerrissen die Wolken wirken.
- </notification>
- <notification name="HelpCloudDensity">
- Mit den X- und Y-Reglern steuern Sie die Position der Wolken, mit dem Regler D die Wolkendichte.
- </notification>
- <notification name="HelpCloudCoverage">
- Steuert, wie stark die Wolken den Himmel bedecken.
- </notification>
- <notification name="HelpCloudScale">
- Steuert die Skalierung des Wolkenbilds auf der Himmelskuppel.
- </notification>
- <notification name="HelpCloudScrollX">
- Steuert die Bewegungsgeschwindigkeit der Wolken in X-Richtung.
- </notification>
- <notification name="HelpCloudScrollY">
- Steuert die Bewegungsgeschwindigkeit der Wolken in Y-Richtung.
- </notification>
- <notification name="HelpClassicClouds">
- Aktivieren Sie dieses Kontrollkästchen, um die Darstellung der klassischen Second Life Wolken zusätzlich zu den WindLight-Wolken zu erzwingen.
- </notification>
- <notification name="HelpWaterFogColor">
- Steuert die Farbe der Wassertrübung
- </notification>
- <notification name="HelpWaterFogDensity">
- Steuert die Dichte der Wassertrübung und wie weit Sie unter Wasser sehen können.
- </notification>
- <notification name="HelpUnderWaterFogMod">
- Beeinflusst die Auswirkung des Wassertrübungs-Exponenten und regelt die Sichtweite Ihres Avatars unter Wasser.
- </notification>
- <notification name="HelpWaterGlow">
- Steuert, wie groß der Anteil der leuchtenden Wasseroberfläche ist.
- </notification>
- <notification name="HelpWaterNormalScale">
- Steuert die Skalierung der drei Elementarwellen, die das Wasser ausmachen.
- </notification>
- <notification name="HelpWaterFresnelScale">
- Steuert die winkelabhängige Lichtreflexion.
- </notification>
- <notification name="HelpWaterFresnelOffset">
- Steuert die Intensität des reflektierten Lichts.
- </notification>
- <notification name="HelpWaterScaleAbove">
- Steuert die Stärke der Lichtbrechung von oberhalb der Wasseroberfläche aus gesehen.
- </notification>
- <notification name="HelpWaterScaleBelow">
- Steuert die Stärke der Lichtbrechung von unterhalb der Wasseroberfläche aus gesehen.
- </notification>
- <notification name="HelpWaterBlurMultiplier">
- Steuert die Mischung von Wellen und Reflexionen.
- </notification>
- <notification name="HelpWaterNormalMap">
- Ermöglicht die Auswahl einer Normal-Map zur Berechnung von Reflexionen/Brechungen auf dem Wasser.
- </notification>
- <notification name="HelpWaterWave1">
- Steuert die Bewegungsgeschwindigkeit und -richtung der großen Normal-Map-Version in X- und Y-Richtung.
- </notification>
- <notification name="HelpWaterWave2">
- Steuert die Bewegungsgeschwindigkeit und -richtung der kleinen Normal-Map-Version in X- und Y-Richtung.
- </notification>
<notification name="NewSkyPreset">
Wählen Sie einen Namen für den neuen Himmel.
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Neue Voreinstellung
</input>
<button name="OK" text="OK"/>
@@ -2279,7 +1863,7 @@ Entspricht dem Azimut.
<notification name="NewWaterPreset">
Wählen Sie einen Namen für die neue Wasservoreinstellung.
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Neue Voreinstellung
</input>
<button name="OK" text="OK"/>
@@ -2308,7 +1892,7 @@ Entspricht dem Azimut.
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="Cannot_Purchase_an_Attachment">
- Objekte können nicht gekauft werden, solange sie Teil eines Anhangs sind.
+ Sie können kein Objekt kaufen, während es angehängt ist.
</notification>
<notification label="Info zur Abfrage der Abbucherlaubnis" name="DebitPermissionDetails">
Wenn Sie dieser Anfrage zustimmen, erhält das Skript die Erlaubnis, regelmäßig Linden-Dollar (L$) von Ihrem Konto abzubuchen. Diese Erlaubnis kann nur zurückgezogen werden, wenn der Eigentümer das Objekt löscht oder die Skripts in dem Objekt zurücksetzt.
@@ -2316,27 +1900,25 @@ Entspricht dem Azimut.
</notification>
<notification name="AutoWearNewClothing">
Möchten Sie das neu erstellte Kleidungsstück automatisch anziehen?
- <usetemplate ignoretext="Neue Kleidung automatisch tragen" name="okcancelignore" notext="Nein" yestext="Ja"/>
+ <usetemplate ignoretext="Die Kleidung, die während dem Bearbeiten meines Aussehens erstellt wird, sofort anziehen" name="okcancelignore" notext="Nein" yestext="Ja"/>
</notification>
<notification name="NotAgeVerified">
- Um Zugang zu dieser Parzelle zu erhalten, müssen Sie sich einer Altersprüfung unterziehen.
-Möchten Sie auf der Second Life Website eine Altersüberprüfung durchführen?
+ Sie müssen altersüberprüft sein, um diesen Bereich betreten zu können. Möchten Sie auf der [SECOND_LIFE]-Webseite Ihr Alter verifizieren lassen?
[_URL]
<url name="url" option="0">
https://secondlife.com/account/verification.php?lang=de
</url>
- <usetemplate ignoretext="Auf fehlende Altersprüfung aufmerksam machen" name="okcancelignore" notext="Nein" yestext="Ja"/>
+ <usetemplate ignoretext="Ich habe mein Alter nicht verifizieren lassen" name="okcancelignore" notext="Nein" yestext="Ja"/>
</notification>
<notification name="Cannot enter parcel: no payment info on file">
- Um Zugang zu dieser Parzelle zu erhalten, müssen Sie Zahlungsinformationen hinterlegt haben.
-Möchten Sie die Second Life Website öffnen, um diese Angaben zu hinterlegen?
+ Um diesen Bereich besuchen zu können, müssen Ihre Zahlungsinformationen gespeichert sein. Möchten Sie diese Einstellung auf der [SECOND_LIFE]-Webseite einrichten?
[_URL]
<url name="url" option="0">
https://secondlife.com/account/index.php?lang=de
</url>
- <usetemplate ignoretext="Auf fehlende Zahlungsinformationen aufmerksam machen" name="okcancelignore" notext="Nein" yestext="Ja"/>
+ <usetemplate ignoretext="Meine Zahlungsinformation ist nicht gespeichert" name="okcancelignore" notext="Nein" yestext="Ja"/>
</notification>
<notification name="MissingString">
Der String „[STRING_NAME]“ fehlt in strings.xml
@@ -2366,7 +1948,7 @@ Möchten Sie die Second Life Website öffnen, um diese Angaben zu hinterlegen?
[FIRST] [LAST] ist offline
</notification>
<notification name="AddSelfFriend">
- Sie können sich nicht selbst als Freund hinzufügen.
+ Obwohl Sie ein sehr netter Mensch sind, können Sie sich nicht selbst als Freund hinzufügen.
</notification>
<notification name="UploadingAuctionSnapshot">
In-Welt- und Website-Fotos werden hochgeladen...
@@ -2385,7 +1967,7 @@ Möchten Sie die Second Life Website öffnen, um diese Angaben zu hinterlegen?
Terrain.raw heruntergeladen
</notification>
<notification name="GestureMissing">
- Geste [NAME] fehlt in Datenbank.
+ Hmm. Geste [NAME] fehlt in Datenbank.
</notification>
<notification name="UnableToLoadGesture">
Geste [NAME] konnte nicht geladen werden.
@@ -2398,14 +1980,14 @@ Bitte versuchen Sie es erneut.
Landmarke konnte nicht geladen werden. Bitte versuchen Sie es erneut.
</notification>
<notification name="CapsKeyOn">
- Die Feststelltaste ist aktiv.
-Da dies Auswirkung auf die Kennworteingabe hat, sollten Sie die Taste besser ausschalten.
+ Die Umschalttaste ist aktiv.
+Dies kann die Eingabe Ihres Passworts beeinflussen.
</notification>
<notification name="NotecardMissing">
Notizkarte fehlt in Datenbank.
</notification>
<notification name="NotecardNoPermissions">
- Unzureichende Rechte zur Anzeige der Notizkarte.
+ Ihnen fehlt die Berechtigung zur Anzeige dieser Notizkarte.
</notification>
<notification name="RezItemNoPermissions">
Keine Berechtigung zum Rezzen von Objekten.
@@ -2443,23 +2025,23 @@ Bitte versuchen Sie es erneut.
Bitte versuchen Sie es erneut.
</notification>
<notification name="CannotBuyObjectsFromDifferentOwners">
- Objekte können nicht von mehreren Eigentümern gleichzeitig gekauft werden.
+ Sie können nur von einem Eigentümer auf einmal Objekte kaufen.
Wählen Sie ein einzelnes Objekt aus.
</notification>
<notification name="ObjectNotForSale">
- Objekt ist nicht zu verkaufen.
+ Dieses Objekt wird nicht verkauft.
</notification>
<notification name="EnteringGodMode">
Gott-Modus aktiviert, Level [LEVEL]
</notification>
<notification name="LeavingGodMode">
- Gott-Modus deaktiviert, Level [LEVEL]
+ Gott-Modus wird nun de-aktiviert, Level [LEVEL]
</notification>
<notification name="CopyFailed">
- Kopieren aufgrund fehlender Kopierrechte fehlgeschlagen
+ Ihnen fehlt die Berechtigung zum Kopieren.
</notification>
<notification name="InventoryAccepted">
- [NAME] hat Ihr Inventarangebot akzeptiert.
+ [NAME] hat Ihr Inventarangebot erhalten.
</notification>
<notification name="InventoryDeclined">
[NAME] hat Ihr Inventarangebot abgelehnt.
@@ -2474,12 +2056,14 @@ Wählen Sie ein einzelnes Objekt aus.
Ihre Visitenkarte wurde abgelehnt.
</notification>
<notification name="TeleportToLandmark">
- Jetzt, nachdem Sie das Mainland erreicht haben, können Sie sich an Positionen wie „[NAME]“ teleportieren, indem Sie unten rechts im Fenster auf „Inventar“ klicken und den Ordner „Landmarken“ auswählen.
-Klicken Sie eine Landmarke doppelt an und wählen Sie „Teleportieren“, um an diesen Ort zu gelangen.
+ Sie können an Positionen wie „[NAME]“ teleportieren, wenn Sie rechts in Ihrem Bildschirm die Tafel „Orte“ öffnen und dann die Registerkarte „Landmarken“ auswählen.
+Klicken Sie auf eine Landmarke, um diese auszuwählen. Klicken Sie anschließend auf „Teleport“ unten in der Konsole.
+(Sie können auch auf die Landmarke doppelt klicken oder mit rechts auf die Landmarke klicken und dann „Teleport“ auswählen).
</notification>
<notification name="TeleportToPerson">
- Jetzt, nachdem Sie das Mainland erreicht haben, können Sie mit Einwohnern wie „[NAME]“ Kontakt aufnehmen, indem Sie unten rechts im Fenster auf „Inventar“ klicken und den Ordner „Visitenkarten“ auswählen.
-Klicken Sie die Karte doppelt an, wählen Sie „Instant Message“ und geben Sie eine Nachricht ein.
+ Sie können Einwohner wie „[NAME]“ kontaktieren, wenn Sie die Tafel „Leute“ auf der rechten Seite Ihres Bildschirms öffnen.
+Wählen Sie den Einwohner aus der Liste aus und klicken Sie unten auf „IM“.
+(Sie können auch auf den Namen doppelt klicken oder mit rechts auf den Namen klicken und dann „IM“ auswählen).
</notification>
<notification name="CantSelectLandFromMultipleRegions">
Land kann nicht über Servergrenzen hinweg ausgewählt werden.
@@ -2526,8 +2110,20 @@ Wählen Sie eine kleinere Landfläche.
[NAMES]
</notification>
<notification name="NoQuickTime">
- Apple QuickTime ist auf Ihrem System anscheinend nicht installiert.
-Laden Sie QuickTime von der QuickTime-Webseite (http://www.apple.com/de/quicktime) herunter, um auf Parzellen, die diese Funktion unterstützen, Streaming-Inhalte wiederzugeben.
+ AppleQuickTime ist auf Ihrem System anscheinend nicht installiert.
+Laden Sie QuickTime von der [http://www.apple.com/quicktime QuickTime-Webseite] herunter, um auf Parzellen, die diese Funktion unterstützen, Streaming-Inhalte wiederzugeben.
+ </notification>
+ <notification name="NoPlugin">
+ Es wurde kein Medien-Plugin gefunden, das &quot;[MIME_TYPE]&quot; ausführen kann. Medien dieses Dateityps sind nicht verfügbar.
+ </notification>
+ <notification name="MediaPluginFailed">
+ Bei folgendem Plugin ist ein Fehler aufgetreten:
+ [PLUGIN]
+
+Bitte installieren Sie das Plugin erneut. Falls weiterhin Problem auftreten, kontaktieren Sie bitte den Hersteller.
+ <form name="form">
+ <ignore name="ignore" text="Ein Plugin kann nicht ausgeführt werden"/>
+ </form>
</notification>
<notification name="OwnedObjectsReturned">
Ihre Objekte auf der ausgewählten Parzelle wurden in Ihr Inventar transferiert.
@@ -2547,24 +2143,27 @@ Nicht transferierbare an die Gruppe übertragene Objekte wurden gelöscht.
<notification name="UnOwnedObjectsReturned">
Alle Objekte auf der ausgewählten Parzelle, die NICHT Ihnen gehören, wurden ihren Eigentümern zurückgegeben.
</notification>
+ <notification name="ServerObjectMessage">
+ Nachricht von [NAME]:
+[MSG]
+ <usetemplate name="okcancelbuttons" notext="OK" yestext="Untersuchen"/>
+ </notification>
<notification name="NotSafe">
- Auf diesem Land ist Schaden aktiviert („Unsicher“).
+ Auf diesem Land ist Schaden aktiviert.
Verletzungen sind möglich. Wenn Sie sterben, werden Sie zu Ihrem Heimatstandort teleportiert.
</notification>
<notification name="NoFly">
- Auf diesem Land ist Fliegen deaktiviert („Fliegen aus“).
+ In diesem Bereich ist das Fliegen deaktiviert.
Fliegen ist hier nicht möglich.
</notification>
<notification name="PushRestricted">
- Auf diesem Land gilt „Kein Stoßen“.
-Sie können keine anderen Personen stoßen, außer Ihnen gehört das Land.
+ In diesem Bereich ist Stoßen nicht erlaubt. Sie können keine anderen Personen stoßen, außer Ihnen gehört das Land.
</notification>
<notification name="NoVoice">
- Auf diesem Land ist Voice deaktiviert.
+ In diesem Bereich ist Voice deaktiviert. Sie werden niemanden sprechen hören.
</notification>
<notification name="NoBuild">
- Auf diesem Land ist Bauen deaktiviert („Bauen aus“).
-Sie können hier keine Objekte erstellen.
+ In diesem Bereich ist das Bauen deaktiviert. Sie können keine Objekte bauen oder rezzen.
</notification>
<notification name="ScriptsStopped">
Ein Administrator hat die Skriptausführung in dieser Region vorübergehend deaktiviert.
@@ -2574,8 +2173,8 @@ Sie können hier keine Objekte erstellen.
</notification>
<notification name="NoOutsideScripts">
Auf diesem Land sind externe Skripts deaktiviert
-(„Externe Skripts aus“).
-Nur Skripts, die dem Landeigentümer gehören, funktionieren.
+
+Hier funktionieren nur Skripts, die dem Landeigentümer gehören.
</notification>
<notification name="ClaimPublicLand">
Öffentliches Land kann nur in der Region in Besitz genommen werden, in der Sie sich befinden.
@@ -2591,10 +2190,6 @@ Bitte besuchen Sie unsere Knowledgebase, um mehr Details über Zugang zu Regione
<notification name="NoTeenGridAccess">
Ihr Konto kann keine Verbindung zu dieser Teen Grid-Region herstellen.
</notification>
- <notification name="NoHelpIslandTP">
- Sie können nicht zurück nach Help Island teleportieren.
-Gehen Sie zu „Help Island Public“ und wiederholen sie das Tutorial.
- </notification>
<notification name="ImproperPaymentStatus">
Die für den Zutritt zu dieser Region erforderlichen Zahlungsinformationen liegen nicht vor.
</notification>
@@ -2663,31 +2258,35 @@ Versuchen Sie es in einigen Minuten erneut.
Es konnte keine gültige Parzelle gefunden werden.
</notification>
<notification name="ObjectGiveItem">
- Das Objekt [OBJECTFROMNAME] von [FIRST] [LAST] hat Ihnen Folgendes übergeben: [OBJECTTYPE] ([OBJECTNAME]).
+ Ein Objekt namens [OBJECTFROMNAME] von [NAME_SLURL] hat Ihnen folgendes übergeben [OBJECTTYPE]:
+[ITEM_SLURL]
<form name="form">
<button name="Keep" text="Behalten"/>
<button name="Discard" text="Verwerfen"/>
- <button name="Mute" text="Stummschalten"/>
+ <button name="Mute" text="Ignorieren"/>
</form>
</notification>
<notification name="ObjectGiveItemUnknownUser">
- Das Objekt [OBJECTFROMNAME] von (unbekannt) hat Ihnen Folgendes übergeben: [OBJECTTYPE] ([OBJECTNAME]).
+ Ein Objekt namens [OBJECTFROMNAME] von (einem unbekannten Einwohner) hat Ihnen folgendes übergeben [OBJECTTYPE]:
+[ITEM_SLURL]
<form name="form">
<button name="Keep" text="Behalten"/>
<button name="Discard" text="Verwerfen"/>
- <button name="Mute" text="Stummschalten"/>
+ <button name="Mute" text="Ignorieren"/>
</form>
</notification>
<notification name="UserGiveItem">
- [NAME] hat Ihnen ein [OBJECTTYPE] namens „[OBJECTNAME]“ gegeben.
+ [NAME_SLURL] hat Ihnen folgendes [OBJECTTYPE]:
+[ITEM_SLURL]
<form name="form">
<button name="Keep" text="Behalten"/>
+ <button name="Show" text="Anzeigen"/>
<button name="Discard" text="Verwerfen"/>
- <button name="Mute" text="Stummschalten"/>
</form>
</notification>
<notification name="GodMessage">
[NAME]
+
[MESSAGE]
</notification>
<notification name="JoinGroup">
@@ -2699,7 +2298,7 @@ Versuchen Sie es in einigen Minuten erneut.
</form>
</notification>
<notification name="TeleportOffered">
- [NAME] hat angeboten, Sie zu ihrem/seinem Standort zu teleportieren:
+ [NAME] hat Ihnen einen Teleport an seine/ihre Position angeboten:
[MESSAGE]
<form name="form">
@@ -2750,11 +2349,11 @@ Dies erstellt ein Lesezeichen in Ihrem Inventar, damit Sie diesen Einwohner jede
</form>
</notification>
<notification name="RegionRestartMinutes">
- Region wird in [MINUTES] Minuten neu gestartet.
+ Diese Region wird in [Minuten] neu gestartet.
Wenn Sie in dieser Region bleiben, werden Sie abgemeldet.
</notification>
<notification name="RegionRestartSeconds">
- Region wird in [SECONDS] Sekunden neu gestartet.
+ Diese Region wird in [SECONDS] neu gestartet.
Wenn Sie in dieser Region bleiben, werden Sie abgemeldet.
</notification>
<notification name="LoadWebPage">
@@ -2775,7 +2374,7 @@ Von Objekt: [OBJECTNAME], Eigentümer: [NAME]?
[TYPE] namens [DESC] nicht in Datenbank.
</notification>
<notification name="InvalidWearable">
- Dieser Artikel verwendet eine Funktion, die Ihr Viewer nicht unterstützt. Bitte aktualisieren Sie Ihre Version von Second Life, um diesen Artikel anziehen zu können.
+ Dieser Artikel verwendet eine Funktion, die Ihr Viewer nicht unterstützt. Bitte aktualisieren Sie Ihre Version von [APP_NAME], um dieses Objekt anziehen zu können.
</notification>
<notification name="ScriptQuestion">
Das Objekt „[OBJECTNAME]“, Eigentum von „[NAME]“, möchte:
@@ -2785,14 +2384,14 @@ Ist das OK?
<form name="form">
<button name="Yes" text="Ja"/>
<button name="No" text="Nein"/>
- <button name="Mute" text="Stummschalten"/>
+ <button name="Mute" text="Ignorieren"/>
</form>
</notification>
<notification name="ScriptQuestionCaution">
- Das Objekt „[OBJECTNAME]“, Eigentum von „[NAME]“, möchte:
+ Ein Objekt namens „[OBJECTNAME]“ des Eigentümers „[NAME]“ möchte:
[QUESTIONS]
-Wenn Sie diesem Objekt und seinem Ersteller nicht vertrauen, sollten Sie diese Anfrage ablehnen. Klicken Sie für weitere Informationen auf „Info...“.
+Wenn Sie diesem Objekt und seinem Ersteller nicht vertrauen, sollten Sie diese Anfrage ablehnen.
Anfrage gestatten?
<form name="form">
@@ -2815,40 +2414,44 @@ Anfrage gestatten?
<button name="Ignore" text="Ignorieren"/>
</form>
</notification>
+ <notification name="ScriptToast">
+ [FIRST] [LAST]s &apos;[TITLE]&apos; fordert Eingaben vom Benutzer an.
+ <form name="form">
+ <button name="Open" text="Dialog öffnen"/>
+ <button name="Ignore" text="Ignorieren"/>
+ <button name="Block" text="Ignorieren"/>
+ </form>
+ </notification>
<notification name="FirstBalanceIncrease">
Sie haben gerade [AMOUNT] L$ erhalten.
-Objekte und andere Benutzer können Ihnen L$ geben.
-Ihren Kontostand sehen Sie in der oberen rechten Ecke des Bildschirms.
+Ihr Kontostand wird oben rechts angezeigt.
</notification>
<notification name="FirstBalanceDecrease">
Sie haben gerade [AMOUNT] L$ bezahlt.
-Ihren Kontostand sehen Sie in der oberen rechten Ecke des Bildschirms.
+Ihr Kontostand wird oben rechts angezeigt.
+ </notification>
+ <notification name="BuyLindenDollarSuccess">
+ Vielen Dank für Ihre Zahlung.
+
+Ihr L$-Kontostand wird aktualisiert, sobald die Bearbeitung abgeschlossen ist. Falls die Bearbeitung länger als 20 min dauert, ist es möglich, dass Ihre Transaktion abgebrochen wird. In diesem Fall wird der Kaufbetrag in US$ auf Ihrem Konto gutgeschrieben.
+
+Der Zahlungsstatus kann auf Ihrer [http://secondlife.com/account/ Startseite] unter Transaktionsübersicht überprüft werden.
</notification>
<notification name="FirstSit">
Sie sitzen.
-Benutzen Sie die Pfeil- oder WASD-Tasten, um die Ansicht zu ändern.
-Klicken Sie auf „Aufstehen“, um aufzustehen.
+Verwenden Sie die Pfeiltasten (oder AWSD-Tasten), um sich umzusehen.
+Um aufzustehen, klicken Sie auf die Schaltfläche „Aufstehen“.
</notification>
<notification name="FirstMap">
- Zum Verschieben der Karte klicken und ziehen.
+ Klicken Sie auf die Karte und bewegen Sie die Maus, um sich auf der Karte umzusehen.
Zum Teleportieren doppelklicken.
-Nutzen Sie die Optionen links, um Dinge zu finden und um verschiedene Hintergründe anzuzeigen.
+Nutzen Sie die Optionen rechts, um Objekte, Einwohner oder Events anzuzeigen und einen anderen Hintergrund auszuwählen.
</notification>
<notification name="FirstBuild">
- In einigen Bereichen von [SECOND_LIFE] können Sie neue Objekte erstellen.
-Verwenden Sie zum Bauen die Werkzeuge oben links.
-Mit den Strg- und Alt-Tasten können Sie schnell zwischen den Werkzeugen umschalten.
-Drücken Sie Esc, um das Bauen abzubrechen.
- </notification>
- <notification name="FirstLeftClickNoHit">
- Die linke Maustaste ermöglicht Objektinteraktionen.
-Der Mauszeiger zeigt eine Hand, wenn Sie
-mit dem Objekt interagieren können.
-Die rechte Maustaste zeigt immer ein Aktionsmenü an.
+ Sie haben die Bauwerkzeuge geöffnet. Jedes Objekt, dass Sie sehen wurde mit diesen Werkzeugen gebaut.
</notification>
<notification name="FirstTeleport">
- Diese Region unterstützt keine direkten Teleports. Sie wurden zum nächstgelegenen Telehub transportiert.
-Ihr Ziel ist mit einem großen roten Strahl markiert. Folgen Sie dem roten Pfeil zum Strahl oder klicken Sie auf den Pfeil, um den Strahl zu entfernen.
+ Sie können nur zu bestimmten Bereichen in dieser Region teleportieren. Der Pfeil deutet zu Ihrem Ziel hin. Klicken Sie auf den Pfeil, um diesen auszublenden.
</notification>
<notification name="FirstOverrideKeys">
Ihre Bewegungstasten werden jetzt von einem Objekt gesteuert.
@@ -2858,38 +2461,33 @@ Drücken Sie dazu „M“.
</notification>
<notification name="FirstAppearance">
Sie bearbeiten gerade Ihr Aussehen.
-Benutzen Sie die Pfeiltasten zum Drehen und Zoomen.
-Klicken Sie auf „Alles speichern“, wenn Sie fertig sind, um Ihr Aussehen zu speichern.
-Sie können Ihr Aussehen jederzeit verändern.
+Verwenden Sie die Pfeiltasten, um sich umzusehen.
+Klicken Sie auf „Alles speichern“, wenn Sie fertig sind.
</notification>
<notification name="FirstInventory">
- Ihr Inventar. Es enthält Objekte, Notizkarten, Kleidung und andere Dinge in Ihrem Besitz.
-* Zum Anziehen eines Objekts oder Outfit-Ordners ziehen Sie es/ihn auf sich.
-* Um ein Objekt in der Welt abzulegen, ziehen Sie es auf den Boden.
+ Dies ist Ihr Inventar. Es enthält Objekte, die Ihnen gehören.
+
+* Um etwas anzuziehen, ziehen Sie es mit der Maus auf Ihren Avatar.
+* Um etwas inworld zu rezzen, ziehen Sie das Objekt auf den Boden.
* Zum Lesen einer Notizkarte klicken Sie sie doppelt an.
</notification>
<notification name="FirstSandbox">
- Dies ist eine Sandkastenregion.
-Objekte, die Sie hier bauen, können gelöscht werden, wenn Sie das Gebiet verlassen. Sandkästen werden regelmäßig gereinigt. Weitere Informationen hierzu finden Sie oben im Bild neben dem Regionsnamen.
+ Dies ist ein Sandkasten. Hier können Einwohner lernen, wie Objekte gebaut werden.
-Sandkastenregionen kommen selten vor und sind entsprechend gekennzeichnet.
+Objekte, die Sie hier bauen, werden gelöscht, nachdem Sie den Sandkasten verlassen. Vergessen Sie nicht, Ihr Werk mit einem Rechtsklick und der Auswahl „Nehmen“ in Ihrem Inventar zu speichern.
</notification>
<notification name="FirstFlexible">
- Dieses Objekt ist flexibel.
-Ein flexibles Objekt ist ein Phantom und nicht physisch, bis die Option „Flexibel“ deaktiviert wurde.
+ Dieses Objekt ist flexibel. Flexible Objekte müssen die Eigenschaft „Phantom“ haben und dürfen nicht „physisch“ sein.
</notification>
<notification name="FirstDebugMenus">
- Sie haben das Advanced-Menü aktiviert.
-Dieses Menü enthält nützliche Funktionen zum Debuggen von Second Life.
-Drücken Sie in Windows Strg-Alt-D (Mac: Befehl-Opt-Umschalt-D) zum Ein- und Ausschalten dieses Menüs.
+ Sie haben das Menü „Erweitert“ geöffnet.
+
+Um dieses Menü zu aktivieren bzw. deaktivieren:
+ Windows Strg+Alt+D
+ Mac &#8997;&#8984;D
</notification>
<notification name="FirstSculptedPrim">
- Sie bearbeiten ein geformtes Primitiv.
-Geformte Primitive benötigen eine spezielle Textur, die ihre Form definiert.
-Beispiele für Formtexturen finden Sie in der Inventarbibliothek.
- </notification>
- <notification name="FirstMedia">
- Sie haben die Medienwiedergabe gestartet. Unter „Audio und Video“ im Fenster „Einstellungen“ können Sie festlegen, dass Medien automatisch wiedergegeben werden. Beachten Sie, dass dies bei nicht vertrauenswürdigen Medienseiten ein Sicherheitsrisiko darstellen kann.
+ Sie bearbeiten ein geformtes Primitiv. Geformte Primitive benötigen eine spezielle Textur, die ihre Form definiert.
</notification>
<notification name="MaxListSelectMessage">
Sie können maximal [MAX_SELECT] Objekte
@@ -2897,47 +2495,47 @@ von der Liste auswählen.
</notification>
<notification name="VoiceInviteP2P">
[NAME] lädt Sie zu einem Voice-Chat ein.
-Klicken Sie auf „Akzeptieren“, um dem Gespräch beizutreten, oder auf „Ablehnen“, um die Einladung auszuschlagen. Klicken Sie auf „Stummschalten“, um diesen Anrufer stumm zu schalten.
+Klicken Sie auf &apos;Akzeptieren &apos;, um dem Gespräch beizutreten, oder auf &apos;Ablehnen &apos;, um die Einladung auszuschlagen. Klicken Sie auf Ignorieren, um diesen Anrufer zu ignorieren.
<form name="form">
<button name="Accept" text="Akzeptieren"/>
<button name="Decline" text="Ablehnen"/>
- <button name="Mute" text="Stummschalten"/>
+ <button name="Mute" text="Ignorieren"/>
</form>
</notification>
<notification name="AutoUnmuteByIM">
- [FIRST] [LAST] hat eine Instant Message erhalten; die Stummschaltung wurde aufgehoben.
+ [FIRST] [LAST] hat eine Benachrichtigung erhalten und wird nicht länger ignoriert.
</notification>
<notification name="AutoUnmuteByMoney">
- [FIRST] [LAST] hat Geld erhalten; die Stummschaltung wurde aufgehoben.
+ [FIRST] [LAST] wurde bezahlt und wird nicht länger ignoriert.
</notification>
<notification name="AutoUnmuteByInventory">
- [FIRST] [LAST] wurde ein Inventarobjekt angeboten; die Stummschaltung wurde aufgehoben.
+ [FIRST] [LAST] wurde Inventar angeboten und wird nicht länger ignoriert.
</notification>
<notification name="VoiceInviteGroup">
[NAME] ist einem Voice-Chat mit der Gruppe [GROUP] beigetreten.
-Klicken Sie auf „Akzeptieren“, um dem Gespräch beizutreten, oder auf „Ablehnen“, um die Einladung auszuschlagen. Klicken Sie auf „Stummschalten“, um diesen Anrufer stumm zu schalten.
+Klicken Sie auf &apos;Akzeptieren &apos;, um dem Gespräch beizutreten, oder auf &apos;Ablehnen &apos;, um die Einladung auszuschlagen. Klicken Sie auf Ignorieren, um diesen Anrufer zu ignorieren.
<form name="form">
<button name="Accept" text="Akzeptieren"/>
<button name="Decline" text="Ablehnen"/>
- <button name="Mute" text="Stummschalten"/>
+ <button name="Mute" text="Ignorieren"/>
</form>
</notification>
<notification name="VoiceInviteAdHoc">
- [NAME] ist einem Voice-Konferenz-Chat beigetreten.
-Klicken Sie auf „Akzeptieren“, um dem Gespräch beizutreten, oder auf „Ablehnen“, um die Einladung auszuschlagen. Klicken Sie auf „Stummschalten“, um diesen Benutzer stumm zu schalten.
+ [NAME] ist einem Voice-Chat mit Konferenzschaltung beigetreten.
+Klicken Sie auf &apos;Akzeptieren &apos;, um dem Gespräch beizutreten, oder auf &apos;Ablehnen &apos;, um die Einladung auszuschlagen. Klicken Sie auf Ignorieren, um diesen Anrufer zu ignorieren.
<form name="form">
<button name="Accept" text="Akzeptieren"/>
<button name="Decline" text="Ablehnen"/>
- <button name="Mute" text="Stummschalten"/>
+ <button name="Mute" text="Ignorieren"/>
</form>
</notification>
<notification name="InviteAdHoc">
[NAME] lädt Sie zu einem Konferenz-Chat ein.
-Klicken Sie auf „Akzeptieren“, um dem Chat beizutreten, oder auf „Ablehnen“, um die Einladung auszuschlagen. Klicken Sie auf „Stummschalten“, um diesen Benutzer stumm zu schalten.
+Klicken Sie auf &apos;Akzeptieren &apos;, um dem Chat beizutreten, oder auf &apos;Ablehnen &apos;, um die Einladung auszuschlagen. Klicken Sie auf Ignorieren, um diesen Anrufer zu ignorieren.
<form name="form">
<button name="Accept" text="Akzeptieren"/>
<button name="Decline" text="Ablehnen"/>
- <button name="Mute" text="Stummschalten"/>
+ <button name="Mute" text="Ignorieren"/>
</form>
</notification>
<notification name="VoiceChannelFull">
@@ -2947,25 +2545,25 @@ Klicken Sie auf „Akzeptieren“, um dem Chat beizutreten, oder auf „Ablehnen
Es tut uns Leid. Dieses Gebiet hat seine maximale Kapazität für Voice-Gespräche erreicht. Bitte versuchen Sie es in einem anderen Gebiet.
</notification>
<notification name="VoiceChannelDisconnected">
- Sie haben [VOICE_CHANNEL_NAME] verlassen. Sie werden nun wieder mit dem Umgebungs-Voice-Chat verbunden.
+ Die Verbindung zu [VOICE_CHANNEL_NAME] wurde abgebrochen. Sie werden nun wieder mit dem Chat in Ihrer Nähe verbunden.
</notification>
<notification name="VoiceChannelDisconnectedP2P">
- [VOICE_CHANNEL_NAME] hat das Gespräch beendet. Sie werden nun wieder mit dem Umgebungs-Voice-Chat verbunden.
+ [VOICE_CHANNEL_NAME] hat den Anruf beendet. Sie werden nun wieder mit dem Chat in Ihrer Nähe verbunden.
</notification>
<notification name="P2PCallDeclined">
- [VOICE_CHANNEL_NAME] hat Ihren Anruf abgelehnt. Sie werden nun wieder mit dem Umgebungs-Voice-Chat verbunden.
+ [VOICE_CHANNEL_NAME] hat ihren Anruf abgelehnt. Sie werden nun wieder mit dem Chat in Ihrer Nähe verbunden.
</notification>
<notification name="P2PCallNoAnswer">
- [VOICE_CHANNEL_NAME] ist zurzeit nicht erreichbar. Sie werden nun wieder mit dem Umgebungs-Voice-Chat verbunden.
+ [VOICE_CHANNEL_NAME] kann Ihren Anruf nicht entgegennehmen. Sie werden nun wieder mit dem Chat in Ihrer Nähe verbunden.
</notification>
<notification name="VoiceChannelJoinFailed">
- Verbindung zu [VOICE_CHANNEL_NAME] nicht möglich. Bitte versuchen Sie es später. Sie werden nun wieder mit dem Umgebungs-Voice-Chat verbunden.
+ Verbindung zu [VOICE_CHANNEL_NAME] nicht möglich. Bitte versuchen Sie es später. Sie werden nun wieder mit dem Chat in Ihrer Nähe verbunden.
</notification>
<notification name="VoiceLoginRetry">
Wir erstellen einen Voice-Kanal für Sie. Bitte warten Sie einen Moment.
</notification>
<notification name="Cannot enter parcel: not a group member">
- Zugang zur Parzelle verweigert, Sie gehören keiner berechtigten Gruppe an.
+ Nur Mitglieder einer bestimmten Gruppe dürfen diesen Bereich betreten.
</notification>
<notification name="Cannot enter parcel: banned">
Zugang zur Parzelle verweigert. Sie wurden verbannt.
@@ -2980,18 +2578,43 @@ Klicken Sie auf „Akzeptieren“, um dem Chat beizutreten, oder auf „Ablehnen
Fehler beim Versuch, eine Voice-Chat-Verbindung zu [VOICE_CHANNEL_NAME] herzustellen. Bitte versuchen Sie es erneut.
</notification>
<notification name="ServerVersionChanged">
- Die Region, die Sie betreten haben, verwendet eine andere Simulatorversion. Klicken Sie auf diese Nachricht, um weitere Informationen zu erhalten.
+ Sie haben eine Region betreten, die eine andere Server-Version verwendet. Dies kann sich auf die Leistung auswirken. [[URL] Versionshinweise anzeigen.]
+ </notification>
+ <notification name="UnsupportedCommandSLURL">
+ Die SLurl, auf die Sie geklickt haben, wird nicht unterstützt.
+ </notification>
+ <notification name="IMToast">
+ [MESSAGE]
+ <form name="form">
+ <button name="respondbutton" text="Antworten"/>
+ </form>
</notification>
- <notification name="UnableToOpenCommandURL">
- Die URL, die Sie angeklickt haben, kann in diesem Web Browser nicht geöffnet werden.
+ <notification name="AttachmentSaved">
+ Der Anhang wurde gespeichert.
+ </notification>
+ <notification name="UnableToFindHelpTopic">
+ Hilfethema für dieses Element wurde nicht gefunden.
+ </notification>
+ <notification name="ObjectMediaFailure">
+ Serverfehler: Medienaktualisierung oder Fehler
+&apos;[ERROR]&apos;
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="ConfirmClearTeleportHistory">
+ Möchten Sie Ihren Teleport-Verlauf löschen?
+ <usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/>
+ </notification>
+ <notification name="BottomTrayButtonCanNotBeShown">
+ Die ausgewählte Schaltfläche kann zur Zeit nicht angezeigt werden.
+Die Schaltfläche wird angezeigt, wenn genügend Platz vorhanden ist.
</notification>
<global name="UnsupportedCPU">
- Ihre CPU-Geschwindigkeit entspricht nicht den Mindestanforderungen.
</global>
<global name="UnsupportedGLRequirements">
- Ihr Computer entspricht nicht den Hardwareanforderungen von Second Life. Second Life setzt eine OpenGL-Grafikkarte mit Multitextur-Unterstützung voraus. Falls Ihre Grafikkarte diese Funktion unterstützt, installieren Sie die neuesten Treiber sowie die aktuellen Service Packs und Patches für Ihr Betriebssystem.
+ Ihr Computer entspricht nicht den Hardwareanforderungen von [APP_NAME]. [APP_NAME] setzt eine OpenGL-Grafikkarte mit Multitextur-Unterstützung voraus. Falls Ihre Grafikkarte diese Funktion unterstützt, installieren Sie die neuesten Treiber sowie die aktuellen Service Packs und Patches für Ihr Betriebssystem.
-Sollte das Problem fortbestehen, finden Sie weitere Hilfestellung unter: http://www.secondlife.com/support
+Sollte das Problem fortbestehen, finden Sie weitere Hilfestellung unter [SUPPORT_SITE].
</global>
<global name="UnsupportedCPUAmount">
796
@@ -3005,10 +2628,8 @@ Sollte das Problem fortbestehen, finden Sie weitere Hilfestellung unter: http://
<global name="UnsupportedRAM">
- Ihr Arbeitsspeicher entspricht nicht den Mindestanforderungen.
</global>
- <global name="PermYes">
- Ja
- </global>
- <global name="PermNo">
- Nein
+ <global name="You can only set your &apos;Home Location&apos; on your land or at a mainland Infohub.">
+ Wenn Sie ein Stück Land besitzen, können Sie dies als Ihren Heimatort festlegen.
+Ansonsten können Sie auf der Karte nachsehen und dort Ort suchen, die als „Infohub“ gekennzeichnet sind.
</global>
</notifications>
diff --git a/indra/newview/skins/default/xui/de/panel_activeim_row.xml b/indra/newview/skins/default/xui/de/panel_activeim_row.xml
new file mode 100644
index 0000000000..84272752cf
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_activeim_row.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_activeim_row">
+ <text name="contact_name">
+ Grumpity ProductEngine
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_adhoc_control_panel.xml b/indra/newview/skins/default/xui/de/panel_adhoc_control_panel.xml
new file mode 100644
index 0000000000..6109d8b0ea
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_adhoc_control_panel.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_im_control_panel">
+ <panel name="panel_call_buttons">
+ <button label="Anrufen" name="call_btn"/>
+ <button label="Anruf beenden" name="end_call_btn"/>
+ <button label="Voice-Steuerung" name="voice_ctrls_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/de/panel_avatar_list_item.xml
new file mode 100644
index 0000000000..ae5c1ec424
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_avatar_list_item.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="avatar_list_item">
+ <string name="FormatSeconds">
+ [COUNT]s
+ </string>
+ <string name="FormatMinutes">
+ [COUNT]min
+ </string>
+ <string name="FormatHours">
+ [COUNT]h
+ </string>
+ <string name="FormatDays">
+ [COUNT]d
+ </string>
+ <string name="FormatWeeks">
+ [COUNT]W
+ </string>
+ <string name="FormatMonths">
+ [COUNT]M
+ </string>
+ <string name="FormatYears">
+ [COUNT]J
+ </string>
+ <text name="avatar_name" value="Unbekannt"/>
+ <text name="last_interaction" value="0s"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_avatar_tag.xml b/indra/newview/skins/default/xui/de/panel_avatar_tag.xml
new file mode 100644
index 0000000000..09f930ec01
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_avatar_tag.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="avatar_tag_notification">
+ <panel name="msg_caption">
+ <text name="sender_tag_name">
+ Angela Tester
+ </text>
+ <text name="tag_time" value="23:30"/>
+ </panel>
+ <text_editor name="msg_text">
+ Zwölf große Boxkämpfer jagen Viktor quer über den großen Sylter Deich.
+ </text_editor>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/de/panel_block_list_sidetray.xml
new file mode 100644
index 0000000000..462009746b
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_block_list_sidetray.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="block_list_panel">
+ <text name="title_text">
+ Liste der ignorierten Einwohner
+ </text>
+ <scroll_list name="blocked" tool_tip="Liste der zur Zeit ignorierten Einwohner"/>
+ <button label="Einwohner ignorieren..." label_selected="Einwohner ignorieren..." name="Block resident..." tool_tip="Wählen Sie einen Einwohner, um ihn zu ignorieren"/>
+ <button label="Objekt nach Name ignorieren..." label_selected="Objekt nach Name ignorieren..." name="Block object by name..." tool_tip="Ein Objekt auswählen, um nach Namen zu ignorieren."/>
+ <button label="Freischalten" label_selected="Freischalten" name="Unblock" tool_tip="Einwohner oder Objekt von der Liste der ignorierten Einwohner oder Objekte entfernen"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_bottomtray.xml b/indra/newview/skins/default/xui/de/panel_bottomtray.xml
new file mode 100644
index 0000000000..11dd99a1d4
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_bottomtray.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="bottom_tray">
+ <string name="SpeakBtnToolTip">
+ Schaltet Mikrofon ein/aus
+ </string>
+ <string name="VoiceControlBtnToolTip">
+ Voice-Chat-Steuerung anzeigen/ausblenden
+ </string>
+ <layout_stack name="toolbar_stack">
+ <layout_panel name="gesture_panel">
+ <gesture_combo_box label="Gesten" name="Gesture" tool_tip="Gesten anzeigen/ausblenden"/>
+ </layout_panel>
+ <layout_panel name="movement_panel">
+ <button label="Bewegen" name="movement_btn" tool_tip="Bewegungssteuerung anzeigen/ausblenden"/>
+ </layout_panel>
+ <layout_panel name="cam_panel">
+ <button label="Ansicht" name="camera_btn" tool_tip="Kamerasteuerung anzeigen/ausblenden"/>
+ </layout_panel>
+ <layout_panel name="snapshot_panel">
+ <button label="" name="snapshots" tool_tip="Foto machen"/>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_chat_header.xml b/indra/newview/skins/default/xui/de/panel_chat_header.xml
new file mode 100644
index 0000000000..babbff3132
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_chat_header.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="im_header" name="im_header">
+ <text_editor name="user_name" value="Ericag Vader"/>
+ <text name="time_box" value="23:30"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_classified_info.xml b/indra/newview/skins/default/xui/de/panel_classified_info.xml
new file mode 100644
index 0000000000..d45e28f0c8
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_classified_info.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_classified_info">
+ <panel.string name="type_mature">
+ Moderat
+ </panel.string>
+ <panel.string name="type_pg">
+ Allgemeiner Inhalt
+ </panel.string>
+ <text name="title" value="Informationen über Anzeige"/>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <text name="classified_name" value="[name]"/>
+ <text name="classified_location" value="[wird geladen...]"/>
+ <text name="content_type" value="[Inhalts-Art]"/>
+ <text name="category" value="[Kategorie]"/>
+ <check_box label="Jede Woche automatisch erneuern" name="auto_renew"/>
+ <text name="price_for_listing" tool_tip="Preis für Anzeige.">
+ [PRICE] L$
+ </text>
+ <text name="classified_desc" value="[description]"/>
+ </panel>
+ </scroll_container>
+ <panel name="buttons">
+ <button label="Teleportieren" name="teleport_btn"/>
+ <button label="Karte" name="show_on_map_btn"/>
+ <button label="Bearbeiten" name="edit_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_alpha.xml b/indra/newview/skins/default/xui/de/panel_edit_alpha.xml
new file mode 100644
index 0000000000..4b48950341
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_edit_alpha.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_alpha_panel">
+ <panel name="avatar_alpha_color_panel">
+ <texture_picker label="Alpha: Unten" name="Lower Alpha" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <texture_picker label="Alpha: Oben" name="Upper Alpha" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <texture_picker label="Kopf: Alpha" name="Head Alpha" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <texture_picker label="Alpha: Augen" name="Eye Alpha" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <texture_picker label="Alpha: Haare" name="Hair Alpha" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_classified.xml b/indra/newview/skins/default/xui/de/panel_edit_classified.xml
new file mode 100644
index 0000000000..ca357abda3
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_edit_classified.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Anzeige bearbeiten" name="panel_edit_classified">
+ <panel.string name="location_notice">
+ (wird nach Speichern aktualisiert)
+ </panel.string>
+ <text name="title">
+ Anzeige bearbeiten
+ </text>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <icon label="" name="edit_icon" tool_tip="Klicken, um ein Bild auszuwählen"/>
+ <text name="Name:">
+ Titel:
+ </text>
+ <text name="description_label">
+ Beschreibung:
+ </text>
+ <text name="location_label">
+ Standort:
+ </text>
+ <text name="classified_location">
+ wird geladen...
+ </text>
+ <button label="Auf aktuelle Position einstellen" name="set_to_curr_location_btn"/>
+ <combo_box name="content_type">
+ <combo_item name="mature_ci">
+ Mature-Inhalt
+ </combo_item>
+ <combo_item name="pg_ci">
+ PG-Inhalt
+ </combo_item>
+ </combo_box>
+ <spinner label="L$" name="price_for_listing" tool_tip="Preis für Anzeige." value="50"/>
+ <check_box label="Jede Woche automatisch erneuern" name="auto_renew"/>
+ </panel>
+ </scroll_container>
+ <panel label="bottom_panel" name="bottom_panel">
+ <button label="Speichern" name="save_changes_btn"/>
+ <button label="Abbrechen" name="cancel_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_eyes.xml b/indra/newview/skins/default/xui/de/panel_edit_eyes.xml
new file mode 100644
index 0000000000..31251ed48f
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_edit_eyes.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_eyes_panel">
+ <panel name="avatar_eye_color_panel">
+ <texture_picker label="Iris" name="Iris" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="eyes_main_tab" title="Augen"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_gloves.xml b/indra/newview/skins/default/xui/de/panel_edit_gloves.xml
new file mode 100644
index 0000000000..2d11befbfd
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_edit_gloves.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_gloves_panel">
+ <panel name="avatar_gloves_color_panel">
+ <texture_picker label="Stoff" name="Fabric" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <color_swatch label="Farbe/Ton" name="Color/Tint" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="gloves_main_tab" title="Handschuhe"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_hair.xml b/indra/newview/skins/default/xui/de/panel_edit_hair.xml
new file mode 100644
index 0000000000..d255b1c16c
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_edit_hair.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_hair_panel">
+ <panel name="avatar_hair_color_panel">
+ <texture_picker label="Textur" name="Texture" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="hair_color_tab" title="Farbe"/>
+ <accordion_tab name="hair_style_tab" title="Stil"/>
+ <accordion_tab name="hair_eyebrows_tab" title="Augenbrauen"/>
+ <accordion_tab name="hair_facial_tab" title="Gesicht"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_jacket.xml b/indra/newview/skins/default/xui/de/panel_edit_jacket.xml
new file mode 100644
index 0000000000..3752faf48a
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_edit_jacket.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_jacket_panel">
+ <panel name="avatar_jacket_color_panel">
+ <texture_picker label="Oberstoff" name="Upper Fabric" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <texture_picker label="Unterstoff" name="Lower Fabric" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <color_swatch label="Farbe/Ton" name="Color/Tint" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="jacket_main_tab" title="Jacke"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_pants.xml b/indra/newview/skins/default/xui/de/panel_edit_pants.xml
new file mode 100644
index 0000000000..1ff439dc26
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_edit_pants.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_pants_panel">
+ <panel name="avatar_pants_color_panel">
+ <texture_picker label="Stoff" name="Fabric" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <color_swatch label="Farbe/Ton" name="Color/Tint" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="pants_main_tab" title="Hose"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_pick.xml b/indra/newview/skins/default/xui/de/panel_edit_pick.xml
new file mode 100644
index 0000000000..bd05a4151e
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_edit_pick.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Auswahl bearbeiten" name="panel_edit_pick">
+ <text name="title">
+ Auswahl bearbeiten
+ </text>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <icon label="" name="edit_icon" tool_tip="Klicken, um ein Bild auszuwählen"/>
+ <text name="Name:">
+ Titel:
+ </text>
+ <text name="description_label">
+ Beschreibung:
+ </text>
+ <text name="location_label">
+ Standort:
+ </text>
+ <text name="pick_location">
+ wird geladen...
+ </text>
+ <button label="Auf aktuelle Position einstellen" name="set_to_curr_location_btn"/>
+ </panel>
+ </scroll_container>
+ <panel label="bottom_panel" name="bottom_panel">
+ <button label="[WHAT] speichern" name="save_changes_btn"/>
+ <button label="Abbrechen" name="cancel_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_profile.xml b/indra/newview/skins/default/xui/de/panel_edit_profile.xml
new file mode 100644
index 0000000000..811ca118d6
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_edit_profile.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Profil bearbeiten" name="edit_profile_panel">
+ <string name="CaptionTextAcctInfo">
+ [ACCTTYPE]
+[PAYMENTINFO] [AGEVERIFICATION]
+ </string>
+ <string name="RegisterDateFormat">
+ [REG_DATE] ([AGE])
+ </string>
+ <string name="AcctTypeResident" value="Einwohner"/>
+ <string name="AcctTypeTrial" value="Test"/>
+ <string name="AcctTypeCharterMember" value="Charta-Mitglied"/>
+ <string name="AcctTypeEmployee" value="Linden Lab-Mitarbeiter"/>
+ <string name="PaymentInfoUsed" value="Zahlungsinfo verwendet"/>
+ <string name="PaymentInfoOnFile" value="Zahlungsinfo archiviert"/>
+ <string name="NoPaymentInfoOnFile" value="Keine Zahlungsinfo archiviert"/>
+ <string name="AgeVerified" value="Altersgeprüft"/>
+ <string name="NotAgeVerified" value="Nicht altersgeprüft"/>
+ <string name="partner_edit_link_url">
+ http://www.secondlife.com/account/partners.php?lang=de
+ </string>
+ <string name="no_partner_text" value="Keiner"/>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <panel name="data_panel">
+ <panel name="lifes_images_panel">
+ <panel name="second_life_image_panel">
+ <text name="second_life_photo_title_text" value="[SECOND_LIFE]:"/>
+ </panel>
+ <icon label="" name="2nd_life_edit_icon" tool_tip="Klicken, um ein Bild auszuwählen"/>
+ </panel>
+ <panel name="first_life_image_panel">
+ <text name="real_world_photo_title_text" value="Echtes Leben:"/>
+ </panel>
+ <icon label="" name="real_world_edit_icon" tool_tip="Klicken, um ein Bild auszuwählen"/>
+ <text name="title_homepage_text">
+ Webseite:
+ </text>
+ <line_editor name="homepage_edit" value="http://"/>
+ <check_box label="In Suchergebnissen anzeigen" name="show_in_search_checkbox"/>
+ <text name="title_acc_status_text" value="Mein Konto:"/>
+ <text name="my_account_link" value="[[URL] Meine Startseite aufrufen]"/>
+ <text name="acc_status_text" value="Einwohner. Keine Zahlungsinfo archiviert."/>
+ <text name="title_partner_text" value="Mein Partner:"/>
+ <text name="partner_edit_link" value="[[URL] bearbeiten]"/>
+ <panel name="partner_data_panel">
+ <text name="partner_text" value="[FIRST] [LAST]"/>
+ </panel>
+ </panel>
+ </panel>
+ </scroll_container>
+ <panel name="profile_me_buttons_panel">
+ <button label="Änderungen speichern" name="save_btn"/>
+ <button label="Abbrechen" name="cancel_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_shape.xml b/indra/newview/skins/default/xui/de/panel_edit_shape.xml
new file mode 100644
index 0000000000..37be3c1d90
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_edit_shape.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_shape_panel">
+ <panel name="avatar_sex_panel">
+ <text name="gender_text">
+ Geschlecht:
+ </text>
+ <radio_group name="sex_radio">
+ <radio_item label="weiblich" name="radio"/>
+ <radio_item label="Männlich" name="radio2"/>
+ </radio_group>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="shape_body_tab" title="Körper"/>
+ <accordion_tab name="shape_head_tab" title="Kopf"/>
+ <accordion_tab name="shape_eyes_tab" title="Augen"/>
+ <accordion_tab name="shape_ears_tab" title="Ohren"/>
+ <accordion_tab name="shape_nose_tab" title="Nase"/>
+ <accordion_tab name="shape_mouth_tab" title="Mund"/>
+ <accordion_tab name="shape_chin_tab" title="Kinn"/>
+ <accordion_tab name="shape_torso_tab" title="Oberkörper"/>
+ <accordion_tab name="shape_legs_tab" title="Beine"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_shirt.xml b/indra/newview/skins/default/xui/de/panel_edit_shirt.xml
new file mode 100644
index 0000000000..6025606777
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_edit_shirt.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_shirt_panel">
+ <panel name="avatar_shirt_color_panel">
+ <texture_picker label="Stoff" name="Fabric" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <color_swatch label="Farbe/Ton" name="Color/Tint" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="shirt_main_tab" title="Hemd"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_shoes.xml b/indra/newview/skins/default/xui/de/panel_edit_shoes.xml
new file mode 100644
index 0000000000..15e8a21dd7
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_edit_shoes.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_shoes_panel">
+ <panel name="avatar_shoes_color_panel">
+ <texture_picker label="Stoff" name="Fabric" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <color_swatch label="Farbe/Ton" name="Color/Tint" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="shoes_main_tab" title="Schuhe"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_skin.xml b/indra/newview/skins/default/xui/de/panel_edit_skin.xml
new file mode 100644
index 0000000000..46bd1d9f4d
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_edit_skin.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_skin_panel">
+ <panel name="avatar_skin_color_panel">
+ <texture_picker label="Kopftattoo" name="Head Tattoos" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <texture_picker label="Obere Tattoos" name="Upper Tattoos" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <texture_picker label="Untere Tattoos" name="Lower Tattoos" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="skin_color_tab" title="Hautfarbe"/>
+ <accordion_tab name="skin_face_tab" title="Gesichtsdetails"/>
+ <accordion_tab name="skin_makeup_tab" title="Make-Uup"/>
+ <accordion_tab name="skin_body_tab" title="Körperdetails"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_skirt.xml b/indra/newview/skins/default/xui/de/panel_edit_skirt.xml
new file mode 100644
index 0000000000..4fa9126c37
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_edit_skirt.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_skirt_panel">
+ <panel name="avatar_skirt_color_panel">
+ <texture_picker label="Stoff" name="Fabric" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <color_swatch label="Farbe/Ton" name="Color/Tint" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="skirt_main_tab" title="Rock"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_socks.xml b/indra/newview/skins/default/xui/de/panel_edit_socks.xml
new file mode 100644
index 0000000000..c2ecad8642
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_edit_socks.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_socks_panel">
+ <panel name="avatar_socks_color_panel">
+ <texture_picker label="Stoff" name="Fabric" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <color_swatch label="Farbe/Ton" name="Color/Tint" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="socks_main_tab" title="Socken"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/de/panel_edit_tattoo.xml
new file mode 100644
index 0000000000..c05a3a6645
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_edit_tattoo.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_tattoo_panel">
+ <panel name="avatar_tattoo_color_panel">
+ <texture_picker label="Kopftattoo" name="Head Tattoo" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <texture_picker label="Obere Tattoos" name="Upper Tattoo" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <texture_picker label="Untere Tattoos" name="Lower Tattoo" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_underpants.xml b/indra/newview/skins/default/xui/de/panel_edit_underpants.xml
new file mode 100644
index 0000000000..4484068c1d
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_edit_underpants.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_underpants_panel">
+ <panel name="avatar_underpants_color_panel">
+ <texture_picker label="Stoff" name="Fabric" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <color_swatch label="Farbe/Ton" name="Color/Tint" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="underpants_main_tab" title="Unterhose"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_undershirt.xml b/indra/newview/skins/default/xui/de/panel_edit_undershirt.xml
new file mode 100644
index 0000000000..847f806fce
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_edit_undershirt.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_undershirt_panel">
+ <panel name="avatar_undershirt_color_panel">
+ <texture_picker label="Stoff" name="Fabric" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
+ <color_swatch label="Farbe/Ton" name="Color/Tint" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="undershirt_main_tab" title="Unterhemd"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_wearable.xml b/indra/newview/skins/default/xui/de/panel_edit_wearable.xml
new file mode 100644
index 0000000000..c3ffb2f353
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_edit_wearable.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Tragbar" name="panel_edit_wearable">
+ <string name="edit_shape_title">
+ Form bearbeiten
+ </string>
+ <string name="edit_skin_title">
+ Skin (Haut) bearbeiten
+ </string>
+ <string name="edit_hair_title">
+ Haare bearbeiten
+ </string>
+ <string name="edit_eyes_title">
+ Augen bearbeiten
+ </string>
+ <string name="edit_shirt_title">
+ Hemd bearbeiten
+ </string>
+ <string name="edit_pants_title">
+ Hosen bearbeiten
+ </string>
+ <string name="edit_shoes_title">
+ Schuhe bearbeiten
+ </string>
+ <string name="edit_socks_title">
+ Strümpfe bearbeiten
+ </string>
+ <string name="edit_jacket_title">
+ Jacke bearbeiten
+ </string>
+ <string name="edit_skirt_title">
+ Rock bearbeiten
+ </string>
+ <string name="edit_gloves_title">
+ Handschuhe bearbeiten
+ </string>
+ <string name="edit_undershirt_title">
+ Unterhemd bearbeiten
+ </string>
+ <string name="edit_underpants_title">
+ Unterhose bearbeiten
+ </string>
+ <string name="edit_alpha_title">
+ Alpha-Maske bearbeiten
+ </string>
+ <string name="edit_tattoo_title">
+ Tätowierung bearbeiten
+ </string>
+ <string name="shape_desc_text">
+ Form:
+ </string>
+ <string name="skin_desc_text">
+ Haut:
+ </string>
+ <string name="hair_desc_text">
+ Haare:
+ </string>
+ <string name="eyes_desc_text">
+ Augen:
+ </string>
+ <string name="shirt_desc_text">
+ Hemd:
+ </string>
+ <string name="pants_desc_text">
+ Hose:
+ </string>
+ <string name="shoes_desc_text">
+ Schuhe:
+ </string>
+ <string name="socks_desc_text">
+ Socken:
+ </string>
+ <string name="jacket_desc_text">
+ Jacke:
+ </string>
+ <string name="skirt_skirt_desc_text">
+ Rock:
+ </string>
+ <string name="gloves_desc_text">
+ Handschuhe:
+ </string>
+ <string name="undershirt_desc_text">
+ Unterhemd:
+ </string>
+ <string name="underpants_desc_text">
+ Unterhose:
+ </string>
+ <string name="alpha_desc_text">
+ Alpha-Maske:
+ </string>
+ <string name="tattoo_desc_text">
+ Tätowierung:
+ </string>
+ <text name="edit_wearable_title" value="Form bearbeiten"/>
+ <panel label="Hemd" name="wearable_type_panel">
+ <text name="description_text" value="Form:"/>
+ </panel>
+ <panel name="button_panel">
+ <button label="Speichern unter" name="save_as_button"/>
+ <button label="Zurücksetzen" name="revert_button"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_group_control_panel.xml b/indra/newview/skins/default/xui/de/panel_group_control_panel.xml
new file mode 100644
index 0000000000..6a7546457f
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_group_control_panel.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_im_control_panel">
+ <button label="Gruppeninfo" name="group_info_btn"/>
+ <panel name="panel_call_buttons">
+ <button label="Gruppe anrufen" name="call_btn"/>
+ <button label="Anruf beenden" name="end_call_btn"/>
+ <button label="Voice-Steuerung öffnen" name="voice_ctrls_btn"/>
+ </panel>
+</panel>
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 ce19248755..e6abd4349d 100644
--- a/indra/newview/skins/default/xui/de/panel_group_general.xml
+++ b/indra/newview/skins/default/xui/de/panel_group_general.xml
@@ -1,80 +1,37 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Allgemein" name="general_tab">
- <string name="help_text">
- Die Registerkarte „Allgemein“ enthält Informationen über
-diese Gruppe, eine Liste der Eigentümer und sichtbaren Mitglieder,
-allgemeine Gruppeneinstellungen und Mitgliederoptionen.
+ <panel.string name="help_text">
+ Die Registerkarte Allgemein enthält allgemeine Informationen über diese Gruppe, eine Liste der Mitglieder, allgemeine Gruppeneinstellungen und Mitgliederoptionen.
Bewegen Sie die Maus über die Optionen, um weitere Informationen anzuzeigen.
- </string>
- <string name="group_info_unchanged">
+ </panel.string>
+ <panel.string name="group_info_unchanged">
Die allgemeine Gruppeninfo wurde geändert.
- </string>
- <button label="?" label_selected="?" name="help_button"/>
- <line_editor label="Neuen Gruppennamen hier eingeben" name="group_name_editor"/>
- <text name="group_name">
- Neuen Gruppennamen hier eingeben
- </text>
- <text name="prepend_founded_by">
- Gegründet von
- </text>
- <text left_delta="79" name="founder_name">
- (wartet)
- </text>
- <text name="group_charter_label">
- Gruppencharta
- </text>
- <texture_picker label="Gruppeninsignien" name="insignia" tool_tip="Klicken Sie hier, um ein Bild auszuwählen"/>
+ </panel.string>
+ <panel.string name="incomplete_member_data_str">
+ Mitgliedsdaten werden abgerufen
+ </panel.string>
<text_editor name="charter">
Gruppencharta
</text_editor>
- <button label="Beitreten (0 L$)" label_selected="Beitreten (0 L$)" name="join_button"/>
- <button label="Detailansicht" label_selected="Detailansicht" name="info_button"/>
- <text name="text_owners_and_visible_members">
- Eigentümer und sichtbare Mitglieder
- </text>
- <text name="text_owners_are_shown_in_bold">
- (Eigentümer werden fettgedruckt angezeigt)
- </text>
<name_list name="visible_members">
- <column label="Mitgliedsname" name="name" relwidth="0.40"/>
- <column label="Titel" name="title" relwidth="0.25"/>
- <column label="Letzte Anmeldung" name="online" relwidth="0.35"/>
+ <name_list.columns label="Mitglied" name="name" relwidth="0.40"/>
+ <name_list.columns label="Titel" name="title" relwidth="0.25"/>
</name_list>
- <text name="text_group_preferences">
- Gruppeneinstellungen
+ <text name="active_title_label">
+ Mein Titel
</text>
+ <combo_box name="active_title" tool_tip="Legt fest, was im Namensschild Ihres Avatars angezeigt wird, wenn diese Gruppe aktiviert ist."/>
+ <check_box label="Notizen erhalten" name="receive_notices" tool_tip="Festlegen, ob Sie von dieser Gruppe Mitteilungen erhalten können. Deaktivieren Sie diese Option, wenn Sie von der Gruppe Spam erhalten."/>
+ <check_box label="In meinem Profil anzeigen" name="list_groups_in_profile" tool_tip="Steuert, ob diese Gruppe in Ihrem Profil angezeigt wird"/>
<panel name="preferences_container">
- <check_box label="In Suche anzeigen" name="show_in_group_list" tool_tip="Diese Gruppe in Suchergebnissen anzeigen."/>
<check_box label="Registrierung offen" name="open_enrollement" tool_tip="Festlegen, ob der Gruppenbeitritt ohne Einladung zulässig ist."/>
- <check_box label="Beitrittsgebühr: L$" name="check_enrollment_fee" tool_tip="Festlegen, ob Neumitglieder eine Beitrittsgebühr zahlen müssen." width="125"/>
- <spinner 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="Festlegen, ob die Informationen Ihrer Gruppe „Mature“ sind.">
- <combo_item name="select_mature">
- - Mature wählen -
- </combo_item>
- <combo_item name="mature">
- Mature-Inhalt
- </combo_item>
- <combo_item name="pg">
- PG-Inhalt
- </combo_item>
+ <check_box label="Beitrittsgebühr" 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."/>
+ <check_box initial_value="true" label="In Suche anzeigen" name="show_in_group_list" tool_tip="Diese Gruppe in Suchergebnissen anzeigen"/>
+ <combo_box name="group_mature_check" tool_tip="Festlegen, ob die Informationen Ihrer Gruppe „Moderat“ sind">
+ <combo_box.item label="PG-Inhalt" name="pg"/>
+ <combo_box.item label="Mature-Inhalt" name="mature"/>
</combo_box>
- <panel name="title_container">
- <text name="active_title_label">
- Mein aktiver Titel
- </text>
- <combo_box name="active_title" tool_tip="Legt fest, was im Namensschild Ihres Avatars angezeigt wird, wenn diese Gruppe aktiviert ist."/>
- </panel>
- <check_box label="Gruppenmitteilungen erhalten" name="receive_notices" tool_tip="Festlegen, ob Sie von dieser Gruppe Mitteilungen erhalten können. Deaktivieren Sie diese Option, wenn Sie von der Gruppe Spam erhalten." width="173"/>
- <check_box label="Gruppe im Profil anzeigen" name="list_groups_in_profile" tool_tip="Steuert, ob diese Gruppe in Ihrem Profil angezeigt wird"/>
</panel>
- <string name="incomplete_member_data_str">
- Mitgliedsdaten werden abgerufen
- </string>
- <string name="confirm_group_create_str">
- Die Gründung dieser Gruppe kostet 100 L$.
-Sind Sie wirklich, WIRKLICH sicher, dass Sie 100 L$ für die Gründung dieser Gruppe ausgeben möchten?
-Falls in den nächsten 48 Stunden niemand sonst dieser Gruppe beitritt, wird sie aufgelöst und der Name der Gruppe wird nicht mehr verfügbar sein.
- </string>
</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/de/panel_group_info_sidetray.xml
new file mode 100644
index 0000000000..71a0adcdfb
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_group_info_sidetray.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Gruppeninfo" name="GroupInfo">
+ <panel.string name="default_needs_apply_text">
+ In der aktuellen Registerkarte befinden sich ungesicherte Änderungen
+ </panel.string>
+ <panel.string name="want_apply_text">
+ Möchten Sie diese Änderungen speichern?
+ </panel.string>
+ <panel.string name="group_join_btn">
+ Beitreten ([AMOUNT]L$)
+ </panel.string>
+ <panel.string name="group_join_free">
+ Kostenlos
+ </panel.string>
+ <text name="group_name" value="(Lädt...)"/>
+ <line_editor label="Geben Sie Ihren neuen Gruppennamen hier ein" name="group_name_editor"/>
+ <texture_picker label="" name="insignia" tool_tip="Klicken Sie, um ein Bild auszuwählen"/>
+ <text name="prepend_founded_by">
+ Gründer:
+ </text>
+ <name_box initial_value="(empfange)" name="founder_name"/>
+ <text name="join_cost_text">
+ Kostenlos
+ </text>
+ <button label="JETZT BEITRETEN!" name="btn_join"/>
+ <accordion name="groups_accordion">
+ <accordion_tab name="group_general_tab" title="Allgemein"/>
+ <accordion_tab name="group_roles_tab" title="Rollen"/>
+ <accordion_tab name="group_notices_tab" title="Mitteilungen"/>
+ <accordion_tab name="group_land_tab" title="Land/Kapital"/>
+ </accordion>
+ <panel name="button_row">
+ <button label="Erstellen" label_selected="Neue Gruppe" name="btn_create"/>
+ <button label="Speichern" label_selected="Speichern" name="btn_apply"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_group_invite.xml b/indra/newview/skins/default/xui/de/panel_group_invite.xml
index 84ba91a63f..0712722cb3 100644
--- a/indra/newview/skins/default/xui/de/panel_group_invite.xml
+++ b/indra/newview/skins/default/xui/de/panel_group_invite.xml
@@ -1,29 +1,29 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Mitglied einladen" name="invite_panel">
+ <panel.string name="confirm_invite_owner_str">
+ Möchten Sie wirklich (einen) neue(n) Eigentümer einladen? Dies kann nicht rückgängig gemacht werden!
+ </panel.string>
+ <panel.string name="loading">
+ (wird geladen...)
+ </panel.string>
+ <panel.string name="already_in_group">
+ Einige Avatare sind bereits Mitglied und wurden nicht eingeladen.
+ </panel.string>
<text name="help_text">
Sie können mehrere Einwohner in Ihre
Gruppe einladen. Klicken Sie hierzu
auf „Einwohnerliste öffnen“.
</text>
<button label="Einwohnerliste öffnen" name="add_button" tool_tip=""/>
- <name_list name="invitee_list"
- tool_tip="Halten Sie zur Mehrfachauswahl die Strg-Taste gedrückt und klicken Sie auf die Einwohnernamen." />
- <button label="Auswahl aus Liste löschen" name="remove_button"
- tool_tip="Die oben ausgewählten Einwohner von der Einladungsliste entfernen." />
- <text>
- Wählen Sie eine Rolle aus:
- </text>
+ <name_list name="invitee_list" tool_tip="Halten Sie zur Mehrfachauswahl die Strg-Taste gedrückt und klicken Sie auf die Einwohnernamen."/>
+ <button label="Auswahl aus Liste löschen" name="remove_button" tool_tip="Die oben ausgewählten Einwohner von der Einladungsliste entfernen."/>
<text name="role_text">
Wählen Sie eine Rolle aus:
</text>
- <combo_box name="role_name"
- tool_tip="Wählen Sie aus der Liste der Rollen, die Sie an Mitglieder vergeben dürfen." />
- <button label="Einladungen versenden" name="ok_button" />
- <button label="Abbrechen" name="cancel_button" />
- <string name="confirm_invite_owner_str">
- Möchten Sie wirklich (einen) neue(n) Eigentümer einladen? Dies kann nicht rückgängig gemacht werden!
+ <combo_box name="role_name" tool_tip="Wählen Sie aus der Liste der Rollen, die Sie an Mitglieder vergeben dürfen."/>
+ <button label="Einladungen versenden" name="ok_button"/>
+ <button label="Abbrechen" name="cancel_button"/>
+ <string name="GroupInvitation">
+ Gruppeneinladung
</string>
- <text name="loading">
- (wird geladen...)
- </text>
</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_group_land_money.xml b/indra/newview/skins/default/xui/de/panel_group_land_money.xml
index c038d97822..e9743c5d5d 100644
--- a/indra/newview/skins/default/xui/de/panel_group_land_money.xml
+++ b/indra/newview/skins/default/xui/de/panel_group_land_money.xml
@@ -1,6 +1,92 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Land und L$" name="land_money_tab">
<string name="help_text">
+ Ein Warnhinweis wird angezeigt, solange der Wert für das insgesamt verwendete Land gleich oder weniger ist als der Gesamtbeitrag.
+ </string>
+ <button label="?" name="help_button"/>
+ <string name="cant_view_group_land_text">
+ Sie sind nicht berechtigt, Landeigentum der Gruppe anzuzeigen.
+ </string>
+ <string name="cant_view_group_accounting_text">
+ Sie sind nicht berechtigt, die Finanzinformationen der Gruppe anzuzeigen.
+ </string>
+ <string name="loading_txt">
+ Wird geladen...
+ </string>
+ <text name="group_land_heading">
+ Land in Gruppenbesitz
+ </text>
+ <scroll_list name="group_parcel_list">
+ <column label="Parzelle" name="name"/>
+ <column label="Region" name="location"/>
+ <column label="Typ" name="type"/>
+ <column label="Gebiet" name="area"/>
+ <column label="" name="hidden"/>
+ </scroll_list>
+ <button label="Karte" label_selected="Karte" name="map_button"/>
+ <text name="total_contributed_land_label">
+ Gesamtbeitrag:
+ </text>
+ <text name="total_contributed_land_value">
+ [AREA] m².
+ </text>
+ <text name="total_land_in_use_label">
+ Insgesamt verwendetes Land:
+ </text>
+ <text name="total_land_in_use_value">
+ [AREA] m².
+ </text>
+ <text name="land_available_label">
+ Land verfügbar:
+ </text>
+ <text name="land_available_value">
+ [AREA] m².
+ </text>
+ <text name="your_contribution_label">
+ Ihr Beitrag:
+ </text>
+ <string name="land_contrib_error">
+ Ihr Landbeitrag kann nicht festgelegt werden.
+ </string>
+ <text name="your_contribution_units">
+ m²
+ </text>
+ <text name="your_contribution_max_value">
+ ([AMOUNT] max.)
+ </text>
+ <text name="group_over_limit_text">
+ Um das benutzte Land zu unterstützen, sind weitere Landnutzungsrechte erforderlich.
+ </text>
+ <text name="group_money_heading">
+ Gruppen-L$
+ </text>
+ <tab_container name="group_money_tab_container">
+ <panel label="PLANUNG" name="group_money_planning_tab">
+ <text_editor name="group_money_planning_text">
+ Wird geladen...
+ </text_editor>
+ </panel>
+ <panel label="DETAILS" name="group_money_details_tab">
+ <text_editor name="group_money_details_text">
+ Wird geladen...
+ </text_editor>
+ <button label="&lt; Früher" label_selected="&lt; Früher" name="earlier_details_button" tool_tip="Hinten"/>
+ <button label="Später &gt;" label_selected="Später &gt;" name="later_details_button" tool_tip="Weiter"/>
+ </panel>
+ <panel label="VERKAUF" name="group_money_sales_tab">
+ <text_editor name="group_money_sales_text">
+ Wird geladen...
+ </text_editor>
+ <button label="&lt; Früher" label_selected="&lt; Früher" name="earlier_sales_button" tool_tip="Hinten"/>
+ <button label="Später &gt;" label_selected="Später &gt;" name="later_sales_button" tool_tip="Weiter"/>
+ </panel>
+ </tab_container>
+</panel>
+<!--
+
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Land und L$" name="land_money_tab">
+ <string name="help_text">
Parzellen in Gruppenbesitz werden zusammen mit Beitragsdetails angezeigt. Ein Warnhinweis wird angezeigt, solange der Wert für das insgesamt verwendete Land gleich oder weniger ist als der Gesamtbeitrag. Die Registerkarten „Planung“, „Details“ und „Verkäufe“ enthalten Informationen über die Gruppenfinanzen.
</string>
<button label="?" name="help_button"/>
@@ -80,3 +166,5 @@ das verwendete Land gehalten werden kann.
</panel>
</tab_container>
</panel>
+
+-->
diff --git a/indra/newview/skins/default/xui/de/panel_group_list_item.xml b/indra/newview/skins/default/xui/de/panel_group_list_item.xml
new file mode 100644
index 0000000000..1b37c35ea5
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_group_list_item.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="group_list_item">
+ <text name="group_name" value="Unbekannt"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_group_notices.xml b/indra/newview/skins/default/xui/de/panel_group_notices.xml
index 12dcbb1321..6d0fd9eefb 100644
--- a/indra/newview/skins/default/xui/de/panel_group_notices.xml
+++ b/indra/newview/skins/default/xui/de/panel_group_notices.xml
@@ -1,48 +1,34 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Mitteilungen" name="notices_tab">
- <text name="help_text">
- Mitteilungen sind eine schnelle Möglichkeit,
-Mitglieder auf dem Laufenden zu halten und
-Objekte im Anhang zu versenden. Mitteilungen werden
-nur an Mitglieder mit einer entsprechenden Rolle
-gesendet. Mitteilungen können unter
-„Allgemein“ ausgeschaltet werden.
- </text>
- <text name="no_notices_text">
+ <panel.string name="help_text">
+ Mit Mitteilungen können Sie eine Nachricht und
+Objekte im Anhang versenden. Mitteilungen werden
+nur an Mitglieder mit einer entsprechenden Rolle
+gesendet. Mitteilungen können unter
+ &apos;Allgemein &apos; ausgeschaltet werden.
+ </panel.string>
+ <panel.string name="no_notices_text">
Keine älteren Mitteilungen.
- </text>
- <button label="?" label_selected="?" name="help_button" />
- <text name="lbl">
- Gruppenmitteilungsarchiv
- </text>
+ </panel.string>
<text name="lbl2">
- Mitteilungen werden 14 Tage lang aufbewahrt. Klicken Sie auf eine Mitteilung,
-um sie anzuzeigen. Klicken Sie „Aktualisieren“, um neue Mitteilungen zu suchen.
-Eine Mitteilungsliste speichert maximal 200 Mitteilungen pro Gruppe täglich.
+ Mitteilungen werden 14 Tage lang aufbewahrt.
+Maximal 200 pro Gruppe täglich
</text>
<scroll_list name="notice_list">
- <column label="" name="icon" />
- <column label="Thema" name="subject" />
- <column label="Von" name="from" />
- <column label="Datum" name="date" />
+ <scroll_list.columns label="" name="icon"/>
+ <scroll_list.columns label="Thema" name="subject"/>
+ <scroll_list.columns label="Von" name="from"/>
+ <scroll_list.columns label="Datum" name="date"/>
</scroll_list>
<text name="notice_list_none_found">
Nicht gefunden.
</text>
- <button label="Neue Mitteilung" label_selected="Neue Mitteilung"
- name="create_new_notice" />
- <button label="Aktualisieren" label_selected="Liste aktualisieren"
- name="refresh_notices" />
+ <button label="Neue Mitteilung erstellen" label_selected="Neue Mitteilung" name="create_new_notice" tool_tip="Neue Mitteilung erstellen"/>
+ <button label="Aktualisieren" label_selected="Liste aktualisieren" name="refresh_notices"/>
<panel label="Neue Mitteilung" name="panel_create_new_notice">
<text name="lbl">
Mitteilung schreiben
</text>
- <text name="lbl2">
- Geben Sie einen Betreff für die Mitteilung ein. Sie können der
-Mitteilung ein Objekt anfügen, indem Sie es aus dem Inventar
-in dieses Feld ziehen. Angehängte Objekte müssen kopier-
-und transferierbar sein. Ordner können nicht gesendet werden.
- </text>
<text name="lbl3">
Betreff:
</text>
@@ -52,18 +38,19 @@ und transferierbar sein. Ordner können nicht gesendet werden.
<text name="lbl5">
Anhängen:
</text>
- <button label="Anhang entfernen" label_selected="Anhang entfernen"
- name="remove_attachment" />
- <button label="Mitteilung senden" label_selected="Mitteilung senden" name="send_notice" />
- <panel name="drop_target"
- tool_tip="Drag an inventory item onto the message box to send it with the notice. You must have permission to copy and transfer the object to send it with the notice." />
+ <text name="string">
+ Hierhin ziehen, um etwas anzuhängen -- &gt;
+ </text>
+ <button label="Entfernen" label_selected="Anhang entfernen" name="remove_attachment"/>
+ <button label="Senden" label_selected="Senden" name="send_notice"/>
+ <group_drop_target name="drop_target" tool_tip="Drag an inventory item onto the message box to send it with the notice. You must have permission to copy and transfer the object to send it with the notice."/>
</panel>
<panel label="Ältere Notiz anzeigen" name="panel_view_past_notice">
<text name="lbl">
Archivierte Mitteilung
</text>
<text name="lbl2">
- Klicken Sie zum Senden einer Mitteilung auf „Neue Mitteilung“.
+ Um eine neue Mitteilung zu senden, klicken Sie die Schaltfläche +
</text>
<text name="lbl3">
Betreff:
@@ -71,6 +58,6 @@ und transferierbar sein. Ordner können nicht gesendet werden.
<text name="lbl4">
Nachricht:
</text>
- <button label="Anlage öffnen" label_selected="Anlage öffnen" name="open_attachment" />
+ <button label="Anhang öffnen" label_selected="Anlage öffnen" name="open_attachment"/>
</panel>
</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_group_notify.xml b/indra/newview/skins/default/xui/de/panel_group_notify.xml
new file mode 100644
index 0000000000..cb4c6cdb39
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_group_notify.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="instant_message" name="panel_group_notify">
+ <string name="message_max_lines_count" value="7"/>
+ <string name="subject_font" value="SANSSERIF_BIG"/>
+ <string name="date_font" value="SANSSERIF"/>
+ <panel label="Ãœberschrift" name="header">
+ <text name="title" value="Name des Absenders / Gruppenname"/>
+ </panel>
+ <text_editor name="message" value="Nachricht"/>
+ <text name="attachment" value="Anhang"/>
+ <button label="OK" name="btn_ok"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_group_roles.xml b/indra/newview/skins/default/xui/de/panel_group_roles.xml
index d4589f83e4..3103fd65b1 100644
--- a/indra/newview/skins/default/xui/de/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/de/panel_group_roles.xml
@@ -1,157 +1,115 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Mitglieder und Rollen" name="roles_tab">
- <string name="default_needs_apply_text">
- Das Unterregister enthält nicht übernommene Änderungen.
- </string>
- <string name="want_apply_text">
- Diese Änderungen übernehmen?
- </string>
- <button label="?" name="help_button"/>
- <panel name="members_header">
- <text name="static">
- Mitglieder und Rollen
- </text>
- <text name="static2">
- Gruppenmitgliedern werden Rollen mit Fähigkeiten zugewiesen. Diese
-Einstellungen können zur flexibleren Organisation angepasst werden.
- </text>
- </panel>
- <panel name="roles_header">
- <text name="static">
- Rollen
- </text>
- <text name="role_properties_modifiable">
- Wählen Sie eine Rolle. Sie können ihren Namen, ihre Beschreibung und den Mitgliedstitel ändern.
- </text>
- <text name="role_properties_not_modifiable">
- Rolle anklicken um Mitglieder und Fähigkeiten anzuzeigen.
- </text>
- <text name="role_actions_modifiable">
- Sie können der Rolle auch Fähigkeiten zuweisen.
- </text>
- <text name="role_actions_not_modifiable">
- Sie können zugewiesene Fähigkeiten anzeigen, aber nicht bearbeiten.
- </text>
- </panel>
- <panel name="actions_header">
- <text name="static">
- Fähigkeiten
- </text>
- <text name="static2">
- Sie können Fähigkeiten-Beschreibungen anzeigen und welche Rollen bzw.
-Mitglieder diese Fähigkeit haben.
- </text>
- </panel>
+ <panel.string name="default_needs_apply_text">
+ Die Registerkarte enthält nicht gespeicherte Änderungen.
+ </panel.string>
+ <panel.string name="want_apply_text">
+ Möchten Sie Ihre Änderungen speichern?
+ </panel.string>
<tab_container name="roles_tab_container">
- <panel label="Mitglieder" name="members_sub_tab" tool_tip="Mitglieder">
- <button label="Suchen" name="search_button"/>
- <button label="Alle anzeigen" name="show_all_button"/>
- <name_list name="member_list">
- <column label="Mitgliedsname" name="name" width="116"/>
- <column label="Ãœbertragene Landanteile" name="donated" width="156"/>
- <column label="Letzte Anmeldung" name="online"/>
- </name_list>
- <button label="Neues Mitglied einladen..." name="member_invite"/>
- <button label="Aus Gruppe werfen" name="member_eject"/>
- <string name="help_text">
+ <panel label="MITGLIEDER" name="members_sub_tab" tool_tip="Mitglieder">
+ <panel.string name="help_text">
Sie können Mitgliedern Rollen zuweisen und entziehen.
Drücken Sie die Strg-Taste und klicken Sie auf Namen,
um mehrere Mitglieder auszuwählen.
- </string>
+ </panel.string>
+ <filter_editor label="Mitglieder filtern" name="filter_input"/>
+ <name_list name="member_list">
+ <name_list.columns label="Mitglied" name="name"/>
+ <name_list.columns label="Ãœbereignung" name="donated"/>
+ <name_list.columns label="Status" name="online"/>
+ </name_list>
+ <button label="Einladen" name="member_invite"/>
+ <button label="Hinauswerfen" name="member_eject"/>
</panel>
- <panel label="Rollen" name="roles_sub_tab">
- <button label="Suchen" name="search_button"/>
- <button label="Alle anzeigen" name="show_all_button"/>
+ <panel label="ROLLEN" name="roles_sub_tab">
+ <panel.string name="help_text">
+ Rollen haben einen Titel und umfassen bestimmte
+Fähigkeiten. Mitglieder können mehrere
+Rollen innehaben. Eine Gruppe kann bis zu 10 Rollen
+definieren, darunter &apos;Jeder &apos; und &apos;Eigentümer &apos;.
+ </panel.string>
+ <panel.string name="cant_delete_role">
+ Die Rollen „Jeder&quot; und „Eigentuemer&quot; sind besondere Rollen und können nicht gelöscht werden.
+ </panel.string>
+ <panel.string name="power_folder_icon">
+ Inv_FolderClosed
+ </panel.string>
+ <panel.string name="power_all_have_icon">
+ Checkbox_On
+ </panel.string>
+ <panel.string name="power_partial_icon">
+ Checkbox_Off
+ </panel.string>
+ <filter_editor label="Rollen filtern" name="filter_input"/>
<scroll_list name="role_list">
- <column label="Rolle" name="name" width="126"/>
- <column label="Titel" name="title" width="180"/>
- <column label="Mitglieder" name="members" width="82"/>
+ <scroll_list.columns label="Rolle" name="name"/>
+ <scroll_list.columns label="Titel" name="title"/>
+ <scroll_list.columns label="#" name="members"/>
</scroll_list>
- <button label="Neue Rolle erstellen..." name="role_create"/>
+ <button label="Neue Rolle" name="role_create"/>
<button label="Rolle löschen" name="role_delete"/>
- <string name="help_text">
- Rollen haben einen Titel und umfassen bestimmte
-Fähigkeiten. Mitglieder können mehrere
-Rollen innehaben. Eine Gruppe kann bis zu 10 Rollen
-definieren, darunter „Jeder“ und „Eigentümer“.
- </string>
- <string name="cant_delete_role">
- Die Rollen „Jeder“ und „Eigentümer“ können nicht gelöscht werden.
- </string>
</panel>
- <panel label="Fähigkeiten" name="actions_sub_tab">
- <button label="Suchen" name="search_button"/>
- <button label="Alle anzeigen" name="show_all_button"/>
- <scroll_list name="action_list" tool_tip="Select an Ability to view more details.">
- <column label="" name="icon"/>
- <column label="" name="action"/>
- </scroll_list>
- <string name="help_text">
+ <panel label="FÄHIGKEITEN" name="actions_sub_tab" tool_tip="Sie können eine Beschreibung der Fähigkeit anzeigen und welche Rollen bzw. Mitglieder über diese Fähigkeit verfügen.">
+ <panel.string name="help_text">
Fähigkeiten verleihen Mitgliedern in Rollen bestimmte
Rechte in einer Gruppe. Es gibt viele verschiedene Fähigkeiten.
- </string>
+ </panel.string>
+ <filter_editor label="Fähigkeiten filtern" name="filter_input"/>
+ <scroll_list name="action_list" tool_tip="Eine Fähigkeit auswählen, um mehr Details anzuzeigen.">
+ <scroll_list.columns label="" name="action"/>
+ </scroll_list>
</panel>
</tab_container>
<panel name="members_footer">
<text name="static">
Rollen
</text>
+ <scroll_list name="member_assigned_roles">
+ <scroll_list.columns label="" name="checkbox"/>
+ <scroll_list.columns label="" name="role"/>
+ </scroll_list>
<text name="static2">
Zulässige Fähigkeiten
</text>
- <scroll_list name="member_assigned_roles">
- <column label="" name="checkbox"/>
- <column label="" name="role"/>
- </scroll_list>
- <scroll_list name="member_allowed_actions" tool_tip="Um detaillierte Informationen zu erlaubten Fähigkeiten anzuzeigen, siehe Reiter Fähigkeiten.">
- <column label="" name="icon"/>
- <column label="" name="action"/>
+ <scroll_list name="member_allowed_actions" tool_tip="Um detaillierte Informationen zu den Fähigkeiten anzuzeigen, siehe Registerkarte Fähigkeiten.">
+ <scroll_list.columns label="" name="action"/>
</scroll_list>
</panel>
<panel name="roles_footer">
<text name="static">
- Name
+ Rolle:
</text>
+ <line_editor name="role_name"/>
+ <text name="static3">
+ Rollentitel
+ </text>
+ <line_editor name="role_title"/>
<text name="static2">
Beschreibung
</text>
- <line_editor name="role_name">
- Angestellte
- </line_editor>
- <text name="static3">
- Titel
- </text>
- <line_editor name="role_title">
- (wartet)
- </line_editor>
- <text_editor name="role_description">
- (wartet)
- </text_editor>
+ <text_editor name="role_description"/>
<text name="static4">
Mitglieder in Rolle
</text>
+ <check_box label="Mitglieder anzeigen" name="role_visible_in_list" tool_tip="Festlegen, ob Mitglieder in dieser Rolle auf der Registerkarte &apos;Allgemein &apos; für Personen außerhalb der Gruppe sichtbar sind."/>
<text name="static5" tool_tip="Eine Liste der Fähigkeiten der aktuell ausgewählten Rolle.">
Zulässige Fähigkeiten
</text>
- <check_box label="Mitglieder sind sichtbar" name="role_visible_in_list" tool_tip="Festlegen, ob Mitglieder in dieser Rolle auf der Registerkarte „Allgemein“ für Personen außerhalb der Gruppe sichtbar sind."/>
- <scroll_list name="role_allowed_actions" tool_tip="Um detaillierte Informationen zu erlaubten Fähigkeiten anzuzeigen, siehe Reiter Fähigkeiten.">
- <column label="" name="icon"/>
- <column label="" name="checkbox"/>
- <column label="" name="action"/>
+ <scroll_list name="role_allowed_actions" tool_tip="Um detaillierte Informationen zu den Fähigkeiten anzuzeigen, siehe Registerkarte Fähigkeiten.">
+ <scroll_list.columns label="" name="checkbox"/>
+ <scroll_list.columns label="" name="action"/>
</scroll_list>
</panel>
<panel name="actions_footer">
- <text name="static">
- Beschreibung
- </text>
<text_editor name="action_description">
Diese Fähigkeit heißt „Mitglieder aus dieser Gruppe werfen“. Eigentümer können nur von anderen Eigentümern hinausgeworfen werden.
</text_editor>
<text name="static2">
- Rollen mit Fähigkeit
+ Rollen mit Fähigkeiten
</text>
<text name="static3">
- Mitglieder mit Fähigkeit
+ Rollen mit dieser Fähigkeit
</text>
</panel>
</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_im_control_panel.xml b/indra/newview/skins/default/xui/de/panel_im_control_panel.xml
new file mode 100644
index 0000000000..d91c7c0dcf
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_im_control_panel.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_im_control_panel">
+ <text name="avatar_name" value="Unbekannt"/>
+ <button label="Profil" name="view_profile_btn"/>
+ <button label="Freund hinzufügen" name="add_friend_btn"/>
+ <button label="Teleportieren" name="teleport_btn"/>
+ <button label="Teilen" name="share_btn"/>
+ <panel name="panel_call_buttons">
+ <button label="Anrufen" name="call_btn"/>
+ <button label="Anruf beenden" name="end_call_btn"/>
+ <button label="Voice-Steuerung" name="voice_ctrls_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_instant_message.xml b/indra/newview/skins/default/xui/de/panel_instant_message.xml
new file mode 100644
index 0000000000..1433552c15
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_instant_message.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="im_panel" name="im_panel">
+ <string name="message_max_lines_count">
+ 6
+ </string>
+ <panel label="im_header" name="im_header">
+ <text name="user_name" value="Erica Vader"/>
+ <text name="time_box" value="23:30"/>
+ </panel>
+ <button label="Antworten" name="reply"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_landmark_info.xml b/indra/newview/skins/default/xui/de/panel_landmark_info.xml
new file mode 100644
index 0000000000..1a68c9b351
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_landmark_info.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="landmark_info">
+ <string name="title_create_landmark" value="Landmarken erstellen"/>
+ <string name="title_edit_landmark" value="Landmarke bearbeiten"/>
+ <string name="title_landmark" value="Landmarke"/>
+ <string name="not_available" value="k.A."/>
+ <string name="unknown" value="(unbekannt)"/>
+ <string name="public" value="(öffentlich)"/>
+ <string name="server_update_text">
+ Ohne Serverupdate sind keine Ortsinformationen verfügbar.
+ </string>
+ <string name="server_error_text">
+ Zur Zeit gibt es keine Informationen zu diesem Standort. Bitte versuchen Sie es später.
+ </string>
+ <string name="server_forbidden_text">
+ Die Informationen über diesen Standort sind zugriffsbeschränkt. Bitte wenden Sie sich bezüglich Ihrer Berechtigungen an den Eigentümer der Parzelle.
+ </string>
+ <string name="acquired_date">
+ [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+ </string>
+ <string name="icon_PG" value="parcel_drk_PG"/>
+ <string name="icon_M" value="parcel_drk_M"/>
+ <string name="icon_R" value="parcel_drk_R"/>
+ <text name="title" value="Ortsprofil"/>
+ <scroll_container name="place_scroll">
+ <panel name="scrolling_panel">
+ <text name="region_title" value="SampleRegion"/>
+ <text name="parcel_title" value="SampleParcel, Name Long (145, 228, 26)"/>
+ <expandable_text name="description" value="Du waltz die spritz"/>
+ <text name="maturity_value" value="unbekannt"/>
+ <panel name="landmark_info_panel">
+ <text name="owner_label" value="Eigentümer:"/>
+ <text name="creator_label" value="Ersteller:"/>
+ <text name="created_label" value="Erstellt:"/>
+ </panel>
+ <panel name="landmark_edit_panel">
+ <text name="title_label" value="Titel:"/>
+ <text name="notes_label" value="Meine Notizen:"/>
+ <text name="folder_label" value="Landmarken-Position:"/>
+ </panel>
+ </panel>
+ </scroll_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_landmarks.xml b/indra/newview/skins/default/xui/de/panel_landmarks.xml
new file mode 100644
index 0000000000..3336232782
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_landmarks.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="Landmarks">
+ <accordion name="landmarks_accordion">
+ <accordion_tab name="tab_favorites" title="Favoritenleiste"/>
+ <accordion_tab name="tab_landmarks" title="Landmarken"/>
+ <accordion_tab name="tab_inventory" title="Mein Inventar"/>
+ <accordion_tab name="tab_library" title="Bibliothek"/>
+ </accordion>
+ <panel name="bottom_panel">
+ <button name="options_gear_btn" tool_tip="Zusätzliche Optionen anzeigen"/>
+ <button name="add_btn" tool_tip="Neue Landmarke hinzufügen"/>
+ <dnd_button name="trash_btn" tool_tip="Ausgewählte Landmarke hinzufügen"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_login.xml b/indra/newview/skins/default/xui/de/panel_login.xml
index 6846b1536c..62973be4cb 100644
--- a/indra/newview/skins/default/xui/de/panel_login.xml
+++ b/indra/newview/skins/default/xui/de/panel_login.xml
@@ -1,49 +1,41 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="panel_login">
- <text name="first_name_text">
- Vorname:
- </text>
- <text name="last_name_text">
- Nachname:
- </text>
- <text name="password_text">
- Kennwort:
- </text>
- <text name="start_location_text">
- Startposition:
- </text>
- <combo_box name="start_location_combo">
- <combo_item name="MyHome">
- Mein Heimatort
- </combo_item>
- <combo_item name="MyLastLocation">
- Mein letzter Standort
- </combo_item>
- <combo_item name="Typeregionname">
- &lt;Region eingeben&gt;
- </combo_item>
- </combo_box>
- <check_box label="Kennwort merken" name="remember_check"/>
- <text name="full_screen_text">
- Die Anzeige schaltet bei Anmeldung auf Vollbild um.
- </text>
- <button label="Neues Konto..." label_selected="Neues Konto..." name="new_account_btn"/>
- <button label="Einstellungen..." label_selected="Einstellungen..." name="preferences_btn"/>
- <button label="Anmelden" label_selected="Anmelden" name="connect_btn"/>
- <button label="Beenden" label_selected="Beenden" name="quit_btn"/>
- <text name="version_text">
- 1.23.4 (5)
- </text>
- <text name="create_new_account_text">
- Konto erstellen
- </text>
- <text name="channel_text">
- [VERSION]
- </text>
- <text name="forgot_password_text">
- Namen oder Kennwort vergessen?
- </text>
- <text name="forgot_password_url">
- http://secondlife.com/account/request.php
- </text>
+ <panel.string name="create_account_url">
+ http://de.secondlife.com/registration/
+ </panel.string>
+ <panel.string name="forgot_password_url">
+ http://secondlife.com/account/request.php?lang=de
+ </panel.string>
+ <panel name="login_widgets">
+ <text name="first_name_text">
+ Vorname:
+ </text>
+ <line_editor name="first_name_edit" tool_tip="[SECOND_LIFE] Vorname"/>
+ <text name="last_name_text">
+ Nachname:
+ </text>
+ <line_editor name="last_name_edit" tool_tip="[SECOND_LIFE] Nachname"/>
+ <text name="password_text">
+ Kennwort:
+ </text>
+ <button label="Login" label_selected="Login" name="connect_btn"/>
+ <text name="start_location_text">
+ Startposition:
+ </text>
+ <combo_box name="start_location_combo">
+ <combo_box.item label="Mein letzter Standort" name="MyLastLocation"/>
+ <combo_box.item label="Mein Zuhause" name="MyHome"/>
+ <combo_box.item label="&lt;Region eingeben&gt;" name="Typeregionname"/>
+ </combo_box>
+ <check_box label="Kennwort merken" name="remember_check"/>
+ <text name="create_new_account_text">
+ Neues Konto erstellen
+ </text>
+ <text name="forgot_password_text">
+ Namen oder Kennwort vergessen?
+ </text>
+ <text name="channel_text">
+ [VERSION]
+ </text>
+ </panel>
</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_main_inventory.xml b/indra/newview/skins/default/xui/de/panel_main_inventory.xml
new file mode 100644
index 0000000000..3d1b89ff40
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_main_inventory.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Sonstiges" name="main inventory panel">
+ <panel.string name="Title">
+ Sonstiges
+ </panel.string>
+ <filter_editor label="Filter" name="inventory search editor"/>
+ <tab_container name="inventory filter tabs">
+ <inventory_panel label="Alle Objekte" name="All Items"/>
+ <inventory_panel label="Letzte Objekte" name="Recent Items"/>
+ </tab_container>
+ <panel name="bottom_panel">
+ <button name="options_gear_btn" tool_tip="Zusätzliche Optionen anzeigen"/>
+ <button name="add_btn" tool_tip="Neues Objekt hinzufügen"/>
+ <dnd_button name="trash_btn" tool_tip="Auswahl löschen"/>
+ </panel>
+ <menu_bar name="Inventory Menu">
+ <menu label="Datei" name="File">
+ <menu_item_call label="Öffnen" name="Open"/>
+ <menu label="Hochladen" name="upload">
+ <menu_item_call label="Bild ([COST] L$)..." name="Upload Image"/>
+ <menu_item_call label="Sound ([COST] L$)..." name="Upload Sound"/>
+ <menu_item_call label="Animation ([COST] L$)..." name="Upload Animation"/>
+ <menu_item_call label="Mehrfach-Upload ([COST] L$ pro Datei)..." name="Bulk Upload"/>
+ </menu>
+ <menu_item_call label="Neues Fenster" name="New Window"/>
+ <menu_item_call label="Filter anzeigen" name="Show Filters"/>
+ <menu_item_call label="Filter zurücksetzen" name="Reset Current"/>
+ <menu_item_call label="Alle Ordner schließen" name="Close All Folders"/>
+ <menu_item_call label="Papierkorb ausleeren" name="Empty Trash"/>
+ <menu_item_call label="Fundstücke ausleeren" name="Empty Lost And Found"/>
+ </menu>
+ <menu label="Bauen" name="Create">
+ <menu_item_call label="Neuer Ordner" name="New Folder"/>
+ <menu_item_call label="Neues Skript" name="New Script"/>
+ <menu_item_call label="Neue Notiz" name="New Note"/>
+ <menu_item_call label="Neue Geste" name="New Gesture"/>
+ <menu label="Neue Kleider" name="New Clothes">
+ <menu_item_call label="Neues Hemd" name="New Shirt"/>
+ <menu_item_call label="Neue Hose" name="New Pants"/>
+ <menu_item_call label="Neue Schuhe" name="New Shoes"/>
+ <menu_item_call label="Neue Socken" name="New Socks"/>
+ <menu_item_call label="Neue Jacke" name="New Jacket"/>
+ <menu_item_call label="Neuer Rock" name="New Skirt"/>
+ <menu_item_call label="Neue Handschuhe" name="New Gloves"/>
+ <menu_item_call label="Neues Unterhemd" name="New Undershirt"/>
+ <menu_item_call label="Neue Unterhose" name="New Underpants"/>
+ <menu_item_call label="Alpha: Neu" name="New Alpha"/>
+ <menu_item_call label="Neue Tätowierung" name="New Tattoo"/>
+ </menu>
+ <menu label="Neue Körperteile" name="New Body Parts">
+ <menu_item_call label="Neue Form/Gestalt" name="New Shape"/>
+ <menu_item_call label="Neue Haut" name="New Skin"/>
+ <menu_item_call label="Neues Haar" name="New Hair"/>
+ <menu_item_call label="Neue Augen" name="New Eyes"/>
+ </menu>
+ </menu>
+ <menu label="Sortieren" name="Sort">
+ <menu_item_check label="Nach Name" name="By Name"/>
+ <menu_item_check label="Nach Datum" name="By Date"/>
+ <menu_item_check label="Ordner immer nach Name" name="Folders Always By Name"/>
+ <menu_item_check label="Systemordner nach oben" name="System Folders To Top"/>
+ </menu>
+ </menu_bar>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_me.xml b/indra/newview/skins/default/xui/de/panel_me.xml
new file mode 100644
index 0000000000..c61fc26f4c
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_me.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Mein Profil" name="panel_me">
+ <tab_container name="tabs">
+ <panel label="PROFIL" name="panel_profile"/>
+ <panel label="AUSWAHL" name="panel_picks"/>
+ </tab_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_media_settings_general.xml b/indra/newview/skins/default/xui/de/panel_media_settings_general.xml
new file mode 100644
index 0000000000..b657333439
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_media_settings_general.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Allgemein" name="Media Settings General">
+ <text name="home_label">
+ Home-URL:
+ </text>
+ <text name="home_fails_whitelist_label">
+ (Diese URL befindet sich nicht auf der festgelegten Whitelist)
+ </text>
+ <line_editor name="home_url" tool_tip="Die Home-URL für diese Medienquelle"/>
+ <text name="preview_label">
+ Vorschau
+ </text>
+ <text name="current_url_label">
+ Derzeitige URL:
+ </text>
+ <text name="current_url" tool_tip="Die derzeitige URL für diese Medienquelle" value=""/>
+ <button label="Zurücksetzen" name="current_url_reset_btn"/>
+ <check_box initial_value="false" label="Automatisch wiederholen" name="auto_loop"/>
+ <check_box initial_value="false" label="Interaktion beim ersten Anklicken" name="first_click_interact"/>
+ <check_box initial_value="false" label="Automatisch zoomen" name="auto_zoom"/>
+ <check_box initial_value="false" label="Medien automatisch abspielen" name="auto_play"/>
+ <text name="media_setting_note">
+ Hinweis: Einwohner können diese Einstellung überschreiben
+ </text>
+ <check_box initial_value="false" label="Medien automatisch auf Objektflächen skalieren" name="auto_scale"/>
+ <text name="size_label">
+ Größe:
+ </text>
+ <text name="X_label">
+ X
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_media_settings_permissions.xml b/indra/newview/skins/default/xui/de/panel_media_settings_permissions.xml
new file mode 100644
index 0000000000..603fb67fd2
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_media_settings_permissions.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Steuerung" name="Media settings for controls">
+ <check_box initial_value="false" label="Navigation &amp; Interaktivität deaktivieren" name="perms_owner_interact"/>
+ <check_box initial_value="false" label="Kontrollleiste verstecken" name="perms_owner_control"/>
+ <check_box initial_value="false" label="Navigation &amp; Interaktivität deaktivieren" name="perms_group_interact"/>
+ <check_box initial_value="false" label="Kontrollleiste verstecken" name="perms_group_control"/>
+ <check_box initial_value="false" label="Navigation &amp; Interaktivität deaktivieren" name="perms_anyone_interact"/>
+ <check_box initial_value="false" label="Kontrollleiste verstecken" name="perms_anyone_control"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_media_settings_security.xml b/indra/newview/skins/default/xui/de/panel_media_settings_security.xml
new file mode 100644
index 0000000000..d94d8b9375
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_media_settings_security.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Sicherheit" name="Media Settings Security">
+ <check_box initial_value="false" label="Zugang nur für bestimmte URLs ermöglichen (mittels Präfix)" name="whitelist_enable"/>
+ <text name="home_url_fails_some_items_in_whitelist">
+ Einträge, die auf ungültige Home-URLs hinweisen, sind markiert:
+ </text>
+ <button label="Hinzufügen" name="whitelist_add"/>
+ <button label="Löschen" name="whitelist_del"/>
+ <text name="home_url_fails_whitelist">
+ Warnung: Die Home-URL, die in der Registerkarte &quot;Allgemein&quot; angegeben wurde, entspricht nicht den Einträgen auf der Whitelist. Sie wurde deaktiviert, bis ein gültiger Eintrag angegeben wird.
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_my_profile.xml b/indra/newview/skins/default/xui/de/panel_my_profile.xml
new file mode 100644
index 0000000000..8357e4318d
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_my_profile.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Profil" name="panel_profile">
+ <string name="CaptionTextAcctInfo">
+ [ACCTTYPE]
+[PAYMENTINFO] [AGEVERIFICATION]
+ </string>
+ <string name="no_partner_text" value="Keiner"/>
+ <string name="RegisterDateFormat">
+ [REG_DATE] ([AGE])
+ </string>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <panel name="second_life_image_panel">
+ <icon label="" name="2nd_life_edit_icon" tool_tip="Klicken Sie unten auf die Schaltfläche Profil bearbeiten, um das Bild zu ändern."/>
+ <text name="title_sl_descr_text" value="[SECOND_LIFE]:"/>
+ <expandable_text name="sl_description_edit">
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ <panel name="first_life_image_panel">
+ <icon label="" name="real_world_edit_icon" tool_tip="Klicken Sie unten auf die Schaltfläche Profil bearbeiten, um das Bild zu ändern."/>
+ <text name="title_rw_descr_text" value="Echtes Leben:"/>
+ <expandable_text name="fl_description_edit">
+ Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ <text name="me_homepage_text">
+ Webseite:
+ </text>
+ <text name="title_member_text" value="Mitglied seit:"/>
+ <text name="register_date" value="05/31/1976"/>
+ <text name="title_acc_status_text" value="Kontostatus:"/>
+ <text name="acc_status_text" value="Einwohner. Keine Zahlungsinfo archiviert."/>
+ <text name="title_partner_text" value="Partner:"/>
+ <panel name="partner_data_panel">
+ <text name="partner_text" value="[FIRST] [LAST]"/>
+ </panel>
+ <text name="title_groups_text" value="Gruppen:"/>
+ <expandable_text name="sl_groups">
+ Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ </scroll_container>
+ <panel name="profile_buttons_panel">
+ <button label="Freund hinzufügen" name="add_friend"/>
+ <button label="IM" name="im"/>
+ <button label="Anrufen" name="call"/>
+ <button label="Karte" name="show_on_map_btn"/>
+ <button label="Teleportieren" name="teleport"/>
+ </panel>
+ <panel name="profile_me_buttons_panel">
+ <button label="Profil bearbeiten" name="edit_profile_btn"/>
+ <button label="Aussehen bearbeiten" name="edit_appearance_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_navigation_bar.xml b/indra/newview/skins/default/xui/de/panel_navigation_bar.xml
new file mode 100644
index 0000000000..5bf78be3d3
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_navigation_bar.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="navigation_bar">
+ <panel name="navigation_panel">
+ <button name="back_btn" tool_tip="Zurück zum vorherigen Standort gehen"/>
+ <button name="forward_btn" tool_tip="Um einen Standort weiter gehen"/>
+ <button name="home_btn" tool_tip="Zu meinem Heimatort teleportieren"/>
+ <location_input label="Standort" name="location_combo"/>
+ <search_combo_box label="Suche" name="search_combo_box" tool_tip="Suche">
+ <combo_editor label="[SECOND_LIFE] durchsuchen" name="search_combo_editor"/>
+ </search_combo_box>
+ </panel>
+ <favorites_bar name="favorite">
+ <chevron_button name="&gt;&gt;" tool_tip="Zeige weitere meiner Favoriten an"/>
+ </favorites_bar>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_nearby_chat.xml b/indra/newview/skins/default/xui/de/panel_nearby_chat.xml
new file mode 100644
index 0000000000..699bddc6eb
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_nearby_chat.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- All our XML is utf-8 encoded. -->
+<panel name="nearby_chat">
+ <panel name="chat_caption">
+ <text name="sender_name">
+ CHAT IN DER NÄHE
+ </text>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/de/panel_nearby_chat_bar.xml
new file mode 100644
index 0000000000..5e6e460c65
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_nearby_chat_bar.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="chat_bar">
+ <string name="min_width">
+ 192
+ </string>
+ <string name="max_width">
+ 320
+ </string>
+ <line_editor label="Zum Chatten hier klicken." name="chat_box" tool_tip="Eingabe drücken, um zu sprechen, Strg-Eingabe drücken, um zu Rufen."/>
+ <button name="show_nearby_chat" tool_tip="Protokoll des Chats in der Nähe anzeigen/ausblenden"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_notes.xml b/indra/newview/skins/default/xui/de/panel_notes.xml
new file mode 100644
index 0000000000..994c02935c
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_notes.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Notizen &amp; Privatsphäre" name="panel_notes">
+ <layout_stack name="layout">
+ <panel name="notes_stack">
+ <scroll_container name="profile_scroll">
+ <panel name="profile_scroll_panel">
+ <text name="status_message" value="Meine Notizen:"/>
+ <text name="status_message2" value="Diese Person kann:"/>
+ <check_box label="meinen Online-Status sehen." name="status_check"/>
+ <check_box label="mich auf der Karte sehen." name="map_check"/>
+ <check_box label="meine Objekte bearbeiten, löschen oder nehmen." name="objects_check"/>
+ </panel>
+ </scroll_container>
+ </panel>
+ <panel name="notes_buttons_panel">
+ <button label="Hinzufügen" name="add_friend"/>
+ <button label="IM" name="im"/>
+ <button label="Anrufen" name="call"/>
+ <button label="Karte" name="show_on_map_btn"/>
+ <button label="Teleportieren" name="teleport"/>
+ </panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/de/panel_outfits_inventory.xml
new file mode 100644
index 0000000000..da871cad47
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_outfits_inventory.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="Outfits">
+ <accordion name="outfits_accordion">
+ <accordion_tab name="tab_outfits" title="Outfit-Leiste"/>
+ <accordion_tab name="tab_cof" title="Aktuelles Outfit"/>
+ </accordion>
+ <button label="&gt;" name="selector" tool_tip="Outfit-Eigenschaften anzeigen"/>
+ <panel name="bottom_panel">
+ <button name="options_gear_btn" tool_tip="Zusätzliche Optionen anzeigen"/>
+ <button name="add_btn" tool_tip="Neues Objekt hinzufügen"/>
+ <dnd_button name="trash_btn" tool_tip="Auswahl löschen"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_outfits_inventory_gear_default.xml b/indra/newview/skins/default/xui/de/panel_outfits_inventory_gear_default.xml
new file mode 100644
index 0000000000..ec4d109acd
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_outfits_inventory_gear_default.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_gear_default">
+ <menu_item_call label="Neues Outfit" name="new"/>
+ <menu_item_call label="Outfit anziehen" name="wear"/>
+ <menu_item_call label="Outfit löschen" name="delete"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/de/panel_people.xml b/indra/newview/skins/default/xui/de/panel_people.xml
new file mode 100644
index 0000000000..3e99272833
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_people.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- Side tray panel -->
+<panel label="Leute" name="people_panel">
+ <string name="no_people" value="Keine Leute"/>
+ <string name="no_one_near" value="Keiner in der Nähe"/>
+ <string name="no_friends_online" value="Keine Freunde online"/>
+ <string name="no_friends" value="Keine Freunde"/>
+ <string name="no_groups" value="Keine Gruppen"/>
+ <string name="people_filter_label" value="Nach Leuten filtern"/>
+ <string name="groups_filter_label" value="Nach Gruppen filtern"/>
+ <filter_editor label="Filter" name="filter_input"/>
+ <tab_container name="tabs">
+ <panel label="IN DER NÄHE" name="nearby_panel">
+ <panel label="bottom_panel" name="bottom_panel">
+ <button name="nearby_view_sort_btn" tool_tip="Optionen"/>
+ <button name="add_friend_btn" tool_tip="Ausgewählten Einwohner zur Freundeliste hinzufügen"/>
+ </panel>
+ </panel>
+ <panel label="FREUNDE" name="friends_panel">
+ <accordion name="friends_accordion">
+ <accordion_tab name="tab_online" title="Online"/>
+ <accordion_tab name="tab_all" title="Alle"/>
+ </accordion>
+ <panel label="bottom_panel" name="bottom_panel">
+ <button name="friends_viewsort_btn" tool_tip="Optionen"/>
+ <button name="add_btn" tool_tip="Bieten Sie einem Einwohner die Freundschaft an"/>
+ <button name="del_btn" tool_tip="Ausgewählte Person von Ihrer Freundesliste entfernen"/>
+ </panel>
+ </panel>
+ <panel label="GRUPPEN" name="groups_panel">
+ <panel label="bottom_panel" name="bottom_panel">
+ <button name="groups_viewsort_btn" tool_tip="Optionen"/>
+ <button name="plus_btn" tool_tip="Gruppe beitreten/Neue Gruppe erstellen"/>
+ <button name="activate_btn" tool_tip="Ausgewählte Gruppe aktivieren"/>
+ </panel>
+ </panel>
+ <panel label="AKTUELL" name="recent_panel">
+ <panel label="bottom_panel" name="bottom_panel">
+ <button name="recent_viewsort_btn" tool_tip="Optionen"/>
+ <button name="add_friend_btn" tool_tip="Ausgewählten Einwohner zur Freundeliste hinzufügen"/>
+ </panel>
+ </panel>
+ </tab_container>
+ <panel name="button_bar">
+ <button label="Profil" name="view_profile_btn" tool_tip="Bilder, Gruppen und andere Einwohner-Informationen anzeigen"/>
+ <button label="IM" name="im_btn" tool_tip="Instant Messenger öffnen"/>
+ <button label="Anrufen" name="call_btn" tool_tip="Diesen Einwohner anrufen"/>
+ <button label="Teilen" name="share_btn"/>
+ <button label="Teleportieren" name="teleport_btn" tool_tip="Teleport anbieten"/>
+ <button label="Gruppenprofil" name="group_info_btn" tool_tip="Gruppeninformationen anzeigen"/>
+ <button label="Gruppen-Chat" name="chat_btn" tool_tip="Chat öffnen"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_pick_info.xml b/indra/newview/skins/default/xui/de/panel_pick_info.xml
new file mode 100644
index 0000000000..d8939a8ed1
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_pick_info.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_pick_info">
+ <text name="title" value="Auswahl-Info"/>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <text name="pick_name" value="[name]"/>
+ <text name="pick_location" value="[wird geladen...]"/>
+ <text name="pick_desc" value="[description]"/>
+ </panel>
+ </scroll_container>
+ <panel name="buttons">
+ <button label="Teleportieren" name="teleport_btn"/>
+ <button label="Karte" name="show_on_map_btn"/>
+ <button label="Bearbeiten" name="edit_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_picks.xml b/indra/newview/skins/default/xui/de/panel_picks.xml
new file mode 100644
index 0000000000..a1588e5930
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_picks.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Auswahl" name="panel_picks">
+ <string name="no_picks" value="Keine Auswahl"/>
+ <string name="no_classifieds" value="Keine Anzeigen"/>
+ <text name="empty_picks_panel_text">
+ Es wurde keine Auswahl getroffen/keine Anzeigen ausgewählt
+ </text>
+ <accordion name="accordion">
+ <accordion_tab name="tab_picks" title="Auswahl"/>
+ <accordion_tab name="tab_classifieds" title="Anzeigen"/>
+ </accordion>
+ <panel label="bottom_panel" name="edit_panel">
+ <button name="new_btn" tool_tip="Aktuellen Standort zur Auswahl hinzufügen"/>
+ </panel>
+ <panel name="buttons_cucks">
+ <button label="Info" name="info_btn"/>
+ <button label="Teleportieren" name="teleport_btn"/>
+ <button label="Karte" name="show_on_map_btn"/>
+ <button label="â–¼" name="overflow_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_place_profile.xml b/indra/newview/skins/default/xui/de/panel_place_profile.xml
new file mode 100644
index 0000000000..e012acac8d
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_place_profile.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="place_profile">
+ <string name="on" value="Ein"/>
+ <string name="off" value="Aus"/>
+ <string name="anyone" value="Jeder"/>
+ <string name="available" value="verfügbar"/>
+ <string name="allocated" value="vergeben"/>
+ <string name="title_place" value="Ortsprofil"/>
+ <string name="title_teleport_history" value="Teleport-Verlauf"/>
+ <string name="not_available" value="k.A."/>
+ <string name="unknown" value="(unbekannt)"/>
+ <string name="public" value="(öffentlich)"/>
+ <string name="none_text" value="(keiner)"/>
+ <string name="sale_pending_text" value="(Wird verkauft)"/>
+ <string name="group_owned_text" value="(In Gruppenbesitz)"/>
+ <string name="price_text" value="L$"/>
+ <string name="area_text" value="m²"/>
+ <string name="all_residents_text" value="Alle Einwohner"/>
+ <string name="group_text" value="Gruppe"/>
+ <string name="can_resell">
+ Gekauftes Land in dieser Region kann wiederverkauft werden.
+ </string>
+ <string name="can_not_resell">
+ Gekauftes Land in dieser Region kann nicht wiederverkauft werden.
+ </string>
+ <string name="can_change">
+ Gekauftes Land in dieser Region kann zusammengelegt und geteilt werden.
+ </string>
+ <string name="can_not_change">
+ Gekauftes Land in dieser Region kann nicht zusammengelegt und geteilt werden.
+ </string>
+ <string name="server_update_text">
+ Ohne Serverupdate sind keine Ortsinformationen verfügbar.
+ </string>
+ <string name="server_error_text">
+ Zur Zeit gibt es keine Informationen zu diesem Standort. Bitte versuchen Sie es später.
+ </string>
+ <string name="server_forbidden_text">
+ Die Informationen über diesen Standort sind zugriffsbeschränkt. Bitte wenden Sie sich bezüglich Ihrer Berechtigungen an den Eigentümer der Parzelle.
+ </string>
+ <string name="acquired_date">
+ [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+ </string>
+ <string name="icon_PG" value="parcel_drk_PG"/>
+ <string name="icon_M" value="parcel_drk_M"/>
+ <string name="icon_R" value="parcel_drk_R"/>
+ <string name="icon_Voice" value="parcel_drk_Voice"/>
+ <string name="icon_VoiceNo" value="parcel_drk_VoiceNo"/>
+ <string name="icon_Fly" value="parcel_drk_Fly"/>
+ <string name="icon_FlyNo" value="parcel_drk_FlyNo"/>
+ <string name="icon_Push" value="parcel_drk_Push"/>
+ <string name="icon_PushNo" value="parcel_drk_PushNo"/>
+ <string name="icon_Build" value="parcel_drk_Build"/>
+ <string name="icon_BuildNo" value="parcel_drk_BuildNo"/>
+ <string name="icon_Scripts" value="parcel_drk_Scripts"/>
+ <string name="icon_ScriptsNo" value="parcel_drk_ScriptsNo"/>
+ <string name="icon_Damage" value="parcel_drk_Damage"/>
+ <string name="icon_DamageNo" value="parcel_drk_DamageNo"/>
+ <text name="title" value="Ortsprofil"/>
+ <scroll_container name="place_scroll">
+ <panel name="scrolling_panel">
+ <text name="region_title" value="SampleRegion"/>
+ <text name="parcel_title" value="SampleParcel, Name Long (145, 228, 26)"/>
+ <expandable_text name="description" value="Du waltz die spritz"/>
+ <text name="owner_label" value="Eigentümer:"/>
+ <text name="owner_value" value="Alex Superduperlongenamenton"/>
+ <text name="maturity_value" value="unbekannt"/>
+ <accordion name="advanced_info_accordion">
+ <accordion_tab name="parcel_characteristics_tab" title="Parzelle">
+ <panel>
+ <text name="rating_label" value="Einstufung:"/>
+ <text name="rating_value" value="unbekannt"/>
+ <text name="voice_label" value="Voice:"/>
+ <text name="voice_value" value="Ein"/>
+ <text name="fly_label" value="Fliegen:"/>
+ <text name="fly_value" value="Ein"/>
+ <text name="push_label" value="Stoßen:"/>
+ <text name="push_value" value="Aus"/>
+ <text name="build_label" value="Bauen:"/>
+ <text name="build_value" value="Ein"/>
+ <text name="scripts_label" value="Skripts:"/>
+ <text name="scripts_value" value="Ein"/>
+ <text name="damage_label" value="Schaden:"/>
+ <text name="damage_value" value="Aus"/>
+ <button label="Ãœber Land" name="about_land_btn"/>
+ </panel>
+ </accordion_tab>
+ <accordion_tab name="region_information_tab" title="Region">
+ <panel>
+ <text name="region_name_label" value="Region:"/>
+ <text name="region_name" value="Mooseland"/>
+ <text name="region_type_label" value="Typ:"/>
+ <text name="region_type" value="Moose"/>
+ <text name="region_rating_label" value="Einstufung:"/>
+ <text name="region_rating" value="Adult"/>
+ <text name="region_owner_label" value="Eigentümer:"/>
+ <text name="region_owner" value="moose Van Moose"/>
+ <text name="region_group_label" value="Gruppe:"/>
+ <text name="region_group">
+ The Mighty Moose of mooseville soundvillemoose
+ </text>
+ <button label="Region/Grundstück" name="region_info_btn"/>
+ </panel>
+ </accordion_tab>
+ <accordion_tab name="estate_information_tab" title="Grundstück">
+ <panel>
+ <text name="estate_name_label" value="Grundstück:"/>
+ <text name="estate_rating_label" value="Einstufung:"/>
+ <text name="estate_owner_label" value="Eigentümer:"/>
+ <text name="covenant_label" value="Vertrag:"/>
+ </panel>
+ </accordion_tab>
+ <accordion_tab name="sales_tab" title="Zum Verkauf">
+ <panel>
+ <text name="sales_price_label" value="Preis:"/>
+ <text name="area_label" value="Gebiet:"/>
+ <text name="traffic_label" value="Traffic:"/>
+ <text name="primitives_label" value="Primitive:"/>
+ <text name="parcel_scripts_label" value="Skripts:"/>
+ <text name="terraform_limits_label" value="Terraform-Begrenzungen:"/>
+ <text name="subdivide_label" value="Teilen/Zusammenlegen:"/>
+ <text name="resale_label" value="Wiederverkaufen:"/>
+ <text name="sale_to_label" value="Zum Verkauf an:"/>
+ </panel>
+ </accordion_tab>
+ </accordion>
+ </panel>
+ </scroll_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_places.xml b/indra/newview/skins/default/xui/de/panel_places.xml
new file mode 100644
index 0000000000..a2f98bf199
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_places.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Orte" name="places panel">
+ <string name="landmarks_tab_title" value="MEINE LANDMARKEN"/>
+ <string name="teleport_history_tab_title" value="TELEPORT-VERLAUF"/>
+ <filter_editor label="Filter" name="Filter"/>
+ <panel name="button_panel">
+ <button label="Teleportieren" name="teleport_btn"/>
+ <button label="Karte" name="map_btn"/>
+ <button label="Bearbeiten" name="edit_btn"/>
+ <button label="Schließen" name="close_btn"/>
+ <button label="Abbrechen" name="cancel_btn"/>
+ <button label="Speichern" name="save_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/de/panel_preferences_advanced.xml
new file mode 100644
index 0000000000..14d4e01586
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_preferences_advanced.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<panel name="advanced">
+ <panel.string name="resolution_format">
+ [RES_X] x [RES_Y]
+ </panel.string>
+ <panel.string name="aspect_ratio_text">
+ [NUM]:[DEN]
+ </panel.string>
+ <check_box label="Blasen-Chat" name="bubble_text_chat"/>
+ <color_swatch name="background" tool_tip="Farbe für Blasen-Chat auswählen"/>
+ <slider label="Deckkraft" name="bubble_chat_opacity"/>
+ <text name="AspectRatioLabel1" tool_tip="Breite/Höhe">
+ Seitenverhältnis
+ </text>
+ <combo_box name="aspect_ratio" tool_tip="Breite/Höhe">
+ <combo_box.item label="4:3 (Standard-CRT)" name="item1"/>
+ <combo_box.item label="5:4 (1280x1024 LCD)" name="item2"/>
+ <combo_box.item label="8:5 (Widescreen)" name="item3"/>
+ <combo_box.item label="16:9 (Widescreen)" name="item4"/>
+ </combo_box>
+ <check_box label="Automatisch erkennen" name="aspect_auto_detect"/>
+ <text name="heading1">
+ Kamera:
+ </text>
+ <slider label="Sichtwinkel" name="camera_fov"/>
+ <slider label="Abstand" name="camera_offset_scale"/>
+ <text name="heading2">
+ Automatische Positionierung:
+ </text>
+ <check_box label="Bauen/Bearbeiten" name="edit_camera_movement" tool_tip="Automatische Kamerapositionierung bei Wechsel in und aus dem Bearbeitungsmodus verwenden"/>
+ <check_box label="Aussehen" name="appearance_camera_movement" tool_tip="Automatische Kamerapositionierung im Bearbeitenmodus verwenden"/>
+ <text name="heading3">
+ Avatare:
+ </text>
+ <check_box label="Mich im Mouselook anzeigen" name="first_person_avatar_visible"/>
+ <check_box label="Mit Pfeiltasten bewegen" name="arrow_keys_move_avatar_check"/>
+ <check_box label="2-mal-drücken-halten, um zu rennen" name="tap_tap_hold_to_run"/>
+ <check_box label="Avatarlippen beim Sprechen bewegen" name="enable_lip_sync"/>
+ <check_box label="Skript-Fehler anzeigen" name="show_script_errors"/>
+ <radio_group name="show_location">
+ <radio_item label="In Chat" name="0"/>
+ <radio_item label="In einem Fenster" name="1"/>
+ </radio_group>
+ <check_box label="Umschaltmodus für Mikrofon, wenn die Auslöste-Taste zum Sprechen gedrückt wird:" name="push_to_talk_toggle_check" tool_tip="Wenn der Umschaltmodus aktiviert ist, drücken Sie die Auslöse-Taste EINMAL, um Ihr Mikrofon an oder aus zu stellen. Wenn der Umschaltmodus nicht motiviert ist, ist das Mikro nur dann eingeschaltet, wenn Sie die Auslösetaste gedrückt halten."/>
+ <line_editor label="Auslöser für Zum-Sprechen-drücken:" name="modifier_combo"/>
+ <button label="Taste festlegen" name="set_voice_hotkey_button"/>
+ <button label="Mittlere Maustaste" name="set_voice_middlemouse_button"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_alerts.xml b/indra/newview/skins/default/xui/de/panel_preferences_alerts.xml
new file mode 100644
index 0000000000..3e00c39289
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_preferences_alerts.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Popups" name="popups" title="Popups">
+ <text name="tell_me_label">
+ Anzeigen:
+ </text>
+ <check_box label="Wenn ich Geld ausgebe oder L$ erhalte" name="notify_money_change_checkbox"/>
+ <check_box label="Wenn meinen Freund sich an- oder abmelden" name="friends_online_notify_checkbox"/>
+ <text name="show_label">
+ Diese Warnhinweise immer anzeigen:
+ </text>
+ <text name="dont_show_label">
+ Diese Warnhinweise immer anzeigen:
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_chat.xml b/indra/newview/skins/default/xui/de/panel_preferences_chat.xml
index feeb528721..d51675e150 100644
--- a/indra/newview/skins/default/xui/de/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/de/panel_preferences_chat.xml
@@ -1,59 +1,43 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Text-Chat" name="chat">
- <text length="1" name="text_box" type="string">
- Chat-Schriftgröße:
- </text>
<radio_group name="chat_font_size">
- <radio_item length="1" name="radio" type="string">
- Klein
- </radio_item>
- <radio_item length="1" name="radio2" type="string">
- Mittel
- </radio_item>
- <radio_item length="1" name="radio3" type="string">
- Groß
- </radio_item>
+ <radio_item label="Klein" name="radio"/>
+ <radio_item label="Mittel" name="radio2"/>
+ <radio_item label="Groß" name="radio3"/>
</radio_group>
- <text length="1" name="text_box2" type="string">
- Chat-Farbe:
- </text>
<color_swatch label="Sie" name="user"/>
+ <text name="text_box1">
+ Ich
+ </text>
<color_swatch label="Andere" name="agent"/>
+ <text name="text_box2">
+ Andere
+ </text>
<color_swatch label="IM" name="im"/>
+ <text name="text_box3">
+ IM
+ </text>
<color_swatch label="System" name="system"/>
- <color_swatch label="Chat" name="users"/>
+ <text name="text_box4">
+ System
+ </text>
+ <color_swatch label="Skriptfehler" name="script_error"/>
+ <text name="text_box5">
+ Skriptfehler
+ </text>
<color_swatch label="Objekte" name="objects"/>
- <color_swatch label="Eigentümer" name="owner" width="58"/>
- <color_swatch label="Blase" left_delta="62" name="background"/>
+ <text name="text_box6">
+ Objekte
+ </text>
+ <color_swatch label="Eigentümer" name="owner"/>
+ <text name="text_box7">
+ Eigentümer
+ </text>
<color_swatch label="URLs" name="links"/>
- <text length="1" name="text_box3" type="string">
- Chat-Konsole:
- </text>
- <spinner label="Chat ausblenden nach" label_width="115" left="148" name="fade_chat_time" width="160"/>
- <text left="310" length="1" name="text_box4" type="string">
- (Sekunden)
- </text>
- <spinne left="370" name="max_chat_count"/>
- <text left="435" length="1" name="text_box5" type="string">
- (# Zeilen)
- </text>
- <slider label="Deckkraft" name="console_opacity"/>
- <text length="1" name="text_box6" type="string">
- Chat-Optionen:
- </text>
- <check_box label="Chat verwendet volle Bildbreite (Neustart erforderlich)" name="chat_full_width_check"/>
- <check_box label="Chatleiste nach Drücken der Eingabetaste schließen" name="close_chat_on_return_check"/>
- <check_box label="Pfeiltasten bewegen immer den Avatar beim Chatten" name="arrow_keys_move_avatar_check"/>
- <check_box label="Zeitstempel im lokalen Chat anzeigen" name="show_timestamps_check"/>
- <check_box label="Beim Chatten Tippanimation abspielen" name="play_typing_animation"/>
- <text length="1" name="text_box7" type="string">
- Blasen-Chat:
- </text>
- <check_box label="Chat-Blasen anzeigen" name="bubble_text_chat"/>
- <slider label="Deckkraft" name="bubble_chat_opacity"/>
- <text length="1" name="text_box8" type="string">
- Skriptfehler:
- </text>
- <check_box label="Skriptfehler und Warnungen als normalen Chat anzeigen" name="script_errors_as_chat"/>
- <color_swatch label="Fehler" name="script_error"/>
+ <text name="text_box9">
+ URLs
+ </text>
+ <check_box initial_value="true" label="Beim Chatten Tippanimation abspielen" name="play_typing_animation"/>
+ <check_box label="IMs per Email zuschicken, wenn ich offline bin" name="send_im_to_email"/>
+ <check_box label="Text-Chatverlauf aktivieren" name="plain_text_chat_history"/>
</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_general.xml b/indra/newview/skins/default/xui/de/panel_preferences_general.xml
index 40b4909e84..5bbd579ff6 100644
--- a/indra/newview/skins/default/xui/de/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/de/panel_preferences_general.xml
@@ -1,147 +1,68 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Allgemein" name="general_panel">
- <radio_group name="default_start_location">
- <radio_item name="MyHome" tool_tip="Als Standardeinstellung in Zuhauseposition anmelden.">
- Mein Heimatort
- </radio_item>
- <radio_item name="MyLastLocation" tool_tip="Als Standardeinstellung in letztem Standort anmelden.">
- Mein letzter Standort
- </radio_item>
- </radio_group>
- <check_box label="Startposition auf Anmeldebildschirm anzeigen" name="show_location_checkbox"/>
- <combo_box name="fade_out_combobox">
- <combo_item name="Never">
- Nie
- </combo_item>
- <combo_item name="Show Temporarily">
- Temporär anzeigen
- </combo_item>
- <combo_item name="Always">
- Immer
- </combo_item>
- </combo_box>
- <check_box label="Kleine Avatarnamen" name="small_avatar_names_checkbox"/>
- <check_box label="Meinen Namen auf meinem Bildschirm ausblenden" name="show_my_name_checkbox"/>
- <text name="group_titles_textbox">
- Gruppentitel:
- </text>
- <check_box label="Alle Gruppentitel ausblenden" name="show_all_title_checkbox"/>
- <check_box label="Meinen Gruppentitel ausblenden" name="show_my_title_checkbox"/>
- <color_swatch label="" name="effect_color_swatch" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen"/>
- <text name="UI Size:">
- UI-Größe:
+ <text name="language_textbox">
+ Sprache:
</text>
- <check_box label="Auflösungsunabhängigen Maßstab verwenden" name="ui_auto_scale"/>
- <spinner label="Timeout für Abwesenheit:" name="afk_timeout_spinner"/>
- <check_box label="L$ Eingänge und Ausgaben melden" name="notify_money_change_checkbox"/>
- <text name="maturity_desired_label" bottom="-312">
- Einstufung:
+ <combo_box name="language_combobox">
+ <combo_box.item label="Systemvorgabe" name="System Default Language"/>
+ <combo_box.item label="English (Englisch)" name="English"/>
+ <combo_box.item label="Danks (Dänisch) - Beta" name="Danish"/>
+ <combo_box.item label="Deutsch - Beta" name="Deutsch(German)"/>
+ <combo_box.item label="Español (Spanisch) - Beta" name="Spanish"/>
+ <combo_box.item label="Français (Französisch) - Beta" name="French"/>
+ <combo_box.item label="Italiano (Italienisch) - Beta" name="Italian"/>
+ <combo_box.item label="Nederlands (Niederländisch) - Beta" name="Dutch"/>
+ <combo_box.item label="Polski (Polnisch) - Beta" name="Polish"/>
+ <combo_box.item label="Português (Portugiesisch) - Beta" name="Portugese"/>
+ <combo_box.item label="日本語 (Japanisch) - Beta" name="(Japanese)"/>
+ <combo_box.item label="Testsprache" name="TestLanguage"/>
+ </combo_box>
+ <text name="language_textbox2">
+ (Erfordert Neustart)
</text>
- <text name="maturity_desired_prompt" bottom="-312">
- Ich möchte auf Inhalt mit folgender
-Alterseinstufung zugreifen:
+ <text name="maturity_desired_prompt">
+ Ich möchte auf Inhalt mit folgender Alterseinstufung zugreifen:
</text>
- <combo_box name="maturity_desired_combobox" bottom="-330" left="336">
- <combo_item name="Desired_Adult">
- PG, Mature und Adult
- </combo_item>
- <combo_item name="Desired_Mature">
- PG und Mature
- </combo_item>
- <combo_item name="Desired_PG">
- Nur PG
- </combo_item>
+ <text name="maturity_desired_textbox"/>
+ <combo_box name="maturity_desired_combobox">
+ <combo_box.item label="PG, Mature und Adult" name="Desired_Adult"/>
+ <combo_box.item label="PG und Mature" name="Desired_Mature"/>
+ <combo_box.item label="Allgemein" name="Desired_PG"/>
</combo_box>
- <text name="maturity_desired_textbox" bottom="-324" left="336">
- Nur PG
- </text>
<text name="start_location_textbox">
- Startposition:
+ Startstandort:
</text>
- <text name="show_names_textbox">
- Namen anzeigen:
+ <combo_box name="start_location_combo">
+ <combo_box.item label="Mein letzter Standort" name="MyLastLocation" tool_tip="Als Standardeinstellung in letztem Standort anmelden."/>
+ <combo_box.item label="Mein Heimatort" name="MyHome" tool_tip="Als Standardeinstellung in Zuhauseposition anmelden."/>
+ </combo_box>
+ <check_box initial_value="true" label="Beim Anmelden anzeigen" name="show_location_checkbox"/>
+ <text name="name_tags_textbox">
+ Avatarnamen:
</text>
+ <radio_group name="Name_Tag_Preference">
+ <radio_item label="Aus" name="radio"/>
+ <radio_item label="An" name="radio2"/>
+ <radio_item label="Vorübergehend anzeigen" name="radio3"/>
+ </radio_group>
+ <check_box label="Meinen Namen anzeigen" name="show_my_name_checkbox1"/>
+ <check_box initial_value="true" label="Kleine Avatarnamen" name="small_avatar_names_checkbox"/>
+ <check_box label="Gruppentitel anzeigen" name="show_all_title_checkbox1"/>
<text name="effects_color_textbox">
- Farbe für meine Effekte:
+ Meine Effekte:
+ </text>
+ <color_swatch label="" name="effect_color_swatch" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen"/>
+ <text name="title_afk_text">
+ Zeit bis zur Abwesenheit:
</text>
+ <spinner label="" name="afk_timeout_spinner"/>
<text name="seconds_textbox">
Sekunden
</text>
- <text name="crash_report_textbox">
- Crash-Berichte:
- </text>
- <text name="language_textbox">
- Sprache:
- </text>
- <text left_delta="313" name="language_textbox2">
- (Erfordert Neustart)
+ <text name="text_box3">
+ Antwort, wenn im „Beschäftigt“-Modus:
</text>
- <string name="region_name_prompt">
- &lt;Region eingeben&gt;
- </string>
- <combo_box name="crash_behavior_combobox" width="166">
- <combo_item name="Askbeforesending">
- Vor dem Senden fragen
- </combo_item>
- <combo_item name="Alwayssend">
- Immer senden
- </combo_item>
- <combo_item name="Neversend">
- Nie senden
- </combo_item>
- </combo_box>
- <combo_box name="language_combobox" width="166">
- <combo_item name="System Default Language">
- Betriebssystem-Einstellung
- </combo_item>
- <combo_item name="English">
- English (Englisch)
- </combo_item>
- <combo_item name="Danish">
- Danks (Dänisch) - Beta
- </combo_item>
- <combo_item name="Deutsch(German)">
- Deutsch - Beta
- </combo_item>
- <combo_item name="Spanish">
- Español (Spanisch) - Beta
- </combo_item>
- <combo_item name="French">
- Français (Französisch) - Beta
- </combo_item>
- <combo_item name="Italian">
- Italiano (Italienisch) - Beta
- </combo_item>
- <combo_item name="Hungarian">
- Magyar (Ungarisch) - Beta
- </combo_item>
- <combo_item name="Dutch">
- Nederlands (Niederländisch) - Beta
- </combo_item>
- <combo_item name="Polish">
- Polski (Polnisch) - Beta
- </combo_item>
- <combo_item name="Portugese">
- Português (Portugiesisch) - Beta
- </combo_item>
- <combo_item name="Russian">
- РуÑÑкий (Russian) - Beta
- </combo_item>
- <combo_item name="Turkish">
- Türkçe (Türkisch) - Beta
- </combo_item>
- <combo_item name="Ukrainian">
- УкраїнÑька (Ukrainisch) - Beta
- </combo_item>
- <combo_item name="Chinese">
- 中文 (简体) (Chinesisch) - Beta
- </combo_item>
- <combo_item name="(Japanese)">
- 日本語 (Japanisch) - Beta
- </combo_item>
- <combo_item name="(Korean)">
- 한국어 (Koreanisch) - Beta
- </combo_item>
- </combo_box>
- <check_box label="Objekten Sprache mitteilen" name="language_is_public" tool_tip="In-Welt-Objekten wird Ihre bevorzugte Spracheinstellung mitgeteilt."/>
+ <text_editor name="busy_response">
+ log_in_to_change
+ </text_editor>
</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml
index bc40ec0da1..e7bb768925 100644
--- a/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml
@@ -1,85 +1,28 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Grafik" name="Display panel">
- <text type="string" length="1" name="text">
- Anzeigeauflösung:
- </text>
- <button label=" ?" name="GraphicsPreferencesHelpButton" />
- <check_box label="Second Life in einem Fenster ausführen" name="windowed mode" />
- <text_editor name="voice_chat_description">
- Wenn deaktiviert Anzeige bei Anmeldung in Vollbild.
- </text_editor>
- <text type="string" length="1" name="Fullscreen Aspect Ratio:">
- Vollbild-Aspektverhältnis:
- </text>
- <text type="string" length="1" name="(width / height)">
- (Breite/Höhe)
- </text>
- <text_editor name="FullScreenInfo" width="480">
- Wenn deaktiviert, schaltet die Anzeige bei Anmeldung auf Vollbild um.
- </text_editor>
<text name="WindowSizeLabel">
Fenstergröße:
</text>
+ <check_box label="Vollbildmodus verwenden" name="windowed mode"/>
<combo_box left="115" name="windowsize combo">
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="720x480">
- 720x480 (NTSC)
- </combo_item>
- <combo_item name="768x576">
- 768x576 (PAL)
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
- </combo_box>
- <text name="DisplayResLabel" width="100">
- Anzeigeauflösung:
- </text>
- <combo_box left="115" name="fullscreen combo" />
- <text name="AspectRatioLabel1" tool_tip="Breite/Höhe" width="100">
- Aspektverhältnis:
- </text>
- <combo_box left="115" name="aspect_ratio" tool_tip="Breite/Höhe">
- <combo_item type="string" length="1" name="4:3(StandardCRT)">
- 4:3 (Standard-CRT)
- </combo_item>
- <combo_item type="string" length="1" name="5:4(1280x1024LCD)">
- 5:4 (1280x1024 LCD)
- </combo_item>
- <combo_item name="8:5(Widescreen)">
- 8:5 (Widescreen)
- </combo_item>
- <combo_item type="string" length="1" name="16:9(Widescreen)">
- 16:9 (Widescreen)
- </combo_item>
+ <combo_box.item label="640x480" name="640x480"/>
+ <combo_box.item label="800x600" name="800x600"/>
+ <combo_box.item label="720x480 (NTSC)" name="720x480"/>
+ <combo_box.item label="768x576 (PAL)" name="768x576"/>
+ <combo_box.item label="1024x768" name="1024x768"/>
</combo_box>
- <check_box label="Verhältnis automatisch erkennen" left="275" name="aspect_auto_detect" />
- <text type="string" length="1" name="UI Size:">
+ <text name="UI Size:">
UI-Größe:
</text>
- <text type="string" length="1" name="(meters, lower is faster)">
- (Meter, niedriger ist schneller)
- </text>
- <text type="string" length="1" name="text2">
- Anzeigeoptionen:
- </text>
- <check_box label="Auflösungsunabhängigen Maßstab verwenden" name="ui_auto_scale" />
- <spinner label="Sichtweite:" name="draw_distance" />
- <check_box label="Avatar in Mouselook anzeigen" name="avfp" />
- <text name="HigherText">
- Qualität und
- </text>
- <text name="QualityText">
- Performance:
+ <text name="QualitySpeed">
+ Qualität und Geschwindigkeit:
</text>
<text name="FasterText">
Schneller
</text>
+ <text name="BetterText">
+ Besser
+ </text>
<text name="ShadersPrefText">
Niedrig
</text>
@@ -92,112 +35,82 @@
<text name="ShadersPrefText4">
Ultra
</text>
- <text name="HigherText2">
- Höhere
- </text>
- <text name="QualityText2">
- Qualität
- </text>
- <check_box label="Benutzerdefiniert" name="CustomSettings" />
- <text name="ShadersText">
- Shader:
- </text>
- <check_box label="Bumpmapping und Glanz" name="BumpShiny" />
- <check_box label="Einfache Shader" name="BasicShaders"
- tool_tip="Deaktivieren Sie diese Option, wenn der Grafikkartentreiber Abstürze verursacht." />
- <check_box label="Atmosphären-Shader" name="WindLightUseAtmosShaders" />
- <check_box label="Wasserreflexionen" name="Reflections" />
- <text name="ReflectionDetailText">
- Spiegelung:
- </text>
- <radio_group name="ReflectionDetailRadio">
- <radio_item name="0">
- Terrain und Bäume
- </radio_item>
- <radio_item name="1">
- Alle statischen Objekte
- </radio_item>
- <radio_item name="2">
- Alle Avatare und Objekte
- </radio_item>
- <radio_item name="3">
- Alles
- </radio_item>
- </radio_group>
- <text name="AvatarRenderingText">
- Avatar-Darstellung:
- </text>
- <check_box label="Ersatzavatare" name="AvatarImpostors" />
- <check_box label="Hardware-Hautberechnung" name="AvatarVertexProgram" />
- <check_box label="Avatar-Kleidung" name="AvatarCloth" />
- <text name="DrawDistanceMeterText1">
- m
- </text>
- <text name="DrawDistanceMeterText2">
- m
- </text>
- <slider label="Sichtweite:" name="DrawDistance" />
- <slider label="Max. Partikelzahl:" name="MaxParticleCount" />
- <slider label="Post-Processing-Qualität:" name="RenderPostProcess" />
- <text name="MeshDetailText">
- Gitterdetails:
- </text>
- <slider label=" Objekte:" name="ObjectMeshDetail" />
- <slider label=" Flexiprimitiva:" name="FlexibleMeshDetail" />
- <slider label=" Bäume:" name="TreeMeshDetail" />
- <slider label=" Avatare:" name="AvatarMeshDetail" />
- <slider label=" Terrain:" name="TerrainMeshDetail" />
- <slider label=" Himmel:" name="SkyMeshDetail" />
- <text name="PostProcessText">
- Niedrig
- </text>
- <text name="ObjectMeshDetailText">
- Niedrig
- </text>
- <text name="FlexibleMeshDetailText">
- Niedrig
- </text>
- <text name="TreeMeshDetailText">
- Niedrig
- </text>
- <text name="AvatarMeshDetailText">
- Niedrig
- </text>
- <text name="TerrainMeshDetailText">
- Niedrig
- </text>
- <text name="SkyMeshDetailText">
- Niedrig
- </text>
- <text name="LightingDetailText">
- Beleuchtungsdetails:
- </text>
- <radio_group name="LightingDetailRadio">
- <radio_item name="SunMoon">
- Nur Sonne und Mond
- </radio_item>
- <radio_item name="LocalLights">
- Lokale Lichtquellen
- </radio_item>
- </radio_group>
- <text name="TerrainDetailText">
- Terraindetails:
- </text>
- <radio_group name="TerrainDetailRadio">
- <radio_item name="0">
+ <panel label="CustomGraphics" name="CustomGraphics Panel">
+ <text name="ShadersText">
+ Shader:
+ </text>
+ <check_box initial_value="true" label="Bumpmapping und Glanz" name="BumpShiny"/>
+ <check_box initial_value="true" label="Einfache Shader" name="BasicShaders" tool_tip="Deaktivieren Sie diese Option, wenn der Grafikkartentreiber Abstürze verursacht"/>
+ <check_box initial_value="true" label="Atmosphären-Shader" name="WindLightUseAtmosShaders"/>
+ <check_box initial_value="true" label="Wasserreflexionen" name="Reflections"/>
+ <text name="ReflectionDetailText">
+ Spiegelung:
+ </text>
+ <radio_group name="ReflectionDetailRadio">
+ <radio_item label="Terrain und Bäume" name="0"/>
+ <radio_item label="Alle statischen Objekte" name="1"/>
+ <radio_item label="Alle Avatare und Objekte" name="2"/>
+ <radio_item label="Alles" name="3"/>
+ </radio_group>
+ <text name="AvatarRenderingText">
+ Avatar-Darstellung:
+ </text>
+ <check_box initial_value="true" label="Scheinavatare" name="AvatarImpostors"/>
+ <check_box initial_value="true" label="Hardware-Hautberechnung" name="AvatarVertexProgram"/>
+ <check_box initial_value="true" label="Avatar-Kleidung" name="AvatarCloth"/>
+ <slider label="Sichtweite:" name="DrawDistance"/>
+ <text name="DrawDistanceMeterText2">
+ m
+ </text>
+ <slider label="Max. Partikelzahl:" name="MaxParticleCount"/>
+ <slider label="Post-Processing-Qualität:" name="RenderPostProcess"/>
+ <text name="MeshDetailText">
+ Gitterdetails:
+ </text>
+ <slider label=" Objekte:" name="ObjectMeshDetail"/>
+ <slider label=" Flexiprimitiva:" name="FlexibleMeshDetail"/>
+ <slider label=" Bäume:" name="TreeMeshDetail"/>
+ <slider label=" Avatare:" name="AvatarMeshDetail"/>
+ <slider label=" Terrain:" name="TerrainMeshDetail"/>
+ <slider label=" Himmel:" name="SkyMeshDetail"/>
+ <text name="PostProcessText">
Niedrig
- </radio_item>
- <radio_item name="2">
- Hoch
- </radio_item>
- </radio_group>
- <button label="Empfohlene Einstellungen" name="Defaults" />
- <button label="Hardware-Optionen" label_selected="Hardware-Optionen"
- name="GraphicsHardwareButton" />
- <text name="resolution_format">
- [RES_X] x [RES_Y]
- </text>
- <text name="aspect_ratio_text">
- [NUM]:[DEN]
- </text>
+ </text>
+ <text name="ObjectMeshDetailText">
+ Niedrig
+ </text>
+ <text name="FlexibleMeshDetailText">
+ Niedrig
+ </text>
+ <text name="TreeMeshDetailText">
+ Niedrig
+ </text>
+ <text name="AvatarMeshDetailText">
+ Niedrig
+ </text>
+ <text name="TerrainMeshDetailText">
+ Niedrig
+ </text>
+ <text name="SkyMeshDetailText">
+ Niedrig
+ </text>
+ <text name="LightingDetailText">
+ Beleuchtungsdetails:
+ </text>
+ <radio_group name="LightingDetailRadio">
+ <radio_item label="Nur Sonne und Mond" name="SunMoon"/>
+ <radio_item label="Lokale Lichtquellen" name="LocalLights"/>
+ </radio_group>
+ <text name="TerrainDetailText">
+ Terraindetails:
+ </text>
+ <radio_group name="TerrainDetailRadio">
+ <radio_item label="Niedrig" name="0"/>
+ <radio_item label="Hoch" name="2"/>
+ </radio_group>
+ </panel>
+ <button label="Ãœbernehmen" label_selected="Ãœbernehmen" name="Apply"/>
+ <button label="Zurücksetzen" name="Defaults"/>
+ <button label="Erweitert" name="Advanced"/>
+ <button label="Hardware" label_selected="Hardware" name="GraphicsHardwareButton"/>
</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/de/panel_preferences_privacy.xml
new file mode 100644
index 0000000000..fe0dca78d1
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_preferences_privacy.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Kommunikation" name="im">
+ <panel.string name="log_in_to_change">
+ Anmelden, um Änderungen vorzunehmen
+ </panel.string>
+ <button label="Verlauf leeren" name="clear_cache"/>
+ <text name="cache_size_label_l">
+ (Standorte, Bilder, Web, Suchverlauf)
+ </text>
+ <check_box label="Nur Freunde und Gruppen wissen, dass ich online bin" name="online_visibility"/>
+ <check_box label="Nur Freunde und Gruppen können mich anrufen oder mir eine IM schicken" name="voice_call_friends_only_check"/>
+ <check_box label="Mikrofon ausschalten, wenn Anrufe beendet werden" name="auto_disengage_mic_check"/>
+ <check_box label="Cookies annehmen" name="cookies_enabled"/>
+ <check_box label="Automatisches Abspielen von Medien erlauben" name="autoplay_enabled"/>
+ <check_box label="Medien auf Parzellen automatisch abspielen" name="parcel_autoplay_enabled"/>
+ <text name="Logs:">
+ Protokolle:
+ </text>
+ <check_box label="Protokolle von Gesprächen in der Nähe auf meinem Computer speichern" name="log_nearby_chat"/>
+ <check_box label="IM Protokolle auf meinem Computer speichern" name="log_instant_messages"/>
+ <check_box label="Zeitstempel hinzufügen" name="show_timestamps_check_im"/>
+ <text name="log_path_desc">
+ Speicherort der Protokolldateien
+ </text>
+ <button label="Durchsuchen" label_selected="Durchsuchen" name="log_path_button"/>
+ <button label="Ignorierte Einwohner/Objekte" name="block_list"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_setup.xml b/indra/newview/skins/default/xui/de/panel_preferences_setup.xml
new file mode 100644
index 0000000000..f1d4a853e8
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_preferences_setup.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Kamera" name="Input panel">
+ <button label="Andere Geräte" name="joystick_setup_button"/>
+ <text name="Mouselook:">
+ Mouselook:
+ </text>
+ <text name=" Mouse Sensitivity">
+ Mausempfindlichkeit:
+ </text>
+ <check_box label="Umkehren" name="invert_mouse"/>
+ <text name="Network:">
+ Netzwerk:
+ </text>
+ <text name="Maximum bandwidth">
+ Maximale Bandbreite
+ </text>
+ <text name="text_box2">
+ kbit/s
+ </text>
+ <check_box label="Eigener Port" name="connection_port_enabled"/>
+ <spinner label="Portnummer:" name="web_proxy_port"/>
+ <text name="cache_size_label_l">
+ Cachegröße
+ </text>
+ <text name="text_box5">
+ MB
+ </text>
+ <button label="Durchsuchen" label_selected="Durchsuchen" name="set_cache"/>
+ <button label="Zurücksetzen" label_selected="Set" name="reset_cache"/>
+ <text name="Cache location">
+ Speicherort des Caches
+ </text>
+ <text name="Web:">
+ Web:
+ </text>
+ <radio_group name="use_external_browser">
+ <radio_item label="Integrierten Browser verwenden" name="internal" tool_tip="Integrierten Webbrowser verwenden, um die Hilfe, Weblinks usw. anzuzeigen. Dieser Browser öffnet als neues Fenster innerhalb von [APP_NAME]."/>
+ <radio_item label="Meinen Browser verwenden (IE, Firefox)" name="external" tool_tip="Standard Webbrowser des Systems verwenden, um die Hilfe, Weblinks usw. anzuzeigen. Bei Vollbildmodus nicht empfohlen."/>
+ </radio_group>
+ <check_box initial_value="false" label="Web Proxy" name="web_proxy_enabled"/>
+ <line_editor name="web_proxy_editor" tool_tip="Name oder IP Adresse des Proxyservers, den Sie benutzen möchten"/>
+ <button label="Durchsuchen" label_selected="Durchsuchen" name="set_proxy"/>
+ <text name="Proxy location">
+ Proxyadresse
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_sound.xml b/indra/newview/skins/default/xui/de/panel_preferences_sound.xml
new file mode 100644
index 0000000000..94c215b80b
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_preferences_sound.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Sounds" name="Preference Media panel">
+ <slider label="Master-Lautstärke" name="System Volume"/>
+ <check_box initial_value="true" label="Stummschalten, wenn verkleinert" name="mute_when_minimized"/>
+ <slider label="Umgebung" name="Wind Volume"/>
+ <slider label="Schaltflächen" name="UI Volume"/>
+ <slider label="Medien" name="Media Volume"/>
+ <slider label="Soundeffekte" name="SFX Volume"/>
+ <slider label="Musik wird gestreamt" name="Music Volume"/>
+ <check_box label="Sprache" name="enable_voice_check"/>
+ <slider label="Sprache" name="Voice Volume"/>
+ <text name="Listen from">
+ Hören von:
+ </text>
+ <radio_group name="ear_location">
+ <radio_item label="Kameraposition" name="0"/>
+ <radio_item label="Avatarposition" name="1"/>
+ </radio_group>
+ <button label="Eingabe-/Ausgabegeräte" name="device_settings_btn"/>
+ <panel label="Geräte-Einstellungen" name="device_settings_panel">
+ <panel.string name="default_text">
+ Standard
+ </panel.string>
+ <text name="Input">
+ Eingabe
+ </text>
+ <text name="My volume label">
+ Meine Lautstärke:
+ </text>
+ <slider_bar initial_value="1.0" name="mic_volume_slider" tool_tip="Ändern Sie die Lautstärke mit dem Regler"/>
+ <text name="wait_text">
+ Bitte warten
+ </text>
+ <text name="Output">
+ Ausgabe
+ </text>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/de/panel_prim_media_controls.xml
new file mode 100644
index 0000000000..ed5daa60ce
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_prim_media_controls.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="MediaControls">
+ <string name="control_background_image_name">
+ Inspector_Background
+ </string>
+ <string name="skip_step">
+ 0.2
+ </string>
+ <layout_stack name="media_controls">
+ <layout_panel name="media_address">
+ <line_editor name="media_address_url" tool_tip="Medien URL"/>
+ <layout_stack name="media_address_url_icons">
+ <layout_panel>
+ <icon name="media_whitelist_flag" tool_tip="Whitelist aktiviert"/>
+ </layout_panel>
+ <layout_panel>
+ <icon name="media_secure_lock_flag" tool_tip="Sicheres Browsen"/>
+ </layout_panel>
+ </layout_stack>
+ </layout_panel>
+ <layout_panel name="media_play_position">
+ <slider_bar initial_value="0.5" name="media_play_slider" tool_tip="Fortschritt der Filmwiedergabe"/>
+ </layout_panel>
+ <layout_panel name="media_volume">
+ <button name="media_volume_button" tool_tip="Dieses Medium stummschalten"/>
+ </layout_panel>
+ </layout_stack>
+ <layout_stack>
+ <panel name="media_progress_indicator">
+ <progress_bar name="media_progress_bar" tool_tip="Medien werden geladen"/>
+ </panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_profile.xml b/indra/newview/skins/default/xui/de/panel_profile.xml
new file mode 100644
index 0000000000..c67d7f7fbc
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_profile.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Profil" name="panel_profile">
+ <string name="CaptionTextAcctInfo">
+ [ACCTTYPE]
+[PAYMENTINFO] [AGEVERIFICATION]
+ </string>
+ <string name="payment_update_link_url">
+ http://www.secondlife.com/account/billing.php?lang=de-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/my/account/index.php?lang=de-DE"/>
+ <string name="no_partner_text" value="Keiner"/>
+ <string name="RegisterDateFormat">
+ [REG_DATE] ([AGE])
+ </string>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <panel name="second_life_image_panel">
+ <text name="title_sl_descr_text" value="[SECOND_LIFE]:"/>
+ <expandable_text name="sl_description_edit">
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ <panel name="first_life_image_panel">
+ <text name="title_rw_descr_text" value="Echtes Leben:"/>
+ <expandable_text name="fl_description_edit">
+ Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ <text name="me_homepage_text">
+ Webseite:
+ </text>
+ <text name="title_member_text" value="Mitglied seit:"/>
+ <text name="register_date" value="05/31/1976"/>
+ <text name="title_acc_status_text" value="Kontostatus:"/>
+ <text name="acc_status_text" value="Einwohner. Keine Zahlungsinfo archiviert."/>
+ <text name="title_partner_text" value="Partner:"/>
+ <panel name="partner_data_panel">
+ <text name="partner_text" value="[FIRST] [LAST]"/>
+ </panel>
+ <text name="title_groups_text" value="Gruppen:"/>
+ <expandable_text name="sl_groups">
+ Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ </scroll_container>
+ <panel name="profile_buttons_panel">
+ <button label="Freund hinzufügen" name="add_friend"/>
+ <button label="IM" name="im"/>
+ <button label="Anrufen" name="call"/>
+ <button label="Karte" name="show_on_map_btn"/>
+ <button label="Teleportieren" name="teleport"/>
+ <button label="â–¼" name="overflow_btn"/>
+ </panel>
+ <panel name="profile_me_buttons_panel">
+ <button label="Profil bearbeiten" name="edit_profile_btn"/>
+ <button label="Aussehen bearbeiten" name="edit_appearance_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_profile_view.xml b/indra/newview/skins/default/xui/de/panel_profile_view.xml
new file mode 100644
index 0000000000..4d59c16e98
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_profile_view.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_target_profile">
+ <string name="status_online">
+ Online
+ </string>
+ <string name="status_offline">
+ Offline
+ </string>
+ <text_editor name="user_name" value="(wird geladen...)"/>
+ <text name="status" value="Online"/>
+ <tab_container name="tabs">
+ <panel label="PROFIL" name="panel_profile"/>
+ <panel label="AUSWAHL" name="panel_picks"/>
+ <panel label="NOTIZEN &amp; PRIVATSPHÄRE" name="panel_notes"/>
+ </tab_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_region_covenant.xml b/indra/newview/skins/default/xui/de/panel_region_covenant.xml
index a72f0e4240..14be8def7e 100644
--- a/indra/newview/skins/default/xui/de/panel_region_covenant.xml
+++ b/indra/newview/skins/default/xui/de/panel_region_covenant.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Vertrag" name="Covenant">
<text name="estate_section_lbl">
- Grundstück:
+ Grundstück
</text>
<text name="estate_name_lbl">
Name:
@@ -31,17 +31,16 @@
Grundstück übernommen.
</text>
<text bottom_delta="-36" name="covenant_instructions">
- Ziehen Sie eine Notizkarte an diese Stelle, um den Vertrag für dieses
- Grundstück zu ändern.
+ Ziehen Sie eine Notizkarte an diese Stelle, um den Vertrag für dieses Grundstück zu ändern.
</text>
<text bottom_delta="-36" name="region_section_lbl">
- Region:
+ Region
</text>
<text name="region_name_lbl">
Name:
</text>
<text name="region_name_text">
- leyla
+ Erica
</text>
<text name="region_landtype_lbl">
Typ:
diff --git a/indra/newview/skins/default/xui/de/panel_region_debug.xml b/indra/newview/skins/default/xui/de/panel_region_debug.xml
index 9e03ebeda3..40befab4dd 100644
--- a/indra/newview/skins/default/xui/de/panel_region_debug.xml
+++ b/indra/newview/skins/default/xui/de/panel_region_debug.xml
@@ -22,13 +22,13 @@
<line_editor name="target_avatar_name">
(keiner)
</line_editor>
- <button label="Auswählen..." name="choose_avatar_btn"/>
+ <button label="Auswählen" name="choose_avatar_btn"/>
<text name="options_text_lbl">
Optionen:
</text>
- <check_box label="Nur Objekte mit Skripten zurückgeben" name="return_scripts" tool_tip="Es werden nur die Objekte zurückgegeben, die über Skripte verfügen."/>
- <check_box label="Nur Objekte auf dem Land eines anderen Einwohners zurückgeben" name="return_other_land" tool_tip="Es werden nur die Objekte zurückgegeben, die sich auf dem Land eines anderen Einwohners befinden"/>
- <check_box label="Objekte in jeder Region dieses Grundstücks zurückgeben" name="return_estate_wide" tool_tip="Es werden die Objekte in allen Regionen dieses Grundstücks zurückgegeben"/>
+ <check_box label="Mit Skripten" name="return_scripts" tool_tip="Es werden nur die Objekte zurückgegeben, die über Skripte verfügen."/>
+ <check_box label="Auf dem Land von jemand anderem" name="return_other_land" tool_tip="Es werden nur die Objekte zurückgegeben, die sich auf dem Land eines anderen Einwohners befinden"/>
+ <check_box label="In jeder Region auf diesem Grundstück" name="return_estate_wide" tool_tip="Es werden die Objekte in allen Regionen dieses Grundstücks zurückgegeben"/>
<button label="Zurückgeben" name="return_btn" width="90"/>
<button label="Top-Kollisionsobjekte..." name="top_colliders_btn" tool_tip="Liste der Objekte mit den meisten potenziellen Kollisionen"/>
<button label="?" name="top_colliders_help"/>
diff --git a/indra/newview/skins/default/xui/de/panel_region_estate.xml b/indra/newview/skins/default/xui/de/panel_region_estate.xml
index ddc5941da6..e0008d2a39 100644
--- a/indra/newview/skins/default/xui/de/panel_region_estate.xml
+++ b/indra/newview/skins/default/xui/de/panel_region_estate.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Grundstück" name="Estate">
<text name="estate_help_text">
Änderungen auf dieser Registerkarte wirken sich
@@ -11,7 +11,7 @@ auf alle Regionen auf dem Grundstück aus.
(unbekannt)
</text>
<text name="owner_text">
- Eigentümer:
+ Grundstückseigentümer:
</text>
<text name="estate_owner">
(unbekannt)
@@ -19,59 +19,57 @@ auf alle Regionen auf dem Grundstück aus.
<text name="Only Allow">
Zugang beschränken auf:
</text>
- <check_box label="Einwohner mit Zahlungsinformationen" name="limit_payment"
- tool_tip="Nicht identifizierte Einwohner verbannen." />
- <check_box label="Altersgeprüfte Erwachsene" name="limit_age_verified"
- tool_tip="Einwohner ohne Altersprüfung verbannen. Weitere Informationen finden Sie auf support.secondlife.com." />
- <check_box label="Voice-Chat erlauben" name="voice_chat_check" />
- <button label="?" name="voice_chat_help" />
+ <check_box label="Einwohner mit Zahlungsinformationen" name="limit_payment" tool_tip="Nicht identifizierte Einwohner verbannen"/>
+ <check_box label="Altersgeprüfte Erwachsene" name="limit_age_verified" tool_tip="Einwohner ohne Altersüberprüfung verbannen. Weitere Informationen finden Sie auf [SUPPORT_SITE]."/>
+ <check_box label="Voice-Chat erlauben" name="voice_chat_check"/>
+ <button label="?" name="voice_chat_help"/>
<text name="abuse_email_text" width="222">
E-Mail-Adresse für Missbrauchsmeldungen:
</text>
<string name="email_unsupported">
Funktion nicht unterstützt
</string>
- <button label=" ?" name="abuse_email_address_help" />
- <button label="?" name="estate_manager_help" />
- <button label="Hinzufügen..." name="add_estate_manager_btn" />
- <button label="Entfernen..." name="remove_estate_manager_btn" />
- <check_box label="Globale Zeit verwenden" name="use_global_time_check" />
- <button label="?" name="use_global_time_help" />
- <check_box label="Sonne fest" name="fixed_sun_check" />
- <button label="?" name="fixed_sun_help" />
- <slider label="Phase" name="sun_hour_slider" />
- <check_box label="Freien Zugang erlauben" name="externally_visible_check" />
- <button label="?" name="externally_visible_help" />
- <check_box label="Direktteleport zulassen" name="allow_direct_teleport" />
- <button label="?" name="allow_direct_teleport_help" />
+ <button label=" ?" name="abuse_email_address_help"/>
+ <button label="?" name="estate_manager_help"/>
+ <button label="Hinzufügen..." name="add_estate_manager_btn"/>
+ <button label="Entfernen..." name="remove_estate_manager_btn"/>
+ <check_box label="Globale Zeit verwenden" name="use_global_time_check"/>
+ <button label="?" name="use_global_time_help"/>
+ <check_box label="Sonne fest" name="fixed_sun_check"/>
+ <button label="?" name="fixed_sun_help"/>
+ <slider label="Phase" name="sun_hour_slider"/>
+ <check_box label="Freien Zugang erlauben" name="externally_visible_check"/>
+ <button label="?" name="externally_visible_help"/>
+ <check_box label="Direktteleport zulassen" name="allow_direct_teleport"/>
+ <button label="?" name="allow_direct_teleport_help"/>
<text name="region_text_lbl">
Zugang nach Zahlungsstatus verweigern:
</text>
- <check_box label="Verweigern - keine archivierte Zahlungsinfo" name="deny_anonymous" />
- <check_box label="Verweigern - Zahlungsinfo archiviert" name="deny_identified" />
- <check_box label="Verweigern - Zahlungsinfo verwendet" name="deny_transacted" />
- <button label="Ãœbernehmen" name="apply_btn" />
+ <check_box label="Verweigern - keine archivierte Zahlungsinfo" name="deny_anonymous"/>
+ <check_box label="Verweigern - Zahlungsinfo archiviert" name="deny_identified"/>
+ <check_box label="Verweigern - Zahlungsinfo verwendet" name="deny_transacted"/>
+ <button label="Ãœbernehmen" name="apply_btn"/>
<text name="estate_manager_label">
Grundstücksverwalter:
</text>
<text name="allow_resident_label">
Zulässige Einwohner:
</text>
- <button label="?" name="allow_resident_help" />
- <button label="Hinzufügen..." name="add_allowed_avatar_btn" />
- <button label="Entfernen..." name="remove_allowed_avatar_btn" />
+ <button label="?" name="allow_resident_help"/>
+ <button label="Hinzufügen..." name="add_allowed_avatar_btn"/>
+ <button label="Entfernen..." name="remove_allowed_avatar_btn"/>
<text name="allow_group_label">
Zulässige Gruppen:
</text>
- <button label="?" name="allow_group_help" />
- <button label="Hinzufügen..." name="add_allowed_group_btn" />
- <button label="Entfernen..." name="remove_allowed_group_btn" />
+ <button label="?" name="allow_group_help"/>
+ <button label="Hinzufügen..." name="add_allowed_group_btn"/>
+ <button label="Entfernen..." name="remove_allowed_group_btn"/>
<text name="ban_resident_label">
Verbannte Einwohner:
</text>
- <button label="?" name="ban_resident_help" />
- <button label="Hinzufügen..." name="add_banned_avatar_btn" />
- <button label="Entfernen..." name="remove_banned_avatar_btn" />
- <button label="Nachricht an Grundstück senden..." name="message_estate_btn" />
- <button label="Benutzer von Grundstück werfen..." name="kick_user_from_estate_btn" />
+ <button label="?" name="ban_resident_help"/>
+ <button label="Hinzufügen..." name="add_banned_avatar_btn"/>
+ <button label="Entfernen..." name="remove_banned_avatar_btn"/>
+ <button label="Nachricht an Grundstück senden..." name="message_estate_btn"/>
+ <button label="Benutzer von Grundstück werfen..." name="kick_user_from_estate_btn"/>
</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_region_general.xml b/indra/newview/skins/default/xui/de/panel_region_general.xml
index 9980393ab0..13df2bfb3b 100644
--- a/indra/newview/skins/default/xui/de/panel_region_general.xml
+++ b/indra/newview/skins/default/xui/de/panel_region_general.xml
@@ -40,15 +40,9 @@
Einstufung:
</text>
<combo_box label="Mature" name="access_combo">
- <combo_item name="Adult">
- Adult
- </combo_item>
- <combo_item name="Mature">
- Mature
- </combo_item>
- <combo_item name="PG">
- PG
- </combo_item>
+ <combo_box.item label="Adult" name="Adult"/>
+ <combo_box.item label="Mature" name="Mature"/>
+ <combo_box.item label="PG" name="PG"/>
</combo_box>
<button label="?" name="access_help"/>
<button label="Ãœbernehmen" name="apply_btn"/>
diff --git a/indra/newview/skins/default/xui/de/panel_region_texture.xml b/indra/newview/skins/default/xui/de/panel_region_texture.xml
index df936ff643..4361b39def 100644
--- a/indra/newview/skins/default/xui/de/panel_region_texture.xml
+++ b/indra/newview/skins/default/xui/de/panel_region_texture.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Bodentexturen" name="Textures">
<text name="region_text_lbl">
Region:
@@ -36,22 +36,23 @@
<text name="height_text_lbl9">
Nordost
</text>
- <spinner label="Niedrig" name="height_start_spin_0" />
- <spinner label="Niedrig" name="height_start_spin_1" />
- <spinner label="Niedrig" name="height_start_spin_2" />
- <spinner label="Niedrig" name="height_start_spin_3" />
- <spinner label="Hoch" name="height_range_spin_0" />
- <spinner label="Hoch" name="height_range_spin_1" />
- <spinner label="Hoch" name="height_range_spin_2" />
- <spinner label="Hoch" name="height_range_spin_3" />
+ <spinner label="Niedrig" name="height_start_spin_0"/>
+ <spinner label="Niedrig" name="height_start_spin_1"/>
+ <spinner label="Niedrig" name="height_start_spin_2"/>
+ <spinner label="Niedrig" name="height_start_spin_3"/>
+ <spinner label="Hoch" name="height_range_spin_0"/>
+ <spinner label="Hoch" name="height_range_spin_1"/>
+ <spinner label="Hoch" name="height_range_spin_2"/>
+ <spinner label="Hoch" name="height_range_spin_3"/>
<text name="height_text_lbl10">
Diese Werte geben den Mischungsgrad für die obigen Texturen an.
</text>
<text name="height_text_lbl11">
Der UNTERE Wert gibt die MAXIMALE Höhe von Textur Nr. 1 an
+und der OBERE WERT die MINIMALE Höhe von Textur 4.
</text>
<text name="height_text_lbl12">
und der OBERE WERT die MINIMALE Höhe von Textur 4.
</text>
- <button label="Ãœbernehmen" name="apply_btn" />
+ <button label="Ãœbernehmen" name="apply_btn"/>
</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_script_ed.xml b/indra/newview/skins/default/xui/de/panel_script_ed.xml
new file mode 100644
index 0000000000..17970cf261
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_script_ed.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="script panel">
+ <panel.string name="loading">
+ Wird geladen...
+ </panel.string>
+ <panel.string name="can_not_view">
+ Dieses Skript kann nicht angezeigt oder bearbeitet werden, da als Berechtigung „kein kopieren&quot; festgelegt wurde. Um ein Skript innerhalb eines Objektes anzuzeigen oder zu bearbeiten, benötigen Sie die vollständige Berechtigung.
+ </panel.string>
+ <panel.string name="public_objects_can_not_run">
+ Öffentliche Objekte können keine Skripts ausführen
+ </panel.string>
+ <panel.string name="script_running">
+ Läuft
+ </panel.string>
+ <panel.string name="Title">
+ Skript: [NAME]
+ </panel.string>
+ <text_editor name="Script Editor">
+ Wird geladen...
+ </text_editor>
+ <button label="Speichern" label_selected="Speichern" name="Save_btn"/>
+ <combo_box label="Einfügen..." name="Insert..."/>
+ <menu_bar name="script_menu">
+ <menu label="Datei" name="File">
+ <menu_item_call label="Speichern" name="Save"/>
+ <menu_item_call label="Alle Änderungen zurücksetzen" name="Revert All Changes"/>
+ </menu>
+ <menu label="Bearbeiten" name="Edit">
+ <menu_item_call label="Rückgängig" name="Undo"/>
+ <menu_item_call label="Wiederherstellen" name="Redo"/>
+ <menu_item_call label="Ausschneiden" name="Cut"/>
+ <menu_item_call label="Kopieren" name="Copy"/>
+ <menu_item_call label="Einfügen" name="Paste"/>
+ <menu_item_call label="Alle auswählen" name="Select All"/>
+ <menu_item_call label="Auswahl aufheben" name="Deselect"/>
+ <menu_item_call label="Suchen / Ersetzen..." name="Search / Replace..."/>
+ </menu>
+ <menu label="Hilfe" name="Help">
+ <menu_item_call label="Hilfe..." name="Help..."/>
+ <menu_item_call label="Schlüsselwort-Hilfe" name="Keyword Help..."/>
+ </menu>
+ </menu_bar>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_scrolling_param.xml b/indra/newview/skins/default/xui/de/panel_scrolling_param.xml
index d51fda0b5e..50590b8d73 100644
--- a/indra/newview/skins/default/xui/de/panel_scrolling_param.xml
+++ b/indra/newview/skins/default/xui/de/panel_scrolling_param.xml
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="LLScrollingPanelParam">
- <text type="string" length="1" name="Loading...">
+ <text name="Loading...">
Wird geladen...
</text>
- <text type="string" length="1" name="Loading...2">
+ <text name="Loading...2">
Wird geladen...
</text>
<button label="" label_selected="" name="less" />
diff --git a/indra/newview/skins/default/xui/de/panel_side_tray.xml b/indra/newview/skins/default/xui/de/panel_side_tray.xml
new file mode 100644
index 0000000000..d5baacd357
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_side_tray.xml
@@ -0,0 +1,26 @@
+<?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="Startseite." name="sidebar_home">
+ <panel label="Startseite" name="panel_home"/>
+ </sidetray_tab>
+ <sidetray_tab description="Freunde, Kontakte und Leute in Ihrer Nähe finden." name="sidebar_people">
+ <panel_container name="panel_container">
+ <panel label="Gruppeninfo" name="panel_group_info_sidetray"/>
+ <panel label="Ignorierte Einwohner &amp; Objekte" name="panel_block_list_sidetray"/>
+ </panel_container>
+ </sidetray_tab>
+ <sidetray_tab description="Hier finden Sie neue Orte und Orte, die Sie bereits besucht haben." label="Orte" name="sidebar_places">
+ <panel label="Orte" name="panel_places"/>
+ </sidetray_tab>
+ <sidetray_tab description="Ihr öffentliches Profil und Auswahl bearbeiten." name="sidebar_me">
+ <panel label="Ich" name="panel_me"/>
+ </sidetray_tab>
+ <sidetray_tab description="Ändern Sie Ihr Aussehen und Ihren aktuellen Look." name="sidebar_appearance">
+ <panel label="Aussehen bearbeiten" name="sidepanel_appearance"/>
+ </sidetray_tab>
+ <sidetray_tab description="Inventar durchsuchen." name="sidebar_inventory">
+ <panel label="Inventar bearbeiten" name="sidepanel_inventory"/>
+ </sidetray_tab>
+</side_tray>
diff --git a/indra/newview/skins/default/xui/de/panel_side_tray_tab_caption.xml b/indra/newview/skins/default/xui/de/panel_side_tray_tab_caption.xml
new file mode 100644
index 0000000000..93fff56f84
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_side_tray_tab_caption.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="sidetray_tab_panel">
+ <text name="sidetray_tab_title" value="Klappmenü??"/>
+ <button name="show_help" tool_tip="Hilfe anzeigen"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_sidetray_home_tab.xml b/indra/newview/skins/default/xui/de/panel_sidetray_home_tab.xml
new file mode 100644
index 0000000000..cf3080a4f9
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_sidetray_home_tab.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- Part of side tray, see that XML file for panel config -->
+<panel label="home_tab" name="home_tab">
+ <scroll_container name="profile_scroll">
+ <panel name="profile_scroll_panel">
+ <panel name="sidebar_people">
+ <text name="tab_name" value="Leute"/>
+ <text name="tab_description">
+ Freunde, Gruppen, Kontakte und Leute in Ihrer Nähe finden.
+ </text>
+ </panel>
+ <panel name="sidebar_places">
+ <text name="tab_name" value="Orte"/>
+ <text name="tab_description">
+ Hier finden Sie neue Orte und Orte, die Sie bereits besucht haben.
+ </text>
+ </panel>
+ <panel name="sidebar_me">
+ <text name="tab_name" value="Mein Profil"/>
+ <text name="tab_description">
+ Öffentliches Profil bearbeiten.
+ </text>
+ </panel>
+ <panel name="sidebar_appearance">
+ <text name="tab_name" value="Mein Aussehen"/>
+ <text name="tab_description">
+ Ändern Sie Ihr Aussehen und Ihren aktuellen Look.
+ </text>
+ </panel>
+ <panel name="sidebar_inventory">
+ <text name="tab_name" value="Mein Inventar"/>
+ <text name="tab_description">
+ Inventar durchsuchen.
+ </text>
+ </panel>
+ </panel>
+ </scroll_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_stand_stop_flying.xml b/indra/newview/skins/default/xui/de/panel_stand_stop_flying.xml
new file mode 100644
index 0000000000..5b8137af4a
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_stand_stop_flying.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- Width and height of this panel should be synchronized with "panel_modes" in the floater_moveview.xml-->
+<panel name="panel_stand_stop_flying">
+ <button label="Stehen" name="stand_btn" tool_tip="Klicken Sie hier, um aufzustehen."/>
+ <button label="Landen" name="stop_fly_btn" tool_tip="Landen"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_status_bar.xml b/indra/newview/skins/default/xui/de/panel_status_bar.xml
index adfe38797d..253207fe73 100644
--- a/indra/newview/skins/default/xui/de/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/de/panel_status_bar.xml
@@ -1,42 +1,29 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="status">
- <text length="1" name="ParcelNameText" tool_tip="Der Name der Parzelle, auf der Sie sich befinden. Klicken Sie für Land-Informationen." type="string">
- Parzellenname hier
- </text>
- <text length="1" name="BalanceText" tool_tip="Kontostand" type="string">
- Wird geladen...
- </text>
- <button label="" label_selected="" name="buycurrency" tool_tip="Geld kaufen"/>
- <text length="12" name="TimeText" tool_tip="Aktuelle Zeit (Pazifik)" type="string">
- 12:00
- </text>
- <text name="StatBarDaysOfWeek">
+ <panel.string name="StatBarDaysOfWeek">
Sonntag:Montag:Dienstag:Mittwoch:Donnerstag:Freitag:Samstag
- </text>
- <text name="StatBarMonthsOfYear">
+ </panel.string>
+ <panel.string name="StatBarMonthsOfYear">
Januar:Februar:März:April:Mai:Juni:Juli:August:September:Oktober:November:Dezember
- </text>
- <button label="" label_selected="" name="scriptout" tool_tip="Skriptwarnungen und -fehler"/>
- <button label="" label_selected="" name="health" tool_tip="Gesundheit"/>
- <text length="1" name="HealthText" tool_tip="Gesundheit" type="string">
- 100%
- </text>
- <button label="" label_selected="" name="fly" tool_tip="Fliegen aus"/>
- <button label="" label_selected="" name="build" tool_tip="Bauen aus"/>
- <button label="" label_selected="" name="scripts" tool_tip="Skripts aus"/>
- <button name="no_fly" tool_tip="Fliegen ist unzulässig"/>
- <button name="no_build" tool_tip="Bauen/Rezzen ist unzulässig"/>
- <button name="no_scripts" tool_tip="Skripte sind unzulässig"/>
- <button label="" label_selected="" name="restrictpush" tool_tip="Kein Stoßen"/>
- <button name="status_voice" tool_tip="Voice aktiviert"/>
- <button name="status_no_voice" tool_tip="Voice hier nicht möglich"/>
- <button label="" label_selected="" name="buyland" tool_tip="Diese Parzelle kaufen"/>
- <text name="packet_loss_tooltip">
+ </panel.string>
+ <panel.string name="packet_loss_tooltip">
Paketverlust
- </text>
- <text name="bandwidth_tooltip">
+ </panel.string>
+ <panel.string name="bandwidth_tooltip">
Bandbreite
+ </panel.string>
+ <panel.string name="time">
+ [hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]
+ </panel.string>
+ <panel.string name="timeTooltip">
+ [weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]
+ </panel.string>
+ <panel.string name="buycurrencylabel">
+ [AMT] L$
+ </panel.string>
+ <button label="" label_selected="" name="buycurrency" tool_tip="Mein Kontostand: Hier klicken, um mehr L$ zu kaufen"/>
+ <text name="TimeText" tool_tip="Aktuelle Zeit (Pazifik)">
+ 12:00
</text>
- <line_editor label="Suchen" name="search_editor" tool_tip="Second Life durchsuchen"/>
- <button name="search_btn" tool_tip="Second Life durchsuchen"/>
+ <button name="volume_btn" tool_tip="Steuerung der Gesamtlautstärke"/>
</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_sys_well_item.xml b/indra/newview/skins/default/xui/de/panel_sys_well_item.xml
new file mode 100644
index 0000000000..504f1727e2
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_sys_well_item.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- All our XML is utf-8 encoded. -->
+<panel name="sys_well_item" title="sys_well_item">
+ <text name="title">
+ Achtung Forelle! ACHTUNG! DIE! FORELLE!
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_teleport_history.xml b/indra/newview/skins/default/xui/de/panel_teleport_history.xml
new file mode 100644
index 0000000000..3149ddf19e
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_teleport_history.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="Teleport History">
+ <accordion name="history_accordion">
+ <accordion_tab name="today" title="Heute"/>
+ <accordion_tab name="yesterday" title="Gestern"/>
+ <accordion_tab name="2_days_ago" title="Vor 2 Tagen"/>
+ <accordion_tab name="3_days_ago" title="Vor 3 Tagen"/>
+ <accordion_tab name="4_days_ago" title="Vor 4 Tagen"/>
+ <accordion_tab name="5_days_ago" title="Vor 5 Tagen"/>
+ <accordion_tab name="6_days_and_older" title="6 Tage und älter"/>
+ <accordion_tab name="1_month_and_older" title="1 Monat und älter"/>
+ <accordion_tab name="6_months_and_older" title="6 Monate und älter"/>
+ </accordion>
+ <panel label="bottom_panel" name="bottom_panel"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_teleport_history_item.xml b/indra/newview/skins/default/xui/de/panel_teleport_history_item.xml
new file mode 100644
index 0000000000..9d18c52442
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_teleport_history_item.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="teleport_history_item">
+ <text name="region" value="..."/>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_world_map.xml b/indra/newview/skins/default/xui/de/panel_world_map.xml
new file mode 100644
index 0000000000..f7454dd634
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_world_map.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="world_map">
+ <panel.string name="Loading">
+ Wird geladen...
+ </panel.string>
+ <panel.string name="InvalidLocation">
+ Ungültige Position
+ </panel.string>
+ <panel.string name="world_map_north">
+ N
+ </panel.string>
+ <panel.string name="world_map_east">
+ O
+ </panel.string>
+ <panel.string name="world_map_west">
+ W
+ </panel.string>
+ <panel.string name="world_map_south">
+ S
+ </panel.string>
+ <panel.string name="world_map_southeast">
+ SO
+ </panel.string>
+ <panel.string name="world_map_northeast">
+ NO
+ </panel.string>
+ <panel.string name="world_map_southwest">
+ SW
+ </panel.string>
+ <panel.string name="world_map_northwest">
+ NW
+ </panel.string>
+ <text label="N" name="floater_map_north" text="N">
+ N
+ </text>
+ <text label="O" name="floater_map_east" text="O">
+ O
+ </text>
+ <text label="W" name="floater_map_west" text="W">
+ W
+ </text>
+ <text label="S" name="floater_map_south" text="S">
+ S
+ </text>
+ <text label="SO" name="floater_map_southeast" text="SO">
+ SO
+ </text>
+ <text label="NO" name="floater_map_northeast" text="NO">
+ NO
+ </text>
+ <text label="SW" name="floater_map_southwest" text="SW">
+ SW
+ </text>
+ <text label="NW" name="floater_map_northwest" text="NW">
+ NW
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/sidepanel_appearance.xml b/indra/newview/skins/default/xui/de/sidepanel_appearance.xml
new file mode 100644
index 0000000000..07d35f30e4
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/sidepanel_appearance.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Aussehen" name="appearance panel">
+ <string name="No Outfit" value="Kein Outfit"/>
+ <panel name="panel_currentlook">
+ <button label="Bearbeiten" name="editappearance_btn"/>
+ <text name="currentlook_title">
+ Aktuelles Outfit:
+ </text>
+ <text name="currentlook_name">
+ Mein Outfit
+ </text>
+ </panel>
+ <filter_editor label="Filter" name="Filter"/>
+ <button label="Anziehen" name="wear_btn"/>
+ <button label="Neues Outfit" name="newlook_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/sidepanel_inventory.xml b/indra/newview/skins/default/xui/de/sidepanel_inventory.xml
new file mode 100644
index 0000000000..d40e2f3398
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/sidepanel_inventory.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Sonstiges" name="objects panel">
+ <panel label="" name="sidepanel__inventory_panel">
+ <panel name="button_panel">
+ <button label="Info" name="info_btn"/>
+ <button label="Anziehen" name="wear_btn"/>
+ <button label="Wiedergeben" name="play_btn"/>
+ <button label="Teleportieren" name="teleport_btn"/>
+ </panel>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/sidepanel_item_info.xml b/indra/newview/skins/default/xui/de/sidepanel_item_info.xml
new file mode 100644
index 0000000000..947ffbf186
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/sidepanel_item_info.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="item properties" title="Inventarobjekt-Eigenschaften">
+ <panel.string name="unknown">
+ (unbekannt)
+ </panel.string>
+ <panel.string name="public">
+ (öffentlich)
+ </panel.string>
+ <panel.string name="you_can">
+ Sie können:
+ </panel.string>
+ <panel.string name="owner_can">
+ Eigentümer kann:
+ </panel.string>
+ <panel.string name="acquiredDate">
+ [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+ </panel.string>
+ <panel label="">
+ <text name="LabelItemNameTitle">
+ Name:
+ </text>
+ <text name="LabelItemDescTitle">
+ Beschreibung:
+ </text>
+ <text name="LabelCreatorTitle">
+ Ersteller:
+ </text>
+ <text name="LabelCreatorName">
+ Nicole Linden
+ </text>
+ <button label="Profil..." name="BtnCreator"/>
+ <text name="LabelOwnerTitle">
+ Eigentümer:
+ </text>
+ <text name="LabelOwnerName">
+ Thrax Linden
+ </text>
+ <button label="Profil..." name="BtnOwner"/>
+ <text name="LabelAcquiredTitle">
+ Erworben:
+ </text>
+ <text name="LabelAcquiredDate">
+ Mittwoch, 24. Mai 2006, 12:50:46
+ </text>
+ <text name="OwnerLabel">
+ Sie:
+ </text>
+ <check_box label="Bearbeiten" name="CheckOwnerModify"/>
+ <check_box label="Kopieren" name="CheckOwnerCopy"/>
+ <check_box label="Wiederverkaufen" name="CheckOwnerTransfer"/>
+ <text name="AnyoneLabel">
+ Jeder:
+ </text>
+ <check_box label="Kopieren" name="CheckEveryoneCopy"/>
+ <text name="GroupLabel">
+ Gruppe:
+ </text>
+ <check_box label="Teilen" name="CheckShareWithGroup"/>
+ <text name="NextOwnerLabel">
+ Nächster Eigentümer:
+ </text>
+ <check_box label="Bearbeiten" name="CheckNextOwnerModify"/>
+ <check_box label="Kopieren" name="CheckNextOwnerCopy"/>
+ <check_box label="Wiederverkaufen" name="CheckNextOwnerTransfer"/>
+ <check_box label="Zum Verkauf" name="CheckPurchase"/>
+ <combo_box name="combobox sale copy">
+ <combo_box.item label="Kopieren" name="Copy"/>
+ <combo_box.item label="Original" name="Original"/>
+ </combo_box>
+ <spinner label="Preis:" name="Edit Cost"/>
+ <text name="CurrencySymbol">
+ L$
+ </text>
+ </panel>
+ <panel name="button_panel">
+ <button label="Bearbeiten" name="edit_btn"/>
+ <button label="Abbrechen" name="cancel_btn"/>
+ <button label="Speichern" name="save_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/sidepanel_task_info.xml b/indra/newview/skins/default/xui/de/sidepanel_task_info.xml
new file mode 100644
index 0000000000..b0ce47e3ae
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/sidepanel_task_info.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="object properties" title="Objekteigenschaften">
+ <panel.string name="text deed continued">
+ Ãœbertragung
+ </panel.string>
+ <panel.string name="text deed">
+ Ãœbertragung
+ </panel.string>
+ <panel.string name="text modify info 1">
+ Sie können dieses Objekt bearbeiten.
+ </panel.string>
+ <panel.string name="text modify info 2">
+ Sie können diese Objekte bearbeiten.
+ </panel.string>
+ <panel.string name="text modify info 3">
+ Sie können dieses Objekt nicht bearbeiten.
+ </panel.string>
+ <panel.string name="text modify info 4">
+ Sie können diese Objekte nicht bearbeiten.
+ </panel.string>
+ <panel.string name="text modify warning">
+ Diese Objekt verfügt über verknüpfte Teile
+ </panel.string>
+ <panel.string name="Cost Default">
+ Preis: L$
+ </panel.string>
+ <panel.string name="Cost Total">
+ Summe: L$
+ </panel.string>
+ <panel.string name="Cost Per Unit">
+ Stückpreis: L$
+ </panel.string>
+ <panel.string name="Cost Mixed">
+ Mischpreis
+ </panel.string>
+ <panel.string name="Sale Mixed">
+ Mischverkauf
+ </panel.string>
+ <panel label="">
+ <text name="Name:">
+ Name:
+ </text>
+ <text name="Description:">
+ Beschreibung:
+ </text>
+ <text name="Creator:">
+ Ersteller:
+ </text>
+ <text name="Creator Name">
+ Esbee Linden
+ </text>
+ <text name="Owner:">
+ Eigentümer:
+ </text>
+ <text name="Owner Name">
+ Erica Linden
+ </text>
+ <text name="Group:">
+ Gruppe:
+ </text>
+ <button name="button set group" tool_tip="Eine Gruppe auswählen, um die Berechtigungen des Objekts zu teilen."/>
+ <name_box initial_value="Wird geladen..." name="Group Name Proxy"/>
+ <button label="Übertragung" label_selected="Übertragung" name="button deed" tool_tip="Eine Übertragung bedeutet, dass das Objekt mit den Berechtigungen „Nächster Eigentümer“ weitergegeben wird. Mit der Gruppe geteilte Objekte können von einem Gruppen-Officer übertragen werden."/>
+ <check_box label="Teilen" name="checkbox share with group" tool_tip="Mit allen Mitgliedern der zugeordneten Gruppe, Ihre Berechtigungen dieses Objekt zu ändern teilen. Sie müssen Übereignen, um Rollenbeschränkungen zu aktivieren."/>
+ <text name="label click action">
+ Bei Linksklick:
+ </text>
+ <combo_box name="clickaction">
+ <combo_box.item label="Berühren (Standard)" name="Touch/grab(default)"/>
+ <combo_box.item label="Auf Objekt setzen" name="Sitonobject"/>
+ <combo_box.item label="Objekt kaufen" name="Buyobject"/>
+ <combo_box.item label="Objekt bezahlen" name="Payobject"/>
+ <combo_box.item label="Öffnen" name="Open"/>
+ </combo_box>
+ <check_box label="Zum Verkauf:" name="checkbox for sale"/>
+ <combo_box name="sale type">
+ <combo_box.item label="Kopieren" name="Copy"/>
+ <combo_box.item label="Inhalte" name="Contents"/>
+ <combo_box.item label="Original" name="Original"/>
+ </combo_box>
+ <spinner label="Preis: L$" name="Edit Cost"/>
+ <check_box label="In Suche anzeigen" name="search_check" tool_tip="Dieses Objekt in Suchergebnissen anzeigen"/>
+ <panel name="perms_build">
+ <text name="perm_modify">
+ Sie können dieses Objekt bearbeiten.
+ </text>
+ <text name="Anyone can:">
+ Jeder:
+ </text>
+ <check_box label="Bewegen" name="checkbox allow everyone move"/>
+ <check_box label="Kopieren" name="checkbox allow everyone copy"/>
+ <text name="Next owner can:">
+ Nächster Eigentümer:
+ </text>
+ <check_box label="Bearbeiten" name="checkbox next owner can modify"/>
+ <check_box label="Kopieren" name="checkbox next owner can copy"/>
+ <check_box label="Transferieren" name="checkbox next owner can transfer" tool_tip="Nächster Eigentümer kann dieses Objekt weitergeben oder -verkaufen"/>
+ <text name="B:">
+ B:
+ </text>
+ <text name="O:">
+ O:
+ </text>
+ <text name="G:">
+ G:
+ </text>
+ <text name="E:">
+ E:
+ </text>
+ <text name="N:">
+ N:
+ </text>
+ <text name="F:">
+ F:
+ </text>
+ </panel>
+ </panel>
+ <panel name="button_panel">
+ <button label="Bearbeiten" name="edit_btn"/>
+ <button label="Öffnen" name="open_btn"/>
+ <button label="Zahlen" name="pay_btn"/>
+ <button label="Kaufen" name="buy_btn"/>
+ <button label="Abbrechen" name="cancel_btn"/>
+ <button label="Speichern" name="save_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml
index 3436cfac1e..1488f615a3 100644
--- a/indra/newview/skins/default/xui/de/strings.xml
+++ b/indra/newview/skins/default/xui/de/strings.xml
@@ -1,12 +1,36 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- This file contains strings that used to be hardcoded in the source.
It is only for those strings which do not belong in a floater.
- For example, the strings used in avatar chat bubbles, and strings
+ For example, the strings used in avatar chat bubbles, and strings
that are returned from one component and may appear in many places-->
<strings>
+ <string name="SECOND_LIFE">
+ Second Life
+ </string>
+ <string name="APP_NAME">
+ Second Life
+ </string>
+ <string name="SECOND_LIFE_GRID">
+ Second Life-Grid:
+ </string>
+ <string name="SUPPORT_SITE">
+ Second Life Support-Portal
+ </string>
+ <string name="StartupDetectingHardware">
+ Hardware wird erfasst...
+ </string>
+ <string name="StartupLoading">
+ Wird geladen
+ </string>
+ <string name="Fullbright">
+ Fullbright (Legacy)
+ </string>
<string name="LoginInProgress">
Anmeldevorgang gestartet. [APP_NAME] reagiert möglicherweise nicht. Bitte warten.
</string>
+ <string name="LoginInProgressNoFrozen">
+ Anmeldung erfolgt...
+ </string>
<string name="LoginAuthenticating">
Authentifizierung
</string>
@@ -55,8 +79,14 @@
<string name="LoginDownloadingClothing">
Kleidung wird geladen...
</string>
+ <string name="Quit">
+ Beenden
+ </string>
+ <string name="create_account_url">
+ http://join.secondlife.com/index.php?lang=de-DE
+ </string>
<string name="AgentLostConnection">
- In dieser Region kann es zu Problemen kommen. Bitte überprüfen Sie Ihre Internetverbindung.
+ In dieser Region kann es zu Problemen kommen. Bitte überprüfen Sie Ihre Internetverbindung.
</string>
<string name="TooltipPerson">
Person
@@ -73,39 +103,9 @@
<string name="TooltipIsGroup">
(Gruppe)
</string>
- <string name="TooltipFlagScript">
- Skript
- </string>
- <string name="TooltipFlagPhysics">
- Physik
- </string>
- <string name="TooltipFlagTouch">
- Berühren
- </string>
- <string name="TooltipFlagL$">
- L$
- </string>
- <string name="TooltipFlagDropInventory">
- Inventar fallen lassen
- </string>
- <string name="TooltipFlagPhantom">
- Phantom
- </string>
- <string name="TooltipFlagTemporary">
- Temporär
- </string>
- <string name="TooltipFlagRightClickMenu">
- (Rechtsklick für Menü)
- </string>
- <string name="TooltipFreeToCopy">
- Kopieren möglich
- </string>
<string name="TooltipForSaleL$">
Zum Verkauf: [AMOUNT] L$
</string>
- <string name="TooltipForSaleMsg">
- Zum Verkauf: [MESSAGE]
- </string>
<string name="TooltipFlagGroupBuild">
Gruppenbau
</string>
@@ -133,6 +133,76 @@
<string name="TooltipMustSingleDrop">
Sie können nur ein einzelnes Objekt hierher ziehen
</string>
+ <string name="TooltipHttpUrl">
+ Anklicken, um Webseite anzuzeigen
+ </string>
+ <string name="TooltipSLURL">
+ Anklicken, um Informationen zu diesem Standort anzuzeigen
+ </string>
+ <string name="TooltipAgentUrl">
+ Anklicken, um das Profil dieses Einwohners anzuzeigen
+ </string>
+ <string name="TooltipGroupUrl">
+ Anklicken, um Beschreibung der Gruppe anzuzeigen
+ </string>
+ <string name="TooltipEventUrl">
+ Anklicken, um Beschreibung der Veranstaltung anzuzeigen
+ </string>
+ <string name="TooltipClassifiedUrl">
+ Anklicken, um diese Anzeige anzuzeigen
+ </string>
+ <string name="TooltipParcelUrl">
+ Anklicken, um Beschreibung der Parzelle anzuzeigen
+ </string>
+ <string name="TooltipTeleportUrl">
+ Anklicken, um zu diesem Standort zu teleportieren
+ </string>
+ <string name="TooltipObjectIMUrl">
+ Anklicken, um Beschreibung des Objekts anzuzeigen
+ </string>
+ <string name="TooltipMapUrl">
+ Klicken, um diese Position auf der Karte anzuzeigen
+ </string>
+ <string name="TooltipSLAPP">
+ Anklicken, um Befehl secondlife:// auszuführen
+ </string>
+ <string name="CurrentURL" value=" CurrentURL: [CurrentURL]"/>
+ <string name="SLurlLabelTeleport">
+ Teleportieren nach
+ </string>
+ <string name="SLurlLabelShowOnMap">
+ Karte anzeigen für
+ </string>
+ <string name="BUTTON_CLOSE_DARWIN">
+ Schließen (&#8984;W)
+ </string>
+ <string name="BUTTON_CLOSE_WIN">
+ Schließen (Strg+W)
+ </string>
+ <string name="BUTTON_RESTORE">
+ Wiederherstellen
+ </string>
+ <string name="BUTTON_MINIMIZE">
+ Minimieren
+ </string>
+ <string name="BUTTON_TEAR_OFF">
+ Abnehmen
+ </string>
+ <string name="BUTTON_DOCK">
+ Andocken
+ </string>
+ <string name="BUTTON_UNDOCK">
+ Abkoppeln
+ </string>
+ <string name="BUTTON_HELP">
+ Hilfe anzeigen
+ </string>
+ <string name="Searching">
+ Suchen...
+ </string>
+ <string name="NoneFound">
+ Nicht gefunden.
+ </string>
<string name="RetrievingData">
Laden...
</string>
@@ -148,6 +218,9 @@
<string name="AvatarNameWaiting">
(wartet)
</string>
+ <string name="AvatarNameMultiple">
+ (mehrere)
+ </string>
<string name="AvatarNameHippos">
(hippos)
</string>
@@ -187,7 +260,79 @@
<string name="AssetErrorUnknownStatus">
Status unbekannt
</string>
- <string name="AvatarEditingApparance">
+ <string name="texture">
+ Textur
+ </string>
+ <string name="sound">
+ Sound
+ </string>
+ <string name="calling card">
+ Visitenkarte
+ </string>
+ <string name="landmark">
+ Landmarke
+ </string>
+ <string name="legacy script">
+ Skript (veraltet)
+ </string>
+ <string name="clothing">
+ Kleidung
+ </string>
+ <string name="object">
+ Objekt
+ </string>
+ <string name="note card">
+ Notizkarte
+ </string>
+ <string name="folder">
+ Ordner
+ </string>
+ <string name="root">
+ Hauptverzeichnis
+ </string>
+ <string name="lsl2 script">
+ LSL2 Skript
+ </string>
+ <string name="lsl bytecode">
+ LSL Bytecode
+ </string>
+ <string name="tga texture">
+ tga-Textur
+ </string>
+ <string name="body part">
+ Körperteil
+ </string>
+ <string name="snapshot">
+ Foto
+ </string>
+ <string name="lost and found">
+ Fundbüro
+ </string>
+ <string name="targa image">
+ targa-Bild
+ </string>
+ <string name="trash">
+ Papierkorb
+ </string>
+ <string name="jpeg image">
+ jpeg-Bild
+ </string>
+ <string name="animation">
+ Animation
+ </string>
+ <string name="gesture">
+ Geste
+ </string>
+ <string name="simstate">
+ simstate
+ </string>
+ <string name="favorite">
+ Favoriten
+ </string>
+ <string name="symbolic link">
+ Link
+ </string>
+ <string name="AvatarEditingAppearance">
(Aussehen wird bearbeitet)
</string>
<string name="AvatarAway">
@@ -197,7 +342,7 @@
Beschäftigt
</string>
<string name="AvatarMuted">
- Stummgeschaltet
+ Ignoriert
</string>
<string name="anim_express_afraid">
Ängstlich
@@ -412,12 +557,75 @@
<string name="worldmap_offline">
Offline
</string>
+ <string name="worldmap_results_none_found">
+ Nicht gefunden.
+ </string>
+ <string name="Ok">
+ OK
+ </string>
+ <string name="Premature end of file">
+ Unvollständige Datei
+ </string>
+ <string name="ST_NO_JOINT">
+ HAUPTVERZEICHNIS oder VERBINDUNG nicht gefunden.
+ </string>
<string name="whisper">
flüstert:
</string>
<string name="shout">
ruft:
</string>
+ <string name="ringing">
+ Verbindung mit In-Welt-Voice-Chat...
+ </string>
+ <string name="connected">
+ Verbunden
+ </string>
+ <string name="unavailable">
+ Der aktuelle Standort unterstützt keine Voice-Kommunikation
+ </string>
+ <string name="hang_up">
+ Verbindung mit In-Welt-Voice-Chat getrennt
+ </string>
+ <string name="ScriptQuestionCautionChatGranted">
+ Dem Objekt „[OBJECTNAME]“, ein Objekt von „[OWNERNAME]“, in [REGIONNAME] [REGIONPOS], wurde folgende Berechtigung erteilt: [PERMISSIONS].
+ </string>
+ <string name="ScriptQuestionCautionChatDenied">
+ Dem Objekt „[OBJECTNAME]“, ein Objekt von „[OWNERNAME]“, in [REGIONNAME] [REGIONPOS], wurde folgende Berechtigung verweigert: [PERMISSIONS].
+ </string>
+ <string name="ScriptTakeMoney">
+ Linden-Dollar (L$) von Ihnen nehmen
+ </string>
+ <string name="ActOnControlInputs">
+ Steuerung festlegen
+ </string>
+ <string name="RemapControlInputs">
+ Steuerung neu zuweisen
+ </string>
+ <string name="AnimateYourAvatar">
+ Avatar animieren
+ </string>
+ <string name="AttachToYourAvatar">
+ An Avatar anhängen
+ </string>
+ <string name="ReleaseOwnership">
+ Eigentum aufgeben und öffentlich machen
+ </string>
+ <string name="LinkAndDelink">
+ Mit Objekten verknüpfen und davon trennen
+ </string>
+ <string name="AddAndRemoveJoints">
+ Verbindungen zu anderen Objekten hinzufügen und entfernen
+ </string>
+ <string name="ChangePermissions">
+ Berechtigungen ändern
+ </string>
+ <string name="TrackYourCamera">
+ Kameraverfolgung
+ </string>
+ <string name="ControlYourCamera">
+ Kamerasteuerung
+ </string>
<string name="SIM_ACCESS_PG">
PG
</string>
@@ -436,12 +644,6 @@
<string name="land_type_unknown">
(unbekannt)
</string>
- <string name="covenant_never_modified">
- Zuletzt geändert: (nie)
- </string>
- <string name="covenant_modified">
- Zuletzt geändert:
- </string>
<string name="all_files">
Alle Dateien
</string>
@@ -487,4 +689,2432 @@
<string name="choose_the_directory">
Verzeichnis auswählen
</string>
+ <string name="AvatarSetNotAway">
+ Nicht abwesend
+ </string>
+ <string name="AvatarSetAway">
+ Abwesend
+ </string>
+ <string name="AvatarSetNotBusy">
+ Nicht beschäftigt
+ </string>
+ <string name="AvatarSetBusy">
+ Beschäftigt
+ </string>
+ <string name="shape">
+ Form
+ </string>
+ <string name="skin">
+ Haut
+ </string>
+ <string name="hair">
+ Haare
+ </string>
+ <string name="eyes">
+ Augen
+ </string>
+ <string name="shirt">
+ Hemd
+ </string>
+ <string name="pants">
+ Hose
+ </string>
+ <string name="shoes">
+ Schuhe
+ </string>
+ <string name="socks">
+ Socken
+ </string>
+ <string name="jacket">
+ Jacke
+ </string>
+ <string name="gloves">
+ Handschuhe
+ </string>
+ <string name="undershirt">
+ Unterhemd
+ </string>
+ <string name="underpants">
+ Unterhose
+ </string>
+ <string name="skirt">
+ Rock
+ </string>
+ <string name="alpha">
+ Alpha
+ </string>
+ <string name="tattoo">
+ Tätowierung
+ </string>
+ <string name="invalid">
+ ungültig
+ </string>
+ <string name="next">
+ Weiter
+ </string>
+ <string name="ok">
+ OK
+ </string>
+ <string name="GroupNotifyGroupNotice">
+ Gruppenmitteilung
+ </string>
+ <string name="GroupNotifyGroupNotices">
+ Gruppenmitteilungen
+ </string>
+ <string name="GroupNotifySentBy">
+ Gesendet von
+ </string>
+ <string name="GroupNotifyAttached">
+ Im Anhang:
+ </string>
+ <string name="GroupNotifyViewPastNotices">
+ Alte Mitteilungen anzeigen oder hier Auswahl treffen, um keine Mitteilungen mehr zu erhalten.
+ </string>
+ <string name="GroupNotifyOpenAttachment">
+ Anlage öffnen
+ </string>
+ <string name="GroupNotifySaveAttachment">
+ Siehe Anhang
+ </string>
+ <string name="TeleportOffer">
+ Teleport-Angebot
+ </string>
+ <string name="StartUpNotifications">
+ Sie haben neue Benachrichtigungen erhalten, während Sie abwesend waren.
+ </string>
+ <string name="OverflowInfoChannelString">
+ Sie haben noch %d weitere Benachrichtigungen
+ </string>
+ <string name="BodyPartsRightArm">
+ Rechter Arm
+ </string>
+ <string name="BodyPartsHead">
+ Kopf
+ </string>
+ <string name="BodyPartsLeftArm">
+ Linker Arm
+ </string>
+ <string name="BodyPartsLeftLeg">
+ Linkes Bein
+ </string>
+ <string name="BodyPartsTorso">
+ Oberkörper
+ </string>
+ <string name="BodyPartsRightLeg">
+ Rechtes Bein
+ </string>
+ <string name="GraphicsQualityLow">
+ Niedrig
+ </string>
+ <string name="GraphicsQualityMid">
+ Mittel
+ </string>
+ <string name="GraphicsQualityHigh">
+ Hoch
+ </string>
+ <string name="LeaveMouselook">
+ ESC drücken, um zur Normalansicht zurückzukehren
+ </string>
+ <string name="InventoryNoMatchingItems">
+ Im Inventar wurden keine passenden Artikel gefunden.
+ </string>
+ <string name="InventoryNoTexture">
+ Sie haben keine Kopie dieser Textur in Ihrem Inventar.
+ </string>
+ <string name="no_transfer" value=" (kein Transferieren)"/>
+ <string name="no_modify" value=" (kein Bearbeiten)"/>
+ <string name="no_copy" value=" (kein Kopieren)"/>
+ <string name="worn" value=" (getragen)"/>
+ <string name="link" value=" (Link)"/>
+ <string name="broken_link" value=" (unvollständiger_Link)"/>
+ <string name="LoadingContents">
+ Inhalte werden geladen...
+ </string>
+ <string name="NoContents">
+ Keine Inhalte
+ </string>
+ <string name="WornOnAttachmentPoint" value=" (getragen am [ATTACHMENT_POINT])"/>
+ <string name="PermYes">
+ Ja
+ </string>
+ <string name="PermNo">
+ Nein
+ </string>
+ <string name="Chat" value=" Chat:"/>
+ <string name="Sound" value=" Sound:"/>
+ <string name="Wait" value=" --- Warten:"/>
+ <string name="AnimFlagStop" value=" Animation stoppen:"/>
+ <string name="AnimFlagStart" value=" Animation starten:"/>
+ <string name="Wave" value=" Winken"/>
+ <string name="HelloAvatar" value=" Hallo Avatar!"/>
+ <string name="ViewAllGestures" value=" Alle anzeigen &gt;&gt;"/>
+ <string name="Animations" value=" Animationen,"/>
+ <string name="Calling Cards" value=" Visitenkarten,"/>
+ <string name="Clothing" value=" Kleidung,"/>
+ <string name="Gestures" value=" Gesten,"/>
+ <string name="Landmarks" value=" Landmarken,"/>
+ <string name="Notecards" value=" Notizkarten,"/>
+ <string name="Objects" value=" Objekte,"/>
+ <string name="Scripts" value=" Skripts,"/>
+ <string name="Sounds" value=" Sounds,"/>
+ <string name="Textures" value=" Texturen,"/>
+ <string name="Snapshots" value=" Fotos,"/>
+ <string name="No Filters" value="Nein "/>
+ <string name="Since Logoff" value=" - Seit Abmeldung"/>
+ <string name="InvFolder My Inventory">
+ Mein Inventar
+ </string>
+ <string name="InvFolder My Favorites">
+ Meine Favoriten
+ </string>
+ <string name="InvFolder Library">
+ Bibliothek
+ </string>
+ <string name="InvFolder Textures">
+ Texturen
+ </string>
+ <string name="InvFolder Sounds">
+ Sounds
+ </string>
+ <string name="InvFolder Calling Cards">
+ Visitenkarten
+ </string>
+ <string name="InvFolder Landmarks">
+ Landmarken
+ </string>
+ <string name="InvFolder Scripts">
+ Skripts
+ </string>
+ <string name="InvFolder Clothing">
+ Kleidung
+ </string>
+ <string name="InvFolder Objects">
+ Objekte
+ </string>
+ <string name="InvFolder Notecards">
+ Notizkarten
+ </string>
+ <string name="InvFolder New Folder">
+ Neuer Ordner
+ </string>
+ <string name="InvFolder Inventory">
+ Inventar
+ </string>
+ <string name="InvFolder Uncompressed Images">
+ Nicht-Komprimierte Bilder
+ </string>
+ <string name="InvFolder Body Parts">
+ Körperteile
+ </string>
+ <string name="InvFolder Trash">
+ Papierkorb
+ </string>
+ <string name="InvFolder Photo Album">
+ Fotoalbum
+ </string>
+ <string name="InvFolder Lost And Found">
+ Fundbüro
+ </string>
+ <string name="InvFolder Uncompressed Sounds">
+ Nicht-Komprimierte Sounds
+ </string>
+ <string name="InvFolder Animations">
+ Animationen
+ </string>
+ <string name="InvFolder Gestures">
+ Gesten
+ </string>
+ <string name="InvFolder favorite">
+ Favoriten
+ </string>
+ <string name="InvFolder Current Outfit">
+ Aktuelles Outfit
+ </string>
+ <string name="InvFolder My Outfits">
+ Meine Outfits
+ </string>
+ <string name="InvFolder Friends">
+ Freunde
+ </string>
+ <string name="InvFolder All">
+ Alle
+ </string>
+ <string name="Buy">
+ Kaufen
+ </string>
+ <string name="BuyforL$">
+ Kaufen für L$
+ </string>
+ <string name="Stone">
+ Stein
+ </string>
+ <string name="Metal">
+ Metall
+ </string>
+ <string name="Glass">
+ Glas
+ </string>
+ <string name="Wood">
+ Holz
+ </string>
+ <string name="Flesh">
+ Fleisch
+ </string>
+ <string name="Plastic">
+ Plastik
+ </string>
+ <string name="Rubber">
+ Gummi
+ </string>
+ <string name="Light">
+ Licht
+ </string>
+ <string name="KBShift">
+ Umschalt-Taste
+ </string>
+ <string name="KBCtrl">
+ Strg
+ </string>
+ <string name="Chest">
+ Brust
+ </string>
+ <string name="Skull">
+ Schädel
+ </string>
+ <string name="Left Shoulder">
+ Linke Schulter
+ </string>
+ <string name="Right Shoulder">
+ Rechte Schulter
+ </string>
+ <string name="Left Hand">
+ Linke Hand
+ </string>
+ <string name="Right Hand">
+ Rechte Hand
+ </string>
+ <string name="Left Foot">
+ Linker Fuß
+ </string>
+ <string name="Right Foot">
+ Rechter Fuß
+ </string>
+ <string name="Spine">
+ Wirbelsäule
+ </string>
+ <string name="Pelvis">
+ Becken
+ </string>
+ <string name="Mouth">
+ Mund
+ </string>
+ <string name="Chin">
+ Kinn
+ </string>
+ <string name="Left Ear">
+ Linkes Ohr
+ </string>
+ <string name="Right Ear">
+ Rechtes Ohr
+ </string>
+ <string name="Left Eyeball">
+ Linker Augapfel
+ </string>
+ <string name="Right Eyeball">
+ Rechter Augapfel
+ </string>
+ <string name="Nose">
+ Nase
+ </string>
+ <string name="R Upper Arm">
+ R Oberarm
+ </string>
+ <string name="R Forearm">
+ R Unterarm
+ </string>
+ <string name="L Upper Arm">
+ L Oberarm
+ </string>
+ <string name="L Forearm">
+ L Unterarm
+ </string>
+ <string name="Right Hip">
+ Rechte Hüfte
+ </string>
+ <string name="R Upper Leg">
+ R Oberschenkel
+ </string>
+ <string name="R Lower Leg">
+ R Unterschenkel
+ </string>
+ <string name="Left Hip">
+ Linke Hüfte
+ </string>
+ <string name="L Upper Leg">
+ L Oberschenkel
+ </string>
+ <string name="L Lower Leg">
+ L Unterschenkel
+ </string>
+ <string name="Stomach">
+ Bauch
+ </string>
+ <string name="Left Pec">
+ Linke Brust
+ </string>
+ <string name="Right Pec">
+ Rechts
+ </string>
+ <string name="YearsMonthsOld">
+ [AGEYEARS] [AGEMONTHS] alt
+ </string>
+ <string name="YearsOld">
+ [AGEYEARS] alt
+ </string>
+ <string name="MonthsOld">
+ [AGEMONTHS] alt
+ </string>
+ <string name="WeeksOld">
+ [AGEWEEKS] alt
+ </string>
+ <string name="DaysOld">
+ [AGEDAYS] alt
+ </string>
+ <string name="TodayOld">
+ Seit heute Mitglied
+ </string>
+ <string name="AgeYearsA">
+ [COUNT] Jahr
+ </string>
+ <string name="AgeYearsB">
+ [COUNT] Jahre
+ </string>
+ <string name="AgeYearsC">
+ [COUNT] Jahre
+ </string>
+ <string name="AgeMonthsA">
+ [COUNT] Monat
+ </string>
+ <string name="AgeMonthsB">
+ [COUNT] Monate
+ </string>
+ <string name="AgeMonthsC">
+ [COUNT] Monate
+ </string>
+ <string name="AgeWeeksA">
+ [COUNT] Woche
+ </string>
+ <string name="AgeWeeksB">
+ [COUNT] Wochen
+ </string>
+ <string name="AgeWeeksC">
+ [COUNT] Wochen
+ </string>
+ <string name="AgeDaysA">
+ [COUNT] Tag
+ </string>
+ <string name="AgeDaysB">
+ [COUNT] Tage
+ </string>
+ <string name="AgeDaysC">
+ [COUNT] Tage
+ </string>
+ <string name="GroupMembersA">
+ [COUNT] Mitglied
+ </string>
+ <string name="GroupMembersB">
+ [COUNT] Mitglieder
+ </string>
+ <string name="GroupMembersC">
+ [COUNT] Mitglieder
+ </string>
+ <string name="AcctTypeResident">
+ Einwohner
+ </string>
+ <string name="AcctTypeTrial">
+ Test
+ </string>
+ <string name="AcctTypeCharterMember">
+ Charta-Mitglied
+ </string>
+ <string name="AcctTypeEmployee">
+ Linden Lab-Mitarbeiter
+ </string>
+ <string name="PaymentInfoUsed">
+ Zahlungsinfo verwendet
+ </string>
+ <string name="PaymentInfoOnFile">
+ Zahlungsinfo archiviert
+ </string>
+ <string name="NoPaymentInfoOnFile">
+ Keine Zahlungsinfo archiviert
+ </string>
+ <string name="AgeVerified">
+ Altersgeprüft
+ </string>
+ <string name="NotAgeVerified">
+ Nicht altersgeprüft
+ </string>
+ <string name="Center 2">
+ Mitte 2
+ </string>
+ <string name="Top Right">
+ Oben rechts
+ </string>
+ <string name="Top">
+ Oben
+ </string>
+ <string name="Top Left">
+ Oben links
+ </string>
+ <string name="Center">
+ Zentrieren
+ </string>
+ <string name="Bottom Left">
+ Unten links
+ </string>
+ <string name="Bottom">
+ Unten
+ </string>
+ <string name="Bottom Right">
+ Unten rechts
+ </string>
+ <string name="CompileQueueDownloadedCompiling">
+ Heruntergeladen, wird kompiliert
+ </string>
+ <string name="CompileQueueScriptNotFound">
+ Skript wurde auf Server nicht gefunden.
+ </string>
+ <string name="CompileQueueProblemDownloading">
+ Beim Herunterladen ist ein Problem aufgetreten
+ </string>
+ <string name="CompileQueueInsufficientPermDownload">
+ Unzureichende Rechte zum Herunterladen eines Skripts.
+ </string>
+ <string name="CompileQueueInsufficientPermFor">
+ Unzureichende Berechtigungen für
+ </string>
+ <string name="CompileQueueUnknownFailure">
+ Unbekannter Fehler beim Herunterladen
+ </string>
+ <string name="CompileQueueTitle">
+ Rekompilierung
+ </string>
+ <string name="CompileQueueStart">
+ rekompilieren
+ </string>
+ <string name="ResetQueueTitle">
+ Zurücksetzen
+ </string>
+ <string name="ResetQueueStart">
+ Zurücksetzen
+ </string>
+ <string name="RunQueueTitle">
+ Skript ausführen
+ </string>
+ <string name="RunQueueStart">
+ Skript ausführen
+ </string>
+ <string name="NotRunQueueTitle">
+ Skript anhalten
+ </string>
+ <string name="NotRunQueueStart">
+ Skript anhalten
+ </string>
+ <string name="CompileSuccessful">
+ Kompilieren erfolgreich abgeschlossen!
+ </string>
+ <string name="CompileSuccessfulSaving">
+ Kompilieren erfolgreich abgeschlossen, speichern...
+ </string>
+ <string name="SaveComplete">
+ Speichervorgang abgeschlossen.
+ </string>
+ <string name="ObjectOutOfRange">
+ Skript (Objekt außerhalb des Bereichs)
+ </string>
+ <string name="GodToolsObjectOwnedBy">
+ Objekt [OBJECT], Besitzer [OWNER]
+ </string>
+ <string name="GroupsNone">
+ keine
+ </string>
+ <string name="Group" value=" (Gruppe)"/>
+ <string name="Unknown">
+ (unbekannt)
+ </string>
+ <string name="SummaryForTheWeek" value="Zusammenfassung für diese Woche, beginnend am "/>
+ <string name="NextStipendDay" value="Der nächste Stipendium-Tag ist "/>
+ <string name="GroupIndividualShare" value=" Gruppenanteil Einzelanteil"/>
+ <string name="Balance">
+ Kontostand
+ </string>
+ <string name="Credits">
+ Danksagung
+ </string>
+ <string name="Debits">
+ Soll
+ </string>
+ <string name="Total">
+ Gesamtbetrag
+ </string>
+ <string name="NoGroupDataFound">
+ Für Gruppe wurden keine Gruppendaten gefunden
+ </string>
+ <string name="IMParentEstate">
+ parent estate
+ </string>
+ <string name="IMMainland">
+ Mainland
+ </string>
+ <string name="IMTeen">
+ Teen
+ </string>
+ <string name="RegionInfoError">
+ Fehler
+ </string>
+ <string name="RegionInfoAllEstatesOwnedBy">
+ alle Grundstücke gehören [OWNER]
+ </string>
+ <string name="RegionInfoAllEstatesYouOwn">
+ alle Grundstücke, die Sie besitzen
+ </string>
+ <string name="RegionInfoAllEstatesYouManage">
+ alle Grundstücke, die Sie für [OWNER] verwalten
+ </string>
+ <string name="RegionInfoAllowedResidents">
+ Zulässige Einwohner: ([ALLOWEDAGENTS], max [MAXACCESS])
+ </string>
+ <string name="RegionInfoAllowedGroups">
+ Zulässige Gruppen: ([ALLOWEDGROUPS], max [MAXACCESS])
+ </string>
+ <string name="CursorPos">
+ Zeile [LINE], Spalte [COLUMN]
+ </string>
+ <string name="PanelDirCountFound">
+ [COUNT] gefunden
+ </string>
+ <string name="PanelDirTimeStr">
+ [hour12,datetime,slt]:[min,datetime,slt] [ampm,datetime,slt]
+ </string>
+ <string name="PanelDirEventsDateText">
+ [mthnum,datetime,slt]/[day,datetime,slt]
+ </string>
+ <string name="PanelContentsNewScript">
+ Neues Skript
+ </string>
+ <string name="MuteByName">
+ (nach Namen)
+ </string>
+ <string name="MuteAgent">
+ (Einwohner)
+ </string>
+ <string name="MuteObject">
+ (Objekt)
+ </string>
+ <string name="MuteGroup">
+ (Gruppe)
+ </string>
+ <string name="RegionNoCovenant">
+ Für dieses Grundstück liegt kein Vertrag vor.
+ </string>
+ <string name="RegionNoCovenantOtherOwner">
+ Für dieses Grundstück liegt kein Vertrag vor. Das Land auf diesem Grundstück wird vom Grundstückseigentümer und nicht von Linden Lab verkauft. Für Informationen zum Verkauf setzen Sie sich bitte mit dem Grundstückseigentümer in Verbindung.
+ </string>
+ <string name="covenant_last_modified">
+ Zuletzt geändert:
+ </string>
+ <string name="none_text" value=" (keiner)"/>
+ <string name="never_text" value=" (nie)"/>
+ <string name="GroupOwned">
+ In Gruppenbesitz
+ </string>
+ <string name="Public">
+ Öffentlich
+ </string>
+ <string name="ClassifiedClicksTxt">
+ Klicks: [TELEPORT] teleportieren, [MAP] Karte, [PROFILE] Profil
+ </string>
+ <string name="ClassifiedUpdateAfterPublish">
+ (wird nach Veröffentlichung aktualisiert)
+ </string>
+ <string name="MultiPreviewTitle">
+ Vorschau
+ </string>
+ <string name="MultiPropertiesTitle">
+ Eigenschaften
+ </string>
+ <string name="InvOfferAnObjectNamed">
+ Ein Objekt namens
+ </string>
+ <string name="InvOfferOwnedByGroup">
+ im Besitz der Gruppe
+ </string>
+ <string name="InvOfferOwnedByUnknownGroup">
+ im Besitz einer unbekannten Gruppe
+ </string>
+ <string name="InvOfferOwnedBy">
+ im Besitz von
+ </string>
+ <string name="InvOfferOwnedByUnknownUser">
+ im Besitz eines unbekannten Einwohners
+ </string>
+ <string name="InvOfferGaveYou">
+ hat Ihnen folgendes übergeben
+ </string>
+ <string name="InvOfferYouDecline">
+ Sie lehnen folgendes ab:
+ </string>
+ <string name="InvOfferFrom">
+ von
+ </string>
+ <string name="GroupMoneyTotal">
+ Gesamtbetrag
+ </string>
+ <string name="GroupMoneyBought">
+ gekauft
+ </string>
+ <string name="GroupMoneyPaidYou">
+ bezahlte Ihnen
+ </string>
+ <string name="GroupMoneyPaidInto">
+ bezahlte an
+ </string>
+ <string name="GroupMoneyBoughtPassTo">
+ kaufte Pass für
+ </string>
+ <string name="GroupMoneyPaidFeeForEvent">
+ bezahlte Gebühr für Event
+ </string>
+ <string name="GroupMoneyPaidPrizeForEvent">
+ bezahlte Preis für Event
+ </string>
+ <string name="GroupMoneyBalance">
+ Kontostand
+ </string>
+ <string name="GroupMoneyCredits">
+ Danksagung
+ </string>
+ <string name="GroupMoneyDebits">
+ Soll
+ </string>
+ <string name="ViewerObjectContents">
+ Inhalte
+ </string>
+ <string name="AcquiredItems">
+ Erworbene Artikel
+ </string>
+ <string name="Cancel">
+ Abbrechen
+ </string>
+ <string name="UploadingCosts">
+ Hochladen von %s kostet
+ </string>
+ <string name="UnknownFileExtension">
+ Unbekanntes Dateiformat .%s
+Gültige Formate: .wav, .tga, .bmp, .jpg, .jpeg oder .bvh
+ </string>
+ <string name="AddLandmarkNavBarMenu">
+ Landmarke hinzufügen...
+ </string>
+ <string name="EditLandmarkNavBarMenu">
+ Landmarke bearbeiten...
+ </string>
+ <string name="accel-mac-control">
+ &#8963;
+ </string>
+ <string name="accel-mac-command">
+ &#8984;
+ </string>
+ <string name="accel-mac-option">
+ &#8997;
+ </string>
+ <string name="accel-mac-shift">
+ &#8679;
+ </string>
+ <string name="accel-win-control">
+ Strg+
+ </string>
+ <string name="accel-win-alt">
+ Alt+
+ </string>
+ <string name="accel-win-shift">
+ Umschalt+
+ </string>
+ <string name="FileSaved">
+ Datei wurde gespeichert
+ </string>
+ <string name="Receiving">
+ Daten werden empfangen
+ </string>
+ <string name="AM">
+ Uhr
+ </string>
+ <string name="PM">
+ Uhr
+ </string>
+ <string name="PST">
+ PST
+ </string>
+ <string name="PDT">
+ PDT
+ </string>
+ <string name="Forward">
+ Vorwärts
+ </string>
+ <string name="Left">
+ Links
+ </string>
+ <string name="Right">
+ Rechts
+ </string>
+ <string name="Back">
+ Hinten
+ </string>
+ <string name="North">
+ Norden
+ </string>
+ <string name="South">
+ Süden
+ </string>
+ <string name="West">
+ Westen
+ </string>
+ <string name="East">
+ Osten
+ </string>
+ <string name="Up">
+ Nach oben
+ </string>
+ <string name="Down">
+ Nach unten
+ </string>
+ <string name="Any Category">
+ Alle Kategorien
+ </string>
+ <string name="Shopping">
+ Shopping
+ </string>
+ <string name="Land Rental">
+ Land mieten
+ </string>
+ <string name="Property Rental">
+ Immobilie mieten
+ </string>
+ <string name="Special Attraction">
+ Attraktionen
+ </string>
+ <string name="New Products">
+ Neue Produkte
+ </string>
+ <string name="Employment">
+ Stellenangebote
+ </string>
+ <string name="Wanted">
+ Gesucht
+ </string>
+ <string name="Service">
+ Dienstleistungen
+ </string>
+ <string name="Personal">
+ Sonstiges
+ </string>
+ <string name="None">
+ Keiner
+ </string>
+ <string name="Linden Location">
+ Lindenort
+ </string>
+ <string name="Adult">
+ Adult
+ </string>
+ <string name="Arts&amp;Culture">
+ Kunst &amp; Kultur
+ </string>
+ <string name="Business">
+ Firmen
+ </string>
+ <string name="Educational">
+ Bildung
+ </string>
+ <string name="Gaming">
+ Spielen
+ </string>
+ <string name="Hangout">
+ Treffpunkt
+ </string>
+ <string name="Newcomer Friendly">
+ Anfängergerecht
+ </string>
+ <string name="Parks&amp;Nature">
+ Parks und Natur
+ </string>
+ <string name="Residential">
+ Wohngebiet
+ </string>
+ <string name="Stage">
+ Phase
+ </string>
+ <string name="Other">
+ Sonstige
+ </string>
+ <string name="Any">
+ Alle
+ </string>
+ <string name="You">
+ Sie
+ </string>
+ <string name=":">
+ :
+ </string>
+ <string name=",">
+ ,
+ </string>
+ <string name="...">
+ ...
+ </string>
+ <string name="***">
+ ***
+ </string>
+ <string name="(">
+ (
+ </string>
+ <string name=")">
+ )
+ </string>
+ <string name=".">
+ .
+ </string>
+ <string name="&apos;">
+ &apos;
+ </string>
+ <string name="---">
+ ---
+ </string>
+ <string name="Multiple Media">
+ Mehrere Medien
+ </string>
+ <string name="Play Media">
+ Medien Abspielen/Pausieren
+ </string>
+ <string name="MBCmdLineError">
+ Beim Parsen der Befehlszeile wurde ein Fehler festgestellt.
+Weitere Informationen: http://wiki.secondlife.com/wiki/Client_parameters (EN)
+Fehler:
+ </string>
+ <string name="MBCmdLineUsg">
+ [APP_NAME] Verwendung in Befehlszeile:
+ </string>
+ <string name="MBUnableToAccessFile">
+ [APP_NAME] kann auf die erforderliche Datei nicht zugreifen.
+
+Grund hierfür ist, dass Sie entweder mehrere Instanzen gleichzeitig ausführen oder dass Ihr System denkt, eine Datei sei geöffnet.
+Falls diese Nachricht erneut angezeigt wird, starten Sie bitte Ihren Computer neu und probieren Sie es noch einmal.
+Falls der Fehler dann weiterhin auftritt, müssen Sie [APP_NAME] von Ihrem System de-installieren und erneut installieren.
+ </string>
+ <string name="MBFatalError">
+ Unbehebbarer Fehler
+ </string>
+ <string name="MBRequiresAltiVec">
+ [APP_NAME] erfordert einen Prozessor mit AltiVec (G4 oder später).
+ </string>
+ <string name="MBAlreadyRunning">
+ [APP_NAME] läuft bereits.
+Bitte sehen Sie in Ihrer Menüleiste nach, dort sollte ein Symbol für das Programm angezeigt werden.
+Falls diese Nachricht erneut angezeigt wird, starten Sie Ihren Computer bitte neu.
+ </string>
+ <string name="MBFrozenCrashed">
+ [APP_NAME] scheint eingefroren zu sein oder ist abgestürzt.
+Möchten Sie einen Absturz-Bericht einschicken?
+ </string>
+ <string name="MBAlert">
+ Alarm
+ </string>
+ <string name="MBNoDirectX">
+ [APP_NAME] kann DirectX 9.0b oder höher nicht feststellen.
+[APP_NAME] verwendet DirectX, um nach Hardware und/oder veralteten Treibern zu suchen, die zu Problemen mit der Stabilität, Leistung und Abstürzen führen können. Sie können [APP_NAME] auch so ausführen, wir empfehlen jedoch, dass DirectX 9.0b vorhanden ist und ausgeführt wird.
+
+Möchten Sie fortfahren?
+ </string>
+ <string name="MBWarning">
+ Hinweis
+ </string>
+ <string name="MBNoAutoUpdate">
+ Für Linux ist zur Zeit noch kein automatisches Aktualisieren möglich.
+Bitte laden Sie die aktuellste Version von www.secondlife.com herunter.
+ </string>
+ <string name="MBRegClassFailed">
+ RegisterClass fehlgeschlagen
+ </string>
+ <string name="MBError">
+ Fehler
+ </string>
+ <string name="MBFullScreenErr">
+ Vollbildschirm mit [WIDTH] x [HEIGHT] kann nicht ausgeführt werden.
+Ausführung erfolgt in Fenster.
+ </string>
+ <string name="MBDestroyWinFailed">
+ Fehler beim Herunterfahren während Fenster geschlossen wurde (DestroyWindow() fehlgeschlagen)
+ </string>
+ <string name="MBShutdownErr">
+ Fehler beim Herunterfahren
+ </string>
+ <string name="MBDevContextErr">
+ Kann keinen Kontext für GL-Gerät erstellen
+ </string>
+ <string name="MBPixelFmtErr">
+ Passendes Pixelformat wurde nicht gefunden
+ </string>
+ <string name="MBPixelFmtDescErr">
+ Beschreibung für Pixelformat nicht verfügbar
+ </string>
+ <string name="MBTrueColorWindow">
+ Um [APP_NAME] auszuführen, ist True Color (32-bit) erforderlich.
+Klicken Sie öffnen Sie auf Ihrem Computer die Einstellungen für die Anzeige und stellen Sie den Bildschirm auf 32-bit Farbe ein.
+ </string>
+ <string name="MBAlpha">
+ [APP_NAME] kann nicht ausgeführt werden, da kein 8-Bit-Alpha-Kanal verfügbar ist. Dies geschieht normalerweise bei Problemen mit dem Treiber der Video-Karte.
+Bitte vergewissern Sie sich, dass Sie die aktuellsten Treiber für Ihre Videokarte installiert haben.
+Vergewissern Sie sich außerdem, dass Ihr Bildschirm auf True Color (32-Bit) eingestellt ist (Systemsteuerung &gt; Anzeige &gt; Einstellungen).
+Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich bitte an [SUPPORT_SITE].
+ </string>
+ <string name="MBPixelFmtSetErr">
+ Pixel-Format kann nicht eingestellt werden.
+ </string>
+ <string name="MBGLContextErr">
+ Kann keinen Kontext für GL-Gerät erstellen
+ </string>
+ <string name="MBGLContextActErr">
+ Kann keinen Kontext für GL-Gerät aktivieren
+ </string>
+ <string name="MBVideoDrvErr">
+ [APP_NAME] kann nicht ausgeführt werden, da die Treiber Ihrer Videokarte entweder nicht richtig installiert oder veraltet sind, oder die entsprechende Hardware nicht unterstützt wird. Bitte vergewissern Sie sich, dass Sie die aktuellsten Treiber für die Videokarte installiert haben. Falls Sie die aktuellsten Treiber bereits installiert haben, installieren Sie diese bitte erneut.
+
+Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich bitte an [SUPPORT_SITE].
+ </string>
+ <string name="5 O&apos;Clock Shadow">
+ Bartschatten
+ </string>
+ <string name="All White">
+ Ganz weiß
+ </string>
+ <string name="Anime Eyes">
+ Anime-Augen
+ </string>
+ <string name="Arced">
+ Gewölbt
+ </string>
+ <string name="Arm Length">
+ Armlänge
+ </string>
+ <string name="Attached">
+ Angewachsen
+ </string>
+ <string name="Attached Earlobes">
+ Angewachsene Ohrläppchen
+ </string>
+ <string name="Back Fringe">
+ Nackenfransen
+ </string>
+ <string name="Baggy">
+ Tränensäcke
+ </string>
+ <string name="Bangs">
+ Pony
+ </string>
+ <string name="Beady Eyes">
+ Knopfaugen
+ </string>
+ <string name="Belly Size">
+ Bauchgröße
+ </string>
+ <string name="Big">
+ Groß
+ </string>
+ <string name="Big Butt">
+ Großer Hintern
+ </string>
+ <string name="Big Hair Back">
+ Volumen: Hinten
+ </string>
+ <string name="Big Hair Front">
+ Volumen: Vorne
+ </string>
+ <string name="Big Hair Top">
+ Volumen: Oben
+ </string>
+ <string name="Big Head">
+ Großer Kopf
+ </string>
+ <string name="Big Pectorals">
+ Große Brustmuskeln
+ </string>
+ <string name="Big Spikes">
+ Große Stacheln
+ </string>
+ <string name="Black">
+ Schwarz
+ </string>
+ <string name="Blonde">
+ Blond
+ </string>
+ <string name="Blonde Hair">
+ Blondes Haar
+ </string>
+ <string name="Blush">
+ Rouge
+ </string>
+ <string name="Blush Color">
+ Rougefarbe
+ </string>
+ <string name="Blush Opacity">
+ Rouge Deckkraft
+ </string>
+ <string name="Body Definition">
+ Körperkonturen
+ </string>
+ <string name="Body Fat">
+ Körperfett
+ </string>
+ <string name="Body Freckles">
+ Sommersprossen
+ </string>
+ <string name="Body Thick">
+ Körper - breit
+ </string>
+ <string name="Body Thickness">
+ Körperbreite
+ </string>
+ <string name="Body Thin">
+ Körper - schmal
+ </string>
+ <string name="Bow Legged">
+ o-beinig
+ </string>
+ <string name="Breast Buoyancy">
+ Brust, Straffheit
+ </string>
+ <string name="Breast Cleavage">
+ Dekolleté
+ </string>
+ <string name="Breast Size">
+ Brustgröße
+ </string>
+ <string name="Bridge Width">
+ Rückenbreite
+ </string>
+ <string name="Broad">
+ Breit
+ </string>
+ <string name="Brow Size">
+ Brauengröße
+ </string>
+ <string name="Bug Eyes">
+ Glubschaugen
+ </string>
+ <string name="Bugged Eyes">
+ Hervortretend
+ </string>
+ <string name="Bulbous">
+ Knollennase
+ </string>
+ <string name="Bulbous Nose">
+ Knollennase
+ </string>
+ <string name="Bushy Eyebrows">
+ Buschige Augenbrauen
+ </string>
+ <string name="Bushy Hair">
+ Buschiges Haar
+ </string>
+ <string name="Butt Size">
+ Hintern, Größe
+ </string>
+ <string name="bustle skirt">
+ Tournürenrock
+ </string>
+ <string name="no bustle">
+ Ohne
+ </string>
+ <string name="more bustle">
+ Mit
+ </string>
+ <string name="Chaplin">
+ Chaplin
+ </string>
+ <string name="Cheek Bones">
+ Wangenknochen
+ </string>
+ <string name="Chest Size">
+ Brustgröße
+ </string>
+ <string name="Chin Angle">
+ Kinnwinkel
+ </string>
+ <string name="Chin Cleft">
+ Kinnspalte
+ </string>
+ <string name="Chin Curtains">
+ Schifferfräse
+ </string>
+ <string name="Chin Depth">
+ Kinnlänge
+ </string>
+ <string name="Chin Heavy">
+ Kinn ausgeprägt
+ </string>
+ <string name="Chin In">
+ Kinn zurück
+ </string>
+ <string name="Chin Out">
+ Kinn nach vorne
+ </string>
+ <string name="Chin-Neck">
+ Kinn-Hals
+ </string>
+ <string name="Clear">
+ Löschen
+ </string>
+ <string name="Cleft">
+ Spalte
+ </string>
+ <string name="Close Set Eyes">
+ Eng stehende Augen
+ </string>
+ <string name="Closed">
+ Geschlossen
+ </string>
+ <string name="Closed Back">
+ Hinten geschlossen
+ </string>
+ <string name="Closed Front">
+ Vorne geschlossen
+ </string>
+ <string name="Closed Left">
+ Links geschlossen
+ </string>
+ <string name="Closed Right">
+ Rechts geschlossen
+ </string>
+ <string name="Coin Purse">
+ Klein
+ </string>
+ <string name="Collar Back">
+ Kragen hinten
+ </string>
+ <string name="Collar Front">
+ Kragen vorne
+ </string>
+ <string name="Corner Down">
+ Nach unten
+ </string>
+ <string name="Corner Up">
+ Nach oben
+ </string>
+ <string name="Creased">
+ Schlupflid
+ </string>
+ <string name="Crooked Nose">
+ Krumme Nase
+ </string>
+ <string name="Cuff Flare">
+ Hosenaufschlag
+ </string>
+ <string name="Dark">
+ Dunkel
+ </string>
+ <string name="Dark Green">
+ Dunkelgrün
+ </string>
+ <string name="Darker">
+ Dunkler
+ </string>
+ <string name="Deep">
+ Tief
+ </string>
+ <string name="Default Heels">
+ Standardabsätze
+ </string>
+ <string name="Dense">
+ Dicht
+ </string>
+ <string name="Double Chin">
+ Doppelkinn
+ </string>
+ <string name="Downturned">
+ Nach unten
+ </string>
+ <string name="Duffle Bag">
+ Groß
+ </string>
+ <string name="Ear Angle">
+ Ohrenwinkel
+ </string>
+ <string name="Ear Size">
+ Ohrengröße
+ </string>
+ <string name="Ear Tips">
+ Ohrenspitzen
+ </string>
+ <string name="Egg Head">
+ Eierkopf
+ </string>
+ <string name="Eye Bags">
+ Augenränder
+ </string>
+ <string name="Eye Color">
+ Augenfarbe
+ </string>
+ <string name="Eye Depth">
+ Augentiefe
+ </string>
+ <string name="Eye Lightness">
+ Helligkeit
+ </string>
+ <string name="Eye Opening">
+ Öffnung
+ </string>
+ <string name="Eye Pop">
+ Symmetrie
+ </string>
+ <string name="Eye Size">
+ Augengröße
+ </string>
+ <string name="Eye Spacing">
+ Augenstand
+ </string>
+ <string name="Eyebrow Arc">
+ Brauenbogen
+ </string>
+ <string name="Eyebrow Density">
+ Brauendichte
+ </string>
+ <string name="Eyebrow Height">
+ Brauenhöhe
+ </string>
+ <string name="Eyebrow Points">
+ Brauenenden
+ </string>
+ <string name="Eyebrow Size">
+ Brauengröße
+ </string>
+ <string name="Eyelash Length">
+ Wimpernlänge
+ </string>
+ <string name="Eyeliner">
+ Eyeliner
+ </string>
+ <string name="Eyeliner Color">
+ Farbe des Eyeliners
+ </string>
+ <string name="Eyes Bugged">
+ Glubschaugen
+ </string>
+ <string name="Eyes Shear Left Up">
+ Augen Verzerrung links hoch
+ </string>
+ <string name="Eyes Shear Right Up">
+ Augen Verzerrung rechts hoch
+ </string>
+ <string name="Face Shear">
+ Gesichtsverzerrung
+ </string>
+ <string name="Facial Definition">
+ Gesichtskonturen
+ </string>
+ <string name="Far Set Eyes">
+ Weit auseinander
+ </string>
+ <string name="Fat Lips">
+ Volle Lippen
+ </string>
+ <string name="Female">
+ weiblich
+ </string>
+ <string name="Fingerless">
+ Ohne Finger
+ </string>
+ <string name="Fingers">
+ Finger
+ </string>
+ <string name="Flared Cuffs">
+ Ausgestellt
+ </string>
+ <string name="Flat">
+ Flach
+ </string>
+ <string name="Flat Butt">
+ Flacher Hintern
+ </string>
+ <string name="Flat Head">
+ Flacher Kopf
+ </string>
+ <string name="Flat Toe">
+ Flache Spitze
+ </string>
+ <string name="Foot Size">
+ Fußgröße
+ </string>
+ <string name="Forehead Angle">
+ Stirnwinkel
+ </string>
+ <string name="Forehead Heavy">
+ Stirn ausgeprägt
+ </string>
+ <string name="Freckles">
+ Sommersprossen
+ </string>
+ <string name="Front Fringe">
+ Fransen, vorne
+ </string>
+ <string name="Full Back">
+ Hinten volles Haar
+ </string>
+ <string name="Full Eyeliner">
+ Starker Eyeliner
+ </string>
+ <string name="Full Front">
+ Vorne volles Haar
+ </string>
+ <string name="Full Hair Sides">
+ Seitlich volles Haar
+ </string>
+ <string name="Full Sides">
+ Volle Seiten
+ </string>
+ <string name="Glossy">
+ Glänzend
+ </string>
+ <string name="Glove Fingers">
+ Handschuhfinger
+ </string>
+ <string name="Glove Length">
+ Handschuhlänge
+ </string>
+ <string name="Hair">
+ Haare
+ </string>
+ <string name="Hair Back">
+ Haare: Hinten
+ </string>
+ <string name="Hair Front">
+ Haare: Vorne
+ </string>
+ <string name="Hair Sides">
+ Haare: Seiten
+ </string>
+ <string name="Hair Sweep">
+ Haartolle
+ </string>
+ <string name="Hair Thickess">
+ Haardicke
+ </string>
+ <string name="Hair Thickness">
+ Haardicke
+ </string>
+ <string name="Hair Tilt">
+ Haarneigung
+ </string>
+ <string name="Hair Tilted Left">
+ Nach links
+ </string>
+ <string name="Hair Tilted Right">
+ Nach rechts
+ </string>
+ <string name="Hair Volume">
+ Haare: Volumen
+ </string>
+ <string name="Hand Size">
+ Handgröße
+ </string>
+ <string name="Handlebars">
+ Zwirbelbart
+ </string>
+ <string name="Head Length">
+ Kopflänge
+ </string>
+ <string name="Head Shape">
+ Kopfform
+ </string>
+ <string name="Head Size">
+ Kopfgröße
+ </string>
+ <string name="Head Stretch">
+ Kopfstreckung
+ </string>
+ <string name="Heel Height">
+ Absatzhöhe
+ </string>
+ <string name="Heel Shape">
+ Absatzform
+ </string>
+ <string name="Height">
+ Höhe
+ </string>
+ <string name="High">
+ Hoch
+ </string>
+ <string name="High Heels">
+ Hohe Absätze
+ </string>
+ <string name="High Jaw">
+ Hoch
+ </string>
+ <string name="High Platforms">
+ Hohe Plattformsohlen
+ </string>
+ <string name="High and Tight">
+ Hoch und eng
+ </string>
+ <string name="Higher">
+ Höhere
+ </string>
+ <string name="Hip Length">
+ Länge der Hüfte
+ </string>
+ <string name="Hip Width">
+ Breite der Hüfte
+ </string>
+ <string name="In">
+ In
+ </string>
+ <string name="In Shdw Color">
+ Farbe Innenseite
+ </string>
+ <string name="In Shdw Opacity">
+ Deckkraft: innerer Lidschatten
+ </string>
+ <string name="Inner Eye Corner">
+ Ecke: Nasenseite
+ </string>
+ <string name="Inner Eye Shadow">
+ Innerer Lidschatten
+ </string>
+ <string name="Inner Shadow">
+ Innerer Lidschatten
+ </string>
+ <string name="Jacket Length">
+ Jackenlänge
+ </string>
+ <string name="Jacket Wrinkles">
+ Jackenfalten
+ </string>
+ <string name="Jaw Angle">
+ Kinnansatz
+ </string>
+ <string name="Jaw Jut">
+ Kinnposition
+ </string>
+ <string name="Jaw Shape">
+ Kinnform
+ </string>
+ <string name="Join">
+ Zusammen
+ </string>
+ <string name="Jowls">
+ Hängebacken
+ </string>
+ <string name="Knee Angle">
+ Kniewinkel
+ </string>
+ <string name="Knock Kneed">
+ X-beinig
+ </string>
+ <string name="Large">
+ Groß
+ </string>
+ <string name="Large Hands">
+ Große Hände
+ </string>
+ <string name="Left Part">
+ Linksscheitel
+ </string>
+ <string name="Leg Length">
+ Beinlänge
+ </string>
+ <string name="Leg Muscles">
+ Beinmuskeln
+ </string>
+ <string name="Less">
+ Weniger
+ </string>
+ <string name="Less Body Fat">
+ Weniger Speck
+ </string>
+ <string name="Less Curtains">
+ Weniger
+ </string>
+ <string name="Less Freckles">
+ Weniger
+ </string>
+ <string name="Less Full">
+ Weniger
+ </string>
+ <string name="Less Gravity">
+ Weniger
+ </string>
+ <string name="Less Love">
+ Weniger
+ </string>
+ <string name="Less Muscles">
+ Weniger
+ </string>
+ <string name="Less Muscular">
+ Weniger
+ </string>
+ <string name="Less Rosy">
+ Weniger
+ </string>
+ <string name="Less Round">
+ Weniger
+ </string>
+ <string name="Less Saddle">
+ Weniger
+ </string>
+ <string name="Less Square">
+ Weniger
+ </string>
+ <string name="Less Volume">
+ Weniger
+ </string>
+ <string name="Less soul">
+ Weniger
+ </string>
+ <string name="Lighter">
+ Heller
+ </string>
+ <string name="Lip Cleft">
+ Amorbogen
+ </string>
+ <string name="Lip Cleft Depth">
+ Tiefe: Amorbogen
+ </string>
+ <string name="Lip Fullness">
+ Fülle
+ </string>
+ <string name="Lip Pinkness">
+ Pinkton
+ </string>
+ <string name="Lip Ratio">
+ Lippenproportionen
+ </string>
+ <string name="Lip Thickness">
+ Lippendicke
+ </string>
+ <string name="Lip Width">
+ Mundbreite
+ </string>
+ <string name="Lipgloss">
+ Lipgloss
+ </string>
+ <string name="Lipstick">
+ Lippenstift
+ </string>
+ <string name="Lipstick Color">
+ Farbe
+ </string>
+ <string name="Long">
+ Lang
+ </string>
+ <string name="Long Head">
+ Langer Kopf
+ </string>
+ <string name="Long Hips">
+ Lange Hüften
+ </string>
+ <string name="Long Legs">
+ Lange Beine
+ </string>
+ <string name="Long Neck">
+ Langer Hals
+ </string>
+ <string name="Long Pigtails">
+ Lange Zöpfe
+ </string>
+ <string name="Long Ponytail">
+ Langer Pferdeschwanz
+ </string>
+ <string name="Long Torso">
+ Langer Oberkörper
+ </string>
+ <string name="Long arms">
+ Lange Arme
+ </string>
+ <string name="Loose Pants">
+ Weite Hosen
+ </string>
+ <string name="Loose Shirt">
+ Weites Hemd
+ </string>
+ <string name="Loose Sleeves">
+ Weite Ärmel
+ </string>
+ <string name="Love Handles">
+ Fettpölsterchen
+ </string>
+ <string name="Low">
+ Niedrig
+ </string>
+ <string name="Low Heels">
+ Niedrig
+ </string>
+ <string name="Low Jaw">
+ Niedrig
+ </string>
+ <string name="Low Platforms">
+ Niedrig
+ </string>
+ <string name="Low and Loose">
+ Weit
+ </string>
+ <string name="Lower">
+ Absenken
+ </string>
+ <string name="Lower Bridge">
+ Brücke, Unterer Teil
+ </string>
+ <string name="Lower Cheeks">
+ Wangen, unterer Bereich
+ </string>
+ <string name="Male">
+ Männlich
+ </string>
+ <string name="Middle Part">
+ Mittelscheitel
+ </string>
+ <string name="More">
+ Mehr
+ </string>
+ <string name="More Blush">
+ Mehr
+ </string>
+ <string name="More Body Fat">
+ Mehr Speck
+ </string>
+ <string name="More Curtains">
+ Mehr
+ </string>
+ <string name="More Eyeshadow">
+ Mehr
+ </string>
+ <string name="More Freckles">
+ Mehr
+ </string>
+ <string name="More Full">
+ Voller
+ </string>
+ <string name="More Gravity">
+ Mehr
+ </string>
+ <string name="More Lipstick">
+ Mehr
+ </string>
+ <string name="More Love">
+ Mehr
+ </string>
+ <string name="More Lower Lip">
+ Größer
+ </string>
+ <string name="More Muscles">
+ Mehr
+ </string>
+ <string name="More Muscular">
+ Mehr
+ </string>
+ <string name="More Rosy">
+ Mehr
+ </string>
+ <string name="More Round">
+ Runder
+ </string>
+ <string name="More Saddle">
+ Mehr
+ </string>
+ <string name="More Sloped">
+ Mehr
+ </string>
+ <string name="More Square">
+ Mehr
+ </string>
+ <string name="More Upper Lip">
+ Mehr
+ </string>
+ <string name="More Vertical">
+ Mehr
+ </string>
+ <string name="More Volume">
+ Mehr
+ </string>
+ <string name="More soul">
+ Mehr
+ </string>
+ <string name="Moustache">
+ Schnauzer
+ </string>
+ <string name="Mouth Corner">
+ Mundwinkel
+ </string>
+ <string name="Mouth Position">
+ Mundposition
+ </string>
+ <string name="Mowhawk">
+ Irokese
+ </string>
+ <string name="Muscular">
+ Muskulös
+ </string>
+ <string name="Mutton Chops">
+ Koteletten
+ </string>
+ <string name="Nail Polish">
+ Nagellack
+ </string>
+ <string name="Nail Polish Color">
+ Farbe
+ </string>
+ <string name="Narrow">
+ Schmal
+ </string>
+ <string name="Narrow Back">
+ Wenig
+ </string>
+ <string name="Narrow Front">
+ Wenig
+ </string>
+ <string name="Narrow Lips">
+ Schmale Lippen
+ </string>
+ <string name="Natural">
+ Natürlich
+ </string>
+ <string name="Neck Length">
+ Halslänge
+ </string>
+ <string name="Neck Thickness">
+ Halsdicke
+ </string>
+ <string name="No Blush">
+ Kein Rouge
+ </string>
+ <string name="No Eyeliner">
+ Kein Eyeliner
+ </string>
+ <string name="No Eyeshadow">
+ Kein Lidschatten
+ </string>
+ <string name="No Lipgloss">
+ Kein Lipgloss
+ </string>
+ <string name="No Lipstick">
+ Kein Lippenstift
+ </string>
+ <string name="No Part">
+ Kein Scheitel
+ </string>
+ <string name="No Polish">
+ Kein Nagellack
+ </string>
+ <string name="No Red">
+ Nicht rot
+ </string>
+ <string name="No Spikes">
+ Keine Stachel
+ </string>
+ <string name="No White">
+ Kein Weiß
+ </string>
+ <string name="No Wrinkles">
+ Keine Falten
+ </string>
+ <string name="Normal Lower">
+ Normal unten
+ </string>
+ <string name="Normal Upper">
+ Normal oben
+ </string>
+ <string name="Nose Left">
+ Links
+ </string>
+ <string name="Nose Right">
+ Rechts
+ </string>
+ <string name="Nose Size">
+ Größe
+ </string>
+ <string name="Nose Thickness">
+ Dicke
+ </string>
+ <string name="Nose Tip Angle">
+ Nasenspitze
+ </string>
+ <string name="Nose Tip Shape">
+ Nasenspitze
+ </string>
+ <string name="Nose Width">
+ Nasenbreite
+ </string>
+ <string name="Nostril Division">
+ Teilung
+ </string>
+ <string name="Nostril Width">
+ Größe
+ </string>
+ <string name="Opaque">
+ Deckend
+ </string>
+ <string name="Open">
+ Öffnen
+ </string>
+ <string name="Open Back">
+ Hinten offen
+ </string>
+ <string name="Open Front">
+ Vorne offen
+ </string>
+ <string name="Open Left">
+ Links offen
+ </string>
+ <string name="Open Right">
+ Rechts offen
+ </string>
+ <string name="Orange">
+ Orange
+ </string>
+ <string name="Out">
+ Aus
+ </string>
+ <string name="Out Shdw Color">
+ Farbe: Oberer Lidschatten
+ </string>
+ <string name="Out Shdw Opacity">
+ Deckkraft: Oberer Lidschatten
+ </string>
+ <string name="Outer Eye Corner">
+ Äußerer Augenwinkel
+ </string>
+ <string name="Outer Eye Shadow">
+ Lidschatten: Oben
+ </string>
+ <string name="Outer Shadow">
+ Lidschatten: Oben
+ </string>
+ <string name="Overbite">
+ Ãœberbiss
+ </string>
+ <string name="Package">
+ Ausbeulung
+ </string>
+ <string name="Painted Nails">
+ Lackierte Nägel
+ </string>
+ <string name="Pale">
+ Blass
+ </string>
+ <string name="Pants Crotch">
+ Schritt
+ </string>
+ <string name="Pants Fit">
+ Passform
+ </string>
+ <string name="Pants Length">
+ Hosenlänge
+ </string>
+ <string name="Pants Waist">
+ Hüfte
+ </string>
+ <string name="Pants Wrinkles">
+ Falten
+ </string>
+ <string name="Part">
+ Scheitel
+ </string>
+ <string name="Part Bangs">
+ Pony scheiteln
+ </string>
+ <string name="Pectorals">
+ Brustmuskel
+ </string>
+ <string name="Pigment">
+ Pigmentierung
+ </string>
+ <string name="Pigtails">
+ Zöpfe
+ </string>
+ <string name="Pink">
+ Pink
+ </string>
+ <string name="Pinker">
+ Mehr Pink
+ </string>
+ <string name="Platform Height">
+ Höhe
+ </string>
+ <string name="Platform Width">
+ Breite
+ </string>
+ <string name="Pointy">
+ Spitz
+ </string>
+ <string name="Pointy Heels">
+ Pfennigabsätze
+ </string>
+ <string name="Ponytail">
+ Pferdeschwanz
+ </string>
+ <string name="Poofy Skirt">
+ Weit ausgestellt
+ </string>
+ <string name="Pop Left Eye">
+ Linkes Auge größer
+ </string>
+ <string name="Pop Right Eye">
+ Rechtes Auge größer
+ </string>
+ <string name="Puffy">
+ Geschwollen
+ </string>
+ <string name="Puffy Eyelids">
+ Geschwollene Lider
+ </string>
+ <string name="Rainbow Color">
+ Regenbogenfarben
+ </string>
+ <string name="Red Hair">
+ Rote Haare
+ </string>
+ <string name="Regular">
+ Normal
+ </string>
+ <string name="Right Part">
+ Scheitel rechts
+ </string>
+ <string name="Rosy Complexion">
+ Rosiger Teint
+ </string>
+ <string name="Round">
+ Rund
+ </string>
+ <string name="Ruddiness">
+ Röte
+ </string>
+ <string name="Ruddy">
+ Rötlich
+ </string>
+ <string name="Rumpled Hair">
+ Zerzauste Haare
+ </string>
+ <string name="Saddle Bags">
+ Hüftspeck
+ </string>
+ <string name="Scrawny Leg">
+ Dürres Bein
+ </string>
+ <string name="Separate">
+ Auseinander
+ </string>
+ <string name="Shallow">
+ Flach
+ </string>
+ <string name="Shear Back">
+ Hinterkopf rasiert
+ </string>
+ <string name="Shear Face">
+ Gesicht verzerren
+ </string>
+ <string name="Shear Front">
+ Vorne rasiert
+ </string>
+ <string name="Shear Left Up">
+ Links
+ </string>
+ <string name="Shear Right Up">
+ Rechts
+ </string>
+ <string name="Sheared Back">
+ Hinterkopf rasiert
+ </string>
+ <string name="Sheared Front">
+ Vorne rasiert
+ </string>
+ <string name="Shift Left">
+ Nach links
+ </string>
+ <string name="Shift Mouth">
+ Mund verschieben
+ </string>
+ <string name="Shift Right">
+ Nach rechts
+ </string>
+ <string name="Shirt Bottom">
+ Hemdlänge
+ </string>
+ <string name="Shirt Fit">
+ Passform
+ </string>
+ <string name="Shirt Wrinkles">
+ Falten
+ </string>
+ <string name="Shoe Height">
+ Höhe
+ </string>
+ <string name="Short">
+ Kurz
+ </string>
+ <string name="Short Arms">
+ Kurze Arme
+ </string>
+ <string name="Short Legs">
+ Kurze Beine
+ </string>
+ <string name="Short Neck">
+ Kurzer Hals
+ </string>
+ <string name="Short Pigtails">
+ Kurze Zöpfe
+ </string>
+ <string name="Short Ponytail">
+ Kurzer Pferdeschwanz
+ </string>
+ <string name="Short Sideburns">
+ Kurze Koteletten
+ </string>
+ <string name="Short Torso">
+ Kurzer Oberkörper
+ </string>
+ <string name="Short hips">
+ Kurze Hüften
+ </string>
+ <string name="Shoulders">
+ Schultern
+ </string>
+ <string name="Side Fringe">
+ Seitliche Fransen
+ </string>
+ <string name="Sideburns">
+ Koteletten
+ </string>
+ <string name="Sides Hair">
+ Seitliches Haar
+ </string>
+ <string name="Sides Hair Down">
+ Lang
+ </string>
+ <string name="Sides Hair Up">
+ Kurz
+ </string>
+ <string name="Skinny Neck">
+ Dünner Hals
+ </string>
+ <string name="Skirt Fit">
+ Passform
+ </string>
+ <string name="Skirt Length">
+ Rocklänge
+ </string>
+ <string name="Slanted Forehead">
+ Fliehende Stirn
+ </string>
+ <string name="Sleeve Length">
+ Ärmellänge
+ </string>
+ <string name="Sleeve Looseness">
+ Passform Ärmel
+ </string>
+ <string name="Slit Back">
+ Schlitz: Hinten
+ </string>
+ <string name="Slit Front">
+ Schlitz: Vorne
+ </string>
+ <string name="Slit Left">
+ Schlitz: Links
+ </string>
+ <string name="Slit Right">
+ Schlitz: Rechts
+ </string>
+ <string name="Small">
+ Klein
+ </string>
+ <string name="Small Hands">
+ Kleine Hände
+ </string>
+ <string name="Small Head">
+ Kleiner Kopf
+ </string>
+ <string name="Smooth">
+ Glätten
+ </string>
+ <string name="Smooth Hair">
+ Glattes Haar
+ </string>
+ <string name="Socks Length">
+ Strumpflänge
+ </string>
+ <string name="Soulpatch">
+ Unterlippenbart
+ </string>
+ <string name="Sparse">
+ Wenig
+ </string>
+ <string name="Spiked Hair">
+ Stachelhaare
+ </string>
+ <string name="Square">
+ Rechteck
+ </string>
+ <string name="Square Toe">
+ Eckig
+ </string>
+ <string name="Squash Head">
+ Gestaucht
+ </string>
+ <string name="Stretch Head">
+ Gestreckt
+ </string>
+ <string name="Sunken">
+ Eingefallen
+ </string>
+ <string name="Sunken Chest">
+ Trichterbrust
+ </string>
+ <string name="Sunken Eyes">
+ Eingesunkene Augen
+ </string>
+ <string name="Sweep Back">
+ Nach hinten
+ </string>
+ <string name="Sweep Forward">
+ Nach vorne
+ </string>
+ <string name="Tall">
+ Groß
+ </string>
+ <string name="Taper Back">
+ Ansatzbreite hinten
+ </string>
+ <string name="Taper Front">
+ Ansatzbreite vorne
+ </string>
+ <string name="Thick Heels">
+ Dicke Absätze
+ </string>
+ <string name="Thick Neck">
+ Dicker Hals
+ </string>
+ <string name="Thick Toe">
+ Dick
+ </string>
+ <string name="Thin">
+ Dünn
+ </string>
+ <string name="Thin Eyebrows">
+ Dünne Augenbrauen
+ </string>
+ <string name="Thin Lips">
+ Dünne Lippen
+ </string>
+ <string name="Thin Nose">
+ Dünne Nase
+ </string>
+ <string name="Tight Chin">
+ Straffes Kinn
+ </string>
+ <string name="Tight Cuffs">
+ Eng
+ </string>
+ <string name="Tight Pants">
+ Enge Hosen
+ </string>
+ <string name="Tight Shirt">
+ Enges Hemd
+ </string>
+ <string name="Tight Skirt">
+ Enger Rock
+ </string>
+ <string name="Tight Sleeves">
+ Enge Ärmel
+ </string>
+ <string name="Toe Shape">
+ Spitze
+ </string>
+ <string name="Toe Thickness">
+ Dicke
+ </string>
+ <string name="Torso Length">
+ Länge des Oberkörpers
+ </string>
+ <string name="Torso Muscles">
+ Muskeln
+ </string>
+ <string name="Torso Scrawny">
+ Dürr
+ </string>
+ <string name="Unattached">
+ Frei
+ </string>
+ <string name="Uncreased">
+ Straffes Lid
+ </string>
+ <string name="Underbite">
+ Unterbiss
+ </string>
+ <string name="Unnatural">
+ Unnatürlich
+ </string>
+ <string name="Upper Bridge">
+ Brücke, oberer Teil
+ </string>
+ <string name="Upper Cheeks">
+ Obere Wangen
+ </string>
+ <string name="Upper Chin Cleft">
+ Obere Kinnspalte
+ </string>
+ <string name="Upper Eyelid Fold">
+ Obere Lidfalte
+ </string>
+ <string name="Upturned">
+ Stupsnase
+ </string>
+ <string name="Very Red">
+ Sehr rot
+ </string>
+ <string name="Waist Height">
+ Bund
+ </string>
+ <string name="Well-Fed">
+ Gut genährt
+ </string>
+ <string name="White Hair">
+ Weiße Haare
+ </string>
+ <string name="Wide">
+ Breit
+ </string>
+ <string name="Wide Back">
+ Breit
+ </string>
+ <string name="Wide Front">
+ Breit
+ </string>
+ <string name="Wide Lips">
+ Breit
+ </string>
+ <string name="Wild">
+ Wild
+ </string>
+ <string name="Wrinkles">
+ Falten
+ </string>
+ <string name="LocationCtrlAddLandmarkTooltip">
+ Zu meinen Landmarken hinzufügen
+ </string>
+ <string name="LocationCtrlEditLandmarkTooltip">
+ Meine Landmarken bearbeiten
+ </string>
+ <string name="LocationCtrlInfoBtnTooltip">
+ Weitere Informationen über die aktuelle Position
+ </string>
+ <string name="LocationCtrlComboBtnTooltip">
+ Mein Reiseverlauf
+ </string>
+ <string name="UpdaterWindowTitle">
+ [APP_NAME] Aktualisierung
+ </string>
+ <string name="UpdaterNowUpdating">
+ [APP_NAME] wird aktualisiert...
+ </string>
+ <string name="UpdaterNowInstalling">
+ [APP_NAME] wird installiert...
+ </string>
+ <string name="UpdaterUpdatingDescriptive">
+ Ihr [APP_NAME]-Viewer wird aktualisiert. Dies kann einen Moment dauern. Wir bitten um Ihr Verständnis.
+ </string>
+ <string name="UpdaterProgressBarTextWithEllipses">
+ Aktualisierung wird heruntergeladen...
+ </string>
+ <string name="UpdaterProgressBarText">
+ Aktualisierung wird heruntergeladen
+ </string>
+ <string name="UpdaterFailDownloadTitle">
+ Herunterladen ist fehlgeschlagen
+ </string>
+ <string name="UpdaterFailUpdateDescriptive">
+ Beim Aktualisieren von [APP_NAME] ist ein Fehler aufgetreten. Bitte laden Sie die aktuellste Version von www.secondlife.com herunter.
+ </string>
+ <string name="UpdaterFailInstallTitle">
+ Aktualisierung konnte nicht installiert werden
+ </string>
+ <string name="UpdaterFailStartTitle">
+ Viewer konnte nicht gestartet werden
+ </string>
+ <string name="IM_logging_string">
+ -- Instant-Message-Protokoll aktiviert --
+ </string>
+ <string name="IM_typing_start_string">
+ [NAME] tippt...
+ </string>
+ <string name="Unnamed">
+ (Nicht benannt)
+ </string>
+ <string name="IM_moderated_chat_label">
+ (Moderiert: Stimmen in der Standardeinstellung stummgeschaltet)
+ </string>
+ <string name="IM_unavailable_text_label">
+ Für diese Verbindung ist kein Text-Chat verfügbar.
+ </string>
+ <string name="IM_muted_text_label">
+ Ihr Text-Chat wurde von einem Gruppenmoderator deaktiviert.
+ </string>
+ <string name="IM_default_text_label">
+ Für Instant Message hier klicken.
+ </string>
+ <string name="IM_to_label">
+ Bis
+ </string>
+ <string name="IM_moderator_label">
+ (Moderator)
+ </string>
+ <string name="only_user_message">
+ Sie sind der einzige Benutzer in dieser Sitzung.
+ </string>
+ <string name="offline_message">
+ [FIRST] [LAST] ist offline.
+ </string>
+ <string name="invite_message">
+ Klicken Sie auf [BUTTON NAME], um eine Verbindung zu diesem Voice-Chat herzustellen.
+ </string>
+ <string name="generic_request_error">
+ Fehler bei Anfrage, bitte versuchen Sie es später.
+ </string>
+ <string name="insufficient_perms_error">
+ Sie sind dazu nicht berechtigt.
+ </string>
+ <string name="session_does_not_exist_error">
+ Die Sitzung ist abgelaufen
+ </string>
+ <string name="no_ability_error">
+ Sie besitzen diese Fähigkeit nicht.
+ </string>
+ <string name="no_ability">
+ Sie besitzen diese Fähigkeit nicht.
+ </string>
+ <string name="not_a_mod_error">
+ Sie sind kein Sitzungsmoderator.
+ </string>
+ <string name="muted_error">
+ Ein Gruppenmoderator hat Ihren Text-Chat deaktiviert.
+ </string>
+ <string name="add_session_event">
+ Es konnten keine Benutzer zur Chat-Sitzung mit [RECIPIENT] hinzugefügt werden.
+ </string>
+ <string name="message_session_event">
+ Ihre Nachricht konnte nicht an die Chat-Sitzung mit [RECIPIENT] gesendet werden.
+ </string>
+ <string name="removed_from_group">
+ Sie wurden von der Gruppe ausgeschlossen.
+ </string>
+ <string name="close_on_no_ability">
+ Sie haben nicht mehr die Berechtigung an der Chat-Sitzung teilzunehmen.
+ </string>
</strings>
diff --git a/indra/newview/skins/default/xui/de/teleport_strings.xml b/indra/newview/skins/default/xui/de/teleport_strings.xml
index 31f92dc920..2c56eff0a3 100644
--- a/indra/newview/skins/default/xui/de/teleport_strings.xml
+++ b/indra/newview/skins/default/xui/de/teleport_strings.xml
@@ -1,13 +1,13 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<teleport_messages name="">
<message_set name="errors">
<message name="invalid_tport">
- Bei der Bearbeitung Ihrer Teleport-Anfrage ist ein Problem aufgetreten. Sie müssen sich zum Teleportieren eventuell neu anmelden. Wenn Sie diese Nachricht weiterhin erhalten, konsultieren Sie bitte die Tech-Support-FAQ unter:
-www.secondlife.com/support
+ Bei der Bearbeitung Ihrer Teleport-Anfrage ist ein Problem aufgetreten. Sie müssen sich zum Teleportieren eventuell neu anmelden.
+Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich bitte an [SUPPORT_SITE].
</message>
<message name="invalid_region_handoff">
- Bei der Bearbeitung Ihres Regionswechsels ist ein Problem aufgetreten. Sie müssen sich zum Wechsel der Region eventuell neu anmelden. Wenn Sie diese Nachricht weiterhin erhalten, konsultieren Sie bitte die Tech-Support-FAQ unter:
-www.secondlife.com/support
+ Bei der Bearbeitung Ihres Regionswechsels ist ein Problem aufgetreten. Sie müssen eventuell neu anmelden, um die Region wechseln zu können.
+Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich bitte an [SUPPORT_SITE].
</message>
<message name="blocked_tport">
Teleportieren ist zurzeit leider nicht möglich. Versuchen Sie es später noch einmal.
diff --git a/indra/newview/skins/default/xui/en/accordion_drag.xml b/indra/newview/skins/default/xui/en/accordion_drag.xml
new file mode 100644
index 0000000000..94839a7593
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/accordion_drag.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel border_thickness="2" visible ="true" name="splitter_drag"
+ width="100"
+ height="5"
+ left="50"
+ top="50"
+ follows="left|bottom|right" background_visible="true" label="splitter_drag" title="">
+</panel>
diff --git a/indra/newview/skins/default/xui/en/accordion_parent.xml b/indra/newview/skins/default/xui/en/accordion_parent.xml
new file mode 100644
index 0000000000..ea34bac0a7
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/accordion_parent.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+ <panel border_thickness="0" name="splitter_parent"
+ background_visible="true"
+ label="splitter_parent"
+ title=""
+ >
+ </panel>
diff --git a/indra/newview/skins/default/xui/en/alert_button.xml b/indra/newview/skins/default/xui/en/alert_button.xml
new file mode 100644
index 0000000000..632564d793
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/alert_button.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+
+<button
+ name="Alert Button"
+ label_shadow="true"
+ auto_resize="false"
+ image_overlay_alignment="center"
+ use_ellipses="flse"
+ pad_right="10"
+ pad_left="10"
+ is_toggle="false"
+ scale_image="true"
+ commit_on_return="true"
+ font="SansSerifSmall"
+ follows="bottom"/>
diff --git a/indra/newview/skins/default/xui/en/alert_check_box.xml b/indra/newview/skins/default/xui/en/alert_check_box.xml
new file mode 100644
index 0000000000..9f1bdb5193
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/alert_check_box.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<check_box
+ text_enabled_color="LabelTextColor"
+ text_disabled_color="LabelDisabledColor"
+ font="SansSerif"
+ follows="left|top"
+ name="check"/> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/alert_icon.xml b/indra/newview/skins/default/xui/en/alert_icon.xml
new file mode 100644
index 0000000000..b0886fce06
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/alert_icon.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<icon color="1.0 1.0 1.0 1.0"
+ tab_stop="false"
+ mouse_opaque="false"
+ name="icon"
+ image_name="notify_caution_icon.tga"
+ follows="left|top">
+</icon>
diff --git a/indra/newview/skins/default/xui/en/alert_line_editor.xml b/indra/newview/skins/default/xui/en/alert_line_editor.xml
new file mode 100644
index 0000000000..97991153d8
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/alert_line_editor.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<line_editor
+ select_on_focus="false"
+ handle_edit_keys_directly="false"
+ revert_on_esc="true"
+ commit_on_focus_lost="true"
+ ignore_tab="true"
+ max_length="254"
+ text_pad_right="0"
+ text_pad_left="2"
+ mouse_opaque="true"/>
diff --git a/indra/newview/skins/default/xui/en/favorites_bar_button.xml b/indra/newview/skins/default/xui/en/favorites_bar_button.xml
new file mode 100644
index 0000000000..b365040c20
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/favorites_bar_button.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- *NOTE: mantipov: top & height should be synchronized with <favorites_bar> in the panel_navigation_bar.xml-->
+<!-- All buttons in the Favorites bar will be created from this one -->
+<button
+ follows="left|bottom"
+ halign="center"
+ height="15"
+ image_disabled="transparent.j2c"
+ image_disabled_selected="transparent.j2c"
+ image_selected="transparent.j2c"
+ image_unselected="transparent.j2c"
+ image_pressed="Favorite_Link_Over"
+ image_hover_selected="Favorite_Link_Over"
+ image_hover_unselected="Favorite_Link_Over"
+ hover_glow_amount="0.15"
+ label_shadow="false"
+ layout="topleft"
+ left="0"
+ name="favorites_bar_btn"
+ pad_bottom="1"
+ pad_left="11"
+ pad_right="9"
+ scale_image="true"
+ tab_stop="false"
+ top="0"
+ use_ellipses="true"
+ width="140" />
diff --git a/indra/newview/skins/default/xui/en/floater_aaa.xml b/indra/newview/skins/default/xui/en/floater_aaa.xml
new file mode 100644
index 0000000000..cb9f943949
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_aaa.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ can_tear_off="false"
+ can_resize="true"
+ can_drag_on_left="false"
+ can_close="true"
+ can_dock="true"
+ bevel_style="in"
+ height="300"
+ layout="topleft"
+ name="Test Floater"
+ save_rect="true"
+ title="TEST FLOATER"
+ save_dock_state="true"
+ save_visibility="true"
+ single_instance="true"
+ width="320">
+ <string name="nudge_parabuild">Nudge 1</string>
+ <string name="test_the_vlt">This string CHANGE is extracted.</string>
+ <string name="testing_eli">Just a test.</string>
+ <chat_history
+ allow_html="true"
+ bg_readonly_color="ChatHistoryBgColor"
+ bg_writeable_color="ChatHistoryBgColor"
+ border_visible="false"
+ follows="all"
+ font="SansSerif"
+ left="1"
+ top="20"
+ layout="topleft"
+ height="260"
+ name="chat_history"
+ parse_highlights="true"
+ text_color="ChatHistoryTextColor"
+ text_readonly_color="ChatHistoryTextColor"
+ width="320">
+Really long line that is long enough to wrap once with jyg descenders.
+Really long line that is long enough to wrap once with jyg descenders.
+Really long line that is long enough to wrap once with jyg descenders.
+Really long line that is long enough to wrap once with jyg descenders.
+Really long line that is long enough to wrap once with jyg descenders.
+Really long line that is long enough to wrap once with jyg descenders.
+Really long line that is long enough to wrap once with jyg descenders.
+Really long line that is long enough to wrap once with jyg descenders.
+Really long line that is long enough to wrap once with jyg descenders.
+Really long line that is long enough to wrap once with jyg descenders.
+Really long line that is long enough to wrap once with jyg descenders.
+Really long line that is long enough to wrap once with jyg descenders.
+Really long line that is long enough to wrap once with jyg descenders.
+Really long line that is long enough to wrap once with jyg descenders.
+Really long line that is long enough to wrap once with jyg descenders.
+Really long line that is long enough to wrap once with jyg descenders.
+ </chat_history>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml
new file mode 100644
index 0000000000..b6443c4c21
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_about.xml
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="440"
+ layout="topleft"
+ name="floater_about"
+ help_topic="floater_about"
+ save_rect="true"
+ title="ABOUT [CAPITALIZED_APP_NAME]"
+ width="470">
+ <floater.string
+ name="AboutHeader">
+[APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL])
+[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]]
+
+</floater.string>
+ <floater.string
+ name="AboutCompiler">
+Built with [COMPILER] version [COMPILER_VERSION]
+
+</floater.string>
+ <floater.string
+ name="AboutPosition">
+You are at [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] in [REGION] located at [HOSTNAME] ([HOSTIP])
+[SERVER_VERSION]
+[[SERVER_RELEASE_NOTES_URL] [ReleaseNotes]]
+
+</floater.string>
+ <!-- *NOTE: Do not translate text like GPU, Graphics Card, etc -
+ Most PC users who know what these mean will be used to the English versions,
+ and this info sometimes gets sent to support. -->
+ <floater.string
+ name="AboutSystem">
+CPU: [CPU]
+Memory: [MEMORY_MB] MB
+OS Version: [OS_VERSION]
+Graphics Card Vendor: [GRAPHICS_CARD_VENDOR]
+Graphics Card: [GRAPHICS_CARD]
+</floater.string>
+ <floater.string
+ name="AboutDriver">
+Windows Graphics Driver Version: [GRAPHICS_DRIVER_VERSION]
+</floater.string>
+ <floater.string
+ name="AboutLibs">
+OpenGL Version: [OPENGL_VERSION]
+
+libcurl Version: [LIBCURL_VERSION]
+J2C Decoder Version: [J2C_VERSION]
+Audio Driver Version: [AUDIO_DRIVER_VERSION]
+Qt Webkit Version: [QT_WEBKIT_VERSION]
+Vivox Version: [VIVOX_VERSION]
+</floater.string>
+ <floater.string
+ name="none">
+ (none)
+ </floater.string>
+ <floater.string
+ name="AboutTraffic">
+Packets Lost: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%)
+</floater.string>
+ <tab_container
+ follows="all"
+ top="25"
+ left="10"
+ height="405"
+ width="450"
+ name="about_tab"
+ tab_position="top">
+ <panel
+ border="true"
+ label="Info"
+ help_topic="about_support_tab"
+ name="support_panel">
+ <text_editor
+ allow_html="true"
+ follows="top|left"
+ font="SansSerif"
+ height="350"
+ bg_readonly_color="Transparent"
+ left="5"
+ max_length="65536"
+ name="support_editor"
+ top="5"
+ width="435"
+ word_wrap="true" />
+ <button
+ follows="left|top"
+ label="Copy to Clipboard"
+ name="copy_btn"
+ left="10"
+ top_pad="5"
+ height="25"
+ width="160" />
+ </panel>
+ <panel
+ border="true"
+ label="Credits"
+ help_topic="about_credits_tab"
+ name="credits_panel">
+ <text_editor
+ enabled="false"
+ follows="left|top"
+ height="375"
+ bg_readonly_color="Transparent"
+ left="5"
+ text_color="LtGray"
+ max_length="65536"
+ name="credits_editor"
+ top="5"
+ width="435"
+ word_wrap="true">
+Second Life is brought to you by Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les and many others.
+
+Thank you to the following Residents for helping to ensure that this is the best version yet: (in progress)
+
+
+
+
+
+
+
+
+It is a rare mind indeed that can render the hitherto non-existent blindingly obvious. The cry 'I could have thought of that' is a very popular and misleading one, for the fact is that they didn't, and a very significant and revealing fact it is too.
+ -- Douglas Adams
+ </text_editor>
+ </panel>
+ <panel
+ border="true"
+ label="Licenses"
+ help_topic="about_licenses_tab"
+ name="licenses_panel">
+ <text_editor
+ enabled="false"
+ follows="left|top"
+ height="375"
+ bg_readonly_color="Transparent"
+ left="5"
+ text_color="LtGray"
+ max_length="65536"
+ name="credits_editor"
+ top="5"
+ width="435"
+ word_wrap="true">
+3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
+APR Copyright (C) 2000-2004 The Apache Software Foundation
+cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
+DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc.
+expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
+FreeType Copyright (C) 1996-2002, The FreeType Project (www.freetype.org).
+GL Copyright (C) 1999-2004 Brian Paul.
+google-perftools Copyright (c) 2005, Google Inc.
+Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited.
+jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW)
+jpeglib Copyright (C) 1991-1998, Thomas G. Lane.
+ogg/vorbis Copyright (C) 2001, Xiphophorus
+OpenSSL Copyright (C) 1998-2002 The OpenSSL Project.
+Pth Copyright (C) 1999-2006 Ralf S. Engelschall &lt;rse@gnu.org&gt;
+SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
+SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
+zlib Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler.
+google-perftools Copyright (c) 2005, Google Inc.
+
+All rights reserved. See licenses.txt for details.
+
+Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
+ </text_editor>
+ </panel>
+ </tab_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
new file mode 100644
index 0000000000..61ca783d14
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -0,0 +1,2122 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ can_tear_off="false"
+ height="420"
+ layout="topleft"
+ name="floaterland"
+ help_topic="floaterland"
+ save_rect="true"
+ title="ABOUT LAND"
+ width="490">
+ <floater.string
+ name="Minutes">
+ [MINUTES] minutes
+ </floater.string>
+ <floater.string
+ name="Minute">
+ minute
+ </floater.string>
+ <floater.string
+ name="Seconds">
+ [SECONDS] seconds
+ </floater.string>
+ <floater.string
+ name="Remaining">
+ remaining
+ </floater.string>
+ <tab_container
+ follows="all"
+ height="410"
+ layout="topleft"
+ left="0"
+ name="landtab"
+ tab_position="top"
+ tab_height="25"
+ tab_min_width="67"
+ top="10"
+ width="489">
+ <panel
+ border="false"
+ follows="all"
+ label="GENERAL"
+ layout="topleft"
+ left="0"
+ help_topic="land_general_tab"
+ name="land_general_panel"
+ top="0">
+ <panel.string
+ name="new users only">
+ New users only
+ </panel.string>
+ <panel.string
+ name="anyone">
+ Anyone
+ </panel.string>
+ <panel.string
+ name="area_text">
+ Area
+ </panel.string>
+ <panel.string
+ name="area_size_text">
+ [AREA] m²
+ </panel.string>
+ <panel.string
+ name="auction_id_text">
+ Auction ID: [ID]
+ </panel.string>
+ <panel.string
+ name="need_tier_to_modify">
+ You must approve your purchase to modify this land.
+ </panel.string>
+ <panel.string
+ name="group_owned_text">
+ (Group Owned)
+ </panel.string>
+ <panel.string
+ name="profile_text">
+ Profile
+ </panel.string>
+ <panel.string
+ name="info_text">
+ Info
+ </panel.string>
+ <panel.string
+ name="public_text">
+ (public)
+ </panel.string>
+ <panel.string
+ name="none_text">
+ (none)
+ </panel.string>
+ <panel.string
+ name="sale_pending_text">
+ (Sale Pending)
+ </panel.string>
+ <panel.string
+ name="no_selection_text">
+ No parcel selected.
+ </panel.string>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="Name:"
+ top="10"
+ width="100">
+ Name:
+ </text>
+ <line_editor
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left_pad="2"
+ max_length="63"
+ name="Name"
+ top_delta="0"
+ width="365" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="Description:"
+ width="100">
+ Description:
+ </text>
+ <text_editor
+ follows="left|top|right"
+ height="52"
+ layout="topleft"
+ left_pad="2"
+ name="Description"
+ top_delta="0"
+ width="365"
+ word_wrap="true" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="LandType"
+ top_pad="5"
+ width="100">
+ Type:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="2"
+ name="LandTypeText"
+ top_delta="0"
+ width="250">
+ Mainland / Homestead
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="ContentRating"
+ width="100">
+ Rating:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="2"
+ name="ContentRatingText"
+ top_delta="0"
+ width="250">
+ Adult
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="Owner:"
+ top_pad="5"
+ width="100">
+ Owner:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="2"
+ name="OwnerText"
+ width="240">
+ Leyla Linden
+ </text>
+ <button
+ follows="right"
+ height="23"
+ image_pressed="Info_Press"
+ image_unselected="Info_Over"
+ left_pad="3"
+ name="info_btn"
+ top_delta="-2"
+ width="16" />
+ <!-- <button
+ follows="left|top"
+ height="23"
+ label="Profile"
+ layout="topleft"
+ left_pad="4"
+ name="Profile..."
+ width="90" />-->
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="Group:"
+ top_pad="7"
+ width="100">
+ Group:
+ </text>
+ <!--TODO: HOOK UP GROUP ICON-->
+ <text
+ enabled="false"
+ follows="left|top"
+ height="16"
+ left_pad="2"
+ layout="topleft"
+ name="GroupText"
+ width="240">
+Leyla Linden </text>
+ <button
+ follows="right"
+ height="23"
+ image_pressed="Info_Press"
+ image_unselected="Info_Over"
+ left_pad="3"
+ name="info_btn"
+ top_delta="-2"
+ width="16" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Set"
+ layout="topleft"
+ left_pad="4"
+ right="-10"
+ name="Set..."
+ width="50"
+ top_delta="-2"/>
+ <check_box
+ enabled="false"
+ height="16"
+ label="Allow Deed to Group"
+ layout="topleft"
+ left="108"
+ name="check deed"
+ tool_tip="A group officer can deed this land to the group, so it will be supported by the group&apos;s land allocation."
+ top_pad="3"
+ width="146" />
+ <button
+ enabled="false"
+ follows="left|top"
+ height="23"
+ label="Deed"
+ layout="topleft"
+ left_pad="2"
+ right="-10"
+ name="Deed..."
+ tool_tip="You may only deed land if you are an officer in the selected group."
+ top_delta="-2"
+ width="90" />
+ <check_box
+ enabled="false"
+ height="16"
+ label="Owner Makes Contribution With Deed"
+ layout="topleft"
+ left="108"
+ name="check contrib"
+ tool_tip="When the land is deeded to the group, the former owner contributes enough land allocation to support it."
+ width="199"
+ top_pad="0"/>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="For Sale:"
+ width="100">
+ For Sale:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="2"
+ name="Not for sale."
+ width="186">
+ Not for sale
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="For Sale: Price L$[PRICE]."
+ width="226">
+ Price: L$[PRICE] (L$[PRICE_PER_SQM]/m²)
+ </text>
+ <text
+ enabled="false"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="SalePending"
+ top_pad="5"
+ width="324" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Sell Land"
+ layout="topleft"
+ left_pad="5"
+ right="-10"
+ name="Sell Land..."
+ width="145"
+ top_delta="-25"/>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="-199"
+ name="For sale to"
+ top_delta="20"
+ width="186">
+ For sale to: [BUYER]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="Sell with landowners objects in parcel."
+ top_pad="-3"
+ width="186">
+ Objects included in sale
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="Selling with no objects in parcel."
+ top_delta="0"
+ width="186">
+ Objects not included in sale
+ </text>
+ <button
+ follows="left|top"
+ height="23"
+ label="Cancel Land Sale"
+ label_selected="Cancel Land Sale"
+ layout="topleft"
+ right="-10"
+ name="Cancel Land Sale"
+ left_pad="5"
+ top_pad="-25"
+ width="145" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="Claimed:"
+ top="268"
+ width="100">
+ Claimed:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="2"
+ name="DateClaimText"
+ top_delta="0"
+ width="186">
+ Tue Aug 15 13:47:25 2006
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="PriceLabel"
+ top_pad="5"
+ width="100">
+ Area:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="2"
+ name="PriceText"
+ top_delta="0"
+ width="186">
+ 4048 m²
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="Traffic:"
+ top="308"
+ width="100">
+ Traffic:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="2"
+ name="DwellText"
+ top_delta="0"
+ width="186">
+ 0
+ </text>
+ <button
+ enabled="false"
+ follows="left|top"
+ height="23"
+ label="Buy Land"
+ layout="topleft"
+ left_delta="82"
+ name="Buy Land..."
+ top_pad="7"
+ width="100" />
+ <button
+ enabled="true"
+ follows="left|top"
+ height="23"
+ label="Script Info"
+ layout="topleft"
+ left="10"
+ name="Scripts..."
+ top_pad="1"
+ width="100" />
+ <button
+ enabled="false"
+ follows="left|top"
+ height="23"
+ label="Buy For Group"
+ layout="topleft"
+ right="-10"
+ name="Buy For Group..."
+ top_delta="0"
+ width="180" />
+ <button
+ enabled="false"
+ follows="left|top"
+ height="23"
+ label="Buy Pass"
+ layout="topleft"
+ left_delta="-105"
+ name="Buy Pass..."
+ tool_tip="A pass gives you temporary access to this land."
+ top_delta="0"
+ width="100" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Abandon Land"
+ layout="topleft"
+ right="-10"
+ name="Abandon Land..."
+ top_pad="-47"
+ width="180" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Reclaim Land"
+ layout="topleft"
+ left_delta="0"
+ name="Reclaim Land..."
+ top_delta="-61"
+ width="180" />
+ <button
+ enabled="false"
+ follows="left|top"
+ height="23"
+ label="Linden Sale"
+ layout="topleft"
+ left_delta="0"
+ name="Linden Sale..."
+ tool_tip="Land must be owned, set content, and not already for auction."
+ top_pad="2"
+ width="180" />
+ </panel>
+ <panel
+ border="true"
+ follows="all"
+ label="COVENANT"
+ layout="topleft"
+ left="0"
+ top="0"
+ help_topic="land_covenant_tab"
+ name="land_covenant_panel">
+ <panel.string
+ name="can_resell">
+ Purchased land in this region may be resold.
+ </panel.string>
+ <panel.string
+ name="can_not_resell">
+ Purchased land in this region may not be resold.
+ </panel.string>
+ <panel.string
+ name="can_change">
+ Purchased land in this region may be joined or subdivided.
+ </panel.string>
+ <panel.string
+ name="can_not_change">
+ Purchased land in this region may not be joined or subdivided.
+ </panel.string>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="estate_section_lbl"
+ top="10"
+ width="100">
+ Estate:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="0"
+ mouse_opaque="false"
+ name="estate_name_text"
+ top_delta="0"
+ width="260">
+ mainland
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="estate_owner_lbl"
+ width="100">
+ Owner:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="0"
+ mouse_opaque="false"
+ name="estate_owner_text"
+ width="300">
+ (none)
+ </text>
+ <text_editor
+ type="string"
+ length="1"
+ enabled="false"
+ follows="all"
+ handle_edit_keys_directly="true"
+ height="200"
+ layout="topleft"
+ left="10"
+ max_length="65535"
+ name="covenant_editor"
+ width="470"
+ word_wrap="true">
+ There is no Covenant provided for this Estate.
+ </text_editor>
+ <text
+ type="string"
+ length="1"
+ follows="right|top"
+ height="16"
+ halign="right"
+ layout="topleft"
+ right="-10"
+ top_pad="0"
+ mouse_opaque="false"
+ name="covenant_timestamp_text"
+ width="460">
+ Last Modified Wed Dec 31 16:00:00 1969
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="region_section_lbl"
+ width="100">
+ Region:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ mouse_opaque="false"
+ name="region_name_text"
+ width="150">
+ EricaVille
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="region_landtype_lbl"
+ width="100">
+ Type:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ mouse_opaque="false"
+ name="region_landtype_text"
+ width="150">
+ Mainland / Homestead
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="region_maturity_lbl"
+ width="100">
+ Rating:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ mouse_opaque="false"
+ name="region_maturity_text"
+ width="150">
+ Adult
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="resellable_lbl"
+ width="100">
+ Resale:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ mouse_opaque="false"
+ name="resellable_clause"
+ width="330">
+ Land in this region may not be resold.
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="30"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="changeable_lbl"
+ width="100">
+ Subdivide:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="30"
+ layout="topleft"
+ left_pad="10"
+ mouse_opaque="false"
+ name="changeable_clause"
+ word_wrap="true"
+ width="330">
+ Land in this region may not be joined/subdivided.
+ </text>
+ </panel>
+ <panel
+ border="true"
+ follows="all"
+ label="OBJECTS"
+ layout="topleft"
+ left="0"
+ top="0"
+ help_topic="land_objects_tab"
+ name="land_objects_panel">
+ <panel.string
+ name="objects_available_text">
+ [COUNT] out of [MAX] ([AVAILABLE] available)
+ </panel.string>
+ <panel.string
+ name="objects_deleted_text">
+ [COUNT] out of [MAX] ([DELETED] will be deleted)
+ </panel.string>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="parcel_object_bonus"
+ top="4"
+ visible="false"
+ width="364">
+ Region Object Bonus Factor: [BONUS]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="Simulator primitive usage:"
+ top_pad="4"
+ width="364">
+ Primative usage:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="190"
+ name="objects_available"
+ top_delta="0"
+ width="260">
+ [COUNT] out of [MAX] ([AVAILABLE] available)
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="Primitives parcel supports:"
+ top="44"
+ width="152">
+ Prims parcel supports:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="190"
+ name="object_contrib_text"
+ top_delta="0"
+ width="212">
+ [COUNT]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="Primitives on parcel:"
+ top="64"
+ width="152">
+ Prims on parcel:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="190"
+ name="total_objects_text"
+ top_delta="0"
+ width="48">
+ [COUNT]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left="28"
+ name="Owned by parcel owner:"
+ top="84"
+ width="176">
+ Owned by parcel owner:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left_delta="172"
+ name="owner_objects_text"
+ top_delta="0"
+ width="48">
+ [COUNT]
+ </text>
+ <button
+ bottom="100"
+ enabled="false"
+ follows="left|top"
+ height="23"
+ label="Show"
+ label_selected="Show"
+ layout="topleft"
+ name="ShowOwner"
+ right="-140"
+ width="60"
+ top_delta="-6"/>
+ <button
+ bottom="100"
+ enabled="false"
+ follows="left|top"
+ height="23"
+ label="Return"
+ layout="topleft"
+ name="ReturnOwner..."
+ right="-10"
+ tool_tip="Return objects to their owners."
+ width="119"
+ top_delta="0"/>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left="28"
+ name="Set to group:"
+ top_pad="5"
+ width="176">
+ Set to group:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left_delta="172"
+ name="group_objects_text"
+ top_delta="0"
+ width="48">
+ [COUNT]
+ </text>
+ <button
+ bottom="120"
+ enabled="false"
+ follows="left|top"
+ label="Show"
+ height="23"
+ label_selected="Show"
+ layout="topleft"
+ name="ShowGroup"
+ right="-140"
+ width="60"
+ top_delta="-6"/>
+ <button
+ bottom="120"
+ enabled="false"
+ follows="left|top"
+ height="23"
+ label="Return"
+ layout="topleft"
+ name="ReturnGroup..."
+ right="-10"
+ tool_tip="Return objects to their owners."
+ width="119"
+ top_delta="0"/>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left="28"
+ name="Owned by others:"
+ top_pad="5"
+ width="176">
+ Owned by others:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left_delta="172"
+ name="other_objects_text"
+ top_delta="0"
+ width="48">
+ [COUNT]
+ </text>
+ <button
+ bottom="140"
+ enabled="false"
+ follows="left|top"
+ height="23"
+ label="Show"
+ label_selected="Show"
+ layout="topleft"
+ name="ShowOther"
+ right="-140"
+ width="60"
+ top_delta="-6"/>
+ <button
+ bottom="140"
+ enabled="false"
+ follows="left|top"
+ height="23"
+ label="Return"
+ layout="topleft"
+ name="ReturnOther..."
+ right="-10"
+ tool_tip="Return objects to their owners."
+ width="119"
+ top_delta="0"/>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left="28"
+ name="Selected / sat upon:"
+ top_pad="5"
+ width="176">
+ Selected / sat upon:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left_delta="172"
+ name="selected_objects_text"
+ top_delta="0"
+ width="48">
+ [COUNT]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left="10"
+ name="Autoreturn"
+ top_pad="0"
+ width="294">
+ Auto return other Residents&apos; objects (minutes, 0 for off):
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ bottom="180"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ max_length="6"
+ name="clean other time"
+ right="-72"
+ width="56"
+ top_delta="-6"/>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left="10"
+ name="Object Owners:"
+ top_pad="10"
+ width="104">
+ Object Owners:
+ </text>
+ <button
+ follows="top|right"
+ height="23"
+ image_overlay="Refresh_Off"
+ layout="topleft"
+ name="Refresh List"
+ left_pad="5"
+ right="-183"
+ tool_tip="Refresh Object List"
+ width="20"
+ top_delta="-6"/>
+ <button
+ enabled="false"
+ follows="left|top"
+ height="23"
+ label="Return Objects"
+ layout="topleft"
+ left_pad="6"
+ name="Return objects..."
+ top_delta="0"
+ right="-10"
+ width="164" />
+ <name_list
+ column_padding="0"
+ draw_heading="true"
+ follows="all"
+ height="180"
+ layout="topleft"
+ left="10"
+ name="owner list"
+ name_column="name"
+ width="470">
+ <name_list.columns
+ label="Type"
+ name="type"
+ sort_column="online_status"
+ width="24" />
+ <name_list.columns
+ name="online_status"
+ width="-1" />
+ <name_list.columns
+ dynamic_width="true"
+ label="Name"
+ name="name" />
+ <name_list.columns
+ label="Count"
+ name="count"
+ width="60" />
+ <name_list.columns
+ label="Most Recent"
+ name="mostrecent"
+ width="170" />
+ </name_list>
+ </panel>
+ <panel
+ border="true"
+ follows="all"
+ label="OPTIONS"
+ layout="topleft"
+ help_topic="land_options_tab"
+ name="land_options_panel"
+ left="0"
+ top="0">
+ <panel.string
+ name="search_enabled_tooltip">
+ Let people see this parcel in search results
+ </panel.string>
+ <panel.string
+ name="search_disabled_small_tooltip">
+ This option is disabled because this parcel&apos;s area is 128 m² or smaller.
+Only large parcels can be listed in search.
+ </panel.string>
+ <panel.string
+ name="search_disabled_permissions_tooltip">
+ This option is disabled because you cannot modify this parcel&apos;s options.
+ </panel.string>
+ <panel.string
+ name="mature_check_mature">
+ Moderate Content
+ </panel.string>
+ <panel.string
+ name="mature_check_adult">
+ Adult Content
+ </panel.string>
+ <panel.string
+ name="mature_check_mature_tooltip">
+ Your parcel information or content is considered moderate.
+ </panel.string>
+ <panel.string
+ name="mature_check_adult_tooltip">
+ Your parcel information or content is considered adult.
+ </panel.string>
+ <panel.string
+ name="landing_point_none">
+ (none)
+ </panel.string>
+ <panel.string
+ name="push_restrict_text">
+ No Pushing
+ </panel.string>
+ <panel.string
+ name="push_restrict_region_text">
+ No Pushing (Region Override)
+ </panel.string>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ text_color="white"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="allow_label"
+ top="10"
+ width="278">
+ Allow other Residents to:
+ </text>
+ <check_box
+ height="16"
+ label="Edit Terrain"
+ layout="topleft"
+ left="14"
+ name="edit land check"
+ tool_tip="If checked, anyone can terraform your land. It is best to leave this unchecked, as you can always edit your own land."
+ top_pad="4"
+ width="147i" />
+ <check_box
+ height="16"
+ label="Fly"
+ layout="topleft"
+ name="check fly"
+ tool_tip="If checked, Residents can fly on your land. If unchecked, they can only fly into and over your land."
+ left_pad="4"
+ width="150" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="14"
+ name="allow_label2"
+ width="150">
+ Build:
+ </text>
+ <check_box
+ height="16"
+ label="Everyone"
+ layout="topleft"
+ left_pad="2"
+ name="edit objects check"
+ width="120" />
+ <check_box
+ height="16"
+ label="Group"
+ layout="topleft"
+ left_pad="2"
+ name="edit group objects check"
+ width="70" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="14"
+ name="allow_label3"
+ width="150">
+ Object Entry:
+ </text>
+ <check_box
+ height="16"
+ label="Everyone"
+ layout="topleft"
+ left_pad="2"
+ name="all object entry check"
+ top_delta="0"
+ width="120" />
+ <check_box
+ height="16"
+ label="Group"
+ layout="topleft"
+ left_pad="2"
+ name="group object entry check"
+ top_delta="0"
+ width="70" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="14"
+ name="allow_label4"
+ width="150">
+ Run Scripts:
+ </text>
+ <check_box
+ height="16"
+ label="Everyone"
+ layout="topleft"
+ left_pad="2"
+ name="check other scripts"
+ top_delta="0"
+ width="120" />
+ <check_box
+ height="16"
+ label="Group"
+ layout="topleft"
+ left_pad="2"
+ name="check group scripts"
+ top_delta="0"
+ width="70" />
+ <text
+ type="string"
+ text_color="white"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="land_options_label"
+ width="278">
+ Land Options:
+ </text>
+ <check_box
+ height="16"
+ label="Safe (no damage)"
+ layout="topleft"
+ left="14"
+ name="check safe"
+ tool_tip="If checked, sets the land to Safe, disabling damage combat. If cleared, damage combat is enabled."
+ top_pad="5"
+ width="200" />
+ <check_box
+ height="16"
+ label="No Pushing"
+ layout="topleft"
+ left_pad="5"
+ name="PushRestrictCheck"
+ tool_tip="Prevents scripts from pushing. Checking this option may be useful for preventing disruptive behavior on your land."
+ top_delta="0"
+ width="119" />
+ <check_box
+ height="16"
+ label="Show Place in Search (L$30/week)"
+ layout="topleft"
+ left="14"
+ name="ShowDirectoryCheck"
+ tool_tip="Let people see this parcel in search results"
+ width="430" />
+ <combo_box
+ enabled="false"
+ height="23"
+ layout="topleft"
+ left="30"
+ name="land category with adult"
+ visible="false"
+ width="130">
+ <combo_box.item
+ label="Any Category"
+ name="item0"
+ value="any" />
+ <combo_box.item
+ label="Linden Location"
+ name="item1"
+ value="linden" />
+ <combo_box.item
+ label="Adult"
+ name="item2"
+ value="adult" />
+ <combo_box.item
+ label="Arts &amp; Culture"
+ name="item3"
+ value="arts" />
+ <combo_box.item
+ label="Business"
+ name="item4"
+ value="store" />
+ <combo_box.item
+ label="Educational"
+ name="item5"
+ value="educational" />
+ <combo_box.item
+ label="Gaming"
+ name="item6"
+ value="game" />
+ <combo_box.item
+ label="Hangout"
+ name="item7"
+ value="gather" />
+ <combo_box.item
+ label="Newcomer Friendly"
+ name="item8"
+ value="newcomer" />
+ <combo_box.item
+ label="Parks &amp; Nature"
+ name="item9"
+ value="park" />
+ <combo_box.item
+ label="Residential"
+ name="item10"
+ value="home" />
+ <combo_box.item
+ label="Shopping"
+ name="item11"
+ value="shopping" />
+ <combo_box.item
+ label="Other"
+ name="item12"
+ value="other" />
+ </combo_box>
+ <combo_box
+ enabled="false"
+ height="23"
+ layout="topleft"
+ left="30"
+ name="land category"
+ visible="false"
+ width="130">
+ <combo_box.item
+ label="Any Category"
+ name="item0"
+ value="any" />
+ <combo_box.item
+ label="Linden Location"
+ name="item1"
+ value="linden" />
+ <combo_box.item
+ label="Arts &amp; Culture"
+ name="item3"
+ value="arts" />
+ <combo_box.item
+ label="Business"
+ name="item4"
+ value="store" />
+ <combo_box.item
+ label="Educational"
+ name="item5"
+ value="educational" />
+ <combo_box.item
+ label="Gaming"
+ name="item6"
+ value="game" />
+ <combo_box.item
+ label="Hangout"
+ name="item7"
+ value="gather" />
+ <combo_box.item
+ label="Newcomer Friendly"
+ name="item8"
+ value="newcomer" />
+ <combo_box.item
+ label="Parks &amp; Nature"
+ name="item9"
+ value="park" />
+ <combo_box.item
+ label="Residential"
+ name="item10"
+ value="home" />
+ <combo_box.item
+ label="Shopping"
+ name="item11"
+ value="shopping" />
+ <combo_box.item
+ label="Other"
+ name="item12"
+ value="other" />
+ </combo_box>
+ <check_box
+ height="16"
+ label="Moderate Content"
+ layout="topleft"
+ left="14"
+ name="MatureCheck"
+ top="177"
+ tool_tip=" "
+ width="107" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="Snapshot:"
+ text_color="white"
+ top="220"
+ width="200">
+ Snapshot:
+ </text>
+ <texture_picker
+ follows="left|top"
+ height="150"
+ layout="topleft"
+ left="14"
+ name="snapshot_ctrl"
+ tool_tip="Click to choose a picture"
+ width="195" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="220"
+ top="180"
+ text_color="white"
+ name="landing_point"
+ word_wrap="true"
+ width="200">
+ Landing Point: [LANDING]
+ </text>
+ <button
+ follows="right|top"
+ height="23"
+ label="Set"
+ label_selected="Set"
+ layout="topleft"
+ name="Set"
+ right="-68"
+ tool_tip="Sets the landing point where visitors arrive. Sets to your avatar&apos;s location inside this parcel."
+ width="50" />
+ <button
+ follows="right|top"
+ height="23"
+ label="Clear"
+ label_selected="Clear"
+ layout="topleft"
+ left_pad="5"
+ name="Clear"
+ tool_tip="Clear the landing point"
+ right="-10"
+ width="50" />
+ <text
+ type="string"
+ length="1"
+ text_color="white"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="220"
+ top_pad="10"
+ name="Teleport Routing: "
+ width="200">
+ Teleport Routing:
+ </text>
+ <combo_box
+ height="23"
+ layout="topleft"
+ name="landing type"
+ top_pad="3"
+ tool_tip="Teleport Routing -- select how to handle teleports onto your land"
+ width="120">
+ <combo_box.item
+ enabled="true"
+ label="Blocked"
+ name="Blocked"
+ value="Blocked" />
+ <combo_box.item
+ enabled="true"
+ label="Landing Point"
+ name="LandingPoint"
+ value="Landing Point" />
+ <combo_box.item
+ enabled="true"
+ label="Anywhere"
+ name="Anywhere"
+ value="Anywhere" />
+ </combo_box>
+ </panel>
+ <panel
+ border="true"
+ follows="all"
+ label="MEDIA"
+ layout="topleft"
+ left="0"
+ top="0"
+ help_topic="land_media_tab"
+ name="land_media_panel">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="with media:"
+ top="10"
+ width="100">
+ Type:
+ </text>
+ <combo_box
+ height="23"
+ layout="topleft"
+ left_pad="0"
+ name="media type"
+ tool_tip="Specify if the URL is a movie, web page, or other media"
+ width="120"
+ top_delta="0"/>
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="mime_type"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="at URL:"
+ width="100"
+ top_pad="10">
+ Home Page:
+ </text>
+ <line_editor
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left_pad="0"
+ max_length="255"
+ name="media_url"
+ select_on_focus="true"
+ width="300"
+ top_delta="0"/>
+ <button
+ follows="right|top"
+ height="23"
+ label="Set"
+ layout="topleft"
+ left_pad="5"
+ name="set_media_url"
+ width="50"
+ top_delta="0"/>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="CurrentURL:"
+ width="100"
+ top_pad="10">
+ Current Page:
+ </text>
+ <button
+ follows="top|right"
+ height="23"
+ image_overlay="Refresh_Off"
+ layout="topleft"
+ name="reset_media_url"
+ left_pad="0"
+ tool_tip="Refresh URL"
+ width="23"
+ top_delta="0"/>
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="current_url"
+ width="300" />
+ <check_box
+ follows="top|left"
+ height="16"
+ label="Hide URL"
+ layout="topleft"
+ left_delta="-36"
+ name="hide_media_url"
+ tool_tip="Checking this option will hide the media url to any non-authorized viewers of this parcel information. Note this is not available for HTML types."
+ width="50"
+ top_pad="5"/>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left="10"
+ name="Description:"
+ width="364"
+ top_pad="10">
+ Description:
+ </text>
+ <line_editor
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="110"
+ max_length="255"
+ name="url_description"
+ select_on_focus="true"
+ tool_tip="Text displayed next to play/load button"
+ top_delta="0"
+ width="300" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="Media texture:"
+ top_pad="10"
+ width="364"
+ word_wrap="true">
+ Replace Texture:
+ </text>
+ <texture_picker
+ allow_no_texture="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ layout="topleft"
+ left="110"
+ name="media texture"
+ tool_tip="Click to choose a picture"
+ top_delta="0"
+ width="64" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="80"
+ layout="topleft"
+ left_pad="8"
+ name="replace_texture_help"
+ width="300"
+ word_wrap="true"
+ top_delta="0">
+ Objects using this texture will show the movie or web page after you click the play arrow. Select the thumbnail to choose a different texture.
+ </text>
+ <check_box
+ height="16"
+ label="Auto scale"
+ layout="topleft"
+ left="107"
+ name="media_auto_scale"
+ top_pad="-10"
+ tool_tip="Checking this option will scale the content for this parcel automatically. It may be slightly slower and lower quality visually but no other texture scaling or alignment will be required."
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="media_size"
+ tool_tip="Size to render Web media, leave 0 for default."
+ width="100"
+ top_pad="10">
+ Size:
+ </text>
+ <spinner
+ decimal_digits="0"
+ enabled="false"
+ follows="left|top"
+ halign="right"
+ height="23"
+ increment="1"
+ initial_value="0"
+ layout="topleft"
+ left_pad="0"
+ max_val="1024"
+ name="media_size_width"
+ tool_tip="Size to render Web media, leave 0 for default."
+ top_delta="0"
+ width="64" />
+ <spinner
+ decimal_digits="0"
+ enabled="false"
+ follows="left|top"
+ halign="right"
+ height="23"
+ increment="1"
+ initial_value="0"
+ layout="topleft"
+ left_pad="16"
+ max_val="1024"
+ name="media_size_height"
+ tool_tip="Size to render Web media, leave 0 for default."
+ top_delta="0"
+ width="64" />
+ <text
+ type="string"
+ length="1"
+ bottom_delta="0"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="5"
+ name="pixels"
+ right="-10">
+ pixels
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="Options:"
+ top_pad="10"
+ width="100">
+ Options:
+ </text>
+ <check_box
+ height="16"
+ label="Loop"
+ layout="topleft"
+ left_pad="-3"
+ name="media_loop"
+ tool_tip="Play media in a loop. When the media has finished playing, it will restart from the beginning."
+ top_delta="-1"
+ width="200" />
+ </panel>
+ <panel
+ border="true"
+ follows="all"
+ label="SOUND"
+ layout="topleft"
+ left="0"
+ top="0"
+ help_topic="land_audio_tab"
+ name="land_audio_panel">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ top="10"
+ name="MusicURL:"
+ width="364">
+ Music URL:
+ </text>
+ <line_editor
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left="100"
+ max_length="255"
+ name="music_url"
+ top_delta="0"
+ right="-15"
+ select_on_focus="true" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="Sound:"
+ top_pad="10"
+ width="100">
+ Sound:
+ </text>
+ <check_box
+ height="16"
+ label="Restrict gesture and object sounds to this parcel"
+ layout="topleft"
+ name="check sound local"
+ left_pad="0"
+ width="292" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="Voice settings:"
+ top_pad="10"
+ width="100">
+ Voice:
+ </text>
+ <check_box
+ height="16"
+ label="Enable Voice"
+ layout="topleft"
+ left_pad="0"
+ name="parcel_enable_voice_channel"
+ width="300" />
+ <check_box
+ enabled="false"
+ height="16"
+ label="Enable Voice (established by the Estate)"
+ layout="topleft"
+ left="110"
+ name="parcel_enable_voice_channel_is_estate_disabled"
+ top_delta="0"
+ width="300" />
+ <check_box
+ height="16"
+ label="Restrict Voice to this parcel"
+ layout="topleft"
+ left="110"
+ name="parcel_enable_voice_channel_local"
+ width="300" />
+ </panel>
+ <panel
+ border="true"
+ follows="all"
+ label="ACCESS"
+ layout="topleft"
+ left="0"
+ top="0"
+ help_topic="land_access_tab"
+ name="land_access_panel">
+ <panel.string
+ name="access_estate_defined">
+ (Defined by the Estate)
+ </panel.string>
+ <panel.string
+ name="estate_override">
+ One or more of these options is set at the estate level
+ </panel.string>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="Limit access to this parcel to:"
+ text_color="White"
+ top="10"
+ width="400">
+ Access To This Parcel
+ </text>
+ <check_box
+ follows="top|left"
+ height="16"
+ label="Allow Public Access [MATURITY]"
+ layout="topleft"
+ left_delta="0"
+ name="public_access"
+ top_pad="5"
+ width="278" />
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ height="16"
+ layout="topleft"
+ left_delta="20"
+ name="Only Allow"
+ top="49"
+ width="278">
+ Restrict Access to Residents verified by:
+ </text>
+ <check_box
+ follows="top|left"
+ height="16"
+ label="Payment Information on File [ESTATE_PAYMENT_LIMIT]"
+ layout="topleft"
+ left_delta="0"
+ name="limit_payment"
+ tool_tip="Ban unidentified Residents."
+ top_pad="4"
+ width="278" />
+ <check_box
+ follows="top|left"
+ height="16"
+ label="Age Verification [ESTATE_AGE_LIMIT]"
+ layout="topleft"
+ left_delta="0"
+ name="limit_age_verified"
+ tool_tip="Ban Residents who have not verified their age. See the [SUPPORT_SITE] for more information."
+ top_pad="4"
+ width="278" />
+ <check_box
+ height="16"
+ label="Allow Group Access: [GROUP]"
+ layout="topleft"
+ left="8"
+ name="GroupCheck"
+ tool_tip="Set group in the General tab."
+ top="109"
+ width="278" />
+ <check_box
+ enabled="false"
+ height="16"
+ label="Sell passes to:"
+ layout="topleft"
+ left_delta="0"
+ name="PassCheck"
+ tool_tip="Allows temporary access to this parcel"
+ top_pad="4"
+ width="120" />
+ <combo_box
+ height="23"
+ layout="topleft"
+ left_pad="22"
+ name="pass_combo"
+ top_delta="0"
+ width="100">
+ <combo_box.item
+ label="Anyone"
+ name="Anyone"
+ value="anyone" />
+ <combo_box.item
+ label="Group"
+ name="Group"
+ value="group" />
+ </combo_box>
+ <spinner
+ enabled="false"
+ follows="left|top"
+ height="23"
+ increment="1"
+ initial_value="10"
+ label="Price in L$:"
+ label_width="120"
+ layout="topleft"
+ left="28"
+ max_val="500"
+ min_val="1"
+ name="PriceSpin"
+ top_pad="5"
+ width="200" />
+ <spinner
+ enabled="false"
+ follows="left|top"
+ height="23"
+ increment="0.25"
+ initial_value="1"
+ label="Hours of access:"
+ label_width="120"
+ layout="topleft"
+ left_delta="0"
+ max_val="24"
+ min_val="0.01"
+ name="HoursSpin"
+ top_pad="5"
+ width="200" />
+ <panel
+ name="Allowed_layout_panel"
+ follows="top|left"
+ left="10"
+ height="170"
+ top_pad="8"
+ width="240">
+ <text
+ type="string"
+ length="1"
+ follows="left|right|top"
+ height="16"
+ label="Always Allow"
+ layout="topleft"
+ left="0"
+ name="AllowedText"
+ top="0"
+ width="230">
+ Allowed Residents
+ </text>
+ <name_list
+ column_padding="0"
+ follows="top|bottom"
+ heading_height="14"
+ height="120"
+ layout="topleft"
+ left="0"
+ multi_select="true"
+ name="AccessList"
+ tool_tip="([LISTED] listed, [MAX] max)"
+ width="230" />
+ <button
+ follows="bottom"
+ height="23"
+ label="Add"
+ layout="topleft"
+ left="0"
+ name="add_allowed"
+ width="100" />
+ <button
+ follows="bottom"
+ height="23"
+ label="Remove"
+ label_selected="Remove"
+ layout="topleft"
+ left_pad="10"
+ name="remove_allowed"
+ right="-1"
+ width="100" />
+ </panel>
+ <panel
+ name="Banned_layout_panel"
+ follows="top|right"
+ height="170"
+ width="240"
+ left_pad="2">
+ <text
+ type="string"
+ length="1"
+ follows="left|right|top"
+ height="16"
+ label="Ban"
+ layout="topleft"
+ left="0"
+ name="BanCheck"
+ top="0"
+ width="200">
+ Banned Residents
+ </text>
+ <name_list
+ column_padding="0"
+ follows="top|bottom"
+ heading_height="14"
+ height="120"
+ layout="topleft"
+ left="0"
+ multi_select="true"
+ name="BannedList"
+ tool_tip="([LISTED] listed, [MAX] max)"
+ width="230" />
+ <button
+ follows="bottom"
+ height="23"
+ label="Add"
+ layout="topleft"
+ left="0"
+ name="add_banned"
+ width="100" />
+ <button
+ enabled="false"
+ follows="bottom"
+ height="23"
+ label="Remove"
+ label_selected="Remove"
+ layout="topleft"
+ left_pad="10"
+ name="remove_banned"
+ right="-1"
+ width="100" />
+ </panel>
+ </panel>
+ </tab_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_activeim.xml b/indra/newview/skins/default/xui/en/floater_activeim.xml
new file mode 100644
index 0000000000..96fe0aa70c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_activeim.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ name="floater_activeim"
+ help_topic="floater_activeim"
+ title="ACTIVE IM"
+ top="26"
+ left="0"
+ height="22"
+ width="320"
+ follows="right|bottom"
+ background_visible="true"
+ can_close="true"
+ can_dock="true"
+ can_minimize="false"
+ visible="true"
+ bg_alpha_color="0 0 0 0">
+ <scroll_container
+ follows="top|bottom"
+ layout="topleft"
+ top="20"
+ left="1"
+ width="320"
+ height="2"
+ name="panel_list_container">
+ <scrolling_panel_list
+ follows="left|right"
+ layout="topleft"
+ left="1"
+ name="chiclet_row_panel_list"
+ width="318"/>
+ </scroll_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_animation_preview.xml b/indra/newview/skins/default/xui/en/floater_animation_preview.xml
new file mode 100644
index 0000000000..4f4288b654
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_animation_preview.xml
@@ -0,0 +1,545 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ height="610"
+ layout="topleft"
+ name="Animation Preview"
+ help_topic="animation_preview"
+ width="280">
+ <floater.string
+ name="failed_to_initialize">
+ Failed to initialize motion
+ </floater.string>
+ <floater.string
+ name="anim_too_long">
+ Animation file is [LENGTH] seconds in length.
+
+Maximum animation length is [MAX_LENGTH] seconds.
+ </floater.string>
+ <floater.string
+ name="failed_file_read">
+ Unable to read animation file.
+
+[STATUS]
+ </floater.string>
+ <floater.string
+ name="E_ST_OK">
+ Ok
+ </floater.string>
+ <floater.string
+ name="E_ST_EOF">
+ Premature end of file.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_CONSTRAINT">
+ Cannot read constraint definition.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_FILE">
+ Cannot open BVH file.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_HIER">
+ Invalid HIERARCHY header.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_JOINT">
+ Cannot find ROOT or JOINT.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_NAME">
+ Cannot get JOINT name.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_OFFSET">
+ Cannot find OFFSET.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_CHANNELS">
+ Cannot find CHANNELS.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_ROTATION">
+ Cannot get rotation order.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_AXIS">
+ Cannot get rotation axis.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_MOTION">
+ Cannot find MOTION.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_FRAMES">
+ Cannot get number of frames.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_FRAME_TIME">
+ Cannot get frame time.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_POS">
+ Cannot get position values.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_ROT">
+ Cannot get rotation values.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_XLT_FILE">
+ Cannot open translation file.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_XLT_HEADER">
+ Cannot read translation header.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_XLT_NAME">
+ Cannot read translation names.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_XLT_IGNORE">
+ Cannot read translation ignore value.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_XLT_RELATIVE">
+ Cannot read translation relative value.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_XLT_OUTNAME">
+ Cannot read translation outname value.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_XLT_MATRIX">
+ Cannot read translation matrix.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_XLT_MERGECHILD">
+ Cannot get mergechild name.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_XLT_MERGEPARENT">
+ Cannot get mergeparent name.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_XLT_PRIORITY">
+ Cannot get priority value.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_XLT_LOOP">
+ Cannot get loop value.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_XLT_EASEIN">
+ Cannot get easeIn values.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_XLT_EASEOUT">
+ Cannot get easeOut values.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_XLT_HAND">
+ Cannot get hand morph value.
+ </floater.string>
+ <floater.string
+ name="E_ST_NO_XLT_EMOTE">
+ Cannot read emote name.
+ </floater.string>
+ <text
+ type="string"
+ length="1"
+ bottom="42"
+ follows="top|left"
+ height="23"
+ layout="topleft"
+ left="10"
+ name="name_label">
+ Name:
+ </text>
+ <line_editor
+ bottom_delta="0"
+ follows="top|left|right"
+ height="23"
+ layout="topleft"
+ left="100"
+ name="name_form"
+ right="-10" />
+ <text
+ type="string"
+ length="1"
+ top_pad="5"
+ follows="top|left"
+ height="23"
+ layout="topleft"
+ left="10"
+ name="description_label">
+ Description:
+ </text>
+ <line_editor
+ bottom_delta="0"
+ follows="top|left|right"
+ height="23"
+ layout="topleft"
+ left="100"
+ name="description_form"
+ right="-10" />
+ <spinner
+ decimal_digits="0"
+ follows="left|top"
+ height="23"
+ increment="1"
+ initial_value="0"
+ label="Priority"
+ label_width="88"
+ layout="topleft"
+ left="10"
+ max_val="4"
+ name="priority"
+ tool_tip="Controls which other animations can be overridden by this animation"
+ width="160" />
+ <check_box
+ top_pad="0"
+ height="14"
+ label="Loop"
+ layout="topleft"
+ left="10"
+ width="100"
+ name="loop_check"
+ tool_tip="Makes this animation loop" />
+ <spinner
+ follows="left|top"
+ height="23"
+ increment="1"
+ initial_value="0"
+ label="In(%)"
+ label_width="49"
+ layout="topleft"
+ top_pad="5"
+ left="30"
+ max_val="100"
+ name="loop_in_point"
+ tool_tip="Sets point in animation that looping returns to"
+ width="115" />
+ <spinner
+ bottom_delta="0"
+ follows="left|top"
+ height="23"
+ increment="1"
+ initial_value="0"
+ label="Out(%)"
+ layout="topleft"
+ left_pad="10"
+ max_val="100"
+ name="loop_out_point"
+ tool_tip="Sets point in animation that ends a loop"
+ label_width="49"
+ width="115" />
+ <text
+ type="string"
+ length="1"
+ top_pad="0"
+ follows="top|left"
+ height="23"
+ width="110"
+ word_wrap="true"
+ layout="topleft"
+ left="10"
+ name="hand_label">
+ Hand Pose
+ </text>
+ <combo_box
+ height="23"
+ layout="topleft"
+ left_pad="0"
+ name="hand_pose_combo"
+ tool_tip="Controls what hands do during animation"
+ width="150">
+ <combo_box.item
+ label="Spread"
+ name="Spread"
+ value="" />
+ <combo_box.item
+ label="Relaxed"
+ name="Relaxed"
+ value="Hands_Relaxed" />
+ <combo_box.item
+ label="Point Both"
+ name="PointBoth"
+ value="Hands_Point" />
+ <combo_box.item
+ label="Fist"
+ name="Fist"
+ value="Hands_Fist" />
+ <combo_box.item
+ label="Relaxed Left"
+ name="RelaxedLeft"
+ value="Hands_Relaxed_L" />
+ <combo_box.item
+ label="Point Left"
+ name="PointLeft"
+ value="Hands_Point_L" />
+ <combo_box.item
+ label="Fist Left"
+ name="FistLeft"
+ value="Hands_Fist_L" />
+ <combo_box.item
+ label="Relaxed Right"
+ name="RelaxedRight"
+ value="Hands_Relaxed_R" />
+ <combo_box.item
+ label="Point Right"
+ name="PointRight"
+ value="Hands_Point_R" />
+ <combo_box.item
+ label="Fist Right"
+ name="FistRight"
+ value="Hands_Fist_R" />
+ <combo_box.item
+ label="Salute Right"
+ name="SaluteRight"
+ value="Hands_Salute_R" />
+ <combo_box.item
+ label="Typing"
+ name="Typing"
+ value="Hands_Typing" />
+ <combo_box.item
+ label="Peace Right"
+ name="PeaceRight"
+ value="Hands_Peace_R" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ top_pad="5"
+ follows="top|left"
+ height="23"
+ width="110"
+ word_wrap="true"
+ layout="topleft"
+ left="10"
+ name="emote_label">
+ Expression
+ </text>
+ <combo_box
+ height="23"
+ width="150"
+ layout="topleft"
+ left_pad="0"
+ name="emote_combo"
+ tool_tip="Controls what face does during animation">
+ <combo_box.item
+ label="(None)"
+ name="[None]" />
+ <combo_box.item
+ label="Aaaaah"
+ name="Aaaaah" />
+ <combo_box.item
+ label="Afraid"
+ name="Afraid" />
+ <combo_box.item
+ label="Angry"
+ name="Angry" />
+ <combo_box.item
+ label="Big Smile"
+ name="BigSmile" />
+ <combo_box.item
+ label="Bored"
+ name="Bored" />
+ <combo_box.item
+ label="Cry"
+ name="Cry" />
+ <combo_box.item
+ label="Disdain"
+ name="Disdain" />
+ <combo_box.item
+ label="Embarrassed"
+ name="Embarrassed" />
+ <combo_box.item
+ label="Frown"
+ name="Frown" />
+ <combo_box.item
+ label="Kiss"
+ name="Kiss" />
+ <combo_box.item
+ label="Laugh"
+ name="Laugh" />
+ <combo_box.item
+ label="Plllppt"
+ name="Plllppt" />
+ <combo_box.item
+ label="Repulsed"
+ name="Repulsed" />
+ <combo_box.item
+ label="Sad"
+ name="Sad" />
+ <combo_box.item
+ label="Shrug"
+ name="Shrug" />
+ <combo_box.item
+ label="Smile"
+ name="Smile" />
+ <combo_box.item
+ label="Surprise"
+ name="Surprise" />
+ <combo_box.item
+ label="Wink"
+ name="Wink" />
+ <combo_box.item
+ label="Worry"
+ name="Worry" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ top_pad="5"
+ follows="top|left"
+ height="23"
+ width="110"
+ word_wrap="true"
+ layout="topleft"
+ left="10"
+ name="preview_label">
+ Preview while
+ </text>
+ <combo_box
+ height="23"
+ width="150"
+ layout="topleft"
+ left_pad="0"
+ name="preview_base_anim"
+ tool_tip="Use this to test your animation behavior while your avatar performs common actions.">
+ <combo_box.item
+ label="Standing"
+ name="Standing" />
+ <combo_box.item
+ label="Walking"
+ name="Walking" />
+ <combo_box.item
+ label="Sitting"
+ name="Sitting" />
+ <combo_box.item
+ label="Flying"
+ name="Flying" />
+ </combo_box>
+ <spinner
+ follows="left|top"
+ height="23"
+ increment="0.01"
+ initial_value="0"
+ label="Ease In (sec)"
+ label_width="110"
+ layout="topleft"
+ left="10"
+ max_val="10"
+ name="ease_in_time"
+ tool_tip="Amount of time (in seconds) over which animations blends in"
+ top_pad="10"
+ width="200" />
+ <spinner
+ follows="left|top"
+ height="23"
+ increment="0.01"
+ initial_value="0"
+ label="Ease Out (sec)"
+ label_width="110"
+ layout="topleft"
+ top_pad="0"
+ max_val="10"
+ name="ease_out_time"
+ tool_tip="Amount of time (in seconds) over which animations blends out"
+ width="200" />
+ <button
+ follows="top|right"
+ height="23"
+ image_overlay="Play_Over"
+ image_unselected="SegmentedBtn_Left_Off"
+ image_selected="SegmentedBtn_Left_On_Selected"
+ image_disabled_selected="SegmentedBtn_Left_Selected_Disabled"
+ image_disabled="SegmentedBtn_Left_Disabled"
+ image_pressed="SegmentedBtn_Left_Press"
+ image_pressed_selected="SegmentedBtn_Left_Selected_Press"
+ layout="topleft"
+ left="10"
+ name="play_btn"
+ tool_tip="Play your animation"
+ top_pad="0"
+ width="23" />
+ <button
+ visible = "false"
+ follows="top|right"
+ height="23"
+ image_overlay="Pause_Over"
+ image_unselected="SegmentedBtn_Left_Off"
+ image_selected="SegmentedBtn_Left_On_Selected"
+ image_disabled_selected="SegmentedBtn_Left_Selected_Disabled"
+ image_disabled="SegmentedBtn_Left_Disabled"
+ image_pressed="SegmentedBtn_Left_Press"
+ image_pressed_selected="SegmentedBtn_Left_Selected_Press"
+ layout="topleft"
+ left="10"
+ name="pause_btn"
+ tool_tip="Pause your animation"
+ top_pad="-23"
+ width="23" />
+ <button
+ follows="top|right"
+ height="23"
+ image_overlay="StopReload_Over"
+ image_unselected="SegmentedBtn_Right_Off"
+ image_selected="SegmentedBtn_Right_On_Selected"
+ image_disabled_selected="SegmentedBtn_Right_Selected_Disabled"
+ image_disabled="SegmentedBtn_Right_Disabled"
+ image_pressed="SegmentedBtn_Right_Press"
+ image_pressed_selected="SegmentedBtn_Right_Selected_Press"
+ layout="topleft"
+ name="stop_btn"
+ tool_tip="Stop animation playback"
+ top_delta="0"
+ left_delta="23"
+ width="23" />
+ <slider
+ left_pad="10"
+ follows="top|right"
+ height="23"
+ width="200"
+ increment="0.0001"
+ initial_value="0"
+ layout="topleft"
+ name="playback_slider"
+ show_text="false" />
+ <text
+ type="string"
+ length="1"
+ height="72"
+ word_wrap="true"
+ top_pad="5"
+ text_color="EmphasisColor"
+ follows="top|left"
+ layout="topleft"
+ left="70"
+ name="bad_animation_text">
+ Unable to read animation file.
+
+We recommend BVH files exported from Poser 4.
+ </text>
+ <button
+ top="580"
+ follows="bottom|left"
+ height="23"
+ label="Upload (L$[AMOUNT])"
+ layout="topleft"
+ left="10"
+ name="ok_btn"
+ width="128" />
+ <button
+ top="580"
+ follows="bottom|left"
+ height="23"
+ label="Cancel"
+ layout="topleft"
+ name="cancel_btn"
+ left="142"
+ width="128" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_auction.xml b/indra/newview/skins/default/xui/en/floater_auction.xml
new file mode 100644
index 0000000000..9c6d114c4c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_auction.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="412"
+ layout="topleft"
+ min_height="412"
+ min_width="420"
+ name="floater_auction"
+ help_topic="floater_auction"
+ title="START LINDEN LAND SALE"
+ width="420">
+ <floater.string
+ name="already for sale">
+ You cannot auction parcels which are already for sale.
+ </floater.string>
+ <icon
+ bottom="280"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="4"
+ name="snapshot_icon"
+ right="-4"
+ top="24" />
+ <text
+ follows="left|right|bottom"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="parcel_text"
+ top_pad="12"
+ width="400" />
+ <check_box
+ control_name="AuctionShowFence"
+ follows="left|bottom"
+ height="16"
+ initial_value="true"
+ label="Include yellow selection fence"
+ layout="topleft"
+ left_delta="0"
+ name="fence_check"
+ top_pad="12"
+ width="199" />
+ <button
+ follows="left|bottom"
+ height="20"
+ label="Snapshot"
+ label_selected="Snapshot"
+ layout="topleft"
+ left_delta="0"
+ name="snapshot_btn"
+ top_pad="4"
+ width="150">
+ <button.commit_callback
+ function="ClickSnapshot" />
+ </button>
+ <button
+ follows="left|bottom"
+ height="20"
+ label="Sell to Anyone"
+ label_selected="Sell to Anyone"
+ layout="topleft"
+ left_delta="0"
+ name="sell_to_anyone_btn"
+ top_pad="4"
+ width="150">
+ <button.commit_callback
+ function="ClickSellToAnyone" />
+ </button>
+ <button
+ follows="left|bottom"
+ height="20"
+ label="Clear Settings"
+ label_selected="Clear Settings"
+ layout="topleft"
+ left_delta="0"
+ name="reset_parcel_btn"
+ top_pad="4"
+ width="150">
+ <button.commit_callback
+ function="ClickResetParcel" />
+ </button>
+ <button
+ follows="left|bottom"
+ height="20"
+ label="Start Auction"
+ label_selected="Start Auction"
+ layout="topleft"
+ left_pad="4"
+ name="start_auction_btn"
+ top_delta="0"
+ width="150">
+ <button.commit_callback
+ function="ClickStartAuction" />
+ </button>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
new file mode 100644
index 0000000000..f59badfcb4
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
@@ -0,0 +1,226 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="350"
+ layout="topleft"
+ min_height="200"
+ min_width="265"
+ name="avatarpicker"
+ help_topic="avatarpicker"
+ title="CHOOSE RESIDENT"
+ width="265">
+ <floater.string
+ name="not_found">
+ &apos;[TEXT]&apos; not found
+ </floater.string>
+ <floater.string
+ name="no_one_near">
+ No one near
+ </floater.string>
+ <floater.string
+ name="no_results">
+ No results
+ </floater.string>
+ <floater.string
+ name="searching">
+ Searching...
+ </floater.string>
+ <!-- For multiple person selection, use "Select" and "Close"
+ instead of "OK" and "Cancel" because "Cancel" still keeps the ones
+ you have already selected. The code will show the appropriate
+ set of buttons. -->
+ <string name="Select">Select</string>
+ <string name="Close">Close</string>
+ <tab_container
+ follows="all"
+ height="300"
+ layout="topleft"
+ left="0"
+ name="ResidentChooserTabs"
+ tab_position="top"
+ top="20"
+ width="265">
+ <panel
+ border="none"
+ height="150"
+ label="Search"
+ layout="topleft"
+ left="6"
+ help_topic="avatarpicker"
+ name="SearchPanel"
+ top="150"
+ width="132">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="InstructSearchResidentName"
+ top="8"
+ width="220">
+ Type part of a person&apos;s name:
+ </text>
+ <line_editor
+ bevel_style="none"
+ border_style="line"
+ border.border_thickness="0"
+ commit_on_focus_lost="false"
+ follows="left|top|right"
+ height="23"
+ left_delta="0"
+ name="Edit"
+ top_pad="0"
+ width="65" />
+ <button
+ follows="top|right"
+ height="23"
+ label="Go"
+ label_selected="Go"
+ layout="topleft"
+ left_pad="5"
+ name="Find"
+ width="45" />
+ <scroll_list
+ follows="all"
+ height="98"
+ layout="topleft"
+ left="0"
+ name="SearchResults"
+ top="52"
+ width="132" />
+ </panel>
+ <panel
+ border="none"
+ height="150"
+ label="Friends"
+ layout="topleft"
+ left="6"
+ help_topic="avatarpicker"
+ name="FriendsPanel"
+ top="150"
+ width="132">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="InstructSelectFriend"
+ top="5"
+ width="200">
+ Select a person:
+ </text>
+ <button
+ follows="top|right"
+ layout="topleft"
+ right="-5"
+ top ="5"
+ height="20"
+ width="20"
+ name="RefreshFriends"
+ image_overlay="Refresh_Off">
+ <button.commit_callback
+ function="Refresh.FriendList"/>
+ </button>
+ <scroll_list
+ follows="all"
+ height="100"
+ border="false"
+ layout="topleft"
+ left="0"
+ name="Friends"
+ sort_column="0"
+ top_pad="5"
+ width="132" />
+ </panel>
+
+ <panel
+ border="none"
+ height="150"
+ label="Near Me"
+ layout="topleft"
+ left="6"
+ help_topic="avatarpicker"
+ name="NearMePanel"
+ top="150"
+ width="132">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="InstructSelectResident"
+ top="8"
+ width="220">
+ Select a person nearby:
+ </text>
+ <slider
+ control_name="NearMeRange"
+ decimal_digits="0"
+ follows="left|top"
+ height="18"
+ increment="1"
+ initial_value="20"
+ label="Range"
+ layout="topleft"
+ left="10"
+ max_val="130"
+ min_val="5"
+ name="near_me_range"
+ top_pad="0"
+ width="160" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="18"
+ layout="topleft"
+ left_pad="0"
+ name="meters"
+ width="60">
+ Meters
+ </text>
+ <button
+ follows="top|left"
+ layout="topleft"
+ left_pad="0"
+ height="28"
+ width="28"
+ name="Refresh"
+ image_overlay="Refresh_Off" />
+ <scroll_list
+ follows="all"
+ height="100"
+ border="false"
+ layout="topleft"
+ left="0"
+ name="NearMe"
+ sort_column="0"
+ top="50"
+ width="132" />
+ </panel>
+ </tab_container>
+ <button
+ follows="right|bottom"
+ height="23"
+ label="OK"
+ label_selected="OK"
+ name="ok_btn"
+ top_pad="3"
+ left="46"
+ width="100" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Cancel"
+ label_selected="Cancel"
+ name="cancel_btn"
+ width="100"
+ left_pad="5" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_avatar_textures.xml b/indra/newview/skins/default/xui/en/floater_avatar_textures.xml
new file mode 100644
index 0000000000..54b6edb0ec
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_avatar_textures.xml
@@ -0,0 +1,306 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="650"
+ layout="topleft"
+ name="avatar_texture_debug"
+ help_topic="avatar_texture_debug"
+ title="AVATAR TEXTURES"
+ width="1250">
+ <floater.string
+ name="InvalidAvatar">
+ INVALID AVATAR
+ </floater.string>
+ <text
+ type="string"
+ length="1"
+ height="16"
+ layout="topleft"
+ left="30"
+ name="label"
+ top="40"
+ width="80">
+ Baked Textures
+ </text>
+ <text
+ type="string"
+ length="1"
+ height="16"
+ layout="topleft"
+ left_pad="50"
+ name="composite_label"
+ top_delta="0"
+ width="120">
+ Composite Textures
+ </text>
+ <button
+ height="20"
+ label="Dump IDs to Console"
+ label_selected="Dump"
+ layout="topleft"
+ left_pad="530"
+ name="Dump"
+ top_delta="0"
+ width="150" />
+
+ <scroll_container
+ color="DkGray2"
+ opaque="true"
+ follows="all"
+ height="590"
+ layout="topleft"
+ left="5"
+ top_pad="5"
+ name="profile_scroll"
+ reserve_scroll_corner="false"
+ width="1240">
+ <panel
+ name="scroll_content_panel"
+ follows="left|top"
+ min_height="300"
+ layout="topleft"
+ top="0"
+ background_visible="false"
+ height="950"
+ left="0"
+ width="1250">
+ <texture_picker
+ height="143"
+ label="Hair"
+ layout="topleft"
+ left="10"
+ name="hair-baked"
+ top="17"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Hair"
+ layout="topleft"
+ left_pad="7"
+ name="hair_grain"
+ top_delta="0"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Hair Alpha"
+ layout="topleft"
+ left_pad="7"
+ name="hair_alpha"
+ top_delta="0"
+ width="128" />
+
+ <texture_picker
+ height="143"
+ label="Head"
+ layout="topleft"
+ left="10"
+ name="head-baked"
+ top="167"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Makeup"
+ layout="topleft"
+ left_pad="7"
+ name="head_bodypaint"
+ top_delta="0"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Head Alpha"
+ layout="topleft"
+ left_pad="7"
+ name="head_alpha"
+ top_delta="0"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Head Tattoo"
+ layout="topleft"
+ left_pad="7"
+ name="head_tattoo"
+ top_delta="0"
+ width="128" />
+
+ <texture_picker
+ height="143"
+ label="Eyes"
+ layout="topleft"
+ left="10"
+ name="eyes-baked"
+ top="317"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Eye"
+ layout="topleft"
+ left_pad="7"
+ name="eyes_iris"
+ top_delta="0"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Eyes Alpha"
+ layout="topleft"
+ left_pad="7"
+ name="eyes_alpha"
+ top_delta="0"
+ width="128" />
+
+ <texture_picker
+ height="143"
+ label="Upper Body"
+ layout="topleft"
+ left="10"
+ name="upper-baked"
+ top="467"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Upper Body Bodypaint"
+ layout="topleft"
+ left_pad="7"
+ name="upper_bodypaint"
+ top_delta="0"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Undershirt"
+ layout="topleft"
+ left_pad="7"
+ name="upper_undershirt"
+ top_delta="0"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Gloves"
+ layout="topleft"
+ left_pad="7"
+ name="upper_gloves"
+ top_delta="0"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Shirt"
+ layout="topleft"
+ left_pad="7"
+ name="upper_shirt"
+ top_delta="0"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Upper Jacket"
+ layout="topleft"
+ left_pad="7"
+ name="upper_jacket"
+ top_delta="0"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Upper Alpha"
+ layout="topleft"
+ left_pad="7"
+ name="upper_alpha"
+ top_delta="0"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Upper Tattoo"
+ layout="topleft"
+ left_pad="7"
+ name="upper_tattoo"
+ top_delta="0"
+ width="128" />
+
+ <texture_picker
+ height="143"
+ label="Lower Body"
+ layout="topleft"
+ left="10"
+ name="lower-baked"
+ top="617"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Lower Body Bodypaint"
+ layout="topleft"
+ left_pad="7"
+ name="lower_bodypaint"
+ top_delta="0"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Underpants"
+ layout="topleft"
+ left_pad="7"
+ name="lower_underpants"
+ top_delta="0"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Socks"
+ layout="topleft"
+ left_pad="7"
+ name="lower_socks"
+ top_delta="0"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Shoes"
+ layout="topleft"
+ left_pad="7"
+ name="lower_shoes"
+ top_delta="0"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Pants"
+ layout="topleft"
+ left_pad="7"
+ name="lower_pants"
+ top_delta="0"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Jacket"
+ layout="topleft"
+ left_pad="7"
+ name="lower_jacket"
+ top_delta="0"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Lower Alpha"
+ layout="topleft"
+ left_pad="7"
+ name="lower_alpha"
+ top_delta="0"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Lower Tattoo"
+ layout="topleft"
+ left_pad="7"
+ name="lower_tattoo"
+ top_delta="0"
+ width="128" />
+
+ <texture_picker
+ height="143"
+ label="Skirt"
+ layout="topleft"
+ left="10"
+ name="skirt-baked"
+ top="767"
+ width="128" />
+ <texture_picker
+ height="143"
+ label="Skirt"
+ layout="topleft"
+ left_pad="7"
+ name="skirt"
+ top_delta="0"
+ width="128" />
+</panel>
+</scroll_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_beacons.xml b/indra/newview/skins/default/xui/en/floater_beacons.xml
new file mode 100644
index 0000000000..c8f6c613af
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_beacons.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="225"
+ layout="topleft"
+ name="beacons"
+ help_topic="beacons"
+ save_rect="true"
+ save_visibility="true"
+ single_instance="true"
+ title="BEACONS"
+ width="240">
+ <panel
+ follows="left|top|right|bottom"
+ height="200"
+ layout="topleft"
+ left="10"
+ name="beacons_panel"
+ top="20"
+ width="230">
+ <text
+ follows="all"
+ height="16"
+ font="SansSerif"
+ name="label_show"
+ text_color="White"
+ type="string">
+ Show:
+ </text>
+ <check_box
+ control_name="renderbeacons"
+ height="16"
+ width="100"
+ label="Beacons"
+ layout="topleft"
+ name="beacons" >
+ <check_box.commit_callback
+ function="Beacons.UICheck" />
+ </check_box>
+ <check_box
+ control_name="renderhighlights"
+ height="16"
+ left_pad="10"
+ label="Highlights"
+ layout="topleft"
+ name="highlights" >
+ <check_box.commit_callback
+ function="Beacons.UICheck" />
+ </check_box>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="20"
+ tool_tip="Beacon width"
+ name="beacon_width_label"
+ top_pad="3"
+ width="128">
+ Width:
+ </text>
+ <slider
+ control_name="DebugBeaconLineWidth"
+ decimal_digits="0"
+ height="16"
+ increment="1"
+ initial_value="1"
+ layout="topleft"
+ max_val="16"
+ min_val="1"
+ name="beacon_width"
+ top_pad="0"
+ width="180" />
+ <text
+ follows="all"
+ height="16"
+ font="SansSerif"
+ left="0"
+ top_pad="5"
+ name="label_objects"
+ text_color="White"
+ type="string">
+ For these objects:
+ </text>
+ <check_box
+ control_name="physicalbeacon"
+ height="16"
+ left="0"
+ label="Physical"
+ layout="topleft"
+ name="physical" >
+ <check_box.commit_callback
+ function="Beacons.UICheck" />
+ </check_box>
+ <check_box
+ control_name="scriptsbeacon"
+ height="16"
+ left="0"
+ label="Scripted"
+ layout="topleft"
+ name="scripted">
+ <check_box.commit_callback
+ function="Beacons.UICheck" />
+ </check_box>
+ <check_box
+ control_name="scripttouchbeacon"
+ height="16"
+ top_pad="4"
+ left="20"
+ label="Touch only"
+ layout="topleft"
+ name="touch_only" >
+ <check_box.commit_callback
+ function="Beacons.UICheck" />
+ </check_box>
+ <check_box
+ control_name="soundsbeacon"
+ height="16"
+ label="Sound sources"
+ layout="topleft"
+ name="sounds" >
+ <check_box.commit_callback
+ function="Beacons.UICheck" />
+ </check_box>
+ <check_box
+ control_name="particlesbeacon"
+ height="16"
+ label="Particle sources"
+ layout="topleft"
+ name="particles" >
+ <check_box.commit_callback
+ function="Beacons.UICheck" />
+ </check_box>
+
+ </panel>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_build_options.xml b/indra/newview/skins/default/xui/en/floater_build_options.xml
new file mode 100644
index 0000000000..56230e912c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_build_options.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ follows="right"
+ height="170"
+ layout="topleft"
+ name="build options floater"
+ help_topic="build_options_floater"
+ save_rect="true"
+ title="GRID OPTIONS"
+ width="264">
+ <spinner
+ control_name="GridResolution"
+ follows="left|top"
+ height="23"
+ initial_value="1"
+ label="Grid Units (meters)"
+ label_width="160"
+ layout="topleft"
+ left="10"
+ max_val="5"
+ min_val="0.01"
+ name="GridResolution"
+ top="25"
+ width="230" />
+ <spinner
+ control_name="GridDrawSize"
+ decimal_digits="1"
+ follows="left|top"
+ height="23"
+ increment="0.5"
+ initial_value="5"
+ label="Grid Extents (meters)"
+ label_width="160"
+ layout="topleft"
+ left_delta="0"
+ max_val="50"
+ min_val="1"
+ name="GridDrawSize"
+ top_pad="0"
+ width="230" />
+ <check_box
+ control_name="GridSubUnit"
+ height="16"
+ label="Snap to sub-units"
+ layout="topleft"
+ name="GridSubUnit"
+ top_pad="0"
+ width="200" />
+ <check_box
+ control_name="GridCrossSections"
+ height="16"
+ label="View cross-sections"
+ layout="topleft"
+ name="GridCrossSection"
+ top_pad="5"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ tool_tip="Grid opacity"
+ name="grid_opacity_label"
+ top_pad="5"
+ width="128">
+ Opacity:
+ </text>
+ <slider
+ control_name="GridOpacity"
+ follows="left"
+ height="18"
+ increment="0.05"
+ initial_value="0.7"
+ layout="topleft"
+ name="GridOpacity"
+ show_text="false"
+ top_pad="0"
+ width="210" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml
new file mode 100644
index 0000000000..d007ceff98
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml
@@ -0,0 +1,310 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_tear_off="false"
+ height="310"
+ layout="topleft"
+ name="floaterbulkperms"
+ help_topic="floaterbulkperms"
+ title="EDIT CONTENT PERMISSIONS"
+ width="270">
+ <floater.string
+ name="nothing_to_modify_text">
+ Selection contains no editable contents.
+ </floater.string>
+ <floater.string
+ name="status_text">
+ Setting permissions on [NAME]
+ </floater.string>
+ <floater.string
+ name="start_text">
+ Starting permission change requests...
+ </floater.string>
+ <floater.string
+ name="done_text">
+ Finished permission change requests.
+ </floater.string>
+
+ <check_box
+ control_name="BulkChangeIncludeAnimations"
+ height="16"
+ name="check_animation"
+ top="24"
+ left="10"
+ width="16" />
+ <icon
+ height="16"
+ image_name="Inv_Animation"
+ mouse_opaque="true"
+ name="icon_animation"
+ tool_tip="Animation"
+ left_pad="5" />
+ <check_box
+ control_name="BulkChangeIncludeBodyParts"
+ height="16"
+ name="check_bodypart"
+ left="10"
+ width="16"
+ top_pad="2" />
+ <icon
+ height="16"
+ image_name="Inv_Eye"
+ tool_tip="Body Parts"
+ mouse_opaque="true"
+ name="icon_bodypart"
+ left_pad="2" />
+ <check_box
+ control_name="BulkChangeIncludeClothing"
+ height="16"
+ name="check_clothing"
+ left="10"
+ width="16"
+ top_pad="5" />
+ <icon
+ height="16"
+ image_name="Inv_Shirt"
+ mouse_opaque="true"
+ name="icon_clothing"
+ tool_tip="Clothing"
+ left_pad="2" />
+ <check_box
+ control_name="BulkChangeIncludeGestures"
+ height="16"
+ name="check_gesture"
+ left="65"
+ width="16"
+ top="25" />
+ <icon
+ height="16"
+ image_name="Inv_Gesture"
+ layout="topleft"
+ mouse_opaque="true"
+ name="icon_gesture"
+ tool_tip="Gestures"
+ left_pad="2" />
+ <check_box
+ control_name="BulkChangeIncludeNotecards"
+ height="16"
+ layout="topleft"
+ name="check_notecard"
+ left="65"
+ width="16"
+ top_pad="5" />
+ <icon
+ height="16"
+ image_name="Inv_Notecard"
+ layout="topleft"
+ mouse_opaque="true"
+ name="icon_notecard"
+ tool_tip="Notecards"
+ left_pad="4" />
+ <check_box
+ control_name="BulkChangeIncludeObjects"
+ height="16"
+ name="check_object"
+ left="65"
+ top_pad="5"
+ width="16" />
+ <icon
+ height="16"
+ image_name="Inv_Object"
+ mouse_opaque="true"
+ name="icon_object"
+ tool_tip="Objects"
+ left_pad="2" />
+ <check_box
+ control_name="BulkChangeIncludeScripts"
+ height="16"
+ name="check_script"
+ top="25"
+ left="120"
+ width="16"
+ />
+ <icon
+ height="16"
+ image_name="Inv_Script"
+ layout="topleft"
+ mouse_opaque="true"
+ name="icon_script"
+ tool_tip="Scripts"
+ left_pad="4" />
+ <check_box
+ control_name="BulkChangeIncludeSounds"
+ height="16"
+ name="check_sound"
+ top_pad="5"
+ left="120"
+ width="16" />
+ <icon
+ height="16"
+ image_name="Inv_Sound"
+ mouse_opaque="true"
+ name="icon_sound"
+ tool_tip="Sounds"
+ left_pad="4" />
+ <check_box
+ control_name="BulkChangeIncludeTextures"
+ height="16"
+ name="check_texture"
+ top_pad="5"
+ left="120"
+ width="16" />
+ <icon
+ height="16"
+ image_name="Inv_Texture"
+ mouse_opaque="true"
+ name="icon_texture"
+ tool_tip="Textures"
+ left_pad="2" />
+
+ <button
+ height="23"
+ layout="topleft"
+ name="check_all"
+ label="√ All"
+ left="180"
+ top="26"
+ width="70">
+ <button.commit_callback
+ function="BulkPermission.CheckAll" />
+ </button>
+ <button
+ follows="left|top"
+ height="23"
+ label="Clear"
+ label_selected="None"
+ layout="topleft"
+ top_pad="8"
+ name="check_none"
+ width="70" >
+ <button.commit_callback
+ function="BulkPermission.UncheckAll"/>
+ </button>
+
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerifLarge"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="newperms"
+ top="90"
+ width="250">
+ New Content Permissions
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ height="16"
+ left="10"
+ name="GroupLabel"
+ width="88">
+ Group:
+ </text>
+ <check_box
+ control_name="BulkChangeShareWithGroup"
+ height="16"
+ label="Share"
+ layout="topleft"
+ top_pad="0"
+ name="share_with_group"
+ width="88" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ name="AnyoneLabel"
+ left="100"
+ top="110"
+ width="88">
+ Anyone:
+ </text>
+ <check_box
+ control_name="BulkChangeEveryoneCopy"
+ height="16"
+ label="Copy"
+ layout="topleft"
+ top_pad="0"
+ name="everyone_copy"
+ width="88" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ name="NextOwnerLabel"
+ top="110"
+ left="185"
+ width="88">
+ Next owner:
+ </text>
+ <check_box
+ control_name="BulkChangeNextOwnerModify"
+ height="16"
+ label="Modify"
+ layout="topleft"
+ name="next_owner_modify"
+ top_pad="0"
+ width="83" />
+ <check_box
+ control_name="BulkChangeNextOwnerCopy"
+ height="16"
+ label="Copy"
+ layout="topleft"
+ top_pad="0"
+ name="next_owner_copy"
+ width="88">
+ <check_box.commit_callback
+ function="BulkPermission.CommitCopy"/>
+ </check_box>
+ <check_box
+ control_name="BulkChangeNextOwnerTransfer"
+ enabled_control="BulkChangeNextOwnerCopy"
+ height="16"
+ top_pad="0"
+ initial_value="true"
+ label="Transfer"
+ layout="topleft"
+ name="next_owner_transfer"
+ tool_tip="Next owner can give away or resell this object"
+ width="106" />
+ <scroll_list
+ enabled="false"
+ follows="all"
+ height="95"
+ layout="topleft"
+ left="10"
+ name="queue output"
+ top="175"
+ width="250" />
+ <button
+ follows="left|top"
+ height="23"
+ label="OK"
+ layout="topleft"
+ left="65"
+ name="apply"
+ top_pad="10"
+ width="90">
+ <button.commit_callback
+ function="BulkPermission.Apply"/>
+ </button>
+ <button
+ follows="left|top"
+ height="23"
+ label="Cancel"
+ layout="topleft"
+ left_pad="5"
+ name="close"
+ width="100" >
+ <button.commit_callback
+ function="BulkPermission.Close"/>
+ </button>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_bumps.xml b/indra/newview/skins/default/xui/en/floater_bumps.xml
new file mode 100644
index 0000000000..303c28d7c8
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_bumps.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="180"
+ layout="topleft"
+ name="floater_bumps"
+ help_topic="floater_bumps"
+ save_rect="true"
+ title="BUMPS, PUSHES &amp; HITS"
+ width="400">
+ <floater.string
+ name="none_detected">
+ None detected
+ </floater.string>
+ <floater.string
+ name="bump">
+ [TIME] [FIRST] [LAST] bumped you
+ </floater.string>
+ <floater.string
+ name="llpushobject">
+ [TIME] [FIRST] [LAST] pushed you with a script
+ </floater.string>
+ <floater.string
+ name="selected_object_collide">
+ [TIME] [FIRST] [LAST] hit you with an object
+ </floater.string>
+ <floater.string
+ name="scripted_object_collide">
+ [TIME] [FIRST] [LAST] hit you with a scripted object
+ </floater.string>
+ <floater.string
+ name="physical_object_collide">
+ [TIME] [FIRST] [LAST] hit you with a physical object
+ </floater.string>
+ <floater.string
+ name="timeStr">
+ [[hour,datetime,slt]:[min,datetime,slt]]
+ </floater.string>
+ <scroll_list
+ draw_border="false"
+ follows="left|top|right|bottom"
+ height="152"
+ layout="topleft"
+ left="6"
+ multi_select="true"
+ name="bump_list"
+ top="20"
+ width="388" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_buy_contents.xml b/indra/newview/skins/default/xui/en/floater_buy_contents.xml
new file mode 100644
index 0000000000..77a0e9b91b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_buy_contents.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="290"
+ layout="topleft"
+ min_height="150"
+ min_width="200"
+ name="floater_buy_contents"
+ help_topic="floater_buy_contents"
+ save_rect="true"
+ title="BUY CONTENTS"
+ width="280">
+ <floater.string
+ name="no_copy_text">
+ (no copy)
+ </floater.string>
+ <floater.string
+ name="no_modify_text">
+ (no modify)
+ </floater.string>
+ <floater.string
+ name="no_transfer_text">
+ (no transfer)
+ </floater.string>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ top="22"
+ left="10"
+ layout="topleft"
+ name="contains_text"
+ width="276">
+ [NAME] contains:
+ </text>
+ <scroll_list
+ background_visible="true"
+ draw_border="false"
+ follows="all"
+ height="163"
+ layout="topleft"
+ left="10"
+ name="item_list"
+ top_pad="4"
+ width="260">
+ <scroll_list.columns
+ name="icon"
+ width="16" />
+ <scroll_list.columns
+ name="text"
+ relative_width="1" />
+ </scroll_list>
+ <text
+ type="string"
+ length="1"
+ follows="left|bottom"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="buy_text"
+ text_color="white"
+ top="220"
+ width="260">
+ Buy for L$[AMOUNT] from [NAME]?
+ </text>
+ <check_box
+ follows="left|bottom"
+ height="16"
+ label="Wear clothing now"
+ layout="topleft"
+ left="10"
+ name="wear_check"
+ width="250" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Buy"
+ label_selected="Buy"
+ layout="topleft"
+ left="65"
+ name="buy_btn"
+ top_pad="5"
+ width="100" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Cancel"
+ label_selected="Cancel"
+ layout="topleft"
+ left_pad="5"
+ name="cancel_btn"
+ width="100" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
new file mode 100644
index 0000000000..8f67f564a2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
@@ -0,0 +1,324 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ height="275"
+ layout="topleft"
+ title="BUY L$"
+ name="buy currency"
+ help_topic="buy_linden_dollars"
+ single_instance="true"
+ width="350">
+ <floater.string
+ name="buy_currency">
+ Buy L$ [LINDENS] for approx. [LOCALAMOUNT]
+ </floater.string>
+ <icon
+ height="215"
+ image_name="Linden_Dollar_Background"
+ layout="topleft"
+ left="0"
+ name="normal_background"
+ top="17"
+ width="350" />
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifHuge"
+ layout="topleft"
+ left="20"
+ height="30"
+ top="25"
+ width="300"
+ name="info_need_more">
+ You need more L$
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ height="16"
+ layout="topleft"
+ top="246"
+ left="15"
+ width="300"
+ name="contacting">
+ Contacting LindeX...
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifHuge"
+ layout="topleft"
+ left="20"
+ height="30"
+ top="25"
+ width="200"
+ name="info_buying">
+ Buy L$
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifMedium"
+ height="16"
+ layout="topleft"
+ left="20"
+ name="balance_label"
+ top="65"
+ width="210">
+ I have
+ </text>
+ <text
+ type="string"
+ length="1"
+ font="SansSerifMedium"
+ follows="top|left"
+ halign="right"
+ height="16"
+ layout="topleft"
+ left="200"
+ name="balance_amount"
+ top_delta="0"
+ width="120">
+ L$ [AMT]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifMedium"
+ height="16"
+ top="95"
+ layout="topleft"
+ left="20"
+ name="currency_action"
+ width="210">
+ I want to buy
+ </text>
+ <text
+ font="SansSerifMedium"
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ top_delta="0"
+ left="217"
+ name="currency_label"
+ width="15">
+ L$
+ </text>
+ <line_editor
+ type="string"
+ halign="right"
+ font="SansSerifMedium"
+ select_on_focus="true"
+ follows="top|left"
+ top_delta="-7"
+ height="22"
+ label="L$"
+ left_pad="3"
+ name="currency_amt"
+ width="85">
+ 1234
+ </line_editor>
+ <text
+ type="string"
+ font="SansSerifMedium"
+ length="1"
+ follows="top|left"
+ height="16"
+ layout="topleft"
+ left="20"
+ top="125"
+ name="buying_label"
+ width="210">
+ For the price
+ </text>
+ <text
+ type="string"
+ length="1"
+ font="SansSerifMedium"
+ text_color="EmphasisColor"
+ follows="top|left"
+ halign="right"
+ height="16"
+ top_delta="0"
+ layout="topleft"
+ left="150"
+ name="currency_est"
+ width="170">
+ approx. [LOCALAMOUNT]
+ </text>
+ <text
+ type="string"
+ font="SansSerifSmall"
+ text_color="EmphasisColor"
+ length="1"
+ follows="top|left"
+ height="16"
+ layout="topleft"
+ top="125"
+ left="170"
+ width="150"
+ halign="right"
+ name="getting_data">
+ Estimating...
+ </text>
+ <text
+ type="string"
+ font="SansSerifSmall"
+ top="145"
+ length="1"
+ follows="top|left"
+ height="16"
+ halign="right"
+ left="150"
+ width="170"
+ layout="topleft"
+ name="buy_action">
+ [NAME] L$ [PRICE]
+ </text>
+ <text
+ type="string"
+ font="SansSerifMedium"
+ length="1"
+ follows="top|left"
+ height="16"
+ layout="topleft"
+ left="20"
+ name="total_label"
+ top="165"
+ width="210">
+ My new balance will be
+ </text>
+ <text
+ type="string"
+ length="1"
+ font="SansSerifMedium"
+ follows="top|left"
+ top_delta="0"
+ height="16"
+ layout="topleft"
+ left="200"
+ halign="right"
+ name="total_amount"
+ width="120">
+ L$ [AMT]
+ </text>
+ <text
+ type="string"
+ length="1"
+ text_color="0.7 0.7 0.7 0.5"
+ follows="top|left"
+ layout="topleft"
+ halign="right"
+ top="189"
+ left="20"
+ width="300"
+ height="30"
+ name="currency_links">
+ [http://www.secondlife.com/my/account/payment_method_management.php payment method] | [http://www.secondlife.com/my/account/currency.php currency] | [http://www.secondlife.com/my/account/exchange_rates.php exchange rate]
+ </text>
+ <text
+ type="string"
+ length="1"
+ text_color="0.7 0.7 0.7 0.5"
+ follows="top|left"
+ layout="topleft"
+ halign="right"
+ top="202"
+ left="20"
+ width="300"
+ height="30"
+ name="exchange_rate_note">
+Re-enter amount to see the latest exchange rate.
+ </text>
+ <text
+ type="string"
+ length="1"
+ text_color="0.7 0.7 0.7 0.5"
+ follows="top|left"
+ layout="topleft"
+ halign="right"
+ top="213"
+ left="10"
+ width="310"
+ height="30"
+ name="purchase_warning_repurchase">
+ Confirming this purchase only buys L$, not the object.
+ </text>
+ <text
+ type="string"
+ length="1"
+ text_color="0.7 0.7 0.7 0.5"
+ follows="top|left"
+ layout="topleft"
+ halign="right"
+ top="213"
+ left="20"
+ width="300"
+ height="30"
+ name="purchase_warning_notenough">
+ You aren&apos;t buying enough L$. Please increase the amount.
+ </text>
+
+ <button
+ follows="bottom|left"
+ height="20"
+ label="Buy Now"
+ layout="topleft"
+ left="151"
+ name="buy_btn"
+ top="242"
+ width="90"/>
+ <button
+ follows="bottom|right"
+ height="20"
+ label="Cancel"
+ layout="topleft"
+ left_pad="10"
+ name="cancel_btn"
+ width="90"/>
+ <icon
+ height="215"
+ image_name="Linden_Dollar_Alert"
+ layout="topleft"
+ left="0"
+ name="error_background"
+ top="15"
+ width="350"/>
+ <text
+ type="string"
+ font="SansSerifHuge"
+ left="165"
+ width="170"
+ height="25"
+ top="25"
+ name="info_cannot_buy">
+ Unable to Buy
+ </text>
+ <text
+ type="string"
+ width="176"
+ height="125"
+ top="60"
+ left="165"
+ word_wrap="true"
+ follows="bottom|right"
+ name="cannot_buy_message">
+ </text>
+ <button
+ follows="bottom|left"
+ height="20"
+ label="Continue to the Web"
+ layout="topleft"
+ left="170"
+ name="error_web"
+ top="200"
+ width="160"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_buy_land.xml b/indra/newview/skins/default/xui/en/floater_buy_land.xml
new file mode 100644
index 0000000000..6e0c3dfe54
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_buy_land.xml
@@ -0,0 +1,707 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ height="484"
+ layout="topleft"
+ name="buy land"
+ help_topic="buy_land"
+ single_instance="true"
+ title="BUY LAND"
+ width="740">
+ <floater.string
+ name="can_resell">
+ May be resold.
+ </floater.string>
+ <floater.string
+ name="can_not_resell">
+ May not be resold.
+ </floater.string>
+ <floater.string
+ name="can_change">
+ May be joined or subdivided.
+ </floater.string>
+ <floater.string
+ name="can_not_change">
+ May not be joined or subdivided.
+ </floater.string>
+ <floater.string
+ name="cant_buy_for_group">
+ You do not have permission to buy land for your active group.
+ </floater.string>
+ <floater.string
+ name="no_land_selected">
+ No land selected.
+ </floater.string>
+ <floater.string
+ name="multiple_parcels_selected">
+ Multiple different parcels selected.
+Try selecting a smaller area.
+ </floater.string>
+ <floater.string
+ name="no_permission">
+ You do not have permission to buy land for your active group.
+ </floater.string>
+ <floater.string
+ name="parcel_not_for_sale">
+ The selected parcel is not for sale.
+ </floater.string>
+ <floater.string
+ name="group_already_owns">
+ The group already owns the parcel.
+ </floater.string>
+ <floater.string
+ name="you_already_own">
+ You already own the parcel.
+ </floater.string>
+ <floater.string
+ name="set_to_sell_to_other">
+ The selected parcel is set to sell to another party.
+ </floater.string>
+ <floater.string
+ name="no_public_land">
+ The selected area has no public land.
+ </floater.string>
+ <floater.string
+ name="not_owned_by_you">
+ Land owned by another user is selected.
+Try selecting a smaller area.
+ </floater.string>
+ <floater.string
+ name="processing">
+ Processing your purchase...
+
+(This may take a minute or two.)
+ </floater.string>
+ <floater.string
+ name="fetching_error">
+ There has been an error while fetching land buying information.
+ </floater.string>
+ <floater.string
+ name="buying_will">
+ Buying this land will:
+ </floater.string>
+ <floater.string
+ name="buying_for_group">
+ Buying land for group will:
+ </floater.string>
+ <floater.string
+ name="cannot_buy_now">
+ Cannot buy now:
+ </floater.string>
+ <floater.string
+ name="not_for_sale">
+ Not for sale:
+ </floater.string>
+ <floater.string
+ name="none_needed">
+ none needed
+ </floater.string>
+ <floater.string
+ name="must_upgrade">
+ Your account must be upgraded to own land.
+ </floater.string>
+ <floater.string
+ name="cant_own_land">
+ Your account can own land.
+ </floater.string>
+ <floater.string
+ name="land_holdings">
+ You hold [BUYER] m² of land.
+ </floater.string>
+ <floater.string
+ name="pay_to_for_land">
+ Pay L$ [AMOUNT] to [SELLER] for this land
+ </floater.string>
+ <floater.string
+ name="buy_for_US">
+ Buy L$ [AMOUNT] for approx. [LOCAL_AMOUNT],
+ </floater.string>
+ <floater.string
+ name="parcel_meters">
+ This parcel is [AMOUNT] m²
+ </floater.string>
+ <floater.string
+ name="premium_land">
+ This land is premium, and will charge as [AMOUNT] m².
+ </floater.string>
+ <floater.string
+ name="discounted_land">
+ This land is discounted, and will charge as [AMOUNT] m².
+ </floater.string>
+ <floater.string
+ name="meters_supports_object">
+ [AMOUNT] m²
+supports [AMOUNT2] objects
+ </floater.string>
+ <floater.string
+ name="sold_with_objects">
+ sold with objects
+ </floater.string>
+ <floater.string
+ name="sold_without_objects">
+ objects not included
+ </floater.string>
+ <floater.string
+ name="info_price_string">
+ L$ [PRICE]
+(L$ [PRICE_PER_SQM]/m²)
+[SOLD_WITH_OBJECTS]
+ </floater.string>
+ <floater.string
+ name="insufficient_land_credits">
+ The group [GROUP] will need sufficient contributed land use credits to cover this parcel before the purchase will complete.
+ </floater.string>
+ <floater.string
+ name="have_enough_lindens">
+ You have L$ [AMOUNT], which is enough to buy this land.
+ </floater.string>
+ <floater.string
+ name="not_enough_lindens">
+ You have only L$ [AMOUNT], and need L$ [AMOUNT2] more.
+ </floater.string>
+ <floater.string
+ name="balance_left">
+ After the purchase, you will have L$ [AMOUNT] left.
+ </floater.string>
+ <floater.string
+ name="balance_needed">
+ You need to buy at least L$ [AMOUNT] to afford this land.
+ </floater.string>
+ <floater.string
+ name="no_parcel_selected">
+ (no parcel selected)
+ </floater.string>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="14"
+ layout="topleft"
+ left="440"
+ name="region_name_label"
+ right="550"
+ top="21"
+ width="60"
+ word_wrap="true">
+ Region:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="14"
+ layout="topleft"
+ left_delta="110"
+ name="region_name_text"
+ top_delta="0"
+ width="175">
+ (unknown)
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="14"
+ layout="topleft"
+ left="440"
+ name="region_type_label"
+ right="550"
+ width="60"
+ word_wrap="true">
+ Type:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="14"
+ layout="topleft"
+ left_delta="110"
+ name="region_type_text"
+ top_delta="0"
+ width="175">
+ (unknown)
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="14"
+ layout="topleft"
+ left="440"
+ name="estate_name_label"
+ right="550"
+ width="60"
+ word_wrap="true">
+ Estate:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="14"
+ layout="topleft"
+ left_delta="110"
+ name="estate_name_text"
+ top_delta="0"
+ width="175">
+ (unknown)
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="440"
+ name="estate_owner_label"
+ right="550"
+ width="100"
+ word_wrap="true">
+ Estate Owner:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_delta="110"
+ name="estate_owner_text"
+ top_delta="0"
+ width="175">
+ (unknown)
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="440"
+ name="resellable_changeable_label"
+ right="725"
+ width="260"
+ word_wrap="true">
+ Purchased land in this region:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="470"
+ name="resellable_clause"
+ right="725"
+ width="260"
+ word_wrap="true">
+ May or may not be resold.
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="470"
+ name="changeable_clause"
+ right="725"
+ width="260"
+ word_wrap="true">
+ May or may not be joined or subdivided.
+ </text>
+ <text
+ type="string"
+ length="1"
+ height="16"
+ layout="topleft"
+ left="440"
+ name="covenant_text"
+ right="725"
+ width="260">
+ You must agree to the Estate Covenant:
+ </text>
+ <text
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left="500"
+ name="covenant_timestamp_text"
+ right="725"
+ top="175"
+ width="275"
+ word_wrap="true" />
+ <text_editor
+ type="string"
+ length="1"
+ enabled="false"
+ follows="top|right"
+ handle_edit_keys_directly="false"
+ height="237"
+ layout="topleft"
+ left="444"
+ max_length="65535"
+ name="covenant_editor"
+ right="725"
+ top="192"
+ width="271"
+ word_wrap="true">
+ Loading...
+ </text_editor>
+ <check_box
+ height="20"
+ label="I Agree to the Covenant Defined Above."
+ layout="topleft"
+ left="440"
+ name="agree_covenant"
+ right="725"
+ width="275" />
+ <texture_picker
+ enabled="false"
+ follows="top|left"
+ height="135"
+ layout="topleft"
+ left="16"
+ name="info_image"
+ top="28"
+ width="180" />
+ <text
+ type="string"
+ length="1"
+ bottom_delta="-119"
+ follows="top|left"
+ height="16"
+ layout="topleft"
+ left="204"
+ name="info_parcel_label"
+ top="30"
+ width="48">
+ Parcel:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="16"
+ name="info_parcel"
+ top_pad="1"
+ width="180">
+ Scotopteryx 138,204
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ height="16"
+ layout="topleft"
+ left="204"
+ name="info_size_label"
+ top_pad="1"
+ width="48">
+ Size:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerif"
+ height="32"
+ layout="topleft"
+ left_delta="16"
+ name="info_size"
+ top_pad="1"
+ width="180">
+ 1024 m²
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ height="16"
+ layout="topleft"
+ left="204"
+ name="info_price_label"
+ top_pad="1"
+ width="48">
+ Price:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="16"
+ name="info_price"
+ top_pad="1"
+ width="180">
+ L$ 1500
+(L$ 1.1/m²)
+sold with objects
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifHuge"
+ height="24"
+ layout="topleft"
+ left="16"
+ name="info_action"
+ top="166"
+ width="350">
+ Buying this land will:
+ </text>
+ <locate
+ height="6"
+ layout="topleft" />
+ <icon
+ follows="top|left"
+ height="64"
+ image_name="badge_note.j2c"
+ layout="topleft"
+ left="0"
+ name="step_error"
+ width="64" />
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ height="160"
+ layout="topleft"
+ left="72"
+ name="error_message"
+ right="435"
+ top="208"
+ width="215"
+ word_wrap="true">
+ Something ain&apos;t right.
+ </text>
+ <button
+ follows="bottom|left"
+ height="20"
+ label="Go to website"
+ layout="topleft"
+ left_delta="0"
+ name="error_web"
+ top_delta="154"
+ width="120" />
+ <locate
+ height="-200"
+ layout="topleft" />
+ <icon
+ follows="top|left"
+ height="64"
+ image_name="badge_ok.j2c"
+ layout="topleft"
+ left="0"
+ name="step_1"
+ width="64" />
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifBig"
+ height="16"
+ layout="topleft"
+ left="72"
+ name="account_action"
+ right="438"
+ top="200"
+ width="218">
+ Upgrade you to premium membership.
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ height="16"
+ layout="topleft"
+ left="72"
+ name="account_reason"
+ right="400"
+ width="180">
+ Only premimum members may own land.
+ </text>
+ <combo_box
+ follows="top|left"
+ height="16"
+ layout="topleft"
+ left="80"
+ name="account_level"
+ width="336">
+ <combo_box.item
+ label="US$9.95/month, billed monthly"
+ name="US$9.95/month,billedmonthly" />
+ <combo_box.item
+ label="US$7.50/month, billed quarterly"
+ name="US$7.50/month,billedquarterly" />
+ <combo_box.item
+ label="US$6.00/month, billed annually"
+ name="US$6.00/month,billedannually" />
+ </combo_box>
+ <locate
+ height="10"
+ layout="topleft" />
+ <icon
+ follows="top|left"
+ height="64"
+ image_name="badge_note.j2c"
+ layout="topleft"
+ left="0"
+ name="step_2"
+ width="64" />
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifBig"
+ height="16"
+ layout="topleft"
+ left="72"
+ name="land_use_action"
+ right="438"
+ top="284"
+ width="218">
+ Increase your monthly land use fees to US$ 40/month.
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ height="32"
+ layout="topleft"
+ left="72"
+ name="land_use_reason"
+ right="435"
+ width="215"
+ word_wrap="true">
+ You hold 1309 m² of land.
+This parcel is 512 m² of land.
+ </text>
+ <locate
+ height="10"
+ layout="topleft" />
+ <icon
+ follows="top|left"
+ height="64"
+ image_name="badge_note.j2c"
+ layout="topleft"
+ left="0"
+ name="step_3"
+ width="64" />
+ <text
+ type="string"
+ length="1"
+ bottom_delta="-38"
+ follows="top|left"
+ font="SansSerifBig"
+ height="16"
+ layout="topleft"
+ left="72"
+ name="purchase_action"
+ right="438">
+ Pay Joe Resident L$ 4000 for the land
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ height="16"
+ layout="topleft"
+ left="72"
+ name="currency_reason"
+ right="400">
+ You have L$ 2,100.
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="currency_action"
+ top_pad="9"
+ width="90">
+ Buy additional L$
+ </text>
+ <locate
+ height="0"
+ layout="topleft"
+ width="8" />
+ <line_editor
+ type="string"
+ length="1"
+ follows="top|right"
+ height="16"
+ layout="topleft"
+ left="170"
+ name="currency_amt"
+ top="408"
+ width="80">
+ 1000
+ </line_editor>
+ <locate
+ height="0"
+ layout="topleft"
+ width="8" />
+ <text
+ type="string"
+ length="1"
+ follows="top|right"
+ height="16"
+ layout="topleft"
+ left="260"
+ name="currency_est"
+ top="409"
+ width="178">
+ for approx. [LOCAL_AMOUNT]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ height="16"
+ layout="topleft"
+ left="72"
+ name="currency_balance"
+ right="400">
+ You have L$ 2,100.
+ </text>
+ <check_box
+ follows="bottom|left"
+ height="20"
+ label="Remove [AMOUNT] m² of contribution from group."
+ layout="topleft"
+ left_delta="3"
+ name="remove_contribution"
+ top_delta="14"
+ visible="false"
+ width="275" />
+ <button
+ follows="bottom|left"
+ height="20"
+ label="Purchase"
+ layout="topleft"
+ left="70"
+ name="buy_btn"
+ top="448"
+ width="100" />
+ <button
+ follows="bottom|right"
+ height="20"
+ label="Cancel"
+ layout="topleft"
+ left="-90"
+ name="cancel_btn"
+ top="454"
+ width="80" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_buy_object.xml b/indra/newview/skins/default/xui/en/floater_buy_object.xml
new file mode 100644
index 0000000000..f0e5e30010
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_buy_object.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="290"
+ layout="topleft"
+ min_height="150"
+ min_width="200"
+ name="contents"
+ help_topic="contents"
+ save_rect="true"
+ single_instance="true"
+ title="BUY COPY OF OBJECT"
+ width="280">
+ <floater.string
+ name="title_buy_text">
+ Buy
+ </floater.string>
+ <floater.string
+ name="title_buy_copy_text">
+ Buy a copy of
+ </floater.string>
+ <floater.string
+ name="no_copy_text">
+ (no copy)
+ </floater.string>
+ <floater.string
+ name="no_modify_text">
+ (no modify)
+ </floater.string>
+ <floater.string
+ name="no_transfer_text">
+ (no transfer)
+ </floater.string>
+ <scroll_list
+ background_visible="true"
+ draw_border="false"
+ follows="left|top|right"
+ height="35"
+ layout="topleft"
+ name="object_list"
+ top="20"
+ left="10"
+ width="260">
+ <scroll_list.columns
+ name="icon"
+ width="16" />
+ <scroll_list.columns
+ name="text"
+ width="234" />
+ </scroll_list>
+ <text
+ type="string"
+ length="1"
+ follows="all"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="contents_text"
+ top_pad="5"
+ width="260">
+ Contains:
+ </text>
+ <scroll_list
+ background_visible="true"
+ draw_border="false"
+ follows="all"
+ height="145"
+ layout="topleft"
+ left_delta="0"
+ name="item_list"
+ top_pad="4"
+ width="260">
+ <scroll_list.columns
+ name="icon"
+ width="16" />
+ <scroll_list.columns
+ name="text"
+ width="234" />
+ </scroll_list>
+ <text
+ type="string"
+ length="1"
+ follows="left|right|bottom"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="buy_text"
+ text_color="white"
+ top_pad="5"
+ width="276">
+ Buy for L$[AMOUNT] from [NAME]?
+ </text>
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Buy"
+ label_selected="Buy"
+ layout="topleft"
+ left="65"
+ name="buy_btn"
+ top_pad="10"
+ width="100" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Cancel"
+ label_selected="Cancel"
+ layout="topleft"
+ left_pad="5"
+ name="cancel_btn"
+ top_delta="0"
+ width="100" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml
new file mode 100644
index 0000000000..a797d54749
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_camera.xml
@@ -0,0 +1,245 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_dock="true"
+ can_minimize="true"
+ can_close="false"
+ center_horiz="true"
+ follows="bottom"
+ height="152"
+ layout="topleft"
+ name="camera_floater"
+ help_topic="camera_floater"
+ save_rect="true"
+ save_visibility="true"
+ single_instance="true"
+ width="150">
+ <floater.string
+ name="rotate_tooltip">
+ Rotate Camera Around Focus
+ </floater.string>
+ <floater.string
+ name="zoom_tooltip">
+ Zoom Camera Towards Focus
+ </floater.string>
+ <floater.string
+ name="move_tooltip">
+ Move Camera Up and Down, Left and Right
+ </floater.string>
+ <panel
+ border="false"
+ height="110"
+ layout="topleft"
+ left="2"
+ top="0"
+ mouse_opaque="false"
+ name="controls"
+ width="148">
+ <joystick_track
+ follows="top|left"
+ height="78"
+ image_selected="Cam_Tracking_In"
+ image_unselected="Cam_Tracking_Out"
+ layout="topleft"
+ left="45"
+ name="cam_track_stick"
+ quadrant="left"
+ scale_image="false"
+ sound_flags="3"
+ tool_tip="Move camera up and down, left and right"
+ top="22"
+ visible="false"
+ width="78" />
+ <!--TODO: replace + - images -->
+ <panel
+ border="false"
+ class="camera_zoom_panel"
+ height="94"
+ layout="topleft"
+ left="7"
+ mouse_opaque="false"
+ name="zoom"
+ top="22"
+ width="18">
+ <button
+ follows="top|left"
+ height="18"
+ image_disabled="AddItem_Disabled"
+ image_selected="AddItem_Press"
+ image_unselected="AddItem_Off"
+ layout="topleft"
+ name="zoom_plus_btn"
+ width="18">
+ <commit_callback
+ function="Zoom.plus" />
+ <mouse_held_callback
+ function="Zoom.plus" />
+ </button>
+ <slider_bar
+ height="48"
+ layout="topleft"
+ name="zoom_slider"
+ orientation="vertical"
+ tool_tip="Zoom camera toward focus"
+ top_pad="0"
+ width="18">
+ <commit_callback function="Slider.value_changed"/>
+ </slider_bar>
+ <button
+ follows="top|left"
+ height="18"
+ image_disabled="MinusItem_Disabled"
+ image_selected="MinusItem_Press"
+ image_unselected="MinusItem_Off"
+ layout="topleft"
+ name="zoom_minus_btn"
+ top_pad="0"
+ width="18">
+ <commit_callback
+ function="Zoom.minus" />
+ <mouse_held_callback
+ function="Zoom.minus" />
+ </button>
+ </panel>
+ <joystick_rotate
+ follows="top|left"
+ height="78"
+ image_selected="Cam_Rotate_In"
+ image_unselected="Cam_Rotate_Out"
+ layout="topleft"
+ left="45"
+ mouse_opaque="false"
+ name="cam_rotate_stick"
+ quadrant="left"
+ scale_image="false"
+ sound_flags="3"
+ visible="true"
+ tool_tip="Orbit camera around focus"
+ top="22"
+ width="78" />
+ <panel
+ height="78"
+ layout="topleft"
+ left="36"
+ name="camera_presets"
+ top="20"
+ visible="false"
+ width="78">
+ <button
+ height="40"
+ image_selected="Cam_Preset_Back_On"
+ image_unselected="Cam_Preset_Back_Off"
+ layout="topleft"
+ left="0"
+ name="rear_view"
+ tool_tip="Rear View"
+ top="2"
+ width="40">
+ <click_callback
+ function="CameraPresets.ChangeView"
+ parameter="rear_view" />
+ </button>
+ <button
+ height="40"
+ image_selected="Cam_Preset_Side_On"
+ image_unselected="Cam_Preset_Side_Off"
+ layout="topleft"
+ left_pad="5"
+ name="group_view"
+ tool_tip="Group View"
+ top="2"
+ width="40">
+ <click_callback
+ function="CameraPresets.ChangeView"
+ parameter="group_view" />
+ </button>
+ <button
+ height="40"
+ image_selected="Cam_Preset_Front_On"
+ image_unselected="Cam_Preset_Front_Off"
+ layout="topleft"
+ left="0"
+ name="front_view"
+ tool_tip="Front View"
+ top_pad="5"
+ width="40">
+ <click_callback
+ function="CameraPresets.ChangeView"
+ parameter="front_view" />
+ </button>
+ <button
+ height="40"
+ image_selected="Cam_Preset_Eye_Off"
+ image_unselected="Cam_Preset_Eye_Off"
+ layout="topleft"
+ left_pad="5"
+ name="mouselook_view"
+ tool_tip="Mouselook View"
+ width="40">
+ <click_callback
+ function="CameraPresets.ChangeView"
+ parameter="mouselook_view" />
+ </button>
+ </panel>
+ </panel>
+ <panel
+ border="false"
+ height="42"
+ layout="topleft"
+ left="2"
+ top_pad="0"
+ name="buttons"
+ width="148">
+ <button
+ height="23"
+ label=""
+ layout="topleft"
+ left="23"
+ is_toggle="true"
+ image_overlay="Cam_Orbit_Off"
+ image_selected="PushButton_Selected_Press"
+ name="orbit_btn"
+ tab_stop="false"
+ tool_tip="Orbit camera"
+ width="25">
+ </button>
+ <button
+ height="23"
+ label=""
+ layout="topleft"
+ left_pad="0"
+ is_toggle="true"
+ image_overlay="Cam_Pan_Off"
+ image_selected="PushButton_Selected_Press"
+ name="pan_btn"
+ tab_stop="false"
+ tool_tip="Pan camera"
+ width="25">
+ </button>
+ <button
+ height="23"
+ label=""
+ layout="topleft"
+ left_pad="0"
+ image_overlay="Cam_Avatar_Off"
+ image_selected="PushButton_Selected_Press"
+ name="avatarview_btn"
+ tab_stop="false"
+ tool_tip="See as avatar"
+ width="25">
+ </button>
+ <button
+ height="23"
+ label=""
+ layout="topleft"
+ left_pad="0"
+ is_toggle="true"
+ image_overlay="Cam_FreeCam_Off"
+ image_selected="PushButton_Selected_Press"
+ name="freecamera_btn"
+ tab_stop="false"
+ tool_tip="View object"
+ width="25">
+ </button>
+ </panel>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_choose_group.xml b/indra/newview/skins/default/xui/en/floater_choose_group.xml
new file mode 100644
index 0000000000..dc1ee5f24e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_choose_group.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="258"
+ layout="topleft"
+ name="groups"
+ help_topic="groups"
+ title="GROUPS"
+ width="280">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="12"
+ name="groupdesc"
+ top="24"
+ width="248">
+ Choose a group:
+ </text>
+ <scroll_list
+ height="160"
+ layout="topleft"
+ left_delta="0"
+ name="group list"
+ top_pad="8"
+ width="248">
+ <scroll_list.columns
+ name="name"
+ width="248" />
+ </scroll_list>
+ <button
+ height="20"
+ label="OK"
+ label_selected="OK"
+ layout="topleft"
+ left_delta="0"
+ name="OK"
+ top_pad="8"
+ width="80" />
+ <button
+ height="20"
+ label="Cancel"
+ label_selected="Cancel"
+ layout="topleft"
+ left_pad="8"
+ name="Cancel"
+ top_delta="0"
+ width="80" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_color_picker.xml b/indra/newview/skins/default/xui/en/floater_color_picker.xml
new file mode 100644
index 0000000000..fbecebc363
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_color_picker.xml
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ follows="left|top"
+ height="380"
+ layout="topleft"
+ name="ColorPicker"
+ help_topic="colorpicker"
+ title="COLOR PICKER"
+ width="440">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="10"
+ layout="topleft"
+ left="12"
+ mouse_opaque="false"
+ name="r_val_text"
+ top="35"
+ width="413">
+ Red:
+ </text>
+ <spinner
+ decimal_digits="0"
+ follows="left"
+ height="16"
+ increment="1"
+ initial_value="128"
+ layout="topleft"
+ left_delta="63"
+ max_val="255"
+ name="rspin"
+ top_delta="0"
+ width="50" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="10"
+ layout="topleft"
+ left="12"
+ mouse_opaque="false"
+ name="g_val_text"
+ top="56"
+ width="413">
+ Green:
+ </text>
+ <spinner
+ decimal_digits="0"
+ follows="left"
+ height="16"
+ increment="1"
+ initial_value="128"
+ layout="topleft"
+ left_delta="63"
+ max_val="255"
+ name="gspin"
+ top_delta="0"
+ width="50" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="10"
+ layout="topleft"
+ left="12"
+ mouse_opaque="false"
+ name="b_val_text"
+ top="77"
+ width="413">
+ Blue:
+ </text>
+ <spinner
+ decimal_digits="0"
+ follows="left"
+ height="16"
+ increment="1"
+ initial_value="128"
+ layout="topleft"
+ left_delta="63"
+ max_val="255"
+ name="bspin"
+ top_delta="0"
+ width="50" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="10"
+ layout="topleft"
+ left="12"
+ mouse_opaque="false"
+ name="h_val_text"
+ top="108"
+ width="413">
+ Hue:
+ </text>
+ <spinner
+ decimal_digits="0"
+ follows="left"
+ height="16"
+ increment="1"
+ initial_value="180"
+ layout="topleft"
+ left_delta="63"
+ max_val="360"
+ name="hspin"
+ top_delta="0"
+ width="50" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="10"
+ layout="topleft"
+ left="12"
+ mouse_opaque="false"
+ name="s_val_text"
+ top="129"
+ width="413">
+ Sat:
+ </text>
+ <spinner
+ decimal_digits="0"
+ follows="left"
+ height="16"
+ increment="1"
+ initial_value="50"
+ layout="topleft"
+ left_delta="63"
+ max_val="100"
+ name="sspin"
+ top_delta="0"
+ width="50" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="10"
+ layout="topleft"
+ left="12"
+ mouse_opaque="false"
+ name="l_val_text"
+ top="150"
+ width="413">
+ Lum:
+ </text>
+ <spinner
+ decimal_digits="0"
+ follows="left"
+ height="16"
+ increment="1"
+ initial_value="50"
+ layout="topleft"
+ left_delta="63"
+ max_val="100"
+ name="lspin"
+ top_delta="0"
+ width="50" />
+ <check_box
+ follows="left|bottom"
+ height="20"
+ label="Apply now"
+ layout="topleft"
+ left="12"
+ name="apply_immediate"
+ top_pad="185"
+ width="100" />
+ <button
+ follows="left|bottom"
+ height="28"
+ image_selected="eye_button_active.tga"
+ image_unselected="eye_button_inactive.tga"
+ layout="topleft"
+ left_pad="50"
+ name="Pipette"
+ width="28" />
+ <button
+ follows="right|bottom"
+ height="20"
+ label="OK"
+ label_selected="OK"
+ layout="topleft"
+ right="-120"
+ top_delta="9"
+ name="select_btn"
+ width="100" />
+ <button
+ follows="right|bottom"
+ height="20"
+ label="Cancel"
+ label_selected="Cancel"
+ layout="topleft"
+ left_pad="5"
+ right="-10"
+ name="cancel_btn"
+ width="100" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="12"
+ name="Current color:"
+ top="172"
+ width="110">
+ Current color:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="12"
+ name="(Drag below to save.)"
+ top_pad="66"
+ width="130">
+ (Drag below to save)
+ </text>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_critical.xml b/indra/newview/skins/default/xui/en/floater_critical.xml
new file mode 100644
index 0000000000..7b5451553f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_critical.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_close="false"
+ can_minimize="false"
+ height="500"
+ layout="topleft"
+ name="modal container"
+ width="600">
+ <button
+ height="20"
+ label="Continue"
+ label_selected="Continue"
+ layout="topleft"
+ left="484"
+ name="Continue"
+ top="465"
+ width="100" />
+ <button
+ height="20"
+ label="Cancel"
+ label_selected="Cancel"
+ layout="topleft"
+ left_delta="-468"
+ name="Cancel"
+ top_delta="0"
+ width="100" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_delta="4"
+ name="tos_heading"
+ top_delta="-450"
+ width="552">
+ Please read the following message carefully.
+ </text>
+ <text_editor
+ type="string"
+ length="1"
+ bg_readonly_color="1 1 1 1"
+ bottom="455"
+ follows="left|top"
+ font="SansSerif"
+ layout="topleft"
+ left="20"
+ max_length="65536"
+ name="tos_text"
+ right="-20"
+ text_readonly_color="0 0 0 1"
+ top="45"
+ word_wrap="true">
+ TOS_TEXT
+ </text_editor>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_customize.xml b/indra/newview/skins/default/xui/en/floater_customize.xml
new file mode 100644
index 0000000000..b048eeceb6
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_customize.xml
@@ -0,0 +1,3389 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ follows="left|top"
+ height="583"
+ layout="topleft"
+ left_delta="-3"
+ name="floater customize"
+ help_topic="floater_customize"
+ save_rect="true"
+ title="APPEARANCE"
+ top_delta="-185"
+ width="524">
+ <tab_container
+ height="517"
+ layout="topleft"
+ left="10"
+ name="customize tab container"
+ tab_min_width="96"
+ tab_position="left"
+ tab_height="50"
+ top="26"
+ width="506">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="5"
+ name="body_parts_placeholder"
+ font="SansSerifSmallBold"
+ top="10"
+ width="100">
+ Body Parts
+ </text>
+ <placeholder />
+ <panel
+ border="false"
+ background_visible="true"
+ bg_alpha_color="DkGray2"
+ follows="left|top|right|bottom"
+ height="508"
+ label="Shape"
+ layout="topleft"
+ name="Shape"
+ help_topic="customize_shape_tab"
+ width="400">
+ <icon
+ follows="top|right"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ left="315"
+ mouse_opaque="true"
+ name="square"
+ top="4"
+ width="18" />
+ <icon
+ height="16"
+ top="10"
+ left="10"
+ layout="topleft"
+ mouse_opaque="true"
+ width="16" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Revert"
+ label_selected="Revert"
+ layout="topleft"
+ right="390"
+ name="Revert"
+ top="477"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Body"
+ label_selected="Body"
+ layout="topleft"
+ left="10"
+ name="Body"
+ top="63"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Head"
+ label_selected="Head"
+ layout="topleft"
+ left_delta="0"
+ name="Head"
+ top_pad="4"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Eyes"
+ label_selected="Eyes"
+ layout="topleft"
+ left_delta="0"
+ name="Eyes"
+ top_pad="4"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Ears"
+ label_selected="Ears"
+ layout="topleft"
+ left_delta="0"
+ name="Ears"
+ top_pad="4"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Nose"
+ label_selected="Nose"
+ layout="topleft"
+ left_delta="0"
+ name="Nose"
+ top_pad="4"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Mouth"
+ label_selected="Mouth"
+ layout="topleft"
+ left_delta="0"
+ name="Mouth"
+ top_pad="4"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Chin"
+ label_selected="Chin"
+ layout="topleft"
+ left_delta="0"
+ name="Chin"
+ top_pad="4"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Torso"
+ label_selected="Torso"
+ layout="topleft"
+ left_delta="0"
+ name="Torso"
+ top_pad="4"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Legs"
+ label_selected="Legs"
+ layout="topleft"
+ left_delta="0"
+ name="Legs"
+ top_pad="4"
+ width="82" />
+ <radio_group
+ control_name="AvatarSex"
+ height="34"
+ layout="topleft"
+ name="sex radio"
+ top_pad="10"
+ width="82">
+ <radio_item
+ height="16"
+ label="Female"
+ layout="topleft"
+ name="radio"
+ value="0"
+ width="82" />
+ <radio_item
+ height="16"
+ label="Male"
+ layout="topleft"
+ name="radio2"
+ value="1"
+ width="82" />
+ </radio_group>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title"
+ top="10"
+ width="355">
+ [DESC]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_no_modify"
+ top="10"
+ width="355">
+ [DESC]: cannot modify
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_loading"
+ top="10"
+ width="355">
+ [DESC]: loading...
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_not_worn"
+ top="10"
+ width="355">
+ [DESC]: not worn
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="path"
+ top="36"
+ width="373">
+ Located in [PATH]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="not worn instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ Put on a new shape by dragging one from your inventory to your avatar. Alternately, you create a new one from scratch and wear it.
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="no modify instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ You do not have permission to modify this wearable.
+ </text>
+ <text
+ type="string"
+ length="1"
+ top="488"
+ follows="left|top|right"
+ font="SansSerif"
+ halign="right"
+ height="23"
+ layout="topleft"
+ name="Item Action Label"
+ right="132"
+ width="100">
+ Shape:
+ </text>
+ <button
+ follows="left|top"
+ height="23"
+ label="Create New Shape"
+ label_selected="Create New Shape"
+ layout="topleft"
+ left="10"
+ name="Create New"
+ top="104"
+ width="160" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ name="Save"
+ right="218"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save As..."
+ label_selected="Save As..."
+ layout="topleft"
+ name="Save As"
+ top="477"
+ right="304"
+ width="82" />
+ </panel>
+ <panel
+ border="false"
+ background_visible="true"
+ bg_alpha_color="DkGray2"
+ follows="left|top|right|bottom"
+ height="508"
+ label="Skin"
+ layout="topleft"
+ name="Skin"
+ help_topic="customize_skin_tab"
+ width="400">
+ <icon
+ follows="top|right"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ left="315"
+ mouse_opaque="true"
+ name="square"
+ top="4"
+ width="18" />
+ <icon
+ height="16"
+ top="10"
+ left="10"
+ layout="topleft"
+ mouse_opaque="true"
+ width="16" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Skin Color"
+ label_selected="Skin Color"
+ layout="topleft"
+ left="10"
+ name="Skin Color"
+ top="63"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Face Detail"
+ label_selected="Face Detail"
+ layout="topleft"
+ left_delta="0"
+ name="Face Detail"
+ top_pad="4"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Makeup"
+ label_selected="Makeup"
+ layout="topleft"
+ left_delta="0"
+ name="Makeup"
+ top_pad="4"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Body Detail"
+ label_selected="Body Detail"
+ layout="topleft"
+ left_delta="0"
+ name="Body Detail"
+ top_pad="4"
+ width="82" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title"
+ top="10"
+ width="355">
+ [DESC]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_no_modify"
+ top="10"
+ width="355">
+ [DESC]: cannot modify
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_loading"
+ top="10"
+ width="355">
+ [DESC]: loading...
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_not_worn"
+ top="10"
+ width="355">
+ [DESC]: not worn
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="14"
+ layout="topleft"
+ left="10"
+ name="path"
+ top="36"
+ width="373">
+ Located in [PATH]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="not worn instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ Put on a new skin by dragging one from your inventory to your avatar. Alternately, you create a new one from scratch and wear it.
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="no modify instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ You do not have permission to modify this wearable.
+ </text>
+ <text
+ type="string"
+ length="1"
+ top="488"
+ follows="left|top|right"
+ font="SansSerif"
+ halign="right"
+ height="23"
+ layout="topleft"
+ name="Item Action Label"
+ right="132"
+ width="100">
+ Skin:
+ </text>
+ <texture_picker
+ allow_no_texture="true"
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Head Tattoos"
+ layout="topleft"
+ left="10"
+ name="Head Tattoos"
+ tool_tip="Click to choose a picture"
+ top="176"
+ width="82" />
+ <texture_picker
+ allow_no_texture="true"
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Upper Tattoos"
+ layout="topleft"
+ left_delta="0"
+ name="Upper Tattoos"
+ tool_tip="Click to choose a picture"
+ top_delta="102"
+ width="82" />
+ <texture_picker
+ allow_no_texture="true"
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Lower Tattoos"
+ layout="topleft"
+ left_delta="0"
+ name="Lower Tattoos"
+ tool_tip="Click to choose a picture"
+ top_delta="102"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Create New Skin"
+ label_selected="Create New Skin"
+ layout="topleft"
+ left_delta="0"
+ name="Create New"
+ top_delta="-249"
+ width="160" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ right="218"
+ name="Save"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save As..."
+ label_selected="Save As..."
+ layout="topleft"
+ right="304"
+ name="Save As"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Revert"
+ label_selected="Revert"
+ layout="topleft"
+ right="390"
+ name="Revert"
+ top="477"
+ width="82" />
+ </panel>
+ <panel
+ border="false"
+ background_visible="true"
+ bg_alpha_color="DkGray2"
+ follows="left|top|right|bottom"
+ height="508"
+ label="Hair"
+ layout="topleft"
+ name="Hair"
+ help_topic="customize_hair_tab"
+ width="400">
+ <icon
+ follows="top|right"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ left="315"
+ mouse_opaque="true"
+ name="square"
+ top="4"
+ width="18" />
+ <icon
+ height="16"
+ top="10"
+ left="10"
+ layout="topleft"
+ mouse_opaque="true"
+ width="16" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Color"
+ label_selected="Color"
+ layout="topleft"
+ left="10"
+ name="Color"
+ top="63"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Style"
+ label_selected="Style"
+ layout="topleft"
+ left_delta="0"
+ name="Style"
+ top_pad="4"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Eyebrows"
+ label_selected="Eyebrows"
+ layout="topleft"
+ name="Eyebrows"
+ top_pad="4"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Facial"
+ label_selected="Facial"
+ layout="topleft"
+ name="Facial"
+ top_pad="4"
+ width="82" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title"
+ top="10"
+ width="355">
+ [DESC]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_no_modify"
+ top="10"
+ width="355">
+ [DESC]: cannot modify
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_loading"
+ top="10"
+ width="355">
+ [DESC]: loading...
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_not_worn"
+ top="10"
+ width="355">
+ [DESC]: not worn
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="14"
+ layout="topleft"
+ left="10"
+ name="path"
+ top="36"
+ width="373">
+ Located in [PATH]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="not worn instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ Put on a new hair by dragging one from your inventory to your avatar. Alternately, you create a new one from scratch and wear it.
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="no modify instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ You do not have permission to modify this wearable.
+ </text>
+ <text
+ type="string"
+ length="1"
+ top="488"
+ follows="left|top|right"
+ font="SansSerif"
+ halign="right"
+ height="23"
+ layout="topleft"
+ name="Item Action Label"
+ right="132"
+ width="100">
+ Hair:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Texture"
+ layout="topleft"
+ left="10"
+ name="Texture"
+ tool_tip="Click to choose a picture"
+ top="176"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Create New Hair"
+ label_selected="Create New Hair"
+ layout="topleft"
+ left_delta="0"
+ name="Create New"
+ top_delta="-89"
+ width="160" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ right="218"
+ name="Save"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save As..."
+ label_selected="Save As..."
+ layout="topleft"
+ right="304"
+ name="Save As"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Revert"
+ label_selected="Revert"
+ layout="topleft"
+ right="390"
+ name="Revert"
+ top="477"
+ width="82" />
+ </panel>
+ <panel
+ border="false"
+ background_visible="true"
+ bg_alpha_color="DkGray2"
+ follows="left|top|right|bottom"
+ height="508"
+ label="Eyes"
+ layout="topleft"
+ name="Eyes"
+ help_topic="customize_eyes_tab"
+ width="400">
+ <icon
+ follows="top|right"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ left="315"
+ mouse_opaque="true"
+ name="square"
+ top="4"
+ width="18" />
+ <icon
+ height="16"
+ top="10"
+ left="10"
+ layout="topleft"
+ mouse_opaque="true"
+ width="16" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title"
+ top="10"
+ width="355">
+ [DESC]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_no_modify"
+ top="10"
+ width="355">
+ [DESC]: cannot modify
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_loading"
+ top="10"
+ width="355">
+ [DESC]: loading...
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_not_worn"
+ top="10"
+ width="355">
+ [DESC]: not worn
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="path"
+ top="36"
+ width="373">
+ Located in [PATH]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="not worn instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ Put on a new set of eyes by dragging one from your inventory to your avatar. Alternately, you create a new one from scratch and wear it.
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="no modify instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ You do not have permission to modify this wearable.
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="4"
+ follows="left|bottom|right"
+ font="SansSerif"
+ halign="right"
+ height="23"
+ layout="bottomleft"
+ name="Item Action Label"
+ right="132"
+ width="100">
+ Eyes:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Iris"
+ layout="topleft"
+ left="10"
+ name="Iris"
+ tool_tip="Click to choose a picture"
+ top="66"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Create New Eyes"
+ label_selected="Create New Eyes"
+ layout="topleft"
+ name="Create New"
+ top="66"
+ width="160" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ right="218"
+ name="Save"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save As..."
+ label_selected="Save As..."
+ layout="topleft"
+ right="304"
+ name="Save As"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Revert"
+ label_selected="Revert"
+ layout="topleft"
+ right="390"
+ name="Revert"
+ top="477"
+ width="82" />
+ </panel>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="5"
+ name="clothes_placeholder"
+ font="SansSerifSmallBold"
+ top="125"
+ width="100">
+ Clothes
+ </text>
+ <placeholder />
+ <panel
+ border="false"
+ background_visible="true"
+ bg_alpha_color="DkGray2"
+ follows="left|top|right|bottom"
+ height="508"
+ label="Shirt"
+ layout="topleft"
+ name="Shirt"
+ help_topic="customize_shirt_tab"
+ top_delta="0"
+ width="400">
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ name="square"
+ top="10"
+ width="18" />
+ <icon
+ height="16"
+ top="10"
+ left="10"
+ layout="topleft"
+ mouse_opaque="true"
+ width="16" />
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Fabric"
+ layout="topleft"
+ left="10"
+ name="Fabric"
+ tool_tip="Click to choose a picture"
+ top="66"
+ width="82" />
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="108"
+ label="Color/Tint"
+ layout="topleft"
+ name="Color/Tint"
+ tool_tip="Click to open color picker"
+ top_delta="102"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Take Off"
+ label_selected="Take Off"
+ layout="topleft"
+ name="Take Off"
+ top_pad="4"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Create New Shirt"
+ label_selected="Create New Shirt"
+ layout="topleft"
+ name="Create New"
+ top="66"
+ width="160" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ right="218"
+ name="Save"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save As..."
+ label_selected="Save As..."
+ layout="topleft"
+ right="304"
+ name="Save As"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Revert"
+ label_selected="Revert"
+ layout="topleft"
+ right="390"
+ name="Revert"
+ top="477"
+ width="82" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title"
+ top="10"
+ width="355">
+ [DESC]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_no_modify"
+ top="10"
+ width="355">
+ [DESC]: cannot modify
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_loading"
+ top="10"
+ width="355">
+ [DESC]: loading...
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_not_worn"
+ top="10"
+ width="355">
+ [DESC]: not worn
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="path"
+ top="36"
+ width="373">
+ Located in [PATH]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="not worn instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ Put on a new shirt by dragging one from your inventory to your avatar. Alternately, you create a new one from scratch and wear it.
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="no modify instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ You do not have permission to modify this wearable.
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="4"
+ follows="left|bottom|right"
+ font="SansSerif"
+ halign="right"
+ height="23"
+ layout="bottomleft"
+ name="Item Action Label"
+ right="132"
+ width="100">
+ Shirt:
+ </text>
+ </panel>
+ <panel
+ border="false"
+ background_visible="true"
+ bg_alpha_color="DkGray2"
+ follows="left|top|right|bottom"
+ height="508"
+ label="Pants"
+ layout="topleft"
+ name="Pants"
+ help_topic="customize_pants_tab"
+ width="400">
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ name="square"
+ top="10"
+ width="18" />
+ <icon
+ height="16"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ top="10"
+ width="16" />
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Fabric"
+ layout="topleft"
+ left="10"
+ name="Fabric"
+ tool_tip="Click to choose a picture"
+ top="66"
+ width="82" />
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="108"
+ label="Color/Tint"
+ layout="topleft"
+ name="Color/Tint"
+ tool_tip="Click to open color picker"
+ top_delta="102"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Take Off"
+ label_selected="Take Off"
+ layout="topleft"
+ name="Take Off"
+ top_pad="4"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Create New Pants"
+ label_selected="Create New Pants"
+ layout="topleft"
+ name="Create New"
+ top="66"
+ width="160" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ right="218"
+ name="Save"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save As..."
+ label_selected="Save As..."
+ layout="topleft"
+ right="304"
+ name="Save As"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Revert"
+ label_selected="Revert"
+ layout="topleft"
+ right="390"
+ name="Revert"
+ top="477"
+ width="82" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title"
+ top="10"
+ width="355">
+ [DESC]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_no_modify"
+ top="10"
+ width="355">
+ [DESC]: cannot modify
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_loading"
+ top="10"
+ width="355">
+ [DESC]: loading...
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_not_worn"
+ top="10"
+ width="355">
+ [DESC]: not worn
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="14"
+ layout="topleft"
+ left="10"
+ name="path"
+ top="36"
+ width="373">
+ Located in [PATH]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="not worn instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ Put on new pants by dragging one from your inventory to your avatar. Alternately, you create a new one from scratch and wear it.
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="no modify instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ You do not have permission to modify this wearable.
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="4"
+ follows="left|bottom|right"
+ font="SansSerif"
+ halign="right"
+ height="23"
+ layout="bottomleft"
+ name="Item Action Label"
+ right="132"
+ width="100">
+ Pants:
+ </text>
+ </panel>
+ <panel
+ border="false"
+ background_visible="true"
+ bg_alpha_color="DkGray2"
+ follows="left|top|right|bottom"
+ height="508"
+ label="Shoes"
+ layout="topleft"
+ name="Shoes"
+ help_topic="customize_shoes_tab"
+ width="400">
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ name="square"
+ top="10"
+ width="18" />
+ <icon
+ height="16"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ top="10"
+ width="16" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title"
+ top="10"
+ width="355">
+ [DESC]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_no_modify"
+ top="10"
+ width="355">
+ [DESC]: cannot modify
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_loading"
+ top="10"
+ width="355">
+ [DESC]: loading...
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_not_worn"
+ top="10"
+ width="355">
+ [DESC]: not worn
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="14"
+ layout="topleft"
+ left="10"
+ name="path"
+ top="36"
+ width="373">
+ Located in [PATH]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="not worn instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ Put on a new pair of shoes by dragging one from your inventory to your avatar. Alternately, you create a new one from scratch and wear it.
+ </text>
+ <button
+ follows="left|top"
+ height="23"
+ label="Create New Shoes"
+ label_selected="Create New Shoes"
+ layout="topleft"
+ name="Create New"
+ top_pad="18"
+ width="160" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="no modify instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ You do not have permission to modify this wearable.
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="4"
+ follows="left|bottom|right"
+ font="SansSerif"
+ halign="right"
+ height="23"
+ layout="bottomleft"
+ name="Item Action Label"
+ right="132"
+ width="100">
+ Shoes:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Fabric"
+ layout="topleft"
+ left="10"
+ name="Fabric"
+ tool_tip="Click to choose a picture"
+ top="66"
+ width="82" />
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="108"
+ label="Color/Tint"
+ layout="topleft"
+ name="Color/Tint"
+ tool_tip="Click to open color picker"
+ top_delta="102"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Take Off"
+ label_selected="Take Off"
+ layout="topleft"
+ name="Take Off"
+ top_pad="4"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ right="218"
+ name="Save"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save As..."
+ label_selected="Save As..."
+ layout="topleft"
+ right="304"
+ name="Save As"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Revert"
+ label_selected="Revert"
+ layout="topleft"
+ right="390"
+ name="Revert"
+ top="477"
+ width="82" />
+ </panel>
+ <panel
+ border="false"
+ background_visible="true"
+ bg_alpha_color="DkGray2"
+ follows="left|top|right|bottom"
+ height="508"
+ label="Socks"
+ layout="topleft"
+ name="Socks"
+ help_topic="customize_socks_tab"
+ width="400">
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ name="square"
+ top="10"
+ width="18" />
+ <icon
+ height="16"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ top="10"
+ width="16" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title"
+ top="10"
+ width="355">
+ [DESC]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_no_modify"
+ top="10"
+ width="355">
+ [DESC]: cannot modify
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_loading"
+ top="10"
+ width="355">
+ [DESC]: loading...
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_not_worn"
+ top="10"
+ width="355">
+ [DESC]: not worn
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="14"
+ layout="topleft"
+ left="10"
+ name="path"
+ top="36"
+ width="373">
+ Located in [PATH]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="not worn instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ Put on new socks by dragging one from your inventory to your avatar. Alternately, you create a new one from scratch and wear it.
+ </text>
+ <button
+ follows="left|top"
+ height="23"
+ label="Create New Socks"
+ label_selected="Create New Socks"
+ layout="topleft"
+ name="Create New"
+ top_pad="7"
+ width="160" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="no modify instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ You do not have permission to modify this wearable.
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="4"
+ follows="left|bottom|right"
+ font="SansSerif"
+ halign="right"
+ height="23"
+ layout="bottomleft"
+ name="Item Action Label"
+ right="132"
+ width="100">
+ Socks:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Fabric"
+ layout="topleft"
+ left="10"
+ name="Fabric"
+ tool_tip="Click to choose a picture"
+ top="66"
+ width="82" />
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="108"
+ label="Color/Tint"
+ layout="topleft"
+ name="Color/Tint"
+ tool_tip="Click to open color picker"
+ top_delta="102"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Take Off"
+ label_selected="Take Off"
+ layout="topleft"
+ name="Take Off"
+ top_pad="4"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ right="218"
+ name="Save"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save As..."
+ label_selected="Save As..."
+ layout="topleft"
+ right="304"
+ name="Save As"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Revert"
+ label_selected="Revert"
+ layout="topleft"
+ right="390"
+ name="Revert"
+ top="477"
+ width="82" />
+ </panel>
+ <panel
+ border="false"
+ background_visible="true"
+ bg_alpha_color="DkGray2"
+ follows="left|top|right|bottom"
+ height="508"
+ label="Jacket"
+ layout="topleft"
+ name="Jacket"
+ help_topic="customize_jacket_tab"
+ width="400">
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ name="square"
+ top="10"
+ width="18" />
+ <icon
+ height="16"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ top="10"
+ width="16" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title"
+ top="10"
+ width="355">
+ [DESC]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_no_modify"
+ top="10"
+ width="355">
+ [DESC]: cannot modify
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_loading"
+ top="10"
+ width="355">
+ [DESC]: loading...
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_not_worn"
+ top="10"
+ width="355">
+ [DESC]: not worn
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="14"
+ layout="topleft"
+ left="10"
+ name="path"
+ top="36"
+ width="373">
+ Located in [PATH]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="not worn instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ Put on a new jacket by dragging one from your inventory to your avatar. Alternately, you create a new one from scratch and wear it.
+ </text>
+ <button
+ follows="left|top"
+ height="23"
+ label="Create New Jacket"
+ label_selected="Create New Jacket"
+ layout="topleft"
+ name="Create New"
+ top_pad="7"
+ width="160" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="no modify instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ You do not have permission to modify this wearable.
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="4"
+ follows="left|bottom|right"
+ font="SansSerif"
+ halign="right"
+ height="23"
+ layout="bottomleft"
+ name="Item Action Label"
+ right="132"
+ width="100">
+ Jacket:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Upper Fabric"
+ layout="topleft"
+ left="10"
+ name="Upper Fabric"
+ tool_tip="Click to choose a picture"
+ top="66"
+ width="82" />
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Lower Fabric"
+ layout="topleft"
+ name="Lower Fabric"
+ tool_tip="Click to choose a picture"
+ top_delta="102"
+ width="82" />
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="108"
+ label="Color/Tint"
+ layout="topleft"
+ name="Color/Tint"
+ tool_tip="Click to open color picker"
+ top_delta="102"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Take Off"
+ label_selected="Take Off"
+ layout="topleft"
+ name="Take Off"
+ top_pad="4"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ right="218"
+ name="Save"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save As..."
+ label_selected="Save As..."
+ layout="topleft"
+ right="304"
+ name="Save As"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Revert"
+ label_selected="Revert"
+ layout="topleft"
+ right="390"
+ name="Revert"
+ top="477"
+ width="82" />
+ </panel>
+ <panel
+ border="false"
+ background_visible="true"
+ bg_alpha_color="DkGray2"
+ follows="left|top|right|bottom"
+ height="508"
+ label="Gloves"
+ layout="topleft"
+ name="Gloves"
+ help_topic="customize_gloves_tab"
+ width="400">
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ name="square"
+ top="10"
+ width="18" />
+ <icon
+ height="16"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ top="10"
+ width="16" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title"
+ top="10"
+ width="355">
+ [DESC]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_no_modify"
+ top="10"
+ width="355">
+ [DESC]: cannot modify
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_loading"
+ top="10"
+ width="355">
+ [DESC]: loading...
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_not_worn"
+ top="10"
+ width="355">
+ [DESC]: not worn
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="14"
+ layout="topleft"
+ left="10"
+ name="path"
+ top="36"
+ width="373">
+ Located in [PATH]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="not worn instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ Put on new gloves by dragging one from your inventory to your avatar. Alternately, you create a new one from scratch and wear it.
+ </text>
+ <button
+ follows="left|top"
+ height="23"
+ label="Create New Gloves"
+ label_selected="Create New Gloves"
+ layout="topleft"
+ name="Create New"
+ top_pad="7"
+ width="160" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="no modify instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ You do not have permission to modify this wearable.
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="4"
+ follows="left|bottom|right"
+ font="SansSerif"
+ halign="right"
+ height="23"
+ layout="bottomleft"
+ name="Item Action Label"
+ right="132"
+ width="100">
+ Gloves:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Fabric"
+ layout="topleft"
+ left="10"
+ name="Fabric"
+ tool_tip="Click to choose a picture"
+ top="66"
+ width="82" />
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="108"
+ label="Color/Tint"
+ layout="topleft"
+ name="Color/Tint"
+ tool_tip="Click to open color picker"
+ top_delta="102"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Take Off"
+ label_selected="Take Off"
+ layout="topleft"
+ name="Take Off"
+ top_pad="4"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ right="218"
+ name="Save"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save As..."
+ label_selected="Save As..."
+ layout="topleft"
+ right="304"
+ name="Save As"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Revert"
+ label_selected="Revert"
+ layout="topleft"
+ right="390"
+ name="Revert"
+ top="477"
+ width="82" />
+ </panel>
+ <panel
+ border="false"
+ background_visible="true"
+ bg_alpha_color="DkGray2"
+ follows="left|top|right|bottom"
+ height="508"
+ label="Undershirt"
+ layout="topleft"
+ name="Undershirt"
+ help_topic="customize_undershirt_tab"
+ width="400">
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ name="square"
+ top="10"
+ width="18" />
+ <icon
+ height="16"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ top="10"
+ width="16" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title"
+ top="10"
+ width="355">
+ [DESC]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_no_modify"
+ top="10"
+ width="355">
+ [DESC]: cannot modify
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_loading"
+ top="10"
+ width="355">
+ [DESC]: loading...
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_not_worn"
+ top="10"
+ width="355">
+ [DESC]: not worn
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="14"
+ layout="topleft"
+ left="10"
+ name="path"
+ top="36"
+ width="373">
+ Located in [PATH]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="not worn instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ Put on a new undershirt by dragging one from your inventory to your avatar. Alternately, you create a new one from scratch and wear it.
+ </text>
+ <button
+ follows="left|top"
+ height="23"
+ label="Create New Undershirt"
+ label_selected="Create New Undershirt"
+ layout="topleft"
+ name="Create New"
+ top_pad="7"
+ width="160" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="no modify instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ You do not have permission to modify this wearable.
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="4"
+ follows="left|bottom|right"
+ font="SansSerif"
+ halign="right"
+ height="23"
+ layout="bottomleft"
+ name="Item Action Label"
+ right="132"
+ width="100">
+ Undershirt:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Fabric"
+ layout="topleft"
+ left="10"
+ name="Fabric"
+ tool_tip="Click to choose a picture"
+ top="66"
+ width="82" />
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="108"
+ label="Color/Tint"
+ layout="topleft"
+ name="Color/Tint"
+ tool_tip="Click to open color picker"
+ top_delta="102"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Take Off"
+ label_selected="Take Off"
+ layout="topleft"
+ name="Take Off"
+ top_pad="4"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ right="218"
+ name="Save"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save As..."
+ label_selected="Save As..."
+ layout="topleft"
+ right="304"
+ name="Save As"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Revert"
+ label_selected="Revert"
+ layout="topleft"
+ right="390"
+ name="Revert"
+ top="477"
+ width="82" />
+ </panel>
+ <panel
+ border="false"
+ background_visible="true"
+ bg_alpha_color="DkGray2"
+ follows="left|top|right|bottom"
+ height="508"
+ label="Underpants"
+ layout="topleft"
+ name="Underpants"
+ help_topic="customize_underpants_tab"
+ width="400">
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ name="square"
+ top="10"
+ width="18" />
+ <icon
+ height="16"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ top="10"
+ width="16" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title"
+ top="10"
+ width="355">
+ [DESC]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_no_modify"
+ top="10"
+ width="355">
+ [DESC]: cannot modify
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_loading"
+ top="10"
+ width="355">
+ [DESC]: loading...
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_not_worn"
+ top="10"
+ width="355">
+ [DESC]: not worn
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="14"
+ layout="topleft"
+ left="10"
+ name="path"
+ top="36"
+ width="373">
+ Located in [PATH]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="not worn instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ Put on new underpants by dragging one from your inventory to your avatar. Alternately, you create a new one from scratch and wear it.
+ </text>
+ <button
+ follows="left|top"
+ height="23"
+ label="Create New Underpants"
+ label_selected="Create New Underpants"
+ layout="topleft"
+ name="Create New"
+ top_pad="7"
+ width="160" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="no modify instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ You do not have permission to modify this wearable.
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="4"
+ follows="left|bottom|right"
+ font="SansSerif"
+ halign="right"
+ height="23"
+ layout="bottomleft"
+ name="Item Action Label"
+ right="132"
+ width="100">
+ Underpants:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Fabric"
+ layout="topleft"
+ left="10"
+ name="Fabric"
+ tool_tip="Click to choose a picture"
+ top="66"
+ width="82" />
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="108"
+ label="Color/Tint"
+ layout="topleft"
+ name="Color/Tint"
+ tool_tip="Click to open color picker"
+ top_delta="102"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Take Off"
+ label_selected="Take Off"
+ layout="topleft"
+ name="Take Off"
+ top_pad="4"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ right="218"
+ name="Save"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save As..."
+ label_selected="Save As..."
+ layout="topleft"
+ right="304"
+ name="Save As"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Revert"
+ label_selected="Revert"
+ layout="topleft"
+ right="390"
+ name="Revert"
+ top="477"
+ width="82" />
+ </panel>
+ <panel
+ border="false"
+ background_visible="true"
+ bg_alpha_color="DkGray2"
+ follows="left|top|right|bottom"
+ height="508"
+ label="Skirt"
+ layout="topleft"
+ name="Skirt"
+ help_topic="customize_skirt_tab"
+ width="400">
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ name="square"
+ top="10"
+ width="18" />
+ <icon
+ height="16"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ top="10"
+ width="16" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title"
+ top="10"
+ width="355">
+ [DESC]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_no_modify"
+ top="10"
+ width="355">
+ [DESC]: cannot modify
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_loading"
+ top="10"
+ width="355">
+ [DESC]: loading...
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_not_worn"
+ top="10"
+ width="355">
+ [DESC]: not worn
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="14"
+ layout="topleft"
+ left="10"
+ name="path"
+ top="36"
+ width="373">
+ Located in [PATH]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="not worn instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ Put on a new skirt by dragging one from your inventory to your avatar. Alternately, you create a new one from scratch and wear it.
+ </text>
+ <button
+ follows="left|top"
+ height="23"
+ label="Create New Skirt"
+ label_selected="Create New Skirt"
+ layout="topleft"
+ name="Create New"
+ top_pad="7"
+ width="160" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="no modify instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ You do not have permission to modify this wearable.
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="4"
+ follows="left|bottom|right"
+ font="SansSerif"
+ halign="right"
+ height="23"
+ layout="bottomleft"
+ name="Item Action Label"
+ right="132"
+ width="100">
+ Skirt:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Fabric"
+ layout="topleft"
+ left="10"
+ name="Fabric"
+ tool_tip="Click to choose a picture"
+ top="66"
+ width="82" />
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="108"
+ label="Color/Tint"
+ layout="topleft"
+ name="Color/Tint"
+ tool_tip="Click to open color picker"
+ top_delta="102"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Take Off"
+ label_selected="Take Off"
+ layout="topleft"
+ name="Take Off"
+ top_pad="4"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ right="218"
+ name="Save"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save As..."
+ label_selected="Save As..."
+ layout="topleft"
+ right="304"
+ name="Save As"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Revert"
+ label_selected="Revert"
+ layout="topleft"
+ right="390"
+ name="Revert"
+ top="477"
+ width="82" />
+ </panel>
+ <panel
+ border="false"
+ background_visible="true"
+ bg_alpha_color="DkGray2"
+ follows="left|top|right|bottom"
+ height="508"
+ label="Tattoo"
+ layout="topleft"
+ name="Tattoo"
+ help_topic="customize_tattoo_tab"
+ width="400">
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ name="square"
+ top="10"
+ width="18" />
+ <icon
+ height="16"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ top="10"
+ width="16" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title"
+ top="10"
+ width="355">
+ [DESC]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_no_modify"
+ top="10"
+ width="355">
+ [DESC]: cannot modify
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_loading"
+ top="10"
+ width="355">
+ [DESC]: loading...
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_not_worn"
+ top="10"
+ width="355">
+ [DESC]: not worn
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="14"
+ layout="topleft"
+ left="10"
+ name="path"
+ top="36"
+ width="373">
+ Located in [PATH]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="not worn instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ Put on a new tattoo by dragging one from your inventory to your avatar. Alternately, you create a new one from scratch and wear it.
+ </text>
+ <button
+ follows="left|top"
+ height="23"
+ label="Create New Tattoo"
+ label_selected="Create New Tattoo"
+ layout="topleft"
+ name="Create New"
+ top_pad="7"
+ width="160" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="no modify instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ You do not have permission to modify this wearable.
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="4"
+ follows="left|bottom|right"
+ font="SansSerif"
+ halign="right"
+ height="23"
+ layout="bottomleft"
+ name="Item Action Label"
+ right="132"
+ width="100">
+ Tattoo:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Head Tattoo"
+ layout="topleft"
+ left="10"
+ name="Head Tattoo"
+ tool_tip="Click to choose a picture"
+ top="66"
+ width="82" />
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Upper Tattoo"
+ layout="topleft"
+ name="Upper Tattoo"
+ tool_tip="Click to choose a picture"
+ left_delta="90"
+ width="82" />
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Lower Tattoo"
+ layout="topleft"
+ name="Lower Tattoo"
+ tool_tip="Click to choose a picture"
+ left_delta="90"
+ width="82" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Take Off"
+ label_selected="Take Off"
+ layout="topleft"
+ name="Take Off"
+ top_pad="4"
+ left="10"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ right="218"
+ name="Save"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save As..."
+ label_selected="Save As..."
+ layout="topleft"
+ right="304"
+ name="Save As"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Revert"
+ label_selected="Revert"
+ layout="topleft"
+ right="390"
+ name="Revert"
+ top="477"
+ width="82" />
+ </panel>
+ <panel
+ border="false"
+ background_visible="true"
+ bg_alpha_color="DkGray2"
+ follows="left|top|right|bottom"
+ height="508"
+ label="Alpha"
+ layout="topleft"
+ name="Alpha"
+ help_topic="customize_alpha_tab"
+ width="400">
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ name="square"
+ top="10"
+ width="18" />
+ <icon
+ height="16"
+ layout="topleft"
+ left="10"
+ mouse_opaque="true"
+ top="10"
+ width="16" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title"
+ top="10"
+ width="355">
+ [DESC]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_no_modify"
+ top="10"
+ width="355">
+ [DESC]: cannot modify
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_loading"
+ top="10"
+ width="355">
+ [DESC]: loading...
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="31"
+ name="title_not_worn"
+ top="10"
+ width="355">
+ [DESC]: not worn
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="14"
+ layout="topleft"
+ left="10"
+ name="path"
+ top="36"
+ width="373">
+ Located in [PATH]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="not worn instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ Put on a new alpha mask by dragging one from your inventory to your avatar. Alternately, you create a new one from scratch and wear it.
+ </text>
+ <button
+ follows="left|top"
+ height="23"
+ label="Create New Alpha"
+ label_selected="Create New Alpha"
+ layout="topleft"
+ name="Create New"
+ top_pad="18"
+ width="160" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="no modify instructions"
+ top="31"
+ word_wrap="true"
+ width="373">
+ You do not have permission to modify this wearable.
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="4"
+ follows="left|bottom|right"
+ font="SansSerif"
+ halign="right"
+ height="23"
+ layout="bottomleft"
+ name="Item Action Label"
+ right="132"
+ width="100">
+ Alpha:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Lower Alpha"
+ layout="topleft"
+ left="10"
+ name="Lower Alpha"
+ tool_tip="Click to choose a picture"
+ top="66"
+ width="82" />
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Upper Alpha"
+ layout="topleft"
+ name="Upper Alpha"
+ tool_tip="Click to choose a picture"
+ left_delta="90"
+ width="82" />
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Head Alpha"
+ layout="topleft"
+ name="Head Alpha"
+ tool_tip="Click to choose a picture"
+ left_delta="90"
+ width="82" />
+ <check_box
+ control_name="LowerAlphaTextureInvisible"
+ follows="left"
+ height="16"
+ layout="topleft"
+ left="43"
+ name="lower alpha texture invisible"
+ top_delta="96"
+ width="16" />
+ <check_box
+ control_name="UpperAlphaTextureInvisible"
+ follows="left"
+ height="16"
+ layout="topleft"
+ left_pad="72"
+ name="upper alpha texture invisible"
+ width="16" />
+ <check_box
+ control_name="HeadAlphaTextureInvisible"
+ follows="left"
+ height="16"
+ layout="topleft"
+ left_pad="72"
+ name="head alpha texture invisible"
+ width="16" />
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Eye Alpha"
+ layout="topleft"
+ name="Eye Alpha"
+ tool_tip="Click to choose a picture"
+ left="10"
+ top_pad="20"
+ width="82" />
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="108"
+ label="Hair Alpha"
+ layout="topleft"
+ name="Hair Alpha"
+ left_delta="90"
+ tool_tip="Click to choose a picture"
+ width="82" />
+ <check_box
+ control_name="Eye AlphaTextureInvisible"
+ follows="left"
+ height="16"
+ layout="topleft"
+ left="43"
+ name="eye alpha texture invisible"
+ top_delta="96"
+ width="16" />
+ <check_box
+ control_name="HairAlphaTextureInvisible"
+ follows="left"
+ height="16"
+ layout="topleft"
+ left_pad="72"
+ name="hair alpha texture invisible"
+ width="16" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Take Off"
+ label_selected="Take Off"
+ layout="topleft"
+ name="Take Off"
+ left="10"
+ top_pad="20"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ right="218"
+ name="Save"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Save As..."
+ label_selected="Save As..."
+ layout="topleft"
+ right="304"
+ name="Save As"
+ top="477"
+ width="82" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Revert"
+ label_selected="Revert"
+ layout="topleft"
+ right="390"
+ name="Revert"
+ top="477"
+ width="82" />
+ </panel>
+ </tab_container>
+ <scroll_container
+ follows="left|top|right|bottom"
+ height="409"
+ layout="topleft"
+ left="211"
+ mouse_opaque="false"
+ name="panel_container"
+ top="92"
+ width="292">
+ <scrolling_panel_list
+ follows="left|bottom"
+ layout="topleft"
+ name="panel_list" />
+ </scroll_container>
+ <button
+ bottom="460"
+ follows="right|left"
+ height="23"
+ label="Script Info"
+ label_selected="Script Info"
+ layout="topleft"
+ name="script_info"
+ tool_tip="Show scripts attached to your avatar"
+ left="13"
+ width="90" />
+ <button
+ bottom="574"
+ follows="right|bottom"
+ height="23"
+ label="Make Outfit"
+ label_selected="Make Outfit"
+ layout="topleft"
+ name="make_outfit_btn"
+ right="-218"
+ width="100" />
+ <button
+ bottom="574"
+ follows="right|bottom"
+ height="23"
+ label="Cancel"
+ label_selected="Cancel"
+ layout="topleft"
+ name="Cancel"
+ right="-10"
+ width="100" />
+ <button
+ bottom="574"
+ follows="right|bottom"
+ height="23"
+ label="OK"
+ label_selected="OK"
+ layout="topleft"
+ name="Ok"
+ right="-114"
+ width="100" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_day_cycle_options.xml b/indra/newview/skins/default/xui/en/floater_day_cycle_options.xml
new file mode 100644
index 0000000000..8c5af2283d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_day_cycle_options.xml
@@ -0,0 +1,557 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="275"
+ layout="topleft"
+ name="Day Cycle Floater"
+ help_topic="day_cycle_floater"
+ save_rect="true"
+ title="DAY CYCLE EDITOR"
+ width="646">
+ <tab_container
+ follows="left|top"
+ height="255"
+ layout="topleft"
+ left="0"
+ name="Day Cycle Tabs"
+ tab_position="top"
+ top="20"
+ width="644">
+ <panel
+ border="true"
+ follows="left|top|right|bottom"
+ height="255"
+ label="Day Cycle"
+ layout="topleft"
+ left="1"
+ mouse_opaque="false"
+ name="Day Cycle"
+ top="0"
+ width="642">
+ <multi_slider
+ can_edit_text="true"
+ control_name="WLTimeSlider"
+ decimal_digits="0"
+ draw_track="false"
+ follows="bottom"
+ height="10"
+ increment="0.0833333"
+ initial_value="0"
+ layout="topleft"
+ left="20"
+ max_sliders="20"
+ max_val="24"
+ name="WLTimeSlider"
+ show_text="false"
+ top="25"
+ use_triangle="true"
+ width="525" />
+ <multi_slider
+ can_edit_text="true"
+ control_name="WLDayCycleKeys"
+ decimal_digits="0"
+ follows="bottom"
+ height="10"
+ increment="0.0833333"
+ initial_value="0"
+ layout="topleft"
+ left_delta="0"
+ max_sliders="20"
+ max_val="24"
+ name="WLDayCycleKeys"
+ show_text="false"
+ top_pad="15"
+ width="525" />
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left="8"
+ name="WL12am"
+ top="74"
+ width="55">
+ 12am
+ </text>
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="WL3am"
+ top_delta="0"
+ width="55">
+ 3am
+ </text>
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="WL6am"
+ top_delta="0"
+ width="55">
+ 6am
+ </text>
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="WL9amHash"
+ top_delta="0"
+ width="55">
+ 9am
+ </text>
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="WL12pmHash"
+ top_delta="0"
+ width="55">
+ 12pm
+ </text>
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="WL3pm"
+ top_delta="0"
+ width="55">
+ 3pm
+ </text>
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="WL6pm"
+ top_delta="0"
+ width="55">
+ 6pm
+ </text>
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="WL9pm"
+ top_delta="0"
+ width="55">
+ 9pm
+ </text>
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="WL12am2"
+ top_delta="0"
+ width="55">
+ 12am
+ </text>
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ font="SansSerif"
+ height="14"
+ layout="topleft"
+ left="20"
+ name="WL12amHash"
+ top="54"
+ width="6">
+ |
+ </text>
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ font="SansSerif"
+ height="11"
+ layout="topleft"
+ left_pad="59"
+ name="WL3amHash"
+ top_delta="3"
+ width="6">
+ I
+ </text>
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ font="SansSerif"
+ height="14"
+ layout="topleft"
+ left_pad="59"
+ name="WL6amHash"
+ top_delta="-3"
+ width="6">
+ |
+ </text>
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ font="SansSerif"
+ height="11"
+ layout="topleft"
+ left_pad="59"
+ name="WL9amHash2"
+ top_delta="3"
+ width="6">
+ I
+ </text>
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ font="SansSerif"
+ height="14"
+ layout="topleft"
+ left_pad="59"
+ name="WL12pmHash2"
+ top_delta="-3"
+ width="6">
+ |
+ </text>
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ font="SansSerif"
+ height="11"
+ layout="topleft"
+ left_pad="59"
+ name="WL3pmHash"
+ top_delta="3"
+ width="6">
+ I
+ </text>
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ font="SansSerif"
+ height="14"
+ layout="topleft"
+ left_pad="59"
+ name="WL6pmHash"
+ top_delta="-3"
+ width="6">
+ |
+ </text>
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ font="SansSerif"
+ height="11"
+ layout="topleft"
+ left_pad="59"
+ name="WL9pmHash"
+ top_delta="3"
+ width="6">
+ I
+ </text>
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ font="SansSerif"
+ height="14"
+ layout="topleft"
+ left_pad="59"
+ name="WL12amHash2"
+ top_delta="-3"
+ width="6">
+ |
+ </text>
+ <button
+ height="20"
+ label="Add Key"
+ label_selected="Add Key"
+ layout="topleft"
+ left="555"
+ name="WLAddKey"
+ top="30"
+ width="80" />
+ <button
+ height="20"
+ label="Delete Key"
+ label_selected="Delete Key"
+ layout="topleft"
+ left_delta="0"
+ name="WLDeleteKey"
+ top_pad="5"
+ width="80" />
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="20"
+ name="WLCurKeyFrameText"
+ top="104"
+ width="150">
+ Key Frame Settings:
+ </text>
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="30"
+ name="WLCurKeyTimeText"
+ top="124"
+ width="100">
+ Key Time:
+ </text>
+ <spinner
+ control_name="WLCurKeyHour"
+ decimal_digits="0"
+ follows="left|top"
+ height="16"
+ increment="1"
+ initial_value="0"
+ label="Hour"
+ label_width="30"
+ layout="topleft"
+ left_delta="0"
+ max_val="100"
+ name="WLCurKeyHour"
+ top_pad="4"
+ width="70" />
+ <spinner
+ control_name="WLCurKeyMin"
+ decimal_digits="0"
+ follows="left|top"
+ height="16"
+ increment="5"
+ initial_value="0"
+ label="Min"
+ label_width="20"
+ layout="topleft"
+ left_pad="5"
+ max_val="55"
+ name="WLCurKeyMin"
+ top_delta="0"
+ width="60" />
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="30"
+ name="WLCurKeyTimeText2"
+ top="169"
+ width="120">
+ Key Preset:
+ </text>
+ <combo_box
+ height="18"
+ label="Preset"
+ layout="topleft"
+ left_delta="0"
+ name="WLKeyPresets"
+ top_pad="7"
+ width="155" />
+ <view_border
+ bevel_style="none"
+ follows="top|left"
+ height="115"
+ layout="topleft"
+ left="12"
+ top="101"
+ width="190" />
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="220"
+ name="DayCycleText"
+ top="114"
+ width="120">
+ Snap:
+ </text>
+ <combo_box
+ enabled="false"
+ height="18"
+ label="5 min"
+ layout="topleft"
+ left_delta="0"
+ name="WLSnapOptions"
+ top_pad="7"
+ width="70" />
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="DayCycleText2"
+ top_pad="9"
+ width="120">
+ Length of Cycle:
+ </text>
+ <spinner
+ control_name="WLLengthOfDayHour"
+ decimal_digits="0"
+ follows="left|top"
+ height="16"
+ increment="1"
+ initial_value="0"
+ label="Hour"
+ label_width="30"
+ layout="topleft"
+ left_delta="0"
+ max_val="100"
+ name="WLLengthOfDayHour"
+ top_pad="4"
+ width="70" />
+ <spinner
+ control_name="WLLengthOfDayMin"
+ decimal_digits="0"
+ follows="left|top"
+ height="16"
+ increment="1"
+ initial_value="0"
+ label="Min"
+ label_width="20"
+ layout="topleft"
+ left_pad="5"
+ max_val="59"
+ name="WLLengthOfDayMin"
+ top_delta="0"
+ width="60" />
+ <spinner
+ control_name="WLLengthOfDaySec"
+ decimal_digits="0"
+ follows="left|top"
+ height="16"
+ increment="1"
+ initial_value="24"
+ label="Sec"
+ label_width="20"
+ layout="topleft"
+ left_pad="5"
+ max_val="59"
+ name="WLLengthOfDaySec"
+ top_delta="0"
+ width="60" />
+ <text
+ type="string"
+ length="1"
+ border_visible="true"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="310"
+ name="DayCycleText3"
+ top="114"
+ width="120">
+ Preview:
+ </text>
+ <button
+ height="20"
+ label="Play"
+ label_selected="Play"
+ layout="topleft"
+ left_delta="60"
+ name="WLAnimSky"
+ top_pad="5"
+ width="50" />
+ <button
+ height="20"
+ label="Stop!"
+ label_selected="Stop"
+ layout="topleft"
+ left_pad="5"
+ name="WLStopAnimSky"
+ top_delta="0"
+ width="50" />
+ <button
+ height="20"
+ label="Use Estate Time"
+ label_selected="Go to Estate Time"
+ layout="topleft"
+ left_pad="5"
+ name="WLUseLindenTime"
+ top_delta="0"
+ width="150" />
+ <button
+ height="20"
+ label="Save Test Day"
+ label_selected="Save Test Day"
+ layout="topleft"
+ left="480"
+ name="WLSaveDayCycle"
+ top="175"
+ width="150" />
+ <button
+ height="20"
+ label="Load Test Day"
+ label_selected="Load Test Day"
+ layout="topleft"
+ left_delta="0"
+ name="WLLoadDayCycle"
+ top_pad="5"
+ width="150" />
+ </panel>
+ </tab_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_device_settings.xml b/indra/newview/skins/default/xui/en/floater_device_settings.xml
new file mode 100644
index 0000000000..91a7a678da
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_device_settings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="260"
+ layout="topleft"
+ name="floater_device_settings"
+ help_topic="floater_device_settings"
+ title="VOICE CHAT DEVICE SETTINGS"
+ width="405">
+ <panel
+ bottom="260"
+ filename="panel_audio_device.xml"
+ layout="topleft"
+ left="2"
+ name="device_settings"
+ right="-5"
+ top="20" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_env_settings.xml b/indra/newview/skins/default/xui/en/floater_env_settings.xml
new file mode 100644
index 0000000000..8c87bd42dd
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_env_settings.xml
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="150"
+ layout="topleft"
+ name="Environment Editor Floater"
+ help_topic="environment_editor_floater"
+ save_rect="true"
+ title="ENVIRONMENT EDITOR"
+ width="600">
+ <floater.string
+ name="timeStr">
+ [hour12,datetime,utc]:[min,datetime,utc] [ampm,datetime,utc]
+ </floater.string>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="EnvTimeText"
+ top="32"
+ width="140">
+ Time of Day
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left="15"
+ name="EnvTimeText2"
+ top="62"
+ width="140">
+ 12:00 PM
+ </text>
+ <icon
+ height="25"
+ image_name="icon_diurnal.tga"
+ layout="topleft"
+ left="85"
+ name="EnvDayCycle"
+ top="30"
+ width="200" />
+ <slider
+ control_name="EnvTimeSlider"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.0069444"
+ initial_value="0.7"
+ layout="topleft"
+ left_delta="0"
+ max_val="0.99"
+ name="EnvTimeSlider"
+ show_text="false"
+ top_pad="10"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="EnvCloudText"
+ top="86"
+ width="140">
+ Cloud Cover
+ </text>
+ <slider
+ control_name="EnvCloudSlider"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left_delta="75"
+ name="EnvCloudSlider"
+ top_delta="4"
+ width="210" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="310"
+ name="EnvWaterColorText"
+ top="39"
+ width="140">
+ Water Color
+ </text>
+ <color_swatch
+ can_apply_immediately="true"
+ color="0.5 0.5 0.5 1"
+ follows="left|top"
+ height="50"
+ layout="topleft"
+ left="390"
+ name="EnvWaterColor"
+ tool_tip="Click to open color picker"
+ top="30"
+ width="40" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="310"
+ name="EnvWaterFogText"
+ top="86"
+ width="140">
+ Water Fog
+ </text>
+ <slider
+ control_name="EnvWaterFogSlider"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ initial_value="0"
+ layout="topleft"
+ left_delta="75"
+ max_val="10"
+ name="EnvWaterFogSlider"
+ top_delta="4"
+ width="210" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Use Estate Time"
+ layout="topleft"
+ left="8"
+ name="EnvUseEstateTimeButton"
+ top="120"
+ width="137" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Advanced Sky"
+ layout="topleft"
+ left_pad="9"
+ name="EnvAdvancedSkyButton"
+ top_delta="0"
+ width="137" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Advanced Water"
+ layout="topleft"
+ left_pad="9"
+ name="EnvAdvancedWaterButton"
+ top_delta="0"
+ width="137" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_first_time_tip.xml b/indra/newview/skins/default/xui/en/floater_first_time_tip.xml
new file mode 100644
index 0000000000..e4ac8fed77
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_first_time_tip.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_close="true"
+ can_minimize="false"
+ height="250"
+ layout="topleft"
+ name="set_name_in_the_cladd"
+ help_topic="set_name_in_the_cladd"
+ save_rect="true"
+ width="300">
+ <check_box
+ height="20"
+ follows="left|bottom|right"
+ label="Turn off Quick Tips"
+ layout="topleft"
+ left="5"
+ name="DontShowFirstTimeTip_checkbox"
+ text_enabled_color="white"
+ top="225"
+ width="200" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_font_test.xml b/indra/newview/skins/default/xui/en/floater_font_test.xml
new file mode 100644
index 0000000000..3ab19ec9d9
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_font_test.xml
@@ -0,0 +1,364 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="800"
+ layout="topleft"
+ min_height="175"
+ min_width="154"
+ name="contents"
+ help_topic="contents"
+ title="FONT TEST"
+ width="500">
+ <text
+ type="string"
+ length="1"
+ bottom_delta="40"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left="16">
+ SansSerifSmall
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="SansSerifMedium"
+ height="16"
+ layout="topleft"
+ left="16">
+ SansSerifMedium
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="16">
+ SansSerif, no size or style (should be same as medium)
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="SansSerifLarge"
+ height="16"
+ layout="topleft"
+ left="16">
+ SansSerifLarge
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="36"
+ follows="left|top|right"
+ font="SansSerifHuge"
+ height="32"
+ layout="topleft"
+ left="16">
+ SansSerifHuge
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="36"
+ follows="left|top|right"
+ font="SansSerifHuge"
+ font.style.="BOLD"
+ height="32"
+ layout="topleft"
+ left="16">
+ SansSerifHuge style=BOLD
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="36"
+ follows="left|top|right"
+ font="SansSerifBold"
+ font.size="Huge"
+ height="32"
+ layout="topleft"
+ left="16">
+ SansSerifBold size=Huge
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="40"
+ follows="left|top|right"
+ font="Monospace"
+ height="16"
+ layout="topleft"
+ left="16">
+ Monospace
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="Monospace"
+ font.size="Large"
+ height="16"
+ layout="topleft"
+ left="16">
+ Monospace size=Large
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="SansSerifLarge"
+ font.style="BOLD"
+ height="16"
+ layout="topleft"
+ left="16">
+ SansSerifLarge style=BOLD
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="SansSerifBold"
+ height="16"
+ layout="topleft"
+ left="16">
+ SansSerifBold
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="SansSerif"
+ font.style="BOLD"
+ height="16"
+ layout="topleft"
+ left="16">
+ SansSerif style=BOLD (should be same as SansSerifBold)
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="SansSerif"
+ font.style="ITALIC"
+ height="16"
+ layout="topleft"
+ left="16">
+ SansSerif style=ITALIC
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="SansSerif"
+ font.style="BOLD|ITALIC"
+ height="16"
+ layout="topleft"
+ left="16">
+ SansSerif style=BOLD|ITALIC
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="SansSerif"
+ font.style="BOLD|ITALIC"
+ height="16"
+ layout="topleft"
+ left="16">
+ SansSerif style=BOLD|ITALIC shadow=soft
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="SansSerif"
+ font.style="UNDERLINE"
+ height="16"
+ layout="topleft"
+ left="16">
+ SansSerif style=UNDERLINE
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="SansSerif"
+ font_shadow="none"
+ height="16"
+ layout="topleft"
+ left="16">
+ SansSerif style=hard
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="16">
+ SansSerif shadow=soft
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="DejaVu"
+ height="16"
+ layout="topleft"
+ left="16">
+ DejaVu
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="DejaVu"
+ font.style="BOLD"
+ height="16"
+ layout="topleft"
+ left="16">
+ DejaVu style=BOLD
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="DejaVu"
+ font.style="ITALIC"
+ height="16"
+ layout="topleft"
+ left="16">
+ DejaVu style=ITALIC
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="DejaVu"
+ font.style="BOLD|ITALIC"
+ height="16"
+ layout="topleft"
+ left="16">
+ DejaVu style=BOLD|ITALIC
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="DejaVu"
+ font.size="Large"
+ font.style="BOLD|ITALIC"
+ height="16"
+ layout="topleft"
+ left="16">
+ DejaVu size=Large style=BOLD|ITALIC
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="Helvetica"
+ height="16"
+ layout="topleft"
+ left="16">
+ Helvetica
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="Helvetica"
+ font.style="BOLD"
+ height="16"
+ layout="topleft"
+ left="16">
+ Helvetica style=BOLD
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="Helvetica"
+ font.style="ITALIC"
+ height="16"
+ layout="topleft"
+ left="16">
+ Helvetica style=ITALIC
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="Helvetica"
+ font.style="BOLD|ITALIC"
+ height="16"
+ layout="topleft"
+ left="16">
+ Helvetica style=BOLD|ITALIC
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="Helvetica"
+ font.size="Large"
+ font.style="BOLD|ITALIC"
+ height="16"
+ layout="topleft"
+ left="16">
+ Helvetica size=Large style=BOLD|ITALIC
+ </text>
+<!--
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ font="OverrideTest"
+ height="16"
+ layout="topleft"
+ left="16"
+ name="linea">
+ OverrideTest, should be times, from default/xui/en
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left="16">
+ BogusFontName
+ </text>
+-->
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_gesture.xml b/indra/newview/skins/default/xui/en/floater_gesture.xml
new file mode 100644
index 0000000000..9f5e6828d2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_gesture.xml
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="465"
+ name="gestures"
+ help_topic="gestures"
+ title="GESTURES"
+ background_visible="true"
+ follows="all"
+ label="Places"
+ layout="topleft"
+ min_height="350"
+ min_width="240"
+ width="313">
+ <floater.string
+ name="loading">
+ Loading...
+ </floater.string>
+ <floater.string
+ name="playing">
+ (Playing)
+ </floater.string>
+ <!-- It's used to build new name for gesture created by "Copy" menu item -->
+ <floater.string
+ name="copy_name">Copy of [COPY_NAME]</floater.string>
+ <scroll_list
+ bottom_delta="400"
+ draw_heading="true"
+ follows="all"
+ layout="topleft"
+ left="0"
+ multi_select="true"
+ top="20"
+ name="gesture_list">
+ <scroll_list.columns
+ label="Name"
+ name="name"
+ width="153" />
+ <scroll_list.columns
+ label="Chat"
+ name="trigger"
+ width="80" />
+ <scroll_list.columns
+ label=""
+ name="key"
+ width="-1" />
+ <scroll_list.columns
+ label="Key"
+ name="shortcut"
+ width="80" />
+ </scroll_list>
+ <panel
+ background_visible="true"
+ bevel_style="none"
+ top_pad="0"
+ follows="left|right|bottom"
+ height="30"
+ label="bottom_panel"
+ layout="topleft"
+ left="0"
+ name="bottom_panel"
+ width="313">
+ <menu_button
+ follows="bottom|left"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ layout="topleft"
+ left="10"
+ menu_filename="menu_gesture_gear.xml"
+ name="gear_btn"
+ top="5"
+ tool_tip="More options"
+ width="18" />
+ <button
+ follows="bottom|left"
+ font="SansSerifBigBold"
+ height="18"
+ image_selected="AddItem_Press"
+ image_unselected="AddItem_Off"
+ image_disabled="AddItem_Disabled"
+ layout="topleft"
+ left_pad="5"
+ name="new_gesture_btn"
+ tool_tip="Make new gesture"
+ top_delta="0"
+ width="18" />
+ <button
+ follows="bottom|left"
+ font="SansSerifBigBold"
+ height="10"
+ image_hover_selected="Activate_Checkmark"
+ image_selected="Activate_Checkmark"
+ image_unselected="Activate_Checkmark"
+ layout="topleft"
+ left_pad="5"
+ name="activate_btn"
+ tool_tip="Activate/Deactivate selected gesture"
+ top="10"
+ width="10" />
+ <button
+ follows="bottom|right"
+ font="SansSerifBigBold"
+ height="18"
+ image_selected="TrashItem_Press"
+ image_unselected="TrashItem_Off"
+ image_disabled="TrashItem_Disabled"
+ layout="topleft"
+ name="del_btn"
+ right="-5"
+ tool_tip="Delete this gesture"
+ top_delta="0"
+ width="18" />
+ </panel>
+ <button
+ follows="left|bottom"
+ height="23"
+ label="Edit"
+ layout="topleft"
+ left="6"
+ name="edit_btn"
+ top_pad="5"
+ width="83" />
+ <button
+ follows="left|bottom"
+ height="23"
+ label="Play"
+ layout="topleft"
+ left_pad="6"
+ name="play_btn"
+ top_delta="0"
+ width="83" />
+ <button
+ follows="left|bottom"
+ height="23"
+ label="Stop"
+ layout="topleft"
+ left_delta="0"
+ name="stop_btn"
+ top_delta="0"
+ width="83" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_god_tools.xml b/indra/newview/skins/default/xui/en/floater_god_tools.xml
new file mode 100644
index 0000000000..0fac6cd5f1
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_god_tools.xml
@@ -0,0 +1,789 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="384"
+ layout="topleft"
+ name="godtools floater"
+ help_topic="godtools_floater"
+ title="GOD TOOLS"
+ width="400">
+ <tab_container
+ follows="left|top"
+ height="364"
+ layout="topleft"
+ left="0"
+ name="GodTools Tabs"
+ tab_position="top"
+ top="20"
+ width="400">
+ <panel
+ border="true"
+ follows="left|top|right|bottom"
+ height="347"
+ label="Grid"
+ layout="topleft"
+ left="1"
+ mouse_opaque="false"
+ help_topic="godtools_grid_tab"
+ name="grid"
+ top="16"
+ width="398">
+ <button
+ follows="left|top"
+ height="20"
+ label="Kick all users"
+ label_selected="Kick all users"
+ layout="topleft"
+ left="10"
+ name="Kick all users"
+ top="30"
+ width="120">
+ <button.commit_callback
+ function="GridTools.KickAll" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="Flush This Region&apos;s Map Visibility Caches"
+ label_selected="Flush This Region&apos;s Map Visibility Caches"
+ layout="topleft"
+ left="10"
+ name="Flush This Region&apos;s Map Visibility Caches"
+ top_pad="30"
+ width="350">
+ <button.commit_callback
+ function="GridTools.FlushMapVisibilityCaches" />
+ </button>
+ </panel>
+ <panel
+ border="true"
+ follows="left|top|right|bottom"
+ height="347"
+ label="Region"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ help_topic="godtools_region_tab"
+ name="region"
+ top_delta="0"
+ width="398">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="Sim Name:"
+ top="12"
+ width="80">
+ Sim Name:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ height="20"
+ layout="topleft"
+ left_pad="0"
+ max_length="63"
+ name="region name"
+ top_delta="0"
+ width="250">
+ <line_editor.commit_callback
+ function="RegionTools.ChangeAnything" />
+ </line_editor>
+ <check_box
+ height="16"
+ label="Prelude"
+ layout="topleft"
+ left="10"
+ name="check prelude"
+ tool_tip="Set this to make the region a prelude"
+ top_pad="10"
+ width="180">
+ <check_box.commit_callback
+ function="RegionTools.ChangePrelude" />
+ </check_box>
+ <check_box
+ height="16"
+ label="Fixed Sun"
+ layout="topleft"
+ left_delta="0"
+ name="check fixed sun"
+ tool_tip="Fix the sun position (like in Region/Estate &gt; Terrain"
+ top_pad="4"
+ width="180">
+ <check_box.commit_callback
+ function="RegionTools.ChangeAnything" />
+ </check_box>
+ <check_box
+ height="16"
+ label="Reset Home On Teleport"
+ layout="topleft"
+ left_delta="0"
+ name="check reset home"
+ tool_tip="When Resident teleports out, reset their home to the destination position."
+ top_pad="4"
+ width="180">
+ <check_box.commit_callback
+ function="RegionTools.ChangeAnything" />
+ </check_box>
+ <check_box
+ height="16"
+ label="Visible"
+ layout="topleft"
+ left_delta="0"
+ name="check visible"
+ tool_tip="Set this to make the region visible to non-gods"
+ top_pad="4"
+ width="180">
+ <check_box.commit_callback
+ function="RegionTools.ChangeAnything" />
+ </check_box>
+ <check_box
+ height="16"
+ label="Damage"
+ layout="topleft"
+ left_delta="0"
+ name="check damage"
+ tool_tip="Set this to enable damage in this region"
+ top_pad="4"
+ width="180">
+ <check_box.commit_callback
+ function="RegionTools.ChangeAnything" />
+ </check_box>
+ <check_box
+ height="16"
+ label="Block Traffic Tracking"
+ layout="topleft"
+ left_delta="0"
+ name="block dwell"
+ tool_tip="Set this to make the region not compute traffic"
+ top_pad="4"
+ width="180">
+ <check_box.commit_callback
+ function="RegionTools.ChangeAnything" />
+ </check_box>
+ <check_box
+ height="16"
+ label="Block Terraform"
+ layout="topleft"
+ left_delta="0"
+ name="block terraform"
+ tool_tip="Set this to disallow people terraforming their land"
+ top_pad="4"
+ width="180">
+ <check_box.commit_callback
+ function="RegionTools.ChangeAnything" />
+ </check_box>
+ <check_box
+ height="16"
+ label="Sandbox"
+ layout="topleft"
+ left_delta="0"
+ name="is sandbox"
+ tool_tip="Toggle whether this is a sandbox region"
+ top_pad="4"
+ width="180">
+ <check_box.commit_callback
+ function="RegionTools.ChangeAnything" />
+ </check_box>
+ <button
+ follows="top|right"
+ height="22"
+ label="Bake Terrain"
+ label_selected="Bake Terrain"
+ layout="topleft"
+ left="12"
+ name="Bake Terrain"
+ tool_tip="Save the current terrain as default"
+ top_pad="32"
+ width="110">
+ <button.commit_callback
+ function="RegionTools.BakeTerrain" />
+ </button>
+ <button
+ follows="top|right"
+ height="22"
+ label="Revert Terrain"
+ label_selected="Revert Terrain"
+ layout="topleft"
+ name="Revert Terrain"
+ tool_tip="Replace the current terrain with default"
+ top_pad="10"
+ width="110">
+ <button.commit_callback
+ function="RegionTools.RevertTerrain" />
+ </button>
+ <button
+ follows="top|right"
+ height="22"
+ label="Swap Terrain"
+ label_selected="Swap Terrain"
+ layout="topleft"
+ name="Swap Terrain"
+ tool_tip="Swap current terrain with default"
+ top_pad="10"
+ width="110">
+ <button.commit_callback
+ function="RegionTools.SwapTerrain" />
+ </button>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="200"
+ name="estate id"
+ top="40"
+ width="190">
+ Estate ID:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="top|right"
+ height="16"
+ layout="topleft"
+ left_delta="108"
+ max_length="10"
+ name="estate"
+ top_delta="0"
+ width="50" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="200"
+ name="parent id"
+ top_pad="4"
+ width="190">
+ Parent ID:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="top|right"
+ height="16"
+ layout="topleft"
+ left_delta="108"
+ max_length="10"
+ name="parentestate"
+ tool_tip="This is the parent estate for this region"
+ top_delta="0"
+ width="50">
+ <line_editor.commit_callback
+ function="RegionTools.ChangeAnything" />
+ </line_editor>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="200"
+ name="Grid Pos: "
+ top_pad="4"
+ width="190">
+ Grid Pos:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="top|right"
+ height="16"
+ layout="topleft"
+ left_delta="88"
+ max_length="10"
+ name="gridposx"
+ tool_tip="This is the grid x position for this region"
+ top_delta="0"
+ width="50">
+ <line_editor.commit_callback
+ function="RegionTools.ChangeAnything" />
+ </line_editor>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="top|right"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ max_length="10"
+ name="gridposy"
+ tool_tip="This is the grid y position for this region"
+ top_delta="0"
+ width="40">
+ <line_editor.commit_callback
+ function="RegionTools.ChangeAnything" />
+ </line_editor>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="200"
+ name="Redirect to Grid: "
+ top_pad="4"
+ width="88">
+ Redirect to Grid:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="top|right"
+ height="16"
+ layout="topleft"
+ left_pad="0"
+ max_length="10"
+ name="redirectx"
+ width="50">
+ <line_editor.commit_callback
+ function="RegionTools.ChangeAnything" />
+ </line_editor>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="top|right"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ max_length="10"
+ name="redirecty"
+ top_delta="0"
+ width="40">
+ <line_editor.commit_callback
+ function="RegionTools.ChangeAnything" />
+ </line_editor>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="200"
+ name="billable factor text"
+ top_pad="10"
+ width="110">
+ Billable Factor:
+ </text>
+ <spinner
+ follows="top|right"
+ height="16"
+ initial_value="1"
+ layout="topleft"
+ max_val="4"
+ name="billable factor"
+ left_pad="0"
+ width="80">
+ <spinner.commit_callback
+ function="RegionTools.ChangeAnything" />
+ </spinner>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="200"
+ name="land cost text"
+ top_pad="10"
+ width="110">
+ L$ per m²:
+ </text>
+ <spinner
+ follows="top|right"
+ height="16"
+ increment="1"
+ initial_value="1"
+ layout="topleft"
+ left_pad="0"
+ max_val="100"
+ name="land cost"
+ width="80">
+ <spinner.commit_callback
+ function="RegionTools.ChangeAnything" />
+ </spinner>
+
+ <button
+ follows="top|right"
+ height="22"
+ label="Refresh"
+ label_selected="Refresh"
+ layout="topleft"
+ left="278"
+ name="Refresh"
+ tool_tip="Click here to refresh the above information"
+ top_pad="10"
+ width="110">
+ <button.commit_callback
+ function="RegionTools.Refresh" />
+ </button>
+ <button
+ follows="top|right"
+ height="22"
+ label="Apply"
+ label_selected="Apply"
+ layout="topleft"
+ left="278"
+ name="Apply"
+ tool_tip="Click here to apply any changes from above"
+ top="317"
+ width="110">
+ <button.commit_callback
+ function="RegionTools.ApplyChanges" />
+ </button>
+ <button
+ follows="top|right"
+ height="22"
+ label="Select Region"
+ label_selected="Select Region"
+ layout="topleft"
+ left="130"
+ name="Select Region"
+ tool_tip="Select the whole region with the land tool"
+ top="238"
+ width="110">
+ <button.commit_callback
+ function="RegionTools.SelectRegion" />
+ </button>
+ <button
+ follows="top|right"
+ height="22"
+ label="Autosave now"
+ label_selected="Autosave now"
+ layout="topleft"
+ left_delta="0"
+ name="Autosave now"
+ tool_tip="Save gzipped state to autosave directory"
+ top_pad="10"
+ width="110">
+ <button.commit_callback
+ function="RegionTools.SaveState" />
+ </button>
+ </panel>
+ <panel
+ border="true"
+ follows="left|top|right|bottom"
+ height="347"
+ label="Objects"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ help_topic="godtools_objects_tab"
+ name="objects"
+ top_delta="0"
+ width="398">
+ <panel.string
+ name="no_target">
+ (no target)
+ </panel.string>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="Sim Name:"
+ top="10"
+ width="80">
+ Sim Name:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="10"
+ name="region name"
+ top_delta="0"
+ width="320">
+ Welsh
+ </text>
+ <check_box
+ height="16"
+ label="Disable Scripts"
+ layout="topleft"
+ left="10"
+ name="disable scripts"
+ tool_tip="Set this to disable all scripts in this region"
+ top="30"
+ width="110">
+ <check_box.commit_callback
+ function="ObjectTools.ChangeAnything" />
+ </check_box>
+ <check_box
+ height="16"
+ label="Disable Collisions"
+ layout="topleft"
+ left_pad="10"
+ name="disable collisions"
+ tool_tip="Set this to disable non-agent collisions in this region"
+ top_delta="0"
+ width="121">
+ <check_box.commit_callback
+ function="ObjectTools.ChangeAnything" />
+ </check_box>
+ <check_box
+ height="16"
+ label="Disable Physics"
+ layout="topleft"
+ left_delta="120"
+ name="disable physics"
+ tool_tip="Set this to disable all physics in this region"
+ top_delta="0"
+ width="130">
+ <check_box.commit_callback
+ function="ObjectTools.ChangeAnything" />
+ </check_box>
+ <button
+ follows="top|right"
+ height="22"
+ label="Apply"
+ label_selected="Apply"
+ layout="topleft"
+ left="278"
+ name="Apply"
+ tool_tip="Click here to apply any changes from above"
+ top="54"
+ width="110">
+ <button.commit_callback
+ function="ObjectTools.ApplyChanges" />
+ </button>
+ <button
+ follows="top|right"
+ height="22"
+ label="Set Target"
+ label_selected="Set Target"
+ layout="topleft"
+ left="8"
+ name="Set Target"
+ tool_tip="Set the target avatar for object deletion"
+ top="78"
+ width="110">
+ <button.commit_callback
+ function="ObjectTools.Set" />
+ </button>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="12"
+ name="target_avatar_name"
+ top_delta="0"
+ width="260">
+ (no target)
+ </text>
+ <button
+ follows="top|right"
+ height="22"
+ label="Delete Target&apos;s Scripted Objects On Others Land"
+ label_selected="Delete Target&apos;s Scripted Objects On Others Land"
+ layout="topleft"
+ left="8"
+ name="Delete Target&apos;s Scripted Objects On Others Land"
+ tool_tip="Delete all scripted objects owned by the target on land not owned by the target. (no copy) objects will be returned."
+ top="126"
+ width="380">
+ <button.commit_callback
+ function="ObjectTools.DeletePublicOwnedBy" />
+ </button>
+ <button
+ follows="top|right"
+ height="22"
+ label="Delete Target&apos;s Scripted Objects On *Any* Land"
+ label_selected="Delete Target&apos;s Scripted Objects On *Any* Land"
+ layout="topleft"
+ left_delta="0"
+ name="Delete Target&apos;s Scripted Objects On *Any* Land"
+ tool_tip="Delete all scripted objects owned by the target in this region. (no copy) objects will be returned."
+ top_pad="28"
+ width="380">
+ <button.commit_callback
+ function="ObjectTools.DeleteAllScriptedOwnedBy" />
+ </button>
+ <button
+ follows="top|right"
+ height="22"
+ label="Delete *ALL* Of Target&apos;s Objects"
+ label_selected="Delete *ALL* Of Target&apos;s Objects"
+ layout="topleft"
+ left_delta="0"
+ name="Delete *ALL* Of Target&apos;s Objects"
+ tool_tip="Delete all objects owned by the target in this region. (no copy) objects will be returned."
+ top_pad="28"
+ width="380">
+ <button.commit_callback
+ function="ObjectTools.DeleteAllOwnedBy" />
+ </button>
+ <button
+ follows="top|right"
+ height="20"
+ label="Get Top Colliders"
+ label_selected="Get Top Colliders"
+ layout="topleft"
+ left="12"
+ name="Get Top Colliders"
+ tool_tip="Gets list of objects experiencing the most narrowphase callbacks"
+ top_pad="20"
+ width="130">
+ <button.commit_callback
+ function="ObjectTools.GetTopColliders" />
+ </button>
+ <button
+ follows="top|right"
+ height="20"
+ label="Get Top Scripts"
+ label_selected="Get Top Scripts"
+ layout="topleft"
+ left_delta="0"
+ name="Get Top Scripts"
+ tool_tip="Gets list of objects spending the most time running scripts"
+ top_pad="5"
+ width="130">
+ <button.commit_callback
+ function="ObjectTools.GetTopScripts" />
+ </button>
+ <button
+ follows="top|right"
+ height="20"
+ label="Scripts digest"
+ label_selected="Scripts digest"
+ layout="topleft"
+ left_delta="0"
+ name="Scripts digest"
+ tool_tip="Gets a list of all scripts and number of occurences of each"
+ top_pad="5"
+ width="130" >
+ <button.commit_callback
+ function="ObjectTools.GetScriptDigest" />
+ </button>
+ </panel>
+ <panel
+ border="true"
+ follows="left|top|right|bottom"
+ height="347"
+ label="Request"
+ layout="topleft"
+ left_delta="0"
+ help_topic="godtools_request_tab"
+ name="request"
+ top_delta="0"
+ width="398">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="10"
+ name="Destination:"
+ top="12"
+ width="80">
+ Destination:
+ </text>
+ <combo_box
+ height="22"
+ layout="topleft"
+ left_pad="10"
+ name="destination"
+ top_delta="0"
+ width="290">
+ <combo_box.item
+ label="Selection"
+ name="item1"
+ value="Selection" />
+ <combo_box.item
+ label="Agent Region"
+ name="item2"
+ value="Agent Region" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="10"
+ name="Request:"
+ top_pad="10"
+ width="80">
+ Request:
+ </text>
+ <combo_box
+ allow_text_entry="true"
+ height="22"
+ layout="topleft"
+ left_pad="10"
+ name="request"
+ top_delta="0"
+ width="290">
+ <combo_box.item
+ label="colliders &lt;steps&gt;"
+ name="item1"
+ value="colliders &lt;steps&gt;" />
+ <combo_box.item
+ label="scripts &lt;count&gt;,&lt;optional pattern&gt;"
+ name="item2"
+ value="scripts &lt;count&gt;,&lt;optional pattern&gt;" />
+ <combo_box.item
+ label="objects &lt;pattern&gt;"
+ name="item3"
+ value="objects &lt;pattern&gt;" />
+ <combo_box.item
+ label="rez &lt;asset_id&gt;"
+ name="item4"
+ value="rez &lt;asset_id&gt;" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="Parameter:"
+ top_pad="10"
+ width="80">
+ Parameter:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left_pad="10"
+ max_length="63"
+ name="parameter"
+ top_delta="0"
+ width="290" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Make Request"
+ label_selected="Make Request"
+ layout="topleft"
+ left="10"
+ name="Make Request"
+ top_pad="10"
+ width="140">
+ <button.commit_callback
+ function="GodTools.Request" />
+ </button>
+ </panel>
+ </tab_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml
new file mode 100644
index 0000000000..1e2440580e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="224"
+ layout="topleft"
+ name="Hardware Settings Floater"
+ help_topic="hardware_settings_floater"
+ title="HARDWARE SETTINGS"
+ width="500">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left="10"
+ name="Filtering:"
+ top="20"
+ width="128">
+ Filtering:
+ </text>
+ <check_box
+ control_name="RenderAnisotropic"
+ height="16"
+ label="Anisotropic Filtering (slower when enabled)"
+ layout="topleft"
+ left_pad="10"
+ name="ani"
+ top_delta="0"
+ width="256" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left="10"
+ name="Antialiasing:"
+ top_pad="7"
+ width="128">
+ Antialiasing:
+ </text>
+ <combo_box
+ control_name="RenderFSAASamples"
+ height="22"
+ initial_value="false"
+ label="Antialiasing"
+ layout="topleft"
+ left_pad="10"
+ name="fsaa"
+ top_delta="0"
+ width="130">
+ <combo_box.item
+ label="Disabled"
+ name="FSAADisabled"
+ value="0" />
+ <combo_box.item
+ label="2x"
+ name="2x"
+ value="2" />
+ <combo_box.item
+ label="4x"
+ name="4x"
+ value="4" />
+ <combo_box.item
+ label="8x"
+ name="8x"
+ value="8" />
+ <combo_box.item
+ label="16x"
+ name="16x"
+ value="16" />
+ </combo_box>
+ <spinner
+ control_name="RenderGamma"
+ decimal_digits="2"
+ follows="left|top"
+ height="16"
+ increment="0.01"
+ initial_value="1"
+ label="Gamma:"
+ label_width="138"
+ layout="topleft"
+ left="10"
+ max_val="2"
+ name="gamma"
+ top_pad="7"
+ width="202" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left_pad="10"
+ name="(brightness, lower is brighter)"
+ top_delta="2"
+ width="315">
+ (0 = default brightness, lower = brighter)
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="Enable VBO:"
+ top_pad="10"
+ width="128">
+ Enable VBO:
+ </text>
+ <check_box
+ control_name="RenderVBOEnable"
+ height="16"
+ initial_value="true"
+ label="Enable OpenGL Vertex Buffer Objects"
+ layout="topleft"
+ left_pad="10"
+ name="vbo"
+ tool_tip="Enabling this on modern hardware gives a performance gain. However, older hardware often has poor implementations of VBOs and you may get crashes when this is enabled."
+ width="315" />
+ <slider
+ control_name="TextureMemory"
+ decimal_digits="0"
+ follows="left|top"
+ height="20"
+ increment="16"
+ initial_value="32"
+ label="Texture Memory (MB):"
+ label_width="135"
+ layout="topleft"
+ left="10"
+ max_val="4096"
+ name="GraphicsCardTextureMemory"
+ tool_tip="Amount of memory to allocate for textures. Defaults to video card memory. Reducing this may improve performance but may also make textures blurry."
+ top_pad="10"
+ width="300" />
+ <spinner
+ control_name="RenderFogRatio"
+ decimal_digits="1"
+ follows="left|top"
+ height="22"
+ initial_value="4"
+ label="Fog Distance Ratio:"
+ label_width="138"
+ layout="topleft"
+ left_delta="0"
+ max_val="10"
+ min_val="0.5"
+ name="fog"
+ top_pad="7"
+ width="202" />
+ <button
+ follows="right|bottom"
+ height="22"
+ label="OK"
+ label_selected="OK"
+ layout="topleft"
+ left="-102"
+ name="OK"
+ top="192"
+ width="90" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_help_browser.xml b/indra/newview/skins/default/xui/en/floater_help_browser.xml
new file mode 100644
index 0000000000..e83bc1555c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_help_browser.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="480"
+ layout="topleft"
+ min_height="140"
+ min_width="467"
+ name="floater_help_browser"
+ help_topic="floater_help_browser"
+ save_rect="true"
+ single_instance="true"
+ title="HELP BROWSER"
+ width="620">
+ <floater.string
+ name="home_page_url">
+ http://www.secondlife.com
+ </floater.string>
+ <floater.string
+ name="support_page_url">
+ http://support.secondlife.com
+ </floater.string>
+ <layout_stack
+ bottom="480"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="10"
+ name="stack1"
+ top="20"
+ width="600">
+ <layout_panel
+ height="1"
+ layout="topleft"
+ left_delta="0"
+ name="external_controls"
+ top_delta="0"
+ user_resize="false"
+ width="590">
+ <web_browser
+ bottom="-4"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="0"
+ name="browser"
+ top="0"
+ width="590" />
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_hud.xml b/indra/newview/skins/default/xui/en/floater_hud.xml
new file mode 100644
index 0000000000..99a6a95828
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_hud.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ height="292"
+ layout="topleft"
+ name="floater_hud"
+ help_topic="floater_hud"
+ save_rect="true"
+ save_visibility="true"
+ title="TUTORIAL"
+ width="362">
+ <web_browser
+ border_visible="false"
+ caret_color="1 1 1 1"
+ follows="top|left|bottom|right"
+ height="265"
+ layout="topleft"
+ left="1"
+ name="floater_hud_browser"
+ start_url="data:text/html,%3Chtml%3E%3Chead%3E%3C/head%3E%3Cbody bgcolor=%22#000000%22 text=%22ffffff%22%3E%3Ch1%3E%3Ctt%3E%0D%0A%0D%0ALoading...%3C/tt%3E%3C/h1%3E%3C/body%3E%3C/html%3E"
+ top="26"
+ width="360" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_im.xml b/indra/newview/skins/default/xui/en/floater_im.xml
new file mode 100644
index 0000000000..a21242ffe1
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_im.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<multi_floater
+ legacy_header_height="18"
+ can_resize="true"
+ follows="left|bottom"
+ height="422"
+ layout="topleft"
+ min_height="130"
+ min_width="350"
+ name="im_floater"
+ help_topic="im_floater"
+ save_rect="true"
+ title="Instant Message"
+ width="419">
+ <multi_floater.string
+ name="only_user_message">
+ You are the only user in this session.
+ </multi_floater.string>
+ <multi_floater.string
+ name="offline_message">
+ [FIRST] [LAST] is offline.
+ </multi_floater.string>
+ <multi_floater.string
+ name="invite_message">
+ Click the [BUTTON NAME] button to accept/connect to this voice chat.
+ </multi_floater.string>
+ <multi_floater.string
+ name="muted_message">
+ You have blocked this Resident. Sending a message will automatically unblock them.
+ </multi_floater.string>
+ <multi_floater.string
+ name="generic_request_error">
+ Error making request, please try again later.
+ </multi_floater.string>
+ <multi_floater.string
+ name="insufficient_perms_error">
+ You do not have sufficient permissions.
+ </multi_floater.string>
+ <multi_floater.string
+ name="session_does_not_exist_error">
+ The session no longer exists
+ </multi_floater.string>
+ <multi_floater.string
+ name="no_ability_error">
+ You do not have that ability.
+ </multi_floater.string>
+ <multi_floater.string
+ name="not_a_mod_error">
+ You are not a session moderator.
+ </multi_floater.string>
+ <multi_floater.string
+ name="muted_error">
+ A group moderator disabled your text chat.
+ </multi_floater.string>
+ <multi_floater.string
+ name="add_session_event">
+ Unable to add users to chat session with [RECIPIENT].
+ </multi_floater.string>
+ <multi_floater.string
+ name="message_session_event">
+ Unable to send your message to the chat session with [RECIPIENT].
+ </multi_floater.string>
+ <multi_floater.string
+ name="removed_from_group">
+ You have been removed from the group.
+ </multi_floater.string>
+ <multi_floater.string
+ name="close_on_no_ability">
+ You no longer have the ability to be in the chat session.
+ </multi_floater.string>
+ <tab_container
+ follows="left|top|right|bottom"
+ height="406"
+ layout="topleft"
+ left="1"
+ name="Preview Tabs"
+ tab_position="bottom"
+ top="16"
+ width="417" />
+</multi_floater>
diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml
new file mode 100644
index 0000000000..bd25288a9e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_im_container.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<multi_floater
+ can_close="false"
+ can_minimize="true"
+ can_resize="true"
+ height="390"
+ layout="topleft"
+ name="floater_im_box"
+ help_topic="floater_im_box"
+ save_rect="true"
+ save_visibility="true"
+ single_instance="true"
+ title="CONVERSATIONS"
+ width="392">
+ <tab_container
+ follows="left|right|top|bottom"
+ height="390"
+ layout="topleft"
+ left="1"
+ name="im_box_tab_container"
+ tab_position="bottom"
+ tab_width="80"
+ tab_height="16"
+ top="0"
+ width="390" />
+ <icon
+ color="DefaultShadowLight"
+ enabled="false"
+ follows="left|right|bottom"
+ height="17"
+ image_name="tabarea.tga"
+ layout="bottomleft"
+ left="1"
+ name="im_box_tab_container_icon"
+ bottom="10"
+ width="390" />
+</multi_floater>
diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml
new file mode 100644
index 0000000000..d2e5473157
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_im_session.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ background_visible="true"
+ follows="all"
+ height="350"
+ layout="topleft"
+ left="0"
+ name="panel_im"
+ top="0"
+ can_dock="false"
+ can_minimize="true"
+ can_close="true"
+ visible="false"
+ width="360"
+ can_resize="true"
+ min_width="250"
+ min_height="190">
+ <layout_stack
+ animate="false"
+ follows="all"
+ height="320"
+ width="360"
+ layout="topleft"
+ orientation="horizontal"
+ name="im_panels"
+ top="20"
+ left="0">
+ <layout_panel
+ name="panel_im_control_panel"
+ layout="topleft"
+ follows="left"
+ label="IM Control Panel"
+ min_width="115"
+ auto_resize="false"
+ user_resize="true" />
+ <layout_panel
+ left="0"
+ top="0"
+ height="200"
+ width="245"
+ user_resize="true">
+ <button
+ height="20"
+ follows="left|top"
+ top="0"
+ left="2"
+ image_overlay="TabIcon_Open_Off"
+ layout="topleft"
+ width="25"
+ name="slide_left_btn" />
+ <button
+ height="20"
+ follows="left|top"
+ top="0"
+ left="2"
+ image_overlay="TabIcon_Close_Off"
+ width="25"
+ name="slide_right_btn" />
+ <chat_history
+ font="SansSerifSmall"
+ follows="left|right|top|bottom"
+ height="150"
+ name="chat_history"
+ parse_highlights="true"
+ allow_html="true"
+ left="1"
+ width="240">
+ </chat_history>
+ <line_editor
+ bottom="0"
+ follows="left|right|bottom"
+ font="SansSerifSmall"
+ height="20"
+ label="To"
+ layout="bottomleft"
+ name="chat_editor"
+ width="240">
+ </line_editor>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_image_preview.xml b/indra/newview/skins/default/xui/en/floater_image_preview.xml
new file mode 100644
index 0000000000..6f8f272128
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_image_preview.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ height="440"
+ layout="topleft"
+ name="Image Preview"
+ help_topic="image_preview"
+ width="300">
+ <text
+ type="string"
+ length="1"
+ bottom_delta="40"
+ follows="top|left"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="name_label">
+ Name:
+ </text>
+ <line_editor
+ follows="top|left|right"
+ height="19"
+ layout="topleft"
+ left_delta="0"
+ name="name_form"
+ top_pad="5"
+ width="280" />
+ <text
+ type="string"
+ length="1"
+ bottom_delta="20"
+ follows="top|left"
+ height="15"
+ layout="topleft"
+ name="description_label">
+ Description:
+ </text>
+ <line_editor
+ follows="top|left|right"
+ height="19"
+ layout="topleft"
+ left_delta="0"
+ name="description_form"
+ top_pad="5"
+ width="280" />
+ <text
+ type="string"
+ length="1"
+ bottom_delta="30"
+ follows="top|left"
+ height="25"
+ width="105"
+ word_wrap="true"
+ layout="topleft"
+ name="preview_label">
+ Preview image as:
+ </text>
+ <combo_box
+ height="18"
+ label="Clothing Type"
+ layout="topleft"
+ left_delta="110"
+ name="clothing_type_combo"
+ top_delta="3"
+ width="160">
+ <combo_box.item
+ label="Image"
+ name="Image" />
+ <combo_box.item
+ label="Hair"
+ name="Hair" />
+ <combo_box.item
+ label="Female Head"
+ name="FemaleHead" />
+ <combo_box.item
+ label="Female Upper Body"
+ name="FemaleUpperBody" />
+ <combo_box.item
+ label="Female Lower Body"
+ name="FemaleLowerBody" />
+ <combo_box.item
+ label="Male Head"
+ name="MaleHead" />
+ <combo_box.item
+ label="Male Upper Body"
+ name="MaleUpperBody" />
+ <combo_box.item
+ label="Male Lower Body"
+ name="MaleLowerBody" />
+ <combo_box.item
+ label="Skirt"
+ name="Skirt" />
+ <combo_box.item
+ label="Sculpted Prim"
+ name="SculptedPrim" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ bottom="225"
+ height="45"
+ word_wrap="true"
+ follows="top|left"
+ layout="topleft"
+ left="10"
+ name="bad_image_text">
+ Unable to read image.
+
+Try saving image as 24 bit Targa (.tga).
+ </text>
+ <check_box
+ control_name="LosslessJ2CUpload"
+ enabled="false"
+ follows="bottom|left"
+ height="16"
+ label="Use lossless compression"
+ layout="topleft"
+ left_delta="2"
+ name="lossless_check"
+ top_pad="162"
+ width="280" />
+ <button
+ follows="bottom|right"
+ height="20"
+ label="Cancel"
+ layout="topleft"
+ left="165"
+ name="cancel_btn"
+ top="410"
+ width="125" />
+ <button
+ follows="bottom|left"
+ height="20"
+ label="Upload (L$[AMOUNT])"
+ layout="topleft"
+ left_delta="-150"
+ name="ok_btn"
+ top_delta="0"
+ width="125" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_incoming_call.xml b/indra/newview/skins/default/xui/en/floater_incoming_call.xml
new file mode 100644
index 0000000000..1d67123726
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_close="false"
+ can_minimize="false"
+ can_tear_off="false"
+ height="125"
+ layout="topleft"
+ name="incoming call"
+ help_topic="incoming_call"
+ title="UNKNOWN PERSON IS CALLING"
+ width="410">
+ <floater.string
+ name="lifetime">
+ 5
+ </floater.string>
+ <floater.string
+ name="localchat">
+ Nearby Voice Chat
+ </floater.string>
+ <floater.string
+ name="anonymous">
+ anonymous
+ </floater.string>
+ <floater.string
+ name="VoiceInviteP2P">
+ is calling.
+ </floater.string>
+ <floater.string
+ name="VoiceInviteAdHoc">
+ has joined a Voice Chat call with a conference chat.
+ </floater.string>
+ <floater.string
+ name="VoiceInviteGroup">
+ has joined a Voice Chat call with the group [GROUP].
+ </floater.string>
+ <avatar_icon
+ enabled="false"
+ follows="left|top"
+ height="36"
+ image_name="icon_avatar_online.tga"
+ layout="topleft"
+ left_delta="19"
+ top="35"
+ width="36" />
+ <group_icon
+ enabled="false"
+ follows="left|top"
+ height="36"
+ layout="topleft"
+ top="35"
+ width="36" />
+ <text
+ clip_partial="true"
+ font="SansSerifLarge"
+ height="37"
+ layout="topleft"
+ left="77"
+ name="caller name"
+ top="20"
+ use_ellipses="true"
+ width="315"
+ word_wrap="true" />
+ <text
+ clip_partial="true"
+ font="SansSerif"
+ height="30"
+ layout="topleft"
+ left="77"
+ name="question"
+ top_pad="5"
+ use_ellipses="true"
+ width="315"
+ word_wrap="true">
+ Do you want to leave [CURRENT_CHAT] and join this voice chat?
+ </text>
+ <button
+ height="24"
+ label="Accept"
+ label_selected="Accept"
+ layout="topleft"
+ left="70"
+ name="Accept"
+ top="92"
+ width="100" />
+ <button
+ height="24"
+ label="Reject"
+ label_selected="Reject"
+ layout="topleft"
+ name="Reject"
+ left_pad="10"
+ width="100" />
+ <button
+ height="24"
+ label="Start IM"
+ layout="topleft"
+ name="Start IM"
+ left_pad="10"
+ width="100" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_inspect.xml b/indra/newview/skins/default/xui/en/floater_inspect.xml
new file mode 100644
index 0000000000..3f7642fafe
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_inspect.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="300"
+ layout="topleft"
+ min_height="300"
+ min_width="400"
+ name="inspect"
+ help_topic="inspect"
+ save_rect="true"
+ title="INSPECT OBJECTS"
+ width="400">
+ <floater.string
+ name="timeStamp">
+ [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+ </floater.string>
+ <scroll_list
+ bottom="270"
+ column_padding="0"
+ draw_heading="true"
+ follows="top|right|left|bottom"
+ layout="topleft"
+ left="10"
+ name="object_list"
+ right="-10"
+ tool_tip="Select an object from this list to highlight it in-world"
+ top="20">
+ <scroll_list.columns
+ dynamic_width="true"
+ label="Object Name"
+ name="object_name" />
+ <scroll_list.columns
+ dynamic_width="true"
+ label="Owner Name"
+ name="owner_name" />
+ <scroll_list.columns
+ dynamic_width="true"
+ label="Creator Name"
+ name="creator_name" />
+ <scroll_list.columns
+ label="Creation Date"
+ name="creation_date"
+ width="150" />
+ <scroll_list.commit_callback
+ function="Inspect.SelectObject" />
+ </scroll_list>
+ <button
+ follows="left|bottom"
+ height="20"
+ label="See Owner Profile..."
+ layout="topleft"
+ left_delta="0"
+ name="button owner"
+ tool_tip="See profile of the highlighted object&apos;s owner"
+ top_pad="5"
+ width="150">
+ <button.commit_callback
+ function="Inspect.OwnerProfile" />
+ </button>
+ <button
+ follows="left|bottom"
+ height="20"
+ label="See Creator Profile..."
+ layout="topleft"
+ left_pad="10"
+ name="button creator"
+ tool_tip="See profile of the highlighted object&apos;s original creator"
+ top_delta="0"
+ width="150">
+ <button.commit_callback
+ function="Inspect.CreatorProfile" />
+ </button>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_inventory.xml b/indra/newview/skins/default/xui/en/floater_inventory.xml
new file mode 100644
index 0000000000..ff9f0daee6
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_inventory.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ auto_tile="true"
+ can_resize="true"
+ height="563"
+ layout="topleft"
+ min_height="150"
+ min_width="240"
+ name="Inventory"
+ help_topic="inventory"
+ save_rect="true"
+ save_visibility="true"
+ single_instance="false"
+ title="INVENTORY"
+ width="467">
+ <floater.string
+ name="Title">
+ Inventory
+ </floater.string>
+ <floater.string
+ name="TitleFetching">
+ Inventory (Fetching [ITEM_COUNT] Items...) [FILTER]
+ </floater.string>
+ <floater.string
+ name="TitleCompleted">
+ Inventory ([ITEM_COUNT] Items) [FILTER]
+ </floater.string>
+ <floater.string
+ name="Fetched">
+ Fetched
+ </floater.string>
+ <panel
+ bottom="560"
+ class="panel_main_inventory"
+ filename="panel_main_inventory.xml"
+ follows="all"
+ layout="topleft"
+ left="0"
+ label="Inventory Panel"
+ name="Inventory Panel"
+ top="15"
+ width="467" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml
new file mode 100644
index 0000000000..366098013b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml
@@ -0,0 +1,468 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ auto_tile="true"
+ height="340"
+ layout="topleft"
+ name="item properties"
+ help_topic="item_properties"
+ save_rect="true"
+ title="INVENTORY ITEM PROPERTIES"
+ width="350">
+ <floater.string
+ name="unknown">
+ (unknown)
+ </floater.string>
+ <floater.string
+ name="public">
+ (public)
+ </floater.string>
+ <floater.string
+ name="you_can">
+ You can:
+ </floater.string>
+ <floater.string
+ name="owner_can">
+ Owner can:
+ </floater.string>
+ <floater.string
+ name="acquiredDate">
+ [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+ </floater.string>
+ <icon
+ follows="top|right"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ left="276"
+ mouse_opaque="true"
+ name="IconLocked"
+ top="4"
+ width="18" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="LabelItemNameTitle"
+ top="25"
+ width="78">
+ Name:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_delta="78"
+ max_length="63"
+ name="LabelItemName"
+ top_delta="0"
+ width="252" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="LabelItemDescTitle"
+ top="45"
+ width="78">
+ Description:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_delta="78"
+ max_length="127"
+ name="LabelItemDesc"
+ top_delta="0"
+ width="252" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="LabelCreatorTitle"
+ top="65"
+ width="78">
+ Creator:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="78"
+ name="LabelCreatorName"
+ top_delta="0"
+ width="170">
+ Nicole Linden
+ </text>
+ <button
+ follows="top|right"
+ height="16"
+ label="Profile..."
+ layout="topleft"
+ left_delta="174"
+ name="BtnCreator"
+ top_delta="0"
+ width="78" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="LabelOwnerTitle"
+ top="85"
+ width="78">
+ Owner:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="78"
+ name="LabelOwnerName"
+ top_delta="0"
+ width="170">
+ Thrax Linden
+ </text>
+ <button
+ follows="top|right"
+ height="16"
+ label="Profile..."
+ layout="topleft"
+ left_delta="174"
+ name="BtnOwner"
+ top_delta="0"
+ width="78" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="LabelAcquiredTitle"
+ top="105"
+ width="78">
+ Acquired:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="78"
+ name="LabelAcquiredDate"
+ top_delta="0"
+ width="252">
+ Wed May 24 12:50:46 2006
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="OwnerLabel"
+ top="125"
+ width="78">
+ You:
+ </text>
+ <check_box
+ height="16"
+ label="Edit"
+ layout="topleft"
+ left_pad="5"
+ name="CheckOwnerModify"
+ top_delta="0"
+ width="78" />
+ <check_box
+ height="16"
+ label="Copy"
+ layout="topleft"
+ left_delta="0"
+ name="CheckOwnerCopy"
+ top_pad="5"
+ width="88" />
+ <check_box
+ height="16"
+ label="Resell"
+ layout="topleft"
+ left_delta="0"
+ name="CheckOwnerTransfer"
+ top_pad="5"
+ width="106" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="AnyoneLabel"
+ top_pad="5"
+ width="78">
+ Anyone:
+ </text>
+ <check_box
+ height="16"
+ label="Copy"
+ layout="topleft"
+ left_pad="5"
+ name="CheckEveryoneCopy"
+ top_delta="0"
+ width="130" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="GroupLabel"
+ top_pad="5"
+ width="78">
+ Group:
+ </text>
+ <check_box
+ height="16"
+ label="Share"
+ layout="topleft"
+ left_pad="5"
+ name="CheckShareWithGroup"
+ top_delta="5"
+ width="106" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left="10"
+ name="NextOwnerLabel"
+ top_pad="5"
+ width="78"
+ word_wrap="true">
+ Next owner:
+ </text>
+ <check_box
+ height="16"
+ label="Edit"
+ layout="topleft"
+ left_pad="5"
+ name="CheckNextOwnerModify"
+ top_delta="0"
+ width="78" />
+ <check_box
+ height="16"
+ label="Copy"
+ layout="topleft"
+ left_delta="0"
+ name="CheckNextOwnerCopy"
+ top_pad="5"
+ width="88" />
+ <check_box
+ height="16"
+ label="Resell"
+ layout="topleft"
+ left_delta="0"
+ name="CheckNextOwnerTransfer"
+ top_pad="5"
+ width="106" />
+ <check_box
+ height="16"
+ label="For Sale"
+ layout="topleft"
+ left="10"
+ name="CheckPurchase"
+ top_pad="5"
+ width="78" />
+ <combo_box
+ height="19"
+ left_pad="5"
+ layout="topleft"
+ follows="left|top"
+ name="combobox sale copy"
+ width="110">
+ <combo_box.item
+ label="Copy"
+ name="Copy"
+ value="Copy" />
+ <combo_box.item
+ label="Original"
+ name="Original"
+ value="Original" />
+ </combo_box>
+ <spinner
+ follows="left|top"
+ decimal_digits="0"
+ increment="1"
+ control_name="Edit Cost"
+ name="Edit Cost"
+ label="Price:"
+ label_width="100"
+ left="10"
+ width="192"
+ min_val="1"
+ height="19"
+ max_val="999999999"
+ top_pad="5"/>
+ <text
+ type="string"
+ length="1"
+ height="15"
+ follows="left|top"
+ layout="topleft"
+ left_delta="82"
+ name="CurrencySymbol"
+ top_delta="1"
+ width="18">
+ L$
+ </text>
+
+ <!--line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_pad="5"
+ max_length="25"
+ name="EditPrice"
+ top_delta="0"
+ width="242" /-->
+
+ <!--text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="BaseMaskDebug"
+ top="155"
+ width="330">
+ B:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="60"
+ name="OwnerMaskDebug"
+ top_delta="0"
+ width="270">
+ O:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="60"
+ name="GroupMaskDebug"
+ top_delta="0"
+ width="210">
+ G:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="60"
+ name="EveryoneMaskDebug"
+ top_delta="0"
+ width="150">
+ E:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="60"
+ name="NextMaskDebug"
+ top_delta="0"
+ width="90">
+ N:
+ </text-->
+ <!--text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="SaleLabel"
+ top_pad="5"
+ width="330">
+ Mark Item:
+ </text-->
+
+
+ <!--radio_group
+ draw_border="false"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_delta="78"
+ name="RadioSaleType"
+ top_delta="0"
+ width="252">
+ <radio_item
+ height="16"
+ label="Original"
+ layout="topleft"
+ left="0"
+ name="radio"
+ top="0"
+ width="70" />
+ <radio_item
+ height="16"
+ label="Copy"
+ layout="topleft"
+ left_delta="60"
+ name="radio2"
+ top_delta="0"
+ width="70" />
+ </radio_group-->
+
+ <!--text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="TextPrice"
+ top_pad="5"
+ width="78">
+ Price: L$
+ </text-->
+
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml
new file mode 100644
index 0000000000..90fee857fb
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml
@@ -0,0 +1,283 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ height="408"
+ layout="topleft"
+ name="Inventory Finder"
+ help_topic="inventory_finder"
+ title="INVENTORY_RECENT_ITEMS"
+ width="280">
+ <icon
+ height="16"
+ image_name="Inv_Animation"
+ layout="topleft"
+ left="8"
+ mouse_opaque="true"
+ name="icon_animation"
+ top="22"
+ width="16" />
+ <check_box
+ height="16"
+ label="Animation"
+ layout="topleft"
+ left_pad="2"
+ name="check_animation"
+ top_delta="0"
+ width="126" />
+ <icon
+ height="16"
+ image_name="Inv_CallingCard"
+ layout="topleft"
+ left="8"
+ mouse_opaque="true"
+ name="icon_calling_card"
+ top="42"
+ width="16" />
+ <check_box
+ height="16"
+ label="Calling Cards"
+ layout="topleft"
+ left_pad="2"
+ name="check_calling_card"
+ top_delta="0"
+ width="126" />
+ <icon
+ height="16"
+ image_name="Inv_Shirt"
+ layout="topleft"
+ left="8"
+ mouse_opaque="true"
+ name="icon_clothing"
+ top="62"
+ width="16" />
+ <check_box
+ height="16"
+ label="Clothing"
+ layout="topleft"
+ left_pad="2"
+ name="check_clothing"
+ top_delta="0"
+ width="126" />
+ <icon
+ height="16"
+ image_name="Inv_Gesture"
+ layout="topleft"
+ left="8"
+ mouse_opaque="true"
+ name="icon_gesture"
+ top="82"
+ width="16" />
+ <check_box
+ height="16"
+ label="Gestures"
+ layout="topleft"
+ left_pad="2"
+ name="check_gesture"
+ top_delta="0"
+ width="126" />
+ <icon
+ height="16"
+ image_name="Inv_Landmark"
+ layout="topleft"
+ left="8"
+ mouse_opaque="true"
+ name="icon_landmark"
+ top="102"
+ width="16" />
+ <check_box
+ height="16"
+ label="Landmarks"
+ layout="topleft"
+ left_pad="2"
+ name="check_landmark"
+ top_delta="0"
+ width="126" />
+ <icon
+ height="16"
+ image_name="Inv_Notecard"
+ layout="topleft"
+ left="8"
+ mouse_opaque="true"
+ name="icon_notecard"
+ top="122"
+ width="16" />
+ <check_box
+ height="16"
+ label="Notecards"
+ layout="topleft"
+ left_pad="2"
+ name="check_notecard"
+ top_delta="0"
+ width="126" />
+ <icon
+ height="16"
+ image_name="Inv_Object"
+ layout="topleft"
+ left="8"
+ mouse_opaque="true"
+ name="icon_object"
+ top="142"
+ width="16" />
+ <check_box
+ height="16"
+ label="Objects"
+ layout="topleft"
+ left_pad="2"
+ name="check_object"
+ top_delta="0"
+ width="126" />
+ <icon
+ height="16"
+ image_name="Inv_Script"
+ layout="topleft"
+ left="8"
+ mouse_opaque="true"
+ name="icon_script"
+ top="162"
+ width="16" />
+ <check_box
+ height="16"
+ label="Scripts"
+ layout="topleft"
+ left_pad="2"
+ name="check_script"
+ top_delta="0"
+ width="126" />
+ <icon
+ height="16"
+ image_name="Inv_Sound"
+ layout="topleft"
+ left="8"
+ mouse_opaque="true"
+ name="icon_sound"
+ top="182"
+ width="16" />
+ <check_box
+ height="16"
+ label="Sounds"
+ layout="topleft"
+ left_pad="2"
+ name="check_sound"
+ top_delta="0"
+ width="126" />
+ <icon
+ height="16"
+ image_name="Inv_Texture"
+ layout="topleft"
+ left="8"
+ mouse_opaque="true"
+ name="icon_texture"
+ top="202"
+ width="16" />
+ <check_box
+ height="16"
+ label="Textures"
+ layout="topleft"
+ left_pad="2"
+ name="check_texture"
+ top_delta="0"
+ width="126" />
+ <icon
+ height="16"
+ image_name="Inv_Snapshot"
+ layout="topleft"
+ left="8"
+ mouse_opaque="true"
+ name="icon_snapshot"
+ top="222"
+ width="16" />
+ <check_box
+ height="16"
+ label="Snapshots"
+ layout="topleft"
+ left_pad="2"
+ name="check_snapshot"
+ top_delta="0"
+ width="126" />
+ <button
+ follows="left|top"
+ height="20"
+ label="All"
+ label_selected="All"
+ layout="topleft"
+ left="8"
+ name="All"
+ top="242"
+ width="100" />
+ <button
+ follows="left|top"
+ height="20"
+ label="None"
+ label_selected="None"
+ layout="topleft"
+ left_delta="0"
+ name="None"
+ top_pad="4"
+ width="100" />
+ <check_box
+ height="16"
+ label="Always show folders"
+ layout="topleft"
+ left_delta="0"
+ name="check_show_empty"
+ top_pad="4"
+ width="144" />
+ <check_box
+ height="16"
+ label="Since Logoff"
+ layout="topleft"
+ left_delta="0"
+ name="check_since_logoff"
+ top_pad="4"
+ width="144" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ halign="center"
+ height="12"
+ layout="topleft"
+ left_delta="0"
+ name="- OR -"
+ top_delta="16"
+ width="144">
+ - OR -
+ </text>
+ <spinner
+ follows="left|top"
+ height="16"
+ increment="1"
+ initial_value="0"
+ label="Hours Ago"
+ label_width="64"
+ layout="topleft"
+ left_delta="0"
+ max_val="240000"
+ name="spin_hours_ago"
+ top_pad="4"
+ width="144" />
+ <spinner
+ follows="left|top"
+ height="16"
+ increment="1"
+ initial_value="0"
+ label="Days Ago"
+ label_width="64"
+ layout="topleft"
+ left_delta="0"
+ max_val="10000"
+ name="spin_days_ago"
+ top_pad="4"
+ width="144" />
+ <button
+ follows="top|right"
+ height="20"
+ label="Close"
+ label_selected="Close"
+ layout="topleft"
+ name="Close"
+ right="-6"
+ top="382"
+ width="76" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_joystick.xml b/indra/newview/skins/default/xui/en/floater_joystick.xml
new file mode 100644
index 0000000000..4d67e4c343
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_joystick.xml
@@ -0,0 +1,864 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="500"
+ layout="topleft"
+ name="Joystick"
+ help_topic="joystick"
+ title="JOYSTICK CONFIGURATION"
+ width="550">
+ <floater.string
+ name="NoDevice">
+ no device detected
+ </floater.string>
+ <check_box
+ bottom="38"
+ control_name="JoystickEnabled"
+ halign="left"
+ label="Enable Joystick:"
+ layout="topleft"
+ left="14"
+ name="enable_joystick"
+ width="60" />
+ <text
+ bottom="32"
+ layout="topleft"
+ left="120"
+ name="joystick_type"
+ width="380" />
+ <spinner
+ bottom="48"
+ control_name="JoystickAxis1"
+ decimal_digits="0"
+ increment="1"
+ label="X Axis Mapping"
+ label_width="100"
+ layout="topleft"
+ left="20"
+ max_val="5"
+ min_val="-1"
+ name="JoystickAxis1"
+ width="140" />
+ <spinner
+ bottom="48"
+ control_name="JoystickAxis2"
+ decimal_digits="0"
+ increment="1"
+ label="Y Axis Mapping"
+ label_width="100"
+ layout="topleft"
+ left="190"
+ max_val="5"
+ min_val="-1"
+ name="JoystickAxis2"
+ width="140" />
+ <spinner
+ bottom="48"
+ control_name="JoystickAxis0"
+ decimal_digits="0"
+ increment="1"
+ label="Z Axis Mapping"
+ label_width="100"
+ layout="topleft"
+ left="360"
+ max_val="5"
+ min_val="-1"
+ name="JoystickAxis0"
+ width="140" />
+ <spinner
+ bottom="68"
+ control_name="JoystickAxis4"
+ decimal_digits="0"
+ increment="1"
+ label="Pitch Mapping"
+ label_width="100"
+ layout="topleft"
+ left="20"
+ max_val="5"
+ min_val="-1"
+ name="JoystickAxis4"
+ width="140" />
+ <spinner
+ bottom="68"
+ control_name="JoystickAxis5"
+ decimal_digits="0"
+ increment="1"
+ label="Yaw Mapping"
+ label_width="100"
+ layout="topleft"
+ left="190"
+ max_val="5"
+ min_val="-1"
+ name="JoystickAxis5"
+ width="140" />
+ <spinner
+ bottom="68"
+ control_name="JoystickAxis3"
+ decimal_digits="0"
+ increment="1"
+ label="Roll Mapping"
+ label_width="100"
+ layout="topleft"
+ left="360"
+ max_val="5"
+ min_val="-1"
+ name="JoystickAxis3"
+ width="140" />
+ <spinner
+ bottom="88"
+ control_name="JoystickAxis6"
+ decimal_digits="0"
+ increment="1"
+ label="Zoom Mapping"
+ label_width="100"
+ layout="topleft"
+ left="20"
+ max_val="5"
+ min_val="-1"
+ name="JoystickAxis6"
+ width="140" />
+ <check_box
+ bottom_delta="18"
+ control_name="ZoomDirect"
+ label="Direct Zoom"
+ layout="topleft"
+ left="185"
+ name="ZoomDirect"
+ width="60" />
+ <check_box
+ bottom_delta="0"
+ control_name="Cursor3D"
+ label="3D Cursor"
+ layout="topleft"
+ left="310"
+ name="Cursor3D"
+ width="60" />
+ <check_box
+ bottom_delta="0"
+ control_name="AutoLeveling"
+ label="Auto Level"
+ layout="topleft"
+ left="420"
+ name="AutoLeveling"
+ width="60" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ halign="right"
+ height="10"
+ layout="topleft"
+ left="12"
+ mouse_opaque="false"
+ name="Control Modes:"
+ top="110"
+ width="102">
+ Control Modes:
+ </text>
+ <check_box
+ bottom="127"
+ control_name="JoystickAvatarEnabled"
+ halign="center"
+ label="Avatar"
+ layout="topleft"
+ left="125"
+ name="JoystickAvatarEnabled"
+ width="60" />
+ <check_box
+ bottom="127"
+ control_name="JoystickBuildEnabled"
+ halign="center"
+ label="Build"
+ layout="topleft"
+ left="194"
+ name="JoystickBuildEnabled"
+ width="60" />
+ <check_box
+ bottom="127"
+ control_name="JoystickFlycamEnabled"
+ halign="center"
+ label="Flycam"
+ layout="topleft"
+ left="262"
+ name="JoystickFlycamEnabled"
+ width="60" />
+ <stat_view
+ height="250"
+ label="Joystick Monitor"
+ layout="topleft"
+ left="340"
+ name="axis_view"
+ show_label="true"
+ top="142"
+ width="200">
+ <stat_bar
+ bar_max="2"
+ bar_min="-2"
+ height="0"
+ label="Axis 0"
+ label_spacing="1"
+ layout="topleft"
+ left="0"
+ name="axis0"
+ tick_spacing="0.5"
+ top="20"
+ width="0" />
+ <stat_bar
+ bar_max="2"
+ bar_min="-2"
+ label="Axis 1"
+ label_spacing="1"
+ layout="topleft"
+ name="axis1"
+ tick_spacing="0.5" />
+ <stat_bar
+ bar_max="2"
+ bar_min="-2"
+ label="Axis 2"
+ label_spacing="1"
+ layout="topleft"
+ name="axis2"
+ tick_spacing="0.5" />
+ <stat_bar
+ bar_max="2"
+ bar_min="-2"
+ label="Axis 3"
+ label_spacing="1"
+ layout="topleft"
+ name="axis3"
+ tick_spacing="0.5" />
+ <stat_bar
+ bar_max="2"
+ bar_min="-2"
+ label="Axis 4"
+ label_spacing="1"
+ layout="topleft"
+ name="axis4"
+ tick_spacing="0.5" />
+ <stat_bar
+ bar_max="2"
+ bar_min="-2"
+ label="Axis 5"
+ label_spacing="1"
+ layout="topleft"
+ name="axis5"
+ tick_spacing="0.5" />
+ </stat_view>
+ <text
+ type="string"
+ length="1"
+ bottom="144"
+ halign="right"
+ layout="topleft"
+ left="20"
+ name="XScale"
+ width="94">
+ X Scale
+ </text>
+ <spinner
+ bottom="144"
+ control_name="AvatarAxisScale1"
+ decimal_digits="2"
+ label_width="0"
+ layout="topleft"
+ left="125"
+ max_val="50"
+ min_val="-50"
+ name="AvatarAxisScale1"
+ width="56" />
+ <spinner
+ bottom="144"
+ control_name="BuildAxisScale1"
+ decimal_digits="2"
+ label_width="0"
+ layout="topleft"
+ left="195"
+ max_val="1024"
+ min_val="-1024"
+ name="BuildAxisScale1"
+ width="56" />
+ <spinner
+ bottom="144"
+ control_name="FlycamAxisScale1"
+ decimal_digits="2"
+ label_width="0"
+ layout="topleft"
+ left="265"
+ max_val="1024"
+ min_val="-1024"
+ name="FlycamAxisScale1"
+ width="56" />
+ <text
+ type="string"
+ length="1"
+ bottom="164"
+ halign="right"
+ layout="topleft"
+ left="20"
+ name="YScale"
+ width="94">
+ Y Scale
+ </text>
+ <spinner
+ bottom="164"
+ control_name="AvatarAxisScale2"
+ decimal_digits="2"
+ label_width="0"
+ layout="topleft"
+ left="125"
+ max_val="50"
+ min_val="-50"
+ name="AvatarAxisScale2"
+ width="56" />
+ <spinner
+ bottom="164"
+ control_name="BuildAxisScale2"
+ decimal_digits="2"
+ label_width="0"
+ layout="topleft"
+ left="195"
+ max_val="1024"
+ min_val="-1024"
+ name="BuildAxisScale2"
+ width="56" />
+ <spinner
+ bottom="164"
+ control_name="FlycamAxisScale2"
+ decimal_digits="2"
+ label_width="0"
+ layout="topleft"
+ left="265"
+ max_val="1024"
+ min_val="-1024"
+ name="FlycamAxisScale2"
+ width="56" />
+ <text
+ type="string"
+ length="1"
+ bottom="184"
+ halign="right"
+ layout="topleft"
+ left="20"
+ name="ZScale"
+ width="94">
+ Z Scale
+ </text>
+ <spinner
+ bottom="184"
+ control_name="AvatarAxisScale0"
+ decimal_digits="2"
+ label_width="0"
+ layout="topleft"
+ left="125"
+ max_val="50"
+ min_val="-50"
+ name="AvatarAxisScale0"
+ width="56" />
+ <spinner
+ bottom="184"
+ control_name="BuildAxisScale0"
+ decimal_digits="2"
+ label_width="0"
+ layout="topleft"
+ left="195"
+ max_val="1024"
+ min_val="-1024"
+ name="BuildAxisScale0"
+ width="56" />
+ <spinner
+ bottom="184"
+ control_name="FlycamAxisScale0"
+ decimal_digits="2"
+ label_width="0"
+ layout="topleft"
+ left="265"
+ max_val="1024"
+ min_val="-1024"
+ name="FlycamAxisScale0"
+ width="56" />
+ <text
+ type="string"
+ length="1"
+ bottom="204"
+ halign="right"
+ layout="topleft"
+ left="20"
+ name="PitchScale"
+ width="94">
+ Pitch Scale
+ </text>
+ <spinner
+ bottom="204"
+ control_name="AvatarAxisScale4"
+ decimal_digits="2"
+ label_width="0"
+ layout="topleft"
+ left="125"
+ max_val="1024"
+ min_val="-1024"
+ name="AvatarAxisScale4"
+ width="56" />
+ <spinner
+ bottom="204"
+ control_name="BuildAxisScale4"
+ decimal_digits="2"
+ label_width="0"
+ layout="topleft"
+ left="195"
+ max_val="1024"
+ min_val="-1024"
+ name="BuildAxisScale4"
+ width="56" />
+ <spinner
+ bottom="204"
+ control_name="FlycamAxisScale4"
+ decimal_digits="2"
+ label_width="0"
+ layout="topleft"
+ left="265"
+ max_val="1024"
+ min_val="-1024"
+ name="FlycamAxisScale4"
+ width="56" />
+ <text
+ type="string"
+ length="1"
+ bottom="224"
+ halign="right"
+ layout="topleft"
+ left="20"
+ name="YawScale"
+ width="94">
+ Yaw Scale
+ </text>
+ <spinner
+ bottom="224"
+ control_name="AvatarAxisScale5"
+ decimal_digits="2"
+ label_width="0"
+ layout="topleft"
+ left="125"
+ max_val="1024"
+ min_val="-1024"
+ name="AvatarAxisScale5"
+ width="56" />
+ <spinner
+ bottom="224"
+ control_name="BuildAxisScale5"
+ decimal_digits="2"
+ label_width="0"
+ layout="topleft"
+ left="195"
+ max_val="1024"
+ min_val="-1024"
+ name="BuildAxisScale5"
+ width="56" />
+ <spinner
+ bottom="224"
+ control_name="FlycamAxisScale5"
+ decimal_digits="2"
+ label_width="0"
+ layout="topleft"
+ left="265"
+ max_val="1024"
+ min_val="-1024"
+ name="FlycamAxisScale5"
+ width="56" />
+ <text
+ type="string"
+ length="1"
+ bottom="244"
+ halign="right"
+ layout="topleft"
+ left="20"
+ name="RollScale"
+ width="94">
+ Roll Scale
+ </text>
+ <spinner
+ bottom="244"
+ control_name="BuildAxisScale3"
+ decimal_digits="2"
+ label_width="0"
+ layout="topleft"
+ left="195"
+ max_val="1024"
+ min_val="-1024"
+ name="BuildAxisScale3"
+ width="56" />
+ <spinner
+ bottom="244"
+ control_name="FlycamAxisScale3"
+ decimal_digits="2"
+ label_width="0"
+ layout="topleft"
+ left="265"
+ max_val="1024"
+ min_val="-1024"
+ name="FlycamAxisScale3"
+ width="56" />
+ <text
+ type="string"
+ length="1"
+ bottom="274"
+ halign="right"
+ layout="topleft"
+ left="20"
+ name="XDeadZone"
+ width="94">
+ X Dead Zone
+ </text>
+ <spinner
+ bottom="274"
+ control_name="AvatarAxisDeadZone1"
+ decimal_digits="2"
+ increment="0.01"
+ label_width="0"
+ layout="topleft"
+ left="125"
+ name="AvatarAxisDeadZone1"
+ width="56" />
+ <spinner
+ bottom="274"
+ control_name="BuildAxisDeadZone1"
+ decimal_digits="2"
+ increment="0.01"
+ label_width="0"
+ layout="topleft"
+ left="195"
+ name="BuildAxisDeadZone1"
+ width="56" />
+ <spinner
+ bottom="274"
+ control_name="FlycamAxisDeadZone1"
+ decimal_digits="2"
+ increment="0.01"
+ label_width="0"
+ layout="topleft"
+ left="265"
+ name="FlycamAxisDeadZone1"
+ width="56" />
+ <text
+ type="string"
+ length="1"
+ bottom="294"
+ halign="right"
+ layout="topleft"
+ left="20"
+ name="YDeadZone"
+ width="94">
+ Y Dead Zone
+ </text>
+ <spinner
+ bottom="294"
+ control_name="AvatarAxisDeadZone2"
+ decimal_digits="2"
+ increment="0.01"
+ label_width="0"
+ layout="topleft"
+ left="125"
+ name="AvatarAxisDeadZone2"
+ width="56" />
+ <spinner
+ bottom="294"
+ control_name="BuildAxisDeadZone2"
+ decimal_digits="2"
+ increment="0.01"
+ label_width="0"
+ layout="topleft"
+ left="195"
+ name="BuildAxisDeadZone2"
+ width="56" />
+ <spinner
+ bottom="294"
+ control_name="FlycamAxisDeadZone2"
+ decimal_digits="2"
+ increment="0.01"
+ label_width="0"
+ layout="topleft"
+ left="265"
+ name="FlycamAxisDeadZone2"
+ width="56" />
+ <text
+ type="string"
+ length="1"
+ bottom="314"
+ halign="right"
+ layout="topleft"
+ left="20"
+ name="ZDeadZone"
+ width="94">
+ Z Dead Zone
+ </text>
+ <spinner
+ bottom="314"
+ control_name="AvatarAxisDeadZone0"
+ decimal_digits="2"
+ increment="0.01"
+ label_width="0"
+ layout="topleft"
+ left="125"
+ name="AvatarAxisDeadZone0"
+ width="56" />
+ <spinner
+ bottom="314"
+ control_name="BuildAxisDeadZone0"
+ decimal_digits="2"
+ increment="0.01"
+ label_width="0"
+ layout="topleft"
+ left="195"
+ name="BuildAxisDeadZone0"
+ width="56" />
+ <spinner
+ bottom="314"
+ control_name="FlycamAxisDeadZone0"
+ decimal_digits="2"
+ increment="0.01"
+ label_width="0"
+ layout="topleft"
+ left="265"
+ name="FlycamAxisDeadZone0"
+ width="56" />
+ <text
+ type="string"
+ length="1"
+ bottom="334"
+ halign="right"
+ layout="topleft"
+ left="20"
+ name="PitchDeadZone"
+ width="94">
+ Pitch Dead Zone
+ </text>
+ <spinner
+ bottom="334"
+ control_name="AvatarAxisDeadZone4"
+ decimal_digits="2"
+ increment="0.01"
+ label_width="0"
+ layout="topleft"
+ left="125"
+ name="AvatarAxisDeadZone4"
+ width="56" />
+ <spinner
+ bottom="334"
+ control_name="BuildAxisDeadZone4"
+ decimal_digits="2"
+ increment="0.01"
+ label_width="0"
+ layout="topleft"
+ left="195"
+ name="BuildAxisDeadZone4"
+ width="56" />
+ <spinner
+ bottom="334"
+ control_name="FlycamAxisDeadZone4"
+ decimal_digits="2"
+ increment="0.01"
+ label_width="0"
+ layout="topleft"
+ left="265"
+ name="FlycamAxisDeadZone4"
+ width="56" />
+ <text
+ type="string"
+ length="1"
+ bottom="354"
+ halign="right"
+ layout="topleft"
+ left="20"
+ name="YawDeadZone"
+ width="94">
+ Yaw Dead Zone
+ </text>
+ <spinner
+ bottom="354"
+ control_name="AvatarAxisDeadZone5"
+ decimal_digits="2"
+ increment="0.01"
+ label_width="0"
+ layout="topleft"
+ left="125"
+ name="AvatarAxisDeadZone5"
+ width="56" />
+ <spinner
+ bottom="354"
+ control_name="BuildAxisDeadZone5"
+ decimal_digits="2"
+ increment="0.01"
+ label_width="0"
+ layout="topleft"
+ left="195"
+ name="BuildAxisDeadZone5"
+ width="56" />
+ <spinner
+ bottom="354"
+ control_name="FlycamAxisDeadZone5"
+ decimal_digits="2"
+ increment="0.01"
+ label_width="0"
+ layout="topleft"
+ left="265"
+ name="FlycamAxisDeadZone5"
+ width="56" />
+ <text
+ type="string"
+ length="1"
+ bottom="374"
+ halign="right"
+ layout="topleft"
+ left="20"
+ name="RollDeadZone"
+ width="94">
+ Roll Dead Zone
+ </text>
+ <spinner
+ bottom="374"
+ control_name="BuildAxisDeadZone3"
+ decimal_digits="2"
+ increment="0.01"
+ label_width="0"
+ layout="topleft"
+ left="195"
+ name="BuildAxisDeadZone3"
+ width="56" />
+ <spinner
+ bottom="374"
+ control_name="FlycamAxisDeadZone3"
+ decimal_digits="2"
+ increment="0.01"
+ label_width="0"
+ layout="topleft"
+ left="265"
+ name="FlycamAxisDeadZone3"
+ width="56" />
+ <text
+ type="string"
+ length="1"
+ bottom="402"
+ halign="right"
+ layout="topleft"
+ left="20"
+ name="Feathering"
+ width="94">
+ Feathering
+ </text>
+ <slider
+ control_name="AvatarFeathering"
+ decimal_digits="0"
+ follows="left|top"
+ height="16"
+ increment="1"
+ initial_value="0.7"
+ layout="topleft"
+ left="116"
+ max_val="32"
+ min_val="1"
+ name="AvatarFeathering"
+ show_text="false"
+ top="402"
+ width="73" />
+ <slider
+ control_name="BuildFeathering"
+ decimal_digits="0"
+ follows="left|top"
+ height="16"
+ increment="1"
+ initial_value="0.7"
+ layout="topleft"
+ left_delta="70"
+ max_val="32"
+ min_val="1"
+ name="BuildFeathering"
+ show_text="false"
+ top_delta="0"
+ width="73" />
+ <slider
+ control_name="FlycamFeathering"
+ decimal_digits="0"
+ follows="left|top"
+ height="16"
+ increment="1"
+ initial_value="0.7"
+ layout="topleft"
+ left_delta="70"
+ max_val="32"
+ min_val="1"
+ name="FlycamFeathering"
+ show_text="false"
+ top_delta="0"
+ width="73" />
+ <text
+ type="string"
+ length="1"
+ bottom="430"
+ halign="right"
+ layout="topleft"
+ left="20"
+ name="ZoomScale2"
+ width="94">
+ Zoom Scale
+ </text>
+ <spinner
+ bottom="430"
+ control_name="FlycamAxisScale6"
+ decimal_digits="2"
+ label_width="0"
+ layout="topleft"
+ left="265"
+ max_val="1024"
+ min_val="-1024"
+ name="FlycamAxisScale6"
+ width="56" />
+ <text
+ type="string"
+ length="1"
+ bottom="450"
+ halign="right"
+ layout="topleft"
+ left="20"
+ name="ZoomDeadZone"
+ width="94">
+ Zoom Dead Zone
+ </text>
+ <spinner
+ bottom="450"
+ control_name="FlycamAxisDeadZone6"
+ decimal_digits="2"
+ increment="0.01"
+ label_width="0"
+ layout="topleft"
+ left="265"
+ name="FlycamAxisDeadZone6"
+ width="56" />
+ <button
+ follows="left|top"
+ height="22"
+ label="SpaceNavigator Defaults"
+ layout="topleft"
+ left="340"
+ name="SpaceNavigatorDefaults"
+ top="429"
+ width="184" />
+ <button
+ follows="right|bottom"
+ height="20"
+ label="OK"
+ label_selected="OK"
+ layout="topleft"
+ left_delta="0"
+ name="ok_btn"
+ top_pad="9"
+ width="90" />
+ <button
+ follows="right|bottom"
+ height="20"
+ label="Cancel"
+ label_selected="Cancel"
+ layout="topleft"
+ left_pad="4"
+ name="cancel_btn"
+ top_delta="0"
+ width="90" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_lagmeter.xml b/indra/newview/skins/default/xui/en/floater_lagmeter.xml
new file mode 100644
index 0000000000..b24c745bdd
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_lagmeter.xml
@@ -0,0 +1,336 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="170"
+ layout="topleft"
+ name="floater_lagmeter"
+ help_topic="floater_lagmeter"
+ save_rect="true"
+ title="LAG METER"
+ width="350">
+ <floater.string
+ name="max_title_msg">
+ Lag Meter
+ </floater.string>
+ <floater.string
+ name="max_width_px">
+ 360
+ </floater.string>
+ <floater.string
+ name="min_title_msg">
+ Lag
+ </floater.string>
+ <floater.string
+ name="min_width_px">
+ 90
+ </floater.string>
+ <floater.string
+ name="client_text_msg">
+ Client
+ </floater.string>
+ <floater.string
+ name="client_frame_rate_critical_fps">
+ 10
+ </floater.string>
+ <floater.string
+ name="client_frame_rate_warning_fps">
+ 15
+ </floater.string>
+ <floater.string
+ name="client_frame_time_window_bg_msg">
+ Normal, window in background
+ </floater.string>
+ <floater.string
+ name="client_frame_time_critical_msg">
+ Client frame rate below [CLIENT_FRAME_RATE_CRITICAL]
+ </floater.string>
+ <floater.string
+ name="client_frame_time_warning_msg">
+ Client frame rate between [CLIENT_FRAME_RATE_CRITICAL] and [CLIENT_FRAME_RATE_WARNING]
+ </floater.string>
+ <floater.string
+ name="client_frame_time_normal_msg">
+ Normal
+ </floater.string>
+ <floater.string
+ name="client_draw_distance_cause_msg">
+ Possible cause: Draw distance set too high
+ </floater.string>
+ <floater.string
+ name="client_texture_loading_cause_msg">
+ Possible cause: Images loading
+ </floater.string>
+ <floater.string
+ name="client_texture_memory_cause_msg">
+ Possible cause: Too many images in memory
+ </floater.string>
+ <floater.string
+ name="client_complex_objects_cause_msg">
+ Possible cause: Too many complex objects in scene
+ </floater.string>
+ <floater.string
+ name="network_text_msg">
+ Network
+ </floater.string>
+ <floater.string
+ name="network_packet_loss_critical_pct">
+ 10
+ </floater.string>
+ <floater.string
+ name="network_packet_loss_warning_pct">
+ 5
+ </floater.string>
+ <floater.string
+ name="network_packet_loss_critical_msg">
+ Connection is dropping over [NETWORK_PACKET_LOSS_CRITICAL]% of packets
+ </floater.string>
+ <floater.string
+ name="network_packet_loss_warning_msg">
+ Connection is dropping [NETWORK_PACKET_LOSS_WARNING]%-[NETWORK_PACKET_LOSS_CRITICAL]% of packets
+ </floater.string>
+ <floater.string
+ name="network_performance_normal_msg">
+ Normal
+ </floater.string>
+ <floater.string
+ name="network_ping_critical_ms">
+ 600
+ </floater.string>
+ <floater.string
+ name="network_ping_warning_ms">
+ 300
+ </floater.string>
+ <floater.string
+ name="network_ping_critical_msg">
+ Connection ping time is over [NETWORK_PING_CRITICAL] ms
+ </floater.string>
+ <floater.string
+ name="network_ping_warning_msg">
+ Connection ping time is [NETWORK_PING_WARNING]-[NETWORK_PING_CRITICAL] ms
+ </floater.string>
+ <floater.string
+ name="network_packet_loss_cause_msg">
+ Possible bad connection or &apos;Bandwidth&apos; pref too high.
+ </floater.string>
+ <floater.string
+ name="network_ping_cause_msg">
+ Possible bad connection or file-sharing app.
+ </floater.string>
+ <floater.string
+ name="server_text_msg">
+ Server
+ </floater.string>
+ <floater.string
+ name="server_frame_rate_critical_fps">
+ 20
+ </floater.string>
+ <floater.string
+ name="server_frame_rate_warning_fps">
+ 30
+ </floater.string>
+ <floater.string
+ name="server_single_process_max_time_ms">
+ 20
+ </floater.string>
+ <floater.string
+ name="server_frame_time_critical_msg">
+ Simulator framerate below [SERVER_FRAME_RATE_CRITICAL]
+ </floater.string>
+ <floater.string
+ name="server_frame_time_warning_msg">
+ Simulator framerate between [SERVER_FRAME_RATE_CRITICAL] and [SERVER_FRAME_RATE_WARNING]
+ </floater.string>
+ <floater.string
+ name="server_frame_time_normal_msg">
+ Normal
+ </floater.string>
+ <floater.string
+ name="server_physics_cause_msg">
+ Possible Cause: Too many physical objects
+ </floater.string>
+ <floater.string
+ name="server_scripts_cause_msg">
+ Possible Cause: Too many scripted objects
+ </floater.string>
+ <floater.string
+ name="server_net_cause_msg">
+ Possible Cause: Too much network traffic
+ </floater.string>
+ <floater.string
+ name="server_agent_cause_msg">
+ Possible Cause: Too many moving people in region
+ </floater.string>
+ <floater.string
+ name="server_images_cause_msg">
+ Possible Cause: Too many image calculations
+ </floater.string>
+ <floater.string
+ name="server_generic_cause_msg">
+ Possible Cause: Simulator load too heavy
+ </floater.string>
+ <floater.string
+ name="smaller_label">
+ &gt;&gt;
+ </floater.string>
+ <floater.string
+ name="bigger_label">
+ &lt;&lt;
+ </floater.string>
+ <button
+ follows="top|left"
+ height="16"
+ image_selected="lag_status_good.tga"
+ image_unselected="lag_status_good.tga"
+ layout="topleft"
+ left="8"
+ name="client_lagmeter"
+ tab_stop="false"
+ tool_tip="Client lag status"
+ top="24"
+ width="16" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_pad="3"
+ name="client"
+ top_delta="0"
+ width="128">
+ Client
+ </text>
+ <text
+ invisiblity_control="LagMeterShrunk"
+ type="string"
+ length="1"
+ bottom="40"
+ follows="left|top"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="110"
+ name="client_text"
+ right="-10">
+ Normal
+ </text>
+ <text
+ invisiblity_control="LagMeterShrunk"
+ bottom="56"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="40"
+ name="client_lag_cause"
+ right="-32" />
+ <button
+ follows="top|left"
+ height="16"
+ image_selected="lag_status_good.tga"
+ image_unselected="lag_status_good.tga"
+ layout="topleft"
+ left="8"
+ name="network_lagmeter"
+ tab_stop="false"
+ tool_tip="Network lag status"
+ top="64"
+ width="16" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_pad="3"
+ name="network"
+ top_delta="0"
+ width="128">
+ Network
+ </text>
+ <text
+ invisiblity_control="LagMeterShrunk"
+ type="string"
+ length="1"
+ bottom="80"
+ follows="left|top"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="110"
+ name="network_text"
+ right="-10">
+ Normal
+ </text>
+ <text
+ invisiblity_control="LagMeterShrunk"
+ bottom="96"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="40"
+ name="network_lag_cause"
+ right="-32" />
+ <button
+ follows="top|left"
+ height="16"
+ image_selected="lag_status_good.tga"
+ image_unselected="lag_status_good.tga"
+ layout="topleft"
+ left="8"
+ name="server_lagmeter"
+ tab_stop="false"
+ tool_tip="Server lag status"
+ top="104"
+ width="16" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_pad="3"
+ name="server"
+ top_delta="0"
+ width="60">
+ Server
+ </text>
+ <text
+ invisiblity_control="LagMeterShrunk"
+ type="string"
+ length="1"
+ bottom="120"
+ follows="left|top"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="110"
+ name="server_text"
+ right="-10">
+ Normal
+ </text>
+ <text
+ invisiblity_control="LagMeterShrunk"
+ bottom="136"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="40"
+ name="server_lag_cause"
+ right="-32" />
+ <button
+ follows="left|top"
+ height="20"
+ label="&gt;&gt;"
+ layout="topleft"
+ left="10"
+ name="minimize"
+ tool_tip="Toggle floater size"
+ top_delta="24"
+ width="40">
+ <button.commit_callback
+ function="LagMeter.ClickShrink" />
+ </button>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_land_holdings.xml b/indra/newview/skins/default/xui/en/floater_land_holdings.xml
new file mode 100644
index 0000000000..06c766f744
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_land_holdings.xml
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="430"
+ layout="topleft"
+ name="land holdings floater"
+ help_topic="land_holdings_floater"
+ title="MY LAND"
+ width="600">
+ <floater.string
+ name="area_string">
+ [AREA] m²
+ </floater.string>
+ <scroll_list
+ draw_heading="true"
+ height="170"
+ layout="topleft"
+ left="10"
+ name="parcel list"
+ top="28"
+ width="580">
+ <scroll_list.columns
+ label="Parcel"
+ name="name"
+ width="167" />
+ <scroll_list.columns
+ label="Region"
+ name="location"
+ width="180" />
+ <scroll_list.columns
+ label="Type"
+ name="type"
+ width="145" />
+ <scroll_list.columns
+ label="Area"
+ name="area"
+ width="88" />
+ <scroll_list.columns
+ label=""
+ name="hidden"
+ width="-1" />
+ </scroll_list>
+ <button
+ height="23"
+ label="Teleport"
+ label_selected="Teleport"
+ layout="topleft"
+ top="208"
+ left="10"
+ name="Teleport"
+ tool_tip="Teleport to the center of this land."
+ width="80" />
+ <button
+ height="23"
+ label="Map"
+ label_selected="Map"
+ layout="topleft"
+ top="208"
+ left="95"
+ name="Show on Map"
+ tool_tip="Show this land on the world map"
+ width="80" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ top="251"
+ left="10"
+ name="contrib_label"
+ height="16"
+ width="580">
+ Contributions to your groups:
+ </text>
+ <scroll_list
+ draw_heading="true"
+ height="75"
+ layout="topleft"
+ name="grant list"
+ top="271"
+ left="10"
+ width="580">
+ <scroll_list.columns
+ label="Group"
+ name="group"
+ width="290"
+ left_pad="10" />
+ <scroll_list.columns
+ label="Area"
+ name="area"
+ width="290" />
+ </scroll_list>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ name="allowed_label"
+ top="366"
+ left="10"
+ width="290">
+ Allowed land holdings at current payment plan:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ name="allowed_text"
+ top="366"
+ left="305"
+ width="290">
+ [AREA] m²
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ top="386"
+ left="10"
+ name="current_label"
+ width="290">
+ Current land holdings:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ top="386"
+ left="305"
+ name="current_text"
+ width="290">
+ [AREA] m²
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerifBold"
+ height="16"
+ layout="topleft"
+ top="406"
+ left="10"
+ name="available_label"
+ width="290">
+ Available for land purchases:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerifBold"
+ height="16"
+ layout="topleft"
+ name="available_text"
+ top="406"
+ left="305"
+ width="290">
+ [AREA] m²
+ </text>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml
new file mode 100644
index 0000000000..e94717fe32
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ bevel_style="none"
+ border_style="line"
+ can_resize="true"
+ follows="left|top"
+ height="570"
+ layout="topleft"
+ min_height="271"
+ min_width="290"
+ name="script ed float"
+ help_topic="script_ed_float"
+ save_rect="true"
+ title="SCRIPT: NEW SCRIPT"
+ width="500">
+ <floater.string
+ name="not_allowed">
+ You can not view or edit this script, since it has been set as &quot;no copy&quot;. You need full permissions to view or edit a script inside an object.
+ </floater.string>
+ <floater.string
+ name="script_running">
+ Running
+ </floater.string>
+ <floater.string
+ name="Title">
+ Script: [NAME]
+ </floater.string>
+ <button
+ follows="right|bottom"
+ height="20"
+ label="Reset"
+ label_selected="Reset"
+ layout="topleft"
+ left="358"
+ name="Reset"
+ top="545"
+ width="128" />
+ <check_box
+ enabled="false"
+ follows="left|bottom"
+ font="SansSerif"
+ height="18"
+ initial_value="true"
+ label="Running"
+ layout="topleft"
+ left_delta="-350"
+ name="running"
+ top_delta="2"
+ width="100" />
+ <check_box
+ enabled="false"
+ follows="left|bottom"
+ font="SansSerif"
+ height="18"
+ initial_value="true"
+ label="Mono"
+ layout="topleft"
+ left_delta="70"
+ name="mono"
+ top_delta="0"
+ width="100" />
+ <panel
+ bevel_style="none"
+ border_style="line"
+ follows="left|top|right|bottom"
+ height="506"
+ layout="topleft"
+ left="1"
+ name="script ed panel"
+ top="18"
+ width="497" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_lsl_guide.xml b/indra/newview/skins/default/xui/en/floater_lsl_guide.xml
new file mode 100644
index 0000000000..c9d87f158f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_lsl_guide.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ follows="left|top"
+ height="400"
+ layout="topleft"
+ min_height="271"
+ min_width="350"
+ name="script ed float"
+ help_topic="lsl_reference"
+ save_rect="true"
+ title="LSL REFERENCE"
+ width="370">
+ <check_box
+ follows="top|left"
+ font="SansSerif"
+ halign="center"
+ height="20"
+ label="Follow cursor"
+ layout="topleft"
+ left="10"
+ name="lock_check"
+ top="25"
+ width="60" />
+ <combo_box
+ allow_text_entry="true"
+ follows="top|left|right"
+ font="SansSerif"
+ halign="center"
+ height="20"
+ label="Lock"
+ layout="topleft"
+ left_pad="40"
+ name="history_combo"
+ top_delta="0"
+ width="90" />
+ <button
+ follows="top|right"
+ height="20"
+ label="Back"
+ layout="topleft"
+ left_pad="5"
+ name="back_btn"
+ top_delta="0"
+ width="70" />
+ <button
+ follows="top|right"
+ height="20"
+ label="Forward"
+ layout="topleft"
+ left_pad="5"
+ name="fwd_btn"
+ top_delta="0"
+ width="70" />
+ <web_browser
+ bottom="390"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="10"
+ name="lsl_guide_html"
+ right="-10"
+ top="50" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_map.xml b/indra/newview/skins/default/xui/en/floater_map.xml
new file mode 100644
index 0000000000..3a5ceed5fb
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_map.xml
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ can_resize="true"
+ follows="top|right"
+ height="225"
+ layout="topleft"
+ min_height="60"
+ min_width="174"
+ name="Map"
+ help_topic="map"
+ save_rect="true"
+ save_visibility="true"
+ single_instance="true"
+ width="200">
+ <floater.string
+ name="mini_map_north">
+ N
+ </floater.string>
+ <floater.string
+ name="mini_map_east">
+ E
+ </floater.string>
+ <floater.string
+ name="mini_map_west">
+ W
+ </floater.string>
+ <floater.string
+ name="mini_map_south">
+ S
+ </floater.string>
+ <floater.string
+ name="mini_map_southeast">
+ SE
+ </floater.string>
+ <floater.string
+ name="mini_map_northeast">
+ NE
+ </floater.string>
+ <floater.string
+ name="mini_map_southwest">
+ SW
+ </floater.string>
+ <floater.string
+ name="mini_map_northwest">
+ NW
+ </floater.string>
+ <floater.string
+ name="ToolTipMsg">
+ [AGENT][REGION](Double-click to open Map)
+ </floater.string>
+ <net_map
+ bg_color="NetMapBackgroundColor"
+ bottom="225"
+ follows="top|left|bottom|right"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="Net Map"
+ right="198"
+ top="2" />
+ <text
+ type="string"
+ length="1"
+ bottom="225"
+ label="N"
+ layout="topleft"
+ left="0"
+ name="floater_map_north"
+ right="10"
+ text_color="1 1 1 0.7"
+ top="215">
+ N
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="225"
+ label="E"
+ layout="topleft"
+ left="0"
+ name="floater_map_east"
+ right="10"
+ text_color="1 1 1 0.7"
+ top="215">
+ E
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="225"
+ label="W"
+ layout="topleft"
+ left="0"
+ name="floater_map_west"
+ right="11"
+ text_color="1 1 1 0.7"
+ top="215">
+ W
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="225"
+ label="S"
+ layout="topleft"
+ left="0"
+ name="floater_map_south"
+ right="10"
+ text_color="1 1 1 0.7"
+ top="215">
+ S
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="225"
+ label="SE"
+ layout="topleft"
+ left="0"
+ name="floater_map_southeast"
+ right="20"
+ text_color="1 1 1 0.7"
+ top="215">
+ SE
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="225"
+ label="NE"
+ layout="topleft"
+ left="0"
+ name="floater_map_northeast"
+ right="20"
+ text_color="1 1 1 0.7"
+ top="215">
+ NE
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="225"
+ label="SW"
+ layout="topleft"
+ left="0"
+ name="floater_map_southwest"
+ right="20"
+ text_color="1 1 1 0.7"
+ top="215">
+ SW
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="225"
+ label="NW"
+ layout="topleft"
+ left="0"
+ name="floater_map_northwest"
+ right="20"
+ text_color="1 1 1 0.7"
+ top="215">
+ NW
+ </text>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_media_browser.xml b/indra/newview/skins/default/xui/en/floater_media_browser.xml
new file mode 100644
index 0000000000..70dac7e41c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_media_browser.xml
@@ -0,0 +1,236 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="440"
+ layout="topleft"
+ min_height="140"
+ min_width="467"
+ name="floater_about"
+ help_topic="floater_about"
+ save_rect="true"
+ single_instance="true"
+ title="MEDIA BROWSER"
+ width="820">
+ <floater.string
+ name="home_page_url">
+ http://www.secondlife.com
+ </floater.string>
+ <floater.string
+ name="support_page_url">
+ http://support.secondlife.com
+ </floater.string>
+ <layout_stack
+ bottom="440"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="10"
+ name="stack1"
+ top="20"
+ width="800">
+ <layout_panel
+ auto_resize="false"
+ height="20"
+ layout="topleft"
+ left="0"
+ name="nav_controls"
+ top="400"
+ user_resize="false"
+ width="800">
+ <button
+ follows="left|top"
+ height="20"
+ label="Back"
+ layout="topleft"
+ left="0"
+ name="back"
+ top="0"
+ width="55">
+ <button.commit_callback
+ function="MediaBrowser.Back" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="Forward"
+ layout="topleft"
+ left_pad="3"
+ name="forward"
+ top_delta="0"
+ width="68">
+ <button.commit_callback
+ function="MediaBrowser.Forward" />
+ </button>
+ <button
+ enabled="false"
+ follows="left|top"
+ height="20"
+ label="Reload"
+ layout="topleft"
+ left_pad="2"
+ name="reload"
+ top_delta="0"
+ width="70">
+ <button.commit_callback
+ function="MediaBrowser.Refresh" />
+ </button>
+ <combo_box
+ allow_text_entry="true"
+ follows="left|top|right"
+ height="20"
+ layout="topleft"
+ left_pad="5"
+ max_chars="1024"
+ name="address"
+ top_delta="0"
+ width="540">
+ <combo_box.commit_callback
+ function="MediaBrowser.EnterAddress" />
+ </combo_box>
+ <button
+ enabled="false"
+ follows="right|top"
+ height="20"
+ label="Go"
+ layout="topleft"
+ left_pad="5"
+ name="go"
+ top_delta="0"
+ width="55">
+ <button.commit_callback
+ function="MediaBrowser.Go" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="time_controls"
+ top_delta="0"
+ user_resize="false"
+ width="800">
+ <button
+ follows="left|top"
+ height="20"
+ label="rewind"
+ layout="topleft"
+ left="0"
+ name="rewind"
+ top="0"
+ width="55" />
+ <button
+ follows="left|top"
+ height="20"
+ image_selected="button_anim_play_selected.tga"
+ image_unselected="button_anim_play.tga"
+ layout="topleft"
+ left_delta="55"
+ name="play"
+ top_delta="0"
+ width="55" />
+ <button
+ follows="left|top"
+ height="20"
+ image_selected="button_anim_pause_selected.tga"
+ image_unselected="button_anim_pause.tga"
+ layout="topleft"
+ left_delta="0"
+ name="pause"
+ top_delta="0"
+ width="55" />
+ <button
+ follows="left|top"
+ height="20"
+ label="stop"
+ layout="topleft"
+ left_pad="10"
+ name="stop"
+ top_delta="0"
+ width="55" />
+ <button
+ follows="left|top"
+ height="20"
+ label="forward"
+ layout="topleft"
+ left_pad="20"
+ name="seek"
+ top_delta="0"
+ width="55" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="parcel_owner_controls"
+ top_delta="0"
+ user_resize="false"
+ width="540">
+ <button
+ enabled="false"
+ follows="left|top"
+ height="20"
+ label="Send Current Page to Parcel"
+ layout="topleft"
+ left="0"
+ name="assign"
+ top="0"
+ width="200">
+ <button.commit_callback
+ function="MediaBrowser.Assign" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="external_controls"
+ top_delta="0"
+ user_resize="false"
+ width="540">
+ <web_browser
+ bottom="-10"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="0"
+ name="browser"
+ top="0"
+ width="540" />
+ <button
+ follows="bottom|left"
+ height="20"
+ label="Open in My Web Browser"
+ layout="topleft"
+ left_delta="0"
+ name="open_browser"
+ top_pad="5"
+ width="185">
+ <button.commit_callback
+ function="MediaBrowser.OpenWebBrowser" />
+ </button>
+ <check_box
+ control_name="UseExternalBrowser"
+ follows="bottom|left"
+ height="20"
+ label="Always open in my web browser"
+ layout="topleft"
+ left_pad="5"
+ name="open_always"
+ top_delta="0"
+ width="200" />
+ <button
+ follows="bottom|right"
+ height="20"
+ label="Close"
+ layout="topleft"
+ left_pad="80"
+ name="close"
+ top_delta="0"
+ width="70">
+ <button.commit_callback
+ function="MediaBrowser.Close" />
+ </button>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_media_settings.xml b/indra/newview/skins/default/xui/en/floater_media_settings.xml
new file mode 100644
index 0000000000..681731b0da
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_media_settings.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_close="true"
+ can_drag_on_left="false"
+ can_minimize="true"
+ can_resize="false"
+ can_tear_off="true"
+ default_tab_group="1"
+ enabled="true"
+ width="365"
+ height="535"
+ left="330"
+ min_height="535"
+ min_width="365"
+ mouse_opaque="true"
+ name="media_settings"
+ help_topic = "media_settings"
+ title="MEDIA SETTINGS">
+ <button
+ bottom="525"
+ enabled="true"
+ follows="right|bottom"
+ font="SansSerif"
+ halign="center"
+ height="20"
+ label="OK"
+ label_selected="OK"
+ left="75"
+ mouse_opaque="true"
+ name="OK"
+ scale_image="true"
+ width="90" />
+ <button
+ bottom_delta="0"
+ enabled="true"
+ follows="right|bottom"
+ font="SansSerif"
+ halign="center"
+ height="20"
+ label="Cancel"
+ label_selected="Cancel"
+ left_delta="93"
+ mouse_opaque="true"
+ name="Cancel"
+ scale_image="true"
+ width="90" />
+ <button
+ bottom_delta="0"
+ enabled="true"
+ follows="right|bottom"
+ font="SansSerif"
+ halign="center"
+ height="20"
+ label="Apply"
+ label_selected="Apply"
+ left_delta="93"
+ mouse_opaque="true"
+ name="Apply"
+ scale_image="true"
+ width="90" />
+ <tab_container
+ bottom="500"
+ enabled="true"
+ follows="left|top|right|bottom"
+ height="485"
+ left="0"
+ mouse_opaque="false"
+ name="tab_container"
+ tab_group="1"
+ tab_position="top"
+ tab_width="80"
+ width="365" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_mem_leaking.xml b/indra/newview/skins/default/xui/en/floater_mem_leaking.xml
new file mode 100644
index 0000000000..28a29c42aa
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_mem_leaking.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ follows="left|top"
+ height="175"
+ layout="topleft"
+ name="MemLeak"
+ help_topic="memleak"
+ title="SIMULATE A MEMORY LEAK"
+ width="350">
+ <spinner
+ decimal_digits="0"
+ follows="left|top"
+ height="20"
+ increment="256"
+ initial_value="512"
+ label="Leaking Speed (bytes per frame):"
+ label_width="220"
+ layout="topleft"
+ left="10"
+ max_val="4.29497e+009"
+ name="leak_speed"
+ top="30"
+ width="330">
+ <spinner.commit_callback
+ function="MemLeak.ChangeLeakingSpeed" />
+ </spinner>
+ <spinner
+ decimal_digits="0"
+ follows="left|top"
+ height="20"
+ increment="4"
+ initial_value="512"
+ label="Max Leaked Memory (MB):"
+ label_width="220"
+ layout="topleft"
+ left_delta="0"
+ max_val="4096"
+ name="max_leak"
+ top_pad="5"
+ width="330">
+ <spinner.commit_callback
+ function="MemLeak.ChangeMaxMemLeaking" />
+ </spinner>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="total_leaked_label"
+ top_delta="20"
+ width="300">
+ Current leaked memory: [SIZE] KB
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="note_label_1"
+ top_delta="25"
+ width="330">
+ [NOTE1]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left_delta="0"
+ name="note_label_2"
+ top_delta="25"
+ width="330">
+ [NOTE2]
+ </text>
+ <button
+ follows="left|top"
+ height="20"
+ label="Start"
+ layout="topleft"
+ left_delta="0"
+ name="start_btn"
+ top_delta="20"
+ width="70">
+ <button.commit_callback
+ function="MemLeak.Start" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="Stop"
+ layout="topleft"
+ left_pad="7"
+ name="stop_btn"
+ top_delta="0"
+ width="70">
+ <button.commit_callback
+ function="MemLeak.Stop" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="Release"
+ layout="topleft"
+ left_pad="7"
+ name="release_btn"
+ top_delta="0"
+ width="70">
+ <button.commit_callback
+ function="MemLeak.Release" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="Close"
+ layout="topleft"
+ left_pad="36"
+ name="close_btn"
+ top_delta="0"
+ width="70">
+ <button.commit_callback
+ function="MemLeak.Close" />
+ </button>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_moveview.xml b/indra/newview/skins/default/xui/en/floater_moveview.xml
new file mode 100644
index 0000000000..0bdcbf30df
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_moveview.xml
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_dock="true"
+ can_minimize="true"
+ can_close="false"
+ center_horiz="true"
+ follows="bottom"
+ height="110"
+ layout="topleft"
+ name="move_floater"
+ help_topic="move_floater"
+ save_rect="true"
+ save_visibility="true"
+ width="115">
+ <string
+ name="walk_forward_tooltip">
+ Walk Forward (press Up Arrow or W)
+ </string>
+ <string
+ name="walk_back_tooltip">
+ Walk Backwards (press Down Arrow or S)
+ </string>
+ <string
+ name="run_forward_tooltip">
+ Run Forward (press Up Arrow or W)
+ </string>
+ <string
+ name="run_back_tooltip">
+ Run Backwards (press Down Arrow or S)
+ </string>
+ <string
+ name="fly_forward_tooltip">
+ Fly Forward (press Up Arrow or W)
+ </string>
+ <string
+ name="fly_back_tooltip">
+ Fly Backwards (press Down Arrow or S)
+ </string>
+ <panel
+ border="false"
+ height="83"
+ follows="left|top"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="panel_actions"
+ top="0"
+ width="115">
+ <button
+ follows="left|bottom"
+ height="25"
+ image_selected="Movement_TurnLeft_On"
+ image_pressed_selected="Movement_TurnLeft_On"
+ image_unselected="Movement_TurnLeft_Off"
+ layout="topleft"
+ left="17"
+ name="turn left btn"
+ scale_image="false"
+ tool_tip="Turn left (press Left Arrow or A)"
+ top="45"
+ width="25" />
+ <button
+ follows="left|bottom"
+ height="25"
+ image_selected="Movement_TurnRight_On"
+ image_pressed_selected="Movement_TurnRight_On"
+ image_unselected="Movement_TurnRight_Off"
+ layout="topleft"
+ left_pad="34"
+ name="turn right btn"
+ scale_image="false"
+ tool_tip="Turn right (press Right Arrow or D)"
+ top_delta="0"
+ width="25" />
+ <button
+ follows="left|bottom"
+ height="25"
+ image_selected="Movement_Up_On"
+ image_pressed_selected="Movement_Up_On"
+ image_unselected="Movement_Up_Off"
+ layout="topleft"
+ left="10"
+ name="move up btn"
+ scale_image="false"
+ tool_tip="Fly up, press &quot;E&quot;"
+ top="14"
+ width="25" />
+ <button
+ follows="left|bottom"
+ height="25"
+ image_selected="Movement_Down_On"
+ image_pressed_selected="Movement_Down_On"
+ image_unselected="Movement_Down_Off"
+ layout="topleft"
+ left_pad="45"
+ name="move down btn"
+ scale_image="false"
+ tool_tip="Fly down, press &quot;C&quot;"
+ top_delta="0"
+ width="20" />
+ <joystick_turn
+ follows="left|bottom"
+ height="25"
+ image_selected="Movement_Forward_On"
+ image_pressed_selected="Movement_Forward_On"
+ image_unselected="Movement_Forward_Off"
+ layout="topleft"
+ left="46"
+ name="forward btn"
+ quadrant="up"
+ scale_image="false"
+ tool_tip="Walk forward (press up arrow or W)"
+ top_delta="10"
+ width="21" />
+ <joystick_turn
+ follows="left|bottom"
+ height="25"
+ image_selected="Movement_Backward_On"
+ image_pressed_selected="Movement_Backward_On"
+ image_unselected="Movement_Backward_Off"
+ layout="topleft"
+ left_delta="0"
+ name="backward btn"
+ quadrant="down"
+ scale_image="false"
+ tool_tip="Walk backward (press down arrow or S)"
+ top_delta="30"
+ width="21" />
+ </panel>
+<!-- Width and height of this panel should be synchronized with panel_stand_stop_flying.xml -->
+ <panel
+ border="false"
+ height="27"
+ layout="topleft"
+ left="0"
+ name="panel_modes"
+ top_pad="0"
+ width="115">
+ <button
+ follows="left|bottom"
+ height="23"
+ image_overlay="Move_Walk_Off"
+ image_selected="PushButton_Selected_Press"
+ label=""
+ layout="topleft"
+ name="mode_walk_btn"
+ left="10"
+ pad_right="0"
+ tool_tip="Walking mode"
+ top="2"
+ width="31" />
+ <button
+ follows="left|bottom"
+ height="23"
+ image_overlay="Move_Run_Off"
+ image_selected="PushButton_Selected_Press"
+ label=""
+ layout="topleft"
+ left_pad="0"
+ name="mode_run_btn"
+ pad_left="0"
+ pad_right="0"
+ tool_tip="Running mode"
+ top="2"
+ width="31" />
+ <button
+ follows="left|bottom"
+ height="23"
+ image_overlay="Move_Fly_Off"
+ image_selected="PushButton_Selected_Press"
+ label=""
+ layout="topleft"
+ left_pad="0"
+ name="mode_fly_btn"
+ pad_left="0"
+ pad_right="0"
+ tool_tip="Flying mode"
+ top="2"
+ width="31" />
+ <button
+ visible="false"
+ follows="left|bottom"
+ height="20"
+ label="Stop Flying"
+ layout="topleft"
+ left="0"
+ name="stop_fly_btn"
+ tool_tip="Stop flying"
+ top="2"
+ width="115" />
+ </panel>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_mute_object.xml b/indra/newview/skins/default/xui/en/floater_mute_object.xml
new file mode 100644
index 0000000000..22b0a1783f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_mute_object.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ height="130"
+ layout="topleft"
+ name="block by name"
+ help_topic="mute_by_name"
+ title="BLOCK OBJECT BY NAME"
+ width="375">
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifLarge"
+ height="16"
+ layout="topleft"
+ left="10"
+ top="25"
+ name="message">
+ Block an object:
+ </text>
+ <line_editor
+ type="string"
+ length="1"
+ follows="top|right"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="object_name"
+ top_pad="5"
+ width="350">
+ Object name
+ </line_editor>
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifSmall"
+ height="16"
+ layout="topleft"
+ left="30"
+ name="note">
+ * Only blocks object text, not sounds
+ </text>
+ <button
+ follows="bottom|left"
+ height="23"
+ label="OK"
+ layout="topleft"
+ left="155"
+ name="OK"
+ top_pad="10"
+ width="100" />
+ <button
+ follows="bottom|right"
+ height="23"
+ label="Cancel"
+ layout="topleft"
+ left_pad="5"
+ name="Cancel"
+ width="100" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_my_friends.xml b/indra/newview/skins/default/xui/en/floater_my_friends.xml
new file mode 100644
index 0000000000..e7efcc7844
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_my_friends.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_close="false"
+ can_resize="true"
+ height="390"
+ layout="topleft"
+ min_height="240"
+ min_width="365"
+ name="floater_my_friends"
+ help_topic="floater_my_friends"
+ save_rect="true"
+ single_instance="true"
+ title="CONTACTS"
+ width="395">
+ <tab_container
+ follows="all"
+ height="364"
+ layout="topleft"
+ left="4"
+ name="friends_and_groups"
+ tab_position="top"
+ tab_width="80"
+ top="20"
+ width="383">
+ <panel
+ bottom="364"
+ filename="panel_friends.xml"
+ label="Friends"
+ layout="topleft"
+ left="0"
+ help_topic="my_friends_friends_tab"
+ name="friends_panel"
+ width="370" />
+ <panel
+ bottom="364"
+ filename="panel_groups.xml"
+ label="Groups"
+ layout="topleft"
+ left="0"
+ help_topic="my_friends_groups_tab"
+ name="groups_panel"
+ width="370" />
+ </tab_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
new file mode 100644
index 0000000000..ae686d9ab7
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater
+ border_visible="false"
+ border_drop_shadow_visible="false"
+ drop_shadow_visible="false"
+ border="false"
+ bg_opaque_image="Window_Foreground"
+ bg_alpha_image="Window_Background"
+ bg_alpha_color="0 0 0 0"
+ legacy_header_height="18"
+ can_minimize="true"
+ can_tear_off="false"
+ can_resize="true"
+ can_drag_on_left="false"
+ can_close="false"
+ can_dock="true"
+ bevel_style="in"
+ height="300"
+ min_width="150"
+ layout="topleft"
+ name="nearby_chat"
+ help_topic="nearby_chat"
+ save_rect="true"
+ title="NEARBY CHAT"
+ save_dock_state="true"
+ save_visibility="true"
+ single_instance="true"
+ width="320">
+ <chat_history
+ allow_html="true"
+ bg_readonly_color="ChatHistoryBgColor"
+ bg_writeable_color="ChatHistoryBgColor"
+ follows="all"
+ left="5"
+ top="20"
+ layout="topleft"
+ height="275"
+ name="chat_history"
+ parse_highlights="true"
+ text_color="ChatHistoryTextColor"
+ text_readonly_color="ChatHistoryTextColor"
+ right_widget_pad="5"
+ left_widget_pad="0"
+ width="315" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_notification.xml b/indra/newview/skins/default/xui/en/floater_notification.xml
new file mode 100644
index 0000000000..1f9ddecac2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_notification.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="200"
+ layout="topleft"
+ min_height="50"
+ name="notification"
+ title="NOTIFICATIONS CONSOLE"
+ width="200">
+ <text_editor
+ type="string"
+ length="1"
+ enabled="false"
+ follows="left|top|right|bottom"
+ font="SansSerif"
+ height="140"
+ ignore_tab="false"
+ layout="topleft"
+ left="4"
+ max_length="65536"
+ name="payload"
+ top="25"
+ width="192"
+ word_wrap="true">
+ Loading...
+ </text_editor>
+ <combo_box
+ follows="left|bottom"
+ height="20"
+ label="Response"
+ layout="topleft"
+ left="10"
+ name="response"
+ top="171"
+ width="100" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_notifications_console.xml b/indra/newview/skins/default/xui/en/floater_notifications_console.xml
new file mode 100644
index 0000000000..ca81b9bcf0
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_notifications_console.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="500"
+ layout="topleft"
+ min_height="50"
+ name="notifications_console"
+ help_topic="notifications_console"
+ single_instance="true"
+ title="NOTIFICATIONS CONSOLE"
+ width="500">
+ <combo_box
+ follows="left|right|top"
+ height="18"
+ label="Select notification type"
+ layout="topleft"
+ left="2"
+ name="notification_types"
+ top="22"
+ width="440" />
+ <button
+ follows="right|top"
+ height="18"
+ label="Add"
+ layout="topleft"
+ left_pad="3"
+ name="add_notification"
+ top_delta="0"
+ width="50" >
+ <button.commit_callback
+ function="ClickAdd" />
+ </button>
+ <layout_stack
+ bottom="495"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="5"
+ name="notification_channels"
+ right="-5"
+ top="42" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_openobject.xml b/indra/newview/skins/default/xui/en/floater_openobject.xml
new file mode 100644
index 0000000000..41a440aaa0
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_openobject.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ default_tab_group="1"
+ height="350"
+ layout="topleft"
+ min_height="160"
+ min_width="270"
+ name="objectcontents"
+ help_topic="objectcontents"
+ save_rect="true"
+ title="OBJECT CONTENTS"
+ width="300">
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ text_color="White"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="object_name"
+ top="20"
+ width="284">
+ [DESC]:
+ </text>
+ <panel_inventory_object
+ background_visible="false"
+ draw_border="false"
+ follows="all"
+ height="276"
+ layout="topleft"
+ left="10"
+ name="object_contents"
+ top_pad="0"
+ width="284" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Copy To Inventory"
+ label_selected="Copy To Inventory"
+ layout="topleft"
+ left="20"
+ name="copy_to_inventory_button"
+ tab_group="1"
+ top_pad="5"
+ width="120">
+ <button.commit_callback
+ function="OpenObject.MoveToInventory" />
+ </button>
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Copy And Wear"
+ label_selected="Copy And Wear"
+ layout="topleft"
+ left_pad="10"
+ name="copy_and_wear_button"
+ width="120">
+ <button.commit_callback
+ function="OpenObject.MoveAndWear" />
+ </button>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_outfit_save_as.xml b/indra/newview/skins/default/xui/en/floater_outfit_save_as.xml
new file mode 100644
index 0000000000..16079b30cb
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_outfit_save_as.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ can_close="false"
+ can_minimize="false"
+ height="100"
+ layout="topleft"
+ name="modal container"
+ width="240">
+ <button
+ height="23"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ left="20"
+ name="Save"
+ top="70"
+ width="82" />
+ <button
+ height="23"
+ label="Cancel"
+ label_selected="Cancel"
+ layout="topleft"
+ left_pad="36"
+ name="Cancel"
+ top_delta="0"
+ width="82" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="30"
+ layout="topleft"
+ left="20"
+ word_wrap="true"
+ name="Save item as:"
+ top="10"
+ width="200">
+ Save what I'm wearing
+as a new Outfit:
+ </text>
+ <line_editor
+ type="string"
+ length="1"
+ border_style="line"
+ border_thickness="1"
+ follows="left|top"
+ handle_edit_keys_directly="true"
+ height="23"
+ layout="topleft"
+ left_delta="0"
+ show_text_as_tentative="false"
+ top_pad="0"
+ max_length="63"
+ name="name ed"
+ width="200">
+ [DESC] (new)
+ </line_editor>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_outgoing_call.xml b/indra/newview/skins/default/xui/en/floater_outgoing_call.xml
new file mode 100644
index 0000000000..eb772cc0bd
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_outgoing_call.xml
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_close="false"
+ can_minimize="false"
+ can_tear_off="false"
+ height="125"
+ layout="topleft"
+ name="outgoing call"
+ help_topic="outgoing_call"
+ title="CALLING"
+ width="410">
+ <floater.string
+ name="lifetime">
+ 5
+ </floater.string>
+ <floater.string
+ name="localchat">
+ Nearby Voice Chat
+ </floater.string>
+ <floater.string
+ name="anonymous">
+ anonymous
+ </floater.string>
+ <floater.string
+ name="VoiceInviteP2P">
+ is calling.
+ </floater.string>
+ <floater.string
+ name="VoiceInviteAdHoc">
+ has joined a Voice Chat call with a conference chat.
+ </floater.string>
+ <avatar_icon
+ enabled="false"
+ follows="left|top"
+ height="36"
+ image_name="icon_avatar_online.tga"
+ layout="topleft"
+ left_delta="19"
+ top="35"
+ width="36" />
+ <group_icon
+ enabled="false"
+ follows="left|top"
+ height="36"
+ layout="topleft"
+ top="35"
+ width="36" />
+ <text
+ font="SansSerifLarge"
+ height="20"
+ layout="topleft"
+ left="77"
+ name="connecting"
+ top="27"
+ visible="false"
+ width="315"
+ word_wrap="true">
+Connecting to [CALLEE_NAME]
+ </text>
+ <text
+ font="SansSerifLarge"
+ height="20"
+ layout="topleft"
+ left="77"
+ name="calling"
+ top="27"
+ width="315"
+ word_wrap="true">
+Calling [CALLEE_NAME]
+ </text>
+ <text
+ font="SansSerifLarge"
+ height="20"
+ layout="topleft"
+ left="77"
+ name="noanswer"
+ top="27"
+ width="315"
+ word_wrap="true">
+No Answer. Please try again later.
+ </text>
+ <text
+ font="SansSerifLarge"
+ height="40"
+ layout="topleft"
+ left="77"
+ name="nearby"
+ top="27"
+ width="315"
+ word_wrap="true">
+ You have been disconnected from [VOICE_CHANNEL_NAME]. You will now be reconnected to Nearby Voice Chat.
+ </text>
+ <text
+ font="SansSerifLarge"
+ height="40"
+ layout="topleft"
+ left="77"
+ name="nearby_P2P"
+ top="27"
+ width="315"
+ word_wrap="true">
+ [VOICE_CHANNEL_NAME] has ended the call. You will now be reconnected to Nearby Voice Chat.
+ </text>
+ <text
+ font="SansSerif"
+ height="50"
+ layout="topleft"
+ left="77"
+ name="leaving"
+ top="52"
+ width="315"
+ word_wrap="true">
+Leaving [CURRENT_CHAT].
+ </text>
+ <button
+ height="24"
+ label="Cancel"
+ label_selected="Cancel"
+ left="70"
+ layout="topleft"
+ name="Cancel"
+ left_pad="10"
+ width="100" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_pay.xml b/indra/newview/skins/default/xui/en/floater_pay.xml
new file mode 100644
index 0000000000..509cffe490
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_pay.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ height="200"
+ layout="topleft"
+ name="Give Money"
+ help_topic="give_money"
+ save_rect="true"
+ width="225">
+ <string
+ name="payee_group">
+ Pay Group
+ </string>
+ <string
+ name="payee_resident">
+ Pay Resident
+ </string>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="18"
+ layout="topleft"
+ left="12"
+ name="payee_label"
+ top="22"
+ width="75">
+ Pay:
+ </text>
+ <icon
+ height="16"
+ width="16"
+ image_name="Generic_Person"
+ mouse_opaque="true"
+ name="icon_person"
+ tool_tip="Person"
+ top_pad="0"
+ left="10"
+ />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ layout="topleft"
+ left_pad="7"
+ name="payee_name"
+ width="210">
+ [FIRST] [LAST]
+ </text>
+ <button
+ height="23"
+ label="L$1"
+ label_selected="L$1"
+ layout="topleft"
+ left="25"
+ name="fastpay 1"
+ top_pad="8"
+ width="80" />
+ <button
+ height="23"
+ label="L$5"
+ label_selected="L$5"
+ layout="topleft"
+ left_pad="15"
+ name="fastpay 5"
+ width="80" />
+ <button
+ height="23"
+ label="L$10"
+ label_selected="L$10"
+ layout="topleft"
+ left="25"
+ name="fastpay 10"
+ top_pad="8"
+ width="80" />
+ <button
+ height="23"
+ label="L$20"
+ label_selected="L$20"
+ layout="topleft"
+ left_pad="15"
+ name="fastpay 20"
+ width="80" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="18"
+ layout="topleft"
+ left="25"
+ name="amount text"
+ top_pad="8"
+ width="180">
+ Or, choose amount:
+ </text>
+ <line_editor
+ border_style="line"
+ follows="left|top|right"
+ height="19"
+ top_pad="0"
+ layout="topleft"
+ left="120"
+ max_length="9"
+ name="amount"
+ width="80" />
+ <button
+ enabled="false"
+ height="23"
+ label="Pay"
+ label_selected="Pay"
+ layout="topleft"
+ left="10"
+ name="pay btn"
+ top_pad="5"
+ width="100" />
+ <button
+ height="23"
+ label="Cancel"
+ label_selected="Cancel"
+ layout="topleft"
+ left_pad="5"
+ name="cancel btn"
+ width="100" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_pay_object.xml b/indra/newview/skins/default/xui/en/floater_pay_object.xml
new file mode 100644
index 0000000000..455018f467
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_pay_object.xml
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ height="220"
+ layout="topleft"
+ name="Give Money"
+ help_topic="give_money"
+ save_rect="true"
+ width="225">
+ <string
+ name="payee_group">
+ Pay Group
+ </string>
+ <string
+ name="payee_resident">
+ Pay Resident
+ </string>
+ <icon
+ height="16"
+ width="16"
+ image_name="Generic_Person"
+ mouse_opaque="true"
+ name="icon_person"
+ tool_tip="Person"
+ top_pad="24"
+ left="10"
+ />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="7"
+ top_delta="3"
+ name="payee_name"
+ width="184">
+ Ericacita Moostopolison
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ halign="left"
+ height="14"
+ layout="topleft"
+ left="34"
+ name="object_name_label"
+ top_pad="0"
+ width="180">
+ Via object:
+ </text>
+ <icon
+ height="16"
+ width="16"
+ image_name="Inv_Object"
+ mouse_opaque="true"
+ name="icon_object"
+ tool_tip="Objects"
+ top_pad="0"
+ left="10"
+ />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="7"
+ name="object_name_text"
+ top_delta="3"
+ use_ellipses="true"
+ word_wrap="false"
+ width="188">
+ My awesome object with a really damn long name
+ </text>
+ <button
+ height="23"
+ label="L$1"
+ label_selected="L$1"
+ layout="topleft"
+ left="25"
+ name="fastpay 1"
+ top_pad="8"
+ width="80" />
+ <button
+ height="23"
+ label="L$5"
+ label_selected="L$5"
+ layout="topleft"
+ left_pad="15"
+ name="fastpay 5"
+ width="80" />
+ <button
+ height="23"
+ label="L$10"
+ label_selected="L$10"
+ layout="topleft"
+ left="25"
+ name="fastpay 10"
+ top_pad="8"
+ width="80" />
+ <button
+ height="23"
+ label="L$20"
+ label_selected="L$20"
+ layout="topleft"
+ left_pad="15"
+ name="fastpay 20"
+ width="80" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="14"
+ layout="topleft"
+ left="25"
+ name="amount text"
+ top_pad="8"
+ width="180">
+ Or, choose amount:
+ </text>
+ <line_editor
+ border_style="line"
+ follows="left|top|right"
+ height="21"
+ top_pad="0"
+ layout="topleft"
+ left="120"
+ max_length="9"
+ name="amount"
+ width="80" />
+ <button
+ enabled="false"
+ height="23"
+ label="Pay"
+ label_selected="Pay"
+ layout="topleft"
+ left="10"
+ name="pay btn"
+ top_pad="5"
+ width="100" />
+ <button
+ height="23"
+ label="Cancel"
+ label_selected="Cancel"
+ layout="topleft"
+ left_pad="5"
+ name="cancel btn"
+ width="100" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_perm_prefs.xml b/indra/newview/skins/default/xui/en/floater_perm_prefs.xml
new file mode 100644
index 0000000000..4909b8988f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_perm_prefs.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="180"
+ layout="topleft"
+ name="perm prefs"
+ help_topic="perm_prefs"
+ save_rect="true"
+ title="DEFAULT UPLOAD PERMISSIONS"
+ width="315">
+ <panel
+ follows="left|top|right|bottom"
+ height="120"
+ label="Permissions"
+ layout="topleft"
+ left="10"
+ name="permissions"
+ top="20"
+ width="315">
+ <check_box
+ control_name="ShareWithGroup"
+ height="16"
+ label="Share with group"
+ layout="topleft"
+ left="10"
+ name="share_with_group"
+ top="5"
+ width="150" />
+ <check_box
+ control_name="EveryoneCopy"
+ height="16"
+ label="Allow anyone to copy"
+ layout="topleft"
+ left_delta="0"
+ name="everyone_copy"
+ top_pad="5"
+ width="150" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="NextOwnerLabel"
+ top_pad="5"
+ width="150">
+ Next owner can:
+ </text>
+ <check_box
+ control_name="NextOwnerModify"
+ height="16"
+ label="Modify"
+ layout="topleft"
+ left_delta="0"
+ name="next_owner_modify"
+ top_pad="5"
+ width="150" />
+ <check_box
+ control_name="NextOwnerCopy"
+ height="16"
+ label="Copy"
+ layout="topleft"
+ left_delta="0"
+ name="next_owner_copy"
+ top_pad="5"
+ width="150" >
+ <check_box.commit_callback
+ function="Perms.Copy" />
+ </check_box>
+ <check_box
+ enabled_control="NextOwnerCopy"
+ control_name="NextOwnerTransfer"
+ enabled="false"
+ height="16"
+ initial_value="true"
+ label="Resell/Give away"
+ layout="topleft"
+ left_delta="0"
+ name="next_owner_transfer"
+ top_pad="5"
+ width="150" />
+ </panel>
+ <button
+ height="20"
+ label="OK"
+ label_selected="OK"
+ layout="topleft"
+ left="90"
+ name="ok"
+ top="150"
+ width="100">
+ <button.commit_callback
+ function="Perms.OK" />
+ </button>
+ <button
+ height="20"
+ label="Cancel"
+ label_selected="Cancel"
+ layout="topleft"
+ left_pad="5"
+ name="cancel"
+ top_delta="0"
+ width="100">
+ <button.commit_callback
+ function="Perms.Cancel" />
+ </button>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_post_process.xml b/indra/newview/skins/default/xui/en/floater_post_process.xml
new file mode 100644
index 0000000000..05559adf89
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_post_process.xml
@@ -0,0 +1,426 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="400"
+ layout="topleft"
+ name="Post-Process Floater"
+ help_topic="post_process_floater"
+ title="POST-PROCESS SETTINGS"
+ width="400">
+ <tab_container
+ follows="left|top"
+ height="400"
+ layout="topleft"
+ left="0"
+ name="Post-Process Tabs"
+ tab_position="top"
+ top="0"
+ width="400">
+ <panel
+ border="true"
+ follows="left|top|right|bottom"
+ height="400"
+ label="Color Filter"
+ layout="topleft"
+ left="1"
+ mouse_opaque="false"
+ help_topic="post_process_color_filter_tab"
+ name="wmiColorFilterPanel"
+ top="0"
+ width="398">
+ <check_box
+ control_name="wmiColorFilterToggle"
+ height="16"
+ label="Enable"
+ layout="topleft"
+ left="14"
+ name="wmiColorFilterToggle"
+ top="4"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-4"
+ name="wmiColorFilterBrightnessText"
+ top_pad="4"
+ width="355">
+ Brightness
+ </text>
+ <slider
+ control_name="wmiColorFilterBrightness"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="1.0"
+ layout="topleft"
+ left_delta="4"
+ max_val="4"
+ name="wmiColorFilterBrightness"
+ top_pad="20"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-4"
+ name="wmiColorFilterSaturationText"
+ top_pad="4"
+ width="355">
+ Saturation
+ </text>
+ <slider
+ control_name="wmiColorFilterSaturation"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="1.0"
+ layout="topleft"
+ left_delta="4"
+ max_val="2"
+ min_val="-1"
+ name="wmiColorFilterSaturation"
+ top_pad="20"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-4"
+ name="wmiColorFilterContrastText"
+ top_pad="4"
+ width="355">
+ Contrast
+ </text>
+ <slider
+ control_name="wmiColorFilterContrast"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="1.0"
+ layout="topleft"
+ left_delta="4"
+ max_val="4"
+ name="wmiColorFilterContrast"
+ top_pad="20"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-4"
+ name="wmiColorFilterBaseText"
+ top_pad="4"
+ width="355">
+ Contrast Base Color
+ </text>
+ <slider
+ control_name="wmiColorFilterBaseR"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="1.0"
+ label="R"
+ layout="topleft"
+ left_delta="4"
+ name="wmiColorFilterBaseR"
+ top_pad="20"
+ width="200" />
+ <slider
+ control_name="wmiColorFilterBaseG"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="1.0"
+ label="G"
+ layout="topleft"
+ left_delta="0"
+ name="wmiColorFilterBaseG"
+ top_pad="10"
+ width="200" />
+ <slider
+ control_name="wmiColorFilterBaseB"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="1.0"
+ label="B"
+ layout="topleft"
+ left_delta="0"
+ name="wmiColorFilterBaseB"
+ top_pad="10"
+ width="200" />
+ <slider
+ control_name="wmiColorFilterBaseI"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.5"
+ label="I"
+ layout="topleft"
+ left_delta="0"
+ name="wmiColorFilterBaseI"
+ top_pad="10"
+ width="200" />
+ </panel>
+ <panel
+ border="true"
+ follows="left|top|right|bottom"
+ height="400"
+ label="Night Vision"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ help_topic="post_process_night_vision_tab"
+ name="wmiNightVisionPanel"
+ top_delta="-236"
+ width="398">
+ <check_box
+ control_name="wmiNightVisionToggle"
+ height="16"
+ label="Enable"
+ layout="topleft"
+ left="14"
+ name="wmiNightVisionToggle"
+ top="4"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-4"
+ name="wmiNightVisionBrightMultText"
+ top_pad="5"
+ width="355">
+ Light Amplification Multiple
+ </text>
+ <slider
+ control_name="wmiNightVisionBrightMult"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="3.0"
+ layout="topleft"
+ left_delta="4"
+ max_val="10"
+ min_val="1"
+ name="wmiNightVisionBrightMult"
+ top_pad="20"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-4"
+ name="wmiNightVisionNoiseSizeText"
+ top_pad="4"
+ width="355">
+ Noise Size
+ </text>
+ <slider
+ control_name="wmiNightVisionNoiseSize"
+ follows="left"
+ height="10"
+ initial_value="1"
+ layout="topleft"
+ left_delta="4"
+ max_val="100"
+ min_val="1"
+ name="wmiNightVisionNoiseSize"
+ top_pad="20"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-4"
+ name="wmiNightVisionNoiseStrengthText"
+ top_pad="4"
+ width="355">
+ Noise Strength
+ </text>
+ <slider
+ control_name="wmiNightVisionNoiseStrength"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.3"
+ layout="topleft"
+ left_delta="4"
+ name="wmiNightVisionNoiseStrength"
+ top_pad="20"
+ width="200" />
+ </panel>
+ <panel
+ border="true"
+ follows="left|top|right|bottom"
+ height="400"
+ label="Bloom"
+ layout="topleft"
+ left_delta="0"
+ help_topic="post_process_bloom_tab"
+ name="wmiBloomPanel"
+ top_delta="-236"
+ width="398">
+ <check_box
+ control_name="wmiBloomToggle"
+ height="16"
+ label="Enable"
+ layout="topleft"
+ left="14"
+ name="wmiBloomToggle"
+ top="4"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-4"
+ name="wmiBloomExtractText"
+ top_pad="5"
+ width="355">
+ Luminosity Extraction
+ </text>
+ <slider
+ control_name="wmiBloomExtract"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.9"
+ layout="topleft"
+ left_delta="4"
+ name="wmiBloomExtract"
+ top_pad="20"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-4"
+ name="wmiBloomSizeText"
+ top_pad="4"
+ width="355">
+ Bloom Size
+ </text>
+ <slider
+ control_name="wmiBloomSize"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="3.0"
+ layout="topleft"
+ left_delta="4"
+ max_val="20"
+ name="wmiBloomSize"
+ top_pad="20"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-4"
+ name="wmiBloomStrengthText"
+ top_pad="4"
+ width="355">
+ Bloom Strength
+ </text>
+ <slider
+ control_name="wmiBloomStrength"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="1.2"
+ layout="topleft"
+ left_delta="4"
+ max_val="10"
+ name="wmiBloomStrength"
+ top_pad="20"
+ width="200" />
+ </panel>
+ <panel
+ border="true"
+ follows="left|top|right|bottom"
+ height="400"
+ label="Extras"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ help_topic="post_process_extras_tab"
+ name="Extras"
+ top_delta="-236"
+ width="398">
+ <button
+ height="20"
+ label="LoadEffect"
+ label_selected="LoadEffect"
+ layout="topleft"
+ left="15"
+ name="PPLoadEffect"
+ top="13"
+ width="100" />
+ <button
+ height="20"
+ label="SaveEffect"
+ label_selected="SaveEffect"
+ layout="topleft"
+ left_delta="0"
+ name="PPSaveEffect"
+ top_pad="7"
+ width="100" />
+ <combo_box
+ height="18"
+ layout="topleft"
+ left_delta="120"
+ name="PPEffectsCombo"
+ top="15"
+ width="150" />
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|right|bottom"
+ font="SansSerif"
+ height="20"
+ label="Effect Name"
+ layout="topleft"
+ left_delta="0"
+ max_length="40"
+ name="PPEffectNameEditor"
+ tab_group="1"
+ top_pad="22"
+ width="150" />
+ </panel>
+ </tab_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_postcard.xml b/indra/newview/skins/default/xui/en/floater_postcard.xml
new file mode 100644
index 0000000000..3a7b6cc832
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_postcard.xml
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ auto_tile="true"
+ can_minimize="false"
+ can_resize="true"
+ height="380"
+ layout="topleft"
+ min_height="380"
+ min_width="450"
+ name="Postcard"
+ help_topic="postcard"
+ title="EMAIL SNAPSHOT"
+ width="450">
+ <floater.string
+ name="default_subject">
+ Postcard from [SECOND_LIFE].
+ </floater.string>
+ <floater.string
+ name="default_message">
+ Check this out!
+ </floater.string>
+ <floater.string
+ name="upload_message">
+ Sending...
+ </floater.string>
+ <text
+ type="string"
+ length="1"
+ bottom="35"
+ follows="top|left"
+ font="SansSerif"
+ layout="topleft"
+ left="12"
+ name="to_label">
+ Recipient&apos;s Email:
+ </text>
+ <line_editor
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_delta="108"
+ name="to_form"
+ top_delta="-4"
+ width="150" />
+ <text
+ type="string"
+ length="1"
+ bottom_delta="23"
+ follows="top|left"
+ font="SansSerif"
+ layout="topleft"
+ left="12"
+ name="from_label">
+ Your Email:
+ </text>
+ <line_editor
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_delta="108"
+ name="from_form"
+ top_delta="-4"
+ width="150" />
+ <text
+ type="string"
+ length="1"
+ bottom_delta="23"
+ follows="top|left"
+ font="SansSerif"
+ layout="topleft"
+ left="12"
+ name="name_label">
+ Your Name:
+ </text>
+ <line_editor
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_delta="108"
+ max_length="100"
+ name="name_form"
+ top_delta="-4"
+ width="150" />
+ <text
+ type="string"
+ length="1"
+ bottom_delta="23"
+ follows="top|left"
+ font="SansSerif"
+ layout="topleft"
+ left="12"
+ name="subject_label">
+ Subject:
+ </text>
+ <line_editor
+ follows="left|top"
+ height="20"
+ label="Type your subject here."
+ layout="topleft"
+ left_delta="108"
+ max_length="100"
+ name="subject_form"
+ top_delta="-4"
+ width="150" />
+ <text
+ type="string"
+ length="1"
+ bottom_delta="23"
+ follows="top|left"
+ font="SansSerif"
+ layout="topleft"
+ left="12"
+ name="msg_label">
+ Message:
+ </text>
+ <text_editor
+ type="string"
+ length="1"
+ follows="left|top|right|bottom"
+ height="140"
+ layout="topleft"
+ left_delta="0"
+ max_length="700"
+ name="msg_form"
+ word_wrap="true"
+ top_pad="10"
+ width="420">
+ Type your message here.
+ </text_editor>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="37"
+ follows="left|bottom"
+ layout="topleft"
+ left="12"
+ name="fine_print">
+ If your recipient joins SL, you&apos;ll get a referral bonus.
+ </text>
+ <button
+ follows="right|bottom"
+ height="20"
+ label="Cancel"
+ layout="topleft"
+ name="cancel_btn"
+ right="-10"
+ top="350"
+ width="100" />
+ <button
+ follows="right|bottom"
+ height="20"
+ label="Send"
+ layout="topleft"
+ left_delta="-106"
+ name="send_btn"
+ top_delta="0"
+ width="100" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml
new file mode 100644
index 0000000000..15655a920e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_preferences.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ center_horiz="true"
+ center_vert="true"
+ default_tab_group="1"
+ height="460"
+ layout="topleft"
+ name="Preferences"
+ help_topic="preferences"
+ single_instance="true"
+ title="PREFERENCES"
+ width="620">
+ <button
+ follows="right|bottom"
+ height="23"
+ label="OK"
+ label_selected="OK"
+ layout="topleft"
+ right="-105"
+ name="OK"
+ top="433"
+ width="90">
+ <button.commit_callback
+ function="Pref.OK" />
+ </button>
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Cancel"
+ label_selected="Cancel"
+ layout="topleft"
+ left_pad="5"
+ name="Cancel"
+ right="-10"
+ width="90" >
+ <button.commit_callback
+ function="Pref.Cancel" />
+ </button>
+ <tab_container
+ follows="all"
+ height="410"
+ layout="topleft"
+ left="0"
+ name="pref core"
+ tab_group="1"
+ tab_position="left"
+ tab_width="115"
+ top="21"
+ width="620">
+ <panel
+ class="panel_preference"
+ filename="panel_preferences_general.xml"
+ label="General"
+ layout="topleft"
+ help_topic="preferences_general_tab"
+ name="general" />
+ <panel
+ class="panel_preference"
+ filename="panel_preferences_graphics1.xml"
+ label="Graphics"
+ layout="topleft"
+ help_topic="preferences_display_tab"
+ name="display" />
+ <panel
+ class="panel_preference"
+ filename="panel_preferences_privacy.xml"
+ label="Privacy"
+ layout="topleft"
+ help_topic="preferences_im_tab"
+ name="im" />
+ <panel
+ class="panel_preference"
+ filename="panel_preferences_sound.xml"
+ label="Sound"
+ layout="topleft"
+ help_topic="preferences_audio_tab"
+ name="audio" />
+ <panel
+ class="panel_preference"
+ filename="panel_preferences_chat.xml"
+ label="Chat"
+ layout="topleft"
+ help_topic="preferences_chat_tab"
+ name="chat" />
+ <panel
+ class="panel_preference"
+ filename="panel_preferences_alerts.xml"
+ label="Notifications"
+ layout="topleft"
+ help_topic="preferences_msgs_tab"
+ name="msgs" />
+ <panel
+ class="panel_preference"
+ filename="panel_preferences_setup.xml"
+ label="Setup"
+ layout="topleft"
+ help_topic="preferences_input_tab"
+ name="input" />
+ <panel
+ class="panel_preference"
+ filename="panel_preferences_advanced.xml"
+ label="Advanced"
+ layout="topleft"
+ help_topic="preferences_advanced1_tab"
+ name="advanced1" />
+ </tab_container>
+
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preview_animation.xml b/indra/newview/skins/default/xui/en/floater_preview_animation.xml
new file mode 100644
index 0000000000..bbfb362337
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_preview_animation.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ auto_tile="true"
+ height="85"
+ layout="topleft"
+ name="preview_anim"
+ help_topic="preview_anim"
+ width="280">
+ <floater.string
+ name="Title">
+ Animation: [NAME]
+ </floater.string>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="19"
+ layout="topleft"
+ left="10"
+ name="desc txt"
+ top="25"
+ width="80">
+ Description:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ font="SansSerifSmall"
+ height="19"
+ layout="topleft"
+ left_delta="95"
+ max_length="127"
+ name="desc"
+ top="19"
+ width="170" />
+ <button
+ height="20"
+ label="Play in World"
+ label_selected="Stop"
+ layout="topleft"
+ left="10"
+ name="Anim play btn"
+ tool_tip="Play this animation so that others can see it"
+ top="47"
+ width="125" />
+ <button
+ height="20"
+ label="Play Locally"
+ label_selected="Stop"
+ layout="topleft"
+ left_pad="5"
+ name="Anim audition btn"
+ tool_tip="Play this animation so that only you can see it"
+ top_delta="0"
+ width="125" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preview_classified.xml b/indra/newview/skins/default/xui/en/floater_preview_classified.xml
new file mode 100644
index 0000000000..2017cf2bd1
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_preview_classified.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ auto_tile="true"
+ height="510"
+ layout="topleft"
+ name="classified_preview"
+ help_topic="classified_preview"
+ save_rect="true"
+ title="CLASSIFIED INFORMATION"
+ width="440">
+ <floater.string
+ name="Title">
+ Classified: [NAME]
+ </floater.string>
+ <panel
+ follows="bottom|left"
+ height="470"
+ layout="topleft"
+ left="0"
+ name="classified_details_panel"
+ top="20"
+ width="440" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preview_event.xml b/indra/newview/skins/default/xui/en/floater_preview_event.xml
new file mode 100644
index 0000000000..a4066b34c5
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_preview_event.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ auto_tile="true"
+ height="510"
+ layout="topleft"
+ name="event_preview"
+ help_topic="event_preview"
+ save_rect="true"
+ title="EVENT INFORMATION"
+ width="440">
+ <floater.string
+ name="Title">
+ Event: [NAME]
+ </floater.string>
+ <panel
+ follows="bottom|left"
+ height="470"
+ layout="topleft"
+ left="0"
+ name="event_details_panel"
+ top="20"
+ width="440" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preview_gesture.xml b/indra/newview/skins/default/xui/en/floater_preview_gesture.xml
new file mode 100644
index 0000000000..3dc546aee3
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_preview_gesture.xml
@@ -0,0 +1,381 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ auto_tile="true"
+ height="460"
+ layout="topleft"
+ name="gesture_preview"
+ help_topic="gesture_preview"
+ width="280">
+ <floater.string
+ name="step_anim">
+ Animation to play:
+ </floater.string>
+ <floater.string
+ name="step_sound">
+ Sound to play:
+ </floater.string>
+ <floater.string
+ name="step_chat">
+ Chat to say:
+ </floater.string>
+ <floater.string
+ name="step_wait">
+ Wait:
+ </floater.string>
+ <floater.string
+ name="stop_txt">
+ Stop
+ </floater.string>
+ <floater.string
+ name="preview_txt">
+ Preview
+ </floater.string>
+ <floater.string
+ name="none_text">
+ -- None --
+ </floater.string>
+ <floater.string
+ name="Title">
+ Gesture: [NAME]
+ </floater.string>
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifSmall"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="name_text"
+ top="20"
+ font.style="BOLD"
+ width="100">
+ Name:
+ </text>
+ <line_editor
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_delta="84"
+ name="name"
+ top_delta="-4"
+ width="180" />
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifSmall"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="desc_label"
+ top_pad="10"
+ font.style="BOLD"
+ width="100">
+ Description:
+ </text>
+ <line_editor
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_delta="84"
+ name="desc"
+ top_delta="-4"
+ width="180" />
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifSmall"
+ height="10"
+ layout="topleft"
+ left="10"
+ font.style="BOLD"
+ name="trigger_label"
+ top_pad="10"
+ width="100">
+ Trigger:
+ </text>
+ <line_editor
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_delta="84"
+ max_length="31"
+ name="trigger_editor"
+ top_delta="-4"
+ width="180" />
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifSmall"
+ height="10"
+ layout="topleft"
+ left="10"
+ font.style="BOLD"
+ name="replace_text"
+ tool_tip="Replace the trigger word(s) with these words. For example, trigger &apos;hello&apos; replace with &apos;howdy&apos; will turn the chat &apos;I wanted to say hello&apos; into &apos;I wanted to say howdy&apos; as well as playing the gesture!"
+ top_pad="10"
+ width="200">
+ Replace with:
+ </text>
+ <line_editor
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_delta="84"
+ max_length="31"
+ name="replace_editor"
+ tool_tip="Replace the trigger word(s) with these words. For example, trigger &apos;hello&apos; replace with &apos;howdy&apos; will turn the chat &apos;I wanted to say hello&apos; into &apos;I wanted to say howdy&apos; as well as playing the gesture"
+ top_delta="-4"
+ width="180" />
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifSmall"
+ height="10"
+ layout="topleft"
+ left="10"
+ font.style="BOLD"
+ name="key_label"
+ top_pad="10"
+ width="100">
+ Shortcut Key:
+ </text>
+ <combo_box
+ height="20"
+ label="None"
+ layout="topleft"
+ left_delta="84"
+ name="modifier_combo"
+ top_delta="-4"
+ width="75" />
+ <combo_box
+ height="20"
+ label="None"
+ layout="topleft"
+ left_pad="10"
+ name="key_combo"
+ top_delta="0"
+ width="75" />
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifSmall"
+ height="10"
+ layout="topleft"
+ left="10"
+ font.style="BOLD"
+ name="library_label"
+ top="135"
+ width="100">
+ Library:
+ </text>
+ <scroll_list
+ follows="top|left"
+ height="60"
+ layout="topleft"
+ left="10"
+ name="library_list"
+ top="150"
+ width="180">
+ <scroll_list.rows
+ value="Animation" />
+ <scroll_list.rows
+ value="Sound" />
+ <scroll_list.rows
+ value="Chat" />
+ <scroll_list.rows
+ value="Wait" />
+ </scroll_list>
+ <button
+ follows="top|left"
+ height="20"
+ label="Add &gt;&gt;"
+ layout="topleft"
+ left_pad="10"
+ name="add_btn"
+ top_delta="0"
+ width="70" />
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifSmall"
+ height="10"
+ layout="topleft"
+ left="10"
+ font.style="BOLD"
+ name="steps_label"
+ top_pad="50"
+ width="100">
+ Steps:
+ </text>
+ <scroll_list
+ follows="top|left"
+ height="85"
+ layout="topleft"
+ left="10"
+ name="step_list"
+ top_pad="5"
+ width="180" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Up"
+ layout="topleft"
+ left_pad="10"
+ name="up_btn"
+ top_delta="0"
+ width="70" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Down"
+ layout="topleft"
+ left_delta="0"
+ name="down_btn"
+ top_pad="10"
+ width="70" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Remove"
+ layout="topleft"
+ left_delta="0"
+ name="delete_btn"
+ top_pad="10"
+ width="70" />
+ <text
+ follows="top|left"
+ height="60"
+ layout="topleft"
+ left="15"
+ name="options_text"
+ top="330"
+ width="205" />
+ <combo_box
+ follows="top|left"
+ height="20"
+ layout="topleft"
+ left_delta="15"
+ name="animation_list"
+ top="345"
+ width="100" />
+ <combo_box
+ follows="top|left"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="sound_list"
+ top_delta="0"
+ width="100" />
+ <line_editor
+ follows="top|left"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ max_length="127"
+ name="chat_editor"
+ top_delta="0"
+ width="100" />
+ <radio_group
+ draw_border="false"
+ follows="top|left"
+ height="40"
+ layout="topleft"
+ left_pad="8"
+ name="animation_trigger_type"
+ top_delta="0"
+ width="80">
+ <radio_item
+ height="16"
+ label="Start"
+ layout="topleft"
+ left="3"
+ name="start"
+ top="-11"
+ width="80" />
+ <radio_item
+ height="16"
+ label="Stop"
+ layout="topleft"
+ left_delta="0"
+ name="stop"
+ top_pad="10"
+ width="80" />
+ </radio_group>
+ <check_box
+ follows="top|left"
+ height="20"
+ label="until animations are done"
+ layout="topleft"
+ left="16"
+ name="wait_anim_check"
+ top="340"
+ width="100" />
+ <check_box
+ follows="top|left"
+ height="20"
+ label="time in seconds"
+ layout="topleft"
+ left_delta="0"
+ name="wait_time_check"
+ top_delta="20"
+ width="100" />
+ <line_editor
+ follows="top|left"
+ height="20"
+ layout="topleft"
+ left_pad="5"
+ max_length="15"
+ name="wait_time_editor"
+ top_delta="0"
+ width="50" />
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifSmall"
+ height="30"
+ layout="topleft"
+ left="10"
+ name="help_label"
+ top_pad="20"
+ word_wrap="true"
+ width="265">
+ All steps happen simultaneously, unless you add wait steps.
+ </text>
+ <check_box
+ follows="top|left"
+ height="20"
+ label="Active"
+ layout="topleft"
+ left="20"
+ name="active_check"
+ tool_tip="Active gestures can be triggered by chatting their trigger phrases or pressing their hot keys. Gestures usually become inactive when there is a key binding conflict."
+ top_pad="0"
+ width="100" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Preview"
+ layout="topleft"
+ left_delta="75"
+ name="preview_btn"
+ top_delta="2"
+ width="80" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Save"
+ layout="topleft"
+ left_pad="10"
+ name="save_btn"
+ top_delta="0"
+ width="80" />
+</floater> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/floater_preview_gesture_info.xml b/indra/newview/skins/default/xui/en/floater_preview_gesture_info.xml
new file mode 100644
index 0000000000..66408a5057
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_preview_gesture_info.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ follows="left|top"
+ height="155"
+ layout="topleft"
+ name="Gesture"
+ help_topic="gesture"
+ save_rect="true"
+ title="GESTURE SHORTCUT"
+ width="260">
+ <scroll_list
+ follows="top|left"
+ height="110"
+ layout="topleft"
+ left="10"
+ name="library_list"
+ top="10"
+ width="240">
+ <scroll_list.rows
+ value="Animation" />
+ <scroll_list.rows
+ value="Sound" />
+ <scroll_list.rows
+ value="Chat" />
+ <scroll_list.rows
+ value="Wait" />
+ </scroll_list>
+ <!--button
+ follows="top|left"
+ height="20"
+ label="Preview"
+ layout="topleft"
+ left="20"
+ name="preview_btn"
+ top_pad="50"
+ width="80" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Save"
+ layout="topleft"
+ left_pad="5"
+ name="save_btn"
+ top_delta="0"
+ width="80" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Cancel (not working)"
+ layout="topleft"
+ left_pad="5"
+ name="save_btn"
+ top_delta="0"
+ width="80" /-->
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preview_gesture_shortcut.xml b/indra/newview/skins/default/xui/en/floater_preview_gesture_shortcut.xml
new file mode 100644
index 0000000000..26252a7a16
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_preview_gesture_shortcut.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ follows="left|top"
+ height="90"
+ layout="topleft"
+ name="Gesture"
+ help_topic="gesture"
+ save_rect="true"
+ title="GESTURE SHORTCUT"
+ width="260">
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifSmall"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="trigger_label"
+ top_pad="10"
+ width="100">
+ Chat:
+ </text>
+ <line_editor
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="5"
+ max_length="31"
+ name="trigger_editor"
+ top_delta="-4"
+ width="135" />
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifSmall"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="key_label"
+ top_pad="10"
+ width="100">
+ Keyboard:
+ </text>
+ <combo_box
+ height="20"
+ label="None"
+ layout="topleft"
+ left_pad="13"
+ name="modifier_combo"
+ top_delta="-4"
+ width="50" />
+ <combo_box
+ height="20"
+ label="None"
+ layout="topleft"
+ left_pad="5"
+ name="key_combo"
+ top_delta="0"
+ width="45" />
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifSmall"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="replace_text"
+ tool_tip="Replace the trigger word(s) with these words. For example, trigger &apos;hello&apos; replace with &apos;howdy&apos; will turn the chat &apos;I wanted to say hello&apos; into &apos;I wanted to say howdy&apos; as well as playing the gesture!"
+ top_pad="10"
+ width="100">
+ Replace:
+ </text>
+ <line_editor
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="5"
+ max_length="31"
+ name="replace_editor"
+ tool_tip="Replace the trigger word(s) with these words. For example, trigger &apos;hello&apos; replace with &apos;howdy&apos; will turn the chat &apos;I wanted to say hello&apos; into &apos;I wanted to say howdy&apos; as well as playing the gesture"
+ top_delta="-4"
+ width="135" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preview_gesture_steps.xml b/indra/newview/skins/default/xui/en/floater_preview_gesture_steps.xml
new file mode 100644
index 0000000000..34f707cd2a
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_preview_gesture_steps.xml
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ follows="left|top"
+ height="155"
+ layout="topleft"
+ name="Gesture"
+ help_topic="gesture"
+ save_rect="true"
+ title="GESTURE SHORTCUT"
+ width="260">
+ <scroll_list
+ follows="top|left"
+ height="110"
+ layout="topleft"
+ left="10"
+ name="step_list"
+ top_pad="10"
+ width="240" />
+ <!--text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifSmall"
+ height="60"
+ layout="topleft"
+ left="10"
+ name="help_label"
+ top_pad="10"
+ width="200">
+ All steps happen simultaneously,
+unless you add wait steps.
+ </text-->
+ <!--text
+ follows="top|left"
+ height="60"
+ layout="topleft"
+ left="10"
+ name="options_text"
+ top_pad="10"
+ width="205" /-->
+ <!--combo_box
+ follows="top|left"
+ height="20"
+ layout="topleft"
+ left_delta="10"
+ name="animation_list"
+ top_pad="10"
+ width="100" />
+ <combo_box
+ follows="top|left"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="sound_list"
+ top_delta="10"
+ width="100" />
+ <line_editor
+ follows="top|left"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ max_length="127"
+ name="chat_editor"
+ top_pad="10"
+ width="100" />
+ <radio_group
+ draw_border="false"
+ follows="top|left"
+ height="40"
+ layout="topleft"
+ left_pad="8"
+ name="animation_trigger_type"
+ top_pad="10"
+ width="80">
+ <radio_item
+ height="16"
+ label="Start"
+ layout="topleft"
+ left="3"
+ name="start"
+ top="-11"
+ width="80" />
+ <radio_item
+ height="16"
+ label="Stop"
+ layout="topleft"
+ left_delta="0"
+ name="stop"
+ top_pad="10"
+ width="80" />
+ </radio_group>
+ <check_box
+ follows="top|left"
+ height="20"
+ label="until animations are done"
+ layout="topleft"
+ left="16"
+ name="wait_anim_check"
+ top_pad="10"
+ width="100" />
+ <check_box
+ follows="top|left"
+ height="20"
+ label="time in seconds"
+ layout="topleft"
+ left_delta="0"
+ name="wait_time_check"
+ top_pad="10"
+ width="100" />
+ <line_editor
+ follows="top|left"
+ height="20"
+ layout="topleft"
+ left_pad="5"
+ max_length="15"
+ name="wait_time_editor"
+ top_pad="10"
+ width="50" /-->
+
+
+
+ <!--For pop out floater-->
+ <!--scroll_list
+ follows="top|left"
+ height="110"
+ layout="topleft"
+ left="10"
+ name="library_list"
+ top_pad="10"
+ width="260">
+ <scroll_list.rows
+ value="Animation" />
+ <scroll_list.rows
+ value="Sound" />
+ <scroll_list.rows
+ value="Chat" />
+ <scroll_list.rows
+ value="Wait" />
+ </scroll_list>
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifSmall"
+ height="60"
+ layout="topleft"
+ left="10"
+ name="help_label"
+ top_pad="10"
+ width="200">
+ All steps happen simultaneously,
+unless you add wait steps.
+ </text>
+ <text
+ follows="top|left"
+ height="60"
+ layout="topleft"
+ left="10"
+ name="options_text"
+ top_pad="10"
+ width="205" />
+ <combo_box
+ follows="top|left"
+ height="20"
+ layout="topleft"
+ left_delta="10"
+ name="animation_list"
+ top_pad="10"
+ width="100" />
+ <combo_box
+ follows="top|left"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="sound_list"
+ top_delta="0"
+ width="100" />
+ <line_editor
+ follows="top|left"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ max_length="127"
+ name="chat_editor"
+ top_delta="0"
+ width="100" />
+ <radio_group
+ draw_border="false"
+ follows="top|left"
+ height="40"
+ layout="topleft"
+ left_pad="8"
+ name="animation_trigger_type"
+ top="445"
+ width="80">
+ <radio_item
+ height="16"
+ label="Start"
+ layout="topleft"
+ left="3"
+ name="start"
+ top="-11"
+ width="80" />
+ <radio_item
+ height="16"
+ label="Stop"
+ layout="topleft"
+ left_delta="0"
+ name="stop"
+ top_pad="10"
+ width="80" />
+ </radio_group>
+ <check_box
+ follows="top|left"
+ height="20"
+ label="until animations are done"
+ layout="topleft"
+ left="16"
+ name="wait_anim_check"
+ top="430"
+ width="100" />
+ <check_box
+ follows="top|left"
+ height="20"
+ label="time in seconds"
+ layout="topleft"
+ left_delta="0"
+ name="wait_time_check"
+ top_delta="20"
+ width="100" />
+ <line_editor
+ follows="top|left"
+ height="20"
+ layout="topleft"
+ left_pad="5"
+ max_length="15"
+ name="wait_time_editor"
+ top_delta="0"
+ width="50" /-->
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
new file mode 100644
index 0000000000..ead5b8c8f2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ auto_tile="true"
+ can_resize="true"
+ default_tab_group="1"
+ follows="left|top"
+ height="361"
+ layout="topleft"
+ min_height="243"
+ min_width="234"
+ name="preview notecard"
+ help_topic="preview_notecard"
+ title="NOTECARD:"
+ width="400">
+ <floater.string
+ name="no_object">
+ Unable to find object containing this notecard.
+ </floater.string>
+ <floater.string
+ name="not_allowed">
+ You do not have permission to view this notecard.
+ </floater.string>
+ <floater.string
+ name="Title">
+ Notecard: [NAME]
+ </floater.string>
+ <floater.string
+ name="Save">
+ Save
+ </floater.string>
+ <icon
+ follows="top|right"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ left="322"
+ mouse_opaque="true"
+ name="lock"
+ top="4"
+ width="18" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="19"
+ layout="topleft"
+ left="10"
+ name="desc txt"
+ top="22"
+ width="90">
+ Description:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="22"
+ layout="topleft"
+ left_pad="0"
+ max_length="127"
+ name="desc"
+ width="296" />
+ <text_editor
+ type="string"
+ length="1"
+ embedded_items="true"
+ follows="left|top|right|bottom"
+ font="SansSerif"
+ height="281"
+ ignore_tab="false"
+ layout="topleft"
+ left="4"
+ max_length="65536"
+ name="Notecard Editor"
+ allow_html="false"
+ handle_edit_keys_directly="true"
+ tab_group="1"
+ top="46"
+ width="392"
+ word_wrap="true">
+ Loading...
+ </text_editor>
+ <button
+ follows="right|bottom"
+ height="22"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ left="288"
+ name="Save"
+ top="332"
+ width="100" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preview_sound.xml b/indra/newview/skins/default/xui/en/floater_preview_sound.xml
new file mode 100644
index 0000000000..68a78d5017
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_preview_sound.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ auto_tile="true"
+ height="85"
+ layout="topleft"
+ name="preview_sound"
+ help_topic="preview_sound"
+ width="280">
+ <floater.string
+ name="Title">
+ Sound: [NAME]
+ </floater.string>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="19"
+ layout="topleft"
+ left="10"
+ top="22"
+ name="desc txt"
+ 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="127"
+ name="desc"
+ width="170" />
+ <button
+ follows="left|top"
+ height="22"
+ label="Play in World"
+ label_selected="Play in World"
+ layout="topleft"
+ name="Sound play btn"
+ sound_flags="0"
+ top="55"
+ left="10"
+ tool_tip="Play this sound so that others can hear it"
+ width="125" />
+ <button
+ follows="left|top"
+ height="22"
+ label="Play Locally"
+ label_selected="Play Locally"
+ layout="topleft"
+ name="Sound audition btn"
+ sound_flags="0"
+ tool_tip="Play this sound so that only you can hear it"
+ left_pad="10"
+ width="125" />
+
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preview_texture.xml b/indra/newview/skins/default/xui/en/floater_preview_texture.xml
new file mode 100644
index 0000000000..0d155fb01e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_preview_texture.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ auto_tile="true"
+ can_resize="true"
+ follows="left|top"
+ height="350"
+ layout="topleft"
+ min_height="200"
+ min_width="370"
+ name="preview_texture"
+ help_topic="preview_texture"
+ width="370">
+ <floater.string
+ name="Title">
+ Texture: [NAME]
+ </floater.string>
+ <floater.string
+ 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="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_item name="Unconstrained" value="Unconstrained">
+ Unconstrained
+ </combo_item>
+ <combo_item name="1:1" value="1:1" tool_tip="Group insignia or Real World profile">
+ 1:1
+ </combo_item>
+ <combo_item name="4:3" value="4:3" tool_tip="[SECOND_LIFE] profile">
+ 4:3
+ </combo_item>
+ <combo_item name="10:7" value="10:7" tool_tip="Classifieds and search listings, landmarks">
+ 10:7
+ </combo_item>
+ <combo_item name="3:2" value="3:2" tool_tip="About land">
+ 3:2
+ </combo_item>
+ <combo_item name="16:10" value="16:10">
+ 16:10
+ </combo_item>
+ <combo_item name="16:9" value="16:9" tool_tip="Profile picks">
+ 16:9
+ </combo_item>
+ <combo_item name="2:1" value="2:1">
+ 2:1
+ </combo_item>
+ </combo_box>
+ <button
+ follows="right|bottom"
+ height="22"
+ label="OK"
+ layout="topleft"
+ left="6"
+ name="Keep"
+ top_pad="5"
+ width="100" />
+ <button
+ follows="right|bottom"
+ height="22"
+ label="Cancel"
+ layout="topleft"
+ left_pad="5"
+ name="Discard"
+ top_delta="0"
+ width="100" />
+ <button
+ follows="right|bottom"
+ height="22"
+ label="Save As"
+ layout="topleft"
+ left_pad="5"
+ name="save_tex_btn"
+ top_delta="0"
+ width="100" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_region_info.xml b/indra/newview/skins/default/xui/en/floater_region_info.xml
new file mode 100644
index 0000000000..262bcd07a0
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_region_info.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="555"
+ help_topic="regioninfo"
+ layout="topleft"
+ name="regioninfo"
+ save_rect="true"
+ title="REGION/ESTATE"
+ width="480">
+ <tab_container
+ bottom="555"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="1"
+ name="region_panels"
+ right="-1"
+ tab_position="top"
+ top="20" />
+</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
new file mode 100644
index 0000000000..aa219b9615
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
@@ -0,0 +1,514 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="580"
+ layout="topleft"
+ name="floater_report_abuse"
+ help_topic="floater_report_abuse"
+ title="REPORT ABUSE"
+ width="333">
+ <floater.string
+ name="Screenshot">
+ Screenshot
+ </floater.string>
+ <texture_picker
+ allow_no_texture="true"
+ default_image_name="None"
+ follows="left|top"
+ height="150"
+ layout="topleft"
+ left="60"
+ name="screenshot"
+ top="15"
+ width="220" />
+ <check_box
+ height="15"
+ label="Use this screenshot"
+ layout="topleft"
+ left="8"
+ name="screen_check"
+ top_pad="-12"
+ width="116" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ font.name="SansSerif"
+ font.style="BOLD"
+ layout="topleft"
+ left="10"
+ name="reporter_title"
+ top_pad="0"
+ width="100">
+ Reporter:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="5"
+ name="reporter_field"
+ top_delta="0"
+ use_ellipses="true"
+ width="200">
+ Loremipsum Dolorsitamut Longnamez
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ font.name="SansSerif"
+ font.style="BOLD"
+ layout="topleft"
+ left="10"
+ name="sim_title"
+ top_pad="2"
+ width="100">
+ Region:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="5"
+ name="sim_field"
+ top_delta="0"
+ use_ellipses="true"
+ width="200">
+ Region Name
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ font.name="SansSerif"
+ font.style="BOLD"
+ layout="topleft"
+ left="10"
+ name="pos_title"
+ top_pad="2"
+ width="100">
+ Position:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="5"
+ name="pos_field"
+ top_delta="0"
+ width="200">
+ {128.1, 128.1, 15.4}
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="select_object_label"
+ top_pad="2"
+ width="310">
+ Click the button, then the abusive object:
+ </text>
+ <button
+ height="32"
+ layout="topleft"
+ left_delta="0"
+ name="pick_btn"
+ image_overlay="Inv_Object"
+ tool_tip="Object Picker - Identify an object as the subject of this report"
+ top_pad="0"
+ width="32" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ font.name="SansSerif"
+ font.style="BOLD"
+ layout="topleft"
+ left="48"
+ name="object_name_label"
+ top_delta="0"
+ width="80">
+ Object:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="6"
+ name="object_name"
+ top_delta="0"
+ use_ellipses="true"
+ width="185">
+ Consetetur Sadipscing
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ font.name="SansSerif"
+ font.style="BOLD"
+ layout="topleft"
+ left="48"
+ name="owner_name_label"
+ top_pad="0"
+ width="80">
+ Owner:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="6"
+ name="owner_name"
+ top_delta="0"
+ use_ellipses="true"
+ width="185">
+ Hendrerit Vulputate Kamawashi Longname
+ </text>
+ <combo_box
+ height="23"
+ layout="topleft"
+ left="10"
+ name="category_combo"
+ tool_tip="Category -- select the category that best describes this report"
+ top_pad="5"
+ width="313">
+ <combo_box.item
+ label="Select category"
+ name="Select_category"
+ value="0" />
+ <combo_box.item
+ label="Age &gt; Age play"
+ name="Age__Age_play"
+ value="31" />
+ <combo_box.item
+ label="Age &gt; Adult Resident on Teen Second Life"
+ name="Age__Adult_resident_on_Teen_Second_Life"
+ value="32" />
+ <combo_box.item
+ label="Age &gt; Underage Resident outside of Teen Second Life"
+ name="Age__Underage_resident_outside_of_Teen_Second_Life"
+ value="33" />
+ <combo_box.item
+ label="Assault &gt; Combat sandbox / unsafe area"
+ name="Assault__Combat_sandbox___unsafe_area"
+ value="34" />
+ <combo_box.item
+ label="Assault &gt; Safe area"
+ name="Assault__Safe_area"
+ value="35" />
+ <combo_box.item
+ label="Assault &gt; Weapons testing sandbox"
+ name="Assault__Weapons_testing_sandbox"
+ value="36" />
+ <combo_box.item
+ label="Commerce &gt; Failure to deliver product or service"
+ name="Commerce__Failure_to_deliver_product_or_service"
+ value="38" />
+ <combo_box.item
+ label="Disclosure &gt; Real world information"
+ name="Disclosure__Real_world_information"
+ value="39" />
+ <combo_box.item
+ label="Disclosure &gt; Remotely monitoring chat"
+ name="Disclosure__Remotely_monitoring chat"
+ value="40" />
+ <combo_box.item
+ label="Disclosure &gt; Second Life information/chat/IMs"
+ name="Disclosure__Second_Life_information_chat_IMs"
+ value="41" />
+ <combo_box.item
+ label="Disturbing the peace &gt; Unfair use of region resources"
+ name="Disturbing_the_peace__Unfair_use_of_region_resources"
+ value="42" />
+ <combo_box.item
+ label="Disturbing the peace &gt; Excessive scripted objects"
+ name="Disturbing_the_peace__Excessive_scripted_objects"
+ value="43" />
+ <combo_box.item
+ label="Disturbing the peace &gt; Object littering"
+ name="Disturbing_the_peace__Object_littering"
+ value="44" />
+ <combo_box.item
+ label="Disturbing the peace &gt; Repetitive spam"
+ name="Disturbing_the_peace__Repetitive_spam"
+ value="45" />
+ <combo_box.item
+ label="Disturbing the peace &gt; Unwanted advert spam"
+ name="Disturbing_the_peace__Unwanted_advert_spam"
+ value="46" />
+ <combo_box.item
+ label="Fraud &gt; L$"
+ name="Fraud__L$"
+ value="47" />
+ <combo_box.item
+ label="Fraud &gt; Land"
+ name="Fraud__Land"
+ value="48" />
+ <combo_box.item
+ label="Fraud &gt; Pyramid scheme or chain letter"
+ name="Fraud__Pyramid_scheme_or_chain_letter"
+ value="49" />
+ <combo_box.item
+ label="Fraud &gt; US$"
+ name="Fraud__US$"
+ value="50" />
+ <combo_box.item
+ label="Harassment &gt; Advert farms / visual spam"
+ name="Harassment__Advert_farms___visual_spam"
+ value="51" />
+ <combo_box.item
+ label="Harassment &gt; Defaming individuals or groups"
+ name="Harassment__Defaming_individuals_or_groups"
+ value="52" />
+ <combo_box.item
+ label="Harassment &gt; Impeding movement"
+ name="Harassment__Impeding_movement"
+ value="53" />
+ <combo_box.item
+ label="Harassment &gt; Sexual harassment"
+ name="Harassment__Sexual_harassment"
+ value="54" />
+ <combo_box.item
+ label="Harassment &gt; Solicting/inciting others to violate ToS"
+ name="Harassment__Solicting_inciting_others_to_violate_ToS"
+ value="55" />
+ <combo_box.item
+ label="Harassment &gt; Verbal abuse"
+ name="Harassment__Verbal_abuse"
+ value="56" />
+ <combo_box.item
+ label="Indecency &gt; Broadly offensive content or conduct"
+ name="Indecency__Broadly_offensive_content_or_conduct"
+ value="57" />
+ <combo_box.item
+ label="Indecency &gt; Inappropriate avatar name"
+ name="Indecency__Inappropriate_avatar_name"
+ value="59" />
+ <combo_box.item
+ label="Indecency &gt; Inappropriate content or conduct in a PG region"
+ name="Indecency__Mature_content_in_PG_region"
+ value="60" />
+ <combo_box.item
+ label="Indecency &gt; Inappropriate content or conduct in a Moderate region"
+ name="Indecency__Inappropriate_content_in_Mature_region"
+ value="69" />
+ <combo_box.item
+ label="Intellectual property infringement &gt; Content Removal"
+ name="Intellectual_property_infringement_Content_Removal"
+ value="66" />
+ <combo_box.item
+ label="Intellectual property infringement &gt; CopyBot or Permissions Exploit"
+ name="Intellectual_property_infringement_CopyBot_or_Permissions_Exploit"
+ value="37" />
+ <combo_box.item
+ label="Intolerance"
+ name="Intolerance"
+ value="61" />
+ <combo_box.item
+ label="Land &gt; Abuse of sandbox resources"
+ name="Land__Abuse_of_sandbox_resources"
+ value="62" />
+ <combo_box.item
+ label="Land &gt; Encroachment &gt; Objects/textures"
+ name="Land__Encroachment__Objects_textures"
+ value="63" />
+ <combo_box.item
+ label="Land &gt; Encroachment &gt; Particles"
+ name="Land__Encroachment__Particles"
+ value="64" />
+ <combo_box.item
+ label="Land &gt; Encroachment &gt; Trees/plants"
+ name="Land__Encroachment__Trees_plants"
+ value="65" />
+ <combo_box.item
+ label="Wagering/gambling"
+ name="Wagering_gambling"
+ value="67" />
+ <combo_box.item
+ label="Other"
+ name="Other"
+ value="68" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="14"
+ font.name="SansSerif"
+ font.style="BOLD"
+ layout="topleft"
+ left_delta="0"
+ name="abuser_name_title"
+ top_pad="6"
+ width="313">
+ Abuser name:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left_delta="0"
+ max_length="32"
+ name="abuser_name_edit"
+ top_pad="0"
+ width="195" />
+ <button
+ height="23"
+ label="Choose"
+ layout="topleft"
+ left_pad="5"
+ name="select_abuser"
+ tool_tip="Select the name of the abuser from a list"
+ top_delta="0"
+ width="100" />
+<!-- <check_box
+ height="23"
+ label="Don&apos;t know abuser&apos;s name"
+ layout="topleft"
+ left="10"
+ name="omit_abuser_name"
+ tool_tip="Check this if you are unable to provide the abuser&apos;s name"
+ top_pad="2"
+ visible="false"
+ width="250" />-->
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="14"
+ font.name="SansSerif"
+ font.style="BOLD"
+ layout="topleft"
+ left="10"
+ name="abuser_name_title2"
+ top_pad="2"
+ width="313">
+ Location of Abuse:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left="10"
+ max_length="256"
+ name="abuse_location_edit"
+ top_pad="0"
+ width="313" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ font.name="SansSerif"
+ font.style="BOLD"
+ layout="topleft"
+ left_delta="0"
+ name="sum_title"
+ top_pad="2"
+ width="313">
+ Summary:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left_delta="0"
+ max_length="64"
+ name="summary_edit"
+ top_pad="0"
+ width="313" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="14"
+ font.name="SansSerif"
+ font.style="BOLD"
+ layout="topleft"
+ left_delta="0"
+ name="dscr_title"
+ top_pad="5"
+ width="50">
+ Details:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ name="bug_aviso"
+ left_pad="10"
+ width="200">
+ Please be as specific as possible
+ </text>
+ <text_editor
+ follows="left|top"
+ height="75"
+ layout="topleft"
+ left="10"
+ max_length="800"
+ mouse_opaque="false"
+ name="details_edit"
+ width="313"
+ word_wrap="true" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="30"
+ layout="topleft"
+ left="10"
+ font.name="SansSerifSmall"
+ name="incomplete_title"
+ top_pad="2"
+ word_wrap="true"
+ width="313">
+ * Incomplete reports won't be investigated
+ </text>
+ <button
+ left="80"
+ follows="left|top"
+ height="23"
+ top="550"
+ label="Report Abuse"
+ label_selected="Report Abuse"
+ layout="topleft"
+ name="send_btn"
+ width="140" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Cancel"
+ label_selected="Cancel"
+ layout="topleft"
+ name="cancel_btn"
+ left_pad="5"
+ width="100" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_script.xml b/indra/newview/skins/default/xui/en/floater_script.xml
new file mode 100644
index 0000000000..c3e974d978
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_script.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ background_visible="true"
+ follows="left|top|right|bottom"
+ height="369"
+ layout="topleft"
+ left="0"
+ name="script_floater"
+ top="0"
+ can_dock="true"
+ can_minimize="true"
+ visible="true"
+ width="520"
+ can_resize="true"
+ min_width="350"
+ min_height="369">
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_script_debug.xml b/indra/newview/skins/default/xui/en/floater_script_debug.xml
new file mode 100644
index 0000000000..53d4925214
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_script_debug.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<multi_floater
+ can_resize="true"
+ height="233"
+ layout="topleft"
+ name="script debug floater"
+ help_topic="script_debug_floater"
+ save_rect="true"
+ title="Script Warning/Error"
+ width="450">
+ <tab_container
+ follows="left|top|right|bottom"
+ height="217"
+ layout="topleft"
+ left="1"
+ name="Preview Tabs"
+ tab_position="bottom"
+ top="16"
+ width="448" />
+</multi_floater>
diff --git a/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml b/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml
new file mode 100644
index 0000000000..bd9925be1d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ follows="left|top|right|bottom"
+ height="200"
+ layout="topleft"
+ name="script"
+ help_topic="script"
+ short_title="[ALL SCRIPTS]"
+ title="[ALL SCRIPTS]"
+ width="440">
+ <text_editor
+ bottom="197"
+ follows="left|top|right|bottom"
+ height="176"
+ layout="topleft"
+ max_length="10000"
+ name="Chat History Editor"
+ parse_highlights="true"
+ width="420"
+ word_wrap="true" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_script_limits.xml b/indra/newview/skins/default/xui/en/floater_script_limits.xml
new file mode 100644
index 0000000000..98c44ad1b3
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_script_limits.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="570"
+ help_topic="scriptlimits"
+ layout="topleft"
+ name="scriptlimits"
+ save_rect="true"
+ title="SCRIPT INFORMATION"
+ width="480">
+ <tab_container
+ bottom="555"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="1"
+ name="scriptlimits_panels"
+ right="-1"
+ tab_position="top"
+ top="20" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_script_preview.xml b/indra/newview/skins/default/xui/en/floater_script_preview.xml
new file mode 100644
index 0000000000..bb0702c353
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_script_preview.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ auto_tile="true"
+ can_resize="true"
+ height="550"
+ layout="topleft"
+ left_delta="343"
+ min_height="271"
+ min_width="290"
+ name="preview lsl text"
+ help_topic="preview_lsl_text"
+ save_rect="true"
+ title="SCRIPT: ROTATION SCRIPT"
+ top_delta="0"
+ width="500">
+ <floater.string
+ name="Title">
+ Script: [NAME]
+ </floater.string>
+ <panel
+ follows="left|top|right|bottom"
+ height="508"
+ layout="topleft"
+ left="0"
+ name="script panel"
+ top="42"
+ width="497" />
+ <icon
+ follows="top|right"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ left="426"
+ mouse_opaque="true"
+ name="lock"
+ top="4"
+ width="18" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="19"
+ layout="topleft"
+ left="13"
+ name="desc txt"
+ top="19"
+ width="80">
+ Description:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="19"
+ layout="topleft"
+ left_delta="80"
+ max_length="127"
+ name="desc"
+ top_delta="0"
+ width="394" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_script_queue.xml b/indra/newview/skins/default/xui/en/floater_script_queue.xml
new file mode 100644
index 0000000000..60a26fcf1d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_script_queue.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ auto_tile="true"
+ can_resize="true"
+ height="400"
+ layout="topleft"
+ name="queue"
+ help_topic="queue"
+ save_rect="true"
+ title="RESET PROGRESS"
+ width="300">
+ <floater.string
+ name="Starting">
+ Starting [START] of [COUNT] items.
+ </floater.string>
+ <floater.string
+ name="Done">
+ Done.
+ </floater.string>
+ <floater.string
+ name="Resetting">
+ Resetting
+ </floater.string>
+ <floater.string
+ name="Running">
+ Running
+ </floater.string>
+ <floater.string
+ name="NotRunning">
+ Not running
+ </floater.string>
+ <button
+ follows="right|bottom"
+ height="24"
+ label="Close"
+ label_selected="Close"
+ layout="topleft"
+ left="220"
+ name="close"
+ top="368"
+ width="64" />
+ <scroll_list
+ follows="left|top|right|bottom"
+ height="344"
+ layout="topleft"
+ left="4"
+ name="queue output"
+ top="20"
+ width="292" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_script_search.xml b/indra/newview/skins/default/xui/en/floater_script_search.xml
new file mode 100644
index 0000000000..ade0156bc7
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_script_search.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ default_tab_group="1"
+ height="120"
+ layout="topleft"
+ name="script search"
+ help_topic="script_search"
+ title="SCRIPT SEARCH"
+ width="300">
+ <check_box
+ control_name="LSLFindCaseInsensitivity"
+ height="16"
+ label="Case Insensitive"
+ layout="topleft"
+ left="55"
+ name="case_text"
+ top="61"
+ width="240" />
+ <button
+ height="24"
+ label="Search"
+ label_selected="Search"
+ layout="topleft"
+ left="10"
+ name="search_btn"
+ top="84"
+ width="90" />
+ <button
+ height="24"
+ label="Replace"
+ label_selected="Replace"
+ layout="topleft"
+ left_pad="5"
+ name="replace_btn"
+ top_delta="0"
+ width="90" />
+ <button
+ height="24"
+ label="Replace All"
+ label_selected="Replace All"
+ layout="topleft"
+ left_pad="5"
+ name="replace_all_btn"
+ top_delta="0"
+ width="90" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="5"
+ name="txt"
+ top="21"
+ width="45">
+ Search
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="txt2"
+ top_pad="5"
+ width="45">
+ Replace
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="55"
+ name="search_text"
+ tab_group="1"
+ top="21"
+ width="240" />
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="replace_text"
+ top_pad="5"
+ width="240" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_search.xml b/indra/newview/skins/default/xui/en/floater_search.xml
new file mode 100644
index 0000000000..b0bb282abd
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_search.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="13"
+ can_resize="true"
+ height="646"
+ layout="topleft"
+ min_height="646"
+ min_width="670"
+ name="floater_search"
+ help_topic="floater_search"
+ save_rect="true"
+ single_instance="true"
+ title="FIND"
+ width="670">
+ <floater.string
+ name="loading_text">
+ Loading...
+ </floater.string>
+ <floater.string
+ name="done_text">
+ Done
+ </floater.string>
+ <layout_stack
+ bottom="641"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="10"
+ name="stack1"
+ top="20"
+ width="650">
+ <layout_panel
+ layout="topleft"
+ left_delta="0"
+ top_delta="0"
+ name="browser_layout"
+ user_resize="false"
+ width="650">
+ <web_browser
+ bottom="-10"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="0"
+ name="browser"
+ top="0"
+ height="600"
+ width="650" />
+ <text
+ follows="bottom|left"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="status_text"
+ top_pad="7"
+ width="150" />
+ <text
+ visible="false"
+ follows="bottom|right"
+ height="16"
+ left_delta="0"
+ name="refresh_search"
+ left_pad="0"
+ right="-10"
+ halign="right"
+ width="450">
+ Redo search to reflect current God level
+ </text>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_select_key.xml b/indra/newview/skins/default/xui/en/floater_select_key.xml
new file mode 100644
index 0000000000..4e89df5a73
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_select_key.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ border="false"
+ can_close="false"
+ can_minimize="false"
+ height="90"
+ layout="topleft"
+ name="modal container"
+ width="240">
+ <text
+ type="string"
+ halign="center"
+ length="1"
+ follows="left|top"
+ height="30"
+ layout="topleft"
+ left="30"
+ name="Save item as:"
+ top="25"
+ word_wrap="true"
+ width="180">
+ Press a key to set your Speak button trigger.
+ </text>
+ <button
+ height="23"
+ label="Cancel"
+ label_selected="Cancel"
+ layout="topleft"
+ right="-10"
+ name="Cancel"
+ top_pad="8"
+ width="100" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_sell_land.xml b/indra/newview/skins/default/xui/en/floater_sell_land.xml
new file mode 100644
index 0000000000..afc44c41b8
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_sell_land.xml
@@ -0,0 +1,253 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ can_resize="true"
+ height="535"
+ layout="topleft"
+ name="sell land"
+ help_topic="sell_land"
+ single_instance="true"
+ title="SELL LAND"
+ width="313">
+ <scroll_container
+ color="DkGray2"
+ follows="left|top|right|bottom"
+ height="520"
+ layout="topleft"
+ name="profile_scroll"
+ reserve_scroll_corner="true"
+ opaque="true"
+ top="15"
+ width="313">
+ <panel
+ name="scroll_content_panel"
+ follows="left|top|right"
+ layout="topleft"
+ top="0"
+ left="0"
+ width="293"
+ height="615">
+ <texture_picker
+ enabled="false"
+ follows="top|left"
+ height="135"
+ left="60"
+ name="info_image"
+ top="20"
+ width="180" />
+ <text
+ top="150"
+ follows="top|left"
+ left="16"
+ name="info_parcel_label"
+ width="48">
+ Parcel:
+ </text>
+ <text
+ top_delta="0"
+ follows="top|left"
+ height="16"
+ left="56"
+ name="info_parcel"
+ right="-20">
+ PARCEL NAME
+ </text>
+ <text
+ follows="top|left"
+ left="16"
+ name="info_size_label"
+ width="48">
+ Size:
+ </text>
+ <text
+ follows="top|left"
+ top_delta="0"
+ height="32"
+ left="56"
+ name="info_size"
+ right="-20">
+ [AREA] m²
+ </text>
+ <text
+ follows="top|left"
+ font="SansSerifBig"
+ height="24"
+ left="16"
+ name="info_action"
+ text_color="white"
+ top="195"
+ width="200">
+ To sell this parcel:
+ </text>
+ <text
+ follows="top|left"
+ font="SansSerif"
+ height="16"
+ left="30"
+ name="price_label">
+ 1. Set a price:
+ </text>
+ <text
+ follows="top|left"
+ height="16"
+ left="40"
+ name="price_text">
+ Choose an appropriate price.
+ </text>
+ <text
+ height="16"
+ left="40"
+ name="price_ld"
+ width="20">
+ L$
+ </text>
+ <line_editor
+ follows="top|left"
+ height="18"
+ left_delta="20"
+ name="price"
+ top_delta="0"
+ width="100">
+ 0
+ </line_editor>
+ <text
+ height="16"
+ left="40"
+ name="price_per_m"
+ top_delta="25"
+ width="200">
+ (L$[PER_METER] per m²)
+ </text>
+ <text
+ follows="top|left"
+ font="SansSerif"
+ height="16"
+ left="30"
+ name="sell_to_label">
+ 2. Sell the land to:
+ </text>
+ <text
+ follows="top|left"
+ height="25"
+ left="40"
+ word_wrap="true"
+ name="sell_to_text"
+ right="-20">
+ Choose whether to sell to anyone or a particular buyer.
+ </text>
+ <combo_box
+ follows="top|left"
+ height="18"
+ left_delta="0"
+ name="sell_to"
+ top_delta="32"
+ width="130">
+ <combo_box.item
+ enabled="false"
+ label="- Select one -"
+ name="--selectone--"
+ value="select" />
+ <combo_box.item
+ label="Anyone"
+ name="Anyone"
+ value="anyone" />
+ <combo_box.item
+ label="Specific person:"
+ name="Specificuser:"
+ value="user" />
+ </combo_box>
+ <line_editor
+ enabled="false"
+ follows="top|left"
+ height="18"
+ left_delta="0"
+ name="sell_to_agent"
+ top_pad="4"
+ width="130" />
+ <button
+ height="20"
+ label="Select"
+ left_pad="5"
+ name="sell_to_select_agent"
+ top_delta="0"
+ width="60" />
+ <text
+ follows="top|left"
+ font="SansSerif"
+ height="16"
+ left="30"
+ name="sell_objects_label">
+ 3. Sell the objects with the land?
+ </text>
+ <text
+ font="SansSerifSmall"
+ follows="top|left"
+ height="25"
+ word_wrap="true"
+ left="40"
+ name="sell_objects_text">
+ Land owner&apos;s transferable objects on parcel will change ownership.
+ </text>
+ <radio_group
+ top_pad="5"
+ follows="top|left"
+ height="40"
+ left="40"
+ name="sell_objects"
+ right="-20">
+ <radio_item
+ bottom="40"
+ height="0"
+ left="10"
+ name="none"
+ visible="false" />
+ <radio_item
+ bottom="20"
+ height="16"
+ label="No, keep ownership of objects"
+ left="10"
+ name="no" />
+ <radio_item
+ bottom="40"
+ height="16"
+ label="Yes, sell objects with land"
+ left="10"
+ name="yes" />
+ </radio_group>
+ <button
+ height="20"
+ label="Show Objects"
+ name="show_objects"
+ left="70"
+ top_pad="10"
+ width="110" />
+ <text
+ bottom_delta="30"
+ follows="top|left"
+ font="SansSerifBig"
+ height="16"
+ left="16"
+ name="nag_message_label"
+ right="-20">
+ REMEMBER: All sales are final.
+ </text>
+ <button
+ follows="bottom|left"
+ height="20"
+ label="Set Land For Sale"
+ left_delta="0"
+ name="sell_btn"
+ top_pad="10"
+ width="130" />
+ <button
+ follows="bottom|left"
+ height="20"
+ label="Cancel"
+ left_pad="30"
+ name="cancel_btn"
+ top_delta="0"
+ width="90" />
+ </panel>
+ </scroll_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_settings_debug.xml b/indra/newview/skins/default/xui/en/floater_settings_debug.xml
new file mode 100644
index 0000000000..3ed2bd7206
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_settings_debug.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ height="215"
+ layout="topleft"
+ name="settings_debug"
+ help_topic="settings_debug"
+ title="DEBUG SETTINGS"
+ width="350">
+ <combo_box
+ allow_text_entry="true"
+ follows="top|left"
+ height="22"
+ layout="topleft"
+ left="15"
+ max_chars="255"
+ name="settings_combo"
+ top="30"
+ width="320">
+ <combo_box.commit_callback
+ function="SettingSelect" />
+ </combo_box>
+ <text_editor
+ enabled="false"
+ height="60"
+ layout="topleft"
+ left_delta="0"
+ name="comment_text"
+ top_pad="10"
+ width="320"
+ word_wrap="true" />
+ <radio_group
+ follows="top|left"
+ height="30"
+ layout="topleft"
+ left_delta="0"
+ name="boolean_combo"
+ top_pad="10"
+ visible="false"
+ tab_stop="true"
+ width="100">
+ <radio_item
+ top_pad="5"
+ label="TRUE"
+ name="TRUE"
+ value="true" />
+ <radio_item
+ top_pad="5"
+ label="FALSE"
+ name="FALSE"
+ value="" />
+ <commit_callback
+ function="CommitSettings" />
+ </radio_group>
+ <line_editor
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="val_text"
+ top_delta="0"
+ visible="false"
+ width="300" >
+ <line_editor.commit_callback
+ function="CommitSettings" />
+ </line_editor>
+ <color_swatch
+ bottom="185"
+ can_apply_immediately="true"
+ height="55"
+ name="val_color_swatch"
+ label="Color"
+ layout="topleft"
+ width="37" >
+ <color_swatch.commit_callback
+ function="CommitSettings" />
+ </color_swatch>
+ <spinner
+ height="20"
+ label="x"
+ layout="topleft"
+ left_delta="0"
+ max_val="1e+007"
+ name="val_spinner_1"
+ top_delta="10"
+ visible="false"
+ width="120" >
+ <spinner.commit_callback
+ function="CommitSettings" />
+ </spinner>
+ <spinner
+ height="20"
+ label="x"
+ layout="topleft"
+ left_pad="15"
+ max_val="1e+007"
+ name="val_spinner_2"
+ top_delta="0"
+ visible="false"
+ width="120">
+ <spinner.commit_callback
+ function="CommitSettings" />
+ </spinner>
+ <spinner
+ height="20"
+ label="x"
+ layout="topleft"
+ left="15"
+ max_val="1e+007"
+ name="val_spinner_3"
+ top="160"
+ visible="false"
+ width="120">
+ <spinner.commit_callback
+ function="CommitSettings" />
+ </spinner>
+ <spinner
+ height="20"
+ label="x"
+ layout="topleft"
+ left_pad="15"
+ max_val="1e+007"
+ name="val_spinner_4"
+ top_delta="0"
+ visible="false"
+ width="120" >
+ <spinner.commit_callback
+ function="CommitSettings" />
+ </spinner>
+ <button
+ height="22"
+ label="Reset to default"
+ layout="topleft"
+ left="15"
+ name="default_btn"
+ top="186"
+ width="150" >
+ <button.commit_callback
+ function="ClickDefault" />
+ </button>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml
new file mode 100644
index 0000000000..60c9810e95
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml
@@ -0,0 +1,394 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ can_close="true"
+ follows="left|top"
+ height="516"
+ layout="topleft"
+ name="Snapshot"
+ help_topic="snapshot"
+ save_rect="true"
+ save_visibility="true"
+ title="SNAPSHOT PREVIEW"
+ width="215">
+ <floater.string
+ name="unknown">
+ unknown
+ </floater.string>
+ <radio_group
+ height="58"
+ label="Snapshot type"
+ layout="topleft"
+ left="10"
+ name="snapshot_type_radio"
+ top="25"
+ width="205">
+ <radio_item
+ bottom="19"
+ height="16"
+ label="Email"
+ layout="topleft"
+ name="postcard" />
+ <radio_item
+ bottom="38"
+ height="16"
+ label="My inventory (L$[AMOUNT])"
+ layout="topleft"
+ name="texture" />
+ <radio_item
+ bottom="57"
+ height="16"
+ label="Save to my computer"
+ layout="topleft"
+ name="local" />
+ </radio_group>
+ <ui_ctrl
+ height="90"
+ width="90"
+ name="thumbnail_placeholder"
+ top_pad="6"
+ />
+ <text
+ type="string"
+ font="SansSerifSmall"
+ length="1"
+ follows="left|top"
+ height="14"
+ layout="topleft"
+ right="-5"
+ left_delta="0"
+ halign="right"
+ name="file_size_label"
+ top_pad="10"
+ width="195">
+ [SIZE] KB
+ </text>
+ <button
+ follows="left|top"
+ height="22"
+ image_overlay="Refresh_Off"
+ layout="topleft"
+ left="10"
+ name="new_snapshot_btn"
+ width="23" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Send"
+ layout="topleft"
+ left_pad="5"
+ right="-5"
+ name="send_btn"
+ width="100" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Save (L$[AMOUNT])"
+ layout="topleft"
+ right="-5"
+ name="upload_btn"
+ top_delta="0"
+ width="100" />
+ <flyout_button
+ follows="left|top"
+ height="23"
+ label="Save"
+ layout="topleft"
+ right="-5"
+ name="save_btn"
+ tool_tip="Save image to a file"
+ top_delta="0"
+ width="100">
+ <flyout_button.item
+ label="Save"
+ value="save" />
+ <flyout_button.item
+ label="Save As..."
+ value="save as" />
+ </flyout_button>
+ <button
+ follows="left|top"
+ height="23"
+ label="More"
+ layout="topleft"
+ left="10"
+ name="more_btn"
+ tool_tip="Advanced options"
+ width="80" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Less"
+ layout="topleft"
+ left_delta="0"
+ name="less_btn"
+ tool_tip="Advanced options"
+ top_delta="0"
+ width="80" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Cancel"
+ layout="topleft"
+ right="-5"
+ left_pad="5"
+ name="discard_btn"
+ width="100" />
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ height="12"
+ layout="topleft"
+ left="10"
+ name="type_label2"
+ top_pad="5"
+ width="120">
+ Size
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ height="12"
+ layout="topleft"
+ left_pad="5"
+ name="format_label"
+ top_delta="0"
+ width="70">
+ Format
+ </text>
+ <combo_box
+ height="23"
+ label="Resolution"
+ layout="topleft"
+ left="10"
+ name="postcard_size_combo"
+ width="120">
+ <combo_box.item
+ label="Current Window"
+ name="CurrentWindow"
+ value="[i0,i0]" />
+ <combo_box.item
+ label="640x480"
+ name="640x480"
+ value="[i640,i480]" />
+ <combo_box.item
+ label="800x600"
+ name="800x600"
+ value="[i800,i600]" />
+ <combo_box.item
+ label="1024x768"
+ name="1024x768"
+ value="[i1024,i768]" />
+ <combo_box.item
+ label="Custom"
+ name="Custom"
+ value="[i-1,i-1]" />
+ </combo_box>
+ <combo_box
+ height="23"
+ label="Resolution"
+ layout="topleft"
+ left_delta="0"
+ name="texture_size_combo"
+ top_delta="0"
+ width="120">
+ <combo_box.item
+ label="Current Window"
+ name="CurrentWindow"
+ value="[i0,i0]" />
+ <combo_box.item
+ label="Small (128x128)"
+ name="Small(128x128)"
+ value="[i128,i128]" />
+ <combo_box.item
+ label="Medium (256x256)"
+ name="Medium(256x256)"
+ value="[i256,i256]" />
+ <combo_box.item
+ label="Large (512x512)"
+ name="Large(512x512)"
+ value="[i512,i512]" />
+ <combo_box.item
+ label="Custom"
+ name="Custom"
+ value="[i-1,i-1]" />
+ </combo_box>
+ <combo_box
+ height="23"
+ label="Resolution"
+ layout="topleft"
+ left_delta="0"
+ name="local_size_combo"
+ top_delta="0"
+ width="120">
+ <combo_box.item
+ label="Current Window"
+ name="CurrentWindow"
+ value="[i0,i0]" />
+ <combo_box.item
+ label="320x240"
+ name="320x240"
+ value="[i320,i240]" />
+ <combo_box.item
+ label="640x480"
+ name="640x480"
+ value="[i640,i480]" />
+ <combo_box.item
+ label="800x600"
+ name="800x600"
+ value="[i800,i600]" />
+ <combo_box.item
+ label="1024x768"
+ name="1024x768"
+ value="[i1024,i768]" />
+ <combo_box.item
+ label="1280x1024"
+ name="1280x1024"
+ value="[i1280,i1024]" />
+ <combo_box.item
+ label="1600x1200"
+ name="1600x1200"
+ value="[i1600,i1200]" />
+ <combo_box.item
+ label="Custom"
+ name="Custom"
+ value="[i-1,i-1]" />
+ </combo_box>
+ <combo_box
+ height="23"
+ label="Format"
+ layout="topleft"
+ left_pad="5"
+ name="local_format_combo"
+ width="70">
+ <combo_box.item
+ label="PNG"
+ name="PNG" />
+ <combo_box.item
+ label="JPEG"
+ name="JPEG" />
+ <combo_box.item
+ label="BMP"
+ name="BMP" />
+ </combo_box>
+ <spinner
+ allow_text_entry="false"
+ decimal_digits="0"
+ follows="left|top"
+ height="20"
+ increment="32"
+ label="Width"
+ label_width="40"
+ layout="topleft"
+ left="10"
+ max_val="6016"
+ min_val="32"
+ name="snapshot_width"
+ top_pad="10"
+ width="95" />
+ <spinner
+ allow_text_entry="false"
+ decimal_digits="0"
+ follows="left|top"
+ height="20"
+ increment="32"
+ label="Height"
+ label_width="40"
+ layout="topleft"
+ left_pad="5"
+ max_val="6016"
+ min_val="32"
+ name="snapshot_height"
+ top_delta="0"
+ width="95" />
+ <check_box
+ bottom_delta="20"
+ label="Constrain proportions"
+ layout="topleft"
+ left="10"
+ name="keep_aspect_check" />
+ <slider
+ decimal_digits="0"
+ follows="left|top"
+ height="15"
+ increment="1"
+ initial_value="75"
+ label="Image quality"
+ label_width="100"
+ layout="topleft"
+ left_delta="0"
+ max_val="100"
+ name="image_quality_slider"
+ top_pad="5"
+ width="205" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="13"
+ layout="topleft"
+ left="10"
+ name="layer_type_label"
+ top_pad="5"
+ width="50">
+ Capture:
+ </text>
+ <combo_box
+ height="23"
+ label="Image Layers"
+ layout="topleft"
+ left="30"
+ name="layer_types"
+ width="145">
+ <combo_box.item
+ label="Colors"
+ name="Colors"
+ value="colors" />
+ <combo_box.item
+ label="Depth"
+ name="Depth"
+ value="depth" />
+ <combo_box.item
+ label="Object Mattes"
+ name="ObjectMattes"
+ value="objects" />
+ </combo_box>
+ <check_box
+ label="Interface"
+ layout="topleft"
+ left="30"
+ top_pad="10"
+ width="180"
+ name="ui_check" />
+ <check_box
+ label="HUDs"
+ layout="topleft"
+ left="30"
+ top_pad="10"
+ width="180"
+ name="hud_check" />
+ <check_box
+ label="Keep open after saving"
+ layout="topleft"
+ left="10"
+ top_pad="8"
+ width="180"
+ name="keep_open_check" />
+ <check_box
+ label="Freeze frame (fullscreen)"
+ layout="topleft"
+ left="10"
+ top_pad="8"
+ width="180"
+ name="freeze_frame_check" />
+ <check_box
+ label="Auto-refresh"
+ layout="topleft"
+ left="10"
+ top_pad="8"
+ width="180"
+ name="auto_snapshot_check" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_sound_preview.xml b/indra/newview/skins/default/xui/en/floater_sound_preview.xml
new file mode 100644
index 0000000000..ca54ee6604
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_sound_preview.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="190"
+ layout="topleft"
+ name="Sound Preview"
+ help_topic="sound_preview"
+ title="SOUND.WAV"
+ width="300">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="name_label"
+ top="20"
+ width="275">
+ Name:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ height="19"
+ layout="topleft"
+ left_delta="0"
+ max_length="63"
+ name="name_form"
+ top_pad="0"
+ width="280" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="description_label"
+ top_pad="10"
+ width="270">
+ Description:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ height="19"
+ layout="topleft"
+ left_delta="0"
+ max_length="127"
+ name="description_form"
+ top_pad="0"
+ width="280" />
+ <button
+ follows="left|bottom"
+ height="22"
+ label="Upload (L$[AMOUNT])"
+ layout="topleft"
+ left="45"
+ name="ok_btn"
+ top_pad="60"
+ width="150" />
+ <button
+ follows="right|bottom"
+ height="22"
+ label="Cancel"
+ label_selected="Cancel"
+ layout="topleft"
+ name="cancel_btn"
+ left_pad="5"
+ width="90" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_statistics.xml b/indra/newview/skins/default/xui/en/floater_statistics.xml
new file mode 100644
index 0000000000..3a4e845141
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_statistics.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ follows="right|top"
+ height="392"
+ layout="topleft"
+ mouse_opaque="false"
+ name="stats floater"
+ help_topic="stats_floater"
+ title="STATISTICS"
+ width="250" />
diff --git a/indra/newview/skins/default/xui/en/floater_stats.xml b/indra/newview/skins/default/xui/en/floater_stats.xml
new file mode 100644
index 0000000000..f9dacf0207
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_stats.xml
@@ -0,0 +1,694 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ follows="top|right"
+ height="400"
+ layout="topleft"
+ name="Statistics"
+ help_topic="statistics"
+ save_rect="true"
+ save_visibility="true"
+ title="STATISTICS"
+ width="250">
+ <scroll_container
+ follows="top|left|bottom|right"
+ height="380"
+ layout="topleft"
+ left="0"
+ name="statistics_scroll"
+ reserve_scroll_corner="true"
+ top="20"
+ width="250">
+ <container_view
+ follows="top|left|bottom|right"
+ height="378"
+ layout="topleft"
+ left="2"
+ name="statistics_view"
+ top="20"
+ width="230" >
+ <stat_view
+ name="basic"
+ label="Basic"
+ show_label="true"
+ setting="OpenDebugStatBasic">
+ <stat_bar
+ name="fps"
+ label="FPS"
+ unit_label="fps"
+ stat="fpsstat"
+ bar_min="0"
+ bar_max="45"
+ tick_spacing="7.5"
+ label_spacing="15.0"
+ precision="1"
+ show_bar="true"
+ show_history="true">
+ </stat_bar>
+ <stat_bar
+ name="bandwidth"
+ label="Bandwidth"
+ unit_label="kbps"
+ stat="kbitstat"
+ bar_min="0"
+ bar_max="900"
+ tick_spacing="100"
+ label_spacing="300"
+ show_bar="true"
+ show_history="false">
+ </stat_bar>
+ <stat_bar
+ name="packet_loss"
+ label="Packet Loss"
+ unit_label=" %"
+ stat="packetslostpercentstat"
+ bar_min="0"
+ bar_max="5"
+ tick_spacing="1"
+ label_spacing="1"
+ precision="1"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="true">
+ </stat_bar>
+ <stat_bar
+ name="ping"
+ label="Ping Sim"
+ unit_label="msec"
+ stat="simpingstat"
+ bar_min="0"
+ bar_max="1000"
+ tick_spacing="100"
+ label_spacing="200"
+ show_bar="false"
+ show_per_sec="false"
+ show_mean="false">
+ </stat_bar>
+ </stat_view>
+ <stat_view
+ name="advanced"
+ label="Advanced"
+ show_label="true"
+ setting="OpenDebugStatAdvanced">
+ <stat_view
+ name="render"
+ label="Render"
+ show_label="true"
+ setting="OpenDebugStatRender">
+ <stat_bar
+ name="ktrisframe"
+ label="KTris Drawn"
+ unit_label="/fr"
+ stat="trianglesdrawnstat"
+ bar_min="0"
+ bar_max="500"
+ tick_spacing="100"
+ label_spacing="500"
+ precision="1"
+ show_per_sec="false">
+ </stat_bar>
+ <stat_bar
+ name="ktrissec"
+ label="KTris Drawn"
+ unit_label="/sec"
+ stat="trianglesdrawnstat"
+ bar_min="0"
+ bar_max="3000"
+ tick_spacing="250"
+ label_spacing="1000"
+ precision="1">
+ </stat_bar>
+ <stat_bar
+ name="objs"
+ label="Total Objects"
+ unit_label=""
+ stat="numobjectsstat"
+ bar_min="0"
+ bar_max="3000"
+ tick_spacing="250"
+ label_spacing="1000"
+ precision="1"
+ show_per_sec="false"
+ show_bar="false">
+ </stat_bar>
+ <stat_bar
+ name="newobjs"
+ label="New Objects"
+ unit_label="/sec"
+ stat="numnewobjectsstat"
+ bar_min="0"
+ bar_max="1000"
+ tick_spacing="100"
+ label_spacing="500"
+ show_per_sec="true"
+ show_bar="false">
+ </stat_bar>
+ </stat_view>
+ <stat_view
+ name="texture"
+ label="Texture"
+ show_label="true">
+ <stat_bar
+ name="numimagesstat"
+ label="Count"
+ stat="numimagesstat"
+ bar_min="0.f"
+ bar_max="8000.f"
+ tick_spacing="2000.f"
+ label_spacing="4000.f"
+ show_per_sec="false"
+ show_bar="false">
+ </stat_bar>
+
+ <stat_bar
+ name="numrawimagesstat"
+ label="Raw Count"
+ stat="numrawimagesstat"
+ bar_min="0.f"
+ bar_max="8000.f"
+ tick_spacing="2000.f"
+ label_spacing="4000.f"
+ show_per_sec="false"
+ show_bar="false">
+ </stat_bar>
+
+ <stat_bar
+ name="gltexmemstat"
+ label="GL Mem"
+ stat="gltexmemstat"
+ bar_min="0.f"
+ bar_max="400.f"
+ tick_spacing="100.f"
+ label_spacing="200.f"
+ precision="1"
+ show_per_sec="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="formattedmemstat"
+ label="Formatted Mem"
+ stat="formattedmemstat"
+ bar_min="0.f"
+ bar_max="400.f"
+ tick_spacing="100.f"
+ label_spacing="200.f"
+ precision="1"
+ show_per_sec="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="rawmemstat"
+ label="Raw Mem"
+ stat="rawmemstat"
+ bar_min="0.f"
+ bar_max="400.f"
+ tick_spacing="100.f"
+ label_spacing="200.f"
+ precision="1"
+ show_per_sec="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="glboundmemstat"
+ label="Bound Mem"
+ stat="glboundmemstat"
+ bar_min="0.f"
+ bar_max="400.f"
+ tick_spacing="100.f"
+ label_spacing="200.f"
+ precision="1"
+ show_per_sec="false" >
+ </stat_bar>
+ </stat_view>
+
+ <stat_view
+ name="network"
+ label="Network"
+ show_label="true"
+ setting="OpenDebugStatNet">
+ <stat_bar
+ name="packetsinstat"
+ label="Packets In"
+ stat="packetsinstat"
+ unit_label="/sec"
+ show_bar="false">
+ </stat_bar>
+
+ <stat_bar
+ name="packetsoutstat"
+ label="Packets Out"
+ stat="packetsoutstat"
+ unit_label="/sec"
+ show_bar="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="objectkbitstat"
+ label="Objects"
+ stat="objectkbitstat"
+ unit_label="kbps"
+ show_bar="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="texturekbitstat"
+ label="Texture"
+ stat="texturekbitstat"
+ unit_label="kbps"
+ show_bar="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="assetkbitstat"
+ label="Asset"
+ stat="assetkbitstat"
+ unit_label="kbps"
+ show_bar="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="layerskbitstat"
+ label="Layers"
+ stat="layerskbitstat"
+ unit_label="kbps"
+ show_bar="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="actualinkbitstat"
+ label="Actual In"
+ stat="actualinkbitstat"
+ unit_label="kbps"
+ bar_min="0.f"
+ bar_max="1024.f"
+ tick_spacing="128.f"
+ label_spacing="256.f"
+ show_bar="true"
+ show_history="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="actualoutkbitstat"
+ label="Actual Out"
+ stat="actualoutkbitstat"
+ unit_label="kbps"
+ bar_min="0.f"
+ bar_max="512.f"
+ tick_spacing="128.f"
+ label_spacing="256.f"
+ show_bar="true"
+ show_history="false">
+ </stat_bar>
+
+ <stat_bar
+ name="vfspendingoperations"
+ label="VFS Pending Ops"
+ stat="vfspendingoperations"
+ unit_label=" "
+ show_per_sec="false"
+ show_bar="false" >
+ </stat_bar>
+ </stat_view>
+ </stat_view>
+
+ <stat_view
+ name="sim"
+ label="Simulator"
+ show_label="true"
+ setting="OpenDebugStatSim">
+ <stat_bar
+ name="simtimedilation"
+ label="Time Dilation"
+ stat="simtimedilation"
+ precision="2"
+ bar_min="0.f"
+ bar_max="1.f"
+ tick_spacing="0.25f"
+ label_spacing="0.5f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="simfps"
+ label="Sim FPS"
+ stat="simfps"
+ bar_min="0.f"
+ bar_max="200.f"
+ tick_spacing="20.f"
+ label_spacing="100.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="simphysicsfps"
+ label="Physics FPS"
+ stat="simphysicsfps"
+ precision="1"
+ bar_min="0.f"
+ bar_max="66.f"
+ tick_spacing="33.f"
+ label_spacing="33.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_view
+ name="physicsdetail"
+ label="Physics Details"
+ show_label="true"
+ display_children="false">
+ <stat_bar
+ name="physicspinnedtasks"
+ label="Pinned Objects"
+ stat="physicspinnedtasks"
+ precision="0"
+ bar_min="0.f"
+ bar_max="500.f"
+ tick_spacing="10.f"
+ label_spacing="40.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="physicslodtasks"
+ label="Low LOD Objects"
+ stat="physicslodtasks"
+ precision="0"
+ bar_min="0.f"
+ bar_max="500.f"
+ tick_spacing="10.f"
+ label_spacing="40.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="physicsmemoryallocated"
+ label="Memory Allocated"
+ stat="physicsmemoryallocated"
+ unit_label="MB"
+ precision="0"
+ bar_min="0.f"
+ bar_max="1024.f"
+ tick_spacing="128.f"
+ label_spacing="256.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+ </stat_view>
+
+ <stat_bar
+ name="simagentups"
+ label="Agent Updates/Sec"
+ stat="simagentups"
+ precision="1"
+ bar_min="0.f"
+ bar_max="100.f"
+ tick_spacing="25.f"
+ label_spacing="50.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="simmainagents"
+ label="Main Agents"
+ stat="simmainagents"
+ precision="0"
+ bar_min="0.f"
+ bar_max="80.f"
+ tick_spacing="10.f"
+ label_spacing="40.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="simchildagents"
+ label="Child Agents"
+ stat="simchildagents"
+ precision="0"
+ bar_min="0.f"
+ bar_max="40.f"
+ tick_spacing="5.f"
+ label_spacing="10.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="simobjects"
+ label="Objects"
+ stat="simobjects"
+ precision="0"
+ bar_min="0.f"
+ bar_max="30000.f"
+ tick_spacing="5000.f"
+ label_spacing="10000.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="simactiveobjects"
+ label="Active Objects"
+ stat="simactiveobjects"
+ precision="0"
+ bar_min="0.f"
+ bar_max="800.f"
+ tick_spacing="100.f"
+ label_spacing="200.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="simactivescripts"
+ label="Active Scripts"
+ stat="simactivescripts"
+ precision="0"
+ bar_min="0.f"
+ bar_max="800.f"
+ tick_spacing="100.f"
+ label_spacing="200.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="simscripteps"
+ label="Script Events"
+ stat="simscripteps"
+ unit_label="eps"
+ precision="0"
+ bar_min="0.f"
+ bar_max="20000.f"
+ tick_spacing="2500.f"
+ label_spacing="5000.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="siminpps"
+ label="Packets In"
+ stat="siminpps"
+ unit_label="pps"
+ precision="0"
+ bar_min="0.f"
+ bar_max="2000.f"
+ tick_spacing="250.f"
+ label_spacing="1000.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="simoutpps"
+ label="Packets Out"
+ stat="simoutpps"
+ unit_label="pps"
+ precision="0"
+ bar_min="0.f"
+ bar_max="2000.f"
+ tick_spacing="250.f"
+ label_spacing="1000.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="simpendingdownloads"
+ label="Pending Downloads"
+ stat="simpendingdownloads"
+ precision="0"
+ bar_min="0.f"
+ bar_max="800.f"
+ tick_spacing="100.f"
+ label_spacing="200.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="simpendinguploads"
+ label="Pending Uploads"
+ stat="simpendinguploads"
+ precision="0"
+ bar_min="0.f"
+ bar_max="100.f"
+ tick_spacing="25.f"
+ label_spacing="50.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="simtotalunackedbytes"
+ label="Total Unacked Bytes"
+ stat="simtotalunackedbytes"
+ unit_label="kb"
+ precision="0"
+ bar_min="0.f"
+ bar_max="100000.f"
+ tick_spacing="25000.f"
+ label_spacing="50000.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_view
+ name="simperf"
+ label="Time (ms)"
+ show_label="true">
+ <stat_bar
+ name="simframemsec"
+ label="Total Frame Time"
+ stat="simframemsec"
+ unit_label="ms"
+ precision="1"
+ bar_min="0.f"
+ bar_max="40.f"
+ tick_spacing="10.f"
+ label_spacing="20.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="simnetmsec"
+ label="Net Time"
+ stat="simnetmsec"
+ unit_label="ms"
+ precision="1"
+ bar_min="0.f"
+ bar_max="40.f"
+ tick_spacing="10.f"
+ label_spacing="20.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="simsimphysicsmsec"
+ label="Physics Time"
+ stat="simsimphysicsmsec"
+ unit_label="ms"
+ precision="1"
+ bar_min="0.f"
+ bar_max="40.f"
+ tick_spacing="10.f"
+ label_spacing="20.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="simsimothermsec"
+ label="Simulation Time"
+ stat="simsimothermsec"
+ unit_label="ms"
+ precision="1"
+ bar_min="0.f"
+ bar_max="40.f"
+ tick_spacing="10.f"
+ label_spacing="20.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="simagentmsec"
+ label="Agent Time"
+ stat="simagentmsec"
+ unit_label="ms"
+ precision="1"
+ bar_min="0.f"
+ bar_max="40.f"
+ tick_spacing="10.f"
+ label_spacing="20.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="simimagesmsec"
+ label="Images Time"
+ stat="simimagesmsec"
+ unit_label="ms"
+ precision="1"
+ bar_min="0.f"
+ bar_max="40.f"
+ tick_spacing="10.f"
+ label_spacing="20.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+
+ <stat_bar
+ name="simscriptmsec"
+ label="Script Time"
+ stat="simscriptmsec"
+ unit_label="ms"
+ precision="1"
+ bar_min="0.f"
+ bar_max="40.f"
+ tick_spacing="10.f"
+ label_spacing="20.f"
+ show_per_sec="false"
+ show_bar="false"
+ show_mean="false" >
+ </stat_bar>
+ </stat_view>
+ </stat_view>
+ </container_view>
+ </scroll_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_sys_well.xml b/indra/newview/skins/default/xui/en/floater_sys_well.xml
new file mode 100644
index 0000000000..005952f3f2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_sys_well.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater
+ legacy_header_height="18"
+ bevel_style="in"
+ left="0"
+ top="0"
+ follows="right|bottom"
+ layout="topleft"
+ name="sys_well_window"
+ help_topic="notification_chiclet"
+ save_rect="true"
+ title="NOTIFICATIONS"
+ width="320"
+ min_width="320"
+ height="23"
+ can_minimize="false"
+ can_tear_off="false"
+ can_resize="true"
+ can_drag_on_left="false"
+ can_dock="true"
+ save_visibility="true"
+ single_instance="true"
+>
+ <string
+ name="title_im_well_window">
+ CONVERSATIONS
+ </string>
+ <string
+ name="title_notification_well_window">
+ NOTIFICATIONS
+ </string>
+
+ <flat_list_view
+ color="FloaterDefaultBackgroundColor"
+ follows="all"
+ layout="topleft"
+ name="notification_list"
+ left="1"
+ top="20"
+ height="0"
+ width="318"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_telehub.xml b/indra/newview/skins/default/xui/en/floater_telehub.xml
new file mode 100644
index 0000000000..da412ed8a0
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_telehub.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- Explicit left edge to avoid overlapping build tools -->
+<floater
+ legacy_header_height="18"
+ height="250"
+ layout="topleft"
+ left="300"
+ name="telehub"
+ help_topic="telehub"
+ title="TELEHUB"
+ width="330">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="status_text_connected"
+ top="24"
+ width="315">
+ Telehub connected to object [OBJECT]
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="status_text_not_connected"
+ top_delta="0"
+ width="315">
+ No telehub connected.
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="help_text_connected"
+ top_delta="16"
+ width="315">
+ To remove, click Disconnect.
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="help_text_not_connected"
+ top_delta="0"
+ width="315">
+ Select object and click Connect Telehub.
+ </text>
+ <button
+ follows="top|left"
+ height="23"
+ label="Connect Telehub"
+ layout="topleft"
+ left_delta="0"
+ name="connect_btn"
+ top_delta="20"
+ width="130" />
+ <button
+ follows="top|left"
+ height="23"
+ label="Disconnect"
+ layout="topleft"
+ left_pad="10"
+ name="disconnect_btn"
+ top_delta="0"
+ width="130" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="14"
+ layout="topleft"
+ left="10"
+ name="spawn_points_text"
+ top="84"
+ width="315">
+ Spawn Points (positions, not objects):
+ </text>
+ <scroll_list
+ follows="left|top"
+ height="60"
+ layout="topleft"
+ name="spawn_points_list"
+ width="315" />
+ <button
+ follows="top|left"
+ height="23"
+ label="Add Spawn"
+ layout="topleft"
+ name="add_spawn_point_btn"
+ width="130" />
+ <button
+ follows="top|left"
+ height="23"
+ label="Remove Spawn"
+ layout="topleft"
+ left_pad="10"
+ name="remove_spawn_point_btn"
+ width="130" />
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ height="56"
+ layout="topleft"
+ left="10"
+ name="spawn_point_help"
+ word_wrap="true"
+ width="317">
+ Select object and click "Add Spawn" to specify position.
+You can then move or delete the object.
+Positions are relative to the telehub center.
+Select an item in list to highlight it inworld.
+ </text>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_button.xml b/indra/newview/skins/default/xui/en/floater_test_button.xml
new file mode 100644
index 0000000000..8c6ad5c0f7
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_test_button.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="500"
+ layout="topleft"
+ name="floater_test_button"
+ help_topic="floater_test_button"
+ width="500">
+ <button
+ height="23"
+ label="Generic Button"
+ layout="topleft"
+ left="10"
+ name="generic_button"
+ top="20"
+ width="150" />
+ <button
+ bottom_delta="30"
+ height="23"
+ label="Bottom delta"
+ layout="topleft"
+ name="bottom_delta_button" />
+ <button
+ bottom_delta="30"
+ height="23"
+ label="SansSerifSmall"
+ layout="topleft"
+ name="sans_serif_small_button" />
+ <button
+ auto_resize="true"
+ bottom_delta="30"
+ height="23"
+ label="Auto Resize"
+ layout="topleft"
+ name="auto_resize_button" />
+ <button
+ bottom_delta="30"
+ height="23"
+ is_toggle="true"
+ label="Click Change Label"
+ label_selected="New Label"
+ layout="topleft"
+ name="label_selected_button" />
+ <button
+ bottom_delta="30"
+ height="23"
+ label="No Label Shadow"
+ label_shadow="false"
+ layout="topleft"
+ name="label_shadow_button" />
+ <button
+ bottom_delta="30"
+ height="23"
+ label="EmphasisColor Label"
+ label_color="EmphasisColor"
+ layout="topleft"
+ name="label_color_button" />
+ <button
+ bottom_delta="30"
+ height="23"
+ is_toggle="true"
+ label="Toggle"
+ label_color_selected="EmphasisColor"
+ label_selected="Toggle on"
+ layout="topleft"
+ name="label_color_selected_button" />
+ <button
+ bottom_delta="30"
+ enabled="false"
+ height="23"
+ label="Disabled"
+ label_color_disabled="EmphasisColor"
+ label_selected="Selected"
+ layout="topleft"
+ name="label_color_disabled_button" />
+ <button
+ bottom_delta="30"
+ height="23"
+ highlight_color="EmphasisColor"
+ label="Highlight"
+ layout="topleft"
+ name="highlight_color_button" />
+ <button
+ bottom_delta="30"
+ height="23"
+ hover_glow_amount="0"
+ label="No Hover Glow"
+ layout="topleft"
+ name="hover_glow_amount_button" />
+ <button
+ height="16"
+ image_selected="Move_Run_Off"
+ image_unselected="Move_Run_Off"
+ layout="topleft"
+ left="200"
+ name="image_button"
+ top="20"
+ width="16" />
+ <button
+ height="16"
+ image_color="EmphasisColor"
+ image_selected="Move_Run_Off"
+ image_unselected="Move_Run_Off"
+ layout="topleft"
+ left_delta="0"
+ name="image_color_button"
+ top_pad="10"
+ width="16" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_checkbox.xml b/indra/newview/skins/default/xui/en/floater_test_checkbox.xml
new file mode 100644
index 0000000000..042b4226c3
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_test_checkbox.xml
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="400"
+ layout="topleft"
+ name="floater_test_checkbox"
+ help_topic="floater_test_checkbox"
+ width="400">
+ <check_box
+ control_name="ShowStartLocation"
+ height="15"
+ initial_value="true"
+ label="Oh look it's a checkbox!"
+ layout="topleft"
+ left="10"
+ name="show_location_checkbox"
+ top="28"
+ width="256" />
+ <check_box
+ height="15"
+ label="Minimal Checkbox"
+ layout="topleft"
+ left_delta="0"
+ name="minimal_checkbox"
+ top_pad="14"
+ width="150" />
+ <check_box
+ enabled="false"
+ height="15"
+ label="Disabled Checkbox"
+ layout="topleft"
+ left_delta="0"
+ name="disabled_checkbox"
+ top_pad="14"
+ width="150" />
+ <check_box
+ height="15"
+ label="Text Enabled Color"
+ layout="topleft"
+ left_delta="0"
+ name="text_enabled_color_checkbox"
+ text_enabled_color="EmphasisColor"
+ top_pad="14"
+ width="150" />
+ <check_box
+ enabled="false"
+ height="15"
+ label="Text Disabled Color"
+ layout="topleft"
+ left_delta="0"
+ name="text_disabled_color_checkbox"
+ text_disabled_color="EmphasisColor_35"
+ top_pad="14"
+ width="150" />
+ <check_box
+ height="15"
+ initial_value="true"
+ label="Initial Value Checked"
+ layout="topleft"
+ left_delta="0"
+ name="initial_value_checkbox"
+ top_pad="14"
+ width="150" />
+ <check_box
+ font="Monospace"
+ height="15"
+ label="Font Monospace"
+ layout="topleft"
+ left_delta="0"
+ name="font_checkbox"
+ top_pad="14"
+ width="150" />
+
+<chiclet_im_p2p
+ height="25"
+ name="im_p2p_chiclet"
+ show_speaker="false"
+ width="25">
+ <chiclet_im_p2p.chiclet_button
+ height="25"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ name="chiclet_button"
+ tab_stop="false"
+ width="25"/>
+ <chiclet_im_p2p.speaker
+ auto_update="true"
+ draw_border="false"
+ height="25"
+ left="25"
+ name="speaker"
+ visible="false"
+ width="20" />
+ <chiclet_im_p2p.avatar_icon
+ bottom="3"
+ follows="left|top|bottom"
+ height="20"
+ left="2"
+ mouse_opaque="false"
+ name="avatar_icon"
+ width="21" />
+ <chiclet_im_p2p.unread_notifications
+ height="25"
+ font_halign="center"
+ left="25"
+ mouse_opaque="false"
+ name="unread"
+ text_color="white"
+ v_pad="5"
+ visible="false"
+ width="20"/>
+ <chiclet_im_p2p.new_message_icon
+ bottom="11"
+ height="14"
+ image_name="Unread_Chiclet"
+ left="12"
+ name="new_message_icon"
+ visible="false"
+ width="14" />
+</chiclet_im_p2p>
+
+
+<chiclet_offer
+ height="25"
+ name="offer_chiclet"
+ width="25">
+ <chiclet_offer.chiclet_button
+ height="25"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ name="chiclet_button"
+ tab_stop="false"
+ width="25"/>
+ <chiclet_offer.icon
+ bottom="3"
+ default_icon="Generic_Object_Small"
+ follows="all"
+ height="19"
+ left="3"
+ mouse_opaque="false"
+ name="chiclet_icon"
+ width="19" />
+ <chiclet_offer.new_message_icon
+ bottom="11"
+ height="14"
+ image_name="Unread_Chiclet"
+ left="12"
+ name="new_message_icon"
+ visible="false"
+ width="14" />
+</chiclet_offer>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_combobox.xml b/indra/newview/skins/default/xui/en/floater_test_combobox.xml
new file mode 100644
index 0000000000..317d8f5ba8
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_test_combobox.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="400"
+ layout="topleft"
+ name="floater_test_combobox"
+ help_topic="floater_test_combobox"
+ width="400">
+ <text
+ type="string"
+ length="1"
+ height="16"
+ layout="topleft"
+ left="10"
+ top="24"
+ width="200">
+ Real world usage (login location):
+ </text>
+ <combo_box
+ allow_text_entry="true"
+ control_name="LoginLocation"
+ follows="left|bottom"
+ height="18"
+ layout="topleft"
+ left_delta="0"
+ max_chars="128"
+ name="start_location_combo"
+ top_pad="2"
+ width="155">
+ <combo_box.item
+ label="My Last Location"
+ name="MyLastLocation"
+ value="last" />
+ <combo_box.item
+ label="My Home"
+ name="MyHome"
+ value="home" />
+ <combo_box.item
+ label="&lt;Type region name&gt;"
+ name="Typeregionname"
+ value="" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ top_pad="24"
+ width="200">
+ Minimal combobox:
+ </text>
+ <combo_box
+ height="18"
+ layout="topleft"
+ left_delta="0"
+ name="minimal_combo"
+ top_pad="2"
+ width="150">
+ <combo_box.item
+ label="First Item"
+ name="item1"
+ value="first" />
+ <combo_box.item
+ label="Second Item"
+ name="item2"
+ value="second" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ top_pad="24"
+ width="200">
+ Allow text input:
+ </text>
+ <combo_box
+ allow_text_entry="true"
+ height="18"
+ layout="topleft"
+ left_delta="0"
+ name="text_entry_combo"
+ top_pad="2"
+ width="150">
+ <combo_box.item
+ label="First Item"
+ name="item1"
+ value="first" />
+ <combo_box.item
+ label="Second Item"
+ name="item2"
+ value="second" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ top_pad="24"
+ width="200">
+ Allow text input, default to second item:
+ </text>
+ <combo_box
+ allow_text_entry="true"
+ height="18"
+ initial_value="second"
+ layout="topleft"
+ left_delta="0"
+ name="text_entry_combo2"
+ top_pad="2"
+ width="150">
+ <combo_box.item
+ label="First Item"
+ name="item1"
+ value="first" />
+ <combo_box.item
+ label="Second Item"
+ name="item2"
+ value="second" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ top_pad="24"
+ width="200">
+ Two character max input:
+ </text>
+ <combo_box
+ allow_text_entry="true"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ max_chars="2"
+ name="state_combo"
+ top_pad="4"
+ width="150">
+ <combo_box.item
+ label="CA"
+ name="item1"
+ value="ca" />
+ <combo_box.item
+ label="NY"
+ name="item2"
+ value="ny" />
+ <combo_box.item
+ label="TX"
+ name="item3"
+ value="tx" />
+ </combo_box>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_inspectors.xml b/indra/newview/skins/default/xui/en/floater_test_inspectors.xml
new file mode 100644
index 0000000000..9143048aeb
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_test_inspectors.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="false"
+ height="400"
+ layout="topleft"
+ name="floater_test_inspectors"
+ help_topic="floater_test_inspectors"
+ title="TEST INSPECTORS"
+ width="400">
+ <text
+ height="20"
+ left="10"
+ name="test_inspectors"
+ top="30"
+ width="300">
+ Click to spawn an inspector:
+ </text>
+ <button
+ name="avatar_2d_btn1"
+ label="Avatar 2D"
+ top="50"
+ left="10"
+ height="20"
+ width="100"
+ commit_callback.function="ShowAvatarInspector"
+ commit_callback.parameter="22df1dcb-810a-4975-aab9-0159958fe155" />
+ <!-- InspectorA Tester -->
+ <button
+ name="avatar_2d_btn5"
+ label="Avatar 2D"
+ top_pad="10"
+ left="10"
+ height="20"
+ width="100"
+ commit_callback.function="ShowAvatarInspector"
+ commit_callback.parameter="927e68e0-e52d-4bb8-b1a9-add97a57c86a" />
+ <!-- InspectorB Tester -->
+ <button
+ name="avatar_2d_btn2"
+ label="Avatar 2D"
+ top_pad="10"
+ left="10"
+ height="20"
+ width="100"
+ commit_callback.function="ShowAvatarInspector"
+ commit_callback.parameter="9a2300ca-e251-45dd-bb61-e33139f6e4eb" />
+ <!-- InspectorC Tester -->
+ <button
+ name="avatar_2d_btn3"
+ label="Avatar 2D"
+ top_pad="10"
+ left="10"
+ height="20"
+ width="100"
+ commit_callback.function="ShowAvatarInspector"
+ commit_callback.parameter="8024f082-34cc-48a3-a42e-c42f345efd74" />
+ <!-- jarvtest Bombastic 2009-10-3 -->
+ <button
+ name="avatar_2d_btn4"
+ label="Avatar 2D"
+ top_pad="10"
+ left="10"
+ height="20"
+ width="100"
+ commit_callback.function="ShowAvatarInspector"
+ commit_callback.parameter="e7dc3c83-1e11-4fa7-beeb-4b18adfb4efa" />
+ <button
+ name="avatar_3d_btn"
+ label="Avatar 3D"
+ top="50"
+ left="150"
+ height="20"
+ width="100"/>
+ <button
+ name="object_2d_btn"
+ label="Object 2D"
+ top_pad="10"
+ left_delta="0"
+ height="20"
+ width="100"/>
+ <button
+ name="object_3d_btn"
+ label="Object 3D"
+ top_pad="10"
+ left_delta="0"
+ height="20"
+ width="100"
+ commit_callback.function="ShowObjectInspector"
+ commit_callback.parameter="" />
+ <button
+ name="group_btn"
+ label="Group"
+ top_pad="10"
+ left_delta="0"
+ height="20"
+ width="100"
+ commit_callback.function="ShowGroupInspector"
+ commit_callback.parameter="" />
+ <button
+ name="place_btn"
+ label="Place"
+ top_pad="10"
+ left_delta="0"
+ height="20"
+ width="100"/>
+ <button
+ name="event_btn"
+ label="Event"
+ top_pad="10"
+ left_delta="0"
+ height="20"
+ width="100"/>
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ left="0"
+ max_length="65536"
+ name="slurl"
+ top_pad="4"
+ width="150">
+ secondlife:///app/agent/00000000-0000-0000-0000-000000000000/inspect
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ left="0"
+ max_length="65536"
+ name="slurl_group"
+ top_pad="4"
+ width="150">
+ secondlife:///app/group/00000000-0000-0000-0000-000000000000/inspect
+ </text>
+
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_layout.xml b/indra/newview/skins/default/xui/en/floater_test_layout.xml
new file mode 100644
index 0000000000..c6acb7c96e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_test_layout.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="500"
+ layout="topleft"
+ name="floater_test_layout"
+ help_topic="floater_test_layout"
+ width="500">
+ <text
+ type="string"
+ length="1"
+ height="16"
+ layout="topleft"
+ left="10"
+ top="84"
+ width="200">
+ bottom 400 left 10
+ </text>
+ <text
+ type="string"
+ length="1"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ top_pad="4"
+ width="200">
+ Bottom delta -20
+ </text>
+ <text
+ type="string"
+ length="1"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ top_pad="64"
+ width="200">
+ bottom 300 left 10, should delta_bottom
+ </text>
+ <text
+ type="string"
+ length="1"
+ height="16"
+ layout="topleft"
+ left_pad="40"
+ top_delta="0"
+ width="200">
+ bottom 300 left 250, should delta_left
+ </text>
+ <text
+ type="string"
+ length="1"
+ height="16"
+ layout="topleft"
+ left="10"
+ top="204"
+ width="200">
+ bottom 280 left 10, should absolute position
+ </text>
+ <text
+ type="string"
+ length="1"
+ height="16"
+ layout="topleft"
+ left_pad="40"
+ top_delta="-2"
+ width="200">
+ bottom 282 left 250, should delta_left and delta_bottom
+ </text>
+ <text
+ type="string"
+ length="1"
+ height="16"
+ layout="topleft"
+ left="10"
+ top="234"
+ width="200">
+ bottom 250 left 10, should absolute position
+ </text>
+ <text
+ type="string"
+ length="1"
+ height="16"
+ layout="topleft"
+ left="250"
+ top="244"
+ width="200">
+ bottom 240 left 250, should absolute position
+ </text>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_line_editor.xml b/indra/newview/skins/default/xui/en/floater_test_line_editor.xml
new file mode 100644
index 0000000000..fe6ec91709
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_test_line_editor.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="500"
+ layout="topleft"
+ name="floater_test_line_editor"
+ help_topic="floater_test_line_editor"
+ width="400">
+ <line_editor
+ height="20"
+ layout="topleft"
+ left="10"
+ name="enabled_line_editor"
+ top="40"
+ tool_tip="enabled line editor"
+ width="200">
+ Enabled line editor
+ </line_editor>
+ <line_editor
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="ascii_line_editor"
+ prevalidate_callback="ascii"
+ tool_tip="ascii line editor"
+ top_pad="10"
+ width="200">
+ ASCII only line editor
+ </line_editor>
+ <line_editor
+ enabled="false"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="disabled_line_editor"
+ top_pad="10"
+ tool_tip="disabled line editor"
+ width="200">
+ Disabled line editor
+ </line_editor>
+ <line_editor
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="enabled_colored_line_editor"
+ text_color="1 0 0 1"
+ top_pad="10"
+ tool_tip="enabled colored line editor"
+ width="200">
+ Enabled red-text line editor
+ </line_editor>
+ <line_editor
+ enabled="false"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="disabled_colored_line_editor"
+ text_readonly_color="1 0 0 1"
+ top_pad="10"
+ tool_tip="disabled colored line editor"
+ width="200">
+ Disabled red-text line editor
+ </line_editor>
+ <line_editor
+ height="20"
+ left_delta="0"
+ name="left_pad_editor"
+ text_pad_left="25"
+ top_pad="10"
+ width="200">
+ 25 px left text padding
+ </line_editor>
+ <line_editor
+ height="20"
+ left_delta="0"
+ name="left_pad_editor"
+ text_pad_right="75"
+ top_pad="10"
+ width="200">
+ 75 px right text padding
+ </line_editor>
+ <line_editor
+ height="20"
+ left_delta="0"
+ name="left_pad_editor"
+ text_pad_left="25"
+ text_pad_right="75"
+ top_pad="10"
+ width="200">
+ 25 px left 75 px right text padding
+ </line_editor>
+ <!-- "search_editor" is a specialized line_editor that shows read-only
+ help text until the user clicks in the widget. -->
+ <search_editor
+ follows="left|top|right"
+ height="20"
+ label="Type here to search"
+ layout="topleft"
+ left_delta="0"
+ name="search editor"
+ tool_tip="search editor"
+ top_pad="10"
+ width="200" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_list_view.xml b/indra/newview/skins/default/xui/en/floater_test_list_view.xml
new file mode 100644
index 0000000000..247c705687
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_test_list_view.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="400"
+ layout="topleft"
+ name="floater_test_list_view"
+ help_topic="floater_test_list_view"
+ width="400">
+ <!-- intentionally empty -->
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_navigation_bar.xml b/indra/newview/skins/default/xui/en/floater_test_navigation_bar.xml
new file mode 100644
index 0000000000..c6b4cca6b9
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_test_navigation_bar.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="200"
+ layout="topleft"
+ name="floater_test_navigation_bar"
+ help_topic="floater_test_navigation_bar"
+ width="900">
+ <panel
+ name="navigation_bar"
+ filename="panel_navigation_bar.xml"
+ left="10"
+ right="-10"
+ top="30"
+ height="100"
+ border="true"
+ />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_radiogroup.xml b/indra/newview/skins/default/xui/en/floater_test_radiogroup.xml
new file mode 100644
index 0000000000..7ef2d97cdc
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_test_radiogroup.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="400"
+ layout="topleft"
+ name="floater_test_radiogroup"
+ help_topic="floater_test_radiogroup"
+ width="400">
+ <radio_group
+ height="54"
+ layout="topleft"
+ left="10"
+ name="parcel_voice_channel"
+ top="46"
+ width="219">
+ <radio_item
+ height="16"
+ label="Use the Estate spatial channel"
+ layout="topleft"
+ left="3"
+ name="Estate"
+ top="3"
+ width="463" />
+ <radio_item
+ height="16"
+ label="Use a private spatial channel"
+ layout="topleft"
+ left_delta="0"
+ name="Private"
+ top_delta="16"
+ width="463" />
+ <radio_item
+ height="16"
+ label="Disable spatial audio on this parcel"
+ layout="topleft"
+ left_delta="0"
+ name="Disabled"
+ top_delta="16"
+ width="463" />
+ </radio_group>
+ <radio_group
+ height="50"
+ layout="topleft"
+ left_delta="0"
+ name="simple_radio_group"
+ top_pad="50"
+ width="150">
+ <radio_item
+ bottom="20"
+ height="16"
+ label="Label in label attribute"
+ layout="topleft"
+ name="label_radio_item" />
+ <radio_item
+ bottom_delta="20"
+ height="16"
+ label="Label in text contents"
+ layout="topleft"
+ name="contents_radio_item" />
+ </radio_group>
+ <radio_group
+ draw_border="false"
+ height="50"
+ layout="topleft"
+ left_delta="0"
+ name="no_border_radio_group"
+ top_pad="50"
+ width="150">
+ <radio_item
+ bottom="20"
+ height="16"
+ label="No Border Foo"
+ layout="topleft"
+ name="foo_radio_item" />
+ <radio_item
+ bottom_delta="20"
+ height="16"
+ label="No Border Bar"
+ layout="topleft"
+ name="bar_item" />
+ </radio_group>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_slider.xml b/indra/newview/skins/default/xui/en/floater_test_slider.xml
new file mode 100644
index 0000000000..85d8bb2bb1
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_test_slider.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="500"
+ layout="topleft"
+ name="floater_test_slider"
+ help_topic="floater_test_slider"
+ width="450">
+ <slider
+ height="20"
+ label="Generic Slider"
+ layout="topleft"
+ left="10"
+ name="generic_slider"
+ top="40"
+ width="250" />
+ <slider
+ height="20"
+ label="Callback Slider"
+ layout="topleft"
+ left_delta="0"
+ name="callback_slider"
+ top_pad="20"
+ width="400">
+ <slider.mouse_up_callback
+ function="Test.TestCallback"
+ parameter="test" />
+ </slider>
+ <slider
+ height="20"
+ increment="1"
+ initial_value="2.0"
+ label="Value Slider"
+ layout="topleft"
+ left_delta="0"
+ max_val="5"
+ min_val="1"
+ name="value_slider"
+ top_pad="20"
+ width="250" />
+ <slider
+ height="20"
+ label="Mini Slider 1"
+ layout="topleft"
+ left_delta="0"
+ name="mini_slider_1"
+ top_pad="20"
+ width="200" />
+ <slider
+ height="20"
+ label="Mini Slider 2"
+ layout="topleft"
+ left_pad="20"
+ name="mini_slider_2"
+ top_delta="0"
+ width="200" />
+ <slider_bar
+ bottom="320"
+ height="100"
+ left="20"
+ name="slider_bar_vertical"
+ orientation="vertical"
+ width="20" />
+ <slider_bar
+ bottom="300"
+ height="20"
+ increment="1"
+ initial_value="2.0"
+ label="Slider Bar"
+ layout="topleft"
+ max_val="5"
+ min_val="1"
+ left_pad="20"
+ name="slider_bar"
+ width="300" />
+ <slider
+ bottom="360"
+ decimal_digits="1"
+ height="20"
+ label="Red Slider"
+ label_width="100"
+ layout="topleft"
+ name="red_slider"
+ text_color="red"
+ text_width="40" />
+ <slider
+ width ="140"
+ bottom="490"
+ decimal_digits="1"
+ height="100"
+ left="20"
+ label="Red Slider Vertical"
+ label_width="100"
+ layout="topleft"
+ name="red_slider_vertical"
+ text_color="red"
+ orientation="vertical"
+ text_width="20" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_spinner.xml b/indra/newview/skins/default/xui/en/floater_test_spinner.xml
new file mode 100644
index 0000000000..3c44a4884d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_test_spinner.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="400"
+ layout="topleft"
+ name="floater_test_spinner"
+ help_topic="floater_test_spinner"
+ width="450">
+ <spinner
+ height="32"
+ label="Generic Spinner"
+ layout="topleft"
+ left="10"
+ label_width="100"
+ name="generic_spinner"
+ top="40"
+ width="350" />
+ <spinner
+ height="20"
+ label="Callback Spinner"
+ label_width="100"
+ layout="topleft"
+ left_delta="0"
+ name="callback_spinner"
+ top_pad="20"
+ width="400" />
+ <spinner
+ height="20"
+ label="Colorful Spinner"
+ layout="topleft"
+ left_delta="0"
+ name="colorful_spinner"
+ top_pad="20"
+ width="250" />
+ <spinner
+ height="20"
+ increment="1"
+ initial_value="2.0"
+ label="Value Spinner"
+ layout="topleft"
+ left_delta="0"
+ max_val="5"
+ min_val="1"
+ name="value_spinner"
+ top_pad="20"
+ width="250" />
+ <spinner
+ height="20"
+ label="Mini Spinner 1"
+ layout="topleft"
+ left_delta="0"
+ name="mini_spinner_1"
+ top_pad="20"
+ width="200" />
+ <spinner
+ height="20"
+ label="Mini Spinner 2"
+ layout="topleft"
+ left_pad="20"
+ name="mini_spinner_2"
+ top_delta="0"
+ width="200" />
+ <spinner
+ control_name="RenderFogRatio"
+ decimal_digits="1"
+ height="20"
+ label="Control Spinner"
+ layout="topleft"
+ left="10"
+ max_val="20"
+ min_val="10"
+ name="control_spinner"
+ top="260"
+ width="250" />
+ <spinner
+ follows="left"
+ height="20"
+ label="Follows Left"
+ label_width="85"
+ layout="topleft"
+ left_delta="0"
+ name="follows_left"
+ top_pad="20"
+ width="250" />
+ <spinner
+ follows="right"
+ height="20"
+ label="Follows Right"
+ label_width="85"
+ layout="topleft"
+ left_delta="0"
+ name="follows_right"
+ top_pad="20"
+ width="250" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_text_editor.xml b/indra/newview/skins/default/xui/en/floater_test_text_editor.xml
new file mode 100644
index 0000000000..8be0c28c5c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_test_text_editor.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="600"
+ layout="topleft"
+ name="floater_test_text_editor"
+ width="800">
+ <text_editor
+ height="50"
+ follows="top|left|bottom"
+ left="10"
+ name="test_text_editor"
+ tool_tip="text editor"
+ top="25"
+ width="200">
+ Text Editor
+ </text_editor>
+ <text_editor
+ height="50"
+ follows="top|left|bottom"
+ font="SansSerif"
+ left="10"
+ name="test_text_editor"
+ tool_tip="text editor"
+ top_pad="10"
+ width="200">
+ This contains long text and should scroll horizontally to the right
+ </text_editor>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_textbox.xml b/indra/newview/skins/default/xui/en/floater_test_textbox.xml
new file mode 100644
index 0000000000..8fc2677cbe
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_test_textbox.xml
@@ -0,0 +1,253 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="600"
+ layout="topleft"
+ name="floater_test_textbox"
+ help_topic="floater_test_textbox"
+ width="800">
+ <text
+ type="string"
+ length="1"
+ height="90"
+ layout="topleft"
+ left="10"
+ top_pad="30"
+ width="300">
+ First line of multiple lines
+Second line of multiple lines
+Third line of multiple lines
+Fourth line of multiple lines
+Fifth line of multiple lines
+ </text>
+ <text
+ clip_partial="true"
+ top_pad="10"
+ left="10"
+ width="267"
+ height="28"
+ layout="topleft"
+ follows="right|left"
+ text_color="white"
+ use_ellipses="true"
+ word_wrap="true"
+ mouse_opaque="false"
+ name="title" >
+ This text has word_wrap set true, use_ellipses set true, and clip_partial set true, so it should wrap around, spilling over to the last line, then clip the last partial line and show ellipses to indicate there is more text
+ </text>
+
+ <text
+ font="SansSerif"
+ font.style="BOLD"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ top_pad="10"
+ width="300">
+ SansSerif BOLD
+ </text>
+ <text
+ font="SansSerif"
+ font.style="BOLD|UNDERLINE"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ top_pad="10"
+ width="300">
+ SansSerif BOLD UNDERLINE
+ </text>
+ <text
+ bottom="390"
+ left="10"
+ name="right_aligned_text"
+ width="300"
+ halign="right"
+ top_pad="10">
+ Right aligned text
+ </text>
+ <text
+ bottom="390"
+ left="10"
+ name="centered_text"
+ width="300"
+ halign="center"
+ top_pad="10">
+ Centered text
+ </text>
+ <text
+ left="10"
+ name="left_aligned_text"
+ width="300"
+ halign="left"
+ top_pad="10">
+ Left aligned text
+ </text>
+ <text
+ left="10"
+ name="v_pad_text"
+ height="40"
+ width="300"
+ halign="left"
+ top_pad="10"
+ v_pad="10">
+ v_pad = 10, height = 40
+ </text>
+ <text
+ left="10"
+ name="v_pad_text"
+ height="40"
+ width="300"
+ halign="left"
+ top_pad="10"
+ h_pad="30">
+ h_pad = 30, height = 40
+ </text>
+ <text
+ top_pad="10"
+ left="10"
+ right="-10"
+ height="20"
+ follows="top|left"
+ font.name="SansSerifSmall"
+ name="test_text10"
+ tool_tip="text">
+ SansSerifSmall
+ The åŽæ–‡ç»†é»‘ brown fox ヒラキjumped over the lazy dog.
+ </text>
+ <text
+ top_pad="10"
+ left="10"
+ right="-10"
+ height="25"
+ follows="top|left"
+ font.name="SansSerifMedium"
+ name="test_text11"
+ tool_tip="text">
+ SansSerif
+ The åŽæ–‡ç»†é»‘ brown fox ヒラキjumped over the lazy dog.
+ </text>
+ <text
+ top_pad="10"
+ left="10"
+ right="-10"
+ follows="top|left"
+ height="26"
+ font.name="SansSerifLarge"
+ name="test_text12"
+ tool_tip="text">
+ SansSerifLarge
+ The åŽæ–‡ç»†é»‘ brown fox ヒラキjumped over the lazy dog.
+ </text>
+ <text
+ top_pad="10"
+ left="10"
+ height="35"
+ right="-10"
+ follows="top|left"
+ font.name="SansSerifHuge"
+ name="test_text13"
+ tool_tip="text">
+ SansSerifHuge
+ The åŽæ–‡ç»†é»‘ brown fox ヒラキjumped over the lazy dog.
+ </text>
+
+<!-- next column -->
+ <text_editor
+ height="50"
+ follows="top|left|bottom"
+ left="400"
+ name="test_text_editor"
+ tool_tip="text editor"
+ top="25"
+ width="200">
+ Text Editor
+ </text_editor>
+ <text_editor
+ height="50"
+ follows="top|left|bottom"
+ left_delta="0"
+ name="long_text_editor"
+ tool_tip="text editor"
+ top_pad="10"
+ width="200">
+Text Editor
+with multiple
+lines of text
+and hence a
+scroll bar
+ </text_editor>
+ <text_editor
+ height="50"
+ follows="top|left|bottom"
+ left_delta="0"
+ max_length="65536"
+ name="blob_text_editor"
+ tool_tip="text editor"
+ top_pad="10"
+ width="200"
+ word_wrap="true">
+Second Life is brought to you by Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les and many others.
+ </text_editor>
+ <text_editor
+ height="50"
+ follows="top|left|bottom"
+ font="Monospace"
+ left_delta="0"
+ name="monospace_text_editor"
+ tool_tip="text editor"
+ top_pad="10"
+ width="200">
+Text Editor
+with multiple
+lines of text
+and hence a
+scroll bar gjyrrr
+ </text_editor>
+ <text_editor
+ border_visible="true"
+ height="50"
+ follows="top|left|bottom"
+ font="Monospace"
+ left_delta="0"
+ name="monospace_text_editor"
+ tool_tip="text editor"
+ top_pad="10"
+ width="200">
+Text Editor
+with multiple
+lines of text
+and hence a
+scroll bar gjyrrr
+ </text_editor>
+ <text_editor
+ height="50"
+ follows="top|left|bottom"
+ font="SansSerif"
+ left_delta="0"
+ name="sansserif_text_editor"
+ tool_tip="text editor"
+ top_pad="10"
+ width="200">
+Text Editor
+with multiple
+lines of text
+and hence a
+scroll bar gjyrrr
+ </text_editor>
+
+ <text
+ height="40"
+ follows="top|left|bottom"
+ layout="topleft"
+ name="test_text_box"
+ tool_tip="text box"
+ top_pad="5"
+ width="200">
+Text box
+with
+multiple lines
+and too many lines
+to actually fit
+ </text>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_widgets.xml b/indra/newview/skins/default/xui/en/floater_test_widgets.xml
new file mode 100644
index 0000000000..2f88c234cc
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_test_widgets.xml
@@ -0,0 +1,450 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- Sample "floater" window with examples of common widgets.
+
+ Notes:
+ XML UI (XUI) files use spaces for indentation, not tabs.
+ All position values are in pixels.
+ For now, each widget must contain attribute layout="topleft".
+ 0,0 is the top-left corner of the floater.
+ Each widget must have a unique name attribute.
+ If a widget is aligned with the one before it, use relative positioning:
+ top_pad
+ top_delta
+ left_pad
+ left_delta
+ Otherwise specify location with left and top attributes.
+-->
+<floater
+ legacy_header_height="18"
+ can_dock="true"
+ can_resize="true"
+ title="TEST FLOATER"
+ height="500"
+ min_width="850"
+ min_height="500"
+ layout="topleft"
+ name="floater_test_widgets"
+ help_topic="floater_test_widgets"
+ width="850">
+
+ <!-- Strings are used by C++ code for localization. They are not visible
+ unless the C++ code uses them to fill in another widget. -->
+ <floater.string
+ name="sample_string"
+ value="Sample String" />
+ <floater.string
+ name="other_string"
+ value="Other String" />
+
+ <!-- Floaters can contain drop-down menus.
+ The menu_bar widget contains the inividual menus.
+ The width is automatically computed to fit the labels. -->
+ <menu_bar
+ height="18"
+ layout="topleft"
+ follows="top|left"
+ tool_tip="menu"
+ left="2"
+ name="test_menu_bar"
+ top="16">
+ <menu
+ height="16"
+ label="Menu"
+ layout="topleft"
+ tear_off="true"
+ left="0"
+ name="Menu"
+ top="-32"
+ width="128">
+ <!-- menu_item_call will trigger a function call in the C++ code -->
+ <menu_item_call
+ label="Menu Item 1"
+ layout="topleft"
+ name="test_menu_item_1" />
+ <!-- menu_item_separator is a horizontal line used to separate sections
+ of a menu. In general, menus should be divided into chunks of
+ no more than 7 items separated by menu_item_separators. -->
+ <menu_item_separator/>
+ <menu_item_call
+ label="Menu Item 2"
+ layout="topleft"
+ name="test_menu_item_2" />
+ </menu>
+ </menu_bar>
+
+ <!-- "text" is one or more read-only lines of text.
+ It can be made clickable but this requires C++ code
+ support. URLs are not automatically underlined. -->
+ <text
+ bottom="55"
+ layout="topleft"
+ follows="top|left"
+ left="10"
+ height="16">
+ For widget list see https://wiki.lindenlab.com/wiki/Viewer:UI/Widgets
+ </text>
+
+ <!-- First column -->
+
+ <button
+ height="20"
+ follows="top|left"
+ label="Button"
+ layout="topleft"
+ left_delta="0"
+ name="test_button"
+ tool_tip="button"
+ top="80"
+ width="100" />
+ <!-- "flyout_button" is a button that can spawn a menu -->
+ <flyout_button
+ follows="top|left"
+ height="20"
+ label="Flyout"
+ layout="topleft"
+ left_delta="0"
+ name="fly_btn"
+ top_pad="15"
+ tool_tip="flyout button"
+ width="100">
+ <flyout_button.item
+ label="Item 1"
+ value="shout" />
+ <flyout_button.item
+ label="Item 2"
+ value="say" />
+ <flyout_button.item
+ label="Item 3"
+ value="whisper" />
+ </flyout_button>
+ <check_box
+ bottom_delta="35"
+ label="Checkbox"
+ layout="topleft"
+ tool_tip="checkbox"
+ name="test_checkbox" />
+ <check_box
+ top_pad="5"
+ enabled="false"
+ label="Checkbox Disabled"
+ tool_tip="checkbox disabled"
+ name="test_checkbox_disabled" />
+ <!-- "combo_box" is a pop-menu of items. Optionally the box itself can
+ contain a general purpose line input editor, allowing the user to
+ provide input that is not a list item. -->
+ <combo_box
+ bottom_delta="35"
+ follows="top|left"
+ height="16"
+ width="150"
+ label="Combobox"
+ layout="topleft"
+ tool_tip="combo box"
+ name="test_combo_box">
+ <combo_box.item
+ name="item1"
+ label="Combobox Item 1" />
+ <combo_box.item
+ name="item2"
+ label="Combobox Item 2" />
+ </combo_box>
+ <!-- "icon" is a read-only image. The image_name must match an entry
+ in textures.xml. We support TGA and PNG for UI images. -->
+ <icon
+ height="16"
+ image_name="icon_avatar_online.tga"
+ layout="topleft"
+ left_delta="0"
+ tool_tip="icon"
+ name="test_icon"
+ top_pad="40"
+ width="16" />
+ <!-- "line_editor" allows a single line of editable text input.
+ The contents of this XML node are used as the initial value for
+ the text. -->
+ <line_editor
+ height="20"
+ follows="top|left"
+ layout="topleft"
+ left_delta="0"
+ name="test_line_editor"
+ top_pad="20"
+ tool_tip="line editor"
+ width="200">
+ Line Editor Sample Text
+ </line_editor>
+ <!-- "filter_editor" is a specialized line_editor that shows read-only
+ help text until the user clicks in the widget. -->
+ <filter_editor
+ follows="left|top"
+ height="20"
+ label="Type here to search"
+ layout="topleft"
+ left_delta="0"
+ name="search editor"
+ tool_tip="search editor"
+ top_pad="30"
+ width="200" />
+ <!-- "progress_bar" percent completed gets set in C++ code -->
+ <progress_bar
+ height="16"
+ follows="top|left"
+ layout="topleft"
+ left_delta="0"
+ name="test_progress_bar"
+ top_pad="30"
+ tool_tip="progress bar"
+ width="200" />
+ <!-- "stat_view" is a container for statistics graphs. It is only used
+ for debugging/diagnostic displays. -->
+ <stat_view
+ height="250"
+ label="Statistics View"
+ layout="topleft"
+ left_delta="0"
+ name="axis_view"
+ show_label="true"
+ top_pad="30"
+ tool_tip="stat view"
+ width="200">
+ <stat_bar
+ width="100"
+ bar_max="100"
+ bottom_delta="30"
+ label="Test Stat"
+ layout="topleft"
+ stat="stat"
+ bar_min="20"
+ name="test_stat_bar" />
+ </stat_view>
+
+ <!-- New column -->
+
+ <!-- "radio_group" is a set of mutually exclusive choices, like the buttons
+ on a car radio that allow a single radio station to be chosen. -->
+ <radio_group
+ height="40"
+ layout="topleft"
+ left_pad="90"
+ name="size_radio_group"
+ tool_tip="radio group"
+ top="80"
+ width="200">
+ <radio_item
+ bottom="20"
+ label="Radio 1"
+ layout="topleft"
+ name="small_radio_item" />
+ <radio_item
+ label="Radio 2"
+ layout="topleft"
+ name="large_radio_item" />
+ </radio_group>
+ <!-- "scroll_list" is a scrolling list of columnar data. -->
+ <scroll_list
+ bottom_delta="100"
+ follows="top|left"
+ height="80"
+ draw_heading="true"
+ tool_tip="scroll list"
+ layout="topleft">
+ <scroll_list.columns
+ dynamic_width="true"
+ name="first_column"
+ label="Column A"/>
+ <scroll_list.columns
+ dynamic_width="true"
+ name="second_column"
+ label="Column B"/>
+ <row>
+ <column column="first_column">short text</column>
+ <column column="second_column">more short text</column>
+ </row>
+ <row>
+ <column column="first_column">this is some longer text</column>
+ <column column="second_column">and here is some more long text</column>
+ </row>
+ </scroll_list>
+ <!-- "slider" is a horizontal input widget for numerical data. -->
+ <slider
+ bottom_delta="45"
+ follows="top|left"
+ layout="topleft"
+ min_val="0"
+ max_val="100"
+ initial_value="20"
+ label="Slider"
+ name="test_slider"
+ tool_tip="slider"
+ width="200" />
+ <!-- "spinner" is a numerical input widget with an up and down arrow to
+ change the value. -->
+ <spinner
+ bottom_delta="35"
+ follows="top|left"
+ label="Spinner"
+ layout="topleft"
+ label_width="45"
+ name="test_spinner"
+ tool_tip="spinner"/>
+ <text
+ bottom_delta="50"
+ follows="top|left"
+ font.name="SansSerifSmall"
+ font.style = "UNDERLINE"
+ layout="topleft"
+ name="test_text"
+ tool_tip="text">
+ Text (underlined)
+ </text>
+ <text
+ top_pad="10"
+ follows="top|left"
+ layout="topleft"
+ width="60"
+ use_ellipses="true"
+ name="test_text"
+ tool_tip="text">
+ Truncated text here
+ </text>
+ <!-- "text_editor" is a multi-line text input widget, similar to
+ textarea in HTML. -->
+ <text_editor
+ height="40"
+ follows="top|left|bottom"
+ layout="topleft"
+ left_delta="0"
+ name="test_text_editor"
+ tool_tip="text editor"
+ top_pad="25"
+ width="200">
+ Text Editor
+ </text_editor>
+ <text
+ height="40"
+ follows="top|left|bottom"
+ layout="topleft"
+ name="test_text_box"
+ tool_tip="text box"
+ top_pad="5"
+ width="200">
+ Text box
+with
+multiple lines
+and too
+many
+line to actually fit
+ </text>
+ <!-- And a third column -->
+
+ <!-- "tab_container" is a holder for multiple panels of UI widgets.
+ Tabs can appear at the top, bottom, or left of the container. -->
+ <tab_container
+ follows="all"
+ height="400"
+ halign="center"
+ layout="topleft"
+ left="525"
+ name="group_tab_container"
+ tab_position="top"
+ tab_height="20"
+ tool_tip="tab container"
+ top="80"
+ width="300">
+ <!-- "panel" is a container for widgets. It is automatically resized to
+ fit the parent tab_container. -->
+ <panel
+ border="true"
+ label="Tab 1 - Color"
+ layout="topleft"
+ name="panel2">
+ <!-- "color_swatch" displays a color and spawns a color picker when
+ clicked. -->
+ <color_swatch
+ can_apply_immediately="true"
+ color="0.3 0.6 0.9 1"
+ follows="left|top"
+ height="90"
+ layout="topleft"
+ left="10"
+ label="Color Swatch 1"
+ name="swatch1"
+ tool_tip="Color Swatch: Click to open Color Picker"
+ top="10"
+ width="80" />
+ <color_swatch
+ can_apply_immediately="true"
+ color="1 0 1 1"
+ follows="left|top"
+ height="90"
+ label="Color Swatch 2"
+ layout="topleft"
+ left_pad="10"
+ name="swatch2"
+ tool_tip="Color Swatch: Click to open Color Picker"
+ top_delta="0"
+ width="80" />
+ <text
+ top_pad="10"
+ left="10"
+ width="250"
+ follows="top|left"
+ font.name="Monospace"
+ name="test_text10"
+ tool_tip="text">
+ Monospace Button Flyout Checkbox
+ </text>
+ <text
+ top_pad="10"
+ left="10"
+ width="250"
+ follows="top|left"
+ font.name="SansSerifSmall"
+ name="test_text10"
+ tool_tip="text">
+ SansSerifSmall. РуÑÑкий 中文 (简体)
+ </text>
+ <text
+ top_pad="10"
+ left="10"
+ width="250"
+ follows="top|left"
+ font.name="SansSerif"
+ name="test_text11"
+ tool_tip="text">
+ SansSerif. РуÑÑкий 中文 (简体)
+ </text>
+ <text
+ top_pad="10"
+ left="10"
+ width="250"
+ follows="top|left"
+ font.name="SansSerifLarge"
+ name="test_text12"
+ tool_tip="text">
+ SansSerifLarge. РуÑÑкий 中文 (简体)
+ </text>
+ <text
+ top_pad="10"
+ left="10"
+ width="250"
+ follows="top|left"
+ font.name="SansSerifHuge"
+ name="test_text13"
+ tool_tip="text">
+ SansSerifHuge. РуÑÑкий 中文 (简体)
+ </text>
+ </panel>
+ <!-- panels can also refer to other floaters or panels -->
+ <panel
+ border="true"
+ filename="floater_test_checkbox.xml"
+ height="225"
+ label="Tab 2 - Checkbox"
+ layout="topleft"
+ left_delta="0"
+ name="tab2"
+ top_delta="159"
+ width="250" />
+ </tab_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
new file mode 100644
index 0000000000..cad7d72ed7
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ can_resize="true"
+ height="290"
+ layout="topleft"
+ min_height="290"
+ min_width="410"
+ name="texture picker"
+ help_topic="texture_picker"
+ title="PICK: TEXTURE"
+ width="410">
+ <floater.string
+ name="choose_picture">
+ Click to choose a picture
+ </floater.string>
+ <floater.string
+ name="pick title">
+ Pick:
+ </floater.string>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ text_color="White"
+ font="SansSerifBig"
+ halign="center"
+ height="17"
+ layout="topleft"
+ left="4"
+ name="Multiple"
+ top="96"
+ width="163">
+ Multiple textures
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="14"
+ layout="topleft"
+ left_delta="0"
+ name="unknown"
+ top_pad="80"
+ width="163">
+ Size: [DIMENSIONS]
+ </text>
+ <button
+ enabled="false"
+ follows="left|bottom"
+ height="20"
+ label="Default"
+ label_selected="Default"
+ layout="topleft"
+ left_delta="0"
+ name="Default"
+ top_pad="4"
+ width="80" />
+ <button
+ enabled="false"
+ follows="left|bottom"
+ height="20"
+ label="None"
+ label_selected="None"
+ layout="topleft"
+ left_pad="4"
+ name="None"
+ top_delta="0"
+ width="80" />
+ <button
+ follows="left|bottom"
+ height="20"
+ label="Blank"
+ label_selected="Blank"
+ layout="topleft"
+ left="4"
+ name="Blank"
+ top_pad="5"
+ width="80" />
+ <button
+ follows="left|bottom"
+ height="28"
+ image_selected="eye_button_active.tga"
+ image_unselected="eye_button_inactive.tga"
+ layout="topleft"
+ left_pad="50"
+ top_delta="3"
+ name="Pipette"
+ width="28" />
+ <check_box
+ follows="left|bottom"
+ height="20"
+ initial_value="true"
+ label="Apply now"
+ layout="topleft"
+ left="4"
+ name="apply_immediate_check"
+ top="262"
+ width="120" />
+ <filter_editor
+ follows="left|top|right"
+ height="23"
+ label="Filter Textures"
+ layout="topleft"
+ left="175"
+ name="inventory search editor"
+ top="20"
+ width="231" />
+ <inventory_panel
+ allow_multi_select="false"
+ bg_visible="true"
+ bg_alpha_color="DkGray2"
+ border="false"
+ follows="all"
+ height="200"
+ layout="topleft"
+ left_delta="0"
+ name="inventory panel"
+ top_pad="4"
+ width="231" />
+ <check_box
+ height="14"
+ initial_value="false"
+ label="Show folders"
+ layout="topleft"
+ name="show_folders_check"
+ top_pad="0"
+ left_delta="-3"
+ width="200" />
+ <button
+ follows="right|bottom"
+ height="20"
+ label="OK"
+ label_selected="OK"
+ layout="topleft"
+ right="-120"
+ name="Select"
+ width="100" />
+ <button
+ follows="right|bottom"
+ height="20"
+ label="Cancel"
+ label_selected="Cancel"
+ layout="topleft"
+ right="-10"
+ left_pad="5"
+ name="Cancel"
+ width="100" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
new file mode 100644
index 0000000000..f1aa5c27c1
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -0,0 +1,2933 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ follows="left|top|right"
+ height="570"
+ layout="topleft"
+ bg_opaque_image="Window_NoTitle_Foreground"
+ bg_alpha_image="Window_NoTitle_Background"
+ name="toolbox floater"
+ help_topic="toolbox_floater"
+ save_rect="true"
+ short_title="BUILD TOOLS"
+ single_instance="true"
+ sound_flags="0"
+ width="280">
+ <floater.string
+ name="status_rotate">
+ Drag colored bands to rotate object
+ </floater.string>
+ <floater.string
+ name="status_scale">
+ Click and drag to stretch selected side
+ </floater.string>
+ <floater.string
+ name="status_move">
+ Drag to move, shift-drag to copy
+ </floater.string>
+ <floater.string
+ name="status_modifyland">
+ Click and hold to modify land
+ </floater.string>
+ <floater.string
+ name="status_camera">
+ Click and drag to move camera
+ </floater.string>
+ <floater.string
+ name="status_grab">
+ Drag to move, Ctrl to lift, Ctrl+Shift to rotate
+ </floater.string>
+ <floater.string
+ name="status_place">
+ Click inworld to build
+ </floater.string>
+ <floater.string
+ name="status_selectland">
+ Click and drag to select land
+ </floater.string>
+ <floater.string
+ name="grid_screen_text">
+ Screen
+ </floater.string>
+ <floater.string
+ name="grid_local_text">
+ Local
+ </floater.string>
+ <floater.string
+ name="grid_world_text">
+ World
+ </floater.string>
+ <floater.string
+ name="grid_reference_text">
+ Reference
+ </floater.string>
+ <floater.string
+ name="grid_attachment_text">
+ Attachment
+ </floater.string>
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Tool_Zoom"
+ image_disabled_selected="Tool_Zoom"
+ image_selected="Tool_Zoom"
+ image_unselected="Tool_Zoom"
+ layout="topleft"
+ left="10"
+ name="button focus"
+ tool_tip="Focus"
+ width="20">
+ <button.commit_callback
+ function="BuildTool.setTool"
+ parameter="Focus" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Tool_Grab"
+ image_disabled_selected="Tool_Grab"
+ image_selected="Tool_Grab"
+ image_unselected="Tool_Grab"
+ layout="topleft"
+ left_pad="20"
+ name="button move"
+ tool_tip="Move"
+ width="20">
+ <button.commit_callback
+ function="BuildTool.setTool"
+ parameter="Move" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Tool_Face"
+ image_disabled_selected="Tool_Face"
+ image_selected="Tool_Face"
+ image_unselected="Tool_Face"
+ layout="topleft"
+ left_pad="20"
+ name="button edit"
+ tool_tip="Edit"
+ width="20">
+ <button.commit_callback
+ function="BuildTool.setTool"
+ parameter="Edit" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Tool_Create"
+ image_disabled_selected="Tool_Create"
+ image_selected="Tool_Create"
+ image_unselected="Tool_Create"
+ layout="topleft"
+ left_pad="20"
+ name="button create"
+ tool_tip="Create"
+ width="20">
+ <button.commit_callback
+ function="BuildTool.setTool"
+ parameter="Create" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Tool_Dozer"
+ image_disabled_selected="Tool_Dozer"
+ image_selected="Tool_Dozer"
+ image_unselected="Tool_Dozer"
+ layout="topleft"
+ left_pad="20"
+ name="button land"
+ tool_tip="Land"
+ width="20">
+ <button.commit_callback
+ function="BuildTool.setTool"
+ parameter="Land" />
+ </button>
+ <text
+ height="30"
+ word_wrap="true"
+ use_ellipses="true"
+ type="string"
+ text_color="LabelSelectedDisabledColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left="8"
+ name="text status"
+ top_pad="3"
+ width="275">
+ Drag to move, shift-drag to copy
+ </text>
+ <radio_group
+ layout="topleft"
+ left="10"
+ height="70"
+ top="54"
+ name="focus_radio_group">
+ <radio_item
+ top_pad="6"
+ label="Zoom"
+ layout="topleft"
+ name="radio zoom" />
+ <radio_item
+ top_pad="6"
+ label="Orbit (Ctrl)"
+ layout="topleft"
+ name="radio orbit" />
+ <radio_item
+ top_pad="6"
+ label="Pan (Ctrl+Shift)"
+ layout="topleft"
+ name="radio pan" />
+ <radio_group.commit_callback
+ function="BuildTool.commitRadioFocus"/>
+ </radio_group>
+ <slider_bar
+ follows="left|top"
+ height="14"
+ increment="0.01"
+ initial_value="0.125"
+ layout="topleft"
+ max_val="0.5"
+ top_delta="-2"
+ left_delta="100"
+ name="slider zoom"
+ width="134">
+ <slider_bar.commit_callback
+ function="BuildTool.commitZoom"/>
+ </slider_bar>
+ <radio_group
+ left="10"
+ height="70"
+ top="54"
+ layout="topleft"
+ name="move_radio_group">
+ <radio_item
+ top_pad="6"
+ label="Move"
+ layout="topleft"
+ name="radio move" />
+ <radio_item
+ top_pad="6"
+ label="Lift (Ctrl)"
+ layout="topleft"
+ name="radio lift" />
+ <radio_item
+ top_pad="6"
+ label="Spin (Ctrl+Shift)"
+ layout="topleft"
+ name="radio spin" />
+ <radio_group.commit_callback
+ function="BuildTool.commitRadioMove"/>
+ </radio_group>
+ <radio_group
+ follows="left|top"
+ left="10"
+ top="54"
+ height="70"
+ layout="topleft"
+ name="edit_radio_group">
+ <radio_item
+ label="Move"
+ layout="topleft"
+ name="radio position" />
+ <radio_item
+ top_pad="6"
+ label="Rotate (Ctrl)"
+ layout="topleft"
+ name="radio rotate" />
+ <radio_item
+ top_pad="6"
+ label="Stretch (Ctrl+Shift)"
+ layout="topleft"
+ name="radio stretch" />
+ <radio_item
+ top_pad="6"
+ label="Select Face"
+ layout="topleft"
+ name="radio select face" />
+ <radio_group.commit_callback
+ function="BuildTool.commitRadioEdit"/>
+ </radio_group>
+ <check_box
+ left="10"
+ follows="left|top"
+ height="16"
+ control_name="EditLinkedParts"
+ label="Edit linked"
+ layout="topleft"
+ name="checkbox edit linked parts" >
+ <check_box.commit_callback
+ function="BuildTool.selectComponent"/>
+ </check_box>
+
+ <text
+ text_color="LtGray_50"
+ follows="top|left"
+ halign="left"
+ left="13"
+ name="RenderingCost"
+ tool_tip="Shows the rendering cost calculated for this object"
+ top_pad="9"
+ type="string"
+ width="100">
+ þ: [COUNT]
+ </text>
+ <check_box
+ control_name="ScaleUniform"
+ height="19"
+ label="Stretch Both Sides"
+ layout="topleft"
+ left="143"
+ name="checkbox uniform"
+ top="50"
+ width="134" />
+ <check_box
+ control_name="ScaleStretchTextures"
+ height="19"
+ initial_value="true"
+ label="Stretch Textures"
+ layout="topleft"
+ name="checkbox stretch textures"
+ top_pad="0"
+ width="134" />
+ <check_box
+ control_name="SnapEnabled"
+ height="20"
+ initial_value="true"
+ label="Snap to grid"
+ layout="topleft"
+ top_pad="0"
+ name="checkbox snap to grid"
+ width="134" />
+ <combo_box
+ height="23"
+ layout="topleft"
+ follows="left|top"
+ name="combobox grid mode"
+ tool_tip="Choose the type of grid ruler for positioning the object"
+ width="108">
+ <combo_box.item
+ label="World grid"
+ name="World"
+ value="World" />
+ <combo_box.item
+ label="Local grid"
+ name="Local"
+ value="Local" />
+ <combo_box.item
+ label="Reference grid"
+ name="Reference"
+ value="Reference" />
+ <combo_box.commit_callback
+ function="BuildTool.gridMode"/>
+ </combo_box>
+ <button
+ left_pad="0"
+ image_disabled="ForwardArrow_Disabled"
+ image_selected="ForwardArrow_Press"
+ image_unselected="ForwardArrow_Off"
+ layout="topleft"
+ name="Options..."
+ tool_tip="See more grid options"
+ top_delta="0"
+ right="-10"
+ width="18"
+ height="19" >
+ <button.commit_callback
+ function="BuildTool.gridOptions"/>
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Cube"
+ image_disabled_selected="Object_Cube"
+ image_selected="Object_Cube"
+ image_unselected="Object_Cube"
+ layout="topleft"
+ left="4"
+ name="ToolCube"
+ tool_tip="Cube"
+ top="51"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Prism"
+ image_disabled_selected="Object_Prism"
+ image_selected="Object_Prism"
+ image_unselected="Object_Prism"
+ layout="topleft"
+ left_delta="26"
+ name="ToolPrism"
+ tool_tip="Prism"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Pyramid"
+ image_disabled_selected="Object_Pyramid"
+ image_selected="Object_Pyramid"
+ image_unselected="Object_Pyramid"
+ layout="topleft"
+ left_delta="26"
+ name="ToolPyramid"
+ tool_tip="Pyramid"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Tetrahedron"
+ image_disabled_selected="Object_Tetrahedron"
+ image_selected="Object_Tetrahedron"
+ image_unselected="Object_Tetrahedron"
+ layout="topleft"
+ left_delta="26"
+ name="ToolTetrahedron"
+ tool_tip="Tetrahedron"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Cylinder"
+ image_disabled_selected="Object_Cylinder"
+ image_selected="Object_Cylinder"
+ image_unselected="Object_Cylinder"
+ layout="topleft"
+ left_delta="26"
+ name="ToolCylinder"
+ tool_tip="Cylinder"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Hemi_Cylinder"
+ image_disabled_selected="Object_Hemi_Cylinder"
+ image_selected="Object_Hemi_Cylinder"
+ image_unselected="Object_Hemi_Cylinder"
+ layout="topleft"
+ left_delta="26"
+ name="ToolHemiCylinder"
+ tool_tip="Hemicylinder"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Cone"
+ image_disabled_selected="Object_Cone"
+ image_selected="Object_Cone"
+ image_unselected="Object_Cone"
+ layout="topleft"
+ left_delta="26"
+ name="ToolCone"
+ tool_tip="Cone"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Hemi_Cone"
+ image_disabled_selected="Object_Hemi_Cone"
+ image_selected="Object_Hemi_Cone"
+ image_unselected="Object_Hemi_Cone"
+ layout="topleft"
+ left_delta="26"
+ name="ToolHemiCone"
+ tool_tip="Hemicone"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Sphere"
+ image_disabled_selected="Object_Sphere"
+ image_selected="Object_Sphere"
+ image_unselected="Object_Sphere"
+ layout="topleft"
+ left_delta="26"
+ name="ToolSphere"
+ tool_tip="Sphere"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Hemi_Sphere"
+ image_disabled_selected="Object_Hemi_Sphere"
+ image_selected="Object_Hemi_Sphere"
+ image_unselected="Object_Hemi_Sphere"
+ layout="topleft"
+ left_delta="26"
+ name="ToolHemiSphere"
+ tool_tip="Hemisphere"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Torus"
+ image_disabled_selected="Object_Torus"
+ image_selected="Object_Torus"
+ image_unselected="Object_Torus"
+ layout="topleft"
+ left="4"
+ name="ToolTorus"
+ tool_tip="Torus"
+ top="77"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Tube"
+ image_disabled_selected="Object_Tube"
+ image_selected="Object_Tube"
+ image_unselected="Object_Tube"
+ layout="topleft"
+ left_delta="26"
+ name="ToolTube"
+ tool_tip="Tube"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Ring"
+ image_disabled_selected="Object_Ring"
+ image_selected="Object_Ring"
+ image_unselected="Object_Ring"
+ layout="topleft"
+ left_delta="26"
+ name="ToolRing"
+ tool_tip="Ring"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Tree"
+ image_disabled_selected="Object_Tree"
+ image_selected="Object_Tree"
+ image_unselected="Object_Tree"
+ layout="topleft"
+ left_delta="26"
+ name="ToolTree"
+ tool_tip="Tree"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Grass"
+ image_disabled_selected="Object_Grass"
+ image_selected="Object_Grass"
+ image_unselected="Object_Grass"
+ layout="topleft"
+ left_delta="26"
+ name="ToolGrass"
+ tool_tip="Grass"
+ top_delta="0"
+ width="20" />
+ <check_box
+ control_name="CreateToolKeepSelected"
+ height="19"
+ label="Keep Tool selected"
+ layout="topleft"
+ left="4"
+ name="checkbox sticky"
+ top="101"
+ width="128" />
+ <check_box
+ control_name="CreateToolCopySelection"
+ height="19"
+ label="Copy selection"
+ layout="topleft"
+ left_delta="0"
+ name="checkbox copy selection"
+ top_delta="15"
+ width="134" />
+ <check_box
+ control_name="CreateToolCopyCenters"
+ height="19"
+ initial_value="true"
+ label="Center Copy"
+ layout="topleft"
+ left_delta="18"
+ name="checkbox copy centers"
+ top="132"
+ width="134" />
+ <check_box
+ control_name="CreateToolCopyRotates"
+ height="19"
+ label="Rotate Copy"
+ layout="topleft"
+ left_delta="0"
+ name="checkbox copy rotates"
+ top_delta="16"
+ width="134" />
+ <radio_group
+ height="105"
+ layout="topleft"
+ left="4"
+ name="land_radio_group"
+ top="54"
+ width="114">
+ <radio_item
+ height="19"
+ label="Select Land"
+ layout="topleft"
+ left="0"
+ name="radio select land"
+ top="-1"
+ width="114" />
+ <radio_item
+ height="19"
+ label="Flatten"
+ layout="topleft"
+ left_delta="0"
+ name="radio flatten"
+ top_delta="15"
+ width="114" />
+ <radio_item
+ height="19"
+ label="Raise"
+ layout="topleft"
+ left_delta="0"
+ name="radio raise"
+ top_delta="15"
+ width="114" />
+ <radio_item
+ height="19"
+ label="Lower"
+ layout="topleft"
+ left_delta="0"
+ name="radio lower"
+ top_delta="15"
+ width="114" />
+ <radio_item
+ height="19"
+ label="Smooth"
+ layout="topleft"
+ left_delta="0"
+ name="radio smooth"
+ top_delta="15"
+ width="114" />
+ <radio_item
+ height="19"
+ label="Roughen"
+ layout="topleft"
+ left_delta="0"
+ name="radio noise"
+ top_delta="15"
+ width="114" />
+ <radio_item
+ height="19"
+ label="Revert"
+ layout="topleft"
+ left_delta="0"
+ name="radio revert"
+ top_delta="15"
+ width="114" />
+ <radio_group.commit_callback
+ function="BuildTool.commitRadioLand"/>
+ </radio_group>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left="125"
+ name="Bulldozer:"
+ top="57"
+ width="100">
+ Bulldozer:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ name="Dozer Size:"
+ left="135"
+ top_pad="5"
+ width="50">
+ Size
+ </text>
+ <slider_bar
+ control_name ="LandBrushSize"
+ follows="left|top"
+ height="19"
+ initial_value="2.0"
+ layout="topleft"
+ max_val="11"
+ min_val="1"
+ left_pad="0"
+ name="slider brush size"
+ top_delta="-3"
+ width="80" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ name="Strength:"
+ left="135"
+ top_pad="5"
+ width="50">
+ Strength
+ </text>
+ <slider_bar
+ follows="left|top"
+ height="19"
+ left_pad="0"
+ initial_value="0.00"
+ layout="topleft"
+ max_val="2"
+ min_val="-1"
+ name="slider force"
+ top_delta="-3"
+ width="80" >
+ <slider_bar.commit_callback
+ function="BuildTool.LandBrushForce"/>
+ </slider_bar>
+ <button
+ follows="left|top"
+ height="19"
+ label="Apply"
+ label_selected="Apply"
+ top_pad="5"
+ layout="topleft"
+ left="135"
+ name="button apply to selection"
+ tool_tip="Modify selected land"
+ width="78">
+ <button.commit_callback
+ function="BuildTool.applyToSelection"/>
+ </button>
+ <text
+ text_color="LtGray_50"
+ type="string"
+ length="1"
+ height="12"
+ follows="left|top"
+ halign="right"
+ layout="topleft"
+ right="-10"
+ name="obj_count"
+ top_pad="6"
+ width="143">
+ Objects: [COUNT]
+ </text>
+ <text
+ text_color="LtGray_50"
+ type="string"
+ length="1"
+ follows="left|top"
+ halign="right"
+ layout="topleft"
+ right="-10"
+ name="prim_count"
+ width="143">
+ Prims: [COUNT]
+ </text>
+ <tab_container
+ follows="left|top"
+ height="400"
+ halign="center"
+ left="0"
+ name="Object Info Tabs"
+ tab_max_width="54"
+ tab_min_width="40"
+ tab_position="top"
+ tab_height="25"
+ top="170"
+ width="280">
+ <panel
+ border="false"
+ follows="all"
+ label="General"
+ layout="topleft"
+ mouse_opaque="false"
+ help_topic="toolbox_general_tab"
+ name="General"
+ top="16"
+ width="280">
+ <panel.string
+ name="text deed continued">
+ Deed
+ </panel.string>
+ <panel.string
+ name="text deed">
+ Deed
+ </panel.string>
+ <panel.string
+ name="text modify info 1">
+ You can modify this object
+ </panel.string>
+ <panel.string
+ name="text modify info 2">
+ You can modify these objects
+ </panel.string>
+ <panel.string
+ name="text modify info 3">
+ You can't modify this object
+ </panel.string>
+ <panel.string
+ name="text modify info 4">
+ You can't modify these objects
+ </panel.string>
+ <panel.string
+ name="text modify warning">
+ You must select entire object to set permissions
+ </panel.string>
+ <panel.string
+ name="Cost Default">
+ Price: L$
+ </panel.string>
+ <panel.string
+ name="Cost Total">
+ Total Price: L$
+ </panel.string>
+ <panel.string
+ name="Cost Per Unit">
+ Price Per: L$
+ </panel.string>
+ <panel.string
+ name="Cost Mixed">
+ Mixed Price
+ </panel.string>
+ <panel.string
+ name="Sale Mixed">
+ Mixed Sale
+ </panel.string>
+ <text
+ follows="left|top"
+ height="10"
+ left="10"
+ name="Name:"
+ top="0"
+ width="90">
+ Name:
+ </text>
+ <line_editor
+ follows="left|top|right"
+ height="19"
+ left_pad="0"
+ max_length="63"
+ name="Object Name"
+ select_on_focus="true"
+ top_delta="0"
+ width="170" />
+ <text
+ follows="left|top"
+ height="10"
+ left="10"
+ name="Description:"
+ top_pad="3"
+ width="90">
+ Description:
+ </text>
+ <line_editor
+ follows="left|top|right"
+ height="19"
+ left_pad="0"
+ max_length="127"
+ name="Object Description"
+ select_on_focus="true"
+ top_delta="0"
+ width="170" />
+ <text
+ type="string"
+ left="10"
+ length="1"
+ follows="left|top"
+ height="19"
+ layout="topleft"
+ name="Creator:"
+ width="90">
+ Creator:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ left_pad="0"
+ height="19"
+ layout="topleft"
+ name="Creator Name"
+ width="175">
+ Esbee Linden
+ </text>
+ <text
+ type="string"
+ length="1"
+ left="10"
+ follows="left|top"
+ height="19"
+ layout="topleft"
+ name="Owner:"
+ width="90">
+ Owner:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="19"
+ layout="topleft"
+ name="Owner Name"
+ left_pad="0"
+ width="175">
+ Erica Linden
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left="10"
+ height="18"
+ name="Group:"
+ top_pad="4"
+ width="75">
+ Group:
+ </text>
+ <button
+ follows="top|left"
+ height="10"
+ image_disabled="Activate_Checkmark"
+ image_selected="Activate_Checkmark"
+ image_unselected="Activate_Checkmark"
+ image_color="White_50"
+ layout="topleft"
+ left_pad="0"
+ top_delta="0"
+ name="button set group"
+ tab_stop="false"
+ tool_tip="Choose a group to share this object's permissions"
+ width="10" />
+ <name_box
+ follows="left|top"
+ height="18"
+ initial_value="Loading..."
+ layout="topleft"
+ left_pad="5"
+ top_delta="-1"
+ name="Group Name Proxy"
+ width="150" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Deed"
+ label_selected="Deed"
+ layout="topleft"
+ name="button deed"
+ top_pad="0"
+ left="100"
+ tool_tip="Deeding gives this item away with next owner permissions. Group shared objects can be deeded by a group officer."
+ width="80" />
+ <check_box
+ height="19"
+ follows="left|top"
+ label="Share"
+ layout="topleft"
+ name="checkbox share with group"
+ tool_tip="Allow all members of the set group to share your modify permissions for this object. You must Deed to enable role restrictions."
+ left_pad="3"
+ width="100" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ top_pad="15"
+ left="10"
+ name="label click action"
+ width="90">
+ Click to:
+ </text>
+ <combo_box
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ name="clickaction"
+ width="168"
+ left_pad="0">
+ <combo_box.item
+ label="Touch (default)"
+ name="Touch/grab(default)"
+ value="Touch" />
+ <combo_box.item
+ label="Sit on object"
+ name="Sitonobject"
+ value="Sit" />
+ <combo_box.item
+ label="Buy object"
+ name="Buyobject"
+ value="Buy" />
+ <combo_box.item
+ label="Pay object"
+ name="Payobject"
+ value="Pay" />
+ <combo_box.item
+ label="Open"
+ name="Open"
+ value="Open" />
+ <combo_box.item
+ label="Zoom"
+ name="Zoom"
+ value="Zoom" />
+ </combo_box>
+ <check_box
+ height="16"
+ top_pad="15"
+ label="For Sale:"
+ layout="topleft"
+ name="checkbox for sale"
+ left="10"
+ width="90" />
+<!-- NEW SALE TYPE COMBO BOX -->
+ <combo_box
+ left_pad="0"
+ layout="topleft"
+ follows="left|top"
+ allow_text_entry="false"
+ height="20"
+ intial_value="2"
+ max_chars="20"
+ mouse_opaque="true"
+ name="sale type"
+ width="158">
+ <combo_box.item
+ name="Copy"
+ label="Copy"
+ value="2" />
+ <combo_box.item
+ name="Contents"
+ label="Contents"
+ value="3" />
+ <combo_box.item
+ name="Original"
+ label="Original"
+ value="1" />
+ </combo_box>
+<!-- NEW PRICE SPINNER
+Objects are allowed to be for sale for L$0 to invoke buy UI behavior
+even though the user gets a free copy.
+-->
+ <spinner
+ follows="left|top"
+ decimal_digits="0"
+ increment="1"
+ top_pad="8"
+ left="100"
+ control_name="Edit Cost"
+ name="Edit Cost"
+ label="Price: L$"
+ label_width="65"
+ width="150"
+ min_val="0"
+ height="20"
+ max_val="999999999" />
+ <check_box
+ height="15"
+ width="110"
+ top_pad="3"
+ label="Show in search"
+ layout="topleft"
+ left="100"
+ name="search_check"
+ tool_tip="Let people see this object in search results" />
+ <panel
+ border="false"
+ follows="left|top"
+ layout="topleft"
+ mouse_opaque="false"
+ background_visible="true"
+ bg_alpha_color="DkGray"
+ name="perms_build"
+ left="0"
+ top="241"
+ height="120"
+ width="278">
+ <text
+ type="string"
+ length="1"
+ left="10"
+ top_pad="9"
+ text_color="EmphasisColor"
+ height="16"
+ follows="left|top|right"
+ layout="topleft"
+ name="perm_modify"
+ width="264">
+ You can modify this object
+ </text>
+ <text
+ type="string"
+ follows="left|top"
+ name="Anyone can:"
+ width="250"
+ left="10">
+ Anyone:
+ </text>
+ <check_box
+ height="19"
+ label="Move"
+ layout="topleft"
+ name="checkbox allow everyone move"
+ left="15"
+ width="85" />
+ <check_box
+ height="19"
+ label="Copy"
+ layout="topleft"
+ left_pad="0"
+ name="checkbox allow everyone copy"
+ width="90" />
+ <text
+ type="string"
+ follows="left|top"
+ height="19"
+ name="Next owner can:"
+ width="250"
+ left="10">
+ Next owner:
+ </text>
+ <check_box
+ follows="left|top|right"
+ label="Modify"
+ layout="topleft"
+ left="15"
+ name="checkbox next owner can modify"
+ width="85" />
+ <check_box
+ follows="left|top|right"
+ height="19"
+ label="Copy"
+ layout="topleft"
+ left_pad="0"
+ name="checkbox next owner can copy"
+ width="90" />
+ <check_box
+ follows="left|top|right"
+ height="19"
+ label="Transfer"
+ layout="topleft"
+ name="checkbox next owner can transfer"
+ left_pad="0"
+ top_delta="0"
+ tool_tip="Next owner can give away or resell this object"
+ width="90" />
+ <text
+ type="string"
+ text_color="EmphasisColor"
+ length="1"
+ top_pad="5"
+ follows="left|top"
+ layout="topleft"
+ left="10"
+ name="B:"
+ height="10"
+ width="45">
+ B:
+ </text>
+ <text
+ type="string"
+ text_color="White"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="0"
+ name="O:"
+ height="10"
+ width="44">
+ O:
+ </text>
+ <text
+ type="string"
+ text_color="EmphasisColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="0"
+ name="G:"
+ height="10"
+ width="43">
+ G:
+ </text>
+ <text
+ type="string"
+ text_color="White"
+ length="1"
+ follows="left|top"
+ left_pad="0"
+ layout="topleft"
+ name="E:"
+ height="10"
+ width="43">
+ E:
+ </text>
+ <text
+ type="string"
+ text_color="EmphasisColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="0"
+ name="N:"
+ height="10"
+ width="48">
+ N:
+ </text>
+ <text
+ type="string"
+ text_color="White"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="0"
+ name="F:"
+ height="10"
+ width="50">
+ F:
+ </text>
+ </panel>
+ </panel>
+ <panel
+ border="false"
+ follows="all"
+ height="367"
+ label="Object"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ help_topic="toolbox_object_tab"
+ name="Object"
+ top="16"
+ width="280">
+ <check_box
+ height="19"
+ label="Locked"
+ layout="topleft"
+ name="checkbox locked"
+ tool_tip="Prevents object from being moved or deleted. Frequently useful during building to avoid unintended edits."
+ top_pad="5"
+ left="10"
+ width="123" />
+ <check_box
+ height="19"
+ label="Physical"
+ layout="topleft"
+ name="Physical Checkbox Ctrl"
+ tool_tip="Allows object to be pushed and affected by gravity"
+ top_pad="0"
+ width="123" />
+ <check_box
+ height="19"
+ label="Temporary"
+ layout="topleft"
+ name="Temporary Checkbox Ctrl"
+ tool_tip="Causes object to be deleted 1 minute after creation"
+ top_pad="0"
+ width="123" />
+ <check_box
+ height="19"
+ label="Phantom"
+ layout="topleft"
+ name="Phantom Checkbox Ctrl"
+ tool_tip="Causes object to not collide with other objects or avatars"
+ top_pad="0"
+ width="123" />
+
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ name="label position"
+ top_pad="10"
+ width="121">
+ Position (meters)
+ </text>
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="X"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="512"
+ min_val="-256"
+ name="Pos X"
+ text_enabled_color="1 0 0.3 .7"
+ top_pad="5"
+ width="87" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="Y"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="512"
+ min_val="-256"
+ name="Pos Y"
+ text_enabled_color="EmphasisColor"
+ top_pad="3"
+ width="87" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="Z"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="4096"
+ name="Pos Z"
+ text_enabled_color="0 0.8 1 .65"
+ top_pad="3"
+ width="87" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="label size"
+ top_pad="6"
+ width="121">
+ Size (meters)
+ </text>
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="X"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="10"
+ min_val="0.01"
+ name="Scale X"
+ text_enabled_color="1 1 1 1"
+ top_pad="5"
+ width="87" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="Y"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="10"
+ min_val="0.01"
+ name="Scale Y"
+ text_enabled_color="1 1 1 1"
+ top_pad="3"
+ width="87" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="Z"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="10"
+ min_val="0.01"
+ name="Scale Z"
+ text_enabled_color="1 1 1 1"
+ top_pad="3"
+ width="87" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="label rotation"
+ top_pad="10"
+ width="121">
+ Rotation (degrees)
+ </text>
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="1"
+ initial_value="0"
+ label="X"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="9999"
+ min_val="-9999"
+ name="Rot X"
+ text_enabled_color="1 1 1 1"
+ top_pad="5"
+ width="87" />
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="1"
+ initial_value="0"
+ label="Y"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="9999"
+ min_val="-9999"
+ name="Rot Y"
+ text_enabled_color="1 1 1 1"
+ top_pad="3"
+ width="87" />
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="1"
+ initial_value="0"
+ label="Z"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="9999"
+ min_val="-9999"
+ name="Rot Z"
+ text_enabled_color="1 1 1 1"
+ top_pad="3"
+ width="87" />
+
+ <!-- <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="125"
+ name="label basetype"
+ top="5"
+ width="150">
+ Prim Type
+ </text>-->
+ <combo_box
+ height="19"
+ layout="topleft"
+ name="comboBaseType"
+ top="6"
+ left="125"
+ width="150">
+ <combo_box.item
+ label="Box"
+ name="Box"
+ value="Box" />
+ <combo_box.item
+ label="Cylinder"
+ name="Cylinder"
+ value="Cylinder" />
+ <combo_box.item
+ label="Prism"
+ name="Prism"
+ value="Prism" />
+ <combo_box.item
+ label="Sphere"
+ name="Sphere"
+ value="Sphere" />
+ <combo_box.item
+ label="Torus"
+ name="Torus"
+ value="Torus" />
+ <combo_box.item
+ label="Tube"
+ name="Tube"
+ value="Tube" />
+ <combo_box.item
+ label="Ring"
+ name="Ring"
+ value="Ring" />
+ <combo_box.item
+ label="Sculpted"
+ name="Sculpted"
+ value="Sculpted" />
+ </combo_box>
+ <combo_box
+ height="19"
+ layout="topleft"
+ name="material"
+ top_pad="5"
+ width="150">
+ <combo_box.item
+ label="Stone"
+ name="Stone"
+ value="Stone" />
+ <combo_box.item
+ label="Metal"
+ name="Metal"
+ value="Metal" />
+ <combo_box.item
+ label="Glass"
+ name="Glass"
+ value="Glass" />
+ <combo_box.item
+ label="Wood"
+ name="Wood"
+ value="Wood" />
+ <combo_box.item
+ label="Flesh"
+ name="Flesh"
+ value="Flesh" />
+ <combo_box.item
+ label="Plastic"
+ name="Plastic"
+ value="Plastic" />
+ <combo_box.item
+ label="Rubber"
+ name="Rubber"
+ value="Rubber" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="text cut"
+ top_pad="5"
+ width="150">
+ Path Cut (begin/end)
+ </text>
+ <spinner
+ follows="left|top"
+ height="16"
+ increment="0.025"
+ initial_value="0"
+ label="B"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="0.98"
+ name="cut begin"
+ top_pad="4"
+ width="68" />
+ <spinner
+ follows="left|top"
+ height="16"
+ increment="0.025"
+ initial_value="1"
+ label="E"
+ label_width="10"
+ layout="topleft"
+ left_pad="10"
+ min_val="0.02"
+ name="cut end"
+ top_delta="0"
+ width="68" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="125"
+ name="text hollow"
+ top_pad="5"
+ width="68">
+ Hollow
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="10"
+ name="text skew"
+ width="63">
+ Skew
+ </text>
+ <spinner
+ decimal_digits="1"
+ follows="left|top"
+ height="19"
+ increment="5"
+ initial_value="0"
+ layout="topleft"
+ left="125"
+ max_val="95"
+ name="Scale 1"
+ top_pad="4"
+ width="68" />
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="0.05"
+ initial_value="0"
+ layout="topleft"
+ left_pad="10"
+ max_val="0.95"
+ min_val="-0.95"
+ name="Skew"
+ top_delta="0"
+ width="68" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="125"
+ name="Hollow Shape"
+ top_pad="0"
+ width="150">
+ Hollow Shape
+ </text>
+ <combo_box
+ height="19"
+ layout="topleft"
+ left_delta="0"
+ name="hole"
+ top_pad="3"
+ width="150">
+ <combo_box.item
+ label="Default"
+ name="Default"
+ value="Default" />
+ <combo_box.item
+ label="Circle"
+ name="Circle"
+ value="Circle" />
+ <combo_box.item
+ label="Square"
+ name="Square"
+ value="Square" />
+ <combo_box.item
+ label="Triangle"
+ name="Triangle"
+ value="Triangle" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="text twist"
+ top_pad="5"
+ width="150">
+ Twist (begin/end)
+ </text>
+ <spinner
+ decimal_digits="0"
+ follows="left|top"
+ height="19"
+ increment="9"
+ initial_value="0"
+ label="B"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="180"
+ min_val="-180"
+ name="Twist Begin"
+ top_pad="4"
+ width="68" />
+ <spinner
+ decimal_digits="0"
+ follows="left|top"
+ height="19"
+ increment="9"
+ initial_value="0"
+ label="E"
+ label_width="10"
+ layout="topleft"
+ left_pad="10"
+ max_val="180"
+ min_val="-180"
+ name="Twist End"
+ top_delta="0"
+ width="68" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="125"
+ name="scale_taper"
+ top_pad="3"
+ width="150">
+ Taper
+ </text>
+ <text
+ visible="false"
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="scale_hole"
+ top_delta="0"
+ width="150">
+ Hole Size
+ </text>
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="0.05"
+ initial_value="0"
+ label="X"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ min_val="-1"
+ name="Taper Scale X"
+ top_pad="4"
+ width="68" />
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="0.05"
+ initial_value="0"
+ label="Y"
+ label_width="10"
+ layout="topleft"
+ left_pad="10"
+ min_val="-1"
+ name="Taper Scale Y"
+ top_delta="0"
+ width="68" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="125"
+ name="text topshear"
+ top_pad="3"
+ width="141">
+ Top Shear
+ </text>
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="0.05"
+ initial_value="0"
+ label="X"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="0.5"
+ min_val="-0.5"
+ name="Shear X"
+ top_pad="4"
+ width="68" />
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="0.05"
+ initial_value="0"
+ label="Y"
+ label_width="10"
+ layout="topleft"
+ left_pad="10"
+ max_val="0.5"
+ min_val="-0.5"
+ name="Shear Y"
+ top_delta="0"
+ width="68" />
+ <text
+ visible="false"
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="125"
+ name="advanced_cut"
+ top_pad="3"
+ width="150">
+ Profile Cut (begin/end)
+ </text>
+ <text
+ visible="false"
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="advanced_dimple"
+ top_delta="0"
+ width="150">
+ Dimple (begin/end)
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="advanced_slice"
+ top_delta="0"
+ width="150">
+ Slice (begin/end)
+ </text>
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.025"
+ initial_value="0"
+ label="B"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="0.95"
+ name="Path Limit Begin"
+ top_pad="3"
+ width="68" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.025"
+ initial_value="1"
+ label="E"
+ label_width="10"
+ layout="topleft"
+ left_pad="10"
+ min_val="0.05"
+ name="Path Limit End"
+ top_delta="0"
+ width="68" />
+ <text
+ visible="false"
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="125"
+ name="text taper2"
+ top_pad="3"
+ width="150">
+ Taper
+ </text>
+ <spinner
+ visible="false"
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="0.05"
+ initial_value="0"
+ label="X"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ min_val="-1"
+ name="Taper X"
+ top_pad="3"
+ width="68" />
+ <spinner
+ visible="false"
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="0.05"
+ initial_value="0"
+ label="Y"
+ label_width="10"
+ layout="topleft"
+ left_pad="10"
+ min_val="-1"
+ name="Taper Y"
+ top_delta="0"
+ width="68" />
+ <text
+ visible="false"
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="125"
+ name="text radius delta"
+ top_pad="0"
+ width="78">
+ Radius
+ </text>
+ <text
+ visible="false"
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="78"
+ name="text revolutions"
+ width="68">
+ Revolutions
+ </text>
+ <spinner
+ visible="false"
+ follows="left|top"
+ height="19"
+ increment="0.05"
+ initial_value="0"
+ layout="topleft"
+ left="125"
+ min_val="-1"
+ name="Radius Offset"
+ top_pad="4"
+ width="68" />
+ <spinner
+ visible="false"
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ initial_value="1"
+ layout="topleft"
+ left_pad="10"
+ max_val="4"
+ min_val="1"
+ name="Revolutions"
+ top_delta="0"
+ width="68" />
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="141"
+ label="Sculpt Texture"
+ layout="topleft"
+ left="125"
+ name="sculpt texture control"
+ tool_tip="Click to choose a picture"
+ top="70"
+ visible="false"
+ width="145" />
+ <check_box
+ height="19"
+ label="Mirror"
+ layout="topleft"
+ left_delta="0"
+ name="sculpt mirror control"
+ tool_tip="Flips sculpted prim along the X axis"
+ top_pad="8"
+ visible="false"
+ width="130" />
+ <check_box
+ height="19"
+ label="Inside-out"
+ layout="topleft"
+ left_delta="0"
+ name="sculpt invert control"
+ tool_tip="Inverts the sculpted prims normals, making it appear inside-out"
+ top_pad="4"
+ visible="false"
+ width="121" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="label sculpt type"
+ top_pad="10"
+ visible="false"
+ width="130">
+ Stitching type
+ </text>
+ <combo_box
+ height="19"
+ layout="topleft"
+ left_delta="0"
+ name="sculpt type control"
+ top_pad="4"
+ visible="false"
+ width="150">
+ <combo_box.item
+ label="(none)"
+ name="None"
+ value="None" />
+ <combo_box.item
+ label="Sphere"
+ name="Sphere"
+ value="Sphere" />
+ <combo_box.item
+ label="Torus"
+ name="Torus"
+ value="Torus" />
+ <combo_box.item
+ label="Plane"
+ name="Plane"
+ value="Plane" />
+ <combo_box.item
+ label="Cylinder"
+ name="Cylinder"
+ value="Cylinder" />
+ </combo_box>
+ </panel>
+
+ <panel
+ border="false"
+ follows="all"
+ height="367"
+ label="Features"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ help_topic="toolbox_features_tab"
+ name="Features"
+ top_delta="0"
+ width="280">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="select_single"
+ top="5"
+ width="252">
+ Select only one primitive to edit features.
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="edit_object"
+ top="5"
+ width="252">
+ Edit object features:
+ </text>
+ <check_box
+ height="19"
+ label="Flexible Path"
+ layout="topleft"
+ left="10"
+ name="Flexible1D Checkbox Ctrl"
+ tool_tip="Allows object to flex about the Z axis (Client-side only)"
+ top_pad="10"
+ width="121" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="1"
+ initial_value="2"
+ label="Softness"
+ label_width="65"
+ layout="topleft"
+ left_delta="0"
+ max_val="3"
+ name="FlexNumSections"
+ top_pad="10"
+ width="128" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.5"
+ initial_value="0.3"
+ label="Gravity"
+ label_width="65"
+ layout="topleft"
+ left_delta="0"
+ max_val="10"
+ min_val="-10"
+ name="FlexGravity"
+ top_pad="4"
+ width="128" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.5"
+ initial_value="2"
+ label="Drag"
+ label_width="65"
+ layout="topleft"
+ left_delta="0"
+ max_val="10"
+ name="FlexFriction"
+ top_pad="4"
+ width="128" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.5"
+ initial_value="0"
+ label="Wind"
+ label_width="65"
+ layout="topleft"
+ left_delta="0"
+ max_val="10"
+ name="FlexWind"
+ top_pad="4"
+ width="128" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.5"
+ initial_value="1"
+ label="Tension"
+ label_width="65"
+ layout="topleft"
+ left_delta="0"
+ max_val="10"
+ name="FlexTension"
+ top_pad="4"
+ width="128" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="Force X"
+ label_width="65"
+ layout="topleft"
+ left_delta="0"
+ max_val="10"
+ min_val="-10"
+ name="FlexForceX"
+ top_pad="4"
+ width="128" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="Force Y"
+ label_width="65"
+ layout="topleft"
+ left_delta="0"
+ max_val="10"
+ min_val="-10"
+ name="FlexForceY"
+ top_pad="4"
+ width="128" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="Force Z"
+ label_width="65"
+ layout="topleft"
+ left_delta="0"
+ max_val="10"
+ min_val="-10"
+ name="FlexForceZ"
+ top_pad="4"
+ width="128" />
+ <check_box
+ height="16"
+ label="Light"
+ layout="topleft"
+ left="10"
+ name="Light Checkbox Ctrl"
+ tool_tip="Causes object to emit light"
+ top_pad="15"
+ width="60" />
+ <color_swatch
+ can_apply_immediately="true"
+ bevel_style="none"
+ border_style="line"
+ color="0.5 0.5 0.5 1"
+ border.border_thickness="0"
+ follows="left|top"
+ height="50"
+ layout="topleft"
+ left_pad="10"
+ top_pad="-17"
+ name="colorswatch"
+ tool_tip="Click to open color picker"
+ width="40" />
+ <texture_picker
+ allow_no_texture="true"
+ top_delta="0"
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="48"
+ label=""
+ left_delta="57"
+ mouse_opaque="true"
+ name="light texture control"
+ tool_tip="Click to choose a projection image (only has effect with deferred rendering enabled)"
+ width="32" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0.5"
+ label="Intensity"
+ label_width="70"
+ layout="topleft"
+ left="10"
+ name="Light Intensity"
+ top_pad="3"
+ width="128" />
+ <spinner bottom_delta="0" decimal_digits="3" follows="left|top" height="16"
+ increment="0.1" initial_val="0.5" label="FOV" label_width="55"
+ left="144" max_val="3" min_val="0" mouse_opaque="true"
+ name="Light FOV" width="120" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="5"
+ label="Radius"
+ label_width="70"
+ layout="topleft"
+ left="10"
+ max_val="20"
+ name="Light Radius"
+ top_pad="3"
+ width="128" />
+ <spinner bottom_delta="0" decimal_digits="3" follows="left|top" height="16"
+ increment="0.5" initial_val="0.5" label="Focus" label_width="55"
+ left="144" max_val="20" min_val="-20" mouse_opaque="true"
+ name="Light Focus" width="120" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.25"
+ initial_value="1"
+ label="Falloff"
+ label_width="70"
+ layout="topleft"
+ left="10"
+ max_val="2"
+ name="Light Falloff"
+ top_pad="3"
+ width="128" />
+ <spinner bottom_delta="0" decimal_digits="3" follows="left|top" height="16"
+ increment="0.05" initial_val="1" label="Ambiance" label_width="55"
+ left="144" max_val="1" min_val="0" mouse_opaque="true"
+ name="Light Ambiance" width="120" />
+ </panel>
+ <panel
+ border="false"
+ follows="all"
+ height="367"
+ label="Texture"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ help_topic="toolbox_texture_tab"
+ name="Texture"
+ top_delta="0"
+ width="280">
+ <panel.string
+ name="string repeats per meter">
+ Repeats Per Meter
+ </panel.string>
+ <panel.string
+ name="string repeats per face">
+ Repeats Per Face
+ </panel.string>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Texture"
+ layout="topleft"
+ left="10"
+ name="texture control"
+ tool_tip="Click to choose a picture"
+ top="8"
+ width="64" />
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="80"
+ label="Color"
+ layout="topleft"
+ left_pad="15"
+ name="colorswatch"
+ tool_tip="Click to open color picker"
+ top_delta="0"
+ width="64" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="15"
+ name="color trans"
+ top="6"
+ width="110">
+ Transparency %
+ </text>
+ <spinner
+ decimal_digits="0"
+ follows="left|top"
+ height="19"
+ increment="2"
+ initial_value="0"
+ layout="topleft"
+ left_delta="0"
+ max_val="90"
+ name="ColorTrans"
+ top_pad="4"
+ width="80" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="glow label"
+ top_pad="2"
+ width="80">
+ Glow
+ </text>
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ layout="topleft"
+ left_delta="0"
+ name="glow"
+ top_pad="4"
+ width="80" />
+ <check_box
+ height="19"
+ label="Full Bright"
+ layout="topleft"
+ left_delta="0"
+ name="checkbox fullbright"
+ top_pad="4"
+ width="81" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="tex gen"
+ top_pad="5"
+ width="85">
+ Mapping
+ </text>
+ <combo_box
+ height="23"
+ layout="topleft"
+ left_delta="0"
+ name="combobox texgen"
+ top_pad="4"
+ width="85">
+ <combo_box.item
+ label="Default"
+ name="Default"
+ value="Default" />
+ <combo_box.item
+ label="Planar"
+ name="Planar"
+ value="Planar" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ name="label shininess"
+ left_pad="4"
+ top_pad="-36"
+ width="85">
+ Shininess
+ </text>
+ <combo_box
+ height="23"
+ layout="topleft"
+ left_delta="0"
+ name="combobox shininess"
+ top_pad="4"
+ width="85">
+ <combo_box.item
+ label="None"
+ name="None"
+ value="None" />
+ <combo_box.item
+ label="Low"
+ name="Low"
+ value="Low" />
+ <combo_box.item
+ label="Medium"
+ name="Medium"
+ value="Medium" />
+ <combo_box.item
+ label="High"
+ name="High"
+ value="High" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="4"
+ name="label bumpiness"
+ top_pad="-36"
+ width="85">
+ Bumpiness
+ </text>
+ <combo_box
+ height="23"
+ layout="topleft"
+ left_delta="0"
+ name="combobox bumpiness"
+ top_pad="4"
+ width="85">
+ <combo_box.item
+ label="None"
+ name="None"
+ value="None" />
+ <combo_box.item
+ label="Brightness"
+ name="Brightness"
+ value="Brightness" />
+ <combo_box.item
+ label="Darkness"
+ name="Darkness"
+ value="Darkness" />
+ <combo_box.item
+ label="woodgrain"
+ name="woodgrain"
+ value="woodgrain" />
+ <combo_box.item
+ label="bark"
+ name="bark"
+ value="bark" />
+ <combo_box.item
+ label="bricks"
+ name="bricks"
+ value="bricks" />
+ <combo_box.item
+ label="checker"
+ name="checker"
+ value="checker" />
+ <combo_box.item
+ label="concrete"
+ name="concrete"
+ value="concrete" />
+ <combo_box.item
+ label="crustytile"
+ name="crustytile"
+ value="crustytile" />
+ <combo_box.item
+ label="cutstone"
+ name="cutstone"
+ value="cutstone" />
+ <combo_box.item
+ label="discs"
+ name="discs"
+ value="discs" />
+ <combo_box.item
+ label="gravel"
+ name="gravel"
+ value="gravel" />
+ <combo_box.item
+ label="petridish"
+ name="petridish"
+ value="petridish" />
+ <combo_box.item
+ label="siding"
+ name="siding"
+ value="siding" />
+ <combo_box.item
+ label="stonetile"
+ name="stonetile"
+ value="stonetile" />
+ <combo_box.item
+ label="stucco"
+ name="stucco"
+ value="stucco" />
+ <combo_box.item
+ label="suction"
+ name="suction"
+ value="suction" />
+ <combo_box.item
+ label="weave"
+ name="weave"
+ value="weave" />
+ </combo_box>
+ <!--
+ <line_editor
+ bevel_style="in"
+ border_style="line"
+ border_thickness="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ max_length="63"
+ name="Home Url"
+ select_on_focus="true"
+ top="134"
+ width="250" />
+ <check_box
+ height="16"
+ label="Media Face"
+ layout="topleft"
+ left_delta="0"
+ name="has media"
+ top_pad="6"
+ width="70" />
+ <button
+ follows="left|top"
+ font="SansSerifSmall"
+ height="20"
+ label="Set Media Info"
+ label_selected="Set Media Info"
+ layout="topleft"
+ left_pad="60"
+ name="media info set"
+ top_delta="-4"
+ width="120" />
+-->
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="tex scale"
+ top_pad="5"
+ width="200">
+ Repeats / Face
+ </text>
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Horizontal (U)"
+ label_width="90"
+ layout="topleft"
+ left="20"
+ max_val="100"
+ name="TexScaleU"
+ top_pad="6"
+ width="160" />
+ <check_box
+ height="19"
+ label="Flip"
+ layout="topleft"
+ left_pad="10"
+ name="checkbox flip s"
+ top_delta="0"
+ width="70" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Vertical (V)"
+ label_width="90"
+ layout="topleft"
+ left="20"
+ max_val="100"
+ name="TexScaleV"
+ top_pad="0"
+ width="160" />
+ <check_box
+ height="19"
+ label="Flip"
+ layout="topleft"
+ left_pad="10"
+ name="checkbox flip t"
+ top_delta="0"
+ width="70" />
+
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="1"
+ initial_value="0"
+ label="RotationËš"
+ layout="topleft"
+ label_width="100"
+ left="10"
+ max_val="9999"
+ min_val="-9999"
+ name="TexRot"
+ top_delta="25"
+ width="170" />
+
+ <spinner
+ decimal_digits="1"
+ follows="left|top"
+ height="19"
+ initial_value="1"
+ label="Repeats / Meter"
+ layout="topleft"
+ label_width="100"
+ left="10"
+ max_val="10"
+ min_val="0.1"
+ name="rptctrl"
+ top_delta="20"
+ width="170" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Apply"
+ label_selected="Apply"
+ layout="topleft"
+ left_pad="10"
+ name="button apply"
+ width="75" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="tex offset"
+ top_delta="20"
+ width="200">
+ Texture Offset
+ </text>
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Horizontal (U)"
+ label_width="90"
+ layout="topleft"
+ left="20"
+ min_val="-1"
+ name="TexOffsetU"
+ top_pad="6"
+ width="160" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Vertical (V)"
+ label_width="90"
+ layout="topleft"
+ left_delta="0"
+ min_val="-1"
+ name="TexOffsetV"
+ top_pad="1"
+ width="160" />
+ <panel
+ border="false"
+ follows="left|top"
+ layout="topleft"
+ mouse_opaque="false"
+ background_visible="true"
+ bg_alpha_color="DkGray"
+ name="Add_Media"
+ left="0"
+ top_pad="0"
+ height="75"
+ width="278">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left="10"
+ top_pad="5"
+ name="media_tex"
+ width="260">
+ Media
+ </text>
+ <text
+ follows="left|top|right"
+ height="18"
+ layout="topleft"
+ left="10"
+ use_ellipses="true"
+ read_only="true"
+ name="media_info"
+ width="180" />
+ <button
+ follows="top|left"
+ height="18"
+ image_selected="AddItem_Press"
+ image_unselected="AddItem_Off"
+ image_disabled="AddItem_Disabled"
+ layout="topleft"
+ left_pad="0"
+ name="add_media"
+ tab_stop="false"
+ top_delta="0"
+ tool_tip="Add Media"
+ width="18">
+ <button.commit_callback
+ function="BuildTool.AddMedia"/>
+ </button>
+ <button
+ follows="top|left"
+ height="18"
+ image_selected="TrashItem_Press"
+ image_unselected="TrashItem_Off"
+ layout="topleft"
+ left_pad="5"
+ name="delete_media"
+ tool_tip="Delete this media texture"
+ top_delta="0"
+ width="18">
+ <button.commit_callback
+ function="BuildTool.DeleteMedia"/>
+ </button>
+ <button
+ follows="top|left"
+ tool_tip="Edit this Media"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ layout="topleft"
+ left_pad="10"
+ name="edit_media"
+ top_delta="0"
+ width="18">
+ <button.commit_callback
+ function="BuildTool.EditMedia"/>
+ </button>
+ <web_browser
+ visible="false"
+ enabled="false"
+ border_visible="true"
+ bottom_delta="0"
+ follows="top|left"
+ left="0"
+ name="title_media"
+ width="4"
+ height="4"
+ start_url="about:blank"
+ decouple_texture_size="true" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Align"
+ label_selected="Align Media"
+ layout="topleft"
+ left="10"
+ name="button align"
+ top_pad="5"
+ tool_tip="Align media texture (must load first)"
+ width="100" />
+ </panel>
+ </panel>
+ <panel
+ border="false"
+ follows="all"
+ label="Content"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ help_topic="toolbox_contents_tab"
+ name="Contents"
+ top_delta="0"
+ width="280">
+ <button
+ follows="left|top"
+ height="19"
+ label="New Script"
+ label_selected="New Script"
+ layout="topleft"
+ left="10"
+ name="button new script"
+ top="10"
+ width="120" />
+ <button
+ follows="left|top"
+ height="19"
+ label="Permissions"
+ layout="topleft"
+ left_pad="8"
+ name="button permissions"
+ width="130" />
+ <panel_inventory_object
+ follows="left|top"
+ height="325"
+ layout="topleft"
+ left="10"
+ name="contents_inventory"
+ top="50"
+ width="260" />
+ </panel>
+ </tab_container>
+ <panel
+ follows="left|top"
+ height="384"
+ layout="topleft"
+ left_delta="0"
+ name="land info panel"
+ top_delta="0"
+ width="280">
+ <text
+ type="string"
+ length="1"
+ font="SansSerifBig"
+ follows="left|top"
+ height="19"
+ layout="topleft"
+ left="20"
+ name="label_parcel_info"
+ top="24"
+ width="150">
+ Parcel Information
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="19"
+ layout="topleft"
+ left="30"
+ name="label_area_price"
+ top="48"
+ width="150">
+ Price: L$[PRICE] for [AREA] m²
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="19"
+ layout="topleft"
+ left_delta="0"
+ name="label_area"
+ top_delta="0"
+ width="150">
+ Area: [AREA] m²
+ </text>
+ <button
+ follows="left|top"
+ height="20"
+ label="About Land"
+ label_selected="About Land"
+ layout="topleft"
+ left_delta="0"
+ name="button about land"
+ top_pad="4"
+ width="112" />
+ <check_box
+ control_name="ShowParcelOwners"
+ height="19"
+ label="Show owners"
+ layout="topleft"
+ left_delta="0"
+ name="checkbox show owners"
+ tool_tip="Colorize the parcels according to the type of owner: &#10;&#10;Green = Your land &#10;Aqua = Your group&apos;s land &#10;Red = Owned by others &#10;Yellow = For sale &#10;Purple = For auction &#10;Grey = Public"
+ top_pad="8"
+ width="205" />
+ <text
+ type="string"
+ length="1"
+ font="SansSerifBig"
+ follows="left|top"
+ height="19"
+ layout="topleft"
+ left="20"
+ name="label_parcel_modify"
+ top="152"
+ width="150">
+ Modify Parcel
+ </text>
+ <button
+ follows="left|top"
+ height="20"
+ label="Subdivide"
+ label_selected="Subdivide"
+ layout="topleft"
+ left="30"
+ name="button subdivide land"
+ top="172"
+ width="112" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Join"
+ label_selected="Join"
+ layout="topleft"
+ left_delta="0"
+ name="button join land"
+ top_pad="4"
+ width="112" />
+ <text
+ type="string"
+ length="1"
+ font="SansSerifBig"
+ follows="left|top"
+ height="19"
+ layout="topleft"
+ left="20"
+ name="label_parcel_trans"
+ top="256"
+ width="150">
+ Land Transactions
+ </text>
+ <button
+ follows="left|top"
+ height="20"
+ label="Buy Land"
+ label_selected="Buy Land"
+ layout="topleft"
+ left="30"
+ name="button buy land"
+ top="276"
+ width="112" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Abandon Land"
+ label_selected="Abandon Land"
+ layout="topleft"
+ left_delta="0"
+ name="button abandon land"
+ top_pad="4"
+ width="112" />
+ </panel>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_top_objects.xml b/indra/newview/skins/default/xui/en/floater_top_objects.xml
new file mode 100644
index 0000000000..b06c6dc215
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_top_objects.xml
@@ -0,0 +1,256 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="350"
+ layout="topleft"
+ min_height="300"
+ min_width="450"
+ name="top_objects"
+ help_topic="top_objects"
+ title="Top Objects"
+ width="800">
+ <floater.string
+ name="top_scripts_title">
+ Top Scripts
+ </floater.string>
+ <floater.string
+ name="top_scripts_text">
+ [COUNT] scripts taking a total of [TIME] ms
+ </floater.string>
+ <floater.string
+ name="scripts_score_label">
+ Time
+ </floater.string>
+ <floater.string
+ name="scripts_mono_time_label">
+ Mono Time
+ </floater.string>
+ <floater.string
+ name="top_colliders_title">
+ Top Colliders
+ </floater.string>
+ <floater.string
+ name="top_colliders_text">
+ Top [COUNT] objects experiencing many potential collisions
+ </floater.string>
+ <floater.string
+ name="colliders_score_label">
+ Score
+ </floater.string>
+ <floater.string
+ name="none_descriptor">
+ None found.
+ </floater.string>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="title_text"
+ top="20"
+ text_color="EmphasisColor"
+ width="400">
+ Loading...
+ </text>
+ <scroll_list
+ draw_heading="true"
+ follows="all"
+ height="170"
+ layout="topleft"
+ left_delta="0"
+ multi_select="true"
+ name="objects_list"
+ top_delta="17"
+ width="780">
+ <scroll_list.columns
+ label="Score"
+ name="score"
+ width="55" />
+ <scroll_list.columns
+ label="Name"
+ name="name"
+ width="140" />
+ <scroll_list.columns
+ label="Owner"
+ name="owner"
+ width="105" />
+ <scroll_list.columns
+ label="Location"
+ name="location"
+ width="130" />
+ <scroll_list.columns
+ label="Time"
+ name="time"
+ width="150" />
+ <scroll_list.columns
+ label="Mono Time"
+ name="mono_time"
+ width="100" />
+ <scroll_list.columns
+ label="URLs"
+ name="URLs"
+ width="100" />
+ <scroll_list.commit_callback
+ function="TopObjects.CommitObjectsList" />
+ </scroll_list>
+ <text
+ type="string"
+ length="1"
+ follows="left|bottom"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="id_text"
+ top_pad="10"
+ width="100">
+ Object ID:
+ </text>
+ <line_editor
+ enabled="false"
+ follows="left|bottom|right"
+ height="20"
+ layout="topleft"
+ left_pad="3"
+ name="id_editor"
+ top_delta="-3"
+ width="575" />
+ <button
+ follows="bottom|right"
+ height="23"
+ label="Show Beacon"
+ layout="topleft"
+ left_pad="5"
+ name="show_beacon_btn"
+ top_delta="0"
+ width="100">
+ <button.commit_callback
+ function="TopObjects.ShowBeacon" />
+ </button>
+ <text
+ type="string"
+ length="1"
+ follows="left|bottom"
+ height="20"
+ layout="topleft"
+ left="10"
+ top_pad="5"
+ name="obj_name_text"
+ width="100">
+ Object name:
+ </text>
+ <line_editor
+ follows="left|bottom|right"
+ height="20"
+ layout="topleft"
+ left_pad="3"
+ name="object_name_editor"
+ top_delta="-3"
+ width="575" />
+ <button
+ follows="bottom|right"
+ height="23"
+ label="Filter"
+ layout="topleft"
+ left_pad="5"
+ name="filter_object_btn"
+ top_delta="0"
+ width="100">
+ <button.commit_callback
+ function="TopObjects.GetByObjectName" />
+ </button>
+ <text
+ type="string"
+ length="1"
+ follows="left|bottom"
+ height="20"
+ layout="topleft"
+ left="10"
+ top_pad="5"
+ name="owner_name_text"
+ width="100">
+ Owner:
+ </text>
+ <line_editor
+ follows="left|bottom|right"
+ height="20"
+ layout="topleft"
+ left_pad="3"
+ name="owner_name_editor"
+ top_delta="-3"
+ width="575" />
+ <button
+ follows="bottom|right"
+ height="23"
+ label="Filter"
+ layout="topleft"
+ left_pad="5"
+ name="filter_owner_btn"
+ top_delta="0"
+ width="100">
+ <button.commit_callback
+ function="TopObjects.GetByOwnerName" />
+ </button>
+ <button
+ follows="bottom|right"
+ height="22"
+ image_overlay="Refresh_Off"
+ layout="topleft"
+ name="refresh_btn"
+ right="-8"
+ top_pad="5"
+ width="23">
+ <button.commit_callback
+ function="TopObjects.Refresh" />
+ </button>
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Return Selected"
+ layout="topleft"
+ left="112"
+ top_delta="0"
+ name="return_selected_btn"
+ width="130">
+ <button.commit_callback
+ function="TopObjects.ReturnSelected" />
+ </button>
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Return All"
+ layout="topleft"
+ left_pad="10"
+ name="return_all_btn"
+ top_delta="0"
+ width="130">
+ <button.commit_callback
+ function="TopObjects.ReturnAll" />
+ </button>
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Disable Selected"
+ layout="topleft"
+
+ left="112"
+ name="disable_selected_btn"
+ width="130">
+ <button.commit_callback
+ function="TopObjects.DisableSelected" />
+ </button>
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Disable All"
+ layout="topleft"
+ left_pad="10"
+ name="disable_all_btn"
+ top_delta="0"
+ width="130">
+ <button.commit_callback
+ function="TopObjects.DisableAll" />
+ </button>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_tos.xml b/indra/newview/skins/default/xui/en/floater_tos.xml
new file mode 100644
index 0000000000..5e168fe4aa
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_tos.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_close="false"
+ can_minimize="false"
+ height="500"
+ layout="topleft"
+ name="modal container"
+ width="600">
+ <floater.string
+ name="real_url">
+ http://secondlife.com/app/tos/
+ </floater.string>
+ <button
+ enabled="false"
+ height="20"
+ label="Continue"
+ label_selected="Continue"
+ layout="topleft"
+ left="484"
+ name="Continue"
+ top="464"
+ width="100" />
+ <button
+ height="20"
+ label="Cancel"
+ label_selected="Cancel"
+ layout="topleft"
+ left_delta="-468"
+ name="Cancel"
+ top_delta="0"
+ width="100" />
+ <check_box
+ follows="top|right"
+ height="16"
+ label="I Agree to the Terms of Service"
+ layout="topleft"
+ left_delta="0"
+ name="agree_chk"
+ top_delta="-45"
+ width="55" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="30"
+ layout="topleft"
+ left_delta="0"
+ name="tos_heading"
+ top_delta="-399"
+ word_wrap="true"
+ width="552">
+ Please read the following Terms of Service carefully. To continue logging in to [SECOND_LIFE], you must accept the agreement.
+ </text>
+ <web_browser
+ follows="left|top"
+ height="340"
+ layout="topleft"
+ left_delta="0"
+ name="tos_html"
+ start_url="data:text/html,%3Chtml%3E%3Chead%3E%3C/head%3E%3Cbody text=%22000000%22%3E%3Ch2%3E Loading %3Ca%20target%3D%22_external%22%20href%3D%22http%3A//secondlife.com/app/tos/%22%3ETerms%20of%20Service%3C/a%3E...%3C/h2%3E %3C/body%3E %3C/html%3E"
+ top_delta="40"
+ width="568" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_ui_preview.xml b/indra/newview/skins/default/xui/en/floater_ui_preview.xml
new file mode 100644
index 0000000000..8b2136c2dc
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_ui_preview.xml
@@ -0,0 +1,407 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="640"
+ layout="topleft"
+ min_height="230"
+ min_width="650"
+ name="gui_preview_tool"
+ help_topic="gui_preview_tool"
+ single_instance="true"
+ title="XUI PREVIEW TOOL"
+ width="750">
+ <panel
+ bottom="640"
+ follows="left|top|right|bottom"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="main_panel"
+ right="750"
+ top="0">
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerif"
+ height="30"
+ layout="topleft"
+ left="10"
+ name="select_language_label"
+ top="25"
+ width="130">
+ Primary Language:
+ </text>
+ <combo_box
+ follows="top|left"
+ height="20"
+ layout="topleft"
+ left_pad="5"
+ name="language_select_combo"
+ top_delta="0"
+ width="55">
+ <combo_box.item
+ label="en"
+ name="item1"
+ value="en" />
+ </combo_box>
+ <button
+ follows="left|top"
+ height="25"
+ label="Show"
+ label_selected="Show"
+ layout="topleft"
+ left_pad="10"
+ name="display_floater"
+ tool_tip="Display the XUI floater defined by the selected XML file"
+ top_delta="-2"
+ width="95" />
+ <button
+ enabled="false"
+ follows="left|top"
+ height="25"
+ label="Hide"
+ label_selected="Hide"
+ layout="topleft"
+ left_pad="10"
+ name="close_displayed_floater"
+ tool_tip="Closes the currently-displayed floater, if one exists"
+ top_delta="0"
+ width="85" />
+ <button
+ follows="left|top"
+ height="25"
+ label="Edit..."
+ label_selected="Edit..."
+ layout="topleft"
+ left_pad="10"
+ name="edit_floater"
+ tool_tip="Edit the XUI floater defined by the selected XML file (opens external editor). Opens en version if no localized version exists."
+ top_delta="0"
+ width="95" />
+ <button
+ follows="left|top"
+ height="25"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ left_pad="5"
+ name="save_floater"
+ tool_tip="Save the XUI floater defined by the selected XML file"
+ top_delta="0"
+ width="85" />
+ <button
+ follows="left|top"
+ height="25"
+ label="Save All"
+ label_selected="Save All"
+ layout="topleft"
+ left_pad="10"
+ name="save_all_floaters"
+ tool_tip="Save all XUI floaters defined by the selected language"
+ top_delta="0"
+ width="85" />
+ <button
+ follows="right|top"
+ height="25"
+ is_toggle="true"
+ label="&gt; &gt;"
+ label_selected="&lt; &lt;"
+ layout="topleft"
+ left_pad="15"
+ name="toggle_overlap_panel"
+ tool_tip="Toggle highlighting and display panel for overlapping elements; right click an element to select it for this feature. The selected element is marked by a red rectangle."
+ top_delta="0"
+ width="30" />
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerif"
+ height="30"
+ layout="topleft"
+ left="10"
+ name="select_language_label_2"
+ right="-50"
+ top="53"
+ width="105">
+ Secondary Language:
+ </text>
+ <combo_box
+ follows="top|left"
+ height="20"
+ layout="topleft"
+ left_delta="135"
+ name="language_select_combo_2"
+ top_delta="0"
+ width="55">
+ <combo_box.item
+ label="en"
+ name="item1"
+ value="en" />
+ </combo_box>
+ <button
+ follows="left|top"
+ height="25"
+ label="Show"
+ layout="topleft"
+ left_pad="10"
+ name="display_floater_2"
+ tool_tip="Display the XUI floater defined by the selected XML file"
+ top_delta="-2"
+ width="95" />
+ <button
+ enabled="false"
+ follows="left|top"
+ height="25"
+ label="Hide"
+ layout="topleft"
+ left_pad="10"
+ name="close_displayed_floater_2"
+ tool_tip="Closes the currently-displayed floater, if one exists"
+ top_delta="0"
+ width="85" />
+ <button
+ follows="left|top"
+ height="25"
+ label="Export Schema"
+ layout="topleft"
+ left_pad="10"
+ name="export_schema"
+ top_delta="0"
+ width="120" />
+ <check_box
+ follows="left|top"
+ label="Show Rectangles"
+ name="show_rectangles"
+ left_pad="10"
+ top_delta="0"
+ height="25"
+ width="120" />
+
+ <scroll_list
+ bottom="525"
+ column_padding="0"
+ draw_heading="true"
+ draw_stripes="false"
+ follows="left|top|bottom|right"
+ label="Name"
+ layout="topleft"
+ left="10"
+ name="name_list"
+ right="-10"
+ search_column="1"
+ top="80">
+ <scroll_list.columns
+ label="Title"
+ name="title_column"
+ width="150" />
+ <scroll_list.columns
+ label="File"
+ name="file_column"
+ width="150" />
+ <scroll_list.columns
+ dynamic_width="true"
+ label="Top-Level Node"
+ name="top_level_node_column" />
+ </scroll_list>
+ <panel
+ bevel_style="in"
+ bg_alpha_color="0 0 0 0"
+ bg_opaque_color="0 0 0 0.3"
+ border="true"
+ bottom_delta="65"
+ follows="left|right|bottom"
+ height="60"
+ layout="topleft"
+ left="10"
+ name="editor_panel"
+ right="-10">
+ <text
+ type="string"
+ length="1"
+ follows="left|bottom"
+ font="SansSerif"
+ height="30"
+ layout="topleft"
+ left="10"
+ left_delta="10"
+ name="editor_path_label"
+ top="10"
+ width="100">
+ Editor Path:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|bottom"
+ font="SansSerif"
+ handle_edit_keys_directly="true"
+ height="20"
+ layout="topleft"
+ left_delta="100"
+ max_length="300"
+ name="executable_path_field"
+ select_on_focus="true"
+ tool_tip="The full path to an editor (executable) to edit floater XML files (quotes not necessary)"
+ top_delta="-2"
+ width="315" />
+ <button
+ follows="left|bottom"
+ height="25"
+ label="Browse..."
+ label_selected="Browse..."
+ layout="topleft"
+ left_pad="5"
+ name="browse_for_executable"
+ tool_tip="Browse for an editor (executable) to edit floater XML files"
+ top_delta="-2"
+ width="75" />
+ <text
+ type="string"
+ length="1"
+ follows="left|bottom"
+ font="SansSerif"
+ height="30"
+ layout="topleft"
+ left="10"
+ left_delta="-420"
+ name="executable_args_label"
+ top="36"
+ width="100">
+ Editor Arguments:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|bottom"
+ font="SansSerif"
+ handle_edit_keys_directly="true"
+ height="20"
+ layout="topleft"
+ left_delta="100"
+ max_length="300"
+ name="executable_args_field"
+ select_on_focus="true"
+ tool_tip="Command-line arguments to the editor; use &apos;%FILE%&apos; to refer to the target file; &apos;YourProgram.exe FileName.xml&apos; will be run if this field is empty"
+ top_delta="-2"
+ width="315" />
+ </panel>
+ <panel
+ bevel_style="in"
+ bg_alpha_color="0 0 0 0"
+ bg_opaque_color="0 0 0 0.3"
+ border="true"
+ bottom_delta="40"
+ follows="left|right|bottom"
+ height="35"
+ layout="topleft"
+ left="10"
+ name="vlt_panel"
+ right="-10">
+ <text
+ type="string"
+ length="1"
+ follows="left|bottom"
+ font="SansSerif"
+ height="30"
+ layout="topleft"
+ left="10"
+ left_delta="10"
+ name="diff_file_label"
+ top="10"
+ width="200">
+ Delta File:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|bottom"
+ font="SansSerif"
+ handle_edit_keys_directly="true"
+ height="20"
+ layout="topleft"
+ left_delta="65"
+ max_length="300"
+ name="vlt_diff_path_field"
+ select_on_focus="true"
+ tool_tip="The full path to an XML D0 or D1 localization difference file generated by the Viewer Localization Toolkit"
+ top_delta="-2"
+ width="235" />
+ <button
+ follows="left|bottom"
+ height="25"
+ label="Browse..."
+ label_selected="Browse..."
+ layout="topleft"
+ left_pad="5"
+ name="browse_for_vlt_diffs"
+ tool_tip="Browse for a VLT-generated D0 or D1 difference file to highlight changed files and elements"
+ top_delta="-2"
+ width="75" />
+ <button
+ follows="left|bottom"
+ height="25"
+ is_toggle="true"
+ label="Highlight Diffs"
+ label_selected="Unhighlight Diffs"
+ layout="topleft"
+ left_pad="5"
+ name="toggle_vlt_diff_highlight"
+ tool_tip="Toggle highlighting of files and elements containing changed localization data"
+ top_delta="0"
+ width="110" />
+ </panel>
+ </panel>
+ <scroll_container
+ follows="top|right|bottom"
+ height="600"
+ layout="topleft"
+ left="750"
+ name="overlap_scroll"
+ reserve_scroll_corner="true"
+ top="20"
+ width="300">
+ <panel
+ border="true"
+ name="overlap_dummy_panel"
+ top="0"
+ left="0"
+ width="300"
+ height="600"
+ >
+ <overlap_panel
+ background_opaque="true"
+ background_visible="true"
+ bevel_style="in"
+ bg_alpha_color="0 0 0 1"
+ bg_opaque_color="1 1 1 1"
+ border="true"
+ follows="top|right|bottom"
+ height="600"
+ label="Overlap Panel"
+ layout="topleft"
+ left="0"
+ min_width="300"
+ name="overlap_panel"
+ tool_tip="This panel displays the currently-selected element and all of the elements that overlap it, separated by horizontal lines"
+ top="0"
+ visible="false"
+ width="300" />
+ <text
+ type="string"
+ length="1"
+ follows="top|right"
+ font="SansSerif"
+ height="30"
+ layout="topleft"
+ left="10"
+ name="overlap_panel_label"
+ top="10"
+ width="150">
+ Overlapping Elements:
+ </text>
+ </panel>
+ </scroll_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_url_entry.xml b/indra/newview/skins/default/xui/en/floater_url_entry.xml
new file mode 100644
index 0000000000..29fb29fabf
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_url_entry.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ height="87"
+ layout="topleft"
+ name="url_entry"
+ help_topic="url_entry"
+ width="280">
+ <text
+ type="string"
+ length="1"
+ bottom="20"
+ follows="top|left"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="media_label"
+ top="20">
+ Media URL:
+ </text>
+ <combo_box
+ allow_text_entry="true"
+ follows="left|top|right"
+ height="19"
+ layout="topleft"
+ left_delta="70"
+ max_chars="255"
+ name="media_entry"
+ top_delta="-4"
+ width="190" />
+ <button
+ follows="top|left"
+ height="20"
+ label="OK"
+ layout="topleft"
+ left="10"
+ name="ok_btn"
+ top="50"
+ width="64" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Cancel"
+ layout="topleft"
+ left_pad="5"
+ name="cancel_btn"
+ top_delta="0"
+ width="64" />
+ <button
+ follows="top|right"
+ height="20"
+ label="Clear"
+ layout="topleft"
+ left_pad="65"
+ name="clear_btn"
+ top_delta="0"
+ width="64" />
+ <text
+ type="string"
+ length="1"
+ font="SansSerifSmall"
+ bottom_delta="-2"
+ follows="bottom|left"
+ height="15"
+ layout="topleft"
+ left="152"
+ name="loading_label"
+ visible="true">
+ Loading...
+ </text>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
new file mode 100644
index 0000000000..c4411db8c5
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ can_resize="true"
+ can_minimize="true"
+ can_close="false"
+ height="202"
+ layout="topleft"
+ min_height="124"
+ min_width="190"
+ name="floater_voice_controls"
+ help_topic="floater_voice_controls"
+ title="Voice Controls"
+ save_visibility="true"
+ single_instance="true"
+ width="282">
+ <string
+ name="title_nearby">
+ NEARBY VOICE
+ </string>
+ <string
+ name="title_group">
+ Group Call with [GROUP]
+ </string>
+ <string
+ name="title_adhoc">
+ Conference Call
+ </string>
+ <string
+ name="title_peer_2_peer">
+ Call with [NAME]
+ </string>
+ <string
+ name="no_one_near">
+ No one near has voice enabled
+ </string>
+ <layout_stack
+ clip="false"
+ follows="all"
+ height="189"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="my_call_stack"
+ orientation="vertical"
+ width="263">
+ <layout_panel
+ follows="top|left|right"
+ user_resize="false"
+ auto_resize="false"
+ layout="topleft"
+ height="26"
+ name="my_panel">
+ <avatar_icon
+ enabled="false"
+ follows="left|top"
+ height="18"
+ default_icon_name="Generic_Person"
+ layout="topleft"
+ left="5"
+ name="user_icon"
+ top="0"
+ width="18" />
+ <text
+ follows="top|left|right"
+ font="SansSerifSmallBold"
+ height="16"
+ layout="topleft"
+ left_pad="10"
+ name="user_text"
+ text_color="white"
+ top="4"
+ use_ellipses="true"
+ value="Mya Avatar:"
+ width="210" />
+ <output_monitor
+ auto_update="true"
+ draw_border="false"
+ follows="top|right"
+ height="16"
+ layout="topleft"
+ right="-3"
+ name="speaking_indicator"
+ left_pad="5"
+ visible="true"
+ width="20" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ user_resize="false"
+ follows="top|left"
+ height="26"
+ visible="true"
+ layout="topleft"
+ name="leave_call_btn_panel"
+ width="100">
+ <button
+ follows="right|top"
+ height="23"
+ top_pad="0"
+ label="Leave Call"
+ name="leave_call_btn"
+ width="100" />
+ </layout_panel>
+ <layout_panel
+ follows="all"
+ layout="topleft"
+ left="2"
+ top_pad="0"
+ height="132"
+ name="callers_panel"
+ user_resize="false"
+ width="280">
+ <avatar_list
+ follows="all"
+ height="132"
+ ignore_online_status="true"
+ layout="topleft"
+ multi_select="true"
+ name="speakers_list"
+ width="280" />
+ <panel
+ filename="panel_avatar_list_item.xml"
+ follows="left|right|top"
+ height="24"
+ layout="topleft"
+ left="0"
+ name="non_avatar_caller"
+ top="10"
+ width="276" />
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_water.xml b/indra/newview/skins/default/xui/en/floater_water.xml
new file mode 100644
index 0000000000..32739ac953
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_water.xml
@@ -0,0 +1,498 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="240"
+ layout="topleft"
+ name="Water Floater"
+ help_topic="water_floater"
+ save_rect="true"
+ title="ADVANCED WATER EDITOR"
+ width="700">
+ <floater.string
+ name="WLDefaultWaterNames">
+ Default:Glassy:Pond:Murky:Second Plague:SNAKE!!!:Valdez
+ </floater.string>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font.style="BOLD"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="KeyFramePresetsText"
+ top="34"
+ width="110">
+ Water Presets:
+ </text>
+ <combo_box
+ height="18"
+ layout="topleft"
+ left_pad="10"
+ name="WaterPresetsCombo"
+ top_delta="-2"
+ width="150" />
+ <button
+ height="20"
+ label="New"
+ label_selected="New"
+ layout="topleft"
+ left_pad="20"
+ name="WaterNewPreset"
+ top_delta="1"
+ width="90" />
+ <button
+ height="20"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ left_pad="10"
+ name="WaterSavePreset"
+ top_delta="0"
+ width="90" />
+ <button
+ height="20"
+ label="Delete"
+ label_selected="Delete"
+ layout="topleft"
+ left_pad="10"
+ name="WaterDeletePreset"
+ top_delta="0"
+ width="90" />
+ <tab_container
+ border="false"
+ follows="left|top"
+ height="180"
+ halign="center"
+ layout="topleft"
+ left="0"
+ name="Water Tabs"
+ tab_position="top"
+ top="60"
+ width="700">
+ <panel
+ border="true"
+ follows="all"
+ height="180"
+ label="Settings"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ help_topic="water_settings_tab"
+ name="Settings"
+ top="0"
+ width="698">
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="BHText"
+ top="4"
+ width="200">
+ Water Fog Color
+ </text>
+ <color_swatch
+ can_apply_immediately="true"
+ color="0.5 0.5 0.5 1"
+ follows="left|top"
+ height="50"
+ layout="topleft"
+ left="40"
+ name="WaterFogColor"
+ tool_tip="Click to open color picker"
+ top="30"
+ width="40" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="WaterFogDensText"
+ top="84"
+ width="200">
+ Fog Density Exponent
+ </text>
+ <slider
+ control_name="WaterFogDensity"
+ decimal_digits="1"
+ follows="left"
+ height="10"
+ initial_value="16"
+ layout="topleft"
+ left="24"
+ max_val="10"
+ name="WaterFogDensity"
+ top="124"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-14"
+ name="WaterUnderWaterFogModText"
+ top="124"
+ width="200">
+ Underwater Fog Modifier
+ </text>
+ <slider
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="16"
+ layout="topleft"
+ left="24"
+ max_val="2"
+ name="WaterUnderWaterFogMod"
+ top="164"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="245"
+ name="BDensText"
+ top="4"
+ width="200">
+ Reflection Wavelet Scale
+ </text>
+ <slider
+ control_name="WaterNormalScaleX"
+ decimal_digits="1"
+ follows="left"
+ height="15"
+ initial_value="0.7"
+ label="1"
+ layout="topleft"
+ max_val="10"
+ name="WaterNormalScaleX"
+ top_pad="24"
+ width="200" />
+ <slider
+ control_name="WaterNormalScaleY"
+ decimal_digits="1"
+ follows="left"
+ height="15"
+ initial_value="0.7"
+ label="2"
+ layout="topleft"
+ max_val="10"
+ name="WaterNormalScaleY"
+ top_pad="4"
+ width="200" />
+ <slider
+ control_name="WaterNormalScaleZ"
+ decimal_digits="1"
+ follows="left"
+ height="15"
+ initial_value="0.7"
+ label="3"
+ layout="topleft"
+ max_val="10"
+ name="WaterNormalScaleZ"
+ top_pad="4"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ name="HDText"
+ top="84"
+ width="200">
+ Fresnel Scale
+ </text>
+ <slider
+ control_name="WaterFresnelScale"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ name="WaterFresnelScale"
+ top="124"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ name="FresnelOffsetText"
+ top="124"
+ width="200">
+ Fresnel Offset
+ </text>
+ <slider
+ control_name="WaterFresnelOffset"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ name="WaterFresnelOffset"
+ top="164"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="480"
+ name="DensMultText"
+ top="4"
+ width="200">
+ Refract Scale Above
+ </text>
+ <slider
+ control_name="WaterScaleAbove"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.1"
+ layout="topleft"
+ left="494"
+ name="WaterScaleAbove"
+ top="44"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-14"
+ name="WaterScaleBelowText"
+ top="44"
+ width="200">
+ Refract Scale Below
+ </text>
+ <slider
+ control_name="WaterScaleBelow"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0"
+ layout="topleft"
+ left="494"
+ name="WaterScaleBelow"
+ top="84"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-14"
+ name="MaxAltText"
+ top="84"
+ width="200">
+ Blur Multiplier
+ </text>
+ <slider
+ control_name="WaterBlurMult"
+ follows="left"
+ height="10"
+ increment="0.001"
+ initial_value="0"
+ layout="topleft"
+ left="494"
+ max_val="0.16"
+ name="WaterBlurMult"
+ top="124"
+ width="200" />
+ </panel>
+ <panel
+ border="true"
+ follows="all"
+ height="180"
+ label="Image"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ help_topic="water_waves_tab"
+ name="Waves"
+ top="0"
+ width="698">
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="BHText"
+ top="10"
+ width="200">
+ Big Wave Direction
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="WaterWave1DirXText"
+ top_pad="4"
+ width="10">
+ X
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="WaterWave1DirYText"
+ top_delta="18"
+ width="10">
+ Y
+ </text>
+ <slider
+ control_name="WaterWave1DirX"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left="24"
+ max_val="4"
+ min_val="-4"
+ name="WaterWave1DirX"
+ top="55"
+ width="200" />
+ <slider
+ control_name="WaterWave1DirY"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left_delta="0"
+ max_val="4"
+ min_val="-4"
+ name="WaterWave1DirY"
+ top_pad="5"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-14"
+ name="BHText2"
+ top_delta="3"
+ width="355">
+ Little Wave Direction
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="WaterWave2DirXText"
+ top="90"
+ width="10">
+ X
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="WaterWave2DirYText"
+ top_delta="20"
+ width="10">
+ Y
+ </text>
+ <slider
+ control_name="WaterWave2DirX"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left="24"
+ max_val="4"
+ min_val="-4"
+ name="WaterWave2DirX"
+ top="115"
+ width="200" />
+ <slider
+ control_name="WaterWave2DirY"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left_delta="0"
+ max_val="4"
+ min_val="-4"
+ name="WaterWave2DirY"
+ top_pad="10"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="240"
+ name="BHText3"
+ top="4"
+ width="200">
+ Normal Map
+ </text>
+ <texture_picker
+ height="143"
+ layout="topleft"
+ left="250"
+ name="WaterNormalMap"
+ top="22"
+ width="128" />
+ </panel>
+ </tab_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_wearable_save_as.xml b/indra/newview/skins/default/xui/en/floater_wearable_save_as.xml
new file mode 100644
index 0000000000..b4b57f2dbc
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_wearable_save_as.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="0"
+ can_close="false"
+ can_minimize="false"
+ height="100"
+ layout="topleft"
+ name="modal container"
+ width="240">
+ <button
+ height="23"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ left="20"
+ name="Save"
+ top="70"
+ width="82" />
+ <button
+ height="23"
+ label="Cancel"
+ label_selected="Cancel"
+ layout="topleft"
+ left_pad="36"
+ name="Cancel"
+ top_delta="0"
+ width="82" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="30"
+ layout="topleft"
+ word_wrap="true"
+ left="20"
+ name="Save item as:"
+ top="10"
+ width="200">
+ Save item to my inventory as:
+ </text>
+ <line_editor
+ type="string"
+ length="1"
+ border_style="line"
+ border_thickness="1"
+ follows="left|top"
+ handle_edit_keys_directly="true"
+ height="23"
+ layout="topleft"
+ left_delta="0"
+ max_length="63"
+ name="name ed"
+ top_pad="0"
+ width="200">
+ New [DESC]
+ </line_editor>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml b/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml
new file mode 100644
index 0000000000..897d959b98
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_minimize="false"
+ height="108"
+ layout="topleft"
+ name="whitelist_entry"
+ single_instance="true"
+ help_topic="whitelist_entry"
+ title="WHITELIST ENTRY"
+ width="390">
+
+ <text type="string" length="1" bottom="20" follows="top|left" height="15" layout="topleft"
+ left="10" name="media_label" top="20">
+ Enter a URL or URL pattern to add to the list of allowed domains
+ </text>
+
+ <line_editor bottom_delta="40" enabled="true" follows="left|top" font="SansSerif"
+ height="20" left="10" name="whitelist_entry"
+ tool_tip="Enter a URL or URL pattern to White List"
+ width="350" />
+
+ <button follows="top|left" height="20" label="OK"
+ layout="topleft" left="10" name="ok_btn" bottom_delta="28" width="64" />
+
+ <button follows="top|left" height="20" label="Cancel"
+ layout="topleft" left_pad="5" name="cancel_btn" bottom_delta="0" width="64" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_windlight_options.xml b/indra/newview/skins/default/xui/en/floater_windlight_options.xml
new file mode 100644
index 0000000000..0cb7814c6a
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_windlight_options.xml
@@ -0,0 +1,1274 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="220"
+ layout="topleft"
+ name="WindLight floater"
+ help_topic="windlight_floater"
+ save_rect="true"
+ title="ADVANCED SKY EDITOR"
+ width="700">
+ <floater.string
+ name="WLDefaultSkyNames">
+ A-12AM:A-12PM:A-3AM:A-3PM:A-4.30PM:A-6AM:A-6PM:A-9AM:A-9PM:Barcelona:Blizzard:Blue Midday:Coastal Afternoon:Coastal Sunset:Default:Desert Sunset:Fine Day:Fluffy Big Clouds:Foggy:Funky Funky:Funky Funky Funky:Gelatto:Ghost:Incongruent Truths:Midday 1:Midday 2:Midday 3:Midday 4:Night:Pirate:Purple:Sailor&apos;s Delight:Sheer Sensuality
+ </floater.string>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="KeyFramePresetsText"
+ top="34"
+ width="110">
+ Sky Presets:
+ </text>
+ <combo_box
+ height="18"
+ layout="topleft"
+ left_delta="110"
+ name="WLPresetsCombo"
+ top_delta="-2"
+ width="150" />
+ <button
+ height="20"
+ label="New"
+ label_selected="New"
+ layout="topleft"
+ left_pad="20"
+ name="WLNewPreset"
+ top_delta="1"
+ width="70" />
+ <button
+ height="20"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ left_pad="10"
+ name="WLSavePreset"
+ top_delta="0"
+ width="70" />
+ <button
+ height="20"
+ label="Delete"
+ label_selected="Delete"
+ layout="topleft"
+ left_pad="10"
+ name="WLDeletePreset"
+ top_delta="0"
+ width="70" />
+ <button
+ height="20"
+ label="Day Cycle Editor"
+ label_selected="Day Cycle Editor"
+ layout="topleft"
+ left_pad="50"
+ name="WLDayCycleMenuButton"
+ top_delta="0"
+ width="120" />
+ <tab_container
+ follows="left|top"
+ height="160"
+ halign="center"
+ layout="topleft"
+ left="0"
+ name="WindLight Tabs"
+ tab_position="top"
+ tab_height="20"
+ top="60"
+ width="700">
+ <panel
+ border="true"
+ follows="left|top|right|bottom"
+ height="160"
+ label="Atmosphere"
+ layout="topleft"
+ left="1"
+ mouse_opaque="false"
+ help_topic="windlight_atmosphere_tab"
+ name="Atmosphere"
+ top="60"
+ width="698">
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="BHText"
+ top="4"
+ width="355">
+ Blue Horizon
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="BHText2"
+ top="21"
+ width="10">
+ R
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="BHText3"
+ top_delta="11"
+ width="10">
+ G
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="BHText4"
+ top_delta="11"
+ width="10">
+ B
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="BHText5"
+ top_delta="11"
+ width="10">
+ I
+ </text>
+ <slider
+ control_name="WLBlueHorizonR"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left="24"
+ name="WLBlueHorizonR"
+ top="40"
+ width="200" />
+ <slider
+ control_name="WLBlueHorizonG"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left_delta="0"
+ name="WLBlueHorizonG"
+ top_pad="1"
+ width="200" />
+ <slider
+ control_name="WLBlueHorizonB"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left_delta="0"
+ name="WLBlueHorizonB"
+ top_pad="1"
+ width="200" />
+ <slider
+ control_name="WLBlueHorizonI"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="1.0"
+ layout="topleft"
+ left_delta="0"
+ name="WLBlueHorizonI"
+ top_pad="1"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-14"
+ name="BDensText"
+ top_delta="-2"
+ width="355">
+ Haze Horizon
+ </text>
+ <slider
+ control_name="WLHazeHorizon"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.25"
+ layout="topleft"
+ left="24"
+ name="WLHazeHorizon"
+ top="107"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="245"
+ name="BDensText2"
+ top="4"
+ width="355">
+ Blue Density
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left="245"
+ name="BHText6"
+ top="21"
+ width="10">
+ R
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="BHText7"
+ top_delta="11"
+ width="10">
+ G
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="BHText8"
+ top_delta="11"
+ width="10">
+ B
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="BHText9"
+ top_delta="11"
+ width="10">
+ I
+ </text>
+ <slider
+ control_name="WLBlueDensityR"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left="259"
+ name="WLBlueDensityR"
+ top="40"
+ width="200" />
+ <slider
+ control_name="WLBlueDensityG"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left_delta="0"
+ name="WLBlueDensityG"
+ top_pad="1"
+ width="200" />
+ <slider
+ control_name="WLBlueDensityB"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left_delta="0"
+ name="WLBlueDensityB"
+ top_pad="1"
+ width="200" />
+ <slider
+ control_name="WLBlueDensityI"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="1"
+ layout="topleft"
+ left_delta="0"
+ name="WLBlueDensityI"
+ top_pad="1"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-14"
+ name="HDText"
+ top_delta="-2"
+ width="355">
+ Haze Density
+ </text>
+ <slider
+ control_name="WLHazeDensity"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left="259"
+ max_val="4"
+ name="WLHazeDensity"
+ top="107"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="480"
+ name="DensMultText"
+ top="4"
+ width="355">
+ Density Multiplier
+ </text>
+ <slider
+ control_name="WLDensityMult"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.1"
+ layout="topleft"
+ left="494"
+ max_val="0.9"
+ name="WLDensityMult"
+ top="40"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-14"
+ name="WLDistanceMultText"
+ top_delta="-3"
+ width="355">
+ Distance Multiplier
+ </text>
+ <slider
+ control_name="WLDistancMult"
+ decimal_digits="1"
+ follows="left"
+ height="10"
+ initial_value="1.0"
+ layout="topleft"
+ left="494"
+ max_val="100"
+ name="WLDistanceMult"
+ top="73"
+ width="207" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-14"
+ name="MaxAltText"
+ top_delta="-2"
+ width="355">
+ Max Altitude
+ </text>
+ <slider
+ control_name="WLMaxAltitude"
+ decimal_digits="0"
+ follows="left"
+ height="10"
+ increment="1"
+ initial_value="500"
+ layout="topleft"
+ left="494"
+ max_val="4000"
+ name="WLMaxAltitude"
+ top="107"
+ width="205" />
+ </panel>
+ <panel
+ border="true"
+ follows="left|top|right|bottom"
+ height="160"
+ label="Lighting"
+ layout="topleft"
+ left_delta="0"
+ help_topic="windlight_lighting_tab"
+ name="Lighting"
+ top_delta="4"
+ width="698">
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="SLCText"
+ top="4"
+ width="355">
+ Sun/Moon Color
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="BHText"
+ top="21"
+ width="10">
+ R
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="BHText2"
+ top_delta="11"
+ width="10">
+ G
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="BHText3"
+ top_delta="11"
+ width="10">
+ B
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="BHText4"
+ top_delta="11"
+ width="10">
+ I
+ </text>
+ <slider
+ control_name="WLSunlightR"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left="24"
+ name="WLSunlightR"
+ top="40"
+ width="200" />
+ <slider
+ control_name="WLSunlightG"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left_delta="0"
+ name="WLSunlightG"
+ top_pad="1"
+ width="200" />
+ <slider
+ control_name="WLSunlightB"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left_delta="0"
+ name="WLSunlightB"
+ top_pad="1"
+ width="200" />
+ <slider
+ control_name="WLSunlightI"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="1.0"
+ layout="topleft"
+ left_delta="0"
+ name="WLSunlightI"
+ top_pad="1"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-14"
+ name="TODText"
+ top_delta="-2"
+ width="355">
+ Sun/Moon Position
+ </text>
+ <icon
+ height="20"
+ image_name="icon_diurnal.tga"
+ layout="topleft"
+ left="30"
+ name="SkyDayCycle"
+ top="97"
+ width="148" />
+ <slider
+ control_name="WLSunAngle"
+ follows="left"
+ height="10"
+ increment="0.001"
+ initial_value="0.7"
+ layout="topleft"
+ left="24"
+ name="WLSunAngle"
+ top="137"
+ width="204" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="245"
+ name="WLAmbientText"
+ top="4"
+ width="355">
+ Ambient
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left="245"
+ name="BHText5"
+ top="21"
+ width="10">
+ R
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="BHText6"
+ top_delta="11"
+ width="10">
+ G
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="BHText7"
+ top_delta="11"
+ width="10">
+ B
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="BHText8"
+ top_delta="11"
+ width="10">
+ I
+ </text>
+ <slider
+ control_name="WLAmbientR"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left="259"
+ name="WLAmbientR"
+ top="40"
+ width="200" />
+ <slider
+ control_name="WLAmbientG"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left_delta="0"
+ name="WLAmbientG"
+ top_pad="1"
+ width="200" />
+ <slider
+ control_name="WLAmbientB"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left_delta="0"
+ name="WLAmbientB"
+ top_pad="1"
+ width="200" />
+ <slider
+ control_name="WLAmbientI"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="1"
+ layout="topleft"
+ left_delta="0"
+ name="WLAmbientI"
+ top_pad="1"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-14"
+ name="WLEastAngleText"
+ top_delta="-2"
+ width="355">
+ East Angle
+ </text>
+ <slider
+ control_name="WLEastAngle"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.0"
+ layout="topleft"
+ left="259"
+ name="WLEastAngle"
+ top="107"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="480"
+ name="SunGlowText"
+ top="4"
+ width="355">
+ Sun Glow
+ </text>
+ <slider
+ control_name="WLGlowB"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.1"
+ label="Focus "
+ layout="topleft"
+ left="494"
+ max_val="0.5"
+ name="WLGlowB"
+ top="40"
+ width="200" />
+ <slider
+ control_name="WLGlowR"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.25"
+ label="Size "
+ layout="topleft"
+ left_delta="0"
+ max_val="1.99"
+ min_val="1"
+ name="WLGlowR"
+ top_pad="1"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-14"
+ name="SceneGammaText"
+ top_delta="0"
+ width="200">
+ Scene Gamma
+ </text>
+ <slider
+ control_name="WLGamma"
+ decimal_digits="2"
+ follows="bottom"
+ height="10"
+ increment="0.01"
+ initial_value="2.0"
+ layout="topleft"
+ left="494"
+ max_val="10"
+ name="WLGamma"
+ top="87"
+ width="207" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-14"
+ name="WLStarText"
+ top_delta="-1"
+ width="355">
+ Star Brightness
+ </text>
+ <slider
+ control_name="WLStarAlpha"
+ decimal_digits="2"
+ follows="bottom"
+ height="10"
+ increment="0.01"
+ initial_value="0"
+ layout="topleft"
+ left="494"
+ max_val="2"
+ name="WLStarAlpha"
+ top="122"
+ width="200" />
+ </panel>
+ <panel
+ border="true"
+ follows="left|top|right|bottom"
+ height="160"
+ label="Clouds"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ help_topic="windlight_clouds_tab"
+ name="Clouds"
+ top_delta="4"
+ width="698">
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="WLCloudColorText"
+ top="4"
+ width="355">
+ Cloud Color
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="BHText"
+ top="21"
+ width="10">
+ R
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="BHText2"
+ top_delta="11"
+ width="10">
+ G
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="BHText3"
+ top_delta="11"
+ width="10">
+ B
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="BHText4"
+ top_delta="11"
+ width="10">
+ I
+ </text>
+ <slider
+ control_name="WLCloudColorR"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left="24"
+ name="WLCloudColorR"
+ top="40"
+ width="200" />
+ <slider
+ control_name="WLCloudColorG"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left_delta="0"
+ name="WLCloudColorG"
+ top_pad="1"
+ width="200" />
+ <slider
+ control_name="WLCloudColorB"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.7"
+ layout="topleft"
+ left_delta="0"
+ name="WLCloudColorB"
+ top_pad="1"
+ width="200" />
+ <slider
+ control_name="WLCloudColorI"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="1.0"
+ layout="topleft"
+ left_delta="0"
+ name="WLCloudColorI"
+ top_pad="1"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-14"
+ name="WLCloudColorText2"
+ top_delta="-2"
+ width="355">
+ Cloud XY/Density
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="BHText5"
+ top="87"
+ width="10">
+ X
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="BHText6"
+ top_delta="11"
+ width="10">
+ Y
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="BHText7"
+ top_delta="11"
+ width="10">
+ D
+ </text>
+ <slider
+ control_name="WLCloudX"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.5"
+ layout="topleft"
+ left_pad="4"
+ name="WLCloudX"
+ top_delta="-2"
+ width="200" />
+ <slider
+ control_name="WLCloudY"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.5"
+ layout="topleft"
+ left_delta="0"
+ name="WLCloudY"
+ top_pad="1"
+ width="200" />
+ <slider
+ control_name="WLCloudDensity"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="1.0"
+ layout="topleft"
+ left_delta="0"
+ name="WLCloudDensity"
+ top_pad="1"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="245"
+ name="WLCloudCoverageText"
+ top="4"
+ width="355">
+ Cloud Coverage
+ </text>
+ <slider
+ control_name="WLCloudCoverage"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.5"
+ layout="topleft"
+ left="259"
+ name="WLCloudCoverage"
+ top="40"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-14"
+ name="WLCloudScaleText"
+ top_delta="-1"
+ width="355">
+ Cloud Scale
+ </text>
+ <slider
+ control_name="WLCloudScale"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="1.0"
+ layout="topleft"
+ left="259"
+ min_val="0.01"
+ name="WLCloudScale"
+ top="75"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-14"
+ name="WLCloudDetailText"
+ top_delta="-4"
+ width="355">
+ Cloud Detail (XY/Density)
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left="245"
+ name="BHText8"
+ top="87"
+ width="10">
+ X
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="BHText9"
+ top_delta="11"
+ width="10">
+ Y
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ halign="center"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="BHText10"
+ top_delta="11"
+ width="10">
+ D
+ </text>
+ <slider
+ control_name="WLCloudDetailX"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.5"
+ layout="topleft"
+ left_pad="4"
+ name="WLCloudDetailX"
+ top_delta="-2"
+ width="200" />
+ <slider
+ control_name="WLCloudDetailY"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.5"
+ layout="topleft"
+ left_delta="0"
+ name="WLCloudDetailY"
+ top_pad="1"
+ width="200" />
+ <slider
+ control_name="WLCloudDetailDensity"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="1.0"
+ layout="topleft"
+ left_delta="0"
+ name="WLCloudDetailDensity"
+ top_pad="1"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left="480"
+ name="WLCloudScrollXText"
+ top="4"
+ width="355">
+ Cloud Scroll X
+ </text>
+ <check_box
+ control_name="WLCloudLockX"
+ follows="left"
+ height="16"
+ label="Lock"
+ layout="topleft"
+ left="625"
+ name="WLCloudLockX"
+ width="200" />
+ <slider
+ control_name="WLCloudScrollX"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.5"
+ layout="topleft"
+ left="494"
+ max_val="10"
+ min_val="-10"
+ name="WLCloudScrollX"
+ top="45"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerif"
+ height="16"
+ layout="topleft"
+ left_delta="-14"
+ name="WLCloudScrollYText"
+ top_delta="-1"
+ width="355">
+ Cloud Scroll Y
+ </text>
+ <check_box
+ control_name="WLCloudLockY"
+ follows="left"
+ height="16"
+ label="Lock"
+ layout="topleft"
+ left="625"
+ name="WLCloudLockY"
+ width="200" />
+ <slider
+ control_name="WLCloudScrollY"
+ decimal_digits="2"
+ follows="left"
+ height="10"
+ increment="0.01"
+ initial_value="0.5"
+ layout="topleft"
+ left="494"
+ max_val="10"
+ min_val="-10"
+ name="WLCloudScrollY"
+ top="85"
+ width="200" />
+ <check_box
+ control_name="DrawClassicClouds"
+ follows="left"
+ height="16"
+ label="Draw Classic Clouds"
+ layout="topleft"
+ left="480"
+ name="DrawClassicClouds"
+ top="104"
+ width="200" />
+ </panel>
+ </tab_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_window_size.xml b/indra/newview/skins/default/xui/en/floater_window_size.xml
new file mode 100644
index 0000000000..355d257785
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_window_size.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ can_minimize="false"
+ can_resize="false"
+ height="105"
+ layout="topleft"
+ name="window_size"
+ title="WINDOW SIZE"
+ width="205">
+ <string name="resolution_format">[RES_X] x [RES_Y]</string>
+ <text
+ follows="top|left"
+ font="SansSerif"
+ height="16"
+ left="15"
+ top="10"
+ name="windowsize_text"
+ width="280">
+ Set window size:
+ </text>
+ <combo_box
+ allow_text_entry="true"
+ height="23"
+ follows="left|top"
+ left_delta="0"
+ max_chars="20"
+ name="window_size_combo"
+ tool_tip="width x height"
+ top_pad="5"
+ width="179">
+ <combo_box.item
+ label="1000 x 700 (default)"
+ name="item0"
+ value="1000 x 700" />
+ <combo_box.item
+ label="1024 x 768"
+ name="item1"
+ value="1024 x 768" />
+ <combo_box.item
+ label="1280 x 720 (720p)"
+ name="item2"
+ value="1280 x 720" />
+ <combo_box.item
+ label="1920 x 1080 (1080p)"
+ name="item3"
+ value="1920 x 1080" />
+ </combo_box>
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Set"
+ left_delta="0"
+ name="set_btn"
+ top_pad="10"
+ width="85" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Cancel"
+ left_pad="5"
+ name="cancel_btn"
+ top_delta="0"
+ width="85" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_world_map.xml b/indra/newview/skins/default/xui/en/floater_world_map.xml
new file mode 100644
index 0000000000..65c9c2a8fa
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_world_map.xml
@@ -0,0 +1,687 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ center_horiz="true"
+ center_vert="true"
+ height="535"
+ layout="topleft"
+ min_height="520"
+ min_width="520"
+ name="worldmap"
+ help_topic="worldmap"
+ save_rect="true"
+ save_visibility="true"
+ single_instance="true"
+ title="WORLD MAP"
+ width="800">
+ <panel
+ filename="panel_world_map.xml"
+ follows="all"
+ height="500"
+ layout="topleft"
+ left="10"
+ name="objects_mapview"
+ top="25"
+ width="542" />
+ <panel
+ name="layout_panel_1"
+ height="22"
+ width="238"
+ follows="right|top"
+ top="25"
+ left_pad="5"
+ background_visible="true"
+ bg_alpha_color="DkGray2">
+ <text
+ text_color="White"
+ font="SansSerifLarge"
+ type="string"
+ length="1"
+ follows="top|right"
+ halign="left"
+ height="16"
+ 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">
+<button
+ follows="right|top"
+ height="22"
+ image_overlay="map_avatar_16.tga"
+ scale_image="true"
+ left="4"
+ layout="topleft"
+ name="Show My Location"
+ tool_tip="Center map on my avatar&apos;s location"
+ top="6"
+ width="24" >
+ <button.commit_callback
+ function="WMap.ShowAgent" />
+ </button>
+ <text
+ type="string"
+ length="1"
+ follows="top|right"
+ halign="left"
+ height="13"
+ top_delta="6"
+ left_pad="5"
+ layout="topleft"
+ name="me_label"
+ width="90">
+ Me
+ </text>
+ <check_box
+ control_name="MapShowPeople"
+ follows="top|right"
+ height="16"
+ layout="topleft"
+ left="3"
+ name="people_chk"
+ top_pad="9"
+ width="22" />
+ <icon
+ color="0 1 0 1"
+ follows="top|right"
+ height="8"
+ image_name="map_avatar_8.tga"
+ layout="topleft"
+ left_pad="3"
+ mouse_opaque="true"
+ name="person"
+ top_delta="3"
+ width="8" />
+ <text
+ type="string"
+ length="1"
+ follows="top|right"
+ halign="left"
+ height="16"
+ top_delta="-2"
+ left_pad="7"
+ layout="topleft"
+ name="person_label"
+ width="90">
+ Person
+ </text>
+ <check_box
+ control_name="MapShowInfohubs"
+ follows="top|right"
+ height="16"
+ layout="topleft"
+ left="3"
+ name="infohub_chk"
+ top_pad="3"
+ width="22" />
+ <icon
+ follows="top|right"
+ height="16"
+ image_name="map_infohub.tga"
+ layout="topleft"
+ left_pad="0"
+ mouse_opaque="true"
+ name="infohub"
+ top_delta="0"
+ width="16" />
+ <text
+ type="string"
+ length="1"
+ follows="top|right"
+ halign="left"
+ height="16"
+ top_delta="2"
+ left_pad="3"
+ layout="topleft"
+ name="infohub_label"
+ width="90">
+ Infohub
+ </text>
+ <check_box
+ control_name="MapShowLandForSale"
+ follows="top|right"
+ height="16"
+ layout="topleft"
+ left="3"
+ name="land_for_sale_chk"
+ top_pad="2"
+ width="22" />
+ <icon
+ follows="top|right"
+ height="16"
+ image_name="icon_for_sale.tga"
+ layout="topleft"
+ mouse_opaque="true"
+ name="landforsale"
+ top_delta="0"
+ left_pad="0"
+ width="16" />
+ <text
+ type="string"
+ length="1"
+ follows="top|right"
+ halign="left"
+ height="16"
+ top_delta="2"
+ left_pad="3"
+ layout="topleft"
+ name="land_sale_label"
+ width="90">
+ Land Sale
+ </text>
+ <icon
+ color="1 1 0.25 1"
+ follows="top|right"
+ height="16"
+ image_name="legend.tga"
+ layout="topleft"
+ mouse_opaque="true"
+ name="square2"
+ left="41"
+ top_pad="-2"
+ width="16" />
+ <text
+ type="string"
+ length="1"
+ follows="top|right"
+ height="16"
+ layout="topleft"
+ left_pad="0"
+ name="by_owner_label"
+ top_delta="3"
+ width="100">
+ by owner
+ </text>
+ <icon
+ color="0.5 0.25 1 1"
+ follows="top|right"
+ height="16"
+ image_name="legend.tga"
+ layout="topleft"
+ mouse_opaque="true"
+ name="square2"
+ left="41"
+ top_pad="-3"
+ width="16" />
+ <text
+ type="string"
+ length="1"
+ follows="top|right"
+ height="16"
+ layout="topleft"
+ left_pad="0"
+ name="auction_label"
+ top_delta="3"
+ width="170">
+ land auction
+ </text>
+
+ <button
+ follows="top|right"
+ height="22"
+ image_overlay="map_home.tga"
+ scale_image="true"
+ label_color="White"
+ layout="topleft"
+ left="136"
+ top="6"
+ name="Go Home"
+ tool_tip="Teleport to my home location"
+ width="24" >
+ <button.commit_callback
+ function="WMap.GoHome" />
+ </button>
+ <text
+ type="string"
+ length="1"
+ follows="top|right"
+ halign="left"
+ height="13"
+ top_delta="6"
+ left_pad="5"
+ layout="topleft"
+ name="Home_label"
+ width="70">
+ Home
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="top|right"
+ halign="left"
+ height="16"
+ layout="topleft"
+ left="137"
+ name="events_label"
+ top_pad="9"
+ width="66">
+ Events:
+ </text>
+
+ <check_box
+ control_name="MapShowEvents"
+ follows="top|right"
+ height="16"
+ layout="topleft"
+ left="135"
+ top_pad="1"
+ name="event_chk"
+ width="22" />
+ <icon
+ follows="top|right"
+ height="16"
+ image_name="map_event.tga"
+ layout="topleft"
+ mouse_opaque="true"
+ name="event"
+ left_pad="0"
+ width="16" />
+ <text
+ type="string"
+ length="1"
+ follows="top|right"
+ halign="left"
+ height="16"
+ top_delta="2"
+ left_pad="3"
+ layout="topleft"
+ name="pg_label"
+ width="60">
+ General
+ </text>
+
+ <check_box
+ control_name="ShowMatureEvents"
+ follows="top|right"
+ height="16"
+ initial_value="true"
+ layout="topleft"
+ left="135"
+ name="event_mature_chk"
+ top_pad="3"
+ width="22" />
+ <icon
+ follows="top|right"
+ height="16"
+ image_name="map_event_mature.tga"
+ layout="topleft"
+ mouse_opaque="true"
+ name="events_mature_icon"
+ top_delta="0"
+ left_pad="0"
+ width="16" />
+ <text
+ type="string"
+ length="1"
+ follows="top|right"
+ halign="left"
+ height="16"
+ top_delta="2"
+ left_pad="3"
+ layout="topleft"
+ name="mature_label"
+ width="66">
+ Moderate
+ </text>
+
+ <check_box
+ control_name="ShowAdultEvents"
+ follows="top|right"
+ height="16"
+ layout="topleft"
+ left="135"
+ name="event_adult_chk"
+ top_pad="3"
+ width="22" />
+ <icon
+ follows="top|right"
+ height="16"
+ image_name="map_event_adult.tga"
+ layout="topleft"
+ left_pad="0"
+ mouse_opaque="true"
+ name="events_adult_icon"
+ top_delta="0"
+ width="16" />
+ <text
+ type="string"
+ length="1"
+ follows="top|right"
+ halign="left"
+ height="16"
+ top_delta="2"
+ left_pad="3"
+ layout="topleft"
+ name="adult_label"
+ width="66">
+ Adult
+ </text>
+</panel>
+
+
+ <panel
+ follows="right|top"
+ height="22"
+ top_pad="0"
+ width="238"
+ background_visible="true"
+ bg_alpha_color="DkGray2">
+ <text
+ text_color="White"
+ font="SansSerifLarge"
+ type="string"
+ length="1"
+ follows="top|right"
+ halign="left"
+ height="16"
+ layout="topleft"
+ left="15"
+ name="find_on_map_label"
+ top="3"
+ width="215">
+ Find on Map
+ </text>
+ </panel>
+
+ <panel
+ follows="right|top|bottom"
+ height="270"
+ top_pad="0"
+ width="238">
+ <icon
+ color="0.5 0 0 1"
+ follows="top|right"
+ height="16"
+ image_name="map_track_16.tga"
+ layout="topleft"
+ left="5"
+ top="11"
+ mouse_opaque="true"
+ name="friends_icon"
+ width="16" />
+ <combo_box
+ allow_text_entry="true"
+ follows="top|right"
+ height="23"
+ label="Online Friends"
+ layout="topleft"
+ top_delta="-4"
+ left_pad="5"
+ max_chars="60"
+ name="friend combo"
+ tool_tip="Show friends on map"
+ width="182">
+ <combo_box.item
+ label="My Friends Online"
+ name="item1"
+ value="None" />
+ <combo_box.commit_callback
+ function="WMap.AvatarCombo"/>
+ </combo_box>
+ <icon
+ color="0.5 0 0 1"
+ follows="top|right"
+ height="16"
+ image_name="map_track_16.tga"
+ layout="topleft"
+ left="5"
+ top_pad="8"
+ mouse_opaque="true"
+ name="landmark_icon"
+ width="16" />
+ <combo_box
+ allow_text_entry="true"
+ follows="top|right"
+ height="23"
+ label="My Landmarks"
+ layout="topleft"
+ top_delta="-3"
+ left_pad="5"
+ max_chars="64"
+ name="landmark combo"
+ tool_tip="Landmark to show on map"
+ width="182">
+ <combo_box.item
+ label="My Landmarks"
+ name="item1"
+ value="None" />
+ <combo_box.commit_callback
+ function="WMap.Landmark"/>
+ </combo_box>
+ <icon
+ color="0.5 0 0 1"
+ follows="top|right"
+ height="16"
+ image_name="map_track_16.tga"
+ layout="topleft"
+ left="5"
+ top_pad="7"
+ mouse_opaque="true"
+ name="region_icon"
+ width="16" />
+ <search_editor
+ follows="top|right"
+ search_button_visible="false"
+ height="22"
+ text_readonly_color="DkGray"
+ label="Regions by Name"
+ layout="topleft"
+ top_delta="-2"
+ left_pad="5"
+ name="location"
+ select_on_focus="true"
+ tool_tip="Type the name of a region"
+ width="152">
+ <search_editor.commit_callback
+ function="WMap.Location" />
+ </search_editor>
+ <button
+ follows="top|right"
+ height="23"
+ label="Find"
+ layout="topleft"
+ left_pad="2"
+ top_delta="-1"
+ name="DoSearch"
+ tool_tip="Search for region"
+ width="58">
+ <button.commit_callback
+ function="WMap.Location" />
+ </button>
+ <scroll_list
+ draw_stripes="false"
+ bg_writeable_color="MouseGray"
+ follows="all"
+ height="115"
+ layout="topleft"
+ left="28"
+ name="search_results"
+ top_pad="5"
+ width="209"
+ sort_column="1">
+ <scroll_list.columns
+ label=""
+ name="icon"
+ width="16" />
+ <scroll_list.columns
+ label=""
+ name="sim_name"
+ width="193" />
+ <scroll_list.commit_callback
+ function="WMap.SearchResult" />
+ </scroll_list>
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Teleport"
+ layout="topleft"
+ left="25"
+ name="Teleport"
+ tool_tip="Teleport to selected location"
+ top_pad="7"
+ width="104">
+ <button.commit_callback
+ function="WMap.Teleport" />
+ </button>
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Copy SLurl"
+ layout="topleft"
+ left_pad="5"
+ name="copy_slurl"
+ tool_tip="Copies current location as SLurl to be used on the web."
+ top_delta="0"
+ width="104">
+ <button.commit_callback
+ function="WMap.CopySLURL" />
+ </button>
+ <!-- <button
+ follows="right|bottom"
+ height="23"
+ label="Clear"
+ layout="topleft"
+ left="10"
+ name="Clear"
+ tool_tip="Stop tracking"
+ top_pad="5"
+ width="105">
+ <button.commit_callback
+ function="WMap.Clear" />
+ </button>-->
+ <button
+ enabled="false"
+ follows="right|bottom"
+ height="23"
+ label="Show Selection"
+ left="25"
+ top_pad="5"
+ name="Show Destination"
+ tool_tip="Center map on selected location"
+ width="213">
+ <button.commit_callback
+ function="WMap.ShowTarget" />
+ </button>
+
+<!-- <text
+ type="string"
+ length="1"
+ follows="bottom|right"
+ halign="left"
+ height="16"
+ top_pad="4"
+ left="25"
+ layout="topleft"
+ name="land_sale_label"
+ width="250">
+ Location:
+ </text>
+ <spinner
+ decimal_digits="0"
+ follows="bottom|right"
+ increment="1"
+ initial_value="128"
+ layout="topleft"
+ top_pad="0"
+ left="25"
+ max_val="255"
+ name="spin x"
+ tool_tip="X coordinate of location to show on map"
+ width="48">
+ <spinner.commit_callback
+ function="WMap.CommitLocation" />
+ </spinner>
+ <spinner
+ decimal_digits="0"
+ follows="bottom|right"
+ height="16"
+ increment="1"
+ initial_value="128"
+ layout="topleft"
+ left_pad="2"
+ max_val="255"
+ name="spin y"
+ tool_tip="Y coordinate of location to show on map"
+ top_delta="0"
+ width="48" >
+ <spinner.commit_callback
+ function="WMap.CommitLocation" />
+ </spinner>
+ <spinner
+ decimal_digits="0"
+ follows="bottom|right"
+ increment="1"
+ initial_value="0"
+ layout="topleft"
+ left_pad="2"
+ max_val="4096"
+ name="spin z"
+ tool_tip="Z coordinate of location to show on map"
+ top_delta="0"
+ width="48">
+ <spinner.commit_callback
+ function="WMap.CommitLocation" />
+ </spinner>-->
+ </panel>
+ <panel
+ follows="right|bottom"
+ height="22"
+ top_pad="0"
+ width="238"
+ background_visible="true"
+ bg_alpha_color="DkGray2">
+ <text
+ text_color="White"
+ font="SansSerifLarge"
+ type="string"
+ length="1"
+ follows="top|right"
+ halign="left"
+ height="16"
+ layout="topleft"
+ left="15"
+ name="zoom_label"
+ top="3"
+ width="210">
+ Zoom
+ </text>
+ </panel>
+ <panel
+ follows="right|bottom"
+ height="30"
+ min_height="30"
+ top_pad="0"
+ width="238">
+ <icon
+ follows="left|bottom"
+ height="16"
+ image_name="Zoom_Off"
+ layout="topleft"
+ left="20"
+ mouse_opaque="true"
+ name="zoom_icon"
+ top_pad="7"
+ width="16" />
+ <slider
+ follows="left|bottom"
+ height="16"
+ increment="0.2"
+ initial_value="-2"
+ left_pad="0"
+ layout="topleft"
+ max_val="0"
+ min_val="-8"
+ name="zoom slider"
+ show_text="false"
+ width="200" />
+ </panel>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml
new file mode 100644
index 0000000000..ebbb53729d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/fonts.xml
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<fonts>
+
+ <font name="default" comment="default font files (global fallbacks)">
+ <file>DejaVuSans.ttf</file>
+ <os name="Windows">
+ <file>MSGOTHIC.TTC</file>
+ <file>gulim.ttc</file>
+ <file>simhei.ttf</file>
+ <file>ArialUni.ttf</file>
+ </os>
+ <os name="Mac">
+ <file>ヒラギノ角ゴ Pro W3.otf</file>
+ <file>ヒラギノ角ゴ ProN W3.otf</file>
+ <file>AppleGothic.dfont</file>
+ <file>AppleGothic.ttf</file>
+ <file>åŽæ–‡ç»†é»‘.ttf</file>
+ </os>
+ </font>
+
+ <font name="SansSerifBold"
+ comment="Name of bold sans-serif font">
+ <file>DejaVuSans-Bold.ttf</file>
+ <os name="Windows">
+ <file>arialbd.ttf</file>
+ </os>
+ <os name="Mac">
+ <file>Helvetica.dfont</file>
+ </os>
+ </font>
+
+ <font name="SansSerif" comment="Name of san-serif font (Truetype file name)">
+ <file>DejaVuSans.ttf</file>
+ <os name="Windows">
+ <file>arial.ttf</file>
+ </os>
+ <os name="Mac">
+ <file>Helvetica.dfont</file>
+ </os>
+ </font>
+
+ <font name="SansSerif"
+ comment="Name of bold sans-serif font"
+ font_style="BOLD">
+ <file>DejaVuSans-Bold.ttf</file>
+ </font>
+
+ <font name="SansSerif"
+ comment="Name of italic sans-serif font"
+ font_style="ITALIC">
+ <file>DejaVuSans-Oblique.ttf</file>
+ </font>
+
+ <font name="SansSerif"
+ comment="Name of bold italic sans-serif font"
+ font_style="BOLD|ITALIC">
+ <file>DejaVuSans-BoldOblique.ttf</file>
+ </font>
+
+ <font name="Monospace"
+ comment="Name of monospace font">
+ <file>DejaVuSansMono.ttf</file>
+ </font>
+
+ <font name="DejaVu"
+ comment="Name of DejaVu font">
+ <file>DejaVuSans.ttf</file>
+ </font>
+
+ <font name="DejaVu"
+ comment="Name of DejaVu font (bold)"
+ font_style="BOLD">
+ <file>DejaVuSans-Bold.ttf</file>
+ </font>
+
+ <font name="DejaVu"
+ comment="Name of DejaVu font (italic)"
+ font_style="ITALIC">
+ <file>DejaVuSans-Oblique.ttf</file>
+ </font>
+
+ <font name="DejaVu"
+ comment="Name of DejaVu font (bold italic)"
+ font_style="BOLD|ITALIC">
+ <file>DejaVuSans-BoldOblique.ttf</file>
+ </font>
+
+ <font name="Helvetica"
+ comment="Name of Helvetica font">
+ <file>DejaVuSans.ttf</file>
+ <os name="Windows">
+ <file>arial.ttf</file>
+ </os>
+ <os name="Mac">
+ <file>arial.ttf</file>
+ </os>
+ </font>
+
+ <font name="Helvetica"
+ comment="Name of Helvetica font (bold)"
+ font_style="BOLD">
+ <file>DejaVuSans-Bold.ttf</file>
+ <os name="Windows">
+ <file>arialbd.ttf</file>
+ </os>
+ <os name="Mac">
+ <file>arialbd.ttf</file>
+ </os>
+ </font>
+
+ <font name="Helvetica"
+ comment="Name of Helvetica font (italic)"
+ font_style="ITALIC">
+ <file>DejaVuSans-Oblique.ttf</file>
+ <os name="Windows">
+ <file>ariali.ttf</file>
+ </os>
+ <os name="Mac">
+ <file>ariali.ttf</file>
+ </os>
+ </font>
+
+ <font name="Helvetica"
+ comment="Name of Helvetica font (bold italic)"
+ font_style="BOLD|ITALIC">
+ <file>DejaVuSans-BoldOblique.ttf</file>
+ <os name="Windows">
+ <file>arialbi.ttf</file>
+ </os>
+ <os name="Mac">
+ <file>arialbi.ttf</file>
+ </os>
+ </font>
+
+ <font name="OverrideTest"
+ comment="Name of font to test overriding">
+ <file>times.ttf</file>
+ <file>DejaVuSans.ttf</file>
+ </font>
+
+ <font_size name="Monospace"
+ comment="Size for monospaced font (points, or 1/72 of an inch)"
+ size="8.0"
+ />
+ <font_size name="Huge"
+ comment="Size of huge font (points, or 1/72 of an inch)"
+ size="16.0"
+ />
+ <font_size name="Large"
+ comment="Size of large font (points, or 1/72 of an inch)"
+ size="10.6"
+ />
+ <font_size name="Medium"
+ comment="Size of medium font (points, or 1/72 of an inch)"
+ size="8.6"
+ />
+ <font_size name="Small"
+ comment="Size of small font (points, or 1/72 of an inch)"
+ size="7.6"
+ />
+</fonts>
diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml
new file mode 100644
index 0000000000..9796f7b5b6
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater
+ legacy_header_height="25"
+ bevel_style="in"
+ bg_opaque_image="Inspector_Background"
+ can_close="false"
+ can_minimize="false"
+ height="148"
+ layout="topleft"
+ name="inspect_avatar"
+ single_instance="true"
+ sound_flags="0"
+ visible="true"
+ width="228">
+ <!-- Allowed fields include:
+ [BORN_ON] ("12/3/2008")
+ [SL_PROFILE] (Second Life profile),
+ [RW_PROFILE] (real world profile),
+ [ACCTTYPE] ("Resident"),
+ [PAYMENTINFO] ("Payment Info on File"),
+ [AGE] ("1 year 2 months")
+ -->
+ <string
+ name="Subtitle">
+[AGE]
+ </string>
+ <string
+ name="Details">
+[SL_PROFILE]
+ </string>
+ <text
+ follows="top|left"
+ font="SansSerifLarge"
+ height="16"
+ left="8"
+ name="user_name"
+ top="10"
+ text_color="White"
+ use_ellipses="true"
+ value="Grumpity ProductEngine"
+ width="175" />
+ <text
+ follows="top|left"
+ height="16"
+ left="8"
+ name="user_subtitle"
+ font="SansSerifSmall"
+ text_color="White"
+ value="11 Months, 3 days old"
+ width="175"
+ use_ellipses="true" />
+ <text
+ follows="left|top|right"
+ height="35"
+ left="8"
+ name="user_details"
+ right="-10"
+ word_wrap="true"
+ top_pad="6"
+ use_ellipses="true"
+ width="220">This is my second life description and I really think it is great.
+ </text>
+ <slider
+ follows="top|left"
+ height="23"
+ increment="0.01"
+ left="1"
+ max_val="0.95"
+ min_val="0.05"
+ name="volume_slider"
+ show_text="false"
+ tool_tip="Voice volume"
+ top_pad="0"
+ value="0.5"
+ width="195" />
+ <button
+ follows="top|left"
+ height="16"
+ image_disabled="Audio_Off"
+ image_disabled_selected="AudioMute_Off"
+ image_hover_selected="AudioMute_Over"
+ image_selected="AudioMute_Off"
+ image_unselected="Audio_Off"
+ is_toggle="true"
+ left_pad="0"
+ top_delta="4"
+ name="mute_btn"
+ width="16" />
+ <avatar_icon
+ follows="top|left"
+ height="38"
+ right="-10"
+ bevel_style="in"
+ border_style="line"
+ mouse_opaque="true"
+ name="avatar_icon"
+ top="10"
+ width="38" />
+<!-- Overlapping buttons for default actions
+ llinspectavatar.cpp makes visible the most likely default action
+-->
+ <button
+ follows="top|left"
+ height="20"
+ label="Add Friend"
+ left="8"
+ top="119"
+ name="add_friend_btn"
+ width="90" />
+ <button
+ follows="top|left"
+ height="20"
+ label="IM"
+ left_delta="0"
+ top_delta="0"
+ name="im_btn"
+ width="80"
+ commit_callback.function="InspectAvatar.IM"/>
+ <button
+ follows="top|left"
+ height="20"
+ label="More"
+ layout="topleft"
+ name="view_profile_btn"
+ left_delta="96"
+ top_delta="0"
+ tab_stop="false"
+ width="80" />
+ <!-- gear buttons here -->
+ <menu_button
+ follows="top|left"
+ height="20"
+ layout="topleft"
+ image_overlay="OptionsMenu_Off"
+ menu_filename="menu_inspect_avatar_gear.xml"
+ name="gear_btn"
+ right="-5"
+ top_delta="0"
+ width="35" />
+ <menu_button
+ follows="top|left"
+ height="20"
+ image_overlay="OptionsMenu_Off"
+ menu_filename="menu_inspect_self_gear.xml"
+ name="gear_self_btn"
+ right="-5"
+ top_delta="0"
+ width="35" />
+ <panel
+ follows="top|left"
+ top="148"
+ left="0"
+ height="60"
+ width="228"
+ visible="false"
+ background_visible="true"
+ name="moderator_panel"
+ background_opaque="true"
+ bg_opaque_color="MouseGray">
+ <button
+ name="disable_voice"
+ label="Disable Voice"
+ top="20"
+ width="95"
+ height="20"
+ left="10"
+ commit_callback.function="InspectAvatar.DisableVoice"/>
+ <button
+ name="enable_voice"
+ label="Enable Voice"
+ top="20"
+ width="95"
+ height="20"
+ left="10"
+ visible="false"
+ commit_callback.function="InspectAvatar.EnableVoice"/>
+ </panel>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/inspect_group.xml b/indra/newview/skins/default/xui/en/inspect_group.xml
new file mode 100644
index 0000000000..37ae5a64d7
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/inspect_group.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater
+ legacy_header_height="25"
+ bevel_style="in"
+ bg_opaque_image="Inspector_Background"
+ can_close="false"
+ can_minimize="false"
+ height="158"
+ layout="topleft"
+ name="inspect_group"
+ single_instance="true"
+ sound_flags="0"
+ visible="true"
+ width="228">
+ <string name="PrivateGroup">Private group</string>
+ <string name="FreeToJoin">Free to join</string>
+ <string name="CostToJoin">L$[AMOUNT] to join</string>
+ <string name="YouAreMember">You are a member</string>
+ <text
+ follows="all"
+ font="SansSerifLarge"
+ height="16"
+ left="8"
+ name="group_name"
+ top="10"
+ text_color="White"
+ use_ellipses="true"
+ width="175"
+ word_wrap="false">
+ Grumpity&apos;s Grumpy Group of Moose
+ </text>
+ <text
+ follows="all"
+ font="SansSerifSmall"
+ text_color="White"
+ height="16"
+ left="8"
+ name="group_subtitle"
+ use_ellipses="true"
+ width="175">
+ 123 members
+ </text>
+ <text
+ follows="all"
+ height="45"
+ left="8"
+ name="group_details"
+ use_ellipses="true"
+ top_pad="6"
+ width="220"
+ word_wrap="true">
+A group of folks charged with creating a room with a moose.
+Fear the moose! Fear it! And the mongoose too!
+ </text>
+ <text
+ follows="all"
+ height="13"
+ left="8"
+ name="group_cost"
+ top_pad="13"
+ width="220">
+L$123 to join
+ </text>
+ <icon
+ follows="all"
+ height="38"
+ right="-10"
+ mouse_opaque="true"
+ name="group_icon"
+ top="10"
+ width="38"
+ bevel_style="in" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Join"
+ left="8"
+ top="286"
+ name="join_btn"
+ width="103"
+ commit_callback.function="InspectGroup.Join"/>
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Leave"
+ left="8"
+ top="286"
+ name="leave_btn"
+ width="103"
+ commit_callback.function="InspectGroup.Leave"/>
+ <button
+ follows="bottom|left"
+ height="23"
+ label="View Profile"
+ name="view_profile_btn"
+ top="286"
+ left="117"
+ width="103"
+ commit_callback.function="InspectGroup.ViewProfile" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/inspect_object.xml b/indra/newview/skins/default/xui/en/inspect_object.xml
new file mode 100644
index 0000000000..00e00b9694
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/inspect_object.xml
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater
+ legacy_header_height="25"
+ bevel_style="in"
+ bg_opaque_image="Inspector_Background"
+ can_close="false"
+ can_minimize="false"
+ height="150"
+ layout="topleft"
+ name="inspect_object"
+ single_instance="true"
+ sound_flags="0"
+ visible="true"
+ width="228">
+ <string name="Creator">By [CREATOR]</string>
+ <string name="CreatorAndOwner">
+by [CREATOR]
+owner [OWNER]
+ </string>
+ <string name="Price">L$[AMOUNT]</string>
+ <string name="PriceFree">Free!</string>
+ <string name="Touch">Touch</string>
+ <string name="Sit">Sit</string>
+ <text
+ follows="all"
+ font="SansSerifLarge"
+ height="16"
+ left="8"
+ name="object_name"
+ text_color="White"
+ top="10"
+ use_ellipses="true"
+ value="Test Object Name That Is Really Long"
+ width="220" />
+ <text
+ follows="all"
+ height="33"
+ left="8"
+ name="object_creator"
+ top_pad="0"
+ use_ellipses="true"
+ width="220">
+ by secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
+owner secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
+ </text>
+ <!-- *TODO: Replace this icon -->
+ <icon
+ name="price_icon"
+ image_name="Icon_For_Sale"
+ right="-5"
+ width="16"
+ height="16"
+ top="56"
+ follows="left|top"
+ />
+ <text
+ follows="all"
+ font="SansSerifSmall"
+ font.style="BOLD"
+ height="16"
+ halign="right"
+ left="5"
+ name="price_text"
+ text_color="white"
+ top="58"
+ font_shadow="none"
+ width="196">
+L$300,000
+ </text>
+ <text
+ clip_partial="true"
+ follows="all"
+ font="SansSerifSmall"
+ height="37"
+ left="8"
+ name="object_description"
+ top_pad="0"
+ use_ellipses="true"
+ width="220"
+ word_wrap="true">
+This is a really long description for an object being as how it is at least 80 characters in length and maybe more like 120 at this point. Who knows, really?
+ </text>
+ <!-- Overlapping buttons for all default actions. Show "Buy" if
+ for sale, "Sit" if can sit, etc. -->
+ <text
+ follows="all"
+ font="SansSerifSmall"
+ height="13"
+ left_delta="0"
+ name="object_media_url"
+ bottom_pad="2"
+ width="200"
+ max_length = "50"
+ use_ellipses="true">
+ http://www.superdupertest.com
+</text>
+ <button
+ follows="top|left"
+ height="20"
+ label="Buy"
+ left="8"
+ name="buy_btn"
+ top="121"
+ width="80" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Pay"
+ left_delta="0"
+ name="pay_btn"
+ top_delta="0"
+ width="80" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Take Copy"
+ left_delta="0"
+ name="take_free_copy_btn"
+ top_delta="0"
+ width="80" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Touch"
+ left_delta="0"
+ name="touch_btn"
+ top_delta="0"
+ width="80" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Sit"
+ left_delta="0"
+ name="sit_btn"
+ top_delta="0"
+ width="80" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Open"
+ left_delta="0"
+ name="open_btn"
+ top_delta="0"
+ width="80" />
+ <icon
+ name="secure_browsing"
+ image_name="Lock"
+ left_delta="80"
+ visible="false"
+ width="18"
+ height="18"
+ top_delta="0"
+ tool_tip="Secure Browsing"
+ follows="left|top" />
+
+ <!-- non-overlapping buttons here -->
+ <button
+ follows="top|left"
+ height="20"
+ label="More"
+ layout="topleft"
+ name="more_info_btn"
+ left_delta="10"
+ top_delta="0"
+ tab_stop="false"
+ width="80" />
+ <menu_button
+ follows="top|left"
+ height="20"
+ image_overlay="OptionsMenu_Off"
+ menu_filename="menu_inspect_object_gear.xml"
+ name="gear_btn"
+ right="-5"
+ top_delta="0"
+ width="35" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/inspect_remote_object.xml b/indra/newview/skins/default/xui/en/inspect_remote_object.xml
new file mode 100644
index 0000000000..ef3dd844cd
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/inspect_remote_object.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater
+ legacy_header_height="18"
+ bevel_style="in"
+ bg_opaque_image="Inspector_Background"
+ can_close="false"
+ can_minimize="false"
+ height="130"
+ layout="topleft"
+ name="inspect_remote_object"
+ single_instance="true"
+ sound_flags="0"
+ visible="true"
+ width="300">
+ <text
+ follows="all"
+ font="SansSerifLarge"
+ font_style="BOLD"
+ height="30"
+ left="8"
+ name="object_name"
+ text_color="White"
+ top="5"
+ use_ellipses="true"
+ word_wrap="true"
+ width="291">
+ Test Object Name That Is Really Long OMG so long I can't believe how long the name of this object is, I mean really.
+ </text>
+ <text
+ follows="top|left"
+ font="SansSerifSmall"
+ height="16"
+ left="8"
+ name="object_owner_label"
+ width="55"
+ top_pad="12">
+ Owner:
+ </text>
+ <text
+ follows="top|left"
+ height="16"
+ left_pad="5"
+ name="object_owner"
+ use_ellipses="true"
+ width="230"
+ word_wrap="false">
+ Longavatarname Johnsonlongstonnammer
+ </text>
+ <!--<text
+ follows="top|left"
+ height="16"
+ left="8"
+ name="object_slurl_label"
+ top_pad="5"
+ width="55">
+ Location:
+ </text>-->
+ <text
+ follows="top|left"
+ height="16"
+ left="8"
+ name="object_slurl"
+ width="290"
+ use_ellipses="true"
+ word_wrap="false">
+ http://slurl.com/Ahern/50/50/50
+ </text>
+ <button
+ follows="top|left"
+ height="23"
+ label="Map"
+ left="8"
+ top_pad="8"
+ name="map_btn"
+ width="90" />
+ <button
+ follows="top|left"
+ height="23"
+ label="Block"
+ left_pad="8"
+ name="block_btn"
+ width="90" />
+ <button
+ follows="top|left"
+ height="23"
+ label="Close"
+ right="-8"
+ name="close_btn"
+ left_pad="5"
+ width="90" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/inspect_toast.xml b/indra/newview/skins/default/xui/en/inspect_toast.xml
new file mode 100644
index 0000000000..0221397a8c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/inspect_toast.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater
+ legacy_header_height="25"
+ bevel_style="in"
+ bg_opaque_image="Inspector_Background"
+ can_close="false"
+ can_minimize="false"
+ height="148"
+ layout="topleft"
+ name="inspect_toast"
+ single_instance="true"
+ sound_flags="0"
+ visible="true"
+ width="228">
+</floater>
diff --git a/indra/newview/skins/default/xui/en/language_settings.xml b/indra/newview/skins/default/xui/en/language_settings.xml
new file mode 100644
index 0000000000..c523185034
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/language_settings.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- This file contains strings that used to be hardcoded in the source.-->
+<strings>
+
+ <!-- Locale Information -->
+ <string name="MicrosoftLocale">english</string>
+ <string name="DarwinLocale">C</string>
+ <string name="LinuxLocale">C</string>
+
+ <!-- Note: for plural nouns, see strings.xml. For example:
+ AgeYearsA = singular,
+ AgeYearsB = plural,
+ AgeYearsC = plural for non-English languages like Russian
+ For example, LLTrans::getCountString("AgeYears", 3) is plural form B
+ in English and form C in Russian -->
+ <!--
+ datetimeToCodes["wkday"] = "%a"; // Thu
+ datetimeToCodes["weekday"] = "%A"; // Thursday
+ datetimeToCodes["year4"] = "%Y"; // 2009
+ datetimeToCodes["year"] = "%Y"; // 2009
+ datetimeToCodes["year2"] = "%y"; // 09
+ datetimeToCodes["mth"] = "%b"; // Aug
+ datetimeToCodes["month"] = "%B"; // August
+ datetimeToCodes["mthnum"] = "%m"; // 08
+ datetimeToCodes["day"] = "%d"; // 31
+ datetimeToCodes["hour24"] = "%H"; // 14
+ datetimeToCodes["hour"] = "%H"; // 14
+ datetimeToCodes["hour12"] = "%I"; // 02
+ datetimeToCodes["min"] = "%M"; // 59
+ datetimeToCodes["ampm"] = "%p"; // AM
+ datetimeToCodes["second"] = "%S"; // 59
+ datetimeToCodes["timezone"] = "%Z"; // PST
+ -->
+
+ <string name="TimeHour">hour,datetime,slt</string>
+ <string name="TimeMin">min,datetime,slt</string>
+ <string name="TimeYear">year,datetime,slt</string>
+ <string name="TimeDay">day,datetime,slt</string>
+ <string name="TimeMonth">mthnum,datetime,slt</string>
+ <string name="TimeWeek">wkday,datetime,slt</string>
+ <string name="TimeAMPM">ampm,datetime,slt</string>
+ <string name="TimeHour12">hour12,datetime,slt</string>
+
+ <string name="LTimeMthNum">mthnum,datetime,local</string>
+ <string name="LTimeWeek">wkday,datetime,local</string>
+ <string name="LTimeMonth">mth,datetime,local</string>
+ <string name="LTimeDay">day,datetime,local</string>
+ <string name="LTimeSec">second,datetime,local</string>
+ <string name="LTimeHour">hour,datetime,local</string>
+ <string name="LTimeMin">min,datetime,local</string>
+ <string name="LTimeYear">year,datetime,local</string>
+
+ <string name="UTCTimeWeek">weekday,datetime,utc</string>
+ <string name="UTCTimeDay">day,datetime,utc</string>
+ <string name="UTCTimeMth">mth,datetime,utc</string>
+ <string name="UTCTimeYr">year,datetime,utc</string>
+ <string name="UTCTimeHr">hour,datetime,utc</string>
+ <string name="UTCTimeMin">min,datetime,utc</string>
+ <string name="UTCTimeSec">second,datetime,utc</string>
+ <string name="UTCTimeTimezone">timezone,datetime,utc</string>
+</strings>
diff --git a/indra/newview/skins/default/xui/en/main_view.xml b/indra/newview/skins/default/xui/en/main_view.xml
new file mode 100644
index 0000000000..1d4377e339
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/main_view.xml
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="left|right|top|bottom"
+ height="768"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ tab_stop="false"
+ name="main_view"
+ width="1024">
+ <layout_stack border_size="0"
+ follows="all"
+ mouse_opaque="false"
+ height="749"
+ name="menu_stack"
+ orientation="vertical"
+ top="19">
+ <layout_panel auto_resize="false"
+ height="60"
+ mouse_opaque="false"
+ name="nav_bar_container"
+ tab_stop="false"
+ width="1024"
+ user_resize="false"
+ visible="false">
+ </layout_panel>
+ <layout_panel auto_resize="true"
+ follows="all"
+ height="500"
+ layout="topleft"
+ mouse_opaque="false"
+ tab_stop="false"
+ name="hud"
+ width="1024">
+ <layout_stack border_size="0"
+ follows="all"
+ height="500"
+ left="0"
+ mouse_opaque="false"
+ name="hud_stack"
+ orientation="horizontal"
+ top="0"
+ width="1024">
+ <layout_panel auto_resize="true"
+ follows="all"
+ height="500"
+ layout="topleft"
+ mouse_opaque="false"
+ tab_stop="false"
+ name="non_side_tray_view"
+ user_resize="false"
+ width="500">
+ <view bottom="500"
+ follows="all"
+ height="500"
+ left="0"
+ mouse_opaque="false"
+ name="world_view_rect"
+ width="500"/>
+ <layout_stack border_size="0"
+ bottom="500"
+ follows="all"
+ height="500"
+ left="0"
+ mouse_opaque="false"
+ name="world_stack"
+ orientation="vertical"
+ tab_stop="false">
+ <panel auto_resize="true"
+ follows="all"
+ height="500"
+ layout="topleft"
+ tab_stop="false"
+ mouse_opaque="false"
+ name="hud container"
+ width="500">
+ <panel follows="right|top|bottom"
+ height="500"
+ mouse_opaque="false"
+ name="side_bar_tabs"
+ right="500"
+ tab_stop="false"
+ top="0"
+ width="32"/>
+ <panel bottom="500"
+ follows="left|right|bottom"
+ height="25"
+ left="0"
+ mouse_opaque="false"
+ tab_stop="false"
+ name="stand_stop_flying_container"
+ visible="false"
+ width="500"/>
+ </panel>
+ <layout_panel auto_resize="false"
+ follows="all"
+ min_height="33"
+ mouse_opaque="false"
+ name="bottom_tray_container"
+ visible="false"/>
+ </layout_stack>
+ </layout_panel>
+ <!-- side tray -->
+ <layout_panel auto_resize="false"
+ follows="all"
+ height="500"
+ min_width="333"
+ mouse_opaque="false"
+ tab_stop="false"
+ name="side_tray_container"
+ user_resize="false"
+ visible="false"
+ width="333"/>
+ </layout_stack>
+ <panel follows="all"
+ height="500"
+ left="0"
+ mouse_opaque="false"
+ name="floater_view_holder"
+ tab_group="-1"
+ tab_stop="false"
+ top="0"
+ width="1024">
+ <floater_view follows="all"
+ height="500"
+ left="0"
+ mouse_opaque="false"
+ name="Floater View"
+ tab_group="-1"
+ tab_stop="false"
+ top="0"
+ width="1024"/>
+ </panel>
+ <debug_view follows="all"
+ left="0"
+ top="0"
+ mouse_opaque="false"
+ height="500"
+ name="DebugView"
+ width="1024"/>
+ </layout_panel>
+ </layout_stack>
+ <panel mouse_opaque="false"
+ follows="left|right|top"
+ name="status_bar_container"
+ tab_stop="false"
+ height="19"
+ left="0"
+ top="0"
+ width="1024"
+ visible="false"/>
+ <notify_box_view top="0"
+ follows="all"
+ height="768"
+ mouse_opaque="false"
+ name="notify_container"
+ tab_group="-2"
+ width="1024"/>
+ <menu_holder top="0"
+ follows="all"
+ height="768"
+ mouse_opaque="false"
+ name="Menu Holder"
+ width="1024"/>
+ <snapshot_floater_view enabled="false"
+ follows="all"
+ height="768"
+ left="0"
+ mouse_opaque="false"
+ name="Snapshot Floater View"
+ tab_stop="false"
+ top="0"
+ visible="false"
+ width="1024"/>
+ <tooltip_view top="0"
+ follows="all"
+ height="768"
+ mouse_opaque="false"
+ name="tooltip view"
+ tab_group="-2"
+ width="1024"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/menu_attachment_other.xml b/indra/newview/skins/default/xui/en/menu_attachment_other.xml
new file mode 100644
index 0000000000..5b94645b60
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_attachment_other.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- *NOTE: See also menu_avatar_other.xml -->
+<context_menu
+ layout="topleft"
+ name="Avatar Pie">
+ <menu_item_call
+ label="View Profile"
+ name="Profile...">
+ <menu_item_call.on_click
+ function="ShowAgentProfile"
+ parameter="hit object" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Add Friend"
+ name="Add Friend">
+ <menu_item_call.on_click
+ function="Avatar.AddFriend" />
+ <menu_item_call.on_enable
+ function="Avatar.EnableAddFriend" />
+ </menu_item_call>
+ <menu_item_call
+ label="IM"
+ name="Send IM...">
+ <menu_item_call.on_click
+ function="Avatar.SendIM" />
+ </menu_item_call>
+ <menu_item_call
+ label="Call"
+ name="Call">
+ <menu_item_call.on_click
+ function="Avatar.Call" />
+ </menu_item_call>
+ <menu_item_call
+ label="Invite to Group"
+ name="Invite...">
+ <menu_item_call.on_click
+ function="Avatar.InviteToGroup" />
+ </menu_item_call>
+ <menu_item_separator />
+ <menu_item_call
+ enabled="false"
+ label="Block"
+ name="Avatar Mute">
+ <menu_item_call.on_click
+ function="Avatar.Mute" />
+ <menu_item_call.on_enable
+ function="Avatar.EnableMute" />
+ </menu_item_call>
+ <menu_item_call
+ label="Report"
+ name="abuse">
+ <menu_item_call.on_click
+ function="Avatar.ReportAbuse" />
+ </menu_item_call>
+ <menu_item_call
+ label="Freeze"
+ name="Freeze...">
+ <menu_item_call.on_click
+ function="Avatar.Freeze" />
+ <menu_item_call.on_visible
+ function="Avatar.EnableFreezeEject"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Eject"
+ name="Eject...">
+ <menu_item_call.on_click
+ function="Avatar.Eject" />
+ <menu_item_call.on_visible
+ function="Avatar.EnableFreezeEject"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Debug"
+ name="Debug...">
+ <menu_item_call.on_click
+ function="Avatar.Debug" />
+ <menu_item_call.on_visible
+ function="IsGodCustomerService"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Zoom In"
+ name="Zoom In">
+ <menu_item_call.on_click
+ function="Tools.LookAtSelection"
+ parameter="zoom" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Pay"
+ name="Pay...">
+ <menu_item_call.on_click
+ function="PayObject" />
+ <menu_item_call.on_enable
+ function="EnablePayAvatar" />
+ </menu_item_call>
+ <menu_item_separator />
+ <menu_item_call
+ label="Object Profile"
+ name="Object Inspect">
+ <menu_item_call.on_click
+ function="Object.Inspect" />
+ <menu_item_call.on_enable
+ function="Object.EnableInspect" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_attachment_self.xml b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
new file mode 100644
index 0000000000..281ec5a7c3
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Attachment Pie">
+ <menu_item_call
+ enabled="false"
+ label="Touch"
+ layout="topleft"
+ name="Attachment Object Touch">
+ <menu_item_call.on_click
+ function="Object.Touch" />
+ <menu_item_call.on_enable
+ function="Object.EnableTouch"
+ name="EnableTouch"
+ parameter="Touch" />
+ </menu_item_call>
+ <!--menu_item_call
+ label="Stand Up"
+ layout="topleft"
+ name="Stand Up">
+ <menu_item_call.on_click
+ function="Self.StandUp"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="Self.EnableStandUp" />
+ </menu_item_call-->
+ <menu_item_call
+ enabled="false"
+ label="Edit"
+ layout="topleft"
+ name="Edit...">
+ <menu_item_call.on_click
+ function="Object.Edit" />
+ <menu_item_call.on_enable
+ function="EnableEdit" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Detach"
+ layout="topleft"
+ name="Detach">
+ <menu_item_call.on_click
+ function="Attachment.Detach" />
+ <menu_item_call.on_enable
+ function="Attachment.EnableDetach" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Drop"
+ layout="topleft"
+ name="Drop">
+ <menu_item_call.on_click
+ function="Attachment.Drop" />
+ <menu_item_call.on_enable
+ function="Attachment.EnableDrop" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+
+ <menu_item_call
+ label="Stand Up"
+ layout="topleft"
+ name="Stand Up">
+ <menu_item_call.on_click
+ function="Self.StandUp"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="Self.EnableStandUp" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Appearance"
+ name="Appearance...">
+ <menu_item_call.on_click
+ function="CustomizeAvatar" />
+ <menu_item_call.on_enable
+ function="Edit.EnableCustomizeAvatar" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Friends"
+ layout="topleft"
+ name="Friends...">
+ <menu_item_call.on_click
+ function="SideTray.PanelPeopleTab"
+ parameter="friends_panel" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Groups"
+ layout="topleft"
+ name="Groups...">
+ <menu_item_call.on_click
+ function="SideTray.PanelPeopleTab"
+ parameter="groups_panel" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Profile"
+ layout="topleft"
+ name="Profile...">
+ <menu_item_call.on_click
+ function="ShowAgentProfile"
+ parameter="agent" />
+ </menu_item_call>
+
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_avatar_icon.xml b/indra/newview/skins/default/xui/en/menu_avatar_icon.xml
new file mode 100644
index 0000000000..50910dff32
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_avatar_icon.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ height="101"
+ layout="topleft"
+ left="100"
+ mouse_opaque="false"
+ name="Avatar Icon Menu"
+ top="724"
+ visible="false"
+ width="128">
+ <menu_item_call
+ label="View Profile"
+ layout="topleft"
+ name="Show Profile">
+ <menu_item_call.on_click
+ function="AvatarIcon.Action"
+ parameter="profile" />
+ </menu_item_call>
+ <menu_item_call
+ label="Send IM..."
+ layout="topleft"
+ name="Send IM">
+ <menu_item_call.on_click
+ function="AvatarIcon.Action"
+ parameter="im" />
+ </menu_item_call>
+ <menu_item_call
+ label="Add Friend..."
+ layout="topleft"
+ name="Add Friend">
+ <menu_item_call.on_click
+ function="AvatarIcon.Action"
+ parameter="add" />
+ </menu_item_call>
+ <menu_item_call
+ label="Remove Friend..."
+ layout="topleft"
+ name="Remove Friend">
+ <menu_item_call.on_click
+ function="AvatarIcon.Action"
+ parameter="remove" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_avatar_other.xml b/indra/newview/skins/default/xui/en/menu_avatar_other.xml
new file mode 100644
index 0000000000..0ad41546d2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_avatar_other.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- *NOTE: See also menu_attachment_other.xml -->
+<context_menu
+ layout="topleft"
+ name="Avatar Pie">
+ <menu_item_call
+ label="View Profile"
+ name="Profile...">
+ <menu_item_call.on_click
+ function="ShowAgentProfile"
+ parameter="hit object" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Add Friend"
+ name="Add Friend">
+ <menu_item_call.on_click
+ function="Avatar.AddFriend" />
+ <menu_item_call.on_enable
+ function="Avatar.EnableAddFriend" />
+ </menu_item_call>
+ <menu_item_call
+ label="IM"
+ name="Send IM...">
+ <menu_item_call.on_click
+ function="Avatar.SendIM" />
+ </menu_item_call>
+ <menu_item_call
+ label="Call"
+ name="Call">
+ <menu_item_call.on_click
+ function="Avatar.Call" />
+ </menu_item_call>
+ <menu_item_call
+ label="Invite to Group"
+ name="Invite...">
+ <menu_item_call.on_click
+ function="Avatar.InviteToGroup" />
+ </menu_item_call>
+ <menu_item_separator />
+ <menu_item_call
+ enabled="false"
+ label="Block"
+ name="Avatar Mute">
+ <menu_item_call.on_click
+ function="Avatar.Mute" />
+ <menu_item_call.on_enable
+ function="Avatar.EnableMute" />
+ </menu_item_call>
+ <menu_item_call
+ label="Report"
+ name="abuse">
+ <menu_item_call.on_click
+ function="Avatar.ReportAbuse" />
+ </menu_item_call>
+ <menu_item_call
+ label="Freeze"
+ name="Freeze...">
+ <menu_item_call.on_click
+ function="Avatar.Freeze" />
+ <menu_item_call.on_visible
+ function="Avatar.EnableFreezeEject"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Eject"
+ name="Eject...">
+ <menu_item_call.on_click
+ function="Avatar.Eject" />
+ <menu_item_call.on_visible
+ function="Avatar.EnableFreezeEject"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Debug"
+ name="Debug...">
+ <menu_item_call.on_click
+ function="Avatar.Debug" />
+ <menu_item_call.on_visible
+ function="IsGodCustomerService"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Zoom In"
+ name="Zoom In">
+ <menu_item_call.on_click
+ function="Tools.LookAtSelection"
+ parameter="zoom" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Pay"
+ name="Pay...">
+ <menu_item_call.on_click
+ function="PayObject" />
+ <menu_item_call.on_enable
+ function="EnablePayAvatar" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_avatar_self.xml b/indra/newview/skins/default/xui/en/menu_avatar_self.xml
new file mode 100644
index 0000000000..9212d2d648
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_avatar_self.xml
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Self Pie">
+ <menu_item_call
+ label="Stand Up"
+ layout="topleft"
+ name="Stand Up">
+ <menu_item_call.on_click
+ function="Self.StandUp"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="Self.EnableStandUp" />
+ </menu_item_call>
+ <context_menu
+ label="Take Off &gt;"
+ layout="topleft"
+ name="Take Off &gt;">
+ <context_menu
+ label="Clothes &gt;"
+ layout="topleft"
+ name="Clothes &gt;">
+ <menu_item_call
+ enabled="false"
+ label="Shirt"
+ layout="topleft"
+ name="Shirt">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="shirt" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="shirt" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Pants"
+ layout="topleft"
+ name="Pants">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="pants" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="pants" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Skirt"
+ layout="topleft"
+ name="Skirt">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="skirt" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="skirt" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Shoes"
+ layout="topleft"
+ name="Shoes">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="shoes" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="shoes" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Socks"
+ layout="topleft"
+ name="Socks">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="socks" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="socks" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Jacket"
+ layout="topleft"
+ name="Jacket">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="jacket" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="jacket" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Gloves"
+ layout="topleft"
+ name="Gloves">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="gloves" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="gloves" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Undershirt"
+ layout="topleft"
+ name="Self Undershirt">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="undershirt" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="undershirt" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Underpants"
+ layout="topleft"
+ name="Self Underpants">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="underpants" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="underpants" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Tattoo"
+ layout="topleft"
+ name="Self Tattoo">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="tattoo" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="tattoo" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Alpha"
+ layout="topleft"
+ name="Self Alpha">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="alpha" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="alpha" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="All Clothes"
+ layout="topleft"
+ name="All Clothes">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="all" />
+ </menu_item_call>
+ </context_menu>
+ <context_menu
+ label="HUD &gt;"
+ layout="topleft"
+ name="Object Detach HUD" />
+ <context_menu
+ label="Detach &gt;"
+ layout="topleft"
+ name="Object Detach" />
+ <menu_item_call
+ label="Detach All"
+ layout="topleft"
+ name="Detach All">
+ <menu_item_call.on_click
+ function="Self.RemoveAllAttachments"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="Self.EnableRemoveAllAttachments" />
+ </menu_item_call>
+ </context_menu>
+ <menu_item_call
+ label="My Appearance"
+ layout="topleft"
+ name="Appearance...">
+ <menu_item_call.on_click
+ function="CustomizeAvatar" />
+ <menu_item_call.on_enable
+ function="Edit.EnableCustomizeAvatar" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Friends"
+ layout="topleft"
+ name="Friends...">
+ <menu_item_call.on_click
+ function="SideTray.PanelPeopleTab"
+ parameter="friends_panel" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Groups"
+ layout="topleft"
+ name="Groups...">
+ <menu_item_call.on_click
+ function="SideTray.PanelPeopleTab"
+ parameter="groups_panel" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Profile"
+ layout="topleft"
+ name="Profile...">
+ <menu_item_call.on_click
+ function="ShowAgentProfile"
+ parameter="agent" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_bottomtray.xml b/indra/newview/skins/default/xui/en/menu_bottomtray.xml
new file mode 100644
index 0000000000..7ef91a1d85
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_bottomtray.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ height="201"
+ layout="topleft"
+ left="100"
+ mouse_opaque="false"
+ name="hide_camera_move_controls_menu"
+ top="624"
+ visible="false"
+ width="128">
+ <menu_item_check
+ label="Gesture button"
+ layout="topleft"
+ name="ShowGestureButton">
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowGestureButton" />
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="ShowGestureButton" />
+ </menu_item_check>
+ <menu_item_check
+ label="Move button"
+ layout="topleft"
+ name="ShowMoveButton">
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowMoveButton" />
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="ShowMoveButton" />
+ </menu_item_check>
+ <menu_item_check
+ label="View button"
+ layout="topleft"
+ name="ShowCameraButton">
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowCameraButton" />
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="ShowCameraButton" />
+ </menu_item_check>
+ <menu_item_check
+ label="Snapshot button"
+ layout="topleft"
+ name="ShowSnapshotButton">
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowSnapshotButton" />
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="ShowSnapshotButton" />
+ </menu_item_check>
+ <menu_item_separator
+ name="Separator" />
+ <menu_item_call
+ label="Cut"
+ name="NearbyChatBar_Cut">
+ <menu_item_call.on_click
+ function="NearbyChatBar.Action"
+ parameter="cut" />
+ <menu_item_call.on_enable
+ function="NearbyChatBar.EnableMenuItem"
+ parameter="can_cut" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy"
+ name="NearbyChatBar_Copy">
+ <menu_item_call.on_click
+ function="NearbyChatBar.Action"
+ parameter="copy" />
+ <menu_item_call.on_enable
+ function="NearbyChatBar.EnableMenuItem"
+ parameter="can_copy" />
+ </menu_item_call>
+ <menu_item_call
+ label="Paste"
+ name="NearbyChatBar_Paste">
+ <menu_item_call.on_click
+ function="NearbyChatBar.Action"
+ parameter="paste" />
+ <menu_item_call.on_enable
+ function="NearbyChatBar.EnableMenuItem"
+ parameter="can_paste" />
+ </menu_item_call>
+ <menu_item_call
+ label="Delete"
+ name="NearbyChatBar_Delete">
+ <menu_item_call.on_click
+ function="NearbyChatBar.Action"
+ parameter="delete" />
+ <menu_item_call.on_enable
+ function="NearbyChatBar.EnableMenuItem"
+ parameter="can_delete" />
+ </menu_item_call>
+ <menu_item_call
+ label="Select All"
+ name="NearbyChatBar_Select_All">
+ <menu_item_call.on_click
+ function="NearbyChatBar.Action"
+ parameter="select_all" />
+ <menu_item_call.on_enable
+ function="NearbyChatBar.EnableMenuItem"
+ parameter="can_select_all" />
+ </menu_item_call>
+
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_favorites.xml b/indra/newview/skins/default/xui/en/menu_favorites.xml
new file mode 100644
index 0000000000..be380e11e5
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_favorites.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ bottom="825"
+ layout="topleft"
+ name="Popup"
+ visible="false">
+ <menu_item_call
+ label="Teleport"
+ layout="topleft"
+ name="Teleport To Landmark">
+ <menu_item_call.on_click
+ function="Favorites.DoToSelected"
+ parameter="open" />
+ </menu_item_call>
+ <menu_item_call
+ label="View/Edit Landmark"
+ layout="topleft"
+ name="Landmark Open">
+ <menu_item_call.on_click
+ function="Favorites.DoToSelected"
+ parameter="about" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy SLurl"
+ layout="topleft"
+ name="Copy slurl">
+ <menu_item_call.on_click
+ function="Favorites.DoToSelected"
+ parameter="copy_slurl" />
+ </menu_item_call>
+ <menu_item_call
+ label="Show on Map"
+ layout="topleft"
+ name="Show On Map">
+ <menu_item_call.on_click
+ function="Favorites.DoToSelected"
+ parameter="show_on_map" />
+ </menu_item_call>
+
+ <menu_item_separator
+ layout="topleft" />
+
+ <menu_item_call
+ label="Copy"
+ layout="topleft"
+ name="Landmark Copy">
+ <menu_item_call.on_click
+ function="Favorites.DoToSelected"
+ parameter="copy" />
+ </menu_item_call>
+ <menu_item_call
+ label="Paste"
+ layout="topleft"
+ name="Landmark Paste">
+ <menu_item_call.on_click
+ function="Favorites.DoToSelected"
+ parameter="paste" />
+ <menu_item_call.on_enable
+ function="Favorites.EnableSelected"
+ parameter="can_paste" />
+ </menu_item_call>
+
+ <menu_item_separator
+ layout="topleft" />
+
+ <menu_item_call
+ label="Delete"
+ layout="topleft"
+ name="Delete">
+ <menu_item_call.on_click
+ function="Favorites.DoToSelected"
+ parameter="delete" />
+ </menu_item_call>
+</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
new file mode 100644
index 0000000000..d96f3c5494
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_gesture_gear.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ layout="topleft"
+ mouse_opaque="false"
+ name="menu_gesture_gear"
+ visible="false">
+ <menu_item_call
+ font="SansSerifBold"
+ label="Add/Remove from Favorites"
+ layout="topleft"
+ name="activate">
+ <on_click
+ function="Gesture.Action.ToogleActiveState" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy"
+ layout="topleft"
+ name="copy_gesture">
+ <on_click
+ function="Gesture.Action.CopyPaste"
+ parameter="copy_gesture" />
+ <on_enable
+ function="Gesture.EnableAction"
+ parameter="copy_gesture" />
+ </menu_item_call>
+ <menu_item_call
+ label="Paste"
+ layout="topleft"
+ name="paste">
+ <on_click
+ function="Gesture.Action.CopyPaste"
+ parameter="paste" />
+ <on_enable
+ function="Gesture.EnableAction"
+ parameter="paste" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy UUID"
+ layout="topleft"
+ name="copy_uuid">
+ <on_click
+ function="Gesture.Action.CopyPaste"
+ parameter="copy_uuid" />
+ <on_enable
+ function="Gesture.EnableAction"
+ parameter="copy_uuid" />
+ </menu_item_call>
+ <menu_item_call
+ label="Save to current outfit"
+ layout="topleft"
+ name="save_to_outfit">
+ <on_click
+ function="Gesture.Action.SaveToCOF" />
+ </menu_item_call>
+ <menu_item_call
+ label="Edit"
+ layout="topleft"
+ name="edit_gesture">
+ <on_click
+ function="Gesture.Action.ShowPreview" />
+ <on_enable
+ function="Gesture.EnableAction"
+ parameter="edit_gesture" />
+ </menu_item_call>
+ <menu_item_call
+ label="Inspect"
+ layout="topleft"
+ name="inspect">
+ <on_click
+ function="Gesture.Action.ShowPreview" />
+ <on_enable
+ function="Gesture.EnableAction"
+ parameter="inspect" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_group_plus.xml b/indra/newview/skins/default/xui/en/menu_group_plus.xml
new file mode 100644
index 0000000000..e83d07baec
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_group_plus.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu name="menu_group_plus"
+ left="0" bottom="0" visible="false"
+ mouse_opaque="false" opaque="true" color="MenuDefaultBgColor" drop_shadow="false">
+ <menu_item_call name="item_join" label="Join Group...">
+ <menu_item_call.on_click function="People.Group.Plus.Action" userdata="join_group" />
+ </menu_item_call>
+ <menu_item_call name="item_new" label="New Group...">
+ <menu_item_call.on_click function="People.Group.Plus.Action" userdata="new_group" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_hide_navbar.xml b/indra/newview/skins/default/xui/en/menu_hide_navbar.xml
new file mode 100644
index 0000000000..a175b3103f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_hide_navbar.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ height="201"
+ layout="topleft"
+ left="100"
+ mouse_opaque="false"
+ name="hide_navbar_menu"
+ top="624"
+ visible="false"
+ width="128">
+ <menu_item_check
+ label="Show Navigation Bar"
+ layout="topleft"
+ name="ShowNavbarNavigationPanel">
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowNavbarNavigationPanel" />
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="ShowNavbarNavigationPanel" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Favorites Bar"
+ layout="topleft"
+ name="ShowNavbarFavoritesPanel">
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowNavbarFavoritesPanel" />
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="ShowNavbarFavoritesPanel" />
+ </menu_item_check>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_im_well_button.xml b/indra/newview/skins/default/xui/en/menu_im_well_button.xml
new file mode 100644
index 0000000000..f8dfba91ff
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_im_well_button.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="IM Well Button Context Menu">
+ <menu_item_call
+ label="Close All"
+ layout="topleft"
+ name="Close All">
+ <menu_item_call.on_click
+ function="IMWellChicletMenu.Action"
+ parameter="close all" />
+ <menu_item_call.on_enable
+ function="IMWellChicletMenu.EnableItem"
+ parameter="can close all" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_imchiclet_adhoc.xml b/indra/newview/skins/default/xui/en/menu_imchiclet_adhoc.xml
new file mode 100644
index 0000000000..eb5e31b57d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_imchiclet_adhoc.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ height="101"
+ layout="topleft"
+ left="100"
+ mouse_opaque="false"
+ name="IMChiclet AdHoc Menu"
+ top="724"
+ visible="false"
+ width="128">
+ <menu_item_call
+ label="End Session"
+ layout="topleft"
+ name="End Session">
+ <menu_item_call.on_click
+ function="IMChicletMenu.Action"
+ parameter="end" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_imchiclet_group.xml b/indra/newview/skins/default/xui/en/menu_imchiclet_group.xml
new file mode 100644
index 0000000000..8cbe62cfb0
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_imchiclet_group.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ height="101"
+ layout="topleft"
+ left="100"
+ mouse_opaque="false"
+ name="IMChiclet Group Menu"
+ top="724"
+ visible="false"
+ width="128">
+ <menu_item_call
+ label="Group Info"
+ layout="topleft"
+ name="Show Profile">
+ <menu_item_call.on_click
+ function="IMChicletMenu.Action"
+ parameter="info" />
+ </menu_item_call>
+ <menu_item_call
+ label="Show Session"
+ layout="topleft"
+ name="Chat">
+ <menu_item_call.on_click
+ function="IMChicletMenu.Action"
+ parameter="group chat" />
+ </menu_item_call>
+ <menu_item_call
+ label="End Session"
+ layout="topleft"
+ name="End Session">
+ <menu_item_call.on_click
+ function="IMChicletMenu.Action"
+ parameter="end" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_imchiclet_p2p.xml b/indra/newview/skins/default/xui/en/menu_imchiclet_p2p.xml
new file mode 100644
index 0000000000..038b8328cb
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_imchiclet_p2p.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ height="101"
+ layout="topleft"
+ left="100"
+ mouse_opaque="false"
+ name="IMChiclet P2P Menu"
+ top="724"
+ visible="false"
+ width="128">
+ <menu_item_call
+ label="View Profile"
+ layout="topleft"
+ name="Show Profile">
+ <menu_item_call.on_click
+ function="IMChicletMenu.Action"
+ parameter="profile" />
+ </menu_item_call>
+ <menu_item_call
+ label="Add Friend"
+ layout="topleft"
+ name="Add Friend">
+ <menu_item_call.on_click
+ function="IMChicletMenu.Action"
+ parameter="add" />
+ </menu_item_call>
+ <menu_item_call
+ label="Show Session"
+ layout="topleft"
+ name="Send IM">
+ <menu_item_call.on_click
+ function="IMChicletMenu.Action"
+ parameter="im" />
+ </menu_item_call>
+ <menu_item_call
+ label="End Session"
+ layout="topleft"
+ name="End Session">
+ <menu_item_call.on_click
+ function="IMChicletMenu.Action"
+ parameter="end" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml
new file mode 100644
index 0000000000..dde92f23b6
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu
+ create_jump_keys="true"
+ layout="topleft"
+ mouse_opaque="false"
+ visible="false"
+ name="Gear Menu">
+ <menu_item_call
+ label="View Profile"
+ enabled="true"
+ name="view_profile">
+ <menu_item_call.on_click
+ function="InspectAvatar.ViewProfile"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Add Friend"
+ name="add_friend">
+ <menu_item_call.on_click
+ function="InspectAvatar.AddFriend"/>
+ <menu_item_call.on_enable
+ function="InspectAvatar.Gear.Enable"/>
+ </menu_item_call>
+ <menu_item_call
+ label="IM"
+ name="im">
+ <menu_item_call.on_click
+ function="InspectAvatar.IM"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Call"
+ enabled="true"
+ name="call">
+ <menu_item_call.on_click
+ function="InspectAvatar.Call"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Teleport"
+ name="teleport">
+ <menu_item_call.on_click
+ function="InspectAvatar.Teleport"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Invite to Group"
+ name="invite_to_group">
+ <menu_item_call.on_click
+ function="InspectAvatar.InviteToGroup"/>
+ </menu_item_call>
+ <menu_item_separator />
+ <menu_item_call
+ label="Block"
+ name="block">
+ <menu_item_call.on_click
+ function="InspectAvatar.ToggleMute"/>
+ <menu_item_call.on_visible
+ function="InspectAvatar.EnableMute" />
+ </menu_item_call>
+ <menu_item_call
+ label="Unblock"
+ name="unblock">
+ <menu_item_call.on_click
+ function="InspectAvatar.ToggleMute"/>
+ <menu_item_call.on_visible
+ function="InspectAvatar.EnableUnmute" />
+ </menu_item_call>
+ <menu_item_call
+ label="Report"
+ name="report">
+ <menu_item_call.on_click
+ function="InspectAvatar.Report"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Freeze"
+ name="freeze">
+ <menu_item_call.on_click
+ function="InspectAvatar.Freeze"/>
+ <menu_item_call.on_visible
+ function="InspectAvatar.VisibleFreezeEject"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Eject"
+ name="eject">
+ <menu_item_call.on_click
+ function="InspectAvatar.Eject"/>
+ <menu_item_call.on_visible
+ function="InspectAvatar.VisibleFreezeEject"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Debug"
+ name="debug">
+ <menu_item_call.on_click
+ function="Avatar.Debug"/>
+ <menu_item_call.on_visible
+ function="IsGodCustomerService"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Find On Map"
+ name="find_on_map">
+ <menu_item_call.on_click
+ function="InspectAvatar.FindOnMap"/>
+ <menu_item_call.on_visible
+ function="InspectAvatar.VisibleFindOnMap"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Zoom In"
+ name="zoom_in">
+ <menu_item_call.on_click
+ function="InspectAvatar.ZoomIn"/>
+ <menu_item_call.on_visible
+ function="InspectAvatar.VisibleZoomIn"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Pay"
+ name="pay">
+ <menu_item_call.on_click
+ function="InspectAvatar.Pay"/>
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml
new file mode 100644
index 0000000000..22df02cd7e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu
+ create_jump_keys="true"
+ layout="topleft"
+ mouse_opaque="false"
+ visible="false"
+ name="Gear Menu">
+ <menu_item_call
+ label="Touch"
+ layout="topleft"
+ enabled="true"
+ name="touch">
+ <menu_item_call.on_click
+ function="InspectObject.Touch"/>
+ <menu_item_call.on_visible
+ function="Object.EnableTouch" />
+ </menu_item_call>
+ <menu_item_call
+ label="Sit"
+ layout="topleft"
+ name="sit">
+ <menu_item_call.on_click
+ function="InspectObject.Sit"/>
+ <menu_item_call.on_visible
+ function="Object.EnableSit" />
+ </menu_item_call>
+ <menu_item_call
+ label="Pay"
+ layout="topleft"
+ name="pay">
+ <menu_item_call.on_click
+ function="InspectObject.Pay"/>
+ <menu_item_call.on_visible
+ function="EnablePayObject" />
+ </menu_item_call>
+ <menu_item_call
+ label="Buy"
+ layout="topleft"
+ enabled="true"
+ name="buy">
+ <menu_item_call.on_click
+ function="InspectObject.Buy"/>
+ <menu_item_call.on_visible
+ function="Object.VisibleBuy" />
+ </menu_item_call>
+ <menu_item_call
+ label="Take"
+ layout="topleft"
+ name="take">
+ <menu_item_call.on_click
+ function="Object.Take" />
+ <menu_item_call.on_enable
+ function="Object.VisibleTake"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Take Copy"
+ layout="topleft"
+ name="take_copy">
+ <menu_item_call.on_click
+ function="InspectObject.TakeFreeCopy"/>
+ <menu_item_call.on_visible
+ function="Tools.EnableTakeCopy"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Open"
+ layout="topleft"
+ name="open">
+ <menu_item_call.on_click
+ function="InspectObject.Open"/>
+ <menu_item_call.on_visible
+ function="Object.EnableOpen" />
+ </menu_item_call>
+ <menu_item_call
+ label="Edit"
+ layout="topleft"
+ name="edit">
+ <menu_item_call.on_click
+ function="Object.Edit" />
+ <menu_item_call.on_enable
+ function="EnableEdit"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Wear"
+ layout="topleft"
+ name="wear">
+ <menu_item_call.on_click
+ function="Object.AttachToAvatar" />
+ <menu_item_call.on_visible
+ function="Object.EnableWear" />
+ </menu_item_call>
+ <menu_item_call
+ label="Report"
+ layout="topleft"
+ name="report">
+ <menu_item_call.on_click
+ function="Object.ReportAbuse" />
+ </menu_item_call>
+ <menu_item_call
+ label="Block"
+ layout="topleft"
+ name="block">
+ <menu_item_call.on_click
+ function="Object.Mute" />
+ <menu_item_call.on_visible
+ function="Object.EnableMute" />
+ </menu_item_call>
+ <menu_item_call
+ label="Zoom In"
+ layout="topleft"
+ name="zoom_in">
+ <menu_item_call.on_click
+ function="InspectObject.ZoomIn" />
+ </menu_item_call>
+ <menu_item_call
+ label="Remove"
+ layout="topleft"
+ name="remove">
+ <menu_item_call.on_click
+ function="Object.Delete" />
+ <menu_item_call.on_visible
+ function="Object.EnableDelete" />
+ </menu_item_call>
+ <menu_item_call
+ label="More Info"
+ layout="topleft"
+ name="more_info">
+ <menu_item_call.on_click
+ function="InspectObject.MoreInfo"/>
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml
new file mode 100644
index 0000000000..9dc2611663
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu
+ create_jump_keys="true"
+ layout="topleft"
+ mouse_opaque="false"
+ visible="false"
+ name="Gear Menu">
+ <menu_item_call
+ label="Stand Up"
+ enabled="true"
+ name="stand_up">
+ <menu_item_call.on_click
+ function="Self.StandUp"
+ parameter="" />
+ <menu_item_call.on_visible
+ function="Self.EnableStandUp" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Appearance"
+ name="my_appearance">
+ <menu_item_call.on_click
+ function="CustomizeAvatar" />
+ <menu_item_call.on_enable
+ function="Edit.EnableCustomizeAvatar" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Profile"
+ enabled="true"
+ name="my_profile">
+ <menu_item_call.on_click
+ function="ShowAgentProfile"
+ parameter="agent" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Friends"
+ name="my_friends">
+ <menu_item_call.on_click
+ function="SideTray.PanelPeopleTab"
+ parameter="friends_panel" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Groups"
+ name="my_groups">
+ <menu_item_call.on_click
+ function="SideTray.PanelPeopleTab"
+ parameter="groups_panel" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
new file mode 100644
index 0000000000..1e10467148
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -0,0 +1,662 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ bottom="825"
+ layout="topleft"
+ name="Popup"
+ visible="false">
+ <menu_item_call
+ label="Buy"
+ layout="topleft"
+ name="Task Buy">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="task_buy" />
+ </menu_item_call>
+ <menu_item_call
+ label="Open"
+ layout="topleft"
+ name="Task Open">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="task_open" />
+ </menu_item_call>
+ <menu_item_call
+ label="Play"
+ layout="topleft"
+ name="Task Play">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="task_play" />
+ </menu_item_call>
+ <menu_item_call
+ label="Properties"
+ layout="topleft"
+ name="Task Properties">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="task_properties" />
+ </menu_item_call>
+ <menu_item_call
+ label="Rename"
+ layout="topleft"
+ name="Task Rename">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="rename" />
+ </menu_item_call>
+ <menu_item_call
+ label="Delete"
+ layout="topleft"
+ name="Task Remove">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="delete" />
+ </menu_item_call>
+ <menu_item_call
+ label="Empty Trash"
+ layout="topleft"
+ name="Empty Trash">
+ <menu_item_call.on_click
+ function="Inventory.EmptyTrash"
+ parameter="rename" />
+ </menu_item_call>
+ <menu_item_call
+ label="Empty Lost And Found"
+ layout="topleft"
+ name="Empty Lost And Found">
+ <menu_item_call.on_click
+ function="Inventory.EmptyLostAndFound"
+ parameter="rename" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Folder"
+ layout="topleft"
+ name="New Folder">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="category" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Script"
+ layout="topleft"
+ name="New Script">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="lsl" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Notecard"
+ layout="topleft"
+ name="New Note">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="notecard" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Gesture"
+ layout="topleft"
+ name="New Gesture">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="gesture" />
+ </menu_item_call>
+ <menu
+ label="New Clothes"
+ layout="topleft"
+ name="New Clothes">
+ <menu_item_call
+ label="New Shirt"
+ layout="topleft"
+ name="New Shirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Pants"
+ layout="topleft"
+ name="New Pants">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="pants" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Shoes"
+ layout="topleft"
+ name="New Shoes">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shoes" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Socks"
+ layout="topleft"
+ name="New Socks">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="socks" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Jacket"
+ layout="topleft"
+ name="New Jacket">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="jacket" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Skirt"
+ layout="topleft"
+ name="New Skirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="skirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Gloves"
+ layout="topleft"
+ name="New Gloves">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="gloves" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Undershirt"
+ layout="topleft"
+ name="New Undershirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="undershirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Underpants"
+ layout="topleft"
+ name="New Underpants">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="underpants" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Alpha Mask"
+ layout="topleft"
+ name="New Alpha Mask">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="alpha" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Tattoo"
+ layout="topleft"
+ name="New Tattoo">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="tattoo" />
+ </menu_item_call>
+ </menu>
+ <menu
+ label="New Body Parts"
+ layout="topleft"
+ name="New Body Parts">
+ <menu_item_call
+ label="New Shape"
+ layout="topleft"
+ name="New Shape">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shape" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Skin"
+ layout="topleft"
+ name="New Skin">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="skin" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Hair"
+ layout="topleft"
+ name="New Hair">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="hair" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Eyes"
+ layout="topleft"
+ name="New Eyes">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="eyes" />
+ </menu_item_call>
+ </menu>
+ <menu
+ label="Change Type"
+ layout="topleft"
+ name="Change Type">
+ <menu_item_call
+ label="Default"
+ layout="topleft"
+ name="Default">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="change_folder_type_default" />
+ </menu_item_call>
+ <menu_item_call
+ label="Gloves"
+ layout="topleft"
+ name="Gloves">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="change_folder_type_gloves" />
+ </menu_item_call>
+ <menu_item_call
+ label="Jacket"
+ layout="topleft"
+ name="Jacket">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="change_folder_type_jacket" />
+ </menu_item_call>
+ <menu_item_call
+ label="Pants"
+ layout="topleft"
+ name="Pants">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="change_folder_type_pants" />
+ </menu_item_call>
+ <menu_item_call
+ label="Shape"
+ layout="topleft"
+ name="Shape">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="change_folder_type_shape" />
+ </menu_item_call>
+ <menu_item_call
+ label="Shoes"
+ layout="topleft"
+ name="Shoes">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="change_folder_type_shoes" />
+ </menu_item_call>
+ <menu_item_call
+ label="Shirt"
+ layout="topleft"
+ name="Shirt">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="change_folder_type_shirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="Skirt"
+ layout="topleft"
+ name="Skirt">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="change_folder_type_skirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="Underpants"
+ layout="topleft"
+ name="Underpants">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="change_folder_type_underpants" />
+ </menu_item_call>
+ <menu_item_call
+ label="Undershirt"
+ layout="topleft"
+ name="Undershirt">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="change_folder_type_undershirt" />
+ </menu_item_call>
+ </menu>
+ <menu_item_call
+ label="Teleport"
+ layout="topleft"
+ name="Landmark Open">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="open" />
+ </menu_item_call>
+ <menu_item_call
+ label="Open"
+ layout="topleft"
+ name="Animation Open">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="open" />
+ </menu_item_call>
+ <menu_item_call
+ label="Open"
+ layout="topleft"
+ name="Sound Open">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="open" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"
+ name="Folder Wearables Separator" />
+ <menu_item_call
+ label="Replace Current Outfit"
+ layout="topleft"
+ name="Replace Outfit">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="replaceoutfit" />
+ </menu_item_call>
+ <menu_item_call
+ label="Add To Current Outfit"
+ layout="topleft"
+ name="Add To Outfit">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="addtooutfit" />
+ </menu_item_call>
+ <menu_item_call
+ label="Remove From Current Outfit"
+ layout="topleft"
+ name="Remove From Outfit">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="removefromoutfit" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"
+ name="Outfit Separator" />
+ <menu_item_call
+ label="Purge Item"
+ layout="topleft"
+ name="Purge Item">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="purge" />
+ </menu_item_call>
+ <menu_item_call
+ label="Restore Item"
+ layout="topleft"
+ name="Restore Item">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="restore" />
+ </menu_item_call>
+ <menu_item_call
+ label="Find Original"
+ layout="topleft"
+ name="Find Original">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="goto" />
+ </menu_item_call>
+ <menu_item_call
+ label="Open"
+ layout="topleft"
+ name="Open">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="open" />
+ </menu_item_call>
+ <menu_item_call
+ label="Properties"
+ layout="topleft"
+ name="Properties">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="properties" />
+ </menu_item_call>
+ <menu_item_call
+ label="Rename"
+ layout="topleft"
+ name="Rename">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="rename" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy Asset UUID"
+ layout="topleft"
+ name="Copy Asset UUID">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="copy_uuid" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"
+ name="Copy Separator" />
+ <menu_item_call
+ label="Copy"
+ layout="topleft"
+ name="Copy">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="copy" />
+ </menu_item_call>
+ <menu_item_call
+ label="Paste"
+ layout="topleft"
+ name="Paste">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="paste" />
+ </menu_item_call>
+ <menu_item_call
+ label="Paste As Link"
+ layout="topleft"
+ name="Paste As Link">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="paste_link" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"
+ name="Paste Separator" />
+ <menu_item_call
+ label="Remove Link"
+ layout="topleft"
+ name="Remove Link">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="delete" />
+ </menu_item_call>
+ <menu_item_call
+ label="Delete"
+ layout="topleft"
+ name="Delete">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="delete" />
+ </menu_item_call>
+ <menu_item_call
+ label="Delete System Folder"
+ layout="topleft"
+ name="Delete System Folder">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="delete_system_folder" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Start Conference Chat"
+ layout="topleft"
+ name="Conference Chat Folder">
+ <menu_item_call.on_click
+ function="Inventory.BeginIMSession"
+ parameter="everyone" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Play"
+ layout="topleft"
+ name="Sound Play">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="open" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"
+ name="Landmark Separator" />
+ <menu_item_call
+ label="About Landmark"
+ layout="topleft"
+ name="About Landmark">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="about" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"
+ name="Animation Separator" />
+ <menu_item_call
+ label="Play in World"
+ layout="topleft"
+ name="Animation Play">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="playworld" />
+ </menu_item_call>
+ <menu_item_call
+ label="Play Locally"
+ layout="topleft"
+ name="Animation Audition">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="playlocal" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"
+ name="Send Instant Message Separator" />
+ <menu_item_call
+ label="Send Instant Message"
+ layout="topleft"
+ name="Send Instant Message">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="begin_im" />
+ </menu_item_call>
+ <menu_item_call
+ label="Offer Teleport..."
+ layout="topleft"
+ name="Offer Teleport...">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="lure" />
+ </menu_item_call>
+ <menu_item_call
+ label="Start Conference Chat"
+ layout="topleft"
+ name="Conference Chat">
+ <menu_item_call.on_click
+ function="Inventory.BeginIMSession"
+ parameter="selected" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"
+ name="Gesture Separator" />
+ <menu_item_call
+ label="Activate"
+ layout="topleft"
+ name="Activate">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="activate" />
+ </menu_item_call>
+ <menu_item_call
+ label="Deactivate"
+ layout="topleft"
+ name="Deactivate">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="deactivate" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"
+ name="Texture Separator" />
+ <menu_item_call
+ label="Save As"
+ layout="topleft"
+ name="Save As">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="save_as" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"
+ name="Attach Separator"/>
+ <menu_item_call
+ label="Detach From Yourself"
+ layout="topleft"
+ name="Detach From Yourself">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="detach" />
+ </menu_item_call>
+ <!-- COMMENTED OUT for DEV-32347 -->
+ <!--
+ <menu_item_call
+ label="Restore to Last Position"
+ layout="topleft"
+ name="Restore to Last Position">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="restoreToWorld" />
+ </menu_item_call>
+ -->
+ <menu_item_call
+ label="Wear"
+ layout="topleft"
+ name="Object Wear">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="attach" />
+ </menu_item_call>
+ <menu
+ label="Attach To"
+ layout="topleft"
+ name="Attach To" />
+ <menu
+ label="Attach To HUD"
+ layout="topleft"
+ name="Attach To HUD" />
+ <menu_item_separator
+ layout="topleft"
+ name="Wearable Separator"/>
+ <menu_item_call
+ label="Edit"
+ layout="topleft"
+ name="Wearable Edit">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="edit" />
+ </menu_item_call>
+ <menu_item_call
+ label="Wear"
+ layout="topleft"
+ name="Wearable Wear">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="wear" />
+ </menu_item_call>
+ <menu_item_call
+ label="Take Off"
+ layout="topleft"
+ name="Take Off">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="take_off" />
+ </menu_item_call>
+ <menu_item_call
+ label="--no options--"
+ layout="topleft"
+ name="--no options--" />
+ <menu_item_separator
+ layout="topleft" />
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_inventory_add.xml b/indra/newview/skins/default/xui/en/menu_inventory_add.xml
new file mode 100644
index 0000000000..5ad099e2d9
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_inventory_add.xml
@@ -0,0 +1,229 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="menu_inventory_add"
+ visible="false">
+ <menu
+ create_jump_keys="true"
+ label="Upload"
+ layout="topleft"
+ name="upload"
+ tear_off="true">
+ <menu_item_call
+ label="Image (L$[COST])..."
+ layout="topleft"
+ name="Upload Image"
+ shortcut="control|U">
+ <menu_item_call.on_click
+ function="File.UploadImage"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="File.EnableUpload" />
+ </menu_item_call>
+ <menu_item_call
+ label="Sound (L$[COST])..."
+ layout="topleft"
+ name="Upload Sound">
+ <menu_item_call.on_click
+ function="File.UploadSound"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="File.EnableUpload" />
+ </menu_item_call>
+ <menu_item_call
+ label="Animation (L$[COST])..."
+ layout="topleft"
+ name="Upload Animation">
+ <menu_item_call.on_click
+ function="File.UploadAnim"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="File.EnableUpload" />
+ </menu_item_call>
+ <menu_item_call
+ label="Bulk (L$[COST] per file)..."
+ layout="topleft"
+ name="Bulk Upload">
+ <menu_item_call.on_click
+ function="File.UploadBulk"
+ parameter="" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ </menu>
+
+ <menu_item_call
+ label="New Folder"
+ layout="topleft"
+ name="New Folder">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="category" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Script"
+ layout="topleft"
+ name="New Script">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="lsl" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Notecard"
+ layout="topleft"
+ name="New Note">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="notecard" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Gesture"
+ layout="topleft"
+ name="New Gesture">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="gesture" />
+ </menu_item_call>
+ <menu
+ height="175"
+ label="New Clothes"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="New Clothes"
+ top_pad="514"
+ width="125">
+ <menu_item_call
+ label="New Shirt"
+ layout="topleft"
+ name="New Shirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Pants"
+ layout="topleft"
+ name="New Pants">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="pants" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Shoes"
+ layout="topleft"
+ name="New Shoes">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shoes" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Socks"
+ layout="topleft"
+ name="New Socks">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="socks" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Jacket"
+ layout="topleft"
+ name="New Jacket">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="jacket" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Skirt"
+ layout="topleft"
+ name="New Skirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="skirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Gloves"
+ layout="topleft"
+ name="New Gloves">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="gloves" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Undershirt"
+ layout="topleft"
+ name="New Undershirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="undershirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Underpants"
+ layout="topleft"
+ name="New Underpants">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="underpants" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Alpha"
+ layout="topleft"
+ name="New Alpha">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="alpha" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Tattoo"
+ layout="topleft"
+ name="New Tattoo">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="tattoo" />
+ </menu_item_call>
+ </menu>
+ <menu
+ height="85"
+ label="New Body Parts"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="New Body Parts"
+ top_pad="514"
+ width="118">
+ <menu_item_call
+ label="New Shape"
+ layout="topleft"
+ name="New Shape">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shape" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Skin"
+ layout="topleft"
+ name="New Skin">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="skin" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Hair"
+ layout="topleft"
+ name="New Hair">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="hair" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Eyes"
+ layout="topleft"
+ name="New Eyes">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="eyes" />
+ </menu_item_call>
+ </menu>
+</menu> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml
new file mode 100644
index 0000000000..4e6a07d020
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ bottom="806"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="menu_gear_default"
+ visible="false">
+ <menu_item_call
+ label="New Inventory Window"
+ layout="topleft"
+ name="new_window">
+ <on_click
+ function="Inventory.GearDefault.Custom.Action"
+ parameter="new_window" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Sort by Name"
+ layout="topleft"
+ name="sort_by_name">
+ <on_click
+ function="Inventory.GearDefault.Custom.Action"
+ parameter="sort_by_name" />
+ </menu_item_call>
+ <menu_item_call
+ label="Sort by Most Recent"
+ layout="topleft"
+ name="sort_by_recent">
+ <on_click
+ function="Inventory.GearDefault.Custom.Action"
+ parameter="sort_by_recent" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Show Filters"
+ layout="topleft"
+ name="show_filters">
+ <on_click
+ function="Inventory.GearDefault.Custom.Action"
+ parameter="show_filters" />
+ </menu_item_call>
+ <menu_item_call
+ label="Reset Filters"
+ layout="topleft"
+ name="reset_filters">
+ <on_click
+ function="Inventory.GearDefault.Custom.Action"
+ parameter="reset_filters" />
+ </menu_item_call>
+ <menu_item_call
+ label="Close All Folders"
+ layout="topleft"
+ name="close_folders">
+ <on_click
+ function="Inventory.GearDefault.Custom.Action"
+ parameter="close_folders" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Empty Trash"
+ layout="topleft"
+ name="empty_trash">
+ <on_click
+ function="Inventory.GearDefault.Custom.Action"
+ parameter="empty_trash" />
+ </menu_item_call>
+ <menu_item_call
+ label="Empty Lost and Found"
+ layout="topleft"
+ name="empty_lostnfound">
+ <on_click
+ function="Inventory.GearDefault.Custom.Action"
+ parameter="empty_lostnfound" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Save Texture As"
+ layout="topleft"
+ name="Save Texture As">
+ <on_click
+ function="Inventory.GearDefault.Custom.Action"
+ parameter="save_texture" />
+ <on_enable
+ function="Inventory.GearDefault.Enable"
+ parameter="save_texture" />
+ </menu_item_call>
+ <menu_item_call
+ label="Find Original"
+ layout="topleft"
+ name="Find Original">
+ <on_click
+ function="Inventory.GearDefault.Custom.Action"
+ parameter="find_original" />
+ <on_enable
+ function="Inventory.GearDefault.Enable"
+ parameter="find_original" />
+ </menu_item_call>
+ <menu_item_call
+ label="Find All Links"
+ layout="topleft"
+ name="Find All Links">
+ <on_click
+ function="Inventory.GearDefault.Custom.Action"
+ parameter="find_links" />
+ <on_enable
+ function="Inventory.GearDefault.Enable"
+ parameter="find_links" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_land.xml b/indra/newview/skins/default/xui/en/menu_land.xml
new file mode 100644
index 0000000000..cc6d8ad9c1
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_land.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Land Pie">
+ <menu_item_call
+ label="About Land"
+ name="Place Information...">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="about_land" />
+ </menu_item_call>
+ <!-- <menu_item_call
+ label="Go Here"
+ name="Go Here">
+ <menu_item_call.on_click
+ function="GoToObject" />
+ </menu_item_call>-->
+ <menu_item_call
+ label="Sit Here"
+ name="Sit Here">
+ <menu_item_call.on_click
+ function="Land.Sit" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ enabled="false"
+ label="Buy This Land"
+ name="Land Buy">
+ <menu_item_call.on_click
+ function="Land.Buy" />
+ <menu_item_call.on_enable
+ function="World.EnableBuyLand" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Buy Pass"
+ name="Land Buy Pass">
+ <menu_item_call.on_click
+ function="Land.BuyPass" />
+ <menu_item_call.on_enable
+ function="Land.EnableBuyPass" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ enabled="false"
+ label="Build"
+ name="Create">
+ <menu_item_call.on_click
+ function="Land.Build" />
+ <menu_item_call.on_enable
+ function="EnableEdit" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Edit Terrain"
+ name="Edit Terrain">
+ <menu_item_call.on_click
+ function="Land.Edit" />
+ <menu_item_call.on_enable
+ function="EnableEdit" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_landmark.xml b/indra/newview/skins/default/xui/en/menu_landmark.xml
new file mode 100644
index 0000000000..93b6db222a
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_landmark.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu
+ height="201"
+ layout="topleft"
+ mouse_opaque="false"
+ name="landmark_overflow_menu"
+ width="128">
+ <menu_item_call
+ label="Copy SLurl"
+ layout="topleft"
+ name="copy">
+ <menu_item_call.on_click
+ function="Places.OverflowMenu.Action"
+ parameter="copy" />
+ </menu_item_call>
+ <menu_item_call
+ label="Delete"
+ layout="topleft"
+ name="delete">
+ <menu_item_call.on_click
+ function="Places.OverflowMenu.Action"
+ parameter="delete" />
+ </menu_item_call>
+ <menu_item_call
+ label="Create Pick"
+ layout="topleft"
+ name="pick">
+ <menu_item_call.on_click
+ function="Places.OverflowMenu.Action"
+ parameter="pick" />
+ <menu_item_call.on_enable
+ function="Places.OverflowMenu.Enable"
+ parameter="can_create_pick" />
+ </menu_item_call>
+ <menu_item_call
+ label="Add to Favorites Bar"
+ layout="topleft"
+ name="add_to_favbar">
+ <menu_item_call.on_click
+ function="Places.OverflowMenu.Action"
+ parameter="add_to_favbar" />
+ </menu_item_call>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml
new file mode 100644
index 0000000000..a0dec346a4
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_login.xml
@@ -0,0 +1,267 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu_bar
+ follows="left|top|right"
+ height="18"
+ layout="topleft"
+ left_delta="0"
+ name="Login Menu"
+ top_delta="0"
+ width="802">
+ <menu
+ create_jump_keys="true"
+ label="Me"
+ name="File">
+ <menu_item_call
+ label="Preferences"
+ name="Preferences..."
+ shortcut="control|P">
+ <menu_item_call.on_click
+ function="Floater.Toggle"
+ parameter="preferences" />
+ </menu_item_call>
+ <menu_item_separator />
+ <menu_item_call
+ label="Quit [APP_NAME]"
+ name="Quit"
+ shortcut="control|Q">
+ <menu_item_call.on_click
+ function="File.Quit" />
+ </menu_item_call>
+ </menu>
+<!-- Edit menu merged into the Me menu above
+ <menu
+ create_jump_keys="true"
+ label="Edit"
+ name="Edit"
+ width="153">
+ </menu>
+-->
+ <menu
+ create_jump_keys="true"
+ label="Help"
+ name="Help">
+ <menu_item_call
+ label="[SECOND_LIFE] Help"
+ name="Second Life Help"
+ shortcut="F1">
+ <menu_item_call.on_click
+ function="ShowHelp"
+ parameter="f1_help" />
+ </menu_item_call>
+ <menu_item_separator />
+ <menu_item_call
+ label="About [APP_NAME]"
+ name="About Second Life">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="sl_about" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Debug"
+ name="Debug"
+ tear_off="true">
+ <!-- Need a copy of the edit menu here so keyboard shortcuts like
+ control-C work to copy text at login screen and About dialog (for QA)
+ -->
+ <menu
+ create_jump_keys="true"
+ label="Edit"
+ name="Edit"
+ tear_off="true">
+ <menu_item_call
+ label="Undo"
+ name="Undo"
+ shortcut="control|Z">
+ <menu_item_call.on_click
+ function="Edit.Undo" />
+ <menu_item_call.on_enable
+ function="Edit.EnableUndo" />
+ </menu_item_call>
+ <menu_item_call
+ label="Redo"
+ name="Redo"
+ shortcut="control|Y">
+ <menu_item_call.on_click
+ function="Edit.Redo" />
+ <menu_item_call.on_enable
+ function="Edit.EnableRedo" />
+ </menu_item_call>
+ <menu_item_separator />
+ <menu_item_call
+ label="Cut"
+ name="Cut"
+ shortcut="control|X">
+ <menu_item_call.on_click
+ function="Edit.Cut" />
+ <menu_item_call.on_enable
+ function="Edit.EnableCut" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy"
+ name="Copy"
+ shortcut="control|C">
+ <menu_item_call.on_click
+ function="Edit.Copy" />
+ <menu_item_call.on_enable
+ function="Edit.EnableCopy" />
+ </menu_item_call>
+ <menu_item_call
+ label="Paste"
+ name="Paste"
+ shortcut="control|V">
+ <menu_item_call.on_click
+ function="Edit.Paste" />
+ <menu_item_call.on_enable
+ function="Edit.EnablePaste" />
+ </menu_item_call>
+ <menu_item_call
+ label="Delete"
+ name="Delete"
+ shortcut="Del">
+ <menu_item_call.on_click
+ function="Edit.Delete" />
+ <menu_item_call.on_enable
+ function="Edit.EnableDelete" />
+ </menu_item_call>
+ <menu_item_call
+ label="Duplicate"
+ name="Duplicate"
+ shortcut="control|D">
+ <menu_item_call.on_click
+ function="Edit.Duplicate" />
+ <menu_item_call.on_enable
+ function="Edit.EnableDuplicate" />
+ </menu_item_call>
+ <menu_item_separator />
+ <menu_item_call
+ label="Select All"
+ name="Select All"
+ shortcut="control|A">
+ <menu_item_call.on_click
+ function="Edit.SelectAll" />
+ <menu_item_call.on_enable
+ function="Edit.EnableSelectAll" />
+ </menu_item_call>
+ <menu_item_call
+ label="Deselect"
+ name="Deselect"
+ shortcut="control|E">
+ <menu_item_call.on_click
+ function="Edit.Deselect" />
+ <menu_item_call.on_enable
+ function="Edit.EnableDeselect" />
+ </menu_item_call>
+ </menu>
+ <menu_item_separator />
+ <menu_item_call
+ label="Show Debug Settings"
+ name="Debug Settings">
+ <menu_item_call.on_click
+ function="Advanced.ShowDebugSettings"
+ parameter="all" />
+ </menu_item_call>
+ <menu_item_call
+ label="UI/Color Settings"
+ name="UI/Color Settings">
+ <menu_item_call.on_click
+ function="Advanced.ShowDebugSettings"
+ parameter="skin" />
+ </menu_item_call>
+ <menu_item_separator />
+ <menu_item_call
+ label="XUI Preview Tool"
+ name="UI Preview Tool"
+ shortcut="control|T">
+ <menu_item_call.on_click
+ function="Floater.Toggle"
+ parameter="ui_preview" />
+ </menu_item_call>
+ <menu_item_separator />
+ <!-- Broken
+ <menu_item_call
+ label="Show Side Tray"
+ name="Show Side Tray">
+ <menu_item_call.on_click
+ function="Advanced.ShowSideTray" />
+ </menu_item_call>
+ -->
+ <menu
+ label="UI Tests"
+ name="UI Tests"
+ tear_off="true">
+ <menu_item_call
+ label="Textbox"
+ name="Textbox"
+ shortcut="control|1">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="test_textbox" />
+ </menu_item_call>
+ <menu_item_call
+ label="Text Editor"
+ name="Text Editor"
+ shortcut="control|2">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="test_text_editor" />
+ </menu_item_call>
+ <menu_item_call
+ label="Widgets"
+ name="Widgets"
+ shortcut="control|shift|T">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="test_widgets" />
+ </menu_item_call>
+ <menu_item_call
+ label="Inspectors"
+ name="Inspectors">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="test_inspectors" />
+ </menu_item_call>
+ </menu>
+<!--
+ <menu_item_check
+ label="Reg In Client Test (restart)"
+ name="Reg In Client Test (restart)">
+ <menu_item_check.on_check
+ control="RegInClient" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RegInClient" />
+ </menu_item_check>
+-->
+ <menu_item_separator />
+ <menu_item_call
+ label="Set Window Size..."
+ name="Set Window Size...">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="window_size" />
+ </menu_item_call>
+ <menu_item_call
+ label="Show TOS"
+ name="TOS">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="message_tos" />
+ </menu_item_call>
+ <menu_item_call
+ label="Show Critical Message"
+ name="Critical">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="message_critical" />
+ </menu_item_call>
+ <menu_item_call
+ label="Web Browser Test"
+ name="Web Browser Test">
+ <menu_item_call.on_click
+ function="Advanced.WebBrowserTest"
+ parameter="http://join.secondlife.com/"/>
+ </menu_item_call>
+ </menu>
+</menu_bar>
diff --git a/indra/newview/skins/default/xui/en/menu_mini_map.xml b/indra/newview/skins/default/xui/en/menu_mini_map.xml
new file mode 100644
index 0000000000..f5ea3e735b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_mini_map.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ height="101"
+ layout="topleft"
+ left="100"
+ mouse_opaque="false"
+ name="Popup"
+ top="724"
+ visible="false"
+ width="128">
+ <menu_item_call
+ label="Zoom Close"
+ name="Zoom Close">
+ <menu_item_call.on_click
+ function="Minimap.Zoom"
+ parameter="close" />
+ </menu_item_call>
+ <menu_item_call
+ label="Zoom Medium"
+ name="Zoom Medium">
+ <menu_item_call.on_click
+ function="Minimap.Zoom"
+ parameter="medium" />
+ </menu_item_call>
+ <menu_item_call
+ label="Zoom Far"
+ name="Zoom Far">
+ <menu_item_call.on_click
+ function="Minimap.Zoom"
+ parameter="far" />
+ </menu_item_call>
+ <menu_item_check
+ label="Rotate Map"
+ name="Rotate Map">
+ <menu_item_check.on_check
+ control="MiniMapRotate" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="MiniMapRotate" />
+ </menu_item_check>
+ <menu_item_separator />
+ <menu_item_call
+ 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="World Map"
+ name="World Map">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="world_map" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_navbar.xml b/indra/newview/skins/default/xui/en/menu_navbar.xml
new file mode 100644
index 0000000000..b71b866c4b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_navbar.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ height="201"
+ layout="topleft"
+ left="100"
+ mouse_opaque="false"
+ name="Navbar Menu"
+ top="624"
+ visible="false"
+ width="128">
+ <menu_item_check
+ label="Show Coordinates"
+ name="Show Coordinates">
+ <menu_item_check.on_click
+ function="Navbar.Action"
+ parameter="show_coordinates" />
+ <menu_item_check.on_check
+ function="Navbar.EnableMenuItem"
+ parameter="show_coordinates" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Parcel Properties"
+ name="Show Parcel Properties">
+ <menu_item_check.on_click
+ function="Navbar.Action"
+ parameter="show_properties" />
+ <menu_item_check.on_check
+ control="NavBarShowParcelProperties" />
+ </menu_item_check>
+ <menu_item_separator
+ name="Separator" />
+ <!-- Label of 'Landmark' item is changing in runtime,
+ see AddLandmarkNavBarMenu/EditLandmarkNavBarMenu in strings.xml -->
+ <menu_item_call
+ label="Landmark"
+ name="Landmark">
+ <menu_item_call.on_click
+ function="Navbar.Action"
+ parameter="landmark" />
+ </menu_item_call>
+ <menu_item_separator
+ name="Separator" />
+ <menu_item_call
+ label="Cut"
+ name="Cut">
+ <menu_item_call.on_click
+ function="Navbar.Action"
+ parameter="cut" />
+ <menu_item_call.on_enable
+ function="Navbar.EnableMenuItem"
+ parameter="can_cut" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy"
+ name="Copy">
+ <menu_item_call.on_click
+ function="Navbar.Action"
+ parameter="copy" />
+ <menu_item_call.on_enable
+ function="Navbar.EnableMenuItem"
+ parameter="can_copy" />
+ </menu_item_call>
+ <menu_item_call
+ label="Paste"
+ name="Paste">
+ <menu_item_call.on_click
+ function="Navbar.Action"
+ parameter="paste" />
+ <menu_item_call.on_enable
+ function="Navbar.EnableMenuItem"
+ parameter="can_paste" />
+ </menu_item_call>
+ <menu_item_call
+ label="Delete"
+ name="Delete">
+ <menu_item_call.on_click
+ function="Navbar.Action"
+ parameter="delete" />
+ <menu_item_call.on_enable
+ function="Navbar.EnableMenuItem"
+ parameter="can_delete" />
+ </menu_item_call>
+ <menu_item_call
+ label="Select All"
+ name="Select All">
+ <menu_item_call.on_click
+ function="Navbar.Action"
+ parameter="select_all" />
+ <menu_item_call.on_enable
+ function="Navbar.EnableMenuItem"
+ parameter="can_select_all" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_nearby_chat.xml b/indra/newview/skins/default/xui/en/menu_nearby_chat.xml
new file mode 100644
index 0000000000..ff89e20ea5
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_nearby_chat.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu bottom="100" color="MenuDefaultBgColor" drop_shadow="true" height="101" left="100"
+ mouse_opaque="false" name="NearBy Chat Menu" opaque="true" width="128" visible="false">
+ <menu_item_call bottom_delta="-18" height="18" label="Show Nearby People..." left="0" mouse_opaque="true"
+ name="nearby_people" width="128">
+ <menu_item_call.on_click function="NearbyChat.Action" userdata="nearby_people" />
+ </menu_item_call>
+
+ <menu_item_separator />
+ <menu_item_check bottom_delta="-18" height="18" label="Show Blocked Text" left="0" mouse_opaque="true"
+ name="muted_text" width="128">
+ <menu_item_check.on_click function="NearbyChat.Action" userdata="muted_text" />
+ <menu_item_check.on_check function="NearbyChat.Check" userdata="muted_text"/>
+ </menu_item_check>
+
+ <menu_item_separator />
+
+ <menu_item_check bottom_delta="-18" height="18" label="Show Buddy Icons" left="0" mouse_opaque="true"
+ name="show_buddy_icons" width="128">
+ <menu_item_check.on_click function="NearbyChat.Action" userdata="show_buddy_icons" />
+ <menu_item_check.on_check function="NearbyChat.Check" userdata="show_buddy_icons"/>
+ </menu_item_check>
+ <menu_item_check bottom_delta="-18" height="18" label="Show Names" left="0" mouse_opaque="true"
+ name="show_names" width="128">
+ <menu_item_check.on_click function="NearbyChat.Action" userdata="show_names" />
+ <menu_item_check.on_check function="NearbyChat.Check" userdata="show_names"/>
+ </menu_item_check>
+ <menu_item_check bottom_delta="-18" height="18" label="Show Icons and Names" left="0" mouse_opaque="true"
+ name="show_icons_and_names" width="128">
+ <menu_item_check.on_click function="NearbyChat.Action" userdata="show_icons_and_names" />
+ <menu_item_check.on_check function="NearbyChat.Check" userdata="show_icons_and_names"/>
+ </menu_item_check>
+
+ <menu_item_separator />
+ <menu_item_call bottom_delta="-18" height="18" label="Font Size" left="0" mouse_opaque="true"
+ name="font_size" width="128">
+ <menu_item_call.on_click function="NearbyChat.Action" userdata="font_size" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_notification_well_button.xml b/indra/newview/skins/default/xui/en/menu_notification_well_button.xml
new file mode 100644
index 0000000000..263ac40f4e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_notification_well_button.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Notification Well Button Context Menu">
+ <menu_item_call
+ label="Close All"
+ layout="topleft"
+ name="Close All">
+ <menu_item_call.on_click
+ function="NotificationWellChicletMenu.Action"
+ parameter="close all" />
+ <menu_item_call.on_enable
+ function="NotificationWellChicletMenu.EnableItem"
+ parameter="can close all" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_object.xml b/indra/newview/skins/default/xui/en/menu_object.xml
new file mode 100644
index 0000000000..35518cd13b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_object.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Object Pie">
+ <menu_item_call
+ enabled="false"
+ label="Touch"
+ name="Object Touch">
+ <menu_item_call.on_click
+ function="Object.Touch" />
+ <menu_item_call.on_enable
+ function="Object.EnableTouch"
+ name="EnableTouch"
+ parameter="Touch" />
+ </menu_item_call>
+ <menu_item_call
+ label="Edit"
+ name="Edit...">
+ <menu_item_call.on_click
+ function="Object.Edit" />
+ <menu_item_call.on_visible
+ function="EnableEdit"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Build"
+ name="Build">
+ <menu_item_call.on_click
+ function="Object.Edit" />
+ <menu_item_call.on_visible
+ function="VisibleBuild"/>
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Open"
+ name="Open">
+ <menu_item_call.on_click
+ function="Object.Open" />
+ <menu_item_call.on_enable
+ function="Object.EnableOpen" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Sit Here"
+ name="Object Sit">
+ <menu_item_call.on_click
+ function="Object.SitOrStand" />
+ <menu_item_call.on_enable
+ function="Object.EnableSitOrStand"
+ name="EnableSitOrStand"
+ parameter="Sit Here,Stand Up" />
+ </menu_item_call>
+ <menu_item_call
+ label="Object Profile"
+ name="Object Inspect">
+ <menu_item_call.on_click
+ function="Object.Inspect" />
+ <menu_item_call.on_enable
+ function="Object.EnableInspect" />
+ </menu_item_call>
+ <menu_item_call
+ label="Zoom In"
+ name="Zoom In">
+ <menu_item_call.on_click
+ function="Object.ZoomIn" />
+ </menu_item_call>
+<menu_item_separator layout="topleft" />
+ <context_menu
+ label="Put On &gt;"
+ name="Put On" >
+ <menu_item_call
+ enabled="false"
+ label="Wear"
+ name="Wear">
+ <menu_item_call.on_click
+ function="Object.AttachToAvatar" />
+ <menu_item_call.on_enable
+ function="Object.EnableWear" />
+ </menu_item_call>
+ <context_menu
+ label="Attach &gt;"
+ name="Object Attach" />
+ <context_menu
+ label="Attach HUD &gt;"
+ name="Object Attach HUD" />
+ </context_menu>
+ <context_menu
+ label="Remove &gt;"
+ name="Remove">
+ <menu_item_call
+ enabled="false"
+ label="Take"
+ name="Pie Object Take">
+ <menu_item_call.on_click
+ function="Tools.BuyOrTake" />
+ <menu_item_call.on_enable
+ function="Tools.EnableBuyOrTake"
+ parameter="Buy,Take" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Report Abuse"
+ name="Report Abuse...">
+ <menu_item_call.on_click
+ function="Object.ReportAbuse" />
+ <menu_item_call.on_enable
+ function="Object.EnableReportAbuse" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Block"
+ name="Object Mute">
+ <menu_item_call.on_click
+ function="Object.Mute" />
+ <menu_item_call.on_enable
+ function="Object.EnableMute" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Return"
+ name="Return...">
+ <menu_item_call.on_click
+ function="Object.Return" />
+ <menu_item_call.on_enable
+ function="Object.EnableReturn" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Delete"
+ name="Delete">
+ <menu_item_call.on_click
+ function="Object.Delete" />
+ <menu_item_call.on_enable
+ function="Object.EnableDelete" />
+ </menu_item_call>
+ </context_menu>
+ <menu_item_separator layout="topleft" />
+ <menu_item_call
+ enabled="false"
+ label="Take Copy"
+ name="Take Copy">
+ <menu_item_call.on_click
+ function="Tools.TakeCopy" />
+ <menu_item_call.on_enable
+ function="Tools.EnableTakeCopy" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Pay"
+ name="Pay...">
+ <menu_item_call.on_click
+ function="PayObject" />
+ <menu_item_call.on_enable
+ function="EnablePayObject" />
+</menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Buy"
+ name="Buy...">
+ <menu_item_call.on_click
+ function="Object.Buy" />
+ <menu_item_call.on_enable
+ function="Object.EnableBuy" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_object_icon.xml b/indra/newview/skins/default/xui/en/menu_object_icon.xml
new file mode 100644
index 0000000000..0c8a2af002
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_object_icon.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ height="101"
+ layout="topleft"
+ left="100"
+ mouse_opaque="false"
+ name="Object Icon Menu"
+ top="724"
+ visible="false"
+ width="128">
+ <menu_item_call
+ label="Object Profile..."
+ layout="topleft"
+ name="Object Profile">
+ <menu_item_call.on_click
+ function="ObjectIcon.Action"
+ parameter="profile" />
+ </menu_item_call>
+ <menu_item_call
+ label="Block..."
+ layout="topleft"
+ name="Block">
+ <menu_item_call.on_click
+ function="ObjectIcon.Action"
+ parameter="block" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_participant_list.xml b/indra/newview/skins/default/xui/en/menu_participant_list.xml
new file mode 100644
index 0000000000..805ffbae66
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_participant_list.xml
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Participant List Context Menu">
+ <menu_item_check
+ label="Sort by Name"
+ layout="topleft"
+ name="SortByName">
+ <menu_item_check.on_click
+ function="ParticipantList.Sort"
+ parameter="sort_by_name" />
+ <menu_item_check.on_check
+ function="ParticipantList.CheckItem"
+ parameter="is_sorted_by_name" />
+ </menu_item_check>
+ <menu_item_check
+ label="Sort by Recent Speakers"
+ layout="topleft"
+ name="SortByRecentSpeakers">
+ <menu_item_check.on_click
+ function="ParticipantList.Sort"
+ parameter="sort_by_recent_speakers" />
+ <menu_item_check.on_check
+ function="ParticipantList.CheckItem"
+ parameter="is_sorted_by_recent_speakers" />
+ </menu_item_check>
+ <menu_item_call
+ label="View Profile"
+ layout="topleft"
+ name="View Profile">
+ <menu_item_call.on_click
+ function="Avatar.Profile" />
+ </menu_item_call>
+ <menu_item_call
+ label="Add Friend"
+ layout="topleft"
+ name="Add Friend">
+ <menu_item_call.on_click
+ function="Avatar.AddFriend" />
+ <menu_item_call.on_enable
+ function="ParticipantList.EnableItem"
+ parameter="can_add" />
+ </menu_item_call>
+ <menu_item_call
+ label="IM"
+ layout="topleft"
+ name="IM">
+ <menu_item_call.on_click
+ function="Avatar.IM" />
+ <menu_item_call.on_enable
+ function="ParticipantList.EnableItem"
+ parameter="can_im" />
+ </menu_item_call>
+ <menu_item_call
+ label="Call"
+ layout="topleft"
+ name="Call">
+ <menu_item_call.on_click
+ function="Avatar.Call" />
+ <menu_item_call.on_enable
+ function="ParticipantList.EnableItem"
+ parameter="can_call" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="true"
+ label="Share"
+ layout="topleft"
+ name="Share">
+ <menu_item_call.on_click
+ function="Avatar.Share" />
+ <menu_item_call.on_enable
+ function="ParticipantList.EnableItem"
+ parameter="can_share" />
+ </menu_item_call>
+ <menu_item_call
+ label="Pay"
+ layout="topleft"
+ name="Pay">
+ <menu_item_call.on_click
+ function="Avatar.Pay" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_check
+ label="Block Voice"
+ layout="topleft"
+ name="Block/Unblock">
+ <menu_item_check.on_click
+ function="Avatar.BlockUnblock" />
+ <menu_item_check.on_check
+ function="ParticipantList.CheckItem"
+ parameter="is_blocked" />
+ <menu_item_check.on_enable
+ function="ParticipantList.EnableItem"
+ parameter="can_block" />
+ </menu_item_check>
+ <menu_item_check
+ label="Block Text"
+ layout="topleft"
+ name="MuteText">
+ <on_check
+ function="ParticipantList.CheckItem"
+ parameter="is_muted" />
+ <on_click
+ function="ParticipantList.ToggleMuteText" />
+ <on_enable
+ function="ParticipantList.EnableItem"
+ parameter="can_mute_text" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <context_menu
+ label="Moderator Options &gt;"
+ layout="topleft"
+ name="Moderator Options" >
+ <menu_item_check
+ label="Allow text chat"
+ layout="topleft"
+ name="AllowTextChat">
+ <on_check
+ function="ParticipantList.CheckItem"
+ parameter="is_allowed_text_chat" />
+ <on_click
+ function="ParticipantList.ToggleAllowTextChat" />
+ <on_enable
+ function="ParticipantList.EnableItem"
+ parameter="can_allow_text_chat" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft"
+ name="moderate_voice_separator" />
+ <menu_item_call
+ label="Mute this participant"
+ layout="topleft"
+ name="ModerateVoiceMuteSelected">
+ <on_click
+ function="ParticipantList.ModerateVoice"
+ parameter="selected" />
+ <on_enable
+ function="ParticipantList.EnableItem"
+ parameter="can_moderate_voice" />
+ </menu_item_call>
+ <menu_item_call
+ label="Mute everyone else"
+ layout="topleft"
+ name="ModerateVoiceMuteOthers">
+ <on_click
+ function="ParticipantList.ModerateVoice"
+ parameter="others" />
+ <on_enable
+ function="ParticipantList.EnableItem"
+ parameter="can_moderate_voice" />
+ </menu_item_call>
+ <menu_item_call
+ label="Unmute this participant"
+ layout="topleft"
+ name="ModerateVoiceUnMuteSelected">
+ <on_click
+ function="ParticipantList.ModerateVoice"
+ parameter="selected" />
+ <on_enable
+ function="ParticipantList.EnableItem"
+ parameter="can_moderate_voice" />
+ </menu_item_call>
+ <menu_item_call
+ label="Unmute everyone else"
+ layout="topleft"
+ name="ModerateVoiceUnMuteOthers">
+ <on_click
+ function="ParticipantList.ModerateVoice"
+ parameter="others" />
+ <on_enable
+ function="ParticipantList.EnableItem"
+ parameter="can_moderate_voice" />
+ </menu_item_call>
+ </context_menu>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml
new file mode 100644
index 0000000000..f1117d1419
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu name="menu_group_plus"
+ left="0" bottom="0" visible="false"
+ mouse_opaque="false" opaque="true" color="MenuDefaultBgColor" drop_shadow="false">
+ <menu_item_check
+ label="Sort by Name"
+ name="sort_name">
+ <menu_item_check.on_click
+ function="People.Friends.ViewSort.Action"
+ parameter="sort_name" />
+ <menu_item_check.on_check
+ function="People.Friends.ViewSort.CheckItem"
+ parameter="sort_name" />
+ </menu_item_check>
+ <menu_item_check
+ label="Sort by Status"
+ name="sort_status">
+ <menu_item_check.on_click
+ function="People.Friends.ViewSort.Action"
+ parameter="sort_status" />
+ <menu_item_check.on_check
+ function="People.Friends.ViewSort.CheckItem"
+ parameter="sort_status" />
+ </menu_item_check>
+ <menu_item_separator layout="topleft" />
+ <menu_item_check name="view_icons" label="View People Icons">
+ <menu_item_check.on_click
+ function="People.Friends.ViewSort.Action"
+ parameter="view_icons" />
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="FriendsListShowIcons" />
+ </menu_item_check>
+ <menu_item_separator layout="topleft" />
+ <menu_item_call name="show_blocked_list" label="Show Blocked Residents &amp; Objects">
+ <menu_item_call.on_click function="SideTray.ShowPanel" parameter="panel_block_list_sidetray" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_groups.xml b/indra/newview/skins/default/xui/en/menu_people_groups.xml
new file mode 100644
index 0000000000..afa680139d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_people_groups.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu name="menu_group_plus"
+ left="0" bottom="0" visible="false"
+ mouse_opaque="false" opaque="true" color="MenuDefaultBgColor" drop_shadow="false">
+ <menu_item_call
+ label="View Info"
+ name="View Info">
+ <menu_item_call.on_click
+ function="People.Groups.Action"
+ parameter="view_info" />
+ <menu_item_call.on_enable
+ function="People.Groups.Enable"
+ parameter="view_info" />
+ </menu_item_call>
+ <menu_item_call
+ label="Chat"
+ name="Chat">
+ <menu_item_call.on_click
+ function="People.Groups.Action"
+ parameter="chat" />
+ <menu_item_call.on_enable
+ function="People.Groups.Enable"
+ parameter="chat" />
+ </menu_item_call>
+ <menu_item_call
+ label="Call"
+ name="Call">
+ <menu_item_call.on_click
+ function="People.Groups.Action"
+ parameter="call" />
+ <menu_item_call.on_enable
+ function="People.Groups.Enable"
+ parameter="call" />
+ </menu_item_call>
+ <menu_item_separator />
+ <menu_item_call
+ label="Activate"
+ name="Activate">
+ <menu_item_call.on_click
+ function="People.Groups.Action"
+ parameter="activate" />
+ <menu_item_call.on_enable
+ function="People.Groups.Enable"
+ parameter="activate" />
+ </menu_item_call>
+ <menu_item_separator />
+ <menu_item_call
+ label="Leave"
+ name="Leave">
+ <menu_item_call.on_click
+ function="People.Groups.Action"
+ parameter="leave" />
+ <menu_item_call.on_enable
+ function="People.Groups.Enable"
+ parameter="leave" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml
new file mode 100644
index 0000000000..df3cb26b04
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu name="menu_group_plus"
+ left="0" bottom="0" visible="false"
+ mouse_opaque="false" opaque="true" color="MenuDefaultBgColor" drop_shadow="false">
+ <menu_item_check
+ label="Display Group Icons"
+ layout="topleft"
+ name="Display Group Icons">
+ <menu_item_check.on_click
+ function="People.Groups.ViewSort.Action"
+ parameter="show_icons" />
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="GroupListShowIcons" />
+ </menu_item_check>
+ <menu_item_call
+ label="Leave Selected Group"
+ layout="topleft"
+ name="Leave Selected Group">
+ <menu_item_call.on_click
+ function="People.Group.Minus.Action"/>
+ <menu_item_call.on_enable
+ function="People.Group.Minus.Enable"/>
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml
new file mode 100644
index 0000000000..c4da1df017
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Avatar Context Menu">
+ <menu_item_call
+ label="View Profile"
+ layout="topleft"
+ name="View Profile">
+ <menu_item_call.on_click
+ function="Avatar.Profile" />
+ </menu_item_call>
+ <menu_item_call
+ label="Add Friend"
+ layout="topleft"
+ name="Add Friend">
+ <menu_item_call.on_click
+ function="Avatar.AddFriend" />
+ <menu_item_call.on_enable
+ function="Avatar.EnableItem"
+ parameter="can_add" />
+ </menu_item_call>
+ <menu_item_call
+ label="IM"
+ layout="topleft"
+ name="IM">
+ <menu_item_call.on_click
+ function="Avatar.IM" />
+ </menu_item_call>
+ <menu_item_call
+ label="Call"
+ layout="topleft"
+ name="Call">
+ <menu_item_call.on_click
+ function="Avatar.Call" />
+ <menu_item_call.on_enable
+ function="Avatar.EnableItem"
+ parameter="can_call" />
+ </menu_item_call>
+ <menu_item_call
+ label="Share"
+ layout="topleft"
+ name="Share">
+ <menu_item_call.on_click
+ function="Avatar.Share" />
+ </menu_item_call>
+ <menu_item_call
+ label="Pay"
+ layout="topleft"
+ name="Pay">
+ <menu_item_call.on_click
+ function="Avatar.Pay" />
+ </menu_item_call>
+ <menu_item_check
+ label="Block/Unblock"
+ layout="topleft"
+ name="Block/Unblock">
+ <menu_item_check.on_click
+ function="Avatar.BlockUnblock" />
+ <menu_item_check.on_check
+ function="Avatar.CheckItem"
+ parameter="is_blocked" />
+ <menu_item_check.on_enable
+ function="Avatar.EnableItem"
+ parameter="can_block" />
+ </menu_item_check>
+ <menu_item_call
+ label="Offer Teleport"
+ name="teleport">
+ <menu_item_call.on_click
+ function="Avatar.OfferTeleport"/>
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml
new file mode 100644
index 0000000000..0d3dd3366d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Multi-Selected People Context Menu">
+ <menu_item_call
+ enabled="false"
+ label="Add Friends"
+ layout="topleft"
+ name="Add Friends">
+ <on_click
+ function="Avatar.AddFriends" />
+ <on_enable
+ function="Avatar.EnableItem"
+ parameter="can_add" />
+ </menu_item_call>
+ <menu_item_call
+ label="IM"
+ layout="topleft"
+ name="IM">
+ <on_click
+ function="Avatar.IM" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Call"
+ layout="topleft"
+ name="Call">
+ <on_click
+ function="Avatar.Call" />
+ <on_enable
+ function="Avatar.EnableItem"
+ parameter="can_call" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Share"
+ layout="topleft"
+ name="Share">
+ <on_click
+ function="Avatar.Share" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Pay"
+ layout="topleft"
+ name="Pay">
+ <on_click
+ function="Avatar.Pay" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml
new file mode 100644
index 0000000000..39f9e48609
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu name="menu_group_plus"
+ left="0" bottom="0" visible="false"
+ mouse_opaque="false" opaque="true" color="MenuDefaultBgColor" drop_shadow="false">
+ <menu_item_check
+ label="Sort by Recent Speakers"
+ name="sort_by_recent_speakers">
+ <menu_item_check.on_click
+ function="People.Nearby.ViewSort.Action"
+ parameter="sort_by_recent_speakers"/>
+ <menu_item_check.on_check
+ function="People.Nearby.ViewSort.CheckItem"
+ parameter="sort_by_recent_speakers"/>
+ </menu_item_check>
+ <menu_item_check
+ label="Sort by Name"
+ name="sort_name">
+ <menu_item_check.on_click
+ function="People.Nearby.ViewSort.Action"
+ parameter="sort_name"/>
+ <menu_item_check.on_check
+ function="People.Nearby.ViewSort.CheckItem"
+ parameter="sort_name"/>
+ </menu_item_check>
+ <menu_item_check
+ label="Sort by Distance"
+ name="sort_distance">
+ <menu_item_check.on_click
+ function="People.Nearby.ViewSort.Action"
+ parameter="sort_distance"/>
+ <menu_item_check.on_check
+ function="People.Nearby.ViewSort.CheckItem"
+ parameter="sort_distance"/>
+ </menu_item_check>
+ <menu_item_separator layout="topleft" />
+ <menu_item_check name="view_icons" label="View People Icons">
+ <menu_item_check.on_click
+ function="People.Nearby.ViewSort.Action"
+ parameter="view_icons" />
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="NearbyListShowIcons" />
+ </menu_item_check>
+ <menu_item_separator layout="topleft" />
+ <menu_item_call name="show_blocked_list" label="Show Blocked Residents &amp; Objects">
+ <menu_item_call.on_click function="SideTray.ShowPanel" userdata="panel_block_list_sidetray" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml
new file mode 100644
index 0000000000..cfd6dc78b6
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu name="menu_group_plus"
+ left="0" bottom="0" visible="false"
+ mouse_opaque="false" opaque="true" color="MenuDefaultBgColor" drop_shadow="false">
+ <menu_item_check
+ label="Sort by Most Recent"
+ name="sort_most">
+ <menu_item_check.on_click
+ function="People.Recent.ViewSort.Action"
+ parameter="sort_recent" />
+ <menu_item_check.on_check
+ function="People.Recent.ViewSort.CheckItem"
+ parameter="sort_recent" />
+ </menu_item_check>
+ <menu_item_check
+ label="Sort by Name"
+ name="sort_name">
+ <menu_item_check.on_click
+ function="People.Recent.ViewSort.Action"
+ parameter="sort_name" />
+ <menu_item_check.on_check
+ function="People.Recent.ViewSort.CheckItem"
+ parameter="sort_name" />
+ </menu_item_check>
+ <menu_item_separator layout="topleft" />
+ <menu_item_check name="view_icons" label="View People Icons">
+ <menu_item_check.on_click
+ function="People.Recent.ViewSort.Action"
+ parameter="view_icons" />
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RecentListShowIcons" />
+ </menu_item_check>
+ <menu_item_separator layout="topleft" />
+ <menu_item_call name="show_blocked_list" label="Show Blocked Residents &amp; Objects">
+ <menu_item_call.on_click function="SideTray.ShowPanel" userdata="panel_block_list_sidetray" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_picks.xml b/indra/newview/skins/default/xui/en/menu_picks.xml
new file mode 100644
index 0000000000..7e07a97016
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_picks.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Picks">
+ <menu_item_call
+ label="Info"
+ layout="topleft"
+ name="pick_info">
+ <menu_item_call.on_click
+ function="Pick.Info" />
+ </menu_item_call>
+ <menu_item_call
+ label="Edit"
+ layout="topleft"
+ name="pick_edit"
+ visible="false">
+ <menu_item_call.on_click
+ function="Pick.Edit" />
+ </menu_item_call>
+ <menu_item_call
+ label="Teleport"
+ layout="topleft"
+ name="pick_teleport">
+ <menu_item_call.on_click
+ function="Pick.Teleport" />
+ </menu_item_call>
+ <menu_item_call
+ label="Map"
+ layout="topleft"
+ name="pick_map">
+ <menu_item_call.on_click
+ function="Pick.Map" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"
+ name="pick_separator"
+ visible="false" />
+ <menu_item_call
+ label="Delete"
+ layout="topleft"
+ name="pick_delete"
+ visible="false">
+ <menu_item_call.on_click
+ function="Pick.Delete" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_picks_plus.xml b/indra/newview/skins/default/xui/en/menu_picks_plus.xml
new file mode 100644
index 0000000000..f3b207e36c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_picks_plus.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu
+ height="201"
+ layout="topleft"
+ mouse_opaque="false"
+ name="picks_plus_menu"
+ width="120">
+ <menu_item_call
+ name="create_pick"
+ label="New Pick">
+ <menu_item_call.on_click
+ function="Picks.Plus.Action"
+ userdata="new_pick" />
+ <menu_item_call.on_enable
+ function="Picks.Plus.Enable"
+ userdata="new_pick" />
+ </menu_item_call>
+ <menu_item_call
+ name="create_classified"
+ label="New Classified">
+ <menu_item_call.on_click
+ function="Picks.Plus.Action"
+ userdata="new_classified" />
+ </menu_item_call>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_place.xml b/indra/newview/skins/default/xui/en/menu_place.xml
new file mode 100644
index 0000000000..1b96eb51f0
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_place.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu
+ height="201"
+ layout="topleft"
+ mouse_opaque="false"
+ name="place_overflow_menu"
+ width="128">
+ <menu_item_call
+ label="Make a Landmark"
+ layout="topleft"
+ name="landmark">
+ <menu_item_call.on_click
+ function="Places.OverflowMenu.Action"
+ parameter="landmark" />
+ </menu_item_call>
+ <menu_item_call
+ label="Create Pick"
+ layout="topleft"
+ name="pick">
+ <menu_item_call.on_click
+ function="Places.OverflowMenu.Action"
+ parameter="pick" />
+ <menu_item_call.on_enable
+ function="Places.OverflowMenu.Enable"
+ parameter="can_create_pick" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"/>
+ <menu_item_call
+ enabled="false"
+ label="Buy Pass"
+ layout="topleft"
+ name="pass">
+ <menu_item_call.on_click
+ function="Places.OverflowMenu.Action"
+ parameter="pass" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"/>
+ <menu_item_call
+ enabled="false"
+ label="Edit"
+ layout="topleft"
+ name="edit">
+ <menu_item_call.on_click
+ function="Places.OverflowMenu.Action"
+ parameter="edit" />
+ </menu_item_call>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_place_add_button.xml b/indra/newview/skins/default/xui/en/menu_place_add_button.xml
new file mode 100644
index 0000000000..e3a39a1242
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_place_add_button.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="menu_folder_gear"
+ visible="false">
+ <menu_item_call
+ label="Add Folder"
+ layout="topleft"
+ name="add_folder">
+ <on_click
+ function="Places.LandmarksGear.Add.Action"
+ parameter="category" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="category" />
+ </menu_item_call>
+ <menu_item_call
+ label="Add Landmark"
+ layout="topleft"
+ name="add_landmark">
+ <on_click
+ function="Places.LandmarksGear.Add.Action"
+ parameter="add_landmark" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
new file mode 100644
index 0000000000..9b3948b29b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ bottom="806"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="menu_folder_gear"
+ visible="false">
+ <menu_item_call
+ label="Add Landmark"
+ layout="topleft"
+ name="add_landmark">
+ <on_click
+ function="Places.LandmarksGear.Add.Action"
+ parameter="add_landmark" />
+ </menu_item_call>
+ <menu_item_call
+ label="Add Folder"
+ layout="topleft"
+ name="add_folder">
+ <on_click
+ function="Places.LandmarksGear.Add.Action"
+ parameter="category" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="category" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Cut"
+ layout="topleft"
+ name="cut">
+ <on_click
+ function="Places.LandmarksGear.CopyPaste.Action"
+ parameter="cut" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="cut" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy"
+ layout="topleft"
+ name="copy_folder">
+ <on_click
+ function="Places.LandmarksGear.CopyPaste.Action"
+ parameter="copy" />
+ </menu_item_call>
+ <menu_item_call
+ label="Paste"
+ layout="topleft"
+ name="paste">
+ <on_click
+ function="Places.LandmarksGear.CopyPaste.Action"
+ parameter="paste" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="paste" />
+ </menu_item_call>
+ <menu_item_call
+ label="Rename"
+ layout="topleft"
+ name="rename">
+ <on_click
+ function="Places.LandmarksGear.CopyPaste.Action"
+ parameter="rename" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="rename" />
+ </menu_item_call>
+ <menu_item_call
+ label="Delete"
+ layout="topleft"
+ name="delete">
+ <on_click
+ function="Places.LandmarksGear.CopyPaste.Action"
+ parameter="delete" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="delete" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Expand"
+ layout="topleft"
+ name="expand">
+ <on_click
+ function="Places.LandmarksGear.Folding.Action"
+ parameter="expand" />
+ </menu_item_call>
+ <menu_item_call
+ label="Collapse"
+ layout="topleft"
+ name="collapse">
+ <on_click
+ function="Places.LandmarksGear.Folding.Action"
+ parameter="collapse" />
+ </menu_item_call>
+ <menu_item_call
+ label="Expand all folders"
+ layout="topleft"
+ name="expand_all">
+ <on_click
+ function="Places.LandmarksGear.Folding.Action"
+ parameter="expand_all" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="expand_all" />
+ </menu_item_call>
+ <menu_item_call
+ label="Collapse all folders"
+ layout="topleft"
+ name="collapse_all">
+ <on_click
+ function="Places.LandmarksGear.Folding.Action"
+ parameter="collapse_all" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="collapse_all" />
+ </menu_item_call>
+ <menu_item_check
+ label="Sort by Date"
+ layout="topleft"
+ name="sort_by_date">
+ <on_check
+ function="Places.LandmarksGear.Check"
+ parameter="sort_by_date" />
+ <on_click
+ function="Places.LandmarksGear.Folding.Action"
+ parameter="sort_by_date" />
+ </menu_item_check>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml b/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml
new file mode 100644
index 0000000000..4b8bc8132f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ bottom="806"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="menu_ladmark_gear"
+ visible="false">
+ <menu_item_call
+ label="Teleport"
+ layout="topleft"
+ name="teleport">
+ <on_click
+ function="Places.LandmarksGear.Custom.Action"
+ parameter="teleport" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="teleport" />
+ </menu_item_call>
+ <menu_item_call
+ label="More Information"
+ layout="topleft"
+ name="more_info">
+ <on_click
+ function="Places.LandmarksGear.Custom.Action"
+ parameter="more_info" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="more_info" />
+ </menu_item_call>
+ <menu_item_call
+ label="Show on Map"
+ layout="topleft"
+ name="show_on_map">
+ <on_click
+ function="Places.LandmarksGear.Custom.Action"
+ parameter="show_on_map" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="show_on_map" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Add Landmark"
+ layout="topleft"
+ name="add_landmark">
+ <on_click
+ function="Places.LandmarksGear.Add.Action"
+ parameter="add_landmark" />
+ </menu_item_call>
+ <menu_item_call
+ label="Add Folder"
+ layout="topleft"
+ name="add_folder">
+ <on_click
+ function="Places.LandmarksGear.Add.Action"
+ parameter="category" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="category" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Cut"
+ layout="topleft"
+ name="cut">
+ <on_click
+ function="Places.LandmarksGear.CopyPaste.Action"
+ parameter="cut" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="cut" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy Landmark"
+ layout="topleft"
+ name="copy_landmark">
+ <on_click
+ function="Places.LandmarksGear.CopyPaste.Action"
+ parameter="copy" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy SLurl"
+ layout="topleft"
+ name="copy_slurl">
+ <on_click
+ function="Places.LandmarksGear.CopyPaste.Action"
+ parameter="copy_slurl" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="copy_slurl" />
+ </menu_item_call>
+ <menu_item_call
+ label="Paste"
+ layout="topleft"
+ name="paste">
+ <on_click
+ function="Places.LandmarksGear.CopyPaste.Action"
+ parameter="paste" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="paste" />
+ </menu_item_call>
+ <menu_item_call
+ label="Rename"
+ layout="topleft"
+ name="rename">
+ <on_click
+ function="Places.LandmarksGear.CopyPaste.Action"
+ parameter="rename" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="rename" />
+ </menu_item_call>
+ <menu_item_call
+ label="Delete"
+ layout="topleft"
+ name="delete">
+ <on_click
+ function="Places.LandmarksGear.CopyPaste.Action"
+ parameter="delete" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="delete" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Expand all folders"
+ layout="topleft"
+ name="expand_all">
+ <on_click
+ function="Places.LandmarksGear.Folding.Action"
+ parameter="expand_all" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="expand_all" />
+ </menu_item_call>
+ <menu_item_call
+ label="Collapse all folders"
+ layout="topleft"
+ name="collapse_all">
+ <on_click
+ function="Places.LandmarksGear.Folding.Action"
+ parameter="collapse_all" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="collapse_all" />
+ </menu_item_call>
+ <menu_item_check
+ label="Sort by Date"
+ layout="topleft"
+ name="sort_by_date">
+ <on_check
+ function="Places.LandmarksGear.Check"
+ parameter="sort_by_date" />
+ <on_click
+ function="Places.LandmarksGear.Folding.Action"
+ parameter="sort_by_date" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="sort_by_date" />
+ </menu_item_check>
+ <menu_item_call
+ label="Create Pick"
+ layout="topleft"
+ name="create_pick">
+ <on_click
+ function="Places.LandmarksGear.Custom.Action"
+ parameter="create_pick" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="create_pick" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_profile_overflow.xml b/indra/newview/skins/default/xui/en/menu_profile_overflow.xml
new file mode 100644
index 0000000000..1dc1c610cf
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_profile_overflow.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu
+ height="50"
+ layout="topleft"
+ mouse_opaque="false"
+ name="profile_overflow_menu"
+ width="120">
+ <menu_item_call
+ label="Pay"
+ layout="topleft"
+ name="pay">
+ <menu_item_call.on_click
+ function="Profile.Pay" />
+ </menu_item_call>
+ <menu_item_call
+ label="Share"
+ layout="topleft"
+ name="share">
+ <menu_item_call.on_click
+ function="Profile.Share" />
+ </menu_item_call>
+ <menu_item_call
+ label="Kick"
+ layout="topleft"
+ name="kick">
+ <menu_item_call.on_click
+ function="Profile.Kick" />
+ <menu_item_call.on_visible
+ function="Profile.EnableGod" />
+ </menu_item_call>
+ <menu_item_call
+ label="Freeze"
+ layout="topleft"
+ name="freeze">
+ <menu_item_call.on_click
+ function="Profile.Freeze" />
+ <menu_item_call.on_visible
+ function="Profile.EnableGod" />
+ </menu_item_call>
+ <menu_item_call
+ label="Unfreeze"
+ layout="topleft"
+ name="unfreeze">
+ <menu_item_call.on_click
+ function="Profile.Unfreeze" />
+ <menu_item_call.on_visible
+ function="Profile.EnableGod" />
+ </menu_item_call>
+ <menu_item_call
+ label="CSR"
+ layout="topleft"
+ name="csr">
+ <menu_item_call.on_click
+ function="Profile.CSR" />
+ <menu_item_call.on_visible
+ function="Profile.EnableGod" />
+ </menu_item_call>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_slurl.xml b/indra/newview/skins/default/xui/en/menu_slurl.xml
new file mode 100644
index 0000000000..ee37d49946
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_slurl.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ height="101"
+ layout="topleft"
+ left="100"
+ mouse_opaque="false"
+ name="Popup"
+ top="724"
+ width="128">
+ <menu_item_separator
+ layout="topleft"
+ name="Landmark Separator" />
+ <menu_item_call
+ label="About URL"
+ layout="topleft"
+ name="about_url">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="about" />
+ </menu_item_call>
+ <menu_item_call
+ label="Teleport to URL"
+ layout="topleft"
+ name="teleport_to_url">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="about" />
+ </menu_item_call>
+ <menu_item_call
+ label="Map"
+ layout="topleft"
+ name="show_on_map">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="about" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml b/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml
new file mode 100644
index 0000000000..134b331514
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ name="Teleport History Gear Context Menu"
+ left="0"
+ bottom="0"
+ visible="false"
+ mouse_opaque="false"
+ opaque="true"
+ color="MenuDefaultBgColor"
+ drop_shadow="true" >
+ <menu_item_call
+ label="Expand all folders"
+ name="Expand all folders">
+ <menu_item_call.on_click
+ function="TeleportHistory.ExpandAllFolders" />
+ <on_enable
+ function="TeleportHistory.GearMenu.Enable"
+ parameter="expand_all" />
+ </menu_item_call>
+ <menu_item_call
+ label="Collapse all folders"
+ name="Collapse all folders">
+ <menu_item_call.on_click
+ function="TeleportHistory.CollapseAllFolders" />
+ <on_enable
+ function="TeleportHistory.GearMenu.Enable"
+ parameter="collapse_all" />
+ </menu_item_call>
+ <menu_item_separator layout="topleft" />
+ <menu_item_call
+ label="Clear Teleport History"
+ name="Clear Teleport History">
+ <menu_item_call.on_click
+ function="TeleportHistory.ClearTeleportHistory" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
new file mode 100644
index 0000000000..0160d52b17
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Teleport History Item Context Menu">
+ <menu_item_call
+ label="Teleport"
+ layout="topleft"
+ name="Teleport">
+ <menu_item_call.on_click
+ function="TeleportHistory.Teleport" />
+ </menu_item_call>
+ <menu_item_call
+ label="More Information"
+ layout="topleft"
+ name="More Information">
+ <menu_item_call.on_click
+ function="TeleportHistory.MoreInformation" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy to Clipboard"
+ layout="topleft"
+ name="CopyToClipboard">
+ <menu_item_call.on_click
+ function="TeleportHistory.CopyToClipboard" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_teleport_history_tab.xml b/indra/newview/skins/default/xui/en/menu_teleport_history_tab.xml
new file mode 100644
index 0000000000..ecc1d8a954
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_teleport_history_tab.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Teleport History Item Context Menu">
+ <menu_item_call
+ label="Open"
+ layout="topleft"
+ name="TabOpen">
+ <menu_item_call.on_click
+ function="TeleportHistory.TabOpen" />
+ </menu_item_call>
+ <menu_item_call
+ label="Close"
+ layout="topleft"
+ name="TabClose">
+ <menu_item_call.on_click
+ function="TeleportHistory.TabClose" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_text_editor.xml b/indra/newview/skins/default/xui/en/menu_text_editor.xml
new file mode 100644
index 0000000000..ecd96088e7
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_text_editor.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ name="Text editor context menu">
+ <menu_item_call
+ label="Cut"
+ layout="topleft"
+ name="Cut"
+ shortcut="control|X">
+ <menu_item_call.on_click
+ function="Edit.Cut" />
+ <menu_item_call.on_enable
+ function="Edit.EnableCut" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy"
+ layout="topleft"
+ name="Copy"
+ shortcut="control|C">
+ <menu_item_call.on_click
+ function="Edit.Copy" />
+ <menu_item_call.on_enable
+ function="Edit.EnableCopy" />
+ </menu_item_call>
+ <menu_item_call
+ label="Paste"
+ layout="topleft"
+ name="Paste"
+ shortcut="control|V">
+ <menu_item_call.on_click
+ function="Edit.Paste" />
+ <menu_item_call.on_enable
+ function="Edit.EnablePaste" />
+ </menu_item_call>
+ <menu_item_call
+ label="Delete"
+ layout="topleft"
+ name="Delete"
+ shortcut="Del">
+ <menu_item_call.on_click
+ function="Edit.Delete" />
+ <menu_item_call.on_enable
+ function="Edit.EnableDelete" />
+ </menu_item_call>
+ <menu_item_call
+ label="Select All"
+ layout="topleft"
+ name="Select All"
+ shortcut="control|A">
+ <menu_item_call.on_click
+ function="Edit.SelectAll" />
+ <menu_item_call.on_enable
+ function="Edit.EnableSelectAll" />
+ </menu_item_call>
+</context_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
new file mode 100644
index 0000000000..fa05dac148
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_url_agent.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Url Popup">
+ <menu_item_call
+ label="Show Resident Profile"
+ layout="topleft"
+ name="show_agent">
+ <menu_item_call.on_click
+ function="Url.Execute" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Copy Name to clipboard"
+ layout="topleft"
+ name="url_copy_label">
+ <menu_item_call.on_click
+ function="Url.CopyLabel" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy SLurl to clipboard"
+ layout="topleft"
+ name="url_copy">
+ <menu_item_call.on_click
+ function="Url.CopyUrl" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_url_group.xml b/indra/newview/skins/default/xui/en/menu_url_group.xml
new file mode 100644
index 0000000000..c5eaf94d22
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_url_group.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Url Popup">
+ <menu_item_call
+ label="Show Group Information"
+ layout="topleft"
+ name="show_group">
+ <menu_item_call.on_click
+ function="Url.Execute" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Copy Group to clipboard"
+ layout="topleft"
+ name="url_copy_label">
+ <menu_item_call.on_click
+ function="Url.CopyLabel" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy SLurl to clipboard"
+ layout="topleft"
+ name="url_copy">
+ <menu_item_call.on_click
+ function="Url.CopyUrl" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_url_http.xml b/indra/newview/skins/default/xui/en/menu_url_http.xml
new file mode 100644
index 0000000000..7a4b1e619b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_url_http.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Url Popup">
+ <menu_item_call
+ label="Open Web Page"
+ layout="topleft"
+ name="url_open">
+ <menu_item_call.on_click
+ function="Url.Open" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Open in Internal Browser"
+ layout="topleft"
+ name="url_open_internal">
+ <menu_item_call.on_click
+ function="Url.OpenInternal" />
+ </menu_item_call>
+ <menu_item_call
+ label="Open in External Browser"
+ layout="topleft"
+ name="url_open_external">
+ <menu_item_call.on_click
+ function="Url.OpenExternal" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Copy URL to clipboard"
+ layout="topleft"
+ name="url_copy">
+ <menu_item_call.on_click
+ function="Url.CopyUrl" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_url_inventory.xml b/indra/newview/skins/default/xui/en/menu_url_inventory.xml
new file mode 100644
index 0000000000..cf9d1d5881
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_url_inventory.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Url Popup">
+ <menu_item_call
+ label="Show Inventory Item"
+ layout="topleft"
+ name="show_item">
+ <menu_item_call.on_click
+ function="Url.Execute" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Copy Name to clipboard"
+ layout="topleft"
+ name="url_copy_label">
+ <menu_item_call.on_click
+ function="Url.CopyLabel" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy SLurl to clipboard"
+ layout="topleft"
+ name="url_copy">
+ <menu_item_call.on_click
+ function="Url.CopyUrl" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_url_map.xml b/indra/newview/skins/default/xui/en/menu_url_map.xml
new file mode 100644
index 0000000000..2ca9e3b3fe
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_url_map.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Url Popup">
+ <menu_item_call
+ label="Show on Map"
+ layout="topleft"
+ name="show_on_map">
+ <menu_item_call.on_click
+ function="Url.Execute" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Teleport to Location"
+ layout="topleft"
+ name="teleport_to_location">
+ <menu_item_call.on_click
+ function="Url.Teleport" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Copy SLurl to clipboard"
+ layout="topleft"
+ name="url_copy">
+ <menu_item_call.on_click
+ function="Url.CopyUrl" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_url_objectim.xml b/indra/newview/skins/default/xui/en/menu_url_objectim.xml
new file mode 100644
index 0000000000..35c2269b0d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_url_objectim.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Url Popup">
+ <menu_item_call
+ label="Show Object Information"
+ layout="topleft"
+ name="show_object">
+ <menu_item_call.on_click
+ function="Url.Execute" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Show on Map"
+ layout="topleft"
+ name="show_on_map">
+ <menu_item_call.on_click
+ function="Url.ShowOnMap" />
+ </menu_item_call>
+ <menu_item_call
+ label="Teleport to Object Location"
+ layout="topleft"
+ name="teleport_to_object">
+ <menu_item_call.on_click
+ function="Url.Teleport" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Copy Object Name to clipboard"
+ layout="topleft"
+ name="url_copy_label">
+ <menu_item_call.on_click
+ function="Url.CopyLabel" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy SLurl to clipboard"
+ layout="topleft"
+ name="url_copy">
+ <menu_item_call.on_click
+ function="Url.CopyUrl" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_url_parcel.xml b/indra/newview/skins/default/xui/en/menu_url_parcel.xml
new file mode 100644
index 0000000000..f477c310fb
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_url_parcel.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Url Popup">
+ <menu_item_call
+ label="Show Parcel Information"
+ layout="topleft"
+ name="show_parcel">
+ <menu_item_call.on_click
+ function="Url.Execute" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Show on Map"
+ layout="topleft"
+ name="show_on_map">
+ <menu_item_call.on_click
+ function="Url.ShowOnMap" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Copy SLurl to clipboard"
+ layout="topleft"
+ name="url_copy">
+ <menu_item_call.on_click
+ function="Url.CopyUrl" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_url_slapp.xml b/indra/newview/skins/default/xui/en/menu_url_slapp.xml
new file mode 100644
index 0000000000..6d1060b633
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_url_slapp.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Url Popup">
+ <menu_item_call
+ label="Run This Command"
+ layout="topleft"
+ name="run_slapp">
+ <menu_item_call.on_click
+ function="Url.Execute" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Copy SLurl to clipboard"
+ layout="topleft"
+ name="url_copy">
+ <menu_item_call.on_click
+ function="Url.CopyUrl" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_url_slurl.xml b/indra/newview/skins/default/xui/en/menu_url_slurl.xml
new file mode 100644
index 0000000000..98abc206a5
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_url_slurl.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Url Popup">
+ <menu_item_call
+ label="Show Place Information"
+ layout="topleft"
+ name="show_place">
+ <menu_item_call.on_click
+ function="Url.Execute" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Show on Map"
+ layout="topleft"
+ name="show_on_map">
+ <menu_item_call.on_click
+ function="Url.ShowOnMap" />
+ </menu_item_call>
+ <menu_item_call
+ label="Teleport to Location"
+ layout="topleft"
+ name="teleport_to_location">
+ <menu_item_call.on_click
+ function="Url.Teleport" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Copy SLurl to clipboard"
+ layout="topleft"
+ name="url_copy">
+ <menu_item_call.on_click
+ function="Url.CopyUrl" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_url_teleport.xml b/indra/newview/skins/default/xui/en/menu_url_teleport.xml
new file mode 100644
index 0000000000..289e32bcf4
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_url_teleport.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Url Popup">
+ <menu_item_call
+ label="Teleport to this Location"
+ layout="topleft"
+ name="teleport">
+ <menu_item_call.on_click
+ function="Url.Execute" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Show on Map"
+ layout="topleft"
+ name="show_on_map">
+ <menu_item_call.on_click
+ function="Url.ShowOnMap" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Copy SLurl to clipboard"
+ layout="topleft"
+ name="url_copy">
+ <menu_item_call.on_click
+ function="Url.CopyUrl" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
new file mode 100644
index 0000000000..a98a049c17
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -0,0 +1,3652 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu_bar
+ bg_visible="false"
+ follows="left|top|right"
+ layout="topleft"
+ name="Main Menu">
+ <menu
+ label="Me"
+ layout="topleft"
+ name="Me"
+ tear_off="true">
+ <menu_item_call
+ label="Preferences"
+ layout="topleft"
+ name="Preferences"
+ shortcut="control|P">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="preferences" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Dashboard"
+ layout="topleft"
+ name="Manage My Account">
+ <menu_item_call.on_click
+ function="PromptShowURL"
+ name="ManageMyAccount_url"
+ parameter="WebLaunchJoinNow,http://secondlife.com/account/" />
+ </menu_item_call>
+ <menu_item_call
+ label="Buy L$"
+ layout="topleft"
+ name="Buy and Sell L$">
+ <menu_item_call.on_click
+ function="BuyCurrency" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="My Profile"
+ layout="topleft"
+ name="Profile">
+ <menu_item_call.on_click
+ function="ShowAgentProfile"
+ parameter="agent" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Appearance"
+ layout="topleft"
+ name="Appearance">
+ <menu_item_call.on_click
+ function="CustomizeAvatar" />
+ <menu_item_call.on_enable
+ function="Edit.EnableCustomizeAvatar" />
+ </menu_item_call>
+ <menu_item_check
+ label="My Inventory"
+ layout="topleft"
+ name="Inventory"
+ shortcut="control|shift|I">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="inventory" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="inventory" />
+ </menu_item_check>
+ <menu_item_call
+ label="Show Inventory in Side Tray"
+ name="ShowSidetrayInventory"
+ shortcut="control|I"
+ visible="false">
+ <menu_item_call.on_click
+ function="ShowSidetrayPanel"
+ parameter="sidepanel_inventory" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Gestures"
+ layout="topleft"
+ name="Gestures"
+ shortcut="control|G">
+ <menu_item_call.on_click
+ function="Floater.Toggle"
+ parameter="gestures" />
+ </menu_item_call>
+ <menu
+ label="My Status"
+ layout="topleft"
+ name="Status"
+ tear_off="true">
+ <menu_item_call
+ label="Away"
+ layout="topleft"
+ name="Set Away">
+ <menu_item_call.on_click
+ function="World.SetAway" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"/>
+ <menu_item_call
+ label="Busy"
+ layout="topleft"
+ name="Set Busy">
+ <menu_item_call.on_click
+ function="World.SetBusy"/>
+ </menu_item_call>
+ </menu>
+ <menu_item_call
+ label="Request Admin Status"
+ layout="topleft"
+ name="Request Admin Options"
+ shortcut="control|alt|G"
+ visible="false">
+ <menu_item_call.on_click
+ function="Advanced.RequestAdminStatus" />
+ </menu_item_call>
+ <menu_item_call
+ label="Leave Admin Status"
+ layout="topleft"
+ name="Leave Admin Options"
+ shortcut="control|alt|shift|G"
+ visible="false">
+ <menu_item_call.on_click
+ function="Advanced.LeaveAdminStatus" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Quit [APP_NAME]"
+ layout="topleft"
+ name="Quit"
+ shortcut="control|Q">
+ <menu_item_call.on_click
+ function="File.Quit" />
+ </menu_item_call>
+ </menu>
+ <menu
+ label="Communicate"
+ layout="topleft"
+ name="Communicate"
+ tear_off="true">
+ <menu_item_call
+ label="My Friends"
+ layout="topleft"
+ name="My Friends"
+ shortcut="control|shift|F">
+ <menu_item_call.on_click
+ function="SideTray.PanelPeopleTab"
+ parameter="friends_panel" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Groups"
+ layout="topleft"
+ name="My Groups">
+ <menu_item_call.on_click
+ function="SideTray.PanelPeopleTab"
+ parameter="groups_panel" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <!--menu_item_call
+ label="Chat"
+ layout="topleft"
+ name="Chat">
+ <menu_item_call.on_click
+ function="World.Chat" />
+ </menu_item_call-->
+ <menu_item_check
+ label="Nearby Chat"
+ layout="topleft"
+ name="Nearby Chat"
+ shortcut="control|H">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="nearby_chat" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="nearby_chat" />
+ </menu_item_check>
+ <menu_item_call
+ label="Nearby People"
+ layout="topleft"
+ name="Active Speakers"
+ shortcut="control|shift|A">
+ <menu_item_call.on_click
+ function="SideTray.PanelPeopleTab"
+ parameter="nearby_panel" />
+ </menu_item_call>
+ <menu_item_check
+ label="Nearby Media"
+ layout="topleft"
+ name="Nearby Media"
+ shortcut="control|alt|N">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="nearby_media" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="nearby_media" />
+ </menu_item_check>
+ </menu>
+ <menu
+ label="World"
+ layout="topleft"
+ name="World"
+ tear_off="true">
+ <menu_item_check
+ label="Mini-Map"
+ layout="topleft"
+ name="Mini-Map"
+ shortcut="control|shift|M">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="mini_map" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="mini_map" />
+ </menu_item_check>
+ <menu_item_check
+ label="World Map"
+ layout="topleft"
+ name="World Map"
+ shortcut="control|M"
+ use_mac_ctrl="true">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="world_map" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="world_map" />
+ </menu_item_check>
+ <menu_item_call
+ label="Snapshot"
+ layout="topleft"
+ name="Take Snapshot"
+ shortcut="control|shift|S">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="snapshot" />
+ </menu_item_call>
+ <menu_item_call
+ label="Landmark This Place"
+ layout="topleft"
+ name="Create Landmark Here">
+ <menu_item_call.on_click
+ function="World.CreateLandmark" />
+ <menu_item_call.on_enable
+ function="World.EnableCreateLandmark" />
+ </menu_item_call>
+ <menu
+ create_jump_keys="true"
+ label="Place Profile"
+ layout="topleft"
+ name="Land"
+ tear_off="true">
+ <menu_item_call
+ label="About Land"
+ layout="topleft"
+ name="About Land">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="about_land" />
+ </menu_item_call>
+ <menu_item_call
+ label="Region/Estate"
+ layout="topleft"
+ name="Region/Estate">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="region_info" />
+ </menu_item_call>
+ </menu>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Buy This Land"
+ layout="topleft"
+ name="Buy Land">
+ <menu_item_call.on_click
+ function="Land.Buy" />
+ <menu_item_call.on_enable
+ function="World.EnableBuyLand" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Land"
+ layout="topleft"
+ name="My Land">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="land_holdings" />
+ </menu_item_call>
+ <menu
+ create_jump_keys="true"
+ label="Show"
+ layout="topleft"
+ name="LandShow"
+ tear_off="true">
+ <menu_item_check
+ label="Move Controls"
+ layout="topleft"
+ name="Movement Controls">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="moveview" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="moveview" />
+ </menu_item_check>
+ <menu_item_check
+ label="View Controls"
+ layout="topleft"
+ name="Camera Controls">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="camera" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="camera" />
+ </menu_item_check>
+ <menu_item_check
+ label="Ban Lines"
+ layout="topleft"
+ name="Ban Lines">
+ <menu_item_check.on_check
+ control="ShowBanLines" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowBanLines" />
+ </menu_item_check>
+ <menu_item_check
+ label="Beacons"
+ layout="topleft"
+ name="beacons"
+ shortcut="control|alt|shift|N">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="beacons" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="beacons" />
+ </menu_item_check>
+ <menu_item_check
+ label="Property Lines"
+ layout="topleft"
+ name="Property Lines"
+ shortcut="control|alt|shift|P">
+ <menu_item_check.on_check
+ control="ShowPropertyLines" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowPropertyLines" />
+ </menu_item_check>
+ <menu_item_check
+ label="Land Owners"
+ layout="topleft"
+ name="Land Owners">
+ <menu_item_check.on_check
+ control="ShowParcelOwners" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowParcelOwners" />
+ </menu_item_check>
+ </menu>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Teleport Home"
+ layout="topleft"
+ name="Teleport Home"
+ shortcut="control|shift|H">
+ <menu_item_call.on_click
+ function="World.TeleportHome" />
+ <menu_item_call.on_enable
+ function="World.EnableTeleportHome" />
+ </menu_item_call>
+ <menu_item_call
+ label="Set Home to Here"
+ layout="topleft"
+ name="Set Home to Here">
+ <menu_item_call.on_click
+ function="World.SetHomeLocation" />
+ <menu_item_call.on_enable
+ function="World.EnableSetHomeLocation" />
+ </menu_item_call>
+ <!-- <menu_item_check
+ label="Show Navigation Bar"
+ layout="topleft"
+ name="ShowNavbarNavigationPanel">
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowNavbarNavigationPanel" />
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="ShowNavbarNavigationPanel" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Favorites Bar"
+ layout="topleft"
+ name="ShowNavbarFavoritesPanel">
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowNavbarFavoritesPanel" />
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="ShowNavbarFavoritesPanel" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />-->
+ <menu_item_separator
+ layout="topleft" />
+ <menu
+ create_jump_keys="true"
+ label="Sun"
+ layout="topleft"
+ name="Environment Settings"
+ tear_off="true">
+ <menu_item_call
+ label="Sunrise"
+ layout="topleft"
+ name="Sunrise">
+ <menu_item_call.on_click
+ function="World.EnvSettings"
+ parameter="sunrise" />
+ </menu_item_call>
+ <menu_item_call
+ label="Midday"
+ layout="topleft"
+ name="Noon"
+ shortcut="control|shift|Y">
+ <menu_item_call.on_click
+ function="World.EnvSettings"
+ parameter="noon" />
+ </menu_item_call>
+ <menu_item_call
+ label="Sunset"
+ layout="topleft"
+ name="Sunset"
+ shortcut="control|shift|N">
+ <menu_item_call.on_click
+ function="World.EnvSettings"
+ parameter="sunset" />
+ </menu_item_call>
+ <menu_item_call
+ label="Midnight"
+ layout="topleft"
+ name="Midnight">
+ <menu_item_call.on_click
+ function="World.EnvSettings"
+ parameter="midnight" />
+ </menu_item_call>
+ <menu_item_call
+ label="Estate Time"
+ layout="topleft"
+ name="Revert to Region Default">
+ <menu_item_call.on_click
+ function="World.EnvSettings"
+ parameter="default" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Environment Editor"
+ layout="topleft"
+ name="Environment Editor">
+ <menu_item_call.on_click
+ function="World.EnvSettings"
+ parameter="editor" />
+ </menu_item_call>
+ </menu>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Build"
+ layout="topleft"
+ name="BuildTools"
+ tear_off="true"
+ visible="true">
+ <menu_item_check
+ label="Build"
+ layout="topleft"
+ name="Show Build Tools"
+ shortcut="control|B">
+ <menu_item_check.on_check
+ function="Build.Active" />
+ <menu_item_check.on_click
+ function="Build.Toggle" />
+ <menu_item_check.on_enable
+ function="Build.Enabled" />
+ </menu_item_check>
+ <menu
+ create_jump_keys="true"
+ label="Select Build Tool"
+ layout="topleft"
+ name="Select Tool"
+ tear_off="true">
+ <menu_item_call
+ label="Focus Tool"
+ layout="topleft"
+ name="Focus"
+ shortcut="control|1">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="focus" />
+ </menu_item_call>
+ <menu_item_call
+ label="Move Tool"
+ layout="topleft"
+ name="Move"
+ shortcut="control|2">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="move" />
+ </menu_item_call>
+ <menu_item_call
+ label="Edit Tool"
+ layout="topleft"
+ name="Edit"
+ shortcut="control|3">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="edit" />
+ </menu_item_call>
+ <menu_item_call
+ label="Create Tool"
+ layout="topleft"
+ name="Create"
+ shortcut="control|4">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="create" />
+ </menu_item_call>
+ <menu_item_call
+ label="Land Tool"
+ layout="topleft"
+ name="Land"
+ shortcut="control|5">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="land" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Edit"
+ layout="topleft"
+ name="Edit"
+ tear_off="true">
+ <menu_item_call
+ label="Undo"
+ layout="topleft"
+ name="Undo"
+ shortcut="control|Z">
+ <menu_item_call.on_click
+ function="Edit.Undo" />
+ <menu_item_call.on_enable
+ function="Edit.EnableUndo" />
+ </menu_item_call>
+ <menu_item_call
+ label="Redo"
+ layout="topleft"
+ name="Redo"
+ shortcut="control|Y">
+ <menu_item_call.on_click
+ function="Edit.Redo" />
+ <menu_item_call.on_enable
+ function="Edit.EnableRedo" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Cut"
+ layout="topleft"
+ name="Cut"
+ shortcut="control|X">
+ <menu_item_call.on_click
+ function="Edit.Cut" />
+ <menu_item_call.on_enable
+ function="Edit.EnableCut" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy"
+ layout="topleft"
+ name="Copy"
+ shortcut="control|C">
+ <menu_item_call.on_click
+ function="Edit.Copy" />
+ <menu_item_call.on_enable
+ function="Edit.EnableCopy" />
+ </menu_item_call>
+ <menu_item_call
+ label="Paste"
+ layout="topleft"
+ name="Paste"
+ shortcut="control|V">
+ <menu_item_call.on_click
+ function="Edit.Paste" />
+ <menu_item_call.on_enable
+ function="Edit.EnablePaste" />
+ </menu_item_call>
+ <menu_item_call
+ label="Delete"
+ layout="topleft"
+ name="Delete"
+ shortcut="Del">
+ <menu_item_call.on_click
+ function="Edit.Delete" />
+ <menu_item_call.on_enable
+ function="Edit.EnableDelete" />
+ </menu_item_call>
+ <menu_item_call
+ label="Duplicate"
+ layout="topleft"
+ name="Duplicate"
+ shortcut="control|D">
+ <menu_item_call.on_click
+ function="Edit.Duplicate" />
+ <menu_item_call.on_enable
+ function="Edit.EnableDuplicate" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Select All"
+ layout="topleft"
+ name="Select All"
+ shortcut="control|A">
+ <menu_item_call.on_click
+ function="Edit.SelectAll" />
+ <menu_item_call.on_enable
+ function="Edit.EnableSelectAll" />
+ </menu_item_call>
+ <menu_item_call
+ label="Deselect"
+ layout="topleft"
+ name="Deselect"
+ shortcut="control|E">
+ <menu_item_call.on_click
+ function="Edit.Deselect" />
+ <menu_item_call.on_enable
+ function="Edit.EnableDeselect" />
+ </menu_item_call>
+ </menu>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Link"
+ layout="topleft"
+ name="Link"
+ shortcut="control|L">
+ <menu_item_call.on_click
+ function="Tools.Link" />
+ <menu_item_call.on_enable
+ function="Tools.EnableLink" />
+ </menu_item_call>
+ <menu_item_call
+ label="Unlink"
+ layout="topleft"
+ name="Unlink"
+ shortcut="control|shift|L">
+ <menu_item_call.on_click
+ function="Tools.Unlink" />
+ <menu_item_call.on_enable
+ function="Tools.EnableUnlink" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Focus on Selection"
+ layout="topleft"
+ name="Focus on Selection"
+ shortcut="H">
+ <menu_item_call.on_click
+ function="Tools.LookAtSelection"
+ parameter="focus" />
+ <menu_item_call.on_enable
+ function="Tools.SomethingSelectedNoHUD" />
+ </menu_item_call>
+ <menu_item_call
+ label="Zoom to Selection"
+ layout="topleft"
+ name="Zoom to Selection"
+ shortcut="shift|H">
+ <menu_item_call.on_click
+ function="Tools.LookAtSelection"
+ parameter="zoom" />
+ <menu_item_call.on_enable
+ function="Tools.SomethingSelectedNoHUD" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu
+ create_jump_keys="true"
+ label="Object"
+ layout="topleft"
+ name="Object"
+ tear_off="true">
+ <menu_item_call
+ label="Buy"
+ layout="topleft"
+ name="Menu Object Take"
+ visible="true">
+ <menu_item_call.on_click
+ function="Tools.BuyOrTake" />
+ <menu_item_call.on_enable
+ function="Tools.EnableBuyOrTake"
+ name="EnableBuyOrTake"
+ parameter="Buy,Take" />
+ </menu_item_call>
+ <menu_item_call
+ label="Take Copy"
+ layout="topleft"
+ name="Take Copy">
+ <menu_item_call.on_click
+ function="Tools.TakeCopy" />
+ <menu_item_call.on_enable
+ function="Tools.EnableTakeCopy" />
+ </menu_item_call>
+ <menu_item_call
+ label="Save Back to My Inventory"
+ layout="topleft"
+ name="Save Object Back to My Inventory">
+ <menu_item_call.on_click
+ function="Tools.SaveToInventory" />
+ <menu_item_call.on_enable
+ function="Tools.EnableSaveToInventory" />
+ </menu_item_call>
+ <menu_item_call
+ label="Save Back to Object Contents"
+ layout="topleft"
+ name="Save Object Back to Object Contents">
+ <menu_item_call.on_click
+ function="Tools.SaveToObjectInventory" />
+ <menu_item_call.on_enable
+ function="Tools.EnableSaveToObjectInventory" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Scripts"
+ layout="topleft"
+ name="Scripts"
+ tear_off="true">
+ <menu_item_call
+ label="Recompile Scripts (Mono)"
+ layout="topleft"
+ name="Mono">
+ <menu_item_call.on_click
+ function="Tools.SelectedScriptAction"
+ parameter="compile mono" />
+ <menu_item_call.on_enable
+ function="EditableSelectedMono" />
+ </menu_item_call>
+ <menu_item_call
+ label="Recompile Scripts (LSL)"
+ layout="topleft"
+ name="LSL">
+ <menu_item_call.on_click
+ function="Tools.SelectedScriptAction"
+ parameter="compile lsl" />
+ <menu_item_call.on_enable
+ function="EditableSelected" />
+ </menu_item_call>
+ <menu_item_call
+ label="Reset Scripts"
+ layout="topleft"
+ name="Reset Scripts">
+ <menu_item_call.on_click
+ function="Tools.SelectedScriptAction"
+ parameter="reset" />
+ <menu_item_call.on_enable
+ function="EditableSelected" />
+ </menu_item_call>
+ <menu_item_call
+ label="Set Scripts to Running"
+ layout="topleft"
+ name="Set Scripts to Running">
+ <menu_item_call.on_click
+ function="Tools.SelectedScriptAction"
+ parameter="start" />
+ <menu_item_call.on_enable
+ function="EditableSelected" />
+ </menu_item_call>
+ <menu_item_call
+ label="Set Scripts to Not Running"
+ layout="topleft"
+ name="Set Scripts to Not Running">
+ <menu_item_call.on_click
+ function="Tools.SelectedScriptAction"
+ parameter="stop" />
+ <menu_item_call.on_enable
+ function="EditableSelected" />
+ </menu_item_call>
+ </menu>
+ <menu_item_separator
+ layout="topleft" />
+ <menu
+ create_jump_keys="true"
+ label="Options"
+ layout="topleft"
+ name="Options"
+ tear_off="true">
+ <menu_item_check
+ label="Edit Linked Parts"
+ layout="topleft"
+ name="Edit Linked Parts">
+ <menu_item_check.on_check
+ control="EditLinkedParts" />
+ <menu_item_check.on_click
+ function="Tools.EditLinkedParts"
+ parameter="EditLinkedParts" />
+ <menu_item_check.on_enable
+ function="Tools.EnableToolNotPie" />
+ </menu_item_check>
+ <menu_item_call
+ label="Set Default Upload Permissions"
+ layout="topleft"
+ name="perm prefs">
+ <menu_item_call.on_click
+ function="Floater.Toggle"
+ parameter="perm_prefs" />
+ </menu_item_call>
+ <menu_item_check
+ label="Show Advanced Permissions"
+ layout="topleft"
+ name="DebugPermissions">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DebugPermissions" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DebugPermissions" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu
+ create_jump_keys="true"
+ label="Selection"
+ layout="topleft"
+ name="Selection"
+ tear_off="true">
+ <menu_item_check
+ label="Select Only My Objects"
+ layout="topleft"
+ name="Select Only My Objects">
+ <menu_item_check.on_check
+ control="SelectOwnedOnly" />
+ <menu_item_check.on_click
+ function="Tools.SelectOnlyMyObjects"
+ parameter="agents" />
+ </menu_item_check>
+ <menu_item_check
+ label="Select Only Movable Objects"
+ layout="topleft"
+ name="Select Only Movable Objects">
+ <menu_item_check.on_check
+ control="SelectMovableOnly" />
+ <menu_item_check.on_click
+ function="Tools.SelectOnlyMovableObjects"
+ parameter="movable" />
+ </menu_item_check>
+ <menu_item_check
+ label="Select By Surrounding"
+ layout="topleft"
+ name="Select By Surrounding">
+ <menu_item_check.on_check
+ control="RectangleSelectInclusive" />
+ <menu_item_check.on_click
+ function="Tools.SelectBySurrounding" />
+ </menu_item_check>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Show"
+ layout="topleft"
+ name="Show"
+ tear_off="true">
+ <menu_item_check
+ label="Show Hidden Selection"
+ layout="topleft"
+ name="Show Hidden Selection">
+ <menu_item_check.on_check
+ control="RenderHiddenSelections" />
+ <menu_item_check.on_click
+ function="Tools.ShowHiddenSelection" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Light Radius for Selection"
+ layout="topleft"
+ name="Show Light Radius for Selection">
+ <menu_item_check.on_check
+ control="RenderLightRadius" />
+ <menu_item_check.on_click
+ function="Tools.ShowSelectionLightRadius" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Selection Beam"
+ layout="topleft"
+ name="Show Selection Beam">
+ <menu_item_check.on_check
+ control="ShowSelectionBeam" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowSelectionBeam" />
+ </menu_item_check>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Grid"
+ layout="topleft"
+ name="Grid"
+ tear_off="true">
+ <menu_item_check
+ label="Snap to Grid"
+ layout="topleft"
+ name="Snap to Grid"
+ shortcut="G">
+ <menu_item_check.on_check
+ control="SnapEnabled" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="SnapEnabled" />
+ <menu_item_check.on_enable
+ function="Tools.EnableToolNotPie" />
+ </menu_item_check>
+ <menu_item_call
+ label="Snap Object XY to Grid"
+ layout="topleft"
+ name="Snap Object XY to Grid"
+ shortcut="shift|X">
+ <menu_item_call.on_click
+ function="Tools.SnapObjectXY" />
+ <menu_item_call.on_enable
+ function="Tools.EnableToolNotPie" />
+ </menu_item_call>
+ <menu_item_call
+ label="Use Selection for Grid"
+ layout="topleft"
+ name="Use Selection for Grid"
+ shortcut="shift|G">
+ <menu_item_call.on_click
+ function="Tools.UseSelectionForGrid" />
+ <menu_item_call.on_enable
+ function="SomethingSelected" />
+ </menu_item_call>
+ <menu_item_call
+ label="Grid Options"
+ layout="topleft"
+ name="Grid Options"
+ shortcut="control|shift|B">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="build_options" />
+ <menu_item_call.on_enable
+ function="Tools.EnableToolNotPie" />
+ </menu_item_call>
+ </menu>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Select Linked Parts"
+ layout="topleft"
+ name="Select Linked Parts"
+ tear_off="true">
+ <menu_item_call
+ label="Select Next Part"
+ layout="topleft"
+ name="Select Next Part"
+ shortcut="control|.">
+ <menu_item_call.on_click
+ function="Tools.SelectNextPart"
+ parameter="next" />
+ <menu_item_call.on_enable
+ function="Tools.EnableSelectNextPart" />
+ </menu_item_call>
+ <menu_item_call
+ label="Select Previous Part"
+ layout="topleft"
+ name="Select Previous Part"
+ shortcut="control|,">
+ <menu_item_call.on_click
+ function="Tools.SelectNextPart"
+ parameter="previous" />
+ <menu_item_call.on_enable
+ function="Tools.EnableSelectNextPart" />
+ </menu_item_call>
+ <menu_item_call
+ label="Include Next Part"
+ layout="topleft"
+ name="Include Next Part"
+ shortcut="control|shift|.">
+ <menu_item_call.on_click
+ function="Tools.SelectNextPart"
+ parameter="includenext" />
+ <menu_item_call.on_enable
+ function="Tools.EnableSelectNextPart" />
+ </menu_item_call>
+ <menu_item_call
+ label="Include Previous Part"
+ layout="topleft"
+ name="Include Previous Part"
+ shortcut="control|shift|,">
+ <menu_item_call.on_click
+ function="Tools.SelectNextPart"
+ parameter="includeprevious" />
+ <menu_item_call.on_enable
+ function="Tools.EnableSelectNextPart" />
+ </menu_item_call>
+ </menu>
+ </menu>
+ <menu
+ label="Help"
+ layout="topleft"
+ name="Help"
+ tear_off="true">
+ <menu_item_call
+ label="[SECOND_LIFE] Help"
+ layout="topleft"
+ name="Second Life Help"
+ shortcut="F1">
+ <menu_item_call.on_click
+ function="ShowHelp"
+ parameter="f1_help" />
+ </menu_item_call>
+ <!-- <menu_item_call
+ label="Tutorial"
+ layout="topleft"
+ name="Tutorial">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="hud" />
+ </menu_item_call>-->
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Report Abuse"
+ layout="topleft"
+ name="Report Abuse">
+ <menu_item_call.on_click
+ function="ReportAbuse" />
+ </menu_item_call>
+ <menu_item_call
+ label="Report Bug"
+ layout="topleft"
+ name="Report Bug">
+ <menu_item_call.on_click
+ function="ShowHelp"
+ parameter="report_bug" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="About [APP_NAME]"
+ layout="topleft"
+ name="About Second Life">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="sl_about" />
+ </menu_item_call>
+ </menu>
+ <menu
+ label="Advanced"
+ layout="topleft"
+ name="Advanced"
+ tear_off="true"
+ visible="false">
+ <menu_item_call
+ label="Stop Animating Me"
+ layout="topleft"
+ name="Stop Animating My Avatar">
+ <menu_item_call.on_click
+ function="Tools.StopAllAnimations" />
+ </menu_item_call>
+ <menu_item_call
+ label="Rebake Textures"
+ layout="topleft"
+ name="Rebake Texture"
+ shortcut="control|alt|R">
+ <menu_item_call.on_click
+ function="Advanced.RebakeTextures" />
+ </menu_item_call>
+ <menu_item_call
+ label="Set UI Size to Default"
+ layout="topleft"
+ name="Set UI Size to Default">
+ <menu_item_call.on_click
+ function="View.DefaultUISize" />
+ </menu_item_call>
+ <menu_item_call
+ label="Set Window Size..."
+ name="Set Window Size...">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="window_size" />
+ </menu_item_call>
+ <menu_item_separator/>
+ <menu_item_check
+ label="Limit Select Distance"
+ layout="topleft"
+ name="Limit Select Distance">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="LimitSelectDistance" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="LimitSelectDistance" />
+ </menu_item_check>
+ <menu_item_check
+ label="Disable Camera Constraints"
+ layout="topleft"
+ name="Disable Camera Distance">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DisableCameraConstraints" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DisableCameraConstraints" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_check
+ label="High-res Snapshot"
+ layout="topleft"
+ name="HighResSnapshot">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="HighResSnapshot" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="HighResSnapshot" />
+ </menu_item_check>
+ <menu_item_check
+ label="Quiet Snapshots to Disk"
+ layout="topleft"
+ name="QuietSnapshotsToDisk">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="QuietSnapshotsToDisk" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="QuietSnapshotsToDisk" />
+ </menu_item_check>
+ <menu_item_check
+ label="Compress Snapshots to Disk"
+ layout="topleft"
+ name="CompressSnapshotsToDisk">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="CompressSnapshotsToDisk" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="CompressSnapshotsToDisk" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu
+ create_jump_keys="true"
+ label="Performance Tools"
+ layout="topleft"
+ name="Performance Tools"
+ tear_off="true">
+ <menu_item_call
+ label="Lag Meter"
+ layout="topleft"
+ name="Lag Meter">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="lagmeter" />
+ </menu_item_call>
+ <menu_item_check
+ label="Statistics Bar"
+ layout="topleft"
+ name="Statistics Bar"
+ shortcut="control|shift|1">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="stats" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="stats" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Avatar Rendering Cost"
+ layout="topleft"
+ name="Avatar Rendering Cost">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="shame" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="shame" />
+ </menu_item_check>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Highlighting and Visibility"
+ layout="topleft"
+ name="Highlighting and Visibility"
+ tear_off="true">
+ <menu_item_check
+ label="Cheesy Beacon"
+ layout="topleft"
+ name="Cheesy Beacon">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="CheesyBeacon" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="CheesyBeacon" />
+ </menu_item_check>
+ <menu_item_check
+ label="Hide Particles"
+ layout="topleft"
+ name="Hide Particles"
+ shortcut="control|alt|shift|=">
+ <menu_item_check.on_check
+ function="View.CheckRenderType"
+ parameter="hideparticles" />
+ <menu_item_check.on_click
+ function="View.ToggleRenderType"
+ parameter="hideparticles" />
+ </menu_item_check>
+ <menu_item_check
+ label="Hide Selected"
+ layout="topleft"
+ name="Hide Selected">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="HideSelectedObjects" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="HideSelectedObjects" />
+ </menu_item_check>
+ <menu_item_check
+ label="Highlight Transparent"
+ layout="topleft"
+ name="Highlight Transparent"
+ shortcut="control|alt|T">
+ <menu_item_check.on_check
+ function="View.CheckHighlightTransparent" />
+ <menu_item_check.on_click
+ function="View.HighlightTransparent" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show HUD Attachments"
+ layout="topleft"
+ name="Show HUD Attachments"
+ shortcut="alt|shift|H">
+ <menu_item_check.on_check
+ function="View.CheckHUDAttachments" />
+ <menu_item_check.on_click
+ function="View.ShowHUDAttachments" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Mouselook Crosshairs"
+ layout="topleft"
+ name="ShowCrosshairs">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="ShowCrosshairs" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowCrosshairs" />
+ </menu_item_check>
+ <!-- <menu
+ create_jump_keys="true"
+ label="Hover Tips"
+ layout="topleft"
+ name="Hover Tips"
+ tear_off="true">
+ <menu_item_check
+ label="Show Tips"
+ layout="topleft"
+ name="Show Tips"
+ shortcut="control|shift|T">
+ <menu_item_check.on_check
+ function="View.CheckShowHoverTips" />
+ <menu_item_check.on_click
+ function="View.ShowHoverTips" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />-->
+ <menu_item_check
+ label="Show Land Tooltips"
+ layout="topleft"
+ name="Land Tips">
+ <menu_item_check.on_check
+ control="ShowLandHoverTip" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowLandHoverTip" />
+ <menu_item_check.on_enable
+ function="View.CheckShowHoverTips" />
+ </menu_item_check>
+ <!-- <menu_item_check
+ label="Show Tips On All Objects"
+ layout="topleft"
+ name="Tips On All Objects">
+ <menu_item_check.on_check
+ control="ShowAllObjectHoverTip" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowAllObjectHoverTip" />
+ <menu_item_check.on_enable
+ function="View.CheckShowHoverTips" />
+ </menu_item_check>
+ </menu>-->
+
+ </menu>
+
+ <menu
+ create_jump_keys="true"
+ label="Rendering Types"
+ layout="topleft"
+ name="Rendering Types"
+ tear_off="true">
+ <menu_item_check
+ label="Simple"
+ layout="topleft"
+ name="Simple"
+ shortcut="control|alt|shift|1">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="simple" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="simple" />
+ </menu_item_check>
+ <menu_item_check
+ label="Alpha"
+ layout="topleft"
+ name="Alpha"
+ shortcut="control|alt|shift|2">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="alpha" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="alpha" />
+ </menu_item_check>
+ <menu_item_check
+ label="Tree"
+ layout="topleft"
+ name="Tree"
+ shortcut="control|alt|shift|3">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="tree" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="tree" />
+ </menu_item_check>
+ <menu_item_check
+ label="Avatars"
+ layout="topleft"
+ name="Character"
+ shortcut="control|alt|shift|4">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="character" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="character" />
+ </menu_item_check>
+ <menu_item_check
+ label="SurfacePath"
+ layout="topleft"
+ name="SurfacePath"
+ shortcut="control|alt|shift|5">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="surfacePath" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="surfacePath" />
+ </menu_item_check>
+ <menu_item_check
+ label="Sky"
+ layout="topleft"
+ name="Sky"
+ shortcut="control|alt|shift|6">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="sky" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="sky" />
+ </menu_item_check>
+ <menu_item_check
+ label="Water"
+ layout="topleft"
+ name="Water"
+ shortcut="control|alt|shift|7">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="water" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="water" />
+ </menu_item_check>
+ <menu_item_check
+ label="Ground"
+ layout="topleft"
+ name="Ground"
+ shortcut="control|alt|shift|8">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="ground" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="ground" />
+ </menu_item_check>
+ <menu_item_check
+ label="Volume"
+ layout="topleft"
+ name="Volume"
+ shortcut="control|alt|shift|9">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="volume" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="volume" />
+ </menu_item_check>
+ <menu_item_check
+ label="Grass"
+ layout="topleft"
+ name="Grass"
+ shortcut="control|alt|shift|0">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="grass" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="grass" />
+ </menu_item_check>
+ <menu_item_check
+ label="Clouds"
+ layout="topleft"
+ name="Clouds"
+ shortcut="control|alt|shift|-">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="clouds" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="clouds" />
+ </menu_item_check>
+ <menu_item_check
+ label="Particles"
+ layout="topleft"
+ name="Particles"
+ shortcut="control|alt|shift|=">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="particles" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="particles" />
+ </menu_item_check>
+ <menu_item_check
+ label="Bump"
+ layout="topleft"
+ name="Bump"
+ shortcut="control|alt|shift|\">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="bump" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="bump" />
+ </menu_item_check>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Rendering Features"
+ layout="topleft"
+ name="Rendering Features"
+ tear_off="true">
+ <menu_item_check
+ label="UI"
+ layout="topleft"
+ name="UI"
+ shortcut="control|alt|F1">
+ <menu_item_check.on_check
+ function="Advanced.CheckFeature"
+ parameter="ui" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleFeature"
+ parameter="ui" />
+ </menu_item_check>
+ <menu_item_check
+ label="Selected"
+ layout="topleft"
+ name="Selected"
+ shortcut="control|alt|F2">
+ <menu_item_check.on_check
+ function="Advanced.CheckFeature"
+ parameter="selected" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleFeature"
+ parameter="selected" />
+ </menu_item_check>
+ <menu_item_check
+ label="Highlighted"
+ layout="topleft"
+ name="Highlighted"
+ shortcut="control|alt|F3">
+ <menu_item_check.on_check
+ function="Advanced.CheckFeature"
+ parameter="highlighted" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleFeature"
+ parameter="highlighted" />
+ </menu_item_check>
+ <menu_item_check
+ label="Dynamic Textures"
+ layout="topleft"
+ name="Dynamic Textures"
+ shortcut="control|alt|F4">
+ <menu_item_check.on_check
+ function="Advanced.CheckFeature"
+ parameter="dynamic textures" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleFeature"
+ parameter="dynamic textures" />
+ </menu_item_check>
+ <menu_item_check
+ label="Foot Shadows"
+ layout="topleft"
+ name="Foot Shadows"
+ shortcut="control|alt|F5">
+ <menu_item_check.on_check
+ function="Advanced.CheckFeature"
+ parameter="foot shadows" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleFeature"
+ parameter="foot shadows" />
+ </menu_item_check>
+ <menu_item_check
+ label="Fog"
+ layout="topleft"
+ name="Fog"
+ shortcut="control|alt|F6">
+ <menu_item_check.on_check
+ function="Advanced.CheckFeature"
+ parameter="fog" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleFeature"
+ parameter="fog" />
+ </menu_item_check>
+ <menu_item_check
+ label="Test FRInfo"
+ layout="topleft"
+ name="Test FRInfo"
+ shortcut="control|alt|F8">
+ <menu_item_check.on_check
+ function="Advanced.CheckFeature"
+ parameter="fr info" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleFeature"
+ parameter="fr info" />
+ </menu_item_check>
+ <menu_item_check
+ label="Flexible Objects"
+ layout="topleft"
+ name="Flexible Objects"
+ shortcut="control|alt|F9">
+ <menu_item_check.on_check
+ function="Advanced.CheckFeature"
+ parameter="flexible" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleFeature"
+ parameter="flexible" />
+ </menu_item_check>
+ </menu>
+ <menu_item_check
+ label="Run Multiple Threads"
+ layout="topleft"
+ name="Run Multiple Threads">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RunMultipleThreads" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RunMultipleThreads" />
+ </menu_item_check>
+ <menu_item_call
+ label="Clear Group Cache"
+ layout="topleft"
+ name="ClearGroupCache">
+ <menu_item_call.on_click
+ function="Advanced.ClearGroupCache"
+ parameter="ClearGroupCache" />
+ </menu_item_call>
+ <menu_item_check
+ label="Mouse Smoothing"
+ layout="topleft"
+ name="Mouse Smoothing">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="MouseSmooth" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="MouseSmooth" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu
+ label="Shortcuts"
+ layout="topleft"
+ name="Shortcuts"
+ tear_off="true"
+ visible="false">
+ <menu_item_check
+ label="Search"
+ layout="topleft"
+ name="Search"
+ shortcut="control|F">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="search" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="search" />
+ </menu_item_check>
+ <menu_item_call
+ enabled="false"
+ label="Release Keys"
+ layout="topleft"
+ name="Release Keys">
+ <menu_item_call.on_click
+ function="Tools.ReleaseKeys"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="Tools.EnableReleaseKeys"
+ parameter="" />
+ </menu_item_call>
+ <menu_item_call
+ label="Set UI Size to Default"
+ layout="topleft"
+ name="Set UI Size to Default">
+ <menu_item_call.on_click
+ function="View.DefaultUISize" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_check
+ label="Always Run"
+ layout="topleft"
+ name="Always Run"
+ shortcut="control|R">
+ <menu_item_check.on_check
+ function="World.CheckAlwaysRun" />
+ <menu_item_check.on_click
+ function="World.AlwaysRun" />
+ </menu_item_check>
+ <menu_item_check
+ label="Fly"
+ layout="topleft"
+ name="Fly"
+ shortcut="Home">
+ <menu_item_check.on_check
+ function="Agent.getFlying" />
+ <menu_item_check.on_click
+ function="Agent.toggleFlying" />
+ <menu_item_check.on_enable
+ function="Agent.enableFlying" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Close Window"
+ layout="topleft"
+ name="Close Window"
+ shortcut="control|W">
+ <menu_item_call.on_click
+ function="File.CloseWindow" />
+ <menu_item_call.on_enable
+ function="File.EnableCloseWindow" />
+ </menu_item_call>
+ <menu_item_call
+ label="Close All Windows"
+ layout="topleft"
+ name="Close All Windows"
+ shortcut="control|shift|W">
+ <menu_item_call.on_click
+ function="File.CloseAllWindows" />
+ <menu_item_call.on_enable
+ function="File.EnableCloseAllWindows" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Snapshot to Disk"
+ layout="topleft"
+ name="Snapshot to Disk"
+ shortcut="control|`"
+ use_mac_ctrl="true">
+ <menu_item_call.on_click
+ function="File.TakeSnapshotToDisk" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Mouselook"
+ layout="topleft"
+ name="Mouselook"
+ shortcut="M">
+ <menu_item_call.on_click
+ function="View.Mouselook" />
+ <menu_item_call.on_enable
+ function="View.EnableMouselook" />
+ </menu_item_call>
+ <menu_item_check
+ label="Joystick Flycam"
+ layout="topleft"
+ name="Joystick Flycam"
+ shortcut="alt|shift|F">
+ <menu_item_check.on_check
+ function="View.CheckJoystickFlycam" />
+ <menu_item_check.on_click
+ function="View.JoystickFlycam" />
+ <menu_item_check.on_enable
+ function="View.EnableJoystickFlycam" />
+ </menu_item_check>
+ <menu_item_call
+ label="Reset View"
+ layout="topleft"
+ name="Reset View"
+ shortcut="Esc">
+ <menu_item_call.on_click
+ function="View.ResetView" />
+ </menu_item_call>
+ <menu_item_call
+ label="Look at Last Chatter"
+ layout="topleft"
+ name="Look at Last Chatter"
+ shortcut="control|\">
+ <menu_item_call.on_click
+ function="View.LookAtLastChatter" />
+ <menu_item_call.on_enable
+ function="View.EnableLastChatter" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu
+ create_jump_keys="true"
+ label="Select Build Tool"
+ layout="topleft"
+ name="Select Tool"
+ tear_off="true">
+ <menu_item_call
+ label="Focus Tool"
+ layout="topleft"
+ name="Focus"
+ shortcut="control|1">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="focus" />
+ </menu_item_call>
+ <menu_item_call
+ label="Move Tool"
+ layout="topleft"
+ name="Move"
+ shortcut="control|2">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="move" />
+ </menu_item_call>
+ <menu_item_call
+ label="Edit Tool"
+ layout="topleft"
+ name="Edit"
+ shortcut="control|3">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="edit" />
+ </menu_item_call>
+ <menu_item_call
+ label="Create Tool"
+ layout="topleft"
+ name="Create"
+ shortcut="control|4">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="create" />
+ </menu_item_call>
+ <menu_item_call
+ label="Land Tool"
+ layout="topleft"
+ name="Land"
+ shortcut="control|5">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="land" />
+ </menu_item_call>
+ </menu>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Zoom In"
+ layout="topleft"
+ name="Zoom In"
+ shortcut="control|0">
+ <menu_item_call.on_click
+ function="View.ZoomIn" />
+ </menu_item_call>
+ <menu_item_call
+ label="Zoom Default"
+ layout="topleft"
+ name="Zoom Default"
+ shortcut="control|9">
+ <menu_item_call.on_click
+ function="View.ZoomDefault" />
+ </menu_item_call>
+ <menu_item_call
+ label="Zoom Out"
+ layout="topleft"
+ name="Zoom Out"
+ shortcut="control|8">
+ <menu_item_call.on_click
+ function="View.ZoomOut" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Toggle Fullscreen"
+ layout="topleft"
+ name="Toggle Fullscreen"
+ >
+ <!-- Note: shortcut="alt|Enter" was deleted from the preceding node-->
+ <menu_item_call.on_click
+ function="View.Fullscreen" />
+ </menu_item_call>
+ </menu>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Show Debug Settings"
+ layout="topleft"
+ name="Debug Settings">
+ <menu_item_call.on_click
+ function="Advanced.ShowDebugSettings"
+ parameter="all" />
+ </menu_item_call>
+ <menu_item_check
+ label="Show Develop Menu"
+ layout="topleft"
+ name="Debug Mode"
+ shortcut="control|alt|Q">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="QAMode" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="QAMode" />
+ </menu_item_check>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Develop"
+ layout="topleft"
+ name="Develop"
+ tear_off="true"
+ visible="false">
+ <menu
+ create_jump_keys="true"
+ label="Consoles"
+ layout="topleft"
+ name="Consoles"
+ tear_off="true">
+ <menu_item_check
+ label="Texture Console"
+ layout="topleft"
+ name="Texture Console"
+ shortcut="control|shift|3"
+ use_mac_ctrl="true">
+ <menu_item_check.on_check
+ function="Advanced.CheckConsole"
+ parameter="texture" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleConsole"
+ parameter="texture" />
+ </menu_item_check>
+ <menu_item_check
+ label="Debug Console"
+ layout="topleft"
+ name="Debug Console"
+ shortcut="control|shift|4"
+ use_mac_ctrl="true">
+ <menu_item_check.on_check
+ function="Advanced.CheckConsole"
+ parameter="debug" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleConsole"
+ parameter="debug" />
+ </menu_item_check>
+ <menu_item_call
+ label="Notifications Console"
+ layout="topleft"
+ name="Notifications"
+ shortcut="control|shift|5">
+ <menu_item_call.on_click
+ function="Floater.Toggle"
+ parameter="notifications_console" />
+ </menu_item_call>
+ <menu_item_check
+ label="Texture Size Console"
+ layout="topleft"
+ name="Texture Size"
+ shortcut="control|shift|6">
+ <menu_item_check.on_check
+ function="Advanced.CheckConsole"
+ parameter="texture size" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleConsole"
+ parameter="texture size" />
+ </menu_item_check>
+ <menu_item_check
+ label="Texture Category Console"
+ layout="topleft"
+ name="Texture Category"
+ shortcut="control|shift|7">
+ <menu_item_check.on_check
+ function="Advanced.CheckConsole"
+ parameter="texture category" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleConsole"
+ parameter="texture category" />
+ </menu_item_check>
+ <menu_item_check
+ label="Fast Timers"
+ layout="topleft"
+ name="Fast Timers"
+ shortcut="control|shift|9"
+ use_mac_ctrl="true">
+ <menu_item_check.on_check
+ function="Advanced.CheckConsole"
+ parameter="fast timers" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleConsole"
+ parameter="fast timers" />
+ </menu_item_check>
+ <menu_item_check
+ label="Memory"
+ layout="topleft"
+ name="Memory"
+ shortcut="control|shift|0"
+ use_mac_ctrl="true">
+ <menu_item_check.on_check
+ function="Advanced.CheckConsole"
+ parameter="memory view" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleConsole"
+ parameter="memory view" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Region Info to Debug Console"
+ layout="topleft"
+ name="Region Info to Debug Console">
+ <menu_item_call.on_click
+ function="Advanced.DumpInfoToConsole"
+ parameter="region" />
+ </menu_item_call>
+ <menu_item_call
+ label="Group Info to Debug Console"
+ layout="topleft"
+ name="Group Info to Debug Console">
+ <menu_item_call.on_click
+ function="Advanced.DumpInfoToConsole"
+ parameter="group" />
+ </menu_item_call>
+ <menu_item_call
+ label="Capabilities Info to Debug Console"
+ layout="topleft"
+ name="Capabilities Info to Debug Console">
+ <menu_item_call.on_click
+ function="Advanced.DumpInfoToConsole"
+ parameter="capabilities" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_check
+ label="Camera"
+ layout="topleft"
+ name="Camera">
+ <menu_item_check.on_check
+ function="Advanced.CheckHUDInfo"
+ parameter="camera" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleHUDInfo"
+ parameter="camera" />
+ </menu_item_check>
+ <menu_item_check
+ label="Wind"
+ layout="topleft"
+ name="Wind">
+ <menu_item_check.on_check
+ function="Advanced.CheckHUDInfo"
+ parameter="wind" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleHUDInfo"
+ parameter="wind" />
+ </menu_item_check>
+ <menu_item_check
+ label="FOV"
+ layout="topleft"
+ name="FOV">
+ <menu_item_check.on_check
+ function="Advanced.CheckHUDInfo"
+ parameter="fov" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleHUDInfo"
+ parameter="fov" />
+ </menu_item_check>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Show Info"
+ layout="topleft"
+ name="Display Info"
+ tear_off="true">
+ <menu_item_check
+ label="Show Time"
+ layout="topleft"
+ name="Show Time">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DebugShowTime" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DebugShowTime" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Render Info"
+ layout="topleft"
+ name="Show Render Info">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DebugShowRenderInfo" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DebugShowRenderInfo" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Matrices"
+ layout="topleft"
+ name="Show Matrices">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DebugShowRenderMatrices" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DebugShowRenderMatrices" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Color Under Cursor"
+ layout="topleft"
+ name="Show Color Under Cursor">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DebugShowColor" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DebugShowColor" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_check
+ label="Show Updates to Objects"
+ layout="topleft"
+ name="Show Updates"
+ shortcut="control|alt|shift|U">
+ <menu_item_check.on_check
+ function="Advanced.CheckShowObjectUpdates"
+ parameter="ObjectUpdates" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleShowObjectUpdates" />
+ </menu_item_check>
+ </menu>
+ <menu_item_separator
+ layout="topleft" />
+ <menu
+ create_jump_keys="true"
+ label="Force an Error"
+ layout="topleft"
+ name="Force Errors"
+ tear_off="true">
+ <menu_item_call
+ label="Force Breakpoint"
+ layout="topleft"
+ name="Force Breakpoint"
+ shortcut="control|alt|shift|B">
+ <menu_item_call.on_click
+ function="Advanced.ForceErrorBreakpoint" />
+ </menu_item_call>
+ <menu_item_call
+ label="Force LLError And Crash"
+ layout="topleft"
+ name="Force LLError And Crash">
+ <menu_item_call.on_click
+ function="Advanced.ForceErrorLlerror" />
+ </menu_item_call>
+ <menu_item_call
+ label="Force Bad Memory Access"
+ layout="topleft"
+ name="Force Bad Memory Access">
+ <menu_item_call.on_click
+ function="Advanced.ForceErrorBadMemoryAccess" />
+ </menu_item_call>
+ <menu_item_call
+ label="Force Infinite Loop"
+ layout="topleft"
+ name="Force Infinite Loop">
+ <menu_item_call.on_click
+ function="Advanced.ForceErrorInfiniteLoop" />
+ </menu_item_call>
+ <menu_item_call
+ label="Force Driver Crash"
+ layout="topleft"
+ name="Force Driver Carsh">
+ <menu_item_call.on_click
+ function="Advanced.ForceErrorDriverCrash" />
+ </menu_item_call>
+ <menu_item_call
+ label="Force Software Exception"
+ layout="topleft"
+ name="Force Software Exception">
+ <menu_item_call.on_click
+ function="Advanced.ForceErrorSoftwareException" />
+ </menu_item_call>
+ <menu_item_call
+ label="Force Disconnect Viewer"
+ layout="topleft"
+ name="Force Disconnect Viewer">
+ <menu_item_call.on_click
+ function="Advanced.ForceErrorDisconnectViewer" />
+ </menu_item_call>
+ <menu_item_call
+ label="Simulate a Memory Leak"
+ layout="topleft"
+ name="Memory Leaking Simulation">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="mem_leaking" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Render Tests"
+ layout="topleft"
+ name="Render Tests"
+ tear_off="true">
+ <menu_item_check
+ label="Camera Offset"
+ layout="topleft"
+ name="Camera Offset">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="CameraOffset" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="CameraOffset" />
+ </menu_item_check>
+ <menu_item_check
+ label="Randomize Framerate"
+ layout="topleft"
+ name="Randomize Framerate">
+ <menu_item_check.on_check
+ function="Advanced.CheckRandomizeFramerate"
+ parameter="Randomize Framerate" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRandomizeFramerate" />
+ </menu_item_check>
+ <menu_item_check
+ label="Periodic Slow Frame"
+ layout="topleft"
+ name="Periodic Slow Frame">
+ <menu_item_check.on_check
+ function="Advanced.CheckPeriodicSlowFrame"
+ parameter="points" />
+ <menu_item_check.on_click
+ function="Advanced.TogglePeriodicSlowFrame"
+ parameter="points" />
+ </menu_item_check>
+ <menu_item_check
+ label="Frame Test"
+ layout="topleft"
+ name="Frame Test">
+ <menu_item_check.on_check
+ function="Advanced.CheckFrameTest"
+ parameter="Frame Test" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleFrameTest" />
+ </menu_item_check>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Render Metadata"
+ layout="topleft"
+ name="Render Metadata"
+ tear_off="true">
+ <menu_item_check
+ label="Bounding Boxes"
+ layout="topleft"
+ name="Bounding Boxes">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="bboxes" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="bboxes" />
+ </menu_item_check>
+ <menu_item_check
+ label="Octree"
+ layout="topleft"
+ name="Octree">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="octree" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="octree" />
+ </menu_item_check>
+ <menu_item_check
+ label="Shadow Frusta"
+ layout="topleft"
+ name="Shadow Frusta">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="shadow frusta" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="shadow frusta" />
+ </menu_item_check>
+ <menu_item_check
+ label="Occlusion"
+ layout="topleft"
+ name="Occlusion">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="occlusion" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="occlusion" />
+ </menu_item_check>
+ <menu_item_check
+ label="Render Batches"
+ layout="topleft"
+ name="Render Batches">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="render batches" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="render batches" />
+ </menu_item_check>
+ <menu_item_check
+ label="Texture Anim"
+ layout="topleft"
+ name="Texture Anim">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="texture anim" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="texture anim" />
+ </menu_item_check>
+ <menu_item_check
+ label="Texture Priority"
+ layout="topleft"
+ name="Texture Priority">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="texture priority" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="texture priority" />
+ </menu_item_check>
+ <menu_item_check
+ label="Texture Area"
+ layout="topleft"
+ name="Texture Area">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="texture area" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="texture area" />
+ </menu_item_check>
+ <menu_item_check
+ label="Face Area"
+ layout="topleft"
+ name="Face Area">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="face area" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="face area" />
+ </menu_item_check>
+ <menu_item_check
+ label="Lights"
+ layout="topleft"
+ name="Lights">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="lights" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="lights" />
+ </menu_item_check>
+ <menu_item_check
+ label="Collision Skeleton"
+ layout="topleft"
+ name="Collision Skeleton">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="collision skeleton" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="collision skeleton" />
+ </menu_item_check>
+ <menu_item_check
+ label="Raycast"
+ layout="topleft"
+ name="Raycast">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="raycast" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="raycast" />
+ </menu_item_check>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Rendering"
+ layout="topleft"
+ name="Rendering"
+ tear_off="true">
+ <menu_item_check
+ label="Axes"
+ name="Axes">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="ShowAxes" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowAxes" />
+ </menu_item_check>
+ <menu_item_check
+ label="Tangent Basis"
+ name="Tangent Basis">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="ShowTangentBasis" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowTangentBasis" />
+ </menu_item_check>
+ <menu_item_call
+ label="Selected Texture Info Basis"
+ name="Selected Texture Info Basis"
+ shortcut="control|alt|shift|T">
+ <menu_item_call.on_click
+ function="Advanced.SelectedTextureInfo" />
+ </menu_item_call>
+ <menu_item_check
+ label="Wireframe"
+ name="Wireframe"
+ shortcut="control|shift|R">
+ <menu_item_check.on_check
+ function="Advanced.CheckWireframe"
+ parameter="Wireframe" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleWireframe" />
+ </menu_item_check>
+ <menu_item_check
+ label="Object-Object Occlusion"
+ name="Object-Object Occlusion"
+ shortcut="control|shift|O">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="UseOcclusion" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="UseOcclusion" />
+ <menu_item_check.on_enable
+ function="Advanced.EnableObjectObjectOcclusion" />
+ </menu_item_check>
+ <menu_item_check
+ label="Framebuffer Objects"
+ name="Framebuffer Objects">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderUseFBO" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderUseFBO" />
+ <menu_item_check.on_enable
+ function="Advanced.EnableRenderFBO" />
+ </menu_item_check>
+ <menu_item_check
+ label="Deferred Rendering"
+ name="Deferred Rendering">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderDeferred" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderDeferred" />
+ <menu_item_check.on_enable
+ function="Advanced.EnableRenderDeferred" />
+ </menu_item_check>
+ <menu_item_check
+ label="Global Illumination"
+ name="Global Illumination">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderDeferredGI" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderDeferredGI" />
+ <menu_item_check.on_enable
+ function="Advanced.EnableRenderDeferredGI" />
+ </menu_item_check>
+ <menu_item_separator />
+ <menu_item_check
+ label="Debug GL"
+ name="Debug GL">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderDebugGL" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderDebugGL" />
+ </menu_item_check>
+ <menu_item_check
+ label="Debug Pipeline"
+ name="Debug Pipeline">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderDebugPipeline" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderDebugPipeline" />
+ </menu_item_check>
+ <menu_item_check
+ label="Fast Alpha"
+ name="Fast Alpha">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderFastAlpha" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderFastAlpha" />
+ </menu_item_check>
+ <menu_item_check
+ label="Animation Textures"
+ name="Animation Textures">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="AnimateTextures" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="AnimateTextures" />
+ </menu_item_check>
+ <menu_item_check
+ label="Disable Textures"
+ name="Disable Textures">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="TextureDisable" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="TextureDisable" />
+ </menu_item_check>
+ <menu_item_check
+ label="Full Res Textures"
+ layout="topleft"
+ name="Rull Res Textures">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="TextureLoadFullRes" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="TextureLoadFullRes" />
+ </menu_item_check>
+ <menu_item_check
+ label="Audit Textures"
+ layout="topleft"
+ name="Audit Textures">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="AuditTexture" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="AuditTexture" />
+ </menu_item_check>
+ <menu_item_check
+ label="Texture Atlas"
+ name="Texture Atlas">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="EnableTextureAtlas" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="EnableTextureAtlas" />
+ </menu_item_check>
+ <menu_item_check
+ label="Render Attached Lights"
+ name="Render Attached Lights">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderAttachedLights" />
+ <menu_item_check.on_click
+ function="Advanced.HandleAttachedLightParticles"
+ parameter="RenderAttachedLights" />
+ </menu_item_check>
+ <menu_item_check
+ label="Render Attached Particles"
+ name="Render Attached Particles">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderAttachedParticles" />
+ <menu_item_check.on_click
+ function="Advanced.HandleAttachedLightParticles"
+ parameter="RenderAttachedParticles" />
+ </menu_item_check>
+ <menu_item_check
+ label="Hover Glow Objects"
+ name="Hover Glow Objects">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderHoverGlowEnable" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderHoverGlowEnable" />
+ </menu_item_check>
+ </menu>
+
+ <menu
+ create_jump_keys="true"
+ label="Network"
+ layout="topleft"
+ name="Network"
+ tear_off="true">
+ <menu_item_check
+ label="Pause Agent"
+ layout="topleft"
+ name="AgentPause">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="AgentPause" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="AgentPause" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Enable Message Log"
+ layout="topleft"
+ name="Enable Message Log">
+ <menu_item_call.on_click
+ function="Advanced.EnableMessageLog" />
+ </menu_item_call>
+ <menu_item_call
+ label="Disable Message Log"
+ layout="topleft"
+ name="Disable Message Log">
+ <menu_item_call.on_click
+ function="Advanced.DisableMessageLog" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_check
+ label="Velocity Interpolate Objects"
+ layout="topleft"
+ name="Velocity Interpolate Objects">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="VelocityInterpolate" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="VelocityInterpolate" />
+ </menu_item_check>
+ <menu_item_check
+ label="Ping Interpolate Object Positions"
+ layout="topleft"
+ name="Ping Interpolate Object Positions">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="PingInterpolate" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="PingInterpolate" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Drop a Packet"
+ layout="topleft"
+ name="Drop a Packet"
+ shortcut="control|alt|L">
+ <menu_item_call.on_click
+ function="Advanced.DropPacket" />
+ </menu_item_call>
+ </menu>
+ <menu_item_call
+ label="Dump Scripted Camera"
+ layout="topleft"
+ name="Dump Scripted Camera">
+ <menu_item_call.on_click
+ function="Advanced.DumpScriptedCamera" />
+ </menu_item_call>
+ <menu_item_call
+ label="Bumps, Pushes &amp; Hits"
+ layout="topleft"
+ name="Bumps, Pushes &amp;amp; Hits">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="bumps" />
+ </menu_item_call>
+
+ <menu
+ create_jump_keys="true"
+ label="Recorder"
+ layout="topleft"
+ name="Recorder"
+ tear_off="true">
+ <menu_item_call
+ label="Start Playback"
+ layout="topleft"
+ name="Start Playback">
+ <menu_item_call.on_click
+ function="Advanced.AgentPilot"
+ parameter="start playback" />
+ </menu_item_call>
+ <menu_item_call
+ label="Stop Playback"
+ layout="topleft"
+ name="Stop Playback">
+ <menu_item_call.on_click
+ function="Advanced.AgentPilot"
+ parameter="stop playback" />
+ </menu_item_call>
+ <menu_item_check
+ label="Loop Playback"
+ layout="topleft"
+ name="Loop Playback">
+ <menu_item_check.on_check
+ function="Advanced.CheckAgentPilotLoop"
+ parameter="loopPlayback" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleAgentPilotLoop" />
+ </menu_item_check>
+ <menu_item_call
+ label="Start Record"
+ layout="topleft"
+ name="Start Record">
+ <menu_item_call.on_click
+ function="Advanced.AgentPilot"
+ parameter="start record" />
+ </menu_item_call>
+ <menu_item_call
+ label="Stop Record"
+ layout="topleft"
+ name="Stop Record">
+ <menu_item_call.on_click
+ function="Advanced.AgentPilot"
+ parameter="stop record" />
+ </menu_item_call>
+ </menu>
+
+ <menu
+ create_jump_keys="true"
+ label="World"
+ layout="topleft"
+ name="World"
+ tear_off="true">
+ <menu_item_check
+ label="Sim Sun Override"
+ layout="topleft"
+ name="Sim Sun Override">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="SkyOverrideSimSunPosition" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="SkyOverrideSimSunPosition" />
+ </menu_item_check>
+ <menu_item_check
+ label="Cheesy Beacon"
+ layout="topleft"
+ name="Cheesy Beacon">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="CheesyBeacon" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="CheesyBeacon" />
+ </menu_item_check>
+ <menu_item_check
+ label="Fixed Weather"
+ layout="topleft"
+ name="Fixed Weather">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="FixedWeather" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="FixedWeather" />
+ </menu_item_check>
+ <menu_item_call
+ label="Dump Region Object Cache"
+ layout="topleft"
+ name="Dump Region Object Cache">
+ <menu_item_call.on_click
+ function="Advanced.DumpRegionObjectCache" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="UI"
+ layout="topleft"
+ name="UI"
+ tear_off="true">
+ <!-- <menu_item_check
+ label="New Bottom Bar"
+ layout="topleft"
+ name="New Bottom Bar">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="BottomPanelNew" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="BottomPanelNew" />
+ </menu_item_check>-->
+ <menu_item_call
+ label="Web Browser Test"
+ layout="topleft"
+ name="Web Browser Test">
+ <menu_item_call.on_click
+ function="Advanced.WebBrowserTest"
+ parameter="http://secondlife.com/app/search/slurls.html"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Dump SelectMgr"
+ layout="topleft"
+ name="Dump SelectMgr">
+ <menu_item_call.on_click
+ function="Advanced.DumpSelectMgr" />
+ </menu_item_call>
+ <menu_item_call
+ label="Dump Inventory"
+ layout="topleft"
+ name="Dump Inventory">
+ <menu_item_call.on_click
+ function="Advanced.DumpInventory" />
+ </menu_item_call>
+ <menu_item_call
+ label="Dump Timers"
+ name="Dump Timers">
+ <menu_item_call.on_click
+ function="Advanced.DumpTimers" />
+ </menu_item_call>
+ <menu_item_call
+ label="Dump Focus Holder"
+ layout="topleft"
+ name="Dump Focus Holder">
+ <menu_item_call.on_click
+ function="Advanced.DumpFocusHolder" />
+ </menu_item_call>
+ <menu_item_call
+ label="Print Selected Object Info"
+ layout="topleft"
+ name="Print Selected Object Info"
+ shortcut="control|shift|P">
+ <menu_item_call.on_click
+ function="Advanced.PrintSelectedObjectInfo" />
+ </menu_item_call>
+ <menu_item_call
+ label="Print Agent Info"
+ layout="topleft"
+ name="Print Agent Info"
+ shortcut="shift|P">
+ <menu_item_call.on_click
+ function="Advanced.PrintAgentInfo" />
+ </menu_item_call>
+ <menu_item_call
+ label="Memory Stats"
+ layout="topleft"
+ name="Memory Stats"
+ shortcut="control|alt|shift|M">
+ <menu_item_call.on_click
+ function="Advanced.PrintTextureMemoryStats" />
+ </menu_item_call>
+ <menu_item_check
+ label="Double-ClickAuto-Pilot"
+ layout="topleft"
+ name="Double-ClickAuto-Pilot">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DoubleClickAutoPilot" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DoubleClickAutoPilot" />
+ </menu_item_check>
+
+ <menu_item_separator />
+ <menu_item_check
+ label="Debug SelectMgr"
+ layout="topleft"
+ name="Debug SelectMgr">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DebugSelectMgr" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DebugSelectMgr" />
+ </menu_item_check>
+ <menu_item_check
+ label="Debug Clicks"
+ layout="topleft"
+ name="Debug Clicks">
+ <menu_item_check.on_check
+ function="Advanced.CheckDebugClicks"
+ parameter="DebugClicks" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleDebugClicks"
+ parameter="DebugClicks" />
+ </menu_item_check>
+ <menu_item_check
+ label="Debug Views"
+ layout="topleft"
+ name="Debug Views">
+ <menu_item_check.on_check
+ function="Advanced.CheckDebugViews" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleDebugViews" />
+ </menu_item_check>
+ <menu_item_check
+ label="Debug Name Tooltips"
+ layout="topleft"
+ name="Debug Name Tooltips">
+ <menu_item_check.on_check
+ function="Advanced.CheckXUINameTooltips"
+ parameter="XUINameTooltips" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleXUINameTooltips" />
+ </menu_item_check>
+ <menu_item_check
+ label="Debug Mouse Events"
+ layout="topleft"
+ name="Debug Mouse Events">
+ <menu_item_check.on_check
+ function="Advanced.CheckDebugMouseEvents"
+ parameter="MouseEvents" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleDebugMouseEvents" />
+ </menu_item_check>
+ <menu_item_check
+ label="Debug Keys"
+ layout="topleft"
+ name="Debug Keys">
+ <menu_item_check.on_check
+ function="Advanced.CheckDebugKeys"
+ parameter="DebugKeys" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleDebugKeys" />
+ </menu_item_check>
+ <menu_item_check
+ label="Debug WindowProc"
+ layout="topleft"
+ name="Debug WindowProc">
+ <menu_item_check.on_check
+ function="Advanced.CheckDebugWindowProc"
+ parameter="DebugWindowProc" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleDebugWindowProc"
+ parameter="DebugWindowProc" />
+ </menu_item_check>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="XUI"
+ name="XUI"
+ tear_off="true">
+ <menu_item_call
+ label="Reload Color Settings"
+ layout="topleft"
+ name="Reload Color Settings">
+ <menu_item_call.on_click
+ function="Advanced.ReloadColorSettings" />
+ </menu_item_call>
+ <menu_item_call
+ label="Show Font Test"
+ layout="topleft"
+ name="Show Font Test">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="font_test" />
+ </menu_item_call>
+ <menu_item_call
+ label="Load from XML"
+ layout="topleft"
+ name="Load from XML">
+ <menu_item_call.on_click
+ function="Advanced.LoadUIFromXML" />
+ </menu_item_call>
+ <menu_item_call
+ label="Save to XML"
+ layout="topleft"
+ name="Save to XML">
+ <menu_item_call.on_click
+ function="Advanced.SaveUIToXML" />
+ </menu_item_call>
+ <menu_item_check
+ label="Show XUI Names"
+ layout="topleft"
+ name="Show XUI Names">
+ <menu_item_check.on_check
+ function="Advanced.CheckXUINames"
+ parameter="showUIname" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleXUINames" />
+ </menu_item_check>
+ <menu_item_call
+ label="Send Test IMs"
+ layout="topleft"
+ name="Send Test IMs">
+ <menu_item_call.on_click
+ function="Advanced.SendTestIMs" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Avatar"
+ layout="topleft"
+ name="Character"
+ tear_off="true">
+ <menu
+ create_jump_keys="true"
+ label="Grab Baked Texture"
+ layout="topleft"
+ name="Grab Baked Texture"
+ tear_off="true">
+ <menu_item_call
+ label="Iris"
+ layout="topleft"
+ name="Iris">
+ <menu_item_call.on_click
+ function="Advanced.GrabBakedTexture"
+ parameter="iris" />
+ <menu_item_call.on_enable
+ function="Advanced.EnableGrabBakedTexture"
+ parameter="iris" />
+ </menu_item_call>
+ <menu_item_call
+ label="Head"
+ layout="topleft"
+ name="Head">
+ <menu_item_call.on_click
+ function="Advanced.GrabBakedTexture"
+ parameter="head" />
+ <menu_item_call.on_enable
+ function="Advanced.EnableGrabBakedTexture"
+ parameter="head" />
+ </menu_item_call>
+ <menu_item_call
+ label="Upper Body"
+ layout="topleft"
+ name="Upper Body">
+ <menu_item_call.on_click
+ function="Advanced.GrabBakedTexture"
+ parameter="upper" />
+ <menu_item_call.on_enable
+ function="Advanced.EnableGrabBakedTexture"
+ parameter="upper" />
+ </menu_item_call>
+ <menu_item_call
+ label="Lower Body"
+ layout="topleft"
+ name="Lower Body">
+ <menu_item_call.on_click
+ function="Advanced.GrabBakedTexture"
+ parameter="lower" />
+ <menu_item_call.on_enable
+ function="Advanced.EnableGrabBakedTexture"
+ parameter="lower" />
+ </menu_item_call>
+ <menu_item_call
+ label="Skirt"
+ layout="topleft"
+ name="Skirt">
+ <menu_item_call.on_click
+ function="Advanced.GrabBakedTexture"
+ parameter="skirt" />
+ <menu_item_call.on_enable
+ function="Advanced.EnableGrabBakedTexture"
+ parameter="skirt" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Character Tests"
+ layout="topleft"
+ name="Character Tests"
+ tear_off="true">
+ <menu_item_call
+ label="Appearance To XML"
+ layout="topleft"
+ name="Appearance To XML">
+ <menu_item_call.on_click
+ function="Advanced.AppearanceToXML" />
+ </menu_item_call>
+ <menu_item_call
+ label="Toggle Character Geometry"
+ layout="topleft"
+ name="Toggle Character Geometry">
+ <menu_item_call.on_click
+ function="Advanced.ToggleCharacterGeometry" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ <menu_item_call
+ label="Test Male"
+ layout="topleft"
+ name="Test Male">
+ <menu_item_call.on_click
+ function="Advanced.TestMale" />
+ </menu_item_call>
+ <menu_item_call
+ label="Test Female"
+ layout="topleft"
+ name="Test Female">
+ <menu_item_call.on_click
+ function="Advanced.TestFemale" />
+ </menu_item_call>
+ <menu_item_call
+ label="Toggle PG"
+ layout="topleft"
+ name="Toggle PG">
+ <menu_item_call.on_click
+ function="Advanced.TogglePG" />
+ </menu_item_call>
+ <menu_item_check
+ label="Allow Select Avatar"
+ layout="topleft"
+ name="Allow Select Avatar">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="AllowSelectAvatar" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="AllowSelectAvatar" />
+ </menu_item_check>
+ </menu>
+ <menu_item_call
+ label="Force Params to Default"
+ layout="topleft"
+ name="Force Params to Default">
+ <menu_item_call.on_click
+ function="Advanced.ForceParamsToDefault" />
+ </menu_item_call>
+ <menu_item_check
+ label="Animation Info"
+ layout="topleft"
+ name="Animation Info">
+ <menu_item_check.on_check
+ function="Advanced.CheckAnimationInfo"
+ parameter="AnimationInfo" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleAnimationInfo"
+ parameter="" />
+ </menu_item_check>
+ <menu_item_check
+ label="Slow Motion Animations"
+ layout="topleft"
+ name="Slow Motion Animations">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="SlowMotionAnimation" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="SlowMotionAnimation" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Look At"
+ layout="topleft"
+ name="Show Look At">
+ <menu_item_check.on_check
+ function="Advanced.CheckShowLookAt"
+ parameter="ShowLookAt" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleShowLookAt" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Point At"
+ layout="topleft"
+ name="Show Point At">
+ <menu_item_check.on_check
+ function="Advanced.CheckShowPointAt"
+ parameter="ShowPointAt" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleShowPointAt" />
+ </menu_item_check>
+ <menu_item_check
+ label="Debug Joint Updates"
+ layout="topleft"
+ name="Debug Joint Updates">
+ <menu_item_check.on_check
+ function="Advanced.CheckDebugJointUpdates"
+ parameter="DebugJointUpdates" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleDebugJointUpdates" />
+ </menu_item_check>
+ <menu_item_check
+ label="Disable LOD"
+ layout="topleft"
+ name="Disable LOD">
+ <menu_item_check.on_check
+ function="Advanced.CheckDisableLOD"
+ parameter="DisableLOD" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleDisableLOD" />
+ </menu_item_check>
+ <menu_item_check
+ label="Debug Character Vis"
+ layout="topleft"
+ name="Debug Character Vis">
+ <menu_item_check.on_check
+ function="Advanced.CheckDebugCharacterVis"
+ parameter="DebugCharacterVis" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleDebugCharacterVis" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Collision Skeleton"
+ layout="topleft"
+ name="Show Collision Skeleton">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="collision skeleton" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="collision skeleton" />
+ </menu_item_check>
+ <menu_item_check
+ label="Display Agent Target"
+ layout="topleft"
+ name="Display Agent Target">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="agent target" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="agent target" />
+ </menu_item_check>
+<!-- Appears not to exist anymore
+ <menu_item_check
+ label="Debug Rotation"
+ layout="topleft"
+ name="Debug Rotation">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DebugAvatarRotation" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DebugAvatarRotation" />
+ </menu_item_check> -->
+-->
+ <menu_item_call
+ label="Dump Attachments"
+ layout="topleft"
+ name="Dump Attachments">
+ <menu_item_call.on_click
+ function="Advanced.DumpAttachments" />
+ </menu_item_call>
+ <menu_item_call
+ label="Debug Avatar Textures"
+ layout="topleft"
+ name="Debug Avatar Textures"
+ shortcut="control|alt|shift|A">
+ <menu_item_call.on_click
+ function="Advanced.DebugAvatarTextures" />
+ </menu_item_call>
+ <menu_item_call
+ label="Dump Local Textures"
+ layout="topleft"
+ name="Dump Local Textures"
+ shortcut="alt|shift|M">
+ <menu_item_call.on_click
+ function="Advanced.DumpAvatarLocalTextures" />
+ </menu_item_call>
+ </menu>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_check
+ label="HTTP Textures"
+ layout="topleft"
+ name="HTTP Textures">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="ImagePipelineUseHTTP" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ImagePipelineUseHTTP" />
+ </menu_item_check>
+ <menu_item_call
+ label="Compress Images"
+ layout="topleft"
+ name="Compress Images">
+ <menu_item_call.on_click
+ function="Advanced.CompressImage" />
+ </menu_item_call>
+ <menu_item_check
+ label="Output Debug Minidump"
+ layout="topleft"
+ name="Output Debug Minidump">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="SaveMinidump" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="SaveMinidump" />
+ </menu_item_check>
+ <menu_item_check
+ label="Console Window on next Run"
+ layout="topleft"
+ name="Console Window">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="ShowConsoleWindow" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowConsoleWindow" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_check
+ label="Show Admin Menu"
+ layout="topleft"
+ name="View Admin Options">
+ <menu_item_check.on_check
+ function="Advanced.CheckViewAdminOptions"
+ parameter="ViewAdminOptions" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleViewAdminOptions" />
+ </menu_item_check>
+ <menu_item_call
+ label="Request Admin Status"
+ layout="topleft"
+ name="Request Admin Options"
+ shortcut="control|alt|G">
+ <menu_item_call.on_click
+ function="Advanced.RequestAdminStatus" />
+ </menu_item_call>
+ <menu_item_call
+ label="Leave Admin Status"
+ layout="topleft"
+ name="Leave Admin Options"
+ shortcut="control|alt|shift|G">
+ <menu_item_call.on_click
+ function="Advanced.LeaveAdminStatus" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Admin"
+ layout="topleft"
+ name="Admin"
+ tear_off="true"
+ visible="false">
+ <menu
+ create_jump_keys="true"
+ label="Object"
+ layout="topleft"
+ tear_off="true">
+ <menu_item_call
+ label="Take Copy"
+ layout="topleft"
+ name="Take Copy"
+ shortcut="control|alt|shift|O">
+ <menu_item_call.on_click
+ function="Admin.ForceTakeCopy" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ <menu_item_call
+ label="Force Owner To Me"
+ layout="topleft"
+ name="Force Owner To Me">
+ <menu_item_call.on_click
+ function="Admin.HandleObjectOwnerSelf" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ <menu_item_call
+ label="Force Owner Permissive"
+ layout="topleft"
+ name="Force Owner Permissive">
+ <menu_item_call.on_click
+ function="Admin.HandleObjectOwnerPermissive" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ <menu_item_call
+ label="Delete"
+ layout="topleft"
+ name="Delete"
+ shortcut="control|alt|shift|Del">
+ <menu_item_call.on_click
+ function="Admin.HandleForceDelete" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ <menu_item_call
+ label="Lock"
+ layout="topleft"
+ name="Lock"
+ shortcut="control|alt|shift|L">
+ <menu_item_call.on_click
+ function="Admin.HandleObjectLock" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ <menu_item_call
+ label="Get Assets IDs"
+ layout="topleft"
+ name="Get Assets IDs"
+ shortcut="control|alt|shift|I">
+ <menu_item_call.on_click
+ function="Admin.HandleObjectAssetIDs" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Parcel"
+ layout="topleft"
+ name="Parcel"
+ tear_off="true">
+ <menu_item_call
+ label="Force Owner To Me"
+ layout="topleft"
+ name="Owner To Me">
+ <menu_item_call.on_click
+ function="Admin.HandleForceParcelOwnerToMe" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ <menu_item_call
+ label="Set to Linden Content"
+ layout="topleft"
+ name="Set to Linden Content"
+ shortcut="control|alt|shift|C">
+ <menu_item_call.on_click
+ function="Admin.HandleForceParcelToContent" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ <menu_item_call
+ label="Claim Public Land"
+ layout="topleft"
+ name="Claim Public Land">
+ <menu_item_call.on_click
+ function="Admin.HandleClaimPublicLand" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Region"
+ layout="topleft"
+ name="Region"
+ tear_off="true">
+ <menu_item_call
+ label="Dump Temp Asset Data"
+ layout="topleft"
+ name="Dump Temp Asset Data">
+ <menu_item_call.on_click
+ function="Admin.HandleRegionDumpTempAssetData" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ <menu_item_call
+ label="Save Region State"
+ layout="topleft"
+ name="Save Region State">
+ <menu_item_call.on_click
+ function="Admin.OnSaveState" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ </menu>
+ <menu_item_call
+ label="God Tools"
+ layout="topleft"
+ name="God Tools">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="god_tools" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Admin"
+ layout="topleft"
+ name="Deprecated"
+ tear_off="true"
+ visible="false">
+ <menu
+ create_jump_keys="true"
+ label="Attach Object"
+ layout="topleft"
+ mouse_opaque="false"
+ name="Attach Object"
+ tear_off="true" />
+ <menu
+ create_jump_keys="true"
+ label="Detach Object"
+ layout="topleft"
+ mouse_opaque="false"
+ name="Detach Object"
+ tear_off="true" />
+ <menu
+ create_jump_keys="true"
+ label="Take Off Clothing"
+ layout="topleft"
+ mouse_opaque="false"
+ name="Take Off Clothing"
+ tear_off="true">
+ <menu_item_call
+ label="Shirt"
+ layout="topleft"
+ name="Shirt">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="shirt" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="shirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="Pants"
+ layout="topleft"
+ name="Pants">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="pants" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="pants" />
+ </menu_item_call>
+ <menu_item_call
+ label="Shoes"
+ layout="topleft"
+ name="Shoes">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="shoes" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="shoes" />
+ </menu_item_call>
+ <menu_item_call
+ label="Socks"
+ layout="topleft"
+ name="Socks">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="socks" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="socks" />
+ </menu_item_call>
+ <menu_item_call
+ label="Jacket"
+ layout="topleft"
+ name="Jacket">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="jacket" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="jacket" />
+ </menu_item_call>
+ <menu_item_call
+ label="Gloves"
+ layout="topleft"
+ name="Gloves">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="gloves" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="gloves" />
+ </menu_item_call>
+ <menu_item_call
+ label="Undershirt"
+ layout="topleft"
+ name="Menu Undershirt">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="undershirt" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="undershirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="Underpants"
+ layout="topleft"
+ name="Menu Underpants">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="underpants" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="underpants" />
+ </menu_item_call>
+ <menu_item_call
+ label="Skirt"
+ layout="topleft"
+ name="Skirt">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="skirt" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="skirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="Alpha"
+ layout="topleft"
+ name="Alpha">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="alpha" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="alpha" />
+ </menu_item_call>
+ <menu_item_call
+ label="Tattoo"
+ layout="topleft"
+ name="Tattoo">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="tattoo" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="tattoo" />
+ </menu_item_call>
+ <menu_item_call
+ label="All Clothes"
+ layout="topleft"
+ name="All Clothes">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="all" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Help"
+ layout="topleft"
+ name="Help"
+ tear_off="true">
+ <menu_item_call
+ label="Official Linden Blog"
+ layout="topleft"
+ name="Official Linden Blog">
+ <menu_item_call.on_click
+ function="PromptShowURL"
+ name="OfficialLindenBlog_url"
+ parameter="WebLaunchSupportWiki,http://blog.secondlife.com/" />
+ </menu_item_call>
+ <menu_item_call
+ label="Scripting Portal"
+ layout="topleft"
+ name="Scripting Portal">
+ <menu_item_call.on_click
+ function="PromptShowURL"
+ name="ScriptingPortal_url"
+ parameter="WebLaunchLSLWiki,http://wiki.secondlife.com/wiki/LSL_Portal" />
+ </menu_item_call>
+ <menu
+ create_jump_keys="true"
+ label="Bug Reporting"
+ layout="topleft"
+ name="Bug Reporting"
+ tear_off="true">
+ <menu_item_call
+ label="Public Issue Tracker"
+ layout="topleft"
+ name="Public Issue Tracker">
+ <menu_item_call.on_click
+ function="PromptShowURL"
+ name="PublicIssueTracker_url"
+ parameter="WebLaunchPublicIssue,http://jira.secondlife.com" />
+ </menu_item_call>
+ <menu_item_call
+ label="Public Issue Tracker Help"
+ layout="topleft"
+ name="Publc Issue Tracker Help">
+ <menu_item_call.on_click
+ function="PromptShowURL"
+ name="PublicIssueTrackerHelp_url"
+ parameter="WebLaunchPublicIssueHelp,http://wiki.secondlife.com/wiki/Issue_tracker" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Bug Reporting 101"
+ layout="topleft"
+ name="Bug Reporing 101">
+ <menu_item_call.on_click
+ function="PromptShowURL"
+ name="BugReporting101_url"
+ parameter="WebLaunchBugReport101,http://wiki.secondlife.com/wiki/Bug_Reporting_101" />
+ </menu_item_call>
+ <menu_item_call
+ label="Security Issues"
+ layout="topleft"
+ name="Security Issues">
+ <menu_item_call.on_click
+ function="PromptShowURL"
+ name="SecurityIssues_url"
+ parameter="WebLaunchSecurityIssues,http://wiki.secondlife.com/wiki/Security_issues" />
+ </menu_item_call>
+ <menu_item_call
+ label="QA Wiki"
+ layout="topleft"
+ name="QA Wiki">
+ <menu_item_call.on_click
+ function="PromptShowURL"
+ name="QAWiki_url"
+ parameter="WebLaunchQAWiki,http://wiki.secondlife.com/wiki/QA_Portal" />
+ </menu_item_call>
+ </menu>
+ </menu>
+ </menu>
+</menu_bar>
diff --git a/indra/newview/skins/default/xui/en/mime_types.xml b/indra/newview/skins/default/xui/en/mime_types.xml
new file mode 100644
index 0000000000..76c0d027f3
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/mime_types.xml
@@ -0,0 +1,442 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<mimetypes name="default">
+ <defaultlabel>
+ (Unknown)
+ </defaultlabel>
+ <defaultwidget>
+ none
+ </defaultwidget>
+ <defaultimpl>
+ media_plugin_webkit
+ </defaultimpl>
+ <widgetset name="web">
+ <label name="web_label">
+ Web Content
+ </label>
+ <icon>
+ icn_media_web.tga
+ </icon>
+ <default_type>
+ text/html
+ </default_type>
+ <tooltip name="web_tooltip">
+ This location has Web content
+ </tooltip>
+ <playtip name="web_playtip">
+ Show Web content
+ </playtip>
+ <allow_resize>
+ true
+ </allow_resize>
+ <allow_looping>
+ false
+ </allow_looping>
+ </widgetset>
+ <widgetset name="movie">
+ <label name="movie_label">
+ Movie
+ </label>
+ <default_type>
+ video/*
+ </default_type>
+ <icon>
+ icn_media_movie.tga
+ </icon>
+ <tooltip name="movie_tooltip">
+ There is a movie to play here
+ </tooltip>
+ <playtip name="movie_playtip">
+ Play movie
+ </playtip>
+ <allow_resize>
+ false
+ </allow_resize>
+ <allow_looping>
+ true
+ </allow_looping>
+ </widgetset>
+ <widgetset name="image">
+ <label name="image_label">
+ Image
+ </label>
+ <icon>
+ icn_media_web.tga
+ </icon>
+ <default_type>
+ image/*
+ </default_type>
+ <tooltip name="image_tooltip">
+ There is an image at this location
+ </tooltip>
+ <playtip name="image_playtip">
+ View this location&apos;s image
+ </playtip>
+ <allow_resize>
+ false
+ </allow_resize>
+ <allow_looping>
+ false
+ </allow_looping>
+ </widgetset>
+ <widgetset name="audio">
+ <label name="audio_label">
+ Audio
+ </label>
+ <icon>
+ icn_media_web.tga
+ </icon>
+ <default_type>
+ audio/*
+ </default_type>
+ <tooltip name="audio_tooltip">
+ There is audio at this location
+ </tooltip>
+ <playtip name="audio_playtip">
+ Play this location&apos;s audio
+ </playtip>
+ <allow_resize>
+ false
+ </allow_resize>
+ <allow_looping>
+ true
+ </allow_looping>
+ </widgetset>
+ <scheme name="rtsp">
+ <label name="rtsp_label">
+ Real Time Streaming
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </scheme>
+ <mimetype name="blank">
+ <label name="blank_label">
+ - None -
+ </label>
+ <widgettype>
+ none
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype name="none/none">
+ <label name="none/none_label">
+ - None -
+ </label>
+ <widgettype>
+ none
+ </widgettype>
+ </mimetype>
+ <mimetype name="audio/*">
+ <label name="audio2_label">
+ Audio
+ </label>
+ <widgettype>
+ audio
+ </widgettype>
+ </mimetype>
+ <mimetype name="video/*">
+ <label name="video2_label">
+ Video
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ </mimetype>
+ <mimetype name="image/*">
+ <label name="image2_label">
+ Image
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ </mimetype>
+ <mimetype menu="1" name="video/vnd.secondlife.qt.legacy">
+ <label name="vnd.secondlife.qt.legacy_label">
+ Movie (QuickTime)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype name="application/javascript">
+ <label name="application/javascript_label">
+ Javascript
+ </label>
+ <widgettype>
+ web
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/ogg">
+ <label name="application/ogg_label">
+ Ogg Audio/Video
+ </label>
+ <widgettype>
+ audio
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/pdf">
+ <label name="application/pdf_label">
+ PDF Document
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/postscript">
+ <label name="application/postscript_label">
+ Postscript Document
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/rtf">
+ <label name="application/rtf_label">
+ Rich Text (RTF)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/smil">
+ <label name="application/smil_label">
+ Synchronized Multimedia Integration Language (SMIL)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/xhtml+xml">
+ <label name="application/xhtml+xml_label">
+ Web Page (XHTML)
+ </label>
+ <widgettype>
+ web
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/x-director">
+ <label name="application/x-director_label">
+ Macromedia Director
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ </mimetype>
+ <mimetype name="audio/mid">
+ <label name="audio/mid_label">
+ Audio (MIDI)
+ </label>
+ <widgettype>
+ audio
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype name="audio/mpeg">
+ <label name="audio/mpeg_label">
+ Audio (MP3)
+ </label>
+ <widgettype>
+ audio
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype name="audio/x-aiff">
+ <label name="audio/x-aiff_label">
+ Audio (AIFF)
+ </label>
+ <widgettype>
+ audio
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype name="audio/x-wav">
+ <label name="audio/x-wav_label">
+ Audio (WAV)
+ </label>
+ <widgettype>
+ audio
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="image/bmp">
+ <label name="image/bmp_label">
+ Image (BMP)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="image/gif">
+ <label name="image/gif_label">
+ Image (GIF)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="image/jpeg">
+ <label name="image/jpeg_label">
+ Image (JPEG)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="image/png">
+ <label name="image/png_label">
+ Image (PNG)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype name="image/svg+xml">
+ <label name="image/svg+xml_label">
+ Image (SVG)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="image/tiff">
+ <label name="image/tiff_label">
+ Image (TIFF)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="text/html">
+ <label name="text/html_label">
+ Web Page
+ </label>
+ <widgettype>
+ web
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="text/plain">
+ <label name="text/plain_label">
+ Text
+ </label>
+ <widgettype>
+ text
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype name="text/xml">
+ <label name="text/xml_label">
+ XML
+ </label>
+ <widgettype>
+ text
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="video/mpeg">
+ <label name="video/mpeg_label">
+ Movie (MPEG)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype name="video/mp4">
+ <label name="video/mp4_label">
+ Movie (MP4)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="video/quicktime">
+ <label name="video/quicktime_label">
+ Movie (QuickTime)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype name="video/x-ms-asf">
+ <label name="video/x-ms-asf_label">
+ Movie (Windows Media ASF)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype name="video/x-ms-wmv">
+ <label name="video/x-ms-wmv_label">
+ Movie (Windows Media WMV)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="video/x-msvideo">
+ <label name="video/x-msvideo_label">
+ Movie (AVI)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+</mimetypes>
diff --git a/indra/newview/skins/default/xui/en/mime_types_linux.xml b/indra/newview/skins/default/xui/en/mime_types_linux.xml
new file mode 100644
index 0000000000..05cd850725
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/mime_types_linux.xml
@@ -0,0 +1,442 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<mimetypes name="default">
+ <defaultlabel>
+ (Unknown)
+ </defaultlabel>
+ <defaultwidget>
+ none
+ </defaultwidget>
+ <defaultimpl>
+ media_plugin_webkit
+ </defaultimpl>
+ <widgetset name="web">
+ <label name="web_label">
+ Web Content
+ </label>
+ <icon>
+ icn_media_web.tga
+ </icon>
+ <default_type>
+ text/html
+ </default_type>
+ <tooltip name="web_tooltip">
+ This location has Web content
+ </tooltip>
+ <playtip name="web_playtip">
+ Show Web content
+ </playtip>
+ <allow_resize>
+ true
+ </allow_resize>
+ <allow_looping>
+ false
+ </allow_looping>
+ </widgetset>
+ <widgetset name="movie">
+ <label name="movie_label">
+ Movie
+ </label>
+ <default_type>
+ video/*
+ </default_type>
+ <icon>
+ icn_media_movie.tga
+ </icon>
+ <tooltip name="movie_tooltip">
+ There is a movie to play here
+ </tooltip>
+ <playtip name="movie_playtip">
+ Play movie
+ </playtip>
+ <allow_resize>
+ false
+ </allow_resize>
+ <allow_looping>
+ true
+ </allow_looping>
+ </widgetset>
+ <widgetset name="image">
+ <label name="image_label">
+ Image
+ </label>
+ <icon>
+ icn_media_web.tga
+ </icon>
+ <default_type>
+ image/*
+ </default_type>
+ <tooltip name="image_tooltip">
+ There is an image at this location
+ </tooltip>
+ <playtip name="image_playtip">
+ View this location&apos;s image
+ </playtip>
+ <allow_resize>
+ false
+ </allow_resize>
+ <allow_looping>
+ false
+ </allow_looping>
+ </widgetset>
+ <widgetset name="audio">
+ <label name="audio_label">
+ Audio
+ </label>
+ <icon>
+ icn_media_web.tga
+ </icon>
+ <default_type>
+ audio/*
+ </default_type>
+ <tooltip name="audio_tooltip">
+ There is audio at this location
+ </tooltip>
+ <playtip name="audio_playtip">
+ Play this location&apos;s audio
+ </playtip>
+ <allow_resize>
+ false
+ </allow_resize>
+ <allow_looping>
+ true
+ </allow_looping>
+ </widgetset>
+ <scheme name="rtsp">
+ <label name="rtsp_label">
+ Real Time Streaming
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_gstreamer
+ </impl>
+ </scheme>
+ <mimetype name="blank">
+ <label name="blank_label">
+ - None -
+ </label>
+ <widgettype>
+ none
+ </widgettype>
+ <impl>
+ media_plugin_gstreamer
+ </impl>
+ </mimetype>
+ <mimetype name="none/none">
+ <label name="none/none_label">
+ - None -
+ </label>
+ <widgettype>
+ none
+ </widgettype>
+ </mimetype>
+ <mimetype name="audio/*">
+ <label name="audio2_label">
+ Audio
+ </label>
+ <widgettype>
+ audio
+ </widgettype>
+ </mimetype>
+ <mimetype name="video/*">
+ <label name="video2_label">
+ Video
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ </mimetype>
+ <mimetype name="image/*">
+ <label name="image2_label">
+ Image
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ </mimetype>
+ <mimetype menu="1" name="video/vnd.secondlife.qt.legacy">
+ <label name="vnd.secondlife.qt.legacy_label">
+ Movie (QuickTime)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_gstreamer
+ </impl>
+ </mimetype>
+ <mimetype name="application/javascript">
+ <label name="application/javascript_label">
+ Javascript
+ </label>
+ <widgettype>
+ web
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/ogg">
+ <label name="application/ogg_label">
+ Ogg Audio/Video
+ </label>
+ <widgettype>
+ audio
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/pdf">
+ <label name="application/pdf_label">
+ PDF Document
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/postscript">
+ <label name="application/postscript_label">
+ Postscript Document
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/rtf">
+ <label name="application/rtf_label">
+ Rich Text (RTF)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/smil">
+ <label name="application/smil_label">
+ Synchronized Multimedia Integration Language (SMIL)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/xhtml+xml">
+ <label name="application/xhtml+xml_label">
+ Web Page (XHTML)
+ </label>
+ <widgettype>
+ web
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/x-director">
+ <label name="application/x-director_label">
+ Macromedia Director
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ </mimetype>
+ <mimetype name="audio/mid">
+ <label name="audio/mid_label">
+ Audio (MIDI)
+ </label>
+ <widgettype>
+ audio
+ </widgettype>
+ <impl>
+ media_plugin_gstreamer
+ </impl>
+ </mimetype>
+ <mimetype name="audio/mpeg">
+ <label name="audio/mpeg_label">
+ Audio (MP3)
+ </label>
+ <widgettype>
+ audio
+ </widgettype>
+ <impl>
+ media_plugin_gstreamer
+ </impl>
+ </mimetype>
+ <mimetype name="audio/x-aiff">
+ <label name="audio/x-aiff_label">
+ Audio (AIFF)
+ </label>
+ <widgettype>
+ audio
+ </widgettype>
+ <impl>
+ media_plugin_gstreamer
+ </impl>
+ </mimetype>
+ <mimetype name="audio/x-wav">
+ <label name="audio/x-wav_label">
+ Audio (WAV)
+ </label>
+ <widgettype>
+ audio
+ </widgettype>
+ <impl>
+ media_plugin_gstreamer
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="image/bmp">
+ <label name="image/bmp_label">
+ Image (BMP)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="image/gif">
+ <label name="image/gif_label">
+ Image (GIF)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="image/jpeg">
+ <label name="image/jpeg_label">
+ Image (JPEG)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="image/png">
+ <label name="image/png_label">
+ Image (PNG)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype name="image/svg+xml">
+ <label name="image/svg+xml_label">
+ Image (SVG)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="image/tiff">
+ <label name="image/tiff_label">
+ Image (TIFF)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="text/html">
+ <label name="text/html_label">
+ Web Page
+ </label>
+ <widgettype>
+ web
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="text/plain">
+ <label name="text/plain_label">
+ Text
+ </label>
+ <widgettype>
+ text
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype name="text/xml">
+ <label name="text/xml_label">
+ XML
+ </label>
+ <widgettype>
+ text
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="video/mpeg">
+ <label name="video/mpeg_label">
+ Movie (MPEG)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_gstreamer
+ </impl>
+ </mimetype>
+ <mimetype name="video/mp4">
+ <label name="video/mp4_label">
+ Movie (MP4)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_gstreamer
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="video/quicktime">
+ <label name="video/quicktime_label">
+ Movie (QuickTime)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_gstreamer
+ </impl>
+ </mimetype>
+ <mimetype name="video/x-ms-asf">
+ <label name="video/x-ms-asf_label">
+ Movie (Windows Media ASF)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_gstreamer
+ </impl>
+ </mimetype>
+ <mimetype name="video/x-ms-wmv">
+ <label name="video/x-ms-wmv_label">
+ Movie (Windows Media WMV)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_gstreamer
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="video/x-msvideo">
+ <label name="video/x-msvideo_label">
+ Movie (AVI)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_gstreamer
+ </impl>
+ </mimetype>
+</mimetypes>
diff --git a/indra/newview/skins/default/xui/en/mime_types_mac.xml b/indra/newview/skins/default/xui/en/mime_types_mac.xml
new file mode 100644
index 0000000000..76c0d027f3
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/mime_types_mac.xml
@@ -0,0 +1,442 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<mimetypes name="default">
+ <defaultlabel>
+ (Unknown)
+ </defaultlabel>
+ <defaultwidget>
+ none
+ </defaultwidget>
+ <defaultimpl>
+ media_plugin_webkit
+ </defaultimpl>
+ <widgetset name="web">
+ <label name="web_label">
+ Web Content
+ </label>
+ <icon>
+ icn_media_web.tga
+ </icon>
+ <default_type>
+ text/html
+ </default_type>
+ <tooltip name="web_tooltip">
+ This location has Web content
+ </tooltip>
+ <playtip name="web_playtip">
+ Show Web content
+ </playtip>
+ <allow_resize>
+ true
+ </allow_resize>
+ <allow_looping>
+ false
+ </allow_looping>
+ </widgetset>
+ <widgetset name="movie">
+ <label name="movie_label">
+ Movie
+ </label>
+ <default_type>
+ video/*
+ </default_type>
+ <icon>
+ icn_media_movie.tga
+ </icon>
+ <tooltip name="movie_tooltip">
+ There is a movie to play here
+ </tooltip>
+ <playtip name="movie_playtip">
+ Play movie
+ </playtip>
+ <allow_resize>
+ false
+ </allow_resize>
+ <allow_looping>
+ true
+ </allow_looping>
+ </widgetset>
+ <widgetset name="image">
+ <label name="image_label">
+ Image
+ </label>
+ <icon>
+ icn_media_web.tga
+ </icon>
+ <default_type>
+ image/*
+ </default_type>
+ <tooltip name="image_tooltip">
+ There is an image at this location
+ </tooltip>
+ <playtip name="image_playtip">
+ View this location&apos;s image
+ </playtip>
+ <allow_resize>
+ false
+ </allow_resize>
+ <allow_looping>
+ false
+ </allow_looping>
+ </widgetset>
+ <widgetset name="audio">
+ <label name="audio_label">
+ Audio
+ </label>
+ <icon>
+ icn_media_web.tga
+ </icon>
+ <default_type>
+ audio/*
+ </default_type>
+ <tooltip name="audio_tooltip">
+ There is audio at this location
+ </tooltip>
+ <playtip name="audio_playtip">
+ Play this location&apos;s audio
+ </playtip>
+ <allow_resize>
+ false
+ </allow_resize>
+ <allow_looping>
+ true
+ </allow_looping>
+ </widgetset>
+ <scheme name="rtsp">
+ <label name="rtsp_label">
+ Real Time Streaming
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </scheme>
+ <mimetype name="blank">
+ <label name="blank_label">
+ - None -
+ </label>
+ <widgettype>
+ none
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype name="none/none">
+ <label name="none/none_label">
+ - None -
+ </label>
+ <widgettype>
+ none
+ </widgettype>
+ </mimetype>
+ <mimetype name="audio/*">
+ <label name="audio2_label">
+ Audio
+ </label>
+ <widgettype>
+ audio
+ </widgettype>
+ </mimetype>
+ <mimetype name="video/*">
+ <label name="video2_label">
+ Video
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ </mimetype>
+ <mimetype name="image/*">
+ <label name="image2_label">
+ Image
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ </mimetype>
+ <mimetype menu="1" name="video/vnd.secondlife.qt.legacy">
+ <label name="vnd.secondlife.qt.legacy_label">
+ Movie (QuickTime)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype name="application/javascript">
+ <label name="application/javascript_label">
+ Javascript
+ </label>
+ <widgettype>
+ web
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/ogg">
+ <label name="application/ogg_label">
+ Ogg Audio/Video
+ </label>
+ <widgettype>
+ audio
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/pdf">
+ <label name="application/pdf_label">
+ PDF Document
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/postscript">
+ <label name="application/postscript_label">
+ Postscript Document
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/rtf">
+ <label name="application/rtf_label">
+ Rich Text (RTF)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/smil">
+ <label name="application/smil_label">
+ Synchronized Multimedia Integration Language (SMIL)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/xhtml+xml">
+ <label name="application/xhtml+xml_label">
+ Web Page (XHTML)
+ </label>
+ <widgettype>
+ web
+ </widgettype>
+ </mimetype>
+ <mimetype name="application/x-director">
+ <label name="application/x-director_label">
+ Macromedia Director
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ </mimetype>
+ <mimetype name="audio/mid">
+ <label name="audio/mid_label">
+ Audio (MIDI)
+ </label>
+ <widgettype>
+ audio
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype name="audio/mpeg">
+ <label name="audio/mpeg_label">
+ Audio (MP3)
+ </label>
+ <widgettype>
+ audio
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype name="audio/x-aiff">
+ <label name="audio/x-aiff_label">
+ Audio (AIFF)
+ </label>
+ <widgettype>
+ audio
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype name="audio/x-wav">
+ <label name="audio/x-wav_label">
+ Audio (WAV)
+ </label>
+ <widgettype>
+ audio
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="image/bmp">
+ <label name="image/bmp_label">
+ Image (BMP)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="image/gif">
+ <label name="image/gif_label">
+ Image (GIF)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="image/jpeg">
+ <label name="image/jpeg_label">
+ Image (JPEG)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="image/png">
+ <label name="image/png_label">
+ Image (PNG)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype name="image/svg+xml">
+ <label name="image/svg+xml_label">
+ Image (SVG)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="image/tiff">
+ <label name="image/tiff_label">
+ Image (TIFF)
+ </label>
+ <widgettype>
+ image
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="text/html">
+ <label name="text/html_label">
+ Web Page
+ </label>
+ <widgettype>
+ web
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="text/plain">
+ <label name="text/plain_label">
+ Text
+ </label>
+ <widgettype>
+ text
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype name="text/xml">
+ <label name="text/xml_label">
+ XML
+ </label>
+ <widgettype>
+ text
+ </widgettype>
+ <impl>
+ media_plugin_webkit
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="video/mpeg">
+ <label name="video/mpeg_label">
+ Movie (MPEG)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype name="video/mp4">
+ <label name="video/mp4_label">
+ Movie (MP4)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="video/quicktime">
+ <label name="video/quicktime_label">
+ Movie (QuickTime)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype name="video/x-ms-asf">
+ <label name="video/x-ms-asf_label">
+ Movie (Windows Media ASF)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype name="video/x-ms-wmv">
+ <label name="video/x-ms-wmv_label">
+ Movie (Windows Media WMV)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+ <mimetype menu="1" name="video/x-msvideo">
+ <label name="video/x-msvideo_label">
+ Movie (AVI)
+ </label>
+ <widgettype>
+ movie
+ </widgettype>
+ <impl>
+ media_plugin_quicktime
+ </impl>
+ </mimetype>
+</mimetypes>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
new file mode 100644
index 0000000000..41f4621d66
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -0,0 +1,5951 @@
+<?xml version="1.0" ?><notifications>
+
+ <global name="skipnexttime">
+
+ Don&apos;t show me this again
+ </global>
+
+ <global name="alwayschoose">
+
+ Always choose this option
+ </global>
+
+ <global name="implicitclosebutton">
+ Close
+ </global>
+
+ <template name="okbutton">
+ <form>
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="$yestext"/>
+ </form>
+ </template>
+
+ <template name="okignore">
+ <form>
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="$yestext"/>
+ <ignore text="$ignoretext"/>
+ </form>
+ </template>
+
+ <template name="okcancelbuttons">
+ <form>
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="$yestext"/>
+ <button
+ index="1"
+ name="Cancel"
+ text="$notext"/>
+ </form>
+ </template>
+
+ <template name="okcancelignore">
+ <form>
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="$yestext"/>
+ <button
+ index="1"
+ name="Cancel"
+ text="$notext"/>
+ <ignore text="$ignoretext"/>
+ </form>
+ </template>
+
+ <template name="okhelpbuttons">
+ <form>
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="$yestext"/>
+ <button
+ index="1"
+ name="Help"
+ text="$helptext"/>
+ </form>
+ </template>
+
+ <template name="yesnocancelbuttons">
+ <form>
+ <button
+ default="true"
+ index="0"
+ name="Yes"
+ text="$yestext"/>
+ <button
+ index="1"
+ name="No"
+ text="$notext"/>
+ <button
+ index="2"
+ name="Cancel"
+ text="$canceltext"/>
+ </form>
+ </template>
+
+ <notification
+ functor="GenericAcknowledge"
+ icon="alertmodal.tga"
+ name="MissingAlert"
+ label="Unknown Notification Message"
+ type="alertmodal">
+Your version of [APP_NAME] does not know how to display the notification it just received. Please verify that you have the latest Viewer installed.
+
+Error details: The notification called &apos;[_NAME]&apos; was not found in notifications.xml.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="FloaterNotFound"
+ type="alertmodal">
+Floater error: Could not find the following controls:
+
+[CONTROLS]
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="TutorialNotFound"
+ type="alertmodal">
+No tutorial is currently available.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="GenericAlert"
+ type="alertmodal">
+[MESSAGE]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="GenericAlertYesCancel"
+ type="alertmodal">
+[MESSAGE]
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="BadInstallation"
+ type="alertmodal">
+ An error occurred while updating [APP_NAME]. Please [http://get.secondlife.com download the latest version] of the Viewer.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="LoginFailedNoNetwork"
+ type="alertmodal">
+Could not connect to the [SECOND_LIFE_GRID].
+&apos;[DIAGNOSTIC]&apos;
+Make sure your Internet connection is working properly.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="MessageTemplateNotFound"
+ type="alertmodal">
+Message Template [PATH] not found.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="WearableSave"
+ type="alertmodal">
+Save changes to current clothing/body part?
+ <usetemplate
+ canceltext="Cancel"
+ name="yesnocancelbuttons"
+ notext="Don&apos;t Save"
+ yestext="Save"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CompileQueueSaveText"
+ type="alertmodal">
+There was a problem uploading the text for a script due to the following reason: [REASON]. Please try again later.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CompileQueueSaveBytecode"
+ type="alertmodal">
+There was a problem uploading the compiled script due to the following reason: [REASON]. Please try again later.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="WriteAnimationFail"
+ type="alertmodal">
+There was a problem writing animation data. Please try again later.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="UploadAuctionSnapshotFail"
+ type="alertmodal">
+There was a problem uploading the auction snapshot due to the following reason: [REASON]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="UnableToViewContentsMoreThanOne"
+ type="alertmodal">
+Unable to view the contents of more than one item at a time.
+Please select only one object and try again.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SaveClothingBodyChanges"
+ type="alertmodal">
+Save all changes to clothing/body parts?
+ <usetemplate
+ canceltext="Cancel"
+ name="yesnocancelbuttons"
+ notext="Don&apos;t Save"
+ yestext="Save All"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="FriendsAndGroupsOnly"
+ type="alertmodal">
+ Non-friends won't know that you've choosen to ignore their calls and instant messages.
+ <usetemplate
+ name="okbutton"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="GrantModifyRights"
+ type="alertmodal">
+Granting modify rights to another Resident allows them to change, delete or take ANY objects you may have in-world. Be VERY careful when handing out this permission.
+Do you want to grant modify rights for [FIRST_NAME] [LAST_NAME]?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="GrantModifyRightsMultiple"
+ type="alertmodal">
+Granting modify rights to another Resident allows them to change ANY objects you may have in-world. Be VERY careful when handing out this permission.
+Do you want to grant modify rights for the selected Residents?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="RevokeModifyRights"
+ type="alertmodal">
+Do you want to revoke modify rights for [FIRST_NAME] [LAST_NAME]?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="RevokeModifyRightsMultiple"
+ type="alertmodal">
+Do you want to revoke modify rights for the selected Residents?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="UnableToCreateGroup"
+ type="alertmodal">
+Unable to create group.
+[MESSAGE]
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="PanelGroupApply"
+ type="alertmodal">
+[NEEDS_APPLY_MESSAGE]
+[WANT_APPLY_MESSAGE]
+ <usetemplate
+ canceltext="Cancel"
+ name="yesnocancelbuttons"
+ notext="Ignore Changes"
+ yestext="Apply Changes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="MustSpecifyGroupNoticeSubject"
+ type="alertmodal">
+You must specify a subject to send a group notice.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="AddGroupOwnerWarning"
+ type="alertmodal">
+You are about to add group members to the role of [ROLE_NAME].
+Members cannot be removed from that role.
+The members must resign from the role themselves.
+Are you sure you want to continue?
+ <usetemplate
+ ignoretext="Confirm before I add a new group Owner"
+ name="okcancelignore"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="AssignDangerousActionWarning"
+ type="alertmodal">
+You are about to add the Ability &apos;[ACTION_NAME]&apos; to the Role &apos;[ROLE_NAME]&apos;.
+
+ *WARNING*
+ Any Member in a Role with this Ability can assign themselves -- and any other member -- to Roles that have more powers than they currently have, potentially elevating themselves to near-Owner power. Be sure you know what you&apos;re doing before assigning this Ability.
+
+Add this Ability to &apos;[ROLE_NAME]&apos;?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="AssignDangerousAbilityWarning"
+ type="alertmodal">
+You are about to add the Ability &apos;[ACTION_NAME]&apos; to the Role &apos;[ROLE_NAME]&apos;.
+
+ *WARNING*
+ Any Member in a Role with this Ability can assign themselves -- and any other member -- all Abilities, elevating themselves to near-Owner power.
+
+Add this Ability to &apos;[ROLE_NAME]&apos;?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="AttachmentDrop"
+ type="alertmodal">
+ You are about to drop your attachment.
+ Are you sure you want to continue?
+ <usetemplate
+ ignoretext="Confirm before dropping attachments"
+ name="okcancelignore"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ClickUnimplemented"
+ type="alertmodal">
+Sorry, not implemented yet.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="JoinGroupCanAfford"
+ type="alertmodal">
+Joining this group costs L$[COST].
+Do you wish to proceed?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="Join"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="JoinGroupCannotAfford"
+ type="alertmodal">
+Joining this group costs L$[COST].
+You do not have enough L$ to join this group.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CreateGroupCost"
+ type="alertmodal">
+Creating this group will cost L$100.
+Groups need more than one member, or they are deleted forever.
+Please invite members within 48 hours.
+ <usetemplate
+ canceltext="Cancel"
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="Create group for L$100"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="LandBuyPass"
+ type="alertmodal">
+For L$[COST] you can enter this land (&apos;[PARCEL_NAME]&apos;) for [TIME] hours. Buy a pass?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SalePriceRestriction"
+ type="alertmodal">
+Sale price must be set to more than L$0 if selling to anyone.
+Please select an individual to sell to if selling for L$0.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmLandSaleChange"
+ priority="high"
+ type="alertmodal">
+The selected [LAND_SIZE] m² land is being set for sale.
+Your selling price will be L$[SALE_PRICE] and will be authorized for sale to [NAME].
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmLandSaleToAnyoneChange"
+ type="alertmodal">
+ATTENTION: Clicking &apos;sell to anyone&apos; makes your land available to the entire [SECOND_LIFE] community, even those not in this region.
+
+The selected [LAND_SIZE] m² land is being set for sale.
+Your selling price will be L$[SALE_PRICE] and will be authorized for sale to [NAME].
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ReturnObjectsDeededToGroup"
+ type="alertmodal">
+Are you sure you want to return all objects shared with the group &apos;[NAME]&apos; on this parcel of land back to their previous owner&apos;s inventory?
+
+*WARNING* This will delete the non-transferable objects deeded to the group!
+
+Objects: [N]
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ReturnObjectsOwnedByUser"
+ type="alertmodal">
+Are you sure you want to return all objects owned by the Resident &apos;[NAME]&apos; on this parcel of land back to their inventory?
+
+Objects: [N]
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ReturnObjectsOwnedBySelf"
+ type="alertmodal">
+Are you sure you want to return all objects owned by you on this parcel of land back to your inventory?
+
+Objects: [N]
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ReturnObjectsNotOwnedBySelf"
+ type="alertmodal">
+Are you sure you want to return all objects NOT owned by you on this parcel of land back to their owner&apos;s inventory?
+Transferable objects deeded to a group will be returned to their previous owners.
+
+*WARNING* This will delete the non-transferable objects deeded to the group!
+
+Objects: [N]
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ReturnObjectsNotOwnedByUser"
+ type="alertmodal">
+Are you sure you want to return all objects NOT owned by [NAME] on this parcel of land back to their owner&apos;s inventory?
+Transferable objects deeded to a group will be returned to their previous owners.
+
+*WARNING* This will delete the non-transferable objects deeded to the group!
+
+Objects: [N]
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ReturnAllTopObjects"
+ type="alertmodal">
+Are you sure you want to return all listed objects back to their owner&apos;s inventory?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="DisableAllTopObjects"
+ type="alertmodal">
+Are you sure you want to disable all objects in this region?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ReturnObjectsNotOwnedByGroup"
+ type="alertmodal">
+Return the objects on this parcel of land that are NOT shared with the group [NAME] back to their owners?
+
+Objects: [N]
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="UnableToDisableOutsideScripts"
+ type="alertmodal">
+Can not disable scripts.
+This entire region is damage enabled.
+Scripts must be allowed to run for weapons to work.
+ </notification>
+
+<notification
+ icon="alertmodal.tga"
+ name="MultipleFacesSelected"
+ type="alertmodal">
+Multiple faces are currently selected.
+If you continue this action, separate instances of media will be set on multiple faces of the object.
+To place the media on only one face, choose Select Face and click on the desired face of that object then click Add.
+ <usetemplate
+ ignoretext="Media will be set on multiple selected faces"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="MustBeInParcel"
+ type="alertmodal">
+You must be standing inside the land parcel to set its Landing Point.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="PromptRecipientEmail"
+ type="alertmodal">
+Please enter a valid email address for the recipient(s).
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="PromptSelfEmail"
+ type="alertmodal">
+Please enter your email address.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="PromptMissingSubjMsg"
+ type="alertmodal">
+Email snapshot with the default subject or message?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ErrorProcessingSnapshot"
+ type="alertmodal">
+Error processing snapshot data
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ErrorEncodingSnapshot"
+ type="alertmodal">
+Error encoding snapshot.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ErrorUploadingPostcard"
+ type="alertmodal">
+There was a problem sending a snapshot due to the following reason: [REASON]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ErrorUploadingReportScreenshot"
+ type="alertmodal">
+There was a problem uploading a report screenshot due to the following reason: [REASON]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="MustAgreeToLogIn"
+ type="alertmodal">
+You must agree to the Terms of Service to continue logging into [SECOND_LIFE].
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CouldNotPutOnOutfit"
+ type="alertmodal">
+Could not put on outfit.
+The outfit folder contains no clothing, body parts, or attachments.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotWearTrash"
+ type="alertmodal">
+You can not wear clothes or body parts that are in the trash
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="MaxAttachmentsOnOutfit"
+ type="alertmodal">
+Could not attach object.
+Exceeds the attachments limit of [MAX_ATTACHMENTS] objects. Please detach another object first.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotWearInfoNotComplete"
+ type="alertmodal">
+You can not wear that item because it has not yet loaded. Please try again in a minute.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="MustHaveAccountToLogIn"
+ type="alertmodal">
+Oops! Something was left blank.
+You need to enter both the First and Last name of your avatar.
+
+You need an account to enter [SECOND_LIFE]. Would you like to create one now?
+ <url
+ option="0"
+ name="url"
+ openexternally = "1">
+
+ http://join.secondlife.com/
+ </url>
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Try again"
+ yestext="Create a new account"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="AddClassified"
+ type="alertmodal">
+Classified ads appear in the &apos;Classified&apos; section of the Search directory and on [http://secondlife.com/community/classifieds secondlife.com] for one week.
+Fill out your ad, then click &apos;Publish...&apos; to add it to the directory.
+You&apos;ll be asked for a price to pay when clicking Publish.
+Paying more makes your ad appear higher in the list, and also appear higher when people search for keywords.
+ <usetemplate
+ ignoretext="How to create a new Classified ad"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="DeleteClassified"
+ type="alertmodal">
+Delete classified &apos;[NAME]&apos;?
+There is no reimbursement for fees paid.
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+
+<notification
+ icon="alertmodal.tga"
+ name="DeleteMedia"
+ type="alertmodal">
+You have selected to delete the media associated with this face.
+Are you sure you want to continue?
+ <usetemplate
+ ignoretext="Confirm before I delete media from an object"
+ name="okcancelignore"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ClassifiedSave"
+ type="alertmodal">
+Save changes to classified [NAME]?
+ <usetemplate
+ canceltext="Cancel"
+ name="yesnocancelbuttons"
+ notext="Don&apos;t Save"
+ yestext="Save"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ClassifiedInsufficientFunds"
+ type="alertmodal">
+Insufficient funds to create classified.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="DeleteAvatarPick"
+ type="alertmodal">
+Delete pick [PICK]?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="PromptGoToEventsPage"
+ type="alertmodal">
+Go to the [SECOND_LIFE] events web page?
+ <url option="0" name="url">
+
+ http://secondlife.com/events/
+ </url>
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SelectProposalToView"
+ type="alertmodal">
+Please select a proposal to view.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SelectHistoryItemToView"
+ type="alertmodal">
+Please select a history item to view.
+ </notification>
+
+<!--
+ <notification
+ icon="alertmodal.tga"
+ name="ResetShowNextTimeDialogs"
+ type="alertmodal">
+Would you like to re-enable all these popups, which you previously indicated &apos;Don&apos;t show me again&apos;?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SkipShowNextTimeDialogs"
+ type="alertmodal">
+Would you like to disable all popups which can be skipped?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+-->
+
+ <notification
+ icon="alertmodal.tga"
+ name="CacheWillClear"
+ type="alertmodal">
+Cache will be cleared after you restart [APP_NAME].
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CacheWillBeMoved"
+ type="alertmodal">
+Cache will be moved after you restart [APP_NAME].
+Note: This will clear the cache.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ChangeConnectionPort"
+ type="alertmodal">
+Port settings take effect after you restart [APP_NAME].
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ChangeSkin"
+ type="alertmodal">
+The new skin will appear after you restart [APP_NAME].
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="GoToAuctionPage"
+ type="alertmodal">
+Go to the [SECOND_LIFE] web page to see auction details or make a bid?
+ <url option="0" name="url">
+
+ http://secondlife.com/auctions/auction-detail.php?id=[AUCTION_ID]
+ </url>
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SaveChanges"
+ type="alertmodal">
+Save Changes?
+ <usetemplate
+ canceltext="Cancel"
+ name="yesnocancelbuttons"
+ notext="Don&apos;t Save"
+ yestext="Save"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="GestureSaveFailedTooManySteps"
+ type="alertmodal">
+Gesture save failed.
+This gesture has too many steps.
+Try removing some steps, then save again.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="GestureSaveFailedTryAgain"
+ type="alertmodal">
+Gesture save failed. Please try again in a minute.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="GestureSaveFailedObjectNotFound"
+ type="alertmodal">
+Could not save gesture because the object or the associated object inventory could not be found.
+The object may be out of range or may have been deleted.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="GestureSaveFailedReason"
+ type="alertmodal">
+There was a problem saving a gesture due to the following reason: [REASON]. Please try resaving the gesture later.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SaveNotecardFailObjectNotFound"
+ type="alertmodal">
+Could not save notecard because the object or the associated object inventory could not be found.
+The object may be out of range or may have been deleted.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SaveNotecardFailReason"
+ type="alertmodal">
+There was a problem saving a notecard due to the following reason: [REASON]. Please try re-saving the notecard later.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ScriptCannotUndo"
+ type="alertmodal">
+Could not undo all changes in your version of the script.
+Would you like to load the server&apos;s last saved version?
+(**Warning** This operation cannot be undone.)
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SaveScriptFailReason"
+ type="alertmodal">
+There was a problem saving a script due to the following reason: [REASON]. Please try re-saving the script later.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SaveScriptFailObjectNotFound"
+ type="alertmodal">
+Could not save the script because the object it is in could not be found.
+The object may be out of range or may have been deleted.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SaveBytecodeFailReason"
+ type="alertmodal">
+There was a problem saving a compiled script due to the following reason: [REASON]. Please try re-saving the script later.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="StartRegionEmpty"
+ type="alertmodal">
+Oops, Your Start Region is not defined.
+Please type the Region name in Start Location box or choose My Last Location or My Home as your Start Location.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CouldNotStartStopScript"
+ type="alertmodal">
+Could not start or stop the script because the object it is on could not be found.
+The object may be out of range or may have been deleted.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotDownloadFile"
+ type="alertmodal">
+Unable to download file
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotWriteFile"
+ type="alertmodal">
+Unable to write file [[FILE]]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="UnsupportedHardware"
+ type="alertmodal">
+Warning: Your system does not meet [APP_NAME]&apos;s minimum system requirements. If you continue using [APP_NAME], you may experience poor performance. Unfortunately, the [SUPPORT_SITE] cannot provide technical support for unsupported system configurations.
+
+MINSPECS
+Do you wish to visit [_URL] for more information?
+ <url option="0" name="url">
+
+ http://www.secondlife.com/corporate/sysreqs.php
+ </url>
+ <usetemplate
+ ignoretext="My computer hardware is not supported"
+ name="okcancelignore"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="UnknownGPU"
+ type="alertmodal">
+Your system contains a graphics card that is unknown to [APP_NAME] at this time.
+This is often the case with new hardware that hasn&apos;t been tested yet with [APP_NAME]. [APP_NAME] will most likely run properly, but you may need to adjust your graphics settings to something more appropriate.
+(Me &gt; Preferences &gt; Graphics).
+ <form name="form">
+ <ignore name="ignore"
+ text="My graphics card could not be identified"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="DisplaySettingsNoShaders"
+ type="alertmodal">
+[APP_NAME] crashed while initializing graphics drivers.
+Graphics Quality will be set to Low to avoid some common driver errors. This will disable some graphics features.
+We recommend updating your graphics card drivers.
+Graphics Quality can be raised in Preferences &gt; Graphics.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="RegionNoTerraforming"
+ type="alertmodal">
+The region [REGION] does not allow terraforming.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotCopyWarning"
+ type="alertmodal">
+You do not have permission to copy this item and will lose it from your inventory if you give it away. Do you really want to offer this item?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotGiveItem"
+ type="alertmodal">
+Unable to give inventory item.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="TransactionCancelled"
+ type="alertmodal">
+Transaction cancelled.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="TooManyItems"
+ type="alertmodal">
+Cannot give more than 42 items in a single inventory transfer.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="NoItems"
+ type="alertmodal">
+You do not have permission to transfer the selected items.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotCopyCountItems"
+ type="alertmodal">
+You do not have permission to copy [COUNT] of the selected items. You will lose these items from your inventory.
+Do you really want to give these items?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotGiveCategory"
+ type="alertmodal">
+You do not have permission to transfer the selected folder.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="FreezeAvatar"
+ type="alertmodal">
+Freeze this avatar?
+He or she will temporarily be unable to move, chat, or interact with the world.
+ <usetemplate
+ canceltext="Cancel"
+ name="yesnocancelbuttons"
+ notext="Unfreeze"
+ yestext="Freeze"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="FreezeAvatarFullname"
+ type="alertmodal">
+Freeze [AVATAR_NAME]?
+He or she will temporarily be unable to move, chat, or interact with the world.
+ <usetemplate
+ canceltext="Cancel"
+ name="yesnocancelbuttons"
+ notext="Unfreeze"
+ yestext="Freeze"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="EjectAvatarFullname"
+ type="alertmodal">
+Eject [AVATAR_NAME] from your land?
+ <usetemplate
+ canceltext="Cancel"
+ name="yesnocancelbuttons"
+ notext="Eject and Ban"
+ yestext="Eject"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="EjectAvatarNoBan"
+ type="alertmodal">
+Eject this avatar from your land?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="Eject"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="EjectAvatarFullnameNoBan"
+ type="alertmodal">
+Eject [AVATAR_NAME] from your land?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="Eject"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="EjectAvatarFromGroup"
+ type="notify">
+You ejected [AVATAR_NAME] from group [GROUP_NAME]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="AcquireErrorTooManyObjects"
+ type="alertmodal">
+ACQUIRE ERROR: Too many objects selected.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="AcquireErrorObjectSpan"
+ type="alertmodal">
+ACQUIRE ERROR: Objects span more than one region.
+Please move all objects to be acquired onto the same region.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="PromptGoToCurrencyPage"
+ type="alertmodal">
+[EXTRA]
+
+Go to [_URL] for information on purchasing L$?
+ <url option="0" name="url">
+
+ http://secondlife.com/app/currency/
+ </url>
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="UnableToLinkObjects"
+ type="alertmodal">
+Unable to link these [COUNT] objects.
+You can link a maximum of [MAX] objects.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotLinkIncompleteSet"
+ type="alertmodal">
+You can only link complete sets of objects, and must select more than one object.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotLinkModify"
+ type="alertmodal">
+Unable to link because you don&apos;t have modify permission on all the objects.
+
+Please make sure none are locked, and that you own all of them.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotLinkDifferentOwners"
+ type="alertmodal">
+Unable to link because not all of the objects have the same owner.
+
+Please make sure you own all of the selected objects.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="NoFileExtension"
+ type="alertmodal">
+No file extension for the file: &apos;[FILE]&apos;
+
+Please make sure the file has a correct file extension.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="InvalidFileExtension"
+ type="alertmodal">
+Invalid file extension [EXTENSION]
+Expected [VALIDS]
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotUploadSoundFile"
+ type="alertmodal">
+Couldn&apos;t open uploaded sound file for reading:
+[FILE]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SoundFileNotRIFF"
+ type="alertmodal">
+File does not appear to be a RIFF WAVE file:
+[FILE]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SoundFileNotPCM"
+ type="alertmodal">
+File does not appear to be a PCM WAVE audio file:
+[FILE]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SoundFileInvalidChannelCount"
+ type="alertmodal">
+File has invalid number of channels (must be mono or stereo):
+[FILE]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SoundFileInvalidSampleRate"
+ type="alertmodal">
+File does not appear to be a supported sample rate (must be 44.1k):
+[FILE]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SoundFileInvalidWordSize"
+ type="alertmodal">
+File does not appear to be a supported word size (must be 8 or 16 bit):
+[FILE]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SoundFileInvalidHeader"
+ type="alertmodal">
+Could not find &apos;data&apos; chunk in WAV header:
+[FILE]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SoundFileInvalidTooLong"
+ type="alertmodal">
+Audio file is too long (10 second maximum):
+[FILE]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ProblemWithFile"
+ type="alertmodal">
+Problem with file [FILE]:
+
+[ERROR]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotOpenTemporarySoundFile"
+ type="alertmodal">
+Couldn&apos;t open temporary compressed sound file for writing: [FILE]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="UnknownVorbisEncodeFailure"
+ type="alertmodal">
+Unknown Vorbis encode failure on: [FILE]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotEncodeFile"
+ type="alertmodal">
+Unable to encode file: [FILE]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CorruptResourceFile"
+ type="alertmodal">
+Corrupt resource file: [FILE]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="UnknownResourceFileVersion"
+ type="alertmodal">
+Unknown Linden resource file version in file: [FILE]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="UnableToCreateOutputFile"
+ type="alertmodal">
+Unable to create output file: [FILE]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="DoNotSupportBulkAnimationUpload"
+ type="alertmodal">
+[APP_NAME] does not currently support bulk upload of animation files.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotUploadReason"
+ type="alertmodal">
+Unable to upload [FILE] due to the following reason: [REASON]
+Please try again later.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="LandmarkCreated"
+ type="notifytip">
+You have added "[LANDMARK_NAME]" to your [FOLDER_NAME] folder.
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="LandmarkAlreadyExists"
+ type="alert">
+You already have a landmark for this location.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotCreateLandmarkNotOwner"
+ type="alertmodal">
+You cannot create a landmark here because the owner of the land doesn&apos;t allow it.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotRecompileSelectObjectsNoScripts"
+ type="alertmodal">
+Not able to perform &apos;recompilation&apos;.
+Select an object with a script.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotRecompileSelectObjectsNoPermission"
+ type="alertmodal">
+Not able to perform &apos;recompilation&apos;.
+
+Select objects with scripts that you have permission to modify.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotResetSelectObjectsNoScripts"
+ type="alertmodal">
+Not able to perform &apos;reset&apos;.
+
+Select objects with scripts.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotResetSelectObjectsNoPermission"
+ type="alertmodal">
+Not able to perform &apos;reset&apos;.
+
+Select objects with scripts that you have permission to modify.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotOpenScriptObjectNoMod"
+ type="alertmodal">
+ Unable to open script in object without modify permissions.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotSetRunningSelectObjectsNoScripts"
+ type="alertmodal">
+Not able to set any scripts to &apos;running&apos;.
+
+Select objects with scripts.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotSetRunningNotSelectObjectsNoScripts"
+ type="alertmodal">
+Unable to set any scripts to &apos;not running&apos;.
+
+Select objects with scripts.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="NoFrontmostFloater"
+ type="alertmodal">
+No frontmost floater to save.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SeachFilteredOnShortWords"
+ type="alertmodal">
+Your search query was modified and the words that were too short were removed.
+
+Searched for: [FINALQUERY]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SeachFilteredOnShortWordsEmpty"
+ type="alertmodal">
+Your search terms were too short so no search was performed.
+ </notification>
+
+ <!-- Generic Teleport failure modes - strings will be inserted from
+ teleport_strings.xml if available. -->
+ <notification
+ icon="alertmodal.tga"
+ name="CouldNotTeleportReason"
+ type="alertmodal">
+Could not teleport.
+[REASON]
+ </notification>
+
+ <!-- Teleport failure modes not delivered via the generic mechanism
+ above (for example, delivered as an AlertMessage on
+ region-crossing :( ) - these paths should really be merged
+ in the future. -->
+ <notification
+ icon="alertmodal.tga"
+ name="invalid_tport"
+ type="alertmodal">
+Problem encountered processing your teleport request. You may need to log back in before you can teleport.
+If you continue to get this message, please check the [SUPPORT_SITE].
+ </notification>
+ <notification
+ icon="alertmodal.tga"
+ name="invalid_region_handoff"
+ type="alertmodal">
+Problem encountered processing your region crossing. You may need to log back in before you can cross regions.
+If you continue to get this message, please check the [SUPPORT_SITE].
+ </notification>
+ <notification
+ icon="alertmodal.tga"
+ name="blocked_tport"
+ type="alertmodal">
+Sorry, teleport is currently blocked. Try again in a moment. If you still cannot teleport, please log out and log back in to resolve the problem.
+ </notification>
+ <notification
+ icon="alertmodal.tga"
+ name="nolandmark_tport"
+ type="alertmodal">
+Sorry, but system was unable to locate landmark destination.
+ </notification>
+ <notification
+ icon="alertmodal.tga"
+ name="timeout_tport"
+ type="alertmodal">
+Sorry, but system was unable to complete the teleport connection. Try again in a moment.
+ </notification>
+ <notification
+ icon="alertmodal.tga"
+ name="noaccess_tport"
+ type="alertmodal">
+Sorry, you do not have access to that teleport destination.
+ </notification>
+ <notification
+ icon="alertmodal.tga"
+ name="missing_attach_tport"
+ type="alertmodal">
+Your attachments have not arrived yet. Try waiting for a few more seconds or log out and back in again before attempting to teleport.
+ </notification>
+ <notification
+ icon="alertmodal.tga"
+ name="too_many_uploads_tport"
+ type="alertmodal">
+The asset queue in this region is currently clogged so your teleport request will not be able to succeed in a timely manner. Please try again in a few minutes or go to a less busy area.
+ </notification>
+ <notification
+ icon="alertmodal.tga"
+ name="expired_tport"
+ type="alertmodal">
+Sorry, but the system was unable to complete your teleport request in a timely fashion. Please try again in a few minutes.
+ </notification>
+ <notification
+ icon="alertmodal.tga"
+ name="expired_region_handoff"
+ type="alertmodal">
+Sorry, but the system was unable to complete your region crossing in a timely fashion. Please try again in a few minutes.
+ </notification>
+ <notification
+ icon="alertmodal.tga"
+ name="no_host"
+ type="alertmodal">
+Unable to find teleport destination. The destination may be temporarily unavailable or no longer exists. Please try again in a few minutes.
+ </notification>
+ <notification
+ icon="alertmodal.tga"
+ name="no_inventory_host"
+ type="alertmodal">
+The inventory system is currently unavailable.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotSetLandOwnerNothingSelected"
+ type="alertmodal">
+Unable to set land owner:
+No parcel selected.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotSetLandOwnerMultipleRegions"
+ type="alertmodal">
+Unable to force land ownership because selection spans multiple regions. Please select a smaller area and try again.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ForceOwnerAuctionWarning"
+ type="alertmodal">
+This parcel is up for auction. Forcing ownership will cancel the auction and potentially make some Residents unhappy if bidding has begun.
+Force ownership?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotContentifyNothingSelected"
+ type="alertmodal">
+Unable to contentify:
+No parcel selected.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotContentifyNoRegion"
+ type="alertmodal">
+Unable to contentify:
+No region selected.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotReleaseLandNothingSelected"
+ type="alertmodal">
+Unable to abandon land:
+No parcel selected.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotReleaseLandNoRegion"
+ type="alertmodal">
+Unable to abandon land:
+Cannot find region.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotBuyLandNothingSelected"
+ type="alertmodal">
+Unable to buy land:
+No parcel selected.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotBuyLandNoRegion"
+ type="alertmodal">
+Unable to buy land:
+Cannot find the region this land is in.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotCloseFloaterBuyLand"
+ type="alertmodal">
+You cannot close the Buy Land window until [APP_NAME] estimates the price of this transaction.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotDeedLandNothingSelected"
+ type="alertmodal">
+Unable to deed land:
+No parcel selected.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotDeedLandNoGroup"
+ type="alertmodal">
+Unable to deed land:
+No Group selected.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotDeedLandNoRegion"
+ type="alertmodal">
+Unable to deed land:
+Cannot find the region this land is in.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotDeedLandMultipleSelected"
+ type="alertmodal">
+Unable to deed land:
+Multiple parcels selected.
+
+Try selecting a single parcel.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ParcelCanPlayMedia"
+ type="alertmodal">
+This location can play streaming media.
+Streaming media requires a fast Internet connection.
+
+Play streaming media when available?
+(You can change this option later under Preferences &gt; Privacy.)
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Disable"
+ yestext="Play Media"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotDeedLandWaitingForServer"
+ type="alertmodal">
+Unable to deed land:
+Waiting for server to report ownership.
+
+Please try again.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotDeedLandNoTransfer"
+ type="alertmodal">
+Unable to deed land:
+The region [REGION] does not allow transfer of land.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotReleaseLandWatingForServer"
+ type="alertmodal">
+Unable to abandon land:
+Waiting for server to update parcel information.
+
+Try again in a few seconds.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotReleaseLandSelected"
+ type="alertmodal">
+Unable to abandon land:
+You do not own all the parcels selected.
+
+Please select a single parcel.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotReleaseLandDontOwn"
+ type="alertmodal">
+Unable to abandon land:
+You don&apos;t have permission to release this parcel.
+Parcels you own appear in green.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotReleaseLandRegionNotFound"
+ type="alertmodal">
+Unable to abandon land:
+Cannot find the region this land is in.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotReleaseLandNoTransfer"
+ type="alertmodal">
+Unable to abandon land:
+The region [REGION] does not allow transfer of land.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotReleaseLandPartialSelection"
+ type="alertmodal">
+Unable to abandon land:
+You must select an entire parcel to release it.
+
+Select an entire parcel, or divide your parcel first.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ReleaseLandWarning"
+ type="alertmodal">
+You are about to release [AREA] m² of land.
+Releasing this parcel will remove it from your land holdings, but will not grant any L$.
+
+Release this land?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotDivideLandNothingSelected"
+ type="alertmodal">
+Unable to divide land:
+
+No parcels selected.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotDivideLandPartialSelection"
+ type="alertmodal">
+Unable to divide land:
+
+You have an entire parcel selected.
+Try selecting a part of the parcel.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="LandDivideWarning"
+ type="alertmodal">
+Dividing this land will split this parcel into two and each parcel can have its own settings. Some settings will be reset to defaults after the operation.
+
+Divide land?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotDivideLandNoRegion"
+ type="alertmodal">
+Unable to divide land:
+Cannot find the region this land is in.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotJoinLandNoRegion"
+ type="alertmodal">
+Unable to join land:
+Cannot find the region this land is in.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotJoinLandNothingSelected"
+ type="alertmodal">
+Unable to join land:
+No parcels selected.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotJoinLandEntireParcelSelected"
+ type="alertmodal">
+Unable to join land:
+You only have one parcel selected.
+
+Select land across both parcels.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotJoinLandSelection"
+ type="alertmodal">
+Unable to join land:
+You must select more than one parcel.
+
+Select land across both parcels.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="JoinLandWarning"
+ type="alertmodal">
+Joining this land will create one large parcel out of all parcels intersecting the selected rectangle.
+You will need to reset the name and options of the new parcel.
+
+Join land?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmNotecardSave"
+ type="alertmodal">
+This notecard needs to be saved before the item can be copied or viewed. Save notecard?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmItemCopy"
+ type="alertmodal">
+Copy this item to your inventory?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="Copy"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ResolutionSwitchFail"
+ type="alertmodal">
+Failed to switch resolution to [RESX] by [RESY]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ErrorUndefinedGrasses"
+ type="alertmodal">
+Error: Undefined grasses: [SPECIES]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ErrorUndefinedTrees"
+ type="alertmodal">
+Error: Undefined trees: [SPECIES]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotSaveWearableOutOfSpace"
+ type="alertmodal">
+Unable to save &apos;[NAME]&apos; to wearable file. You will need to free up some space on your computer and save the wearable again.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotSaveToAssetStore"
+ type="alertmodal">
+Unable to save [NAME] to central asset store.
+This is usually a temporary failure. Please customize and save the wearable again in a few minutes.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="YouHaveBeenLoggedOut"
+ type="alertmodal">
+You have been logged out of [SECOND_LIFE]:
+ [MESSAGE]
+You can still look at existing IM and chat by clicking &apos;View IM &amp; Chat&apos;. Otherwise, click &apos;Quit&apos; to exit [APP_NAME] immediately.
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Quit"
+ yestext="View IM &amp; Chat"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="OnlyOfficerCanBuyLand"
+ type="alertmodal">
+Unable to buy land for the group:
+You do not have permission to buy land for your active group.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ label="Add Friend"
+ name="AddFriend"
+ type="alertmodal">
+Friends can give permissions to track each other on the map and receive online status updates.
+
+Offer friendship to [NAME]?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ label="Add Friend"
+ name="AddFriendWithMessage"
+ type="alertmodal">
+Friends can give permissions to track each other on the map and receive online status updates.
+
+Offer friendship to [NAME]?
+ <form name="form">
+ <input name="message" type="text">
+Would you be my friend?
+ </input>
+ <button
+ default="true"
+ index="0"
+ name="Offer"
+ text="OK"/>
+ <button
+ index="1"
+ name="Cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="RemoveFromFriends"
+ type="alertmodal">
+Do you want to remove [FIRST_NAME] [LAST_NAME] from your Friends List?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="RemoveMultipleFromFriends"
+ type="alertmodal">
+Do you want to remove multiple friends from your Friends list?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="GodDeleteAllScriptedPublicObjectsByUser"
+ type="alertmodal">
+Are you sure you want to delete all scripted objects owned by
+** [AVATAR_NAME] **
+on all others land in this sim?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="GodDeleteAllScriptedObjectsByUser"
+ type="alertmodal">
+Are you sure you want to DELETE ALL scripted objects owned by
+** [AVATAR_NAME] **
+on ALL LAND in this sim?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="GodDeleteAllObjectsByUser"
+ type="alertmodal">
+Are you sure you want to DELETE ALL objects (scripted or not) owned by
+** [AVATAR_NAME] **
+on ALL LAND in this sim?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="BlankClassifiedName"
+ type="alertmodal">
+You must specify a name for your classified.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="MinClassifiedPrice"
+ type="alertmodal">
+Price to pay for listing must be at least L$[MIN_PRICE].
+
+Please enter a higher price.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmObjectDeleteLock"
+ type="alertmodal">
+At least one of the items you have selected is locked.
+
+Are you sure you want to delete these items?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmObjectDeleteNoCopy"
+ type="alertmodal">
+At least one of the items you have selected is not copyable.
+
+Are you sure you want to delete these items?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmObjectDeleteNoOwn"
+ type="alertmodal">
+You do not own least one of the items you have selected.
+
+Are you sure you want to delete these items?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmObjectDeleteLockNoCopy"
+ type="alertmodal">
+At least one object is locked.
+At least one object is not copyable.
+
+Are you sure you want to delete these items?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmObjectDeleteLockNoOwn"
+ type="alertmodal">
+At least one object is locked.
+You do not own least one object.
+
+Are you sure you want to delete these items?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmObjectDeleteNoCopyNoOwn"
+ type="alertmodal">
+At least one object is not copyable.
+You do not own least one object.
+
+Are you sure you want to delete these items?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmObjectDeleteLockNoCopyNoOwn"
+ type="alertmodal">
+At least one object is locked.
+At least one object is not copyable.
+You do not own least one object.
+
+Are you sure you want to delete these items?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmObjectTakeLock"
+ type="alertmodal">
+At least one object is locked.
+
+Are you sure you want to take these items?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmObjectTakeNoOwn"
+ type="alertmodal">
+You do not own all of the objects you are taking.
+If you continue, next owner permissions will be applied and possibly restrict your ability to modify or copy them.
+
+Are you sure you want to take these items?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmObjectTakeLockNoOwn"
+ type="alertmodal">
+At least one object is locked.
+You do not own all of the objects you are taking.
+If you continue, next owner permissions will be applied and possibly restrict your ability to modify or copy them.
+However, you can take the current selection.
+
+Are you sure you want to take these items?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CantBuyLandAcrossMultipleRegions"
+ type="alertmodal">
+Unable to buy land because selection spans multiple regions.
+
+Please select a smaller area and try again.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="DeedLandToGroup"
+ type="alertmodal">
+By deeding this parcel, the group will be required to have and maintain sufficient land use credits.
+The purchase price of the land is not refunded to the owner. If a deeded parcel is sold, the sale price will be divided evenly among group members.
+
+Deed this [AREA] m² of land to the group &apos;[GROUP_NAME]&apos;?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="DeedLandToGroupWithContribution"
+ type="alertmodal">
+By deeding this parcel, the group will be required to have and maintain sufficient land use credits.
+The deed will include a simultaneous land contribution to the group from &apos;[FIRST_NAME] [LAST_NAME]&apos;.
+The purchase price of the land is not refunded to the owner. If a deeded parcel is sold, the sale price will be divided evenly among group members.
+
+Deed this [AREA] m² of land to the group &apos;[GROUP_NAME]&apos;?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="DisplaySetToSafe"
+ type="alertmodal">
+Display settings have been set to safe levels because you have specified the -safe option.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="DisplaySetToRecommended"
+ type="alertmodal">
+Display settings have been set to recommended levels based on your system configuration.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ErrorMessage"
+ type="alertmodal">
+[ERROR_MESSAGE]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="AvatarMovedDesired"
+ type="alertmodal">
+Your desired location is not currently available.
+You have been moved into a nearby region.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="AvatarMovedLast"
+ type="alertmodal">
+Your last location is not currently available.
+You have been moved into a nearby region.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="AvatarMovedHome"
+ type="alertmodal">
+Your home location is not currently available.
+You have been moved into a nearby region.
+You may want to set a new home location.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ClothingLoading"
+ type="alertmodal">
+Your clothing is still downloading.
+You can use [SECOND_LIFE] normally and other people will see you correctly.
+ <form name="form">
+ <ignore name="ignore"
+ text="Clothing is taking a long time to download"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="FirstRun"
+ type="alertmodal">
+
+[APP_NAME] installation is complete.
+
+If this is your first time using [SECOND_LIFE], you will need to create an account before you can log in.
+Return to [http://join.secondlife.com secondlife.com] to create a new account?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Continue"
+ yestext="New Account..."/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="LoginPacketNeverReceived"
+ type="alertmodal">
+We&apos;re having trouble connecting. There may be a problem with your Internet connection or the [SECOND_LIFE_GRID].
+
+You can either check your Internet connection and try again in a few minutes, click Help to view the [SUPPORT_SITE], or click Teleport to attempt to teleport home.
+ <url option="1" name="url">
+
+ http://secondlife.com/support/
+ </url>
+ <form name="form">
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="OK"/>
+ <button
+ index="1"
+ name="Help"
+ text="Help"/>
+ <button
+ index="2"
+ name="Teleport"
+ text="Teleport"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="WelcomeChooseSex"
+ type="alertmodal">
+Your character will appear in a moment.
+
+Use arrow keys to walk.
+Press the F1 key at any time for help or to learn more about [SECOND_LIFE].
+Please choose the male or female avatar. You can change your mind later.
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Female"
+ yestext="Male"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="NotEnoughCurrency"
+ type="alertmodal">
+[NAME] L$ [PRICE] You don&apos;t have enough L$ to do that.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="GrantedModifyRights"
+ type="notify">
+[NAME] has given you permission to edit their objects.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="RevokedModifyRights"
+ type="notify">
+Your privilege to modify [NAME]&apos;s objects has been revoked
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="FlushMapVisibilityCaches"
+ type="alertmodal">
+This will flush the map caches on this region.
+This is really only useful for debugging.
+(In production, wait 5 minutes, then everyone&apos;s map will update after they relog.)
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="BuyOneObjectOnly"
+ type="alertmodal">
+Unable to buy more than one object at a time. Please select only one object and try again.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="OnlyCopyContentsOfSingleItem"
+ type="alertmodal">
+Unable to copy the contents of more than one item at a time.
+Please select only one object and try again.
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="KickUsersFromRegion"
+ type="alertmodal">
+Teleport all Residents in this region home?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="EstateObjectReturn"
+ type="alertmodal">
+Are you sure you want to return objects owned by [USER_NAME]?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="InvalidTerrainBitDepth"
+ type="alertmodal">
+Couldn&apos;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 &quot;Apply&quot; again.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="InvalidTerrainSize"
+ type="alertmodal">
+Couldn&apos;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 &quot;Apply&quot; again.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="RawUploadStarted"
+ type="alertmodal">
+Upload started. It may take up to two minutes, depending on your connection speed.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmBakeTerrain"
+ type="alertmodal">
+Do you really want to bake the current terrain, make it the center for terrain raise/lower limits and the default for the &apos;Revert&apos; tool?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="MaxAllowedAgentOnRegion"
+ type="alertmodal">
+You can only have [MAX_AGENTS] Allowed Residents.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="MaxBannedAgentsOnRegion"
+ type="alertmodal">
+You can only have [MAX_BANNED] Banned Residents.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="MaxAgentOnRegionBatch"
+ type="alertmodal">
+Failure while attempting to add [NUM_ADDED] agents:
+Exceeds the [MAX_AGENTS] [LIST_TYPE] limit by [NUM_EXCESS].
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="MaxAllowedGroupsOnRegion"
+ type="alertmodal">
+You can only have [MAX_GROUPS] Allowed Groups.
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="Bake"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="MaxManagersOnRegion"
+ type="alertmodal">
+You can only have [MAX_MANAGER] Estate Managers.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="OwnerCanNotBeDenied"
+ type="alertmodal">
+Can&apos;t add estate owner to estate &apos;Banned Resident&apos; list.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CanNotChangeAppearanceUntilLoaded"
+ type="alertmodal">
+Can&apos;t change appearance until clothing and shape are loaded.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ClassifiedMustBeAlphanumeric"
+ type="alertmodal">
+The name of your classified must start with a letter from A to Z or a number. No punctuation is allowed.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CantSetBuyObject"
+ type="alertmodal">
+Can&apos;t set Buy Object, because the object is not for sale.
+Please set the object for sale and try again.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="FinishedRawDownload"
+ type="alertmodal">
+Finished download of raw terrain file to:
+[DOWNLOAD_PATH].
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="DownloadWindowsMandatory"
+ type="alertmodal">
+A new version of [APP_NAME] is available.
+[MESSAGE]
+You must download this update to use [APP_NAME].
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Quit"
+ yestext="Download"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="DownloadWindows"
+ type="alertmodal">
+An updated version of [APP_NAME] is available.
+[MESSAGE]
+This update is not required, but we suggest you install it to improve performance and stability.
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Continue"
+ yestext="Download"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="DownloadWindowsReleaseForDownload"
+ type="alertmodal">
+An updated version of [APP_NAME] is available.
+[MESSAGE]
+This update is not required, but we suggest you install it to improve performance and stability.
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Continue"
+ yestext="Download"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="DownloadLinuxMandatory"
+ type="alertmodal">
+A new version of [APP_NAME] is available.
+[MESSAGE]
+You must download this update to use [APP_NAME].
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Quit"
+ yestext="Download"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="DownloadLinux"
+ type="alertmodal">
+An updated version of [APP_NAME] is available.
+[MESSAGE]
+This update is not required, but we suggest you install it to improve performance and stability.
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Continue"
+ yestext="Download"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="DownloadLinuxReleaseForDownload"
+ type="alertmodal">
+An updated version of [APP_NAME] is available.
+[MESSAGE]
+This update is not required, but we suggest you install it to improve performance and stability.
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Continue"
+ yestext="Download"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="DownloadMacMandatory"
+ type="alertmodal">
+A new version of [APP_NAME] is available.
+[MESSAGE]
+You must download this update to use [APP_NAME].
+
+Download to your Applications folder?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Quit"
+ yestext="Download"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="DownloadMac"
+ type="alertmodal">
+An updated version of [APP_NAME] is available.
+[MESSAGE]
+This update is not required, but we suggest you install it to improve performance and stability.
+
+Download to your Applications folder?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Continue"
+ yestext="Download"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="DownloadMacReleaseForDownload"
+ type="alertmodal">
+An updated version of [APP_NAME] is available.
+[MESSAGE]
+This update is not required, but we suggest you install it to improve performance and stability.
+
+Download to your Applications folder?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Continue"
+ yestext="Download"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="DeedObjectToGroup"
+ type="alertmodal">
+Deeding this object will cause the group to:
+* Receive L$ paid into the object
+ <usetemplate
+ ignoretext="Confirm before I deed an object to a group"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="Deed"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="WebLaunchExternalTarget"
+ type="alertmodal">
+Do you want to open your Web browser to view this content?
+ <usetemplate
+ ignoretext="Launch my browser to view a web page"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="WebLaunchJoinNow"
+ type="alertmodal">
+Go to your [http://secondlife.com/account/ Dashboard] to manage your account?
+ <usetemplate
+ ignoretext="Launch my browser to manage my account"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="WebLaunchSecurityIssues"
+ type="alertmodal">
+Visit the [SECOND_LIFE] Wiki for details of how to report a security issue.
+ <usetemplate
+ ignoretext="Launch my browser to learn how to report a Security Issue"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="WebLaunchQAWiki"
+ type="alertmodal">
+Visit the [SECOND_LIFE] QA Wiki.
+ <usetemplate
+ ignoretext="Launch my browser to view the QA Wiki"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="WebLaunchPublicIssue"
+ type="alertmodal">
+Visit the [SECOND_LIFE] Public Issue Tracker, where you can report bugs and other issues.
+ <usetemplate
+ ignoretext="Launch my browser to use the Public Issue Tracker"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="Go to page"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="WebLaunchSupportWiki"
+ type="alertmodal">
+Go to the Official Linden Blog, for the latest news and information.
+ <usetemplate
+ ignoretext="Launch my browser to view the blog"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="WebLaunchLSLGuide"
+ type="alertmodal">
+Do you want to open the Scripting Guide for help with scripting?
+ <usetemplate
+ ignoretext="Launch my browser to view the Scripting Guide"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="WebLaunchLSLWiki"
+ type="alertmodal">
+Do you want to visit the LSL Portal for help with scripting?
+ <usetemplate
+ ignoretext="Launch my browser to view the LSL Portal"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="Go to page"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ReturnToOwner"
+ type="alertmodal">
+Are you sure you want to return the selected objects to their owners? Transferable deeded objects will be returned to their previous owners.
+
+*WARNING* No-transfer deeded objects will be deleted!
+ <usetemplate
+ ignoretext="Confirm before I return objects to their owners"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="GroupLeaveConfirmMember"
+ type="alert">
+You are currently a member of the group [GROUP].
+Leave Group?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="ConfirmKick"
+ type="alert">
+Do you REALLY want to kick all users off the grid?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="Kick All Users"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="MuteLinden"
+ type="alertmodal">
+Sorry, you cannot block a Linden.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotStartAuctionAlreadyForSale"
+ type="alertmodal">
+You cannot start an auction on a parcel which is already set for sale. Disable the land sale if you are sure you want to start an auction.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ label="Block object by name failed"
+ name="MuteByNameFailed"
+ type="alertmodal">
+You already have blocked this name.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="RemoveItemWarn"
+ type="alert">
+Though permitted, deleting contents may damage the object. Do you want to delete that item?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="CantOfferCallingCard"
+ type="alert">
+Cannot offer a calling card at this time. Please try again in a moment.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="CantOfferFriendship"
+ type="alert">
+Cannot offer friendship at this time. Please try again in a moment.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="BusyModeSet"
+ type="alert">
+Busy mode is set.
+Chat and instant messages will be hidden. Instant messages will get your Busy mode response. All teleportation offers will be declined. All inventory offers will go to your Trash.
+ <usetemplate
+ ignoretext="I change my status to Busy mode"
+ name="okignore"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="JoinedTooManyGroupsMember"
+ type="alert">
+You have reached your maximum number of groups. Please leave another group before joining this one, or decline the offer.
+[NAME] has invited you to join a group as a member.
+[INVITE]
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Decline"
+ yestext="Join"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="JoinedTooManyGroups"
+ type="alert">
+You have reached your maximum number of groups. Please leave some group before joining or creating a new one.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="KickUser"
+ type="alert">
+Kick this user with what message?
+ <form name="form">
+ <input name="message" type="text">
+An administrator has logged you off.
+ </input>
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="OK"/>
+ <button
+ index="1"
+ name="Cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="KickAllUsers"
+ type="alert">
+Kick everyone currently on the grid with what message?
+ <form name="form">
+ <input name="message" type="text">
+An administrator has logged you off.
+ </input>
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="OK"/>
+ <button
+ index="1"
+ name="Cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="FreezeUser"
+ type="alert">
+Freeze this user with what message?
+ <form name="form">
+ <input name="message" type="text">
+You have been frozen. You cannot move or chat. An administrator will contact you via instant message (IM).
+ </input>
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="OK"/>
+ <button
+ index="1"
+ name="Cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="UnFreezeUser"
+ type="alert">
+Unfreeze this user with what message?
+ <form name="form">
+ <input name="message" type="text">
+You are no longer frozen.
+ </input>
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="OK"/>
+ <button
+ index="1"
+ name="Cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="OfferTeleport"
+ type="alertmodal">
+Offer a teleport to your location with the following message?
+ <form name="form">
+ <input name="message" type="text">
+Join me in [REGION]
+ </input>
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="OK"/>
+ <button
+ index="1"
+ name="Cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="OfferTeleportFromGod"
+ type="alertmodal">
+God summon user to your location?
+ <form name="form">
+ <input name="message" type="text">
+Join me in [REGION]
+ </input>
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="OK"/>
+ <button
+ index="1"
+ name="Cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="TeleportFromLandmark"
+ type="alertmodal">
+Are you sure you want to teleport to [LOCATION]?
+ <usetemplate
+ ignoretext="Confirm that I want to teleport to a landmark"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="Teleport"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="TeleportToPick"
+ type="alertmodal">
+Teleport to [PICK]?
+ <usetemplate
+ ignoretext="Confirm that I want to teleport to a location in Picks"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="Teleport"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="TeleportToClassified"
+ type="alertmodal">
+ Teleport to [CLASSIFIED]?
+ <usetemplate
+ ignoretext="Confirm that I want to teleport to a location in Classifieds"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="Teleport"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ label="Message everyone in your Estate"
+ name="MessageEstate"
+ type="alert">
+Type a short announcement which will be sent to everyone currently in your estate.
+ <form name="form">
+ <input name="message" type="text"/>
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="OK"/>
+ <button
+ index="1"
+ name="Cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ label="Change Linden Estate"
+ name="ChangeLindenEstate"
+ type="alert">
+You are about to change a Linden owned estate (mainland, teen grid, orientation, etc.).
+
+This is EXTREMELY DANGEROUS because it can fundamentally affect the user experience. On the mainland, it will change thousands of regions and make the spaceserver hiccup.
+
+Proceed?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ label="Change Linden Estate Access"
+ name="ChangeLindenAccess"
+ type="alert">
+You are about to change the access list for a Linden owned estate (mainland, teen grid, orientation, etc.).
+
+This is DANGEROUS and should only be done to invoke the hack allowing objects/L$ to be transfered in/out of a grid.
+It will change thousands of regions and make the spaceserver hiccup.
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ label="Select estate"
+ name="EstateAllowedAgentAdd"
+ type="alert">
+Add to allowed list for this estate only or for [ALL_ESTATES]?
+ <usetemplate
+ canceltext="Cancel"
+ name="yesnocancelbuttons"
+ notext="All Estates"
+ yestext="This Estate"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ label="Select estate"
+ name="EstateAllowedAgentRemove"
+ type="alert">
+Remove from allowed list for this estate only or for [ALL_ESTATES]?
+ <usetemplate
+ canceltext="Cancel"
+ name="yesnocancelbuttons"
+ notext="All Estates"
+ yestext="This Estate"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ label="Select estate"
+ name="EstateAllowedGroupAdd"
+ type="alert">
+Add to group allowed list for this estate only or for [ALL_ESTATES]?
+ <usetemplate
+ canceltext="Cancel"
+ name="yesnocancelbuttons"
+ notext="All Estates"
+ yestext="This Estate"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ label="Select estate"
+ name="EstateAllowedGroupRemove"
+ type="alert">
+Remove from group allowed list for this estate only or [ALL_ESTATES]?
+ <usetemplate
+ canceltext="Cancel"
+ name="yesnocancelbuttons"
+ notext="All Estates"
+ yestext="This Estate"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ label="Select estate"
+ name="EstateBannedAgentAdd"
+ type="alert">
+Deny access for this estate only or for [ALL_ESTATES]?
+ <usetemplate
+ canceltext="Cancel"
+ name="yesnocancelbuttons"
+ notext="All Estates"
+ yestext="This Estate"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ label="Select estate"
+ name="EstateBannedAgentRemove"
+ type="alert">
+Remove this Resident from the ban list for access for this estate only or for [ALL_ESTATES]?
+ <usetemplate
+ canceltext="Cancel"
+ name="yesnocancelbuttons"
+ notext="All Estates"
+ yestext="This Estate"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ label="Select estate"
+ name="EstateManagerAdd"
+ type="alert">
+Add estate manager for this estate only or for [ALL_ESTATES]?
+ <usetemplate
+ canceltext="Cancel"
+ name="yesnocancelbuttons"
+ notext="All Estates"
+ yestext="This Estate"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ label="Select estate"
+ name="EstateManagerRemove"
+ type="alert">
+Remove estate manager for this estate only or for [ALL_ESTATES]?
+ <usetemplate
+ canceltext="Cancel"
+ name="yesnocancelbuttons"
+ notext="All Estates"
+ yestext="This Estate"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ label="Confirm Kick"
+ name="EstateKickUser"
+ type="alert">
+Kick [EVIL_USER] from this estate?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="EstateChangeCovenant"
+ type="alertmodal">
+Are you sure you want to change the Estate Covenant?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="RegionEntryAccessBlocked"
+ type="alertmodal">
+You are not allowed in that Region due to your maturity Rating. This may be a result of a lack of information validating your age.
+
+Please verify you have the latest Viewer installed, and go to the Knowledge Base for details on accessing areas with this maturity rating.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="RegionEntryAccessBlocked_KB"
+ type="alertmodal">
+You are not allowed in that region due to your maturity Rating.
+
+Go to the Knowledge Base for more information about maturity Ratings?
+ <url option="0" name="url">
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview
+ </url>
+ <usetemplate
+ name="okcancelignore"
+ yestext="Go to Knowledge Base"
+ notext="Close"
+ ignoretext="I can&apos;t enter this Region, due to restrictions of the maturity Rating"/>
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="RegionEntryAccessBlocked_Notify"
+ type="notifytip">
+You are not allowed in that region due to your maturity Rating.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="RegionEntryAccessBlocked_Change"
+ type="alertmodal">
+You are not allowed in that Region due to your maturity Rating preference.
+
+You can click &apos;Change Preference&apos; to raise your maturity Rating preference now and allow you to enter. You will be able to search and access [REGIONMATURITY] content from now on. If you later want to change this setting back, go to Me &gt; Preferences &gt; General.
+ <form name="form">
+ <button
+ index="0"
+ name="OK"
+ text="Change Preference"/>
+ <button
+ default="true"
+ index="1"
+ name="Cancel"
+ text="Close"/>
+ <ignore name="ignore" text="My chosen Rating preference prevents me from entering a Region"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="LandClaimAccessBlocked"
+ type="alertmodal">
+You cannot claim this land due to your maturity Rating. This may be a result of a lack of information validating your age.
+
+Please verify you have the latest Viewer installed, and go to the Knowledge Base for details on accessing areas with this maturity rating.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="LandClaimAccessBlocked_KB"
+ type="alertmodal">
+You cannot claim this land due to your maturity Rating.
+
+Go to the Knowledge Base for more information about maturity Ratings?
+ <url option="0" name="url">
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview
+ </url>
+ <usetemplate
+ name="okcancelignore"
+ yestext="Go to Knowledge Base"
+ notext="Close"
+ ignoretext="I can&apos;t claim this Land, due to restrictions of the maturity Rating"/>
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="LandClaimAccessBlocked_Notify"
+ type="notifytip">
+You cannot claim this land due to your maturity Rating.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="LandClaimAccessBlocked_Change"
+ type="alertmodal">
+You cannot claim this land due to your maturity Rating preference.
+
+You can click &apos;Change Preference&apos; to raise your maturity Rating preference now and allow you to enter. You will be able to search and access [REGIONMATURITY] content from now on. If you later want to change this setting back, go to Me &gt; Preferences &gt; General.
+ <usetemplate
+ name="okcancelignore"
+ yestext="Change Preference"
+ notext="Close"
+ ignoretext="My chosen Rating preference prevents me from claiming Land"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="LandBuyAccessBlocked"
+ type="alertmodal">
+You cannot buy this land due to your maturity Rating. This may be a result of a lack of information validating your age.
+
+Please verify you have the latest Viewer installed, and go to the Knowledge Base for details on accessing areas with this maturity rating.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="LandBuyAccessBlocked_KB"
+ type="alertmodal">
+You cannot buy this land due to your maturity Rating.
+
+Go to the Knowledge Base for more information about maturity Ratings?
+ <url option="0" name="url">
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview
+ </url>
+ <usetemplate
+ name="okcancelignore"
+ yestext="Go to Knowledge Base"
+ notext="Close"
+ ignoretext="I can&apos;t buy this Land, due to restrictions of the maturity Rating"/>
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="LandBuyAccessBlocked_Notify"
+ type="notifytip">
+You cannot buy this land due to your maturity Rating.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="LandBuyAccessBlocked_Change"
+ type="alertmodal">
+You cannot buy this land due to your maturity Rating preference.
+
+You can click &apos;Change Preference&apos; to raise your maturity Rating preference now and allow you to enter. You will be able to search and access [REGIONMATURITY] content from now on. If you later want to change this setting back, go to Me &gt; Preferences &gt; General.
+ <usetemplate
+ name="okcancelignore"
+ yestext="Change Preference"
+ notext="Close"
+ ignoretext="My chosen Rating preference prevents me from buying Land"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="TooManyPrimsSelected"
+ type="alertmodal">
+There are too many prims selected. Please select [MAX_PRIM_COUNT] or fewer prims and try again
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ProblemImportingEstateCovenant"
+ type="alertmodal">
+Problem importing estate covenant.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ProblemAddingEstateManager"
+ type="alertmodal">
+Problems adding a new estate manager. One or more estates may have a full manager list.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ProblemAddingEstateGeneric"
+ type="alertmodal">
+Problems adding to this estate list. One or more estates may have a full list.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="UnableToLoadNotecardAsset"
+ type="alertmodal">
+Unable to load notecard&apos;s asset at this time.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="NotAllowedToViewNotecard"
+ type="alertmodal">
+Insufficient permissions to view notecard associated with asset ID requested.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="MissingNotecardAssetID"
+ type="alertmodal">
+Asset ID for notecard is missing from database.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="PublishClassified"
+ type="alert">
+Remember: Classified ad fees are non-refundable.
+
+Publish this classified now for L$[AMOUNT]?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SetClassifiedMature"
+ type="alertmodal">
+Does this classified contain Moderate content?
+ <usetemplate
+ canceltext="Cancel"
+ name="yesnocancelbuttons"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SetGroupMature"
+ type="alertmodal">
+Does this group contain Moderate content?
+ <usetemplate
+ canceltext="Cancel"
+ name="yesnocancelbuttons"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ label="Confirm restart"
+ name="ConfirmRestart"
+ type="alert">
+Do you really want to restart this region in 2 minutes?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ label="Message everyone in this region"
+ name="MessageRegion"
+ type="alert">
+Type a short announcement which will be sent to everyone in this region.
+ <form name="form">
+ <input name="message" type="text"/>
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="OK"/>
+ <button
+ index="1"
+ name="Cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ label="Changed Region Maturity"
+ name="RegionMaturityChange"
+ type="alertmodal">
+The maturity rating for this region has been updated.
+It may take some time for the change to be reflected on the map.
+
+To enter Adult regions, Residents must be Account Verified, either by age-verification or payment-verification.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ label="Voice Version Mismatch"
+ name="VoiceVersionMismatch"
+ type="alertmodal">
+This version of [APP_NAME] is not compatible with the Voice Chat feature in this region. In order for Voice Chat to function correctly you will need to update [APP_NAME].
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ label="Can&apos;t Buy Objects"
+ name="BuyObjectOneOwner"
+ type="alertmodal">
+Cannot buy objects from different owners at the same time.
+Please select only one object and try again.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ label="Can&apos;t Buy Contents"
+ name="BuyContentsOneOnly"
+ type="alertmodal">
+Unable to buy the contents of more than one object at a time.
+Please select only one object and try again.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ label="Can&apos;t Buy Contents"
+ name="BuyContentsOneOwner"
+ type="alertmodal">
+Cannot buy objects from different owners at the same time.
+Please select only one object and try again.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="BuyOriginal"
+ type="alertmodal">
+Buy original object from [OWNER] for L$[PRICE]?
+You will become the owner of this object.
+You will be able to:
+ Modify: [MODIFYPERM]
+ Copy: [COPYPERM]
+ Resell or Give Away: [RESELLPERM]
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="BuyOriginalNoOwner"
+ type="alertmodal">
+Buy original object for L$[PRICE]?
+You will become the owner of this object.
+You will be able to:
+ Modify: [MODIFYPERM]
+ Copy: [COPYPERM]
+ Resell or Give Away: [RESELLPERM]
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="BuyCopy"
+ type="alertmodal">
+Buy a copy from [OWNER] for L$[PRICE]?
+The object will be copied to your inventory.
+You will be able to:
+ Modify: [MODIFYPERM]
+ Copy: [COPYPERM]
+ Resell or Give Away: [RESELLPERM]
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="BuyCopyNoOwner"
+ type="alertmodal">
+Buy a copy for L$[PRICE]?
+The object will be copied to your inventory.
+You will be able to:
+ Modify: [MODIFYPERM]
+ Copy: [COPYPERM]
+ Resell or Give Away: [RESELLPERM]
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="BuyContents"
+ type="alertmodal">
+Buy contents from [OWNER] for L$[PRICE]?
+They will be copied to your inventory.
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="BuyContentsNoOwner"
+ type="alertmodal">
+Buy contents for L$[PRICE]?
+They will be copied to your inventory.
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmPurchase"
+ type="alertmodal">
+This transaction will:
+[ACTION]
+
+Are you sure you want to proceed with this purchase?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmPurchasePassword"
+ type="password">
+This transaction will:
+[ACTION]
+
+Are you sure you want to proceed with this purchase?
+Please re-enter your password and click OK.
+ <form name="form">
+ <input
+ name="message"
+ type="password"/>
+ <button
+ default="true"
+ index="0"
+ name="ConfirmPurchase"
+ text="OK"/>
+ <button
+ index="1"
+ name="Cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="SetPickLocation"
+ type="alert">
+Note:
+You have updated the location of this pick but the other details will retain their original values.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="MoveInventoryFromObject"
+ type="alertmodal">
+You have selected &apos;no copy&apos; inventory items.
+These items will be moved to your inventory, not copied.
+
+Move the inventory item(s)?
+ <usetemplate
+ ignoretext="Warn me before I move &apos;no-copy&apos; items from an object"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="MoveInventoryFromScriptedObject"
+ type="alertmodal">
+You have selected &apos;no copy&apos; inventory items. These items will be moved to your inventory, not copied.
+Because this object is scripted, moving these items to your inventory may cause the script to malfunction.
+
+Move the inventory item(s)?
+ <usetemplate
+ ignoretext="Warn me before I move &apos;no-copy&apos; items which might break a scripted object"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="ClickActionNotPayable"
+ type="alert">
+Warning: The &apos;Pay object&apos; click action has been set, but it will only work if a script is added with a money() event.
+ <form name="form">
+ <ignore name="ignore"
+ text="I set the action &apos;Pay object&apos; when building an object without a money() script"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="OpenObjectCannotCopy"
+ type="alertmodal">
+There are no items in this object that you are allowed to copy.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="WebLaunchAccountHistory"
+ type="alertmodal">
+Go to your [http://secondlife.com/account/ Dashboard] to see your account history?
+ <usetemplate
+ ignoretext="Launch my browser to see my account history"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="Go to page"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmQuit"
+ type="alertmodal">
+Are you sure you want to quit?
+ <usetemplate
+ ignoretext="Confirm before I quit"
+ name="okcancelignore"
+ notext="Don&apos;t Quit"
+ yestext="Quit"/>
+ <unique/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="HelpReportAbuseEmailLL"
+ type="alertmodal">
+Use this tool to report violations of the [http://secondlife.com/corporate/tos.php Terms of Service] and [http://secondlife.com/corporate/cs.php Community Standards].
+
+All reported abuses are investigated and resolved. You can view the resolution by reading the [http://secondlife.com/support/incidentreport.php Incident Report].
+ <unique/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="HelpReportAbuseSelectCategory"
+ type="alertmodal">
+Please select a category for this abuse report.
+Selecting a category helps us file and process abuse reports.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="HelpReportAbuseAbuserNameEmpty"
+ type="alertmodal">
+Please enter the name of the abuser.
+Entering an accurate value helps us file and process abuse reports.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="HelpReportAbuseAbuserLocationEmpty"
+ type="alertmodal">
+Please enter the location where the abuse took place.
+Entering an accurate value helps us file and process abuse reports.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="HelpReportAbuseSummaryEmpty"
+ type="alertmodal">
+Please enter a summary of the abuse that took place.
+Entering an accurate summary helps us file and process abuse reports.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="HelpReportAbuseDetailsEmpty"
+ type="alertmodal">
+Please enter a detailed description of the abuse that took place.
+Be as specific as you can, including names and the details of the incident you are reporting.
+Entering an accurate description helps us file and process abuse reports.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="HelpReportAbuseContainsCopyright"
+ type="alertmodal">
+Dear Resident,
+
+You appear to be reporting intellectual property infringement. Please make sure you are reporting it correctly:
+
+(1) The Abuse Process. You may submit an abuse report if you believe a Resident is exploiting the [SECOND_LIFE] permissions system, for example, by using CopyBot or similar copying tools, to infringe intellectual property rights. The Abuse Team investigates and issues appropriate disciplinary action for behavior that violates the [SECOND_LIFE] [http://secondlife.com/corporate/tos.php Terms of Service] or [http://secondlife.com/corporate/cs.php Community Standards]. However, the Abuse Team does not handle and will not respond to requests to remove content from the [SECOND_LIFE] world.
+
+(2) The DMCA or Content Removal Process. To request removal of content from [SECOND_LIFE], you MUST submit a valid notification of infringement as provided in our [http://secondlife.com/corporate/dmca.php DMCA Policy].
+
+If you still wish to continue with the abuse process, please close this window and finish submitting your report. You may need to select the specific category &apos;CopyBot or Permissions Exploit&apos;.
+
+Thank you,
+
+Linden Lab
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="FailedRequirementsCheck"
+ type="alertmodal">
+The following required components are missing from [FLOATER]:
+[COMPONENTS]
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ label="Replace Existing Attachment"
+ name="ReplaceAttachment"
+ type="alert">
+There is already an object attached to this point on your body.
+Do you want to replace it with the selected object?
+ <form name="form">
+ <ignore name="ignore"
+ save_option="true"
+ text="Replace an existing attachment with the selected item"/>
+ <button
+ default="true"
+ ignore="Replace Automatically"
+ index="0"
+ name="Yes"
+ text="OK"/>
+ <button
+ ignore="Never Replace"
+ index="1"
+ name="No"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ label="Busy Mode Warning"
+ name="BusyModePay"
+ type="alert">
+You are in Busy Mode, which means you will not receive any items offered in exchange for this payment.
+
+Would you like to leave Busy Mode before completing this transaction?
+ <form name="form">
+ <ignore name="ignore"
+ save_option="true"
+ text="I am about to pay a person or object while I am in Busy mode"/>
+ <button
+ default="true"
+ ignore="Always leave Busy Mode"
+ index="0"
+ name="Yes"
+ text="OK"/>
+ <button
+ ignore="Never leave Busy Mode"
+ index="1"
+ name="No"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmDeleteProtectedCategory"
+ type="alertmodal">
+The folder &apos;[FOLDERNAME]&apos; is a system folder. Deleting system folders can cause instability. Are you sure you want to delete it?
+ <usetemplate
+ ignoretext="Confirm before I delete a system folder"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmEmptyTrash"
+ type="alertmodal">
+Are you sure you want to permanently delete the contents of your Trash?
+ <usetemplate
+ ignoretext="Confirm before I empty the inventory Trash folder"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmClearBrowserCache"
+ type="alertmodal">
+Are you sure you want to delete your travel, web, and search history?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmClearCookies"
+ type="alertmodal">
+Are you sure you want to clear your cookies?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmClearMediaUrlList"
+ type="alertmodal">
+Are you sure you want to clear your list of saved URLs?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmEmptyLostAndFound"
+ type="alertmodal">
+Are you sure you want to permanently delete the contents of your Lost And Found?
+ <usetemplate
+ ignoretext="Confirm before I empty the inventory Lost And Found folder"
+ name="okcancelignore"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="CopySLURL"
+ type="alertmodal">
+The following SLurl has been copied to your clipboard:
+ [SLURL]
+
+Link to this from a web page to give others easy access to this location, or try it out yourself by pasting it into the address bar of any web browser.
+ <form name="form">
+ <ignore name="ignore"
+ text="SLurl is copied to my clipboard"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="WLSavePresetAlert"
+ type="alertmodal">
+Do you wish to overwrite the saved preset?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="WLDeletePresetAlert"
+ type="alertmodal">
+Do you wish to delete [SKY]?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="WLNoEditDefault"
+ type="alertmodal">
+You cannot edit or delete a default preset.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="WLMissingSky"
+ type="alertmodal">
+This day cycle file references a missing sky file: [SKY].
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="PPSaveEffectAlert"
+ type="alertmodal">
+PostProcess Effect exists. Do you still wish overwrite it?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="NewSkyPreset"
+ type="alert">
+Give me a name for the new sky.
+ <form name="form">
+ <input name="message" type="text">
+New Preset
+ </input>
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="OK"/>
+ <button
+ index="1"
+ name="Cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ExistsSkyPresetAlert"
+ type="alertmodal">
+Preset already exists!
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="NewWaterPreset"
+ type="alert">
+Give me a name for the new water preset.
+ <form name="form">
+ <input name="message" type="text">
+New Preset
+ </input>
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="OK"/>
+ <button
+ index="1"
+ name="Cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ExistsWaterPresetAlert"
+ type="alertmodal">
+Preset already exists!
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="WaterNoEditDefault"
+ type="alertmodal">
+You cannot edit or delete a default preset.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ChatterBoxSessionStartError"
+ type="alertmodal">
+Unable to start a new chat session with [RECIPIENT].
+[REASON]
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ChatterBoxSessionEventError"
+ type="alertmodal">
+[EVENT]
+[REASON]
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ForceCloseChatterBoxSession"
+ type="alertmodal">
+Your chat session with [NAME] must close.
+[REASON]
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="Cannot_Purchase_an_Attachment"
+ type="alertmodal">
+You can&apos;t buy an object while it is attached.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ label="About Requests for the Debit Permission"
+ name="DebitPermissionDetails"
+ type="alertmodal">
+Granting this request gives a script ongoing permission to take Linden dollars (L$) from your account. To revoke this permission, the object owner must delete the object or reset the scripts in the object.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="AutoWearNewClothing"
+ type="alertmodal">
+Would you like to automatically wear the clothing you are about to create?
+ <usetemplate
+ ignoretext="Wear the clothing I create while editing My Appearance"
+ name="okcancelignore"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="NotAgeVerified"
+ type="alertmodal">
+You must be age-verified to visit this area. Do you want to go to the [SECOND_LIFE] website and verify your age?
+
+[_URL]
+ <url option="0" name="url">
+
+ https://secondlife.com/account/verification.php
+ </url>
+ <usetemplate
+ ignoretext="I have not verified my age"
+ name="okcancelignore"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="Cannot enter parcel: no payment info on file"
+ type="alertmodal">
+You must have payment information on file to visit this area. Do you want to go to the [SECOND_LIFE] website and set this up?
+
+[_URL]
+ <url option="0" name="url">
+
+ https://secondlife.com/account/
+ </url>
+ <usetemplate
+ ignoretext="I lack payment information on file"
+ name="okcancelignore"
+ notext="No"
+ yestext="Yes"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="MissingString"
+ type="alertmodal">
+The string [STRING_NAME] is missing from strings.xml
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="SystemMessageTip"
+ type="notifytip">
+[MESSAGE]
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="Cancelled"
+ type="notifytip">
+Cancelled
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="CancelledSit"
+ type="notifytip">
+Cancelled Sit
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="CancelledAttach"
+ type="notifytip">
+Cancelled Attach
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="ReplacedMissingWearable"
+ type="notifytip">
+Replaced missing clothing/body part with default.
+ </notification>
+
+ <notification
+ icon="groupnotify"
+ name="GroupNotice"
+ type="groupnotify">
+Topic: [SUBJECT], Message: [MESSAGE]
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="FriendOnline"
+ type="notifytip">
+[FIRST] [LAST] is Online
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="FriendOffline"
+ type="notifytip">
+[FIRST] [LAST] is Offline
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="AddSelfFriend"
+ type="notifytip">
+Although you&apos;re very nice, you can&apos;t add yourself as a friend.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="UploadingAuctionSnapshot"
+ type="notifytip">
+Uploading in-world and web site snapshots...
+(Takes about 5 minutes.)
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="UploadPayment"
+ type="notify">
+You paid L$[AMOUNT] to upload.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="UploadWebSnapshotDone"
+ type="notifytip">
+Web site snapshot upload done.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="UploadSnapshotDone"
+ type="notifytip">
+In-world snapshot upload done
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="TerrainDownloaded"
+ type="notifytip">
+Terrain.raw downloaded
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="GestureMissing"
+ type="notifytip">
+Hmm. Gesture [NAME] is missing from the database.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="UnableToLoadGesture"
+ type="notifytip">
+Unable to load gesture [NAME].
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="LandmarkMissing"
+ type="notifytip">
+Landmark is missing from database.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="UnableToLoadLandmark"
+ type="notifytip">
+Unable to load landmark. Please try again.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="CapsKeyOn"
+ type="notifytip">
+Your Caps Lock key is on.
+This might affect your password.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="NotecardMissing"
+ type="notifytip">
+Notecard is missing from database.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="NotecardNoPermissions"
+ type="notifytip">
+You don&apos;t have permission to view this notecard.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="RezItemNoPermissions"
+ type="notifytip">
+Insufficient permissions to rez object.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="UnableToLoadNotecard"
+ type="notifytip">
+Unable to load notecard.
+Please try again.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="ScriptMissing"
+ type="notifytip">
+Script is missing from database.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="ScriptNoPermissions"
+ type="notifytip">
+Insufficient permissions to view script.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="UnableToLoadScript"
+ type="notifytip">
+Unable to load script. Please try again.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="IncompleteInventory"
+ type="notifytip">
+The complete contents you are offering are not yet locally available. Please try offering those items again in a minute.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="CannotModifyProtectedCategories"
+ type="notifytip">
+You cannot modify protected categories.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="CannotRemoveProtectedCategories"
+ type="notifytip">
+You cannot remove protected categories.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="OfferedCard"
+ type="notifytip">
+You have offered a calling card to [FIRST] [LAST]
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="UnableToBuyWhileDownloading"
+ type="notifytip">
+Unable to buy while downloading object data.
+Please try again.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="UnableToLinkWhileDownloading"
+ type="notifytip">
+Unable to link while downloading object data.
+Please try again.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="CannotBuyObjectsFromDifferentOwners"
+ type="notifytip">
+You can only buy objects from one owner at a time.
+Please select a single object.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="ObjectNotForSale"
+ type="notifytip">
+This object is not for sale.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="EnteringGodMode"
+ type="notifytip">
+Entering god mode, level [LEVEL]
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="LeavingGodMode"
+ type="notifytip">
+Now leaving god mode, level [LEVEL]
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="CopyFailed"
+ type="notifytip">
+You don&apos;t have permission to copy this.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="InventoryAccepted"
+ type="notifytip">
+[NAME] received your inventory offer.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="InventoryDeclined"
+ type="notifytip">
+[NAME] declined your inventory offer.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="ObjectMessage"
+ type="notifytip">
+[NAME]: [MESSAGE]
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="CallingCardAccepted"
+ type="notifytip">
+Your calling card was accepted.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="CallingCardDeclined"
+ type="notifytip">
+Your calling card was declined.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="TeleportToLandmark"
+ type="notifytip">
+You can teleport to locations like &apos;[NAME]&apos; by opening the Places panel on the right side of your screen, and then select the Landmarks tab.
+Click on any landmark to select it, then click &apos;Teleport&apos; at the bottom of the panel.
+(You can also double-click on the landmark, or right-click it and choose &apos;Teleport&apos;.)
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="TeleportToPerson"
+ type="notifytip">
+You can contact Residents like &apos;[NAME]&apos; by opening the People panel on the right side of your screen.
+Select the Resident from the list, then click &apos;IM&apos; at the bottom of the panel.
+(You can also double-click on their name in the list, or right-click and choose &apos;IM&apos;).
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="CantSelectLandFromMultipleRegions"
+ type="notifytip">
+Can&apos;t select land across server boundaries.
+Try selecting a smaller piece of land.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="SearchWordBanned"
+ type="notifytip">
+Some terms in your search query were excluded due to content restrictions as clarified in the Community Standards.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="NoContentToSearch"
+ type="notifytip">
+Please select at least one type of content to search (General, Moderate, or Adult).
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="GroupVote"
+ type="notify">
+[NAME] has proposed to vote on:
+[MESSAGE]
+ <form name="form">
+ <button
+ index="0"
+ name="VoteNow"
+ text="Vote Now"/>
+ <button
+ index="1"
+ name="Later"
+ text="Later"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="SystemMessage"
+ type="notify">
+[MESSAGE]
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="PaymentRecived"
+ type="notify">
+[MESSAGE]
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="EventNotification"
+ type="notify">
+Event Notification:
+
+[NAME]
+[DATE]
+ <form name="form">
+ <button
+ index="0"
+ name="Teleport"
+ text="Teleport"/>
+ <button
+ index="1"
+ name="Description"
+ text="Description"/>
+ <button
+ index="2"
+ name="Cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="TransferObjectsHighlighted"
+ type="notify">
+All objects on this parcel that will transfer to the purchaser of this parcel are now highlighted.
+
+* Trees and grasses that will transfer are not highlighted.
+ <form name="form">
+ <button
+ index="0"
+ name="Done"
+ text="Done"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="DeactivatedGesturesTrigger"
+ type="notify">
+Deactivated gestures with same trigger:
+[NAMES]
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="NoQuickTime"
+ type="notify">
+Apple&apos;s QuickTime software does not appear to be installed on your system.
+If you want to view streaming media on parcels that support it you should go to the [http://www.apple.com/quicktime QuickTime site] and install the QuickTime Player.
+ </notification>
+ <notification
+ icon="notify.tga"
+ name="NoPlugin"
+ type="notify">
+No Media Plugin was found to handle the "[MIME_TYPE]" mime type. Media of this type will be unavailable.
+ </notification>
+ <notification
+ icon="alertmodal.tga"
+ name="MediaPluginFailed"
+ type="alertmodal">
+The following Media Plugin has failed:
+ [PLUGIN]
+
+Please re-install the plugin or contact the vendor if you continue to experience problems.
+ <form name="form">
+ <ignore name="ignore"
+ text="A Media Plugin fails to run"/>
+ </form>
+ </notification>
+ <notification
+ icon="notify.tga"
+ name="OwnedObjectsReturned"
+ type="notify">
+The objects you own on the selected parcel of land have been returned back to your inventory.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="OtherObjectsReturned"
+ type="notify">
+The objects on the selected parcel of land that is owned by [FIRST] [LAST] have been returned to his or her inventory.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="OtherObjectsReturned2"
+ type="notify">
+The objects on the selected parcel of land owned by the Resident &apos;[NAME]&apos; have been returned to their owner.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="GroupObjectsReturned"
+ type="notify">
+The objects on the selected parcel of land shared with the group [GROUPNAME] have been returned back to their owner&apos;s inventory.
+Transferable deeded objects have been returned to their previous owners.
+Non-transferable objects that are deeded to the group have been deleted.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="UnOwnedObjectsReturned"
+ type="notify">
+The objects on the selected parcel that are NOT owned by you have been returned to their owners.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="ServerObjectMessage"
+ type="notify">
+Message from [NAME]:
+[MSG]
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="NotSafe"
+ type="notify">
+This land has damage enabled.
+You can be hurt here. If you die, you will be teleported to your home location.
+ <unique/>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="NoFly"
+ type="notify">
+This area has flying disabled.
+You can&apos;t fly here.
+ <unique/>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="PushRestricted"
+ type="notify">
+This area does not allow pushing. You can&apos;t push others here unless you own the land.
+ <unique/>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="NoVoice"
+ type="notify">
+This area has voice chat disabled. You won&apos;t be able to hear anyone talking.
+ <unique/>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="NoBuild"
+ type="notify">
+This area has building disabled. You can&apos;t build or rez objects here.
+ <unique/>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="ScriptsStopped"
+ type="notify">
+An administrator has temporarily stopped scripts in this region.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="ScriptsNotRunning"
+ type="notify">
+This region is not running any scripts.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="NoOutsideScripts"
+ type="notify">
+This land has outside scripts disabled.
+
+No scripts will work here except those belonging to the land owner.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="ClaimPublicLand"
+ type="notify">
+You can only claim public land in the Region you&apos;re in.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="RegionTPAccessBlocked"
+ type="notify">
+You aren&apos;t allowed in that Region due to your maturity Rating. You may need to validate your age and/or install the latest Viewer.
+
+Please go to the Knowledge Base for details on accessing areas with this maturity Rating.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="URBannedFromRegion"
+ type="notify">
+You are banned from the region.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="NoTeenGridAccess"
+ type="notify">
+Your account cannot connect to this teen grid region.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="ImproperPaymentStatus"
+ type="notify">
+You do not have proper payment status to enter this region.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="MustGetAgeRgion"
+ type="notify">
+You must be age-verified to enter this region.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="MustGetAgeParcel"
+ type="notify">
+You must be age-verified to enter this parcel.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="NoDestRegion"
+ type="notify">
+No destination region found.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="NotAllowedInDest"
+ type="notify">
+You are not allowed into the destination.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="RegionParcelBan"
+ type="notify">
+Cannot region cross into banned parcel. Try another way.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="TelehubRedirect"
+ type="notify">
+You have been redirected to a telehub.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="CouldntTPCloser"
+ type="notify">
+Could not teleport closer to destination.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="TPCancelled"
+ type="notify">
+Teleport cancelled.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="FullRegionTryAgain"
+ type="notify">
+The region you are attempting to enter is currently full.
+Please try again in a few moments.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="GeneralFailure"
+ type="notify">
+General failure.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="RoutedWrongRegion"
+ type="notify">
+Routed to wrong region. Please try again.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="NoValidAgentID"
+ type="notify">
+No valid agent id.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="NoValidSession"
+ type="notify">
+No valid session id.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="NoValidCircuit"
+ type="notify">
+No valid circuit code.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="NoValidTimestamp"
+ type="notify">
+No valid timestamp.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="NoPendingConnection"
+ type="notify">
+Unable to create pending connection.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="InternalUsherError"
+ type="notify">
+Internal error attempting to connect agent usher.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="NoGoodTPDestination"
+ type="notify">
+Unable to find a good teleport destination in this region.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="InternalErrorRegionResolver"
+ type="notify">
+Internal error attempting to activate region resolver.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="NoValidLanding"
+ type="notify">
+A valid landing point could not be found.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="NoValidParcel"
+ type="notify">
+No valid parcel could be found.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="ObjectGiveItem"
+ type="offer">
+An object named [OBJECTFROMNAME] owned by [NAME_SLURL] has given you this [OBJECTTYPE]:
+[ITEM_SLURL]
+ <form name="form">
+ <button
+ index="0"
+ name="Keep"
+ text="Keep"/>
+ <button
+ index="1"
+ name="Discard"
+ text="Discard"/>
+ <button
+ index="2"
+ name="Mute"
+ text="Block"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="ObjectGiveItemUnknownUser"
+ type="offer">
+An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you this [OBJECTTYPE]:
+[ITEM_SLURL]
+ <form name="form">
+ <button
+ index="0"
+ name="Keep"
+ text="Keep"/>
+ <button
+ index="1"
+ name="Discard"
+ text="Discard"/>
+ <button
+ index="2"
+ name="Mute"
+ text="Block"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="UserGiveItem"
+ type="offer">
+[NAME_SLURL] has given you this [OBJECTTYPE]:
+[ITEM_SLURL]
+ <form name="form">
+ <button
+ index="4"
+ name="Show"
+ text="Show"/>
+ <button
+ index="1"
+ name="Discard"
+ text="Discard"/>
+ <button
+ index="2"
+ name="Mute"
+ text="Block"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="GodMessage"
+ type="notify">
+[NAME]
+
+[MESSAGE]
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="JoinGroup"
+ type="notify">
+[MESSAGE]
+ <form name="form">
+ <button
+ index="0"
+ name="Join"
+ text="Join"/>
+ <button
+ index="1"
+ name="Decline"
+ text="Decline"/>
+ <button
+ index="2"
+ name="Info"
+ text="Info"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="TeleportOffered"
+ type="offer">
+[NAME] has offered to teleport you to their location:
+
+[MESSAGE]
+ <form name="form">
+ <button
+ index="0"
+ name="Teleport"
+ text="Teleport"/>
+ <button
+ index="1"
+ name="Cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="TeleportOfferSent"
+ type="offer">
+ Teleport offer sent to [TO_NAME]
+ </notification>
+
+
+ <notification
+ icon="notify.tga"
+ name="GotoURL"
+ type="notify">
+[MESSAGE]
+[URL]
+ <form name="form">
+ <button
+ index="0"
+ name="Later"
+ text="Later"/>
+ <button
+ index="1"
+ name="GoNow..."
+ text="Go Now..."/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="OfferFriendship"
+ type="alertmodal">
+[NAME] is offering friendship.
+
+[MESSAGE]
+
+(By default, you will be able to see each other&apos;s online status.)
+ <form name="form">
+ <button
+ index="0"
+ name="Accept"
+ text="Accept"/>
+ <button
+ index="1"
+ name="Decline"
+ text="Decline"/>
+ <button
+ index="2"
+ name="Send IM"
+ text="Send IM"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="FriendshipOffered"
+ type="offer">
+ You have offered friendship to [TO_NAME]
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="OfferFriendshipNoMessage"
+ type="notify">
+[NAME] is offering friendship.
+
+(By default, you will be able to see each other&apos;s online status.)
+ <form name="form">
+ <button
+ index="0"
+ name="Accept"
+ text="Accept"/>
+ <button
+ index="1"
+ name="Decline"
+ text="Decline"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="FriendshipAccepted"
+ type="offer">
+[NAME] accepted your friendship offer.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="FriendshipDeclined"
+ type="notify">
+[NAME] declined your friendship offer.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="OfferCallingCard"
+ type="notify">
+[FIRST] [LAST] is offering their calling card.
+This will add a bookmark in your inventory so you can quickly IM this Resident.
+ <form name="form">
+ <button
+ index="0"
+ name="Accept"
+ text="Accept"/>
+ <button
+ index="1"
+ name="Decline"
+ text="Decline"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="RegionRestartMinutes"
+ priority="high"
+ sound="UISndAlert"
+ type="notify">
+This region will restart in [MINUTES] minutes.
+If you stay in this region you will be logged out.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="RegionRestartSeconds"
+ priority="high"
+ sound="UISndAlert"
+ type="notify">
+This region will restart in [SECONDS] seconds.
+If you stay in this region you will be logged out.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="LoadWebPage"
+ type="notify">
+Load web page [URL]?
+
+[MESSAGE]
+
+From object: [OBJECTNAME], owner: [NAME]?
+ <form name="form">
+ <button
+ index="0"
+ name="Gotopage"
+ text="Go to page"/>
+ <button
+ index="1"
+ name="Cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="FailedToFindWearableUnnamed"
+ type="notify">
+Failed to find [TYPE] in database.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="FailedToFindWearable"
+ type="notify">
+Failed to find [TYPE] named [DESC] in database.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="InvalidWearable"
+ type="notify">
+The item you are trying to wear uses a feature that your Viewer can&apos;t read. Please upgrade your version of [APP_NAME] to wear this item.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="ScriptQuestion"
+ type="notify">
+&apos;[OBJECTNAME]&apos;, an object owned by &apos;[NAME]&apos;, would like to:
+
+[QUESTIONS]
+Is this OK?
+ <form name="form">
+ <button
+ index="0"
+ name="Yes"
+ text="Yes"/>
+ <button
+ index="1"
+ name="No"
+ text="No"/>
+ <button
+ index="2"
+ name="Mute"
+ text="Block"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="ScriptQuestionCaution"
+ priority="high"
+ type="notify">
+An object named &apos;[OBJECTNAME]&apos;, owned by &apos;[NAME]&apos; would like to:
+
+[QUESTIONS]
+If you do not trust this object and its creator, you should deny the request.
+
+Grant this request?
+ <form name="form">
+ <button
+ index="0"
+ name="Grant"
+ text="Grant"/>
+ <button
+ default="true"
+ index="1"
+ name="Deny"
+ text="Deny"/>
+ <button
+ index="2"
+ name="Details"
+ text="Details..."/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="ScriptDialog"
+ type="notify">
+[FIRST] [LAST]&apos;s &apos;[TITLE]&apos;
+[MESSAGE]
+ <form name="form">
+ <button
+ index="-1"
+ name="Ignore"
+ text="Ignore"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="ScriptDialogGroup"
+ type="notify">
+[GROUPNAME]&apos;s &apos;[TITLE]&apos;
+[MESSAGE]
+ <form name="form">
+ <button
+ index="-1"
+ name="Ignore"
+ text="Ignore"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="ScriptToast"
+ type="notify">
+ [FIRST] [LAST]&apos;s &apos;[TITLE]&apos; is requesting user input.
+ <form name="form">
+ <button
+ index="0"
+ name="Open"
+ text="Open Dialog"/>
+ <button
+ index="1"
+ name="Ignore"
+ text="Ignore"/>
+ <button
+ index="2"
+ name="Block"
+ text="Block"/>
+ </form>
+ </notification>
+
+<!--
+ <notification
+ icon="notify.tga"
+ name="FirstBalanceIncrease"
+ type="notify">
+You just received L$[AMOUNT].
+Your L$ balance is shown in the upper-right.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="FirstBalanceDecrease"
+ type="notify">
+You just paid L$[AMOUNT].
+Your L$ balance is shown in the upper-right.
+ </notification>
+-->
+
+ <notification
+ icon="notify.tga"
+ name="BuyLindenDollarSuccess"
+ type="notify">
+Thank you for your payment!
+
+Your L$ balance will be updated when processing completes. If processing takes more than 20 mins, your transaction may be cancelled. In that case, the purchase amount will be credited to your US$ balance.
+
+The status of your payment can be checked on your Transaction History page on your [http://secondlife.com/account/ Dashboard]
+ </notification>
+
+<!--
+ <notification
+ icon="notify.tga"
+ name="FirstSit"
+ type="notify">
+You are sitting.
+Use your arrow keys (or AWSD) to look around.
+Click the &apos;Stand Up&apos; button to stand.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="FirstMap"
+ type="notify">
+Click and drag the map to look around.
+Double-click to teleport.
+Use the controls on the right to find things and display different backgrounds.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="FirstBuild"
+ type="notify">
+You have opened the Build Tools. Every object you see around you was created using these tools.
+ </notification>
+-->
+
+<!--
+ <notification
+ icon="notify.tga"
+ name="FirstLeftClickNoHit"
+ type="notify">
+ Left-clicking interacts with special objects.
+ If the mouse pointer changes to a hand, you can interact with the object.
+ Right-click always shows a menu of things you can do.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="FirstTeleport"
+ type="notify">
+You can only teleport to certain areas in this region. The arrow points to your specific destination. Click the arrow to dismiss it.
+ </notification>
+
+-->
+
+ <notification
+ icon="notify.tga"
+ name="FirstOverrideKeys"
+ type="notify">
+Your movement keys are now being handled by an object.
+Try the arrow keys or AWSD to see what they do.
+Some objects (like guns) require you to go into mouselook to use them.
+Press &apos;M&apos; to do this.
+ </notification>
+
+<!--
+ <notification
+ icon="notify.tga"
+ name="FirstAppearance"
+ type="notify">
+You are editing your Appearance.
+Use the arrow keys to look around.
+When you are done, press &apos;Save All&apos;.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="FirstInventory"
+ type="notify">
+This is your Inventory, which contains items you own.
+
+* To wear something, drag it onto yourself.
+* To rez something inworld, drag it onto the ground.
+* To read a notecard, double-click it.
+ </notification>
+-->
+
+ <notification
+ icon="notify.tga"
+ name="FirstSandbox"
+ type="notify">
+This is a sandbox area, and is meant to help Residents learn how to build.
+
+Things you build here will be deleted after you leave, so don&apos;t forget to right-click and choose &apos;Take&apos; to move your creation to your Inventory.
+ </notification>
+
+<!--
+ <notification
+ icon="notify.tga"
+ name="FirstFlexible"
+ type="notify">
+This object is flexible. Flexis must be phantom and not physical.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="FirstDebugMenus"
+ type="notify">
+You opened the Advanced menu.
+
+To toggle this menu,
+ Windows: Ctrl+Alt+D
+ Mac: &#8997;&#8984;D
+
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="FirstSculptedPrim"
+ type="notify">
+You are editing a Sculpted prim. Sculpties require a special texture to define their shape.
+ </notification>
+-->
+
+ <!--
+ <notification
+ icon="notify.tga"
+ name="FirstMedia"
+ type="notify">
+ You have begun playing media. Media can set to play automatically in the preferences window under Audio / Video. Note that this can be a security risk for media sites you do not trust.
+ </notification>
+ -->
+
+ <notification
+ icon="notifytip.tga"
+ name="MaxListSelectMessage"
+ type="notifytip">
+You may only select up to [MAX_SELECT] items from this list.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="VoiceInviteP2P"
+ type="notify">
+[NAME] is inviting you to a Voice Chat call.
+Click Accept to join the call or Decline to decline the invitation. Click Block to block this caller.
+ <unique>
+ <context key="NAME"/>
+ </unique>
+ <form name="form">
+ <button
+ index="0"
+ name="Accept"
+ text="Accept"/>
+ <button
+ index="1"
+ name="Decline"
+ text="Decline"/>
+ <button
+ index="2"
+ name="Mute"
+ text="Block"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="AutoUnmuteByIM"
+ type="notify">
+[FIRST] [LAST] was sent an instant message and has been automatically unblocked.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="AutoUnmuteByMoney"
+ type="notify">
+[FIRST] [LAST] was given money and has been automatically unblocked.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="AutoUnmuteByInventory"
+ type="notify">
+[FIRST] [LAST] was offered inventory and has been automatically unblocked.
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="VoiceInviteGroup"
+ type="notify">
+[NAME] has joined a Voice Chat call with the group [GROUP].
+Click Accept to join the call or Decline to decline the invitation. Click Block to block this caller.
+ <unique>
+ <context key="NAME"/>
+ <context key="GROUP"/>
+ </unique>
+ <form name="form">
+ <button
+ index="0"
+ name="Accept"
+ text="Accept"/>
+ <button
+ index="1"
+ name="Decline"
+ text="Decline"/>
+ <button
+ index="2"
+ name="Mute"
+ text="Block"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="VoiceInviteAdHoc"
+ type="notify">
+[NAME] has joined a voice chat call with a conference chat.
+Click Accept to join the call or Decline to decline the invitation. Click Block to block this caller.
+ <unique>
+ <context key="NAME"/>
+ </unique>
+ <form name="form">
+ <button
+ index="0"
+ name="Accept"
+ text="Accept"/>
+ <button
+ index="1"
+ name="Decline"
+ text="Decline"/>
+ <button
+ index="2"
+ name="Mute"
+ text="Block"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="InviteAdHoc"
+ type="notify">
+[NAME] is inviting you to a conference chat.
+Click Accept to join the chat or Decline to decline the invitation. Click Block to block this caller.
+ <unique>
+ <context key="NAME"/>
+ </unique>
+ <form name="form">
+ <button
+ index="0"
+ name="Accept"
+ text="Accept"/>
+ <button
+ index="1"
+ name="Decline"
+ text="Decline"/>
+ <button
+ index="2"
+ name="Mute"
+ text="Block"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="VoiceChannelFull"
+ type="notifytip">
+The voice call you are trying to join, [VOICE_CHANNEL_NAME], has reached maximum capacity. Please try again later.
+ <unique>
+ <context key="VOICE_CHANNEL_NAME"/>
+ </unique>
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="ProximalVoiceChannelFull"
+ type="notifytip">
+We&apos;re sorry. This area has reached maximum capacity for voice conversations. Please try to use voice in another area.
+ <unique/>
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="VoiceChannelDisconnected"
+ type="notifytip">
+You have been disconnected from [VOICE_CHANNEL_NAME]. You will now be reconnected to Nearby Voice Chat.
+ <unique>
+ <context key="VOICE_CHANNEL_NAME"/>
+ </unique>
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="VoiceChannelDisconnectedP2P"
+ type="notifytip">
+[VOICE_CHANNEL_NAME] has ended the call. You will now be reconnected to Nearby Voice Chat.
+ <unique>
+ <context key="VOICE_CHANNEL_NAME"/>
+ </unique>
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="P2PCallDeclined"
+ type="notifytip">
+[VOICE_CHANNEL_NAME] has declined your call. You will now be reconnected to Nearby Voice Chat.
+ <unique>
+ <context key="VOICE_CHANNEL_NAME"/>
+ </unique>
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="P2PCallNoAnswer"
+ type="notifytip">
+[VOICE_CHANNEL_NAME] is not available to take your call. You will now be reconnected to Nearby Voice Chat.
+ <unique>
+ <context key="VOICE_CHANNEL_NAME"/>
+ </unique>
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="VoiceChannelJoinFailed"
+ type="notifytip">
+Failed to connect to [VOICE_CHANNEL_NAME], please try again later. You will now be reconnected to Nearby Voice Chat.
+ <unique>
+ <context key="VOICE_CHANNEL_NAME"/>
+ </unique>
+ </notification>
+
+ <notification
+ duration="10"
+ icon="notifytip.tga"
+ name="VoiceLoginRetry"
+ type="notifytip">
+We are creating a voice channel for you. This may take up to one minute.
+ <unique/>
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="Cannot enter parcel: not a group member"
+ type="notifytip">
+Only members of a certain group can visit this area.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="Cannot enter parcel: banned"
+ type="notifytip">
+Cannot enter parcel, you have been banned.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="Cannot enter parcel: not on access list"
+ type="notifytip">
+Cannot enter parcel, you are not on the access list.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="VoiceNotAllowed"
+ type="notifytip">
+You do not have permission to connect to voice chat for [VOICE_CHANNEL_NAME].
+ <unique>
+ <context key="VOICE_CHANNEL_NAME"/>
+ </unique>
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="VoiceCallGenericError"
+ type="notifytip">
+An error has occurred while trying to connect to voice chat for [VOICE_CHANNEL_NAME]. Please try again later.
+ <unique>
+ <context key="VOICE_CHANNEL_NAME"/>
+ </unique>
+ </notification>
+
+ <notification
+ duration="10"
+ icon="notifytip.tga"
+ name="ServerVersionChanged"
+ priority="high"
+ type="notifytip">
+You just entered a region using a different server version, which may affect performance. [[URL] View the release notes.]
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="UnsupportedCommandSLURL"
+ priority="high"
+ type="notifytip">
+The SLurl you clicked on is not supported.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="BlockedSLURL"
+ priority="high"
+ type="notifytip">
+A SLurl was received from an untrusted browser and has been blocked for your security.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="ThrottledSLURL"
+ priority="high"
+ type="notifytip">
+Multiple SLurls were received from an untrusted browser within a short period.
+They will be blocked for a few seconds for your security.
+ </notification>
+
+ <notification name="IMToast" type="notifytoast">
+[MESSAGE]
+ <form name="form">
+ <button index="0" name="respondbutton" text="Respond"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="ConfirmCloseAll"
+ type="alertmodal">
+Are you sure you want to close all IMs?
+ <usetemplate
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification icon="notifytip.tga"
+ name="AttachmentSaved" type="notifytip">
+Attachment has been saved.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="UnableToFindHelpTopic"
+ type="alertmodal">
+Unable to find the help topic for this element.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ObjectMediaFailure"
+ type="alertmodal">
+Server Error: Media update or get failed.
+&apos;[ERROR]&apos;
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="TextChatIsMutedByModerator"
+ type="alertmodal">
+Your text chat has been muted by moderator.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="VoiceIsMutedByModerator"
+ type="alertmodal">
+Your voice has been muted by moderator.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmClearTeleportHistory"
+ type="alertmodal">
+Are you sure you want to delete your teleport history?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="BottomTrayButtonCanNotBeShown"
+ type="alert">
+Selected button can not be shown right now.
+The button will be shown when there is enough space for it.
+ </notification>
+
+
+ <global name="UnsupportedCPU">
+- Your CPU speed does not meet the minimum requirements.
+ </global>
+
+ <global name="UnsupportedGLRequirements">
+You do not appear to have the proper hardware requirements for [APP_NAME]. [APP_NAME] requires an OpenGL graphics card that has multitexture support. If this is the case, you may want to make sure that you have the latest drivers for your graphics card, and service packs and patches for your operating system.
+
+If you continue to have problems, please visit the [SUPPORT_SITE].
+ </global>
+
+ <global name="UnsupportedCPUAmount">
+796
+ </global>
+
+ <global name="UnsupportedRAMAmount">
+510
+ </global>
+
+ <global name="UnsupportedGPU">
+- Your graphics card does not meet the minimum requirements.
+ </global>
+
+ <global name="UnsupportedRAM">
+- Your system memory does not meet the minimum requirements.
+ </global>
+
+<!-- this is alert string from server. the name needs to match entire the server string, and needs to be changed
+ whenever the server string changes -->
+ <global name="You can only set your 'Home Location' on your land or at a mainland Infohub.">
+If you own a piece of land, you can make it your home location.
+Otherwise, you can look at the Map and find places marked &quot;Infohub&quot;.
+ </global>
+
+</notifications>
diff --git a/indra/newview/skins/default/xui/en/panel_active_object_row.xml b/indra/newview/skins/default/xui/en/panel_active_object_row.xml
new file mode 100644
index 0000000000..7657fb8055
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_active_object_row.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ name="panel_activeim_row"
+ layout="topleft"
+ follows="left|right"
+ top="0"
+ left="0"
+ height="35"
+ width="318"
+ background_opaque="false"
+ background_visible="true"
+ bg_alpha_color="0.0 0.0 0.0 0.0" >
+ <string
+ name="unknown_obj">
+ Unknown Object
+ </string>
+ <chiclet_script
+ name="object_chiclet"
+ layout="topleft"
+ follows="left"
+ top="3"
+ left="5"
+ height="25"
+ width="25"
+ visible="false"
+ speaker.name="speaker_p2p"
+ speaker.width="20"
+ speaker.height="25"
+ speaker.left="25"
+ speaker.top="25"
+ speaker.auto_update="true"
+ speaker.draw_border="false"
+ speaker.visible="false">
+ </chiclet_script>
+ <chiclet_offer
+ name="inv_offer_chiclet"
+ layout="topleft"
+ follows="left"
+ top="3"
+ left="5"
+ height="25"
+ width="25"
+ visible="false"
+ speaker.name="speaker_p2p"
+ speaker.width="20"
+ speaker.height="25"
+ speaker.left="25"
+ speaker.top="25"
+ speaker.auto_update="true"
+ speaker.draw_border="false"
+ speaker.visible="false">
+ </chiclet_offer>
+ <text
+ type="string"
+ name="object_name"
+ layout="topleft"
+ top="10"
+ left_pad="20"
+ height="14"
+ width="245"
+ length="1"
+ follows="right|left"
+ use_ellipses="true"
+ font="SansSerifBold">
+ Unnamed Object
+ </text>
+ <button
+ top="10"
+ right="-5"
+ width="17"
+ height="17"
+ layout="topleft"
+ follows="right"
+ name="hide_btn"
+ mouse_opaque="true"
+ label=""
+ tab_stop="false"
+ image_unselected="Toast_CloseBtn"
+ image_selected="Toast_CloseBtn"
+ />
+</panel> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/panel_activeim_row.xml b/indra/newview/skins/default/xui/en/panel_activeim_row.xml
new file mode 100644
index 0000000000..3416b2369d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_activeim_row.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ name="panel_activeim_row"
+ layout="topleft"
+ follows="left|right"
+ top="0"
+ left="0"
+ height="35"
+ width="318"
+ background_opaque="false"
+ background_visible="true"
+ bg_alpha_color="0.0 0.0 0.0 0.0" >
+ <chiclet_im_p2p
+ name="p2p_chiclet"
+ layout="topleft"
+ follows="left"
+ top="3"
+ left="5"
+ height="25"
+ width="25"
+ visible="false"
+ speaker.name="speaker_p2p"
+ speaker.width="20"
+ speaker.height="25"
+ speaker.left="25"
+ speaker.top="25"
+ speaker.auto_update="true"
+ speaker.draw_border="false"
+ speaker.visible="false">
+ </chiclet_im_p2p>
+ <chiclet_im_group
+ name="group_chiclet"
+ layout="topleft"
+ follows="left"
+ top="3"
+ left="5"
+ height="25"
+ width="25"
+ visible="false"
+ speaker.name="speaker_grp"
+ speaker.width="20"
+ speaker.height="25"
+ speaker.left="25"
+ speaker.top="25"
+ speaker.auto_update="true"
+ speaker.draw_border="false"
+ speaker.visible="false">
+ </chiclet_im_group>
+ <chiclet_im_adhoc
+ name="adhoc_chiclet"
+ layout="topleft"
+ follows="left"
+ top="3"
+ left="5"
+ height="25"
+ width="25"
+ visible="false"
+ speaker.name="speaker_hoc"
+ speaker.width="20"
+ speaker.height="25"
+ speaker.left="25"
+ speaker.top="25"
+ speaker.auto_update="true"
+ speaker.draw_border="false"
+ speaker.visible="false">
+ </chiclet_im_adhoc>
+ <text
+ type="string"
+ name="contact_name"
+ layout="topleft"
+ top="10"
+ left_pad="10"
+ height="14"
+ width="255"
+ length="1"
+ follows="right|left"
+ use_ellipses="true"
+ font="SansSerifBold">
+ Grumpity ProductEngine
+ </text>
+ <button
+ top="10"
+ right="-5"
+ width="17"
+ height="17"
+ layout="topleft"
+ follows="right"
+ name="hide_btn"
+ mouse_opaque="true"
+ label=""
+ tab_stop="false"
+ image_unselected="Toast_CloseBtn"
+ image_selected="Toast_CloseBtn"
+ />
+</panel> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml
new file mode 100644
index 0000000000..28a6995186
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="false"
+ follows="all"
+ height="215"
+ name="panel_im_control_panel"
+ width="150">
+ <layout_stack
+ mouse_opaque="false"
+ border_size="0"
+ clip="false"
+ follows="all"
+ height="215"
+ layout="topleft"
+ left="3"
+ name="vertical_stack"
+ orientation="vertical"
+ top="0"
+ width="147">
+ <layout_panel
+ auto_resize="true"
+ follows="top|left"
+ height="130"
+ layout="topleft"
+ left="0"
+ min_height="0"
+ mouse_opaque="false"
+ width="147"
+ top="0"
+ name="speakers_list_panel"
+ user_resize="false">
+ <avatar_list
+ color="DkGray2"
+ follows="all"
+ height="130"
+ ignore_online_status="true"
+ layout="topleft"
+ name="speakers_list"
+ opaque="false"
+ show_info_btn="false"
+ show_profile_btn="false"
+ show_speaking_indicator="false"
+ width="147" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="25"
+ layout="topleft"
+ min_height="25"
+ width="130"
+ name="call_btn_panel"
+ user_resize="false"
+ visible="false">
+ <button
+ follows="all"
+ height="20"
+ label="Call"
+ name="call_btn"
+ width="130"
+ top="5" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="25"
+ layout="topleft"
+ min_height="25"
+ width="130"
+ name="end_call_btn_panel"
+ user_resize="false"
+ visible="false">
+ <button
+ follows="all"
+ height="20"
+ label="Leave Call"
+ name="end_call_btn"
+ top="5"/>
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="25"
+ layout="topleft"
+ min_height="25"
+ width="130"
+ name="voice_ctrls_btn_panel"
+ user_resize="false"
+ visible="false">
+ <button
+ follows="all"
+ height="20"
+ label="Voice Controls"
+ name="voice_ctrls_btn"
+ top="5"
+ use_ellipses="true" />
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_audio_device.xml b/indra/newview/skins/default/xui/en/panel_audio_device.xml
new file mode 100644
index 0000000000..546f46205f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_audio_device.xml
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ height="240"
+ layout="topleft"
+ left="8"
+ name="device_settings"
+ top="240"
+ width="404">
+ <panel.string
+ name="default_text">
+ Default
+ </panel.string>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="6"
+ name="Audio Devices"
+ width="200">
+ Audio Devices
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="20"
+ name="Input device (microphone):"
+ top="26"
+ width="200">
+ Input device (microphone):
+ </text>
+ <combo_box
+ height="18"
+ layout="topleft"
+ left_delta="0"
+ max_chars="128"
+ name="voice_input_device"
+ top_pad="2"
+ width="225" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="Output device (speakers):"
+ top_pad="9"
+ width="200">
+ Output device (speakers):
+ </text>
+ <combo_box
+ height="18"
+ layout="topleft"
+ left_delta="0"
+ max_chars="128"
+ name="voice_output_device"
+ top_pad="2"
+ width="225" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="6"
+ name="Input level:"
+ top="121"
+ width="200">
+ Input Level
+ </text>
+ <text_editor
+ type="string"
+ length="1"
+ top="135"
+ bg_readonly_color="0 0 0 0"
+ enabled="false"
+ height="60"
+ border_visible="false"
+ layout="topleft"
+ left_delta="10"
+ max_length="65535"
+ name="voice_intro_text1"
+ tab_stop="false"
+ width="380"
+ word_wrap="true">
+ Adjust the slider to control how loud you sound to other Residents. To test the input level, simply speak into your microphone.
+ </text_editor>
+ <slider_bar
+ follows="left|top"
+ height="17"
+ increment="0.05"
+ initial_value="1.0"
+ layout="topleft"
+ left_delta="5"
+ max_val="2"
+ name="mic_volume_slider"
+ tool_tip="Change the volume using this slider"
+ top="202"
+ width="90" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="5"
+ name="wait_text"
+ top_delta="1"
+ width="200">
+ Please wait
+ </text>
+ <locate
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="bar0"
+ top_delta="5"
+ width="20" />
+ <locate
+ height="20"
+ layout="topleft"
+ left_pad="2"
+ name="bar1"
+ top_delta="0"
+ width="20" />
+ <locate
+ height="20"
+ layout="topleft"
+ left_pad="2"
+ name="bar2"
+ top_delta="0"
+ width="20" />
+ <locate
+ height="20"
+ layout="topleft"
+ left_pad="2"
+ name="bar3"
+ top_delta="0"
+ width="20" />
+ <locate
+ height="20"
+ layout="topleft"
+ left_pad="2"
+ name="bar4"
+ top_delta="0"
+ width="20" />
+</panel>
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
new file mode 100644
index 0000000000..c605975c8e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="top|right|left"
+ height="24"
+ layout="topleft"
+ left="0"
+ name="avatar_list_item"
+ top="0"
+ width="320">
+ <!--
+ Strings used to localize last interaction time.
+ See last_interaction textbox below.
+ -->
+ <string name="FormatSeconds">[COUNT]s</string>
+ <string name="FormatMinutes">[COUNT]m</string>
+ <string name="FormatHours">[COUNT]h</string>
+ <string name="FormatDays">[COUNT]d</string>
+ <string name="FormatWeeks">[COUNT]w</string>
+ <string name="FormatMonths">[COUNT]mon</string>
+ <string name="FormatYears">[COUNT]y</string>
+
+ <icon
+ follows="top|right|left"
+ height="24"
+ image_name="ListItem_Over"
+ layout="topleft"
+ left="0"
+ name="hovered_icon"
+ top="0"
+ visible="false"
+ width="320" />
+ <icon
+ height="24"
+ follows="top|right|left"
+ image_name="ListItem_Select"
+ layout="topleft"
+ left="0"
+ name="selected_icon"
+ top="0"
+ visible="false"
+ width="320" />
+ <avatar_icon
+ follows="top|left"
+ height="20"
+ default_icon_name="Generic_Person"
+ layout="topleft"
+ left="5"
+ mouse_opaque="true"
+ top="2"
+ width="20" />
+ <text
+ follows="left|right"
+ font="SansSerifSmall"
+ height="15"
+ layout="topleft"
+ left_pad="5"
+ name="avatar_name"
+ top="6"
+ use_ellipses="true"
+ value="Unknown"
+ width="180" />
+ <text
+ follows="right"
+ font="SansSerifSmall"
+ height="15"
+ layout="topleft"
+ left_pad="5"
+ right="-72"
+ name="last_interaction"
+ text_color="LtGray_50"
+ value="0s"
+ width="24" />
+ <button
+ follows="right"
+ height="16"
+ image_pressed="Info_Press"
+ image_unselected="Info_Over"
+ left_pad="3"
+ right="-53"
+ name="info_btn"
+ top_delta="-2"
+ width="16" />
+ <button
+ follows="right"
+ height="20"
+ image_overlay="ForwardArrow_Off"
+ layout="topleft"
+ left_pad="5"
+ right="-28"
+ name="profile_btn"
+ tool_tip="View profile"
+ top_delta="-2"
+ width="20" />
+ <output_monitor
+ auto_update="true"
+ follows="right"
+ draw_border="false"
+ height="16"
+ layout="topleft"
+ left_pad="5"
+ right="-3"
+ mouse_opaque="true"
+ name="speaking_indicator"
+ visible="true"
+ width="20" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_avatar_tag.xml b/indra/newview/skins/default/xui/en/panel_avatar_tag.xml
new file mode 100644
index 0000000000..b779b08a63
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_avatar_tag.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ name="avatar_tag_notification"
+ top="10"
+ width="250"
+ height="100"
+ follows="all">
+ <panel
+ width="240"
+ height="24"
+ left="5"
+ background_visible="true"
+ background_opaque="false"
+ follows="left|top|right"
+ top="-5"
+ bg_alpha_color="black"
+ name="msg_caption">
+ <avatar_icon
+ top="-3"
+ left="3"
+ width="18"
+ image_name="Generic_Person"
+ height="18"
+ follows="left|top"
+ enabled="true"
+ name="avatar_tag_icon" />
+ <text
+ width="160"
+ top="-8"
+ left="30"
+ height="20"
+ follows="left|right|top"
+ font.style="BOLD"
+ text_color="white"
+ word_wrap="true"
+ mouse_opaque="true"
+ name="sender_tag_name">
+ Angela Tester
+ </text>
+ <text
+ font="SansSerifSmall"
+ follows="right"
+ height="13"
+ layout="topleft"
+ halign="right"
+ right="-5"
+ name="tag_time"
+ top="8"
+ value="23:30"
+ width="50" />
+ </panel>
+ <text_editor
+ bg_readonly_color="DkGray"
+ font="SansSerifSmall"
+ top="65"
+ left="5"
+ right="-5"
+ height="100"
+ follows="all"
+ read_only="true"
+ word_wrap="true"
+ mouse_opaque="true"
+ name="msg_text">
+ The quick brown fox jumps over the lazy dog.
+ </text_editor>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_bars.xml b/indra/newview/skins/default/xui/en/panel_bars.xml
new file mode 100644
index 0000000000..96722ce278
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_bars.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="left|right|top|bottom"
+ height="768"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="screen"
+ width="1024">
+ <layout_stack name="menu_stack" orientation="vertical" height="768" border_size="0">
+ <panel auto_resize="false" width="1024" name="status_bar" filename="panel_status_bar.xml"/>
+ <panel auto_resize="false" width="1024" height="60" name="navigation bar" filename="panel_navigation_bar.xml"/>
+ <layout_stack name="hud_stack" orientation="horizontal" auto_resize="true" width="1024" height="500" follows="all">
+ <panel auto_resize="true" name="floater_view" height="500"/>
+ <panel auto_resize="false" filename="panel_side_tray.xml" height="500" width="333"/>
+ </layout_stack>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml
new file mode 100644
index 0000000000..39170b90ca
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ follows="left|top|right|bottom"
+ height="305"
+ layout="topleft"
+ name="block_list_panel"
+ help_topic="blocked_list"
+ min_height="350"
+ min_width="240"
+ width="280">
+ <button
+ follows="top|left"
+ height="25"
+ image_overlay="BackArrow_Off"
+ layout="topleft"
+ name="back"
+ left="10"
+ tab_stop="false"
+ top="0"
+ width="25"/>
+ <text
+ follows="top|left|right"
+ font="SansSerifLargeBold"
+ height="20"
+ layout="topleft"
+ left_pad="10"
+ name="title_text"
+ text_color="white"
+ top="5"
+ width="250">
+ Blocked List
+ </text>
+ <scroll_list
+ follows="all"
+ height="190"
+ layout="topleft"
+ left="5"
+ name="blocked"
+ tool_tip="List of currently blocked Residents"
+ top="30"
+ width="270" />
+ <button
+ follows="left|bottom"
+ height="23"
+ label="Block person"
+ layout="topleft"
+ left_delta="0"
+ name="Block resident..."
+ tool_tip="Pick a Resident to block"
+ top_pad="4"
+ width="210">
+ <button.commit_callback
+ function="Block.ClickPick" />
+ </button>
+ <button
+ follows="left|bottom"
+ height="23"
+ label="Block object by name"
+ layout="topleft"
+ left_delta="0"
+ name="Block object by name..."
+ tool_tip="Pick an object to block by name"
+ top_pad="4"
+ width="210" >
+ <button.commit_callback
+ function="Block.ClickBlockByName" />
+ </button>
+ <button
+ enabled="false"
+ follows="left|bottom"
+ height="23"
+ label="Unblock"
+ layout="topleft"
+ left_delta="0"
+ name="Unblock"
+ tool_tip="Remove Resident or object from blocked list"
+ top_pad="4"
+ width="210" >
+ <button.commit_callback
+ function="Block.ClickRemove" />
+ </button>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
new file mode 100644
index 0000000000..09ec2137b7
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
@@ -0,0 +1,439 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ mouse_opaque="true"
+ background_visible="true"
+ bg_alpha_color="DkGray"
+ bg_opaque_color="DkGray"
+ follows="left|bottom|right"
+ height="33"
+ layout="topleft"
+ left="0"
+ name="bottom_tray"
+ top="28"
+ chrome="true"
+ border_visible="false"
+ width="1000">
+ <string name="SpeakBtnToolTip">Turns microphone on/off</string>
+ <string name="VoiceControlBtnToolTip">Shows/hides voice control panel</string>
+ <layout_stack
+ mouse_opaque="false"
+ border_size="0"
+ clip="false"
+ follows="all"
+ height="28"
+ layout="topleft"
+ left="0"
+ name="toolbar_stack"
+ orientation="horizontal"
+ top="0"
+ width="1000">
+ <icon
+ auto_resize="false"
+ follows="left|right"
+ height="10"
+ image_name="spacer24.tga"
+ layout="topleft"
+ min_width="2"
+ left="0"
+ top="0"
+ width="2" />
+ <layout_panel
+ mouse_opaque="false"
+ auto_resize="false"
+ follows="left|right"
+ height="28"
+ layout="topleft"
+ left="0"
+ min_height="23"
+ width="310"
+ top="4"
+ min_width="188"
+ name="chat_bar"
+ user_resize="false"
+ filename="panel_nearby_chat_bar.xml" />
+ <layout_panel
+ mouse_opaque="false"
+ auto_resize="false"
+ follows="right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ width="100"
+ top_delta="0"
+ min_width="54"
+ name="speak_panel"
+ user_resize="false">
+ <talk_button
+ follows="left|right"
+ height="23"
+ speak_button.tab_stop="true"
+ show_button.tab_stop="true"
+ layout="topleft"
+ left="0"
+ name="talk"
+ top="5"
+ width="100">
+ <show_button>
+ <show_button.init_callback
+ function="Button.SetDockableFloaterToggle"
+ parameter="voice_controls" />
+ </show_button>
+ </talk_button>
+ </layout_panel>
+ <icon
+ auto_resize="false"
+ follows="left|right"
+ height="10"
+ image_name="spacer24.tga"
+ layout="topleft"
+ left="0"
+ name="DUMMY"
+ min_width="3"
+ top="0"
+ width="3"/>
+ <layout_panel
+ mouse_opaque="false"
+ auto_resize="false"
+ follows="right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ width="82"
+ top_delta="0"
+ min_width="52"
+ name="gesture_panel"
+ user_resize="false">
+ <gesture_combo_list
+ follows="left|right"
+ height="23"
+ label="Gesture"
+ layout="topleft"
+ name="Gesture"
+ left="0"
+ top="5"
+ width="82"
+ tool_tip="Shows/hides gestures">
+ <gesture_combo_list.combo_button
+ pad_right="10"
+ use_ellipses="true" />
+ </gesture_combo_list>
+ </layout_panel>
+ <icon
+ auto_resize="false"
+ color="0 0 0 0"
+ follows="left|right"
+ height="10"
+ image_name="spacer24.tga"
+ layout="topleft"
+ left="0"
+ min_width="3"
+ name="DUMMY"
+ top="0"
+ width="3"/>
+ <layout_panel
+ mouse_opaque="false"
+ auto_resize="false"
+ follows="right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ name="movement_panel"
+ user_resize="false"
+ width="80"
+ min_width="49">
+ <button
+ image_selected="PushButton_Selected_Press"
+ image_pressed="PushButton_Press"
+ image_pressed_selected="PushButton_Selected_Press"
+ follows="left|right"
+ height="23"
+ use_ellipses="true"
+ is_toggle="true"
+ label="Move"
+ layout="topleft"
+ name="movement_btn"
+ tool_tip="Shows/hides movement controls"
+ top="5"
+ width="80">
+ <button.init_callback
+ function="Button.SetDockableFloaterToggle"
+ parameter="moveview" />
+ </button>
+ </layout_panel>
+ <icon
+ auto_resize="false"
+ color="0 0 0 0"
+ follows="left|right"
+ height="10"
+ image_name="spacer24.tga"
+ layout="topleft"
+ left="0"
+ min_width="3"
+ name="DUMMY"
+ top="0"
+ width="3"/>
+ <layout_panel
+ mouse_opaque="false"
+ auto_resize="false"
+ follows="left|right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ min_width="49"
+ name="cam_panel"
+ user_resize="false"
+ width="80">
+ <button
+ image_selected="PushButton_Selected_Press"
+ image_pressed="PushButton_Press"
+ image_pressed_selected="PushButton_Selected_Press"
+ follows="left|right"
+ height="23"
+ use_ellipses="true"
+ is_toggle="true"
+ label="View"
+ layout="topleft"
+ left="0"
+ tool_tip="Shows/hides camera controls"
+ top="5"
+ name="camera_btn"
+ width="80">
+ <button.init_callback
+ function="Button.SetDockableFloaterToggle"
+ parameter="camera" />
+ </button>
+ </layout_panel>
+ <icon
+ auto_resize="false"
+ color="0 0 0 0"
+ follows="left|right"
+ height="10"
+ image_name="spacer24.tga"
+ layout="topleft"
+ left="0"
+ min_width="3"
+ name="DUMMY"
+ top="0"
+ width="3"/>
+ <layout_panel
+ mouse_opaque="false"
+ auto_resize="false"
+ follows="left|right"
+ height="28"
+ layout="topleft"
+ min_width="40"
+ name="snapshot_panel"
+ width="40">
+ <button
+ follows="left|right"
+ height="23"
+ image_selected="PushButton_Selected_Press"
+ image_pressed="PushButton_Press"
+ image_pressed_selected="PushButton_Selected_Press"
+ left="0"
+ label=""
+ layout="topleft"
+ name="snapshots"
+ width="36"
+ top="5"
+ is_toggle="true"
+ image_overlay="Snapshot_Off"
+ tool_tip="Take snapshot">
+ <button.init_callback
+ function="Button.SetFloaterToggle"
+ parameter="snapshot" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ mouse_opaque="false"
+ follows="left|right"
+ height="29"
+ layout="topleft"
+ top="0"
+ name="chiclet_list_panel"
+ width="189"
+ min_width="110"
+ user_resize="false"
+ auto_resize="true">
+<!--*NOTE: min_width of the chiclet_panel (chiclet_list) must be the same
+as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. EXT-991-->
+ <chiclet_panel
+ mouse_opaque="false"
+ follows="left|right"
+ height="23"
+ layout="topleft"
+ left="1"
+ min_width="110"
+ name="chiclet_list"
+ top="8"
+ chiclet_padding="4"
+ scrolling_offset="40"
+ width="189">
+ <button
+ auto_resize="true"
+ follows="right"
+ height="29"
+ image_selected="SegmentedBtn_Left_Off"
+ image_unselected="SegmentedBtn_Left_Off"
+ image_hover_selected="SegmentedBtn_Left_Over"
+ image_hover_unselected="SegmentedBtn_Left_Over"
+ image_pressed="SegmentedBtn_Left_Press"
+ image_pressed_selected="SegmentedBtn_Left_Press"
+ image_overlay="Arrow_Small_Left"
+ layout="topleft"
+ name="chicklet_left_scroll_button"
+ scale_image="true"
+ tab_stop="false"
+ top="-4"
+ right_pad="2"
+ visible="false"
+ width="7" />
+ <button
+ auto_resize="true"
+ follows="right"
+ height="29"
+ image_selected="SegmentedBtn_Right_Off"
+ image_unselected="SegmentedBtn_Right_Off"
+ image_hover_selected="SegmentedBtn_Right_Over"
+ image_hover_unselected="SegmentedBtn_Right_Over"
+ image_pressed="SegmentedBtn_Right_Press"
+ image_pressed_selected="SegmentedBtn_Right_Press"
+ image_overlay="Arrow_Small_Right"
+ layout="topleft"
+ name="chicklet_right_scroll_button"
+ scale_image="true"
+ tab_stop="false"
+ top="-4"
+ visible="false"
+ width="7" />
+ </chiclet_panel>
+ </layout_panel>
+ <icon
+ auto_resize="false"
+ color="0 0 0 0"
+ follows="left|right"
+ height="10"
+ image_name="spacer24.tga"
+ layout="topleft"
+ left="0"
+ min_width="4"
+ top="0"
+ width="5"/>
+ <layout_panel
+ auto_resize="false"
+ follows="right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ top="0"
+ name="im_well_panel"
+ width="35"
+ min_width="35"
+ user_resize="false">
+ <chiclet_im_well
+ max_displayed_count="99"
+ flash_period="0.3"
+ follows="right"
+ height="28"
+ layout="topleft"
+ left="0"
+ name="im_well"
+ top="0"
+ width="35">
+ <!--
+Emulate 4 states of button by background images, see details in EXT-3147. The same should be for notification_well button
+xml attribute Description
+image_unselected "Unlit" - there are no new messages
+image_selected "Unlit" + "Selected" - there are no new messages and the Well is open
+image_pressed "Lit" - there are new messages
+image_pressed_selected "Lit" + "Selected" - there are new messages and the Well is open
+ -->
+ <button
+ auto_resize="true"
+ follows="right"
+ halign="center"
+ height="23"
+ image_overlay="Unread_IM"
+ image_overlay_alignment="center"
+ image_pressed="WellButton_Lit"
+ image_pressed_selected="WellButton_Lit_Selected"
+ image_selected="PushButton_Press"
+ label_color="Black"
+ left="0"
+ name="Unread IM messages"
+ tool_tip="Conversations"
+ width="34" >
+ <button.init_callback
+ function="Button.SetDockableFloaterToggle"
+ parameter="im_well_window" />
+ </button>
+ </chiclet_im_well>
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ top="0"
+ left_pad="3"
+ name="notification_well_panel"
+ width="40"
+ min_width="40"
+ user_resize="false">
+ <icon
+ auto_resize="false"
+ color="0 0 0 0"
+ follows="left|right"
+ height="10"
+ image_name="spacer24.tga"
+ layout="topleft"
+ left="0"
+ min_width="4"
+ top="0"
+ width="5" />
+ <chiclet_notification
+ flash_period="0.25"
+ follows="right"
+ height="23"
+ layout="topleft"
+ left="0"
+ max_displayed_count="99"
+ name="notification_well"
+ top="5"
+ width="35">
+ <button
+ bottom_pad="3"
+ image_pressed="WellButton_Lit"
+ image_pressed_selected="WellButton_Lit_Selected"
+ image_selected="PushButton_Press"
+ auto_resize="true"
+ halign="center"
+ height="23"
+ follows="right"
+ label_color="Black"
+ left="0"
+ name="Unread"
+ image_overlay="Notices_Unread"
+ image_overlay_alignment="center"
+ tool_tip="Notifications"
+ width="34" >
+ <button.init_callback
+ function="Button.SetDockableFloaterToggle"
+ parameter="notification_well_window" />
+ </button>
+ <icon
+ auto_resize="false"
+ color="0 0 0 0"
+ follows="left|right"
+ height="10"
+ image_name="spacer24.tga"
+ layout="topleft"
+ left="0"
+ min_width="4"
+ top="0"
+ width="5" />
+ </chiclet_notification>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_chat_header.xml b/indra/newview/skins/default/xui/en/panel_chat_header.xml
new file mode 100644
index 0000000000..39c4923f12
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_chat_header.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ bevel_style="in"
+ bg_alpha_color="black"
+ follows="top|left|right"
+ height="24"
+ label="im_header"
+ layout="topleft"
+ name="im_header"
+ width="310">
+ <avatar_icon
+ follows="left"
+ height="18"
+ image_name="Generic_Person"
+ layout="topleft"
+ left="3"
+ mouse_opaque="true"
+ name="avatar_icon"
+ top="3"
+ width="18" />
+ <text_editor
+ allow_scroll="false"
+ v_pad = "0"
+ read_only = "true"
+ follows="left|right"
+ font.style="BOLD"
+ height="12"
+ layout="topleft"
+ left_pad="5"
+ right="-120"
+ name="user_name"
+ text_color="white"
+ bg_readonly_color="black"
+ top="8"
+ use_ellipses="true"
+ value="Ericag Vader" />
+ <text
+ font="SansSerifSmall"
+ follows="right"
+ halign="right"
+ height="13"
+ layout="topleft"
+ left_pad="5"
+ name="time_box"
+ right="-5"
+ top="8"
+ value="23:30"
+ width="110" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_chat_item.xml b/indra/newview/skins/default/xui/en/panel_chat_item.xml
new file mode 100644
index 0000000000..34c6e02684
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_chat_item.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- All our XML is utf-8 encoded. -->
+<panel
+ name="instant_message"
+ width="315"
+ height="180"
+ follows="all">
+ <avatar_icon
+ follows="left|top"
+ height="18"
+ image_name="Generic_Person"
+ layout="topleft"
+ left="3"
+ mouse_opaque="true"
+ name="avatar_icon"
+ top="3"
+ width="18" />
+ <text_chat
+ top="5"
+ left="30"
+ height="120"
+ text_color="white"
+ word_wrap="true"
+ mouse_opaque="true"
+ name="msg_text">
+ </text_chat>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_chat_separator.xml b/indra/newview/skins/default/xui/en/panel_chat_separator.xml
new file mode 100644
index 0000000000..357dbc07cc
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_chat_separator.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ bg_alpha_color="black"
+ follows="left|right|top"
+ height="0"
+ layout="topleft"
+ name="chat_separator_panel" />
diff --git a/indra/newview/skins/default/xui/en/panel_classified.xml b/indra/newview/skins/default/xui/en/panel_classified.xml
new file mode 100644
index 0000000000..c8293d3663
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_classified.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="bottom|left"
+ height="490"
+ label="Classified"
+ layout="topleft"
+ left="330"
+ name="Classified"
+ top="490"
+ width="450">
+ <panel.string
+ name="ad_placed_paid">
+ Ad placed: [DATE], Paid L$[AMT] for listing.
+ </panel.string>
+ <panel.string
+ name="update_txt">
+ Update
+ </panel.string>
+ <panel.string
+ name="publish_txt">
+ Publish...
+ </panel.string>
+ <panel.string
+ name="dateStr">
+ [mthnum,datetime,slt]/[day,datetime,slt]/[year,datetime,slt]
+ </panel.string>
+ <texture_picker
+ follows="left|top"
+ height="300"
+ layout="topleft"
+ left="20"
+ name="snapshot_ctrl"
+ top="15"
+ width="400" />
+ <line_editor
+ enabled="false"
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="given_name_editor"
+ tool_tip="Name must begin with a letter or number, not punctuation"
+ top_delta="288"
+ width="400" />
+ <text_editor
+ enabled="false"
+ follows="left|top"
+ height="90"
+ layout="topleft"
+ left="20"
+ max_length="1023"
+ name="desc_editor"
+ width="400"
+ word_wrap="true" />
+ <line_editor
+ enabled="false"
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left="20"
+ name="location_editor"
+ tool_tip="Set the location for this classified to your current position"
+ width="400" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Set"
+ layout="topleft"
+ left_delta="360"
+ name="set_location_btn"
+ top_delta="0"
+ width="60" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Teleport"
+ layout="topleft"
+ left="20"
+ name="classified_teleport_btn"
+ top="449"
+ width="100" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Map"
+ layout="topleft"
+ left_pad="5"
+ name="classified_map_btn"
+ top_delta="0"
+ width="100" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Profile"
+ layout="topleft"
+ left_pad="5"
+ name="classified_profile_btn"
+ top_delta="0"
+ width="100" />
+ <combo_box
+ height="20"
+ layout="topleft"
+ left="30"
+ name="classified_mature_check"
+ top="48"
+ width="130">
+ <combo_box.item
+ label="- Select one -"
+ name="select_mature"
+ value="Select" />
+ <combo_box.item
+ label="Moderate Content"
+ name="mature"
+ value="Mature" />
+ <combo_box.item
+ label="General Content"
+ name="pg"
+ value="PG" />
+ </combo_box>
+ <combo_box
+ bottom="45"
+ height="18"
+ layout="topleft"
+ left="20"
+ name="classified_category_combo"
+ right="150" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Update"
+ layout="topleft"
+ left="30"
+ name="classified_update_btn"
+ top="70"
+ width="70" />
+</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
new file mode 100644
index 0000000000..677bdbc3d2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_classified_info.xml
@@ -0,0 +1,181 @@
+<?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_classified_info"
+ help_topic="profile_classified_info"
+ top="0"
+ width="333">
+ <panel.string
+ name="type_mature">
+ Moderate
+ </panel.string>
+ <panel.string
+ name="type_pg">
+ General Content
+ </panel.string>
+ <button
+ follows="top|right"
+ height="23"
+ image_overlay="BackArrow_Off"
+ layout="topleft"
+ name="back_btn"
+ picture_style="true"
+ left="10"
+ tab_stop="false"
+ top="2"
+ width="23" />
+ <text
+ follows="top|left|right"
+ font="SansSerifHugeBold"
+ height="26"
+ layout="topleft"
+ left_pad="10"
+ name="title"
+ text_color="white"
+ top="0"
+ value="Classified Info"
+ use_ellipses="true"
+ width="275" />
+ <scroll_container
+ color="DkGray2"
+ opaque="true"
+ follows="all"
+ height="500"
+ layout="topleft"
+ left="10"
+ top_pad="10"
+ name="profile_scroll"
+ reserve_scroll_corner="false"
+ width="313">
+ <panel
+ name="scroll_content_panel"
+ follows="left|top"
+ min_height="300"
+ layout="topleft"
+ top="0"
+ background_visible="false"
+ height="500"
+ left="0"
+ width="295">
+ <texture_picker
+ enabled="false"
+ follows="left|top"
+ height="197"
+ layout="topleft"
+ left="10"
+ name="classified_snapshot"
+ top="20"
+ width="290" />
+ <text
+ follows="left|top|right"
+ height="35"
+ width="290"
+ layout="topleft"
+ font="SansSerifBig"
+ font.style="BOLD"
+ left="10"
+ top_pad="10"
+ name="classified_name"
+ text_color="white"
+ value="[name]"
+ use_ellipses="true" />
+ <text
+ follows="left|top"
+ height="25"
+ layout="topleft"
+ left="10"
+ name="classified_location"
+ width="290"
+ word_wrap="true"
+ value="[loading...]" />
+ <text
+ follows="left|top|right"
+ height="18"
+ layout="topleft"
+ left="10"
+ name="content_type"
+ width="290"
+ top_pad="5"
+ value="[content type]" />
+ <text
+ follows="left|top|right"
+ height="18"
+ layout="topleft"
+ left="10"
+ name="category"
+ width="290"
+ top_pad="5"
+ value="[category]" />
+ <check_box
+ enabled="false"
+ height="16"
+ label="Auto renew each week"
+ layout="topleft"
+ left="10"
+ name="auto_renew"
+ top_pad="5"
+ width="290" />
+ <text
+ follows="left|top"
+ halign="left"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="price_for_listing"
+ top_pad="5"
+ tool_tip="Price for listing."
+ width="105">
+ L$[PRICE]
+ </text>
+ <text
+ follows="left|top|right"
+ height="200"
+ layout="topleft"
+ left="10"
+ name="classified_desc"
+ width="290"
+ value="[description]"
+ word_wrap="true" />
+ </panel>
+ </scroll_container>
+ <panel
+ follows="left|right|bottom"
+ height="20"
+ layout="topleft"
+ top_pad="8"
+ left="10"
+ name="buttons">
+ <button
+ follows="bottom|left"
+ height="19"
+ label="Teleport"
+ layout="topleft"
+ left="0"
+ name="teleport_btn"
+ top="0"
+ width="90" />
+ <button
+ follows="bottom|left"
+ height="19"
+ label="Map"
+ layout="topleft"
+ left_pad="10"
+ name="show_on_map_btn"
+ top="0"
+ width="90" />
+ <button
+ follows="bottom|left"
+ height="19"
+ label="Edit"
+ layout="topleft"
+ right="-1"
+ name="edit_btn"
+ top="0"
+ width="90" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml b/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml
new file mode 100644
index 0000000000..b881719e3a
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_classifieds_list_item.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ bevel_style="none"
+ follows="top|left|right"
+ height="85"
+ layout="topleft"
+ left="0"
+ name="classified_item"
+ top="0"
+ width="313">
+ <icon
+ follows="all"
+ height="85"
+ image_name="ListItem_Over"
+ right="-2"
+ mouse_opaque="false"
+ name="hovered_icon"
+ top="1"
+ scale_image="true"
+ visible="false"
+ width="308"/>
+ <icon
+ follows="all"
+ height="85"
+ image_name="ListItem_Select"
+ right="-2"
+ mouse_opaque="false"
+ name="selected_icon"
+ top="1"
+ scale_image="true"
+ visible="false"
+ width="308"/>
+ <texture_picker
+ allow_no_texture="true"
+ border_enabled="true"
+ default_image_name="TabIcon_Places_Large"
+ enabled="false"
+ follows="left|top"
+ height="80"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="picture"
+ tab_stop="false"
+ top="10"
+ top_pad="10"
+ width="90" />
+ <text
+ follows="top|left|right"
+ font="SansSerifSmall"
+ height="15"
+ layout="topleft"
+ left="110"
+ name="name"
+ text_color="white"
+ top="9"
+ use_ellipses="true"
+ width="193"
+ word_wrap="false" />
+ <expandable_text
+ follows="top|left|right"
+ font="SansSerifSmall"
+ height="55"
+ layout="topleft"
+ left="103"
+ name="description"
+ top_pad="0"
+ width="178"
+ word_wrap="true" />
+ <button
+ follows="right"
+ height="20"
+ image_overlay="ForwardArrow_Off"
+ layout="topleft"
+ left_pad="5"
+ right="-8"
+ name="info_chevron"
+ top_delta="15"
+ width="20" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_edit_alpha.xml b/indra/newview/skins/default/xui/en/panel_edit_alpha.xml
new file mode 100644
index 0000000000..40647e1b81
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_alpha.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+ <panel
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="10"
+ name="edit_alpha_panel"
+ top_pad="10"
+ width="313" >
+ <panel
+ border="true"
+ follows="left|top|right"
+ height="180"
+ left="10"
+ layout="topleft"
+ name="avatar_alpha_color_panel"
+ top="0"
+ width="293" >
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Lower Alpha"
+ layout="topleft"
+ left="10"
+ name="Lower Alpha"
+ tool_tip="Click to choose a picture"
+ top="10"
+ width="64" />
+ <check_box
+ control_name="LowerAlphaTextureInvisible"
+ follows="left"
+ height="16"
+ layout="topleft"
+ left_pad="6"
+ name="lower alpha texture invisible"
+ top_delta="4"
+ width="16" />
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Upper Alpha"
+ layout="topleft"
+ left_pad="10"
+ name="Upper Alpha"
+ tool_tip="Click to choose a picture"
+ top="10"
+ width="64" />
+ <check_box
+ control_name="UpperAlphaTextureInvisible"
+ follows="left"
+ height="16"
+ layout="topleft"
+ left_pad="6"
+ name="upper alpha texture invisible"
+ top_delta="4"
+ width="16" />
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Head Alpha"
+ layout="topleft"
+ left_pad="10"
+ name="Head Alpha"
+ tool_tip="Click to choose a picture"
+ top="10"
+ width="64" />
+ <check_box
+ control_name="HeadAlphaTextureInvisible"
+ follows="left"
+ height="16"
+ layout="topleft"
+ left_pad="6"
+ name="head alpha texture invisible"
+ top_delta="4"
+ width="16" />
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Eye Alpha"
+ layout="topleft"
+ left="10"
+ name="Eye Alpha"
+ tool_tip="Click to choose a picture"
+ top="100"
+ width="64" />
+ <check_box
+ control_name="Eye AlphaTextureInvisible"
+ follows="left"
+ height="16"
+ layout="topleft"
+ left_pad="6"
+ name="eye alpha texture invisible"
+ top_delta="4"
+ width="16" />
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Hair Alpha"
+ layout="topleft"
+ left_pad="10"
+ name="Hair Alpha"
+ tool_tip="Click to choose a picture"
+ top_delta="-4"
+ width="64" />
+ <check_box
+ control_name="HairAlphaTextureInvisible"
+ follows="left"
+ height="16"
+ layout="topleft"
+ left_pad="6"
+ name="hair alpha texture invisible"
+ top_delta="4"
+ width="16" />
+ </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
new file mode 100644
index 0000000000..188ded3dab
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_classified.xml
@@ -0,0 +1,257 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ bevel_style="in"
+ follows="left|top|right|bottom"
+ height="570"
+ 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>
+ <button
+ follows="top|right"
+ height="23"
+ image_overlay="BackArrow_Off"
+ layout="topleft"
+ name="back_btn"
+ picture_style="true"
+ left="10"
+ tab_stop="false"
+ top="2"
+ width="23" />
+ <text
+ type="string"
+ length="1"
+ follows="top"
+ font="SansSerifHuge"
+ height="15"
+ layout="topleft"
+ left_pad="10"
+ name="title"
+ text_color="white"
+ top="5"
+ width="250">
+ Edit Classified
+ </text>
+ <scroll_container
+ color="DkGray2"
+ follows="all"
+ height="510"
+ layout="topleft"
+ left="10"
+ top_pad="10"
+ name="profile_scroll"
+ reserve_scroll_corner="false"
+ opaque="true"
+ width="313">
+ <panel
+ name="scroll_content_panel"
+ follows="left|top"
+ min_height="300"
+ layout="topleft"
+ top="0"
+ background_visible="false"
+ height="600"
+ left="0"
+ width="295">
+ <texture_picker
+ follows="left|top|right"
+ height="197"
+ width="290"
+ layout="topleft"
+ top="20"
+ left="10"
+ name="classified_snapshot" />
+ <icon
+ height="18"
+ image_name="AddItem_Off"
+ layout="topleft"
+ right="-5"
+ name="edit_icon"
+ label=""
+ tool_tip="Click to select an image"
+ top="27"
+ width="18" />
+ <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="290">
+ Title:
+ </text>
+ <line_editor
+ follows="left|top|right"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left="10"
+ top_pad="2"
+ max_length="63"
+ name="classified_name"
+ prevalidate_callback="ascii"
+ text_color="black"
+ width="290" />
+ <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="290">
+ Description:
+ </text>
+ <text_editor
+ follows="left|top|right"
+ height="100"
+ width="290"
+ hide_scrollbar="false"
+ layout="topleft"
+ left="10"
+ top_pad="2"
+ max_length="1023"
+ 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="290">
+ Location:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="50"
+ layout="topleft"
+ left="10"
+ name="classified_location"
+ right="-10"
+ top_pad="2"
+ width="290"
+ word_wrap="true">
+ loading...
+ </text>
+ <button
+ follows="left|top"
+ height="20"
+ label="Set to Current Location"
+ layout="topleft"
+ left="8"
+ top_pad="5"
+ name="set_to_curr_location_btn"
+ width="200" />
+ <combo_box
+ follows="left|top"
+ height="18"
+ label=""
+ left="10"
+ name="category"
+ top_pad="5"
+ width="200" />
+ <combo_box
+ allow_text_entry="false"
+ follows="left|top"
+ height="18"
+ left="10"
+ name="content_type"
+ top_pad="5"
+ width="200">
+ <combo_item
+ name="mature_ci"
+ value="Mature">
+ Moderate Content
+ </combo_item>
+ <combo_item
+ name="pg_ci"
+ value="PG">
+ General Content
+ </combo_item>
+ </combo_box>
+ <spinner
+ decimal_digits="0"
+ follows="left|top"
+ halign="left"
+ height="16"
+ increment="1"
+ label_width="20"
+ label="L$"
+ 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" />
+ <check_box
+ height="16"
+ label="Auto renew each week"
+ layout="topleft"
+ left="10"
+ name="auto_renew"
+ top_pad="5"
+ width="250" />
+ </panel>
+ </scroll_container>
+ <panel
+ follows="left|right|bottom"
+ height="20"
+ label="bottom_panel"
+ layout="topleft"
+ left="10"
+ name="bottom_panel"
+ top_pad="5"
+ width="303">
+ <button
+ follows="bottom|left"
+ height="19"
+ label="Save"
+ layout="topleft"
+ name="save_changes_btn"
+ left="0"
+ top="0"
+ width="130" />
+ <button
+ follows="bottom|left"
+ height="19"
+ label="Cancel"
+ layout="topleft"
+ name="cancel_btn"
+ left_pad="5"
+ right="-1"
+ width="130" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_edit_eyes.xml b/indra/newview/skins/default/xui/en/panel_edit_eyes.xml
new file mode 100644
index 0000000000..c514054c41
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_eyes.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+ <panel
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="10"
+ name="edit_eyes_panel"
+ top_pad="10"
+ width="313" >
+ <panel
+ border="true"
+ follows="left|top|right"
+ height="100"
+ left="10"
+ layout="topleft"
+ name="avatar_eye_color_panel"
+ top="0"
+ width="293" >
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Iris"
+ layout="topleft"
+ left="8"
+ name="Iris"
+ tool_tip="Click to choose a picture"
+ top_pad="10"
+ width="64" />
+ </panel>
+ <accordion
+ follows="left|top|right|bottom"
+ height ="340"
+ left="10"
+ name="wearable_accordion"
+ top_pad="10"
+ width="303">
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="eyes_main_tab"
+ title="Eyes">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="eyes_main_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ </accordion>
+</panel>
+
diff --git a/indra/newview/skins/default/xui/en/panel_edit_gloves.xml b/indra/newview/skins/default/xui/en/panel_edit_gloves.xml
new file mode 100644
index 0000000000..7aca40e8d9
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_gloves.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+ <panel
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="10"
+ name="edit_gloves_panel"
+ top_pad="10"
+ width="313" >
+ <panel
+ border="true"
+ follows="left|top|right"
+ height="100"
+ left="10"
+ layout="topleft"
+ name="avatar_gloves_color_panel"
+ top="0"
+ width="293" >
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Fabric"
+ layout="topleft"
+ left="10"
+ name="Fabric"
+ tool_tip="Click to choose a picture"
+ top="10"
+ width="64" />
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="80"
+ label="Color/Tint"
+ layout="topleft"
+ left_pad="10"
+ name="Color/Tint"
+ tool_tip="Click to open color picker"
+ top="10"
+ width="64" />
+ </panel>
+ <accordion
+ follows="left|top|right|bottom"
+ height ="340"
+ left="10"
+ name="wearable_accordion"
+ top_pad="10"
+ width="303">
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="gloves_main_tab"
+ title="Gloves">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="gloves_main_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ </accordion>
+</panel>
+
diff --git a/indra/newview/skins/default/xui/en/panel_edit_hair.xml b/indra/newview/skins/default/xui/en/panel_edit_hair.xml
new file mode 100644
index 0000000000..e7d1c05301
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_hair.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+ <panel
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="10"
+ name="edit_hair_panel"
+ top_pad="10"
+ width="313" >
+ <panel
+ border="true"
+ follows="left|top|right"
+ height="100"
+ left="10"
+ layout="topleft"
+ name="avatar_hair_color_panel"
+ top="0"
+ width="293" >
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Texture"
+ layout="topleft"
+ left="8"
+ name="Texture"
+ tool_tip="Click to choose a picture"
+ top="10"
+ width="64" />
+ </panel>
+ <accordion
+ follows="left|top|right|bottom"
+ height ="340"
+ left="10"
+ name="wearable_accordion"
+ top_pad="10"
+ width="303">
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="hair_color_tab"
+ title="Color">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="hair_color_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="hair_style_tab"
+ title="Style">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="hair_style_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="hair_eyebrows_tab"
+ title="Eyebrows">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="hair_eyebrows_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="hair_facial_tab"
+ title="Facial">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="hair_facial_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ </accordion>
+</panel>
+
diff --git a/indra/newview/skins/default/xui/en/panel_edit_jacket.xml b/indra/newview/skins/default/xui/en/panel_edit_jacket.xml
new file mode 100644
index 0000000000..ed92b1e0f8
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_jacket.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+ <panel
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="10"
+ name="edit_jacket_panel"
+ top_pad="10"
+ width="313" >
+ <panel
+ border="true"
+ follows="left|top|right"
+ height="100"
+ left="10"
+ layout="topleft"
+ name="avatar_jacket_color_panel"
+ top="0"
+ width="293" >
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Upper Fabric"
+ layout="topleft"
+ left="10"
+ name="Upper Fabric"
+ tool_tip="Click to choose a picture"
+ top="10"
+ width="64" />
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Lower Fabric"
+ layout="topleft"
+ left_pad="10"
+ name="Lower Fabric"
+ tool_tip="Click to choose a picture"
+ top="10"
+ width="64" />
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="80"
+ label="Color/Tint"
+ layout="topleft"
+ left_pad="10"
+ name="Color/Tint"
+ tool_tip="Click to open color picker"
+ top="10"
+ width="64" />
+ </panel>
+ <accordion
+ follows="left|top|right|bottom"
+ height ="340"
+ left="10"
+ name="wearable_accordion"
+ top_pad="10"
+ width="303">
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="jacket_main_tab"
+ title="Jacket">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="jacket_main_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ </accordion>
+</panel>
+
diff --git a/indra/newview/skins/default/xui/en/panel_edit_pants.xml b/indra/newview/skins/default/xui/en/panel_edit_pants.xml
new file mode 100644
index 0000000000..b764188e04
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_pants.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+ <panel
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="10"
+ name="edit_pants_panel"
+ top_pad="10"
+ width="313" >
+ <panel
+ border="true"
+ follows="left|top|right"
+ height="100"
+ left="10"
+ layout="topleft"
+ name="avatar_pants_color_panel"
+ top="0"
+ width="293" >
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Fabric"
+ layout="topleft"
+ left="10"
+ name="Fabric"
+ tool_tip="Click to choose a picture"
+ top="10"
+ width="64" />
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="80"
+ label="Color/Tint"
+ layout="topleft"
+ left_pad="10"
+ name="Color/Tint"
+ tool_tip="Click to open color picker"
+ top="10"
+ width="64" />
+ </panel>
+ <accordion
+ follows="left|top|right|bottom"
+ height ="340"
+ left="10"
+ name="wearable_accordion"
+ top_pad="10"
+ width="303">
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="pants_main_tab"
+ title="Pants">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="pants_main_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ </accordion>
+</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
new file mode 100644
index 0000000000..8e39697a16
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_pick.xml
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ bevel_style="in"
+ follows="left|top|right|bottom"
+ height="570"
+ label="Edit Pick"
+ layout="topleft"
+ left="0"
+ min_height="350"
+ name="panel_edit_pick"
+ help_topic="profile_edit_pick"
+ top="0"
+ width="333">
+ <button
+ follows="top|right"
+ height="23"
+ image_overlay="BackArrow_Off"
+ layout="topleft"
+ name="back_btn"
+ left="10"
+ tab_stop="false"
+ top="2"
+ width="23" />
+ <text
+ type="string"
+ length="1"
+ follows="top"
+ font="SansSerifHuge"
+ height="15"
+ layout="topleft"
+ left_pad="10"
+ name="title"
+ text_color="white"
+ top="5"
+ width="250">
+ Edit Pick
+ </text>
+ <scroll_container
+ color="DkGray2"
+ follows="all"
+ height="500"
+ layout="topleft"
+ left="10"
+ top_pad="10"
+ name="profile_scroll"
+ opaque="true"
+ width="313">
+ <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
+ follows="left|top|right"
+ height="197"
+ width="280"
+ layout="topleft"
+ no_commit_on_selection="true"
+ top="20"
+ left="10"
+ name="pick_snapshot" />
+ <icon
+ height="18"
+ image_name="AddItem_Off"
+ layout="topleft"
+ right="-5"
+ name="edit_icon"
+ label=""
+ tool_tip="Click to select an image"
+ top="27"
+ width="18" />
+ <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="63"
+ name="pick_name"
+ text_color="black"
+ width="280" />
+ <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="280"
+ hide_scrollbar="false"
+ layout="topleft"
+ left="10"
+ top_pad="2"
+ max_length="1023"
+ name="pick_desc"
+ 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="20"
+ 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="20"
+ label="bottom_panel"
+ layout="topleft"
+ left="10"
+ name="bottom_panel"
+ top_pad="5"
+ width="303">
+ <button
+ follows="bottom|left"
+ height="19"
+ label="Save [WHAT]"
+ layout="topleft"
+ name="save_changes_btn"
+ left="0"
+ top="0"
+ width="130" />
+ <button
+ follows="bottom|left"
+ height="19"
+ label="Cancel"
+ layout="topleft"
+ name="cancel_btn"
+ left_pad="5"
+ right="-1"
+ width="130" />
+ </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
new file mode 100644
index 0000000000..8268937e7f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_profile.xml
@@ -0,0 +1,345 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ class="edit_profile_panel"
+ follows="all"
+ height="535"
+ 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="505"
+ min_height="300"
+ layout="topleft"
+ left="0"
+ name="profile_scroll"
+ reserve_scroll_corner="true"
+ opaque="true"
+ top="0">
+ <panel
+ name="scroll_content_panel"
+ follows="left|top|right"
+ layout="topleft"
+ top="0"
+ height="505"
+ min_height="300"
+ left="0"
+ width="313">
+ <panel
+ name="data_panel"
+ follows="left|top|right"
+ layout="topleft"
+ top="0"
+ height="505"
+ min_height="300"
+ left="0"
+ width="313">
+ <panel
+ name="lifes_images_panel"
+ follows="left|top|right"
+ height="244"
+ layout="topleft"
+ top="0"
+ left="0"
+ width="285">
+ <panel
+ follows="left|top"
+ height="117"
+ layout="topleft"
+ left="10"
+ name="second_life_image_panel"
+ top="0"
+ width="285">
+ <text
+ follows="left|top|right"
+ font.style="BOLD"
+ height="15"
+ layout="topleft"
+ left="0"
+ name="second_life_photo_title_text"
+ text_color="white"
+ value="[SECOND_LIFE]:"
+ width="170" />
+ <texture_picker
+ allow_no_texture="true"
+ default_image_name="None"
+ enabled="false"
+ follows="top|left"
+ height="117"
+ layout="topleft"
+ left="0"
+ name="2nd_life_pic"
+ top_pad="0"
+ width="102" />
+ </panel>
+ <icon
+ height="18"
+ image_name="AddItem_Off"
+ layout="topleft"
+ name="2nd_life_edit_icon"
+ label=""
+ left="87"
+ tool_tip="Click to select an image"
+ top="25"
+ width="18" />
+ </panel>
+ <text_editor
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerifSmall"
+ height="100"
+ layout="topleft"
+ left="120"
+ top="18"
+ max_length="512"
+ name="sl_description_edit"
+ width="173"
+ 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"
+ name="real_world_photo_title_text"
+ text_color="white"
+ value="Real World:"
+ width="173" />
+ <texture_picker
+ allow_no_texture="true"
+ default_image_name="None"
+ enabled="false"
+ follows="top|left"
+ height="117"
+ layout="topleft"
+ left="0"
+ name="real_world_pic"
+ top_pad="0"
+ width="102" />
+ </panel>
+ <icon
+ height="18"
+ image_name="AddItem_Off"
+ layout="topleft"
+ name="real_world_edit_icon"
+ label=""
+ left="87"
+ tool_tip="Click to select an image"
+ top="148"
+ width="18" />
+ <text_editor
+ type="string"
+ length="1"
+ follows="left|top|right"
+ font="SansSerifSmall"
+ height="100"
+ layout="topleft"
+ left="120"
+ max_length="512"
+ top="142"
+ name="fl_description_edit"
+ width="173"
+ 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="285">
+ 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="285">
+ </line_editor>
+ <check_box
+ follows="left|top"
+ font="SansSerifSmall"
+ label="Show me in Search results"
+ layout="topleft"
+ left="10"
+ name="show_in_search_checkbox"
+ height="15"
+ text_enabled_color="white"
+ top_pad="10"
+ width="240" />
+ <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="5"
+ value="My Account:"
+ width="285" />
+ <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="285" />
+ <text
+ follows="left|top|right"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="acc_status_text"
+ top_pad="5"
+ value="Resident. No payment info on file."
+ width="285"
+ word_wrap="true" />
+ <text
+ follows="left|top"
+ font="SansSerifSmall"
+ font.style="BOLD"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="title_partner_text"
+ text_color="white"
+ top_pad="0"
+ value="My Partner:"
+ width="150" />
+ <text
+ follows="left|top"
+ height="15"
+ halign="right"
+ layout="topleft"
+ left_pad="10"
+ right="-10"
+ name="partner_edit_link"
+ value="[[URL] Edit]"
+ width="50" />
+ <panel
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="partner_data_panel"
+ width="285">
+ <name_box
+ follows="left|top|right"
+ height="30"
+ initial_value="(retrieving)"
+ layout="topleft"
+ left="0"
+ link="true"
+ name="partner_text"
+ top="0"
+ width="285"
+ word_wrap="true" />
+ </panel>
+ </panel>
+ </panel>
+ </scroll_container>
+ <panel
+ follows="bottom|left"
+ height="20"
+ left="10"
+ name="profile_me_buttons_panel"
+ top_pad="5"
+ width="303">
+ <button
+ follows="bottom|left"
+ height="19"
+ label="Save Changes"
+ layout="topleft"
+ left="0"
+ name="save_btn"
+ top="0"
+ width="130" />
+ <button
+ follows="bottom|left"
+ height="19"
+ label="Cancel"
+ layout="topleft"
+ left_pad="10"
+ name="cancel_btn"
+ right="-1"
+ width="130" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_edit_shape.xml b/indra/newview/skins/default/xui/en/panel_edit_shape.xml
new file mode 100644
index 0000000000..45c4b92338
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_shape.xml
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+ <panel
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="10"
+ name="edit_shape_panel"
+ top_pad="10"
+ width="313" >
+ <panel
+ border="true"
+ follows="top|left"
+ height="50"
+ left="10"
+ layout="topleft"
+ name="avatar_sex_panel"
+ top="10"
+ width="293" >
+ <text
+ follows="top|left"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="gender_text"
+ width="303">
+ Gender:
+ </text>
+ <radio_group
+ follows="all"
+ left="10"
+ height="34"
+ layout="topleft"
+ name="sex_radio"
+ top_pad="3"
+ width="200" >
+ <radio_item
+ follows="all"
+ height="16"
+ label="Female"
+ layout="topleft"
+ left="10"
+ name="radio"
+ width="82" />
+ <radio_item
+ follows="all"
+ height="16"
+ label="Male"
+ layout="topleft"
+ left_pad="10"
+ name="radio2"
+ width="82" />
+ </radio_group>
+ </panel>
+ <accordion
+ follows="left|top|right|bottom"
+ height ="330"
+ left="10"
+ name="wearable_accordion"
+ top_pad="10"
+ width="303">
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="shape_body_tab"
+ title="Body">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="shape_body_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="shape_head_tab"
+ title="Head">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="shape_head_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="shape_eyes_tab"
+ title="Eyes">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="shape_eyes_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="shape_ears_tab"
+ title="Ears">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="shape_ears_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="shape_nose_tab"
+ title="Nose">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="shape_nose_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="shape_mouth_tab"
+ title="Mouth">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="shape_mouth_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="shape_chin_tab"
+ title="Chin">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="shape_chin_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="shape_torso_tab"
+ title="Torso">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="shape_torso_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="shape_legs_tab"
+ title="Legs">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="shape_legs_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ </accordion>
+</panel>
+
diff --git a/indra/newview/skins/default/xui/en/panel_edit_shirt.xml b/indra/newview/skins/default/xui/en/panel_edit_shirt.xml
new file mode 100644
index 0000000000..4b7235545f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_shirt.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+ <panel
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="10"
+ name="edit_shirt_panel"
+ top_pad="10"
+ width="313" >
+ <panel
+ border="true"
+ follows="left|top|right"
+ height="100"
+ left="10"
+ layout="topleft"
+ name="avatar_shirt_color_panel"
+ top="0"
+ width="293" >
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Fabric"
+ layout="topleft"
+ left="10"
+ name="Fabric"
+ tool_tip="Click to choose a picture"
+ top="10"
+ width="64" />
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="80"
+ label="Color/Tint"
+ layout="topleft"
+ left_pad="10"
+ name="Color/Tint"
+ tool_tip="Click to open color picker"
+ top="10"
+ width="64" />
+ </panel>
+ <accordion
+ follows="left|top|right|bottom"
+ height ="340"
+ left="10"
+ name="wearable_accordion"
+ top_pad="10"
+ width="303">
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="shirt_main_tab"
+ title="Shirt">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="shirt_main_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ </accordion>
+</panel>
+
diff --git a/indra/newview/skins/default/xui/en/panel_edit_shoes.xml b/indra/newview/skins/default/xui/en/panel_edit_shoes.xml
new file mode 100644
index 0000000000..e886afa010
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_shoes.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+ <panel
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="10"
+ name="edit_shoes_panel"
+ top_pad="10"
+ width="313" >
+ <panel
+ border="true"
+ follows="left|top|right"
+ height="100"
+ left="10"
+ layout="topleft"
+ name="avatar_shoes_color_panel"
+ top="0"
+ width="293" >
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Fabric"
+ layout="topleft"
+ left="10"
+ name="Fabric"
+ tool_tip="Click to choose a picture"
+ top="10"
+ width="64" />
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="80"
+ label="Color/Tint"
+ layout="topleft"
+ left_pad="10"
+ name="Color/Tint"
+ tool_tip="Click to open color picker"
+ top="10"
+ width="64" />
+ </panel>
+ <accordion
+ follows="left|top|right|bottom"
+ height ="340"
+ left="10"
+ name="wearable_accordion"
+ top_pad="10"
+ width="303">
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="shoes_main_tab"
+ title="Shoes">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="shoes_main_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ </accordion>
+</panel>
+
diff --git a/indra/newview/skins/default/xui/en/panel_edit_skin.xml b/indra/newview/skins/default/xui/en/panel_edit_skin.xml
new file mode 100644
index 0000000000..918606b54c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_skin.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+ <panel
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="10"
+ name="edit_skin_panel"
+ top_pad="10"
+ width="313" >
+ <panel
+ border="true"
+ follows="left|top|right"
+ height="100"
+ left="10"
+ layout="topleft"
+ name="avatar_skin_color_panel"
+ top="0"
+ width="293" >
+ <texture_picker
+ allow_no_texture="true"
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Head Tattoos"
+ layout="topleft"
+ left="10"
+ name="Head Tattoos"
+ tool_tip="Click to choose a picture"
+ top="10"
+ width="74" />
+ <texture_picker
+ allow_no_texture="true"
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Upper Tattoos"
+ layout="topleft"
+ left_pad="10"
+ name="Upper Tattoos"
+ tool_tip="Click to choose a picture"
+ top="10"
+ width="74" />
+ <texture_picker
+ allow_no_texture="true"
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Lower Tattoos"
+ layout="topleft"
+ left_pad="10"
+ name="Lower Tattoos"
+ tool_tip="Click to choose a picture"
+ top="10"
+ width="74" />
+ </panel>
+ <accordion
+ follows="left|top|right|bottom"
+ height ="340"
+ left="10"
+ name="wearable_accordion"
+ top_pad="10"
+ width="303">
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="skin_color_tab"
+ title="Skin Color">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="skin_color_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="skin_face_tab"
+ title="Face Detail">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="skin_face_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="skin_makeup_tab"
+ title="Makeup">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="skin_makeup_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="skin_body_tab"
+ title="Body Detail">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="skin_body_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ </accordion>
+</panel>
+
diff --git a/indra/newview/skins/default/xui/en/panel_edit_skirt.xml b/indra/newview/skins/default/xui/en/panel_edit_skirt.xml
new file mode 100644
index 0000000000..6cccab1843
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_skirt.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+ <panel
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="10"
+ name="edit_skirt_panel"
+ top_pad="10"
+ width="313" >
+ <panel
+ border="true"
+ follows="left|top|right"
+ height="100"
+ left="10"
+ layout="topleft"
+ name="avatar_skirt_color_panel"
+ top="0"
+ width="293" >
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Fabric"
+ layout="topleft"
+ left="10"
+ name="Fabric"
+ tool_tip="Click to choose a picture"
+ top="10"
+ width="64" />
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="80"
+ label="Color/Tint"
+ layout="topleft"
+ left_pad="10"
+ name="Color/Tint"
+ tool_tip="Click to open color picker"
+ top="10"
+ width="64" />
+ </panel>
+ <accordion
+ follows="left|top|right|bottom"
+ height ="340"
+ left="10"
+ name="wearable_accordion"
+ top_pad="10"
+ width="303">
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="skirt_main_tab"
+ title="Skirt">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="skirt_main_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ </accordion>
+</panel>
+
diff --git a/indra/newview/skins/default/xui/en/panel_edit_socks.xml b/indra/newview/skins/default/xui/en/panel_edit_socks.xml
new file mode 100644
index 0000000000..fc7de00714
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_socks.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+ <panel
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="10"
+ name="edit_socks_panel"
+ top_pad="10"
+ width="313" >
+ <panel
+ border="true"
+ follows="left|top|right"
+ height="100"
+ left="10"
+ layout="topleft"
+ name="avatar_socks_color_panel"
+ top="0"
+ width="293" >
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Fabric"
+ layout="topleft"
+ left="10"
+ name="Fabric"
+ tool_tip="Click to choose a picture"
+ top="10"
+ width="64" />
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="80"
+ label="Color/Tint"
+ layout="topleft"
+ left_pad="10"
+ name="Color/Tint"
+ tool_tip="Click to open color picker"
+ top="10"
+ width="64" />
+ </panel>
+ <accordion
+ follows="left|top|right|bottom"
+ height ="340"
+ left="10"
+ name="wearable_accordion"
+ top_pad="10"
+ width="303">
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="socks_main_tab"
+ title="Socks">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="socks_main_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ </accordion>
+</panel>
+
diff --git a/indra/newview/skins/default/xui/en/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/en/panel_edit_tattoo.xml
new file mode 100644
index 0000000000..b214cd3de0
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_tattoo.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+ <panel
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="10"
+ name="edit_tattoo_panel"
+ top_pad="10"
+ width="313" >
+ <panel
+ border="true"
+ follows="left|top|right"
+ height="100"
+ left="10"
+ layout="topleft"
+ name="avatar_tattoo_color_panel"
+ top="0"
+ width="293" >
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Head Tattoo"
+ layout="topleft"
+ left="10"
+ name="Head Tattoo"
+ tool_tip="Click to choose a picture"
+ top="10"
+ width="64" />
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Upper Tattoo"
+ layout="topleft"
+ left_pad="10"
+ name="Upper Tattoo"
+ tool_tip="Click to choose a picture"
+ top="10"
+ width="64" />
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Lower Tattoo"
+ layout="topleft"
+ left_pad="10"
+ name="Lower Tattoo"
+ tool_tip="Click to choose a picture"
+ top="10"
+ width="64" />
+ </panel>
+</panel>
+
diff --git a/indra/newview/skins/default/xui/en/panel_edit_underpants.xml b/indra/newview/skins/default/xui/en/panel_edit_underpants.xml
new file mode 100644
index 0000000000..03e0bb70ef
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_underpants.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+ <panel
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="10"
+ name="edit_underpants_panel"
+ top_pad="10"
+ width="313" >
+ <panel
+ border="true"
+ follows="left|top|right"
+ height="100"
+ left="10"
+ layout="topleft"
+ name="avatar_underpants_color_panel"
+ top="0"
+ width="293" >
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Fabric"
+ layout="topleft"
+ left="10"
+ name="Fabric"
+ tool_tip="Click to choose a picture"
+ top="10"
+ width="64" />
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="80"
+ label="Color/Tint"
+ layout="topleft"
+ left_pad="10"
+ name="Color/Tint"
+ tool_tip="Click to open color picker"
+ top="10"
+ width="64" />
+ </panel>
+ <accordion
+ follows="left|top|right|bottom"
+ height ="340"
+ left="10"
+ name="wearable_accordion"
+ top_pad="10"
+ width="303">
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="underpants_main_tab"
+ title="Underpants">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="underpants_main_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ </accordion>
+</panel>
+
diff --git a/indra/newview/skins/default/xui/en/panel_edit_undershirt.xml b/indra/newview/skins/default/xui/en/panel_edit_undershirt.xml
new file mode 100644
index 0000000000..20c56142fb
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_undershirt.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+ <panel
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="10"
+ name="edit_undershirt_panel"
+ top_pad="10"
+ width="313" >
+ <panel
+ border="true"
+ follows="left|top|right"
+ height="100"
+ left="10"
+ layout="topleft"
+ name="avatar_undershirt_color_panel"
+ top="0"
+ width="293" >
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="80"
+ label="Fabric"
+ layout="topleft"
+ left="10"
+ name="Fabric"
+ tool_tip="Click to choose a picture"
+ top="10"
+ width="64" />
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="80"
+ label="Color/Tint"
+ layout="topleft"
+ left_pad="10"
+ name="Color/Tint"
+ tool_tip="Click to open Color Picker"
+ top="10"
+ width="64" />
+ </panel>
+ <accordion
+ follows="left|top|right|bottom"
+ height ="340"
+ left="10"
+ name="wearable_accordion"
+ top_pad="10"
+ width="303">
+ <accordion_tab
+ layout="topleft"
+ min_height="150"
+ name="undershirt_main_tab"
+ title="Undershirt">
+ <scrolling_panel_list
+ follows="all"
+ left="0"
+ name="undershirt_main_param_list"
+ top="0"
+ width="303" />
+ </accordion_tab>
+ </accordion>
+</panel>
+
diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
new file mode 100644
index 0000000000..f76a56bda4
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
@@ -0,0 +1,364 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ bevel_style="in"
+ follows="all"
+ height="570"
+ label="Wearable"
+ layout="topleft"
+left="0"
+ name="panel_edit_wearable"
+ top="0"
+ width="333">
+ <string
+ name="edit_shape_title">
+ Editing Shape
+ </string>
+ <string
+ name="edit_skin_title">
+ Editing Skin
+ </string>
+ <string
+ name="edit_hair_title">
+ Editing Hair
+ </string>
+ <string
+ name="edit_eyes_title">
+ Editing Eyes
+ </string>
+ <string
+ name="edit_shirt_title">
+ Editing Shirt
+ </string>
+ <string
+ name="edit_pants_title">
+ Editing Pants
+ </string>
+ <string
+ name="edit_shoes_title">
+ Editing Shoes
+ </string>
+ <string
+ name="edit_socks_title">
+ Editing Socks
+ </string>
+ <string
+ name="edit_jacket_title">
+ Editing Jacket
+ </string>
+ <string
+ name="edit_skirt_title">
+ Editing Skirt
+ </string>
+ <string
+ name="edit_gloves_title">
+ Editing Gloves
+ </string>
+ <string
+ name="edit_undershirt_title">
+ Editing Undershirt
+ </string>
+ <string
+ name="edit_underpants_title">
+ Editing Underpants
+ </string>
+ <string
+ name="edit_alpha_title">
+ Editing Alpha Mask
+ </string>
+ <string
+ name="edit_tattoo_title">
+ Editing Tattoo
+ </string>
+ <string
+ name="shape_desc_text">
+ Shape:
+ </string>
+ <string
+ name="skin_desc_text">
+ Skin:
+ </string>
+ <string
+ name="hair_desc_text">
+ Hair:
+ </string>
+ <string
+ name="eyes_desc_text">
+ Eyes:
+ </string>
+ <string
+ name="shirt_desc_text">
+ Shirt:
+ </string>
+ <string
+ name="pants_desc_text">
+ Pants:
+ </string>
+ <string
+ name="shoes_desc_text">
+ Shoes:
+ </string>
+ <string
+ name="socks_desc_text">
+ Socks:
+ </string>
+ <string
+ name="jacket_desc_text">
+ Jacket:
+ </string>
+ <string
+ name="skirt_skirt_desc_text">
+ Skirt:
+ </string>
+ <string
+ name="gloves_desc_text">
+ Gloves:
+ </string>
+ <string
+ name="undershirt_desc_text">
+ Undershirt:
+ </string>
+ <string
+ name="underpants_desc_text">
+ Underpants:
+ </string>
+ <string
+ name="alpha_desc_text">
+ Alpha Mask:
+ </string>
+ <string
+ name="tattoo_desc_text">
+ Tattoo:
+ </string>
+ <button
+ follows="top|left"
+ height="25"
+ width="25"
+ image_overlay="BackArrow_Off"
+ layout="topleft"
+ name="back_btn"
+ left="10"
+ top="7" />
+ <text
+ follows="top|left"
+ font="SansSerifHugeBold"
+ height="22"
+ layout="topleft"
+ left_pad="15"
+ name="edit_wearable_title"
+ text_color="white"
+ value="Editing Shape"
+ width="270" />
+ <panel
+ border="true"
+ follows="top|left"
+ height="60"
+ label="Shirt"
+ layout="topleft"
+ left="10"
+ name="wearable_type_panel"
+ top_pad="10"
+ width="313">
+ <text
+ follows="top|left"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="description_text"
+ value="Shape:"
+ width="303" />
+ <text_editor
+ follows="all"
+ height="23"
+ left="10"
+ layout="topleft"
+ max_length="300"
+ name="description"
+ width="290" />
+ </panel>
+ <panel
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="0"
+ name="edit_subpanel_container"
+ top_pad="10"
+ width="333">
+ <panel
+ filename="panel_edit_shape.xml"
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="0"
+ name="edit_shape_panel"
+ top="0"
+ visible="false"
+ width="333" />
+ <panel
+ filename="panel_edit_skin.xml"
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="0"
+ name="edit_skin_panel"
+ top="0"
+ visible="false"
+ width="333" />
+ <panel
+ filename="panel_edit_hair.xml"
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="0"
+ name="edit_hair_panel"
+ top="0"
+ visible="false"
+ width="333" />
+ <panel
+ filename="panel_edit_eyes.xml"
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="0"
+ name="edit_eyes_panel"
+ top="0"
+ visible="false"
+ width="333" />
+ <panel
+ filename="panel_edit_shirt.xml"
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="0"
+ name="edit_shirt_panel"
+ top="0"
+ visible="false"
+ width="333" />
+ <panel
+ filename="panel_edit_pants.xml"
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="0"
+ name="edit_pants_panel"
+ top="0"
+ visible="false"
+ width="333" />
+ <panel
+ filename="panel_edit_shoes.xml"
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="0"
+ name="edit_shoes_panel"
+ top="0"
+ visible="false"
+ width="333" />
+ <panel
+ filename="panel_edit_socks.xml"
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="0"
+ name="edit_socks_panel"
+ top="0"
+ visible="false"
+ width="333" />
+ <panel
+ filename="panel_edit_jacket.xml"
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="0"
+ name="edit_jacket_panel"
+ top="0"
+ visible="false"
+ width="333" />
+ <panel
+ filename="panel_edit_skirt.xml"
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="0"
+ name="edit_skirt_panel"
+ top="0"
+ visible="false"
+ width="333" />
+ <panel
+ filename="panel_edit_gloves.xml"
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="0"
+ name="edit_gloves_panel"
+ top="0"
+ visible="false"
+ width="333" />
+ <panel
+ filename="panel_edit_undershirt.xml"
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="0"
+ name="edit_undershirt_panel"
+ top="0"
+ visible="false"
+ width="333" />
+ <panel
+ filename="panel_edit_underpants.xml"
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="0"
+ name="edit_underpants_panel"
+ top="0"
+ visible="false"
+ width="333" />
+ <panel
+ filename="panel_edit_alpha.xml"
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="0"
+ name="edit_alpha_panel"
+ top="0"
+ visible="false"
+ width="333" />
+ <panel
+ filename="panel_edit_tattoo.xml"
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="0"
+ name="edit_tattoo_panel"
+ top="0"
+ visible="false"
+ width="333" />
+ </panel>
+ <panel
+ follows="all"
+ height="25"
+ layout="bottom|left|right"
+ left="0"
+ name="button_panel"
+ top_pad="10"
+ width="333" >
+ <button
+ follows="bottomleft"
+ layout="topleft"
+ height="23"
+ label="Save As"
+ left="10"
+ name="save_as_button"
+ top="0"
+ width="100" />
+ <button
+ follows="bottomleft"
+ layout="topleft"
+ height="23"
+ label="Revert"
+ left_pad="10"
+ name="revert_button"
+ width="100" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_friends.xml b/indra/newview/skins/default/xui/en/panel_friends.xml
new file mode 100644
index 0000000000..c315adb33e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_friends.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="all"
+ height="347"
+ layout="topleft"
+ name="friends"
+ width="100">
+ <panel.string
+ name="Multiple">
+ Multiple friends
+ </panel.string>
+ <scroll_list
+ bottom="337"
+ column_padding="0"
+ draw_heading="true"
+ follows="left|top|bottom|right"
+ layout="topleft"
+ left="10"
+ multi_select="true"
+ name="friend_list"
+ right="-100"
+ search_column="1"
+ tool_tip="Hold shift or control while clicking to select multiple friends"
+ top="10">
+ <scroll_list.columns
+ image="ff_online_status_button.tga"
+ name="icon_online_status"
+ tool_tip="Online status"
+ width="20" />
+ <scroll_list.columns
+ dynamic_width="true"
+ label="Name"
+ name="friend_name"
+ tool_tip="Name" />
+ <scroll_list.columns
+ image="ff_visible_online_button.tga"
+ name="icon_visible_online"
+ tool_tip="Friend can see when you&apos;re online"
+ width="20" />
+ <scroll_list.columns
+ image="ff_visible_map_button.tga"
+ name="icon_visible_map"
+ tool_tip="Friend can locate you on the map"
+ width="20" />
+ <scroll_list.columns
+ image="ff_edit_mine_button.tga"
+ name="icon_edit_mine"
+ tool_tip="Friend can edit, delete or take objects"
+ width="20" />
+ <scroll_list.columns
+ image="ff_edit_theirs_button.tga"
+ name="icon_edit_theirs"
+ tool_tip="You can edit this friend&apos;s objects"
+ width="20" />
+ <scroll_list.columns
+ name="friend_last_update_generation"
+ width="0" />
+ </scroll_list>
+ <locate
+ bottom="7"
+ layout="topleft"
+ left="-90" />
+ <button
+ follows="top|right"
+ height="22"
+ label="IM/Call"
+ layout="topleft"
+ left_pad="10"
+ name="im_btn"
+ tool_tip="Open Instant Message session"
+ top_pad="3"
+ width="80" />
+ <button
+ follows="top|right"
+ height="22"
+ label="Profile"
+ layout="topleft"
+ left_delta="0"
+ name="profile_btn"
+ tool_tip="Show picture, groups, and other information"
+ top_pad="3"
+ width="80" />
+ <button
+ follows="top|right"
+ height="22"
+ label="Teleport"
+ layout="topleft"
+ left_delta="0"
+ name="offer_teleport_btn"
+ tool_tip="Offer this friend a teleport to your current location"
+ top_pad="3"
+ width="80" />
+ <button
+ follows="top|right"
+ height="22"
+ label="Pay"
+ layout="topleft"
+ left_delta="0"
+ name="pay_btn"
+ tool_tip="Give Linden dollars (L$) to this friend"
+ top_pad="3"
+ width="80" />
+ <button
+ follows="top|right"
+ height="22"
+ label="Remove"
+ layout="topleft"
+ left_delta="0"
+ name="remove_btn"
+ tool_tip="Remove this person from your friends list"
+ top_pad="3"
+ width="80" />
+ <button
+ follows="top|right"
+ height="22"
+ label="Add"
+ layout="topleft"
+ left_delta="0"
+ name="add_btn"
+ tool_tip="Offer friendship to a Resident"
+ top_pad="13"
+ width="80" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml
new file mode 100644
index 0000000000..aa7d621e4c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="false"
+ follows="all"
+ height="238"
+ name="panel_im_control_panel"
+ width="150">
+ <layout_stack
+ mouse_opaque="false"
+ border_size="0"
+ clip="false"
+ follows="all"
+ height="238"
+ layout="topleft"
+ left="5"
+ name="vertical_stack"
+ orientation="vertical"
+ top="0"
+ width="145">
+ <layout_panel
+ auto_resize="true"
+ follows="top|left"
+ height="100"
+ layout="topleft"
+ min_height="0"
+ mouse_opaque="false"
+ width="145"
+ top="0"
+ name="speakers_list_panel"
+ user_resize="false">
+ <avatar_list
+ color="DkGray2"
+ follows="all"
+ height="100"
+ ignore_online_status="true"
+ layout="topleft"
+ name="speakers_list"
+ opaque="false"
+ show_info_btn="false"
+ show_profile_btn="false"
+ show_speaking_indicator="false"
+ width="145" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ width="130"
+ name="group_info_btn_panel"
+ user_resize="false">
+ <button
+ follows="left|right|bottom"
+ height="23"
+ label="Group Profile"
+ name="group_info_btn"
+ use_ellipses="true"
+ top="5"
+ width="130" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ width="130"
+ name="call_btn_panel"
+ user_resize="false">
+ <button
+ follows="all"
+ height="23"
+ label="Call Group"
+ name="call_btn"
+ use_ellipses="true"
+ width="130" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ width="130"
+ name="end_call_btn_panel"
+ user_resize="false"
+ visible="false">
+ <button
+ follows="all"
+ height="23"
+ label="Leave Call"
+ name="end_call_btn"
+ use_ellipses="true" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ width="130"
+ name="voice_ctrls_btn_panel"
+ user_resize="false"
+ visible="false">
+ <button
+ follows="all"
+ height="23"
+ label="Open Voice Controls"
+ name="voice_ctrls_btn"
+ use_ellipses="true" />
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_general.xml b/indra/newview/skins/default/xui/en/panel_group_general.xml
new file mode 100644
index 0000000000..af73faf9a1
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_group_general.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="all"
+ height="395"
+ label="General"
+ class="panel_group_general"
+ layout="topleft"
+ name="general_tab"
+ width="323">
+ <panel.string
+ name="help_text">
+ The General tab contains general information about this group, a list of members, general Group Preferences and member options.
+
+Hover your mouse over the options for more help.
+ </panel.string>
+ <panel.string
+ name="group_info_unchanged">
+ General group information has changed
+ </panel.string>
+ <panel.string
+ name="incomplete_member_data_str">
+ Retrieving member data
+ </panel.string>
+ <text_editor
+ type="string"
+ follows="left|top|right"
+ left="5"
+ height="60"
+ layout="topleft"
+ max_length="511"
+ name="charter"
+ top="5"
+ right="-1"
+ word_wrap="true">
+ Group Charter
+ </text_editor>
+ <name_list
+ column_padding="0"
+ draw_heading="true"
+ follows="left|top|right"
+ heading_height="20"
+ height="156"
+ layout="topleft"
+ left="0"
+ right="-1"
+ name="visible_members"
+ top_pad="2">
+ <name_list.columns
+ label="Member"
+ name="name"
+ relative_width="0.6" />
+ <name_list.columns
+ label="Title"
+ name="title"
+ relative_width="0.4" />
+ </name_list>
+ <text
+ follows="left|top|right"
+ type="string"
+ height="12"
+ layout="left|top|right"
+ left="5"
+ name="active_title_label"
+ top_pad="5"
+ width="300">
+ My Title
+ </text>
+ <combo_box
+ follows="left|top|right"
+ height="20"
+ layout="topleft"
+ left="5"
+ right="-5"
+ name="active_title"
+ tool_tip="Sets the title that appears in your avatar&apos;s name tag when this group is active."
+ top_pad="2" />
+ <check_box
+ height="16"
+ font="SansSerifSmall"
+ label="Receive group notices"
+ layout="topleft"
+ left="5"
+ name="receive_notices"
+ tool_tip="Sets whether you want to receive Notices from this group. Uncheck this box if this group is spamming you."
+ top_pad="5"
+ width="300" />
+ <check_box
+ height="16"
+ label="Show in my profile"
+ layout="topleft"
+ left="5"
+ name="list_groups_in_profile"
+ tool_tip="Sets whether you want to show this group in your profile"
+ top_pad="5"
+ width="295" />
+ <panel
+ background_visible="true"
+ bevel_style="in"
+ border="true"
+ bg_alpha_color="FloaterUnfocusBorderColor"
+ follows="left|top|right"
+ height="88"
+ layout="topleft"
+ left="2"
+ right="-1"
+ name="preferences_container"
+ top_pad="2">
+ <check_box
+ follows="right|top|left"
+ height="16"
+ label="Open enrollment"
+ layout="topleft"
+ left="10"
+ name="open_enrollement"
+ tool_tip="Sets whether this group allows new members to join without being invited."
+ top_pad="5"
+ width="90" />
+ <check_box
+ height="16"
+ label="Enrollment fee"
+ layout="topleft"
+ left_delta="0"
+ name="check_enrollment_fee"
+ tool_tip="Sets whether to require an enrollment fee to join the group"
+ top_pad="5"
+ width="300" />
+ <spinner
+ decimal_digits="0"
+ follows="left|top|right"
+ halign="left"
+ height="16"
+ increment="1"
+ label_width="15"
+ label="L$"
+ layout="topleft"
+ right="-30"
+ max_val="99999"
+ left_pad="0"
+ name="spin_enrollment_fee"
+ tool_tip="New members must pay this fee to join the group when Enrollment Fee is checked."
+ width="80" />
+ <combo_box
+ follows="left|top|right"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="group_mature_check"
+ tool_tip="Sets whether your group contains information rated as Moderate"
+ top_pad="0"
+ width="190">
+ <combo_box.item
+ label="General Content"
+ name="pg"
+ value="Not Mature" />
+ <combo_box.item
+ label="Moderate Content"
+ name="mature"
+ value="Mature" />
+ </combo_box>
+ <check_box
+ follows="left|top|right"
+ height="16"
+ initial_value="true"
+ label="Show in search"
+ layout="topleft"
+ left="10"
+ name="show_in_group_list"
+ tool_tip="Let people see this group in search results"
+ top_pad="4"
+ width="300" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
new file mode 100644
index 0000000000..0893c204e7
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
@@ -0,0 +1,243 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+background_visible="true"
+ follows="all"
+ height="635"
+ label="Group Info"
+ layout="topleft"
+ min_height="460"
+ left="0"
+ top="20"
+ name="GroupInfo"
+ width="323">
+ <panel.string
+ name="default_needs_apply_text">
+ There are unsaved changes to the current tab
+ </panel.string>
+ <panel.string
+ name="want_apply_text">
+ Do you want to save these changes?
+ </panel.string>
+ <panel.string
+ name="group_join_btn">
+ Join (L$[AMOUNT])
+ </panel.string>
+ <panel.string
+ name="group_join_free">
+ Free
+ </panel.string>
+ <button
+ follows="top|right"
+ height="23"
+ image_overlay="BackArrow_Off"
+ layout="topleft"
+ name="back"
+ left="10"
+ tab_stop="false"
+ top="2"
+ width="23" />
+ <text
+ follows="top|left|right"
+ font="SansSerifHugeBold"
+ height="26"
+ layout="topleft"
+ left_pad="10"
+ name="group_name"
+ text_color="white"
+ top="0"
+ value="(Loading...)"
+ use_ellipses="true"
+ width="300" />
+ <line_editor
+ follows="left|top"
+ font="SansSerif"
+ label="Type your new group name here"
+ layout="topleft"
+ left_delta="10"
+ max_length="35"
+ name="group_name_editor"
+ top_delta="5"
+ width="250"
+ height="20"
+ visible="false" />
+ <texture_picker
+ follows="left|top"
+ height="113"
+ label=""
+ layout="topleft"
+ left="20"
+ name="insignia"
+ no_commit_on_selection="true"
+ tool_tip="Click to choose a picture"
+ top_pad="5"
+ width="100" />
+ <text
+ type="string"
+ follows="left|top"
+ height="16"
+ length="1"
+ layout="topleft"
+ left_pad="10"
+ name="prepend_founded_by"
+ top_delta="0"
+ width="140">
+ Founder:
+ </text>
+ <name_box
+ follows="left|top"
+ height="16"
+ initial_value="(retrieving)"
+ layout="topleft"
+ left_delta="0"
+ link="true"
+ name="founder_name"
+ top_pad="2"
+ use_ellipses="true"
+ width="140" />
+ <text
+ font="SansSerifBig"
+ text_color="EmphasisColor"
+ type="string"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="join_cost_text"
+ top_pad="10"
+ visible="true"
+ width="140">
+ Free
+ </text>
+ <button
+ follows="left|top"
+ left_delta="0"
+ top_pad="6"
+ height="23"
+ label="JOIN NOW!"
+ name="btn_join"
+ visible="true"
+ width="120" />
+ <accordion
+ single_expansion="true"
+ follows="all"
+ height="478"
+ layout="topleft"
+ left="0"
+ name="groups_accordion"
+ top_pad="10"
+ width="323">
+ <accordion_tab
+ expanded="false"
+ layout="topleft"
+ name="group_general_tab"
+ title="General">
+ <panel
+ border="false"
+ class="panel_group_general"
+ filename="panel_group_general.xml"
+ layout="topleft"
+ left="0"
+ help_topic="group_general_tab"
+ name="group_general_tab_panel"
+ top="0" />
+ </accordion_tab>
+ <accordion_tab
+ expanded="true"
+ layout="topleft"
+ name="group_roles_tab"
+ title="Roles">
+ <panel
+ border="false"
+ class="panel_group_roles"
+ filename="panel_group_roles.xml"
+ layout="topleft"
+ left="0"
+ name="group_roles_tab_panel"
+ top="0" />
+ </accordion_tab>
+ <accordion_tab
+ expanded="false"
+ layout="topleft"
+ name="group_notices_tab"
+ title="Notices">
+ <panel
+ border="false"
+ class="panel_group_notices"
+ filename="panel_group_notices.xml"
+ layout="topleft"
+ left="0"
+ help_topic="group_notices_tab"
+ name="group_notices_tab_panel"
+ top="0" />
+ </accordion_tab>
+ <accordion_tab
+ expanded="false"
+ layout="topleft"
+ name="group_land_tab"
+ title="Land/Assets">
+ <panel
+ border="false"
+ class="panel_group_land_money"
+ filename="panel_group_land_money.xml"
+ layout="topleft"
+ left="0"
+ name="group_land_tab_panel"
+ top="0" />
+ </accordion_tab>
+ </accordion>
+ <panel
+ name="button_row"
+ height="23"
+ follows="bottom|left"
+ top_pad="-1"
+ width="323">
+ <button
+ follows="top|left"
+ height="22"
+ image_overlay="Refresh_Off"
+ layout="topleft"
+ left="10"
+ name="btn_refresh"
+ width="23" />
+ <button
+ height="22"
+ label="Create"
+ label_selected="New group"
+ name="btn_create"
+ left_pad="10"
+ visible="false"
+ width="100" />
+ <!-- <button
+ left_pad="10"
+ height="20"
+ label="Cancel"
+ label_selected="Cancel"
+ name="btn_cancel"
+ visible="false"
+ width="65" />-->
+ <button
+ follows="bottom|right"
+ label="Group Chat"
+ name="btn_chat"
+ right="-184"
+ left_pad="2"
+ height="22"
+ width="85" />
+ <button
+ follows="bottom|right"
+ label="Group Call"
+ name="btn_call"
+ right="-97"
+ left_pad="2"
+ height="22"
+ width="85" />
+ <button
+ height="22"
+ label="Save"
+ label_selected="Save"
+ name="btn_apply"
+ left_pad="10"
+ right="-10"
+ width="85" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_invite.xml b/indra/newview/skins/default/xui/en/panel_group_invite.xml
new file mode 100644
index 0000000000..48083b7677
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_group_invite.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ height="380"
+ label="Invite a Member"
+ layout="topleft"
+ left="0"
+ name="invite_panel"
+ top="380"
+ width="210">
+ <panel.string
+ name="confirm_invite_owner_str">
+ Are you sure you want to invite new owner(s)? This action is permanent!
+ </panel.string>
+ <panel.string
+ name="loading">
+ (loading...)
+ </panel.string>
+ <panel.string
+ name="already_in_group">
+ Some Residents you chose are already in the group, and so were not sent an invitation.
+ </panel.string>
+ <text
+ type="string"
+ length="1"
+ height="54"
+ layout="topleft"
+ left="7"
+ name="help_text"
+ top="28"
+ word_wrap="true"
+ width="200">
+ You can select multiple Residents to invite to your group. Click &apos;Open Resident Chooser&apos; to start.
+ </text>
+ <button
+ height="20"
+ label="Open Resident Chooser"
+ layout="topleft"
+ left_delta="-2"
+ name="add_button"
+ top_delta="44"
+ width="200" />
+ <name_list
+ allow_calling_card_drop="true"
+ column_padding="0"
+ height="174"
+ layout="topleft"
+ left_delta="0"
+ multi_select="true"
+ name="invitee_list"
+ tool_tip="Hold the Ctrl key and click Resident names to multi-select"
+ top_pad="4"
+ width="200" />
+ <button
+ height="20"
+ label="Remove Selected from List"
+ layout="topleft"
+ left_delta="0"
+ name="remove_button"
+ tool_tip="Removes the Residents selected above from the invite list"
+ top_pad="4"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ height="16"
+ layout="topleft"
+ left_delta="4"
+ name="role_text"
+ top_pad="5"
+ word_wrap="true"
+ width="200">
+ Choose what Role to assign them to:
+ </text>
+ <combo_box
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="role_name"
+ tool_tip="Choose from the list of Roles you are allowed to assign members to"
+ top_delta="16"
+ width="196" />
+ <button
+ height="20"
+ label="Send Invitations"
+ layout="topleft"
+ left="4"
+ name="ok_button"
+ top="356"
+ width="130" />
+ <button
+ height="20"
+ label="Cancel"
+ layout="topleft"
+ left_pad="2"
+ name="cancel_button"
+ top_delta="0"
+ width="70" />
+ <string
+ name="GroupInvitation">
+ Group Invitation
+ </string>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_land_money.xml b/indra/newview/skins/default/xui/en/panel_group_land_money.xml
new file mode 100644
index 0000000000..db156f7877
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_group_land_money.xml
@@ -0,0 +1,366 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="false"
+ follows="all"
+ height="420"
+ label="Land &amp; L$"
+ layout="topleft"
+ left="0"
+ name="land_money_tab"
+ top="0"
+ width="310">
+ <panel.string
+ name="help_text">
+ A warning appears until the Total Land in Use is less than or = to the Total Contribution.
+ </panel.string>
+ <panel.string
+ name="cant_view_group_land_text">
+ You don&apos;t have permission to view group owned land
+ </panel.string>
+ <panel.string
+ name="cant_view_group_accounting_text">
+ You don&apos;t have permission to view the group&apos;s accounting information.
+ </panel.string>
+ <panel.string
+ name="loading_txt">
+ Loading...
+ </panel.string>
+ <panel.string
+ name="land_contrib_error">
+ Unable to set your land contribution
+ </panel.string>
+ <!-- <text
+ type="string"
+ follows="left|top"
+ font="SansSerifBig"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="group_land_heading"
+ top_pad="10"
+ width="260">
+ Group Owned Land
+ </text> -->
+ <scroll_list
+ draw_heading="true"
+ follows="top|left|right"
+ heading_height="20"
+ height="130"
+ layout="topleft"
+ left="0"
+ top="0"
+ name="group_parcel_list"
+ width="310">
+ <scroll_list.columns
+ label="Parcel"
+ name="name"
+ width="78" />
+ <scroll_list.columns
+ label="Region"
+ name="location"
+ width="78" />
+ <scroll_list.columns
+ label="Type"
+ name="type"
+ width="70" />
+ <scroll_list.columns
+ label="Area"
+ name="area"
+ width="50" />
+ <scroll_list.columns
+ label=""
+ name="hidden"
+ width="-1" />
+ </scroll_list>
+ <text
+ type="string"
+ follows="left|top"
+ halign="right"
+ height="15"
+ layout="topleft"
+ left="0"
+ name="total_contributed_land_label"
+ width="130">
+ Total contribution:
+ </text>
+ <text
+ text_color="EmphasisColor"
+ type="string"
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left_pad="5"
+ name="total_contributed_land_value"
+ top_delta="0"
+ width="120">
+ [AREA] m²
+ </text>
+ <button
+ follows="top"
+ height="20"
+ label="Map"
+ label_selected="Map"
+ layout="topleft"
+ name="map_button"
+ right="-5"
+ left_pad="0"
+ width="95"
+ enabled="false" />
+ <text
+ type="string"
+ follows="left|top"
+ halign="right"
+ height="15"
+ layout="topleft"
+ left="0"
+ name="total_land_in_use_label"
+ top_pad="0"
+ width="130">
+ Total land in use:
+ </text>
+ <text
+ text_color="EmphasisColor"
+ type="string"
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left_pad="5"
+ name="total_land_in_use_value"
+ top_delta="0"
+ width="120">
+ [AREA] m²
+ </text>
+ <text
+ type="string"
+ follows="left|top"
+ halign="right"
+ height="15"
+ layout="topleft"
+ left="0"
+ name="land_available_label"
+ top_pad="0"
+ width="130">
+ Land available:
+ </text>
+ <text
+ text_color="EmphasisColor"
+ type="string"
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left_pad="5"
+ name="land_available_value"
+ top_delta="0"
+ width="120">
+ [AREA] m²
+ </text>
+ <text
+ type="string"
+ follows="left|top"
+ halign="right"
+ height="15"
+ layout="topleft"
+ left="0"
+ name="your_contribution_label"
+ top_pad="0"
+ width="130">
+ Your contribution:
+ </text>
+ <line_editor
+ follows="left|top"
+ height="19"
+ layout="topleft"
+ left_pad="5"
+ max_length="10"
+ name="your_contribution_line_editor"
+ top_delta="0"
+ width="80" />
+ <text
+ type="string"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="3"
+ name="your_contribution_units"
+ top_delta="2"
+ width="40"
+ >
+ m²
+ </text>
+ <text
+ type="string"
+ follows="left|top"
+ halign="right"
+ height="12"
+ layout="topleft"
+ left="140"
+ name="your_contribution_max_value"
+ top_pad="2"
+ width="95">
+ ([AMOUNT] max)
+ </text>
+ <icon
+ height="18"
+ image_name="BuyArrow_Over"
+ layout="topleft"
+ left="75"
+ name="group_over_limit_icon"
+ top_pad="0"
+ visible="true"
+ width="18" />
+ <text
+ follows="left|top"
+ type="string"
+ word_wrap="true"
+ font="SansSerifSmall"
+ height="20"
+ layout="topleft"
+ left_pad="2"
+ name="group_over_limit_text"
+ text_color="EmphasisColor"
+ top_delta="0"
+ width="213">
+ More land credits are needed to support land in use
+ </text>
+ <text
+ type="string"
+ follows="left|top"
+ font="SansSerifBig"
+ height="16"
+ layout="topleft"
+ left="0"
+ name="group_money_heading"
+ text_color="EmphasisColor"
+ top_pad="-15"
+ width="100">
+ Group L$
+ </text>
+ <tab_container
+ follows="all"
+ height="180"
+ halign="center"
+ layout="topleft"
+ left="0"
+ name="group_money_tab_container"
+ tab_position="top"
+ tab_height="20"
+ top_pad="2"
+ tab_min_width="75"
+ width="310">
+ <panel
+ border="false"
+ follows="all"
+ height="180"
+ label="PLANNING"
+ layout="topleft"
+ left="0"
+ help_topic="group_money_planning_tab"
+ name="group_money_planning_tab"
+ top="5"
+ width="300">
+ <text_editor
+ type="string"
+ follows="all"
+ height="140"
+ layout="topleft"
+ left="0"
+ max_length="4096"
+ name="group_money_planning_text"
+ top="2"
+ width="300"
+ word_wrap="true">
+ Loading...
+ </text_editor>
+ </panel>
+ <panel
+ border="false"
+ follows="all"
+ height="180"
+ label="DETAILS"
+ layout="topleft"
+ left="0"
+ help_topic="group_money_details_tab"
+ name="group_money_details_tab"
+ top="0"
+ width="300">
+ <text_editor
+ type="string"
+ follows="all"
+ height="140"
+ layout="topleft"
+ left="0"
+ max_length="4096"
+ name="group_money_details_text"
+ top="2"
+ width="300"
+ word_wrap="true">
+ Loading...
+ </text_editor>
+
+ <button
+ height="20"
+ image_overlay="Arrow_Left_Off"
+ layout="topleft"
+ left="5"
+ name="earlier_details_button"
+ tool_tip="Go back in time"
+ top_pad="10"
+ width="25" />
+ <button
+ height="20"
+ image_overlay="Arrow_Right_Off"
+ layout="topleft"
+ left_pad="5"
+ name="later_details_button"
+ tool_tip="Go forward in time"
+ top_delta="0"
+ width="25" />
+
+
+ </panel>
+ <panel
+ border="false"
+ follows="all"
+ height="180"
+ label="SALES"
+ layout="topleft"
+ left_delta="0"
+ help_topic="group_money_sales_tab"
+ mouse_opaque="false"
+ name="group_money_sales_tab"
+ top="0"
+ width="300">
+ <text_editor
+ type="string"
+ follows="all"
+ height="130"
+ layout="topleft"
+ left="0"
+ max_length="4096"
+ name="group_money_sales_text"
+ top="2"
+ width="300"
+ word_wrap="true">
+ Loading...
+ </text_editor>
+ <button
+ height="20"
+ image_overlay="Arrow_Left_Off"
+ layout="topleft"
+ left="5"
+ name="earlier_sales_button"
+ tool_tip="Go back in time"
+ top_pad="10"
+ width="25" />
+ <button
+ height="20"
+ image_overlay="Arrow_Right_Off"
+ layout="topleft"
+ left_pad="5"
+ name="later_sales_button"
+ tool_tip="Go forward in time"
+ top_delta="0"
+ width="25" />
+ </panel>
+ </tab_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_list_item.xml b/indra/newview/skins/default/xui/en/panel_group_list_item.xml
new file mode 100644
index 0000000000..c243d08b97
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_group_list_item.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="top|right|left"
+ height="24"
+ layout="topleft"
+ left="0"
+ name="group_list_item"
+ top="0"
+ width="320">
+ <icon
+ follows="top|right|left"
+ height="24"
+ image_name="ListItem_Over"
+ layout="topleft"
+ left="0"
+ name="hovered_icon"
+ top="0"
+ visible="false"
+ width="320" />
+ <icon
+ height="24"
+ follows="top|right|left"
+ image_name="ListItem_Select"
+ layout="topleft"
+ left="0"
+ name="selected_icon"
+ top="0"
+ visible="false"
+ width="320" />
+ <icon
+ height="20"
+ image_name="Generic_Group"
+ name="group_icon"
+ mouse_opaque="true"
+ left="5"
+ top="2"
+ width="20" />
+ <text
+ follows="left|right"
+ font="SansSerifSmall"
+ height="15"
+ layout="topleft"
+ left_pad="5"
+ name="group_name"
+ top="6"
+ use_ellipses="true"
+ value="Unknown"
+ width="242" />
+ <button
+ follows="right"
+ height="16"
+ image_pressed="Info_Press"
+ image_unselected="Info_Over"
+ left_pad="3"
+ right="-31"
+ name="info_btn"
+ top_delta="-2"
+ width="16" />
+ <!--*TODO: Should only appear on rollover-->
+ <button
+ follows="right"
+ height="20"
+ image_overlay="ForwardArrow_Off"
+ layout="topleft"
+ left_pad="5"
+ right="-3"
+ name="profile_btn"
+ tool_tip="View profile"
+ top_delta="-2"
+ width="20" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_notices.xml b/indra/newview/skins/default/xui/en/panel_group_notices.xml
new file mode 100644
index 0000000000..0d9c2c2162
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_group_notices.xml
@@ -0,0 +1,340 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="all"
+ height="463"
+ label="Notices"
+ layout="topleft"
+ left="0"
+ name="notices_tab"
+ top="0"
+ width="310">
+ <panel.string
+ name="help_text">
+ Notices let you send a message and an optionally attached item.
+Notices only go to group members in Roles with the ability to receive Notices.
+You can turn off Notices on the General tab.
+ </panel.string>
+ <panel.string
+ name="no_notices_text">
+ There are no past notices
+ </panel.string>
+ <text
+ follows="left|top"
+ type="string"
+ word_wrap="true"
+ height="24"
+ halign="right"
+ layout="topleft"
+ left="5"
+ name="lbl2"
+ top="5"
+ width="300">
+ Notices are kept for 14 days.
+Maximum 200 per group daily
+ </text>
+ <scroll_list
+ follows="left|top"
+ column_padding="0"
+ draw_heading="true"
+ heading_height="16"
+ height="125"
+ layout="topleft"
+ left="2"
+ name="notice_list"
+ top_pad="0"
+ width="300">
+ <scroll_list.columns
+ label=""
+ name="icon"
+ width="20" />
+ <scroll_list.columns
+ label="Subject"
+ name="subject"
+ width="110" />
+ <scroll_list.columns
+ label="From"
+ name="from"
+ width="100" />
+ <scroll_list.columns
+ label="Date"
+ name="date"
+ width="60" />
+ <scroll_list.columns
+ name="sort"
+ width="-1" />
+ </scroll_list>
+ <text
+ follows="left|top"
+ type="string"
+ layout="topleft"
+ name="notice_list_none_found"
+ visible="false">
+ None found
+ </text>
+ <button
+ follows="bottom|left"
+ height="18"
+ image_selected="AddItem_Press"
+ image_unselected="AddItem_Off"
+ image_disabled="AddItem_Disabled"
+ layout="topleft"
+ left="5"
+ name="create_new_notice"
+ tool_tip="Create a new notice"
+ top_delta="-3"
+ width="18" />
+ <button
+ follows="top|left"
+ height="22"
+ image_overlay="Refresh_Off"
+ layout="topleft"
+ name="refresh_notices"
+ right="-5"
+ tool_tip="Refresh list of notices"
+ top_delta="0"
+ width="23" />
+ <panel
+ follows="left|top"
+ height="280"
+ label="Create New Notice"
+ layout="topleft"
+ left="0"
+ top_pad="0"
+ visible="true"
+ name="panel_create_new_notice"
+ width="300">
+ <text
+ follows="left|top"
+ type="string"
+ font="SansSerifBig"
+ height="16"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="lbl"
+ text_color="EmphasisColor"
+ top="0"
+ width="200">
+ Create a Notice
+ </text>
+ <text
+ follows="left|top"
+ type="string"
+ halign="left"
+ height="16"
+ layout="topleft"
+ name="lbl3"
+ top_pad="10"
+ width="60">
+ Subject:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ height="16"
+ layout="topleft"
+ left_pad="3"
+ max_length="63"
+ name="create_subject"
+ prevalidate_callback="ascii"
+ width="220" />
+ <text
+ follows="left|top"
+ type="string"
+ halign="left"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="lbl4"
+ top_pad="5"
+ width="60">
+ Message:
+ </text>
+ <text_editor
+ height="90"
+ layout="topleft"
+ left_pad="3"
+ max_length="511"
+ name="create_message"
+ top_delta="0"
+ width="220"
+ word_wrap="true" />
+ <text
+ follows="left|top"
+ type="string"
+ halign="left"
+ height="14"
+ layout="topleft"
+ left="10"
+ name="lbl5"
+ width="200">
+ Attach:
+ </text>
+ <line_editor
+ enabled="false"
+ height="19"
+ layout="topleft"
+ max_length="90"
+ mouse_opaque="false"
+ name="create_inventory_name"
+ top_pad="2"
+ width="285" />
+ <text
+ text_color="EmphasisColor"
+ follows="left|top"
+ type="string"
+ halign="right"
+ height="34"
+ layout="topleft"
+ left="10"
+ name="string"
+ top_pad="15"
+ word_wrap="true"
+ width="150">
+ Drag and drop item here to attach it:
+ </text>
+ <icon
+ height="72"
+ image_name="DropTarget"
+ layout="topleft"
+ left_pad="10"
+ mouse_opaque="true"
+ name="drop_icon"
+ top_delta="-10"
+ width="72" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Remove"
+ layout="topleft"
+ left="70"
+ name="remove_attachment"
+ top_delta="45"
+ width="90" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Send"
+ label_selected="Send"
+ layout="topleft"
+ right="-10"
+ top_pad="10"
+ name="send_notice"
+ width="100" />
+ <group_drop_target
+ height="95"
+ top="160"
+ left="10"
+ layout="topleft"
+ name="drop_target"
+ tool_tip="Drag an inventory item onto this target box to send it with this notice. You must have permission to copy and transfer the item in order to attach it."
+ width="280" />
+ </panel>
+ <panel
+ follows="left|top"
+ height="280"
+ label="View Past Notice"
+ layout="topleft"
+ left="0"
+ visible="false"
+ name="panel_view_past_notice"
+ top="180"
+ width="300">
+ <text
+ type="string"
+ font="SansSerifBig"
+ height="16"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="lbl"
+ text_color="EmphasisColor"
+ top_pad="0"
+ width="265">
+ Archived Notice
+ </text>
+ <text
+ type="string"
+ height="16"
+ word_wrap="true"
+ layout="topleft"
+ left_delta="0"
+ name="lbl2"
+ top_pad="2"
+ width="265">
+ To send a new notice, click the + button
+ </text>
+ <text
+ type="string"
+ halign="left"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="lbl3"
+ top_pad="15"
+ visible="false"
+ width="60">
+ Subject:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ enabled="false"
+ height="16"
+ layout="topleft"
+ left_pad="3"
+ max_length="63"
+ name="view_subject"
+ top_delta="-1"
+ visible="false"
+ width="200" />
+ <text
+ type="string"
+ halign="left"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="lbl4"
+ top_pad="10"
+ visible="false"
+ width="60">
+ Message:
+ </text>
+ <text_editor
+ enabled="false"
+ height="160"
+ layout="topleft"
+ left="10"
+ max_length="511"
+ name="view_message"
+ top_delta="-35"
+ width="285"
+ word_wrap="true" />
+ <line_editor
+ enabled="false"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ max_length="63"
+ mouse_opaque="false"
+ name="view_inventory_name"
+ top_pad="8"
+ width="285" />
+ <icon
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="view_inv_icon"
+ top_delta="0"
+ width="16" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Open attachment"
+ layout="topleft"
+ right="-10"
+ name="open_attachment"
+ top_pad="5"
+ width="135" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_notify.xml b/indra/newview/skins/default/xui/en/panel_group_notify.xml
new file mode 100644
index 0000000000..65b2e81d50
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_group_notify.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ height="90"
+ label="instant_message"
+ layout="topleft"
+ left="0"
+ name="panel_group_notify"
+ top="0"
+ width="305">
+ <string
+ name="message_max_lines_count"
+ value="7" />
+ <string
+ name="subject_font"
+ value="SANSSERIF_BIG" />
+ <string
+ name="date_font"
+ value="SANSSERIF" />
+ <panel
+ background_visible="true"
+ follows="top"
+ height="30"
+ label="header"
+ layout="topleft"
+ left="0"
+ name="header"
+ top="0"
+ width="305">
+ <icon
+ follows="all"
+ height="20"
+ layout="topleft"
+ left="5"
+ mouse_opaque="true"
+ name="group_icon"
+ top="5"
+ width="20" />
+ <text
+ follows="all"
+ font="SansSerifBig"
+ height="20"
+ layout="topleft"
+ left_pad="10"
+ name="title"
+ text_color="GroupNotifyTextColor"
+ top="5"
+ use_ellipses="true"
+ value="Sender Name / Group Name"
+ width="230" />
+ </panel>
+ <text_editor
+ allow_html="true"
+ enabled="true"
+ follows="all"
+ height="0"
+ layout="topleft"
+ left="25"
+ max_length="2147483647"
+ name="message"
+ parse_highlights="true"
+ read_only="true"
+ text_color="GroupNotifyTextColor"
+ top="40"
+ type="string"
+ use_ellipses="true"
+ value="message"
+ width="270"
+ word_wrap="true" >
+ </text_editor>
+ <icon
+ bottom="60"
+ follows="left|bottom|right"
+ height="15"
+ layout="topleft"
+ left="25"
+ mouse_opaque="true"
+ name="attachment_icon"
+ width="15" />
+ <text
+ bottom="60"
+ follows="left|bottom|right"
+ font="SansSerif"
+ height="15"
+ layout="topleft"
+ left="45"
+ name="attachment"
+ text_color="GroupNotifyTextColor"
+ value="Attachment"
+ use_ellipses="true"
+ width="250" />
+ <button
+ bottom="85"
+ follows="bottom"
+ height="20"
+ label="OK"
+ layout="topleft"
+ right="-10"
+ name="btn_ok"
+ width="70" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_roles.xml b/indra/newview/skins/default/xui/en/panel_group_roles.xml
new file mode 100644
index 0000000000..618d2f3b8e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_group_roles.xml
@@ -0,0 +1,540 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="all"
+ height="552"
+ label="Members &amp; Roles"
+ layout="topleft"
+ left="0"
+ top="0"
+ name="roles_tab"
+ width="310">
+ <panel.string
+ name="default_needs_apply_text">
+ There are unsaved changes to the current tab
+ </panel.string>
+ <panel.string
+ name="want_apply_text">
+ Do you want to save your changes?
+ </panel.string>
+ <panel.string
+ name="help_text" />
+ <tab_container
+ border="false"
+ follows="left|top"
+ height="552"
+ halign="center"
+ layout="topleft"
+ left="0"
+ name="roles_tab_container"
+ tab_position="top"
+ tab_height="20"
+ tab_min_width="75"
+ top="0"
+ width="310">
+ <panel
+ border="false"
+ follows="all"
+ height="303"
+ label="MEMBERS"
+ layout="topleft"
+ left="0"
+ help_topic="roles_members_tab"
+ name="members_sub_tab"
+ tool_tip="Members"
+ class="panel_group_members_subtab"
+ width="310">
+ <panel.string
+ name="help_text">
+ You can add or remove Roles assigned to Members.
+Select multiple Members by holding the Ctrl key and
+clicking on their names.
+ </panel.string>
+ <panel.string
+ name="power_folder_icon">
+ Inv_FolderClosed
+ </panel.string>
+ <panel.string
+ name="power_all_have_icon">
+ Checkbox_On
+ </panel.string>
+ <panel.string
+ name="power_partial_icon">
+ Checkbox_Off
+ </panel.string>
+ <filter_editor
+ layout="topleft"
+ top="5"
+ left="5"
+ width="280"
+ height="20"
+ follows="top"
+ max_length="250"
+ label="Filter Members"
+ name="filter_input" />
+ <name_list
+ column_padding="0"
+ draw_heading="true"
+ heading_height="20"
+ height="240"
+ follows="left|top"
+ layout="topleft"
+ left="0"
+ multi_select="true"
+ name="member_list"
+ top_pad="2"
+ width="300">
+ <name_list.columns
+ label="Member"
+ name="name"
+ relative_width="0.44" />
+ <name_list.columns
+ label="Donation"
+ name="donated"
+ relative_width="0.25" />
+ <name_list.columns
+ label="Status"
+ name="online"
+ relative_width="0.15" />
+ </name_list>
+ <button
+ height="20"
+ follows="bottom|left"
+ label="Invite"
+ left="5"
+ name="member_invite"
+ width="100" />
+ <button
+ height="20"
+ label="Eject"
+ left_pad="5"
+ right="-5"
+ name="member_eject"
+ width="100" />
+ </panel>
+ <panel
+ border="false"
+ height="230"
+ label="ROLES"
+ layout="topleft"
+ left="0"
+ help_topic="roles_roles_tab"
+ name="roles_sub_tab"
+ class="panel_group_roles_subtab"
+ width="310">
+ <!-- <button
+ enabled="false"
+ height="20"
+ label="Show All"
+ layout="topleft"
+ top="-65"
+ right="-5"
+ name="show_all_button"
+ width="100" />-->
+ <panel.string
+ name="help_text">
+ Roles have a title and an allowed list of Abilities
+that Members can perform. Members can belong to
+one or more Roles. A group can have up to 10 Roles,
+including the Everyone and Owner Roles.
+ </panel.string>
+ <panel.string
+ name="cant_delete_role">
+ The &apos;Everyone&apos; and &apos;Owners&apos; Roles are special and can't be deleted.
+ </panel.string>
+ <panel.string
+ name="power_folder_icon">
+ Inv_FolderClosed
+ </panel.string>
+ <panel.string
+ name="power_all_have_icon">
+ Checkbox_On
+ </panel.string>
+ <panel.string
+ name="power_partial_icon">
+ Checkbox_Off
+ </panel.string>
+ <filter_editor
+ layout="topleft"
+ top="5"
+ left="5"
+ width="280"
+ height="20"
+ follows="left|top|right"
+ max_length="250"
+ label="Filter Roles"
+ name="filter_input" />
+ <scroll_list
+ column_padding="0"
+ draw_heading="true"
+ draw_stripes="false"
+ follows="left|top"
+ heading_height="20"
+ height="170"
+ layout="topleft"
+ search_column="1"
+ left="0"
+ name="role_list"
+ top_pad="2"
+ width="310">
+ <scroll_list.columns
+ label="Role"
+ name="name"
+ relative_width="0.45" />
+ <scroll_list.columns
+ label="Title"
+ name="title"
+ relative_width="0.45" />
+ <scroll_list.columns
+ label="#"
+ name="members"
+ relative_width="0.15" />
+ </scroll_list>
+ <button
+ follows="bottom|left"
+ height="20"
+ label="New Role"
+ layout="topleft"
+ left="5"
+ name="role_create"
+ width="100" />
+ <button
+ height="20"
+ label="Delete Role"
+ layout="topleft"
+ left_pad="5"
+ right="-5"
+ name="role_delete"
+ width="100" />
+ </panel>
+ <panel
+ border="false"
+ height="220"
+ label="ABILITIES"
+ layout="topleft"
+ left="0"
+ help_topic="roles_actions_tab"
+ name="actions_sub_tab"
+ class="panel_group_actions_subtab"
+ tool_tip="You can view an Ability&apos;s Description and which Roles and Members can execute the Ability."
+ width="310">
+ <panel.string
+ name="help_text">
+ Abilities allow Members in Roles to do specific
+things in this group. There&apos;s a broad variety of Abilities.
+ </panel.string>
+ <panel.string
+ name="power_folder_icon">
+ Inv_FolderClosed
+ </panel.string>
+ <panel.string
+ name="power_all_have_icon">
+ Checkbox_On
+ </panel.string>
+ <panel.string
+ name="power_partial_icon">
+ Checkbox_Off
+ </panel.string>
+ <filter_editor
+ layout="topleft"
+ top="5"
+ left="5"
+ width="280"
+ height="20"
+ follows="left|top|right"
+ max_length="250"
+ label="Filter Abilities"
+ name="filter_input" />
+
+ <scroll_list
+ column_padding="0"
+ draw_stripes="true"
+ height="200"
+ follows="left|top"
+ layout="topleft"
+ left="0"
+ name="action_list"
+ search_column="2"
+ tool_tip="Select an Ability to view more details"
+ top_pad="5"
+ width="300">
+ <scroll_list.columns
+ label=""
+ name="icon"
+ width="2" />
+ <scroll_list.columns
+ label=""
+ name="checkbox"
+ width="20" />
+ <scroll_list.columns
+ label=""
+ name="action"
+ width="270" />
+ </scroll_list>
+ </panel>
+ </tab_container>
+ <panel
+ height="252"
+ layout="topleft"
+ follows="left|top"
+ left="0"
+ mouse_opaque="false"
+ name="members_footer"
+ top="300"
+ visible="false"
+ width="310">
+ <text
+ type="string"
+ height="14"
+ layout="topleft"
+ follows="left|top"
+ left="0"
+ name="static"
+ top_pad="5"
+ width="300">
+ Assigned Roles
+ </text>
+ <scroll_list
+ draw_stripes="true"
+ follows="left|top"
+ height="90"
+ layout="topleft"
+ left="0"
+ name="member_assigned_roles"
+ top_pad="0"
+ width="300">
+ <scroll_list.columns
+ label=""
+ name="checkbox"
+ width="20" />
+ <scroll_list.columns
+ label=""
+ name="role"
+ width="270" />
+ </scroll_list>
+ <text
+ type="string"
+ height="14"
+ layout="topleft"
+ follows="left|top"
+ left="0"
+ name="static2"
+ top_pad="5"
+ width="285">
+ Allowed Abilities
+ </text>
+ <scroll_list
+ draw_stripes="true"
+ height="90"
+ layout="topleft"
+ left="0"
+ name="member_allowed_actions"
+ search_column="2"
+ tool_tip="For details of each allowed ability see the abilities tab"
+ top_pad="0"
+ width="300">
+ <scroll_list.columns
+ label=""
+ name="icon"
+ width="2" />
+ <scroll_list.columns
+ label=""
+ name="checkbox"
+ width="20" />
+ <scroll_list.columns
+ label=""
+ name="action"
+ width="270" />
+ </scroll_list>
+ </panel>
+ <panel
+ height="297"
+ layout="topleft"
+ left="0"
+ name="roles_footer"
+ top_delta="0"
+ top="220"
+ visible="false"
+ width="310">
+ <text
+ type="string"
+ height="14"
+ layout="topleft"
+ left="0"
+ name="static"
+ top="0"
+ width="300">
+ Role Name
+ </text>
+ <line_editor
+ type="string"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="0"
+ max_length="295"
+ name="role_name"
+ top_pad="0"
+ width="300">
+ </line_editor>
+ <text
+ type="string"
+ height="14"
+ layout="topleft"
+ name="static3"
+ top_pad="5"
+ width="300">
+ Role Title
+ </text>
+ <line_editor
+ type="string"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ max_length="295"
+ name="role_title"
+ top_pad="0"
+ width="300">
+ </line_editor>
+ <text
+ type="string"
+ height="14"
+ layout="topleft"
+ left="0"
+ name="static2"
+ top_pad="5"
+ width="200">
+ Description
+ </text>
+ <text_editor
+ type="string"
+ halign="left"
+ height="35"
+ layout="topleft"
+ left="0"
+ max_length="295"
+ name="role_description"
+ top_pad="0"
+ width="300"
+ word_wrap="true">
+ </text_editor>
+ <text
+ type="string"
+ height="14"
+ layout="topleft"
+ follows="left|top"
+ left="0"
+ name="static4"
+ top_pad="5"
+ width="300">
+ Assigned Members
+ </text>
+ <name_list
+ draw_stripes="true"
+ height="60"
+ layout="topleft"
+ left="0"
+ name="role_assigned_members"
+ top_pad="0"
+ width="300" />
+ <check_box
+ height="15"
+ label="Reveal members"
+ layout="topleft"
+ name="role_visible_in_list"
+ tool_tip="Sets whether members of this role are visible in the General tab to people outside of the group."
+ top_pad="4"
+ width="300" />
+ <text
+ type="string"
+ height="13"
+ layout="topleft"
+ follows="left|top"
+ left="0"
+ name="static5"
+ top_pad="5"
+ width="300">
+ Allowed Abilities
+ </text>
+ <scroll_list
+ draw_stripes="true"
+ height="60"
+ layout="topleft"
+ left="0"
+ name="role_allowed_actions"
+ search_column="2"
+ tool_tip="For details of each allowed ability see the abilities tab"
+ top_pad="0"
+ width="300">
+ <scroll_list.columns
+ label=""
+ name="icon"
+ width="2" />
+ <scroll_list.columns
+ label=""
+ name="checkbox"
+ width="20" />
+ <scroll_list.columns
+ label=""
+ name="action"
+ width="270" />
+ </scroll_list>
+ </panel>
+ <panel
+ height="303"
+ layout="topleft"
+ left="0"
+ name="actions_footer"
+ top_delta="0"
+ top="255"
+ visible="false"
+ width="310">
+ <text_editor
+ bg_readonly_color="Transparent"
+ text_readonly_color="EmphasisColor"
+ font="SansSerifSmall"
+ type="string"
+ enabled="false"
+ halign="left"
+ height="90"
+ layout="topleft"
+ max_length="512"
+ name="action_description"
+ top_pad="0"
+ width="295"
+ word_wrap="true">
+ This Ability is &apos;Eject Members from this Group&apos;. Only an Owner can eject another Owner.
+ </text_editor>
+ <text
+ type="string"
+ height="14"
+ layout="topleft"
+ left="5"
+ name="static2"
+ top_pad="5"
+ width="300">
+ Roles with this ability
+ </text>
+ <scroll_list
+ height="65"
+ layout="topleft"
+ left="5"
+ name="action_roles"
+ top_pad="0"
+ width="300" />
+ <text
+ type="string"
+ height="14"
+ layout="topleft"
+ name="static3"
+ top_pad="5"
+ width="300">
+ Members with this ability
+ </text>
+ <name_list
+ height="100"
+ layout="topleft"
+ name="action_members"
+ top_pad="0"
+ width="300" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_groups.xml b/indra/newview/skins/default/xui/en/panel_groups.xml
new file mode 100644
index 0000000000..bba399481b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_groups.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="all"
+ height="347"
+ layout="topleft"
+ left="280"
+ name="groups"
+ top="24"
+ width="350">
+ <scroll_list
+ bottom="302"
+ follows="left|top|right|bottom"
+ layout="topleft"
+ left="10"
+ name="group list"
+ top="10"
+ width="240">
+ <scroll_list.columns
+ label=""
+ name="name"
+ width="248" />
+ </scroll_list>
+ <text
+ type="string"
+ length="1"
+ follows="left|bottom"
+ height="16"
+ layout="topleft"
+ left_delta="2"
+ mouse_opaque="false"
+ name="groupdesc"
+ top_pad="7"
+ width="248">
+ Your currently active group is displayed in bold.
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|bottom"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="groupcount"
+ top_pad="1"
+ width="248">
+ You belong to [COUNT] groups (of [MAX] maximum).
+ </text>
+ <locate
+ height="0"
+ layout="topleft"
+ left="-90"
+ top="7"
+ width="1" />
+ <button
+ follows="top|right"
+ height="22"
+ label="IM/Call"
+ layout="topleft"
+ left_delta="0"
+ name="IM"
+ tool_tip="Open Instant Message session"
+ top_pad="3"
+ width="80" />
+ <button
+ follows="top|right"
+ height="22"
+ label="Info"
+ layout="topleft"
+ left_delta="0"
+ name="Info"
+ top_pad="3"
+ width="80" />
+ <button
+ follows="top|right"
+ height="22"
+ label="Activate"
+ layout="topleft"
+ left_delta="0"
+ name="Activate"
+ top_pad="3"
+ width="80" />
+ <button
+ follows="top|right"
+ height="22"
+ label="Leave"
+ layout="topleft"
+ left_delta="0"
+ name="Leave"
+ top_pad="3"
+ width="80" />
+ <button
+ follows="top|right"
+ height="22"
+ label="Create..."
+ layout="topleft"
+ left_delta="0"
+ name="Create"
+ top_pad="13"
+ width="80" />
+ <button
+ follows="top|right"
+ height="22"
+ label="Search..."
+ layout="topleft"
+ left_delta="0"
+ name="Search..."
+ top_pad="3"
+ width="80" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_hud.xml b/indra/newview/skins/default/xui/en/panel_hud.xml
new file mode 100644
index 0000000000..3e9614a9b7
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_hud.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="left|right|top|bottom"
+ height="728"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="hud"
+ top="778"
+ width="1024" />
diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
new file mode 100644
index 0000000000..2e3d5a7320
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="false"
+ height="300"
+ name="panel_im_control_panel"
+ width="110">
+ <avatar_icon
+ follows="left|top"
+ height="105"
+ left_delta="5"
+ name="avatar_icon"
+ top="-5"
+ width="105"/>
+ <text
+ follows="top|left|right"
+ font="SansSerifLarge"
+ height="19"
+ layout="topleft"
+ name="avatar_name"
+ use_ellipses="true"
+ value="Unknown"
+ width="110" />
+ <layout_stack
+ mouse_opaque="false"
+ border_size="0"
+ clip="false"
+ follows="all"
+ height="168"
+ layout="topleft"
+ left="5"
+ name="button_stack"
+ orientation="vertical"
+ top_pad="0"
+ width="105">
+ <layout_panel
+ mouse_opaque="false"
+ auto_resize="true"
+ follows="top|left"
+ height="0"
+ layout="topleft"
+ left="2"
+ min_height="0"
+ width="100"
+ top="0"
+ name="spacer"
+ user_resize="false" />
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="20"
+ layout="topleft"
+ min_height="20"
+ width="100"
+ name="view_profile_btn_panel"
+ user_resize="false">
+ <button
+ follows="left|top|right"
+ height="20"
+ label="Profile"
+ name="view_profile_btn"
+ top="0"
+ width="100" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="25"
+ layout="topleft"
+ min_height="25"
+ width="100"
+ name="add_friend_btn_panel"
+ user_resize="false">
+ <button
+ follows="left|top|right"
+ height="20"
+ label="Add Friend"
+ name="add_friend_btn"
+ top="5"
+ width="100" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="25"
+ layout="topleft"
+ min_height="25"
+ width="100"
+ name="teleport_btn_panel"
+ user_resize="false">
+ <button
+ auto_resize="false"
+ follows="left|top|right"
+ height="20"
+ label="Teleport"
+ name="teleport_btn"
+ width="100" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="25"
+ layout="topleft"
+ min_height="25"
+ width="100"
+ name="share_btn_panel"
+ user_resize="false">
+ <button
+ auto_resize="true"
+ follows="left|top|right"
+ height="20"
+ label="Share"
+ name="share_btn"
+ width="100" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="25"
+ layout="topleft"
+ min_height="25"
+ width="100"
+ name="call_btn_panel"
+ user_resize="false">
+ <button
+ follows="left|top|right"
+ height="20"
+ label="Call"
+ name="call_btn"
+ width="100" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="25"
+ layout="topleft"
+ min_height="25"
+ width="100"
+ name="end_call_btn_panel"
+ user_resize="false"
+ visible="false">
+ <button
+ follows="left|top|right"
+ height="20"
+ label="Leave Call"
+ name="end_call_btn"
+ width="100" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="25"
+ layout="topleft"
+ min_height="25"
+ width="100"
+ name="voice_ctrls_btn_panel"
+ user_resize="false"
+ visible="false">
+ <button
+ follows="left|top|right"
+ height="20"
+ label="Voice Controls"
+ name="voice_ctrls_btn"
+ width="100" />
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_instant_message.xml b/indra/newview/skins/default/xui/en/panel_instant_message.xml
new file mode 100644
index 0000000000..7204e57479
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_instant_message.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ height="152"
+ label="im_panel"
+ layout="topleft"
+ left="0"
+ name="im_panel"
+ top="0"
+ width="305">
+ <string
+ name="message_max_lines_count">
+ 6
+ </string>
+ <panel
+ background_visible="true"
+ bevel_style="in"
+ bg_alpha_color="black"
+ follows="top"
+ height="24"
+ label="im_header"
+ layout="topleft"
+ left="5"
+ mouse_opaque="false"
+ name="im_header"
+ top="5"
+ width="295">
+ <avatar_icon
+ follows="right"
+ height="18"
+ image_name="Generic_Person"
+ layout="topleft"
+ left="3"
+ mouse_opaque="false"
+ name="avatar_icon"
+ top="3"
+ width="18" />
+ <!--<icon
+ follows="right"
+ height="20"
+ image_name=""
+ layout="topleft"
+ left="3"
+ mouse_opaque="true"
+ name="sys_msg_icon"
+ top="0"
+ width="20" />-->
+ <text
+ follows="left|right"
+ font.style="BOLD"
+ height="12"
+ layout="topleft"
+ left_pad="5"
+ name="user_name"
+ text_color="white"
+ top="8"
+ use_ellipses="true"
+ value="Erica Vader"
+ width="212" />
+ <!-- TIME STAMP -->
+ <text
+ font="SansSerifSmall"
+ follows="right"
+ height="13"
+ layout="topleft"
+ halign="right"
+ right="-5"
+ name="time_box"
+ top="8"
+ value="23:30"
+ width="50" />
+ </panel>
+ <text
+ font="SansSerifSmall"
+ follows="all"
+ height="97"
+ layout="topleft"
+ left="10"
+ name="message"
+ text_color="white"
+ top="33"
+ use_ellipses="true"
+ value=""
+ width="285"
+ word_wrap="true"
+ max_length="350" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml
new file mode 100644
index 0000000000..67a4edbf32
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml
@@ -0,0 +1,294 @@
+<?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="landmark_info"
+ top="20"
+ width="330">
+ <string
+ name="title_create_landmark"
+ value="Create Landmark" />
+ <string
+ name="title_edit_landmark"
+ value="Edit Landmark" />
+ <string
+ name="title_landmark"
+ value="Landmark" />
+ <string
+ name="not_available"
+ value="(N\A)" />
+ <string
+ name="unknown"
+ value="(unknown)" />
+ <string
+ name="public"
+ value="(public)" />
+ <string
+ name="server_update_text">
+ Place information not available without server update.
+ </string>
+ <string
+ name="server_error_text">
+ Information about this location is unavailable at this time, please try again later.
+ </string>
+ <string
+ name="server_forbidden_text">
+ Information about this location is unavailable due to access restrictions. Please check your permissions with the parcel owner.
+ </string>
+ <string
+ name="acquired_date">
+ [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+ </string>
+ <!-- Texture names for rating icons -->
+ <string
+ name="icon_PG"
+ value="Parcel_PG_Dark" />
+ <string
+ name="icon_M"
+ value="Parcel_M_Dark" />
+ <string
+ name="icon_R"
+ value="Parcel_R_Dark" />
+ <button
+ follows="top|right"
+ height="23"
+ image_overlay="BackArrow_Off"
+ layout="topleft"
+ left="10"
+ name="back_btn"
+ tool_tip="Back"
+ tab_stop="false"
+ top="0"
+ width="23" />
+ <text
+ follows="top|left|right"
+ font="SansSerifHugeBold"
+ height="26"
+ layout="topleft"
+ left_pad="10"
+ name="title"
+ text_color="white"
+ top="0"
+ use_ellipses="true"
+ value="Place Profile"
+ width="275" />
+ <scroll_container
+ color="DkGray2"
+ follows="all"
+ height="533"
+ layout="topleft"
+ left="10"
+ name="place_scroll"
+ opaque="true"
+ top_pad="5"
+ width="313">
+ <panel
+ bg_alpha_color="DkGray2"
+ follows="left|top|right"
+ height="610"
+ layout="topleft"
+ left="0"
+ min_height="300"
+ name="scrolling_panel"
+ top="0"
+ width="313">
+ <texture_picker
+ enabled="false"
+ follows="top|left"
+ height="190"
+ layout="topleft"
+ left="10"
+ name="logo"
+ top="10"
+ width="290" />
+ <text
+ follows="left|top|right"
+ font="SansSerifLarge"
+ height="14"
+ layout="topleft"
+ left="10"
+ name="region_title"
+ text_color="white"
+ top_pad="5"
+ use_ellipses="true"
+ value="SampleRegion"
+ width="290" />
+ <text
+ follows="left|top|right"
+ height="14"
+ layout="topleft"
+ left="10"
+ name="parcel_title"
+ top_pad="4"
+ use_ellipses="true"
+ value="SampleParcel, Name Long (145, 228, 26)"
+ width="285" />
+ <expandable_text
+ follows="left|top|right"
+ height="50"
+ layout="topleft"
+ left="5"
+ name="description"
+ top_pad="10"
+ value="Du waltz die spritz"
+ width="300" />
+ <icon
+ follows="top|left"
+ height="16"
+ image_name="unknown"
+ layout="topleft"
+ left="10"
+ name="maturity_icon"
+ top_pad="10"
+ width="18" />
+ <text
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_pad="8"
+ name="maturity_value"
+ top_delta="0"
+ value="unknown"
+ width="268" />
+ <panel
+ follows="left|top|right"
+ height="55"
+ layout="topleft"
+ left="10"
+ name="landmark_info_panel"
+ top_pad="10"
+ width="290">
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="0"
+ name="owner_label"
+ top_pad="10"
+ value="Owner:"
+ width="90" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left="70"
+ name="owner"
+ top_delta="0"
+ width="200" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="0"
+ name="creator_label"
+ value="Creator:"
+ width="90" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left="70"
+ name="creator"
+ top_delta="0"
+ width="200" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="0"
+ name="created_label"
+ value="Created:"
+ width="50" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left="70"
+ name="created"
+ top_delta="0"
+ width="200" />
+ </panel>
+ <panel
+ follows="left|top|right"
+ height="210"
+ layout="topleft"
+ left="10"
+ name="landmark_edit_panel"
+ width="290">
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="0"
+ name="title_label"
+ top_pad="10"
+ value="Title:"
+ width="290" />
+ <text
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="0"
+ name="title_value"
+ text_color="white"
+ top_pad="5"
+ use_ellipses="true"
+ width="290" />
+ <line_editor
+ follows="left|top|right"
+ height="22"
+ layout="topleft"
+ left="0"
+ max_length="63"
+ name="title_editor"
+ prevalidate_callback="ascii"
+ text_readonly_color="white"
+ top_delta="0"
+ width="290" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="0"
+ name="notes_label"
+ top_pad="10"
+ value="My notes:"
+ width="290" />
+ <text_editor
+ bg_readonly_color="DkGray2"
+ follows="all"
+ height="70"
+ layout="topleft"
+ left="0"
+ max_length="127"
+ name="notes_editor"
+ read_only="true"
+ text_readonly_color="white"
+ top_pad="5"
+ width="290"
+ wrap="true" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="0"
+ name="folder_label"
+ top_pad="15"
+ value="Landmark location:"
+ width="290" />
+ <combo_box
+ follows="bottom|left|right"
+ height="20"
+ layout="topleft"
+ left="0"
+ name="folder_combo"
+ top_pad="5"
+ width="200" />
+ </panel>
+ </panel>
+ </scroll_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml
new file mode 100644
index 0000000000..039e1ae086
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ name="Landmarks"
+ top="0"
+ height="400"
+ layout="topleft"
+ left="0"
+ width="380"
+ help_topic="panel_landmarks"
+ border="true"
+ background_visible="true"
+ bg_alpha_color="DkGray2"
+ follows="left|top|right|bottom">
+ <accordion
+ follows="left|top|right|bottom"
+ height="368"
+ layout="topleft"
+ left="0"
+ name="landmarks_accordion"
+ top="2"
+ width="380">
+ <accordion_tab
+ layout="topleft"
+ name="tab_favorites"
+ title="Favorites bar">
+ <places_inventory_panel
+ allow_multi_select="true"
+ border="false"
+ bottom="0"
+ follows="left|top|right|bottom"
+ height="126"
+ left="0"
+ mouse_opaque="true"
+ name="favorites_list"
+ start_folder="Favorites"
+ width="380"/>
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ name="tab_landmarks"
+ title="Landmarks">
+ <places_inventory_panel
+ allow_multi_select="true"
+ border="false"
+ bottom="0"
+ follows="left|top|right|bottom"
+ height="126"
+ left="0"
+ mouse_opaque="true"
+ name="landmarks_list"
+ start_folder="Landmarks"
+ width="380"/>
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ name="tab_inventory"
+ title="My Inventory">
+ <places_inventory_panel
+ allow_multi_select="true"
+ border="false"
+ bottom="0"
+ follows="left|top|right|bottom"
+ height="126"
+ left="0"
+ mouse_opaque="true"
+ name="my_inventory_list"
+ start_folder="My Inventory"
+ width="380"/>
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ name="tab_library"
+ title="Library">
+ <places_inventory_panel
+ allow_multi_select="true"
+ border="false"
+ bottom="0"
+ follows="left|top|right|bottom"
+ height="120"
+ left="0"
+ mouse_opaque="true"
+ name="library_list"
+ start_folder="LIBRARY"
+ width="380"/>
+ </accordion_tab>
+ </accordion>
+ <panel
+ background_visible="true"
+ bevel_style="none"
+ bottom="0"
+ follows="left|right|bottom"
+ height="30"
+ layout="bottomleft"
+ left="0"
+ name="bottom_panel"
+ width="380">
+ <button
+ follows="bottom|left"
+ tool_tip="Show additional options"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ layout="topleft"
+ left="10"
+ name="options_gear_btn"
+ top="6"
+ width="18" />
+ <button
+ follows="bottom|left"
+ height="18"
+ image_selected="AddItem_Press"
+ image_unselected="AddItem_Off"
+ image_disabled="AddItem_Disabled"
+ layout="topleft"
+ left_pad="5"
+ name="add_btn"
+ tool_tip="Add new landmark"
+ width="18" />
+ <dnd_button
+ follows="bottom|right"
+ height="18"
+ image_selected="TrashItem_Press"
+ image_unselected="TrashItem_Off"
+ layout="topleft"
+ right="-5"
+ name="trash_btn"
+ tool_tip="Remove selected landmark"
+ top="6"
+ width="18" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml
new file mode 100644
index 0000000000..df942b1a26
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_login.xml
@@ -0,0 +1,234 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+follows="all"
+height="600"
+layout="topleft"
+left="0"
+name="panel_login"
+top="600"
+ width="996">
+<panel.string
+ name="create_account_url">
+ http://join.secondlife.com/
+</panel.string>
+<panel.string
+ name="real_url">
+ http://secondlife.com/app/login/
+</panel.string>
+ <string name="reg_in_client_url">
+ http://secondlife.eniac15.lindenlab.com/reg-in-client/
+</string>
+<panel.string
+ name="forgot_password_url">
+ http://secondlife.com/account/request.php
+</panel.string>
+<!-- *NOTE: Custom resize logic for login_html in llpanellogin.cpp -->
+<web_browser
+bg_opaque_color="Black"
+border_visible="false"
+bottom="600"
+follows="all"
+hide_loading="true"
+left="0"
+name="login_html"
+start_url=""
+top="0"
+height="600"
+ width="980" />
+<layout_stack
+follows="left|bottom|right"
+name="login_widgets"
+layout="topleft"
+orientation="horizontal"
+top="519"
+width="996"
+height="80">
+<layout_panel
+auto_resize="false"
+follows="left|bottom"
+name="login"
+layout="topleft"
+width="695"
+min_width="695"
+user_resize="false"
+height="80">
+<text
+follows="left|bottom"
+font="SansSerifSmall"
+height="16"
+name="first_name_text"
+top="20"
+left="20"
+width="150">
+First name:
+</text>
+<line_editor
+follows="left|bottom"
+handle_edit_keys_directly="true"
+height="22"
+label="First"
+left_delta="0"
+max_length="31"
+name="first_name_edit"
+select_on_focus="true"
+tool_tip="[SECOND_LIFE] First Name"
+top_pad="0"
+ width="135" />
+ <text
+ follows="left|bottom"
+ font="SansSerifSmall"
+ height="16"
+ left_pad="8"
+ name="last_name_text"
+ top="20"
+ width="150">
+ Last name: </text>
+<line_editor
+follows="left|bottom"
+handle_edit_keys_directly="true"
+height="22"
+label="Last"
+max_length="31"
+name="last_name_edit"
+select_on_focus="true"
+tool_tip="[SECOND_LIFE] Last Name"
+ top_pad="0"
+ width="135" />
+<text
+follows="left|bottom"
+font="SansSerifSmall"
+height="15"
+left_pad="8"
+name="password_text"
+top="20"
+ width="150">
+ Password:
+</text>
+<line_editor
+follows="left|bottom"
+handle_edit_keys_directly="true"
+ height="22"
+ max_length="16"
+name="password_edit"
+select_on_focus="true"
+ top_pad="0"
+ width="135" />
+ <check_box
+control_name="RememberPassword"
+follows="left|bottom"
+font="SansSerifSmall"
+height="16"
+label="Remember"
+ top_pad="3"
+ name="remember_check"
+ width="135" />
+ <text
+ follows="left|bottom"
+ font="SansSerifSmall"
+ height="15"
+ left_pad="8"
+ name="start_location_text"
+top="20"
+ width="130">
+ Start at:
+ </text>
+<combo_box
+allow_text_entry="true"
+control_name="LoginLocation"
+ follows="left|bottom"
+ height="23"
+max_chars="128"
+top_pad="0"
+name="start_location_combo"
+ width="135">
+<combo_box.item
+label="My last location"
+name="MyLastLocation"
+ value="last" />
+<combo_box.item
+label="My home"
+name="MyHome"
+ value="home" />
+<combo_box.item
+label="&lt;Type region name&gt;"
+name="Typeregionname" value="" />
+</combo_box>
+<combo_box
+allow_text_entry="true"
+font="SansSerifSmall"
+ follows="left|right|bottom"
+ height="23"
+layout="topleft"
+top_pad="2"
+name="server_combo"
+width="135"
+ visible="false" />
+<button
+ follows="left|bottom"
+ height="23"
+ image_unselected="PushButton_On"
+ image_selected="PushButton_On_Selected"
+ label="Log In"
+ label_color="White"
+ layout="topleft"
+ left_pad="15"
+ name="connect_btn"
+ top="35"
+ width="90" />
+</layout_panel>
+<layout_panel
+follows="right|bottom"
+name="links"
+width="200"
+min_width="200"
+user_resize="false"
+height="80">
+ <text
+follows="right|bottom"
+font="SansSerifSmall"
+text_color="EmphasisColor"
+halign="right"
+height="16"
+top="12"
+right="-10"
+name="create_new_account_text"
+ width="180">
+ Sign up
+ </text>
+<text
+follows="right|bottom"
+font="SansSerifSmall"
+text_color="EmphasisColor"
+halign="right"
+height="16"
+name="forgot_password_text"
+top_pad="12"
+right="-10"
+ width="180">
+ Forgot your name or password?
+</text>
+<text
+follows="right|bottom"
+font="SansSerifSmall"
+text_color="EmphasisColor"
+halign="right"
+height="16"
+name="login_help"
+top_pad="2"
+right="-10"
+ width="180">
+ Need help logging in? </text>
+<!-- <text
+ follows="right|bottom"
+ font="SansSerifSmall"
+ halign="right"
+ height="28"
+ top_pad="2"
+ name="channel_text"
+ width="180"
+ word_wrap="true">
+ [VERSION]
+ </text>-->
+ </layout_panel>
+</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
new file mode 100644
index 0000000000..4030c7184a
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
@@ -0,0 +1,473 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ follows="all"
+ height="400"
+ label="Things"
+ layout="topleft"
+ min_height="350"
+ min_width="240"
+ name="main inventory panel"
+ width="330">
+ <panel.string
+ name="Title">
+ Things
+ </panel.string>
+ <filter_editor
+ text_pad_left="14"
+ follows="left|top|right"
+ height="23"
+ label="Filter Inventory"
+ layout="topleft"
+ left="15"
+max_length="300"
+ name="inventory search editor"
+ top="26"
+ width="303" />
+ <tab_container
+follows="all"
+halign="center"
+ height="300"
+ layout="topleft"
+ left_delta="-4"
+ name="inventory filter tabs"
+ tab_height="30"
+ tab_position="top"
+ tab_min_width="100"
+ top_pad="4"
+ width="305">
+ <inventory_panel
+ border="false"
+ follows="all"
+ height="295"
+ label="MY INVENTORY"
+ help_topic="my_inventory_tab"
+ layout="topleft"
+ left="0"
+ name="All Items"
+ top="16"
+ width="290" />
+ <inventory_panel
+ border="false"
+ follows="all"
+ height="295"
+ label="RECENT"
+ help_topic="recent_inventory_tab"
+ layout="topleft"
+ left_delta="0"
+ name="Recent Items"
+ width="290" />
+ </tab_container>
+
+ <panel
+ background_visible="true"
+ bevel_style="none"
+ bottom="0"
+ follows="left|right|bottom"
+ height="30"
+ layout="bottomleft"
+ left="0"
+ visible="true"
+ name="bottom_panel"
+ width="330">
+ <button
+ follows="bottom|left"
+ tool_tip="Show additional options"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ layout="topleft"
+ left="10"
+ name="options_gear_btn"
+ picture_style="true"
+ top="6"
+ width="18" />
+ <button
+ follows="bottom|left"
+ height="18"
+ image_selected="AddItem_Press"
+ image_unselected="AddItem_Off"
+ image_disabled="AddItem_Disabled"
+ layout="topleft"
+ left_pad="5"
+ name="add_btn"
+ picture_style="true"
+ tool_tip="Add new item"
+ width="18" />
+ <dnd_button
+ follows="bottom|right"
+ height="18"
+ image_selected="TrashItem_Press"
+ image_unselected="TrashItem_Off"
+ layout="topleft"
+ right="-5"
+ name="trash_btn"
+ picture_style="true"
+ tool_tip="Remove selected item"
+ top="6"
+ width="18" />
+ </panel>
+
+ <menu_bar
+ bg_visible="false"
+ follows="left|top|right"
+ height="20"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="Inventory Menu"
+ top="0"
+ visible="true"
+ width="290">
+ <menu
+ height="101"
+ label="File"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="File"
+ tear_off="true"
+ top="-117"
+ width="128">
+ <menu_item_call
+ label="Open"
+ layout="topleft"
+ name="Open">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="open" />
+ </menu_item_call>
+ <menu
+ create_jump_keys="true"
+ label="Upload"
+ layout="topleft"
+ name="upload"
+ tear_off="true">
+ <menu_item_call
+ label="Image (L$[COST])..."
+ layout="topleft"
+ name="Upload Image"
+ shortcut="control|U">
+ <menu_item_call.on_click
+ function="File.UploadImage"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="File.EnableUpload" />
+ </menu_item_call>
+ <menu_item_call
+ label="Sound (L$[COST])..."
+ layout="topleft"
+ name="Upload Sound">
+ <menu_item_call.on_click
+ function="File.UploadSound"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="File.EnableUpload" />
+ </menu_item_call>
+ <menu_item_call
+ label="Animation (L$[COST])..."
+ layout="topleft"
+ name="Upload Animation">
+ <menu_item_call.on_click
+ function="File.UploadAnim"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="File.EnableUpload" />
+ </menu_item_call>
+ <menu_item_call
+ label="Bulk (L$[COST] per file)..."
+ layout="topleft"
+ name="Bulk Upload">
+ <menu_item_call.on_click
+ function="File.UploadBulk"
+ parameter="" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ </menu>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="New Window"
+ layout="topleft"
+ name="New Window">
+ <menu_item_call.on_click
+ function="Inventory.NewWindow" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"
+ name="separator2" />
+ <menu_item_call
+ label="Show Filters"
+ layout="topleft"
+ name="Show Filters">
+ <menu_item_call.on_click
+ function="Inventory.ShowFilters" />
+ </menu_item_call>
+ <menu_item_call
+ label="Reset Filters"
+ layout="topleft"
+ name="Reset Current">
+ <menu_item_call.on_click
+ function="Inventory.ResetFilters" />
+ </menu_item_call>
+ <menu_item_call
+ label="Close All Folders"
+ layout="topleft"
+ name="Close All Folders">
+ <menu_item_call.on_click
+ function="Inventory.CloseAllFolders" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"
+ name="separator3" />
+ <menu_item_call
+ label="Empty Trash"
+ layout="topleft"
+ name="Empty Trash">
+ <menu_item_call.on_click
+ function="Inventory.EmptyTrash" />
+ </menu_item_call>
+ <menu_item_call
+ label="Empty Lost And Found"
+ layout="topleft"
+ name="Empty Lost And Found">
+ <menu_item_call.on_click
+ function="Inventory.EmptyLostAndFound" />
+ </menu_item_call>
+ </menu>
+ <menu
+ height="121"
+ label="Create"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="Create"
+ tear_off="true"
+ top="-201"
+ width="121">
+ <menu_item_call
+ label="New Folder"
+ layout="topleft"
+ name="New Folder">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="category" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Script"
+ layout="topleft"
+ name="New Script">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="lsl" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Notecard"
+ layout="topleft"
+ name="New Note">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="notecard" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Gesture"
+ layout="topleft"
+ name="New Gesture">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="gesture" />
+ </menu_item_call>
+ <menu
+ height="175"
+ label="New Clothes"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="New Clothes"
+ top_pad="514"
+ width="125">
+ <menu_item_call
+ label="New Shirt"
+ layout="topleft"
+ name="New Shirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Pants"
+ layout="topleft"
+ name="New Pants">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="pants" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Shoes"
+ layout="topleft"
+ name="New Shoes">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shoes" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Socks"
+ layout="topleft"
+ name="New Socks">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="socks" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Jacket"
+ layout="topleft"
+ name="New Jacket">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="jacket" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Skirt"
+ layout="topleft"
+ name="New Skirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="skirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Gloves"
+ layout="topleft"
+ name="New Gloves">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="gloves" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Undershirt"
+ layout="topleft"
+ name="New Undershirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="undershirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Underpants"
+ layout="topleft"
+ name="New Underpants">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="underpants" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Alpha"
+ layout="topleft"
+ name="New Alpha">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="alpha" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Tattoo"
+ layout="topleft"
+ name="New Tattoo">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="tattoo" />
+ </menu_item_call>
+ </menu>
+ <menu
+ height="85"
+ label="New Body Parts"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="New Body Parts"
+ top_pad="514"
+ width="118">
+ <menu_item_call
+ label="New Shape"
+ layout="topleft"
+ name="New Shape">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shape" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Skin"
+ layout="topleft"
+ name="New Skin">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="skin" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Hair"
+ layout="topleft"
+ name="New Hair">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="hair" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Eyes"
+ layout="topleft"
+ name="New Eyes">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="eyes" />
+ </menu_item_call>
+ </menu>
+ </menu>
+ <menu
+ height="49"
+ label="Sort"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="Sort"
+ tear_off="true"
+ top="-113"
+ width="118">
+ <menu_item_check
+ control_name="Inventory.SortByName"
+ label="By Name"
+ layout="topleft"
+ name="By Name">
+ <menu_item_check.on_click
+ function="Inventory.SetSortBy"
+ parameter="name" />
+ </menu_item_check>
+ <menu_item_check
+ control_name="Inventory.SortByDate"
+ label="By Date"
+ layout="topleft"
+ name="By Date">
+ <menu_item_check.on_click
+ function="Inventory.SetSortBy"
+ parameter="date" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_check
+ control_name="Inventory.FoldersAlwaysByName"
+ label="Folders Always By Name"
+ layout="topleft"
+ name="Folders Always By Name">
+ <menu_item_check.on_click
+ function="Inventory.SetSortBy"
+ parameter="foldersalwaysbyname" />
+ </menu_item_check>
+ <menu_item_check
+ control_name="Inventory.SystemFoldersToTop"
+ label="System Folders To Top"
+ layout="topleft"
+ name="System Folders To Top">
+ <menu_item_check.on_click
+ function="Inventory.SetSortBy"
+ parameter="systemfolderstotop" />
+ </menu_item_check>
+ </menu>
+ </menu_bar>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_me.xml b/indra/newview/skins/default/xui/en/panel_me.xml
new file mode 100644
index 0000000000..e779e37419
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_me.xml
@@ -0,0 +1,52 @@
+<?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">
+ <!--<text
+ type="string"
+ follows="top|left|right"
+ font="SansSerifHugeBold"
+ height="20"
+ layout="topleft"
+ left="15"
+ name="user_name"
+ text_color="white"
+ top="0"
+ mouse_opaque="true"
+ width="280">
+ (Loading...)
+ </text> -->
+ <tab_container
+ follows="all"
+ height="570"
+ halign="center"
+ layout="topleft"
+ left="10"
+ name="tabs"
+ tab_min_width="95"
+ tab_height="30"
+ tab_position="top"
+ top_pad="10"
+ width="313">
+ <panel
+ class="panel_my_profile"
+ filename="panel_my_profile.xml"
+ label="PROFILE"
+ help_topic="panel_my_profile_tab"
+ name="panel_profile" />
+ <panel
+ class="panel_picks"
+ filename="panel_picks.xml"
+ label="PICKS"
+ help_topic="panel_my_picks_tab"
+ name="panel_picks" />
+ </tab_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_media_settings_general.xml b/indra/newview/skins/default/xui/en/panel_media_settings_general.xml
new file mode 100644
index 0000000000..38e8b9844f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_media_settings_general.xml
@@ -0,0 +1,226 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ enabled="true"
+ follows="left|top|right|bottom"
+ height="500"
+ label="General"
+ left="102"
+ mouse_opaque="true"
+ name="Media Settings General"
+ help_topic = "media_settings_general"
+ width="365">
+
+ <text
+ bottom_delta="-25"
+ follows="top|left"
+ height="15"
+ left="10"
+ name="home_label">
+ Home Page:
+ </text>
+ <text
+ visible="false"
+ bottom_delta="0"
+ follows="top|left"
+ height="15"
+ left_delta="64"
+ text_color="red"
+ name="home_fails_whitelist_label">
+ (This page does not pass the specified whitelist)
+ </text>
+ <line_editor
+ max_length="1024"
+ bottom_delta="-24"
+ enabled="true"
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ left="10"
+ name="home_url"
+ tool_tip="The home page for this media source"
+ width="340">
+ <!-- <line_editor.commit_callback
+ function="Media.CommitHomeURL"/> -->
+ </line_editor>
+
+ <web_browser
+ border_visible="true"
+ bottom_delta="-133"
+ follows="top|left"
+ left="120"
+ name="preview_media"
+ width="128"
+ height="128"
+ start_url="about:blank"
+ decouple_texture_size="true" />
+
+ <text
+ bottom_delta="-15"
+ follows="top|left"
+ height="15"
+ left="164"
+ name="preview_label">
+ Preview
+ </text>
+
+ <text
+ bottom_delta="-20"
+ follows="top|left"
+ height="15"
+ left="10"
+ name="current_url_label">
+ Current Page:
+ </text>
+ <text
+ name="current_url"
+ max_length="1024"
+ use_ellipses="true"
+ bottom_delta="-20"
+ enabled="false"
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ left="10"
+ tool_tip="The current page for this media source"
+ value=""
+ width="340" />
+ <button
+ bottom_delta="-20"
+ follows="top|left"
+ height="20"
+ label="Reset"
+ left_delta="233"
+ name="current_url_reset_btn"
+ width="110" >
+ <button.commit_callback
+ function="Media.ResetCurrentUrl"/>
+ </button>
+ <check_box
+ bottom_delta="-25"
+ enabled="true"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Auto Loop"
+ left="10"
+ mouse_opaque="true"
+ name="auto_loop"
+ radio_style="false"
+ width="150" />
+ <check_box
+ bottom_delta="-25"
+ visible="false"
+ enabled="false"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="First Click Interacts"
+ left_delta="0"
+ mouse_opaque="true"
+ name="first_click_interact"
+ radio_style="false"
+ width="150" />
+
+ <check_box
+ bottom_delta="0"
+ enabled="true"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Auto Zoom"
+ left_delta="0"
+ mouse_opaque="true"
+ name="auto_zoom"
+ radio_style="false"
+ width="150" />
+
+ <check_box
+ bottom_delta="-25"
+ enabled="true"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Auto Play Media"
+ left="10"
+ mouse_opaque="true"
+ name="auto_play"
+ radio_style="false"
+ width="150" />
+
+ <text
+ bottom_delta="-14"
+ follows="top|left"
+ height="15"
+ left="30"
+ width="340"
+ enabled="false"
+ name="media_setting_note">
+ Note: Residents can override this setting
+ </text>
+
+ <check_box
+ bottom_delta="-25"
+ enabled="true"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Auto Scale Media on Face of Object"
+ left="10"
+ mouse_opaque="true"
+ name="auto_scale"
+ radio_style="false"
+ width="150" />
+
+ <text
+ bottom_delta="-20"
+ follows="top|left"
+ height="15"
+ left="30"
+ name="size_label">
+ Size:
+ </text>
+
+ <spinner
+ bottom_delta="0"
+ decimal_digits="0"
+ enabled="true"
+ follows="left|top"
+ height="16"
+ increment="1"
+ initial_val="256"
+ label=""
+ label_width="0"
+ left_delta="40"
+ max_val="2048"
+ min_val="0"
+ mouse_opaque="true"
+ name="width_pixels"
+ width="50" />
+
+ <text bottom_delta="0" follows="top|left" height="15" left_delta="60" name="X_label">
+ X
+ </text>
+ <spinner
+ bottom_delta="0"
+ decimal_digits="0"
+ enabled="true"
+ follows="left|top"
+ height="16"
+ increment="1"
+ initial_val="256"
+ label=""
+ label_width="0"
+ left_delta="20"
+ max_val="2048"
+ min_val="0"
+ mouse_opaque="true"
+ name="height_pixels"
+ width="50" />
+
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml b/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml
new file mode 100644
index 0000000000..b5c2371510
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ enabled="true"
+ follows="left|top|right|bottom"
+ height="500"
+ label="Customize"
+ left="102"
+ mouse_opaque="true"
+ name="Media settings for controls"
+ help_topic = "media_settings_controls"
+ width="365">
+
+ <text
+ bottom_delta="-50"
+ follows="top|left"
+ height="15"
+ left="10"
+ name="controls_label">
+ Controls:
+ </text>
+ <combo_box
+ allow_text_entry="false"
+ bottom_delta="0"
+ follows="left|top"
+ height="18"
+ left="100"
+ max_chars="20"
+ name="controls"
+ width="120">
+ <combo_item
+ name="Standard"
+ value="Standard">
+ Standard
+ </combo_item>
+ <combo_item
+ name="Mini"
+ value="Mini">
+ Mini
+ </combo_item>
+ </combo_box>
+
+ <text
+ bottom_delta="-50"
+ follows="top|left"
+ height="15"
+ left="10"
+ enabled="false">
+ Owner
+ </text>
+
+ <check_box
+ bottom_delta="-22"
+ enabled="true"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Allow Navigation &amp; Interactivity"
+ left="30"
+ mouse_opaque="true"
+ name="perms_owner_interact"
+ radio_style="false"
+ width="250" />
+
+ <check_box
+ bottom_delta="-22"
+ enabled="true"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Show Control Bar"
+ left="30"
+ mouse_opaque="true"
+ name="perms_owner_control"
+ radio_style="false"
+ width="250" />
+
+ <text
+ bottom_delta="-36"
+ follows="top|left"
+ height="15"
+ left="10"
+ enabled="false">
+ Group:
+ </text>
+
+ <name_box
+ bottom_delta="-5"
+ enabled="false"
+ follows="left|top"
+ font="SansSerif"
+ height="20" left="60"
+ name="perms_group_name"
+ value =""
+ width="200" />
+
+ <check_box
+ bottom_delta="-22"
+ enabled="true"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Allow Navigation &amp; Interactivity"
+ left="30"
+ mouse_opaque="true"
+ name="perms_group_interact"
+ radio_style="false"
+ width="250" />
+
+ <check_box
+ bottom_delta="-22"
+ enabled="true"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Show Control Bar"
+ left="30"
+ mouse_opaque="true"
+ name="perms_group_control"
+ radio_style="false"
+ width="250" />
+
+ <text
+ bottom_delta="-36"
+ follows="top|left"
+ height="15"
+ left="10"
+ enabled="false">
+ Anyone
+ </text>
+
+ <check_box
+ bottom_delta="-22"
+ enabled="true"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Allow Navigation &amp; Interactivity"
+ left="30"
+ mouse_opaque="true"
+ name="perms_anyone_interact"
+ radio_style="false"
+ width="250" />
+
+ <check_box
+ bottom_delta="-22"
+ enabled="true"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Show Control Bar"
+ left="30"
+ mouse_opaque="true"
+ name="perms_anyone_control"
+ radio_style="false"
+ width="250" />
+
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_media_settings_security.xml b/indra/newview/skins/default/xui/en/panel_media_settings_security.xml
new file mode 100644
index 0000000000..1f580831f9
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_media_settings_security.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ enabled="true"
+ follows="left|top|right|bottom"
+ height="500"
+ label="Security"
+ left="102"
+ mouse_opaque="true"
+ name="Media Settings Security"
+ help_topic = "media_settings_security"
+ width="365">
+ <check_box
+ bottom_delta="-40"
+ enabled="true"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Only Allow Access to Specified URL patterns"
+ left="10"
+ mouse_opaque="true"
+ name="whitelist_enable"
+ radio_style="false"
+ width="250" />
+ <scroll_list
+ follows="top|left"
+ height="200"
+ left="30"
+ name="whitelist"
+ width="315"
+ enabled="true" />
+ <icon
+ bottom_delta="-23"
+ right="-35"
+ width="16"
+ height="16"
+ image_name="Parcel_Exp_Color"
+ mouse_opaque="true"
+ follows="top|left"
+ name="Parcel_Exp_Color"
+ />
+ <text
+ visible="true"
+ follows="top|left"
+ height="15"
+ left="30"
+ bottom_delta="0"
+ text_color="0.4 0.4 0.4 1.0"
+ name="home_url_fails_some_items_in_whitelist">
+ Entries that the home page fails against are marked:
+ </text>
+ <button
+ bottom_delta="-36"
+ follows="top|left"
+ height="20"
+ label="Add"
+ left="30"
+ name="whitelist_add"
+ width="70"
+ enabled="true">
+ <button.commit_callback
+ function="Media.whitelistAdd"/>
+ </button>
+ <button
+ bottom_delta="0"
+ follows="top|left"
+ height="20"
+ label="Delete"
+ left="275"
+ name="whitelist_del"
+ width="70"
+ enabled="true">
+ <button.commit_callback
+ function="Media.whitelistDelete"/>
+ </button>
+ <text
+ visible="true"
+ bottom_delta="-75"
+ follows="top|left"
+ height="40"
+ left="30"
+ text_color="0.6 0.0 0.0 1.0"
+ word_wrap="true"
+ name="home_url_fails_whitelist">
+Warning: the home page specified in the General tab fails to pass this whitelist. It has been disabled until a valid entry has been added.
+ </text>
+
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_my_profile.xml b/indra/newview/skins/default/xui/en/panel_my_profile.xml
new file mode 100644
index 0000000000..4894ae01da
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_my_profile.xml
@@ -0,0 +1,395 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="all"
+ height="500"
+ label="Profile"
+ layout="topleft"
+ left="0"
+ name="panel_profile"
+ top="0"
+ width="313">
+ <string
+ name="CaptionTextAcctInfo">
+ [ACCTTYPE]
+[PAYMENTINFO] [AGEVERIFICATION]
+ </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="None" />
+ <string
+ name="no_group_text"
+ value="None" />
+ <string
+ name="RegisterDateFormat">
+ [REG_DATE] ([AGE])
+ </string>
+ <layout_stack
+ name="layout"
+ orientation="vertical"
+ follows="all"
+ layout="topleft"
+ left="0"
+ top="0"
+ height="480"
+ width="313"
+ border_size="0">
+ <layout_panel
+ name="profile_stack"
+ follows="all"
+ layout="topleft"
+ top="0"
+ left="0"
+ height="480"
+ user_resize="false"
+ width="313">
+ <scroll_container
+ color="DkGray2"
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="profile_scroll"
+ opaque="true"
+ height="480"
+ width="313"
+ top="0">
+ <panel
+ layout="topleft"
+ follows="left|top|right"
+ height="505"
+ name="scroll_content_panel"
+ top="0"
+ left="0"
+ width="297">
+ <panel
+ follows="left|top|right"
+ height="117"
+ layout="topleft"
+ left="10"
+ name="second_life_image_panel"
+ top="0"
+ width="297">
+ <texture_picker
+ allow_no_texture="true"
+ default_image_name="None"
+ enabled="false"
+ follows="top|left"
+ height="117"
+ layout="topleft"
+ left="0"
+ name="2nd_life_pic"
+ top="10"
+ width="102" />
+ <icon
+ height="102"
+ image_name="Blank"
+ layout="topleft"
+ name="2nd_life_edit_icon"
+ label=""
+ left="0"
+ tool_tip="Click the Edit Profile button below to change image"
+ top="10"
+ width="102" />
+ <text
+ follows="left|top|right"
+ font.style="BOLD"
+ height="15"
+ layout="topleft"
+ left_pad="10"
+ name="title_sl_descr_text"
+ text_color="white"
+ top_delta="0"
+ value="[SECOND_LIFE]:"
+ width="180" />
+ <expandable_text
+ follows="left|top|right"
+ height="95"
+ layout="topleft"
+ left="107"
+ textbox.max_length="512"
+ name="sl_description_edit"
+ top_pad="-3"
+ width="181"
+ expanded_bg_visible="true"
+ expanded_bg_color="DkGray">
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ <panel
+ follows="left|top|right"
+ height="117"
+ layout="topleft"
+ top_pad="10"
+ left="10"
+ name="first_life_image_panel"
+ width="297">
+ <texture_picker
+ allow_no_texture="true"
+ default_image_name="None"
+ enabled="false"
+ follows="top|left"
+ height="117"
+ layout="topleft"
+ left="0"
+ name="real_world_pic"
+ width="102" />
+ <icon
+ height="102"
+ image_name="Blank"
+ layout="topleft"
+ name="real_world_edit_icon"
+ label=""
+ left="0"
+ tool_tip="Click the Edit Profile button below to change image"
+ top="4"
+ width="102" />
+ <text
+ follows="left|top|right"
+ font.style="BOLD"
+ height="15"
+ layout="topleft"
+ left_pad="10"
+ name="title_rw_descr_text"
+ text_color="white"
+ top_delta="0"
+ value="Real World:"
+ width="180" />
+ <expandable_text
+ follows="left|top|right"
+ height="95"
+ layout="topleft"
+ left="107"
+ textbox.max_length="512"
+ name="fl_description_edit"
+ top_pad="-3"
+ width="181"
+ expanded_bg_visible="true"
+ expanded_bg_color="DkGray">
+ Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ <text
+ follows="left|top"
+ height="15"
+ font.style="BOLD"
+ font="SansSerifMedium"
+ layout="topleft"
+ left="10"
+ name="homepage_edit"
+ top_pad="0"
+ value="http://librarianavengers.org"
+ width="300"
+ word_wrap="false"
+ use_ellipses="true"
+ />
+ <text
+ follows="left|top"
+ font.style="BOLD"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="title_member_text"
+ text_color="white"
+ top_pad="10"
+ value="Resident Since:"
+ width="300" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="register_date"
+ value="05/31/2376"
+ width="300"
+ word_wrap="true" />
+ <text
+ follows="left|top"
+ font.style="BOLD"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="title_acc_status_text"
+ text_color="white"
+ top_pad="5"
+ value="Account Status:"
+ width="300" />
+ <!-- <text
+ type="string"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="15"
+ layout="topleft"
+ left_pad="10"
+ name="my_account_link"
+ top_delta="0"
+ value="Go to Dashboard"
+ width="100"/> -->
+ <text
+ follows="left|top"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="acc_status_text"
+ top_pad="0"
+ width="300"
+ word_wrap="true">
+ Resident. No payment info on file.
+ Linden.
+ </text>
+ <text
+ follows="left|top"
+ font.style="BOLD"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="title_partner_text"
+ text_color="white"
+ top_pad="3"
+ value="Partner:"
+ width="300" />
+ <panel
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="partner_data_panel"
+ top_pad="0"
+ width="300">
+ <name_box
+ follows="left|top"
+ height="10"
+ initial_value="(retrieving)"
+ layout="topleft"
+ left="0"
+ link="true"
+ name="partner_text"
+ top="0"
+ width="300"
+ word_wrap="true" />
+ </panel>
+ <text
+ follows="left|top"
+ font.style="BOLD"
+ height="13"
+ layout="topleft"
+ left="10"
+ name="title_groups_text"
+ text_color="white"
+ top_pad="3"
+ value="Groups:"
+ width="300" />
+ <expandable_text
+ follows="all"
+ height="113"
+ layout="topleft"
+ left="7"
+ name="sl_groups"
+ top_pad="0"
+ width="298"
+ expanded_bg_visible="true"
+ expanded_bg_color="DkGray">
+ Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. Aenean viverra tulip moosetop. Slan de heelish marfnik tooplod. Sum sum to whop de wompam booster copm.
+ </expandable_text>
+ </panel>
+ </scroll_container>
+ </layout_panel>
+ <!-- <layout_panel
+ follows="bottom|left"
+ layout="topleft"
+ left="0"
+ name="profile_buttons_panel"
+ height="28"
+ width="313">
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Add Friend"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="add_friend"
+ tool_tip="Offer friendship to the Resident"
+ top="5"
+ width="80" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="IM"
+ layout="topleft"
+ name="im"
+ top="5"
+ left_pad="3"
+ width="45" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Call"
+ layout="topleft"
+ name="call"
+ left_pad="3"
+ top="5"
+ width="45" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ height="23"
+ label="Map"
+ layout="topleft"
+ name="show_on_map_btn"
+ top="5"
+ left_pad="3"
+ width="45" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Teleport"
+ layout="topleft"
+ name="teleport"
+ left_pad="3"
+ top="5"
+ width="85" />
+ </panel>-->
+ <layout_panel
+ follows="bottom|left"
+ layout="topleft"
+ left="0"
+ top_pad="0"
+ name="profile_me_buttons_panel"
+ visible="false"
+ user_resize="false"
+ auto_resize="false"
+ height="28"
+ width="313">
+ <button
+ follows="bottom|right"
+ height="23"
+ left="20"
+ top="5"
+ label="Edit Profile"
+ layout="topleft"
+ name="edit_profile_btn"
+ tool_tip="Edit your personal information"
+ width="130" />
+ <button
+ follows="bottom|right"
+ height="23"
+ label="Edit Appearance"
+ left_pad="10"
+ layout="topleft"
+ name="edit_appearance_btn"
+ top="5"
+ tool_tip="Create/edit your appearance: physical data, clothes and etc."
+ width="130" />
+ </layout_panel>
+</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
new file mode 100644
index 0000000000..baa6c2e51f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_opaque="true"
+ background_visible="true"
+ bg_opaque_color="MouseGray"
+ follows="left|top|right"
+ height="60"
+ layout="topleft"
+ name="navigation_bar"
+ chrome="true"
+ width="600">
+ <icon
+ follows="all"
+ image_name="NavBar_BG"
+ mouse_opaque="false"
+ name="bg_icon"
+ scale_image="true"
+ visible="true"
+ left="0"
+ top="0"
+ height="60"
+ width="600"/>
+ <icon
+ follows="all"
+ image_name="NavBar_BG_NoFav"
+ mouse_opaque="false"
+ name="bg_icon_no_fav"
+ scale_image="true"
+ visible="false"
+ left="0"
+ top="0"
+ height="50"
+ width="600"/>
+ <panel
+ background_visible="false"
+ follows="left|top|right"
+ top="3"
+ height="23"
+ layout="topleft"
+ name="navigation_panel"
+ width="600">
+ <button
+ follows="left|top"
+ height="23"
+ image_overlay="Arrow_Left_Off"
+ layout="topleft"
+ left="10"
+ name="back_btn"
+ tool_tip="Go back to previous location"
+ top="2"
+ width="31" />
+ <button
+ follows="left|top"
+ height="23"
+ image_overlay="Arrow_Right_Off"
+ layout="topleft"
+ left_pad="0"
+ name="forward_btn"
+ tool_tip="Go forward one location"
+ top_delta="0"
+ width="31" />
+ <button
+ follows="left|top"
+ height="23"
+ image_overlay="Home_Off"
+ layout="topleft"
+ left_pad="7"
+ name="home_btn"
+ tool_tip="Teleport to my home location"
+ top_delta="0"
+ width="32" />
+ <location_input
+ follows="left|right|top"
+ halign="right"
+ height="23"
+ label="Location"
+ layout="topleft"
+ left_pad="7"
+ max_chars="254"
+ mouse_opaque="false"
+ name="location_combo"
+ top_delta="0"
+ width="266">
+ <!-- *TODO: Delete. Let the location_input use the correct art sizes.
+ <location_input.add_landmark_button
+ height="18"
+ name="location_combo_add"
+ width="20" />
+ <location_input.info_button
+ height="18"
+ name="location_combo_info"
+ width="20" />
+ -->
+ </location_input>
+ <!-- <button -->
+ <!-- follows="right|top" -->
+ <!-- height="20" -->
+ <!-- image_disabled="TextField_Search_Off" -->
+ <!-- image_disabled_selected="TextField_Search_Off" -->
+ <!-- image_hover_selected="TextField_Search_Off" -->
+ <!-- image_hover_unselected="TextField_Search_Off" -->
+ <!-- image_selected="TextField_Search_Off" -->
+ <!-- image_unselected="TextField_Search_Off" -->
+ <!-- layout="topleft" -->
+ <!-- left_pad="5" -->
+ <!-- mouse_opaque="false" -->
+ <!-- name="search_bg" -->
+ <!-- top_delta="0" -->
+ <!-- width="168" /> -->
+ <search_combo_box
+ bevel_style="none"
+ border_style="line"
+ border.border_thickness="0"
+ commit_on_focus_lost="false"
+ follows="right|top"
+ halign="right"
+ height="22"
+ label="Search"
+ layout="topleft"
+ right="-10"
+ mouse_opaque="false"
+ name="search_combo_box"
+ tool_tip="Search"
+ top_delta="0"
+ width="200" >
+ <combo_editor
+ label="Search [SECOND_LIFE]"
+ name="search_combo_editor"/>
+ <combo_list
+ draw_border="true"
+ border.highlight_light_color="FocusColor"
+ border.highlight_dark_color="FocusColor"
+ border.shadow_light_color="FocusColor"
+ border.shadow_dark_color="FocusColor"/>
+ </search_combo_box>
+ </panel>
+ <favorites_bar
+ follows="left|right|top"
+ font="SansSerifSmall"
+ height="15"
+ layout="topleft"
+ left="0"
+ name="favorite"
+ image_drag_indication="Accordion_ArrowOpened_Off"
+ bottom="55"
+ width="590">
+ <chevron_button name=">>"
+ image_unselected="TabIcon_Close_Off"
+ image_selected="TabIcon_Close_Off"
+ tab_stop="false"
+ follows="left|bottom"
+ tool_tip="Show more of My Favorites"
+ width="15"
+ top="15"
+ height="15"/>
+ </favorites_bar>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml
new file mode 100644
index 0000000000..50a78e1c71
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- All our XML is utf-8 encoded. -->
+
+<panel
+ name="nearby_chat" visible="true" width="250" height="480" background_opaque="false"
+ background_visible="true" bevel_style="in" follows="left|top" bg_alpha_color="0.3 0.3 0.3 1.0">
+ <panel bottom="380" width="250" height="30" background_visible="true" background_opaque="false" bg_alpha_color="0.0 0.0 0.0 1.0" name="chat_caption">
+ <text
+ width="140" left="25" height="20" follows="left|right|top"
+ font="SansSerifBigBold" text_color="white" word_wrap="true"
+ mouse_opaque="true" name="sender_name" >NEARBY CHAT </text>
+ <icon top="25" left="180"
+ width="20" height="20" follows="top|right"
+ color="1 1 1 1" enabled="true" image_name="icn_voice-groupfocus.tga"
+ mouse_opaque="true" name="nearby_speakers_btn"/>
+ <icon top="25" left="205"
+ width="20" height="20" follows="top|right"
+ color="1 1 1 1" enabled="true" image_name="inv_item_landmark_visited.tga"
+ mouse_opaque="true" name="tearoff_btn"/>
+ <icon top="22" left="230"
+ width="15" height="15" follows="top|right"
+ color="1 1 1 1" enabled="true" image_name="closebox.tga"
+ name="close_btn"/>
+ </panel>
+ <chat_history_view bottom="0" width="250" height="320" follows="left|right|top|bottom" name="chat_scroll" />
+</panel>
+
diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml
new file mode 100644
index 0000000000..2b361c0628
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ default_tab_group="1"
+ follows="left|bottom|right"
+ height="25"
+ layout="topleft"
+ left="0"
+ name="chat_bar"
+ top="21"
+ width="310">
+ <string name="min_width">
+ 188
+ </string>
+ <string name="max_width">
+ 320
+ </string>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|right"
+ height="23"
+ label="Click here to chat."
+ layout="topleft"
+ left_delta="3"
+ text_pad_right="25"
+ left="0"
+ max_length="512"
+ name="chat_box"
+ tool_tip="Press Enter to say, Ctrl+Enter to shout"
+ top="2"
+ width="283" />
+ <output_monitor
+ auto_update="true"
+ follows="right"
+ draw_border="false"
+ height="16"
+ layout="topleft"
+ left_pad="-24"
+ mouse_opaque="true"
+ name="chat_zone_indicator"
+ top="6"
+ visible="true"
+ width="20" />
+ <button
+ follows="right"
+ is_toggle="true"
+ width="20"
+ top="2"
+ layout="topleft"
+ left_pad="4"
+ image_disabled="ComboButton_UpOff"
+ image_unselected="ComboButton_UpOff"
+ image_selected="ComboButton_Up_On_Selected"
+ image_pressed="ComboButton_UpSelected"
+ image_pressed_selected="ComboButton_Up_On_Selected"
+ height="23"
+ name="show_nearby_chat"
+ tool_tip="Shows/hides nearby chat log">
+ <button.init_callback
+ function="Button.SetDockableFloaterToggle"
+ parameter="nearby_chat" />
+ </button>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_notes.xml b/indra/newview/skins/default/xui/en/panel_notes.xml
new file mode 100644
index 0000000000..ac100a2c06
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_notes.xml
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="all"
+ height="540"
+ label="Notes &amp; Privacy"
+ layout="topleft"
+ left="0"
+ name="panel_notes"
+ top="0"
+ width="313"
+>
+ <layout_stack
+ name="layout"
+ orientation="vertical"
+ follows="all"
+ layout="topleft"
+ left="0"
+ top="0"
+ height="517"
+ width="313"
+ border_size="0">
+ <layout_panel
+ name="notes_stack"
+ follows="all"
+ layout="topleft"
+ top="0"
+ left="0"
+ height="475"
+ width="313">
+ <scroll_container
+ color="DkGray2"
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="profile_scroll"
+ opaque="true"
+ height="475"
+ width="313"
+ top="0">
+ <panel
+ height="450"
+ layout="topleft"
+ name="profile_scroll_panel"
+ top="0"
+ left="0"
+ width="303">
+ <text
+ follows="left|top"
+ font="SansSerifBold"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="status_message"
+ text_color="white"
+ top="20"
+ value="My private notes:"
+ width="293" />
+ <text_editor
+ follows="left|top"
+ height="120"
+ layout="topleft"
+ left="10"
+ max_length="1000"
+ name="notes_edit"
+ text_color="DkGray"
+ top_pad="10"
+ width="280"
+ word_wrap="true" />
+ <text
+ follows="left|top"
+ font="SansSerifBold"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="status_message2"
+ text_color="white"
+ top_pad="30"
+ value="Allow this person to:"
+ width="293" />
+ <check_box
+ enabled="false"
+ height="16"
+ label="See my online status"
+ layout="topleft"
+ left="20"
+ name="status_check"
+ width="293" />
+ <check_box
+ enabled="false"
+ height="16"
+ label="See me on the map"
+ layout="topleft"
+ left="20"
+ name="map_check"
+ width="293" />
+ <check_box
+ enabled="false"
+ height="16"
+ label="Edit, delete or take my objects"
+ layout="topleft"
+ left="20"
+ name="objects_check"
+ width="293" />
+ </panel>
+ </scroll_container>
+ </layout_panel>
+ <layout_panel
+ follows="bottom|left"
+ height="30"
+ layout="topleft"
+ left="0"
+ name="notes_buttons_panel"
+ auto_resize="false"
+ width="313">
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Add Friend"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="add_friend"
+ tool_tip="Offer friendship to the Resident"
+ top="5"
+ width="80" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="IM"
+ layout="topleft"
+ name="im"
+ tool_tip="Open instant message session"
+ top="5"
+ left_pad="3"
+ width="45" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Call"
+ layout="topleft"
+ name="call"
+ tool_tip="Call this Resident"
+ left_pad="3"
+ top="5"
+ width="45" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ height="23"
+ label="Map"
+ layout="topleft"
+ name="show_on_map_btn"
+ tool_tip="Show the Resident on the map"
+ top="5"
+ left_pad="3"
+ width="45" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Teleport"
+ layout="topleft"
+ name="teleport"
+ tool_tip="Offer teleport"
+ left_pad="3"
+ top="5"
+ width="80" />
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_notification.xml b/indra/newview/skins/default/xui/en/panel_notification.xml
new file mode 100644
index 0000000000..df37f9973c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_notification.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_opaque="false"
+ border_visible="false"
+ background_visible="true"
+ bg_alpha_color="0.3 0.3 0.3 0"
+ bg_opaque_color="0.3 0.3 0.3 0"
+ label="notification_panel"
+ layout="topleft"
+ left="0"
+ name="notification_panel"
+ top="0"
+ height="140"
+ width="305">
+ <!-- THIS PANEL CONTROLS TOAST HEIGHT? -->
+ <panel
+ border_visible="false"
+ bevel_style="none"
+ background_visible="true"
+ bg_alpha_color="0.3 0.3 0.3 0"
+ bg_opaque_color="0.3 0.3 0.3 0"
+ follows="left|right|top"
+ height="100"
+ label="info_panel"
+ layout="topleft"
+ left="0"
+ name="info_panel"
+ top="0"
+ width="305">
+ <text
+ border_visible="false"
+ follows="left|right|top|bottom"
+ font="SansSerif"
+ height="85"
+ layout="topleft"
+ left="10"
+ name="text_box"
+ read_only="true"
+ text_color="white"
+ top="10"
+ visible="false"
+ width="285"
+ wrap="true"/>
+ <text
+ border_visible="false"
+ follows="left|right|top|bottom"
+ font="SansSerifBold"
+ height="85"
+ layout="topleft"
+ left="10"
+ name="caution_text_box"
+ text_color="1 0.82 0.46 1"
+ top="10"
+ visible="false"
+ width="285"
+ wrap="true"/>
+ <text_editor
+ h_pad="0"
+ v_pad="0"
+ bg_readonly_color="0.0 0.0 0.0 0"
+ border_visible="false"
+ embedded_items="false"
+ enabled="false"
+ follows="left|right|top|bottom"
+ font="SansSerif"
+ height="85"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="text_editor_box"
+ read_only="true"
+ tab_stop="false"
+ text_color="white"
+ text_readonly_color="white"
+ top="10"
+ visible="false"
+ width="285"
+ wrap="true"
+ parse_highlights="true"
+ allow_html="true"/>
+ </panel>
+ <panel
+ background_visible="false"
+ follows="left|right|bottom"
+ height="40"
+ label="control_panel"
+ layout="topleft"
+ left="0"
+ left_delta="-38"
+ name="control_panel"
+ top_pad="0">
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_notifications_channel.xml b/indra/newview/skins/default/xui/en/panel_notifications_channel.xml
new file mode 100644
index 0000000000..7b6c0f33da
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_notifications_channel.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ height="100"
+ layout="topleft"
+ name="notifications_panel"
+ width="100">
+ <layout_stack
+ follows="left|right|top|bottom"
+ height="78"
+ layout="topleft"
+ left="0"
+ name="stack1"
+ orientation="horizontal"
+ top="20"
+ width="100">
+ <scroll_list
+ draw_heading="true"
+ follows="left|right|top|bottom"
+ height="78"
+ layout="topleft"
+ left="0"
+ name="notifications_list"
+ sort_ascending="false"
+ sort_column="2"
+ top="-78"
+ user_resize="true"
+ width="100">
+ <scroll_list.columns
+ label="Name"
+ name="name"
+ width="100" />
+ <scroll_list.columns
+ label="Content"
+ name="content"
+ width="150" />
+ <scroll_list.columns
+ label="Date"
+ name="date"
+ width="150" />
+ </scroll_list>
+ <scroll_list
+ draw_heading="true"
+ follows="left|right|top|bottom"
+ height="78"
+ layout="topleft"
+ left="0"
+ name="notification_rejects_list"
+ sort_ascending="false"
+ sort_column="2"
+ top="-78"
+ user_resize="true"
+ width="100">
+ <scroll_list.columns
+ label="Name"
+ name="name"
+ width="100" />
+ <scroll_list.columns
+ label="Content"
+ name="content"
+ width="150" />
+ <scroll_list.columns
+ label="Date"
+ name="date"
+ width="150" />
+ </scroll_list>
+ </layout_stack>
+ <button
+ follows="left|right|top"
+ height="20"
+ is_toggle="true"
+ layout="topleft"
+ left_delta="0"
+ name="header"
+ top_delta="-20"
+ width="100" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
new file mode 100644
index 0000000000..710ca733e0
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+ <panel name="Outfits"
+ background_visible="true"
+ follows="all"
+ height="570"
+ label="Things"
+ layout="topleft"
+ min_height="350"
+ min_width="240"
+ width="320"
+ border="false">
+ <tab_container
+ follows="all"
+ height="500"
+ layout="topleft"
+ left="10"
+ name="appearance_tabs"
+ tab_min_width="140"
+ tab_height="30"
+ tab_position="top"
+ halign="center"
+ width="313">
+ <inventory_panel
+ background_visible="true"
+ background_opaque="true"
+ label="MY OUTFITS"
+ help_topic="my_outfits_tab"
+ allow_multi_select="true"
+ follows="all"
+ border="false"
+ left="0"
+ top="0"
+ width="314"
+ mouse_opaque="true"
+ name="outfitslist_tab"
+ start_folder="My Outfits" />
+ <inventory_panel
+ follows="all"
+ background_visible="true"
+ background_opaque="true"
+ label="WEARING"
+ help_topic="now_wearing_tab"
+ allow_multi_select="true"
+ border="false"
+ left="0"
+ top="0"
+ mouse_opaque="true"
+ name="cof_tab"
+ start_folder="Current Outfit"
+ width="313" />
+ </tab_container>
+ <panel
+ background_visible="true"
+ follows="bottom|left"
+ height="50"
+ layout="topleft"
+ left="0"
+ visible="true"
+ name="bottom_panel"
+ top_pad="10"
+ width="313">
+ <button
+ follows="bottom|left"
+ tool_tip="Show additional options"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ layout="topleft"
+ left="10"
+ name="options_gear_btn"
+ top="6"
+ width="18" />
+ <dnd_button
+ follows="bottom|left"
+ height="18"
+ image_selected="TrashItem_Press"
+ image_unselected="TrashItem_Off"
+ layout="topleft"
+ right="-5"
+ name="trash_btn"
+ tool_tip="Remove selected item"
+ top="6"
+ width="18" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Save Outfit"
+ layout="topleft"
+ name="make_outfit_btn"
+ tool_tip="Save appearance as an outfit"
+ top="26"
+ left='10'
+ width="120" />
+ <button
+ follows="bottom|right"
+ height="23"
+ label="Wear"
+ layout="topleft"
+ name="wear_btn"
+ right="-10"
+ left_pad="10"
+ top="26"
+ tool_tip="Wear selected outfit"
+ width="120" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="M"
+ layout="topleft"
+ right="-140"
+ name="look_edit_btn"
+ top="26"
+ visible="false"
+ width="20" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory_gear_default.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory_gear_default.xml
new file mode 100644
index 0000000000..2c7a51f0e7
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory_gear_default.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ bottom="806"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="menu_gear_default"
+ visible="false">
+ <menu_item_call
+ label="Replace Current Outfit"
+ layout="topleft"
+ name="wear">
+ <on_click
+ function="panel_outfits_inventory_gear_default.Custom.Action"
+ parameter="wear" />
+ <on_enable
+ function="panel_outfits_inventory_gear_default.Enable"
+ parameter="wear" />
+ </menu_item_call>
+ <menu_item_call
+ label="Remove From Current Outfit"
+ layout="topleft"
+ name="remove">
+ <on_click
+ function="panel_outfits_inventory_gear_default.Custom.Action"
+ parameter="remove" />
+ <on_enable
+ function="panel_outfits_inventory_gear_default.Enable"
+ parameter="remove" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"
+ name="Outfits Gear Separator" />
+ <menu_item_call
+ label="Rename"
+ layout="topleft"
+ name="rename">
+ <on_click
+ function="panel_outfits_inventory_gear_default.Custom.Action"
+ parameter="rename" />
+ <on_enable
+ function="panel_outfits_inventory_gear_default.Enable"
+ parameter="rename" />
+ </menu_item_call>
+ <menu_item_call
+ label="Remove Link"
+ layout="topleft"
+ name="remove_link">
+ <on_click
+ function="panel_outfits_inventory_gear_default.Custom.Action"
+ parameter="remove_link" />
+ <on_enable
+ function="panel_outfits_inventory_gear_default.Enable"
+ parameter="remove_link" />
+ </menu_item_call>
+ <menu_item_call
+ label="Delete Outfit"
+ layout="topleft"
+ name="delete">
+ <on_click
+ function="panel_outfits_inventory_gear_default.Custom.Action"
+ parameter="delete" />
+ <on_enable
+ function="panel_outfits_inventory_gear_default.Enable"
+ parameter="delete_outfit" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
new file mode 100644
index 0000000000..da3a2274c9
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -0,0 +1,425 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- Side tray panel -->
+<panel
+background_visible="true"
+ follows="all"
+ height="575"
+ label="People"
+ layout="topleft"
+ min_height="350"
+ name="people_panel"
+ top="0"
+ left="0"
+ width="333">
+ <string
+ name="no_people"
+ value="No people" />
+ <string
+ name="no_one_near"
+ value="No one near" />
+ <string
+ name="no_friends_online"
+ value="No friends online" />
+ <string
+ name="no_friends"
+ value="No friends" />
+ <string
+ name="no_groups"
+ value="No groups" />
+ <string
+ name="people_filter_label"
+ value="Filter People" />
+ <string
+ name="groups_filter_label"
+ value="Filter Groups" />
+ <filter_editor
+ follows="left|top|right"
+ height="23"
+ layout="topleft"
+ left="15"
+ label="Filter"
+ max_length="300"
+ name="filter_input"
+ text_color="Black"
+ top="3"
+ width="303" />
+ <tab_container
+ follows="all"
+ height="500"
+ layout="topleft"
+ left="10"
+ name="tabs"
+ tab_min_width="70"
+ tab_height="30"
+ tab_position="top"
+ top_pad="10"
+ halign="center"
+ width="313">
+ <panel
+ follows="all"
+ height="500"
+ label="NEARBY"
+ layout="topleft"
+ left="0"
+ help_topic="people_nearby_tab"
+ name="nearby_panel"
+ top="0"
+ width="313">
+ <avatar_list
+ allow_select="true"
+ follows="all"
+ height="470"
+ ignore_online_status="true"
+ layout="topleft"
+ left="0"
+ multi_select="true"
+ name="avatar_list"
+ top="0"
+ width="313" />
+ <panel
+ follows="left|right|bottom"
+ height="30"
+ label="bottom_panel"
+ layout="topleft"
+ left="0"
+ name="bottom_panel"
+ width="313">
+ <button
+ follows="bottom|left"
+ tool_tip="Options"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ layout="topleft"
+ left="10"
+ name="nearby_view_sort_btn"
+ top="5"
+ width="18" />
+ <button
+ follows="bottom|left"
+ height="18"
+ image_selected="AddItem_Press"
+ image_unselected="AddItem_Off"
+ image_disabled="AddItem_Disabled"
+ layout="topleft"
+ left_pad="5"
+ name="add_friend_btn"
+ top_delta="0"
+ tool_tip="Add selected Resident to your friends List"
+ width="18">
+ <commit_callback
+ function="People.addFriend" />
+ </button>
+ </panel>
+ </panel>
+ <panel
+ follows="all"
+ height="500"
+ label="FRIENDS"
+ layout="topleft"
+ left="0"
+ help_topic="people_friends_tab"
+ name="friends_panel"
+ top="0"
+ width="313">
+ <accordion
+ follows="all"
+ height="470"
+ layout="topleft"
+ left="0"
+ name="friends_accordion"
+ top="0"
+ width="313">
+ <accordion_tab
+ layout="topleft"
+ height="235"
+ min_height="150"
+ name="tab_online"
+ title="Online">
+ <avatar_list
+ allow_select="true"
+ follows="all"
+ layout="topleft"
+ left="0"
+ multi_select="true"
+ name="avatars_online"
+ top="0"
+ width="313" />
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ height="235"
+ name="tab_all"
+ title="All">
+ <avatar_list
+ allow_select="true"
+ follows="all"
+ layout="topleft"
+ left="0"
+ multi_select="true"
+ name="avatars_all"
+ top="0"
+ width="313" />
+ </accordion_tab>
+ </accordion>
+ <panel
+ follows="left|right|bottom"
+ height="30"
+ label="bottom_panel"
+ layout="topleft"
+ left="0"
+ name="bottom_panel"
+ width="313">
+ <button
+ follows="bottom|left"
+ tool_tip="Options"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ layout="topleft"
+ left="10"
+ name="friends_viewsort_btn"
+ top="5"
+ width="18" />
+ <button
+ follows="bottom|left"
+ height="18"
+ image_selected="AddItem_Press"
+ image_unselected="AddItem_Off"
+ image_disabled="AddItem_Disabled"
+ layout="topleft"
+ left_pad="5"
+ name="add_btn"
+ tool_tip="Offer friendship to a Resident"
+ top_delta="0"
+ width="18" />
+ <button
+ follows="bottom|left"
+ height="18"
+ image_selected="TrashItem_Press"
+ image_unselected="TrashItem_Off"
+ image_disabled="TrashItem_Disabled"
+ layout="topleft"
+ left_pad="10"
+ right="-10"
+ name="del_btn"
+ tool_tip="Remove selected person from your Friends list"
+ top_delta="0"
+ width="18" />
+ </panel>
+ </panel>
+ <panel
+ follows="all"
+ height="500"
+ label="GROUPS"
+ layout="topleft"
+ left="0"
+ help_topic="people_groups_tab"
+ name="groups_panel"
+ top="0"
+ width="313">
+ <group_list
+ follows="all"
+ height="470"
+ layout="topleft"
+ left="0"
+ name="group_list"
+ top="0"
+ width="313" />
+ <panel
+ top_pad="0"
+ follows="left|right|bottom"
+ height="30"
+ label="bottom_panel"
+ layout="topleft"
+ left="0"
+ name="bottom_panel"
+ width="313">
+ <button
+ follows="bottom|left"
+ tool_tip="Options"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ layout="topleft"
+ left="10"
+ name="groups_viewsort_btn"
+ top="7"
+ width="18" />
+ <button
+ follows="bottom|left"
+ height="18"
+ image_selected="AddItem_Press"
+ image_unselected="AddItem_Off"
+ image_disabled="AddItem_Disabled"
+ layout="topleft"
+ left_pad="5"
+ name="plus_btn"
+ tool_tip="Join group/Create new group"
+ top_delta="0"
+ width="18" />
+ <button
+ follows="bottom|left"
+ height="10"
+ image_hover_selected="Activate_Checkmark"
+ image_selected="Activate_Checkmark"
+ image_unselected="Activate_Checkmark"
+ layout="topleft"
+ left_pad="24"
+ name="activate_btn"
+ tool_tip="Activate selected group"
+ top_delta="5"
+ width="10" />
+ </panel>
+ </panel>
+ <panel
+ follows="all"
+ height="500"
+ label="RECENT"
+ layout="topleft"
+ left="0"
+ help_topic="people_recent_tab"
+ name="recent_panel"
+ top="0"
+ width="313">
+ <avatar_list
+ allow_select="true"
+ follows="all"
+ height="470"
+ layout="topleft"
+ left="0"
+ multi_select="true"
+ name="avatar_list"
+ show_last_interaction_time="true"
+ top="0"
+ width="313" />
+ <panel
+ top_pad="0"
+ follows="left|right|bottom"
+ height="30"
+ label="bottom_panel"
+ layout="topleft"
+ left="0"
+ name="bottom_panel"
+ width="313">
+ <button
+ follows="bottom|left"
+ tool_tip="Options"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ layout="topleft"
+ left="10"
+ name="recent_viewsort_btn"
+ top="7"
+ width="18" />
+ <button
+ follows="bottom|left"
+ height="18"
+ image_selected="AddItem_Press"
+ image_unselected="AddItem_Off"
+ image_disabled="AddItem_Disabled"
+ layout="topleft"
+ left_pad="5"
+ name="add_friend_btn"
+ top_delta="0"
+ tool_tip="Add selected Resident to your friends List"
+ width="18">
+ <commit_callback
+ function="People.addFriend" />
+ </button>
+ </panel>
+ </panel>
+ </tab_container>
+ <panel
+ follows="bottom|left"
+ height="35"
+ layout="topleft"
+ left="10"
+ name="button_bar"
+ width="313">
+ <button
+ follows="bottom|left"
+ top="4"
+ left="0"
+ height="23"
+ label="Profile"
+ layout="topleft"
+ name="view_profile_btn"
+ tool_tip="Show picture, groups, and other Residents information"
+ width="70" />
+ <button
+ follows="bottom|left"
+ top="4"
+ left_pad="2"
+ height="23"
+ label="IM"
+ layout="topleft"
+ name="im_btn"
+ tool_tip="Open instant message session"
+ width="45" />
+ <button
+ follows="bottom|left"
+ top="4"
+ left_pad="2"
+ height="23"
+ label="Call"
+ layout="topleft"
+ name="call_btn"
+ tool_tip="Call this Resident"
+ width="50" />
+ <button
+ follows="left|top"
+ top="4"
+ left_pad="2"
+ height="23"
+ label="Share"
+ layout="topleft"
+ name="share_btn"
+ width="60" />
+ <button
+ follows="bottom|left"
+ top="4"
+ left_pad="2"
+ height="23"
+ label="Teleport"
+ layout="topleft"
+ name="teleport_btn"
+ tool_tip="Offer teleport"
+ width="75" />
+ <button
+ follows="bottom|left"
+ top="4"
+ left="0"
+ height="23"
+ label="Group Profile"
+ layout="topleft"
+ name="group_info_btn"
+ tool_tip="Show group information"
+ width="102" />
+ <button
+ follows="bottom|left"
+ top="4"
+ left_pad="2"
+ height="23"
+ label="Group Chat"
+ layout="topleft"
+ name="chat_btn"
+ tool_tip="Open chat session"
+ width="102" />
+ <button
+ follows="bottom|left"
+ top="4"
+ left_pad="2"
+ height="23"
+ label="Group Call"
+ layout="topleft"
+ name="group_call_btn"
+ tool_tip="Call this group"
+ width="102" />
+ </panel>
+</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
new file mode 100644
index 0000000000..65ccd10cf0
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_pick_info.xml
@@ -0,0 +1,138 @@
+<?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|right"
+ height="23"
+ image_overlay="BackArrow_Off"
+ layout="topleft"
+ name="back_btn"
+ left="10"
+ tab_stop="false"
+ top="2"
+ width="23" />
+ <text
+ follows="top|left|right"
+ font="SansSerifHugeBold"
+ height="26"
+ layout="topleft"
+ left_pad="10"
+ name="title"
+ text_color="white"
+ top="0"
+ value="Pick Info"
+ use_ellipses="true"
+ width="275" />
+ <scroll_container
+ color="DkGray2"
+ opaque="true"
+ follows="all"
+ height="500"
+ layout="topleft"
+ left="10"
+ top_pad="5"
+ name="profile_scroll"
+ width="313">
+ <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
+ enabled="false"
+ follows="left|top|right"
+ height="197"
+ layout="topleft"
+ left="10"
+ name="pick_snapshot"
+ top="20"
+ width="280" />
+ <text
+ follows="left|top|right"
+ height="35"
+ width="280"
+ layout="topleft"
+ font="SansSerifBig"
+ font.style="BOLD"
+ left="10"
+ top_pad="10"
+ name="pick_name"
+ text_color="white"
+ value="[name]"
+ use_ellipses="true" />
+ <text
+ follows="left|top|right"
+ height="25"
+ layout="topleft"
+ left="10"
+ name="pick_location"
+ width="280"
+ word_wrap="true"
+ value="[loading...]" />
+ <text_editor
+ bg_readonly_color="DkGray2"
+ follows="all"
+ height="100"
+ width="280"
+ hide_scrollbar="false"
+ 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="35"
+ layout="topleft"
+ top_pad="8"
+ left="10"
+ name="buttons">
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Teleport"
+ layout="topleft"
+ left="0"
+ name="teleport_btn"
+ top="0"
+ width="90" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Map"
+ layout="topleft"
+ left_pad="10"
+ name="show_on_map_btn"
+ top="0"
+ width="90" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Edit"
+ layout="topleft"
+ right="-1"
+ name="edit_btn"
+ top="0"
+ width="90" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_pick_list_item.xml b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml
new file mode 100644
index 0000000000..023b1fc81d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ bevel_style="none"
+ follows="top|left|right"
+ height="85"
+ layout="topleft"
+ left="0"
+ name="picture_item"
+ top="0"
+ width="313">
+ <icon
+ follows="all"
+ height="85"
+ image_name="ListItem_Over"
+ right="-2"
+ mouse_opaque="false"
+ name="hovered_icon"
+ top="1"
+ scale_image="true"
+ visible="false"
+ width="308" />
+ <icon
+ follows="all"
+ height="85"
+ image_name="ListItem_Select"
+ right="-2"
+ mouse_opaque="false"
+ name="selected_icon"
+ top="1"
+ scale_image="true"
+ visible="false"
+ width="308" />
+ <texture_picker
+ allow_no_texture="true"
+ border_enabled="true"
+ default_image_name="TabIcon_Places_Large"
+ enabled="false"
+ follows="left|top"
+ height="80"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="picture"
+ tab_stop="false"
+ top="10"
+ top_pad="10"
+ width="90" />
+ <text
+ follows="top|left|right"
+ font="SansSerifSmall"
+ height="15"
+ layout="topleft"
+ left="110"
+ name="picture_name"
+ text_color="white"
+ top="9"
+ use_ellipses="true"
+ width="193"
+ word_wrap="false" />
+ <expandable_text
+ follows="top|left|right"
+ font="SansSerifSmall"
+ height="55"
+ layout="topleft"
+ left="103"
+ name="picture_descr"
+ top_pad="0"
+ width="178"
+ word_wrap="true" />
+ <button
+ follows="right"
+ height="20"
+ image_overlay="ForwardArrow_Off"
+ layout="topleft"
+ left_pad="5"
+ right="-8"
+ name="info_chevron"
+ top_delta="15"
+ width="20" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_picks.xml b/indra/newview/skins/default/xui/en/panel_picks.xml
new file mode 100644
index 0000000000..d31f4d039f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_picks.xml
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="all"
+ height="540"
+ label="Picks"
+ layout="topleft"
+ left="0"
+ name="panel_picks"
+ top="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"
+ top="10"
+ width="313"/>
+ <accordion
+ fit_parent="true"
+ follows="all"
+ height="465"
+ layout="topleft"
+ left="0"
+ name="accordion"
+ top="0"
+ single_expansion="true"
+ width="313">
+ <accordion_tab
+ can_resize="false"
+ 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
+ can_resize="false"
+ 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
+ background_visible="true"
+ bevel_style="none"
+ enabled="false"
+ auto_resize="false"
+ follows="bottom"
+ left="0"
+ height="18"
+ label="bottom_panel"
+ layout="topleft"
+ name="edit_panel"
+ top_pad="0"
+ width="313">
+ <button
+ enabled="false"
+ follows="bottom|left"
+ height="18"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ image_disabled="OptionsMenu_Disabled"
+ layout="topleft"
+ left="0"
+ name="gear_menu_btn"
+ top="5"
+ width="18" />
+ <button
+ follows="bottom|left"
+ height="18"
+ image_disabled="AddItem_Disabled"
+ image_selected="AddItem_Press"
+ image_unselected="AddItem_Off"
+ layout="topleft"
+ left_pad="15"
+ name="new_btn"
+ tool_tip="Create a new pick or classified at the current location"
+ top="5"
+ 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"
+ right="-10"
+ top="5"
+ width="18" />
+ </panel>
+ <panel
+ layout="topleft"
+ left="0"
+ height="30"
+ top_pad="10"
+ name="buttons_cucks"
+ width="313">
+ <button
+ enabled="false"
+ follows="bottom|left"
+ height="23"
+ label="Info"
+ layout="topleft"
+ left="5"
+ name="info_btn"
+ tab_stop="false"
+ tool_tip="Show pick information"
+ top="0"
+ width="55" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ height="23"
+ label="Teleport"
+ layout="topleft"
+ left_pad="5"
+ name="teleport_btn"
+ tab_stop="false"
+ tool_tip="Teleport to the corresponding area"
+ top="0"
+ width="77" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ height="23"
+ label="Map"
+ layout="topleft"
+ left_pad="5"
+ name="show_on_map_btn"
+ tab_stop="false"
+ tool_tip="Show the corresponding area on the World Map"
+ top="0"
+ width="50" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_place_profile.xml b/indra/newview/skins/default/xui/en/panel_place_profile.xml
new file mode 100644
index 0000000000..8fc2ae39f0
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml
@@ -0,0 +1,929 @@
+<?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="place_profile"
+ top="20"
+ width="330">
+ <string
+ name="on"
+ value="On" />
+ <string
+ name="off"
+ value="Off" />
+ <string
+ name="anyone"
+ value="Anyone" />
+ <string
+ name="available"
+ value="available" />
+ <string
+ name="allocated"
+ value="allocated" />
+ <string
+ name="title_place"
+ value="Place Profile" />
+ <string
+ name="title_teleport_history"
+ value="Teleport History Location" />
+ <string
+ name="not_available"
+ value="(N\A)" />
+ <string
+ name="unknown"
+ value="(unknown)" />
+ <string
+ name="public"
+ value="(public)" />
+ <string
+ name="none_text"
+ value="(none)" />
+ <string
+ name="sale_pending_text"
+ value="(Sale Pending)" />
+ <string
+ name="group_owned_text"
+ value="(Group Owned)" />
+ <string
+ name="price_text"
+ value="L$" />
+ <string
+ name="area_text"
+ value="m²" />
+ <string
+ name="all_residents_text"
+ value="All Residents" />
+ <string
+ name="group_text"
+ value="Group" />
+ <string
+ name="can_resell">
+ Purchased land in this region may be resold.
+ </string>
+ <string
+ name="can_not_resell">
+ Purchased land in this region may not be resold.
+ </string>
+ <string
+ name="can_change">
+ Purchased land in this region may be joined or subdivided.
+ </string>
+ <string
+ name="can_not_change">
+ Purchased land in this region may not be joined or subdivided.
+ </string>
+ <string
+ name="server_update_text">
+ Place information not available without server update.
+ </string>
+ <string
+ name="server_error_text">
+ Information about this location is unavailable at this time, please try again later.
+ </string>
+ <string
+ name="server_forbidden_text">
+ Information about this location is unavailable due to access restrictions. Please check your permissions with the parcel owner.
+ </string>
+ <string
+ name="acquired_date">
+ [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+ </string>
+ <!-- Texture names for parcel permissions icons -->
+ <string
+ name="icon_PG"
+ value="Parcel_PG_Dark" />
+ <string
+ name="icon_M"
+ value="Parcel_M_Dark" />
+ <string
+ name="icon_R"
+ value="Parcel_R_Dark" />
+ <string
+ name="icon_Voice"
+ value="Parcel_Voice_Dark" />
+ <string
+ name="icon_VoiceNo"
+ value="Parcel_VoiceNo_Dark" />
+ <string
+ name="icon_Fly"
+ value="Parcel_Fly_Dark" />
+ <string
+ name="icon_FlyNo"
+ value="Parcel_FlyNo_Dark" />
+ <string
+ name="icon_Push"
+ value="Parcel_Push_Dark" />
+ <string
+ name="icon_PushNo"
+ value="Parcel_PushNo_Dark" />
+ <string
+ name="icon_Build"
+ value="Parcel_Build_Dark" />
+ <string
+ name="icon_BuildNo"
+ value="Parcel_BuildNo_Dark" />
+ <string
+ name="icon_Scripts"
+ value="Parcel_Scripts_Dark" />
+ <string
+ name="icon_ScriptsNo"
+ value="Parcel_ScriptsNo_Dark" />
+ <string
+ name="icon_Damage"
+ value="Parcel_Damage_Dark" />
+ <string
+ name="icon_DamageNo"
+ value="Parcel_DamageNo_Dark" />
+ <button
+ follows="top|right"
+ height="23"
+ image_overlay="BackArrow_Off"
+ layout="topleft"
+ left="10"
+ name="back_btn"
+ tool_tip="Back"
+ tab_stop="false"
+ top="0"
+ width="23" />
+ <text
+ follows="top|left|right"
+ font="SansSerifHugeBold"
+ height="26"
+ layout="topleft"
+ left_pad="10"
+ name="title"
+ text_color="white"
+ top="0"
+ use_ellipses="true"
+ value="Place Profile"
+ width="275" />
+ <scroll_container
+ color="DkGray2"
+ follows="all"
+ height="533"
+ layout="topleft"
+ left="10"
+ name="place_scroll"
+ opaque="true"
+ top_pad="5"
+ width="313">
+ <panel
+ bg_alpha_color="DkGray2"
+ follows="left|top|right"
+ height="533"
+ layout="topleft"
+ left="0"
+ min_height="300"
+ name="scrolling_panel"
+ top="0"
+ width="313">
+ <texture_picker
+ enabled="false"
+ follows="top|left"
+ height="190"
+ layout="topleft"
+ left="10"
+ name="logo"
+ top="10"
+ width="290" />
+ <layout_stack
+ border_size="0"
+ clip="false"
+ follows="left|top|right"
+ height="50"
+ layout="topleft"
+ mouse_opaque="false"
+ name="panel_stack"
+ orientation="horizontal"
+ top_pad="-65"
+ width="100">
+ <layout_panel
+ follows="left|right"
+ height="50"
+ layout="topleft"
+ left="0"
+ min_height="50"
+ min_width="50"
+ mouse_opaque="false"
+ name="here_panel"
+ top="0"
+ user_resize="false"
+ width="60">
+ <icon
+ follows="top|left"
+ height="50"
+ image_name="YouAreHere_Badge"
+ layout="topleft"
+ left="0"
+ name="icon_you_are_here"
+ top="0"
+ width="50" />
+ </layout_panel>
+ <layout_panel
+ follows="left|right"
+ height="60"
+ layout="topleft"
+ min_height="50"
+ min_width="60"
+ mouse_opaque="false"
+ name="for_sale_panel"
+ top="0"
+ user_resize="false"
+ width="60">
+ <icon
+ follows="top|left"
+ height="50"
+ image_name="ForSale_Badge"
+ layout="topleft"
+ left="10"
+ name="icon_for_sale"
+ top="0"
+ width="50" />
+ </layout_panel>
+ </layout_stack>
+ <text
+ follows="left|top|right"
+ font="SansSerifLarge"
+ height="14"
+ layout="topleft"
+ left="10"
+ name="region_title"
+ text_color="white"
+ top_pad="5"
+ use_ellipses="true"
+ value="SampleRegion"
+ width="290" />
+ <text
+ follows="left|top|right"
+ height="14"
+ layout="topleft"
+ left="10"
+ name="parcel_title"
+ top_pad="4"
+ use_ellipses="true"
+ value="SampleParcel, Name Long (145, 228, 26)"
+ width="285" />
+ <expandable_text
+ follows="left|top|right"
+ height="50"
+ layout="topleft"
+ left="5"
+ name="description"
+ top_pad="10"
+ value="Du waltz die spritz"
+ width="300" />
+ <text
+ follows="left|top"
+ height="14"
+ layout="topleft"
+ left="10"
+ name="owner_label"
+ text_color="White"
+ top_pad="0"
+ value="Owner:"
+ width="90" />
+ <!--TODO: HOOK THIS NAME UP WITH AN INSPECTOR -->
+ <text
+ follows="left|top|right"
+ height="14"
+ layout="topleft"
+ left_pad="1"
+ name="owner_value"
+ top_delta="0"
+ value="Alex Superduperlongenamenton"
+ width="205" />
+ <icon
+ follows="top|left"
+ height="16"
+ image_name="unknown"
+ layout="topleft"
+ left="10"
+ name="maturity_icon"
+ top_delta="0"
+ width="18" />
+ <text
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_pad="8"
+ name="maturity_value"
+ top_delta="0"
+ value="unknown"
+ width="268" />
+ <accordion
+ follows="all"
+ height="230"
+ layout="topleft"
+ left="0"
+ name="advanced_info_accordion"
+ top_pad="10"
+ width="313">
+ <accordion_tab
+ layout="topleft"
+ name="parcel_characteristics_tab"
+ title="Parcel">
+ <panel
+ follows="all"
+ height="160"
+ layout="topleft"
+ left="0"
+ top="0"
+ width="275">
+ <icon
+ follows="top|left"
+ height="16"
+ image_name="Parcel_PG_Dark"
+ layout="topleft"
+ left="10"
+ name="rating_icon"
+ top="0"
+ width="18" />
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="12"
+ name="rating_label"
+ value="Rating:"
+ width="60" />
+ <text
+ follows="left|right|top"
+ height="16"
+ layout="topleft"
+ left_pad="0"
+ name="rating_value"
+ top_delta="0"
+ value="unknown"
+ width="60" />
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="Parcel_Voice_Dark"
+ layout="topleft"
+ left="10"
+ name="voice_icon"
+ top_pad="5"
+ width="22" />
+ <text
+ follows="left|top"
+ height="18"
+ layout="topleft"
+ left_pad="8"
+ name="voice_label"
+ top_delta="0"
+ value="Voice:"
+ width="60" />
+ <text
+ follows="left|right|top"
+ height="18"
+ layout="topleft"
+ left_pad="0"
+ name="voice_value"
+ top_delta="0"
+ value="On"
+ width="60" />
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="Parcel_Fly_Dark"
+ layout="topleft"
+ left="10"
+ name="fly_icon"
+ top_pad="3"
+ width="22" />
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="8"
+ name="fly_label"
+ value="Fly:"
+ width="60" />
+ <text
+ follows="left|right|top"
+ height="16"
+ layout="topleft"
+ left_pad="0"
+ name="fly_value"
+ top_delta="0"
+ value="On"
+ width="60" />
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="Parcel_Push_Dark"
+ layout="topleft"
+ left="10"
+ name="push_icon"
+ top_pad="3"
+ width="22" />
+ <text
+ follows="left|top"
+ height="14"
+ layout="topleft"
+ left_pad="8"
+ name="push_label"
+ value="Push:"
+ width="60" />
+ <text
+ follows="left|right|top"
+ height="14"
+ layout="topleft"
+ left_pad="0"
+ name="push_value"
+ top_delta="0"
+ value="Off"
+ width="60" />
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="Parcel_Build_Dark"
+ layout="topleft"
+ left="10"
+ name="build_icon"
+ top_pad="3"
+ width="22" />
+ <text
+ follows="left|top"
+ height="14"
+ layout="topleft"
+ left_pad="8"
+ name="build_label"
+ value="Build:"
+ width="60" />
+ <text
+ follows="left|right|top"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="build_value"
+ top_delta="0"
+ value="On"
+ width="60" />
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="Parcel_Scripts_Dark"
+ layout="topleft"
+ left="10"
+ name="scripts_icon"
+ top_pad="3"
+ width="22" />
+ <text
+ follows="left|top"
+ height="14"
+ layout="topleft"
+ left_pad="8"
+ name="scripts_label"
+ value="Scripts:"
+ width="60" />
+ <text
+ follows="left|right|top"
+ height="14"
+ layout="topleft"
+ left_pad="0"
+ name="scripts_value"
+ top_delta="0"
+ value="On"
+ width="60" />
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="Parcel_Damage_Dark"
+ layout="topleft"
+ left="10"
+ name="damage_icon"
+ top_pad="7"
+ width="22" />
+ <text
+ follows="left|top"
+ height="14"
+ layout="topleft"
+ left_pad="8"
+ name="damage_label"
+ value="Damage:"
+ width="60" />
+ <text
+ follows="left|right|top"
+ height="14"
+ layout="topleft"
+ left_pad="0"
+ name="damage_value"
+ top_delta="0"
+ value="Off"
+ width="60" />
+ <button
+ follows="bottom|right"
+ height="23"
+ label="About Land"
+ layout="topleft"
+ name="about_land_btn"
+ right="-5"
+ tab_stop="false"
+ top="138"
+ width="90">
+ <click_callback
+ function="Floater.Show"
+ parameter="about_land" />
+ </button>
+ </panel>
+ </accordion_tab>
+ <accordion_tab
+ expanded="false"
+ layout="topleft"
+ name="region_information_tab"
+ title="Region">
+ <panel
+ follows="all"
+ height="125"
+ layout="topleft"
+ left="0"
+ top="0"
+ width="290">
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="region_name_label"
+ top_pad="5"
+ value="Region:"
+ width="90" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="region_name"
+ top_delta="0"
+ value="Mooseland"
+ width="187" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="region_type_label"
+ top_pad="5"
+ value="Type:"
+ width="90" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="region_type"
+ top_delta="0"
+ value="Moose"
+ width="187" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="region_rating_label"
+ top_pad="7"
+ value="Rating:"
+ width="90" />
+ <icon
+ follows="top|left"
+ height="16"
+ image_name="Parcel_PG_Dark"
+ layout="topleft"
+ left_pad="0"
+ name="region_rating_icon"
+ width="18" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left_pad="10"
+ name="region_rating"
+ value="Adult"
+ width="159" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="region_owner_label"
+ top_pad="5"
+ value="Owner:"
+ width="90" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="region_owner"
+ top_delta="0"
+ value="moose Van Moose"
+ width="187" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="region_group_label"
+ top_pad="5"
+ value="Group:"
+ width="90" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="region_group"
+ top_delta="0"
+ use_ellipses="true"
+ width="187">
+ The Mighty Moose of mooseville soundvillemoose
+ </text>
+ <button
+ follows="bottom|right"
+ height="23"
+ label="Region/Estate"
+ layout="topleft"
+ name="region_info_btn"
+ right="-5"
+ tab_stop="false"
+ width="105">
+ <click_callback
+ function="Floater.Show"
+ parameter="region_info" />
+ </button>
+ </panel>
+ </accordion_tab>
+ <accordion_tab
+ expanded="false"
+ layout="topleft"
+ name="estate_information_tab"
+ title="Estate">
+ <panel
+ follows="all"
+ height="189"
+ layout="topleft"
+ left="0"
+ top="0"
+ width="290">
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="estate_name_label"
+ top_pad="5"
+ value="Estate:"
+ width="90" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="estate_name"
+ top_delta="0"
+ width="187" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="estate_rating_label"
+ top_pad="5"
+ value="Rating:"
+ width="90" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="estate_rating"
+ top_delta="0"
+ width="187" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="estate_owner_label"
+ top_pad="5"
+ value="Owner:"
+ width="90" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="estate_owner"
+ top_delta="0"
+ width="187" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="covenant_label"
+ top_pad="5"
+ value="Covenant:"
+ width="277" />
+ <text_editor
+ bg_focus_color="DkGray2"
+ bg_readonly_color="DkGray2"
+ follows="left|top|right"
+ handle_edit_keys_directly="true"
+ height="90"
+ layout="topleft"
+ left="10"
+ max_length="65535"
+ name="covenant"
+ read_only="true"
+ top_pad="0"
+ width="277"
+ word_wrap="true" />
+ </panel>
+ </accordion_tab>
+ <accordion_tab
+ expanded="false"
+ layout="topleft"
+ name="sales_tab"
+ title="For Sale">
+ <panel
+ follows="all"
+ height="300"
+ layout="topleft"
+ left="0"
+ top="0"
+ width="290">
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="sales_price_label"
+ top_pad="5"
+ value="Price:"
+ width="90" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="sales_price"
+ top_delta="0"
+ width="187" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="area_label"
+ top_pad="5"
+ value="Area:"
+ width="90" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="area"
+ top_delta="0"
+ width="187" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="traffic_label"
+ top_pad="5"
+ value="Traffic:"
+ width="90" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="traffic"
+ top_delta="0"
+ width="187" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="primitives_label"
+ top_pad="5"
+ value="Primitives:"
+ width="90" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="primitives"
+ top_delta="0"
+ width="187" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="parcel_scripts_label"
+ top_pad="5"
+ value="Scripts:"
+ width="90" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="parcel_scripts"
+ top_delta="0"
+ width="187" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="terraform_limits_label"
+ top_pad="5"
+ value="Terraform limits:"
+ width="90" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="terraform_limits"
+ top_delta="0"
+ width="187" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="subdivide_label"
+ top_pad="5"
+ value="Subdivide/Join ability:"
+ width="277" />
+ <text_editor
+ bg_focus_color="DkGray2"
+ bg_readonly_color="DkGray2"
+ follows="left|top|right"
+ height="45"
+ layout="topleft"
+ left="10"
+ max_length="65535"
+ name="subdivide"
+ read_only="true"
+ top_pad="5"
+ width="277"
+ word_wrap="true" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="resale_label"
+ top_pad="5"
+ value="ReSale ability:"
+ width="277" />
+ <text_editor
+ bg_focus_color="DkGray2"
+ bg_readonly_color="DkGray2"
+ follows="left|top|right"
+ height="45"
+ layout="topleft"
+ left="10"
+ max_length="65535"
+ name="resale"
+ read_only="true"
+ top_pad="5"
+ width="277"
+ word_wrap="true" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="sale_to_label"
+ top_pad="5"
+ value="For sale to:"
+ width="90" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="sale_to"
+ top_delta="0"
+ width="187" />
+ </panel>
+ </accordion_tab>
+ </accordion>
+ </panel>
+ </scroll_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml
new file mode 100644
index 0000000000..9bfd8b91d8
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_places.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+background_visible="true"
+ follows="all"
+ height="570"
+ label="Places"
+ layout="topleft"
+ min_height="350"
+ name="places panel"
+ top="0"
+ left="0"
+ width="333">
+ <string
+ name="landmarks_tab_title"
+ value="MY LANDMARKS" />
+ <string
+ name="teleport_history_tab_title"
+ value="TELEPORT HISTORY" />
+ <filter_editor
+ follows="left|top|right"
+ font="SansSerif"
+ height="23"
+ layout="topleft"
+ left="15"
+ label="Filter Places"
+ max_length="300"
+ name="Filter"
+ top="3"
+ width="303" />
+ <tab_container
+ follows="all"
+ halign="center"
+ height="500"
+ layout="topleft"
+ left="10"
+ name="Places Tabs"
+ tab_min_width="80"
+ tab_height="30"
+ tab_position="top"
+ top_pad="10"
+ width="313" />
+ <panel
+ class="panel_place_profile"
+ filename="panel_place_profile.xml"
+ follows="all"
+ height="533"
+ layout="topleft"
+ left="0"
+ help_topic="place_profile"
+ name="panel_place_profile"
+ top="5"
+ visible="false"
+ width="313" />
+ <panel
+ class="panel_landmark_info"
+ filename="panel_landmark_info.xml"
+ follows="all"
+ height="533"
+ layout="topleft"
+ left="0"
+ help_topic="landmark"
+ name="panel_landmark_info"
+ top="5"
+ visible="false"
+ width="313" />
+ <panel
+ height="19"
+ layout="topleft"
+ left="0"
+ name="button_panel"
+ width="313">
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Teleport"
+ layout="topleft"
+ left="5"
+ name="teleport_btn"
+ tool_tip="Teleport to the selected area"
+ top="0"
+ width="100" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Map"
+ layout="topleft"
+ left_pad="5"
+ name="map_btn"
+ top="0"
+ width="70" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Edit"
+ layout="topleft"
+ left_pad="5"
+ name="edit_btn"
+ tool_tip="Edit landmark information"
+ top="0"
+ width="70" />
+ <button
+ follows="bottom|right"
+ height="23"
+ image_disabled="ForwardArrow_Off"
+ image_selected="ForwardArrow_Press"
+ image_unselected="ForwardArrow_Off"
+ layout="topleft"
+ name="overflow_btn"
+ tool_tip="Show additional options"
+ right="-10"
+ top="0"
+ width="18" />
+ <button
+ follows="bottom|right"
+ height="23"
+ label="Close"
+ layout="topleft"
+ name="close_btn"
+ right="-10"
+ top="0"
+ width="60" />
+ <button
+ follows="bottom|right"
+ height="23"
+ label="Cancel"
+ layout="topleft"
+ name="cancel_btn"
+ right="-10"
+ top="0"
+ width="60" />
+ <button
+ follows="bottom|right"
+ height="23"
+ label="Save"
+ layout="topleft"
+ name="save_btn"
+ right="-75"
+ top="0"
+ width="60" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
new file mode 100644
index 0000000000..141678f7eb
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
@@ -0,0 +1,333 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<panel
+ border="true"
+ follows="left|top|right|bottom"
+ height="408"
+ layout="topleft"
+ left="102"
+ name="advanced"
+ top="1"
+ width="517">
+ <panel.string
+ name="aspect_ratio_text">
+ [NUM]:[DEN]
+ </panel.string>
+ <check_box
+ control_name="UseChatBubbles"
+ follows="left|top"
+ height="16"
+ label="Bubble chat"
+ layout="topleft"
+ left="30"
+ top="10"
+ name="bubble_text_chat"
+ width="150" />
+ <color_swatch
+ can_apply_immediately="true"
+ color="0 0 0 1"
+ control_name="BackgroundChatColor"
+ follows="left|top"
+ height="47"
+ layout="topleft"
+ left_delta="280"
+ name="background"
+ tool_tip="Choose color for bubble chat"
+ top_delta="1"
+ width="44">
+ <color_swatch.init_callback
+ function="Pref.getUIColor"
+ parameter="BackgroundChatColor" />
+ <color_swatch.commit_callback
+ function="Pref.applyUIColor"
+ parameter="BackgroundChatColor" />
+ </color_swatch>
+ <slider
+ control_name="ChatBubbleOpacity"
+ follows="left|top"
+ height="16"
+ increment="0.05"
+ initial_value="1"
+ label="Opacity"
+ layout="topleft"
+ left_delta="-230"
+ top_pad="-28"
+ label_width="50"
+ name="bubble_chat_opacity"
+ width="200" />
+ <text
+ follows="left|top"
+ type="string"
+ length="1"
+ height="25"
+ layout="topleft"
+ left="30"
+ top_pad="5"
+ name="AspectRatioLabel1"
+ tool_tip="width / height"
+ label_width="50"
+ width="120">
+ Aspect ratio
+ </text>
+ <combo_box
+ allow_text_entry="true"
+ height="23"
+ follows="left|top"
+ layout="topleft"
+ left_pad="0"
+ max_chars="100"
+ name="aspect_ratio"
+ tool_tip="width / height"
+ top_delta="0"
+ width="150">
+ <combo_box.item
+ enabled="true"
+ label=" 4:3 (Standard CRT)"
+ name="item1"
+ value="1.333333" />
+ <combo_box.item
+ enabled="true"
+ label=" 5:4 (1280x1024 LCD)"
+ name="item2"
+ value="1.25" />
+ <combo_box.item
+ enabled="true"
+ label=" 8:5 (Widescreen)"
+ name="item3"
+ value="1.6" />
+ <combo_box.item
+ enabled="true"
+ label=" 16:9 (Widescreen)"
+ name="item4"
+ value="1.7777777" />
+ </combo_box>
+ <check_box
+ control_name="FullScreenAutoDetectAspectRatio"
+ follows="left|top"
+ height="25"
+ label="Auto-detect"
+ layout="topleft"
+ left_pad="10"
+ name="aspect_auto_detect"
+ width="256">
+ <check_box.commit_callback
+ function="Pref.AutoDetectAspect" />
+ </check_box>
+ <text
+ follows="left|top"
+ type="string"
+ length="1"
+ height="10"
+ left="30"
+ name="heading1"
+ top_pad="5"
+ width="270">
+Camera:
+ </text>
+ <slider
+ can_edit_text="true"
+ control_name="CameraAngle"
+ decimal_digits="2"
+ top_pad="5"
+ follows="left|top"
+ height="16"
+ increment="0.025"
+ initial_value="1.57"
+ layout="topleft"
+ label_width="100"
+ label="View Angle"
+ left_delta="50"
+ max_val="2.97"
+ min_val="0.17"
+ name="camera_fov"
+ show_text="false"
+ width="240" />
+ <slider
+ can_edit_text="true"
+ control_name="CameraOffsetScale"
+ decimal_digits="2"
+ follows="left|top"
+ height="16"
+ increment="0.025"
+ initial_value="1"
+ layout="topleft"
+ label="Distance"
+ left_delta="0"
+ label_width="100"
+ max_val="3"
+ min_val="0.5"
+ name="camera_offset_scale"
+ show_text="false"
+ width="240"
+ top_pad="5"/>
+ <text
+ follows="left|top"
+ type="string"
+ length="1"
+ height="10"
+ left="30"
+ name="heading2"
+ width="270"
+ top_pad="5">
+Automatic positioning for:
+ </text>
+ <check_box
+ control_name="EditCameraMovement"
+ height="20"
+ follows="left|top"
+ label="Build/Edit"
+ layout="topleft"
+ left_delta="50"
+ name="edit_camera_movement"
+ tool_tip="Use automatic camera positioning when entering and exiting edit mode"
+ width="280"
+ top_pad="5" />
+ <check_box
+ control_name="AppearanceCameraMovement"
+ follows="left|top"
+ height="16"
+ label="Appearance"
+ layout="topleft"
+ name="appearance_camera_movement"
+ tool_tip="Use automatic camera positioning while in edit mode"
+ width="242" />
+ <text
+ follows="left|top"
+ type="string"
+ length="1"
+ height="10"
+ left="30"
+ name="heading3"
+ top_pad="5"
+ width="270">
+Avatars:
+ </text>
+ <check_box
+ control_name="FirstPersonAvatarVisible"
+ follows="left|top"
+ height="20"
+ label="Show me in Mouselook"
+ layout="topleft"
+ left_delta="50"
+ name="first_person_avatar_visible"
+ width="256"
+ top_pad="0"/>
+ <check_box
+ control_name="ArrowKeysAlwaysMove"
+ follows="left|top"
+ height="20"
+ label="Arrow keys always move me"
+ layout="topleft"
+ left_delta="0"
+ name="arrow_keys_move_avatar_check"
+ width="237"
+ top_pad="0"/>
+ <check_box
+ control_name="AllowTapTapHoldRun"
+ follows="left|top"
+ height="20"
+ label="Tap-tap-hold to run"
+ layout="topleft"
+ left_delta="0"
+ name="tap_tap_hold_to_run"
+ width="237"
+ top_pad="0"/>
+ <check_box
+ control_name="LipSyncEnabled"
+ follows="left|top"
+ height="20"
+ label="Move avatar lips when speaking"
+ layout="topleft"
+ left_delta="0"
+ name="enable_lip_sync"
+ width="237"
+ top_pad="0" />
+ <check_box
+ control_name="ShowScriptErrors"
+ follows="left|top"
+ height="20"
+ label="Show script errors"
+ layout="topleft"
+ left="30"
+ name="show_script_errors"
+ width="256"
+ top_pad="5"/>
+ <radio_group
+ enabled_control="ShowScriptErrors"
+ control_name="ShowScriptErrorsLocation"
+ follows="top|left"
+ draw_border="false"
+ height="40"
+ layout="topleft"
+ left_delta="50"
+ name="show_location"
+ top_pad="5"
+ width="364">
+ <radio_item
+ height="16"
+ label="In chat"
+ layout="topleft"
+ left="3"
+ name="0"
+ top="0"
+ width="315" />
+ <radio_item
+ height="16"
+ label="In a window"
+ layout="topleft"
+ left_delta="175"
+ name="1"
+ top_delta="0"
+ width="315" />
+ </radio_group>
+ <check_box
+ follows="top|left"
+ enabled_control="EnableVoiceChat"
+ control_name="PushToTalkToggle"
+ height="20"
+ label="Toggle mode for microphone when I press the Speak trigger key:"
+ layout="topleft"
+ left="30"
+ name="push_to_talk_toggle_check"
+ width="237"
+ top_pad="-25"
+ tool_tip="When in toggle mode, press and release the trigger key ONCE to switch your microphone on or off. When not in toggle mode, the microphone broadcasts your voice only while the trigger is being held down."/>
+ <line_editor
+ follows="top|left"
+ control_name="PushToTalkButton"
+ enabled="false"
+ enabled_control="EnableVoiceChat"
+ height="19"
+ left_delta="50"
+ max_length="254"
+ name="modifier_combo"
+ label="Push-to-Speak trigger"
+ top_pad="0"
+ width="280" />
+ <button
+ follows="top|left"
+ enabled_control="EnableVoiceChat"
+ height="23"
+ label="Set Key"
+ left_delta="0"
+ name="set_voice_hotkey_button"
+ width="115"
+ top_pad="5">
+ <button.commit_callback
+ function="Pref.VoiceSetKey" />
+ </button>
+ <button
+ bottom_delta="0"
+ enabled_control="EnableVoiceChat"
+ follows="left"
+ halign="center"
+ height="23"
+ label="Middle Mouse Button"
+ left_delta="120"
+ mouse_opaque="true"
+ name="set_voice_middlemouse_button"
+ width="160">
+ <button.commit_callback
+ function="Pref.VoiceSetMiddleMouse" />
+ </button>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_alerts.xml b/indra/newview/skins/default/xui/en/panel_preferences_alerts.xml
new file mode 100644
index 0000000000..ace8281b4e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_preferences_alerts.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ height="500"
+ label="Popups"
+ layout="topleft"
+ left="0"
+ name="popups"
+ top="500"
+ width="517">
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ height="12"
+ layout="topleft"
+ left="30"
+ name="tell_me_label"
+ top="10"
+ width="300">
+ Tell me:
+ </text>
+ <check_box
+ control_name="NotifyMoneyChange"
+ height="16"
+ label="When I spend or get L$"
+ layout="topleft"
+ left_delta="50"
+ name="notify_money_change_checkbox"
+ top_pad="4"
+ width="300" />
+ <check_box
+ control_name="ChatOnlineNotification"
+ height="16"
+ label="When my friends log out or in"
+ layout="topleft"
+ left_delta="0"
+ name="friends_online_notify_checkbox"
+ top_pad="4"
+ width="300" />
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifBold"
+ height="12"
+ layout="topleft"
+ left="30"
+ name="show_label"
+ top_pad="14"
+ width="450">
+ Always show these notifications:
+ </text>
+ <scroll_list
+ follows="top|left"
+ height="92"
+ layout="topleft"
+ left="10"
+ multi_select="true"
+ name="enabled_popups"
+ width="475" />
+ <button
+ enabled_control="FirstSelectedDisabledPopups"
+ follows="top|left"
+ height="23"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_overlay="Arrow_Up"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ layout="topleft"
+ left_delta="137"
+ name="enable_this_popup"
+ top_pad="10"
+ width="43">
+ <button.commit_callback
+ function="Pref.ClickEnablePopup" />
+ </button>
+ <button
+ enabled_control="FirstSelectedEnabledPopups"
+ follows="top|left"
+ height="23"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_overlay="Arrow_Down"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ layout="topleft"
+ left_pad="50"
+ name="disable_this_popup"
+ top_delta="0"
+ width="43">
+ <button.commit_callback
+ function="Pref.ClickDisablePopup" />
+ </button>
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerifBold"
+ height="12"
+ layout="topleft"
+ left="30"
+ name="dont_show_label"
+ top_pad="10"
+ width="450">
+ Never show these notifications:
+ </text>
+ <scroll_list
+ follows="top|left"
+ height="92"
+ layout="topleft"
+ left="10"
+ multi_select="true"
+ name="disabled_popups"
+ width="475" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
new file mode 100644
index 0000000000..6e0b94ac2b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
@@ -0,0 +1,351 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="left|top|right|bottom"
+ height="408"
+ label="Text Chat"
+ layout="topleft"
+ left="102"
+ name="chat"
+ top="1"
+ width="517">
+ <radio_group
+ height="30"
+ layout="topleft"
+ left="30"
+ control_name="ChatFontSize"
+ name="chat_font_size"
+ top="10"
+ width="440">
+ <radio_item
+ height="16"
+ label="Small"
+ layout="topleft"
+ left="0"
+ name="radio"
+ value="0"
+ top="10"
+ width="125" />
+ <radio_item
+ height="16"
+ label="Medium"
+ layout="topleft"
+ left_delta="145"
+ name="radio2"
+ value="1"
+ top_delta="0"
+ width="125" />
+ <radio_item
+ height="16"
+ label="Large"
+ layout="topleft"
+ left_delta="170"
+ name="radio3"
+ value="2"
+ top_delta="0"
+ width="125" />
+ </radio_group>
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="47"
+ layout="topleft"
+ left="30"
+ name="user"
+ top_pad="10"
+ width="44" >
+ <color_swatch.init_callback
+ function="Pref.getUIColor"
+ parameter="UserChatColor" />
+ <color_swatch.commit_callback
+ function="Pref.applyUIColor"
+ parameter="UserChatColor" />
+ </color_swatch>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="5"
+ mouse_opaque="false"
+ name="text_box1"
+ top_delta="5"
+ width="95">
+ Me
+ </text>
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="47"
+ layout="topleft"
+ left="180"
+ name="agent"
+ top_pad="-17"
+ width="44" >
+ <color_swatch.init_callback
+ function="Pref.getUIColor"
+ parameter="AgentChatColor" />
+ <color_swatch.commit_callback
+ function="Pref.applyUIColor"
+ parameter="AgentChatColor" />
+ </color_swatch>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="5"
+ mouse_opaque="false"
+ name="text_box2"
+ top_delta="5"
+ width="95">
+ Others
+ </text>
+ <color_swatch
+ can_apply_immediately="true"
+ color="0.6 0.6 1 1"
+ follows="left|top"
+ height="47"
+ label_width="60"
+ layout="topleft"
+ left="350"
+ name="im"
+ top_pad="-17"
+ width="44">
+ <color_swatch.init_callback
+ function="Pref.getUIColor"
+ parameter="IMChatColor" />
+ <color_swatch.commit_callback
+ function="Pref.applyUIColor"
+ parameter="IMChatColor" />
+ </color_swatch>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="5"
+ mouse_opaque="false"
+ name="text_box3"
+ top_delta="5"
+ width="95">
+ IM
+ </text>
+ <color_swatch
+ can_apply_immediately="true"
+ color="0.8 1 1 1"
+ follows="left|top"
+ height="47"
+ label_width="44"
+ layout="topleft"
+ left="30"
+ name="system"
+ top_pad="40"
+ width="44" >
+ <color_swatch.init_callback
+ function="Pref.getUIColor"
+ parameter="SystemChatColor" />
+ <color_swatch.commit_callback
+ function="Pref.applyUIColor"
+ parameter="SystemChatColor" />
+ </color_swatch>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="5"
+ mouse_opaque="false"
+ name="text_box4"
+ top_delta="5"
+ width="95">
+ System
+ </text>
+ <color_swatch
+ can_apply_immediately="true"
+ color="0.82 0.82 0.99 1"
+ follows="left|top"
+ height="47"
+ layout="topleft"
+ left="180"
+ name="script_error"
+ top_pad="-17"
+ width="44">
+ <color_swatch.init_callback
+ function="Pref.getUIColor"
+ parameter="ScriptErrorColor" />
+ <color_swatch.commit_callback
+ function="Pref.applyUIColor"
+ parameter="ScriptErrorColor" />
+ </color_swatch>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="5"
+ mouse_opaque="false"
+ name="text_box5"
+ top_delta="5"
+ width="95">
+ Errors
+ </text>
+ <color_swatch
+ can_apply_immediately="true"
+ color="0.7 0.9 0.7 1"
+ follows="left|top"
+ height="47"
+ layout="topleft"
+ left="350"
+ name="objects"
+ top_pad="-17"
+ width="44" >
+ <color_swatch.init_callback
+ function="Pref.getUIColor"
+ parameter="ObjectChatColor" />
+ <color_swatch.commit_callback
+ function="Pref.applyUIColor"
+ parameter="ObjectChatColor" />
+ </color_swatch>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="5"
+ mouse_opaque="false"
+ name="text_box6"
+ top_delta="5"
+ width="95">
+ Objects
+ </text>
+ <color_swatch
+ can_apply_immediately="true"
+ color="0.7 0.9 0.7 1"
+ follows="left|top"
+ height="47"
+ layout="topleft"
+ left="30"
+ name="owner"
+ top_pad="40"
+ width="44" >
+ <color_swatch.init_callback
+ function="Pref.getUIColor"
+ parameter="llOwnerSayChatColor" />
+ <color_swatch.commit_callback
+ function="Pref.applyUIColor"
+ parameter="llOwnerSayChatColor" />
+ </color_swatch>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="5"
+ mouse_opaque="false"
+ name="text_box7"
+ top_delta="5"
+ width="95">
+ Owner
+ </text>
+ <color_swatch
+ can_apply_immediately="true"
+ color="0.6 0.6 1 1"
+ follows="left|top"
+ height="47"
+ layout="topleft"
+ left="180"
+ name="links"
+ top_pad="-17"
+ width="44" >
+ <color_swatch.init_callback
+ function="Pref.getUIColor"
+ parameter="HTMLLinkColor" />
+ <color_swatch.commit_callback
+ function="Pref.applyUIColor"
+ parameter="HTMLLinkColor" />
+ </color_swatch>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="5"
+ mouse_opaque="false"
+ name="text_box9"
+ top_delta="5"
+ width="95">
+ URLs
+ </text>
+ <check_box
+ control_name="PlayTypingAnim"
+ height="16"
+ initial_value="true"
+ label="Play typing animation when chatting"
+ layout="topleft"
+ left="30"
+ name="play_typing_animation"
+ top_pad="40"
+ width="400" />
+ <check_box
+ enabled="false"
+ height="16"
+ label="Email me IMs when I'm offline"
+ layout="topleft"
+ left_delta="0"
+ name="send_im_to_email"
+ top_pad="5"
+ width="400" />
+ <check_box
+ enabled="false"
+ height="16"
+ label="Enable plain text chat history"
+ layout="topleft"
+ left_delta="0"
+ name="plain_text_chat_history"
+ top_pad="5"
+ width="400" />
+ <text
+ left="30"
+ height="20"
+ width="300"
+ top_pad="20">
+ Show IMs in: (Requires restart)
+ </text>
+ <radio_group
+ height="30"
+ layout="topleft"
+ left_delta="30"
+ control_name="ChatWindow"
+ name="chat_window"
+ top_pad="0"
+ tool_tip="Show your Instant Messages in separate windows, or in one window with many tabs (Requires restart)"
+ width="331">
+ <radio_item
+ height="16"
+ label="Multiple windows"
+ layout="topleft"
+ left="0"
+ name="radio"
+ value="0"
+ top="0"
+ width="150" />
+ <radio_item
+ height="16"
+ label="One window"
+ layout="topleft"
+ left_delta="0"
+ name="radio2"
+ value="1"
+ top_pad="5"
+ width="150" />
+ </radio_group>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
new file mode 100644
index 0000000000..22c75a595e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
@@ -0,0 +1,353 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="left|top|right|bottom"
+ height="408"
+ label="General"
+ layout="topleft"
+ left="102"
+ name="general_panel"
+ top="1"
+ width="517">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="30"
+ name="language_textbox"
+ top="10"
+ width="400">
+ Language:
+ </text>
+ <combo_box
+ control_name="Language"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left="50"
+ max_chars="135"
+ name="language_combobox"
+ width="200">
+ <combo_box.item
+ enabled="true"
+ label="System default"
+ name="System Default Language"
+ value="default" />
+ <combo_box.item
+ enabled="true"
+ label="English"
+ name="English"
+ value="en" />
+ <combo_box.item
+ enabled="true"
+ label="Dansk (Danish) - Beta"
+ name="Danish"
+ value="da" />
+ <combo_box.item
+ enabled="true"
+ label="Deutsch (German) - Beta"
+ name="Deutsch(German)"
+ value="de" />
+ <combo_box.item
+ enabled="true"
+ label="Español (Spanish) - Beta"
+ name="Spanish"
+ value="es" />
+ <combo_box.item
+ enabled="true"
+ label="Français (French) - Beta"
+ name="French"
+ value="fr" />
+ <combo_box.item
+ enabled="true"
+ label="Italiano (Italian) - Beta"
+ name="Italian"
+ value="it" />
+ <combo_box.item
+ enabled="true"
+ label="Nederlands (Dutch) - Beta"
+ name="Dutch"
+ value="nl" />
+ <combo_box.item
+ enabled="true"
+ label="Polski (Polish) - Beta"
+ name="Polish"
+ value="pl" />
+ <combo_box.item
+ enabled="true"
+ label="Portugués (Portuguese) - Beta"
+ name="Portugese"
+ value="pt" />
+ <combo_box.item
+ enabled="true"
+ label="日本語 (Japanese) - Beta"
+ name="(Japanese)"
+ value="ja" />
+ </combo_box>
+ <text
+ font="SansSerifSmall"
+ type="string"
+ length="1"
+ follows="left|top"
+ height="18"
+ layout="topleft"
+ left_pad="5"
+ name="language_textbox2"
+ width="200">
+ (Requires restart)
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="30"
+ top_pad="15"
+ name="maturity_desired_prompt"
+ width="200">
+ I want to access content rated:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left_pad="5"
+ name="maturity_desired_textbox"
+ width="200">
+ </text>
+ <combo_box
+ control_name="PreferredMaturity"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left="50"
+ name="maturity_desired_combobox"
+ width="200">
+ <combo_box.item
+ label="General, Moderate, Adult"
+ name="Desired_Adult"
+ value="42" />
+ <combo_box.item
+ label="General and Moderate"
+ name="Desired_Mature"
+ value="21" />
+ <combo_box.item
+ label="General"
+ name="Desired_PG"
+ value="13" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="30"
+ name="start_location_textbox"
+ top_pad="10"
+ width="394">
+ Start location:
+ </text>
+ <combo_box
+ control_name="LoginLocation"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ name="start_location_combo"
+ left="50"
+ width="200">
+ <combo_box.item
+ label="My Last Location"
+ name="MyLastLocation"
+ value="last" />
+ <combo_box.item
+ label="My Home"
+ name="MyHome"
+ value="home" />
+ </combo_box>
+ <check_box
+ control_name="ShowStartLocation"
+ height="16"
+ initial_value="true"
+ label="Show on login"
+ layout="topleft"
+ left_pad="5"
+ name="show_location_checkbox"
+ top_delta="5"
+ width="256" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="30"
+ name="name_tags_textbox"
+ top_pad="15"
+ width="400">
+ Name tags:
+ </text>
+ <radio_group
+ control_name="AvatarNameTagMode"
+ height="20"
+ layout="topleft"
+ left="50"
+ name="Name_Tag_Preference">
+ <radio_item
+ label="Off"
+ layout="topleft"
+ name="radio"
+ value="0"
+ width="100" />
+ <radio_item
+ label="On"
+ layout="topleft"
+ left_pad="12"
+ name="radio2"
+ value="1"
+ width="100" />
+ <radio_item
+ label="Show briefly"
+ layout="topleft"
+ left_pad="12"
+ name="radio3"
+ value="2"
+ width="100" />
+ </radio_group>
+ <check_box
+ enabled_control="AvatarNameTagMode"
+ control_name="RenderNameShowSelf"
+ height="16"
+ label="Show my name"
+ layout="topleft"
+ left="50"
+ name="show_my_name_checkbox1"
+ width="300" />
+ <check_box
+ enabled_control="AvatarNameTagMode"
+ control_name="SmallAvatarNames"
+ height="16"
+ initial_value="true"
+ label="Small name tags"
+ layout="topleft"
+ left_delta="175"
+ name="small_avatar_names_checkbox"
+ width="200" />
+ <check_box
+ enabled_control="AvatarNameTagMode"
+ control_name="RenderShowGroupTitleAll"
+ height="16"
+ label="Show group titles"
+ layout="topleft"
+ left_delta="-175"
+ name="show_all_title_checkbox1"
+ top_pad="5"
+ width="300" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="30"
+ name="effects_color_textbox"
+ top_pad="15"
+ width="200">
+ My effects:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="13"
+ layout="topleft"
+ left_pad="5"
+ name="title_afk_text"
+ width="190">
+ Away timeout:
+ </text>
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="50"
+ layout="topleft"
+ left="50"
+ name="effect_color_swatch"
+ tool_tip="Click to open Color Picker"
+ width="38">
+ <color_swatch.init_callback
+ function="Pref.getUIColor"
+ parameter="EffectColor" />
+ <color_swatch.commit_callback
+ function="Pref.applyUIColor"
+ parameter="EffectColor" />
+ </color_swatch>
+ <combo_box
+ height="23"
+ layout="topleft"
+ control_name="AFKTimeout"
+ left_pad="160"
+ label="Away timeout:"
+ top_delta="0"
+ name="afk"
+ width="130">
+ <combo_box.item
+ label="2 minutes"
+ name="item0"
+ value="120" />
+ <combo_box.item
+ label="5 minutes"
+ name="item1"
+ value="300" />
+ <combo_box.item
+ label="10 minutes"
+ name="item2"
+ value="600" />
+ <combo_box.item
+ label="30 minutes"
+ name="item3"
+ value="1800" />
+ <combo_box.item
+ label="never"
+ name="item4"
+ value="0" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="13"
+ layout="topleft"
+ text_color="white"
+ left="30"
+ mouse_opaque="false"
+ name="text_box3"
+ top_pad="15"
+ width="240">
+ Busy mode response:
+ </text>
+ <text_editor
+ control_name="BusyModeResponse2"
+ text_readonly_color="LabelDisabledColor"
+ bg_writeable_color="LtGray"
+ use_ellipses="false"
+ bg_visible="true"
+ border_visible="true"
+ hover="false"
+ commit_on_focus_lost = "true"
+ follows="left|top"
+ height="50"
+ layout="topleft"
+ left="50"
+ name="busy_response"
+ width="400"
+ word_wrap="true">
+ log_in_to_change
+ </text_editor>
+
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
new file mode 100644
index 0000000000..a0fcf59fc8
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
@@ -0,0 +1,760 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="left|top|right|bottom"
+ height="408"
+ label="Graphics"
+ layout="topleft"
+ left="102"
+ name="Display panel"
+ top="1"
+ width="517">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left="30"
+ name="UI Size:"
+ top="10"
+ width="300">
+ UI size:
+ </text>
+ <slider
+ can_edit_text="true"
+ control_name="UIScaleFactor"
+ decimal_digits="2"
+ follows="left|top"
+ height="15"
+ increment="0.025"
+ initial_value="1"
+ layout="topleft"
+ left_delta="52"
+ max_val="1.4"
+ min_val="0.75"
+ name="ui_scale_slider"
+ top_pad="2"
+ width="180" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left="30"
+ name="QualitySpeed"
+ top_pad="4"
+ width="400">
+ Quality and speed:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ halign="right"
+ height="12"
+ layout="topleft"
+ left="35"
+ name="FasterText"
+ top_pad="4"
+ width="80">
+ Faster
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left_delta="360"
+ name="BetterText"
+ top_delta="0"
+ width="100">
+ Better
+ </text>
+ <icon
+ color="0.12 0.12 0.12 1"
+ height="14"
+ image_name="Rounded_Square"
+ layout="topleft"
+ left="128"
+ name="LowGraphicsDivet"
+ top_delta="-2"
+ width="2" />
+ <icon
+ color="0.12 0.12 0.12 1"
+ height="14"
+ image_name="Rounded_Square"
+ layout="topleft"
+ left_pad="83"
+ name="MidGraphicsDivet"
+ top_delta="0"
+ width="2" />
+ <icon
+ color="0.12 0.12 0.12 1"
+ height="14"
+ image_name="Rounded_Square"
+ layout="topleft"
+ left_pad="85"
+ name="HighGraphicsDivet"
+ top_delta="0"
+ width="2" />
+ <icon
+ color="0.12 0.12 0.12 1"
+ height="14"
+ image_name="Rounded_Square"
+ layout="topleft"
+ left_pad="83"
+ name="UltraGraphicsDivet"
+ top_delta="0"
+ width="2" />
+ <slider
+ control_name="RenderQualityPerformance"
+ decimal_digits="0"
+ follows="left|top"
+ height="16"
+ increment="1"
+ initial_value="0"
+ layout="topleft"
+ left="120"
+ max_val="3"
+ name="QualityPerformanceSelection"
+ show_text="false"
+ top_delta="-2"
+ width="275">
+ <slider.commit_callback
+ function="Pref.QualityPerformance"/>
+ </slider>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ halign="center"
+ height="12"
+ layout="topleft"
+ left="88"
+ name="ShadersPrefText"
+ top_delta="20"
+ width="80">
+ Low
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ halign="center"
+ height="12"
+ layout="topleft"
+ left_delta="87"
+ name="ShadersPrefText2"
+ top_delta="0"
+ width="80">
+ Mid
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ halign="center"
+ height="12"
+ layout="topleft"
+ left_delta="87"
+ name="ShadersPrefText3"
+ top_delta="0"
+ width="80">
+ High
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ halign="center"
+ height="12"
+ layout="topleft"
+ left_delta="85"
+ name="ShadersPrefText4"
+ top_delta="0"
+ width="80">
+ Ultra
+ </text>
+ <panel
+ visiblity_control="ShowAdvancedGraphicsSettings"
+ border="false"
+ follows="top|left"
+ height="260"
+ label="CustomGraphics"
+ layout="topleft"
+ left="5"
+ name="CustomGraphics Panel"
+ top="124"
+ width="485">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left_delta="5"
+ name="ShadersText"
+ top="3"
+ width="128">
+ Shaders:
+ </text>
+ <check_box
+ control_name="RenderObjectBump"
+ height="16"
+ initial_value="true"
+ label="Bump mapping and shiny"
+ layout="topleft"
+ left_delta="0"
+ name="BumpShiny"
+ top_pad="7"
+ width="256" />
+ <check_box
+ control_name="VertexShaderEnable"
+ height="16"
+ initial_value="true"
+ label="Basic shaders"
+ layout="topleft"
+ left_delta="0"
+ name="BasicShaders"
+ tool_tip="Disabling this option may prevent some graphics card drivers from crashing"
+ top_pad="1"
+ width="315">
+ <check_box.commit_callback
+ function="Pref.VertexShaderEnable" />
+ </check_box>
+ <check_box
+ control_name="WindLightUseAtmosShaders"
+ height="16"
+ initial_value="true"
+ label="Atmospheric shaders"
+ layout="topleft"
+ left_delta="0"
+ name="WindLightUseAtmosShaders"
+ top_pad="1"
+ width="256">
+ <check_box.commit_callback
+ function="Pref.VertexShaderEnable" />
+ </check_box>
+ <check_box
+ control_name="RenderWaterReflections"
+ height="16"
+ initial_value="true"
+ label="Water reflections"
+ layout="topleft"
+ left_delta="0"
+ name="Reflections"
+ top_pad="1"
+ width="256">
+ <check_box.commit_callback
+ function="Pref.VertexShaderEnable" />
+ </check_box>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left_delta="0"
+ name="ReflectionDetailText"
+ top_pad="7"
+ width="128">
+ Reflection detail:
+ </text>
+ <radio_group
+ control_name="RenderReflectionDetail"
+ draw_border="false"
+ height="70"
+ layout="topleft"
+ left_delta="-2"
+ name="ReflectionDetailRadio"
+ top_pad="3"
+ width="321">
+ <radio_item
+ height="16"
+ label="Terrain and trees"
+ layout="topleft"
+ left="3"
+ name="0"
+ top="3"
+ width="315" />
+ <radio_item
+ height="16"
+ label="All static objects"
+ layout="topleft"
+ left_delta="0"
+ name="1"
+ top_delta="16"
+ width="315" />
+ <radio_item
+ height="16"
+ label="All avatars and objects"
+ layout="topleft"
+ left_delta="0"
+ name="2"
+ top_delta="16"
+ width="315" />
+ <radio_item
+ height="16"
+ label="Everything"
+ layout="topleft"
+ left_delta="0"
+ name="3"
+ top_delta="16"
+ width="315" />
+ </radio_group>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left_delta="2"
+ name="AvatarRenderingText"
+ top_pad="5"
+ width="128">
+ Avatar rendering:
+ </text>
+ <check_box
+ control_name="RenderUseImpostors"
+ height="16"
+ initial_value="true"
+ label="Avatar impostors"
+ layout="topleft"
+ left_delta="0"
+ name="AvatarImpostors"
+ top_pad="7"
+ width="256" />
+ <check_box
+ control_name="RenderAvatarVP"
+ height="16"
+ initial_value="true"
+ label="Hardware skinning"
+ layout="topleft"
+ left_delta="0"
+ name="AvatarVertexProgram"
+ top_pad="1"
+ width="256">
+ <check_box.commit_callback
+ function="Pref.VertexShaderEnable" />
+ </check_box>
+ <check_box
+ control_name="RenderAvatarCloth"
+ height="16"
+ initial_value="true"
+ label="Avatar cloth"
+ layout="topleft"
+ left_delta="0"
+ name="AvatarCloth"
+ top_pad="1"
+ width="256" />
+
+ <slider
+ control_name="RenderFarClip"
+ decimal_digits="0"
+ follows="left|top"
+ height="16"
+ increment="8"
+ initial_value="160"
+ label="Draw distance:"
+ label_width="140"
+ layout="topleft"
+ left="216"
+ max_val="512"
+ min_val="64"
+ name="DrawDistance"
+ top="3"
+ width="255">
+ <slider.commit_callback
+ function="Pref.UpdateMeterText" />
+ </slider>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left_delta="250"
+ name="DrawDistanceMeterText2"
+ top_delta="0"
+ width="128">
+ m
+ </text>
+ <slider
+ control_name="RenderMaxPartCount"
+ decimal_digits="0"
+ follows="left|top"
+ height="16"
+ increment="256"
+ initial_value="4096"
+ label="Max. particle count:"
+ label_width="140"
+ layout="topleft"
+ left="216"
+ max_val="8192"
+ name="MaxParticleCount"
+ top_pad="7"
+ width="262" />
+ <slider
+ control_name="RenderGlowResolutionPow"
+ decimal_digits="0"
+ follows="left|top"
+ height="16"
+ increment="1"
+ initial_value="8"
+ label="Post process quality:"
+ label_width="140"
+ layout="topleft"
+ left_delta="0"
+ max_val="9"
+ min_val="8"
+ name="RenderPostProcess"
+ show_text="false"
+ top_pad="4"
+ width="223">
+ <slider.commit_callback
+ function="Pref.UpdateSliderText"
+ parameter="PostProcessText" />
+ </slider>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left_delta="0"
+ name="MeshDetailText"
+ top_pad="5"
+ width="128">
+ Mesh detail:
+ </text>
+ <slider
+ control_name="RenderVolumeLODFactor"
+ follows="left|top"
+ height="16"
+ increment="0.125"
+ initial_value="160"
+ label=" Objects:"
+ label_width="140"
+ layout="topleft"
+ left_delta="0"
+ max_val="2"
+ name="ObjectMeshDetail"
+ show_text="false"
+ top_pad="6"
+ width="223">
+ <slider.commit_callback
+ function="Pref.UpdateSliderText"
+ parameter="ObjectMeshDetailText" />
+ </slider>
+ <slider
+ control_name="RenderFlexTimeFactor"
+ follows="left|top"
+ height="16"
+ initial_value="160"
+ label=" Flexiprims:"
+ label_width="140"
+ layout="topleft"
+ left_delta="0"
+ name="FlexibleMeshDetail"
+ show_text="false"
+ top_pad="4"
+ width="223">
+ <slider.commit_callback
+ function="Pref.UpdateSliderText"
+ parameter="FlexibleMeshDetailText" />
+ </slider>
+ <slider
+ control_name="RenderTreeLODFactor"
+ follows="left|top"
+ height="16"
+ increment="0.125"
+ initial_value="160"
+ label=" Trees:"
+ label_width="140"
+ layout="topleft"
+ left_delta="0"
+ name="TreeMeshDetail"
+ show_text="false"
+ top_pad="4"
+ width="223">
+ <slider.commit_callback
+ function="Pref.UpdateSliderText"
+ parameter="TreeMeshDetailText" />
+ </slider>
+ <slider
+ control_name="RenderAvatarLODFactor"
+ follows="left|top"
+ height="16"
+ increment="0.125"
+ initial_value="160"
+ label=" Avatars:"
+ label_width="140"
+ layout="topleft"
+ left_delta="0"
+ name="AvatarMeshDetail"
+ show_text="false"
+ top_pad="4"
+ width="223">
+ <slider.commit_callback
+ function="Pref.UpdateSliderText"
+ parameter="AvatarMeshDetailText" />
+ </slider>
+ <slider
+ control_name="RenderTerrainLODFactor"
+ follows="left|top"
+ height="16"
+ increment="0.125"
+ initial_value="160"
+ label=" Terrain:"
+ label_width="140"
+ layout="topleft"
+ left_delta="0"
+ max_val="2"
+ min_val="1"
+ name="TerrainMeshDetail"
+ show_text="false"
+ top_pad="4"
+ width="223">
+ <slider.commit_callback
+ function="Pref.UpdateSliderText"
+ parameter="TerrainMeshDetailText" />
+ </slider>
+ <slider
+ control_name="WLSkyDetail"
+ enabled_control="WindLightUseAtmosShaders"
+ decimal_digits="0"
+ follows="left|top"
+ height="16"
+ increment="8"
+ initial_value="160"
+ label=" Sky:"
+ label_width="140"
+ layout="topleft"
+ left_delta="0"
+ max_val="128"
+ min_val="16"
+ name="SkyMeshDetail"
+ show_text="false"
+ top_pad="4"
+ width="223">
+ <slider.commit_callback
+ function="Pref.UpdateSliderText"
+ parameter="SkyMeshDetailText" />
+ </slider>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left="444"
+ name="PostProcessText"
+ top="305"
+ width="128">
+ Low
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left_delta="0"
+ name="ObjectMeshDetailText"
+ top_pad="26"
+ width="128">
+ Low
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left_delta="0"
+ name="FlexibleMeshDetailText"
+ top_pad="8"
+ width="128">
+ Low
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left_delta="0"
+ name="TreeMeshDetailText"
+ top_pad="8"
+ width="128">
+ Low
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left_delta="0"
+ name="AvatarMeshDetailText"
+ top_pad="8"
+ width="128">
+ Low
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left_delta="0"
+ name="TerrainMeshDetailText"
+ top_pad="8"
+ width="128">
+ Low
+ </text>
+ <text
+ enabled_control="WindLightUseAtmosShaders"
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left_delta="0"
+ name="SkyMeshDetailText"
+ top_pad="8"
+ width="128">
+ Low
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left_delta="-230"
+ name="LightingDetailText"
+ top_pad="8"
+ width="128">
+ Lighting detail:
+ </text>
+ <radio_group
+ control_name="RenderLightingDetail"
+ draw_border="false"
+ height="38"
+ layout="topleft"
+ left_delta="0"
+ name="LightingDetailRadio"
+ top_pad="5"
+ width="321">
+ <radio_item
+ height="16"
+ label="Sun and moon only"
+ layout="topleft"
+ left="3"
+ name="SunMoon"
+ value="0"
+ top="3"
+ width="156" />
+ <radio_item
+ height="16"
+ label="Nearby local lights"
+ layout="topleft"
+ left_delta="0"
+ name="LocalLights"
+ value="1"
+ top_delta="16"
+ width="156" />
+ </radio_group>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left="360"
+ name="TerrainDetailText"
+ top="465"
+ width="128">
+ Terrain detail:
+ </text>
+ <radio_group
+ control_name="RenderTerrainDetail"
+ draw_border="false"
+ height="38"
+ layout="topleft"
+ left_delta="0"
+ name="TerrainDetailRadio"
+ top_pad="5"
+ width="321">
+ <radio_item
+ height="16"
+ label="Low"
+ layout="topleft"
+ left="3"
+ name="0"
+ top="3"
+ width="315" />
+ <radio_item
+ height="16"
+ label="High"
+ layout="topleft"
+ left_delta="0"
+ name="2"
+ top_delta="16"
+ width="315" />
+ </radio_group>
+ </panel>
+ <button
+ follows="left|bottom"
+ height="23"
+ label="Apply"
+ label_selected="Apply"
+ layout="topleft"
+ left="10"
+ name="Apply"
+ top="383"
+ width="115">
+ <button.commit_callback
+ function="Pref.Apply" />
+ </button>
+ <button
+ follows="left|bottom"
+ height="23"
+ label="Reset"
+ layout="topleft"
+ left_pad="3"
+ name="Defaults"
+ top="383"
+ width="115">
+ <button.commit_callback
+ function="Pref.HardwareDefaults" />
+ </button>
+ <button
+ control_name="ShowAdvancedGraphicsSettings"
+ follows="right|bottom"
+ height="23"
+ is_toggle="true"
+ label="Advanced"
+ layout="topleft"
+ left_pad="35"
+ name="Advanced"
+ top_delta="0"
+ width="115" />
+ <button
+ follows="right|bottom"
+ height="23"
+ label="Hardware"
+ label_selected="Hardware"
+ layout="topleft"
+ left_pad="3"
+ name="GraphicsHardwareButton"
+ top_delta="0"
+ width="115">
+ <button.commit_callback
+ function="Pref.HardwareSettings" />
+ </button>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml
new file mode 100644
index 0000000000..0aaeb6114e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml
@@ -0,0 +1,215 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="left|top|right|bottom"
+ height="408"
+ label="Communication"
+ layout="topleft"
+ left="102"
+ name="im"
+ top="1"
+ width="517">
+ <panel.string
+ name="log_in_to_change">
+ log in to change
+ </panel.string>
+ <button
+ follows="left|bottom"
+ height="23"
+ label="Clear History"
+ layout="topleft"
+ left="30"
+ name="clear_cache"
+ top="10"
+ width="145">
+ <button.commit_callback
+ function="Pref.WebClearCache" />
+ </button>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="10"
+ mouse_opaque="false"
+ name="cache_size_label_l"
+ top_delta="3"
+ text_color="LtGray_50"
+ width="300">
+ (Locations, images, web, search history)
+ </text>
+ <check_box
+ height="16"
+ enabled="false"
+ label="Only friends and groups know I'm online"
+ layout="topleft"
+ left="30"
+ name="online_visibility"
+ top_pad="20"
+ width="350" />
+ <check_box
+ enabled_control="EnableVoiceChat"
+ control_name="VoiceCallsFriendsOnly"
+ height="16"
+ label="Only friends and groups can call or IM me"
+ layout="topleft"
+ left="30"
+ name="voice_call_friends_only_check"
+ top_pad="10"
+ width="350" />
+ <check_box
+ enabled_control="EnableVoiceChat"
+ control_name="AutoDisengageMic"
+ height="16"
+ label="Switch off microphone when ending calls"
+ layout="topleft"
+ left="30"
+ name="auto_disengage_mic_check"
+ top_pad="10"
+ width="350" />
+ <check_box
+ control_name="CookiesEnabled"
+ height="16"
+ label="Accept cookies"
+ layout="topleft"
+ left="30"
+ name="cookies_enabled"
+ top_pad="10"
+ width="350" />
+ <check_box
+ name="media_enabled"
+ control_name="AudioStreamingMedia"
+ height="16"
+ label="Media Enabled"
+ layout="topleft"
+ left="30"
+ top_pad="10"
+ width="350">
+ <check_box.commit_callback
+ function="Pref.MediaEnabled" />
+ </check_box>
+ <check_box
+ enabled_control="AudioStreamingMedia"
+ control_name="ParcelMediaAutoPlayEnable"
+ height="16"
+ label="Allow Media to auto-play"
+ layout="topleft"
+ left="30"
+ name="autoplay_enabled"
+ top_pad="10"
+ width="350">
+ <check_box.commit_callback
+ function="Pref.ParcelMediaAutoPlayEnable" />
+ </check_box>
+ <check_box
+ control_name="AudioStreamingMusic"
+ height="16"
+ label="Music Enabled"
+ layout="topleft"
+ left="30"
+ name="music_enabled"
+ top_pad="10"
+ width="350">
+ <check_box.commit_callback
+ function="Pref.MusicEnabled" />
+ </check_box>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="30"
+ mouse_opaque="false"
+ name="Logs:"
+ top_pad="10"
+ width="350">
+ Logs:
+ </text>
+ <check_box
+ enabled="false"
+ control_name="LogChat"
+ height="16"
+ label="Save nearby chat logs on my computer"
+ layout="topleft"
+ left="30"
+ name="log_nearby_chat"
+ top_pad="10"
+ width="350">
+ </check_box>
+ <check_box
+ enabled="false"
+ control_name="LogInstantMessages"
+ height="16"
+ label="Save IM logs on my computer"
+ layout="topleft"
+ left="30"
+ name="log_instant_messages"
+ top_pad="10"
+ width="350">
+ </check_box>
+ <check_box
+ control_name="LogTimestamp"
+ enabled="false"
+ height="16"
+ label="Add timestamp"
+ layout="topleft"
+ left_delta="0"
+ name="show_timestamps_check_im"
+ top_pad="10"
+ width="237" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="log_path_desc"
+ top_pad="5"
+ width="128">
+ Location of logs:
+ </text>
+ <line_editor
+ bottom="366"
+ control_name="InstantMessageLogFolder"
+ enabled="false"
+ follows="top|left|right"
+ halign="right"
+ height="23"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="log_path_string"
+ top_pad="5"
+ width="250"/>
+ <button
+ enabled="false"
+ follows="right|bottom"
+ height="23"
+ label="Browse"
+ label_selected="Browse"
+ layout="topleft"
+ left_pad="5"
+ name="log_path_button"
+ top_delta="0"
+ width="145">
+ <button.commit_callback
+ function="Pref.LogPath" />
+ </button>
+ <button
+ follows="left|bottom"
+ height="23"
+ label="Block list"
+ layout="topleft"
+ left="30"
+ name="block_list"
+ top_pad="20"
+ width="145">
+ <button.commit_callback
+ function="SideTray.ShowPanel"
+ parameter="panel_block_list_sidetray" />
+ </button>
+ </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
new file mode 100644
index 0000000000..8723e0a832
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
@@ -0,0 +1,346 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="left|top|right|bottom"
+ height="408"
+ label="Setup"
+ layout="topleft"
+ left="102"
+ name="Input panel"
+ top="1"
+ width="517">
+ <button
+ height="23"
+ label="Other Devices"
+ layout="topleft"
+ left="30"
+ name="joystick_setup_button"
+ top="10"
+ width="155">
+ <button.commit_callback
+ function="Floater.Show"
+ parameter="pref_joystick" />
+ </button>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="30"
+ name="Mouselook:"
+ top_pad="10"
+ width="300">
+ Mouselook:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="50"
+ name=" Mouse Sensitivity"
+ top_pad="10"
+ width="150">
+ Mouse sensitivity
+ </text>
+ <slider
+ control_name="MouseSensitivity"
+ follows="left|top"
+ height="15"
+ initial_value="2"
+ layout="topleft"
+ show_text="false"
+ left_delta="150"
+ max_val="15"
+ name="mouse_sensitivity"
+ top_delta="0"
+ width="145" />
+ <check_box
+ control_name="InvertMouse"
+ height="16"
+ label="Invert"
+ layout="topleft"
+ left_pad="2"
+ name="invert_mouse"
+ top_delta="0"
+ width="128" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="30"
+ name="Network:"
+ mouse_opaque="false"
+ top_pad="4"
+ width="300">
+ Network:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="50"
+ name="Maximum bandwidth"
+ mouse_opaque="false"
+ top_pad="10"
+ width="200">
+ Maximum bandwidth
+ </text>
+ <slider
+ can_edit_text="true"
+ control_name="ThrottleBandwidthKBPS"
+ decimal_digits="0"
+ follows="left|top"
+ height="15"
+ increment="100"
+ initial_value="500"
+ layout="topleft"
+ left_delta="150"
+ max_val="10000"
+ min_val="100"
+ name="max_bandwidth"
+ top_delta="0"
+ width="180" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="6"
+ mouse_opaque="false"
+ name="text_box2"
+ top_delta="1"
+ width="200">
+ kbps
+ </text>
+ <check_box
+ control_name="ConnectionPortEnabled"
+ height="16"
+ label="Custom port"
+ layout="topleft"
+ left="77"
+ name="connection_port_enabled"
+ top_pad="20"
+ width="256">
+ <check_box.commit_callback
+ function="Notification.Show"
+ parameter="ChangeConnectionPort" />
+ </check_box>
+ <spinner
+ control_name="ConnectionPort"
+ enabled_control="ConnectionPortEnabled"
+ decimal_digits="0"
+ follows="left|top"
+ height="23"
+ increment="1"
+ initial_value="13000"
+ label="Port number:"
+ label_width="75"
+ layout="topleft"
+ left_delta="160"
+ max_val="13050"
+ min_val="13000"
+ name="connection_port"
+ top_delta="-2"
+ width="140" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="80"
+ mouse_opaque="false"
+ name="cache_size_label_l"
+ top_pad="20"
+ width="200">
+ Cache size
+ </text>
+ <slider
+ can_edit_text="true"
+ control_name="CacheSize"
+ decimal_digits="0"
+ follows="left|top"
+ height="15"
+ increment="16"
+ initial_value="512"
+ layout="topleft"
+ left_delta="150"
+ max_val="1024"
+ min_val="32"
+ name="cache_size"
+ top_delta="-2"
+ width="180" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="6"
+ mouse_opaque="false"
+ name="text_box5"
+ top_delta="1"
+ width="40">
+ MB
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="80"
+ name="Cache location"
+ top_delta="20"
+ width="300">
+ Cache location:
+ </text>
+ <line_editor
+ control_name="CacheLocationTopFolder"
+ border_style="line"
+ border_thickness="1"
+ enabled="false"
+ follows="left|top"
+ font="SansSerif"
+ handle_edit_keys_directly="true"
+ height="23"
+ layout="topleft"
+ left="80"
+ max_length="4096"
+ name="cache_location"
+ top_pad="5"
+ width="205" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Browse"
+ label_selected="Browse"
+ layout="topleft"
+ left_pad="5"
+ name="set_cache"
+ top_delta="-1"
+ width="100">
+ <button.commit_callback
+ function="Pref.SetCache" />
+ </button>
+ <button
+ follows="left|top"
+ height="23"
+ label="Reset"
+ label_selected="Reset"
+ layout="topleft"
+ left_pad="3"
+ name="reset_cache"
+ top_delta="0"
+ width="100">
+ <button.commit_callback
+ function="Pref.ResetCache" />
+ </button>
+
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="30"
+ name="Web:"
+ top_pad="5"
+ width="300">
+ Web:
+ </text>
+ <radio_group
+ control_name="UseExternalBrowser"
+ draw_border="false"
+ follows="top|left"
+ height="40"
+ layout="topleft"
+ left_delta="50"
+ name="use_external_browser"
+ top_pad="4"
+ width="480">
+ <radio_item
+ height="20"
+ label="Use built-in browser"
+ layout="topleft"
+ left="0"
+ name="internal"
+ value="0"
+ tool_tip="Use the built-in web browser for help, web links, etc. This browser opens as a new window inside [APP_NAME]."
+ top="0"
+ width="480" />
+ <radio_item
+ height="20"
+ label="Use my browser (IE, Firefox, Safari)"
+ layout="topleft"
+ left_delta="0"
+ name="external"
+ value="1"
+ tool_tip="Use the default system web browser for help, web links, etc. Not recommended if running full screen."
+ top_delta="20"
+ width="480" />
+ </radio_group>
+
+ <check_box
+ top_delta="4"
+ enabled="true"
+ follows="left|top"
+ height="16"
+ initial_value="false"
+ control_name="BrowserProxyEnabled"
+ label="Enable Web Proxy"
+ left_delta="0"
+ mouse_opaque="true"
+ name="web_proxy_enabled"
+ radio_style="false"
+ width="400" top_pad="5"/>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="1"
+ name="Proxy location"
+ top_delta="20"
+ width="300">
+ Proxy location:
+ </text>
+ <line_editor
+ control_name="BrowserProxyAddress"
+ enabled_control="BrowserProxyEnabled"
+ follows="left|top"
+ font="SansSerif"
+ height="23"
+ layout="topleft"
+ left_delta="0"
+ name="web_proxy_editor"
+ tool_tip="The name or IP address of the proxy you would like to use"
+ top_pad="4"
+ width="200" />
+ <spinner
+ control_name="BrowserProxyPort"
+ enabled_control="BrowserProxyEnabled"
+ decimal_digits="0"
+ follows="left|top"
+ height="23"
+ increment="1"
+ initial_value="80"
+ label="Port number:"
+ label_width="75"
+ layout="topleft"
+ left_delta="230"
+ max_val="12000"
+ min_val="10"
+ name="web_proxy_port"
+ top_delta="0"
+ width="140" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
new file mode 100644
index 0000000000..d8e3f4ccfb
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
@@ -0,0 +1,507 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="all"
+ height="408"
+ label="Sounds"
+ layout="topleft"
+ left="102"
+ name="Preference Media panel"
+ top="1"
+ width="517">
+ <slider
+ control_name="AudioLevelMaster"
+ follows="left|top"
+ font.style="BOLD"
+ height="15"
+ increment="0.05"
+ initial_value="0.5"
+ label="Master volume"
+ label_width="160"
+ layout="topleft"
+ left="0"
+ name="System Volume"
+ show_text="false"
+ slider_label.halign="right"
+ top="10"
+ volume="true"
+ width="350">
+ <slider.commit_callback
+ function="Pref.setControlFalse"
+ parameter="MuteAudio" />
+ </slider>
+ <button
+ control_name="MuteAudio"
+ follows="top|right"
+ height="18"
+ image_selected="Parcel_VoiceNo_Dark"
+ image_unselected="Parcel_Voice_Dark"
+ is_toggle="true"
+ layout="topleft"
+ left_pad="16"
+ name="mute_audio"
+ tab_stop="false"
+ top_delta="-2"
+ width="22" />
+ <check_box
+ control_name="MuteWhenMinimized"
+ height="15"
+ initial_value="true"
+ label="Mute if minimized"
+ layout="topleft"
+ left="167"
+ name="mute_when_minimized"
+ top_pad="5"
+ width="215" />
+ <slider
+ control_name="AudioLevelAmbient"
+ disabled_control="MuteAudio"
+ follows="left|top"
+ height="15"
+ increment="0.05"
+ initial_value="0.5"
+ label="Ambient"
+ label_width="160"
+ layout="topleft"
+ left="0"
+ name="Wind Volume"
+ show_text="false"
+ slider_label.halign="right"
+ top_pad="7"
+ volume="true"
+ width="350">
+ <slider.commit_callback
+ function="Pref.setControlFalse"
+ parameter="MuteAmbient" />
+ </slider>
+ <button
+ control_name="MuteAmbient"
+ disabled_control="MuteAudio"
+ follows="top|right"
+ height="18"
+ image_selected="Parcel_VoiceNo_Dark"
+ image_unselected="Parcel_Voice_Dark"
+ is_toggle="true"
+ layout="topleft"
+ left_pad="16"
+ name="mute_wind"
+ tab_stop="false"
+ top_delta="-2"
+ width="22" />
+ <slider
+ control_name="AudioLevelUI"
+ disabled_control="MuteAudio"
+ follows="left|top"
+ height="15"
+ increment="0.05"
+ initial_value="0.5"
+ label="Buttons"
+ label_width="160"
+ layout="topleft"
+ left="0"
+ name="UI Volume"
+ show_text="false"
+ slider_label.halign="right"
+ top_pad="7"
+ volume="true"
+ width="350">
+ <slider.commit_callback
+ function="Pref.setControlFalse"
+ parameter="MuteUI" />
+ </slider>
+ <button
+ control_name="MuteUI"
+ disabled_control="MuteAudio"
+ follows="top|right"
+ height="18"
+ image_selected="Parcel_VoiceNo_Dark"
+ image_unselected="Parcel_Voice_Dark"
+ is_toggle="true"
+ layout="topleft"
+ left_pad="16"
+ name="mute_ui"
+ tab_stop="false"
+ top_delta="-2"
+ width="22" />
+ <slider
+ control_name="AudioLevelMedia"
+ disabled_control="MuteAudio"
+ follows="left|top"
+ height="15"
+ increment="0.05"
+ initial_value="0.5"
+ label="Media"
+ label_width="160"
+ layout="topleft"
+ left="0"
+ name="Media Volume"
+ show_text="false"
+ slider_label.halign="right"
+ top_pad="7"
+ volume="true"
+ width="350">
+ <slider.commit_callback
+ function="Pref.setControlFalse"
+ parameter="MuteMedia" />
+ </slider>
+ <button
+ control_name="MuteMedia"
+ disabled_control="MuteAudio"
+ follows="top|right"
+ height="18"
+ image_selected="Parcel_VoiceNo_Dark"
+ image_unselected="Parcel_Voice_Dark"
+ is_toggle="true"
+ layout="topleft"
+ left_pad="16"
+ name="mute_media"
+ tab_stop="false"
+ top_delta="-2"
+ width="22" />
+ <slider
+ control_name="AudioLevelSFX"
+ disabled_control="MuteAudio"
+ follows="left|top"
+ height="15"
+ increment="0.05"
+ initial_value="0.5"
+ label="Sound effects"
+ label_width="160"
+ slider_label.halign="right"
+ layout="topleft"
+ left="0"
+ name="SFX Volume"
+ show_text="false"
+ top_pad="7"
+ volume="true"
+ width="350">
+ <slider.commit_callback
+ function="Pref.setControlFalse"
+ parameter="MuteSounds" />
+ </slider>
+ <button
+ control_name="MuteSounds"
+ disabled_control="MuteAudio"
+ follows="top|right"
+ height="18"
+ image_selected="Parcel_VoiceNo_Dark"
+ image_unselected="Parcel_Voice_Dark"
+ is_toggle="true"
+ layout="topleft"
+ left_pad="16"
+ name="mute_sfx"
+ tab_stop="false"
+ top_delta="-2"
+ width="22" />
+ <slider
+ control_name="AudioLevelMusic"
+ disabled_control="MuteAudio"
+ follows="left|top"
+ height="15"
+ increment="0.05"
+ initial_value="0.5"
+ label="Streaming music"
+ label_width="160"
+ layout="topleft"
+ left="0"
+ name="Music Volume"
+ slider_label.halign="right"
+ show_text="false"
+ top_pad="7"
+ volume="true"
+ width="350">
+ <slider.commit_callback
+ function="Pref.setControlFalse"
+ parameter="MuteMusic" />
+ </slider>
+ <button
+ control_name="MuteMusic"
+ disabled_control="MuteAudio"
+ follows="top|right"
+ height="18"
+ image_selected="Parcel_VoiceNo_Dark"
+ image_unselected="Parcel_Voice_Dark"
+ is_toggle="true"
+ layout="topleft"
+ left_pad="16"
+ name="mute_music"
+ tab_stop="false"
+ top_delta="-2"
+ width="22" />
+ <check_box
+ label_text.halign="left"
+ follows="left|top"
+ height="16"
+ control_name ="EnableVoiceChat"
+ disabled_control="CmdLineDisableVoice"
+ label="Enable voice"
+ layout="topleft"
+ left="28"
+ name="enable_voice_check"
+ top_pad="5"
+ width="110"
+ >
+ </check_box>
+ <slider
+ control_name="AudioLevelVoice"
+ enabled_control="EnableVoiceChat"
+ disabled_control="MuteAudio"
+ follows="left|top"
+ height="15"
+ increment="0.05"
+ initial_value="0.5"
+ label="Voice"
+ label_width="160"
+ layout="topleft"
+ left="0"
+ top_delta="20"
+ name="Voice Volume"
+ show_text="false"
+ slider_label.halign="right"
+ volume="true"
+ width="350">
+ <slider.commit_callback
+ function="Pref.setControlFalse"
+ parameter="MuteVoice" />
+ </slider>
+ <button
+ control_name="MuteVoice"
+ enabled_control="EnableVoiceChat"
+ disabled_control="MuteAudio"
+ follows="top|right"
+ height="18"
+ image_selected="Parcel_VoiceNo_Dark"
+ image_unselected="Parcel_Voice_Dark"
+ is_toggle="true"
+ layout="topleft"
+ left_pad="16"
+ name="mute_voice"
+ tab_stop="false"
+ top_delta="-2"
+ width="22" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="13"
+ layout="topleft"
+ left="30"
+ name="Listen from"
+ width="200"
+ top="205">
+ Listen from:
+ </text>
+ <icon
+ follows="left|top"
+ height="18"
+ image_name="Cam_FreeCam_Off"
+ layout="topleft"
+ name="camera_icon"
+ mouse_opaque="false"
+ visible="true"
+ width="18"
+ left="80"
+ top="219"/>
+ <icon
+ follows="left|top"
+ height="18"
+ image_name="Move_Walk_Off"
+ layout="topleft"
+ name="avatar_icon"
+ mouse_opaque="false"
+ visible="true"
+ width="18"
+ top="239"
+ left="80"
+ />
+ <radio_group
+ enabled_control="EnableVoiceChat"
+ control_name="VoiceEarLocation"
+ draw_border="false"
+ follows="left|top"
+ layout="topleft"
+ left="100"
+ width="221"
+ height="38"
+ name="ear_location"
+ top="218">
+ <radio_item
+ height="16"
+ label="Camera position"
+ follows="left|top"
+ layout="topleft"
+ name="0"
+ width="200"/>
+ <radio_item
+ height="16"
+ follows="left|top"
+ label="Avatar position"
+ layout="topleft"
+ name="1"
+ width="200" />
+ </radio_group>
+ <button
+ control_name="ShowDeviceSettings"
+ follows="left|top"
+ height="23"
+ is_toggle="true"
+ label="Input/Output devices"
+ layout="topleft"
+ left="30"
+ top="262"
+ name="device_settings_btn"
+ width="190">
+ </button>
+ <panel
+ background_visible="false"
+ bg_alpha_color="DkGray"
+ visiblity_control="ShowDeviceSettings"
+ border="false"
+ follows="top|left"
+ height="120"
+ label="Device Settings"
+ layout="topleft"
+ left="0"
+ name="device_settings_panel"
+ class="panel_voice_device_settings"
+ width="501"
+ top="285">
+ <panel.string
+ name="default_text">
+ Default
+ </panel.string>
+ <icon
+ height="18"
+ image_name="Microphone_On"
+ left="80"
+ name="microphone_icon"
+ mouse_opaque="false"
+ top="7"
+ visible="true"
+ width="18" />
+ <text
+ type="string"
+ length="1"
+ font.style="BOLD"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="3"
+ name="Input"
+ width="200">
+ Input
+ </text>
+ <combo_box
+ height="23"
+ control_name="VoiceInputAudioDevice"
+ layout="topleft"
+ left="165"
+ max_chars="128"
+ name="voice_input_device"
+ top_pad="-2"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="165"
+ name="My volume label"
+ top_pad="5"
+ width="200">
+ My volume:
+ </text>
+ <slider_bar
+ control_name="AudioLevelMic"
+ follows="left|top"
+ height="17"
+ increment="0.05"
+ initial_value="1.0"
+ layout="topleft"
+ left="160"
+ max_val="2"
+ name="mic_volume_slider"
+ tool_tip="Change the volume using this slider"
+ top_pad="-2"
+ width="220" />
+ <text
+ type="string"
+ text_color="EmphasisColor"
+ length="1"
+ follows="left|top"
+ height="18"
+ layout="topleft"
+ left_pad="5"
+ name="wait_text"
+ top_delta="0"
+ width="110">
+ Please wait
+ </text>
+ <locate
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="bar0"
+ top_delta="0"
+ width="20" />
+ <locate
+ height="20"
+ layout="topleft"
+ left_pad="2"
+ name="bar1"
+ top_delta="0"
+ width="20" />
+ <locate
+ height="20"
+ layout="topleft"
+ left_pad="2"
+ name="bar2"
+ top_delta="0"
+ width="20" />
+ <locate
+ height="20"
+ layout="topleft"
+ left_pad="2"
+ name="bar3"
+ top_delta="0"
+ width="20" />
+ <locate
+ height="20"
+ layout="topleft"
+ left_pad="2"
+ name="bar4"
+ top_delta="0"
+ width="20" />
+ <icon
+ height="18"
+ image_name="Parcel_Voice_Light"
+ left="80"
+ name="speaker_icon"
+ mouse_opaque="false"
+ top_pad="-8"
+ visible="true"
+ width="22" />
+ <text
+ font.style="BOLD"
+ type="string"
+ length="1"
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="Output"
+ width="200">
+ Output
+ </text>
+ <combo_box
+ control_name="VoiceOutputAudioDevice"
+ height="23"
+ layout="topleft"
+ left="165"
+ max_chars="128"
+ name="voice_output_device"
+ top_pad="-2"
+ width="200" />
+ </panel>
+ </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
new file mode 100644
index 0000000000..e1d8ee241d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
@@ -0,0 +1,612 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="left|right|top|bottom"
+ name="MediaControlsPanel"
+ background_visible="false"
+ height="200"
+ layout="topleft"
+ help_topic="prim_media_controls"
+ mouse_opaque="false"
+ min_width="300"
+ width="800">
+ <string name="control_background_image_name">Inspector_Background</string>
+ <string name="skip_step">0.2</string>
+ <string name="min_width">300</string>
+ <string name="min_height">75</string>
+ <string name="zoom_near_padding">1.0</string>
+ <string name="zoom_medium_padding">1.1</string>
+ <string name="zoom_far_padding">1.5</string>
+ <string name="top_world_view_avoid_zone">50</string>
+ <layout_stack
+ name="progress_indicator_area"
+ follows="left|right|top"
+ height="8"
+ layout="topleft"
+ animate="false"
+ left="0"
+ orientation="horizontal"
+ top="22">
+ <!-- outer layout_panels center the inner one -->
+ <layout_panel
+ width="0"
+ name="left_bookend_bottom"
+ mouse_opaque="false"
+ layout="topleft"
+ user_resize="false" />
+ <panel
+ name="media_progress_indicator"
+ mouse_opaque="false"
+ follows="left|right|top"
+ height="8"
+ layout="topleft"
+ left="0"
+ top="0"
+ auto_resize="false"
+ user_resize="false"
+ min_width="100"
+ width="200">
+ <progress_bar
+ name="media_progress_bar"
+ color_bg="1 1 1 1"
+ color_bar="1 1 1 0.96"
+ follows="left|right|top"
+ height="8"
+ layout="topleft"
+ top="0"
+ left="0"
+ tool_tip="Media is Loading"/>
+ </panel>
+ <layout_panel
+ name="right_bookend_bottom"
+ width="0"
+ mouse_opaque="false"
+ layout="topleft"
+ user_resize="false" />
+ </layout_stack>
+ <layout_stack
+ name="media_controls"
+ follows="left|right|top"
+ animate="false"
+ height="75"
+ layout="topleft"
+ top="0"
+ left="0"
+ border_size="1"
+ mouse_opaque="false"
+ orientation="horizontal">
+ <!-- outer layout_panels center the inner one -->
+ <layout_panel
+ name="left_bookend"
+ top="0"
+ width="0"
+ mouse_opaque="false"
+ layout="topleft"
+ user_resize="false" />
+ <layout_panel
+ name="back"
+ top="0"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ mouse_opaque="false"
+ min_width="22"
+ width="22">
+ <button
+ name="back_btn"
+ follows="top"
+ image_overlay="Arrow_Left_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ auto_resize="false"
+ layout="topleft"
+ tool_tip="Navigate back"
+ top="0"
+ left="0"
+ width="22"
+ height="22">
+ <button.commit_callback
+ function="MediaCtrl.Back" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="fwd"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ min_width="22"
+ top="0"
+ height="22"
+ width="22">
+ <button
+ name="fwd_btn"
+ follows="top"
+ image_overlay="Arrow_Right_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ top="0"
+ height="22"
+ width="22"
+ layout="topleft"
+ tool_tip="Navigate forward">
+ <button.commit_callback
+ function="MediaCtrl.Forward" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="home"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ height="22"
+ min_width="22"
+ width="22">
+ <button
+ name="home_btn"
+ follows="top"
+ image_overlay="Home_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ layout="topleft"
+ tool_tip="Home page"
+ top="0"
+ height="22"
+ width="22">
+ <button.commit_callback
+ function="MediaCtrl.Home" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="media_stop"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ height="22"
+ min_width="22"
+ width="22">
+ <button
+ name="media_stop_btn"
+ follows="top"
+ image_overlay="Stop_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ layout="topleft"
+ tool_tip="Stop media"
+ top="0"
+ height="22"
+ width="22">
+ <button.commit_callback
+ function="MediaCtrl.MediaStop" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="reload"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ height="22"
+ min_width="22"
+ width="22">
+ <button
+ name="reload_btn"
+ follows="top"
+ image_overlay="Refresh_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ layout="topleft"
+ tool_tip="Reload"
+ top="0"
+ height="22"
+ width="22">
+ <button.commit_callback
+ function="MediaCtrl.Reload" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="stop"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ height="22"
+ min_width="22"
+ width="22">
+ <button
+ name="stop_btn"
+ follows="top"
+ image_overlay="StopReload_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ layout="topleft"
+ tool_tip = "Stop loading"
+ top="0"
+ height="22"
+ width="22">
+ <button.commit_callback
+ function="MediaCtrl.Stop" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="play"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ height="22"
+ min_width="22"
+ width="24">
+ <button
+ name="play_btn"
+ follows="top"
+ image_overlay="Play_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ layout="topleft"
+ tool_tip = "Play media"
+ left_delta="2"
+ top="0"
+ height="22"
+ width="22">
+ <button.commit_callback
+ function="MediaCtrl.Play" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="pause"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ min_width="22"
+ width="24">
+ <button
+ name="pause_btn"
+ follows="top"
+ image_overlay="Pause_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ layout="topleft"
+ top="0"
+ height="22"
+ width="22"
+ left_delta="-1"
+ tool_tip = "Pause media">
+ <button.commit_callback
+ function="MediaCtrl.Pause" />
+ </button>
+ </layout_panel>
+ <!-- media URL entry -->
+ <layout_panel
+ name="media_address"
+ mouse_opaque="false"
+ auto_resize="true"
+ user_resize="false"
+ height="24"
+ follows="left|right|bottom"
+ layout="topleft"
+ top="0"
+ width="190"
+ min_width="90">
+ <line_editor
+ name="media_address_url"
+ max_length="1024"
+ follows="top|left|right"
+ height="22"
+ top="0"
+ tool_tip="Media URL"
+ text_pad_right="16">
+ <line_editor.commit_callback
+ function="MediaCtrl.CommitURL"/>
+ </line_editor>
+ <layout_stack
+ name="media_address_url_icons"
+ animate="false"
+ follows="top|right"
+ height="20"
+ width="38"
+ top="0"
+ right="-1"
+ border_size="0"
+ mouse_opaque="false"
+ orientation="horizontal">
+ <layout_panel
+ layout="topleft"
+ width="16"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false">
+ <icon
+ name="media_whitelist_flag"
+ follows="top|right"
+ height="16"
+ image_name="Flag"
+ layout="topleft"
+ tool_tip="White List enabled"
+ width="16" />
+ </layout_panel>
+ <layout_panel
+ layout="topleft"
+ width="16"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false">
+ <icon
+ name="media_secure_lock_flag"
+ height="16"
+ image_name="Lock2"
+ layout="topleft"
+ tool_tip="Secured Browsing"
+ width="16" />
+ </layout_panel>
+ </layout_stack>
+ </layout_panel>
+ <layout_panel
+ name="media_play_position"
+ mouse_opaque="false"
+ auto_resize="true"
+ user_resize="false"
+ follows="left|right"
+ layout="topleft"
+ top="0"
+ height="22"
+ min_width="100"
+ width="200">
+ <slider_bar
+ name="media_play_slider"
+ follows="left|right|top"
+ top="0"
+ height="22"
+ increment="0.01"
+ initial_value="0.5"
+ layout="topleft"
+ tool_tip="Movie play progress"
+ width="200">
+ <slider_bar.commit_callback
+ function="MediaCtrl.JumpProgress" />
+ </slider_bar>
+ </layout_panel>
+ <layout_panel
+ name="skip_back"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ min_width="22"
+ width="22">
+ <button
+ name="skip_back_btn"
+ follows="top"
+ image_overlay="SkipBackward_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ auto_resize="false"
+ height="22"
+ layout="topleft"
+ tool_tip="Step back"
+ top="0"
+ width="22"
+ left="0">
+ <button.commit_callback
+ function="MediaCtrl.SkipBack" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="skip_forward"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ min_width="22"
+ width="22">
+ <button
+ name="skip_forward_btn"
+ follows="top"
+ image_overlay="SkipForward_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ height="22"
+ layout="topleft"
+ tool_tip="Step forward"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="MediaCtrl.SkipForward" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="media_volume"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ height="72"
+ min_width="22"
+ width="22">
+ <!-- Note: this is not quite right either...the mute button is not the -->
+ <!-- same as the others because it cannot have the "image_overlay" be -->
+ <!-- two different images. -->
+ <!-- Note also: the button and the slider must overlap! -->
+ <button
+ name="media_mute_button"
+ follows="top"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="AudioMute_Off"
+ image_unselected="Audio_Off"
+ hover_glow_amount="0.15"
+ is_toggle="true"
+ layout="topleft"
+ scale_image="false"
+ tool_tip="Mute This Media"
+ top="0"
+ height="20"
+ width="22" >
+ <button.commit_callback
+ function="MediaCtrl.ToggleMute" />
+ <button.mouseenter_callback
+ function="MediaCtrl.ShowVolumeSlider" />
+ <button.mouseleave_callback
+ function="MediaCtrl.HideVolumeSlider" />
+ </button>
+ <slider
+ orientation="vertical"
+ left="0"
+ top="16"
+ height="50"
+ layout="topleft"
+ increment="0.01"
+ initial_value="0.5"
+ name="volume_slider"
+ tool_tip="Media Volume"
+ show_text="false"
+ volume="true">
+ <slider.commit_callback
+ function="MediaCtrl.Volume"/>
+ <slider.mouseenter_callback
+ function="MediaCtrl.ShowVolumeSlider" />
+ <slider.mouseleave_callback
+ function="MediaCtrl.HideVolumeSlider" />
+ </slider>
+ </layout_panel>
+ <layout_panel
+ name="zoom_frame"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ height="28"
+ min_width="22"
+ width="22">
+ <button
+ name="zoom_frame_btn"
+ follows="top"
+ image_overlay="Zoom_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ top="0"
+ height="22"
+ layout="topleft"
+ tool_tip="Zoom into media"
+ width="22">
+ <button.commit_callback
+ function="MediaCtrl.Zoom" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="close"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ min_width="21"
+ width="21" >
+ <button
+ name="close_btn"
+ follows="top"
+ image_overlay="UnZoom_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ top="0"
+ height="22"
+ layout="topleft"
+ tool_tip ="Zoom Back"
+ top_delta="-4"
+ width="21" >
+ <button.commit_callback
+ function="MediaCtrl.Close" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="new_window"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ min_width="22"
+ width="22">
+ <button
+ name="new_window_btn"
+ follows="top"
+ image_overlay="ExternalBrowser_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ height="22"
+ layout="topleft"
+ tool_tip = "Open URL in browser"
+ top="0"
+ width="24" >
+ <button.commit_callback
+ function="MediaCtrl.Open" />
+ </button>
+ </layout_panel>
+ <!-- bookend panel -->
+ <layout_panel
+ name="right_bookend"
+ mouse_opaque="false"
+ top="0"
+ width="0"
+ layout="topleft"
+ user_resize="false" />
+ </layout_stack>
+ <panel
+ name="media_region"
+ height="100"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ mouse_opaque="false"
+ top="30" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml
new file mode 100644
index 0000000000..7c584ba2c8
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_profile.xml
@@ -0,0 +1,384 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="all"
+ height="540"
+ label="Profile"
+ layout="topleft"
+ left="0"
+ name="panel_profile"
+ top="0"
+ width="313">
+ <string
+ name="CaptionTextAcctInfo">
+ [ACCTTYPE]
+[PAYMENTINFO] [AGEVERIFICATION]
+ </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="None" />
+ <string
+ name="no_group_text"
+ value="None" />
+ <string
+ name="RegisterDateFormat">
+ [REG_DATE] ([AGE])
+ </string>
+ <layout_stack
+ name="layout"
+ orientation="vertical"
+ follows="all"
+ layout="topleft"
+ left="0"
+ top="0"
+ height="517"
+ width="313"
+ border_size="0">
+ <layout_panel
+ name="profile_stack"
+ follows="all"
+ layout="topleft"
+ top="0"
+ left="0"
+ height="505"
+ width="313">
+ <scroll_container
+ color="DkGray2"
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="profile_scroll"
+ opaque="true"
+ height="505"
+ width="313"
+ top="0">
+ <panel
+ layout="topleft"
+ follows="left|top|right"
+ height="505"
+ min_height="505"
+ name="profile_scroll_panel"
+ top="0"
+ left="0"
+ width="297">
+ <panel
+ follows="left|top|right"
+ height="117"
+ layout="topleft"
+ left="10"
+ name="second_life_image_panel"
+ top="0"
+ width="297">
+ <texture_picker
+ allow_no_texture="true"
+ default_image_name="None"
+ enabled="false"
+ follows="top|left"
+ height="117"
+ layout="topleft"
+ left="0"
+ name="2nd_life_pic"
+ top="10"
+ width="102" />
+ <text
+ follows="left|top|right"
+ font.style="BOLD"
+ height="15"
+ layout="topleft"
+ left_pad="10"
+ name="title_sl_descr_text"
+ text_color="white"
+ top_delta="0"
+ value="[SECOND_LIFE]:"
+ width="180" />
+ <expandable_text
+ follows="left|top|right"
+ height="95"
+ layout="topleft"
+ left="107"
+ textbox.max_length="512"
+ name="sl_description_edit"
+ top_pad="-3"
+ width="180"
+ expanded_bg_visible="true"
+ expanded_bg_color="DkGray">
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean viverra orci et justo sagittis aliquet.Nullamma lesuada mauris sit amet ipsum. adipiscing elit. Ae nean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ <panel
+ follows="left|top|right"
+ height="117"
+ layout="topleft"
+ top_pad="10"
+ left="10"
+ name="first_life_image_panel"
+ width="297">
+ <texture_picker
+ allow_no_texture="true"
+ default_image_name="None"
+ enabled="false"
+ follows="top|left"
+ height="117"
+ layout="topleft"
+ left="0"
+ name="real_world_pic"
+ width="102" />
+ <text
+ follows="left|top|right"
+ font.style="BOLD"
+ height="15"
+ layout="topleft"
+ left_pad="10"
+ name="title_rw_descr_text"
+ text_color="white"
+ top_delta="0"
+ value="Real World:"
+ width="180" />
+ <expandable_text
+ follows="left|top|right"
+ height="95"
+ layout="topleft"
+ left="107"
+ textbox.max_length="512"
+ name="fl_description_edit"
+ top_pad="-3"
+ width="180"
+ expanded_bg_visible="true"
+ expanded_bg_color="DkGray">
+ Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ <text
+ follows="left|top"
+ height="15"
+ font.style="BOLD"
+ font="SansSerifMedium"
+ layout="topleft"
+ left="10"
+ name="homepage_edit"
+ top_pad="0"
+ value="http://librarianavengers.org"
+ width="300"
+ word_wrap="false"
+ use_ellipses="true"
+ />
+ <text
+ follows="left|top"
+ font.style="BOLD"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="title_member_text"
+ text_color="white"
+ top_pad="10"
+ value="Resident Since:"
+ width="300" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="register_date"
+ value="05/31/2376"
+ width="300"
+ word_wrap="true" />
+ <text
+ follows="left|top"
+ font.style="BOLD"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="title_acc_status_text"
+ text_color="white"
+ top_pad="5"
+ value="Account Status:"
+ width="300" />
+ <!-- <text
+ type="string"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="15"
+ layout="topleft"
+ left_pad="10"
+ name="my_account_link"
+ top_delta="0"
+ value="Go to Dashboard"
+ width="100"/> -->
+ <text
+ follows="left|top"
+ height="28"
+ layout="topleft"
+ left="10"
+ name="acc_status_text"
+ top_pad="0"
+ width="300"
+ word_wrap="true">
+ Resident. No payment info on file.
+ Linden.
+ </text>
+ <text
+ follows="left|top"
+ font.style="BOLD"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="title_partner_text"
+ text_color="white"
+ top_pad="3"
+ value="Partner:"
+ width="300" />
+ <panel
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="partner_data_panel"
+ top_pad="0"
+ width="300">
+ <name_box
+ follows="left|top"
+ height="10"
+ initial_value="(retrieving)"
+ layout="topleft"
+ left="0"
+ link="true"
+ name="partner_text"
+ top="0"
+ width="300"
+ word_wrap="true" />
+ </panel>
+ <text
+ follows="left|top"
+ font.style="BOLD"
+ height="13"
+ layout="topleft"
+ left="10"
+ name="title_groups_text"
+ text_color="white"
+ top_pad="3"
+ value="Groups:"
+ width="300" />
+ <expandable_text
+ follows="all"
+ height="113"
+ layout="topleft"
+ left="7"
+ name="sl_groups"
+ top_pad="0"
+ width="290"
+ expanded_bg_visible="true"
+ expanded_bg_color="DkGray">
+ Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. Aenean viverra tulip moosetop. Slan de heelish marfnik tooplod. Sum sum to whop de wompam booster copm.
+ </expandable_text>
+ </panel>
+ </scroll_container>
+ </layout_panel>
+ <layout_panel
+ follows="bottom|left"
+ height="30"
+ layout="topleft"
+ name="profile_buttons_panel"
+ auto_resize="false"
+ width="313">
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Add Friend"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="add_friend"
+ tool_tip="Offer friendship to the Resident"
+ top="5"
+ width="80" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="IM"
+ layout="topleft"
+ name="im"
+ tool_tip="Open instant message session"
+ top="5"
+ left_pad="3"
+ width="45" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Call"
+ layout="topleft"
+ name="call"
+ tool_tip="Call this Resident"
+ left_pad="3"
+ top="5"
+ width="45" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ height="23"
+ label="Map"
+ layout="topleft"
+ name="show_on_map_btn"
+ tool_tip="Show the Resident on the map"
+ top="5"
+ left_pad="3"
+ width="45" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Teleport"
+ layout="topleft"
+ name="teleport"
+ tool_tip="Offer teleport"
+ left_pad="3"
+ top="5"
+ width="85" />
+ <!-- <button
+ follows="bottom|right"
+ height="23"
+ label="â–¼"
+ layout="topleft"
+ name="overflow_btn"
+ tool_tip="Pay money to or share inventory with the Resident"
+ right="-1"
+ top="5"
+ left_pad="3"
+ width="23" />-->
+ </layout_panel>
+ <layout_panel
+ follows="bottom|left"
+ height="30"
+ layout="topleft"
+ name="profile_me_buttons_panel"
+ visible="false"
+ width="313">
+ <button
+ follows="bottom|right"
+ height="23"
+ left="20"
+ top="0"
+ label="Edit Profile"
+ name="edit_profile_btn"
+ tool_tip="Edit your personal information"
+ width="130" />
+ <button
+ follows="bottom|right"
+ height="23"
+ label="Edit Appearance"
+ left_pad="10"
+ name="edit_appearance_btn"
+ tool_tip="Create/edit your appearance: physical data, clothes and etc."
+ width="130" />
+ </layout_panel>
+
+</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_profile_view.xml b/indra/newview/skins/default/xui/en/panel_profile_view.xml
new file mode 100644
index 0000000000..d46e1f9852
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_profile_view.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ follows="all"
+ height="570"
+ layout="topleft"
+ min_height="350"
+ name="panel_target_profile"
+ width="333">
+ <string
+ name="status_online">
+ Online
+ </string>
+ <string
+ name="status_offline">
+ Offline
+ </string>
+ <button
+ follows="top|right"
+ height="23"
+ image_overlay="BackArrow_Off"
+ layout="topleft"
+ name="back"
+ left="10"
+ tab_stop="false"
+ top="2"
+ width="23" />
+ <text_editor
+ allow_scroll="false"
+ bg_visible="false"
+ read_only = "true"
+ follows="top|left|right"
+ font="SansSerifHugeBold"
+ height="29"
+ layout="topleft"
+ left_pad="10"
+ name="user_name"
+ text_color="white"
+ top="0"
+ value="(Loading...)"
+ use_ellipses="true"
+ width="275" />
+ <text
+ follows="top|left"
+ height="13"
+ layout="topleft"
+ left="45"
+ name="status"
+ text_color="LtGray_50"
+ value="Online"
+ width="150" />
+ <tab_container
+ follows="all"
+ height="535"
+ halign="center"
+ layout="topleft"
+ left="10"
+ min_width="333"
+ name="tabs"
+ tab_min_width="80"
+ tab_height="30"
+ tab_position="top"
+ top_pad="5"
+ width="313">
+ <panel
+ class="panel_profile"
+ filename="panel_profile.xml"
+ label="PROFILE"
+ layout="topleft"
+ help_topic="profile_profile_tab"
+ name="panel_profile" />
+ <panel
+ class="panel_picks"
+ filename="panel_picks.xml"
+ label="PICKS"
+ layout="topleft"
+ help_topic="profile_picks_tab"
+ name="panel_picks" />
+ <panel
+ class="panel_notes"
+ filename="panel_notes.xml"
+ label="NOTES &amp; PRIVACY"
+ layout="topleft"
+ help_topic="profile_notes_tab"
+ name="panel_notes" />
+ </tab_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_progress.xml b/indra/newview/skins/default/xui/en/panel_progress.xml
new file mode 100644
index 0000000000..727c5fb7b2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_progress.xml
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="left|bottom|right|top"
+ height="768"
+ layout="topleft"
+ left="0"
+ name="login_progress_panel"
+ top="768"
+ width="1024">
+ <layout_stack
+ follows="left|right|top|bottom"
+ height="768"
+ layout="topleft"
+ left="0"
+ name="stack1"
+ orientation="horizontal"
+ top="0"
+ width="1024">
+ <layout_panel
+ layout="topleft"
+ min_width="10"
+ name="panel1"
+ user_resize="false"
+ width="150" />
+ <layout_panel
+ height="768"
+ layout="topleft"
+ min_width="640"
+ name="panel2"
+ user_resize="false"
+ width="640">
+ <layout_stack
+ follows="left|right|top|bottom"
+ height="768"
+ layout="topleft"
+ left="0"
+ name="stack2"
+ top="0"
+ width="640">
+ <layout_panel
+ height="200"
+ layout="topleft"
+ min_height="10"
+ name="panel3"
+ width="640" />
+ <layout_panel
+ auto_resize="false"
+ height="250"
+ layout="topleft"
+ min_height="250"
+ name="panel4"
+ width="640">
+ <icon
+ color="LoginProgressBoxCenterColor"
+ follows="left|right|bottom|top"
+ height="250"
+ image_name="Rounded_Square"
+ layout="topleft"
+ left="0"
+ top="0"
+ width="640" />
+ <text
+ follows="left|right|top"
+ font="SansSerifHuge"
+ font_shadow="none"
+ halign="left"
+ height="20"
+ layout="topleft"
+ left_delta="47"
+ name="title_text"
+ text_color="LoginProgressBoxTextColor"
+ top_delta="50"
+ width="593" />
+ <text
+ follows="left|right|top"
+ font="SansSerif"
+ font_shadow="none"
+ halign="left"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="progress_text"
+ text_color="LoginProgressBoxTextColor"
+ top_pad="5"
+ width="593"
+ word_wrap="true"/>
+ <progress_bar
+ bottom="115"
+ color_bar="1 1 1 0.96"
+ follows="left|right|top"
+ height="16"
+ layout="topleft"
+ left="45"
+ name="login_progress_bar"
+ right="-45" />
+ <text
+ follows="left|right|top|bottom"
+ font="SansSerifLarge"
+ font_shadow="none"
+ halign="left"
+ height="100"
+ layout="topleft"
+ left="45"
+ line_spacing.pixels="2"
+ name="message_text"
+ text_color="LoginProgressBoxTextColor"
+ top="145"
+ width="550"
+ word_wrap="true"/>
+ </layout_panel>
+ <layout_panel
+ height="200"
+ layout="topleft"
+ min_width="10"
+ name="panel5"
+ width="640" />
+ </layout_stack>
+ </layout_panel>
+ <layout_panel
+ layout="topleft"
+ min_width="10"
+ name="panel6"
+ user_resize="false"
+ width="150" />
+ </layout_stack>
+ <button
+ follows="right|bottom"
+ height="22"
+ layout="topleft"
+ left="-106"
+ name="cancel_btn"
+ top="700"
+ width="90" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_region_covenant.xml b/indra/newview/skins/default/xui/en/panel_region_covenant.xml
new file mode 100644
index 0000000000..dc8f71c868
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_region_covenant.xml
@@ -0,0 +1,278 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="top|left"
+ height="320"
+ help_topic="panel_region_covenant_tab"
+ label="Covenant"
+ layout="topleft"
+ left="0"
+ name="Covenant"
+ top="320"
+ width="480">
+ <panel.string
+ name="can_resell">
+ Purchased land in this region may be resold.
+ </panel.string>
+ <panel.string
+ name="can_not_resell">
+ Purchased land in this region may not be resold.
+ </panel.string>
+ <panel.string
+ name="can_change">
+ Purchased land in this region may be joined or subdivided.
+ </panel.string>
+ <panel.string
+ name="can_not_change">
+ Purchased land in this region may not be joined or subdivided.
+ </panel.string>
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left="5"
+ mouse_opaque="false"
+ name="estate_section_lbl"
+ top="5"
+ width="100">
+ Estate
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="estate_name_lbl"
+ top_pad="5"
+ width="100">
+ Name:
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="10"
+ mouse_opaque="false"
+ name="estate_name_text"
+ top_delta="0"
+ width="150">
+ mainland
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="estate_owner_lbl"
+ top_pad="5"
+ width="100">
+ Owner:
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="10"
+ mouse_opaque="false"
+ name="estate_owner_text"
+ top_delta="0"
+ width="150">
+ (none)
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="estate_cov_lbl"
+ top_pad="5"
+ width="100">
+ Covenant:
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="10"
+ mouse_opaque="false"
+ name="covenant_timestamp_text"
+ top_delta="0"
+ width="308">
+ Last Modified Wed Dec 31 16:00:00 1969
+ </text>
+ <text_editor
+ enabled="false"
+ follows="left|top"
+ height="100"
+ layout="topleft"
+ left="110"
+ max_length="65535"
+ name="covenant_editor"
+ top_delta="30"
+ handle_edit_keys_directly="true"
+ width="340"
+ word_wrap="true">
+ There is no Covenant provided for this Estate.
+ </text_editor>
+ <button
+ follows="left|top"
+ height="18"
+ label="Reset"
+ layout="topleft"
+ left_delta="250"
+ name="reset_covenant"
+ top_pad="5"
+ width="90" />
+
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="120"
+ name="covenant_help_text"
+ top_pad="10"
+ word_wrap="true"
+ width="360">
+ Changes to the covenant will show on all parcels in the estate.
+ </text>
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="covenant_instructions"
+ top_pad="5"
+ word_wrap="true"
+ font.style="ITALIC"
+ width="360">
+ Drag and drop a notecard to change the Covenant for this estate.
+ </text>
+
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left="5"
+ mouse_opaque="false"
+ name="region_section_lbl"
+ top_pad="5"
+ width="100">
+ Region
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="region_name_lbl"
+ top_pad="5"
+ width="100">
+ Name:
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="10"
+ mouse_opaque="false"
+ name="region_name_text"
+ top_delta="0"
+ width="150">
+ Erica
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="region_landtype_lbl"
+ top_pad="5"
+ width="100">
+ Type:
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="10"
+ mouse_opaque="false"
+ name="region_landtype_text"
+ top_delta="0"
+ width="150">
+ Mainland / Homestead
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="region_maturity_lbl"
+ top_pad="5"
+ width="100">
+ Rating:
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="10"
+ mouse_opaque="false"
+ name="region_maturity_text"
+ top_delta="0"
+ width="150">
+ Adult
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="resellable_lbl"
+ top_pad="5"
+ width="100">
+ Resale:
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="10"
+ mouse_opaque="false"
+ name="resellable_clause"
+ top_delta="0"
+ width="330">
+ Land in this region may not be resold.
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="changeable_lbl"
+ top_pad="5"
+ width="100">
+ Subdivide:
+ </text>
+ <text
+ follows="left|top"
+ height="30"
+ layout="topleft"
+ left_pad="10"
+ mouse_opaque="false"
+ name="changeable_clause"
+ top_delta="0"
+ width="330">
+ Land in this region may not be joined/subdivided.
+ </text>
+
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_region_debug.xml b/indra/newview/skins/default/xui/en/panel_region_debug.xml
new file mode 100644
index 0000000000..a6b4ddd01e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_region_debug.xml
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="top|left"
+ height="320"
+ help_topic="panel_region_debug_tab"
+ label="Debug"
+ layout="topleft"
+ left="0"
+ name="Debug"
+ top="320"
+ width="480">
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="region_text_lbl"
+ top="10"
+ width="100">
+ Region:
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_delta="50"
+ name="region_text"
+ top_delta="0"
+ width="400">
+ unknown
+ </text>
+ <check_box
+ height="20"
+ label="Disable Scripts"
+ layout="topleft"
+ left="10"
+ name="disable_scripts_check"
+ tool_tip="Disable all scripts in this region"
+ top="30"
+ width="80" />
+ <check_box
+ height="20"
+ label="Disable Collisions"
+ layout="topleft"
+ left="10"
+ name="disable_collisions_check"
+ tool_tip="Disable non-avatar collisions in this region"
+ top="50"
+ width="80" />
+ <check_box
+ height="20"
+ label="Disable Physics"
+ layout="topleft"
+ left="10"
+ name="disable_physics_check"
+ tool_tip="Disable all physics in this region"
+ top="70"
+ width="80" />
+ <button
+ enabled="false"
+ follows="left|top"
+ height="20"
+ label="Apply"
+ layout="topleft"
+ left="60"
+ name="apply_btn"
+ top="100"
+ width="100" />
+ <text
+
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="objret_text_lbl"
+ top="150"
+ width="90">
+ Object Return
+ </text>
+ <text
+
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="30"
+ name="resident_text_lbl"
+ top="175"
+ width="60">
+ Resident:
+ </text>
+ <line_editor
+
+ border_style="line"
+ border_thickness="1"
+ enabled="false"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_delta="60"
+ mouse_opaque="false"
+ name="target_avatar_name"
+ top_delta="-2"
+ width="180">
+ (none)
+ </line_editor>
+ <button
+ follows="left|top"
+ height="20"
+ label="Choose"
+ layout="topleft"
+ left_pad="5"
+ name="choose_avatar_btn"
+ top_delta="0"
+ width="70" />
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="30"
+ name="options_text_lbl"
+ top="198"
+ width="60">
+ Options:
+ </text>
+ <check_box
+ height="20"
+ label="With scripts"
+ layout="topleft"
+ left_delta="60"
+ name="return_scripts"
+ tool_tip="Return only objects which have scripts"
+ top_delta="0"
+ width="80" />
+ <check_box
+ height="20"
+ label="On someone else&apos;s land"
+ layout="topleft"
+ left_delta="0"
+ name="return_other_land"
+ tool_tip="Return only objects which are on land belonging to someone else"
+ top_delta="20"
+ width="80" />
+ <check_box
+ height="20"
+ label="In every region of this estate"
+ layout="topleft"
+ left_delta="0"
+ name="return_estate_wide"
+ tool_tip="Return objects in all of the regions that make up this estate"
+ top_delta="20"
+ width="80" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Return"
+ layout="topleft"
+ left="20"
+ name="return_btn"
+ top="263"
+ width="80" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Get Top Colliders..."
+ layout="topleft"
+ left="10"
+ name="top_colliders_btn"
+ tool_tip="List of objects experiencing the most potential collisions"
+ top="313"
+ width="150" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Get Top Scripts..."
+ layout="topleft"
+ left="10"
+ name="top_scripts_btn"
+ tool_tip="List of objects spending the most time running scripts"
+ top_pad="5"
+ width="150" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Restart Region"
+ layout="topleft"
+ left="10"
+ name="restart_btn"
+ tool_tip="Give 2 minute countdown and restart region"
+ top_pad="5"
+ width="130" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Delay Restart"
+ layout="topleft"
+ left="10"
+ name="cancel_restart_btn"
+ tool_tip="Delay region restart by one hour"
+ top_pad="5"
+ width="130" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_region_estate.xml b/indra/newview/skins/default/xui/en/panel_region_estate.xml
new file mode 100644
index 0000000000..3980eb86d3
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_region_estate.xml
@@ -0,0 +1,396 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="false"
+ follows="top|left"
+ height="320"
+ help_topic="panel_region_estate_tab"
+ label="Estate"
+ layout="topleft"
+ left="0"
+ name="Estate"
+ top="320"
+ width="480">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="32"
+ layout="topleft"
+ left="10"
+ name="estate_help_text"
+ top="14"
+ word_wrap="true"
+ width="275">
+ Changes to settings on this tab will affect all regions in the estate.
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="estate_text"
+ top_pad="2"
+ width="80">
+ Estate:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="estate_name"
+ top_delta="16"
+ width="150">
+ (unknown)
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="owner_text"
+ top_pad="2"
+ width="80">
+ Estate owner:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="estate_owner"
+ top_delta="16"
+ width="150">
+ (unknown)
+ </text>
+ <view_border
+ bevel_style="in"
+ follows="top|left"
+ height="270"
+ layout="topleft"
+ left_delta="-4"
+ top_pad="5"
+ width="250" />
+ <check_box
+ height="20"
+ label="Use Global Time"
+ layout="topleft"
+ left="12"
+ name="use_global_time_check"
+ top="132"
+ width="200" />
+ <check_box
+ height="20"
+ label="Fixed Sun"
+ layout="topleft"
+ left="12"
+ name="fixed_sun_check"
+ top="152"
+ width="100" />
+ <icon
+ height="20"
+ image_name="icon_day_cycle.tga"
+ layout="topleft"
+ left="47"
+ name="daycycle"
+ top="177"
+ width="165" />
+ <slider
+ follows="left|top"
+ height="20"
+ increment="0.001"
+ label="Phase"
+ layout="topleft"
+ left="12"
+ max_val="30"
+ min_val="6"
+ name="sun_hour_slider"
+ show_text="false"
+ top="202"
+ width="200" />
+ <check_box
+ height="20"
+ label="Allow Public Access"
+ layout="topleft"
+ left_delta="0"
+ name="externally_visible_check"
+ top_pad="6"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ height="16"
+ layout="topleft"
+ left="32"
+ name="Only Allow"
+ top="250"
+ width="278">
+ Restrict Access to accounts verified by:
+ </text>
+ <check_box
+ follows="top|left"
+ height="16"
+ label="Payment Information on File"
+ layout="topleft"
+ left_delta="0"
+ name="limit_payment"
+ tool_tip="Ban unidentified Residents"
+ top_pad="2"
+ width="278" />
+ <check_box
+ follows="top|left"
+ height="16"
+ label="Age Verification"
+ layout="topleft"
+ left_delta="0"
+ name="limit_age_verified"
+ tool_tip="Ban Residents who have not verified their age. See the [SUPPORT_SITE] for more information."
+ top_pad="2"
+ width="278" />
+ <check_box
+ height="20"
+ label="Allow Voice Chat"
+ layout="topleft"
+ left="12"
+ name="voice_chat_check"
+ top="304"
+ width="200" />
+ <check_box
+ height="20"
+ label="Allow Direct Teleport"
+ layout="topleft"
+ left="12"
+ name="allow_direct_teleport"
+ top_pad="4"
+ width="80" />
+ <button
+ enabled="false"
+ follows="left|top"
+ height="23"
+ label="Apply"
+ layout="topleft"
+ name="apply_btn"
+ top_pad="10"
+ left="78"
+ width="97" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Send Message To Estate..."
+ layout="topleft"
+ left="50"
+ name="message_estate_btn"
+ top_pad="20"
+ width="160" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Kick User from Estate..."
+ layout="topleft"
+ left="50"
+ name="kick_user_from_estate_btn"
+ top_pad="5"
+ width="160" />
+
+ <text
+ type="string"
+ length="1"
+ bottom="34"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ name="estate_manager_label"
+ right="470"
+ width="200">
+ Estate Managers:
+ </text>
+ <view_border
+ bevel_style="none"
+ follows="top|left"
+ height="71"
+ layout="topleft"
+ right="470"
+ top_pad="-5"
+ width="200" />
+ <name_list
+ follows="left|top"
+ height="71"
+ layout="topleft"
+ left_delta="0"
+ multi_select="true"
+ name="estate_manager_name_list"
+ top_delta="0"
+ width="200" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Remove..."
+ layout="topleft"
+ name="remove_estate_manager_btn"
+ right="470"
+ top_pad="5"
+ width="97" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Add..."
+ layout="topleft"
+ left_delta="-103"
+ name="add_estate_manager_btn"
+ top_delta="0"
+ width="97" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="allow_resident_label"
+ top_pad="10"
+ width="200">
+ Allowed Residents:
+ </text>
+ <view_border
+ bevel_style="none"
+ follows="top|left"
+ height="71"
+ layout="topleft"
+ right="470"
+ top_pad="-5"
+ width="200" />
+ <name_list
+ follows="left|top"
+ height="71"
+ layout="topleft"
+ left_delta="0"
+ multi_select="true"
+ name="allowed_avatar_name_list"
+ top_delta="0"
+ width="200" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Remove..."
+ layout="topleft"
+ name="remove_allowed_avatar_btn"
+ right="470"
+ top_pad="5"
+ width="97" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Add..."
+ layout="topleft"
+ left_delta="-103"
+ name="add_allowed_avatar_btn"
+ top_delta="0"
+ width="97" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="allow_group_label"
+ top_pad="10"
+ width="200">
+ Allowed Groups:
+ </text>
+ <view_border
+ bevel_style="none"
+ follows="top|left"
+ height="71"
+ layout="topleft"
+ right="470"
+ top_pad="-5"
+ width="200" />
+ <name_list
+ follows="left|top"
+ height="71"
+ layout="topleft"
+ left_delta="0"
+ multi_select="true"
+ name="allowed_group_name_list"
+ top_delta="0"
+ width="200" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Remove..."
+ layout="topleft"
+ name="remove_allowed_group_btn"
+ right="470"
+ top_pad="5"
+ width="97" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Add..."
+ layout="topleft"
+ left_delta="-103"
+ name="add_allowed_group_btn"
+ top_delta="0"
+ width="97" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="ban_resident_label"
+ top_pad="10"
+ width="200">
+ Banned Residents:
+ </text>
+ <view_border
+ bevel_style="none"
+ follows="top|left"
+ height="71"
+ layout="topleft"
+ right="470"
+ top_pad="-5"
+ width="200" />
+ <name_list
+ follows="left|top"
+ height="71"
+ layout="topleft"
+ left_delta="0"
+ multi_select="true"
+ name="banned_avatar_name_list"
+ top_delta="0"
+ width="200" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Remove..."
+ layout="topleft"
+ name="remove_banned_avatar_btn"
+ right="470"
+ top_pad="5"
+ width="97" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Add..."
+ layout="topleft"
+ left_delta="-103"
+ name="add_banned_avatar_btn"
+ top_delta="0"
+ width="97" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_region_general.xml b/indra/newview/skins/default/xui/en/panel_region_general.xml
new file mode 100644
index 0000000000..26568c2a28
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_region_general.xml
@@ -0,0 +1,243 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="top|left"
+ height="320"
+ help_topic="panel_region_general_tab"
+ label="Region"
+ layout="topleft"
+ left="0"
+ name="General"
+ top="320"
+ width="480">
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="region_text_lbl"
+ top="10"
+ width="100">
+ Region:
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_delta="50"
+ name="region_text"
+ top_delta="0"
+ width="400">
+ unknown
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="version_channel_text_lbl"
+ top="30"
+ width="100">
+ Version:
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_delta="50"
+ name="version_channel_text"
+ top_delta="0"
+ width="200">
+ unknown
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="region_type_lbl"
+ top="50"
+ width="100">
+ Type:
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_delta="50"
+ name="region_type"
+ top_delta="0"
+ width="200">
+ unknown
+ </text>
+ <check_box
+ height="20"
+ label="Block Terraform"
+ layout="topleft"
+ left="10"
+ name="block_terraform_check"
+ top="70"
+ width="80" />
+ <check_box
+ height="20"
+ label="Block Fly"
+ layout="topleft"
+ left="10"
+ name="block_fly_check"
+ top="90"
+ width="80" />
+ <check_box
+ height="20"
+ label="Allow Damage"
+ layout="topleft"
+ left="10"
+ name="allow_damage_check"
+ top="110"
+ width="80" />
+ <check_box
+ height="20"
+ label="Restrict Pushing"
+ layout="topleft"
+ left="10"
+ name="restrict_pushobject"
+ top="130"
+ width="80" />
+ <check_box
+ height="20"
+ label="Allow Land Resell"
+ layout="topleft"
+ left="10"
+ name="allow_land_resell_check"
+ top="160"
+ width="80" />
+ <check_box
+ height="20"
+ label="Allow Land Join/Divide"
+ layout="topleft"
+ left="10"
+ name="allow_parcel_changes_check"
+ top="180"
+ width="80" />
+ <check_box
+ height="20"
+ label="Block Land Show in Search"
+ layout="topleft"
+ left="10"
+ name="block_parcel_search_check"
+ tool_tip="Let people see this region and its parcels in search results"
+ top="200"
+ width="80" />
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="1"
+ label="Agent Limit"
+ label_width="97"
+ layout="topleft"
+ left="10"
+ max_val="100"
+ min_val="1"
+ name="agent_limit_spin"
+ top="240"
+ width="170" />
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.5"
+ label="Object Bonus"
+ label_width="97"
+ layout="topleft"
+ left="10"
+ max_val="10"
+ min_val="1"
+ name="object_bonus_spin"
+ top="260"
+ width="170" />
+ <text
+ follows="left|top"
+ height="20"
+ label="Maturity"
+ layout="topleft"
+ left="10"
+ name="access_text"
+ top="290"
+ width="100">
+ Rating:
+ </text>
+ <combo_box
+ height="20"
+ label="Moderate"
+ layout="topleft"
+ left_delta="100"
+ name="access_combo"
+ top_delta="0"
+ width="85">
+ <combo_box.item
+ label="Adult"
+ name="Adult"
+ value="42" />
+ <combo_box.item
+ label="Moderate"
+ name="Mature"
+ value="21" />
+ <combo_box.item
+ label="General"
+ name="PG"
+ value="13" />
+ </combo_box>
+ <button
+ enabled="false"
+ follows="left|top"
+ height="20"
+ label="Apply"
+ layout="topleft"
+ left="108"
+ name="apply_btn"
+ top="320"
+ width="100"/>
+ <button
+ follows="left|top"
+ height="20"
+ label="Teleport Home One User..."
+ layout="topleft"
+ left="10"
+ name="kick_btn"
+ top_pad="10"
+ width="250" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Teleport Home All Users..."
+ layout="topleft"
+ left_delta="0"
+ name="kick_all_btn"
+ top_pad="3"
+ width="250" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Send Message To Region..."
+ layout="topleft"
+ left_delta="0"
+ name="im_btn"
+ top_pad="20"
+ width="200" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Manage Telehub..."
+ layout="topleft"
+ left="250"
+ name="manage_telehub_btn"
+ top="70"
+ width="150">
+ <button.commit_callback
+ function="RegionInfo.ManageTelehub" />
+ </button>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_region_general_layout.xml b/indra/newview/skins/default/xui/en/panel_region_general_layout.xml
new file mode 100644
index 0000000000..525c5aa8e7
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_region_general_layout.xml
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="top|left"
+ height="360"
+ label="Region"
+ layout="topleft"
+ left="0"
+ name="General"
+ top="360"
+ width="280">
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="region_text_lbl"
+ top="10"
+ width="100">
+ Region:
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_delta="50"
+ name="region_text"
+ top_delta="0"
+ width="200">
+ unknown
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="version_channel_text_lbl"
+ top="30"
+ width="100">
+ Version:
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_delta="50"
+ name="version_channel_text"
+ top_delta="0"
+ width="200">
+ unknown
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="region_type_lbl"
+ top="50"
+ width="100">
+ Type:
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_delta="50"
+ name="region_type"
+ top_delta="0"
+ width="200">
+ unknown
+ </text>
+ <check_box
+ height="20"
+ label="Block Terraform"
+ layout="topleft"
+ left="10"
+ name="block_terraform_check"
+ top="70"
+ width="80" />
+ <check_box
+ height="20"
+ label="Block Fly"
+ layout="topleft"
+ left="10"
+ name="block_fly_check"
+ top="90"
+ width="80" />
+ <check_box
+ height="20"
+ label="Allow Damage"
+ layout="topleft"
+ left="10"
+ name="allow_damage_check"
+ top="110"
+ width="80" />
+ <check_box
+ height="20"
+ label="Restrict Pushing"
+ layout="topleft"
+ left="10"
+ name="restrict_pushobject"
+ top="130"
+ width="80" />
+ <check_box
+ height="20"
+ label="Allow Land Resell"
+ layout="topleft"
+ left="10"
+ name="allow_land_resell_check"
+ top="160"
+ width="80" />
+ <check_box
+ height="20"
+ label="Allow Land Join/Divide"
+ layout="topleft"
+ left="10"
+ name="allow_parcel_changes_check"
+ top="180"
+ width="80" />
+ <check_box
+ height="20"
+ label="Block Land Show in Search"
+ layout="topleft"
+ left="10"
+ name="block_parcel_search_check"
+ tool_tip="Let people see this region and its parcels in search results"
+ top="200"
+ width="80" />
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="1"
+ label="Agent Limit"
+ label_width="97"
+ layout="topleft"
+ left="10"
+ max_val="100"
+ min_val="1"
+ name="agent_limit_spin"
+ top="240"
+ width="170" />
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.5"
+ label="Object Bonus"
+ label_width="97"
+ layout="topleft"
+ left="10"
+ max_val="10"
+ min_val="1"
+ name="object_bonus_spin"
+ top="260"
+ width="170" />
+ <text
+ follows="left|top"
+ height="20"
+ label="Maturity"
+ layout="topleft"
+ left="10"
+ name="access_text"
+ top="290"
+ width="100">
+ Rating:
+ </text>
+ <combo_box
+ height="20"
+ label="Moderate"
+ layout="topleft"
+ left_delta="100"
+ name="access_combo"
+ top_delta="0"
+ width="85">
+ <combo_box.item
+ label="Adult"
+ name="Adult"
+ value="42" />
+ <combo_box.item
+ label="Moderate"
+ name="Mature"
+ value="21" />
+ <combo_box.item
+ label="General"
+ name="PG"
+ value="13" />
+ </combo_box>
+ <button
+ enabled="false"
+ follows="left|top"
+ height="20"
+ label="Apply"
+ layout="topleft"
+ left="108"
+ name="apply_btn"
+ top="320"
+ width="100"/>
+ <button
+ follows="left|top"
+ height="20"
+ label="Teleport Home One User..."
+ layout="topleft"
+ left="10"
+ name="kick_btn"
+ top_pad="10"
+ width="250" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Teleport Home All Users..."
+ layout="topleft"
+ left_delta="0"
+ name="kick_all_btn"
+ top_pad="3"
+ width="250" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Send Message To Region..."
+ layout="topleft"
+ left_delta="0"
+ name="im_btn"
+ top_pad="20"
+ width="200" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Manage Telehub..."
+ layout="topleft"
+ left_delta="0"
+ name="manage_telehub_btn"
+ top_pad="20"
+ width="150" >
+ <button.commit_callback
+ function="RegionInfo.ManageTelehub" />
+ </button>
+</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
new file mode 100644
index 0000000000..5093c52129
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_region_terrain.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="top|left"
+ height="320"
+ help_topic="panel_region_terrain_tab"
+ label="Terrain"
+ layout="topleft"
+ left="0"
+ name="Terrain"
+ top="320"
+ width="480">
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="region_text_lbl"
+ top="10"
+ width="100">
+ Region:
+ </text>
+ <text
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_delta="50"
+ name="region_text"
+ top_delta="0"
+ width="400">
+ unknown
+ </text>
+ <spinner
+ follows="left|top"
+ height="20"
+ label="Water Height"
+ label_width="120"
+ layout="topleft"
+ left="15"
+ max_val="100"
+ name="water_height_spin"
+ top="40"
+ width="180" />
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.2"
+ label="Terrain Raise Limit"
+ label_width="120"
+ layout="topleft"
+ left="15"
+ max_val="100"
+ name="terrain_raise_spin"
+ top="60"
+ width="180" />
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.2"
+ label="Terrain Lower Limit"
+ label_width="120"
+ layout="topleft"
+ left="15"
+ max_val="0"
+ min_val="-100"
+ name="terrain_lower_spin"
+ top="80"
+ width="180" />
+ <check_box
+ height="20"
+ label="Use Estate Sun"
+ layout="topleft"
+ left="250"
+ name="use_estate_sun_check"
+ top="35"
+ width="100" />
+ <check_box
+ height="20"
+ label="Fixed Sun"
+ layout="topleft"
+ left="250"
+ name="fixed_sun_check"
+ top="55"
+ width="100" />
+ <icon
+ height="20"
+ image_name="icon_day_cycle.tga"
+ layout="topleft"
+ left="285"
+ name="daycycle"
+ top="80"
+ width="165" />
+ <slider
+ follows="left|top"
+ height="20"
+ increment="0.001"
+ label="Phase"
+ layout="topleft"
+ left="250"
+ max_val="30"
+ min_val="6"
+ name="sun_hour_slider"
+ show_text="false"
+ top="105"
+ width="200" />
+ <button
+ enabled="false"
+ follows="left|top"
+ height="20"
+ label="Apply"
+ layout="topleft"
+ left="350"
+ name="apply_btn"
+ top="135"
+ width="90" />
+ <view_border
+ bevel_style="none"
+ follows="top|left"
+ height="130"
+ layout="topleft"
+ left="8"
+ top="30"
+ width="460" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Download RAW terrain..."
+ layout="topleft"
+ left_delta="2"
+ name="download_raw_btn"
+ tool_tip="Available only to estate owners, not managers"
+ top_pad="60"
+ width="170" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Upload RAW terrain..."
+ layout="topleft"
+ left="10"
+ name="upload_raw_btn"
+ tool_tip="Available only to estate owners, not managers"
+ top="243"
+ width="170" />
+ <button
+ follows="left|top"
+ height="20"
+ label="Bake Terrain"
+ layout="topleft"
+ left="10"
+ name="bake_terrain_btn"
+ tool_tip="Set current terrain as mid-point for raise/lower limits"
+ top="283"
+ width="100" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_region_texture.xml b/indra/newview/skins/default/xui/en/panel_region_texture.xml
new file mode 100644
index 0000000000..04dbf73be9
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_region_texture.xml
@@ -0,0 +1,319 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="top|left"
+ height="320"
+ help_topic="panel_region_texture_tab"
+ label="Ground Textures"
+ layout="topleft"
+ left="0"
+ name="Textures"
+ top="320"
+ width="480">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="region_text_lbl"
+ top="10"
+ width="100">
+ Region:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_delta="50"
+ name="region_text"
+ top_delta="0"
+ width="400">
+ unknown
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="detail_texture_text"
+ top="36"
+ width="300">
+ Terrain Textures (requires 512x512, 24 bit .tga files)
+ </text>
+ <texture_picker
+ follows="left|top"
+ height="100"
+ layout="topleft"
+ left_delta="0"
+ name="texture_detail_0"
+ top_delta="20"
+ width="100" />
+ <texture_picker
+ follows="left|top"
+ height="100"
+ layout="topleft"
+ left_pad="10"
+ name="texture_detail_1"
+ top_delta="0"
+ width="100" />
+ <texture_picker
+ follows="left|top"
+ height="100"
+ layout="topleft"
+ left_pad="10"
+ name="texture_detail_2"
+ top_delta="0"
+ width="100" />
+ <texture_picker
+ follows="left|top"
+ height="100"
+ layout="topleft"
+ left_pad="10"
+ name="texture_detail_3"
+ top_delta="0"
+ width="100" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="height_text_lbl"
+ top="146"
+ width="65">
+ 1 (Low)
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="45"
+ name="height_text_lbl2"
+ top_delta="0"
+ width="100">
+ 2
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="10"
+ name="height_text_lbl3"
+ top_delta="0"
+ width="100">
+ 3
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="10"
+ name="height_text_lbl4"
+ top_delta="0"
+ width="100">
+ 4 (High)
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="height_text_lbl5"
+ top="170"
+ width="300">
+ Texture Elevation Ranges
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="51"
+ name="height_text_lbl6"
+ top="185"
+ width="100">
+ Southwest
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="10"
+ name="height_text_lbl7"
+ top_delta="0"
+ width="100">
+ Northwest
+ </text>
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.5"
+ label="Low"
+ label_width="37"
+ layout="topleft"
+ left="10"
+ max_val="500"
+ min_val="-500"
+ name="height_start_spin_0"
+ top_delta="15"
+ width="100" />
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.5"
+ label="Low"
+ label_width="37"
+ layout="topleft"
+ left_pad="10"
+ max_val="500"
+ min_val="-500"
+ name="height_start_spin_1"
+ top_delta="0"
+ width="100" />
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.5"
+ label="High"
+ label_width="37"
+ layout="topleft"
+ left="10"
+ max_val="500"
+ min_val="-500"
+ name="height_range_spin_0"
+ top_delta="20"
+ width="100" />
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.5"
+ label="High"
+ label_width="37"
+ layout="topleft"
+ left_pad="10"
+ max_val="500"
+ min_val="-500"
+ name="height_range_spin_1"
+ top_delta="0"
+ width="100" />
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="51"
+ name="height_text_lbl8"
+ top_pad="10"
+ width="100">
+ Southeast
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_pad="10"
+ name="height_text_lbl9"
+ top_delta="0"
+ width="100">
+ Northeast
+ </text>
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.5"
+ label="Low"
+ label_width="37"
+ layout="topleft"
+ left="10"
+ max_val="500"
+ min_val="-500"
+ name="height_start_spin_2"
+ top_delta="15"
+ width="100" />
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.5"
+ label="Low"
+ label_width="37"
+ layout="topleft"
+ left_pad="10"
+ max_val="500"
+ min_val="-500"
+ name="height_start_spin_3"
+ top_delta="0"
+ width="100" />
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.5"
+ label="High"
+ label_width="37"
+ layout="topleft"
+ left="10"
+ max_val="500"
+ min_val="-500"
+ name="height_range_spin_2"
+ top_delta="20"
+ width="100" />
+ <spinner
+ follows="left|top"
+ height="20"
+ increment="0.5"
+ label="High"
+ label_width="37"
+ layout="topleft"
+ left_pad="10"
+ max_val="500"
+ min_val="-500"
+ name="height_range_spin_3"
+ top_delta="0"
+ width="100" />
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="height_text_lbl10"
+ top_delta="30"
+ width="400"
+ word_wrap="true">
+ These values represent the blend range for the textures above.
+ </text>
+ <text
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="height_text_lbl11"
+ top_delta="32"
+ width="400"
+ word_wrap="true">
+ Measured in meters, the LOW value is the MAXIMUM height of Texture #1, and the HIGH value is the MINIMUM height of Texture #4.
+ </text>
+ <button
+ enabled="false"
+ follows="left|bottom"
+ height="20"
+ label="Apply"
+ layout="topleft"
+ left="350"
+ name="apply_btn"
+ top="290"
+ width="100" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_script_ed.xml b/indra/newview/skins/default/xui/en/panel_script_ed.xml
new file mode 100644
index 0000000000..765e2ae623
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_script_ed.xml
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ bevel_style="none"
+ border_style="line"
+ bottom="550"
+ follows="left|top|right|bottom"
+ height="508"
+ layout="topleft"
+ left="0"
+ name="script panel"
+ width="500">
+ <panel.string
+ name="loading">
+ Loading...
+ </panel.string>
+ <panel.string
+ name="can_not_view">
+ You can not view or edit this script, since it has been set as &quot;no copy&quot;. You need full permissions to view or edit a script inside an object.
+ </panel.string>
+ <panel.string
+ name="public_objects_can_not_run">
+ Public Objects cannot run scripts
+ </panel.string>
+ <panel.string
+ name="script_running">
+ Running
+ </panel.string>
+ <panel.string
+ name="Title">
+ Script: [NAME]
+ </panel.string>
+ <text_editor
+ type="string"
+ length="1"
+ bottom="393"
+ follows="left|top|right|bottom"
+ font="Monospace"
+ height="376"
+ ignore_tab="false"
+ layout="topleft"
+ left="4"
+ max_length="65536"
+ name="Script Editor"
+ width="492"
+ show_line_numbers="true"
+ handle_edit_keys_directly="true"
+ word_wrap="true">
+ Loading...
+ </text_editor>
+ <button
+ bottom="499"
+ follows="right|bottom"
+ height="20"
+ label="Save"
+ label_selected="Save"
+ layout="topleft"
+ left="360"
+ name="Save_btn"
+ width="128" />
+ <scroll_list
+ bottom="457"
+ follows="left|right|bottom"
+ height="60"
+ layout="topleft"
+ left="4"
+ name="lsl errors"
+ width="492" />
+ <combo_box
+ bottom="499"
+ follows="left|bottom"
+ height="20"
+ label="Insert..."
+ layout="topleft"
+ left="12"
+ name="Insert..."
+ width="128" />
+ <text
+ bottom="473"
+ follows="left|bottom"
+ height="12"
+ layout="topleft"
+ left="12"
+ name="line_col"
+ width="128" />
+ <menu_bar
+ bg_visible="false"
+ bottom="18"
+ follows="left|top|right"
+ height="18"
+ layout="topleft"
+ left="8"
+ mouse_opaque="false"
+ name="script_menu"
+ width="476">
+ <menu
+ bottom="18"
+ height="62"
+ label="File"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="File"
+ width="138">
+ <menu_item_call
+ label="Save"
+ layout="topleft"
+ name="Save" />
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Revert All Changes"
+ layout="topleft"
+ name="Revert All Changes" />
+ </menu>
+ <menu
+ bottom="-647"
+ height="198"
+ label="Edit"
+ layout="topleft"
+ left="222"
+ mouse_opaque="false"
+ name="Edit"
+ width="139">
+ <menu_item_call
+ enabled="false"
+ label="Undo"
+ layout="topleft"
+ name="Undo" />
+ <menu_item_call
+ enabled="false"
+ label="Redo"
+ layout="topleft"
+ name="Redo" />
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ enabled="false"
+ label="Cut"
+ layout="topleft"
+ name="Cut" />
+ <menu_item_call
+ enabled="false"
+ label="Copy"
+ layout="topleft"
+ name="Copy" />
+ <menu_item_call
+ enabled="false"
+ label="Paste"
+ layout="topleft"
+ name="Paste" />
+ <menu_item_separator
+ layout="topleft"
+ name="separator2" />
+ <menu_item_call
+ label="Select All"
+ layout="topleft"
+ name="Select All" />
+ <menu_item_call
+ enabled="false"
+ label="Deselect"
+ layout="topleft"
+ name="Deselect" />
+ <menu_item_separator
+ layout="topleft"
+ name="separator3" />
+ <menu_item_call
+ label="Search / Replace..."
+ layout="topleft"
+ name="Search / Replace..." />
+ </menu>
+ <menu
+ bottom="18"
+ height="34"
+ label="Help"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="Help"
+ width="112">
+ <menu_item_call
+ label="Help..."
+ layout="topleft"
+ name="Help..." />
+ <menu_item_call
+ label="Keyword Help..."
+ layout="topleft"
+ name="Keyword Help..." />
+ </menu>
+ </menu_bar>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml b/indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml
new file mode 100644
index 0000000000..d98f690339
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="top|left"
+ height="570"
+ label="MY AVATAR"
+ layout="topleft"
+ left="0"
+ name="script_limits_my_avatar_panel"
+ top="0"
+ width="480">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="loading_text"
+ top="10"
+ text_color="EmphasisColor"
+ width="480">
+ Loading...
+ </text>
+ <scroll_list
+ draw_heading="true"
+ follows="all"
+ height="500"
+ layout="topleft"
+ left_delta="0"
+ multi_select="true"
+ name="scripts_list"
+ top_delta="17"
+ width="460">
+ <scroll_list.columns
+ label="Size (kb)"
+ name="size"
+ width="70" />
+ <scroll_list.columns
+ label="URLs"
+ name="urls"
+ width="50" />
+ <scroll_list.columns
+ label="Object Name"
+ name="name"
+ width="140" />
+ <scroll_list.columns
+ label="Location"
+ name="location"
+ width="130" />
+ </scroll_list>
+ <button
+ follows="bottom|left"
+ height="19"
+ label="Refresh List"
+ layout="bottomleft"
+ left_pad="5"
+ name="refresh_list_btn"
+ top="34"
+ left="10"
+ width="100" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml b/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml
new file mode 100644
index 0000000000..0fa3c1cf2e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="top|left"
+ height="570"
+ label="REGION MEMORY"
+ layout="topleft"
+ name="script_limits_region_memory_panel"
+ top="0"
+ left="0"
+ width="480">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="script_memory"
+ top_pad="24"
+ text_color="White"
+ width="480">
+ Parcel Script Memory
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="30"
+ name="parcels_listed"
+ top_delta="18"
+ visible="true"
+ width="480">
+ Parcels Owned:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="30"
+ name="memory_used"
+ top_delta="18"
+ width="480">
+ Memory used:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="loading_text"
+ top_delta="32"
+ text_color="EmphasisColor"
+ width="480">
+ Loading...
+ </text>
+ <scroll_list
+ draw_heading="true"
+ follows="all"
+ height="409"
+ layout="topleft"
+ left_delta="0"
+ multi_select="true"
+ name="scripts_list"
+ top_delta="16"
+ width="460">
+ <scroll_list.columns
+ label="Size (kb)"
+ name="size"
+ width="70" />
+ <scroll_list.columns
+ label="Object Name"
+ name="name"
+ width="100" />
+ <scroll_list.columns
+ label="Object Owner"
+ name="owner"
+ width="100" />
+ <scroll_list.columns
+ label="Parcel / Location"
+ name="location"
+ width="130" />
+<!-- <scroll_list.commit_callback
+ function="TopObjects.CommitObjectsList" />-->
+ </scroll_list>
+ <button
+ follows="bottom|left"
+ height="19"
+ label="Refresh List"
+ layout="bottomleft"
+ left_pad="5"
+ name="refresh_list_btn"
+ top="34"
+ left="10"
+ width="100" />
+ <button
+ follows="bottom|right"
+ height="19"
+ visible="false"
+ label="Highlight"
+ layout="bottomright"
+ left="370"
+ name="highlight_btn"
+ top="34"
+ width="100" />
+ <button
+ follows="bottom|right"
+ height="19"
+ visible="false"
+ label="Return"
+ layout="bottomright"
+ name="return_btn"
+ top="34"
+ left_delta="-105"
+ width="100" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_scrolling_param.xml b/indra/newview/skins/default/xui/en/panel_scrolling_param.xml
new file mode 100644
index 0000000000..44afadf65a
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_scrolling_param.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ height="152"
+ layout="topleft"
+ left="0"
+ name="LLScrollingPanelParam"
+ top="152"
+ width="270">
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="4"
+ name="min param text"
+ top="116"
+ width="128" />
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="6"
+ name="max param text"
+ top_delta="0"
+ width="128" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="8"
+ name="Loading..."
+ top="11"
+ width="128">
+ Loading...
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="6"
+ name="Loading...2"
+ top_delta="0"
+ width="128">
+ Loading...
+ </text>
+ <button
+ enabled="false"
+ height="132"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled_Selected"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ layout="topleft"
+ left="2"
+ name="less"
+ tab_stop="false"
+ top="0"
+ width="132" />
+ <button
+ enabled="false"
+ height="132"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled_Selected"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ layout="topleft"
+ left_pad="2"
+ name="more"
+ tab_stop="false"
+ top_delta="0"
+ width="132" />
+ <slider
+ can_edit_text="true"
+ decimal_digits="0"
+ enabled="false"
+ height="16"
+ increment="1"
+ initial_value="0"
+ label="[DESC]"
+ label_width="100"
+ layout="topleft"
+ left="6"
+ max_val="100"
+ name="param slider"
+ top="134"
+ width="258" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml
new file mode 100644
index 0000000000..3f836a661d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_side_tray.xml
@@ -0,0 +1,166 @@
+<?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"
+ background_visible="false"
+ mouse_opaque="true"
+ width="333"
+ collapsed="true"
+>
+ <!-- Individual tabs must show background to have seemless
+ appearance up to tray panel header word like "Home".
+ Embedded panels are inset by a pixel and so their
+ backgrounds will not block the world fully. -->
+
+ <sidetray_tab
+ name="sidebar_openclose"
+ help_topic="sidebar_openclose"
+ tab_title="Toggle Sidebar"
+ description="Toggle Sidebar."
+ image="TabIcon_Open_Off"
+ image_selected="TabIcon_Close_Off"
+ mouse_opaque="false"
+ background_visible="true"
+ >
+ <panel /> <!-- dummy panel, never to actually be seen -->
+ </sidetray_tab>
+
+ <sidetray_tab
+ name="sidebar_home"
+ help_topic="sidebar_home"
+ tab_title="Home"
+ description="Home."
+ image="TabIcon_Home_Off"
+ image_selected="TabIcon_Home_Selected"
+ mouse_opaque="false"
+ background_visible="true"
+ >
+ <panel
+ class="panel_sidetray_home"
+ name="panel_home"
+ filename="panel_sidetray_home_tab.xml"
+ label="home"
+ />
+ </sidetray_tab>
+
+ <sidetray_tab
+ name="sidebar_me"
+ help_topic="sidebar_me"
+ tab_title="My Profile"
+ description="Edit your public profile and Picks."
+ image="TabIcon_Me_Off"
+ image_selected="TabIcon_Me_Selected"
+ mouse_opaque="false"
+ background_visible="true"
+ >
+ <panel
+ class="panel_me"
+ name="panel_me"
+ filename="panel_me.xml"
+ label="Me"
+ />
+ </sidetray_tab>
+
+ <sidetray_tab
+ name="sidebar_people"
+ help_topic="sidebar_people"
+ tab_title="People"
+ description="Find your friends, contacts and people nearby."
+ image="TabIcon_People_Off"
+ image_selected="TabIcon_People_Selected"
+ mouse_opaque="false"
+ background_visible="true"
+ >
+ <panel_container
+ name="panel_container"
+ default_panel_name="panel_people"
+ width="333"
+ >
+ <panel
+ class="panel_people"
+ name="panel_people"
+ filename="panel_people.xml"
+ />
+ <panel
+ class="panel_profile_view"
+ name="panel_profile_view"
+ filename="panel_profile_view.xml"
+ />
+ <panel
+ class="panel_group_info_sidetray"
+ name="panel_group_info_sidetray"
+ filename="panel_group_info_sidetray.xml"
+ label="Group Info"
+ font="SansSerifBold"
+ />
+ <panel
+ class="panel_block_list_sidetray"
+ name="panel_block_list_sidetray"
+ filename="panel_block_list_sidetray.xml"
+ label="Blocked Residents &amp; Objects"
+ font="SansSerifBold"
+ />
+
+ </panel_container>
+ </sidetray_tab>
+
+ <sidetray_tab
+ name="sidebar_places"
+ help_topic="sidebar_places"
+ tab_title="Places"
+ label="Places"
+ description="Find places to go and places you&apos;ve visited before."
+ image="TabIcon_Places_Off"
+ image_selected="TabIcon_Places_Selected"
+ mouse_opaque="false"
+ background_visible="true"
+ >
+ <panel
+ class="panel_places"
+ name="panel_places"
+ filename="panel_places.xml"
+ label="Places"
+ font="SansSerifBold"
+ />
+ </sidetray_tab>
+
+ <sidetray_tab
+ name="sidebar_inventory"
+ help_topic="sidebar_inventory"
+ tab_title="My Inventory"
+ description="Browse your inventory."
+ image="TabIcon_Things_Off"
+ image_selected="TabIcon_Things_Selected"
+ mouse_opaque="false"
+ background_visible="true"
+ >
+ <panel
+ class="sidepanel_inventory"
+ name="sidepanel_inventory"
+ filename="sidepanel_inventory.xml"
+ label="Edit Inventory"
+ font="SansSerifBold"
+ />
+ </sidetray_tab>
+
+ <sidetray_tab
+ name="sidebar_appearance"
+ help_topic="sidebar_appearance"
+ tab_title="My Appearance"
+ description="Change your appearance and current look."
+ image="TabIcon_Appearance_Off"
+ image_selected="TabIcon_Appearance_Selected"
+ mouse_opaque="false"
+ background_visible="true"
+ >
+ <panel
+ class="sidepanel_appearance"
+ name="sidepanel_appearance"
+ filename="sidepanel_appearance.xml"
+ label="Edit Appearance"
+ font="SansSerifBold"
+ />
+ </sidetray_tab>
+
+</side_tray>
diff --git a/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml b/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml
new file mode 100644
index 0000000000..0a9c70303e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ bottom="0"
+ follows="left|top|right"
+ height="30"
+ width="333"
+ layout="topleft"
+ left="0"
+ name="sidetray_tab_panel">
+ <text
+ follows="left|top"
+ font="SansSerifHuge"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="sidetray_tab_title"
+ text_color="white"
+ top="4"
+ value="Side Panel"
+ width="255" />
+ <button
+ follows="left|right|top"
+ height="16"
+ image_selected="Icon_Help_Press"
+ image_unselected="Icon_Help_Foreground"
+ image_disabled="Icon_Help_Press"
+ layout="topleft"
+ name="show_help"
+ top="10"
+ right="-11"
+ width="16"
+ tool_tip="Show Help">
+ <button.commit_callback
+ function="Button.ShowHelp" />
+ </button>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml b/indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml
new file mode 100644
index 0000000000..ab3cc036d5
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- the web-based Home panel of the side tray -->
+<panel
+ follows="all"
+ height="570"
+ min_height="350"
+ help_topic="sidetray_home"
+ layout="topleft"
+ top="0"
+ left="0"
+ name="home_tab"
+ width="333">
+ <layout_stack
+ follows="all"
+ height="550"
+ layout="topleft"
+ left="10"
+ name="stack"
+ top_pad="10"
+ width="313">
+ <layout_panel
+ height="550"
+ layout="topleft"
+ left_delta="0"
+ name="browser_layout"
+ top_delta="0"
+ width="313">
+ <web_browser
+ border_visible="false"
+ follows="all"
+ height="550"
+ layout="topleft"
+ left="0"
+ name="browser"
+ start_url="data:text/html,%3Chtml%3E%3Cbody bgcolor=%22#2A2A2A%22 text=%22eeeeee%22%3E %3Ch3%3E %0D%0A%0D%0ALoading... %3C/h3%3E %3C/body%3E%3C/html%3E"
+ top="0"
+ width="313" />
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_stand_stop_flying.xml b/indra/newview/skins/default/xui/en/panel_stand_stop_flying.xml
new file mode 100644
index 0000000000..b48943c699
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_stand_stop_flying.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- Width and height of this panel should be synchronized with "panel_modes" in the floater_moveview.xml-->
+<panel
+ height="25"
+ layout="topleft"
+ name="panel_stand_stop_flying"
+ mouse_opaque="false"
+ visible="true"
+ width="115">
+ <button
+ follows="left|bottom"
+ height="19"
+ label="Stand"
+ layout="topleft"
+ name="stand_btn"
+ tool_tip="Click here to stand up."
+ top="2"
+ visible="false"
+ width="115" />
+ <button
+ follows="left|bottom"
+ height="19"
+ label="Stop Flying"
+ layout="topleft"
+ name="stop_fly_btn"
+ tool_tip="Stop flying"
+ top="2"
+ visible="false"
+ width="115" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml
new file mode 100644
index 0000000000..7a6089c74e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_opaque="true"
+ background_visible="true"
+ bg_opaque_color="MouseGray"
+ follows="top|right"
+ height="19"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="status"
+ top="19"
+ width="1000">
+ <panel.string
+ name="StatBarDaysOfWeek">
+ Sunday:Monday:Tuesday:Wednesday:Thursday:Friday:Saturday
+ </panel.string>
+ <panel.string
+ name="StatBarMonthsOfYear">
+ January:February:March:April:May:June:July:August:September:October:November:December
+ </panel.string>
+ <panel.string
+ name="packet_loss_tooltip">
+ Packet Loss
+ </panel.string>
+ <panel.string
+ name="bandwidth_tooltip">
+ Bandwidth
+ </panel.string>
+ <panel.string
+ name="time">
+ [hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]
+ </panel.string>
+ <panel.string
+ name="timeTooltip">
+ [weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]
+ </panel.string>
+ <panel.string
+ name="buycurrencylabel">
+ L$ [AMT]
+ </panel.string>
+ <button
+ auto_resize="true"
+ halign="right"
+ font="SansSerifSmall"
+ follows="right|top"
+ image_overlay=""
+ image_selected="spacer35.tga"
+ image_unselected="spacer35.tga"
+ image_pressed="spacer35.tga"
+ height="16"
+ right="-228"
+ label_shadow="false"
+ name="buycurrency"
+ tool_tip="My Balance"
+ top="3"
+ width="100" />
+ <button
+ auto_resize="true"
+ halign="right"
+ font="SansSerifSmall"
+ follows="right|top"
+ image_selected="BuyArrow_Over"
+ image_unselected="BuyArrow_Over"
+ image_pressed="BuyArrow_Press"
+ height="16"
+ label="Buy L$"
+ label_color="EmphasisColor"
+ left_pad="0"
+ label_shadow="false"
+ name="buyL"
+ pad_right="20px"
+ tool_tip="Click to buy more L$"
+ top="2"
+ width="100" />
+ <text
+ type="string"
+ font="SansSerifSmall"
+ text_readonly_color="TimeTextColor"
+ follows="right|bottom"
+ halign="right"
+ height="16"
+ top="5"
+ layout="topleft"
+ left_pad="0"
+ name="TimeText"
+ tool_tip="Current time (Pacific)"
+ width="85">
+ 12:00 AM
+ </text>
+ <button
+ follows="right|bottom"
+ height="15"
+ image_selected="AudioMute_Off"
+ image_pressed="Audio_Press"
+ image_unselected="Audio_Off"
+ is_toggle="true"
+ left_pad="18"
+ top="2"
+ name="volume_btn"
+ tool_tip="Global Volume Control"
+ width="16" />
+ <text
+ follows="right|bottom"
+ halign="center"
+ height="12"
+ layout="topleft"
+ left_delta="0"
+ name="stat_btn"
+ top_delta="0"
+ width="20"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_sys_well_item.xml b/indra/newview/skins/default/xui/en/panel_sys_well_item.xml
new file mode 100644
index 0000000000..2822f7b841
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_sys_well_item.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- All our XML is utf-8 encoded. -->
+<panel
+ name="sys_well_item"
+ title="sys_well_item"
+ visible="true"
+ top="0"
+ left="0"
+ width="300"
+ height="35"
+ layout="topleft"
+ follows="left|right"
+ background_opaque="false"
+ background_visible="true"
+ bg_alpha_color="0.0 0.0 0.0 0.0" >
+ <text
+ clip_partial="true"
+ top="2"
+ left="10"
+ width="267"
+ height="28"
+ layout="topleft"
+ follows="right|left"
+ text_color="white"
+ use_ellipses="true"
+ word_wrap="true"
+ mouse_opaque="false"
+ name="title" >
+ Beware the trout. BEWARE! THE! TROUT!
+ </text>
+ <button
+ top="5"
+ right="-5"
+ width="17"
+ height="17"
+ layout="topleft"
+ follows="right"
+ name="close_btn"
+ mouse_opaque="true"
+ tab_stop="false"
+ image_unselected="Icon_Close_Toast"
+ image_selected="Icon_Close_Toast"
+ />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history.xml b/indra/newview/skins/default/xui/en/panel_teleport_history.xml
new file mode 100644
index 0000000000..06da64533b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_teleport_history.xml
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel name="Teleport History" bottom="0" height="326" left="0" width="380"
+ help_topic="panel_teleport_history"
+ border="true" follows="left|top|right|bottom">
+ <accordion
+ follows="left|top|right|bottom"
+ height="300"
+ layout="topleft"
+ left="0"
+ top="0"
+ name="history_accordion"
+ width="380">
+ <accordion_tab
+ layout="topleft"
+ name="today"
+ title="Today">
+ <flat_list_view
+ follows="all"
+ height="150"
+ layout="topleft"
+ left="0"
+ name="today_items"
+ top="0"
+ width="380">
+ </flat_list_view>
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ name="yesterday"
+ title="Yesterday">
+ <flat_list_view
+ follows="all"
+ height="150"
+ layout="topleft"
+ left="0"
+ name="yesterday_items"
+ top="0"
+ width="380">
+ </flat_list_view>
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ name="2_days_ago"
+ title="2 days ago">
+ <flat_list_view
+ follows="all"
+ height="150"
+ layout="topleft"
+ left="0"
+ name="2_days_ago"
+ top="0"
+ width="380">
+ </flat_list_view>
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ name="3_days_ago"
+ title="3 days ago">
+ <flat_list_view
+ follows="all"
+ height="150"
+ layout="topleft"
+ left="0"
+ name="3_days_ago"
+ top="0"
+ width="380">
+ </flat_list_view>
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ name="4_days_ago"
+ title="4 days ago">
+ <flat_list_view
+ follows="all"
+ height="150"
+ layout="topleft"
+ left="0"
+ name="4_days_ago"
+ top="0"
+ width="380">
+ </flat_list_view>
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ name="5_days_ago"
+ title="5 days ago">
+ <flat_list_view
+ follows="all"
+ height="150"
+ layout="topleft"
+ left="0"
+ name="5_days_ago_items"
+ top="0"
+ width="380">
+ </flat_list_view>
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ name="6_days_and_older"
+ title="6 days and older">
+ <flat_list_view
+ follows="all"
+ height="150"
+ layout="topleft"
+ left="0"
+ name="6_days_and_older_items"
+ top="0"
+ width="380">
+ </flat_list_view>
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ name="1_month_and_older"
+ title="1 month and older">
+ <flat_list_view
+ follows="all"
+ height="150"
+ layout="topleft"
+ left="0"
+ name="1_month_and_older_items"
+ top="0"
+ width="380">
+ </flat_list_view>
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ name="6_months_and_older"
+ title="6 months and older">
+ <flat_list_view
+ follows="all"
+ height="150"
+ layout="topleft"
+ left="0"
+ name="6_months_and_older_items"
+ top="0"
+ width="380">
+ </flat_list_view>
+ </accordion_tab>
+ </accordion>
+ <panel
+ background_visible="true"
+ bevel_style="none"
+ top_pad="0"
+ follows="left|right|bottom"
+ height="30"
+ label="bottom_panel"
+ layout="topleft"
+ left="0"
+ name="bottom_panel"
+ width="380">
+ <button
+ follows="bottom|left"
+ font="SansSerifBigBold"
+ tool_tip="Show additional optioins"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ layout="topleft"
+ left="10"
+ name="gear_btn"
+ top="5"
+ width="18" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml
new file mode 100644
index 0000000000..4f40e00815
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="top|right|left"
+ height="20"
+ layout="topleft"
+ left="0"
+ name="teleport_history_item"
+ top="0"
+ width="380">
+ <icon
+ follows="top|right|left"
+ height="20"
+ image_name="ListItem_Over"
+ layout="topleft"
+ left="0"
+ name="hovered_icon"
+ top="0"
+ visible="false"
+ width="380" />
+ <icon
+ height="20"
+ follows="top|right|left"
+ image_name="ListItem_Select"
+ layout="topleft"
+ left="0"
+ name="selected_icon"
+ top="0"
+ visible="false"
+ width="380" />
+ <icon
+ height="16"
+ follows="top|left"
+ image_name="Inv_Landmark"
+ layout="topleft"
+ left="0"
+ name="landmark_icon"
+ top="0"
+ width="16" />
+ <text
+ follows="left|right"
+ height="20"
+ layout="topleft"
+ left_pad="5"
+ use_ellipses="true"
+ name="region"
+ text_color="white"
+ top="4"
+ value="..."
+ width="330" />
+ <button
+ follows="right"
+ height="20"
+ image_overlay="ForwardArrow_Off"
+ layout="topleft"
+ left_pad="5"
+ right="-3"
+ name="profile_btn"
+ tool_tip="Show item info"
+ top="1"
+ visible="false"
+ width="20" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_toast.xml b/indra/newview/skins/default/xui/en/panel_toast.xml
new file mode 100644
index 0000000000..d198237e5d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_toast.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- All our XML is utf-8 encoded. -->
+
+<!-- Don't remove floater's height! It is needed for Overflow and Start-Up toasts!-->
+
+<floater
+ legacy_header_height="18"
+ name="toast"
+ title=""
+ visible="false"
+ layout="topleft"
+ height="40"
+ width="305"
+ left="0"
+ top="0"
+ follows="right|bottom"
+ bg_opaque_image="Toast_Over"
+ bg_alpha_image="Toast_Background"
+ can_minimize="false"
+ can_tear_off="false"
+ can_resize="false"
+ can_drag_on_left="false"
+ can_close="false"
+ can_dock="false"
+ border_visible = "false"
+ border_drop_shadow_visible = "false"
+ drop_shadow_visible = "false"
+ border = "false"
+>
+ <!-- Don't remove this wiget! It is needed for Overflow and Start-Up toasts!-->
+ <text
+ clip_partial="true"
+ visible="false"
+ follows="left|top|right|bottom"
+ font="SansSerifBold"
+ height="20"
+ layout="topleft"
+ left="20"
+ name="toast_text"
+ word_wrap="true"
+ text_color="white"
+ top="5"
+ v_pad="5"
+ use_ellipses="true"
+ width="260">
+ Toast text;
+ </text>
+ <button
+ layout="topleft"
+ top="-14"
+ left="293"
+ width="17"
+ height="17"
+ follows="top|right"
+ visible="false"
+ enabled="true"
+ mouse_opaque="false"
+ name="hide_btn"
+ label=""
+ tab_stop="false"
+ image_unselected="Toast_CloseBtn"
+ image_selected="Toast_CloseBtn"
+ />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml b/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml
new file mode 100644
index 0000000000..60d4a7e00b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_opaque="true"
+ background_visible="false"
+ border_visible="false"
+ border="false"
+ chrome="true"
+ follows="bottom"
+ height="150"
+ layout="topleft"
+ name="volumepulldown_floater"
+ width="32">
+ <!-- floater background image -->
+ <icon
+ height="150"
+ image_name="Inspector_Background"
+ layout="topleft"
+ left="0"
+ name="normal_background"
+ top="0"
+ width="32" />
+ <slider
+ control_name="AudioLevelMaster"
+ follows="left|top"
+ left="0"
+ top="1"
+ orientation="vertical"
+ height="120"
+ increment="0.05"
+ initial_value="0.5"
+ layout="topleft"
+ name="mastervolume"
+ show_text="false"
+ slider_label.halign="right"
+ top_pad="2"
+ volume="true">
+ <slider.commit_callback
+ function="Vol.setControlFalse"
+ parameter="MuteAudio" />
+ </slider>
+ <button
+ left="7"
+ top_pad="9"
+ width="18"
+ height="12"
+ follows="top|left"
+ name="prefs_btn"
+ image_unselected="Icon_Gear_Foreground"
+ image_disabled="Icon_Gear_Background"
+ image_pressed="Icon_Gear_Press"
+ scale_image="false">
+ <button.commit_callback
+ function="Vol.GoAudioPrefs" />
+ </button>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_world_map.xml b/indra/newview/skins/default/xui/en/panel_world_map.xml
new file mode 100644
index 0000000000..9f08d3a817
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_world_map.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="left|top|right|bottom"
+ height="300"
+ layout="topleft"
+ name="world_map"
+ width="400">
+ <panel.string
+ name="Loading">
+ Loading...
+ </panel.string>
+ <panel.string
+ name="InvalidLocation">
+ Invalid Location
+ </panel.string>
+ <panel.string
+ name="world_map_north">
+ N
+ </panel.string>
+ <panel.string
+ name="world_map_east">
+ E
+ </panel.string>
+ <panel.string
+ name="world_map_west">
+ W
+ </panel.string>
+ <panel.string
+ name="world_map_south">
+ S
+ </panel.string>
+ <panel.string
+ name="world_map_southeast">
+ SE
+ </panel.string>
+ <panel.string
+ name="world_map_northeast">
+ NE
+ </panel.string>
+ <panel.string
+ name="world_map_southwest">
+ SW
+ </panel.string>
+ <panel.string
+ name="world_map_northwest">
+ NW
+ </panel.string>
+ <text
+ type="string"
+ length="1"
+ label="N"
+ layout="topleft"
+ name="floater_map_north"
+ text_color="1 1 1 0.7">
+ N
+ </text>
+ <text
+ type="string"
+ length="1"
+ label="E"
+ layout="topleft"
+ name="floater_map_east"
+ text_color="1 1 1 0.7">
+ E
+ </text>
+ <text
+ type="string"
+ length="1"
+ label="W"
+ layout="topleft"
+ name="floater_map_west"
+ text_color="1 1 1 0.7">
+ W
+ </text>
+ <text
+ type="string"
+ length="1"
+ label="S"
+ layout="topleft"
+ name="floater_map_south"
+ text_color="1 1 1 0.7">
+ S
+ </text>
+ <text
+ type="string"
+ length="1"
+ label="SE"
+ layout="topleft"
+ name="floater_map_southeast"
+ text_color="1 1 1 0.7">
+ SE
+ </text>
+ <text
+ type="string"
+ length="1"
+ label="NE"
+ layout="topleft"
+ name="floater_map_northeast"
+ text_color="1 1 1 0.7">
+ NE
+ </text>
+ <text
+ type="string"
+ length="1"
+ label="SW"
+ layout="topleft"
+ name="floater_map_southwest"
+ text_color="1 1 1 0.7">
+ SW
+ </text>
+ <text
+ type="string"
+ length="1"
+ label="NW"
+ layout="topleft"
+ name="floater_map_northwest"
+ text_color="1 1 1 0.7">
+ NW
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/role_actions.xml b/indra/newview/skins/default/xui/en/role_actions.xml
new file mode 100644
index 0000000000..a6036f8b78
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/role_actions.xml
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<role_actions>
+ <action_set
+ description="These Abilities include powers to add and remove group Members, and allow new Members to join without an invitation."
+ name="Membership">
+ <action description="Invite People to this Group"
+ longdescription="Invite People to this Group using the &apos;Invite&apos; button in the Roles section &gt; Members tab."
+ name="member invite" value="1" />
+ <action description="Eject Members from this Group"
+ longdescription="Eject Members from this Group using the &apos;Eject&apos; button in the Roles section &gt; Members tab. An Owner can eject anyone except another Owner. If you&apos;re not an Owner, a Member can be ejected from a group if, and only if, they&apos;re only in the Everyone Role, and NO other Roles. To remove Members from Roles, you need to have the &apos;Remove Members from Roles&apos; Ability."
+ name="member eject" value="2" />
+ <action
+ description="Toggle &apos;Open Enrollment&apos; and change &apos;Enrollment fee&apos;"
+ longdescription="Toggle &apos;Open Enrollment&apos; to let new Members join without an invitation, and change the &apos;Enrollment fee&apos; in the General section."
+ name="member options" value="3" />
+ </action_set>
+ <action_set
+ description="These Abilities include powers to add, remove, and change group Roles, add and remove Members in Roles, and assign Abilities to Roles."
+ name="Roles">
+ <action description="Create new Roles"
+ longdescription="Create new Roles in the Roles section &gt; Roles tab."
+ name="role create" value="4" />
+ <action description="Delete Roles"
+ longdescription="Delete Roles in the Roles section &gt; Roles tab."
+ name="role delete" value="5" />
+ <action description="Change Role names, titles, descriptions, and whether Role members are publicly revealed"
+ longdescription="Change Role names, titles, descriptions, and whether Role members are publicly revealed. This is done at the bottom of the the Roles section &gt; Roles tab after selecting a Role."
+ name="role properties" value="6" />
+ <action description="Assign Members to Assigner&apos;s Roles"
+ longdescription="Assign Members to Roles in the list of Assigned Roles (Roles section &gt; Members tab). A Member with this Ability can only add Members to a Role that the assigner is already in."
+ name="role assign member limited" value="7" />
+ <action description="Assign Members to Any Role"
+ longdescription="Assign Members to Any Role in the list of Assigned Roles (Roles section &gt; Members tab). *WARNING* Any Member in a Role with this Ability can assign themselves--and any other non-Owner Member--to Roles that have more powers than they currently have, potentially elevating themselves to near-Owner power. Be sure you know what you&apos;re doing before assigning this Ability."
+ name="role assign member" value="8" />
+ <action description="Remove Members from Roles"
+ longdescription="Remove Members from Roles in the list of Assigned Roles (Roles section &gt; Members tab). Owners can&apos;t be removed."
+ name="role remove member" value="9" />
+ <action description="Assign and Remove Abilities in Roles"
+ longdescription="Assign and Remove Abilities for each Role in the list of Allowed Abilities (Roles section &gt; Roles tab). *WARNING* Any Member in a Role with this Ability can assign themselves--and any other non-Owner Member--all Abilities, potentially elevating themselves to near-Owner power. Be sure you know what you&apos;re doing before assigning this Ability."
+ name="role change actions" value="10" />
+ </action_set>
+ <action_set
+ description="These Abilities include powers to modify this group&apos;s identity, such as changing public visibility, charter, and insignia."
+ name="Group Identity">
+ <action
+ description="Change Charter, Insignia, and &apos;Show in search&apos;"
+ longdescription="Change Charter, Insignia, and &apos;Show in search&apos;. This is done in the General section."
+ name="group change identity" value="11" />
+ </action_set>
+ <action_set
+ description="These Abilities include powers to deed, modify, and sell land in this group&apos;s land holdings. To get to the About Land window, right-click the ground and select &apos;About Land&apos;, or click the &apos;i&apos; icon in the Navigation Bar."
+ name="Parcel Management">
+ <action description="Deed land and buy land for group"
+ longdescription="Deed land and buy land for group. This is done in About Land &gt; General tab."
+ name="land deed" value="12" />
+ <action description="Abandon land to Governor Linden"
+ longdescription="Abandon land to Governor Linden. *WARNING* Any Member in a Role with this Ability can abandon group-owned land in About Land &gt; General tab, reverting it to Linden ownership without a sale! Be sure you know what you&apos;re doing before assigning this Ability."
+ name="land release" value="13" />
+ <action description="Set land for sale info"
+ longdescription="Set land for sale info. *WARNING* Any Member in a Role with this Ability can sell group-owned land in About Land &gt; General tab as they wish! Be sure you know what you&apos;re doing before assigning this Ability."
+ name="land set sale info" value="14" />
+ <action description="Subdivide and join parcels"
+ longdescription="Subdivide and join parcels. This is done by right-clicking the ground, &apos;Edit Terrain&apos;, and dragging your mouse on the land to make a selection. To subdivide, select what you want to split and click &apos;Subdivide&apos;. To join, select two or more contiguous parcels and click &apos;Join&apos;. "
+ name="land divide join" value="15" />
+ </action_set>
+ <action_set
+ description="These Abilities include powers to change the parcel name and publish settings, Find directory visibility, and landing point &amp; TP routing options."
+ name="Parcel Identity">
+ <action description="Toggle &apos;Show Place in Search&apos; and set category"
+ longdescription="Toggle &apos;Show Place in Search&apos; and setting a parcel&apos;s category in About Land &gt; Options tab."
+ name="land find places" value="17" />
+ <action
+ description="Change parcel name, description, and &apos;Show Place in Search&apos; settings"
+ longdescription="Change parcel name, description, and &apos;Show Place in Search&apos; settings. This is done in About Land &gt; Options tab."
+ name="land change identity" value="18" />
+ <action description="Set landing point and set teleport routing"
+ longdescription="On a group-owned parcel, Members in a Role with this Ability can set a landing point to specify where incoming teleports arrive, and also set teleport routing for further control. This is done in About Land &gt; Options tab."
+ name="land set landing point" value="19" />
+ </action_set>
+ <action_set
+ description="These Abilities include powers which affect parcel options, such as &apos;Create Objects&apos;, &apos;Edit Terrain&apos;, and music &amp; media settings."
+ name="Parcel Settings">
+ <action description="Change music &amp; media settings"
+ longdescription="Change streaming music and movie settings in About Land &gt; Media tab."
+ name="land change media" value="20" />
+ <action description="Toggle &apos;Edit Terrain&apos;"
+ longdescription="Toggle &apos;Edit Terrain&apos;. *WARNING* About Land &gt; Options tab &gt; Edit Terrain allows anyone to terraform your land&apos;s shape, and place and move Linden plants. Be sure you know what you&apos;re doing before assigning this Ability. Editing terrain is toggled in About Land &gt; Options tab."
+ name="land edit" value="21" />
+ <action description="Toggle various About Land &gt; Options settings"
+ longdescription="Toggle &apos;Safe (no damage)&apos;, &apos;Fly&apos;, and allow other Residents to: &apos;Edit Terrain&apos;, &apos;Build&apos;, &apos;Create Landmarks&apos;, and &apos;Run Scripts&apos; on group-owned land in About Land &gt; Options tab."
+ name="land options" value="22" />
+ </action_set>
+ <action_set
+ description="These Abilities include powers which allow Members to bypass restrictions on group-owned parcels."
+ name="Parcel Powers">
+ <action description="Always allow &apos;Edit Terrain&apos;"
+ longdescription="Members in a Role with this Ability can edit terrain on a group-owned parcel, even if it&apos;s turned off in About Land &gt; Options tab."
+ name="land allow edit land" value="23" />
+ <action description="Always allow &apos;Fly&apos;"
+ longdescription="Members in a Role with this Ability can fly on a group-owned parcel, even if it&apos;s turned off in About Land &gt; Options tab."
+ name="land allow fly" value="24" />
+ <action description="Always allow &apos;Create Objects&apos;"
+ longdescription="Members in a Role with this Ability can create objects on a group-owned parcel, even if it&apos;s turned off in About Land &gt; Options tab."
+ name="land allow create" value="25" />
+ <action description="Always allow &apos;Create Landmark&apos;"
+ longdescription="Members in a Role with this Ability can landmark a group-owned parcel, even if it&apos;s turned off in About Land &gt; Options tab."
+ name="land allow landmark" value="26" />
+ <action description="Allow &apos;Set Home to Here&apos; on group land"
+ longdescription="Members in a Role with this Ability can use World menu &gt; Landmarks &gt; Set Home to Here on a parcel deeded to this group."
+ name="land allow set home" value="28" />
+ </action_set>
+ <action_set
+ description="These Abilities include powers to allow or restrict access to group-owned parcels, including freezing and ejecting Residents."
+ name="Parcel Access">
+ <action description="Manage parcel Access lists"
+ longdescription="Manage parcel Access lists in About Land &gt; Access tab."
+ name="land manage allowed" value="29" />
+ <action description="Manage parcel Ban lists"
+ longdescription="Manage parcel Ban lists in About Land &gt; Access tab."
+ name="land manage banned" value="30" />
+ <action description="Change parcel &apos;Sell passes to&apos; settings"
+ longdescription="Change parcel &apos;Sell passes to&apos; settings in About Land &gt; Access tab."
+ name="land manage passes" value="31" />
+ <action description="Eject and freeze Residents on parcels"
+ longdescription="Members in a Role with this Ability can handle an unwelcome Resident on a group-owned parcel by right-clicking them, then selecting &apos;Eject&apos; or &apos;Freeze&apos;."
+ name="land admin" value="32" />
+ </action_set>
+ <action_set
+ description="These Abilities include powers to allow members to return objects and place and move Linden plants. This is useful for Members to clean up litter and do landscaping, but it should also be used with care, because there&apos;s no undo for returning objects."
+ name="Parcel Content">
+ <action description="Return objects owned by group"
+ longdescription="Return objects on group-owned parcels that are owned by the group in About Land &gt; Objects tab."
+ name="land return group owned" value="48" />
+ <action description="Return objects set to group"
+ longdescription="Return objects on group-owned parcels that are set to the group in About Land &gt; Objects tab."
+ name="land return group set" value="33" />
+ <action description="Return non-group objects"
+ longdescription="Return objects on group-owned parcels that are non-group in About Land &gt; Objects tab."
+ name="land return non group" value="34" />
+ <action description="Landscaping using Linden plants"
+ longdescription="Landscaping ability to place and move Linden trees, plants, and grasses. These items can be found in your inventory&apos;s Library &gt; Objects folder, or they can be created via the Build menu."
+ name="land gardening" value="35" />
+ </action_set>
+ <action_set
+ description="These Abilities include powers to deed, modify, and sell group-owned objects. These changes are done in the Build Tools &gt; General tab. Right-click an object and Edit to see its settings. "
+ name="Object Management">
+ <action description="Deed objects to group"
+ longdescription="Deed objects to group in the Build Tools &gt; General tab."
+ name="object deed" value="36" />
+ <action description="Manipulate (move, copy, modify) group-owned objects"
+ longdescription="Manipulate (move, copy, modify) group-owned objects in the Build Tools &gt; General tab."
+ name="object manipulate" value="38" />
+ <action description="Set group-owned objects for sale"
+ longdescription="Set group-owned objects for sale in the Build Tools &gt; General tab."
+ name="object set sale" value="39" />
+ </action_set>
+ <action_set
+ description="These Abilities include powers which require Members to pay group liabilities and receive group dividends, and restrict access to group account history."
+ name="Accounting">
+ <action description="Pay group liabilities and receive group dividends"
+ longdescription="Members in a Role with this Ability will automatically pay group liabilities and receive group dividends. This means they will receive a portion of group-owned land sales which are distributed daily, as well as contribute towards things like parcel listing fees. "
+ name="accounting accountable" value="40" />
+ </action_set>
+ <action_set
+ description="These Abilities include powers to allow Members to send, receive, and view group Notices."
+ name="Notices">
+ <action description="Send Notices"
+ longdescription="Members in a Role with this Ability can send Notices via the Group &gt; Notices section."
+ name="notices send" value="42" />
+ <action description="Receive Notices and view past Notices"
+ longdescription="Members in a Role with this Ability can receive Notices and view past Notices in Group &gt; Notices section."
+ name="notices receive" value="43" />
+ </action_set>
+ <action_set
+ description="These Abilities include powers to allow or restrict access to group chat sessions and group voice chat."
+ name="Chat">
+ <action description="Join Group Chat"
+ longdescription="Members in a Role with this Ability can join group chat sessions, for text and voice."
+ name="join group chat" value="16" />
+ <action description="Join Group Voice Chat"
+ longdescription="Members in a Role with this Ability can join group voice chat sessions. NOTE: The Join Group Chat ability is required to access the voice chat session."
+ name="join voice chat" value="27" />
+ <action description="Moderate Group Chat"
+ longdescription="Members in a Role with this Ability can control access and participation in group voice and text chat sessions."
+ name="moderate group chat" value="37" />
+ </action_set>
+</role_actions>
diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
new file mode 100644
index 0000000000..fab1f11273
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+background_visible="true"
+follows="all"
+height="570"
+label="Outfits"
+layout="topleft"
+min_height="350"
+min_width="240"
+name="appearance panel"
+top="0"
+left="0"
+width="333">
+ <string
+ name="No Outfit"
+ value="No Outfit" />
+ <panel
+ left="0"
+ top="0"
+ follows="all"
+ layout="topleft"
+ width="330"
+ height="33"
+ name="panel_currentlook"
+ >
+ <button
+ follows="left|top"
+ top="0" width="1" height="1"
+ layout="topleft"
+ left="0"
+ name="editappearance_btn" />
+ <button
+ follows="left|top"
+ top="0" width="1" height="1"
+ layout="topleft"
+ left="0"
+ name="openoutfit_btn" />
+ <icon
+ follows="top|left"
+ height="30"
+ image_name="TabIcon_Appearance_Off"
+ name="outfit_icon"
+ mouse_opaque="false"
+ visible="true"
+ left="5"
+ top="0"
+ width="30" />
+ <text
+ font="SansSerifHuge"
+ height="20"
+ left_pad="5"
+ text_color="white"
+ top="3"
+ use_ellipses="true"
+ width="305"
+ follows="top|left"
+ word_wrap="true"
+ mouse_opaque="false"
+ name="currentlook_name">
+ MyOutfit With a really Long Name like MOOSE
+ </text>
+ <text
+ font="SansSerifSmall"
+ text_color="White_50"
+ width="300"
+ height="1"
+ follows="top|left"
+ layout="topleft"
+ top_pad="5"
+ mouse_opaque="false"
+ name="currentlook_title" >
+ (unsaved)
+ </text>
+ </panel>
+ <filter_editor
+ height="23"
+ follows="left|top|right"
+ layout="topleft"
+ left="15"
+ label="Filter Outfits"
+ max_length="300"
+ name="Filter"
+ top_pad="10"
+ width="303" />
+ <panel
+ class="panel_outfits_inventory"
+ filename="panel_outfits_inventory.xml"
+ name="panel_outfits_inventory"
+ height="505"
+ min_height="410"
+ width="320"
+ left="0"
+ top_pad="0"
+ follows="all" />
+ <!-- <button
+ follows="bottom|left"
+ height="23"
+ label="New outfit"
+ layout="topleft"
+ left_pad="5"
+ right="-10"
+ name="newlook_btn"
+ width="100" />-->
+ <panel
+ class="panel_look_info"
+ filename="panel_look_info.xml"
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="panel_look_info"
+ top="35"
+ visible="false" />
+ <panel
+ class="panel_edit_wearable"
+ filename="panel_edit_wearable.xml"
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="panel_edit_wearable"
+ top="35"
+ visible="false" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
new file mode 100644
index 0000000000..fb5f9d2ec8
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ follows="all"
+ height="570"
+ label="Things"
+ layout="topleft"
+ min_height="350"
+ min_width="240"
+ name="objects panel"
+ width="333">
+ <panel
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="sidepanel__inventory_panel"
+ top="0"
+ label=""
+ height="570"
+ visible="true"
+ width="330">
+ <panel
+ class="panel_main_inventory"
+ filename="panel_main_inventory.xml"
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="panel_main_inventory"
+ top="0"
+ label=""
+ height="545"
+ width="330" />
+ <panel
+ height="25"
+ layout="bottomright"
+ name="button_panel"
+ left="5"
+ bottom="5"
+ width="313">
+ <button
+ enabled="true"
+ follows="bottom|left"
+ height="23"
+ label="Profile"
+ layout="topleft"
+ left="0"
+ name="info_btn"
+ top="0"
+ width="100" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ height="23"
+ label="Wear"
+ layout="topleft"
+ left="130"
+ name="wear_btn"
+ top="0"
+ width="100" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ height="23"
+ label="Play"
+ layout="topleft"
+ name="play_btn"
+ left="130"
+ top="0"
+ width="80" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ height="23"
+ label="Teleport"
+ layout="topleft"
+ left="130"
+ name="teleport_btn"
+ top="0"
+ width="100" />
+ </panel>
+ </panel>
+
+<panel
+ follows="all"
+ layout="topleft"
+ left="0"
+ class="sidepanel_item_info"
+ filename="sidepanel_item_info.xml"
+ name="sidepanel__item_panel"
+ top="0"
+ label=""
+ height="570"
+ visible="false"
+ width="330">
+ </panel>
+
+<panel
+ follows="all"
+ layout="topleft"
+ left="0"
+ class="sidepanel_task_info"
+ filename="sidepanel_task_info.xml"
+ name="sidepanel__task_panel"
+ top="0"
+ label=""
+ height="570"
+ visible="false"
+ width="330">
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml
new file mode 100644
index 0000000000..e18f59ab64
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml
@@ -0,0 +1,416 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ auto_tile="true"
+ height="570"
+ layout="topleft"
+ name="item properties"
+ help_topic="item_properties"
+ save_rect="true"
+ title="Object Profile"
+ width="333">
+ <panel.string
+ name="unknown">
+ (unknown)
+ </panel.string>
+ <panel.string
+ name="public">
+ (public)
+ </panel.string>
+ <panel.string
+ name="you_can">
+ You can:
+ </panel.string>
+ <panel.string
+ name="owner_can">
+ Owner can:
+ </panel.string>
+ <panel.string
+ name="acquiredDate">
+ [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+ </panel.string>
+ <icon
+ follows="top|right"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ right="-15"
+ mouse_opaque="true"
+ name="IconLocked"
+ top="8"
+ width="18" />
+ <button
+ follows="top|right"
+ height="23"
+ image_overlay="BackArrow_Off"
+ layout="topleft"
+ left="10"
+ name="back_btn"
+ tab_stop="false"
+ top="0"
+ width="23" />
+ <text
+ follows="top|left|right"
+ font="SansSerifHuge"
+ height="26"
+ layout="topleft"
+ left_pad="10"
+ name="title"
+ text_color="LtGray"
+ top="0"
+ use_ellipses="true"
+ value="Object Profile"
+ width="275" />
+ <text
+ follows="top|left"
+ height="13"
+ layout="topleft"
+ left="45"
+ name="where"
+ text_color="LtGray_50"
+ value="(Inventory)"
+ width="150" />
+ <panel
+ follows="all"
+ height="490"
+ label=""
+ layout="topleft"
+ left="10"
+ help_topic=""
+ top="45"
+ width="313"
+ background_visible="true"
+ bg_alpha_color="DkGray2">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="5"
+ name="LabelItemNameTitle"
+ top="10"
+ width="78">
+ Name:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ height="20"
+ layout="topleft"
+ left_delta="78"
+ max_length="63"
+ name="LabelItemName"
+ top_delta="0"
+ width="225" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="5"
+ name="LabelItemDescTitle"
+ top_pad="10"
+ width="78">
+ Description:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ height="23"
+ layout="topleft"
+ left_delta="78"
+ max_length="127"
+ name="LabelItemDesc"
+ top_delta="-5"
+ width="225" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left="5"
+ name="LabelCreatorTitle"
+ top_pad="10"
+ width="78">
+ Creator:
+ </text>
+ <avatar_icon
+ follows="top|left"
+ height="20"
+ default_icon_name="Generic_Person"
+ layout="topleft"
+ left_pad="0"
+ top_delta="-6"
+ mouse_opaque="true"
+ width="20" />
+ <text
+ type="string"
+ follows="left|right|top"
+ font="SansSerifSmall"
+ height="15"
+ layout="topleft"
+ left_pad="5"
+ name="LabelCreatorName"
+ top_delta="6"
+ width="140">
+ Nicole Linden
+ </text>
+ <button
+ follows="top|right"
+ height="23"
+ label="Profile"
+ layout="topleft"
+ right="-1"
+ name="BtnCreator"
+ top_delta="-6"
+ width="78" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left="5"
+ name="LabelOwnerTitle"
+ top_pad="10"
+ width="78">
+ Owner:
+ </text>
+ <avatar_icon
+ follows="top|left"
+ height="20"
+ default_icon_name="Generic_Person"
+ layout="topleft"
+ left_pad="0"
+ top_delta="-6"
+ mouse_opaque="true"
+ width="20" />
+ <text
+ type="string"
+ follows="left|right|top"
+ font="SansSerifSmall"
+ height="15"
+ layout="topleft"
+ left_pad="5"
+ name="LabelOwnerName"
+ top_delta="6"
+ width="140">
+ Thrax Linden
+ </text>
+ <button
+ follows="top|right"
+ height="23"
+ label="Profile"
+ layout="topleft"
+ right="-1"
+ name="BtnOwner"
+ top_delta="-3"
+ width="78" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left="5"
+ name="LabelAcquiredTitle"
+top_pad="10"
+ width="78">
+ Acquired:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left_delta="78"
+ name="LabelAcquiredDate"
+ top_delta="0"
+ width="222">
+ Wed May 24 12:50:46 2006
+ </text>
+ <panel
+ border="false"
+ follows="left|top"
+ layout="topleft"
+ mouse_opaque="false"
+ background_visible="true"
+ bg_alpha_color="DkGray"
+ name="perms_inv"
+ left="0"
+ top_pad="25"
+ height="155"
+ width="313">
+ <text
+ type="string"
+ length="1"
+ left="10"
+ top_pad="13"
+ text_color="EmphasisColor"
+ height="15"
+ follows="left|top|right"
+ layout="topleft"
+ name="perm_modify"
+ width="200">
+ You can:
+ </text>
+ <check_box
+ height="18"
+ label="Modify"
+ layout="topleft"
+ left="20"
+ name="CheckOwnerModify"
+ top_pad="0"
+ width="90" />
+ <check_box
+ height="18"
+ label="Copy"
+ layout="topleft"
+ left_pad="0"
+ name="CheckOwnerCopy"
+ width="90" />
+ <check_box
+ height="18"
+ label="Transfer"
+ layout="topleft"
+ left_pad="0"
+ name="CheckOwnerTransfer"
+ width="106" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="AnyoneLabel"
+ top_pad="8"
+ width="100">
+ Anyone:
+ </text>
+ <check_box
+ height="18"
+ label="Copy"
+ layout="topleft"
+ left_pad="0"
+ name="CheckEveryoneCopy"
+ top_delta="-2"
+ width="150" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="GroupLabel"
+ top_pad="8"
+ width="100">
+ Group:
+ </text>
+ <check_box
+ height="18"
+ label="Share"
+ layout="topleft"
+ left_pad="0"
+ top_delta="-2"
+ name="CheckShareWithGroup"
+ tool_tip="Allow all members of the set group to share your modify permissions for this object. You must Deed to enable role restrictions."
+ width="150" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="NextOwnerLabel"
+ top_pad="8"
+ width="200"
+ word_wrap="true">
+ Next owner:
+ </text>
+ <check_box
+ height="18"
+ label="Modify"
+ layout="topleft"
+ left="20"
+ top_pad="0"
+ name="CheckNextOwnerModify"
+ width="90" />
+ <check_box
+ height="18"
+ label="Copy"
+ layout="topleft"
+ left_pad="0"
+ name="CheckNextOwnerCopy"
+ width="90" />
+ <check_box
+ height="18"
+ label="Transfer"
+ layout="topleft"
+ left_pad="0"
+ name="CheckNextOwnerTransfer"
+ tool_tip="Next owner can give away or resell this object"
+ width="106" />
+ </panel>
+ <check_box
+ height="18"
+ label="For Sale"
+ layout="topleft"
+ left="20"
+ name="CheckPurchase"
+ top_pad="20"
+ width="100" />
+ <combo_box
+ height="23"
+ left_pad="0"
+ layout="topleft"
+ follows="left|top"
+ name="combobox sale copy"
+ width="170">
+ <combo_box.item
+ label="Copy"
+ name="Copy"
+ value="Copy" />
+ <combo_box.item
+ label="Original"
+ name="Original"
+ value="Original" />
+ </combo_box>
+ <spinner
+ follows="left|top"
+ decimal_digits="0"
+ increment="1"
+ control_name="Edit Cost"
+ name="Edit Cost"
+ label="Price: L$"
+ label_width="75"
+ left="120"
+ width="170"
+ min_val="1"
+ height="23"
+ max_val="999999999"
+ top_pad="10"/>
+ </panel>
+ <panel
+ height="30"
+ layout="bottomright"
+ name="button_panel"
+ left="5"
+ bottom="2"
+ width="313">
+ <button
+ height="23"
+ label="Cancel"
+ layout="topleft"
+ name="cancel_btn"
+ right="-1"
+ width="100" />
+ </panel>
+ </panel>
diff --git a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml
new file mode 100644
index 0000000000..74f97dca4e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml
@@ -0,0 +1,553 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ auto_tile="true"
+ height="570"
+ layout="topleft"
+ name="object properties"
+ help_topic="object_properties"
+ save_rect="true"
+ title="Object Profile"
+ width="333">
+ <panel.string
+ name="text deed continued">
+ Deed
+ </panel.string>
+ <panel.string
+ name="text deed">
+ Deed
+ </panel.string>
+ <panel.string
+ name="text modify info 1">
+ You can modify this object
+ </panel.string>
+ <panel.string
+ name="text modify info 2">
+ You can modify these objects
+ </panel.string>
+ <panel.string
+ name="text modify info 3">
+ You can't modify this object
+ </panel.string>
+ <panel.string
+ name="text modify info 4">
+ You can't modify these objects
+ </panel.string>
+ <panel.string
+ name="text modify warning">
+ This object has linked parts
+ </panel.string>
+ <panel.string
+ name="Cost Default">
+ Price: L$
+ </panel.string>
+ <panel.string
+ name="Cost Total">
+ Total Price: L$
+ </panel.string>
+ <panel.string
+ name="Cost Per Unit">
+ Price Per: L$
+ </panel.string>
+ <panel.string
+ name="Cost Mixed">
+ Mixed Price
+ </panel.string>
+ <panel.string
+ name="Sale Mixed">
+ Mixed Sale
+ </panel.string>
+ <button
+ follows="top|right"
+ height="23"
+ image_overlay="BackArrow_Off"
+ layout="topleft"
+ left="10"
+ name="back_btn"
+ tab_stop="false"
+ top="0"
+ width="23" />
+ <text
+ follows="top|left|right"
+ font="SansSerifHuge"
+ height="26"
+ layout="topleft"
+ left_pad="10"
+ name="title"
+ text_color="LtGray"
+ top="0"
+ use_ellipses="true"
+ value="Object Profile"
+ width="275" />
+ <text
+ follows="top|left"
+ height="13"
+ layout="topleft"
+ left="45"
+ name="where"
+ text_color="LtGray_50"
+ value="(In World)"
+ width="150" />
+ <panel
+ follows="all"
+ height="490"
+ label=""
+ layout="topleft"
+ left="10"
+ help_topic=""
+ top="45"
+ width="313"
+ background_visible="true"
+ bg_alpha_color="DkGray2">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="5"
+ name="Name:"
+ top="10"
+ width="78">
+ Name:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ height="20"
+ layout="topleft"
+ left_delta="78"
+ max_length="63"
+ name="Object Name"
+ top_delta="0"
+ width="225" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="5"
+ name="Description:"
+ top_pad="10"
+ width="78">
+ Description:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ height="23"
+ layout="topleft"
+ name="Object Description"
+ select_on_focus="true"
+ left_delta="78"
+ max_length="127"
+ top_delta="-5"
+ width="225"/>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left="5"
+ name="CreatorNameLabel"
+ top_pad="12"
+ width="78">
+ Creator:
+ </text>
+ <text
+ type="string"
+ follows="left|right|top"
+ font="SansSerifSmall"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="Creator Name"
+ top_delta="0"
+ width="140">
+ Erica Linden
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left="5"
+ name="Owner:"
+ top_pad="15"
+ width="78">
+ Owner:
+ </text>
+ <text
+ type="string"
+ follows="left|right|top"
+ font="SansSerifSmall"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="Owner Name"
+ top_delta="0"
+ width="140">
+ Erica Linden
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ left="5"
+ name="Group_label"
+ top_pad="15"
+ width="78">
+ Group:
+ </text>
+ <button
+ follows="top|left"
+ height="10"
+ image_disabled="Activate_Checkmark"
+ image_selected="Activate_Checkmark"
+ image_unselected="Activate_Checkmark"
+ image_color="White_50"
+ layout="topleft"
+ left_pad="0"
+ top_delta="0"
+ name="button set group"
+ picture_style="true"
+ tab_stop="false"
+ tool_tip="Choose a group to share this object's permissions"
+ width="10" />
+ <name_box
+ follows="left|top"
+ height="18"
+ initial_value="Loading..."
+ layout="topleft"
+ left_pad="5"
+ top_delta="-1"
+ name="Group Name Proxy"
+ width="150" />
+ <button
+ follows="top|left"
+ height="23"
+ label="Deed"
+ label_selected="Deed"
+ layout="topleft"
+ name="button deed"
+ top_pad="0"
+ left="81"
+ tool_tip="Deeding gives this item away with next owner permissions. Group shared objects can be deeded by a group officer."
+ width="100" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="9"
+ layout="topleft"
+ top_pad="5"
+ left="5"
+ name="label click action"
+ width="280">
+ Click to:
+ </text>
+ <combo_box
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ name="clickaction"
+ width="168"
+ left="81">
+ <combo_box.item
+ label="Touch (default)"
+ name="Touch/grab(default)"
+ value="Touch/grab (default)" />
+ <combo_box.item
+ label="Sit on object"
+ name="Sitonobject"
+ value="Sit on object" />
+ <combo_box.item
+ label="Buy object"
+ name="Buyobject"
+ value="Buy object" />
+ <combo_box.item
+ label="Pay object"
+ name="Payobject"
+ value="Pay object" />
+ <combo_box.item
+ label="Open"
+ name="Open"
+ value="Open" />
+ </combo_box>
+ <panel
+ border="false"
+ follows="left|top"
+ layout="topleft"
+ mouse_opaque="false"
+ background_visible="true"
+ bg_alpha_color="DkGray"
+ name="perms_inv"
+ left="0"
+ top_pad="15"
+ height="135"
+ width="313">
+ <text
+ type="string"
+ length="1"
+ left="10"
+ top_pad="15"
+ text_color="EmphasisColor"
+ height="15"
+ follows="left|top|right"
+ layout="topleft"
+ name="perm_modify"
+ width="200">
+ You can modify this object
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="Anyone can:"
+ top_pad="8"
+ width="100">
+ Anyone:
+ </text>
+ <check_box
+ height="18"
+ label="Copy"
+ layout="topleft"
+ left_pad="0"
+ name="checkbox allow everyone copy"
+ top_delta="-2"
+ width="90" />
+ <check_box
+ height="18"
+ label="Move"
+ layout="topleft"
+ name="checkbox allow everyone move"
+ left_pad="0"
+ width="150" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="GroupLabel"
+ top_pad="8"
+ width="100">
+ Group:
+ </text>
+ <check_box
+ height="18"
+ label="Share"
+ layout="topleft"
+ left_pad="90"
+ top_delta="-2"
+ name="checkbox share with group"
+ tool_tip="Allow all members of the set group to share your modify permissions for this object. You must Deed to enable role restrictions."
+ width="150" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="NextOwnerLabel"
+ top_pad="8"
+ width="200"
+ word_wrap="true">
+ Next owner:
+ </text>
+ <check_box
+ height="18"
+ label="Modify"
+ layout="topleft"
+ left="20"
+ top_pad="0"
+ name="checkbox next owner can modify"
+ width="90" />
+ <check_box
+ height="18"
+ label="Copy"
+ layout="topleft"
+ left_pad="0"
+ name="checkbox next owner can copy"
+ width="90" />
+ <check_box
+ height="18"
+ label="Transfer"
+ layout="topleft"
+ left_pad="0"
+ name="checkbox next owner can transfer"
+ tool_tip="Next owner can give away or resell this object"
+ width="106" />
+ </panel>
+ <check_box
+ height="23"
+ label="For Sale"
+ layout="topleft"
+ left="20"
+ name="checkbox for sale"
+ top_pad="10"
+ width="100" />
+ <combo_box
+ height="23"
+ left_pad="0"
+ layout="topleft"
+ follows="left|top"
+ name="sale type"
+ width="170">
+ <combo_box.item
+ name="Copy"
+ label="Copy"
+ value="2" />
+ <combo_box.item
+ name="Contents"
+ label="Contents"
+ value="3" />
+ <combo_box.item
+ name="Original"
+ label="Original"
+ value="1" />
+ </combo_box>
+ <spinner
+ follows="left|top"
+ decimal_digits="0"
+ increment="1"
+ top_pad="10"
+ left="120"
+ control_name="Edit Cost"
+ name="Edit Cost"
+ label="Price: L$"
+ label_width="65"
+ width="150"
+ min_val="1"
+ height="20"
+ max_val="999999999" />
+ <check_box
+ height="20"
+ width="110"
+ top_pad="6"
+ label="Show in search"
+ layout="topleft"
+ left="120"
+ name="search_check"
+ tool_tip="Let people see this object in search results" />
+ <text
+ type="string"
+ text_color="EmphasisColor"
+ length="1"
+ top_pad="15"
+ follows="left|top"
+ layout="topleft"
+ left="10"
+ name="B:"
+ height="10"
+ width="50">
+ B:
+ </text>
+ <text
+ type="string"
+ text_color="White"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="0"
+ name="O:"
+ height="10"
+ width="50">
+ O:
+ </text>
+ <text
+ type="string"
+ text_color="EmphasisColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="0"
+ name="G:"
+ height="10"
+ width="50">
+ G:
+ </text>
+ <text
+ type="string"
+ text_color="White"
+ length="1"
+ follows="left|top"
+ left_pad="0"
+ layout="topleft"
+ name="E:"
+ height="10"
+ width="50">
+ E:
+ </text>
+ <text
+ type="string"
+ text_color="EmphasisColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="0"
+ name="N:"
+ height="10"
+ width="50">
+ N:
+ </text>
+ <text
+ type="string"
+ text_color="White"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_pad="0"
+ name="F:"
+ height="10"
+ width="50">
+ F:
+ </text>
+ </panel>
+ <panel
+ height="25"
+ layout="bottomright"
+ name="button_panel"
+ left="5"
+ bottom="5"
+ width="313">
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Open"
+ layout="topleft"
+ left="5"
+ name="open_btn"
+ top="0"
+ width="100" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Pay"
+ layout="topleft"
+ left_pad="5"
+ name="pay_btn"
+ top="0"
+ width="100" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Buy"
+ layout="topleft"
+ left_pad="5"
+ name="buy_btn"
+ top="0"
+ width="100" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
new file mode 100644
index 0000000000..b378944e48
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -0,0 +1,3013 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- This file contains strings that used to be hardcoded in the source.
+ It is only for those strings which do not belong in a floater.
+ For example, the strings used in avatar chat bubbles, and strings
+ that are returned from one component and may appear in many places-->
+<strings>
+
+ <!-- Default Args - these arguments will be replaced in all strings -->
+ <string name="SECOND_LIFE">Second Life</string>
+ <string name="APP_NAME">Second Life</string>
+ <string name="CAPITALIZED_APP_NAME">SECOND LIFE</string>
+ <string name="SECOND_LIFE_GRID">Second Life Grid</string>
+ <string name="SUPPORT_SITE">Second Life Support Portal</string>
+
+ <!-- starting up -->
+ <string name="StartupDetectingHardware">Detecting hardware...</string>
+ <string name="StartupLoading">Loading</string>
+
+ <!-- Legacy strings, almost never used -->
+ <string name="Fullbright">Fullbright (Legacy)</string> <!-- used in the Build > materials dropdown-->
+
+ <!-- Login -->
+ <string name="LoginInProgress">Logging in. [APP_NAME] may appear frozen. Please wait.</string>
+ <string name="LoginInProgressNoFrozen">Logging in...</string>
+ <string name="LoginAuthenticating">Authenticating</string>
+ <string name="LoginMaintenance">Performing account maintenance...</string>
+ <string name="LoginAttempt">Previous login attempt failed. Logging in, attempt [NUMBER]</string>
+ <string name="LoginPrecaching">Loading world...</string>
+ <string name="LoginInitializingBrowser">Initializing embedded web browser...</string>
+ <string name="LoginInitializingMultimedia">Initializing multimedia...</string>
+ <string name="LoginInitializingFonts">Loading fonts...</string>
+ <string name="LoginVerifyingCache">Verifying cache files (can take 60-90 seconds)...</string>
+ <string name="LoginProcessingResponse">Processing Response...</string>
+ <string name="LoginInitializingWorld">Initializing World...</string>
+ <string name="LoginDecodingImages">Decoding images...</string>
+ <string name="LoginInitializingQuicktime">Initializing QuickTime...</string>
+ <string name="LoginQuicktimeNotFound">QuickTime not found - unable to initialize.</string>
+ <string name="LoginQuicktimeOK">QuickTime initialized successfully.</string>
+ <string name="LoginWaitingForRegionHandshake">Waiting for region handshake...</string>
+ <string name="LoginConnectingToRegion">Connecting to region...</string>
+ <string name="LoginDownloadingClothing">Downloading clothing...</string>
+ <string name="LoginFailedNoNetwork">Network Error: Could not establish connection, please check your network connection.</string>
+ <string name="Quit">Quit</string>
+ <string name="create_account_url">http://join.secondlife.com/</string>
+
+ <!-- Disconnection -->
+ <string name="AgentLostConnection">This region may be experiencing trouble. Please check your connection to the Internet.</string>
+
+
+ <!-- Tooltip, lltooltipview.cpp -->
+ <string name="TooltipPerson">Person</string><!-- Object under mouse pointer is an avatar -->
+ <string name="TooltipNoName">(no name)</string> <!-- No name on an object -->
+ <string name="TooltipOwner">Owner:</string> <!-- Owner name follows -->
+ <string name="TooltipPublic">Public</string> <!-- Public permissions on an object -->
+ <string name="TooltipIsGroup">(Group)</string> <!-- The name before this text is that of a group -->
+ <string name="TooltipForSaleL$">For Sale: L$[AMOUNT]</string> <!-- L$ version -->
+ <string name="TooltipFlagGroupBuild">Group Build</string>
+ <string name="TooltipFlagNoBuild">No Build</string>
+ <string name="TooltipFlagNoEdit">Group Build</string>
+ <string name="TooltipFlagNotSafe">Not Safe</string><!-- damage area -->
+ <string name="TooltipFlagNoFly">No Fly</string>
+ <string name="TooltipFlagGroupScripts">Group Scripts</string>
+ <string name="TooltipFlagNoScripts">No Scripts</string>
+ <string name="TooltipLand">Land:</string>
+ <string name="TooltipMustSingleDrop">Only a single item can be dragged here</string>
+
+ <!-- tooltips for Urls -->
+ <string name="TooltipHttpUrl">Click to view this web page</string>
+ <string name="TooltipSLURL">Click to view this location's information</string>
+ <string name="TooltipAgentUrl">Click to view this Resident's profile</string>
+ <string name="TooltipGroupUrl">Click to view this group's description</string>
+ <string name="TooltipEventUrl">Click to view this event's description</string>
+ <string name="TooltipClassifiedUrl">Click to view this classified</string>
+ <string name="TooltipParcelUrl">Click to view this parcel's description</string>
+ <string name="TooltipTeleportUrl">Click to teleport to this location</string>
+ <string name="TooltipObjectIMUrl">Click to view this object's description</string>
+ <string name="TooltipMapUrl">Click to view this location on a map</string>
+ <string name="TooltipSLAPP">Click to run the secondlife:// command</string>
+ <string name="CurrentURL" value=" CurrentURL: [CurrentURL]" />
+
+ <!-- text for SLURL labels -->
+ <string name="SLurlLabelTeleport">Teleport to</string>
+ <string name="SLurlLabelShowOnMap">Show Map for</string>
+
+ <!-- ButtonToolTips, llfloater.cpp -->
+ <string name="BUTTON_CLOSE_DARWIN">Close (&#8984;W)</string>
+ <string name="BUTTON_CLOSE_WIN">Close (Ctrl+W)</string>
+ <string name="BUTTON_RESTORE">Restore</string>
+ <string name="BUTTON_MINIMIZE">Minimize</string>
+ <string name="BUTTON_TEAR_OFF">Tear Off</string>
+ <string name="BUTTON_DOCK">Dock</string>
+ <string name="BUTTON_HELP">Show Help</string>
+
+ <!-- searching - generic -->
+ <string name="Searching">Searching...</string>
+ <string name="NoneFound">None found.</string>
+
+ <!-- Indicates that an avatar name or other similar datum is being retrieved. General usage. -->
+ <string name="RetrievingData">Retrieving...</string>
+
+ <string name="ReleaseNotes">Release Notes</string>
+ <string name="RELEASE_NOTES_BASE_URL">http://secondlife.com/app/releasenotes/</string>
+
+ <!-- Indicates something is being loaded. Maybe should be merged with RetrievingData -->
+ <string name="LoadingData">Loading...</string>
+
+
+ <!-- namecache -->
+ <!-- Avatar name: text shown for LLUUID::null -->
+ <string name="AvatarNameNobody">(nobody)</string>
+
+ <!-- Avatar name: text shown while fetching name -->
+ <string name="AvatarNameWaiting">(waiting)</string>
+
+ <!-- Avatar name: More than one avatar is selected/used here -->
+ <string name="AvatarNameMultiple">(multiple)</string>
+
+ <!-- Avatar name: text shown as an alternative to AvatarNameFetching, easter egg. -->
+ <string name="AvatarNameHippos">(hippos)</string>
+
+ <!-- Group name: text shown for LLUUID::null -->
+ <string name="GroupNameNone">(none)</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>
+ <string name="AssetErrorNonexistentFile">Asset request: non-existent file</string>
+ <string name="AssetErrorNotInDatabase">Asset request: asset not found in database</string>
+ <string name="AssetErrorEOF">End of file</string>
+ <string name="AssetErrorCannotOpenFile">Cannot open file</string>
+ <string name="AssetErrorFileNotFound">File not found</string>
+ <string name="AssetErrorTCPTimeout">File transfer timeout</string>
+ <string name="AssetErrorCircuitGone">Circuit gone</string>
+ <string name="AssetErrorPriceMismatch">Viewer and server do not agree on price</string>
+ <string name="AssetErrorUnknownStatus">Unknown status</string>
+
+ <!-- Asset Type human readable names: these will replace variable [TYPE] in notification FailedToFindWearable* -->
+ <string name="texture">texture</string>
+ <string name="sound">sound</string>
+ <string name="calling card">calling card</string>
+ <string name="landmark">landmark</string>
+ <string name="legacy script">legacy script</string>
+ <string name="clothing">clothing</string>
+ <string name="object">object</string>
+ <string name="note card">notecard</string>
+ <string name="folder">folder</string>
+ <string name="root">root</string>
+ <string name="lsl2 script">LSL2 script</string>
+ <string name="lsl bytecode">LSL bytecode</string>
+ <string name="tga texture">tga texture</string>
+ <string name="body part">body part</string>
+ <string name="snapshot">snapshot</string>
+ <string name="lost and found">Lost and Found</string>
+ <string name="targa image">targa image</string>
+ <string name="trash">Trash</string>
+ <string name="jpeg image">jpeg image</string>
+ <string name="animation">animation</string>
+ <string name="gesture">gesture</string>
+ <string name="simstate">simstate</string>
+ <string name="favorite">favorite</string>
+ <string name="symbolic link">link</string>
+
+ <!-- llvoavatar. Displayed in the avatar chat bubble -->
+ <string name="AvatarEditingAppearance">(Editing Appearance)</string>
+ <string name="AvatarAway">Away</string>
+ <string name="AvatarBusy">Busy</string>
+ <string name="AvatarMuted">Blocked</string>
+
+ <!-- animations -->
+ <string name="anim_express_afraid">Afraid</string>
+ <string name="anim_express_anger">Angry</string>
+ <string name="anim_away">Away</string>
+ <string name="anim_backflip">Backflip</string>
+ <string name="anim_express_laugh">Belly Laugh</string>
+ <string name="anim_express_toothsmile">BigSmile</string>
+ <string name="anim_blowkiss">Blow Kiss</string>
+ <string name="anim_express_bored">Bored</string>
+ <string name="anim_bow">Bow</string>
+ <string name="anim_clap">Clap</string>
+ <string name="anim_courtbow">Court Bow</string>
+ <string name="anim_express_cry">Cry</string>
+ <string name="anim_dance1">Dance 1</string>
+ <string name="anim_dance2">Dance 2</string>
+ <string name="anim_dance3">Dance 3</string>
+ <string name="anim_dance4">Dance 4</string>
+ <string name="anim_dance5">Dance 5</string>
+ <string name="anim_dance6">Dance 6</string>
+ <string name="anim_dance7">Dance 7</string>
+ <string name="anim_dance8">Dance 8</string>
+ <string name="anim_express_disdain">Disdain</string>
+ <string name="anim_drink">Drink</string>
+ <string name="anim_express_embarrased">Embarrassed</string>
+ <string name="anim_angry_fingerwag">Finger Wag</string>
+ <string name="anim_fist_pump">Fist Pump</string>
+ <string name="anim_yoga_float">Floating Yoga</string>
+ <string name="anim_express_frown">Frown</string>
+ <string name="anim_impatient">Impatient</string>
+ <string name="anim_jumpforjoy">Jump For Joy</string>
+ <string name="anim_kissmybutt">Kiss My Butt</string>
+ <string name="anim_express_kiss">Kiss</string>
+ <string name="anim_laugh_short">Laugh</string>
+ <string name="anim_musclebeach">Muscle Beach</string>
+ <string name="anim_no_unhappy">No (Unhappy)</string>
+ <string name="anim_no_head">No</string>
+ <string name="anim_nyanya">Nya-nya-nya</string>
+ <string name="anim_punch_onetwo">One-Two Punch</string>
+ <string name="anim_express_open_mouth">Open Mouth</string>
+ <string name="anim_peace">Peace</string>
+ <string name="anim_point_you">Point at Other</string>
+ <string name="anim_point_me">Point at Self</string>
+ <string name="anim_punch_l">Punch Left</string>
+ <string name="anim_punch_r">Punch Right</string>
+ <string name="anim_rps_countdown">RPS count</string>
+ <string name="anim_rps_paper">RPS paper</string>
+ <string name="anim_rps_rock">RPS rock</string>
+ <string name="anim_rps_scissors">RPS scissors</string>
+ <string name="anim_express_repulsed">Repulsed</string>
+ <string name="anim_kick_roundhouse_r">Roundhouse Kick</string>
+ <string name="anim_express_sad">Sad</string>
+ <string name="anim_salute">Salute</string>
+ <string name="anim_shout">Shout</string>
+ <string name="anim_express_shrug">Shrug</string>
+ <string name="anim_express_smile">Smile</string>
+ <string name="anim_smoke_idle">Smoke Idle</string>
+ <string name="anim_smoke_inhale">Smoke Inhale</string>
+ <string name="anim_smoke_throw_down">Smoke Throw Down</string>
+ <string name="anim_express_surprise">Surprise</string>
+ <string name="anim_sword_strike_r">Sword Strike</string>
+ <string name="anim_angry_tantrum">Tantrum</string>
+ <string name="anim_express_tongue_out">TongueOut</string>
+ <string name="anim_hello">Wave</string>
+ <string name="anim_whisper">Whisper</string>
+ <string name="anim_whistle">Whistle</string>
+ <string name="anim_express_wink">Wink</string>
+ <string name="anim_wink_hollywood">Wink (Hollywood)</string>
+ <string name="anim_express_worry">Worry</string>
+ <string name="anim_yes_happy">Yes (Happy)</string>
+ <string name="anim_yes_head">Yes</string>
+
+ <!-- world map -->
+ <string name="texture_loading">Loading...</string>
+ <string name="worldmap_offline">Offline</string>
+ <string name="worldmap_results_none_found">None found.</string>
+
+ <!-- animations uploading status codes -->
+ <string name="Ok">OK</string>
+ <string name="Premature end of file">Premature end of file</string>
+ <string name="ST_NO_JOINT">Can't find ROOT or JOINT.</string>
+
+ <!-- Chat -->
+ <string name="whisper">whispers:</string>
+ <string name="shout">shouts:</string>
+ <string name="ringing">Connecting to in-world Voice Chat...</string>
+ <string name="connected">Connected</string>
+ <string name="unavailable">Voice not available at your current location</string>
+ <string name="hang_up">Disconnected from in-world Voice Chat</string>
+ <string name="ScriptQuestionCautionChatGranted">'[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been granted permission to: [PERMISSIONS].</string>
+ <string name="ScriptQuestionCautionChatDenied">'[OBJECTNAME]', an object owned by '[OWNERNAME]', located in [REGIONNAME] at [REGIONPOS], has been denied permission to: [PERMISSIONS].</string>
+ <string name="ScriptTakeMoney">Take Linden dollars (L$) from you</string>
+ <string name="ActOnControlInputs">Act on your control inputs</string>
+ <string name="RemapControlInputs">Remap your control inputs</string>
+ <string name="AnimateYourAvatar">Animate your avatar</string>
+ <string name="AttachToYourAvatar">Attach to your avatar</string>
+ <string name="ReleaseOwnership">Release ownership and become public</string>
+ <string name="LinkAndDelink">Link and delink from other objects</string>
+ <string name="AddAndRemoveJoints">Add and remove joints with other objects</string>
+ <string name="ChangePermissions">Change its permissions</string>
+ <string name="TrackYourCamera">Track your camera</string>
+ <string name="ControlYourCamera">Control your camera</string>
+ <string name="NotConnected">Not Connected</string>
+
+ <!-- Sim Access labels -->
+ <string name="SIM_ACCESS_PG">General</string>
+ <string name="SIM_ACCESS_MATURE">Moderate</string>
+ <string name="SIM_ACCESS_ADULT">Adult</string>
+ <string name="SIM_ACCESS_DOWN">Offline</string>
+ <string name="SIM_ACCESS_MIN">Unknown</string>
+
+ <!-- For use when we do not have land type back from the server -->
+ <string name="land_type_unknown">(unknown)</string>
+
+ <!-- File load/save dialogs -->
+ <string name="all_files">All Files</string>
+ <string name="sound_files">Sounds</string>
+ <string name="animation_files">Animations</string>
+ <string name="image_files">Images</string>
+ <string name="save_file_verb">Save</string>
+ <string name="load_file_verb">Load</string>
+ <string name="targa_image_files">Targa Images</string>
+ <string name="bitmap_image_files">Bitmap Images</string>
+ <string name="avi_movie_file">AVI Movie File</string>
+ <string name="xaf_animation_file">XAF Anim File</string>
+ <string name="xml_file">XML File</string>
+ <string name="dot_raw_file">RAW File</string>
+ <string name="compressed_image_files">Compressed Images</string>
+ <string name="load_files">Load Files</string>
+ <string name="choose_the_directory">Choose Directory</string>
+
+ <!-- LSL Usage Hover Tips -->
+ <!-- NOTE: For now these are set as translate="false", until DEV-40761 is implemented (to internationalize the rest of tooltips in the same window).
+ This has no effect on viewer code, but prevents Linden Lab internal localization tool from scraping these strings. -->
+ <string name="LSLTipSleepTime" translate="false">
+Sleeps script for [SLEEP_TIME] seconds.
+ </string>
+
+ <string name="LSLTipText_llSin" translate="false">
+float llSin(float theta)
+Returns the sine of theta (theta in radians)
+ </string>
+ <string name="LSLTipText_llCos" translate="false">
+float llCos(float theta)
+Returns the cosine of theta (theta in radians)
+ </string>
+ <string name="LSLTipText_llTan" translate="false">
+float llTan(float theta)
+Returns the tangent of theta (theta in radians)
+ </string>
+ <string name="LSLTipText_llAtan2" translate="false">
+float llAtan2(float y, float x)
+Returns the arctangent2 of y, x
+ </string>
+ <string name="LSLTipText_llSqrt" translate="false">
+float llSqrt(float val)
+Returns the square root of val, or returns 0 and triggers a Math Error for imaginary results
+ </string>
+ <string name="LSLTipText_llPow" translate="false">
+float llPow(float base, float exponent)
+Returns the base raised to the power exponent, or returns 0 and triggers Math Error for imaginary results
+ </string>
+ <string name="LSLTipText_llAbs" translate="false">
+integer llAbs(integer val)
+Returns the positive version of val
+ </string>
+ <string name="LSLTipText_llFabs" translate="false">
+float llFabs(float val)
+Returns the positive version of val
+ </string>
+ <string name="LSLTipText_llFrand" translate="false">
+float llFrand(float mag)
+Returns a pseudo random number in the range [0,mag) or (mag,0]
+ </string>
+ <string name="LSLTipText_llFloor" translate="false">
+integer llFloor(float val)
+Returns largest integer value &lt;= val
+ </string>
+ <string name="LSLTipText_llCeil" translate="false">
+integer llCeil(float val)
+Returns smallest integer value &gt;= val
+ </string>
+ <string name="LSLTipText_llRound" translate="false">
+integer llRound(float val)
+Returns val rounded to the nearest integer
+ </string>
+ <string name="LSLTipText_llVecMag" translate="false">
+float llVecMag(vector v)
+Returns the magnitude of v
+ </string>
+ <string name="LSLTipText_llVecNorm" translate="false">
+vector llVecNorm(vector v)
+Returns the v normalized
+ </string>
+ <string name="LSLTipText_llVecDist" translate="false">
+float llVecDist(vector v1, vector v2)
+Returns the 3D distance between v1 and v2
+ </string>
+ <string name="LSLTipText_llRot2Euler" translate="false">
+vector llRot2Euler(rotation q)
+Returns the Euler representation (roll, pitch, yaw) of q
+ </string>
+ <string name="LSLTipText_llEuler2Rot" translate="false">
+rotation llEuler2Rot(vector v)
+Returns the rotation representation of Euler Angles v
+ </string>
+ <string name="LSLTipText_llAxes2Rot" translate="false">
+rotation llAxes2Rot(vector fwd, vector left, vector up)
+Returns the rotation defined by the coordinate axes
+ </string>
+ <string name="LSLTipText_llRot2Fwd" translate="false">
+vector llRot2Fwd(rotation q)
+Returns the forward vector defined by q
+ </string>
+ <string name="LSLTipText_llRot2Left" translate="false">
+vector llRot2Left(rotation q)
+Returns the left vector defined by q
+ </string>
+ <string name="LSLTipText_llRot2Up" translate="false">
+vector llRot2Up(rotation q)
+Returns the up vector defined by q
+ </string>
+ <string name="LSLTipText_llRotBetween" translate="false">
+rotation llRotBetween(vector v1, vector v2)
+Returns the rotation to rotate v1 to v2
+ </string>
+ <string name="LSLTipText_llWhisper" translate="false">
+llWhisper(integer channel, string msg)
+Whispers the text of msg on channel
+ </string>
+ <string name="LSLTipText_llSay" translate="false">
+llSay(integer channel, string msg)
+Says the text of msg on channel
+ </string>
+ <string name="LSLTipText_llShout" translate="false">
+llShout(integer channel, string msg)
+Shouts the text of msg on channel
+ </string>
+ <string name="LSLTipText_llListen" translate="false">
+integer llListen(integer channel, string name, key id, string msg)
+Sets a callback for msg on channel from name and id (name, id, and/or msg can be empty) and returns an identifier that can be used to deactivate or remove the listen
+ </string>
+ <string name="LSLTipText_llListenControl" translate="false">
+llListenControl(integer number, integer active)
+Makes a listen event callback active or inactive
+ </string>
+ <string name="LSLTipText_llListenRemove" translate="false">
+llListenRemove(integer number)
+Removes listen event callback number
+ </string>
+ <string name="LSLTipText_llSensor" translate="false">
+llSensor(string name, key id, integer type, float range, float arc)
+Performs a single scan for name and id with type (AGENT, ACTIVE, PASSIVE, and/or SCRIPTED) within range meters and arc radians of forward vector (name, id, and/or keytype can be empty or 0)
+ </string>
+ <string name="LSLTipText_llSensorRepeat" translate="false">
+llSensorRepeat(string name, key id, integer type, float range, float arc, float rate)
+Sets a callback for name and id with type (AGENT, ACTIVE, PASSIVE, and/or SCRIPTED) within range meters and arc radians of forward vector (name, id, and/or keytype can be empty or 0) and repeats every rate seconds
+ </string>
+ <string name="LSLTipText_llSensorRemove" translate="false">
+llSensorRemove()
+Removes the sensor setup by llSensorRepeat
+ </string>
+ <string name="LSLTipText_llDetectedName" translate="false">
+string llDetectedName(integer number)
+Returns the name of detected object number (returns empty string if number is not a valid sensed object)
+ </string>
+ <string name="LSLTipText_llDetectedKey" translate="false">
+key llDetectedKey(integer number)
+Returns the key of detected object number (returns empty key if number is not a valid sensed object)
+ </string>
+ <string name="LSLTipText_llDetectedOwner" translate="false">
+key llDetectedOwner(integer number)
+Returns the key of detected object&apos;s owner (returns empty key if number is not a valid sensed object)
+ </string>
+ <string name="LSLTipText_llDetectedType" translate="false">
+integer llDetectedType(integer number)
+Returns the type (AGENT, ACTIVE, PASSIVE, SCRIPTED) of detected object (returns 0 if number is not a valid sensed object)
+ </string>
+ <string name="LSLTipText_llDetectedPos" translate="false">
+vector llDetectedPos(integer number)
+Returns the position of detected object number (returns &lt;0,0,0&gt; if number is not a valid sensed object)
+ </string>
+ <string name="LSLTipText_llDetectedVel" translate="false">
+vector llDetectedVel(integer number)
+Returns the velocity of detected object number (returns &lt;0,0,0&gt; if number is not a valid sensed object)
+ </string>
+ <string name="LSLTipText_llDetectedGrab" translate="false">
+vector llDetectedGrab(integer number)
+Returns the grab offset of the user touching object (returns &lt;0,0,0&gt; if number is not a valid sensed object)
+ </string>
+ <string name="LSLTipText_llDetectedRot" translate="false">
+rotation llDetectedRot(integer number)
+Returns the rotation of detected object number (returns &lt;0,0,0,1&gt; if number is not a valid sensed object)
+ </string>
+ <string name="LSLTipText_llDetectedGroup" translate="false">
+integer llDetectedGroup(integer number)
+Returns TRUE if detected object is part of same group as owner
+ </string>
+ <string name="LSLTipText_llDetectedLinkNumber" translate="false">
+integer llDetectedLinkNumber(integer number)
+Returns the link position of the triggered event for touches and collisions only
+ </string>
+ <string name="LSLTipText_llDie" translate="false">
+llDie()
+Deletes the object
+ </string>
+ <string name="LSLTipText_llGround" translate="false">
+float llGround(vector offset)
+Returns the ground height below the object position + offset
+ </string>
+ <string name="LSLTipText_llCloud" translate="false">
+float llCloud(vector offset)
+Returns the cloud density at the object position + offset
+ </string>
+ <string name="LSLTipText_llWind" translate="false">
+vector llWind(vector offset)
+Returns the wind velocity at the object position + offset
+ </string>
+ <string name="LSLTipText_llSetStatus" translate="false">
+llSetStatus(integer status, integer value)
+Sets status (STATUS_PHYSICS, STATUS_PHANTOM, STATUS_BLOCK_GRAB, STATUS_ROTATE_X, STATUS_ROTATE_Y, and/or STATUS_ROTATE_Z) to value
+ </string>
+ <string name="LSLTipText_llGetStatus" translate="false">
+integer llGetStatus(integer status)
+Returns value of status (STATUS_PHYSICS, STATUS_PHANTOM, STATUS_BLOCK_GRAB, STATUS_ROTATE_X, STATUS_ROTATE_Y, and/or STATUS_ROTATE_Z)
+ </string>
+ <string name="LSLTipText_llSetScale" translate="false">
+llSetScale(vector scale)
+Sets the scale of the prim
+ </string>
+ <string name="LSLTipText_llGetScale" translate="false">
+vector llGetScale()
+Returns the scale of the prim
+ </string>
+ <string name="LSLTipText_llSetColor" translate="false">
+llSetColor(vector color, integer face)
+Sets the color on face of the prim
+ </string>
+ <string name="LSLTipText_llGetAlpha" translate="false">
+float llGetAlpha(integer face)
+Returns the alpha of face
+ </string>
+ <string name="LSLTipText_llSetAlpha" translate="false">
+llSetAlpha(float alpha, integer face)
+Sets the alpha on face
+ </string>
+ <string name="LSLTipText_llGetColor" translate="false">
+vector llGetColor(integer face)
+Returns the color on face
+ </string>
+ <string name="LSLTipText_llSetTexture" translate="false">
+llSetTexture(string texture, integer face)
+Sets the texture of face or ALL_SIDES
+ </string>
+ <string name="LSLTipText_llScaleTexture" translate="false">
+llScaleTexture(float u, float v, integer face)
+Sets the texture u &amp; v scales for the chosen face or ALL_SIDES
+ </string>
+ <string name="LSLTipText_llOffsetTexture" translate="false">
+llOffsetTexture(float u, float v, integer face)
+Sets the texture u &amp; v offsets for the chosen face or ALL_SIDES
+ </string>
+ <string name="LSLTipText_llRotateTexture" translate="false">
+llRotateTexture(float rotation, integer face)
+Sets the texture rotation for the chosen face
+ </string>
+ <string name="LSLTipText_llGetTexture" translate="false">
+string llGetTexture(integer face)
+Returns a string that is the texture on face (the inventory name if it is a texture in the prim&apos;s inventory, otherwise the key)
+ </string>
+ <string name="LSLTipText_llSetPos" translate="false">
+llSetPos(vector pos)
+Moves the object or prim towards pos without using physics (if the script isn&apos;t physical)
+ </string>
+ <string name="LSLTipText_llGetPos" translate="false">
+vector llGetPos()
+Returns the position of the task in region coordinates
+ </string>
+ <string name="LSLTipText_llGetLocalPos" translate="false">
+vector llGetLocalPos()
+Returns the position relative to the root
+ </string>
+ <string name="LSLTipText_llSetRot" translate="false">
+llSetRot(rotation rot)
+Sets the rotation
+ </string>
+ <string name="LSLTipText_llGetRot" translate="false">
+rotation llGetRot()
+Returns the rotation relative to the region&apos;s axes
+ </string>
+ <string name="LSLTipText_llGetLocalRot" translate="false">
+rotation llGetLocalRot()
+Returns the rotation local to the root
+ </string>
+ <string name="LSLTipText_llSetForce" translate="false">
+llSetForce(vector force, integer local)
+Applies force to the object (if the script is physical), in local coords if local == TRUE
+ </string>
+ <string name="LSLTipText_llGetForce" translate="false">
+vector llGetForce()
+Returns the force (if the script is physical)
+ </string>
+ <string name="LSLTipText_llTarget" translate="false">
+integer llTarget(vector position, float range)
+Sets positions within range of position as a target and return an ID for the target
+ </string>
+ <string name="LSLTipText_llTargetRemove" translate="false">
+llTargetRemove(integer number)
+Removes positional target number registered with llTarget
+ </string>
+ <string name="LSLTipText_llRotTarget" translate="false">
+integer llRotTarget(rotation rot, float error)
+Set rotations with error of rot as a rotational target and return an ID for the rotational target
+ </string>
+ <string name="LSLTipText_llRotTargetRemove" translate="false">
+llRotTargetRemove(integer number)
+Removes rotational target number registered with llRotTarget
+ </string>
+ <string name="LSLTipText_llMoveToTarget" translate="false">
+llMoveToTarget(vector target, float tau)
+Critically damps to target in tau seconds (if the script is physical)
+ </string>
+ <string name="LSLTipText_llStopMoveToTarget" translate="false">
+llStopMoveToTarget()
+Stops critically damped motion
+ </string>
+ <string name="LSLTipText_llApplyImpulse" translate="false">
+llApplyImpulse(vector force, integer local)
+Applies impulse to object (if the script is physical), in local coords if local == TRUE
+ </string>
+ <string name="LSLTipText_llApplyRotationalImpulse" translate="false">
+llApplyRotationalImpulse(vector force, integer local)
+Applies rotational impulse to object (if the script is physical), in local coords if local == TRUE
+ </string>
+ <string name="LSLTipText_llSetTorque" translate="false">
+llSetTorque(vector torque, integer local)
+Sets the torque of object (if the script is physical), in local coords if local == TRUE
+ </string>
+ <string name="LSLTipText_llGetTorque" translate="false">
+vector llGetTorque()
+Returns the torque (if the script is physical)
+ </string>
+ <string name="LSLTipText_llSetForceAndTorque" translate="false">
+llSetForceAndTorque(vector force, vector torque, integer local)
+Sets the force and torque of object (if the script is physical), in local coords if local == TRUE
+ </string>
+ <string name="LSLTipText_llGetVel" translate="false">
+vector llGetVel()
+Returns the velocity of the object
+ </string>
+ <string name="LSLTipText_llGetAccel" translate="false">
+vector llGetAccel()
+Returns the acceleration of the object relative to the region&apos;s axes
+ </string>
+ <string name="LSLTipText_llGetOmega" translate="false">
+vector llGetOmega()
+Returns the rotation velocity in radians per second
+ </string>
+ <string name="LSLTipText_llGetTimeOfDay" translate="false">
+float llGetTimeOfDay()
+Returns the time in seconds since [SECOND_LIFE] server midnight or since region up-time, whichever is smaller
+ </string>
+ <string name="LSLTipText_llGetWallclock" translate="false">
+float llGetWallclock()
+Returns the time in seconds since midnight California Pacific time (PST/PDT)
+ </string>
+ <string name="LSLTipText_llGetTime" translate="false">
+float llGetTime()
+Returns the time in seconds since the last region reset, script reset, or call to either llResetTime or llGetAndResetTime
+ </string>
+ <string name="LSLTipText_llResetTime" translate="false">
+llResetTime()
+Sets the script timer to zero
+ </string>
+ <string name="LSLTipText_llGetAndResetTime" translate="false">
+float llGetAndResetTime()
+Returns the script time in seconds and then resets the script timer to zero
+ </string>
+ <string name="LSLTipText_llSoplayund" translate="false">
+llSound(string sound, float volume, integer queue, integer loop)
+Plays sound at volume and whether it should loop or not
+ </string>
+ <string name="LSLTipText_llPlaySound" translate="false">
+llPlaySound(string sound, float volume)
+Plays attached sound once at volume (0.0 - 1.0)
+ </string>
+ <string name="LSLTipText_llLoopSound" translate="false">
+llLoopSound(string sound, float volume)
+Plays attached sound looping indefinitely at volume (0.0 - 1.0)
+ </string>
+ <string name="LSLTipText_llLoopSoundMaster" translate="false">
+llLoopSoundMaster(string sound, float volume)
+Plays attached sound looping at volume (0.0 - 1.0), declares it a sync master
+ </string>
+ <string name="LSLTipText_llLoopSoundSlave" translate="false">
+llLoopSoundSlave(string sound, float volume)
+Plays attached sound looping at volume (0.0 - 1.0), synced to most audible sync master
+ </string>
+ <string name="LSLTipText_llPlaySoundSlave" translate="false">
+llPlaySoundSlave(string sound, float volume)
+Plays attached sound once at volume (0.0 - 1.0), synced to next loop of most audible sync master
+ </string>
+ <string name="LSLTipText_llTriggerSound" translate="false">
+llTriggerSound(string sound, float volume)
+Plays sound at volume (0.0 - 1.0), centered at but not attached to object
+ </string>
+ <string name="LSLTipText_llStopSound" translate="false">
+llStopSound()
+Stops currently attached sound
+ </string>
+ <string name="LSLTipText_llPreloadSound" translate="false">
+llPreloadSound(string sound)
+Preloads a sound on viewers within range
+ </string>
+ <string name="LSLTipText_llGetSubString" translate="false">
+string llGetSubString(string src, integer start, integer end)
+Returns the indicated substring
+ </string>
+ <string name="LSLTipText_llDeleteSubString" translate="false">
+string llDeleteSubString(string src, integer start, integer end)
+Removes the indicated substring and returns the result
+ </string>
+ <string name="LSLTipText_llInsertString" translate="false">
+string llInsertString(string dst, integer position, string src)
+Returns a destination string dst with the string src inserted starting at position pos
+ </string>
+ <string name="LSLTipText_llToUpper" translate="false">
+string llToUpper(string src)
+Returns a string that is src with all upper-case characters
+ </string>
+ <string name="LSLTipText_llToLower" translate="false">
+string llToLower(string src)
+Returns a string that is src with all lower-case characters
+ </string>
+ <string name="LSLTipText_llGiveMoney" translate="false">
+llGiveMoney(key destination, integer amount)
+Transfers amount of L$ from script owner to destination
+ </string>
+ <string name="LSLTipText_llMakeExplosion" translate="false">
+llMakeExplosion(integer particles, float scale, float vel, float lifetime, float arc, string texture, vector offset)
+Makes a round explosion of particles
+ </string>
+ <string name="LSLTipText_llMakeFountain" translate="false">
+llMakeFountain(integer particles, float scale, float vel, float lifetime, float arc, integer bounce, string texture, vector offset, float bounce_offset)
+Makes a fountain of particles
+ </string>
+ <string name="LSLTipText_llMakeSmoke" translate="false">
+llMakeSmoke(integer particles, float scale, float vel, float lifetime, float arc, string texture, vector offset)
+Makes smoke like particles
+ </string>
+ <string name="LSLTipText_llMakeFire" translate="false">
+llMakeFire(integer particles, float scale, float vel, float lifetime, float arc, string texture, vector offset)
+Makes fire like particles
+ </string>
+ <string name="LSLTipText_llRezObject" translate="false">
+llRezObject(string inventory, vector pos, vector vel, rotation rot, integer param)
+Instantiates owner&apos;s inventory object at pos with velocity vel and rotation rot with start parameter param
+ </string>
+ <string name="LSLTipText_llLookAt" translate="false">
+llLookAt(vector target, float strength, float damping)
+Causes object to point its up axis (positive z) towards target, while keeping its forward axis (positive x) below the horizon
+ </string>
+ <string name="LSLTipText_llStopLookAt" translate="false">
+llStopLookAt()
+Stops causing object to point at a target
+ </string>
+ <string name="LSLTipText_llSetTimerEvent" translate="false">
+llSetTimerEvent(float sec)
+Causes the timer event to be triggered a maximum of once every sec seconds
+ </string>
+ <string name="LSLTipText_llSleep" translate="false">
+llSleep(float sec)
+Puts the script to sleep for sec seconds
+ </string>
+ <string name="LSLTipText_llGetMass" translate="false">
+float llGetMass()
+Returns the mass of object that the script is attached to
+ </string>
+ <string name="LSLTipText_llCollisionFilter" translate="false">
+llCollisionFilter(string name, key id, integer accept)
+Sets the collision filter, exclusively or inclusively. If accept == TRUE, only accept collisions with objects name and id (either is optional), otherwise with objects not name or id
+ </string>
+ <string name="LSLTipText_llTakeControls" translate="false">
+llTakeControls(integer controls, integer accept, integer pass_on)
+Allows for intercepting keyboard and mouse clicks from the agent the script has permissions for
+ </string>
+ <string name="LSLTipText_llReleaseControls" translate="false">
+llReleaseControls()
+Stops taking inputs that were taken with llTakeControls
+ </string>
+ <string name="LSLTipText_llAttachToAvatar" translate="false">
+llAttachToAvatar(integer attach_point)
+Attaches the object to the avatar who has granted permission to the script
+ </string>
+ <string name="LSLTipText_llDetachFromAvatar" translate="false">
+llDetachFromAvatar()
+Detaches object from avatar
+ </string>
+ <string name="LSLTipText_llTakeCamera" translate="false">
+llTakeCamera(key avatar)
+Moves avatar&apos;s viewpoint to task
+ </string>
+ <string name="LSLTipText_llReleaseCamera" translate="false">
+llReleaseCamera(key avatar)
+Returns camera to agent avatar
+ </string>
+ <string name="LSLTipText_llGetOwner" translate="false">
+key llGetOwner()
+Returns the object owner&apos;s UUID
+ </string>
+ <string name="LSLTipText_llInstantMessage" translate="false">
+llInstantMessage(key user, string message)
+Sends the specified string as an Instant Message to the user
+ </string>
+ <string name="LSLTipText_llEmail" translate="false">
+llEmail(string address, string subject, string message)
+Sends an email to address with the subject and message
+ </string>
+ <string name="LSLTipText_llGetNextEmail" translate="false">
+llGetNextEmail(string address, string subject)
+Gets the next waiting email that comes from address, with specified subject
+ </string>
+ <string name="LSLTipText_llGetKey" translate="false">
+key llGetKey()
+Returns the key of the prim the script is attached to
+ </string>
+ <string name="LSLTipText_llSetBuoyancy" translate="false">
+llSetBuoyancy(float buoyancy)
+Sets the buoyancy of the task or object (0 is disabled, &lt; 1.0 sinks, 1.0 floats, &gt; 1.0 rises)
+ </string>
+ <string name="LSLTipText_llSetHoverHeight" translate="false">
+llSetHoverHeight(float height, integer water, float tau)
+Critically damps to a height above the ground (or water) in tau seconds
+ </string>
+ <string name="LSLTipText_llStopHover" translate="false">
+llStopHover()
+Stops hovering to a height
+ </string>
+ <string name="LSLTipText_llMinEventDelay" translate="false">
+llMinEventDelay(float delay)
+Sets the minimum time between events being handled
+ </string>
+ <string name="LSLTipText_llSoundPreload" translate="false">
+llSoundPreload(string sound)
+Preloads a sound on viewers within range
+ </string>
+ <string name="LSLTipText_llRotLookAt" translate="false">
+llRotLookAt(rotation target, float strength, float damping)
+Causes object to point its forward axis towards target
+ </string>
+ <string name="LSLTipText_llStringLength" translate="false">
+integer llStringLength(string str)
+Returns the length of string
+ </string>
+ <string name="LSLTipText_llStartAnimation" translate="false">
+llStartAnimation(string anim)
+Starts animation anim for agent that granted PERMISSION_TRIGGER_ANIMATION if the permission has not been revoked
+ </string>
+ <string name="LSLTipText_llStopAnimation" translate="false">
+llStopAnimation(string anim)
+Stops animation anim for agent that granted permission
+ </string>
+ <string name="LSLTipText_llPointAt" translate="false">
+llPointAt(vector pos)
+Makes agent that owns object point at pos
+ </string>
+ <string name="LSLTipText_llStopPointAt" translate="false">
+llStopPointAt()
+Stops pointing agent that owns object
+ </string>
+ <string name="LSLTipText_llTargetOmega" translate="false">
+llTargetOmega(vector axis, float spinrate, float gain)
+Rotates the object around axis at spinrate with strength gain
+ </string>
+ <string name="LSLTipText_llGetStartParameter" translate="false">
+integer llGetStartParameter()
+Returns an integer that is the script start/rez parameter
+ </string>
+ <string name="LSLTipText_llGodLikeRezObject" translate="false">
+llGodLikeRezObject(key inventory, vector pos)
+Rezzes directly off of UUID if owner is in God Mode
+ </string>
+ <string name="LSLTipText_llRequestPermissions" translate="false">
+llRequestPermissions(key agent, integer perm)
+Asks the agent for permission to run certain classes of functions
+ </string>
+ <string name="LSLTipText_llGetPermissionsKey" translate="false">
+key llGetPermissionsKey()
+Returns the key of the avatar that last granted permissions to the script
+ </string>
+ <string name="LSLTipText_llGetPermissions" translate="false">
+integer llGetPermissions()
+Returns an integer bitfield with the permissions that have been granted
+ </string>
+ <string name="LSLTipText_llGetLinkNumber" translate="false">
+integer llGetLinkNumber()
+Returns the link number of the prim containing the script (0 means not linked, 1 the prim is the root, 2 the prim is the first child, etc)
+ </string>
+ <string name="LSLTipText_llSetLinkColor" translate="false">
+llSetLinkColor(integer linknumber, vector color, integer face)
+Sets face to color if a task exists in the link chain at linknumber
+ </string>
+ <string name="LSLTipText_llCreateLink" translate="false">
+llCreateLink(key target, integer parent)
+Attempts to link the script&apos;s object with the target (requires that PERMISSION_CHANGE_LINKS be granted). If parent == TRUE, then the script&apos;s object becomes the root
+ </string>
+ <string name="LSLTipText_llBreakLink" translate="false">
+llBreakLink(integer linknum)
+Delinks the prim with the given link number in a linked object set (requires that PERMISSION_CHANGE_LINKS be granted)
+ </string>
+ <string name="LSLTipText_llBreakAllLinks" translate="false">
+llBreakAllLinks()
+Delinks all prims in the link set (requires that PERMISSION_CHANGE_LINKS be granted)
+ </string>
+ <string name="LSLTipText_llGetLinkKey" translate="false">
+key llGetLinkKey(integer linknumber)
+Returns the key of the linked prim linknumber
+ </string>
+ <string name="LSLTipText_llGetLinkName" translate="false">
+string llGetLinkName(integer linknumber)
+Returns the name of linknumber in a link set
+ </string>
+ <string name="LSLTipText_llGetInventoryNumber" translate="false">
+integer llGetInventoryNumber(integer type)
+Returns the number of items of a given type (INVENTORY_* flag) in the prim&apos;s inventory
+ </string>
+ <string name="LSLTipText_llGetInventoryName" translate="false">
+string llGetInventoryName(integer type, integer number)
+Returns the name of the inventory item number of a given type
+ </string>
+ <string name="LSLTipText_llSetScriptState" translate="false">
+llSetScriptState(string name, integer run)
+Sets the running state of the specified script
+ </string>
+ <string name="LSLTipText_llGetEnergy" translate="false">
+float llGetEnergy()
+Returns how much energy is in the object as a percentage of maximum
+ </string>
+ <string name="LSLTipText_llGiveInventory" translate="false">
+llGiveInventory(key destination, string inventory)
+Gives inventory to destination
+ </string>
+ <string name="LSLTipText_llRemoveInventory" translate="false">
+llRemoveInventory(string item)
+Removes the named inventory item
+ </string>
+ <string name="LSLTipText_llSetText" translate="false">
+llSetText(string text, vector color, float alpha)
+Displays text that hovers over the prim with specific color and translucency specified with alpha
+ </string>
+ <string name="LSLTipText_llWater" translate="false">
+float llWater(vector offset)
+Returns the water height below the object position + offset
+ </string>
+ <string name="LSLTipText_llPassTouches" translate="false">
+llPassTouches(integer pass)
+If pass == TRUE, touches are passed from children on to parents
+ </string>
+ <string name="LSLTipText_llRequestAgentData" translate="false">
+key llRequestAgentData(key id, integer data)
+Requests data about agent id. When data is available the dataserver event will be raised.
+ </string>
+ <string name="LSLTipText_llRequestInventoryData" translate="false">
+key llRequestInventoryData(string name)
+Requests data from object&apos;s inventory object. When data is available the dataserver event will be raised.
+ </string>
+ <string name="LSLTipText_llSetDamage" translate="false">
+llSetDamage(float damage)
+Sets the amount of damage that will be done when this object hits an avatar.
+ </string>
+ <string name="LSLTipText_llTeleportAgentHome" translate="false">
+llTeleportAgentHome(key id)
+Teleports avatar on the owner&apos;s land to their home location without any warning
+ </string>
+ <string name="LSLTipText_llModifyLand" translate="false">
+llModifyLand(integer action, integer brush)
+Modifies land using the specified action on the specified brush size of land
+ </string>
+ <string name="LSLTipText_llCollisionSound" translate="false">
+llCollisionSound(string impact_sound, float impact_volume)
+Suppresses default collision sounds, replaces default impact sounds with impact_sound at the volume impact_volume
+ </string>
+ <string name="LSLTipText_llCollisionSprite" translate="false">
+llCollisionSprite(string impact_sprite)
+Suppresses default collision sprites, replaces default impact sprite with impact_sprite (use an empty string to just suppress)
+ </string>
+ <string name="LSLTipText_llGetAnimation" translate="false">
+string llGetAnimation(key id)
+Returns the name of the currently playing locomotion animation for avatar id
+ </string>
+ <string name="LSLTipText_llResetScript" translate="false">
+llResetScript()
+Resets the script
+ </string>
+ <string name="LSLTipText_llMessageLinked" translate="false">
+llMessageLinked(integer linknum, integer num, string str, key id)
+Allows scripts in the same object to communicate. Triggers a link_message event with the same parameters num, str, and id in all scripts in the prim(s) described by linknum.
+ </string>
+ <string name="LSLTipText_llPushObject" translate="false">
+llPushObject(key id, vector impulse, vector ang_impulse, integer local)
+Applies impulse and ang_impulse to object id
+ </string>
+ <string name="LSLTipText_llPassCollisions" translate="false">
+llPassCollisions(integer pass)
+If pass == TRUE, collisions are passed from children on to parents (default is FALSE)
+ </string>
+ <string name="LSLTipText_llGetScriptName" translate="false">
+string llGetScriptName()
+Returns the name of the script that this function is used in
+ </string>
+ <string name="LSLTipText_llGetNumberOfSides" translate="false">
+integer llGetNumberOfSides()
+Returns the number of faces (or sides) of the prim
+ </string>
+ <string name="LSLTipText_llAxisAngle2Rot" translate="false">
+rotation llAxisAngle2Rot(vector axis, float angle)
+Returns the rotation that is a generated angle about axis
+ </string>
+ <string name="LSLTipText_llRot2Axis" translate="false">
+vector llRot2Axis(rotation rot)
+Returns the rotation axis represented by rot
+ </string>
+ <string name="LSLTipText_llRot2Angle" translate="false">
+float llRot2Angle(rotation rot)
+Returns the rotation angle represented by rot
+ </string>
+ <string name="LSLTipText_llAcos" translate="false">
+float llAcos(float val)
+Returns the arccosine in radians of val
+ </string>
+ <string name="LSLTipText_llAsin" translate="false">
+float llAsin(float val)
+Returns the arcsine in radians of val
+ </string>
+ <string name="LSLTipText_llAngleBetween" translate="false">
+float llAngleBetween(rotation a, rotation b)
+Returns angle between rotation a and b
+ </string>
+ <string name="LSLTipText_llGetInventoryKey" translate="false">
+key llGetInventoryKey(string name)
+Returns the key that is the UUID of the inventory name
+ </string>
+ <string name="LSLTipText_llAllowInventoryDrop" translate="false">
+llAllowInventoryDrop(integer add)
+If add == TRUE, users without modify permissions can still drop inventory items onto a prim
+ </string>
+ <string name="LSLTipText_llGetSunDirection" translate="false">
+vector llGetSunDirection()
+Returns a normalized vector of the direction of the sun in the region
+ </string>
+ <string name="LSLTipText_llGetTextureOffset" translate="false">
+vector llGetTextureOffset(integer face)
+Returns the texture offset of face in the x and y components of a vector
+ </string>
+ <string name="LSLTipText_llGetTextureScale" translate="false">
+vector llGetTextureScale(integer side)
+Returns the texture scale of side in the x and y components of a vector
+ </string>
+ <string name="LSLTipText_llGetTextureRot" translate="false">
+float llGetTextureRot(integer side)
+Returns the texture rotation of side
+ </string>
+ <string name="LSLTipText_llSubStringIndex" translate="false">
+integer llSubStringIndex(string source, string pattern)
+Returns an integer that is the index in source where pattern first appears.
+(Returns -1 if not found)
+ </string>
+ <string name="LSLTipText_llGetOwnerKey" translate="false">
+key llGetOwnerKey(key id)
+Returns the owner of object id
+ </string>
+ <string name="LSLTipText_llGetCenterOfMass" translate="false">
+vector llGetCenterOfMass()
+Returns the prim&apos;s center of mass (unless called from the root prim, where it returns the object&apos;s center of mass)
+ </string>
+ <string name="LSLTipText_llListSort" translate="false">
+list llListSort(list src, integer stride, integer ascending)
+Sorts the list into blocks of stride, in ascending order if ascending == TRUE.
+The sort order is affected by type.
+ </string>
+ <string name="LSLTipText_llGetListLength" translate="false">
+integer llGetListLength(list src)
+Returns the number of elements in the list
+ </string>
+ <string name="LSLTipText_llList2Integer" translate="false">
+integer llList2Integer(list src, integer index)
+Copies the integer at index in the list
+ </string>
+ <string name="LSLTipText_llList2Float" translate="false">
+float llList2Float(list src, integer index)
+Copies the float at index in the list
+ </string>
+ <string name="LSLTipText_llList2String" translate="false">
+string llList2String(list src, integer index)
+Copies the string at index in the list
+ </string>
+ <string name="LSLTipText_llList2Key" translate="false">
+key llList2Key(list src, integer index)
+Copies the key at index in the list
+ </string>
+ <string name="LSLTipText_llList2Vector" translate="false">
+vector llList2Vector(list src, integer index)
+Copies the vector at index in the list
+ </string>
+ <string name="LSLTipText_llList2Rot" translate="false">
+rotation llList2Rot(list src, integer index)
+Copies the rotation at index in the list
+ </string>
+ <string name="LSLTipText_llList2List" translate="false">
+list llList2List(list src, integer start, integer end)
+Copies the slice of the list from start to end
+ </string>
+ <string name="LSLTipText_llDeleteSubList" translate="false">
+list llDeleteSubList(list src, integer start, integer end)
+Removes the slice from start to end and returns the remainder of the list
+ </string>
+ <string name="LSLTipText_llGetListEntryType" translate="false">
+integer llGetListEntryType(list src, integer index)
+Returns the type of the index entry in the list
+(TYPE_INTEGER, TYPE_FLOAT, TYPE_STRING, TYPE_KEY, TYPE_VECTOR, TYPE_ROTATION, or TYPE_INVALID if index is off list)
+ </string>
+ <string name="LSLTipText_llList2CSV" translate="false">
+string llList2CSV(list src)
+Creates a string of comma separated values from list
+ </string>
+ <string name="LSLTipText_llCSV2List" translate="false">
+list llCSV2List(string src)
+Creates a list from a string of comma separated values
+ </string>
+ <string name="LSLTipText_llListRandomize" translate="false">
+list llListRandomize(list src, integer stride)
+Returns a randomized list of blocks of size stride
+ </string>
+ <string name="LSLTipText_llList2ListStrided" translate="false">
+list llList2ListStrided(list src, integer start, integer end, integer stride)
+Copies the strided slice of the list from start to end
+ </string>
+ <string name="LSLTipText_llGetRegionCorner" translate="false">
+vector llGetRegionCorner()
+Returns a vector in meters that is the global location of the south-west corner of the region which the object is in
+ </string>
+ <string name="LSLTipText_llListInsertList" translate="false">
+list llListInsertList(list dest, list src, integer start)
+Returns a list that contains all the elements from dest but with the elements from src inserted at position start
+ </string>
+ <string name="LSLTipText_llListFindList" translate="false">
+integer llListFindList(list src, list test)
+Returns the index of the first instance of test in src.
+(Returns -1 if not found)
+ </string>
+ <string name="LSLTipText_llGetObjectName" translate="false">
+string llGetObjectName()
+Returns the name of the prim which the script is attached to
+ </string>
+ <string name="LSLTipText_llSetObjectName" translate="false">
+llSetObjectName(string name)
+Sets the prim&apos;s name to the name parameter
+ </string>
+ <string name="LSLTipText_llGetDate" translate="false">
+string llGetDate()
+Returns the current date in the UTC time zone in the format YYYY-MM-DD
+ </string>
+ <string name="LSLTipText_llEdgeOfWorld" translate="false">
+integer llEdgeOfWorld(vector pos, vector dir)
+Checks to see whether the border hit by dir from pos is the edge of the world (has no neighboring region)
+ </string>
+ <string name="LSLTipText_llGetAgentInfo" translate="false">
+integer llGetAgentInfo(key id)
+Returns an integer bitfield containing the agent information about id.
+Returns AGENT_FLYING, AGENT_ATTACHMENTS, AGENT_SCRIPTED, AGENT_SITTING, AGENT_ON_OBJECT, AGENT_MOUSELOOK, AGENT_AWAY, AGENT_BUSY, AGENT_TYPING, AGENT_CROUCHING, AGENT_ALWAYS_RUN, AGENT_WALKING and/or AGENT_IN_AIR.
+ </string>
+ <string name="LSLTipText_llAdjustSoundVolume" translate="false">
+llAdjustSoundVolume(float volume)
+Adjusts volume of attached sound (0.0 - 1.0)
+ </string>
+ <string name="LSLTipText_llSetSoundQueueing" translate="false">
+llSetSoundQueueing(integer queue)
+Sets whether attached sounds wait for the current sound to finish (If queue == TRUE then queuing is enabled, if FALSE queuing is disabled [default])
+ </string>
+ <string name="LSLTipText_llSetSoundRadius" translate="false">
+llSetSoundRadius(float radius)
+Establishes a hard cut-off radius for audibility of scripted sounds (both attached and triggered)
+ </string>
+ <string name="LSLTipText_llKey2Name" translate="false">
+string llKey2Name(key id)
+Returns the name of the prim or avatar specified by id.
+(The id must be a valid rezzed prim or avatar key in the current simulator, otherwise an empty string is returned.)
+ </string>
+ <string name="LSLTipText_llSetTextureAnim" translate="false">
+llSetTextureAnim(integer mode, integer face, integer sizex, integer sizey, float start, float length, float rate)
+Animates the texture on the specified face/faces
+ </string>
+ <string name="LSLTipText_llTriggerSoundLimited" translate="false">
+llTriggerSoundLimited(string sound, float volume, vector top_north_east, vector bottom_south_west)
+Plays sound at volume (0.0 - 1.0), centered at but not attached to object, limited to the box defined by vectors top_north_east and bottom_south_west
+ </string>
+ <string name="LSLTipText_llEjectFromLand" translate="false">
+llEjectFromLand(key avatar)
+Ejects avatar from the parcel
+ </string>
+ <string name="LSLTipText_llParseString2List" translate="false">
+list llParseString2List(string src, list separators, list spacers)
+Breaks src into a list, discarding separators, keeping spacers
+(separators and spacers must be lists of strings, maximum of 8 each)
+ </string>
+ <string name="LSLTipText_llOverMyLand" translate="false">
+integer llOverMyLand(key id)
+Returns TRUE if id is over land owned by the script owner, otherwise FALSE
+ </string>
+ <string name="LSLTipText_llGetLandOwnerAt" translate="false">
+key llGetLandOwnerAt(vector pos)
+Returns the key of the land owner, returns NULL_KEY if public
+ </string>
+ <string name="LSLTipText_llGetNotecardLine" translate="false">
+key llGetNotecardLine(string name, integer line)
+Returns line line of notecard name via the dataserver event
+ </string>
+ <string name="LSLTipText_llGetAgentSize" translate="false">
+vector llGetAgentSize(key id)
+If the avatar is in the same region, returns the size of the bounding box of the requested avatar by id, otherwise returns ZERO_VECTOR
+ </string>
+ <string name="LSLTipText_llSameGroup" translate="false">
+integer llSameGroup(key id)
+Returns TRUE if avatar id is in the same region and has the same active group, otherwise FALSE
+ </string>
+ <string name="LSLTipText_llUnSit" translate="false">
+key llUnSit(key id)
+If avatar identified by id is sitting on the object the script is attached to or is over land owned by the object&apos;s owner, the avatar is forced to stand up
+ </string>
+ <string name="LSLTipText_llGroundSlope" translate="false">
+vector llGroundSlope(vector offset)
+Returns the ground slope below the object position + offset
+ </string>
+ <string name="LSLTipText_llGroundNormal" translate="false">
+vector llGroundNormal(vector offset)
+Returns the ground normal below the object position + offset
+ </string>
+ <string name="LSLTipText_llGroundContour" translate="false">
+vector llGroundCountour(vector offset)
+Returns the ground contour direction below the object position + offset
+ </string>
+ <string name="LSLTipText_llGetAttached" translate="false">
+integer llGetAttached()
+Returns the object&apos;s attachment point, or 0 if not attached
+ </string>
+ <string name="LSLTipText_llGetFreeMemory" translate="false">
+integer llGetFreeMemory()
+Returns the number of free bytes of memory the script can use
+ </string>
+ <string name="LSLTipText_llGetRegionName" translate="false">
+string llGetRegionName()
+Returns the current region name
+ </string>
+ <string name="LSLTipText_llGetRegionTimeDilation" translate="false">
+float llGetRegionTimeDilation()
+Returns the current time dilation as a float between 0.0 (full dilation) and 1.0 (no dilation)
+ </string>
+ <string name="LSLTipText_llGetRegionFPS" translate="false">
+float llGetRegionFPS()
+Returns the mean region frames per second
+ </string>
+ <string name="LSLTipText_llParticleSystem" translate="false">
+llParticleSystem(list rules)
+Creates a particle system based on rules. An empty list removes the particle system.
+List format is [ rule1, data1, rule2, data2 . . . rulen, datan ]
+ </string>
+ <string name="LSLTipText_llGroundRepel" translate="false">
+llGroundRepel(float height, integer water, float tau)
+Critically damps to height if within height*0.5 of level (either above ground level, or above the higher of land and water if water == TRUE)
+ </string>
+ <string name="LSLTipText_llGiveInventoryList" translate="false">
+llGiveInventoryList(key target, string folder, list inventory)
+Gives inventory items to target, creating a new folder to put them in
+ </string>
+ <string name="LSLTipText_llSetVehicleType" translate="false">
+llSetVehicleType(integer type)
+Sets the vehicle to one of the default types
+ </string>
+ <string name="LSLTipText_llSetVehicleFloatParam" translate="false">
+llSetVehicleFloatParam(integer param, float value)
+Sets the specified vehicle float parameter
+ </string>
+ <string name="LSLTipText_llSetVehicleVectorParam" translate="false">
+llSetVehicleVectorParam(integer param, vector vec)
+Sets the specified vehicle vector parameter
+ </string>
+ <string name="LSLTipText_llSetVehicleRotationParam" translate="false">
+llSetVehicleVectorParam(integer param, rotation rot)
+Sets the specified vehicle rotation parameter
+ </string>
+ <string name="LSLTipText_llSetVehicleFlags" translate="false">
+llSetVehicleFlags(integer flags)
+Sets the enabled bits in &apos;flags&apos;
+ </string>
+ <string name="LSLTipText_llRemoveVehicleFlags" translate="false">
+llRemoveVehicleFlags(integer flags)
+Removes the enabled bits in &apos;flags&apos;
+ </string>
+ <string name="LSLTipText_llSitTarget" translate="false">
+llSitTarget(vector offset, rotation rot)
+Sets the sit location for the prim. If offset == &lt;0,0,0&gt; then the sit target is removed.
+ </string>
+ <string name="LSLTipText_llAvatarOnSitTarget" translate="false">
+key llAvatarOnSitTarget()
+If an avatar is seated on the sit target, returns the avatar&apos;s key, otherwise NULL_KEY
+ </string>
+ <string name="LSLTipText_llAddToLandPassList" translate="false">
+llAddToLandPassList(key avatar, float hours)
+Adds avatar to the land pass list for hours, or indefinitely if hours is 0
+ </string>
+ <string name="LSLTipText_llSetTouchText" translate="false">
+llSetTouchText(string text)
+Displays text rather than the default &apos;Touch&apos; in the pie menu
+ </string>
+ <string name="LSLTipText_llSetSitText" translate="false">
+llSetSitText(string text)
+Displays text rather than the default &apos;Sit Here&apos; in the pie menu
+ </string>
+ <string name="LSLTipText_llSetCameraEyeOffset" translate="false">
+llSetCameraEyeOffset(vector offset)
+Sets the camera eye offset for avatars that sit on the object
+ </string>
+ <string name="LSLTipText_llSetCameraAtOffset" translate="false">
+llSetCameraAtOffset(vector offset)
+Sets the point the camera is looking at to offset for avatars that sit on the object
+ </string>
+ <string name="LSLTipText_llDumpList2String" translate="false">
+string llDumpList2String(list src, string separator)
+Returns the list in a single string, using separator between the entries
+ </string>
+ <string name="LSLTipText_llScriptDanger" translate="false">
+integer llScriptDanger(vector pos)
+Returns TRUE if pos is over public land, sandbox land, land that doesn&apos;t allow everyone to edit and build, or land that doesn&apos;t allow outside scripts
+ </string>
+ <string name="LSLTipText_llDialog" translate="false">
+llDialog(key avatar, string message, list buttons, integer chat_channel
+Shows a dialog box on the avatar&apos;s screen with a message and up to 12 buttons.
+If a button is pressed, the avatar says the text of the button label on chat_channel.
+ </string>
+ <string name="LSLTipText_llVolumeDetect" translate="false">
+llVolumeDetect(integer detect)
+If detect = TRUE, object works much like Phantom, but triggers collision_start and collision_end events when other objects start and stop interpenetrating.
+Must be applied to the root prim.
+ </string>
+ <string name="LSLTipText_llResetOtherScript" translate="false">
+llResetOtherScript(string name)
+Resets script name
+ </string>
+ <string name="LSLTipText_llGetScriptState" translate="false">
+integer llGetScriptState(string name)
+Returns TRUE if the script name is running
+ </string>
+ <string name="LSLTipText_llRemoteLoadScript" translate="false">
+DEPRECATED! Please use llRemoteLoadScriptPin instead.
+ </string>
+ <string name="LSLTipText_llSetRemoteScriptAccessPin" translate="false">
+llSetRemoteScriptAccessPin(integer pin)
+If pin is set to a non-zero number, allows a prim to have scripts remotely loaded via llRemoteLoadScriptPin when it passes in the correct pin. Otherwise, llRemoteLoadScriptPin is ignored.
+ </string>
+ <string name="LSLTipText_llRemoteLoadScriptPin" translate="false">
+llRemoteLoadScriptPin(key target, string name, integer pin, integer running, integer start_param)
+Copies script name onto target, if the owner of this scripted object can modify target and is in the same region, and the matching pin is used.
+If running == TRUE, starts the script with start_param
+ </string>
+ <string name="LSLTipText_llOpenRemoteDataChannel" translate="false">
+llOpenRemoteDataChannel()
+Creates a channel to listen for XML-RPC calls, and will trigger a remote_data event with channel id once it is available
+ </string>
+ <string name="LSLTipText_llSendRemoteData" translate="false">
+key llSendRemoteData(key channel, string dest, integer idata, string sdata)
+Sends an XML-RPC request to dest through channel with payload of channel (in a string), integer idata and string sdata.
+Returns a key that is the message_id for the resulting remote_data events.
+ </string>
+ <string name="LSLTipText_llRemoteDataReply" translate="false">
+llRemoteDataReply(key channel, key message_id, string sdata, integer idata)
+Sends an XML-RPC reply to message_id on channel with payload of string sdata and integer idata
+ </string>
+ <string name="LSLTipText_llCloseRemoteDataChannel" translate="false">
+llCloseRemoteDataChannel(key channel)
+Closes XML-RPC channel
+ </string>
+ <string name="LSLTipText_llMD5String" translate="false">
+string llMD5String(string src, integer nonce)
+Returns a string of 32 hex characters that is a RSA Data Security, Inc. MD5 Message-Digest Algorithm of src with nonce
+ </string>
+ <string name="LSLTipText_llSetPrimitiveParams" translate="false">
+llSetPrimitiveParams(list rules)
+Sets the prim&apos;s parameters according to rules
+ </string>
+ <string name="LSLTipText_llStringToBase64" translate="false">
+string llStringToBase64(string str)
+Converts a string to the Base64 representation of the string
+ </string>
+ <string name="LSLTipText_llBase64ToString" translate="false">
+string llBase64ToString(string str)
+Converts a Base64 string to a conventional string.
+If the conversion creates any unprintable characters, they are converted to spaces.
+ </string>
+ <string name="LSLTipText_llXorBase64Strings" translate="false">
+string llXorBase64Strings(string s1, string s2)
+DEPRECATED! Please use llXorBase64StringsCorrect instead.
+Incorrectly performs an exclusive or on two Base64 strings and returns a Base64 string. s2 repeats if it is shorter than s1. Retained for backwards compatability.
+ </string>
+ <string name="LSLTipText_llRemoteDataSetRegion" translate="false">
+llRemoteDataSetRegion()
+DEPRECATED! Please use llOpenRemoteDataChannel instead.
+If an object using remote data channels changes regions, you must call this function to reregister the remote data channels. This call is not needed if the prim does not change regions.
+ </string>
+ <string name="LSLTipText_llLog10" translate="false">
+float llLog10(float val)
+Returns the base 10 logarithm of val. Returns zero if val &lt;= 0.
+ </string>
+ <string name="LSLTipText_llLog" translate="false">
+float llLog(float val)
+Returns the natural logarithm of val. Returns zero if val &lt;= 0.
+ </string>
+ <string name="LSLTipText_llGetAnimationList" translate="false">
+list llGetAnimationList(key id)
+Returns a list of keys of playing animations for avatar described by id
+ </string>
+ <string name="LSLTipText_llSetParcelMusicURL" translate="false">
+llSetParcelMusicURL(string url)
+Sets the streaming audio URL for the parcel which the object is on
+ </string>
+ <string name="LSLTipText_llGetRootPosition" translate="false">
+vector llGetRootPosition()
+Returns the position (in region coordinates) of the root prim of the object which the script is attached to
+ </string>
+ <string name="LSLTipText_llGetRootRotation" translate="false">
+rotation llGetRootRotation()
+Returns the rotation (relative to the region) of the root prim of the object which the script is attached to
+ </string>
+ <string name="LSLTipText_llGetObjectDesc" translate="false">
+string llGetObjectDesc()
+Returns the description of the prim the script is attached to
+ </string>
+ <string name="LSLTipText_llSetObjectDesc" translate="false">
+llSetObjectDesc(string name)
+Sets the prim&apos;s description
+ </string>
+ <string name="LSLTipText_llGetCreator" translate="false">
+key llGetCreator()
+Returns a key for the creator of the prim
+ </string>
+ <string name="LSLTipText_llGetTimestamp" translate="false">
+string llGetTimestamp()
+Returns the timestamp in the UTC time zone in the format: YYYY-MM-DDThh:mm:ss.ff..fZ
+ </string>
+ <string name="LSLTipText_llSetLinkAlpha" translate="false">
+llSetLinkAlpha(integer linknumber, float alpha, integer face)
+If a prim exists in the link chain at linknumber, sets face to alpha
+ </string>
+ <string name="LSLTipText_llGetNumberOfPrims" translate="false">
+integer llGetNumberOfPrims()
+Returns the number of prims in a link set the script is attached to
+ </string>
+ <string name="LSLTipText_llGetNumberOfNotecardLines" translate="false">
+key llGetNumberOfNotecardLines(string name)
+Returns number of lines in notecard name via the dataserver event (cast return value to integer)
+ </string>
+ <string name="LSLTipText_llGetBoundingBox" translate="false">
+list llGetBoundingBox(key object)
+Returns the bounding box around the object (including any linked prims) relative to its root prim, in a list in the format [ (vector) min_corner, (vector) max_corner ]
+ </string>
+ <string name="LSLTipText_llGetGeometricCenter" translate="false">
+vector llGetGeometricCenter()
+Returns the geometric center of the linked set the script is attached to.
+ </string>
+ <string name="LSLTipText_llGetPrimitiveParams" translate="false">
+list llGetPrimitiveParams(list params)
+Returns the primitive parameters specified in the params list.
+ </string>
+ <string name="LSLTipText_llIntegerToBase64" translate="false">
+string llIntegerToBase64(integer number)
+Returns a string that is a Base64 big endian encode of number
+ </string>
+ <string name="LSLTipText_llBase64ToInteger" translate="false">
+integer llBase64ToInteger(string str)
+Returns an integer that is the str Base64 decoded as a big endian integer
+ </string>
+ <string name="LSLTipText_llGetGMTclock" translate="false">
+float llGetGMTclock()
+Returns the time in seconds since midnight GMT
+ </string>
+ <string name="LSLTipText_llGetSimulatorHostname" translate="false">
+string llGetSimulatorHostname()
+Returns the hostname of the machine which the script is running on (same as string in viewer Help dialog)
+ </string>
+ <string name="LSLTipText_llSetLocalRot" translate="false">
+llSetLocalRot(rotation rot)
+Sets the rotation of a child prim relative to the root prim
+ </string>
+ <string name="LSLTipText_llParseStringKeepNulls" translate="false">
+list llParseStringKeepNulls(string src, list separators, list spacers)
+Breaks src into a list, discarding separators, keeping spacers, keeping any null values generated.
+(separators and spacers must be lists of strings, maximum of 8 each)
+ </string>
+ <string name="LSLTipText_llRezAtRoot" translate="false">
+llRezAtRoot(string inventory, vector pos, vector vel, rotation rot, integer param)
+Instantiates owner&apos;s inventory object rotated to rot with its root at pos, moving at vel, using param as the start parameter
+ </string>
+ <string name="LSLTipText_llGetObjectPermMask" translate="false">
+integer llGetObjectPermMask(integer mask)
+Returns the requested permission mask for the root object the task is attached to
+ </string>
+ <string name="LSLTipText_llSetObjectPermMask" translate="false">
+llSetObjectPermMask(integer mask, integer value)
+Sets the given permission mask to the new value on the root object the task is attached to (requires God Mode)
+ </string>
+ <string name="LSLTipText_llGetInventoryPermMask" translate="false">
+integer llGetInventoryPermMask(string item, integer mask)
+Returns the requested permission mask for the inventory item
+ </string>
+ <string name="LSLTipText_llSetInventoryPermMask" translate="false">
+llSetInventoryPermMask(string item, integer mask, integer value)
+Sets the given permission mask to the new value on the inventory item (requires God Mode)
+ </string>
+ <string name="LSLTipText_llGetInventoryCreator" translate="false">
+key llGetInventoryCreator(string item)
+Returns a key for the creator of the inventory item
+ </string>
+ <string name="LSLTipText_llOwnerSay" translate="false">
+llOwnerSay(string msg)
+Says msg to owner only. (Owner must be in the same region.)
+ </string>
+ <string name="LSLTipText_llRequestSimulatorData" translate="false">
+key llRequestSimulatorData(string simulator, integer data)
+Requests data about simulator. When data is available the dataserver event will be raised.
+ </string>
+ <string name="LSLTipText_llForceMouselook" translate="false">
+llForceMouselook(integer mouselook)
+If mouselook is TRUE, any avatar that sits upon the prim will be forced into mouselook mode
+ </string>
+ <string name="LSLTipText_llGetObjectMass" translate="false">
+float llGetObjectMass(key id)
+Returns the mass of the avatar or object in the region
+ </string>
+ <string name="LSLTipText_llListReplaceList" translate="false">
+list llListReplaceList(list dest, list src, integer start, integer end)
+Returns a list that is dest with start through end removed and src inserted at start
+ </string>
+ <string name="LSLTipText_llLoadURL" translate="false">
+llLoadURL(key avatar, string message, string url)
+Shows a dialog to avatar offering to load the web page at url with a message.
+If user clicks yes, launches the page in their web browser.
+ </string>
+ <string name="LSLTipText_llParcelMediaCommandList" translate="false">
+llParcelMediaCommandList(list command)
+Sends a list of commands, some with arguments, to a parcel to control the playback of movies and other media
+ </string>
+ <string name="LSLTipText_llParcelMediaQuery" translate="false">
+list llParcelMediaQuery(list query)
+Returns a list containing results of the sent query
+ </string>
+ <string name="LSLTipText_llModPow" translate="false">
+integer llModPow(integer a, integer b, integer c)
+Returns a raised to the b power, mod c. ( (a**b)%c )
+b is capped at 0xFFFF (16 bits).
+ </string>
+ <string name="LSLTipText_llGetInventoryType" translate="false">
+integer llGetInventoryType(string name)
+Returns the type of the inventory item name
+ </string>
+ <string name="LSLTipText_llSetPayPrice" translate="false">
+llSetPayPrice(integer price, list quick_pay_buttons)
+Sets the default amount on the dialog that appears when someone chooses to pay this prim
+ </string>
+ <string name="LSLTipText_llGetCameraPos" translate="false">
+vector llGetCameraPos()
+Returns the current camera position for the agent the task has permissions for
+ </string>
+ <string name="LSLTipText_llGetCameraRot" translate="false">
+rotation llGetCameraRot()
+Returns the current camera orientation for the agent the task has permissions for
+ </string>
+ <string name="LSLTipText_llSetPrimURL" translate="false">
+llSetPrimURL(string url)
+Updates the URL for the web page shown on the sides of the object
+ </string>
+ <string name="LSLTipText_llRefreshPrimURL" translate="false">
+llRefreshPrimURL()
+Reloads the web page shown on the sides of the object
+ </string>
+ <string name="LSLTipText_llEscapeURL" translate="false">
+string llEscapeURL(string url)
+Returns an escaped/encoded version of url, replacing spaces with %20 etc.
+ </string>
+ <string name="LSLTipText_llUnescapeURL" translate="false">
+string llUnescapeURL(string url)
+Returns an unescaped/ unencoded version of url, replacing %20 with spaces etc.
+ </string>
+ <string name="LSLTipText_llMapDestination" translate="false">
+llMapDestination(string simname, vector pos, vector look_at)
+Opens the World Map centered on the region simname with pos highlighted. (NOTE: look_at currently does nothing.)
+Only works for scripts attached to avatar, or during touch events.
+ </string>
+ <string name="LSLTipText_llAddToLandBanList" translate="false">
+llAddToLandBanList(key avatar, float hours)
+Adds avatar to the land ban list for hours, or indefinitely if hours is 0
+ </string>
+ <string name="LSLTipText_llRemoveFromLandPassList" translate="false">
+llRemoveFromLandPassList(key avatar)
+Removes avatar from the land pass list
+ </string>
+ <string name="LSLTipText_llRemoveFromLandBanList" translate="false">
+llRemoveFromLandBanList(key avatar)
+Removes avatar from the land ban list
+ </string>
+ <string name="LSLTipText_llSetCameraParams" translate="false">
+llSetCameraParams(list rules)
+Sets multiple camera parameters at once.
+List format is [ rule1, data1, rule2, data2 . . . rulen, datan ]
+ </string>
+ <string name="LSLTipText_llClearCameraParams" translate="false">
+llClearCameraParams()
+Resets all camera parameters to default values and turns off scripted camera control
+ </string>
+ <string name="LSLTipText_llListStatistics" translate="false">
+float llListStatistics(integer operation, list src)
+Performs statistical aggregate functions on list src using LIST_STAT_* operations
+ </string>
+ <string name="LSLTipText_llGetUnixTime" translate="false">
+integer llGetUnixTime()
+Returns the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC from the system clock
+ </string>
+ <string name="LSLTipText_llGetParcelFlags" translate="false">
+integer llGetParcelFlags(vector pos)
+Returns a mask of the parcel flags (PARCEL_FLAG_*) for the parcel that includes the point pos
+ </string>
+ <string name="LSLTipText_llGetRegionFlags" translate="false">
+integer llGetRegionFlags()
+Returns the region flags (REGION_FLAG_*) for the region the object is in
+ </string>
+ <string name="LSLTipText_llXorBase64StringsCorrect" translate="false">
+string llXorBase64StringsCorrect(string s1, string s2)
+Correctly performs an exclusive or on two Base64 strings and returns a Base64 string.
+s2 repeats if it is shorter than s1.
+ </string>
+ <string name="LSLTipText_llHTTPRequest" translate="false">
+llHTTPRequest(string url, list parameters, string body)
+Sends an HTTP request to the specified url with the body of the request and parameters
+ </string>
+ <string name="LSLTipText_llResetLandBanList" translate="false">
+llResetLandBanList()
+Removes all Residents from the land ban list
+ </string>
+ <string name="LSLTipText_llResetLandPassList" translate="false">
+llResetLandPassList()
+Removes all Residents from the land access/pass list
+ </string>
+ <string name="LSLTipText_llGetObjectPrimCount" translate="false">
+integer llGetObjectPrimCount(key object_id)
+Returns the total number of prims for an object in the region
+ </string>
+ <string name="LSLTipText_llGetParcelPrimOwners" translate="false">
+list llGetParcelPrimOwners(vector pos)
+Returns a list of all Residents who own objects on the parcel at pos and with individual prim counts.
+Requires owner-like permissions for the parcel.
+ </string>
+ <string name="LSLTipText_llGetParcelPrimCount" translate="false">
+integer llGetParcelPrimCount(vector pos, integer category, integer sim_wide)
+Returns the number of prims on the parcel at pos of the given category.
+Categories: PARCEL_COUNT_TOTAL, _OWNER, _GROUP, _OTHER, _SELECTED, _TEMP
+ </string>
+ <string name="LSLTipText_llGetParcelMaxPrims" translate="false">
+integer llGetParcelMaxPrims(vector pos, integer sim_wide)
+Returns the maximum number of prims allowed on the parcel at pos
+ </string>
+ <string name="LSLTipText_llGetParcelDetails" translate="false">
+list llGetParcelDetails(vector pos, list params)
+Returns the parcel details specified in params for the parcel at pos.
+Params is one or more of: PARCEL_DETAILS_NAME, _DESC, _OWNER, _GROUP, _AREA
+ </string>
+ <string name="LSLTipText_llSetLinkPrimitiveParams" translate="false">
+llSetLinkPrimitiveParams(integer linknumber, list rules)
+Sets primitive parameters for linknumber based on rules
+ </string>
+ <string name="LSLTipText_llSetLinkTexture" translate="false">
+llSetLinkTexture(integer linknumber, string texture, integer face)
+Sets the texture of face for a task that exists in the link chain at linknumber
+ </string>
+ <string name="LSLTipText_llStringTrim" translate="false">
+string llStringTrim(string src, integer trim_type)
+Trims the leading and/or trailing white spaces from a string.
+trim_type can be STRING_TRIM, STRING_TRIM_HEAD or STRING_TRIM_TAIL.
+ </string>
+ <string name="LSLTipText_llRegionSay" translate="false">
+llRegionSay(integer channel, string msg)
+Broadcasts msg on channel (not 0) that can be heard anywhere in the region by a script listening on channel
+ </string>
+ <string name="LSLTipText_llGetObjectDetails" translate="false">
+list llGetObjectDetails(key id, list params)
+Returns the object details specified in params for the object with key id.
+Params are OBJECT_NAME, _DESC, _POS, _ROT, _VELOCITY, _OWNER, _GROUP, _CREATOR
+ </string>
+ <string name="LSLTipText_llSetClickAction" translate="false">
+llSetClickAction(integer action)
+Sets the action performed when a prim is clicked upon
+ </string>
+ <string name="LSLTipText_llGetRegionAgentCount" translate="false">
+integer llGetRegionAgentCount()
+Returns the number of avatars in the region
+ </string>
+ <string name="LSLTipText_llTextBox" translate="false">
+llTextBox(key avatar, string message, integer chat_channel
+Shows a dialog box on the avatar&apos;s screen with the message.
+It contains a text box for input, and if entered that text is chatted on chat_channel.
+ </string>
+ <string name="LSLTipText_llGetAgentLanguage" translate="false">
+string llGetAgentLanguage(key avatar)
+Returns the language code of the preferred interface language of the avatar
+ </string>
+ <string name="LSLTipText_llDetectedTouchUV" translate="false">
+vector llDetectedTouchUV(integer index)
+Returns the u and v coordinates in the first two components of a vector, for the texture coordinates where the prim was touched in a triggered touch event
+ </string>
+ <string name="LSLTipText_llDetectedTouchFace" translate="false">
+integer llDetectedTouchFace(integer index)
+Returns the index of the face where the avatar clicked in a triggered touch event
+ </string>
+ <string name="LSLTipText_llDetectedTouchPos" translate="false">
+vector llDetectedTouchPos(integer index)
+Returns the position where the object was touched in a triggered touch event
+ </string>
+ <string name="LSLTipText_llDetectedTouchNormal" translate="false">
+vector llDetectedTouchNormal(integer index)
+Returns the surface normal for a triggered touch event
+ </string>
+ <string name="LSLTipText_llDetectedTouchBinormal" translate="false">
+vector llDetectedTouchBinormal(integer index)
+Returns the surface binormal for a triggered touch event
+ </string>
+ <string name="LSLTipText_llDetectedTouchST" translate="false">
+vector llDetectedTouchST(integer index)
+Returns the s and t coordinates in the first two components of a vector, for the surface coordinates where the prim was touched in a triggered touch event
+ </string>
+ <string name="LSLTipText_llSHA1String" translate="false">
+string llSHA1String(string src)
+Returns a string of 40 hex characters that is the SHA1 security Hash of src
+ </string>
+ <string name="LSLTipText_llGetFreeURLs" translate="false">
+integer llGetFreeURLs()
+Returns the number of available URLs for the current script
+ </string>
+ <string name="LSLTipText_llRequestURL" translate="false">
+key llRequestURL()
+Requests one HTTP:// url for use by this object.
+An http_request event is triggered with the results.
+ </string>
+ <string name="LSLTipText_llRequestSecureURL" translate="false">
+key llRequestSecureURL()
+Requests one HTTPS:// (SSL) url for use by this object.
+An http_request event is triggered with the results.
+ </string>
+ <string name="LSLTipText_llReleaseURL" translate="false">
+llReleaseURL(string url)
+Releases the specified URL, it will no longer be usable
+ </string>
+ <string name="LSLTipText_llHTTPResponse" translate="false">
+llHTTPResponse(key request_id, integer status, string body)
+Responds to request_id with status and body
+ </string>
+ <string name="LSLTipText_llGetHTTPHeader" translate="false">
+string llGetHTTPHeader(key request_id, string header)
+Returns the value for header for request_id
+ </string>
+ <string name="LSLTipText_llSetPrimMediaParams" translate="false">
+llSetPrimMediaParams(integer face, list params)
+Sets the media params for a particular face on an object. If media is not already on this object, add it.
+List is a set of name/value pairs in no particular order. Params not specified are unchanged, or if new media is added then set to the default specified.
+The possible names are below, along with the types of values and what they mean.
+ </string>
+ <string name="LSLTipText_llGetPrimMediaParams" translate="false">
+list llGetPrimMediaParams(integer face, list params)
+Returns the media params for a particular face on an object, given the desired list of names, in the order requested.
+(Returns an empty list if no media exists on the face.)
+ </string>
+ <string name="LSLTipText_llClearPrimMedia" translate="false">
+llClearPrimMedia(integer face)
+Clears (deletes) the media and all params from the given face.
+ </string>
+
+ <!-- Avatar busy/away mode -->
+ <string name="AvatarSetNotAway">Not Away</string>
+ <string name="AvatarSetAway">Away</string>
+ <string name="AvatarSetNotBusy">Not Busy</string>
+ <string name="AvatarSetBusy">Busy</string>
+
+ <!-- Wearable Types -->
+ <string name="shape">Shape</string>
+ <string name="skin">Skin</string>
+ <string name="hair">Hair</string>
+ <string name="eyes">Eyes</string>
+ <string name="shirt">Shirt</string>
+ <string name="pants">Pants</string>
+ <string name="shoes">Shoes</string>
+ <string name="socks">Socks</string>
+ <string name="jacket">Jacket</string>
+ <string name="gloves">Gloves</string>
+ <string name="undershirt">Undershirt</string>
+ <string name="underpants">Underpants</string>
+ <string name="skirt">Skirt</string>
+ <string name="alpha">Alpha</string>
+ <string name="tattoo">Tattoo</string>
+ <string name="invalid">invalid</string>
+
+ <!-- LLGroupNotify -->
+ <!-- used in the construction of a Group Notice blue dialog box, buttons, tooltip etc. Seems to be no longer utilized by code in Viewer 2.0 -->
+ <string name="next">Next</string>
+ <string name="ok">OK</string>
+ <string name="GroupNotifyGroupNotice">Group Notice</string>
+ <string name="GroupNotifyGroupNotices">Group Notices</string>
+ <string name="GroupNotifySentBy">Sent by</string>
+ <string name="GroupNotifyAttached">Attached:</string>
+ <string name="GroupNotifyViewPastNotices">View past notices or opt-out of receiving these messages here.</string>
+ <string name="GroupNotifyOpenAttachment">Open Attachment</string>
+ <string name="GroupNotifySaveAttachment">Save Attachment</string>
+
+ <string name="TeleportOffer">Teleport offering</string>
+ <!-- start-up toast's string-->
+ <string name="StartUpNotifications">New notifications arrived while you were away.</string>
+ <!-- overflow toast's string-->
+ <string name="OverflowInfoChannelString">You have %d more notification</string>
+
+
+ <!-- body parts -->
+ <string name="BodyPartsRightArm">Right Arm</string>
+ <string name="BodyPartsHead">Head</string>
+ <string name="BodyPartsLeftArm">Left Arm</string>
+ <string name="BodyPartsLeftLeg">Left Leg</string>
+ <string name="BodyPartsTorso">Torso</string>
+ <string name="BodyPartsRightLeg">Right Leg</string>
+
+ <!-- slider -->
+ <string name="GraphicsQualityLow">Low</string>
+ <string name="GraphicsQualityMid">Mid</string>
+ <string name="GraphicsQualityHigh">High</string>
+
+ <!-- mouselook -->
+ <string name="LeaveMouselook">Press ESC to return to World View</string>
+
+ <!-- inventory -->
+ <string name="InventoryNoMatchingItems">No matching items found in inventory.</string>
+ <string name="FavoritesNoMatchingItems">Drag a landmark here to add it to your favorites.</string>
+ <string name="InventoryNoTexture">
+ You do not have a copy of
+this texture in your inventory
+ </string>
+ <!-- use value="" because they have preceding spaces -->
+ <string name="no_transfer" value=" (no transfer)" />
+ <string name="no_modify" value=" (no modify)" />
+ <string name="no_copy" value=" (no copy)" />
+ <string name="worn" value=" (worn)" />
+ <string name="link" value=" (link)" />
+ <string name="broken_link" value=" (broken_link)" />
+ <string name="LoadingContents">Loading contents...</string>
+ <string name="NoContents">No contents</string>
+ <string name="WornOnAttachmentPoint" value=" (worn on [ATTACHMENT_POINT])" />
+ <!-- Inventory permissions -->
+ <string name="PermYes">Yes</string>
+ <string name="PermNo">No</string>
+
+ <!-- Gestures labels -->
+ <!-- use value="" because they have preceding spaces -->
+ <string name="Chat" value=" Chat : " />
+ <string name="Sound" value=" Sound : " />
+ <string name="Wait" value=" --- Wait : " />
+ <string name="AnimFlagStop" value=" Stop Animation : " />
+ <string name="AnimFlagStart" value=" Start Animation : " />
+ <string name="Wave" value=" Wave " />
+ <string name="HelloAvatar" value=" Hello, avatar! " />
+ <string name="ViewAllGestures" value=" View All &gt;&gt;" />
+
+ <!-- inventory filter -->
+ <!-- use value="" because they have preceding spaces -->
+ <string name="Animations" value=" Animations," />
+ <string name="Calling Cards" value=" Calling Cards," />
+ <string name="Clothing" value=" Clothing," />
+ <string name="Gestures" value=" Gestures," />
+ <string name="Landmarks" value=" Landmarks," />
+ <string name="Notecards" value=" Notecards," />
+ <string name="Objects" value=" Objects," />
+ <string name="Scripts" value=" Scripts," />
+ <string name="Sounds" value=" Sounds," />
+ <string name="Textures" value=" Textures," />
+ <string name="Snapshots" value=" Snapshots," />
+ <string name="No Filters" value="No " />
+ <string name="Since Logoff" value=" - Since Logoff" />
+
+ <!-- inventory folder -->
+ <string name="InvFolder My Inventory">My Inventory</string>
+ <string name="InvFolder My Favorites">My Favorites</string>
+ <string name="InvFolder Library">Library</string>
+ <string name="InvFolder Textures">Textures</string>
+ <string name="InvFolder Sounds">Sounds</string>
+ <string name="InvFolder Calling Cards">Calling Cards</string>
+ <string name="InvFolder Landmarks">Landmarks</string>
+ <string name="InvFolder Scripts">Scripts</string>
+ <string name="InvFolder Clothing">Clothing</string>
+ <string name="InvFolder Objects">Objects</string>
+ <string name="InvFolder Notecards">Notecards</string>
+ <string name="InvFolder New Folder">New Folder</string>
+ <string name="InvFolder Inventory">Inventory</string>
+ <string name="InvFolder Uncompressed Images">Uncompressed Images</string>
+ <string name="InvFolder Body Parts">Body Parts</string>
+ <string name="InvFolder Trash">Trash</string>
+ <string name="InvFolder Photo Album">Photo Album</string>
+ <string name="InvFolder Lost And Found">Lost And Found</string>
+ <string name="InvFolder Uncompressed Sounds">Uncompressed Sounds</string>
+ <string name="InvFolder Animations">Animations</string>
+ <string name="InvFolder Gestures">Gestures</string>
+ <string name="InvFolder favorite">Favorites</string>
+ <string name="InvFolder Current Outfit">Current Outfit</string>
+ <string name="InvFolder My Outfits">My Outfits</string>
+
+ <!-- are used for Friends and Friends/All folders in Inventory "Calling cards" folder. See EXT-694-->
+ <string name="InvFolder Friends">Friends</string>
+ <string name="InvFolder All">All</string>
+
+ <!-- inventory FVBridge -->
+ <!-- This is used in llpanelinventory.cpp when constructing a context menu for an item for Sale -->
+ <string name="Buy">Buy</string>
+ <string name="BuyforL$">Buy for L$</string>
+
+ <string name="Stone">Stone</string>
+ <string name="Metal">Metal</string>
+ <string name="Glass">Glass</string>
+ <string name="Wood">Wood</string>
+ <string name="Flesh">Flesh</string>
+ <string name="Plastic">Plastic</string>
+ <string name="Rubber">Rubber</string>
+ <string name="Light">Light</string>
+
+ <!-- keyboard -->
+ <string name="KBShift">Shift</string>
+ <string name="KBCtrl">Ctrl</string>
+
+ <!-- Avatar Skeleton -->
+ <string name="Chest">Chest</string>
+ <string name="Skull">Skull</string>
+ <string name="Left Shoulder">Left Shoulder</string>
+ <string name="Right Shoulder">Right Shoulder</string>
+ <string name="Left Hand">Left Hand</string>
+ <string name="Right Hand">Right Hand</string>
+ <string name="Left Foot">Left Foot</string>
+ <string name="Right Foot">Right Foot</string>
+ <string name="Spine">Spine</string>
+ <string name="Pelvis">Pelvis</string>
+ <string name="Mouth">Mouth</string>
+ <string name="Chin">Chin</string>
+ <string name="Left Ear">Left Ear</string>
+ <string name="Right Ear">Right Ear</string>
+ <string name="Left Eyeball">Left Eyeball</string>
+ <string name="Right Eyeball">Right Eyeball</string>
+ <string name="Nose">Nose</string>
+ <string name="R Upper Arm">R Upper Arm</string>
+ <string name="R Forearm">R Forearm</string>
+ <string name="L Upper Arm">L Upper Arm</string>
+ <string name="L Forearm">L Forearm</string>
+ <string name="Right Hip">Right Hip</string>
+ <string name="R Upper Leg">R Upper Leg</string>
+ <string name="R Lower Leg">R Lower Leg</string>
+ <string name="Left Hip">Left Hip</string>
+ <string name="L Upper Leg">L Upper Leg</string>
+ <string name="L Lower Leg">L Lower Leg</string>
+ <string name="Stomach">Stomach</string>
+ <string name="Left Pec">Left Pec</string>
+ <string name="Right Pec">Right Pec</string>
+
+ <!-- Avatar age computation, see LLDateUtil::ageFromDate -->
+ <string name="YearsMonthsOld">[AGEYEARS] [AGEMONTHS] old</string>
+ <string name="YearsOld">[AGEYEARS] old</string>
+ <string name="MonthsOld">[AGEMONTHS] old</string>
+ <string name="WeeksOld">[AGEWEEKS] old</string>
+ <string name="DaysOld">[AGEDAYS] old</string>
+ <string name="TodayOld">Joined today</string>
+
+ <!-- AgeYearsA = singular,
+ AgeYearsB = plural,
+ AgeYearsC = plural for non-English languages like Russian
+ For example, LLTrans::getCountString("AgeYears", 3) is plural form B
+ in English and form C in Russian -->
+ <string name="AgeYearsA">[COUNT] year</string>
+ <string name="AgeYearsB">[COUNT] years</string>
+ <string name="AgeYearsC">[COUNT] years</string>
+ <string name="AgeMonthsA">[COUNT] month</string>
+ <string name="AgeMonthsB">[COUNT] months</string>
+ <string name="AgeMonthsC">[COUNT] months</string>
+ <string name="AgeWeeksA">[COUNT] week</string>
+ <string name="AgeWeeksB">[COUNT] weeks</string>
+ <string name="AgeWeeksC">[COUNT] weeks</string>
+ <string name="AgeDaysA">[COUNT] day</string>
+ <string name="AgeDaysB">[COUNT] days</string>
+ <string name="AgeDaysC">[COUNT] days</string>
+ <!-- Group member counts -->
+ <string name="GroupMembersA">[COUNT] member</string>
+ <string name="GroupMembersB">[COUNT] members</string>
+ <string name="GroupMembersC">[COUNT] members</string>
+
+ <!-- Account types, see LLAvatarPropertiesProcessor -->
+ <string name="AcctTypeResident">Resident</string>
+ <string name="AcctTypeTrial">Trial</string>
+ <string name="AcctTypeCharterMember">Charter Member</string>
+ <string name="AcctTypeEmployee">Linden Lab Employee</string>
+ <string name="PaymentInfoUsed">Payment Info Used</string>
+ <string name="PaymentInfoOnFile">Payment Info On File</string>
+ <string name="NoPaymentInfoOnFile">No Payment Info On File</string>
+ <string name="AgeVerified">Age-verified</string>
+ <string name="NotAgeVerified">Not Age-verified</string>
+
+ <!-- HUD Position -->
+ <string name="Center 2">Center 2</string>
+ <string name="Top Right">Top Right</string>
+ <string name="Top">Top</string>
+ <string name="Top Left">Top Left</string>
+ <string name="Center">Center</string>
+ <string name="Bottom Left">Bottom Left</string>
+ <string name="Bottom">Bottom</string>
+ <string name="Bottom Right">Bottom Right</string>
+
+ <!-- compile queue-->
+ <string name="CompileQueueDownloadedCompiling">Downloaded, now compiling</string>
+ <string name="CompileQueueScriptNotFound">Script not found on server.</string>
+ <string name="CompileQueueProblemDownloading">Problem downloading</string>
+ <string name="CompileQueueInsufficientPermDownload">Insufficient permissions to download a script.</string>
+ <string name="CompileQueueInsufficientPermFor">Insufficient permissions for</string>
+ <string name="CompileQueueUnknownFailure">Unknown failure to download</string>
+ <string name="CompileQueueTitle">Recompilation Progress</string>
+ <string name="CompileQueueStart">recompile</string>
+ <string name="ResetQueueTitle">Reset Progress</string>
+ <string name="ResetQueueStart">reset</string>
+ <string name="RunQueueTitle">Set Running Progress</string>
+ <string name="RunQueueStart">set running</string>
+ <string name="NotRunQueueTitle">Set Not Running Progress</string>
+ <string name="NotRunQueueStart">set not running</string>
+
+ <!-- compile comment text-->
+ <string name="CompileSuccessful">Compile successful!</string>
+ <string name="CompileSuccessfulSaving">Compile successful, saving...</string>
+ <string name="SaveComplete">Save complete.</string>
+ <string name="ObjectOutOfRange">Script (object out of range)</string>
+
+ <!-- god tools -->
+ <string name="GodToolsObjectOwnedBy">Object [OBJECT] owned by [OWNER]</string>
+
+ <!-- groups -->
+ <string name="GroupsNone">none</string>
+ <string name="Group" value=" (group)" />
+ <string name="Unknown">(Unknown)</string>
+ <string name="SummaryForTheWeek" value="Summary for this week, beginning on " />
+ <string name="NextStipendDay" value="The next stipend day is " />
+ <string name="GroupIndividualShare" value=" Group Individual Share" />
+ <string name="Balance">Balance</string>
+ <string name="Credits">Credits</string>
+ <string name="Debits">Debits</string>
+ <string name="Total">Total</string>
+ <string name="NoGroupDataFound">No group data found for group </string>
+
+ <!-- floater IM bonus_info: When a Linden with Admin/god status receives a new IM this displays the estate (Mainland vs. teen grid) of the source avatar.
+ This is to help Lindens when answering questions. -->
+ <string name="IMParentEstate">parent estate</string>
+ <string name="IMMainland">mainland</string>
+ <string name="IMTeen">teen</string>
+
+ <!-- floater region info -->
+ <!-- The following will replace variable [ALL_ESTATES] in notifications EstateAllowed*, EstateBanned*, EstateManager* -->
+ <string name="RegionInfoError">error</string>
+ <string name="RegionInfoAllEstatesOwnedBy">
+ all estates owned by [OWNER]
+ </string>
+ <string name="RegionInfoAllEstatesYouOwn">all estates that you own</string>
+ <string name="RegionInfoAllEstatesYouManage">
+ all estates that you manage for [OWNER]
+ </string>
+ <string name="RegionInfoAllowedResidents">Allowed Residents: ([ALLOWEDAGENTS], max [MAXACCESS])</string>
+ <string name="RegionInfoAllowedGroups">Allowed groups: ([ALLOWEDGROUPS], max [MAXACCESS])</string>
+
+ <!-- script limits floater -->
+ <string name="ScriptLimitsParcelScriptMemory">Parcel Script Memory</string>
+ <string name="ScriptLimitsParcelsOwned">Parcels Listed: [PARCELS]</string>
+ <string name="ScriptLimitsMemoryUsed">Memory used: [COUNT] kb out of [MAX] kb; [AVAILABLE] kb available</string>
+ <string name="ScriptLimitsMemoryUsedSimple">Memory used: [COUNT] kb</string>
+ <string name="ScriptLimitsParcelScriptURLs">Parcel Script URLs</string>
+ <string name="ScriptLimitsURLsUsed">URLs used: [COUNT] out of [MAX]; [AVAILABLE] available</string>
+ <string name="ScriptLimitsURLsUsedSimple">URLs used: [COUNT]</string>
+ <string name="ScriptLimitsRequestError">Error requesting information</string>
+ <string name="ScriptLimitsRequestWrongRegion">Error: script information is only available in your current region</string>
+ <string name="ScriptLimitsRequestWaiting">Retrieving information...</string>
+ <string name="ScriptLimitsRequestDontOwnParcel">You do not have permission to examine this parcel</string>
+
+ <string name="SITTING_ON">Sitting On</string>
+ <string name="ATTACH_CHEST">Chest</string>
+ <string name="ATTACH_HEAD">Head</string>
+ <string name="ATTACH_LSHOULDER">Left Shoulder</string>
+ <string name="ATTACH_RSHOULDER">Right Shoulder</string>
+ <string name="ATTACH_LHAND">Left Hand</string>
+ <string name="ATTACH_RHAND">Right Hand</string>
+ <string name="ATTACH_LFOOT">Left Foot</string>
+ <string name="ATTACH_RFOOT">Right Foot</string>
+ <string name="ATTACH_BACK">Back</string>
+ <string name="ATTACH_PELVIS">Pelvis</string>
+ <string name="ATTACH_MOUTH">Mouth</string>
+ <string name="ATTACH_CHIN">Chin</string>
+ <string name="ATTACH_LEAR">Left Ear</string>
+ <string name="ATTACH_REAR">Right Ear</string>
+ <string name="ATTACH_LEYE">Left Eye</string>
+ <string name="ATTACH_REYE">Right Eye</string>
+ <string name="ATTACH_NOSE">Nose</string>
+ <string name="ATTACH_RUARM">Right Upper Arm</string>
+ <string name="ATTACH_RLARM">Right Lower Arm</string>
+ <string name="ATTACH_LUARM">Left Upper Arm</string>
+ <string name="ATTACH_LLARM">Left Lower Arm</string>
+ <string name="ATTACH_RHIP">Right Hip</string>
+ <string name="ATTACH_RULEG">Right Upper Leg</string>
+ <string name="ATTACH_RLLEG">Right Lower Leg</string>
+ <string name="ATTACH_LHIP">Left Hip</string>
+ <string name="ATTACH_LULEG">Left Upper Leg</string>
+ <string name="ATTACH_LLLEG">Left Lower Leg</string>
+ <string name="ATTACH_BELLY">Belly</string>
+ <string name="ATTACH_RPEC">Right Pec</string>
+ <string name="ATTACH_LPEC">Left Pec</string>
+ <string name="ATTACH_HUD_CENTER_2">HUD Center 2</string>
+ <string name="ATTACH_HUD_TOP_RIGHT">HUD Top Right</string>
+ <string name="ATTACH_HUD_TOP_CENTER">HUD Top Center</string>
+ <string name="ATTACH_HUD_TOP_LEFT">HUD Top Left</string>
+ <string name="ATTACH_HUD_CENTER_1">HUD Center 1</string>
+ <string name="ATTACH_HUD_BOTTOM_LEFT">HUD Bottom Left</string>
+ <string name="ATTACH_HUD_BOTTOM">HUD Bottom</string>
+ <string name="ATTACH_HUD_BOTTOM_RIGHT">HUD Bottom Right</string>
+
+ <!-- script editor -->
+ <string name="CursorPos">Line [LINE], Column [COLUMN]</string>
+
+ <!-- panel dir browser -->
+ <string name="PanelDirCountFound">[COUNT] found</string>
+ <string name="PanelDirTimeStr">[hour12,datetime,slt]:[min,datetime,slt] [ampm,datetime,slt]</string>
+
+ <!-- panel dir events -->
+ <string name="PanelDirEventsDateText">[mthnum,datetime,slt]/[day,datetime,slt]</string>
+
+ <!-- panel contents -->
+ <string name="PanelContentsNewScript">New Script</string>
+
+ <!-- Mute -->
+ <string name="MuteByName">(by name)</string>
+ <string name="MuteAgent">(Resident)</string>
+ <string name="MuteObject">(object)</string>
+ <string name="MuteGroup">(group)</string>
+
+ <!-- Region/Estate Covenant -->
+ <string name="RegionNoCovenant">There is no Covenant provided for this Estate.</string>
+ <string name="RegionNoCovenantOtherOwner">There is no Covenant provided for this Estate. The land on this estate is being sold by the Estate owner, not Linden Lab. Please contact the Estate Owner for sales details.</string>
+ <string name="covenant_last_modified">Last Modified:</string>
+ <string name="none_text" value=" (none) " />
+ <string name="never_text" value=" (never) " />
+
+ <!--Region Details-->
+ <string name="GroupOwned">Group Owned</string>
+ <string name="Public">Public</string>
+
+ <!-- panel classified -->
+ <string name="ClassifiedClicksTxt">Clicks: [TELEPORT] teleport, [MAP] map, [PROFILE] profile</string>
+ <string name="ClassifiedUpdateAfterPublish">(will update after publish)</string>
+
+ <!-- panel picks -->
+ <string name="NoPicksClassifiedsText">There are no picks/classifieds here</string>
+ <string name="PicksClassifiedsLoadingText">Loading...</string>
+
+ <!-- Multi Preview Floater -->
+ <string name="MultiPreviewTitle">Preview</string>
+ <string name="MultiPropertiesTitle">Properties</string>
+
+ <!-- inventory offer -->
+ <string name="InvOfferAnObjectNamed">An object named</string>
+ <string name="InvOfferOwnedByGroup">owned by the group</string>
+ <string name="InvOfferOwnedByUnknownGroup">owned by an unknown group</string>
+ <string name="InvOfferOwnedBy">owned by</string>
+ <string name="InvOfferOwnedByUnknownUser">owned by an unknown user</string>
+ <string name="InvOfferGaveYou">gave you</string>
+ <string name="InvOfferYouDecline">You decline</string>
+ <string name="InvOfferFrom">from</string>
+
+ <!-- group money -->
+ <string name="GroupMoneyTotal">Total</string>
+ <string name="GroupMoneyBought">bought</string>
+ <string name="GroupMoneyPaidYou">paid you</string>
+ <string name="GroupMoneyPaidInto">paid into</string>
+ <string name="GroupMoneyBoughtPassTo">bought pass to</string>
+ <string name="GroupMoneyPaidFeeForEvent">paid fee for event</string>
+ <string name="GroupMoneyPaidPrizeForEvent">paid prize for event</string>
+ <string name="GroupMoneyBalance">Balance</string>
+ <string name="GroupMoneyCredits">Credits</string>
+ <string name="GroupMoneyDebits">Debits</string>
+
+ <!-- viewer object -->
+ <string name="ViewerObjectContents">Contents</string>
+
+ <!-- Viewer menu -->
+ <string name="AcquiredItems">Acquired Items</string>
+ <string name="Cancel">Cancel</string>
+ <string name="UploadingCosts">Uploading %s costs</string>
+ <string name="UnknownFileExtension">
+ Unknown file extension .%s
+Expected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh
+ </string>
+ <string name="MuteObject2">Block</string>
+ <string name="MuteAvatar">Block</string>
+ <string name="UnmuteObject">Unblock</string>
+ <string name="UnmuteAvatar">Unblock</string>
+ <string name="AddLandmarkNavBarMenu">Add to My Landmarks...</string>
+ <string name="EditLandmarkNavBarMenu">Edit my Landmark...</string>
+
+ <!-- menu accelerators -->
+ <string name="accel-mac-control">&#8963;</string>
+ <string name="accel-mac-command">&#8984;</string>
+ <string name="accel-mac-option">&#8997;</string>
+ <string name="accel-mac-shift">&#8679;</string>
+ <string name="accel-win-control">Ctrl+</string>
+ <string name="accel-win-alt">Alt+</string>
+ <string name="accel-win-shift">Shift+</string>
+
+ <!-- Previews -->
+ <string name="FileSaved">File Saved</string>
+ <string name="Receiving">Receiving</string>
+
+ <!-- status bar , Time -->
+ <string name="AM">AM</string>
+ <string name="PM">PM</string>
+ <string name="PST">PST</string>
+ <string name="PDT">PDT</string>
+
+ <!-- Directions, HUD -->
+ <string name="Forward">Forward</string>
+ <string name="Left">Left</string>
+ <string name="Right">Right</string>
+ <string name="Back">Back</string>
+ <string name="North">North</string>
+ <string name="South">South</string>
+ <string name="West">West</string>
+ <string name="East">East</string>
+ <string name="Up">Up</string>
+ <string name="Down">Down</string>
+
+ <!-- Search Category Strings -->
+ <string name="Any Category">Any Category</string>
+ <string name="Shopping">Shopping</string>
+ <string name="Land Rental">Land Rental</string>
+ <string name="Property Rental">Property Rental</string>
+ <string name="Special Attraction">Special Attraction</string>
+ <string name="New Products">New Products</string>
+ <string name="Employment">Employment</string>
+ <string name="Wanted">Wanted</string>
+ <string name="Service">Service</string>
+ <string name="Personal">Personal</string>
+
+ <!-- PARCEL_CATEGORY_UI_STRING -->
+ <string name="None">None</string>
+ <string name="Linden Location">Linden Location</string>
+ <string name="Adult">Adult</string>
+ <string name="Arts&amp;Culture">Arts &amp; Culture</string>
+ <string name="Business">Business</string>
+ <string name="Educational">Educational</string>
+ <string name="Gaming">Gaming</string>
+ <string name="Hangout">Hangout</string>
+ <string name="Newcomer Friendly">Newcomer Friendly</string>
+ <string name="Parks&amp;Nature">Parks &amp; Nature</string>
+ <string name="Residential">Residential</string>
+ <!--<string name="Shopping">Shopping</string> -->
+ <string name="Stage">Stage</string>
+ <string name="Other">Other</string>
+ <string name="Any">Any</string>
+ <string name="You">You</string>
+
+ <!-- punctuations -->
+ <string name=":">:</string>
+ <string name=",">,</string>
+ <string name="...">...</string>
+ <string name="***">***</string>
+ <string name="(">(</string>
+ <string name=")">)</string>
+ <string name=".">.</string>
+ <string name="'">'</string>
+ <string name="---">---</string>
+
+ <!-- media -->
+ <string name="Multiple Media">Multiple Media</string>
+ <string name="Play Media">Play/Pause Media</string>
+
+ <!-- OSMessageBox messages -->
+ <string name="MBCmdLineError">
+ An error was found parsing the command line.
+Please see: http://wiki.secondlife.com/wiki/Client_parameters
+Error:
+ </string>
+ <string name="MBCmdLineUsg">[APP_NAME] Command line usage:</string>
+ <string name="MBUnableToAccessFile">
+ [APP_NAME] is unable to access a file that it needs.
+
+This can be because you somehow have multiple copies running, or your system incorrectly thinks a file is open.
+If this message persists, restart your computer and try again.
+If it continues to persist, you may need to completely uninstall [APP_NAME] and reinstall it.
+ </string>
+ <string name="MBFatalError">Fatal Error</string>
+ <string name="MBRequiresAltiVec"> [APP_NAME] requires a processor with AltiVec (G4 or later).</string>
+ <string name="MBAlreadyRunning">
+ [APP_NAME] is already running.
+Check your task bar for a minimized copy of the program.
+If this message persists, restart your computer.
+ </string>
+ <string name="MBFrozenCrashed">
+ [APP_NAME] appears to have frozen or crashed on the previous run.
+Would you like to send a crash report?
+ </string>
+ <string name="MBAlert">Notification</string>
+ <string name="MBNoDirectX">
+ [APP_NAME] is unable to detect DirectX 9.0b or greater.
+[APP_NAME] uses DirectX to detect hardware and/or outdated drivers that can cause stability problems, poor performance and crashes. While you can run [APP_NAME] without it, we highly recommend running with DirectX 9.0b.
+
+Do you wish to continue?
+ </string>
+ <string name="MBWarning">Warning</string>
+ <string name="MBNoAutoUpdate">
+ Automatic updating is not yet implemented for Linux.
+Please download the latest version from www.secondlife.com.
+ </string>
+ <string name="MBRegClassFailed">RegisterClass failed</string>
+ <string name="MBError">Error</string>
+ <string name="MBFullScreenErr">
+ Unable to run fullscreen at [WIDTH] x [HEIGHT].
+Running in window.
+ </string>
+ <string name="MBDestroyWinFailed">Shutdown Error while destroying window (DestroyWindow() failed)</string>
+ <string name="MBShutdownErr">Shutdown Error</string>
+ <string name="MBDevContextErr">Can't make GL device context</string>
+ <string name="MBPixelFmtErr">Can't find suitable pixel format</string>
+ <string name="MBPixelFmtDescErr">Can't get pixel format description</string>
+ <string name="MBTrueColorWindow">
+ [APP_NAME] requires True Color (32-bit) to run.
+Please go to your computer's display settings and set the color mode to 32-bit.
+ </string>
+ <string name="MBAlpha">
+ [APP_NAME] is unable to run because it can't get an 8 bit alpha channel. Usually this is due to video card driver issues.
+Please make sure you have the latest video card drivers installed.
+Also be sure your monitor is set to True Color (32-bit) in Control Panels &gt; Display &gt; Settings.
+If you continue to receive this message, contact the [SUPPORT_SITE].
+ </string>
+ <string name="MBPixelFmtSetErr">Can't set pixel format</string>
+ <string name="MBGLContextErr">Can't create GL rendering context</string>
+ <string name="MBGLContextActErr">Can't activate GL rendering context</string>
+ <string name="MBVideoDrvErr">
+ [APP_NAME] is unable to run because your video card drivers did not install properly, are out of date, or are for unsupported hardware. Please make sure you have the latest video card drivers and even if you do have the latest, try reinstalling them.
+
+If you continue to receive this message, contact the [SUPPORT_SITE].
+ </string>
+
+ <!-- Avatar Shape Information -->
+<string name="5 O'Clock Shadow">5 O'Clock Shadow</string>
+
+<string name="All White">All White</string>
+<string name="Anime Eyes">Anime Eyes</string>
+<string name="Arced">Arced</string>
+<string name="Arm Length">Arm Length</string>
+<string name="Attached">Attached</string>
+<string name="Attached Earlobes">Attached Earlobes</string>
+
+
+<string name="Back Fringe">Back Fringe</string>
+
+<string name="Baggy">Baggy</string>
+<string name="Bangs">Bangs</string>
+
+<string name="Beady Eyes">Beady Eyes</string>
+<string name="Belly Size">Belly Size</string>
+<string name="Big">Big</string>
+<string name="Big Butt">Big Butt</string>
+
+<string name="Big Hair Back">Big Hair: Back</string>
+<string name="Big Hair Front">Big Hair: Front</string>
+<string name="Big Hair Top">Big Hair: Top</string>
+<string name="Big Head">Big Head</string>
+<string name="Big Pectorals">Big Pectorals</string>
+<string name="Big Spikes">Big Spikes</string>
+<string name="Black">Black</string>
+<string name="Blonde">Blonde</string>
+<string name="Blonde Hair">Blonde Hair</string>
+<string name="Blush">Blush</string>
+<string name="Blush Color">Blush Color</string>
+<string name="Blush Opacity">Blush Opacity</string>
+<string name="Body Definition">Body Definition</string>
+<string name="Body Fat">Body Fat</string>
+<string name="Body Freckles">Body Freckles</string>
+<string name="Body Thick">Body Thick</string>
+<string name="Body Thickness">Body Thickness</string>
+<string name="Body Thin">Body Thin</string>
+
+<string name="Bow Legged">Bow Legged</string>
+<string name="Breast Buoyancy">Breast Buoyancy</string>
+<string name="Breast Cleavage">Breast Cleavage</string>
+<string name="Breast Size">Breast Size</string>
+<string name="Bridge Width">Bridge Width</string>
+<string name="Broad">Broad</string>
+<string name="Brow Size">Brow Size</string>
+<string name="Bug Eyes">Bug Eyes</string>
+<string name="Bugged Eyes">Bugged Eyes</string>
+<string name="Bulbous">Bulbous</string>
+<string name="Bulbous Nose">Bulbous Nose</string>
+
+
+<string name="Bushy Eyebrows">Bushy Eyebrows</string>
+<string name="Bushy Hair">Bushy Hair</string>
+<string name="Butt Size">Butt Size</string>
+<string name="bustle skirt">Bustle Skirt</string>
+<string name="no bustle">No Bustle</string>
+<string name="more bustle">More Bustle</string>
+
+<string name="Chaplin">Chaplin</string>
+<string name="Cheek Bones">Cheek Bones</string>
+<string name="Chest Size">Chest Size</string>
+<string name="Chin Angle">Chin Angle</string>
+<string name="Chin Cleft">Chin Cleft</string>
+<string name="Chin Curtains">Chin Curtains</string>
+
+<string name="Chin Depth">Chin Depth</string>
+<string name="Chin Heavy">Chin Heavy</string>
+<string name="Chin In">Chin In</string>
+<string name="Chin Out">Chin Out</string>
+<string name="Chin-Neck">Chin-Neck</string>
+<string name="Clear">Clear</string>
+<string name="Cleft">Cleft</string>
+<string name="Close Set Eyes">Close Set Eyes</string>
+<string name="Closed">Closed</string>
+<string name="Closed Back">Closed Back</string>
+<string name="Closed Front">Closed Front</string>
+<string name="Closed Left">Closed Left</string>
+<string name="Closed Right">Closed Right</string>
+<string name="Coin Purse">Coin Purse</string>
+<string name="Collar Back">Collar Back</string>
+
+
+
+<string name="Collar Front">Collar Front</string>
+
+
+
+<string name="Corner Down">Corner Down</string>
+
+<string name="Corner Up">Corner Up</string>
+<string name="Creased">Creased</string>
+<string name="Crooked Nose">Crooked Nose</string>
+
+<string name="Cuff Flare">Cuff Flare</string>
+<string name="Dark">Dark</string>
+<string name="Dark Green">Dark Green</string>
+<string name="Darker">Darker</string>
+<string name="Deep">Deep</string>
+<string name="Default Heels">Default Heels</string>
+
+<string name="Dense">Dense</string>
+
+<string name="Double Chin">Double Chin</string>
+<string name="Downturned">Downturned</string>
+<string name="Duffle Bag">Duffle Bag</string>
+<string name="Ear Angle">Ear Angle</string>
+<string name="Ear Size">Ear Size</string>
+<string name="Ear Tips">Ear Tips</string>
+<string name="Egg Head">Egg Head</string>
+<string name="Eye Bags">Eye Bags</string>
+<string name="Eye Color">Eye Color</string>
+<string name="Eye Depth">Eye Depth</string>
+<string name="Eye Lightness">Eye Lightness</string>
+<string name="Eye Opening">Eye Opening</string>
+<string name="Eye Pop">Eye Pop</string>
+<string name="Eye Size">Eye Size</string>
+<string name="Eye Spacing">Eye Spacing</string>
+
+<string name="Eyebrow Arc">Eyebrow Arc</string>
+<string name="Eyebrow Density">Eyebrow Density</string>
+
+<string name="Eyebrow Height">Eyebrow Height</string>
+<string name="Eyebrow Points">Eyebrow Points</string>
+<string name="Eyebrow Size">Eyebrow Size</string>
+
+<string name="Eyelash Length">Eyelash Length</string>
+<string name="Eyeliner">Eyeliner</string>
+<string name="Eyeliner Color">Eyeliner Color</string>
+
+<string name="Eyes Bugged">Eyes Bugged</string>
+
+
+
+
+
+
+
+
+<string name="Face Shear">Face Shear</string>
+<string name="Facial Definition">Facial Definition</string>
+<string name="Far Set Eyes">Far Set Eyes</string>
+
+<string name="Fat Lips">Fat Lips</string>
+
+<string name="Female">Female</string>
+<string name="Fingerless">Fingerless</string>
+<string name="Fingers">Fingers</string>
+<string name="Flared Cuffs">Flared Cuffs</string>
+<string name="Flat">Flat</string>
+<string name="Flat Butt">Flat Butt</string>
+<string name="Flat Head">Flat Head</string>
+<string name="Flat Toe">Flat Toe</string>
+<string name="Foot Size">Foot Size</string>
+<string name="Forehead Angle">Forehead Angle</string>
+<string name="Forehead Heavy">Forehead Heavy</string>
+<string name="Freckles">Freckles</string>
+
+<string name="Front Fringe">Front Fringe</string>
+
+<string name="Full Back">Full Back</string>
+<string name="Full Eyeliner">Full Eyeliner</string>
+<string name="Full Front">Full Front</string>
+<string name="Full Hair Sides">Full Hair Sides</string>
+<string name="Full Sides">Full Sides</string>
+<string name="Glossy">Glossy</string>
+<string name="Glove Fingers">Glove Fingers</string>
+
+<string name="Glove Length">Glove Length</string>
+
+
+<string name="Hair">Hair</string>
+<string name="Hair Back">Hair: Back</string>
+<string name="Hair Front">Hair: Front</string>
+<string name="Hair Sides">Hair: Sides</string>
+<string name="Hair Sweep">Hair Sweep</string>
+<string name="Hair Thickess">Hair Thickness</string>
+<string name="Hair Thickness">Hair Thickness</string>
+<string name="Hair Tilt">Hair Tilt</string>
+<string name="Hair Tilted Left">Hair Tilted Left</string>
+<string name="Hair Tilted Right">Hair Tilted Right</string>
+<string name="Hair Volume">Hair: Volume</string>
+<string name="Hand Size">Hand Size</string>
+<string name="Handlebars">Handlebars</string>
+<string name="Head Length">Head Length</string>
+<string name="Head Shape">Head Shape</string>
+<string name="Head Size">Head Size</string>
+<string name="Head Stretch">Head Stretch</string>
+<string name="Heel Height">Heel Height</string>
+<string name="Heel Shape">Heel Shape</string>
+<string name="Height">Height</string>
+<string name="High">High</string>
+<string name="High Heels">High Heels</string>
+<string name="High Jaw">High Jaw</string>
+<string name="High Platforms">High Platforms</string>
+<string name="High and Tight">High and Tight</string>
+<string name="Higher">Higher</string>
+<string name="Hip Length">Hip Length</string>
+<string name="Hip Width">Hip Width</string>
+<string name="In">In</string>
+<string name="In Shdw Color">Inner Shadow Color</string>
+<string name="In Shdw Opacity">Inner Shadow Opacity</string>
+<string name="Inner Eye Corner">Inner Eye Corner</string>
+<string name="Inner Eye Shadow">Inner Eye Shadow</string>
+<string name="Inner Shadow">Inner Shadow</string>
+
+
+<string name="Jacket Length">Jacket Length</string>
+
+<string name="Jacket Wrinkles">Jacket Wrinkles</string>
+<string name="Jaw Angle">Jaw Angle</string>
+<string name="Jaw Jut">Jaw Jut</string>
+<string name="Jaw Shape">Jaw Shape</string>
+<string name="Join">Join</string>
+<string name="Jowls">Jowls</string>
+<string name="Knee Angle">Knee Angle</string>
+<string name="Knock Kneed">Knock Kneed</string>
+
+<string name="Large">Large</string>
+<string name="Large Hands">Large Hands</string>
+<string name="Left Part">Left Part</string>
+<string name="Leg Length">Leg Length</string>
+<string name="Leg Muscles">Leg Muscles</string>
+<string name="Less">Less</string>
+<string name="Less Body Fat">Less Body Fat</string>
+<string name="Less Curtains">Less Curtains</string>
+<string name="Less Freckles">Less Freckles</string>
+<string name="Less Full">Less Full</string>
+<string name="Less Gravity">Less Gravity</string>
+<string name="Less Love">Less Love</string>
+<string name="Less Muscles">Less Muscles</string>
+<string name="Less Muscular">Less Muscular</string>
+<string name="Less Rosy">Less Rosy</string>
+<string name="Less Round">Less Round</string>
+<string name="Less Saddle">Less Saddle</string>
+<string name="Less Square">Less Square</string>
+<string name="Less Volume">Less Volume</string>
+<string name="Less soul">Less soul</string>
+<string name="Lighter">Lighter</string>
+<string name="Lip Cleft">Lip Cleft</string>
+<string name="Lip Cleft Depth">Lip Cleft Depth</string>
+<string name="Lip Fullness">Lip Fullness</string>
+<string name="Lip Pinkness">Lip Pinkness</string>
+<string name="Lip Ratio">Lip Ratio</string>
+<string name="Lip Thickness">Lip Thickness</string>
+<string name="Lip Width">Lip Width</string>
+<string name="Lipgloss">Lipgloss</string>
+<string name="Lipstick">Lipstick</string>
+<string name="Lipstick Color">Lipstick Color</string>
+<string name="Long">Long</string>
+<string name="Long Head">Long Head</string>
+<string name="Long Hips">Long Hips</string>
+<string name="Long Legs">Long Legs</string>
+<string name="Long Neck">Long Neck</string>
+<string name="Long Pigtails">Long Pigtails</string>
+<string name="Long Ponytail">Long Ponytail</string>
+<string name="Long Torso">Long Torso</string>
+<string name="Long arms">Long arms</string>
+
+
+<string name="Loose Pants">Loose Pants</string>
+<string name="Loose Shirt">Loose Shirt</string>
+<string name="Loose Sleeves">Loose Sleeves</string>
+
+<string name="Love Handles">Love Handles</string>
+<string name="Low">Low</string>
+<string name="Low Heels">Low Heels</string>
+<string name="Low Jaw">Low Jaw</string>
+<string name="Low Platforms">Low Platforms</string>
+<string name="Low and Loose">Low and Loose</string>
+<string name="Lower">Lower</string>
+<string name="Lower Bridge">Lower Bridge</string>
+<string name="Lower Cheeks">Lower Cheeks</string>
+
+<string name="Male">Male</string>
+<string name="Middle Part">Middle Part</string>
+<string name="More">More</string>
+<string name="More Blush">More Blush</string>
+<string name="More Body Fat">More Body Fat</string>
+<string name="More Curtains">More Curtains</string>
+<string name="More Eyeshadow">More Eyeshadow</string>
+<string name="More Freckles">More Freckles</string>
+<string name="More Full">More Full</string>
+<string name="More Gravity">More Gravity</string>
+<string name="More Lipstick">More Lipstick</string>
+<string name="More Love">More Love</string>
+<string name="More Lower Lip">More Lower Lip</string>
+<string name="More Muscles">More Muscles</string>
+<string name="More Muscular">More Muscular</string>
+<string name="More Rosy">More Rosy</string>
+<string name="More Round">More Round</string>
+<string name="More Saddle">More Saddle</string>
+<string name="More Sloped">More Sloped</string>
+<string name="More Square">More Square</string>
+<string name="More Upper Lip">More Upper Lip</string>
+<string name="More Vertical">More Vertical</string>
+<string name="More Volume">More Volume</string>
+<string name="More soul">More soul</string>
+<string name="Moustache">Moustache</string>
+
+<string name="Mouth Corner">Mouth Corner</string>
+<string name="Mouth Position">Mouth Position</string>
+<string name="Mowhawk">Mowhawk</string>
+<string name="Muscular">Muscular</string>
+<string name="Mutton Chops">Mutton Chops</string>
+
+<string name="Nail Polish">Nail Polish</string>
+<string name="Nail Polish Color">Nail Polish Color</string>
+<string name="Narrow">Narrow</string>
+<string name="Narrow Back">Narrow Back</string>
+<string name="Narrow Front">Narrow Front</string>
+<string name="Narrow Lips">Narrow Lips</string>
+<string name="Natural">Natural</string>
+<string name="Neck Length">Neck Length</string>
+<string name="Neck Thickness">Neck Thickness</string>
+<string name="No Blush">No Blush</string>
+<string name="No Eyeliner">No Eyeliner</string>
+<string name="No Eyeshadow">No Eyeshadow</string>
+
+<string name="No Lipgloss">No Lipgloss</string>
+<string name="No Lipstick">No Lipstick</string>
+<string name="No Part">No Part</string>
+<string name="No Polish">No Polish</string>
+<string name="No Red">No Red</string>
+<string name="No Spikes">No Spikes</string>
+<string name="No White">No White</string>
+<string name="No Wrinkles">No Wrinkles</string>
+<string name="Normal Lower">Normal Lower</string>
+<string name="Normal Upper">Normal Upper</string>
+<string name="Nose Left">Nose Left</string>
+<string name="Nose Right">Nose Right</string>
+<string name="Nose Size">Nose Size</string>
+<string name="Nose Thickness">Nose Thickness</string>
+<string name="Nose Tip Angle">Nose Tip Angle</string>
+<string name="Nose Tip Shape">Nose Tip Shape</string>
+<string name="Nose Width">Nose Width</string>
+<string name="Nostril Division">Nostril Division</string>
+<string name="Nostril Width">Nostril Width</string>
+
+
+<string name="Opaque">Opaque</string>
+<string name="Open">Open</string>
+<string name="Open Back">Open Back</string>
+<string name="Open Front">Open Front</string>
+<string name="Open Left">Open Left</string>
+<string name="Open Right">Open Right</string>
+<string name="Orange">Orange</string>
+<string name="Out">Out</string>
+<string name="Out Shdw Color">Outer Shadow Color</string>
+<string name="Out Shdw Opacity">Outer Shadow Opacity</string>
+<string name="Outer Eye Corner">Outer Eye Corner</string>
+<string name="Outer Eye Shadow">Outer Eye Shadow</string>
+<string name="Outer Shadow">Outer Shadow</string>
+<string name="Overbite">Overbite</string>
+
+<string name="Package">Package</string>
+<string name="Painted Nails">Painted Nails</string>
+<string name="Pale">Pale</string>
+<string name="Pants Crotch">Pants Crotch</string>
+<string name="Pants Fit">Pants Fit</string>
+<string name="Pants Length">Pants Length</string>
+
+
+<string name="Pants Waist">Pants Waist</string>
+<string name="Pants Wrinkles">Pants Wrinkles</string>
+<string name="Part">Part</string>
+<string name="Part Bangs">Part Bangs</string>
+<string name="Pectorals">Pectorals</string>
+<string name="Pigment">Pigment</string>
+<string name="Pigtails">Pigtails</string>
+<string name="Pink">Pink</string>
+<string name="Pinker">Pinker</string>
+<string name="Platform Height">Platform Height</string>
+<string name="Platform Width">Platform Width</string>
+<string name="Pointy">Pointy</string>
+<string name="Pointy Heels">Pointy Heels</string>
+
+<string name="Ponytail">Ponytail</string>
+<string name="Poofy Skirt">Poofy Skirt</string>
+<string name="Pop Left Eye">Pop Left Eye</string>
+<string name="Pop Right Eye">Pop Right Eye</string>
+<string name="Puffy">Puffy</string>
+<string name="Puffy Eyelids">Puffy Eyelids</string>
+<string name="Rainbow Color">Rainbow Color</string>
+<string name="Red Hair">Red Hair</string>
+
+<string name="Regular">Regular</string>
+
+<string name="Right Part">Right Part</string>
+<string name="Rosy Complexion">Rosy Complexion</string>
+<string name="Round">Round</string>
+
+<string name="Ruddiness">Ruddiness</string>
+<string name="Ruddy">Ruddy</string>
+<string name="Rumpled Hair">Rumpled Hair</string>
+<string name="Saddle Bags">Saddle Bags</string>
+
+
+<string name="Scrawny Leg">Scrawny Leg</string>
+<string name="Separate">Separate</string>
+
+
+<string name="Shallow">Shallow</string>
+<string name="Shear Back">Shear Back</string>
+<string name="Shear Face">Shear Face</string>
+<string name="Shear Front">Shear Front</string>
+
+<string name="Shear Left Up">Shear Left Up</string>
+
+<string name="Shear Right Up">Shear Right Up</string>
+<string name="Sheared Back">Sheared Back</string>
+<string name="Sheared Front">Sheared Front</string>
+<string name="Shift Left">Shift Left</string>
+<string name="Shift Mouth">Shift Mouth</string>
+<string name="Shift Right">Shift Right</string>
+<string name="Shirt Bottom">Shirt Bottom</string>
+
+<string name="Shirt Fit">Shirt Fit</string>
+
+<string name="Shirt Wrinkles">Shirt Wrinkles</string>
+<string name="Shoe Height">Shoe Height</string>
+
+<string name="Short">Short</string>
+<string name="Short Arms">Short Arms</string>
+<string name="Short Legs">Short Legs</string>
+<string name="Short Neck">Short Neck</string>
+<string name="Short Pigtails">Short Pigtails</string>
+<string name="Short Ponytail">Short Ponytail</string>
+<string name="Short Sideburns">Short Sideburns</string>
+<string name="Short Torso">Short Torso</string>
+<string name="Short hips">Short hips</string>
+<string name="Shoulders">Shoulders</string>
+
+<string name="Side Fringe">Side Fringe</string>
+<string name="Sideburns">Sideburns</string>
+
+<string name="Sides Hair">Sides Hair</string>
+<string name="Sides Hair Down">Sides Hair Down</string>
+<string name="Sides Hair Up">Sides Hair Up</string>
+
+<string name="Skinny Neck">Skinny Neck</string>
+<string name="Skirt Fit">Skirt Fit</string>
+<string name="Skirt Length">Skirt Length</string>
+<string name="Slanted Forehead">Slanted Forehead</string>
+<string name="Sleeve Length">Sleeve Length</string>
+
+
+
+<string name="Sleeve Looseness">Sleeve Looseness</string>
+<string name="Slit Back">Slit: Back</string>
+<string name="Slit Front">Slit: Front</string>
+<string name="Slit Left">Slit: Left</string>
+<string name="Slit Right">Slit: Right</string>
+<string name="Small">Small</string>
+<string name="Small Hands">Small Hands</string>
+<string name="Small Head">Small Head</string>
+<string name="Smooth">Smooth</string>
+<string name="Smooth Hair">Smooth Hair</string>
+<string name="Socks Length">Socks Length</string>
+
+
+<string name="Soulpatch">Soulpatch</string>
+
+<string name="Sparse">Sparse</string>
+<string name="Spiked Hair">Spiked Hair</string>
+<string name="Square">Square</string>
+<string name="Square Toe">Square Toe</string>
+<string name="Squash Head">Squash Head</string>
+
+<string name="Stretch Head">Stretch Head</string>
+<string name="Sunken">Sunken</string>
+<string name="Sunken Chest">Sunken Chest</string>
+<string name="Sunken Eyes">Sunken Eyes</string>
+<string name="Sweep Back">Sweep Back</string>
+<string name="Sweep Forward">Sweep Forward</string>
+
+<string name="Tall">Tall</string>
+<string name="Taper Back">Taper Back</string>
+<string name="Taper Front">Taper Front</string>
+<string name="Thick Heels">Thick Heels</string>
+<string name="Thick Neck">Thick Neck</string>
+<string name="Thick Toe">Thick Toe</string>
+
+<string name="Thin">Thin</string>
+<string name="Thin Eyebrows">Thin Eyebrows</string>
+<string name="Thin Lips">Thin Lips</string>
+<string name="Thin Nose">Thin Nose</string>
+<string name="Tight Chin">Tight Chin</string>
+<string name="Tight Cuffs">Tight Cuffs</string>
+<string name="Tight Pants">Tight Pants</string>
+<string name="Tight Shirt">Tight Shirt</string>
+<string name="Tight Skirt">Tight Skirt</string>
+<string name="Tight Sleeves">Tight Sleeves</string>
+
+<string name="Toe Shape">Toe Shape</string>
+<string name="Toe Thickness">Toe Thickness</string>
+<string name="Torso Length">Torso Length</string>
+<string name="Torso Muscles">Torso Muscles</string>
+<string name="Torso Scrawny">Torso Scrawny</string>
+<string name="Unattached">Unattached</string>
+<string name="Uncreased">Uncreased</string>
+<string name="Underbite">Underbite</string>
+<string name="Unnatural">Unnatural</string>
+<string name="Upper Bridge">Upper Bridge</string>
+<string name="Upper Cheeks">Upper Cheeks</string>
+<string name="Upper Chin Cleft">Upper Chin Cleft</string>
+
+<string name="Upper Eyelid Fold">Upper Eyelid Fold</string>
+<string name="Upturned">Upturned</string>
+<string name="Very Red">Very Red</string>
+<string name="Waist Height">Waist Height</string>
+
+
+<string name="Well-Fed">Well-Fed</string>
+<string name="White Hair">White Hair</string>
+<string name="Wide">Wide</string>
+<string name="Wide Back">Wide Back</string>
+<string name="Wide Front">Wide Front</string>
+<string name="Wide Lips">Wide Lips</string>
+<string name="Wild">Wild</string>
+<string name="Wrinkles">Wrinkles</string>
+
+ <!-- Navigation bar location input control.
+ Strings are here because widget xml is not localizable -->
+ <string name="LocationCtrlAddLandmarkTooltip">Add to My Landmarks</string>
+ <string name="LocationCtrlEditLandmarkTooltip">Edit my Landmark</string>
+ <string name="LocationCtrlInfoBtnTooltip">See more info about the current location</string>
+ <string name="LocationCtrlComboBtnTooltip">My location history</string>
+ <string name="LocationCtrlForSaleTooltip">Buy this land</string>
+ <string name="LocationCtrlVoiceTooltip">Voice not available here</string>
+ <string name="LocationCtrlFlyTooltip">Flying not allowed</string>
+ <string name="LocationCtrlPushTooltip">No pushing</string>
+ <string name="LocationCtrlBuildTooltip">Building/dropping objects not allowed</string>
+ <string name="LocationCtrlScriptsTooltip">Scripts not allowed</string>
+ <string name="LocationCtrlDamageTooltip">Health</string>
+
+ <!-- Strings used by the (currently Linux) auto-updater app -->
+ <string name="UpdaterWindowTitle">
+ [APP_NAME] Update
+ </string>
+ <string name="UpdaterNowUpdating">
+ Now updating [APP_NAME]...
+ </string>
+ <string name="UpdaterNowInstalling">
+ Installing [APP_NAME]...
+ </string>
+ <string name="UpdaterUpdatingDescriptive">
+ Your [APP_NAME] Viewer is being updated to the latest release. This may take some time, so please be patient.
+ </string>
+ <string name="UpdaterProgressBarTextWithEllipses">
+ Downloading update...
+ </string>
+ <string name="UpdaterProgressBarText">
+ Downloading update
+ </string>
+ <string name="UpdaterFailDownloadTitle">
+ Failed to download update
+ </string>
+ <string name="UpdaterFailUpdateDescriptive">
+ An error occurred while updating [APP_NAME]. Please download the latest version from www.secondlife.com.
+ </string>
+ <string name="UpdaterFailInstallTitle">
+ Failed to install update
+ </string>
+ <string name="UpdaterFailStartTitle">
+ Failed to start viewer
+ </string>
+
+ <!-- IM system messages -->
+ <string name="IM_logging_string">-- Instant message logging enabled --</string>
+ <string name="IM_typing_start_string">[NAME] is typing...</string>
+ <string name="Unnamed">(Unnamed)</string>
+ <string name="IM_moderated_chat_label">(Moderated: Voices off by default)</string>
+ <string name="IM_unavailable_text_label">Text chat is not available for this call.</string>
+ <string name="IM_muted_text_label">Your text chat has been disabled by a Group Moderator.</string>
+ <string name="IM_default_text_label">Click here to instant message.</string>
+ <string name="IM_to_label">To</string>
+ <string name="IM_moderator_label">(Moderator)</string>
+
+ <!-- voice calls -->
+ <string name="started_call">Started a voice call</string>
+ <string name="joined_call">Joined the voice call</string>
+
+ <string name="ringing-im">
+ Joining voice call...
+ </string>
+ <string name="connected-im">
+ Connected, click Leave Call to hang up
+ </string>
+ <string name="hang_up-im">
+ Left voice call
+ </string>
+ <string name="answering-im">
+ Connecting...
+ </string>
+ <string name="conference-title">
+ Ad-hoc Conference
+ </string>
+ <string name="inventory_item_offered-im">
+ Inventory item offered
+ </string>
+ <string name="share_alert">
+ Drag items from inventory here
+ </string>
+
+
+ <string name="only_user_message">
+ You are the only user in this session.
+ </string>
+ <string name="offline_message">
+ [FIRST] [LAST] is offline.
+ </string>
+ <string name="invite_message">
+ Click the [BUTTON NAME] button to accept/connect to this voice chat.
+ </string>
+ <string name="muted_message">
+ You have blocked this Resident. Sending a message will automatically unblock them.
+ </string>
+ <!--Some times string name is getting from the body of server response.
+ For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post.
+ In case of the EXT-3115 issue 'generic' is passed into the gIMMgr::showSessionStartError as a string name.
+ Also there are some other places where "generic" is used.
+ So, let add string with name="generic" with the same value as "generic_request_error" -->
+ <string name="generic">
+ Error making request, please try again later.
+ </string>
+ <string name="generic_request_error">
+ Error making request, please try again later.
+ </string>
+ <string name="insufficient_perms_error">
+ You do not have sufficient permissions.
+ </string>
+ <string name="session_does_not_exist_error">
+ The session no longer exists
+ </string>
+ <string name="no_ability_error">
+ You do not have that ability.
+ </string>
+ <string name="no_ability">
+ You do not have that ability.
+ </string>
+ <string name="not_a_mod_error">
+ You are not a session moderator.
+ </string>
+ <!--Some times string name is getting from the body of server response.
+ For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post.
+ In case of the EXT-3562 issue 'muted' is passed into the gIMMgr::showSessionStartError as a string name.
+ So, let add string with name="muted" with the same value as "muted_error" -->
+ <string name="muted">
+ A group moderator disabled your text chat.
+ </string>
+ <string name="muted_error">
+ A group moderator disabled your text chat.
+ </string>
+ <string name="add_session_event">
+ Unable to add users to chat session with [RECIPIENT].
+ </string>
+ <!--Some times string name is getting from the body of server response.
+ For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post.
+ In case of the EXT-3562 issue 'message' is passed into the gIMMgr::showSessionStartError as a string name.
+ So, let add string with name="message" with the same value as "message_session_event" -->
+ <string name="message">
+ Unable to send your message to the chat session with [RECIPIENT].
+ </string>
+ <string name="message_session_event">
+ Unable to send your message to the chat session with [RECIPIENT].
+ </string>
+ <string name="mute">
+ Error while moderating.
+ </string>
+ <!--Some times string name is getting from the body of server response.
+ For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post.
+ In case of the EXT-3459 issue 'removed' is passed into the gIMMgr::showSessionStartError as a string name.
+ So, let add string with name="removed" with the same value as "removed_from_group" -->
+ <string name="removed">
+ You have been removed from the group.
+ </string>
+ <string name="removed_from_group">
+ You have been removed from the group.
+ </string>
+ <string name="close_on_no_ability">
+ You no longer have the ability to be in the chat session.
+ </string>
+ <string name="unread_chat_single">
+ [SOURCES] has said something new
+ </string>"
+ <string name="unread_chat_multiple">
+ [SOURCES] have said something new
+ </string>"
+</strings>
diff --git a/indra/newview/skins/default/xui/en/teleport_strings.xml b/indra/newview/skins/default/xui/en/teleport_strings.xml
new file mode 100644
index 0000000000..e8f6b1319a
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/teleport_strings.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<teleport_messages>
+ <message_set name="errors">
+ <message name="invalid_tport">
+ Problem encountered processing your teleport request. You may need to log back in before you can teleport.
+If you continue to get this message, please check the [SUPPORT_SITE].
+ </message>
+ <message name="invalid_region_handoff">
+ Problem encountered processing your region crossing. You may need to log back in before you can cross regions.
+If you continue to get this message, please check the [SUPPORT_SITE].
+ </message>
+ <message name="blocked_tport">
+ Sorry, teleport is currently blocked. Try again in a moment.
+If you still cannot teleport, please log out and log back in to resolve the problem.
+ </message>
+ <message name="nolandmark_tport">
+ Sorry, but system was unable to locate landmark destination.
+ </message>
+ <message name="timeout_tport">
+ Sorry, but system was unable to complete the teleport connection.
+Try again in a moment.
+ </message>
+ <message name="noaccess_tport">
+ Sorry, you do not have access to that teleport destination.
+ </message>
+ <message name="missing_attach_tport">
+ Your attachments have not arrived yet. Try waiting for a few more seconds or log out and back in again before attempting to teleport.
+ </message>
+ <message name="too_many_uploads_tport">
+ The asset queue in this region is currently clogged so your teleport request will not be able to succeed in a timely manner. Please try again in a few minutes or go to a less busy area.
+ </message>
+ <message name="expired_tport">
+ Sorry, but the system was unable to complete your teleport request in a timely fashion. Please try again in a few minutes.
+ </message>
+ <message name="expired_region_handoff">
+ Sorry, but the system was unable to complete your region crossing in a timely fashion. Please try again in a few minutes.
+ </message>
+ <message name="no_host">
+ Unable to find teleport destination. The destination may be temporarily unavailable or no longer exists. Please try again in a few minutes.
+ </message>
+ <message name="no_inventory_host">
+ The inventory system is currently unavailable.
+ </message>
+ </message_set>
+ <message_set name="progress">
+ <message name="sending_dest">
+ Sending to destination.
+ </message>
+ <message name="redirecting">
+ Redirecting to different location.
+ </message>
+ <message name="relaying">
+ Relaying to destination.
+ </message>
+ <message name="sending_home">
+ Sending home location request.
+ </message>
+ <message name="sending_landmark">
+ Sending landmark location request.
+ </message>
+ <message name="completing">
+ Completing teleport.
+ </message>
+ <message name="resolving">
+ Resolving destination.
+ </message>
+ <message name="contacting">
+ Contacting new region.
+ </message>
+ <message name="arriving">
+ Arriving...
+ </message>
+ <message name="requesting">
+ Requesting Teleport...
+ </message>
+ </message_set>
+</teleport_messages>
diff --git a/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml b/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml
new file mode 100644
index 0000000000..102dc0c16d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<accordion_tab
+ header_bg_color="DkGray2"
+ header_collapse_img="Accordion_ArrowClosed_Off"
+ header_collapse_img_pressed="Accordion_ArrowClosed_Press"
+ header_expand_img="Accordion_ArrowOpened_Off"
+ header_expand_img_pressed="Accordion_ArrowOpened_Press"
+ header_image="Accordion_Off"
+ header_image_over="Accordion_Over"
+ header_image_pressed="Accordion_Press"
+ header_image_focused="Accordion_Selected"
+ header_text_color="LtGray"
+ font="SansSerif"
+ />
diff --git a/indra/newview/skins/default/xui/en/widgets/avatar_icon.xml b/indra/newview/skins/default/xui/en/widgets/avatar_icon.xml
new file mode 100644
index 0000000000..a35e2c3663
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/avatar_icon.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+
+<avatar_icon default_icon_name="Generic_Person_Large">
+</avatar_icon>
diff --git a/indra/newview/skins/default/xui/en/widgets/button.xml b/indra/newview/skins/default/xui/en/widgets/button.xml
new file mode 100644
index 0000000000..51f85e65e2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/button.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- Additional attributes:
+ image_pressed
+ image_pressed_selected
+ -->
+<button image_unselected="PushButton_Off"
+ image_selected="PushButton_Selected"
+ image_disabled_selected="PushButton_Selected_Disabled"
+ image_disabled="PushButton_Disabled"
+ label_color="ButtonLabelColor"
+ label_color_selected="ButtonLabelSelectedColor"
+ label_color_disabled="ButtonLabelDisabledColor"
+ label_color_disabled_selected="ButtonLabelSelectedDisabledColor"
+ highlight_color="ButtonUnselectedFgColor"
+ image_color="ButtonImageColor"
+ image_color_disabled="ButtonImageColor"
+ flash_color="ButtonFlashBgColor"
+ font="SansSerifSmall"
+ hover_glow_amount="0.15"
+ halign="center"
+ pad_bottom="3"
+ scale_image="true">
+</button>
diff --git a/indra/newview/skins/default/xui/en/widgets/chat_history.xml b/indra/newview/skins/default/xui/en/widgets/chat_history.xml
new file mode 100644
index 0000000000..ef885e8045
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/chat_history.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chat_history
+ message_header="panel_chat_header.xml"
+ message_separator="panel_chat_separator.xml"
+ left_text_pad="10"
+ right_text_pad="15"
+ left_widget_pad="0"
+ right_widget_pad="10"
+ top_separator_pad="1"
+ bottom_separator_pad="1"
+ top_header_pad="12"
+ bottom_header_pad="5"
+ max_length="2147483647"
+ track_bottom="true"
+ name="chat_history"
+ type="string"
+ word_wrap="true"
+ line_spacing.multiple="1.0"
+ font="SansSerif">
+ <more_chat_text
+ mouse_opaque="true"
+ word_wrap="true"
+ />
+</chat_history> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/check_box.xml b/indra/newview/skins/default/xui/en/widgets/check_box.xml
new file mode 100644
index 0000000000..726ae803fe
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/check_box.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<check_box text_enabled_color="LabelTextColor"
+ text_disabled_color="LabelDisabledColor"
+ font="SansSerifSmall"
+ follows="left|top">
+ <check_box.label_text name="checkbox label" />
+ <check_box.check_button name="CheckboxCtrl Button"
+ commit_on_return="false"
+ label=""
+ is_toggle="true"
+ font="SansSerif"
+ scale_image="false"
+ image_unselected="Checkbox_Off"
+ image_selected="Checkbox_On"
+ image_disabled="Checkbox_Off_Disabled"
+ image_disabled_selected="Checkbox_On_Disabled"
+ image_pressed="Checkbox_Press"
+ image_pressed_selected="Checkbox_On_Press" />
+</check_box>
diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml
new file mode 100644
index 0000000000..63f08a4250
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/chiclet_im_adhoc.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<chiclet_im_adhoc
+ height="23"
+ name="im_adhoc_chiclet"
+ show_speaker="false"
+ width="25">
+ <chiclet_im_adhoc.chiclet_button
+ height="25"
+ image_selected="PushButton_On"
+ image_unselected="PushButton_Off"
+ name="chiclet_button"
+ tab_stop="false"
+ width="25" />
+ <chiclet_im_adhoc.speaker
+ auto_update="true"
+ draw_border="false"
+ height="23"
+ left="25"
+ name="speaker"
+ visible="false"
+ width="20" />
+ <chiclet_im_adhoc.avatar_icon
+ bottom="3"
+ follows="left|top|bottom"
+ height="20"
+ left="2"
+ mouse_opaque="true"
+ name="adhoc_icon"
+ width="21" />
+ <chiclet_im_adhoc.unread_notifications
+ halign="center"
+ height="23"
+ left="25"
+ mouse_opaque="false"
+ name="unread"
+ text_color="white"
+ v_pad="3"
+ visible="false"
+ width="20" />
+ <chiclet_im_adhoc.new_message_icon
+ bottom="11"
+ height="14"
+ image_name="Unread_Chiclet"
+ left="12"
+ name="new_message_icon"
+ visible="false"
+ width="14" />
+</chiclet_im_adhoc> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml
new file mode 100644
index 0000000000..372a89cbc7
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/chiclet_im_group.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<chiclet_im_group
+ height="23"
+ name="im_group_chiclet"
+ show_speaker="false"
+ width="25">
+ <chiclet_im_group.chiclet_button
+ height="25"
+ image_selected="PushButton_On"
+ image_unselected="PushButton_Off"
+ name="chiclet_button"
+ tab_stop="false"
+ width="25" />
+ <chiclet_im_group.speaker
+ auto_update="true"
+ draw_border="false"
+ height="25"
+ left="25"
+ name="speaker"
+ visible="false"
+ width="20" />
+ <chiclet_im_group.group_icon
+ bottom="3"
+ default_icon="Generic_Group"
+ follows="left|top|bottom"
+ height="20"
+ left="2"
+ mouse_opaque="false"
+ name="group_icon"
+ width="21" />
+ <chiclet_im_group.unread_notifications
+ height="23"
+ halign="center"
+ left="25"
+ mouse_opaque="false"
+ name="unread"
+ text_color="white"
+ v_pad="3"
+ visible="false"
+ width="20"/>
+ <chiclet_im_group.new_message_icon
+bottom="11"
+ height="14"
+ image_name="Unread_Chiclet"
+ left="12"
+ name="new_message_icon"
+ visible="false"
+ width="14" />
+</chiclet_im_group> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml
new file mode 100644
index 0000000000..99807d4717
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/chiclet_im_p2p.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<chiclet_im_p2p
+ height="23"
+ name="im_p2p_chiclet"
+ show_speaker="false"
+ width="25">
+ <chiclet_im_p2p.chiclet_button
+ height="25"
+ image_selected="PushButton_On"
+ image_unselected="PushButton_Off"
+ name="chiclet_button"
+ tab_stop="false"
+ width="25"/>
+ <chiclet_im_p2p.speaker
+ auto_update="true"
+ draw_border="false"
+ height="23"
+ left="25"
+ name="speaker"
+ visible="false"
+ width="20" />
+ <chiclet_im_p2p.avatar_icon
+ bottom="3"
+ follows="left|top|bottom"
+ height="20"
+ left="2"
+ mouse_opaque="false"
+ name="avatar_icon"
+ width="21" />
+ <chiclet_im_p2p.unread_notifications
+ height="23"
+ halign="center"
+ left="25"
+ mouse_opaque="false"
+ name="unread"
+ text_color="white"
+ v_pad="3"
+ visible="false"
+ width="20"/>
+ <chiclet_im_p2p.new_message_icon
+ bottom="11"
+ height="14"
+ image_name="Unread_Chiclet"
+ left="12"
+ name="new_message_icon"
+ visible="false"
+ width="14" />
+</chiclet_im_p2p>
diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_offer.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_offer.xml
new file mode 100644
index 0000000000..4bc295f747
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/chiclet_offer.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<chiclet_offer
+ height="23"
+ name="offer_chiclet"
+ width="25">
+ <chiclet_offer.chiclet_button
+ height="25"
+ image_selected="PushButton_On"
+ image_unselected="PushButton_Off"
+ name="chiclet_button"
+ tab_stop="false"
+ width="25" />
+ <chiclet_offer.icon
+ bottom="3"
+ default_icon="Generic_Object_Small"
+ follows="all"
+ height="20"
+ left="2"
+ mouse_opaque="false"
+ name="chiclet_icon"
+ width="21" />
+ <chiclet_offer.new_message_icon
+ bottom="11"
+ height="14"
+ image_name="Unread_Chiclet"
+ left="12"
+ name="new_message_icon"
+ visible="false"
+ width="14" />
+</chiclet_offer> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_panel.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_panel.xml
new file mode 100644
index 0000000000..5f51f4afd9
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/chiclet_panel.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<chiclet_panel
+ name="chiclet_panel"
+ chiclet_padding="3"
+ scrolling_offset="40"
+ scroll_button_hpad="0"
+ scroll_ratio="10"
+ min_width="180"
+ /> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml b/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml
new file mode 100644
index 0000000000..db6a9434df
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/chiclet_script.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<chiclet_script
+ height="23"
+ name="script_chiclet"
+ width="25">
+ <chiclet_script.chiclet_button
+ height="25"
+ image_selected="PushButton_On"
+ image_unselected="PushButton_Off"
+ name="chiclet_button"
+ tab_stop="false"
+ width="25"/>
+ <chiclet_script.icon
+ bottom="3"
+ follows="all"
+ height="18"
+ image_name="Generic_Object_Small"
+ left="2"
+ mouse_opaque="false"
+ name="chiclet_icon"
+ width="21"/>
+ <chiclet_script.new_message_icon
+ bottom="11"
+ height="14"
+ image_name="Unread_Chiclet"
+ left="12"
+ name="new_message_icon"
+ visible="false"
+ width="14" />
+</chiclet_script> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/color_swatch.xml b/indra/newview/skins/default/xui/en/widgets/color_swatch.xml
new file mode 100644
index 0000000000..dfd301a770
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/color_swatch.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<color_swatch alpha_background_image="color_swatch_alpha.tga"
+ border_color="ColorSwatchBorderColor"
+ name="color_swatch">
+ <color_swatch.caption_text name="caption"
+ halign="center"
+ follows="left|right|bottom"/>
+</color_swatch>
diff --git a/indra/newview/skins/default/xui/en/widgets/combo_box.xml b/indra/newview/skins/default/xui/en/widgets/combo_box.xml
new file mode 100644
index 0000000000..132bd24bca
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/combo_box.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<combo_box font="SansSerifSmall"
+ list_position="below"
+ max_chars="20"
+ follows="right|top">
+ <combo_box.combo_button name="Combobox Button"
+ hover_glow_amount="0.15"
+ font="SansSerifSmall"
+ scale_image="false"
+ image_unselected="ComboButton_Off"
+ image_selected="ComboButton_Selected"
+ image_disabled="ComboButton_Disabled" />
+ <combo_box.drop_down_button name="Drop Down Button"
+ hover_glow_amount="0.15"
+ font="SansSerifSmall"
+ scale_image="true"
+ pad_right="24"
+ image_unselected="DropDown_Off"
+ image_selected="DropDown_On"
+ image_pressed="DropDown_Press"
+ image_pressed_selected="DropDown_Press"
+ image_disabled="DropDown_Disabled" />
+ <combo_box.combo_list bg_writeable_color="MenuDefaultBgColor"
+ background_visible="true"
+ />
+ <!-- Text is "tentative" if you have typed in a string that does not match
+ any item in the list, but we usually don't care, so use the same color
+ as normal text. -->
+ <combo_box.combo_editor name="Combo Text Entry"
+ select_on_focus="true"
+ font="SansSerifSmall"
+ text_tentative_color="TextFgColor" />
+</combo_box>
diff --git a/indra/newview/skins/default/xui/en/widgets/context_menu.xml b/indra/newview/skins/default/xui/en/widgets/context_menu.xml
new file mode 100644
index 0000000000..459706c689
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/context_menu.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu visible="false"/>
diff --git a/indra/newview/skins/default/xui/en/widgets/drop_down.xml b/indra/newview/skins/default/xui/en/widgets/drop_down.xml
new file mode 100644
index 0000000000..602250ace6
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/drop_down.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<drop_down text_enabled_color="LabelTextColor"
+ text_disabled_color="LabelDisabledColor"
+ font="SansSerifSmall"
+ allow_text_entry="false"
+ follows="left|top">
+ <drop_down.combo_button name="Combobox Button"
+ hover_glow_amount="0.15"
+ font="SansSerifSmall"
+ halign="left"
+ scale_image="true"
+ image_unselected="PushButton_Off"
+ image_selected="PushButton_Selected"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled_Selected"
+ image_overlay="Combobox_Over"
+ image_overlay_alignment="right" />
+ <drop_down.combo_list bg_writeable_color="white" />
+ <drop_down.combo_editor name="Combo Text Entry" visible="false" select_on_focus="true" />
+</drop_down>
diff --git a/indra/newview/skins/default/xui/en/widgets/expandable_text.xml b/indra/newview/skins/default/xui/en/widgets/expandable_text.xml
new file mode 100644
index 0000000000..f59c46b2f5
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/expandable_text.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<expandable_text
+ max_height="300" >
+ <textbox
+ more_label="More"
+ follows="left|top|right"
+ name="text"
+ allow_scroll="true"
+ use_ellipses="true"
+ word_wrap="true"
+ tab_stop="true"
+ v_pad="3"
+ h_pad="4" >
+ </textbox>
+ <scroll
+ name="scroll"
+ follows="all"
+ />
+</expandable_text> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
new file mode 100644
index 0000000000..48baa2812d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<filter_editor
+ clear_button_visible="true"
+ search_button_visible="true"
+ text_pad_left="7"
+ select_on_focus="true"
+ text_tentative_color="TextFgTentativeColor"
+ background_image="TextField_Search_Off"
+ background_image_disabled="TextField_Search_Disabled"
+ background_image_focused="TextField_Search_Active">
+ <search_button label=""
+ top_pad="4"
+ left_pad="4"
+ width="13"
+ height="13"
+ image_unselected="Search"
+ image_selected="Search" />
+ <clear_button label=""
+ image_unselected="Icon_Close_Foreground"
+ image_selected="Icon_Close_Press" />
+</filter_editor>
diff --git a/indra/newview/skins/default/xui/en/widgets/flat_list_view.xml b/indra/newview/skins/default/xui/en/widgets/flat_list_view.xml
new file mode 100644
index 0000000000..888b4eaf7c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/flat_list_view.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<flat_list_view
+ allow_select="true"
+ color="PanelFocusBackgroundColor"
+ item_pad="0"
+ keep_one_selected="true"
+ multi_select="false"
+ opaque="true" /> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/floater.xml b/indra/newview/skins/default/xui/en/widgets/floater.xml
new file mode 100644
index 0000000000..85d0c633af
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/floater.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- See also settings.xml UIFloater* settings for configuration -->
+<floater
+ name="floater"
+ bg_opaque_color="FloaterFocusBackgroundColor"
+ bg_alpha_color="FloaterDefaultBackgroundColor"
+ bg_opaque_image="Window_Foreground"
+ bg_alpha_image="Window_Background"
+ background_visible="true"
+ background_opaque="false"
+ header_height="25"
+ close_image="Icon_Close_Foreground"
+ restore_image="Icon_Restore_Foreground"
+ minimize_image="Icon_Minimize_Foreground"
+ tear_off_image="tearoffbox.tga"
+ dock_image="Icon_Dock_Foreground"
+ help_image="Icon_Help_Foreground"
+ close_pressed_image="Icon_Close_Press"
+ restore_pressed_image="Icon_Restore_Press"
+ minimize_pressed_image="Icon_Minimize_Press"
+ tear_off_pressed_image="tearoff_pressed.tga"
+ dock_pressed_image="Icon_Dock_Press"
+ help_pressed_image="Icon_Help_Press"
+ />
diff --git a/indra/newview/skins/default/xui/en/widgets/flyout_button.xml b/indra/newview/skins/default/xui/en/widgets/flyout_button.xml
new file mode 100644
index 0000000000..a5043c5c14
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/flyout_button.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<flyout_button list_position="below">
+ <action_button scale_image="true"
+ image_selected="SegmentedBtn_Left_Selected"
+ image_unselected="SegmentedBtn_Left_Off"
+ image_disabled="SegmentedBtn_Left_Disabled"/>
+ <combo_button image_selected="ComboButton_Selected"
+ image_unselected="ComboButton_Off"
+ image_disabled="ComboButton_Disabled"
+ pad_right="6"
+ tab_stop="false"/>
+</flyout_button> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/folder_view_item.xml b/indra/newview/skins/default/xui/en/widgets/folder_view_item.xml
new file mode 100644
index 0000000000..e6bdcccfdf
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/folder_view_item.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<folder_view_item
+ folder_arrow_image="Folder_Arrow"
+ folder_indentation="8"
+ item_height="20"
+ item_top_pad="4"
+ selection_image="Rounded_Square"
+ />
diff --git a/indra/newview/skins/default/xui/en/widgets/gesture_combo_list.xml b/indra/newview/skins/default/xui/en/widgets/gesture_combo_list.xml
new file mode 100644
index 0000000000..808683864d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/gesture_combo_list.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<gesture_combo_list
+ follows="right|top">
+ <gesture_combo_list.combo_button
+ name="Combolist Button"
+ label=""
+ layout="topleft"
+ halign="center"
+ hover_glow_amount="0.15"
+ mouse_opaque="false"
+ scale_image="true"
+ image_selected="PushButton_Selected_Press"
+ image_pressed="PushButton_Press"
+ image_pressed_selected="PushButton_Selected_Press"
+ image_unselected="PushButton_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Selected_Disabled" />
+ <gesture_combo_list.combo_list
+ bg_writeable_color="MenuDefaultBgColor"
+ scroll_bar_bg_visible="false" />
+</gesture_combo_list>
diff --git a/indra/newview/skins/default/xui/en/widgets/group_icon.xml b/indra/newview/skins/default/xui/en/widgets/group_icon.xml
new file mode 100644
index 0000000000..58d5e19fcc
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/group_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<group_icon
+ default_icon_name="Generic_Group"
+ image_name="Generic_Group"
+ name="group_icon" />
diff --git a/indra/newview/skins/default/xui/en/widgets/icon.xml b/indra/newview/skins/default/xui/en/widgets/icon.xml
new file mode 100644
index 0000000000..adb743a628
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/icon.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<icon color="1.0 1.0 1.0 1.0"
+ tab_stop="false"
+ mouse_opaque="false"
+ name="icon"
+ follows="left|top">
+</icon>
diff --git a/indra/newview/skins/default/xui/en/widgets/inspector.xml b/indra/newview/skins/default/xui/en/widgets/inspector.xml
new file mode 100644
index 0000000000..8ec206023e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/inspector.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- See also settings.xml UIFloater* settings for configuration -->
+<inspector name="inspector"
+ bg_opaque_color="DkGray_66"
+ background_visible="true"
+ bg_opaque_image="none"
+ background_opaque="true"
+ bg_alpha_image="none"
+ text_color="InspectorTipTextColor"
+ />
diff --git a/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml b/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml
new file mode 100644
index 0000000000..93875d66e6
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ bg_opaque_color="InventoryBackgroundColor"
+ background_visible="true"
+ background_opaque="true"
+ />
diff --git a/indra/newview/skins/default/xui/en/widgets/line_editor.xml b/indra/newview/skins/default/xui/en/widgets/line_editor.xml
new file mode 100644
index 0000000000..a21e3f2645
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/line_editor.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<line_editor background_image="TextField_Off"
+ background_image_disabled="TextField_Disabled"
+ background_image_focused="TextField_Active"
+ select_on_focus="false"
+ handle_edit_keys_directly="false"
+ commit_on_focus_lost="true"
+ ignore_tab="true"
+ cursor_color="TextCursorColor"
+ text_color="TextFgColor"
+ text_pad_left="2"
+ text_readonly_color="TextFgReadOnlyColor"
+ text_tentative_color="TextFgTentativeColor"
+ highlight_color="EmphasisColor"
+ preedit_bg_color="White"
+ mouse_opaque="true"
+ name="line_editor"
+ font="SansSerifSmall">
+</line_editor>
diff --git a/indra/newview/skins/default/xui/en/widgets/list_view.xml b/indra/newview/skins/default/xui/en/widgets/list_view.xml
new file mode 100644
index 0000000000..2e976bc755
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/list_view.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<list_view
+ fg_selected_color="ListViewSelectedFgColor"
+ bg_selected_color="ListViewSelectedBgColor"
+ bg_color="ListViewBgColor"
+ />
diff --git a/indra/newview/skins/default/xui/en/widgets/location_input.xml b/indra/newview/skins/default/xui/en/widgets/location_input.xml
new file mode 100644
index 0000000000..1c0a8ba7c5
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/location_input.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!--
+*TODO: Replace hardcoded buttons width/height with getting this info from the button images.
+ Currently that doesn't work because LLUIImage::getWidth/getHeight() return 1 for the images.
+-->
+<location_input font="SansSerifSmall"
+ add_landmark_image_enabled="Favorite_Star_Active"
+ add_landmark_image_disabled="Favorite_Star_Off"
+ add_landmark_image_hover="Favorite_Star_Over"
+ add_landmark_image_selected="Favorite_Star_Press"
+ add_landmark_hpad="12"
+ icon_hpad="2"
+ allow_text_entry="true"
+ list_position="below"
+ show_text_as_tentative="false"
+ max_chars="20"
+ follows="left|top"
+ allow_new_values="true"
+ >
+ <!-- *NOTE: Tooltips are in strings.xml so they can be localized.
+ See LocationCtrlAddLandmarkTooltip etc. -->
+ <info_button
+ name="Place Information"
+ width="16"
+ height="16"
+ left="6"
+ top="20"
+ follows="left|top"
+ hover_glow_amount="0.15"
+ image_unselected="Info_Off"
+ image_selected="Info_Off"
+ image_disabled_selected="Info_Off"
+ image_disabled="Info_Off" />
+ <add_landmark_button name="Add Landmark"
+ hover_glow_amount="0.15"
+ image_hover_selected="Favorite_Star_Over"
+ image_hover_unselected="Favorite_Star_Over"
+ width="18"
+ height="18"
+ follows="right|top"
+ scale_image="false"
+ top="19"
+ left="-3" />
+ <for_sale_button
+ name="for_sale_btn"
+ image_unselected="Parcel_ForSale_Light"
+ image_selected="Parcel_ForSale_Light"
+ width="22"
+ height="18"
+ follows="right|top"
+ scale_image="false"
+ top="21"
+ />
+ <voice_icon
+ enabled="true"
+ name="voice_icon"
+ width="22"
+ height="18"
+ top="21"
+ follows="right|top"
+ image_name="Parcel_VoiceNo_Light"
+ />
+ <fly_icon
+ name="fly_icon"
+ width="22"
+ height="18"
+ top="21"
+ follows="right|top"
+ image_name="Parcel_FlyNo_Light"
+ />
+ <push_icon
+ name="push_icon"
+ width="22"
+ height="18"
+ top="21"
+ follows="right|top"
+ image_name="Parcel_PushNo_Light"
+ />
+ <build_icon
+ name="build_icon"
+ width="22"
+ height="18"
+ top="21"
+ follows="right|top"
+ image_name="Parcel_BuildNo_Light"
+ />
+ <scripts_icon
+ name="scripts_icon"
+ width="22"
+ height="18"
+ top="21"
+ follows="right|top"
+ image_name="Parcel_ScriptsNo_Light"
+ />
+ <damage_icon
+ name="damage_icon"
+ width="14"
+ height="13"
+ top="25"
+ left="2"
+ follows="right|top"
+ image_name="Parcel_Damage_Dark"
+ />
+ <!-- Default text color is invisible on top of nav bar background -->
+ <damage_text
+ name="damage_text"
+ width="35"
+ height="18"
+ top="16"
+ follows="right|top"
+ halign="right"
+ font="SansSerifSmall"
+ text_color="TextFgColor"
+ />
+ <combo_button
+ name="Location History"
+ label=""
+ pad_right="0"/>
+ <combo_list
+ bg_writeable_color="MenuDefaultBgColor"
+ page_lines="10"
+ scroll_bar_bg_visible="true" />
+ <combo_editor name="Combo Text Entry"
+ text_pad_left="27"
+ select_on_focus="false"
+ font="SansSerifSmall"
+ bevel_style="none"
+ border_style="line"
+ border.border_thickness="0" />
+</location_input>
diff --git a/indra/newview/skins/default/xui/en/widgets/menu.xml b/indra/newview/skins/default/xui/en/widgets/menu.xml
new file mode 100644
index 0000000000..58543338f6
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/menu.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu bg_color="MenuDefaultBgColor"
+ bg_visible="true"
+ drop_shadow="true"
+ tear_off="false"
+ shortcut_pad="15">
+</menu>
diff --git a/indra/newview/skins/default/xui/en/widgets/menu_item.xml b/indra/newview/skins/default/xui/en/widgets/menu_item.xml
new file mode 100644
index 0000000000..c65244ae22
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/menu_item.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- Use this for the top-level menu styling -->
+<menu_item font="SansSerif" />
diff --git a/indra/newview/skins/default/xui/en/widgets/menu_item_call.xml b/indra/newview/skins/default/xui/en/widgets/menu_item_call.xml
new file mode 100644
index 0000000000..24bda97f44
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/menu_item_call.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu_item_call enabled_color="MenuItemEnabledColor"
+ disabled_color="MenuItemDisabledColor"
+ highlight_bg_color="MenuItemHighlightBgColor"
+ highlight_fg_color="MenuItemHighlightFgColor">
+</menu_item_call>
diff --git a/indra/newview/skins/default/xui/en/widgets/menu_item_check.xml b/indra/newview/skins/default/xui/en/widgets/menu_item_check.xml
new file mode 100644
index 0000000000..f6b06cb50b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/menu_item_check.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu_item_check enabled_color="MenuItemEnabledColor"
+ disabled_color="MenuItemDisabledColor"
+ highlight_bg_color="MenuItemHighlightBgColor"
+ highlight_fg_color="MenuItemHighlightFgColor">
+</menu_item_check>
diff --git a/indra/newview/skins/default/xui/en/widgets/menu_item_separator.xml b/indra/newview/skins/default/xui/en/widgets/menu_item_separator.xml
new file mode 100644
index 0000000000..e5cea476da
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/menu_item_separator.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu_item_separator enabled_color="MenuItemEnabledColor"
+ disabled_color="MenuItemDisabledColor"
+ highlight_bg_color="MenuItemHighlightBgColor"
+ highlight_fg_color="MenuItemHighlightFgColor">
+</menu_item_separator>
diff --git a/indra/newview/skins/default/xui/en/widgets/menu_item_tear_off.xml b/indra/newview/skins/default/xui/en/widgets/menu_item_tear_off.xml
new file mode 100644
index 0000000000..185ed6ee3e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/menu_item_tear_off.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- Use "disabled color" to make it look like menu separators -->
+<menu_item_tear_off enabled_color="MenuItemDisabledColor"
+ disabled_color="MenuItemDisabledColor"
+ highlight_bg_color="MenuItemHighlightBgColor"
+ highlight_fg_color="MenuItemHighlightFgColor">
+</menu_item_tear_off>
diff --git a/indra/newview/skins/default/xui/en/widgets/multi_slider.xml b/indra/newview/skins/default/xui/en/widgets/multi_slider.xml
new file mode 100644
index 0000000000..e0900b48f3
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/multi_slider.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<multi_slider text_color="LabelTextColor"
+ text_disabled_color="LabelDisabledColor"
+ draw_track="true"
+ use_triangle="false"
+ font="SansSerifSmall"/>
diff --git a/indra/newview/skins/default/xui/en/widgets/multi_slider_bar.xml b/indra/newview/skins/default/xui/en/widgets/multi_slider_bar.xml
new file mode 100644
index 0000000000..04a2cd635c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/multi_slider_bar.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<multi_slider_bar track_color="MultiSliderTrackColor"
+ thumb_disabled_color="MultiSliderDisabledThumbColor"
+ thumb_outline_color="MultiSliderThumbOutlineColor"
+ thumb_center_color="MultiSliderThumbCenterColor"
+ thumb_center_selected_color="MultiSliderThumbCenterSelectedColor"
+ triangle_color="MultiSliderTriangleColor"
+ draw_track="true"
+ use_triangle="false"
+ thumb_width="8"/>
diff --git a/indra/newview/skins/default/xui/en/widgets/name_editor.xml b/indra/newview/skins/default/xui/en/widgets/name_editor.xml
new file mode 100644
index 0000000000..21ba5c77f8
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/name_editor.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<name_editor default_text="(retrieving)"/> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/output_monitor.xml b/indra/newview/skins/default/xui/en/widgets/output_monitor.xml
new file mode 100644
index 0000000000..9d71ceca2f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/output_monitor.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<output_monitor
+ draw_border="true"
+ follows="top|left"
+ image_mute="Parcel_VoiceNo_Light"
+ image_off="VoicePTT_Off"
+ image_on="VoicePTT_On"
+ image_level_1="VoicePTT_Lvl1"
+ image_level_2="VoicePTT_Lvl2"
+ image_level_3="VoicePTT_Lvl3"
+ mouse_opaque="false"
+ name="output_monitor"
+ />
diff --git a/indra/newview/skins/default/xui/en/widgets/panel.xml b/indra/newview/skins/default/xui/en/widgets/panel.xml
new file mode 100644
index 0000000000..7262c0dc5c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/panel.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- Optional parameters:
+ border - show border around panel
+ bg_opaque_image - image name for "in-front" panel look
+ bg_alpha_image - image name for "in-back" or transparent panel look
+-->
+<panel bg_opaque_color="PanelFocusBackgroundColor"
+ bg_alpha_color="PanelDefaultBackgroundColor"
+ background_visible="false"
+ background_opaque="false"
+ chrome="false"/> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/progress_bar.xml b/indra/newview/skins/default/xui/en/widgets/progress_bar.xml
new file mode 100644
index 0000000000..339e53fbb8
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/progress_bar.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<progress_bar image_bar="ProgressTrack"
+ image_fill="ProgressBar"
+ color_bar.red="0.5764"
+ color_bar.green="0.6627"
+ color_bar.blue="0.8352"
+ color_bar.alpha="1"
+ color_bg.red="0.3254"
+ color_bg.green="0.4000"
+ color_bg.blue="0.5058"
+ color_bg.alpha="1"
+ />
diff --git a/indra/newview/skins/default/xui/en/widgets/radio_group.xml b/indra/newview/skins/default/xui/en/widgets/radio_group.xml
new file mode 100644
index 0000000000..ad7ef5bffc
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/radio_group.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<radio_group draw_border="false"
+ name="radio_group"
+ mouse_opaque="false"
+ follows="left|top"
+ font="SansSerifSmall"/>
diff --git a/indra/newview/skins/default/xui/en/widgets/radio_item.xml b/indra/newview/skins/default/xui/en/widgets/radio_item.xml
new file mode 100644
index 0000000000..3ddf18b2cb
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/radio_item.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<radio_item follows="left|top" font="SansSerif">
+ <radio_item.label_text name="Radio Item label"/>
+ <radio_item.check_button name="Radio control button"
+ image_unselected="RadioButton_Off"
+ image_selected="RadioButton_On"
+ image_disabled="RadioButton_Disabled"
+ image_disabled_selected="RadioButton_On_Disabled"
+ image_pressed="RadioButton_Press"
+ image_pressed_selected="RadioButton_On_Press"/>
+</radio_item>
+
diff --git a/indra/newview/skins/default/xui/en/widgets/scroll_bar.xml b/indra/newview/skins/default/xui/en/widgets/scroll_bar.xml
new file mode 100644
index 0000000000..48bc021e6d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/scroll_bar.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<scroll_bar thumb_image_vertical ="ScrollThumb_Vert"
+ thumb_image_horizontal ="ScrollThumb_Horiz"
+ track_image_vertical ="ScrollTrack_Vert"
+ track_image_horizontal ="ScrollTrack_Horiz"
+ track_color="ScrollbarTrackColor"
+ thumb_color="ScrollbarThumbColor"
+ thickness="15">
+ <up_button image_unselected="ScrollArrow_Up"
+ image_selected="ScrollArrow_Up"
+ scale_image="true" thickness="15"
+ hover_glow_amount="0.35"/>
+ <down_button image_unselected="ScrollArrow_Down"
+ image_selected="ScrollArrow_Down"
+ scale_image="true" thickness="15"
+ hover_glow_amount="0.35"/>
+ <left_button image_unselected="ScrollArrow_Left"
+ image_selected="ScrollArrow_Left"
+ scale_image="true" thickness="15"
+ hover_glow_amount="0.35"/>
+ <right_button image_unselected="ScrollArrow_Right"
+ image_selected="ScrollArrow_Right"
+ scale_image="true" thickness="15"
+ hover_glow_amount="0.35"/>
+</scroll_bar>
diff --git a/indra/newview/skins/default/xui/en/widgets/scroll_column_header.xml b/indra/newview/skins/default/xui/en/widgets/scroll_column_header.xml
new file mode 100644
index 0000000000..f936a1e208
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/scroll_column_header.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<scroll_column_header
+ image_unselected="SegmentedBtn_Middle_Selected"
+ image_selected="SegmentedBtn_Middle_Selected"
+ image_pressed="SegmentedBtn_Middle_Selected_Press"
+ image_disabled="SegmentedBtn_Middle_Disabled"
+ image_disabled_selected="SegmentedBtn_Middle_Selected_Disabled"
+ image_overlay="DisclosureArrow_Opened_Off"
+ image_overlay_alignment="right"
+ halign="left"
+ scale_image="true" />
diff --git a/indra/newview/skins/default/xui/en/widgets/scroll_container.xml b/indra/newview/skins/default/xui/en/widgets/scroll_container.xml
new file mode 100644
index 0000000000..86356ff563
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/scroll_container.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<scroll_container color="black"
+ opaque="false"
+ min_auto_scroll_rate="120"
+ max_auto_scroll_rate="500"/>
diff --git a/indra/newview/skins/default/xui/en/widgets/scroll_list.xml b/indra/newview/skins/default/xui/en/widgets/scroll_list.xml
new file mode 100644
index 0000000000..63166f32b7
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/scroll_list.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<scroll_list fg_unselected_color="ScrollUnselectedColor"
+ fg_selected_color="ScrollSelectedFGColor"
+ bg_selected_color="ScrollSelectedBGColor"
+ fg_disable_color="ScrollDisabledColor"
+ bg_writeable_color="ScrollBgWriteableColor"
+ bg_readonly_color="ScrollBgReadOnlyColor"
+ bg_stripe_color="ScrollBGStripeColor"
+ hovered_color="ScrollHoveredColor"
+ highlighted_color="ScrollHighlightedColor"
+ column_padding="5"
+ draw_stripes="true"
+ scroll_bar_bg_visible="false"
+ scroll_bar_bg_color="black"
+ background_visible="true"
+ heading_height="23"
+ draw_border="false"
+ draw_heading="false"
+ border.name="dig border"
+ border.bevel_style="in" />
diff --git a/indra/newview/skins/default/xui/en/widgets/search_combo_box.xml b/indra/newview/skins/default/xui/en/widgets/search_combo_box.xml
new file mode 100644
index 0000000000..5d429d5b5b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/search_combo_box.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<search_combo_box
+ allow_text_entry="true"
+ list_position="BELOW"
+ show_text_as_tentative="false"
+ dropdown_button_visible="false"
+ max_chars="256"
+ name="parent"
+ allow_new_values="true"
+ background_image="TextField_Search_Off"
+ background_image_disabled="TextField_Search_Disabled"
+ background_image_focused="TextField_Search_Active">
+ <combo_editor
+ name="child1"
+ select_on_focus="true"
+ text_pad_left="30"
+ text_tentative_color="TextFgTentativeColor"
+ background_image="TextField_Search_Off"
+ background_image_disabled="TextField_Search_Disabled"
+ background_image_focused="TextField_Search_Active"/>
+ <combo_list
+ multi_select="false"
+ name="child2"
+ page_lines="10"
+ scroll_bar_bg_visible="true" />
+ <search_button label=""
+ top_pad="5"
+ left_pad="10"
+ name="child3"
+ width="13"
+ height="13"
+ image_unselected="Search"
+ image_selected="Search" />
+</search_combo_box> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/search_editor.xml b/indra/newview/skins/default/xui/en/widgets/search_editor.xml
new file mode 100644
index 0000000000..1616e4c3f7
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/search_editor.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<search_editor
+ clear_button_visible="false"
+ search_button_visible="true"
+ text_pad_left="6"
+ select_on_focus="true"
+ text_tentative_color="TextFgTentativeColor"
+ background_image="TextField_Search_Off"
+ background_image_disabled="TextField_Search_Disabled"
+ background_image_focused="TextField_Search_Active" >
+ <search_button
+ top_pad="4"
+ left_pad="4"
+ width="13"
+ height="13"
+ image_unselected="Search"
+ image_selected="Search" />
+ <clear_button
+ image_unselected="Icon_Close_Foreground"
+ image_selected="Icon_Close_Press" />
+</search_editor>
diff --git a/indra/newview/skins/default/xui/en/widgets/side_tray.xml b/indra/newview/skins/default/xui/en/widgets/side_tray.xml
new file mode 100644
index 0000000000..022564c12f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/side_tray.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<side_tray tab_btn_image="TaskPanel_Tab_Off"
+ tab_btn_image_selected="TaskPanel_Tab_Selected"
+ tab_btn_width="32"
+ tab_btn_height="40"
+ tab_btn_margin="1">
+</side_tray>
diff --git a/indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml b/indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml
new file mode 100644
index 0000000000..bb46ec0954
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<simple_text_editor
+ allow_html="false"
+ mouse_opaque="true"
+ font="SansSerifSmall"
+ max_length="255"
+ embedded_items="false"
+ allow_scroll="true"
+ border_visible="false"
+ word_wrap="false"
+ ignore_tab="true"
+ line_spacing.pixels="1"
+ track_bottom="false"
+ cursor_color="TextCursorColor"
+ default_color="TextDefaultColor"
+ text_color="TextFgColor"
+ text_readonly_color="TextFgReadOnlyColor"
+ h_pad="6"
+ v_pad="4"
+ bg_visible="true"
+ bg_readonly_color="TextBgReadOnlyColor"
+ bg_writeable_color="TextBgWriteableColor"
+ bg_focus_color="TextBgFocusColor">
+ <simple_text_editor.border
+ bevel_style="in"
+ follows="all" />
+</simple_text_editor>
diff --git a/indra/newview/skins/default/xui/en/widgets/slider.xml b/indra/newview/skins/default/xui/en/widgets/slider.xml
new file mode 100644
index 0000000000..f735d09476
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/slider.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<slider name="slider"
+ can_edit_text="false"
+ font="SansSerifSmall"
+ volume="false"
+ mouse_opaque="true"
+ show_text="true"
+ text_color="LabelTextColor"
+ text_disabled_color="LabelDisabledColor">
+ <slider.value_editor name="slider editor"
+ max_length="10"
+ follows="left|bottom"/>
+ <slider.value_text name="slider text"
+ follows="left|bottom"/>
+ <slider.slider_label name="slider label"/>
+</slider>
diff --git a/indra/newview/skins/default/xui/en/widgets/slider_bar.xml b/indra/newview/skins/default/xui/en/widgets/slider_bar.xml
new file mode 100644
index 0000000000..89d5950e98
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/slider_bar.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<slider_bar track_color="SliderTrackColor"
+ thumb_outline_color="SliderThumbOutlineColor"
+ thumb_center_color="SliderThumbCenterColor"
+ thumb_image="SliderThumb_Off"
+ thumb_image_pressed="SliderThumb_Press"
+ thumb_image_disabled="SliderThumb_Disabled"
+ track_image_horizontal="SliderTrack_Horiz"
+ track_image_vertical="SliderTrack_Vert"
+ track_highlight_horizontal_image="SliderTrack_Horiz"
+ track_highlight_vertical_image="SliderTrack_Vert"
+ font="SansSerif" />
diff --git a/indra/newview/skins/default/xui/en/widgets/spinner.xml b/indra/newview/skins/default/xui/en/widgets/spinner.xml
new file mode 100644
index 0000000000..d7af6077e5
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/spinner.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<spinner text_enabled_color="LabelTextColor"
+ text_disabled_color="LabelDisabledColor"
+ font="SansSerifSmall"
+ decimal_digits="3"
+ label_width="40" >
+ <spinner.up_button name="SpinCtrl Up"
+ image_unselected="Stepper_Up_Off"
+ image_selected="Stepper_Up_Press"
+ tab_stop="false"
+ follows="left|bottom" />
+ <spinner.down_button name="SpinCtrl Down"
+ image_unselected="Stepper_Down_Off"
+ image_selected="Stepper_Down_Press"
+ tab_stop="false"
+ follows="left|bottom" />
+</spinner> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/split_button.xml b/indra/newview/skins/default/xui/en/widgets/split_button.xml
new file mode 100644
index 0000000000..2ff9ada90a
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/split_button.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<split_button
+ font="SansSerifSmall"
+ arrow_position="left"
+ follows="right|top">
+ <split_button.items_panel
+ background_visible="true"
+ border="true"
+ bg_alpha_color="1 1 1 1"
+ bg_opaq_color="1 1 1 1"
+ scale_image="false"
+ image_selected="SegmentedBtn_Left_Selected"
+ image_unselected="SegmentedBtn_Left_Off"
+ layout="topleft"
+ name="item_buttons"
+ />
+ <split_button.arrow_button
+ name="Arrow Button"
+ label=""
+ font="SansSerifSmall"
+ scale_image="false"
+ image_selected="SegmentedBtn_Right_Selected"
+ image_unselected="SegmentedBtn_Right_Off"
+ />
+</split_button>
diff --git a/indra/newview/skins/default/xui/en/widgets/tab_container.xml b/indra/newview/skins/default/xui/en/widgets/tab_container.xml
new file mode 100644
index 0000000000..3f5a4b8379
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/tab_container.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!--
+label_pad_bottom - vertical padding under tab button labels
+label_pad_left - padding to the left of tab button labels
+-->
+<tab_container tab_min_width="60"
+ tab_max_width="150"
+ halign="center"
+ font="SansSerifSmall"
+ tab_height="21"
+ label_pad_bottom="2"
+ label_pad_left="4">
+ <first_tab tab_top_image_unselected="TabTop_Left_Off"
+ tab_top_image_selected="TabTop_Left_Selected"
+ tab_bottom_image_unselected="Toolbar_Left_Off"
+ tab_bottom_image_selected="Toolbar_Left_Selected"
+ tab_left_image_unselected="TabTop_Middle_Off"
+ tab_left_image_selected="TabTop_Middle_Selected"/>
+ <middle_tab tab_top_image_unselected="TabTop_Middle_Off"
+ tab_top_image_selected="TabTop_Middle_Selected"
+ tab_bottom_image_unselected="Toolbar_Middle_Off"
+ tab_bottom_image_selected="Toolbar_Middle_Selected"
+ tab_left_image_unselected="SegmentedBtn_Left_Disabled"
+ tab_left_image_selected="SegmentedBtn_Left_Off"/>
+ <last_tab tab_top_image_unselected="TabTop_Right_Off"
+ tab_top_image_selected="TabTop_Right_Selected"
+ tab_bottom_image_unselected="Toolbar_Right_Off"
+ tab_bottom_image_selected="Toolbar_Right_Selected"
+ tab_left_image_unselected="SegmentedBtn_Left_Disabled"
+ tab_left_image_selected="SegmentedBtn_Left_Off"/>
+</tab_container>
diff --git a/indra/newview/skins/default/xui/en/widgets/talk_button.xml b/indra/newview/skins/default/xui/en/widgets/talk_button.xml
new file mode 100644
index 0000000000..68cf082c35
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/talk_button.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- Derives from LLUICtrl -->
+<talk_button>
+ <!-- To make speak button look green when selected set:
+ image_selected="SegmentedBtn_Left_Selected"
+ image_unselected="SegmentedBtn_Left_Off"
+ -->
+ <speak_button
+ follows="left|right"
+ image_selected="SegmentedBtn_Left_Selected_Press"
+ image_unselected="SegmentedBtn_Left_Off"
+ image_pressed="SegmentedBtn_Left_Selected_Press"
+ image_pressed_selected="SegmentedBtn_Left_Selected_Press"
+ name="speak_btn"
+ label="Speak"
+ label_selected="Speak"
+ tab_stop="false"
+ />
+ <show_button
+ follows="right"
+ name="speak_flyout_btn"
+ label=""
+ left="0"
+ top="0"
+ right="20"
+ bottom="0"
+ tab_stop="false"
+ is_toggle="true"
+ image_selected="SegmentedBtn_Right_Selected_Press"
+ image_unselected="SegmentedBtn_Right_Off"
+ image_pressed="SegmentedBtn_Right_Press"
+ image_pressed_selected="SegmentedBtn_Right_Selected_Press"
+ image_overlay="Arrow_Small_Up"
+ />
+ <monitor
+ follows="right"
+ name="monitor"
+ left="0"
+ top="18"
+ right="18"
+ bottom="0"
+ />
+</talk_button>
diff --git a/indra/newview/skins/default/xui/en/widgets/teleport_history_menu_item.xml b/indra/newview/skins/default/xui/en/widgets/teleport_history_menu_item.xml
new file mode 100644
index 0000000000..4f574d75d5
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/teleport_history_menu_item.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- Menu items for the back button drop-down menu of locations.
+ Based on menu_item_call.xml -->
+<teleport_history_menu_item
+ back_item_font="SansSerif"
+ current_item_font="SansSerifBold"
+ forward_item_font="SansSerif"
+ />
diff --git a/indra/newview/skins/default/xui/en/widgets/text.xml b/indra/newview/skins/default/xui/en/widgets/text.xml
new file mode 100644
index 0000000000..855584a0db
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/text.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<text allow_html="true"
+ mouse_opaque="false"
+ name="text_box"
+ font="SansSerifSmall"
+ font_shadow="none"
+ tab_stop="false"
+ halign="left"
+ hover_color="LabelSelectedColor"
+ h_pad="0"
+ allow_scroll="false"
+ text_readonly_color="LabelDisabledColor"
+ bg_writeable_color="FloaterDefaultBackgroundColor"
+ use_ellipses="false"
+ bg_visible="false"
+ border_visible="false"
+ hover="false"
+ text_color="LabelTextColor"
+ v_pad="0"
+ max_length="4096"/>
diff --git a/indra/newview/skins/default/xui/en/widgets/text_editor.xml b/indra/newview/skins/default/xui/en/widgets/text_editor.xml
new file mode 100644
index 0000000000..23ca8ea338
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/text_editor.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- Core parameters are in simple_text_editor.xml -->
+<text_editor
+ allow_html="false"/>
diff --git a/indra/newview/skins/default/xui/en/widgets/textbase.xml b/indra/newview/skins/default/xui/en/widgets/textbase.xml
new file mode 100644
index 0000000000..f4dc192bc3
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/textbase.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<textbase clip_partial="false"
+ font="SansSerif"/>
diff --git a/indra/newview/skins/default/xui/en/widgets/texture_picker.xml b/indra/newview/skins/default/xui/en/widgets/texture_picker.xml
new file mode 100644
index 0000000000..33c3475eb2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/texture_picker.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<texture_picker border_color="DefaultHighlightLight">
+ <multiselect_text font="SansSerifSmall"/>
+ <caption_text text="Multiple"
+ halign="center"
+ font="SansSerifSmall"/>
+ <border bevel_style="in"/>
+</texture_picker>
+
diff --git a/indra/newview/skins/default/xui/en/widgets/toggleable_menu.xml b/indra/newview/skins/default/xui/en/widgets/toggleable_menu.xml
new file mode 100644
index 0000000000..48950a98ad
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/toggleable_menu.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu visible="false"/>
diff --git a/indra/newview/skins/default/xui/en/widgets/tool_tip.xml b/indra/newview/skins/default/xui/en/widgets/tool_tip.xml
new file mode 100644
index 0000000000..a19201f7c3
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/tool_tip.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- See also settings.xml UIFloater* settings for configuration -->
+<tool_tip name="tooltip"
+ max_width="200"
+ padding="4"
+ wrap="true"
+ font="SansSerif"
+ bg_opaque_image="Tooltip"
+ background_opaque="true"
+ background_visible="true"
+ text_color="ToolTipTextColor"
+ />
diff --git a/indra/newview/skins/default/xui/en/widgets/ui_ctrl.xml b/indra/newview/skins/default/xui/en/widgets/ui_ctrl.xml
new file mode 100644
index 0000000000..f4dbb8f404
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/ui_ctrl.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- Global settings for all widgets ("UI Controls") -->
+<!-- The params in this file aren't currently getting loaded in OSX -->
+<ui_ctrl
+ />
diff --git a/indra/newview/skins/default/xui/en/widgets/view_border.xml b/indra/newview/skins/default/xui/en/widgets/view_border.xml
new file mode 100644
index 0000000000..0b0a9beb95
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/view_border.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<view_border highlight_light_color="DefaultHighlightLight"
+ highlight_dark_color="DefaultHighlightDark"
+ shadow_light_color="DefaultShadowLight"
+ shadow_dark_color="DefaultShadowDark"
+ border_thickness="1"
+ border_style="line"
+ bevel_style="out"/> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/web_browser.xml b/indra/newview/skins/default/xui/en/widgets/web_browser.xml
new file mode 100644
index 0000000000..118d63bbf0
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/web_browser.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<web_browser border_visible="true"/>
diff --git a/indra/newview/skins/default/xui/en/xui_version.xml b/indra/newview/skins/default/xui/en/xui_version.xml
new file mode 100644
index 0000000000..0e777751d3
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/xui_version.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<xui_version>
+ 1.0
+</xui_version>
diff --git a/indra/newview/skins/default/xui/es/floater_about.xml b/indra/newview/skins/default/xui/es/floater_about.xml
index d6fbc38752..e8e38316f9 100644
--- a/indra/newview/skins/default/xui/es/floater_about.xml
+++ b/indra/newview/skins/default/xui/es/floater_about.xml
@@ -1,10 +1,19 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_about" title="Acerca de Second Life">
+<floater name="floater_about" title="ACERCA DE [CAPITALIZED_APP_NAME]">
+<tab_container name="about_tab">
+ <panel name="credits_panel">
<text_editor name="credits_editor">
- Le ofrecen Second Life Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, y otros muchos.
+ Le ofrecen Second Life Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, Michon, Jenelle, Geo, Siz, Shapiro, Pete, Calyle, Selene, Allen, Phoebe, Goldin, Kimmora, Dakota, Slaton, Lindquist, Zoey, Hari, Othello, Rohit, Sheldon, Petra, Viale, Gordon, Kaye, Pink, Ferny, Emerson, Davy, Bri, Chan, Juan, Robert, Terrence, Nathan, Carl, y otros muchos.
- Gracias a todos estos residentes por contribuir a garantizar que, por el momento, esta es la mejor versión:
+ Gracias a todos estos residentes por contribuir a garantizar que esta es la mejor versión: able whitman, Adeon Writer, adonaira aabye, Aeron Kohime, Agathos Frascati, Aimee Trescothick, Aleric Inglewood, Alissa Sabre, Aminom Marvin, Angela Talamasca, Aralara Rajal, Armin Weatherwax, Ashrilyn Hayashida, Athanasius Skytower, Aura Dirval, Barney Boomslang, Biancaluce Robbiani, Biker Offcourse, Borg Capalini, Bulli Schumann, catherine pfeffer, Chalice Yao, Corre Porta, Court Goodman, Cummere Mayo, Dale Innis, Darien Caldwell, Darjeeling Schoonhoven, Daten Thielt, dimentox travanti, Dirk Talamasca, Drew Dwi, Duckless Vandyke, Elanthius Flagstaff, Electro Burnstein, emiley tomsen, Escort DeFarge, Eva Rau, Ezian Ecksol, Fire Centaur, Fluf Fredriksson, Francisco Koolhoven, Frontera Thor, Frungi Stastny, Gally Young, gearsawe stonecutter, Gigs Taggart, Gordon Wendt, Gudmund Shepherd, Gypsy Paz, Harleen Gretzky, Henri Beauchamp, Inma Rau, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Jessicka Graves, Joeseph Albanese, Joshua Philgarlic, Khyota Wulluf, kirstenlee Cinquetti, Latif Khalifa, Lex Neva, Lilibeth Andree, Lisa Lowe, Lunita Savira, Loosey Demonia, lum pfohl, Marcos Fonzarelli, MartinRJ Fayray, Marusame Arai, Matthew Dowd, Maya Remblai, McCabe Maxsted, Meghan Dench, Melchoir Tokhes, Menos Short, Michelle2 Zenovka, Mimika Oh, Minerva Memel, Mm Alder, Ochi Wolfe, Omei Turnbull, Pesho Replacement, Phantom Ninetails, phoenixflames kukulcan, Polo Gufler, prez pessoa, princess niven, Prokofy Neva, Qie Niangao, Rem Beattie, RodneyLee Jessop, Saijanai Kuhn, Seg Baphomet, Sergen Davies, Shirley Marquez, SignpostMarv Martin, Sindy Tsure, Sira Arbizu, Skips Jigsaw, Sougent Harrop, Spritely Pixel, Squirrel Wood, StarSong Bright, Subversive Writer, Sugarcult Dagger, Sylumm Grigorovich, Tammy Nowotny, Tanooki Darkes, Tayra Dagostino, Theoretical Chemistry, Thickbrick Sleaford, valerie rosewood, Vex Streeter, Vixen Heron, Whoops Babii, Winter Ventura, Xiki Luik, Yann Dufaux, Yina Yao, Yukinoroh Kamachi, Zolute Infinity, Zwagoth Klaar
+
+
+ Para tener éxito en los negocios, se atrevido, se el primero, se diferente. (Henry Marchant)
+ </text_editor>
+ </panel>
+ <panel name="licenses_panel">
+ <text_editor name="credits_editor">
3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
APR Copyright (C) 2000-2004 The Apache Software Foundation
cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
@@ -26,10 +35,9 @@
All rights reserved. See licenses.txt for details.
Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
-
-
- Para tener éxito en los negocios, se atrevido, se el primero, se diferente. (Henry Marchant)
</text_editor>
+ </panel>
+</tab_container>
<string name="you_are_at">
Está en [POSITION]
</string>
diff --git a/indra/newview/skins/default/xui/es/floater_about_land.xml b/indra/newview/skins/default/xui/es/floater_about_land.xml
index 767b384a2d..7575df4b98 100644
--- a/indra/newview/skins/default/xui/es/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/es/floater_about_land.xml
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterland" title="Acerca del terreno">
+<floater name="floaterland" title="ACERCA DEL TERRENO">
<tab_container name="landtab">
<panel label="General" name="land_general_panel">
- <text length="1" name="Name:" type="string">
+ <text name="Name:">
Nombre:
</text>
- <text length="1" name="Description:" type="string">
+ <text name="Description:">
Descripción:
</text>
<text name="LandType">
@@ -20,56 +20,56 @@
<text name="ContentRatingText">
&apos;Adult&apos;
</text>
- <text length="1" name="Owner:" type="string">
+ <text name="Owner:">
Propietario:
</text>
- <text length="1" name="OwnerText" type="string">
+ <text name="OwnerText">
Leyla Linden
</text>
<button label="Perfil..." label_selected="Perfil..." name="Profile..."/>
- <text length="1" name="Group:" type="string">
+ <text name="Group:">
Grupo:
</text>
<button label="Configurar..." label_selected="Configurar..." name="Set..."/>
<check_box label="Permitir transferir al grupo" name="check deed" tool_tip="Un oficial del grupo puede transferir este terreno al grupo. El terreno será apoyado por el grupo en sus asignaciones de terreno."/>
<button label="Transferir..." label_selected="Transferir..." name="Deed..." tool_tip="Sólo si es usted un oficial del grupo seleccionado puede transferir terreno."/>
<check_box label="El propietario hace una contribución transfiriendo" name="check contrib" tool_tip="Cuando el terreno se transfiere al grupo, el antiguo propietario contribuye con una asignación suficiente de terreno."/>
- <text length="1" name="For Sale:" type="string">
+ <text name="For Sale:">
En venta:
</text>
- <text length="1" name="Not for sale." type="string">
+ <text name="Not for sale.">
No está en venta.
</text>
- <text length="1" name="For Sale: Price L$[PRICE]." type="string">
+ <text name="For Sale: Price L$[PRICE].">
Precio: [PRICE] L$ ([PRICE_PER_SQM] L$/m²).
</text>
<button label="Vender el terreno..." label_selected="Vender el terreno..." name="Sell Land..."/>
- <text length="1" name="For sale to" type="string">
+ <text name="For sale to">
En venta a: [BUYER]
</text>
- <text length="1" name="Sell with landowners objects in parcel." type="string">
+ <text width="216" name="Sell with landowners objects in parcel.">
Los objetos se incluyen en la venta.
</text>
- <text length="1" name="Selling with no objects in parcel." type="string">
+ <text width="216" name="Selling with no objects in parcel.">
Los objetos no se incluyen en la venta.
</text>
- <button font="SansSerifSmall" left="275" width="165" label="Cancelar la venta del terreno" label_selected="Cancelar la venta del terreno" name="Cancel Land Sale"/>
- <text length="1" name="Claimed:" type="string">
+ <button font="SansSerifSmall" bottom="-245" left="275" width="165" label="Cancelar la venta del terreno" label_selected="Cancelar la venta del terreno" name="Cancel Land Sale"/>
+ <text name="Claimed:">
Reclamada:
</text>
- <text length="1" name="DateClaimText" type="string">
+ <text name="DateClaimText">
Mar 15 Ago 15 13:47:25 2006
</text>
- <text length="1" name="PriceLabel" type="string">
+ <text name="PriceLabel">
Superficie:
</text>
- <text length="1" name="PriceText" type="string">
+ <text name="PriceText">
4048 m²
</text>
- <text length="1" name="Traffic:" type="string">
+ <text name="Traffic:">
Tráfico:
</text>
- <text length="1" name="DwellText" type="string">
+ <text name="DwellText">
0
</text>
<button label="Comprar terreno..." label_selected="Comprar terreno..." left="130" name="Buy Land..." width="125"/>
@@ -78,76 +78,76 @@
<button label="Abandonar el terreno..." label_selected="Abandonar el terreno..." name="Abandon Land..."/>
<button label="Reclamar el terreno..." label_selected="Reclamar el terreno..." name="Reclaim Land..."/>
<button label="Venta Linden..." label_selected="Venta Linden..." name="Linden Sale..." tool_tip="El terreno debe estar en propiedad, con contenido, y no estar en subasta."/>
- <string name="new users only">
+ <panel.string name="new users only">
Sólo usuarios nuevos
- </string>
- <string name="anyone">
+ </panel.string>
+ <panel.string name="anyone">
Cualquiera
- </string>
- <string name="area_text">
+ </panel.string>
+ <panel.string name="area_text">
Superficie
- </string>
- <string name="area_size_text">
+ </panel.string>
+ <panel.string name="area_size_text">
[AREA] m²
- </string>
- <string name="auction_id_text">
+ </panel.string>
+ <panel.string name="auction_id_text">
ID de la subasta: [ID]
- </string>
- <string name="need_tier_to_modify">
+ </panel.string>
+ <panel.string name="need_tier_to_modify">
Debe aprobar su compra para modificar este terreno.
- </string>
- <string name="group_owned_text">
+ </panel.string>
+ <panel.string name="group_owned_text">
(Propiedad del grupo)
- </string>
- <string name="profile_text">
+ </panel.string>
+ <panel.string name="profile_text">
Perfil...
- </string>
- <string name="info_text">
+ </panel.string>
+ <panel.string name="info_text">
Información...
- </string>
- <string name="public_text">
+ </panel.string>
+ <panel.string name="public_text">
(público)
- </string>
- <string name="none_text">
+ </panel.string>
+ <panel.string name="none_text">
(ninguno)
- </string>
- <string name="sale_pending_text">
+ </panel.string>
+ <panel.string name="sale_pending_text">
(Venta pendiente)
- </string>
- <string name="no_selection_text">
+ </panel.string>
+ <panel.string name="no_selection_text">
No se ha seleccionado una parcela.
Vaya al menú Mundo &gt; Acerca del terreno o seleccione otra parcela para ver sus características.
- </string>
+ </panel.string>
</panel>
<panel label="Contrato" name="land_covenant_panel">
<text name="estate_section_lbl">
Estado:
</text>
- <text length="1" name="estate_name_lbl" type="string">
+ <text name="estate_name_lbl">
Nombre:
</text>
- <text length="1" name="estate_name_text" type="string">
+ <text name="estate_name_text">
mainland
</text>
- <text length="1" name="estate_owner_lbl" type="string">
+ <text name="estate_owner_lbl">
Propietario:
</text>
- <text length="1" name="estate_owner_text" type="string">
+ <text name="estate_owner_text">
(nadie)
</text>
- <text_editor length="1" name="covenant_editor" type="string">
+ <text_editor name="covenant_editor">
No se ha aportado un contrato para este estado.
</text_editor>
- <text length="1" name="covenant_timestamp_text" type="string">
+ <text name="covenant_timestamp_text">
Última modificación, Dic Miér 31 16:00:00 1969
</text>
<text name="region_section_lbl">
Región:
</text>
- <text length="1" name="region_name_lbl" type="string">
+ <text name="region_name_lbl">
Nombre:
</text>
- <text length="1" name="region_name_text" type="string">
+ <text name="region_name_text">
leyla
</text>
<text name="region_landtype_lbl">
@@ -165,91 +165,91 @@ Vaya al menú Mundo &gt; Acerca del terreno o seleccione otra parcela para ver s
<text name="resellable_lbl">
Revender:
</text>
- <text length="1" name="resellable_clause" type="string">
+ <text name="resellable_clause">
El terreno de esta región no se podrá revender.
</text>
<text name="changeable_lbl">
Dividir:
</text>
- <text length="1" name="changeable_clause" type="string">
+ <text name="changeable_clause">
El terreno de esta región no se podrá unir/dividir.
</text>
- <string name="can_resell">
+ <panel.string name="can_resell">
El terreno comprado en esta región se podrá revender.
- </string>
- <string name="can_not_resell">
+ </panel.string>
+ <panel.string name="can_not_resell">
El terreno comprado en esta región no se podrá revender.
- </string>
- <string name="can_change">
+ </panel.string>
+ <panel.string name="can_change">
El terreno comprado en esta región se podrá unir o dividir.
- </string>
- <string name="can_not_change">
+ </panel.string>
+ <panel.string name="can_not_change">
El terreno comprado en esta región no se podrá unir o dividir.
- </string>
+ </panel.string>
</panel>
<panel label="Objetos" name="land_objects_panel">
<text name="parcel_object_bonus">
Plus de objetos en la región: [BONUS]
</text>
- <text length="1" name="Simulator primitive usage:" type="string">
+ <text name="Simulator primitive usage:">
Simulador de uso de prims:
</text>
- <text name="objects_available" left="214" width="230" >
+ <text name="objects_available" left="204" width="250" >
[COUNT] de un máximo de [MAX] ([AVAILABLE] disponibles)
</text>
- <string name="objects_available_text">
+ <panel.string name="objects_available_text">
[COUNT] de un máximo de [MAX] ([AVAILABLE] disponibles)
- </string>
- <string name="objects_deleted_text">
+ </panel.string>
+ <panel.string name="objects_deleted_text">
[COUNT] de un máximo de [MAX] ([DELETED] se borrarán)
- </string>
- <text length="1" name="Primitives parcel supports:" type="string" width="200">
+ </panel.string>
+ <text name="Primitives parcel supports:" width="200">
Prims que admite la parcela:
</text>
- <text name="object_contrib_text" left="214" width="152">
+ <text name="object_contrib_text" left="204" width="152">
[COUNT]
</text>
- <text length="1" name="Primitives on parcel:" type="string">
+ <text name="Primitives on parcel:">
Prims en la parcela:
</text>
- <text name="total_objects_text" left="214" width="48">
+ <text name="total_objects_text" left="204" width="48">
[COUNT]
</text>
- <text length="1" name="Owned by parcel owner:" type="string" left="14" width="180" >
+ <text name="Owned by parcel owner:" left="14" width="180" >
Del propietario de la parcela:
</text>
- <text name="owner_objects_text" left="214" width="48">
+ <text name="owner_objects_text" left="204" width="48">
[COUNT]
</text>
<button label="Mostrar" label_selected="Mostrar" name="ShowOwner" right="-135" width="60"/>
<button label="Devolver..." label_selected="Devolver..." name="ReturnOwner..." tool_tip="Devolver los objetos a sus propietarios." right="-10" width="119"/>
- <text length="1" name="Set to group:" type="string" left="14" width="180">
+ <text name="Set to group:" left="14" width="180">
Del grupo:
</text>
- <text name="group_objects_text" left="214" width="48">
+ <text name="group_objects_text" left="204" width="48">
[COUNT]
</text>
<button label="Mostrar" label_selected="Mostrar" name="ShowGroup" right="-135" width="60"/>
<button label="Devolver..." label_selected="Devolver..." name="ReturnGroup..." tool_tip="Devolver los objetos a sus propietarios." right="-10" width="119"/>
- <text length="1" name="Owned by others:" type="string" left="14" width="128">
+ <text name="Owned by others:" left="14" width="128">
Propiedad de otros:
</text>
- <text name="other_objects_text" left="214" width="48">
+ <text name="other_objects_text" left="204" width="48">
[COUNT]
</text>
<button label="Mostrar" label_selected="Mostrar" name="ShowOther" right="-135" width="60"/>
<button label="Devolver..." label_selected="Devolver..." name="ReturnOther..." tool_tip="Devolver los objetos a sus propietarios." right="-10" width="119"/>
- <text length="1" name="Selected / sat upon:" type="string" left="14" width="193" >
+ <text name="Selected / sat upon:" left="14" width="193" >
Seleccionados / con gente sentada:
</text>
- <text name="selected_objects_text" left="214" width="48">
+ <text name="selected_objects_text" left="204" width="48">
[COUNT]
</text>
<text name="Autoreturn" left="4" width="412" >
Autodevolución de objetos a otros residentes (minutos; 0 la desactiva):
</text>
<line_editor name="clean other time" right="-20" />
- <text length="1" name="Object Owners:" type="string" width="150">
+ <text name="Object Owners:" width="150">
Propietarios de los objetos:
</text>
<button label="Actualizar la lista" label_selected="Actualizar la lista" name="Refresh List" left="158"/>
@@ -262,168 +262,140 @@ Vaya al menú Mundo &gt; Acerca del terreno o seleccione otra parcela para ver s
</name_list>
</panel>
<panel label="Opciones" name="land_options_panel">
- <text length="1" name="allow_label" type="string">
+ <text name="allow_label">
Permitir a otros residentes:
</text>
<check_box label="Editar el terreno" name="edit land check" tool_tip="Si se marca, cualquiera podrá modificar su terreno. Mejor dejarlo desmarcado, pues usted siempre puede modificar su terreno."/>
<check_box label="Crear hitos" name="check landmark"/>
<check_box label="Volar" name="check fly" tool_tip="Si se marca, los residentes podrán volar en su terreno. Si no, sólo podrán volar al cruzarlo o hasta que aterricen en él."/>
- <text length="1" name="allow_label2" type="string" left="162" >
+ <text name="allow_label2" left="162" >
Crear objetos:
</text>
<check_box label="Todos los residentes" name="edit objects check" left="255" />
<check_box label="El grupo" name="edit group objects check" left="385" />
- <text length="1" name="allow_label3" type="string" left="162">
+ <text name="allow_label3" left="162">
Dejar objetos:
</text>
<check_box label="Todos los residentes" name="all object entry check" left="255"/>
<check_box label="El grupo" name="group object entry check" left="385"/>
- <text length="1" name="allow_label4" type="string" left="162">
+ <text name="allow_label4" left="162">
Ejecutar scripts:
</text>
<check_box label="Todos los residentes" name="check other scripts" left="255"/>
<check_box label="El grupo" name="check group scripts" left="385"/>
- <text length="1" name="land_options_label" type="string">
+ <text name="land_options_label">
Opciones del terreno:
</text>
<check_box label="Seguro (sin daño)" name="check safe" tool_tip="Si se marca, convierte el terreno en &apos;seguro&apos;, desactivando el daño en combate. Si no, se activa el daño en combate."/>
<check_box label="Sin &apos;empujones&apos;" name="PushRestrictCheck" tool_tip="Previene scripts que empujen. Marcando esta opción prevendrá que en su terreno haya comportamientos destructivos."/>
<check_box label="Mostrar la parcela en Buscar (30 L$/semana) en" name="ShowDirectoryCheck" tool_tip="Let people see this parcel in search results"/>
- <string name="search_enabled_tooltip">
+ <panel.string name="search_enabled_tooltip">
Permitir que aparezca esta parcela en los resultados de la búsqueda
- </string>
- <string name="search_disabled_small_tooltip">
+ </panel.string>
+ <panel.string name="search_disabled_small_tooltip">
Esta opción está desactivada porque la parcela tiene 128 m² o menos.
Sólo las parcelas más grandes pueden listarse en la búsqueda.
- </string>
- <string name="search_disabled_permissions_tooltip">
+ </panel.string>
+ <panel.string name="search_disabled_permissions_tooltip">
Esta opción no esta activada porque usted no puede modificar las opciones de la parcela.
- </string>
- <combo_box name="land category with adult">
- <combo_item name="AnyCategory">
- Cualquier categoría
- </combo_item>
- <combo_item name="LindenLocation">
- Localización Linden
- </combo_item>
- <combo_item name="Adult">
- &apos;Adult&apos;
- </combo_item>
- <combo_item name="Arts&amp;Culture">
- Arte y Cultura
- </combo_item>
- <combo_item name="Business">
- Negocios
- </combo_item>
- <combo_item name="Educational">
- Educativo
- </combo_item>
- <combo_item name="Gaming">
- Juegos de azar
- </combo_item>
- <combo_item name="Hangout">
- Entretenimiento
- </combo_item>
- <combo_item name="NewcomerFriendly">
- Para recién llegados
- </combo_item>
- <combo_item name="Parks&amp;Nature">
- Parques y Naturaleza
- </combo_item>
- <combo_item name="Residential">
- Residencial
- </combo_item>
- <combo_item name="Shopping">
- Compras
- </combo_item>
- <combo_item name="Other">
- Otra
- </combo_item>
+ </panel.string>
+ <combo_box name="land category with adult" left="282" width="140">
+ <combo_box.item name="item0" label="Cualquier categoría"
+ />
+ <combo_box.item name="item1" label="Localización Linden"
+ />
+ <combo_box.item name="item2" label="&apos;Adult&apos;"
+ />
+ <combo_box.item name="item3" label="Arte y Cultura"
+ />
+ <combo_box.item name="item4" label="Negocios"
+ />
+ <combo_box.item name="item5" label="Educativo"
+ />
+ <combo_box.item name="item6" label="Juegos de azar"
+ />
+ <combo_box.item name="item7" label="Entretenimiento"
+ />
+ <combo_box.item name="item8" label="Para recién llegados"
+ />
+ <combo_box.item name="item9" label="Parques y Naturaleza"
+ />
+ <combo_box.item name="item10" label="Residencial"
+ />
+ <combo_box.item name="item11" label="Compras"
+ />
+ <combo_box.item name="item12" label="Otra"
+ />
</combo_box>
- <combo_box name="land category">
- <combo_item name="AnyCategory">
- Cualquier categoría
- </combo_item>
- <combo_item name="LindenLocation">
- Localización Linden
- </combo_item>
- <combo_item name="Arts&amp;Culture">
- Arte y Cultura
- </combo_item>
- <combo_item name="Business">
- Negocios
- </combo_item>
- <combo_item name="Educational">
- Educativo
- </combo_item>
- <combo_item name="Gaming">
- Juegos de azar
- </combo_item>
- <combo_item name="Hangout">
- Entretenimiento
- </combo_item>
- <combo_item name="NewcomerFriendly">
- Para recién llegados
- </combo_item>
- <combo_item name="Parks&amp;Nature">
- Parques y Naturaleza
- </combo_item>
- <combo_item name="Residential">
- Residencial
- </combo_item>
- <combo_item name="Shopping">
- Compras
- </combo_item>
- <combo_item name="Other">
- Otra
- </combo_item>
+ <combo_box name="land category" left="282" width="140">
+ <combo_box.item name="item0" label="Cualquier categoría"
+ />
+ <combo_box.item name="item1" label="Localización Linden"
+ />
+ <combo_box.item name="item3" label="Arte y Cultura"
+ />
+ <combo_box.item name="item4" label="Negocios"
+ />
+ <combo_box.item name="item5" label="Educativo"
+ />
+ <combo_box.item name="item6" label="Juegos de azar"
+ />
+ <combo_box.item name="item7" label="Entretenimiento"
+ />
+ <combo_box.item name="item8" label="Para recién llegados"
+ />
+ <combo_box.item name="item9" label="Parques y Naturaleza"
+ />
+ <combo_box.item name="item10" label="Residencial"
+ />
+ <combo_box.item name="item11" label="Compras"
+ />
+ <combo_box.item name="item12" label="Otra"
+ />
</combo_box>
- <button label="?" label_selected="?" name="?"/>
+ <button label="?" label_selected="?" name="?" left="427"/>
<check_box label="Contenido &apos;Mature&apos;" name="MatureCheck" tool_tip=""/>
- <string name="mature_check_mature">
+ <panel.string name="mature_check_mature">
Contenido &apos;Mature&apos;
- </string>
- <string name="mature_check_adult">
+ </panel.string>
+ <panel.string name="mature_check_adult">
Contenido &apos;Adult&apos;
- </string>
- <string name="mature_check_mature_tooltip">
+ </panel.string>
+ <panel.string name="mature_check_mature_tooltip">
La información o el contenido de su parcela se considera &apos;Mature&apos;.
- </string>
- <string name="mature_check_adult_tooltip">
+ </panel.string>
+ <panel.string name="mature_check_adult_tooltip">
La información o el contenido de su parcela se considera &apos;Adult&apos;.
- </string>
- <text length="1" name="Snapshot:" type="string">
+ </panel.string>
+ <text name="Snapshot:">
Foto:
</text>
<texture_picker label="" name="snapshot_ctrl" tool_tip="Pulse para elegir una imagen"/>
<text name="landing_point">
Punto de llegada: [LANDING]
</text>
- <string name="landing_point_none">
+ <panel.string name="landing_point_none">
(ninguno)
- </string>
+ </panel.string>
<button label="Definir" label_selected="Definir" name="Set" tool_tip="Configura el punto de llegada donde aparecerán los visitantes. Configúrelo a la posición de su avatar dentro de esta parcela."/>
<button label="Borrar" label_selected="Borrar" name="Clear" tool_tip="Borrar el punto de llegada."/>
- <text length="1" name="Teleport Routing: " type="string">
+ <text name="Teleport Routing: ">
Punto de teleporte:
</text>
<combo_box name="landing type" tool_tip="Punto de teleporte: defina cómo manejar en su terreno los teleportes.">
- <combo_item length="1" name="Blocked" type="string">
- Bloqueado
- </combo_item>
- <combo_item length="1" name="LandingPoint" type="string">
- Punto de llegada
- </combo_item>
- <combo_item length="1" name="Anywhere" type="string">
- Cualquiera
- </combo_item>
+ <combo_box.item name="Blocked" label="Bloqueado"
+ />
+ <combo_box.item name="LandingPoint" label="Punto de llegada"
+ />
+ <combo_box.item name="Anywhere" label="Cualquiera"
+ />
</combo_box>
- <string name="push_restrict_text">
+ <panel.string name="push_restrict_text">
Sin &apos;empujones&apos;
- </string>
- <string name="push_restrict_region_text">
+ </panel.string>
+ <panel.string name="push_restrict_region_text">
Sin &apos;empujones&apos; (prevalece lo marcado en la región)
- </string>
+ </panel.string>
</panel>
<panel label="Media" name="land_media_panel">
<text name="with media:" width="85">
@@ -439,7 +411,7 @@ Sólo las parcelas más grandes pueden listarse en la búsqueda.
Descripción:
</text>
<line_editor name="url_description" tool_tip="Texto a mostrar cerca del botón play/cargar" left="97" />
- <text length="1" name="Media texture:" type="string">
+ <text name="Media texture:">
Cambiar
la textura:
</text>
@@ -482,7 +454,7 @@ música:
<check_box left="117" label="Limitar la voz a esta parcela" name="parcel_enable_voice_channel_parcel"/>
</panel>
<panel label="Acceso" name="land_access_panel">
- <text length="1" name="Limit access to this parcel to:" type="string">
+ <text name="Limit access to this parcel to:">
Acceso a esta parcela
</text>
<check_box label="Permitir el acceso público" name="public_access"/>
@@ -491,18 +463,16 @@ música:
</text>
<check_box label="Residentes que no hayan dado a Linden Lab información de su forma de pago" name="limit_payment" tool_tip="Impedir el acceso a los residentes no identificados."/>
<check_box label="Residentes de los que no se ha verificado si son adultos" name="limit_age_verified" tool_tip="Residentes que no hayan verificado su edad. Para más información, vea support.secondlife.com"/>
- <string name="estate_override">
+ <panel.string name="estate_override">
Una o más de esta opciones está configurada a nivel del estado
- </string>
+ </panel.string>
<check_box label="Acceso permitido al grupo: [GROUP]" name="GroupCheck" tool_tip="Elija el grupo en la pestaña General."/>
<check_box label="Vender pases a:" name="PassCheck" tool_tip="Permitir acceso temporal a esta parcela"/>
<combo_box name="pass_combo">
- <combo_item name="Anyone">
- Cualquiera
- </combo_item>
- <combo_item name="Group">
- Grupo
- </combo_item>
+ <combo_box.item name="Anyone" label="Cualquiera"
+ />
+ <combo_box.item name="Group" label="Grupo"
+ />
</combo_box>
<spinner label="Precio en L$:" name="PriceSpin"/>
<spinner label="Horas de acceso:" name="HoursSpin"/>
diff --git a/indra/newview/skins/default/xui/es/floater_animation_preview.xml b/indra/newview/skins/default/xui/es/floater_animation_preview.xml
index a5b9847c4f..5a03aa6370 100644
--- a/indra/newview/skins/default/xui/es/floater_animation_preview.xml
+++ b/indra/newview/skins/default/xui/es/floater_animation_preview.xml
@@ -6,145 +6,72 @@
<text name="description_label">
Descripción:
</text>
- <spinner label="Prioridad" name="priority" tool_tip="Controle qué otras animaciones pueden ser anuladas por ésta."/>
- <check_box label="Bucle" name="loop_check" tool_tip="Haga esta animación en bucle."/>
- <spinner label="Empieza(%)" name="loop_in_point" tool_tip="Indique el punto en el que la animación empieza el bucle."/>
- <spinner label="Acaba(%)" name="loop_out_point" tool_tip="Indique el punto en el que la animación acaba el bucle."/>
+ <spinner label_width="72" width="110" label="Prioridad:" name="priority" tool_tip="Controle qué otras animaciones pueden ser anuladas por ésta."/>
+ <check_box left="8" label="Bucle:" name="loop_check" tool_tip="Haga esta animación en bucle."/>
+ <spinner label_width="65" left="65" width="116" label="Empieza(%)" name="loop_in_point" tool_tip="Indique el punto en el que la animación empieza el bucle."/>
+ <spinner label_width="50" left="185" label="Acaba(%)" name="loop_out_point" tool_tip="Indique el punto en el que la animación acaba el bucle."/>
<text name="hand_label">
Posición de las manos
</text>
- <combo_box label="" name="hand_pose_combo" tool_tip="Control de lo que hacen las manos durante la animación.">
- <combo_item name="Spread">
- Extendidas
- </combo_item>
- <combo_item name="Relaxed">
- Relajadas
- </combo_item>
- <combo_item name="PointBoth">
- Ambas señalan
- </combo_item>
- <combo_item name="Fist">
- Puño
- </combo_item>
- <combo_item name="RelaxedLeft">
- La izquierda relajada
- </combo_item>
- <combo_item name="PointLeft">
- La izquierda señala
- </combo_item>
- <combo_item name="FistLeft">
- Puño en la izquierda
- </combo_item>
- <combo_item name="RelaxedRight">
- La derecha relajada
- </combo_item>
- <combo_item name="PointRight">
- La derecha señala
- </combo_item>
- <combo_item name="FistRight">
- Puño en la derecha
- </combo_item>
- <combo_item name="SaluteRight">
- La derecha saluda
- </combo_item>
- <combo_item name="Typing">
- Escribiendo
- </combo_item>
- <combo_item name="PeaceRight">
- Paz en la derecha
- </combo_item>
+ <combo_box left_delta="120" width="164" name="hand_pose_combo" tool_tip="Control de lo que hacen las manos durante la animación.">
+ <combo_box.item name="Spread" label="Extendidas"/>
+ <combo_box.item name="Relaxed" label="Relajadas"/>
+ <combo_box.item name="PointBoth" label="Ambas señalan"/>
+ <combo_box.item name="Fist" label="Puño"/>
+ <combo_box.item name="RelaxedLeft" label="La izquierda relajada"/>
+ <combo_box.item name="PointLeft" label="La izquierda señala"/>
+ <combo_box.item name="FistLeft" label="Puño en la izquierda"/>
+ <combo_box.item name="RelaxedRight" label="La derecha relajada"/>
+ <combo_box.item name="PointRight" label="La derecha señala"/>
+ <combo_box.item name="FistRight" label="Puño en la derecha"/>
+ <combo_box.item name="SaluteRight" label="La derecha saluda"/>
+ <combo_box.item name="Typing" label="Escribiendo"/>
+ <combo_box.item name="PeaceRight" label="Paz en la derecha"/>
</combo_box>
<text name="emote_label">
Expresión
</text>
- <combo_box label="" name="emote_combo" tool_tip="Controle qué hace la cara durante la animación.">
- <combo_item name="[None]">
- [Nada]
- </combo_item>
- <combo_item name="Aaaaah">
- Aaaaah
- </combo_item>
- <combo_item name="Afraid">
- Con miedo
- </combo_item>
- <combo_item name="Angry">
- Enfadada
- </combo_item>
- <combo_item name="BigSmile">
- Gran sonrisa
- </combo_item>
- <combo_item name="Bored">
- Aburrida
- </combo_item>
- <combo_item name="Cry">
- Llorar
- </combo_item>
- <combo_item name="Disdain">
- Desdén
- </combo_item>
- <combo_item name="Embarrassed">
- Avergonzada
- </combo_item>
- <combo_item name="Frown">
- Fruncir el ceño
- </combo_item>
- <combo_item name="Kiss">
- Besar
- </combo_item>
- <combo_item name="Laugh">
- Reír
- </combo_item>
- <combo_item name="Plllppt">
- Sacar la lengua
- </combo_item>
- <combo_item name="Repulsed">
- Rechazo
- </combo_item>
- <combo_item name="Sad">
- Triste
- </combo_item>
- <combo_item name="Shrug">
- Encogerse de hombros
- </combo_item>
- <combo_item name="Smile">
- Sonrisa
- </combo_item>
- <combo_item name="Surprise">
- Sorpresa
- </combo_item>
- <combo_item name="Wink">
- Guiño
- </combo_item>
- <combo_item name="Worry">
- Preocupación
- </combo_item>
+ <combo_box left_delta="120" width="164" name="emote_combo" tool_tip="Controle qué hace la cara durante la animación.">
+ <combo_box.item name="[None]" label="Nada]"/>
+ <combo_box.item name="Aaaaah" label="Aaaaah"/>
+ <combo_box.item name="Afraid" label="Con miedo"/>
+ <combo_box.item name="Angry" label="Enfadada"/>
+ <combo_box.item name="BigSmile" label="Gran sonrisa"/>
+ <combo_box.item name="Bored" label="Aburrida"/>
+ <combo_box.item name="Cry" label="Llorar"/>
+ <combo_box.item name="Disdain" label="Desdén"/>
+ <combo_box.item name="Embarrassed" label="Avergonzada"/>
+ <combo_box.item name="Frown" label="Fruncir el ceño"/>
+ <combo_box.item name="Kiss" label="Besar"/>
+ <combo_box.item name="Laugh" label="Reír"/>
+ <combo_box.item name="Plllppt" label="Sacar la lengua"/>
+ <combo_box.item name="Repulsed" label="Rechazo"/>
+ <combo_box.item name="Sad" label="Triste"/>
+ <combo_box.item name="Shrug" label="Encogerse de hombros"/>
+ <combo_box.item name="Smile" label="Sonrisa"/>
+ <combo_box.item name="Surprise" label="Sorpresa"/>
+ <combo_box.item name="Wink" label="Guiño"/>
+ <combo_box.item name="Worry" label="Preocupación"/>
</combo_box>
- <text name="preview_label">
+ <text name="preview_label" width="250">
Vista previa mientras
</text>
- <combo_box label="" name="preview_base_anim" tool_tip="Compruebe cómo se comporta su animación a la vez que el avatar realiza acciones comunes.">
- <combo_item name="Standing">
- Estar de pie
- </combo_item>
- <combo_item name="Walking">
- Caminar
- </combo_item>
- <combo_item name="Sitting">
- Estar sentado
- </combo_item>
- <combo_item name="Flying">
- Volar
- </combo_item>
+ <combo_box left_delta="120" width="130" name="preview_base_anim" tool_tip="Compruebe cómo se comporta su animación a la vez que el avatar realiza acciones comunes.">
+ <combo_box.item name="Standing" label="Estar de pie"/>
+ <combo_box.item name="Walking" label="Caminar"/>
+ <combo_box.item name="Sitting" label="Estar sentado"/>
+ <combo_box.item name="Flying" label="Volar"/>
</combo_box>
- <spinner label="Combinar (sec)" name="ease_in_time" tool_tip="Tiempo (en segundos) en el que se combinan las animaciones."/>
- <spinner label="Dejar de combinar (sec)" name="ease_out_time" tool_tip="Tiempo (en segundos) en el que dejan de combinarse las animaciones."/>
- <button label="" name="play_btn" tool_tip="Mover/Pausar su animación."/>
+ <spinner label_width="125" width="192" label="Combinar (sec)" name="ease_in_time" tool_tip="Tiempo (en segundos) en el que se combinan las animaciones."/>
+ <spinner bottom_delta="-20" label_width="125" left="10" width="192" label="Dejar de combinar (sec)" name="ease_out_time" tool_tip="Tiempo (en segundos) en el que dejan de combinarse las animaciones."/>
+ <button bottom_delta="-32" name="play_btn" tool_tip="Mover/Pausar su animación."/>
<button label="" name="stop_btn" tool_tip="Parar la repetición de la animación"/>
<slider label="" name="playback_slider"/>
<text name="bad_animation_text">
No se ha podido leer el archivo de la animación.
-Recomendamos usar archivos BVH exportados de Poser 4.
+Recomendamos usar archivos BVH exportados de
+Poser 4.
</text>
<button label="Cancelar" name="cancel_btn"/>
<button label="Subir ([AMOUNT] L$)" name="ok_btn"/>
diff --git a/indra/newview/skins/default/xui/es/floater_auction.xml b/indra/newview/skins/default/xui/es/floater_auction.xml
index c6d89891bc..5196ac0b78 100644
--- a/indra/newview/skins/default/xui/es/floater_auction.xml
+++ b/indra/newview/skins/default/xui/es/floater_auction.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_auction" title="Empezar venta de terreno Linden">
+<floater name="floater_auction" title="EMPEZAR VENTA DE TERRENO LINDEN">
<check_box label="Incluir la valla amarilla de selección" name="fence_check"/>
<button label="Foto" label_selected="Foto" name="snapshot_btn"/>
<button label="OK" label_selected="OK" name="ok_btn"/>
diff --git a/indra/newview/skins/default/xui/es/floater_avatar_picker.xml b/indra/newview/skins/default/xui/es/floater_avatar_picker.xml
index 105111f29f..df0147b191 100644
--- a/indra/newview/skins/default/xui/es/floater_avatar_picker.xml
+++ b/indra/newview/skins/default/xui/es/floater_avatar_picker.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="avatarpicker" title="Elegir a un residente">
+<floater name="avatarpicker" title="ELEGIR A UN RESIDENTE">
<tab_container name="ResidentChooserTabs">
<panel label="Buscar" name="SearchPanel">
<text name="InstructSearchResidentName">
@@ -14,13 +14,15 @@
</panel>
<panel label="Cercanos" name="NearMePanel">
<text name="InstructSelectResident">
- Seleccionar un residente cercano:
+ Seleccionar un
+residente cercano:
</text>
- <button label="Actualizar la lista" label_selected="Actualizar la lista" name="Refresh"/>
- <slider label="Alcance" name="near_me_range"/>
+ <button font="SansSerifSmall" left_delta="1" width="115" label="Actualizar la lista" label_selected="Actualizar la lista" name="Refresh"/>
+ <slider label="Alcance" name="near_me_range" bottom_delta="-36"/>
<text name="meters">
Metros
</text>
+ <scroll_list bottom_delta="-169" height="159" name="NearMe" />
</panel>
</tab_container>
<button label="Elegir" label_selected="Elegir" name="Select"/>
diff --git a/indra/newview/skins/default/xui/es/floater_avatar_textures.xml b/indra/newview/skins/default/xui/es/floater_avatar_textures.xml
index 6344768c7f..8febe4b0a9 100644
--- a/indra/newview/skins/default/xui/es/floater_avatar_textures.xml
+++ b/indra/newview/skins/default/xui/es/floater_avatar_textures.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="avatar_texture_debug" title="Texturas del avatar">
+<floater name="avatar_texture_debug" title="TEXTURAS DEL AVATAR">
<text name="baked_label">
Texturas predeterminadas
</text>
diff --git a/indra/newview/skins/default/xui/es/floater_beacons.xml b/indra/newview/skins/default/xui/es/floater_beacons.xml
index 9282cb04a6..2df90bc911 100644
--- a/indra/newview/skins/default/xui/es/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/es/floater_beacons.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="beacons" title="Balizas">
+<floater name="beacons" title="BALIZAS">
<panel name="beacons_panel">
<check_box label="Objetos con script sólo al tocarlos" name="touch_only"/>
<check_box label="Objetos con script" name="scripted"/>
diff --git a/indra/newview/skins/default/xui/es/floater_build_options.xml b/indra/newview/skins/default/xui/es/floater_build_options.xml
index bbb5b0e36d..3d839bf645 100644
--- a/indra/newview/skins/default/xui/es/floater_build_options.xml
+++ b/indra/newview/skins/default/xui/es/floater_build_options.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="build options floater" title="Opciones de la cuadrícula">
- <spinner label="Unidad de la cuadrícula (metros)" name="GridResolution"/>
- <spinner label="Graduación de la cuadrícula (metros)" name="GridDrawSize"/>
+<floater name="build options floater" title="OPCIONES DE LA CUADRÃCULA">
+ <spinner label="Unidad de la cuadrícula (metros)" name="GridResolution" width="250" label_width="192"/>
+ <spinner label="Graduación de la cuadrícula (metros)" name="GridDrawSize" width="250" label_width="192"/>
<check_box label="Activar subunidades" name="GridSubUnit"/>
<check_box label="Ver la sección transversal" name="GridCrossSection"/>
- <slider label="Opacidad de la cuadrícula" name="GridOpacity"/>
+ <slider label="Opacidad de la cuadrícula" name="GridOpacity" width="250"/>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_bulk_perms.xml b/indra/newview/skins/default/xui/es/floater_bulk_perms.xml
index 3251713074..0553f4c672 100644
--- a/indra/newview/skins/default/xui/es/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/es/floater_bulk_perms.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterbulkperms" title="Cambio masivo de los permisos del contenido">
+<floater name="floaterbulkperms" title="CAMBIO MASIVO DE LOS PERMISOS DEL CONTENIDO">
<text name="applyto">
Tipos de contenido
</text>
diff --git a/indra/newview/skins/default/xui/es/floater_bumps.xml b/indra/newview/skins/default/xui/es/floater_bumps.xml
index ed43e93688..0522f788bb 100644
--- a/indra/newview/skins/default/xui/es/floater_bumps.xml
+++ b/indra/newview/skins/default/xui/es/floater_bumps.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_bumps" title="Choques, empujones, e impactos">
+<floater name="floater_bumps" title="CHOQUES, EMPUJONES, E IMPACTOS">
<text name="none_detected">
No se han detectado
</text>
diff --git a/indra/newview/skins/default/xui/es/floater_buy_contents.xml b/indra/newview/skins/default/xui/es/floater_buy_contents.xml
index e93b8bce2d..c4d269ff39 100644
--- a/indra/newview/skins/default/xui/es/floater_buy_contents.xml
+++ b/indra/newview/skins/default/xui/es/floater_buy_contents.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_buy_contents" title="Comprar el contenido">
+<floater name="floater_buy_contents" title="COMPRAR EL CONTENIDO">
<text name="contains_text">
[NAME] contiene:
</text>
<text name="buy_text">
¿Comprar por [AMOUNT] L$ a [NAME]?
</text>
- <button label="Cancelar" label_selected="Cancelar" name="cancel_btn"/>
+ <button label="Cancelar" label_selected="Cancelar" name="cancel_btn" width="73"/>
<button label="Comprar" label_selected="Comprar" name="buy_btn"/>
<check_box label="Vestirse ahora la ropa" name="wear_check"/>
<string name="no_copy_text">
diff --git a/indra/newview/skins/default/xui/es/floater_buy_currency.xml b/indra/newview/skins/default/xui/es/floater_buy_currency.xml
index b26a9c7494..1ecb813dd1 100644
--- a/indra/newview/skins/default/xui/es/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/es/floater_buy_currency.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="buy currency" title="Comprar dinero">
+<floater name="buy currency" title="COMPRAR DINERO">
<text name="info_buying">
Comprando dinero:
</text>
@@ -22,14 +22,14 @@
<text name="buy_action">
[NAME] [PRICE] L$
</text>
- <text name="currency_action">
- Comprar L$
+ <text name="currency_action" width="50">
+ Comprar
</text>
- <line_editor name="currency_amt">
+ <line_editor name="currency_amt" width="65" left_delta="50">
1234
</line_editor>
- <text name="currency_est">
- por, aprox., [USD] US$
+ <text name="currency_est" width="138" left_delta="68">
+ por, aprox., [LOCALAMOUNT]
</text>
<text name="getting_data">
Obteniendo los datos...
@@ -52,6 +52,9 @@
<text name="total_amount">
[AMT] L$
</text>
+ <text name="currency_links">
+ [http://www.secondlife.com/my/account/payment_method_management.php?lang=es-ES payment method] | [http://www.secondlife.com/my/account/currency.php?lang=es-ES currency] | [http://www.secondlife.com/my/account/exchange_rates.php?lang=es-ES exchange rate]
+ </text>
<text name="purchase_warning_repurchase" right="-10">
Confirmando esta compra sólo compra la moneda.
Tendrá que intentar de nuevo la operación.
@@ -63,6 +66,6 @@ Aumente la cantidad a comprar.
<button label="Cancelar" name="cancel_btn"/>
<button label="Comprar" name="buy_btn"/>
<string name="buy_currency">
- Comprar L$ [LINDENS] por, aprox., [USD] U$D
+ Compre [LINDENS] L$ por, aprox., [LOCALAMOUNT]
</string>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_buy_land.xml b/indra/newview/skins/default/xui/es/floater_buy_land.xml
index a0d3734bbb..7ff45fcf79 100644
--- a/indra/newview/skins/default/xui/es/floater_buy_land.xml
+++ b/indra/newview/skins/default/xui/es/floater_buy_land.xml
@@ -1,27 +1,27 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="buy land" title="Comprar terreno">
+<floater name="buy land" title="COMPRAR TERRENO">
<text name="region_name_label">
Región:
</text>
- <text name="region_name_text">
+ <text name="region_name_text" left="565">
(desconocida)
</text>
<text name="region_type_label">
Tipo:
</text>
- <text name="region_type_text">
+ <text name="region_type_text" left="565">
(desconocido)
</text>
<text name="estate_name_label">
Estado:
</text>
- <text name="estate_name_text">
+ <text name="estate_name_text" left="565">
(desconocido)
</text>
- <text name="estate_owner_label">
+ <text name="estate_owner_label" width="115" right="565">
Propietario del estado:
</text>
- <text name="estate_owner_text">
+ <text name="estate_owner_text" left="565" >
(desconocido)
</text>
<text name="resellable_changeable_label">
@@ -36,6 +36,7 @@
<text name="covenant_text">
Deve aceptar el Contrato del Estado:
</text>
+ <text left="470" name="covenant_timestamp_text"/>
<text_editor name="covenant_editor">
Cargando...
</text_editor>
@@ -74,15 +75,9 @@ incluyendo los objetos
Sólo pueden ser propietarios de terreno los miembros premium.
</text>
<combo_box name="account_level">
- <combo_item name="US$9.95/month,billedmonthly">
- 9.95 US$/mes, facturados mensualmente
- </combo_item>
- <combo_item name="US$7.50/month,billedquarterly">
- 7.50 US$/mes, facturados cuatrimestralmente
- </combo_item>
- <combo_item name="US$6.00/month,billedannually">
- 6.00 US$/mes, facturados anualmente
- </combo_item>
+ <combo_box.item name="US$9.95/month,billedmonthly" label="9.95 US$/mes, facturados mensualmente" />
+ <combo_box.item name="US$7.50/month,billedquarterly" label="7.50 US$/mes, facturados cuatrimestralmente" />
+ <combo_box.item name="US$6.00/month,billedannually" label="6.00 US$/mes, facturados anualmente" />
</combo_box>
<text name="land_use_action">
Aumenta su cuota mensual por uso de terreno a 40 US$/mes.
diff --git a/indra/newview/skins/default/xui/es/floater_buy_object.xml b/indra/newview/skins/default/xui/es/floater_buy_object.xml
index 8e713f362b..26696bc868 100644
--- a/indra/newview/skins/default/xui/es/floater_buy_object.xml
+++ b/indra/newview/skins/default/xui/es/floater_buy_object.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="contents" title="Comprar una copia del objeto">
+<floater name="contents" title="COMPRAR UNA COPIA DEL OBJETO">
<text name="contents_text">
y sus contenidos:
</text>
diff --git a/indra/newview/skins/default/xui/es/floater_camera.xml b/indra/newview/skins/default/xui/es/floater_camera.xml
index 0246f0d440..3aeb4e5771 100644
--- a/indra/newview/skins/default/xui/es/floater_camera.xml
+++ b/indra/newview/skins/default/xui/es/floater_camera.xml
@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move floater" title="">
- <string name="rotate_tooltip">
+<floater name="camera_floater" title="">
+ <floater.string name="rotate_tooltip">
Girar la cámara alrededor de lo enfocado
- </string>
- <string name="zoom_tooltip">
+ </floater.string>
+ <floater.string name="zoom_tooltip">
Hacer zoom con la cámara en lo enfocado
- </string>
- <string name="move_tooltip">
- Mover la cámara arriba y abajo, izquierda y derecha.
- </string>
+ </floater.string>
+ <floater.string name="move_tooltip">
+ Mover la cámara arriba y abajo, izquierda y derecha
+ </floater.string>
+ <panel name="controls">
+ <joystick_track name="cam_track_stick" tool_tip="Mover la cámara arriba y abajo, izquierda y derecha"/>
+ <joystick_zoom name="zoom" tool_tip="Hacer zoom con la cámara en lo enfocado"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_choose_group.xml b/indra/newview/skins/default/xui/es/floater_choose_group.xml
index 71331abb65..a5967b814e 100644
--- a/indra/newview/skins/default/xui/es/floater_choose_group.xml
+++ b/indra/newview/skins/default/xui/es/floater_choose_group.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="groups" title="Grupos">
+<floater name="groups" title="GRUPOS">
<text name="groupdesc">
Elegir un grupo:
</text>
diff --git a/indra/newview/skins/default/xui/es/floater_color_picker.xml b/indra/newview/skins/default/xui/es/floater_color_picker.xml
index 238853c58d..4395ee6890 100644
--- a/indra/newview/skins/default/xui/es/floater_color_picker.xml
+++ b/indra/newview/skins/default/xui/es/floater_color_picker.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="ColorPicker" title="Paleta de colores">
+<floater name="ColorPicker" title="PALETA DE COLORES">
<text name="r_val_text">
Rojo:
</text>
@@ -25,6 +25,7 @@
Color actual:
</text>
<text name="(Drag below to save.)">
- (Arrástrelo abajo para guardarlo)
+ (Arrástrelo abajo
+ para guardarlo)
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_customize.xml b/indra/newview/skins/default/xui/es/floater_customize.xml
index fa3113faf7..94452dae6b 100644
--- a/indra/newview/skins/default/xui/es/floater_customize.xml
+++ b/indra/newview/skins/default/xui/es/floater_customize.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater customize" title="Apariencia" width="527">
+<floater name="floater customize" title="APARIENCIA" width="527">
<tab_container name="customize tab container" width="525">
- <panel label="Partes del cuerpo" name="body_parts_placeholder"/>
+ <placeholder label="Partes del cuerpo" name="body_parts_placeholder"/>
<panel label="Forma" name="Shape" width="389">
<button label="Restablecer" label_selected="Restablecer" name="Revert"/>
<button label="Cuerpo" label_selected="Cuerpo" name="Body"/>
@@ -14,33 +14,29 @@
<button label="Torso" label_selected="Torso" name="Torso"/>
<button label="Piernas" label_selected="Piernas" name="Legs"/>
<radio_group name="sex radio">
- <radio_item length="1" name="radio" type="string">
- Mujer
- </radio_item>
- <radio_item length="1" name="radio2" type="string">
- Varón
- </radio_item>
+ <radio_item name="radio" label="Mujer" />
+ <radio_item name="radio2" label="Varón" />
</radio_group>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: no modificable
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: cargando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: no lleva
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Situada en [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Póngase una forma nueva arrastrando una desde su inventario hasta su
avatar. O parta de cero creando una nueva y vistiéndola.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
No tiene permiso para modificar este ítem.
</text>
<text name="Item Action Label" right="107">
@@ -55,26 +51,26 @@ avatar. O parta de cero creando una nueva y vistiéndola.
<button label="Detalles faciales" label_selected="Detalles faciales" name="Face Detail" width="115"/>
<button label="Maquillaje" label_selected="Maquillaje" name="Makeup" width="115"/>
<button label="Detalles del cuerpo" label_selected="Detalles del cuerpo" name="Body Detail" width="115"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: no modificable
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: cargando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: no lleva
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Situada en [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Póngase otra piel arrastrando una desde su inventario hasta su
avatar. O parta de cero creando una nueva y vistiéndola.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
No tiene permiso para modificar este ítem.
</text>
<text name="Item Action Label" right="107">
@@ -93,26 +89,26 @@ avatar. O parta de cero creando una nueva y vistiéndola.
<button label="Peinado" label_selected="Peinado" name="Style"/>
<button label="Cejas" label_selected="Cejas" name="Eyebrows"/>
<button label="Facial" label_selected="Facial" name="Facial"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: no modificable
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: cargando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: no lleva
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Situado en [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Póngase otro pelo arrastrando uno desde su inventario hasta su
avatar. O parta de cero creando uno nueva y vistiéndolo.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
No tiene permiso para modificar este ítem.
</text>
<text name="Item Action Label" right="107">
@@ -125,26 +121,26 @@ avatar. O parta de cero creando uno nueva y vistiéndolo.
<button label="Restablecer" label_selected="Restablecer" name="Revert"/>
</panel>
<panel label="Ojos" name="Eyes">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: no modificables
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: cargando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: no lleva
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Situados en [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Póngase otros ojos arrastrando unos desde su inventario hasta su
avatar. O parta de cero creando unos nuevos y vistiéndoselos.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
No tiene permiso para modificar este ítem.
</text>
<text name="Item Action Label" right="107">
@@ -165,30 +161,30 @@ avatar. O parta de cero creando unos nuevos y vistiéndoselos.
<button left="113" label="Guardar" label_selected="Guardar" name="Save"/>
<button left="199" width="102" label="Guardar como..." label_selected="Guardar como..." name="Save As"/>
<button label="Restablecer" label_selected="Restablecer" name="Revert"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: no modificable
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: cargando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: no lleva
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Situada en [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Póngase otra camisa arrastrando una desde su inventario hasta su
avatar. O parta de cero creando una nueva y vistiéndola.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
No tiene permiso para modificar este ítem.
</text>
<text name="Item Action Label" right="107">
- Camiseta:
+ Camisa:
</text>
</panel>
<panel label="Pantalones" name="Pants">
@@ -199,53 +195,53 @@ avatar. O parta de cero creando una nueva y vistiéndola.
<button left="113" label="Guardar" label_selected="Guardar" name="Save"/>
<button left="199" width="102" label="Guardar como..." label_selected="Guardar como..." name="Save As"/>
<button label="Restablecer" label_selected="Restablecer" name="Revert"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: no modificables
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: cargando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: no lleva
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Situados en [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Póngase otros pantalones arrastrando unos desde su inventario hasta su
avatar. O parta de cero creando unos nuevos y vistiéndoselos.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
No tiene permiso para modificar este ítem.
</text>
<text name="Item Action Label" right="107">
Pantalones:
</text>
</panel>
- <panel label="Shoes" name="Shoes">
- <text length="1" name="title" type="string">
+ <panel label="Zapatos" name="Shoes">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: no modificables
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: cargando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: no lleva
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Situados en [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Póngase otros zapatos arrastrando unos desde su inventario hasta su
avatar. O parta de cero creando unos nuevos y vistiéndoselos.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
No tiene permiso para modificar este ítem.
</text>
<text name="Item Action Label" right="107">
@@ -260,26 +256,26 @@ avatar. O parta de cero creando unos nuevos y vistiéndoselos.
<button label="Restablecer" label_selected="Restablecer" name="Revert"/>
</panel>
<panel label="Calcetines" name="Socks">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: no modificables
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: cargando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: no lleva
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Situados en [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Póngase otros calcetines arrastrando unos desde su inventario hasta su
avatar. O parta de cero creando unos nuevos y vistiéndoselos.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
No tiene permiso para modificar este ítem.
</text>
<text name="Item Action Label" right="107">
@@ -294,26 +290,26 @@ avatar. O parta de cero creando unos nuevos y vistiéndoselos.
<button label="Restablecer" label_selected="Restablecer" name="Revert"/>
</panel>
<panel label="Chaqueta" name="Jacket">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: no modificable
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: cargando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: no lleva
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Situada en [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Póngase otra chaqueta arrastrando una desde su inventario hasta su
avatar. O parta de cero creando una nueva y vistiéndola.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
No tiene permiso para modificar este ítem.
</text>
<text name="Item Action Label" right="107">
@@ -329,26 +325,26 @@ avatar. O parta de cero creando una nueva y vistiéndola.
<button label="Restablecer" label_selected="Restablecer" name="Revert"/>
</panel>
<panel label="Guantes" name="Gloves">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: no modificables
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: cargando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: no lleva
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Situados en [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Póngase otros guantes arrastrando unos desde su inventario hasta su
avatar. O parta de cero creando unos nuevos y vistiéndoselos.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
No tiene permiso para modificar este ítem.
</text>
<text name="Item Action Label" right="107">
@@ -363,26 +359,26 @@ avatar. O parta de cero creando unos nuevos y vistiéndoselos.
<button label="Restablecer" label_selected="Restablecer" name="Revert"/>
</panel>
<panel label="Camiseta" name="Undershirt">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: no modificable
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: cargando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: no lleva
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Situada en [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Póngase otra camiseta arrastrando una desde su inventario hasta su
avatar. O parta de cero creando una nueva y vistiéndola.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
No tiene permiso para modificar este ítem.
</text>
<text name="Item Action Label" right="107">
@@ -397,26 +393,26 @@ avatar. O parta de cero creando una nueva y vistiéndola.
<button label="Restablecer" label_selected="Restablecer" name="Revert"/>
</panel>
<panel label="Ropa interior" name="Underpants">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: no modificable
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: cargando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: no lleva
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Situada en [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Póngase otra ropa interior arrastrando una desde su inventario hasta su
avatar. O parta de cero creando una nueva y vistiéndola.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
No tiene permiso para modificar este ítem.
</text>
<text name="Item Action Label" right="107">
@@ -431,26 +427,26 @@ avatar. O parta de cero creando una nueva y vistiéndola.
<button label="Restablecer" label_selected="Restablecer" name="Revert"/>
</panel>
<panel label="Falda" name="Skirt">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: no modificable
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: cargando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: no lleva
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Situada en [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Póngase otra falda arrastrando una desde su inventario hasta su
avatar. O parta de cero creando una nueva y vistiéndola.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
No tiene permiso para modificar este ítem.
</text>
<text name="Item Action Label" right="107">
@@ -468,5 +464,5 @@ avatar. O parta de cero creando una nueva y vistiéndola.
<scroll_container left="230" name="panel_container"/>
<button label="Cancelar" label_selected="Cancelar" name="Cancel"/>
<button label="OK" label_selected="OK" name="Ok"/>
- <button label="Hacer un vestuario..." label_selected="Hacer un vestuario..." name="Make Outfit" width="125"/>
+ <button label="Hacer un vestuario..." label_selected="Hacer un vestuario..." name="Make Outfit" width="130"/>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_day_cycle_options.xml b/indra/newview/skins/default/xui/es/floater_day_cycle_options.xml
index dd74505239..fc2b12d1e4 100644
--- a/indra/newview/skins/default/xui/es/floater_day_cycle_options.xml
+++ b/indra/newview/skins/default/xui/es/floater_day_cycle_options.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Day Cycle Floater" title="Editor del ciclo de un día">
+<floater name="Day Cycle Floater" title="EDITOR DEL CICLO DE UN DÃA">
<tab_container name="Day Cycle Tabs">
<panel label="Ciclo de un día" name="Day Cycle">
<button label="?" name="WLDayCycleHelp"/>
@@ -57,9 +57,9 @@
<text name="WL12amHash2">
|
</text>
- <button label="Añadir un punto" label_selected="Añadir un punto" name="WLAddKey"/>
- <button label="Quitar un punto" label_selected="Quitar un punto" name="WLDeleteKey"/>
- <text name="WLCurKeyFrameText">
+ <button font="SansSerifSmall" width="96" left="546" label="Añadir un punto" label_selected="Añadir un punto" name="WLAddKey"/>
+ <button font="SansSerifSmall" width="96" left="546" label="Quitar un punto" label_selected="Quitar un punto" name="WLDeleteKey"/>
+ <text font="SansSerifSmall" name="WLCurKeyFrameText" width="190">
Configuración del fotograma clave:
</text>
<text name="WLCurKeyTimeText">
@@ -86,9 +86,9 @@
</text>
<button label="Probar" label_selected="Probar" name="WLAnimSky"/>
<button label="Parar" label_selected="Parar" name="WLStopAnimSky"/>
- <button label="Usar el horario del estado" label_selected="Ir al horario del estado" name="WLUseLindenTime"/>
- <button label="Guardar este tipo de día" label_selected="Guardar este tipo de día" name="WLSaveDayCycle"/>
- <button label="Cargar y probar un tipo de día" label_selected="Cargar y probar un tipo de día" name="WLLoadDayCycle"/>
+ <button width="150" font="SansSerifSmall" label="Usar el horario del estado" label_selected="Ir al horario del estado" name="WLUseLindenTime"/>
+ <button left="440" width="180" font="SansSerifSmall" label="Guardar este tipo de día" label_selected="Guardar este tipo de día" name="WLSaveDayCycle"/>
+ <button left="440" width="180" font="SansSerifSmall" label="Cargar y probar un tipo de día" label_selected="Cargar y probar un tipo de día" name="WLLoadDayCycle"/>
</panel>
</tab_container>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_device_settings.xml b/indra/newview/skins/default/xui/es/floater_device_settings.xml
index e8989f44ef..eadf04a417 100644
--- a/indra/newview/skins/default/xui/es/floater_device_settings.xml
+++ b/indra/newview/skins/default/xui/es/floater_device_settings.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_device_settings" title="Configuración de los dispositivos del chat de voz"/>
+<floater name="floater_device_settings" title="CONFIGURACIÓN DE LOS DISPOSITIVOS DEL CHAT DE VOZ"/>
diff --git a/indra/newview/skins/default/xui/es/floater_env_settings.xml b/indra/newview/skins/default/xui/es/floater_env_settings.xml
index 8b9bfe7362..5d6ba47daf 100644
--- a/indra/newview/skins/default/xui/es/floater_env_settings.xml
+++ b/indra/newview/skins/default/xui/es/floater_env_settings.xml
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Environment Editor Floater" title="Editor del entorno">
+<floater name="Environment Editor Floater" title="EDITOR DEL ENTORNO">
<text name="EnvTimeText">
- Duración de un día
+ Duración de
+un día
</text>
<text name="EnvTimeText2">
12:00 PM
@@ -10,14 +11,16 @@
Nubosidad
</text>
<text name="EnvWaterColorText">
- Color del agua
+ Color del
+agua
</text>
<color_swatch label="" name="EnvWaterColor" tool_tip="Pulse para abrir el selector de color"/>
<text name="EnvWaterFogText">
- Claridad del agua
+ Claridad del
+agua
</text>
- <button label="Usar el horario del estado" name="EnvUseEstateTimeButton"/>
- <button label="Cielo avanzado" name="EnvAdvancedSkyButton"/>
- <button label="Agua avanzada" name="EnvAdvancedWaterButton"/>
+ <button bottom="-144" label="Usar el horario del estado" name="EnvUseEstateTimeButton" width="155"/>
+ <button label="Cielo avanzado" name="EnvAdvancedSkyButton" width="155" left="167" />
+ <button label="Agua avanzada" name="EnvAdvancedWaterButton" width="155" left="326"/>
<button label="?" name="EnvSettingsHelpButton"/>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_font_test.xml b/indra/newview/skins/default/xui/es/floater_font_test.xml
index e6b8087b60..9a665321a4 100644
--- a/indra/newview/skins/default/xui/es/floater_font_test.xml
+++ b/indra/newview/skins/default/xui/es/floater_font_test.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="contents" title="Prueba de fuentes">
+<floater name="contents" title="PRUEBA DE FUENTES">
<text name="linea">
OverrideTest, debería de aparecer aquí en Times. (Desde default/xui/en-us)
</text>
diff --git a/indra/newview/skins/default/xui/es/floater_gesture.xml b/indra/newview/skins/default/xui/es/floater_gesture.xml
index 4f19286d01..496881f2d2 100644
--- a/indra/newview/skins/default/xui/es/floater_gesture.xml
+++ b/indra/newview/skins/default/xui/es/floater_gesture.xml
@@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="gestures" title="Gestos disponibles">
+<floater name="gestures" title="GESTOS DISPONIBLES">
<text name="help_label">
- Pulse dos veces en un gesto para reproducir las animaciones y sonidos.
+ Pulse dos veces en un gesto para reproducir las animaciones
+y sonidos.
</text>
- <scroll_list name="gesture_list">
+ <scroll_list bottom_delta="-385" height="360" name="gesture_list">
<column label="Botón" name="trigger"/>
<column label="Tecla" name="shortcut"/>
<column label="Nombre" name="name"/>
diff --git a/indra/newview/skins/default/xui/es/floater_god_tools.xml b/indra/newview/skins/default/xui/es/floater_god_tools.xml
index 583bc2607f..78ec76e32b 100644
--- a/indra/newview/skins/default/xui/es/floater_god_tools.xml
+++ b/indra/newview/skins/default/xui/es/floater_god_tools.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="godtools floater" title="Herramientas de Dios">
+<floater name="godtools floater" title="HERRAMIENTAS DE DIOS">
<tab_container name="GodTools Tabs">
<panel label="Red" name="grid">
<button label="Expulsar a todos los usuarios"
@@ -54,7 +54,7 @@
Factor cobrable:
</text>
<text name="land cost text">
- L$ por m2:
+ L$ por m²:
</text>
<button label="Actualizar" label_selected="Actualizar" name="Refresh"
tool_tip="Haga clic aquí para actualizar la información arriba." />
@@ -114,29 +114,17 @@
Destino:
</text>
<combo_box name="destination">
- <combo_item name="Selection">
- Selección
- </combo_item>
- <combo_item name="AgentRegion">
- Agente de región
- </combo_item>
+ <combo_box.item name="item1" label="Selección" />
+ <combo_box.item name="item2" label="Agente de región" />
</combo_box>
<text name="Request:">
Exigencia:
</text>
<combo_box name="request">
- <combo_item name="colliders&lt;steps&gt;">
- colisionadores &lt;pasos&gt;
- </combo_item>
- <combo_item name="scripts&lt;count&gt;,&lt;optionalpattern&gt;">
- scripts &lt;contar&gt;,&lt;patrón opcional&gt;
- </combo_item>
- <combo_item name="objects&lt;pattern&gt;">
- objetos &lt;patrón&gt;
- </combo_item>
- <combo_item name="rez&lt;asset_id&gt;">
- rez &lt;asset_id&gt;
- </combo_item>
+ <combo_box.item name="item1" label="colisionadores &lt;pasos&gt;" />
+ <combo_box.item name="item2" label="scripts &lt;contar&gt;,&lt;patrón opcional&gt;" />
+ <combo_box.item name="item3" label="objetos &lt;patrón&gt;" />
+ <combo_box.item name="item4" label="rez &lt;asset_id&gt;" />
</combo_box>
<text name="Parameter:">
Parámetro:
diff --git a/indra/newview/skins/default/xui/es/floater_hardware_settings.xml b/indra/newview/skins/default/xui/es/floater_hardware_settings.xml
index e596ee7f9e..9418252036 100644
--- a/indra/newview/skins/default/xui/es/floater_hardware_settings.xml
+++ b/indra/newview/skins/default/xui/es/floater_hardware_settings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Hardware Settings Floater" title="Configuración del hardware">
+<floater name="Hardware Settings Floater" title="CONFIGURACIÓN DEL HARDWARE">
<text name="Filtering:">
Filtrado:
</text>
@@ -7,22 +7,12 @@
<text name="Antialiasing:">
Antialiasing:
</text>
- <combo_box label="Antialiasing" name="fsaa">
- <combo_item name="FSAADisabled">
- Desactivado
- </combo_item>
- <combo_item name="2x">
- 2x
- </combo_item>
- <combo_item name="4x">
- 4x
- </combo_item>
- <combo_item name="8x">
- 8x
- </combo_item>
- <combo_item name="16x">
- 16x
- </combo_item>
+ <combo_box label="Antialiasing" name="fsaa" width="94">
+ <combo_box.item name="FSAADisabled" label="Desactivado"/>
+ <combo_box.item name="2x" label="2x"/>
+ <combo_box.item name="4x" label="4x"/>
+ <combo_box.item name="8x" label="8x"/>
+ <combo_box.item name="16x" label="16x"/>
</combo_box>
<spinner label="Gamma:" name="gamma"/>
<text name="(brightness, lower is brighter)">
@@ -32,7 +22,7 @@
Activar VBO:
</text>
<check_box label="Activar OpenGL Vertex Buffer Objects" name="vbo" tool_tip="En hardware moderno, habilitar esta opción mejora el rendimiento. Pero en hardware antiguo, el habilitarlo hace que, frecuentemente, se obtenga una implementación pobre de VBO, lo que puede provocarle caídas."/>
- <slider label="Memoria para texturas (MB):" name="GrapicsCardTextureMemory" tool_tip="Cantidad de memoria asignada a las texturas. Por defecto es la memoria de la tarjeta de vídeo. Reducir esta cantidad puede mejorar el rendimiento, pero también puede hacer que las texturas se vean borrosas."/>
+ <slider label_width="150" left="10" width="300" label="Memoria para texturas (MB):" name="GrapicsCardTextureMemory" tool_tip="Cantidad de memoria asignada a las texturas. Por defecto es la memoria de la tarjeta de vídeo. Reducir esta cantidad puede mejorar el rendimiento, pero también puede hacer que las texturas se vean borrosas."/>
<spinner label="Intensidad de la niebla:" name="fog"/>
<button label="OK" label_selected="OK" name="OK"/>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_hud.xml b/indra/newview/skins/default/xui/es/floater_hud.xml
index d31bcedf05..e458913452 100644
--- a/indra/newview/skins/default/xui/es/floater_hud.xml
+++ b/indra/newview/skins/default/xui/es/floater_hud.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_hud" title="Tutorial"/>
+<floater name="floater_hud" title="TUTORIAL"/>
diff --git a/indra/newview/skins/default/xui/es/floater_image_preview.xml b/indra/newview/skins/default/xui/es/floater_image_preview.xml
index f682254a50..6d51a800b7 100644
--- a/indra/newview/skins/default/xui/es/floater_image_preview.xml
+++ b/indra/newview/skins/default/xui/es/floater_image_preview.xml
@@ -7,46 +7,28 @@
Descripción:
</text>
<text name="preview_label">
- Previsualizar la imagen como:
+ Previsualizar la
+imagen como:
</text>
- <combo_box label="Tipo de ropa" name="clothing_type_combo">
- <combo_item name="Image">
- Imagen
- </combo_item>
- <combo_item name="Hair">
- Pelo
- </combo_item>
- <combo_item name="FemaleHead">
- Cabeza de mujer
- </combo_item>
- <combo_item name="FemaleUpperBody">
- Mujer: parte superior del cuerpo
- </combo_item>
- <combo_item name="FemaleLowerBody">
- Mujer: parte inferior del cuerpo
- </combo_item>
- <combo_item name="MaleHead">
- Cabeza de varón
- </combo_item>
- <combo_item name="MaleUpperBody">
- Varón: parte superior del cuerpo
- </combo_item>
- <combo_item name="MaleLowerBody">
- Varón: parte inferior del cuerpo
- </combo_item>
- <combo_item name="Skirt">
- Falda
- </combo_item>
- <combo_item name="SculptedPrim">
- Prim sculpted
- </combo_item>
+ <combo_box label="Tipo de ropa" name="clothing_type_combo" left="100" width="186">
+ <combo_box.item name="Image" label="Imagen" />
+ <combo_box.item name="Hair" label="Pelo" />
+ <combo_box.item name="FemaleHead" label="Cabeza de mujer" />
+ <combo_box.item name="FemaleUpperBody" label="Mujer: parte superior del cuerpo" />
+ <combo_box.item name="FemaleLowerBody" label="Mujer: parte inferior del cuerpo" />
+ <combo_box.item name="MaleHead" label="Cabeza de varón" />
+ <combo_box.item name="MaleUpperBody" label="Varón: parte superior del cuerpo" />
+ <combo_box.item name="MaleLowerBody" label="Varón: parte inferior del cuerpo" />
+ <combo_box.item name="Skirt" label="Falda" />
+ <combo_box.item name="SculptedPrim" label="Prim sculpted"/>
</combo_box>
<text name="bad_image_text">
Imposible leer la imagen.
-Pruebe a guardar la imagen como Targa (.tga) de 24 bites.
+Pruebe a guardar la imagen como Targa (.tga)
+de 24 bites.
</text>
<check_box label="Usar compresión sin pérdida" name="lossless_check"/>
<button label="Cancelar" name="cancel_btn"/>
- <button label="Subir ([AMOUNT] 10L$)" name="ok_btn"/>
+ <button label="Subir ([AMOUNT]L$)" name="ok_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_inspect.xml b/indra/newview/skins/default/xui/es/floater_inspect.xml
index 7a9f76de0f..3c8b38648f 100644
--- a/indra/newview/skins/default/xui/es/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/es/floater_inspect.xml
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="inspect" title="Examinar objetos">
+<floater name="inspect" title="EXAMINAR OBJETOS" min_width="450">
<scroll_list name="object_list" tool_tip="Seleccione un objeto de esta lista para realzarlo en el mundo">
<column label="Nombre del objeto" name="object_name"/>
- <column label="Nombre del propietario" name="owner_name"/>
- <column label="Nombre del creador" name="creator_name"/>
+ <column label="Propietario" name="owner_name"/>
+ <column label="Creador" name="creator_name"/>
<column label="Fecha de creación" name="creation_date"/>
</scroll_list>
- <button label="Ver el perfil del propietario..." label_selected="" name="button owner" tool_tip="Ver el perfil del propietario del objeto realzado"/>
- <button label="Ver el perfil del creadir..." label_selected="" name="button creator" tool_tip="Ver el perfil del creador original del objeto realzado"/>
+ <button width="185" label="Ver el perfil del propietario..." label_selected="" name="button owner" tool_tip="Ver el perfil del propietario del objeto realzado"/>
+ <button width="165" left="205" label="Ver el perfil del creador..." label_selected="" name="button creator" tool_tip="Ver el perfil del creador original del objeto realzado"/>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_inventory.xml b/indra/newview/skins/default/xui/es/floater_inventory.xml
index 7da14c0579..8d16d6089e 100644
--- a/indra/newview/skins/default/xui/es/floater_inventory.xml
+++ b/indra/newview/skins/default/xui/es/floater_inventory.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Inventory" title="Inventario">
+<floater name="Inventory" title="INVENTARIO">
<search_editor label="Escriba aquí para buscar" name="inventory search editor"/>
<tab_container name="inventory filter tabs">
<inventory_panel label="Todos los ítems" name="All Items"/>
diff --git a/indra/newview/skins/default/xui/es/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/es/floater_inventory_item_properties.xml
index dfe0b8e520..7abdfceb94 100644
--- a/indra/newview/skins/default/xui/es/floater_inventory_item_properties.xml
+++ b/indra/newview/skins/default/xui/es/floater_inventory_item_properties.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="item properties" title="Propiedades del ítem del inventario">
+<floater name="item properties" title="PROPIEDADES DEL ÃTEM DEL INVENTARIO">
<text name="LabelItemNameTitle">
Nombre:
</text>
@@ -30,7 +30,7 @@
Usted puede:
</text>
<check_box label="Modificarlo" name="CheckOwnerModify"/>
- <check_box label="Copiarlo" name="CheckOwnerCopy"/>
+ <check_box left_delta="88" label="Copiarlo" name="CheckOwnerCopy"/>
<check_box label="Venderlo/darlo" name="CheckOwnerTransfer"/>
<text name="BaseMaskDebug">
B:
@@ -49,23 +49,19 @@
</text>
<check_box label="Compartir con el grupo" name="CheckShareWithGroup"/>
<check_box label="Permitir a cualquiera que lo copie" name="CheckEveryoneCopy"/>
- <text name="NextOwnerLabel">
+ <text name="NextOwnerLabel" width="230">
El próximo propietario puede:
</text>
<check_box label="Modificarlo" name="CheckNextOwnerModify"/>
- <check_box label="Copiarlo" name="CheckNextOwnerCopy"/>
+ <check_box left_delta="88" label="Copiarlo" name="CheckNextOwnerCopy"/>
<check_box label="Revenderlo/darlo" name="CheckNextOwnerTransfer"/>
<text name="SaleLabel">
Marcar ítem como:
</text>
<check_box label="En venta" name="CheckPurchase"/>
- <radio_group name="RadioSaleType">
- <radio_item name="radio">
- Original
- </radio_item>
- <radio_item name="radio2">
- Copia
- </radio_item>
+ <radio_group name="RadioSaleType" left_delta="88" >
+ <radio_item name="radio" label="Original" />
+ <radio_item name="radio2" label="Copia" />
</radio_group>
<text name="TextPrice">
Precio: L$
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 d341de17e9..0cbee11bfb 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
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Inventory Finder" title="ítems_recientes_del_inventario">
+<floater name="Inventory Finder" title="ÃTEMS_RECIENTES_DEL_INVENTARIO">
<check_box label="Animaciones" name="check_animation"/>
<check_box label="Tarjetas de visita" name="check_calling_card"/>
<check_box label="Ropa" name="check_clothing"/>
@@ -11,14 +11,14 @@
<check_box label="Sonidos" name="check_sound"/>
<check_box label="Texturas" name="check_texture"/>
<check_box label="Fotos" name="check_snapshot"/>
- <button label="Todo" label_selected="Todo" name="All"/>
- <button label="Nada" label_selected="Nada" name="None"/>
- <check_box label="Mostrar siempre las carpetas" name="check_show_empty"/>
- <check_box label="Desde el fin de sesión" name="check_since_logoff"/>
- <text length="1" name="- OR -" type="string">
+ <button label="Todo" label_selected="Todo" name="All" width="70"/>
+ <button label="Nada" label_selected="Nada" name="None" width="70" bottom_delta="0" left="83"/>
+ <check_box label="Mostrar siempre las&#10;carpetas" name="check_show_empty"/>
+ <check_box label="Desde el fin de sesión" name="check_since_logoff" bottom_delta="-36"/>
+ <text name="- OR -">
- O -
</text>
<spinner label="horas atrás" name="spin_hours_ago"/>
<spinner label="días atrás" name="spin_days_ago"/>
- <button label="Cerrar" label_selected="Cerrar" name="Close"/>
+ <button label="Cerrar" label_selected="Cerrar" name="Close" bottom_delta="-30"/>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_joystick.xml b/indra/newview/skins/default/xui/es/floater_joystick.xml
index 527485e57d..75c53dd646 100644
--- a/indra/newview/skins/default/xui/es/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/es/floater_joystick.xml
@@ -1,30 +1,23 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Joystick" title="Configuración del joystick">
- <check_box name="enable_joystick">
- Activar el joystick:
- </check_box>
- <spinner label="Mapping: X" name="JoystickAxis1"/>
- <spinner label="Mapping: Y" name="JoystickAxis2"/>
- <spinner label="Mapping: Z" name="JoystickAxis0"/>
- <spinner label="Mapping: arriba/abajo" name="JoystickAxis4"/>
- <spinner label="Mapping: izq./der." name="JoystickAxis5"/>
- <spinner label="Mapping: giro" name="JoystickAxis3"/>
- <spinner label="Mapping: zoom" name="JoystickAxis6"/>
+<floater name="Joystick" title="CONFIGURACIÓN DEL JOYSTICK">
+ <check_box name="enable_joystick" label="Activar el joystick:"/>
+ <text left="140" name="joystick_type" width="360"/>
+ <spinner label="Mapping: eje X" name="JoystickAxis1" label_width="118" width="161"/>
+ <spinner label="Mapping: eje Y" name="JoystickAxis2" label_width="105" width="148"/>
+ <spinner label="Mapping: eje Z" name="JoystickAxis0" label_width="95" width="138"/>
+ <spinner label="Mapping: arriba/abajo" name="JoystickAxis4" label_width="118" width="161"/>
+ <spinner label="Mapping: izq./der." name="JoystickAxis5" label_width="105" width="148"/>
+ <spinner label="Mapping: giro" name="JoystickAxis3" label_width="95" width="138"/>
+ <spinner label="Mapping: zoom" name="JoystickAxis6" label_width="118" width="161"/>
<check_box label="Zoom directo" name="ZoomDirect"/>
<check_box label="Cursor 3D" name="Cursor3D"/>
<check_box label="Nivel automático" name="AutoLeveling"/>
<text name="Control Modes:">
Modos de control:
</text>
- <check_box name="JoystickAvatarEnabled">
- Avatar
- </check_box>
- <check_box name="JoystickBuildEnabled">
- Construir
- </check_box>
- <check_box name="JoystickFlycamEnabled">
- Flycam
- </check_box>
+ <check_box name="JoystickAvatarEnabled" label="Avatar"/>
+ <check_box name="JoystickBuildEnabled" left="192" label="Construir"/>
+ <check_box name="JoystickFlycamEnabled" label="Flycam"/>
<text name="XScale">
Escala: X
</text>
@@ -34,7 +27,7 @@
<text name="ZScale">
Escala: Z
</text>
- <text name="PitchScale">
+ <text name="PitchScale" left="3" width="115">
Escala: arriba/abajo
</text>
<text name="YawScale">
@@ -52,11 +45,11 @@
<text name="ZDeadZone">
Zona muerta Z
</text>
- <text name="PitchDeadZone">
- Zona muerta arriba/abajo
+ <text name="PitchDeadZone" left="3" width="115">
+ Zona muerta arri./aba.
</text>
- <text name="YawDeadZone">
- Zona muerta izq./der
+ <text name="YawDeadZone" left="3" width="115">
+ Zona muerta izq./der.
</text>
<text name="RollDeadZone">
Zona muerta giro
@@ -70,15 +63,17 @@
<text name="ZoomDeadZone">
Zona muerta zoom
</text>
- <button label="Predeterminados del SpaceNavigator" name="SpaceNavigatorDefaults"/>
- <button label="OK" label_selected="OK" name="ok_btn"/>
- <button label="Cancelar" label_selected="Cancelar" name="cancel_btn"/>
- <string name="JoystickMonitor">
- Monitor del joystick
- </string>
- <string name="Axis">
- Eje [NUM]
- </string>
+ <button label="Predeterminados del SpaceNavigator" name="SpaceNavigatorDefaults" font="SansSerifSmall" left="330" width="210"/>
+ <button label="OK" label_selected="OK" name="ok_btn" left="330"/>
+ <button label="Cancelar" label_selected="Cancelar" name="cancel_btn" left_delta="120"/>
+ <stat_view label="Monitor del joystick" name="axis_view">
+ <stat_bar label="Eje 0" name="axis0"/>
+ <stat_bar label="Eje 1" name="axis1"/>
+ <stat_bar label="Eje 2" name="axis2"/>
+ <stat_bar label="Eje 3" name="axis3"/>
+ <stat_bar label="Eje 4" name="axis4"/>
+ <stat_bar label="Eje 5" name="axis5"/>
+ </stat_view>
<string name="NoDevice">
no se ha detectado el dispositivo
</string>
diff --git a/indra/newview/skins/default/xui/es/floater_lagmeter.xml b/indra/newview/skins/default/xui/es/floater_lagmeter.xml
index 7d499750de..54c4ce8c6a 100644
--- a/indra/newview/skins/default/xui/es/floater_lagmeter.xml
+++ b/indra/newview/skins/default/xui/es/floater_lagmeter.xml
@@ -1,26 +1,29 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_lagmeter" title="Medidor del lag">
+<floater name="floater_lagmeter" title="MEDIDOR DEL LAG">
<button label="" label_selected="" name="client_lagmeter" tool_tip="Estado del lag del cliente"/>
<text name="client">
Cliente:
</text>
- <text name="client_text">
+ <text name="client_text" font="SansSerifSmall">
Normal
</text>
+ <text left="30" name="client_lag_cause" right="-10" />
<button label="" label_selected="" name="network_lagmeter" tool_tip="Estado del lag de la red"/>
<text name="network">
Red:
</text>
- <text name="network_text">
+ <text name="network_text" font="SansSerifSmall">
Normal
</text>
+ <text left="30" name="network_lag_cause" right="-10" />
<button label="" label_selected="" name="server_lagmeter" tool_tip="Estado del lag del servidor"/>
<text name="server">
Servidor:
</text>
- <text name="server_text">
+ <text name="server_text" font="SansSerifSmall">
Normal
</text>
+ <text left="30" name="server_lag_cause" right="-32" />
<button label="?" name="server_help"/>
<button label="&gt;&gt;" name="minimize"/>
<string name="max_title_msg">
@@ -117,10 +120,10 @@
20
</string>
<string name="server_frame_time_critical_msg">
- Frecuencia del simulador -framerate- por debajo de [SERVER_FRAME_RATE_CRITICAL]
+ Frecuencia (framerate) por debajo de [SERVER_FRAME_RATE_CRITICAL]
</string>
<string name="server_frame_time_warning_msg">
- Frecuencia del simulador -framerate- entre [SERVER_FRAME_RATE_CRITICAL] y [SERVER_FRAME_RATE_WARNING]
+ Frecuencia (framerate) entre [SERVER_FRAME_RATE_CRITICAL] y [SERVER_FRAME_RATE_WARNING]
</string>
<string name="server_frame_time_normal_msg">
Normal
diff --git a/indra/newview/skins/default/xui/es/floater_land_holdings.xml b/indra/newview/skins/default/xui/es/floater_land_holdings.xml
index 5c08b04055..bcdebf4588 100644
--- a/indra/newview/skins/default/xui/es/floater_land_holdings.xml
+++ b/indra/newview/skins/default/xui/es/floater_land_holdings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="land holdings floater" title="Mi terreno">
+<floater name="land holdings floater" title="MI TERRENO">
<scroll_list name="parcel list">
<column label="Nombre de la parcela" name="name"/>
<column label="Región" name="location"/>
@@ -8,7 +8,7 @@
<column label="" name="hidden"/>
</scroll_list>
<button label="Teleportar" label_selected="Teleportar" name="Teleport" tool_tip="Teleportar al centro de este terreno."/>
- <button label="Mostrar en el mapa" label_selected="Mostrar en el mapa" name="Show on Map" tool_tip="Mostrar este terreno en el mapa del mundo."/>
+ <button width="130" label="Mostrar en el mapa" label_selected="Mostrar en el mapa" name="Show on Map" tool_tip="Mostrar este terreno en el mapa del mundo."/>
<text name="contrib_label">
Contribuciones a sus grupos:
</text>
diff --git a/indra/newview/skins/default/xui/es/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/es/floater_live_lsleditor.xml
index 00a6995575..02be809319 100644
--- a/indra/newview/skins/default/xui/es/floater_live_lsleditor.xml
+++ b/indra/newview/skins/default/xui/es/floater_live_lsleditor.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="script ed float" title="Script: script nuevo">
+<floater name="script ed float" title="SCRIPT: SCRIPT NUEVO">
<button label="Reiniciar" label_selected="Reiniciar" name="Reset"/>
- <check_box label="Ejecutándose" name="running"/>
- <check_box label="Mono" name="mono"/>
+ <check_box label="Ejecutándose" name="running" left="4"/>
+ <check_box label="Mono" name="mono" left="106"/>
<string name="not_allowed">
No está autorizado para ver este script.
</string>
diff --git a/indra/newview/skins/default/xui/es/floater_lsl_guide.xml b/indra/newview/skins/default/xui/es/floater_lsl_guide.xml
index c1e431f274..0cde2fe5bc 100644
--- a/indra/newview/skins/default/xui/es/floater_lsl_guide.xml
+++ b/indra/newview/skins/default/xui/es/floater_lsl_guide.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="script ed float" title="Wiki de LSL">
+<floater name="script ed float" title="WIKI DE LSL">
<check_box label="Seguir al cursor" name="lock_check"/>
- <combo_box label="Bloquear" name="history_combo"/>
- <button label="Atrás" name="back_btn"/>
+ <combo_box label="Bloquear" name="history_combo" left_delta="120" width="70"/>
+ <button label="Atrás" name="back_btn" left_delta="75"/>
<button label="Adelante" name="fwd_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_map.xml b/indra/newview/skins/default/xui/es/floater_map.xml
new file mode 100644
index 0000000000..eee9caf830
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/floater_map.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Map">
+ <floater.string name="mini_map_north">
+ N
+ </floater.string>
+ <floater.string name="mini_map_east">
+ E
+ </floater.string>
+ <floater.string name="mini_map_west">
+ O
+ </floater.string>
+ <floater.string name="mini_map_south">
+ S
+ </floater.string>
+ <floater.string name="mini_map_southeast">
+ SE
+ </floater.string>
+ <floater.string name="mini_map_northeast">
+ NE
+ </floater.string>
+ <floater.string name="mini_map_southwest">
+ SO
+ </floater.string>
+ <floater.string name="mini_map_northwest">
+ NO
+ </floater.string>
+ <text label="N" name="floater_map_north" text="N">
+ N
+ </text>
+ <text label="E" name="floater_map_east" text="E">
+ E
+ </text>
+ <text label="O" name="floater_map_west" text="O">
+ O
+ </text>
+ <text label="S" name="floater_map_south" text="S">
+ S
+ </text>
+ <text label="SE" name="floater_map_southeast" text="SE">
+ SE
+ </text>
+ <text label="NE" name="floater_map_northeast" text="NE">
+ NE
+ </text>
+ <text label="SO" name="floater_map_southwest" text="SO">
+ SO
+ </text>
+ <text label="NW" name="floater_map_northwest" text="NO">
+ NO
+ </text>
+</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_media_browser.xml b/indra/newview/skins/default/xui/es/floater_media_browser.xml
index 9b60b28537..cdc7ae49ff 100644
--- a/indra/newview/skins/default/xui/es/floater_media_browser.xml
+++ b/indra/newview/skins/default/xui/es/floater_media_browser.xml
@@ -1,11 +1,18 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_about" title="Navegador">
+<floater name="floater_about" title="NAVEGADOR">
+ <floater.string name="home_page_url">
+ http://es.secondlife.com
+ </floater.string>
+ <floater.string name="support_page_url">
+ http://es.secondlife.com/support
+ </floater.string>
<layout_stack name="stack1">
<layout_panel name="nav_controls">
- <button label="Atrás" name="back"/>
- <button label="Adelante" name="forward"/>
- <button label="Actualizar" name="reload"/>
- <button label="Ir" name="go"/>
+ <button label="Atrás" name="back" width="75"/>
+ <button label="Adelante" name="forward" left_delta="75" width="70"/>
+ <button label="Actualizar" name="reload" left_delta="75"/>
+ <combo_box left_delta="75" name="address" width="510"/>
+ <button label="Ir" name="go" left_delta="515"/>
</layout_panel>
<layout_panel name="parcel_owner_controls">
<button label="Enviar a la parcela la URL actual" name="assign"/>
diff --git a/indra/newview/skins/default/xui/es/floater_mem_leaking.xml b/indra/newview/skins/default/xui/es/floater_mem_leaking.xml
index a2791d6432..6d5e987409 100644
--- a/indra/newview/skins/default/xui/es/floater_mem_leaking.xml
+++ b/indra/newview/skins/default/xui/es/floater_mem_leaking.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="MemLeak" title="Prueba de la fuga de memoria">
+<floater name="MemLeak" title="PRUEBA DE LA FUGA DE MEMORIA">
<spinner label="Velocidad de la fuga (bites por fotograma):" name="leak_speed"/>
<spinner label="Fuga de memoria máx. (MB):" name="max_leak"/>
<text name="total_leaked_label">
diff --git a/indra/newview/skins/default/xui/es/floater_moveview.xml b/indra/newview/skins/default/xui/es/floater_moveview.xml
index a5cd2f3097..a61cebbf80 100644
--- a/indra/newview/skins/default/xui/es/floater_moveview.xml
+++ b/indra/newview/skins/default/xui/es/floater_moveview.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move floater" title="">
+<floater name="move_floater">
+<panel name="panel_actions">
<button label="" label_selected="" name="turn left btn" tool_tip="Girar a la izquierda"/>
<button label="" label_selected="" name="turn right btn" tool_tip="Girar a la derecha"/>
<button label="" label_selected="" name="move up btn" tool_tip="Saltar o ascender"/>
@@ -8,4 +9,5 @@
<joystick_slide name="slide right btn" tool_tip="Ir hacia la derecha"/>
<joystick_turn name="forward btn" tool_tip="Ir hacia adelante"/>
<joystick_turn name="backward btn" tool_tip="Ir hacia atrás"/>
+</panel>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_mute_object.xml b/indra/newview/skins/default/xui/es/floater_mute_object.xml
index a2b87b67ab..390333cd1d 100644
--- a/indra/newview/skins/default/xui/es/floater_mute_object.xml
+++ b/indra/newview/skins/default/xui/es/floater_mute_object.xml
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="mute by name" title="Ignorar un objeto según su nombre">
- <text name="message">
- Ignorar según el nombre sólo afecta al chat y los MI del objeto, no a sus sonidos.
+<floater name="mute by name" title="IGNORAR UN OBJETO SEGÚN SU NOMBRE">
+ <text name="message" bottom_delta="-40">
+ Ignorar según el nombre sólo afecta al chat y los MI del
+objeto, no a sus sonidos.
Debe escribir exactamente el nombre del objeto.
</text>
- <line_editor name="object_name">
+ <line_editor name="object_name" bottom_delta="-58">
Nombre del objeto
</line_editor>
<button label="OK" name="OK"/>
diff --git a/indra/newview/skins/default/xui/es/floater_my_friends.xml b/indra/newview/skins/default/xui/es/floater_my_friends.xml
index d555eed305..07f362560b 100644
--- a/indra/newview/skins/default/xui/es/floater_my_friends.xml
+++ b/indra/newview/skins/default/xui/es/floater_my_friends.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_my_friends" title="Contactos">
+<floater name="floater_my_friends" title="CONTACTOS">
<tab_container name="friends_and_groups">
<panel label="Amigos" name="friends_panel"/>
<panel label="Grupos" name="groups_panel"/>
diff --git a/indra/newview/skins/default/xui/es/floater_openobject.xml b/indra/newview/skins/default/xui/es/floater_openobject.xml
index c7846afa6a..89c79e8833 100644
--- a/indra/newview/skins/default/xui/es/floater_openobject.xml
+++ b/indra/newview/skins/default/xui/es/floater_openobject.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="objectcontents" title="Contenido del objeto">
- <text length="1" name="object_name" type="string">
+<floater name="objectcontents" title="CONTENIDO DEL OBJETO">
+ <text name="object_name">
[DESC]:
</text>
<button label="Copiar al inventario" label_selected="Copiar al inventario" name="copy_to_inventory_button"/>
diff --git a/indra/newview/skins/default/xui/es/floater_pay.xml b/indra/newview/skins/default/xui/es/floater_pay.xml
index 9770e90bf4..64156d94e3 100644
--- a/indra/newview/skins/default/xui/es/floater_pay.xml
+++ b/indra/newview/skins/default/xui/es/floater_pay.xml
@@ -6,16 +6,17 @@
<button label="20 L$" label_selected="20 L$" name="fastpay 20"/>
<button label="Pagar" label_selected="Pagar" name="pay btn"/>
<button label="Cancelar" label_selected="Cancelar" name="cancel btn"/>
- <text length="1" name="payee_label" type="string">
+ <text name="payee_label" left="5" width="105">
Pagar al residente:
</text>
- <text length="1" name="payee_name" type="string">
+ <text name="payee_name" left="115">
[FIRST] [LAST]
</text>
- <text length="1" name="fastpay text" type="string">
+ <text name="fastpay text" width="100" halign="left">
Pago rápido:
</text>
- <text length="1" name="amount text" type="string">
+ <text name="amount text" left="4" >
Cantidad:
</text>
+ <line_editor left="60" name="amount" width="55"/>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_pay_object.xml b/indra/newview/skins/default/xui/es/floater_pay_object.xml
index 86b3af76f8..b5eca53bfa 100644
--- a/indra/newview/skins/default/xui/es/floater_pay_object.xml
+++ b/indra/newview/skins/default/xui/es/floater_pay_object.xml
@@ -1,24 +1,24 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Give Money" title="">
- <text length="1" name="payee_group" type="string">
+ <text name="payee_group" left="5" width="110">
Pagar al grupo:
</text>
- <text length="1" name="payee_resident" type="string">
+ <text name="payee_resident" left="5" width="110">
Pagar al residente:
</text>
- <text length="1" name="payee_name" type="string">
+ <text name="payee_name" left="120" width="180">
[FIRST] [LAST]
</text>
- <text length="1" name="object_name_label" type="string">
+ <text name="object_name_label" left="5" width="110">
A través del objeto:
</text>
- <text length="1" name="object_name_text" type="string">
+ <text name="object_name_text" left="120" width="180">
...
</text>
- <text length="1" name="fastpay text" type="string">
+ <text name="fastpay text">
Pago rápido:
</text>
- <text length="1" name="amount text" type="string">
+ <text name="amount text">
Cantidad:
</text>
<button label="1 L$" label_selected="1 L$" name="fastpay 1"/>
diff --git a/indra/newview/skins/default/xui/es/floater_perm_prefs.xml b/indra/newview/skins/default/xui/es/floater_perm_prefs.xml
index 4a3977be3d..7d3c8e62f3 100644
--- a/indra/newview/skins/default/xui/es/floater_perm_prefs.xml
+++ b/indra/newview/skins/default/xui/es/floater_perm_prefs.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="perm prefs" title="Permisos de subida por defecto">
+<floater name="perm prefs" title="PERMISOS DE SUBIDA POR DEFECTO">
<panel label="Permisos" name="permissions">
<button label="?" label_selected="?" name="help"/>
<check_box label="Compartir con el grupo" name="share_with_group"/>
diff --git a/indra/newview/skins/default/xui/es/floater_post_process.xml b/indra/newview/skins/default/xui/es/floater_post_process.xml
index acac2b2bf9..5c62ccde36 100644
--- a/indra/newview/skins/default/xui/es/floater_post_process.xml
+++ b/indra/newview/skins/default/xui/es/floater_post_process.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Post-Process Floater" title="Configuración del procesamiento">
+<floater name="Post-Process Floater" title="CONFIGURACIÓN DEL PROCESAMIENTO">
<tab_container name="Post-Process Tabs">
<panel label="Color del filtro" name="wmiColorFilterPanel">
<check_box label="Activar" name="wmiColorFilterToggle"/>
diff --git a/indra/newview/skins/default/xui/es/floater_postcard.xml b/indra/newview/skins/default/xui/es/floater_postcard.xml
index 06f8e7294a..ace3204cc7 100644
--- a/indra/newview/skins/default/xui/es/floater_postcard.xml
+++ b/indra/newview/skins/default/xui/es/floater_postcard.xml
@@ -1,11 +1,15 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Postcard" title="Foto por correo electrónico">
+<floater name="Postcard" title="FOTO POR CORREO ELECTRÓNICO">
<text name="to_label">
- Correo electrónico del destinatario:
+ Correo electrónico
+ del destinatario:
</text>
- <text name="from_label">
- Su correo electrónico:
+ <line_editor bottom_delta="-20" name="to_form" />
+ <text name="from_label" bottom_delta="-12">
+ Su correo
+ electrónico:
</text>
+ <line_editor bottom_delta="-20" name="from_form" />
<text name="name_label">
Su nombre:
</text>
@@ -13,24 +17,25 @@
Asunto:
</text>
<line_editor label="Escriba aquí el asunto." name="subject_form"/>
- <text name="msg_label">
+ <text name="msg_label" bottom_delta="-18">
Mensaje:
</text>
<text_editor name="msg_form">
Escriba aquí el mensaje.
</text_editor>
- <text name="fine_print">
- Si su destinatario se registra en SL, usted conseguirá un bono de referido.
+ <text name="fine_print" bottom_delta="-21">
+ Si su destinatario se registra en [SECOND_LIFE],
+usted conseguirá un bono de referido.
</text>
<button label="Cancelar" name="cancel_btn"/>
<button label="Enviar" name="send_btn"/>
<string name="default_subject">
- Postal desde Second Life.
+ Postal desde [SECOND_LIFE]
</string>
<string name="default_message">
¡Mira esto!
</string>
<string name="upload_message">
- &quot;Enviando...&quot;
+ Enviando...
</string>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_preferences.xml b/indra/newview/skins/default/xui/es/floater_preferences.xml
index 56e99e2285..5fe4ae3b64 100644
--- a/indra/newview/skins/default/xui/es/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/es/floater_preferences.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Preferences" title="Preferencias">
+<floater name="Preferences" title="PREFERENCIAS" min_width="350" width="646">
<button label="OK" label_selected="OK" name="OK"/>
<button label="Cancelar" label_selected="Cancelar" name="Cancel"/>
<button label="Aplicar" label_selected="Aplicar" name="Apply"/>
- <button label="Acerca de" label_selected="Acerca de" name="About..."/>
+ <button label="Acerca de..." label_selected="Acerca de..." name="About..." />
<button label="Ayuda" label_selected="Ayuda" name="Help"/>
+ <tab_container name="pref core" tab_width="146" width="646" />
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_preview_animation.xml b/indra/newview/skins/default/xui/es/floater_preview_animation.xml
index cea2273089..0d9cf8ec9f 100644
--- a/indra/newview/skins/default/xui/es/floater_preview_animation.xml
+++ b/indra/newview/skins/default/xui/es/floater_preview_animation.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="preview_anim">
- <text length="1" name="desc txt" type="string">
+ <text name="desc txt">
Descripción:
</text>
- <button label="Ejecutarla en el mundo" label_selected="Parar" name="Anim play btn" tool_tip="Ejecutar esta animación de modo que puedan verla los demás."/>
- <button label="Ejecutarla para usted" label_selected="Parar" name="Anim audition btn" tool_tip="Ejecutar esta animación de modo que sólo la vea usted."/>
+ <button left="12" width="142" label="Ejecutarla en el mundo" label_selected="Parar" name="Anim play btn" tool_tip="Ejecutar esta animación de modo que puedan verla los demás."/>
+ <button left="156" width="136" label="Ejecutarla para usted" label_selected="Parar" name="Anim audition btn" tool_tip="Ejecutar esta animación de modo que sólo la vea usted."/>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_preview_classified.xml b/indra/newview/skins/default/xui/es/floater_preview_classified.xml
index f2fa38ead8..8114c7f3c2 100644
--- a/indra/newview/skins/default/xui/es/floater_preview_classified.xml
+++ b/indra/newview/skins/default/xui/es/floater_preview_classified.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="classified_preview" title="Información clasificada"/>
+<floater name="classified_preview" title="INFORMACIÓN CLASIFICADA"/>
diff --git a/indra/newview/skins/default/xui/es/floater_preview_event.xml b/indra/newview/skins/default/xui/es/floater_preview_event.xml
index 7f727b0502..04cb0de4d4 100644
--- a/indra/newview/skins/default/xui/es/floater_preview_event.xml
+++ b/indra/newview/skins/default/xui/es/floater_preview_event.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="event_preview" title="Información de eventos"/>
+<floater name="event_preview" title="INFORMACIÓN DE EVENTOS"/>
diff --git a/indra/newview/skins/default/xui/es/floater_preview_gesture.xml b/indra/newview/skins/default/xui/es/floater_preview_gesture.xml
index 4513fc6f3c..0e43ce536c 100644
--- a/indra/newview/skins/default/xui/es/floater_preview_gesture.xml
+++ b/indra/newview/skins/default/xui/es/floater_preview_gesture.xml
@@ -15,15 +15,15 @@
<text name="trigger_label">
Palabra clave:
</text>
- <text name="replace_text" tool_tip="Reemplaza la/s palabra/s clave con estas palabras. Por ejemplo, si cambia la palabra clave &apos;hola&apos; por &apos;qué tal&apos;, se cambiará en el chat &apos;Quise decir hola&apos; por &apos;Quise decir qué tal&apos; en cuanto realice el gesto.">
+ <text left="208" name="replace_text" tool_tip="Reemplaza la/s palabra/s clave con estas palabras. Por ejemplo, si cambia la palabra clave &apos;hola&apos; por &apos;qué tal&apos;, se cambiará en el chat &apos;Quise decir hola&apos; por &apos;Quise decir qué tal&apos; en cuanto realice el gesto.">
Reemplazar por:
</text>
<line_editor name="replace_editor" tool_tip="Reemplaza la/s palabra/s clave con estas palabras. Por ejemplo, si cambia la palabra clave &apos;hola&apos; por &apos;qué tal&apos;, se cambiará en el chat &apos;Quise decir hola&apos; por &apos;Quise decir qué tal&apos; en cuanto realice el gesto."/>
<text name="key_label">
Atajo de teclado:
</text>
- <combo_box label="Ninguno" name="modifier_combo"/>
- <combo_box label="Ninguno" name="key_combo"/>
+ <combo_box label="Ninguno" name="modifier_combo" left="116" width="76"/>
+ <combo_box label="Ninguno" name="key_combo" width="76" left_delta="80"/>
<text name="library_label">
Biblioteca:
</text>
@@ -44,17 +44,15 @@ Esperar
Todos los pasos suceden a la vez,
a menos que añada pasos de espera.
</text>
+ <text left="230" name="options_text" width="200" />
<radio_group name="animation_trigger_type">
- <radio_item name="start">
- Empezar
- </radio_item>
- <radio_item name="stop">
- Parar
- </radio_item>
+ <radio_item name="start" label="Empezar" />
+ <radio_item name="stop" label="Parar" />
</radio_group>
- <check_box label="hasta que las animaciones estén hechas" name="wait_anim_check"/>
- <check_box label="tiempo en segundos" name="wait_time_check"/>
- <check_box label="Disponible" name="active_check" tool_tip="Los gestos disponibles pueden realizarse escribiendo en el chat su frase clave o pulsando su tecla de acceso rápido. Generalmente, los gestos pasan a no disponibles cuando hay un conflicto de teclas."/>
- <button label="Vista previa" name="preview_btn"/>
+ <check_box bottom_delta="34" label="hasta que las animaciones &#10;estén hechas" name="wait_anim_check"/>
+ <check_box bottom_delta="-30" label="tiempo en segundos" name="wait_time_check"/>
+ <line_editor left_delta="130" name="wait_time_editor" />
+ <check_box left="130" label="Disponible" name="active_check" tool_tip="Los gestos disponibles pueden realizarse escribiendo en el chat su frase clave o pulsando su tecla de acceso rápido. Generalmente, los gestos pasan a no disponibles cuando hay un conflicto de teclas."/>
+ <button label="Vista previa" name="preview_btn" width="85"/>
<button label="Guardar" name="save_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_preview_notecard.xml b/indra/newview/skins/default/xui/es/floater_preview_notecard.xml
index 2d13e41924..35f795a7ec 100644
--- a/indra/newview/skins/default/xui/es/floater_preview_notecard.xml
+++ b/indra/newview/skins/default/xui/es/floater_preview_notecard.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="preview notecard" title="Nota:">
+<floater name="preview notecard" title="NOTA:">
<button label="Guardar" label_selected="Guardar" name="Save"/>
- <text length="1" name="desc txt" type="string">
+ <text name="desc txt">
Descripción:
</text>
- <text_editor length="1" name="Notecard Editor" type="string">
+ <text_editor name="Notecard Editor">
Cargando...
</text_editor>
<string name="no_object">
diff --git a/indra/newview/skins/default/xui/es/floater_preview_sound.xml b/indra/newview/skins/default/xui/es/floater_preview_sound.xml
index 82c01e1d1b..060a033b08 100644
--- a/indra/newview/skins/default/xui/es/floater_preview_sound.xml
+++ b/indra/newview/skins/default/xui/es/floater_preview_sound.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="preview_sound">
- <text length="1" name="desc txt" type="string">
+ <text name="desc txt">
Descripción:
</text>
<button label="Tocar en el mundo" label_selected="Tocar en el mundo" name="Sound play btn" tool_tip="Tocar este sonido para que puedan oírlo los demás."/>
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 2fb66f1fdc..280438fefd 100644
--- a/indra/newview/skins/default/xui/es/floater_preview_texture.xml
+++ b/indra/newview/skins/default/xui/es/floater_preview_texture.xml
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="preview_texture">
- <text length="1" name="desc txt" type="string">
+ <text name="desc txt">
Descripción:
</text>
- <text length="1" name="dimensions" type="string">
+ <text name="dimensions">
Tamaño: [WIDTH] x [HEIGHT]
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_region_info.xml b/indra/newview/skins/default/xui/es/floater_region_info.xml
index b5a85378c2..46d0839238 100644
--- a/indra/newview/skins/default/xui/es/floater_region_info.xml
+++ b/indra/newview/skins/default/xui/es/floater_region_info.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="regioninfo" title="Región/Estado"/>
+<floater name="regioninfo" title="REGIÓN/ESTADO"/>
diff --git a/indra/newview/skins/default/xui/es/floater_report_abuse.xml b/indra/newview/skins/default/xui/es/floater_report_abuse.xml
index 0624f48a01..a075c51247 100644
--- a/indra/newview/skins/default/xui/es/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/es/floater_report_abuse.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_report_abuse" title="Denuncia de Infracción">
+<floater name="floater_report_abuse" title="DENUNCIA DE INFRACCIÓN">
<texture_picker label="" name="screenshot"/>
<check_box label="Incluir una captura de pantalla" name="screen_check"/>
<text name="reporter_title">
@@ -37,123 +37,45 @@
Hendrerit Vulputate
</text>
<combo_box name="category_combo" tool_tip="Categoría -- Elija la categoría que describa mejor esta denuncia">
- <combo_item name="Select_category">
- Elegir la categoría
- </combo_item>
- <combo_item name="Age__Age_play">
- Edad &gt; Jugar a ser niño
- </combo_item>
- <combo_item name="Age__Adult_resident_on_Teen_Second_Life">
- Edad &gt; Residente adulto en Teen Second Life
- </combo_item>
- <combo_item name="Age__Underage_resident_outside_of_Teen_Second_Life">
- Edad &gt; Residente menor de edad fuera de Teen Second Life
- </combo_item>
- <combo_item name="Assault__Combat_sandbox___unsafe_area">
- Ataque &gt; Sandbox de combate / Zona no segura
- </combo_item>
- <combo_item name="Assault__Safe_area">
- Ataque &gt; Zona segura
- </combo_item>
- <combo_item name="Assault__Weapons_testing_sandbox">
- Ataque &gt; Sandbox de prueba de armas
- </combo_item>
- <combo_item name="Commerce__Failure_to_deliver_product_or_service">
- Comercio &gt; Error en la entrega de productos o servicios
- </combo_item>
- <combo_item name="Disclosure__Real_world_information">
- Indiscreción &gt; Información del mundo real
- </combo_item>
- <combo_item name="Disclosure__Remotely_monitoring chat">
- Indiscreción &gt; Monitorizar a distancia el chat
- </combo_item>
- <combo_item name="Disclosure__Second_Life_information_chat_IMs">
- Indiscreción &gt; Información Se Second Life, el chat o los MI
- </combo_item>
- <combo_item name="Disturbing_the_peace__Unfair_use_of_region_resources">
- Perturbando la paz &gt; Abuso de los recursos de la región
- </combo_item>
- <combo_item name="Disturbing_the_peace__Excessive_scripted_objects">
- Perturbando la paz &gt; Excesivos objetos con script
- </combo_item>
- <combo_item name="Disturbing_the_peace__Object_littering">
- Perturbando la paz &gt; Objeto basura
- </combo_item>
- <combo_item name="Disturbing_the_peace__Repetitive_spam">
- Perturbando la paz &gt; Spam (mensajes no pedidos) repetitivo
- </combo_item>
- <combo_item name="Disturbing_the_peace__Unwanted_advert_spam">
- Perturbando la paz &gt; Publicidad no deseada
- </combo_item>
- <combo_item name="Fraud__L$">
- Fraude &gt; L$
- </combo_item>
- <combo_item name="Fraud__Land">
- Fraude &gt; Terreno
- </combo_item>
- <combo_item name="Fraud__Pyramid_scheme_or_chain_letter">
- Fraude &gt; Esquemas piramidales o cadenas de cartas
- </combo_item>
- <combo_item name="Fraud__US$">
- Fraude &gt; US$
- </combo_item>
- <combo_item name="Harassment__Advert_farms___visual_spam">
- Acoso &gt; Anuncios múltiples / Spam visual
- </combo_item>
- <combo_item name="Harassment__Defaming_individuals_or_groups">
- Acoso &gt; Difamación de individuos o grupos
- </combo_item>
- <combo_item name="Harassment__Impeding_movement">
- Acoso &gt; Impedir el movimiento
- </combo_item>
- <combo_item name="Harassment__Sexual_harassment">
- Acoso &gt; Acoso sexual
- </combo_item>
- <combo_item name="Harassment__Solicting_inciting_others_to_violate_ToS">
- Acoso &gt; Incitar a, o pedir, que otros violen las Condiciones del Servicio
- </combo_item>
- <combo_item name="Harassment__Verbal_abuse">
- Acoso &gt; Abuso verbal
- </combo_item>
- <combo_item name="Indecency__Broadly_offensive_content_or_conduct">
- Indecencia &gt; En general, contenido o conducta ofensivos
- </combo_item>
- <combo_item name="Indecency__Inappropriate_avatar_name">
- Indecencia &gt; Nombre inapropiado del avatar
- </combo_item>
- <combo_item name="Indecency__Mature_content_in_PG_region">
- Indecencia &gt; Contenido o conducta inapropiada en una región &apos;PG&apos;
- </combo_item>
- <combo_item name="Indecency__Inappropriate_content_in_Mature_region">
- Indecencia &gt; Contenido o conducta inapropiada en una región &apos;Mature&apos;
- </combo_item>
- <combo_item name="Intellectual_property_infringement_Content_Removal">
- Infracción de la propiedad intelectual &gt; Eliminación de contenidos
- </combo_item>
- <combo_item name="Intellectual_property_infringement_CopyBot_or_Permissions_Exploit">
- Infracción de la propiedad intelectual &gt; CopyBot o Exploit (programa malicioso) de permisos
- </combo_item>
- <combo_item name="Intolerance">
- Intolerancia
- </combo_item>
- <combo_item name="Land__Abuse_of_sandbox_resources">
- Terreno &gt; Abuso de los recursos de un sandbox
- </combo_item>
- <combo_item name="Land__Encroachment__Objects_textures">
- Terreno &gt; Invasión &gt; Objetos/Texturas
- </combo_item>
- <combo_item name="Land__Encroachment__Particles">
- Terreno &gt; Invasión &gt; Partículas
- </combo_item>
- <combo_item name="Land__Encroachment__Trees_plants">
- Terreno &gt; Invasión &gt; Ãrboles/Plantas
- </combo_item>
- <combo_item name="Wagering_gambling">
- Apuestas/Juego
- </combo_item>
- <combo_item name="Other">
- Otra
- </combo_item>
+ <combo_box.item name="Select_category" label="Elegir la categoría"/>
+ <combo_box.item name="Age__Age_play" label="Edad &gt; Jugar a ser niño"/>
+ <combo_box.item name="Age__Adult_resident_on_Teen_Second_Life" label="Edad &gt; Residente adulto en Teen Second Life"/>
+ <combo_box.item name="Age__Underage_resident_outside_of_Teen_Second_Life" label="Edad &gt; Residente menor de edad fuera de Teen Second Life"/>
+ <combo_box.item name="Assault__Combat_sandbox___unsafe_area" label="Ataque &gt; Sandbox de combate / Zona no segura"/>
+ <combo_box.item name="Assault__Safe_area" label="Ataque &gt; Zona segura"/>
+ <combo_box.item name="Assault__Weapons_testing_sandbox" label="Ataque &gt; Sandbox de prueba de armas"/>
+ <combo_box.item name="Commerce__Failure_to_deliver_product_or_service" label="Comercio &gt; Error en la entrega de productos o servicios"/>
+ <combo_box.item name="Disclosure__Real_world_information" label="Indiscreción &gt; Información del mundo real"/>
+ <combo_box.item name="Disclosure__Remotely_monitoring chat" label="Indiscreción &gt; Monitorizar a distancia el chat"/>
+ <combo_box.item name="Disclosure__Second_Life_information_chat_IMs" label="Indiscreción &gt; Información Se Second Life, el chat o los MI"/>
+ <combo_box.item name="Disturbing_the_peace__Unfair_use_of_region_resources" label="Perturbando la paz &gt; Abuso de los recursos de la región"/>
+ <combo_box.item name="Disturbing_the_peace__Excessive_scripted_objects" label="Perturbando la paz &gt; Excesivos objetos con script"/>
+ <combo_box.item name="Disturbing_the_peace__Object_littering" label="Perturbando la paz &gt; Objeto basura"/>
+ <combo_box.item name="Disturbing_the_peace__Repetitive_spam" label="Perturbando la paz &gt; Spam (mensajes no pedidos) repetitivo"/>
+ <combo_box.item name="Disturbing_the_peace__Unwanted_advert_spam" label="Perturbando la paz &gt; Publicidad no deseada"/>
+ <combo_box.item name="Fraud__L$" label="Fraude &gt; L$"/>
+ <combo_box.item name="Fraud__Land" label="Fraude &gt; Terreno"/>
+ <combo_box.item name="Fraud__Pyramid_scheme_or_chain_letter" label="Fraude &gt; Esquemas piramidales o cadenas de cartas"/>
+ <combo_box.item name="Fraud__US$" label="Fraude &gt; US$"/>
+ <combo_box.item name="Harassment__Advert_farms___visual_spam" label="Acoso &gt; Anuncios múltiples / Spam visual"/>
+ <combo_box.item name="Harassment__Defaming_individuals_or_groups" label="Acoso &gt; Difamación de individuos o grupos"/>
+ <combo_box.item name="Harassment__Impeding_movement" label="Acoso &gt; Impedir el movimiento"/>
+ <combo_box.item name="Harassment__Sexual_harassment" label="Acoso &gt; Acoso sexual"/>
+ <combo_box.item name="Harassment__Solicting_inciting_others_to_violate_ToS" label="Acoso &gt; Incitar a, o pedir, que otros violen las Condiciones del Servicio"/>
+ <combo_box.item name="Harassment__Verbal_abuse" label="Acoso &gt; Abuso verbal"/>
+ <combo_box.item name="Indecency__Broadly_offensive_content_or_conduct" label="Indecencia &gt; En general, contenido o conducta ofensivos"/>
+ <combo_box.item name="Indecency__Inappropriate_avatar_name" label="Indecencia &gt; Nombre inapropiado del avatar"/>
+ <combo_box.item name="Indecency__Mature_content_in_PG_region" label="Indecencia &gt; Contenido o conducta inapropiada en una región &apos;PG&apos;"/>
+ <combo_box.item name="Indecency__Inappropriate_content_in_Mature_region" label="Indecencia &gt; Contenido o conducta inapropiada en una región &apos;Mature&apos;"/>
+ <combo_box.item name="Intellectual_property_infringement_Content_Removal" label="Infracción de la propiedad intelectual &gt; Eliminación de contenidos"/>
+ <combo_box.item name="Intellectual_property_infringement_CopyBot_or_Permissions_Exploit" label="Infracción de la propiedad intelectual &gt; CopyBot o Exploit (programa malicioso) de permisos"/>
+ <combo_box.item name="Intolerance" label="Intolerancia"/>
+ <combo_box.item name="Land__Abuse_of_sandbox_resources" label="Terreno &gt; Abuso de los recursos de un sandbox"/>
+ <combo_box.item name="Land__Encroachment__Objects_textures" label="Terreno &gt; Invasión &gt; Objetos/Texturas"/>
+ <combo_box.item name="Land__Encroachment__Particles" label="Terreno &gt; Invasión &gt; Partículas"/>
+ <combo_box.item name="Land__Encroachment__Trees_plants" label="Terreno &gt; Invasión &gt; Ãrboles/Plantas"/>
+ <combo_box.item name="Wagering_gambling" label="Apuestas/Juego"/>
+ <combo_box.item name="Other" label="Otra"/>
</combo_box>
<text name="abuser_name_title">
Nombre del infractor:
@@ -170,7 +92,9 @@
Detalles:
</text>
<text name="bug_aviso">
- Por favor, sea muy concreto sobre la fecha, la localización, la naturaleza de la infracción, el aportar textos relevantes del chat o los MI, y, si es posible, seleccione el objeto.
+ Por favor, sea muy concreto sobre la fecha, la localización,
+la naturaleza de la infracción, el aportar textos relevantes
+del chat o los MI, y, si es posible, seleccione el objeto.
</text>
<text name="incomplete_title">
Nota: las denuncias incompletas no se investigarán.
diff --git a/indra/newview/skins/default/xui/es/floater_script_debug.xml b/indra/newview/skins/default/xui/es/floater_script_debug.xml
index e33ffb7d96..e7eddfd9f3 100644
--- a/indra/newview/skins/default/xui/es/floater_script_debug.xml
+++ b/indra/newview/skins/default/xui/es/floater_script_debug.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<multi_floater name="script debug floater" title="Alerta/Error de los scripts">
<tab_container name="Preview Tabs">
- <floater label="Script" name="all_scripts" title="[Todos los scripts]"/>
+ <floater label="Script" name="all_scripts" title="[ALL SCRIPTS]"/>
</tab_container>
</multi_floater>
diff --git a/indra/newview/skins/default/xui/es/floater_script_preview.xml b/indra/newview/skins/default/xui/es/floater_script_preview.xml
index f8d143af9d..79984e7bc1 100644
--- a/indra/newview/skins/default/xui/es/floater_script_preview.xml
+++ b/indra/newview/skins/default/xui/es/floater_script_preview.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="preview lsl text" title="Script: script de rotación">
- <text length="1" name="desc txt" type="string">
+<floater name="preview lsl text" title="SCRIPT: SCRIPT DE ROTACIÓN">
+ <text name="desc txt">
Descripción:
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_script_queue.xml b/indra/newview/skins/default/xui/es/floater_script_queue.xml
index dcd2bfe5b0..ace596cd9a 100644
--- a/indra/newview/skins/default/xui/es/floater_script_queue.xml
+++ b/indra/newview/skins/default/xui/es/floater_script_queue.xml
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="queue" title="Reinicio">
+<floater name="queue" title="REINICIO">
<button label="Cerrar" label_selected="Cerrar" name="close"/>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_script_search.xml b/indra/newview/skins/default/xui/es/floater_script_search.xml
index 9cabed9e36..a59f258a18 100644
--- a/indra/newview/skins/default/xui/es/floater_script_search.xml
+++ b/indra/newview/skins/default/xui/es/floater_script_search.xml
@@ -1,13 +1,15 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="script search" title="Buscar en el script">
- <check_box label="Indiferente mays./mins." name="case_text"/>
- <button label="Buscar" label_selected="Buscar" name="search_btn"/>
- <button label="Reemplazar" label_selected="Reemplazar" name="replace_btn"/>
- <button label="Reemplazar todos" label_selected="Reemplazar todos" name="replace_all_btn"/>
- <text length="1" name="txt" type="string">
+<floater name="script search" title="BUSCAR EN EL SCRIPT" width="320">
+ <check_box label="Indiferente mays./mins." name="case_text" left="75"/>
+ <button label="Buscar" label_selected="Buscar" name="search_btn" width="85"/>
+ <button label="Reemplazar" label_selected="Reemplazar" name="replace_btn" left="100" width="85"/>
+ <button label="Reemplazar todos" label_selected="Reemplazar todos" name="replace_all_btn" left="190" width="122"/>
+ <text name="txt" width="65">
Buscar
</text>
- <text length="1" name="txt2" type="string">
+ <text name="txt2" width="65">
Reemplazar
</text>
+ <line_editor left="75" name="search_text" width="240" />
+ <line_editor left="75" name="replace_text" width="240" />
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_select_key.xml b/indra/newview/skins/default/xui/es/floater_select_key.xml
index 132985864c..9c889df63a 100644
--- a/indra/newview/skins/default/xui/es/floater_select_key.xml
+++ b/indra/newview/skins/default/xui/es/floater_select_key.xml
@@ -2,6 +2,6 @@
<floater name="modal container" title="">
<button label="Cancelar" label_selected="Cancelar" name="Cancel"/>
<text name="Save item as:">
- Pulse una tecla para seleccionar
+ Pulse una tecla para seleccionarla
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_sell_land.xml b/indra/newview/skins/default/xui/es/floater_sell_land.xml
index 26aa56f22b..c6e8746250 100644
--- a/indra/newview/skins/default/xui/es/floater_sell_land.xml
+++ b/indra/newview/skins/default/xui/es/floater_sell_land.xml
@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="sell land" title="Vender el terreno">
+<floater name="sell land" title="VENDER EL TERRENO">
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
<text name="info_parcel_label">
Parcela:
</text>
@@ -35,15 +37,9 @@
Elija si venderlo a cualquiera o a un comprador concreto.
</text>
<combo_box name="sell_to">
- <combo_item name="--selectone--">
- -- seleccione --
- </combo_item>
- <combo_item name="Anyone">
- Cualquiera
- </combo_item>
- <combo_item name="Specificuser:">
- Un usuario concreto:
- </combo_item>
+ <combo_box.item name="--selectone--" label="seleccione --" />
+ <combo_box.item name="Anyone" label="Cualquiera" />
+ <combo_box.item name="Specificuser:" label="Un usuario concreto:" />
</combo_box>
<button label="Seleccionar..." name="sell_to_select_agent"/>
<text name="sell_objects_label">
@@ -54,12 +50,8 @@
de propietario.
</text>
<radio_group name="sell_objects" bottom_delta="-58" >
- <radio_item name="no">
- No, mantener la propiedad de los objetos
- </radio_item>
- <radio_item name="yes">
- Sí, vender los objetos con el terreno
- </radio_item>
+ <radio_item name="no" label="No, mantener la propiedad de los objetos" />
+ <radio_item name="yes" label="Sí, vender los objetos con el terreno" />
</radio_group>
<button label="Mostrar los objetos" name="show_objects" width="120"/>
<text name="nag_message_label">
@@ -67,4 +59,6 @@ de propietario.
</text>
<button label="Poner el terreno en venta" name="sell_btn"/>
<button label="Cancelar" name="cancel_btn"/>
+ </panel>
+ </scroll_container>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_settings_debug.xml b/indra/newview/skins/default/xui/es/floater_settings_debug.xml
index 056d71a7bc..0e8e6bdfd2 100644
--- a/indra/newview/skins/default/xui/es/floater_settings_debug.xml
+++ b/indra/newview/skins/default/xui/es/floater_settings_debug.xml
@@ -1,17 +1,13 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="settings_debug" title="Configuración del depurador">
+<floater name="settings_debug" title="CONFIGURACIÓN DEL DEPURADOR">
<combo_box name="boolean_combo">
- <combo_item name="TRUE">
- TRUE
- </combo_item>
- <combo_item name="FALSE">
- FALSE
- </combo_item>
+ <combo_box.item name="TRUE" label="TRUE" />
+ <combo_box.item name="FALSE" label="FALSE" />
</combo_box>
<color_swatch label="Color" name="color_swatch"/>
<spinner label="x" name="val_spinner_1"/>
<spinner label="x" name="val_spinner_2"/>
<spinner label="x" name="val_spinner_3"/>
<spinner label="x" name="val_spinner_4"/>
- <button label="Volver a las opciones por defecto" name="default_btn"/>
+ <button label="Volver a las opciones por defecto" name="default_btn" width="210"/>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_snapshot.xml b/indra/newview/skins/default/xui/es/floater_snapshot.xml
index ad23be3166..afea6c09fe 100644
--- a/indra/newview/skins/default/xui/es/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/es/floater_snapshot.xml
@@ -1,18 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Snapshot" title="Vista previa de la foto">
+<floater name="Snapshot" title="VISTA PREVIA DE LA FOTO">
<text name="type_label">
Destino de la foto
</text>
<radio_group label="Tipo de la foto" name="snapshot_type_radio">
- <radio_item name="postcard">
- Enviar por correo electrónico
- </radio_item>
- <radio_item name="texture">
- Guardarla en su inventario ([AMOUNT] L$)
- </radio_item>
- <radio_item name="local">
- Guardarla en su disco duro
- </radio_item>
+ <radio_item name="postcard" label="Enviar por correo electrónico" />
+ <radio_item name="texture" label="Guardarla en su inventario ([AMOUNT] L$)" />
+ <radio_item name="local" label="Guardarla en su disco duro" />
</radio_group>
<text name="file_size_label">
Tamaño del archivo: [SIZE] KB
@@ -21,12 +15,8 @@
<button label="Enviar" name="send_btn"/>
<button label="Guardar ([AMOUNT] L$)" name="upload_btn"/>
<flyout_button label="Guardar" name="save_btn" tool_tip="Guardar la imagen en un archivo">
- <flyout_button_item name="save_item">
- Guardar
- </flyout_button_item>
- <flyout_button_item name="saveas_item">
- Guardar como...
- </flyout_button_item>
+ <flyout_button_item name="save_item" label="Guardar"/>
+ <flyout_button_item name="saveas_item" label="Guardar como..."/>
</flyout_button>
<button label="Cancelar" name="discard_btn"/>
<button label="Más &gt;&gt;" name="more_btn" tool_tip="Opciones avanzadas"/>
@@ -38,99 +28,51 @@
Formato
</text>
<combo_box label="Resolución" name="postcard_size_combo">
- <combo_item name="CurrentWindow">
- Ventana actual
- </combo_item>
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
- <combo_item name="Custom">
- Personalizar
- </combo_item>
+ <combo_box.item name="CurrentWindow" label="Ventana actual"/>
+ <combo_box.item name="640x480" label="640x480"/>
+ <combo_box.item name="800x600" label="800x600"/>
+ <combo_box.item name="1024x768" label="1024x768"/>
+ <combo_box.item name="Custom" label="Personalizar"/>
</combo_box>
<combo_box label="Resolución" name="texture_size_combo">
- <combo_item name="CurrentWindow">
- Ventana actual
- </combo_item>
- <combo_item name="Small(128x128)">
- Pequeño (128x128)
- </combo_item>
- <combo_item name="Medium(256x256)">
- Medio (256x256)
- </combo_item>
- <combo_item name="Large(512x512)">
- Grande (512x512)
- </combo_item>
- <combo_item name="Custom">
- Personalizar
- </combo_item>
+ <combo_box.item name="CurrentWindow" label="Ventana actual"/>
+ <combo_box.item name="Small(128x128)" label="Pequeño (128x128)"/>
+ <combo_box.item name="Medium(256x256)" label="Medio (256x256)"/>
+ <combo_box.item name="Large(512x512)" label="Grande (512x512)"/>
+ <combo_box.item name="Custom" label="Personalizar"/>
</combo_box>
<combo_box label="Resolución" name="local_size_combo">
- <combo_item name="CurrentWindow">
- Ventana actual
- </combo_item>
- <combo_item name="320x240">
- 320x240
- </combo_item>
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
- <combo_item name="1280x1024">
- 1280x1024
- </combo_item>
- <combo_item name="1600x1200">
- 1600x1200
- </combo_item>
- <combo_item name="Custom">
- Personalizar
- </combo_item>
+ <combo_box.item name="CurrentWindow" label="Ventana actual"/>
+ <combo_box.item name="320x240" label="320x240"/>
+ <combo_box.item name="640x480" label="640x480"/>
+ <combo_box.item name="800x600" label="800x600"/>
+ <combo_box.item name="1024x768" label="1024x768"/>
+ <combo_box.item name="1280x1024" label="1280x1024"/>
+ <combo_box.item name="1600x1200" label="1600x1200"/>
+ <combo_box.item name="Custom" label="Personalizar"/>
</combo_box>
<combo_box label="Formato" name="local_format_combo">
- <combo_item name="PNG">
- PNG
- </combo_item>
- <combo_item name="JPEG">
- JPEG
- </combo_item>
- <combo_item name="BMP">
- BMP
- </combo_item>
+ <combo_box.item name="PNG" label="PNG"/>
+ <combo_box.item name="JPEG" label="JPEG"/>
+ <combo_box.item name="BMP" label="BMP"/>
</combo_box>
- <spinner label="Ancho" name="snapshot_width"/>
- <spinner label="Alto" name="snapshot_height"/>
+ <spinner label="Ancho" name="snapshot_width" label_width="41" width="101"/>
+ <spinner label="Alto" name="snapshot_height" label_width="30" width="90" left="121"/>
<check_box label="Mantener las proporciones" name="keep_aspect_check"/>
<slider label="Calidad de la imagen" name="image_quality_slider"/>
<text name="layer_type_label">
Captura:
</text>
<combo_box label="Capas de la imagen" name="layer_types">
- <combo_item name="Colors">
- Colores
- </combo_item>
- <combo_item name="Depth">
- Profundidad
- </combo_item>
- <combo_item name="ObjectMattes">
- Bandas negras
- </combo_item>
+ <combo_box.item name="Colors" label="Colores"/>
+ <combo_box.item name="Depth" label="Profundidad"/>
+ <combo_box.item name="ObjectMattes" label="Bandas negras"/>
</combo_box>
<check_box label="Incluir la interfaz en la foto" name="ui_check"/>
- <check_box label="Incluir los HUD en la foto" name="hud_check"/>
- <check_box label="Mantenerla abierta tras guardarla" name="keep_open_check"/>
- <check_box label="Congelar la toma (vista previa en pantalla completa)" name="freeze_frame_check"/>
- <check_box label="Actualizar automáticamente" name="auto_snapshot_check"/>
+ <check_box bottom_delta="-17" label="Incluir los HUD en la foto" name="hud_check"/>
+ <check_box bottom_delta="-17" label="Mantenerla abierta tras guardarla" name="keep_open_check"/>
+ <check_box bottom_delta="-17" label="Congelar la toma &#10;(vista previa en pantalla completa)" name="freeze_frame_check"/>
+ <check_box bottom_delta="-29" label="Actualizar automáticamente" name="auto_snapshot_check"/>
<string name="unknown">
desconocido
</string>
diff --git a/indra/newview/skins/default/xui/es/floater_sound_preview.xml b/indra/newview/skins/default/xui/es/floater_sound_preview.xml
index e69ac10123..8b8d9f13ce 100644
--- a/indra/newview/skins/default/xui/es/floater_sound_preview.xml
+++ b/indra/newview/skins/default/xui/es/floater_sound_preview.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Sound Preview" title="sound.wav">
+<floater name="Sound Preview" title="SOUND.WAV">
<text name="name_label">
Nombre:
</text>
diff --git a/indra/newview/skins/default/xui/es/floater_statistics.xml b/indra/newview/skins/default/xui/es/floater_statistics.xml
index 6e644cacf1..c9b0a76df0 100644
--- a/indra/newview/skins/default/xui/es/floater_statistics.xml
+++ b/indra/newview/skins/default/xui/es/floater_statistics.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="stats floater" title="Estadísticas"/>
+<floater name="stats floater" title="ESTADÃSTICAS"/>
diff --git a/indra/newview/skins/default/xui/es/floater_telehub.xml b/indra/newview/skins/default/xui/es/floater_telehub.xml
index 921577751a..b2dddfb7f7 100644
--- a/indra/newview/skins/default/xui/es/floater_telehub.xml
+++ b/indra/newview/skins/default/xui/es/floater_telehub.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="telehub" title="Punto de Teleporte">
+<floater name="telehub" title="PUNTO DE TELEPORTE" min_height="310" height="310">
<text name="status_text_connected">
Punto de Teleporte conectado al objeto [OBJECT]
</text>
@@ -9,20 +9,24 @@
<text name="help_text_connected">
Para quitar, pulse Desconectar.
</text>
- <text name="help_text_not_connected">
- Seleccione el objeto y pulse Conectar el Punto de Teleporte.
+ <text name="help_text_not_connected" height="38" bottom_delta="-18">
+ Seleccione el objeto y pulse Conectar el Punto
+de Teleporte.
</text>
<button label="Conectar el Punto de Teleporte" name="connect_btn"/>
<button label="Desconectar" name="disconnect_btn"/>
<text name="spawn_points_text">
- Spawn Points (positions, not objects):
+ Sucursales (posiciónes, no objetos):
</text>
<button label="Añadir sucursales" name="add_spawn_point_btn"/>
<button label="Quitar sucursales" name="remove_spawn_point_btn"/>
<text name="spawn_point_help">
- Seleccione el objeto y pulse Añadir para especificar la posición.
+ Seleccione el objeto y pulse Añadir para
+especificar la posición.
Hecho eso, puede mover o borrar el objeto.
-Las posiciones son relativas al centro del Punto de Teleporte.
-Seleccione un ítem de la lista para mostrar su posición en el mundo.
+Las posiciones son relativas al centro del
+Punto de Teleporte.
+Seleccione un ítem de la lista para mostrar su
+posición en el mundo.
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/es/floater_texture_ctrl.xml
index 8c3882f0c8..09d6e7e4aa 100644
--- a/indra/newview/skins/default/xui/es/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/es/floater_texture_ctrl.xml
@@ -1,16 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="texture picker" title="Elegir: Textura">
+<floater name="texture picker" title="ELEGIR: TEXTURA">
<string name="choose_picture">
Pulse para elegir una imagen
</string>
- <text length="1" name="Multiple" type="string">
+ <text name="Multiple">
Múltiple
</text>
- <text length="1" name="unknown" type="string">
+ <text name="unknown">
Dimensiones: [DIMENSIONS]
</text>
- <button label="Por defecto" label_selected="Por defecto" name="Default"/>
- <button label="Ninguna" label_selected="Ninguna" name="None"/>
+ <button label="Por defecto" label_selected="Por defecto" name="Default" width="84"/>
+ <button label="Ninguna" label_selected="Ninguna" name="None" left="90"/>
<button label="Blanca" label_selected="Blanca" name="Blank"/>
<check_box label="Ver las carpetas" name="show_folders_check"/>
<search_editor label="Escriba aquí para buscar una" name="inventory search editor"/>
diff --git a/indra/newview/skins/default/xui/es/floater_tools.xml b/indra/newview/skins/default/xui/es/floater_tools.xml
index 15c66c8366..24db352ac4 100644
--- a/indra/newview/skins/default/xui/es/floater_tools.xml
+++ b/indra/newview/skins/default/xui/es/floater_tools.xml
@@ -1,41 +1,44 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="toolbox floater" title="">
+<floater name="toolbox floater" title="" short_title="CONSTRUIR" width="288">
<button label="" label_selected="" name="button focus" tool_tip="Visión"/>
<button label="" label_selected="" name="button move" tool_tip="Mover"/>
<button label="" label_selected="" name="button edit" tool_tip="Editar"/>
<button label="" label_selected="" name="button create" tool_tip="Crear"/>
<button label="" label_selected="" name="button land" tool_tip="Terreno"/>
- <check_box label="Zoom" name="radio zoom"/>
- <check_box label="Órbita (Ctrl)" name="radio orbit"/>
- <check_box label="Panorámica (Ctrl-Shift)" name="radio pan"/>
- <check_box label="Mover" name="radio move"/>
- <check_box label="Vertical (Ctrl)" name="radio lift"/>
- <check_box label="Horizontal (Ctrl-Shift)" name="radio spin"/>
- <check_box label="Posición" name="radio position"/>
- <check_box label="Girar (Ctrl)" name="radio rotate"/>
- <check_box label="Estirar (Ctrl-Shift)" name="radio stretch"/>
- <check_box label="Elegir la cara" name="radio select face"/>
+ <radio_group name="focus_radio_group">
+ <radio_item label="Zoom" name="radio zoom"/>
+ <radio_item label="Órbita (Ctrl)" name="radio orbit"/>
+ <radio_item label="Panorámica (Ctrl-Shift)" name="radio pan"/>
+ </radio_group>
+ <radio_group name="move_radio_group">
+ <radio_item label="Mover" name="radio move"/>
+ <radio_item label="Vertical (Ctrl)" name="radio lift"/>
+ <radio_item label="Horizontal (Ctrl-Shift)" name="radio spin"/>
+ </radio_group>
+ <radio_group name="edit_radio_group">
+ <radio_item label="Posición" name="radio position"/>
+ <radio_item label="Girar (Ctrl)" name="radio rotate"/>
+ <radio_item label="Estirar (Ctrl-Shift)" name="radio stretch"/>
+ <radio_item label="Elegir la cara" name="radio select face"/>
+ </radio_group>
<check_box label="Editar las partes enlazadas" name="checkbox edit linked parts"/>
<text name="text ruler mode">
Ajuste:
</text>
- <combo_box name="combobox grid mode">
- <combo_item name="World">
- Mundo
- </combo_item>
- <combo_item name="Local">
- Local
- </combo_item>
- <combo_item name="Reference">
- Referencia
- </combo_item>
+ <combo_box name="combobox grid mode" width="82">
+ <combo_box.item name="World" label="Mundo"
+ />
+ <combo_box.item name="Local" label="Local"
+ />
+ <combo_box.item name="Reference" label="Referencia"
+ />
</combo_box>
<check_box label="Estirar ambos lados" name="checkbox uniform"/>
<check_box label="Estirar las texturas" name="checkbox stretch textures"/>
<check_box label="Usar la cuadrícula" name="checkbox snap to grid"/>
<button label="Opciones..." label_selected="Opciones..." name="Options..."/>
- <text name="text status">
- Arrastrar para mover, arrastrar + Mayús. para copiar
+ <text name="text status" width="280">
+ Arrastrar para mover, Mayús.+arrastrar para copiar
</text>
<button label="" label_selected="" name="ToolCube" tool_tip="Cubo"/>
<button label="" label_selected="" name="ToolPrism" tool_tip="Prisma"/>
@@ -56,14 +59,16 @@
<check_box label="Copia seleccionada" name="checkbox copy selection"/>
<check_box label="Centrada" name="checkbox copy centers"/>
<check_box label="Girada" name="checkbox copy rotates"/>
- <check_box label="Seleccionar el terreno" name="radio select land"/>
- <check_box label="Nivelar" name="radio flatten"/>
- <check_box label="Elevar" name="radio raise"/>
- <check_box label="Bajar" name="radio lower"/>
- <check_box label="Suavizar" name="radio smooth"/>
- <check_box label="Escarpar" name="radio noise"/>
- <check_box label="Restablecer" name="radio revert"/>
- <button label="Aplicar" label_selected="Aplicar" name="button apply to selection" tool_tip="Modificar el terreno seleccionado"/>
+ <radio_group name="land_radio_group">
+ <radio_item label="Seleccionar el terreno" name="radio select land"/>
+ <radio_item label="Nivelar" name="radio flatten"/>
+ <radio_item label="Elevar" name="radio raise"/>
+ <radio_item label="Bajar" name="radio lower"/>
+ <radio_item label="Suavizar" name="radio smooth"/>
+ <radio_item label="Escarpar" name="radio noise"/>
+ <radio_item label="Restablecer" name="radio revert"/>
+ </radio_group>
+ <button label="Aplicar" label_selected="Aplicar" name="button apply to selection" tool_tip="Modificar el terreno seleccionado" left="146"/>
<text name="Bulldozer:">
Bulldozer:
</text>
@@ -73,13 +78,13 @@
<text name="Strength:">
Fuerza
</text>
- <text name="obj_count">
+ <text name="obj_count" left="134">
Objetos seleccionados: [COUNT]
</text>
- <text name="prim_count">
+ <text name="prim_count" left="134">
primitivas: [COUNT]
</text>
- <tab_container name="Object Info Tabs">
+ <tab_container name="Object Info Tabs" tab_max_width="62" tab_min_width="30" width="288">
<panel label="General" name="General">
<text name="Name:">
Nombre:
@@ -111,9 +116,7 @@
<text name="Permissions:">
Permisos:
</text>
- <text name="perm_modify">
- Puede modificar este objeto.
- </text>
+
<check_box label="Compartir con el grupo" name="checkbox share with group" tool_tip="Permitir que todos los miembros del grupo compartan y utilicen sus permisos sobre este objeto. Debe transferirlo para activar las restricciones según los roles."/>
<string name="text deed continued">
Transferir...
@@ -129,49 +132,35 @@
<text name="Cost">
Precio: L$
</text>
- <radio_group name="sale type">
- <radio_item name="Original">
- Original
- </radio_item>
- <radio_item name="Copy">
- Copia
- </radio_item>
- <radio_item name="Contents">
- Contenidos
- </radio_item>
- </radio_group>
- <text name="Next owner can:">
- El próximo propietario puede:
- </text>
- <check_box label="Modificarlo" name="checkbox next owner can modify"/>
- <check_box label="Copiarlo" name="checkbox next owner can copy"/>
- <check_box label="Revenderlo/Darlo" name="checkbox next owner can transfer"/>
- <text name="label click action">
+ <combo_box name="sale type">
+ <combo_box.item label="Copia" name="Copy"/>
+ <combo_box.item label="Contenidos" name="Contents"/>
+ <combo_box.item label="Original" name="Original"/>
+ </combo_box>
+
+ <text name="label click action" width="180">
Al pulsarlo con el botón izquierdo:
</text>
- <combo_box name="clickaction">
- <combo_item name="Touch/grab(default)">
- Tocar/Agarrar (por defecto)
- </combo_item>
- <combo_item name="Sitonobject">
- Sentarse en el objeto
- </combo_item>
- <combo_item name="Buyobject">
- Comprar el objeto
- </combo_item>
- <combo_item name="Payobject">
- Pagar al objeto
- </combo_item>
- <combo_item name="Open">
- Abrirlo
- </combo_item>
- <combo_item name="Play">
- Ejecutar los media de la parcela
- </combo_item>
- <combo_item name="Opemmedia">
- Abrir los media de la parcela
- </combo_item>
+ <combo_box name="clickaction" width="192">
+ <combo_box.item name="Touch/grab(default)" label="Tocar/Agarrar (por defecto)"
+ />
+ <combo_box.item name="Sitonobject" label="Sentarse en el objeto"
+ />
+ <combo_box.item name="Buyobject" label="Comprar el objeto"
+ />
+ <combo_box.item name="Payobject" label="Pagar al objeto"
+ />
+ <combo_box.item name="Open" label="Abrirlo"
+ />
+ <combo_box.item name="Play" label="Ejecutar los media de la parcela"
+ />
+ <combo_box.item name="Opemmedia" label="Abrir los media de la parcela"
+ />
</combo_box>
+ <panel name="perms_build">
+ <text name="perm_modify">
+ Puede modificar este objeto
+ </text>
<text name="B:">
B:
</text>
@@ -190,29 +179,36 @@
<text name="F:">
F:
</text>
+ <text name="Next owner can:">
+ El próximo propietario puede:
+ </text>
+ <check_box label="Modificarlo" name="checkbox next owner can modify"/>
+ <check_box label="Copiarlo" name="checkbox next owner can copy" left_delta="80"/>
+ <check_box name="checkbox next owner can transfer" left_delta="67"/>
+ </panel>
<string name="text modify info 1">
- Puede modificar este objeto.
+ Puede modificar este objeto
</string>
<string name="text modify info 2">
- Puede modificar estos objetos.
+ Puede modificar estos objetos
</string>
<string name="text modify info 3">
- No puede modificar este objeto.
+ No puede modificar este objeto
</string>
<string name="text modify info 4">
- No puede modificar estos objetos.
+ No puede modificar estos objetos
</string>
<string name="text modify warning">
- Debe seleccionar todo el objeto para definir los permisos.
+ Debe seleccionar todo el objeto para definir los permisos
</string>
<string name="Cost Default">
- Precio: L$
+ Precio: L$
</string>
<string name="Cost Total">
- Precio total: L$
+ Precio total: L$
</string>
<string name="Cost Per Unit">
- Precio por: L$
+ Precio por: L$
</string>
<string name="Cost Mixed">
Precio variable
@@ -223,7 +219,7 @@
</panel>
<panel label="Objeto" name="Object">
<text name="select_single">
- Seleccione un único prim para editar los parámetros.
+ Seleccione un sólo prim para editarlo.
</text>
<text name="edit_object">
Modificar los parámetros del objeto:
@@ -254,56 +250,41 @@
Material
</text>
<combo_box name="material">
- <combo_item name="Stone">
- Piedra
- </combo_item>
- <combo_item name="Metal">
- Metal
- </combo_item>
- <combo_item name="Glass">
- Vidrio
- </combo_item>
- <combo_item name="Wood">
- Madera
- </combo_item>
- <combo_item name="Flesh">
- Carne
- </combo_item>
- <combo_item name="Plastic">
- Plástico
- </combo_item>
- <combo_item name="Rubber">
- Goma
- </combo_item>
+ <combo_box.item name="Stone" label="Piedra"
+ />
+ <combo_box.item name="Metal" label="Metal"
+ />
+ <combo_box.item name="Glass" label="Vidrio"
+ />
+ <combo_box.item name="Wood" label="Madera"
+ />
+ <combo_box.item name="Flesh" label="Carne"
+ />
+ <combo_box.item name="Plastic" label="Plástico"
+ />
+ <combo_box.item name="Rubber" label="Goma"
+ />
</combo_box>
<text name="label basetype">
- Tipo de objeto para construir
+ Tipo de objeto a construir
</text>
<combo_box name="comboBaseType">
- <combo_item name="Box">
- Caja
- </combo_item>
- <combo_item name="Cylinder">
- Cilindro
- </combo_item>
- <combo_item name="Prism">
- Prisma
- </combo_item>
- <combo_item name="Sphere">
- Esfera
- </combo_item>
- <combo_item name="Torus">
- Toroide
- </combo_item>
- <combo_item name="Tube">
- Tubo
- </combo_item>
- <combo_item name="Ring">
- Cono truncado
- </combo_item>
- <combo_item name="Sculpted">
- Sculpted
- </combo_item>
+ <combo_box.item name="Box" label="Caja"
+ />
+ <combo_box.item name="Cylinder" label="Cilindro"
+ />
+ <combo_box.item name="Prism" label="Prisma"
+ />
+ <combo_box.item name="Sphere" label="Esfera"
+ />
+ <combo_box.item name="Torus" label="Toroide"
+ />
+ <combo_box.item name="Tube" label="Tubo"
+ />
+ <combo_box.item name="Ring" label="Cono truncado"
+ />
+ <combo_box.item name="Sculpted" label="Sculpted"
+ />
</combo_box>
<text name="text cut">
Corte: Inicio y Fin
@@ -320,21 +301,17 @@
Forma del hueco
</text>
<combo_box name="hole">
- <combo_item name="Default">
- Por defecto
- </combo_item>
- <combo_item name="Circle">
- Círculo
- </combo_item>
- <combo_item name="Square">
- Cuadrado
- </combo_item>
- <combo_item name="Triangle">
- Triángulo
- </combo_item>
+ <combo_box.item name="Default" label="Por defecto"
+ />
+ <combo_box.item name="Circle" label="Círculo"
+ />
+ <combo_box.item name="Square" label="Cuadrado"
+ />
+ <combo_box.item name="Triangle" label="Triángulo"
+ />
</combo_box>
<text name="text twist">
- La torsión: Inicio y Fin
+ Torsión: Inicio y Fin
</text>
<spinner label="I" name="Twist Begin"/>
<spinner label="F" name="Twist End"/>
@@ -380,26 +357,21 @@
Tipo de unión
</text>
<combo_box name="sculpt type control">
- <combo_item name="None">
- (ninguna)
- </combo_item>
- <combo_item name="Sphere">
- Esfera
- </combo_item>
- <combo_item name="Torus">
- Toroide
- </combo_item>
- <combo_item name="Plane">
- Plano
- </combo_item>
- <combo_item name="Cylinder">
- Cilindro
- </combo_item>
+ <combo_box.item name="None" label="(ninguna)"
+ />
+ <combo_box.item name="Sphere" label="Esfera"
+ />
+ <combo_box.item name="Torus" label="Toroide"
+ />
+ <combo_box.item name="Plane" label="Plano"
+ />
+ <combo_box.item name="Cylinder" label="Cilindro"
+ />
</combo_box>
</panel>
- <panel label="Características" name="Features">
+ <panel label="Caracter." name="Features">
<text name="select_single">
- Seleccione un sólo prim para editar las características.
+ Seleccione un sólo prim para editarlo.
</text>
<text name="edit_object">
Editar las características del objeto:
@@ -431,93 +403,69 @@
<text name="glow label">
Resplandor
</text>
- <check_box label="Brillo al máximo" name="checkbox fullbright"/>
+ <check_box label="Brillo al &#10;máximo" name="checkbox fullbright" bottom_delta="-21"/>
<text name="tex gen">
Detallado
</text>
- <combo_box name="combobox texgen">
- <combo_item name="Default">
- Por defecto
- </combo_item>
- <combo_item name="Planar">
- Plano
- </combo_item>
+ <combo_box name="combobox texgen" width="86">
+ <combo_box.item name="Default" label="Por defecto"
+ />
+ <combo_box.item name="Planar" label="Plano"
+ />
</combo_box>
<text name="label shininess">
Brillantez
</text>
<combo_box name="combobox shininess">
- <combo_item name="None">
- Ninguna
- </combo_item>
- <combo_item name="Low">
- Baja
- </combo_item>
- <combo_item name="Medium">
- Media
- </combo_item>
- <combo_item name="High">
- Alta
- </combo_item>
+ <combo_box.item name="None" label="Ninguna"
+ />
+ <combo_box.item name="Low" label="Baja"
+ />
+ <combo_box.item name="Medium" label="Media"
+ />
+ <combo_box.item name="High" label="Alta"
+ />
</combo_box>
<text name="label bumpiness">
Relieve
</text>
<combo_box name="combobox bumpiness">
- <combo_item name="None">
- Ninguno
- </combo_item>
- <combo_item name="Brightness">
- Brillo
- </combo_item>
- <combo_item name="Darkness">
- Oscuro
- </combo_item>
- <combo_item name="woodgrain">
- grano de madera
- </combo_item>
- <combo_item name="bark">
- corteza
- </combo_item>
- <combo_item name="bricks">
- ladrillos
- </combo_item>
- <combo_item name="checker">
- cajero
- </combo_item>
- <combo_item name="concrete">
- cemento
- </combo_item>
- <combo_item name="crustytile">
- azulejería
- </combo_item>
- <combo_item name="cutstone">
- piedra cortada
- </combo_item>
- <combo_item name="discs">
- discos
- </combo_item>
- <combo_item name="gravel">
- grava
- </combo_item>
- <combo_item name="petridish">
- placa de Petri
- </combo_item>
- <combo_item name="siding">
- revestimiento
- </combo_item>
- <combo_item name="stonetile">
- baldosa de piedra
- </combo_item>
- <combo_item name="stucco">
- estuco
- </combo_item>
- <combo_item name="suction">
- succión
- </combo_item>
- <combo_item name="weave">
- tejido
- </combo_item>
+ <combo_box.item name="None" label="Ninguno"
+ />
+ <combo_box.item name="Brightness" label="Brillo"
+ />
+ <combo_box.item name="Darkness" label="Oscuro"
+ />
+ <combo_box.item name="woodgrain" label="grano de madera"
+ />
+ <combo_box.item name="bark" label="corteza"
+ />
+ <combo_box.item name="bricks" label="ladrillos"
+ />
+ <combo_box.item name="checker" label="cajero"
+ />
+ <combo_box.item name="concrete" label="cemento"
+ />
+ <combo_box.item name="crustytile" label="azulejería"
+ />
+ <combo_box.item name="cutstone" label="piedra cortada"
+ />
+ <combo_box.item name="discs" label="discos"
+ />
+ <combo_box.item name="gravel" label="grava"
+ />
+ <combo_box.item name="petridish" label="placa de Petri"
+ />
+ <combo_box.item name="siding" label="revestimiento"
+ />
+ <combo_box.item name="stonetile" label="baldosa de piedra"
+ />
+ <combo_box.item name="stucco" label="estuco"
+ />
+ <combo_box.item name="suction" label="succión"
+ />
+ <combo_box.item name="weave" label="tejido"
+ />
</combo_box>
<text name="tex scale">
Repeticiones por cara
@@ -530,29 +478,31 @@
Rotación (grados)
</text>
<string name="string repeats per meter">
- Repeticiones por metro
+ Repeticiones por m.
</string>
<string name="string repeats per face">
Repeticiones por cara
</string>
<text name="rpt">
- Repeticiones por metro
+ Repeticiones por m.
</text>
- <button label="Aplicar" label_selected="Aplicar" name="button apply"/>
+ <spinner left="118" name="TexRot" width="62" />
+ <spinner left="118" name="rptctrl" width="62" />
+ <button label="Aplicar" label_selected="Aplicar" name="button apply" left_delta="72"/>
<text name="tex offset">
Desplazar
</text>
<spinner label="Horizontal (U)" name="TexOffsetU"/>
<spinner label="Vertical (V)" name="TexOffsetV"/>
- <text name="textbox autofix">
+ <text name="textbox autofix" width="180">
Centrar la textura para los media
(primero debe subirla)
</text>
- <button label="Alinear" label_selected="Alinear" name="button align"/>
+ <button label="Alinear" label_selected="Alinear" name="button align" left="180"/>
</panel>
- <panel label="Contenido" name="Contents">
+ <panel label="Contenido " name="Contents">
<button label="Script nuevo" label_selected="Script nuevo" name="button new script"/>
- <button label="Permisos..." name="button permissions"/>
+ <button label="Permisos" name="button permissions"/>
</panel>
</tab_container>
<panel name="land info panel">
@@ -565,57 +515,57 @@
<text name="label_area">
Superficie: [AREA] m²
</text>
- <button label="Acerca del terreno..." label_selected="Acerca del terreno..." name="button about land"/>
- <check_box label="Mostrar los propietarios" name="checkbox show owners" tool_tip="El color de las parcelas es según su propietario"/>
- <button label="?" label_selected="?" name="button show owners help"/>
+ <button label="Acerca del terreno..." label_selected="Acerca del terreno..." name="button about land" width="140"/>
+ <check_box label="Mostrar los propietarios" name="checkbox show owners" tool_tip="El color de las parcelas es según su propietario: &#10;&#10;Verde = Su terreno &#10;Agua = Terreno de sus grupos &#10;Rojo = Propiedad de otros &#10;Amarillo = En venta &#10;Morado = Para subasta &#10;Gris = Público"/>
+ <button label="?" label_selected="?" name="button show owners help" left_delta="150"/>
<text name="label_parcel_modify">
Modificar la parcela
</text>
- <button label="Subdividir..." label_selected="Subdividir..." name="button subdivide land"/>
- <button label="Unir..." label_selected="Unir..." name="button join land"/>
+ <button label="Subdividir" label_selected="Subdividir" name="button subdivide land" width="140"/>
+ <button label="Unir" label_selected="Unir" name="button join land" width="140"/>
<text name="label_parcel_trans">
Transacciones de terreno
</text>
- <button label="Comprar terreno..." label_selected="Comprar terreno..." name="button buy land"/>
- <button label="Abandonar el terreno..." label_selected="Abandonar el terreno..." name="button abandon land"/>
+ <button label="Comprar terreno" label_selected="Comprar terreno" name="button buy land" width="140"/>
+ <button label="Abandonar el terreno" label_selected="Abandonar el terreno" name="button abandon land" width="140"/>
</panel>
- <string name="status_rotate">
+ <floater.string name="status_rotate">
Arrastre las bandas de color para girar el objeto
- </string>
- <string name="status_scale">
+ </floater.string>
+ <floater.string name="status_scale">
Pulse y arrastre para estirar el lado seleccionado
- </string>
- <string name="status_move">
- Arrastrar para mover, arrastrar + Mayús. para copiar
- </string>
- <string name="status_modifyland">
+ </floater.string>
+ <floater.string name="status_move">
+ Arrastrar para mover, Mayús.+arrastrar para copiar
+ </floater.string>
+ <floater.string name="status_modifyland">
Mantenga pulsado para modificar el terreno
- </string>
- <string name="status_camera">
+ </floater.string>
+ <floater.string name="status_camera">
Pulse y arrastre para cambiar el punto de vista
- </string>
- <string name="status_grab">
+ </floater.string>
+ <floater.string name="status_grab">
Arrastre para mover objetos: Ctrl, verticalmente; Ctrl-Mayús., para girarlos.
- </string>
- <string name="status_place">
+ </floater.string>
+ <floater.string name="status_place">
Pulse en el mundo para construir
- </string>
- <string name="status_selectland">
+ </floater.string>
+ <floater.string name="status_selectland">
Pulse y arrastre para seleccionar el terreno
- </string>
- <string name="grid_screen_text">
+ </floater.string>
+ <floater.string name="grid_screen_text">
Pantalla
- </string>
- <string name="grid_local_text">
+ </floater.string>
+ <floater.string name="grid_local_text">
Local
- </string>
- <string name="grid_world_text">
+ </floater.string>
+ <floater.string name="grid_world_text">
Mundo
- </string>
- <string name="grid_reference_text">
+ </floater.string>
+ <floater.string name="grid_reference_text">
Referencia
- </string>
- <string name="grid_attachment_text">
+ </floater.string>
+ <floater.string name="grid_attachment_text">
Añadido
- </string>
+ </floater.string>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_top_objects.xml b/indra/newview/skins/default/xui/es/floater_top_objects.xml
index ce0c22062b..29ae9991af 100644
--- a/indra/newview/skins/default/xui/es/floater_top_objects.xml
+++ b/indra/newview/skins/default/xui/es/floater_top_objects.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="top_objects" title="cargando...">
+<floater name="top_objects" title="CARGANDO...">
<text name="title_text">
Cargando...
</text>
@@ -11,23 +11,26 @@
<column label="Tiempo" name="time"/>
<column label="Tiempo en Mono" name="mono_time"/>
</scroll_list>
+ <line_editor font="SansSerifSmall" left="140" name="id_editor" width="280"/>
+ <line_editor font="SansSerifSmall" left="140" name="object_name_editor" width="280"/>
+ <line_editor font="SansSerifSmall" left="140" name="owner_name_editor" width="280"/>
<text name="id_text">
ID del objeto:
</text>
- <button label="Mostrar la baliza" name="show_beacon_btn"/>
+ <button label="Mostrar la baliza" name="show_beacon_btn" width="115"/>
<text name="obj_name_text">
Nombre del objeto:
</text>
- <button label="Filtro" name="filter_object_btn"/>
- <text name="owner_name_text">
+ <button label="Filtro" name="filter_object_btn" width="115"/>
+ <text name="owner_name_text" width="130">
Nombre del propietario:
</text>
- <button label="Filtro" name="filter_owner_btn"/>
- <button label="Devolver lo seleccionado" name="return_selected_btn"/>
- <button label="Devolver todo" name="return_all_btn"/>
- <button label="Desactivar lo seleccionado" name="disable_selected_btn"/>
- <button label="Desactivar todo" name="disable_all_btn"/>
- <button label="Actualizar" name="refresh_btn"/>
+ <button label="Filtro" name="filter_owner_btn" width="115"/>
+ <button label="Devolver lo seleccionado" name="return_selected_btn" width="170"/>
+ <button label="Devolver todo" name="return_all_btn" left="190"/>
+ <button label="Desactivar lo seleccionado" name="disable_selected_btn" width="170"/>
+ <button label="Desactivar todo" name="disable_all_btn" left="190"/>
+ <button label="Actualizar" name="refresh_btn" width="115"/>
<string name="top_scripts_title">
Scripts según su uso
</string>
diff --git a/indra/newview/skins/default/xui/es/floater_tos.xml b/indra/newview/skins/default/xui/es/floater_tos.xml
index 9f2ff615f3..d46c84cb03 100644
--- a/indra/newview/skins/default/xui/es/floater_tos.xml
+++ b/indra/newview/skins/default/xui/es/floater_tos.xml
@@ -4,8 +4,8 @@
<button label="Cancelar" label_selected="Cancelar" name="Cancel"/>
<check_box label="Estoy de acuerdo con las Condiciones del Servicio" name="agree_chk"/>
<text name="tos_heading">
- Por favor, lea cuidadosamente las siguientes Condiciones del Servicio. Si quiere seguir iniciando sesión en Second Life,
-debe aceptar el acuerdo.
+ Por favor, lea cuidadosamente las siguientes Condiciones del Servicio. Si quiere seguir
+iniciando sesión en [SECOND_LIFE], debe aceptar el acuerdo.
</text>
<text_editor name="tos_text">
TOS_TEXT
diff --git a/indra/newview/skins/default/xui/es/floater_url_entry.xml b/indra/newview/skins/default/xui/es/floater_url_entry.xml
index abdd69b090..f7c85ff068 100644
--- a/indra/newview/skins/default/xui/es/floater_url_entry.xml
+++ b/indra/newview/skins/default/xui/es/floater_url_entry.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="url_entry" title="">
<text name="media_label">
- URL para media:
+ URL del media:
</text>
+ <combo_box left="106" name="media_entry" width="354" />
<button label="OK" name="ok_btn"/>
<button label="Cancelar" name="cancel_btn"/>
<button label="Limpiar" name="clear_btn"/>
diff --git a/indra/newview/skins/default/xui/es/floater_water.xml b/indra/newview/skins/default/xui/es/floater_water.xml
index 5a759af5ff..c86e49a355 100644
--- a/indra/newview/skins/default/xui/es/floater_water.xml
+++ b/indra/newview/skins/default/xui/es/floater_water.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Water Floater" title="Editor avanzado del agua">
+<floater name="Water Floater" title="EDITOR AVANZADO DEL AGUA">
<text name="KeyFramePresetsText">
Agua predefinida:
</text>
@@ -11,20 +11,20 @@
<text name="BHText">
Color del agua
</text>
- <button label="?" name="WaterFogColorHelp"/>
+ <button label="?" name="WaterFogColorHelp" left="175" />
<color_swatch label="" name="WaterFogColor" tool_tip="Pulse para abrir el selector de color"/>
<text name="WaterFogDensText">
Transparencia
</text>
- <button label="?" name="WaterFogDensityHelp"/>
+ <button label="?" name="WaterFogDensityHelp" left="175" />
<text name="WaterUnderWaterFogModText">
Modificar la claridad del agua
</text>
- <button label="?" name="WaterUnderWaterFogModHelp"/>
+ <button label="?" name="WaterUnderWaterFogModHelp" left="175" />
<text name="BDensText">
Tamaño de las ondulaciones
</text>
- <button label="?" name="WaterNormalScaleHelp"/>
+ <button label="?" name="WaterNormalScaleHelp" left="405"/>
<text name="BHText2">
1
</text>
@@ -37,29 +37,29 @@
<text name="HDText">
Escala de Fresnel
</text>
- <button label="?" name="WaterFresnelScaleHelp"/>
+ <button label="?" name="WaterFresnelScaleHelp" left="405"/>
<text name="FresnelOffsetText">
Coeficiente de reflexión
</text>
- <button label="?" name="WaterFresnelOffsetHelp"/>
+ <button label="?" name="WaterFresnelOffsetHelp" left="405"/>
<text name="DensMultText">
Refracción de la superficie
</text>
- <button label="?" name="WaterScaleAboveHelp"/>
+ <button label="?" name="WaterScaleAboveHelp" left="640"/>
<text name="WaterScaleBelowText">
Refracción bajo la superficie
</text>
- <button label="?" name="WaterScaleBelowHelp"/>
+ <button label="?" name="WaterScaleBelowHelp" left="640"/>
<text name="MaxAltText">
Desenfoque
</text>
- <button label="?" name="WaterBlurMultiplierHelp"/>
+ <button label="?" name="WaterBlurMultiplierHelp" left="640"/>
</panel>
<panel label="Imagen" name="Waves">
<text name="BHText">
Sentido de la onda grande
</text>
- <button label="?" name="WaterWave1Help"/>
+ <button label="?" name="WaterWave1Help" left="170"/>
<text name="WaterWave1DirXText">
X
</text>
@@ -69,7 +69,7 @@
<text name="BHText2">
Sentido de la onda pequeña
</text>
- <button label="?" name="WaterWave2Help"/>
+ <button label="?" name="WaterWave2Help" left="170"/>
<text name="WaterWave2DirXText">
X
</text>
diff --git a/indra/newview/skins/default/xui/es/floater_wearable_save_as.xml b/indra/newview/skins/default/xui/es/floater_wearable_save_as.xml
index 34e76abb42..1dfff90004 100644
--- a/indra/newview/skins/default/xui/es/floater_wearable_save_as.xml
+++ b/indra/newview/skins/default/xui/es/floater_wearable_save_as.xml
@@ -2,7 +2,7 @@
<floater name="modal container" title=" ">
<button label="Guardar" label_selected="Guardar" name="Save"/>
<button label="Cancelar" label_selected="Cancelar" name="Cancel"/>
- <text length="1" name="Save item as:" type="string">
+ <text name="Save item as:">
Guardar el ítem como:
</text>
<line_editor name="name ed">
diff --git a/indra/newview/skins/default/xui/es/floater_windlight_options.xml b/indra/newview/skins/default/xui/es/floater_windlight_options.xml
index 79b70d4d59..0697f05553 100644
--- a/indra/newview/skins/default/xui/es/floater_windlight_options.xml
+++ b/indra/newview/skins/default/xui/es/floater_windlight_options.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="WindLight floater" title="Editor avanzado del cielo">
+<floater name="WindLight floater" title="EDITOR AVANZADO DEL CIELO">
<text name="KeyFramePresetsText">
Cielos definidos:
</text>
<button label="Nuevo" label_selected="Nuevo" name="WLNewPreset"/>
<button label="Guardar" label_selected="Guardar" name="WLSavePreset"/>
<button label="Borrar" label_selected="Borrar" name="WLDeletePreset"/>
- <button label="Editor del ciclo de un día" label_selected="Editor del ciclo de un día" name="WLDayCycleMenuButton"/>
+ <button font="SansSerifSmall" width="150" left_delta="90" label="Editor del ciclo de un día" label_selected="Editor del ciclo de un día" name="WLDayCycleMenuButton"/>
<tab_container name="WindLight Tabs">
<panel label="Atmósfera" name="Atmosphere">
<text name="BHText">
@@ -122,7 +122,7 @@
<text name="WLCloudColorText">
Color de las nubes
</text>
- <button label="?" name="WLCloudColorHelp"/>
+ <button label="?" name="WLCloudColorHelp" left="190" />
<text name="BHText">
R
</text>
@@ -138,7 +138,7 @@
<text name="WLCloudColorText2">
Posición/Densidad de las nubes
</text>
- <button label="?" name="WLCloudDensityHelp"/>
+ <button label="?" name="WLCloudDensityHelp" left="190"/>
<text name="BHText5">
X
</text>
@@ -156,11 +156,12 @@
Altitud de las nubes
</text>
<button label="?" name="WLCloudScaleHelp"/>
- <text name="WLCloudDetailText">
- Detalle de las nubes (Posición/Densidad)
+ <text name="WLCloudDetailText" font="SansSerifSmall">
+ Detalle de las nubes
+(Posición/Densidad)
</text>
<button label="?" name="WLCloudDetailHelp"/>
- <text name="BHText8">
+ <text name="BHText8" bottom="-113">
X
</text>
<text name="BHText9">
@@ -169,18 +170,19 @@
<text name="BHText10">
D
</text>
+ <slider bottom="-127" name="WLCloudDetailX"/>
<text name="WLCloudScrollXText">
- Velocidad de las nubes: X
+ Velocidad de X
</text>
<button label="?" name="WLCloudScrollXHelp"/>
<check_box label="Bloquear" name="WLCloudLockX"/>
<text name="WLCloudScrollYText">
- Velocidad de las nubes: Y
+ Velocidad de Y
</text>
<button label="?" name="WLCloudScrollYHelp"/>
<check_box label="Bloquear" name="WLCloudLockY"/>
<check_box label="Incluir nubes clásicas" name="DrawClassicClouds"/>
- <button label="?" name="WLClassicCloudsHelp"/>
+ <button label="?" name="WLClassicCloudsHelp" left="618"/>
</panel>
</tab_container>
<string name="WLDefaultSkyNames">
diff --git a/indra/newview/skins/default/xui/es/floater_world_map.xml b/indra/newview/skins/default/xui/es/floater_world_map.xml
index aad417790f..4d7337bef7 100644
--- a/indra/newview/skins/default/xui/es/floater_world_map.xml
+++ b/indra/newview/skins/default/xui/es/floater_world_map.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="worldmap" title="Mapa del Mundo">
+<floater name="worldmap" title="MAPA DEL MUNDO">
<tab_container name="maptab">
<panel label="Objetos" name="objects_mapview"/>
<panel label="Terreno" name="terrain_mapview"/>
@@ -28,14 +28,10 @@
<check_box label="&apos;Mature&apos;" name="event_mature_chk"/>
<check_box label="&apos;Adult&apos;" name="event_adult_chk"/>
<combo_box label="Amigos conectados" name="friend combo" tool_tip="Amigo a mostrar en el mapa">
- <combo_item name="none_selected">
- Amigos conectados
- </combo_item>
+ <combo_box.item name="item1" label="Amigos conectados" />
</combo_box>
<combo_box label="Hitos" name="landmark combo" tool_tip="Hito a mostrar en el mapa">
- <combo_item name="none_selected">
- Hitos
- </combo_item>
+ <combo_box.item name="item1" label="Hitos" />
</combo_box>
<line_editor label="Buscar por el nombre de la región" name="location" tool_tip="Escriba el nombre de una región"/>
<button label="Buscar" name="DoSearch" tool_tip="Buscar una región"/>
diff --git a/indra/newview/skins/default/xui/es/language_settings.xml b/indra/newview/skins/default/xui/es/language_settings.xml
new file mode 100644
index 0000000000..71418d446a
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/language_settings.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- This file contains strings that used to be hardcoded in the source.-->
+<strings>
+
+ <!-- Locale Information -->
+ <string name="MicrosoftLocale">english</string>
+ <string name="DarwinLocale">C</string>
+ <string name="LinuxLocale">C</string>
+
+ <!--
+ datetimeToCodes["wkday"] = "%a"; // Thu
+ datetimeToCodes["weekday"] = "%A"; // Thursday
+ datetimeToCodes["year4"] = "%Y"; // 2009
+ datetimeToCodes["year"] = "%Y"; // 2009
+ datetimeToCodes["year2"] = "%y"; // 09
+ datetimeToCodes["mth"] = "%b"; // Aug
+ datetimeToCodes["month"] = "%B"; // August
+ datetimeToCodes["mthnum"] = "%m"; // 08
+ datetimeToCodes["day"] = "%d"; // 31
+ datetimeToCodes["hour24"] = "%H"; // 14
+ datetimeToCodes["hour"] = "%H"; // 14
+ datetimeToCodes["hour12"] = "%I"; // 02
+ datetimeToCodes["min"] = "%M"; // 59
+ datetimeToCodes["ampm"] = "%p"; // AM
+ datetimeToCodes["second"] = "%S"; // 59
+ datetimeToCodes["timezone"] = "%Z"; // PST
+ -->
+
+ <string name="TimeHour">hour,datetime,slt</string>
+ <string name="TimeMin">min,datetime,slt</string>
+ <string name="TimeYear">year,datetime,slt</string>
+ <string name="TimeDay">day,datetime,slt</string>
+ <string name="TimeMonth">mthnum,datetime,slt</string>
+ <string name="TimeWeek">wkday,datetime,slt</string>
+ <string name="TimeAMPM">ampm,datetime,slt</string>
+ <string name="TimeHour12">hour12,datetime,slt</string>
+
+ <string name="LTimeMthNum">mthnum,datetime,local</string>
+ <string name="LTimeWeek">wkday,datetime,local</string>
+ <string name="LTimeMonth">mth,datetime,local</string>
+ <string name="LTimeDay">day,datetime,local</string>
+ <string name="LTimeSec">second,datetime,local</string>
+ <string name="LTimeHour">hour,datetime,local</string>
+ <string name="LTimeMin">min,datetime,local</string>
+ <string name="LTimeYear">year,datetime,local</string>
+
+ <string name="UTCTimeWeek">weekday,datetime,utc</string>
+ <string name="UTCTimeDay">day,datetime,utc</string>
+ <string name="UTCTimeMth">mth,datetime,utc</string>
+ <string name="UTCTimeYr">year,datetime,utc</string>
+ <string name="UTCTimeHr">hour,datetime,utc</string>
+ <string name="UTCTimeMin">min,datetime,utc</string>
+ <string name="UTCTimeSec">second,datetime,utc</string>
+ <string name="UTCTimeTimezone">timezone,datetime,utc</string>
+</strings>
diff --git a/indra/newview/skins/default/xui/es/menu_inventory.xml b/indra/newview/skins/default/xui/es/menu_inventory.xml
index 557123d4f8..28d47fce52 100644
--- a/indra/newview/skins/default/xui/es/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/es/menu_inventory.xml
@@ -12,7 +12,7 @@
<menu_item_call label="Script nuevo" name="New Script"/>
<menu_item_call label="Nota nueva" name="New Note"/>
<menu_item_call label="Gesto nuevo" name="New Gesture"/>
- <menu name="New Clothes">
+ <menu name="New Clothes" label="Nueva ropa">
<menu_item_call label="Camisa nueva" name="New Shirt"/>
<menu_item_call label="Pantalones nuevos" name="New Pants"/>
<menu_item_call label="Zapatos nuevos" name="New Shoes"/>
@@ -23,7 +23,7 @@
<menu_item_call label="Camiseta nueva" name="New Undershirt"/>
<menu_item_call label="Ropa interior nueva" name="New Underpants"/>
</menu>
- <menu name="New Body Parts">
+ <menu name="New Body Parts" label="Nuevas partes del cuerpo">
<menu_item_call label="Forma nueva" name="New Shape"/>
<menu_item_call label="Piel nueva" name="New Skin"/>
<menu_item_call label="Pelo nuevo" name="New Hair"/>
diff --git a/indra/newview/skins/default/xui/es/menu_login.xml b/indra/newview/skins/default/xui/es/menu_login.xml
index a60e41d896..1cf6ad5ae6 100644
--- a/indra/newview/skins/default/xui/es/menu_login.xml
+++ b/indra/newview/skins/default/xui/es/menu_login.xml
@@ -7,7 +7,7 @@
<menu_item_call label="Preferencias..." name="Preferences..."/>
</menu>
<menu label="Ayuda" name="Help">
- <menu_item_call label="Ayuda de Second Life" name="Second Life Help"/>
- <menu_item_call label="Acerca de Second Life..." name="About Second Life..."/>
+ <menu_item_call label="Ayuda de [SECOND_LIFE]" name="Second Life Help"/>
+ <menu_item_call label="Acerca de [APP_NAME]..." name="About Second Life..."/>
</menu>
</menu_bar>
diff --git a/indra/newview/skins/default/xui/es/menu_viewer.xml b/indra/newview/skins/default/xui/es/menu_viewer.xml
index 0712440e1f..fdb6a92084 100644
--- a/indra/newview/skins/default/xui/es/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/es/menu_viewer.xml
@@ -1,5 +1,11 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<menu_bar name="Main Menu">
+ <menu name="Me">
+ <menu_item_call label="Preferencias" name="Preferences"/>
+ <menu_item_call name="Manage My Account">
+ <menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=es" />
+ </menu_item_call>
+ </menu>
<menu label="Archivo" name="File">
<tearoff_menu label="~~~~~~~~~~~" name="~~~~~~~~~~~"/>
<menu label="Subir" name="upload">
@@ -119,8 +125,12 @@
<menu_item_call label="Parar la animación de mi avatar" name="Stop Animating My Avatar"/>
<menu_item_call label="Recuperar las teclas" name="Release Keys"/>
<menu_item_separator label="-----------" name="separator4"/>
- <menu_item_call label="Historial de mi cuenta..." name="Account History..."/>
- <menu_item_call label="Administrar mi cuenta..." name="Manage My Account..."/>
+ <menu_item_call label="Historial de mi cuenta..." name="Account History...">
+ <on_click name="AccountHistory_url" userdata="WebLaunchAccountHistory,http://secondlife.com/account/transactions.php?lang=es"/>
+ </menu_item_call>
+ <menu_item_call label="Administrar mi cuenta..." name="Manage My Account...">
+ <on_click name="ManageMyAccount_url" userdata="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=es"/>
+ </menu_item_call>
<menu_item_call label="Comprar L$..." name="Buy and Sell L$..."/>
<menu_item_separator label="-----------" name="separator5"/>
<menu_item_call label="Mi terreno..." name="My Land..."/>
@@ -165,7 +175,9 @@
<menu_item_separator label="-----------" name="separator4"/>
<menu_item_call label="Visión en lo seleccionado" name="Focus on Selection"/>
<menu_item_call label="Zoom en lo seleccionado" name="Zoom to Selection"/>
- <menu_item_call label="Comprar el objeto" name="Menu Object Take"/>
+ <menu_item_call label="Comprar el objeto" name="Menu Object Take">
+ <on_enable userdata="Comprar el objeto,Coger el objeto" name="EnableBuyOrTake"/>
+ </menu_item_call>
<menu_item_call label="Coger una copia" name="Take Copy"/>
<menu_item_call label="Devolver una copia del objeto a los contenidos de donde salió" name="Save Object Back to Object Contents"/>
<menu_item_separator label="-----------" name="separator6"/>
@@ -179,7 +191,7 @@
<menu_item_call label="Definir los scripts a no ejecutar en lo seleccionado" name="Set Scripts to Not Running in Selection"/>
</menu>
<menu label="Ayuda" name="Help">
- <menu_item_call label="Ayuda de Second Life" name="Second Life Help"/>
+ <menu_item_call label="Ayuda de [SECOND_LIFE]" name="Second Life Help"/>
<menu_item_call label="Tutorial" name="Tutorial"/>
<menu_item_separator label="-----------" name="separator"/>
<menu_item_call label="Blog oficial..." name="Official Linden Blog..."/>
@@ -200,6 +212,6 @@
<menu_item_separator label="-----------" name="separator9"/>
<menu_item_call label="Informar de un fallo..." name="Report Bug..."/>
</menu>
- <menu_item_call label="Acerca de Second Life..." name="About Second Life..."/>
+ <menu_item_call label="Acerca de [APP_NAME]..." name="About Second Life..."/>
</menu>
</menu_bar>
diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml
index d7e480c653..6b58bbea47 100644
--- a/indra/newview/skins/default/xui/es/notifications.xml
+++ b/indra/newview/skins/default/xui/es/notifications.xml
@@ -6,6 +6,9 @@
<global name="alwayschoose">
Elegir siempre esta opción
</global>
+ <global name="implicitclosebutton">
+ Cerrar
+ </global>
<template name="okbutton">
<form>
<button
@@ -71,7 +74,7 @@
</form>
</template>
<notification functor="GenericAcknowledge" label="Mensaje de alerta desconocida" name="MissingAlert">
- Su versión de Second Life no sabe cómo mostrar el mensaje de alerta que acaba de recibir.
+ Su versión de [APP_NAME] no sabe cómo mostrar el mensaje de alerta que acaba de recibir.
Detalles del error: no se ha encontrado en notifications.xml la alerta llamada &apos;[_NAME]&apos;.
<usetemplate name="okbutton" yestext="OK"/>
@@ -94,7 +97,7 @@ Detalles del error: no se ha encontrado en notifications.xml la alerta llamada &
<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Sí"/>
</notification>
<notification name="BadInstallation">
- Ha habido un error al actualizar Second Life. Por favor, descargue la última versión desde secondlife.com.
+ Ha habido un error al actualizar [APP_NAME]. Por favor, descargue la última versión desde secondlife.com.
<usetemplate
name="okbutton"
yestext="OK"/>
@@ -189,7 +192,7 @@ No podrá removérseles de ese rol, sino que deberán renunciar a él por sí mi
<usetemplate name="okcancelbuttons" notext="No" yestext="Sí"/>
</notification>
<notification name="ClickPublishHelpLand">
- Seleccionar &quot;Publicar en la web&quot;
+ Seleccionar &apos;Publicar en la web&apos;
Marcando este ítem, se mostrará:
- esta parcela en los resultados de la búsqueda
- los objetos públicos de esta parcela
@@ -219,14 +222,14 @@ Marcando este ítem, se mostrará:
No puede hacer que esta parcela aparezca en la búsqueda, porque está situada en una región que lo prohíbe.
</notification>
<notification name="ClickPublishHelpAvatar">
- Al seleccionar &quot;Mostrar en Buscar&quot; se mostrará:
+ Al seleccionar &apos;Mostrar en la búsqueda&apos; se mostrará:
- mi perfil en los resultados de la búsqueda
- un enlace a mi perfil en las páginas públicas de grupo
</notification>
<notification name="ClickPartnerHelpAvatar">
Puede proponérselo a otro residente o disolver su relación con un/a compañero/a en el sitio web de [SECOND_LIFE].
-¿Ir al sitio web de Second Life para tener más información sobre este asunto?
+¿Ir al sitio web de [SECOND_LIFE] para tener más información sobre este asunto?
<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Ir a la página"/>
</notification>
<notification name="ClickUploadHelpPermissions">
@@ -264,7 +267,7 @@ Su precio de venta será de [SALE_PRICE] L$, y se autorizará la compra sólo a
<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/>
</notification>
<notification name="ConfirmLandSaleToAnyoneChange">
- ATENCIÓN: Al pulsar &apos;vender a cualquiera&apos;, su terreno estará disponible para toda la comunidad de Second Life, incluso para quienes no están en esta región.
+ ATENCIÓN: Al pulsar &apos;vender a cualquiera&apos;, su terreno estará disponible para toda la comunidad de [SECOND_LIFE], incluso para quienes no están en esta región.
Los [LAND_SIZE] m² de terreno seleccionados se van a poner a la venta.
Su precio de venta será de [SALE_PRICE] L$, y se autorizará la compra a [NAME].
@@ -371,10 +374,13 @@ La carpeta del vestuario contiene partes del cuerpo, u objetos a anexar o que no
Debe escribir tanto el nombre como el apellido de su avatar, los dos.
Necesita una cuenta para entrar en [SECOND_LIFE]. ¿Quiere crear una ahora?
+ <url name="url">
+ https://join.secondlife.com/index.php?lang=es-ES
+ </url>
<usetemplate name="okcancelbuttons" notext="Volver a intentarlo" yestext="Crear una cuenta nueva"/>
</notification>
<notification name="AddClassified">
- Los anuncios clasificados aparecen durante una semana en la sección &apos;Clasificados&apos; del directorio Buscar y en www.secondlife.com.
+ Los anuncios clasificados aparecen durante una semana en la sección &apos;Clasificados&apos; del directorio Buscar y en [http://secondlife.com/community/classifieds/?lang=es-ES secondlife.com].
Rellene su anuncio y pulse &apos;Publicar...&apos; para añadirlo al directorio.
Cuando pulse Publicar, se le preguntará por un precio a pagar.
El pagar más hará que su anuncio aparezca más arriba en la lista, y que también aparezca más arriba cuando la gente busque por palabras clave.
@@ -395,6 +401,9 @@ No se reembolsan las cuotas pagadas.
</notification>
<notification name="PromptGoToEventsPage">
¿Ir a la web de eventos de [SECOND_LIFE]?
+ <url name="url">
+ http://secondlife.com/events/?lang=es-ES
+ </url>
<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/>
</notification>
<notification name="SelectProposalToView">
@@ -412,17 +421,17 @@ No se reembolsan las cuotas pagadas.
<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/>
</notification>
<notification name="CacheWillClear">
- La caché se limpiará cuando reinicie [SECOND_LIFE].
+ La caché se limpiará cuando reinicie [APP_NAME].
</notification>
<notification name="CacheWillBeMoved">
- La caché se moverá cuando reinicie [SECOND_LIFE].
+ La caché se moverá cuando reinicie [APP_NAME].
Nota: esto limpiará la caché.
</notification>
<notification name="ChangeConnectionPort">
- Las configuraciones del puerto tendrán efecto cuando reinicie [SECOND_LIFE].
+ Las configuraciones del puerto tendrán efecto cuando reinicie [APP_NAME].
</notification>
<notification name="ChangeSkin">
- La nueva apariencia se verá cuando reinicie [SECOND_LIFE].
+ La nueva apariencia se verá cuando reinicie [APP_NAME].
</notification>
<notification name="GoToAuctionPage">
¿Ir a la página web de [SECOND_LIFE] para ver los detalles de la subasta
@@ -482,7 +491,7 @@ El objeto debe de haber sido borrado o estar fuera de rango (&apos;out of range&
No se ha podido escribir el archivo [[FILE]]
</notification>
<notification name="UnsupportedHardware">
- Atención: su sistema no tiene los requerimientos mínimos que necesita Second Life. Si sigue usando Second Life, tendrá un funcionamiento pobre. Desafortunadamente, no podemos ofrecer soporte técnico para configuraciones inadecuadas del sistema.
+ Atención: su sistema no tiene los requerimientos mínimos que necesita [APP_NAME]. Si sigue usando [APP_NAME], tendrá un funcionamiento pobre. Desafortunadamente, no podemos ofrecer soporte técnico para configuraciones inadecuadas del sistema.
MINSPECS
Para más información, ¿quiere visitar [_URL]?
@@ -494,14 +503,14 @@ Para más información, ¿quiere visitar [_URL]?
<notification name="UnknownGPU">
En este momento, desconocemos la tarjeta gráfica de su sistema.
Con frecuencia, esto se debe a hardware nuevo que no hemos podido revisar aún.
-Es muy probable que Second Life funcione correctamente, pero deberá ajustar sus configuraciones gráficas a lo que sea más apropiado.
+Es muy probable que [APP_NAME] funcione correctamente, pero deberá ajustar sus configuraciones gráficas a lo que sea más apropiado.
(Menú Editar &gt; Preferencias &gt; Gráficos).
<form name="form">
<ignore name="ignore" text="Cuando se detecte una tarjeta gráfica desconocida"/>
</form>
</notification>
<notification name="DisplaySettingsNoShaders">
- [SECOND_LIFE] se cayó al inicializar los drivers gráficos.
+ [APP_NAME] se cayó al inicializar los drivers gráficos.
La calidad de los gráficos deberá establecerse en un nivel bajo para prevenir algunos errores frecuentes en los drivers.
Esto desactivará algunas opciones gráficas.
Le recomendamos que actualice los drivers de su tarjeta gráfica.
@@ -571,7 +580,10 @@ misma región.
<notification name="PromptGoToCurrencyPage">
[EXTRA]
-¿Ir a [URL] para informarse sobre la compra de moneda?
+¿Ir a [_URL] para informarse sobre la compra de L$?
+ <url name="url">
+ http://secondlife.com/app/currency/?lang=es-ES
+ </url>
<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/>
</notification>
<notification name="UnableToLinkObjects">
@@ -792,7 +804,7 @@ no se ha seleccionado una parcela.
no se ha podido encontrar en qué región está.
</notification>
<notification name="CannotCloseFloaterBuyLand">
- No puede cerrar la ventana de Comprar terreno hasta que Second Life calcule el precio de esta transacción.
+ No puede cerrar la ventana de Comprar terreno hasta que [APP_NAME] calcule el precio de esta transacción.
</notification>
<notification name="CannotDeedLandNothingSelected">
No se ha podido transferir el terreno:
@@ -805,7 +817,6 @@ no ha seleccionado un grupo.
<notification name="CannotDeedLandNoRegion">
No se ha podido transferir el terreno:
Ha sido imposible encontrar en qué región está.
-Por favor, para informar de esto use Herramientas -&gt; Informar de un fallo.
</notification>
<notification name="CannotDeedLandMultipleSelected">
No se ha podido transferir el terreno:
@@ -851,8 +862,6 @@ Las parcelas de su propiedad se muestran en verde.
<notification name="CannotReleaseLandRegionNotFound">
No se ha podido abandonar el terreno:
Ha sido imposible encontrar en qué región está.
-
-Por favor, para informar de esto use Herramientas &gt; Informar de un fallo.
</notification>
<notification name="CannotReleaseLandNoTransfer">
No se ha podido abandonar el terreno:
@@ -891,14 +900,10 @@ Inténtelo seleccionando una parte.
<notification name="CannotDivideLandNoRegion">
No se ha podido dividir el terreno:
Ha sido imposible encontrar en qué región está.
-
-Por favor, para informar de esto use Herramientas -&gt; Informar de un fallo.
</notification>
<notification name="CannotJoinLandNoRegion">
No se ha podido unir el terreno:
Ha sido imposible encontrar en qué región está.
-
-Por favor, para informar de esto use Herramientas -&gt; Informar de un fallo.
</notification>
<notification name="CannotJoinLandNothingSelected">
No se ha podido unir el terreno:
@@ -928,7 +933,7 @@ Deberá reconfigurar el nombre y las opciones de la nueva parcela.
El color de las parcelas indica el tipo de propietario.
Verde = Su terreno
-Agua = Terreno de su&apos;s grupo&apos;s
+Agua = Terreno de sus grupos
Rojo = Propiedad de otros
Amarillo = En venta
Morado = Para subasta
@@ -957,13 +962,11 @@ Gris = Público
<notification name="CannotSaveToAssetStore">
No se ha podido guardar [NAME] en la base central de almacenamiento.
Esto es, generalmente, un fallo temporal. Por favor, reinténtelo en unos pocos minutos.
-
-Si persiste el problema, por favor, pulse en en el menú &apos;Herramientas &gt; Informar de un fallo&apos; y aporte detalles sobre la configuración de su conexión.
</notification>
<notification name="YouHaveBeenLoggedOut">
Se ha cerrado su sesión en [SECOND_LIFE]:
[MESSAGE]
-Aún puede ver el chat y los MI existentes pulsando &apos;Ver MI y Chat&apos;. Si no, pulse &apos;Salir&apos; para dejar inmediatemente [SECOND_LIFE].
+Aún puede ver el chat y los MI existentes pulsando &apos;Ver MI y Chat&apos;. Si no, pulse &apos;Salir&apos; para dejar inmediatemente [APP_NAME].
<usetemplate name="okcancelbuttons" notext="Salir" yestext="Ver MI y Chat"/>
</notification>
<notification name="OnlyOfficerCanBuyLand">
@@ -981,7 +984,7 @@ usted no tiene el permiso de comprar terreno para el grupo que tiene activado ac
¿Ofrecer a [NAME] que sea su amigo?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
¿Quieres formar parte de mis amigos?
</input>
<button name="Offer" text="OK"/>
@@ -1127,6 +1130,14 @@ Si se vende una parcela transferida, el precio de venta se dividirá a partes ig
Su localización [TYPE] no está disponible en estos momentos. [HELP]
Ha sido llevado a una región cercana.
</notification>
+ <notification name="AvatarMovedDesired">
+ La localización que ha elegido no está disponible en estos momentos.
+Ha sido llevado a una región cercana.
+ </notification>
+ <notification name="AvatarMovedLast">
+ Su última posición no está disponible en estos momentos.
+Ha sido llevado a una región cercana.
+ </notification>
<notification name="ClothingLoading">
Aún está descargándose su ropa.
Puede usar normalmente [SECOND_LIFE], los demás residentes le verán correctamente.
@@ -1135,16 +1146,19 @@ Puede usar normalmente [SECOND_LIFE], los demás residentes le verán correctame
</form>
</notification>
<notification name="FirstRun">
- Se ha completado la instalación de [SECOND_LIFE].
+ Se ha completado la instalación de [APP_NAME].
Si esta es la primera vez que usa [SECOND_LIFE], deberá crear una cuenta antes de que pueda iniciar una sesión.
-¿Volver a www.secondlife.com para crear una cuenta nueva?
+¿Volver a [https://join.secondlife.com/index.php?lang=es-ES secondlife.com] para crear una cuenta nueva?
<usetemplate name="okcancelbuttons" notext="Continuar" yestext="Cuenta nueva..."/>
</notification>
<notification name="LoginPacketNeverReceived">
- Tenemos problemas de conexión. Puede deberse a un problema de su conexión a internet o de los servidores de Second Life.
+ Tenemos problemas de conexión. Puede deberse a un problema de su conexión a internet o de los servidores de [SECOND_LIFE].
Puede revisar su conexión a internet y volver a intentarlo en unos minutos. Pulse Ayuda para conectarse a nuestro sitio de Sporte, o pulse Teleportar para intentar teleportarse a su Base.
+ <url name="url">
+ http://es.secondlife.com/support/
+ </url>
<form name="form">
<button name="OK" text="OK"/>
<button name="Help" text="Ayuda"/>
@@ -1196,13 +1210,13 @@ Por favor, selección sólo uno y reinténtelo.
No se han podido configurar las texturas de la región:
La textura del terreno [TEXTURE_NUM] tiene una profundidad de bites inválida: [TEXTURE_BIT_DEPTH].
-Cambie la textura [TEXTURE_NUM] por una imagen de 24-bit y 512x512 o menor, y pulse de nuevo &quot;Aplicar&quot; .
+Cambie la textura [TEXTURE_NUM] por una imagen de 24-bit y 512x512 o menor, y pulse de nuevo &apos;Aplicar&apos; .
</notification>
<notification name="InvalidTerrainSize">
No se han podido configurar las texturas de la región:
La textura del terreno [TEXTURE_NUM] es demasiado grande: [TEXTURE_SIZE_X]x[TEXTURE_SIZE_Y].
-Cambie la textura [TEXTURE_NUM] por una imagen de 24-bit y 512x512 o menor, y pulse de nuevo &quot;Aplicar&quot; .
+Cambie la textura [TEXTURE_NUM] por una imagen de 24-bit y 512x512 o menor, y pulse de nuevo &apos;Aplicar&apos; .
</notification>
<notification name="RawUploadStarted">
Ha empezado la subida. Dependiendo de la velocidad de su conexión, llevará unos dos minutos.
@@ -1246,33 +1260,33 @@ Por favor, ponga en venta el objeto y reinténtelo.
[DOWNLOAD_PATH].
</notification>
<notification name="DownloadWindowsMandatory">
- Está disponible una versión nueva de [SECOND_LIFE].
+ Está disponible una versión nueva de [APP_NAME].
[MESSAGE]
-Debe descargar esta actualización para usar [SECOND_LIFE].
+Debe descargar esta actualización para usar [APP_NAME].
<usetemplate name="okcancelbuttons" notext="Salir" yestext="Descargarla"/>
</notification>
<notification name="DownloadWindows">
- Está disponible una versión actualizada de [SECOND_LIFE].
+ Está disponible una versión actualizada de [APP_NAME].
[MESSAGE]
Esta actualización no es obligatoria, pero le sugerimos instalarla para mejorar el rendimiento y la estabilidad.
<usetemplate name="okcancelbuttons" notext="Continuar" yestext="Descargarla"/>
</notification>
<notification name="DownloadWindowsReleaseForDownload">
- Está disponible una versión actualizada de [SECOND_LIFE].
+ Está disponible una versión actualizada de [APP_NAME].
[MESSAGE]
Esta actualización no es obligatoria, pero le sugerimos instalarla para mejorar el rendimiento y la estabilidad.
<usetemplate name="okcancelbuttons" notext="Continuar" yestext="Descargarla"/>
</notification>
<notification name="DownloadMacMandatory">
- Está disponible una versión nueva de [SECOND_LIFE].
+ Está disponible una versión nueva de [APP_NAME].
[MESSAGE]
-Debe descargar esta actualización para usar [SECOND_LIFE].
+Debe descargar esta actualización para usar [APP_NAME].
¿Descargarla a su carpeta de aplicaciones?
<usetemplate name="okcancelbuttons" notext="Salir" yestext="Descargarla"/>
</notification>
<notification name="DownloadMac">
- Está disponible una versión actualizada de [SECOND_LIFE].
+ Está disponible una versión actualizada de [APP_NAME].
[MESSAGE]
Esta actualización no es obligatoria, pero le sugerimos instalarla para mejorar el rendimiento y la estabilidad.
@@ -1280,7 +1294,7 @@ Esta actualización no es obligatoria, pero le sugerimos instalarla para mejorar
<usetemplate name="okcancelbuttons" notext="Continuar" yestext="Descargarla"/>
</notification>
<notification name="DownloadMacReleaseForDownload">
- Está disponible una versión actualizada de [SECOND_LIFE].
+ Está disponible una versión actualizada de [APP_NAME].
[MESSAGE]
Esta actualización no es obligatoria, pero le sugerimos instalarla para mejorar el rendimiento y la estabilidad.
@@ -1300,10 +1314,6 @@ Esta actualización no es obligatoria, pero le sugerimos instalarla para mejorar
¿Ir a www.secondlife.com para administrar su cuenta?
<usetemplate ignoretext="Cuando se abra el navegador para administrar su cuenta" name="okcancelignore" notext="Cancelar" yestext="OK"/>
</notification>
- <notification name="WebLaunchBugReport101">
- Visite el wiki de [SECOND_LIFE] y aprenda cómo informar correctamente de fallos.
- <usetemplate ignoretext="Cuando se abra el navegador para ver el wiki de Informes de fallos - instrucciones" name="okcancelignore" notext="Cancelar" yestext="OK"/>
- </notification>
<notification name="WebLaunchSecurityIssues">
Visite el wiki de [SECOND_LIFE] para más detalles sobre cómo informar de una cuestión de seguridad.
<usetemplate ignoretext="Cuando se abra el navegador para ver el wiki de cuestiones de seguridad" name="okcancelignore" notext="Cancelar" yestext="OK"/>
@@ -1385,7 +1395,7 @@ Se ocultará el chat y los mensajes instantáneos. Los mensajes instantáneos re
<notification name="KickUser">
¿Con qué mensaje se expulsará a este usuario?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Un administrador le ha desconectado.
</input>
<button name="OK" text="OK"/>
@@ -1395,7 +1405,7 @@ Se ocultará el chat y los mensajes instantáneos. Los mensajes instantáneos re
<notification name="KickAllUsers">
¿Con qué mensaje se expulsará a cualquiera que esté actualmente en el grid?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Un administrador le ha desconectado.
</input>
<button name="OK" text="OK"/>
@@ -1405,7 +1415,7 @@ Se ocultará el chat y los mensajes instantáneos. Los mensajes instantáneos re
<notification name="FreezeUser">
¿Con qué mensaje se congelará a este usuario?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Ha sido usted congelado. No puede moverse o escribir en el chat. Un administrador contactará con usted a través de un mensaje instantáneo (MI).
</input>
<button name="OK" text="OK"/>
@@ -1415,7 +1425,7 @@ Se ocultará el chat y los mensajes instantáneos. Los mensajes instantáneos re
<notification name="UnFreezeUser">
¿Con qué mensaje se descongelará a este usuario?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Ya no está usted congelado.
</input>
<button name="OK" text="OK"/>
@@ -1425,7 +1435,7 @@ Se ocultará el chat y los mensajes instantáneos. Los mensajes instantáneos re
<notification name="OfferTeleport">
¿Ofrecer teleporte a su posición con este mensaje?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Ven conmigo a [REGION]
</input>
<button name="OK" text="OK"/>
@@ -1435,7 +1445,7 @@ Se ocultará el chat y los mensajes instantáneos. Los mensajes instantáneos re
<notification name="OfferTeleportFromGod">
¿Convocar a este usuario a su posición?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Ven conmigo a [REGION]
</input>
<button name="OK" text="OK"/>
@@ -1449,7 +1459,7 @@ Se ocultará el chat y los mensajes instantáneos. Los mensajes instantáneos re
<notification label="Mensaje a todo el estado" name="MessageEstate">
Escriba un anuncio breve que se enviará a todo el que esté en su estado.
<form name="form">
- <input name="message" type="text"/>
+ <input name="message"/>
<button name="OK" text="OK"/>
<button name="Cancel" text="Cancelar"/>
</form>
@@ -1522,7 +1532,7 @@ Por favor, compruebe que tiene instalado el último visor, y vaya a la Base de C
¿Quiere ir a la Base de Conocimientos para aprender más sobre el nivel de calificación?
<url name="url">
- https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=6010
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview/es
</url>
<usetemplate
name="okcancelignore"
@@ -1537,7 +1547,7 @@ Por favor, compruebe que tiene instalado el último visor, y vaya a la Base de C
Usted no está autorizado en esa región por su nivel de calificación..
Puede pulsar &apos;Cambiar preferencia&apos; para aumentar su nivel de calificación y poder entrar. Desde ese momento, podrá buscar y acceder a contenido [REGIONMATURITY]. Si más adelante quiere deshacer esta configuración, vaya a Editar &gt; Preferencias... &gt; General.
- <form>
+ <form name="form">
<button
name="OK"
text="Cambiar preferencia"/>
@@ -1545,7 +1555,7 @@ Puede pulsar &apos;Cambiar preferencia&apos; para aumentar su nivel de calificac
default="true"
name="Cancel"
text="Cerrar"/>
- <ignore text="Cuando la entrada a la región está bloqueada por la preferencia del nivel de calificación"/>
+ <ignore name="ignore" text="Cuando la entrada a la región está bloqueada por la preferencia del nivel de calificación"/>
</form>
</notification>
<notification name="LandClaimAccessBlocked">
@@ -1561,7 +1571,7 @@ Por favor, compruebe que tiene instalado el último visor, y vaya a la Base de C
¿Quiere ir a la Base de Conocimientos para más información sobre el nivel de calificación?
<url name="url">
- https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=6010
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview/es
</url>
<usetemplate
name="okcancelignore"
@@ -1595,7 +1605,7 @@ Por favor, compruebe que tiene instalado el último visor, y vaya a la Base de C
¿Quiere ir a la Base de Conocimientos para más información sobre el nivel de calificación?
<url name="url">
- https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=6010
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview/es
</url>
<usetemplate
name="okcancelignore"
@@ -1673,7 +1683,7 @@ Puede pulsar &apos;Cambiar preferencia&apos; para aumentar su nivel de calificac
<notification label="Mensaje a toda la región" name="MessageRegion">
Escriba un anuncio breve que se enviará a todo el que esté en esta región.
<form name="form">
- <input name="message" type="text"/>
+ <input name="message"/>
<button name="OK" text="OK"/>
<button name="Cancel" text="Cancelar"/>
</form>
@@ -1735,7 +1745,7 @@ Cuando está activada, los residentes sólo pueden ser empujados por sí mismos
Por defecto: Off
</notification>
<notification label="Unir/Dividir parcelas" name="HelpParcelChanges">
- Esta casilla determina si las parcelas que no son del propietario del estado pueden puede unirse o subdividirse.
+ Esta casilla determina si las parcelas que no son del propietario del estado pueden unirse o subdividirse.
Si no se marca esta opción:
* Sólo los propietarios o los administradores del estado pueden unir o dividir parcelas.
* Sólo podrán unir o dividir las parcelas pertenecientes al propietario o a un grupo en el que tengan los poderes adecuados.
@@ -1762,7 +1772,7 @@ Si se marca esta opción, los compradores podrán revender el terreno que compre
Por defecto: Deshabilitado
</notification>
<notification label="Desactivar los scripts" name="HelpRegionDisableScripts">
- Cuando el rendimiento de un sim es pobre, el culpable puede ser un script. Abra Estadísticas (Ctrl-May-1). Mire Simulator Physics FPS. Si es menor de 45, abre el panel Time, en la parte inferior de las Estadísticas. Si ve que Script Time está en 25 ms o más alto, pulse el botón Listar los scripts según su uso, y verá el nombre y la posición de los scripts que pueden estar causando el bajo rendimiento.
+ Cuando el rendimiento de un sim es pobre, el culpable puede ser un script. Abra Estadísticas (Ctrl+May+1). Mire Simulator Physics FPS. Si es menor de 45, abre el panel Time, en la parte inferior de las Estadísticas. Si ve que Script Time está en 25 ms o más alto, pulse el botón Listar los scripts según su uso, y verá el nombre y la posición de los scripts que pueden estar causando el bajo rendimiento.
Marcando la casilla Desactivar los scripts y pulsando el botón Aplicar, se desactivarán temporalmente en esta región todos los scripts.
Debe hacer esto para viajar a la posición que ha visto en la Lista de scripts según su uso. Cuando llegue, investigue el script para determinar si es él quien causa el problema. Deberá contactar con el propietario del script, o borrar o devolver el objeto.
@@ -1771,7 +1781,7 @@ Desmarque la casilla Desactivar los scripts y pulse Aplicar para reactivar los s
Por defecto: off
</notification>
<notification label="Desactivar las colisiones" name="HelpRegionDisableCollisions">
- Cuando el rendimiento de un sim es pobre, la culpa puede estar en los objetos físicos. Abra Estadísticas (Ctrl-May-1). Mire Simulator Physics FPS. Si es menor de 45, abre el panel Time, en la parte inferior de las Estadísticas. Si ve que Sim Time (Physics) está en 20 ms o más alto, pulse el botón Listar los objetos que colisionan, y verá el nombre y la posición de los objetos que pueden estar causando el bajo rendimiento.
+ Cuando el rendimiento de un sim es pobre, la culpa puede estar en los objetos físicos. Abra Estadísticas (Ctrl+May+1). Mire Simulator Physics FPS. Si es menor de 45, abre el panel Time, en la parte inferior de las Estadísticas. Si ve que Sim Time (Physics) está en 20 ms o más alto, pulse el botón Listar los objetos que colisionan, y verá el nombre y la posición de los objetos que pueden estar causando el bajo rendimiento.
Marcando la casilla Desactivar las colisiones y pulsando el botón Aplicar, se desactivarán temporalmente las colisiones entre objetos.
Debe hacer esto para viajar a la localización que se ha avisado en la Lista de objetos que colisionan. Cuando llegue, investigue el objeto:
@@ -1860,7 +1870,7 @@ Por defecto: on
Esta casilla fija la posición del Sol en la posición del deslizable Fase, y detiene su movimiento.
</notification>
<notification label="Acceso público" name="HelpEstateExternallyVisible">
- Esta casilla habilita a cualquier residente que esté en otro estado pueda entrar en éste sin tener que estar en una lista de acceso.
+ Esta casilla habilita que cualquier residente que esté en otro estado pueda entrar en éste sin tener que estar en una lista de acceso.
Por defecto: on
</notification>
@@ -1888,7 +1898,7 @@ Si se deja en blanco, las Denuncias de Infracción se enviarán sólo a Linden L
Por defecto: off
</notification>
<notification label="Desajuste en la versión de voz" name="VoiceVersionMismatch">
- En esta región, la versión de Second Life no es compatible con el chat de voz. Para que el chat de voz funcione correctamente, debe actualizar Second Life.
+ En esta región, la versión de [APP_NAME] no es compatible con el chat de voz. Para que el chat de voz funcione correctamente, debe actualizar [APP_NAME].
</notification>
<notification label="Contrato del estado" name="HelpEstateCovenant">
Definir un contrato del estado le permite vender parcelas del mismo. Si no existe un contrato, no puede vender terreno.
@@ -1964,14 +1974,14 @@ Serán copiados a su inventario.
¿Está seguro de querer hacer esta compra?
<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/>
</notification>
- <notification name="ConfirmPurchasePassword" type="password">
+ <notification name="ConfirmPurchasePassword">
Esta transacción hará que:
[ACTION]
¿Está seguro de querer hacer esta compra?
Por favor, vuelva a escribir su contraseña y pulse OK.
<form name="form">
- <input name="message" type="password"/>
+ <input name="message"/>
<button name="ConfirmPurchase" text="OK"/>
<button name="Cancel" text="Cancelar"/>
</form>
@@ -1995,31 +2005,28 @@ Dado que estos objetos tienen scripts, moverlos a su inventario puede provocar u
<usetemplate ignoretext="Cuando mueva objetos con script &apos;no copiables&apos; del inventario" name="okcancelignore" notext="Cancelar" yestext="OK"/>
</notification>
<notification name="ClickActionNotPayable">
- Atención: la acción Pagar al objeto al pulsar ha sido marcada, pero sólo funcionará si se añade un script con un evento money().
+ Atención: la acción &apos;Pagar al objeto&apos; al pulsar ha sido marcada, pero sólo funcionará si se añade un script con un evento money().
<form name="form">
- <ignore name="ignore" text="Cuando configure &apos;Pagar&apos; en objetos sin el evento money()"/>
+ <ignore name="ignore" text="Cuando configure &apos;Pagar al objeto&apos; sin el evento money()"/>
</form>
</notification>
<notification name="OpenObjectCannotCopy">
En este objeto, no hay ítems que esté autorizado a copiar.
</notification>
<notification name="WebLaunchAccountHistory">
- ¿Ir al sitio web de Second Life para ver el historial de su cuenta?
+ ¿Ir al sitio web de [SECOND_LIFE] para ver el historial de su cuenta?
<usetemplate ignoretext="Cuando se cargue la página web del historial de la cuenta" name="okcancelignore" notext="Cancelar" yestext="Ir a la página"/>
</notification>
<notification name="ClickOpenF1Help">
- ¿Visitar el sitio web de Soporte de Second Life?
- <usetemplate ignoretext="Cuando visite el sitio web de Soporte de Second Life." name="okcancelignore" notext="Cancelar" yestext="Ir"/>
+ ¿Visitar el sitio web de Soporte de [SECOND_LIFE]?
+ <usetemplate ignoretext="Cuando visite el sitio web de Soporte de [SECOND_LIFE]." name="okcancelignore" notext="Cancelar" yestext="Ir"/>
</notification>
<notification name="ConfirmQuit">
¿Está seguro de que quiere salir?
- <usetemplate ignoretext="Cuando esté saliendo de Second Life." name="okcancelignore" notext="Continuar" yestext="Salir"/>
+ <usetemplate ignoretext="Cuando esté saliendo de [APP_NAME]." name="okcancelignore" notext="Continuar" yestext="Salir"/>
</notification>
<notification name="HelpReportAbuseEmailLL">
- Use esta herramienta para denunciar violaciones de las Normas de la Comunidad y las Condiciones del Servicio. Vea:
-
-http://secondlife.com/corporate/tos.php
-http://secondlife.com/corporate/cs.php
+ Use esta herramienta para denunciar violaciones de las [http://secondlife.com/corporate/tos.php?lang=es-ES Condiciones del Servicio] y las [http://secondlife.com/corporate/cs.php?lang=es-ES Normas de la Comunidad].
Se investigan y resuelven todas las infracciones denunciadas de las Normas de la Comunidad y las Condiciones del Servicio. Puede ver la resolución tomada en el Informe de Incidentes, en:
@@ -2033,28 +2040,12 @@ Como un servicio a los residentes y visitantes, el propietario de la región ha
El propietario de la región resolverá las denuncias basándose en las reglas locales de la región, tal como se detallan en el Contrato del estado.
(Puede ver el Contrato yendo al menú Mundo y eligiendo Acerca del terreno).
-La resolución de esta denuncia se aplica exclusivamente a esta región; el acceso de los residentes a otras áreas de Second Life no se verá afectado por el resultado de esta denuncia. Únicamente Linden Lab puede impedir el acceso a la totalidad de Second Life.
- </notification>
- <notification name="HelpReportBug">
- Use esta herramienta *sólo* para informar de cuestiones técnicas que no se comportan como se describe o era esperable. Por favor, aporte todos los detalles que pueda.
-Deberá responder al correo electrónico de auto respuesta para añadir más detalles a su informe.
-
-Todos los informes de fallos serán investigados y evaluados. No se contestará por correo electrónico.
-
-Si tiene algún problema técnico, por favor, contacte con Soporte en:
-
-http://secondlife.com/community/support.php
-
-Nota: no se investigarán los informes incompletos.
+La resolución de esta denuncia se aplica exclusivamente a esta región; el acceso de los residentes a otras áreas de [SECOND_LIFE] no se verá afectado por el resultado de esta denuncia. Únicamente Linden Lab puede impedir el acceso a la totalidad de [SECOND_LIFE].
</notification>
<notification name="HelpReportAbuseSelectCategory">
Por favor, elija una categoría para esta denuncia de infracción.
Seleccionar una categoría nos ayuda a clasificar y procesar las denuncias de infracciones.
</notification>
- <notification name="HelpReportBugSelectCategory">
- Por favor, elija una categoría para este fallo.
-Seleccionar una categoría nos ayuda a clasificar y procesar los informes de fallos.
- </notification>
<notification name="HelpReportAbuseAbuserNameEmpty">
Por favor, escriba el nombre del infractor.
Aportar el dato preciso nos ayuda a clasificar y procesar las denuncias de infracciones.
@@ -2067,28 +2058,19 @@ Aportar el dato preciso nos ayuda a clasificar y procesar las denuncias de infra
Por favor, escriba un resumen de la infracción que ha habido.
Aportar un resumen preciso nos ayuda a clasificar y procesar las denuncias de infracciones.
</notification>
- <notification name="HelpReportBugSummaryEmpty">
- Por favor, escriba un resumen del fallo.
-Aportar un resumen preciso nos ayuda a clasificar y procesar los informes de fallos.
- </notification>
<notification name="HelpReportAbuseDetailsEmpty">
Por favor, escriba una descripción minuciosa de la infracción que ha habido.
Sea tan específico como pueda, incluyendo los nombres y los detalles implicados en el incidente que denuncia.
Aportar una descripción precisa nos ayuda a clasificar y procesar las denuncias de infracciones.
</notification>
- <notification name="HelpReportBugDetailsEmpty">
- Por favor, escriba una descripción minuciosa del fallo.
-Sea tan específico como pueda, incluyendo -si es posible- los pasos que permitan reproducir el fallo.
-Aportar una descripción precisa nos ayuda a clasificar y procesar los informes de fallos.
- </notification>
<notification name="HelpReportAbuseContainsCopyright">
Estimado Residente:
Parece que está usted denunciando una violación de la propiedad intelectual. Por favor, asegúrese de que su denuncia es correcto.
-(1) El proceso de la denuncia. Debe enviar una denuncia de infracción si cree que un Residente está reventando el sistema de permisos de Second Life, por ejemplo, usando un CopyBot u otras herramientas parecidas para copiar, infringiendo los derechos de propiedad intelectual. El Equipo de Infracciones (Abuse Team) investiga y lleva a cabo las acciones disciplinarias apropiadas ante toda acción que viole las las Normas de la Comunidad de Second Life o las Condiciones del Servicio. Sin embargo, el Equipo de Infracciones ni gestiona ni responde a las solicitudes de eliminar contenidos del mundo de Second Life.
+(1) El proceso de la denuncia. Debe enviar una denuncia de infracción si cree que un Residente está reventando el sistema de permisos de [SECOND_LIFE], por ejemplo, usando un CopyBot u otras herramientas parecidas para copiar, infringiendo los derechos de propiedad intelectual. El Equipo de Infracciones (Abuse Team) investiga y lleva a cabo las acciones disciplinarias apropiadas ante toda acción que viole las las Normas de la Comunidad de [SECOND_LIFE] o las Condiciones del Servicio. Sin embargo, el Equipo de Infracciones ni gestiona ni responde a las solicitudes de eliminar contenidos del mundo de [SECOND_LIFE].
-(2) El DMCA o Proceso de Eliminación de Contenido. Para solicitar que se elimine algún contenido de Second Life, DEBE enviar una notificación válida de infracción tal y como se explica en nuestra DMCA Policy en http://secondlife.com/corporate/dmca.php.
+(2) El DMCA o Proceso de Eliminación de Contenido. Para solicitar que se elimine algún contenido de [SECOND_LIFE], DEBE enviar una notificación válida de infracción tal y como se explica en nuestra DMCA Policy en http://secondlife.com/corporate/dmca.php.
Si todavía quiere seguir con el proceso de infracción, por favor, cierre esta ventana y acabe de enviar su denuncia. En concreto, debe seleccionar la categoría &apos;CopyBot o Programa para saltarse los permisos&apos;.
@@ -2162,7 +2144,7 @@ Núm. máx. de partículas: define el número máximo de partículas que podrá
Calidad del procesamiento: define la resolución con que se renderiza el brillo.
-Detalle de la malla: define la cantidad de dettales o número de triángulos usados para renderizar algunos objetos. Cuanto más alto sea el valor, más detalle, pero más tiempo para renderizar.
+Detalle de la malla: define la cantidad de detalles o número de triángulos usados para renderizar algunos objetos. Cuanto más alto sea el valor, más detalle, pero más tiempo para renderizar.
Detalles de la iluminación: determina que tipo de luces quiere usted que se rendericen.
@@ -2195,30 +2177,30 @@ Nivel de detalle del terreno: marca con cuánto detalle quiere ver la textura de
<notification name="EnvSettingsHelpButton">
Estas configuraciones ajustan la forma en que usted ve el medio ambiente localmente, en su ordenador. Su tarjeta gráfica debe admitir shaders de la atmósfera (&apos;atmospheric shaders&apos;) para poder acceder a esta configuración.
-Ajuste el deslizable &quot;Duración de un día&quot; para cambiar localmente, en su visor, las etapas del día.
+Ajuste el deslizable &apos;Duración de un día&apos; para cambiar localmente, en su visor, las etapas del día.
-Ajuste el deslizable &quot;Nubosidad&quot; para controlar cuántas nubes cubren el cielo.
+Ajuste el deslizable &apos;Nubosidad&apos; para controlar cuántas nubes cubren el cielo.
-Pulse un color en el selector de &quot;Color del agua&quot; para cambiar el color de la misma.
+Pulse un color en el selector de &apos;Color del agua&apos; para cambiar el color de la misma.
-Ajuste el deslizable &quot;Claridad del agua&quot; para controlar el nivel de claridad del agua bajo la superficie.
+Ajuste el deslizable &apos;Claridad del agua&apos; para controlar el nivel de claridad del agua bajo la superficie.
-Pulse &quot;Usar el horario del estado&quot; para devolver los valores del día al tiempo actual de la región y seguir a partir de él.
+Pulse &apos;Usar el horario del estado&apos; para devolver los valores del día al tiempo actual de la región y seguir a partir de él.
-Pulse &quot;Cielo avanzado&quot; para abrir un editor con configuraciones avanzadas para el cielo.
+Pulse &apos;Cielo avanzado&apos; para abrir un editor con configuraciones avanzadas para el cielo.
-Pulse &quot;Agua avanzada&quot; para abrir un editor con configuraciones avanzadas para el agua.
+Pulse &apos;Agua avanzada&apos; para abrir un editor con configuraciones avanzadas para el agua.
</notification>
<notification name="HelpDayCycle">
- El Editor del ciclo del día le permite controlar el cielo de Second Life durante el ciclo día/noche. Este es el ciclo que usa el deslizable Duración de un día del Editor del entorno.
+ El Editor del ciclo del día le permite controlar el cielo de [SECOND_LIFE] durante el ciclo día/noche. Este es el ciclo que usa el deslizable Duración de un día del Editor del entorno.
-El Editor del ciclo del día trabaja configurando fotogramas clave (&apos;keyframes&apos;): nodos (representados por los puntos grises en la línea del tiempo) cada uno de los cuales tiene asociado un Cielo definido. Según progresa la Duración de un día, el WindLight realiza la &quot;animación&quot; del cielo interpolándose entre esos fotogramas clave.
+El Editor del ciclo del día trabaja configurando fotogramas clave (&apos;keyframes&apos;): nodos (representados por los puntos grises en la línea del tiempo) cada uno de los cuales tiene asociado un Cielo definido. Según progresa la Duración de un día, el WindLight realiza la &apos;animación&apos; del cielo interpolándose entre esos fotogramas clave.
La flecha amarilla sobre la línea del tiempo representa lo que usted ve actualmente, basándose en la Duración de un día. Púlsela y muévela para ver cómo cambia la animación del día. Puede añadir o borrar fotogramas clave pulsando los botones Añadir un punto o Quitar un punto, situados a la derecha de la línea del tiempo.
-Puede establecer la posición en el tiempo de cualquier fotograma clave moviéndolo a lo largo de la línea del tiempo, o configurando manualmente su valor por su valor manualmente en el recuadro Configuración del fotograma clave. También en ese recuadro podrá asociar el fotograma clave a un modelo predefinido de WindLight.
+Puede establecer la posición en el tiempo de cualquier fotograma clave moviéndolo a lo largo de la línea del tiempo, o configurando manualmente su valor en el recuadro Configuración del fotograma clave. También en ese recuadro podrá asociar el fotograma clave a un modelo predefinido de WindLight.
-La Duración del ciclo establece la duración total de un &quot;día&quot;. Marcar un valor bajo (por ejemplo, 2 min.) hará que las 24 horas de su línea del tiempo se animen ¡en sólo dos minutos reales! Una vez que esté satisfecho con su ciclo de la línea del tiempo y los fotogramas clave, utilice los botones Probar y Parar para obtener una vista previa de los resultados. Recuerde que también puede mover la flecha amarilla de encima de la línea del tiempo para ver el ciclo de la animación. El botón Usar el horario del estado sincronizará su ciclo de duración de un día con el ciclo del estado.
+La Duración del ciclo establece la duración total de un &apos;día&apos;. Marcar un valor bajo (por ejemplo, 2 min.) hará que las 24 horas de su línea del tiempo se animen ¡en sólo dos minutos reales! Una vez que esté satisfecho con su ciclo de la línea del tiempo y los fotogramas clave, utilice los botones Probar y Parar para obtener una vista previa de los resultados. Recuerde que también puede mover la flecha amarilla de encima de la línea del tiempo para ver el ciclo de la animación. El botón Usar el horario del estado sincronizará su ciclo de duración de un día con el ciclo del estado.
Cuando todo esté a su gusto, puede guardar esos datos y cargarlos luego usando los botones Guardar este tipo de día y Cargar un tipo de día. Note que, por el momento, sólo podemos permitir un ciclo de un día.
</notification>
@@ -2235,13 +2217,13 @@ Cuando todo esté a su gusto, puede guardar esos datos y cargarlos luego usando
La Densidad de la bruma controla lo sombrío de la atmósfera, su neblina. Es eficaz para simular escenas con mucho humo o contaminantes, y también para simular niebla y llovizna.
</notification>
<notification name="HelpDensityMult">
- La Densidad puede usarse para definir globalmente la &apos;pesadez&apos; de la atmósfera. Los ajustes bajos dan sensación de un &quot;aire limpio&quot;, y los altos de pesadez, de esmog.
+ La Densidad puede usarse para definir globalmente la &apos;pesadez&apos; de la atmósfera. Los ajustes bajos dan sensación de un &apos;aire limpio&apos;, y los altos de pesadez, de esmog.
</notification>
<notification name="HelpDistanceMult">
Ajusta a qué distancia se percibe el WindLight. El valor cero desactiva la influencia del WindLight en el terreno y los objetos. Los valores superiores a 1 simulan mayores distancias a las que afectan los efectos atmosféricos
</notification>
<notification name="HelpMaxAltitude">
- La Altitud máx. ajusta hasta que altura el WindLight realiza sus cálculos para computar la iluminación atmosférica. En las últimas horas del día, es útil para ajustar la &quot;profundidad&quot; a la que aparece el Sol.
+ La Altitud máx. ajusta hasta que altura el WindLight realiza sus cálculos para computar la iluminación atmosférica. En las últimas horas del día, es útil para ajustar la &apos;profundidad&apos; a la que aparece el Sol.
</notification>
<notification name="HelpSunlightColor">
Ajusta en la escena la intensidad y el color de las luces directas.
@@ -2288,7 +2270,7 @@ Pero, vaya, diviértase si quiere.
Controla la velocidad de las nubes al moverse en la dirección del eje Y.
</notification>
<notification name="HelpClassicClouds">
- Marque esta casilla para activar la aparición de las nubes clásicas de Second Life junto a las nubes del WindLight.
+ Marque esta casilla para activar la aparición de las nubes clásicas de [SECOND_LIFE] junto a las nubes del WindLight.
</notification>
<notification name="HelpWaterFogColor">
Elije el color del agua bajo la superficie.
@@ -2332,7 +2314,7 @@ Pero, vaya, diviértase si quiere.
<notification name="NewSkyPreset">
Dame un nombre para el cielo nuevo.
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Preselección nueva
</input>
<button name="OK" text="OK"/>
@@ -2345,7 +2327,7 @@ Pero, vaya, diviértase si quiere.
<notification name="NewWaterPreset">
Dame un nombre para la nueva preselección de agua.
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Preselección nueva
</input>
<button name="OK" text="OK"/>
@@ -2382,21 +2364,21 @@ Pero, vaya, diviértase si quiere.
</notification>
<notification name="AutoWearNewClothing">
¿Quiere vestirse automáticamente el ítem de ropa nueva que ha creado?
- <usetemplate ignoretext="Vestirme automáticamente la ropa nueva" name="okcancelignore" notext="No" yestext="Sí"/>
+ <usetemplate ignoretext="Al vestirme automáticamente la ropa nueva" name="okcancelignore" notext="No" yestext="Sí"/>
</notification>
<notification name="NotAgeVerified">
Para acceder a esta parcela, se debe haber verificado su edad.
-¿Quiere visitar la web de Second Life para verificar su edad?
+¿Quiere visitar la web de [SECOND_LIFE] para verificar su edad?
[_URL]
<url name="url" option="0">
- https://secondlife.com/account/verification.php
+ https://secondlife.com/account/verification.php?lang=es
</url>
<usetemplate ignoretext="Advertir de la falta de la verificación de edad" name="okcancelignore" notext="No" yestext="Sí"/>
</notification>
<notification name="Cannot enter parcel: no payment info on file">
Antes de que pueda acceder a esta parcela, se requiere que usted tenga archivada su información de pago.
-¿Quiere visitar la web de Second Life para actualizar esto?
+¿Quiere visitar la web de [SECOND_LIFE] para actualizar esto?
[_URL]
<url name="url" option="0">
@@ -2663,7 +2645,7 @@ Vaya a la &apos;Help Island Public&apos; (&apos;Isla Pública de Ayuda&apos;) pa
<notification name="ImproperPaymentStatus">
No tiene el estado de pago adecuado para entrar a esta región.
</notification>
- <notification name="MustGetAgeRgion">
+ <notification name="MustGetAgeRegion">
Debe haber verificado su edad para entrar a esta región.
</notification>
<notification name="MustGetAgeParcel">
@@ -2713,13 +2695,13 @@ Por favor, reinténtelo en unos momentos.
No se puede crear la conexión.
</notification>
<notification name="InternalUsherError">
- Se ha producido un error interno al intentar acceder al destino de su teleporte. Puede que, en este momento, el servicio de Second Life tenga problemas.
+ Se ha producido un error interno al intentar acceder al destino de su teleporte. Puede que, en este momento, el servicio de [SECOND_LIFE] tenga problemas.
</notification>
<notification name="NoGoodTPDestination">
No se puede encontrar en esta región un buen destino para el teleporte.
</notification>
<notification name="InternalErrorRegionResolver">
- Ha sucedido un error interno al manejar las coordenadas globales de su petición de teleporte. Puede que, en este momento, el servicio de Second Life tenga problemas.
+ Ha sucedido un error interno al manejar las coordenadas globales de su petición de teleporte. Puede que, en este momento, el servicio de [SECOND_LIFE] tenga problemas.
</notification>
<notification name="NoValidLanding">
No se ha podido encontrar un punto de aterrizaje válido.
@@ -2840,7 +2822,7 @@ Del objeto: [OBJECTNAME]; propiedad de: [NAME]?
Búsqueda fallida de [TYPE] de nombre [DESC] en la base de datos.
</notification>
<notification name="InvalidWearable">
- El ítem que intenta llevar usa una característica que su visor no puede leer. Por favor, actualice su versión de Second Life para llevar este ítem.
+ El ítem que intenta llevar usa una característica que su visor no puede leer. Por favor, actualice su versión de [APP_NAME] para llevar este ítem.
</notification>
<notification name="ScriptQuestion">
&apos;[OBJECTNAME]&apos;, un objeto propiedad de &apos;[NAME]&apos;, querría:
@@ -2943,8 +2925,8 @@ Los objetos flexibles no pueden ser materiales, y serán inmateriales hasta que
</notification>
<notification name="FirstDebugMenus">
Ha activado el menú Avanzado.
-Contiene herramientas útiles para los desarrolladores que trabajan mejorando Second Life.
-Para pasar este menú a una ventana, pulse Ctrl-Alt-D. En un Mac, pulse Cmd-Opt-Shift-D.
+Contiene herramientas útiles para los desarrolladores que trabajan mejorando [SECOND_LIFE].
+Para pasar este menú a una ventana, pulse Ctrl+Alt+D. En un Mac, pulse &#8997;&#8984;D.
</notification>
<notification name="FirstSculptedPrim">
Está editando un prim &apos;sculpted&apos;.
@@ -3051,7 +3033,7 @@ Pulse Aceptar para entrar al chat o Rehusar para declinar la invitación. Pulse
- La velocidad de su CPU no cumple los requerimientos mínimos.
</global>
<global name="UnsupportedGLRequirements">
- Parece que no tiene los requerimientos de hardware apropiados para Second Life. Second Life requiere una tarjeta gráfica OpenGL que admita texturas múltiples (&apos;multitexture support&apos;). Si la tiene, compruebe que tiene los últimos drivers para su tarjeta gráfica, así como los últimos parches y &apos;service packs&apos; para su sistema operativo.
+ Parece que no tiene los requerimientos de hardware apropiados para [APP_NAME]. [APP_NAME] requiere una tarjeta gráfica OpenGL que admita texturas múltiples (&apos;multitexture support&apos;). Si la tiene, compruebe que tiene los últimos drivers para su tarjeta gráfica, así como los últimos parches y &apos;service packs&apos; para su sistema operativo.
Si los problemas persisten, por favor, acuda a: http://www.secondlife.com/support
</global>
diff --git a/indra/newview/skins/default/xui/es/panel_edit_profile.xml b/indra/newview/skins/default/xui/es/panel_edit_profile.xml
new file mode 100644
index 0000000000..c12dd8d58c
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_edit_profile.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel name="edit_profile_panel">
+ <string name="CaptionTextAcctInfo">
+ [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION]
+ </string>
+ <string name="AcctTypeResident"
+ value="Residente" />
+ <string name="AcctTypeTrial"
+ value="Prueba" />
+ <string name="AcctTypeCharterMember"
+ value="Miembro fundador" />
+ <string name="AcctTypeEmployee"
+ value="Empleado de Linden Lab" />
+ <string name="PaymentInfoUsed"
+ value="Ha usado una forma de pago" />
+ <string name="PaymentInfoOnFile"
+ value="Hay infor. de la forma de pago" />
+ <string name="NoPaymentInfoOnFile"
+ value="Sin infor. de la forma de pago" />
+ <string name="AgeVerified"
+ value="Edad verificada" />
+ <string name="NotAgeVerified"
+ value="Edad no verificada" />
+ <string name="partner_edit_link_url">
+ http://www.secondlife.com/account/partners.php?lang=es
+ </string>
+ <panel name="scroll_content_panel">
+ <panel name="data_panel" >
+ <panel name="lifes_images_panel">
+ <panel name="second_life_image_panel">
+ <text name="second_life_photo_title_text">
+ [SECOND_LIFE]:
+ </text>
+ </panel>
+ </panel>
+ <text name="title_partner_text" value="Compañero/a:"/>
+ <panel name="partner_data_panel">
+ <text name="partner_text" value="[FIRST] [LAST]"/>
+ </panel>
+ <text name="text_box3">
+ Mensaje en el estado ocupado:
+ </text>
+ </panel>
+ </panel>
+</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 e5fd4b3aae..4fd5685b7d 100644
--- a/indra/newview/skins/default/xui/es/panel_group_general.xml
+++ b/indra/newview/skins/default/xui/es/panel_group_general.xml
@@ -1,9 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="General" name="general_tab">
<string name="help_text">
- La pestaña General contiene información global de este grupo,
-la lista de propietarios y miembros visibles,
-las preferencias generales del grupo, y las opciones de los miembros.
+ La pestaña General contiene información global de este grupo, la lista de propietarios y miembros visibles, las preferencias generales del grupo, y las opciones de los miembros.
Ponga su ratón sobre las opciones para más información.
</string>
@@ -37,9 +35,9 @@ Ponga su ratón sobre las opciones para más información.
(los propietarios aparecen en negrilla)
</text>
<name_list name="visible_members">
- <column label="Nombre del miembro" name="name"/>
- <column label="Etiqueta" name="title"/>
- <column label="Última conexión" name="online"/>
+ <name_list.columns label="Nombre del miembro" name="name" relwidth="0.40"/>
+ <name_list.columns label="Etiqueta" name="title" relwidth="0.25"/>
+ <name_list.columns label="Última conexión" name="online" relwidth="0.35"/>
</name_list>
<text name="text_group_preferences">
Preferencias del grupo
@@ -47,18 +45,12 @@ Ponga su ratón sobre las opciones para más información.
<panel name="preferences_container">
<check_box label="Mostrar en la búsqueda" name="show_in_group_list" tool_tip="Dejar que la gente vea este grupo en los resultados de la búsqueda."/>
<check_box label="Inscripción libre" name="open_enrollement" tool_tip="Definir si se admiten al grupo nuevos miembros sin que sea preciso invitárseles."/>
- <check_box label="Cuota de inscripción en L$" name="check_enrollment_fee" tool_tip="Define si se requiere una cuota para entrar al grupo."/>
- <spinner name="spin_enrollment_fee" tool_tip="Cuando está marcado &apos;Cuota de inscripción&apos;, los miembros nuevos deben pagar esta cuota para entrar al grupo."/>
- <combo_box name="group_mature_check" tool_tip="Establece si la información de su grupo es &apos;mature&apos;.">
- <combo_item name="select_mature">
- - Elegir Calificación -
- </combo_item>
- <combo_item name="mature">
- Contenido &apos;Mature&apos;
- </combo_item>
- <combo_item name="pg">
- Contenido &apos;PG&apos;
- </combo_item>
+ <check_box label="Cuota de inscripción:" name="check_enrollment_fee" tool_tip="Define si se requiere una cuota para entrar al grupo."/>
+ <spinner width="60" left_delta="130" name="spin_enrollment_fee" tool_tip="Cuando está marcado &apos;Cuota de inscripción&apos;, los miembros nuevos deben pagar esta cuota para entrar al grupo."/>
+ <combo_box bottom_delta="-38" width="150" name="group_mature_check" tool_tip="Establece si la información de su grupo es &apos;mature&apos;.">
+ <combo_box.item name="select_mature" label="- Elegir Calificación -"/>
+ <combo_box.item name="mature" label="Contenido &apos;Mature&apos;"/>
+ <combo_box.item name="pg" label="Contenido &apos;PG&apos;"/>
</combo_box>
<panel name="title_container">
<text name="active_title_label">
diff --git a/indra/newview/skins/default/xui/es/panel_group_invite.xml b/indra/newview/skins/default/xui/es/panel_group_invite.xml
index 5f5f2c6e2e..f66f0c473a 100644
--- a/indra/newview/skins/default/xui/es/panel_group_invite.xml
+++ b/indra/newview/skins/default/xui/es/panel_group_invite.xml
@@ -1,13 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<panel label="Invitar a un miembro" name="invite_panel">
- <text name="help_text">
- Puede seleccionar a varios residentes para
-invitarles a su grupo. Para empezar, pulse
-&apos;Abrir el selector de residentes&apos;.
+<panel label="Invitar a un miembro" name="invite_panel" width="224">
+ <text name="help_text" height="72" bottom_delta="-96" width="214">
+ Puede seleccionar a varios residentes
+para invitarles a su grupo. Para
+empezar, pulse &apos;Abrir el selector de
+residentes&apos;.
</text>
- <button label="Abrir el selector de residentes" name="add_button" tool_tip=""/>
- <name_list name="invitee_list" tool_tip="Para seleccionar a varios residentes, mantenga pulsada la tecla Ctrl y vaya pulsando sus nombres."/>
- <button label="Eliminar de la lista a los seleccionados" name="remove_button" tool_tip="Elimina los residentes seleccionados de la lista de invitaciones."/>
+ <button bottom_delta="-10" label="Abrir el selector de residentes" name="add_button" tool_tip=""/>
+ <name_list height="156" bottom_delta="-160" name="invitee_list" tool_tip="Para seleccionar a varios residentes, mantenga pulsada la tecla Ctrl y vaya pulsando sus nombres."/>
+ <button left_delta="-7" width="214" label="Eliminar de la lista a los seleccionados" name="remove_button" tool_tip="Elimina los residentes seleccionados de la lista de invitaciones."/>
<text name="role_text">
Elegir qué rol asignarles:
</text>
diff --git a/indra/newview/skins/default/xui/es/panel_group_land_money.xml b/indra/newview/skins/default/xui/es/panel_group_land_money.xml
index 32473b8133..bccc114624 100644
--- a/indra/newview/skins/default/xui/es/panel_group_land_money.xml
+++ b/indra/newview/skins/default/xui/es/panel_group_land_money.xml
@@ -13,17 +13,17 @@
<string name="loading_txt">
Cargando...
</string>
- <text name="group_land_heading">
+ <text name="group_land_heading" width="250">
Terreno propiedad del grupo
</text>
<scroll_list name="group_parcel_list">
- <column label="Parcela" name="name"/>
- <column label="Región" name="location"/>
- <column label="Tipo" name="type"/>
- <column label="Superficie" name="area"/>
+ <column label="Parcela" name="name" width="100"/>
+ <column label="Región" name="location" width="100"/>
+ <column label="Tipo" name="type" width="100"/>
+ <column label="Superficie" name="area" width="81"/>
<column label="" name="hidden"/>
</scroll_list>
- <button label="Mostrar en el mapa" label_selected="Mostrar en el mapa" name="map_button"/>
+ <button label="Mostrar en el mapa" label_selected="Mostrar en el mapa" name="map_button" left="282" width="130"/>
<text name="total_contributed_land_label">
Contribución total:
</text>
@@ -48,11 +48,15 @@
<string name="land_contrib_error">
No se ha podido defininir su contribución de terreno.
</string>
+ <text name="your_contribution_units">
+ ( m² )
+ </text>
<text name="your_contribution_max_value">
- m² ([AMOUNT] máx.)
+ ([AMOUNT] máx.)
</text>
<text name="group_over_limit_text">
- Los miembros del grupo deben contribuir con más créditos de terreno para mantener el terreno en uso.
+ Los miembros del grupo deben contribuir con más créditos de terreno
+para mantener el terreno en uso.
</text>
<text name="group_money_heading">
L$ del grupo
diff --git a/indra/newview/skins/default/xui/es/panel_group_notices.xml b/indra/newview/skins/default/xui/es/panel_group_notices.xml
index 8215575362..c6788b3a65 100644
--- a/indra/newview/skins/default/xui/es/panel_group_notices.xml
+++ b/indra/newview/skins/default/xui/es/panel_group_notices.xml
@@ -1,12 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Avisos" name="notices_tab">
<text name="help_text">
- Los avisos son una forma rápida de comunicación dentro
-de un grupo, difundiendo un mensaje y,
-si se quiere, añadiéndole un ítem. Los avisos sólo
-los reciben los miembros del grupo cuyo rol
-tiene adjudicada tal habilidad. Puede desactivar
-los avisos en la pestaña General
+ Los avisos son una forma rápida de comunicación dentro de un grupo, difundiendo un mensaje y, si se quiere, añadiéndole un ítem. Los avisos sólo los reciben los miembros del grupo cuyo rol tiene adjudicada tal habilidad. Puede desactivar los avisos en la pestaña General.
</text>
<text name="no_notices_text">
No hay avisos pasados.
@@ -16,9 +11,7 @@ los avisos en la pestaña General
Archivo de avisos del grupo
</text>
<text name="lbl2">
- Los avisos se mantienen durante 14 días. Pulse en la lista de abajo el que quiere ver.
-Pulse el botón &apos;Actualizar&apos; para comprobar si se han recibido avisos nuevos.
-Las listas de avisos tienen un límite de 200 avisos por día.
+ Los avisos se mantienen durante 14 días. Las listas de avisos tienen un límite de 200 avisos por día.
</text>
<scroll_list name="notice_list">
<column label="Asunto" name="subject"/>
@@ -35,10 +28,7 @@ Las listas de avisos tienen un límite de 200 avisos por día.
Crear un aviso
</text>
<text name="lbl2">
- Para enviar un aviso, debe escribir un asunto. Puede añadir un ítem
-al aviso arrastrándolo desde su inventario a este panel.
-Los ítems anexados deben ser copiables y transferibles,
-y no se puede enviar una carpeta.
+ Puede añadir un ítem al aviso arrastrándolo desde su inventario a este panel. Los ítems anexados deben ser copiables y transferibles, y no se puede enviar una carpeta.
</text>
<text name="lbl3">
Asunto:
@@ -50,7 +40,7 @@ y no se puede enviar una carpeta.
Anexar:
</text>
<button label="Remover lo anexado" label_selected="Remover lo anexado" name="remove_attachment"/>
- <button label="Enviar el aviso" label_selected="Enviar el aviso" name="send_notice"/>
+ <button label="Enviar" label_selected="Enviar" name="send_notice"/>
<panel name="drop_target" tool_tip="Para enviar un ítem con el aviso, arrástrelo desde su inventario hasta el cuadro del mensaje. Para poder enviar ese objeto con el aviso, usted debe tener permiso para copiarlo y transferirlo."/>
</panel>
<panel label="Ver avisos pasados" name="panel_view_past_notice">
diff --git a/indra/newview/skins/default/xui/es/panel_group_roles.xml b/indra/newview/skins/default/xui/es/panel_group_roles.xml
index 8cc1a4ba9d..2739a3da5e 100644
--- a/indra/newview/skins/default/xui/es/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/es/panel_group_roles.xml
@@ -12,7 +12,9 @@
Miembros y Roles
</text>
<text name="static2">
- Los miembros del grupo tienen asignados roles con distintas capacidades. Estas configuraciones son fácilmente personalizables, para facilitar una mayor flexibilidad y organización.
+ Los miembros del grupo tienen asignados roles con distintas capacidades.
+Estas configuraciones son fácilmente personalizables, para facilitar una
+mayor flexibilidad y organización.
</text>
</panel>
<panel name="roles_header">
@@ -20,12 +22,14 @@
Roles
</text>
<text name="role_properties_modifiable">
- Elija un rol de los de abajo. Puede modificar su nombre, su descripción, y la etiqueta de los miembros.
+ Elija un rol de los de abajo. Puede modificar su nombre, su
+descripción, y la etiqueta de los miembros.
</text>
<text name="role_properties_not_modifiable">
- Elija un rol de los de abajo para ver sus propiedades, miembros, y qué capacidades tiene asignadas.
+ Elija un rol de los de abajo para ver sus propiedades, miembros, y qué
+capacidades tiene asignadas.
</text>
- <text name="role_actions_modifiable">
+ <text bottom_delta="-28" name="role_actions_modifiable">
También puede asignar capacidades al rol.
</text>
<text name="role_actions_not_modifiable">
@@ -37,29 +41,32 @@
Capacidades
</text>
<text name="static2">
- Puede ver una descripción de la capacidad, y qué miembros y roles pueden realizarla.
+ Puede ver una descripción de la capacidad, y qué miembros y roles pueden
+realizarla.
</text>
</panel>
- <tab_container name="roles_tab_container">
- <panel label="Miembros" name="members_sub_tab" tool_tip="Miembros">
- <button label="Buscar" name="search_button"/>
- <button label="Verlos todos" name="show_all_button"/>
- <name_list name="member_list">
+ <tab_container height="164" name="roles_tab_container">
+ <panel height="148" label="Miembros" name="members_sub_tab" tool_tip="Miembros">
+ <line_editor bottom="127" name="search_text"/>
+ <button label="Buscar" name="search_button" width="75"/>
+ <button label="Verlos todos" name="show_all_button" left_delta="80"/>
+ <name_list name="member_list" bottom_delta="-105" height="104" >
<column label="Nombre del miembro" name="name"/>
<column label="Cuotas donadas" name="donated"/>
<column label="Última conexión" name="online"/>
</name_list>
- <button label="Invitar a un nuevo miembro..." name="member_invite"/>
+ <button label="Invitar a un nuevo miembro..." name="member_invite" width="175"/>
<button label="Expulsar del grupo" name="member_eject"/>
<string name="help_text">
Puede añadir o quitar los roles asignados a los miembros.
Seleccione varios nombres manteniendo pulsada la tecla Ctrl y pulsando en cada uno de ellos.
</string>
</panel>
- <panel label="Roles" name="roles_sub_tab">
- <button label="Buscar" name="search_button"/>
- <button label="Verlos todos" name="show_all_button"/>
- <scroll_list name="role_list">
+ <panel height="148" label="Roles" name="roles_sub_tab">
+ <line_editor bottom="127" name="search_text"/>
+ <button label="Buscar" name="search_button" width="75"/>
+ <button label="Verlos todos" name="show_all_button" left_delta="80"/>
+ <scroll_list name="role_list" bottom_delta="-104" height="104">
<column label="Nombre del rol" name="name"/>
<column label="Etiqueta" name="title"/>
<column label="Miembros" name="members"/>
@@ -73,10 +80,11 @@ Seleccione varios nombres manteniendo pulsada la tecla Ctrl y pulsando en cada u
Los roles de &apos;Todos&apos; y &apos;Propietarios&apos; son especiales, y no pueden eliminarse.
</string>
</panel>
- <panel label="Capacidades" name="actions_sub_tab">
- <button label="Buscar" name="search_button"/>
- <button label="Verlos todos" name="show_all_button"/>
- <scroll_list name="action_list" tool_tip="Elija una capacidad para verla más en detalle.">
+ <panel height="148" label="Capacidades" name="actions_sub_tab">
+ <line_editor bottom="127" name="search_text"/>
+ <button label="Buscar" name="search_button" width="75"/>
+ <button label="Verlos todos" name="show_all_button" left_delta="80"/>
+ <scroll_list bottom_delta="-120" height="118" name="action_list" tool_tip="Elija una capacidad para verla más en detalle.">
<column label="" name="icon"/>
<column label="" name="action"/>
</scroll_list>
diff --git a/indra/newview/skins/default/xui/es/panel_groups.xml b/indra/newview/skins/default/xui/es/panel_groups.xml
index 1259ded62f..232de85522 100644
--- a/indra/newview/skins/default/xui/es/panel_groups.xml
+++ b/indra/newview/skins/default/xui/es/panel_groups.xml
@@ -1,9 +1,11 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="groups">
- <text name="groupdesc">
- El grupo que tiene activado actualmente se muestra en negrilla
+ <scroll_list bottom="50" name="group list"/>
+ <text bottom="16" height="32" name="groupdesc" width="268">
+ El grupo que tiene activado actualmente se
+muestra en negrilla.
</text>
- <text name="groupcount">
+ <text bottom="3" name="groupcount" width="268">
Pertenece a [COUNT] grupo/s (de un máximo de [MAX]).
</text>
<button label="MI/Llamar" name="IM" tool_tip="Abrir una sesión de mensajes instantáneos"/>
diff --git a/indra/newview/skins/default/xui/es/panel_login.xml b/indra/newview/skins/default/xui/es/panel_login.xml
index 04edcc4faa..52c3855d6a 100644
--- a/indra/newview/skins/default/xui/es/panel_login.xml
+++ b/indra/newview/skins/default/xui/es/panel_login.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="panel_login">
- <string name="real_url">
- http://secondlife.com/app/login/
- </string>
- <string name="forgot_password_url">
- http://secondlife.com/account/request.php
- </string>
+ <panel.string name="create_account_url">
+ http://join.secondlife.com/index.php?lang=es-ES
+ </panel.string>
+ <panel.string name="forgot_password_url">
+ http://secondlife.com/account/request.php?lang=es
+ </panel.string>
+<panel name="login_widgets">
<text name="first_name_text">
Nombre:
</text>
@@ -19,15 +20,9 @@
Posición inicial:
</text>
<combo_box name="start_location_combo">
- <combo_item name="MyHome">
- Mi Base
- </combo_item>
- <combo_item name="MyLastLocation">
- Mi última posición
- </combo_item>
- <combo_item name="Typeregionname">
- &lt;Escriba el nombre de la Región&gt;
- </combo_item>
+ <combo_box.item name="MyHome" label="Mi Base"/>
+ <combo_box.item name="MyLastLocation" label="Mi última posición"/>
+ <combo_box.item name="Typeregionname" label="&lt;Escriba el nombre de la Región&gt;"/>
</combo_box>
<check_box label="Recordar la contraseña" name="remember_check"/>
<button label="Iniciar sesión" label_selected="Iniciar sesión" name="connect_btn"/>
@@ -41,3 +36,4 @@
[VERSION]
</text>
</panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/es/panel_preferences_advanced.xml
new file mode 100644
index 0000000000..02fb4da017
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_preferences_advanced.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<panel name="advanced">
+ <text name="AspectRatioLabel1" tool_tip="ancho / alto">
+ Proporción:
+ </text>
+ <combo_box name="aspect_ratio" tool_tip="ancho / alto">
+ <combo_box.item label="4:3 (Standard CRT)" name="item1"/>
+ <combo_box.item label="5:4 (1280x1024 LCD)" name="item2"/>
+ <combo_box.item label="8:5 (Widescreen)" name="item3"/>
+ <combo_box.item label="16:9 (Widescreen)" name="item4"/>
+ </combo_box>
+</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_preferences_alerts.xml b/indra/newview/skins/default/xui/es/panel_preferences_alerts.xml
new file mode 100644
index 0000000000..a71ac172a3
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_preferences_alerts.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Ventanas emergentes" name="popups" title="Ventanas emergentes">
+ <text name="dont_show_label">
+ No mostrar estas ventanas emergentes:
+ </text>
+ <button width="200" label="Activar esta ventana emergente" label_selected="Activar esta popup" name="enable_popup"/>
+ <button width="255" left="225" label="Activar todas las ventanas emergentes..." label_selected="Restaurar cajas de diálogo &apos;Mostrar en la próxima vez&apos;..." name="reset_dialogs_btn" tool_tip="Activar todas las ventanas emergentes y los avisos de &apos;primera vez que se usa&apos;."/>
+ <text name="show_label" width="300">
+ Mostrar estas ventanas emergentes:
+ </text>
+ <button left="205" width="275" label="Desactivar todas estas ventanas emergentes..." name="skip_dialogs_btn" tool_tip="Desactivar todas las ventanas emergentes y los avisos de &apos;primera vez que se usa&apos;."/>
+ <text name="text_box2">
+ Oferta de notas, texturas e hitos:
+ </text>
+ <check_box label="Aceptar automáticamente" name="accept_new_inventory"/>
+ <check_box label="Ver automáticamente tras aceptar" name="show_new_inventory"/>
+ <check_box label="Mostrar automáticamente los objetos aceptados recientemente en el inventario" name="show_in_inventory"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_preferences_chat.xml b/indra/newview/skins/default/xui/es/panel_preferences_chat.xml
index 0e092e58a2..4e9dc6db6f 100644
--- a/indra/newview/skins/default/xui/es/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/es/panel_preferences_chat.xml
@@ -1,57 +1,58 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Chat de texto" name="chat">
- <text length="1" name="text_box" type="string">
- Tamaño de la fuente del chat:
+ <text name="text_box">
+ Tamaño de la fuente
+del chat:
</text>
<radio_group name="chat_font_size">
- <radio_item name="radio">
- Pequeño
- </radio_item>
- <radio_item name="radio2">
- Medio
- </radio_item>
- <radio_item name="radio3">
- Grande
- </radio_item>
+ <radio_item name="radio" label="Pequeño" />
+ <radio_item name="radio2" label="Medio" />
+ <radio_item name="radio3" label="Grande" />
</radio_group>
- <text length="1" name="text_box2" type="string">
- Color del chat:
- </text>
<color_swatch label="Usted" name="user"/>
- <color_swatch label="Otros" name="agent" width="60" left_delta="48"/>
- <color_swatch label="MI" name="im" left_delta="64" width="50"/>
+ <text name="text_box1">
+ Usted
+ </text>
+ <color_swatch label="Otros" name="agent"/>
+ <text name="text_box2">
+ Otros
+ </text>
+ <color_swatch label="MI" name="im"/>
+ <text name="text_box3">
+ MI
+ </text>
<color_swatch label="Sistema" name="system"/>
- <color_swatch label="Errores" name="script_error" left_delta="48"/>
+ <text name="text_box4">
+ Sistema
+ </text>
+ <color_swatch label="Errores de script" name="script_error"/>
+ <text name="text_box5">
+ Errores de script
+ </text>
<color_swatch label="Objetos" name="objects"/>
- <color_swatch label="Propietario" name="owner" width="60" left_delta="48"/>
- <color_swatch label="Bocadillo" name="background" left_delta="64" width="50"/>
- <color_swatch label="URL" name="links" />
- <text length="1" name="text_box8" type="string">
- Errores de script:
+ <text name="text_box6">
+ Objetos
</text>
- <check_box label="Ver en el chat los avisos y errores de los scripts" name="script_errors_as_chat"/>
- <text length="1" name="text_box3" type="string">
- Consola del chat:
+ <color_swatch label="Propietario" name="owner"/>
+ <text name="text_box7">
+ Propietario
</text>
- <spinner label="Quitar el chat tras" name="fade_chat_time" label_width="95" width="145" />
- <text length="1" name="text_box4" type="string" left="297" >
- (s)
+ <color_swatch label="Bocadillo" name="background"/>
+ <text name="text_box8">
+ Bocadillo
</text>
- <text length="1" name="text_box5" type="string">
- (# líneas)
+ <color_swatch label="URL" name="links"/>
+ <text name="text_box9">
+ URL
</text>
+ <check_box label="Ver en el chat los avisos y errores de los scripts" name="script_errors_as_chat"/>
+ <spinner label="Quitar el chat tras" name="fade_chat_time" label_width="95" width="145" />
<slider label="Opacidad" name="console_opacity"/>
<check_box label="Usar el ancho de la pantalla (tras reiniciar)" name="chat_full_width_check"/>
- <text length="1" name="text_box6" type="string">
- Opciones del chat:
- </text>
<check_box label="Cerrar el chat al pulsar Intro" name="close_chat_on_return_check"/>
<check_box label="En el chat, las teclas del cursor mueven el avatar" name="arrow_keys_move_avatar_check"/>
<check_box label="Incluir la hora en el chat" name="show_timestamps_check"/>
<check_box label="Ejecutar la animación de escribir al hacerlo en el chat" name="play_typing_animation"/>
- <text length="1" name="text_box7" type="string">
- Bocadillos del chat:
- </text>
<check_box label="Mostrar el chat en bocadillos" name="bubble_text_chat"/>
<slider label="Opacidad" name="bubble_chat_opacity"/>
</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_preferences_general.xml b/indra/newview/skins/default/xui/es/panel_preferences_general.xml
index 9e5cd88603..2b813a18bf 100644
--- a/indra/newview/skins/default/xui/es/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/es/panel_preferences_general.xml
@@ -1,24 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="General" name="general_panel">
- <radio_group name="default_start_location">
- <radio_item name="MyHome" tool_tip="Por defecto, iniciar sesión en mi Base.">
- Mi Base
- </radio_item>
- <radio_item name="MyLastLocation" tool_tip="Por defecto, iniciar sesión en mi última posición.">
- Mi última posición
- </radio_item>
- </radio_group>
+ <combo_box name="start_location_combo">
+ <combo_box.item name="MyHome" tool_tip="Por defecto, iniciar sesión en mi Base." label="Mi Base"/>
+ <combo_box.item name="MyLastLocation" tool_tip="Por defecto, iniciar sesión en mi última posición." label="Mi última posición"/>
+ </combo_box>
<check_box label="Ver mi posición inicial en la pantalla de inicio de sesión" name="show_location_checkbox"/>
- <combo_box name="fade_out_combobox" width="166">
- <combo_item name="Never">
- Nunca
- </combo_item>
- <combo_item name="Show Temporarily">
- Mostrarlos temporalmente
- </combo_item>
- <combo_item name="Always">
- Siempre
- </combo_item>
+ <combo_box name="fade_out_combobox">
+ <combo_box.item name="Never" label="Nunca"/>
+ <combo_box.item name="Show Temporarily" label="Mostrarlos temporalmente"/>
+ <combo_box.item name="Always" label="Siempre"/>
</combo_box>
<check_box label="Nombres de avatar en pequeño" name="small_avatar_names_checkbox"/>
<check_box label="No ver mi nombre en mi pantalla" name="show_my_name_checkbox"/>
@@ -34,114 +24,67 @@
<check_box label="Resolución independiente del tamaño" name="ui_auto_scale"/>
<spinner label="Ausente tras:" name="afk_timeout_spinner"/>
<check_box label="Avisar cuando gasto o recibo dólares Linden (L$)" name="notify_money_change_checkbox"/>
- <text name="maturity_desired_label" bottom="-312">
+ <text name="maturity_desired_label">
Calificación:
</text>
- <text name="maturity_desired_prompt" bottom="-312">
- Quiero acceder a
-contenido calificado:
+ <text name="maturity_desired_prompt">
+ Quiero acceder a contenido calificado:
</text>
- <combo_box name="maturity_desired_combobox" bottom="-330" left="274">
- <combo_item name="Desired_Adult">
- &apos;PG&apos;, &apos;Mature&apos; y &apos;Adult&apos;
- </combo_item>
- <combo_item name="Desired_Mature">
- &apos;PG&apos; y &apos;Mature&apos;
- </combo_item>
- <combo_item name="Desired_PG">
- sólo &apos;PG&apos;
- </combo_item>
+ <combo_box name="maturity_desired_combobox">
+ <combo_box.item name="Desired_Adult" label="&apos;PG&apos;, &apos;Mature&apos; y &apos;Adult&apos;"/>
+ <combo_box.item name="Desired_Mature" label="&apos;PG&apos; y &apos;Mature&apos;"/>
+ <combo_box.item name="Desired_PG" label="&apos;PG&apos;"/>
</combo_box>
- <text name="maturity_desired_textbox" bottom="-324" left="274">
- sólo &apos;PG&apos;
+ <text name="maturity_desired_textbox">
+ &apos;PG&apos;
</text>
- <text length="1" name="start_location_textbox" type="string">
+ <text name="start_location_textbox">
Posición inicial:
</text>
- <text length="1" name="show_names_textbox" type="string">
+ <text name="show_names_textbox">
Mostrar los nombres:
</text>
- <text length="1" name="effects_color_textbox" type="string">
+ <text name="effects_color_textbox">
Color de mis efectos:
</text>
- <text length="1" name="seconds_textbox" type="string">
+ <text name="seconds_textbox">
segundos
</text>
- <text length="1" name="crash_report_textbox" type="string">
+ <text name="crash_report_textbox">
Informes de caídas:
</text>
- <text length="1" name="language_textbox" type="string">
+ <text name="language_textbox">
Idioma:
</text>
- <text left_delta="313" length="1" name="language_textbox2" type="string">
+ <text name="language_textbox2">
(Tendrá efecto tras reiniciar)
</text>
<string name="region_name_prompt">
&lt;escriba el nombre de la región&gt;
</string>
- <combo_box name="crash_behavior_combobox" width="166">
- <combo_item length="1" name="Askbeforesending" type="string">
- Preguntar antes de enviar
- </combo_item>
- <combo_item length="1" name="Alwayssend" type="string">
- Enviar siempre
- </combo_item>
- <combo_item length="1" name="Neversend" type="string">
- No enviar nunca
- </combo_item>
+ <combo_box name="crash_behavior_combobox">
+ <combo_box.item name="Askbeforesending" label="Preguntar antes de enviar"/>
+ <combo_box.item name="Alwayssend" label="Enviar siempre"/>
+ <combo_box.item name="Neversend" label="No enviar nunca"/>
</combo_box>
- <combo_box name="language_combobox" width="166">
- <combo_item name="System Default Language">
- Predeterminado del sistema
- </combo_item>
- <combo_item length="1" name="English" type="string">
- English (Inglés)
- </combo_item>
- <combo_item name="Danish">
- Dansk (Danés) - Beta
- </combo_item>
- <combo_item length="1" name="Deutsch(German)" type="string">
- Deutsch (Alemán) - Beta
- </combo_item>
- <combo_item name="Spanish" type="string">
- Español - Beta
- </combo_item>
- <combo_item length="1" name="French" type="string">
- Français (Francés) - Beta
- </combo_item>
- <combo_item name="Italian">
- Italiano - Beta
- </combo_item>
- <combo_item name="Hungarian">
- Magyar (Húngaro) - Beta
- </combo_item>
- <combo_item name="Dutch">
- Nederlands (Neerlandés) - Beta
- </combo_item>
- <combo_item name="Polish">
- Polski (Polaco) - Beta
- </combo_item>
- <combo_item name="Portugese">
- Portugués (Portugués) - Beta
- </combo_item>
- <combo_item name="Russian">
- РуÑÑкий (Ruso) - Beta
- </combo_item>
- <combo_item name="Turkish">
- Türkçe (Turco) - Beta
- </combo_item>
- <combo_item name="Ukrainian">
- УкраїнÑька (Ucraniano) - Beta
- </combo_item>
- <combo_item length="1" name="Chinese" type="string">
- 中文 (简体) (Chino) - Beta
- </combo_item>
- <combo_item length="1" name="(Japanese)" type="string">
- 日本語 (Japonés) - Beta
- </combo_item>
- <combo_item length="1" name="(Korean)" type="string">
- 한국어 (Coreano) - Beta
- </combo_item>
+ <combo_box name="language_combobox">
+ <combo_box.item name="System Default Language" label="Predeterminado del sistema"/>
+ <combo_box.item name="English" label="English (Inglés)"/>
+ <combo_box.item name="Danish" label="Dansk (Danés) - Beta"/>
+ <combo_box.item name="Deutsch(German)" label="Deutsch (Alemán) - Beta"/>
+ <combo_box.item name="Spanish" label="Español - Beta"/>
+ <combo_box.item name="French" label="Français (Francés) - Beta"/>
+ <combo_box.item name="Italian" label="Italiano - Beta"/>
+ <combo_box.item name="Hungarian" label="Magyar (Húngaro) - Beta"/>
+ <combo_box.item name="Dutch" label="Nederlands (Neerlandés) - Beta"/>
+ <combo_box.item name="Polish" label="Polski (Polaco) - Beta"/>
+ <combo_box.item name="Portugese" label="Portugués (Portugués) - Beta"/>
+ <combo_box.item name="Russian" label="РуÑÑкий (Ruso) - Beta"/>
+ <combo_box.item name="Turkish" label="Türkçe (Turco) - Beta"/>
+ <combo_box.item name="Ukrainian" label="УкраїнÑька (Ucraniano) - Beta"/>
+ <combo_box.item name="Chinese" label="中文 (简体) (Chino) - Beta"/>
+ <combo_box.item name="(Japanese)" label="日本語 (Japonés) - Beta"/>
+ <combo_box.item name="(Korean)" label="한국어 (Coreano) - Beta"/>
</combo_box>
<check_box label="Compartir el idioma con los objetos" name="language_is_public" tool_tip="Hace que los objetos con script del mundo sepan su idioma preferido."/>
</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/es/panel_preferences_graphics1.xml
index 03eb802117..4038940256 100644
--- a/indra/newview/skins/default/xui/es/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/es/panel_preferences_graphics1.xml
@@ -2,57 +2,40 @@
<panel label="Gráficos" name="Display panel">
<button label="?" name="GraphicsPreferencesHelpButton"/>
<check_box label="Abrir Second Life en una ventana" name="windowed mode"/>
- <text_editor name="FullScreenInfo">
+ <text_editor name="FullScreenInfo" width="480">
Si no está marcado, el visor se mostrará en pantalla completa cuando inicie sesión.
</text_editor>
<text name="WindowSizeLabel">
Tamaño de la ventana:
</text>
- <combo_box name="windowsize combo">
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="720x480">
- 720x480 (NTSC)
- </combo_item>
- <combo_item name="768x576">
- 768x576 (PAL)
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
+ <combo_box left="124" name="windowsize combo">
+ <combo_box.item name="640x480" label="640x480"/>
+ <combo_box.item name="800x600" label="800x600"/>
+ <combo_box.item name="720x480" label="720x480 (NTSC)"/>
+ <combo_box.item name="768x576" label="768x576 (PAL)"/>
+ <combo_box.item name="1024x768" label="1024x768"/>
</combo_box>
<text name="DisplayResLabel">
Resolución:
</text>
+ <combo_box left="124" name="fullscreen combo" />
<text name="AspectRatioLabel1" tool_tip="ancho / alto">
Proporción:
</text>
- <combo_box name="aspect_ratio" tool_tip="ancho / alto">
- <combo_item length="1" name="4:3(StandardCRT)" type="string">
- 4:3 (Standard CRT)
- </combo_item>
- <combo_item length="1" name="5:4(1280x1024LCD)" type="string">
- 5:4 (1280x1024 LCD)
- </combo_item>
- <combo_item name="8:5(Widescreen)">
- 8:5 (Widescreen)
- </combo_item>
- <combo_item length="1" name="16:9(Widescreen)" type="string">
- 16:9 (Widescreen)
- </combo_item>
+ <combo_box left="124" name="aspect_ratio" tool_tip="ancho / alto">
+ <combo_box.item name="4:3(StandardCRT)" label="4:3 (Standard CRT)"/>
+ <combo_box.item name="5:4(1280x1024LCD)" label="5:4 (1280x1024 LCD)"/>
+ <combo_box.item name="8:5(Widescreen)" label="8:5 (Widescreen)"/>
+ <combo_box.item name="16:9(Widescreen)" label="16:9 (Widescreen)"/>
</combo_box>
- <check_box label="Detectar automáticamente la proporción" name="aspect_auto_detect"/>
+ <check_box label="Detectar automáticamente &#10;la proporción" name="aspect_auto_detect" left="295" />
<text name="HigherText">
Calidad y
</text>
<text name="QualityText">
Rendimiento:
</text>
- <text name="FasterText">
+ <text name="FasterText" left="95">
El más rápido
</text>
<text name="ShadersPrefText">
@@ -67,13 +50,14 @@
<text name="ShadersPrefText4">
Ultra
</text>
- <text name="HigherText2">
+ <text name="HigherText2" left="325" >
Más alto
</text>
- <text name="QualityText2">
- Calidad
+ <text name="QualityText2" left="325" >
+ calidad
</text>
<check_box label="Personalizar" name="CustomSettings"/>
+ <panel name="CustomGraphics Panel">
<text name="ShadersText">
Shaders:
</text>
@@ -85,18 +69,10 @@
Objetos reflejados:
</text>
<radio_group name="ReflectionDetailRadio">
- <radio_item name="0">
- Terreno y árboles
- </radio_item>
- <radio_item name="1">
- Todos los objetos estáticos
- </radio_item>
- <radio_item name="2">
- Todos los avatares y objetos
- </radio_item>
- <radio_item name="3">
- Todo
- </radio_item>
+ <radio_item name="0" label="Terreno y árboles" />
+ <radio_item name="1" label="Todos los objetos estáticos" />
+ <radio_item name="2" label="Todos los avatares y objetos" />
+ <radio_item name="3" label="Todo" />
</radio_group>
<text name="AvatarRenderingText">
Renderización del avatar:
@@ -112,16 +88,16 @@
</text>
<slider label="Distancia de dibujo:" name="DrawDistance"/>
<slider label="Núm. máx. de partículas:" name="MaxParticleCount"/>
- <slider label="Calidad del procesamiento:" name="RenderPostProcess"/>
+ <slider label="Calidad del procesamiento:" name="RenderPostProcess" label_width="142"/>
<text name="MeshDetailText">
Detalle de la malla:
</text>
- <slider label="Objetos:" name="ObjectMeshDetail"/>
- <slider label="Prims flexibles:" name="FlexibleMeshDetail"/>
- <slider label="Ãrboles:" name="TreeMeshDetail"/>
- <slider label="Avatares:" name="AvatarMeshDetail"/>
- <slider label="Terreno:" name="TerrainMeshDetail"/>
- <slider label="Cielo:" name="SkyMeshDetail"/>
+ <slider label=" Objetos:" name="ObjectMeshDetail"/>
+ <slider label=" Prims flexibles:" name="FlexibleMeshDetail"/>
+ <slider label=" Ãrboles:" name="TreeMeshDetail"/>
+ <slider label=" Avatares:" name="AvatarMeshDetail"/>
+ <slider label=" Terreno:" name="TerrainMeshDetail"/>
+ <slider label=" Cielo:" name="SkyMeshDetail"/>
<text name="PostProcessText">
Baja
</text>
@@ -143,34 +119,28 @@
<text name="SkyMeshDetailText">
Bajo
</text>
- <text name="LightingDetailText">
+ <text name="LightingDetailText" width="135">
Detalles de la iluminación:
</text>
<radio_group name="LightingDetailRadio">
- <radio_item name="SunMoon">
- Sólo el Sol y la Luna
- </radio_item>
- <radio_item name="LocalLights">
- Puntos de luz cercanos
- </radio_item>
+ <radio_item name="SunMoon" label="Sólo el Sol y la Luna" />
+ <radio_item name="LocalLights" label="Puntos de luz cercanos" />
</radio_group>
<text name="TerrainDetailText">
- Nivel de detalle del terreno:
- </text>
- <radio_group name="TerrainDetailRadio">
- <radio_item name="0">
- Bajo
- </radio_item>
- <radio_item name="2">
- Alto
- </radio_item>
+ Nivel de detalle del
+ terreno:
+ </text>
+ <radio_group name="TerrainDetailRadio" left_delta="60">
+ <radio_item name="0" label="Bajo" />
+ <radio_item name="2" label="Alto" />
</radio_group>
- <button label="Configuraciones recomendadas" name="Defaults"/>
- <button label="Opciones del hardware" label_selected="Opciones del hardware" name="GraphicsHardwareButton"/>
- <string name="resolution_format">
+ </panel>
+ <button label="Configuraciones recomendadas" name="Defaults" width="195" left="110"/>
+ <button label="Opciones del hardware" label_selected="Opciones del hardware" name="GraphicsHardwareButton" left="315"/>
+ <panel.string name="resolution_format">
[RES_X] x [RES_Y]
- </string>
- <string name="aspect_ratio_text">
+ </panel.string>
+ <panel.string name="aspect_ratio_text">
[NUM]:[DEN]
- </string>
+ </panel.string>
</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/es/panel_preferences_privacy.xml
new file mode 100644
index 0000000000..cbaa3d96ee
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_preferences_privacy.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Comunicación" name="im">
+ <text name="text_box">
+ Mi estado de conexión:
+ </text>
+ <check_box label="Sólo pueden ver si estoy conectado mis amigos y grupos" name="online_visibility"/>
+ <text name="text_box2">
+ Opciones de los MI:
+ </text>
+ <string name="log_in_to_change">
+ inicie sesión para cambiar
+ </string>
+ <check_box label="Enviar MI al correo electrónico ([EMAIL])" name="send_im_to_email"/>
+ <check_box label="Incluir los MI en la consola del chat" name="include_im_in_chat_console"/>
+ <check_box label="Incluir la hora en los MI" name="show_timestamps_check"/>
+ <check_box label="Avisar si se conecta un amigo" name="friends_online_notify_checkbox"/>
+ <text name="text_box3">
+ Mensaje en el estado
+ocupado:
+ </text>
+ <text name="text_box4">
+ Opciones de los
+registros:
+ </text>
+ <check_box label="Guardar un registro de los MI en mi ordenador" name="log_instant_messages"/>
+ <check_box label="Incluir la hora en el registro de los MI" name="log_instant_messages_timestamp"/>
+ <check_box label="Mostrar el final de la última conversación por MI" name="log_show_history"/>
+ <check_box label="Guardar un registro del chat en mi ordenador" name="log_chat"/>
+ <check_box label="Incluir la hora en el registro del chat" name="log_chat_timestamp"/>
+ <check_box label="Mostrar en el chat la llegada de los MI" name="log_chat_IM"/>
+ <check_box label="Incluir la fecha junto a la hora" name="log_date_timestamp"/>
+ <button label="Cambiar la ruta" label_selected="Cambiar la ruta" name="log_path_button" width="120"/>
+ <line_editor left="278" name="log_path_string" right="-20"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_preferences_setup.xml b/indra/newview/skins/default/xui/es/panel_preferences_setup.xml
new file mode 100644
index 0000000000..967626b8d5
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_preferences_setup.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Dispositivos y Cámara" name="Input panel">
+ <text name=" Mouselook Options:">
+ Vista subjetiva:
+ </text>
+ <text name=" Mouse Sensitivity:">
+ Sensibilidad del ratón:
+ </text>
+ <check_box label="Invertir el ratón" name="invert_mouse"/>
+ <text name=" Auto Fly Options:">
+ Vuelo:
+ </text>
+ <check_box label="Despegar/Aterrizar pulsando RePág/AvPág" name="automatic_fly"/>
+ <text name=" Camera Options:">
+ Opciones de la cámara:
+ </text>
+ <text name="camera_fov_label" width="218">
+ Ãngulo de vista de la cámara:
+ </text>
+ <slider bottom_delta="-6" width="128" left="326" name="camera_fov" />
+ <text name="Camera Follow Distance:" width="218">
+ Distancia a la que sigue la cámara:
+ </text>
+ <slider bottom_delta="-6" width="128" left="326" name="camera_offset_scale" />
+ <check_box label="Reorientar la cámara al editar" name="edit_camera_movement" tool_tip="Usar la reorientación automática de la cámara al entrar y salir del modo de edición"/>
+ <check_box label="Reorientar la cámara al modificar la apariencia" name="appearance_camera_movement" tool_tip="Usar la reorientación automática de la cámara mientras se modifica la apariencia"/>
+ <text name="text2">
+ Visualización del avatar:
+ </text>
+ <check_box label="Ver el avatar en vista subjetiva" name="first_person_avatar_visible"/>
+ <button bottom_delta="-40" label="Configurar el joystick" name="joystick_setup_button"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_preferences_sound.xml b/indra/newview/skins/default/xui/es/panel_preferences_sound.xml
new file mode 100644
index 0000000000..241f3042fe
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_preferences_sound.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Audio y Vídeo" name="Preference Media panel">
+ <slider label="General" name="System Volume"/>
+ <slider label="Ambiental" name="Wind Volume"/>
+ <slider label="Sonidos" name="SFX Volume"/>
+ <slider label="Media" name="Media Volume"/>
+ <slider label="Interfaz" name="UI Volume"/>
+ <slider label="Música" name="Music Volume"/>
+ <slider label="Voz" name="Voice Volume"/>
+ <text_editor name="voice_unavailable">
+ El chat de voz no está disponible
+ </text_editor>
+ <check_box label="Activar el chat de voz" name="enable_voice_check"/>
+ <radio_group name="ear_location">
+ <radio_item name="0" label="Oír el chat desde la posición de la cámara." />
+ <radio_item name="1" label="Oír el chat desde la posición del avatar." />
+ </radio_group>
+ <button label="Configuración de los dispositivos" name="device_settings_btn" width="210" />
+ <text name="muting_text">
+ Volumen:
+ </text>
+ <text name="streaming_prefs_text">
+ Preferencias multimedia:
+ </text>
+ <text name="audio_prefs_text">
+ Preferencias de sonido:
+ </text>
+ <panel label="Volumen" name="Volume Panel"/>
+ <check_box label="Si hay música, reproducirla en streaming" name="streaming_music"/>
+ <check_box label="Si hay media, reproducirlos en streaming" name="streaming_video"/>
+ <check_box label="Reproducir automáticamente los media" name="auto_streaming_video"/>
+ <check_box label="Silenciar el sonido al minimizar la ventana" name="mute_when_minimized"/>
+ <slider label="Efecto Doppler" name="Doppler Effect" label_width="140" width="270" />
+ <slider label="Distancia de escucha" name="Distance Factor" label_width="140" width="270" />
+ <slider label="Nivel de atenuación" name="Rolloff Factor" label_width="140" width="270" />
+ <spinner label="Avisar de transacción de L$ desde" name="L$ Change Threshold" label_width="195" width="259"/>
+ <spinner label="Avisar del estado de la vida desde" name="Health Change Threshold" label_width="195" width="259"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_profile.xml b/indra/newview/skins/default/xui/es/panel_profile.xml
new file mode 100644
index 0000000000..218e03dcce
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_profile.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_profile">
+ <string name="CaptionTextAcctInfo">
+ [ACCTTYPE]
+[PAYMENTINFO] [AGEVERIFICATION]
+ </string>
+ <string name="payment_update_link_url">
+ http://www.secondlife.com/account/billing.php?lang=es-ES
+ </string>
+ <string name="partner_edit_link_url">
+ http://www.secondlife.com/account/partners.php?lang=es
+ </string>
+ <string name="my_account_link_url" value="http://secondlife.com/my/account/index.php?lang=es-ES"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_region_covenant.xml b/indra/newview/skins/default/xui/es/panel_region_covenant.xml
index 3f9e782bd7..220479098b 100644
--- a/indra/newview/skins/default/xui/es/panel_region_covenant.xml
+++ b/indra/newview/skins/default/xui/es/panel_region_covenant.xml
@@ -22,14 +22,15 @@
Última modificación el miér. 31 de dic. de 1969, 16:00:00
</text>
<button label="?" name="covenant_help"/>
- <text_editor name="covenant_editor">
+ <text_editor name="covenant_editor" bottom="-263" height="178" >
No se ha aportado un contrato para este estado.
</text_editor>
<button label="Cambiar" name="reset_covenant"/>
<text name="covenant_help_text">
- Los cambios en el contrato se mostrarán en todas las parcelas del estado.
+ Los cambios en el contrato se mostrarán en todas las parcelas
+ del estado.
</text>
- <text name="covenant_instructions">
+ <text name="covenant_instructions" bottom_delta="-31" >
Para cambiar el contrato de este estado, arrastre y suelte una nota.
</text>
<text name="region_section_lbl">
@@ -75,6 +76,7 @@
El terreno comprado en esta región se podrá unir o subdividir.
</string>
<string name="can_not_change">
- El terreno comprado en esta región no se podrá unir ni subdividir.
+ El terreno comprado en esta región no se podrá unir ni
+subdividir.
</string>
</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_region_debug.xml b/indra/newview/skins/default/xui/es/panel_region_debug.xml
index a722235243..a7999cc54d 100644
--- a/indra/newview/skins/default/xui/es/panel_region_debug.xml
+++ b/indra/newview/skins/default/xui/es/panel_region_debug.xml
@@ -7,13 +7,13 @@
desconocida
</text>
<check_box label="Desactivar los scripts" name="disable_scripts_check" tool_tip="Descativar todos los scripts en esta región"/>
- <button label="?" name="disable_scripts_help"/>
+ <button label="?" name="disable_scripts_help" left="215"/>
<check_box label="Desactivar las colisiones" name="disable_collisions_check" tool_tip="Desactiva las colisiones (no las de avatares) en esta región"/>
- <button label="?" name="disable_collisions_help"/>
+ <button label="?" name="disable_collisions_help" left="215"/>
<check_box label="Desactivar las propiedades físicas" name="disable_physics_check" tool_tip="Desactiva toda la física en esta región"/>
- <button label="?" name="disable_physics_help"/>
+ <button label="?" name="disable_physics_help" left="215"/>
<button label="Aplicar" name="apply_btn"/>
- <text name="objret_text_lbl">
+ <text name="objret_text_lbl" width="130">
Devolver el objeto
</text>
<text name="resident_text_lbl">
@@ -30,10 +30,10 @@
<check_box label="Devolver sólo los objetos que están en terreno de otro" name="return_other_land" tool_tip="Devolver sólo los objetos que están en terreno de otro"/>
<check_box label="Devolver los objetos de cualquier región de este estado" name="return_estate_wide" tool_tip="Devolver los objetos de todas las regiones que forman este estado"/>
<button label="Devolver" name="return_btn"/>
- <button label="Listar los objetos que colisionan..." name="top_colliders_btn" tool_tip="Lista de los objetos con más posibles colisiones potenciales"/>
- <button label="?" name="top_colliders_help"/>
- <button label="Listar los scripts según su uso..." name="top_scripts_btn" tool_tip="Lista de los objetos que más tiempo emplean ejecutando scripts"/>
- <button label="?" name="top_scripts_help"/>
+ <button width="280" label="Listar los objetos que colisionan..." name="top_colliders_btn" tool_tip="Lista de los objetos con más posibles colisiones potenciales"/>
+ <button label="?" name="top_colliders_help" left="297"/>
+ <button width="280" label="Listar los scripts según su uso..." name="top_scripts_btn" tool_tip="Lista de los objetos que más tiempo emplean ejecutando scripts"/>
+ <button label="?" name="top_scripts_help" left="297"/>
<button label="Reiniciar la región" name="restart_btn" tool_tip="Cuenta atrás de 2 minutos y reiniciar la región"/>
<button label="?" name="restart_help"/>
<button label="Retrasar el reinicio" name="cancel_restart_btn" tool_tip="Retrasar una hora el reinicio de la región"/>
diff --git a/indra/newview/skins/default/xui/es/panel_region_estate.xml b/indra/newview/skins/default/xui/es/panel_region_estate.xml
index 93155d828d..f16ec89cb0 100644
--- a/indra/newview/skins/default/xui/es/panel_region_estate.xml
+++ b/indra/newview/skins/default/xui/es/panel_region_estate.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Estado" name="Estate">
<text name="estate_help_text">
- Los cambios en las configuraciones de esta pestaña afectarán a todas
-las regiones de este estado.
+ Los cambios en las configuraciones de esta
+pestaña afectarán a todas las regiones del estado.
</text>
<text name="estate_text">
Estado:
@@ -24,16 +24,16 @@ las regiones de este estado.
<check_box label="Permitir el acceso público" name="externally_visible_check"/>
<button label="?" name="externally_visible_help"/>
<text name="Only Allow">
- Impedir el acceso a:
+ Impedir el acceso a Residentes...
</text>
- <check_box label="Residentes sin información de pago archivada" name="limit_payment" tool_tip="Impedir el acceso a los residentes no identificados."/>
- <check_box label="Residentes de los que no se ha verificado si son adultos" name="limit_age_verified" tool_tip="Impedir el acceso a residentes que no hayan verificado su edad. Para más información, vea support.secondlife.com"/>
+ <check_box label="sin información de pago archivada" name="limit_payment" tool_tip="Impedir el acceso a los residentes no identificados."/>
+ <check_box label="que no han verificado si son adultos" name="limit_age_verified" tool_tip="Impedir el acceso a residentes que no hayan verificado su edad. Para más información, vea support.secondlife.com"/>
<check_box label="Permitir el chat de voz" name="voice_chat_check"/>
<button label="?" name="voice_chat_help"/>
<check_box label="Permitir el teleporte a cualquier punto" name="allow_direct_teleport"/>
<button label="?" name="allow_direct_teleport_help"/>
- <text name="abuse_email_text">
- Dirección de correo electrónico para infracciones:
+ <text name="abuse_email_text" width="260">
+ Dirección de correo-e para infracciones:
</text>
<string name="email_unsupported">
Característica no disponible
@@ -63,7 +63,7 @@ las regiones de este estado.
<text name="ban_resident_label">
Residentes con el acceso prohibido:
</text>
- <button label="?" name="ban_resident_help"/>
+ <button label="?" name="ban_resident_help" right="476"/>
<button label="Quitar..." name="remove_banned_avatar_btn"/>
<button label="Añadir..." name="add_banned_avatar_btn"/>
</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_region_general.xml b/indra/newview/skins/default/xui/es/panel_region_general.xml
index 64169e427b..ca8da6ccaf 100644
--- a/indra/newview/skins/default/xui/es/panel_region_general.xml
+++ b/indra/newview/skins/default/xui/es/panel_region_general.xml
@@ -30,30 +30,24 @@
<button label="?" name="land_resell_help"/>
<check_box label="Permitir unir/dividir el terreno" name="allow_parcel_changes_check"/>
<button label="?" name="parcel_changes_help"/>
- <check_box label="Bloquear el mostrar el terreno en la búsqueda." name="block_parcel_search_check" tool_tip="Permitir que la gente vea esta región y sus parcelas en los resultados de la búsqueda."/>
+ <check_box label="Bloquear el mostrar el terreno en &#10;la búsqueda." name="block_parcel_search_check" tool_tip="Permitir que la gente vea esta región y sus parcelas en los resultados de la búsqueda."/>
<button label="?" name="parcel_search_help"/>
- <spinner label="Nº máximo de avatares" name="agent_limit_spin"/>
+ <spinner label="Nº máximo de avatares" name="agent_limit_spin" label_width="120" width="180"/>
<button label="?" name="agent_limit_help"/>
- <spinner label="Plus de objetos" name="object_bonus_spin"/>
+ <spinner label="Plus de objetos" name="object_bonus_spin" label_width="120" width="180"/>
<button label="?" name="object_bonus_help"/>
<text label="Calificación" name="access_text">
Calificación:
</text>
<combo_box label="&apos;Mature&apos;" name="access_combo">
- <combo_item name="Adult">
- &apos;Adult&apos;
- </combo_item>
- <combo_item name="Mature">
- &apos;Mature&apos;
- </combo_item>
- <combo_item name="PG">
- &apos;PG&apos;
- </combo_item>
+ <combo_box.item label="&apos;Adult&apos;" name="Adult"/>
+ <combo_box.item label="&apos;Mature&apos;" name="Mature"/>
+ <combo_box.item label="&apos;PG&apos;" name="PG"/>
</combo_box>
<button label="?" name="access_help"/>
<button label="Aplicar" name="apply_btn"/>
<button label="Teleportar a su Base a un usuario..." name="kick_btn"/>
<button label="Teleportar a su Base a todos los usuarios..." name="kick_all_btn"/>
- <button label="Enviar un mensaje a toda la región..." name="im_btn"/>
- <button label="Administrar el Punto de Teleporte..." name="manage_telehub_btn"/>
+ <button label="Enviar un mensaje a toda la región..." name="im_btn" width="250" />
+ <button label="Administrar el Punto de Teleporte..." name="manage_telehub_btn" width="210"/>
</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 df333c0c5e..903b826a0b 100644
--- a/indra/newview/skins/default/xui/es/panel_region_terrain.xml
+++ b/indra/newview/skins/default/xui/es/panel_region_terrain.xml
@@ -8,9 +8,9 @@
</text>
<spinner label="Nivel del agua" name="water_height_spin"/>
<button label="?" name="water_height_help"/>
- <spinner label="Límite de elevación del terreno" name="terrain_raise_spin"/>
+ <spinner label="Límite de elevación del &#10;terreno" name="terrain_raise_spin"/>
<button label="?" name="terrain_raise_help"/>
- <spinner label="Límite de bajada del terreno" name="terrain_lower_spin"/>
+ <spinner label="Límite de bajada del &#10;terreno" name="terrain_lower_spin" bottom_delta="-34"/>
<button label="?" name="terrain_lower_help"/>
<check_box label="Usar el Sol del estado" name="use_estate_sun_check"/>
<button label="?" name="use_estate_sun_help"/>
@@ -18,10 +18,10 @@
<button label="?" name="fixed_sun_help"/>
<slider label="Fase" name="sun_hour_slider"/>
<button label="Aplicar" name="apply_btn"/>
- <button label="Descargar el RAW del terreno..." name="download_raw_btn" tool_tip="Disponible sólo para los propietarios del estado, no para los administradores"/>
- <button label="?" name="download_raw_help"/>
- <button label="Subir un RAW para el terreno..." name="upload_raw_btn" tool_tip="Disponible sólo para los propietarios del estado, no para los administradores"/>
- <button label="?" name="upload_raw_help"/>
- <button label="Predeterminar este terreno" name="bake_terrain_btn" tool_tip="Definir el terreno actual como punto medio para los límites de elevación/bajada"/>
- <button label="?" name="bake_terrain_help"/>
+ <button width="230" label="Descargar el RAW del terreno..." name="download_raw_btn" tool_tip="Disponible sólo para los propietarios del estado, no para los administradores"/>
+ <button left="246" label="?" name="download_raw_help"/>
+ <button width="230" label="Subir un RAW para el terreno..." name="upload_raw_btn" tool_tip="Disponible sólo para los propietarios del estado, no para los administradores"/>
+ <button left="246" label="?" name="upload_raw_help"/>
+ <button width="230" label="Predeterminar este terreno" name="bake_terrain_btn" tool_tip="Definir el terreno actual como punto medio para los límites de elevación/bajada"/>
+ <button left="246" label="?" name="bake_terrain_help"/>
</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_region_texture.xml b/indra/newview/skins/default/xui/es/panel_region_texture.xml
index d7f42ac41c..5540358f97 100644
--- a/indra/newview/skins/default/xui/es/panel_region_texture.xml
+++ b/indra/newview/skins/default/xui/es/panel_region_texture.xml
@@ -6,7 +6,7 @@
<text name="region_text">
desconocida
</text>
- <text name="detail_texture_text">
+ <text name="detail_texture_text" width="380">
Texturas del terreno (se requieren archivos .tga de 512x512 y 24 bites)
</text>
<text name="height_text_lbl">
diff --git a/indra/newview/skins/default/xui/es/panel_scrolling_param.xml b/indra/newview/skins/default/xui/es/panel_scrolling_param.xml
index f6feab274f..bafd4e5e55 100644
--- a/indra/newview/skins/default/xui/es/panel_scrolling_param.xml
+++ b/indra/newview/skins/default/xui/es/panel_scrolling_param.xml
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="LLScrollingPanelParam">
- <text length="1" name="Loading..." type="string">
+ <text name="Loading...">
Cargando...
</text>
- <text length="1" name="Loading...2" type="string">
+ <text name="Loading...2">
Cargando...
</text>
<slider label="[DESC]" name="param slider"/>
diff --git a/indra/newview/skins/default/xui/es/panel_status_bar.xml b/indra/newview/skins/default/xui/es/panel_status_bar.xml
index add7db2f9a..31cde7d237 100644
--- a/indra/newview/skins/default/xui/es/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/es/panel_status_bar.xml
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="status">
- <text length="1" name="ParcelNameText" tool_tip="Nombre de la parcela en la que está. Pulse Acerca del terreno." type="string">
+ <text name="ParcelNameText" tool_tip="Nombre de la parcela en la que está. Pulse Acerca del terreno.">
el nombre de la parcela va aquí
</text>
- <text length="1" name="BalanceText" tool_tip="Saldo de su cuenta" type="string">
+ <text name="BalanceText" tool_tip="Saldo de su cuenta">
Cargando...
</text>
<button label="" label_selected="" name="buycurrency" tool_tip="Comprar dinero"/>
- <text length="12" name="TimeText" tool_tip="Hora actual (costa oeste EE.UU.)" type="string">
+ <text name="TimeText" tool_tip="Hora actual (costa oeste EE.UU.)">
12:00 AM
</text>
<string name="StatBarDaysOfWeek">
@@ -18,7 +18,7 @@
</string>
<button label="" label_selected="" name="scriptout" tool_tip="Errores y alertas de los scripts"/>
<button label="" label_selected="" name="health" tool_tip="Vida"/>
- <text length="1" name="HealthText" tool_tip="Vida" type="string">
+ <text name="HealthText" tool_tip="Vida">
100%
</text>
<button label="" label_selected="" name="no_fly" tool_tip="Prohibido volar"/>
@@ -27,8 +27,8 @@
<button label="" label_selected="" name="restrictpush" tool_tip="Sin &apos;empujones&apos;"/>
<button label="" label_selected="" name="status_no_voice" tool_tip="Aquí no está disponible la voz"/>
<button label="" label_selected="" name="buyland" tool_tip="Comprar esta parcela"/>
- <line_editor label="Buscar" name="search_editor" tool_tip="Buscar en Second Life"/>
- <button label="" label_selected="" name="search_btn" tool_tip="Buscar en Second Life"/>
+ <line_editor label="Buscar" name="search_editor" tool_tip="Buscar en [SECOND_LIFE]"/>
+ <button label="" label_selected="" name="search_btn" tool_tip="Buscar en [SECOND_LIFE]"/>
<string name="packet_loss_tooltip">
Pérdida de paquetes
</string>
diff --git a/indra/newview/skins/default/xui/es/panel_world_map.xml b/indra/newview/skins/default/xui/es/panel_world_map.xml
new file mode 100644
index 0000000000..7cb4009422
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_world_map.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="world_map">
+ <panel.string name="world_map_north">
+ N
+ </panel.string>
+ <panel.string name="world_map_east">
+ E
+ </panel.string>
+ <panel.string name="world_map_west">
+ O
+ </panel.string>
+ <panel.string name="world_map_south">
+ S
+ </panel.string>
+ <panel.string name="world_map_southeast">
+ SE
+ </panel.string>
+ <panel.string name="world_map_northeast">
+ NE
+ </panel.string>
+ <panel.string name="world_map_southwest">
+ SO
+ </panel.string>
+ <panel.string name="world_map_northwest">
+ NO
+ </panel.string>
+ <text label="N" name="floater_map_north" text="N">
+ N
+ </text>
+ <text label="E" name="floater_map_east" text="E">
+ E
+ </text>
+ <text label="O" name="floater_map_west" text="O">
+ O
+ </text>
+ <text label="S" name="floater_map_south" text="S">
+ S
+ </text>
+ <text label="SE" name="floater_map_southeast" text="SE">
+ SE
+ </text>
+ <text label="NE" name="floater_map_northeast" text="NE">
+ NE
+ </text>
+ <text label="SO" name="floater_map_southwest" text="SO">
+ SO
+ </text>
+ <text label="NW" name="floater_map_northwest" text="NO">
+ NO
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/es/role_actions.xml b/indra/newview/skins/default/xui/es/role_actions.xml
index 1e10ccf992..da9a820eb8 100644
--- a/indra/newview/skins/default/xui/es/role_actions.xml
+++ b/indra/newview/skins/default/xui/es/role_actions.xml
@@ -1,186 +1,199 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<role_actions>
<action_set
- description="Estas habilidades incluyen poderes de adicionar o remover miembros del grupo y permitir que nuevos miembros se junten sin una invitación."
+ description="Estas capacidades incluyen poderes para añadir o quitar miembros del grupo, y para pemitir que se sumen nuevos miembros sin necesidad de invitación."
name="Membership">
- <action description="Invitar personas para este grupo"
- longdescription="Invite personas para este grupo usando el botón &apos;Invitar nueva persona...&apos; en Miembros &amp; pestaña Funciones &gt; subpestaña Miembros."
+ <action description="Invitar personas al grupo"
+ longdescription="Invitar a personas al grupo usando el botón &apos;Invitar a un nuevo miembro&apos; en Miembros y Roles &gt; subpestaña Miembros."
name="member invite" value="1" />
- <action description="Expulsar a miembros de este grupo"
- longdescription="Expulse a miembros de este grupo usando el botón &apos;Expulsar del grupo&apos; en Miembros &amp; pestaña Funciones &gt; subpestaña Miembros. Un propietario puede expulsar a cualquiera, excepto a otro propietario. Si usted no es un propietario, un miembro puede a expulsarlo del grupo si, y solamente si, él apenas tiene la función de todos y no otras funciones. Para remover miembros de funciones, necesita tener la habilidad &apos;Remover miembros de funciones&apos;."
+ <action description="Expulsar a miembros del grupo"
+ longdescription="Expulsar a miembros del grupo usando el botón &apos;Expulsar del grupo&apos; en Miembros y Roles &gt; subpestaña Miembros. Un propietario puede expulsar a cualquiera, excepto a otro propietario. Si usted no es un propietario, un miembro del grupo puede expulsarle sólo si tiene concedida tal capacidad específica. Para quitar capacidades a los miembros, usted debe tener la de &apos;Quitar capacidades a miembros&apos;."
name="member eject" value="2" />
<action
- description="Activar/desactivar &apos;Abrir registro&apos; y cambiar &apos;Tasa de suscripción&apos;"
- longdescription="Active/desactive &apos;Abrir registro&apos; para permitir que nuevos miembros se unan sin una invitación, y cambie &apos;Tasa de registro&apos; en la sección Preferencia de grupo de la pestaña General."
+ description="Activar/desactivar &apos;Inscripción libre&apos; y cambiar &apos;Cuota de inscripción&apos;"
+ longdescription="Activar/desactivar &apos;Inscripción libre&apos; para permitir o no que se unan sin invitación nuevos miembros, y cambiar la &apos;Cuota de inscripción&apos; en la sección Preferencias del grupo de la pestaña General."
name="member options" value="3" />
</action_set>
<action_set
- description="Estas habilidades incluyen poderes de adicionar, remover y cambiar funciones del grupo; adicionar y remover miembros en funciones y designar habilidades a funciones."
+ description="Estas habilidades incluyen el poder añadir, quitar y cambiar roles, asignarlos a miembros, y darles capacidades."
name="Roles">
- <action description="Crear nuevas funciones"
- longdescription="Cree nuevas funciones en Miembros &amp; pestaña Funciones &gt; subpestaña Funciones."
+ <action description="Crear nuevos roles"
+ longdescription="Crear nuevos roles en Miembros y Roles &gt; pestaña Roles &gt; botón Crear un rol nuevo."
name="role create" value="4" />
- <action description="Borrar funciones"
- longdescription="Borra funciones en Miembros &amp; pestaña Funciones &gt; subpestaña Funciones."
+ <action description="Borrar roles"
+ longdescription="Borrar roles en Miembros y Roles &gt; pestaña Roles &gt; botón Eliminar el rol."
name="role delete" value="5" />
- <action description="Cambiar nombres de funciones, títulos y descripciones"
- longdescription="Cambie el nombre de funciones, títulos y descripciones en la parte inferior de Miembros &amp; pestaña Funciones &gt; subpestaña Funciones después de seleccionar una función."
+ <action description="Cambiar nombres de roles, títulos y descripciones"
+ longdescription="Cambiar el nombre del rol que elija, su etiqueta y descripción en la parte media de la pestaña Miembros y Roles."
name="role properties" value="6" />
- <action description="Designar miembros para la función&apos;s del asignador"
- longdescription="Designe miembros para funciones en la sección de funciones designadas de Miembros &amp; pestaña Funciones &gt; subpestaña Miembros. Un miembro con este poder puede solamente adicionar miembros para la función que el asignador ya posee."
+ <action description="Designar miembros para el rol del asignador"
+ longdescription="Designar miembros para un rol en la sección Roles asignados de la pestaña Miembros y Roles &gt; subpestaña Miembros. Un miembro con este poder sólo puede asignar a otros el rol que él posee."
name="role assign member limited" value="7" />
- <action description="Designar miembros para cualquier función"
- longdescription="Designe miembros para cualquier función en la sección de funciones designadas de Miembros &amp; pestaña Funciones &gt; subpestaña Miembros. *AVISO* Cualesquiera miembros en una función con esta habilidad pueden designar a sí propios--y cualesquiera otros miembros no propietarios--para funciones que tienen más poderes que las actuales, promocionándolos a poderes próximos al del propietario. Asegúrese de saber lo que está haciendo antes de designar esta habilidad."
+ <action description="Designar miembros para cualquier rol"
+ longdescription="Designar miembros para cualquier rol en la sección Roles asignados de la pestaña Miembros y Roles &gt; subpestaña Miembros. *AVISO* Todos los miembros con esta capacidad podrán asignarse a sí mismos -y a otros miembros- roles con mayores poderes de los que actualmente tienen. Potencialmente, podrían elevarse hasta poderes cercanos a los del propietario. Asegúrese de lo que está haciendo antes de otorgar esta capacidad."
name="role assign member" value="8" />
- <action description="Remover miembros de las funciones"
- longdescription="Remueva miembros de funciones en la sección de funciones designadas de Miembros &amp; pestaña Funciones &gt; subpestaña Miembros. Propietarios no pueden&apos; ser removidos."
+ <action description="Quitar capacidades a los miembros"
+ longdescription="Quitar capacidades a los miembros en la sección Capacidades asignadas de Miembros y Roles &gt; subpestaña Roles. No se pueden quitar a los Propietarios."
name="role remove member" value="9" />
- <action description="Determinar y remover habilidades en función"
- longdescription="Designe y remueva habilidades en funciones en la sección habilidades permitidas de Miembros &amp; pestaña Funciones &gt; subpestaña Funciones. *AVISO* Cualesquiera miembros en una función con esta habilidad pueden designar a sí propios--y cualesquiera otros miembros no propietarios--todas las habilidades, promocionándolos a poderes próximos al del propietario. Asegúrese de saber lo que está haciendo antes de designar esta habilidad."
+ <action description="Añadir o quitar capacidades a los roles"
+ longdescription="Añadir o quitar capacidades a los roles en la sección Capacidades asignadas de Miembros y Roles &gt; subpestaña Roles. *AVISO* Todos los miembros con esta capacidad podrán asignarse a sí mismos -y a otros miembros- roles con mayores poderes de los que actualmente tienen. Potencialmente, podrían elevarse hasta poderes cercanos a los del propietario. Asegúrese de lo que está haciendo antes de otorgar esta capacidad."
name="role change actions" value="10" />
</action_set>
<action_set
- description="Estas habilidades incluyen poderes para modificar esta identidad de grupo, como cambiar la visibilidad pública, presentación y insignia."
+ description="Estas capacidades incluyen poderes para modificar la identidad del grupo, como su visibilidad pública, su carta o su emblema."
name="Group Identity">
<action
- description="Cambiar presentación, insignia, &apos;Publicar en la web&apos;, y cuales miembros están públicamente visibles en Informaciones del Grupo."
- longdescription="Cambie la presentación, insignia, &apos;Publicar en la web&apos; y cuales miembros están públicamente visibles en Informaciones del grupo. Es hecho en la pestaña General."
+ description="Cambiar la carta, emblema, &apos;Mostrar en la búsqueda&apos;, y qué miembros serán visibles en la información del grupo"
+ longdescription="Cambiar la carta, emblema, &apos;Mostrar en la búsqueda&apos;, y qué miembros serán visibles en la información del grupo de la pestaña General."
name="group change identity" value="11" />
</action_set>
<action_set
- description="Estas habilidades incluyen poderes para transferir, modificar y vender terrenos del grupo. Vaya para la ventana Sobre el terreno, haga clic con el botón derecho en el terreno y seleccione &apos;Sobre el terreno...&apos; o haga clic en la información de la parcela en la barra del menú."
+ description="Estas capacidades incluyen poderes para transferir, modificar y vender terrenos del grupo. Vea el menú Mundo &gt; Acerca del terreno, o pulse con el botón derecho en el terreno y seleccione &apos;Acerca del terreno...&apos;, o pulse en la información de la parcela en la barra superior del menú."
name="Parcel Management">
<action description="Transferir y comprar terreno para el grupo"
- longdescription="Transfiere y compre terreno para el grupo. Es hecho en Sobre el terreno &gt; pestaña General."
+ longdescription="Transferir y comprar terreno para el grupo. Se hace en Acerca del terreno &gt; pestaña General."
name="land deed" value="12" />
- <action description="Abandonar al terreno para Gobernador Linden"
- longdescription="Abandone al terreno para Gobernador Linden. *AVISO* Cualquier miembro en una función con esta habilidad puede abandonar al terreno perteneciente al grupo en Sobre el terreno &gt; pestaña General, revirtiendo a la posesión Linden sin una venta! Asegúrese de saber lo que está haciendo antes de designar esta habilidad."
+ <action description="Abandonar al terreno a favor de Governor Linden"
+ longdescription="Abandonar al terreno a favor de Governor Linden. *AVISO* Todos los miembros con esta capacidad pueden abandonar terreno perteneciente al grupo en Acerca del terreno &gt; pestaña General, devolviendo la posesión a Linden ¡gratuitamente! Asegúrese de lo que está haciendo antes de otorgar esta capacidad."
name="land release" value="13" />
- <action description="Definir terreno para información de venta"
- longdescription="Defina informaciones de venta para terreno. *AVISO* Cualquier miembro en una función con esta habilidad puede vender terrenos pertenecientes al grupo en Sobre el terreno &gt; pestaña General ¡cómo quiera! Asegúrese de saber lo que está haciendo antes de designar esta habilidad."
+ <action description="Vender terreno"
+ longdescription="Vender terreno. *AVISO* Todos los miembros con esta capacidad pueden vender terreno perteneciente al grupo -¡en la forma en que quieran!- en Acerca del terreno &gt; pestaña General. Asegúrese de lo que está haciendo antes de otorgar esta capacidad."
name="land set sale info" value="14" />
- <action description="Subdividir y unir parcelas"
- longdescription="Subdivide and join parcels. This is done by right-clicking the ground, &apos;Edit Terrain&apos;, and dragging your mouse on the land to make a selection. To subdivide, select what you want to split and click &apos;Subdivide...&apos;. To join, select two or more contiguous parcels and click &apos;Join...&apos;. "
+ <action description="Dividir y unir parcelas"
+ longdescription="Dividir y unir parcelas. Se hace pulsando con el botón derecho en el terreno, &apos;Modificar el terreno&apos;, y dibujando en el terreno con el ratón lo que se quiere seleccionar. Para dividir, elija la parte que quiere separar y pulse &apos;Subdividir...&apos;. Para unir, seleccione dos o más parcelas contiguas y pulse &apos;Unir...&apos;. "
name="land divide join" value="15" />
</action_set>
<action_set
- description="Estas habilidades incluyen poderes para cambiar el nombre de las parcelas y configuraciones de publicación, visibilidad de la búsqueda de directorio y punto de aterrizaje &amp; opciones de ruta de TP."
+ description="Estas capacidades incluyen poder cambiar el nombre de la parcela y su configuración, así como si se muestra en Buscar y las opciones del punto de llegada y el de teleporte."
name="Parcel Identity">
<action
- description="Activar/desactivar &apos;Exhibir en locales de encuentro&apos; y definir categoría"
- longdescription="Activar/desactivar &apos;Exhibir en locales de encuentro&apos; y configurar una categoría de parcela en Sobre el terreno &gt; pestaña Opciones."
+ description="Activar/desactivar &apos;Mostrar en Buscar&apos; y el definir la categoría"
+ longdescription="Activar/desactivar el &apos;Mostrar en Buscar&apos; y en que categoría se mostrará en Acerca del terreno &gt; pestaña Opciones."
name="land find places" value="17" />
<action
- description="Cambiar nombre de la parcela, descripción, y configuraciones &apos;Publicar en la web&apos;"
- longdescription="Cambie el nombre de la parcela, descripción y configuraciones de &apos;Publicar en la web&apos;. Es hecho en Sobre el terreno &gt; pestaña Opciones."
+ description="Cambiar el nombre de la parcela, la descripción, y la configuración de &apos;Mostrar en Buscar&apos;"
+ longdescription="Cambiar el nombre y descripción de la parcela, y la configuración de &apos;Mostrar en Buscar&apos;. Se hace en Acerca del terreno &gt; pestaña Opciones."
name="land change identity" value="18" />
- <action description="Definir punto de aterrizaje y ruta de teletransporte"
- longdescription="En una parcela perteneciente al grupo, miembros en una función con esta habilidad pueden definir un punto de aterrizaje para especificar donde los teletransportes llegan y también definir la ruta del teletransporte para un mayor control. Es hecho en Sobre el terreno &gt; pestaña Opciones."
+ <action description="Definir los puntos de llegada y teleporte"
+ longdescription="En una parcela perteneciente al grupo, los miembros con un rol que tenga esta capacidad pueden precisar el punto de llegada o el de teleporte. Se hace en Acerca del terreno &gt; pestaña Opciones."
name="land set landing point" value="19" />
</action_set>
<action_set
- description="Estas habilidades incluyen poderes que afectan opciones de parcela, como &apos;Crear objetos&apos;, &apos;Editar terreno&apos; y música &amp; configuraciones de multimedia."
+ description="Estas capacidades incluyen poderes que afectan a las opciones de la parcela, como &apos;Crear objetos&apos;, &apos;Editar el terreno&apos; y las configuraciones de la música y los media."
name="Parcel Settings">
- <action description="Cambiar música &amp; configuraciones de multimedia"
- longdescription="Cambie streaming de música y configuraciones de vídeo en Sobre el terreno &gt; pestaña Multimedia."
+ <action description="Cambiar música y configuraciones de los media"
+ longdescription="Cambiar la música en streaming y las configuraciones de vídeo en Acerca del terreno &gt; pestaña Media."
name="land change media" value="20" />
- <action description="Activar/desactivar &apos;Editar terreno&apos;"
- longdescription="Active/desactive &apos;Editar terreno&apos;. *AVISO* Sobre el terreno &gt; pestaña Opciones &gt; Editar terreno permite a cualquiera alterar las formas de su terreno&apos;, sustituir y mover plantas Linden. Asegúrese de saber lo que está haciendo antes de designar esta habilidad. La edición de terreno es activada/desactivada en Sobre el terreno &gt; pestaña Opciones."
+ <action description="Activar/desactivar &apos;Editar el terreno&apos;"
+ longdescription="Activar/desactivar &apos;Editar el terreno&apos;. *AVISO* Acerca del terreno &gt; pestaña Opciones &gt; Editar el terreno, permite a cualquiera alterar la forma de su terreno y sustituir y mover plantas Linden. Asegúrese de lo que está haciendo antes de otorgar esta capacidad. La edición del terreno se activada/desactiva en Acerca del terreno &gt; pestaña Opciones."
name="land edit" value="21" />
<action
- description="Activar/desactivar variados Sobre el Terreno &gt; Opciones de configuraciones"
- longdescription="Active/desactive &apos;Seguro (sin daño)&apos;, &apos;Volar&apos;, y permita a otros residentes: &apos;Crear objetos&apos;, &apos;Editar terreno&apos;, &apos;Crear puntos de referencia&apos;, y &apos;Ejecutar scripts&apos; en un terreno perteneciente al grupo en Sobre el terreno &gt; pestaña Opciones."
+ description="Activar/desactivar varios ítems de Acerca del terreno &gt; Opciones"
+ longdescription="Activar/desactivar en un terreno del grupo los ítems de Acerca del terreno &gt; pestaña Opciones: &apos;Seguro (sin daño)&apos;, &apos;Volar&apos;, y permitir a otros residentes: &apos;Crear objetos&apos;, &apos;Editar el terreno&apos;, &apos;Crear hitos&apos;, y &apos;Ejecutar scripts&apos;."
name="land options" value="22" />
</action_set>
<action_set
- description="Estas habilidades incluyen poderes que permiten a miembros rebasar restricciones en parcelas pertenecientes al grupo."
+ description="Estas capacidades incluyen poderes que permiten a los miembros rebasar las restricciones de parcelas pertenecientes al grupo."
name="Parcel Powers">
- <action description="Siempre permitir &apos;Editar terreno&apos;"
- longdescription="Miembros en una función con esta habilidad pueden editar terreno en una parcela perteneciente al grupo, mismo si está desactivada en Sobre el terreno &gt; pestaña Opciones."
+ <action description="Permitir siempre &apos;Editar el terreno&apos;"
+ longdescription="Quien tenga un rol con esta capacidad puede editar el terreno de una parcela perteneciente al grupo aunque eso esté desactivado en Acerca del terreno &gt; pestaña Opciones."
name="land allow edit land" value="23" />
- <action description="Siempre permitir &apos;Volar&apos;"
- longdescription="Miembros en una función con esta habilidad pueden volar sobre una parcela perteneciente al grupo, mismo si está desactivada en Sobre el terreno &gt; pestaña Opciones."
+ <action description="Permitir siempre &apos;Volar&apos;"
+ longdescription="Quien tenga un rol con esta capacidad puede volar sobre una parcela perteneciente al grupo aunque eso esté desactivado en Acerca del terreno &gt; pestaña Opciones."
name="land allow fly" value="24" />
- <action description="Siempre permitir &apos;Crear objetos&apos;"
- longdescription="Miembros en una función con esta habilidad pueden crear objetos en una parcela perteneciente al grupo, mismo si está desactivada en Sobre el terreno &gt; pestaña Opciones."
+ <action description="Permitir siempre &apos;Crear objetos&apos;"
+ longdescription="Quien tenga un rol con esta capacidad puede crear objetos en una parcela perteneciente al grupo aunque eso esté desactivado en Acerca del terreno &gt; pestaña Opciones."
name="land allow create" value="25" />
- <action description="Siempre permitir &apos;Crear punto de referencia&apos;"
- longdescription="Miembros en una función con esta habilidad pueden poner un punto de referencia en una parcela perteneciente al grupo, mismo si está desactivada en Sobre el terreno &gt; pestaña Opciones."
+ <action description="Permitir siempre &apos;Crear hitos&apos;"
+ longdescription="Quien tenga un rol con esta capacidad puede crear un hito en una parcela perteneciente al grupo aunque eso esté desactivado en Acerca del terreno &gt; pestaña Opciones."
name="land allow landmark" value="26" />
- <action description="Permitir &apos;Colocar casa aquí&apos; en el terreno del grupo"
- longdescription="Miembros en una función con esta habilidad pueden usar el menú Mundo &gt; Definir hogar aquí en una parcela del grupo (definir terreno o transferir para este grupo)."
+ <action description="Permitir &apos;Fijar mi Base aquí&apos; en el terreno del grupo"
+ longdescription="Quien tenga un rol con esta capacidad puede usar el menú Mundo &gt; Fijar mi Base aquí en una parcela transferida al grupo."
name="land allow set home" value="28" />
</action_set>
<action_set
- description="Estas habilidades incluyen poderes de permitir o restringir acceso a parcelas pertenecientes al grupo, incluyendo congelar y expulsar a residentes."
+ description="Estas capacidades incluyen poderes para permitir o restringir el acceso a parcelas pertenecientes al grupo, incluyendo el congelar y expulsar a residentes."
name="Parcel Access">
- <action description="Administrar listas de acceso a la parcela"
- longdescription="Administre la lista de acceso a la parcela en Sobre el terreno &gt; pestaña Acceso."
+ <action description="Administrar las listas de acceso a la parcela"
+ longdescription="Administre las listas de acceso a la parcela en Acerca del terreno &gt; pestaña Acceso."
name="land manage allowed" value="29" />
- <action description="Administrar lista de desterrados de la parcela"
- longdescription="Administre la lista de desterrados de la parcela en Sobre el terreno &gt; pestaña Desterrado."
+ <action description="Administrar la lista de residentes con el acceso prohibido"
+ longdescription="Administrar la lista de residentes con el acceso prohibido a la parcela en Acerca del terreno &gt; pestaña Acceso."
name="land manage banned" value="30" />
- <action description="Cambiar configuraciones de parcela &apos;Vender pases...&apos;"
- longdescription="Cambie configuraciones de &apos;Vender pases...&apos; en Sobre el terreno &gt; pestaña Acceso."
+ <action description="Cambiar en las configuraciones de parcela el &apos;Vender pases a...&apos;"
+ longdescription="Cambiar la configuración de &apos;Vender pases a...&apos; en Acerca del terreno &gt; pestaña Acceso."
name="land manage passes" value="31" />
<action description="Expulsar y congelar residentes en las parcelas"
- longdescription="Miembros en una función con esta habilidad pueden lidiar con un residente indeseado en una parcela perteneciente al grupo haciendo clic con el botón derecho sobre él, Más &gt; y seleccionando &apos;Expulsar...&apos; o &apos;Congelar...&apos;."
+ longdescription="Quien tenga un rol con esta capacidad puede actuar frente a un residente indeseado en una parcela del grupo pulsando con el botón derecho sobre él, Más &gt; y seleccionando &apos;Expulsar...&apos; o &apos;Congelar...&apos;."
name="land admin" value="32" />
</action_set>
<action_set
- description="Estas habilidades incluyen poderes de permitir a miembros devolver objetos y poner y mover plantas Linden. Útil para que miembros organicen el paisaje, pero debe ser usado con cuidado, debido a no ser posible deshacer la mudanza de los objetos."
+ description="Estas capacidades incluyen poderes que permitan a los miembros devolver objetos y poner y mover plantas Linden. Es útil para que miembros organicen el paisaje, pero debe ser usado con cuidado, ya que no se pueden deshacer esos cambios en los objetos."
name="Parcel Content">
<action description="Devolver objetos que pertenecen al grupo"
- longdescription="Devuelva objetos en parcelas pertenecientes al grupo que pertenecen al grupo en Sobre el terreno &gt; pestaña Objetos."
+ longdescription="Devolver objetos pertenecientes al grupo en parcelas de su propiedad en Acerca del terreno &gt; pestaña Objetos."
name="land return group owned" value="48" />
<action description="Devolver objetos definidos para el grupo"
- longdescription="Devuelva objetos en parcelas pertenecientes al grupo en Sobre el terreno &gt; pestaña Objetos."
+ longdescription="Devuelva objetos en parcelas pertenecientes al grupo en Acerca del terreno &gt; pestaña Objetos."
name="land return group set" value="33" />
<action description="Devolver objetos que no pertenecen al grupo"
- longdescription="Devuelva objetos en las parcelas pertenecientes a un grupo que está sin grupo en el Sobre el terreno &gt; pestaña Objetos."
+ longdescription="Devuolver objetos que estén en una parcela del grupo y pertenezcan a alguien que no sea del grupo en Acerca del terreno &gt; pestaña Objetos."
name="land return non group" value="34" />
- <action description="Enjardinar usando plantas Linden"
- longdescription="La habilidad de enjardinar permite poner y mover árboles Linden, plantas y céspedes. Estos ítems pueden ser encontrados en la&apos;s Biblioteca de su inventario &gt; carpeta Objetos o pueden ser criados a través del botón Construir."
+ <action description="Modificar el paisaje usando plantas Linden"
+ longdescription="La capacidad de modificar el paisaje permite poner y mover árboles Linden, plantas y arbustos. Estos ítems están en la &apos;s Biblioteca de su Inventario &gt; carpeta Objetos, o pueden crearse con el botón Construir."
name="land gardening" value="35" />
</action_set>
<action_set
- description="These Abilities include powers to deed, modify, and sell group-owned objects. These changes are done in the Edit Tools &gt; General Tab. Right-click an object and Edit to see its settings. "
+ description="Estas capacidades incluyen poderes para tranferir, modificar y vender objetos pertenecientes al grupo. Estos cambios se hacen en la pestaña General de la herramienta de edición. Para verlo, pulse en un objeto con el botón derecho y elija Editar. "
name="Object Management">
- <action description="Transferir objetos para el grupo"
- longdescription="Transfiere objetos para el grupo en Editar herramientas &gt; pestaña General."
+ <action description="Transferir objetos al grupo"
+ longdescription="Transferir objetos al grupo en Editar &gt; pestaña General."
name="object deed" value="36" />
- <action description="Manipular (mover, copiar, modificar) objetos del grupo"
- longdescription="Manipule (mover,copiar, modificar) objetos pertenecientes al grupo en Editar Herramientas &gt; pestaña General."
+ <action description="Manipular (mover, copiar, y modificar) objetos del grupo"
+ longdescription="Manipular (mover, copiar, y modificar) objetos pertenecientes al grupo en Editar &gt; pestaña General."
name="object manipulate" value="38" />
- <action description="Definir objetos pertenecientes al grupo para venta"
- longdescription="Defina objetos pertenecientes al grupo para venta en Editar Herramientas &gt; pestaña General."
+ <action description="Vender objetos pertenecientes al grupo"
+ longdescription="Poner a la venta objetos pertenecientes al grupo para venta en Editar &gt; pestaña General."
name="object set sale" value="39" />
</action_set>
<action_set
- description="Estas habilidades incluyen poderes que requieren que miembros paguen deudas y reciban dividendos del grupo, y restringen acceso al historial de cuenta del grupo."
+ description="Estas habilidades incluyen poderes para que los miembros paguen deudas del grupo o reciban sus dividendos, y para limitar el acceso al historial de la cuenta del grupo."
name="Accounting">
- <action description="Pagar débitos y reciber dividendos del grupo"
- longdescription="Members in a Role with this Ability will automatically pay group liabilities and receive group dividends. This means they will receive a portion of group-owned land sales which are distributed daily, as well as contribute towards things like parcel listing fees. "
+ <action description="Pagar deudas y recibir dividendos del grupo"
+ longdescription="Quien tenga un rol con esta capacidad, automáticamente pagará deudas del grupo y recibirá sus dividendos. Esto significa que recibirá una parte de las ventas de terreno de grupo, y que contribuirá a cosas como, por ejemplo, las cuotas por posesión de terreno. "
name="accounting accountable" value="40" />
</action_set>
<action_set
- description="Estas habilidades incluyen poderes de permitir enviar, recibir y ver avisos de grupo."
+ description="Estas habilidades incluyen poderes para enviar, recibir y ver avisos de grupo."
name="Notices">
<action description="Enviar aviso"
- longdescription="Miembros en una función con esta habilidad pueden enviar avisos en Informaciones de grupo &gt; pestaña Avisos."
+ longdescription="Quien tenga un rol con esta capacidad puede enviar avisos en Información del grupo &gt; pestaña Avisos."
name="notices send" value="42" />
- <action description="Reciber nuevos avisos y ver los anteriores"
- longdescription="Miembros en una función con esta habilidad pueden recibir los nuevos avisos y ver los anteriores en Informaciones de grupo &gt; pestaña Avisos."
+ <action description="Recibir avisos nuevos y ver los anteriores"
+ longdescription="Quien tenga un rol con esta capacidad puede recibir los avisos nuevos, y ver los anteriores en Información del grupo &gt; pestaña Avisos."
name="notices receive" value="43" />
</action_set>
<action_set
- description="Estas habilidades incluyen poderes de permitir a miembros definir y votar en propuestas y ver historial de votación."
+ description="Estas habilidades incluyen poderes para permitir a los miembros crear propuestas, votarlas, y ver el historial de votaciones."
name="Proposals">
- <action description="Crear propuesta"
- longdescription="Miembros en una función con esta habilidad pueden crear propuestas para que sean votadas en Informaciones de grupo &gt; pestaña Propuestas."
+ <action description="Hacer una propuesta"
+ longdescription="Quien tenga un rol con esta capacidad puede crear propuestas para que sean votadas en Información del grupo &gt; pestaña Propuestas."
name="proposal start" value="44" />
<action description="Votar en propuestas"
- longdescription="Miembros en una función con esta habilidad pueden votar en propuestas en Informaciones de grupo &gt; pestaña Propuestas."
+ longdescription="Quien tenga un rol con esta capacidad puede votar las propuestas en Información del grupo &gt; pestaña Propuestas."
name="proposal vote" value="45" />
</action_set>
+ <action_set
+ description="Estas capacidades incluyen poderes para permitir o no el aceso a las sesiones de chat del grupo y al chat de voz del mismo."
+ name="Chat">
+ <action description="Abrir chat de grupo"
+ longdescription="Quien tenga un rol con esta capacidad puede abrir sesiones de chat del grupo, tanto de texto como de voz."
+ name="join group chat" value="16" />
+ <action description="Abrir chat de voz del grupo"
+ longdescription="Quien tenga un rol con esta capacidad puede abrir sesiones de chat de voz del grupo. NOTA: para acceder al chat de voz debe tenerse la capacidad &apos;Abrir chat de grupo&apos;."
+ name="join voice chat" value="27" />
+ <action description="Moderar el chat de grupo"
+ longdescription="Quien tenga esta capacidad puede controlar el acceso y la participación en los chats de texto y de voz del grupo."
+ name="moderate group chat" value="37" />
+ </action_set>
</role_actions>
diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml
index 4793f6c661..dc508f7c37 100644
--- a/indra/newview/skins/default/xui/es/strings.xml
+++ b/indra/newview/skins/default/xui/es/strings.xml
@@ -4,6 +4,7 @@
For example, the strings used in avatar chat bubbles, and strings
that are returned from one component and may appear in many places-->
<strings>
+ <string name="create_account_url">http://join.secondlife.com/index.php?lang=es-ES</string>
<string name="LoginInProgress">
Iniciando la sesión. [APP_NAME] debe de aparecer congelado. Por favor, espere.
</string>
@@ -55,6 +56,9 @@
<string name="LoginDownloadingClothing">
Descargando la ropa...
</string>
+ <string name="Quit">
+ Salir
+ </string>
<string name="AgentLostConnection">
Esta región puede estar teniendo problemas. Por favor, compruebe su conexión a internet.
</string>
@@ -483,4 +487,181 @@
<string name="choose_the_directory">
Elegir directorio
</string>
+ <!-- OSMessageBox messages -->
+ <string name="MBAlreadyRunning">
+ [APP_NAME] ya se está ejecutando.
+Busque en la barra de su escritorio una copia minimizada del programa.
+Si aun así persiste este mensaje, reinicie su ordenador.
+ </string>
+ <string name="MBVideoDrvErr">
+ No se puede ejecutar [APP_NAME] porque los drivers de su tarjeta de vídeo no están instalados correctamente, o no están actualizados, o son de un hardware no admitido. Por favor, asegúrese de que tiene los últimos drivers para su tarjeta de vídeo, e incluso en ese caso intente reinstalarlos.
+
+Si sigue recibiendo este mensaje, contacte con el [SUPPORT_SITE].
+ </string>
+ <string name="accel-mac-control">
+ &#8963;
+ </string>
+ <string name="accel-mac-command">
+ &#8984;
+ </string>
+ <string name="accel-mac-option">
+ &#8997;
+ </string>
+ <string name="accel-mac-shift">
+ &#8679;
+ </string>
+ <string name="accel-win-control">
+ Ctrl+
+ </string>
+ <string name="accel-win-alt">
+ Alt+
+ </string>
+ <string name="accel-win-shift">
+ Mayús+
+ </string>
+ <string name="GraphicsQualityLow">
+ Bajo
+ </string>
+ <string name="GraphicsQualityMid">
+ Medio
+ </string>
+ <string name="GraphicsQualityHigh">
+ Alto
+ </string>
+
+ <!-- PARCEL_CATEGORY_UI_STRING -->
+ <string name="Linden Location">Localización Linden</string>
+ <string name="Adult">&apos;Adult&apos;</string>
+ <string name="Arts&amp;Culture">Arte y Cultura</string>
+ <string name="Business">Negocios</string>
+ <string name="Educational">Educativo</string>
+ <string name="Gaming">Juegos de azar</string>
+ <string name="Hangout">Entretenimiento</string>
+ <string name="Newcomer Friendly">Para recién llegados</string>
+ <string name="Parks&amp;Nature">Parques y Naturaleza</string>
+ <string name="Residential">Residencial</string>
+ <string name="Shopping">Compras</string>
+ <string name="Other">Otra</string>
+
+ <string name="ringing">
+ Conectando al chat de voz...
+ </string>
+ <string name="connected">
+ Conectado
+ </string>
+ <string name="unavailable">
+ La voz no está disponible en su localización actual
+ </string>
+ <string name="hang_up">
+ Desconectado del chat de voz
+ </string>
+ <string name="ScriptQuestionCautionChatGranted">
+ &apos;[OBJECTNAME]&apos;, un objeto propiedad de &apos;[OWNERNAME]&apos;, localizado en [REGIONNAME] con la posición [REGIONPOS], ha recibido permiso para: [PERMISSIONS].
+ </string>
+ <string name="ScriptQuestionCautionChatDenied">
+ A &apos;[OBJECTNAME]&apos;, un objeto propiedad de &apos;[OWNERNAME]&apos;, localizado en [REGIONNAME] con la posición [REGIONPOS], se le ha denegado el permiso para: [PERMISSIONS].
+ </string>
+ <string name="ScriptTakeMoney">
+ Cogerle a usted dólares Linden (L$)
+ </string>
+ <string name="ActOnControlInputs">
+ Actuar en sus controles de entrada
+ </string>
+ <string name="RemapControlInputs">
+ Reconfigurar sus controles de entrada
+ </string>
+ <string name="AnimateYourAvatar">
+ Ejecutar animaciones en su avatar
+ </string>
+ <string name="AttachToYourAvatar">
+ Anexarse a su avatar
+ </string>
+ <string name="ReleaseOwnership">
+ Anular la propiedad y que pase a ser público
+ </string>
+ <string name="LinkAndDelink">
+ Enlazar y desenlazar de otros objetos
+ </string>
+ <string name="AddAndRemoveJoints">
+ Añadir y quitar uniones con otros objetos
+ </string>
+ <string name="ChangePermissions">
+ Cambiar sus permisos
+ </string>
+ <string name="TrackYourCamera">
+ Seguir su cámara
+ </string>
+ <string name="ControlYourCamera">
+ Controlar su cámara
+ </string>
+
+ <string name="only_user_message">
+ Usted es el único usuario en esta sesión.
+ </string>
+ <string name="offline_message">
+ [FIRST] [LAST] no está conectado.
+ </string>
+ <string name="invite_message">
+ Pulse el botón [BUTTON NAME] para aceptar/conectar este chat de voz.
+ </string>
+ <string name="generic_request_error">
+ Error al hacer lo solicitado; por favor, inténtelo más tarde.
+ </string>
+ <string name="insufficient_perms_error">
+ Usted no tiene permisos suficientes.
+ </string>
+ <string name="session_does_not_exist_error">
+ La sesión ya acabó
+ </string>
+ <string name="no_ability_error">
+ Usted no tiene esa capacidad.
+ </string>
+ <string name="no_ability">
+ Usted no tiene esa capacidad.
+ </string>
+ <string name="not_a_mod_error">
+ Usted no es un moderador de la sesión.
+ </string>
+ <string name="muted_error">
+ Un moderador del grupo le ha desactivado el chat de texto.
+ </string>
+ <string name="add_session_event">
+ No se ha podido añadir usuarios a la sesión de chat con [RECIPIENT].
+ </string>
+ <string name="message_session_event">
+ No se ha podido enviar su mensaje a la sesión de chat con [RECIPIENT].
+ </string>
+ <string name="removed_from_group">
+ Ha sido eliminado del grupo.
+ </string>
+ <string name="close_on_no_ability">
+ Usted ya no tendrá más la capacidad de estar en la sesión de chat.
+ </string>
+ <string name="AcctTypeResident">
+ Residente
+ </string>
+ <string name="AcctTypeTrial">
+ Prueba
+ </string>
+ <string name="AcctTypeCharterMember">
+ Miembro fundador
+ </string>
+ <string name="AcctTypeEmployee">
+ Empleado de Linden Lab
+ </string>
+ <string name="PaymentInfoUsed">
+ Ha usado una forma de pago
+ </string>
+ <string name="PaymentInfoOnFile">
+ Hay infor. de la forma de pago
+ </string>
+ <string name="NoPaymentInfoOnFile">
+ Sin infor. de la forma de pago
+ </string>
+ <string name="AgeVerified">
+ Edad verificada
+ </string>
+ <string name="NotAgeVerified">
+ Edad no verificada
+ </string>
</strings>
diff --git a/indra/newview/skins/default/xui/fr/floater_about.xml b/indra/newview/skins/default/xui/fr/floater_about.xml
index d627571ae9..7d6d736c5e 100644
--- a/indra/newview/skins/default/xui/fr/floater_about.xml
+++ b/indra/newview/skins/default/xui/fr/floater_about.xml
@@ -1,11 +1,60 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_about" title="A propos de Second Life">
- <text_editor name="credits_editor">
- Second Life existe grâce aux efforts de Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les et de nombreuses autres personnes.
+<floater name="floater_about" title="À PROPOS DE [CAPITALIZED_APP_NAME]">
+ <floater.string name="AboutHeader">
+ [APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL])
+[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]]
+ </floater.string>
+ <floater.string name="AboutCompiler">
+ Compilé avec [COMPILER] version [COMPILER_VERSION]
+ </floater.string>
+ <floater.string name="AboutPosition">
+ Vous êtes à [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] dans [REGION] se trouvant à [HOSTNAME] ([HOSTIP])
+[SERVER_VERSION]
+[[SERVER_RELEASE_NOTES_URL] [ReleaseNotes]]
+ </floater.string>
+ <floater.string name="AboutSystem">
+ CPU : [CPU]
+Mémoire : [MEMORY_MB] Mo
+Version OS : [OS_VERSION]
+Distributeur de cartes graphiques : [GRAPHICS_CARD_VENDOR]
+Cartes graphiques : [GRAPHICS_CARD]
+ </floater.string>
+ <floater.string name="AboutDriver">
+ Version Windows Graphics Driver : [GRAPHICS_DRIVER_VERSION]
+ </floater.string>
+ <floater.string name="AboutLibs">
+ Version OpenGL : [OPENGL_VERSION]
- Tous nos remerciements aux résidents suivants pour avoir testé cette version (la meilleure qui soit jusqu&apos;à présent) : afon shepherd, Aimee Trescothick, Alexandrea Fride, Alissa Sabre, Amber DeCuir, Asuka Neely, Auron Forcella, Blue Revolution, Bocan Undercroft, Boroondas Gupte, Brandon Shinobu, Bri Gufler, Buckaroo Mu, Celierra Darling, Christos Atlantis, Coder Kas, Cummere Mayo, dakota schwade, Dirk Talamasca, Dizzy Banjo, Drew Dwi, Duckling Kwak, Ellla McMahon, Erikah Jameson, Erinyse Planer, Eyana Yohkoh, Ezian Ecksol, Faron Karu, Fenoe Lowey, Fox Hwasung, Francisca Biedermann, Gally Young, Gellan Glenelg, Geneko Nemeth, Glenn Rotaru, Hagar Qinan, Harleen Gretzky, Holger Gilruth, hotrodjohnny gears, IAm Zabelin, Inigo Catteneo, Iustinian Tomsen, Jacek Antonell, James Benedek, Jim Kupferberg, Joeseph Albanese, JPT62089 Agnon, Kardargo Adamczyk, Kirstenlee Cinquetti, Latif Khalifa, lea Parnall, Lex Neva, Lillith Anatine, Lilly Zenovka, Lim Catteneo, Lindal Kidd, Mark Rosenbaum, MasterJ Chaplin, McCabe Maxsted, Melvin Starbrook, Meni Kaiousei, Mero Collas, Minakothegothicgeisha Kamachi, Moon Metty, neofilo aabye, Neutron Chesnokov, Nomad Ingwer, norritt Xi, Opensource Obscure, Oracle Weatherwax, Ourasi Ferraris, Pabl0 Roffo, Peyton Aleixandre, Phli Foxchase, Psi Merlin, r2d2 Wunderlich, Regi Yifu, Saijanai Kuhn, Sandor Balczo, Sarkan Dreamscape, Scree Raymaker, Sedona Mills, Selena Beale, Sheet Spotter, Shibari Twine, Silver Key, Simon Kline, SLB Wirefly, Stacy Wombat, Sugarcult Dagger, Tayra Dagostino, Tetsuryu Vlodovic, ThaBiGGDoGG Richez, Timo Gufler, tx Oh, wayfinder wishbringer, Wizzytoe McCullough, Wundur Primbee, Yann Dufaux, Yuu Nakamichi, Aminom Marvin, Andred Qinan, arminasx saiman, caroline apollo, Iskar Ariantho, Jenika Connolly, Maghnus Balogh, Nefertiti Nefarious, RodneyLee Jessop
+Version libcurl : [LIBCURL_VERSION]
+Version J2C Decoder : [J2C_VERSION]
+Version Audio Driver : [AUDIO_DRIVER_VERSION]
+Version Qt Webkit : [QT_WEBKIT_VERSION]
+Version Vivox : [VIVOX_VERSION]
+ </floater.string>
+ <floater.string name="none">
+ (aucun)
+ </floater.string>
+ <floater.string name="AboutTraffic">
+ Paquets perdus : [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%)
+ </floater.string>
+ <tab_container name="about_tab">
+ <panel label="Infos" name="support_panel">
+ <button label="Copier dans le presse-papiers" name="copy_btn"/>
+ </panel>
+ <panel label="Remerciements" name="credits_panel">
+ <text_editor name="credits_editor">
+ Second Life existe grâce aux efforts de Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, Michon, Jenelle, Geo, Siz, Shapiro, Pete, Calyle, Selene, Allen, Phoebe, Goldin, Kimmora, Dakota, Slaton, Lindquist, Zoey, Hari, Othello, Rohit, Sheldon, Petra, Viale, Gordon, Kaye, Pink, Ferny, Emerson, Davy, Bri, Chan, Juan, Robert, Terrence, Nathan, Carl et de nombreuses autres personnes.
- 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
+ Tous nos remerciements aux résidents suivants pour avoir testé cette version (la meilleure qui soit jusqu&apos;à présent) : able whitman, Adeon Writer, adonaira aabye, Aeron Kohime, Agathos Frascati, Aimee Trescothick, Aleric Inglewood, Alissa Sabre, Aminom Marvin, Angela Talamasca, Aralara Rajal, Armin Weatherwax, Ashrilyn Hayashida, Athanasius Skytower, Aura Dirval, Barney Boomslang, Biancaluce Robbiani, Biker Offcourse, Borg Capalini, Bulli Schumann, catherine pfeffer, Chalice Yao, Corre Porta, Court Goodman, Cummere Mayo, Dale Innis, Darien Caldwell, Darjeeling Schoonhoven, Daten Thielt, dimentox travanti, Dirk Talamasca, Drew Dwi, Duckless Vandyke, Elanthius Flagstaff, Electro Burnstein, emiley tomsen, Escort DeFarge, Eva Rau, Ezian Ecksol, Fire Centaur, Fluf Fredriksson, Francisco Koolhoven, Frontera Thor, Frungi Stastny, Gally Young, gearsawe stonecutter, Gigs Taggart, Gordon Wendt, Gudmund Shepherd, Gypsy Paz, Harleen Gretzky, Henri Beauchamp, Inma Rau, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Jessicka Graves, Joeseph Albanese, Joshua Philgarlic, Khyota Wulluf, kirstenlee Cinquetti, Latif Khalifa, Lex Neva, Lilibeth Andree, Lisa Lowe, Lunita Savira, Loosey Demonia, lum pfohl, Marcos Fonzarelli, MartinRJ Fayray, Marusame Arai, Matthew Dowd, Maya Remblai, McCabe Maxsted, Meghan Dench, Melchoir Tokhes, Menos Short, Michelle2 Zenovka, Mimika Oh, Minerva Memel, Mm Alder, Ochi Wolfe, Omei Turnbull, Pesho Replacement, Phantom Ninetails, phoenixflames kukulcan, Polo Gufler, prez pessoa, princess niven, Prokofy Neva, Qie Niangao, Rem Beattie, RodneyLee Jessop, Saijanai Kuhn, Seg Baphomet, Sergen Davies, Shirley Marquez, SignpostMarv Martin, Sindy Tsure, Sira Arbizu, Skips Jigsaw, Sougent Harrop, Spritely Pixel, Squirrel Wood, StarSong Bright, Subversive Writer, Sugarcult Dagger, Sylumm Grigorovich, Tammy Nowotny, Tanooki Darkes, Tayra Dagostino, Theoretical Chemistry, Thickbrick Sleaford, valerie rosewood, Vex Streeter, Vixen Heron, Whoops Babii, Winter Ventura, Xiki Luik, Yann Dufaux, Yina Yao, Yukinoroh Kamachi, Zolute Infinity, Zwagoth Klaar
+
+
+
+ Pour réussir dans les affaires, soyez audacieux, créatif et différent. - Henry Marchant
+ </text_editor>
+ </panel>
+ <panel label="Licences" name="licenses_panel">
+ <text_editor name="credits_editor">
+ 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
APR Copyright (C) 2000-2004 The Apache Software Foundation
cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
@@ -25,11 +74,7 @@
Tous droits réservés. Voir licenses.txt pour plus de détails.
Codage Audio du chat vocal : Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
-
-
- Pour réussir dans les affaires, soyez audacieux, créatif et différent. - Henry Marchant
- </text_editor>
- <string name="you_are_at">
- Votre position : [POSITION]
- </string>
+ </text_editor>
+ </panel>
+ </tab_container>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_about_land.xml b/indra/newview/skins/default/xui/fr/floater_about_land.xml
index a556fa4173..cf595edab9 100644
--- a/indra/newview/skins/default/xui/fr/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/fr/floater_about_land.xml
@@ -1,12 +1,64 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterland" title="À propos du terrain">
+<floater name="floaterland" title="À PROPOS DES TERRAINS">
+ <floater.string name="Minutes">
+ [MINUTES] minutes
+ </floater.string>
+ <floater.string name="Minute">
+ minute
+ </floater.string>
+ <floater.string name="Seconds">
+ [SECONDS] secondes
+ </floater.string>
+ <floater.string name="Remaining">
+ restantes
+ </floater.string>
<tab_container name="landtab">
<panel label="Général" name="land_general_panel">
- <text length="1" name="Name:" type="string">
+ <panel.string name="new users only">
+ Nouveaux utilisateurs uniquement
+ </panel.string>
+ <panel.string name="anyone">
+ Tout le monde
+ </panel.string>
+ <panel.string name="area_text">
+ Surface
+ </panel.string>
+ <panel.string name="area_size_text">
+ [AREA] m²
+ </panel.string>
+ <panel.string name="auction_id_text">
+ Code de l&apos;enchère : [ID]
+ </panel.string>
+ <panel.string name="need_tier_to_modify">
+ Pour modifier ce terrain, vous devez approuver votre achat.
+ </panel.string>
+ <panel.string name="group_owned_text">
+ (propriété du groupe)
+ </panel.string>
+ <panel.string name="profile_text">
+ Profil...
+ </panel.string>
+ <panel.string name="info_text">
+ Infos...
+ </panel.string>
+ <panel.string name="public_text">
+ (public)
+ </panel.string>
+ <panel.string name="none_text">
+ (aucun)
+ </panel.string>
+ <panel.string name="sale_pending_text">
+ (vente en cours)
+ </panel.string>
+ <panel.string name="no_selection_text">
+ Aucune parcelle sélectionnée.
+Allez dans le menu Monde &gt; À propos du terrain ou sélectionnez une autre parcelle pour en afficher les détails.
+ </panel.string>
+ <text name="Name:">
Nom :
</text>
<line_editor name="Name"/>
- <text length="1" name="Description:" type="string">
+ <text name="Description:">
Description :
</text>
<text_editor name="Description"/>
@@ -22,58 +74,58 @@
<text name="ContentRatingText">
Adult
</text>
- <text length="1" name="Owner:" type="string">
+ <text name="Owner:">
Propriétaire :
</text>
- <text length="1" name="OwnerText" type="string">
+ <text name="OwnerText">
Leyla Linden
</text>
<button label="Profil..." label_selected="Profil..." name="Profile..."/>
- <text length="1" name="Group:" type="string">
+ <text name="Group:">
Groupe :
</text>
<text name="GroupText"/>
<button label="Définir..." label_selected="Définir..." name="Set..."/>
- <check_box label="Autoriser la cession au groupe" name="check deed" tool_tip="Un officier peut céder ce terrain au groupe. Il viendra alors s&apos;ajouter au patrimoine du groupe."/>
+ <check_box label="Autoriser la cession au groupe" name="check deed" tool_tip="Un officier du groupe peut céder ce terrain à ce groupe, afin qu&apos;il soit pris en charge par l&apos;allocation de terrains du groupe."/>
<button label="Céder..." label_selected="Céder..." name="Deed..." tool_tip="Vous ne pouvez céder le terrain que si vous avez un rôle d&apos;officier dans le groupe sélectionné."/>
<check_box label="Le propriétaire contribue en cédant du terrain" name="check contrib" tool_tip="Lorsqu&apos;un terrain est cédé au groupe, l&apos;ancien propriétaire fait également un don de terrain suffisant."/>
- <text length="1" name="For Sale:" type="string">
+ <text name="For Sale:">
À vendre :
</text>
- <text length="1" name="Not for sale." type="string">
+ <text name="Not for sale.">
Pas à vendre
</text>
- <text length="1" name="For Sale: Price L$[PRICE]." type="string">
- Prix : [PRICE] L$ ([PRICE_PER_SQM] L$/m²).
+ <text name="For Sale: Price L$[PRICE].">
+ Prix : [PRICE] L$ ([PRICE_PER_SQM] L$/m²).
</text>
<text name="SalePending"/>
<button label="Vendre le terrain..." label_selected="Vendre le terrain..." name="Sell Land..."/>
- <text length="1" name="For sale to" type="string">
+ <text name="For sale to">
À vendre à : [BUYER]
</text>
- <text length="1" name="Sell with landowners objects in parcel." type="string">
+ <text name="Sell with landowners objects in parcel.">
Objets inclus dans la vente.
</text>
- <text length="1" name="Selling with no objects in parcel." type="string">
+ <text name="Selling with no objects in parcel.">
Objets non inclus dans la vente.
</text>
<button label="Annuler la vente du terrain" label_selected="Annuler la vente du terrain" left="275" name="Cancel Land Sale" width="165"/>
- <text length="1" name="Claimed:" type="string">
+ <text name="Claimed:">
Acquis :
</text>
- <text length="1" name="DateClaimText" type="string">
+ <text name="DateClaimText">
Tue Aug 15 13:47:25 2006
</text>
- <text length="1" name="PriceLabel" type="string">
+ <text name="PriceLabel">
Superficie :
</text>
- <text length="1" name="PriceText" type="string">
- 4048 m²
+ <text name="PriceText">
+ 4 048 m²
</text>
- <text length="1" name="Traffic:" type="string">
+ <text name="Traffic:">
Trafic :
</text>
- <text length="1" name="DwellText" type="string">
+ <text name="DwellText">
0
</text>
<button label="Acheter le terrain..." label_selected="Acheter le terrain..." left="130" name="Buy Land..." width="125"/>
@@ -82,76 +134,50 @@
<button label="Abandonner le terrain..." label_selected="Abandonner le terrain..." name="Abandon Land..."/>
<button label="Redemander le terrain..." label_selected="Redemander le terrain…" name="Reclaim Land..."/>
<button label="Vente Linden..." label_selected="Vente Linden..." name="Linden Sale..." tool_tip="Le terrain doit être la propriété d&apos;un résident, avoir un contenu défini et ne pas être aux enchères."/>
- <string name="new users only">
- Nouveaux utilisateurs uniquement
- </string>
- <string name="anyone">
- Tout le monde
- </string>
- <string name="area_text">
- Surface
- </string>
- <string name="area_size_text">
- [AREA] m²
- </string>
- <string name="auction_id_text">
- Code de l&apos;enchère : [ID]
- </string>
- <string name="need_tier_to_modify">
- Pour modifier ce terrain, vous devez approuver votre achat.
- </string>
- <string name="group_owned_text">
- (propriété du groupe)
- </string>
- <string name="profile_text">
- Profil...
- </string>
- <string name="info_text">
- Infos...
- </string>
- <string name="public_text">
- (public)
- </string>
- <string name="none_text">
- (aucun)
- </string>
- <string name="sale_pending_text">
- (vente en cours)
- </string>
- <string name="no_selection_text">
- Aucune parcelle sélectionnée.
-Allez dans le menu Monde &gt; À propos du terrain ou sélectionnez une autre parcelle pour en afficher les détails.
- </string>
</panel>
<panel label="Règlement" name="land_covenant_panel">
+ <panel.string name="can_resell">
+ Le terrain acheté dans cette région peut être revendu.
+ </panel.string>
+ <panel.string name="can_not_resell">
+ Le terrain acheté dans cette région ne peut pas être revendu.
+ </panel.string>
+ <panel.string name="can_change">
+ Le terrain acheté dans cette région peut être fusionné
+ou divisé.
+ </panel.string>
+ <panel.string name="can_not_change">
+ Le terrain acheté dans cette région ne peut pas être fusionné
+ou divisé.
+ </panel.string>
<text name="estate_section_lbl">
Domaine :
</text>
- <text length="1" name="estate_name_lbl" type="string">
+ <text name="estate_name_lbl">
Nom :
</text>
- <text length="1" name="estate_name_text" type="string">
+ <text name="estate_name_text">
continent
</text>
- <text length="1" name="estate_owner_lbl" type="string">
+ <text name="estate_owner_lbl">
Propriétaire :
</text>
- <text length="1" name="estate_owner_text" type="string">
+ <text name="estate_owner_text">
(aucun)
</text>
- <text_editor length="1" name="covenant_editor" type="string">
+ <text_editor name="covenant_editor">
Il n&apos;y a aucun règlement pour ce domaine.
</text_editor>
- <text length="1" name="covenant_timestamp_text" type="string">
+ <text name="covenant_timestamp_text">
Last Modified Wed Dec 31 16:00:00 1969
</text>
<text name="region_section_lbl">
Région :
</text>
- <text length="1" name="region_name_lbl" type="string">
+ <text name="region_name_lbl">
Nom :
</text>
- <text length="1" name="region_name_text" type="string">
+ <text name="region_name_text">
leyla
</text>
<text name="region_landtype_lbl">
@@ -169,111 +195,127 @@ Allez dans le menu Monde &gt; À propos du terrain ou sélectionnez une autre pa
<text name="resellable_lbl">
Revendre :
</text>
- <text length="1" name="resellable_clause" type="string">
+ <text name="resellable_clause">
Le terrain dans cette région ne peut être revendu.
</text>
<text name="changeable_lbl">
Sous-diviser :
</text>
- <text length="1" name="changeable_clause" type="string">
+ <text name="changeable_clause">
Le terrain dans cette région ne peut être fusionné/divisé.
</text>
- <string name="can_resell">
- Le terrain acheté dans cette région peut être revendu.
- </string>
- <string name="can_not_resell">
- Le terrain acheté dans cette région ne peut pas être revendu.
- </string>
- <string name="can_change">
- Le terrain acheté dans cette région peut être fusionné
-ou divisé.
- </string>
- <string name="can_not_change">
- Le terrain acheté dans cette région ne peut pas être fusionné
-ou divisé.
- </string>
</panel>
<panel label="Objets" name="land_objects_panel">
+ <panel.string name="objects_available_text">
+ [COUNT] sur [MAX] ([AVAILABLE] disponibles)
+ </panel.string>
+ <panel.string name="objects_deleted_text">
+ [COUNT] sur [MAX] ([DELETED] seront supprimés)
+ </panel.string>
<text name="parcel_object_bonus">
Facteur Bonus Objets : [BONUS]
</text>
- <text length="1" name="Simulator primitive usage:" type="string">
+ <text name="Simulator primitive usage:">
Prims utilisées sur la parcelle :
</text>
<text left="214" name="objects_available" width="230">
[COUNT] sur [MAX] ([AVAILABLE] disponibles)
</text>
- <string name="objects_available_text">
- [COUNT] sur [MAX] ([AVAILABLE] disponibles)
- </string>
- <string name="objects_deleted_text">
- [COUNT] sur [MAX] ([DELETED] seront supprimés)
- </string>
- <text length="1" name="Primitives parcel supports:" type="string" width="200">
+ <text name="Primitives parcel supports:" width="200">
Prims max. sur la parcelle :
</text>
- <text left="214" length="1" name="object_contrib_text" type="string" width="152">
+ <text left="214" name="object_contrib_text" width="152">
[COUNT]
</text>
- <text length="1" name="Primitives on parcel:" type="string">
+ <text name="Primitives on parcel:">
Prims sur la parcelle :
</text>
- <text left="214" length="1" name="total_objects_text" type="string" width="48">
+ <text left="214" name="total_objects_text" width="48">
[COUNT]
</text>
- <text left="14" length="1" name="Owned by parcel owner:" type="string" width="180">
+ <text left="14" name="Owned by parcel owner:" width="180">
Appartenant au propriétaire :
</text>
- <text left="214" length="1" name="owner_objects_text" type="string" width="48">
+ <text left="214" name="owner_objects_text" width="48">
[COUNT]
</text>
<button label="Afficher" label_selected="Afficher" name="ShowOwner" right="-135" width="60"/>
<button label="Renvoyer..." label_selected="Renvoyer..." name="ReturnOwner..." right="-10" tool_tip="Renvoyer les objets à leurs propriétaires." width="119"/>
- <text left="14" length="1" name="Set to group:" type="string" width="180">
+ <text left="14" name="Set to group:" width="180">
Données au groupe :
</text>
- <text left="214" length="1" name="group_objects_text" type="string" width="48">
+ <text left="214" name="group_objects_text" width="48">
[COUNT]
</text>
<button label="Afficher" label_selected="Afficher" name="ShowGroup" right="-135" width="60"/>
<button label="Renvoyer..." label_selected="Renvoyer..." name="ReturnGroup..." right="-10" tool_tip="Renvoyer les objets à leurs propriétaires." width="119"/>
- <text left="14" length="1" name="Owned by others:" type="string" width="128">
+ <text left="14" name="Owned by others:" width="128">
Appartenant à d&apos;autres :
</text>
- <text left="214" length="1" name="other_objects_text" type="string" width="48">
+ <text left="214" name="other_objects_text" width="48">
[COUNT]
</text>
<button label="Afficher" label_selected="Afficher" name="ShowOther" right="-135" width="60"/>
<button label="Renvoyer..." label_selected="Renvoyer..." name="ReturnOther..." right="-10" tool_tip="Renvoyer les objets à leurs propriétaires." width="119"/>
- <text left="14" length="1" name="Selected / sat upon:" type="string" width="193">
+ <text left="14" name="Selected / sat upon:" width="193">
Sélectionnées/où quelqu&apos;un est assis :
</text>
- <text left="214" length="1" name="selected_objects_text" type="string" width="48">
+ <text left="214" name="selected_objects_text" width="48">
[COUNT]
</text>
<text left="4" name="Autoreturn" width="412">
Renvoi automatique des objets des autres résidents (min., 0 pour désactiver) :
</text>
<line_editor name="clean other time" right="-6" width="36"/>
- <text length="1" name="Object Owners:" type="string">
+ <text name="Object Owners:">
Propriétaires :
</text>
<button label="Rafraîchir" label_selected="Rafraîchir" name="Refresh List"/>
<button label="Renvoyer les objets..." label_selected="Renvoyer les objets..." name="Return objects..."/>
<name_list label="Plus récents" name="owner list">
- <column label="Type" name="type"/>
- <column name="online_status"/>
- <column label="Nom" name="name"/>
- <column label="Nombre" name="count"/>
- <column label="Plus récents" name="mostrecent"/>
+ <name_list.columns label="Type" name="type"/>
+ <name_list.columns name="online_status"/>
+ <name_list.columns label="Nom" name="name"/>
+ <name_list.columns label="Nombre" name="count"/>
+ <name_list.columns label="Plus récents" name="mostrecent"/>
</name_list>
</panel>
<panel label="Options" name="land_options_panel">
- <text length="1" name="allow_label" type="string">
+ <panel.string name="search_enabled_tooltip">
+ Permettre aux autres résidents de voir cette parcelle dans les résultats de recherche
+ </panel.string>
+ <panel.string name="search_disabled_small_tooltip">
+ Cette option est désactivée car la superficie de cette parcelle est inférieure ou égale à 128 m².
+Seules les parcelles de grande taille peuvent apparaître dans la recherche.
+ </panel.string>
+ <panel.string name="search_disabled_permissions_tooltip">
+ Cette option est désactivée car vous ne pouvez pas modifier les options de cette parcelle.
+ </panel.string>
+ <panel.string name="mature_check_mature">
+ Contenu Mature
+ </panel.string>
+ <panel.string name="mature_check_adult">
+ Contenu Adult
+ </panel.string>
+ <panel.string name="mature_check_mature_tooltip">
+ Les informations ou contenu de votre parcelle sont classés Mature.
+ </panel.string>
+ <panel.string name="mature_check_adult_tooltip">
+ Les informations ou contenu de votre parcelle sont classés Adult.
+ </panel.string>
+ <panel.string name="landing_point_none">
+ (aucun)
+ </panel.string>
+ <panel.string name="push_restrict_text">
+ Pas de bousculades
+ </panel.string>
+ <panel.string name="push_restrict_region_text">
+ Pas de bousculades (les règles de la région priment)
+ </panel.string>
+ <text name="allow_label">
Autoriser les autres résidents à :
</text>
<check_box label="Modifier le terrain" name="edit land check" tool_tip="Si cette option est cochée, n&apos;importe qui peut terraformer votre terrain. Il vaut mieux ne pas cocher cette option pour toujours pouvoir modifer votre propre terrain."/>
- <check_box label="Créer des repères" name="check landmark"/>
<check_box label="Voler" name="check fly" tool_tip="Si cette option est cochée, les résidents peuvent voler sur votre terrain. Si elle n&apos;est pas cochée, ils ne pourront voler que lorsqu&apos;ils arrivent et passent au dessus de votre terrain."/>
<text left="152" name="allow_label2">
Créer des objets :
@@ -290,207 +332,124 @@ ou divisé.
</text>
<check_box label="Tous les résidents" left="285" name="check other scripts"/>
<check_box label="Groupe" left="395" name="check group scripts"/>
- <text length="1" name="land_options_label" type="string">
+ <text name="land_options_label">
Options du terrain :
</text>
<check_box label="Sécurisé (pas de dégâts)" name="check safe" tool_tip="Si cette option est cochée, le terrain est sécurisé et il n&apos;y pas de risques de dommages causés par des combats. Si elle est décochée, des dommages causés par les combats peuvent avoir lieu."/>
<check_box bottom="-140" label="Pas de bousculades" left="14" name="PushRestrictCheck" tool_tip="Empêche l&apos;utilisation de scripts causant des bousculades. Cette option est utile pour empêcher les comportements abusifs sur votre terrain."/>
<check_box bottom="-160" label="Afficher dans la recherche (30 L$/semaine) sous" name="ShowDirectoryCheck" tool_tip="Afficher la parcelle dans les résultats de recherche"/>
- <string name="search_enabled_tooltip">
- Permettre aux autres résidents de voir cette parcelle dans les résultats de recherche
- </string>
- <string name="search_disabled_small_tooltip">
- Cette option est désactivée car la superficie de cette parcelle est inférieure ou égale à 128 m².
-Seules les parcelles de grande taille peuvent apparaître dans la recherche.
- </string>
- <string name="search_disabled_permissions_tooltip">
- Cette option est désactivée car vous ne pouvez pas modifier les options de cette parcelle.
- </string>
<combo_box bottom="-160" left="286" name="land category with adult" width="146">
- <combo_item name="AnyCategory">
- Toutes catégories
- </combo_item>
- <combo_item name="LindenLocation">
- Appartenant aux Lindens
- </combo_item>
- <combo_item name="Adult">
- Adult
- </combo_item>
- <combo_item name="Arts&amp;Culture">
- Art et Culture
- </combo_item>
- <combo_item name="Business">
- Affaires
- </combo_item>
- <combo_item name="Educational">
- Éducation
- </combo_item>
- <combo_item name="Gaming">
- Jeux
- </combo_item>
- <combo_item name="Hangout">
- Favoris
- </combo_item>
- <combo_item name="NewcomerFriendly">
- Accueil pour les nouveaux
- </combo_item>
- <combo_item name="Parks&amp;Nature">
- Parcs et Nature
- </combo_item>
- <combo_item name="Residential">
- Résidentiel
- </combo_item>
- <combo_item name="Shopping">
- Shopping
- </combo_item>
- <combo_item name="Other">
- Autre
- </combo_item>
+ <combo_box.item label="Toutes catégories" name="item0"/>
+ <combo_box.item label="Appartenant aux Lindens" name="item1"/>
+ <combo_box.item label="Adult" name="item2"/>
+ <combo_box.item label="Art et Culture" name="item3"/>
+ <combo_box.item label="Affaires" name="item4"/>
+ <combo_box.item label="Éducation" name="item5"/>
+ <combo_box.item label="Jeux" name="item6"/>
+ <combo_box.item label="Favoris" name="item7"/>
+ <combo_box.item label="Accueil pour les nouveaux" name="item8"/>
+ <combo_box.item label="Parcs et Nature" name="item9"/>
+ <combo_box.item label="Résidentiel" name="item10"/>
+ <combo_box.item label="Shopping" name="item11"/>
+ <combo_box.item label="Autre" name="item12"/>
</combo_box>
<combo_box bottom="-160" left="286" name="land category" width="146">
- <combo_item name="AnyCategory">
- Toutes catégories
- </combo_item>
- <combo_item name="LindenLocation">
- Appartenant aux Lindens
- </combo_item>
- <combo_item name="Arts&amp;Culture">
- Art et Culture
- </combo_item>
- <combo_item name="Business">
- Affaires
- </combo_item>
- <combo_item name="Educational">
- Éducation
- </combo_item>
- <combo_item name="Gaming">
- Jeux
- </combo_item>
- <combo_item name="Hangout">
- Favoris
- </combo_item>
- <combo_item name="NewcomerFriendly">
- Accueil pour les nouveaux
- </combo_item>
- <combo_item name="Parks&amp;Nature">
- Parcs et Nature
- </combo_item>
- <combo_item name="Residential">
- Résidentiel
- </combo_item>
- <combo_item name="Shopping">
- Shopping
- </combo_item>
- <combo_item name="Other">
- Autre
- </combo_item>
+ <combo_box.item label="Toutes catégories" name="item0"/>
+ <combo_box.item label="Appartenant aux Lindens" name="item1"/>
+ <combo_box.item label="Art et Culture" name="item3"/>
+ <combo_box.item label="Affaires" name="item4"/>
+ <combo_box.item label="Éducation" name="item5"/>
+ <combo_box.item label="Jeux" name="item6"/>
+ <combo_box.item label="Favoris" name="item7"/>
+ <combo_box.item label="Accueil pour les nouveaux" name="item8"/>
+ <combo_box.item label="Parcs et Nature" name="item9"/>
+ <combo_box.item label="Résidentiel" name="item10"/>
+ <combo_box.item label="Shopping" name="item11"/>
+ <combo_box.item label="Autre" name="item12"/>
</combo_box>
- <button bottom="-160" label="?" label_selected="?" left="436" name="?"/>
<check_box bottom="-180" label="Contenu Mature" name="MatureCheck" tool_tip=""/>
- <string name="mature_check_mature">
- Contenu Mature
- </string>
- <string name="mature_check_adult">
- Contenu Adult
- </string>
- <string name="mature_check_mature_tooltip">
- Les informations ou contenu de votre parcelle sont classés Mature.
- </string>
- <string name="mature_check_adult_tooltip">
- Les informations ou contenu de votre parcelle sont classés Adult.
- </string>
- <text bottom="-200" length="1" name="Snapshot:" type="string">
+ <text bottom="-200" name="Snapshot:">
Photo :
</text>
<texture_picker bottom="-319" label="" name="snapshot_ctrl" tool_tip="Cliquez pour sélectionner une image"/>
<text bottom="-323" name="landing_point">
Lieu d&apos;arrivée : [LANDING]
</text>
- <string name="landing_point_none">
- (aucun)
- </string>
<button bottom="-323" label="Définir" label_selected="Définir" name="Set" tool_tip="Définit le point d&apos;arrivée des visiteurs. Définit l&apos;emplacement de votre avatar sur ce terrain."/>
- <button bottom="-323" label="Annuler" label_selected="Annuler" name="Clear" tool_tip="Libérer le lieu d&apos;arrivée."/>
- <text bottom="-343" length="1" name="Teleport Routing: " type="string">
+ <button bottom="-323" label="Annuler" label_selected="Annuler" name="Clear" tool_tip="Effacer le lieu d&apos;arrivée"/>
+ <text bottom="-343" name="Teleport Routing: ">
Règles de téléportation :
</text>
- <combo_box bottom="-343" left="140" name="landing type" tool_tip="Vous permet de paramétrer les téléportations sur votre terrain." width="140">
- <combo_item length="1" name="Blocked" type="string">
- Bloqué
- </combo_item>
- <combo_item length="1" name="LandingPoint" type="string">
- Lieu d&apos;arrivée fixe
- </combo_item>
- <combo_item length="1" name="Anywhere" type="string">
- Lieu d&apos;arrivée libre
- </combo_item>
+ <combo_box bottom="-343" left="140" name="landing type" tool_tip="Règles de téléportation - Choisissez les règles de téléportation sur votre terrain" width="140">
+ <combo_box.item label="Bloqué" name="Blocked"/>
+ <combo_box.item label="Lieu d&apos;arrivée fixe" name="LandingPoint"/>
+ <combo_box.item label="Lieu d&apos;arrivée libre" name="Anywhere"/>
</combo_box>
- <string name="push_restrict_text">
- Pas de bousculades
- </string>
- <string name="push_restrict_region_text">
- Pas de bousculades (les règles de la région priment)
- </string>
</panel>
<panel label="Médias" name="land_media_panel">
<text name="with media:" width="85">
- Type de média :
+ Type :
</text>
<combo_box left="97" name="media type" tool_tip="Indiquez s&apos;il s&apos;agit de l&apos;URL d&apos;un film, d&apos;une page web ou autre"/>
<text name="mime_type"/>
<text name="at URL:" width="85">
- URL du média :
+ URL du domicile :
</text>
<line_editor left="97" name="media_url"/>
<button label="Définir..." label_selected="Définir..." name="set_media_url"/>
+ <text name="CurrentURL:">
+ URL actuelle :
+ </text>
+ <button label="Réinitialiser..." label_selected="Réinitialiser..." name="reset_media_url"/>
+ <check_box label="Masquer l&apos;URL" left="97" name="hide_media_url" tool_tip="Si vous cochez cette option, les personnes non autorisées à accéder aux infos de cette parcelle ne verront pas l&apos;URL du média. Cette option n&apos;est pas disponible pour les fichiers HTML."/>
<text name="Description:">
Description :
</text>
<line_editor left="97" name="url_description" tool_tip="Texte affiché à côté du bouton Jouer/Charger"/>
- <text length="1" name="Media texture:" type="string">
+ <text name="Media texture:">
Remplacer
la texture :
</text>
<texture_picker label="" left="97" name="media texture" tool_tip="Cliquez pour sélectionner une image"/>
<text name="replace_texture_help">
- (Les objets avec cette texture affichent le film ou
-la page web quand vous cliquez sur la flèche Jouer.)
- </text>
- <text name="Options:">
- Options
-média :
+ Les objets avec cette texture affichent le film ou la page web quand vous cliquez sur la flèche Jouer.
+
+Sélectionnez l&apos;image miniature pour choisir une texture différente.
</text>
<check_box label="Échelle automatique" left="97" name="media_auto_scale" tool_tip="Si vous sélectionnez cette option, le contenu de cette parcelle sera automatiquement mis à l&apos;échelle. La qualité visuelle sera peut-être amoindrie mais vous n&apos;aurez à faire aucune autre mise à l&apos;échelle ou alignement."/>
- <check_box label="Média en boucle" name="media_loop" tool_tip="Jouer le média en boucle. Lorsque le média aura fini de jouer, il recommencera."/>
- <check_box label="Masquer l&apos;URL du média" left="97" name="hide_media_url" tool_tip="Si vous cochez cette option, les personnes non autorisées à accéder aux infos de cette parcelle ne verront pas l&apos;URL du média. Cette option n&apos;est pas disponible pour les fichiers HTML."/>
- <check_box label="Masquer l&apos;URL de la musique" name="hide_music_url" tool_tip="Si vous cochez cette option, les personnes non autorisées à accéder aux infos de cette parcelle ne verront pas l&apos;URL de la musique."/>
<text left="102" name="media_size" tool_tip="Taille du média Web, laisser 0 pour la valeur par défaut." width="105">
- Taille du média :
+ Taille :
</text>
<spinner left_delta="89" name="media_size_width" tool_tip="Taille du média Web, laisser 0 pour la valeur par défaut."/>
<spinner name="media_size_height" tool_tip="Taille du média Web, laisser 0 pour la valeur par défaut."/>
<text name="pixels">
pixels
</text>
- <text bottom_delta="-28" name="MusicURL:">
- URL de la
-musique :
+ <text name="Options:">
+ Options :
+ </text>
+ <check_box label="En boucle" name="media_loop" tool_tip="Jouer le média en boucle. Lorsque le média aura fini de jouer, il recommencera."/>
+ </panel>
+ <panel label="Audio" name="land_audio_panel">
+ <text name="MusicURL:">
+ URL de la musique :
</text>
- <line_editor bottom_delta="-12" left="97" name="music_url"/>
<text name="Sound:">
- Son :
+ Son :
</text>
- <check_box label="Limiter les gestes et sons d&apos;objet à cette parcelle" left="97" name="check sound local"/>
- <button label="?" label_selected="?" left="378" name="?"/>
+ <check_box label="Limiter les gestes et sons d&apos;objet à cette parcelle" name="check sound local"/>
<text name="Voice settings:">
- Voix :
+ Voix :
</text>
- <check_box label="Activer le chat vocal" left="97" name="parcel_enable_voice_channel"/>
- <check_box label="Activer le chat vocal (contrôlé par le domaine)" left="97" name="parcel_enable_voice_channel_is_estate_disabled"/>
- <check_box label="Limiter le chat vocal à cette parcelle" left="117" name="parcel_enable_voice_channel_parcel"/>
+ <check_box label="Activer le chat vocal" name="parcel_enable_voice_channel"/>
+ <check_box label="Activer la voix (contrôlé par le domaine)" name="parcel_enable_voice_channel_is_estate_disabled"/>
+ <check_box label="Limiter le chat vocal à cette parcelle" name="parcel_enable_voice_channel_parcel"/>
</panel>
<panel label="Accès" name="land_access_panel">
- <text length="1" name="Limit access to this parcel to:" type="string">
+ <panel.string name="estate_override">
+ Au moins une de ces options est définie au niveau du domaine.
+ </panel.string>
+ <text name="Limit access to this parcel to:">
Accès à cette parcelle
</text>
<check_box label="Autoriser l&apos;accès public" name="public_access"/>
@@ -498,19 +457,12 @@ musique :
Bloquer l&apos;accès aux résidents :
</text>
<check_box label="Qui n&apos;ont pas fourni leurs informations de paiement à Linden Lab" name="limit_payment" tool_tip="Aux résidents non identifés"/>
- <check_box label="Dont l&apos;âge n&apos;a pas été vérifié" name="limit_age_verified" tool_tip="Aux résidents dont l&apos;âge n&apos;a pas été vérifié. Pour plus d&apos;infos, consultez la page support.secondlife.com."/>
- <string name="estate_override">
- Au moins une de ces options est définie au niveau du domaine.
- </string>
+ <check_box label="Dont l&apos;âge n&apos;a pas été vérifié" name="limit_age_verified" tool_tip="Interdire les résidents qui n&apos;ont pas vérifié leur âge. Consultez la page [SUPPORT_SITE] pour plus d&apos;informations."/>
<check_box label="Autoriser l&apos;accès au groupe : [GROUP]" name="GroupCheck" tool_tip="Définir le groupe à l&apos;onglet Général."/>
<check_box label="Vendre des pass à :" name="PassCheck" tool_tip="Autoriser un accès temporaire à cette parcelle"/>
<combo_box name="pass_combo">
- <combo_item name="Anyone">
- Tout le monde
- </combo_item>
- <combo_item name="Group">
- Groupe
- </combo_item>
+ <combo_box.item label="Tout le monde" name="Anyone"/>
+ <combo_box.item label="Groupe" name="Group"/>
</combo_box>
<spinner label="Prix en L$ :" name="PriceSpin"/>
<spinner label="Durée en heures :" name="HoursSpin"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_activeim.xml b/indra/newview/skins/default/xui/fr/floater_activeim.xml
new file mode 100644
index 0000000000..18e3d66bb7
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_activeim.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_activeim" title="IM ACTIVE"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_animation_preview.xml b/indra/newview/skins/default/xui/fr/floater_animation_preview.xml
index 66e12be5cf..e630208973 100644
--- a/indra/newview/skins/default/xui/fr/floater_animation_preview.xml
+++ b/indra/newview/skins/default/xui/fr/floater_animation_preview.xml
@@ -1,165 +1,185 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Animation Preview" title="">
+ <floater.string name="failed_to_initialize">
+ Echec de l&apos;initialisation du mouvement
+ </floater.string>
+ <floater.string name="anim_too_long">
+ Le fichier d&apos;animation fait [LENGTH] secondes.
+
+La longueur maximale est de [MAX_LENGTH] secondes.
+ </floater.string>
+ <floater.string name="failed_file_read">
+ Impossible de lire le fichier d&apos;animation.
+
+[STATUS]
+ </floater.string>
+ <floater.string name="E_ST_OK">
+ Ok
+ </floater.string>
+ <floater.string name="E_ST_EOF">
+ Fichier incomplet.
+ </floater.string>
+ <floater.string name="E_ST_NO_CONSTRAINT">
+ Impossible de lire la définition des contraintes.
+ </floater.string>
+ <floater.string name="E_ST_NO_FILE">
+ Impossible d&apos;ouvrir le fichier BVH.
+ </floater.string>
+ <floater.string name="E_ST_NO_HIER">
+ En-tête HIERARCHY non valide.
+ </floater.string>
+ <floater.string name="E_ST_NO_JOINT">
+ Impossible de trouver ROOT ou JOINT.
+ </floater.string>
+ <floater.string name="E_ST_NO_NAME">
+ Impossible de trouver le nom JOINT.
+ </floater.string>
+ <floater.string name="E_ST_NO_OFFSET">
+ Impossible de trouver OFFSET.
+ </floater.string>
+ <floater.string name="E_ST_NO_CHANNELS">
+ Impossible de trouver les CHANNELS.
+ </floater.string>
+ <floater.string name="E_ST_NO_ROTATION">
+ Impossible d&apos;obtenir l&apos;ordre de rotation.
+ </floater.string>
+ <floater.string name="E_ST_NO_AXIS">
+ Impossible d&apos;obtenir l&apos;axe de rotation.
+ </floater.string>
+ <floater.string name="E_ST_NO_MOTION">
+ Impossible de trouver MOTION.
+ </floater.string>
+ <floater.string name="E_ST_NO_FRAMES">
+ Impossible d&apos;obtenir le nombre de cadres.
+ </floater.string>
+ <floater.string name="E_ST_NO_FRAME_TIME">
+ Impossible d&apos;obtenir le temps du cadre.
+ </floater.string>
+ <floater.string name="E_ST_NO_POS">
+ Impossible de trouver les valeurs de la position.
+ </floater.string>
+ <floater.string name="E_ST_NO_ROT">
+ Impossible de trouver les valeurs de rotation.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_FILE">
+ Impossible d&apos;ouvrir le fichier de traduction.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_HEADER">
+ Impossible de lire l&apos;en-tête de traduction.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_NAME">
+ Impossible de lire la traduction.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_IGNORE">
+ Impossible de lire la traduction.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_RELATIVE">
+ Impossible de lire la valeur de traduction relative.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_OUTNAME">
+ Impossible de lire la traduction.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_MATRIX">
+ Impossible de lire la matrice de traduction.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_MERGECHILD">
+ Impossible de trouver le nom mergechild.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_MERGEPARENT">
+ Impossible de trouver le nom mergeparent.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_PRIORITY">
+ Impossible de définir la valeur de la priorité.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_LOOP">
+ Impossible de définir la valeur de la boucle
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_EASEIN">
+ Impossible de trouver les valeurs easeIn.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_EASEOUT">
+ Impossible de trouver les valeurs easeOut.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_HAND">
+ Impossible d&apos;obtenir la valeur hand morph.
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_EMOTE">
+ Impossible de lire le nom emote.
+ </floater.string>
<text name="name_label">
Nom :
</text>
<text name="description_label">
Description :
</text>
- <spinner label="Priorité" name="priority" tool_tip="Contrôle quelles animations peuvent êtres écrasées par cette animation."/>
- <text name="preview_label" width="110">
- Prévisualiser pendant
- </text>
- <combo_box label="" name="preview_base_anim" tool_tip="Utilisez cette option pour tester votre animation pendant que votre avatar fait des choses banales." left_delta="116" width="124">
- <combo_item name="Standing">
- Debout
- </combo_item>
- <combo_item name="Walking">
- En train de marcher
- </combo_item>
- <combo_item name="Sitting">
- Assis
- </combo_item>
- <combo_item name="Flying">
- En train de voler
- </combo_item>
- </combo_box>
- <check_box left="6" label="Boucle" name="loop_check" tool_tip="Joue cette animation en boucle."/>
- <spinner left="76" label_width="55" width="105" label="Début (%)" name="loop_in_point" tool_tip="Définit le moment de l&apos;animation où la boucle repart."/>
- <spinner left="195" label="Fin (%)" name="loop_out_point" tool_tip="Définit le moment de l&apos;animation où la boucle finit."/>
- <text name="hand_label" width="110">
- Mouvement de main
+ <spinner label="Priorité" name="priority" tool_tip="Contrôle quelles autres animations peuvent être remplacées par cette animation"/>
+ <check_box label="Boucle" left="6" name="loop_check" tool_tip="Lit cette animation en boucle"/>
+ <spinner label="Début (%)" label_width="65" name="loop_in_point" tool_tip="Définit un point de l&apos;animation auquel retourne la boucle" width="105"/>
+ <spinner label="Fin (%)" name="loop_out_point" tool_tip="Définit un point de l&apos;animation qui met fin à la boucle"/>
+ <text name="hand_label">
+ Mouvement de
+main
</text>
- <combo_box label="" name="hand_pose_combo" tool_tip="Contrôle le mouvement des mains au cours de l&apos;animation" left_delta="116" width="124">
- <combo_item name="Spread">
- Doigts écartés
- </combo_item>
- <combo_item name="Relaxed">
- Détendues
- </combo_item>
- <combo_item name="PointBoth">
- Pointer (les deux)
- </combo_item>
- <combo_item name="Fist">
- Poing
- </combo_item>
- <combo_item name="RelaxedLeft">
- Détendue (gauche)
- </combo_item>
- <combo_item name="PointLeft">
- Pointer (gauche)
- </combo_item>
- <combo_item name="FistLeft">
- Poing (gauche)
- </combo_item>
- <combo_item name="RelaxedRight">
- Détendue (droite)
- </combo_item>
- <combo_item name="PointRight">
- Pointer (droite)
- </combo_item>
- <combo_item name="FistRight">
- Poing (droite)
- </combo_item>
- <combo_item name="SaluteRight">
- Saluer (droite)
- </combo_item>
- <combo_item name="Typing">
- Taper
- </combo_item>
- <combo_item name="PeaceRight">
- Paix (main droite)
- </combo_item>
+ <combo_box label="" name="hand_pose_combo" tool_tip="Contrôle ce que font les mains pendant l&apos;animation">
+ <combo_box.item label="Espacement" name="Spread"/>
+ <combo_box.item label="Détendues" name="Relaxed"/>
+ <combo_box.item label="Pointer (les deux)" name="PointBoth"/>
+ <combo_box.item label="Poing" name="Fist"/>
+ <combo_box.item label="Détendue (gauche)" name="RelaxedLeft"/>
+ <combo_box.item label="Pointer (gauche)" name="PointLeft"/>
+ <combo_box.item label="Poing (gauche)" name="FistLeft"/>
+ <combo_box.item label="Détendue (droite)" name="RelaxedRight"/>
+ <combo_box.item label="Pointer (droite)" name="PointRight"/>
+ <combo_box.item label="Poing (droite)" name="FistRight"/>
+ <combo_box.item label="Saluer (droite)" name="SaluteRight"/>
+ <combo_box.item label="Taper" name="Typing"/>
+ <combo_box.item label="Paix (main droite)" name="PeaceRight"/>
</combo_box>
<text name="emote_label">
Expression
</text>
- <combo_box label="" name="emote_combo" tool_tip="Contrôle l&apos;expression du visage au cours de l&apos;animation." left_delta="116" width="124">
- <combo_item name="[None]">
- [None]
- </combo_item>
- <combo_item name="Aaaaah">
- Aaaaah
- </combo_item>
- <combo_item name="Afraid">
- Effrayé
- </combo_item>
- <combo_item name="Angry">
- En colère
- </combo_item>
- <combo_item name="BigSmile">
- Grand sourire
- </combo_item>
- <combo_item name="Bored">
- Ennui
- </combo_item>
- <combo_item name="Cry">
- Pleurer
- </combo_item>
- <combo_item name="Disdain">
- Mépris
- </combo_item>
- <combo_item name="Embarrassed">
- Gêne
- </combo_item>
- <combo_item name="Frown">
- Froncer les sourcils
- </combo_item>
- <combo_item name="Kiss">
- Embrasser
- </combo_item>
- <combo_item name="Laugh">
- Rire
- </combo_item>
- <combo_item name="Plllppt">
- Plllppt
- </combo_item>
- <combo_item name="Repulsed">
- Dégoût
- </combo_item>
- <combo_item name="Sad">
- Triste
- </combo_item>
- <combo_item name="Shrug">
- Hausser les épaules
- </combo_item>
- <combo_item name="Smile">
- Sourire
- </combo_item>
- <combo_item name="Surprise">
- Surprise
- </combo_item>
- <combo_item name="Wink">
- Clin d&apos;Å“il
- </combo_item>
- <combo_item name="Worry">
- Soucis
- </combo_item>
+ <combo_box label="" name="emote_combo" tool_tip="Contrôle ce que fait le visage pendant l&apos;animation">
+ <combo_box.item label="(aucun)" name="[None]"/>
+ <combo_box.item label="Aaaaah" name="Aaaaah"/>
+ <combo_box.item label="Effrayé" name="Afraid"/>
+ <combo_box.item label="En colère" name="Angry"/>
+ <combo_box.item label="Grand sourire" name="BigSmile"/>
+ <combo_box.item label="Ennui" name="Bored"/>
+ <combo_box.item label="Pleurer" name="Cry"/>
+ <combo_box.item label="Mépris" name="Disdain"/>
+ <combo_box.item label="Gêne" name="Embarrassed"/>
+ <combo_box.item label="Froncer les sourcils" name="Frown"/>
+ <combo_box.item label="Embrasser" name="Kiss"/>
+ <combo_box.item label="Rire" name="Laugh"/>
+ <combo_box.item label="Plllppt" name="Plllppt"/>
+ <combo_box.item label="Dégoût" name="Repulsed"/>
+ <combo_box.item label="Triste" name="Sad"/>
+ <combo_box.item label="Hausser les épaules" name="Shrug"/>
+ <combo_box.item label="Sourire" name="Smile"/>
+ <combo_box.item label="Surprise" name="Surprise"/>
+ <combo_box.item label="Clin d&apos;Å“il" name="Wink"/>
+ <combo_box.item label="Soucis" name="Worry"/>
</combo_box>
- <spinner label_width="65" label="Transition &#10;début (s)" name="ease_in_time" tool_tip="Durée (en secondes) pendant laquelle l&apos;animation s&apos;intègre au mouvement."/>
- <spinner label_width="65" left="160" width="125" label="Transition &#10;fin (s)" name="ease_out_time" tool_tip="Durée (en secondes) pendant laquelle l&apos;animation disparaît du mouvement."/>
- <button label="" name="play_btn" tool_tip="Jouer/Arrêter votre animation." bottom_delta="-48"/>
+ <text name="preview_label">
+ Prévisualiser
+pendant
+ </text>
+ <combo_box label="" name="preview_base_anim" tool_tip="Utilisez cette option pour tester votre animation pendant que votre avatar fait des choses banales.">
+ <combo_box.item label="Debout" name="Standing"/>
+ <combo_box.item label="Marche" name="Walking"/>
+ <combo_box.item label="Assis" name="Sitting"/>
+ <combo_box.item label="Vol" name="Flying"/>
+ </combo_box>
+ <spinner label="Transition début (s)" name="ease_in_time" tool_tip="Durée (en secondes) de l&apos;entrée en fondu de l&apos;animation"/>
+ <spinner label="Transition fin (s)" name="ease_out_time" tool_tip="Durée (en secondes) de la sortie en fondu de l&apos;animation"/>
+ <button label="" name="play_btn" tool_tip="Lire/pauser votre animation"/>
<button label="" name="stop_btn" tool_tip="Arrêter le playback"/>
<slider label="" name="playback_slider"/>
<text name="bad_animation_text">
Impossible de lire le fichier d&apos;animation.
-Nous recommandons les fichiers BVH extraits de
-Poser 4.
+Nous recommandons les fichiers BVH extraits de Poser 4.
</text>
<button label="Annuler" name="cancel_btn"/>
<button label="Charger ([AMOUNT] L$)" name="ok_btn"/>
- <string name="failed_to_initialize">
- Echec de l&apos;initialisation du mouvement
- </string>
- <string name="anim_too_long">
- Le fichier d&apos;animation fait [LENGTH] secondes.
-
-La longueur maximale est de [MAX_LENGTH] secondes.
- </string>
- <string name="failed_file_read">
- Impossible de lire le fichier d&apos;animation.
-
-[STATUS]
- </string>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_auction.xml b/indra/newview/skins/default/xui/fr/floater_auction.xml
index 6fe3f66e13..6cef2a3591 100644
--- a/indra/newview/skins/default/xui/fr/floater_auction.xml
+++ b/indra/newview/skins/default/xui/fr/floater_auction.xml
@@ -1,18 +1,11 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_auction" title="Commencer la vente de terrain Linden">
- <check_box label="Inclure le marquage de sélection jaune" name="fence_check" />
- <combo_box name="saletype_combo">
- <combo_item name="Auction">
- Enchères
- </combo_item>
- <combo_item name="FirstLand">
- Premier terrain
- </combo_item>
- </combo_box>
- <button label="Capture d&apos;écran" label_selected="Capture d&apos;écran"
- name="snapshot_btn" width="110" />
- <button label="OK" label_selected="OK" name="ok_btn" left_delta="114"/>
- <text name="already for sale">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_auction" title="COMMENCER LA VENTE DE TERRAINS LINDEN">
+ <floater.string name="already for sale">
Vous ne pouvez pas mettre aux enchères des parcelles déjà en vente.
- </text>
+ </floater.string>
+ <check_box initial_value="true" label="Inclure le marquage de sélection jaune" name="fence_check"/>
+ <button label="Capture d&apos;écran" label_selected="Capture d&apos;écran" name="snapshot_btn" width="110"/>
+ <button label="Vendre à n&apos;importe qui" label_selected="Vendre à n&apos;importe qui" name="sell_to_anyone_btn"/>
+ <button label="Effacer les paramètres" label_selected="Effacer les paramètres" name="reset_parcel_btn"/>
+ <button label="Commencer les enchères" label_selected="Commencer les enchères" name="start_auction_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_avatar_picker.xml b/indra/newview/skins/default/xui/fr/floater_avatar_picker.xml
index 01b4c944f3..e784bda2e5 100644
--- a/indra/newview/skins/default/xui/fr/floater_avatar_picker.xml
+++ b/indra/newview/skins/default/xui/fr/floater_avatar_picker.xml
@@ -1,42 +1,47 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="avatarpicker" title="Choisir le résident">
+<floater name="avatarpicker" title="CHOISIR UN RÉSIDENT">
+ <floater.string name="not_found">
+ &apos;[TEXT]&apos; introuvable
+ </floater.string>
+ <floater.string name="no_one_near">
+ Personne près de vous
+ </floater.string>
+ <floater.string name="no_results">
+ Aucun résultat
+ </floater.string>
+ <floater.string name="searching">
+ Recherche...
+ </floater.string>
+ <string label="OK" label_selected="OK" name="Select">
+ Sélectionner
+ </string>
+ <string name="Close">
+ Fermer
+ </string>
<tab_container name="ResidentChooserTabs">
<panel label="Rechercher" name="SearchPanel">
<text name="InstructSearchResidentName">
- Saisissez une partie du nom du résident :
+ Saisissez une partie du nom du résident :
</text>
- <button label="Trouver" label_selected="Trouver" name="Find"/>
+ <button label="OK" label_selected="OK" name="Find"/>
</panel>
- <panel label="Cartes de visite" name="CallingCardsPanel">
- <text name="InstructSelectCallingCard">
- Sélectionnez une carte de visite :
+ <panel label="Amis" name="FriendsPanel">
+ <text name="InstructSelectFriend">
+ Sélectionner une personne :
</text>
</panel>
<panel label="Près de moi" name="NearMePanel">
<text name="InstructSelectResident">
- Choisir un résident
-près de vous :
+ Sélectionner une personne près de vous :
</text>
- <button font="SansSerifSmall" label="Rafraîchir la liste" label_selected="Rafraîchir la liste" name="Refresh" left_delta="10" width="105"/>
- <slider label="Distance" name="near_me_range" bottom_delta="-36"/>
+ <slider bottom_delta="-36" label="Distance" name="near_me_range"/>
<text name="meters">
mètres
</text>
- <scroll_list bottom_delta="-169" height="159" name="NearMe" />
+ <button font="SansSerifSmall" label="Rafraîchir la liste" label_selected="Rafraîchir la liste" left_delta="10" name="Refresh" width="105"/>
+ <scroll_list bottom_delta="-169" height="159" name="NearMe"/>
</panel>
</tab_container>
- <button label="Sélectionner" label_selected="Sélectionner" name="Select"/>
- <button label="Annuler" label_selected="Annuler" name="Cancel"/>
- <string name="not_found">
- &apos;[TEXT]&apos; introuvable
- </string>
- <string name="no_one_near">
- Il n'y a personne près de vous
- </string>
- <string name="no_results">
- Aucun résultat
- </string>
- <string name="searching">
- Recherche...
- </string>
+ <button label="OK" label_selected="OK" name="ok_btn"/>
+ <button label="Annuler" label_selected="Annuler" name="cancel_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_avatar_textures.xml b/indra/newview/skins/default/xui/fr/floater_avatar_textures.xml
index f4e3a1615c..142e13640a 100644
--- a/indra/newview/skins/default/xui/fr/floater_avatar_textures.xml
+++ b/indra/newview/skins/default/xui/fr/floater_avatar_textures.xml
@@ -1,31 +1,42 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="avatar_texture_debug" title="Textures de l&apos;avatar">
+<floater name="avatar_texture_debug" title="TEXTURES DES AVATARS">
+ <floater.string name="InvalidAvatar">
+ AVATAR NON VALIDE
+ </floater.string>
<text name="label">
Textures fixées
</text>
<text name="composite_label">
Textures composées
</text>
- <button label="Vider ces ID dans la console" label_selected="Vider" name="Dump" left="-185" width="175"/>
+ <button label="Vider ces ID dans la console" label_selected="Vider" left="-185" name="Dump" width="175"/>
<texture_picker label="Cheveux" name="hair-baked"/>
- <texture_picker label="Cheveux" name="hair"/>
+ <texture_picker label="Cheveux" name="hair_grain"/>
+ <texture_picker label="Alpha cheveux" name="hair_alpha"/>
<texture_picker label="Tête" name="head-baked"/>
- <texture_picker label="Maquillage" name="head bodypaint"/>
+ <texture_picker label="Maquillage" name="head_bodypaint"/>
+ <texture_picker label="Alpha tête" name="head_alpha"/>
+ <texture_picker label="Tatouage tête" name="head_tattoo"/>
<texture_picker label="Yeux" name="eyes-baked"/>
- <texture_picker label="Å’il" name="iris"/>
+ <texture_picker label="Å’il" name="eyes_iris"/>
+ <texture_picker label="Alpha yeux" name="eyes_alpha"/>
<texture_picker label="Haut du corps" name="upper-baked"/>
- <texture_picker label="Tatouage (haut du corps)" name="upper bodypaint"/>
- <texture_picker label="Tricot" name="undershirt"/>
- <texture_picker label="Gants" name="gloves"/>
- <texture_picker label="Chemise" name="shirt"/>
- <texture_picker label="Veste (haut)" name="upper jacket"/>
+ <texture_picker label="Peinture corporelle haut" name="upper_bodypaint"/>
+ <texture_picker label="Sous-vêtements (homme)" name="upper_undershirt"/>
+ <texture_picker label="Gants" name="upper_gloves"/>
+ <texture_picker label="Chemise" name="upper_shirt"/>
+ <texture_picker label="Veste (haut)" name="upper_jacket"/>
+ <texture_picker label="Alpha haut" name="upper_alpha"/>
+ <texture_picker label="Tatouage haut" name="upper_tattoo"/>
<texture_picker label="Bas du corps" name="lower-baked"/>
- <texture_picker label="Tatouage (bas du corps)" name="lower bodypaint"/>
- <texture_picker label="Sous-vêtements" name="underpants"/>
- <texture_picker label="Chaussettes" name="socks"/>
- <texture_picker label="Chaussures" name="shoes"/>
- <texture_picker label="Pantalon" name="pants"/>
- <texture_picker label="Veste" name="lower jacket"/>
+ <texture_picker label="Peinture corporelle bas" name="lower_bodypaint"/>
+ <texture_picker label="Sous-vêtements (femme)" name="lower_underpants"/>
+ <texture_picker label="Chaussettes" name="lower_socks"/>
+ <texture_picker label="Chaussures" name="lower_shoes"/>
+ <texture_picker label="Pantalon" name="lower_pants"/>
+ <texture_picker label="Veste" name="lower_jacket"/>
+ <texture_picker label="Alpha bas" name="lower_alpha"/>
+ <texture_picker label="Tatouage bas" name="lower_tattoo"/>
<texture_picker label="Jupe" name="skirt-baked"/>
<texture_picker label="Jupe" name="skirt"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_beacons.xml b/indra/newview/skins/default/xui/fr/floater_beacons.xml
index 0b060983ee..778d92793b 100644
--- a/indra/newview/skins/default/xui/fr/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/fr/floater_beacons.xml
@@ -1,15 +1,21 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="beacons" title="Balises">
+<floater name="beacons" title="BALISES">
<panel name="beacons_panel">
- <check_box label="Objets scriptés avec Toucher uniquement" name="touch_only"/>
- <check_box label="Objets scriptés" name="scripted"/>
- <check_box label="Objets physiques" name="physical"/>
- <check_box label="Sources sonores" name="sounds"/>
- <check_box label="Sources de particules" name="particles"/>
- <check_box label="Mettre en surbrillance" name="highlights"/>
- <check_box label="Montrer les balises" name="beacons"/>
- <text name="beacon_width_label">
- Largeur de la balise :
+ <text name="label_show">
+ Afficher :
+ </text>
+ <check_box label="Balises" name="beacons"/>
+ <check_box label="Surbrillances" name="highlights"/>
+ <text name="beacon_width_label" tool_tip="Largeur de la balise">
+ Largeur :
</text>
+ <text name="label_objects">
+ Pour ces objets :
+ </text>
+ <check_box label="Physique" name="physical"/>
+ <check_box label="Scripté" name="scripted"/>
+ <check_box label="Toucher uniquement" name="touch_only"/>
+ <check_box label="Sources sonores" name="sounds"/>
+ <check_box label="Sources des particules" name="particles"/>
</panel>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_build_options.xml b/indra/newview/skins/default/xui/fr/floater_build_options.xml
index 3451c2de4c..cad00ea866 100644
--- a/indra/newview/skins/default/xui/fr/floater_build_options.xml
+++ b/indra/newview/skins/default/xui/fr/floater_build_options.xml
@@ -1,8 +1,11 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="build options floater" title="Options de la grille">
- <spinner label="Unité (mètres)" name="GridResolution" />
- <spinner label="Mesures (mètres)" name="GridDrawSize" />
- <check_box label="Activer la fixation des sous-unités" name="GridSubUnit" />
- <check_box label="Afficher les sections transversales" name="GridCrossSection" />
- <slider label="Opacité de la grille" name="GridOpacity" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="build options floater" title="OPTIONS DE LA GRILLE">
+ <spinner label="Unités (mètres)" name="GridResolution"/>
+ <spinner label="Mesures (mètres)" name="GridDrawSize"/>
+ <check_box label="Fixation des sous-unités" name="GridSubUnit"/>
+ <check_box label="Afficher les sections transversales" name="GridCrossSection"/>
+ <text name="grid_opacity_label" tool_tip="Opacité de la grille">
+ Opacité :
+ </text>
+ <slider label="Opacité de la grille" name="GridOpacity"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_bulk_perms.xml b/indra/newview/skins/default/xui/fr/floater_bulk_perms.xml
index b868aa33ad..0552cd3108 100644
--- a/indra/newview/skins/default/xui/fr/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/fr/floater_bulk_perms.xml
@@ -1,44 +1,54 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterbulkperms" title="Changement des droits relatifs au contenu">
- <text name="applyto">
- Types de contenu
- </text>
+<floater name="floaterbulkperms" title="MODIFIER LES DROITS RELATIFS AU CONTENU">
+ <floater.string name="nothing_to_modify_text">
+ La sélection contient des contenus non modifiables.
+ </floater.string>
+ <floater.string name="status_text">
+ Permissions paramétrées sur [NAME]
+ </floater.string>
+ <floater.string name="start_text">
+ Demande de changement des droits lancée...
+ </floater.string>
+ <floater.string name="done_text">
+ Demande de changement des droits finie.
+ </floater.string>
<check_box label="Animation" name="check_animation"/>
+ <icon name="icon_animation" tool_tip="Animation"/>
<check_box label="Parties du corps" name="check_bodypart"/>
+ <icon name="icon_bodypart" tool_tip="Parties du corps"/>
<check_box label="Habits" name="check_clothing"/>
+ <icon name="icon_clothing" tool_tip="Habits"/>
<check_box label="Gestes" name="check_gesture"/>
- <check_box label="Repères" name="check_landmark"/>
+ <icon name="icon_gesture" tool_tip="Gestes"/>
<check_box label="Notes" name="check_notecard"/>
+ <icon name="icon_notecard" tool_tip="Notes"/>
<check_box label="Objets" name="check_object"/>
+ <icon name="icon_object" tool_tip="Objets"/>
<check_box label="Scripts" name="check_script"/>
+ <icon name="icon_script" tool_tip="Scripts"/>
<check_box label="Sons" name="check_sound"/>
+ <icon name="icon_sound" tool_tip="Sons"/>
<check_box label="Textures" name="check_texture"/>
- <button label="Tout cocher" label_selected="Tout" name="check_all"/>
- <button label="Tout décocher" label_selected="Aucun" name="check_none"/>
+ <icon name="icon_texture" tool_tip="Textures"/>
+ <button label="√ Tout" label_selected="Tout" name="check_all"/>
+ <button label="Effacer" label_selected="Aucun" name="check_none"/>
<text name="newperms">
- Nouveaux droits
+ Nouvelles permissions
+ </text>
+ <text name="GroupLabel">
+ Groupe :
</text>
- <check_box label="Partager avec le groupe" name="share_with_group"/>
- <check_box label="Autoriser tout le monde à copier" name="everyone_copy"/>
+ <check_box label="Partager" name="share_with_group"/>
+ <text name="AnyoneLabel">
+ N&apos;importe qui :
+ </text>
+ <check_box label="Copier" name="everyone_copy"/>
<text name="NextOwnerLabel">
- Le prochain propriétaire pourra :
+ Le prochain propriétaire :
</text>
<check_box label="Modifier" name="next_owner_modify"/>
<check_box label="Copier" name="next_owner_copy"/>
- <check_box label="Revendre/Donner" name="next_owner_transfer"/>
- <button label="Aide" name="help"/>
- <button label="Appliquer" name="apply"/>
- <button label="Fermer" name="close"/>
- <string name="nothing_to_modify_text">
- La sélection contient des contenus non modifiables.
- </string>
- <string name="status_text">
- Permissions paramétrées sur [NAME]
- </string>
- <string name="start_text">
- Demande de changement des droits lancée...
- </string>
- <string name="done_text">
- Demande de changement des droits finie.
- </string>
+ <check_box initial_value="true" label="Transférer" name="next_owner_transfer" tool_tip="Le prochain propriétaire peut donner ou revendre cet objet"/>
+ <button label="Ok" name="apply"/>
+ <button label="Annuler" name="close"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_bumps.xml b/indra/newview/skins/default/xui/fr/floater_bumps.xml
index e12c7ed17d..34b33bbd6b 100644
--- a/indra/newview/skins/default/xui/fr/floater_bumps.xml
+++ b/indra/newview/skins/default/xui/fr/floater_bumps.xml
@@ -1,21 +1,24 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_bumps" title="Collisions, coups et bousculades">
- <text name="none_detected">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_bumps" title="COLLISIONS, COUPS ET BOUSCULADES">
+ <floater.string name="none_detected">
Aucun détecté
- </text>
- <text name="bump">
+ </floater.string>
+ <floater.string name="bump">
[TIME] [FIRST] [LAST] est entré en collision avec vous
- </text>
- <text name="llpushobject">
+ </floater.string>
+ <floater.string name="llpushobject">
[TIME] [FIRST] [LAST] vous a bousculé avec un script
- </text>
- <text name="selected_object_collide">
+ </floater.string>
+ <floater.string name="selected_object_collide">
[TIME] [FIRST] [LAST] vous a donné un coup avec un objet
- </text>
- <text name="scripted_object_collide">
+ </floater.string>
+ <floater.string name="scripted_object_collide">
[TIME] [FIRST] [LAST] vous a donné un coup avec un objet scripté
- </text>
- <text name="physical_object_collide">
+ </floater.string>
+ <floater.string name="physical_object_collide">
[TIME] [FIRST] [LAST] vous a donné un coup avec un objet physique
- </text>
+ </floater.string>
+ <floater.string name="timeStr">
+ [[hour,datetime,slt]:[min,datetime,slt]]
+ </floater.string>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_buy_contents.xml b/indra/newview/skins/default/xui/fr/floater_buy_contents.xml
index 916b270500..7aa142b13e 100644
--- a/indra/newview/skins/default/xui/fr/floater_buy_contents.xml
+++ b/indra/newview/skins/default/xui/fr/floater_buy_contents.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_buy_contents" title="Acheter ce contenu">
+<floater name="floater_buy_contents" title="ACHETER DES CONTENUS">
<text name="contains_text">
[NAME] contient :
</text>
diff --git a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
index 85d67218d3..4ca251f3d9 100644
--- a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
@@ -1,69 +1,66 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="buy currency" title="Acheter des L$">
- <text left="5" name="info_buying">
- Achat de L$ :
- </text>
- <text left="5" name="info_cannot_buy" right="-5">
- Impossible d&apos;acheter maintenant :
- </text>
+<floater name="buy currency" title="ACHETER DES L$">
+ <floater.string name="buy_currency">
+ Achetez [LINDENS] L$ pour environ [LOCALAMOUNT]
+ </floater.string>
<text left="5" name="info_need_more" right="-5">
- Vous avez besoin de plus de devises:
+ Vous avez besoin de plus de L$
</text>
- <text name="error_message">
- Quelque chose ne va pas.
- </text>
- <button label="Aller sur le site" name="error_web"/>
<text name="contacting">
En train de contacter le Lindex...
</text>
- <text name="buy_action_unknown" right="-5">
- Acheter des L$ sur le marché du LindeX
+ <text left="5" name="info_buying">
+ Acheter des L$
</text>
- <text name="buy_action">
- [NAME] L$ [PRICE]
+ <text name="balance_label">
+ J&apos;ai
+ </text>
+ <text name="balance_amount">
+ [AMT] L$
</text>
<text name="currency_action">
- Acheter
+ Je veux acheter
</text>
- <line_editor name="currency_amt" width="65">
+ <text name="currency_label">
+ L$
+ </text>
+ <line_editor label="L$" name="currency_amt" width="65">
1234
</line_editor>
- <text name="currency_est" width="138" left_delta="68">
- L$ pour environ [USD] US$
- </text>
- <text name="getting_data" width="138">
- Obtention des données...
+ <text name="buying_label">
+ Pour
</text>
- <text name="balance_label">
- Actuellement, vous avez
+ <text left_delta="68" name="currency_est" width="138">
+ environ [LOCALAMOUNT]
</text>
- <text name="balance_amount">
- [AMT] L$
- </text>
- <text name="buying_label">
- Vous achetez
+ <text name="getting_data" width="138">
+ Estimation en cours...
</text>
- <text name="buying_amount">
- [AMT] L$
+ <text name="buy_action">
+ [NAME] L$ [PRICE]
</text>
<text name="total_label">
- Votre solde sera de
+ Mon nouveau solde sera de
</text>
<text name="total_amount">
[AMT] L$
</text>
- <text name="purchase_warning_repurchase" height="48" bottom_delta="-64" right="-10">
- En confirmant cette transaction, vous achetez
-uniquement les devises. Vous devrez recommencer
-cette opération.
+ <text name="currency_links">
+ [http://www.secondlife.com/my/account/payment_method_management.php?lang=fr-FR payment method] | [http://www.secondlife.com/my/account/currency.php?lang=fr-FR currency] | [http://www.secondlife.com/my/account/exchange_rates.php?lang=fr-FR exchange rate]
+ </text>
+ <text name="exchange_rate_note">
+ Saisissez à nouveau le montant pour voir le taux de change actuel.
</text>
- <text name="purchase_warning_notenough" bottom_delta="16">
- Vous n&apos;achetez pas assez de devises.
-Veuillez saisir un montant plus élevé.
+ <text name="purchase_warning_repurchase">
+ La confirmation de cet achat n&apos;achète que des L$, pas l&apos;objet.
+ </text>
+ <text bottom_delta="16" name="purchase_warning_notenough">
+ Vous n&apos;achetez pas assez de L$. Veuillez augmenter le montant.
</text>
<button label="Acheter" name="buy_btn"/>
<button label="Annuler" name="cancel_btn"/>
- <string name="buy_currency">
- Acheter [LINDENS] L$ pour environ [USD] US$
- </string>
+ <text left="5" name="info_cannot_buy" right="-5">
+ Achat impossible
+ </text>
+ <button label="Accéder au Web" name="error_web"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_buy_land.xml b/indra/newview/skins/default/xui/fr/floater_buy_land.xml
index 80b40ca5e3..1d7eeca3c4 100644
--- a/indra/newview/skins/default/xui/fr/floater_buy_land.xml
+++ b/indra/newview/skins/default/xui/fr/floater_buy_land.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="buy land" title="Acheter le terrain">
+<floater name="buy land" title="ACHETER DU TERRAIN">
<text name="region_name_label">
Région :
</text>
@@ -36,6 +36,7 @@
<text name="covenant_text">
Vous devez accepter le règlement du domaine :
</text>
+ <text left="470" name="covenant_timestamp_text"/>
<text_editor name="covenant_editor">
Chargement...
</text_editor>
@@ -50,15 +51,15 @@
Taille :
</text>
<text name="info_size">
- 1024 m²
+ 1 024 m²
</text>
<text name="info_price_label">
Prix :
</text>
<text name="info_price">
1500 L$
- (1,1 L$/m²)
- vendu avec objets
+(1,1 L$/m²)
+vendu avec objets
</text>
<text name="info_action" width="380">
Si vous achetez ce terrain :
@@ -74,21 +75,15 @@
Seuls les membres Premium peuvent posséder du terrain.
</text>
<combo_box name="account_level">
- <combo_item name="US$9.95/month,billedmonthly">
- 9,95 US$/mois, facturation mensuelle
- </combo_item>
- <combo_item name="US$7.50/month,billedquarterly">
- 7,50 US$/mois, facturation trimestrielle
- </combo_item>
- <combo_item name="US$6.00/month,billedannually">
- 6,00 US$/mois, facturation annuelle
- </combo_item>
+ <combo_box.item label="9,95 US$/mois, facturation mensuelle" name="US$9.95/month,billedmonthly"/>
+ <combo_box.item label="7,50 US$/mois, facturation trimestrielle" name="US$7.50/month,billedquarterly"/>
+ <combo_box.item label="6,00 US$/mois, facturation annuelle" name="US$6.00/month,billedannually"/>
</combo_box>
<text name="land_use_action">
Augmentez vos frais d&apos;occupation de terrain à 40 US$/mois.
</text>
<text name="land_use_reason">
- Vous êtes propriétaire de 1 309 m² de terrain.
+ Vous détenez 1 309 m² de terrain.
Cette parcelle fait 512 m².
</text>
<text name="purchase_action">
@@ -104,12 +99,12 @@ Cette parcelle fait 512 m².
1000
</line_editor>
<text name="currency_est">
- pour environ [AMOUNT2] US$
+ pour environ [LOCAL_AMOUNT]
</text>
<text name="currency_balance">
Vous avez 2 100 L$.
</text>
- <check_box label="Supprimer [AMOUNT] mètres carrés de votre contribution au groupe." name="remove_contribution"/>
+ <check_box label="Enlever [AMOUNT] m² de contribution du groupe." name="remove_contribution"/>
<button label="Acheter" name="buy_btn"/>
<button label="Annuler" name="cancel_btn"/>
<string name="can_resell">
@@ -186,26 +181,26 @@ Sélectionnez une zone plus petite.
Avec votre compte, vous pouvez posséder du terrain.
</string>
<string name="land_holdings">
- Vous possédez un terrain de [BUYER] m².
+ Vous détenez [BUYER] m² de terrain.
</string>
<string name="pay_to_for_land">
Payez [AMOUNT] L$ à [SELLER] pour ce terrain
</string>
<string name="buy_for_US">
- Acheter [AMOUNT] L$ pour environ [AMOUNT2] US$,
+ Achetez [AMOUNT] L$ pour environ [LOCAL_AMOUNT],
</string>
<string name="parcel_meters">
- Cette parcelle fait [AMOUNT] m².
+ Cette parcelle fait [AMOUNT] m²
</string>
<string name="premium_land">
- Ce terrain est premium et les frais associés sont ceux d&apos;un terrain de [AMOUNT] m².
+ C&apos;est un terrain premium, [AMOUNT] m².
</string>
<string name="discounted_land">
- Ce terrain est en solde et les frais associés sont ceux d&apos;un terrain de [AMOUNT] m².
+ Ce terrain est en solde, [AMOUNT] m².
</string>
<string name="meters_supports_object">
[AMOUNT] m²
-peuvent contenir [AMOUNT2] prims
+prend en charge [AMOUNT2] objets
</string>
<string name="sold_with_objects">
vendu avec objets
diff --git a/indra/newview/skins/default/xui/fr/floater_buy_object.xml b/indra/newview/skins/default/xui/fr/floater_buy_object.xml
index 9e0ce25b97..bd29f27cbc 100644
--- a/indra/newview/skins/default/xui/fr/floater_buy_object.xml
+++ b/indra/newview/skins/default/xui/fr/floater_buy_object.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="contents" title="Acheter une copie de l&apos;objet">
+<floater name="contents" title="ACHETER UNE COPIE DE L&apos;OBJET">
<text name="contents_text">
- et ses contenus :
+ Contient :
</text>
<text name="buy_text">
Acheter pour [AMOUNT] L$ à [NAME] ?
diff --git a/indra/newview/skins/default/xui/fr/floater_camera.xml b/indra/newview/skins/default/xui/fr/floater_camera.xml
index 9f280b7265..309c93cf3b 100644
--- a/indra/newview/skins/default/xui/fr/floater_camera.xml
+++ b/indra/newview/skins/default/xui/fr/floater_camera.xml
@@ -1,12 +1,31 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="move floater">
- <string name="rotate_tooltip">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="camera_floater">
+ <floater.string name="rotate_tooltip">
Faire tourner la caméra autour du point central
- </string>
- <string name="zoom_tooltip">
+ </floater.string>
+ <floater.string name="zoom_tooltip">
Zoomer en direction du point central
- </string>
- <string name="move_tooltip">
+ </floater.string>
+ <floater.string name="move_tooltip">
Déplacer la caméra vers le haut et le bas, la gauche et la droite
- </string>
+ </floater.string>
+ <panel name="controls">
+ <joystick_track name="cam_track_stick" tool_tip="Déplacer la caméra vers le haut et le bas, la gauche et la droite"/>
+ <panel name="zoom" tool_tip="Zoomer en direction du point central">
+ <slider_bar name="zoom_slider" tool_tip="Zoomer en direction du point central"/>
+ </panel>
+ <joystick_rotate name="cam_rotate_stick" tool_tip="Faire tourner la caméra autour du point central"/>
+ <panel name="camera_presets">
+ <button name="rear_view" tool_tip="Vue arrière"/>
+ <button name="group_view" tool_tip="Vue Groupe"/>
+ <button name="front_view" tool_tip="Vue frontale"/>
+ <button name="mouselook_view" tool_tip="Vue subjective"/>
+ </panel>
+ </panel>
+ <panel name="buttons">
+ <button label="" name="orbit_btn" tool_tip="Faire tourner la caméra"/>
+ <button label="" name="pan_btn" tool_tip="Faire un panoramique"/>
+ <button label="" name="avatarview_btn" tool_tip="Vue subjective"/>
+ <button label="" name="freecamera_btn" tool_tip="Voir l&apos;objet"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_choose_group.xml b/indra/newview/skins/default/xui/fr/floater_choose_group.xml
index ade440f296..b73bedd7b5 100644
--- a/indra/newview/skins/default/xui/fr/floater_choose_group.xml
+++ b/indra/newview/skins/default/xui/fr/floater_choose_group.xml
@@ -1,8 +1,8 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="groups" title="Groupes">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="groups" title="GROUPES">
<text name="groupdesc">
Choisissez un groupe :
</text>
- <button label="OK" label_selected="OK" name="OK" />
- <button label="Annuler" label_selected="Annuler" name="Cancel" />
+ <button label="OK" label_selected="OK" name="OK"/>
+ <button label="Annuler" label_selected="Annuler" name="Cancel"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_color_picker.xml b/indra/newview/skins/default/xui/fr/floater_color_picker.xml
index adab86dac0..0ad6a69d75 100644
--- a/indra/newview/skins/default/xui/fr/floater_color_picker.xml
+++ b/indra/newview/skins/default/xui/fr/floater_color_picker.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="ColorPicker" title="Choix de texture et de couleur">
+<floater name="ColorPicker" title="SÉLECTEUR DE COULEURS">
<text name="r_val_text">
Rouge :
</text>
@@ -18,15 +18,14 @@
<text name="l_val_text">
Lum :
</text>
- <check_box label="Application auto" left="4" name="apply_immediate" width="108"/>
+ <check_box label="Appliquer maintenant" left="4" name="apply_immediate" width="108"/>
<button label="" label_selected="" left_delta="138" name="color_pipette"/>
<button label="Annuler" label_selected="Annuler" name="cancel_btn"/>
- <button label="Sélectionner" label_selected="Sélectionner" name="select_btn"/>
+ <button label="Ok" label_selected="Ok" name="select_btn"/>
<text left="8" name="Current color:">
Couleur actuelle :
</text>
<text left="8" name="(Drag below to save.)" width="114">
- (Faire glisser dessous
-pour enregistrer.)
+ (Faire glisser dessous pour enregistrer.)
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_customize.xml b/indra/newview/skins/default/xui/fr/floater_customize.xml
index b1d7edbe52..ccffb3f84a 100644
--- a/indra/newview/skins/default/xui/fr/floater_customize.xml
+++ b/indra/newview/skins/default/xui/fr/floater_customize.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater customize" title="Apparence" width="548">
+<floater name="floater customize" title="APPARENCE" width="548">
<tab_container name="customize tab container" tab_min_width="150" width="546">
- <panel label="Parties du corps" name="body_parts_placeholder"/>
+ <placeholder label="Parties du corps" name="body_parts_placeholder"/>
<panel label="Silhouette" left="154" name="Shape" width="389">
<button label="Rétablir" label_selected="Rétablir" left="305" name="Revert" width="82"/>
<button label="Corps" label_selected="Corps" name="Body"/>
@@ -14,34 +14,30 @@
<button label="Torse" label_selected="Torse" name="Torso"/>
<button label="Jambes" label_selected="Jambes" name="Legs"/>
<radio_group name="sex radio">
- <radio_item length="1" name="radio" type="string">
- Femme
- </radio_item>
- <radio_item length="1" name="radio2" type="string">
- Homme
- </radio_item>
+ <radio_item label="Femme" name="radio"/>
+ <radio_item label="Homme" name="radio2"/>
</radio_group>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: impossible de modifier
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: en cours de chargement...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: non portée
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Emplacement : [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Pour changer de silhouette, faites-en glisser une à partir de votre
inventaire jusqu&apos;à votre avatar. Vous pouvez aussi en créer une nouvelle
et de la porter.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Vous n&apos;avez pas la permission de modifier cet objet.
</text>
<text name="Item Action Label" right="92">
@@ -56,26 +52,26 @@ et de la porter.
<button label="Détails visage" label_selected="Détails visage" name="Face Detail" width="84"/>
<button label="Maquillage" label_selected="Maquillage" name="Makeup" width="84"/>
<button label="Détails corps" label_selected="Détails corps" name="Body Detail" width="84"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: impossible de modifier
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: en cours de chargement...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: non portée
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Emplacement : [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Pour changer de peau, faites-en glisser une à partir de votre inventaire.
Vous pouvez aussi en créer une nouvelle et la porter.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Vous n&apos;avez pas la permission de modifier cet objet.
</text>
<text name="Item Action Label" right="92">
@@ -94,27 +90,27 @@ Vous pouvez aussi en créer une nouvelle et la porter.
<button label="Style" label_selected="Style" name="Style"/>
<button label="Sourcils" label_selected="Sourcils" name="Eyebrows"/>
<button label="Pilosité" label_selected="Pilosité" name="Facial"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: impossible de modifier
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: en cours de chargement...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: non portés
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Emplacement : [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Pour changer de chevelure, faites-en glisser une de votre inventaire
jusqu&apos;à votre avatar. Vous pouvez aussi en créer une nouvelle
et la porter.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Vous n&apos;avez pas la permission de modifier cet objet.
</text>
<text name="Item Action Label" right="92">
@@ -127,26 +123,26 @@ et la porter.
<button label="Rétablir" label_selected="Rétablir" left="305" name="Revert" width="82"/>
</panel>
<panel label="Yeux" name="Eyes">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: impossible de modifier
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: en cours de chargement...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: non portés
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Emplacement : [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Pour changer vos yeux, faites-les glisser de votre inventaire jusqu&apos;à
votre avatar. Vous pouvez aussi en créer de nouveaux et les porter.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Vous n&apos;avez pas la permission de modifier cet objet.
</text>
<text name="Item Action Label" right="92">
@@ -158,35 +154,35 @@ votre avatar. Vous pouvez aussi en créer de nouveaux et les porter.
<button label="Enregistrer sous..." label_selected="Enregistrer sous..." left="188" name="Save As" width="111"/>
<button label="Rétablir" label_selected="Rétablir" left="305" name="Revert" width="82"/>
</panel>
- <panel label="Habits" name="clothes_placeholder"/>
+ <placeholder label="Habits" name="clothes_placeholder"/>
<panel label="Chemise" name="Shirt">
<texture_picker label="Tissu" name="Fabric" tool_tip="Cliquez pour sélectionner une image" width="74"/>
- <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquer pour ouvrir le sélecteur de couleurs" width="74"/>
+ <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs" width="74"/>
<button label="Créer une chemise" label_selected="Créer une chemise" name="Create New"/>
<button label="Enlever" label_selected="Enlever" left="12" name="Take Off" width="82"/>
<button label="Enregistrer" label_selected="Enregistrer" left="100" name="Save" width="82"/>
<button label="Enregistrer sous..." label_selected="Enregistrer sous..." left="188" name="Save As" width="111"/>
<button label="Rétablir" label_selected="Rétablir" left="305" name="Revert" width="82"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: impossible de modifier
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: en cours de chargement...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: non portée
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Emplacement : [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
- Pour changer de chemise, faites-en glisser une de votre inventaire
+ <text name="not worn instructions">
+ Pour porter une nouvelle chemise, faites-en glisser une de votre inventaire
jusqu&apos;à votre avatar. Vous pouvez aussi en créer une nouvelle et la porter.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Vous n&apos;avez pas la permission de modifier cet objet.
</text>
<text name="Item Action Label" right="92">
@@ -195,32 +191,32 @@ jusqu&apos;à votre avatar. Vous pouvez aussi en créer une nouvelle et la porte
</panel>
<panel label="Pantalon" name="Pants">
<texture_picker label="Tissu" name="Fabric" tool_tip="Cliquez pour sélectionner une image" width="74"/>
- <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquer pour ouvrir le sélecteur de couleurs" width="74"/>
+ <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs" width="74"/>
<button label="Créer un pantalon" label_selected="Créer un pantalon" name="Create New"/>
<button label="Enlever" label_selected="Enlever" left="12" name="Take Off" width="82"/>
<button label="Enregistrer" label_selected="Enregistrer" left="100" name="Save" width="82"/>
<button label="Enregistrer sous..." label_selected="Enregistrer sous..." left="188" name="Save As" width="111"/>
<button label="Rétablir" label_selected="Rétablir" left="305" name="Revert" width="82"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: impossible de modifier
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: en cours de chargement...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: non porté
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Emplacement : [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
- Pour changer de pantalon, faites-en glisser un de votre inventaire
+ <text name="not worn instructions">
+ Pour porter un nouveau pantalon, faites-en glisser un de votre inventaire
jusqu&apos;à votre avatar. Vous pouvez aussi en créer un nouveau et le porter.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Vous n&apos;avez pas la permission de modifier cet objet.
</text>
<text name="Item Action Label" right="92">
@@ -228,69 +224,69 @@ jusqu&apos;à votre avatar. Vous pouvez aussi en créer un nouveau et le porter.
</text>
</panel>
<panel label="Chaussures" name="Shoes">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: impossible de modifier
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: en cours de chargement...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: non portées
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Emplacement : [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
- Pour changer de chaussures, faites-en glisser une paire de votre
+ <text name="not worn instructions">
+ Pour porter de nouvelles chaussures, faites-en glisser une paire de votre
inventaire jusqu&apos;à votre avatar. Vous pouvez aussi en créer une
nouvelle paire et la porter.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Vous n&apos;avez pas la permission de modifier cet objet.
</text>
<text name="Item Action Label" right="92">
Chaussures :
</text>
<texture_picker label="Tissu" name="Fabric" tool_tip="Cliquez pour sélectionner une image" width="74"/>
- <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquer pour ouvrir le sélecteur de couleurs" width="74"/>
- <button label="Créer des chaussures" label_selected="Créer des chaussures" name="Create New" />
+ <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs" width="74"/>
+ <button label="Créer des chaussures" label_selected="Créer des chaussures" name="Create New"/>
<button label="Enlever" label_selected="Enlever" left="12" name="Take Off" width="82"/>
<button label="Enregistrer" label_selected="Enregistrer" left="100" name="Save" width="82"/>
<button label="Enregistrer sous..." label_selected="Enregistrer sous..." left="188" name="Save As" width="111"/>
<button label="Rétablir" label_selected="Rétablir" left="305" name="Revert" width="82"/>
</panel>
<panel label="Chaussettes" name="Socks">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: impossible de modifier
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: en cours de chargement...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: non portées
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Emplacement : [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
- Pour changer de chaussettes, faites-en glisser une paire de votre
+ <text name="not worn instructions">
+ Pour porter de nouvelles chaussettes, faites-en glisser une paire de votre
inventaire jusqu&apos;à votre avatar. Vous pouvez aussi en créer une
nouvelle paire et la porter.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Vous n&apos;avez pas la permission de modifier cet objet.
</text>
<text name="Item Action Label" right="92">
Chaussettes :
</text>
<texture_picker label="Tissu" name="Fabric" tool_tip="Cliquez pour sélectionner une image" width="74"/>
- <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquer pour ouvrir le sélecteur de couleurs" width="74"/>
+ <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs" width="74"/>
<button label="Créer des chaussettes" label_selected="Créer des chaussettes" name="Create New"/>
<button label="Enlever" label_selected="Enlever" left="12" name="Take Off" width="82"/>
<button label="Enregistrer" label_selected="Enregistrer" left="100" name="Save" width="82"/>
@@ -298,26 +294,26 @@ nouvelle paire et la porter.
<button label="Rétablir" label_selected="Rétablir" left="305" name="Revert" width="82"/>
</panel>
<panel label="Veste" name="Jacket">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: impossible de modifier
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: en cours de chargement...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: non portée
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Emplacement : [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
- Pour changer de veste, faites-en glisser une de votre inventaire jusqu&apos;à
-votre avatar. Vous pouvez aussi en créer une nouvelle et la porter.
+ <text name="not worn instructions">
+ Pour porter une nouvelle veste, faites-en glisser une de votre inventaire
+jusqu&apos;à votre avatar. Vous pouvez aussi en créer une nouvelle et la porter.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Vous n&apos;avez pas la permission de modifier cet objet.
</text>
<text name="Item Action Label" right="92">
@@ -325,7 +321,7 @@ votre avatar. Vous pouvez aussi en créer une nouvelle et la porter.
</text>
<texture_picker label="Tissu (dessus)" name="Upper Fabric" tool_tip="Cliquez pour sélectionner une image" width="81"/>
<texture_picker label="Tissu (dessous)" name="Lower Fabric" tool_tip="Cliquez pour sélectionner une image" width="81"/>
- <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquer pour ouvrir le sélecteur de couleurs" width="81"/>
+ <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs" width="81"/>
<button label="Créer une veste" label_selected="Créer une veste" name="Create New"/>
<button label="Enlever" label_selected="Enlever" left="12" name="Take Off" width="82"/>
<button label="Enregistrer" label_selected="Enregistrer" left="100" name="Save" width="82"/>
@@ -333,33 +329,33 @@ votre avatar. Vous pouvez aussi en créer une nouvelle et la porter.
<button label="Rétablir" label_selected="Rétablir" left="305" name="Revert" width="82"/>
</panel>
<panel label="Gants" name="Gloves">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: impossible de modifier
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: en cours de chargement...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: non portés
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Emplacement : [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
- Pour changer de gants, faites-en glisser une paire à partir de votre
+ <text name="not worn instructions">
+ Pour porter de nouveaux gants, faites-les glisser à partir de votre
inventaire. Vous pouvez aussi en créer une nouvelle paire et la porter.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Vous n&apos;avez pas la permission de modifier cet objet.
</text>
<text name="Item Action Label" right="92">
Gants :
</text>
<texture_picker label="Tissu" name="Fabric" tool_tip="Cliquez pour sélectionner une image" width="74"/>
- <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquer pour ouvrir le sélecteur de couleurs" width="74"/>
+ <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs" width="74"/>
<button label="Créer des gants" label_selected="Créer des gants" name="Create New"/>
<button label="Enlever" label_selected="Enlever" left="12" name="Take Off" width="82"/>
<button label="Enregistrer" label_selected="Enregistrer" left="100" name="Save" width="82"/>
@@ -367,34 +363,34 @@ inventaire. Vous pouvez aussi en créer une nouvelle paire et la porter.
<button label="Rétablir" label_selected="Rétablir" left="305" name="Revert" width="82"/>
</panel>
<panel label="Sous-vêtements (haut)" name="Undershirt">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: impossible de modifier
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: en cours de chargement...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: non portés
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Emplacement : [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
- Pour changer de sous-vêtement, faites-en glisser une paire à partir de
+ <text name="not worn instructions">
+ Pour porter de nouveaux sous-vêtements, faites-les glisser à partir de
votre inventaire. Vous pouvez aussi en créer des nouveaux et les porter.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Vous n&apos;avez pas la permission de modifier cet objet.
</text>
- <text name="Item Action Label" right="92" bottom="-470">
+ <text bottom="-470" name="Item Action Label" right="92">
Sous-vêtements
(haut) :
</text>
<texture_picker label="Tissu" name="Fabric" tool_tip="Cliquez pour sélectionner une image" width="74"/>
- <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquer pour ouvrir le sélecteur de couleurs" width="74"/>
+ <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs" width="74"/>
<button label="Créer des sous-vêtements" label_selected="Créer des sous-vêtements" name="Create New"/>
<button label="Enlever" label_selected="Enlever" left="12" name="Take Off" width="82"/>
<button label="Enregistrer" label_selected="Enregistrer" left="100" name="Save" width="82"/>
@@ -402,34 +398,34 @@ votre inventaire. Vous pouvez aussi en créer des nouveaux et les porter.
<button label="Rétablir" label_selected="Rétablir" left="305" name="Revert" width="82"/>
</panel>
<panel label="Sous-vêtements (bas)" name="Underpants">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: impossible de modifier
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: en cours de chargement...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: non portés
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Emplacement : [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
- Pour changer de sous-vêtement, faites-en glisser une paire à partir de
+ <text name="not worn instructions">
+ Pour porter de nouveaux sous-vêtements, faites-les glisser à partir de
votre inventaire. Vous pouvez aussi en créer des nouveaux et les porter.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Vous n&apos;avez pas la permission de modifier cet objet.
</text>
- <text name="Item Action Label" right="92" bottom="-470">
+ <text bottom="-470" name="Item Action Label" right="92">
Sous-vêtements
(bas) :
</text>
<texture_picker label="Tissu" name="Fabric" tool_tip="Cliquez pour sélectionner une image" width="74"/>
- <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquer pour ouvrir le sélecteur de couleurs" width="74"/>
+ <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs" width="74"/>
<button label="Créer des sous-vêtements" label_selected="Créer des sous-vêtements" name="Create New"/>
<button label="Enlever" label_selected="Enlever" left="12" name="Take Off" width="82"/>
<button label="Enregistrer" label_selected="Enregistrer" left="100" name="Save" width="82"/>
@@ -437,42 +433,114 @@ votre inventaire. Vous pouvez aussi en créer des nouveaux et les porter.
<button label="Rétablir" label_selected="Rétablir" left="305" name="Revert" width="82"/>
</panel>
<panel label="Jupe" name="Skirt">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: impossible de modifier
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: en cours de chargement...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: non portée
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Emplacement : [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
- Pour changer de jupe, faites-en glisser une à partir de votre inventaire.
-Vous pouvez aussi en créer une nouvelle et la porter.
+ <text name="not worn instructions">
+ Pour porter une nouvelle jupe, faites-en glisser une à partir de votre
+inventaire. Vous pouvez aussi en créer une nouvelle et la porter.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Vous n&apos;avez pas la permission de modifier cet objet.
</text>
<text name="Item Action Label" right="92">
Jupe :
</text>
<texture_picker label="Tissu" name="Fabric" tool_tip="Cliquez pour sélectionner une image" width="74"/>
- <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquer pour ouvrir le sélecteur de couleurs" width="74"/>
+ <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs" width="74"/>
<button label="Créer une jupe" label_selected="Créer une jupe" name="Create New"/>
<button label="Enlever" label_selected="Enlever" left="12" name="Take Off" width="82"/>
<button label="Enregistrer" label_selected="Enregistrer" left="100" name="Save" width="82"/>
<button label="Enregistrer sous..." label_selected="Enregistrer sous..." left="188" name="Save As" width="111"/>
<button label="Rétablir" label_selected="Rétablir" left="305" name="Revert" width="82"/>
</panel>
+ <panel label="Alpha" name="Alpha">
+ <text name="title">
+ [DESC]
+ </text>
+ <text name="title_no_modify">
+ [DESC]: impossible de modifier
+ </text>
+ <text name="title_loading">
+ [DESC]: en cours de chargement...
+ </text>
+ <text name="title_not_worn">
+ [DESC]: non porté
+ </text>
+ <text name="path">
+ Dans [PATH]
+ </text>
+ <text name="not worn instructions">
+ Pour changer de masque alpha, faites-en glisser un de votre inventaire à votre avatar.
+Vous pouvez aussi en créer un nouveau et le porter.
+ </text>
+ <text name="no modify instructions">
+ Vous n&apos;avez pas le droit de modifier cet objet.
+ </text>
+ <text name="Item Action Label">
+ Alpha :
+ </text>
+ <texture_picker label="Alpha bas" name="Lower Alpha" tool_tip="Cliquez pour sélectionner une image"/>
+ <texture_picker label="Alpha haut" name="Upper Alpha" tool_tip="Cliquez pour sélectionner une image"/>
+ <texture_picker label="Alpha tête" name="Head Alpha" tool_tip="Cliquez pour sélectionner une image"/>
+ <texture_picker label="Alpha yeux" name="Eye Alpha" tool_tip="Cliquez pour sélectionner une image"/>
+ <texture_picker label="Alpha cheveux" name="Hair Alpha" tool_tip="Cliquez pour sélectionner une image"/>
+ <button label="Créer un nouvel alpha" label_selected="Créer un nouvel alpha" name="Create New"/>
+ <button label="Enlever" label_selected="Enlever" name="Take Off"/>
+ <button label="Enregistrer" label_selected="Enregistrer" name="Save"/>
+ <button label="Enregistrer sous..." label_selected="Enregistrer sous..." name="Save As"/>
+ <button label="Annuler modification" label_selected="Annuler modification" name="Revert"/>
+ </panel>
+ <panel label="Tatouage" name="Tattoo">
+ <text name="title">
+ [DESC]
+ </text>
+ <text name="title_no_modify">
+ [DESC]: impossible de modifier
+ </text>
+ <text name="title_loading">
+ [DESC]: en cours de chargement...
+ </text>
+ <text name="title_not_worn">
+ [DESC]: non porté
+ </text>
+ <text name="path">
+ Dans [PATH]
+ </text>
+ <text name="not worn instructions">
+ Pour changer de tatouage, faites-en glisser un de votre inventaire à votre avatar.
+Vous pouvez aussi en créer un nouveau et le porter.
+ </text>
+ <text name="no modify instructions">
+ Vous n&apos;avez pas le droit de modifier cet objet.
+ </text>
+ <text name="Item Action Label">
+ Tatouage :
+ </text>
+ <texture_picker label="Tatouage tête" name="Head Tattoo" tool_tip="Cliquez pour sélectionner une image"/>
+ <texture_picker label="Tatouage haut" name="Upper Tattoo" tool_tip="Cliquez pour sélectionner une image"/>
+ <texture_picker label="Tatouage bas" name="Lower Tattoo" tool_tip="Cliquez pour sélectionner une image"/>
+ <button label="Créer un nouveau tatouage" label_selected="Créer un nouveau tatouage" name="Create New"/>
+ <button label="Enlever" label_selected="Enlever" name="Take Off"/>
+ <button label="Enregistrer" label_selected="Enregistrer" name="Save"/>
+ <button label="Enregistrer sous..." label_selected="Enregistrer sous..." name="Save As"/>
+ <button label="Annuler modification" label_selected="Annuler modification" name="Revert"/>
+ </panel>
</tab_container>
<scroll_container left="251" name="panel_container"/>
+ <button label="Créer tenue" label_selected="Créer une tenue..." name="make_outfit_btn"/>
<button label="Annuler" label_selected="Annuler" name="Cancel"/>
<button label="OK" label_selected="OK" name="Ok"/>
- <button label="Créer un ensemble..." label_selected="Créer un ensemble..." name="Make Outfit" left="152" width="125"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_day_cycle_options.xml b/indra/newview/skins/default/xui/fr/floater_day_cycle_options.xml
index 1103539898..0b36b7b8ca 100644
--- a/indra/newview/skins/default/xui/fr/floater_day_cycle_options.xml
+++ b/indra/newview/skins/default/xui/fr/floater_day_cycle_options.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Day Cycle Floater" title="Editeur du cycle du jour">
+<floater name="Day Cycle Floater" title="EDITEUR DU CYCLE DU JOUR">
<tab_container name="Day Cycle Tabs">
<panel label="Cycle du jour" name="Day Cycle">
<button label="?" name="WLDayCycleHelp" />
diff --git a/indra/newview/skins/default/xui/fr/floater_device_settings.xml b/indra/newview/skins/default/xui/fr/floater_device_settings.xml
index 656f1c4fba..f5994cb604 100644
--- a/indra/newview/skins/default/xui/fr/floater_device_settings.xml
+++ b/indra/newview/skins/default/xui/fr/floater_device_settings.xml
@@ -1,3 +1,2 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_device_settings"
- title="Paramètres du matériel utilisé pour le chat vocal" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_device_settings" title="PARAMÈTRES DU MATÉRIEL UTILISÉ POUR LE CHAT VOCAL"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_env_settings.xml b/indra/newview/skins/default/xui/fr/floater_env_settings.xml
index 1d14142dd3..505c9236c7 100644
--- a/indra/newview/skins/default/xui/fr/floater_env_settings.xml
+++ b/indra/newview/skins/default/xui/fr/floater_env_settings.xml
@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Environment Editor Floater" title="Éditeur d&apos;environnement">
+<floater name="Environment Editor Floater" title="ÉDITEUR D&apos;ENVIRONNEMENT">
+ <floater.string name="timeStr">
+ [hour12,datetime,utc]:[min,datetime,utc] [ampm,datetime,utc]
+ </floater.string>
<text bottom="-45" name="EnvTimeText">
Heure de la
journée
@@ -15,13 +18,12 @@ nuageuse
Couleur de
l&apos;eau
</text>
- <color_swatch name="EnvWaterColor" tool_tip="Cliquer pour ouvrir le sélecteur de couleurs"/>
+ <color_swatch name="EnvWaterColor" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs"/>
<text name="EnvWaterFogText">
Brouillard
dans l&apos;eau
</text>
<button bottom="-144" label="Utiliser heure du domaine" name="EnvUseEstateTimeButton" width="145"/>
- <button label="Ciel avancé" name="EnvAdvancedSkyButton" width="145" left="162" />
- <button label="Eau avancée" name="EnvAdvancedWaterButton" width="145" left="316"/>
- <button label="?" name="EnvSettingsHelpButton"/>
+ <button label="Ciel avancé" left="162" name="EnvAdvancedSkyButton" width="145"/>
+ <button label="Eau avancée" left="316" name="EnvAdvancedWaterButton" width="145"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_first_time_tip.xml b/indra/newview/skins/default/xui/fr/floater_first_time_tip.xml
new file mode 100644
index 0000000000..a1c6a19e8c
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_first_time_tip.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="set_name_in_the_cladd">
+ <check_box label="Désactiver les astuces" name="DontShowFirstTimeTip_checkbox"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_font_test.xml b/indra/newview/skins/default/xui/fr/floater_font_test.xml
index 11eb11a0d7..974a5ca3a2 100644
--- a/indra/newview/skins/default/xui/fr/floater_font_test.xml
+++ b/indra/newview/skins/default/xui/fr/floater_font_test.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="contents" title="Test de la police">
+<floater name="contents" title="TEST DE POLICE">
<text name="linea">
OverrideTest, Times-BOLD doit être sélectionné ici. (De default/xui/fr)
</text>
diff --git a/indra/newview/skins/default/xui/fr/floater_gesture.xml b/indra/newview/skins/default/xui/fr/floater_gesture.xml
index 4411fee480..113df0acc4 100644
--- a/indra/newview/skins/default/xui/fr/floater_gesture.xml
+++ b/indra/newview/skins/default/xui/fr/floater_gesture.xml
@@ -1,18 +1,27 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="gestures" title="Gestes utilisés">
- <text name="help_label">
- Double-cliquez sur un geste pour jouer les animations
-et les sons.
- </text>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater label="Lieux" name="gestures" title="GESTES">
+ <floater.string name="loading">
+ Chargement...
+ </floater.string>
+ <floater.string name="playing">
+ (lecture en cours)
+ </floater.string>
+ <floater.string name="copy_name">
+ Copie de [COPY_NAME]
+ </floater.string>
<scroll_list bottom_delta="-385" height="360" name="gesture_list">
- <column label="Déclencheur" name="trigger" width="85" />
- <column label="Touche" name="shortcut" />
- <column label="" name="key" />
- <column label="Nom" name="name" width="145"/>
+ <scroll_list.columns label="Nom" name="name" width="145"/>
+ <scroll_list.columns label="Chat" name="trigger" width="85"/>
+ <scroll_list.columns label="" name="key"/>
+ <scroll_list.columns label="Touche" name="shortcut"/>
</scroll_list>
- <button label="Nouveau" name="new_gesture_btn" />
- <button label="Inventaire" name="inventory_btn" />
- <button label="Modifier" name="edit_btn" />
- <button label="Jouer" name="play_btn" />
- <button label="Stop" name="stop_btn" />
+ <panel label="bottom_panel" name="bottom_panel">
+ <menu_button name="gear_btn" tool_tip="Plus d&apos;options"/>
+ <button name="new_gesture_btn" tool_tip="Faire un nouveau geste"/>
+ <button name="activate_btn" tool_tip="Activer/désactiver le geste sélectionné"/>
+ <button name="del_btn" tool_tip="Supprimer ce geste"/>
+ </panel>
+ <button label="Modifier" name="edit_btn"/>
+ <button label="Jouer" name="play_btn"/>
+ <button label="Stop" name="stop_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_god_tools.xml b/indra/newview/skins/default/xui/fr/floater_god_tools.xml
index 81b69eb110..2bf0b9e2f3 100644
--- a/indra/newview/skins/default/xui/fr/floater_god_tools.xml
+++ b/indra/newview/skins/default/xui/fr/floater_god_tools.xml
@@ -1,26 +1,27 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="godtools floater" title="Outils divins">
+<floater name="godtools floater" title="OUTILS DIVINS">
<tab_container name="GodTools Tabs">
<panel label="Grille" name="grid">
- <button label="Éjecter tous" label_selected="Éjecter tous" name="Kick all users" width="175" />
+ <button label="Éjecter tous" label_selected="Éjecter tous" name="Kick all users" width="175"/>
<button label="Vider le cache cartographique de la région" label_selected="Vider le cache cartographique de la région" name="Flush This Region&apos;s Map Visibility Caches" width="285"/>
</panel>
<panel label="Région" name="region">
<text name="Sim Name:" width="70">
Nom du sim :
</text>
- <line_editor left="85" name="region name" width="198" />
+ <line_editor left="85" name="region name" width="198"/>
<check_box label="Initiation" name="check prelude" tool_tip="Définir cette région comme zone d&apos;initiation."/>
<check_box label="Soleil fixe" name="check fixed sun" tool_tip="Définir la position du soleil (comme dans Région et Domaine &gt; Terrain.)"/>
- <check_box label="Réinitialiser le domicile &#10;à la téléportation" name="check reset home" tool_tip="Lorsqu&apos;un résident se téléporte à l&apos;extérieur, réinitialise son domicile à la position de sa destination." height="32"/>
- <check_box label="Visible" name="check visible" tool_tip="Cochez pour rendre la région visible aux non-admins." bottom_delta="-32"/>
+ <check_box height="32" label="Réinitialiser le domicile
+à la téléportation" name="check reset home" tool_tip="Lorsqu&apos;un résident se téléporte à l&apos;extérieur, réinitialise son domicile à la position de sa destination."/>
+ <check_box bottom_delta="-32" label="Visible" name="check visible" tool_tip="Cochez pour rendre la région visible aux non-admins."/>
<check_box label="Dégâts" name="check damage" tool_tip="Cochez pour activer les dégâts dans cette région."/>
<check_box label="Bloquer le suivi de trafic" name="block dwell" tool_tip="Cochez pour que la région ne comptabilise pas le trafic."/>
<check_box label="Interdire le terraformage" name="block terraform" tool_tip="Cochez pour empêcher les personnes de terraformer leur terrain"/>
<check_box label="Bac à sable" name="is sandbox" tool_tip="Basculer cette région en bac à sable."/>
- <button label="Figer le terrain" label_selected="Figer le terrain" name="Bake Terrain" tool_tip="Enregistrer le terrain actuel comme terrain par défaut." width="118" />
- <button label="Rétablir le terrain" label_selected="Rétablir le terrain" name="Revert Terrain" tool_tip="Remplacer le terrain actuel avec le terrain par défaut." width="118" />
- <button label="Échanger le terrain" label_selected="Échanger le terrain" name="Swap Terrain" tool_tip="Échangez le terrain actuel avec le terrain par défaut." width="118" />
+ <button label="Figer le terrain" label_selected="Figer le terrain" name="Bake Terrain" tool_tip="Enregistrer le terrain actuel comme terrain par défaut." width="118"/>
+ <button label="Rétablir le terrain" label_selected="Rétablir le terrain" name="Revert Terrain" tool_tip="Remplacer le terrain actuel avec le terrain par défaut." width="118"/>
+ <button label="Échanger le terrain" label_selected="Échanger le terrain" name="Swap Terrain" tool_tip="Échangez le terrain actuel avec le terrain par défaut." width="118"/>
<text name="estate id">
ID du domaine :
</text>
@@ -31,37 +32,43 @@
<text name="Grid Pos: ">
Position sur la grille :
</text>
- <line_editor name="gridposx" tool_tip="Position x de cette région sur la grille" left_delta="120" width="35"/>
- <line_editor name="gridposy" tool_tip="Position y de cette région sur la grille" left_delta="40" width="35" />
+ <line_editor left_delta="120" name="gridposx" tool_tip="Position x de cette région sur la grille" width="35"/>
+ <line_editor left_delta="40" name="gridposy" tool_tip="Position y de cette région sur la grille" width="35"/>
<text name="Redirect to Grid: ">
Rediriger vers la grille :
</text>
- <line_editor left_delta="120" name="redirectx" width="35" />
- <line_editor left_delta="40" name="redirecty" width="35" />
- <spinner left="320" name="billable factor" width="70" />
- <text name="billable factor text" font="SansSerifSmall" left_delta="-120" width="120">
+ <line_editor left_delta="120" name="redirectx" width="35"/>
+ <line_editor left_delta="40" name="redirecty" width="35"/>
+ <text font="SansSerifSmall" left_delta="-120" name="billable factor text" width="120">
Facteur de facturation :
</text>
- <spinner left="320" name="land cost" width="70" />
- <text name="land cost text" left_delta="-120">
+ <spinner left="320" name="billable factor" width="70"/>
+ <text left_delta="-120" name="land cost text">
L$ par m² :
</text>
+ <spinner left="320" name="land cost" width="70"/>
<button label="Rafraîchir" label_selected="Rafraîchir" name="Refresh" tool_tip="Cliquez ici pour rafraîchir les informations ci-dessus."/>
<button label="Appliquer" label_selected="Appliquer" name="Apply" tool_tip="Cliquez ici pour appliquer les modifications effectuées ci-dessus."/>
- <button label="Sélectionner une région" label_selected="Sélectionner une région" name="Select Region" tool_tip="Sélectionnez une région entière à l&apos;aide de l&apos;outil Terrain." width="140" left="136"/>
- <button label="Sauvegarde automatique" label_selected="Sauvegarde automatique" name="Autosave now" tool_tip="Sauvegarde automatique au format gzip." width="140" left="136"/>
+ <button label="Sélectionner une région" label_selected="Sélectionner une région" left="136" name="Select Region" tool_tip="Sélectionnez une région entière à l&apos;aide de l&apos;outil Terrain." width="140"/>
+ <button label="Sauvegarde automatique" label_selected="Sauvegarde automatique" left="136" name="Autosave now" tool_tip="Sauvegarde automatique au format gzip." width="140"/>
</panel>
<panel label="Objets" name="objects">
+ <panel.string name="no_target">
+ (aucune cible)
+ </panel.string>
<text name="Sim Name:" width="70">
Nom du sim :
</text>
- <text name="region name" left_delta="75">
+ <text left_delta="75" name="region name">
Welsh
</text>
- <check_box label="Désactiver les &#10;scripts" name="disable scripts" tool_tip="Cochez pour désactiver tous les scripts dans cette région"/>
- <check_box label="Désactiver les &#10;collisions" name="disable collisions" tool_tip="Cochez pour désactiver les collisions entre non-avatars dans cette région"/>
- <check_box label="Désactiver la &#10;physique" name="disable physics" tool_tip="Cochez pour désactiver tous les effets liés à la physique dans cette région"/>
- <button label="Appliquer" label_selected="Appliquer" name="Apply" tool_tip="Cliquez ici pour appliquer les modifications effectuées ci-dessus." bottom="-85"/>
+ <check_box label="Désactiver les
+scripts" name="disable scripts" tool_tip="Cochez pour désactiver tous les scripts dans cette région"/>
+ <check_box label="Désactiver les
+collisions" name="disable collisions" tool_tip="Cochez pour désactiver les collisions entre non-avatars dans cette région"/>
+ <check_box label="Désactiver la
+physique" name="disable physics" tool_tip="Cochez pour désactiver tous les effets liés à la physique dans cette région"/>
+ <button bottom="-85" label="Appliquer" label_selected="Appliquer" name="Apply" tool_tip="Cliquez ici pour appliquer les modifications effectuées ci-dessus."/>
<button label="Définir la cible" label_selected="Définir la cible" name="Set Target" tool_tip="Définir l&apos;avatar cible pour la suppression de l&apos;objet."/>
<text name="target_avatar_name">
(aucune cible)
@@ -69,38 +76,26 @@
<button label="Supprimer tous les objets scriptés de la cible sur les terrains des autres" label_selected="Supprimer tous les objets scriptés de la cible sur les terrains des autres" name="Delete Target&apos;s Scripted Objects On Others Land" tool_tip="Supprimer tous les objets scriptés appartenant à la cible sur les terrains ne lui appartenant pas. Les objets non copiables seront renvoyés."/>
<button label="Supprimer les objets scriptés de la cible sur *tous* les terrains" label_selected="Supprimer les objets scriptés de la cible sur *tous* les terrains" name="Delete Target&apos;s Scripted Objects On *Any* Land" tool_tip="Supprimer les objets scriptés appartenant à la cible dans cette région. Les objets non copiables seront renvoyés."/>
<button label="Supprimer *tous* les objets de la cible" label_selected="Supprimer *tous* les objets de la cible" name="Delete *ALL* Of Target&apos;s Objects" tool_tip="Supprimer tous les objets appartenant à la cible dans cette région. Les objets non copiables seront renvoyés."/>
- <button width="300" label="Afficher les collisions les plus consommatrices" label_selected="Afficher les collisions les plus consommatrices" name="Get Top Colliders" tool_tip="Dresse une liste des objets avec les callbacks les plus fréquents. "/>
- <button width="300" label="Afficher les objets scriptés les plus consommateurs" label_selected="Afficher les objets scriptés les plus consommateurs" name="Get Top Scripts" tool_tip="Dresse une liste des objets qui passent le plus de temps à exécuter des scripts."/>
- <button width="300" label="Résumé des scripts" label_selected="Résumé des scripts" name="Scripts digest" tool_tip="Dresse une liste des scripts et de leurs occurrences."/>
+ <button label="Afficher les collisions les plus consommatrices" label_selected="Afficher les collisions les plus consommatrices" name="Get Top Colliders" tool_tip="Dresse une liste des objets avec les callbacks les plus fréquents. " width="300"/>
+ <button label="Afficher les objets scriptés les plus consommateurs" label_selected="Afficher les objets scriptés les plus consommateurs" name="Get Top Scripts" tool_tip="Dresse une liste des objets qui passent le plus de temps à exécuter des scripts." width="300"/>
+ <button label="Résumé des scripts" label_selected="Résumé des scripts" name="Scripts digest" tool_tip="Dresse une liste des scripts et de leurs occurrences." width="300"/>
</panel>
<panel label="Requête" name="request">
<text name="Destination:">
Destination :
</text>
<combo_box name="destination">
- <combo_item name="Selection">
- Sélection
- </combo_item>
- <combo_item name="AgentRegion">
- Région de l&apos;avatar
- </combo_item>
+ <combo_box.item label="Sélection" name="item1"/>
+ <combo_box.item label="Région de l&apos;avatar" name="item2"/>
</combo_box>
<text name="Request:">
Requête :
</text>
<combo_box name="request">
- <combo_item name="colliders&lt;steps&gt;">
- Objets responsables de collisions : étapes
- </combo_item>
- <combo_item name="scripts&lt;count&gt;,&lt;optionalpattern&gt;">
- Nombre de scripts et schéma optionnel
- </combo_item>
- <combo_item name="objects&lt;pattern&gt;">
- Schéma des objets
- </combo_item>
- <combo_item name="rez&lt;asset_id&gt;">
- rezzer &lt;asset_id&gt;
- </combo_item>
+ <combo_box.item label="Objets responsables de collisions : étapes" name="item1"/>
+ <combo_box.item label="Nombre de scripts et schéma optionnel" name="item2"/>
+ <combo_box.item label="Schéma des objets" name="item3"/>
+ <combo_box.item label="rezzer &lt;asset_id&gt;" name="item4"/>
</combo_box>
<text name="Parameter:">
Paramètre :
diff --git a/indra/newview/skins/default/xui/fr/floater_hardware_settings.xml b/indra/newview/skins/default/xui/fr/floater_hardware_settings.xml
index e3624c7ccb..e3d604477c 100644
--- a/indra/newview/skins/default/xui/fr/floater_hardware_settings.xml
+++ b/indra/newview/skins/default/xui/fr/floater_hardware_settings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Hardware Settings Floater" title="Configuration du matériel">
+<floater name="Hardware Settings Floater" title="PARAMÈTRES MATÉRIELS">
<text name="Filtering:">
Filtres :
</text>
@@ -8,21 +8,11 @@
Anti-aliasing :
</text>
<combo_box label="Anti-aliasing" name="fsaa" width="84">
- <combo_item name="FSAADisabled">
- Désactivé
- </combo_item>
- <combo_item name="2x">
- 2x
- </combo_item>
- <combo_item name="4x">
- 4x
- </combo_item>
- <combo_item name="8x">
- 8x
- </combo_item>
- <combo_item name="16x">
- 16x
- </combo_item>
+ <combo_box.item label="Désactivé" name="FSAADisabled"/>
+ <combo_box.item label="2x" name="2x"/>
+ <combo_box.item label="4x" name="4x"/>
+ <combo_box.item label="8x" name="8x"/>
+ <combo_box.item label="16x" name="16x"/>
</combo_box>
<spinner label="Gamma :" name="gamma"/>
<text left="217" name="(brightness, lower is brighter)">
@@ -31,8 +21,8 @@
<text name="Enable VBO:">
Activer le VBO :
</text>
- <check_box label="Activer OpenGL Vertex Buffer Objects" name="vbo" tool_tip="Sur un matériel moderne, cette option permet une meilleure performance. Par contre, sur un matériel plus ancien, les VBO sont souvent mal implémentés et peuvent causer des crashs lorsqu&apos;ils sont activés."/>
- <slider label="Mémoire vidéo (Mo) :" name="GrapicsCardTextureMemory" tool_tip="Total de la mémoire alloué aux textures. Mémoire de la carte vidéo par défaut. En réduisant cette valeur, vous pouvez accroître la performance mais les textures risquent de devenir floues."/>
+ <check_box initial_value="true" label="Activer OpenGL Vertex Buffer Objects" name="vbo" tool_tip="Sur un matériel moderne, cette option permet une meilleure performance. Par contre, sur un matériel plus ancien, les VBO sont souvent mal implémentés et peuvent causer des crashs lorsqu&apos;ils sont activés."/>
+ <slider label="Mémoire textures (Mo) :" name="GraphicsCardTextureMemory" tool_tip="Quantité de mémoire à affecter aux textures. Utilise la mémoire de la carte vidéo par défaut. Si vous réduisez ce paramètre, cela peut améliorer les performances, mais les textures risquent d&apos;être floues."/>
<spinner label="Indice du brouillard :" name="fog"/>
<button label="OK" label_selected="OK" name="OK"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_help_browser.xml b/indra/newview/skins/default/xui/fr/floater_help_browser.xml
new file mode 100644
index 0000000000..1170d1d87b
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_help_browser.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_help_browser" title="NAVIGATEUR D&apos;AIDE">
+ <floater.string name="home_page_url">
+ http://fr.secondlife.com
+ </floater.string>
+ <floater.string name="support_page_url">
+ http://fr.secondlife.com/support
+ </floater.string>
+ <layout_stack name="stack1">
+ <layout_panel name="external_controls">
+ <button label="Ouvrir dans mon navigateur Web" name="open_browser"/>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_hud.xml b/indra/newview/skins/default/xui/fr/floater_hud.xml
index 55c8b57ae2..f212f113b3 100644
--- a/indra/newview/skins/default/xui/fr/floater_hud.xml
+++ b/indra/newview/skins/default/xui/fr/floater_hud.xml
@@ -1,2 +1,2 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_hud" title="Didacticiel" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_hud" title="DIDACTICIEL"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_im.xml b/indra/newview/skins/default/xui/fr/floater_im.xml
index a116c43f3f..0e4039d3af 100644
--- a/indra/newview/skins/default/xui/fr/floater_im.xml
+++ b/indra/newview/skins/default/xui/fr/floater_im.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<multi_floater name="im_floater" title="Message instantané">
<text name="only_user_message">
Vous êtes le seul participant à cette session.
diff --git a/indra/newview/skins/default/xui/fr/floater_im_container.xml b/indra/newview/skins/default/xui/fr/floater_im_container.xml
new file mode 100644
index 0000000000..2637dfa670
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_im_container.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<multi_floater name="floater_im_box" title="Messages instantanés"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_im_session.xml b/indra/newview/skins/default/xui/fr/floater_im_session.xml
new file mode 100644
index 0000000000..c3df4a869c
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_im_session.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="panel_im">
+ <layout_stack name="im_panels">
+ <layout_panel label="Panneau de contrôle IM" name="panel_im_control_panel"/>
+ <layout_panel>
+ <line_editor label="À" name="chat_editor"/>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_image_preview.xml b/indra/newview/skins/default/xui/fr/floater_image_preview.xml
index 3727e3590d..a28e0bd7d5 100644
--- a/indra/newview/skins/default/xui/fr/floater_image_preview.xml
+++ b/indra/newview/skins/default/xui/fr/floater_image_preview.xml
@@ -9,37 +9,17 @@
<text name="preview_label">
Prévisualiser comme :
</text>
- <combo_box label="Habits" name="clothing_type_combo" left="126" >
- <combo_item name="Image">
- Image
- </combo_item>
- <combo_item name="Hair">
- Cheveux
- </combo_item>
- <combo_item name="FemaleHead">
- Tête de femme
- </combo_item>
- <combo_item name="FemaleUpperBody">
- Corps de femme (haut)
- </combo_item>
- <combo_item name="FemaleLowerBody">
- Corps de femme (bas)
- </combo_item>
- <combo_item name="MaleHead">
- Tête d&apos;homme
- </combo_item>
- <combo_item name="MaleUpperBody">
- Corps d&apos;homme (haut)
- </combo_item>
- <combo_item name="MaleLowerBody">
- Corps d&apos;homme (bas)
- </combo_item>
- <combo_item name="Skirt">
- Jupe
- </combo_item>
- <combo_item name="SculptedPrim">
- Sculptie
- </combo_item>
+ <combo_box label="Habits" left="126" name="clothing_type_combo">
+ <combo_box.item label="Image" name="Image"/>
+ <combo_box.item label="Cheveux" name="Hair"/>
+ <combo_box.item label="Tête de femme" name="FemaleHead"/>
+ <combo_box.item label="Corps de femme (haut)" name="FemaleUpperBody"/>
+ <combo_box.item label="Corps de femme (bas)" name="FemaleLowerBody"/>
+ <combo_box.item label="Tête d&apos;homme" name="MaleHead"/>
+ <combo_box.item label="Corps d&apos;homme (haut)" name="MaleUpperBody"/>
+ <combo_box.item label="Corps d&apos;homme (bas)" name="MaleLowerBody"/>
+ <combo_box.item label="Jupe" name="Skirt"/>
+ <combo_box.item label="Sculptie" name="SculptedPrim"/>
</combo_box>
<text name="bad_image_text">
Impossible de lire l&apos;image.
diff --git a/indra/newview/skins/default/xui/fr/floater_incoming_call.xml b/indra/newview/skins/default/xui/fr/floater_incoming_call.xml
new file mode 100644
index 0000000000..d3c461a427
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_incoming_call.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="incoming call" title="APPEL D&apos;UN(E)INCONNU(E)">
+ <floater.string name="localchat">
+ Chat vocal près de vous
+ </floater.string>
+ <floater.string name="anonymous">
+ anonyme
+ </floater.string>
+ <floater.string name="VoiceInviteP2P">
+ appelle.
+ </floater.string>
+ <floater.string name="VoiceInviteAdHoc">
+ a rejoint un chat vocal avec conférence.
+ </floater.string>
+ <text name="question">
+ Voulez-vous quitter [CURRENT_CHAT] et rejoindre ce chat vocal ?
+ </text>
+ <button label="Accepter" label_selected="Accepter" name="Accept"/>
+ <button label="Refuser" label_selected="Refuser" name="Reject"/>
+ <button label="Lancer IM" name="Start IM"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_inspect.xml b/indra/newview/skins/default/xui/fr/floater_inspect.xml
index f140c66de0..de74f47bcf 100644
--- a/indra/newview/skins/default/xui/fr/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/fr/floater_inspect.xml
@@ -1,14 +1,14 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="inspect" title="Inspecter les objets">
- <scroll_list name="object_list"
- tool_tip="Sélectionner un objet de la liste pour le mettre en surbrillance dans le Monde.">
- <column label="Nom" name="object_name" />
- <column label="Propriétaire" name="owner_name" />
- <column label="Créateur" name="creator_name" />
- <column label="Date de création" name="creation_date" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="inspect" title="INSPECTER LES OBJETS">
+ <floater.string name="timeStamp">
+ [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+ </floater.string>
+ <scroll_list name="object_list" tool_tip="Sélectionner un objet de la liste pour le mettre en surbrillance dans le Monde.">
+ <scroll_list.columns label="Nom" name="object_name"/>
+ <scroll_list.columns label="Propriétaire" name="owner_name"/>
+ <scroll_list.columns label="Créateur" name="creator_name"/>
+ <scroll_list.columns label="Date de création" name="creation_date"/>
</scroll_list>
- <button label="Voir le profil du propriétaire..." name="button owner" width="172"
- tool_tip="Voir le profil du propriétaire de l&apos;objet en surbrillance" />
- <button label="Voir le profil du créateur..." name="button creator" left="192" width="172"
- tool_tip="Voir le profil du créateur de l&apos;objet en surbrillance" />
+ <button label="Voir le profil du propriétaire..." name="button owner" tool_tip="Voir le profil du propriétaire de l&apos;objet en surbrillance" width="172"/>
+ <button label="Voir le profil du créateur..." left="192" name="button creator" tool_tip="Voir le profil du créateur de l&apos;objet en surbrillance" width="172"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_inventory.xml b/indra/newview/skins/default/xui/fr/floater_inventory.xml
index 071c0ae133..1f8b7f37ad 100644
--- a/indra/newview/skins/default/xui/fr/floater_inventory.xml
+++ b/indra/newview/skins/default/xui/fr/floater_inventory.xml
@@ -1,55 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Inventory" title="Inventaire">
- <search_editor label="Saisissez votre recherche ici" name="inventory search editor"/>
- <tab_container name="inventory filter tabs">
- <inventory_panel label="Tous les objets" name="All Items"/>
- <inventory_panel label="Objets récents" name="Recent Items"/>
- </tab_container>
- <menu_bar name="Inventory Menu">
- <menu label="Fichier" name="File">
- <tearoff_menu label="~~~~~~~~~~~" name="~~~~~~~~~~~"/>
- <menu_item_call label="Ouvrir" name="Open"/>
- <menu_item_call label="Nouvelle fenêtre" name="New Window"/>
- <menu_item_call label="Afficher les filtres" name="Show Filters"/>
- <menu_item_call label="Réinitialiser les filtres" name="Reset Current"/>
- <menu_item_call label="Fermer tous les dossiers" name="Close All Folders"/>
- <menu_item_call label="Vider la corbeille" name="Empty Trash"/>
- </menu>
- <menu label="Créer" name="Create">
- <tearoff_menu label="~~~~~~~~~~~" name="~~~~~~~~~~~"/>
- <menu_item_call label="Nouveau dossier" name="New Folder"/>
- <menu_item_call label="Nouveau script" name="New Script"/>
- <menu_item_call label="Nouvelle note" name="New Note"/>
- <menu_item_call label="Nouveau geste" name="New Gesture"/>
- <menu name="New Clothes">
- <menu_item_call label="Nouvelle chemise" name="New Shirt"/>
- <menu_item_call label="Nouveau pantalon" name="New Pants"/>
- <menu_item_call label="Nouvelles chaussures" name="New Shoes"/>
- <menu_item_call label="Nouvelles chaussettes" name="New Socks"/>
- <menu_item_call label="Nouvelle veste" name="New Jacket"/>
- <menu_item_call label="Nouvelle jupe" name="New Skirt"/>
- <menu_item_call label="Nouveaux gants" name="New Gloves"/>
- <menu_item_call label="Nouveau tricot" name="New Undershirt"/>
- <menu_item_call label="Nouveaux sous-vêtements" name="New Underpants"/>
- </menu>
- <menu name="New Body Parts">
- <menu_item_call label="Nouvelle silhouette" name="New Shape"/>
- <menu_item_call label="Nouvelle peau" name="New Skin"/>
- <menu_item_call label="Nouveaux cheveux" name="New Hair"/>
- <menu_item_call label="Nouveaux yeux" name="New Eyes"/>
- </menu>
- </menu>
- <menu label="Trier" name="Sort">
- <tearoff_menu label="~~~~~~~~~~~" name="~~~~~~~~~~~"/>
- <menu_item_check label="Par nom" name="By Name"/>
- <menu_item_check label="Par date" name="By Date"/>
- <menu_item_check label="Trier les dossiers par nom" name="Folders Always By Name"/>
- <menu_item_check label="Dossiers système en premier" name="System Folders To Top"/>
- </menu>
- <menu label="Filters" name="Filters">
- <tearoff_menu label="~~~~~~~~~~~" name="~~~~~~~~~~~"/>
- <menu_item_check label="Modifier actuel" name="Modify Current"/>
- <menu_item_call label="Réinitialiser actuel" name="Reset Current"/>
- </menu>
- </menu_bar>
+<floater name="Inventory" title="INVENTAIRE">
+ <floater.string name="Title">
+ Inventaire
+ </floater.string>
+ <floater.string name="TitleFetching">
+ Inventaire (Récupération de [ITEM_COUNT] articles en cours) [FILTER]
+ </floater.string>
+ <floater.string name="TitleCompleted">
+ Inventaire ([ITEM_COUNT] articles) [FILTER]
+ </floater.string>
+ <floater.string name="Fetched">
+ Récupéré
+ </floater.string>
+ <panel label="Panneau Inventaire" name="Inventory Panel"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/fr/floater_inventory_item_properties.xml
index 92dbc36a03..b0d5df161c 100644
--- a/indra/newview/skins/default/xui/fr/floater_inventory_item_properties.xml
+++ b/indra/newview/skins/default/xui/fr/floater_inventory_item_properties.xml
@@ -1,5 +1,20 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="item properties" title="Propriétés de l&apos;objet de l&apos;inventaire">
+<floater name="item properties" title="PROPRIÉTÉS DES ARTICLES DE L&apos;INVENTAIRE">
+ <floater.string name="unknown">
+ (inconnu)
+ </floater.string>
+ <floater.string name="public">
+ (public)
+ </floater.string>
+ <floater.string name="you_can">
+ Vous pouvez :
+ </floater.string>
+ <floater.string name="owner_can">
+ Le propriétaire peut :
+ </floater.string>
+ <floater.string name="acquiredDate">
+ [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+ </floater.string>
<text name="LabelItemNameTitle">
Nom :
</text>
@@ -27,59 +42,32 @@
Wed May 24 12:50:46 2006
</text>
<text name="OwnerLabel">
- Vous pouvez :
+ Vous :
</text>
- <check_box label="Modifier" name="CheckOwnerModify"/>
+ <check_box label="Éditer" name="CheckOwnerModify"/>
<check_box label="Copier" name="CheckOwnerCopy"/>
- <check_box label="Revendre/Donner" name="CheckOwnerTransfer"/>
- <text name="BaseMaskDebug">
- B :
- </text>
- <text name="OwnerMaskDebug">
- O :
- </text>
- <text name="GroupMaskDebug">
- G :
+ <check_box label="Revendre" name="CheckOwnerTransfer"/>
+ <text name="AnyoneLabel">
+ N&apos;importe qui :
</text>
- <text name="EveryoneMaskDebug">
- E :
+ <check_box label="Copier" name="CheckEveryoneCopy"/>
+ <text name="GroupLabel">
+ Groupe :
</text>
- <text name="NextMaskDebug">
- N :
- </text>
- <check_box label="Partager avec le groupe" name="CheckShareWithGroup"/>
- <check_box label="Autoriser tout le monde à copier" name="CheckEveryoneCopy"/>
+ <check_box label="Partager" name="CheckShareWithGroup"/>
<text name="NextOwnerLabel" width="192">
- Le prochain propriétaire pourra :
+ Le prochain propriétaire :
</text>
- <check_box label="Modifier" name="CheckNextOwnerModify"/>
+ <check_box label="Éditer" name="CheckNextOwnerModify"/>
<check_box label="Copier" name="CheckNextOwnerCopy"/>
- <check_box label="Revendre/Donner" name="CheckNextOwnerTransfer"/>
- <text name="SaleLabel">
- Marquer l&apos;objet :
- </text>
+ <check_box label="Revendre" name="CheckNextOwnerTransfer"/>
<check_box label="À vendre" name="CheckPurchase"/>
- <radio_group name="RadioSaleType">
- <radio_item name="radio">
- Original
- </radio_item>
- <radio_item name="radio2">
- Copie
- </radio_item>
- </radio_group>
- <text name="TextPrice">
- Prix : L$
+ <combo_box name="combobox sale copy">
+ <combo_box.item label="Copier" name="Copy"/>
+ <combo_box.item label="Original" name="Original"/>
+ </combo_box>
+ <spinner label="Prix :" name="Edit Cost"/>
+ <text name="CurrencySymbol">
+ L$
</text>
- <string name="unknown">
- (inconnu)
- </string>
- <string name="public">
- (public)
- </string>
- <string name="you_can">
- Vous pouvez :
- </string>
- <string name="owner_can">
- Le propriétaire peut :
- </string>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/fr/floater_inventory_view_finder.xml
index 090f5f6bc9..52f8597dc2 100644
--- a/indra/newview/skins/default/xui/fr/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/fr/floater_inventory_view_finder.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Inventory Finder" title="inventory_recent_items">
+<floater name="Inventory Finder" title="INVENTORY_RECENT_ITEMS">
<check_box label="Animations" name="check_animation"/>
<check_box label="Cartes de visite" name="check_calling_card"/>
<check_box label="Habits" name="check_clothing"/>
@@ -12,13 +12,13 @@
<check_box label="Textures" name="check_texture"/>
<check_box label="Photos" name="check_snapshot"/>
<button label="Tout" label_selected="Tout" name="All" width="70"/>
- <button label="Aucun" label_selected="Aucun" name="None" width="70" bottom="-260" left="83"/>
- <check_box label="Toujours montrer &#10;les dossiers" name="check_show_empty" bottom="-284"/>
- <check_box label="Depuis la déconnexion" name="check_since_logoff" bottom="-318"/>
- <text length="1" name="- OR -" type="string">
+ <button bottom_delta="0" label="Aucun" label_selected="Aucun" left="83" name="None" width="70"/>
+ <check_box bottom_delta="-20" label="Toujours montrer les dossiers" name="check_show_empty"/>
+ <check_box bottom_delta="-36" label="Depuis la déconnexion" name="check_since_logoff"/>
+ <text name="- OR -">
Ou il y a...
</text>
<spinner label="Heures" name="spin_hours_ago"/>
<spinner label="Jours" name="spin_days_ago"/>
- <button label="Fermer" label_selected="Fermer" name="Close"/>
+ <button bottom_delta="-30" label="Fermer" label_selected="Fermer" name="Close"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_joystick.xml b/indra/newview/skins/default/xui/fr/floater_joystick.xml
index be336c827e..d3a1b6c61b 100644
--- a/indra/newview/skins/default/xui/fr/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/fr/floater_joystick.xml
@@ -1,8 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Joystick" title="Configuration du joystick">
- <check_box name="enable_joystick">
- Activer :
- </check_box>
+<floater name="Joystick" title="CONFIGURATION DU JOYSTICK">
+ <check_box label="Activer :" name="enable_joystick"/>
<spinner label="Mapping axe des X " name="JoystickAxis1"/>
<spinner label="Mapping axe des Y" name="JoystickAxis2"/>
<spinner label="Mapping axe des Z" name="JoystickAxis0"/>
@@ -16,15 +14,9 @@
<text name="Control Modes:">
Modes de contrôle :
</text>
- <check_box name="JoystickAvatarEnabled">
- Avatar
- </check_box>
- <check_box name="JoystickBuildEnabled">
- Build
- </check_box>
- <check_box name="JoystickFlycamEnabled">
- Flycam
- </check_box>
+ <check_box label="Avatar" name="JoystickAvatarEnabled"/>
+ <check_box label="Build" name="JoystickBuildEnabled"/>
+ <check_box label="Flycam" name="JoystickFlycamEnabled"/>
<text name="XScale">
Échelle des X
</text>
@@ -73,12 +65,14 @@
<button label="Options par défaut du joystick" name="SpaceNavigatorDefaults"/>
<button label="OK" label_selected="OK" name="ok_btn"/>
<button label="Annuler" label_selected="Annuler" name="cancel_btn"/>
- <string name="JoystickMonitor">
- Contrôle du joystick
- </string>
- <string name="Axis">
- Axe [NUM]
- </string>
+ <stat_view label="Contrôle du joystick" name="axis_view">
+ <stat_bar label="Axe 0" name="axis0"/>
+ <stat_bar label="Axe 1" name="axis1"/>
+ <stat_bar label="Axe 2" name="axis2"/>
+ <stat_bar label="Axe 3" name="axis3"/>
+ <stat_bar label="Axe 4" name="axis4"/>
+ <stat_bar label="Axe 5" name="axis5"/>
+ </stat_view>
<string name="NoDevice">
aucun joystick détecté
</string>
diff --git a/indra/newview/skins/default/xui/fr/floater_lagmeter.xml b/indra/newview/skins/default/xui/fr/floater_lagmeter.xml
index 54069c9c49..20dffbbbc8 100644
--- a/indra/newview/skins/default/xui/fr/floater_lagmeter.xml
+++ b/indra/newview/skins/default/xui/fr/floater_lagmeter.xml
@@ -1,152 +1,151 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_lagmeter" title="Mesure du lag">
- <button name="client_lagmeter" tool_tip="Statut du lag client"/>
- <text name="client">
- Client :
- </text>
- <text name="client_text">
- Normal
- </text>
- <button name="network_lagmeter" tool_tip="Statut du lag réseau"/>
- <text name="network">
- Réseau :
- </text>
- <text name="network_text">
- Normal
- </text>
- <button name="server_lagmeter" tool_tip="Statut du lag serveur"/>
- <text name="server">
- Serveur :
- </text>
- <text name="server_text">
- Normal
- </text>
- <button label="?" name="server_help"/>
- <button label="&gt;&gt;" name="minimize"/>
- <string name="max_title_msg">
+<floater name="floater_lagmeter" title="MESURE DU LAG">
+ <floater.string name="max_title_msg">
Mesure du lag
- </string>
- <string name="max_width_px">
+ </floater.string>
+ <floater.string name="max_width_px">
360
- </string>
- <string name="min_title_msg">
+ </floater.string>
+ <floater.string name="min_title_msg">
Lag
- </string>
- <string name="min_width_px">
+ </floater.string>
+ <floater.string name="min_width_px">
90
- </string>
- <string name="client_text_msg">
+ </floater.string>
+ <floater.string name="client_text_msg">
Client
- </string>
- <string name="client_frame_rate_critical_fps">
+ </floater.string>
+ <floater.string name="client_frame_rate_critical_fps">
10
- </string>
- <string name="client_frame_rate_warning_fps">
+ </floater.string>
+ <floater.string name="client_frame_rate_warning_fps">
15
- </string>
- <string name="client_frame_time_window_bg_msg">
+ </floater.string>
+ <floater.string name="client_frame_time_window_bg_msg">
Normal, fenêtre en arrière-plan
- </string>
- <string name="client_frame_time_critical_msg">
+ </floater.string>
+ <floater.string name="client_frame_time_critical_msg">
Taux de défilement client ci-dessous [CLIENT_FRAME_RATE_CRITICAL]
- </string>
- <string name="client_frame_time_warning_msg">
+ </floater.string>
+ <floater.string name="client_frame_time_warning_msg">
Taux de défilement client entre [CLIENT_FRAME_RATE_CRITICAL] et [CLIENT_FRAME_RATE_WARNING]
- </string>
- <string name="client_frame_time_normal_msg">
+ </floater.string>
+ <floater.string name="client_frame_time_normal_msg">
Normal
- </string>
- <string name="client_draw_distance_cause_msg">
+ </floater.string>
+ <floater.string name="client_draw_distance_cause_msg">
Cause possible : la limite d&apos;affichage est trop élevée
- </string>
- <string name="client_texture_loading_cause_msg">
+ </floater.string>
+ <floater.string name="client_texture_loading_cause_msg">
Cause possible : images en cours de chargement
- </string>
- <string name="client_texture_memory_cause_msg">
+ </floater.string>
+ <floater.string name="client_texture_memory_cause_msg">
Cause possible : trop d&apos;images en mémoire
- </string>
- <string name="client_complex_objects_cause_msg">
+ </floater.string>
+ <floater.string name="client_complex_objects_cause_msg">
Cause possible : trop d&apos;objets complexes dans la scène
- </string>
- <string name="network_text_msg">
+ </floater.string>
+ <floater.string name="network_text_msg">
Réseau
- </string>
- <string name="network_packet_loss_critical_pct">
+ </floater.string>
+ <floater.string name="network_packet_loss_critical_pct">
10
- </string>
- <string name="network_packet_loss_warning_pct">
+ </floater.string>
+ <floater.string name="network_packet_loss_warning_pct">
5
- </string>
- <string name="network_packet_loss_critical_msg">
+ </floater.string>
+ <floater.string name="network_packet_loss_critical_msg">
La connexion perd plus de [NETWORK_PACKET_LOSS_CRITICAL] % de paquets
- </string>
- <string name="network_packet_loss_warning_msg">
+ </floater.string>
+ <floater.string name="network_packet_loss_warning_msg">
La connexion perd entre [NETWORK_PACKET_LOSS_WARNING] % et [NETWORK_PACKET_LOSS_CRITICAL] % de paquets
- </string>
- <string name="network_performance_normal_msg">
+ </floater.string>
+ <floater.string name="network_performance_normal_msg">
Normal
- </string>
- <string name="network_ping_critical_ms">
+ </floater.string>
+ <floater.string name="network_ping_critical_ms">
600
- </string>
- <string name="network_ping_warning_ms">
+ </floater.string>
+ <floater.string name="network_ping_warning_ms">
300
- </string>
- <string name="network_ping_critical_msg">
+ </floater.string>
+ <floater.string name="network_ping_critical_msg">
Temps de connexion ping supérieur à [NETWORK_PING_CRITICAL] ms
- </string>
- <string name="network_ping_warning_msg">
+ </floater.string>
+ <floater.string name="network_ping_warning_msg">
Temps de connexion ping entre [NETWORK_PING_WARNING] et [NETWORK_PING_CRITICAL] ms
- </string>
- <string name="network_packet_loss_cause_msg">
+ </floater.string>
+ <floater.string name="network_packet_loss_cause_msg">
Mauvaise connexion possible ou réglage de la bande passante trop élevé.
- </string>
- <string name="network_ping_cause_msg">
+ </floater.string>
+ <floater.string name="network_ping_cause_msg">
Mauvaise connexion possible ou app. de partage des fichiers
- </string>
- <string name="server_text_msg">
+ </floater.string>
+ <floater.string name="server_text_msg">
Serveur
- </string>
- <string name="server_frame_rate_critical_fps">
+ </floater.string>
+ <floater.string name="server_frame_rate_critical_fps">
20
- </string>
- <string name="server_frame_rate_warning_fps">
+ </floater.string>
+ <floater.string name="server_frame_rate_warning_fps">
30
- </string>
- <string name="server_single_process_max_time_ms">
+ </floater.string>
+ <floater.string name="server_single_process_max_time_ms">
20
- </string>
- <string name="server_frame_time_critical_msg">
+ </floater.string>
+ <floater.string name="server_frame_time_critical_msg">
Taux de défilement du simulateur au dessous de [SERVER_FRAME_RATE_CRITICAL]
- </string>
- <string name="server_frame_time_warning_msg">
+ </floater.string>
+ <floater.string name="server_frame_time_warning_msg">
Taux de défilement du simulateur entre [SERVER_FRAME_RATE_CRITICAL] et [SERVER_FRAME_RATE_WARNING]
- </string>
- <string name="server_frame_time_normal_msg">
+ </floater.string>
+ <floater.string name="server_frame_time_normal_msg">
Normal
- </string>
- <string name="server_physics_cause_msg">
+ </floater.string>
+ <floater.string name="server_physics_cause_msg">
Cause possible : trop d&apos;objets physiques
- </string>
- <string name="server_scripts_cause_msg">
+ </floater.string>
+ <floater.string name="server_scripts_cause_msg">
Cause possible : trop d&apos;objets scriptés
- </string>
- <string name="server_net_cause_msg">
+ </floater.string>
+ <floater.string name="server_net_cause_msg">
Cause possible : trop de trafic réseau
- </string>
- <string name="server_agent_cause_msg">
+ </floater.string>
+ <floater.string name="server_agent_cause_msg">
Cause possible : trop de personnes en mouvement dans la région
- </string>
- <string name="server_images_cause_msg">
+ </floater.string>
+ <floater.string name="server_images_cause_msg">
Cause possible : trop de calculs d&apos;images
- </string>
- <string name="server_generic_cause_msg">
+ </floater.string>
+ <floater.string name="server_generic_cause_msg">
Cause possible : charge simulateur trop lourde
- </string>
- <string name="smaller_label">
+ </floater.string>
+ <floater.string name="smaller_label">
&gt;&gt;
- </string>
- <string name="bigger_label">
+ </floater.string>
+ <floater.string name="bigger_label">
&lt;&lt;
- </string>
+ </floater.string>
+ <button name="client_lagmeter" tool_tip="Statut du lag client"/>
+ <text name="client">
+ Client
+ </text>
+ <text name="client_text">
+ Normal
+ </text>
+ <button name="network_lagmeter" tool_tip="Statut du lag réseau"/>
+ <text name="network">
+ Réseau
+ </text>
+ <text name="network_text">
+ Normal
+ </text>
+ <button name="server_lagmeter" tool_tip="Statut du lag serveur"/>
+ <text name="server">
+ Serveur
+ </text>
+ <text name="server_text">
+ Normal
+ </text>
+ <button label="&gt;&gt;" name="minimize" tool_tip="Activer/désactiver la taille du floater"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_land_holdings.xml b/indra/newview/skins/default/xui/fr/floater_land_holdings.xml
index 9c4f4ee966..10fe132623 100644
--- a/indra/newview/skins/default/xui/fr/floater_land_holdings.xml
+++ b/indra/newview/skins/default/xui/fr/floater_land_holdings.xml
@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="land holdings floater" title="Mes terrains">
+<floater name="land holdings floater" title="MES TERRAINS">
<scroll_list name="parcel list">
- <column label="Nom de la parcelle" name="name"/>
+ <column label="Parcelle" name="name"/>
<column label="Région" name="location"/>
<column label="Type" name="type"/>
<column label="Surface" name="area"/>
<column label="" name="hidden"/>
</scroll_list>
<button label="Téléporter" label_selected="Téléporter" name="Teleport" tool_tip="Téléportez-vous au milieu de ce terrain."/>
- <button label="Voir sur la carte" label_selected="Voir sur la carte" name="Show on Map" tool_tip="Affichez ce terrain sur la carte du monde."/>
+ <button label="Carte" label_selected="Carte" name="Show on Map" tool_tip="Afficher ce terrain sur la carte du monde"/>
<text name="contrib_label">
Vos contributions :
</text>
diff --git a/indra/newview/skins/default/xui/fr/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/fr/floater_live_lsleditor.xml
index e2e2a9af9a..b0a2f92f7c 100644
--- a/indra/newview/skins/default/xui/fr/floater_live_lsleditor.xml
+++ b/indra/newview/skins/default/xui/fr/floater_live_lsleditor.xml
@@ -1,12 +1,15 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script ed float" title="Script : Nouveau script">
- <button label="Réinitialiser" label_selected="Réinitialiser" name="Reset" width="100" left="390"/>
- <check_box label="Exécution en cours" name="running" left="4"/>
- <check_box label="Mono" name="mono" left="130"/>
- <string name="not_allowed">
- Vous n&apos;êtes pas autorisé à afficher ce script.
- </string>
- <string name="script_running">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="script ed float" title="SCRIPT : NOUVEAU SCRIPT">
+ <floater.string name="not_allowed">
+ Ce script ne peut pas être copié, visualisé ou modifié. Pour visualiser ou modifier un script à l&apos;intérieur d&apos;un objet, vous devez avoir les permissions requises.
+ </floater.string>
+ <floater.string name="script_running">
Exécution en cours
- </string>
+ </floater.string>
+ <floater.string name="Title">
+ Script : [NAME]
+ </floater.string>
+ <button label="Réinitialiser" label_selected="Réinitialiser" left="390" name="Reset" width="100"/>
+ <check_box initial_value="true" label="Exécution en cours" left="4" name="running"/>
+ <check_box initial_value="true" label="Mono" left="130" name="mono"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_lsl_guide.xml b/indra/newview/skins/default/xui/fr/floater_lsl_guide.xml
index 5dc0fa76a3..af6ae20dfe 100644
--- a/indra/newview/skins/default/xui/fr/floater_lsl_guide.xml
+++ b/indra/newview/skins/default/xui/fr/floater_lsl_guide.xml
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script ed float" title="Wiki LSL">
- <check_box label="Suivre le curseur" name="lock_check" />
- <combo_box label="Verrouiller" name="history_combo" left_delta="120" width="70"/>
- <button label="Précédente" name="back_btn" left_delta="75"/>
- <button label="Suivante" name="fwd_btn" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="script ed float" title="WIKI LSL">
+ <check_box label="Suivre le curseur" name="lock_check"/>
+ <combo_box label="Verrouiller" left_delta="120" name="history_combo" width="70"/>
+ <button label="Précédente" left_delta="75" name="back_btn"/>
+ <button label="Suivante" name="fwd_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_map.xml b/indra/newview/skins/default/xui/fr/floater_map.xml
new file mode 100644
index 0000000000..aeef4b0e91
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_map.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Map">
+ <floater.string name="mini_map_north">
+ N
+ </floater.string>
+ <floater.string name="mini_map_east">
+ E
+ </floater.string>
+ <floater.string name="mini_map_west">
+ O
+ </floater.string>
+ <floater.string name="mini_map_south">
+ S
+ </floater.string>
+ <floater.string name="mini_map_southeast">
+ SE
+ </floater.string>
+ <floater.string name="mini_map_northeast">
+ NE
+ </floater.string>
+ <floater.string name="mini_map_southwest">
+ SO
+ </floater.string>
+ <floater.string name="mini_map_northwest">
+ NO
+ </floater.string>
+ <floater.string name="ToolTipMsg">
+ [AGENT][REGION](Double-cliquez pour ouvrir la carte)
+ </floater.string>
+ <text label="N" name="floater_map_north" text="N">
+ N
+ </text>
+ <text label="E" name="floater_map_east" text="E">
+ E
+ </text>
+ <text label="O" name="floater_map_west" text="O">
+ O
+ </text>
+ <text label="S" name="floater_map_south" text="S">
+ S
+ </text>
+ <text label="SE" name="floater_map_southeast" text="SE">
+ SE
+ </text>
+ <text label="NE" name="floater_map_northeast" text="NE">
+ NE
+ </text>
+ <text label="SO" name="floater_map_southwest" text="SO">
+ SO
+ </text>
+ <text label="NO" name="floater_map_northwest" text="NO">
+ NO
+ </text>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_media_browser.xml b/indra/newview/skins/default/xui/fr/floater_media_browser.xml
index e75b45c43a..339ca99c92 100644
--- a/indra/newview/skins/default/xui/fr/floater_media_browser.xml
+++ b/indra/newview/skins/default/xui/fr/floater_media_browser.xml
@@ -1,5 +1,11 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_about" title="Navigateur">
+<floater name="floater_about" title="NAVIGATEUR DE MÉDIAS">
+ <floater.string name="home_page_url">
+ http://fr.secondlife.com
+ </floater.string>
+ <floater.string name="support_page_url">
+ http://fr.secondlife.com/support
+ </floater.string>
<layout_stack name="stack1">
<layout_panel name="nav_controls">
<button label="Précédente" name="back" width="75"/>
@@ -8,6 +14,11 @@
<combo_box left_delta="75" name="address" width="510"/>
<button label="OK" left_delta="515" name="go"/>
</layout_panel>
+ <layout_panel name="time_controls">
+ <button label="en arrière" name="rewind"/>
+ <button label="stop" name="stop"/>
+ <button label="en avant" name="seek"/>
+ </layout_panel>
<layout_panel name="parcel_owner_controls">
<button label="Envoyer l&apos;URL sur la parcelle" name="assign"/>
</layout_panel>
diff --git a/indra/newview/skins/default/xui/fr/floater_media_settings.xml b/indra/newview/skins/default/xui/fr/floater_media_settings.xml
new file mode 100644
index 0000000000..27db5ea995
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_media_settings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="media_settings" title="PARAMÈTRES DES MÉDIAS">
+ <button label="OK" label_selected="OK" name="OK"/>
+ <button label="Annuler" label_selected="Annuler" name="Cancel"/>
+ <button label="Appliquer" label_selected="Appliquer" name="Apply"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_mem_leaking.xml b/indra/newview/skins/default/xui/fr/floater_mem_leaking.xml
index a22d0a2934..5993f90cef 100644
--- a/indra/newview/skins/default/xui/fr/floater_mem_leaking.xml
+++ b/indra/newview/skins/default/xui/fr/floater_mem_leaking.xml
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="MemLeak" title="Simulation fuite mémoire">
- <spinner label="Vitesse de la fuite (octets) :" name="leak_speed" />
- <spinner label="Max mémoire perdue (Mo) :" name="max_leak" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="MemLeak" title="SIMULER UNE FUITE DE MÉMOIRE">
+ <spinner label="Vitesse de la fuite (octets) :" name="leak_speed"/>
+ <spinner label="Max mémoire perdue (Mo) :" name="max_leak"/>
<text name="total_leaked_label">
Mémoire perdue actuelle : [SIZE] Ko
</text>
@@ -11,8 +11,8 @@
<text name="note_label_2">
[NOTE2]
</text>
- <button label="Commencer" name="start_btn" />
- <button label="Stop" name="stop_btn" />
- <button label="Libérer" name="release_btn" />
- <button label="Fermer" name="close_btn" />
+ <button label="Commencer" name="start_btn" width="85"/>
+ <button label="Stop" left="100" name="stop_btn"/>
+ <button label="Libérer" left="177" name="release_btn"/>
+ <button label="Fermer" name="close_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_moveview.xml b/indra/newview/skins/default/xui/fr/floater_moveview.xml
index 55ea8700a6..0e8887bb96 100644
--- a/indra/newview/skins/default/xui/fr/floater_moveview.xml
+++ b/indra/newview/skins/default/xui/fr/floater_moveview.xml
@@ -1,12 +1,35 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move floater" title="">
- <button label="" label_selected="" name="turn left btn" tool_tip="Tourner à gauche"/>
- <button label="" label_selected="" name="turn right btn" tool_tip="Tourner à droite"/>
- <button label="" label_selected="" name="move up btn" tool_tip="Sauter ou voler vers le haut"/>
- <button label="" label_selected="" name="move down btn" tool_tip="S&apos;accroupir ou voler vers le bas"/>
- <button label="Voler" label_selected="Voler" name="fly btn" tool_tip="Démarrer/arrêter le vol"/>
- <joystick_slide name="slide left btn" tool_tip="Se déplacer vers la gauche"/>
- <joystick_slide name="slide right btn" tool_tip="Se déplacer vers la droite"/>
- <joystick_turn name="forward btn" tool_tip="Se déplacer vers l&apos;avant"/>
- <joystick_turn name="backward btn" tool_tip="Se déplacer vers l&apos;arrière"/>
+<floater name="move_floater">
+ <string name="walk_forward_tooltip">
+ Marcher en avant (appuyer sur la flèche vers le haut ou W)
+ </string>
+ <string name="walk_back_tooltip">
+ Marcher en arrière (appuyer sur la flèche vers le bas ou S)
+ </string>
+ <string name="run_forward_tooltip">
+ Courir vers l&apos;avant (appuyer sur la flèche vers le haut ou W)
+ </string>
+ <string name="run_back_tooltip">
+ Courir en arrière (appuyer sur la flèche vers le bas ou S)
+ </string>
+ <string name="fly_forward_tooltip">
+ Voler vers l&apos;avant (appuyer sur la flèche vers le haut ou W)
+ </string>
+ <string name="fly_back_tooltip">
+ Voler vers l&apos;arrière (appuyer sur la flèche vers le bas ou S)
+ </string>
+ <panel name="panel_actions">
+ <button label="" label_selected="" name="turn left btn" tool_tip="Tourner à gauche (appuyer sur la flèche de gauche ou sur A)"/>
+ <button label="" label_selected="" name="turn right btn" tool_tip="Tourner à droite (appuyer sur la flèche de droite ou sur D)"/>
+ <button label="" label_selected="" name="move up btn" tool_tip="Voler vers le haut, appuyer sur E"/>
+ <button label="" label_selected="" name="move down btn" tool_tip="Voler vers le bas, appuyer sur C"/>
+ <joystick_turn name="forward btn" tool_tip="Marcher en avant (appuyer sur la flèche vers le haut ou W)"/>
+ <joystick_turn name="backward btn" tool_tip="Marcher en arrière (appuyer sur la flèche vers le bas ou S)"/>
+ </panel>
+ <panel name="panel_modes">
+ <button label="" name="mode_walk_btn" tool_tip="Mode marche"/>
+ <button label="" name="mode_run_btn" tool_tip="Mode course"/>
+ <button label="" name="mode_fly_btn" tool_tip="Mode vol"/>
+ <button label="Atterrir" name="stop_fly_btn" tool_tip="Atterrir"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_mute_object.xml b/indra/newview/skins/default/xui/fr/floater_mute_object.xml
index 23d351f32d..f4db3201a8 100644
--- a/indra/newview/skins/default/xui/fr/floater_mute_object.xml
+++ b/indra/newview/skins/default/xui/fr/floater_mute_object.xml
@@ -1,12 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="mute by name" title="Ignorer les objets par nom">
+<floater name="mute by name" title="IGNORER L&apos;OBJET PAR NOM">
<text name="message">
- Cette fonction ne marche que pour les chats et les IM,
-pas les sons. Saisissez le nom exact de l&apos;objet.
+ Ignorer un objet :
</text>
<line_editor name="object_name">
Nom de l&apos;objet
</line_editor>
+ <text name="note">
+ * Ignore uniquement le texte de l&apos;objet, pas les sons
+ </text>
<button label="OK" name="OK"/>
<button label="Annuler" name="Cancel"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_my_friends.xml b/indra/newview/skins/default/xui/fr/floater_my_friends.xml
index 911647d8be..db7c026e22 100644
--- a/indra/newview/skins/default/xui/fr/floater_my_friends.xml
+++ b/indra/newview/skins/default/xui/fr/floater_my_friends.xml
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_my_friends" title="Contacts">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_my_friends" title="CONTACTS">
<tab_container name="friends_and_groups">
- <panel label="Amis" name="friends_panel" />
- <panel label="Groupes" name="groups_panel" />
+ <panel label="Amis" name="friends_panel"/>
+ <panel label="Groupes" name="groups_panel"/>
</tab_container>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_nearby_chat.xml b/indra/newview/skins/default/xui/fr/floater_nearby_chat.xml
new file mode 100644
index 0000000000..72775169cb
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_nearby_chat.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="nearby_chat" title="CHAT PRÈS DE VOUS"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_notification.xml b/indra/newview/skins/default/xui/fr/floater_notification.xml
index 7ca2dc3a64..62727da007 100644
--- a/indra/newview/skins/default/xui/fr/floater_notification.xml
+++ b/indra/newview/skins/default/xui/fr/floater_notification.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="notification" title="Console de notifications">
+<floater name="notification" title="CONSOLE DE NOTIFICATIONS">
<text_editor name="payload">
Chargement..
</text_editor>
diff --git a/indra/newview/skins/default/xui/fr/floater_notifications_console.xml b/indra/newview/skins/default/xui/fr/floater_notifications_console.xml
index 7262fe8fe2..e040e948f5 100644
--- a/indra/newview/skins/default/xui/fr/floater_notifications_console.xml
+++ b/indra/newview/skins/default/xui/fr/floater_notifications_console.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="notifications_console" title="Console de notifications">
+<floater name="notifications_console" title="CONSOLE DE NOTIFICATIONS">
<combo_box label="Sélectionner le type de notification" name="notification_types" width="412"/>
- <button label="Ajouter" name="add_notification" left="417" width="78"/>
+ <button label="Ajouter" left="417" name="add_notification" width="78"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_openobject.xml b/indra/newview/skins/default/xui/fr/floater_openobject.xml
index 36c712e8a3..4e046ff3f3 100644
--- a/indra/newview/skins/default/xui/fr/floater_openobject.xml
+++ b/indra/newview/skins/default/xui/fr/floater_openobject.xml
@@ -1,8 +1,8 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="objectcontents" title="Contenu des objets">
- <text type="string" length="1" name="object_name">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="objectcontents" title="CONTENU DES OBJETS">
+ <text name="object_name">
[DESC]:
</text>
- <button label="Copier vers l&apos;inventaire" label_selected="Copier vers l&apos;inventaire" name="copy_to_inventory_button" width="132" />
- <button label="Copier et porter" label_selected="Copier et porter" name="copy_and_wear_button" left="152"/>
+ <button label="Copier vers l&apos;inventaire" label_selected="Copier vers l&apos;inventaire" name="copy_to_inventory_button" width="132"/>
+ <button label="Copier et porter" label_selected="Copier et porter" left="152" name="copy_and_wear_button"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_outgoing_call.xml b/indra/newview/skins/default/xui/fr/floater_outgoing_call.xml
new file mode 100644
index 0000000000..38a9109c84
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_outgoing_call.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="outgoing call" title="APPEL EN COURS">
+ <floater.string name="localchat">
+ Chat vocal près de vous
+ </floater.string>
+ <floater.string name="anonymous">
+ anonyme
+ </floater.string>
+ <floater.string name="VoiceInviteP2P">
+ appelle.
+ </floater.string>
+ <floater.string name="VoiceInviteAdHoc">
+ a rejoint un chat vocal avec conférence.
+ </floater.string>
+ <text name="connecting">
+ Connexion à [CALLEE_NAME] en cours
+ </text>
+ <text name="calling">
+ En train d&apos;appeler [CALLEE_NAME]
+ </text>
+ <text name="noanswer">
+ Pas de réponse. Veuillez réessayer ultérieurement.
+ </text>
+ <text name="leaving">
+ En train de quitter [CURRENT_CHAT].
+ </text>
+ <button label="Annuler" label_selected="Annuler" name="Cancel"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_pay.xml b/indra/newview/skins/default/xui/fr/floater_pay.xml
index c5b689e2dd..30e510efb5 100644
--- a/indra/newview/skins/default/xui/fr/floater_pay.xml
+++ b/indra/newview/skins/default/xui/fr/floater_pay.xml
@@ -1,22 +1,26 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Give Money" title="">
- <button label="1 L$" label_selected="1 L$" name="fastpay 1"/>
- <button label="5 L$" label_selected="5 L$" name="fastpay 5"/>
- <button label="10 L$" label_selected="10 L$" name="fastpay 10"/>
- <button label="20 L$" label_selected="20 L$" name="fastpay 20"/>
- <button label="Payer" label_selected="Payer" name="pay btn"/>
- <button label="Annuler" label_selected="Annuler" name="cancel btn"/>
- <text length="1" name="payee_label" type="string" left="5">
+ <string name="payee_group">
+ Payer le groupe
+ </string>
+ <string name="payee_resident">
+ Payer le résident
+ </string>
+ <text left="5" name="payee_label">
Payer :
</text>
- <text length="1" name="payee_name" type="string">
+ <icon name="icon_person" tool_tip="Résident"/>
+ <text name="payee_name">
[FIRST] [LAST]
</text>
- <text length="1" name="fastpay text" type="string" width="100" halign="left">
- Paiement rapide :
- </text>
- <text left="4" length="1" name="amount text" type="string">
- Montant :
+ <button label="1 L$" label_selected="1 L$" name="fastpay 1"/>
+ <button label="5 L$" label_selected="5 L$" name="fastpay 5"/>
+ <button label="10 L$" label_selected="10 L$" name="fastpay 10"/>
+ <button label="20 L$" label_selected="20 L$" name="fastpay 20"/>
+ <text left="4" name="amount text">
+ Ou choisissez un montant :
</text>
<line_editor left="60" name="amount" width="55"/>
+ <button label="Payer" label_selected="Payer" name="pay btn"/>
+ <button label="Annuler" label_selected="Annuler" name="cancel btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_pay_object.xml b/indra/newview/skins/default/xui/fr/floater_pay_object.xml
index 3dc0af75e8..c96db77721 100644
--- a/indra/newview/skins/default/xui/fr/floater_pay_object.xml
+++ b/indra/newview/skins/default/xui/fr/floater_pay_object.xml
@@ -1,31 +1,30 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Give Money" title="">
- <text length="1" name="payee_group" type="string" width="95">
- Payer le groupe :
- </text>
- <text length="1" name="payee_resident" type="string" width="100" halign="left" >
- Payer le résident :
- </text>
- <text length="1" name="payee_name" type="string" left="105">
+ <string name="payee_group" width="95">
+ Payer le groupe
+ </string>
+ <string halign="left" name="payee_resident" width="100">
+ Payer le résident
+ </string>
+ <icon name="icon_person" tool_tip="Résident"/>
+ <text left="105" name="payee_name">
[FIRST] [LAST]
</text>
- <text length="1" name="object_name_label" type="string" left="25">
+ <text left="25" name="object_name_label">
Via un objet :
</text>
- <text length="1" name="object_name_text" type="string" left="105">
+ <icon name="icon_object" tool_tip="Objets"/>
+ <text left="105" name="object_name_text">
...
</text>
- <text length="1" name="fastpay text" type="string" width="95">
- Paiement rapide :
- </text>
- <text length="1" name="amount text" type="string" left="5" halign="left">
- Montant :
+ <button label="1 L$" label_selected="1 L$" left="105" name="fastpay 1"/>
+ <button label="5 L$" label_selected="5 L$" left="190" name="fastpay 5"/>
+ <button label="10 L$" label_selected="10 L$" left="105" name="fastpay 10"/>
+ <button label="20 L$" label_selected="20 L$" left="190" name="fastpay 20"/>
+ <text halign="left" left="5" name="amount text">
+ Ou choisissez un montant :
</text>
- <button label="1 L$" label_selected="1 L$" name="fastpay 1" left="105" />
- <button label="5 L$" label_selected="5 L$" name="fastpay 5" left="190"/>
- <button label="10 L$" label_selected="10 L$" name="fastpay 10" left="105" />
- <button label="20 L$" label_selected="20 L$" name="fastpay 20" left="190"/>
+ <line_editor left="65" name="amount" width="50"/>
<button label="Payer" label_selected="Payer" name="pay btn"/>
<button label="Annuler" label_selected="Annuler" name="cancel btn"/>
- <line_editor left="65" name="amount" width="50" />
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_perm_prefs.xml b/indra/newview/skins/default/xui/fr/floater_perm_prefs.xml
index 9ea970d89d..2be2ae7c88 100644
--- a/indra/newview/skins/default/xui/fr/floater_perm_prefs.xml
+++ b/indra/newview/skins/default/xui/fr/floater_perm_prefs.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="perm prefs" title="Droits par défaut">
+<floater name="perm prefs" title="PERMISSIONS DE CHARGEMENT PAR DÉFAUT">
<panel label="Droits" name="permissions">
<button label="?" label_selected="?" name="help"/>
<check_box label="Partager avec le groupe" name="share_with_group"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_post_process.xml b/indra/newview/skins/default/xui/fr/floater_post_process.xml
index 52afb340a6..a22c7512e5 100644
--- a/indra/newview/skins/default/xui/fr/floater_post_process.xml
+++ b/indra/newview/skins/default/xui/fr/floater_post_process.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Post-Process Floater" title="Paramètres post-traitement">
+<floater name="Post-Process Floater" title="PARAMÈTRES POST-TRAITEMENT">
<tab_container name="Post-Process Tabs">
<panel label="Filtre couleur" name="wmiColorFilterPanel">
<check_box label="Activer" name="wmiColorFilterToggle" />
diff --git a/indra/newview/skins/default/xui/fr/floater_postcard.xml b/indra/newview/skins/default/xui/fr/floater_postcard.xml
index 38eb0ced4a..6a9a674fac 100644
--- a/indra/newview/skins/default/xui/fr/floater_postcard.xml
+++ b/indra/newview/skins/default/xui/fr/floater_postcard.xml
@@ -1,40 +1,38 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Postcard" title="Envoyer la photo par e-mail">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Postcard" title="ENVOYER LA PHOTO PAR E-MAIL">
<text name="to_label" width="135">
E-mail du destinataire :
</text>
- <line_editor name="to_form" left="143" width="127" />
+ <line_editor left="143" name="to_form" width="127"/>
<text name="from_label">
Votre e-mail :
</text>
- <line_editor name="from_form" left="143" width="127" />
+ <line_editor left="143" name="from_form" width="127"/>
<text name="name_label">
Votre nom :
</text>
- <line_editor name="name_form" left="143" width="127" />
+ <line_editor left="143" name="name_form" width="127"/>
<text name="subject_label">
Sujet :
</text>
- <line_editor name="subject_form" left="143" width="127" />
- <line_editor label="Saisissez votre sujet ici." name="subject_form" />
+ <line_editor left="143" name="subject_form" width="127"/>
+ <line_editor label="Saisissez votre sujet ici." name="subject_form"/>
<text name="msg_label">
Message :
</text>
- <check_box label="Publier sur le web" name="allow_publish_check"
- tool_tip="Publiez cette carte postale sur le web." />
- <check_box label="Contenu adulte" name="mature_check"
- tool_tip="Cette carte postale est à caractère adulte." />
- <button label="?" name="publish_help_btn" />
+ <check_box label="Publier sur le web" name="allow_publish_check" tool_tip="Publiez cette carte postale sur le web."/>
+ <check_box label="Contenu adulte" name="mature_check" tool_tip="Cette carte postale est à caractère adulte."/>
+ <button label="?" name="publish_help_btn"/>
<text_editor name="msg_form">
Saisissez votre message ici.
</text_editor>
<text name="fine_print">
- Si le destinataire s&apos;inscrit sur Second Life, vous recevrez un bonus.
+ Si le destinataire s&apos;inscrit sur [SECOND_LIFE], vous recevrez un bonus.
</text>
- <button label="Annuler" name="cancel_btn" />
- <button label="Envoyer" name="send_btn" />
+ <button label="Annuler" name="cancel_btn"/>
+ <button label="Envoyer" name="send_btn"/>
<string name="default_subject">
- Carte postale de Second Life.
+ Carte postale de [SECOND_LIFE].
</string>
<string name="default_message">
Ouvrez-moi !
diff --git a/indra/newview/skins/default/xui/fr/floater_preferences.xml b/indra/newview/skins/default/xui/fr/floater_preferences.xml
index 9dab4d642c..3e6d3611cc 100644
--- a/indra/newview/skins/default/xui/fr/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/fr/floater_preferences.xml
@@ -1,9 +1,15 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Preferences" title="Préférences" min_width="330" width="626">
- <button label="À propos" label_selected="À propos" name="About..." />
- <button label="OK" label_selected="OK" name="OK" />
- <button label="Annuler" label_selected="Annuler" name="Cancel" />
- <button label="Appliquer" label_selected="Appliquer" name="Apply" />
- <button label="Aide" label_selected="Aide" name="Help" />
- <tab_container name="pref core" tab_width="126" width="626" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater min_width="330" name="Preferences" title="PRÉFÉRENCES" width="626">
+ <button label="OK" label_selected="OK" name="OK"/>
+ <button label="Annuler" label_selected="Annuler" name="Cancel"/>
+ <tab_container name="pref core" tab_width="126" width="626">
+ <panel label="Général" name="general"/>
+ <panel label="Graphiques" name="display"/>
+ <panel label="Confidentialité" name="im"/>
+ <panel label="Son" name="audio"/>
+ <panel label="Chat" name="chat"/>
+ <panel label="Alertes" name="msgs"/>
+ <panel label="Configuration" name="input"/>
+ <panel label="Avancées" name="advanced1"/>
+ </tab_container>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_preview_animation.xml b/indra/newview/skins/default/xui/fr/floater_preview_animation.xml
index 0ee4ea1df6..923d56801e 100644
--- a/indra/newview/skins/default/xui/fr/floater_preview_animation.xml
+++ b/indra/newview/skins/default/xui/fr/floater_preview_animation.xml
@@ -1,10 +1,11 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="preview_anim">
- <text type="string" length="1" name="desc txt">
+ <floater.string name="Title">
+ Animation : [NAME]
+ </floater.string>
+ <text name="desc txt">
Description :
</text>
- <button label="Jouer dans le Monde" label_selected="Stop" name="Anim play btn"
- tool_tip="Jouer cette animation et partagez-la avec d&apos;autres." width="131" left="20"/>
- <button label="Jouer localement" label_selected="Stop" name="Anim audition btn"
- tool_tip="Jouer cette animation et soyez le seul à la voir." width="125" left="162"/>
+ <button label="Jouer dans le Monde" label_selected="Stop" left="20" name="Anim play btn" tool_tip="Lire cette animation de façon à ce que les autres puissent la voir" width="131"/>
+ <button label="Jouer localement" label_selected="Stop" left="162" name="Anim audition btn" tool_tip="Lire cette animation de façon à ce que vous soyez la seule personne à pouvoir la voir" width="125"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_preview_classified.xml b/indra/newview/skins/default/xui/fr/floater_preview_classified.xml
index 1b6f26150d..23f86d88b9 100644
--- a/indra/newview/skins/default/xui/fr/floater_preview_classified.xml
+++ b/indra/newview/skins/default/xui/fr/floater_preview_classified.xml
@@ -1,2 +1,6 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="classified_preview" title="Informations sur la petite annonce" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="classified_preview" title="INFOS SUR LA PETITE ANNONCE">
+ <floater.string name="Title">
+ Petite annonce : [NAME]
+ </floater.string>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_preview_event.xml b/indra/newview/skins/default/xui/fr/floater_preview_event.xml
index e7fc2aa8dd..7590c43af1 100644
--- a/indra/newview/skins/default/xui/fr/floater_preview_event.xml
+++ b/indra/newview/skins/default/xui/fr/floater_preview_event.xml
@@ -1,2 +1,6 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="event_preview" title="Informations sur l&apos;événement" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="event_preview" title="INFORMATIONS SUR LES ÉVÉNEMENTS">
+ <floater.string name="Title">
+ Événement : [NAME]
+ </floater.string>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_preview_gesture.xml b/indra/newview/skins/default/xui/fr/floater_preview_gesture.xml
index 5322993b0b..6e8767ea07 100644
--- a/indra/newview/skins/default/xui/fr/floater_preview_gesture.xml
+++ b/indra/newview/skins/default/xui/fr/floater_preview_gesture.xml
@@ -1,65 +1,66 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="gesture_preview">
- <string name="stop_txt">
+ <floater.string name="step_anim">
+ Animation à jouer :
+ </floater.string>
+ <floater.string name="step_sound">
+ Son à lire :
+ </floater.string>
+ <floater.string name="step_chat">
+ Chatter pour dire :
+ </floater.string>
+ <floater.string name="step_wait">
+ Attendre :
+ </floater.string>
+ <floater.string name="stop_txt">
Stop
- </string>
- <string name="preview_txt">
+ </floater.string>
+ <floater.string name="preview_txt">
Prévisualiser
- </string>
- <string name="none_text">
+ </floater.string>
+ <floater.string name="none_text">
-- Aucune --
- </string>
+ </floater.string>
+ <floater.string name="Title">
+ Geste : [NAME]
+ </floater.string>
<text name="desc_label">
Description :
</text>
<text name="trigger_label">
Déclencheur :
</text>
- <text name="replace_text"
- tool_tip="Remplacer les raccourcis avec ces mots. Par exemple, remplacer le mot-clé « salut » par « bonjour » fera dire « je venais dire bonjour » au lieu de « je venais dire salut » dans le chat, et déclenchera le geste.">
+ <text name="replace_text" tool_tip="Remplacer les raccourcis avec ces mots. Par exemple, remplacer le mot-clé « salut » par « bonjour » fera dire « je venais dire bonjour » au lieu de « je venais dire salut » dans le chat, et déclenchera le geste.">
Remplacer par :
</text>
- <line_editor left="310" name="replace_editor"
- tool_tip="Remplacer les raccourcis avec ces mots. Par exemple, remplacer le mot-clé « salut » par « bonjour » fera dire « je venais dire bonjour » au lieu de « je venais dire salut » dans le chat, et déclenchera le geste"
- width="120" />
+ <line_editor left="310" name="replace_editor" tool_tip="Remplacer les raccourcis avec ces mots. Par exemple, remplacer le mot-clé « salut » par « bonjour » fera dire « je venais dire bonjour » au lieu de « je venais dire salut » dans le chat, et déclenchera le geste" width="120"/>
<text name="key_label">
Raccourci :
</text>
- <combo_box label="Aucun" name="modifier_combo" width="55" />
- <combo_box label="Aucun" name="key_combo" width="55" />
+ <combo_box label="Aucun" name="modifier_combo" width="55"/>
+ <combo_box label="Aucun" name="key_combo" width="55"/>
<text name="library_label">
Bibliothèque :
</text>
+ <scroll_list name="library_list"/>
+ <button label="Ajouter &gt;&gt;" name="add_btn"/>
<text name="steps_label">
Étapes :
</text>
- <scroll_list name="library_list">
- Animation
-Son
-Chat
-Attendre
- </scroll_list>
- <button label="Ajouter &gt;&gt;" name="add_btn" />
- <button label="Monter" name="up_btn" />
- <button label="Descendre" name="down_btn" />
- <button label="Supprimer" name="delete_btn" />
- <text name="help_label">
- Toutes les étapes ont lieu
-simultanément, sauf si vous
-ajoutez des pauses.
- </text>
+ <button label="Vers le haut" name="up_btn"/>
+ <button label="Vers le bas" name="down_btn"/>
+ <button label="Supprimer" name="delete_btn"/>
<radio_group name="animation_trigger_type">
- <radio_item name="start">
- Commencer
- </radio_item>
- <radio_item name="stop">
- Stop
- </radio_item>
+ <radio_item label="Lancer" name="start"/>
+ <radio_item label="Arrêter" name="stop"/>
</radio_group>
- <check_box label="jusqu&apos;à la fin des animations" name="wait_anim_check" />
- <check_box label="temps en secondes" name="wait_time_check" />
- <check_box label="Actifs" name="active_check"
- tool_tip="Les gestes actifs peuvent être déclenchés en saisissant leur raccourci dans le chat ou en appuyant sur les raccourcis. Les gestes deviennent généralement inactifs lorsqu&apos;il y a un conflit entre les raccourcis." />
- <button label="Prévisualiser" name="preview_btn" width="86" />
- <button label="Enregistrer" name="save_btn" width="86" left_delta="96"/>
+ <check_box label="jusqu&apos;à la fin des animations" name="wait_anim_check"/>
+ <check_box label="temps en secondes" name="wait_time_check"/>
+ <line_editor left_delta="130" name="wait_time_editor"/>
+ <text name="help_label">
+ Toutes les étapes ont lieu en même temps si vous n&apos;ajoutez pas d&apos;étapes d&apos;attente.
+ </text>
+ <check_box label="Actifs" name="active_check" tool_tip="Les gestes actifs peuvent être déclenchés en saisissant leur raccourci dans le chat ou en appuyant sur les raccourcis. Les gestes deviennent généralement inactifs lorsqu&apos;il y a un conflit entre les raccourcis."/>
+ <button label="Prévisualiser" name="preview_btn" width="86"/>
+ <button label="Enregistrer" left_delta="96" name="save_btn" width="86"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_preview_gesture_info.xml b/indra/newview/skins/default/xui/fr/floater_preview_gesture_info.xml
new file mode 100644
index 0000000000..4a91992f6a
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_preview_gesture_info.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Gesture" title="RACCOURCI DU GESTE"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_preview_gesture_shortcut.xml b/indra/newview/skins/default/xui/fr/floater_preview_gesture_shortcut.xml
new file mode 100644
index 0000000000..06caf0635d
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_preview_gesture_shortcut.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Gesture" title="RACCOURCI DU GESTE">
+ <text name="trigger_label">
+ Chat :
+ </text>
+ <text name="key_label">
+ Clavier :
+ </text>
+ <combo_box label="Aucun" name="modifier_combo"/>
+ <combo_box label="Aucun" name="key_combo"/>
+ <text name="replace_text" tool_tip="Remplacez le ou les mots-clés par ces mots. Par exemple, si vous remplacez le mot-clé &quot; bonjour &quot; par &quot; salut &quot;, le chat &quot; Je voulais te dire bonjour &quot; devient &quot; Je voulais te dire salut &quot; et le geste correspondant s&apos;affiche.">
+ Remplacer :
+ </text>
+ <line_editor name="replace_editor" tool_tip="Remplacez le ou les mots-clés par ces mots. Par exemple, si vous remplacez le mot-clé &quot; bonjour &quot; par &quot; salut &quot;, le chat &quot; Je voulais te dire bonjour &quot; devient &quot; Je voulais te dire salut &quot; et le geste correspondant s&apos;affiche."/>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_preview_gesture_steps.xml b/indra/newview/skins/default/xui/fr/floater_preview_gesture_steps.xml
new file mode 100644
index 0000000000..4a91992f6a
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_preview_gesture_steps.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Gesture" title="RACCOURCI DU GESTE"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_preview_notecard.xml b/indra/newview/skins/default/xui/fr/floater_preview_notecard.xml
index 5e7d7b86ad..a10c01a24c 100644
--- a/indra/newview/skins/default/xui/fr/floater_preview_notecard.xml
+++ b/indra/newview/skins/default/xui/fr/floater_preview_notecard.xml
@@ -1,16 +1,22 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="preview notecard" title="Remarque :">
- <button label="Enregistrer" label_selected="Enregistrer" name="Save" />
- <text type="string" length="1" name="desc txt">
+ <floater.string name="no_object">
+ Impossible de trouver l&apos;objet contenant cette note.
+ </floater.string>
+ <floater.string name="not_allowed">
+ Vous n&apos;avez pas le droit de voir cette note.
+ </floater.string>
+ <floater.string name="Title">
+ Note : [NAME]
+ </floater.string>
+ <floater.string label="Enregistrer" label_selected="Enregistrer" name="Save">
+ Enregistrer
+ </floater.string>
+ <text name="desc txt">
Description :
</text>
- <text_editor type="string" length="1" name="Notecard Editor">
+ <text_editor name="Notecard Editor">
Chargement...
</text_editor>
- <string name="no_object">
- Impossible de trouver l&apos;objet contenant cette note.
- </string>
- <string name="not_allowed">
- Vous n&apos;êtes pas autorisé à afficher cette note.
- </string>
+ <button label="Enregistrer" label_selected="Enregistrer" name="Save"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_preview_sound.xml b/indra/newview/skins/default/xui/fr/floater_preview_sound.xml
index e55ca1a583..67d93e9e92 100644
--- a/indra/newview/skins/default/xui/fr/floater_preview_sound.xml
+++ b/indra/newview/skins/default/xui/fr/floater_preview_sound.xml
@@ -1,12 +1,11 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="preview_sound">
- <text type="string" length="1" name="desc txt">
+ <floater.string name="Title">
+ Son : [NAME]
+ </floater.string>
+ <text name="desc txt">
Description :
</text>
- <button label="Jouer dans le Monde" label_selected="Jouer dans le Monde"
- name="Sound play btn"
- tool_tip="Jouer ce son et partagez-le avec d&apos;autres." width="131" left_delta="-142"/>
- <button label="Jouer localement" label_selected="Jouer localement"
- name="Sound audition btn"
- tool_tip="Jouer ce son et soyez le seul à l&apos;entendre." width="125" left="162"/>
+ <button label="Jouer dans le Monde" label_selected="Jouer dans le Monde" left_delta="-142" name="Sound play btn" tool_tip="Lire ce son de façon à ce que les autres puissent l&apos;entendre" width="131"/>
+ <button label="Jouer localement" label_selected="Jouer localement" left="162" name="Sound audition btn" tool_tip="Lire ce son de façon à ce que vous soyez la seule personne à pouvoir l&apos;entendre" width="125"/>
</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 245847809e..0acfd72323 100644
--- a/indra/newview/skins/default/xui/fr/floater_preview_texture.xml
+++ b/indra/newview/skins/default/xui/fr/floater_preview_texture.xml
@@ -1,9 +1,46 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="preview_texture">
- <text type="string" length="1" name="desc txt">
+ <floater.string name="Title">
+ Texture : [NAME]
+ </floater.string>
+ <floater.string name="Copy">
+ Copier dans l&apos;inventaire
+ </floater.string>
+ <text name="desc txt">
Description :
</text>
- <text type="string" length="1" name="dimensions">
- Dimensions : [WIDTH] x [HEIGHT]
+ <button label="OK" name="Keep"/>
+ <button label="Annuler" name="Discard"/>
+ <text name="dimensions">
+ [WIDTH] px x [HEIGHT] px
</text>
+ <text name="aspect_ratio">
+ Aperçu du rapport hauteur/largeur
+ </text>
+ <combo_box name="combo_aspect_ratio" tool_tip="Aperçu avec un rapport hauteur/largeur fixe">
+ <combo_item name="Unconstrained">
+ Sans contraintes
+ </combo_item>
+ <combo_item name="1:1" tool_tip="Logo du groupe ou profil dans le monde physique">
+ 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 des terrains">
+ 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>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_region_info.xml b/indra/newview/skins/default/xui/fr/floater_region_info.xml
index d69f212b86..c2663174d4 100644
--- a/indra/newview/skins/default/xui/fr/floater_region_info.xml
+++ b/indra/newview/skins/default/xui/fr/floater_region_info.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="regioninfo" title="Région et domaine"/>
+<floater name="regioninfo" title="RÉGION/DOMAINE"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_report_abuse.xml b/indra/newview/skins/default/xui/fr/floater_report_abuse.xml
index 628f308f88..c6ffd32650 100644
--- a/indra/newview/skins/default/xui/fr/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/fr/floater_report_abuse.xml
@@ -1,12 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_report_abuse" title="Signaler une infraction">
- <texture_picker label="" name="screenshot"/>
- <check_box label="Inclure une capture d&apos;écran" name="screen_check"/>
+<floater name="floater_report_abuse" title="SIGNALER UNE INFRACTION">
+ <floater.string name="Screenshot">
+ Capture d&apos;écran
+ </floater.string>
+ <check_box label="Utiliser cette capture d&apos;écran" name="screen_check"/>
<text name="reporter_title" width="60">
Déposant :
</text>
<text name="reporter_field">
- Loremipsum Dolorsitamut
+ Loremipsum Dolorsitamut Longnamez
</text>
<text name="sim_title">
Région :
@@ -21,11 +23,11 @@
{128.1, 128.1, 15.4}
</text>
<text name="select_object_label">
- Cliquez sur le bouton puis l&apos;objet :
+ Cliquez sur le bouton puis l&apos;objet responsable :
</text>
<button label="" label_selected="" name="pick_btn" tool_tip="Le sélecteur d&apos;objet vous permet d&apos;identifier un objet comme sujet du rapport."/>
<text name="object_name_label">
- Nom :
+ Objet :
</text>
<text left_delta="70" name="object_name" width="105">
Consetetur Sadipscing
@@ -34,132 +36,53 @@
Propriétaire :
</text>
<text left_delta="70" name="owner_name" width="105">
- Hendrerit Vulputate
+ Hendrerit Vulputate Kamawashi Longname
</text>
<combo_box name="category_combo" tool_tip="Choisissez la catégorie qui décrit le mieux ce rapport">
- <combo_item name="Select_category">
- Sélectionnez une catégorie
- </combo_item>
- <combo_item name="Age__Age_play">
- Âge &gt; « Age play »
- </combo_item>
- <combo_item name="Age__Adult_resident_on_Teen_Second_Life">
- Âge &gt; Résident adulte sur Second Life pour adolescents
- </combo_item>
- <combo_item name="Age__Underage_resident_outside_of_Teen_Second_Life">
- Âge &gt; Resident mineur en dehors de Teen Second Life
- </combo_item>
- <combo_item name="Assault__Combat_sandbox___unsafe_area">
- Assaut &gt; Bac à sable utilisé pour des combats/zone non sécurisée
- </combo_item>
- <combo_item name="Assault__Safe_area">
- Assaut &gt; Zone sécurisée
- </combo_item>
- <combo_item name="Assault__Weapons_testing_sandbox">
- Assaut &gt; Bac à sable pour tests d&apos;armes à feu
- </combo_item>
- <combo_item name="Commerce__Failure_to_deliver_product_or_service">
- Commerce &gt; Incapacité à fournir un produit ou service
- </combo_item>
- <combo_item name="Disclosure__Real_world_information">
- Divulgation &gt; Informations sur la vie réelle
- </combo_item>
- <combo_item name="Disclosure__Remotely_monitoring chat">
- Divulgation &gt; Écoute d&apos;un chat à distance
- </combo_item>
- <combo_item name="Disclosure__Second_Life_information_chat_IMs">
- Divulgation &gt; Informations sur Second Life/chat/IM
- </combo_item>
- <combo_item name="Disturbing_the_peace__Unfair_use_of_region_resources">
- Trouble de la paix &gt; Utilisation inadéquate des ressources de la région
- </combo_item>
- <combo_item name="Disturbing_the_peace__Excessive_scripted_objects">
- Trouble de la paix &gt; Nombre d&apos;objets scriptés excessif
- </combo_item>
- <combo_item name="Disturbing_the_peace__Object_littering">
- Trouble de la paix &gt; Abandon d&apos;objets
- </combo_item>
- <combo_item name="Disturbing_the_peace__Repetitive_spam">
- Trouble de la paix &gt; Spam à répétition
- </combo_item>
- <combo_item name="Disturbing_the_peace__Unwanted_advert_spam">
- Trouble de la paix &gt; Spam à caractère commercial
- </combo_item>
- <combo_item name="Fraud__L$">
- Fraude &gt; L$
- </combo_item>
- <combo_item name="Fraud__Land">
- Fraude &gt; Terrain
- </combo_item>
- <combo_item name="Fraud__Pyramid_scheme_or_chain_letter">
- Fraude &gt; Vente pyramidale ou lettre-chaîne
- </combo_item>
- <combo_item name="Fraud__US$">
- Fraude &gt; US$
- </combo_item>
- <combo_item name="Harassment__Advert_farms___visual_spam">
- Harcèlement &gt; Spam visuel
- </combo_item>
- <combo_item name="Harassment__Defaming_individuals_or_groups">
- Harcèlement &gt; Diffamation envers des individus ou des groupes
- </combo_item>
- <combo_item name="Harassment__Impeding_movement">
- Harcèlement &gt; Immobilisation
- </combo_item>
- <combo_item name="Harassment__Sexual_harassment">
- Harcèlement &gt; Harcèlement sexuel
- </combo_item>
- <combo_item name="Harassment__Solicting_inciting_others_to_violate_ToS">
- Harcèlement &gt; Incitation à enfreindre les Conditions d&apos;utilisation
- </combo_item>
- <combo_item name="Harassment__Verbal_abuse">
- Harcèlement &gt; Abus verbal
- </combo_item>
- <combo_item name="Indecency__Broadly_offensive_content_or_conduct">
- Indécence &gt; Contenu ou comportement offensifs
- </combo_item>
- <combo_item name="Indecency__Inappropriate_avatar_name">
- Indécence &gt; Nom d&apos;avatar inapproprié
- </combo_item>
- <combo_item name="Indecency__Mature_content_in_PG_region">
- Indécence &gt; Contenu ou conduite inappropriés dans une région PG
- </combo_item>
- <combo_item name="Indecency__Inappropriate_content_in_Mature_region">
- Indécence &gt; Contenu ou conduite inappropriés dans une région Mature
- </combo_item>
- <combo_item name="Intellectual_property_infringement_Content_Removal">
- Violation de droits de propriété intellectuelle &gt; Suppression de contenu
- </combo_item>
- <combo_item name="Intellectual_property_infringement_CopyBot_or_Permissions_Exploit">
- Violation de droits de propriété intellectuelle &gt; CopyBot ou exploitation abusive des droits
- </combo_item>
- <combo_item name="Intolerance">
- Intolérance
- </combo_item>
- <combo_item name="Land__Abuse_of_sandbox_resources">
- Terrain &gt; Utilisation abusive des ressources du bac à sable
- </combo_item>
- <combo_item name="Land__Encroachment__Objects_textures">
- Terrain &gt; Empiètement &gt; Objets/textures
- </combo_item>
- <combo_item name="Land__Encroachment__Particles">
- Terrain &gt; Empiètement &gt; Particules
- </combo_item>
- <combo_item name="Land__Encroachment__Trees_plants">
- Terrain &gt; Empiètement &gt; Arbres/plantes
- </combo_item>
- <combo_item name="Wagering_gambling">
- Paris/jeux d&apos;argent
- </combo_item>
- <combo_item name="Other">
- Autre
- </combo_item>
+ <combo_box.item label="Sélectionnez une catégorie" name="Select_category"/>
+ <combo_box.item label="Âge &gt; « Age play »" name="Age__Age_play"/>
+ <combo_box.item label="Âge &gt; Résident adulte sur Second Life pour adolescents" name="Age__Adult_resident_on_Teen_Second_Life"/>
+ <combo_box.item label="Âge &gt; Resident mineur en dehors de Teen Second Life" name="Age__Underage_resident_outside_of_Teen_Second_Life"/>
+ <combo_box.item label="Assaut &gt; Bac à sable utilisé pour des combats/zone non sécurisée" name="Assault__Combat_sandbox___unsafe_area"/>
+ <combo_box.item label="Assaut &gt; Zone sécurisée" name="Assault__Safe_area"/>
+ <combo_box.item label="Assaut &gt; Bac à sable pour tests d&apos;armes à feu" name="Assault__Weapons_testing_sandbox"/>
+ <combo_box.item label="Commerce &gt; Incapacité à fournir un produit ou service" name="Commerce__Failure_to_deliver_product_or_service"/>
+ <combo_box.item label="Divulgation &gt; Informations sur la vie réelle" name="Disclosure__Real_world_information"/>
+ <combo_box.item label="Divulgation &gt; Écoute d&apos;un chat à distance" name="Disclosure__Remotely_monitoring chat"/>
+ <combo_box.item label="Divulgation &gt; Informations sur Second Life/chat/IM" name="Disclosure__Second_Life_information_chat_IMs"/>
+ <combo_box.item label="Trouble de la paix &gt; Utilisation inadéquate des ressources de la région" name="Disturbing_the_peace__Unfair_use_of_region_resources"/>
+ <combo_box.item label="Trouble de la paix &gt; Nombre d&apos;objets scriptés excessif" name="Disturbing_the_peace__Excessive_scripted_objects"/>
+ <combo_box.item label="Trouble de la paix &gt; Abandon d&apos;objets" name="Disturbing_the_peace__Object_littering"/>
+ <combo_box.item label="Trouble de la paix &gt; Spam à répétition" name="Disturbing_the_peace__Repetitive_spam"/>
+ <combo_box.item label="Trouble de la paix &gt; Spam à caractère commercial" name="Disturbing_the_peace__Unwanted_advert_spam"/>
+ <combo_box.item label="Fraude &gt; L$" name="Fraud__L$"/>
+ <combo_box.item label="Fraude &gt; Terrain" name="Fraud__Land"/>
+ <combo_box.item label="Fraude &gt; Vente pyramidale ou lettre-chaîne" name="Fraud__Pyramid_scheme_or_chain_letter"/>
+ <combo_box.item label="Fraude &gt; US$" name="Fraud__US$"/>
+ <combo_box.item label="Harcèlement &gt; Spam visuel" name="Harassment__Advert_farms___visual_spam"/>
+ <combo_box.item label="Harcèlement &gt; Diffamation envers des individus ou des groupes" name="Harassment__Defaming_individuals_or_groups"/>
+ <combo_box.item label="Harcèlement &gt; Immobilisation" name="Harassment__Impeding_movement"/>
+ <combo_box.item label="Harcèlement &gt; Harcèlement sexuel" name="Harassment__Sexual_harassment"/>
+ <combo_box.item label="Harcèlement &gt; Incitation à enfreindre les Conditions d&apos;utilisation" name="Harassment__Solicting_inciting_others_to_violate_ToS"/>
+ <combo_box.item label="Harcèlement &gt; Abus verbal" name="Harassment__Verbal_abuse"/>
+ <combo_box.item label="Indécence &gt; Contenu ou comportement offensifs" name="Indecency__Broadly_offensive_content_or_conduct"/>
+ <combo_box.item label="Indécence &gt; Nom d&apos;avatar inapproprié" name="Indecency__Inappropriate_avatar_name"/>
+ <combo_box.item label="Indécence &gt; Contenu ou conduite inappropriés dans une région PG" name="Indecency__Mature_content_in_PG_region"/>
+ <combo_box.item label="Indécence &gt; Contenu ou conduite inappropriés dans une région Mature" name="Indecency__Inappropriate_content_in_Mature_region"/>
+ <combo_box.item label="Violation de droits de propriété intellectuelle &gt; Suppression de contenu" name="Intellectual_property_infringement_Content_Removal"/>
+ <combo_box.item label="Violation de droits de propriété intellectuelle &gt; CopyBot ou exploitation abusive des droits" name="Intellectual_property_infringement_CopyBot_or_Permissions_Exploit"/>
+ <combo_box.item label="Intolérance" name="Intolerance"/>
+ <combo_box.item label="Terrain &gt; Utilisation abusive des ressources du bac à sable" name="Land__Abuse_of_sandbox_resources"/>
+ <combo_box.item label="Terrain &gt; Empiètement &gt; Objets/textures" name="Land__Encroachment__Objects_textures"/>
+ <combo_box.item label="Terrain &gt; Empiètement &gt; Particules" name="Land__Encroachment__Particles"/>
+ <combo_box.item label="Terrain &gt; Empiètement &gt; Arbres/plantes" name="Land__Encroachment__Trees_plants"/>
+ <combo_box.item label="Paris/jeux d&apos;argent" name="Wagering_gambling"/>
+ <combo_box.item label="Autre" name="Other"/>
</combo_box>
<text name="abuser_name_title">
Nom du contrevenant :
</text>
- <button label="Choisir le résident" label_selected="" name="select_abuser" tool_tip="Sélectionnez le nom du résident dans une liste"/>
- <check_box label="Ne connaît pas le nom du contrevenant" name="omit_abuser_name" tool_tip="Cochez cette case si vous ne connaissez pas le nom du contrevenant"/>
+ <button label="Choisir" label_selected="" name="select_abuser" tool_tip="Sélectionnez le nom du résident dans une liste"/>
<text name="abuser_name_title2">
Indiquez où l&apos;infraction a eu lieu :
</text>
@@ -170,14 +93,11 @@
Détails :
</text>
<text name="bug_aviso">
- Indiquez la date, le lieu, la nature de l&apos;infraction, ainsi que
-tout chat ou IM relatif à l&apos;infraction, en étant aussi précis
-que possible. Pensez à indiquer un objet si possible.
+ Soyez aussi spécifique que possible
</text>
<text bottom_delta="-16" name="incomplete_title">
- Remarque : les rapports incomplets ne feront pas l&apos;objet d&apos;une
-enquête.
+ * Les rapports incomplets ne feront pas l&apos;objet d&apos;une enquête
</text>
- <button label="Annuler" label_selected="Annuler" name="cancel_btn"/>
<button label="Signaler une infraction" label_selected="Signaler une infraction" name="send_btn"/>
+ <button label="Annuler" label_selected="Annuler" name="cancel_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_script_debug.xml b/indra/newview/skins/default/xui/fr/floater_script_debug.xml
index 3664222fd2..e257aac6c4 100644
--- a/indra/newview/skins/default/xui/fr/floater_script_debug.xml
+++ b/indra/newview/skins/default/xui/fr/floater_script_debug.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<multi_floater name="script debug floater" title="Erreurs/alertes de scripts">
<tab_container name="Preview Tabs">
- <floater label="Script" name="all_scripts" title="[All scripts]" />
+ <floater label="Script" name="all_scripts" title="[ALL SCRIPTS]" />
</tab_container>
</multi_floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_script_debug_panel.xml b/indra/newview/skins/default/xui/fr/floater_script_debug_panel.xml
new file mode 100644
index 0000000000..e70a30fa24
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_script_debug_panel.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="script" short_title="[ALL SCRIPTS]" title="[ALL SCRIPTS]"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_script_preview.xml b/indra/newview/skins/default/xui/fr/floater_script_preview.xml
index 4b77d6b4cd..7b8c5399b9 100644
--- a/indra/newview/skins/default/xui/fr/floater_script_preview.xml
+++ b/indra/newview/skins/default/xui/fr/floater_script_preview.xml
@@ -1,6 +1,9 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="preview lsl text" title="Script : Script de rotation">
- <text type="string" length="1" name="desc txt">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="preview lsl text" title="SCRIPT : SCRIPT DE ROTATION">
+ <floater.string name="Title">
+ Script : [NAME]
+ </floater.string>
+ <text name="desc txt">
Description :
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_script_queue.xml b/indra/newview/skins/default/xui/fr/floater_script_queue.xml
index 55487f75db..b9a8165457 100644
--- a/indra/newview/skins/default/xui/fr/floater_script_queue.xml
+++ b/indra/newview/skins/default/xui/fr/floater_script_queue.xml
@@ -1,4 +1,19 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="queue" title="Réinitialiser progression">
- <button label="Fermer" label_selected="Fermer" name="close" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="queue" title="RÉINITIALISER LES PROGRÈS">
+ <floater.string name="Starting">
+ Lancement de [START] sur [COUNT] objets.
+ </floater.string>
+ <floater.string name="Done">
+ Fini.
+ </floater.string>
+ <floater.string name="Resetting">
+ Réinitialisation
+ </floater.string>
+ <floater.string name="Running">
+ Exécution en cours
+ </floater.string>
+ <floater.string name="NotRunning">
+ Arrêt
+ </floater.string>
+ <button label="Fermer" label_selected="Fermer" name="close"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_script_search.xml b/indra/newview/skins/default/xui/fr/floater_script_search.xml
index 1c20c9c34b..09b903f41c 100644
--- a/indra/newview/skins/default/xui/fr/floater_script_search.xml
+++ b/indra/newview/skins/default/xui/fr/floater_script_search.xml
@@ -1,15 +1,15 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script search" title="Recherche de scripts" width="320">
- <check_box label="Non sensible à la casse" name="case_text" left="75"/>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="script search" title="RECHERCHE DE SCRIPT" width="320">
+ <check_box label="Non sensible à la casse" left="75" name="case_text"/>
<button label="Rechercher" label_selected="Rechercher" name="search_btn" width="96"/>
- <button label="Remplacer" label_selected="Remplacer" name="replace_btn" left="111" width="96"/>
- <button label="Tout remplacer" label_selected="Tout remplacer" name="replace_all_btn" left="212" width="96"/>
- <text type="string" length="1" name="txt" width="65">
+ <button label="Remplacer" label_selected="Remplacer" left="111" name="replace_btn" width="96"/>
+ <button label="Tout remplacer" label_selected="Tout remplacer" left="212" name="replace_all_btn" width="96"/>
+ <text name="txt" width="65">
Rechercher
</text>
- <text type="string" length="1" name="txt2" width="65">
+ <text name="txt2" width="65">
Remplacer
</text>
- <line_editor left="75" name="search_text" width="240" />
- <line_editor left="75" name="replace_text" width="240" />
+ <line_editor left="75" name="search_text" width="240"/>
+ <line_editor left="75" name="replace_text" width="240"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_search.xml b/indra/newview/skins/default/xui/fr/floater_search.xml
new file mode 100644
index 0000000000..8f13b64dea
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_search.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_search" title="RECHERCHER">
+ <floater.string name="loading_text">
+ Chargement...
+ </floater.string>
+ <floater.string name="done_text">
+ Terminé
+ </floater.string>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_sell_land.xml b/indra/newview/skins/default/xui/fr/floater_sell_land.xml
index cf394643bc..3a06f4e189 100644
--- a/indra/newview/skins/default/xui/fr/floater_sell_land.xml
+++ b/indra/newview/skins/default/xui/fr/floater_sell_land.xml
@@ -1,72 +1,65 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="sell land" title="Vendre terrain">
- <text name="info_parcel_label">
- Parcelle :
- </text>
- <text name="info_parcel">
- PARCEL NAME
- </text>
- <text name="info_size_label">
- Taille :
- </text>
- <text name="info_size">
- [AREA] m²
- </text>
- <text name="info_action" bottom_delta="-60">
- Pour vendre cette
-parcelle :
- </text>
- <icon bottom_delta="-86" name="step_price" />
- <text name="price_label">
- Votre prix de vente :
- </text>
- <text name="price_text">
- Fixez un prix convenable pour ce terrain.
- </text>
- <text name="price_ld">
- L$
- </text>
- <text name="price_per_m">
- ([PER_METER] L$ par mètre carré)
- </text>
- <text name="sell_to_label">
- Vos acheteurs :
- </text>
- <text name="sell_to_text">
- Vendez votre terrain à n&apos;importe qui ou uniquement à un acheteur
-spécifique.
- </text>
- <combo_box name="sell_to" bottom_delta="-32">
- <combo_item name="--selectone--">
- -- Sélectionnez --
- </combo_item>
- <combo_item name="Anyone">
- N&apos;importe qui
- </combo_item>
- <combo_item name="Specificuser:">
- Acheteur spécifique :
- </combo_item>
- </combo_box>
- <button label="Sélectionner..." name="sell_to_select_agent" width="100"/>
- <text name="sell_objects_label">
- Vendez-vous des objets avec ce terrain ?
- </text>
- <text name="sell_objects_text">
- Les objets transférables se trouvant sur la parcelle changeront
-de propriétaire.
- </text>
- <radio_group name="sell_objects" right="430" bottom_delta="-54">
- <radio_item name="no">
- Non, rester le propriétaire des objets
- </radio_item>
- <radio_item name="yes">
- Oui, vendre les objets avec le terrain
- </radio_item>
- </radio_group>
- <button label="Afficher les objets" name="show_objects" right="420" width="120"/>
- <text name="nag_message_label" bottom_delta="-30">
- Rappel : toute vente est définitive.
- </text>
- <button label="Mettre le terrain en vente" name="sell_btn" width="165"/>
- <button label="Annuler" name="cancel_btn"/>
+<floater name="sell land" title="VENDRE DU TERRAIN">
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <text name="info_parcel_label">
+ Parcelle :
+ </text>
+ <text name="info_parcel">
+ NOM DE LA PARCELLE
+ </text>
+ <text name="info_size_label">
+ Taille :
+ </text>
+ <text name="info_size">
+ [AREA] m²
+ </text>
+ <text bottom_delta="-60" name="info_action">
+ Pour vendre cette parcelle :
+ </text>
+ <text name="price_label">
+ 1. Votre prix de vente :
+ </text>
+ <text name="price_text">
+ Fixez un prix convenable.
+ </text>
+ <text name="price_ld">
+ L$
+ </text>
+ <line_editor name="price">
+ 0
+ </line_editor>
+ <text name="price_per_m">
+ ([PER_METER] L$/m²)
+ </text>
+ <text name="sell_to_label">
+ 2. Vos acheteurs :
+ </text>
+ <text name="sell_to_text">
+ Vendez votre terrain à n&apos;importe qui ou uniquement à un acheteur spécifique.
+ </text>
+ <combo_box bottom_delta="-32" name="sell_to">
+ <combo_box.item label="-- Sélectionnez --" name="--selectone--"/>
+ <combo_box.item label="Tout le monde" name="Anyone"/>
+ <combo_box.item label="Personne spécifique :" name="Specificuser:"/>
+ </combo_box>
+ <button label="Sélectionner" name="sell_to_select_agent" width="100"/>
+ <text name="sell_objects_label">
+ 3. Vendez-vous les objets avec ce terrain ?
+ </text>
+ <text name="sell_objects_text">
+ Les objets transférables se trouvant sur la parcelle changeront de propriétaire.
+ </text>
+ <radio_group bottom_delta="-54" name="sell_objects" right="430">
+ <radio_item label="Non, rester le propriétaire des objets" name="no"/>
+ <radio_item label="Oui, vendre les objets avec le terrain" name="yes"/>
+ </radio_group>
+ <button label="Afficher les objets" name="show_objects" right="420" width="120"/>
+ <text bottom_delta="-30" name="nag_message_label">
+ Rappel : Toutes les ventes sont définitives.
+ </text>
+ <button label="Indiquer le terrain à vendre" name="sell_btn" width="165"/>
+ <button label="Annuler" name="cancel_btn"/>
+ </panel>
+ </scroll_container>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_settings_debug.xml b/indra/newview/skins/default/xui/fr/floater_settings_debug.xml
index 30183340fc..aae4729347 100644
--- a/indra/newview/skins/default/xui/fr/floater_settings_debug.xml
+++ b/indra/newview/skins/default/xui/fr/floater_settings_debug.xml
@@ -1,17 +1,13 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="settings_debug" title="Paramétrages du mode Debug">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="settings_debug" title="PARAMÈTRES DE DÉBOGAGE">
<combo_box name="boolean_combo">
- <combo_item name="TRUE">
- TRUE
- </combo_item>
- <combo_item name="FALSE">
- FALSE
- </combo_item>
+ <combo_box.item label="VRAI" name="TRUE"/>
+ <combo_box.item label="FAUX" name="FALSE"/>
</combo_box>
- <color_swatch label="Couleur" name="color_swatch" width="43" />
- <spinner label="x" name="val_spinner_1" />
- <spinner label="x" name="val_spinner_2" />
- <spinner label="x" name="val_spinner_3" />
- <spinner label="x" name="val_spinner_4" />
- <button label="Paramètres par défaut" name="default_btn" />
+ <color_swatch label="Couleur" name="val_color_swatch"/>
+ <spinner label="x" name="val_spinner_1"/>
+ <spinner label="x" name="val_spinner_2"/>
+ <spinner label="x" name="val_spinner_3"/>
+ <spinner label="x" name="val_spinner_4"/>
+ <button label="Paramètres par défaut" name="default_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_snapshot.xml b/indra/newview/skins/default/xui/fr/floater_snapshot.xml
index 4351a1a789..6c939b9c68 100644
--- a/indra/newview/skins/default/xui/fr/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/fr/floater_snapshot.xml
@@ -1,18 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Snapshot" title="Prévisualiser la photo" width="247">
+<floater name="Snapshot" title="APERÇU DE LA PHOTO" width="247">
<text name="type_label">
Destination de la photo
</text>
<radio_group label="Type de photo" name="snapshot_type_radio" width="228">
- <radio_item name="postcard">
- Envoyer par e-mail
- </radio_item>
- <radio_item name="texture">
- Enregistrer dans votre inventaire ([AMOUNT] L$)
- </radio_item>
- <radio_item name="local">
- Enregistrer sur votre disque dur
- </radio_item>
+ <radio_item label="Envoyer par e-mail" name="postcard"/>
+ <radio_item label="Enregistrer dans votre inventaire ([AMOUNT] L$)" name="texture"/>
+ <radio_item label="Enregistrer sur votre disque dur" name="local"/>
</radio_group>
<button label="Plus &gt;&gt;" name="more_btn" tool_tip="Options avancées"/>
<button label="&lt;&lt; Moins" name="less_btn" tool_tip="Options avancées"/>
@@ -23,75 +17,33 @@
Format
</text>
<combo_box label="Résolution" name="postcard_size_combo">
- <combo_item name="640x480">
- 640 x 480
- </combo_item>
- <combo_item name="800x600">
- 800 x 600
- </combo_item>
- <combo_item name="1024x768">
- 1024 x 768
- </combo_item>
- <combo_item name="CurrentWindow">
- Fenêtre actuelle
- </combo_item>
- <combo_item name="Custom">
- Personnaliser
- </combo_item>
+ <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="Fenêtre actuelle" name="CurrentWindow"/>
+ <combo_box.item label="Personnaliser" name="Custom"/>
</combo_box>
<combo_box label="Résolution" name="texture_size_combo">
- <combo_item name="CurrentWindow">
- Fenêtre actuelle
- </combo_item>
- <combo_item name="Small(128x128)">
- Petite (128 x 128)
- </combo_item>
- <combo_item name="Medium(256x256)">
- Moyenne (256 x 256)
- </combo_item>
- <combo_item name="Large(512x512)">
- Grande (512 x 512)
- </combo_item>
- <combo_item name="Custom">
- Personnaliser
- </combo_item>
+ <combo_box.item label="Fenêtre actuelle" name="CurrentWindow"/>
+ <combo_box.item label="Petite (128 x 128)" name="Small(128x128)"/>
+ <combo_box.item label="Moyenne (256 x 256)" name="Medium(256x256)"/>
+ <combo_box.item label="Grande (512 x 512)" name="Large(512x512)"/>
+ <combo_box.item label="Personnaliser" name="Custom"/>
</combo_box>
<combo_box label="Résolution" name="local_size_combo">
- <combo_item name="CurrentWindow">
- Fenêtre actuelle
- </combo_item>
- <combo_item name="320x240">
- 320 x 240
- </combo_item>
- <combo_item name="640x480">
- 640 x 480
- </combo_item>
- <combo_item name="800x600">
- 800 x 600
- </combo_item>
- <combo_item name="1024x768">
- 1024 x 768
- </combo_item>
- <combo_item name="1280x1024">
- 1280 x 1024
- </combo_item>
- <combo_item name="1600x1200">
- 1600 x 1200
- </combo_item>
- <combo_item name="Custom">
- Personnaliser
- </combo_item>
+ <combo_box.item label="Fenêtre actuelle" name="CurrentWindow"/>
+ <combo_box.item label="320 x 240" name="320x240"/>
+ <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="1280 x 1024" name="1280x1024"/>
+ <combo_box.item label="1600 x 1200" name="1600x1200"/>
+ <combo_box.item label="Personnaliser" name="Custom"/>
</combo_box>
<combo_box label="Format" name="local_format_combo">
- <combo_item name="PNG">
- PNG
- </combo_item>
- <combo_item name="JPEG">
- JPEG
- </combo_item>
- <combo_item name="BMP">
- BMP
- </combo_item>
+ <combo_box.item label="PNG" name="PNG"/>
+ <combo_box.item label="JPEG" name="JPEG"/>
+ <combo_box.item label="BMP" name="BMP"/>
</combo_box>
<spinner label="Largeur" label_width="41" name="snapshot_width" width="101"/>
<spinner label="Hauteur" label_width="41" left="121" name="snapshot_height" width="101"/>
@@ -100,15 +52,9 @@
Capturer :
</text>
<combo_box label="Couches de l&apos;image" name="layer_types">
- <combo_item name="Colors">
- Couleurs
- </combo_item>
- <combo_item name="Depth">
- Profondeur
- </combo_item>
- <combo_item name="ObjectMattes">
- Matte des objets
- </combo_item>
+ <combo_box.item label="Couleurs" name="Colors"/>
+ <combo_box.item label="Profondeur" name="Depth"/>
+ <combo_box.item label="Matte des objets" name="ObjectMattes"/>
</combo_box>
<text name="file_size_label">
Taille du fichier : [SIZE] Ko
@@ -123,14 +69,10 @@
<button label="Enregistrer ([AMOUNT] L$)" name="upload_btn" width="118"/>
<button label="Envoyer" name="send_btn" width="118"/>
<flyout_button label="Enregistrer" name="save_btn" tool_tip="Enregistrer l&apos;image dans un fichier" width="118">
- <flyout_button_item name="save_item">
- Enregistrer
- </flyout_button_item>
- <flyout_button_item name="saveas_item">
- Enregistrer sous...
- </flyout_button_item>
+ <flyout_button.item label="Enregistrer" name="save_item"/>
+ <flyout_button.item label="Enregistrer sous..." name="saveas_item"/>
</flyout_button>
- <button label="Annuler" name="discard_btn" left="133" width="72" />
+ <button label="Annuler" left="133" name="discard_btn" width="72"/>
<string name="unknown">
inconnu
</string>
diff --git a/indra/newview/skins/default/xui/fr/floater_sound_preview.xml b/indra/newview/skins/default/xui/fr/floater_sound_preview.xml
index 199a6b846f..6f0fb3421f 100644
--- a/indra/newview/skins/default/xui/fr/floater_sound_preview.xml
+++ b/indra/newview/skins/default/xui/fr/floater_sound_preview.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Sound Preview" title="sound.wav">
+<floater name="Sound Preview" title="SOUND.WAV">
<text name="name_label">
Nom :
</text>
@@ -12,17 +12,9 @@
Débit (kbps) :
</text>
<radio_group name="bitrate">
- <radio_item name="32">
- 32
- </radio_item>
- <radio_item name="64">
- 64
- </radio_item>
- <radio_item name="96">
- 96
- </radio_item>
- <radio_item name="128">
- 128
- </radio_item>
+ <radio_item label="32" name="32"/>
+ <radio_item label="64" name="64"/>
+ <radio_item label="96" name="96"/>
+ <radio_item label="128" name="128"/>
</radio_group>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_statistics.xml b/indra/newview/skins/default/xui/fr/floater_statistics.xml
index 0768c3ace4..a2e3c199ab 100644
--- a/indra/newview/skins/default/xui/fr/floater_statistics.xml
+++ b/indra/newview/skins/default/xui/fr/floater_statistics.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="stats floater" title="Statistiques"/>
+<floater name="stats floater" title="STATISTIQUES"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_stats.xml b/indra/newview/skins/default/xui/fr/floater_stats.xml
new file mode 100644
index 0000000000..3c19bb2608
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_stats.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Statistics" title="STATISTIQUES">
+ <scroll_container name="statistics_scroll">
+ <container_view name="statistics_view">
+ <stat_view label="De base" name="basic">
+ <stat_bar label="FPS" name="fps"/>
+ <stat_bar label="Bande passante" name="bandwidth"/>
+ <stat_bar label="Perte de paquets" name="packet_loss"/>
+ <stat_bar label="Ping sim" name="ping"/>
+ </stat_view>
+ <stat_view label="Avancées" name="advanced">
+ <stat_view label="Rendu" name="render">
+ <stat_bar label="KTris Drawn" name="ktrisframe"/>
+ <stat_bar label="KTris Drawn" name="ktrissec"/>
+ <stat_bar label="Objets totaux" name="objs"/>
+ <stat_bar label="Nouveaux objets" name="newobjs"/>
+ </stat_view>
+ <stat_view label="Texture" name="texture">
+ <stat_bar label="Nombre" name="numimagesstat"/>
+ <stat_bar label="Nombre brut" name="numrawimagesstat"/>
+ <stat_bar label="Mém GL" name="gltexmemstat"/>
+ <stat_bar label="Mém formatée" name="formattedmemstat"/>
+ <stat_bar label="Mém brute" name="rawmemstat"/>
+ <stat_bar label="Mém liée" name="glboundmemstat"/>
+ </stat_view>
+ <stat_view label="Réseau" name="network">
+ <stat_bar label="Paquets en entrée" name="packetsinstat"/>
+ <stat_bar label="Paquets en sortie" name="packetsoutstat"/>
+ <stat_bar label="Objets" name="objectkbitstat"/>
+ <stat_bar label="Texture" name="texturekbitstat"/>
+ <stat_bar label="Actif" name="assetkbitstat"/>
+ <stat_bar label="Couches" name="layerskbitstat"/>
+ <stat_bar label="Arrivés" name="actualinkbitstat"/>
+ <stat_bar label="Sortis" name="actualoutkbitstat"/>
+ <stat_bar label="Ops VFS en attente" name="vfspendingoperations"/>
+ </stat_view>
+ </stat_view>
+ <stat_view label="Simulateur" name="sim">
+ <stat_bar label="Dilatation temporelle" name="simtimedilation"/>
+ <stat_bar label="FPS sim" name="simfps"/>
+ <stat_bar label="Propriétés physiques FPS" name="simphysicsfps"/>
+ <stat_view label="Détails des propriétés physiques" name="physicsdetail">
+ <stat_bar label="Objets fixés" name="physicspinnedtasks"/>
+ <stat_bar label="Objets LOD faibles" name="physicslodtasks"/>
+ <stat_bar label="Mémoire allouée" name="physicsmemoryallocated"/>
+ </stat_view>
+ <stat_bar label="Mises à jour avatar/s" name="simagentups"/>
+ <stat_bar label="Avatars principaux" name="simmainagents"/>
+ <stat_bar label="Avatars enfants" name="simchildagents"/>
+ <stat_bar label="Objets" name="simobjects"/>
+ <stat_bar label="Objets actifs" name="simactiveobjects"/>
+ <stat_bar label="Scripts actifs" name="simactivescripts"/>
+ <stat_bar label="Événements de scripts" name="simscripteps"/>
+ <stat_bar label="Paquets en entrée" name="siminpps"/>
+ <stat_bar label="Paquets en sortie" name="simoutpps"/>
+ <stat_bar label="En attente des téléchargements" name="simpendingdownloads"/>
+ <stat_bar label="En attente des chargements" name="simpendinguploads"/>
+ <stat_bar label="Total Unacked Bytes" name="simtotalunackedbytes"/>
+ <stat_view label="Temps (ms)" name="simperf">
+ <stat_bar label="Durée du cadre totale" name="simframemsec"/>
+ <stat_bar label="Durée nette" name="simnetmsec"/>
+ <stat_bar label="Durée physique" name="simsimphysicsmsec"/>
+ <stat_bar label="Durée de la simulation" name="simsimothermsec"/>
+ <stat_bar label="Durée de l&apos;avatar" name="simagentmsec"/>
+ <stat_bar label="Durée des images" name="simimagesmsec"/>
+ <stat_bar label="Durée du script" name="simscriptmsec"/>
+ </stat_view>
+ </stat_view>
+ </container_view>
+ </scroll_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_sys_well.xml b/indra/newview/skins/default/xui/fr/floater_sys_well.xml
new file mode 100644
index 0000000000..279320b04e
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_sys_well.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="notification_chiclet" title="NOTIFICATIONS"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_telehub.xml b/indra/newview/skins/default/xui/fr/floater_telehub.xml
index e6201785bd..1c65a38828 100644
--- a/indra/newview/skins/default/xui/fr/floater_telehub.xml
+++ b/indra/newview/skins/default/xui/fr/floater_telehub.xml
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="telehub" title="Téléhub" min_height="310" height="310" >
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater height="310" min_height="310" name="telehub" title="TÉLÉHUB">
<text name="status_text_connected">
Téléhub connecté à l&apos;objet [OBJECT]
</text>
@@ -9,17 +9,17 @@
<text name="help_text_connected">
Pour supprimer, cliquez sur Déconnecter.
</text>
- <text name="help_text_not_connected" height="38" bottom_delta="-18">
+ <text bottom_delta="-18" height="38" name="help_text_not_connected">
Sélectionner l&apos;objet et cliquez sur Connecter
le téléhub.
</text>
<button label="Connecter le téléhub" name="connect_btn" width="122"/>
- <button label="Déconnecter" name="disconnect_btn" left="142" width="98"/>
+ <button label="Déconnecter" left="142" name="disconnect_btn" width="98"/>
<text name="spawn_points_text" width="230">
Points d&apos;apparition (positions, pas objets) :
</text>
- <button label="Ajouter point" name="add_spawn_point_btn" />
- <button label="Supprimer point" name="remove_spawn_point_btn" />
+ <button label="Ajouter point" name="add_spawn_point_btn"/>
+ <button label="Supprimer point" name="remove_spawn_point_btn"/>
<text name="spawn_point_help">
Sélectionnez l&apos;objet et cliquez sur Ajouter pour
indiquer la position. Vous pourrez ensuite
diff --git a/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml
index 2a234a37c5..197651c8fb 100644
--- a/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml
@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="texture picker" title="Texture">
+<floater name="texture picker" title="CHOISIR : TEXTURE">
<string name="choose_picture">
Cliquez pour sélectionner une image
</string>
- <text length="1" name="Multiple" type="string">
- Multiple
+ <text name="Multiple">
+ Textures multiples
</text>
- <text length="1" name="unknown" type="string">
- Dimensions : [DIMENSIONS]
+ <text name="unknown">
+ Taille : [DIMENSIONS]
</text>
- <button label="Défaut" label_selected="Défaut" name="Default" width="60" />
- <button label="Aucune" label_selected="Aucune" name="None" width="60" left="68" />
- <button label="Vierge" label_selected="Vierge" name="Blank" width="60" />
+ <button label="Défaut" label_selected="Défaut" name="Default" width="60"/>
+ <button label="Aucune" label_selected="Aucune" left="68" name="None" width="60"/>
+ <button label="Vierge" label_selected="Vierge" name="Blank" width="60"/>
<check_box label="Afficher les dossiers" name="show_folders_check"/>
- <search_editor label="Saisissez votre recherche ici" name="inventory search editor"/>
- <check_box label="Appliquer immédiatement" name="apply_immediate_check" />
- <button label="" label_selected="" name="Pipette" bottom="-240" />
+ <search_editor label="Filtrer les textures" name="inventory search editor"/>
+ <check_box label="Appliquer maintenant" name="apply_immediate_check"/>
+ <button bottom="-240" label="" label_selected="" name="Pipette"/>
<button label="Annuler" label_selected="Annuler" name="Cancel"/>
- <button label="Sélectionner" label_selected="Sélectionner" name="Select"/>
+ <button label="Ok" label_selected="Ok" name="Select"/>
<string name="pick title">
Choisir :
</string>
diff --git a/indra/newview/skins/default/xui/fr/floater_tools.xml b/indra/newview/skins/default/xui/fr/floater_tools.xml
index f34100f56f..e5a5998cfb 100644
--- a/indra/newview/skins/default/xui/fr/floater_tools.xml
+++ b/indra/newview/skins/default/xui/fr/floater_tools.xml
@@ -1,42 +1,81 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="toolbox floater" title="">
+<floater name="toolbox floater" short_title="OUTILS DE CONSTRUCTION" title="">
+ <floater.string name="status_rotate">
+ Pour faire tourner l&apos;objet, faîtes glisser les bandes de couleur.
+ </floater.string>
+ <floater.string name="status_scale">
+ Pour étirer le côté sélectionné, cliquez et faites glisser.
+ </floater.string>
+ <floater.string name="status_move">
+ Glissez pour déplacer, Maj-glissez pour copier.
+ </floater.string>
+ <floater.string name="status_modifyland">
+ Cliquez et maintenez pour modifier le terrain.
+ </floater.string>
+ <floater.string name="status_camera">
+ Cliquez et faites glisser pour bouger la caméra
+ </floater.string>
+ <floater.string name="status_grab">
+ Faites glisser pour déplacer, appuyez sur Ctrl pour soulever, Ctrl-Maj pour pivoter
+ </floater.string>
+ <floater.string name="status_place">
+ Cliquez dans le monde pour construire.
+ </floater.string>
+ <floater.string name="status_selectland">
+ Cliquez et faites glisser pour sélectionner le terrain.
+ </floater.string>
+ <floater.string name="grid_screen_text">
+ Écran
+ </floater.string>
+ <floater.string name="grid_local_text">
+ Local
+ </floater.string>
+ <floater.string name="grid_world_text">
+ Monde
+ </floater.string>
+ <floater.string name="grid_reference_text">
+ Référence
+ </floater.string>
+ <floater.string name="grid_attachment_text">
+ Pièce-jointe
+ </floater.string>
<button label="" label_selected="" name="button focus" tool_tip="Mise au point"/>
<button label="" label_selected="" name="button move" tool_tip="Déplacer"/>
<button label="" label_selected="" name="button edit" tool_tip="Modifier"/>
<button label="" label_selected="" name="button create" tool_tip="Créer"/>
<button label="" label_selected="" name="button land" tool_tip="Terrain"/>
- <check_box label="Zoom" name="radio zoom"/>
- <check_box label="Orbite (Ctrl)" name="radio orbit"/>
- <check_box label="Panoramique (Ctrl-Maj)" name="radio pan"/>
- <check_box label="Déplacer" name="radio move"/>
- <check_box label="Orbite (Ctrl)" name="radio lift"/>
- <check_box label="Faire tourner (Ctrl-Maj)" name="radio spin"/>
- <check_box label="Positionner" name="radio position"/>
- <check_box label="Pivoter (Ctrl)" name="radio rotate"/>
- <check_box label="Étirer (Ctrl-Maj)" name="radio stretch"/>
- <check_box label="Sélectionner une face" name="radio select face"/>
- <check_box label="Modifier les parties liées" name="checkbox edit linked parts"/>
- <text name="text ruler mode">
- Axe :
- </text>
- <combo_box name="combobox grid mode">
- <combo_item name="World">
- Monde
- </combo_item>
- <combo_item name="Local">
- Local
- </combo_item>
- <combo_item name="Reference">
- Référence
- </combo_item>
- </combo_box>
- <check_box label="Étirer les deux côtés" name="checkbox uniform"/>
- <check_box label="Étirer les textures" name="checkbox stretch textures"/>
- <check_box label="Utiliser la grille" name="checkbox snap to grid"/>
- <button label="Options..." label_selected="Options..." name="Options..."/>
<text name="text status">
Glissez pour déplacer, Maj-glissez pour copier.
</text>
+ <radio_group name="focus_radio_group">
+ <radio_item label="Zoom" name="radio zoom"/>
+ <radio_item label="Orbite (Ctrl)" name="radio orbit"/>
+ <radio_item label="Faire un panoramique (Ctrl+Maj)" name="radio pan"/>
+ </radio_group>
+ <radio_group name="move_radio_group">
+ <radio_item label="Déplacer" name="radio move"/>
+ <radio_item label="Orbite (Ctrl)" name="radio lift"/>
+ <radio_item label="Faire tourner (Ctrl+Maj)" name="radio spin"/>
+ </radio_group>
+ <radio_group name="edit_radio_group">
+ <radio_item label="Bouger" name="radio position"/>
+ <radio_item label="Pivoter (Ctrl)" name="radio rotate"/>
+ <radio_item label="Étirer (Ctrl+Maj)" name="radio stretch"/>
+ <radio_item label="Sélectionner une face" name="radio select face"/>
+ </radio_group>
+ <check_box label="Modification liée" name="checkbox edit linked parts"/>
+ <text name="RenderingCost" tool_tip="Affiche le coût du rendu calculé pour cet objet">
+ þ : [COUNT]
+ </text>
+ <check_box label="Étirer les deux côtés" name="checkbox uniform"/>
+ <check_box initial_value="true" label="Étirer les textures" name="checkbox stretch textures"/>
+ <check_box initial_value="true" label="Fixer sur la grille" name="checkbox snap to grid"/>
+ <combo_box name="combobox grid mode" tool_tip="Choisissez le type d&apos;axe de grille pour le positionnement de l&apos;objet">
+ <combo_box.item label="Grille du monde" name="World"/>
+ <combo_box.item label="Grille locale" name="Local"/>
+ <combo_box.item label="Grille de référence" name="Reference"/>
+ </combo_box>
+ <button label="Options..." label_selected="Options..." name="Options..." tool_tip="Afficher d&apos;autres options de grille"/>
<button label="" label_selected="" name="ToolCube" tool_tip="Cube"/>
<button label="" label_selected="" name="ToolPrism" tool_tip="Prisme droit"/>
<button label="" label_selected="" name="ToolPyramid" tool_tip="Pyramide"/>
@@ -54,16 +93,17 @@
<button label="" label_selected="" name="ToolGrass" tool_tip="Herbe"/>
<check_box label="Maintenir l&apos;outil sélectionné" name="checkbox sticky"/>
<check_box label="Copier la sélection" name="checkbox copy selection"/>
- <check_box label="Centrer" name="checkbox copy centers"/>
+ <check_box initial_value="true" label="Centrer" name="checkbox copy centers"/>
<check_box label="Pivoter" name="checkbox copy rotates"/>
- <check_box label="Sélectionner le terrain" name="radio select land"/>
- <check_box label="Aplatir" name="radio flatten"/>
- <check_box label="Élever" name="radio raise"/>
- <check_box label="Abaisser" name="radio lower"/>
- <check_box label="Lisser" name="radio smooth"/>
- <check_box label="Bosseler" name="radio noise"/>
- <check_box label="Annuler modification" name="radio revert"/>
- <button label="Appliquer" label_selected="Appliquer" name="button apply to selection" tool_tip="Modifier le terrain sélectionné" left="176"/>
+ <radio_group name="land_radio_group">
+ <radio_item label="Sélectionner le terrain" name="radio select land"/>
+ <radio_item label="Aplatir" name="radio flatten"/>
+ <radio_item label="Élever" name="radio raise"/>
+ <radio_item label="Abaisser" name="radio lower"/>
+ <radio_item label="Lisser" name="radio smooth"/>
+ <radio_item label="Bosseler" name="radio noise"/>
+ <radio_item label="Annuler modification" name="radio revert"/>
+ </radio_group>
<text name="Bulldozer:">
Bulldozer :
</text>
@@ -73,14 +113,51 @@
<text name="Strength:">
Force
</text>
+ <button label="Appliquer" label_selected="Appliquer" left="176" name="button apply to selection" tool_tip="Modifier le terrain sélectionné"/>
<text name="obj_count">
- Objets sélectionnés : [COUNT]
+ Objets : [COUNT]
</text>
<text name="prim_count">
- Prims : [COUNT]
+ Prims : [COUNT]
</text>
<tab_container name="Object Info Tabs">
<panel label="Général" name="General">
+ <panel.string name="text deed continued">
+ Céder
+ </panel.string>
+ <panel.string name="text deed">
+ Transférer
+ </panel.string>
+ <panel.string name="text modify info 1">
+ Vous pouvez modifier cet objet
+ </panel.string>
+ <panel.string name="text modify info 2">
+ Vous pouvez modifier ces objets
+ </panel.string>
+ <panel.string name="text modify info 3">
+ Vous ne pouvez pas modifier cet objet
+ </panel.string>
+ <panel.string name="text modify info 4">
+ Vous ne pouvez pas modifier ces objets
+ </panel.string>
+ <panel.string name="text modify warning">
+ Sélectionnez l&apos;objet en entier
+ </panel.string>
+ <panel.string name="Cost Default">
+ Prix : L$
+ </panel.string>
+ <panel.string name="Cost Total">
+ Prix total : L$
+ </panel.string>
+ <panel.string name="Cost Per Unit">
+ Prix par : L$
+ </panel.string>
+ <panel.string name="Cost Mixed">
+ Prix mixte
+ </panel.string>
+ <panel.string name="Sale Mixed">
+ Vente mixte
+ </panel.string>
<text name="Name:">
Nom :
</text>
@@ -91,146 +168,79 @@
Créateur :
</text>
<text name="Creator Name">
- Thrax Linden
+ Esbee Linden
</text>
- <button label="Profil..." label_selected="Profil..." name="button creator profile"/>
<text name="Owner:">
Propriétaire :
</text>
<text name="Owner Name">
- Thrax Linden
+ Erica Linden
</text>
- <button label="Profil..." label_selected="Profil..." name="button owner profile"/>
<text name="Group:">
Groupe :
</text>
- <text name="Group Name Proxy">
- Les Lindens
- </text>
- <button label="Définir..." label_selected="Définir..." name="button set group"/>
- <text name="Permissions:">
- Droits :
- </text>
- <text name="perm_modify">
- Vous pouvez modifier cet objet.
- </text>
- <check_box label="Partager avec le groupe" name="checkbox share with group" tool_tip="Autorisez tous les membres du groupe choisi à utiliser et à partager vos droits pour cet objet. Pour activer les restrictions de rôles, vous devez d&apos;abord cliquer sur Transférer."/>
- <string name="text deed continued">
- Transférer...
- </string>
- <string name="text deed">
- Transférer
- </string>
- <button label="Céder..." label_selected="Céder..." name="button deed" tool_tip="Les objets partagés par un groupe peuvent être cédés par un officier."/>
- <check_box label="Autoriser tout le monde à déplacer" name="checkbox allow everyone move"/>
- <check_box label="Autoriser tout le monde à copier" name="checkbox allow everyone copy"/>
- <check_box label="Afficher dans la recherche" name="search_check" tool_tip="Afficher l&apos;objet dans les résultats de recherche"/>
- <check_box label="À vendre" name="checkbox for sale"/>
- <text name="Cost">
- Prix : L$
- </text>
- <radio_group name="sale type">
- <radio_item name="Original">
- Original
- </radio_item>
- <radio_item name="Copy">
- Copie
- </radio_item>
- <radio_item name="Contents">
- Contenus
- </radio_item>
- </radio_group>
- <text name="Next owner can:">
- Le prochain propriétaire pourra :
- </text>
- <check_box label="Modifier" name="checkbox next owner can modify"/>
- <check_box label="Copier" left_delta="66" name="checkbox next owner can copy"/>
- <check_box label="Revendre/Donner" name="checkbox next owner can transfer"/>
+ <button label="Définir..." label_selected="Définir..." name="button set group" tool_tip="Choisissez un groupe pour partager les permissions de cet objet"/>
+ <name_box initial_value="Chargement..." name="Group Name Proxy"/>
+ <button label="Céder" label_selected="Céder" name="button deed" tool_tip="En cédant un objet, vous donnez aussi les permissions au prochain propriétaire. Seul un officier peut céder les objets d&apos;un groupe."/>
+ <check_box label="Partager" name="checkbox share with group" tool_tip="Autorisez tous les membres du groupe choisi à utiliser et à partager vos droits pour cet objet. Pour activer les restrictions de rôles, vous devez d&apos;abord cliquer sur Transférer."/>
<text name="label click action">
- Action du clic-gauche :
+ Cliquer pour :
</text>
<combo_box name="clickaction" width="178">
- <combo_item name="Touch/grab(default)">
- Toucher/attraper (défaut)
- </combo_item>
- <combo_item name="Sitonobject">
- S&apos;asseoir sur l&apos;objet
- </combo_item>
- <combo_item name="Buyobject">
- Acheter l&apos;objet
- </combo_item>
- <combo_item name="Payobject">
- Payer l&apos;objet
- </combo_item>
- <combo_item name="Open">
- Ouvrir
- </combo_item>
- <combo_item name="Play">
- Jouer le média de la parcelle
- </combo_item>
- <combo_item name="Opemmedia">
- Ouvrir le média de la parcelle
- </combo_item>
+ <combo_box.item label="Toucher (défaut)" name="Touch/grab(default)"/>
+ <combo_box.item label="S&apos;asseoir sur l&apos;objet" name="Sitonobject"/>
+ <combo_box.item label="Acheter l&apos;objet" name="Buyobject"/>
+ <combo_box.item label="Payer l&apos;objet" name="Payobject"/>
+ <combo_box.item label="Ouvrir" name="Open"/>
+ <combo_box.item label="Zoomer" name="Zoom"/>
</combo_box>
- <text name="B:">
- B :
- </text>
- <text name="O:">
- O :
- </text>
- <text name="G:">
- G :
- </text>
- <text name="E:">
- E :
- </text>
- <text name="N:">
- N :
- </text>
- <text name="F:">
- F :
- </text>
- <string name="text modify info 1">
- Vous pouvez modifier cet objet.
- </string>
- <string name="text modify info 2">
- Vous pouvez modifier ces objets.
- </string>
- <string name="text modify info 3">
- Vous ne pouvez pas modifier cet objet.
- </string>
- <string name="text modify info 4">
- Vous ne pouvez pas modifier ces objets.
- </string>
- <string name="text modify warning">
- Sélectionnez l&apos;objet en entier.
- </string>
- <string name="Cost Default">
- Prix : L$
- </string>
- <string name="Cost Total">
- Prix total : L$
- </string>
- <string name="Cost Per Unit">
- Prix par : L$
- </string>
- <string name="Cost Mixed">
- Prix mixte
- </string>
- <string name="Sale Mixed">
- Vente mixte
- </string>
+ <check_box label="À vendre :" name="checkbox for sale"/>
+ <combo_box name="sale type">
+ <combo_box.item label="Copie" name="Copy"/>
+ <combo_box.item label="Contenus" name="Contents"/>
+ <combo_box.item label="Original" name="Original"/>
+ </combo_box>
+ <spinner label="Prix : L$" name="Edit Cost"/>
+ <check_box label="Afficher dans la recherche" name="search_check" tool_tip="Afficher l&apos;objet dans les résultats de recherche"/>
+ <panel name="perms_build">
+ <text name="perm_modify">
+ Vous pouvez modifier cet objet
+ </text>
+ <text name="Anyone can:">
+ N&apos;importe qui :
+ </text>
+ <check_box label="Bouger" name="checkbox allow everyone move"/>
+ <check_box label="Copier" name="checkbox allow everyone copy"/>
+ <text name="Next owner can:">
+ Le prochain propriétaire :
+ </text>
+ <check_box label="Modifier" name="checkbox next owner can modify"/>
+ <check_box label="Copier" left_delta="66" name="checkbox next owner can copy"/>
+ <check_box label="Transférer" name="checkbox next owner can transfer" tool_tip="Le prochain propriétaire peut donner ou revendre cet objet"/>
+ <text name="B:">
+ B :
+ </text>
+ <text name="O:">
+ O :
+ </text>
+ <text name="G:">
+ G :
+ </text>
+ <text name="E:">
+ E :
+ </text>
+ <text name="N:">
+ N :
+ </text>
+ <text name="F:">
+ F :
+ </text>
+ </panel>
</panel>
<panel label="Objet" name="Object">
- <text name="select_single">
- Sélectionnez un prim pour modifier les paramètres.
- </text>
- <text name="edit_object">
- Modifier les paramètres de l&apos;objet :
- </text>
<check_box label="Verrouillé" name="checkbox locked" tool_tip="Empêche l&apos;objet d&apos;être déplacé ou supprimé. Utile pendant la construction pour éviter les modifications involontaires."/>
<check_box label="Physique" name="Physical Checkbox Ctrl" tool_tip="Permet à l&apos;objet d&apos;être poussé et affecté par la gravité"/>
- <check_box label="Temporaire" name="Temporary Checkbox Ctrl" tool_tip="L&apos;objet est supprimé 1 mn après sa création."/>
+ <check_box label="Temporaire" name="Temporary Checkbox Ctrl" tool_tip="Les objets sont supprimés une minute après leur création"/>
<check_box label="Fantôme" name="Phantom Checkbox Ctrl" tool_tip="Permet à l&apos;objet de ne pas entrer en collision avec d&apos;autres objets ou avatars."/>
<text name="label position">
Position (mètres)
@@ -250,63 +260,27 @@
<spinner label="X" name="Rot X"/>
<spinner label="Y" name="Rot Y"/>
<spinner label="Z" name="Rot Z"/>
- <text name="label material">
- Matériau
- </text>
- <combo_box name="material">
- <combo_item name="Stone">
- Pierre
- </combo_item>
- <combo_item name="Metal">
- Métal
- </combo_item>
- <combo_item name="Glass">
- Verre
- </combo_item>
- <combo_item name="Wood">
- Bois
- </combo_item>
- <combo_item name="Flesh">
- Chair
- </combo_item>
- <combo_item name="Plastic">
- Plastique
- </combo_item>
- <combo_item name="Rubber">
- Caoutchouc
- </combo_item>
- </combo_box>
- <text name="label basetype">
- Type de construction
- </text>
<combo_box name="comboBaseType">
- <combo_item name="Box">
- Boîte
- </combo_item>
- <combo_item name="Cylinder">
- Cylindre
- </combo_item>
- <combo_item name="Prism">
- Prisme
- </combo_item>
- <combo_item name="Sphere">
- Sphère
- </combo_item>
- <combo_item name="Torus">
- Tore
- </combo_item>
- <combo_item name="Tube">
- Tube
- </combo_item>
- <combo_item name="Ring">
- Anneau
- </combo_item>
- <combo_item name="Sculpted">
- Sculptie
- </combo_item>
+ <combo_box.item label="Boîte" name="Box"/>
+ <combo_box.item label="Cylindre" name="Cylinder"/>
+ <combo_box.item label="Prisme" name="Prism"/>
+ <combo_box.item label="Sphère" name="Sphere"/>
+ <combo_box.item label="Tore" name="Torus"/>
+ <combo_box.item label="Tube" name="Tube"/>
+ <combo_box.item label="Anneau" name="Ring"/>
+ <combo_box.item label="Sculptie" name="Sculpted"/>
+ </combo_box>
+ <combo_box name="material">
+ <combo_box.item label="Pierre" name="Stone"/>
+ <combo_box.item label="Métal" name="Metal"/>
+ <combo_box.item label="Verre" name="Glass"/>
+ <combo_box.item label="Bois" name="Wood"/>
+ <combo_box.item label="Chair" name="Flesh"/>
+ <combo_box.item label="Plastique" name="Plastic"/>
+ <combo_box.item label="Caoutchouc" name="Rubber"/>
</combo_box>
<text name="text cut">
- Début et fin de découpe du tracé
+ Découpe du tracé (début/fin)
</text>
<spinner label="D" name="cut begin"/>
<spinner label="F" name="cut end"/>
@@ -320,21 +294,13 @@
Forme du creux
</text>
<combo_box name="hole">
- <combo_item name="Default">
- Défaut
- </combo_item>
- <combo_item name="Circle">
- Cercle
- </combo_item>
- <combo_item name="Square">
- Carré
- </combo_item>
- <combo_item name="Triangle">
- Triangle
- </combo_item>
+ <combo_box.item label="Défaut" name="Default"/>
+ <combo_box.item label="Cercle" name="Circle"/>
+ <combo_box.item label="Carré" name="Square"/>
+ <combo_box.item label="Triangle" name="Triangle"/>
</combo_box>
<text name="text twist">
- Début et fin de vrille
+ Vrille (début/fin)
</text>
<spinner label="D" name="Twist Begin"/>
<spinner label="F" name="Twist End"/>
@@ -352,13 +318,13 @@
<spinner label="X" name="Shear X"/>
<spinner label="Y" name="Shear Y"/>
<text name="advanced_cut">
- Début et fin de découpe du profilé
+ Découpe du profilé (début/fin)
</text>
<text name="advanced_dimple">
- Début et fin du creux
+ Creux (début/fin)
</text>
<text name="advanced_slice">
- Début et fin de la tranche
+ Tranche (début/fin)
</text>
<spinner label="D" name="Path Limit Begin"/>
<spinner label="F" name="Path Limit End"/>
@@ -374,27 +340,17 @@
Révolutions
</text>
<texture_picker label="Texture du sculptie" name="sculpt texture control" tool_tip="Cliquez pour sélectionner une image"/>
- <check_box label="Mirroir" name="sculpt mirror control" tool_tip="Retourne le sculptie le long de l&apos;axe des X."/>
- <check_box label="A l&apos;envers" name="sculpt invert control" tool_tip="Inverse les valeurs normales d&apos;un sculptie et le fait apparaître à l&apos;envers."/>
+ <check_box label="Mirroir" name="sculpt mirror control" tool_tip="Inverse le sculptie le long de l&apos;axe X"/>
+ <check_box label="A l&apos;envers" name="sculpt invert control" tool_tip="Inverse les normales des sculpties, qui apparaissent alors à l&apos;envers"/>
<text name="label sculpt type">
Type de raccord
</text>
<combo_box name="sculpt type control">
- <combo_item name="None">
- (aucun)
- </combo_item>
- <combo_item name="Sphere">
- Sphère
- </combo_item>
- <combo_item name="Torus">
- Tore
- </combo_item>
- <combo_item name="Plane">
- Plan
- </combo_item>
- <combo_item name="Cylinder">
- Cylindre
- </combo_item>
+ <combo_box.item label="(aucun)" name="None"/>
+ <combo_box.item label="Sphère" name="Sphere"/>
+ <combo_box.item label="Tore" name="Torus"/>
+ <combo_box.item label="Plan" name="Plane"/>
+ <combo_box.item label="Cylindre" name="Cylinder"/>
</combo_box>
</panel>
<panel label="Attributs" name="Features">
@@ -404,7 +360,7 @@
<text name="edit_object">
Modifier les attributs de l&apos;objet :
</text>
- <check_box label="Flexibilité" name="Flexible1D Checkbox Ctrl" tool_tip="Donne à l&apos;objet de la souplesse sur l&apos;axe des Z (côté client uniquement)."/>
+ <check_box label="Flexibilité" name="Flexible1D Checkbox Ctrl" tool_tip="Permet à l&apos;objet de se plier le long de l&apos;axe Z (côté client uniquement)"/>
<spinner label="Souplesse" name="FlexNumSections"/>
<spinner label="Gravité" name="FlexGravity"/>
<spinner label="Élasticité" name="FlexFriction"/>
@@ -414,17 +370,24 @@
<spinner label="Force Y" name="FlexForceY"/>
<spinner label="Force Z" name="FlexForceZ"/>
<check_box label="Lumière" name="Light Checkbox Ctrl" tool_tip="Permet aux objets d&apos;émettre de la lumière"/>
- <text name="label color">
- Couleur
- </text>
<color_swatch label="" name="colorswatch" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs"/>
+ <texture_picker label="" name="light texture control" tool_tip="Cliquez pour choisir une image de projection (n&apos;a d&apos;effet que si le rendu différé est activé)"/>
<spinner label="Intensité" name="Light Intensity"/>
+ <spinner label="Angle de champ" name="Light FOV"/>
<spinner label="Portée" name="Light Radius"/>
+ <spinner label="Point central" name="Light Focus"/>
<spinner label="Atténuation" name="Light Falloff"/>
+ <spinner label="Ambiance" name="Light Ambiance"/>
</panel>
<panel label="Texture" name="Texture">
+ <panel.string name="string repeats per meter">
+ Répétitions au mètre
+ </panel.string>
+ <panel.string name="string repeats per face">
+ Répétitions par face
+ </panel.string>
<texture_picker label="Texture" name="texture control" tool_tip="Cliquez pour sélectionner une image"/>
- <color_swatch label="Couleur" name="colorswatch" tool_tip="Cliquer pour ouvrir le sélecteur de couleurs"/>
+ <color_swatch label="Couleur" name="colorswatch" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs"/>
<text name="color trans" width="88">
Transparence
</text>
@@ -436,125 +399,69 @@
Application
</text>
<combo_box name="combobox texgen">
- <combo_item name="Default">
- Défaut
- </combo_item>
- <combo_item name="Planar">
- Planar
- </combo_item>
+ <combo_box.item label="Défaut" name="Default"/>
+ <combo_box.item label="Planar" name="Planar"/>
</combo_box>
<text name="label shininess">
Brillance
</text>
<combo_box name="combobox shininess">
- <combo_item name="None">
- Aucune
- </combo_item>
- <combo_item name="Low">
- Faible
- </combo_item>
- <combo_item name="Medium">
- Moyenne
- </combo_item>
- <combo_item name="High">
- Élevée
- </combo_item>
+ <combo_box.item label="Aucune" name="None"/>
+ <combo_box.item label="Faible" name="Low"/>
+ <combo_box.item label="Moyenne" name="Medium"/>
+ <combo_box.item label="Élevée" name="High"/>
</combo_box>
<text name="label bumpiness">
Relief
</text>
<combo_box name="combobox bumpiness">
- <combo_item name="None">
- Aucun
- </combo_item>
- <combo_item name="Brightness">
- Luminosité
- </combo_item>
- <combo_item name="Darkness">
- Obscurité
- </combo_item>
- <combo_item name="woodgrain">
- Aggloméré
- </combo_item>
- <combo_item name="bark">
- Écorce
- </combo_item>
- <combo_item name="bricks">
- Briques
- </combo_item>
- <combo_item name="checker">
- Damier
- </combo_item>
- <combo_item name="concrete">
- Béton
- </combo_item>
- <combo_item name="crustytile">
- Carrelage
- </combo_item>
- <combo_item name="cutstone">
- Pierre de taille
- </combo_item>
- <combo_item name="discs">
- Disques
- </combo_item>
- <combo_item name="gravel">
- Gravier
- </combo_item>
- <combo_item name="petridish">
- Boîte de Petri
- </combo_item>
- <combo_item name="siding">
- Lattes
- </combo_item>
- <combo_item name="stonetile">
- Carreaux
- </combo_item>
- <combo_item name="stucco">
- Stuc
- </combo_item>
- <combo_item name="suction">
- Ventouses
- </combo_item>
- <combo_item name="weave">
- Tissage
- </combo_item>
+ <combo_box.item label="Aucun" name="None"/>
+ <combo_box.item label="Luminosité" name="Brightness"/>
+ <combo_box.item label="Obscurité" name="Darkness"/>
+ <combo_box.item label="Aggloméré" name="woodgrain"/>
+ <combo_box.item label="Écorce" name="bark"/>
+ <combo_box.item label="Briques" name="bricks"/>
+ <combo_box.item label="Damier" name="checker"/>
+ <combo_box.item label="Béton" name="concrete"/>
+ <combo_box.item label="Carrelage" name="crustytile"/>
+ <combo_box.item label="Pierre de taille" name="cutstone"/>
+ <combo_box.item label="Disques" name="discs"/>
+ <combo_box.item label="Gravier" name="gravel"/>
+ <combo_box.item label="Boîte de Petri" name="petridish"/>
+ <combo_box.item label="Lattes" name="siding"/>
+ <combo_box.item label="Carreaux" name="stonetile"/>
+ <combo_box.item label="Stuc" name="stucco"/>
+ <combo_box.item label="Ventouses" name="suction"/>
+ <combo_box.item label="Tissage" name="weave"/>
</combo_box>
<text name="tex scale">
- Répétitions par face
+ Répétitions / Face
</text>
<spinner label="Horizontal (U)" name="TexScaleU"/>
<check_box label="Inverser" name="checkbox flip s"/>
<spinner label="Vertical (V)" name="TexScaleV"/>
<check_box label="Inverser" name="checkbox flip t"/>
- <text name="tex rotate">
- Rotation (degrés)
- </text>
- <spinner left="122" name="TexRot" width="58"/>
- <string name="string repeats per meter">
- Répétitions au mètre
- </string>
- <string name="string repeats per face">
- Répétitions par face
- </string>
- <text name="rpt" width="160">
- Répétitions au mètre
- </text>
- <spinner left="122" name="rptctrl" width="58"/>
+ <spinner label="RotationËš" left="122" name="TexRot" width="58"/>
+ <spinner label="Répétitions / Mètre" left="122" name="rptctrl" width="58"/>
<button label="Appliquer" label_selected="Appliquer" left_delta="68" name="button apply" width="75"/>
<text name="tex offset">
- Décalage
+ Décalage de la texture
</text>
<spinner label="Horizontal (U)" name="TexOffsetU"/>
<spinner label="Vertical (V)" name="TexOffsetV"/>
- <text name="textbox autofix">
- Ajuster la texture du média
-(chargement préalable)
- </text>
- <button label="Ajuster" label_selected="Ajuster" left="150" name="button align"/>
+ <panel name="Add_Media">
+ <text name="media_tex">
+ URL du média
+ </text>
+ <button name="add_media" tool_tip="Ajouter un média"/>
+ <button name="delete_media" tool_tip="Supprimer cette texture de média"/>
+ <button name="edit_media" tool_tip="Modifier ce média"/>
+ <button label="Aligner" label_selected="Aligner le média" name="button align"/>
+ </panel>
</panel>
<panel label="Contenu" name="Contents">
- <button label="Nouveau script" label_selected="Nouveau script..." name="button new script"/>
- <button label="Droits..." name="button permissions"/>
+ <button label="Nouveau script" label_selected="Nouveau script" name="button new script"/>
+ <button label="Droits" name="button permissions"/>
</panel>
</tab_container>
<panel name="land info panel">
@@ -562,62 +469,29 @@
Informations sur la parcelle
</text>
<text name="label_area_price">
- Prix : [PRICE] L$ pour [AREA] m².
+ Prix : [PRICE] L$ pour [AREA] m²
</text>
<text name="label_area">
- Surface : [AREA] m²
+ Surface : [AREA] m²
</text>
- <button label="À propos du terrain..." label_selected="À propos du terrain..." name="button about land" width="142"/>
- <check_box label="Afficher les propriétaires" name="checkbox show owners" tool_tip="Colorie les parcelles en fonction de leur propriétaire"/>
- <button label="?" label_selected="?" name="button show owners help" left_delta="154"/>
+ <button label="À propos des terrains" label_selected="À propos des terrains" name="button about land" width="142"/>
+ <check_box label="Afficher les propriétaires" name="checkbox show owners" tool_tip="Colorier les parcelles en fonction du type de leur propriétaire :
+
+Vert = votre terrain
+Turquoise = le terrain de votre groupe
+Rouge = appartenant à d&apos;autres
+Jaune = en vente
+Mauve = aux enchères
+Gris = public"/>
<text name="label_parcel_modify">
Modifier la parcelle
</text>
- <button label="Diviser..." label_selected="Diviser..." name="button subdivide land" width="142"/>
- <button label="Fusionner..." label_selected="Fusionner..." name="button join land" width="142"/>
+ <button label="Sous-diviser" label_selected="Sous-diviser" name="button subdivide land" width="142"/>
+ <button label="Fusionner" label_selected="Fusionner" name="button join land" width="142"/>
<text name="label_parcel_trans">
Transactions
</text>
- <button label="Acheter le terrain..." label_selected="Acheter le terrain..." name="button buy land" width="142"/>
- <button label="Abandonner le terrain..." label_selected="Abandonner le terrain..." name="button abandon land" width="142"/>
+ <button label="Acheter du terrain" label_selected="Acheter du terrain" name="button buy land" width="142"/>
+ <button label="Abandonner le terrain" label_selected="Abandonner le terrain" name="button abandon land" width="142"/>
</panel>
- <string name="status_rotate">
- Pour faire tourner l&apos;objet, faîtes glisser les bandes de couleur.
- </string>
- <string name="status_scale">
- Pour étirer le côté sélectionné, cliquez et faites glisser.
- </string>
- <string name="status_move">
- Glissez pour déplacer, Maj-glissez pour copier.
- </string>
- <string name="status_modifyland">
- Cliquez et maintenez pour modifier le terrain.
- </string>
- <string name="status_camera">
- Cliquez et faites glisser pour changer l&apos;affichage.
- </string>
- <string name="status_grab">
- Glisser pour déplacer, Ctrl pour soulever, Crtl-Maj pour pivoter.
- </string>
- <string name="status_place">
- Cliquez dans le monde pour construire.
- </string>
- <string name="status_selectland">
- Cliquez et faites glisser pour sélectionner le terrain.
- </string>
- <string name="grid_screen_text">
- Écran
- </string>
- <string name="grid_local_text">
- Local
- </string>
- <string name="grid_world_text">
- Monde
- </string>
- <string name="grid_reference_text">
- Référence
- </string>
- <string name="grid_attachment_text">
- Pièce-jointe
- </string>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_top_objects.xml b/indra/newview/skins/default/xui/fr/floater_top_objects.xml
index 69a3d0cd18..479559367f 100644
--- a/indra/newview/skins/default/xui/fr/floater_top_objects.xml
+++ b/indra/newview/skins/default/xui/fr/floater_top_objects.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="top_objects" title="en cours de chargement...">
+<floater name="top_objects" title="EN COURS DE CHARGEMENT...">
<text name="title_text">
Chargement...
</text>
diff --git a/indra/newview/skins/default/xui/fr/floater_tos.xml b/indra/newview/skins/default/xui/fr/floater_tos.xml
index b77838d92c..2c8e8bc5bc 100644
--- a/indra/newview/skins/default/xui/fr/floater_tos.xml
+++ b/indra/newview/skins/default/xui/fr/floater_tos.xml
@@ -1,22 +1,17 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="modal container" title=" ">
- <button label="Continuer" label_selected="Continuer" name="Continue" />
- <button label="Annuler" label_selected="Annuler" name="Cancel" />
+ <button label="Continuer" label_selected="Continuer" name="Continue"/>
+ <button label="Annuler" label_selected="Annuler" name="Cancel"/>
<radio_group name="tos_agreement">
- <radio_item name="radio_disagree">
- Je n&apos;accepte pas les Conditions Générales d&apos;Utilisation
- </radio_item>
- <radio_item name="radio_agree">
- J&apos;accepte les Conditions Générales d&apos;Utilisation
- </radio_item>
+ <radio_item label="Je n&apos;accepte pas les Conditions Générales d&apos;Utilisation" name="radio_disagree"/>
+ <radio_item label="J&apos;accepte les Conditions Générales d&apos;Utilisation" name="radio_agree"/>
</radio_group>
<text name="tos_title">
Acceptation des Conditions Générales d&apos;Utilisation
</text>
- <check_box label="J&apos;accepte les Conditions d&apos;utilisation" name="agree_chk" />
+ <check_box label="J&apos;accepte les Conditions d&apos;utilisation" name="agree_chk"/>
<text name="tos_heading">
- Veuillez lire attentivement les Conditions d&apos;utilisation suivantes. Pour continuer à utiliser
-Second Life, vous devez accepter ces conditions.
+ Veuillez lire attentivement les Conditions d&apos;utilisation suivantes. Pour vous connecter à [SECOND_LIFE], vous devez accepter l&apos;accord.
</text>
<text_editor name="tos_text">
TOS_TEXT
diff --git a/indra/newview/skins/default/xui/fr/floater_voice_controls.xml b/indra/newview/skins/default/xui/fr/floater_voice_controls.xml
new file mode 100644
index 0000000000..02d6430699
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_voice_controls.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_voice_controls" title="Contrôles vocaux">
+ <panel name="control_panel">
+ <panel name="my_panel">
+ <text name="user_text" value="Mon avatar :"/>
+ </panel>
+ <layout_stack>
+ <layout_panel>
+ <slider_bar name="volume_slider_bar" tool_tip="Volume principal"/>
+ </layout_panel>
+ </layout_stack>
+ </panel>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_water.xml b/indra/newview/skins/default/xui/fr/floater_water.xml
index 9b77c2450d..287f51d9f7 100644
--- a/indra/newview/skins/default/xui/fr/floater_water.xml
+++ b/indra/newview/skins/default/xui/fr/floater_water.xml
@@ -1,66 +1,53 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Water Floater" title="Éditeur d&apos;eau avancé">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Water Floater" title="ÉDITEUR D&apos;EAU AVANCÉE">
+ <floater.string name="WLDefaultWaterNames">
+ Default:Glassy:Pond:Murky:Second Plague:SNAKE!!!:Valdez
+ </floater.string>
<text name="KeyFramePresetsText">
Préréglages eau :
</text>
- <button label="Nouveau" label_selected="Nouveau" name="WaterNewPreset" />
- <button label="Enregistrer" label_selected="Enregistrer" name="WaterSavePreset" width="75" left_delta="75"/>
- <button label="Supprimer" label_selected="Supprimer" name="WaterDeletePreset" left_delta="80"/>
+ <button label="Nouveau" label_selected="Nouveau" name="WaterNewPreset"/>
+ <button label="Enregistrer" label_selected="Enregistrer" left_delta="75" name="WaterSavePreset" width="75"/>
+ <button label="Supprimer" label_selected="Supprimer" left_delta="80" name="WaterDeletePreset"/>
<tab_container name="Water Tabs">
<panel label="Paramètres" name="Settings">
<text name="BHText">
Couleur du brouillard
dans l&apos;eau
</text>
- <button label="?" name="WaterFogColorHelp" />
- <color_swatch name="WaterFogColor" left="75" tool_tip="Cliquer pour ouvrir le sélecteur de couleurs" />
+ <color_swatch left="75" name="WaterFogColor" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs"/>
<text name="WaterFogDensText">
Densité du brouillard
</text>
- <button label="?" name="WaterFogDensityHelp" />
<text name="WaterUnderWaterFogModText">
Brouillard sous-marin
</text>
- <button label="?" name="WaterUnderWaterFogModHelp" />
<text name="BDensText">
Échelle des vaguelettes
</text>
- <button label="?" name="WaterNormalScaleHelp" />
- <text name="BHText2">
- 1
- </text>
- <text name="BHText3">
- 2
- </text>
- <text name="BHText4">
- 3
- </text>
+ <slider label="1" name="WaterNormalScaleX"/>
+ <slider label="2" name="WaterNormalScaleY"/>
+ <slider label="3" name="WaterNormalScaleZ"/>
<text name="HDText">
Échelle Fresnel
</text>
- <button label="?" name="WaterFresnelScaleHelp" />
<text name="FresnelOffsetText">
Décalage Fresnel
</text>
- <button label="?" name="WaterFresnelOffsetHelp" />
<text name="DensMultText">
Réfraction au dessus
</text>
- <button label="?" name="WaterScaleAboveHelp" />
<text name="WaterScaleBelowText">
Réfraction en dessous
</text>
- <button label="?" name="WaterScaleBelowHelp" />
<text name="MaxAltText">
Multiplicateur de flou
</text>
- <button label="?" name="WaterBlurMultiplierHelp" />
</panel>
<panel label="Image" name="Waves">
<text name="BHText">
Direction grande vague
</text>
- <button label="?" name="WaterWave1Help" />
<text name="WaterWave1DirXText">
X
</text>
@@ -70,7 +57,6 @@ dans l&apos;eau
<text name="BHText2">
Direction petite vague
</text>
- <button label="?" name="WaterWave2Help" />
<text name="WaterWave2DirXText">
X
</text>
@@ -80,10 +66,6 @@ dans l&apos;eau
<text name="BHText3">
Normal Map
</text>
- <button label="?" name="WaterNormalMapHelp" />
</panel>
</tab_container>
- <string name="WLDefaultWaterNames">
- Default:Glassy:Pond:Murky:Second Plague:SNAKE!!!:Valdez
- </string>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_wearable_save_as.xml b/indra/newview/skins/default/xui/fr/floater_wearable_save_as.xml
index a5bc87d951..af6274d4e2 100644
--- a/indra/newview/skins/default/xui/fr/floater_wearable_save_as.xml
+++ b/indra/newview/skins/default/xui/fr/floater_wearable_save_as.xml
@@ -2,7 +2,7 @@
<floater name="modal container">
<button label="Enregistrer" label_selected="Enregistrer" name="Save" />
<button label="Annuler" label_selected="Annuler" name="Cancel" />
- <text type="string" length="1" name="Save item as:">
+ <text name="Save item as:">
Enregistrer l&apos;objet sous :
</text>
<line_editor name="name ed">
diff --git a/indra/newview/skins/default/xui/fr/floater_whitelist_entry.xml b/indra/newview/skins/default/xui/fr/floater_whitelist_entry.xml
new file mode 100644
index 0000000000..f1ba403bf9
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_whitelist_entry.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="whitelist_entry">
+ <text name="media_label">
+ Saisissez une URL ou un style d&apos;URL à ajouter à la liste des domaines autorisés
+ </text>
+ <line_editor name="whitelist_entry" tool_tip="Saisissez une URL ou un style d&apos;URL à ajouter à la liste blanche"/>
+ <button label="OK" name="ok_btn"/>
+ <button label="Annuler" name="cancel_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_windlight_options.xml b/indra/newview/skins/default/xui/fr/floater_windlight_options.xml
index d1a62dc6bc..e28de71625 100644
--- a/indra/newview/skins/default/xui/fr/floater_windlight_options.xml
+++ b/indra/newview/skins/default/xui/fr/floater_windlight_options.xml
@@ -1,19 +1,18 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="WindLight floater" title="Éditeur de ciel avancé" width="706">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="WindLight floater" title="ÉDITEUR DE CIEL AVANCÉ" width="706">
<text name="KeyFramePresetsText">
Préréglages ciel :
</text>
- <button label="Nouveau" label_selected="Nouveau" name="WLNewPreset" />
- <button label="Enregistrer" label_selected="Enregistrer" name="WLSavePreset" width="75" left_delta="75"/>
- <button label="Supprimer" label_selected="Supprimer" name="WLDeletePreset" left_delta="80"/>
- <button label="Éditeur du cycle du jour" label_selected="Éditeur du cycle du jour"
- name="WLDayCycleMenuButton" width="150" left_delta="95" />
+ <button label="Nouveau" label_selected="Nouveau" name="WLNewPreset"/>
+ <button label="Enregistrer" label_selected="Enregistrer" left_delta="75" name="WLSavePreset" width="75"/>
+ <button label="Supprimer" label_selected="Supprimer" left_delta="80" name="WLDeletePreset"/>
+ <button label="Éditeur du cycle du jour" label_selected="Éditeur du cycle du jour" left_delta="95" name="WLDayCycleMenuButton" width="150"/>
<tab_container name="WindLight Tabs" width="706">
<panel label="Atmosphère" name="Atmosphere">
<text name="BHText">
Bleu de l&apos;horizon
</text>
- <button label="?" name="WLBlueHorizonHelp" />
+ <button label="?" name="WLBlueHorizonHelp"/>
<text name="BHText2">
R
</text>
@@ -29,11 +28,11 @@
<text name="BDensText">
Quantité de brume
</text>
- <button label="?" name="WLHazeHorizonHelp" />
+ <button label="?" name="WLHazeHorizonHelp"/>
<text name="BDensText2">
Densité du bleu
</text>
- <button label="?" name="WLBlueDensityHelp" />
+ <button label="?" name="WLBlueDensityHelp"/>
<text name="BHText6">
R
</text>
@@ -49,25 +48,25 @@
<text name="HDText">
Densité de la brume
</text>
- <button label="?" name="WLHazeDensityHelp" />
+ <button label="?" name="WLHazeDensityHelp"/>
<text name="DensMultText">
Multiplicateur de densité
</text>
- <button label="?" name="WLDensityMultHelp" />
+ <button label="?" name="WLDensityMultHelp"/>
<text name="WLDistanceMultText">
Multiplicateur de distance
</text>
- <button label="?" name="WLDistanceMultHelp" />
+ <button label="?" name="WLDistanceMultHelp"/>
<text name="MaxAltText">
Altitude maximum
</text>
- <button label="?" name="WLMaxAltitudeHelp" />
+ <button label="?" name="WLMaxAltitudeHelp"/>
</panel>
<panel label="Éclairage" name="Lighting">
<text name="SLCText">
Couleur soleil/lune
</text>
- <button label="?" name="WLSunlightColorHelp" />
+ <button label="?" name="WLSunlightColorHelp"/>
<text name="BHText">
R
</text>
@@ -83,11 +82,11 @@
<text name="TODText">
Position soleil/lune
</text>
- <button label="?" name="WLTimeOfDayHelp" />
+ <button label="?" name="WLTimeOfDayHelp"/>
<text name="WLAmbientText">
Éclairage ambiant
</text>
- <button label="?" name="WLAmbientHelp" />
+ <button label="?" name="WLAmbientHelp"/>
<text name="BHText5">
R
</text>
@@ -103,27 +102,27 @@
<text name="WLEastAngleText">
Angle du levant
</text>
- <button label="?" name="WLEastAngleHelp" />
+ <button label="?" name="WLEastAngleHelp"/>
<text name="SunGlowText">
Rayonnement du soleil
</text>
- <button label="?" name="WLSunGlowHelp" />
- <slider label="Netteté " name="WLGlowB" />
- <slider label="Taille " name="WLGlowR" />
+ <button label="?" name="WLSunGlowHelp"/>
+ <slider label="Netteté " name="WLGlowB"/>
+ <slider label="Taille " name="WLGlowR"/>
<text name="SceneGammaText">
Gamma de la scène
</text>
- <button label="?" name="WLSceneGammaHelp" />
+ <button label="?" name="WLSceneGammaHelp"/>
<text name="WLStarText">
Éclat des étoiles
</text>
- <button label="?" name="WLStarBrightnessHelp" />
+ <button label="?" name="WLStarBrightnessHelp"/>
</panel>
<panel label="Nuages" name="Clouds">
<text name="WLCloudColorText">
Couleur des nuages
</text>
- <button label="?" name="WLCloudColorHelp" />
+ <button label="?" name="WLCloudColorHelp"/>
<text name="BHText">
R
</text>
@@ -139,7 +138,7 @@
<text name="WLCloudColorText2">
Nuages XY/densité
</text>
- <button label="?" name="WLCloudDensityHelp" />
+ <button label="?" name="WLCloudDensityHelp"/>
<text name="BHText5">
X
</text>
@@ -152,15 +151,15 @@
<text name="WLCloudCoverageText">
Couverture nuageuse
</text>
- <button label="?" name="WLCloudCoverageHelp" left="407"/>
+ <button label="?" left="407" name="WLCloudCoverageHelp"/>
<text name="WLCloudScaleText">
Altitude des nuages
</text>
- <button label="?" name="WLCloudScaleHelp" left="407"/>
+ <button label="?" left="407" name="WLCloudScaleHelp"/>
<text name="WLCloudDetailText">
Détails nuages (XY/densité)
</text>
- <button label="?" name="WLCloudDetailHelp" left="407" bottom_delta="-2" />
+ <button bottom_delta="-2" label="?" left="407" name="WLCloudDetailHelp"/>
<text name="BHText8">
X
</text>
@@ -173,15 +172,15 @@
<text name="WLCloudScrollXText">
Direction et vitesse X
</text>
- <button label="?" name="WLCloudScrollXHelp" />
- <check_box label="Verrouiller" name="WLCloudLockX" />
+ <button label="?" name="WLCloudScrollXHelp"/>
+ <check_box label="Verrouiller" name="WLCloudLockX"/>
<text name="WLCloudScrollYText">
Direction et vitesse Y
</text>
- <button label="?" name="WLCloudScrollYHelp" />
- <check_box label="Verrouiller" name="WLCloudLockY" />
- <check_box label="Nuages classiques" name="DrawClassicClouds" />
- <button label="?" name="WLClassicCloudsHelp" />
+ <button label="?" name="WLCloudScrollYHelp"/>
+ <check_box label="Verrouiller" name="WLCloudLockY"/>
+ <check_box label="Nuages classiques" name="DrawClassicClouds"/>
+ <button label="?" name="WLClassicCloudsHelp"/>
</panel>
</tab_container>
<string name="WLDefaultSkyNames">
diff --git a/indra/newview/skins/default/xui/fr/floater_world_map.xml b/indra/newview/skins/default/xui/fr/floater_world_map.xml
index bf7004e66f..03bbd0af08 100644
--- a/indra/newview/skins/default/xui/fr/floater_world_map.xml
+++ b/indra/newview/skins/default/xui/fr/floater_world_map.xml
@@ -1,75 +1,68 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="worldmap" title="Carte du monde">
- <tab_container name="maptab" width="955">
- <panel label="Objets" name="objects_mapview" width="953"/>
- <panel label="Terrain" name="terrain_mapview" width="953"/>
- </tab_container>
- <icon left="973" name="self"/>
+<floater name="worldmap" title="CARTE DU MONDE">
+ <panel name="objects_mapview" width="542"/>
+ <icon left="-270" name="self"/>
<text name="you_label">
Vous
</text>
- <icon left="1033" name="home"/>
+ <icon name="home"/>
<text name="home_label">
Domicile
</text>
- <icon left="973" name="square2"/>
+ <icon left="-270" name="square2"/>
<text name="auction_label">
Terrain aux enchères
</text>
- <icon left="1105" name="square"/>
+ <icon left_delta="130" name="square"/>
<text name="land_for_sale_label">
Terrain à vendre
</text>
- <button label="Aller chez moi" label_selected="Aller chez moi" name="Go Home" tool_tip="Vous téléporte à votre domicile"/>
- <icon left="977" name="person"/>
+ <button label="Aller chez moi" label_selected="Aller chez moi" left="-120" name="Go Home" tool_tip="Vous téléporte à votre domicile" width="108"/>
+ <icon left="-262" name="person"/>
<check_box label="Résident" name="people_chk"/>
- <icon left="973" name="infohub"/>
+ <icon left="-266" name="infohub"/>
<check_box label="Infohub" name="infohub_chk"/>
- <icon left="973" name="telehub"/>
- <check_box label="Téléhub" name="telehubchk"/>
- <icon left="973" name="landforsale"/>
+ <icon left="-266" name="telehub"/>
+ <check_box label="Téléhub" name="telehub_chk"/>
+ <icon left="-266" name="landforsale"/>
<check_box label="Terrain à vendre" name="land_for_sale_chk"/>
- <text name="events_label" left="1099">
+ <text left="-144" name="events_label">
Événements :
</text>
- <icon left="1121" name="event"/>
+ <icon left="-132" name="event"/>
<check_box label="PG" name="event_chk"/>
- <icon left="1121" name="events_mature_icon"/>
- <check_box label="Mature" name="event_mature_chk"/>
- <icon left="1121" name="events_adult_icon"/>
+ <icon left="-132" name="events_mature_icon"/>
+ <check_box initial_value="true" label="Mature" name="event_mature_chk"/>
+ <icon left="-132" name="events_adult_icon"/>
<check_box label="Adult" name="event_adult_chk"/>
- <icon left="973" name="avatar_icon"/>
- <combo_box label="Amis connectés" name="friend combo" tool_tip="Ami à afficher sur la carte" width="232">
- <combo_item name="none_selected">
- Amis connectés
- </combo_item>
+ <icon left="-270" name="avatar_icon"/>
+ <combo_box label="Amis connectés" name="friend combo" tool_tip="Ami(e) à afficher sur la carte" width="232">
+ <combo_box.item label="Amis connectés" name="item1"/>
</combo_box>
- <icon left="973" name="landmark_icon"/>
+ <icon left="-270" name="landmark_icon"/>
<combo_box label="Repères" name="landmark combo" tool_tip="Repère à afficher sur la carte" width="232">
- <combo_item name="none_selected">
- Repères
- </combo_item>
+ <combo_box.item label="Repères" name="item1"/>
</combo_box>
- <icon left="973" name="location_icon"/>
+ <icon left="-270" name="location_icon"/>
<line_editor label="Rechercher par nom de région" name="location" tool_tip="Saisissez le nom d&apos;une région" width="155"/>
<button label="Rechercher" label_selected="&gt;" left_delta="160" name="DoSearch" tool_tip="Recherchez sur la carte" width="75"/>
- <text left="973" name="search_label">
+ <text left="-270" name="search_label">
Résultats de la recherche :
</text>
- <scroll_list left="973" name="search_results" width="252">
- <column label="" name="icon"/>
- <column label="" name="sim_name"/>
+ <scroll_list left="-270" name="search_results" width="252">
+ <scroll_list.columns label="" name="icon"/>
+ <scroll_list.columns label="" name="sim_name"/>
</scroll_list>
- <text left="973" name="location_label">
+ <text left="-270" name="location_label">
Emplacement :
</text>
- <spinner left="1078" name="spin x" tool_tip="Coordonnées des X du lieu à afficher sur la carte"/>
+ <spinner left_delta="100" name="spin x" tool_tip="Coordonnées des X du lieu à afficher sur la carte"/>
<spinner name="spin y" tool_tip="Coordonnées des Y du lieu à afficher sur la carte"/>
<spinner name="spin z" tool_tip="Coordonnées des Z du lieu à afficher sur la carte"/>
<button label="Téléporter" label_selected="Téléporter" left="-270" name="Teleport" tool_tip="Téléporter à l&apos;endroit sélectionné"/>
<button label="Afficher la destination" label_selected="Afficher la destination" name="Show Destination" tool_tip="Centrer la carte sur l&apos;endroit sélectionné" width="165"/>
<button label="Effacer" label_selected="Effacer" left="-270" name="Clear" tool_tip="Arrêter de suivre"/>
<button label="Afficher mon emplacement" label_selected="Afficher mon emplacement" name="Show My Location" tool_tip="Centrer la carte sur l&apos;emplacement de votre avatar" width="165"/>
- <button label="Copier la SLURL dans le presse-papiers" left="-270" name="copy_slurl" tool_tip="Copier l&apos;emplacement actuel comme SLURL pour l&apos;utiliser sur le Web." width="262"/>
+ <button label="Copier la SLurl dans le presse-papiers" left="-270" name="copy_slurl" tool_tip="Copie l&apos;emplacement actuel sous la forme d&apos;une SLurl à utiliser sur le Web."/>
<slider label="Zoom" left="-270" name="zoom slider"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/inspect_avatar.xml b/indra/newview/skins/default/xui/fr/inspect_avatar.xml
new file mode 100644
index 0000000000..bfc4e06530
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/inspect_avatar.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater name="inspect_avatar">
+ <string name="Subtitle">
+ [AGE]
+ </string>
+ <string name="Details">
+ [SL_PROFILE]
+ </string>
+ <string name="Partner">
+ Partenaire : [PARTNER]
+ </string>
+ <text name="user_name" value="Grumpity ProductEngine"/>
+ <text name="user_subtitle" value="11 mois, 3 jours"/>
+ <text name="user_details">
+ C&apos;est ma description second life et je la trouve vraiment géniale.
+ </text>
+ <text name="user_partner">
+ Erica Linden
+ </text>
+ <slider name="volume_slider" tool_tip="Volume de la voix" value="0.5"/>
+ <button label="Devenir amis" name="add_friend_btn"/>
+ <button label="IM" name="im_btn"/>
+ <button label="Plus" name="view_profile_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/inspect_group.xml b/indra/newview/skins/default/xui/fr/inspect_group.xml
new file mode 100644
index 0000000000..9d6095632e
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/inspect_group.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater name="inspect_group">
+ <string name="PrivateGroup">
+ Groupe privé
+ </string>
+ <string name="FreeToJoin">
+ Inscription gratuite
+ </string>
+ <string name="CostToJoin">
+ Inscription : [AMOUNT] L$
+ </string>
+ <string name="YouAreMember">
+ Vous êtes membre
+ </string>
+ <text name="group_name">
+ Groupe grognon des Orignaux Grumpity
+ </text>
+ <text name="group_subtitle">
+ 123 membres
+ </text>
+ <text name="group_details">
+ Un groupe chargé de créer une pièce avec un orignal.
+Méfiez-vous de l&apos;orignal ! Méfiez-vous ! Et de la mangouste aussi !
+ </text>
+ <text name="group_cost">
+ Inscription : 123 L$
+ </text>
+ <button label="Vous inscrire" name="join_btn"/>
+ <button label="Quitter" name="leave_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/inspect_object.xml b/indra/newview/skins/default/xui/fr/inspect_object.xml
new file mode 100644
index 0000000000..e50de400fd
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/inspect_object.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater name="inspect_object">
+ <string name="Creator">
+ Par [CREATOR]
+ </string>
+ <string name="CreatorAndOwner">
+ par [CREATOR]
+propriétaire [OWNER]
+ </string>
+ <string name="Price">
+ [AMOUNT] L$
+ </string>
+ <string name="PriceFree">
+ Gratuit !
+ </string>
+ <string name="Touch">
+ Toucher
+ </string>
+ <string name="Sit">
+ M&apos;asseoir
+ </string>
+ <text name="object_name" value="Nom d&apos;objet de test vraiment très long"/>
+ <text name="object_creator">
+ par secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
+owner secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
+ </text>
+ <text name="price_text">
+ 300 000 L$
+ </text>
+ <text name="object_description">
+ Cette description d&apos;objet est vraiment très longue : elle compte au moins 80 caractères, voire plus de 120, vraiment très très longue. Who knows, really?
+ </text>
+ <text name="object_media_url">
+ http://www.superdupertest.com
+ </text>
+ <button label="Acheter" name="buy_btn"/>
+ <button label="Payer" name="pay_btn"/>
+ <button label="Prendre une copie" name="take_free_copy_btn"/>
+ <button label="Toucher" name="touch_btn"/>
+ <button label="M&apos;asseoir" name="sit_btn"/>
+ <button label="Ouvert" name="open_btn"/>
+ <icon name="secure_browsing" tool_tip="Navigation sécurisée"/>
+ <button label="Plus" name="more_info_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/inspect_remote_object.xml b/indra/newview/skins/default/xui/fr/inspect_remote_object.xml
new file mode 100644
index 0000000000..6d8c44578a
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/inspect_remote_object.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater name="inspect_remote_object">
+ <text name="object_name">
+ Nom d&apos;objet de test vraiment très long
+ </text>
+ <text name="object_owner_label">
+ Propriétaire :
+ </text>
+ <text name="object_owner">
+ Longavatarname Johnsonlongstonnammer
+ </text>
+ <text name="object_slurl_label">
+ Lieu :
+ </text>
+ <text name="object_slurl">
+ http://slurl.com/Ahern/50/50/50
+ </text>
+ <button label="Carte" name="map_btn"/>
+ <button label="Ignorer" name="block_btn"/>
+ <button label="Fermer" name="close_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/language_settings.xml b/indra/newview/skins/default/xui/fr/language_settings.xml
new file mode 100644
index 0000000000..71418d446a
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/language_settings.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- This file contains strings that used to be hardcoded in the source.-->
+<strings>
+
+ <!-- Locale Information -->
+ <string name="MicrosoftLocale">english</string>
+ <string name="DarwinLocale">C</string>
+ <string name="LinuxLocale">C</string>
+
+ <!--
+ datetimeToCodes["wkday"] = "%a"; // Thu
+ datetimeToCodes["weekday"] = "%A"; // Thursday
+ datetimeToCodes["year4"] = "%Y"; // 2009
+ datetimeToCodes["year"] = "%Y"; // 2009
+ datetimeToCodes["year2"] = "%y"; // 09
+ datetimeToCodes["mth"] = "%b"; // Aug
+ datetimeToCodes["month"] = "%B"; // August
+ datetimeToCodes["mthnum"] = "%m"; // 08
+ datetimeToCodes["day"] = "%d"; // 31
+ datetimeToCodes["hour24"] = "%H"; // 14
+ datetimeToCodes["hour"] = "%H"; // 14
+ datetimeToCodes["hour12"] = "%I"; // 02
+ datetimeToCodes["min"] = "%M"; // 59
+ datetimeToCodes["ampm"] = "%p"; // AM
+ datetimeToCodes["second"] = "%S"; // 59
+ datetimeToCodes["timezone"] = "%Z"; // PST
+ -->
+
+ <string name="TimeHour">hour,datetime,slt</string>
+ <string name="TimeMin">min,datetime,slt</string>
+ <string name="TimeYear">year,datetime,slt</string>
+ <string name="TimeDay">day,datetime,slt</string>
+ <string name="TimeMonth">mthnum,datetime,slt</string>
+ <string name="TimeWeek">wkday,datetime,slt</string>
+ <string name="TimeAMPM">ampm,datetime,slt</string>
+ <string name="TimeHour12">hour12,datetime,slt</string>
+
+ <string name="LTimeMthNum">mthnum,datetime,local</string>
+ <string name="LTimeWeek">wkday,datetime,local</string>
+ <string name="LTimeMonth">mth,datetime,local</string>
+ <string name="LTimeDay">day,datetime,local</string>
+ <string name="LTimeSec">second,datetime,local</string>
+ <string name="LTimeHour">hour,datetime,local</string>
+ <string name="LTimeMin">min,datetime,local</string>
+ <string name="LTimeYear">year,datetime,local</string>
+
+ <string name="UTCTimeWeek">weekday,datetime,utc</string>
+ <string name="UTCTimeDay">day,datetime,utc</string>
+ <string name="UTCTimeMth">mth,datetime,utc</string>
+ <string name="UTCTimeYr">year,datetime,utc</string>
+ <string name="UTCTimeHr">hour,datetime,utc</string>
+ <string name="UTCTimeMin">min,datetime,utc</string>
+ <string name="UTCTimeSec">second,datetime,utc</string>
+ <string name="UTCTimeTimezone">timezone,datetime,utc</string>
+</strings>
diff --git a/indra/newview/skins/default/xui/fr/menu_avatar_icon.xml b/indra/newview/skins/default/xui/fr/menu_avatar_icon.xml
new file mode 100644
index 0000000000..8f3dfae86e
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_avatar_icon.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Avatar Icon Menu">
+ <menu_item_call label="Voir le profil..." name="Show Profile"/>
+ <menu_item_call label="Envoyer IM..." name="Send IM"/>
+ <menu_item_call label="Devenir amis..." name="Add Friend"/>
+ <menu_item_call label="Supprimer cet ami..." name="Remove Friend"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_bottomtray.xml b/indra/newview/skins/default/xui/fr/menu_bottomtray.xml
new file mode 100644
index 0000000000..46db635afd
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_bottomtray.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="hide_camera_move_controls_menu">
+ <menu_item_check label="Bouton Geste" name="ShowGestureButton"/>
+ <menu_item_check label="Bouton Bouger" name="ShowMoveButton"/>
+ <menu_item_check label="Bouton Afficher" name="ShowCameraButton"/>
+ <menu_item_check label="Bouton Photo" name="ShowSnapshotButton"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_favorites.xml b/indra/newview/skins/default/xui/fr/menu_favorites.xml
new file mode 100644
index 0000000000..5f1545fde7
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_favorites.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Popup">
+ <menu_item_call label="Téléporter" name="Teleport To Landmark"/>
+ <menu_item_call label="Voir/Modifier le repère" name="Landmark Open"/>
+ <menu_item_call label="Copier la SLurl" name="Copy slurl"/>
+ <menu_item_call label="Voir sur la carte" name="Show On Map"/>
+ <menu_item_call label="Copier" name="Landmark Copy"/>
+ <menu_item_call label="Coller" name="Landmark Paste"/>
+ <menu_item_call label="Supprimer" name="Delete"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_gesture_gear.xml b/indra/newview/skins/default/xui/fr/menu_gesture_gear.xml
new file mode 100644
index 0000000000..02d734045a
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_gesture_gear.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_gesture_gear">
+ <menu_item_call label="Ajouter/Supprimer des Favoris" name="activate"/>
+ <menu_item_call label="Copier" name="copy_gesture"/>
+ <menu_item_call label="Coller" name="paste"/>
+ <menu_item_call label="Copier l&apos;UUID" name="copy_uuid"/>
+ <menu_item_call label="Enregistrer dans la tenue actuelle" name="save_to_outfit"/>
+ <menu_item_call label="Éditer" name="edit_gesture"/>
+ <menu_item_call label="Inspecter" name="inspect"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_group_plus.xml b/indra/newview/skins/default/xui/fr/menu_group_plus.xml
new file mode 100644
index 0000000000..f5882261b0
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_group_plus.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_call label="Rejoignez des groupes..." name="item_join"/>
+ <menu_item_call label="Nouveau groupe..." name="item_new"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_hide_navbar.xml b/indra/newview/skins/default/xui/fr/menu_hide_navbar.xml
new file mode 100644
index 0000000000..3a7126fe50
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_hide_navbar.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="hide_navbar_menu">
+ <menu_item_check label="Afficher la barre de navigation" name="ShowNavbarNavigationPanel"/>
+ <menu_item_check label="Afficher la barre des Favoris" name="ShowNavbarFavoritesPanel"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_imchiclet_group.xml b/indra/newview/skins/default/xui/fr/menu_imchiclet_group.xml
new file mode 100644
index 0000000000..59f97d8b48
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_imchiclet_group.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="IMChiclet Group Menu">
+ <menu_item_call label="Profil du groupe" name="Show Profile"/>
+ <menu_item_call label="Afficher la session" name="Chat"/>
+ <menu_item_call label="Mettre fin à la session" name="End Session"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_imchiclet_p2p.xml b/indra/newview/skins/default/xui/fr/menu_imchiclet_p2p.xml
new file mode 100644
index 0000000000..b1683ffcd0
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_imchiclet_p2p.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="IMChiclet P2P Menu">
+ <menu_item_call label="Afficher le profil" name="Show Profile"/>
+ <menu_item_call label="Devenir amis" name="Add Friend"/>
+ <menu_item_call label="Afficher la session" name="Send IM"/>
+ <menu_item_call label="Mettre fin à la session" name="End Session"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_inspect_avatar_gear.xml b/indra/newview/skins/default/xui/fr/menu_inspect_avatar_gear.xml
new file mode 100644
index 0000000000..9a4926b678
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_inspect_avatar_gear.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu name="Gear Menu">
+ <menu_item_call label="Voir le profil" name="view_profile"/>
+ <menu_item_call label="Devenir amis" name="add_friend"/>
+ <menu_item_call label="IM" name="im"/>
+ <menu_item_call label="Appeler" name="call"/>
+ <menu_item_call label="Téléporter" name="teleport"/>
+ <menu_item_call label="Inviter dans le groupe" name="invite_to_group"/>
+ <menu_item_call label="Ignorer" name="block"/>
+ <menu_item_call label="Signaler" name="report"/>
+ <menu_item_call label="Geler" name="freeze"/>
+ <menu_item_call label="Expulser" name="eject"/>
+ <menu_item_call label="Débogage" name="debug"/>
+ <menu_item_call label="Situer sur la carte" name="find_on_map"/>
+ <menu_item_call label="Zoomer en avant" name="zoom_in"/>
+ <menu_item_call label="Payer" name="pay"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/fr/menu_inspect_object_gear.xml
new file mode 100644
index 0000000000..0ecce069bd
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_inspect_object_gear.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu name="Gear Menu">
+ <menu_item_call label="Toucher" name="touch"/>
+ <menu_item_call label="M&apos;asseoir" name="sit"/>
+ <menu_item_call label="Payer" name="pay"/>
+ <menu_item_call label="Acheter" name="buy"/>
+ <menu_item_call label="Prendre" name="take"/>
+ <menu_item_call label="Prendre une copie" name="take_copy"/>
+ <menu_item_call label="Ouvrir" name="open"/>
+ <menu_item_call label="Éditer" name="edit"/>
+ <menu_item_call label="Porter" name="wear"/>
+ <menu_item_call label="Signaler" name="report"/>
+ <menu_item_call label="Ignorer" name="block"/>
+ <menu_item_call label="Zoomer en avant" name="zoom_in"/>
+ <menu_item_call label="Supprimer" name="remove"/>
+ <menu_item_call label="En savoir plus" name="more_info"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_inspect_self_gear.xml b/indra/newview/skins/default/xui/fr/menu_inspect_self_gear.xml
new file mode 100644
index 0000000000..d28d36bca7
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_inspect_self_gear.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu name="Gear Menu">
+ <menu_item_call label="Me lever" name="stand_up"/>
+ <menu_item_call label="Mon apparence" name="my_appearance"/>
+ <menu_item_call label="Mon profil" name="my_profile"/>
+ <menu_item_call label="Mes amis" name="my_friends"/>
+ <menu_item_call label="Mes groupes" name="my_groups"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_inventory.xml b/indra/newview/skins/default/xui/fr/menu_inventory.xml
index ce347afe89..d6da4b5557 100644
--- a/indra/newview/skins/default/xui/fr/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/fr/menu_inventory.xml
@@ -12,7 +12,7 @@
<menu_item_call label="Nouveau script" name="New Script"/>
<menu_item_call label="Nouvelle note" name="New Note"/>
<menu_item_call label="Nouveau geste" name="New Gesture"/>
- <menu name="New Clothes">
+ <menu label="Nouveaux habits" name="New Clothes">
<menu_item_call label="Nouvelle chemise" name="New Shirt"/>
<menu_item_call label="Nouveau pantalon" name="New Pants"/>
<menu_item_call label="Nouvelles chaussures" name="New Shoes"/>
@@ -22,31 +22,47 @@
<menu_item_call label="Nouveaux gants" name="New Gloves"/>
<menu_item_call label="Nouveau tricot" name="New Undershirt"/>
<menu_item_call label="Nouveaux sous-vêtements" name="New Underpants"/>
+ <menu_item_call label="Nouveau masque alpha" name="New Alpha Mask"/>
+ <menu_item_call label="Nouveau tatouage" name="New Tattoo"/>
</menu>
- <menu name="New Body Parts">
+ <menu label="Nouvelles parties du corps" name="New Body Parts">
<menu_item_call label="Nouvelle silhouette" name="New Shape"/>
<menu_item_call label="Nouvelle peau" name="New Skin"/>
<menu_item_call label="Nouveaux cheveux" name="New Hair"/>
<menu_item_call label="Nouveaux yeux" name="New Eyes"/>
</menu>
+ <menu label="Changer de type" name="Change Type">
+ <menu_item_call label="Défaut" name="Default"/>
+ <menu_item_call label="Gants" name="Gloves"/>
+ <menu_item_call label="Veste" name="Jacket"/>
+ <menu_item_call label="Pantalon" name="Pants"/>
+ <menu_item_call label="Silhouette" name="Shape"/>
+ <menu_item_call label="Chaussures" name="Shoes"/>
+ <menu_item_call label="Chemise" name="Shirt"/>
+ <menu_item_call label="Jupe" name="Skirt"/>
+ <menu_item_call label="Sous-vêtements (femme)" name="Underpants"/>
+ <menu_item_call label="Sous-vêtements (homme)" name="Undershirt"/>
+ </menu>
<menu_item_call label="Téléporter" name="Landmark Open"/>
<menu_item_call label="Ouvrir" name="Animation Open"/>
<menu_item_call label="Ouvrir" name="Sound Open"/>
<menu_item_call label="Purger l&apos;objet" name="Purge Item"/>
<menu_item_call label="Restaurer l&apos;objet" name="Restore Item"/>
+ <menu_item_call label="Trouver l&apos;original" name="Find Original"/>
<menu_item_call label="Ouvrir" name="Open"/>
<menu_item_call label="Propriétés" name="Properties"/>
<menu_item_call label="Renommer" name="Rename"/>
<menu_item_call label="Copier l&apos;UUID (identifiant universel unique)" name="Copy Asset UUID"/>
<menu_item_call label="Copier" name="Copy"/>
<menu_item_call label="Coller" name="Paste"/>
+ <menu_item_call label="Coller comme lien" name="Paste As Link"/>
<menu_item_call label="Supprimer" name="Delete"/>
- <menu_item_call label="Enlever les objets" name="Take Off Items"/>
+ <menu_item_call label="Enlever de la tenue" name="Remove From Outfit"/>
<menu_item_call label="Ajouter à l&apos;ensemble" name="Add To Outfit"/>
<menu_item_call label="Remplacer l&apos;ensemble" name="Replace Outfit"/>
<menu_item_call label="Démarrer le chat conférence" name="Conference Chat Folder"/>
<menu_item_call label="Jouer" name="Sound Play"/>
- <menu_item_call label="Au sujet du repère" name="Teleport To Landmark"/>
+ <menu_item_call label="À propos du repère" name="About Landmark"/>
<menu_item_call label="Jouer dans le Monde" name="Animation Play"/>
<menu_item_call label="Jouer localement" name="Animation Audition"/>
<menu_item_call label="Envoyer un message instantané" name="Send Instant Message"/>
@@ -54,8 +70,8 @@
<menu_item_call label="Démarrer le chat conférence" name="Conference Chat"/>
<menu_item_call label="Activer" name="Activate"/>
<menu_item_call label="Désactiver" name="Deactivate"/>
+ <menu_item_call label="Enregistrer sous" name="Save As"/>
<menu_item_call label="Détacher de vous" name="Detach From Yourself"/>
- <menu_item_call label="Remettre dans le dernier emplacement" name="Restore to Last Position"/>
<menu_item_call label="Porter" name="Object Wear"/>
<menu label="Attacher à" name="Attach To"/>
<menu label="Attacher au HUD " name="Attach To HUD"/>
diff --git a/indra/newview/skins/default/xui/fr/menu_inventory_add.xml b/indra/newview/skins/default/xui/fr/menu_inventory_add.xml
new file mode 100644
index 0000000000..0e5abdad0a
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_inventory_add.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_inventory_add">
+ <menu label="Importer" name="upload">
+ <menu_item_call label="Image ([COST] L$)..." name="Upload Image"/>
+ <menu_item_call label="Son ([COST] L$)..." name="Upload Sound"/>
+ <menu_item_call label="Animation ([COST] L$)..." name="Upload Animation"/>
+ <menu_item_call label="Lot ([COST] L$ par fichier)..." name="Bulk Upload"/>
+ </menu>
+ <menu_item_call label="Nouveau dossier" name="New Folder"/>
+ <menu_item_call label="Nouveau script" name="New Script"/>
+ <menu_item_call label="Nouvelle note" name="New Note"/>
+ <menu_item_call label="Nouveau geste" name="New Gesture"/>
+ <menu label="Nouveaux habits" name="New Clothes">
+ <menu_item_call label="Nouvelle chemise" name="New Shirt"/>
+ <menu_item_call label="Nouveau pantalon" name="New Pants"/>
+ <menu_item_call label="Nouvelles chaussures" name="New Shoes"/>
+ <menu_item_call label="Nouvelles chaussettes" name="New Socks"/>
+ <menu_item_call label="Nouvelle veste" name="New Jacket"/>
+ <menu_item_call label="Nouvelle jupe" name="New Skirt"/>
+ <menu_item_call label="Nouveaux gants" name="New Gloves"/>
+ <menu_item_call label="Nouveaux sous-vêtements (homme)" name="New Undershirt"/>
+ <menu_item_call label="Nouveaux sous-vêtements (femme)" name="New Underpants"/>
+ <menu_item_call label="Nouvel alpha" name="New Alpha"/>
+ <menu_item_call label="Nouveau tatouage" name="New Tattoo"/>
+ </menu>
+ <menu label="Nouvelles parties du corps" name="New Body Parts">
+ <menu_item_call label="Nouvelle silhouette" name="New Shape"/>
+ <menu_item_call label="Nouvelle peau" name="New Skin"/>
+ <menu_item_call label="Nouveaux cheveux" name="New Hair"/>
+ <menu_item_call label="Nouveaux yeux" name="New Eyes"/>
+ </menu>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_inventory_gear_default.xml b/indra/newview/skins/default/xui/fr/menu_inventory_gear_default.xml
new file mode 100644
index 0000000000..5fe7a215a4
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_inventory_gear_default.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_gear_default">
+ <menu_item_call label="Nouvelle fenêtre d&apos;inventaire" name="new_window"/>
+ <menu_item_call label="Trier par nom" name="sort_by_name"/>
+ <menu_item_call label="Trier en commençant par le plus récent" name="sort_by_recent"/>
+ <menu_item_call label="Afficher les filtres" name="show_filters"/>
+ <menu_item_call label="Réinitialiser les filtres" name="reset_filters"/>
+ <menu_item_call label="Fermer tous les dossiers" name="close_folders"/>
+ <menu_item_call label="Vider la corbeille" name="empty_trash"/>
+ <menu_item_call label="Vider les Objets trouvés" name="empty_lostnfound"/>
+ <menu_item_call label="Enregistrer la texture sous" name="Save Texture As"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_landmark.xml b/indra/newview/skins/default/xui/fr/menu_landmark.xml
new file mode 100644
index 0000000000..2e0cafa227
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_landmark.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="landmark_overflow_menu">
+ <menu_item_call label="Copier la SLurl" name="copy"/>
+ <menu_item_call label="Supprimer" name="delete"/>
+ <menu_item_call label="Créer une préférence" name="pick"/>
+ <menu_item_call label="Ajouter à la barre des Favoris" name="add_to_favbar"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_login.xml b/indra/newview/skins/default/xui/fr/menu_login.xml
index b3169714c3..ac262a75e6 100644
--- a/indra/newview/skins/default/xui/fr/menu_login.xml
+++ b/indra/newview/skins/default/xui/fr/menu_login.xml
@@ -1,13 +1,34 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<menu_bar name="Login Menu">
- <menu label="Fichier" name="File">
- <menu_item_call label="Quitter" name="Quit" />
- </menu>
- <menu label="Édition" name="Edit">
- <menu_item_call label="Préférences..." name="Preferences..." />
+ <menu label="Moi" name="File">
+ <menu_item_call label="Préférences" name="Preferences..."/>
+ <menu_item_call label="Quitter [APP_NAME]" name="Quit"/>
</menu>
<menu label="Aide" name="Help">
- <menu_item_call label="Aide de Second Life" name="Second Life Help" />
- <menu_item_call label="À propos de Second Life..." name="About Second Life..." />
+ <menu_item_call label="Aide de [SECOND_LIFE]" name="Second Life Help"/>
+ <menu_item_call label="À propos de [APP_NAME]" name="About Second Life"/>
+ </menu>
+ <menu label="Débogage" name="Debug">
+ <menu label="Éditer" name="Edit">
+ <menu_item_call label="Annuler" name="Undo"/>
+ <menu_item_call label="Refaire" name="Redo"/>
+ <menu_item_call label="Couper" name="Cut"/>
+ <menu_item_call label="Copier" name="Copy"/>
+ <menu_item_call label="Coller" name="Paste"/>
+ <menu_item_call label="Supprimer" name="Delete"/>
+ <menu_item_call label="Dupliquer" name="Duplicate"/>
+ <menu_item_call label="Tout sélectionner" name="Select All"/>
+ <menu_item_call label="Désélectionner" name="Deselect"/>
+ </menu>
+ <menu_item_call label="Afficher les paramètres de débogage" name="Debug Settings"/>
+ <menu_item_call label="Paramètres de couleurs/interface" name="UI/Color Settings"/>
+ <menu_item_call label="Outil d&apos;aperçu XUI" name="UI Preview Tool"/>
+ <menu_item_call label="Afficher la barre latérale" name="Show Side Tray"/>
+ <menu_item_call label="Test widget" name="Widget Test"/>
+ <menu_item_call label="Tests inspecteurs" name="Inspectors Test"/>
+ <menu_item_check label="Reg In Client Test (restart)" name="Reg In Client Test (restart)"/>
+ <menu_item_call label="Afficher les conditions d&apos;utilisation" name="TOS"/>
+ <menu_item_call label="Afficher le message critique" name="Critical"/>
+ <menu_item_call label="Test du navigateur Web" name="Web Browser Test"/>
</menu>
</menu_bar>
diff --git a/indra/newview/skins/default/xui/fr/menu_mini_map.xml b/indra/newview/skins/default/xui/fr/menu_mini_map.xml
index 36107885f4..a9facb2c30 100644
--- a/indra/newview/skins/default/xui/fr/menu_mini_map.xml
+++ b/indra/newview/skins/default/xui/fr/menu_mini_map.xml
@@ -3,6 +3,7 @@
<menu_item_call label="Zoom rapproché" name="Zoom Close"/>
<menu_item_call label="Zoom moyen" name="Zoom Medium"/>
<menu_item_call label="Zoom éloigné" name="Zoom Far"/>
+ <menu_item_check label="Faire pivoter la carte" name="Rotate Map"/>
<menu_item_call label="Arrêter de suivre" name="Stop Tracking"/>
- <menu_item_call label="Profil..." name="Profile"/>
+ <menu_item_call label="Carte du monde" name="World Map"/>
</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_navbar.xml b/indra/newview/skins/default/xui/fr/menu_navbar.xml
new file mode 100644
index 0000000000..08d810b653
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_navbar.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Navbar Menu">
+ <menu_item_check label="Voir les coordonnées" name="Show Coordinates"/>
+ <menu_item_check label="Afficher les propriétés de la parcelle" name="Show Parcel Properties"/>
+ <menu_item_call label="Repère" name="Landmark"/>
+ <menu_item_call label="Couper" name="Cut"/>
+ <menu_item_call label="Copier" name="Copy"/>
+ <menu_item_call label="Coller" name="Paste"/>
+ <menu_item_call label="Supprimer" name="Delete"/>
+ <menu_item_call label="Tout sélectionner" name="Select All"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_nearby_chat.xml b/indra/newview/skins/default/xui/fr/menu_nearby_chat.xml
new file mode 100644
index 0000000000..99e22aeff7
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_nearby_chat.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="NearBy Chat Menu">
+ <menu_item_call label="Afficher les personnes près de vous..." name="nearby_people"/>
+ <menu_item_check label="Afficher le texte ignoré" name="muted_text"/>
+ <menu_item_check label="Afficher les icônes des Buddy" name="show_buddy_icons"/>
+ <menu_item_check label="Afficher les noms" name="show_names"/>
+ <menu_item_check label="Afficher les icônes et les noms" name="show_icons_and_names"/>
+ <menu_item_call label="Taille de la police" name="font_size"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_object_icon.xml b/indra/newview/skins/default/xui/fr/menu_object_icon.xml
new file mode 100644
index 0000000000..69f8e88a0d
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_object_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Object Icon Menu">
+ <menu_item_call label="Profil de l&apos;objet..." name="Object Profile"/>
+ <menu_item_call label="Ignorer..." name="Block"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_participant_list.xml b/indra/newview/skins/default/xui/fr/menu_participant_list.xml
new file mode 100644
index 0000000000..96d9a003cd
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_participant_list.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Participant List Context Menu">
+ <menu_item_check label="Ignorer le texte" name="MuteText"/>
+ <menu_item_check label="Autoriser les chats écrits" name="AllowTextChat"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_people_friends_view_sort.xml b/indra/newview/skins/default/xui/fr/menu_people_friends_view_sort.xml
new file mode 100644
index 0000000000..5adf8714cf
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_people_friends_view_sort.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Trier par nom" name="sort_name"/>
+ <menu_item_check label="Trier par statut" name="sort_status"/>
+ <menu_item_check label="Afficher les icônes des résidents" name="view_icons"/>
+ <menu_item_call label="Afficher les résidents et les objets ignorés" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_people_groups_view_sort.xml b/indra/newview/skins/default/xui/fr/menu_people_groups_view_sort.xml
new file mode 100644
index 0000000000..34f949cf2c
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_people_groups_view_sort.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Afficher les icônes des groupes" name="Display Group Icons"/>
+ <menu_item_call label="Quitter le groupe sélectionné" name="Leave Selected Group"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_people_nearby.xml b/indra/newview/skins/default/xui/fr/menu_people_nearby.xml
new file mode 100644
index 0000000000..946063dda2
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_people_nearby.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Avatar Context Menu">
+ <menu_item_call label="Voir le profil" name="View Profile"/>
+ <menu_item_call label="Devenir amis" name="Add Friend"/>
+ <menu_item_call label="IM" name="IM"/>
+ <menu_item_call label="Appeler" name="Call"/>
+ <menu_item_call label="Partager" name="Share"/>
+ <menu_item_call label="Payer" name="Pay"/>
+ <menu_item_check label="Ignorer/Ne plus ignorer" name="Block/Unblock"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_people_nearby_multiselect.xml b/indra/newview/skins/default/xui/fr/menu_people_nearby_multiselect.xml
new file mode 100644
index 0000000000..2185ac95e9
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_people_nearby_multiselect.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Multi-Selected People Context Menu">
+ <menu_item_call label="Devenir amis" name="Add Friends"/>
+ <menu_item_call label="IM" name="IM"/>
+ <menu_item_call label="Appeler" name="Call"/>
+ <menu_item_call label="Partager" name="Share"/>
+ <menu_item_call label="Payer" name="Pay"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_people_nearby_view_sort.xml b/indra/newview/skins/default/xui/fr/menu_people_nearby_view_sort.xml
new file mode 100644
index 0000000000..45f97e062e
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_people_nearby_view_sort.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Trier par intervenants récents" name="sort_by_recent_speakers"/>
+ <menu_item_check label="Trier par nom" name="sort_name"/>
+ <menu_item_check label="Trier par distance" name="sort_distance"/>
+ <menu_item_check label="Afficher les icônes des résidents" name="view_icons"/>
+ <menu_item_call label="Afficher les résidents et les objets interdits" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_people_recent_view_sort.xml b/indra/newview/skins/default/xui/fr/menu_people_recent_view_sort.xml
new file mode 100644
index 0000000000..93b90ae61c
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_people_recent_view_sort.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Trier en commençant par le plus récent" name="sort_most"/>
+ <menu_item_check label="Trier par nom" name="sort_name"/>
+ <menu_item_check label="Afficher les icônes des résidents" name="view_icons"/>
+ <menu_item_call label="Afficher les résidents et les objets ignorés" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_picks.xml b/indra/newview/skins/default/xui/fr/menu_picks.xml
new file mode 100644
index 0000000000..adb1cec8f5
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_picks.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Picks">
+ <menu_item_call label="Infos" name="pick_info"/>
+ <menu_item_call label="Éditer" name="pick_edit"/>
+ <menu_item_call label="Téléporter" name="pick_teleport"/>
+ <menu_item_call label="Carte" name="pick_map"/>
+ <menu_item_call label="Supprimer" name="pick_delete"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_picks_plus.xml b/indra/newview/skins/default/xui/fr/menu_picks_plus.xml
new file mode 100644
index 0000000000..a3b4fb4f55
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_picks_plus.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="picks_plus_menu">
+ <menu_item_call label="Nouveau Favori" name="create_pick"/>
+ <menu_item_call label="Nouvelle petite annonce" name="create_classified"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_place.xml b/indra/newview/skins/default/xui/fr/menu_place.xml
new file mode 100644
index 0000000000..beaf37011f
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_place.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="place_overflow_menu">
+ <menu_item_call label="Enregistrer comme repère" name="landmark"/>
+ <menu_item_call label="Créer une préférence" name="pick"/>
+ <menu_item_call label="Acheter un pass" name="pass"/>
+ <menu_item_call label="Éditer" name="edit"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_place_add_button.xml b/indra/newview/skins/default/xui/fr/menu_place_add_button.xml
new file mode 100644
index 0000000000..92f9e7719d
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_place_add_button.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_folder_gear">
+ <menu_item_call label="Ajouter un dossier" name="add_folder"/>
+ <menu_item_call label="Ajouter un repère" name="add_landmark"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_places_gear_folder.xml b/indra/newview/skins/default/xui/fr/menu_places_gear_folder.xml
new file mode 100644
index 0000000000..3570bdec7f
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_places_gear_folder.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_folder_gear">
+ <menu_item_call label="Ajouter un repère" name="add_landmark"/>
+ <menu_item_call label="Ajouter un dossier" name="add_folder"/>
+ <menu_item_call label="Couper" name="cut"/>
+ <menu_item_call label="Copier" name="copy_folder"/>
+ <menu_item_call label="Coller" name="paste"/>
+ <menu_item_call label="Renommer" name="rename"/>
+ <menu_item_call label="Supprimer" name="delete"/>
+ <menu_item_call label="Agrandir" name="expand"/>
+ <menu_item_call label="Réduire" name="collapse"/>
+ <menu_item_call label="Développer tous les dossiers" name="expand_all"/>
+ <menu_item_call label="Réduire tous les dossiers" name="collapse_all"/>
+ <menu_item_check label="Trier par date" name="sort_by_date"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_places_gear_landmark.xml b/indra/newview/skins/default/xui/fr/menu_places_gear_landmark.xml
new file mode 100644
index 0000000000..2ad007c142
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_places_gear_landmark.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_ladmark_gear">
+ <menu_item_call label="Téléporter" name="teleport"/>
+ <menu_item_call label="Plus d&apos;informations" name="more_info"/>
+ <menu_item_call label="Voir sur la carte" name="show_on_map"/>
+ <menu_item_call label="Ajouter un repère" name="add_landmark"/>
+ <menu_item_call label="Ajouter un dossier" name="add_folder"/>
+ <menu_item_call label="Couper" name="cut"/>
+ <menu_item_call label="Copier le repère" name="copy_landmark"/>
+ <menu_item_call label="Copier la SLurl" name="copy_slurl"/>
+ <menu_item_call label="Coller" name="paste"/>
+ <menu_item_call label="Renommer" name="rename"/>
+ <menu_item_call label="Supprimer" name="delete"/>
+ <menu_item_call label="Développer tous les dossiers" name="expand_all"/>
+ <menu_item_call label="Réduire tous les dossiers" name="collapse_all"/>
+ <menu_item_check label="Trier par date" name="sort_by_date"/>
+ <menu_item_call label="Créer une préférence" name="create_pick"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_profile_overflow.xml b/indra/newview/skins/default/xui/fr/menu_profile_overflow.xml
new file mode 100644
index 0000000000..61a346c6af
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_profile_overflow.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="profile_overflow_menu">
+ <menu_item_call label="Payer" name="pay"/>
+ <menu_item_call label="Partager" name="share"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_slurl.xml b/indra/newview/skins/default/xui/fr/menu_slurl.xml
index ebd042a38a..ddfa5c0849 100644
--- a/indra/newview/skins/default/xui/fr/menu_slurl.xml
+++ b/indra/newview/skins/default/xui/fr/menu_slurl.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<menu name="Popup">
- <menu_item_call label="À propos de l&apos;URL" name="about_url" />
- <menu_item_call label="Téléporter vers l&apos;URL" name="teleport_to_url" />
- <menu_item_call label="Voir sur la carte" name="show_on_map" />
+ <menu_item_call label="À propos de l&apos;URL" name="about_url"/>
+ <menu_item_call label="Téléporter vers l&apos;URL" name="teleport_to_url"/>
+ <menu_item_call label="Carte" name="show_on_map"/>
</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_teleport_history_gear.xml b/indra/newview/skins/default/xui/fr/menu_teleport_history_gear.xml
new file mode 100644
index 0000000000..3dea662cc2
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_teleport_history_gear.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Teleport History Gear Context Menu">
+ <menu_item_call label="Développer tous les dossiers" name="Expand all folders"/>
+ <menu_item_call label="Réduire tous les dossiers" name="Collapse all folders"/>
+ <menu_item_call label="Effacer l&apos;historique des téléportations" name="Clear Teleport History"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/fr/menu_teleport_history_item.xml
new file mode 100644
index 0000000000..fb4582dbce
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_teleport_history_item.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Teleport History Item Context Menu">
+ <menu_item_call label="Téléporter" name="Teleport"/>
+ <menu_item_call label="Plus d&apos;informations" name="More Information"/>
+ <menu_item_call label="Copier dans le presse-papiers" name="CopyToClipboard"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_teleport_history_tab.xml b/indra/newview/skins/default/xui/fr/menu_teleport_history_tab.xml
new file mode 100644
index 0000000000..369680985d
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_teleport_history_tab.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Teleport History Item Context Menu">
+ <menu_item_call label="Ouvrir" name="TabOpen"/>
+ <menu_item_call label="Fermer" name="TabClose"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_text_editor.xml b/indra/newview/skins/default/xui/fr/menu_text_editor.xml
new file mode 100644
index 0000000000..b6f429aec9
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_text_editor.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Text editor context menu">
+ <menu_item_call label="Couper" name="Cut"/>
+ <menu_item_call label="Copier" name="Copy"/>
+ <menu_item_call label="Coller" name="Paste"/>
+ <menu_item_call label="Supprimer" name="Delete"/>
+ <menu_item_call label="Tout sélectionner" name="Select All"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_url_agent.xml b/indra/newview/skins/default/xui/fr/menu_url_agent.xml
new file mode 100644
index 0000000000..5ed627fbc3
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_url_agent.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Voir le profil du résident" name="show_agent"/>
+ <menu_item_call label="Copier le nom dans le presse-papiers" name="url_copy_label"/>
+ <menu_item_call label="Copier la SLurl dans le presse-papiers" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_url_group.xml b/indra/newview/skins/default/xui/fr/menu_url_group.xml
new file mode 100644
index 0000000000..de90c3ff7e
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_url_group.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Voir le profil du groupe" name="show_group"/>
+ <menu_item_call label="Copier le groupe dans le presse-papiers" name="url_copy_label"/>
+ <menu_item_call label="Copier la SLurl dans le presse-papiers" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_url_http.xml b/indra/newview/skins/default/xui/fr/menu_url_http.xml
new file mode 100644
index 0000000000..5e96352999
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_url_http.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Ouvrir la page Web" name="url_open"/>
+ <menu_item_call label="Ouvrir dans un navigateur interne" name="url_open_internal"/>
+ <menu_item_call label="Ouvrir dans un navigateur externe" name="url_open_external"/>
+ <menu_item_call label="Copier l&apos;URL dans le presse-papiers" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_url_inventory.xml b/indra/newview/skins/default/xui/fr/menu_url_inventory.xml
new file mode 100644
index 0000000000..8ab88b4be7
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_url_inventory.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Afficher l&apos;article d&apos;inventaire" name="show_item"/>
+ <menu_item_call label="Copier le nom dans le presse-papiers" name="url_copy_label"/>
+ <menu_item_call label="Copier la SLurl dans le presse-papiers" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_url_map.xml b/indra/newview/skins/default/xui/fr/menu_url_map.xml
new file mode 100644
index 0000000000..67e6986f5d
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_url_map.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Voir sur la carte" name="show_on_map"/>
+ <menu_item_call label="Me téléporter à cet endroit" name="teleport_to_location"/>
+ <menu_item_call label="Copier la SLurl dans le presse-papiers" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_url_objectim.xml b/indra/newview/skins/default/xui/fr/menu_url_objectim.xml
new file mode 100644
index 0000000000..f581c3ef9d
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_url_objectim.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Afficher les informations sur l&apos;objet" name="show_object"/>
+ <menu_item_call label="Voir sur la carte" name="show_on_map"/>
+ <menu_item_call label="Me téléporter à l&apos;emplacement de l&apos;objet" name="teleport_to_object"/>
+ <menu_item_call label="Copier le nom de l&apos;objet dans le presse-papiers" name="url_copy_label"/>
+ <menu_item_call label="Copier la SLurl dans le presse-papiers" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_url_parcel.xml b/indra/newview/skins/default/xui/fr/menu_url_parcel.xml
new file mode 100644
index 0000000000..07b0eeca49
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_url_parcel.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Afficher les informations sur la parcelle" name="show_parcel"/>
+ <menu_item_call label="Voir sur la carte" name="show_on_map"/>
+ <menu_item_call label="Copier la SLurl dans le presse-papiers" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_url_slapp.xml b/indra/newview/skins/default/xui/fr/menu_url_slapp.xml
new file mode 100644
index 0000000000..f4b7e212ca
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_url_slapp.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Exécuter cette commande" name="run_slapp"/>
+ <menu_item_call label="Copier la SLurl dans le presse-papiers" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_url_slurl.xml b/indra/newview/skins/default/xui/fr/menu_url_slurl.xml
new file mode 100644
index 0000000000..e44943cf15
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_url_slurl.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Afficher les informations sur ce lieu" name="show_place"/>
+ <menu_item_call label="Voir sur la carte" name="show_on_map"/>
+ <menu_item_call label="Me téléporter à cet endroit" name="teleport_to_location"/>
+ <menu_item_call label="Copier la SLurl dans le presse-papiers" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_url_teleport.xml b/indra/newview/skins/default/xui/fr/menu_url_teleport.xml
new file mode 100644
index 0000000000..a5075a2740
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_url_teleport.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Me téléporter à cet endroit." name="teleport"/>
+ <menu_item_call label="Voir sur la carte" name="show_on_map"/>
+ <menu_item_call label="Copier la SLurl dans le presse-papiers" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_viewer.xml b/indra/newview/skins/default/xui/fr/menu_viewer.xml
index 959cc5764c..9639e8415d 100644
--- a/indra/newview/skins/default/xui/fr/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/fr/menu_viewer.xml
@@ -1,217 +1,426 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<menu_bar name="Main Menu">
- <menu label="Fichier" name="File">
- <tearoff_menu label="~~~~~~~~~~~" name="~~~~~~~~~~~"/>
- <menu label="Importer" name="upload">
- <menu_item_call label="Image ([COST] L$)..." name="Upload Image"/>
- <menu_item_call label="Son ([COST] L$)..." name="Upload Sound"/>
- <menu_item_call label="Animation ([COST] L$)..." name="Upload Animation"/>
- <menu_item_call label="Lot ([COST] L$ par fichier)..." name="Bulk Upload"/>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_call label="Définir les droits par défaut..." name="perm prefs"/>
- </menu>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_call label="Fermer la fenêtre" name="Close Window"/>
- <menu_item_call label="Fermer toutes les fenêtres" name="Close All Windows"/>
- <menu_item_separator label="-----------" name="separator2"/>
- <menu_item_call label="Enregistrer la texture sous..." name="Save Texture As..."/>
- <menu_item_separator label="-----------" name="separator3"/>
- <menu_item_call label="Prendre une photo" name="Take Snapshot"/>
- <menu_item_call label="Enregistrer la photo sur le disque" name="Snapshot to Disk" shortcut="control|shift|X"/>
- <menu_item_separator label="-----------" name="separator4"/>
- <menu_item_call label="Quitter" name="Quit"/>
- </menu>
- <menu label="Édition" name="Edit">
- <menu_item_call label="Annuler" name="Undo"/>
- <menu_item_call label="Recommencer" name="Redo"/>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_call label="Couper" name="Cut"/>
- <menu_item_call label="Copier" name="Copy"/>
- <menu_item_call label="Coller" name="Paste"/>
- <menu_item_call label="Supprimer" name="Delete"/>
- <menu_item_separator label="-----------" name="separator2"/>
- <menu_item_call label="Rechercher..." name="Search..."/>
- <menu_item_separator label="-----------" name="separator3"/>
- <menu_item_call label="Tout sélectionner" name="Select All"/>
- <menu_item_call label="Désélectionner" name="Deselect"/>
- <menu_item_separator label="-----------" name="separator4"/>
- <menu_item_call label="Dupliquer" name="Duplicate"/>
- <menu_item_separator label="-----------" name="separator5"/>
- <menu label="Attacher l&apos;objet" name="Attach Object"/>
- <menu label="Détacher l&apos;objet" name="Detach Object"/>
- <menu label="Enlever mes habits" name="Take Off Clothing">
- <menu_item_call label="Chemise" name="Shirt"/>
- <menu_item_call label="Pantalon" name="Pants"/>
- <menu_item_call label="Chaussures" name="Shoes"/>
- <menu_item_call label="Chaussettes" name="Socks"/>
- <menu_item_call label="Veste" name="Jacket"/>
- <menu_item_call label="Gants" name="Gloves"/>
- <menu_item_call label="Tricot" name="Menu Undershirt"/>
- <menu_item_call label="Sous-vêtements" name="Menu Underpants"/>
- <menu_item_call label="Jupe" name="Skirt"/>
- <menu_item_call label="Tous les habits" name="All Clothes"/>
+ <menu label="Moi" name="Me">
+ <menu_item_call label="Préférences" name="Preferences"/>
+ <menu_item_call label="Ma Page d&apos;accueil" name="Manage My Account">
+ <menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=fr"/>
+ </menu_item_call>
+ <menu_item_call label="Acheter des L$" name="Buy and Sell L$"/>
+ <menu_item_call label="Mon profil" name="Profile"/>
+ <menu_item_call label="Mon apparence" name="Appearance"/>
+ <menu_item_check label="Mon inventaire" name="Inventory"/>
+ <menu_item_call label="Afficher l&apos;inventaire de la barre latérale" name="ShowSidetrayInventory"/>
+ <menu_item_call label="Mes gestes" name="Gestures"/>
+ <menu label="Mon statut" name="Status">
+ <menu_item_call label="Absent" name="Set Away"/>
+ <menu_item_call label="Occupé" name="Set Busy"/>
</menu>
- <menu_item_separator label="-----------" name="separator6"/>
- <menu_item_call label="Gestes..." name="Gestures..."/>
- <menu_item_call label="Profil..." name="Profile..."/>
- <menu_item_call label="Apparence..." name="Appearance..."/>
- <menu_item_separator label="-----------" name="separator7"/>
- <menu_item_check label="Amis..." name="Friends..."/>
- <menu_item_call label="Groupes..." name="Groups..."/>
- <menu_item_separator label="-----------" name="separator8"/>
- <menu_item_call label="Préférences..." name="Preferences..."/>
+ <menu_item_call label="Demander le statut Admin" name="Request Admin Options"/>
+ <menu_item_call label="Quitter le statut Admin" name="Leave Admin Options"/>
+ <menu_item_call label="Quitter [APP_NAME]" name="Quit"/>
</menu>
- <menu label="Affichage" name="View">
- <tearoff_menu label="~~~~~~~~~~~" name="~~~~~~~~~~~"/>
- <menu_item_call label="Vue subjective" name="Mouselook"/>
- <menu_item_check label="Construire" name="Build"/>
- <menu_item_check label="Vue au joystick" name="Joystick Flycam"/>
- <menu_item_call label="Réinitialiser l&apos;affichage" name="Reset View"/>
- <menu_item_call label="Regarder le dernier intervenant" name="Look at Last Chatter" shortcut="alt|V"/>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_check label="Barre d&apos;outils" name="Toolbar"/>
- <menu_item_check label="Chat local" name="Chat History"/>
- <menu_item_check label="Communiquer" name="Instant Message"/>
- <menu_item_check label="Inventaire" name="Inventory"/>
- <menu_item_check label="Intervenants actifs" name="Active Speakers"/>
- <menu_item_check label="Liste des ignorés" name="Mute List"/>
- <menu_item_separator label="-----------" name="separator2"/>
- <menu_item_check label="Contrôles de la caméra" name="Camera Controls"/>
- <menu_item_check label="Contrôle des déplacements" name="Movement Controls"/>
- <menu_item_check label="Carte du monde" name="World Map"/>
- <menu_item_check label="Mini-carte" name="Mini-Map"/>
- <menu_item_separator label="-----------" name="separator3"/>
- <menu_item_check label="Statistiques" name="Statistics Bar"/>
- <menu_item_check label="Limites des parcelles" name="Property Lines"/>
- <menu_item_check label="Barrières d&apos;interdiction d&apos;accès" name="Banlines"/>
- <menu_item_check label="Propriétaires fonciers" name="Land Owners"/>
- <menu_item_separator label="-----------" name="separator4"/>
- <menu label="Infobulles" name="Hover Tips">
- <menu_item_check label="Affichez les infobulles" name="Show Tips"/>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_check label="Infobulles des terrains" name="Land Tips"/>
- <menu_item_check label="Infobulles de tous les objets" name="Tips On All Objects"/>
- </menu>
- <menu_item_check label="Voir les objets invisibles" name="Highlight Transparent"/>
- <menu_item_check label="Balises" name="beacons"/>
- <menu_item_check label="Masquer les particules" name="Hide Particles"/>
- <menu_item_check label="Afficher les éléments HUD" name="Show HUD Attachments"/>
- <menu_item_separator label="-----------" name="separator5"/>
- <menu_item_call label="Zoomer" name="Zoom In"/>
- <menu_item_call label="Zoom par défaut" name="Zoom Default"/>
- <menu_item_call label="Zoomer en arrière" name="Zoom Out"/>
- <menu_item_separator label="-----------" name="separator6"/>
- <menu_item_call label="Activer/Quitter le plein écran" name="Toggle Fullscreen"/>
- <menu_item_call label="Taille de l&apos;interface par défaut" name="Set UI Size to Default"/>
+ <menu label="Communiquer" name="Communicate">
+ <menu_item_call label="Mes amis" name="My Friends"/>
+ <menu_item_call label="Mes groupes" name="My Groups"/>
+ <menu_item_check label="Chat près de vous" name="Nearby Chat"/>
+ <menu_item_call label="Personnes près de vous" name="Active Speakers"/>
+ <menu_item_check label="Média près de vous" name="Nearby Media"/>
+ <menu_item_check label="(Ancienne version) Communiquer" name="Instant Message"/>
+ <menu_item_call label="(Temp) Télécommande média" name="Preferences"/>
</menu>
<menu label="Monde" name="World">
- <menu_item_call label="Chat" name="Chat"/>
- <menu_item_check label="Toujours courir" name="Always Run"/>
- <menu_item_check label="Voler" name="Fly" shortcut="F"/>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_call label="Créer un repère ici" name="Create Landmark Here"/>
- <menu_item_call label="Définir comme domicile" name="Set Home to Here"/>
- <menu_item_separator label="-----------" name="separator2"/>
- <menu_item_call label="Me téléporter chez moi" name="Teleport Home"/>
- <menu_item_separator label="-----------" name="separator3"/>
- <menu_item_call label="Me mettre absent(e)" name="Set Away"/>
- <menu_item_call label="Me mettre occupé(e)" name="Set Busy"/>
- <menu_item_call label="Arrêter d&apos;animer mon avatar" name="Stop Animating My Avatar"/>
- <menu_item_call label="Reprendre le contrôle" name="Release Keys"/>
- <menu_item_separator label="-----------" name="separator4"/>
- <menu_item_call label="Historique de mon compte..." name="Account History...">
- <on_click name="AccountHistory_url" userdata="WebLaunchAccountHistory,http://secondlife.com/account/transactions.php?lang=fr"/>
- </menu_item_call>
- <menu_item_call label="Gérer mon compte..." name="Manage My Account...">
- <on_click name="ManageMyAccount_url" userdata="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=fr"/>
- </menu_item_call>
- <menu_item_call label="Acheter des L$..." name="Buy and Sell L$..."/>
- <menu_item_separator label="-----------" name="separator5"/>
- <menu_item_call label="Mes terrains..." name="My Land..."/>
- <menu_item_call label="À propos du terrain..." name="About Land..."/>
- <menu_item_call label="Acheter le terrain..." name="Buy Land..."/>
- <menu_item_call label="Région et domaine..." name="Region/Estate..."/>
- <menu_item_separator label="-----------" name="separator6"/>
- <menu label="Environnement" name="Environment Settings">
+ <menu_item_check label="Bouger" name="Movement Controls"/>
+ <menu_item_check label="Affichage" name="Camera Controls"/>
+ <menu_item_call label="À propos des terrains" name="About Land"/>
+ <menu_item_call label="Région/Domaine" name="Region/Estate"/>
+ <menu_item_call label="Acheter du terrain" name="Buy Land"/>
+ <menu_item_call label="Mes terrains" name="My Land"/>
+ <menu label="Afficher" name="Land">
+ <menu_item_check label="Lignes d&apos;interdiction" name="Ban Lines"/>
+ <menu_item_check label="Balises" name="beacons"/>
+ <menu_item_check label="Limites du terrain" name="Property Lines"/>
+ <menu_item_check label="Propriétaires de terrains" name="Land Owners"/>
+ </menu>
+ <menu label="Repères" name="Landmarks">
+ <menu_item_call label="Créer un repère ici" name="Create Landmark Here"/>
+ <menu_item_call label="Définir le domicile ici" name="Set Home to Here"/>
+ </menu>
+ <menu_item_call label="Domicile" name="Teleport Home"/>
+ <menu_item_check label="Mini-carte" name="Mini-Map"/>
+ <menu_item_check label="Carte du monde" name="World Map"/>
+ <menu_item_call label="Photo" name="Take Snapshot"/>
+ <menu label="Luminosité" name="Environment Settings">
<menu_item_call label="Aube" name="Sunrise"/>
<menu_item_call label="Milieu de journée" name="Noon"/>
<menu_item_call label="Coucher de soleil" name="Sunset"/>
<menu_item_call label="Minuit" name="Midnight"/>
- <menu_item_call label="Revenir aux options par défaut" name="Revert to Region Default"/>
- <menu_item_separator label="-----------" name="separator"/>
+ <menu_item_call label="Utiliser l&apos;heure du domaine" name="Revert to Region Default"/>
<menu_item_call label="Éditeur d&apos;environnement" name="Environment Editor"/>
</menu>
</menu>
- <menu label="Outils" name="Tools">
- <menu label="Sélectionner un outil" name="Select Tool">
- <menu_item_call label="Mise au point" name="Focus"/>
- <menu_item_call label="Déplacer" name="Move"/>
- <menu_item_call label="Éditer" name="Edit"/>
- <menu_item_call label="Créer" name="Create"/>
- <menu_item_call label="Terrain" name="Land"/>
- </menu>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_check label="Sélectionner mes objets uniquement" name="Select Only My Objects"/>
- <menu_item_check label="Sélectionner les objets déplaçables uniquement" name="Select Only Movable Objects"/>
- <menu_item_check label="Sélectionner en entourant" name="Select By Surrounding"/>
- <menu_item_check label="Afficher les parties cachées de la sélection" name="Show Hidden Selection"/>
- <menu_item_check label="Afficher la sphère de lumière de la sélection" name="Show Light Radius for Selection"/>
- <menu_item_check label="Afficher le faisceau de sélection" name="Show Selection Beam"/>
- <menu_item_separator label="-----------" name="separator2"/>
- <menu_item_check label="Aligner sur la grille" name="Snap to Grid"/>
- <menu_item_call label="Aligner sur les axes XY de la grille" name="Snap Object XY to Grid"/>
- <menu_item_call label="Utiliser la sélection pour la grille" name="Use Selection for Grid"/>
- <menu_item_call label="Options de la grille..." name="Grid Options..."/>
- <menu_item_separator label="-----------" name="separator3"/>
- <menu_item_check label="Modifier les parties liées" name="Edit Linked Parts"/>
- <menu_item_call label="Lier" name="Link"/>
- <menu_item_call label="Délier" name="Unlink"/>
- <menu_item_separator label="-----------" name="separator4"/>
- <menu_item_call label="Mise au point sur la sélection" name="Focus on Selection"/>
- <menu_item_call label="Zoom sur la sélection" name="Zoom to Selection"/>
- <menu_item_call label="Acheter l&apos;objet" name="Menu Object Take"/>
- <menu_item_call label="Prendre une copie" name="Take Copy"/>
- <menu_item_call label="Remplacer l&apos;objet dans le contenu de l&apos;objet" name="Save Object Back to Object Contents"/>
- <menu_item_separator label="-----------" name="separator6"/>
- <menu_item_call label="Afficher la fenêtre d&apos;alertes/erreurs de script" name="Show Script Warning/Error Window"/>
- <menu label="Recompiler les scripts dans la sélection" name="Recompile Scripts in Selection">
- <menu_item_call label="Mono" name="Mono"/>
- <menu_item_call label="LSL" name="LSL"/>
- </menu>
- <menu_item_call label="Réinitialiser les scripts dans la sélection" name="Reset Scripts in Selection"/>
- <menu_item_call label="Activer les scripts dans la sélection" name="Set Scripts to Running in Selection"/>
- <menu_item_call label="Désactiver les scripts dans la sélection" name="Set Scripts to Not Running in Selection"/>
+ <menu label="Construire" name="BuildTools">
+ <menu_item_check label="Construire" name="Show Build Tools"/>
+ <menu label="Sélectionner l&apos;outil de construction" name="Select Tool">
+ <menu_item_call label="Outil de zoom" name="Focus"/>
+ <menu_item_call label="Outil de déplacement" name="Move"/>
+ <menu_item_call label="Outil de modification" name="Edit"/>
+ <menu_item_call label="Outil de création" name="Create"/>
+ <menu_item_call label="Outil Terrain" name="Land"/>
+ </menu>
+ <menu label="Édition" name="Edit">
+ <menu_item_call label="Annuler" name="Undo"/>
+ <menu_item_call label="Refaire" name="Redo"/>
+ <menu_item_call label="Couper" name="Cut"/>
+ <menu_item_call label="Copier" name="Copy"/>
+ <menu_item_call label="Coller" name="Paste"/>
+ <menu_item_call label="Supprimer" name="Delete"/>
+ <menu_item_call label="Dupliquer" name="Duplicate"/>
+ <menu_item_call label="Tout sélectionner" name="Select All"/>
+ <menu_item_call label="Désélectionner" name="Deselect"/>
+ </menu>
+ <menu_item_call label="Lien" name="Link"/>
+ <menu_item_call label="Annuler le lien" name="Unlink"/>
+ <menu_item_call label="Point central sur la sélection" name="Focus on Selection"/>
+ <menu_item_call label="Zoomer sur la sélection" name="Zoom to Selection"/>
+ <menu label="Objet" name="Object">
+ <menu_item_call label="Acheter" name="Menu Object Take"/>
+ <menu_item_call label="Prendre une copie" name="Take Copy"/>
+ <menu_item_call label="Enregistrer dans mon inventaire" name="Save Object Back to My Inventory"/>
+ <menu_item_call label="Enregistrer dans le contenu des objets" name="Save Object Back to Object Contents"/>
+ </menu>
+ <menu label="Scripts" name="Scripts">
+ <menu_item_call label="Recompiler les scripts (Mono)" name="Mono"/>
+ <menu_item_call label="Recompiler les scripts (LSL)" name="LSL"/>
+ <menu_item_call label="Réinitialiser les scripts" name="Reset Scripts"/>
+ <menu_item_call label="Définir les scripts sur Exécution" name="Set Scripts to Running"/>
+ <menu_item_call label="Définir les scripts sur Pas d&apos;exécution" name="Set Scripts to Not Running"/>
+ </menu>
+ <menu label="Options" name="Options">
+ <menu_item_check label="Modifier les parties reliées" name="Edit Linked Parts"/>
+ <menu_item_call label="Définir les droits de chargement par défaut" name="perm prefs"/>
+ <menu_item_check label="Afficher les droits avancés" name="DebugPermissions"/>
+ <menu label="Sélection" name="Selection">
+ <menu_item_check label="Sélectionner mes objets uniquement" name="Select Only My Objects"/>
+ <menu_item_check label="Sélectionner les objets déplaçables uniquement" name="Select Only Movable Objects"/>
+ <menu_item_check label="Sélectionner en entourant" name="Select By Surrounding"/>
+ </menu>
+ <menu label="Afficher" name="Show">
+ <menu_item_check label="Afficher la sélection masquée" name="Show Hidden Selection"/>
+ <menu_item_check label="Afficher le rayon lumineux pour la sélection" name="Show Light Radius for Selection"/>
+ <menu_item_check label="Afficher le faisceau de sélection lumineux" name="Show Selection Beam"/>
+ </menu>
+ <menu label="Grille" name="Grid">
+ <menu_item_check label="Fixer sur la grille" name="Snap to Grid"/>
+ <menu_item_call label="Fixer les coordonnées XY de l&apos;objet sur la grille" name="Snap Object XY to Grid"/>
+ <menu_item_call label="Utiliser la sélection pour la grille" name="Use Selection for Grid"/>
+ <menu_item_call label="Options de la grille" name="Grid Options"/>
+ </menu>
+ </menu>
+ <menu label="Sélectionner les parties reliées" name="Select Linked Parts">
+ <menu_item_call label="Sélectionner la partie suivante" name="Select Next Part"/>
+ <menu_item_call label="Sélectionner la partie précédente" name="Select Previous Part"/>
+ <menu_item_call label="Inclure la partie suivante" name="Include Next Part"/>
+ <menu_item_call label="Inclure la partie précédente" name="Include Previous Part"/>
+ </menu>
</menu>
<menu label="Aide" name="Help">
- <menu_item_call label="Aide de Second Life" name="Second Life Help"/>
+ <menu_item_call label="Aide de [SECOND_LIFE]" name="Second Life Help"/>
<menu_item_call label="Didacticiel" name="Tutorial"/>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_call label="Blog officiel..." name="Official Linden Blog..."/>
- <menu_item_separator label="-----------" name="separator2"/>
- <menu_item_call label="Aide sur le LSL..." name="Scripting Portal...">
- <on_click name="ScriptingPortal_url" userdata="WebLaunchLSLWiki,http://wiki.secondlife.com/wiki/LSL_Portal/fr" />
- </menu_item_call>
- <menu_item_separator label="-----------" name="separator3"/>
- <menu_item_call label="Signaler une infraction..." name="Report Abuse..."/>
- <menu_item_call label="Collisions, coups et bousculades…" name="Bumps, Pushes &amp;amp; Hits..."/>
- <menu_item_call label="Mesure du lag" name="Lag Meter"/>
- <menu_item_separator label="-----------" name="separator7"/>
- <menu label="Signaler des bugs" name="Bug Reporting">
- <menu_item_call label="Ouvrir un JIRA..." name="Public Issue Tracker..."/>
- <menu_item_call label="Comment utiliser JIRA ?" name="Publc Issue Tracker Help...">
- <on_click name="PublicIssueTrackerHelp_url" userdata="WebLaunchPublicIssueHelp,http://wiki.secondlife.com/wiki/Issue_tracker/fr" />
- </menu_item_call>
- <menu_item_separator label="-----------" name="separator7"/>
- <menu_item_call label="Comment signaler des bugs ?" name="Bug Reporing 101...">
- <on_click name="BugReporting101_url" userdata="WebLaunchBugReport101,http://wiki.secondlife.com/wiki/Bug_Reporting_101/fr"/>
- </menu_item_call>
- <menu_item_call label="Comment signaler un problème de sécurité ?" name="Security Issues...">
- <on_click name="SecurityIssues_url" userdata="WebLaunchSecurityIssues,http://wiki.secondlife.com/wiki/Security_issues/fr"/>
- </menu_item_call>
- <menu_item_call label="Wiki Assurance Qualité…" name="QA Wiki..."/>
- <menu_item_separator label="-----------" name="separator9"/>
- <menu_item_call label="Signaler un bug..." name="Report Bug..."/>
- </menu>
- <menu_item_call label="À propos de Second Life..." name="About Second Life..."/>
+ <menu_item_call label="Signaler une infraction" name="Report Abuse"/>
+ <menu_item_call label="À propos de [APP_NAME]" name="About Second Life"/>
+ </menu>
+ <menu label="Avancé" name="Advanced">
+ <menu_item_check label="Me mettre en mode absent après 30 minutes" name="Go Away/AFK When Idle"/>
+ <menu_item_call label="Arrêter mon animation" name="Stop Animating My Avatar"/>
+ <menu_item_call label="Refixer les textures" name="Rebake Texture"/>
+ <menu_item_call label="Taille de l&apos;interface par défaut" name="Set UI Size to Default"/>
+ <menu_item_check label="Limiter la distance de sélection" name="Limit Select Distance"/>
+ <menu_item_check label="Désactiver les contraintes de la caméra" name="Disable Camera Distance"/>
+ <menu_item_check label="Photo haute résolution" name="HighResSnapshot"/>
+ <menu_item_check label="Photos discrètes sur disque" name="QuietSnapshotsToDisk"/>
+ <menu_item_check label="Compresser les photos sur disque" name="CompressSnapshotsToDisk"/>
+ <menu_item_call label="Enregistrer la texture sous" name="Save Texture As"/>
+ <menu label="Outils de performance" name="Performance Tools">
+ <menu_item_call label="Mesure du lag" name="Lag Meter"/>
+ <menu_item_check label="Barre de statistiques" name="Statistics Bar"/>
+ <menu_item_check label="Afficher le coût de rendu de l&apos;avatar" name="Avatar Rendering Cost"/>
+ </menu>
+ <menu label="Surbrillance et visibilité" name="Highlighting and Visibility">
+ <menu_item_check label="Balise animée" name="Cheesy Beacon"/>
+ <menu_item_check label="Cacher les particules" name="Hide Particles"/>
+ <menu_item_check label="Masquer la sélection" name="Hide Selected"/>
+ <menu_item_check label="Mettre la transparence en surbrillance" name="Highlight Transparent"/>
+ <menu_item_check label="Afficher les éléments HUD" name="Show HUD Attachments"/>
+ <menu_item_check label="Afficher le réticule de la vue subjective" name="ShowCrosshairs"/>
+ <menu_item_check label="Afficher les info-bulles de terrain" name="Land Tips"/>
+ </menu>
+ <menu label="Types de rendu" name="Rendering Types">
+ <menu_item_check label="Simple" name="Simple"/>
+ <menu_item_check label="Alpha" name="Alpha"/>
+ <menu_item_check label="Arbre" name="Tree"/>
+ <menu_item_check label="Avatars" name="Character"/>
+ <menu_item_check label="SurfacePath" name="SurfacePath"/>
+ <menu_item_check label="Ciel" name="Sky"/>
+ <menu_item_check label="Eau" name="Water"/>
+ <menu_item_check label="Sol" name="Ground"/>
+ <menu_item_check label="Volume" name="Volume"/>
+ <menu_item_check label="Herbe" name="Grass"/>
+ <menu_item_check label="Nuages" name="Clouds"/>
+ <menu_item_check label="Particules" name="Particles"/>
+ <menu_item_check label="Placage de relief" name="Bump"/>
+ </menu>
+ <menu label="Fonctionnalités de rendu" name="Rendering Features">
+ <menu_item_check label="Interface" name="UI"/>
+ <menu_item_check label="Sélection" name="Selected"/>
+ <menu_item_check label="En surbrillance" name="Highlighted"/>
+ <menu_item_check label="Textures dynamiques" name="Dynamic Textures"/>
+ <menu_item_check label="Ombres des pieds" name="Foot Shadows"/>
+ <menu_item_check label="Brouillard" name="Fog"/>
+ <menu_item_check label="Tester FRInfo" name="Test FRInfo"/>
+ <menu_item_check label="Objets flexibles" name="Flexible Objects"/>
+ </menu>
+ <menu_item_check label="Exécuter plusieurs threads" name="Run Multiple Threads"/>
+ <menu_item_call label="Effacer le cache du groupe" name="ClearGroupCache"/>
+ <menu_item_check label="Effet de lissage de la souris" name="Mouse Smoothing"/>
+ <menu_item_check label="Afficher les IM dans le chat près de vous" name="IMInChat"/>
+ <menu label="Raccourcis" name="Shortcuts">
+ <menu_item_check label="Rechercher" name="Search"/>
+ <menu_item_call label="Relâcher les touches" name="Release Keys"/>
+ <menu_item_call label="Taille de l&apos;interface par défaut" name="Set UI Size to Default"/>
+ <menu_item_check label="Toujours courir" name="Always Run"/>
+ <menu_item_check label="Voler" name="Fly"/>
+ <menu_item_call label="Fermer la fenêtre" name="Close Window"/>
+ <menu_item_call label="Fermer toutes les fenêtres" name="Close All Windows"/>
+ <menu_item_call label="Photo sur disque" name="Snapshot to Disk"/>
+ <menu_item_call label="Vue subjective" name="Mouselook"/>
+ <menu_item_check label="Joystick Flycam" name="Joystick Flycam"/>
+ <menu_item_call label="Réinitialiser la vue" name="Reset View"/>
+ <menu_item_call label="Regarder la dernière conversation" name="Look at Last Chatter"/>
+ <menu label="Sélectionner l&apos;outil de construction" name="Select Tool">
+ <menu_item_call label="Outil de zoom" name="Focus"/>
+ <menu_item_call label="Outil de déplacement" name="Move"/>
+ <menu_item_call label="Outil de modification" name="Edit"/>
+ <menu_item_call label="Outil de création" name="Create"/>
+ <menu_item_call label="Outil Terrain" name="Land"/>
+ </menu>
+ <menu_item_call label="Zoomer en avant" name="Zoom In"/>
+ <menu_item_call label="Zoom par défaut" name="Zoom Default"/>
+ <menu_item_call label="Zoomer en arrière" name="Zoom Out"/>
+ <menu_item_call label="Activer/Quitter le plein écran" name="Toggle Fullscreen"/>
+ </menu>
+ <menu_item_call label="Afficher les paramètres de débogage" name="Debug Settings"/>
+ <menu_item_check label="Afficher le menu Développeurs" name="Debug Mode"/>
+ </menu>
+ <menu label="Développeurs" name="Develop">
+ <menu label="Consoles" name="Consoles">
+ <menu_item_check label="Console de textures" name="Texture Console"/>
+ <menu_item_check label="Console de débogage" name="Debug Console"/>
+ <menu_item_call label="Console de notifications" name="Notifications"/>
+ <menu_item_check label="Console de tailles de textures" name="Texture Size"/>
+ <menu_item_check label="Console des catégories de textures" name="Texture Category"/>
+ <menu_item_check label="Chronos" name="Fast Timers"/>
+ <menu_item_check label="Mémoire" name="Memory"/>
+ <menu_item_call label="Infos de région vers la console de débogage" name="Region Info to Debug Console"/>
+ <menu_item_call label="Infos de groupe vers la console de débogage" name="Group Info to Debug Console"/>
+ <menu_item_call label="Infos de capacités vers la console de débogage" name="Capabilities Info to Debug Console"/>
+ <menu_item_check label="Caméra" name="Camera"/>
+ <menu_item_check label="Vent" name="Wind"/>
+ <menu_item_check label="Angle de champ" name="FOV"/>
+ </menu>
+ <menu label="Afficher les infos" name="Display Info">
+ <menu_item_check label="Afficher l&apos;heure" name="Show Time"/>
+ <menu_item_check label="Afficher les infos de rendu" name="Show Render Info"/>
+ <menu_item_check label="Afficher les matrices" name="Show Matrices"/>
+ <menu_item_check label="Afficher la couleur sous le curseur" name="Show Color Under Cursor"/>
+ <menu_item_check label="Afficher les mises à jour des objets" name="Show Updates"/>
+ </menu>
+ <menu label="Forcer une erreur" name="Force Errors">
+ <menu_item_call label="Forcer le point de rupture" name="Force Breakpoint"/>
+ <menu_item_call label="Forcer LLError et plantage" name="Force LLError And Crash"/>
+ <menu_item_call label="Forcer un mauvais accès à la mémoire" name="Force Bad Memory Access"/>
+ <menu_item_call label="Forcer une boucle infinie" name="Force Infinite Loop"/>
+ <menu_item_call label="Forcer le plantage du driver" name="Force Driver Carsh"/>
+ <menu_item_call label="Forcer une exception logicielle" name="Force Software Exception"/>
+ <menu_item_call label="Forcer la déconnexion du client" name="Force Disconnect Viewer"/>
+ <menu_item_call label="Simuler une fuite de mémoire" name="Memory Leaking Simulation"/>
+ </menu>
+ <menu label="Tests de rendu" name="Render Tests">
+ <menu_item_check label="Décalage de la caméra" name="Camera Offset"/>
+ <menu_item_check label="Taux de défilement aléatoire" name="Randomize Framerate"/>
+ <menu_item_check label="Cadre lent périodique" name="Periodic Slow Frame"/>
+ <menu_item_check label="Test cadre" name="Frame Test"/>
+ </menu>
+ <menu label="Métadonnées de rendu" name="Render Metadata">
+ <menu_item_check label="Cadres" name="Bounding Boxes"/>
+ <menu_item_check label="Octree" name="Octree"/>
+ <menu_item_check label="Shadow Frusta" name="Shadow Frusta"/>
+ <menu_item_check label="Occlusion" name="Occlusion"/>
+ <menu_item_check label="Lots de rendu" name="Render Batches"/>
+ <menu_item_check label="Texture Anim" name="Texture Anim"/>
+ <menu_item_check label="Priorité de la texture" name="Texture Priority"/>
+ <menu_item_check label="Zone de texture" name="Texture Area"/>
+ <menu_item_check label="Zone de face" name="Face Area"/>
+ <menu_item_check label="Lumières" name="Lights"/>
+ <menu_item_check label="Squelette de collision" name="Collision Skeleton"/>
+ <menu_item_check label="Rayons" name="Raycast"/>
+ </menu>
+ <menu label="Rendu" name="Rendering">
+ <menu_item_check label="Axes" name="Axes"/>
+ <menu_item_check label="Tangente" name="Tangent Basis"/>
+ <menu_item_call label="Base des infos de la texture sélectionnée" name="Selected Texture Info Basis"/>
+ <menu_item_check label="Filaire" name="Wireframe"/>
+ <menu_item_check label="Occlusion objet-objet" name="Object-Object Occlusion"/>
+ <menu_item_check label="Objets de mémoire vidéo" name="Framebuffer Objects"/>
+ <menu_item_check label="Rendu différé" name="Deferred Rendering"/>
+ <menu_item_check label="Illumination globale" name="Global Illumination"/>
+ <menu_item_check label="Débogage GL" name="Debug GL"/>
+ <menu_item_check label="Débogage pipeline" name="Debug Pipeline"/>
+ <menu_item_check label="Alpha rapide" name="Fast Alpha"/>
+ <menu_item_check label="Textures d&apos;animation" name="Animation Textures"/>
+ <menu_item_check label="Désactiver les textures" name="Disable Textures"/>
+ <menu_item_check label="Textures pleine résolution" name="Rull Res Textures"/>
+ <menu_item_check label="Audit Textures" name="Audit Textures"/>
+ <menu_item_check label="Atlas des textures" name="Texture Atlas"/>
+ <menu_item_check label="Rendu des lumières jointes" name="Render Attached Lights"/>
+ <menu_item_check label="Rendu des particules jointes" name="Render Attached Particles"/>
+ <menu_item_check label="Hover Glow Objects" name="Hover Glow Objects"/>
+ </menu>
+ <menu label="Réseau" name="Network">
+ <menu_item_check label="Pauser l&apos;avatar" name="AgentPause"/>
+ <menu_item_call label="Activer le journal des messages" name="Enable Message Log"/>
+ <menu_item_call label="Désactiver le journal des messages" name="Disable Message Log"/>
+ <menu_item_check label="Velocity Interpolate Objects" name="Velocity Interpolate Objects"/>
+ <menu_item_check label="Interpolation ping des positions des objets" name="Ping Interpolate Object Positions"/>
+ <menu_item_call label="Abandonner un paquet" name="Drop a Packet"/>
+ </menu>
+ <menu_item_call label="Dump caméra scriptée" name="Dump Scripted Camera"/>
+ <menu_item_call label="Collisions, coups et bousculades" name="Bumps, Pushes &amp;amp; Hits"/>
+ <menu label="Enregistreur" name="Recorder">
+ <menu_item_call label="Commencer la lecture" name="Start Playback"/>
+ <menu_item_call label="Arrêter la lecture" name="Stop Playback"/>
+ <menu_item_check label="Lecture en boucle" name="Loop Playback"/>
+ <menu_item_call label="Commencer l&apos;enregistrement" name="Start Record"/>
+ <menu_item_call label="Arrêter l&apos;enregistrement" name="Stop Record"/>
+ </menu>
+ <menu label="Monde" name="World">
+ <menu_item_check label="Sim Sun Override" name="Sim Sun Override"/>
+ <menu_item_check label="Balise animée" name="Cheesy Beacon"/>
+ <menu_item_check label="Météo fixe" name="Fixed Weather"/>
+ <menu_item_call label="Dump Region Object Cache" name="Dump Region Object Cache"/>
+ </menu>
+ <menu label="Interface" name="UI">
+ <menu_item_call label="Test du navigateur Web" name="Web Browser Test"/>
+ <menu_item_call label="Dump SelectMgr" name="Dump SelectMgr"/>
+ <menu_item_call label="Dump inventaire" name="Dump Inventory"/>
+ <menu_item_call label="Dump Timers" name="Dump Timers"/>
+ <menu_item_call label="Dump Focus Holder" name="Dump Focus Holder"/>
+ <menu_item_call label="Imprimer les infos sur l&apos;objet sélectionné" name="Print Selected Object Info"/>
+ <menu_item_call label="Imprimer les infos sur l&apos;avatar" name="Print Agent Info"/>
+ <menu_item_call label="Statistiques de mémoire" name="Memory Stats"/>
+ <menu_item_check label="Double-ClickAuto-Pilot" name="Double-ClickAuto-Pilot"/>
+ <menu_item_check label="Débogage SelectMgr" name="Debug SelectMgr"/>
+ <menu_item_check label="Débogage clics" name="Debug Clicks"/>
+ <menu_item_check label="Débogage des vues" name="Debug Views"/>
+ <menu_item_check label="Débogage des info-bulles de noms" name="Debug Name Tooltips"/>
+ <menu_item_check label="Débogage des événements de souris" name="Debug Mouse Events"/>
+ <menu_item_check label="Débogage touches" name="Debug Keys"/>
+ <menu_item_check label="Débogage WindowProc" name="Debug WindowProc"/>
+ </menu>
+ <menu label="XUI" name="XUI">
+ <menu_item_call label="Recharger les paramètres de couleurs" name="Reload Color Settings"/>
+ <menu_item_call label="Afficher le test de police" name="Show Font Test"/>
+ <menu_item_call label="Charger à partir de XML" name="Load from XML"/>
+ <menu_item_call label="Enregistrer en XML" name="Save to XML"/>
+ <menu_item_check label="Afficher les noms XUI" name="Show XUI Names"/>
+ <menu_item_call label="Envoyer des IM tests" name="Send Test IMs"/>
+ <menu_item_call label="Tests inspecteurs" name="Test Inspectors"/>
+ </menu>
+ <menu label="Avatar" name="Character">
+ <menu label="Récupérer la texture fixée" name="Grab Baked Texture">
+ <menu_item_call label="Iris" name="Iris"/>
+ <menu_item_call label="Tête" name="Head"/>
+ <menu_item_call label="Haut du corps" name="Upper Body"/>
+ <menu_item_call label="Bas du corps" name="Lower Body"/>
+ <menu_item_call label="Jupe" name="Skirt"/>
+ </menu>
+ <menu label="Tests personnages" name="Character Tests">
+ <menu_item_call label="Apparence dans XML" name="Appearance To XML"/>
+ <menu_item_call label="Basculer la géométrie des personnages" name="Toggle Character Geometry"/>
+ <menu_item_call label="Test homme" name="Test Male"/>
+ <menu_item_call label="Test femme" name="Test Female"/>
+ <menu_item_call label="Activer/désactiver PG" name="Toggle PG"/>
+ <menu_item_check label="Autoriser la sélection de l&apos;avatar" name="Allow Select Avatar"/>
+ </menu>
+ <menu_item_call label="Forcer les paramètres par défaut" name="Force Params to Default"/>
+ <menu_item_check label="Infos sur l&apos;animation" name="Animation Info"/>
+ <menu_item_check label="Animations au ralenti" name="Slow Motion Animations"/>
+ <menu_item_check label="Afficher la direction du regard" name="Show Look At"/>
+ <menu_item_check label="Afficher la direction du pointeur" name="Show Point At"/>
+ <menu_item_check label="Débogages des mises à jour" name="Debug Joint Updates"/>
+ <menu_item_check label="Désactiver LOD" name="Disable LOD"/>
+ <menu_item_check label="Debogage Character Vis" name="Debug Character Vis"/>
+ <menu_item_check label="Afficher le squelette de collision" name="Show Collision Skeleton"/>
+ <menu_item_check label="Afficher la cible de l&apos;avatar" name="Display Agent Target"/>
+ --&gt;
+ <menu_item_call label="Dump Attachments" name="Dump Attachments"/>
+ <menu_item_call label="Débogage des textures des avatars" name="Debug Avatar Textures"/>
+ <menu_item_call label="Dump Local Textures" name="Dump Local Textures"/>
+ </menu>
+ <menu_item_call label="Compresser les images" name="Compress Images"/>
+ <menu_item_check label="Output Debug Minidump" name="Output Debug Minidump"/>
+ <menu_item_check label="Console Window on next Run" name="Console Window"/>
+ <menu_item_check label="Afficher le menu Admin" name="View Admin Options"/>
+ <menu_item_call label="Demander le statut Admin" name="Request Admin Options"/>
+ <menu_item_call label="Quitter le statut Admin" name="Leave Admin Options"/>
+ </menu>
+ <menu label="Admin" name="Admin">
+ <menu label="Object">
+ <menu_item_call label="Prendre une copie" name="Take Copy"/>
+ <menu_item_call label="Forcer le propriétaire sur moi" name="Force Owner To Me"/>
+ <menu_item_call label="Forcer la permission du propriétaire" name="Force Owner Permissive"/>
+ <menu_item_call label="Supprimer" name="Delete"/>
+ <menu_item_call label="Verrouiller" name="Lock"/>
+ <menu_item_call label="Obtenir les ID d&apos;actifs" name="Get Assets IDs"/>
+ </menu>
+ <menu label="Parcelle" name="Parcel">
+ <menu_item_call label="Propriétaire à moi" name="Owner To Me"/>
+ <menu_item_call label="Définir sur le contenu Linden" name="Set to Linden Content"/>
+ <menu_item_call label="Réclamer un terrain public" name="Claim Public Land"/>
+ </menu>
+ <menu label="Région" name="Region">
+ <menu_item_call label="Dump Temp Asset Data" name="Dump Temp Asset Data"/>
+ <menu_item_call label="Enregistrer l&apos;état de la région" name="Save Region State"/>
+ </menu>
+ <menu_item_call label="Outils divins" name="God Tools"/>
+ </menu>
+ <menu label="Admin" name="Deprecated">
+ <menu label="Joindre l&apos;objet" name="Attach Object"/>
+ <menu label="Détacher l&apos;objet" name="Detach Object"/>
+ <menu label="Me déshabiller" name="Take Off Clothing">
+ <menu_item_call label="Chemise" name="Shirt"/>
+ <menu_item_call label="Pantalon" name="Pants"/>
+ <menu_item_call label="Chaussures" name="Shoes"/>
+ <menu_item_call label="Chaussettes" name="Socks"/>
+ <menu_item_call label="Veste" name="Jacket"/>
+ <menu_item_call label="Gants" name="Gloves"/>
+ <menu_item_call label="Sous-vêtements (homme)" name="Menu Undershirt"/>
+ <menu_item_call label="Sous-vêtements (femme)" name="Menu Underpants"/>
+ <menu_item_call label="Jupe" name="Skirt"/>
+ <menu_item_call label="Alpha" name="Alpha"/>
+ <menu_item_call label="Tatouage" name="Tattoo"/>
+ <menu_item_call label="Tous les habits" name="All Clothes"/>
+ </menu>
+ <menu_item_check label="Afficher la barre d&apos;outils" name="Show Toolbar"/>
+ <menu label="Aide" name="Help">
+ <menu_item_call label="Blog officiel des Linden" name="Official Linden Blog"/>
+ <menu_item_call label="Portail d&apos;écriture de scripts" name="Scripting Portal"/>
+ <menu label="Signaler des bugs" name="Bug Reporting">
+ <menu_item_call label="JIRA" name="Public Issue Tracker"/>
+ <menu_item_call label="Aide du JIRA" name="Publc Issue Tracker Help"/>
+ <menu_item_call label="Comment signaler des bugs" name="Bug Reporing 101"/>
+ <menu_item_call label="Problèmes de sécurité" name="Security Issues"/>
+ <menu_item_call label="Wiki sur l&apos;Assurance Qualité" name="QA Wiki"/>
+ </menu>
+ </menu>
</menu>
</menu_bar>
diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml
index ac8d0cc605..dd277c9d37 100644
--- a/indra/newview/skins/default/xui/fr/notifications.xml
+++ b/indra/newview/skins/default/xui/fr/notifications.xml
@@ -6,74 +6,36 @@
<global name="alwayschoose">
Toujours choisir cette option
</global>
- <template name="okbutton">
- <form>
- <button
- name="OK"
- text="$yestext"/>
- </form>
- </template>
-
- <template name="okignore">
- <form>
- <button
- name="OK"
- text="$yestext"/>
- <ignore text="$ignoretext"/>
- </form>
- </template>
-
- <template name="okcancelbuttons">
- <form>
- <button
- name="OK"
- text="$yestext"/>
- <button
- name="Cancel"
- text="$notext"/>
- </form>
- </template>
-
- <template name="okcancelignore">
- <form>
- <button
- name="OK"
- text="$yestext"/>
- <button
- name="Cancel"
- text="$notext"/>
- <ignore text="$ignoretext"/>
- </form>
- </template>
-
- <template name="okhelpbuttons">
- <form>
- <button
- name="OK"
- text="$yestext"/>
- <button
- name="Help"
- text="$helptext"/>
- </form>
- </template>
-
- <template name="yesnocancelbuttons">
- <form>
- <button
- name="Yes"
- text="$yestext"/>
- <button
- name="No"
- text="$notext"/>
- <button
- name="Cancel"
- text="$canceltext"/>
- </form>
- </template>
+ <global name="implicitclosebutton">
+ Fermer
+ </global>
+ <template name="okbutton">
+ <form>
+ <button name="OK" text="$yestext"/>
+ </form>
+ </template>
+ <template name="okignore"/>
+ <template name="okcancelbuttons">
+ <form>
+ <button name="Cancel" text="$notext"/>
+ </form>
+ </template>
+ <template name="okcancelignore"/>
+ <template name="okhelpbuttons">
+ <form>
+ <button name="Help" text="$helptext"/>
+ </form>
+ </template>
+ <template name="yesnocancelbuttons">
+ <form>
+ <button name="Yes" text="$yestext"/>
+ <button name="No" text="$notext"/>
+ </form>
+ </template>
<notification functor="GenericAcknowledge" label="Message d&apos;alerte inconnu" name="MissingAlert">
- Votre version de Second Life ne peut afficher ce message d&apos;erreur.
+ Votre version de [APP_NAME] ne peut afficher ce message d&apos;erreur. Veuillez vous assurer que vous avez bien la toute dernière version du client.
-Détails de l&apos;erreur : L&apos;alerte, appelée &apos;[_NAME]&apos; est introuvable dans notifications.xml.
+Détails de l&apos;erreur : L&apos;alerte, appelée &apos;[_NAME]&apos;, est introuvable dans notifications.xml.
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="FloaterNotFound">
@@ -94,13 +56,13 @@ Détails de l&apos;erreur : L&apos;alerte, appelée &apos;[_NAME]&apos; est int
<usetemplate name="okcancelbuttons" notext="Annuler" yestext="Oui"/>
</notification>
<notification name="BadInstallation">
- Une erreur est survenue lors de la mise à jour de Second Life. Veuillez télécharger la dernière version depuis secondlife.com.
+ Une erreur est survenue lors de la mise à jour de [APP_NAME]. Veuillez [http://get.secondlife.com télécharger la dernière version] du client.
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="LoginFailedNoNetwork">
- Erreur réseau : impossible d&apos;établir une connexion.
+ Connexion à [SECOND_LIFE_GRID] impossible.
&apos;[DIAGNOSTIC]&apos;
-Veuillez vérifier votre connexion.
+Veuillez vérifier votre connexion Internet.
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="MessageTemplateNotFound">
@@ -168,7 +130,7 @@ Souhaitez-vous accorder des droits d&apos;édition aux résidents selectionnésÂ
Les membres ne peuvent pas être destitués de ce rôle.
Ils doivent donner eux-mêmes leur démission.
Êtes-vous certain de vouloir continuer ?
- <usetemplate ignoretext="Lorsque vous donnez à des membres du groupe le rôle de « propriétaire »" name="okcancelignore" notext="Non" yestext="Oui"/>
+ <usetemplate ignoretext="Confirmer avant d&apos;ajouter un nouveau propriétaire" name="okcancelignore" notext="Non" yestext="Oui"/>
</notification>
<notification name="AssignDangerousActionWarning">
Vous êtes sur le point d&apos;ajouter le pouvoir « [ACTION_NAME] » au rôle « [ROLE_NAME] ».
@@ -187,52 +149,8 @@ Ajouter ce pouvoir à « [ROLE_NAME] » ?
Ajouter ce pouvoir à « [ROLE_NAME] » ?
<usetemplate name="okcancelbuttons" notext="Non" yestext="Oui"/>
</notification>
- <notification name="ClickPublishHelpLand">
- Sélectionner l&apos;option Afficher dans la recherche
-En cochant cette case, votre parcelle apparaîtra :
-- dans les résultats de recherche ;
-- dans les objets publics ;
-- dans la recherche web.
- </notification>
- <notification name="ClickSoundHelpLand">
- La musique et le média ne peuvent être utilisés que sur cette parcelle. Les options Son et Voix peuvent être limités à la parcelle ou seront entendus par les résidents en dehors de la parcelle, en fonction de leur catégorie d&apos;accès. Souhaitez-vous en savoir plus sur le paramétrage de ces options ?
- <url name="url">
- http://wiki.secondlife.com/wiki/M%C3%A9dias_sur_la_parcelle_(KB)
- </url>
- <usetemplate name="okcancelbuttons" notext="Fermer" yestext="Consulter les pages d&apos;aide"/>
- </notification>
- <notification name="ClickSearchHelpAll">
- Les résultats de recherche sont organisés en fonction de l&apos;onglet dans lequel vous vous trouvez, votre catégorie d&apos;accès, la catégorie choisie, ainsi que d&apos;autres facteurs. Pour plus de détails, veuillez consulter les pages d&apos;aide.
- <url name="url">
- http://wiki.secondlife.com/wiki/FAQ_sur_la_recherche_(KB)
- </url>
- <usetemplate name="okcancelbuttons" notext="Fermer" yestext="Consulter les pages d&apos;aide"/>
- </notification>
- <notification name="ClickPublishHelpLandDisabled">
- Cette parcelle ne peut pas apparaître dans la recherche car elle est dans une région où cela n&apos;est pas autorisé.
- </notification>
- <notification name="ClickPublishHelpAvatar">
- Si vous sélectionnez Afficher dans la recherche :
-- votre profil apparaîtra dans les résultats de recherche ;
-- un lien vers votre profil apparaîtra dans les pages de groupe publiques.
- </notification>
- <notification name="ClickPartnerHelpAvatar">
- Vous pouvez proposer à un autre résident de devenir votre partenaire ou dissoudre un partenariat existant à partir du site de [SECOND_LIFE].
-
-Aller sur le site de Second Life pour avoir plus d&apos;informations sur les partenariats ?
- <usetemplate name="okcancelbuttons" notext="Annuler" yestext="Aller sur cette page"/>
- </notification>
- <notification name="ClickUploadHelpPermissions">
- Il est possible que vos droits par défaut ne fonctionnent pas dans les anciennes régions.
- </notification>
- <notification name="ClickWebProfileHelpAvatar">
- Si ce résident a défini une URL de profil web, vous pouvez :
- * Cliquer sur Charger pour afficher la page dans cet onglet ;
- * Cliquer sur Charger &gt; Dans un navigateur externe, pour afficher la page dans votre navigateur par défaut ;
- * Cliquer sur Charger &gt; URL du domicile, pour retourner au profil web du résident.
-
-Lorsque vous êtes dans votre propre profil, vous pouvez définir n&apos;importe quelle URL comme profil web. Pour cela, saisissez l&apos;URL et cliquez sur OK.
-Les autres résidents peuvent visiter l&apos;URL que vous avez définie en regardant votre profil.
+ <notification name="ClickUnimplemented">
+ Désolés, pas encore mis en œuvre.
</notification>
<notification name="JoinGroupCanAfford">
Rejoindre ce groupe coûte [COST] L$.
@@ -243,6 +161,12 @@ Voulez-vous continuer ?
Rejoindre ce groupe coûte [COST] L$.
Vous n&apos;avez pas suffisamment de L$ pour rejoindre ce groupe.
</notification>
+ <notification name="CreateGroupCost">
+ La création de ce groupe coûte 100 L$.
+Les groupes doivent comporter plus d&apos;un membre, sinon ils sont supprimés.
+Veuillez inviter des membres d&apos;ici 48 heures.
+ <usetemplate canceltext="Annuler" name="okcancelbuttons" notext="Annuler" yestext="Créer un groupe pour 100 L$"/>
+ </notification>
<notification name="LandBuyPass">
Pour [COST] L$ vous pouvez pénétrer sur ce terrain ([PARCEL_NAME]) et y rester [TIME] heures. Acheter un pass ?
<usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
@@ -257,10 +181,10 @@ Votre prix de vente sera de [SALE_PRICE] L$ et la vente sera disponible à [NAME
<usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
</notification>
<notification name="ConfirmLandSaleToAnyoneChange">
- Attention : en cliquant sur Vendre à n&apos;importe qui, vous rendez votre terrain disponible à toute la communauté de Second Life, même aux personnes qui ne sont pas dans cette région.
+ ATTENTION : en cliquant sur Vendre à n&apos;importe qui, vous rendez votre terrain disponible à toute la communauté de [SECOND_LIFE], même aux personnes qui ne sont pas dans cette région.
Le terrain sélectionné, de [LAND_SIZE] m², est mis en vente.
-Votre prix de vente sera de [SALE_PRICE] L$ et la vente sera disponible à [NAME].
+Votre prix de vente sera de [SALE_PRICE]L$ et la vente sera disponible à [NAME].
<usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
</notification>
<notification name="ReturnObjectsDeededToGroup">
@@ -320,6 +244,18 @@ Objets : [N]
Les dégâts sont autorisés dans toute la région.
Pour que les armes fonctionnent, les scripts doivent être autorisés.
</notification>
+ <notification name="MultipleFacesSelected">
+ Plusieurs faces sont sélectionnées.
+Si vous poursuivez cette action, des instances séparées du média seront définies sur plusieurs faces de l&apos;objet.
+Pour ne placer le média que sur une seule face, choisissez Sélectionner une texture, cliquez sur la face de l&apos;objet de votre choix, puis sur Ajouter.
+ <usetemplate ignoretext="Le média sera défini sur plusieurs faces sélectionnées" name="okcancelignore" notext="Annuler" yestext="OK"/>
+ </notification>
+ <notification name="WhiteListInvalidatesHomeUrl">
+ Si vous ajoutez cette entrée à la liste blanche, l&apos;URL du domicile que vous avez spécifiée
+pour cette instance du média ne sera plus valide. Vous n&apos;êtes pas autorisé(e) à faire cela,
+l&apos;entrée ne peut donc pas être ajoutée à la liste blanche.
+ <usetemplate name="okbutton" yestext="Ok"/>
+ </notification>
<notification name="MustBeInParcel">
Pour définir le point d&apos;atterrissage, vous devez vous trouver à l&apos;intérieur de la parcelle.
</notification>
@@ -355,6 +291,10 @@ Ce dossier ne contient pas d&apos;habits, de parties du corps ni de pièces join
<notification name="CannotWearTrash">
Vous ne pouvez pas porter d&apos;habits ni de parties du corps se trouvant dans la corbeille.
</notification>
+ <notification name="MaxAttachmentsOnOutfit">
+ Impossible de joindre l&apos;objet.
+La limite de [MAX_ATTACHMENTS] objets joints a été dépassée. Veuillez commencer par supprimer un objet joint existant.
+ </notification>
<notification name="CannotWearInfoNotComplete">
Vous ne pouvez pas porter cet article car il n&apos;a pas encore été chargé. Veuillez réessayer dans une minute.
</notification>
@@ -363,20 +303,28 @@ Ce dossier ne contient pas d&apos;habits, de parties du corps ni de pièces join
Vous devez saisir le nom et le prénom de votre avatar.
Pour entrer dans [SECOND_LIFE], vous devez avoir un compte. Voulez-vous en créer un maintenant ?
+ <url name="url">
+ https://join.secondlife.com/index.php?lang=fr-FR
+ </url>
<usetemplate name="okcancelbuttons" notext="Réessayer" yestext="Créer un compte"/>
</notification>
<notification name="AddClassified">
- Les petites annonces sont publiées à l&apos;onglet Petites annonces de la section Recherche pendant une semaine.
+ Les petites annonces sont publiées à l&apos;onglet Petites annonces de la section Recherche et sur [http://secondlife.com/community/classifieds secondlife.com] pendant une semaine.
Rédigez votre annonce, puis cliquez sur Publier pour l&apos;ajouter à la liste des annonces.
Au moment de cliquer sur Publier, vous serez invité à payer des frais.
Plus vous payez cher, plus votre annonce est visible dans la liste ainsi que dans les résultats de recherche de mots-clés.
- <usetemplate ignoretext="Lors de l&apos;ajout d&apos;une nouvelle petite annonce" name="okcancelignore" notext="Annuler" yestext="OK"/>
+ <usetemplate ignoretext="Comment ajouter une nouvelle petite annonce" name="okcancelignore" notext="Annuler" yestext="OK"/>
</notification>
<notification name="DeleteClassified">
Supprimer l&apos;annonce [NAME] ?
Une fois payés, les frais ne sont pas remboursables.
<usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
</notification>
+ <notification name="DeleteMedia">
+ Vous avez choisi de supprimer le média associé à cette face.
+Voulez-vous vraiment continuer ?
+ <usetemplate ignoretext="Confirmer avant de supprimer un média d&apos;un objet" name="okcancelignore" notext="Non" yestext="Oui"/>
+ </notification>
<notification name="ClassifiedSave">
Enregistrer les changements dans l&apos;annonce [NAME] ?
<usetemplate canceltext="Annuler" name="yesnocancelbuttons" notext="Ne pas enregistrer" yestext="Enregistrer"/>
@@ -387,6 +335,9 @@ Une fois payés, les frais ne sont pas remboursables.
</notification>
<notification name="PromptGoToEventsPage">
Aller à la page web de [SECOND_LIFE] réservée aux événements ?
+ <url name="url">
+ http://secondlife.com/events/?lang=fr-FR
+ </url>
<usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
</notification>
<notification name="SelectProposalToView">
@@ -404,20 +355,23 @@ Une fois payés, les frais ne sont pas remboursables.
<usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
</notification>
<notification name="CacheWillClear">
- Le cache sera vidé après le redémarrage de [SECOND_LIFE].
+ Le cache sera vidé après le redémarrage de [APP_NAME].
</notification>
<notification name="CacheWillBeMoved">
- Le cache sera déplacé après le redémarrage de [SECOND_LIFE].
+ Le cache sera déplacé après le redémarrage de [APP_NAME].
Remarque : cela videra le cache.
</notification>
<notification name="ChangeConnectionPort">
- Les paramètres du port prendront effet après le redémarrage de [SECOND_LIFE].
+ Les paramètres du port prendront effet après le redémarrage de [APP_NAME].
</notification>
<notification name="ChangeSkin">
- Le nouveau thème apparaîtra après le redémarrage de [SECOND_LIFE].
+ Le nouveau thème apparaîtra après le redémarrage de [APP_NAME].
</notification>
<notification name="GoToAuctionPage">
Aller à la page web de [SECOND_LIFE] pour voir le détail des enchères ou enchérir ?
+ <url name="url">
+ http://secondlife.com/auctions/auction-detail.php?id=[AUCTION_ID]
+ </url>
<usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
</notification>
<notification name="SaveChanges">
@@ -462,6 +416,11 @@ L&apos;objet est peut-être inaccessible ou a peut-être été supprimé.
<notification name="SaveBytecodeFailReason">
Une erreur est survenue lors de l&apos;enregistrement du script compilé, suite au problème suivant : [REASON]. Essayez d&apos;enregistrer votre script ultérieurement.
</notification>
+ <notification name="StartRegionEmpty">
+ Vous n&apos;avez pas défini de région de départ.
+Veuillez saisir le nom de la région dans la case Lieu de départ, ou choisissez Dernier emplacement ou Domicile comme Lieu de départ.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
<notification name="CouldNotStartStopScript">
Impossible de lancer ou d&apos;arrêter le script car l&apos;objet qui le contient est introuvable.
L&apos;objet est peut-être inaccessible ou a peut-être été supprimé.
@@ -473,28 +432,26 @@ L&apos;objet est peut-être inaccessible ou a peut-être été supprimé.
Impossible d&apos;écrire le fichier [[FILE]]
</notification>
<notification name="UnsupportedHardware">
- Avertissement : vous n&apos;avez pas la configuration système requise pour utiliser Second Life. Si vous continuez à utiliser Second Life, votre performance risque d&apos;être moindre. Malheureusement, nous n&apos;offrons aucune assistance pour les problèmes de configuration système.
+ Avertissement : vous n&apos;avez pas la configuration système requise pour utiliser [APP_NAME]. Si vous continuez à utiliser [APP_NAME], votre performance risque d&apos;être moindre. Malheureusement, la page [SUPPORT_SITE] n&apos;offre aucune assistance pour les problèmes de configuration système.
MINSPECS
-Voulez-vous visiter [_URL] pour plus d&apos;informations ?
+Voulez-vous visiter [_URL] pour plus d&apos;informations ?
<url name="url" option="0">
http://secondlife.com/support/sysreqs.php?lang=fr
</url>
- <usetemplate ignoretext="Lors de la détection de matériel non pris en charge" name="okcancelignore" notext="Non" yestext="Oui"/>
+ <usetemplate ignoretext="Mon matériel n&apos;est pas pris en charge" name="okcancelignore" notext="Non" yestext="Oui"/>
</notification>
<notification name="UnknownGPU">
- Votre système contient une carte graphique que nous ne connaissons pas actuellement.
-Cela est souvent le cas avec le nouveau materiel qui n&apos;a pas encore été testé.
-Vous pourrez probablement utiliser Second Life sans problème, mais vous devrez peut-être ajuster les paramètres de vos graphiques.
-(Menu Édition &gt; Préférences &gt; Graphiques).
+ Votre système contient une carte graphique que [APP_NAME] ne reconnaît pas actuellement.
+Cela est souvent le cas avec le nouveau matériel qui n&apos;a pas encore été testé avec [APP_NAME]. Vous pourrez probablement utiliser [APP_NAME] sans problème, mais vous devrez peut-être ajuster les paramètres de vos graphiques.
+(Moi &gt; Préférences &gt; Graphiques).
<form name="form">
- <ignore name="ignore" text="Lors de la détection d&apos;une carte graphique inconnue"/>
+ <ignore name="ignore" text="Ma carte graphique ne peut être identifiée"/>
</form>
</notification>
<notification name="DisplaySettingsNoShaders">
- [SECOND_LIFE] a planté lors de l&apos;initialisation des drivers graphiques.
-La qualité des graphiques sera paramétrée sur Faible pour éviter certaines erreurs de driver fréquentes.
-Certaines fonctionnalités graphiques seront donc désactivées.
+ [APP_NAME] a planté lors de l&apos;initialisation des drivers graphiques.
+La qualité des graphiques sera paramétrée sur Faible pour éviter certaines erreurs de driver fréquentes. Certaines fonctionnalités graphiques seront donc désactivées.
Nous vous recommandons de mettre à jour les drivers de votre carte graphique.
La qualité des graphiques peut être augmentée à la section Préférences &gt; Graphiques
</notification>
@@ -547,6 +504,9 @@ Il ou elle ne pourra temporairement plus bouger, chatter, ou interagir dans le M
Expulser [AVATAR_NAME] de votre terrain ?
<usetemplate name="okcancelbuttons" notext="Annuler" yestext="Expulser"/>
</notification>
+ <notification name="EjectAvatarFromGroup">
+ Vous avez expulsé [AVATAR_NAME] du groupe [GROUP_NAME]
+ </notification>
<notification name="AcquireErrorTooManyObjects">
Erreur d&apos;acquisition : trop d&apos;objets sélectionnés.
</notification>
@@ -557,7 +517,10 @@ Veuillez mettre tous les objets que vous souhaitez acquérir dans la même régi
<notification name="PromptGoToCurrencyPage">
[EXTRA]
-Aller sur [URL] pour obtenir des informations sur l&apos;achat de devises ?
+Aller sur [_URL] pour obtenir des informations sur l&apos;achat de L$ ?
+ <url name="url">
+ http://secondlife.com/app/currency/?lang=fr-FR
+ </url>
<usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
</notification>
<notification name="UnableToLinkObjects">
@@ -643,12 +606,15 @@ Assurez-vous que le fichier a l&apos;extension correcte.
Impossible de créer le fichier de sortie : [FILE]
</notification>
<notification name="DoNotSupportBulkAnimationUpload">
- Actuellement, nous ne prenons pas en charge le chargement de lots de fichiers d&apos;animation.
+ Actuellement, [APP_NAME] ne prend pas en charge le chargement de lots de fichiers d&apos;animation.
</notification>
<notification name="CannotUploadReason">
Impossible de charger [FILE] suite au problème suivant : [REASON]
Veuillez réessayer ultérieurement.
</notification>
+ <notification name="LandmarkCreated">
+ Vous avez ajouté [LANDMARK_NAME] à votre dossier [FOLDER_NAME].
+ </notification>
<notification name="CannotCreateLandmarkNotOwner">
Vous ne pouvez pas créer de repère ici car le propriétaire du terrain ne l&apos;autorise pas.
</notification>
@@ -671,6 +637,9 @@ Veuillez sélectionner des objets avec des scripts.
Sélectionnez des objets qui ont des scripts et que vous pouvez modifier.
</notification>
+ <notification name="CannotOpenScriptObjectNoMod">
+ Impossible d&apos;ouvrir le script de l&apos;objet sans droits de modification.
+ </notification>
<notification name="CannotSetRunningSelectObjectsNoScripts">
Impossible de définir les scripts sur « exécution ».
@@ -697,12 +666,12 @@ Recherche effectuée : [FINALQUERY]
[REASON]
</notification>
<notification name="invalid_tport">
- Nous avons rencontré des problèmes en essayant de vous téléporter. Vous devrez peut-être vous reconnecter avant de pouvoir être téléporté. Si vous continuez à recevoir ce message, veuillez consulter le Support à la page suivante :
-www.secondlife.com/support
+ Nous avons rencontré des problèmes en essayant de vous téléporter. Vous devrez peut-être vous reconnecter avant de pouvoir vous téléporter.
+Si ce message persiste, veuillez consulter la page [SUPPORT_SITE].
</notification>
<notification name="invalid_region_handoff">
- Nous avons rencontré des problèmes en essayant de vous téléporter. Vous devrez peut-être vous reconnecter avant de pouvoir être téléporté. Si vous continuez à recevoir ce message, veuillez consulter le Support à la page suivante :
-www.secondlife.com/support
+ Nous avons rencontré des problèmes en essayant de vous téléporter. Vous devrez peut-être vous reconnecter avant de pouvoir traverser des régions.
+Si ce message persiste, veuillez consulter la page [SUPPORT_SITE].
</notification>
<notification name="blocked_tport">
Désolé, la téléportation est bloquée actuellement. Veuillez réessayer dans un moment.
@@ -772,7 +741,7 @@ aucune parcelle sélectionnée.
la région dans laquelle il est situé est introuvable.
</notification>
<notification name="CannotCloseFloaterBuyLand">
- Vous ne pouvez pas fermer la fenêtre Acheter le terrain avant que Second Life n&apos;estime le montant de cette transaction.
+ Vous ne pouvez pas fermer la fenêtre Acheter le terrain avant que [APP_NAME] n&apos;estime le montant de cette transaction.
</notification>
<notification name="CannotDeedLandNothingSelected">
Cession du terrain impossible :
@@ -783,9 +752,8 @@ aucune parcelle sélectionnée.
aucun groupe sélectionné.
</notification>
<notification name="CannotDeedLandNoRegion">
- Cession du terrain impossible :
+ Cession du terrain impossible :
la région dans laquelle il est situé est introuvable.
-Veuillez utiliser Aide &gt; Signaler des bugs pour signaler le problème.
</notification>
<notification name="CannotDeedLandMultipleSelected">
Cession du terrain impossible :
@@ -829,10 +797,8 @@ vous n&apos;avez pas le droit de libérer cette parcelle.
Les parcelles qui vous appartiennent sont en vert.
</notification>
<notification name="CannotReleaseLandRegionNotFound">
- Impossible d&apos;abandonner le terrain :
+ Impossible d&apos;abandonner le terrain :
la région dans laquelle il est situé est introuvable.
-
-Veuillez utiliser Aide &gt; Signaler un bug pour signaler le problème.
</notification>
<notification name="CannotReleaseLandNoTransfer">
Impossible d&apos;abandonner le terrain :
@@ -869,16 +835,12 @@ Diviser le terrain ?
<usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
</notification>
<notification name="CannotDivideLandNoRegion">
- Division du terrain impossible :
+ Division du terrain impossible :
la région dans laquelle il est situé est introuvable.
-
-Veuillez utiliser Aide &gt; Signaler un bug pour signaler le problème.
</notification>
<notification name="CannotJoinLandNoRegion">
- Impossible de fusionner le terrain :
+ Impossible de fusionner le terrain :
la région dans laquelle il est situé est introuvable.
-
-Veuillez utiliser Aide &gt; Signaler un bug pour signaler le problème.
</notification>
<notification name="CannotJoinLandNothingSelected">
Impossible de fusionner le terrain :
@@ -903,17 +865,6 @@ Vous devrez réinitialiser le nom et les options de la nouvelle parcelle.
Fusionner le terrain ?
<usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
</notification>
- <notification name="ShowOwnersHelp">
- Afficher les propriétaires :
-La couleur des parcelles indique le type de propriété.
-
-Vert = votre terrain
-Turquoise = le terrain de votre groupe
-Rouge = appartenant à d&apos;autres
-Jaune = en vente
-Mauve = aux enchères
-Gris = public
- </notification>
<notification name="ConfirmNotecardSave">
Cette note doit être sauvegardée avant que l&apos;objet ne puisse être copié ou visualisé. Enregistrer la note ?
<usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
@@ -937,13 +888,11 @@ Gris = public
<notification name="CannotSaveToAssetStore">
Impossible de sauvegarder le fichier [NAME] dans la base de données centrale.
Cette erreur est généralement temporaire. Veuillez éditer et sauvegarder l&apos;élément endossable à nouveau d&apos;ici quelques minutes.
-
-Si le problème persiste, veuillez cliquer sur Aide | Signaler un bug dans le menu déroulant en indiquant les détails de votre connexion.
</notification>
<notification name="YouHaveBeenLoggedOut">
- Vous avez été déconnecté(e) de [SECOND_LIFE] :
+ Vous avez été déconnecté(e) de [SECOND_LIFE] :
[MESSAGE]
-Vous pouvez afficher vos messages instantanés et votre chat en cliquant sur Afficher IM et chat. Sinon, cliquez sur Quitter pour quitter immédiatement [SECOND_LIFE].
+Vous pouvez afficher vos messages instantanés et votre chat en cliquant sur Afficher IM et chat. Sinon, cliquez sur Quitter pour quitter immédiatement [APP_NAME].
<usetemplate name="okcancelbuttons" notext="Quitter" yestext="Afficher IM et chat"/>
</notification>
<notification name="OnlyOfficerCanBuyLand">
@@ -961,7 +910,7 @@ Proposer à [NAME] de devenir votre ami(e) ?
Proposer à [NAME] de devenir votre ami(e) ?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Voulez-vous être mon ami(e) ?
</input>
<button name="Offer" text="OK"/>
@@ -1094,28 +1043,40 @@ Céder ces [AREA] m² de terrain au groupe [GROUP_NAME] ?
<notification name="ErrorMessage">
[ERROR_MESSAGE]
</notification>
- <notification name="AvatarMoved">
- L&apos;emplacement [TYPE] n&apos;est pas disponible actuellement. [HELP]
-Vous avez été déplacé dans une région voisine.
+ <notification name="AvatarMovedDesired">
+ La destination que vous avez choisie n&apos;est pas disponible actuellement.
+Vous avez été téléporté vers une région voisine.
+ </notification>
+ <notification name="AvatarMovedLast">
+ Votre dernière destination n&apos;est pas disponible actuellement.
+Vous avez été téléporté vers une région voisine.
+ </notification>
+ <notification name="AvatarMovedHome">
+ La destination que vous avez choisie n&apos;est pas disponible actuellement.
+Vous avez été téléporté vers une région voisine.
+Nous vous conseillons de définir votre domicile ailleurs.
</notification>
<notification name="ClothingLoading">
- Vos habits sont toujours en train d&apos;être téléchargés.
-Vous pouvez utiliser [SECOND_LIFE] sans problème, les autres résidents vous voient normalement.
+ Vos habits sont en cours de téléchargement.
+Vous pouvez utiliser [SECOND_LIFE] normalement, les autres résidents vous voient correctement.
<form name="form">
- <ignore name="ignore" text="Lorsque les habits prennent longtemps à télécharger"/>
+ <ignore name="ignore" text="Vos habits prennent du temps à télécharger"/>
</form>
</notification>
<notification name="FirstRun">
- L&apos;installation de [SECOND_LIFE] est terminée.
+ L&apos;installation de [APP_NAME] est terminée.
-S&apos;il s&apos;agit de la première fois que vous utilisez [SECOND_LIFE], vous devrez créer un compte avant de pouvoir vous connecter.
-Retourner sur www.secondlife.com pour créer un nouveau compte ?
+Si vous utilisez [SECOND_LIFE] pour la première fois, vous devez ouvrir un compte avant de pouvoir vous connecter.
+Retourner sur [http://join.secondlife.com secondlife.com] pour ouvrir un nouveau compte ?
<usetemplate name="okcancelbuttons" notext="Continuer" yestext="Nouveau compte..."/>
</notification>
<notification name="LoginPacketNeverReceived">
- Vous avez des problèmes à vous connecter. Il peut s&apos;agir d&apos;un problème avec votre connexion internet ou les serveurs de Second Life.
+ Nous avons des difficultés à vous connecter. Il y a peut-être un problème avec votre connexion Internet ou la [SECOND_LIFE_GRID].
-Nous vous conseillons de vérifier votre connexion Internet et de réessayer dans quelques minutes, de cliquer sur Aide, ou bien de cliquer sur Téléporter pour être téléporté vers votre domicile.
+Vérifiez votre connexion Internet et réessayez dans quelques minutes, cliquez sur Aide pour consulter la page [SUPPORT_SITE] ou bien sur Téléporter pour essayer d&apos;aller chez vous.
+ <url name="url">
+ http://fr.secondlife.com/support/
+ </url>
<form name="form">
<button name="OK" text="OK"/>
<button name="Help" text="Aide"/>
@@ -1135,10 +1096,10 @@ Vous pourrez revenir sur votre décision plus tard.
[NAME] [PRICE] L$ Vous n&apos;avez pas suffisamment de L$ pour faire cela.
</notification>
<notification name="GrantedModifyRights">
- Vous avez reçu le droit de modifier les objets de [FIRST_NAME] [LAST_NAME].
+ [NAME] vous a donné la permission de modifier ses objets.
</notification>
<notification name="RevokedModifyRights">
- Vous n&apos;avez plus le droit de modifier les objets de [FIRST_NAME] [LAST_NAME].
+ Vous n&apos;avez plus la permission de modifier les objets de [NAME]
</notification>
<notification name="FlushMapVisibilityCaches">
Cela videra le cache cartographique de cette région.
@@ -1217,97 +1178,107 @@ Veuillez choisir un objet à vendre et réessayer.
[DOWNLOAD_PATH].
</notification>
<notification name="DownloadWindowsMandatory">
- Une nouvelle version de [SECOND_LIFE] est disponible.
+ Une nouvelle version de [APP_NAME] est disponible.
[MESSAGE]
-Pour utiliser [SECOND_LIFE] vous devez télécharger cette mise à jour.
+Pour utiliser [APP_NAME], vous devez télécharger cette mise à jour.
<usetemplate name="okcancelbuttons" notext="Quitter" yestext="Télécharger"/>
</notification>
<notification name="DownloadWindows">
- Une mise à jour de [SECOND_LIFE] est disponible.
+ Une mise à jour de [APP_NAME] est disponible.
[MESSAGE]
Cette mise à jour n&apos;est pas requise mais si vous voulez une meilleure performance et plus de stabilité, nous vous recommandons de l&apos;installer.
<usetemplate name="okcancelbuttons" notext="Continuer" yestext="Télécharger"/>
</notification>
<notification name="DownloadWindowsReleaseForDownload">
- Une mise à jour de [SECOND_LIFE] est disponible.
+ Une mise à jour de [APP_NAME] est disponible.
+[MESSAGE]
+Cette mise à jour n&apos;est pas requise mais si vous voulez une meilleure performance et plus de stabilité, nous vous recommandons de l&apos;installer.
+ <usetemplate name="okcancelbuttons" notext="Continuer" yestext="Télécharger"/>
+ </notification>
+ <notification name="DownloadLinuxMandatory">
+ Une nouvelle version de [APP_NAME] est disponible.
+[MESSAGE]
+Pour utiliser [APP_NAME], vous devez télécharger cette mise à jour.
+ <usetemplate name="okcancelbuttons" notext="Quitter" yestext="Télécharger"/>
+ </notification>
+ <notification name="DownloadLinux">
+ Une mise à jour de [APP_NAME] est disponible.
+[MESSAGE]
+Cette mise à jour n&apos;est pas requise mais si vous voulez une meilleure performance et plus de stabilité, nous vous recommandons de l&apos;installer.
+ <usetemplate name="okcancelbuttons" notext="Continuer" yestext="Télécharger"/>
+ </notification>
+ <notification name="DownloadLinuxReleaseForDownload">
+ Une mise à jour de [APP_NAME] est disponible.
[MESSAGE]
Cette mise à jour n&apos;est pas requise mais si vous voulez une meilleure performance et plus de stabilité, nous vous recommandons de l&apos;installer.
<usetemplate name="okcancelbuttons" notext="Continuer" yestext="Télécharger"/>
</notification>
<notification name="DownloadMacMandatory">
- Une nouvelle version de [SECOND_LIFE] est disponible.
+ Une nouvelle version de [APP_NAME] est disponible.
[MESSAGE]
-Pour utiliser [SECOND_LIFE] vous devez télécharger cette mise à jour.
+Pour utiliser [APP_NAME], vous devez télécharger cette mise à jour.
-Télécharger vers le dossier Applications ?
+Télécharger vers le dossier Applications ?
<usetemplate name="okcancelbuttons" notext="Quitter" yestext="Télécharger"/>
</notification>
<notification name="DownloadMac">
- Une mise à jour de [SECOND_LIFE] est disponible.
+ Une mise à jour de [APP_NAME] est disponible.
[MESSAGE]
Cette mise à jour n&apos;est pas requise mais si vous voulez une meilleure performance et plus de stabilité, nous vous recommandons de l&apos;installer.
-Télécharger vers le dossier Applications ?
+Télécharger vers le dossier Applications ?
<usetemplate name="okcancelbuttons" notext="Continuer" yestext="Télécharger"/>
</notification>
<notification name="DownloadMacReleaseForDownload">
- Une mise à jour de [SECOND_LIFE] est disponible.
+ Une mise à jour de [APP_NAME] est disponible.
[MESSAGE]
Cette mise à jour n&apos;est pas requise mais si vous voulez une meilleure performance et plus de stabilité, nous vous recommandons de l&apos;installer.
-Télécharger vers le dossier Applications ?
+Télécharger vers le dossier Applications ?
<usetemplate name="okcancelbuttons" notext="Continuer" yestext="Télécharger"/>
</notification>
<notification name="DeedObjectToGroup">
Si vous cédez cet objet, le groupe :
* recevra les L$ versés pour l&apos;objet ;
- <usetemplate ignoretext="Lors de la cession d&apos;objets au groupe" name="okcancelignore" notext="Annuler" yestext="Céder"/>
+ <usetemplate ignoretext="Confirmer avant que je ne cède un objet à un groupe" name="okcancelignore" notext="Annuler" yestext="Céder"/>
</notification>
<notification name="WebLaunchExternalTarget">
- Ouvrir votre navigateur web système pour afficher ce contenu ?
- <usetemplate ignoretext="Lors de l&apos;ouverture de votre navigateur système pour afficher une page web" name="okcancelignore" notext="Annuler" yestext="OK"/>
+ Voulez-vous ouvrir votre navigateur web système pour afficher ce contenu ?
+ <usetemplate ignoretext="Ouvrir mon navigateur pour consulter une page web" name="okcancelignore" notext="Annuler" yestext="OK"/>
</notification>
<notification name="WebLaunchJoinNow">
- Aller sur www.secondlife.com pour gérer votre compte ?
- <usetemplate ignoretext="Lors de l&apos;ouverture du navigateur web pour gérer votre compte" name="okcancelignore" notext="Annuler" yestext="OK"/>
- </notification>
- <notification name="WebLaunchBugReport101">
- Pour apprendre à signaler correctement des bugs, consultez le Wiki de [SECOND_LIFE].
- <usetemplate ignoretext="Lors de l&apos;ouverture du navigateur web pour consulter le Wiki et apprendre à signaler des bugs" name="okcancelignore" notext="Annuler" yestext="OK"/>
+ Accéder à votre [http://secondlife.com/account/ Page d&apos;accueil] pour gérer votre compte ?
+ <usetemplate ignoretext="Lancer mon navigateur pour gérer mon compte" name="okcancelignore" notext="Annuler" yestext="OK"/>
</notification>
<notification name="WebLaunchSecurityIssues">
Pour apprendre à signaler un problème de sécurité, consultez le Wiki de [SECOND_LIFE].
- <usetemplate ignoretext="Lors de l&apos;ouverture du navigateur web pour consulter la page Wiki sur les problèmes de sécurité." name="okcancelignore" notext="Annuler" yestext="OK"/>
+ <usetemplate ignoretext="Lancer mon navigateur pour apprendre comment signaler un problème de sécurité" name="okcancelignore" notext="Annuler" yestext="OK"/>
</notification>
<notification name="WebLaunchQAWiki">
Consultez le Wiki sur l&apos;Assurance Qualité de [SECOND_LIFE].
- <usetemplate ignoretext="Lors de l&apos;ouverture du navigateur web pour consulter la page Wiki sur l&apos;Assurance Qualité." name="okcancelignore" notext="Annuler" yestext="OK"/>
+ <usetemplate ignoretext="Lancer mon navigateur web pour consulter la page Wiki sur l&apos;Assurance Qualité." name="okcancelignore" notext="Annuler" yestext="OK"/>
</notification>
<notification name="WebLaunchPublicIssue">
Pour signaler des bugs et autres problèmes, utilisez le JIRA de [SECOND_LIFE].
- <usetemplate ignoretext="Lors de l&apos;ouverture du navigateur web pour consulter le JIRA" name="okcancelignore" notext="Annuler" yestext="Aller sur cette page"/>
- </notification>
- <notification name="WebLaunchPublicIssueHelp">
- Pour apprendre à utiliser JIRA, consultez le Wiki de [SECOND_LIFE].
- <usetemplate ignoretext="Lors de l&apos;ouverture du navigateur web pour consulter la page Wiki sur le JIRA" name="okcancelignore" notext="Annuler" yestext="Aller sur cette page"/>
+ <usetemplate ignoretext="Lancer mon navigateur pour utiliser le Public Issue Tracker (JIRA)" name="okcancelignore" notext="Annuler" yestext="Aller sur cette page"/>
</notification>
<notification name="WebLaunchSupportWiki">
Visitez le blog officiel des Lindens pour les dernières nouvelles et informations.
- <usetemplate ignoretext="Lors de l&apos;ouverture du navigateur web pour consulter le blog" name="okcancelignore" notext="Annuler" yestext="Aller à la page"/>
+ <usetemplate ignoretext="Lancer mon navigateur web pour consulter le blog" name="okcancelignore" notext="Annuler" yestext="Aller à la page"/>
</notification>
<notification name="WebLaunchLSLGuide">
- Consulter le Guide guide pour l&apos;écriture de scripts pour obtenir de l&apos;aide ?
- <usetemplate ignoretext="Lors de l&apos;ouverture du navigateur web pour voir le Guide pour l&apos;écriture de scripts" name="okcancelignore" notext="Annuler" yestext="OK"/>
+ Voulez-vous ouvrir le guide pour l&apos;écriture de scripts ?
+ <usetemplate ignoretext="Lancer mon navigateur web pour consulter le guide pour l&apos;écriture de scripts" name="okcancelignore" notext="Annuler" yestext="OK"/>
</notification>
<notification name="WebLaunchLSLWiki">
- Consulter le Wiki LSL pour de l&apos;aide sur les scripts ?
- <usetemplate ignoretext="Lors de l&apos;ouverture du navigateur web pour consulter le Guide sur l&apos;écriture de scripts" name="okcancelignore" notext="Annuler" yestext="Aller à la page"/>
+ Voulez-vous ouvrir le portail LSL pour l&apos;écriture de scripts ?
+ <usetemplate ignoretext="Lancer mon navigateur web pour consulter le portail LSL" name="okcancelignore" notext="Annuler" yestext="Aller à la page"/>
</notification>
<notification name="ReturnToOwner">
Êtes-vous certain de vouloir renvoyer les objets sélectionnés à leur propriétaire ? Les objets donnés transférables seront renvoyés à leur ancien propriétaire.
*Avertissement* Les objets non transférables seront supprimés !
- <usetemplate ignoretext="Lors du renvoi d&apos;objets à leurs propriétaires" name="okcancelignore" notext="Annuler" yestext="OK"/>
+ <usetemplate ignoretext="Confirmer avant de rendre les objets à leurs propriétaires" name="okcancelignore" notext="Annuler" yestext="OK"/>
</notification>
<notification name="GroupLeaveConfirmMember">
Vous êtes actuellement membre du groupe [GROUP].
@@ -1325,8 +1296,8 @@ Quitter le groupe ?
<notification name="CannotStartAuctionAlreadyForSale">
Vous ne pouvez pas démarrer des enchères sur une parcelle déjà en vente. Si vous êtes certain de vouloir démarrer des enchères, mettez fin à la vente.
</notification>
- <notification label="Échec de la fonction Ignorer les objets par nom" name="MuteByNameFailed">
- Vous ignorez déjà ce résident.
+ <notification label="L&apos;interdiction de l&apos;objet par nom a échoué." name="MuteByNameFailed">
+ Vous avez déjà interdit ce nom.
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="RemoveItemWarn">
@@ -1342,13 +1313,12 @@ Quitter le groupe ?
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="BusyModeSet">
- Mode occupé activé.
-Les chats et les messages instantanés ne s&apos;afficheront pas. Vous répondrez aux messages instantanés en utilisant la réponse automatique que vous avez créée. Toutes les propositions de téléportation seront refusées. Tous objets envoyés iront dans la corbeille.
- <usetemplate ignoretext="Lors de l&apos;utilisation du mode Occupé" name="okignore" yestext="OK"/>
+ Le mode Occupé est sélectionné.
+Les chats et les messages instantanés ne s&apos;afficheront pas. Les messages instantanés génèreront la réponse en mode occupé que vous avez créée. Toutes les offres de téléportation seront refusées. Toutes les offres d&apos;inventaire iront dans la corbeille.
+ <usetemplate ignoretext="Je change mon statut en mode Occupé" name="okignore" yestext="OK"/>
</notification>
<notification name="JoinedTooManyGroupsMember">
- Vous appartenez déjà à un nombre élevé de groupes et nous ne pouvez pas en rejoindre un nouveau. Avant de pouvoir rejoindre ce groupe, vous devez en quitter un ou refuser cette offre.
-Pour quitter un groupe, sélectionnez l&apos;option Groupe dans le menu Éditer.
+ Vous avez atteint le nombre de groupes maximum. Avant de pouvoir rejoindre ce groupe, vous devez en quitter un ou refuser cette offre.
[NAME] vous invite à rejoindre un groupe.
[INVITE]
<usetemplate name="okcancelbuttons" notext="Refuser" yestext="Rejoindre"/>
@@ -1356,7 +1326,7 @@ Pour quitter un groupe, sélectionnez l&apos;option Groupe dans le menu Éditer.
<notification name="KickUser">
Éjecter cet utilisateur avec quel message ?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Un administrateur vous a déconnecté.
</input>
<button name="OK" text="OK"/>
@@ -1366,7 +1336,7 @@ Pour quitter un groupe, sélectionnez l&apos;option Groupe dans le menu Éditer.
<notification name="KickAllUsers">
Éjecter tous les résidents actuellement en ligne avec quel message ?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Un administrateur vous a déconnecté.
</input>
<button name="OK" text="OK"/>
@@ -1376,7 +1346,7 @@ Pour quitter un groupe, sélectionnez l&apos;option Groupe dans le menu Éditer.
<notification name="FreezeUser">
Geler cet utilisateur avec quel message ?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Vous avez été gelé. Vous ne pouvez ni bouger ni chatter. Un administrateur va vous envoyer un message instantané (IM).
</input>
<button name="OK" text="OK"/>
@@ -1386,7 +1356,7 @@ Pour quitter un groupe, sélectionnez l&apos;option Groupe dans le menu Éditer.
<notification name="UnFreezeUser">
Dégeler cet utilisateur avec quel message ?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Vous n&apos;êtes plus gelé.
</input>
<button name="OK" text="OK"/>
@@ -1396,7 +1366,7 @@ Pour quitter un groupe, sélectionnez l&apos;option Groupe dans le menu Éditer.
<notification name="OfferTeleport">
Proposez une téléportation avec le message suivant ?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
On se rejoint à [REGION] ?
</input>
<button name="OK" text="OK"/>
@@ -1406,7 +1376,7 @@ Pour quitter un groupe, sélectionnez l&apos;option Groupe dans le menu Éditer.
<notification name="OfferTeleportFromGod">
Demander au résident de venir vous rejoindre ?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
On se rejoint à [REGION] ?
</input>
<button name="OK" text="OK"/>
@@ -1415,12 +1385,20 @@ Pour quitter un groupe, sélectionnez l&apos;option Groupe dans le menu Éditer.
</notification>
<notification name="TeleportFromLandmark">
Êtes-vous certain de vouloir être téléporté ?
- <usetemplate ignoretext="Lors de la téléportation depuis un repère de l&apos;inventaire" name="okcancelignore" notext="Annuler" yestext="Téléporter"/>
+ <usetemplate ignoretext="Confirmer que je veux me téléporter à un repère" name="okcancelignore" notext="Annuler" yestext="Téléporter"/>
+ </notification>
+ <notification name="TeleportToPick">
+ Vous téléporter vers [PICK] ?
+ <usetemplate ignoretext="Confirmer que je veux me téléporter à un endroit dans mes Favoris" name="okcancelignore" notext="Annuler" yestext="Téléporter"/>
+ </notification>
+ <notification name="TeleportToClassified">
+ Vous téléporter vers [CLASSIFIED] ?
+ <usetemplate ignoretext="Confirmer que je veux me téléporter à un endroit dans les Petites annonces" name="okcancelignore" notext="Annuler" yestext="Téléporter"/>
</notification>
<notification label="Envoyer un message à tout le monde dans votre domaine" name="MessageEstate">
Saisissez un message court qui sera envoyé à tous les résidents se trouvant actuellement sur votre domaine.
<form name="form">
- <input name="message" type="text"/>
+ <input name="message"/>
<button name="OK" text="OK"/>
<button name="Cancel" text="Annuler"/>
</form>
@@ -1491,9 +1469,9 @@ Vérifiez que vous avez la toute dernière version du client et consultez les pa
Souhaitez-vous en savoir plus sur les différentes catégories d&apos;accès ?
<url name="url">
- http://wiki.secondlife.com/wiki/Pr%C3%A9sentation_des_cat%C3%A9gories_de_contenu_(KB)
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview/fr
</url>
- <usetemplate ignoretext="Lorsque l&apos;accès à une région est bloqué à cause de la catégorie d&apos;accès" name="okcancelignore" notext="Fermer" yestext="Consulter les pages d&apos;aide"/>
+ <usetemplate ignoretext="Je ne peux pas pénétrer dans cette région car je n&apos;ai pas accès à cette catégorie de contenu" name="okcancelignore" notext="Fermer" yestext="Consulter les pages d&apos;aide"/>
</notification>
<notification name="RegionEntryAccessBlocked_Notify">
Votre catégorie d&apos;accès ne vous permet pas de pénétrer dans cette région.
@@ -1501,17 +1479,12 @@ Souhaitez-vous en savoir plus sur les différentes catégories d&apos;accès ?
<notification name="RegionEntryAccessBlocked_Change">
Votre catégorie d&apos;accès ne vous permet pas de pénétrer dans cette région.
-En cliquant sur Modifier les préférences, vous pourrez changer votre catégorie d&apos;accès et pénétrer dans la région. À partir de maintenant, vous pouvez rechercher et accéder au contenu [REGIONMATURITY]. Vous pouvez modifier ce paramètre à partir du menu Édition &gt; Préférences... &gt; Général.
- <form name="form">
- <button
- name="OK"
- text="Modifier les Préférences"/>
- <button
- default="true"
- name="Cancel"
- text="Fermer"/>
- <ignore name="ignore" text="Lorsque l&apos;accès à une région est bloqué à cause des préférences concernant la catégorie d&apos;accès"/>
- </form>
+En cliquant sur Modifier les préférences, vous pourrez changer votre catégorie d&apos;accès et pénétrer dans la région. À partir de maintenant, vous pouvez rechercher et accéder au contenu [REGIONMATURITY]. Vous pouvez modifier ce paramètre à partir du menu Moi &gt; Préférences &gt; Général.
+ <form name="form">
+ <button name="OK" text="Modifier les préférences"/>
+ <button default="true" name="Cancel" text="Fermer"/>
+ <ignore name="ignore" text="La catégorie de contenu que j&apos;ai choisie m&apos;empêche de pénétrer dans une région"/>
+ </form>
</notification>
<notification name="LandClaimAccessBlocked">
Votre catégorie d&apos;accès ne vous permet pas de réclamer cette région. Cela vient peut-être du fait qu&apos;il manquait des informations pour valider votre âge.
@@ -1524,9 +1497,9 @@ Vérifiez que vous avez la toute dernière version du client et consultez les pa
Souhaitez-vous en savoir plus sur les différentes catégories d&apos;accès ?
<url name="url">
- http://wiki.secondlife.com/wiki/Pr%C3%A9sentation_des_cat%C3%A9gories_de_contenu_(KB)
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview/fr
</url>
- <usetemplate ignoretext="Lorsqu&apos;une région ne peut pas être réclamée à cause de la catégorie d&apos;accès" name="okcancelignore" notext="Fermer" yestext="Consulter les pages d&apos;aide"/>
+ <usetemplate ignoretext="Je ne peux pas réclamer cette région car je n&apos;ai pas accès à cette catégorie de contenu" name="okcancelignore" notext="Fermer" yestext="Consulter les pages d&apos;aide"/>
</notification>
<notification name="LandClaimAccessBlocked_Notify">
Votre catégorie d&apos;accès ne vous autorise pas à réclamer cette région.
@@ -1534,8 +1507,8 @@ Souhaitez-vous en savoir plus sur les différentes catégories d&apos;accès ?
<notification name="LandClaimAccessBlocked_Change">
Votre catégorie d&apos;accès ne vous permet pas de réclamer cette région.
-En cliquant sur Modifier les préférences, vous pourrez changer votre catégorie d&apos;accès et pénétrer dans la région. À partir de maintenant, vous pouvez rechercher et accéder au contenu [REGIONMATURITY]. Vous pouvez modifier ce paramètre à partir du menu Édition &gt; Préférences... &gt; Général.
- <usetemplate ignoretext="Lorsqu&apos;une région ne peut pas être réclamée à cause des préférences concernant la catégorie d&apos;accès" name="okcancelignore" notext="Fermer" yestext="Modifier les Préférences"/>
+En cliquant sur Modifier les préférences, vous pourrez changer votre catégorie d&apos;accès et pénétrer dans la région. À partir de maintenant, vous pouvez rechercher et accéder au contenu [REGIONMATURITY]. Vous pouvez modifier ce paramètre à partir du menu Moi &gt; Préférences &gt; Général.
+ <usetemplate ignoretext="La catégorie de contenu que j&apos;ai choisie m&apos;empêche de réclamer un terrain" name="okcancelignore" notext="Fermer" yestext="Modifier les Préférences"/>
</notification>
<notification name="LandBuyAccessBlocked">
Votre catégorie d&apos;accès ne vous permet pas d&apos;acheter cette région. Cela vient peut-être du fait qu&apos;il manquait des informations pour valider votre âge.
@@ -1548,9 +1521,9 @@ Vérifiez que vous avez la toute dernière version du client et consultez les pa
Souhaitez-vous en savoir plus sur les différentes catégories d&apos;accès ?
<url name="url">
- http://wiki.secondlife.com/wiki/Pr%C3%A9sentation_des_cat%C3%A9gories_de_contenu_(KB)
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview/fr
</url>
- <usetemplate ignoretext="Lorsqu&apos;une région ne peut pas être achetée à cause de la catégorie d&apos;accès" name="okcancelignore" notext="Fermer" yestext="Consulter les pages d&apos;aide"/>
+ <usetemplate ignoretext="Je ne peux pas acheter ce terrain car je n&apos;ai pas accès à cette catégorie de contenu" name="okcancelignore" notext="Fermer" yestext="Consulter les pages d&apos;aide"/>
</notification>
<notification name="LandBuyAccessBlocked_Notify">
Votre catégorie d&apos;accès ne vous permet pas d&apos;acheter cette région.
@@ -1558,11 +1531,12 @@ Souhaitez-vous en savoir plus sur les différentes catégories d&apos;accès ?
<notification name="LandBuyAccessBlocked_Change">
Votre catégorie d&apos;accès ne vous autorise pas à acheter cette région.
-En cliquant sur Modifier les préférences, vous pourrez changer votre catégorie d&apos;accès et pénétrer dans la région. À partir de maintenant, vous pouvez rechercher et accéder au contenu [REGIONMATURITY]. Vous pouvez modifier ce paramètre à partir du menu Édition &gt; Préférences... &gt; Général.
- <usetemplate ignoretext="Lorsqu&apos;une région ne peut pas être achetée à cause des préférences concernant la catégorie d&apos;accès" name="okcancelignore" notext="Fermer" yestext="Modifier les Préférences"/>
+En cliquant sur Modifier les préférences, vous pourrez changer votre catégorie d&apos;accès et pénétrer dans la région. À partir de maintenant, vous pouvez rechercher et accéder au contenu [REGIONMATURITY]. Vous pouvez modifier ce paramètre à partir du menu Moi &gt; Préférences &gt; Général.
+ <usetemplate ignoretext="La catégorie de contenu que j&apos;ai choisie m&apos;empêche d&apos;acheter un terrain" name="okcancelignore" notext="Fermer" yestext="Modifier les Préférences"/>
</notification>
<notification name="TooManyPrimsSelected">
- &quot;Vous avez sélectionné trop de prims. Veuillez sélectionner au maximum [MAX_PRIM_COUNT] prims et réessayer.&quot;
+ Vous avez sélectionné trop de prims. Veuillez sélectionner au maximum [MAX_PRIM_COUNT] prims et réessayer.
+ <usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="ProblemImportingEstateCovenant">
Problème lors de l&apos;importation du règlement du domaine.
@@ -1576,6 +1550,7 @@ En cliquant sur Modifier les préférences, vous pourrez changer votre catégori
</notification>
<notification name="UnableToLoadNotecardAsset">
Impossible de charger les données de la note actuellement.
+ <usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="NotAllowedToViewNotecard">
Permissions pour afficher la note insuffisantes.
@@ -1606,226 +1581,17 @@ Publier cette petite annonce maintenant pour [AMOUNT] L$ ?
<notification label="Envoyer un message à la région" name="MessageRegion">
Saisissez une message qui sera envoyé à tous les résidents présents dans cette région.
<form name="form">
- <input name="message" type="text"/>
+ <input name="message"/>
<button name="OK" text="OK"/>
<button name="Cancel" text="Annuler"/>
</form>
</notification>
- <notification label="Interdire le terraformage" name="HelpRegionBlockTerraform">
- Si vous cochez cette case, les propriétaires ne pourront plus terraformer leur terrain, quel que soit le paramétrage individuel des parcelles.
-
-Valeur par défaut : désactivé
- </notification>
- <notification label="Interdire le vol" name="HelpRegionBlockFly">
- Si vous cochez cette case, les résidents ne pourront plus voler dans cette région, quel que soit le paramétrage individuel des parcelles.
-
-Valeur par défaut : désactivé
- </notification>
- <notification label="Modifications groupées des droits relatifs au contenu" name="HelpBulkPermission">
- L&apos;outil Modifications groupées des droits vous permet de modifier rapidement et simultanément les droits dans les contenus des objets séléctionnés. Notez toutefois que vous paramétrez uniquement les droits des objets dans les Contenus des objets sélectionnés, et non les droits sur les objets eux-mêmes.
-
-Notez aussi que les droits ne s&apos;appliquent pas aux contenus imbriqués dans les objets contenus. Votre requête ne porte que sur les objets de premier niveau.
-
-Vous pouvez sélectionner quels types d&apos;objets modifier à la section Types de contenu. Les photos sont incluses quand vous sélectionnez Textures.
-
-* Cet outil ne vous permettra de changer que les droits des objets que vous êtes autorisés à modifier.
-* Vous ne pouvez pas accorder de droits que vous n&apos;avez pas au prochain propriétaire.
-* Les droits accordés au prochain propriétaire de sont que des requêtes. Si un objet ne peut recevoir tous les nouveaux droits, aucun de ses droits ne changera.
-
-Lorsque vous êtes prêt à modifier tous les droits, cliquez sur Appliquer et attendez de voir s&apos;afficher les résultats.
-
-Si vous fermez la fenêtre des modifications groupées alors que les droits sont en train d&apos;être modifiés, vous suspendez l&apos;opération.
- </notification>
- <notification label="Autoriser les dégâts" name="HelpRegionAllowDamage">
- Si vous cochez cette case, les résidents peuvent subir des dégâts dans toute la région quel que soit le paramétrage individuel des parcelles. Si la case n&apos;est pas cochée, les propriétaires sont libres d&apos;activer ou non cette option sur leur parcelle.
-
-Valeur par défaut : désactivé
- </notification>
- <notification label="Nombre maximum d&apos;avatars" name="HelpRegionAgentLimit">
- Définit le nombre maximum d&apos;avatars autorisés dans cette région.
-La performance peut varier en fonction du nombre d&apos;avatars présents.
-
-Valeur par défaut : 40
- </notification>
- <notification label="Bonus objet" name="HelpRegionObjectBonus">
- Le bonus objet est le multiplicateur de prims autorisées sur une parcelle donnée. L&apos;échelle autorisée est comprise entre 1 et 10. Lorsque ce chiffre est de 1, chaque parcelle de 512 m² peut contenir 117 prims. S&apos;il est de 2, chaque parcelle peut contenir 234 prims, ou deux fois plus, et ainsi de suite. Le nombre maximum de prims autorisées dans une région est de 15 000, quel que soit le bonus objet. Attention : si vous définissez un bonus objet et décidez ensuite de le diminuer, cela peut entraîner la suppression ou le renvoi d&apos;objets.
-
-Valeur par défaut : 1.0
- </notification>
- <notification label="Accès" name="HelpRegionMaturity">
- Définit la catégorie d&apos;accès de la région, telle qu&apos;affichée dans la barre de menu en haut du client et dans les infobulles de la carte lorsque vous passez votre curseur au-dessus de cette région. Ce paramètre affecte aussi l&apos;accès à cette région et les résultats de recherche. Les autres résidents ne peuvent pénétrer que dans les régions ou n&apos;afficher que les résultats de recherche ayant la même catégorie d&apos;accès que celle indiquée dans leurs Préférences.
-
-Ce changement n&apos;apparaîtra pas immédiatement sur la carte.
- </notification>
- <notification label="Interdire les bousculades" name="HelpRegionRestrictPushObject">
- Cette case permet de restreindre les bousculades dans toute une région.
-Lorsqu&apos;elle est cochée, les résidents ne peuvent être bousculés que par d&apos;autres résidents ou par le propriétaire de la parcelle.
-(Bousculer fait référence à la fonction LSL llPushObjet().)
-
-Valeur par défaut : désactivé
- </notification>
- <notification label="Fusionner/Diviser des parcelles" name="HelpParcelChanges">
- Cette case permet de choisir si les parcelles n&apos;appartenant pas au gérant du domaine peuvent ou pas être fusionnées ou divisées.
-Si cette case n&apos;est pas cochée :
- * Seuls les propriétaires ou gérants de domaine peuvent fusionner ou diviser des parcelles.
- * Ils ne peuvent fusionner ou diviser que les parcelles du propriétaire,
- ou celles d&apos;un groupe dans lequel ils ont les pouvoirs nécessaires.
- Si cette case est cochée :
- * Tous les propriétaires peuvent fusionner ou diviser leurs parcelles.
- * Pour les parcelles appartenant à un groupe, les membres avec les pouvoirs nécessaires peuvent fusionner ou diviser les parcelles.
-
-Valeur par défaut : activée
- </notification>
- <notification label="Ne pas afficher dans la recherche" name="HelpRegionSearch">
- Si vous cochez cette option, les propriétaires ne pourront pas faire apparaître leurs parcelles dans les résultats de recherche.
-Valeur par défaut : désactivé
- </notification>
<notification label="Catégorie de la région modifiée" name="RegionMaturityChange">
La catégorie d&apos;accès de cette région a été mise à jour.
Ce changement n&apos;apparaîtra pas immédiatement sur la carte.
</notification>
- <notification label="Revente de terrain" name="HelpRegionLandResell">
- Les propriétaires et gérants de domaine peuvent vendre n&apos;importe quel terrain appartenant au propriétaire du domaine.
-Si cette option n&apos;est pas cochée, les propriétaires ne peuvent pas revendre leur parcelle.
-Si cette option est cochée, les propriétaires sont libres de revendre leur parcelle.
-
-Valeur par défaut : désactivé
- </notification>
- <notification label="Désactiver les scripts" name="HelpRegionDisableScripts">
- Lorsque la performance d&apos;une région est faible, cela peut venir d&apos;un script. Ouvrez la section Statistiques (Ctrl-Maj-1) et vérifiez le FPS Physique (Physics FPS) de la section Simulateur.
-Si le FPS est en dessous de 45, ouvrez la section Time située en fin de liste. Si le Script Time est au dessus de 25ms, cliquez sur le bouton Afficher les objets scriptés les plus consommateurs. Vous verrez le nom et l&apos;emplacement des scripts éventuellement à l&apos;origine du problème.
-
-Si vous cochez la case Désactiver les scripts et que vous appuyez sur Appliquer, tous les scripts de cette région seront temporairement désactivés. Vous devrez peut-être faire cela le temps d&apos;arriver à l&apos;endroit su script en cause. Une fois sur place, assurez-vous que le script est bien à l&apos;origine du problème. Pour cela, vous devrez peut-être contacter le propriétaire du script ou bien supprimer ou renvoyer l&apos;objet.
-Décochez la case Désactiver le script, puis cliquez sur Appliquer pour réactiver tous les scripts dans la région.
-
-Valeur par défaut : désactivé
- </notification>
- <notification label="Désactiver les collisions" name="HelpRegionDisableCollisions">
- Des objets physiques peuvent fortement réduire les performances d&apos;une région.
-Ouvrez la barre de statistiques (Ctrl-Maj-1) et vérifiez le FPS Physique (Physics FPS) de la section Simulateur.
-Si le FPS est en dessous de 45, ouvrez la section Time située en fin de liste. Si le Script Time est au dessus de 25ms, cliquez sur le bouton Afficher les collisions les plus consommatrices.
-Vous verrez le nom et l&apos;emplacement des objets physiques éventuellement à l&apos;origine du problème.
-
-Si vous décochez la case Désactiver les collisions et que vous cliquez sur Appliquer, toutes les collisions entre objets seront désactivées. Vous pourrez avoir besoin de cette fonction le temps d&apos;arriver à l&apos;emplacement des objets en cause. Une fois sur place, vérifiez que l&apos;&apos;objet est bien responsable du problème (entre-t-il sans cesse en collision avec d&apos;autres objets ?) Pour cela, vous devrez peut-être contacter le propriétaire de l&apos;objet ou bien supprimer ou renvoyer l&apos;objet.
-Décochez la case Désactiver les collisions, puis cliquez sur le bouton Appliquer pour réactiver les collisions dans la région.
-
-Valeur par défaut : désactivé
- </notification>
- <notification label="Désactiver la physique" name="HelpRegionDisablePhysics">
- L&apos;option Désactiver la physique est similaire à l&apos;option Désactiver les collisions sauf qu&apos;elle englobe tous les effets liés à la physique. Cela signifie que les objets n&apos;entreront plus en collision et que les avatars ne pourront plus bouger.
-
-Vous ne devriez utiliser cette option que lorsque l&apos;option Désactiver les collisions n&apos;améliore pas sufisamment la performance de la région pour résoudre un problème de physique ou trouver les objets entrant en collision.
-
-Une fois que vous avez fini, n&apos;oubliez pas de réactiver les propriétés physiques sinon les avatars ne pourront pas bouger.
-
-Valeur par défaut : désactivé
- </notification>
- <notification label="Afficher les collisions les plus consommatrices" name="HelpRegionTopColliders">
- Montre une liste des objets générant le plus de collisions avec d&apos;autres objets. Ces objets peuvent ralentir les performances de votre région. Sélectionnez Affichage &gt; Statistiques et regardez sous Simulator &gt; Time &gt; Sim Time (Physics) pour voir si le temps du moteur physique est au dessus de 20 ms.
- </notification>
- <notification label="Afficher les objets scriptés les plus consommateurs" name="HelpRegionTopScripts">
- Dresse une liste des objets dont les scripts consomment le plus de ressources. Ces objets peuvent ralentir la performance de votre région.
-Sélectionnez Affichage &gt; Statistiques et regardez sous Simulator &gt; Time &gt; Script Time pour voir si le temps des scripts est au dessus de 25 ms.
- </notification>
- <notification label="Redémarrer la région" name="HelpRegionRestart">
- Redémarre le serveur en charge de la région après deux minutes d&apos;avertissement. Tous les résidents dans cette région seront déconnectés. Les données de la région seront sauvegardées et réapparaîtront au bout de 90 secondes.
-
-Le redémarrage de la région ne permet pas de résoudre la plupart des problèmes de performance. Les redémarrages ne doivent avoir lieu qu&apos;en dernier recours.
- </notification>
- <notification label="Niveau de l&apos;eau" name="HelpRegionWaterHeight">
- Il s&apos;agit de la hauteur de l&apos;eau en mètres.
-Si ce paramètre est différent de 20 et que vous avez de l&apos;eau adjacente au bord du monde ou de l&apos;eau « vide », il y aura un espace vide visible.
-
-
-Valeur par défaut : 20
- </notification>
- <notification label="Surélévation du terrain" name="HelpRegionTerrainRaise">
- Il s&apos;agit de la distance (en mètres) à laquelle les propriétaires de parcelle peuvent surélever leur terrain, par rapport au terrain « figé » dont la hauteur est fixée par défaut.
-
-Valeur par défaut : 4
- </notification>
- <notification label="Abaisser le terrain" name="HelpRegionTerrainLower">
- Il s&apos;agit de la distance (en mètres) à laquelle les propriétaires de parcelle peuvent abaisser leur terrain, par rapport au terrain « figé » dont la hauteur est fixée par défaut.
-
-Valeur par défaut : -4
- </notification>
- <notification label="Charger le terrain au format RAW" name="HelpRegionUploadRaw">
- Ce bouton permet de charger un fichier .RAW dans la région où vous vous trouvez.
-Ce fichier doit avoir les bonnes dimensions (RGB, 256 x 256) et 13 canaux. Le meilleur moyen de créer un fichier terrain est de télécharger le fichier RAW existant. Un bon moyen est de modifier le canal rouge (hauteur terrain) et de le charger.
-
-Le chargement peut prendre jusqu&apos;à 45 secondes. Veuillez noter que le chargement d&apos;un fichier terrain ne déplacera pas les objets qui se trouvent sur le terrain, mais seulement le terrain et les droits associés aux parcelles. Certains objets risquent d&apos;aller sous la terre.
-
-Pour en savoir plus sur la modification de la hauteur des terrains d&apos;une région, consultez l&apos;Aide F1.
- </notification>
- <notification label="Télécharger le terrain au format RAW" name="HelpRegionDownloadRaw">
- Ce bouton permet de télécharger un fichier contenant les données relatives à la hauteur du terrain, dimensions de la parcelle, les mises en vente ainsi que certains droits relatifs à la parcelle pour cette région. Lorsque vous ouvrez le fichier avec un programme tel que Photoshop, vous devez indiquer les dimensions du document qui sont les suivantes : RGB, 256 x 256 avec 13 canaux. Le fichier terrain ne peut pas être ouvert différemment.
-
-Pour en savoir plus sur la modification de la hauteur des terrains d&apos;une région, consultez l&apos;Aide F1.
- </notification>
- <notification label="Utiliser le soleil du domaine" name="HelpRegionUseEstateSun">
- Si vous cochez cette case, la position du soleil dans cette région sera la même que dans le reste du domaine.
-
-Valeur par défaut : activé
- </notification>
- <notification label="Soleil fixe" name="HelpRegionFixedSun">
- Si vous cochez cette case, la position du soleil se fixe sur celle du curseur Phase et le soleil arrête de bouger.
-
-Valeur par défaut : désactivé
- </notification>
- <notification label="Figer le terrain" name="HelpRegionBakeTerrain">
- Ce bouton permet d&apos;enregistrer la forme actuelle du terrain comme nouvelle forme par défaut pour la région. Une fois figé, le terrain peut reprendre la forme enregistrée à partir de l&apos;option Rétablir le terrain à la section Modifer le terrain. Le terrain figé est aussi le point de référence pour les limites de surélévation et d&apos;abaissement.
- </notification>
- <notification label="Gérants du domaine" name="HelpEstateEstateManager">
- Un gérant de domaine est un résident chargé du contrôle de la région et des paramètres du domaine. Un gérant de domaine peut modifier tous les paramètres, mais ne peut pas charger, télécharger ni figer de terrain. Un des pouvoirs principaux du gérant est de bannir ou d&apos;autoriser un résident sur votre domaine.
-
-Seuls les propriétaires de domaine peuvent ajouter ou supprimer des gérants de domaine. Lorsque vous choisissez un gérant de domaine, prenez un résident en qui vous avez confiance car vous serez en quelque sorte responsable de ses actions.
- </notification>
- <notification label="Utiliser le temps universel" name="HelpEstateUseGlobalTime">
- Cette case permet au soleil de votre domaine de suivre la position du soleil sur les domaines Linden du continent.
-
-Valeur par défaut : activé
- </notification>
- <notification label="Soleil fixe" name="HelpEstateFixedSun">
- Si vous cochez cette case, la position du soleil se fixe sur celle du curseur Phase et le soleil arrête de bouger.
- </notification>
- <notification label="Accès public" name="HelpEstateExternallyVisible">
- Cette option vous permet de choisir quels résidents d&apos;autres domaines peuvent pénétrer sur votre domaine sans devoir être ajoutés à la liste d&apos;accès.
-
-Valeur par défaut : activé
- </notification>
- <notification label="Autoriser la téléportation directe" name="HelpEstateAllowDirectTeleport">
- Lorsqu&apos;elle est cochée, cette option permet aux résidents d&apos;être téléportés à n&apos;importe quel endroit sur votre domaine. Lorsque cette option n&apos;est pas cochée, les résidents sont téléportés au téléhub le plus proche.
-
-Valeur par défaut : désactivé
- </notification>
- <notification label="Autoriser l&apos;accès" name="HelpEstateAllowResident">
- L&apos;accès à ce domaine sera réservé aux résidents figurant dans cette liste et aux groupes ci-dessous.
-Cette option n&apos;est disponible que lorsque la case Accès public est décochée.
- </notification>
- <notification label="Autoriser l&apos;accès de groupe" name="HelpEstateAllowGroup">
- L&apos;accès à ce domaine sera réservé aux groupes figurant dans cette liste et aux résidents ci-dessous. Cette option n&apos;est disponible que lorsque la case Accès public est décochée.
- </notification>
- <notification label="Adresse e-mail où signaler une infraction" name="HelpEstateAbuseEmailAddress">
- Si vous utilisez une adresse e-mail valide, les rapports d&apos;infraction de ce domaine iront à cette adresse.
-Si vous laissez ce champ vide, les rapports d&apos;infraction seront envoyés à Linden Lab uniquement.
- </notification>
- <notification label="Refuser l&apos;accès" name="HelpEstateBanResident">
- Les résidents figurant sur cette liste ne peuvent pas pénétrer sur votre domaine, quels que soient les autres paramètres.
- </notification>
- <notification label="Autoriser les chats vocaux" name="HelpEstateVoiceChat">
- Les parcelles de ce domaine peuvent avoir leurs propres canaux vocaux, ce qui permet aux résidents de communiquer avec leurs voisins.
-
-Valeur par défaut : désactivé
- </notification>
<notification label="Versions de voix non compatibles" name="VoiceVersionMismatch">
- Cette version de Second Life n&apos;est pas compatible avec la fonctionnalité de chat vocal dans cette région. Vous devez mettre à jour Second Life pour que le chat vocal fonctionne correctement.
- </notification>
- <notification label="Règlement du domaine" name="HelpEstateCovenant">
- Définir un règlement pour le domaine vous permet de vendre les parcelles de ce domaine. S&apos;il n&apos;y a pas de règlement, vous ne pouvez pas vendre le terrain. Si vous ne souhaitez pas indiquer de règlement ou donner de conseils aux acheteurs, laissez la section relative au règlement vide.
-
-Un règlement sert à communiquer des règles, des lignes directrices ou informations culturelles, ou simplement à expliquer vos attentes à un acheteur potentiel. Il peut s&apos;agir de régulations concernant la construction, les options de paiement ou tout autre information que vous souhaitez faire passer au résident avant que l&apos;achat n&apos;ait lieu.
-
-L&apos;acheteur est tenu d&apos;accepter le règlement en cochant une case avant de pouvoir finaliser l&apos;achat. Les règlements, lorsqu&apos;ils existent, apparaissent toujours dans la boîte de dialogue À propos du terrain.
+ Cette version de [APP_NAME] n&apos;est pas compatible avec la fonctionnalité de chat vocal dans cette région. Vous devez mettre à jour [APP_NAME] pour que le chat vocal fonctionne correctement.
</notification>
<notification label="Impossible d&apos;acheter des objets" name="BuyObjectOneOwner">
Impossible d&apos;acheter simultanément des objets de propriétaires différents.
@@ -1892,7 +1658,7 @@ Ils seront copiés dans votre inventaire.
Êtes-vous certain de vouloir effectuer cette transaction ?
<usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
</notification>
- <notification name="ConfirmPurchasePassword" type="password">
+ <notification name="ConfirmPurchasePassword">
Suite à cette transaction, vous allez :
[ACTION]
@@ -1913,76 +1679,51 @@ vous avez mis à jour l&apos;emplacement de ce favori mais les autres détails r
Ces objets seront déplacés dans votre inventaire et non pas copiés.
Déplacer les objets de l&apos;inventaire ?
- <usetemplate ignoretext="Lors du transfert d&apos;un inventaire non copiable depuis des objets" name="okcancelignore" notext="Annuler" yestext="OK"/>
+ <usetemplate ignoretext="M&apos;avertir avant que je ne déplace des objets pour lesquels la copie est interdite" name="okcancelignore" notext="Annuler" yestext="OK"/>
</notification>
<notification name="MoveInventoryFromScriptedObject">
Vous avez sélectionné des objets de l&apos;inventaire qui ne peuvent pas être copiés. Ces objets seront déplacés vers votre inventaire, et non pas copiés.
L&apos;objet les contenant est scripté, déplacer ces objets peut causer des problèmes au niveau du script.
Déplacer les objets de l&apos;inventaire ?
- <usetemplate ignoretext="Lors du transfert d&apos;un inventaire non copiable depuis des objets scriptés" name="okcancelignore" notext="Annuler" yestext="OK"/>
+ <usetemplate ignoretext="M&apos;avertir avant que je ne déplace des objets pour lesquels la copie est interdite et qui pourraient casser des objets scriptés" name="okcancelignore" notext="Annuler" yestext="OK"/>
</notification>
<notification name="ClickActionNotPayable">
- Avertissement : l&apos;action du clic Payer l&apos;objet a été défini mais ne fonctionnera que si un script est ajouté avec l&apos;event money().
+ Avertissement : l&apos;action du clic Payer l&apos;objet a été définie mais ne fonctionnera que si un script est ajouté avec l&apos;event money().
<form name="form">
- <ignore name="ignore" text="Lors du paramétrage de la fonction Payer sur des objets sans événement monétaire"/>
+ <ignore name="ignore" text="Je définis l&apos;action du clic Payer l&apos;objet lorsque je construis un objet sans le script money()"/>
</form>
</notification>
<notification name="OpenObjectCannotCopy">
Vous n&apos;êtes autorisé à copier aucun élément dans cet objet.
</notification>
<notification name="WebLaunchAccountHistory">
- Aller sur le site de Second Life pour consulter l&apos;historique de votre compte ?
- <usetemplate ignoretext="Lors du chargement de la page web contenant l&apos;historique de votre compte" name="okcancelignore" notext="Annuler" yestext="Aller sur cette page"/>
- </notification>
- <notification name="ClickOpenF1Help">
- Visiter les pages d&apos;aide de Second Life ?
- <usetemplate ignoretext="Lors de la visite des pages d&apos;aide de Second Life" name="okcancelignore" notext="Annuler" yestext="Aller"/>
+ Accéder à votre [http://secondlife.com/account/ Page d&apos;accueil] pour consulter l&apos;historique de votre compte ?
+ <usetemplate ignoretext="Lancer mon navigateur pour consulter l&apos;historique de mon compte" name="okcancelignore" notext="Annuler" yestext="Aller sur cette page"/>
</notification>
<notification name="ConfirmQuit">
Êtes-vous certain de vouloir quitter ?
- <usetemplate ignoretext="Lorsque vous quittez Second Life" name="okcancelignore" notext="Continuer" yestext="Quitter"/>
+ <usetemplate ignoretext="Confirmer avant de quitter" name="okcancelignore" notext="Ne pas quitter" yestext="Quitter"/>
</notification>
<notification name="HelpReportAbuseEmailLL">
- Utilisez cet outil pour signaler des infractions aux Conditions d&apos;utilisation et aux Règles de la communauté. Voir :
-
-http://secondlife.com/corporate/tos.php
-http://secondlife.com/corporate/cs.php
+ Utilisez cet outil pour signaler des infractions aux [http://secondlife.com/corporate/tos.php Conditions d&apos;utilisation] et aux [http://secondlife.com/corporate/cs.php Règles communautaires].
-Lorsqu&apos;elles sont signalées, toutes les infractions aux Conditions d&apos;utilisation et aux Règles de la communauté font l&apos;objet d&apos;une enquête et sont résolues. Pour accéder aux détails de la résolution d&apos;un incident, allez sur :
-
-http://secondlife.com/support/incidentreport.php
+Lorsqu&apos;elles sont signalées, toutes les infractions font l&apos;objet d&apos;une enquête et sont résolues. Vous pouvez consulter les détails de la résolution d&apos;un incident dans le [http://secondlife.com/support/incidentreport.php Rapport d&apos;incident].
</notification>
<notification name="HelpReportAbuseEmailEO">
- Important : ce rapport ira au propriétaire de la région dans laquelle vous êtes et non à Linden Lab.
-
-Pour aider les résidents et les visiteurs, le propriétaire de la région dans laquelle vous êtes a choisi de recevoir et de s&apos;occuper de tous les rapports envoyés à partir de cette région. Linden Lab n&apos;enquêtera pas sur les rapports que vous envoyez à partir de cet endroit.
-
-Le propriétaire de la région traitera les rapports en fonction des règles de cette région, comme indiqué dans le réglement du domaine.
-(Les réglements sont visibles à partir du menu Monde &gt; À propos du terrain.)
-
-La résolution de ce rapport ne s&apos;applique qu&apos;à cette région ; L&apos;accès aux autres endroits de Second Life ne sera pas affecté par les résultats de cette enquête. Seul Linden Lab peut interdire l&apos;accès à l&apos;ensemble de Second Life.
- </notification>
- <notification name="HelpReportBug">
- N&apos;utilisez cet outil que pour signaler des problèmes techniques et soyez aussi précis que possible.
-Vous pouvez répondre à l&apos;e-mail automatique pour ajouter des détails à votre rapport.
-
-Tous les bugs signalés sont reproduits et évalués. Aucune réponse ne sera envoyée par e-mail.
+ IMPORTANT : ce rapport sera envoyé au propriétaire de la région dans laquelle vous vous trouvez actuellement et non à Linden Lab.
-Si vous avez un problème technique, veuillez contacter le service clientèle à :
+Pour rendre service aux résidents et visiteurs, le propriétaire de la région dans laquelle vous vous trouvez a choisi de recevoir et de résoudre tous les rapports concernant cette région. Linden Lab n&apos;enquêtera pas sur les rapports que vous envoyez depuis cet emplacement.
-http://secondlife.com/community/support.php
+Le propriétaire de la région résoudra les incidents signalés dans les rapports selon les règles locales de cette région, telles qu&apos;elles sont définies dans le règlement du domaine.
+(Pour consulter les règlements, sélectionnez À propos des terrains dans le menu Monde.)
-Remarque : les rapports incomplets ne feront pas l&apos;objet d&apos;une enquête.
+La résolution de ce rapport ne s&apos;applique qu&apos;à cette région. L&apos;accès des résidents aux autres zones de [SECOND_LIFE] ne sera pas affecté par l&apos;issue de ce rapport. Seul Linden Lab peut interdire l&apos;accès à la totalité de [SECOND_LIFE].
</notification>
<notification name="HelpReportAbuseSelectCategory">
Veuillez choisir une catégorie pour ce rapport d&apos;infraction.
Le choix d&apos;une catégorie nous permet de traiter les rapports d&apos;infraction plus rapidement.
</notification>
- <notification name="HelpReportBugSelectCategory">
- Veuillez choisir une catégorie pour ce bug.
-Le choix d&apos;une catégorie nous permet de traiter les bugs plus rapidement.
- </notification>
<notification name="HelpReportAbuseAbuserNameEmpty">
Veuillez saisir le nom du contrevenant.
Lorsque nous avons le nom du contrevenant, nous sommes en mesure de traiter les rapports plus rapidement.
@@ -1995,28 +1736,19 @@ Les informations précises et exactes nous permettent de traiter les rapports pl
Veuillez saisir un récapitulatif de l&apos;infraction.
Les récapitulatifs précis nous permettent de traiter les rapports plus rapidement.
</notification>
- <notification name="HelpReportBugSummaryEmpty">
- Veuillez saisir un récapitulatif du bug.
-Les récapitulatifs précis nous permettent de résoudre les bugs plus rapidement.
- </notification>
<notification name="HelpReportAbuseDetailsEmpty">
Veuillez saisir une description détaillée de l&apos;infraction.
Soyez aussi précis que possible et essayez de fournir des noms ainsi que des détails sur l&apos;incident que vous signalez.
Les descriptions précises nous permettent de traiter les rapports plus rapidement.
</notification>
- <notification name="HelpReportBugDetailsEmpty">
- Veuillez saisir une description détaillée du bug.
-Soyez aussi spécifique que possible et essayez d&apos;indiquer les étapes à suivre pour reproduire le bug.
-Les descriptions précises nous permettent de résoudre les bugs plus rapidement.
- </notification>
<notification name="HelpReportAbuseContainsCopyright">
Cher résident,
Il semble que vous souhaitiez reporter une infraction à des droits de propriété intellectuelle. Pour signaler correctement cette infraction :
-(1) Remplissez un rapport d&apos;infraction. Vous pouvez soumettre un rapport d&apos;infraction si vous pensez qu&apos;un résident exploite le système de droits de Second Life, par exemple en utilisant un CopyBot ou des outils similaires pour enfreindre des droits de propriété intellectuelle. Notre équipe chargée des infractions mènera une enquête et prendra les mesures nécessaires à l&apos;encontre du résident non respectueux des Conditions d&apos;utilisation ou des règles de la communauté. Sachez toutefois que l&apos;équipe chargée des infractions ne supprimera pas de contenu à l&apos;intérieur de Second Life.
+(1) Remplissez un rapport d&apos;infraction. Vous pouvez soumettre un rapport d&apos;infraction si vous pensez qu&apos;un résident exploite le système de droits de [SECOND_LIFE], par exemple en utilisant un CopyBot ou des outils similaires pour enfreindre des droits de propriété intellectuelle. Notre équipe chargée des infractions mènera une enquête et prendra les mesures nécessaires à l&apos;encontre du résident non respectueux des [SECOND_LIFE] [http://secondlife.com/corporate/tos.php Conditions d&apos;utilisation] ou des [http://secondlife.com/corporate/cs.php Règles communautaires]. Sachez toutefois que l&apos;équipe chargée des infractions ne supprimera pas de contenu à l&apos;intérieur de [SECOND_LIFE].
-(2) Demandez à ce que du contenu à l&apos;intérieur de Second Life soit supprimé. Pour demander à ce que du contenu soit supprimé de Second Life, vous devez soumettre un rapport d&apos;infraction valide, tel que fourni dans notre Règlement contre les violations des droit d&apos;auteurs (DMCA), à http://secondlife.com/corporate/dmca.php.
+(2) Demandez à ce que du contenu à l&apos;intérieur de Second Life soit supprimé. Pour demander à ce que du contenu soit supprimé de [SECOND_LIFE], vous devez soumettre un rapport d&apos;infraction valide, tel que fourni dans notre [http://secondlife.com/corporate/dmca.php Règlement contre les violations des droits d&apos;auteur].
Si vous souhaitez toujours reporter cette infraction, veuillez fermer cette fenêtre et soumettre votre rapport. Vous devrez peut-être sélectionner la catégorie CopyBot ou exploitation abusive des droits.
@@ -2032,7 +1764,7 @@ Linden Lab
Vous avez déjà un objet sur cette partie du corps.
Voulez-vous le remplacer par l&apos;objet sélectionné ?
<form name="form">
- <ignore name="ignore" save_option="true" text="Lors du remplacement de pièces-jointes existantes"/>
+ <ignore name="ignore" save_option="true" text="Remplacer une pièce jointe existante par l&apos;objet sélectionné"/>
<button ignore="Remplacer automatiquement" name="Yes" text="OK"/>
<button ignore="Ne jamais remplacer" name="No" text="Annuler"/>
</form>
@@ -2042,18 +1774,22 @@ Voulez-vous le remplacer par l&apos;objet sélectionné ?
Souhaitez-vous quitter le mode occupé avant de terminer cette transaction ?
<form name="form">
- <ignore name="ignore" save_option="true" text="Lorsque vous envoyez de l&apos;argent à une personne en mode Occupé"/>
+ <ignore name="ignore" save_option="true" text="Je suis sur le point de payer une personne ou un objet mais suis en mode Occupé"/>
<button ignore="Toujours quitter le mode occupé" name="Yes" text="OK"/>
<button ignore="Ne jamais quitter le mode occupé" name="No" text="Annuler"/>
</form>
</notification>
+ <notification name="ConfirmDeleteProtectedCategory">
+ Le dossier [FOLDERNAME] est un dossier système. La suppression d&apos;un dossier système peut provoquer une instabilité. Voulez-vous vraiment le supprimer ?
+ <usetemplate ignoretext="Confirmer avant la suppression d&apos;un dossier système" name="okcancelignore" notext="Annuler" yestext="OK"/>
+ </notification>
<notification name="ConfirmEmptyTrash">
- Êtes-vous certain de vouloir supprimer le contenu de votre corbeille de manière permanente  ?
- <usetemplate ignoretext="Lorsque vous videz la corbeille de l&apos;inventaire" name="okcancelignore" notext="Annuler" yestext="OK"/>
+ Êtes-vous certain de vouloir supprimer le contenu de votre corbeille de manière permanente ?
+ <usetemplate ignoretext="Confirmer avant de vider la corbeille" name="okcancelignore" notext="Annuler" yestext="OK"/>
</notification>
<notification name="ConfirmClearBrowserCache">
- Êtes-vous certain de vouloir vider le cache de votre navigateur ?
- <usetemplate name="okcancelbuttons" notext="Annuler" yestext="Oui"/>
+ Êtes-vous certain de vouloir supprimer l&apos;historique de vos visites et recherches ?
+ <usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
</notification>
<notification name="ConfirmClearCookies">
Êtes-vous certain de vouloir supprimer vos cookies ?
@@ -2064,39 +1800,18 @@ Souhaitez-vous quitter le mode occupé avant de terminer cette transaction ?
<usetemplate name="okcancelbuttons" notext="Annuler" yestext="Oui"/>
</notification>
<notification name="ConfirmEmptyLostAndFound">
- Êtes-vous certain de vouloir supprimer le contenu de votre dossier Objets trouvés de manière permanente ?
- <usetemplate ignoretext="Losque vous videz le dossier Objets trouvés dans votre inventaire" name="okcancelignore" notext="Non" yestext="Oui"/>
+ Êtes-vous certain de vouloir supprimer le contenu de votre dossier Objets trouvés de manière permanente ?
+ <usetemplate ignoretext="Confirmer avant de vider le dossier Objets trouvés" name="okcancelignore" notext="Non" yestext="Oui"/>
</notification>
<notification name="CopySLURL">
- La SLURL suivante a été copiée dans votre presse-papiers :
+ La SLurl suivante a été copiée dans votre presse-papiers :
[SLURL]
-Mettez-la dans une page web pour permettre aux autres résidents d&apos;accéder facilement à cet endroit ou bien collez-la dans la barre d&apos;adresse de votre navigateur.
+Liez-la à partir d&apos;une page web pour permettre aux autres résidents d&apos;accéder facilement à cet endroit ou bien collez-la dans la barre d&apos;adresse de votre navigateur.
<form name="form">
- <ignore name="ignore" text="Lorsque vous copiez une SLURL dans votre presse-papier"/>
+ <ignore name="ignore" text="La SLurl est copiée dans mon presse-papiers"/>
</form>
</notification>
- <notification name="GraphicsPreferencesHelp">
- Ce menu permet de contrôler la taille de la fenêtre et la résolution, ainsi que la qualité des graphiques client. Les préférences de l&apos;interface graphique vous permettent de choisir entre 4 niveaux de graphiques : Faible, Moyen, Élevé et Ultra. Personnalisez vos options graphiques en cliquant sur le bouton Personnaliser et en changeant les paramètres suivants :
-
-Effets : active ou désactive les différents types de shaders pixels.
-
-Objets reflétés : définit le type d&apos;objets reflétés dans l&apos;eau.
-
-Rendu de l&apos;avatar : définit les options qui influent sur la manière dont le client rend les avatars.
-
-Limite d&apos;affichage : la distance à laquelle vous voyez les objets s&apos;afficher dans la scène.
-
-Nombre de particules max. : définit le nombre maximum de particules que vous pouvez voir à la fois sur votre écran.
-
-Qualité post-traitement : définit la résolution du rayonnement.
-
-Détails des rendus : définit le niveau de détail ou le nombre de polygones utilisés dans le rendu de certains objets. Une valeur plus élevée prendra plus de temps pour apparaître, mais permettra d&apos;avoir des objets plus détaillés.
-
-Sources lumineuses : définit les types de lumières que vous souhaitez faire apparaître.
-
-Rendu du terrain : définit le niveau de détail que vous souhaitez utiliser dans la texture du terrain.
- </notification>
<notification name="WLSavePresetAlert">
Voulez-vous écraser l&apos;option précédemment enregistrée ?
<usetemplate name="okcancelbuttons" notext="Non" yestext="Oui"/>
@@ -2115,157 +1830,10 @@ Rendu du terrain : définit le niveau de détail que vous souhaitez utiliser dan
Certains effets post-traitement existent. Voulez-vous quand même écraser ce fichier ?
<usetemplate name="okcancelbuttons" notext="Non" yestext="Oui"/>
</notification>
- <notification name="HelpEditSky">
- Pour créer et sauvegarder plusieurs ciels, utilisez les curseurs WindLight.
- </notification>
- <notification name="HelpEditDayCycle">
- Choisissez quel ciel apparaît au cours de la journée.
- </notification>
- <notification name="EnvSettingsHelpButton">
- Ces paramètres permettent de modifier l&apos;environnement local sur votre ordinateur. Pour que vous ayez accès à tous les paramètres, votre carte graphique doit prendre en charge les effets atmosphériques.
-
-Pour changer les différentes phases de la journée dans le client, utilisez le curseur Heure de la journée.
-
-Le curseur Couverture nuageuse permet de contrôler le nombre de nuages dans le ciel.
-
-L&apos;option Couleur de l&apos;eau vous permet de modifier la couleur de l&apos;eau grâce au sélecteur de couleurs.
-
-Le curseur Brouillard dans l&apos;eau permet de contrôler la densité du brouillard sous l&apos;eau.
-
-Pour synchroniser l&apos;heure du jour sur celle de la région, cliquez sur Utiliser heure domaine.
-
-En cliquant sur le bouton Ciel Avancé, vous aurez accès à tous les réglages relatifs au ciel.
-
-En cliquant sur le bouton Eau Avancée, vous aurez accès à tous les réglages relatifs à l&apos;eau.
- </notification>
- <notification name="HelpDayCycle">
- L&apos;éditeur du cycle du jour vous permet de contrôler le ciel au cours du cycle jour/nuit de second Life. C&apos;est ce même cycle qui est contrôlé par le curseur Heure de la journée dans l&apos;éditeur d&apos;environnement basique.
-
-L&apos;éditeur du jour fonctionne grâce au réglage d&apos;images-clés. Ces images-clés sont représentées par les marques grises sur la ligne du temps et ont des préréglages qui leurs sont associées. Au cours de la journée et de la nuit, le ciel WindLight s&apos;anime en passant d&apos;une clé à l&apos;autre.
-
-La flèche jaune au dessus de la ligne du temps représente votre vue actuelle, basée sur l&apos;heure de la journée. Cliquez et faites glisser pour voir l&apos;animation au cours de votre journée. Ajoutez ou supprimez des clés en appuyant sur les boutons Ajouter clé ou Supprimer clé, à droite de la ligne du temps.
-
-Vous pouvez définir la position d&apos;une clé en la faisant glisser le long de la ligne du temps ou en définissant manuellement ses valeurs dans la section Réglages des images-clés. Dans cette même section, vous pouvez associer chaque clé au préréglage WindLight respectif.
-
-La Durée du cycle contrôle la durée d&apos;une « journée ». Si vous choisissez une valeur basse (2mn par exemple), cela signifie que toutes les animations de votre journée de 24h se dérouleront en 2mn seulement ! Une fois satisfait de vos choix, utilisez les boutons Jouer et Stop ! pour prévisualiser les résultats. Pour voir l&apos;animation, vous pouvez aussi bouger la flèche jaune au dessus de la ligne du temps. Si vous sélectionnez l&apos;option Utiliser heure domaine, vous synchronisez la durée de votre journée et votre heure avec celle du cycle du jour du domaine.
-
-Une fois que vous êtes satisfait de votre Cycle du jour, vous pouvez le sauvegarder et le charger grâce aux boutons Enregistrer jour test et Charger Jour Test. Veuillez noter que pour l&apos;instant, nous ne pouvez avoir qu&apos;un seul Cycle du jour.
- </notification>
- <notification name="HelpBlueHorizon">
- Utilisez les curseurs Rouge/Vert/Bleu (RVB) pour ajuster la couleur du ciel. Pour déplacer les trois curseurs en même temps, utilisez le curseur Intensité.
- </notification>
- <notification name="HelpHazeHorizon">
- Le paramètre Quantité de brume est l&apos;un des plus utiles pour ajuster l&apos;exposition lumineuse de la scène.
-Il permet de simuler de nombreux paramètres d&apos;exposition, tels que les voiles blancs créés par le soleil ou des lumières plus foncées.
- </notification>
- <notification name="HelpBlueDensity">
- La Densité du bleu affecte la saturation générale des couleurs du ciel et du brouillard. Si vous déplacez le curseur Intensité (I) vers la droite, les couleurs deviennent plus vives et plus vibrantes. Si vous le déplacez complètement à gauche, les couleurs deviennent plus fades, puis finalement noires et blanches. Pour paramétrer avec précision la couleur du ciel, vous pouvez contrôler chacun des éléments de la saturation à l&apos;aide des curseurs Rouge/Vert/Bleu (RVB).
- </notification>
- <notification name="HelpHazeDensity">
- Le paramètre Densité de la brume permet de contrôler le niveau de brume grisâtre dans l&apos;atmosphère. Ce paramètre est utile pour simuler les scènes dans lesquelles il y a beaucoup de fumée et de substances polluantes émises par l&apos;homme. Il est également utile pour simuler le brouillard et la brume.
- </notification>
- <notification name="HelpDensityMult">
- Utilisez le Multiplicateur de densité pour modifier la densité atmosphérique générale. Une valeur basse donne l&apos;impression d&apos;un air « léger » alors qu&apos;une valeur élevée donne l&apos;impression d&apos;un air « lourd » et enfumé.
- </notification>
- <notification name="HelpDistanceMult">
- Ajuste la distance perçue par WindLight.
-La valeur zéro désactive l&apos;influence de WindLight sur le terrain et les objets.
-Les valeurs supérieures à 1 simulent des distances plus importantes pour des effets atmosphériques plus épais.
- </notification>
- <notification name="HelpMaxAltitude">
- L&apos;Altitude max. ajuste les calculs de WindLight lors de la computation de la lumière atmosphérique. Quand la fin de la journée approche, il est utile pour ajuster la « profondeur » du coucher de soleil.
- </notification>
- <notification name="HelpSunlightColor">
- Ajuste la couleur et l&apos;intensité de la lumière directe de la scène.
- </notification>
- <notification name="HelpSunAmbient">
- Ajuste la couleur et l&apos;intensité de la lumière atmosphérique ambiante.
- </notification>
- <notification name="HelpSunGlow">
- Le curseur Taille contrôle la taille du soleil.
-Le curseur Netteté permet de rendre le soleil plus ou moins flou dans le ciel.
- </notification>
- <notification name="HelpSceneGamma">
- Ajuste la distribution de clair et de foncé sur l&apos;écran.
- </notification>
- <notification name="HelpStarBrightness">
- Vous permet de contrôler l&apos;intensité des étoiles dans le ciel.
- </notification>
- <notification name="HelpTimeOfDay">
- Contrôle la position du soleil dans le ciel.
-Même chose que l&apos;élévation.
- </notification>
- <notification name="HelpEastAngle">
- Contrôle la position du soleil dans le ciel.
-Même chose que l&apos;azimut.
- </notification>
- <notification name="HelpCloudColor">
- Modifie la couleur des nuages. Il est recommandé de laisser les nuages en blanc mais vous pouvez aussi faire preuve de créativité...
- </notification>
- <notification name="HelpCloudDetail">
- Contrôle le détail de l&apos;image placée sur l&apos;image du nuage principal. X et Y contrôlent sa position. D (Densité) permet de rendre les nuages plus ou moins pleins ou plus ou moins fracturés.
- </notification>
- <notification name="HelpCloudDensity">
- Vous permet de contrôler la position des nuages avec les curseurs X et Y ainsi que leur densité avec le curseur D.
- </notification>
- <notification name="HelpCloudCoverage">
- Contrôle la surface du ciel couverte par les nuages.
- </notification>
- <notification name="HelpCloudScale">
- Contrôle l&apos;échelle de l&apos;image des nuages sur le dôme du ciel.
- </notification>
- <notification name="HelpCloudScrollX">
- Contrôle la vitesse des nuages sur l&apos;axe des X.
- </notification>
- <notification name="HelpCloudScrollY">
- Contrôle la vitesse des nuages sur l&apos;axe des Y.
- </notification>
- <notification name="HelpClassicClouds">
- Cochez cette option pour utiliser les anciens nuages de Second Life en plus des nuages WindLight.
- </notification>
- <notification name="HelpWaterFogColor">
- Permet de sélectionner la couleur du brouillard sous l&apos;eau.
- </notification>
- <notification name="HelpWaterFogDensity">
- Contrôle la densité du brouillard sous l&apos;eau, ainsi que votre visibilité.
- </notification>
- <notification name="HelpUnderWaterFogMod">
- Modifie l&apos;effet créé par l&apos;option Densité du brouillard pour contrôler votre visibilité quand votre avatar est sous l&apos;eau.
- </notification>
- <notification name="HelpWaterGlow">
- Contrôle l&apos;éclat de l&apos;eau à la surface.
- </notification>
- <notification name="HelpWaterNormalScale">
- Contrôle l&apos;échelle des trois vaguelettes qui forment l&apos;eau.
- </notification>
- <notification name="HelpWaterFresnelScale">
- Contrôle la quantité de lumière réfléchie à des angles différents.
- </notification>
- <notification name="HelpWaterFresnelOffset">
- Contrôle l&apos;intensité de la lumière réfléchie.
- </notification>
- <notification name="HelpWaterScaleAbove">
- Contrôle la quantité de lumière réfractée lorsque votre avatar regarde au dessus de l&apos;eau.
- </notification>
- <notification name="HelpWaterScaleBelow">
- Contrôle la quantité de lumière réfractée lorsque votre avatar est sous l&apos;eau.
- </notification>
- <notification name="HelpWaterBlurMultiplier">
- Contrôle le mélange reflets/vagues.
- </notification>
- <notification name="HelpWaterNormalMap">
- Contrôle quelle normal map est posée sur l&apos;eau pour déterminer la réflection/réfraction.
- </notification>
- <notification name="HelpWaterWave1">
- Contrôle dans quelle direction et à quelle vitesse la version grande échelle de la normal map se déplace sur l&apos;axe des X et l&apos;axe des Y.
- </notification>
- <notification name="HelpWaterWave2">
- Contrôle dans quelle direction et à quelle vitesse la version grande échelle de la normal map se déplace sur l&apos;axe des X et l&apos;axe des Y.
- </notification>
<notification name="NewSkyPreset">
Nommez le nouveau ciel.
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Nouveau préréglage
</input>
<button name="OK" text="OK"/>
@@ -2278,7 +1846,7 @@ Même chose que l&apos;azimut.
<notification name="NewWaterPreset">
Nommez ce nouveau préréglage d&apos;eau.
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Nouveau préréglage
</input>
<button name="OK" text="OK"/>
@@ -2307,35 +1875,33 @@ Même chose que l&apos;azimut.
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="Cannot_Purchase_an_Attachment">
- Les objets qui font partie d&apos;une pièce-jointe ne peuvent pas être achetés.
+ Vous ne pouvez pas acheter un objet s&apos;il fait partie d&apos;une pièce jointe.
</notification>
<notification label="À propos des requêtes pour les autorisations de débit" name="DebitPermissionDetails">
Accepter cette requête donne au script l&apos;autorisation de prélever des dollars Linden (L$) sur votre compte de manière continue. Pour révoquer cette autorisation, le propriétaire de l&apos;objet doit supprimer l&apos;objet ou bien réinitialiser les scripts dans l&apos;objet.
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="AutoWearNewClothing">
- Voulez-vous automatiquement porter l&apos;habit que vous créez ?
- <usetemplate ignoretext="Porter automatiquement" name="okcancelignore" notext="Non" yestext="Oui"/>
+ Voulez-vous automatiquement porter l&apos;habit que vous allez créer ?
+ <usetemplate ignoretext="Porter automatiquement tout en modifiant mon apparence" name="okcancelignore" notext="Non" yestext="Oui"/>
</notification>
<notification name="NotAgeVerified">
- Pour que vous puissiez accéder à cette parcelle, votre âge doit être vérifié.
-Voulez-vous aller sur le site de Second Life pour vérifier votre âge ?
+ Pour pouvoir pénétrer dans cette zone, vous devez avoir procédé à la vérification de votre âge. Souhaitez-vous aller sur [SECOND_LIFE] et procéder à la vérification de votre âge ?
[_URL]
<url name="url" option="0">
https://secondlife.com/account/verification.php?lang=fr
</url>
- <usetemplate ignoretext="Avertir si l&apos;âge n&apos;a pas été vérifié" name="okcancelignore" notext="Non" yestext="Oui"/>
+ <usetemplate ignoretext="Je n&apos;ai pas procédé à la vérification de mon âge" name="okcancelignore" notext="Non" yestext="Oui"/>
</notification>
<notification name="Cannot enter parcel: no payment info on file">
- Avant de pouvoir pénétrer sur cette parcelle, vous devez enregistrer vos informations de paiement.
-Voulez-vous aller sur le site de Second Life pour enregistrer ces informations ?
+ Pour pouvoir pénétrer dans cette zone, vous devez avoir enregistré vos informations de paiement. Souhaitez-vous aller sur [SECOND_LIFE] et enregistrer vos informations de paiement ?
[_URL]
<url name="url" option="0">
https://secondlife.com/account/index.php?lang=fr
</url>
- <usetemplate ignoretext="Avertir si les informations de paiement ne sont pas fournies" name="okcancelignore" notext="Non" yestext="Oui"/>
+ <usetemplate ignoretext="Mes informations de paiement ne sont pas enregistrées" name="okcancelignore" notext="Non" yestext="Oui"/>
</notification>
<notification name="MissingString">
The string [STRING_NAME] is missing from strings.xml
@@ -2365,11 +1931,11 @@ Voulez-vous aller sur le site de Second Life pour enregistrer ces informations 
[FIRST] [LAST] est déconnecté(e)
</notification>
<notification name="AddSelfFriend">
- Vous ne pouvez pas devenir ami avec vous-même.
+ Même si vous êtes extrêmement sympathique, vous ne pouvez pas devenir ami avec vous-même.
</notification>
<notification name="UploadingAuctionSnapshot">
- Importation de photos SL et Web en cours
-(prend environ 5 minutes…)
+ Importation de photos SL et Web en cours...
+(prend environ 5 minutes.)
</notification>
<notification name="UploadPayment">
Le chargement a coûté [AMOUNT] L$.
@@ -2398,13 +1964,13 @@ Merci de réessayer.
</notification>
<notification name="CapsKeyOn">
La touche Verr.maj est activée.
-Ce mode modifie le mot de passe que vous saisissez, vous devriez le quitter.
+Cela risque d&apos;impacter votre mot de passe.
</notification>
<notification name="NotecardMissing">
Note absente de la base de données.
</notification>
<notification name="NotecardNoPermissions">
- Permissions insuffisantes pour voir la note.
+ Vous n&apos;avez pas le droit de consulter cette note.
</notification>
<notification name="RezItemNoPermissions">
Permissions insuffisantes pour rezzer l&apos;objet.
@@ -2443,10 +2009,11 @@ Merci de réessayer.
Merci de réessayer.
</notification>
<notification name="CannotBuyObjectsFromDifferentOwners">
- Impossible d&apos;acheter simultanément des objets de propriétaires différents. Veuillez sélectionner un seul objet.
+ Vous ne pouvez pas acheter simultanément des objets de propriétaires différents.
+Veuillez sélectionner un seul objet.
</notification>
<notification name="ObjectNotForSale">
- Cet objet ne semble pas à vendre.
+ Cet objet n&apos;est pas à vendre.
</notification>
<notification name="EnteringGodMode">
Activation du mode divin : niveau [LEVEL]
@@ -2455,10 +2022,10 @@ Merci de réessayer.
Désactivation du mode divin : niveau [LEVEL]
</notification>
<notification name="CopyFailed">
- Copie impossible, droits insuffisants.
+ Vous n&apos;avez pas le droit de copier ceci.
</notification>
<notification name="InventoryAccepted">
- [NAME] a accepté votre envoi.
+ [NAME] a reçu votre offre d&apos;inventaire.
</notification>
<notification name="InventoryDeclined">
[NAME] a refusé votre envoi.
@@ -2473,12 +2040,14 @@ Merci de réessayer.
Votre carte de visite a été refusée.
</notification>
<notification name="TeleportToLandmark">
- A présent que vous êtes sur le continent, vous pouvez voyager par téléportation (vers [NAME] par exemple). Cliquez sur le bouton Inventaire en bas à droite de l&apos;écran puis sélectionnez le dossier Repères (Landmarks).
-Choisissez un repère, double-cliquez dessus et cliquez sur Téléporter.
+ Vous pouvez vous téléporter vers des endroits comme [NAME] en ouvrant le panneau Lieux sur le côté droit de votre écran, puis en sélectionnant l&apos;onglet Repères.
+Cliquez sur le repère de votre choix pour le sélectionner, puis sur Téléporter en bas du panneau.
+(Vous pouvez aussi double-cliquer sur le repère ou cliquer dessus avec le bouton droit de la souris et sélectionner Téléporter.)
</notification>
<notification name="TeleportToPerson">
- A présent que vous êtes sur le continent, vous pouvez contacter des résidents (tel [NAME] par exemple). Cliquez sur le bouton Inventaire en bas à droite de l&apos;écran puis sélectionnez le dossier Cartes de visite (Calling Cards).
-Choisissez en une, double-cliquez dessus et cliquez sur Message Instantané.
+ Vous pouvez contacter des résidents comme [NAME] en ouvrant le panneau Résidents sur le côté droit de votre écran.
+Sélectionnez le résident de votre choix dans la liste, puis cliquez sur IM en bas du panneau.
+(Vous pouvez aussi double-cliquer sur le nom du résident dans la liste ou cliquer dessus avec le bouton droit de la souris et sélectionner IM.)
</notification>
<notification name="CantSelectLandFromMultipleRegions">
Vous ne pouvez pas sélectionner de terrain en dehors des limites du serveur.
@@ -2526,7 +2095,19 @@ Veuillez sélectionner un terrain plus petit.
</notification>
<notification name="NoQuickTime">
Le logiciel Apple QuickTime ne semble pas installé sur votre système.
-Pour voir les vidéos sur les terrains qui le permettent, allez sur le site de QuickTime (http://www.apple.com/fr/quicktime/download) et installez le lecteur QuickTime.
+Pour voir les vidéos sur les terrains qui le permettent, allez sur le [http://www.apple.com/quicktime site de QuickTime] et installez le lecteur QuickTime.
+ </notification>
+ <notification name="NoPlugin">
+ Aucun Media Plugin n&apos;a été trouvé pour prendre en charge [MIME_TYPE]. Les médias de ce type ne sont pas disponibles.
+ </notification>
+ <notification name="MediaPluginFailed">
+ Le Media Plugin suivant a échoué :
+ [PLUGIN]
+
+Si le problème persiste, veuillez réinstaller le plugin ou contacter le vendeur.
+ <form name="form">
+ <ignore name="ignore" text="L&apos;exécution d&apos;un Media Plugin a échoué"/>
+ </form>
</notification>
<notification name="OwnedObjectsReturned">
Les objets que vous possédez sur la parcelle de terrain sélectionnée ont été renvoyés dans votre inventaire.
@@ -2545,24 +2126,27 @@ Les objets non transférables donnés au groupe ont étés supprimés.
<notification name="UnOwnedObjectsReturned">
Les objets sélectionnés sur la parcelle et qui ne sont pas à vous ont été rendus à leurs propriétaires.
</notification>
+ <notification name="ServerObjectMessage">
+ Message de [NAME] :
+[MSG]
+ <usetemplate name="okcancelbuttons" notext="OK" yestext="Inspecter"/>
+ </notification>
<notification name="NotSafe">
- Les dégâts sont autorisés sur ce terrain (« non sécurisé »).
+ Les dégâts sont autorisés sur ce terrain.
Vous pouvez être blessé ici. Si vous décédez, vous serez téléporté à votre domicile.
</notification>
<notification name="NoFly">
- Le vol est interdit sur ce terrain (« pas de vol »).
+ Le vol est interdit dans cette zone.
Vous ne pouvez pas voler ici.
</notification>
<notification name="PushRestricted">
- Les bousculades sont interdites sur ce terrain.
-Vous ne pouvez pas pousser les autres à moins que vous soyez propriétaire de ce terrain.
+ Les bousculades sont interdites dans cette zone. Vous ne pouvez pas pousser les autres à moins que vous soyez propriétaire de ce terrain.
</notification>
<notification name="NoVoice">
- La voix est désactivée sur ce terrain.
+ Le chat vocal est interdit dans cette zone. Vous n&apos;entendrez personne parler.
</notification>
<notification name="NoBuild">
- Le mode construction sur ce terrain est désactivé (« pas de construction »).
-Vous ne pouvez pas créer d&apos;objets ici.
+ La construction est interdite dans cette zone. Vous ne pouvez pas construite ou rezzer d&apos;objets ici.
</notification>
<notification name="ScriptsStopped">
Un administrateur a temporairement stoppé les scripts dans cette région.
@@ -2571,8 +2155,9 @@ Vous ne pouvez pas créer d&apos;objets ici.
Aucun script ne fonctionne dans cette région.
</notification>
<notification name="NoOutsideScripts">
- Les scripts externes sont désactivés sur ce terrain (« pas de scripts externes »).
-Aucun script n&apos;est exécuté à part ceux du propriétaire du terrain.
+ Les scripts externes sont désactivés sur ce terrain.
+
+Aucun script ne marche ici à part ceux du propriétaire du terrain.
</notification>
<notification name="ClaimPublicLand">
Vous ne pouvez réclamer qu&apos;un terrain public dans la région où vous vous trouvez actuellement.
@@ -2588,10 +2173,6 @@ Pour savoir comment accéder aux zones ayant un tel niveau d&apos;accès, veuill
<notification name="NoTeenGridAccess">
Votre compte ne peut pas se connecter à cette région du Teen grid.
</notification>
- <notification name="NoHelpIslandTP">
- Vous ne pouvez pas retourner sur Help Island.
-Pour répéter le didacticiel, veuillez aller sur Help Island Public.
- </notification>
<notification name="ImproperPaymentStatus">
Vous n&apos;avez pas le statut de paiement approprié pour pénétrer dans cette région.
</notification>
@@ -2660,7 +2241,8 @@ Veuillez réessayer dans quelques minutes.
Aucune parcelle valide n&apos;a été trouvée.
</notification>
<notification name="ObjectGiveItem">
- Un objet appelé [OBJECTFROMNAME] appartenant à [FIRST] [LAST] vous a donné : [OBJECTTYPE] appelé(e) [OBJECTNAME].
+ Un objet appelé [OBJECTFROMNAME] appartenant à [NAME_SLURL] vous a donné un [OBJECTTYPE] :
+[ITEM_SLURL]
<form name="form">
<button name="Keep" text="Garder"/>
<button name="Discard" text="Jeter"/>
@@ -2668,7 +2250,8 @@ Veuillez réessayer dans quelques minutes.
</form>
</notification>
<notification name="ObjectGiveItemUnknownUser">
- L&apos;objet [OBJECTFROMNAME] appartenant à un utilisateur inconnu vous a donné un(e) [OBJECTTYPE] nommé(e) [OBJECTNAME].
+ Un objet appelé [OBJECTFROMNAME] appartenant à (un résident inconnu) vous a donné un [OBJECTTYPE] :
+[ITEM_SLURL]
<form name="form">
<button name="Keep" text="Garder"/>
<button name="Discard" text="Jeter"/>
@@ -2676,15 +2259,17 @@ Veuillez réessayer dans quelques minutes.
</form>
</notification>
<notification name="UserGiveItem">
- [NAME] vous a donné un(e) [OBJECTTYPE] nommé(e) [OBJECTNAME].
+ [NAME_SLURL] vous a donné un [OBJECTTYPE] :
+[ITEM_SLURL]
<form name="form">
<button name="Keep" text="Garder"/>
+ <button name="Show" text="Afficher"/>
<button name="Discard" text="Jeter"/>
- <button name="Mute" text="Ignorer"/>
</form>
</notification>
<notification name="GodMessage">
[NAME]
+
[MESSAGE]
</notification>
<notification name="JoinGroup">
@@ -2696,7 +2281,7 @@ Veuillez réessayer dans quelques minutes.
</form>
</notification>
<notification name="TeleportOffered">
- [NAME] vous propose de le/la rejoindre par téléportation :
+ [NAME] vous propose d&apos;être téléporté jusqu&apos;à son emplacement :
[MESSAGE]
<form name="form">
@@ -2772,7 +2357,7 @@ Venant de l&apos;objet : [OBJECTNAME], appartenant à : [NAME]?
La recherche du [TYPE] nommé(e) [DESC] dans la base de données a échoué.
</notification>
<notification name="InvalidWearable">
- L&apos;objet que vous essayez de porter utilise une fonctionnalité que le client ne peut lire. Pour porter cet objet, veuillez télécharger une mise à jour du client.
+ L&apos;objet que vous essayez de porter utilise une fonctionnalité que le client ne peut lire. Pour porter cet objet, veuillez télécharger une mise à jour de [APP_NAME].
</notification>
<notification name="ScriptQuestion">
&apos;[OBJECTNAME]&apos;, un objet appartenant à &apos;[NAME]&apos;, aimerait :
@@ -2782,16 +2367,16 @@ Acceptez-vous ?
<form name="form">
<button name="Yes" text="Oui"/>
<button name="No" text="Non"/>
- <button name="Mute" text="Ignorer"/>
+ <button name="Mute" text="Interdire"/>
</form>
</notification>
<notification name="ScriptQuestionCaution">
- [OBJECTNAME], un objet appartenant à [NAME], aimerait :
+ Un objet appelé [OBJECTNAME], appartenant à [NAME], aimerait :
[QUESTIONS]
-Si vous n&apos;avez pas confiance en cet objet ni en son créateur, vous devriez refuser cette requête. Pour plus d&apos;informations, cliquez sur le bouton Détails.
+Si vous n&apos;avez pas confiance en cet objet ni en son créateur, vous devriez refuser cette requête.
-Accepter cette requête ?
+Accepter cette requête ?
<form name="form">
<button name="Grant" text="Accepter"/>
<button name="Deny" text="Refuser"/>
@@ -2812,18 +2397,32 @@ Accepter cette requête ?
<button name="Ignore" text="Ignorer"/>
</form>
</notification>
+ <notification name="ScriptToast">
+ [FIRST] [LAST]&apos;s &apos;[TITLE]&apos; demande la participation de l&apos;utilisateur.
+ <form name="form">
+ <button name="Open" text="Ouvrir la boîte de dialogue"/>
+ <button name="Ignore" text="Ignorer"/>
+ <button name="Block" text="Ignorer"/>
+ </form>
+ </notification>
<notification name="FirstBalanceIncrease">
Vous venez de recevoir [AMOUNT] L$.
-Des objets et des utilisateurs peuvent vous donner des L$.
-Votre solde est affiché dans le coin supérieur droit de votre écran.
+Votre solde en L$ est affiché en haut à droite.
</notification>
<notification name="FirstBalanceDecrease">
Vous venez de payer [AMOUNT] L$.
-Votre solde est affiché dans le coin supérieur droit de votre écran.
+Votre solde en L$ est affiché en haut à droite.
+ </notification>
+ <notification name="BuyLindenDollarSuccess">
+ Nous vous remercions de votre paiement.
+
+Votre solde en L$ sera mis à jour une fois le traitement terminé. Si le traitement prend plus de 20 minutes, il est possible que votre transaction soit annulée. Dans ce cas, le montant de l&apos;achat sera crédité sur votre solde en US$.
+
+Vous pouvez consulter le statut de votre paiement à la page Historique de mes transactions sur votre [http://secondlife.com/account/ Page d&apos;accueil]
</notification>
<notification name="FirstSit">
Vous êtes assis(e).
-Utilisez les touches de direction (ou AWSD) pour changer la vue.
+Utilisez les touches de direction (ou AWSD) pour regarder autour de vous.
Pour vous lever, cliquez sur le bouton Me lever.
</notification>
<notification name="FirstMap">
@@ -2832,19 +2431,10 @@ Double-cliquez pour vous téléporter.
Utilisez les contrôles à droite pour trouver des choses et afficher différents arrière-plans.
</notification>
<notification name="FirstBuild">
- Vous pouvez construire des objets dans certaines zones de [SECOND_LIFE].
-Utilisez les outils en haut à gauche pour construire et gardez la touche Ctrl ou Alt enfoncée pour passer rapidement d&apos;un outil à l&apos;autre.
-Appuyez sur la touche Esc pour arrêter de construire.
- </notification>
- <notification name="FirstLeftClickNoHit">
- Un clic gauche permet d&apos;interagir avec certains objets.
-Si le pointeur de la souris se transforme en main, vous pouvez interagir avec l&apos;objet.
-Un clic droit fait toujours apparaître un menu des choses que vous pouvez faire.
+ Vous avez ouvert les outils de construction. Tous les objets autour de vous ont été créés avec ces outils.
</notification>
<notification name="FirstTeleport">
- Cette région n&apos;autorise pas la téléportation de point à point. Vous avez donc été transporté au téléhub le plus proche.
-Votre destination est marquée par une grande balise.
-Suivez la flèche rouge vers la balise ou cliquez sur la flèche pour faire disparaître la balise.
+ Vous ne pouvez vous téléporter que dans certaines zones de cette région. La flèche pointe vers votre destination. Cliquez sur la flèche pour la faire disparaître.
</notification>
<notification name="FirstOverrideKeys">
Vos mouvements sont maintenant pris en charge par un objet.
@@ -2854,38 +2444,33 @@ Pour cela, appuyez sur la touche M.
</notification>
<notification name="FirstAppearance">
Vous êtes en train d&apos;éditer votre apparence.
-Pour tourner et zoomer, utilisez les flèches de direction.
-Lorsque vous avez terminé, appuyez sur Enregistrer tout pour sauvegarder votre apparence et sortir.
-Vous pouvez modifier votre apparence aussi souvent que vous le souhaitez.
+Utilisez les touches de direction pour regarder autour de vous.
+Une fois terminé, cliquer sur Tout enregistrer.
</notification>
<notification name="FirstInventory">
- Il s&apos;agit de votre inventaire qui contient des objets, notes, vêtements, et autres possessions.
-* Pour porter un objet ou le dossier contenant un ensemble complet, faites-le glisser sur vous-même.
-* Pour mettre un objet dans le monde, faites-le glisser sur le sol.
+ Il s&apos;agit de votre inventaire qui contient vos possessions.
+
+* Pour porter quelque chose, faites glisser l&apos;objet sur vous-même.
+* Pour rezzer un objet dans le monde, faites-le glisser sur le sol.
* Pour lire une note, double-cliquez dessus.
</notification>
<notification name="FirstSandbox">
- Cette région est un bac à sable.
-Les objets que vous construisez ici peuvent être supprimés quand vous partez. Les bacs à sable sont nettoyés régulièrement, veuillez lire les informations en haut de l&apos;écran à côté du nom de la région.
+ Cette région est un bac à sable et est utilisée par les résidents pour apprendre à construire.
-Les régions bacs à sable sont rares et sont signalées par des panneaux.
+Les objets que vous construisez ici seront supprimés après votre départ. N&apos;oubliez donc pas de cliquer droit et de choisir Prendre pour sauvegarder votre création dans votre inventaire.
</notification>
<notification name="FirstFlexible">
- Cet objet est flexible.
-Les objets flexibles ne peuvent pas avoir de propriétés physiques et doivent rester fantômes jusqu&apos;à ce que la case Fantôme soit décochée.
+ Cet objet est flexible. Les objets flexibles ne peuvent pas avoir de propriétés physiques et doivent rester fantômes.
</notification>
<notification name="FirstDebugMenus">
- Vous avez activé le menu Avancé.
-Ce menu contient des fonctionnalités utiles pour les développeurs qui travaillent sur Second Life.
-Pour activer/désactiver ce menu sous Windows, appuyez sur Ctrl-Alt-D. Sur un Mac, appuyez sur Cmd-Opt-Maj-D
+ Vous avez ouvert le menu Avancé.
+
+Pour activer/désactiver ce menu,
+ Windows : Ctrl+Alt+D
+ Mac : &#8997;&#8984;D
</notification>
<notification name="FirstSculptedPrim">
- Vous êtes en train d&apos;éditer un sculptie.
-Pour modifier la forme d&apos;un sculptie, vous devez utiliser une texture spécifique.
-Vous trouverez des textures dans la bibliothèque de votre inventaire.
- </notification>
- <notification name="FirstMedia">
- Vous avez lancé la lecture d&apos;un média. Dans le menu Préférences, à l&apos;onglet Audio et vidéo, vous pouvez choisir de lire automatiquement les médias. Notez que cela peut être risqué lorsque les médias viennent de sites que vous ne connaissez pas.
+ Vous êtes en train d&apos;éditer un sculptie. Pour spécifier la forme d&apos;un sculptie, vous devez utiliser une texture spécifique.
</notification>
<notification name="MaxListSelectMessage">
Vous ne pouvez sélectionner que [MAX_SELECT] objets maximum dans cette liste.
@@ -2919,7 +2504,7 @@ Pour y participer, cliquez sur Accepter. Sinon, cliquez sur Refuser. Pour ignore
</notification>
<notification name="VoiceInviteAdHoc">
[NAME] a rejoint un chat vocal avec conférence.
-Pour y participer, cliquez sur Accepter. Sinon, cliquez sur Refuser. Pour ignorer cet utilisateur, cliquez sur Ignorer.
+Pour y participer, cliquez sur Accepter. Sinon, cliquez sur Refuser. Pour ignorer cette personne, cliquez sur Ignorer.
<form name="form">
<button name="Accept" text="Accepter"/>
<button name="Decline" text="Refuser"/>
@@ -2928,7 +2513,7 @@ Pour y participer, cliquez sur Accepter. Sinon, cliquez sur Refuser. Pour ignore
</notification>
<notification name="InviteAdHoc">
[NAME] vous invite à un chat conférence.
-Pour y participer, cliquez sur Accepter. Sinon, cliquez sur Refuser. Pour ignorer cet utilisateur, cliquez sur Ignorer.
+Pour y participer, cliquez sur Accepter. Sinon, cliquez sur Refuser. Pour ignorer cette personne, cliquez sur Ignorer.
<form name="form">
<button name="Accept" text="Accepter"/>
<button name="Decline" text="Refuser"/>
@@ -2942,25 +2527,25 @@ Pour y participer, cliquez sur Accepter. Sinon, cliquez sur Refuser. Pour ignore
Nous sommes désolés. Le nombre maximum de conversations vocales a été atteint dans cette zone. Veuillez trouver un autre endroit pour discuter.
</notification>
<notification name="VoiceChannelDisconnected">
- Vous avez été déconnecté(e) de [VOICE_CHANNEL_NAME]. Vous allez maintenant être reconnecté au chat vocal spatial.
+ Vous avez été déconnecté(e) de [VOICE_CHANNEL_NAME]. Vous allez maintenant être reconnecté(e) au chat vocal près de vous.
</notification>
<notification name="VoiceChannelDisconnectedP2P">
- [VOICE_CHANNEL_NAME] a mis fin à l&apos;appel. Vous allez maintenant être reconnecté au chat vocal spatial.
+ [VOICE_CHANNEL_NAME] a mis fin à l&apos;appel. Vous allez maintenant être reconnecté(e) au chat vocal près de vous.
</notification>
<notification name="P2PCallDeclined">
- [VOICE_CHANNEL_NAME] a refusé votre appel. Vous allez maintenant être reconnecté au chat vocal spatial.
+ [VOICE_CHANNEL_NAME] a refusé votre appel. Vous allez maintenant être reconnecté(e) au chat vocal près de vous.
</notification>
<notification name="P2PCallNoAnswer">
- [VOICE_CHANNEL_NAME] ne peut pas prendre votre appel. Vous allez maintenant être reconnecté au chat vocal spatial.
+ [VOICE_CHANNEL_NAME] ne peut pas prendre votre appel. Vous allez maintenant être reconnecté(e) au chat vocal près de vous.
</notification>
<notification name="VoiceChannelJoinFailed">
- Echec de la connexion avec [VOICE_CHANNEL_NAME], veuillez réessayer ultérieurement. Vous allez maintenant être reconnecté au chat vocal spatial.
+ Échec de la connexion avec [VOICE_CHANNEL_NAME], veuillez réessayer ultérieurement. Vous allez maintenant être reconnecté(e) au chat vocal près de vous.
</notification>
<notification name="VoiceLoginRetry">
Nous sommes en train de créer un canal vocal pour vous. Veuillez patienter quelques instants.
</notification>
<notification name="Cannot enter parcel: not a group member">
- Vous ne pouvez pas pénétrer sur ce terrain car vous n&apos;êtes pas membre du groupe adéquat.
+ Seuls les membres d&apos;un certain groupe peuvent visiter cette zone.
</notification>
<notification name="Cannot enter parcel: banned">
Vous ne pouvez pas pénétrer sur ce terrain car l&apos;accès vous y est interdit.
@@ -2975,18 +2560,43 @@ Pour y participer, cliquez sur Accepter. Sinon, cliquez sur Refuser. Pour ignore
Une erreur est survenue pendant la connexion au chat vocal pour [VOICE_CHANNEL_NAME]. Veuillez réessayer ultérieurement.
</notification>
<notification name="ServerVersionChanged">
- La région dans laquelle vous avez pénétré utilise une version de simulateur différente. Pour plus de détails, cliquez sur ce message.
+ La région dans laquelle vous avez pénétré utilise une version de serveur différente, ce qui peut avoir un impact sur votre performance. [[URL] Consultez les notes de version.]
+ </notification>
+ <notification name="UnsupportedCommandSLURL">
+ La SLurl que vous avez saisie n&apos;est pas prise en charge.
+ </notification>
+ <notification name="IMToast">
+ [MESSAGE]
+ <form name="form">
+ <button name="respondbutton" text="Répondre"/>
+ </form>
+ </notification>
+ <notification name="AttachmentSaved">
+ L&apos;élément joint a été sauvegardé.
+ </notification>
+ <notification name="UnableToFindHelpTopic">
+ Impossible de trouver l&apos;aide.
+ </notification>
+ <notification name="ObjectMediaFailure">
+ Erreur serveur : Échec de la mise à jour ou de l&apos;obtention du média.
+&apos;[ERROR]&apos;
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="ConfirmClearTeleportHistory">
+ Voulez-vous vraiment supprimer votre historique des téléportations ?
+ <usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
</notification>
- <notification name="UnableToOpenCommandURL">
- L&apos;URL sur laquelle vous avez cliqué ne peut pas être ouverte dans ce navigateur.
+ <notification name="BottomTrayButtonCanNotBeShown">
+ Le bouton sélectionné ne peut pas être affiché actuellement.
+Le bouton sera affiché quand il y aura suffisamment de place.
</notification>
<global name="UnsupportedCPU">
- Votre processeur ne remplit pas les conditions minimum requises.
</global>
<global name="UnsupportedGLRequirements">
- Vous semblez ne pas avoir le matériel requis pour utiliser Second Life. Second Life requiert une carte graphique OpenGL avec une prise en charge du multitexturing. Si vous avez une telle carte, assurez-vous que vous avez aussi les drivers les plus récents pour la carte, ainsi que les service packs et les patchs pour votre système d&apos;exploitation.
+ Vous semblez ne pas avoir le matériel requis pour utiliser [APP_NAME]. [APP_NAME] requiert une carte graphique OpenGL avec une prise en charge du multitexturing. Si vous avez une telle carte, assurez-vous que vous avez aussi les pilotes les plus récents pour la carte, ainsi que les service packs et les patchs pour votre système d&apos;exploitation.
-Si vous avez toujours des problèmes, veuillez consulter la page suivante : http://www.secondlife.com/support
+Si vous avez toujours des problèmes, veuillez consulter la page [SUPPORT_SITE].
</global>
<global name="UnsupportedCPUAmount">
796
@@ -3000,10 +2610,8 @@ Si vous avez toujours des problèmes, veuillez consulter la page suivante : ht
<global name="UnsupportedRAM">
- Votre mémoire système ne remplit pas les conditions minimum requises.
</global>
- <global name="PermYes">
- Oui
- </global>
- <global name="PermNo">
- Non
+ <global name="You can only set your &apos;Home Location&apos; on your land or at a mainland Infohub.">
+ Si vous possédez un terrain, vous pouvez le définir comme domicile.
+Sinon, consultez la carte et trouvez les &quot; infohubs &quot;.
</global>
</notifications>
diff --git a/indra/newview/skins/default/xui/fr/panel_activeim_row.xml b/indra/newview/skins/default/xui/fr/panel_activeim_row.xml
new file mode 100644
index 0000000000..84272752cf
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_activeim_row.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_activeim_row">
+ <text name="contact_name">
+ Grumpity ProductEngine
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_adhoc_control_panel.xml b/indra/newview/skins/default/xui/fr/panel_adhoc_control_panel.xml
new file mode 100644
index 0000000000..fd5ca4b2a7
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_adhoc_control_panel.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_im_control_panel">
+ <panel name="panel_call_buttons">
+ <button label="Appeler" name="call_btn"/>
+ <button label="Quitter l&apos;appel" name="end_call_btn"/>
+ <button label="Contrôles vocaux" name="voice_ctrls_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/fr/panel_avatar_list_item.xml
new file mode 100644
index 0000000000..69e23a2e76
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_avatar_list_item.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="avatar_list_item">
+ <string name="FormatSeconds">
+ [COUNT] s
+ </string>
+ <string name="FormatMinutes">
+ [COUNT] mn
+ </string>
+ <string name="FormatHours">
+ [COUNT] h
+ </string>
+ <string name="FormatDays">
+ [COUNT] j
+ </string>
+ <string name="FormatWeeks">
+ [COUNT] s
+ </string>
+ <string name="FormatMonths">
+ [COUNT] m
+ </string>
+ <string name="FormatYears">
+ [COUNT] a
+ </string>
+ <text name="avatar_name" value="Inconnu"/>
+ <text name="last_interaction" value="0s"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_avatar_tag.xml b/indra/newview/skins/default/xui/fr/panel_avatar_tag.xml
new file mode 100644
index 0000000000..20a355b11d
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_avatar_tag.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="avatar_tag_notification">
+ <panel name="msg_caption">
+ <text name="sender_tag_name">
+ Angela Testeur
+ </text>
+ <text name="tag_time" value="23:30"/>
+ </panel>
+ <text_editor name="msg_text">
+ Le renard brun et vif saute par dessus le chien paresseux.
+ </text_editor>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/fr/panel_block_list_sidetray.xml
new file mode 100644
index 0000000000..986970b381
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_block_list_sidetray.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="block_list_panel">
+ <text name="title_text">
+ Liste des ignorés
+ </text>
+ <scroll_list name="blocked" tool_tip="Liste des résidents actuellement ignorés"/>
+ <button label="Ignorer le résident..." label_selected="Ignorer le résident..." name="Block resident..." tool_tip="Choisir un résident à ignorer"/>
+ <button label="Ignorer l&apos;objet par nom..." label_selected="Ignorer l&apos;objet par nom..." name="Block object by name..." tool_tip="Choisir un objet à ignorer par nom"/>
+ <button label="Ne plus ignorer" label_selected="Ne plus ignorer" name="Unblock" tool_tip="Enlever le résident ou l&apos;objet de la liste des ignorés"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_bottomtray.xml b/indra/newview/skins/default/xui/fr/panel_bottomtray.xml
new file mode 100644
index 0000000000..3107bf60e3
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_bottomtray.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="bottom_tray">
+ <string name="SpeakBtnToolTip">
+ Active/Désactive le micro
+ </string>
+ <string name="VoiceControlBtnToolTip">
+ Affiche/Masque le panneau de contrôle vocal
+ </string>
+ <layout_stack name="toolbar_stack">
+ <layout_panel name="gesture_panel">
+ <gesture_combo_box label="Geste" name="Gesture" tool_tip="Affiche/Masque les gestes"/>
+ </layout_panel>
+ <layout_panel name="movement_panel">
+ <button label="Bouger" name="movement_btn" tool_tip="Affiche/Masque le contrôle des déplacements"/>
+ </layout_panel>
+ <layout_panel name="cam_panel">
+ <button label="Affichage" name="camera_btn" tool_tip="Affiche/Masque le contrôle de la caméra"/>
+ </layout_panel>
+ <layout_panel name="snapshot_panel">
+ <button label="" name="snapshots" tool_tip="Prendre une photo"/>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_chat_header.xml b/indra/newview/skins/default/xui/fr/panel_chat_header.xml
new file mode 100644
index 0000000000..babbff3132
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_chat_header.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="im_header" name="im_header">
+ <text_editor name="user_name" value="Ericag Vader"/>
+ <text name="time_box" value="23:30"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_classified_info.xml b/indra/newview/skins/default/xui/fr/panel_classified_info.xml
new file mode 100644
index 0000000000..ca7b1cd971
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_classified_info.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_classified_info">
+ <panel.string name="type_mature">
+ Mature
+ </panel.string>
+ <panel.string name="type_pg">
+ Contenu PG
+ </panel.string>
+ <text name="title" value="Infos sur la petite annonce"/>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <text name="classified_name" value="[name]"/>
+ <text name="classified_location" value="[loading...]"/>
+ <text name="content_type" value="[content type]"/>
+ <text name="category" value="[category]"/>
+ <check_box label="Renouvellement automatique toutes les semaines" name="auto_renew"/>
+ <text name="price_for_listing" tool_tip="Coût de l&apos;annonce.">
+ [PRICE] L$
+ </text>
+ <text name="classified_desc" value="[description]"/>
+ </panel>
+ </scroll_container>
+ <panel name="buttons">
+ <button label="Téléporter" name="teleport_btn"/>
+ <button label="Carte" name="show_on_map_btn"/>
+ <button label="Édition" name="edit_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_alpha.xml b/indra/newview/skins/default/xui/fr/panel_edit_alpha.xml
new file mode 100644
index 0000000000..836dd99097
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_edit_alpha.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_alpha_panel">
+ <panel name="avatar_alpha_color_panel">
+ <texture_picker label="Alpha bas" name="Lower Alpha" tool_tip="Cliquez pour sélectionner une image"/>
+ <texture_picker label="Alpha haut" name="Upper Alpha" tool_tip="Cliquez pour sélectionner une image"/>
+ <texture_picker label="Alpha tête" name="Head Alpha" tool_tip="Cliquez pour sélectionner une image"/>
+ <texture_picker label="Alpha yeux" name="Eye Alpha" tool_tip="Cliquez pour sélectionner une image"/>
+ <texture_picker label="Alpha cheveux" name="Hair Alpha" tool_tip="Cliquez pour sélectionner une image"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_classified.xml b/indra/newview/skins/default/xui/fr/panel_edit_classified.xml
new file mode 100644
index 0000000000..392586d8d4
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_edit_classified.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Modifier la petite annonce" name="panel_edit_classified">
+ <panel.string name="location_notice">
+ (mise à jour après l&apos;enregistrement)
+ </panel.string>
+ <text name="title">
+ Modifier la petite annonce
+ </text>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <icon label="" name="edit_icon" tool_tip="Cliquez pour sélectionner une image"/>
+ <text name="Name:">
+ Titre :
+ </text>
+ <text name="description_label">
+ Description :
+ </text>
+ <text name="location_label">
+ Lieu :
+ </text>
+ <text name="classified_location">
+ en cours de chargement...
+ </text>
+ <button label="Définir sur l&apos;emplacement actuel" name="set_to_curr_location_btn"/>
+ <combo_box name="content_type">
+ <combo_item name="mature_ci">
+ Contenu Mature
+ </combo_item>
+ <combo_item name="pg_ci">
+ Contenu PG
+ </combo_item>
+ </combo_box>
+ <spinner label="L$" name="price_for_listing" tool_tip="Coût de l&apos;annonce." value="50"/>
+ <check_box label="Renouvellement automatique toutes les semaines" name="auto_renew"/>
+ </panel>
+ </scroll_container>
+ <panel label="bottom_panel" name="bottom_panel">
+ <button label="Enregistrer" name="save_changes_btn"/>
+ <button label="Annuler" name="cancel_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_eyes.xml b/indra/newview/skins/default/xui/fr/panel_edit_eyes.xml
new file mode 100644
index 0000000000..7de6ca8b3f
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_edit_eyes.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_eyes_panel">
+ <panel name="avatar_eye_color_panel">
+ <texture_picker label="Iris" name="Iris" tool_tip="Cliquez pour sélectionner une image"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="eyes_main_tab" title="Yeux"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_gloves.xml b/indra/newview/skins/default/xui/fr/panel_edit_gloves.xml
new file mode 100644
index 0000000000..e37e0b2481
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_edit_gloves.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_gloves_panel">
+ <panel name="avatar_gloves_color_panel">
+ <texture_picker label="Tissu" name="Fabric" tool_tip="Cliquez pour sélectionner une image"/>
+ <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="gloves_main_tab" title="Gants"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_hair.xml b/indra/newview/skins/default/xui/fr/panel_edit_hair.xml
new file mode 100644
index 0000000000..9293c23e19
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_edit_hair.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_hair_panel">
+ <panel name="avatar_hair_color_panel">
+ <texture_picker label="Texture" name="Texture" tool_tip="Cliquez pour sélectionner une image"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="hair_color_tab" title="Couleur"/>
+ <accordion_tab name="hair_style_tab" title="Coupe"/>
+ <accordion_tab name="hair_eyebrows_tab" title="Sourcils"/>
+ <accordion_tab name="hair_facial_tab" title="Pilosité du visage"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_jacket.xml b/indra/newview/skins/default/xui/fr/panel_edit_jacket.xml
new file mode 100644
index 0000000000..759db657a6
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_edit_jacket.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_jacket_panel">
+ <panel name="avatar_jacket_color_panel">
+ <texture_picker label="Tissu (haut)" name="Upper Fabric" tool_tip="Cliquez pour sélectionner une image"/>
+ <texture_picker label="Tissu (bas)" name="Lower Fabric" tool_tip="Cliquez pour sélectionner une image"/>
+ <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="jacket_main_tab" title="Veste"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_pants.xml b/indra/newview/skins/default/xui/fr/panel_edit_pants.xml
new file mode 100644
index 0000000000..5328e885d3
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_edit_pants.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_pants_panel">
+ <panel name="avatar_pants_color_panel">
+ <texture_picker label="Tissu" name="Fabric" tool_tip="Cliquez pour sélectionner une image"/>
+ <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="pants_main_tab" title="Pantalon"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_pick.xml b/indra/newview/skins/default/xui/fr/panel_edit_pick.xml
new file mode 100644
index 0000000000..f234529764
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_edit_pick.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Modifier la préférence" name="panel_edit_pick">
+ <text name="title">
+ Modifier la préférence
+ </text>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <icon label="" name="edit_icon" tool_tip="Cliquez pour sélectionner une image"/>
+ <text name="Name:">
+ Titre :
+ </text>
+ <text name="description_label">
+ Description :
+ </text>
+ <text name="location_label">
+ Lieu :
+ </text>
+ <text name="pick_location">
+ en cours de chargement...
+ </text>
+ <button label="Définir sur l&apos;emplacement actuel" name="set_to_curr_location_btn"/>
+ </panel>
+ </scroll_container>
+ <panel label="bottom_panel" name="bottom_panel">
+ <button label="Enregistrer [WHAT]" name="save_changes_btn"/>
+ <button label="Annuler" name="cancel_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_profile.xml b/indra/newview/skins/default/xui/fr/panel_edit_profile.xml
new file mode 100644
index 0000000000..a4771db91b
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_edit_profile.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Modification du profil" name="edit_profile_panel">
+ <string name="CaptionTextAcctInfo">
+ [ACCTTYPE]
+[PAYMENTINFO] [AGEVERIFICATION]
+ </string>
+ <string name="RegisterDateFormat">
+ [REG_DATE] ([AGE])
+ </string>
+ <string name="AcctTypeResident" value="Résident"/>
+ <string name="AcctTypeTrial" value="Essai"/>
+ <string name="AcctTypeCharterMember" value="Membre originaire"/>
+ <string name="AcctTypeEmployee" value="Employé(e) de Linden Lab"/>
+ <string name="PaymentInfoUsed" value="Infos de paiement utilisées"/>
+ <string name="PaymentInfoOnFile" value="Infos de paiement enregistrées"/>
+ <string name="NoPaymentInfoOnFile" value="Aucune info de paiement enregistrée"/>
+ <string name="AgeVerified" value="Personne dont l&apos;âge a été vérifié"/>
+ <string name="NotAgeVerified" value="Personne dont l&apos;âge n&apos;a pas été vérifié"/>
+ <string name="partner_edit_link_url">
+ http://www.secondlife.com/account/partners.php?lang=fr
+ </string>
+ <string name="no_partner_text" value="Aucun"/>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <panel name="data_panel">
+ <panel name="lifes_images_panel">
+ <panel name="second_life_image_panel">
+ <text name="second_life_photo_title_text" value="[SECOND_LIFE]:"/>
+ </panel>
+ <icon label="" name="2nd_life_edit_icon" tool_tip="Cliquez pour sélectionner une image"/>
+ </panel>
+ <panel name="first_life_image_panel">
+ <text name="real_world_photo_title_text" value="Monde physique :"/>
+ </panel>
+ <icon label="" name="real_world_edit_icon" tool_tip="Cliquez pour sélectionner une image"/>
+ <text name="title_homepage_text">
+ Page d&apos;accueil :
+ </text>
+ <line_editor name="homepage_edit" value="http://"/>
+ <check_box label="Afficher dans les résultats de recherche" name="show_in_search_checkbox"/>
+ <text name="title_acc_status_text" value="Mon compte :"/>
+ <text name="my_account_link" value="[[URL] Accéder à ma Page d&apos;accueil]"/>
+ <text name="acc_status_text" value="Résident. Aucune info de paiement enregistrée."/>
+ <text name="title_partner_text" value="Mon partenaire :"/>
+ <text name="partner_edit_link" value="[[URL] Modifier]"/>
+ <panel name="partner_data_panel">
+ <text name="partner_text" value="[FIRST] [LAST]"/>
+ </panel>
+ </panel>
+ </panel>
+ </scroll_container>
+ <panel name="profile_me_buttons_panel">
+ <button label="Enregistrer les changements" name="save_btn"/>
+ <button label="Annuler" name="cancel_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_shape.xml b/indra/newview/skins/default/xui/fr/panel_edit_shape.xml
new file mode 100644
index 0000000000..450b23608a
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_edit_shape.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_shape_panel">
+ <panel name="avatar_sex_panel">
+ <text name="gender_text">
+ Sexe :
+ </text>
+ <radio_group name="sex_radio">
+ <radio_item label="Femme" name="radio"/>
+ <radio_item label="Homme" name="radio2"/>
+ </radio_group>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="shape_body_tab" title="Corps"/>
+ <accordion_tab name="shape_head_tab" title="Tête"/>
+ <accordion_tab name="shape_eyes_tab" title="Yeux"/>
+ <accordion_tab name="shape_ears_tab" title="Oreilles"/>
+ <accordion_tab name="shape_nose_tab" title="Nez"/>
+ <accordion_tab name="shape_mouth_tab" title="Bouche"/>
+ <accordion_tab name="shape_chin_tab" title="Menton"/>
+ <accordion_tab name="shape_torso_tab" title="Torse"/>
+ <accordion_tab name="shape_legs_tab" title="Jambes"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_shirt.xml b/indra/newview/skins/default/xui/fr/panel_edit_shirt.xml
new file mode 100644
index 0000000000..0fe7d5bbb0
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_edit_shirt.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_shirt_panel">
+ <panel name="avatar_shirt_color_panel">
+ <texture_picker label="Tissu" name="Fabric" tool_tip="Cliquez pour sélectionner une image"/>
+ <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="shirt_main_tab" title="Chemise"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_shoes.xml b/indra/newview/skins/default/xui/fr/panel_edit_shoes.xml
new file mode 100644
index 0000000000..588a2ca7b2
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_edit_shoes.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_shoes_panel">
+ <panel name="avatar_shoes_color_panel">
+ <texture_picker label="Tissu" name="Fabric" tool_tip="Cliquez pour sélectionner une image"/>
+ <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="shoes_main_tab" title="Chaussures"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_skin.xml b/indra/newview/skins/default/xui/fr/panel_edit_skin.xml
new file mode 100644
index 0000000000..649b91d66d
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_edit_skin.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_skin_panel">
+ <panel name="avatar_skin_color_panel">
+ <texture_picker label="Tatouage tête" name="Head Tattoos" tool_tip="Cliquez pour sélectionner une image"/>
+ <texture_picker label="Tatouage haut" name="Upper Tattoos" tool_tip="Cliquez pour sélectionner une image"/>
+ <texture_picker label="Tatouage bas" name="Lower Tattoos" tool_tip="Cliquez pour sélectionner une image"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="skin_color_tab" title="Couleur de peau"/>
+ <accordion_tab name="skin_face_tab" title="Détails du visage"/>
+ <accordion_tab name="skin_makeup_tab" title="Maquillage"/>
+ <accordion_tab name="skin_body_tab" title="Détails du corps"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_skirt.xml b/indra/newview/skins/default/xui/fr/panel_edit_skirt.xml
new file mode 100644
index 0000000000..9d0f13c4e8
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_edit_skirt.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_skirt_panel">
+ <panel name="avatar_skirt_color_panel">
+ <texture_picker label="Tissu" name="Fabric" tool_tip="Cliquez pour sélectionner une image"/>
+ <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="skirt_main_tab" title="Jupe"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_socks.xml b/indra/newview/skins/default/xui/fr/panel_edit_socks.xml
new file mode 100644
index 0000000000..8b062e0145
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_edit_socks.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_socks_panel">
+ <panel name="avatar_socks_color_panel">
+ <texture_picker label="Tissu" name="Fabric" tool_tip="Cliquez pour sélectionner une image"/>
+ <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="socks_main_tab" title="Chaussettes"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/fr/panel_edit_tattoo.xml
new file mode 100644
index 0000000000..1faee191e0
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_edit_tattoo.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_tattoo_panel">
+ <panel name="avatar_tattoo_color_panel">
+ <texture_picker label="Tatouage tête" name="Head Tattoo" tool_tip="Cliquez pour sélectionner une image"/>
+ <texture_picker label="Tatouage haut" name="Upper Tattoo" tool_tip="Cliquez pour sélectionner une image"/>
+ <texture_picker label="Tatouage bas" name="Lower Tattoo" tool_tip="Cliquez pour sélectionner une image"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_underpants.xml b/indra/newview/skins/default/xui/fr/panel_edit_underpants.xml
new file mode 100644
index 0000000000..b9164ad862
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_edit_underpants.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_underpants_panel">
+ <panel name="avatar_underpants_color_panel">
+ <texture_picker label="Tissu" name="Fabric" tool_tip="Cliquez pour sélectionner une image"/>
+ <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="underpants_main_tab" title="Sous-vêtements (femme)"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_undershirt.xml b/indra/newview/skins/default/xui/fr/panel_edit_undershirt.xml
new file mode 100644
index 0000000000..462eff9451
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_edit_undershirt.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_undershirt_panel">
+ <panel name="avatar_undershirt_color_panel">
+ <texture_picker label="Tissu" name="Fabric" tool_tip="Cliquez pour sélectionner une image"/>
+ <color_swatch label="Couleur/Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="undershirt_main_tab" title="Sous-vêtements (homme)"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_wearable.xml b/indra/newview/skins/default/xui/fr/panel_edit_wearable.xml
new file mode 100644
index 0000000000..24ea030b33
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_edit_wearable.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Portable" name="panel_edit_wearable">
+ <string name="edit_shape_title">
+ Modification de la silhouette
+ </string>
+ <string name="edit_skin_title">
+ Modification de la peau
+ </string>
+ <string name="edit_hair_title">
+ Modification des cheveux
+ </string>
+ <string name="edit_eyes_title">
+ Modification des yeux
+ </string>
+ <string name="edit_shirt_title">
+ Modification de la chemise
+ </string>
+ <string name="edit_pants_title">
+ Modification du pantalon
+ </string>
+ <string name="edit_shoes_title">
+ Modification des chaussures
+ </string>
+ <string name="edit_socks_title">
+ Modification des chaussettes
+ </string>
+ <string name="edit_jacket_title">
+ Modification de la veste
+ </string>
+ <string name="edit_skirt_title">
+ Modification de la jupe
+ </string>
+ <string name="edit_gloves_title">
+ Modification des gants
+ </string>
+ <string name="edit_undershirt_title">
+ Modification des sous-vêtements (homme)
+ </string>
+ <string name="edit_underpants_title">
+ Modification des sous-vêtements (femme)
+ </string>
+ <string name="edit_alpha_title">
+ Modification du masque alpha
+ </string>
+ <string name="edit_tattoo_title">
+ Modification du tatouage
+ </string>
+ <string name="shape_desc_text">
+ Silhouette :
+ </string>
+ <string name="skin_desc_text">
+ Peau :
+ </string>
+ <string name="hair_desc_text">
+ Cheveux :
+ </string>
+ <string name="eyes_desc_text">
+ Yeux :
+ </string>
+ <string name="shirt_desc_text">
+ Chemise :
+ </string>
+ <string name="pants_desc_text">
+ Pantalon :
+ </string>
+ <string name="shoes_desc_text">
+ Chaussures :
+ </string>
+ <string name="socks_desc_text">
+ Chaussettes :
+ </string>
+ <string name="jacket_desc_text">
+ Veste :
+ </string>
+ <string name="skirt_skirt_desc_text">
+ Jupe :
+ </string>
+ <string name="gloves_desc_text">
+ Gants :
+ </string>
+ <string name="undershirt_desc_text">
+ Sous-vêtements (homme) :
+ </string>
+ <string name="underpants_desc_text">
+ Sous-vêtements (femme) :
+ </string>
+ <string name="alpha_desc_text">
+ Masque alpha :
+ </string>
+ <string name="tattoo_desc_text">
+ Tatouage :
+ </string>
+ <text name="edit_wearable_title" value="Modification de la silhouette"/>
+ <panel label="Chemise" name="wearable_type_panel">
+ <text name="description_text" value="Silhouette :"/>
+ </panel>
+ <panel name="button_panel">
+ <button label="Enregistrer sous" name="save_as_button"/>
+ <button label="Annuler modification" name="revert_button"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_group_control_panel.xml b/indra/newview/skins/default/xui/fr/panel_group_control_panel.xml
new file mode 100644
index 0000000000..3e37ba66da
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_group_control_panel.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_im_control_panel">
+ <button label="Profil du groupe" name="group_info_btn"/>
+ <panel name="panel_call_buttons">
+ <button label="Appeler le groupe" name="call_btn"/>
+ <button label="Quitter l&apos;appel" name="end_call_btn"/>
+ <button label="Ouvrir les contrôles vocaux" name="voice_ctrls_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_group_general.xml b/indra/newview/skins/default/xui/fr/panel_group_general.xml
index 2b983ced80..093d65cdba 100644
--- a/indra/newview/skins/default/xui/fr/panel_group_general.xml
+++ b/indra/newview/skins/default/xui/fr/panel_group_general.xml
@@ -1,76 +1,37 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Général" name="general_tab">
- <string name="help_text">
- L&apos;onglet Général contient les infos générales et les préférences du groupe ainsi que la liste des propriétaires et des membres visibles.
- </string>
- <string name="group_info_unchanged">
+ <panel.string name="help_text">
+ L&apos;onglet Général contient les informations générales et les préférences du groupe ainsi que la liste et les options des membres.
+
+Faites glisser le pointeur de la souris sur les options pour en savoir plus.
+ </panel.string>
+ <panel.string name="group_info_unchanged">
Le profil du groupe a changé.
- </string>
- <button label="?" label_selected="?" name="help_button"/>
- <line_editor label="Saisissez le nom du groupe ici" name="group_name_editor"/>
- <text name="group_name">
- Saisissez le nom du groupe ici
- </text>
- <text name="prepend_founded_by">
- Fondé par
- </text>
- <text left_delta="54" name="founder_name">
- (en attente)
- </text>
- <text name="group_charter_label">
- Charte du groupe
- </text>
- <texture_picker label="Logo du groupe" name="insignia" tool_tip="Cliquez pour sélectionner une image"/>
+ </panel.string>
+ <panel.string name="incomplete_member_data_str">
+ Extraction des données du résident en cours
+ </panel.string>
<text_editor name="charter">
Indiquez ici la charte de votre groupe
</text_editor>
- <button label="Rejoindre (0L$)" label_selected="Rejoindre (0L$)" name="join_button"/>
- <button label="Affichage détaillé" label_selected="Affichage détaillé" name="info_button"/>
- <text name="text_owners_and_visible_members">
- Propriétaires et membres visibles
- </text>
- <text name="text_owners_are_shown_in_bold">
- (Les propriétaires apparaissent en gras)
- </text>
<name_list name="visible_members">
- <column label="Nom du membre" name="name" relwidth="0.40"/>
- <column label="Titre" name="title" relwidth="0.25"/>
- <column label="Dernière connexion" name="online" relwidth="0.35"/>
+ <name_list.columns label="Membre" name="name" relwidth="0.40"/>
+ <name_list.columns label="Titre" name="title" relwidth="0.25"/>
</name_list>
- <text name="text_group_preferences">
- Préférences
+ <text name="active_title_label">
+ Mon titre
</text>
+ <combo_box name="active_title" tool_tip="Indique le titre qui apparaît en face du nom de votre avatar lorsque votre groupe est actif."/>
+ <check_box label="Recevoir des notices" name="receive_notices" tool_tip="Indique si vous souhaitez recevoir les notices envoyées au groupe. Décochez si ce groupe vous envoie des spams."/>
+ <check_box label="Afficher dans mon profil" name="list_groups_in_profile" tool_tip="Indique si vous voulez afficher ce groupe dans votre profil"/>
<panel name="preferences_container">
- <check_box label="Afficher dans la recherche" name="show_in_group_list" tool_tip="Afficher ce groupe dans les résultats de recherche."/>
- <check_box label="Inscription libre" name="open_enrollement" tool_tip="Indique si une invitation est nécessaire pour devenir membre de ce groupe."/>
- <check_box label="Frais d&apos;inscription : L$" name="check_enrollment_fee" tool_tip="Indique s&apos;il y a des frais d&apos;inscription pour devenir membre."/>
- <spinner name="spin_enrollment_fee" tool_tip="Si la case Frais d&apos;inscription est cochée, cela signifie qu&apos;il faut payer des frais pour devenir membre."/>
- <combo_box name="group_mature_check" tool_tip="Indique si les informations sur votre groupe sont classées Mature." width="195">
- <combo_item name="select_mature">
- - Type de public -
- </combo_item>
- <combo_item name="mature">
- Contenu Mature
- </combo_item>
- <combo_item name="pg">
- Contenu PG
- </combo_item>
+ <check_box label="Inscription libre" name="open_enrollement" tool_tip="Indique si ce groupe autorise les nouveaux membres à le rejoindre sans y être invités."/>
+ <check_box label="Frais d&apos;inscription" name="check_enrollment_fee" tool_tip="Indique s&apos;il faut payer des frais d&apos;inscription pour rejoindre ce groupe"/>
+ <spinner label="L$" name="spin_enrollment_fee" tool_tip="Les nouveaux membres doivent payer ces frais pour rejoindre le groupe quand l&apos;option Frais d&apos;inscription est cochée."/>
+ <check_box initial_value="true" label="Afficher dans la recherche" name="show_in_group_list" tool_tip="Permettre aux autres résidents de voir ce groupe dans les résultats de recherche"/>
+ <combo_box name="group_mature_check" tool_tip="Indique si les informations sur votre groupe sont classées Mature" width="195">
+ <combo_box.item label="Contenu PG" name="pg"/>
+ <combo_box.item label="Contenu Mature" name="mature"/>
</combo_box>
- <panel name="title_container">
- <text name="active_title_label">
- Mon titre actuel
- </text>
- <combo_box name="active_title" tool_tip="Définit le titre qui apparaît près du nom de votre avatar lorsque ce groupe est actif."/>
- </panel>
- <check_box label="Recevoir les notices" name="receive_notices" tool_tip="Cochez si vous souhaitez recevoir les notices envoyées au groupe. Décochez si ce groupe vous envoie des spams."/>
- <check_box label="Afficher dans mon profil" name="list_groups_in_profile" tool_tip="Indique si vous voulez que ce groupe apparaisse dans votre profil"/>
</panel>
- <string name="incomplete_member_data_str">
- Extraction des données du résident en cours
- </string>
- <string name="confirm_group_create_str">
- La création de ce groupe coûte 100 L$.
-Êtes-vous vraiment certain de vouloir dépenser 100 L$ pour créer ce groupe ?
-Sachez que si personne ne rejoint ce groupe sous 48h, il sera démantelé et ne pourra plus être utilisé.
- </string>
</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/fr/panel_group_info_sidetray.xml
new file mode 100644
index 0000000000..28d13bf3c5
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_group_info_sidetray.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Profil du groupe" name="GroupInfo">
+ <panel.string name="default_needs_apply_text">
+ Certaines modifications sur cet onglet n&apos;ont pas été enregistrées.
+ </panel.string>
+ <panel.string name="want_apply_text">
+ Voulez-vous enregistrer ces modifications ?
+ </panel.string>
+ <panel.string name="group_join_btn">
+ Rejoindre ([AMOUNT] L$)...
+ </panel.string>
+ <panel.string name="group_join_free">
+ Gratuit
+ </panel.string>
+ <text name="group_name" value="(en cours de chargement...)"/>
+ <line_editor label="Saisissez le nom du groupe ici" name="group_name_editor"/>
+ <texture_picker label="" name="insignia" tool_tip="Cliquez pour sélectionner une image"/>
+ <text name="prepend_founded_by">
+ Fondateur :
+ </text>
+ <name_box initial_value="(récupération en cours)" name="founder_name"/>
+ <text name="join_cost_text">
+ Gratuit
+ </text>
+ <button label="REJOINDRE" name="btn_join"/>
+ <accordion name="groups_accordion">
+ <accordion_tab name="group_general_tab" title="Général"/>
+ <accordion_tab name="group_roles_tab" title="Rôles"/>
+ <accordion_tab name="group_notices_tab" title="Notices"/>
+ <accordion_tab name="group_land_tab" title="Terrain/Actifs"/>
+ </accordion>
+ <panel name="button_row">
+ <button label="Créer" label_selected="Nouveau groupe" name="btn_create"/>
+ <button label="Enregistrer" label_selected="Enregistrer" name="btn_apply"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_group_invite.xml b/indra/newview/skins/default/xui/fr/panel_group_invite.xml
index 4cb0b88672..0e59366b84 100644
--- a/indra/newview/skins/default/xui/fr/panel_group_invite.xml
+++ b/indra/newview/skins/default/xui/fr/panel_group_invite.xml
@@ -1,26 +1,29 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Inviter un résident" name="invite_panel">
+ <panel.string name="confirm_invite_owner_str">
+ Etes-vous certain de vouloir inviter un/de nouveau(x) propriétaire(s) ? Ce choix est permanent !
+ </panel.string>
+ <panel.string name="loading">
+ (en cours de chargement...)
+ </panel.string>
+ <panel.string name="already_in_group">
+ Certains des avatars font déjà partie du groupe et n&apos;ont pas été invités.
+ </panel.string>
<text name="help_text">
Vous pouvez inviter plusieurs résidents
à la fois. Cliquez d&apos;abord sur
Choisir un résident.
</text>
<button label="Choisir un résident" name="add_button" tool_tip=""/>
- <name_list name="invitee_list" tool_tip="Pour sélectionner plusieurs noms, maintenez la touche Ctrl enfoncée en cliquant sur le nom des résidents."/>
- <button label="Supprimer de la liste" name="remove_button" tool_tip="Supprime les résidents sélectionnés de la liste des invités."/>
- <text>
- Assignez-leur un rôle :
- </text>
+ <name_list name="invitee_list" tool_tip="Pour sélectionner plusieurs résidents, maintenez la touche Ctrl enfoncée et cliquez sur leurs noms"/>
+ <button label="Supprimer de la liste" name="remove_button" tool_tip="Supprime les résidents sélectionnés ci-dessus de la liste des invités"/>
<text name="role_text">
Assignez-leur un rôle :
</text>
- <combo_box name="role_name" tool_tip="Choisissez des rôles à assigner aux membres dans la liste."/>
+ <combo_box name="role_name" tool_tip="Choisissez dans la liste de rôles que vous êtes autorisé(e) à attribuer aux membres"/>
<button label="Envoyer les invitations" name="ok_button"/>
<button label="Annuler" name="cancel_button"/>
- <string name="confirm_invite_owner_str">
- Etes-vous certain de vouloir inviter un/de nouveau(x) propriétaire(s) ? Ce choix est permanent !
- </string>
- <string name="loading">
- (en cours de chargement...)
+ <string name="GroupInvitation">
+ Invitations au groupe
</string>
</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_group_land_money.xml b/indra/newview/skins/default/xui/fr/panel_group_land_money.xml
index 551d11d588..3ca22b6e21 100644
--- a/indra/newview/skins/default/xui/fr/panel_group_land_money.xml
+++ b/indra/newview/skins/default/xui/fr/panel_group_land_money.xml
@@ -1,15 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Terrain et L$" name="land_money_tab">
<string name="help_text">
- Les parcelles appartenant au groupe sont indiquées avec le détails des contributions. Un avertissement apparaît si la surface utilisée par le groupe est supérieure ou égale au total des contributions. Les onglets Planification, Détails et Ventes correspondent aux finances du groupe.
+ Un avertissement apparaît si la surface utilisée par le groupe est supérieure ou égale au total des contributions.
</string>
<button label="?" name="help_button"/>
<string name="cant_view_group_land_text">
- Vous n&apos;avez pas la permission de voir quel terrain possède ce groupe.
+ Vous n&apos;avez pas la permission de voir quel terrain possède ce groupe
</string>
<string name="cant_view_group_accounting_text">
- Vous n&apos;avez pas la permission d&apos;accéder aux informations
-financières de ce groupe.
+ Vous n&apos;avez pas la permission d&apos;accéder aux informations financières de ce groupe.
</string>
<string name="loading_txt">
Chargement...
@@ -24,60 +23,62 @@ financières de ce groupe.
<column label="Surface" name="area"/>
<column label="" name="hidden"/>
</scroll_list>
- <button label="Voir sur la carte" label_selected="Voir sur la carte" name="map_button"/>
+ <button label="Carte" label_selected="Carte" name="map_button"/>
<text name="total_contributed_land_label">
- Total des contributions :
+ Total des contributions :
</text>
<text name="total_contributed_land_value">
[AREA] m²
</text>
<text name="total_land_in_use_label">
- Superficie déjà utilisée :
+ Superficie déjà utilisée :
</text>
<text name="total_land_in_use_value">
[AREA] m²
</text>
<text name="land_available_label">
- Superficie disponible :
+ Superficie disponible :
</text>
<text name="land_available_value">
[AREA] m²
</text>
<text name="your_contribution_label">
- Votre contribution :
+ Votre contribution :
</text>
<string name="land_contrib_error">
- Impossible de définir votre don de terre.
+ Impossible de définir votre don de terrain
</string>
+ <text name="your_contribution_units">
+ m²
+ </text>
<text name="your_contribution_max_value">
- m² ([AMOUNT] max.)
+ ([AMOUNT] max.)
</text>
<text name="group_over_limit_text">
- Une contribution supplémentaire du groupe est requise pour prendre en
-charge le terrain utilisé.
+ Une contribution supplémentaire est requise pour prendre en charge le terrain utilisé
</text>
<text name="group_money_heading">
Finances
</text>
<tab_container name="group_money_tab_container">
- <panel label="Planification" name="group_money_planning_tab">
+ <panel label="PLANIFICATION" name="group_money_planning_tab">
<text_editor name="group_money_planning_text">
- Calcul en cours...
+ Chargement...
</text_editor>
</panel>
- <panel label="Détails" name="group_money_details_tab">
+ <panel label="DÉTAILS" name="group_money_details_tab">
<text_editor name="group_money_details_text">
- Calcul en cours...
+ Chargement...
</text_editor>
- <button label="&lt; Plus tôt" label_selected="&lt; Plus tôt" name="earlier_details_button" tool_tip="Reculer dans le temps"/>
- <button label="Plus tard &gt;" label_selected="Plus tard &gt;" name="later_details_button" tool_tip="Avancer dans le temps"/>
+ <button label="&lt; Plus tôt" label_selected="&lt; Plus tôt" name="earlier_details_button" tool_tip="Précédent"/>
+ <button label="Plus tard &gt;" label_selected="Plus tard &gt;" name="later_details_button" tool_tip="Suivant"/>
</panel>
- <panel label="Ventes" name="group_money_sales_tab">
+ <panel label="VENTES" name="group_money_sales_tab">
<text_editor name="group_money_sales_text">
- Calcul en cours...
+ Chargement...
</text_editor>
- <button label="&lt; Plus tôt" label_selected="&lt; Plus tôt" name="earlier_sales_button" tool_tip="Reculer dans le temps"/>
- <button label="Plus tard &gt;" label_selected="Plus tard &gt;" name="later_sales_button" tool_tip="Avancer dans le temps"/>
+ <button label="&lt; Plus tôt" label_selected="&lt; Plus tôt" name="earlier_sales_button" tool_tip="Précédent"/>
+ <button label="Plus tard &gt;" label_selected="Plus tard &gt;" name="later_sales_button" tool_tip="Suivant"/>
</panel>
</tab_container>
</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_group_list_item.xml b/indra/newview/skins/default/xui/fr/panel_group_list_item.xml
new file mode 100644
index 0000000000..a61cb787a8
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_group_list_item.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="group_list_item">
+ <text name="group_name" value="Inconnu"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_group_notices.xml b/indra/newview/skins/default/xui/fr/panel_group_notices.xml
index d824ae5461..188fe28d8a 100644
--- a/indra/newview/skins/default/xui/fr/panel_group_notices.xml
+++ b/indra/newview/skins/default/xui/fr/panel_group_notices.xml
@@ -1,64 +1,59 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Notices" name="notices_tab">
- <text name="help_text">
- Les notices vous permettent d&apos;envoyer des messages et pièces-jointes aux membres du groupe autorisés à les recevoir. Vous pouvez désactiver la réception des notices à l&apos;onglet Général.
- </text>
- <text name="no_notices_text">
- Aucune notice
- </text>
- <button label="?" label_selected="?" name="help_button"/>
- <text name="lbl">
- Anciennes notices du groupe
- </text>
+ <panel.string name="help_text">
+ Les notices vous permettent d&apos;envoyer un message et,
+facultativement, une pièce jointe. Les notices ne peuvent être envoyées
+qu&apos;aux membres du groupe dont le rôle leur permet de
+recevoir des notices. Vous pouvez désactiver la réception des notices dans
+l&apos;onglet Général.
+ </panel.string>
+ <panel.string name="no_notices_text">
+ Pas d&apos;anciennes notices
+ </panel.string>
<text name="lbl2">
- Double-cliquez sur une notice pour l'afficher. Les notices sont conservées
-pendant 14 jours et chaque groupe a une limite quotidienne de 200 notices.
+ Les notices sont conservées pendant 14 jours.
+200 maximum par groupe et par jour
</text>
<scroll_list name="notice_list">
- <column label="" name="icon"/>
- <column label="Sujet" name="subject"/>
- <column label="De" name="from"/>
- <column label="Date" name="date"/>
+ <scroll_list.columns label="" name="icon"/>
+ <scroll_list.columns label="Sujet" name="subject"/>
+ <scroll_list.columns label="De" name="from"/>
+ <scroll_list.columns label="Date" name="date"/>
</scroll_list>
<text name="notice_list_none_found">
- Aucun résultat.
+ Aucun résultat
</text>
- <button label="Créer une notice" label_selected="Créer une notice" name="create_new_notice"/>
+ <button label="Créer une notice" label_selected="Créer une notice" name="create_new_notice" tool_tip="Créer une notice"/>
<button label="Rafraîchir" label_selected="Rafraîchir la liste" name="refresh_notices"/>
<panel label="Créer une notice" name="panel_create_new_notice">
<text name="lbl">
Créer une notice
</text>
- <text name="lbl2">
- Pour envoyer une notice, saisissez un sujet. Pour joindre
-une pièce-jointe à cette notice, faites-la glisser depuis votre
-inventaire vers cette fenêtre. Les pièces-jointes doivent être
-copiables et transférables. Il n&apos;est pas possible d&apos;envoyer de
-dossiers.
- </text>
- <text bottom_delta="-79" name="lbl3" left="20">
+ <text bottom_delta="-79" left="20" name="lbl3">
Sujet :
</text>
- <line_editor name="create_subject" width="331" left_delta="61"/>
- <text name="lbl4" left="20">
+ <line_editor left_delta="61" name="create_subject" width="331"/>
+ <text left="20" name="lbl4">
Message :
</text>
- <text_editor name="create_message" bottom_delta="-90" height="104" left_delta="61" width="330"/>
+ <text_editor bottom_delta="-90" height="104" left_delta="61" name="create_message" width="330"/>
<text name="lbl5" width="68">
Pièce-jointe :
</text>
- <line_editor name="create_inventory_name" width="190" left_delta="74"/>
- <button label="Supprimer pièce-jointe" label_selected="Supprimer pièce-jointe" left="274" name="remove_attachment" width="140"/>
- <button label="Envoyer la notice" label_selected="Envoyer la notice" left="274" name="send_notice" width="140"/>
- <panel name="drop_target2" tool_tip="Pour joindre un objet de l&apos;inventaire à la notice, faites-le glisser dans la boîte de message. Pour envoyer l&apos;objet avec la notice, vous devez avoir la permission de le copier et de le transférer."/>
- <panel name="drop_target" tool_tip="Pour joindre un objet de l&apos;inventaire à la notice, faites-le glisser dans la boîte de message. Pour envoyer l&apos;objet avec la notice, vous devez avoir la permission de le copier et de le transférer."/>
+ <line_editor left_delta="74" name="create_inventory_name" width="190"/>
+ <text name="string">
+ Faites glisser ici pour joindre quelque chose -- &gt;
+ </text>
+ <button label="Supprimer" label_selected="Supprimer pièce-jointe" left="274" name="remove_attachment" width="140"/>
+ <button label="Envoyer" label_selected="Envoyer" left="274" name="send_notice" width="140"/>
+ <group_drop_target name="drop_target" tool_tip="Pour joindre un objet de l&apos;inventaire à la notice, faites-le glisser dans la boîte de message. Pour envoyer l&apos;objet avec la notice, vous devez avoir la permission de le copier et de le transférer."/>
</panel>
<panel label="Voir ancienne notice" name="panel_view_past_notice">
<text name="lbl">
Détails
</text>
<text name="lbl2">
- Pour envoyer une nouvelle notice, cliquez sur Créer une notice ci-dessus.
+ Pour envoyer une nouvelle notice, cliquez sur le bouton +
</text>
<text name="lbl3">
Sujet :
@@ -66,7 +61,7 @@ dossiers.
<text name="lbl4">
Message :
</text>
- <button label="Ouvrir pièce-jointe" label_selected="Ouvrir pièce-jointe" name="open_attachment" width="118"/>
<line_editor left="128" name="view_inventory_name" width="256"/>
+ <button label="Ouvrir la pièce jointe" label_selected="Ouvrir pièce-jointe" name="open_attachment" width="118"/>
</panel>
</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_group_notify.xml b/indra/newview/skins/default/xui/fr/panel_group_notify.xml
new file mode 100644
index 0000000000..d3ecbd71d1
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_group_notify.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="instant_message" name="panel_group_notify">
+ <string name="message_max_lines_count" value="7"/>
+ <string name="subject_font" value="SANSSERIF_BIG"/>
+ <string name="date_font" value="SANSSERIF"/>
+ <panel label="en-tête" name="header">
+ <text name="title" value="Nom de l&apos;expéditeur / Nom du groupe"/>
+ </panel>
+ <text_editor name="message" value="message"/>
+ <text name="attachment" value="Pièce jointe"/>
+ <button label="Ok" name="btn_ok"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_group_roles.xml b/indra/newview/skins/default/xui/fr/panel_group_roles.xml
index 008402db32..d0c9f2f302 100644
--- a/indra/newview/skins/default/xui/fr/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/fr/panel_group_roles.xml
@@ -1,152 +1,105 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Membres et rôles" name="roles_tab">
- <text name="default_needs_apply_text">
- Certains changements n&apos;ont pas été appliqués sur ce sous-onglet.
- </text>
- <text name="want_apply_text">
- Voulez-vous enregistrer les modifications ?
- </text>
- <text name="cant_delete_role">
- Les Rôles Tout le monde et Propriétaires sont spéciaux et ne peuvent être supprimés.
- </text>
- <button label="?" name="help_button"/>
- <panel name="members_header">
- <text name="static">
- Membres
- </text>
- <text name="static2">
- Les rôles de chaque membre peuvent être personnalisés, ce qui permet une
-meilleure organisation du groupe.
- </text>
- </panel>
- <panel name="roles_header">
- <text name="static">
- Rôles
- </text>
- <text name="role_properties_modifiable">
- Sélectionnez un rôle ci-dessous. Vous pouvez modifier le nom, la
-description et le titre du membre.
- </text>
- <text name="role_properties_not_modifiable">
- Sélectionnez un rôle ci-dessous pour en connaître les propriétés, les
-membres et les pouvoirs.
- </text>
- <text bottom_delta="-28" name="role_actions_modifiable">
- Vous pouvez aussi assigner des pouvoirs au rôle.
- </text>
- <text name="role_actions_not_modifiable">
- Vous pouvez afficher mais non modifier les pouvoirs assignés.
- </text>
- </panel>
- <panel name="actions_header">
- <text name="static">
- Pouvoirs
- </text>
- <text name="static2">
- Vous pouvez afficher la description du pouvoir et voir à quels rôles ou à
-quels membres ces pouvoirs sont assignés.
- </text>
- </panel>
+ <panel.string name="default_needs_apply_text">
+ Certaines modifications sur cet onglet n&apos;ont pas été enregistrées.
+ </panel.string>
+ <panel.string name="want_apply_text">
+ Voulez-vous enregistrer vos modifications ?
+ </panel.string>
<tab_container height="164" name="roles_tab_container">
- <panel height="148" label="Membres" name="members_sub_tab" tool_tip="Membres">
- <line_editor bottom="127" name="search_text"/>
- <button label="Rechercher" name="search_button" width="75"/>
- <button label="Afficher tout" left_delta="80" name="show_all_button"/>
- <name_list bottom_delta="-105" height="104" name="member_list">
- <column label="Nom du membre" name="name"/>
- <column label="Surface donnée" name="donated" width="116"/>
- <column label="Dernière connexion" name="online" width="136"/>
- </name_list>
- <button label="Inviter un membre..." name="member_invite" width="165"/>
- <button label="Expulser un membre" name="member_eject"/>
- <text name="help_text">
+ <panel height="148" label="MEMBRES" name="members_sub_tab" tool_tip="Membres">
+ <panel.string name="help_text">
Vous pouvez ajouter ou supprimer les rôles assignés aux membres.
Pour sélectionner plusieurs membres, cliquez sur leurs noms en maintenant la touche Ctrl enfoncée.
- </text>
+ </panel.string>
+ <filter_editor label="Filtrer les membres" name="filter_input"/>
+ <name_list bottom_delta="-105" height="104" name="member_list">
+ <name_list.columns label="Membre" name="name"/>
+ <name_list.columns label="Donation" name="donated" width="116"/>
+ <name_list.columns label="Statut" name="online" width="136"/>
+ </name_list>
+ <button label="Inviter" name="member_invite" width="165"/>
+ <button label="Expulser" name="member_eject"/>
</panel>
- <panel height="148" label="Rôles" name="roles_sub_tab">
- <line_editor bottom="127" name="search_text"/>
- <button label="Rechercher" name="search_button" width="75"/>
- <button label="Afficher tout" left_delta="80" name="show_all_button"/>
+ <panel height="148" label="RÔLES" name="roles_sub_tab">
+ <panel.string name="help_text">
+ Chaque rôle possède un titre et des
+pouvoirs. Les membres peuvent avoir
+un ou plusieurs rôles. Un groupe peut avoir jusqu&apos;à 10 rôles,
+notamment les rôles Tous et Propriétaire.
+ </panel.string>
+ <panel.string name="cant_delete_role">
+ Les rôles Tous et Propriétaires sont spéciaux et ne peuvent pas être supprimés.
+ </panel.string>
+ <panel.string name="power_folder_icon">
+ Inv_FolderClosed
+ </panel.string>
+ <panel.string name="power_all_have_icon">
+ Checkbox_On
+ </panel.string>
+ <panel.string name="power_partial_icon">
+ Checkbox_Off
+ </panel.string>
+ <filter_editor label="Filtrer les rôles" name="filter_input"/>
<scroll_list bottom_delta="-104" height="104" name="role_list">
- <column label="Nom du rôle" name="name"/>
- <column label="Titre" name="title"/>
- <column label="Membres" name="members"/>
+ <scroll_list.columns label="Rôle" name="name"/>
+ <scroll_list.columns label="Titre" name="title"/>
+ <scroll_list.columns label="#" name="members"/>
</scroll_list>
- <button label="Créer un rôle..." name="role_create"/>
+ <button label="Nouveau rôle" name="role_create"/>
<button label="Supprimer le rôle" name="role_delete"/>
- <text name="help_text">
- Chaque rôle possède un titre et des pouvoirs. Un membre peut avoir plusieurs rôles mais il ne peut y avoir que 10 rôles dans un groupe, Visiteur et Propriétaire inclus.
- </text>
- <string name="cant_delete_role">
- Les rôles Tous et Propriétaires sont spéciaux et ne peuvent pas être supprimés.
- </string>
</panel>
- <panel height="148" label="Pouvoirs" name="actions_sub_tab">
- <line_editor bottom="127" name="search_text"/>
- <button label="Rechercher" name="search_button" width="75"/>
- <button label="Afficher tout" left_delta="80" name="show_all_button"/>
- <scroll_list bottom_delta="-120" height="118" name="action_list" tool_tip="Sélectionnez un pouvoir pour en afficher les détails.">
- <column label="" name="icon"/>
- <column label="" name="action"/>
- </scroll_list>
- <text name="help_text">
+ <panel height="148" label="POUVOIRS" name="actions_sub_tab" tool_tip="Vous pouvez afficher une description du pouvoir et voir quels membres et rôles peuvent s&apos;en servir.">
+ <panel.string name="help_text">
Les pouvoirs déterminent les facultés de chaque membre dans le groupe.
- </text>
+ </panel.string>
+ <filter_editor label="Filtrer les pouvoirs" name="filter_input"/>
+ <scroll_list bottom_delta="-120" height="118" name="action_list" tool_tip="Sélectionnez un pouvoir pour en savoir plus">
+ <scroll_list.columns label="" name="action"/>
+ </scroll_list>
</panel>
</tab_container>
<panel name="members_footer">
<text name="static">
Rôles assignés
</text>
+ <scroll_list name="member_assigned_roles">
+ <scroll_list.columns label="" name="checkbox"/>
+ <scroll_list.columns label="" name="role"/>
+ </scroll_list>
<text name="static2">
Pouvoirs attribués
</text>
- <scroll_list name="member_assigned_roles">
- <column label="" name="checkbox"/>
- <column label="" name="role"/>
- </scroll_list>
- <scroll_list name="member_allowed_actions" tool_tip="Pour avoir des détails sur chacun des pouvoirs attribués, allez à l&apos;onglet Pouvoirs.">
- <column label="" name="icon"/>
- <column label="" name="action"/>
+ <scroll_list name="member_allowed_actions" tool_tip="Pour en savoir plus sur chaque pouvoir, consultez l&apos;onglet Pouvoirs">
+ <scroll_list.columns label="" name="action"/>
</scroll_list>
</panel>
<panel name="roles_footer">
<text name="static">
- Nom
+ Nom du rôle
+ </text>
+ <line_editor name="role_name"/>
+ <text name="static3">
+ Titre du rôle
</text>
+ <line_editor name="role_title"/>
<text name="static2">
Description
</text>
- <line_editor name="role_name">
- Employés
- </line_editor>
- <text name="static3">
- Titre
- </text>
- <line_editor name="role_title">
- (en attente)
- </line_editor>
- <text_editor name="role_description">
- (en attente)
- </text_editor>
+ <text_editor name="role_description"/>
<text name="static4">
Membres assignés
</text>
+ <check_box label="Afficher les membres" name="role_visible_in_list" tool_tip="Détermine si les personnes n&apos;appartenant pas au groupe peuvent voir les membres de ce rôle dans l&apos;onglet Général."/>
<text name="static5" tool_tip="Une liste des pouvoirs auquel le rôle sélectionné a accès.">
Pouvoirs attribués
</text>
- <check_box label="Membres visibles" name="role_visible_in_list" tool_tip="Définit si les membres de ce rôle sont visibles à partir de l&apos;onglet Général aux personnes en dehors du groupe."/>
- <scroll_list name="role_allowed_actions" tool_tip="Pour avoir des détails sur chacun des pouvoirs attribués, allez à l&apos;onglet Pouvoirs.">
- <column label="" name="icon"/>
- <column label="" name="checkbox"/>
- <column label="" name="action"/>
+ <scroll_list name="role_allowed_actions" tool_tip="Pour en savoir plus sur chaque pouvoir, consultez l&apos;onglet Pouvoirs">
+ <scroll_list.columns label="" name="checkbox"/>
+ <scroll_list.columns label="" name="action"/>
</scroll_list>
</panel>
<panel name="actions_footer">
- <text name="static">
- Description
- </text>
<text_editor name="action_description">
Ce pouvoir permet d&apos;expulser des membres du groupe. Seul un propriétaire peut expulser un autre propriétaire.
</text_editor>
diff --git a/indra/newview/skins/default/xui/fr/panel_im_control_panel.xml b/indra/newview/skins/default/xui/fr/panel_im_control_panel.xml
new file mode 100644
index 0000000000..653f1fff28
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_im_control_panel.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_im_control_panel">
+ <text name="avatar_name" value="Inconnu"/>
+ <button label="Profil" name="view_profile_btn"/>
+ <button label="Devenir amis" name="add_friend_btn"/>
+ <button label="Téléporter" name="teleport_btn"/>
+ <button label="Partager" name="share_btn"/>
+ <panel name="panel_call_buttons">
+ <button label="Appeler" name="call_btn"/>
+ <button label="Quitter l&apos;appel" name="end_call_btn"/>
+ <button label="Contrôles vocaux" name="voice_ctrls_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_instant_message.xml b/indra/newview/skins/default/xui/fr/panel_instant_message.xml
new file mode 100644
index 0000000000..bf3720f411
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_instant_message.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="im_panel" name="im_panel">
+ <string name="message_max_lines_count">
+ 6
+ </string>
+ <panel label="im_header" name="im_header">
+ <text name="user_name" value="Erica Vader"/>
+ <text name="time_box" value="23:30"/>
+ </panel>
+ <button label="Répondre" name="reply"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_landmark_info.xml b/indra/newview/skins/default/xui/fr/panel_landmark_info.xml
new file mode 100644
index 0000000000..1b54f093d9
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_landmark_info.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="landmark_info">
+ <string name="title_create_landmark" value="Créer un repère"/>
+ <string name="title_edit_landmark" value="Modifier le repère"/>
+ <string name="title_landmark" value="Repère"/>
+ <string name="not_available" value="(s/o)"/>
+ <string name="unknown" value="(inconnu)"/>
+ <string name="public" value="(public)"/>
+ <string name="server_update_text">
+ Les informations sur le lieu ne sont pas disponibles sans mise à jour du serveur.
+ </string>
+ <string name="server_error_text">
+ Aucune information sur ce lieu n&apos;est disponible actuellement, veuillez réessayer ultérieurement.
+ </string>
+ <string name="server_forbidden_text">
+ Les informations sur ce lieu ne sont pas disponibles car l&apos;accès y est restreint. Veuillez vérifier vos permissions avec le propriétaire de la parcelle.
+ </string>
+ <string name="acquired_date">
+ [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+ </string>
+ <string name="icon_PG" value="parcel_drk_PG"/>
+ <string name="icon_M" value="parcel_drk_M"/>
+ <string name="icon_R" value="parcel_drk_R"/>
+ <text name="title" value="Profil du lieu"/>
+ <scroll_container name="place_scroll">
+ <panel name="scrolling_panel">
+ <text name="region_title" value="SampleRegion"/>
+ <text name="parcel_title" value="SampleParcel, Name Long (145, 228, 26)"/>
+ <expandable_text name="description" value="Du waltz die spritz"/>
+ <text name="maturity_value" value="(inconnu)"/>
+ <panel name="landmark_info_panel">
+ <text name="owner_label" value="Propriétaire :"/>
+ <text name="creator_label" value="Créé par :"/>
+ <text name="created_label" value="Le :"/>
+ </panel>
+ <panel name="landmark_edit_panel">
+ <text name="title_label" value="Titre :"/>
+ <text name="notes_label" value="Mes notes :"/>
+ <text name="folder_label" value="Emplacement du repère :"/>
+ </panel>
+ </panel>
+ </scroll_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_landmarks.xml b/indra/newview/skins/default/xui/fr/panel_landmarks.xml
new file mode 100644
index 0000000000..c4e90bed61
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_landmarks.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="Landmarks">
+ <accordion name="landmarks_accordion">
+ <accordion_tab name="tab_favorites" title="Barre des Favoris"/>
+ <accordion_tab name="tab_landmarks" title="Repères"/>
+ <accordion_tab name="tab_inventory" title="Mon inventaire"/>
+ <accordion_tab name="tab_library" title="Bibliothèque"/>
+ </accordion>
+ <panel name="bottom_panel">
+ <button name="options_gear_btn" tool_tip="Afficher d&apos;autres options"/>
+ <button name="add_btn" tool_tip="Ajouter un nouveau repère"/>
+ <dnd_button name="trash_btn" tool_tip="Supprimer le repère sélectionné"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_login.xml b/indra/newview/skins/default/xui/fr/panel_login.xml
index c4c6350b4a..55dff07f46 100644
--- a/indra/newview/skins/default/xui/fr/panel_login.xml
+++ b/indra/newview/skins/default/xui/fr/panel_login.xml
@@ -1,52 +1,41 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="panel_login">
- <string name="forgot_password_url">
- http://secondlife.com/account/request.php
- </string>
- <text name="first_name_text">
- Prénom :
- </text>
- <text name="last_name_text">
- Nom :
- </text>
- <text name="password_text">
- Mot de passe :
- </text>
- <text name="start_location_text">
- Lieu de départ :
- </text>
- <combo_box name="start_location_combo">
- <combo_item name="MyHome">
- Domicile
- </combo_item>
- <combo_item name="MyLastLocation">
- Dernier emplacement
- </combo_item>
- <combo_item name="&lt;Typeregionname&gt;">
- &lt;Choisir région&gt;
- </combo_item>
- <combo_item name="Typeregionname">
- &lt;Nom de la région&gt;
- </combo_item>
- </combo_box>
- <check_box label="Mémoriser" name="remember_check"/>
- <text name="full_screen_text">
- Le plein écran sera activé après identification.
- </text>
- <button label="Nouveau Compte..." label_selected="Nouveau Compte..." name="new_account_btn"/>
- <button label="Me connecter" label_selected="Me connecter" name="connect_btn"/>
- <button label="Préférences..." label_selected="Préférences..." name="preferences_btn"/>
- <button label="Quitter" label_selected="Quitter" name="quit_btn"/>
- <text name="version_text">
- 1.23.4 (5)
- </text>
- <text name="create_new_account_text">
- Créer un compte
- </text>
- <text name="forgot_password_text">
- Nom ou mot de passe oublié ?
- </text>
- <text name="channel_text">
- [VERSION]
- </text>
+ <panel.string name="create_account_url">
+ http://fr.secondlife.com/registration/
+ </panel.string>
+ <panel.string name="forgot_password_url">
+ http://secondlife.com/account/request.php?lang=fr
+ </panel.string>
+ <panel name="login_widgets">
+ <text name="first_name_text">
+ Prénom :
+ </text>
+ <line_editor name="first_name_edit" tool_tip="Prénom [SECOND_LIFE]"/>
+ <text name="last_name_text">
+ Nom :
+ </text>
+ <line_editor name="last_name_edit" tool_tip="Nom [SECOND_LIFE]"/>
+ <text name="password_text">
+ Mot de passe :
+ </text>
+ <button label="Connexion" label_selected="Connexion" name="connect_btn"/>
+ <text name="start_location_text">
+ Lieu de départ :
+ </text>
+ <combo_box name="start_location_combo">
+ <combo_box.item label="Dernier emplacement" name="MyLastLocation"/>
+ <combo_box.item label="Domicile" name="MyHome"/>
+ <combo_box.item label="&lt;Saisissez le nom de la région&gt;" name="Typeregionname"/>
+ </combo_box>
+ <check_box label="Enregistrer le mot de passe" name="remember_check"/>
+ <text name="create_new_account_text">
+ Créer un compte
+ </text>
+ <text name="forgot_password_text">
+ Nom ou mot de passe oublié ?
+ </text>
+ <text name="channel_text">
+ [VERSION]
+ </text>
+ </panel>
</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_main_inventory.xml b/indra/newview/skins/default/xui/fr/panel_main_inventory.xml
new file mode 100644
index 0000000000..9a98581cb4
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_main_inventory.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Choses" name="main inventory panel">
+ <panel.string name="Title">
+ Choses
+ </panel.string>
+ <filter_editor label="Filtre" name="inventory search editor"/>
+ <tab_container name="inventory filter tabs">
+ <inventory_panel label="Tous les objets" name="All Items"/>
+ <inventory_panel label="Objets récents" name="Recent Items"/>
+ </tab_container>
+ <panel name="bottom_panel">
+ <button name="options_gear_btn" tool_tip="Afficher d&apos;autres options"/>
+ <button name="add_btn" tool_tip="Ajouter un nouvel article"/>
+ <dnd_button name="trash_btn" tool_tip="Supprimer l&apos;article sélectionné"/>
+ </panel>
+ <menu_bar name="Inventory Menu">
+ <menu label="Fichier" name="File">
+ <menu_item_call label="Ouvrir" name="Open"/>
+ <menu label="Charger" name="upload">
+ <menu_item_call label="Image ([COST] L$)..." name="Upload Image"/>
+ <menu_item_call label="Son ([COST] L$)..." name="Upload Sound"/>
+ <menu_item_call label="Animation ([COST] L$)..." name="Upload Animation"/>
+ <menu_item_call label="Lot ([COST] L$ par fichier)..." name="Bulk Upload"/>
+ </menu>
+ <menu_item_call label="Nouvelle fenêtre" name="New Window"/>
+ <menu_item_call label="Afficher les filtres" name="Show Filters"/>
+ <menu_item_call label="Réinitialiser les filtres" name="Reset Current"/>
+ <menu_item_call label="Fermer tous les dossiers" name="Close All Folders"/>
+ <menu_item_call label="Vider la corbeille" name="Empty Trash"/>
+ <menu_item_call label="Vider les Objets trouvés" name="Empty Lost And Found"/>
+ </menu>
+ <menu label="Créer" name="Create">
+ <menu_item_call label="Nouveau dossier" name="New Folder"/>
+ <menu_item_call label="Nouveau script" name="New Script"/>
+ <menu_item_call label="Nouvelle note" name="New Note"/>
+ <menu_item_call label="Nouveau geste" name="New Gesture"/>
+ <menu label="Nouveaux habits" name="New Clothes">
+ <menu_item_call label="Nouvelle chemise" name="New Shirt"/>
+ <menu_item_call label="Nouveau pantalon" name="New Pants"/>
+ <menu_item_call label="Nouvelles chaussures" name="New Shoes"/>
+ <menu_item_call label="Nouvelles chaussettes" name="New Socks"/>
+ <menu_item_call label="Nouvelle veste" name="New Jacket"/>
+ <menu_item_call label="Nouvelle jupe" name="New Skirt"/>
+ <menu_item_call label="Nouveaux gants" name="New Gloves"/>
+ <menu_item_call label="Nouveaux sous-vêtements (homme)" name="New Undershirt"/>
+ <menu_item_call label="Nouveaux sous-vêtements (femme)" name="New Underpants"/>
+ <menu_item_call label="Nouvel alpha" name="New Alpha"/>
+ <menu_item_call label="Nouveau tatouage" name="New Tattoo"/>
+ </menu>
+ <menu label="Nouvelles parties du corps" name="New Body Parts">
+ <menu_item_call label="Nouvelle silhouette" name="New Shape"/>
+ <menu_item_call label="Nouvelle peau" name="New Skin"/>
+ <menu_item_call label="Nouveaux cheveux" name="New Hair"/>
+ <menu_item_call label="Nouveaux yeux" name="New Eyes"/>
+ </menu>
+ </menu>
+ <menu label="Trier" name="Sort">
+ <menu_item_check label="Par nom" name="By Name"/>
+ <menu_item_check label="Par date" name="By Date"/>
+ <menu_item_check label="Dossiers toujours par nom" name="Folders Always By Name"/>
+ <menu_item_check label="Dossiers système en premier" name="System Folders To Top"/>
+ </menu>
+ </menu_bar>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_me.xml b/indra/newview/skins/default/xui/fr/panel_me.xml
new file mode 100644
index 0000000000..c9d77c208f
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_me.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Mon profil" name="panel_me">
+ <tab_container name="tabs">
+ <panel label="PROFIL" name="panel_profile"/>
+ <panel label="FAVORIS" name="panel_picks"/>
+ </tab_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_media_settings_general.xml b/indra/newview/skins/default/xui/fr/panel_media_settings_general.xml
new file mode 100644
index 0000000000..2e73072e97
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_media_settings_general.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Général" name="Media Settings General">
+ <text name="home_label">
+ URL du domicile :
+ </text>
+ <line_editor name="home_url" tool_tip="L&apos;URL du domicile pour cette source média"/>
+ <text name="preview_label">
+ Prévisualiser
+ </text>
+ <text name="current_url_label">
+ URL actuelle :
+ </text>
+ <line_editor name="current_url" tool_tip="L&apos;URL actuelle pour cette source média" value=""/>
+ <button label="Réinitialiser" name="current_url_reset_btn"/>
+ <text name="controls_label">
+ Contrôles :
+ </text>
+ <combo_box name="controls">
+ <combo_item name="Standard">
+ Standard
+ </combo_item>
+ <combo_item name="Mini">
+ Mini
+ </combo_item>
+ </combo_box>
+ <check_box initial_value="false" label="Boucle auto" name="auto_loop"/>
+ <check_box initial_value="false" label="Premier clic interagit" name="first_click_interact"/>
+ <check_box initial_value="false" label="Zoom auto" name="auto_zoom"/>
+ <check_box initial_value="false" label="Lecture auto du média" name="auto_play"/>
+ <text name="media_setting_note">
+ Remarque : kes résidents peuvent ignorer ce paramètre
+ </text>
+ <check_box initial_value="false" label="Mise à l&apos;échelle auto du média sur la face de l&apos;objet" name="auto_scale"/>
+ <text name="size_label">
+ Taille :
+ </text>
+ <text name="X_label">
+ X
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_media_settings_permissions.xml b/indra/newview/skins/default/xui/fr/panel_media_settings_permissions.xml
new file mode 100644
index 0000000000..88a1897f81
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_media_settings_permissions.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Contrôles" name="Media settings for controls">
+ <check_box initial_value="false" label="Désactiver la navigation et l&apos;interactivité" name="perms_owner_interact"/>
+ <check_box initial_value="false" label="Masquer la barre de contrôles" name="perms_owner_control"/>
+ <check_box initial_value="false" label="Désactiver la navigation et l&apos;interactivité" name="perms_group_interact"/>
+ <check_box initial_value="false" label="Masquer la barre de contrôles" name="perms_group_control"/>
+ <check_box initial_value="false" label="Désactiver la navigation et l&apos;interactivité" name="perms_anyone_interact"/>
+ <check_box initial_value="false" label="Masquer la barre de contrôles" name="perms_anyone_control"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_media_settings_security.xml b/indra/newview/skins/default/xui/fr/panel_media_settings_security.xml
new file mode 100644
index 0000000000..42641f48af
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_media_settings_security.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Sécurité" name="Media Settings Security">
+ <check_box initial_value="false" label="Autoriser l&apos;accès aux URL spécifiées uniquement (par préfixe)" name="whitelist_enable"/>
+ <button label="Ajouter" name="whitelist_add"/>
+ <button label="Supprimer" name="whitelist_del"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_my_profile.xml b/indra/newview/skins/default/xui/fr/panel_my_profile.xml
new file mode 100644
index 0000000000..5ffe0b9d89
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_my_profile.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Profil" name="panel_profile">
+ <string name="CaptionTextAcctInfo">
+ [ACCTTYPE]
+[PAYMENTINFO] [AGEVERIFICATION]
+ </string>
+ <string name="no_partner_text" value="Aucun"/>
+ <string name="RegisterDateFormat">
+ [REG_DATE] ([AGE])
+ </string>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <panel name="second_life_image_panel">
+ <icon label="" name="2nd_life_edit_icon" tool_tip="Cliquez sur le bouton Modifier le profil ci-dessous pour changer d&apos;image"/>
+ <text name="title_sl_descr_text" value="[SECOND_LIFE]:"/>
+ <expandable_text name="sl_description_edit">
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ <panel name="first_life_image_panel">
+ <icon label="" name="real_world_edit_icon" tool_tip="Cliquez sur le bouton Modifier le profil ci-dessous pour changer d&apos;image"/>
+ <text name="title_rw_descr_text" value="Monde physique :"/>
+ <expandable_text name="fl_description_edit">
+ Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ <text name="me_homepage_text">
+ Page d&apos;accueil :
+ </text>
+ <text name="title_member_text" value="Membre depuis :"/>
+ <text name="register_date" value="05/31/1976"/>
+ <text name="title_acc_status_text" value="Statut du compte :"/>
+ <text name="acc_status_text" value="Résident. Aucune info de paiement enregistrée."/>
+ <text name="title_partner_text" value="Partenaire :"/>
+ <panel name="partner_data_panel">
+ <text name="partner_text" value="[FIRST] [LAST]"/>
+ </panel>
+ <text name="title_groups_text" value="Groupes :"/>
+ <expandable_text name="sl_groups">
+ Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ </scroll_container>
+ <panel name="profile_buttons_panel">
+ <button label="Devenir amis" name="add_friend"/>
+ <button label="IM" name="im"/>
+ <button label="Appeler" name="call"/>
+ <button label="Carte" name="show_on_map_btn"/>
+ <button label="Téléporter" name="teleport"/>
+ </panel>
+ <panel name="profile_me_buttons_panel">
+ <button label="Modifier le profil" name="edit_profile_btn"/>
+ <button label="Changer d&apos;apparence" name="edit_appearance_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_navigation_bar.xml b/indra/newview/skins/default/xui/fr/panel_navigation_bar.xml
new file mode 100644
index 0000000000..2cb6d91133
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_navigation_bar.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="navigation_bar">
+ <panel name="navigation_panel">
+ <button name="back_btn" tool_tip="Revenir à l&apos;emplacement précédent"/>
+ <button name="forward_btn" tool_tip="Avancer d&apos;un emplacement"/>
+ <button name="home_btn" tool_tip="Me téléporter jusqu&apos;à mon domicile"/>
+ <location_input label="Emplacement" name="location_combo"/>
+ <search_combo_box label="Rechercher" name="search_combo_box" tool_tip="Rechercher">
+ <combo_editor label="Rechercher dans [SECOND_LIFE]" name="search_combo_editor"/>
+ </search_combo_box>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_nearby_chat.xml b/indra/newview/skins/default/xui/fr/panel_nearby_chat.xml
new file mode 100644
index 0000000000..fa1ddd2430
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_nearby_chat.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- All our XML is utf-8 encoded. -->
+<panel name="nearby_chat">
+ <panel name="chat_caption">
+ <text name="sender_name">
+ CHAT PRÈS DE VOUS
+ </text>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/fr/panel_nearby_chat_bar.xml
new file mode 100644
index 0000000000..8ed441cbae
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_nearby_chat_bar.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="chat_bar">
+ <string name="min_width">
+ 192
+ </string>
+ <string name="max_width">
+ 320
+ </string>
+ <line_editor label="Cliquer ici pour chatter." name="chat_box" tool_tip="Appuyer sur Entrée pour dire, Ctrl-Entrée pour crier"/>
+ <button name="show_nearby_chat" tool_tip="Affiche/Masque le journal de chats près de vous"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_notes.xml b/indra/newview/skins/default/xui/fr/panel_notes.xml
new file mode 100644
index 0000000000..0195118fd8
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_notes.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Notes/Perso" name="panel_notes">
+ <layout_stack name="layout">
+ <panel name="notes_stack">
+ <scroll_container name="profile_scroll">
+ <panel name="profile_scroll_panel">
+ <text name="status_message" value="Mes notes perso :"/>
+ <text name="status_message2" value="Autoriser cette personne à :"/>
+ <check_box label="Afficher mon statut en ligne" name="status_check"/>
+ <check_box label="Me situer sur la carte" name="map_check"/>
+ <check_box label="Modifier, supprimer ou prendre mes objets" name="objects_check"/>
+ </panel>
+ </scroll_container>
+ </panel>
+ <panel name="notes_buttons_panel">
+ <button label="Ajouter" name="add_friend"/>
+ <button label="IM" name="im"/>
+ <button label="Appeler" name="call"/>
+ <button label="Carte" name="show_on_map_btn"/>
+ <button label="Téléporter" name="teleport"/>
+ </panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/fr/panel_outfits_inventory.xml
new file mode 100644
index 0000000000..1ff1227772
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_outfits_inventory.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="Outfits">
+ <accordion name="outfits_accordion">
+ <accordion_tab name="tab_outfits" title="Barre des tenues"/>
+ <accordion_tab name="tab_cof" title="Barre de la tenue actuelle"/>
+ </accordion>
+ <button label="&gt;" name="selector" tool_tip="Afficher les propriétés de la tenue"/>
+ <panel name="bottom_panel">
+ <button name="options_gear_btn" tool_tip="Afficher d&apos;autres options"/>
+ <button name="add_btn" tool_tip="Ajouter un nouvel objet"/>
+ <dnd_button name="trash_btn" tool_tip="Supprimer l&apos;objet sélectionné"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_outfits_inventory_gear_default.xml b/indra/newview/skins/default/xui/fr/panel_outfits_inventory_gear_default.xml
new file mode 100644
index 0000000000..d900344dcc
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_outfits_inventory_gear_default.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_gear_default">
+ <menu_item_call label="Nouvelle tenue" name="new"/>
+ <menu_item_call label="Porter la tenue" name="wear"/>
+ <menu_item_call label="Supprimer la tenue" name="delete"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/fr/panel_people.xml b/indra/newview/skins/default/xui/fr/panel_people.xml
new file mode 100644
index 0000000000..ae2b96da3c
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_people.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- Side tray panel -->
+<panel label="Résidents" name="people_panel">
+ <string name="no_people" value="Personne"/>
+ <string name="no_one_near" value="Personne près de vous"/>
+ <string name="no_friends_online" value="Pas d&apos;amis connectés"/>
+ <string name="no_friends" value="Pas d&apos;amis"/>
+ <string name="no_groups" value="Pas de groupes"/>
+ <string name="people_filter_label" value="Filtrer les personnes"/>
+ <string name="groups_filter_label" value="Filtrer les groupes"/>
+ <filter_editor label="Filtre" name="filter_input"/>
+ <tab_container name="tabs">
+ <panel label="PRÈS DE VOUS" name="nearby_panel">
+ <panel label="bottom_panel" name="bottom_panel">
+ <button name="nearby_view_sort_btn" tool_tip="Options"/>
+ <button name="add_friend_btn" tool_tip="Ajouter le résident sélectionné à votre liste d&apos;amis"/>
+ </panel>
+ </panel>
+ <panel label="AMIS" name="friends_panel">
+ <accordion name="friends_accordion">
+ <accordion_tab name="tab_online" title="En ligne"/>
+ <accordion_tab name="tab_all" title="Tout"/>
+ </accordion>
+ <panel label="bottom_panel" name="bottom_panel">
+ <button name="friends_viewsort_btn" tool_tip="Options"/>
+ <button name="add_btn" tool_tip="Proposer à ce résident de devenir votre ami"/>
+ <button name="del_btn" tool_tip="Supprimer le résident sélectionné de votre liste d&apos;amis"/>
+ </panel>
+ </panel>
+ <panel label="GROUPES" name="groups_panel">
+ <panel label="bottom_panel" name="bottom_panel">
+ <button name="groups_viewsort_btn" tool_tip="Options"/>
+ <button name="plus_btn" tool_tip="Rejoindre/créer un nouveau groupe"/>
+ <button name="activate_btn" tool_tip="Activer le groupe sélectionné"/>
+ </panel>
+ </panel>
+ <panel label="RÉCENT" name="recent_panel">
+ <panel label="bottom_panel" name="bottom_panel">
+ <button name="recent_viewsort_btn" tool_tip="Options"/>
+ <button name="add_friend_btn" tool_tip="Ajouter le résident sélectionné à votre liste d&apos;amis"/>
+ </panel>
+ </panel>
+ </tab_container>
+ <panel name="button_bar">
+ <button label="Profil" name="view_profile_btn" tool_tip="Afficher la photo, les groupes et autres infos des résidents"/>
+ <button label="IM" name="im_btn" tool_tip="Ouvrir une session IM"/>
+ <button label="Appeler" name="call_btn" tool_tip="Appeler ce résident"/>
+ <button label="Partager" name="share_btn"/>
+ <button label="Téléporter" name="teleport_btn" tool_tip="Proposez une téléportation"/>
+ <button label="Profil du groupe" name="group_info_btn" tool_tip="Voir le profil du groupe"/>
+ <button label="Chat de groupe" name="chat_btn" tool_tip="Ouvrir une session de chat"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_pick_info.xml b/indra/newview/skins/default/xui/fr/panel_pick_info.xml
new file mode 100644
index 0000000000..e9572caac7
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_pick_info.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_pick_info">
+ <text name="title" value="Infos"/>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <text name="pick_name" value="[name]"/>
+ <text name="pick_location" value="[loading...]"/>
+ <text name="pick_desc" value="[description]"/>
+ </panel>
+ </scroll_container>
+ <panel name="buttons">
+ <button label="Téléporter" name="teleport_btn"/>
+ <button label="Carte" name="show_on_map_btn"/>
+ <button label="Éditer" name="edit_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_picks.xml b/indra/newview/skins/default/xui/fr/panel_picks.xml
new file mode 100644
index 0000000000..cf110c27b5
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_picks.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Favoris" name="panel_picks">
+ <string name="no_picks" value="Pas de favoris"/>
+ <string name="no_classifieds" value="Pas de petites annonces"/>
+ <text name="empty_picks_panel_text">
+ Il n&apos;y a pas de favoris/petites annonces ici
+ </text>
+ <accordion name="accordion">
+ <accordion_tab name="tab_picks" title="Favoris"/>
+ <accordion_tab name="tab_classifieds" title="Petites annonces"/>
+ </accordion>
+ <panel label="bottom_panel" name="edit_panel">
+ <button name="new_btn" tool_tip="Ajouter cet endroit à mes Préférences"/>
+ </panel>
+ <panel name="buttons_cucks">
+ <button label="Infos" name="info_btn"/>
+ <button label="Téléporter" name="teleport_btn"/>
+ <button label="Carte" name="show_on_map_btn"/>
+ <button label="â–¼" name="overflow_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_place_profile.xml b/indra/newview/skins/default/xui/fr/panel_place_profile.xml
new file mode 100644
index 0000000000..3772d8dd4e
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_place_profile.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="place_profile">
+ <string name="on" value="Activé"/>
+ <string name="off" value="Désactivé"/>
+ <string name="anyone" value="Tout le monde"/>
+ <string name="available" value="disponible"/>
+ <string name="allocated" value="affecté"/>
+ <string name="title_place" value="Profil du lieu"/>
+ <string name="title_teleport_history" value="Emplacement de l&apos;historique des téléportations"/>
+ <string name="not_available" value="(s/o)"/>
+ <string name="unknown" value="(inconnu)"/>
+ <string name="public" value="(public)"/>
+ <string name="none_text" value="(aucun)"/>
+ <string name="sale_pending_text" value="(vente en cours)"/>
+ <string name="group_owned_text" value="(propriété du groupe)"/>
+ <string name="price_text" value="L$"/>
+ <string name="area_text" value="m²"/>
+ <string name="all_residents_text" value="Tous les résidents"/>
+ <string name="group_text" value="Groupe"/>
+ <string name="can_resell">
+ Le terrain acheté dans cette région peut être revendu.
+ </string>
+ <string name="can_not_resell">
+ Le terrain acheté dans cette région ne peut pas être revendu.
+ </string>
+ <string name="can_change">
+ Le terrain acheté dans cette région peut être fusionné ou divisé.
+ </string>
+ <string name="can_not_change">
+ Le terrain acheté dans cette région ne peut pas être fusionné ou divisé.
+ </string>
+ <string name="server_update_text">
+ Les informations sur le lieu ne sont pas disponibles sans mise à jour du serveur.
+ </string>
+ <string name="server_error_text">
+ Aucune information sur ce lieu n&apos;est disponible actuellement, veuillez réessayer ultérieurement.
+ </string>
+ <string name="server_forbidden_text">
+ Les informations sur ce lieu ne sont pas disponibles car l&apos;accès y est restreint. Veuillez vérifier vos permissions auprès du propriétaire de la parcelle.
+ </string>
+ <string name="acquired_date">
+ [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+ </string>
+ <string name="icon_PG" value="parcel_drk_PG"/>
+ <string name="icon_M" value="parcel_drk_M"/>
+ <string name="icon_R" value="parcel_drk_R"/>
+ <string name="icon_Voice" value="parcel_drk_Voice"/>
+ <string name="icon_VoiceNo" value="parcel_drk_VoiceNo"/>
+ <string name="icon_Fly" value="parcel_drk_Fly"/>
+ <string name="icon_FlyNo" value="parcel_drk_FlyNo"/>
+ <string name="icon_Push" value="parcel_drk_Push"/>
+ <string name="icon_PushNo" value="parcel_drk_PushNo"/>
+ <string name="icon_Build" value="parcel_drk_Build"/>
+ <string name="icon_BuildNo" value="parcel_drk_BuildNo"/>
+ <string name="icon_Scripts" value="parcel_drk_Scripts"/>
+ <string name="icon_ScriptsNo" value="parcel_drk_ScriptsNo"/>
+ <string name="icon_Damage" value="parcel_drk_Damage"/>
+ <string name="icon_DamageNo" value="parcel_drk_DamageNo"/>
+ <text name="title" value="Profil du lieu"/>
+ <scroll_container name="place_scroll">
+ <panel name="scrolling_panel">
+ <text name="region_title" value="Exemple de région"/>
+ <text name="parcel_title" value="SampleParcel, Name Long (145, 228, 26)"/>
+ <expandable_text name="description" value="Du waltz die spritz"/>
+ <text name="owner_label" value="Propriétaire :"/>
+ <text name="owner_value" value="Alex Superduperlongenamenton"/>
+ <text name="maturity_value" value="(inconnu)"/>
+ <accordion name="advanced_info_accordion">
+ <accordion_tab name="parcel_characteristics_tab" title="Parcelle">
+ <panel>
+ <text name="rating_label" value="Catégorie :"/>
+ <text name="rating_value" value="(inconnu)"/>
+ <text name="voice_label" value="Voix :"/>
+ <text name="voice_value" value="Activée"/>
+ <text name="fly_label" value="Voler :"/>
+ <text name="fly_value" value="Activé"/>
+ <text name="push_label" value="Appuyer :"/>
+ <text name="push_value" value="Désactivé"/>
+ <text name="build_label" value="Construire :"/>
+ <text name="build_value" value="Activé"/>
+ <text name="scripts_label" value="Scripts :"/>
+ <text name="scripts_value" value="Activés"/>
+ <text name="damage_label" value="Dégâts :"/>
+ <text name="damage_value" value="Désactivés"/>
+ <button label="À propos des terrains" name="about_land_btn"/>
+ </panel>
+ </accordion_tab>
+ <accordion_tab name="region_information_tab" title="Région">
+ <panel>
+ <text name="region_name_label" value="Région :"/>
+ <text name="region_name" value="Pays des orignaux"/>
+ <text name="region_type_label" value="Type :"/>
+ <text name="region_type" value="Orignal"/>
+ <text name="region_rating_label" value="Catégorie :"/>
+ <text name="region_rating" value="Explicite"/>
+ <text name="region_owner_label" value="Propriétaire :"/>
+ <text name="region_owner" value="orignal Van Orignal"/>
+ <text name="region_group_label" value="Groupe :"/>
+ <text name="region_group">
+ Le puissant orignal d&apos;Orignalville
+ </text>
+ <button label="Région/Domaine" name="region_info_btn"/>
+ </panel>
+ </accordion_tab>
+ <accordion_tab name="estate_information_tab" title="Domaine">
+ <panel>
+ <text name="estate_name_label" value="Domaine :"/>
+ <text name="estate_rating_label" value="Catégorie :"/>
+ <text name="estate_owner_label" value="Propriétaire :"/>
+ <text name="covenant_label" value="Règlement :"/>
+ </panel>
+ </accordion_tab>
+ <accordion_tab name="sales_tab" title="À vendre">
+ <panel>
+ <text name="sales_price_label" value="Prix :"/>
+ <text name="area_label" value="Surface :"/>
+ <text name="traffic_label" value="Trafic :"/>
+ <text name="primitives_label" value="Prims :"/>
+ <text name="parcel_scripts_label" value="Scripts :"/>
+ <text name="terraform_limits_label" value="Limites de terraformage :"/>
+ <text name="subdivide_label" value="Possibilité de division/fusion :"/>
+ <text name="resale_label" value="Possibilité de revente :"/>
+ <text name="sale_to_label" value="À vendre à :"/>
+ </panel>
+ </accordion_tab>
+ </accordion>
+ </panel>
+ </scroll_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_places.xml b/indra/newview/skins/default/xui/fr/panel_places.xml
new file mode 100644
index 0000000000..79fe4d63c7
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_places.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Lieux" name="places panel">
+ <string name="landmarks_tab_title" value="MES REPÈRES"/>
+ <string name="teleport_history_tab_title" value="HISTORIQUE DES TÉLÉPORTATIONS"/>
+ <filter_editor label="Filtre" name="Filter"/>
+ <panel name="button_panel">
+ <button label="Téléporter" name="teleport_btn"/>
+ <button label="Carte" name="map_btn"/>
+ <button label="Éditer" name="edit_btn"/>
+ <button label="Fermer" name="close_btn"/>
+ <button label="Annuler" name="cancel_btn"/>
+ <button label="Enregistrer" name="save_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/fr/panel_preferences_advanced.xml
new file mode 100644
index 0000000000..04abcc8aad
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_preferences_advanced.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<panel name="advanced">
+ <panel.string name="resolution_format">
+ [RES_X] x [RES_Y]
+ </panel.string>
+ <panel.string name="aspect_ratio_text">
+ [NUM]:[DEN]
+ </panel.string>
+ <check_box label="Bulles de chat" name="bubble_text_chat"/>
+ <color_swatch name="background" tool_tip="Choisir la couleur des bulles de chat"/>
+ <slider label="Opacité" name="bubble_chat_opacity"/>
+ <text name="AspectRatioLabel1" tool_tip="largeur/hauteur">
+ Rapport hauteur/largeur
+ </text>
+ <combo_box name="aspect_ratio" tool_tip="largeur/hauteur">
+ <combo_box.item label="4:3 (Standard CRT)" name="item1"/>
+ <combo_box.item label="5:4 (1280 x 1024 LCD)" name="item2"/>
+ <combo_box.item label="8:5 (écran large)" name="item3"/>
+ <combo_box.item label="16:9 (plein écran)" name="item4"/>
+ </combo_box>
+ <check_box label="Détection automatique" name="aspect_auto_detect"/>
+ <text name="heading1">
+ Caméra :
+ </text>
+ <slider label="Angle de vue" name="camera_fov"/>
+ <slider label="Distance" name="camera_offset_scale"/>
+ <text name="heading2">
+ Positionnement automatique pour :
+ </text>
+ <check_box label="Construire/Éditer" name="edit_camera_movement" tool_tip="Utilisez le positionnement automatique de la caméra quand vous accédez au mode de modification et quand vous le quittez"/>
+ <check_box label="Apparence" name="appearance_camera_movement" tool_tip="Utiliser le positionnement automatique de la caméra quand je suis en mode Édition"/>
+ <text name="heading3">
+ Avatars :
+ </text>
+ <check_box label="Afficher en vue subjective" name="first_person_avatar_visible"/>
+ <check_box label="Les touches de direction me font toujours me déplacer" name="arrow_keys_move_avatar_check"/>
+ <check_box label="Appuyer deux fois et maintenir enfoncé pour courir" name="tap_tap_hold_to_run"/>
+ <check_box label="Faire bouger les lèvres de l&apos;avatar quand il parle" name="enable_lip_sync"/>
+ <check_box label="Afficher les erreurs de script" name="show_script_errors"/>
+ <radio_group name="show_location">
+ <radio_item label="En chat" name="0"/>
+ <radio_item label="Dans une fenêtre" name="1"/>
+ </radio_group>
+ <check_box label="Basculer le mode micro quand j&apos;appuie sur la touche de contrôle de la fonction Parler :" name="push_to_talk_toggle_check" tool_tip="En mode bascule, appuyez une fois sur la touche de contrôle de la fonction, puis relâchez-la pour activer/désactiver votre micro. Si vous n&apos;êtes pas en mode bascule, le micro ne diffuse votre voix que quand vous maintenez la touche de contrôle de la fonction enfoncée."/>
+ <line_editor label="Touche de contrôle de la fonction Appuyer pour parler" name="modifier_combo"/>
+ <button label="Définir la touche" name="set_voice_hotkey_button"/>
+ <button label="Bouton central de la souris" name="set_voice_middlemouse_button"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_alerts.xml b/indra/newview/skins/default/xui/fr/panel_preferences_alerts.xml
new file mode 100644
index 0000000000..600a825973
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_preferences_alerts.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Pop-ups" name="popups" title="Pop-ups">
+ <text name="tell_me_label">
+ Me prévenir :
+ </text>
+ <check_box label="Quand je dépense ou que je reçois des L$" name="notify_money_change_checkbox"/>
+ <check_box label="Quand mes amis se connectent ou se déconnectent" name="friends_online_notify_checkbox"/>
+ <text name="show_label">
+ Toujours afficher ces alertes :
+ </text>
+ <text name="dont_show_label">
+ Ne jamais afficher ces alertes :
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml b/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml
index d29ec67272..d292b002f6 100644
--- a/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml
@@ -1,59 +1,43 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Chat écrit" name="chat">
- <text length="1" name="text_box" type="string">
- Taille de la police
-du chat :
- </text>
<radio_group name="chat_font_size">
- <radio_item length="1" name="radio" type="string">
- Petite
- </radio_item>
- <radio_item length="1" name="radio2" type="string">
- Moyenne
- </radio_item>
- <radio_item length="1" name="radio3" type="string">
- Grande
- </radio_item>
+ <radio_item label="Moins" name="radio"/>
+ <radio_item label="Moyenne" name="radio2"/>
+ <radio_item label="Plus" name="radio3"/>
</radio_group>
- <text length="1" name="text_box2" type="string">
- Couleur du chat :
- </text>
<color_swatch label="Vous" name="user"/>
- <color_swatch label="Avatars" name="agent" width="60"/>
- <color_swatch label="IM" left_delta="64" name="im"/>
+ <text name="text_box1">
+ Moi
+ </text>
+ <color_swatch label="Avatars" name="agent"/>
+ <text name="text_box2">
+ Avatars
+ </text>
+ <color_swatch label="IM" name="im"/>
+ <text name="text_box3">
+ IM
+ </text>
<color_swatch label="Système" name="system"/>
- <color_swatch label="Erreurs" name="script_error"/>
+ <text name="text_box4">
+ Système
+ </text>
+ <color_swatch label="Erreurs de script" name="script_error"/>
+ <text name="text_box5">
+ Erreurs de script
+ </text>
<color_swatch label="Objets" name="objects"/>
- <color_swatch label="Propriétaire" name="owner" width="60"/>
- <color_swatch label="Bulle" left_delta="64" name="background"/>
+ <text name="text_box6">
+ Objets
+ </text>
+ <color_swatch label="Propriétaire" name="owner"/>
+ <text name="text_box7">
+ Propriétaire
+ </text>
<color_swatch label="URL" name="links"/>
- <text length="1" name="text_box3" type="string">
- Console du chat :
- </text>
- <spinner label="Effacer le texte après" label_width="112" name="fade_chat_time" width="162"/>
- <text left="313" length="1" name="text_box4" type="string">
- s
- </text>
- <spinner left="335" name="max_chat_count"/>
- <text left="397" length="1" name="text_box5" type="string" width="74">
- lignes
- </text>
- <slider label="Opacité" name="console_opacity"/>
- <text length="1" name="text_box6" type="string">
- Options du chat :
- </text>
- <check_box label="Utiliser la largeur de l&apos;écran (redémarrage requis)" name="chat_full_width_check"/>
- <check_box label="Fermer le chat après avoir appuyé sur Entrée" name="close_chat_on_return_check"/>
- <check_box label="Faire bouger l&apos;avatar avec les touches de direction" name="arrow_keys_move_avatar_check"/>
- <check_box label="Afficher les heures dans le chat" name="show_timestamps_check"/>
- <check_box label="Jouer l&apos;animation clavier quand vous écrivez" name="play_typing_animation"/>
- <text length="1" name="text_box7" type="string">
- Bulles de chat  :
- </text>
- <check_box label="Afficher les bulles de chat" name="bubble_text_chat"/>
- <slider label="Opacité" name="bubble_chat_opacity"/>
- <text length="1" name="text_box8" type="string">
- Erreurs de script :
- </text>
- <check_box label="Afficher les erreurs dans le chat" name="script_errors_as_chat"/>
+ <text name="text_box9">
+ URL
+ </text>
+ <check_box initial_value="true" label="Jouer l&apos;animation clavier quand vous écrivez" name="play_typing_animation"/>
+ <check_box label="M&apos;envoyer les IM par e-mail une fois déconnecté" name="send_im_to_email"/>
+ <check_box label="Activer l&apos;historique des chats en texte brut" name="plain_text_chat_history"/>
</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_general.xml b/indra/newview/skins/default/xui/fr/panel_preferences_general.xml
index 23e1e74035..6d331704ea 100644
--- a/indra/newview/skins/default/xui/fr/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/fr/panel_preferences_general.xml
@@ -1,148 +1,68 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Général" name="general_panel">
- <radio_group name="default_start_location" width="166">
- <radio_item name="MyHome" tool_tip="Par défaut, choisir mon domicile comme lieu de départ.">
- Domicile
- </radio_item>
- <radio_item name="MyLastLocation" tool_tip="Par défaut, choisir mon dernier emplacement comme lieu de départ.">
- Dernier emplacement
- </radio_item>
- </radio_group>
- <check_box label="Afficher le lieu de départ sur l&apos;écran de connexion" name="show_location_checkbox"/>
- <combo_box name="fade_out_combobox" width="166">
- <combo_item name="Never">
- Jamais
- </combo_item>
- <combo_item name="Show Temporarily">
- Afficher temporairement
- </combo_item>
- <combo_item name="Always">
- Toujours
- </combo_item>
- </combo_box>
- <check_box label="Nom des avatars en petit" name="small_avatar_names_checkbox"/>
- <check_box label="Masquer mon nom sur mon écran" name="show_my_name_checkbox"/>
- <text name="group_titles_textbox">
- Titres de groupe :
- </text>
- <check_box label="Masquer tous les titres de groupe" name="show_all_title_checkbox"/>
- <check_box label="Masquer mon titre de groupe" name="show_my_title_checkbox"/>
- <color_swatch label="" name="effect_color_swatch" tool_tip="Cliquer pour ouvrir le sélecteur de couleurs"/>
- <text name="UI Size:">
- Taille de l&apos;interface :
+ <text name="language_textbox">
+ Langue :
</text>
- <slider name="ui_scale_slider"/>
- <check_box label="Utiliser une échelle indépendante de la résolution" name="ui_auto_scale"/>
- <spinner label="Absent(e) après :" name="afk_timeout_spinner"/>
- <check_box label="M&apos;avertir lorsque je dépense ou reçois des L$" name="notify_money_change_checkbox"/>
- <text name="maturity_desired_label">
- Catégorie de contenu :
+ <combo_box name="language_combobox">
+ <combo_box.item label="Choix par défaut" name="System Default Language"/>
+ <combo_box.item label="English (Anglais)" name="English"/>
+ <combo_box.item label="Dansk (Danois) - Bêta" name="Danish"/>
+ <combo_box.item label="Deutsch (Allemand) - Bêta" name="Deutsch(German)"/>
+ <combo_box.item label="Español (Espagnol) - Bêta" name="Spanish"/>
+ <combo_box.item label="Français - Bêta" name="French"/>
+ <combo_box.item label="Italiano (Italien) - Bêta" name="Italian"/>
+ <combo_box.item label="Nederlands (Néerlandais) - Bêta" name="Dutch"/>
+ <combo_box.item label="Polski (Polonais) - Bêta" name="Polish"/>
+ <combo_box.item label="Portugués (Portugais) - Bêta" name="Portugese"/>
+ <combo_box.item label="日本語 (Japonais) - Bêta" name="(Japanese)"/>
+ <combo_box.item label="Tests langue" name="TestLanguage"/>
+ </combo_box>
+ <text name="language_textbox2">
+ (redémarrage requis)
</text>
<text name="maturity_desired_prompt">
Je veux accéder au contenu classé :
</text>
- <combo_box name="maturity_desired_combobox" left="340">
- <combo_item name="Desired_Adult">
- PG, Mature et Adult
- </combo_item>
- <combo_item name="Desired_Mature">
- PG et Mature
- </combo_item>
- <combo_item name="Desired_PG">
- PG uniquement
- </combo_item>
+ <text name="maturity_desired_textbox"/>
+ <combo_box name="maturity_desired_combobox">
+ <combo_box.item label="PG, Mature et Adult" name="Desired_Adult"/>
+ <combo_box.item label="PG et Mature" name="Desired_Mature"/>
+ <combo_box.item label="PG" name="Desired_PG"/>
</combo_box>
- <text name="maturity_desired_textbox" left="340">
- PG uniquement
+ <text name="start_location_textbox">
+ Lieu de départ :
</text>
- <text length="1" name="start_location_textbox" type="string">
- Lieu de départ :
+ <combo_box name="start_location_combo">
+ <combo_box.item label="Dernier emplacement" name="MyLastLocation" tool_tip="Par défaut, choisir mon dernier emplacement comme lieu de départ."/>
+ <combo_box.item label="Domicile" name="MyHome" tool_tip="Par défaut, choisir mon domicile comme lieu de départ."/>
+ </combo_box>
+ <check_box initial_value="true" label="Afficher à la connexion" name="show_location_checkbox"/>
+ <text name="name_tags_textbox">
+ Affichage des noms :
</text>
- <text length="1" name="show_names_textbox" type="string">
- Afficher les noms :
+ <radio_group name="Name_Tag_Preference">
+ <radio_item label="Désactivé" name="radio"/>
+ <radio_item label="Activé" name="radio2"/>
+ <radio_item label="Afficher brièvement" name="radio3"/>
+ </radio_group>
+ <check_box label="Afficher mon nom" name="show_my_name_checkbox1"/>
+ <check_box initial_value="true" label="Affichage en petit" name="small_avatar_names_checkbox"/>
+ <check_box label="Afficher les titres de groupe" name="show_all_title_checkbox1"/>
+ <text name="effects_color_textbox">
+ Mes effets :
</text>
- <text bottom="-174" length="1" name="effects_color_textbox" type="string">
- Couleur du faisceau
-de sélection :
+ <color_swatch label="" name="effect_color_swatch" tool_tip="Cliquer pour ouvrir le sélecteur de couleurs"/>
+ <text name="title_afk_text">
+ Délai d&apos;absence :
</text>
- <text length="1" name="seconds_textbox" type="string">
+ <spinner label="" name="afk_timeout_spinner"/>
+ <text name="seconds_textbox">
secondes
</text>
- <text length="1" name="crash_report_textbox" type="string">
- Rapports de crash :
- </text>
- <text length="1" name="language_textbox" type="string">
- Langue :
- </text>
- <text left_delta="313" length="1" name="language_textbox2" type="string">
- (redémarrage requis)
+ <text name="text_box3">
+ Réponse si occupé(e) :
</text>
- <string name="region_name_prompt">
- &lt;Saisissez le nom de la région&gt;
- </string>
- <combo_box name="crash_behavior_combobox" width="166">
- <combo_item length="1" name="Askbeforesending" type="string">
- Demander avant d&apos;envoyer
- </combo_item>
- <combo_item length="1" name="Alwayssend" type="string">
- Toujours envoyer
- </combo_item>
- <combo_item length="1" name="Neversend" type="string">
- Ne jamais envoyer
- </combo_item>
- </combo_box>
- <combo_box name="language_combobox" width="166">
- <combo_item name="System Default Language">
- Choix par défaut
- </combo_item>
- <combo_item length="1" name="English" type="string">
- English (Anglais)
- </combo_item>
- <combo_item length="1" name="Danish" type="string">
- Dansk (Danois) - Bêta
- </combo_item>
- <combo_item length="1" name="Deutsch(German)" type="string">
- Deutsch (Allemand) - Bêta
- </combo_item>
- <combo_item name="Spanish">
- Español (Espagnol) - Bêta
- </combo_item>
- <combo_item name="French">
- Français - Bêta
- </combo_item>
- <combo_item name="Italian">
- Italiano (Italien) - Bêta
- </combo_item>
- <combo_item name="Hungarian">
- Magyar (Hongrois) - Bêta
- </combo_item>
- <combo_item name="Dutch">
- Nederlands (Néerlandais) - Bêta
- </combo_item>
- <combo_item name="Polish">
- Polski (Polonais) - Bêta
- </combo_item>
- <combo_item name="Portugese">
- Portugués (Portugais) - Bêta
- </combo_item>
- <combo_item name="Russian">
- РуÑÑкий (Russe) - Bêta
- </combo_item>
- <combo_item name="Turkish">
- Türkçe (Turc) - Bêta
- </combo_item>
- <combo_item name="Ukrainian">
- УкраїнÑька (Ukrainien) - Bêta
- </combo_item>
- <combo_item length="1" name="Chinese" type="string">
- 中文 (简体) (Chinois) - Bêta
- </combo_item>
- <combo_item length="1" name="(Japanese)" type="string">
- 日本語 (Japonais) - Bêta
- </combo_item>
- <combo_item length="1" name="(Korean)" type="string">
- 한국어 (Coréen) - Bêta
- </combo_item>
- </combo_box>
- <check_box label="Partager la langue avec les objets" name="language_is_public" tool_tip="Cette option permet de faire connaître aux objets du Monde votre langue favorite."/>
+ <text_editor name="busy_response">
+ log_in_to_change
+ </text_editor>
</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/fr/panel_preferences_graphics1.xml
index 27825b7ff9..4459244395 100644
--- a/indra/newview/skins/default/xui/fr/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/fr/panel_preferences_graphics1.xml
@@ -1,81 +1,28 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Graphiques" name="Display panel">
- <button label="?" name="GraphicsPreferencesHelpButton"/>
- <text_editor bottom="-56" height="40" left="25" name="FullScreenInfo" width="460">
- Décochez cette option pour passer en mode plein écran.
- </text_editor>
<text name="WindowSizeLabel">
Taille de la fenêtre :
</text>
+ <check_box label="Utiliser le plein écran" name="windowed mode"/>
<combo_box name="windowsize combo">
- <combo_item name="640x480">
- 640 x 480
- </combo_item>
- <combo_item name="800x600">
- 800 x 600
- </combo_item>
- <combo_item name="720x480">
- 720 x 480 (NTSC)
- </combo_item>
- <combo_item name="768x576">
- 768 x 576 (PAL)
- </combo_item>
- <combo_item name="1024x768">
- 1024 x 768
- </combo_item>
+ <combo_box.item label="640 x 480" name="640x480"/>
+ <combo_box.item label="800 x 600" name="800x600"/>
+ <combo_box.item label="720 x 480 (NTSC)" name="720x480"/>
+ <combo_box.item label="768 x 576 (PAL)" name="768x576"/>
+ <combo_box.item label="1024 x 768" name="1024x768"/>
</combo_box>
- <text name="DisplayResLabel" width="165">
- Résolution de l&apos;affichage :
+ <text name="UI Size:">
+ Taille de l&apos;interface :
</text>
- <text name="AspectRatioLabel1" tool_tip="largeur/hauteur">
- Rapport hauteur/largeur :
- </text>
- <combo_box name="aspect_ratio" tool_tip="largeur/hauteur">
- <combo_item length="1" name="4:3(StandardCRT)" type="string">
- 4:3 (Standard CRT)
- </combo_item>
- <combo_item length="1" name="5:4(1280x1024LCD)" type="string">
- 5:4 (1280 x 1024 LCD)
- </combo_item>
- <combo_item name="8:5(Widescreen)">
- 8:5 (écran large)
- </combo_item>
- <combo_item length="1" name="16:9(Widescreen)" type="string">
- 16:9 (plein écran)
- </combo_item>
- </combo_box>
- <text length="1" name="text" type="string">
- Résolution d&apos;affichage :
- </text>
- <text length="1" name="Fullscreen Aspect Ratio:" type="string">
- Format de plein écran :
- </text>
- <text length="1" name="(width / height)" type="string">
- (largeur / hauteur)
- </text>
- <text length="1" name="UI Size:" type="string">
- Taille de l&apos;IU :
- </text>
- <text length="1" name="(meters, lower is faster)" type="string">
- (mètres, moins = plus rapide)
- </text>
- <text length="1" name="text2" type="string">
- Options d&apos;affichage :
- </text>
- <check_box label="Lancer Second Life en mode fenêtré" name="windowed mode"/>
- <check_box label="Auto-détection du ratio" left="350" name="aspect_auto_detect"/>
- <check_box label="Utiliser échelle de résolution indépendante" name="ui_auto_scale"/>
- <check_box label="Montrer l&apos;avatar en vue subjective" name="avfp"/>
- <spinner label="Distance d&apos;affichage :" name="draw_distance"/>
- <text name="HigherText">
- Qualité et
- </text>
- <text name="QualityText">
- Performance :
+ <text name="QualitySpeed">
+ Qualité et vitesse :
</text>
<text left="105" name="FasterText">
Plus rapide
</text>
+ <text name="BetterText">
+ Meilleur
+ </text>
<text name="ShadersPrefText">
Faible
</text>
@@ -88,108 +35,82 @@
<text name="ShadersPrefText4">
Ultra
</text>
- <text bottom="-86" left="325" name="HigherText2">
- Plus élevée
- </text>
- <text name="QualityText2" visible="false"/>
- <check_box label="Personnaliser" left="395" name="CustomSettings"/>
- <text name="ShadersText">
- Effets :
- </text>
- <check_box label="Placage de relief et brillance" name="BumpShiny"/>
- <check_box label="Effets de base" name="BasicShaders" tool_tip="Désactiver cette option peut empêcher certains drivers de cartes graphiques de planter."/>
- <check_box label="Effets atmosphériques" name="WindLightUseAtmosShaders"/>
- <check_box label="Reflets de l&apos;eau" name="Reflections"/>
- <text name="ReflectionDetailText">
- Objets reflétés :
- </text>
- <radio_group name="ReflectionDetailRadio">
- <radio_item name="0">
- Terrain et Arbres
- </radio_item>
- <radio_item name="1">
- Objets statiques
- </radio_item>
- <radio_item name="2">
- Objets et avatars
- </radio_item>
- <radio_item name="3">
- Tout
- </radio_item>
- </radio_group>
- <text name="AvatarRenderingText">
- Rendu de l&apos;avatar :
- </text>
- <check_box label="Avatars éloignés en 2D" name="AvatarImpostors"/>
- <check_box label="Accélération du rendu" name="AvatarVertexProgram"/>
- <check_box label="Mouvement des habits" name="AvatarCloth"/>
- <text name="DrawDistanceMeterText1">
- m
- </text>
- <text name="DrawDistanceMeterText2">
- m
- </text>
- <slider label="Limite d&apos;affichage :" name="DrawDistance"/>
- <slider label="Nombre de particules max. :" label_width="143" name="MaxParticleCount"/>
- <slider label="Qualité post-traitement :" name="RenderPostProcess"/>
- <text name="MeshDetailText">
- Détails des rendus :
- </text>
- <slider label=" Objets :" name="ObjectMeshDetail"/>
- <slider label=" Flexiprims :" name="FlexibleMeshDetail"/>
- <slider label=" Arbres :" name="TreeMeshDetail"/>
- <slider label=" Avatars :" name="AvatarMeshDetail"/>
- <slider label=" Relief :" name="TerrainMeshDetail"/>
- <slider label=" Ciel :" name="SkyMeshDetail"/>
- <text name="PostProcessText">
- Faible
- </text>
- <text name="ObjectMeshDetailText">
- Faible
- </text>
- <text name="FlexibleMeshDetailText">
- Faible
- </text>
- <text name="TreeMeshDetailText">
- Faible
- </text>
- <text name="AvatarMeshDetailText">
- Faible
- </text>
- <text name="TerrainMeshDetailText">
- Faible
- </text>
- <text name="SkyMeshDetailText">
- Faible
- </text>
- <text name="LightingDetailText">
- Sources lumineuses :
- </text>
- <radio_group name="LightingDetailRadio">
- <radio_item name="SunMoon">
- Soleil et lune uniquement
- </radio_item>
- <radio_item name="LocalLights">
- Lumières à proximité
- </radio_item>
- </radio_group>
- <text left="380" name="TerrainDetailText">
- Rendu du terrain :
- </text>
- <radio_group name="TerrainDetailRadio">
- <radio_item name="0">
+ <panel label="Graphiques personnalisés" name="CustomGraphics Panel">
+ <text name="ShadersText">
+ Effets :
+ </text>
+ <check_box initial_value="true" label="Placage de relief et brillance" name="BumpShiny"/>
+ <check_box initial_value="true" label="Effets de base" name="BasicShaders" tool_tip="La désactivation de cette option peut éviter le plantage de certains pilotes de cartes graphiques"/>
+ <check_box initial_value="true" label="Effets atmosphériques" name="WindLightUseAtmosShaders"/>
+ <check_box initial_value="true" label="Reflets dans l&apos;eau" name="Reflections"/>
+ <text name="ReflectionDetailText">
+ Objets reflétés :
+ </text>
+ <radio_group name="ReflectionDetailRadio">
+ <radio_item label="Terrain et arbres" name="0"/>
+ <radio_item label="Tous les objets statiques" name="1"/>
+ <radio_item label="Tous les objets et avatars" name="2"/>
+ <radio_item label="Tout" name="3"/>
+ </radio_group>
+ <text name="AvatarRenderingText">
+ Rendu de l&apos;avatar :
+ </text>
+ <check_box initial_value="true" label="Avatars éloignés en 2D" name="AvatarImpostors"/>
+ <check_box initial_value="true" label="Accélération du rendu" name="AvatarVertexProgram"/>
+ <check_box initial_value="true" label="Mouvement des habits" name="AvatarCloth"/>
+ <slider label="Limite d&apos;affichage :" name="DrawDistance"/>
+ <text name="DrawDistanceMeterText2">
+ m
+ </text>
+ <slider label="Nombre de particules max. :" label_width="143" name="MaxParticleCount"/>
+ <slider label="Qualité post-traitement :" name="RenderPostProcess"/>
+ <text name="MeshDetailText">
+ Détails des rendus :
+ </text>
+ <slider label=" Objets :" name="ObjectMeshDetail"/>
+ <slider label=" Flexiprims :" name="FlexibleMeshDetail"/>
+ <slider label=" Arbres :" name="TreeMeshDetail"/>
+ <slider label=" Avatars :" name="AvatarMeshDetail"/>
+ <slider label=" Relief :" name="TerrainMeshDetail"/>
+ <slider label=" Ciel :" name="SkyMeshDetail"/>
+ <text name="PostProcessText">
Faible
- </radio_item>
- <radio_item name="2">
- Élevé
- </radio_item>
- </radio_group>
- <button label="Paramètres recommandés" name="Defaults"/>
- <button label="Configuration du matériel" label_selected="Configuration du matériel" name="GraphicsHardwareButton"/>
- <text name="resolution_format">
- [RES_X] x [RES_Y]
- </text>
- <text name="aspect_ratio_text">
- [NUM]:[DEN]
- </text>
+ </text>
+ <text name="ObjectMeshDetailText">
+ Faible
+ </text>
+ <text name="FlexibleMeshDetailText">
+ Faible
+ </text>
+ <text name="TreeMeshDetailText">
+ Faible
+ </text>
+ <text name="AvatarMeshDetailText">
+ Faible
+ </text>
+ <text name="TerrainMeshDetailText">
+ Faible
+ </text>
+ <text name="SkyMeshDetailText">
+ Faible
+ </text>
+ <text name="LightingDetailText">
+ Sources lumineuses :
+ </text>
+ <radio_group name="LightingDetailRadio">
+ <radio_item label="Soleil et lune uniquement" name="SunMoon"/>
+ <radio_item label="Lumières à proximité" name="LocalLights"/>
+ </radio_group>
+ <text left="380" name="TerrainDetailText">
+ Rendu du terrain :
+ </text>
+ <radio_group name="TerrainDetailRadio">
+ <radio_item label="Bas" name="0"/>
+ <radio_item label="Haut" name="2"/>
+ </radio_group>
+ </panel>
+ <button label="Appliquer" label_selected="Appliquer" name="Apply"/>
+ <button label="Réinitialiser" name="Defaults"/>
+ <button label="Avancé" name="Advanced"/>
+ <button label="Matériel" label_selected="Matériel" name="GraphicsHardwareButton"/>
</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/fr/panel_preferences_privacy.xml
new file mode 100644
index 0000000000..4bb6c76617
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_preferences_privacy.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Communication" name="im">
+ <panel.string name="log_in_to_change">
+ se connecter pour changer
+ </panel.string>
+ <button label="Vider le cache" name="clear_cache"/>
+ <text name="cache_size_label_l">
+ (Endroits, images, web, historique des recherches)
+ </text>
+ <check_box label="Seuls mes amis et groupes voient quand je suis en ligne" name="online_visibility"/>
+ <check_box label="Seuls mes amis et groupes peuvent m&apos;appeler ou m&apos;envoyer un IM" name="voice_call_friends_only_check"/>
+ <check_box label="Fermer le micro à la fin d&apos;un appel" name="auto_disengage_mic_check"/>
+ <check_box label="Accepter les cookies" name="cookies_enabled"/>
+ <check_box label="Autoriser la lecture automatique des médias" name="autoplay_enabled"/>
+ <check_box label="Lire le média de la parcelle automatiquement" name="parcel_autoplay_enabled"/>
+ <text name="Logs:">
+ Journaux :
+ </text>
+ <check_box label="Sauvegarder les chats près de moi sur mon ordinateur" name="log_nearby_chat"/>
+ <check_box label="Sauvegarder les IM sur mon ordinateur" name="log_instant_messages"/>
+ <check_box label="Inclure les heures" name="show_timestamps_check_im"/>
+ <line_editor left="308" name="log_path_string" right="-20"/>
+ <text name="log_path_desc">
+ Emplacement
+ </text>
+ <button label="Parcourir" label_selected="Parcourir" name="log_path_button" width="150"/>
+ <button label="Liste des ignorés" name="block_list"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_setup.xml b/indra/newview/skins/default/xui/fr/panel_preferences_setup.xml
new file mode 100644
index 0000000000..ffc822d76f
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_preferences_setup.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Contrôle et caméra" name="Input panel">
+ <button label="Autres accessoires" name="joystick_setup_button" width="175"/>
+ <text name="Mouselook:">
+ Vue subjective :
+ </text>
+ <text name=" Mouse Sensitivity">
+ Sensibilité de la souris
+ </text>
+ <check_box label="Inverser" name="invert_mouse"/>
+ <text name="Network:">
+ Réseau :
+ </text>
+ <text name="Maximum bandwidth">
+ Bande passante maximale
+ </text>
+ <text name="text_box2">
+ kbps
+ </text>
+ <check_box label="Port de connexion personnalisé" name="connection_port_enabled"/>
+ <spinner label="Numéro de port :" name="web_proxy_port"/>
+ <text name="cache_size_label_l">
+ Taille de la mémoire
+ </text>
+ <text name="text_box5">
+ Mo
+ </text>
+ <button label="Parcourir" label_selected="Parcourir" name="set_cache"/>
+ <button label="Réinitialiser" label_selected="Choisir" name="reset_cache"/>
+ <text name="Cache location">
+ Emplacement du cache
+ </text>
+ <text name="Web:">
+ Web :
+ </text>
+ <radio_group name="use_external_browser">
+ <radio_item label="Utiliser le navigateur intégré" name="internal" tool_tip="Utilisez le navigateur intégré pour obtenir de l&apos;aide, ouvrir des liens, etc. Ce navigateur s&apos;ouvre dans [APP_NAME]."/>
+ <radio_item label="Utiliser mon navigateur (IE, Firefox etc.)" name="external" tool_tip="Utiliser le navigateur web système par défaut pour l&apos;aide, les liens etc. Non recommandé en mode plein écran."/>
+ </radio_group>
+ <check_box initial_value="false" label="Proxy web" name="web_proxy_enabled"/>
+ <line_editor name="web_proxy_editor" tool_tip="Le nom ou adresse IP du proxy que vous souhaitez utiliser"/>
+ <button label="Parcourir" label_selected="Parcourir" name="set_proxy"/>
+ <text name="Proxy location">
+ Emplacement du proxy
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_sound.xml b/indra/newview/skins/default/xui/fr/panel_preferences_sound.xml
new file mode 100644
index 0000000000..27768ac73b
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_preferences_sound.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Sons" name="Preference Media panel">
+ <slider label="Volume principal" name="System Volume"/>
+ <check_box initial_value="true" label="Couper le son si minimisé" name="mute_when_minimized"/>
+ <slider label="Ambiant" name="Wind Volume"/>
+ <slider label="Boutons" name="UI Volume"/>
+ <slider label="Média" name="Media Volume"/>
+ <slider label="Effets sonores" name="SFX Volume"/>
+ <slider label="Flux musical" name="Music Volume"/>
+ <check_box label="Voix" name="enable_voice_check"/>
+ <slider label="Voix" name="Voice Volume"/>
+ <text name="Listen from">
+ Écouter à partir de :
+ </text>
+ <radio_group name="ear_location">
+ <radio_item label="Position de la caméra" name="0"/>
+ <radio_item label="Position de l&apos;avatar" name="1"/>
+ </radio_group>
+ <button label="Périphériques d&apos;entrée/de sortie" name="device_settings_btn"/>
+ <panel label="Paramètres du matériel" name="device_settings_panel">
+ <panel.string name="default_text">
+ Défaut
+ </panel.string>
+ <text name="Input">
+ Entrée
+ </text>
+ <text name="My volume label">
+ Mon volume :
+ </text>
+ <slider_bar initial_value="1.0" name="mic_volume_slider" tool_tip="Régler le volume avec le curseur"/>
+ <text name="wait_text">
+ Veuillez patienter
+ </text>
+ <text name="Output">
+ Sortie
+ </text>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/fr/panel_prim_media_controls.xml
new file mode 100644
index 0000000000..dd70c40c3e
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_prim_media_controls.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="MediaControls">
+ <string name="control_background_image_name">
+ Inspector_Background
+ </string>
+ <string name="skip_step">
+ 0.2
+ </string>
+ <layout_stack name="media_controls">
+ <layout_panel name="media_address">
+ <line_editor name="media_address_url" tool_tip="URL du média"/>
+ <layout_stack name="media_address_url_icons">
+ <layout_panel>
+ <icon name="media_whitelist_flag" tool_tip="Liste blanche activée"/>
+ </layout_panel>
+ <layout_panel>
+ <icon name="media_secure_lock_flag" tool_tip="Navigation sécurisée"/>
+ </layout_panel>
+ </layout_stack>
+ </layout_panel>
+ <layout_panel name="media_play_position">
+ <slider_bar initial_value="0.5" name="media_play_slider" tool_tip="Progrès de la lecture du film"/>
+ </layout_panel>
+ <layout_panel name="media_volume">
+ <button name="media_volume_button" tool_tip="Couper le son de ce média"/>
+ </layout_panel>
+ </layout_stack>
+ <layout_stack>
+ <panel name="media_progress_indicator">
+ <progress_bar name="media_progress_bar" tool_tip="Le média est en cours de chargement"/>
+ </panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_profile.xml b/indra/newview/skins/default/xui/fr/panel_profile.xml
new file mode 100644
index 0000000000..c2e291bd09
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_profile.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Profil" name="panel_profile">
+ <string name="CaptionTextAcctInfo">
+ [ACCTTYPE]
+[PAYMENTINFO] [AGEVERIFICATION]
+ </string>
+ <string name="payment_update_link_url">
+ http://www.secondlife.com/account/billing.php?lang=fr-FR
+ </string>
+ <string name="partner_edit_link_url">
+ http://www.secondlife.com/account/partners.php?lang=fr
+ </string>
+ <string name="my_account_link_url" value="http://secondlife.com/my/account/index.php?lang=fr-FR"/>
+ <string name="no_partner_text" value="Aucun"/>
+ <string name="RegisterDateFormat">
+ [REG_DATE] ([AGE])
+ </string>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <panel name="second_life_image_panel">
+ <text name="title_sl_descr_text" value="[SECOND_LIFE]:"/>
+ <expandable_text name="sl_description_edit">
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ <panel name="first_life_image_panel">
+ <text name="title_rw_descr_text" value="Monde physique :"/>
+ <expandable_text name="fl_description_edit">
+ Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ <text name="me_homepage_text">
+ Page d&apos;accueil :
+ </text>
+ <text name="title_member_text" value="Membre depuis :"/>
+ <text name="register_date" value="05/31/1976"/>
+ <text name="title_acc_status_text" value="Statut du compte :"/>
+ <text name="acc_status_text" value="Résident. Aucune info de paiement enregistrée."/>
+ <text name="title_partner_text" value="Partenaire :"/>
+ <panel name="partner_data_panel">
+ <text name="partner_text" value="[FIRST] [LAST]"/>
+ </panel>
+ <text name="title_groups_text" value="Groupes :"/>
+ <expandable_text name="sl_groups">
+ Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ </scroll_container>
+ <panel name="profile_buttons_panel">
+ <button label="Devenir amis" name="add_friend"/>
+ <button label="IM" name="im"/>
+ <button label="Appeler" name="call"/>
+ <button label="Carte" name="show_on_map_btn"/>
+ <button label="Téléporter" name="teleport"/>
+ <button label="â–¼" name="overflow_btn"/>
+ </panel>
+ <panel name="profile_me_buttons_panel">
+ <button label="Modifier le profil" name="edit_profile_btn"/>
+ <button label="Changer d&apos;apparence" name="edit_appearance_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_profile_view.xml b/indra/newview/skins/default/xui/fr/panel_profile_view.xml
new file mode 100644
index 0000000000..8f57dd89c7
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_profile_view.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_target_profile">
+ <string name="status_online">
+ En ligne
+ </string>
+ <string name="status_offline">
+ Hors ligne
+ </string>
+ <text_editor name="user_name" value="(en cours de chargement...)"/>
+ <text name="status" value="En ligne"/>
+ <tab_container name="tabs">
+ <panel label="PROFIL" name="panel_profile"/>
+ <panel label="FAVORIS" name="panel_picks"/>
+ <panel label="NOTES/PERSO" name="panel_notes"/>
+ </tab_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_region_covenant.xml b/indra/newview/skins/default/xui/fr/panel_region_covenant.xml
index f2ba297fd2..cf9f4e0fd0 100644
--- a/indra/newview/skins/default/xui/fr/panel_region_covenant.xml
+++ b/indra/newview/skins/default/xui/fr/panel_region_covenant.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Règlement" name="Covenant">
<text name="estate_section_lbl">
- Domaine :
+ Domaine
</text>
<text bottom_delta="-19" name="estate_name_lbl">
Nom :
@@ -34,13 +34,13 @@
Faire glisser une note pour changer le règlement de ce domaine.
</text>
<text name="region_section_lbl">
- Région :
+ Région
</text>
<text name="region_name_lbl">
Nom :
</text>
<text name="region_name_text">
- leyla
+ Erica
</text>
<text name="region_landtype_lbl">
Type :
diff --git a/indra/newview/skins/default/xui/fr/panel_region_debug.xml b/indra/newview/skins/default/xui/fr/panel_region_debug.xml
index 1338ab9e71..0fabf92889 100644
--- a/indra/newview/skins/default/xui/fr/panel_region_debug.xml
+++ b/indra/newview/skins/default/xui/fr/panel_region_debug.xml
@@ -12,8 +12,8 @@
<button label="?" name="disable_collisions_help"/>
<check_box label="Désactiver la physique" name="disable_physics_check" tool_tip="Désactiver tous les effets liés à la physique dans cette région"/>
<button label="?" name="disable_physics_help"/>
- <button label="Appliquer" name="apply_btn" bottom_delta="-38"/>
- <text name="objret_text_lbl" bottom_delta="-42">
+ <button bottom_delta="-38" label="Appliquer" name="apply_btn"/>
+ <text bottom_delta="-42" name="objret_text_lbl">
Renvoi de l&apos;objet
</text>
<text name="resident_text_lbl">
@@ -22,19 +22,19 @@
<line_editor name="target_avatar_name">
(aucun)
</line_editor>
- <button label="Choisir..." name="choose_avatar_btn"/>
+ <button label="Choisir" name="choose_avatar_btn"/>
<text name="options_text_lbl">
Options :
</text>
- <check_box label="Ne renvoyer que les objets avec des scripts" name="return_scripts" tool_tip="Ne renvoyer que les objets avec des scripts."/>
- <check_box label="Ne renvoyer que les objets sur le terrain de quelqu&apos;un d&apos;autre" name="return_other_land" tool_tip="Ne renvoyer que les objets se trouvant sur le terrain de quelqu&apos;un d&apos;autre"/>
- <check_box label="Renvoyer les objets dans toutes les régions de ce domaine" name="return_estate_wide" tool_tip="Renvoyer les objets dans toutes les régions qui constituent ce domaine"/>
+ <check_box label="Avec scripts" name="return_scripts" tool_tip="Renvoyer les objets avec scripts uniquement"/>
+ <check_box label="Sur le terrain d&apos;un autre résident" name="return_other_land" tool_tip="Ne renvoyer que les objets se trouvant sur le terrain de quelqu&apos;un d&apos;autre"/>
+ <check_box label="Dans toutes les régions de ce domaine" name="return_estate_wide" tool_tip="Renvoyer les objets dans toutes les régions qui constituent ce domaine"/>
<button label="Renvoyer" name="return_btn"/>
<button label="Afficher les collisions les plus consommatrices..." name="top_colliders_btn" tool_tip="Liste des objets avec le plus de collisions potentielles" width="320"/>
- <button label="?" name="top_colliders_help" left="337"/>
+ <button label="?" left="337" name="top_colliders_help"/>
<button label="Afficher les objets scriptés les plus consommateurs..." name="top_scripts_btn" tool_tip="Liste des objets qui passent le plus de temps à exécuter des scripts" width="320"/>
- <button label="?" name="top_scripts_help" left="337"/>
+ <button label="?" left="337" name="top_scripts_help"/>
<button label="Redémarrer la région" name="restart_btn" tool_tip="Redémarrer la région au bout de 2 minutes" width="160"/>
- <button label="?" name="restart_help" left="177" />
+ <button label="?" left="177" name="restart_help"/>
<button label="Retarder le redémarrage" name="cancel_restart_btn" tool_tip="Retarder le redémarrage de la région d&apos;une heure" width="160"/>
</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_region_estate.xml b/indra/newview/skins/default/xui/fr/panel_region_estate.xml
index 425f273790..bfe33a1c3d 100644
--- a/indra/newview/skins/default/xui/fr/panel_region_estate.xml
+++ b/indra/newview/skins/default/xui/fr/panel_region_estate.xml
@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Domaine" name="Estate">
- <text name="estate_help_text" bottom="-34">
+ <text bottom="-34" name="estate_help_text">
Les changements apportés aux paramètres
de cet onglet auront des répercussions sur
toutes les régions du domaine.
</text>
- <text name="estate_text" bottom_delta="-34">
+ <text bottom_delta="-34" name="estate_text">
Domaine :
</text>
<text name="estate_name">
(inconnu)
</text>
<text name="owner_text">
- Propriétaire :
+ Propriétaire :
</text>
<text name="estate_owner">
(inconnu)
@@ -20,8 +20,8 @@ toutes les régions du domaine.
<text name="Only Allow">
Limiter l&apos;accès aux résidents qui :
</text>
- <check_box label="Ont enregistré leurs infos de paiement" name="limit_payment" tool_tip="Bannir les résidents non identifés."/>
- <check_box label="Ont fait vérifier leur âge" name="limit_age_verified" tool_tip="Bannir les résidents dont l&apos;âge n&apos;a pas été vérifié. Pour plus d&apos;infos, consultez la page support.secondlife.com."/>
+ <check_box label="Ont enregistré leurs infos de paiement" name="limit_payment" tool_tip="Interdire les résidents non identifiés"/>
+ <check_box label="Ont fait vérifier leur âge" name="limit_age_verified" tool_tip="Interdire les résidents qui n&apos;ont pas vérifié leur âge. Consultez la page [SUPPORT_SITE] pour plus d&apos;informations."/>
<check_box label="Autoriser les chats vocaux" name="voice_chat_check"/>
<button label="?" name="voice_chat_help"/>
<text name="abuse_email_text">
diff --git a/indra/newview/skins/default/xui/fr/panel_region_general.xml b/indra/newview/skins/default/xui/fr/panel_region_general.xml
index 6a8afd24ed..70782e2aa6 100644
--- a/indra/newview/skins/default/xui/fr/panel_region_general.xml
+++ b/indra/newview/skins/default/xui/fr/panel_region_general.xml
@@ -40,15 +40,9 @@
Catégorie :
</text>
<combo_box label="Mature" name="access_combo">
- <combo_item name="Adult">
- Adult
- </combo_item>
- <combo_item name="Mature">
- Mature
- </combo_item>
- <combo_item name="PG">
- PG
- </combo_item>
+ <combo_box.item label="Adult" name="Adult"/>
+ <combo_box.item label="Mature" name="Mature"/>
+ <combo_box.item label="PG" name="PG"/>
</combo_box>
<button label="?" name="access_help"/>
<button label="Appliquer" name="apply_btn"/>
diff --git a/indra/newview/skins/default/xui/fr/panel_region_texture.xml b/indra/newview/skins/default/xui/fr/panel_region_texture.xml
index d312646788..91d315848e 100644
--- a/indra/newview/skins/default/xui/fr/panel_region_texture.xml
+++ b/indra/newview/skins/default/xui/fr/panel_region_texture.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Textures du sol" name="Textures">
<text name="region_text_lbl">
Région :
@@ -44,6 +44,7 @@
</text>
<text name="height_text_lbl11">
En mètres, la valeur Bas correspond à la hauteur maximum de la texture n°1
+et la valeur Haut correspond à la hauteur minimum de la texture n°4.
</text>
<text name="height_text_lbl12">
et la valeur Haut correspond à la hauteur minimum de la texture n°4.
@@ -51,14 +52,14 @@
<text name="height_text_lbl13">
Nord-est
</text>
- <spinner label="Bas" name="height_start_spin_0" />
- <spinner label="Bas" name="height_start_spin_1" />
- <spinner label="Bas" name="height_start_spin_2" />
- <spinner label="Bas" name="height_start_spin_3" />
- <spinner label="Haut" name="height_range_spin_0" />
- <spinner label="Haut" name="height_range_spin_1" />
- <spinner label="Haut" name="height_range_spin_2" />
- <spinner label="Haut" name="height_range_spin_3" />
+ <spinner label="Bas" name="height_start_spin_0"/>
+ <spinner label="Bas" name="height_start_spin_1"/>
+ <spinner label="Bas" name="height_start_spin_2"/>
+ <spinner label="Bas" name="height_start_spin_3"/>
+ <spinner label="Haut" name="height_range_spin_0"/>
+ <spinner label="Haut" name="height_range_spin_1"/>
+ <spinner label="Haut" name="height_range_spin_2"/>
+ <spinner label="Haut" name="height_range_spin_3"/>
<text name="height_text_lbl14">
Ces valeurs représentent les limites de mélange pour les textures ci-dessus.
</text>
@@ -68,5 +69,5 @@
<text name="height_text_lbl16">
et la valeur HAUTE correspond à la hauteur MINIMUM de la Texture #4.
</text>
- <button label="Appliquer" name="apply_btn" />
+ <button label="Appliquer" name="apply_btn"/>
</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_script_ed.xml b/indra/newview/skins/default/xui/fr/panel_script_ed.xml
new file mode 100644
index 0000000000..ea161ecae8
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_script_ed.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="script panel">
+ <panel.string name="loading">
+ Chargement...
+ </panel.string>
+ <panel.string name="can_not_view">
+ Ce script ne peut pas être copié, visualisé ou modifié. Pour visualiser ou modifier un script à l&apos;intérieur d&apos;un objet, vous devez avoir les permissions requises.
+ </panel.string>
+ <panel.string name="public_objects_can_not_run">
+ Les objets publics ne peuvent pas exécuter de scripts
+ </panel.string>
+ <panel.string name="script_running">
+ Exécution en cours
+ </panel.string>
+ <panel.string name="Title">
+ Script : [NAME]
+ </panel.string>
+ <text_editor name="Script Editor">
+ Chargement...
+ </text_editor>
+ <button label="Enregistrer" label_selected="Enregistrer" name="Save_btn"/>
+ <combo_box label="Insérer..." name="Insert..."/>
+ <menu_bar name="script_menu">
+ <menu label="Fichier" name="File">
+ <menu_item_call label="Enregistrer" name="Save"/>
+ <menu_item_call label="Annuler tous les changements" name="Revert All Changes"/>
+ </menu>
+ <menu label="Éditer" name="Edit">
+ <menu_item_call label="Annuler" name="Undo"/>
+ <menu_item_call label="Refaire" name="Redo"/>
+ <menu_item_call label="Couper" name="Cut"/>
+ <menu_item_call label="Copier" name="Copy"/>
+ <menu_item_call label="Coller" name="Paste"/>
+ <menu_item_call label="Tout sélectionner" name="Select All"/>
+ <menu_item_call label="Désélectionner" name="Deselect"/>
+ <menu_item_call label="Rechercher / Remplacer..." name="Search / Replace..."/>
+ </menu>
+ <menu label="Aide" name="Help">
+ <menu_item_call label="Aide..." name="Help..."/>
+ <menu_item_call label="Aide par mots-clés..." name="Keyword Help..."/>
+ </menu>
+ </menu_bar>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_scrolling_param.xml b/indra/newview/skins/default/xui/fr/panel_scrolling_param.xml
index a6ec93bef5..8febdccbed 100644
--- a/indra/newview/skins/default/xui/fr/panel_scrolling_param.xml
+++ b/indra/newview/skins/default/xui/fr/panel_scrolling_param.xml
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="LLScrollingPanelParam">
- <text type="string" length="1" name="Loading...">
+ <text name="Loading...">
Chargement...
</text>
- <text type="string" length="1" name="Loading...2">
+ <text name="Loading...2">
Chargement...
</text>
<button label="" label_selected="" name="less" />
diff --git a/indra/newview/skins/default/xui/fr/panel_side_tray.xml b/indra/newview/skins/default/xui/fr/panel_side_tray.xml
new file mode 100644
index 0000000000..816834a985
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_side_tray.xml
@@ -0,0 +1,26 @@
+<?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="Domicile." name="sidebar_home">
+ <panel label="domicile" name="panel_home"/>
+ </sidetray_tab>
+ <sidetray_tab description="Trouvez vos amis, vos contacts et les personnes se trouvant près de vous." name="sidebar_people">
+ <panel_container name="panel_container">
+ <panel label="Profil du groupe" name="panel_group_info_sidetray"/>
+ <panel label="Résidents et objets ignorés" name="panel_block_list_sidetray"/>
+ </panel_container>
+ </sidetray_tab>
+ <sidetray_tab description="Trouvez de nouveaux lieux à découvrir et les lieux que vous connaissez déjà." label="Lieux" name="sidebar_places">
+ <panel label="Lieux" name="panel_places"/>
+ </sidetray_tab>
+ <sidetray_tab description="Modifiez votre profil public et vos Favoris." name="sidebar_me">
+ <panel label="Moi" name="panel_me"/>
+ </sidetray_tab>
+ <sidetray_tab description="Modifiez votre apparence actuelle." name="sidebar_appearance">
+ <panel label="Changer d&apos;apparence" name="sidepanel_appearance"/>
+ </sidetray_tab>
+ <sidetray_tab description="Parcourez votre inventaire." name="sidebar_inventory">
+ <panel label="Modifier l&apos;inventaire" name="sidepanel_inventory"/>
+ </sidetray_tab>
+</side_tray>
diff --git a/indra/newview/skins/default/xui/fr/panel_side_tray_tab_caption.xml b/indra/newview/skins/default/xui/fr/panel_side_tray_tab_caption.xml
new file mode 100644
index 0000000000..2899f630f4
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_side_tray_tab_caption.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="sidetray_tab_panel">
+ <text name="sidetray_tab_title" value="Panneau latéral"/>
+ <button name="show_help" tool_tip="Afficher l&apos;aide"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_sidetray_home_tab.xml b/indra/newview/skins/default/xui/fr/panel_sidetray_home_tab.xml
new file mode 100644
index 0000000000..48bcff1c09
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_sidetray_home_tab.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- Part of side tray, see that XML file for panel config -->
+<panel label="home_tab" name="home_tab">
+ <scroll_container name="profile_scroll">
+ <panel name="profile_scroll_panel">
+ <panel name="sidebar_people">
+ <text name="tab_name" value="Résidents"/>
+ <text name="tab_description">
+ Trouvez vos amis, vos groupes, vos contacts et les personnes se trouvant près de vous.
+ </text>
+ </panel>
+ <panel name="sidebar_places">
+ <text name="tab_name" value="Lieux"/>
+ <text name="tab_description">
+ Trouvez de nouveaux lieux à découvrir et les lieux que vous connaissez déjà.
+ </text>
+ </panel>
+ <panel name="sidebar_me">
+ <text name="tab_name" value="Mon profil"/>
+ <text name="tab_description">
+ Modifiez votre profil public.
+ </text>
+ </panel>
+ <panel name="sidebar_appearance">
+ <text name="tab_name" value="Mon apparence"/>
+ <text name="tab_description">
+ Modifiez votre apparence actuelle.
+ </text>
+ </panel>
+ <panel name="sidebar_inventory">
+ <text name="tab_name" value="Mon inventaire"/>
+ <text name="tab_description">
+ Parcourez votre inventaire.
+ </text>
+ </panel>
+ </panel>
+ </scroll_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_stand_stop_flying.xml b/indra/newview/skins/default/xui/fr/panel_stand_stop_flying.xml
new file mode 100644
index 0000000000..ee4e8a6be6
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_stand_stop_flying.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- Width and height of this panel should be synchronized with "panel_modes" in the floater_moveview.xml-->
+<panel name="panel_stand_stop_flying">
+ <button label="Me lever" name="stand_btn" tool_tip="Cliquez ici pour vous lever."/>
+ <button label="Atterrir" name="stop_fly_btn" tool_tip="Atterrir"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_status_bar.xml b/indra/newview/skins/default/xui/fr/panel_status_bar.xml
index 2e4c694efa..9432b44f0e 100644
--- a/indra/newview/skins/default/xui/fr/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/fr/panel_status_bar.xml
@@ -1,41 +1,29 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="status">
- <text length="1" name="ParcelNameText" tool_tip="Nom de la parcelle de terrain sur laquelle vous vous trouvez. Cliquez pour ouvrir la section À propos du terrain." type="string">
- Saisissez le nom de la parcelle ici
- </text>
- <text length="1" name="BalanceText" tool_tip="Solde du compte" type="string">
- Chargement...
- </text>
- <button label="" label_selected="" name="buycurrency" tool_tip="Acheter des devises"/>
- <text length="12" name="TimeText" tool_tip="Heure actuelle (Californie)" type="string">
- midi
- </text>
- <string name="StatBarDaysOfWeek">
+ <panel.string name="StatBarDaysOfWeek">
Sunday:Monday:Tuesday:Wednesday:Thursday:Friday:Saturday
- </string>
- <string name="StatBarMonthsOfYear">
+ </panel.string>
+ <panel.string name="StatBarMonthsOfYear">
January:February:March:April:May:June:July:August:September:October:November:December
- </string>
- <button label="" label_selected="" name="scriptout" tool_tip="Alertes et erreurs de scripts"/>
- <button label="" label_selected="" name="health" tool_tip="Santé"/>
- <text length="1" name="HealthText" tool_tip="Santé" type="string">
- 100 %
- </text>
- <button label="" label_selected="" name="fly" tool_tip="Vol interdit"/>
- <button label="" label_selected="" name="build" tool_tip="Construction interdite"/>
- <button label="" label_selected="" name="scripts" tool_tip="Scripts interdits"/>
- <button name="no_fly" tool_tip="Interdiction de voler"/>
- <button name="no_build" tool_tip="Interdiction de construire/rezzer"/>
- <button name="no_scripts" tool_tip="Interdiction d&apos;utiliser des scripts"/>
- <button label="" label_selected="" name="restrictpush" tool_tip="Pas de bousculades"/>
- <button name="status_no_voice" tool_tip="Voix non disponible ici"/>
- <button label="" label_selected="" name="buyland" tool_tip="Acheter cette parcelle"/>
- <line_editor label="Rechercher" name="search_editor" tool_tip="Rechercher dans Second Life"/>
- <button name="search_btn" tool_tip="Rechercher dans Second Life"/>
- <text name="packet_loss_tooltip">
+ </panel.string>
+ <panel.string name="packet_loss_tooltip">
Perte de paquets
- </text>
- <text name="bandwidth_tooltip">
+ </panel.string>
+ <panel.string name="bandwidth_tooltip">
Bande passante
+ </panel.string>
+ <panel.string name="time">
+ [hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]
+ </panel.string>
+ <panel.string name="timeTooltip">
+ [weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]
+ </panel.string>
+ <panel.string name="buycurrencylabel">
+ [AMT] L$
+ </panel.string>
+ <button label="" label_selected="" name="buycurrency" tool_tip="Mon solde : Cliquez pour acheter plus de L$"/>
+ <text name="TimeText" tool_tip="Heure actuelle (Pacifique)">
+ midi
</text>
+ <button name="volume_btn" tool_tip="Contrôle du volume global"/>
</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_sys_well_item.xml b/indra/newview/skins/default/xui/fr/panel_sys_well_item.xml
new file mode 100644
index 0000000000..81db7c8989
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_sys_well_item.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- All our XML is utf-8 encoded. -->
+<panel name="sys_well_item" title="sys_well_item">
+ <text name="title">
+ Beware the trout. BEWARE! THE! TROUT!
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_teleport_history.xml b/indra/newview/skins/default/xui/fr/panel_teleport_history.xml
new file mode 100644
index 0000000000..623d2deae9
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_teleport_history.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="Teleport History">
+ <accordion name="history_accordion">
+ <accordion_tab name="today" title="Aujourd&apos;hui"/>
+ <accordion_tab name="yesterday" title="Hier"/>
+ <accordion_tab name="2_days_ago" title="Il y a 2 jours"/>
+ <accordion_tab name="3_days_ago" title="Il y a 3 jours"/>
+ <accordion_tab name="4_days_ago" title="Il y a 4 jours"/>
+ <accordion_tab name="5_days_ago" title="Il y a 5 jours"/>
+ <accordion_tab name="6_days_and_older" title="Il y a 6 jours ou plus"/>
+ <accordion_tab name="1_month_and_older" title="Il y a 1 mois ou plus"/>
+ <accordion_tab name="6_months_and_older" title="Il y a 6 mois ou plus"/>
+ </accordion>
+ <panel label="bottom_panel" name="bottom_panel"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_teleport_history_item.xml b/indra/newview/skins/default/xui/fr/panel_teleport_history_item.xml
new file mode 100644
index 0000000000..9d18c52442
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_teleport_history_item.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="teleport_history_item">
+ <text name="region" value="..."/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_world_map.xml b/indra/newview/skins/default/xui/fr/panel_world_map.xml
new file mode 100644
index 0000000000..e6e95c2605
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_world_map.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="world_map">
+ <panel.string name="Loading">
+ Chargement...
+ </panel.string>
+ <panel.string name="InvalidLocation">
+ Lieu invalide...
+ </panel.string>
+ <panel.string name="world_map_north">
+ N
+ </panel.string>
+ <panel.string name="world_map_east">
+ E
+ </panel.string>
+ <panel.string name="world_map_west">
+ O
+ </panel.string>
+ <panel.string name="world_map_south">
+ S
+ </panel.string>
+ <panel.string name="world_map_southeast">
+ SE
+ </panel.string>
+ <panel.string name="world_map_northeast">
+ NE
+ </panel.string>
+ <panel.string name="world_map_southwest">
+ SO
+ </panel.string>
+ <panel.string name="world_map_northwest">
+ NO
+ </panel.string>
+ <text label="N" name="floater_map_north" text="N">
+ N
+ </text>
+ <text label="E" name="floater_map_east" text="E">
+ E
+ </text>
+ <text label="O" name="floater_map_west" text="O">
+ O
+ </text>
+ <text label="S" name="floater_map_south" text="S">
+ S
+ </text>
+ <text label="SE" name="floater_map_southeast" text="SE">
+ SE
+ </text>
+ <text label="NE" name="floater_map_northeast" text="NE">
+ NE
+ </text>
+ <text label="SO" name="floater_map_southwest" text="SO">
+ SO
+ </text>
+ <text label="NO" name="floater_map_northwest" text="NO">
+ NO
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/sidepanel_appearance.xml b/indra/newview/skins/default/xui/fr/sidepanel_appearance.xml
new file mode 100644
index 0000000000..456e1dcb9d
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/sidepanel_appearance.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Apparence" name="appearance panel">
+ <string name="No Outfit" value="Aucune tenue"/>
+ <panel name="panel_currentlook">
+ <button label="Éditer" name="editappearance_btn"/>
+ <text name="currentlook_title">
+ Tenue actuelle :
+ </text>
+ <text name="currentlook_name">
+ Ma tenue
+ </text>
+ </panel>
+ <filter_editor label="Filtre" name="Filter"/>
+ <button label="Porter" name="wear_btn"/>
+ <button label="Nouvelle tenue" name="newlook_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/sidepanel_inventory.xml b/indra/newview/skins/default/xui/fr/sidepanel_inventory.xml
new file mode 100644
index 0000000000..b310574c4c
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/sidepanel_inventory.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Choses" name="objects panel">
+ <panel label="" name="sidepanel__inventory_panel">
+ <panel name="button_panel">
+ <button label="Infos" name="info_btn"/>
+ <button label="Porter" name="wear_btn"/>
+ <button label="Jouer" name="play_btn"/>
+ <button label="Téléporter" name="teleport_btn"/>
+ </panel>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml b/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml
new file mode 100644
index 0000000000..b1df70148b
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="item properties" title="Propriétés des objets de l&apos;inventaire">
+ <panel.string name="unknown">
+ (inconnu)
+ </panel.string>
+ <panel.string name="public">
+ (public)
+ </panel.string>
+ <panel.string name="you_can">
+ Vous pouvez :
+ </panel.string>
+ <panel.string name="owner_can">
+ Le propriétaire peut :
+ </panel.string>
+ <panel.string name="acquiredDate">
+ [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+ </panel.string>
+ <panel label="">
+ <text name="LabelItemNameTitle">
+ Nom :
+ </text>
+ <text name="LabelItemDescTitle">
+ Description :
+ </text>
+ <text name="LabelCreatorTitle">
+ Créateur :
+ </text>
+ <text name="LabelCreatorName">
+ Nicole Linden
+ </text>
+ <button label="Profil..." name="BtnCreator"/>
+ <text name="LabelOwnerTitle">
+ Propriétaire :
+ </text>
+ <text name="LabelOwnerName">
+ Thrax Linden
+ </text>
+ <button label="Profil..." name="BtnOwner"/>
+ <text name="LabelAcquiredTitle">
+ Acquis :
+ </text>
+ <text name="LabelAcquiredDate">
+ Wed May 24 12:50:46 2006
+ </text>
+ <text name="OwnerLabel">
+ Vous :
+ </text>
+ <check_box label="Éditer" name="CheckOwnerModify"/>
+ <check_box label="Copier" name="CheckOwnerCopy"/>
+ <check_box label="Revendre" name="CheckOwnerTransfer"/>
+ <text name="AnyoneLabel">
+ N&apos;importe qui :
+ </text>
+ <check_box label="Copier" name="CheckEveryoneCopy"/>
+ <text name="GroupLabel">
+ Groupe :
+ </text>
+ <check_box label="Partager" name="CheckShareWithGroup"/>
+ <text name="NextOwnerLabel">
+ Le prochain propriétaire :
+ </text>
+ <check_box label="Éditer" name="CheckNextOwnerModify"/>
+ <check_box label="Copier" name="CheckNextOwnerCopy"/>
+ <check_box label="Revendre" name="CheckNextOwnerTransfer"/>
+ <check_box label="À vendre" name="CheckPurchase"/>
+ <combo_box name="combobox sale copy">
+ <combo_box.item label="Copier" name="Copy"/>
+ <combo_box.item label="Original" name="Original"/>
+ </combo_box>
+ <spinner label="Prix :" name="Edit Cost"/>
+ <text name="CurrencySymbol">
+ L$
+ </text>
+ </panel>
+ <panel name="button_panel">
+ <button label="Éditer" name="edit_btn"/>
+ <button label="Annuler" name="cancel_btn"/>
+ <button label="Enregistrer" name="save_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/sidepanel_task_info.xml b/indra/newview/skins/default/xui/fr/sidepanel_task_info.xml
new file mode 100644
index 0000000000..de7751c4ff
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/sidepanel_task_info.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="object properties" title="Propriétés de l&apos;objet">
+ <panel.string name="text deed continued">
+ Céder
+ </panel.string>
+ <panel.string name="text deed">
+ Céder
+ </panel.string>
+ <panel.string name="text modify info 1">
+ Vous pouvez modifier cet objet
+ </panel.string>
+ <panel.string name="text modify info 2">
+ Vous pouvez modifier ces objets
+ </panel.string>
+ <panel.string name="text modify info 3">
+ Vous ne pouvez pas modifier cet objet
+ </panel.string>
+ <panel.string name="text modify info 4">
+ Vous ne pouvez pas modifier ces objets
+ </panel.string>
+ <panel.string name="text modify warning">
+ Cet objet comprend des parties reliées
+ </panel.string>
+ <panel.string name="Cost Default">
+ Prix : L$
+ </panel.string>
+ <panel.string name="Cost Total">
+ Prix total : L$
+ </panel.string>
+ <panel.string name="Cost Per Unit">
+ Prix par : L$
+ </panel.string>
+ <panel.string name="Cost Mixed">
+ Prix mixte
+ </panel.string>
+ <panel.string name="Sale Mixed">
+ Vente mixte
+ </panel.string>
+ <panel label="">
+ <text name="Name:">
+ Nom :
+ </text>
+ <text name="Description:">
+ Description :
+ </text>
+ <text name="Creator:">
+ Créateur :
+ </text>
+ <text name="Creator Name">
+ Esbee Linden
+ </text>
+ <text name="Owner:">
+ Propriétaire :
+ </text>
+ <text name="Owner Name">
+ Erica Linden
+ </text>
+ <text name="Group:">
+ Groupe :
+ </text>
+ <button name="button set group" tool_tip="Choisissez un groupe pour partager les permissions de cet objet"/>
+ <name_box initial_value="Chargement..." name="Group Name Proxy"/>
+ <button label="Céder" label_selected="Céder" name="button deed" tool_tip="En cédant un objet, vous donnez aussi les permissions au prochain propriétaire. Seul un officier peut céder les objets d&apos;un groupe."/>
+ <check_box label="Partager" name="checkbox share with group" tool_tip="Autorisez tous les membres du groupe choisi à utiliser et à partager vos droits pour cet objet. Pour activer les restrictions de rôles, vous devez d&apos;abord cliquer sur Transférer."/>
+ <text name="label click action">
+ Cliquer pour :
+ </text>
+ <combo_box name="clickaction">
+ <combo_box.item label="Toucher (défaut)" name="Touch/grab(default)"/>
+ <combo_box.item label="S&apos;asseoir sur l&apos;objet" name="Sitonobject"/>
+ <combo_box.item label="Acheter l&apos;objet" name="Buyobject"/>
+ <combo_box.item label="Payer l&apos;objet" name="Payobject"/>
+ <combo_box.item label="Ouvrir" name="Open"/>
+ </combo_box>
+ <check_box label="À vendre :" name="checkbox for sale"/>
+ <combo_box name="sale type">
+ <combo_box.item label="Copier" name="Copy"/>
+ <combo_box.item label="Contenus" name="Contents"/>
+ <combo_box.item label="Original" name="Original"/>
+ </combo_box>
+ <spinner label="Prix : L$" name="Edit Cost"/>
+ <check_box label="Afficher dans les résultats de recherche" name="search_check" tool_tip="Permettre aux autres résidents de voir cet objet dans les résultats de recherche"/>
+ <panel name="perms_build">
+ <text name="perm_modify">
+ Vous pouvez modifier cet objet
+ </text>
+ <text name="Anyone can:">
+ N&apos;importe qui :
+ </text>
+ <check_box label="Bouger" name="checkbox allow everyone move"/>
+ <check_box label="Copier" name="checkbox allow everyone copy"/>
+ <text name="Next owner can:">
+ Le prochain propriétaire :
+ </text>
+ <check_box label="Modifier" name="checkbox next owner can modify"/>
+ <check_box label="Copier" name="checkbox next owner can copy"/>
+ <check_box label="Transférer" name="checkbox next owner can transfer" tool_tip="Le prochain propriétaire peut donner ou revendre cet objet"/>
+ <text name="B:">
+ B :
+ </text>
+ <text name="O:">
+ O :
+ </text>
+ <text name="G:">
+ G :
+ </text>
+ <text name="E:">
+ E :
+ </text>
+ <text name="N:">
+ N :
+ </text>
+ <text name="F:">
+ F :
+ </text>
+ </panel>
+ </panel>
+ <panel name="button_panel">
+ <button label="Éditer" name="edit_btn"/>
+ <button label="Ouvrir" name="open_btn"/>
+ <button label="Payer" name="pay_btn"/>
+ <button label="Acheter" name="buy_btn"/>
+ <button label="Annuler" name="cancel_btn"/>
+ <button label="Enregistrer" name="save_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml
index 067c34294d..b45a016822 100644
--- a/indra/newview/skins/default/xui/fr/strings.xml
+++ b/indra/newview/skins/default/xui/fr/strings.xml
@@ -1,12 +1,36 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- This file contains strings that used to be hardcoded in the source.
It is only for those strings which do not belong in a floater.
- For example, the strings used in avatar chat bubbles, and strings
+ For example, the strings used in avatar chat bubbles, and strings
that are returned from one component and may appear in many places-->
<strings>
+ <string name="SECOND_LIFE">
+ Second Life
+ </string>
+ <string name="APP_NAME">
+ Second Life
+ </string>
+ <string name="SECOND_LIFE_GRID">
+ Grille de Second Life
+ </string>
+ <string name="SUPPORT_SITE">
+ Portail Assistance Second Life
+ </string>
+ <string name="StartupDetectingHardware">
+ Détection du matériel...
+ </string>
+ <string name="StartupLoading">
+ Chargement
+ </string>
+ <string name="Fullbright">
+ Fullbright (Legacy)
+ </string>
<string name="LoginInProgress">
La connexion à [APP_NAME] apparaît peut-être comme étant gelée. Veuillez patienter.
</string>
+ <string name="LoginInProgressNoFrozen">
+ Connexion...
+ </string>
<string name="LoginAuthenticating">
Authentification en cours
</string>
@@ -55,8 +79,14 @@
<string name="LoginDownloadingClothing">
Habits en cours de téléchargement...
</string>
+ <string name="Quit">
+ Quitter
+ </string>
+ <string name="create_account_url">
+ http://join.secondlife.com/index.php?lang=fr-FR
+ </string>
<string name="AgentLostConnection">
- Il y a peut-être des problèmes techniques dans cette region. Veuillez vérifier votre connexion Internet.
+ Il y a peut-être des problèmes techniques dans cette région. Veuillez vérifier votre connexion Internet.
</string>
<string name="TooltipPerson">
Personne
@@ -73,39 +103,9 @@
<string name="TooltipIsGroup">
(Groupe)
</string>
- <string name="TooltipFlagScript">
- Script
- </string>
- <string name="TooltipFlagPhysics">
- Propriétés physique
- </string>
- <string name="TooltipFlagTouch">
- Toucher
- </string>
- <string name="TooltipFlagL$">
- L$
- </string>
- <string name="TooltipFlagDropInventory">
- Laisser tomber l&apos;inventaire
- </string>
- <string name="TooltipFlagPhantom">
- Fantôme
- </string>
- <string name="TooltipFlagTemporary">
- Temporaire
- </string>
- <string name="TooltipFlagRightClickMenu">
- (cliquez-droit pour le menu)
- </string>
- <string name="TooltipFreeToCopy">
- Copie autorisée
- </string>
<string name="TooltipForSaleL$">
À vendre : [AMOUNT] L$
</string>
- <string name="TooltipForSaleMsg">
- À vendre : [MESSAGE]
- </string>
<string name="TooltipFlagGroupBuild">
Contruction de groupe
</string>
@@ -133,6 +133,76 @@
<string name="TooltipMustSingleDrop">
Impossible de faire glisser plus d&apos;un objet ici
</string>
+ <string name="TooltipHttpUrl">
+ Cliquez pour afficher cette page web
+ </string>
+ <string name="TooltipSLURL">
+ Cliquez pour en savoir plus sur cet endroit
+ </string>
+ <string name="TooltipAgentUrl">
+ Cliquez pour afficher le profil de ce résident
+ </string>
+ <string name="TooltipGroupUrl">
+ Cliquez pour afficher la description de ce groupe
+ </string>
+ <string name="TooltipEventUrl">
+ Cliquez pour afficher la description de cet événement
+ </string>
+ <string name="TooltipClassifiedUrl">
+ Cliquez pour afficher cette petite annonce
+ </string>
+ <string name="TooltipParcelUrl">
+ Cliquez pour afficher la description de cette parcelle
+ </string>
+ <string name="TooltipTeleportUrl">
+ Cliquez pour vous téléporter à cet endroit
+ </string>
+ <string name="TooltipObjectIMUrl">
+ Cliquez pour afficher la description de cet objet
+ </string>
+ <string name="TooltipMapUrl">
+ Cliquez pour voir cet emplacement sur la carte
+ </string>
+ <string name="TooltipSLAPP">
+ Cliquez pour exécuter la commande secondlife:// command
+ </string>
+ <string name="CurrentURL" value=" URL actuelle : [CurrentURL]"/>
+ <string name="SLurlLabelTeleport">
+ Me téléporter vers
+ </string>
+ <string name="SLurlLabelShowOnMap">
+ Afficher la carte pour
+ </string>
+ <string name="BUTTON_CLOSE_DARWIN">
+ Fermer (&#8984;W)
+ </string>
+ <string name="BUTTON_CLOSE_WIN">
+ Fermer (Ctrl+W)
+ </string>
+ <string name="BUTTON_RESTORE">
+ Restaurer
+ </string>
+ <string name="BUTTON_MINIMIZE">
+ Minimiser
+ </string>
+ <string name="BUTTON_TEAR_OFF">
+ Réduire
+ </string>
+ <string name="BUTTON_DOCK">
+ Attacher
+ </string>
+ <string name="BUTTON_UNDOCK">
+ Détacher
+ </string>
+ <string name="BUTTON_HELP">
+ Afficher l&apos;aide
+ </string>
+ <string name="Searching">
+ Recherche...
+ </string>
+ <string name="NoneFound">
+ Aucun résultat.
+ </string>
<string name="RetrievingData">
En cours d&apos;extraction...
</string>
@@ -140,7 +210,7 @@
Notes de version
</string>
<string name="LoadingData">
- Chargement..
+ Chargement...
</string>
<string name="AvatarNameNobody">
(personne)
@@ -148,6 +218,9 @@
<string name="AvatarNameWaiting">
(en attente)
</string>
+ <string name="AvatarNameMultiple">
+ (multiple)
+ </string>
<string name="AvatarNameHippos">
(hippos)
</string>
@@ -187,7 +260,79 @@
<string name="AssetErrorUnknownStatus">
Statut inconnu
</string>
- <string name="AvatarEditingApparance">
+ <string name="texture">
+ texture
+ </string>
+ <string name="sound">
+ son
+ </string>
+ <string name="calling card">
+ carte de visite
+ </string>
+ <string name="landmark">
+ repère
+ </string>
+ <string name="legacy script">
+ script (ancienne version)
+ </string>
+ <string name="clothing">
+ habits
+ </string>
+ <string name="object">
+ objet
+ </string>
+ <string name="note card">
+ note
+ </string>
+ <string name="folder">
+ dossier
+ </string>
+ <string name="root">
+ racine
+ </string>
+ <string name="lsl2 script">
+ script LSL2
+ </string>
+ <string name="lsl bytecode">
+ bytecode LSL
+ </string>
+ <string name="tga texture">
+ texture tga
+ </string>
+ <string name="body part">
+ partie du corps
+ </string>
+ <string name="snapshot">
+ photo
+ </string>
+ <string name="lost and found">
+ Objets trouvés
+ </string>
+ <string name="targa image">
+ image targa
+ </string>
+ <string name="trash">
+ Poubelle
+ </string>
+ <string name="jpeg image">
+ image jpeg
+ </string>
+ <string name="animation">
+ animation
+ </string>
+ <string name="gesture">
+ geste
+ </string>
+ <string name="simstate">
+ simstate
+ </string>
+ <string name="favorite">
+ favori
+ </string>
+ <string name="symbolic link">
+ lien
+ </string>
+ <string name="AvatarEditingAppearance">
(Apparence en cours de modification)
</string>
<string name="AvatarAway">
@@ -197,7 +342,7 @@
Occupé
</string>
<string name="AvatarMuted">
- Ignoré
+ Bloqué(e)
</string>
<string name="anim_express_afraid">
Effrayé
@@ -412,12 +557,75 @@
<string name="worldmap_offline">
Hors ligne
</string>
+ <string name="worldmap_results_none_found">
+ Aucun résultat.
+ </string>
+ <string name="Ok">
+ OK
+ </string>
+ <string name="Premature end of file">
+ Fichier incomplet
+ </string>
+ <string name="ST_NO_JOINT">
+ Impossible de trouver ROOT ou JOINT.
+ </string>
<string name="whisper">
chuchote :
</string>
<string name="shout">
crie :
</string>
+ <string name="ringing">
+ Connexion au chat vocal du Monde en cours…
+ </string>
+ <string name="connected">
+ Connecté(e)
+ </string>
+ <string name="unavailable">
+ Voix non disponible à l&apos;endroit où vous êtes
+ </string>
+ <string name="hang_up">
+ Déconnecté du chat vocal
+ </string>
+ <string name="ScriptQuestionCautionChatGranted">
+ &apos;[OBJECTNAME]&apos;, un objet appartenant à [OWNERNAME], situé dans [REGIONNAME] à [REGIONPOS], a reçu le droit de : [PERMISSIONS].
+ </string>
+ <string name="ScriptQuestionCautionChatDenied">
+ &apos;[OBJECTNAME]&apos;, un objet appartenant à [OWNERNAME], situé dans [REGIONNAME] à [REGIONPOS], n&apos;a pas reçu le droit de : [PERMISSIONS].
+ </string>
+ <string name="ScriptTakeMoney">
+ Débiter vos Linden dollars (L$)
+ </string>
+ <string name="ActOnControlInputs">
+ Utiliser vos touches de commandes
+ </string>
+ <string name="RemapControlInputs">
+ Reconfigurer vos touches de commandes
+ </string>
+ <string name="AnimateYourAvatar">
+ Animer votre avatar
+ </string>
+ <string name="AttachToYourAvatar">
+ Attacher à votre avatar
+ </string>
+ <string name="ReleaseOwnership">
+ Passer l&apos;objet dans le domaine public (sans propriétaire)
+ </string>
+ <string name="LinkAndDelink">
+ Lier et délier d&apos;autres objets
+ </string>
+ <string name="AddAndRemoveJoints">
+ Créer et supprimer des liens avec d&apos;autres objets
+ </string>
+ <string name="ChangePermissions">
+ Modifier ses droits
+ </string>
+ <string name="TrackYourCamera">
+ Suivre votre caméra
+ </string>
+ <string name="ControlYourCamera">
+ Contrôler votre caméra
+ </string>
<string name="SIM_ACCESS_PG">
PG
</string>
@@ -436,12 +644,6 @@
<string name="land_type_unknown">
(inconnu)
</string>
- <string name="covenant_never_modified">
- Dernière modification : (jamais)
- </string>
- <string name="covenant_modified">
- Dernière modification :
- </string>
<string name="all_files">
Tous fichiers
</string>
@@ -487,4 +689,2432 @@
<string name="choose_the_directory">
Choisir le répertoire
</string>
+ <string name="AvatarSetNotAway">
+ Présent
+ </string>
+ <string name="AvatarSetAway">
+ Absent
+ </string>
+ <string name="AvatarSetNotBusy">
+ Pas occupé
+ </string>
+ <string name="AvatarSetBusy">
+ Occupé
+ </string>
+ <string name="shape">
+ Silhouette
+ </string>
+ <string name="skin">
+ Peau
+ </string>
+ <string name="hair">
+ Cheveux
+ </string>
+ <string name="eyes">
+ Yeux
+ </string>
+ <string name="shirt">
+ Chemise
+ </string>
+ <string name="pants">
+ Pantalon
+ </string>
+ <string name="shoes">
+ Chaussures
+ </string>
+ <string name="socks">
+ Chaussettes
+ </string>
+ <string name="jacket">
+ Veste
+ </string>
+ <string name="gloves">
+ Gants
+ </string>
+ <string name="undershirt">
+ Sous-vêtements (homme)
+ </string>
+ <string name="underpants">
+ Sous-vêtements (femme)
+ </string>
+ <string name="skirt">
+ Jupe
+ </string>
+ <string name="alpha">
+ Alpha
+ </string>
+ <string name="tattoo">
+ Tatouage
+ </string>
+ <string name="invalid">
+ non valide
+ </string>
+ <string name="next">
+ Suivant
+ </string>
+ <string name="ok">
+ OK
+ </string>
+ <string name="GroupNotifyGroupNotice">
+ Note au groupe
+ </string>
+ <string name="GroupNotifyGroupNotices">
+ Notices au groupe
+ </string>
+ <string name="GroupNotifySentBy">
+ Envoyée par
+ </string>
+ <string name="GroupNotifyAttached">
+ Pièce(s) jointe(s) :
+ </string>
+ <string name="GroupNotifyViewPastNotices">
+ Consultez les notices précédentes ou choisissez de ne plus recevoir ces messages ici.
+ </string>
+ <string name="GroupNotifyOpenAttachment">
+ Ouvrir la pièce jointe
+ </string>
+ <string name="GroupNotifySaveAttachment">
+ Enregistrer la pièce jointe
+ </string>
+ <string name="TeleportOffer">
+ Offre de téléportation
+ </string>
+ <string name="StartUpNotifications">
+ De nouvelles notifications sont arrivées en votre absence.
+ </string>
+ <string name="OverflowInfoChannelString">
+ Vous avez %d notification(s) supplémentaire(s)
+ </string>
+ <string name="BodyPartsRightArm">
+ Bras droit
+ </string>
+ <string name="BodyPartsHead">
+ Tête
+ </string>
+ <string name="BodyPartsLeftArm">
+ Bras gauche
+ </string>
+ <string name="BodyPartsLeftLeg">
+ Jambe gauche
+ </string>
+ <string name="BodyPartsTorso">
+ Torse
+ </string>
+ <string name="BodyPartsRightLeg">
+ Jambe droite
+ </string>
+ <string name="GraphicsQualityLow">
+ Faible
+ </string>
+ <string name="GraphicsQualityMid">
+ Moyen
+ </string>
+ <string name="GraphicsQualityHigh">
+ Élevé
+ </string>
+ <string name="LeaveMouselook">
+ Appuyez sur ESC pour quitter la vue subjective
+ </string>
+ <string name="InventoryNoMatchingItems">
+ Aucun objet correspondant dans l&apos;inventaire.
+ </string>
+ <string name="InventoryNoTexture">
+ Vous n&apos;avez pas de copie de cette texture dans votre inventaire
+ </string>
+ <string name="no_transfer" value=" (pas de transfert)"/>
+ <string name="no_modify" value=" (pas de modification)"/>
+ <string name="no_copy" value=" (pas de copie)"/>
+ <string name="worn" value=" (porté)"/>
+ <string name="link" value=" (lien)"/>
+ <string name="broken_link" value=" (broken_link)"/>
+ <string name="LoadingContents">
+ chargement des contenus en cours...
+ </string>
+ <string name="NoContents">
+ Aucun contenu
+ </string>
+ <string name="WornOnAttachmentPoint" value=" (porté sur [ATTACHMENT_POINT])"/>
+ <string name="PermYes">
+ Oui
+ </string>
+ <string name="PermNo">
+ Non
+ </string>
+ <string name="Chat" value=" Chat :"/>
+ <string name="Sound" value=" Son :"/>
+ <string name="Wait" value=" --- Attendre :"/>
+ <string name="AnimFlagStop" value=" Arrêter l&apos;animation :"/>
+ <string name="AnimFlagStart" value=" Démarrer l&apos;animation :"/>
+ <string name="Wave" value=" Faire signe"/>
+ <string name="HelloAvatar" value=" Bonjour, avatar !"/>
+ <string name="ViewAllGestures" value=" Tout afficher &gt;&gt;"/>
+ <string name="Animations" value=" Animations,"/>
+ <string name="Calling Cards" value=" Cartes de visite,"/>
+ <string name="Clothing" value=" Habits,"/>
+ <string name="Gestures" value=" Gestes,"/>
+ <string name="Landmarks" value=" Repères,"/>
+ <string name="Notecards" value=" Notes,"/>
+ <string name="Objects" value=" Objets,"/>
+ <string name="Scripts" value=" Scripts,"/>
+ <string name="Sounds" value=" Sons,"/>
+ <string name="Textures" value=" Textures,"/>
+ <string name="Snapshots" value=" Photos,"/>
+ <string name="No Filters" value="Non "/>
+ <string name="Since Logoff" value=" - Depuis la déconnexion"/>
+ <string name="InvFolder My Inventory">
+ Mon inventaire
+ </string>
+ <string name="InvFolder My Favorites">
+ Mes Favoris
+ </string>
+ <string name="InvFolder Library">
+ Bibliothèque
+ </string>
+ <string name="InvFolder Textures">
+ Textures
+ </string>
+ <string name="InvFolder Sounds">
+ Sons
+ </string>
+ <string name="InvFolder Calling Cards">
+ Cartes de visite
+ </string>
+ <string name="InvFolder Landmarks">
+ Repères
+ </string>
+ <string name="InvFolder Scripts">
+ Scripts
+ </string>
+ <string name="InvFolder Clothing">
+ Habits
+ </string>
+ <string name="InvFolder Objects">
+ Objets
+ </string>
+ <string name="InvFolder Notecards">
+ Notes
+ </string>
+ <string name="InvFolder New Folder">
+ Nouveau dossier
+ </string>
+ <string name="InvFolder Inventory">
+ Inventaire
+ </string>
+ <string name="InvFolder Uncompressed Images">
+ Images non compressées
+ </string>
+ <string name="InvFolder Body Parts">
+ Parties du corps
+ </string>
+ <string name="InvFolder Trash">
+ Poubelle
+ </string>
+ <string name="InvFolder Photo Album">
+ Albums photo
+ </string>
+ <string name="InvFolder Lost And Found">
+ Objets trouvés
+ </string>
+ <string name="InvFolder Uncompressed Sounds">
+ Sons non compressés
+ </string>
+ <string name="InvFolder Animations">
+ Animations
+ </string>
+ <string name="InvFolder Gestures">
+ Gestes
+ </string>
+ <string name="InvFolder favorite">
+ Favoris
+ </string>
+ <string name="InvFolder Current Outfit">
+ Tenue actuelle
+ </string>
+ <string name="InvFolder My Outfits">
+ Mes tenues
+ </string>
+ <string name="InvFolder Friends">
+ Amis
+ </string>
+ <string name="InvFolder All">
+ Tout
+ </string>
+ <string name="Buy">
+ Acheter
+ </string>
+ <string name="BuyforL$">
+ Acheter des L$
+ </string>
+ <string name="Stone">
+ Pierre
+ </string>
+ <string name="Metal">
+ Métal
+ </string>
+ <string name="Glass">
+ Verre
+ </string>
+ <string name="Wood">
+ Bois
+ </string>
+ <string name="Flesh">
+ Chair
+ </string>
+ <string name="Plastic">
+ Plastique
+ </string>
+ <string name="Rubber">
+ Caoutchouc
+ </string>
+ <string name="Light">
+ Léger
+ </string>
+ <string name="KBShift">
+ Maj-
+ </string>
+ <string name="KBCtrl">
+ Ctrl
+ </string>
+ <string name="Chest">
+ Poitrine
+ </string>
+ <string name="Skull">
+ Crâne
+ </string>
+ <string name="Left Shoulder">
+ Épaule gauche
+ </string>
+ <string name="Right Shoulder">
+ Épaule droite
+ </string>
+ <string name="Left Hand">
+ Main gauche
+ </string>
+ <string name="Right Hand">
+ Main droite
+ </string>
+ <string name="Left Foot">
+ Pied gauche
+ </string>
+ <string name="Right Foot">
+ Pied droit
+ </string>
+ <string name="Spine">
+ Colonne
+ </string>
+ <string name="Pelvis">
+ Bassin
+ </string>
+ <string name="Mouth">
+ Bouche
+ </string>
+ <string name="Chin">
+ Menton
+ </string>
+ <string name="Left Ear">
+ Oreille gauche
+ </string>
+ <string name="Right Ear">
+ Oreille droite
+ </string>
+ <string name="Left Eyeball">
+ Globe oculaire gauche
+ </string>
+ <string name="Right Eyeball">
+ Globe oculaire droit
+ </string>
+ <string name="Nose">
+ Nez
+ </string>
+ <string name="R Upper Arm">
+ Bras D
+ </string>
+ <string name="R Forearm">
+ Avant-bras D
+ </string>
+ <string name="L Upper Arm">
+ Bras G
+ </string>
+ <string name="L Forearm">
+ Avant-bras G
+ </string>
+ <string name="Right Hip">
+ Hanche droite
+ </string>
+ <string name="R Upper Leg">
+ Cuisse D
+ </string>
+ <string name="R Lower Leg">
+ Jambe D
+ </string>
+ <string name="Left Hip">
+ Hanche gauche
+ </string>
+ <string name="L Upper Leg">
+ Cuisse G
+ </string>
+ <string name="L Lower Leg">
+ Jambe G
+ </string>
+ <string name="Stomach">
+ Estomac
+ </string>
+ <string name="Left Pec">
+ Pectoral gauche
+ </string>
+ <string name="Right Pec">
+ Pectoral droit
+ </string>
+ <string name="YearsMonthsOld">
+ [AGEYEARS] [AGEMONTHS]
+ </string>
+ <string name="YearsOld">
+ [AGEYEARS]
+ </string>
+ <string name="MonthsOld">
+ [AGEMONTHS]
+ </string>
+ <string name="WeeksOld">
+ [AGEWEEKS]
+ </string>
+ <string name="DaysOld">
+ [AGEDAYS]
+ </string>
+ <string name="TodayOld">
+ Inscrit aujourd&apos;hui
+ </string>
+ <string name="AgeYearsA">
+ [COUNT] an
+ </string>
+ <string name="AgeYearsB">
+ [COUNT] ans
+ </string>
+ <string name="AgeYearsC">
+ [COUNT] ans
+ </string>
+ <string name="AgeMonthsA">
+ [COUNT] mois
+ </string>
+ <string name="AgeMonthsB">
+ [COUNT] mois
+ </string>
+ <string name="AgeMonthsC">
+ [COUNT] mois
+ </string>
+ <string name="AgeWeeksA">
+ [COUNT] semaine
+ </string>
+ <string name="AgeWeeksB">
+ [COUNT] semaines
+ </string>
+ <string name="AgeWeeksC">
+ [COUNT] semaines
+ </string>
+ <string name="AgeDaysA">
+ [COUNT] jour
+ </string>
+ <string name="AgeDaysB">
+ [COUNT] jours
+ </string>
+ <string name="AgeDaysC">
+ [COUNT] jours
+ </string>
+ <string name="GroupMembersA">
+ [COUNT] membre
+ </string>
+ <string name="GroupMembersB">
+ [COUNT] membres
+ </string>
+ <string name="GroupMembersC">
+ [COUNT] membres
+ </string>
+ <string name="AcctTypeResident">
+ Résident
+ </string>
+ <string name="AcctTypeTrial">
+ Essai
+ </string>
+ <string name="AcctTypeCharterMember">
+ Membre originaire
+ </string>
+ <string name="AcctTypeEmployee">
+ Employé(e) de Linden Lab
+ </string>
+ <string name="PaymentInfoUsed">
+ Infos de paiement utilisées
+ </string>
+ <string name="PaymentInfoOnFile">
+ Infos de paiement enregistrées
+ </string>
+ <string name="NoPaymentInfoOnFile">
+ Aucune info de paiement enregistrée
+ </string>
+ <string name="AgeVerified">
+ Personne dont l&apos;âge a été vérifié
+ </string>
+ <string name="NotAgeVerified">
+ Personne dont l&apos;âge n&apos;a pas été vérifié
+ </string>
+ <string name="Center 2">
+ Centrer 2
+ </string>
+ <string name="Top Right">
+ En haut à droite
+ </string>
+ <string name="Top">
+ En haut
+ </string>
+ <string name="Top Left">
+ En haut à gauche
+ </string>
+ <string name="Center">
+ Centrer
+ </string>
+ <string name="Bottom Left">
+ En bas à gauche
+ </string>
+ <string name="Bottom">
+ Bas
+ </string>
+ <string name="Bottom Right">
+ En bas à droite
+ </string>
+ <string name="CompileQueueDownloadedCompiling">
+ Téléchargé, compilation en cours
+ </string>
+ <string name="CompileQueueScriptNotFound">
+ Script introuvable sur le serveur.
+ </string>
+ <string name="CompileQueueProblemDownloading">
+ Problème lors du téléchargement
+ </string>
+ <string name="CompileQueueInsufficientPermDownload">
+ Permissions insuffisantes pour télécharger un script.
+ </string>
+ <string name="CompileQueueInsufficientPermFor">
+ Permissions insuffisantes pour
+ </string>
+ <string name="CompileQueueUnknownFailure">
+ Échec du téléchargement, erreur inconnue
+ </string>
+ <string name="CompileQueueTitle">
+ Recompilation - progrès
+ </string>
+ <string name="CompileQueueStart">
+ recompiler
+ </string>
+ <string name="ResetQueueTitle">
+ Réinitialiser les progrès
+ </string>
+ <string name="ResetQueueStart">
+ réinitialiser
+ </string>
+ <string name="RunQueueTitle">
+ Lancer
+ </string>
+ <string name="RunQueueStart">
+ lancer
+ </string>
+ <string name="NotRunQueueTitle">
+ Arrêter
+ </string>
+ <string name="NotRunQueueStart">
+ arrêter
+ </string>
+ <string name="CompileSuccessful">
+ Compilation réussie !
+ </string>
+ <string name="CompileSuccessfulSaving">
+ Compilation réussie, enregistrement en cours...
+ </string>
+ <string name="SaveComplete">
+ Enregistrement terminé.
+ </string>
+ <string name="ObjectOutOfRange">
+ Script (objet hors de portée)
+ </string>
+ <string name="GodToolsObjectOwnedBy">
+ Objet [OBJECT] appartenant à [OWNER]
+ </string>
+ <string name="GroupsNone">
+ aucun
+ </string>
+ <string name="Group" value=" (groupe)"/>
+ <string name="Unknown">
+ (Inconnu)
+ </string>
+ <string name="SummaryForTheWeek" value="Récapitulatif de la semaine, début le "/>
+ <string name="NextStipendDay" value="Prochaine prime le "/>
+ <string name="GroupIndividualShare" value=" Groupe Part individuelle"/>
+ <string name="Balance">
+ Solde
+ </string>
+ <string name="Credits">
+ Remerciements
+ </string>
+ <string name="Debits">
+ Débits
+ </string>
+ <string name="Total">
+ Total
+ </string>
+ <string name="NoGroupDataFound">
+ Aucune donnée trouvée pour le groupe
+ </string>
+ <string name="IMParentEstate">
+ domaine parent
+ </string>
+ <string name="IMMainland">
+ continent
+ </string>
+ <string name="IMTeen">
+ teen
+ </string>
+ <string name="RegionInfoError">
+ erreur
+ </string>
+ <string name="RegionInfoAllEstatesOwnedBy">
+ tous les domaines appartenant à [OWNER]
+ </string>
+ <string name="RegionInfoAllEstatesYouOwn">
+ tous les domaines vous appartenant
+ </string>
+ <string name="RegionInfoAllEstatesYouManage">
+ tous les domaines que vous gérez pour [OWNER]
+ </string>
+ <string name="RegionInfoAllowedResidents">
+ Résidents autorisés : ([ALLOWEDAGENTS], max. [MAXACCESS])
+ </string>
+ <string name="RegionInfoAllowedGroups">
+ Groupes autorisés : ([ALLOWEDGROUPS], max. [MAXACCESS])
+ </string>
+ <string name="CursorPos">
+ Ligne [LINE], colonne [COLUMN]
+ </string>
+ <string name="PanelDirCountFound">
+ [COUNT] trouvé(s)
+ </string>
+ <string name="PanelDirTimeStr">
+ [hour12,datetime,slt]:[min,datetime,slt] [ampm,datetime,slt]
+ </string>
+ <string name="PanelDirEventsDateText">
+ [mthnum,datetime,slt]/[day,datetime,slt]
+ </string>
+ <string name="PanelContentsNewScript">
+ Nouveau script
+ </string>
+ <string name="MuteByName">
+ (par nom)
+ </string>
+ <string name="MuteAgent">
+ (résident)
+ </string>
+ <string name="MuteObject">
+ (objet)
+ </string>
+ <string name="MuteGroup">
+ (groupe)
+ </string>
+ <string name="RegionNoCovenant">
+ Il n&apos;y a aucun règlement pour ce domaine.
+ </string>
+ <string name="RegionNoCovenantOtherOwner">
+ Il n&apos;y a aucun règlement pour ce domaine. Le terrain sur ce domaine est vendu par le propriétaire, non par Linden Lab. Pour en savoir plus, veuillez contacter le propriétaire.
+ </string>
+ <string name="covenant_last_modified">
+ Dernière modification :
+ </string>
+ <string name="none_text" value=" (aucun)"/>
+ <string name="never_text" value=" (jamais)"/>
+ <string name="GroupOwned">
+ Propriété du groupe
+ </string>
+ <string name="Public">
+ Public
+ </string>
+ <string name="ClassifiedClicksTxt">
+ Clics : [TELEPORT] téléportation, [MAP] carte, [PROFILE] profil
+ </string>
+ <string name="ClassifiedUpdateAfterPublish">
+ (mise à jour après la publication)
+ </string>
+ <string name="MultiPreviewTitle">
+ Prévisualiser
+ </string>
+ <string name="MultiPropertiesTitle">
+ Propriétés
+ </string>
+ <string name="InvOfferAnObjectNamed">
+ Un objet appelé
+ </string>
+ <string name="InvOfferOwnedByGroup">
+ possédé par le groupe
+ </string>
+ <string name="InvOfferOwnedByUnknownGroup">
+ possédé par un groupe inconnu
+ </string>
+ <string name="InvOfferOwnedBy">
+ possédé par
+ </string>
+ <string name="InvOfferOwnedByUnknownUser">
+ possédé par un résident inconnu
+ </string>
+ <string name="InvOfferGaveYou">
+ vous a donné
+ </string>
+ <string name="InvOfferYouDecline">
+ Vous avez refusé
+ </string>
+ <string name="InvOfferFrom">
+ de la part de
+ </string>
+ <string name="GroupMoneyTotal">
+ Total
+ </string>
+ <string name="GroupMoneyBought">
+ acheté
+ </string>
+ <string name="GroupMoneyPaidYou">
+ vous a payé
+ </string>
+ <string name="GroupMoneyPaidInto">
+ payé
+ </string>
+ <string name="GroupMoneyBoughtPassTo">
+ a acheté un pass à
+ </string>
+ <string name="GroupMoneyPaidFeeForEvent">
+ a payé des frais pour un événement
+ </string>
+ <string name="GroupMoneyPaidPrizeForEvent">
+ a payé un prix pour un événement
+ </string>
+ <string name="GroupMoneyBalance">
+ Solde
+ </string>
+ <string name="GroupMoneyCredits">
+ Remerciements
+ </string>
+ <string name="GroupMoneyDebits">
+ Débits
+ </string>
+ <string name="ViewerObjectContents">
+ Contenus
+ </string>
+ <string name="AcquiredItems">
+ Objets acquis
+ </string>
+ <string name="Cancel">
+ Annuler
+ </string>
+ <string name="UploadingCosts">
+ Charger %s coûte
+ </string>
+ <string name="UnknownFileExtension">
+ Extension de fichier inconnue .%s
+.wav, .tga, .bmp, .jpg, .jpeg, ou .bvh acceptés
+ </string>
+ <string name="AddLandmarkNavBarMenu">
+ Ajouter un repère...
+ </string>
+ <string name="EditLandmarkNavBarMenu">
+ Modifier le repère...
+ </string>
+ <string name="accel-mac-control">
+ &#8963;
+ </string>
+ <string name="accel-mac-command">
+ &#8984;
+ </string>
+ <string name="accel-mac-option">
+ &#8997;
+ </string>
+ <string name="accel-mac-shift">
+ &#8679;
+ </string>
+ <string name="accel-win-control">
+ Ctrl+
+ </string>
+ <string name="accel-win-alt">
+ Alt+
+ </string>
+ <string name="accel-win-shift">
+ Maj+
+ </string>
+ <string name="FileSaved">
+ Fichier enregistré
+ </string>
+ <string name="Receiving">
+ Réception
+ </string>
+ <string name="AM">
+ Matin
+ </string>
+ <string name="PM">
+ Après-midi
+ </string>
+ <string name="PST">
+ PST
+ </string>
+ <string name="PDT">
+ PDT
+ </string>
+ <string name="Forward">
+ Vers l&apos;avant
+ </string>
+ <string name="Left">
+ Gauche
+ </string>
+ <string name="Right">
+ Droite
+ </string>
+ <string name="Back">
+ Arrière
+ </string>
+ <string name="North">
+ Nord
+ </string>
+ <string name="South">
+ Sud
+ </string>
+ <string name="West">
+ Ouest
+ </string>
+ <string name="East">
+ Est
+ </string>
+ <string name="Up">
+ Haut
+ </string>
+ <string name="Down">
+ Bas
+ </string>
+ <string name="Any Category">
+ Toutes catégories
+ </string>
+ <string name="Shopping">
+ Shopping
+ </string>
+ <string name="Land Rental">
+ Terrains à louer
+ </string>
+ <string name="Property Rental">
+ Propriétés à louer
+ </string>
+ <string name="Special Attraction">
+ Divertissements
+ </string>
+ <string name="New Products">
+ Nouveaux produits
+ </string>
+ <string name="Employment">
+ Emplois
+ </string>
+ <string name="Wanted">
+ Offres
+ </string>
+ <string name="Service">
+ Services
+ </string>
+ <string name="Personal">
+ Divers
+ </string>
+ <string name="None">
+ Aucun
+ </string>
+ <string name="Linden Location">
+ Appartenant aux Lindens
+ </string>
+ <string name="Adult">
+ Adult
+ </string>
+ <string name="Arts&amp;Culture">
+ Arts et culture
+ </string>
+ <string name="Business">
+ Business
+ </string>
+ <string name="Educational">
+ Éducation
+ </string>
+ <string name="Gaming">
+ Jeux
+ </string>
+ <string name="Hangout">
+ Favoris
+ </string>
+ <string name="Newcomer Friendly">
+ Accueil pour les nouveaux
+ </string>
+ <string name="Parks&amp;Nature">
+ Parcs et nature
+ </string>
+ <string name="Residential">
+ Résidentiel
+ </string>
+ <string name="Stage">
+ Phase
+ </string>
+ <string name="Other">
+ Autre
+ </string>
+ <string name="Any">
+ Aucun
+ </string>
+ <string name="You">
+ Vous
+ </string>
+ <string name=":">
+ :
+ </string>
+ <string name=",">
+ ,
+ </string>
+ <string name="...">
+ ...
+ </string>
+ <string name="***">
+ ***
+ </string>
+ <string name="(">
+ (
+ </string>
+ <string name=")">
+ )
+ </string>
+ <string name=".">
+ .
+ </string>
+ <string name="&apos;">
+ &apos;
+ </string>
+ <string name="---">
+ ---
+ </string>
+ <string name="Multiple Media">
+ Médias multiples
+ </string>
+ <string name="Play Media">
+ Lire/pauser le média
+ </string>
+ <string name="MBCmdLineError">
+ Une erreur est survenue lors de la lecture de la ligne de commande.
+Merci de consulter : http://wiki.secondlife.com/wiki/Client_parameters
+Erreur :
+ </string>
+ <string name="MBCmdLineUsg">
+ [APP_NAME] - Utilisation de la ligne de commande :
+ </string>
+ <string name="MBUnableToAccessFile">
+ [APP_NAME] ne peut accéder à un fichier requis.
+
+Cela vient du fait que quelqu&apos;un a ouvert plusieurs copies ou que votre système pense qu&apos;un fichier est ouvert.
+Si ce message persiste, veuillez redémarrer votre ordinateur.
+Si le problème persiste, vous devrez peut-être complètement désinstaller puis réinstaller [APP_NAME].
+ </string>
+ <string name="MBFatalError">
+ Erreur fatale
+ </string>
+ <string name="MBRequiresAltiVec">
+ [APP_NAME] nécessite un microprocesseur AltiVec (version G4 ou antérieure).
+ </string>
+ <string name="MBAlreadyRunning">
+ [APP_NAME] est déjà en cours d&apos;exécution.
+Vérifiez si une version minimisée du programme apparaît dans votre barre de tâches.
+Si ce message persiste, redémarrez votre ordinateur.
+ </string>
+ <string name="MBFrozenCrashed">
+ [APP_NAME] semble avoir crashé lors de l&apos;utilisation précédente.
+Voulez-vous envoyer un rapport de crash ?
+ </string>
+ <string name="MBAlert">
+ Alerte
+ </string>
+ <string name="MBNoDirectX">
+ [APP_NAME] ne peut détecter DirectX 9.0b ou une version supérieure.
+[APP_NAME] utilise DirectX pour détecter les matériels et/ou les pilotes qui ne sont pas à jour et peuvent causer des problèmes de stabilité, de performance ou des plantages. Bien que vous puissiez utiliser [APP_NAME] sans DirectX, nous vous recommandons de l&apos;utiliser avec DirectX 9.0b.
+
+Voulez-vous continuer ?
+ </string>
+ <string name="MBWarning">
+ Avertissement
+ </string>
+ <string name="MBNoAutoUpdate">
+ Les mises à jour automatiques n&apos;existent pas encore pour Linux.
+Veuillez télécharger la dernière version sur www.secondlife.com.
+ </string>
+ <string name="MBRegClassFailed">
+ RegisterClass a échoué
+ </string>
+ <string name="MBError">
+ Erreur
+ </string>
+ <string name="MBFullScreenErr">
+ Impossible d&apos;ouvrir le mode plein écran à [WIDTH] x [HEIGHT].
+Utilisation du mode fenêtré.
+ </string>
+ <string name="MBDestroyWinFailed">
+ Erreur de fermeture lors de la destruction de la fenêtre (DestroyWindow() a échoué)
+ </string>
+ <string name="MBShutdownErr">
+ Erreur de fermeture
+ </string>
+ <string name="MBDevContextErr">
+ Impossible de créer le contexte GL
+ </string>
+ <string name="MBPixelFmtErr">
+ Impossible de trouver le format pixel approprié
+ </string>
+ <string name="MBPixelFmtDescErr">
+ Impossible de trouver la description du format pixel
+ </string>
+ <string name="MBTrueColorWindow">
+ [APP_NAME] nécessite True Color (32 bits) pour s&apos;exécuter.
+Accédez aux paramètres d&apos;affichage de votre ordinateur et réglez le mode couleur sur 32 bits.
+ </string>
+ <string name="MBAlpha">
+ [APP_NAME] ne peut pas s&apos;exécuter, car il n&apos;y pas de canal alpha 8 bits accessible. En général, ceci vient de problèmes avec le pilote de la carte vidéo.
+Assurez-vous d&apos;avoir installé le pilote de carte vidéo le plus récent possible.
+Assurez-vous aussi que votre écran est réglé sur True Color (32 bits) sous Panneau de configuration &gt; Affichage &gt; Paramètres.
+Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].
+ </string>
+ <string name="MBPixelFmtSetErr">
+ Impossible de trouver le format pixel approprié
+ </string>
+ <string name="MBGLContextErr">
+ Impossible de créer le contexte de rendu GL
+ </string>
+ <string name="MBGLContextActErr">
+ Impossible d&apos;activer le contexte de rendu GL
+ </string>
+ <string name="MBVideoDrvErr">
+ [APP_NAME] ne peut pas s&apos;exécuter car les pilotes de votre carte vidéo n&apos;ont pas été installés correctement, ne sont pas à jour, ou sont pour du matériel non pris en charge. Assurez-vous d&apos;avoir des pilotes de cartes vidéos récents, et même si vous avez les plus récents, réinstallez-les.
+
+Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].
+ </string>
+ <string name="5 O&apos;Clock Shadow">
+ Peu
+ </string>
+ <string name="All White">
+ Tout blancs
+ </string>
+ <string name="Anime Eyes">
+ Grand yeux
+ </string>
+ <string name="Arced">
+ Arqués
+ </string>
+ <string name="Arm Length">
+ Longueur des bras
+ </string>
+ <string name="Attached">
+ Attachés
+ </string>
+ <string name="Attached Earlobes">
+ Lobes
+ </string>
+ <string name="Back Fringe">
+ Mèches de derrière
+ </string>
+ <string name="Baggy">
+ Cernés
+ </string>
+ <string name="Bangs">
+ Frange
+ </string>
+ <string name="Beady Eyes">
+ Yeux perçants
+ </string>
+ <string name="Belly Size">
+ Taille du ventre
+ </string>
+ <string name="Big">
+ Plus
+ </string>
+ <string name="Big Butt">
+ Grosses fesses
+ </string>
+ <string name="Big Hair Back">
+ Volume : Derrière
+ </string>
+ <string name="Big Hair Front">
+ Volume : Devant
+ </string>
+ <string name="Big Hair Top">
+ Volume : Haut
+ </string>
+ <string name="Big Head">
+ Grosse tête
+ </string>
+ <string name="Big Pectorals">
+ Gros pectoraux
+ </string>
+ <string name="Big Spikes">
+ Spikes
+ </string>
+ <string name="Black">
+ Noir
+ </string>
+ <string name="Blonde">
+ Blond
+ </string>
+ <string name="Blonde Hair">
+ Cheveux blonds
+ </string>
+ <string name="Blush">
+ Blush
+ </string>
+ <string name="Blush Color">
+ Couleur du blush
+ </string>
+ <string name="Blush Opacity">
+ Opacité du blush
+ </string>
+ <string name="Body Definition">
+ Contour du corps
+ </string>
+ <string name="Body Fat">
+ Graisse
+ </string>
+ <string name="Body Freckles">
+ Grains de beauté
+ </string>
+ <string name="Body Thick">
+ Corps épais
+ </string>
+ <string name="Body Thickness">
+ Épaisseur du corps
+ </string>
+ <string name="Body Thin">
+ Corps mince
+ </string>
+ <string name="Bow Legged">
+ Jambes arquées
+ </string>
+ <string name="Breast Buoyancy">
+ Hauteur des seins
+ </string>
+ <string name="Breast Cleavage">
+ Clivage
+ </string>
+ <string name="Breast Size">
+ Taille des seins
+ </string>
+ <string name="Bridge Width">
+ Arête du nez
+ </string>
+ <string name="Broad">
+ Large
+ </string>
+ <string name="Brow Size">
+ Taille
+ </string>
+ <string name="Bug Eyes">
+ Yeux globuleux
+ </string>
+ <string name="Bugged Eyes">
+ Yeux globuleux
+ </string>
+ <string name="Bulbous">
+ En bulbe
+ </string>
+ <string name="Bulbous Nose">
+ Nez en bulbe
+ </string>
+ <string name="Bushy Eyebrows">
+ Sourcils touffus
+ </string>
+ <string name="Bushy Hair">
+ Beaucoup
+ </string>
+ <string name="Butt Size">
+ Taille des fesses
+ </string>
+ <string name="bustle skirt">
+ Jupe gonflante
+ </string>
+ <string name="no bustle">
+ Pas gonflante
+ </string>
+ <string name="more bustle">
+ Plus gonflante
+ </string>
+ <string name="Chaplin">
+ Moins
+ </string>
+ <string name="Cheek Bones">
+ Pommettes
+ </string>
+ <string name="Chest Size">
+ Taille de la poitrine
+ </string>
+ <string name="Chin Angle">
+ Angle du menton
+ </string>
+ <string name="Chin Cleft">
+ Fente du menton
+ </string>
+ <string name="Chin Curtains">
+ Favoris
+ </string>
+ <string name="Chin Depth">
+ Profondeur
+ </string>
+ <string name="Chin Heavy">
+ Menton lourd
+ </string>
+ <string name="Chin In">
+ Menton rentré
+ </string>
+ <string name="Chin Out">
+ Menton sorti
+ </string>
+ <string name="Chin-Neck">
+ Menton-cou
+ </string>
+ <string name="Clear">
+ Clair
+ </string>
+ <string name="Cleft">
+ Fendu
+ </string>
+ <string name="Close Set Eyes">
+ Yeux rapprochés
+ </string>
+ <string name="Closed">
+ Fermé(s)
+ </string>
+ <string name="Closed Back">
+ Fermé à l&apos;arrière
+ </string>
+ <string name="Closed Front">
+ Fermé devant
+ </string>
+ <string name="Closed Left">
+ Fermé à gauche
+ </string>
+ <string name="Closed Right">
+ Fermé à droite
+ </string>
+ <string name="Coin Purse">
+ Mini
+ </string>
+ <string name="Collar Back">
+ Col arrière
+ </string>
+ <string name="Collar Front">
+ Col devant
+ </string>
+ <string name="Corner Down">
+ Coin vers le bas
+ </string>
+ <string name="Corner Up">
+ Coin vers le haut
+ </string>
+ <string name="Creased">
+ Fripée
+ </string>
+ <string name="Crooked Nose">
+ Déviation du nez
+ </string>
+ <string name="Cuff Flare">
+ Jambe
+ </string>
+ <string name="Dark">
+ Sombre
+ </string>
+ <string name="Dark Green">
+ Vert foncé
+ </string>
+ <string name="Darker">
+ Plus foncé
+ </string>
+ <string name="Deep">
+ Profonde
+ </string>
+ <string name="Default Heels">
+ Talons par défaut
+ </string>
+ <string name="Dense">
+ Dense
+ </string>
+ <string name="Double Chin">
+ Double menton
+ </string>
+ <string name="Downturned">
+ Pointant vers le bas
+ </string>
+ <string name="Duffle Bag">
+ Maxi
+ </string>
+ <string name="Ear Angle">
+ Angle de l&apos;oreille
+ </string>
+ <string name="Ear Size">
+ Taille
+ </string>
+ <string name="Ear Tips">
+ Extrémités
+ </string>
+ <string name="Egg Head">
+ Forme de la tête
+ </string>
+ <string name="Eye Bags">
+ Cernes
+ </string>
+ <string name="Eye Color">
+ Couleur des yeux
+ </string>
+ <string name="Eye Depth">
+ Profondeur
+ </string>
+ <string name="Eye Lightness">
+ Clarté
+ </string>
+ <string name="Eye Opening">
+ Ouverture
+ </string>
+ <string name="Eye Pop">
+ Œil proéminent
+ </string>
+ <string name="Eye Size">
+ Taille de l&apos;Å“il
+ </string>
+ <string name="Eye Spacing">
+ Espacement
+ </string>
+ <string name="Eyebrow Arc">
+ Arc
+ </string>
+ <string name="Eyebrow Density">
+ Épaisseur sourcils
+ </string>
+ <string name="Eyebrow Height">
+ Hauteur
+ </string>
+ <string name="Eyebrow Points">
+ Direction
+ </string>
+ <string name="Eyebrow Size">
+ Taille
+ </string>
+ <string name="Eyelash Length">
+ Longueur des cils
+ </string>
+ <string name="Eyeliner">
+ Eyeliner
+ </string>
+ <string name="Eyeliner Color">
+ Couleur de l&apos;eyeliner
+ </string>
+ <string name="Eyes Bugged">
+ Yeux globuleux
+ </string>
+ <string name="Eyes Shear Left Up">
+ Å’il gauche vers le haut
+ </string>
+ <string name="Eyes Shear Right Up">
+ Å’il droit vers le haut
+ </string>
+ <string name="Face Shear">
+ Visage
+ </string>
+ <string name="Facial Definition">
+ Définition
+ </string>
+ <string name="Far Set Eyes">
+ Yeux écartés
+ </string>
+ <string name="Fat Lips">
+ Lèvres épaisses
+ </string>
+ <string name="Female">
+ Femme
+ </string>
+ <string name="Fingerless">
+ Sans doigts
+ </string>
+ <string name="Fingers">
+ Doigts
+ </string>
+ <string name="Flared Cuffs">
+ Jambes larges
+ </string>
+ <string name="Flat">
+ Plat
+ </string>
+ <string name="Flat Butt">
+ Fesses plates
+ </string>
+ <string name="Flat Head">
+ Tête plate
+ </string>
+ <string name="Flat Toe">
+ Orteil plat
+ </string>
+ <string name="Foot Size">
+ Pointure
+ </string>
+ <string name="Forehead Angle">
+ Angle du front
+ </string>
+ <string name="Forehead Heavy">
+ Front lourd
+ </string>
+ <string name="Freckles">
+ Tâches de rousseur
+ </string>
+ <string name="Front Fringe">
+ Mèches de devant
+ </string>
+ <string name="Full Back">
+ Arrière touffu
+ </string>
+ <string name="Full Eyeliner">
+ Eyeliner marqué
+ </string>
+ <string name="Full Front">
+ Devant touffu
+ </string>
+ <string name="Full Hair Sides">
+ Côtés touffus
+ </string>
+ <string name="Full Sides">
+ Côtés touffus
+ </string>
+ <string name="Glossy">
+ Brillant
+ </string>
+ <string name="Glove Fingers">
+ Doigts avec gants
+ </string>
+ <string name="Glove Length">
+ Longueur des gants
+ </string>
+ <string name="Hair">
+ Cheveux
+ </string>
+ <string name="Hair Back">
+ Cheveux : Derrière
+ </string>
+ <string name="Hair Front">
+ Cheveux : Devant
+ </string>
+ <string name="Hair Sides">
+ Cheveux : Côtés
+ </string>
+ <string name="Hair Sweep">
+ Sens de la coiffure
+ </string>
+ <string name="Hair Thickess">
+ Épaisseur cheveux
+ </string>
+ <string name="Hair Thickness">
+ Épaisseur cheveux
+ </string>
+ <string name="Hair Tilt">
+ Inclinaison
+ </string>
+ <string name="Hair Tilted Left">
+ Vers la gauche
+ </string>
+ <string name="Hair Tilted Right">
+ Vers la droite
+ </string>
+ <string name="Hair Volume">
+ Cheveux : Volume
+ </string>
+ <string name="Hand Size">
+ Taille de la main
+ </string>
+ <string name="Handlebars">
+ Plus
+ </string>
+ <string name="Head Length">
+ Longueur
+ </string>
+ <string name="Head Shape">
+ Forme
+ </string>
+ <string name="Head Size">
+ Taille
+ </string>
+ <string name="Head Stretch">
+ Allongement
+ </string>
+ <string name="Heel Height">
+ Talons
+ </string>
+ <string name="Heel Shape">
+ Forme des talons
+ </string>
+ <string name="Height">
+ Taille
+ </string>
+ <string name="High">
+ Haut
+ </string>
+ <string name="High Heels">
+ Talons hauts
+ </string>
+ <string name="High Jaw">
+ Haut
+ </string>
+ <string name="High Platforms">
+ Haute
+ </string>
+ <string name="High and Tight">
+ Haut et serré
+ </string>
+ <string name="Higher">
+ Plus élevé
+ </string>
+ <string name="Hip Length">
+ Longueur hanche
+ </string>
+ <string name="Hip Width">
+ Largeur hanche
+ </string>
+ <string name="In">
+ Rentré
+ </string>
+ <string name="In Shdw Color">
+ Couleur ombre interne
+ </string>
+ <string name="In Shdw Opacity">
+ Opacité ombre interne
+ </string>
+ <string name="Inner Eye Corner">
+ Coin interne
+ </string>
+ <string name="Inner Eye Shadow">
+ Ombre de l&apos;Å“il interne
+ </string>
+ <string name="Inner Shadow">
+ Ombre interne
+ </string>
+ <string name="Jacket Length">
+ Longueur de la veste
+ </string>
+ <string name="Jacket Wrinkles">
+ Plis de la veste
+ </string>
+ <string name="Jaw Angle">
+ Angle mâchoire
+ </string>
+ <string name="Jaw Jut">
+ Saillie de la mâchoire
+ </string>
+ <string name="Jaw Shape">
+ Forme de la mâchoire
+ </string>
+ <string name="Join">
+ Rapprochés
+ </string>
+ <string name="Jowls">
+ Bajoues
+ </string>
+ <string name="Knee Angle">
+ Angle du genou
+ </string>
+ <string name="Knock Kneed">
+ Genoux rapprochés
+ </string>
+ <string name="Large">
+ Plus
+ </string>
+ <string name="Large Hands">
+ Grandes mains
+ </string>
+ <string name="Left Part">
+ Raie à gauche
+ </string>
+ <string name="Leg Length">
+ Longueur
+ </string>
+ <string name="Leg Muscles">
+ Muscles
+ </string>
+ <string name="Less">
+ Moins
+ </string>
+ <string name="Less Body Fat">
+ Moins
+ </string>
+ <string name="Less Curtains">
+ Moins
+ </string>
+ <string name="Less Freckles">
+ Moins
+ </string>
+ <string name="Less Full">
+ Moins
+ </string>
+ <string name="Less Gravity">
+ Moins
+ </string>
+ <string name="Less Love">
+ Moins
+ </string>
+ <string name="Less Muscles">
+ Moins
+ </string>
+ <string name="Less Muscular">
+ Moins
+ </string>
+ <string name="Less Rosy">
+ Moins
+ </string>
+ <string name="Less Round">
+ Moins ronde
+ </string>
+ <string name="Less Saddle">
+ Moins
+ </string>
+ <string name="Less Square">
+ Moins carrée
+ </string>
+ <string name="Less Volume">
+ Moins
+ </string>
+ <string name="Less soul">
+ Moins
+ </string>
+ <string name="Lighter">
+ Plus léger
+ </string>
+ <string name="Lip Cleft">
+ Fente labiale
+ </string>
+ <string name="Lip Cleft Depth">
+ Profondeur fente labiale
+ </string>
+ <string name="Lip Fullness">
+ Volume des lèvres
+ </string>
+ <string name="Lip Pinkness">
+ Rougeur des lèvres
+ </string>
+ <string name="Lip Ratio">
+ Proportion des lèvres
+ </string>
+ <string name="Lip Thickness">
+ Épaisseur
+ </string>
+ <string name="Lip Width">
+ Largeur
+ </string>
+ <string name="Lipgloss">
+ Brillant à lèvres
+ </string>
+ <string name="Lipstick">
+ Rouge à lèvres
+ </string>
+ <string name="Lipstick Color">
+ Couleur du rouge à lèvres
+ </string>
+ <string name="Long">
+ Long
+ </string>
+ <string name="Long Head">
+ Tête longue
+ </string>
+ <string name="Long Hips">
+ Hanches longues
+ </string>
+ <string name="Long Legs">
+ Jambes longues
+ </string>
+ <string name="Long Neck">
+ Long cou
+ </string>
+ <string name="Long Pigtails">
+ Longues couettes
+ </string>
+ <string name="Long Ponytail">
+ Longue queue de cheval
+ </string>
+ <string name="Long Torso">
+ Torse long
+ </string>
+ <string name="Long arms">
+ Bras longs
+ </string>
+ <string name="Loose Pants">
+ Pantalons amples
+ </string>
+ <string name="Loose Shirt">
+ Chemise ample
+ </string>
+ <string name="Loose Sleeves">
+ Manches amples
+ </string>
+ <string name="Love Handles">
+ Poignées d&apos;amour
+ </string>
+ <string name="Low">
+ Bas
+ </string>
+ <string name="Low Heels">
+ Talons bas
+ </string>
+ <string name="Low Jaw">
+ Bas
+ </string>
+ <string name="Low Platforms">
+ Basse
+ </string>
+ <string name="Low and Loose">
+ Bas et ample
+ </string>
+ <string name="Lower">
+ Abaisser
+ </string>
+ <string name="Lower Bridge">
+ Arête plus basse
+ </string>
+ <string name="Lower Cheeks">
+ Joue inférieure
+ </string>
+ <string name="Male">
+ Homme
+ </string>
+ <string name="Middle Part">
+ Raie au milieu
+ </string>
+ <string name="More">
+ Plus
+ </string>
+ <string name="More Blush">
+ Plus
+ </string>
+ <string name="More Body Fat">
+ Plus
+ </string>
+ <string name="More Curtains">
+ Plus
+ </string>
+ <string name="More Eyeshadow">
+ Plus
+ </string>
+ <string name="More Freckles">
+ Plus
+ </string>
+ <string name="More Full">
+ Plus
+ </string>
+ <string name="More Gravity">
+ Plus
+ </string>
+ <string name="More Lipstick">
+ Plus
+ </string>
+ <string name="More Love">
+ Plus
+ </string>
+ <string name="More Lower Lip">
+ Plus
+ </string>
+ <string name="More Muscles">
+ Plus
+ </string>
+ <string name="More Muscular">
+ Plus
+ </string>
+ <string name="More Rosy">
+ Plus
+ </string>
+ <string name="More Round">
+ Plus
+ </string>
+ <string name="More Saddle">
+ Plus
+ </string>
+ <string name="More Sloped">
+ Plus
+ </string>
+ <string name="More Square">
+ Plus
+ </string>
+ <string name="More Upper Lip">
+ Plus
+ </string>
+ <string name="More Vertical">
+ Plus
+ </string>
+ <string name="More Volume">
+ Plus
+ </string>
+ <string name="More soul">
+ Plus
+ </string>
+ <string name="Moustache">
+ Moustache
+ </string>
+ <string name="Mouth Corner">
+ Coin de la bouche
+ </string>
+ <string name="Mouth Position">
+ Position
+ </string>
+ <string name="Mowhawk">
+ Mowhawk
+ </string>
+ <string name="Muscular">
+ Musclé
+ </string>
+ <string name="Mutton Chops">
+ Longs
+ </string>
+ <string name="Nail Polish">
+ Vernis à ongles
+ </string>
+ <string name="Nail Polish Color">
+ Couleur du vernis
+ </string>
+ <string name="Narrow">
+ Étroit
+ </string>
+ <string name="Narrow Back">
+ Arrière étroit
+ </string>
+ <string name="Narrow Front">
+ Devant étroit
+ </string>
+ <string name="Narrow Lips">
+ Lèvres étroites
+ </string>
+ <string name="Natural">
+ Naturel
+ </string>
+ <string name="Neck Length">
+ Longueur du cou
+ </string>
+ <string name="Neck Thickness">
+ Épaisseur du cou
+ </string>
+ <string name="No Blush">
+ Pas de blush
+ </string>
+ <string name="No Eyeliner">
+ Pas d&apos;eyeliner
+ </string>
+ <string name="No Eyeshadow">
+ Pas d&apos;ombre à paupières
+ </string>
+ <string name="No Lipgloss">
+ Pas de brillant à lèvres
+ </string>
+ <string name="No Lipstick">
+ Pas de rouge à lèvres
+ </string>
+ <string name="No Part">
+ Pas de raie
+ </string>
+ <string name="No Polish">
+ Pas de vernis
+ </string>
+ <string name="No Red">
+ Pas de rouge
+ </string>
+ <string name="No Spikes">
+ Pas de spikes
+ </string>
+ <string name="No White">
+ Pas de blanc
+ </string>
+ <string name="No Wrinkles">
+ Pas de rides
+ </string>
+ <string name="Normal Lower">
+ Normal plus bas
+ </string>
+ <string name="Normal Upper">
+ Normal plus haut
+ </string>
+ <string name="Nose Left">
+ Nez à gauche
+ </string>
+ <string name="Nose Right">
+ Nez à droite
+ </string>
+ <string name="Nose Size">
+ Taille du nez
+ </string>
+ <string name="Nose Thickness">
+ Épaisseur du nez
+ </string>
+ <string name="Nose Tip Angle">
+ Bout du nez
+ </string>
+ <string name="Nose Tip Shape">
+ Bout du nez
+ </string>
+ <string name="Nose Width">
+ Largeur du nez
+ </string>
+ <string name="Nostril Division">
+ Division des narines
+ </string>
+ <string name="Nostril Width">
+ Largeur des narines
+ </string>
+ <string name="Opaque">
+ Opaque
+ </string>
+ <string name="Open">
+ Ouvert
+ </string>
+ <string name="Open Back">
+ Derrière ouvert
+ </string>
+ <string name="Open Front">
+ Devant ouvert
+ </string>
+ <string name="Open Left">
+ Ouvert à gauche
+ </string>
+ <string name="Open Right">
+ Ouvert à droite
+ </string>
+ <string name="Orange">
+ Orange
+ </string>
+ <string name="Out">
+ Sorti
+ </string>
+ <string name="Out Shdw Color">
+ Couleur de l&apos;ombre externe
+ </string>
+ <string name="Out Shdw Opacity">
+ Opacité de l&apos;ombre externe
+ </string>
+ <string name="Outer Eye Corner">
+ Coin externe
+ </string>
+ <string name="Outer Eye Shadow">
+ Ombre de l&apos;Å“il externe
+ </string>
+ <string name="Outer Shadow">
+ Ombre externe
+ </string>
+ <string name="Overbite">
+ Rentrée
+ </string>
+ <string name="Package">
+ Parties
+ </string>
+ <string name="Painted Nails">
+ Ongles vernis
+ </string>
+ <string name="Pale">
+ Pâle
+ </string>
+ <string name="Pants Crotch">
+ Entrejambe
+ </string>
+ <string name="Pants Fit">
+ Taille
+ </string>
+ <string name="Pants Length">
+ Longueur
+ </string>
+ <string name="Pants Waist">
+ Taille
+ </string>
+ <string name="Pants Wrinkles">
+ Plis
+ </string>
+ <string name="Part">
+ Raie
+ </string>
+ <string name="Part Bangs">
+ Séparation frange
+ </string>
+ <string name="Pectorals">
+ Pectoraux
+ </string>
+ <string name="Pigment">
+ Pigmentation
+ </string>
+ <string name="Pigtails">
+ Couettes
+ </string>
+ <string name="Pink">
+ Rose
+ </string>
+ <string name="Pinker">
+ Plus rose
+ </string>
+ <string name="Platform Height">
+ Plateforme (hauteur)
+ </string>
+ <string name="Platform Width">
+ Plateforme (largeur)
+ </string>
+ <string name="Pointy">
+ Pointu
+ </string>
+ <string name="Pointy Heels">
+ Talons pointus
+ </string>
+ <string name="Ponytail">
+ Queue de cheval
+ </string>
+ <string name="Poofy Skirt">
+ Jupe bouffante
+ </string>
+ <string name="Pop Left Eye">
+ Å’il gauche saillant
+ </string>
+ <string name="Pop Right Eye">
+ Å’il droit saillant
+ </string>
+ <string name="Puffy">
+ Gonflées
+ </string>
+ <string name="Puffy Eyelids">
+ Paupières
+ </string>
+ <string name="Rainbow Color">
+ Couleur arc en ciel
+ </string>
+ <string name="Red Hair">
+ Cheveux roux
+ </string>
+ <string name="Regular">
+ Standard
+ </string>
+ <string name="Right Part">
+ Raie à droite
+ </string>
+ <string name="Rosy Complexion">
+ Teint rosé
+ </string>
+ <string name="Round">
+ Rond
+ </string>
+ <string name="Ruddiness">
+ Rougeur
+ </string>
+ <string name="Ruddy">
+ Rouge
+ </string>
+ <string name="Rumpled Hair">
+ Texture
+ </string>
+ <string name="Saddle Bags">
+ Culotte de cheval
+ </string>
+ <string name="Scrawny Leg">
+ Jambes maigres
+ </string>
+ <string name="Separate">
+ Séparés
+ </string>
+ <string name="Shallow">
+ Creux
+ </string>
+ <string name="Shear Back">
+ Coupe derrière
+ </string>
+ <string name="Shear Face">
+ Visage
+ </string>
+ <string name="Shear Front">
+ Front
+ </string>
+ <string name="Shear Left Up">
+ Haut gauche décalé
+ </string>
+ <string name="Shear Right Up">
+ Haut droit décalé
+ </string>
+ <string name="Sheared Back">
+ Dégagé derrière
+ </string>
+ <string name="Sheared Front">
+ Dégagé devant
+ </string>
+ <string name="Shift Left">
+ Vers la gauche
+ </string>
+ <string name="Shift Mouth">
+ Déplacer la bouche
+ </string>
+ <string name="Shift Right">
+ Vers la droite
+ </string>
+ <string name="Shirt Bottom">
+ Chemise
+ </string>
+ <string name="Shirt Fit">
+ Taille
+ </string>
+ <string name="Shirt Wrinkles">
+ Plis
+ </string>
+ <string name="Shoe Height">
+ Hauteur
+ </string>
+ <string name="Short">
+ Moins
+ </string>
+ <string name="Short Arms">
+ Bras courts
+ </string>
+ <string name="Short Legs">
+ Jambes courtes
+ </string>
+ <string name="Short Neck">
+ Petit cou
+ </string>
+ <string name="Short Pigtails">
+ Couettes courtes
+ </string>
+ <string name="Short Ponytail">
+ Queue de cheval courte
+ </string>
+ <string name="Short Sideburns">
+ Court
+ </string>
+ <string name="Short Torso">
+ Torse court
+ </string>
+ <string name="Short hips">
+ Hanches courtes
+ </string>
+ <string name="Shoulders">
+ Épaules
+ </string>
+ <string name="Side Fringe">
+ Mèches sur le côté
+ </string>
+ <string name="Sideburns">
+ Favoris
+ </string>
+ <string name="Sides Hair">
+ Cheveux sur le côté
+ </string>
+ <string name="Sides Hair Down">
+ Cheveux sur le côté en bas
+ </string>
+ <string name="Sides Hair Up">
+ Cheveux sur le côté en haut
+ </string>
+ <string name="Skinny Neck">
+ Cou maigre
+ </string>
+ <string name="Skirt Fit">
+ Taille jupe
+ </string>
+ <string name="Skirt Length">
+ Longueur jupe
+ </string>
+ <string name="Slanted Forehead">
+ Front incliné
+ </string>
+ <string name="Sleeve Length">
+ Longueur manche
+ </string>
+ <string name="Sleeve Looseness">
+ Ampleur manche
+ </string>
+ <string name="Slit Back">
+ Fente : Derrière
+ </string>
+ <string name="Slit Front">
+ Fente : Devant
+ </string>
+ <string name="Slit Left">
+ Fente : Gauche
+ </string>
+ <string name="Slit Right">
+ Fente : Droite
+ </string>
+ <string name="Small">
+ Moins
+ </string>
+ <string name="Small Hands">
+ Petites mains
+ </string>
+ <string name="Small Head">
+ Petite tête
+ </string>
+ <string name="Smooth">
+ Lisses
+ </string>
+ <string name="Smooth Hair">
+ Cheveux lisses
+ </string>
+ <string name="Socks Length">
+ Longueur des chaussettes
+ </string>
+ <string name="Soulpatch">
+ Barbichette
+ </string>
+ <string name="Sparse">
+ Rares
+ </string>
+ <string name="Spiked Hair">
+ Mèches en pointe
+ </string>
+ <string name="Square">
+ Carré
+ </string>
+ <string name="Square Toe">
+ Orteil carré
+ </string>
+ <string name="Squash Head">
+ Écraser la tête
+ </string>
+ <string name="Stretch Head">
+ Allonger la tête
+ </string>
+ <string name="Sunken">
+ Saillante
+ </string>
+ <string name="Sunken Chest">
+ Poitrine enfoncée
+ </string>
+ <string name="Sunken Eyes">
+ Yeux enfoncés
+ </string>
+ <string name="Sweep Back">
+ En arrière
+ </string>
+ <string name="Sweep Forward">
+ Vers l&apos;avant
+ </string>
+ <string name="Tall">
+ Plus
+ </string>
+ <string name="Taper Back">
+ Arrière
+ </string>
+ <string name="Taper Front">
+ Avant
+ </string>
+ <string name="Thick Heels">
+ Talons épais
+ </string>
+ <string name="Thick Neck">
+ Cou épais
+ </string>
+ <string name="Thick Toe">
+ Orteil épais
+ </string>
+ <string name="Thin">
+ Mince
+ </string>
+ <string name="Thin Eyebrows">
+ Sourcils fins
+ </string>
+ <string name="Thin Lips">
+ Lèvres fines
+ </string>
+ <string name="Thin Nose">
+ Nez fin
+ </string>
+ <string name="Tight Chin">
+ Menton fin
+ </string>
+ <string name="Tight Cuffs">
+ Jambes serrées
+ </string>
+ <string name="Tight Pants">
+ Pantalons serrés
+ </string>
+ <string name="Tight Shirt">
+ Chemise serrée
+ </string>
+ <string name="Tight Skirt">
+ Jupe serrée
+ </string>
+ <string name="Tight Sleeves">
+ Manches serrées
+ </string>
+ <string name="Toe Shape">
+ Forme de l&apos;orteil
+ </string>
+ <string name="Toe Thickness">
+ Épaisseur de l&apos;orteil
+ </string>
+ <string name="Torso Length">
+ Longueur du torse
+ </string>
+ <string name="Torso Muscles">
+ Muscles du torse
+ </string>
+ <string name="Torso Scrawny">
+ Torse maigre
+ </string>
+ <string name="Unattached">
+ Séparés
+ </string>
+ <string name="Uncreased">
+ Lisse
+ </string>
+ <string name="Underbite">
+ Sortie
+ </string>
+ <string name="Unnatural">
+ Artificiel
+ </string>
+ <string name="Upper Bridge">
+ Arête supérieure
+ </string>
+ <string name="Upper Cheeks">
+ Pommette
+ </string>
+ <string name="Upper Chin Cleft">
+ Menton supérieur
+ </string>
+ <string name="Upper Eyelid Fold">
+ Paupière supérieure
+ </string>
+ <string name="Upturned">
+ En trompette
+ </string>
+ <string name="Very Red">
+ Très rouge
+ </string>
+ <string name="Waist Height">
+ Hauteur taille
+ </string>
+ <string name="Well-Fed">
+ Ronde
+ </string>
+ <string name="White Hair">
+ Cheveux blancs
+ </string>
+ <string name="Wide">
+ Large
+ </string>
+ <string name="Wide Back">
+ Derrière large
+ </string>
+ <string name="Wide Front">
+ Devant large
+ </string>
+ <string name="Wide Lips">
+ Lèvres larges
+ </string>
+ <string name="Wild">
+ Artificiel
+ </string>
+ <string name="Wrinkles">
+ Rides
+ </string>
+ <string name="LocationCtrlAddLandmarkTooltip">
+ Ajouter à mes repères
+ </string>
+ <string name="LocationCtrlEditLandmarkTooltip">
+ Modifier mes repères
+ </string>
+ <string name="LocationCtrlInfoBtnTooltip">
+ En savoir plus sur l&apos;emplacement actuel
+ </string>
+ <string name="LocationCtrlComboBtnTooltip">
+ Historique de mes emplacements
+ </string>
+ <string name="UpdaterWindowTitle">
+ [APP_NAME] - Mise à jour
+ </string>
+ <string name="UpdaterNowUpdating">
+ Mise à jour de [APP_NAME]...
+ </string>
+ <string name="UpdaterNowInstalling">
+ Installation de [APP_NAME]...
+ </string>
+ <string name="UpdaterUpdatingDescriptive">
+ Le client [APP_NAME] est en train d&apos;être mis à jour. Cela peut prendre un certain temps, merci de votre patience.
+ </string>
+ <string name="UpdaterProgressBarTextWithEllipses">
+ Mise à jour en cours...
+ </string>
+ <string name="UpdaterProgressBarText">
+ Mise à jour en cours
+ </string>
+ <string name="UpdaterFailDownloadTitle">
+ Le téléchargement de la mise à jour a échoué
+ </string>
+ <string name="UpdaterFailUpdateDescriptive">
+ Une erreur est survenue lors de la mise à jour de [APP_NAME]. Veuillez télécharger la dernière version sur www.secondlife.com.
+ </string>
+ <string name="UpdaterFailInstallTitle">
+ L&apos;installation de la mise à jour a échoué
+ </string>
+ <string name="UpdaterFailStartTitle">
+ Impossible de lancer le client
+ </string>
+ <string name="IM_logging_string">
+ -- Archivage des IM activé --
+ </string>
+ <string name="IM_typing_start_string">
+ [NAME] est en train d&apos;écrire...
+ </string>
+ <string name="Unnamed">
+ (sans nom)
+ </string>
+ <string name="IM_moderated_chat_label">
+ (Modéré : Voix désactivées par défaut)
+ </string>
+ <string name="IM_unavailable_text_label">
+ Le chat écrit n&apos;est pas disponible pour cet appel.
+ </string>
+ <string name="IM_muted_text_label">
+ Votre chat écrit a été désactivé par un modérateur de groupe.
+ </string>
+ <string name="IM_default_text_label">
+ Cliquez ici pour envoyer un message instantané.
+ </string>
+ <string name="IM_to_label">
+ À
+ </string>
+ <string name="IM_moderator_label">
+ (Modérateur)
+ </string>
+ <string name="only_user_message">
+ Vous êtes le seul participant à cette session.
+ </string>
+ <string name="offline_message">
+ [FIRST] [LAST] est déconnecté(e).
+ </string>
+ <string name="invite_message">
+ Pour accepter ce chat vocal/vous connecter, cliquez sur le bouton [BUTTON NAME].
+ </string>
+ <string name="generic_request_error">
+ Erreur lors de la requête, veuillez réessayer ultérieurement.
+ </string>
+ <string name="insufficient_perms_error">
+ Vous n&apos;avez pas les droits requis.
+ </string>
+ <string name="session_does_not_exist_error">
+ La session a expiré
+ </string>
+ <string name="no_ability_error">
+ Vous n&apos;avez pas ce pouvoir.
+ </string>
+ <string name="no_ability">
+ Vous n&apos;avez pas ce pouvoir.
+ </string>
+ <string name="not_a_mod_error">
+ Vous n&apos;êtes pas modérateur de session.
+ </string>
+ <string name="muted_error">
+ Un modérateur de groupe a désactivé votre chat écrit.
+ </string>
+ <string name="add_session_event">
+ Impossible d&apos;ajouter des participants à la session de chat avec [RECIPIENT].
+ </string>
+ <string name="message_session_event">
+ Impossible d&apos;envoyer votre message à la session de chat avec [RECIPIENT].
+ </string>
+ <string name="removed_from_group">
+ Vous avez été supprimé du groupe.
+ </string>
+ <string name="close_on_no_ability">
+ Vous ne pouvez plus participer à la session de chat.
+ </string>
</strings>
diff --git a/indra/newview/skins/default/xui/fr/teleport_strings.xml b/indra/newview/skins/default/xui/fr/teleport_strings.xml
index 810a32f64e..b76ae370fd 100644
--- a/indra/newview/skins/default/xui/fr/teleport_strings.xml
+++ b/indra/newview/skins/default/xui/fr/teleport_strings.xml
@@ -1,13 +1,13 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<teleport_messages name="">
<message_set name="errors">
<message name="invalid_tport">
- Nous avons rencontré des problèmes en essayant de vous téléporter. Vous devrez peut-être vous reconnecter avant de pouvoir être téléporté. Si vous continuez à recevoir ce message, veuillez consulter le Support à la page suivante :
-www.secondlife.com/support
+ Nous avons rencontré des problèmes en essayant de vous téléporter. Vous devrez peut-être vous reconnecter avant de pouvoir vous téléporter.
+Si ce message persiste, veuillez consulter la page [SUPPORT_SITE].
</message>
<message name="invalid_region_handoff">
- Nous avons rencontré des problèmes en essayant de vous téléporter. Vous devrez peut-être vous reconnecter avant de pouvoir être téléporté. Si vous continuez à recevoir ce message, veuillez consulter le Support à la page suivante :
-www.secondlife.com/support
+ Nous avons rencontré des problèmes en essayant de vous téléporter. Vous devrez peut-être vous reconnecter avant de pouvoir traverser des régions.
+Si ce message persiste, veuillez consulter la page [SUPPORT_SITE].
</message>
<message name="blocked_tport">
Désolé, la téléportation est bloquée actuellement. Veuillez réessayer dans un moment.
diff --git a/indra/newview/skins/default/xui/it/floater_about.xml b/indra/newview/skins/default/xui/it/floater_about.xml
index 2ec8bc4dd8..f80f810dba 100644
--- a/indra/newview/skins/default/xui/it/floater_about.xml
+++ b/indra/newview/skins/default/xui/it/floater_about.xml
@@ -1,10 +1,19 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_about" title="Informazioni su Second Life">
+<floater name="floater_about" title="INFORMAZIONI SU [CAPITALIZED_APP_NAME]">
+<tab_container name="about_tab">
+ <panel name="credits_panel">
<text_editor name="credits_editor">
- Second Life è offerto da Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les and many others.
+ Second Life è offerto da Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, Michon, Jenelle, Geo, Siz, Shapiro, Pete, Calyle, Selene, Allen, Phoebe, Goldin, Kimmora, Dakota, Slaton, Lindquist, Zoey, Hari, Othello, Rohit, Sheldon, Petra, Viale, Gordon, Kaye, Pink, Ferny, Emerson, Davy, Bri, Chan, Juan, Robert, Terrence, Nathan, Carl and many others.
- Si ringraziano i seguenti residenti per aver contribuito a rendere questa versione la migliore possibile:
+ Si ringraziano i seguenti residenti per aver contribuito a rendere questa versione la migliore possibile: able whitman, Adeon Writer, adonaira aabye, Aeron Kohime, Agathos Frascati, Aimee Trescothick, Aleric Inglewood, Alissa Sabre, Aminom Marvin, Angela Talamasca, Aralara Rajal, Armin Weatherwax, Ashrilyn Hayashida, Athanasius Skytower, Aura Dirval, Barney Boomslang, Biancaluce Robbiani, Biker Offcourse, Borg Capalini, Bulli Schumann, catherine pfeffer, Chalice Yao, Corre Porta, Court Goodman, Cummere Mayo, Dale Innis, Darien Caldwell, Darjeeling Schoonhoven, Daten Thielt, dimentox travanti, Dirk Talamasca, Drew Dwi, Duckless Vandyke, Elanthius Flagstaff, Electro Burnstein, emiley tomsen, Escort DeFarge, Eva Rau, Ezian Ecksol, Fire Centaur, Fluf Fredriksson, Francisco Koolhoven, Frontera Thor, Frungi Stastny, Gally Young, gearsawe stonecutter, Gigs Taggart, Gordon Wendt, Gudmund Shepherd, Gypsy Paz, Harleen Gretzky, Henri Beauchamp, Inma Rau, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Jessicka Graves, Joeseph Albanese, Joshua Philgarlic, Khyota Wulluf, kirstenlee Cinquetti, Latif Khalifa, Lex Neva, Lilibeth Andree, Lisa Lowe, Lunita Savira, Loosey Demonia, lum pfohl, Marcos Fonzarelli, MartinRJ Fayray, Marusame Arai, Matthew Dowd, Maya Remblai, McCabe Maxsted, Meghan Dench, Melchoir Tokhes, Menos Short, Michelle2 Zenovka, Mimika Oh, Minerva Memel, Mm Alder, Ochi Wolfe, Omei Turnbull, Pesho Replacement, Phantom Ninetails, phoenixflames kukulcan, Polo Gufler, prez pessoa, princess niven, Prokofy Neva, Qie Niangao, Rem Beattie, RodneyLee Jessop, Saijanai Kuhn, Seg Baphomet, Sergen Davies, Shirley Marquez, SignpostMarv Martin, Sindy Tsure, Sira Arbizu, Skips Jigsaw, Sougent Harrop, Spritely Pixel, Squirrel Wood, StarSong Bright, Subversive Writer, Sugarcult Dagger, Sylumm Grigorovich, Tammy Nowotny, Tanooki Darkes, Tayra Dagostino, Theoretical Chemistry, Thickbrick Sleaford, valerie rosewood, Vex Streeter, Vixen Heron, Whoops Babii, Winter Ventura, Xiki Luik, Yann Dufaux, Yina Yao, Yukinoroh Kamachi, Zolute Infinity, Zwagoth Klaar
+
+
+ Per avere successo nel business, sii coraggioso, sii il primo, sii differente. --Henry Marchant
+ </text_editor>
+ </panel>
+ <panel name="licenses_panel">
+ <text_editor name="credits_editor">
3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
APR Copyright (C) 2000-2004 The Apache Software Foundation
cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
@@ -26,10 +35,9 @@
Tutti i diritti riservati. Leggi licenses.txt per maggiori dettagli.
Chat vocale Codifica audio: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
-
-
- Per avere successo nel business, sii coraggioso, sii il primo, sii differente. --Henry Marchant
</text_editor>
+ </panel>
+</tab_container>
<string name="you_are_at">
Sei a [POSITION]
</string>
diff --git a/indra/newview/skins/default/xui/it/floater_about_land.xml b/indra/newview/skins/default/xui/it/floater_about_land.xml
index e4ad34bf50..f2bd150ad7 100644
--- a/indra/newview/skins/default/xui/it/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/it/floater_about_land.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterland" title="Informazioni sul terreno">
+<floater name="floaterland" title="INFORMAZIONI SUL TERRENO">
<tab_container name="landtab">
<panel label="Generale" name="land_general_panel">
<text name="Name:">
@@ -80,46 +80,46 @@
<button label="Abbandona la terra..." label_selected="Abbandona la terra..." name="Abandon Land..."/>
<button label="Reclama la terra..." label_selected="Reclama la terra..." name="Reclaim Land..."/>
<button label="Vendita Linden..." label_selected="Vendita Linden..." name="Linden Sale..." tool_tip="La terra deve essere posseduta, con contenuto impostato, e non già messa in asta."/>
- <string name="new users only">
+ <panel.string name="new users only">
Solo ai nuovi residenti
- </string>
- <string name="anyone">
+ </panel.string>
+ <panel.string name="anyone">
A chiunque
- </string>
- <string name="area_text">
+ </panel.string>
+ <panel.string name="area_text">
Area
- </string>
- <string name="area_size_text">
+ </panel.string>
+ <panel.string name="area_size_text">
[AREA] m²
- </string>
- <string name="auction_id_text">
+ </panel.string>
+ <panel.string name="auction_id_text">
Asta n.: [ID]
- </string>
- <string name="need_tier_to_modify">
+ </panel.string>
+ <panel.string name="need_tier_to_modify">
Devi confermare l&apos;acquisto prima di poter modificare il terreno.
- </string>
- <string name="group_owned_text">
+ </panel.string>
+ <panel.string name="group_owned_text">
(Posseduta dal gruppo)
- </string>
- <string name="profile_text">
+ </panel.string>
+ <panel.string name="profile_text">
Profilo...
- </string>
- <string name="info_text">
+ </panel.string>
+ <panel.string name="info_text">
Info...
- </string>
- <string name="public_text">
+ </panel.string>
+ <panel.string name="public_text">
(pubblica)
- </string>
- <string name="none_text">
+ </panel.string>
+ <panel.string name="none_text">
(nessuno)
- </string>
- <string name="sale_pending_text">
+ </panel.string>
+ <panel.string name="sale_pending_text">
(vendita in corso)
- </string>
- <string name="no_selection_text">
+ </panel.string>
+ <panel.string name="no_selection_text">
Nessun appezzamento selezionato.
Vai al menu Mondo &gt; Informazioni sul terreno oppure seleziona un altro appezzamento per vederne i dettagli.
- </string>
+ </panel.string>
</panel>
<panel label="Regolamento" name="land_covenant_panel">
<text name="estate_section_lbl">
@@ -176,20 +176,20 @@ Vai al menu Mondo &gt; Informazioni sul terreno oppure seleziona un altro appezz
<text name="changeable_clause" left="125">
La terra in questa regione non può essere unita/suddivisa.
</text>
- <string name="can_resell">
+ <panel.string name="can_resell">
La terra acquistata in questa regione può essere rivenduta.
- </string>
- <string name="can_not_resell">
+ </panel.string>
+ <panel.string name="can_not_resell">
La terra acquistata in questa regione non può essere rivenduta.
- </string>
- <string name="can_change">
+ </panel.string>
+ <panel.string name="can_change">
La terra acquistata in questa regione può essere unita
o suddivisa.
- </string>
- <string name="can_not_change">
+ </panel.string>
+ <panel.string name="can_not_change">
La terra acquistata in questa regione non può essere unita
o suddivisa.
- </string>
+ </panel.string>
</panel>
<panel label="Oggetti" name="land_objects_panel">
<text name="parcel_object_bonus">
@@ -201,12 +201,12 @@ o suddivisa.
<text name="objects_available" left="214" width="230" >
[COUNT] dei [MAX] ([AVAILABLE] dsponibili)
</text>
- <string name="objects_available_text">
+ <panel.string name="objects_available_text">
[COUNT] dei [MAX] ([AVAILABLE] disponibili)
- </string>
- <string name="objects_deleted_text">
+ </panel.string>
+ <panel.string name="objects_deleted_text">
[COUNT] dei [MAX] ([DELETED] saranno cancellati)
- </string>
+ </panel.string>
<text name="Primitives parcel supports:" width="200">
Oggetti che il terreno supporta:
</text>
@@ -293,109 +293,84 @@ o suddivisa.
<check_box label="Sicuro (senza danno)" name="check safe" tool_tip="Se spuntato, imposta il terreno su &apos;sicuro&apos;, disabilitando i danni da combattimento. Se non spuntato, viene abilitato il combattimento a morte."/>
<check_box label="Nessuna spinta" name="PushRestrictCheck" tool_tip="Previeni i colpi. Selezionare questa opzione può essere utile per prevenire comportamenti dannosi sul tuo terreno."/>
<check_box label="Mostra il luogo nella ricerca (30 L$/week) sotto" name="ShowDirectoryCheck" tool_tip="Lascia che questa terra sia vista dagli altri nei risultati di ricerca"/>
- <string name="search_enabled_tooltip">
+ <panel.string name="search_enabled_tooltip">
Fai in modo che la gente trovi questo terreno nei risultati della ricerca.
- </string>
- <string name="search_disabled_small_tooltip">
+ </panel.string>
+ <panel.string name="search_disabled_small_tooltip">
Questa opzione è disabilitata perchè questo terreno ha un&apos;area di 128 m² o inferiore.
Solamente terreni più grandi possono essere abilitati nella ricerca.
- </string>
- <string name="search_disabled_permissions_tooltip">
+ </panel.string>
+ <panel.string name="search_disabled_permissions_tooltip">
Questa opzione è disabilitata perchè tu non puoi modificare le opzioni di questo terreno.
- </string>
- <combo_box name="land category with adult">
- <combo_item name="AnyCategory">
- Tutte le categorie
- </combo_item>
- <combo_item name="LindenLocation">
- Luoghi Linden
- </combo_item>
- <combo_item name="Adult">
- Adult
- </combo_item>
- <combo_item name="Arts&amp;Culture">
- Arte &amp; Cultura
- </combo_item>
- <combo_item name="Business">
- Affari
- </combo_item>
- <combo_item name="Educational">
- Educazione
- </combo_item>
- <combo_item name="Gaming">
- Giochi
- </combo_item>
- <combo_item name="Hangout">
- Divertimento
- </combo_item>
- <combo_item name="NewcomerFriendly">
- Ospitalità per i nuovi entrati
- </combo_item>
- <combo_item name="Parks&amp;Nature">
- Parchi &amp; Natura
- </combo_item>
- <combo_item name="Residential">
- Residenziale
- </combo_item>
- <combo_item name="Shopping">
- Shopping
- </combo_item>
- <combo_item name="Other">
- Altro
- </combo_item>
+ </panel.string>
+ <combo_box name="land category with adult" left="282" width="140">
+ <combo_box.item name="item0" label="Tutte le categorie"
+ />
+ <combo_box.item name="item1" label="Luogo dei Linden"
+ />
+ <combo_box.item name="item2" label="Adult"
+ />
+ <combo_box.item name="item3" label="Arte &amp; Cultura"
+ />
+ <combo_box.item name="item4" label="Affari"
+ />
+ <combo_box.item name="item5" label="Educazione"
+ />
+ <combo_box.item name="item6" label="Gioco"
+ />
+ <combo_box.item name="item7" label="Divertimento"
+ />
+ <combo_box.item name="item8" label="Accoglienza nuovi residenti"
+ />
+ <combo_box.item name="item9" label="Parchi &amp; Natura"
+ />
+ <combo_box.item name="item10" label="Residenziale"
+ />
+ <combo_box.item name="item11" label="Shopping"
+ />
+ <combo_box.item name="item12" label="Altro"
+ />
</combo_box>
- <combo_box name="land category">
- <combo_item name="AnyCategory">
- Tutte le categorie
- </combo_item>
- <combo_item name="LindenLocation">
- Luogo dei Linden
- </combo_item>
- <combo_item name="Arts&amp;Culture">
- Arte &amp; Cultura
- </combo_item>
- <combo_item name="Business">
- Affari
- </combo_item>
- <combo_item name="Educational">
- Educazione
- </combo_item>
- <combo_item name="Gaming">
- Gioco
- </combo_item>
- <combo_item name="Hangout">
- Divertimento
- </combo_item>
- <combo_item name="NewcomerFriendly">
- Accoglienza nuovi residenti
- </combo_item>
- <combo_item name="Parks&amp;Nature">
- Parchi &amp; Natura
- </combo_item>
- <combo_item name="Residential">
- Residenziale
- </combo_item>
- <combo_item name="Shopping">
- Shopping
- </combo_item>
- <combo_item name="Other">
- Altro
- </combo_item>
+ <combo_box name="land category" left="282" width="140">
+ <combo_box.item name="item0" label="Tutte le categorie"
+ />
+ <combo_box.item name="item1" label="Luogo dei Linden"
+ />
+ <combo_box.item name="item3" label="Arte &amp; Cultura"
+ />
+ <combo_box.item name="item4" label="Affari"
+ />
+ <combo_box.item name="item5" label="Educazione"
+ />
+ <combo_box.item name="item6" label="Gioco"
+ />
+ <combo_box.item name="item7" label="Divertimento"
+ />
+ <combo_box.item name="item8" label="Accoglienza nuovi residenti"
+ />
+ <combo_box.item name="item9" label="Parchi &amp; Natura"
+ />
+ <combo_box.item name="item10" label="Residenziale"
+ />
+ <combo_box.item name="item11" label="Shopping"
+ />
+ <combo_box.item name="item12" label="Altro"
+ />
</combo_box>
- <button label="?" label_selected="?" name="?"/>
+ <button label="?" label_selected="?" name="?" left="427"/>
<check_box label="Contenuto Mature" name="MatureCheck" tool_tip=" "/>
- <string name="mature_check_mature">
+ <panel.string name="mature_check_mature">
Contenuto Mature
- </string>
- <string name="mature_check_adult">
+ </panel.string>
+ <panel.string name="mature_check_adult">
Contenuto Adult
- </string>
- <string name="mature_check_mature_tooltip">
+ </panel.string>
+ <panel.string name="mature_check_mature_tooltip">
Il contenuto o le informazioni del tuo terreno sono considerate Mature.
- </string>
- <string name="mature_check_adult_tooltip">
+ </panel.string>
+ <panel.string name="mature_check_adult_tooltip">
Il contenuto o le informazioni del tuo terreno sono considerate Adult.
- </string>
+ </panel.string>
<text name="Snapshot:">
Fotografia:
</text>
@@ -403,31 +378,28 @@ Solamente terreni più grandi possono essere abilitati nella ricerca.
<text name="landing_point">
Punto di atterraggio: [LANDING]
</text>
- <string name="landing_point_none">
+ <panel.string name="landing_point_none">
(nessuno)
- </string>
+ </panel.string>
<button width="60" label="Imposta" label_selected="Imposta" name="Set" tool_tip="Imposta il punto di atterraggio dove arrivano i visitatori. Impostalo nel punto dove si trova il tuo avatar in questo terreno."/>
<button width="60" left="301" label="Elimina" label_selected="Elimina" name="Clear" tool_tip="Elimina punto di atterraggio."/>
<text name="Teleport Routing: ">
Rotte dei teleport:
</text>
<combo_box width="140" name="landing type" tool_tip="Rotte dei teleport -- seleziona come vuoi organizzare i teleport nella tua terra.">
- <combo_item name="Blocked">
- Bloccati
- </combo_item>
- <combo_item name="LandingPoint">
- Punto di atterraggio
- </combo_item>
- <combo_item name="Anywhere">
- Ovunque
- </combo_item>
+ <combo_box.item name="Blocked" label="Bloccati"
+ />
+ <combo_box.item name="LandingPoint" label="Punto di atterraggio"
+ />
+ <combo_box.item name="Anywhere" label="Ovunque"
+ />
</combo_box>
- <string name="push_restrict_text">
+ <panel.string name="push_restrict_text">
Nessuna spinta
- </string>
- <string name="push_restrict_region_text">
+ </panel.string>
+ <panel.string name="push_restrict_region_text">
Nessuna spinta (Impostazione regionale)
- </string>
+ </panel.string>
</panel>
<panel label="Media" name="land_media_panel">
<text name="with media:" width="85">
@@ -495,18 +467,16 @@ Media:
</text>
<check_box label="Che non hanno dato le proprie informazioni di pagamento alla Linden Lab" name="limit_payment" tool_tip="Manda via residenti non identificati."/>
<check_box label="Che non sono adulti con età verificata" name="limit_age_verified" tool_tip="Manda via residenti che non hanno verificato la loro età. Guarda il sito support.secondlife.com per ulteriori informazioni."/>
- <string name="estate_override">
+ <panel.string name="estate_override">
Una o più di queste impostazioni sono già impostate a livello regionale
- </string>
+ </panel.string>
<check_box label="Permetti accesso al gruppo: [GROUP]" name="GroupCheck" tool_tip="Imposta il gruppo nel pannello generale."/>
<check_box label="Vendi pass a:" name="PassCheck" tool_tip="Permetti in questo terreno l&apos;accesso temporaneo"/>
<combo_box name="pass_combo">
- <combo_item name="Anyone">
- Chiunque
- </combo_item>
- <combo_item name="Group">
- Gruppo
- </combo_item>
+ <combo_box.item name="Anyone" label="Chiunque"
+ />
+ <combo_box.item name="Group" label="Gruppo"
+ />
</combo_box>
<spinner label="Prezzo in L$:" name="PriceSpin"/>
<spinner label="Ore di accesso:" name="HoursSpin"/>
diff --git a/indra/newview/skins/default/xui/it/floater_animation_preview.xml b/indra/newview/skins/default/xui/it/floater_animation_preview.xml
index 90b6dfe899..b6d6148afb 100644
--- a/indra/newview/skins/default/xui/it/floater_animation_preview.xml
+++ b/indra/newview/skins/default/xui/it/floater_animation_preview.xml
@@ -6,144 +6,71 @@
<text name="description_label">
Descrizione:
</text>
- <spinner label="Priorità" name="priority" tool_tip="Controlla quali altre animazioni possono essere annullate da questa animazione."/>
+ <spinner label_width="72" width="110" label="Priorità" name="priority" tool_tip="Controlla quali altre animazioni possono essere annullate da questa animazione."/>
<check_box label="Ciclica" name="loop_check" tool_tip="Rende questa animazione ciclica."/>
<spinner label="In(%)" name="loop_in_point" tool_tip="Imposta il punto nell&apos;animazione in cui ritornare dopo ogni ciclo."/>
<spinner label="Out(%)" name="loop_out_point" tool_tip="Imposta il punto nell&apos;animazione in cui terminare dopo ogni ciclo."/>
<text name="hand_label">
Postura della mano
</text>
- <combo_box label="" name="hand_pose_combo" tool_tip="Controlla cosa fanno le mani durante l&apos;animazione.">
- <combo_item name="Spread">
- Aperte
- </combo_item>
- <combo_item name="Relaxed">
- Rilassate
- </combo_item>
- <combo_item name="PointBoth">
- Entrambe indicano
- </combo_item>
- <combo_item name="Fist">
- Pugno
- </combo_item>
- <combo_item name="RelaxedLeft">
- Sinistra Rilassata
- </combo_item>
- <combo_item name="PointLeft">
- Sinistra Indica
- </combo_item>
- <combo_item name="FistLeft">
- Sinistra a pugno
- </combo_item>
- <combo_item name="RelaxedRight">
- Destra rilassata
- </combo_item>
- <combo_item name="PointRight">
- Destra Indica
- </combo_item>
- <combo_item name="FistRight">
- Destra a Pugno
- </combo_item>
- <combo_item name="SaluteRight">
- Destra Saluta
- </combo_item>
- <combo_item name="Typing">
- Digitano
- </combo_item>
- <combo_item name="PeaceRight">
- Destra &apos;segno di pace&apos;
- </combo_item>
+ <combo_box left_delta="100" width="184" name="hand_pose_combo" tool_tip="Controlla cosa fanno le mani durante l&apos;animazione.">
+ <combo_box.item name="Spread" label="Aperte"/>
+ <combo_box.item name="Relaxed" label="Rilassate"/>
+ <combo_box.item name="PointBoth" label="Entrambe indicano"/>
+ <combo_box.item name="Fist" label="Pugno"/>
+ <combo_box.item name="RelaxedLeft" label="Sinistra Rilassata"/>
+ <combo_box.item name="PointLeft" label="Sinistra Indica"/>
+ <combo_box.item name="FistLeft" label="Sinistra a pugno"/>
+ <combo_box.item name="RelaxedRight" label="Destra rilassata"/>
+ <combo_box.item name="PointRight" label="Destra Indica"/>
+ <combo_box.item name="FistRight" label="Destra a Pugno"/>
+ <combo_box.item name="SaluteRight" label="Destra Saluta"/>
+ <combo_box.item name="Typing" label="Digitano"/>
+ <combo_box.item name="PeaceRight" label="Destra &apos;segno di pace&apos;"/>
</combo_box>
<text name="emote_label">
Espressione
</text>
- <combo_box label="" name="emote_combo" tool_tip="Controlla l&apos;espressione del viso durante l&apos;animazione.">
- <combo_item name="[None]">
- [None]
- </combo_item>
- <combo_item name="Aaaaah">
- Aaaaah
- </combo_item>
- <combo_item name="Afraid">
- Paura
- </combo_item>
- <combo_item name="Angry">
- Rabbia
- </combo_item>
- <combo_item name="BigSmile">
- Sorriso Aperto
- </combo_item>
- <combo_item name="Bored">
- Noia
- </combo_item>
- <combo_item name="Cry">
- Pianto
- </combo_item>
- <combo_item name="Disdain">
- Sdegno
- </combo_item>
- <combo_item name="Embarrassed">
- Imbarazzo
- </combo_item>
- <combo_item name="Frown">
- Accigliato
- </combo_item>
- <combo_item name="Kiss">
- Bacio
- </combo_item>
- <combo_item name="Laugh">
- Risata
- </combo_item>
- <combo_item name="Plllppt">
- Linguaccia
- </combo_item>
- <combo_item name="Repulsed">
- Repulsione
- </combo_item>
- <combo_item name="Sad">
- Tristezza
- </combo_item>
- <combo_item name="Shrug">
- Spallucce
- </combo_item>
- <combo_item name="Smile">
- Sorriso
- </combo_item>
- <combo_item name="Surprise">
- Sorpresa
- </combo_item>
- <combo_item name="Wink">
- Ammiccamento
- </combo_item>
- <combo_item name="Worry">
- Preoccupazione
- </combo_item>
+ <combo_box left_delta="100" width="184" name="emote_combo" tool_tip="Controlla l&apos;espressione del viso durante l&apos;animazione.">
+ <combo_box.item name="[None]" label="None]"/>
+ <combo_box.item name="Aaaaah" label="Aaaaah"/>
+ <combo_box.item name="Afraid" label="Paura"/>
+ <combo_box.item name="Angry" label="Rabbia"/>
+ <combo_box.item name="BigSmile" label="Sorriso Aperto"/>
+ <combo_box.item name="Bored" label="Noia"/>
+ <combo_box.item name="Cry" label="Pianto"/>
+ <combo_box.item name="Disdain" label="Sdegno"/>
+ <combo_box.item name="Embarrassed" label="Imbarazzo"/>
+ <combo_box.item name="Frown" label="Accigliato"/>
+ <combo_box.item name="Kiss" label="Bacio"/>
+ <combo_box.item name="Laugh" label="Risata"/>
+ <combo_box.item name="Plllppt" label="Linguaccia"/>
+ <combo_box.item name="Repulsed" label="Repulsione"/>
+ <combo_box.item name="Sad" label="Tristezza"/>
+ <combo_box.item name="Shrug" label="Spallucce"/>
+ <combo_box.item name="Smile" label="Sorriso"/>
+ <combo_box.item name="Surprise" label="Sorpresa"/>
+ <combo_box.item name="Wink" label="Ammiccamento"/>
+ <combo_box.item name="Worry" label="Preoccupazione"/>
</combo_box>
- <text name="preview_label">
+ <text name="preview_label" width="250">
Vedi anteprima mentre
</text>
- <combo_box label="" name="preview_base_anim" tool_tip="Da usarsi per controllare il comportamento dell&apos;animazione mentre l&apos;avatar svolge azioni abituali.">
- <combo_item name="Standing">
- In piedi
- </combo_item>
- <combo_item name="Walking">
- Passeggia
- </combo_item>
- <combo_item name="Sitting">
- Siede
- </combo_item>
- <combo_item name="Flying">
- Vola
- </combo_item>
+ <combo_box left_delta="154" width="130" name="preview_base_anim" tool_tip="Da usarsi per controllare il comportamento dell&apos;animazione mentre l&apos;avatar svolge azioni abituali.">
+ <combo_box.item name="Standing" label="In piedi"/>
+ <combo_box.item name="Walking" label="Passeggia"/>
+ <combo_box.item name="Sitting" label="Siede"/>
+ <combo_box.item name="Flying" label="Vola"/>
</combo_box>
- <spinner label="Avvio lento (sec)" name="ease_in_time" tool_tip="Tempo (in secondi) in cui le animazioni iniziano a sfumare."/>
- <spinner label="Arresto lento (sec)" name="ease_out_time" tool_tip="Tempo (in secondi) in cui le animazioni iniziano a sfumare."/>
- <button label="" name="play_btn" tool_tip="Attiva/sospendi l&apos;animazione."/>
+ <spinner label_width="125" width="192" label="Avvio lento (sec)" name="ease_in_time" tool_tip="Tempo (in secondi) in cui le animazioni iniziano a sfumare."/>
+ <spinner bottom_delta="-20" label_width="125" left="10" width="192" label="Arresto lento (sec)" name="ease_out_time" tool_tip="Tempo (in secondi) in cui le animazioni iniziano a sfumare."/>
+ <button bottom_delta="-32" name="play_btn" tool_tip="Attiva/sospendi l&apos;animazione."/>
<button label="" name="stop_btn" tool_tip="Ferma la riproduzione dell&apos;animazione"/>
<text name="bad_animation_text">
Impossibile leggere il file dell&apos;animazione.
-Raccomandiamo file di tipo BVH esportati da Poser 4.
+Raccomandiamo file di tipo BVH esportati da
+Poser 4.
</text>
<button label="Annulla" name="cancel_btn"/>
<button label="Importa ([AMOUNT]L$)" name="ok_btn"/>
diff --git a/indra/newview/skins/default/xui/it/floater_auction.xml b/indra/newview/skins/default/xui/it/floater_auction.xml
index edbb9ab9a9..bba76a83cc 100644
--- a/indra/newview/skins/default/xui/it/floater_auction.xml
+++ b/indra/newview/skins/default/xui/it/floater_auction.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_auction" title="Inizia a vendere terra Linden">
+<floater name="floater_auction" title="INIZIA A VENDERE TERRA LINDEN">
<check_box label="Includi barriere di selezione gialle" name="fence_check"/>
<button label="Fotografia" label_selected="Fotografia" name="snapshot_btn"/>
<button label="OK" label_selected="OK" name="ok_btn"/>
diff --git a/indra/newview/skins/default/xui/it/floater_avatar_picker.xml b/indra/newview/skins/default/xui/it/floater_avatar_picker.xml
index 4e63c3b7d6..89a61eeca8 100644
--- a/indra/newview/skins/default/xui/it/floater_avatar_picker.xml
+++ b/indra/newview/skins/default/xui/it/floater_avatar_picker.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="avatarpicker" title="Scegli residente">
+<floater name="avatarpicker" title="SCEGLI RESIDENTE">
<tab_container name="ResidentChooserTabs">
<panel label="Cerca" name="SearchPanel">
<text name="InstructSearchResidentName">
@@ -14,13 +14,15 @@
</panel>
<panel label="Vicino a me" name="NearMePanel">
<text name="InstructSelectResident">
- Seleziona un residente nelle vicinanze:
+ Seleziona un residente
+nelle vicinanze:
</text>
- <button label="Aggiorna la lista" label_selected="Aggiorna l&apos;elenco" name="Refresh"/>
- <slider label="Range" name="near_me_range"/>
+ <button font="SansSerifSmall" left_delta="6" width="110" label="Aggiorna la lista" label_selected="Aggiorna l&apos;elenco" name="Refresh"/>
+ <slider label="Range" name="near_me_range" bottom_delta="-36"/>
<text name="meters">
Metri
</text>
+ <scroll_list bottom_delta="-169" height="159" name="NearMe" />
</panel>
</tab_container>
<button label="Seleziona" label_selected="Seleziona" name="Select"/>
diff --git a/indra/newview/skins/default/xui/it/floater_avatar_textures.xml b/indra/newview/skins/default/xui/it/floater_avatar_textures.xml
index 281f436224..f55b23af35 100644
--- a/indra/newview/skins/default/xui/it/floater_avatar_textures.xml
+++ b/indra/newview/skins/default/xui/it/floater_avatar_textures.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="avatar_texture_debug" title="Texture dell&apos;Avatar">
+<floater name="avatar_texture_debug" title="TEXTURE DELL&apos;AVATAR">
<text name="baked_label">
Texture Visualizzate
</text>
diff --git a/indra/newview/skins/default/xui/it/floater_beacons.xml b/indra/newview/skins/default/xui/it/floater_beacons.xml
index 035b073729..126c03e855 100644
--- a/indra/newview/skins/default/xui/it/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/it/floater_beacons.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="beacons" title="Segnali luminosi">
+<floater name="beacons" title="SEGNALI LUMINOSI">
<panel name="beacons_panel">
<check_box label="Oggetti scriptati con solo &apos;tocca&apos; abilitato" name="touch_only"/>
<check_box label="Oggetti scriptati" name="scripted"/>
diff --git a/indra/newview/skins/default/xui/it/floater_build_options.xml b/indra/newview/skins/default/xui/it/floater_build_options.xml
index 340d70851c..c6ee0f7917 100644
--- a/indra/newview/skins/default/xui/it/floater_build_options.xml
+++ b/indra/newview/skins/default/xui/it/floater_build_options.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="build options floater" title="Opzioni della griglia">
- <spinner label="Unità di misura della griglia (metri)" name="GridResolution"/>
- <spinner label="Estensione della griglia (metri)" name="GridDrawSize"/>
+<floater name="build options floater" title="OPZIONI DELLA GRIGLIA">
+ <spinner label="Unità di misura della griglia (metri)" name="GridResolution" width="250" label_width="192"/>
+ <spinner label="Estensione della griglia (metri)" name="GridDrawSize" width="250" label_width="192"/>
<check_box label="Abilita sotto-unità di movimento" name="GridSubUnit"/>
<check_box label="Mostra piani d&apos;intersezione" name="GridCrossSection"/>
- <slider label="Trasparenza della griglia" name="GridOpacity"/>
+ <slider label="Trasparenza della griglia" name="GridOpacity" width="250"/>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_bulk_perms.xml b/indra/newview/skins/default/xui/it/floater_bulk_perms.xml
index 7ca57f34b3..7f5b68279e 100644
--- a/indra/newview/skins/default/xui/it/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/it/floater_bulk_perms.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterbulkperms" title="Modifica in massa i permessi del contenuto">
+<floater name="floaterbulkperms" title="MODIFICA IN MASSA I PERMESSI DEL CONTENUTO">
<text name="applyto">
Tipi di contenuto
</text>
diff --git a/indra/newview/skins/default/xui/it/floater_bumps.xml b/indra/newview/skins/default/xui/it/floater_bumps.xml
index d9ce29fa08..23fa1a41a6 100644
--- a/indra/newview/skins/default/xui/it/floater_bumps.xml
+++ b/indra/newview/skins/default/xui/it/floater_bumps.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_bumps" title="Collisioni, spinte e colpi">
+<floater name="floater_bumps" title="COLLISIONI, SPINTE E COLPI">
<string name="none_detected">
Nessuno rilevato
</string>
diff --git a/indra/newview/skins/default/xui/it/floater_buy_contents.xml b/indra/newview/skins/default/xui/it/floater_buy_contents.xml
index dce10d5493..1a6f64c07e 100644
--- a/indra/newview/skins/default/xui/it/floater_buy_contents.xml
+++ b/indra/newview/skins/default/xui/it/floater_buy_contents.xml
@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_buy_contents" title="Compra i contenuti">
+<floater name="floater_buy_contents" title="COMPRA I CONTENUTI">
<text name="contains_text">
[NAME] contiene:
</text>
<text name="buy_text">
Compra per [AMOUNT]L$ da [NAME]?
</text>
- <button label="Annulla" label_selected="Annulla" name="cancel_btn"/>
- <button label="Compra" label_selected="Compra" name="buy_btn"/>
- <check_box label="Indossa adesso l&apos;indumento" name="wear_check"/>
+ <button label="Annulla" label_selected="Annulla" name="cancel_btn" width="73"/>
+ <button label="Compra" label_selected="Compra" name="buy_btn" width="73" left_delta="-77"/>
+ <check_box label="Indossa adesso &#10;l&apos;indumento" name="wear_check" bottom="-234" left_delta="-125"/>
<string name="no_copy_text">
(non copiabile)
</string>
diff --git a/indra/newview/skins/default/xui/it/floater_buy_currency.xml b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
index aa840b4de4..8a59764251 100644
--- a/indra/newview/skins/default/xui/it/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="buy currency" title="Acquista valuta">
+<floater name="buy currency" title="ACQUISTA VALUTA">
<text name="info_buying">
Acquistando valuta:
</text>
@@ -22,14 +22,14 @@
<text name="buy_action">
[NAME] [PRICE]L$
</text>
- <text name="currency_action">
+ <text name="currency_action" width="45">
Compra
</text>
<line_editor name="currency_amt">
1234
</line_editor>
<text name="currency_est">
- L$ per circa [USD]US$
+ per circa [LOCALAMOUNT]
</text>
<text name="getting_data">
Dati in ricezione...
@@ -52,10 +52,11 @@
<text name="total_amount">
[AMT]L$
</text>
- <text name="purchase_warning_repurchase" height="48" bottom_delta="-64" right="-10">
- Confermando questa operazione si acquisterà solo
-la valuta. Per acquistare il bene, dovrai riprovare
-l&apos;operazione nuovamente.
+ <text name="currency_links">
+ [http://www.secondlife.com/my/account/payment_method_management.php?lang=it-IT payment method] | [http://www.secondlife.com/my/account/currency.php?lang=it-IT currency] | [http://www.secondlife.com/my/account/exchange_rates.php?lang=it-IT exchange rate]
+ </text>
+ <text name="purchase_warning_repurchase">
+ Confermando questa operazione si acquisterà solo la valuta. Per acquistare il bene, dovrai riprovare l&apos;operazione nuovamente.
</text>
<text name="purchase_warning_notenough" bottom_delta="16">
Non stai comprando abbastanza denaro.
@@ -64,6 +65,6 @@ Devi aumentare l&apos;importo da acquistare.
<button label="Cancella" name="cancel_btn"/>
<button label="Acquista" name="buy_btn"/>
<string name="buy_currency">
- Compra [LINDENS] L$ per circa [USD] US$
+ acquistare [LINDENS]L$ per circa [LOCALAMOUNT]
</string>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_buy_land.xml b/indra/newview/skins/default/xui/it/floater_buy_land.xml
index 8697a66f86..b5d7ba0763 100644
--- a/indra/newview/skins/default/xui/it/floater_buy_land.xml
+++ b/indra/newview/skins/default/xui/it/floater_buy_land.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="buy land" title="Compra terra">
+<floater name="buy land" title="COMPRA TERRA">
<text name="region_name_label">
Regione:
</text>
@@ -18,10 +18,10 @@
<text name="estate_name_text">
(sconosciuto)
</text>
- <text name="estate_owner_label">
- Proprietario della regione
+ <text name="estate_owner_label" width="120" right="575">
+ Proprietario della regione:
</text>
- <text name="estate_owner_text">
+ <text name="estate_owner_text" left="580" width="155">
(sconosciuto)
</text>
<text name="resellable_changeable_label">
@@ -36,6 +36,7 @@
<text name="covenant_text">
Devi accettare il regolamento della regione:
</text>
+ <text left="470" name="covenant_timestamp_text"/>
<text_editor name="covenant_editor">
Attendi...
</text_editor>
@@ -74,15 +75,9 @@ venduta con gli oggetti
Solo i membri premium possono possedere terra.
</text>
<combo_box name="account_level">
- <combo_item name="US$9.95/month,billedmonthly">
- 9.95 US$/mese, addebitati mensilmente
- </combo_item>
- <combo_item name="US$7.50/month,billedquarterly">
- 7.50 US$/mese, addebitati ogni quadrimestre
- </combo_item>
- <combo_item name="US$6.00/month,billedannually">
- 6.00 US$/mese, addebitati annualmente
- </combo_item>
+ <combo_box.item name="US$9.95/month,billedmonthly" label="9.95 US$/mese, addebitati mensilmente"/>
+ <combo_box.item name="US$7.50/month,billedquarterly" label="7.50 US$/mese, addebitati ogni quadrimestre"/>
+ <combo_box.item name="US$6.00/month,billedannually" label="6.00 US$/mese, addebitati annualmente"/>
</combo_box>
<text name="land_use_action">
Aumenta il tasso di pagamento mensile delle tasse d&apos;uso della terra a 40 US$/mese.
@@ -96,10 +91,10 @@ venduta con gli oggetti
<text name="currency_reason">
Possiedi 2.100 L$.
</text>
- <text name="currency_action">
+ <text name="currency_action" width="106">
Compra ulteriori L$
</text>
- <line_editor name="currency_amt">
+ <line_editor name="currency_amt" left="174" width="80">
1000
</line_editor>
<text name="currency_est">
diff --git a/indra/newview/skins/default/xui/it/floater_buy_object.xml b/indra/newview/skins/default/xui/it/floater_buy_object.xml
index 90ff84a89c..e99d432367 100644
--- a/indra/newview/skins/default/xui/it/floater_buy_object.xml
+++ b/indra/newview/skins/default/xui/it/floater_buy_object.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="contents" title="Compra una copia dell&apos;oggetto">
+<floater name="contents" title="COMPRA UNA COPIA DELL&apos;OGGETTO">
<text name="contents_text">
e dei suoi contenuti:
</text>
diff --git a/indra/newview/skins/default/xui/it/floater_camera.xml b/indra/newview/skins/default/xui/it/floater_camera.xml
index 9655ed2211..823be8f4a1 100644
--- a/indra/newview/skins/default/xui/it/floater_camera.xml
+++ b/indra/newview/skins/default/xui/it/floater_camera.xml
@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move floater" title="">
- <string name="rotate_tooltip">
+<floater name="camera_floater" title="">
+ <floater.string name="rotate_tooltip">
Ruota la telecamera Intorno all&apos;Inquadratura
- </string>
- <string name="zoom_tooltip">
+ </floater.string>
+ <floater.string name="zoom_tooltip">
Avvicina la telecamera nell&apos;inquadratura
- </string>
- <string name="move_tooltip">
+ </floater.string>
+ <floater.string name="move_tooltip">
Muovi la telecamera su e giù e a sinistra e destra
- </string>
+ </floater.string>
+ <panel name="controls">
+ <joystick_track name="cam_track_stick" tool_tip="Muovi la telecamera su e giù e a sinistra e destra"/>
+ <joystick_zoom name="zoom" tool_tip="Avvicina la telecamera nell&apos;inquadratura"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_choose_group.xml b/indra/newview/skins/default/xui/it/floater_choose_group.xml
index 3b5fc79bd8..00f2692295 100644
--- a/indra/newview/skins/default/xui/it/floater_choose_group.xml
+++ b/indra/newview/skins/default/xui/it/floater_choose_group.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="groups" title="Gruppi">
+<floater name="groups" title="GRUPPI">
<text name="groupdesc">
Scegli un gruppo:
</text>
diff --git a/indra/newview/skins/default/xui/it/floater_color_picker.xml b/indra/newview/skins/default/xui/it/floater_color_picker.xml
index 93188c29ac..297b006e72 100644
--- a/indra/newview/skins/default/xui/it/floater_color_picker.xml
+++ b/indra/newview/skins/default/xui/it/floater_color_picker.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="ColorPicker" title="Tavolozza colori">
+<floater name="ColorPicker" title="TAVOLOZZA COLORI">
<text name="r_val_text">
Rosso:
</text>
@@ -33,6 +33,6 @@
</text>
<text name="(Drag below to save.)">
(Trascina qui sotto
- per salvare.)
+ per salvare)
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_customize.xml b/indra/newview/skins/default/xui/it/floater_customize.xml
index aeb285e743..ad6111718a 100644
--- a/indra/newview/skins/default/xui/it/floater_customize.xml
+++ b/indra/newview/skins/default/xui/it/floater_customize.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater customize" title="Aspetto fisico" width="551">
+<floater name="floater customize" title="ASPETTO FISICO" width="551">
<tab_container name="customize tab container" tab_min_width="120" width="549">
- <panel label="Parti del corpo" name="body_parts_placeholder"/>
+ <placeholder label="Parti del corpo" name="body_parts_placeholder"/>
<panel label="Forma del corpo" name="Shape" left="124" width="389">
<button font="SansSerifSmall" width="120" left="267" label="Annulla le modifiche" label_selected="Annulla le modifiche" name="Revert"/>
<button label="Corpo" label_selected="Corpo" name="Body"/>
@@ -14,12 +14,8 @@
<button label="Torso" label_selected="Torso" name="Torso"/>
<button label="Gambe" label_selected="Gambe" name="Legs"/>
<radio_group name="sex radio">
- <radio_item name="radio">
- Femmina
- </radio_item>
- <radio_item name="radio2">
- Maschio
- </radio_item>
+ <radio_item name="radio" label="Femmina" />
+ <radio_item name="radio2" label="Maschio" />
</radio_group>
<text name="title">
[DESC]
diff --git a/indra/newview/skins/default/xui/it/floater_day_cycle_options.xml b/indra/newview/skins/default/xui/it/floater_day_cycle_options.xml
index cac43c9b8a..7d50e322c0 100644
--- a/indra/newview/skins/default/xui/it/floater_day_cycle_options.xml
+++ b/indra/newview/skins/default/xui/it/floater_day_cycle_options.xml
@@ -1,34 +1,34 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Day Cycle Floater" title="Editor delle ciclo giorno/notte">
+<floater name="Day Cycle Floater" title="EDITOR DELLE CICLO GIORNO/NOTTE">
<tab_container name="Day Cycle Tabs">
<panel label="Ciclo giorno/notte" name="Day Cycle">
<button label="?" name="WLDayCycleHelp"/>
<text name="WL12am">
- 12
+ 0:00
</text>
<text name="WL3am">
- 3
+ 3:00
</text>
<text name="WL6am">
- 6
+ 6:00
</text>
<text name="WL9amHash">
- 9
+ 9:00
</text>
<text name="WL12pmHash">
- 24
+ 12:00
</text>
<text name="WL3pm">
- 15
+ 15:00
</text>
<text name="WL6pm">
- 18
+ 18:00
</text>
<text name="WL9pm">
- 21
+ 21:00
</text>
<text name="WL12am2">
- 12
+ 24:00
</text>
<text name="WL12amHash">
|
@@ -57,9 +57,9 @@
<text name="WL12amHash2">
|
</text>
- <button label="Aggiungi voce" label_selected="Aggiungi voce" name="WLAddKey"/>
- <button label="Cancella voce" label_selected="Cancella voce" name="WLDeleteKey"/>
- <text name="WLCurKeyFrameText">
+ <button font="SansSerifSmall" width="96" left="546" label="Aggiungi voce" label_selected="Aggiungi voce" name="WLAddKey"/>
+ <button font="SansSerifSmall" width="96" left="546" label="Cancella voce" label_selected="Cancella voce" name="WLDeleteKey"/>
+ <text name="WLCurKeyFrameText" width="210" left="17">
Impostazioni del fotogramma chiave:
</text>
<text name="WLCurKeyTimeText">
@@ -84,9 +84,9 @@
<text name="DayCycleText3">
Anteprima:
</text>
- <button label="Avvia" label_selected="Avvia" name="WLAnimSky"/>
- <button label="Arresta!" label_selected="Arresta" name="WLStopAnimSky"/>
- <button label="Usa l&apos;ora della proprietà" label_selected="Vai all&apos;ora della proprietà" name="WLUseLindenTime"/>
+ <button width="55" font="SansSerifSmall" label="Avvia" label_selected="Avvia" name="WLAnimSky"/>
+ <button width="55" left_delta="60" font="SansSerifSmall" label="Arresta!" label_selected="Arresta" name="WLStopAnimSky"/>
+ <button left_delta="60" width="150" font="SansSerifSmall" label="Usa l&apos;ora della proprietà" label_selected="Vai all&apos;ora della proprietà" name="WLUseLindenTime"/>
<button label="Salva il test del giorno" label_selected="Salva il test del giorno" name="WLSaveDayCycle"/>
<button label="Carica il test del giorno" label_selected="Carica il test del giorno" name="WLLoadDayCycle"/>
</panel>
diff --git a/indra/newview/skins/default/xui/it/floater_device_settings.xml b/indra/newview/skins/default/xui/it/floater_device_settings.xml
index cbf965bf93..932978809d 100644
--- a/indra/newview/skins/default/xui/it/floater_device_settings.xml
+++ b/indra/newview/skins/default/xui/it/floater_device_settings.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_device_settings" title="Impostazioni dispositivi Voice Chat"/>
+<floater name="floater_device_settings" title="IMPOSTAZIONI DISPOSITIVI VOICE CHAT"/>
diff --git a/indra/newview/skins/default/xui/it/floater_env_settings.xml b/indra/newview/skins/default/xui/it/floater_env_settings.xml
index 58fbff5dc9..32858d18cd 100644
--- a/indra/newview/skins/default/xui/it/floater_env_settings.xml
+++ b/indra/newview/skins/default/xui/it/floater_env_settings.xml
@@ -1,22 +1,26 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Environment Editor Floater" title="Editor dell&apos;ambiente">
+<floater name="Environment Editor Floater" title="EDITOR DELL&apos;AMBIENTE">
<text name="EnvTimeText">
- Ora del giorno
+ Ora del
+giorno
</text>
<text name="EnvTimeText2">
12:00 PM
</text>
<text name="EnvCloudText">
- Intensità delle Nuvole
+ Intensità delle
+Nuvole
</text>
<text name="EnvWaterColorText">
- Colore dell&apos;Acqua
+ Colore
+dell&apos;Acqua
</text>
<color_swatch label="" name="EnvWaterColor" tool_tip="Clicca per aprire la tavolozza dei colori"/>
<text name="EnvWaterFogText">
- Nebbiosità dell&apos;acqua
+ Nebbiosità
+dell&apos;acqua
</text>
- <button label="Usa orario della regione" name="EnvUseEstateTimeButton"/>
+ <button bottom="-144" label="Usa orario della regione" name="EnvUseEstateTimeButton" width="145"/>
<button label="Cielo avanzato" name="EnvAdvancedSkyButton"/>
<button label="Acqua avanzata" name="EnvAdvancedWaterButton"/>
<button label="?" name="EnvSettingsHelpButton"/>
diff --git a/indra/newview/skins/default/xui/it/floater_font_test.xml b/indra/newview/skins/default/xui/it/floater_font_test.xml
index 27b87a931d..859c068b11 100644
--- a/indra/newview/skins/default/xui/it/floater_font_test.xml
+++ b/indra/newview/skins/default/xui/it/floater_font_test.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="contents" title="Tipo di carattere per test">
+<floater name="contents" title="TIPO DI CARATTERE PER TEST">
<text name="linea">
OverrideTest, dovrebbe apparire qui come Times. (Dal default/xui/en-us)
</text>
diff --git a/indra/newview/skins/default/xui/it/floater_gesture.xml b/indra/newview/skins/default/xui/it/floater_gesture.xml
index 27008e97a1..91b7381d13 100644
--- a/indra/newview/skins/default/xui/it/floater_gesture.xml
+++ b/indra/newview/skins/default/xui/it/floater_gesture.xml
@@ -1,12 +1,13 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="gestures" title="Gesture attive">
+<floater name="gestures" title="GESTURE ATTIVE">
<text name="help_label">
- Fai doppio click su una gesture per azionare animazioni e suoni.
+ Fai doppio click su una gesture per azionare animazioni
+e suoni.
</text>
- <scroll_list name="gesture_list">
- <column label="Frase scatenante" name="trigger"/>
- <column label="Pulsante" name="shortcut"/>
- <column label="Nome" name="name"/>
+ <scroll_list bottom_delta="-385" height="360" name="gesture_list">
+ <column label="Frase scatenante" name="trigger" width="106"/>
+ <column label="Pulsante" name="shortcut" width="65"/>
+ <column label="Nome" name="name" width="129"/>
</scroll_list>
<button label="Nuova" name="new_gesture_btn"/>
<button label="Modifica" name="edit_btn"/>
diff --git a/indra/newview/skins/default/xui/it/floater_hardware_settings.xml b/indra/newview/skins/default/xui/it/floater_hardware_settings.xml
index b3179dc534..cdf3e970a6 100644
--- a/indra/newview/skins/default/xui/it/floater_hardware_settings.xml
+++ b/indra/newview/skins/default/xui/it/floater_hardware_settings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Hardware Settings Floater" title="Impostazioni Hardware">
+<floater name="Hardware Settings Floater" title="IMPOSTAZIONI HARDWARE">
<text name="Filtering:">
Filtraggio:
</text>
@@ -7,32 +7,22 @@
<text name="Antialiasing:">
Antialiasing:
</text>
- <combo_box label="Antialiasing" name="fsaa">
- <combo_item name="FSAADisabled">
- Disattivato
- </combo_item>
- <combo_item name="2x">
- 2x
- </combo_item>
- <combo_item name="4x">
- 4x
- </combo_item>
- <combo_item name="8x">
- 8x
- </combo_item>
- <combo_item name="16x">
- 16x
- </combo_item>
+ <combo_box label="Antialiasing" name="fsaa" width="94">
+ <combo_box.item name="FSAADisabled" label="Disattivato"/>
+ <combo_box.item name="2x" label="2x"/>
+ <combo_box.item name="4x" label="4x"/>
+ <combo_box.item name="8x" label="8x"/>
+ <combo_box.item name="16x" label="16x"/>
</combo_box>
<spinner label="Gamma:" name="gamma"/>
<text name="(brightness, lower is brighter)">
- (luminosità, più basso = più luminoso, 0=default)
+ (Luminosità, più basso = più luminoso, 0=default)
</text>
<text name="Enable VBO:">
Attiva VBO:
</text>
<check_box label="Attiva oggetti OpenGL Vertex Buffer" name="vbo" tool_tip="Attivandolo su un hardware moderno aumenta la performance. Ma, su un vecchio hardware, spesso l&apos;implementazione dei VBO è scarsa e potresti avere dei crash quando è attivato."/>
<slider label="Memoria Texture (MB):" name="GrapicsCardTextureMemory" tool_tip="Quantità di memoria allocata per le texture. Impostata di default sulla memoria della scheda grafica. Ridurla può aumentare la performance, ma può anche rendere le texture sfocate."/>
- <spinner label="Indice della distanza della nebbia:" name="fog"/>
+ <spinner label="Indice della distanza &#10;della nebbia:" name="fog"/>
<button label="OK" label_selected="OK" name="OK"/>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_hud.xml b/indra/newview/skins/default/xui/it/floater_hud.xml
index d31bcedf05..e458913452 100644
--- a/indra/newview/skins/default/xui/it/floater_hud.xml
+++ b/indra/newview/skins/default/xui/it/floater_hud.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_hud" title="Tutorial"/>
+<floater name="floater_hud" title="TUTORIAL"/>
diff --git a/indra/newview/skins/default/xui/it/floater_image_preview.xml b/indra/newview/skins/default/xui/it/floater_image_preview.xml
index 74796a5400..8ee3181bce 100644
--- a/indra/newview/skins/default/xui/it/floater_image_preview.xml
+++ b/indra/newview/skins/default/xui/it/floater_image_preview.xml
@@ -7,39 +7,20 @@
Descrizione:
</text>
<text name="preview_label">
- Anteprima dell&apos;immagine come:
+ Anteprima dell&apos;
+immagine come:
</text>
- <combo_box label="Tipo d&apos;abito" name="clothing_type_combo">
- <combo_item name="Image">
- Immagine
- </combo_item>
- <combo_item name="Hair">
- Capelli
- </combo_item>
- <combo_item name="FemaleHead">
- Testa femminile
- </combo_item>
- <combo_item name="FemaleUpperBody">
- Corpo femminile superiore
- </combo_item>
- <combo_item name="FemaleLowerBody">
- Corpo femminile inferiore
- </combo_item>
- <combo_item name="MaleHead">
- Testa maschile
- </combo_item>
- <combo_item name="MaleUpperBody">
- Corpo maschile superiore
- </combo_item>
- <combo_item name="MaleLowerBody">
- Corpo maschile inferiore
- </combo_item>
- <combo_item name="Skirt">
- Gonna
- </combo_item>
- <combo_item name="SculptedPrim">
- Oggetto sculpt
- </combo_item>
+ <combo_box label="Tipo d&apos;abito" name="clothing_type_combo" left="120" width="166">
+ <combo_box.item name="Image" label="Immagine"/>
+ <combo_box.item name="Hair" label="Capelli"/>
+ <combo_box.item name="FemaleHead" label="Testa femminile"/>
+ <combo_box.item name="FemaleUpperBody" label="Corpo femminile superiore"/>
+ <combo_box.item name="FemaleLowerBody" label="Corpo femminile inferiore"/>
+ <combo_box.item name="MaleHead" label="Testa maschile"/>
+ <combo_box.item name="MaleUpperBody" label="Corpo maschile superiore"/>
+ <combo_box.item name="MaleLowerBody" label="Corpo maschile inferiore"/>
+ <combo_box.item name="Skirt" label="Gonna"/>
+ <combo_box.item name="SculptedPrim" label="Oggetto sculpt"/>
</combo_box>
<text name="bad_image_text">
Non è stato possibile leggere l&apos;immagine.
diff --git a/indra/newview/skins/default/xui/it/floater_inspect.xml b/indra/newview/skins/default/xui/it/floater_inspect.xml
index cbf2935c77..1a4e6c3c1b 100644
--- a/indra/newview/skins/default/xui/it/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/it/floater_inspect.xml
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="inspect" title="Ispeziona oggetti">
+<floater name="inspect" title="ISPEZIONA OGGETTI" min_width="450">
<scroll_list name="object_list" tool_tip="Seleziona un oggetto da questo elenco per evidenziarlo inworld">
<column label="Nome dell&apos;oggetto" name="object_name"/>
- <column label="Nome del proprietario" name="owner_name"/>
- <column label="Nome del creatore" name="creator_name"/>
+ <column label="Proprietario" name="owner_name"/>
+ <column label="Creatore" name="creator_name"/>
<column label="Data di creazione" name="creation_date"/>
</scroll_list>
- <button label="Vedi il profilo del proprietario..." label_selected="" name="button owner" tool_tip="Vedi il profilo del proprietario dell&apos;oggetto evidenziato"/>
- <button label="Vedi il profilo del creatore..." label_selected="" name="button creator" tool_tip="Vedi il profilo del creatore originale dell&apos;oggetto evidenziato"/>
+ <button width="185" label="Vedi il profilo del proprietario..." label_selected="" name="button owner" tool_tip="Vedi il profilo del proprietario dell&apos;oggetto evidenziato"/>
+ <button width="165" left="205" label="Vedi il profilo del creatore..." label_selected="" name="button creator" tool_tip="Vedi il profilo del creatore originale dell&apos;oggetto evidenziato"/>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_inventory.xml b/indra/newview/skins/default/xui/it/floater_inventory.xml
index f21f213497..e3325463d6 100644
--- a/indra/newview/skins/default/xui/it/floater_inventory.xml
+++ b/indra/newview/skins/default/xui/it/floater_inventory.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Inventory" title="Inventario">
+<floater name="Inventory" title="INVENTARIO">
<search_editor label="Scrivi qui per cercare" name="inventory search editor"/>
<tab_container name="inventory filter tabs">
<inventory_panel label="Tutti gli elementi" name="All Items"/>
diff --git a/indra/newview/skins/default/xui/it/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/it/floater_inventory_item_properties.xml
index 6c681e7d1f..8860fd8207 100644
--- a/indra/newview/skins/default/xui/it/floater_inventory_item_properties.xml
+++ b/indra/newview/skins/default/xui/it/floater_inventory_item_properties.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="item properties" title="Proprietà dell&apos;oggetto nell&apos;inventario">
+<floater name="item properties" title="PROPRIETÀ DELL&apos;OGGETTO NELL&apos;INVENTARIO">
<text name="LabelItemNameTitle">
Nome:
</text>
@@ -30,7 +30,7 @@
Tu puoi:
</text>
<check_box label="Modificare" name="CheckOwnerModify"/>
- <check_box label="Copiare" name="CheckOwnerCopy"/>
+ <check_box left_delta="88" label="Copiare" name="CheckOwnerCopy"/>
<check_box label="Rivendere/Regalare" name="CheckOwnerTransfer"/>
<text name="BaseMaskDebug">
B:
@@ -49,23 +49,19 @@
</text>
<check_box label="Condividi con il gruppo" name="CheckShareWithGroup"/>
<check_box label="Permetti a tutti di copiare" name="CheckEveryoneCopy"/>
- <text name="NextOwnerLabel">
+ <text name="NextOwnerLabel" width="230">
Il prossimo proprietario può:
</text>
<check_box label="Modificare" name="CheckNextOwnerModify"/>
- <check_box label="Copiare" name="CheckNextOwnerCopy"/>
+ <check_box left_delta="88" label="Copiare" name="CheckNextOwnerCopy"/>
<check_box label="Rivendere/Regalare" name="CheckNextOwnerTransfer"/>
<text name="SaleLabel">
Metti l&apos;oggetto:
</text>
<check_box label="In vendita" name="CheckPurchase"/>
- <radio_group name="RadioSaleType">
- <radio_item name="radio">
- Originale
- </radio_item>
- <radio_item name="radio2">
- Copia
- </radio_item>
+ <radio_group name="RadioSaleType" left_delta="88" >
+ <radio_item name="radio" label="Originale" />
+ <radio_item name="radio2" label="Copia" />
</radio_group>
<text name="TextPrice">
Prezzo: L$
diff --git a/indra/newview/skins/default/xui/it/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/it/floater_inventory_view_finder.xml
index 935e1d7049..b5a17b2fc1 100644
--- a/indra/newview/skins/default/xui/it/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/it/floater_inventory_view_finder.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Inventory Finder" title="Inventario_Cose_recenti">
+<floater name="Inventory Finder" title="INVENTARIO_COSE_RECENTI" width="165">
<check_box label="Animazioni" name="check_animation"/>
<check_box label="Biglietti da visita" name="check_calling_card"/>
<check_box label="Abiti" name="check_clothing"/>
diff --git a/indra/newview/skins/default/xui/it/floater_joystick.xml b/indra/newview/skins/default/xui/it/floater_joystick.xml
index dcd637f199..d74ff9bfb4 100644
--- a/indra/newview/skins/default/xui/it/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/it/floater_joystick.xml
@@ -1,30 +1,23 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Joystick" title="Configurazione Joystick">
- <check_box name="enable_joystick">
- Abilita Joystick:
- </check_box>
- <spinner label="Mapping asse X" name="JoystickAxis1"/>
- <spinner label="Mapping asse Y" name="JoystickAxis2"/>
- <spinner label="Mapping asse Z" name="JoystickAxis0"/>
- <spinner label="Mapping della direzione o Pitch" name="JoystickAxis4"/>
- <spinner label="Mapping dell&apos;altitudine o Yaw" name="JoystickAxis5"/>
- <spinner label="Mapping del Roll" name="JoystickAxis3"/>
- <spinner label="Mapping dello Zoom" name="JoystickAxis6"/>
- <check_box label="Zoom diretto" name="ZoomDirect"/>
+<floater name="Joystick" title="CONFIGURAZIONE JOYSTICK">
+ <check_box name="enable_joystick" label="Abilita Joystick:"/>
+ <text left="120" name="joystick_type" width="380"/>
+ <spinner label="Mapping: asse X" name="JoystickAxis1" label_width="140" width="180" left="12"/>
+ <spinner label="Mapping: asse Y" name="JoystickAxis2" label_width="134" width="174" left="205"/>
+ <spinner label="Mapping: asse Z" name="JoystickAxis0" label_width="94" width="134" left="390"/>
+ <spinner label="Mapping: direzione o Pitch" name="JoystickAxis4" label_width="140" width="180" left="12"/>
+ <spinner label="Mapping: altitudine o Yaw" name="JoystickAxis5" label_width="134" width="174" left="205"/>
+ <spinner label="Mapping del Roll" name="JoystickAxis3" label_width="94" width="134" left="390"/>
+ <spinner label="Mapping dello Zoom" name="JoystickAxis6" label_width="140" width="180" left="12"/>
+ <check_box label="Zoom diretto" name="ZoomDirect" left="205"/>
<check_box label="Cursore 3D" name="Cursor3D"/>
<check_box label="Auto livellamento" name="AutoLeveling"/>
- <text name="Control Modes:">
+ <text name="Control Modes:" left="3" width="113">
Modalità di controllo:
</text>
- <check_box name="JoystickAvatarEnabled">
- Avatar
- </check_box>
- <check_box name="JoystickBuildEnabled">
- Costruire
- </check_box>
- <check_box name="JoystickFlycamEnabled">
- Camera dall&apos;alto
- </check_box>
+ <check_box name="JoystickAvatarEnabled" label="Avatar"/>
+ <check_box name="JoystickBuildEnabled" left="192" label="Costruire"/>
+ <check_box name="JoystickFlycamEnabled" label="Camera dall&apos;alto"/>
<text name="XScale">
Regolazione X
</text>
@@ -34,14 +27,14 @@
<text name="ZScale">
Regolazione Z
</text>
- <text name="PitchScale">
- Regolazione della direzione o Pitch
+ <text name="PitchScale" left="3" width="112">
+ Regolazione: Pitch
</text>
- <text name="YawScale">
- Regolazione dell&apos;altitudine o Yaw
+ <text name="YawScale" left="3" width="112">
+ Regolazione: Yaw
</text>
- <text name="RollScale">
- Regolazione del Roll
+ <text name="RollScale" left="3" width="112">
+ Regolazione: Roll
</text>
<text name="XDeadZone">
Angolo morto X
@@ -52,33 +45,35 @@
<text name="ZDeadZone">
Angolo morto Z
</text>
- <text name="PitchDeadZone">
- Angolo morto della direzione o Pitch
+ <text name="PitchDeadZone" left="3" width="112">
+ Angolo morto: Pitch
</text>
- <text name="YawDeadZone">
- Angolo morto dell&apos;altitudine o Yaw
+ <text name="YawDeadZone" left="3" width="112">
+ Angolo morto: Yaw
</text>
- <text name="RollDeadZone">
- Angolo morto del Roll
+ <text name="RollDeadZone" left="3" width="112">
+ Angolo morto: Roll
</text>
<text name="Feathering">
Smussamento
</text>
- <text name="ZoomScale2">
+ <text name="ZoomScale2" width="135" left="6">
Regolazione dello zoom
</text>
- <text name="ZoomDeadZone">
+ <text name="ZoomDeadZone" width="135" left="6">
Angolo morto dello zoom
</text>
<button label="SpaceNavigator Defaults" name="SpaceNavigatorDefaults"/>
<button label="OK" label_selected="OK" name="ok_btn"/>
<button label="Annulla" label_selected="Annulla" name="cancel_btn"/>
- <string name="JoystickMonitor">
- Monitor del Joystick
- </string>
- <string name="Axis">
- Assi [NUM]
- </string>
+ <stat_view label="Monitor del Joystick" name="axis_view">
+ <stat_bar label="Assi 0" name="axis0"/>
+ <stat_bar label="Assi 1" name="axis1"/>
+ <stat_bar label="Assi 2" name="axis2"/>
+ <stat_bar label="Assi 3" name="axis3"/>
+ <stat_bar label="Assi 4" name="axis4"/>
+ <stat_bar label="Assi 5" name="axis5"/>
+ </stat_view>
<string name="NoDevice">
nessun dispositivo trovato
</string>
diff --git a/indra/newview/skins/default/xui/it/floater_lagmeter.xml b/indra/newview/skins/default/xui/it/floater_lagmeter.xml
index d14f12ea4a..5ed748da69 100644
--- a/indra/newview/skins/default/xui/it/floater_lagmeter.xml
+++ b/indra/newview/skins/default/xui/it/floater_lagmeter.xml
@@ -1,24 +1,27 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_lagmeter" title="Misuratore del lag">
+<floater name="floater_lagmeter" title="MISURATORE DEL LAG">
<button label="" label_selected="" name="client_lagmeter" tool_tip="Stato del lag del programma in locale"/>
+ <text left="30" name="client_lag_cause" right="-10" />
+ <text left="30" name="network_lag_cause" right="-10" />
+ <text left="30" name="server_lag_cause" right="-32" />
<text name="client">
Programma in locale:
</text>
- <text name="client_text">
+ <text name="client_text" left="145" font="SansSerifSmall">
Normale
</text>
<button label="" label_selected="" name="network_lagmeter" tool_tip="Stato del lag del network"/>
<text name="network">
Network:
</text>
- <text name="network_text">
+ <text name="network_text" font="SansSerifSmall">
Normale
</text>
<button label="" label_selected="" name="server_lagmeter" tool_tip="Stato del lag del server"/>
<text name="server">
Server:
</text>
- <text name="server_text">
+ <text name="server_text" font="SansSerifSmall">
Normale
</text>
<button label="?" name="server_help"/>
@@ -48,10 +51,10 @@
Normale, finestra sullo sfondo
</string>
<string name="client_frame_time_critical_msg">
- Velocità dei frame del programma in locale al di sotto di [CLIENT_FRAME_RATE_CRITICAL]
+ Velocità dei frame al di sotto di [CLIENT_FRAME_RATE_CRITICAL]
</string>
<string name="client_frame_time_warning_msg">
- Velocità dei frame del programma in locale tra [CLIENT_FRAME_RATE_CRITICAL] e [CLIENT_FRAME_RATE_WARNING]
+ Velocità dei frame tra [CLIENT_FRAME_RATE_CRITICAL] e [CLIENT_FRAME_RATE_WARNING]
</string>
<string name="client_frame_time_normal_msg">
Normale
@@ -117,10 +120,10 @@
20
</string>
<string name="server_frame_time_critical_msg">
- Velocità del simulatore al di sotto di [SERVER_FRAME_RATE_CRITICAL]
+ Velocità dei frame al di sotto di [SERVER_FRAME_RATE_CRITICAL]
</string>
<string name="server_frame_time_warning_msg">
- Velocità del simulatore tra [SERVER_FRAME_RATE_CRITICAL] e [SERVER_FRAME_RATE_WARNING]
+ Velocità dei frame tra [SERVER_FRAME_RATE_CRITICAL] e [SERVER_FRAME_RATE_WARNING]
</string>
<string name="server_frame_time_normal_msg">
Normale
diff --git a/indra/newview/skins/default/xui/it/floater_land_holdings.xml b/indra/newview/skins/default/xui/it/floater_land_holdings.xml
index 6ac84b854f..8a6689f6af 100644
--- a/indra/newview/skins/default/xui/it/floater_land_holdings.xml
+++ b/indra/newview/skins/default/xui/it/floater_land_holdings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="land holdings floater" title="Il mio terreno">
+<floater name="land holdings floater" title="IL MIO TERRENO">
<scroll_list name="parcel list">
<column label="Nome del terreno" name="name"/>
<column label="Regione" name="location"/>
@@ -7,7 +7,7 @@
<column label="Area" name="area"/>
</scroll_list>
<button label="Teletrasportati" label_selected="Teletrasportati" name="Teleport" tool_tip="Teletrasportati al centro di questo terreno."/>
- <button label="Mostra sulla mappa" label_selected="Mostra sulla mappa" name="Show on Map" tool_tip="Mostra questo terreno sulla mappa."/>
+ <button width="130" label="Mostra sulla mappa" label_selected="Mostra sulla mappa" name="Show on Map" tool_tip="Mostra questo terreno sulla mappa."/>
<text name="contrib_label">
Contributi ai tuoi gruppi:
</text>
@@ -19,21 +19,21 @@
Proprietà di terreni consentite per l&apos;attuale piano di pagamento:
</text>
<text name="allowed_text">
- [AREA] metri quadrati
+ [AREA] m²
</text>
<text name="current_label">
Attuale proprietà di terreni:
</text>
<text name="current_text">
- [AREA] metri quadrati
+ [AREA] m²
</text>
<text name="available_label">
Quantità disponibile per ulteriori acquisti di terreno:
</text>
<text name="available_text">
- [AREA] metri quadrati
+ [AREA] m²
</text>
<string name="area_string">
- [AREA] metri quadrati
+ [AREA] m²
</string>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/it/floater_live_lsleditor.xml
index 55195a00f1..bd50ad3df7 100644
--- a/indra/newview/skins/default/xui/it/floater_live_lsleditor.xml
+++ b/indra/newview/skins/default/xui/it/floater_live_lsleditor.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="script ed float" title="Script: Nuovo script">
+<floater name="script ed float" title="SCRIPT: NUOVO SCRIPT">
<button label="Ripristina" label_selected="Ripristina" name="Reset"/>
- <check_box label="In esecuzione" name="running"/>
- <check_box label="Mono" name="mono"/>
+ <check_box label="In esecuzione" name="running" left="4"/>
+ <check_box label="Mono" name="mono" left="106"/>
<string name="not_allowed">
Non sei autorizzato a visualizzare questo script.
</string>
diff --git a/indra/newview/skins/default/xui/it/floater_lsl_guide.xml b/indra/newview/skins/default/xui/it/floater_lsl_guide.xml
index 6a27703ad6..4241a32ec1 100644
--- a/indra/newview/skins/default/xui/it/floater_lsl_guide.xml
+++ b/indra/newview/skins/default/xui/it/floater_lsl_guide.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="script ed float" title="LSL Wiki">
+<floater name="script ed float" title="LSL WIKI">
<check_box label="Segui il cursore" name="lock_check"/>
- <combo_box label="Blocca" name="history_combo"/>
- <button label="Indietro" name="back_btn"/>
+ <combo_box label="Blocca" name="history_combo" left_delta="120" width="70"/>
+ <button label="Indietro" name="back_btn" left_delta="75"/>
<button label="Avanti" name="fwd_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_map.xml b/indra/newview/skins/default/xui/it/floater_map.xml
new file mode 100644
index 0000000000..ec4bd4ef4a
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/floater_map.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Map">
+ <floater.string name="mini_map_north">
+ N
+ </floater.string>
+ <floater.string name="mini_map_east">
+ E
+ </floater.string>
+ <floater.string name="mini_map_west">
+ O
+ </floater.string>
+ <floater.string name="mini_map_south">
+ S
+ </floater.string>
+ <floater.string name="mini_map_southeast">
+ SE
+ </floater.string>
+ <floater.string name="mini_map_northeast">
+ NE
+ </floater.string>
+ <floater.string name="mini_map_southwest">
+ SO
+ </floater.string>
+ <floater.string name="mini_map_northwest">
+ NO
+ </floater.string>
+ <text label="N" name="floater_map_north" text="N">
+ N
+ </text>
+ <text label="E" name="floater_map_east" text="E">
+ E
+ </text>
+ <text label="O" name="floater_map_west" text="O">
+ O
+ </text>
+ <text label="S" name="floater_map_south" text="S">
+ S
+ </text>
+ <text label="SE" name="floater_map_southeast" text="SE">
+ SE
+ </text>
+ <text label="NE" name="floater_map_northeast" text="NE">
+ NE
+ </text>
+ <text label="SO" name="floater_map_southwest" text="SO">
+ SO
+ </text>
+ <text label="NO" name="floater_map_northwest" text="NO">
+ NO
+ </text>
+</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_media_browser.xml b/indra/newview/skins/default/xui/it/floater_media_browser.xml
index 1c906f5a4d..0e25cef60b 100644
--- a/indra/newview/skins/default/xui/it/floater_media_browser.xml
+++ b/indra/newview/skins/default/xui/it/floater_media_browser.xml
@@ -1,11 +1,18 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_about" title="Browser multimediale">
+<floater name="floater_about" title="BROWSER MULTIMEDIALE">
+ <floater.string name="home_page_url">
+ http://it.secondlife.com
+ </floater.string>
+ <floater.string name="support_page_url">
+ http://it.secondlife.com/support
+ </floater.string>
<layout_stack name="stack1">
<layout_panel name="nav_controls">
- <button label="Indietro" name="back"/>
- <button label="Avanti" name="forward"/>
- <button label="Ricarica" name="reload"/>
- <button label="Vai" name="go"/>
+ <button label="Indietro" name="back" width="75"/>
+ <button label="Avanti" name="forward" left_delta="75" width="70"/>
+ <button label="Ricarica" name="reload" left_delta="75"/>
+ <combo_box left_delta="75" name="address" width="510"/>
+ <button label="Vai" name="go" left_delta="515"/>
</layout_panel>
<layout_panel name="parcel_owner_controls">
<button label="Invia questo URL al terreno" name="assign"/>
diff --git a/indra/newview/skins/default/xui/it/floater_mem_leaking.xml b/indra/newview/skins/default/xui/it/floater_mem_leaking.xml
index 4bd0e6ae6b..d180953157 100644
--- a/indra/newview/skins/default/xui/it/floater_mem_leaking.xml
+++ b/indra/newview/skins/default/xui/it/floater_mem_leaking.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="MemLeak" title="Simulazione di perdità di memoria">
+<floater name="MemLeak" title="SIMULAZIONE DI PERDITÀ DI MEMORIA">
<spinner label="Perdità di velocità (bytes per frame):" name="leak_speed"/>
<spinner label="Memoria Persa Max (MB):" name="max_leak"/>
<text name="total_leaked_label">
diff --git a/indra/newview/skins/default/xui/it/floater_moveview.xml b/indra/newview/skins/default/xui/it/floater_moveview.xml
index 8a86947875..5bd84d48c8 100644
--- a/indra/newview/skins/default/xui/it/floater_moveview.xml
+++ b/indra/newview/skins/default/xui/it/floater_moveview.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move floater" title="">
+<floater name="move_floater">
+<panel name="panel_actions">
<button label="" label_selected="" name="turn left btn" tool_tip="Gira a sinistra"/>
<button label="" label_selected="" name="turn right btn" tool_tip="Gira a destra"/>
<button label="" label_selected="" name="move up btn" tool_tip="Salta o vola in alto"/>
@@ -8,4 +9,5 @@
<joystick_slide name="slide right btn" tool_tip="Vai a destra"/>
<joystick_turn name="forward btn" tool_tip="Vai avanti"/>
<joystick_turn name="backward btn" tool_tip="Vai indietro"/>
+</panel>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_mute_object.xml b/indra/newview/skins/default/xui/it/floater_mute_object.xml
index 4b7370bad0..a72bfe9681 100644
--- a/indra/newview/skins/default/xui/it/floater_mute_object.xml
+++ b/indra/newview/skins/default/xui/it/floater_mute_object.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="mute by name" title="Ignora l&apos;oggetto dal nome">
+<floater name="mute by name" title="IGNORA L&apos;OGGETTO DAL NOME">
<text name="message">
- Ignora per nome ha effetti sull&apos;oggetto in chat e IM, non nei suoni.
-Devi scrivere esattamente il nome dell&apos;oggetto.
+ Ignora per nome ha effetti sull&apos;oggetto in chat e IM, non
+nei suoni. Devi scrivere esattamente il nome dell&apos;oggetto.
</text>
<line_editor name="object_name">
Nome dell&apos;oggetto
</line_editor>
- <button label="Ok" name="OK"/>
+ <button label="OK" name="OK"/>
<button label="Annulla" name="Cancel"/>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_my_friends.xml b/indra/newview/skins/default/xui/it/floater_my_friends.xml
index a77b8aff80..faeba0a6d9 100644
--- a/indra/newview/skins/default/xui/it/floater_my_friends.xml
+++ b/indra/newview/skins/default/xui/it/floater_my_friends.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_my_friends" title="Contatti">
+<floater name="floater_my_friends" title="CONTATTI">
<tab_container name="friends_and_groups">
<panel label="Amici" name="friends_panel"/>
<panel label="Gruppi" name="groups_panel"/>
diff --git a/indra/newview/skins/default/xui/it/floater_openobject.xml b/indra/newview/skins/default/xui/it/floater_openobject.xml
index d04a6f3632..0c2029e18e 100644
--- a/indra/newview/skins/default/xui/it/floater_openobject.xml
+++ b/indra/newview/skins/default/xui/it/floater_openobject.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="objectcontents" title="Contenuto dell&apos;oggetto">
+<floater name="objectcontents" title="CONTENUTO DELL&apos;OGGETTO">
<text name="object_name">
[DESC]:
</text>
diff --git a/indra/newview/skins/default/xui/it/floater_pay.xml b/indra/newview/skins/default/xui/it/floater_pay.xml
index dbf374a67c..4889f97ec7 100644
--- a/indra/newview/skins/default/xui/it/floater_pay.xml
+++ b/indra/newview/skins/default/xui/it/floater_pay.xml
@@ -1,21 +1,22 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Give Money" title="">
- <button label="1 L$" label_selected="1 L$" name="fastpay 1"/>
- <button label="5 L$" label_selected="5 L$" name="fastpay 5"/>
- <button label="10 L$" label_selected="10 L$" name="fastpay 10"/>
- <button label="20 L$" label_selected="20 L$" name="fastpay 20"/>
- <button label="Paga" label_selected="Paga" name="pay btn"/>
- <button label="Annulla" label_selected="Annulla" name="cancel btn"/>
- <text name="payee_label">
+ <button label="1 L$" label_selected="1 L$" name="fastpay 1" left="118" width="80" />
+ <button label="5 L$" label_selected="5 L$" name="fastpay 5" left="210"/>
+ <button label="10 L$" label_selected="10 L$" name="fastpay 10" left="118" width="80" />
+ <button label="20 L$" label_selected="20 L$" name="fastpay 20" left="210"/>
+ <button label="Paga" label_selected="Paga" name="pay btn" left="127"/>
+ <button label="Annulla" label_selected="Annulla" name="cancel btn" left="210"/>
+ <text name="payee_label" left="5" width="105">
Paga residente:
</text>
- <text name="payee_name">
+ <text name="payee_name" left="115">
[FIRST] [LAST]
</text>
- <text name="fastpay text">
+ <text name="fastpay text" width="110" halign="left">
Pagamento veloce:
</text>
- <text name="amount text">
+ <text name="amount text" left="4" >
Ammontare:
</text>
+ <line_editor left="70" name="amount" width="49"/>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_pay_object.xml b/indra/newview/skins/default/xui/it/floater_pay_object.xml
index 021b2d7647..c41c0ba41e 100644
--- a/indra/newview/skins/default/xui/it/floater_pay_object.xml
+++ b/indra/newview/skins/default/xui/it/floater_pay_object.xml
@@ -1,30 +1,31 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Give Money" title="">
- <text name="payee_group">
+ <text name="payee_group" width="100" halign="left">
Paga il gruppo:
</text>
- <text name="payee_resident">
+ <text name="payee_resident" width="120" halign="left">
Paga il residente:
</text>
- <text name="payee_name">
+ <text name="payee_name" left="120">
[FIRST] [LAST]
</text>
- <text name="object_name_label">
+ <text name="object_name_label" left="5" width="110" halign="left">
Mediante l&apos;oggetto:
</text>
- <text name="object_name_text">
+ <text name="object_name_text" left="120" >
...
</text>
- <text name="fastpay text">
+ <text name="fastpay text" width="115" halign="left">
Pagamento diretto:
</text>
- <text name="amount text">
+ <text name="amount text" left="5" halign="left">
Ammontare:
</text>
- <button label="1 L$" label_selected="1 L$" name="fastpay 1"/>
- <button label="5 L$" label_selected="5 L$" name="fastpay 5"/>
- <button label="10 L$" label_selected="10 L$" name="fastpay 10"/>
- <button label="20 L$" label_selected="20 L$" name="fastpay 20"/>
+ <button label="1 L$" label_selected="1 L$" name="fastpay 1" left="125" width="70"/>
+ <button label="5 L$" label_selected="5 L$" name="fastpay 5" left="200" width="70"/>
+ <button label="10 L$" label_selected="10 L$" name="fastpay 10" left="125" width="70"/>
+ <button label="20 L$" label_selected="20 L$" name="fastpay 20" left="200" width="70"/>
<button label="Paga" label_selected="Paga" name="pay btn"/>
<button label="Cancella" label_selected="Cancella" name="cancel btn"/>
+ <line_editor left="74" name="amount" width="50" />
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_perm_prefs.xml b/indra/newview/skins/default/xui/it/floater_perm_prefs.xml
index 8037481f37..46de31455b 100644
--- a/indra/newview/skins/default/xui/it/floater_perm_prefs.xml
+++ b/indra/newview/skins/default/xui/it/floater_perm_prefs.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="perm prefs" title="Permessi di base di importazione">
+<floater name="perm prefs" title="PERMESSI DI BASE DI IMPORTAZIONE">
<panel label="Permessi" name="permissions">
<button label="?" label_selected="?" name="help"/>
<check_box label="Condividi con il gruppo" name="share_with_group"/>
diff --git a/indra/newview/skins/default/xui/it/floater_post_process.xml b/indra/newview/skins/default/xui/it/floater_post_process.xml
index 226970041b..3aa8b29101 100644
--- a/indra/newview/skins/default/xui/it/floater_post_process.xml
+++ b/indra/newview/skins/default/xui/it/floater_post_process.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Post-Process Floater" title="Impostazioni di post-produzione">
+<floater name="Post-Process Floater" title="IMPOSTAZIONI DI POST-PRODUZIONE">
<tab_container name="Post-Process Tabs">
<panel label="Filtro Colore" name="wmiColorFilterPanel">
<check_box label="Abilita" name="wmiColorFilterToggle"/>
diff --git a/indra/newview/skins/default/xui/it/floater_postcard.xml b/indra/newview/skins/default/xui/it/floater_postcard.xml
index b8769f5486..5ea3b634d4 100644
--- a/indra/newview/skins/default/xui/it/floater_postcard.xml
+++ b/indra/newview/skins/default/xui/it/floater_postcard.xml
@@ -1,17 +1,21 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Postcard" title="Invia la fotografia via email">
- <text name="to_label">
+<floater name="Postcard" title="INVIA LA FOTOGRAFIA VIA EMAIL">
+ <text name="to_label" width="135">
Email del destinatario:
</text>
+ <line_editor name="to_form" left="143" width="127" />
<text name="from_label">
La tua email:
</text>
+ <line_editor name="from_form" left="143" width="127" />
<text name="name_label">
Il tuo nome:
</text>
+ <line_editor name="name_form" left="143" width="127" />
<text name="subject_label">
Soggetto:
</text>
+ <line_editor name="subject_form" left="143" width="127" />
<line_editor label="Scrivi il soggetto qui." name="subject_form"/>
<text name="msg_label">
Messaggio:
@@ -20,17 +24,17 @@
Scrivi il messaggio qui.
</text_editor>
<text name="fine_print">
- Se il tuo destinatario si registrerà in SL, riceverai il relativo bonus.
+ Se il tuo destinatario si registrerà in [SECOND_LIFE], riceverai il relativo bonus.
</text>
<button label="Annulla" name="cancel_btn"/>
<button label="Invia" name="send_btn"/>
<string name="default_subject">
- Cartolina da Second Life.
+ Cartolina da [SECOND_LIFE]
</string>
<string name="default_message">
Vieni a vedere!
</string>
<string name="upload_message">
- &quot;In spedizione...&quot;
+ In spedizione...
</string>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_preferences.xml b/indra/newview/skins/default/xui/it/floater_preferences.xml
index 726b6dd70b..172449554d 100644
--- a/indra/newview/skins/default/xui/it/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/it/floater_preferences.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Preferences" title="Preferenze">
+<floater name="Preferences" title="PREFERENZE" min_width="350" width="646">
<button label="OK" label_selected="OK" name="OK"/>
<button label="Annulla" label_selected="Annulla" name="Cancel"/>
<button label="Applica" label_selected="Applica" name="Apply"/>
<button label="Informazioni..." label_selected="Informazioni..." name="About..."/>
<button label="Aiuto" label_selected="Aiuto" name="Help"/>
+ <tab_container name="pref core" tab_width="146" width="646" />
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_preview_animation.xml b/indra/newview/skins/default/xui/it/floater_preview_animation.xml
index 95a8a96066..e9e0252613 100644
--- a/indra/newview/skins/default/xui/it/floater_preview_animation.xml
+++ b/indra/newview/skins/default/xui/it/floater_preview_animation.xml
@@ -3,6 +3,6 @@
<text name="desc txt">
Descrizione:
</text>
- <button label="Esegui inworld" label_selected="Ferma" name="Anim play btn" tool_tip="Esegui questa animazione così che altri possano vederla."/>
- <button label="Esegui localmente" label_selected="Ferma" name="Anim audition btn" tool_tip="Esegui questa animazione così che solo tu possa vederla."/>
+ <button left="20" width="131" label="Esegui inworld" label_selected="Ferma" name="Anim play btn" tool_tip="Esegui questa animazione così che altri possano vederla."/>
+ <button left="162" width="125" label="Esegui localmente" label_selected="Ferma" name="Anim audition btn" tool_tip="Esegui questa animazione così che solo tu possa vederla."/>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_preview_classified.xml b/indra/newview/skins/default/xui/it/floater_preview_classified.xml
index f78c70b1fe..5819bd37a5 100644
--- a/indra/newview/skins/default/xui/it/floater_preview_classified.xml
+++ b/indra/newview/skins/default/xui/it/floater_preview_classified.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="classified_preview" title="Informazione Riservata"/>
+<floater name="classified_preview" title="INFORMAZIONE RISERVATA"/>
diff --git a/indra/newview/skins/default/xui/it/floater_preview_event.xml b/indra/newview/skins/default/xui/it/floater_preview_event.xml
index 7cc99a9fea..dca38c363f 100644
--- a/indra/newview/skins/default/xui/it/floater_preview_event.xml
+++ b/indra/newview/skins/default/xui/it/floater_preview_event.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="event_preview" title="Informazione sull&apos;evento"/>
+<floater name="event_preview" title="INFORMAZIONE SULL&apos;EVENTO"/>
diff --git a/indra/newview/skins/default/xui/it/floater_preview_gesture.xml b/indra/newview/skins/default/xui/it/floater_preview_gesture.xml
index 2e3f20a520..60d3a7710e 100644
--- a/indra/newview/skins/default/xui/it/floater_preview_gesture.xml
+++ b/indra/newview/skins/default/xui/it/floater_preview_gesture.xml
@@ -15,15 +15,15 @@
<text name="trigger_label">
Parole chiave:
</text>
- <text name="replace_text" tool_tip="Sostituisci le parole chiave con questi termini. Per esempio, sostituire la parola chiave &apos;salve&apos; con &apos;ciao&apos; modificherà la chat &apos;Volevo solo dire salve&apos; in &apos;Volevo solo dire ciao&apos; e avvierà la gesture!">
+ <text left="208" name="replace_text" tool_tip="Sostituisci le parole chiave con questi termini. Per esempio, sostituire la parola chiave &apos;salve&apos; con &apos;ciao&apos; modificherà la chat &apos;Volevo solo dire salve&apos; in &apos;Volevo solo dire ciao&apos; e avvierà la gesture!">
Sostituisci con:
</text>
<line_editor name="replace_editor" tool_tip="Sostituisci le parole chiave con questi termini. Per esempio, sostituire la parola chiave &apos;salve&apos; con &apos;ciao&apos; modificherà la chat &apos;Volevo solo dire salve&apos; in &apos;Volevo solo dire ciao&apos; e avvierà la gesture!"/>
<text name="key_label">
Scorciatoia da tastiera:
</text>
- <combo_box label="Nessuno" name="modifier_combo"/>
- <combo_box label="Nessuno" name="key_combo"/>
+ <combo_box label="Nessuno" name="modifier_combo" left="156" width="76"/>
+ <combo_box label="Nessuno" name="key_combo" width="76" left_delta="80"/>
<text name="library_label">
Libreria:
</text>
@@ -46,15 +46,12 @@ simultaneamente, a meno che tu
non aggiunga pause.
</text>
<radio_group name="animation_trigger_type">
- <radio_item name="start">
- Avvio
- </radio_item>
- <radio_item name="stop">
- Stop
- </radio_item>
+ <radio_item name="start" label="Avvio" />
+ <radio_item name="stop" label="Stop" />
</radio_group>
- <check_box label="finché le animazioni sono eseguite" name="wait_anim_check"/>
+ <check_box left="226" label="finché le animazioni sono eseguite" name="wait_anim_check"/>
<check_box label="tempo in secondi" name="wait_time_check"/>
+ <line_editor left_delta="114" name="wait_time_editor" />
<check_box label="Attiva" name="active_check" tool_tip="Le gesture attivate possono essere eseguite scrivendo in chat la parola chiave o premendo i tasti chiave. Le gesture generalmente si disattivano quando c&apos;è un conflitto nei relativi tasti."/>
<button label="Anteprima" name="preview_btn"/>
<button label="Salva" name="save_btn"/>
diff --git a/indra/newview/skins/default/xui/it/floater_preview_notecard.xml b/indra/newview/skins/default/xui/it/floater_preview_notecard.xml
index b0608c8546..81a51223b0 100644
--- a/indra/newview/skins/default/xui/it/floater_preview_notecard.xml
+++ b/indra/newview/skins/default/xui/it/floater_preview_notecard.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="preview notecard" title="Nota:">
+<floater name="preview notecard" title="NOTA:">
<button label="Salva" label_selected="Salva" name="Save"/>
<text name="desc txt">
Descrizione:
diff --git a/indra/newview/skins/default/xui/it/floater_region_info.xml b/indra/newview/skins/default/xui/it/floater_region_info.xml
index a802550bf4..a715cf1f06 100644
--- a/indra/newview/skins/default/xui/it/floater_region_info.xml
+++ b/indra/newview/skins/default/xui/it/floater_region_info.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="regioninfo" title="Regione/Proprietà"/>
+<floater name="regioninfo" title="REGIONE/PROPRIETÀ"/>
diff --git a/indra/newview/skins/default/xui/it/floater_report_abuse.xml b/indra/newview/skins/default/xui/it/floater_report_abuse.xml
index 99165da253..4b969354fe 100644
--- a/indra/newview/skins/default/xui/it/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/it/floater_report_abuse.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_report_abuse" title="Denuncia di Abuso">
+<floater name="floater_report_abuse" title="DENUNCIA DI ABUSO">
<check_box label="Includi una fotografia" name="screen_check"/>
<text name="reporter_title">
Segnalato da:
@@ -36,123 +36,45 @@
Hendrerit Vulputate
</text>
<combo_box name="category_combo" tool_tip="Categoria -- scegli la categoria che descrive meglio questa segnalazione">
- <combo_item name="Select_category">
- Scegli la categoria
- </combo_item>
- <combo_item name="Age__Age_play">
- Età &gt; Far finta di essere minore
- </combo_item>
- <combo_item name="Age__Adult_resident_on_Teen_Second_Life">
- Età &gt; Residente adulto nella Teen Second Life
- </combo_item>
- <combo_item name="Age__Underage_resident_outside_of_Teen_Second_Life">
- Età &gt; Residente minorenne al di fuori della &apos;Second Life per Teenager&apos;
- </combo_item>
- <combo_item name="Assault__Combat_sandbox___unsafe_area">
- Assalto &gt; sandbox da combattimento / area pericolosa
- </combo_item>
- <combo_item name="Assault__Safe_area">
- Assalto &gt; Area sicura
- </combo_item>
- <combo_item name="Assault__Weapons_testing_sandbox">
- Assalto &gt; Test di armi in sandbox
- </combo_item>
- <combo_item name="Commerce__Failure_to_deliver_product_or_service">
- Commercio &gt; Problema nella consegna di un prodotto o servizio
- </combo_item>
- <combo_item name="Disclosure__Real_world_information">
- Divulgazione &gt; Informazioni del mondo reale
- </combo_item>
- <combo_item name="Disclosure__Remotely_monitoring chat">
- Divulgazione &gt; Monitoraggio remoto di chat
- </combo_item>
- <combo_item name="Disclosure__Second_Life_information_chat_IMs">
- Divulgazione &gt; Informazione/chat/IMs di Second Life
- </combo_item>
- <combo_item name="Disturbing_the_peace__Unfair_use_of_region_resources">
- Disturbo della quiete &gt; Uso sleale delle risorse di una regione
- </combo_item>
- <combo_item name="Disturbing_the_peace__Excessive_scripted_objects">
- Disturbo della quiete &gt; Numero eccessivo di oggetti scriptati
- </combo_item>
- <combo_item name="Disturbing_the_peace__Object_littering">
- Disturbo della quiete &gt; Oggetti messi a soqquadro
- </combo_item>
- <combo_item name="Disturbing_the_peace__Repetitive_spam">
- Disturbo della quiete &gt; Spam continuato
- </combo_item>
- <combo_item name="Disturbing_the_peace__Unwanted_advert_spam">
- Disturbo della quiete &gt; Spam pubblicitario non richiesto
- </combo_item>
- <combo_item name="Fraud__L$">
- Truffa &gt; L$
- </combo_item>
- <combo_item name="Fraud__Land">
- Truffa &gt; Terreno
- </combo_item>
- <combo_item name="Fraud__Pyramid_scheme_or_chain_letter">
- Truffa &gt; Multilivello o catena di Sant&apos;Antonio
- </combo_item>
- <combo_item name="Fraud__US$">
- Truffa &gt; Dollari US$
- </combo_item>
- <combo_item name="Harassment__Advert_farms___visual_spam">
- Molestie &gt; Territori adibiti a pubblicità / spam visivo
- </combo_item>
- <combo_item name="Harassment__Defaming_individuals_or_groups">
- Molestie &gt; Diffamazione di individui o gruppi
- </combo_item>
- <combo_item name="Harassment__Impeding_movement">
- Molestie &gt; Impedimento di movimenti
- </combo_item>
- <combo_item name="Harassment__Sexual_harassment">
- Molestie &gt; Molestie sessuali
- </combo_item>
- <combo_item name="Harassment__Solicting_inciting_others_to_violate_ToS">
- Molestie &gt; Sollecitare/incitare altri a violare i Termini di Servizio
- </combo_item>
- <combo_item name="Harassment__Verbal_abuse">
- Molestie &gt; Abusi verbali
- </combo_item>
- <combo_item name="Indecency__Broadly_offensive_content_or_conduct">
- Indecenza &gt; Condotta o contenuti largamente offensivi
- </combo_item>
- <combo_item name="Indecency__Inappropriate_avatar_name">
- Indecenza &gt; Nome di un avatar inappropriato
- </combo_item>
- <combo_item name="Indecency__Mature_content_in_PG_region">
- Indecenza &gt; Contenuto o condotta inappropriata in una regione PG
- </combo_item>
- <combo_item name="Indecency__Inappropriate_content_in_Mature_region">
- Indecenza &gt; Contenuto o condotta inappropriata in una regione Mature
- </combo_item>
- <combo_item name="Intellectual_property_infringement_Content_Removal">
- Violazione della proprietà intellettuale &gt; Rimozione contenuti
- </combo_item>
- <combo_item name="Intellectual_property_infringement_CopyBot_or_Permissions_Exploit">
- Violazione della proprietà intellettuale &gt; CopyBot o sblocco di permessi
- </combo_item>
- <combo_item name="Intolerance">
- Intolleranza
- </combo_item>
- <combo_item name="Land__Abuse_of_sandbox_resources">
- Terreno &gt; Abuso delle risorse di una sandbox
- </combo_item>
- <combo_item name="Land__Encroachment__Objects_textures">
- Terreno &gt; Invasione &gt; Oggetti/textures
- </combo_item>
- <combo_item name="Land__Encroachment__Particles">
- Terreno &gt; Invasione &gt; Particelle
- </combo_item>
- <combo_item name="Land__Encroachment__Trees_plants">
- Terreno &gt; Invasione &gt; Alberi/piante
- </combo_item>
- <combo_item name="Wagering_gambling">
- Chiedere l&apos;elemosina/gioco d&apos;azzardo
- </combo_item>
- <combo_item name="Other">
- Altro
- </combo_item>
+ <combo_box.item name="Select_category" label="Scegli la categoria"/>
+ <combo_box.item name="Age__Age_play" label="Età &gt; Far finta di essere minore"/>
+ <combo_box.item name="Age__Adult_resident_on_Teen_Second_Life" label="Età &gt; Residente adulto nella Teen Second Life"/>
+ <combo_box.item name="Age__Underage_resident_outside_of_Teen_Second_Life" label="Età &gt; Residente minorenne al di fuori della &apos;Second Life per Teenager&apos;"/>
+ <combo_box.item name="Assault__Combat_sandbox___unsafe_area" label="Assalto &gt; sandbox da combattimento / area pericolosa"/>
+ <combo_box.item name="Assault__Safe_area" label="Assalto &gt; Area sicura"/>
+ <combo_box.item name="Assault__Weapons_testing_sandbox" label="Assalto &gt; Test di armi in sandbox"/>
+ <combo_box.item name="Commerce__Failure_to_deliver_product_or_service" label="Commercio &gt; Problema nella consegna di un prodotto o servizio"/>
+ <combo_box.item name="Disclosure__Real_world_information" label="Divulgazione &gt; Informazioni del mondo reale"/>
+ <combo_box.item name="Disclosure__Remotely_monitoring chat" label="Divulgazione &gt; Monitoraggio remoto di chat"/>
+ <combo_box.item name="Disclosure__Second_Life_information_chat_IMs" label="Divulgazione &gt; Informazione/chat/IMs di Second Life"/>
+ <combo_box.item name="Disturbing_the_peace__Unfair_use_of_region_resources" label="Disturbo della quiete &gt; Uso sleale delle risorse di una regione"/>
+ <combo_box.item name="Disturbing_the_peace__Excessive_scripted_objects" label="Disturbo della quiete &gt; Numero eccessivo di oggetti scriptati"/>
+ <combo_box.item name="Disturbing_the_peace__Object_littering" label="Disturbo della quiete &gt; Oggetti messi a soqquadro"/>
+ <combo_box.item name="Disturbing_the_peace__Repetitive_spam" label="Disturbo della quiete &gt; Spam continuato"/>
+ <combo_box.item name="Disturbing_the_peace__Unwanted_advert_spam" label="Disturbo della quiete &gt; Spam pubblicitario non richiesto"/>
+ <combo_box.item name="Fraud__L$" label="Truffa &gt; L$"/>
+ <combo_box.item name="Fraud__Land" label="Truffa &gt; Terreno"/>
+ <combo_box.item name="Fraud__Pyramid_scheme_or_chain_letter" label="Truffa &gt; Multilivello o catena di Sant&apos;Antonio"/>
+ <combo_box.item name="Fraud__US$" label="Truffa &gt; Dollari US$"/>
+ <combo_box.item name="Harassment__Advert_farms___visual_spam" label="Molestie &gt; Territori adibiti a pubblicità / spam visivo"/>
+ <combo_box.item name="Harassment__Defaming_individuals_or_groups" label="Molestie &gt; Diffamazione di individui o gruppi"/>
+ <combo_box.item name="Harassment__Impeding_movement" label="Molestie &gt; Impedimento di movimenti"/>
+ <combo_box.item name="Harassment__Sexual_harassment" label="Molestie &gt; Molestie sessuali"/>
+ <combo_box.item name="Harassment__Solicting_inciting_others_to_violate_ToS" label="Molestie &gt; Sollecitare/incitare altri a violare i Termini di Servizio"/>
+ <combo_box.item name="Harassment__Verbal_abuse" label="Molestie &gt; Abusi verbali"/>
+ <combo_box.item name="Indecency__Broadly_offensive_content_or_conduct" label="Indecenza &gt; Condotta o contenuti largamente offensivi"/>
+ <combo_box.item name="Indecency__Inappropriate_avatar_name" label="Indecenza &gt; Nome di un avatar inappropriato"/>
+ <combo_box.item name="Indecency__Mature_content_in_PG_region" label="Indecenza &gt; Contenuto o condotta inappropriata in una regione PG"/>
+ <combo_box.item name="Indecency__Inappropriate_content_in_Mature_region" label="Indecenza &gt; Contenuto o condotta inappropriata in una regione Mature"/>
+ <combo_box.item name="Intellectual_property_infringement_Content_Removal" label="Violazione della proprietà intellettuale &gt; Rimozione contenuti"/>
+ <combo_box.item name="Intellectual_property_infringement_CopyBot_or_Permissions_Exploit" label="Violazione della proprietà intellettuale &gt; CopyBot o sblocco di permessi"/>
+ <combo_box.item name="Intolerance" label="Intolleranza"/>
+ <combo_box.item name="Land__Abuse_of_sandbox_resources" label="Terreno &gt; Abuso delle risorse di una sandbox"/>
+ <combo_box.item name="Land__Encroachment__Objects_textures" label="Terreno &gt; Invasione &gt; Oggetti/textures"/>
+ <combo_box.item name="Land__Encroachment__Particles" label="Terreno &gt; Invasione &gt; Particelle"/>
+ <combo_box.item name="Land__Encroachment__Trees_plants" label="Terreno &gt; Invasione &gt; Alberi/piante"/>
+ <combo_box.item name="Wagering_gambling" label="Chiedere l&apos;elemosina/gioco d&apos;azzardo"/>
+ <combo_box.item name="Other" label="Altro"/>
</combo_box>
<text name="abuser_name_title">
Nome di chi ha commesso l&apos;abuso:
@@ -169,8 +91,9 @@
Dettagli:
</text>
<text name="bug_aviso">
- Ti preghiamo di essere circostanziato riguardo data, luogo, natura
-dell&apos;abuso, testo rilevante di chat/IM, e, se possibile, indica l&apos;oggetto.
+ Ti preghiamo di essere circostanziato riguardo data,
+luogo, natura dell&apos;abuso, testo rilevante di chat/IM, e,
+se possibile, indica l&apos;oggetto.
</text>
<text name="incomplete_title">
Nota: Segnalazioni incomplete non saranno esaminate.
diff --git a/indra/newview/skins/default/xui/it/floater_script_debug.xml b/indra/newview/skins/default/xui/it/floater_script_debug.xml
index 39736dde67..89bf80da5e 100644
--- a/indra/newview/skins/default/xui/it/floater_script_debug.xml
+++ b/indra/newview/skins/default/xui/it/floater_script_debug.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<multi_floater name="script debug floater" title="Avvisi/Errori Script">
<tab_container name="Preview Tabs">
- <floater label="Script" name="all_scripts" title="[Tutti gli script]"/>
+ <floater label="Script" name="all_scripts" title="[ALL SCRIPTS]"/>
</tab_container>
</multi_floater>
diff --git a/indra/newview/skins/default/xui/it/floater_script_preview.xml b/indra/newview/skins/default/xui/it/floater_script_preview.xml
index 20af60b2d4..934ffd5395 100644
--- a/indra/newview/skins/default/xui/it/floater_script_preview.xml
+++ b/indra/newview/skins/default/xui/it/floater_script_preview.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="preview lsl text" title="Script: Script di rotazione">
+<floater name="preview lsl text" title="SCRIPT: SCRIPT DI ROTAZIONE">
<text name="desc txt">
Descrizione:
</text>
diff --git a/indra/newview/skins/default/xui/it/floater_script_queue.xml b/indra/newview/skins/default/xui/it/floater_script_queue.xml
index e5b38fea62..37eb3e4bbf 100644
--- a/indra/newview/skins/default/xui/it/floater_script_queue.xml
+++ b/indra/newview/skins/default/xui/it/floater_script_queue.xml
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="queue" title="Progressione reset">
+<floater name="queue" title="PROGRESSIONE RESET">
<button label="Chiudi" label_selected="Chiudi" name="close"/>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_script_search.xml b/indra/newview/skins/default/xui/it/floater_script_search.xml
index ebd8ee359f..e5f923f7a3 100644
--- a/indra/newview/skins/default/xui/it/floater_script_search.xml
+++ b/indra/newview/skins/default/xui/it/floater_script_search.xml
@@ -1,13 +1,15 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="script search" title="Cerca Script">
- <check_box label="Senza distinzione tra maiuscole e minuscole" name="case_text"/>
- <button label="Cerca" label_selected="Cerca" name="search_btn"/>
- <button label="Sostituisci" label_selected="Sostituisci" name="replace_btn"/>
- <button label="Sostituisci tutto" label_selected="Sostituisci tutto" name="replace_all_btn"/>
- <text name="txt">
+<floater name="script search" title="CERCA SCRIPT" width="320">
+ <check_box label="Senza distinzione tra maiuscole e minuscole" name="case_text" left="65"/>
+ <button label="Cerca" label_selected="Cerca" name="search_btn" width="85"/>
+ <button label="Sostituisci" label_selected="Sostituisci" name="replace_btn" left="100" width="85"/>
+ <button label="Sostituisci tutto" label_selected="Sostituisci tutto" name="replace_all_btn" left="190" width="122"/>
+ <text name="txt" width="60">
Cerca
</text>
- <text name="txt2">
+ <text name="txt2" width="60">
Sostituisci
</text>
+ <line_editor left="65" name="search_text" width="240" />
+ <line_editor left="65" name="replace_text" width="240" />
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_sell_land.xml b/indra/newview/skins/default/xui/it/floater_sell_land.xml
index 3f47c0ef78..91712a706b 100644
--- a/indra/newview/skins/default/xui/it/floater_sell_land.xml
+++ b/indra/newview/skins/default/xui/it/floater_sell_land.xml
@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="sell land" title="Vendi terra">
+<floater name="sell land" title="VENDI TERRA">
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
<text name="info_parcel_label">
Terreno:
</text>
@@ -36,15 +38,9 @@ terreno:
Scegli se vendere a tutti o ad un compratore in particolare.
</text>
<combo_box name="sell_to">
- <combo_item name="--selectone--">
- -- selezionane uno --
- </combo_item>
- <combo_item name="Anyone">
- Chiunque
- </combo_item>
- <combo_item name="Specificuser:">
- Utente specifico:
- </combo_item>
+ <combo_box.item name="--selectone--" label="selezionane uno --"/>
+ <combo_box.item name="Anyone" label="Chiunque"/>
+ <combo_box.item name="Specificuser:" label="Utente specifico:"/>
</combo_box>
<button label="Seleziona..." name="sell_to_select_agent"/>
<text name="sell_objects_label">
@@ -55,12 +51,8 @@ terreno:
cambieranno proprietario.
</text>
<radio_group name="sell_objects" bottom_delta="-58" >
- <radio_item name="no">
- No, voglio mantenere la proprietà degli oggetti
- </radio_item>
- <radio_item name="yes">
- Si, vendi gli oggetti con la terra
- </radio_item>
+ <radio_item name="no" label="No, voglio mantenere la proprietà degli oggetti" />
+ <radio_item name="yes" label="Si, vendi gli oggetti con la terra" />
</radio_group>
<button label="Mostra oggetti" name="show_objects"/>
<text name="nag_message_label">
@@ -68,4 +60,6 @@ cambieranno proprietario.
</text>
<button label="Metti la terra in vendita" name="sell_btn"/>
<button label="Annulla" name="cancel_btn"/>
+ </panel>
+ </scroll_container>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_settings_debug.xml b/indra/newview/skins/default/xui/it/floater_settings_debug.xml
index 9bedc69a05..aec3c8aa9d 100644
--- a/indra/newview/skins/default/xui/it/floater_settings_debug.xml
+++ b/indra/newview/skins/default/xui/it/floater_settings_debug.xml
@@ -1,17 +1,13 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="settings_debug" title="Configurazioni per il debug">
+<floater name="settings_debug" title="CONFIGURAZIONI PER IL DEBUG">
<combo_box name="boolean_combo">
- <combo_item name="TRUE">
- VERO
- </combo_item>
- <combo_item name="FALSE">
- FALSO
- </combo_item>
+ <combo_box.item name="TRUE" label="VERO"/>
+ <combo_box.item name="FALSE" label="FALSO"/>
</combo_box>
<color_swatch label="Colore" name="color_swatch"/>
<spinner label="x" name="val_spinner_1"/>
<spinner label="x" name="val_spinner_2"/>
<spinner label="x" name="val_spinner_3"/>
<spinner label="x" name="val_spinner_4"/>
- <button label="Reimposta i valori di default" name="default_btn"/>
+ <button label="Reimposta i valori di default" name="default_btn" width="210"/>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_snapshot.xml b/indra/newview/skins/default/xui/it/floater_snapshot.xml
index 7e1bc2cf5d..e226ce6ffe 100644
--- a/indra/newview/skins/default/xui/it/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/it/floater_snapshot.xml
@@ -1,18 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Snapshot" title="Anteprima della fotografia">
+<floater name="Snapshot" title="ANTEPRIMA DELLA FOTOGRAFIA" width="247">
<text name="type_label">
Destinazione della fotografia
</text>
- <radio_group label="Tipo di fotografia" name="snapshot_type_radio">
- <radio_item name="postcard">
- Invia via email
- </radio_item>
- <radio_item name="texture">
- Salva nel tuo inventario ([AMOUNT] L$)
- </radio_item>
- <radio_item name="local">
- Salva sul tuo pc
- </radio_item>
+ <radio_group label="Tipo di fotografia" name="snapshot_type_radio" width="228">
+ <radio_item name="postcard" label="Invia via email" />
+ <radio_item name="texture" label="Salva nel tuo inventario ([AMOUNT] L$)" />
+ <radio_item name="local" label="Salva sul tuo pc" />
</radio_group>
<text name="file_size_label">
Grandezza del file: [SIZE] KB
@@ -20,13 +14,9 @@
<button label="Aggiorna la fotografia" name="new_snapshot_btn"/>
<button label="Invia" name="send_btn"/>
<button label="Salva ([AMOUNT] L$)" name="upload_btn"/>
- <flyout_button label="Salva" name="save_btn" tool_tip="Salva l&apos;immagine come file">
- <flyout_button_item name="save_item">
- Salva
- </flyout_button_item>
- <flyout_button_item name="saveas_item">
- Salva come...
- </flyout_button_item>
+ <flyout_button label="Salva" name="save_btn" tool_tip="Salva l&apos;immagine come file" >
+ <flyout_button_item name="save_item" label="Salva"/>
+ <flyout_button_item name="saveas_item" label="Salva come..."/>
</flyout_button>
<button label="Annulla" name="discard_btn"/>
<button label="Espandi &gt;&gt;" name="more_btn" tool_tip="Opzioni avanzate"/>
@@ -38,99 +28,51 @@
Formato
</text>
<combo_box label="Risoluzione" name="postcard_size_combo">
- <combo_item name="CurrentWindow">
- Finestra corrente
- </combo_item>
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
- <combo_item name="Custom">
- Personalizzata
- </combo_item>
+ <combo_box.item name="CurrentWindow" label="Finestra corrente"/>
+ <combo_box.item name="640x480" label="640x480"/>
+ <combo_box.item name="800x600" label="800x600"/>
+ <combo_box.item name="1024x768" label="1024x768"/>
+ <combo_box.item name="Custom" label="Personalizzata"/>
</combo_box>
<combo_box label="Risoluzione" name="texture_size_combo">
- <combo_item name="CurrentWindow">
- Finestra corrente
- </combo_item>
- <combo_item name="Small(128x128)">
- Piccola (128x128)
- </combo_item>
- <combo_item name="Medium(256x256)">
- Media (256x256)
- </combo_item>
- <combo_item name="Large(512x512)">
- Larga (512x512)
- </combo_item>
- <combo_item name="Custom">
- Personalizzata
- </combo_item>
+ <combo_box.item name="CurrentWindow" label="Finestra corrente"/>
+ <combo_box.item name="Small(128x128)" label="Piccola (128x128)"/>
+ <combo_box.item name="Medium(256x256)" label="Media (256x256)"/>
+ <combo_box.item name="Large(512x512)" label="Larga (512x512)"/>
+ <combo_box.item name="Custom" label="Personalizzata"/>
</combo_box>
<combo_box label="Risoluzione" name="local_size_combo">
- <combo_item name="CurrentWindow">
- Finestra corrente
- </combo_item>
- <combo_item name="320x240">
- 320x240
- </combo_item>
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
- <combo_item name="1280x1024">
- 1280x1024
- </combo_item>
- <combo_item name="1600x1200">
- 1600x1200
- </combo_item>
- <combo_item name="Custom">
- Personalizzata
- </combo_item>
+ <combo_box.item name="CurrentWindow" label="Finestra corrente"/>
+ <combo_box.item name="320x240" label="320x240"/>
+ <combo_box.item name="640x480" label="640x480"/>
+ <combo_box.item name="800x600" label="800x600"/>
+ <combo_box.item name="1024x768" label="1024x768"/>
+ <combo_box.item name="1280x1024" label="1280x1024"/>
+ <combo_box.item name="1600x1200" label="1600x1200"/>
+ <combo_box.item name="Custom" label="Personalizzata"/>
</combo_box>
<combo_box label="Formato" name="local_format_combo">
- <combo_item name="PNG">
- PNG
- </combo_item>
- <combo_item name="JPEG">
- JPEG
- </combo_item>
- <combo_item name="BMP">
- BMP
- </combo_item>
+ <combo_box.item name="PNG" label="PNG"/>
+ <combo_box.item name="JPEG" label="JPEG"/>
+ <combo_box.item name="BMP" label="BMP"/>
</combo_box>
- <spinner label="Larghezza" name="snapshot_width"/>
- <spinner label="Altezza" name="snapshot_height"/>
+ <spinner label="Larghezza" name="snapshot_width" label_width="58" width="116"/>
+ <spinner label="Altezza" name="snapshot_height" label_width="41" width="101" left="130"/>
<check_box label="Mantieni le proporzioni" name="keep_aspect_check"/>
<slider label="Qualità d&apos;immagine" name="image_quality_slider"/>
- <text name="layer_type_label">
+ <text name="layer_type_label" width="55">
Fotografa:
</text>
- <combo_box label="Layer dell&apos;immagine" name="layer_types">
- <combo_item name="Colors">
- Colori
- </combo_item>
- <combo_item name="Depth">
- Profondità
- </combo_item>
- <combo_item name="ObjectMattes">
- Colori primari degli oggetti
- </combo_item>
+ <combo_box label="Layer dell&apos;immagine" name="layer_types" left="68" width="165">
+ <combo_box.item name="Colors" label="Colori"/>
+ <combo_box.item name="Depth" label="Profondità"/>
+ <combo_box.item name="ObjectMattes" label="Colori primari degli oggetti"/>
</combo_box>
<check_box label="Mostra l&apos;interfaccia nella fotografia" name="ui_check"/>
- <check_box label="Mostra i dispositivi indossati nella fotografia" name="hud_check"/>
- <check_box label="Mantieni aperto dopo aver salvato" name="keep_open_check"/>
- <check_box label="Blocca l&apos;anteprima (Anteprima a schermo intero)" name="freeze_frame_check"/>
- <check_box label="Auto-Aggiorna" name="auto_snapshot_check"/>
+ <check_box bottom_delta="-17" label="Mostra i dispositivi indossati nella foto" name="hud_check"/>
+ <check_box bottom_delta="-17" label="Mantieni aperto dopo aver salvato" name="keep_open_check"/>
+ <check_box bottom_delta="-17" label="Blocca l&apos;anteprima &#10;(Anteprima a schermo intero)" name="freeze_frame_check"/>
+ <check_box bottom_delta="-29" label="Auto-Aggiorna" name="auto_snapshot_check"/>
<string name="unknown">
sconosciuto
</string>
diff --git a/indra/newview/skins/default/xui/it/floater_sound_preview.xml b/indra/newview/skins/default/xui/it/floater_sound_preview.xml
index 8611732983..221e5e5b53 100644
--- a/indra/newview/skins/default/xui/it/floater_sound_preview.xml
+++ b/indra/newview/skins/default/xui/it/floater_sound_preview.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Sound Preview" title="sound.wav">
+<floater name="Sound Preview" title="SOUND.WAV">
<text name="name_label">
Nome:
</text>
diff --git a/indra/newview/skins/default/xui/it/floater_statistics.xml b/indra/newview/skins/default/xui/it/floater_statistics.xml
index 6083949b8c..00df1ff994 100644
--- a/indra/newview/skins/default/xui/it/floater_statistics.xml
+++ b/indra/newview/skins/default/xui/it/floater_statistics.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="stats floater" title="Statistiche"/>
+<floater name="stats floater" title="STATISTICHE"/>
diff --git a/indra/newview/skins/default/xui/it/floater_telehub.xml b/indra/newview/skins/default/xui/it/floater_telehub.xml
index 5de215522d..de5c32574f 100644
--- a/indra/newview/skins/default/xui/it/floater_telehub.xml
+++ b/indra/newview/skins/default/xui/it/floater_telehub.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="telehub" title="Telehub">
+<floater name="telehub" title="TELEHUB" min_height="310" height="310" width="286">
<text name="status_text_connected">
Telehub connesso all&apos;oggetto [OBJECT]
</text>
@@ -10,19 +10,23 @@
Per rimuovere, clicca Disconnetti.
</text>
<text name="help_text_not_connected">
- Seleziona l&apos;oggetto e clicca connetti Telehub.
+ Seleziona l&apos;oggetto e clicca Connetti Telehub.
</text>
<button label="Connetti Telehub" name="connect_btn"/>
<button label="Disconnetti" name="disconnect_btn"/>
- <text name="spawn_points_text">
+ <text name="spawn_points_text" width="265">
Rigenera i punti (posizioni, non oggetti):
</text>
- <button label="Aggiungi punti rigenerazione" name="add_spawn_point_btn"/>
- <button label="Rimuovi punti rigenerazione" name="remove_spawn_point_btn"/>
+ <scroll_list name="spawn_points_list" width="265" />
+ <button width="165" label="Aggiungi punti rigenerazione" name="add_spawn_point_btn"/>
+ <button width="105" left="175" label="Rimuovi punti" name="remove_spawn_point_btn"/>
<text name="spawn_point_help">
- Seleziona un oggetto e clicca su aggiungi per specificarne la posizione.
+ Seleziona un oggetto e clicca su aggiungi per
+specificarne la posizione.
Potrai quindi muovere o rimuovere l&apos;oggetto.
Le posizioni sono relative al centro del telehub.
-Seleziona un elemento per vederne la posizione globale.
+
+Seleziona un elemento per vederne la posizione
+globale.
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/it/floater_texture_ctrl.xml
index 65bc8ba41d..836f85b48c 100644
--- a/indra/newview/skins/default/xui/it/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/it/floater_texture_ctrl.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="texture picker" title="Preferiti: Immagine">
+<floater name="texture picker" title="PREFERITI: IMMAGINE">
<string name="choose_picture">
Clicca per scegliere l&apos;immagine
</string>
diff --git a/indra/newview/skins/default/xui/it/floater_tools.xml b/indra/newview/skins/default/xui/it/floater_tools.xml
index a89ae9d803..8e6f27e162 100644
--- a/indra/newview/skins/default/xui/it/floater_tools.xml
+++ b/indra/newview/skins/default/xui/it/floater_tools.xml
@@ -1,40 +1,43 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="toolbox floater" title="">
+<floater name="toolbox floater" title="" short_title="COSTRUISCI" width="288">
<button label="" label_selected="" name="button focus" tool_tip="Focus"/>
<button label="" label_selected="" name="button move" tool_tip="Muoviti"/>
<button label="" label_selected="" name="button edit" tool_tip="Modifica"/>
<button label="" label_selected="" name="button create" tool_tip="Crea"/>
<button label="" label_selected="" name="button land" tool_tip="Terra"/>
- <check_box label="Zoom" name="radio zoom"/>
- <check_box label="Guarda ruotando(Ctrl)" name="radio orbit"/>
- <check_box label="Guarda panoramicamente (Ctrl-Shift)" name="radio pan"/>
- <check_box label="Muovi" name="radio move"/>
- <check_box label="Alza (Ctrl)" name="radio lift"/>
- <check_box label="Gira intorno (Ctrl-Shift)" name="radio spin"/>
- <check_box label="Posizione" name="radio position"/>
- <check_box label="Ruota (Ctrl)" name="radio rotate"/>
- <check_box label="Ridimensiona (Ctrl-Shift)" name="radio stretch"/>
- <check_box label="Seleziona Texture" name="radio select face"/>
+ <radio_group name="focus_radio_group">
+ <radio_item label="Zoom" name="radio zoom"/>
+ <radio_item label="Guarda ruotando (Ctrl)" name="radio orbit"/>
+ <radio_item label="Guarda panoramicamente (Ctrl-Shift)" name="radio pan"/>
+ </radio_group>
+ <radio_group name="move_radio_group">
+ <radio_item label="Muovi" name="radio move"/>
+ <radio_item label="Alza (Ctrl)" name="radio lift"/>
+ <radio_item label="Gira intorno (Ctrl-Shift)" name="radio spin"/>
+ </radio_group>
+ <radio_group name="edit_radio_group">
+ <radio_item label="Posizione" name="radio position"/>
+ <radio_item label="Ruota (Ctrl)" name="radio rotate"/>
+ <radio_item label="Ridimensiona (Ctrl-Shift)" name="radio stretch"/>
+ <radio_item label="Seleziona Texture" name="radio select face"/>
+ </radio_group>
<check_box label="Modifica parti unite" name="checkbox edit linked parts"/>
<text name="text ruler mode">
- Modalità regolo di precisione:
+ Modalità:
</text>
- <combo_box name="combobox grid mode">
- <combo_item name="World">
- Globale
- </combo_item>
- <combo_item name="Local">
- Locale
- </combo_item>
- <combo_item name="Reference">
- Riferito a
- </combo_item>
+ <combo_box name="combobox grid mode" left_delta="48">
+ <combo_box.item name="World" label="Globale"
+ />
+ <combo_box.item name="Local" label="Locale"
+ />
+ <combo_box.item name="Reference" label="Riferito a"
+ />
</combo_box>
- <check_box label="Ridimensiona simmetricamente" name="checkbox uniform"/>
- <check_box label="Ridimensiona le Texture" name="checkbox stretch textures"/>
+ <check_box label="Ridimens. simmetricamente" name="checkbox uniform"/>
+ <check_box label="Ridimensiona le texture" name="checkbox stretch textures"/>
<check_box label="Usa righello" name="checkbox snap to grid"/>
<button label="Opzioni..." label_selected="Opzioni..." name="Options..."/>
- <text name="text status">
+ <text name="text status" width="280">
Trascina per muovere, trascina+maiuscolo per copiare
</text>
<button label="" label_selected="" name="ToolCube" tool_tip="Cubo"/>
@@ -56,30 +59,33 @@
<check_box label="Copia la selezione" name="checkbox copy selection"/>
<check_box label="Centra" name="checkbox copy centers"/>
<check_box label="Ruota" name="checkbox copy rotates"/>
- <check_box label="Seleziona il terreno" name="radio select land"/>
- <check_box label="Appiattisci" name="radio flatten"/>
- <check_box label="Eleva" name="radio raise"/>
- <check_box label="Abbassa" name="radio lower"/>
- <check_box label="Uniforma" name="radio smooth"/>
- <check_box label="Ondula" name="radio noise"/>
- <check_box label="Ripristina" name="radio revert"/>
- <button label="Applica" label_selected="Applica" name="button apply to selection" tool_tip="Modifica il terreno selezionato"/>
+ <radio_group name="land_radio_group">
+ <radio_item label="Seleziona il terreno" name="radio select land"/>
+ <radio_item label="Appiattisci" name="radio flatten"/>
+ <radio_item label="Eleva" name="radio raise"/>
+ <radio_item label="Abbassa" name="radio lower"/>
+ <radio_item label="Uniforma" name="radio smooth"/>
+ <radio_item label="Ondula" name="radio noise"/>
+ <radio_item label="Ripristina" name="radio revert"/>
+ </radio_group>
+ <button label="Applica" label_selected="Applica" name="button apply to selection" tool_tip="Modifica il terreno selezionato" left="146"/>
<text name="Bulldozer:">
Bulldozer:
</text>
<text name="Dozer Size:">
Grandezza
</text>
+ <volume_slider left="184" name="slider brush size" width="74" />
<text name="Strength:">
Potenza
</text>
- <text name="obj_count">
+ <text name="obj_count" left="134">
Oggetti selezionati: [COUNT]
</text>
- <text name="prim_count">
- primitive: [COUNT]
+ <text name="prim_count" left="134">
+ primitivi: [COUNT]
</text>
- <tab_container name="Object Info Tabs">
+ <tab_container name="Object Info Tabs" tab_max_width="150" tab_min_width="30" width="288">
<panel label="Generale" name="General">
<text name="Name:">
Nome:
@@ -111,9 +117,7 @@
<text name="Permissions:">
Permessi:
</text>
- <text name="perm_modify">
- Puoi modificare questo oggetto.
- </text>
+
<check_box label="Condividi con il gruppo" name="checkbox share with group" tool_tip="Permetti a tutti i membri del gruppo di condividere ed utilizzare i tuoi permessi per questo oggetto. Devi cederlo al gruppo per abilitare le restrizioni di ruolo."/>
<string name="text deed continued">
Cedi al gruppo...
@@ -121,7 +125,7 @@
<string name="text deed">
Cedi al gruppo
</string>
- <button label="Cedi al gruppo..." label_selected="Cedi al gruppo..." name="button deed" tool_tip="Gli oggetti condivisi con il gruppo possono essere ceduti da un funzionario del gruppo."/>
+ <button left_delta="152" width="98" label="Cedi al gruppo..." label_selected="Cedi al gruppo..." name="button deed" tool_tip="Gli oggetti condivisi con il gruppo possono essere ceduti da un funzionario del gruppo."/>
<check_box label="Permetti a chiunque di spostare" name="checkbox allow everyone move"/>
<check_box label="Permetti a chiunque di copiare" name="checkbox allow everyone copy"/>
<check_box label="Mostra nella ricerca" name="search_check" tool_tip="Permetti che l&apos;oggetto sia visibile nella ricerca"/>
@@ -129,54 +133,40 @@
<text name="Cost">
Prezzo: L$
</text>
- <radio_group name="sale type">
- <radio_item name="Original">
- Originale
- </radio_item>
- <radio_item name="Copy">
- Copia
- </radio_item>
- <radio_item name="Contents">
- Contenuto
- </radio_item>
- </radio_group>
- <text name="Next owner can:">
- Il prossimo proprietario può:
- </text>
- <check_box label="Modificare" name="checkbox next owner can modify"/>
- <check_box label="Copiare" name="checkbox next owner can copy"/>
- <check_box label="Rivendere/Regalare" name="checkbox next owner can transfer"/>
- <text name="label click action">
- Se cliccato con il tasto sinistro del mouse
- </text>
- <combo_box name="clickaction">
- <combo_item name="Touch/grab(default)">
- Tocca/Afferra (default)
- </combo_item>
- <combo_item name="Sitonobject">
- Siediti sull&apos;oggetto
- </combo_item>
- <combo_item name="Buyobject">
- Compra l&apos;oggetto
- </combo_item>
- <combo_item name="Payobject">
- Paga l&apos;oggetto
- </combo_item>
- <combo_item name="Open">
- Apri
- </combo_item>
- <combo_item name="Play">
- Attiva i multimedia del terreno
- </combo_item>
- <combo_item name="Opemmedia">
- Apri i multimedia del terreno
- </combo_item>
+ <combo_box name="sale type">
+ <combo_box.item label="Copia" name="Copy"/>
+ <combo_box.item label="Contenuto" name="Contents"/>
+ <combo_box.item label="Originale" name="Original"/>
</combo_box>
+
+ <text name="label click action" width="220">
+ Se cliccato con il tasto sinistro del mouse:
+ </text>
+ <combo_box name="clickaction" width="192">
+ <combo_box.item name="Touch/grab(default)" label="Tocca/Afferra (default)"
+ />
+ <combo_box.item name="Sitonobject" label="Siediti sull&apos;oggetto"
+ />
+ <combo_box.item name="Buyobject" label="Compra l&apos;oggetto"
+ />
+ <combo_box.item name="Payobject" label="Paga l&apos;oggetto"
+ />
+ <combo_box.item name="Open" label="Apri"
+ />
+ <combo_box.item name="Play" label="Attiva i multimedia del terreno"
+ />
+ <combo_box.item name="Opemmedia" label="Apri i multimedia del terreno"
+ />
+ </combo_box>
+ <panel name="perms_build">
+ <text name="perm_modify">
+ Puoi modificare questo oggetto
+ </text>
<text name="B:">
B:
</text>
<text name="O:">
- O;
+ O:
</text>
<text name="G:">
G:
@@ -190,29 +180,36 @@
<text name="F:">
F:
</text>
+ <text name="Next owner can:">
+ Il prossimo proprietario può:
+ </text>
+ <check_box label="Modificare" name="checkbox next owner can modify"/>
+ <check_box label="Copiare" name="checkbox next owner can copy" left_delta="80"/>
+ <check_box name="checkbox next owner can transfer" left_delta="67"/>
+ </panel>
<string name="text modify info 1">
- Puoi modificare questo oggetto.
+ Puoi modificare questo oggetto
</string>
<string name="text modify info 2">
- Puoi modificare questi oggetti.
+ Puoi modificare questi oggetti
</string>
<string name="text modify info 3">
- Non puoi modificare questo oggetto.
+ Non puoi modificare questo oggetto
</string>
<string name="text modify info 4">
- Non puoi modificare questi oggetti.
+ Non puoi modificare questi oggetti
</string>
<string name="text modify warning">
- Devi selezionare l&apos;intero oggetto per impostare i permessi.
+ Devi selezionare l&apos;intero oggetto per impostare i permessi
</string>
<string name="Cost Default">
- Prezzo: L$
+ Prezzo: L$
</string>
<string name="Cost Total">
- Prezzo totale: L$
+ Prezzo totale: L$
</string>
<string name="Cost Per Unit">
- Prezzo per: L$
+ Prezzo per: L$
</string>
<string name="Cost Mixed">
Prezzo misto
@@ -254,56 +251,41 @@
Materiale
</text>
<combo_box name="material">
- <combo_item name="Stone">
- Pietra
- </combo_item>
- <combo_item name="Metal">
- Metallo
- </combo_item>
- <combo_item name="Glass">
- Vetro
- </combo_item>
- <combo_item name="Wood">
- Legno
- </combo_item>
- <combo_item name="Flesh">
- Carne
- </combo_item>
- <combo_item name="Plastic">
- Plastica
- </combo_item>
- <combo_item name="Rubber">
- Gomma
- </combo_item>
+ <combo_box.item name="Stone" label="Pietra"
+ />
+ <combo_box.item name="Metal" label="Metallo"
+ />
+ <combo_box.item name="Glass" label="Vetro"
+ />
+ <combo_box.item name="Wood" label="Legno"
+ />
+ <combo_box.item name="Flesh" label="Carne"
+ />
+ <combo_box.item name="Plastic" label="Plastica"
+ />
+ <combo_box.item name="Rubber" label="Gomma"
+ />
</combo_box>
<text name="label basetype">
Forma di costruzione
</text>
<combo_box name="comboBaseType">
- <combo_item name="Box">
- Cubo
- </combo_item>
- <combo_item name="Cylinder">
- Cilindro
- </combo_item>
- <combo_item name="Prism">
- Prisma
- </combo_item>
- <combo_item name="Sphere">
- Sfera
- </combo_item>
- <combo_item name="Torus">
- Toro
- </combo_item>
- <combo_item name="Tube">
- Tubo
- </combo_item>
- <combo_item name="Ring">
- Anello
- </combo_item>
- <combo_item name="Sculpted">
- Sculpted
- </combo_item>
+ <combo_box.item name="Box" label="Cubo"
+ />
+ <combo_box.item name="Cylinder" label="Cilindro"
+ />
+ <combo_box.item name="Prism" label="Prisma"
+ />
+ <combo_box.item name="Sphere" label="Sfera"
+ />
+ <combo_box.item name="Torus" label="Toro"
+ />
+ <combo_box.item name="Tube" label="Tubo"
+ />
+ <combo_box.item name="Ring" label="Anello"
+ />
+ <combo_box.item name="Sculpted" label="Sculpted"
+ />
</combo_box>
<text name="text cut">
Linea di taglio Inizio e Fine
@@ -320,18 +302,14 @@
Forma del foro
</text>
<combo_box name="hole">
- <combo_item name="Default">
- Default
- </combo_item>
- <combo_item name="Circle">
- Rotondo
- </combo_item>
- <combo_item name="Square">
- Quadrato
- </combo_item>
- <combo_item name="Triangle">
- Triangolare
- </combo_item>
+ <combo_box.item name="Default" label="Default"
+ />
+ <combo_box.item name="Circle" label="Rotondo"
+ />
+ <combo_box.item name="Square" label="Quadrato"
+ />
+ <combo_box.item name="Triangle" label="Triangolare"
+ />
</combo_box>
<text name="text twist">
Torsione Inizio e Fine
@@ -351,7 +329,7 @@
</text>
<spinner label="X" name="Shear X"/>
<spinner label="Y" name="Shear Y"/>
- <text name="advanced_cut">
+ <text name="advanced_cut" width="149">
Ritaglia il profilo Inizio e Fine
</text>
<text name="advanced_dimple">
@@ -380,47 +358,42 @@
Tipo di congiunzione
</text>
<combo_box name="sculpt type control">
- <combo_item name="None">
- (nessuna)
- </combo_item>
- <combo_item name="Sphere">
- Sferica
- </combo_item>
- <combo_item name="Torus">
- Toroidale
- </combo_item>
- <combo_item name="Plane">
- Piana
- </combo_item>
- <combo_item name="Cylinder">
- Cilindrica
- </combo_item>
+ <combo_box.item name="None" label="(nessuna)"
+ />
+ <combo_box.item name="Sphere" label="Sferica"
+ />
+ <combo_box.item name="Torus" label="Toroidale"
+ />
+ <combo_box.item name="Plane" label="Piana"
+ />
+ <combo_box.item name="Cylinder" label="Cilindrica"
+ />
</combo_box>
</panel>
<panel label="Caratteristiche" name="Features">
- <text name="select_single">
+ <text name="select_single" width="280">
Seleziona solo un prim per modificarne le caratteristiche.
</text>
<text name="edit_object">
Modifica le caratteristiche dell&apos;oggetto:
</text>
<check_box label="Flessibilità" name="Flexible1D Checkbox Ctrl" tool_tip="Permette all&apos;oggetto di flettersi rispetto all&apos;asse Z. (solo lato client)"/>
- <spinner label="Morbidezza" name="FlexNumSections"/>
- <spinner label="Gravità" name="FlexGravity"/>
- <spinner label="Elasticità" name="FlexFriction"/>
- <spinner label="Sventolio" name="FlexWind"/>
- <spinner label="Tensione" name="FlexTension"/>
- <spinner label="Forza X" name="FlexForceX"/>
- <spinner label="Forza Y" name="FlexForceY"/>
- <spinner label="Forza Z" name="FlexForceZ"/>
+ <spinner label="Morbidezza" name="FlexNumSections" label_width="72" width="135"/>
+ <spinner label="Gravità" name="FlexGravity" label_width="72" width="135"/>
+ <spinner label="Elasticità" name="FlexFriction" label_width="72" width="135"/>
+ <spinner label="Sventolio" name="FlexWind" label_width="72" width="135"/>
+ <spinner label="Tensione" name="FlexTension" label_width="72" width="135"/>
+ <spinner label="Forza X" name="FlexForceX" label_width="72" width="135"/>
+ <spinner label="Forza Y" name="FlexForceY" label_width="72" width="135"/>
+ <spinner label="Forza Z" name="FlexForceZ" label_width="72" width="135"/>
<check_box label="Luce" name="Light Checkbox Ctrl" tool_tip="Imposta l&apos;oggetto come sorgente di luce"/>
<text name="label color">
Colore
</text>
<color_swatch label="" name="colorswatch" tool_tip="Clicca per aprire la tavolozza dei colori"/>
- <spinner label="Intensità" name="Light Intensity"/>
- <spinner label="Raggio" name="Light Radius"/>
- <spinner label="Attenuazione" name="Light Falloff"/>
+ <spinner label="Intensità" name="Light Intensity" label_width="72" width="135"/>
+ <spinner label="Raggio" name="Light Radius" label_width="72" width="135"/>
+ <spinner label="Attenuazione" name="Light Falloff" label_width="72" width="135" />
</panel>
<panel label="Texture" name="Texture">
<texture_picker label="Texture" name="texture control" tool_tip="Clicca per scegliere un&apos;immagine"/>
@@ -431,93 +404,69 @@
<text name="glow label">
Bagliore
</text>
- <check_box label="Massima luminosità" name="checkbox fullbright"/>
+ <check_box label="Massima &#10;luminosità" name="checkbox fullbright" bottom_delta="-21"/>
<text name="tex gen">
- Applicazione della texture
- </text>
- <combo_box name="combobox texgen">
- <combo_item name="Default">
- Default
- </combo_item>
- <combo_item name="Planar">
- Planare
- </combo_item>
+ Applicazione &#10;della texture
+ </text>
+ <combo_box name="combobox texgen" bottom_delta="-38">
+ <combo_box.item name="Default" label="Default"
+ />
+ <combo_box.item name="Planar" label="Planare"
+ />
</combo_box>
- <text name="label shininess">
+ <text name="label shininess" bottom="-120">
Brillantezza
</text>
- <combo_box name="combobox shininess">
- <combo_item name="None">
- Nessuna
- </combo_item>
- <combo_item name="Low">
- Bassa
- </combo_item>
- <combo_item name="Medium">
- Media
- </combo_item>
- <combo_item name="High">
- Alta
- </combo_item>
+ <combo_box name="combobox shininess" bottom_delta="-22">
+ <combo_box.item name="None" label="Nessuna"
+ />
+ <combo_box.item name="Low" label="Bassa"
+ />
+ <combo_box.item name="Medium" label="Media"
+ />
+ <combo_box.item name="High" label="Alta"
+ />
</combo_box>
- <text name="label bumpiness">
+ <text name="label bumpiness" bottom="-120">
Rilievo
</text>
- <combo_box name="combobox bumpiness">
- <combo_item name="None">
- Nessuna
- </combo_item>
- <combo_item name="Brightness">
- Luminoso
- </combo_item>
- <combo_item name="Darkness">
- Scuro
- </combo_item>
- <combo_item name="woodgrain">
- Venature del legno
- </combo_item>
- <combo_item name="bark">
- Corteccia
- </combo_item>
- <combo_item name="bricks">
- Mattoni
- </combo_item>
- <combo_item name="checker">
- Scacchi
- </combo_item>
- <combo_item name="concrete">
- Cemento
- </combo_item>
- <combo_item name="crustytile">
- Mattonella incrostata
- </combo_item>
- <combo_item name="cutstone">
- Mosaico in pietra
- </combo_item>
- <combo_item name="discs">
- Dischi
- </combo_item>
- <combo_item name="gravel">
- Ghiaia
- </combo_item>
- <combo_item name="petridish">
- Sassi
- </combo_item>
- <combo_item name="siding">
- Listoni
- </combo_item>
- <combo_item name="stonetile">
- Mattonelle in pietra
- </combo_item>
- <combo_item name="stucco">
- Stucco
- </combo_item>
- <combo_item name="suction">
- Cerchi rialzati
- </combo_item>
- <combo_item name="weave">
- Trama
- </combo_item>
+ <combo_box name="combobox bumpiness" width="100" bottom_delta="-22">
+ <combo_box.item name="None" label="Nessuna"
+ />
+ <combo_box.item name="Brightness" label="Luminoso"
+ />
+ <combo_box.item name="Darkness" label="Scuro"
+ />
+ <combo_box.item name="woodgrain" label="Venature del legno"
+ />
+ <combo_box.item name="bark" label="Corteccia"
+ />
+ <combo_box.item name="bricks" label="Mattoni"
+ />
+ <combo_box.item name="checker" label="Scacchi"
+ />
+ <combo_box.item name="concrete" label="Cemento"
+ />
+ <combo_box.item name="crustytile" label="Mattonella incrostata"
+ />
+ <combo_box.item name="cutstone" label="Mosaico in pietra"
+ />
+ <combo_box.item name="discs" label="Dischi"
+ />
+ <combo_box.item name="gravel" label="Ghiaia"
+ />
+ <combo_box.item name="petridish" label="Sassi"
+ />
+ <combo_box.item name="siding" label="Listoni"
+ />
+ <combo_box.item name="stonetile" label="Mattonelle in pietra"
+ />
+ <combo_box.item name="stucco" label="Stucco"
+ />
+ <combo_box.item name="suction" label="Cerchi rialzati"
+ />
+ <combo_box.item name="weave" label="Trama"
+ />
</combo_box>
<text name="tex scale">
Ripetizioni per faccia
@@ -538,7 +487,9 @@
<text name="rpt">
Ripetizioni per metro
</text>
- <button label="Applica" label_selected="Applica" name="button apply"/>
+ <spinner left="120" name="TexRot" width="60" />
+ <spinner left="120" name="rptctrl" width="60" />
+ <button label="Applica" label_selected="Applica" name="button apply" left_delta="72"/>
<text name="tex offset">
Offset
</text>
@@ -548,11 +499,12 @@
Allinea texture dei media
(deve prima caricarsi)
</text>
- <button label="Allinea" label_selected="Allinea" name="button align"/>
+ <button label="Allinea" label_selected="Allinea" name="button align" left="160"/>
</panel>
<panel label="Contenuto" name="Contents">
- <button label="Nuovo Script" label_selected="Nuovo script..." name="button new script"/>
- <button label="Permessi..." name="button permissions"/>
+ <button label="Nuovo Script" label_selected="Nuovo script" name="button new script"/>
+ <button label="Permessi" name="button permissions"/>
+ <panel name="ContentsInventory" width="272" />
</panel>
</tab_container>
<panel name="land info panel">
@@ -560,62 +512,62 @@
Informazioni sul terreno
</text>
<text name="label_area_price">
- Prezzo: [PRICE] L$ per [AREA] mq.
+ Prezzo: [PRICE] L$ per [AREA] m²
</text>
<text name="label_area">
- Area: [AREA] mq.
+ Area: [AREA] m²
</text>
- <button label="Informazioni sul terreno..." label_selected="Informazioni sul terreno..." name="button about land"/>
- <check_box label="Mostra i proprietari" name="checkbox show owners" tool_tip="Colora i terreni in base ai loro proprietari"/>
- <button label="?" label_selected="?" name="button show owners help"/>
+ <button label="Informazioni sul terreno..." label_selected="Informazioni sul terreno..." name="button about land" width="156"/>
+ <check_box label="Mostra i proprietari" name="checkbox show owners" tool_tip="Colora i terreni in base ai loro proprietari: &#10;&#10;Verde = il tuo terreno &#10;Acqua = la terra del tuo gruppo &#10;Rosso = posseduta da altri &#10;Giallo = in vendita &#10;Viola = in asta &#10;Grigia = pubblica"/>
+ <button label="?" label_selected="?" name="button show owners help" left_delta="120"/>
<text name="label_parcel_modify">
Modifica il terreno
</text>
- <button label="Suddividi..." label_selected="Suddividi..." name="button subdivide land"/>
- <button label="Unisci..." label_selected="Unisci..." name="button join land"/>
+ <button label="Suddividi" label_selected="Suddividi" name="button subdivide land" width="156"/>
+ <button label="Unisci" label_selected="Unisci" name="button join land" width="156"/>
<text name="label_parcel_trans">
Transazioni del territorio
</text>
- <button label="Acquista il terreno..." label_selected="Acquista il terreno..." name="button buy land"/>
- <button label="Abbandona il terreno..." label_selected="Abbandona il terreno..." name="button abandon land"/>
+ <button label="Acquista il terreno" label_selected="Acquista il terreno" name="button buy land" width="156"/>
+ <button label="Abbandona il terreno" label_selected="Abbandona il terreno" name="button abandon land" width="156"/>
</panel>
- <string name="status_rotate">
+ <floater.string name="status_rotate">
Sposta le fasce colorate per ruotare l&apos;oggetto
- </string>
- <string name="status_scale">
+ </floater.string>
+ <floater.string name="status_scale">
Clicca e trascina per ridimensionare il lato selezionato
- </string>
- <string name="status_move">
+ </floater.string>
+ <floater.string name="status_move">
Trascina per spostare, maiuscolo+trascina per copiare
- </string>
- <string name="status_modifyland">
+ </floater.string>
+ <floater.string name="status_modifyland">
Clicca e tieni premuto per modificare il terreno
- </string>
- <string name="status_camera">
+ </floater.string>
+ <floater.string name="status_camera">
Clicca e sposta per cambiare visuale
- </string>
- <string name="status_grab">
+ </floater.string>
+ <floater.string name="status_grab">
Trascina per muovere, Ctrl per alzare, Ctrl-Shift per ruotare
- </string>
- <string name="status_place">
+ </floater.string>
+ <floater.string name="status_place">
Clicca inworld per costruire
- </string>
- <string name="status_selectland">
+ </floater.string>
+ <floater.string name="status_selectland">
Clicca e trascina per selezionare il terreno
- </string>
- <string name="grid_screen_text">
+ </floater.string>
+ <floater.string name="grid_screen_text">
Schermo
- </string>
- <string name="grid_local_text">
+ </floater.string>
+ <floater.string name="grid_local_text">
Locale
- </string>
- <string name="grid_world_text">
+ </floater.string>
+ <floater.string name="grid_world_text">
Globale
- </string>
- <string name="grid_reference_text">
+ </floater.string>
+ <floater.string name="grid_reference_text">
Riferimento
- </string>
- <string name="grid_attachment_text">
+ </floater.string>
+ <floater.string name="grid_attachment_text">
Accessorio
- </string>
+ </floater.string>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_top_objects.xml b/indra/newview/skins/default/xui/it/floater_top_objects.xml
index ff6e9eb730..9b406199e9 100644
--- a/indra/newview/skins/default/xui/it/floater_top_objects.xml
+++ b/indra/newview/skins/default/xui/it/floater_top_objects.xml
@@ -1,33 +1,36 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="top_objects" title="In caricamento...">
+<floater name="top_objects" title="IN CARICAMENTO...">
<text name="title_text">
In caricamento...
</text>
<scroll_list name="objects_list">
- <column label="Punteggio" name="score"/>
- <column label="Nome" name="name"/>
- <column label="Proprietario" name="owner"/>
- <column label="Ubicazione" name="location"/>
- <column label="Ora" name="time"/>
- <column label="Ora (Mono)" name="mono_time"/>
+ <column label="Punteggio" name="score" width="84"/>
+ <column label="Nome" name="name" width="84"/>
+ <column label="Proprietario" name="owner" width="84"/>
+ <column label="Ubicazione" name="location" width="84"/>
+ <column label="Ora" name="time" width="84"/>
+ <column label="Ora (Mono)" name="mono_time" width="84"/>
</scroll_list>
+ <line_editor font="SansSerifSmall" left="90" name="id_editor" width="280"/>
+ <line_editor font="SansSerifSmall" left="90" name="object_name_editor" width="280"/>
+ <line_editor font="SansSerifSmall" left="90" name="owner_name_editor" width="280"/>
<text name="id_text">
ID oggetto:
</text>
- <button label="Mostra segnali luminosi" name="show_beacon_btn"/>
+ <button label="Mostra segnali luminosi" name="show_beacon_btn" width="150"/>
<text name="obj_name_text">
Nome oggetto:
</text>
- <button label="Filtro" name="filter_object_btn"/>
+ <button label="Filtro" name="filter_object_btn" width="150"/>
<text name="owner_name_text">
Nome oggetto:
</text>
- <button label="Filtro" name="filter_owner_btn"/>
- <button label="Restituisci selezionato" name="return_selected_btn"/>
- <button label="Restituisci tutti" name="return_all_btn"/>
- <button label="Disabilita selezionato" name="disable_selected_btn"/>
- <button label="Disabilita per tutti" name="disable_all_btn"/>
- <button label="Aggiorna" name="refresh_btn"/>
+ <button label="Filtro" name="filter_owner_btn" width="150"/>
+ <button label="Restituisci selezionato" name="return_selected_btn" width="150"/>
+ <button label="Restituisci tutti" name="return_all_btn" left="170"/>
+ <button label="Disabilita selezionato" name="disable_selected_btn" width="150"/>
+ <button label="Disabilita per tutti" name="disable_all_btn" left="170"/>
+ <button label="Aggiorna" name="refresh_btn" width="150"/>
<string name="top_scripts_title">
Script pesanti
</string>
diff --git a/indra/newview/skins/default/xui/it/floater_tos.xml b/indra/newview/skins/default/xui/it/floater_tos.xml
index 76dbe86ee6..12b6021b5b 100644
--- a/indra/newview/skins/default/xui/it/floater_tos.xml
+++ b/indra/newview/skins/default/xui/it/floater_tos.xml
@@ -4,7 +4,7 @@
<button label="Annulla" label_selected="Annulla" name="Cancel"/>
<check_box label="Accetto i Termini di Servizio" name="agree_chk"/>
<text name="tos_heading">
- Leggi attentamente i seguenti Termini di Servizio . Per continuare ad entrare in Second Life,
+ Leggi attentamente i seguenti Termini di Servizio. Per continuare ad entrare in [SECOND_LIFE],
devi accettare l&apos;accordo.
</text>
<text_editor name="tos_text">
diff --git a/indra/newview/skins/default/xui/it/floater_url_entry.xml b/indra/newview/skins/default/xui/it/floater_url_entry.xml
index 2968b19d80..9ad1a0dce5 100644
--- a/indra/newview/skins/default/xui/it/floater_url_entry.xml
+++ b/indra/newview/skins/default/xui/it/floater_url_entry.xml
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="url_entry" title="">
<text name="media_label">
- Media URL:
+ URL Media:
</text>
<button label="OK" name="ok_btn"/>
<button label="Annulla" name="cancel_btn"/>
- <button label="Cancella" name="clear_btn"/>
+ <button label="Elimina" name="clear_btn"/>
<text name="loading_label">
In caricamento...
</text>
diff --git a/indra/newview/skins/default/xui/it/floater_water.xml b/indra/newview/skins/default/xui/it/floater_water.xml
index 6665d97e2a..13db1d4589 100644
--- a/indra/newview/skins/default/xui/it/floater_water.xml
+++ b/indra/newview/skins/default/xui/it/floater_water.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Water Floater" title="Editor avanzato dell&apos;acqua">
- <text name="KeyFramePresetsText">
+<floater name="Water Floater" title="EDITOR AVANZATO DELL&apos;ACQUA">
+ <text name="KeyFramePresetsText" width="224">
Impostazioni predeterminate dell&apos;acqua:
</text>
+ <combo_box left_delta="230" name="WaterPresetsCombo" width="150" />
<button label="Nuovo" label_selected="Nuovo" name="WaterNewPreset"/>
<button label="Salva" label_selected="Salva" name="WaterSavePreset"/>
<button label="Cancella" label_selected="Cancella" name="WaterDeletePreset"/>
@@ -11,20 +12,21 @@
<text name="BHText">
Colore della nebbiosità dell&apos;acqua
</text>
- <button label="?" name="WaterFogColorHelp"/>
+ <button label="?" name="WaterFogColorHelp" left="209"/>
<color_swatch label="" name="WaterFogColor" tool_tip="Clicca per aprire la selezione colore"/>
- <text name="WaterFogDensText">
- Esponente di densità  della nebbia dell&apos;acqua
+ <text name="WaterFogDensText" font="SansSerifSmall">
+ Esponente di densità della nebbia&#10; dell&apos;acqua
</text>
- <button label="?" name="WaterFogDensityHelp"/>
- <text name="WaterUnderWaterFogModText">
+ <slider bottom_delta="-40" name="WaterFogDensity"/>
+ <button label="?" name="WaterFogDensityHelp" left="209"/>
+ <text name="WaterUnderWaterFogModText" font="SansSerifSmall" bottom="-140">
Regolatore effetto nebbia subacquea
</text>
- <button label="?" name="WaterUnderWaterFogModHelp"/>
+ <button label="?" name="WaterUnderWaterFogModHelp" left="209"/>
<text name="BDensText">
Scala di riflessione delle onde
</text>
- <button label="?" name="WaterNormalScaleHelp"/>
+ <button label="?" name="WaterNormalScaleHelp" left="415"/>
<text name="BHText2">
1
</text>
@@ -37,29 +39,31 @@
<text name="HDText">
Scala Fresnel
</text>
- <button label="?" name="WaterFresnelScaleHelp"/>
+ <button label="?" name="WaterFresnelScaleHelp" left="415"/>
<text name="FresnelOffsetText">
Offset Fresnel
</text>
- <button label="?" name="WaterFresnelOffsetHelp"/>
- <text name="DensMultText">
- Scala di rifrazione nell&apos;acqua dall&apos;alto
+ <button label="?" name="WaterFresnelOffsetHelp" left="415"/>
+ <text name="DensMultText" font="SansSerifSmall">
+ Scala di rifrazione nell&apos;acqua&#10; dall&apos;alto
</text>
- <button label="?" name="WaterScaleAboveHelp"/>
- <text name="WaterScaleBelowText">
- Scala di rifrazione nell&apos;acqua dal basso
+ <slider bottom_delta="-40" name="WaterScaleAbove"/>
+ <button label="?" name="WaterScaleAboveHelp" left="650"/>
+ <text name="WaterScaleBelowText" font="SansSerifSmall" bottom="-70">
+ Scala di rifrazione nell&apos;acqua&#10; dal basso
</text>
- <button label="?" name="WaterScaleBelowHelp"/>
- <text name="MaxAltText">
+ <slider bottom_delta="-40" name="WaterScaleBelow"/>
+ <button label="?" name="WaterScaleBelowHelp" left="650"/>
+ <text name="MaxAltText" bottom="-122">
Moltiplicatore della sfocatura
</text>
- <button label="?" name="WaterBlurMultiplierHelp"/>
+ <button label="?" name="WaterBlurMultiplierHelp" left="650"/>
</panel>
<panel label="Immagine" name="Waves">
<text name="BHText">
Direzione della grande onda
</text>
- <button label="?" name="WaterWave1Help"/>
+ <button label="?" name="WaterWave1Help" left="170"/>
<text name="WaterWave1DirXText">
X
</text>
@@ -69,7 +73,7 @@
<text name="BHText2">
Direzione della piccola onda
</text>
- <button label="?" name="WaterWave2Help"/>
+ <button label="?" name="WaterWave2Help" left="170"/>
<text name="WaterWave2DirXText">
X
</text>
diff --git a/indra/newview/skins/default/xui/it/floater_windlight_options.xml b/indra/newview/skins/default/xui/it/floater_windlight_options.xml
index aa99e1d883..e86d656e39 100644
--- a/indra/newview/skins/default/xui/it/floater_windlight_options.xml
+++ b/indra/newview/skins/default/xui/it/floater_windlight_options.xml
@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="WindLight floater" title="Editor avanzato del cielo">
+<floater name="WindLight floater" title="EDITOR AVANZATO DEL CIELO">
<text name="KeyFramePresetsText">
Cieli predefiniti:
</text>
<button label="Nuovo" label_selected="Nuovo" name="WLNewPreset"/>
- <button label="Salva" label_selected="Salva" name="WLSavePreset"/>
- <button label="Elimina" label_selected="Elimina" name="WLDeletePreset"/>
- <button label="Editor del ciclo giorno/notte" label_selected="Editor del ciclo giorno/notte" name="WLDayCycleMenuButton"/>
+ <button label="Salva" label_selected="Salva" name="WLSavePreset" left_delta="72"/>
+ <button label="Elimina" label_selected="Elimina" name="WLDeletePreset" left_delta="72"/>
+ <button font="SansSerifSmall" width="165" left_delta="85" label="Editor del ciclo giorno/notte" label_selected="Editor del ciclo giorno/notte" name="WLDayCycleMenuButton"/>
<tab_container name="WindLight Tabs">
<panel label="Atmosfera" name="Atmosphere">
<text name="BHText">
Blu dell&apos;Orizzonte
</text>
- <button label="?" name="WLBlueHorizonHelp"/>
+ <button label="?" name="WLBlueHorizonHelp" left="189"/>
<text name="BHText2">
R
</text>
@@ -25,14 +25,14 @@
<text name="BHText5">
I
</text>
- <text name="BDensText">
+ <text name="BDensText" font="SansSerifSmall">
Altezza della Foschia all&apos;Orizzonte
</text>
- <button label="?" name="WLHazeHorizonHelp"/>
+ <button label="?" name="WLHazeHorizonHelp" left="189" />
<text name="BDensText2">
Densità del Blu
</text>
- <button label="?" name="WLBlueDensityHelp"/>
+ <button label="?" name="WLBlueDensityHelp" />
<text name="BHText6">
R
</text>
@@ -52,15 +52,15 @@
<text name="DensMultText">
Moltiplicatore di Densità
</text>
- <button label="?" name="WLDensityMultHelp"/>
+ <button label="?" name="WLDensityMultHelp" left="645"/>
<text name="WLDistanceMultText">
Moltiplicatore della Distanza
</text>
- <button label="?" name="WLDistanceMultHelp"/>
+ <button label="?" name="WLDistanceMultHelp" left="645"/>
<text name="MaxAltText">
Altitudine Massima
</text>
- <button label="?" name="WLMaxAltitudeHelp"/>
+ <button label="?" name="WLMaxAltitudeHelp" left="645"/>
</panel>
<panel label="Illuminazione" name="Lighting">
<text name="SLCText">
@@ -151,15 +151,15 @@
<text name="WLCloudCoverageText">
Copertura delle Nuvole
</text>
- <button label="?" name="WLCloudCoverageHelp"/>
+ <button label="?" name="WLCloudCoverageHelp" left="415"/>
<text name="WLCloudScaleText">
Altitudine delle Nuvole
</text>
- <button label="?" name="WLCloudScaleHelp"/>
+ <button label="?" name="WLCloudScaleHelp" left="415"/>
<text name="WLCloudDetailText">
Dettagli Nuvole (XY/ Densità)
</text>
- <button label="?" name="WLCloudDetailHelp"/>
+ <button label="?" name="WLCloudDetailHelp" left="415"/>
<text name="BHText8">
X
</text>
@@ -170,17 +170,17 @@
D
</text>
<text name="WLCloudScrollXText">
- Scorrimento delle nuvole X
+ Scorrimento delle X
</text>
<button label="?" name="WLCloudScrollXHelp"/>
<check_box label="Blocca" name="WLCloudLockX"/>
<text name="WLCloudScrollYText">
- Scorrimento delle nuvole Y
+ Scorrimento delle Y
</text>
<button label="?" name="WLCloudScrollYHelp"/>
<check_box label="Blocca" name="WLCloudLockY"/>
<check_box label="Mostra le Nuvole Classiche" name="DrawClassicClouds"/>
- <button label="?" name="WLClassicCloudsHelp"/>
+ <button label="?" name="WLClassicCloudsHelp" left="645"/>
</panel>
</tab_container>
<string name="WLDefaultSkyNames">
diff --git a/indra/newview/skins/default/xui/it/floater_world_map.xml b/indra/newview/skins/default/xui/it/floater_world_map.xml
index 8d58b7df3e..6fb7b93bc7 100644
--- a/indra/newview/skins/default/xui/it/floater_world_map.xml
+++ b/indra/newview/skins/default/xui/it/floater_world_map.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="worldmap" title="Mappa">
+<floater name="worldmap" title="MAPPA">
<tab_container name="maptab">
<panel label="Oggetti" name="objects_mapview"/>
<panel label="Terreno" name="terrain_mapview"/>
@@ -30,14 +30,10 @@
<check_box label="Adult" name="event_adult_chk"/>
<icon bottom="-200" name="avatar_icon" />
<combo_box label="Amici Online" name="friend combo" tool_tip="Amici da mostrare sulla mappa">
- <combo_item name="none_selected">
- Amici Online
- </combo_item>
+ <combo_box.item name="item1" label="Amici Online"/>
</combo_box>
<combo_box label="Landmark" name="landmark combo" tool_tip="Landmarks da mostrare sulla mappa">
- <combo_item name="none_selected">
- Landmark
- </combo_item>
+ <combo_box.item name="item1" label="Landmark"/>
</combo_box>
<line_editor label="Cerca per nome di regione" name="location" tool_tip="Scrivi il nome di una regione"/>
<button label="Cerca" name="DoSearch" tool_tip="Cerca regione"/>
@@ -58,6 +54,6 @@
<button font="SansSerifSmall" left_delta="91" width="135" label="Mostra destinazione" label_selected="Mostra destinazione" name="Show Destination" tool_tip="Centra la mappa sul luogo prescelto"/>
<button font="SansSerifSmall" label="Pulisci" label_selected="Pulisci" name="Clear" tool_tip="Togli traccia"/>
<button font="SansSerifSmall" left_delta="91" width="135" label="Mostra la mia posizione" label_selected="Mostra la mia posizione" name="Show My Location" tool_tip="Centra la mappa alla posizione del tuo avatar"/>
- <button font="SansSerifSmall" label="Copia lo SLURL negli appunti" name="copy_slurl" tool_tip="Copia l&apos;attuale posizione quale SLURL utilizzabile nel web."/>
+ <button font="SansSerifSmall" label="Copia lo SLurl negli appunti" name="copy_slurl" tool_tip="Copia l&apos;attuale posizione quale SLurl utilizzabile nel web."/>
<slider label="Zoom" name="zoom slider"/>
</floater>
diff --git a/indra/newview/skins/default/xui/it/language_settings.xml b/indra/newview/skins/default/xui/it/language_settings.xml
new file mode 100644
index 0000000000..71418d446a
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/language_settings.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- This file contains strings that used to be hardcoded in the source.-->
+<strings>
+
+ <!-- Locale Information -->
+ <string name="MicrosoftLocale">english</string>
+ <string name="DarwinLocale">C</string>
+ <string name="LinuxLocale">C</string>
+
+ <!--
+ datetimeToCodes["wkday"] = "%a"; // Thu
+ datetimeToCodes["weekday"] = "%A"; // Thursday
+ datetimeToCodes["year4"] = "%Y"; // 2009
+ datetimeToCodes["year"] = "%Y"; // 2009
+ datetimeToCodes["year2"] = "%y"; // 09
+ datetimeToCodes["mth"] = "%b"; // Aug
+ datetimeToCodes["month"] = "%B"; // August
+ datetimeToCodes["mthnum"] = "%m"; // 08
+ datetimeToCodes["day"] = "%d"; // 31
+ datetimeToCodes["hour24"] = "%H"; // 14
+ datetimeToCodes["hour"] = "%H"; // 14
+ datetimeToCodes["hour12"] = "%I"; // 02
+ datetimeToCodes["min"] = "%M"; // 59
+ datetimeToCodes["ampm"] = "%p"; // AM
+ datetimeToCodes["second"] = "%S"; // 59
+ datetimeToCodes["timezone"] = "%Z"; // PST
+ -->
+
+ <string name="TimeHour">hour,datetime,slt</string>
+ <string name="TimeMin">min,datetime,slt</string>
+ <string name="TimeYear">year,datetime,slt</string>
+ <string name="TimeDay">day,datetime,slt</string>
+ <string name="TimeMonth">mthnum,datetime,slt</string>
+ <string name="TimeWeek">wkday,datetime,slt</string>
+ <string name="TimeAMPM">ampm,datetime,slt</string>
+ <string name="TimeHour12">hour12,datetime,slt</string>
+
+ <string name="LTimeMthNum">mthnum,datetime,local</string>
+ <string name="LTimeWeek">wkday,datetime,local</string>
+ <string name="LTimeMonth">mth,datetime,local</string>
+ <string name="LTimeDay">day,datetime,local</string>
+ <string name="LTimeSec">second,datetime,local</string>
+ <string name="LTimeHour">hour,datetime,local</string>
+ <string name="LTimeMin">min,datetime,local</string>
+ <string name="LTimeYear">year,datetime,local</string>
+
+ <string name="UTCTimeWeek">weekday,datetime,utc</string>
+ <string name="UTCTimeDay">day,datetime,utc</string>
+ <string name="UTCTimeMth">mth,datetime,utc</string>
+ <string name="UTCTimeYr">year,datetime,utc</string>
+ <string name="UTCTimeHr">hour,datetime,utc</string>
+ <string name="UTCTimeMin">min,datetime,utc</string>
+ <string name="UTCTimeSec">second,datetime,utc</string>
+ <string name="UTCTimeTimezone">timezone,datetime,utc</string>
+</strings>
diff --git a/indra/newview/skins/default/xui/it/menu_login.xml b/indra/newview/skins/default/xui/it/menu_login.xml
index 45ee43102a..44a801d273 100644
--- a/indra/newview/skins/default/xui/it/menu_login.xml
+++ b/indra/newview/skins/default/xui/it/menu_login.xml
@@ -7,7 +7,7 @@
<menu_item_call label="Preferenze...." name="Preferences..."/>
</menu>
<menu label="Aiuto" name="Help">
- <menu_item_call label="Aiuto di Second Life" name="Second Life Help"/>
- <menu_item_call label="Informazioni su Second Life..." name="About Second Life..."/>
+ <menu_item_call label="Aiuto di [SECOND_LIFE]" name="Second Life Help"/>
+ <menu_item_call label="Informazioni su [APP_NAME]..." name="About Second Life..."/>
</menu>
</menu_bar>
diff --git a/indra/newview/skins/default/xui/it/menu_viewer.xml b/indra/newview/skins/default/xui/it/menu_viewer.xml
index 3dd4e6a94b..b1eb80149e 100644
--- a/indra/newview/skins/default/xui/it/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/it/menu_viewer.xml
@@ -1,5 +1,11 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<menu_bar name="Main Menu">
+ <menu name="Me">
+ <menu_item_call label="Preferenze" name="Preferences"/>
+ <menu_item_call name="Manage My Account">
+ <menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=it" />
+ </menu_item_call>
+ </menu>
<menu label="File" name="File">
<tearoff_menu label="~~~~~~~~~~~" name="~~~~~~~~~~~"/>
<menu label="Carica" name="upload">
@@ -165,7 +171,9 @@
<menu_item_separator label="-----------" name="separator4"/>
<menu_item_call label="Focalizza la selezione" name="Focus on Selection"/>
<menu_item_call label="Fai zoom sulla selezione" name="Zoom to Selection"/>
- <menu_item_call label="Compra l&apos;oggetto" name="Menu Object Take"/>
+ <menu_item_call label="Compra l&apos;oggetto" name="Menu Object Take">
+ <on_enable userdata="Compra,Prendi" name="EnableBuyOrTake"/>
+ </menu_item_call>
<menu_item_call label="Prendi una copia" name="Take Copy"/>
<menu_item_call label="Salva nuovamente l&apos;oggetto nel contenuto dell&apos;oggetto" name="Save Object Back to Object Contents"/>
<menu_item_separator label="-----------" name="separator6"/>
@@ -179,7 +187,7 @@
<menu_item_call label="Disattiva gli script nella selezione" name="Set Scripts to Not Running in Selection"/>
</menu>
<menu label="Aiuto" name="Help">
- <menu_item_call label="Aiuto di Secondlife" name="Second Life Help"/>
+ <menu_item_call label="Aiuto di [SECOND_LIFE]" name="Second Life Help"/>
<menu_item_call label="Tutorial" name="Tutorial"/>
<menu_item_separator label="-----------" name="separator"/>
<menu_item_call label="Blog ufficiale Linden..." name="Official Linden Blog..."/>
@@ -200,6 +208,6 @@
<menu_item_separator label="-----------" name="separator9"/>
<menu_item_call label="Segnala un bug..." name="Report Bug..."/>
</menu>
- <menu_item_call label="Informazioni su Second Life..." name="About Second Life..."/>
+ <menu_item_call label="Informazioni su [APP_NAME]..." name="About Second Life..."/>
</menu>
</menu_bar>
diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml
index 786bfdf7ef..26a64a49d3 100644
--- a/indra/newview/skins/default/xui/it/notifications.xml
+++ b/indra/newview/skins/default/xui/it/notifications.xml
@@ -6,6 +6,9 @@
<global name="alwayschoose">
Scegli sempre questa opzione
</global>
+ <global name="implicitclosebutton">
+ Chiudi
+ </global>
<template name="okbutton">
<form>
<button
@@ -71,7 +74,7 @@
</form>
</template>
<notification functor="GenericAcknowledge" label="Messaggio di allerta sconosciuto" name="MissingAlert">
- La tua versione di Second Life non sa come visualizzare il messaggio di allerta appena ricevuto.
+ La tua versione di [APP_NAME] non sa come visualizzare il messaggio di allerta appena ricevuto.
Dettagli dell&apos;errore: il messaggio di allerta &apos;[_NAME]&apos; non è stato trovato in notifications.xml.
<usetemplate name="okbutton" yestext="OK"/>
@@ -94,7 +97,7 @@ Dettagli dell&apos;errore: il messaggio di allerta &apos;[_NAME]&apos; non è st
<usetemplate name="okcancelbuttons" notext="Annulla" yestext="Si"/>
</notification>
<notification name="BadInstallation">
- Si è verificato un errore durante l&apos;aggiornamento di Second Life. Scarica l&apos;ultima versione da secondlife.com.
+ Si è verificato un errore durante l&apos;aggiornamento di [APP_NAME]. Scarica l&apos;ultima versione da secondlife.com.
<usetemplate
name="okbutton"
yestext="OK"/>
@@ -138,12 +141,12 @@ Scegli solo un oggetto e riprova.
<usetemplate canceltext="Annulla" name="yesnocancelbuttons" notext="Non Salvare" yestext="Salva Tutto"/>
</notification>
<notification name="GrantModifyRights">
- Dare i diritti di modifica ad un altro residente gli consente di cambiare, cancellare o prendere QUALUNQUE oggetto che hai in Second Life. Fai MOLTA attenzione quando concedi questo permesso.
+ Dare i diritti di modifica ad un altro residente gli consente di cambiare, cancellare o prendere QUALUNQUE oggetto che hai in [SECOND_LIFE]. Fai MOLTA attenzione quando concedi questo permesso.
Vuoi davvero dare i diritti di modifica a [FIRST_NAME] [LAST_NAME]?
<usetemplate name="okcancelbuttons" notext="No" yestext="Si"/>
</notification>
<notification name="GrantModifyRightsMultiple">
- Dare i diritti di modifica ad un altro residente gli consente di cambiare QUALUNQUE oggetto che hai in Second Life. Fai MOLTA attenzione quando concedi questo permesso.
+ Dare i diritti di modifica ad un altro residente gli consente di cambiare QUALUNQUE oggetto che hai in [SECOND_LIFE]. Fai MOLTA attenzione quando concedi questo permesso.
Vuoi davvero dare i diritti di modifica ai residenti selezionati?
<usetemplate name="okcancelbuttons" notext="No" yestext="Si"/>
</notification>
@@ -174,7 +177,7 @@ Vuoi davvero dare i diritti di modifica ai residenti selezionati?
Non si possono rimuovere membri da quel ruolo.
I membri devono dimettersi volontariamente dal ruolo.
Confermi l&apos;operazione?
- <usetemplate ignoretext="Quando si aggiungono membri al ruolo di proprietario" name="okcancelignore" notext="No" yestext="Si"/>
+ <usetemplate ignoretext="Quando si aggiungono membri al ruolo di proprietario del gruppo." name="okcancelignore" notext="No" yestext="Si"/>
</notification>
<notification name="AssignDangerousActionWarning">
Stai per aggiungere il potere &apos;[ACTION_NAME]&apos; al ruolo &apos;[ROLE_NAME]&apos;.
@@ -195,7 +198,7 @@ Aggiungi questo potere a &apos;[ROLE_NAME]&apos;?
<usetemplate name="okcancelbuttons" notext="No" yestext="Si"/>
</notification>
<notification name="ClickPublishHelpLand">
- Selezionare &quot;Pubblica in Ricerca&quot;
+ Selezionare &apos;Pubblica in Ricerca&apos;
Marcando questo campo si mostrerà:
- questo terreno nei risultati di ricerca
- gli oggetti pubblici di questo terreno
@@ -225,14 +228,14 @@ Marcando questo campo si mostrerà:
Non puoi rendere questo terreno visibile nella ricerca perchè è in una regione che non lo consente.
</notification>
<notification name="ClickPublishHelpAvatar">
- Scegliendo &quot;Mostra in Ricerca&quot; verrà mostrato:
+ Scegliendo &apos;Mostra in Ricerca&apos; verrà mostrato:
- il mio profilo nei risultati della ricerca
- un link al mio profilo nelle pagine pubbliche del gruppo
</notification>
<notification name="ClickPartnerHelpAvatar">
Puoi proporre o cancellare una partnership con un altro/a residente attraverso il sito web [SECOND_LIFE].
-Vai al sito web di Second Life per ulteriori informazioni sulla partnership?
+Vai al sito web di [SECOND_LIFE] per ulteriori informazioni sulla partnership?
<usetemplate name="okcancelbuttons" notext="Annulla" yestext="Vai alla pagina"/>
</notification>
<notification name="ClickUploadHelpPermissions">
@@ -270,7 +273,7 @@ Il tuo prezzo di vendità è [SALE_PRICE]L$ ed è autorizzato alla vendita a [NA
<usetemplate name="okcancelbuttons" notext="Annulla" yestext="OK"/>
</notification>
<notification name="ConfirmLandSaleToAnyoneChange">
- ATTENZIONE: Cliccando &apos;vendi a tutti&apos; rende il tuo terrono disponibile all&apos;intera comunità di Second Life, anche non in questa regione.
+ ATTENZIONE: Cliccando &apos;vendi a tutti&apos; rende il tuo terrono disponibile all&apos;intera comunità di [SECOND_LIFE], anche non in questa regione.
Il terreno selezionato di [LAND_SIZE] m² sta per essere messo in vendita.
Il tuo prezzo di vendità è [SALE_PRICE]L$ ed è autorizzato alla vendita a [NAME].
@@ -376,14 +379,17 @@ La cartella equipaggiamento non contiene abbigliamento, parti del corpo o attach
Devi inserire sia il nome che il cognome del tuo avatar.
Hai bisogno di un account per entrare in [SECOND_LIFE]. Ne vuoi creare uno adesso?
+ <url name="url">
+ https://join.secondlife.com/index.php?lang=it-IT
+ </url>
<usetemplate name="okcancelbuttons" notext="Riprova" yestext="Crea un nuovo account"/>
</notification>
<notification name="AddClassified">
- Gli annunci appaiono nella sezione &apos;Annunci&apos; della ricerca nel database e su www.secondlife.com per una settimana.
+ Gli annunci appaiono nella sezione &apos;Annunci&apos; della ricerca nel database e su [http://secondlife.com/community/classifieds/?lang=it-IT secondlife.com] per una settimana.
Compila il tuo annuncio e clicca &apos;Pubblica...&apos; per aggiungerlo al database.
Ti verrà chiesto un prezzo da pagare quando clicchi su Pubblica.
Pagare un prezzo più alto fa sì che il tuo annuncio compaia più in alto nella lista, e che sia più facile da trovare quando la gente ricerca per parole chiavi.
- <usetemplate ignoretext="Mentre si aggiunge un annuncio" name="okcancelignore" notext="Annulla" yestext="OK"/>
+ <usetemplate ignoretext="Quando si aggiunge una inserzione." name="okcancelignore" notext="Annulla" yestext="OK"/>
</notification>
<notification name="DeleteClassified">
Cancella annuncio &apos;[NAME]&apos;?
@@ -400,6 +406,9 @@ Non ci sono rimborsi per la tariffa pagata.
</notification>
<notification name="PromptGoToEventsPage">
Vai alla pagina degli eventi di [SECOND_LIFE]?
+ <url name="url">
+ http://secondlife.com/events/?lang=it-IT
+ </url>
<usetemplate name="okcancelbuttons" notext="Annulla" yestext="OK"/>
</notification>
<notification name="SelectProposalToView">
@@ -417,17 +426,17 @@ Non ci sono rimborsi per la tariffa pagata.
<usetemplate name="okcancelbuttons" notext="Annulla" yestext="OK"/>
</notification>
<notification name="CacheWillClear">
- La Cache verrà pulita dopo il riavvio di [SECOND_LIFE].
+ La Cache verrà pulita dopo il riavvio di [APP_NAME].
</notification>
<notification name="CacheWillBeMoved">
- La Cache verrà traslocata dopo il riavvio di [SECOND_LIFE].
+ La Cache verrà traslocata dopo il riavvio di [APP_NAME].
Nota: Questo pulirà la cache.
</notification>
<notification name="ChangeConnectionPort">
- Le impostazioni delle porte avranno effetto dopo il riavvio di [SECOND_LIFE].
+ Le impostazioni delle porte avranno effetto dopo il riavvio di [APP_NAME].
</notification>
<notification name="ChangeSkin">
- La nuova pelle apparità dopo il riavvio di [SECOND_LIFE].
+ La nuova pelle apparità dopo il riavvio di [APP_NAME].
</notification>
<notification name="GoToAuctionPage">
Vai alla pagina web [SECOND_LIFE] per vedere i dettagli dell&apos;asta oppure fai un&apos;offerta?
@@ -486,25 +495,25 @@ L&apos;oggetto potrebbe essere troppo lontano oppure essere stato cancellato.
Non è stato possibile scrivere il file [[FILE]]
</notification>
<notification name="UnsupportedHardware">
- Attenzione: Il tuo sistema non soddisfa i requisiti minimi per il funzionamento Second Life. Se continui ad usare Second Life, potresti osservare una lentezza eccessiva. Sfortunatamente non possiamo fornire supporto tecnico per configurazioni di sistema non supportate.
+ Attenzione: Il tuo sistema non soddisfa i requisiti minimi per il funzionamento [APP_NAME]. Se continui ad usare [APP_NAME], potresti osservare una lentezza eccessiva. Sfortunatamente non possiamo fornire supporto tecnico per configurazioni di sistema non supportate.
MINSPECS
Vuoi visitare [_URL] per maggiori informazioni?
<url name="url" option="0">
http://secondlife.com/support/sysreqs.php?lang=it
</url>
- <usetemplate ignoretext="Mentre sto individuando hardware non supportato" name="okcancelignore" notext="No" yestext="Si"/>
+ <usetemplate ignoretext="Quando sto individuando hardware non supportato." name="okcancelignore" notext="No" yestext="Si"/>
</notification>
<notification name="UnknownGPU">
Il tuo sistema contiene una scheda grafica che attualmente non supportiamo.
-Questo succede spesso con nuovi prodotti che non siamo riusciti a verificare. Probabilmente Second Life funzionerà correttamente ma forse dovrai modificare le impostazioni grafiche in modo appropriato.
+Questo succede spesso con nuovi prodotti che non siamo riusciti a verificare. Probabilmente [APP_NAME] funzionerà correttamente ma forse dovrai modificare le impostazioni grafiche in modo appropriato.
(Modifica &gt; Preferenze &gt; Grafica).
<form name="form">
- <ignore name="ignore" text="Mentre stavo valutando una scheda grafica sconosciuta"/>
+ <ignore name="ignore" text="Quando sto valutando una scheda grafica sconosciuta"/>
</form>
</notification>
<notification name="DisplaySettingsNoShaders">
- [SECOND_LIFE] si è bloccata mentre stava inizializzando i driver grafici.
+ [APP_NAME] si è bloccata mentre stava inizializzando i driver grafici.
La qualità grafica verrà impostata al valore basso per evitare alcuni degli errori più comuni con i driver.
Questo però disabiliterà alcune funzioni grafiche.
Ti raccomandiamo di aggiornare i driver della tua scheda grafica.
@@ -571,7 +580,10 @@ Sposta tutti gli oggetti che vuoi acquisire su una sola regione.
<notification name="PromptGoToCurrencyPage">
[EXTRA]
-Vuoi andare su [URL] per maggiori informazioni su come acquistare denaro?
+Vuoi andare su [_URL] per maggiori informazioni su come acquistare L$?
+ <url name="url">
+ http://secondlife.com/app/currency/?lang=it-IT
+ </url>
<usetemplate name="okcancelbuttons" notext="Annulla" yestext="OK"/>
</notification>
<notification name="UnableToLinkObjects">
@@ -736,7 +748,7 @@ Spiacenti, ma non hai accesso nel luogo di destinazione richiesto.
Gli oggetti da te indossati non sono ancoa arrivati. Attendi ancora qualche secondo o scollegati e ricollegati prima di provare a teleportarti.
</notification>
<notification name="too_many_uploads_tport">
-La gestione dati della regione è al momento occupata e la tua richiesta di teletrasporto non può essere soddisfatta entro breve tempo. Per favore prova di nuovo tra qualche minuto o spostati in un&apos;area meno affollata.
+Il server della regione è al momento occupato e la tua richiesta di teletrasporto non può essere soddisfatta entro breve tempo. Per favore prova di nuovo tra qualche minuto o spostati in un&apos;area meno affollata.
</notification>
<notification name="expired_tport">
Spiacenti, il sistema non riesce a soddisfare la tua richiesta di teletrasporto entro un tempo ragionevole. Riprova tra qualche minuto.
@@ -788,7 +800,7 @@ Nessun terreno selezionato.
Non riesco a trovare la regione dove è situato il terreno.
</notification>
<notification name="CannotCloseFloaterBuyLand">
- Non puoi chiudere la finestra di Acquisto Terreno finchè Second Life non stima il prezzo di questa transazione.
+ Non puoi chiudere la finestra di Acquisto Terreno finchè [APP_NAME] non stima il prezzo di questa transazione.
</notification>
<notification name="CannotDeedLandNothingSelected">
Impossibile cedere il terreno:
@@ -801,7 +813,6 @@ Nessun gruppo selezionato.
<notification name="CannotDeedLandNoRegion">
Impossibile cedere il terreno:
Non riesco a trovare la regione dove è situato il terreno.
-Usa Strumenti -&gt; Segnala Bug per segnalare il problema.
</notification>
<notification name="CannotDeedLandMultipleSelected">
Impossibile cedere il terreno:
@@ -847,8 +858,6 @@ I terreni di tua proprietà vengono visualizzati in verde.
<notification name="CannotReleaseLandRegionNotFound">
Impossibile abbandonare il terreno:
Non riesco a trovare la regione dove è situato il terreno.
-
-Usa Strumenti &gt; Segnala Bug segnalare questo problema.
</notification>
<notification name="CannotReleaseLandNoTransfer">
Impossibile abbandonare il terreno:
@@ -887,14 +896,10 @@ Dividi il terreno?
<notification name="CannotDivideLandNoRegion">
Impossibile dividere il terreno:
Non riesco a trovare la regione dove è situato.
-
-Usa Strumenti -&gt; Segnala Bug per segnalare il problema.
</notification>
<notification name="CannotJoinLandNoRegion">
Impossibile unire il terreno:
Non riesco a trovare la regione dove è situato.
-
-Usa Strumenti -&gt; Segnala Bug per segnalare il problema.
</notification>
<notification name="CannotJoinLandNothingSelected">
Impossibile unire il terreno:
@@ -953,13 +958,11 @@ Grigia = pubblica
<notification name="CannotSaveToAssetStore">
Impossibile salvare [NAME] nel database centrale.
Normalmente questo problema è temporaneo. Riprova a generare la parte indossabile e a salvarla fra qualche minuto.
-
-Se questo problema persiste, clicca sul menu a tendina &apos;Strumenti &gt; Segnala Bug&apos; e fornisci i dettagli sulla tua configurazione di rete.
</notification>
<notification name="YouHaveBeenLoggedOut">
Sei stato sconnesso da [SECOND_LIFE]:
[MESSAGE]
-Puoi ancora vedere i tuoi IM e la chat cliccando &apos;Vedi IM &amp; Chat&apos;. Altrimenti, clicca &apos;Esci&apos; per uscire immediatamente da [SECOND_LIFE].
+Puoi ancora vedere i tuoi IM e la chat cliccando &apos;Vedi IM &amp; Chat&apos;. Altrimenti, clicca &apos;Esci&apos; per uscire immediatamente da [APP_NAME].
<usetemplate name="okcancelbuttons" notext="Esci" yestext="Vedi IM &amp; Chat"/>
</notification>
<notification name="OnlyOfficerCanBuyLand">
@@ -977,7 +980,7 @@ Offri l&apos;amicizia a [NAME]?
Offri l&apos;amicizia a [NAME]?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Vorresti essere mio amico?
</input>
<button name="Offer" text="OK"/>
@@ -1127,20 +1130,23 @@ Il tuo avatar è stato spostato in una regione vicina.
I tuoi vestiti stanno ancora scaricandosi.
Puoi usare [SECOND_LIFE] normalmente e gli altri utenti ti vedranno correttamente.
<form name="form">
- <ignore name="ignore" text="se gli abiti ci impiegano troppo tempo a scaricarsi"/>
+ <ignore name="ignore" text="Qualora gli abiti impieghino troppo tempo a caricarsi."/>
</form>
</notification>
<notification name="FirstRun">
- L&apos;installazione di [SECOND_LIFE] è completata.
+ L&apos;installazione di [APP_NAME] è completata.
Se questa è la prima volta che usi [SECOND_LIFE], avari bisogno di creare un account prima di poterti collegare.
-Vai su www.secondlife.com per creare un nuovo account?
+Vai su [https://join.secondlife.com/index.php?lang=it-IT secondlife.com] per creare un nuovo account?
<usetemplate name="okcancelbuttons" notext="Continua" yestext="Nuovo Account..."/>
</notification>
<notification name="LoginPacketNeverReceived">
- Ci sono stati problemi durante la connessione. Potrebbero esserci problemi con la tua connessione ad internet oppure con i server di Second Life.
+ Ci sono stati problemi durante la connessione. Potrebbero esserci problemi con la tua connessione ad internet oppure con i server di [SECOND_LIFE].
Puoi controllare la tua connessione internet e riprovare fra qualche minuto, oppure cliccare su Aiuto per collegarti al nostro sito di supporto, oppure cliccare teleporta per cercare di teleportarti a casa.
+ <url name="url">
+ http://it.secondlife.com/support/
+ </url>
<form name="form">
<button name="OK" text="OK"/>
<button name="Help" text="Aiuto"/>
@@ -1150,9 +1156,9 @@ Puoi controllare la tua connessione internet e riprovare fra qualche minuto, opp
<notification name="WelcomeChooseSex">
Il tuo avatar apparirà fra un attimo.
-Usa le frecce per camminare.
-Premi F1 in qualunque momento per aiuto o per apprendere altre cose su [SECOND_LIFE].
-Scegli l&apos;avatar maschile o femminile. Puoi sempre cambiare idea più tardi.
+Usa le frecce per muoverti.
+Premi F1 in qualunque momento per la guida o per apprendere altre cose di [SECOND_LIFE].
+Scegli un avatar maschile o femminile. Puoi sempre cambiare idea più tardi.
<usetemplate name="okcancelbuttons" notext="Femminile" yestext="Maschile"/>
</notification>
<notification name="NotEnoughCurrency">
@@ -1190,13 +1196,13 @@ Scegli solo un oggetto e riprova.
Impossibile impostare le texture della regione:
La texture del terreno [TEXTURE_NUM] ha una profondità di bit pari a [TEXTURE_BIT_DEPTH] non corretta.
-Sostituisci la texture [TEXTURE_NUM] con una a 24-bit 512x512 o una immagine più piccola e quindi clicca nuovamente su &quot;Applica&quot;.
+Sostituisci la texture [TEXTURE_NUM] con una a 24-bit 512x512 o una immagine più piccola e quindi clicca nuovamente su &apos;Applica&apos;.
</notification>
<notification name="InvalidTerrainSize">
Impossibile impostare le texture di regione:
La texture del terreno [TEXTURE_NUM] è troppo grande se a [TEXTURE_SIZE_X]x[TEXTURE_SIZE_Y].
-Sostituisci la texture [TEXTURE_NUM] con una a 24-bit 512x512 oppure con una immagine più piccola e quindi clicca di nuovo &quot;Applica&quot;.
+Sostituisci la texture [TEXTURE_NUM] con una a 24-bit 512x512 oppure con una immagine più piccola e quindi clicca di nuovo &apos;Applica&apos;.
</notification>
<notification name="RawUploadStarted">
Importazione iniziata. Può impiegare fino a due minuti, a seconda della velocità della tua connessione.
@@ -1241,33 +1247,33 @@ Imposta l&apos;oggetto per la vendita e riprova.
[DOWNLOAD_PATH].
</notification>
<notification name="DownloadWindowsMandatory">
- E&apos; disponibile una nuova versione di [SECOND_LIFE].
+ E&apos; disponibile una nuova versione di [APP_NAME].
[MESSAGE]
-Devi scaricare questo aggiornamento per usare [SECOND_LIFE].
+Devi scaricare questo aggiornamento per usare [APP_NAME].
<usetemplate name="okcancelbuttons" notext="Esci" yestext="Scarica l&apos;aggiornamento"/>
</notification>
<notification name="DownloadWindows">
- E&apos; disponibile una versione aggiornata di [SECOND_LIFE].
+ E&apos; disponibile una versione aggiornata di [APP_NAME].
[MESSAGE]
Questo aggiornamento non è obbligatorio, ma ti suggeriamo di installarlo per migliorarne le prestazioni e la stabilità.
<usetemplate name="okcancelbuttons" notext="Continua" yestext="Scarica l&apos;aggiornamento"/>
</notification>
<notification name="DownloadWindowsReleaseForDownload">
- E&apos; disponibile una versione aggiornata di [SECOND_LIFE].
+ E&apos; disponibile una versione aggiornata di [APP_NAME].
[MESSAGE]
Questo aggiornamento non è obbligatorio, ma ti suggeriamo di installarlo per migliorarne le prestazioni e la stabilità.
<usetemplate name="okcancelbuttons" notext="Continua" yestext="Scarica l&apos;aggiornamento"/>
</notification>
<notification name="DownloadMacMandatory">
- E&apos; disponibile una nuova versione di [SECOND_LIFE].
+ E&apos; disponibile una nuova versione di [APP_NAME].
[MESSAGE]
-Devi scaricare questo aggiornamento per usare [SECOND_LIFE].
+Devi scaricare questo aggiornamento per usare [APP_NAME].
Vuoi avviarne lo scaricamento nella tua cartella applicazioni?
<usetemplate name="okcancelbuttons" notext="Esci" yestext="Scarica l&apos;aggiornamento"/>
</notification>
<notification name="DownloadMac">
- E&apos; disponibile una versione aggiornata di [SECOND_LIFE].
+ E&apos; disponibile una versione aggiornata di [APP_NAME].
[MESSAGE]
Questo aggiornamento non è obbligatorio, ma ti suggeriamo di installarlo per migliorarne le prestazioni e la stabilità.
@@ -1275,7 +1281,7 @@ Vuoi avviarne lo scaricamento nella tua cartella applicazioni?
<usetemplate name="okcancelbuttons" notext="Continua" yestext="Scarica l&apos;aggiornamento"/>
</notification>
<notification name="DownloadMacReleaseForDownload">
- E&apos; disponibile una versione aggiornata di [SECOND_LIFE].
+ E&apos; disponibile una versione aggiornata di [APP_NAME].
[MESSAGE]
Questo aggiornamento non è obbligatorio, ma ti suggeriamo di installarlo per migliorarne le prestazioni e la stabilità.
@@ -1285,53 +1291,49 @@ Vuoi avviarne lo scaricamento nella tua cartella applicazioni?
<notification name="DeedObjectToGroup">
La cessione di questo oggetto farà in modo che il gruppo:
* Riceva i L$ pagati all&apos;oggetto
- <usetemplate ignoretext="Quando cedi oggetti ai gruppi" name="okcancelignore" notext="Annulla" yestext="Cedi"/>
+ <usetemplate ignoretext="Quando cedi oggetti ai gruppi." name="okcancelignore" notext="Annulla" yestext="Cedi"/>
</notification>
<notification name="WebLaunchExternalTarget">
Apri il tuo browser web per vedere questo contenuto?
- <usetemplate ignoretext="Quando apri il browser di sistema per vedere una pagina web" name="okcancelignore" notext="Annulla" yestext="OK"/>
+ <usetemplate ignoretext="Quando apri il browser di sistema per vedere una pagina web." name="okcancelignore" notext="Annulla" yestext="OK"/>
</notification>
<notification name="WebLaunchJoinNow">
Vuoi andare su www.secondlife.com per gestire il tuo account?
- <usetemplate ignoretext="Quando lanci il browser web per gestire il tuo account" name="okcancelignore" notext="Annulla" yestext="OK"/>
- </notification>
- <notification name="WebLaunchBugReport101">
- Visita la Wiki di [SECOND_LIFE] per imparare a segnalare un bug correttamente.
- <usetemplate ignoretext="Quando lanci il browser web per vedere la Wiki di segnalazione bug base" name="okcancelignore" notext="Annulla" yestext="OK"/>
+ <usetemplate ignoretext="Quando lanci il browser web per gestire il tuo account." name="okcancelignore" notext="Annulla" yestext="OK"/>
</notification>
<notification name="WebLaunchSecurityIssues">
Visita la Wiki di [SECOND_LIFE] per i dettagli su come segnalare un problema di sicurezza.
- <usetemplate ignoretext="Quando lanci il browser web per vedere la Wiki sui problemi di sicurezza" name="okcancelignore" notext="Annulla" yestext="OK"/>
+ <usetemplate ignoretext="Quando lanci il browser web per vedere la Wiki sui problemi di sicurezza." name="okcancelignore" notext="Annulla" yestext="OK"/>
</notification>
<notification name="WebLaunchQAWiki">
Visita il controllo di qualità Wiki [SECOND_LIFE].
- <usetemplate ignoretext="Quando lanci il browser web per vedere il controllo di qualità Wiki" name="okcancelignore" notext="Annulla" yestext="OK"/>
+ <usetemplate ignoretext="Quando lanci il browser web per vedere il controllo di qualità Wiki." name="okcancelignore" notext="Annulla" yestext="OK"/>
</notification>
<notification name="WebLaunchPublicIssue">
Visita il registro pubblico dei problemi di [SECOND_LIFE], dove puoi segnalare bug ed altri problemi.
- <usetemplate ignoretext="Quando lanci il browser web per vedere il registro pubblico dei problemi" name="okcancelignore" notext="Annulla" yestext="Vai alla pagina"/>
+ <usetemplate ignoretext="Quando lanci il browser web per vedere il registro pubblico dei problemi." name="okcancelignore" notext="Annulla" yestext="Vai alla pagina"/>
</notification>
<notification name="WebLaunchPublicIssueHelp">
Visita la Wiki di [SECOND_LIFE] per le informazioni su come usare il registro pubblico dei problemi.
- <usetemplate ignoretext="Quando lanci il browser web per vedere la Wiki del registro pubblico dei problemi" name="okcancelignore" notext="Annulla" yestext="Vai alla pagina"/>
+ <usetemplate ignoretext="Quando lanci il browser web per vedere la Wiki del registro pubblico dei problemi." name="okcancelignore" notext="Annulla" yestext="Vai alla pagina"/>
</notification>
<notification name="WebLaunchSupportWiki">
Vai al blog ufficiale Linden, per le ultime notizie ed informazioni.
- <usetemplate ignoretext="Quando lanci il browser web per vedere il blog" name="okcancelignore" notext="Annulla" yestext="OK"/>
+ <usetemplate ignoretext="Quando lanci il browser web per vedere il blog." name="okcancelignore" notext="Annulla" yestext="OK"/>
</notification>
<notification name="WebLaunchLSLGuide">
Vai alla guida dello scripting per l&apos;aiuto sullo scripting?
- <usetemplate ignoretext="Quando lanci il browser web per vedere la guida dello scripting" name="okcancelignore" notext="Annulla" yestext="OK"/>
+ <usetemplate ignoretext="Quando lanci il browser web per vedere la guida dello scripting." name="okcancelignore" notext="Annulla" yestext="OK"/>
</notification>
<notification name="WebLaunchLSLWiki">
Vai al portale LSL per aiuto sullo scripting?
- <usetemplate ignoretext="Quando lanci il browser web per vedere il portale LSL" name="okcancelignore" notext="Annulla" yestext="Vai alla pagina"/>
+ <usetemplate ignoretext="Quando lanci il browser web per vedere il portale LSL." name="okcancelignore" notext="Annulla" yestext="Vai alla pagina"/>
</notification>
<notification name="ReturnToOwner">
Confermi di voler restituire gli oggetti selezionati ai loro proprietari? Gli oggetti trasferibili ceduti al gruppo, verranno restituiti ai proprietari precedenti.
*ATTENZIONE* Gli oggetti ceduti non trasferibili verranno cancellati!
- <usetemplate ignoretext="Quando restituisci gli oggetti ai loro proprietari" name="okcancelignore" notext="Annulla" yestext="OK"/>
+ <usetemplate ignoretext="Quando restituisci gli oggetti ai loro proprietari." name="okcancelignore" notext="Annulla" yestext="OK"/>
</notification>
<notification name="GroupLeaveConfirmMember">
Sei attualmente un membro del gruppo [GROUP].
@@ -1369,7 +1371,7 @@ Vuoi cancellare quell&apos;elemento?
<notification name="BusyModeSet">
Impostata la modalità &apos;Occupato&apos;.
La chat e i messaggi verranno nascosti. I messaggi IM riceveranno la risposta impostata per la modalità &apos;Occupato&apos;. Tutte le offerte di teleport verranno declinate. Tutte le offerte di inventario andranno nel cestino.
- <usetemplate ignoretext="Quando si imposta la modalità occupato" name="okignore" yestext="OK"/>
+ <usetemplate ignoretext="Quando imposti la modalità &apos;occupato&apos;." name="okignore" yestext="OK"/>
</notification>
<notification name="JoinedTooManyGroupsMember">
Sei membro di troppi gruppi per poterti unire ad uno nuovo.
@@ -1383,7 +1385,7 @@ Per abbandonare un gruppo seleziona l&apos;opzione &apos;Gruppi..&apos; dal menu
<notification name="KickUser">
Espelli questo utente con quale messaggio?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Un amministratore ti ha disconnesso.
</input>
<button name="OK" text="OK"/>
@@ -1393,7 +1395,7 @@ Per abbandonare un gruppo seleziona l&apos;opzione &apos;Gruppi..&apos; dal menu
<notification name="KickAllUsers">
Espelli tutti quelli che sono sulla griglia con quale messaggio?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Un amministratore ti ha disconnesso.
</input>
<button name="OK" text="OK"/>
@@ -1403,7 +1405,7 @@ Per abbandonare un gruppo seleziona l&apos;opzione &apos;Gruppi..&apos; dal menu
<notification name="FreezeUser">
Immobilizza questo utente con quale messaggio?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Sei stato immobilizzato. Non puoi muoverti o usare la chat. Un amministratore ti contatterà con un messaggio (IM).
</input>
<button name="OK" text="OK"/>
@@ -1413,7 +1415,7 @@ Per abbandonare un gruppo seleziona l&apos;opzione &apos;Gruppi..&apos; dal menu
<notification name="UnFreezeUser">
Smobilizza questo utente con quale messaggio?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Non sei più immobilizzato.
</input>
<button name="OK" text="OK"/>
@@ -1423,7 +1425,7 @@ Per abbandonare un gruppo seleziona l&apos;opzione &apos;Gruppi..&apos; dal menu
<notification name="OfferTeleport">
Offri un teleport nel posto dove sei con il seguente messaggio?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Raggiungimi a [REGION]
</input>
<button name="OK" text="OK"/>
@@ -1433,7 +1435,7 @@ Per abbandonare un gruppo seleziona l&apos;opzione &apos;Gruppi..&apos; dal menu
<notification name="OfferTeleportFromGod">
Vuoi trasportare divinamente l&apos;utente nel posto dove sei?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Raggiungimi in [REGION]
</input>
<button name="OK" text="OK"/>
@@ -1442,12 +1444,12 @@ Per abbandonare un gruppo seleziona l&apos;opzione &apos;Gruppi..&apos; dal menu
</notification>
<notification name="TeleportFromLandmark">
Confermi di volerti teleportare?
- <usetemplate ignoretext="Quando ti teleporti da un landmark nell&apos;inventario" name="okcancelignore" notext="Annulla" yestext="Teleportati"/>
+ <usetemplate ignoretext="Quando ti teleporti da un landmark dell&apos;inventario." name="okcancelignore" notext="Annulla" yestext="Teleportati"/>
</notification>
<notification label="Manda un messaggio a tutti nella tua proprietà" name="MessageEstate">
Scrivi un annuncio breve che verrà mandato a tutti quelli che sono in questo momento nella tua proprietà.
<form name="form">
- <input name="message" type="text"/>
+ <input name="message"/>
<button name="OK" text="OK"/>
<button name="Cancel" text="Annulla"/>
</form>
@@ -1520,13 +1522,13 @@ Verifica di avere installato l&apos;ultima versione del programma e vai alla Kno
Vuoi andare alla Knowledge Base per ulteriori informazioni sulle categorie di accesso?
<url name="url">
- https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=6010
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview/it
</url>
<usetemplate
name="okcancelignore"
yestext="Vai alla Knowledge Base"
notext="Chiudi"
- ignoretext="Quando l&apos;entrata nella regione è bloccata a causa delle categorie di accesso"/>
+ ignoretext="Quando l&apos;entrata nella regione è bloccata a causa delle categorie di accesso."/>
</notification>
<notification name="RegionEntryAccessBlocked_Notify">
Non sei ammesso in questa regione a causa della tua categoria d&apos;accesso.
@@ -1543,7 +1545,7 @@ Puoi cliccare su &apos;Cambia le preferenze&apos; per aumentare subito le tue pr
default="true"
name="Cancel"
text="Chiudi"/>
- <ignore name="ignore" text="Quando l&apos;entrata nella regione è bloccata a causa delle preferenze sulle categorie di accesso"/>
+ <ignore name="ignore" text="Quando l&apos;entrata in una regione è bloccata a causa delle preferenze delle categorie di accesso."/>
</form>
</notification>
<notification name="LandClaimAccessBlocked">
@@ -1559,13 +1561,13 @@ Verifica di avere installato l&apos;ultima versione del programma e vai alla Kno
Vuoi andare alla Knowledge Base per maggiori informazioni sulle categorie di accesso?
<url name="url">
- https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=6010
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview/it
</url>
<usetemplate
name="okcancelignore"
yestext="Vai alla Knowledge Base"
notext="Chiudi"
- ignoretext="Quando la presa di possesso della terra è bloccata a causa delle categorie di accesso"/>
+ ignoretext="Quando l&apos;acquisizione della terra è bloccata a causa delle categorie di accesso."/>
</notification>
<notification name="LandClaimAccessBlocked_Notify">
Non puoi prendere possesso di questa terra a causa della tua categoria di accesso.
@@ -1578,7 +1580,7 @@ Puoi cliccare su &apos;Cambia le preferenze&apos; per aumentare subito le tue pr
name="okcancelignore"
yestext="Cambia le preferenze"
notext="Chiudi"
- ignoretext="Quando la presa di possesso della terra è bloccata a causa delle preferenze sulle categorie di accesso"/>
+ ignoretext="Quando l&apos;acquisizione della terra è bloccata a causa delle preferenze delle categorie di accesso."/>
</notification>
<notification name="LandBuyAccessBlocked">
Non puoi acquistare questo terreno a causa della tua categoria di accesso. Questo può essere dovuto ad una mancanza di informazioni valide che confermino la tua età.
@@ -1593,13 +1595,13 @@ Verifica di avere installato l&apos;ultima versione del programma e vai alla Kno
Vuoi andare alla Knowledge Base per maggiori informazioni sulle categorie di accesso?
<url name="url">
- https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=6010
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview/it
</url>
<usetemplate
name="okcancelignore"
yestext="Vai alla Knowledge Base"
notext="Chiudi"
- ignoretext="Quando un acquisto di terra è bloccato a causa delle categorie di accesso"/>
+ ignoretext="Quando un acquisto di terra è bloccato a causa delle categorie di accesso."/>
</notification>
<notification name="LandBuyAccessBlocked_Notify">
Non puoi acquistare questa land a causa della tua categoria di accesso.
@@ -1612,7 +1614,7 @@ Puoi cliccare su &apos;Cambia le preferenze&apos; per aumentare subito le tue pr
name="okcancelignore"
yestext="Cambia le preferenze"
notext="Chiudi"
- ignoretext="Quando un acquisto di terra è bloccato a causa delle preferenze sulle categorie di accesso"/>
+ ignoretext="Quando un acquisto di terra è bloccato a causa delle preferenze sulle categorie di accesso."/>
</notification>
<notification name="TooManyPrimsSelected">
&quot;Hai selezionato troppi prims. Seleziona [MAX_PRIM_COUNT] o meno prims e riprova.&quot;
@@ -1669,7 +1671,7 @@ Pubblica questo annuncio adesso per [AMOUNT]L$?
<notification label="Manda un messaggio a tutti in questa regione" name="MessageRegion">
Scrivi un breve annuncio che verrà mandato a tutti in questa regione.
<form name="form">
- <input name="message" type="text"/>
+ <input name="message"/>
<button name="OK" text="OK"/>
<button name="Cancel" text="Annulla"/>
</form>
@@ -1718,7 +1720,7 @@ Una volta impostato, fai attenzione che abbassare il bonus può causare la cance
Impostazione base: 1.0
</notification>
<notification label="Categoria di accesso" name="HelpRegionMaturity">
- Imposta la categoria di accesso della regione, come mostrato nella barra dei menu nella parte superiore dello schermo di qualsiasi residente e nelle tooltip sulla mappa di Second Life, quando il cursore si muove su questa regione. Questa impostazione influenza anche l&apos;accesso a questa regione e i risultati della ricerca. Altri residenti possono entrare solo in regioni o visualizzare risultati della ricerca con la stessa categoria di accesso che hanno scelto nella loro preferenze.
+ Imposta la categoria di accesso della regione, come mostrato nella barra dei menu nella parte superiore dello schermo di qualsiasi residente e nelle tooltip sulla mappa di [SECOND_LIFE], quando il cursore si muove su questa regione. Questa impostazione influenza anche l&apos;accesso a questa regione e i risultati della ricerca. Altri residenti possono entrare solo in regioni o visualizzare risultati della ricerca con la stessa categoria di accesso che hanno scelto nella loro preferenze.
Può trascorrere un po&apos; di tempo prima che questa modifica si rifletta sulla mappa.
</notification>
@@ -1757,9 +1759,9 @@ Se questa opzione è selezionato i compratori possono rivendere i loro terreni i
Impostazione base: Non consentire
</notification>
<notification label="Disabilita gli script" name="HelpRegionDisableScripts">
- Se le prestazioni di una sim sono basse, probabilmente è colpa di uno script. Apri la &apos;barra delle statistiche&apos; (Ctrl-Shift-1). Controlla il FPS della fisica del simulatore.
-Se è più basso di 45, apri il pannello &quot;Tempi&quot; collocato ln fondo alla &apos;barra delle statistiche&apos;
-Se il tempo per gli script è di 25 ms o più alto, clicca sul bottone &apos;individua script pesanti&apos;. Ti verrà dato il nome e l&apos;ubicazione degli script che probabilmente causano una cattiva prestazione.
+ Se le prestazioni di una sim sono basse, probabilmente è colpa di uno script. Apri la &apos;Barra delle statistiche&apos; (Ctrl+Shift+1). Controlla il FPS della fisica del simulatore.
+Se è più basso di 45, apri il pannello &apos;Time&apos; (Tempi) collocato ln fondo alla &apos;Barra delle statistiche&apos;
+Se il tempo per gli script è di 25 ms o più alto, clicca sul bottone &apos;Visualizza l&apos;elenco degli script più pesanti...&apos;. Ti verrà dato il nome e l&apos;ubicazione degli script che probabilmente causano una cattiva prestazione.
Selezionare la casella della disabilitazione script e, premendo il bottone applica, disabilitare temporaneamente tutti gli script in questa regione. Questo è necessario per poterti recare verso l&apos;ubicazione dello script definito nell&apos;elenco come &apos;script più pesante&apos;. Una volta arrivato all&apos;oggetto, studia lo script per capire se è quello che sta causando il problema. Potresti dover contattare il proprietario dello script oppure cancellare o restituire l&apos;oggetto.
Disabilita la casella e quindi premere applica per riattivare gli script nella regione.
@@ -1768,10 +1770,10 @@ Impostazione base: spento
</notification>
<notification label="Disabilita le collisioni" name="HelpRegionDisableCollisions">
Quando le prestazioni della sim sono basse, può darsi che la colpa sia di oggetti fisici.
-Apri la &apos;barra delle statistiche&apos; (Ctrl-Shift-1).
+Apri la &apos;Barra delle statistiche&apos; (Ctrl+Shift+1).
Controlla il FPS della fisica del simulatore.
-Se è più basso di 45, apri il pannello &quot;Tempi&quot; collocato in fondo alla &apos;barra delle statistiche&apos;.
-Se il tempo della sim (fisica) risulta 20 ms o più, clicca sul bottone &quot;mostra gli oggetti che collidono di più&quot;.
+Se è più basso di 45, apri il pannello &apos;Time&apos; (Tempi) collocato in fondo alla &apos;Barra delle statistiche&apos;.
+Se il tempo della sim (fisica) risulta 20 ms o più, clicca sul bottone &apos;mostra gli oggetti che collidono di più&apos;.
Ti verranno dati il nome e l&apos;ubicazione degli oggetti fisici che possono causare una cattiva prestazione.
Selezionare la casella disabilita collisioni e, premendo il bottone applica, disabilitare temporaneamente le collisioni oggetto-oggetto. Questo è necessario per poterti recare verso l&apos;ubicazione dell&apos;oggetto che sta collidendo eccessivamente.
@@ -1791,11 +1793,11 @@ Impostazione base: spento
</notification>
<notification label="Oggetti con maggiori collisioni" name="HelpRegionTopColliders">
Mostra una lista di oggetti che sperimentano la maggior quantità di potenziali collisioni oggetto-oggetto. Questi oggetti possono abbassare le prestazioni.
-Seleziona Vista &gt; Barra Statistiche e guarda sotto Simulatore &gt; Tempi &gt; Tempo Sim (fisica) per controllare se un tempo di più di 20 ms è impiegato nella fisica.
+Seleziona Visualizza &gt; Barra della statistiche e guarda sotto Simulator (Simulatore) &gt; Time (Tempi) &gt; Physics Time (Tempo Sim fisica) per controllare se un tempo di più di 20 ms è impiegato nella fisica.
</notification>
<notification label="Script pesanti" name="HelpRegionTopScripts">
Mostra una lista degli oggetti che occupano la maggior parte del loro tempo eseguendo script LSL. Questi oggetti possono abbassare le prestazioni.
-Seleziona Vista &gt; Barra statistiche e guarda sotto Simulatore &gt; Tempi &gt; Tempo Script per controllare se un tempo di più di 20 ms è impiegato per gli script.
+Seleziona Visualizza &gt; Barra della statistiche e guarda sotto Simulator (Simulatore) &gt; Time (Tempi) &gt; Script Time (Tempo Script) per controllare se un tempo di più di 20 ms è impiegato per gli script.
</notification>
<notification label="Fai ripartire la regione" name="HelpRegionRestart">
Fai ripartire i processi del server che gestisce questa regione dopo un avvertimento di due minuti. Tutti i residenti nella regione verranno scollegati.
@@ -1891,14 +1893,14 @@ Lasciandolo vuoto causerà l&apos;invio delle segnalazioni di abuso soltanto ai
Impostazione base: spento
</notification>
<notification label="Versione voice non compatibile" name="VoiceVersionMismatch">
- Questa versione di Second Life non è compatibile con le impostazioni di voice chat di questa regione. Per poter fare funzionare correttamente la chat voce devi aggiornare Second Life.
+ Questa versione di [APP_NAME] non è compatibile con le impostazioni di voice chat di questa regione. Per poter fare funzionare correttamente la chat voce devi aggiornare [APP_NAME].
</notification>
<notification label="Regolamento della proprietà" name="HelpEstateCovenant">
Impostare un regolamento della proprietà ti consente di vendere i terreni all&apos;interno di quella proprietà. Se non imposti un regolamento, non puoi vendere i terreni. La notecard per il tuo regolamente può essere vuota se non desideri applicare nessuna regola o informare i compratori di cose inerenti la terra, prima dell&apos;acquisto.
Un regolamento può essere usato per comunicare regole, linee guida, informazioni culturali o semplicemente ciò che ti aspetti dal possibile compratore. Questo può includere impostazioni in zone, regolamenti architettonici, opzioni di pagamento o qualunque altra informazione che ritieni importante che il nuovo proprietario debba aver visto e accettato prima dell&apos;acquisto.
-Il compratore deve accettare il regolamento selezionando la casella appropriata per poter completare l&apos;acquisto. I regolamenti delle proprietà sono sempre visibili nella finestra &quot;Informazioni sul terreno&quot; in tutti gli appezzamenti in cui è stato impostato.
+Il compratore deve accettare il regolamento selezionando la casella appropriata per poter completare l&apos;acquisto. I regolamenti delle proprietà sono sempre visibili nella finestra &apos;Informazioni sul terreno&apos; in tutti gli appezzamenti in cui è stato impostato.
</notification>
<notification label="Impossibile comprare oggetti" name="BuyObjectOneOwner">
Impossibile comprare oggetti da proprietari diversi nello stesso momento.
@@ -1959,20 +1961,20 @@ Il contenuto verrà copiato nel tuo inventario.
<usetemplate name="okcancelbuttons" notext="Annulla" yestext="OK"/>
</notification>
<notification name="ConfirmPurchase">
- Questa transazione farà:
+ Questa transazione ti permetterà di:
[ACTION]
Confermi di voler procedere all&apos;acquisto?
<usetemplate name="okcancelbuttons" notext="Annulla" yestext="OK"/>
</notification>
- <notification name="ConfirmPurchasePassword" type="password">
+ <notification name="ConfirmPurchasePassword">
Questa transazione farà:
[ACTION]
Confermi di voler procedere all&apos;acquisto?
Ridigita la tua password e premi OK.
<form name="form">
- <input name="message" type="password"/>
+ <input name="message"/>
<button name="ConfirmPurchase" text="OK"/>
<button name="Cancel" text="Annulla"/>
</form>
@@ -1987,41 +1989,38 @@ Hai aggiornato l&apos;ubicazione di questo preferito ma gli altri dettagli conse
Questi elementi verranno trasferiti nel tuo inventario, ma non copiati.
Trasferisci gli elementi nell&apos;inventario?
- <usetemplate ignoretext="Quando si trasferiscono, dagli oggetti all&apos;inventario, elementi non copiabili" name="okcancelignore" notext="Annulla" yestext="OK"/>
+ <usetemplate ignoretext="Quando si trasferiscono elementi non copiabili, dagli oggetti all&apos;inventario." name="okcancelignore" notext="Annulla" yestext="OK"/>
</notification>
<notification name="MoveInventoryFromScriptedObject">
Hai selezionato elementi dell&apos;inventario non copiabili. Questi elementi verranno trasferiti nel tuo inventario, non verranno copiati.
Dato che questo oggetto è scriptato, il trasferimento di questi elementi nel tuo inventario potrebbe causare un malfunzionamento degli script.
Trasferisci gli elementi nell&apos;inventario?
- <usetemplate ignoretext="Quando si trasferiscono oggetti scriptati non copiabili nell&apos;inventario" name="okcancelignore" notext="Annulla" yestext="OK"/>
+ <usetemplate ignoretext="Quando si trasferiscono oggetti scriptati non copiabili nell&apos;inventario." name="okcancelignore" notext="Annulla" yestext="OK"/>
</notification>
<notification name="ClickActionNotPayable">
- Attenzione: L&apos;azione di pagamento automatico al click è stata impostata, ma funzionerà solo se aggiungi uno script con un evento money().
+ Attenzione: L&apos;azione &apos;Paga l&apos;oggetto&apos; al click è stata impostata, ma funzionerà solo se aggiungi uno script con un evento money().
<form name="form">
- <ignore name="ignore" text="Quando imposti il &quot;Pagamento&quot; di oggetti senza l&apos;evento money()"/>
+ <ignore name="ignore" text="Quando imposti il &apos;Paga l&apos;oggetto&apos; senza l&apos;evento money()"/>
</form>
</notification>
<notification name="OpenObjectCannotCopy">
Non ci sono elementi in questo oggetto che tu possa copiare.
</notification>
<notification name="WebLaunchAccountHistory">
- Vai nel sito web di Second Life per vedere il tuo estratto conto?
- <usetemplate ignoretext="Quando carichi la pagina web dell&apos;estratto conto" name="okcancelignore" notext="Annulla" yestext="Vai alla pagina"/>
+ Vai nel sito web di [SECOND_LIFE] per vedere il tuo estratto conto?
+ <usetemplate ignoretext="Quando carichi la pagina web dell&apos;estratto conto." name="okcancelignore" notext="Annulla" yestext="Vai alla pagina"/>
</notification>
<notification name="ClickOpenF1Help">
- Visita il sito di supporto di Second Life?
- <usetemplate ignoretext="Quando visiti il sito del supporto di Second Life." name="okcancelignore" notext="Annulla" yestext="Vai"/>
+ Visita il sito di supporto di [SECOND_LIFE]?
+ <usetemplate ignoretext="Quando visiti il sito del supporto di [SECOND_LIFE]." name="okcancelignore" notext="Annulla" yestext="Vai"/>
</notification>
<notification name="ConfirmQuit">
Confermi di voler uscire?
- <usetemplate ignoretext="Quando esci da Second Life." name="okcancelignore" notext="Continua" yestext="Esci"/>
+ <usetemplate ignoretext="Quando esci da [APP_NAME]." name="okcancelignore" notext="Continua" yestext="Esci"/>
</notification>
<notification name="HelpReportAbuseEmailLL">
- Usa questo strumento per segnalare violazioni ai Termini di Servizio e agli standard della Comunità. Vedi:
-
-http://secondlife.com/corporate/tos.php
-http://secondlife.com/corporate/cs.php
+ Usa questo strumento per segnalare violazioni ai [http://secondlife.com/corporate/tos.php?lang=it-IT Termini di Servizio] e agli [http://secondlife.com/corporate/cs.php?lang=it-IT standard della Comunità].
Tutte gli abusi ai Termini di Servizio e agli Standard della Comunità segnalati, sono indagati e risolti. Puoi controllare la risoluzione degli abusi visitando la pagina delle Risoluzioni degli Incidenti:
@@ -2035,27 +2034,12 @@ Come servizio ai residenti e ai visitatori, il proprietario della regione in cui
Il proprietario della regione risolverà le segnalazione basandosi sulle regole locali di questa regione così come sono indicate dal regolamento della proprietà.
(Puoi vedere il regolamento andando sul menu Mondo e selezionando Informazioni sul terreno.)
-La risoluzione di questa segnalazione verrà applicata solo in questa regione; L&apos;accesso dei residenti ad altre aree di Second Life non verrà influenzato dal risultato di questa segnalazione. Soltanto i Linden Lab possono restringere l&apos;accesso alla totalità di Second Life.
- </notification>
- <notification name="HelpReportBug">
- Usa questo strumento per segnalare *soltanto* caratteristiche tecniche che non funzionano come descitto o atteso, fornisci quanti più dettagli è possibile, Puoi rispondere all&apos;email automatica aggiungendo ulteriori dettagli sulla tua segnalazione.
-
-Tutte le segnalazioni di bug sono investigate e valutate. Non vengono inviate risposte via email.
-
-Se hai difficoltà tecniche contatta il supporto:
-
-http://secondlife.com/community/support.php
-
-Nota: segnalazioni incomplete non verranno prese in considerazione
+La risoluzione di questa segnalazione verrà applicata solo in questa regione; L&apos;accesso dei residenti ad altre aree di [SECOND_LIFE] non verrà influenzato dal risultato di questa segnalazione. Soltanto i Linden Lab possono restringere l&apos;accesso alla totalità di [SECOND_LIFE].
</notification>
<notification name="HelpReportAbuseSelectCategory">
Scegli una categoria per questa segnalazione di abuso.
Scegliere una categoria, ci aiuta a gestire ed elaborare le segnalazioni di abuso.
</notification>
- <notification name="HelpReportBugSelectCategory">
- Scegli una categoria per questo bug.
-Scegliere una categoria, ci aiuta a gestire ed elaborare le segnalazioni di bug.
- </notification>
<notification name="HelpReportAbuseAbuserNameEmpty">
Introduci il nome di chi abusa.
Introducendo un valore accurato, ci aiuti a gestire ed elaborare le segnalazioni di abuso.
@@ -2068,28 +2052,19 @@ Introducendo un valore accurato, ci aiuti a gestire ed elaborare le segnalazioni
Inserisci un yiyolo descrittivo dell&apos;abuso che è avvenuto.
Introducendo un titolo descrittivo accurato, ci aiuti a gestire ed elaborare le segnalazioni di abuso.
</notification>
- <notification name="HelpReportBugSummaryEmpty">
- Introduci una descrizione del bug.
-Introducendo una descrizione accurata ci aiuti a gestire ed elaborare le segnalazioni di bug.
- </notification>
<notification name="HelpReportAbuseDetailsEmpty">
Inserisci una descrizione dettagliata dell&apos;abuso che è avvenuto.
Devi essere il più specifico possibile, includendo i nomi e i dettagli dell&apos;incidente che stai segnalando.
Inserendo una descrizione accurata ci aiuti a gestire ed elaborare le segnalazioni di abuso.
</notification>
- <notification name="HelpReportBugDetailsEmpty">
- Inserisci una descrizione dettagliata del bug.
-Devi essere il pià specifico possibile, includendo se possibil i passi per riprodurre il problema.
-Inserendo una descrizione accurata, ci aiuti a gestire ed elaborare le segnalazioni di bug.
- </notification>
<notification name="HelpReportAbuseContainsCopyright">
Caro residente,
Sembra che stai segnalando un problema di furto di proprietà intellettuale. Cerca di essere sicuro che la tua segnalazione stia riportando correttamente:
-(1) Il processo di abuso. Puoi sottomettere una segnalazione di abuso se ritieni che un residente stia sfruttando il sistema di permessi di Second Life, per esempio, usando CopyBot oppure simili strumenti di copia, per rubare i diritti della proprietà intellettuale. L&apos;ufficio Abusi investigherà e deciderà delle azioni disciplinari adeguate per comportamenti che violano gli standard di comunità di Second Life o i Termini di Servizio. Si tenga però presente che l&apos;ufficio Abusi non gestisce e non risponde alle richieste di rimozione di contenuto da Second Life.
+(1) Il processo di abuso. Puoi sottomettere una segnalazione di abuso se ritieni che un residente stia sfruttando il sistema di permessi di [SECOND_LIFE], per esempio, usando CopyBot oppure simili strumenti di copia, per rubare i diritti della proprietà intellettuale. L&apos;ufficio Abusi investigherà e deciderà delle azioni disciplinari adeguate per comportamenti che violano gli standard di comunità di [SECOND_LIFE] o i Termini di Servizio. Si tenga però presente che l&apos;ufficio Abusi non gestisce e non risponde alle richieste di rimozione di contenuto da [SECOND_LIFE].
-(2) Il processo di rimozione DMCA o processo di rimozione dei contenuti. Per richiedere la rimozione di contenuto da Second Life, DEVI sottomettere una notifica valida di furto intellettuale come definito nella nostra politica DMCA che trovi a http://secondlife.com/corporate/dmca.php.
+(2) Il processo di rimozione DMCA o processo di rimozione dei contenuti. Per richiedere la rimozione di contenuto da [SECOND_LIFE], DEVI sottomettere una notifica valida di furto intellettuale come definito nella nostra politica DMCA che trovi a http://secondlife.com/corporate/dmca.php.
Se desideri egualmente continuare con il processo di abuso, chiudi questa finestra e termina di compilare la segnalazione. Potresti dover selezionare la categoria specifica &apos;CopyBot o Sfruttamento permessi&apos;.
@@ -2104,7 +2079,7 @@ La Linden Lab
C&apos;è già un oggetto indossato in questo punto del corpo.
Vuoi sostituirlo con l&apos;oggetto selezionato?
<form name="form">
- <ignore name="ignore" save_option="true" text="Quando avviene la sostituzione di un oggetto indossato già esistente"/>
+ <ignore name="ignore" save_option="true" text="Quando avviene la sostituzione di un oggetto indossato già esistente."/>
<button name="Yes" text="OK"/>
<button name="No" text="Annulla"/>
</form>
@@ -2114,14 +2089,14 @@ Vuoi sostituirlo con l&apos;oggetto selezionato?
Desideri abbandonare la modalità &apos;Occupato&apos; prima di completare questa transazione?
<form name="form">
- <ignore name="ignore" save_option="true" text="Quando avviene il pagamento di una persona o oggetto in modalità &apos;Occupato&apos;"/>
+ <ignore name="ignore" save_option="true" text="Quando avviene il pagamento di una persona o di un oggetto in modalità &apos;Occupato&apos;."/>
<button name="Yes" text="OK"/>
<button name="No" text="Abbandona"/>
</form>
</notification>
<notification name="ConfirmEmptyTrash">
Confermi di volere permanentemente rimuovere il contenuto del tuo cartella Cestino?
- <usetemplate ignoretext="Quando svuoti la cartella cestino del tuo inventario" name="okcancelignore" notext="Annulla" yestext="OK"/>
+ <usetemplate ignoretext="Quando svuoti la cartella cestino del tuo inventario." name="okcancelignore" notext="Annulla" yestext="OK"/>
</notification>
<notification name="ConfirmClearBrowserCache">
Confermi di voler pulire la cache del tuo browser?
@@ -2137,15 +2112,15 @@ Desideri abbandonare la modalità &apos;Occupato&apos; prima di completare quest
</notification>
<notification name="ConfirmEmptyLostAndFound">
Confermi di volere rimuovere permanentemente il contenuto della tua cartalla Persi e ritrovati?
- <usetemplate ignoretext="Quando cancelli la cartella persi e ritrovati del tuo inventario" name="okcancelignore" notext="No" yestext="Si"/>
+ <usetemplate ignoretext="Quando cancelli la cartella degli oggetti perduti e ritrovati del tuo inventario." name="okcancelignore" notext="No" yestext="Si"/>
</notification>
<notification name="CopySLURL">
- Lo SLURL seguente è stato copiato nei tuoi appunti:
+ Lo SLurl seguente è stato copiato nei tuoi appunti:
[SLURL]
Lo puoi inserire in una pagina web per dare ad altri modo di accedere a questo posto o puoi provare a copiarla nella barra indirizzi del tuo browser web.
<form name="form">
- <ignore name="ignore" text="Quando copi lo SLURL negli appunti"/>
+ <ignore name="ignore" text="Quando copi uno SLurl negli appunti."/>
</form>
</notification>
<notification name="GraphicsPreferencesHelp">
@@ -2196,30 +2171,30 @@ Dettaglio del terreno: Imposta la quantità di dettagli che vuoi vedere per le t
<notification name="EnvSettingsHelpButton">
Queste impostazioni modificano il modo in cui l&apos;ambiente viene visto localmente sul tuo computer. La tua scheda grafica deve supportare gli effetti atmosferici per poter accedere a tutte le impostazioni.
-Modifica il cursore &quot;Ora del Giorno &quot; per cambiare la fase giornaliera locale sul client.
+Modifica il cursore &apos;Ora del Giorno&apos; per cambiare la fase giornaliera locale sul client.
-Modifica il cursore &quot;Intensità delle nuvole&quot; per controllare la quantità di nuvole che coprono il cielo.
+Modifica il cursore &apos;Intensità delle nuvole&apos; per controllare la quantità di nuvole che coprono il cielo.
-Scegli un colore nella tavolozza colori per il &quot;colore dell&apos;acqua&quot; per cambiare il colore dell&apos;acqua.
+Scegli un colore nella tavolozza colori per il &apos;colore dell&apos;acqua&apos; per cambiare il colore dell&apos;acqua.
-Modifica il cursore &quot;Nebbiosità dell&apos;acqua&quot; per controllare quanto densa è la nebbia sott&apos;acqua.
+Modifica il cursore &apos;Nebbiosità dell&apos;acqua&apos; per controllare quanto densa è la nebbia sott&apos;acqua.
-Clicca &quot;Usa l&apos;ora della proprietà&quot; per sincronizzare il tempo del giorno con l&apos;ora del giorno della regione e collegarle stabilmente.
+Clicca &apos;Usa l&apos;ora della proprietà&apos; per sincronizzare il tempo del giorno con l&apos;ora del giorno della regione e collegarle stabilmente.
-Clicca &quot;Cielo avanzato&quot; per visualizzare un editor con le impostazioni avanzate per il cielo.
+Clicca &apos;Cielo avanzato&apos; per visualizzare un editor con le impostazioni avanzate per il cielo.
-Clicca &quot;Acqua Avanzata&quot; per visualizzare un editor con le impostazini avanzate per l&apos;acqua.
+Clicca &apos;Acqua Avanzata&apos; per visualizzare un editor con le impostazini avanzate per l&apos;acqua.
</notification>
<notification name="HelpDayCycle">
- L&apos;editor del Ciclo Giorno/Notte permette di controllare il cielo durante il ciclo giornaliero di Second Life. Questo è il ciclo che è usato dal cursore dell&apos;editor base dell&apos;ambiente.
+ L&apos;editor del Ciclo Giorno/Notte permette di controllare il cielo durante il ciclo giornaliero di [SECOND_LIFE]. Questo è il ciclo che è usato dal cursore dell&apos;editor base dell&apos;ambiente.
-L&apos;editor del ciclo giorno/notte funziona impostando i fotogrammi chiave. Questi sono nodi (rappresentati da tacche grige sul grafico temporale) che hanno delle preregolazioni associate del cielo. Man mano che l&apos;ora del giorno procede, il cielo di WindLight&quot;si anima&quot; interpolando i valori fra questi fotogrammi chiave.
+L&apos;editor del ciclo giorno/notte funziona impostando i fotogrammi chiave. Questi sono nodi (rappresentati da tacche grige sul grafico temporale) che hanno delle preregolazioni associate del cielo. Man mano che l&apos;ora del giorno procede, il cielo di WindLight&apos;si anima&apos; interpolando i valori fra questi fotogrammi chiave.
La freccia gialla sopra la linea del tempo rappresenta la tua vista corrente, basata sull&apos;ora del giorno. Cliccandola e spostandola vedrai come il giorno si animerebbe. Si può aggiungere o cancellare fotogrammi chiave cliccando sui tasti &apos;Aggiungi Fotogramma Chiave&apos; e &apos;Cancella Fotogramma Chiave&apos; alla destra della linea del tempo.
Si possono impostare le posizioni temporali dei fotogrammi chiave spostandole lungo la linea del tempo o impostando il loro valore a mano nella finestra di impostazione dei fotogrammi chiave. All&apos;interno della finestra di impostazione si può associare il fotogramma chiave con le impostazioni corrispondenti di Wind Light.
-La durata del ciclo definisce la durata complessiva di un &quot;giorno&quot;. Impostando questo ad un valore basso (per esempio, 2 minuti) tutto il ciclo di 24 ore verrà completato in solo 2 minuti reali! Una volta soddisfatto dell tua linea del tempo e le impostazioni dei fotogrammi chiave, usa i bottoni Play e Stop per vederne in anteprima i risultati. Attenzione: si può sempre spostare la freccia gialla indicatrice del tempo sopra la linea del tempo per vedere il ciclo animarsi interattivamente. Scegliendo invece il pulsanto &apos;Usa il tempo della regione&apos; ci si sincronizza con il le durate del ciclo definite per questa regione.
+La durata del ciclo definisce la durata complessiva di un &apos;giorno&apos;. Impostando questo ad un valore basso (per esempio, 2 minuti) tutto il ciclo di 24 ore verrà completato in solo 2 minuti reali! Una volta soddisfatto dell tua linea del tempo e le impostazioni dei fotogrammi chiave, usa i bottoni Play e Stop per vederne in anteprima i risultati. Attenzione: si può sempre spostare la freccia gialla indicatrice del tempo sopra la linea del tempo per vedere il ciclo animarsi interattivamente. Scegliendo invece il pulsanto &apos;Usa il tempo della regione&apos; ci si sincronizza con il le durate del ciclo definite per questa regione.
Una volta soddisfatto del ciclo giornaliero, puoi salvarlo o ricaricarlo con i bottoni &apos;Salva test del giorno&apos; e &apos;Carica il test del giorno&apos;. Attualmente è possibile definire un solo ciclo giorno/notte
</notification>
@@ -2239,7 +2214,7 @@ E&apos; utile per simulare scene con un livello alto di fumo e di inquinamento d
E&apos; anche utile per simulare la nebbia e la foschia al mattino.
</notification>
<notification name="HelpDensityMult">
- Il moltiplicatore di densità può essere usato per influenzare la densità atmosferica generale. Con valori bassi, crea la sensazione di &quot;aria sottile&quot;, con valori alti crea un effetto molto pesante, annebbiato.
+ Il moltiplicatore di densità può essere usato per influenzare la densità atmosferica generale. Con valori bassi, crea la sensazione di &apos;aria sottile&apos;, con valori alti crea un effetto molto pesante, annebbiato.
</notification>
<notification name="HelpDistanceMult">
Modifica la distanza percepita da WindLight.
@@ -2248,7 +2223,7 @@ Valori più grandi di 1 simulano distanze più grandi per effetti atmosferici pi
</notification>
<notification name="HelpMaxAltitude">
Altitudine Massima modifica i calcoli di altezza che fa WindLight quando calcola l&apos;illuminazione atmosferica.
-In periodi successivi del giorno, è utile per modificare quanto &quot;profondo&quot; appaia il tramonto.
+In periodi successivi del giorno, è utile per modificare quanto &apos;profondo&apos; appaia il tramonto.
</notification>
<notification name="HelpSunlightColor">
Modifica il colore e l&apos;intensità della luce diretta nella scena.
@@ -2257,8 +2232,8 @@ In periodi successivi del giorno, è utile per modificare quanto &quot;profondo&
Modifica il colore e l&apos;intensità della luce atmosferica ambientale nella scena.
</notification>
<notification name="HelpSunGlow">
- Il cursore Dimensione controlla la dimensione del sole.
-Lo slider &quot;Focus&quot; controlla quanto è offuscato il sole sopra il cielo.
+ Il cursore Grandezza controlla la dimensione del sole.
+Il cursore Focus controlla quanto è offuscato il sole sopra il cielo.
</notification>
<notification name="HelpSceneGamma">
Modifica la distribuzione di luci e ombre nello schermo.
@@ -2342,7 +2317,7 @@ D (Densità) controlla quanto gonfie o spezzettate appaiono le nuvole.
<notification name="NewSkyPreset">
Fornisci il nome per il nuovo cielo.
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Nuova preimpostazione
</input>
<button name="OK" text="OK"/>
@@ -2355,7 +2330,7 @@ D (Densità) controlla quanto gonfie o spezzettate appaiono le nuvole.
<notification name="NewWaterPreset">
Fornisci il nome per la nuova preregolazione del livello dell&apos;acqua.
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Nuova preimpostazione
</input>
<button name="OK" text="OK"/>
@@ -2392,27 +2367,27 @@ D (Densità) controlla quanto gonfie o spezzettate appaiono le nuvole.
</notification>
<notification name="AutoWearNewClothing">
Vuoi indossare automaticamente i vestiti che crei?
- <usetemplate ignoretext="Indossa automaticamente i nuovi vestiti." name="okcancelignore" notext="No" yestext="Si"/>
+ <usetemplate ignoretext="Quando Indossi automaticamente nuovi vestiti." name="okcancelignore" notext="No" yestext="Si"/>
</notification>
<notification name="NotAgeVerified">
La tua età deve essere verificata per poter entrare in questo territorio.
-Vuoi visitare il sito di Second Life per verificare la tua eta?
+Vuoi visitare il sito di [SECOND_LIFE] per verificare la tua eta?
[_URL]
<url name="url" option="0">
- https://secondlife.com/account/verification.php
+ https://secondlife.com/account/verification.php?lang=it
</url>
- <usetemplate ignoretext="Avviso per mancanza della verifica dell&apos;età" name="okcancelignore" notext="No" yestext="Si"/>
+ <usetemplate ignoretext="Quando hai un avviso per mancanza della verifica dell&apos;età." name="okcancelignore" notext="No" yestext="Si"/>
</notification>
<notification name="Cannot enter parcel: no payment info on file">
Questo terreno richiede che tu abbia registrato le tue informazioni di pagamento prima che tu possa accedervi.
-Vuoi visitare il sito di Second Life per impostarle?
+Vuoi visitare il sito di [SECOND_LIFE] per impostarle?
[_URL]
<url name="url" option="0">
https://secondlife.com/account/index.php?lang=it
</url>
- <usetemplate ignoretext="Avviso per mancanza di informazioni di pagamento registrato" name="okcancelignore" notext="No" yestext="Si"/>
+ <usetemplate ignoretext="Quando hai un avviso per mancanza di informazioni di pagamento registrate." name="okcancelignore" notext="No" yestext="Si"/>
</notification>
<notification name="MissingString">
La stringa [STRING_NAME] non è presente in strings.xml
@@ -2673,7 +2648,7 @@ Vai alla &apos;Help Island Public&apos; per ripetere il tutorial.
<notification name="ImproperPaymentStatus">
Non hai una impostazioni di pagamento corrette per entrare in questa regione.
</notification>
- <notification name="MustGetAgeRgion">
+ <notification name="MustGetAgeRegion">
Devi avere un&apos;età verificata per entrare in questa regione.
</notification>
<notification name="MustGetAgeParcel">
@@ -2723,13 +2698,13 @@ Riprova tra qualche istante.
Impossibile creare la connessione in sospeso.
</notification>
<notification name="InternalUsherError">
- Si è verificato un errore interno durante il tentativo di trasportarti alla destinazione. Potrebbero esserci problemi in Second Life al momento.
+ Si è verificato un errore interno durante il tentativo di trasportarti alla destinazione. Potrebbero esserci problemi in [SECOND_LIFE] al momento.
</notification>
<notification name="NoGoodTPDestination">
Impossibile trovare una buona destinazione per il teletrasporto in questa regione.
</notification>
<notification name="InternalErrorRegionResolver">
- Si è verificato un errore interno durante il tentativo di risolvere le coordinate per la richiesta di teletrasporto. Può darsi che ci siano problemi in Second Life al momento.
+ Si è verificato un errore interno durante il tentativo di risolvere le coordinate per la richiesta di teletrasporto. Può darsi che ci siano problemi in [SECOND_LIFE] al momento.
</notification>
<notification name="NoValidLanding">
Non è stato trovato un punto di atterraggio valido.
@@ -2851,7 +2826,7 @@ Dall&apos;oggetto: [OBJECTNAME], di: [NAME]?
Impossibile trovare [TYPE] chiamato [DESC] nel database.
</notification>
<notification name="InvalidWearable">
- L&apos;oggetto che si sta tentando di indossare utilizza una funzione che il programma non riesce a leggere. Aggiorna la tua versione di Second Life per riuscire a indossare l&apos;oggetto.
+ L&apos;oggetto che si sta tentando di indossare utilizza una funzione che il programma non riesce a leggere. Aggiorna la tua versione di [APP_NAME] per riuscire a indossare l&apos;oggetto.
</notification>
<notification name="ScriptQuestion">
&apos;[OBJECTNAME]&apos;, un oggetto di proprietà di &apos;[NAME]&apos;, vorrebbe:
@@ -2956,8 +2931,8 @@ Gli oggetti flessibili non possono essere fisici e devano essere fantasma fino a
</notification>
<notification name="FirstDebugMenus">
Hai attivato il menu Avanzato.
-Questo menu contiene funzioni utili per gli sviluppatori per il debug di Second Life.
-Per attivare o disattivare questo menu su Windows premere Ctrl-Alt-D. Su Mac premere Cmd-Opt-Shift-D.
+Questo menu contiene funzioni utili per gli sviluppatori per il debug di [SECOND_LIFE].
+Per attivare o disattivare questo menu su Windows premere Ctrl+Alt+D. Su Mac premere &#8997;&#8984;D.
</notification>
<notification name="FirstSculptedPrim">
Si sta modificando uno sculpted prim.
@@ -3064,7 +3039,7 @@ Fai clic su Accetta per partecipare alla chiamata o su Rifiuta per rifiutare l&a
- La velocità della tua CPU non soddisfa i requisiti minimi.
</global>
<global name="UnsupportedGLRequirements">
- Sembra che tu non abbia i requisiti appropriati hardware per Second Life. Second Life ha bisogno di una scheda grafica OpenGL che abbia il supporto multitexture. Se ritieni di avere l&apos;hardware giusto verifica di avere installati i driver più aggiornati per la tua scheda grafica e gli aggiornamenti e service pack appropriati per il tuo sistema operativo.
+ Sembra che tu non abbia i requisiti appropriati hardware per [APP_NAME]. [APP_NAME] ha bisogno di una scheda grafica OpenGL che abbia il supporto multitexture. Se ritieni di avere l&apos;hardware giusto verifica di avere installati i driver più aggiornati per la tua scheda grafica e gli aggiornamenti e service pack appropriati per il tuo sistema operativo.
Se continui ad avere problemi, visita il sito: http://www.secondlife.com/support
</global>
diff --git a/indra/newview/skins/default/xui/it/panel_edit_profile.xml b/indra/newview/skins/default/xui/it/panel_edit_profile.xml
new file mode 100644
index 0000000000..33f3c367c2
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_edit_profile.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel name="edit_profile_panel">
+ <string name="CaptionTextAcctInfo">
+ [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION]
+ </string>
+ <string name="AcctTypeResident"
+ value="Residente" />
+ <string name="AcctTypeTrial"
+ value="Prova" />
+ <string name="AcctTypeCharterMember"
+ value="Membro privilegiato" />
+ <string name="AcctTypeEmployee"
+ value="Impiegato della Linden Lab" />
+ <string name="PaymentInfoUsed"
+ value="Info. di pagamento usate" />
+ <string name="PaymentInfoOnFile"
+ value="Info. di pagamento in archivio" />
+ <string name="NoPaymentInfoOnFile"
+ value="Nessuna info. di pagamento" />
+ <string name="AgeVerified"
+ value="Età verificata" />
+ <string name="NotAgeVerified"
+ value="Età non verificata" />
+ <string name="partner_edit_link_url">
+ http://www.secondlife.com/account/partners.php?lang=it
+ </string>
+ <panel name="scroll_content_panel">
+ <panel name="data_panel" >
+ <panel name="lifes_images_panel">
+ <panel name="second_life_image_panel">
+ <text name="second_life_photo_title_text">
+ [SECOND_LIFE]:
+ </text>
+ </panel>
+ </panel>
+ <text name="title_partner_text" value="Partner:"/>
+ <panel name="partner_data_panel">
+ <text name="partner_text" value="[FIRST] [LAST]"/>
+ </panel>
+ <text name="text_box3">
+ Risposta agli IM quando sono in &apos;Occupato&apos;:
+ </text>
+ </panel>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_friends.xml b/indra/newview/skins/default/xui/it/panel_friends.xml
index 78e0d542f3..e2eb3dd6e7 100644
--- a/indra/newview/skins/default/xui/it/panel_friends.xml
+++ b/indra/newview/skins/default/xui/it/panel_friends.xml
@@ -16,5 +16,5 @@
<button label="Teleport..." name="offer_teleport_btn" tool_tip="Offri a questo amico un teleport per dove sei tu ora"/>
<button label="Paga..." name="pay_btn" tool_tip="Dai Linden dollar (L$) a questo amico"/>
<button label="Rimuovi..." name="remove_btn" tool_tip="Rimuovi questa persona dalla tua lista amici"/>
- <button label="Aggiungi come amico..." name="add_btn" tool_tip="Offri amicizia ad un residente"/>
+ <button label="Aggiungi..." name="add_btn" tool_tip="Offri amicizia ad un residente"/>
</panel>
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 cc044a2e56..2bc4d82082 100644
--- a/indra/newview/skins/default/xui/it/panel_group_general.xml
+++ b/indra/newview/skins/default/xui/it/panel_group_general.xml
@@ -1,9 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Generale" name="general_tab">
<string name="help_text">
- Il pannello &apos;Generale&apos; contiene informazioni generali riguardanti il
-gruppo, un elenco dei proprietari e i membri visibili,
-le preferenze generali di gruppo e le opzioni dei membri.
+ Il pannello &apos;Generale&apos; contiene informazioni generali riguardanti il gruppo, un elenco dei proprietari e i membri visibili, le preferenze generali di gruppo e le opzioni dei membri.
Passa il mouse sulle opzioni per un aiuto aggiuntivo.
</string>
@@ -37,9 +35,9 @@ Passa il mouse sulle opzioni per un aiuto aggiuntivo.
(I proprietari sono scritti in neretto)
</text>
<name_list name="visible_members">
- <column label="Nome del membro" name="name"/>
- <column label="Titolo" name="title"/>
- <column label="Ultimo login" name="online"/>
+ <name_list.columns label="Nome del membro" name="name"/>
+ <name_list.columns label="Titolo" name="title"/>
+ <name_list.columns label="Ultimo login" name="online"/>
</name_list>
<text name="text_group_preferences">
Preferenze di gruppo
@@ -47,18 +45,12 @@ Passa il mouse sulle opzioni per un aiuto aggiuntivo.
<panel name="preferences_container">
<check_box label="Mostra nella ricerca" name="show_in_group_list" tool_tip="Lascia che i residenti vedano questo gruppo nella ricerca."/>
<check_box label="Iscrizione libera" name="open_enrollement" tool_tip="Imposta se questo gruppo permette ai nuovi membri di unirsi senza essere invitati."/>
- <check_box label="Tassa di iscrizione: L$" name="check_enrollment_fee" tool_tip="Imposta se richiedere una tassa di iscrizione per unirsi al gruppo."/>
- <spinner name="spin_enrollment_fee" tool_tip="I nuovi membri devono pagare questa tassa per unirsi al gruppo. La tassa di iscrizione è selezionata."/>
+ <check_box label="Tassa di iscrizione:" name="check_enrollment_fee" tool_tip="Imposta se richiedere una tassa di iscrizione per unirsi al gruppo."/>
+ <spinner width="60" left_delta="136" name="spin_enrollment_fee" tool_tip="I nuovi membri devono pagare questa tassa per unirsi al gruppo. La tassa di iscrizione è selezionata."/>
<combo_box name="group_mature_check" tool_tip="Imposta se le informazioni sul tuo gruppo sono da considerarsi Mature.">
- <combo_item name="select_mature">
- - Seleziona -
- </combo_item>
- <combo_item name="mature">
- Contenuto Mature
- </combo_item>
- <combo_item name="pg">
- Contenuto PG
- </combo_item>
+ <combo_box.item name="select_mature" label="- Seleziona -"/>
+ <combo_box.item name="mature" label="Contenuto Mature"/>
+ <combo_box.item name="pg" label="Contenuto PG"/>
</combo_box>
<panel name="title_container">
<text name="active_title_label">
diff --git a/indra/newview/skins/default/xui/it/panel_group_invite.xml b/indra/newview/skins/default/xui/it/panel_group_invite.xml
index d75b3a46e8..cc426f7cd2 100644
--- a/indra/newview/skins/default/xui/it/panel_group_invite.xml
+++ b/indra/newview/skins/default/xui/it/panel_group_invite.xml
@@ -2,8 +2,8 @@
<panel label="Invita una persona" name="invite_panel">
<text name="help_text">
Puoi selezionare più di un residente
-da invitare nel tuo gruppo. Clicca su &apos;Scelta
-residenti&apos; per iniziare.
+da invitare nel tuo gruppo. Clicca su
+&apos;Scelta residenti&apos; per iniziare.
</text>
<button label="Scelta residenti" name="add_button" tool_tip=""/>
<name_list name="invitee_list" tool_tip="Tieni premuto il tasto ctrl e clicca i nomi dei residenti per avere una selezione multipla."/>
diff --git a/indra/newview/skins/default/xui/it/panel_group_land_money.xml b/indra/newview/skins/default/xui/it/panel_group_land_money.xml
index 907ce8ea5a..3e6684ed06 100644
--- a/indra/newview/skins/default/xui/it/panel_group_land_money.xml
+++ b/indra/newview/skins/default/xui/it/panel_group_land_money.xml
@@ -13,7 +13,7 @@
<string name="loading_txt">
Attendi...
</string>
- <text name="group_land_heading">
+ <text name="group_land_heading" width="250">
Terra posseduta dal gruppo
</text>
<scroll_list name="group_parcel_list">
@@ -22,24 +22,24 @@
<column label="Tipo" name="type"/>
<column label="Area" name="area"/>
</scroll_list>
- <button label="Mostra sulla mappa" label_selected="Mostra sulla mappa" name="map_button"/>
+ <button label="Mostra sulla mappa" label_selected="Mostra sulla mappa" name="map_button" left="282" width="130"/>
<text name="total_contributed_land_label">
Total Contribution:
</text>
<text name="total_contributed_land_value">
- [AREA] metri quadri
+ [AREA] m²
</text>
<text name="total_land_in_use_label">
Terra totale in uso:
</text>
<text name="total_land_in_use_value">
- [AREA] metri quadri
+ [AREA] m²
</text>
<text name="land_available_label">
Terra disponibile:
</text>
<text name="land_available_value">
- [AREA] metri quadri
+ [AREA] m²
</text>
<text name="your_contribution_label">
Il tuo contributo:
@@ -47,11 +47,15 @@
<string name="land_contrib_error">
Non è possibile impostare i tuoi contributi in terra.
</string>
+ <text name="your_contribution_units">
+ ( m² )
+ </text>
<text name="your_contribution_max_value">
- metri quadri ([AMOUNT] massimo)
+ ([AMOUNT] massimo)
</text>
<text name="group_over_limit_text">
- I membri del gruppo devono contribuire con più crediti per mantenere la quantità  di terra in uso.
+ I membri del gruppo devono contribuire con più crediti per mantenere
+la quantità  di terra in uso.
</text>
<text name="group_money_heading">
L$ del gruppo
@@ -66,15 +70,15 @@
<text_editor name="group_money_details_text">
Calcolo...
</text_editor>
- <button label="&lt; Precedente" label_selected="&lt; Precedente" name="earlier_details_button" tool_tip="Vai ai dettagli precedenti"/>
- <button label="Successivo &gt;" label_selected="Successivo &gt;" name="later_details_button" tool_tip="Vai ai dettagli successivi"/>
+ <button width="90" label="&lt; Precedente" label_selected="&lt; Precedente" name="earlier_details_button" tool_tip="Vai ai dettagli precedenti"/>
+ <button left_delta="260" width="90" label="Successivo &gt;" label_selected="Successivo &gt;" name="later_details_button" tool_tip="Vai ai dettagli successivi"/>
</panel>
<panel label="Vendite" name="group_money_sales_tab">
<text_editor name="group_money_sales_text">
Calcolo...
</text_editor>
- <button label="&lt; Precedente" label_selected="&lt; Precedente" name="earlier_sales_button" tool_tip="Vai ai dettagli precedenti"/>
- <button label="Successivo &gt;" label_selected="Successivo &gt;" name="later_sales_button" tool_tip="Vai ai dettagli successivi"/>
+ <button width="90" label="&lt; Precedente" label_selected="&lt; Precedente" name="earlier_sales_button" tool_tip="Vai ai dettagli precedenti"/>
+ <button left_delta="260" width="90" label="Successivo &gt;" label_selected="Successivo &gt;" name="later_sales_button" tool_tip="Vai ai dettagli successivi"/>
</panel>
</tab_container>
</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_group_notices.xml b/indra/newview/skins/default/xui/it/panel_group_notices.xml
index 7f1f37d67e..c6ef84e220 100644
--- a/indra/newview/skins/default/xui/it/panel_group_notices.xml
+++ b/indra/newview/skins/default/xui/it/panel_group_notices.xml
@@ -1,12 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Notice" name="notices_tab">
<string name="help_text">
- Le notice sono un modo veloce per comunicare in un
-gruppo diffondendo un messaggio e recapitando un
-eventuale oggetto allegato. Le notice arrivano solo ai
-membri del gruppo il cui ruolo è abilitato a riceverli.
-Puoi disattivare la ricezione delle notice
-nella finestra principale.
+ Le notice sono un modo veloce per comunicare in un gruppo diffondendo un messaggio e recapitando un eventuale oggetto allegato. Le notice arrivano solo ai membri del gruppo il cui ruolo è abilitato a riceverli.
+Puoi disattivare la ricezione delle notice nella finestra principale.
</string>
<string name="no_notices_text">
Non ci sono vecchie notice.
@@ -16,9 +12,7 @@ nella finestra principale.
Archivio delle notice del gruppo
</text>
<text name="lbl2">
- Le notice sono conservate per 14 giorni. Clicca la notice qui sotto che desideri leggere.
-Clicca il bottone &apos;Aggiorna&apos; per controllare se sono arrivate nuove notice.
-Il numero delle notice è limitato a 200 notice per gruppo al giorno.
+ Le notice sono conservate per 14 giorni. Il numero delle notice è limitato a 200 notice per gruppo al giorno.
</text>
<scroll_list name="notice_list">
<column label="Oggetto" name="subject"/>
@@ -35,22 +29,22 @@ Il numero delle notice è limitato a 200 notice per gruppo al giorno.
Crea una notice
</text>
<text name="lbl2">
- Devi scrivere l&apos;oggetto della notice per poterla inviare.
-Puoi aggiungere un solo allegato alla notice trascinandolo
-dal tuo inventario in questa finestra. L&apos;allegato deve essere copiabile e cedibile,
-e non puoi allegare una cartella.
+ Puoi aggiungere un solo allegato alla notice trascinandolo dal tuo inventario in questa finestra. L&apos;allegato deve essere copiabile e cedibile, e non puoi allegare una cartella.
</text>
- <text name="lbl3">
+ <text name="lbl3" left="20">
Oggetto:
</text>
- <text name="lbl4">
+ <line_editor name="create_subject" width="251" left_delta="61"/>
+ <text name="lbl4" left="15" width="60">
Messaggio:
</text>
- <text name="lbl5">
+ <text_editor name="create_message" left_delta="66" width="330"/>
+ <text name="lbl5" width="68">
Allega:
</text>
+ <line_editor name="create_inventory_name" width="190" left_delta="74"/>
<button label="Rimuovi allegato" label_selected="Rimuovi allegato" name="remove_attachment"/>
- <button label="Invia la notice" label_selected="Invia la notice" name="send_notice"/>
+ <button label="Invia" label_selected="Invia" name="send_notice"/>
<panel name="drop_target" tool_tip="Trascina un oggetto dall&apos;inventario sulla casella del messaggio per inviarlo con la notice. Devi avere il permesso di copia e trasferimento dell&apos;oggetto per poterlo inviare con la notice."/>
</panel>
<panel label="Vedi le notice precedenti" name="panel_view_past_notice">
@@ -58,7 +52,7 @@ e non puoi allegare una cartella.
Notice archiviate
</text>
<text name="lbl2">
- Per mandare una nuova notice, clicca il bottone &apos;Crea una nuova notice&apos; qui sopra.
+ Per mandare una nuova notice, clicca &apos;Crea una nuova notice&apos; qui sopra.
</text>
<text name="lbl3">
Oggetto:
diff --git a/indra/newview/skins/default/xui/it/panel_group_roles.xml b/indra/newview/skins/default/xui/it/panel_group_roles.xml
index 2629b91db5..8dfdd5a46e 100644
--- a/indra/newview/skins/default/xui/it/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/it/panel_group_roles.xml
@@ -12,8 +12,9 @@
Membri &amp; Ruoli
</text>
<text name="static2">
- I membri del Gruppo hanno ricevuto ruoli con delle abilità. Queste impostazioni possono
-essere facilmente personalizzate, permettendo una maggiore organizzazione e flessibilità.
+ I membri del Gruppo hanno ricevuto ruoli con delle abilità. Queste
+impostazioni possono essere facilmente personalizzate, permettendo
+una maggiore organizzazione e flessibilità.
</text>
</panel>
<panel name="roles_header">
@@ -21,12 +22,14 @@ essere facilmente personalizzate, permettendo una maggiore organizzazione e fles
Ruoli
</text>
<text name="role_properties_modifiable">
- Seleziona un ruolo qui sotto. È possibile modificarne il nome, la descrizione e il titolo.
+ Seleziona un ruolo qui sotto. È possibile modificarne il nome,
+la descrizione e il titolo.
</text>
<text name="role_properties_not_modifiable">
- Seleziona un ruolo qui sotto per vederne le proprietà, i membri e i permessi abilitati.
+ Seleziona un ruolo qui sotto per vederne le proprietà, i membri
+e i permessi abilitati.
</text>
- <text name="role_actions_modifiable">
+ <text bottom_delta="-28" name="role_actions_modifiable">
Puoi anche assegnare abilità al ruolo.
</text>
<text name="role_actions_not_modifiable">
@@ -42,16 +45,17 @@ essere facilmente personalizzate, permettendo una maggiore organizzazione e fles
eseguire tali abilità.
</text>
</panel>
- <tab_container name="roles_tab_container">
- <panel label="Membri" name="members_sub_tab" tool_tip="Membri">
- <button label="Cerca" name="search_button"/>
- <button label="Mostra tutti" name="show_all_button"/>
- <name_list name="member_list">
+ <tab_container height="164" name="roles_tab_container">
+ <panel height="148" label="Membri" name="members_sub_tab" tool_tip="Membri">
+ <line_editor bottom="127" name="search_text"/>
+ <button label="Cerca" name="search_button" width="75"/>
+ <button label="Mostra tutti" name="show_all_button" left_delta="80"/>
+ <name_list name="member_list" bottom_delta="-105" height="104" >
<column label="Nome del membro" name="name"/>
<column label="Contributo donato" name="donated"/>
<column label="Ultimo accesso" name="online"/>
</name_list>
- <button label="Invita un nuovo membro ..." name="member_invite"/>
+ <button label="Invita un nuovo membro..." name="member_invite" width="165"/>
<button label="Espellere dal gruppo" name="member_eject"/>
<string name="help_text">
Puoi aggiungere o rimuovere i ruoli assegnati ai membri.
@@ -59,10 +63,11 @@ Seleziona più membri tenendo premuto il tasto Ctrl e
cliccando sui loro nomi.
</string>
</panel>
- <panel label="Ruoli" name="roles_sub_tab">
- <button label="Cerca" name="search_button"/>
- <button label="Mostra tutti" name="show_all_button"/>
- <scroll_list name="role_list">
+ <panel height="148" label="Ruoli" name="roles_sub_tab">
+ <line_editor bottom="127" name="search_text"/>
+ <button label="Cerca" name="search_button" width="75"/>
+ <button label="Mostra tutti" name="show_all_button" left_delta="80"/>
+ <scroll_list name="role_list" bottom_delta="-104" height="104">
<column label="Nome del ruolo" name="name"/>
<column label="Titolo" name="title"/>
<column label="Membri" name="members"/>
@@ -79,10 +84,11 @@ compresi il ruolo base o &apos;Membro&apos; e il ruolo del Capogruppo.
I ruoli &apos;Membro&apos; e &apos;Capogruppo&apos; sono ruoli speciali e non possono essere eliminati.
</string>
</panel>
- <panel label="Abilità" name="actions_sub_tab">
- <button label="Cerca" name="search_button"/>
- <button label="Visualizza tutto" name="show_all_button"/>
- <scroll_list name="action_list" tool_tip="Seleziona una abilità per vederne maggiori dettagli."/>
+ <panel height="148" label="Abilità" name="actions_sub_tab">
+ <line_editor bottom="127" name="search_text"/>
+ <button label="Cerca" name="search_button" width="75"/>
+ <button label="Visualizza tutto" name="show_all_button" left_delta="80"/>
+ <scroll_list bottom_delta="-120" height="118" name="action_list" tool_tip="Seleziona una abilità per vederne maggiori dettagli."/>
<string name="help_text">
Le abilità permettono ai membri nei ruoli di fare cose specifiche
in questo gruppo. C&apos;è una vasta gamma di abilità.
diff --git a/indra/newview/skins/default/xui/it/panel_groups.xml b/indra/newview/skins/default/xui/it/panel_groups.xml
index 75bccb71a3..43fd36710e 100644
--- a/indra/newview/skins/default/xui/it/panel_groups.xml
+++ b/indra/newview/skins/default/xui/it/panel_groups.xml
@@ -1,10 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="groups">
- <text name="groupdesc">
- Il tuo gruppo attualmente attivo è visualizzato in grassetto.
+ <scroll_list bottom="50" name="group list"/>
+ <text bottom="16" height="32" name="groupdesc" width="268">
+ Il tuo gruppo attualmente attivo è visualizzato
+in grassetto.
</text>
- <text name="groupcount">
- Appartieni a [COUNT] gruppi (su un massimo di [MAX]).
+ <text bottom="3" name="groupcount" width="268">
+ Appartieni a [COUNT] gruppo/i (su un massimo di [MAX]).
</text>
<button label="IM/Chiama" name="IM" tool_tip="Apri una sessione di IM/Instant Messages"/>
<button label="Informazioni" name="Info"/>
diff --git a/indra/newview/skins/default/xui/it/panel_login.xml b/indra/newview/skins/default/xui/it/panel_login.xml
index acd047d75d..e3cb7473fc 100644
--- a/indra/newview/skins/default/xui/it/panel_login.xml
+++ b/indra/newview/skins/default/xui/it/panel_login.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="panel_login">
- <string name="real_url">
- http://secondlife.com/app/login/
- </string>
- <string name="forgot_password_url">
- http://secondlife.com/account/request.php
- </string>
+ <panel.string name="create_account_url">
+ http://join.secondlife.com/index.php?lang=it-IT
+ </panel.string>
+ <panel.string name="forgot_password_url">
+ http://secondlife.com/account/request.php?lang=it
+ </panel.string>
+<panel name="login_widgets">
<text name="first_name_text" left="20">
Nome:
</text>
@@ -21,15 +22,9 @@
Punto di partenza:
</text>
<combo_box name="start_location_combo" left_delta="105" width="160">
- <combo_item name="MyHome">
- Casa Mia
- </combo_item>
- <combo_item name="MyLastLocation">
- Ultimo luogo visitato
- </combo_item>
- <combo_item name="Typeregionname">
- &lt;Scrivi la regione&gt;
- </combo_item>
+ <combo_box.item name="MyHome" label="Casa Mia" />
+ <combo_box.item name="MyLastLocation" label="Ultimo luogo visitato" />
+ <combo_box.item name="Typeregionname" label="&lt;Scrivi la regione&gt;" />
</combo_box>
<check_box label="Ricorda password" name="remember_check" left_delta="168"/>
<button label="Log In" label_selected="Log In" name="connect_btn"/>
@@ -43,3 +38,4 @@
[VERSION]
</text>
</panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/it/panel_preferences_advanced.xml
new file mode 100644
index 0000000000..2355dc7f0a
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_preferences_advanced.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<panel name="advanced">
+ <text name="AspectRatioLabel1" tool_tip="larghezza/altezza">
+ Rapporto di visualizzazione:
+ </text>
+ <combo_box name="aspect_ratio" tool_tip="larghezza/altezza">
+ <combo_box.item label="4:3 (Monitor Standard)" name="item1"/>
+ <combo_box.item label="5:4 (1280x1024 LCD)" name="item2"/>
+ <combo_box.item label="8:5 (Widescreen)" name="item3"/>
+ <combo_box.item label="16:9 (Widescreen)" name="item4"/>
+ </combo_box>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_preferences_alerts.xml b/indra/newview/skins/default/xui/it/panel_preferences_alerts.xml
new file mode 100644
index 0000000000..54517635fd
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_preferences_alerts.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Pop-up" name="popups" title="Pop-up">
+ <text name="dont_show_label">
+ Non mostrare questi pop-up:
+ </text>
+ <button label="Abilita questo pop-up" name="enable_popup"/>
+ <button width="200" label="Abilita tutti i pop-up..." name="reset_dialogs_btn" tool_tip="Abilita tutti i pop-up opzionali e le notifiche da &apos;utilizzo per la prima volta&apos;."/>
+ <text name="show_label">
+ Mostra questi pop-up:
+ </text>
+ <button width="200" label="Disabilita tutti questi pop-up..." name="skip_dialogs_btn" tool_tip="Disabilita tutti i pop-up opzionali e le notifiche da &apos;utilizzo per la prima volta&apos;."/>
+ <text name="text_box2">
+ Offerte di notecard, texture e landmark:
+ </text>
+ <check_box label="Accetta automaticamente" name="accept_new_inventory"/>
+ <check_box label="Apri automaticamente dopo aver accettato" name="show_new_inventory"/>
+ <check_box label="Mostra automaticamente nell&apos;inventario, gli oggetti appena accettati" name="show_in_inventory"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_preferences_chat.xml b/indra/newview/skins/default/xui/it/panel_preferences_chat.xml
index fd20b11c02..7125832c7b 100644
--- a/indra/newview/skins/default/xui/it/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/it/panel_preferences_chat.xml
@@ -5,54 +5,54 @@
chat:
</text>
<radio_group name="chat_font_size">
- <radio_item name="radio">
- Piccolo
- </radio_item>
- <radio_item name="radio2">
- Medio
- </radio_item>
- <radio_item name="radio3">
- Grande
- </radio_item>
+ <radio_item name="radio" label="Piccolo" />
+ <radio_item name="radio2" label="Medio" />
+ <radio_item name="radio3" label="Grande" />
</radio_group>
+ <color_swatch label="Tuo" name="user"/>
+ <text name="text_box1">
+ Tuo
+ </text>
+ <color_swatch label="Altri" name="agent"/>
<text name="text_box2">
- Colore carattere chat:
+ Altri
+ </text>
+ <color_swatch label="IM" name="im"/>
+ <text name="text_box3">
+ IM
</text>
- <color_swatch label="Tuo" name="user"/>
- <color_swatch label="Altri" name="agent" width="60" left_delta="48"/>
- <color_swatch label="IM" name="im" left_delta="64" />
<color_swatch label="Sistema" name="system"/>
- <color_swatch label="Errori" name="script_error"/>
+ <text name="text_box4">
+ Sistema
+ </text>
+ <color_swatch label="Errori script" name="script_error"/>
+ <text name="text_box5">
+ Errori script
+ </text>
<color_swatch label="Oggetti" name="objects"/>
- <color_swatch label="Proprietario" name="owner" width="60" left_delta="48"/>
- <color_swatch label="Vignetta" name="background" left_delta="64" />
- <color_swatch label="URLs" name="links"/>
- <text name="text_box8">
- Errori script:
+ <text name="text_box6">
+ Oggetti
</text>
- <check_box label="Mostra errori script ed avvertimenti nella chat principale" name="script_errors_as_chat"/>
- <text name="text_box3">
- Console della chat:
+ <color_swatch label="Proprietario" name="owner"/>
+ <text name="text_box7">
+ Proprietario
</text>
- <spinner label="Dissolvi la chat dopo" name="fade_chat_time" label_width="112" width="162"/>
- <text name="text_box4" left="313" >
- (s)
+ <color_swatch label="Vignetta" name="background"/>
+ <text name="text_box8">
+ Vignetta
</text>
- <text name="text_box5">
- (# linee)
+ <color_swatch label="URLs" name="links"/>
+ <text name="text_box9">
+ URLs
</text>
+ <check_box label="Mostra errori script ed avvertimenti nella chat principale" name="script_errors_as_chat"/>
+ <spinner label="Dissolvi la chat dopo" name="fade_chat_time" label_width="112" width="162"/>
<slider label="Opacità" name="console_opacity"/>
<check_box label="Utilzza la larghezza intera dello schermo (Richiede riavvio)" name="chat_full_width_check"/>
- <text name="text_box6">
- Opzioni chat:
- </text>
<check_box label="Chiudi la barra chat dopo aver premuto invio" name="close_chat_on_return_check"/>
<check_box label="Le frecce muovono comunque l&apos;avatar quando si sta scrivendo" name="arrow_keys_move_avatar_check"/>
<check_box label="Mostra orario nella chat principale" name="show_timestamps_check"/>
- <check_box label="Simula la battitura tasti quando chatti" name="play_typing_animation"/>
- <text name="text_box7">
- Chat con vignette:
- </text>
+ <check_box label="Simula la battitura tasti quando scrivi" name="play_typing_animation"/>
<check_box label="Mostra vignette chat" name="bubble_text_chat"/>
<slider label="Opacità" name="bubble_chat_opacity"/>
</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_preferences_general.xml b/indra/newview/skins/default/xui/it/panel_preferences_general.xml
index aadd86d055..e6cd6e67b2 100644
--- a/indra/newview/skins/default/xui/it/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/it/panel_preferences_general.xml
@@ -1,24 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Generale" name="general_panel">
- <radio_group name="default_start_location">
- <radio_item name="MyHome" tool_tip="Vai a casa di default quando fai login">
- Casa mia
- </radio_item>
- <radio_item name="MyLastLocation" tool_tip="Vai nell&apos;ultimo posto visitato di default quando fai login.">
- Ultimo posto visitato
- </radio_item>
- </radio_group>
+ <combo_box name="start_location_combo">
+ <combo_box.item name="MyHome" tool_tip="Vai a casa di default quando fai login" label="Casa mia"/>
+ <combo_box.item name="MyLastLocation" tool_tip="Vai nell&apos;ultimo posto visitato di default quando fai login." label="Ultimo posto visitato"/>
+ </combo_box>
<check_box label="Mostra il punto di partenza nella schermata d&apos;inizio" name="show_location_checkbox"/>
- <combo_box name="fade_out_combobox" width="166">
- <combo_item name="Never">
- Mai
- </combo_item>
- <combo_item name="Show Temporarily">
- Mostra temporanemente
- </combo_item>
- <combo_item name="Always">
- Sempre
- </combo_item>
+ <combo_box name="fade_out_combobox">
+ <combo_box.item name="Never" label="Mai"/>
+ <combo_box.item name="Show Temporarily" label="Mostra temporanemente"/>
+ <combo_box.item name="Always" label="Sempre"/>
</combo_box>
<check_box label="Nomi avatar in piccolo" name="small_avatar_names_checkbox"/>
<check_box label="Nascondi il mio nome sul mio schermo" name="show_my_name_checkbox"/>
@@ -34,26 +24,19 @@
<check_box label="Usa ridimensionamento indipendente dalla risoluzione" name="ui_auto_scale"/>
<spinner label="Assente dopo:" name="afk_timeout_spinner"/>
<check_box label="Avvisami quando spendo o ricevo Linden Dollars (L$)" name="notify_money_change_checkbox"/>
- <text name="maturity_desired_label" bottom="-312">
+ <text name="maturity_desired_label">
Categoria di accesso:
</text>
- <text name="maturity_desired_prompt" bottom="-312">
- Voglio accedere al
-contenuto di tipo:
+ <text name="maturity_desired_prompt">
+ Voglio accedere al contenuto di tipo:
</text>
- <combo_box name="maturity_desired_combobox" bottom="-330" left="274">
- <combo_item name="Desired_Adult">
- PG, Mature e Adult
- </combo_item>
- <combo_item name="Desired_Mature">
- PG e Mature
- </combo_item>
- <combo_item name="Desired_PG">
- solo PG
- </combo_item>
+ <combo_box name="maturity_desired_combobox">
+ <combo_box.item name="Desired_Adult" label="PG, Mature e Adult"/>
+ <combo_box.item name="Desired_Mature" label="PG e Mature"/>
+ <combo_box.item name="Desired_PG" label="PG"/>
</combo_box>
- <text name="maturity_desired_textbox" bottom="-324" left="274">
- solo PG
+ <text name="maturity_desired_textbox">
+ PG
</text>
<text name="start_location_textbox">
Punto di partenza:
@@ -73,75 +56,35 @@ contenuto di tipo:
<text name="language_textbox">
Lingua:
</text>
- <text left_delta="313" name="language_textbox2">
+ <text name="language_textbox2">
(Richiede il riavvio)
</text>
<string name="region_name_prompt">
&lt;Scrivi il nome della regione&gt;
</string>
- <combo_box name="crash_behavior_combobox" width="166">
- <combo_item name="Askbeforesending">
- Chiedi prima di inviare
- </combo_item>
- <combo_item name="Alwayssend">
- Invia sempre
- </combo_item>
- <combo_item name="Neversend">
- Non inviare mai
- </combo_item>
+ <combo_box name="crash_behavior_combobox">
+ <combo_box.item name="Askbeforesending" label="Chiedi prima di inviare"/>
+ <combo_box.item name="Alwayssend" label="Invia sempre"/>
+ <combo_box.item name="Neversend" label="Non inviare mai"/>
</combo_box>
- <combo_box name="language_combobox" width="166">
- <combo_item name="System Default Language">
- Default di sistema
- </combo_item>
- <combo_item name="English">
- English
- </combo_item>
- <combo_item name="Danish">
- Dansk (Danese) - Beta
- </combo_item>
- <combo_item name="Deutsch(German)">
- Deutsch (Tedesco) - Beta
- </combo_item>
- <combo_item name="Spanish">
- Español (Spagnolo) - Beta
- </combo_item>
- <combo_item name="French">
- Français (Francese) - Beta
- </combo_item>
- <combo_item name="Italian">
- Italiano - Beta
- </combo_item>
- <combo_item name="Hungarian">
- Magyar (Ungherese) - Beta
- </combo_item>
- <combo_item name="Dutch">
- Nederlands (Olandese) - Beta
- </combo_item>
- <combo_item name="Polish">
- Polski (Polacco) - Beta
- </combo_item>
- <combo_item name="Portugese">
- Portugués (Portoghese) - Beta
- </combo_item>
- <combo_item name="Russian">
- РуÑÑкий (Russo) - Beta
- </combo_item>
- <combo_item name="Turkish">
- Türkçe (Turco) - Beta
- </combo_item>
- <combo_item name="Ukrainian">
- УкраїнÑька (Ukraino) - Beta
- </combo_item>
- <combo_item name="Chinese">
- 中文 (简体) (Cinese) - Beta
- </combo_item>
- <combo_item name="(Japanese)">
- 日本語 (Giapponese) - Beta
- </combo_item>
- <combo_item name="(Korean)">
- 한국어 (Coreano) - Beta
- </combo_item>
+ <combo_box name="language_combobox">
+ <combo_box.item name="System Default Language" label="Default di sistema"/>
+ <combo_box.item name="English" label="English"/>
+ <combo_box.item name="Danish" label="Dansk (Danese) - Beta"/>
+ <combo_box.item name="Deutsch(German)" label="Deutsch (Tedesco) - Beta"/>
+ <combo_box.item name="Spanish" label="Español (Spagnolo) - Beta"/>
+ <combo_box.item name="French" label="Français (Francese) - Beta"/>
+ <combo_box.item name="Italian" label="Italiano - Beta"/>
+ <combo_box.item name="Hungarian" label="Magyar (Ungherese) - Beta"/>
+ <combo_box.item name="Dutch" label="Nederlands (Olandese) - Beta"/>
+ <combo_box.item name="Polish" label="Polski (Polacco) - Beta"/>
+ <combo_box.item name="Portugese" label="Portugués (Portoghese) - Beta"/>
+ <combo_box.item name="Russian" label="РуÑÑкий (Russo) - Beta"/>
+ <combo_box.item name="Turkish" label="Türkçe (Turco) - Beta"/>
+ <combo_box.item name="Ukrainian" label="УкраїнÑька (Ukraino) - Beta"/>
+ <combo_box.item name="Chinese" label="中文 (简体) (Cinese) - Beta"/>
+ <combo_box.item name="(Japanese)" label="日本語 (Giapponese) - Beta"/>
+ <combo_box.item name="(Korean)" label="한국어 (Coreano) - Beta"/>
</combo_box>
<check_box label="Condividi la tua lingua con gli oggetti" name="language_is_public" tool_tip="Questo fa in modo che gli oggetti inworld riconoscano la tua lingua."/>
</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml
index 6ae5b6bb2f..6e1640334f 100644
--- a/indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml
@@ -2,28 +2,18 @@
<panel label="Grafica" name="Display panel">
<button label="?" name="GraphicsPreferencesHelpButton"/>
<check_box label="Esegui Second Life in una finestra" name="windowed mode"/>
- <text_editor name="FullScreenInfo">
- Se deselezionato, il viewer partirà a schermo intero all&apos;avvio.
+ <text_editor name="FullScreenInfo" width="480">
+ Se deselezionato, all&apos;avvio il programma partirà a schermo intero.
</text_editor>
<text name="WindowSizeLabel">
Dimensione della finestra:
</text>
<combo_box name="windowsize combo">
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="720x480">
- 720x480 (NTSC)
- </combo_item>
- <combo_item name="768x576">
- 768x576 (PAL)
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
+ <combo_box.item name="640x480" label="640x480"/>
+ <combo_box.item name="800x600" label="800x600"/>
+ <combo_box.item name="720x480" label="720x480 (NTSC)"/>
+ <combo_box.item name="768x576" label="768x576 (PAL)"/>
+ <combo_box.item name="1024x768" label="1024x768"/>
</combo_box>
<text name="DisplayResLabel">
Risoluzione del monitor:
@@ -32,18 +22,10 @@
Rapporto di visualizzazione:
</text>
<combo_box name="aspect_ratio" tool_tip="larghezza/altezza">
- <combo_item name="4:3(StandardCRT)">
- 4:3 (Monitor Standard)
- </combo_item>
- <combo_item name="5:4(1280x1024LCD)">
- 5:4 (1280x1024 LCD)
- </combo_item>
- <combo_item name="8:5(Widescreen)">
- 8:5 (Widescreen)
- </combo_item>
- <combo_item name="16:9(Widescreen)">
- 16:9 (Widescreen)
- </combo_item>
+ <combo_box.item name="4:3(StandardCRT)" label="4:3 (Monitor Standard)"/>
+ <combo_box.item name="5:4(1280x1024LCD)" label="5:4 (1280x1024 LCD)"/>
+ <combo_box.item name="8:5(Widescreen)" label="8:5 (Widescreen)"/>
+ <combo_box.item name="16:9(Widescreen)" label="16:9 (Widescreen)"/>
</combo_box>
<check_box label="Autoconfigurazione" name="aspect_auto_detect"/>
<text name="HigherText">
@@ -68,35 +50,28 @@
Ultra
</text>
<text name="HigherText2">
- più alto
+ Più alto
</text>
<text name="QualityText2">
Qualità
</text>
<check_box label="Personalizzate" name="CustomSettings"/>
+ <panel name="CustomGraphics Panel">
<text name="ShadersText">
Effetti grafici:
</text>
- <check_box label="Bump Mapping (piccoli rilievi) e scintillii" name="BumpShiny"/>
- <check_box label="Effetti grafici base" name="BasicShaders" tool_tip="Disabilite questa opzione può evitare che qualche scheda grafica vada in crash."/>
+ <check_box label="Piccoli rilievi e scintillii" name="BumpShiny"/>
+ <check_box label="Effetti grafici base" name="BasicShaders" tool_tip="Disabilitare questa opzione può evitare che qualche scheda grafica vada in crash."/>
<check_box label="Effetti grafici atmosferici" name="WindLightUseAtmosShaders"/>
<check_box label="Riflessi dell&apos;acqua" name="Reflections"/>
<text name="ReflectionDetailText">
Dettaglio dei riflessi
</text>
<radio_group name="ReflectionDetailRadio">
- <radio_item name="0">
- Terreno ed alberi
- </radio_item>
- <radio_item name="1">
- Tutti gli aggetti statici
- </radio_item>
- <radio_item name="2">
- Tutti gli avatar e gli oggetti
- </radio_item>
- <radio_item name="3">
- Tutto
- </radio_item>
+ <radio_item name="0" label="Terreno ed alberi" />
+ <radio_item name="1" label="Tutti gli aggetti statici" />
+ <radio_item name="2" label="Tutti gli avatar e gli oggetti" />
+ <radio_item name="3" label="Tutto" />
</radio_group>
<text name="AvatarRenderingText">
Rendering dell&apos;avatar:
@@ -110,18 +85,18 @@
<text name="DrawDistanceMeterText2">
m
</text>
- <slider label="Distanza di disegno:" name="DrawDistance"/>
- <slider label="Conteggio massimo particelle:" name="MaxParticleCount"/>
- <slider label="Qualità in post-produzione:" name="RenderPostProcess"/>
+ <slider label="Distanza di disegno:" name="DrawDistance" label_width="158" width="255"/>
+ <slider label="Conteggio massimo particelle:" name="MaxParticleCount" label_width="158" width="262" />
+ <slider label="Qualità in post-produzione:" name="RenderPostProcess" label_width="158" width="223"/>
<text name="MeshDetailText">
Dettagli reticolo:
</text>
- <slider label="Oggetti:" name="ObjectMeshDetail"/>
- <slider label="Prims flessibili:" name="FlexibleMeshDetail"/>
- <slider label="Alberi:" name="TreeMeshDetail"/>
- <slider label="Avatar:" name="AvatarMeshDetail"/>
- <slider label="Terreno:" name="TerrainMeshDetail"/>
- <slider label="Cielo:" name="SkyMeshDetail"/>
+ <slider label=" Oggetti:" name="ObjectMeshDetail"/>
+ <slider label=" Prims flessibili:" name="FlexibleMeshDetail"/>
+ <slider label=" Alberi:" name="TreeMeshDetail"/>
+ <slider label=" Avatar:" name="AvatarMeshDetail"/>
+ <slider label=" Terreno:" name="TerrainMeshDetail"/>
+ <slider label=" Cielo:" name="SkyMeshDetail"/>
<text name="PostProcessText">
Basso
</text>
@@ -147,30 +122,23 @@
Dettagli illuminazione:
</text>
<radio_group name="LightingDetailRadio">
- <radio_item name="SunMoon">
- Sole e luna solamente
- </radio_item>
- <radio_item name="LocalLights">
- Luci locali
- </radio_item>
+ <radio_item name="SunMoon" label="Solo il sole e la luna" />
+ <radio_item name="LocalLights" label="Luci locali" />
</radio_group>
<text name="TerrainDetailText">
Dettagli terreno:
</text>
<radio_group name="TerrainDetailRadio">
- <radio_item name="0">
- Bassi
- </radio_item>
- <radio_item name="2">
- Alti
- </radio_item>
+ <radio_item name="0" label="Bassi" />
+ <radio_item name="2" label="Alti" />
</radio_group>
+ </panel>
<button label="Configurazione raccomandata" name="Defaults" left="110" width="190" />
<button label="Opzioni hardware" label_selected="Opzioni hardware" name="GraphicsHardwareButton"/>
- <string name="resolution_format">
+ <panel.string name="resolution_format">
[RES_X] x [RES_Y]
- </string>
- <string name="aspect_ratio_text">
+ </panel.string>
+ <panel.string name="aspect_ratio_text">
[NUM]:[DEN]
- </string>
+ </panel.string>
</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/it/panel_preferences_privacy.xml
new file mode 100644
index 0000000000..2249d94688
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_preferences_privacy.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Comunicazioni" name="im">
+ <text name="text_box">
+ Il mio stato online:
+ </text>
+ <check_box label="Solo i miei amici e i miei gruppi possono vedermi online" name="online_visibility"/>
+ <text name="text_box2">
+ Opzioni IM:
+ </text>
+ <string name="log_in_to_change">
+ Effettua login per cambiare
+ </string>
+ <check_box label="Invia gli IM alla mia email ([EMAIL])" name="send_im_to_email"/>
+ <check_box label="Inserisci gli IM nella console della chat" name="include_im_in_chat_console"/>
+ <check_box label="Mostra l&apos;orario negli IM" name="show_timestamps_check"/>
+ <check_box label="Mostrami le notifiche degli amici online" name="friends_online_notify_checkbox"/>
+ <text name="text_box3">
+ Risposta agli IM quando
+sono in &apos;Occupato&apos;:
+ </text>
+ <text name="text_box4" width="136">
+ Opzioni salvataggio chat:
+ </text>
+ <check_box label="Salva una copia degli IM sul mio computer" name="log_instant_messages"/>
+ <check_box label="Mostra l&apos;orario nei registri IM" name="log_instant_messages_timestamp"/>
+ <check_box label="Mostra la parte finale della precedente conversazione IM" name="log_show_history"/>
+ <check_box label="Salva un registro della chat locale sul mio computer" name="log_chat"/>
+ <check_box label="Mostra l&apos;orario nei registri della chat locale" name="log_chat_timestamp"/>
+ <check_box label="Mostra gli IM entranti nel registro della chat locale" name="log_chat_IM"/>
+ <check_box label="Includi la data nell&apos;orario" name="log_date_timestamp"/>
+ <button label="Cambia percorso" label_selected="Cambia percorso" name="log_path_button" width="130"/>
+ <line_editor left="288" name="log_path_string" right="-20"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_preferences_setup.xml b/indra/newview/skins/default/xui/it/panel_preferences_setup.xml
new file mode 100644
index 0000000000..e1239d5820
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_preferences_setup.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Controlli &amp; Telecamera" name="Input panel">
+ <text name=" Mouselook Options:">
+ Opzioni visualizzazione
+in soggettiva:
+ </text>
+ <text name=" Mouse Sensitivity:">
+ Sensibilità del mouse:
+ </text>
+ <check_box label="Inverti i controlli del mouse" name="invert_mouse"/>
+ <text name=" Auto Fly Options:">
+ Opzioni di volo
+automatico:
+ </text>
+ <check_box label="Vola/atterra premendo su/giù" name="automatic_fly"/>
+ <text name=" Camera Options:">
+ Opzioni della
+telecamera:
+ </text>
+ <text name="camera_fov_label" width="218">
+ Angolo di visualizzazione della telecamera:
+ </text>
+ <slider bottom_delta="-6" width="128" left="366" name="camera_fov" />
+ <text name="Camera Follow Distance:" width="218">
+ Distanza della telecamera dall&apos;avatar:
+ </text>
+ <slider bottom_delta="-6" width="128" left="366" name="camera_offset_scale" />
+ <check_box label="Movimenti automatici della telecamera in &#10;modalità modifica oggetti" name="edit_camera_movement" tool_tip="Usa il posizionamento automatico della telecamera entrando e uscendo dalla modalità modifica oggetti"/>
+ <check_box bottom_delta="-34" label="Movimenti automatici della telecamera in &#10;modalità aspetto fisico" name="appearance_camera_movement" tool_tip="Usa il posizionamento automatico della telecamera durante la modalità modifica oggetti"/>
+ <text name="text2" bottom_delta="-42">
+ Opzione di visualizzazione
+dell&apos;avatar:
+ </text>
+ <check_box label="Mostra l&apos;avatar in prima persona" name="first_person_avatar_visible"/>
+ <button bottom_delta="-40" label="Installazione del joystick" name="joystick_setup_button" width="165"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_preferences_sound.xml b/indra/newview/skins/default/xui/it/panel_preferences_sound.xml
new file mode 100644
index 0000000000..41f67951c2
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_preferences_sound.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Audio &amp; Video" name="Preference Media panel">
+ <slider label="Master" name="System Volume"/>
+ <slider label="Ambiente" name="Wind Volume"/>
+ <slider label="Suoni" name="SFX Volume"/>
+ <slider label="Media" name="Media Volume"/>
+ <slider label="Interfaccia utente" name="UI Volume"/>
+ <slider label="Musica" name="Music Volume"/>
+ <slider label="Voice" name="Voice Volume"/>
+ <text_editor name="voice_unavailable">
+ Voice chat non disponibile
+ </text_editor>
+ <check_box label="Abilita voice chat" name="enable_voice_check"/>
+ <radio_group name="ear_location">
+ <radio_item name="0" label="Ascolta voice chat dalla posizione della telecamera" />
+ <radio_item name="1" label="Ascolta voice chat dalla posizione dell&apos;avatar" />
+ </radio_group>
+ <button label="Configurazione periferica" name="device_settings_btn" width="165"/>
+ <text name="muting_text">
+ Volume:
+ </text>
+ <text name="streaming_prefs_text" bottom="-195" >
+ Preferenze Streaming:
+ </text>
+ <text name="audio_prefs_text">
+ Preferenze Audio:
+ </text>
+ <panel label="Volume" name="Volume Panel"/>
+ <check_box label="Ascolta il canale della musica" name="streaming_music"/>
+ <check_box height="32" label="Guarda i video" name="streaming_video"/>
+ <check_box label="Attiva automaticamente i video" name="auto_streaming_video"/>
+ <check_box label="Muta l&apos;audio quando minimizzi la finestra" name="mute_when_minimized"/>
+ <slider label="Effetto Doppler" name="Doppler Effect" label_width="140" width="270" />
+ <slider label="Fattore di Distanza" name="Distance Factor" label_width="140" width="270"/>
+ <slider label="Fattore di Allontanamento" name="Rolloff Factor" label_width="140" width="270"/>
+ <spinner label="Suono di Avviso Transazioni &#8805; a L$" name="L$ Change Threshold" label_width="195" width="259"/>
+ <spinner label="Livello vitale dell&apos;avatar" name="Health Change Threshold" label_width="195" width="259"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_profile.xml b/indra/newview/skins/default/xui/it/panel_profile.xml
new file mode 100644
index 0000000000..2aa8b7d0e4
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_profile.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_profile">
+ <string name="CaptionTextAcctInfo">
+ [ACCTTYPE]
+[PAYMENTINFO] [AGEVERIFICATION]
+ </string>
+ <string name="payment_update_link_url">
+ http://www.secondlife.com/account/billing.php?lang=it-IT
+ </string>
+ <string name="partner_edit_link_url">
+ http://www.secondlife.com/account/partners.php?lang=it
+ </string>
+ <string name="my_account_link_url" value="http://secondlife.com/my/account/index.php?lang=it-IT"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_region_covenant.xml b/indra/newview/skins/default/xui/it/panel_region_covenant.xml
index 802156ea0b..9dfecde317 100644
--- a/indra/newview/skins/default/xui/it/panel_region_covenant.xml
+++ b/indra/newview/skins/default/xui/it/panel_region_covenant.xml
@@ -22,15 +22,17 @@
Ultima modifica Merc 31 Dic 1969 16:00:00
</text>
<button label="?" name="covenant_help"/>
- <text_editor name="covenant_editor">
+ <text_editor name="covenant_editor" bottom="-247" height="162" >
Per questa proprietà non è stato emesso alcun regolamento.
</text_editor>
<button label="Ripristina" name="reset_covenant"/>
- <text name="covenant_help_text">
- Le modifiche nel regolamento saranno visibili su tutti i terreni della proprietà.
+ <text bottom="-25" name="covenant_help_text">
+ Le modifiche nel regolamento saranno visibili su tutti i terreni
+ della proprietà.
</text>
- <text name="covenant_instructions">
- Trascina e rilascia una notecard per cambiare il regolamento di questa proprietà.
+ <text bottom_delta="-36" name="covenant_instructions">
+ Trascina e rilascia una notecard per cambiare il regolamento di
+ questa proprietà.
</text>
<text name="region_section_lbl">
Regione:
@@ -38,31 +40,31 @@
<text name="region_name_lbl">
Nome:
</text>
- <text name="region_name_text">
+ <text name="region_name_text" left="126">
leyla
</text>
<text name="region_landtype_lbl">
Tipo:
</text>
- <text name="region_landtype_text">
+ <text name="region_landtype_text" left="126">
Mainland / Homestead
</text>
- <text name="region_maturity_lbl">
+ <text name="region_maturity_lbl" width="115">
Categoria di accesso:
</text>
- <text name="region_maturity_text">
+ <text name="region_maturity_text" left="126">
Adult
</text>
<text name="resellable_lbl">
Rivendita:
</text>
- <text name="resellable_clause">
+ <text name="resellable_clause" left="126">
La terra in questa regione non può essere rivenduta.
</text>
<text name="changeable_lbl">
Suddividi:
</text>
- <text name="changeable_clause">
+ <text name="changeable_clause" left="126">
La terra in questa regione non può essere unita/suddivisa.
</text>
<string name="can_resell">
@@ -72,9 +74,11 @@
Un terreno acquistato in questa regione non può essere rivenduto.
</string>
<string name="can_change">
- Un terreno acquistato in questa regione può essere unito o suddiviso.
+ Un terreno acquistato in questa regione può essere unito o
+suddiviso.
</string>
<string name="can_not_change">
- Un terreno acquistato in questa regione non può essere unito o suddiviso.
+ Un terreno acquistato in questa regione non può essere unito o
+suddiviso.
</string>
</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_region_debug.xml b/indra/newview/skins/default/xui/it/panel_region_debug.xml
index fddc14e85c..85fb968ab4 100644
--- a/indra/newview/skins/default/xui/it/panel_region_debug.xml
+++ b/indra/newview/skins/default/xui/it/panel_region_debug.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<panel label="Debug - individuazione errori" name="Debug">
+<panel label="Debug" name="Debug">
<text name="region_text_lbl">
Regione:
</text>
@@ -13,7 +13,7 @@
<check_box label="Disabilita la fisica" name="disable_physics_check" tool_tip="Disabilita tutta la fisica dei corpi in questa regione"/>
<button label="?" name="disable_physics_help"/>
<button label="Applica" name="apply_btn"/>
- <text name="objret_text_lbl">
+ <text name="objret_text_lbl" width="130">
Restituisci oggetti
</text>
<text name="resident_text_lbl">
@@ -30,10 +30,10 @@
<check_box label="Restituisci solo gli oggetti che sono sulle terre altrui" name="return_other_land" tool_tip="Restituisci solo gli oggetti che sono in terreni appartenenti a qualcun altro"/>
<check_box label="Restituisci gli oggetti in ogni regione di questi possedimenti" name="return_estate_wide" tool_tip="Restituisci tutti gli oggetti nelle varie regioni che costituiscono l&apos;insieme dei possedimenti terrieri"/>
<button label="Restituisci" name="return_btn"/>
- <button label="Visualizza l&apos;elenco dei maggiori collidenti..." name="top_colliders_btn" tool_tip="Elenco degli oggetti che stanno potenzialmente subendo le maggiori collisioni"/>
- <button label="?" name="top_colliders_help"/>
- <button label="Visualizza l&apos;elenco degli script più pesanti..." name="top_scripts_btn" tool_tip="Elenco degli oggetti che impiegano più tempo a far girare gli script"/>
- <button label="?" name="top_scripts_help"/>
+ <button width="280" label="Visualizza l&apos;elenco dei maggiori collidenti..." name="top_colliders_btn" tool_tip="Elenco degli oggetti che stanno potenzialmente subendo le maggiori collisioni"/>
+ <button label="?" name="top_colliders_help" left="297"/>
+ <button width="280" label="Visualizza l&apos;elenco degli script più pesanti..." name="top_scripts_btn" tool_tip="Elenco degli oggetti che impiegano più tempo a far girare gli script"/>
+ <button label="?" name="top_scripts_help" left="297"/>
<button label="Riavvia la regione" name="restart_btn" tool_tip="Dai 2 minuti di tempo massimo e fai riavviare la regione"/>
<button label="?" name="restart_help"/>
<button label="Ritarda il riavvio" name="cancel_restart_btn" tool_tip="Ritarda il riavvio della regione di un&apos;ora"/>
diff --git a/indra/newview/skins/default/xui/it/panel_region_estate.xml b/indra/newview/skins/default/xui/it/panel_region_estate.xml
index a27e3a716c..5b95b7378b 100644
--- a/indra/newview/skins/default/xui/it/panel_region_estate.xml
+++ b/indra/newview/skins/default/xui/it/panel_region_estate.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Proprietà immobiliari" name="Estate">
<text name="estate_help_text">
- I cambiamenti alle impostazioni in questa finestra avranno effetto su tutte
-le regioni della proprietà.
+ I cambiamenti alle impostazioni in questa finestra
+avranno effetto su tutte le regioni della proprietà.
</text>
- <text name="estate_text">
+ <text name="estate_text" width="140">
Proprietà immobiliari:
</text>
<text name="estate_name">
@@ -24,15 +24,15 @@ le regioni della proprietà.
<check_box label="Permetti accesso pubblico" name="externally_visible_check"/>
<button label="?" name="externally_visible_help"/>
<text name="Only Allow">
- Limita l&apos;accesso a:
+ Limita l&apos;accesso a residenti...
</text>
- <check_box label="residenti che hanno dato informazioni di pagamento" name="limit_payment" tool_tip="Blocca residenti non identificati."/>
+ <check_box label="che hanno dato info. di pagamento" name="limit_payment" tool_tip="Blocca residenti non identificati."/>
<check_box label="Adulti con età verificata" name="limit_age_verified" tool_tip="Blocca residenti che non hanno verificato la loro età. Per maggiori informazioni vai a support.secondlife.com."/>
<check_box label="Permetti la chat voice" name="voice_chat_check"/>
<button label="?" name="voice_chat_help"/>
<check_box label="Permetti teleport diretto" name="allow_direct_teleport"/>
<button label="?" name="allow_direct_teleport_help"/>
- <text name="abuse_email_text">
+ <text name="abuse_email_text" width="230">
Indirizzo email per la denuncia di abuso:
</text>
<string name="email_unsupported">
@@ -40,8 +40,8 @@ le regioni della proprietà.
</string>
<button label="?" name="abuse_email_address_help"/>
<button label="Applica" name="apply_btn"/>
- <button label="Espelli persona dalle proprietà..." name="kick_user_from_estate_btn"/>
- <button label="Manda un messaggio ai residenti di tutte le tue proprietà..." name="message_estate_btn"/>
+ <button font="SansSerifSmall" label="Espelli persona dalle proprietà..." name="kick_user_from_estate_btn"/>
+ <button font="SansSerifSmall" label="Manda un messaggio di le proprietà..." name="message_estate_btn"/>
<text name="estate_manager_label">
Manager delle proprietà:
</text>
diff --git a/indra/newview/skins/default/xui/it/panel_region_general.xml b/indra/newview/skins/default/xui/it/panel_region_general.xml
index fffe51770e..8c31172ab5 100644
--- a/indra/newview/skins/default/xui/it/panel_region_general.xml
+++ b/indra/newview/skins/default/xui/it/panel_region_general.xml
@@ -3,19 +3,19 @@
<text name="region_text_lbl">
Regione:
</text>
- <text name="region_text">
+ <text name="region_text" left="70">
sconosciuta
</text>
<text name="version_channel_text_lbl">
Versione:
</text>
- <text name="version_channel_text">
+ <text name="version_channel_text" left="70">
sconosciuta
</text>
<text name="region_type_lbl">
Tipo:
</text>
- <text name="region_type">
+ <text name="region_type" left="70">
sconosciuto
</text>
<check_box label="Proibisci la modifica del terreno" name="block_terraform_check"/>
@@ -27,33 +27,27 @@
<check_box label="Limita gli urti" name="restrict_pushobject"/>
<button label="?" name="restrict_pushobject_help"/>
<check_box label="Abilita la rivendita del terreno" name="allow_land_resell_check"/>
- <button label="?" name="land_resell_help"/>
+ <button label="?" name="land_resell_help" left="260"/>
<check_box label="Abilita unione/suddivisione del terreno" name="allow_parcel_changes_check"/>
- <button label="?" name="parcel_changes_help"/>
+ <button label="?" name="parcel_changes_help" left="260" />
<check_box label="Proibisci che il terreno appaia nelle ricerche" name="block_parcel_search_check" tool_tip="Permetti che le persone vedano questa regione e le sue suddivisioni nei risultati delle ricerche"/>
- <button label="?" name="parcel_search_help"/>
- <spinner label="Limite massimo di avatar" name="agent_limit_spin"/>
+ <button label="?" name="parcel_search_help" left="260"/>
+ <spinner label="Limite massimo di avatar" name="agent_limit_spin" label_width="135" width="190"/>
<button label="?" name="agent_limit_help"/>
- <spinner label="Bonus di oggetti" name="object_bonus_spin"/>
+ <spinner label="Bonus di oggetti" name="object_bonus_spin" label_width="135" width="190"/>
<button label="?" name="object_bonus_help"/>
- <text label="Maturità" name="access_text">
+ <text label="Maturità" name="access_text" width="120">
Categoria di accesso:
</text>
- <combo_box label="Mature" name="access_combo">
- <combo_item name="Adult">
- Adult
- </combo_item>
- <combo_item name="Mature">
- Mature
- </combo_item>
- <combo_item name="PG">
- PG
- </combo_item>
+ <combo_box label="Mature" name="access_combo" left="126" width="74">
+ <combo_box.item label="Adult" name="Adult"/>
+ <combo_box.item label="Mature" name="Mature"/>
+ <combo_box.item label="PG" name="PG"/>
</combo_box>
<button label="?" name="access_help"/>
<button label="Applica" name="apply_btn"/>
<button label="Teletrasporta a casa un utente..." name="kick_btn"/>
<button label="Teletrasporta a casa tutti gli utenti..." name="kick_all_btn"/>
<button label="Invia messaggio alla regione..." name="im_btn"/>
- <button label="Gestisci snodo di teleport..." name="manage_telehub_btn"/>
+ <button label="Gestisci snodo di teleport..." name="manage_telehub_btn" width="210"/>
</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 70072275eb..92044bae11 100644
--- a/indra/newview/skins/default/xui/it/panel_region_terrain.xml
+++ b/indra/newview/skins/default/xui/it/panel_region_terrain.xml
@@ -8,9 +8,9 @@
</text>
<spinner label="Altezza dell&apos;acqua" name="water_height_spin"/>
<button label="?" name="water_height_help"/>
- <spinner label="Limite di altezza del terreno" name="terrain_raise_spin"/>
+ <spinner label="Limite di altezza del &#10;terreno" name="terrain_raise_spin"/>
<button label="?" name="terrain_raise_help"/>
- <spinner label="Limite di abbassamento del terreno" name="terrain_lower_spin"/>
+ <spinner label="Limite di abbassamento &#10;del terreno" name="terrain_lower_spin" bottom_delta="-34"/>
<button label="?" name="terrain_lower_help"/>
<check_box label="Usa il sole della regione" name="use_estate_sun_check"/>
<button label="?" name="use_estate_sun_help"/>
@@ -22,6 +22,6 @@
<button label="?" name="download_raw_help"/>
<button label="Carica terreno RAW..." name="upload_raw_btn" tool_tip="Disponibile solo per i proprietari del terreno, non per i manager"/>
<button label="?" name="upload_raw_help"/>
- <button label="Trasforma il terreno" name="bake_terrain_btn" tool_tip="Imposta il terreno corrente come punto medio per i limiti di innalzamento/abbassamento"/>
- <button label="?" name="bake_terrain_help"/>
+ <button width="170" label="Trasforma il terreno" name="bake_terrain_btn" tool_tip="Imposta il terreno corrente come punto medio per i limiti di innalzamento/abbassamento"/>
+ <button left="190" label="?" name="bake_terrain_help"/>
</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_region_texture.xml b/indra/newview/skins/default/xui/it/panel_region_texture.xml
index 4e39db9b1d..254700e9f1 100644
--- a/indra/newview/skins/default/xui/it/panel_region_texture.xml
+++ b/indra/newview/skins/default/xui/it/panel_region_texture.xml
@@ -6,7 +6,7 @@
<text name="region_text">
sconosciuto
</text>
- <text name="detail_texture_text">
+ <text name="detail_texture_text" width="380">
Texture del terreno (è necessario siano 512x512, 24 bit .tga files)
</text>
<text name="height_text_lbl">
@@ -48,10 +48,10 @@
Questi valori rappresentano l&apos;intervallo di miscelazione delle texture qui sopra.
</text>
<text name="height_text_lbl11">
- Misurato in metri, il valore più BASSO corrisponde all&apos;altezza MASSIMA della Texture #1,
+ Misurato in metri, il valore più BASSO corrisponde all&apos;altezza MASSIMA della
</text>
<text name="height_text_lbl12">
- e il valore più ALTO all&apos;altezza MINIMA della Texture #4.
+   Texture #1, e il valore più ALTO all&apos;altezza MINIMA della Texture #4.
</text>
<button label="Applica" name="apply_btn"/>
</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_status_bar.xml b/indra/newview/skins/default/xui/it/panel_status_bar.xml
index 2403dce20e..dfaacb659e 100644
--- a/indra/newview/skins/default/xui/it/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/it/panel_status_bar.xml
@@ -27,8 +27,8 @@
<button label="" label_selected="" name="restrictpush" tool_tip="Vietato spingere"/>
<button label="" label_selected="" name="status_no_voice" tool_tip="Voice non disponibile qui"/>
<button label="" label_selected="" name="buyland" tool_tip="Compra questo terreno"/>
- <line_editor label="Cerca" name="search_editor" tool_tip="Cerca in Second Life"/>
- <button label="" label_selected="" name="search_btn" tool_tip="Cerca in Second Life"/>
+ <line_editor label="Cerca" name="search_editor" tool_tip="Cerca in [SECOND_LIFE]"/>
+ <button label="" label_selected="" name="search_btn" tool_tip="Cerca in [SECOND_LIFE]"/>
<string name="packet_loss_tooltip">
Perdita di pacchetti
</string>
diff --git a/indra/newview/skins/default/xui/it/panel_world_map.xml b/indra/newview/skins/default/xui/it/panel_world_map.xml
new file mode 100644
index 0000000000..d00157a297
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_world_map.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="world_map">
+ <panel.string name="world_map_north">
+ N
+ </panel.string>
+ <panel.string name="world_map_east">
+ E
+ </panel.string>
+ <panel.string name="world_map_west">
+ O
+ </panel.string>
+ <panel.string name="world_map_south">
+ S
+ </panel.string>
+ <panel.string name="world_map_southeast">
+ SE
+ </panel.string>
+ <panel.string name="world_map_northeast">
+ NE
+ </panel.string>
+ <panel.string name="world_map_southwest">
+ SO
+ </panel.string>
+ <panel.string name="world_map_northwest">
+ NO
+ </panel.string>
+ <text label="N" name="floater_map_north" text="N">
+ N
+ </text>
+ <text label="E" name="floater_map_east" text="E">
+ E
+ </text>
+ <text label="O" name="floater_map_west" text="O">
+ O
+ </text>
+ <text label="S" name="floater_map_south" text="S">
+ S
+ </text>
+ <text label="SE" name="floater_map_southeast" text="SE">
+ SE
+ </text>
+ <text label="NE" name="floater_map_northeast" text="NE">
+ NE
+ </text>
+ <text label="SO" name="floater_map_southwest" text="SO">
+ SO
+ </text>
+ <text label="NO" name="floater_map_northwest" text="NO">
+ NO
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml
index d7884cfbdb..6e3301fdd9 100644
--- a/indra/newview/skins/default/xui/it/strings.xml
+++ b/indra/newview/skins/default/xui/it/strings.xml
@@ -4,6 +4,7 @@
For example, the strings used in avatar chat bubbles, and strings
that are returned from one component and may appear in many places-->
<strings>
+ <string name="create_account_url">http://join.secondlife.com/index.php?lang=it-IT</string>
<string name="LoginInProgress">
In connessione. [APP_NAME] può sembrare rallentata. Attendi.
</string>
@@ -17,7 +18,7 @@
Un precedente tentativo di login è fallito. Tentativo di connessione [NUMBER]
</string>
<string name="LoginPrecaching">
- Sto caricando SecondLife...
+ Sto caricando [SECOND_LIFE]...
</string>
<string name="LoginInitializingBrowser">
Inizializzazione del browser web incorporato...
@@ -483,4 +484,169 @@
<string name="choose_the_directory">
Scegli la cartella
</string>
+ <string name="accel-mac-control">
+ &#8963;
+ </string>
+ <string name="accel-mac-command">
+ &#8984;
+ </string>
+ <string name="accel-mac-option">
+ &#8997;
+ </string>
+ <string name="accel-mac-shift">
+ &#8679;
+ </string>
+ <string name="accel-win-control">
+ Ctrl+
+ </string>
+ <string name="accel-win-alt">
+ Alt+
+ </string>
+ <string name="accel-win-shift">
+ Shift+
+ </string>
+ <string name="GraphicsQualityLow">
+ Basso
+ </string>
+ <string name="GraphicsQualityMid">
+ Medio
+ </string>
+ <string name="GraphicsQualityHigh">
+ Alto
+ </string>
+
+ <!-- PARCEL_CATEGORY_UI_STRING - TAKE FROM floater_about_land."land category with adult".item1-item12 -->
+ <string name="Linden Location">Luogo dei Linden</string>
+ <string name="Adult">Adult</string>
+ <string name="Arts&amp;Culture">Arte &amp; Cultura</string>
+ <string name="Business">Affari</string>
+ <string name="Educational">Educazione</string>
+ <string name="Gaming">Gioco</string>
+ <string name="Hangout">Divertimento</string>
+ <string name="Newcomer Friendly">Accoglienza nuovi residenti</string>
+ <string name="Parks&amp;Nature">Parchi &amp; Natura</string>
+ <string name="Residential">Residenziale</string>
+ <string name="Shopping">Shopping</string>
+ <string name="Other">Altro</string>
+
+ <string name="ringing">
+ In connessione alla Voice Chat in-world...
+ </string>
+ <string name="connected">
+ Connesso
+ </string>
+ <string name="unavailable">
+ Il voice non è disponibile nel posto dove ti trovi ora
+ </string>
+ <string name="hang_up">
+ Disconnesso dalla Voice Chat in-world
+ </string>
+ <string name="ScriptQuestionCautionChatGranted">
+ A &apos;[OBJECTNAME]&apos;, un oggetto di proprietà di &apos;[OWNERNAME]&apos;, situato in [REGIONNAME] [REGIONPOS], è stato concesso il permesso di: [PERMISSIONS].
+ </string>
+ <string name="ScriptQuestionCautionChatDenied">
+ A &apos;[OBJECTNAME]&apos;, un oggetto di proprietà di &apos;[OWNERNAME]&apos;, situato in [REGIONNAME] [REGIONPOS], è stato negato il permesso di: [PERMISSIONS].
+ </string>
+ <string name="ScriptTakeMoney">
+ Prendere dollari Linden (L$) da te
+ </string>
+ <string name="ActOnControlInputs">
+ Agire sul tuo controllo degli input
+ </string>
+ <string name="RemapControlInputs">
+ Rimappare il tuo controllo degli input
+ </string>
+ <string name="AnimateYourAvatar">
+ Animare il tuo avatar
+ </string>
+ <string name="AttachToYourAvatar">
+ Far indossare al tuo avatar
+ </string>
+ <string name="ReleaseOwnership">
+ Rilasciare la propietà è far diventare pubblico.
+ </string>
+ <string name="LinkAndDelink">
+ Collegare e scollegare dagli altri oggetti
+ </string>
+ <string name="AddAndRemoveJoints">
+ Aggiungere e rimuovere le giunzioni insieme con gli altri oggetti
+ </string>
+ <string name="ChangePermissions">
+ Cambiare i permessi
+ </string>
+ <string name="TrackYourCamera">
+ Tracciare la fotocamera
+ </string>
+ <string name="ControlYourCamera">
+ Controllare la tua fotocamera
+ </string>
+ <string name="only_user_message">
+ Sei l&apos;unico utente di questa sessione.
+ </string>
+ <string name="offline_message">
+ [FIRST] [LAST] è offline.
+ </string>
+ <string name="invite_message">
+ Clicca il tasto [BUTTON NAME] per accettare/connetterti a questa voice chat.
+ </string>
+ <string name="generic_request_error">
+ Errore durante la richiesta, riprova più tardi.
+ </string>
+ <string name="insufficient_perms_error">
+ Non hai sufficienti permessi.
+ </string>
+ <string name="session_does_not_exist_error">
+ Questa sessione non esiste più
+ </string>
+ <string name="no_ability_error">
+ Non hai questa abilitazione.
+ </string>
+ <string name="no_ability">
+ Non hai questa abilitazione.
+ </string>
+ <string name="not_a_mod_error">
+ Non sei un moderatore.
+ </string>
+ <string name="muted_error">
+ Un moderatore di gruppo ti ha disabilitato dalla chat di testo.
+ </string>
+ <string name="add_session_event">
+ Impossibile aggiungere utenti alla chat con [RECIPIENT].
+ </string>
+ <string name="message_session_event">
+ Impossibile inviare il messaggio nella chat con [RECIPIENT].
+ </string>
+ <string name="removed_from_group">
+ Sei stato espulso dal gruppo.
+ </string>
+ <string name="close_on_no_ability">
+ Non hai più le abilitazioni per rimanere nella sessione chat.
+ </string>
+ <string name="AcctTypeResident">
+ Residente
+ </string>
+ <string name="AcctTypeTrial">
+ Prova
+ </string>
+ <string name="AcctTypeCharterMember">
+ Membro privilegiato
+ </string>
+ <string name="AcctTypeEmployee">
+ Impiegato della Linden Lab
+ </string>
+ <string name="PaymentInfoUsed">
+ Info. di pagamento usate
+ </string>
+ <string name="PaymentInfoOnFile">
+ Info. di pagamento in archivio
+ </string>
+ <string name="NoPaymentInfoOnFile">
+ Nessuna info. di pagamento
+ </string>
+ <string name="AgeVerified">
+ Età verificata
+ </string>
+ <string name="NotAgeVerified">
+ Età non verificata
+ </string>
</strings>
diff --git a/indra/newview/skins/default/xui/it/teleport_strings.xml b/indra/newview/skins/default/xui/it/teleport_strings.xml
index 4ef802dc5b..57e81bc41e 100644
--- a/indra/newview/skins/default/xui/it/teleport_strings.xml
+++ b/indra/newview/skins/default/xui/it/teleport_strings.xml
@@ -25,7 +25,7 @@ www.secondlife.com/support
Gli oggetti da te indossati non sono ancoa arrivati. Attendi ancora qualche secondo o scollegati e ricollegati prima di provare a teleportarti.
</message>
<message name="too_many_uploads_tport">
- La gestione dati della regione è al momento occupata e la tua richiesta di teletrasporto non può essere soddisfatta entro breve tempo. Per favore prova di nuovo tra qualche minuto o spostati in un&apos;area meno affollata.
+ Il server della regione è al momento occupato e la tua richiesta di teletrasporto non può essere soddisfatta entro breve tempo. Per favore prova di nuovo tra qualche minuto o spostati in un&apos;area meno affollata.
</message>
<message name="expired_tport">
Spiacenti, il sistema non riesce a soddisfare la tua richiesta di teletrasporto entro un tempo ragionevole. Riprova tra qualche minuto.
@@ -42,34 +42,34 @@ www.secondlife.com/support
</message_set>
<message_set name="progress">
<message name="sending_dest">
- In invio verso la destinazione.
+ In invio a destinazione.
</message>
<message name="redirecting">
In reindirizzamento ad una nuova destinazione.
</message>
<message name="relaying">
- In ritrasmissione alla destinazione.
+ In reinvio a destinazione.
</message>
<message name="sending_home">
- In invio la richiesta di ubicazione casa.
+ In invio verso la destinazione casa.
</message>
<message name="sending_landmark">
- In invio la richiesta della destinazione del landmark.
+ In invio verso la destinazione del landmark.
</message>
<message name="completing">
Teletrasporto completato
</message>
<message name="resolving">
- Destinazione in elaborazione.
+ Elaborazione della destinazione in corso...
</message>
<message name="contacting">
- Si sta contattando la nuova regione.
+ Contattando la nuova regione.
</message>
<message name="arriving">
- In arrivo...
+ In arrivo a destinazione...
</message>
<message name="requesting">
- Teletrasporto in avvio...
+ Avvio teletrasporto....
</message>
</message_set>
</teleport_messages>
diff --git a/indra/newview/skins/default/xui/ja/floater_about.xml b/indra/newview/skins/default/xui/ja/floater_about.xml
index ffdbec666d..0fa20ab1ac 100644
--- a/indra/newview/skins/default/xui/ja/floater_about.xml
+++ b/indra/newview/skins/default/xui/ja/floater_about.xml
@@ -1,11 +1,60 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_about" title="Second Lifeã«ã¤ã„ã¦">
- <text_editor name="credits_editor">
- Second Lifeã¯ã€ Philipã€Tessaã€Andrewã€Coryã€Jamesã€Benã€Charã€Charlieã€Colinã€Danã€Danielã€Dougã€Ericã€Hamletã€Haneyã€Eveã€Hunterã€Ianã€Jeffã€Jenniferã€Jimã€Johnã€Leeã€Markã€Peterã€Phoenixã€Richardã€Robinã€Xenonã€Steveã€Tanyaã€Eddieã€Aviã€Frankã€Bruceã€Aaronã€Aliceã€Bobã€Debraã€Eileenã€Helenã€Janetã€Louieã€Leviathaniaã€Stefanã€Rayã€Kevinã€Tomã€Mikebã€MikeTã€Burgessã€Elenaã€Tracyã€Billã€Toddã€Ryanã€Zachã€Sarahã€Novaã€Timã€Stephanieã€Michaelã€Evanã€Nicolasã€Catherineã€Rachelleã€Daveã€Hollyã€Bubã€Kellyã€Magellanã€Ramziã€Donã€Sabinã€Jillã€Rheyaã€Jeskaã€Torleyã€Konaã€Callumã€Charityã€Ventrellaã€Jackã€Vektorã€Irisã€Chrisã€Nicoleã€Mickã€Reubenã€Blueã€Babbageã€Yedwabã€Deanaã€Laurenã€Brentã€Pathfinderã€Chadrickã€Altruimaã€Jesseã€Teenyã€Monroeã€Icculusã€Davidã€Tessã€Lizzieã€Patsyã€Isaacã€Lawrenceã€Cynã€Boã€Giaã€Annetteã€Mariusã€Tboneã€Jonathanã€Karenã€Ginsuã€Satokoã€Yukoã€Makikoã€Thomasã€Harryã€Sethã€Alexeiã€Brianã€Guyã€Runitaiã€Ethanã€Dataã€Corneliusã€Kennyã€Swissã€Zeroã€Natriaã€Wendyã€Stephenã€Teepleã€Thumperã€Lucyã€Deeã€Miaã€Lianaã€Warrenã€Brankaã€Auraã€beezã€Miloã€Hermiaã€Redã€Thraxã€Joeã€Sallyã€Magentaã€Moguraã€Paulã€Joseã€Rejeanã€Henrikã€Lexieã€Amberã€Loganã€Xanã€Noraã€Morpheusã€Donovanã€Leylaã€MichaelFrancisã€Beastã€Cubeã€Buckyã€Joshuaã€Stryfeã€Harmonyã€Teresaã€Claudiaã€Walkerã€Glennã€Fritzã€Fordakã€Juneã€Cleopetraã€Jeanã€Ivyã€Betsyã€Rooseveltã€Spikeã€Kenã€Whichã€Tofuã€Chiyoã€Robã€Zeeã€dustinã€Georgeã€Delã€Matthewã€Catã€Jacquiã€Lightfootã€Adrianã€Violaã€Alfredã€Noelã€Irfanã€Sunilã€Yoolã€Rikaã€Janeã€Xtremeã€Frontierã€a2ã€Neoã€Siobhanã€Yozã€Justinã€Elleã€Qarlã€Benjaminã€Isabelã€Gulliverã€Everettã€Christopherã€Izzyã€Stephanyã€Garryã€Sejongã€Seanã€Tobinã€Iridiumã€Metaã€Anthonyã€Jeremyã€JPã€Jakeã€Mauriceã€Madhaviã€Leopardã€Kyleã€Joonã€Kariã€Bertã€Belindaã€Jonã€Kristiã€Bridieã€Pramodã€KJã€Socratesã€Mariaã€Ivanã€Aricã€Yamasakiã€Adreanneã€Jayã€MitchKã€Cerenã€Cocoã€Durlã€Jennyã€Periapseã€Karticã€Storrsã€Lotteã€Sandyã€Rohnã€Colossusã€Zenã€BigPapiã€Bradã€Pastramiã€Kurzã€Maniã€Neuroã€Jaimeã€MJã€Rowanã€Sgtã€Elvisã€Geckoã€Samuelã€Sardonyxã€Leoã€Bryanã€Nikoã€Softã€Poppyã€Rachelã€Akiã€Angeloã€Banzaiã€Alexaã€Sueã€CeeLoã€Benderã€CGã€Gillianã€Pelleã€Nickã€Echoã€Zaraã€Christineã€Shamiranã€Emmaã€Blakeã€Keikoã€Plexusã€Joppaã€Sidewinderã€Ericaã€Ashleiã€Twilightã€Kristenã€Brettã€Qã€Enusã€Simonã€Bevisã€Kraftã€Kipã€Chandlerã€Ronã€LauraPã€Ramã€KyleJMã€Scouseã€Prosperoã€Melissaã€Martyã€Natã€Hamiltonã€Kendã€Lordanã€Jimmyã€Kosmoã€Seraphã€Greenã€Ekimã€Wiggoã€JTã€Romeã€Dorisã€Mizã€Benocã€Whumpã€Trinityã€Patchã€Kateã€TJã€Baoã€Joohwanã€Christyã€Sofiaã€Matiasã€Cogsworthã€Johanã€Orehã€Cheahã€Angelaã€Brandyã€Mangoã€Lanã€Aleksã€Gloriaã€Heidyã€Mitchellã€Spaceã€Coltonã€Bambersã€Einsteinã€Maggieã€Malbersã€Roseã€Winnieã€Stellaã€Miltonã€Rothmanã€Niallã€Marinã€Allisonã€Katieã€Dawnã€Kattã€Dustyã€Kalpanaã€Judyã€Andreaã€Ambroffã€Infinityã€Gailã€Ricoã€Raymondã€Yiã€Williamã€Christaã€Mã€Teaganã€Scoutã€Mollyã€Danteã€Corrã€Dynamikeã€Usiã€Kayleeã€Vidtutsã€Lilã€Danicaã€Saschaã€Kelvã€Jacobã€Nyaã€Rodneyã€Brandonã€Elsieã€Blondinã€Grantã€Katrinã€Nyxã€Gabrielã€Locklainnã€Claireã€Devinã€Minervaã€Montyã€Austinã€Bradfordã€Siã€Keiraã€Hã€Caitlinã€Ditaã€Makaiã€Jennã€Annã€Meredithã€Clareã€Joyã€Praveenã€Codyã€Edmundã€Rutheã€Sirenaã€Gayathriã€Spiderã€FJã€Davidoffã€Tianã€Jennieã€Louiseã€Oskarã€Landonã€Noelleã€Jarvã€Ingridã€Alã€Sommerã€Docã€Ariaã€Huinã€Grayã€Liliã€Virã€DJã€Yangã€Tã€Simoneã€Maestroã€Scottã€Charleneã€Quixoteã€Amandaã€Susanã€Zedã€Anneã€Enkiduã€Esbeeã€Joroanã€Katelinã€Roxieã€Tayã€Scarletã€Kevinã€Johnnyã€Wolfgangã€Andrenã€Bobã€Howardã€Merovã€Randã€Rayã€Michonã€Newellã€Galenã€Dessieã€Lesã¨ã€ãã®ä»–多数ã®äººé”ã«ã‚ˆã£ã¦ä½œæˆã•ã‚Œã¾ã—ãŸã€‚
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_about" title="[CAPITALIZED_APP_NAME] ã«ã¤ã„ã¦">
+ <floater.string name="AboutHeader">
+ [APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL])
+[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]]
+ </floater.string>
+ <floater.string name="AboutCompiler">
+ コンパイラー [COMPILER] [COMPILER_VERSION] ãƒãƒ¼ã‚¸ãƒ§ãƒ³
+ </floater.string>
+ <floater.string name="AboutPosition">
+ You are at [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] in [REGION] located at [HOSTNAME] ([HOSTIP])
+[SERVER_VERSION]
+[[SERVER_RELEASE_NOTES_URL] [ReleaseNotes]]
+ </floater.string>
+ <floater.string name="AboutSystem">
+ CPU: [CPU]
+メモリ: [MEMORY_MB] MB
+OS ãƒãƒ¼ã‚¸ãƒ§ãƒ³ï¼š [OS_VERSION]
+グラフィックカード製造元: [GRAPHICS_CARD_VENDOR]
+グラフィックカード: [GRAPHICS_CARD]
+ </floater.string>
+ <floater.string name="AboutDriver">
+ Windows グラフィックドライãƒãƒãƒ¼ã‚¸ãƒ§ãƒ³ï¼š [GRAPHICS_DRIVER_VERSION]
+ </floater.string>
+ <floater.string name="AboutLibs">
+ OpenGL ãƒãƒ¼ã‚¸ãƒ§ãƒ³ï¼š [OPENGL_VERSION]
- ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ã“ã‚Œã¾ã§ã§æœ€é«˜ã®ã‚‚ã®ã«ãªã‚‹ã‚ˆã†ã”å”力をã„ãŸã ã„ãŸä»¥ä¸‹ã®ä½äººã®çš†æ§˜ã«æ·±ãæ„Ÿè¬ã„ãŸã—ã¾ã™ã€‚ afon shepherdã€Aimee Trescothickã€Alexandrea Frideã€Alissa Sabreã€Amber DeCuirã€Asuka Neelyã€Auron Forcellaã€Blue Revolutionã€Bocan Undercroftã€Boroondas Gupteã€Brandon Shinobuã€Bri Guflerã€Buckaroo Muã€Celierra Darlingã€Christos Atlantisã€Coder Kasã€Cummere Mayoã€dakota schwadeã€Dirk Talamascaã€Dizzy Banjoã€Drew Dwiã€Duckling Kwakã€Ellla McMahonã€Erikah Jamesonã€Erinyse Planerã€Eyana Yohkohã€Ezian Ecksolã€Faron Karuã€Fenoe Loweyã€Fox Hwasungã€Francisca Biedermannã€Gally Youngã€Gellan Glenelgã€Geneko Nemethã€Glenn Rotaruã€Hagar Qinanã€Harleen Gretzkyã€Holger Gilruthã€hotrodjohnny gearsã€IAm Zabelinã€Inigo Catteneoã€Iustinian Tomsenã€Jacek Antonellã€James Benedekã€Jim Kupferbergã€Joeseph Albaneseã€JPT62089 Agnonã€Kardargo Adamczykã€Kirstenlee Cinquettiã€Latif Khalifaã€lea Parnallã€Lex Nevaã€Lillith Anatineã€Lilly Zenovkaã€Lim Catteneoã€Lindal Kiddã€Mark Rosenbaumã€MasterJ Chaplinã€McCabe Maxstedã€Melvin Starbrookã€Meni Kaiouseiã€Mero Collasã€Minakothegothicgeisha Kamachiã€Moon Mettyã€neofilo aabyeã€Neutron Chesnokovã€Nomad Ingwerã€norritt Xiã€Opensource Obscureã€Oracle Weatherwaxã€Ourasi Ferrarisã€Pabl0 Roffoã€Peyton Aleixandreã€Phli Foxchaseã€Psi Merlinã€r2d2 Wunderlichã€Regi Yifuã€Saijanai Kuhnã€Sandor Balczoã€Sarkan Dreamscapeã€Scree Raymakerã€Sedona Millsã€Selena Bealeã€Sheet Spotterã€Shibari Twineã€Silver Keyã€Simon Klineã€SLB Wireflyã€Stacy Wombatã€Sugarcult Daggerã€Tayra Dagostinoã€Tetsuryu Vlodovicã€ThaBiGGDoGG Richezã€Timo Guflerã€tx Ohã€wayfinder wishbringerã€Wizzytoe McCulloughã€Wundur Primbeeã€Yann Dufauxã€Yuu Nakamichiã€Aminom Marvinã€Andred Qinanã€arminasx saimanã€caroline apolloã€Iskar Arianthoã€Jenika Connollyã€Maghnus Baloghã€Nefertiti Nefariousã€RodneyLee Jessop
+libcurl ãƒãƒ¼ã‚¸ãƒ§ãƒ³ï¼š [LIBCURL_VERSION]
+J2C デコーダãƒãƒ¼ã‚¸ãƒ§ãƒ³ï¼š [J2C_VERSION]
+オーディオドライãƒãƒãƒ¼ã‚¸ãƒ§ãƒ³ï¼š [AUDIO_DRIVER_VERSION]
+Qt Webkit ãƒãƒ¼ã‚¸ãƒ§ãƒ³ï¼š [QT_WEBKIT_VERSION]
+Vivox ãƒãƒ¼ã‚¸ãƒ§ãƒ³ï¼š [VIVOX_VERSION]
+ </floater.string>
+ <floater.string name="none">
+ (ãªã—)
+ </floater.string>
+ <floater.string name="AboutTraffic">
+ パケットロス: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%)
+ </floater.string>
+ <tab_container name="about_tab">
+ <panel label="情報" name="support_panel">
+ <button label="クリップボードã«ã‚³ãƒ”ー" name="copy_btn"/>
+ </panel>
+ <panel label="クレジット" name="credits_panel">
+ <text_editor name="credits_editor">
+ Second Lifeã¯ã€ Philipã€Tessaã€Andrewã€Coryã€Jamesã€Benã€Charã€Charlieã€Colinã€Danã€Danielã€Dougã€Ericã€Hamletã€Haneyã€Eveã€Hunterã€Ianã€Jeffã€Jenniferã€Jimã€Johnã€Leeã€Markã€Peterã€Phoenixã€Richardã€Robinã€Xenonã€Steveã€Tanyaã€Eddieã€Aviã€Frankã€Bruceã€Aaronã€Aliceã€Bobã€Debraã€Eileenã€Helenã€Janetã€Louieã€Leviathaniaã€Stefanã€Rayã€Kevinã€Tomã€Mikebã€MikeTã€Burgessã€Elenaã€Tracyã€Billã€Toddã€Ryanã€Zachã€Sarahã€Novaã€Timã€Stephanieã€Michaelã€Evanã€Nicolasã€Catherineã€Rachelleã€Daveã€Hollyã€Bubã€Kellyã€Magellanã€Ramziã€Donã€Sabinã€Jillã€Rheyaã€Jeskaã€Torleyã€Konaã€Callumã€Charityã€Ventrellaã€Jackã€Vektorã€Irisã€Chrisã€Nicoleã€Mickã€Reubenã€Blueã€Babbageã€Yedwabã€Deanaã€Laurenã€Brentã€Pathfinderã€Chadrickã€Altruimaã€Jesseã€Teenyã€Monroeã€Icculusã€Davidã€Tessã€Lizzieã€Patsyã€Isaacã€Lawrenceã€Cynã€Boã€Giaã€Annetteã€Mariusã€Tboneã€Jonathanã€Karenã€Ginsuã€Satokoã€Yukoã€Makikoã€Thomasã€Harryã€Sethã€Alexeiã€Brianã€Guyã€Runitaiã€Ethanã€Dataã€Corneliusã€Kennyã€Swissã€Zeroã€Natriaã€Wendyã€Stephenã€Teepleã€Thumperã€Lucyã€Deeã€Miaã€Lianaã€Warrenã€Brankaã€Auraã€beezã€Miloã€Hermiaã€Redã€Thraxã€Joeã€Sallyã€Magentaã€Moguraã€Paulã€Joseã€Rejeanã€Henrikã€Lexieã€Amberã€Loganã€Xanã€Noraã€Morpheusã€Donovanã€Leylaã€MichaelFrancisã€Beastã€Cubeã€Buckyã€Joshuaã€Stryfeã€Harmonyã€Teresaã€Claudiaã€Walkerã€Glennã€Fritzã€Fordakã€Juneã€Cleopetraã€Jeanã€Ivyã€Betsyã€Rooseveltã€Spikeã€Kenã€Whichã€Tofuã€Chiyoã€Robã€Zeeã€dustinã€Georgeã€Delã€Matthewã€Catã€Jacquiã€Lightfootã€Adrianã€Violaã€Alfredã€Noelã€Irfanã€Sunilã€Yoolã€Rikaã€Janeã€Xtremeã€Frontierã€a2ã€Neoã€Siobhanã€Yozã€Justinã€Elleã€Qarlã€Benjaminã€Isabelã€Gulliverã€Everettã€Christopherã€Izzyã€Stephanyã€Garryã€Sejongã€Seanã€Tobinã€Iridiumã€Metaã€Anthonyã€Jeremyã€JPã€Jakeã€Mauriceã€Madhaviã€Leopardã€Kyleã€Joonã€Kariã€Bertã€Belindaã€Jonã€Kristiã€Bridieã€Pramodã€KJã€Socratesã€Mariaã€Ivanã€Aricã€Yamasakiã€Adreanneã€Jayã€MitchKã€Cerenã€Cocoã€Durlã€Jennyã€Periapseã€Karticã€Storrsã€Lotteã€Sandyã€Rohnã€Colossusã€Zenã€BigPapiã€Bradã€Pastramiã€Kurzã€Maniã€Neuroã€Jaimeã€MJã€Rowanã€Sgtã€Elvisã€Geckoã€Samuelã€Sardonyxã€Leoã€Bryanã€Nikoã€Softã€Poppyã€Rachelã€Akiã€Angeloã€Banzaiã€Alexaã€Sueã€CeeLoã€Benderã€CGã€Gillianã€Pelleã€Nickã€Echoã€Zaraã€Christineã€Shamiranã€Emmaã€Blakeã€Keikoã€Plexusã€Joppaã€Sidewinderã€Ericaã€Ashleiã€Twilightã€Kristenã€Brettã€Qã€Enusã€Simonã€Bevisã€Kraftã€Kipã€Chandlerã€Ronã€LauraPã€Ramã€KyleJMã€Scouseã€Prosperoã€Melissaã€Martyã€Natã€Hamiltonã€Kendã€Lordanã€Jimmyã€Kosmoã€Seraphã€Greenã€Ekimã€Wiggoã€JTã€Romeã€Dorisã€Mizã€Benocã€Whumpã€Trinityã€Patchã€Kateã€TJã€Baoã€Joohwanã€Christyã€Sofiaã€Matiasã€Cogsworthã€Johanã€Orehã€Cheahã€Angelaã€Brandyã€Mangoã€Lanã€Aleksã€Gloriaã€Heidyã€Mitchellã€Spaceã€Coltonã€Bambersã€Einsteinã€Maggieã€Malbersã€Roseã€Winnieã€Stellaã€Miltonã€Rothmanã€Niallã€Marinã€Allisonã€Katieã€Dawnã€Kattã€Dustyã€Kalpanaã€Judyã€Andreaã€Ambroffã€Infinityã€Gailã€Ricoã€Raymondã€Yiã€Williamã€Christaã€Mã€Teaganã€Scoutã€Mollyã€Danteã€Corrã€Dynamikeã€Usiã€Kayleeã€Vidtutsã€Lilã€Danicaã€Saschaã€Kelvã€Jacobã€Nyaã€Rodneyã€Brandonã€Elsieã€Blondinã€Grantã€Katrinã€Nyxã€Gabrielã€Locklainnã€Claireã€Devinã€Minervaã€Montyã€Austinã€Bradfordã€Siã€Keiraã€Hã€Caitlinã€Ditaã€Makaiã€Jennã€Annã€Meredithã€Clareã€Joyã€Praveenã€Codyã€Edmundã€Rutheã€Sirenaã€Gayathriã€Spiderã€FJã€Davidoffã€Tianã€Jennieã€Louiseã€Oskarã€Landonã€Noelleã€Jarvã€Ingridã€Alã€Sommerã€Docã€Ariaã€Huinã€Grayã€Liliã€Virã€DJã€Yangã€Tã€Simoneã€Maestroã€Scottã€Charleneã€Quixoteã€Amandaã€Susanã€Zedã€Anneã€Enkiduã€Esbeeã€Joroanã€Katelinã€Roxieã€Tayã€Scarletã€Kevinã€Johnnyã€Wolfgangã€Andrenã€Bobã€Howardã€Merovã€Randã€Rayã€Michonã€Newellã€Galenã€Dessieã€Lesã€Michonã€Jenelleã€Geoã€Sizã€Shapiroã€Peteã€Calyleã€Seleneã€Allenã€Phoebeã€Goldinã€Kimmoraã€Dakotaã€Slatonã€Lindquistã€Zoeyã€Hariã€Othelloã€Rohitã€Sheldonã€Petraã€Vialeã€Gordonã€Kayeã€Pinkã€Fernyã€Emersonã€Davyã€Briã€Chanã€Juanã€Robertã€Terrenceã€Nathanã€Carlã¨ã€ãã®ä»–多数ã®äººé”ã«ã‚ˆã£ã¦ä½œæˆã•ã‚Œã¾ã—ãŸã€‚
- 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
+ ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ã“ã‚Œã¾ã§ã§æœ€é«˜ã®ã‚‚ã®ã«ãªã‚‹ã‚ˆã†ã”å”力をã„ãŸã ã„ãŸä»¥ä¸‹ã®ä½äººã®çš†æ§˜ã«æ·±ãæ„Ÿè¬ã„ãŸã—ã¾ã™ã€‚ able whitman, Adeon Writer, adonaira aabye, Aeron Kohime, Agathos Frascati, Aimee Trescothick, Aleric Inglewood, Alissa Sabre, Aminom Marvin, Angela Talamasca, Aralara Rajal, Armin Weatherwax, Ashrilyn Hayashida, Athanasius Skytower, Aura Dirval, Barney Boomslang, Biancaluce Robbiani, Biker Offcourse, Borg Capalini, Bulli Schumann, catherine pfeffer, Chalice Yao, Corre Porta, Court Goodman, Cummere Mayo, Dale Innis, Darien Caldwell, Darjeeling Schoonhoven, Daten Thielt, dimentox travanti, Dirk Talamasca, Drew Dwi, Duckless Vandyke, Elanthius Flagstaff, Electro Burnstein, emiley tomsen, Escort DeFarge, Eva Rau, Ezian Ecksol, Fire Centaur, Fluf Fredriksson, Francisco Koolhoven, Frontera Thor, Frungi Stastny, Gally Young, gearsawe stonecutter, Gigs Taggart, Gordon Wendt, Gudmund Shepherd, Gypsy Paz, Harleen Gretzky, Henri Beauchamp, Inma Rau, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Jessicka Graves, Joeseph Albanese, Joshua Philgarlic, Khyota Wulluf, kirstenlee Cinquetti, Latif Khalifa, Lex Neva, Lilibeth Andree, Lisa Lowe, Lunita Savira, Loosey Demonia, lum pfohl, Marcos Fonzarelli, MartinRJ Fayray, Marusame Arai, Matthew Dowd, Maya Remblai, McCabe Maxsted, Meghan Dench, Melchoir Tokhes, Menos Short, Michelle2 Zenovka, Mimika Oh, Minerva Memel, Mm Alder, Ochi Wolfe, Omei Turnbull, Pesho Replacement, Phantom Ninetails, phoenixflames kukulcan, Polo Gufler, prez pessoa, princess niven, Prokofy Neva, Qie Niangao, Rem Beattie, RodneyLee Jessop, Saijanai Kuhn, Seg Baphomet, Sergen Davies, Shirley Marquez, SignpostMarv Martin, Sindy Tsure, Sira Arbizu, Skips Jigsaw, Sougent Harrop, Spritely Pixel, Squirrel Wood, StarSong Bright, Subversive Writer, Sugarcult Dagger, Sylumm Grigorovich, Tammy Nowotny, Tanooki Darkes, Tayra Dagostino, Theoretical Chemistry, Thickbrick Sleaford, valerie rosewood, Vex Streeter, Vixen Heron, Whoops Babii, Winter Ventura, Xiki Luik, Yann Dufaux, Yina Yao, Yukinoroh Kamachi, Zolute Infinity, Zwagoth Klaar
+
+
+
+ ビジãƒã‚¹ã§æˆåŠŸã™ã‚‹ã«ã¯ã€å‹‡æ°—ã‚’æŒã£ã¦ã€èª°ã‚ˆã‚Šã‚‚å…ˆã«ã€äººã¨é•ã£ãŸã“ã¨ã‚’ã™ã‚‹ã“ã¨ã ã€‚ --Henry Marchant
+ </text_editor>
+ </panel>
+ <panel label="ライセンス" name="licenses_panel">
+ <text_editor name="credits_editor">
+ 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
APR Copyright (C) 2000-2004 The Apache Software Foundation
cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
@@ -25,11 +74,7 @@
無断転写ã€è¤‡è£½ã€è»¢è¼‰ã‚’ç¦ã˜ã¾ã™ã€‚ 詳細ã¯licenses.txtã‚’å‚ç…§ã—ã¦ãã ã•ã„。
Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
-
-
- ビジãƒã‚¹ã§æˆåŠŸã™ã‚‹ã«ã¯ã€å‹‡æ°—ã‚’æŒã£ã¦ã€èª°ã‚ˆã‚Šã‚‚å…ˆã«ã€äººã¨é•ã£ãŸã“ã¨ã‚’ã™ã‚‹ã“ã¨ã ã€‚ --Henry Marchant
- </text_editor>
- <text name="you_are_at">
- [POSITION]
- </text>
+ </text_editor>
+ </panel>
+ </tab_container>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_about_land.xml b/indra/newview/skins/default/xui/ja/floater_about_land.xml
index c8195d8f38..4b134526e0 100644
--- a/indra/newview/skins/default/xui/ja/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/ja/floater_about_land.xml
@@ -1,12 +1,64 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="floaterland" title="土地情報">
+ <floater.string name="Minutes">
+ [MINUTES] 分
+ </floater.string>
+ <floater.string name="Minute">
+ 分
+ </floater.string>
+ <floater.string name="Seconds">
+ [SECONDS] 秒
+ </floater.string>
+ <floater.string name="Remaining">
+ 残り
+ </floater.string>
<tab_container name="landtab">
<panel label="一般" name="land_general_panel">
- <text length="1" name="Name:" type="string">
+ <panel.string name="new users only">
+ æ–°è¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã¿
+ </panel.string>
+ <panel.string name="anyone">
+ 誰ã§ã‚‚
+ </panel.string>
+ <panel.string name="area_text">
+ é¢ç©ï¼š
+ </panel.string>
+ <panel.string name="area_size_text">
+ [AREA] 平方メートル
+ </panel.string>
+ <panel.string name="auction_id_text">
+ オークションID: [ID]
+ </panel.string>
+ <panel.string name="need_tier_to_modify">
+ ã“ã®åœŸåœ°ã‚’修正変更ã™ã‚‹ã«ã¯ã€è³¼å…¥ã‚’承èªã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+ </panel.string>
+ <panel.string name="group_owned_text">
+ (グループ所有)
+ </panel.string>
+ <panel.string name="profile_text">
+ プロフィール...
+ </panel.string>
+ <panel.string name="info_text">
+ 情報...
+ </panel.string>
+ <panel.string name="public_text">
+ (公共)
+ </panel.string>
+ <panel.string name="none_text">
+ (ãªã—)
+ </panel.string>
+ <panel.string name="sale_pending_text">
+ (購入審査中)
+ </panel.string>
+ <panel.string name="no_selection_text">
+ 区画ãŒé¸å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。
+「世界ã€ãƒ¡ãƒ‹ãƒ¥ãƒ¼ï¼žã€ŒåœŸåœ°æƒ…å ±ã€ã«é€²ã‚€ã‹ã€åˆ¥ã®åŒºç”»ã‚’é¸æŠžã—ã¦ã€è©³ç´°ã‚’表示ã—ã¾ã™ã€‚
+ </panel.string>
+ <text name="Name:">
åå‰ï¼š
</text>
<line_editor name="Name"/>
- <text length="1" name="Description:" type="string">
+ <text name="Description:">
説明:
</text>
<text name="LandType">
@@ -21,56 +73,56 @@
<text name="ContentRatingText">
Adult
</text>
- <text length="1" name="Owner:" type="string">
+ <text name="Owner:">
オーナー:
</text>
- <text length="1" name="OwnerText" type="string">
+ <text name="OwnerText">
Leyla Linden
</text>
<button label="プロフィール..." label_selected="プロフィール..." name="Profile..."/>
- <text length="1" name="Group:" type="string">
+ <text name="Group:">
グループ:
</text>
<button label="設定..." label_selected="設定..." name="Set..."/>
- <check_box label="グループã¸ã®è­²æ¸¡ã‚’許å¯" name="check deed" tool_tip="グループ・オフィサーã¯ã€ã“ã®åœŸåœ°ã‚’グループã«è­²æ¸¡ã—ã€ã‚°ãƒ«ãƒ¼ãƒ—ã®åœŸåœ°é…分ã«å§”ã­ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"/>
+ <check_box label="グループã¸ã®è­²æ¸¡ã‚’許å¯" name="check deed" tool_tip="グループã®ã‚ªãƒ•ã‚£ã‚µãƒ¼ã¯ã“ã®åœŸåœ°ã‚’グループã«è­²æ¸¡ã§ãã¾ã™ã€‚ãã†ã™ã‚‹ã¨ã‚°ãƒ«ãƒ¼ãƒ—ã®åœŸåœ°å‰²ã‚Šå½“ã¦ã«ã‚ˆã£ã¦ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¾ã™ã€‚"/>
<button label="譲渡..." label_selected="譲渡..." name="Deed..." tool_tip="é¸æŠžã•ã‚ŒãŸã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚ªãƒ•ã‚£ã‚µãƒ¼ã§ã‚ã‚‹ã¨ãã®ã¿ã€åœŸåœ°ã‚’譲渡ã§ãã¾ã™ã€‚"/>
<check_box label="オーナーãŒè­²æ¸¡ã¨å…±ã«å¯„付" name="check contrib" tool_tip="土地ãŒã‚°ãƒ«ãƒ¼ãƒ—ã«è­²æ¸¡ã•ã‚Œã‚‹ã¨ãã€å‰ã®æ‰€æœ‰è€…ã¯è­²æ¸¡ãŒæˆç«‹ã™ã‚‹ã‚ˆã†ã€å分ãªåœŸåœ°ã‚’寄付ã—ã¾ã™ã€‚"/>
- <text length="1" name="For Sale:" type="string">
+ <text name="For Sale:">
販売ã®æœ‰ç„¡ï¼š
</text>
- <text length="1" name="Not for sale." type="string">
+ <text name="Not for sale.">
販売対象外
</text>
- <text length="1" name="For Sale: Price L$[PRICE]." type="string">
+ <text name="For Sale: Price L$[PRICE].">
価格: L$[PRICE] (L$[PRICE_PER_SQM]/平方メートル)
</text>
<button label="土地を販売..." label_selected="土地を販売..." name="Sell Land..."/>
- <text length="1" name="For sale to" type="string">
+ <text name="For sale to">
販売先:[BUYER]
</text>
- <text length="1" name="Sell with landowners objects in parcel." type="string">
+ <text name="Sell with landowners objects in parcel.">
オブジェクトも販売価格ã«å«ã¾ã‚Œã¾ã™
</text>
- <text length="1" name="Selling with no objects in parcel." type="string">
+ <text name="Selling with no objects in parcel.">
オブジェクトã¯è²©å£²å¯¾è±¡å¤–ã§ã™
</text>
<button label="土地販売ã®å–り消ã—" label_selected="土地販売ã®å–り消ã—" name="Cancel Land Sale"/>
- <text length="1" name="Claimed:" type="string">
+ <text name="Claimed:">
å–得日時:
</text>
- <text length="1" name="DateClaimText" type="string">
+ <text name="DateClaimText">
2006å¹´8月15æ—¥ç«æ›œæ—¥13:47:25
</text>
- <text length="1" name="PriceLabel" type="string">
+ <text name="PriceLabel">
é¢ç©ï¼š
</text>
- <text length="1" name="PriceText" type="string">
- 4048平方メートル
+ <text name="PriceText">
+ 4048 m²
</text>
- <text length="1" name="Traffic:" type="string">
+ <text name="Traffic:">
交通é‡:
</text>
- <text length="1" name="DwellText" type="string">
+ <text name="DwellText">
誤
</text>
<button label="土地を購入..." label_selected="土地を購入..." left="130" name="Buy Land..." width="125"/>
@@ -79,76 +131,49 @@
<button label="土地を放棄..." label_selected="土地を放棄..." name="Abandon Land..."/>
<button label="土地ã®è¿”é‚„ã‚’è¦æ±‚..." label_selected="土地ã®è¿”é‚„ã‚’è¦æ±‚..." name="Reclaim Land..."/>
<button label="Lindenセール..." label_selected="Lindenセール..." name="Linden Sale..." tool_tip="土地ãŒæ‰€æœ‰ã•ã‚Œã¦ãŠã‚Šã€ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ãŒè¨­å®šã•ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚オークションã®å¯¾è±¡ã«ãªã£ã¦ã„ãªã„ã“ã¨ã‚‚å¿…è¦æ¡ä»¶ã§ã™ã€‚"/>
- <string name="new users only">
- æ–°è¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã¿
- </string>
- <string name="anyone">
- 誰ã§ã‚‚
- </string>
- <string name="area_text">
- é¢ç©ï¼š
- </string>
- <string name="area_size_text">
- [AREA]平方メートル
- </string>
- <string name="auction_id_text">
- オークションID: [ID]
- </string>
- <string name="need_tier_to_modify">
- ã“ã®åœŸåœ°ã‚’修正変更ã™ã‚‹ã«ã¯ã€è³¼å…¥ã‚’承èªã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
- </string>
- <string name="group_owned_text">
- (グループ所有)
- </string>
- <string name="profile_text">
- プロフィール...
- </string>
- <string name="info_text">
- 情報...
- </string>
- <string name="public_text">
- (公共)
- </string>
- <string name="none_text">
- (ãªã—)
- </string>
- <string name="sale_pending_text">
- (購入審査中)
- </string>
- <string name="no_selection_text">
- 区画ãŒé¸å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。
-「世界ã€ãƒ¡ãƒ‹ãƒ¥ãƒ¼ï¼žã€ŒåœŸåœ°æƒ…å ±ã€ã«é€²ã‚€ã‹ã€åˆ¥ã®åŒºç”»ã‚’é¸æŠžã—ã¦ã€è©³ç´°ã‚’表示ã—ã¾ã™ã€‚
- </string>
</panel>
<panel label="約款" name="land_covenant_panel">
+ <panel.string name="can_resell">
+ ã“ã®åœ°åŸŸã§è³¼å…¥ã—ãŸåœŸåœ°ã¯ã€å†è²©ã§ãã¾ã™ã€‚
+ </panel.string>
+ <panel.string name="can_not_resell">
+ ã“ã®åœ°åŸŸã§è³¼å…¥ã—ãŸåœŸåœ°ã¯ã€å†è²©ã§ããªã„ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚
+ </panel.string>
+ <panel.string name="can_change">
+ ã“ã®åœ°åŸŸã§è³¼å…¥ã—ãŸåœŸåœ°ã¯ã€çµ±åˆã¾ãŸã¯å†åˆ†å‰²ã§ãã¾ã™ã€‚
+ </panel.string>
+ <panel.string name="can_not_change">
+ ã“ã®åœ°åŸŸã§è³¼å…¥ã—ãŸåœŸåœ°ã¯ã€çµ±åˆï¼å†åˆ†å‰²ã§ããªã„ã“ã¨ãŒ
+ã‚ã‚Šã¾ã™ã€‚
+ </panel.string>
<text font="SansSerifLarge" name="estate_section_lbl">
ä¸å‹•ç”£ï¼š
</text>
- <text length="1" name="estate_name_lbl" type="string">
+ <text name="estate_name_lbl">
åå‰ï¼š
</text>
- <text length="1" name="estate_name_text" type="string">
+ <text name="estate_name_text">
メインランド
</text>
- <text length="1" name="estate_owner_lbl" type="string">
+ <text name="estate_owner_lbl">
オーナー:
</text>
- <text length="1" name="estate_owner_text" type="string">
+ <text name="estate_owner_text">
(ãªã—)
</text>
- <text_editor length="1" name="covenant_editor" type="string">
+ <text_editor name="covenant_editor">
ã“ã®ä¸å‹•ç”£ã«ã¯ç´„款ãŒã‚ã‚Šã¾ã›ã‚“。
</text_editor>
- <text length="1" name="covenant_timestamp_text" type="string">
+ <text name="covenant_timestamp_text">
最後ã®æ›´æ–°1969å¹´12月31日水曜日16:00:00
</text>
<text font="SansSerifLarge" name="region_section_lbl">
地域:
</text>
- <text length="1" name="region_name_lbl" type="string">
+ <text name="region_name_lbl">
åå‰ï¼š
</text>
- <text length="1" name="region_name_text" type="string">
+ <text name="region_name_text">
Leyla
</text>
<text name="region_landtype_lbl">
@@ -166,300 +191,227 @@
<text name="resellable_lbl">
å†è²©ï¼š
</text>
- <text length="1" name="resellable_clause" type="string">
+ <text name="resellable_clause">
ã“ã®åœ°åŸŸï¼ˆãƒªãƒ¼ã‚¸ãƒ§ãƒ³ï¼‰ã«ã‚る土地ã¯å†è²©ã§ãã¾ã›ã‚“。
</text>
<text name="changeable_lbl">
å†åˆ†å‰²ï¼š
</text>
- <text length="1" name="changeable_clause" type="string">
+ <text name="changeable_clause">
ã“ã®åœ°åŸŸï¼ˆãƒªãƒ¼ã‚¸ãƒ§ãƒ³ï¼‰ã«ã‚る土地ã¯çµ±åˆã¾ãŸã¯åˆ†å‰²ãŒã§ã
ã¾ã›ã‚“。
</text>
- <string name="can_resell">
- ã“ã®åœ°åŸŸã§è³¼å…¥ã—ãŸåœŸåœ°ã¯ã€å†è²©ã§ãã¾ã™ã€‚
- </string>
- <string name="can_not_resell">
- ã“ã®åœ°åŸŸã§è³¼å…¥ã—ãŸåœŸåœ°ã¯ã€å†è²©ã§ããªã„ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚
- </string>
- <string name="can_change">
- ã“ã®åœ°åŸŸã§è³¼å…¥ã—ãŸåœŸåœ°ã¯ã€çµ±åˆã¾ãŸã¯å†åˆ†å‰²ã§ãã¾ã™ã€‚
- </string>
- <string name="can_not_change">
- ã“ã®åœ°åŸŸã§è³¼å…¥ã—ãŸåœŸåœ°ã¯ã€çµ±åˆï¼å†åˆ†å‰²ã§ããªã„ã“ã¨ãŒ
-ã‚ã‚Šã¾ã™ã€‚
- </string>
</panel>
<panel label="オブジェクト" name="land_objects_panel">
+ <panel.string left="200" name="objects_available_text">
+ [MAX]ã®å†…[COUNT]([AVAILABLE]利用å¯èƒ½ï¼‰
+ </panel.string>
+ <panel.string left="200" name="objects_deleted_text">
+ [MAX]ã®å†…[COUNT]([DELETED]を削除)
+ </panel.string>
<text name="parcel_object_bonus">
地域オブジェクトボーナスè¦å› : [BONUS]
</text>
- <text length="1" name="Simulator primitive usage:" type="string" width="500">
+ <text name="Simulator primitive usage:" width="500">
地域全体ã®ãƒ—リム使用状æ³ï¼š
</text>
<text left="200" name="objects_available">
[MAX]ã®å†…[COUNT]([AVAILABLE]利用å¯èƒ½ï¼‰
</text>
- <string left="200" name="objects_available_text">
- [MAX]ã®å†…[COUNT]([AVAILABLE]利用å¯èƒ½ï¼‰
- </string>
- <string left="200" name="objects_deleted_text">
- [MAX]ã®å†…[COUNT]([DELETED]を削除)
- </string>
- <text length="1" name="Primitives parcel supports:" type="string" width="200">
+ <text name="Primitives parcel supports:" width="200">
区画ã§ã‚µãƒãƒ¼ãƒˆã•ã‚Œã‚‹ãƒ—リム数:
</text>
- <text left="200" length="1" name="object_contrib_text" type="string">
+ <text left="200" name="object_contrib_text">
[COUNT]
</text>
- <text length="1" name="Primitives on parcel:" type="string">
+ <text name="Primitives on parcel:">
区画上ã®ãƒ—リム数:
</text>
- <text left="200" length="1" name="total_objects_text" type="string">
+ <text left="200" name="total_objects_text">
[COUNT]
</text>
- <text length="1" name="Owned by parcel owner:" type="string" width="300">
+ <text name="Owned by parcel owner:" width="300">
区画オーナーã«ã‚ˆã‚‹æ‰€æœ‰ï¼š
</text>
- <text left="200" length="1" name="owner_objects_text" type="string">
+ <text left="200" name="owner_objects_text">
[COUNT]
</text>
<button label="表示" label_selected="表示" name="ShowOwner" right="-145"/>
<button label="è¿”å´..." label_selected="è¿”å´..." name="ReturnOwner..." right="-15" tool_tip="オブジェクトをオーナーã«è¿”å´ã—ã¾ã™"/>
- <text length="1" name="Set to group:" type="string">
+ <text name="Set to group:">
グループã«è¨­å®šï¼š
</text>
- <text left="200" length="1" name="group_objects_text" type="string">
+ <text left="200" name="group_objects_text">
[COUNT]
</text>
<button label="表示" label_selected="表示" name="ShowGroup" right="-145"/>
<button label="è¿”å´..." label_selected="è¿”å´..." name="ReturnGroup..." right="-15" tool_tip="オブジェクトをオーナーã«è¿”å´ã—ã¾ã™"/>
- <text length="1" name="Owned by others:" type="string">
+ <text name="Owned by others:">
他人ã«ã‚ˆã‚‹æ‰€æœ‰ï¼š
</text>
- <text left="200" length="1" name="other_objects_text" type="string">
+ <text left="200" name="other_objects_text">
[COUNT]
</text>
<button label="表示" label_selected="表示" name="ShowOther" right="-145"/>
<button label="è¿”å´..." label_selected="è¿”å´..." name="ReturnOther..." right="-15" tool_tip="オブジェクトをオーナーã«è¿”å´ã—ã¾ã™"/>
- <text length="1" name="Selected / sat upon:" type="string">
+ <text name="Selected / sat upon:">
é¸æŠžæ¸ˆã¿ï¼æ±ºå®šæ¸ˆã¿ï¼š
</text>
- <text left="200" length="1" name="selected_objects_text" type="string">
+ <text left="200" name="selected_objects_text">
[COUNT]
</text>
- <text length="1" name="Autoreturn" type="string" width="500">
+ <text name="Autoreturn" width="500">
ä»–ã®ä½äººã®ã‚ªãƒ–ジェクトã®è‡ªå‹•è¿”å´(分ã€0ã§è‡ªå‹•è¿”å´ãªã—)
</text>
<line_editor left_delta="5" name="clean other time" right="-80"/>
- <text length="1" name="Object Owners:" type="string" width="150">
+ <text name="Object Owners:" width="150">
オブジェクトã®ã‚ªãƒ¼ãƒŠãƒ¼ï¼š
</text>
<button label="リスト更新" label_selected="リスト更新" left="146" name="Refresh List"/>
<button label="オブジェクトã®è¿”å´..." label_selected="オブジェクトã®è¿”å´..." left="256" name="Return objects..."/>
<name_list label="カウント" name="owner list">
- <column label="タイプ" name="type"/>
- <column name="online_status"/>
- <column label="åå‰" name="name"/>
- <column label="カウント" name="count"/>
- <column label="最新" name="mostrecent"/>
+ <name_list.columns label="タイプ" name="type"/>
+ <name_list.columns name="online_status"/>
+ <name_list.columns label="åå‰" name="name"/>
+ <name_list.columns label="カウント" name="count"/>
+ <name_list.columns label="最新" name="mostrecent"/>
</name_list>
</panel>
<panel label="オプション" name="land_options_panel">
- <text length="1" name="allow_label" type="string">
+ <panel.string name="search_enabled_tooltip">
+ ã“ã®åŒºç”»ã‚’検索çµæžœã«è¡¨ç¤ºã™ã‚‹
+ </panel.string>
+ <panel.string name="search_disabled_small_tooltip">
+ 区画é¢ç©ãŒ128平方メートルã‹ãれ以下ã®ãŸã‚ã€ã“ã®ã‚ªãƒ—ションã¯ç„¡åŠ¹ã§ã™ã€‚
+大ããªåŒºç”»ã®ã¿æ¤œç´¢ã«è¡¨ç¤ºã•ã›ã‚‹ã“ã¨ãŒå¯èƒ½ã§ã™ã€‚
+ </panel.string>
+ <panel.string name="search_disabled_permissions_tooltip">
+ ã‚ãªãŸã¯ã“ã®åŒºç”»ã®è¨­å®šç·¨é›†ãŒã§ããªã„ãŸã‚ã€ã“ã®ã‚ªãƒ—ションã¯ç„¡åŠ¹ã§ã™ã€‚
+ </panel.string>
+ <panel.string name="mature_check_mature">
+ Matureコンテンツ
+ </panel.string>
+ <panel.string name="mature_check_adult">
+ Adultコンテンツ
+ </panel.string>
+ <panel.string name="mature_check_mature_tooltip">
+ ã‚ãªãŸã®åŒºç”»æƒ…å ±åŠã³ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã¯Matureã¨ã•ã‚Œã¦ã„ã¾ã™ã€‚
+ </panel.string>
+ <panel.string name="mature_check_adult_tooltip">
+ ã‚ãªãŸã®åŒºç”»æƒ…å ±åŠã³ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã¯Adultã¨ã•ã‚Œã¦ã„ã¾ã™ã€‚
+ </panel.string>
+ <panel.string name="landing_point_none">
+ (ãªã—)
+ </panel.string>
+ <panel.string name="push_restrict_text">
+ プッシングを制é™
+ </panel.string>
+ <panel.string name="push_restrict_region_text">
+ ãƒ—ãƒƒã‚·ãƒ³ã‚°ã‚’åˆ¶é™ (地域優先)
+ </panel.string>
+ <text name="allow_label">
ä»–ã®ä½äººã«ä»¥ä¸‹ã‚’許å¯ï¼š
</text>
<check_box label="地形を編集" name="edit land check" tool_tip="ãƒã‚§ãƒƒã‚¯ã‚’入れるã¨ã€ä»–人ãŒã‚ãªãŸã®åœŸåœ°ã®åœ°å½¢ç·¨é›†ã‚’è¡Œã†ã“ã¨ãŒå¯èƒ½ã¨ãªã‚Šã¾ã™ã€‚ã“ã®ã‚ªãƒ—ションã®ãƒã‚§ãƒƒã‚¯ã‚’外ã—ã¦ãŠãã“ã¨ã‚’ãŠã™ã™ã‚ã—ã¾ã™ã€‚外ã—ãŸçŠ¶æ…‹ã§ã‚ãªãŸã®åœŸåœ°ã®åœ°å½¢ç·¨é›†ãŒå¯èƒ½ã§ã™ã€‚"/>
- <check_box label="ランドマーク作æˆ" name="check landmark"/>
<check_box label="飛行" name="check fly" tool_tip="ãƒã‚§ãƒƒã‚¯ã‚’入れるã¨ã“ã®åœŸåœ°ã§ã®é£›è¡ŒãŒå¯èƒ½ã¨ãªã‚Šã¾ã™ã€‚ãƒã‚§ãƒƒã‚¯ã‚’外ã™ã¨åœŸåœ°ã«å…¥ã‚‹éš›ã¨é€šã‚ŠéŽãŽã‚‹ã¨ãã®ã¿é£›è¡Œå¯èƒ½ã¨ãªã‚Šã¾ã™ã€‚"/>
- <text left="138" length="1" name="allow_label2" type="string" width="144">
+ <text left="138" name="allow_label2" width="144">
オブジェクトã®ä½œæˆï¼š
</text>
<check_box label="ã™ã¹ã¦ã®ä½äºº" left="280" name="edit objects check"/>
<check_box label="グループ" left="380" name="edit group objects check"/>
- <text left="138" length="1" name="allow_label3" type="string" width="144">
+ <text left="138" name="allow_label3" width="144">
オブジェクトã®é€²å…¥ï¼š
</text>
<check_box label="ã™ã¹ã¦ã®ä½äºº" left="280" name="all object entry check"/>
<check_box label="グループ" left="380" name="group object entry check"/>
- <text left="138" length="1" name="allow_label4" type="string" width="144">
+ <text left="138" name="allow_label4" width="144">
スクリプトã®å®Ÿè¡Œï¼š
</text>
<check_box label="ã™ã¹ã¦ã®ä½äºº" left="280" name="check other scripts"/>
<check_box label="グループ" left="380" name="check group scripts"/>
- <text length="1" name="land_options_label" type="string">
+ <text name="land_options_label">
土地オプション:
</text>
<check_box label="安全(ダメージãªã—)" name="check safe" tool_tip="ãƒã‚§ãƒƒã‚¯ã‚’入れるã¨ã“ã®åœŸåœ°ã§ã®ãƒ€ãƒ¡ãƒ¼ã‚¸ã‚³ãƒ³ãƒãƒƒãƒˆãŒç„¡åŠ¹ã«ãªã‚Šã€ã€Œå®‰å…¨ã€ã«è¨­å®šã•ã‚Œã¾ã™ã€‚ ãƒã‚§ãƒƒã‚¯ã‚’外ã™ã¨ãƒ€ãƒ¡ãƒ¼ã‚¸ã‚³ãƒ³ãƒãƒƒãƒˆãŒæœ‰åŠ¹ã«ãªã‚Šã¾ã™ã€‚"/>
<check_box label="プッシングを制é™" name="PushRestrictCheck" tool_tip="スクリプトã«ã‚ˆã‚‹ãƒ—ッシングを制é™ã—ã¾ã™ã€‚ ã“ã®ã‚ªãƒ—ションをé¸æŠžã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€ã‚ãªãŸã®åœŸåœ°ã§ã®ç ´å£Šçš„行動を妨ã’ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"/>
<check_box label="検索ã«è¡¨ç¤ºï¼žï¼ˆé€±L$30)以下ã®å ´æ‰€" name="ShowDirectoryCheck" tool_tip="検索çµæžœã§ã“ã®åŒºç”»ã‚’表示ã•ã›ã‚‹"/>
- <string name="search_enabled_tooltip">
- ã“ã®åŒºç”»ã‚’検索çµæžœã«è¡¨ç¤ºã™ã‚‹
- </string>
- <string name="search_disabled_small_tooltip">
- 区画é¢ç©ãŒ128平方メートルã‹ãれ以下ã®ãŸã‚ã€ã“ã®ã‚ªãƒ—ションã¯ç„¡åŠ¹ã§ã™ã€‚
-大ããªåŒºç”»ã®ã¿æ¤œç´¢ã«è¡¨ç¤ºã•ã›ã‚‹ã“ã¨ãŒå¯èƒ½ã§ã™ã€‚
- </string>
- <string name="search_disabled_permissions_tooltip">
- ã‚ãªãŸã¯ã“ã®åŒºç”»ã®è¨­å®šç·¨é›†ãŒã§ããªã„ãŸã‚ã€ã“ã®ã‚ªãƒ—ションã¯ç„¡åŠ¹ã§ã™ã€‚
- </string>
<combo_box name="land category with adult">
- <combo_item name="AnyCategory">
- 全カテゴリ
- </combo_item>
- <combo_item name="LindenLocation">
- Linden所在地
- </combo_item>
- <combo_item name="Adult">
- Adult
- </combo_item>
- <combo_item name="Arts&amp;Culture">
- アートã¨ã‚«ãƒ«ãƒãƒ£ãƒ¼
- </combo_item>
- <combo_item name="Business">
- ビジãƒã‚¹
- </combo_item>
- <combo_item name="Educational">
- 教育的
- </combo_item>
- <combo_item name="Gaming">
- ゲーム
- </combo_item>
- <combo_item name="Hangout">
- ãŸã¾ã‚Šå ´
- </combo_item>
- <combo_item name="NewcomerFriendly">
- æ–°ä½äººã«å¥½æ„çš„
- </combo_item>
- <combo_item name="Parks&amp;Nature">
- 公園ã¨è‡ªç„¶
- </combo_item>
- <combo_item name="Residential">
- ä½å®…用
- </combo_item>
- <combo_item name="Shopping">
- ショッピング
- </combo_item>
- <combo_item name="Other">
- ãã®ä»–
- </combo_item>
+ <combo_box.item label="全カテゴリ" name="item0"/>
+ <combo_box.item label="Linden所在地" name="item1"/>
+ <combo_box.item label="Adult" name="item2"/>
+ <combo_box.item label="アートã¨ã‚«ãƒ«ãƒãƒ£ãƒ¼" name="item3"/>
+ <combo_box.item label="ビジãƒã‚¹" name="item4"/>
+ <combo_box.item label="教育的" name="item5"/>
+ <combo_box.item label="ゲーム" name="item6"/>
+ <combo_box.item label="ãŸã¾ã‚Šå ´" name="item7"/>
+ <combo_box.item label="æ–°ä½äººã«å¥½æ„çš„" name="item8"/>
+ <combo_box.item label="公園ã¨è‡ªç„¶" name="item9"/>
+ <combo_box.item label="ä½å®…用" name="item10"/>
+ <combo_box.item label="ショッピング" name="item11"/>
+ <combo_box.item label="ãã®ä»–" name="item12"/>
</combo_box>
<combo_box name="land category">
- <combo_item name="AnyCategory">
- 全カテゴリー
- </combo_item>
- <combo_item name="LindenLocation">
- Linden所在地
- </combo_item>
- <combo_item name="Arts&amp;Culture">
- アート&amp;カルãƒãƒ£ãƒ¼
- </combo_item>
- <combo_item name="Business">
- ビジãƒã‚¹
- </combo_item>
- <combo_item name="Educational">
- 教育的
- </combo_item>
- <combo_item name="Gaming">
- ゲーム
- </combo_item>
- <combo_item name="Hangout">
- ãŸã¾ã‚Šå ´
- </combo_item>
- <combo_item name="NewcomerFriendly">
- æ–°ä½äººã«å¥½æ„çš„
- </combo_item>
- <combo_item name="Parks&amp;Nature">
- 公園ã¨è‡ªç„¶
- </combo_item>
- <combo_item name="Residential">
- ä½å®…用
- </combo_item>
- <combo_item name="Shopping">
- ショッピング
- </combo_item>
- <combo_item name="Other">
- ãã®ä»–
- </combo_item>
+ <combo_box.item label="全カテゴリー" name="item0"/>
+ <combo_box.item label="Linden所在地" name="item1"/>
+ <combo_box.item label="アート&amp;カルãƒãƒ£ãƒ¼" name="item3"/>
+ <combo_box.item label="ビジãƒã‚¹" name="item4"/>
+ <combo_box.item label="教育的" name="item5"/>
+ <combo_box.item label="ゲーム" name="item6"/>
+ <combo_box.item label="ãŸã¾ã‚Šå ´" name="item7"/>
+ <combo_box.item label="æ–°ä½äººã«å¥½æ„çš„" name="item8"/>
+ <combo_box.item label="公園ã¨è‡ªç„¶" name="item9"/>
+ <combo_box.item label="ä½å®…用" name="item10"/>
+ <combo_box.item label="ショッピング" name="item11"/>
+ <combo_box.item label="ãã®ä»–" name="item12"/>
</combo_box>
- <button label="?" label_selected="?" name="?"/>
<check_box label="Matureコンテンツ" name="MatureCheck" tool_tip=""/>
- <string name="mature_check_mature">
- Matureコンテンツ
- </string>
- <string name="mature_check_adult">
- Adultコンテンツ
- </string>
- <string name="mature_check_mature_tooltip">
- ã‚ãªãŸã®åŒºç”»æƒ…å ±åŠã³ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã¯Matureã¨ã•ã‚Œã¦ã„ã¾ã™ã€‚
- </string>
- <string name="mature_check_adult_tooltip">
- ã‚ãªãŸã®åŒºç”»æƒ…å ±åŠã³ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã¯Adultã¨ã•ã‚Œã¦ã„ã¾ã™ã€‚
- </string>
- <text length="1" name="Snapshot:" type="string">
+ <text name="Snapshot:">
スナップショット:
</text>
<texture_picker label="" left="116" name="snapshot_ctrl" tool_tip="写真をクリックã—ã¦é¸æŠž"/>
<text name="landing_point">
ç€åœ°ç‚¹: [LANDING]
</text>
- <string name="landing_point_none">
- (ãªã—)
- </string>
<button label="設定" label_selected="設定" name="Set" tool_tip="訪å•è€…ã®ç€åœ°ç‚¹ã®è¨­å®šã‚’è¡Œã„ã¾ã™ã€‚ã“ã®åŒºç”»å†…ã«ç«‹ã£ã¦è¡Œã£ã¦ãã ã•ã„。"/>
- <button label="クリア" label_selected="クリア" name="Clear" tool_tip="ç€åœ°ç‚¹ã‚’クリアã—ã¦ãã ã•ã„。"/>
- <text length="1" name="Teleport Routing: " type="string">
+ <button label="クリア" label_selected="クリア" name="Clear" tool_tip="ç€åœ°ç‚¹ã‚’クリア"/>
+ <text name="Teleport Routing: ">
テレãƒãƒ¼ãƒˆåˆ¶é™ï¼š
</text>
- <combo_box name="landing type" tool_tip="Teleport Routing -- select how to handle teleports onto your land.">
- <combo_item length="1" name="Blocked" type="string">
- ä¸å¯
- </combo_item>
- <combo_item length="1" name="LandingPoint" type="string">
- ç€åœ°ç‚¹
- </combo_item>
- <combo_item length="1" name="Anywhere" type="string">
- ã©ã“ã§ã‚‚
- </combo_item>
+ <combo_box name="landing type" tool_tip="テレãƒãƒ¼ãƒˆçµŒè·¯ -- ã‚ãªãŸã®åœŸåœ°ã¸ã®ãƒ†ãƒ¬ãƒãƒ¼ãƒˆçµŒè·¯ã‚’é¸æŠž">
+ <combo_box.item label="ä¸å¯" name="Blocked"/>
+ <combo_box.item label="ç€åœ°ç‚¹" name="LandingPoint"/>
+ <combo_box.item label="ã©ã“ã§ã‚‚" name="Anywhere"/>
</combo_box>
- <string name="push_restrict_text">
- プッシングを制é™
- </string>
- <string name="push_restrict_region_text">
- ãƒ—ãƒƒã‚·ãƒ³ã‚°ã‚’åˆ¶é™ (地域優先)
- </string>
</panel>
<panel label="メディア" name="land_media_panel">
<text name="with media:">
- タイプ:
+ 種類:
</text>
<combo_box name="media type" tool_tip="URL ãŒå‹•ç”»ã€ã‚¦ã‚§ãƒ–・ページã€ãã®ä»–ã®ãƒ¡ãƒ‡ã‚£ã‚¢ã®å ´åˆã«æŒ‡å®šã—ã¾ã™"/>
<text name="at URL:">
- URL:
+ ホーム URL:
</text>
<button label="設定..." label_selected="設定..." name="set_media_url"/>
+ <text name="CurrentURL:">
+ ç¾åœ¨ã® URL:
+ </text>
+ <button label="リセット..." label_selected="リセット..." name="reset_media_url"/>
+ <check_box label="URL ã‚’éžè¡¨ç¤º" name="hide_media_url" tool_tip="ã“ã®ã‚ªãƒ—ションをオンã«ã™ã‚‹ã¨ã€è¨±å¯ãªã—ã§ã“ã®åŒºç”»æƒ…å ±ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã„るユーザーã«ã¯ãƒ¡ãƒ‡ã‚£ã‚¢ URL ãŒè¡¨ç¤ºã•ã‚Œã¾ã›ã‚“。 ã“れ㯠HTML タイプã«ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“ã®ã§ã”注æ„ãã ã•ã„。"/>
<text name="Description:">
説明:
</text>
<line_editor name="url_description" tool_tip="ï¼»å†ç”Ÿï¼½/[ロード]ボタンã®éš£ã«è¡¨ç¤ºã•ã‚Œã‚‹ãƒ†ã‚­ã‚¹ãƒˆ"/>
- <text length="1" name="Media texture:" type="string">
+ <text name="Media texture:">
テクスãƒ
ャå–替:
</text>
<texture_picker label="" name="media texture" tool_tip="写真をクリックã—ã¦é¸æŠž"/>
<text name="replace_texture_help" width="290">
- 「å†ç”Ÿã€çŸ¢å°ã‚’クリックã™ã‚‹ã¨ã€ã“ã®ãƒ†ã‚¯ã‚¹ãƒãƒ£ãƒ¼ã‚’
- 使用ã™ã‚‹ã‚ªãƒ–ジェクトã«å‹•ç”»ã¾ãŸã¯ã‚¦ã‚§ãƒ–・ページ
- ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
- </text>
- <text name="Options:">
- メディア
-オプション:
+ ã“ã®ãƒ†ã‚¯ã‚¹ãƒãƒ£ã‚’使用ã™ã‚‹ã‚ªãƒ–ジェクトã®ãƒ—レイをクリックã™ã‚‹ã¨ã€ãƒ ãƒ¼ãƒ“ーや Web ページを表示ã—ã¾ã™ã€‚
+
+テクスãƒãƒ£ã‚’変更ã™ã‚‹ã«ã¯ã‚µãƒ ãƒã‚¤ãƒ«ã‚’é¸æŠžã—ã¦ãã ã•ã„。
</text>
<check_box label="スケールを自動設定" name="media_auto_scale" tool_tip="ã“ã®ã‚ªãƒ—ションをãƒã‚§ãƒƒã‚¯ã™ã‚‹ã¨ã€ã“ã®åŒºç”»ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã®ã‚¹ã‚±ãƒ¼ãƒ«ãŒè‡ªå‹•çš„ã«è¨­å®šã•ã‚Œã¾ã™ã€‚ 動作速度ã¨ç”»è³ªãŒå°‘ã—低下ã™ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ãŒã€ä»–ã®ãƒ†ã‚¯ã‚¹ãƒãƒ£ãƒ¼ã®ã‚¹ã‚±ãƒ¼ãƒªãƒ³ã‚°ã‚„整列ãŒå¿…è¦ã«ãªã‚‹ã“ã¨ã¯ã‚ã‚Šã¾ã›ã‚“。"/>
- <check_box label="メディアã®ãƒ«ãƒ¼ãƒ—" name="media_loop" tool_tip="メディアをループå†ç”Ÿã—ã¾ã™ã€‚ メディアã®å†ç”ŸãŒçµ‚ã‚ã£ãŸã‚‰ã€æœ€åˆã‹ã‚‰å†ç”Ÿã—ç›´ã—ã¾ã™ã€‚"/>
- <check_box label="メディア URL ã‚’éš ã™" name="hide_media_url" tool_tip="ã“ã®ã‚ªãƒ—ションをオンã«ã™ã‚‹ã¨ã€è¨±å¯ãªã—ã§ã“ã®åŒºç”»æƒ…å ±ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã„るユーザーã«ã¯ãƒ¡ãƒ‡ã‚£ã‚¢ URL ãŒè¡¨ç¤ºã•ã‚Œã¾ã›ã‚“。 ã“れ㯠HTML タイプã«ã¯ä½¿ç”¨ã§ãã¾ã›ã‚“ã®ã§ã”注æ„ãã ã•ã„。"/>
- <check_box label="音楽ã®URLã‚’éš ã™" name="hide_music_url" tool_tip="ã“ã®ã‚ªãƒ—ションをオンã«ã™ã‚‹ã¨ã€è¨±å¯ãªã—ã§ã“ã®åŒºç”»æƒ…å ±ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã„るユーザーã«ã¯éŸ³æ¥½ã® URL ãŒè¡¨ç¤ºã•ã‚Œã¾ã›ã‚“。"/>
<text name="media_size" tool_tip="レンダリングã™ã‚‹ã‚¦ã‚§ãƒ–・メディアã®ã‚µã‚¤ã‚ºã€‚デフォルト㮠0 ã®ã¾ã¾ã«ã—ã¾ã™ã€‚">
サイズ:
</text>
@@ -468,23 +420,31 @@
<text name="pixels">
ピクセル
</text>
+ <text name="Options:">
+ オプション:
+ </text>
+ <check_box label="ループ" name="media_loop" tool_tip="メディアをループå†ç”Ÿã—ã¾ã™ã€‚ メディアã®å†ç”ŸãŒçµ‚ã‚ã£ãŸã‚‰ã€æœ€åˆã‹ã‚‰å†ç”Ÿã—ç›´ã—ã¾ã™ã€‚"/>
+ </panel>
+ <panel label="オーディオ" name="land_audio_panel">
<text name="MusicURL:">
- 音楽ã®URL:
+ 音楽 URL:
</text>
<text name="Sound:">
サウンド:
</text>
<check_box label="ジェスãƒãƒ£ãƒ¼ã¨ã‚ªãƒ–ジェクトã®éŸ³ã‚’ã“ã®åŒºç”»ã ã‘ã«é™å®š" name="check sound local"/>
- <button label="?" label_selected="?" left="408" name="?"/>
<text name="Voice settings:">
ボイス:
</text>
<check_box label="ボイスを有効ã«ã™ã‚‹" name="parcel_enable_voice_channel"/>
<check_box label="ボイスを有効ã«ã™ã‚‹ï¼ˆä¸å‹•ç”£è¨­å®šï¼‰" name="parcel_enable_voice_channel_is_estate_disabled"/>
- <check_box label="ã“ã®åŒºç”»ã§ã®ãƒœã‚¤ã‚¹ä½¿ç”¨ã‚’制é™ã™ã‚‹" name="parcel_enable_voice_channel_parcel"/>
+ <check_box label="ã“ã®åŒºç”»ã§ã®ãƒœã‚¤ã‚¹ä½¿ç”¨ã‚’制é™" name="parcel_enable_voice_channel_parcel"/>
</panel>
<panel label="アクセス" name="land_access_panel">
- <text length="1" name="Limit access to this parcel to:" type="string">
+ <panel.string name="estate_override">
+ 1ã¤ä»¥ä¸Šã®ã‚ªãƒ—ションãŒã€ä¸å‹•ç”£ãƒ¬ãƒ™ãƒ«ã§è¨­å®šã•ã‚Œã¦ã„ã¾ã™ã€‚
+ </panel.string>
+ <text name="Limit access to this parcel to:">
ã“ã®åŒºç”»ã«ã‚¢ã‚¯ã‚»ã‚¹
</text>
<check_box label="パブリック・アクセスを許å¯" name="public_access"/>
@@ -492,19 +452,12 @@
次ã®ä½äººã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’ブロック:
</text>
<check_box label="Linden Labã«æ”¯æ‰•ã„情報を登録ã—ã¦ã„ãªã„ä½äºº" name="limit_payment" tool_tip="支払ã„情報未確èªã®ä½äººã‚’排除ã™ã‚‹"/>
- <check_box label="年齢確èªã‚’済ã¾ã›ã¦ã„ãªã„æˆäººã®ä½äºº" name="limit_age_verified" tool_tip="年齢確èªã‚’済ã¾ã›ã¦ã„ãªã„ä½äººã‚’排除ã™ã‚‹è©³ç´°ã«ã¤ã„ã¦ã¯ã€support.secondlife.comã‚’å‚ç…§ã—ã¦ãã ã•ã„。"/>
- <string name="estate_override">
- 1ã¤ä»¥ä¸Šã®ã‚ªãƒ—ションãŒã€ä¸å‹•ç”£ãƒ¬ãƒ™ãƒ«ã§è¨­å®šã•ã‚Œã¦ã„ã¾ã™ã€‚
- </string>
+ <check_box label="年齢確èªã‚’済ã¾ã›ã¦ã„ãªã„æˆäººã®ä½äºº" name="limit_age_verified" tool_tip="年齢確èªã‚’済ã¾ã›ã¦ã„ãªã„ä½äººã‚’ç«‹å…¥ç¦æ­¢ã«ã—ã¾ã™ã€‚ 詳ã—ã„情報㯠[SUPPORT_SITE] ã‚’ã”覧下ã•ã„。"/>
<check_box label="グループ・アクセスを許å¯ï¼š[GROUP]" name="GroupCheck" tool_tip="[一般]タブã§ã€ã‚°ãƒ«ãƒ¼ãƒ—ã‚’é¸æŠžã—ã¦ãã ã•ã„。"/>
<check_box label="入場許å¯ã‚’販売:" name="PassCheck" tool_tip="ã“ã®åŒºç”»ã¸ã®ä¸€æ™‚çš„ãªã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯"/>
<combo_box name="pass_combo">
- <combo_item name="Anyone">
- 誰ã§ã‚‚
- </combo_item>
- <combo_item name="Group">
- グループ
- </combo_item>
+ <combo_box.item label="誰ã§ã‚‚" name="Anyone"/>
+ <combo_box.item label="グループ" name="Group"/>
</combo_box>
<spinner label="価格(L$):" name="PriceSpin"/>
<spinner label="アクセス時間:" name="HoursSpin"/>
diff --git a/indra/newview/skins/default/xui/ja/floater_activeim.xml b/indra/newview/skins/default/xui/ja/floater_activeim.xml
new file mode 100644
index 0000000000..1c743e1fd2
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_activeim.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_activeim" title="アクティブ㪠IM"/>
diff --git a/indra/newview/skins/default/xui/ja/floater_animation_preview.xml b/indra/newview/skins/default/xui/ja/floater_animation_preview.xml
index 27a07e633b..9ec4bfc4e7 100644
--- a/indra/newview/skins/default/xui/ja/floater_animation_preview.xml
+++ b/indra/newview/skins/default/xui/ja/floater_animation_preview.xml
@@ -1,175 +1,183 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Animation Preview" title="">
+ <floater.string name="failed_to_initialize">
+ モーションをåˆæœŸåŒ–ã§ãã¾ã›ã‚“ã§ã—ãŸ
+ </floater.string>
+ <floater.string name="anim_too_long">
+ アニメーションファイルã®é•·ã•ã¯[LENGTH]秒ã§ã™ã€‚
+
+アニメーションã®æœ€å¤§ã®é•·ã•ã¯[MAX_LENGTH]秒ã§ã™ã€‚
+ </floater.string>
+ <floater.string name="failed_file_read">
+ アニメーションファイルを読ã¿å–ã‚Œã¾ã›ã‚“。
+
+[STATUS]
+ </floater.string>
+ <floater.string name="E_ST_OK">
+ Ok
+ </floater.string>
+ <floater.string name="E_ST_EOF">
+ ä¸å®Œå…¨ãªãƒ•ã‚¡ã‚¤ãƒ«ã€‚
+ </floater.string>
+ <floater.string name="E_ST_NO_CONSTRAINT">
+ 制約定義を読ã¿ã¨ã‚Œã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_FILE">
+ BVH ファイルを開ã‘ã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_HIER">
+ 無効㪠HIERARCHY ヘッダーã§ã™ã€‚.
+ </floater.string>
+ <floater.string name="E_ST_NO_JOINT">
+ ROOT ã¾ãŸã¯ JOINT ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_NAME">
+ JOINT ãƒãƒ¼ãƒ ã‚’å–å¾—ã§ãã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_OFFSET">
+ OFFSET ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_CHANNELS">
+ CHANNELS ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_ROTATION">
+ 回転順åºã‚’å–å¾—ã§ãã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_AXIS">
+ 回転軸をå–å¾—ã§ãã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_MOTION">
+ MOTION ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_FRAMES">
+ フレーム数をå–å¾—ã§ãã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_FRAME_TIME">
+ フレームタイムをå–å¾—ã§ãã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_POS">
+ ãƒã‚¸ã‚·ãƒ§ãƒ³å€¤ã‚’å–å¾—ã§ãã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_ROT">
+ 回転値をå–å¾—ã§ãã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_FILE">
+ ファイルを開ã‘ã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_HEADER">
+ 読ã¿ã¨ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_NAME">
+ 読ã¿ã¨ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_IGNORE">
+ 読ã¿ã¨ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_RELATIVE">
+ 読ã¿ã¨ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_OUTNAME">
+ 読ã¿ã¨ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_MATRIX">
+ 読ã¿ã¨ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_MERGECHILD">
+ Mergechild åã‚’å–å¾—ã§ãã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_MERGEPARENT">
+ Mergeparent åã‚’å–å¾—ã§ãã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_PRIORITY">
+ プロパティ値をå–å¾—ã§ãã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_LOOP">
+ ループ値をå–å¾—ã§ãã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_EASEIN">
+ easeln 値をå–å¾—ã§ãã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_EASEOUT">
+ easeOut 値をå–å¾—ã§ãã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_HAND">
+ Hand morph 値をå–å¾—ã§ãã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="E_ST_NO_XLT_EMOTE">
+ エモートåを読ã¿ã¨ã‚Œã¾ã›ã‚“。
+ </floater.string>
<text name="name_label">
åå‰ï¼š
</text>
<text name="description_label">
説明:
</text>
- <spinner label="優先順ä½" name="priority"
- tool_tip="ã“ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã§ä¸Šæ›¸ãå¯èƒ½ãªä»–ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’制御ã—ã¾ã™ã€‚" />
- <text name="preview_label">
- åŒæ™‚進行行動
- </text>
- <combo_box label="" name="preview_base_anim"
- tool_tip="ã‚¢ãƒã‚¿ãƒ¼ãŒæ™®é€šã®è¡Œå‹•ã‚’ã™ã‚‹ã¨ãã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã®å‹•ãをテストã™ã‚‹ãŸã‚ã«ã“れを使ã„ã¾ã™ã€‚">
- <combo_item name="Standing">
- ç«‹ã¤
- </combo_item>
- <combo_item name="Walking">
- æ­©ã
- </combo_item>
- <combo_item name="Sitting">
- 座る
- </combo_item>
- <combo_item name="Flying">
- 飛行
- </combo_item>
- </combo_box>
- <pad height="7" />
- <check_box label="ループ" name="loop_check"
- tool_tip="ã“ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’ループå†ç”Ÿã—ã¾ã™ã€‚" />
- <spinner label="イン(%)" name="loop_in_point"
- tool_tip="アニメーションã®ãƒ«ãƒ¼ãƒ—復帰点を設定ã—ã¾ã™ã€‚" label_width="45" left="70" width="100" />
- <spinner label="アウト(%)" name="loop_out_point"
- tool_tip="アニメーションã®ãƒ«ãƒ¼ãƒ—終了点を設定ã—ã¾ã™ã€‚" label_width="60" left="170" width="100" />
+ <spinner label="優先順ä½" name="priority" tool_tip="ã“ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ãŒã©ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’上書ãã™ã‚‹ã‹ã‚’決ã‚ã¾ã™"/>
+ <check_box label="ループ" name="loop_check" tool_tip="ã“ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’ループå†ç”Ÿã—ã¾ã™"/>
+ <spinner label="イン(ï¼…)" label_width="45" left="70" name="loop_in_point" tool_tip="アニメーションã®ãƒ«ãƒ¼ãƒ—復帰点を設定ã—ã¾ã™" width="100"/>
+ <spinner label="アウト(ï¼…)" label_width="60" left="170" name="loop_out_point" tool_tip="アニメーションã®ãƒ«ãƒ¼ãƒ—終了点を設定ã—ã¾ã™" width="100"/>
<text name="hand_label">
手ã®å‹•ã
</text>
- <combo_box label="" name="hand_pose_combo"
- tool_tip="アニメーションã®æ‰‹ã®å‹•ãをコントロールã—ã¾ã™ã€‚">
- <combo_item name="Spread">
- 広ãŒã‚‹
- </combo_item>
- <combo_item name="Relaxed">
- リラックス
- </combo_item>
- <combo_item name="PointBoth">
- 両方を指ã™
- </combo_item>
- <combo_item name="Fist">
- 拳
- </combo_item>
- <combo_item name="RelaxedLeft">
- リラックス左
- </combo_item>
- <combo_item name="PointLeft">
- 左を指ã™
- </combo_item>
- <combo_item name="FistLeft">
- 拳左
- </combo_item>
- <combo_item name="RelaxedRight">
- リラックスå³
- </combo_item>
- <combo_item name="PointRight">
- å³ã‚’指ã™
- </combo_item>
- <combo_item name="FistRight">
- 拳å³
- </combo_item>
- <combo_item name="SaluteRight">
- 敬礼å³
- </combo_item>
- <combo_item name="Typing">
- 入力ã™ã‚‹
- </combo_item>
- <combo_item name="PeaceRight">
- ピース・サインå³
- </combo_item>
+ <combo_box label="" name="hand_pose_combo" tool_tip="アニメーションå†ç”Ÿä¸­ã®æ‰‹ã®å‹•ãを決ã‚ã¾ã™">
+ <combo_box.item label="広ã’ã‚‹" name="Spread"/>
+ <combo_box.item label="リラックス" name="Relaxed"/>
+ <combo_box.item label="指を指ã™ãƒ»ä¸¡æ‰‹" name="PointBoth"/>
+ <combo_box.item label="拳" name="Fist"/>
+ <combo_box.item label="リラックス・左" name="RelaxedLeft"/>
+ <combo_box.item label="指を指ã™ãƒ»å·¦" name="PointLeft"/>
+ <combo_box.item label="拳を上ã’る・左" name="FistLeft"/>
+ <combo_box.item label="リラックス・å³" name="RelaxedRight"/>
+ <combo_box.item label="指を指ã™ãƒ»å³" name="PointRight"/>
+ <combo_box.item label="拳を上ã’る・å³" name="FistRight"/>
+ <combo_box.item label="敬礼・å³" name="SaluteRight"/>
+ <combo_box.item label="タイピング" name="Typing"/>
+ <combo_box.item label="ピース・å³" name="PeaceRight"/>
</combo_box>
<text name="emote_label">
表ç¾
</text>
- <combo_box label="" name="emote_combo"
- tool_tip="アニメーションã®é¡”を表情をコントロールã—ã¾ã™ã€‚">
- <combo_item name="[None]">
- [None]
- </combo_item>
- <combo_item name="Aaaaah">
- アーーーーー
- </combo_item>
- <combo_item name="Afraid">
- 怖れ
- </combo_item>
- <combo_item name="Angry">
- 怒り
- </combo_item>
- <combo_item name="BigSmile">
- 満é¢ã®ç¬‘ã¿
- </combo_item>
- <combo_item name="Bored">
- 退屈
- </combo_item>
- <combo_item name="Cry">
- æ³£ã
- </combo_item>
- <combo_item name="Disdain">
- 侮蔑
- </combo_item>
- <combo_item name="Embarrassed">
- 困惑
- </combo_item>
- <combo_item name="Frown">
- ã—ã‹ã‚ã£é¢
- </combo_item>
- <combo_item name="Kiss">
- キス
- </combo_item>
- <combo_item name="Laugh">
- 笑ã†
- </combo_item>
- <combo_item name="Plllppt">
- Plllppt
- </combo_item>
- <combo_item name="Repulsed">
- 嫌悪感
- </combo_item>
- <combo_item name="Sad">
- 悲ã—ã„
- </combo_item>
- <combo_item name="Shrug">
- è‚©ã‚’ã™ãã‚ã‚‹
- </combo_item>
- <combo_item name="Smile">
- 笑ã¿
- </combo_item>
- <combo_item name="Surprise">
- é©šã
- </combo_item>
- <combo_item name="Wink">
- ウィンク
- </combo_item>
- <combo_item name="Worry">
- 心é…
- </combo_item>
+ <combo_box label="" name="emote_combo" tool_tip="アニメーションå†ç”Ÿä¸­ã®é¡”ã®è¡¨æƒ…を決ã‚ã¾ã™">
+ <combo_box.item label="(ãªã—)" name="[None]"/>
+ <combo_box.item label="アーーーーー" name="Aaaaah"/>
+ <combo_box.item label="æれる" name="Afraid"/>
+ <combo_box.item label="怒る" name="Angry"/>
+ <combo_box.item label="満é¢ã®ç¬‘ã¿" name="BigSmile"/>
+ <combo_box.item label="退屈" name="Bored"/>
+ <combo_box.item label="æ³£ã" name="Cry"/>
+ <combo_box.item label="侮辱" name="Disdain"/>
+ <combo_box.item label="æ¥ãšã‹ã—ãŒã‚‹" name="Embarrassed"/>
+ <combo_box.item label="ã—ã‹ã‚ã£é¢" name="Frown"/>
+ <combo_box.item label="キス" name="Kiss"/>
+ <combo_box.item label="笑ã†" name="Laugh"/>
+ <combo_box.item label="Plllppt" name="Plllppt"/>
+ <combo_box.item label="嫌悪感" name="Repulsed"/>
+ <combo_box.item label="悲ã—ã„" name="Sad"/>
+ <combo_box.item label="è‚©ã‚’ã™ãã‚ã‚‹" name="Shrug"/>
+ <combo_box.item label="微笑む" name="Smile"/>
+ <combo_box.item label="é©šã" name="Surprise"/>
+ <combo_box.item label="ウィンク" name="Wink"/>
+ <combo_box.item label="心é…ã™ã‚‹" name="Worry"/>
</combo_box>
- <spinner label="フェーズイï¾(秒)" name="ease_in_time"
- tool_tip="アニメーションã®ãƒ–レンド・イン時間(秒)" />
- <spinner label="フェーズアウト(秒)" name="ease_out_time"
- tool_tip="アニメーションã®ãƒ–レンド・アウト時間(秒)" />
- <button label="" name="play_btn"
- tool_tip="アニメーションã®å†ç”Ÿï¼ä¸€æ™‚åœæ­¢" />
- <button label="" name="stop_btn" tool_tip="アニメーションã®å†ç”Ÿã‚’åœæ­¢" />
- <slider label="" name="playback_slider" />
+ <text name="preview_label">
+ åŒæ™‚進行行動
+ </text>
+ <combo_box label="" name="preview_base_anim" tool_tip="ã‚¢ãƒã‚¿ãƒ¼ãŒæ™®é€šã®è¡Œå‹•ã‚’ã™ã‚‹ã¨ãã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã®å‹•ãをテストã™ã‚‹ãŸã‚ã«ã“れを使ã„ã¾ã™ã€‚">
+ <combo_box.item label="ç«‹ã¤" name="Standing"/>
+ <combo_box.item label="æ­©ã" name="Walking"/>
+ <combo_box.item label="座る" name="Sitting"/>
+ <combo_box.item label="飛ã¶" name="Flying"/>
+ </combo_box>
+ <spinner label="フェーズイï¾(秒)" name="ease_in_time" tool_tip="アニメーションã®ãƒ–レンドイン時間(秒)"/>
+ <spinner label="フェーズアウト(秒)" name="ease_out_time" tool_tip="アニメーションã®ãƒ–レンドアウト時間(秒)"/>
+ <button label="" name="play_btn" tool_tip="アニメーションã®å†ç”Ÿãƒ»ä¸€æ™‚åœæ­¢"/>
+ <button label="" name="stop_btn" tool_tip="アニメーションã®å†ç”Ÿã‚’åœæ­¢"/>
+ <slider label="" name="playback_slider"/>
<text name="bad_animation_text">
アニメーション・ファイルを読ã¿è¾¼ã‚ã¾ã›ã‚“。
Poser 4ã‹ã‚‰ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã•ã‚ŒãŸBVHファイルを推奨ã—ã¾ã™ã€‚
</text>
- <button label="å–り消ã—" name="cancel_btn" />
- <button label="アップロードL$[AMOUNT]" name="ok_btn" />
- <text name="failed_to_initialize">
- モーションをåˆæœŸåŒ–ã§ãã¾ã›ã‚“ã§ã—ãŸ
- </text>
- <text name="anim_too_long">
- アニメーションファイルã®é•·ã•ã¯[LENGTH]秒ã§ã™ã€‚
-
-アニメーションã®æœ€å¤§ã®é•·ã•ã¯[MAX_LENGTH]秒ã§ã™ã€‚
- </text>
- <text name="failed_file_read">
- アニメーションファイルを読ã¿å–ã‚Œã¾ã›ã‚“。
-
-[STATUS]
- </text>
+ <button label="å–り消ã—" name="cancel_btn"/>
+ <button label="アップロードL$[AMOUNT]" name="ok_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_auction.xml b/indra/newview/skins/default/xui/ja/floater_auction.xml
index ba34ec488d..e9aa287f2c 100644
--- a/indra/newview/skins/default/xui/ja/floater_auction.xml
+++ b/indra/newview/skins/default/xui/ja/floater_auction.xml
@@ -1,10 +1,11 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_auction" title="リンデンã®åœŸåœ°å£²è²·é–‹å§‹">
- <check_box label="黄色ã®é¸æŠžãƒ•ã‚§ãƒ³ã‚¹ã‚’å«ã‚ã‚‹" name="fence_check" />
- <button label="スナップショット" label_selected="スナップショット"
- name="snapshot_btn" />
- <button label="OK" label_selected="OK" name="ok_btn" />
- <text name="already for sale">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_auction" title="リンデンランドã®è²©å£²é–‹å§‹">
+ <floater.string name="already for sale">
売り出ã—中ã®åŒºç”»ã¯ã€ã‚ªãƒ¼ã‚¯ã‚·ãƒ§ãƒ³ã«å‡ºå“ã§ãã¾ã›ã‚“。
- </text>
+ </floater.string>
+ <check_box initial_value="true" label="黄色ã®é¸æŠžãƒ•ã‚§ãƒ³ã‚¹ã‚’å«ã‚ã‚‹" name="fence_check"/>
+ <button label="スナップショット" label_selected="スナップショット" name="snapshot_btn"/>
+ <button label="誰ã«ã§ã‚‚販売" label_selected="誰ã«ã§ã‚‚販売" name="sell_to_anyone_btn"/>
+ <button label="設定をクリア" label_selected="設定をクリア" name="reset_parcel_btn"/>
+ <button label="オークション開始" label_selected="オークション開始" name="start_auction_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_avatar_picker.xml b/indra/newview/skins/default/xui/ja/floater_avatar_picker.xml
index ea07684652..7f965e490d 100644
--- a/indra/newview/skins/default/xui/ja/floater_avatar_picker.xml
+++ b/indra/newview/skins/default/xui/ja/floater_avatar_picker.xml
@@ -1,40 +1,46 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="avatarpicker" title="ä½äººã‚’é¸æŠž" min_width="275" width="275">
+<floater min_width="275" name="avatarpicker" title="ä½äººã‚’é¸æŠž" width="275">
+ <floater.string name="not_found">
+ 「[TEXT]ã€ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ
+ </floater.string>
+ <floater.string name="no_one_near">
+ è¿‘ãã«èª°ã‚‚ã„ã¾ã›ã‚“
+ </floater.string>
+ <floater.string name="no_results">
+ 検索çµæžœï¼šã‚¼ãƒ­
+ </floater.string>
+ <floater.string name="searching">
+ 検索中...
+ </floater.string>
+ <string label="OK" label_selected="OK" name="Select">
+ é¸æŠž
+ </string>
+ <string name="Close">
+ é–‰ã˜ã‚‹
+ </string>
<tab_container name="ResidentChooserTabs" width="265">
<panel label="検索" name="SearchPanel" width="145">
<text name="InstructSearchResidentName">
- ä½äººã®åå‰ã®ä¸€éƒ¨ã‚’入力:
+ åå‰ã®ä¸€éƒ¨ã‚’入力:
</text>
<button label="検索" label_selected="検索" name="Find"/>
</panel>
- <panel label="コーリングカード" name="CallingCardsPanel" width="145">
- <text name="InstructSelectCallingCard">
- コーリングカードをé¸æŠžï¼š
+ <panel label="フレンド" name="FriendsPanel">
+ <text name="InstructSelectFriend">
+ ã‚¢ãƒã‚¿ãƒ¼ã‚’é¸æŠžï¼š
</text>
</panel>
<panel label="自分ã®è¿‘ã" name="NearMePanel" width="145">
<text name="InstructSelectResident">
- è¿‘ãã®ä½äººã‚’é¸æŠžï¼š
+ è¿‘ãã®äººã‚’é¸æŠžï¼š
</text>
- <button label="リスト更新" label_selected="リスト更新" name="Refresh"/>
<slider label="範囲" name="near_me_range"/>
<text name="meters" width="50">
メートル
</text>
+ <button label="リスト更新" label_selected="リスト更新" name="Refresh"/>
</panel>
</tab_container>
- <button label="é¸æŠž" label_selected="é¸æŠž" name="Select"/>
- <button label="å–り消ã—" label_selected="å–り消ã—" name="Cancel"/>
- <string name="not_found">
- 「[TEXT]ã€ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ
- </string>
- <string name="no_one_near">
- è¿‘ãã«èª°ã‚‚ã„ã¾ã›ã‚“
- </string>
- <string name="no_results">
- 検索çµæžœï¼šã‚¼ãƒ­
- </string>
- <string name="searching">
- 検索中...
- </string>
+ <button label="OK" label_selected="OK" name="ok_btn"/>
+ <button label="キャンセル" label_selected="キャンセル" name="cancel_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_avatar_textures.xml b/indra/newview/skins/default/xui/ja/floater_avatar_textures.xml
index 95940dba96..4a20c58181 100644
--- a/indra/newview/skins/default/xui/ja/floater_avatar_textures.xml
+++ b/indra/newview/skins/default/xui/ja/floater_avatar_textures.xml
@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="avatar_texture_debug" title="ã‚¢ãƒã‚¿ãƒ¼ãƒ»ãƒ†ã‚¯ã‚¹ãƒãƒ£ãƒ¼">
+<floater name="avatar_texture_debug" title="ã‚¢ãƒã‚¿ãƒ¼ã®ãƒ†ã‚¯ã‚¹ãƒãƒ£">
+ <floater.string name="InvalidAvatar">
+ 無効ãªã‚¢ãƒã‚¿ãƒ¼
+ </floater.string>
<text name="label">
ベークドテクスãƒãƒ£
</text>
@@ -8,24 +11,32 @@
</text>
<button label="テクスãƒãƒ£ID一覧をコンソールã«æ›¸ã込む" label_selected="æ¨ã¦ã‚‹" name="Dump"/>
<texture_picker label="髪型" name="hair-baked"/>
- <texture_picker label="髪" name="hair"/>
+ <texture_picker label="髪" name="hair_grain"/>
+ <texture_picker label="髪ã®ã‚¢ãƒ«ãƒ•ã‚¡" name="hair_alpha"/>
<texture_picker label="é ­" name="head-baked"/>
- <texture_picker label="メイクアップ" name="head bodypaint"/>
+ <texture_picker label="メイクアップ" name="head_bodypaint"/>
+ <texture_picker label="頭部ã®ã‚¢ãƒ«ãƒ•ã‚¡" name="head_alpha"/>
+ <texture_picker label="頭部ã®ã‚¿ãƒˆã‚¥ãƒ¼" name="head_tattoo"/>
<texture_picker label="ç›®" name="eyes-baked"/>
- <texture_picker label="ç›®" name="iris"/>
+ <texture_picker label="ç›®" name="eyes_iris"/>
+ <texture_picker label="ç›®ã®ã‚¢ãƒ«ãƒ•ã‚¡" name="eyes_alpha"/>
<texture_picker label="上åŠèº«" name="upper-baked"/>
- <texture_picker label="上åŠèº«ã®ã‚¿ãƒˆã‚¥ãƒ¼" name="upper bodypaint"/>
- <texture_picker label="(下ç€ã®ï¼‰ã‚·ãƒ£ãƒ„" name="undershirt"/>
- <texture_picker label="手袋" name="gloves"/>
- <texture_picker label="シャツ" name="shirt"/>
- <texture_picker label="上ç€" name="upper jacket"/>
+ <texture_picker label="上åŠèº«ã®ãƒœãƒ‡ã‚£ãƒšã‚¤ãƒ³ãƒˆ" name="upper_bodypaint"/>
+ <texture_picker label="下ç€ã‚·ãƒ£ãƒ„" name="upper_undershirt"/>
+ <texture_picker label="手袋" name="upper_gloves"/>
+ <texture_picker label="シャツ" name="upper_shirt"/>
+ <texture_picker label="上ç€" name="upper_jacket"/>
+ <texture_picker label="アルファ(上)" name="upper_alpha"/>
+ <texture_picker label="上部ã®ã‚¿ãƒˆã‚¥ãƒ¼" name="upper_tattoo"/>
<texture_picker label="下åŠèº«" name="lower-baked"/>
- <texture_picker label="下åŠèº«ã®ã‚¿ãƒˆã‚¥ãƒ¼" name="lower bodypaint"/>
- <texture_picker label="(下ç€ã®ï¼‰ãƒ‘ンツ" name="underpants"/>
- <texture_picker label="é´ä¸‹" name="socks"/>
- <texture_picker label="é´" name="shoes"/>
- <texture_picker label="ズボン" name="pants"/>
- <texture_picker label="上ç€" name="lower jacket"/>
+ <texture_picker label="下åŠèº«ã®ãƒœãƒ‡ã‚£ãƒšã‚¤ãƒ³ãƒˆ" name="lower_bodypaint"/>
+ <texture_picker label="下ç€ãƒ‘ンツ" name="lower_underpants"/>
+ <texture_picker label="é´ä¸‹" name="lower_socks"/>
+ <texture_picker label="é´" name="lower_shoes"/>
+ <texture_picker label="パンツ" name="lower_pants"/>
+ <texture_picker label="ジャケット" name="lower_jacket"/>
+ <texture_picker label="アルファ(下)" name="lower_alpha"/>
+ <texture_picker label="下部ã®ã‚¿ãƒˆã‚¥ãƒ¼" name="lower_tattoo"/>
<texture_picker label="スカート" name="skirt-baked"/>
<texture_picker label="スカート" name="skirt"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_beacons.xml b/indra/newview/skins/default/xui/ja/floater_beacons.xml
index 2065656732..d2f4798949 100644
--- a/indra/newview/skins/default/xui/ja/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/ja/floater_beacons.xml
@@ -1,15 +1,21 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="beacons" title="ビーコン(標識)">
<panel name="beacons_panel">
- <check_box label="タッï¾ï½µï¾ï¾˜ï½°ã®ï½½ï½¸ï¾˜ï¾Œï¾Ÿï¾„ã‚’å«ã‚€ï½µï¾Œï¾žï½¼ï¾žï½ªï½¸ï¾„" name="touch_only"/>
- <check_box label="スクリプト・オブジェクト" name="scripted"/>
- <check_box label="物ç†çš„オブジェクト" name="physical"/>
+ <text name="label_show">
+ 表示:
+ </text>
+ <check_box label="ビーコン(標識)" name="beacons"/>
+ <check_box label="ãƒã‚¤ãƒ©ã‚¤ãƒˆ" name="highlights"/>
+ <text name="beacon_width_label" tool_tip="ビーコン(標識)ã®å¹…">
+ 幅:
+ </text>
+ <text name="label_objects">
+ 対象オブジェクト:
+ </text>
+ <check_box label="物ç†çš„" name="physical"/>
+ <check_box label="スクリプト" name="scripted"/>
+ <check_box label="触れる" name="touch_only"/>
<check_box label="音æº" name="sounds"/>
<check_box label="パーティクルæº" name="particles"/>
- <check_box label="ãƒã‚¤ãƒ©ã‚¤ãƒˆã®ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°" name="highlights"/>
- <check_box label="ビーコン(標識)ã®ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°" name="beacons"/>
- <text name="beacon_width_label">
- ビーコン(標識)ã®å¹…
- </text>
</panel>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_build_options.xml b/indra/newview/skins/default/xui/ja/floater_build_options.xml
index 49348aaa10..8d3dba3883 100644
--- a/indra/newview/skins/default/xui/ja/floater_build_options.xml
+++ b/indra/newview/skins/default/xui/ja/floater_build_options.xml
@@ -1,8 +1,11 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="build options floater" title="グリッドã®ã‚ªãƒ—ション">
- <spinner label="グリッドå˜ä½ï¼ˆï¾’ートル)" name="GridResolution" />
- <spinner label="グリッド範囲(メートル)" name="GridDrawSize" />
- <check_box label="サブユニット・スナッピングを有効化" name="GridSubUnit" />
- <check_box label="æ–­é¢ã‚’表示" name="GridCrossSection" />
- <slider label="グリッドã®ä¸é€æ˜Žåº¦" name="GridOpacity" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="build options floater" title="グリッドオプション">
+ <spinner label="グリッドユニット(メートル)" name="GridResolution"/>
+ <spinner label="グリッド範囲(メートル)" name="GridDrawSize"/>
+ <check_box label="サブユニットã«ã‚¹ãƒŠãƒƒãƒ—" name="GridSubUnit"/>
+ <check_box label="横断é¢ã‚’表示" name="GridCrossSection"/>
+ <text name="grid_opacity_label" tool_tip="グリッドã®é€æ˜Žåº¦">
+ é€æ˜Žåº¦ï¼š
+ </text>
+ <slider label="グリッドã®ä¸é€æ˜Žåº¦" name="GridOpacity"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_bulk_perms.xml b/indra/newview/skins/default/xui/ja/floater_bulk_perms.xml
index 6ee90038fb..7afe70f4d7 100644
--- a/indra/newview/skins/default/xui/ja/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/ja/floater_bulk_perms.xml
@@ -1,44 +1,54 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterbulkperms" title="コンテンツ権é™ã®ä¸€æ‹¬å¤‰æ›´">
- <text name="applyto">
- コンテンツã®ç¨®é¡ž
- </text>
+<floater name="floaterbulkperms" title="コンテンツ権é™ã®ç·¨é›†">
+ <floater.string name="nothing_to_modify_text">
+ é¸æŠžã—ãŸä¸­ã«ç·¨é›†ã§ããªã„コンテンツãŒå«ã¾ã‚Œã¦ã„ã¾ã™
+ </floater.string>
+ <floater.string name="status_text">
+ [NAME]ã«æ¨©é™ã‚’設定中ã§ã™ã€‚
+ </floater.string>
+ <floater.string name="start_text">
+ 権é™å¤‰æ›´ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’ã—ã¦ã„ã¾ã™
+ </floater.string>
+ <floater.string name="done_text">
+ 権é™å¤‰æ›´ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒå®Œäº†ã—ã¾ã—ãŸ
+ </floater.string>
<check_box label="アニメーション" name="check_animation"/>
+ <icon name="icon_animation" tool_tip="アニメーション"/>
<check_box label="身体部ä½" name="check_bodypart"/>
+ <icon name="icon_bodypart" tool_tip="身体部ä½"/>
<check_box label="æœ" name="check_clothing"/>
+ <icon name="icon_clothing" tool_tip="衣類"/>
<check_box label="ジェスãƒãƒ£ãƒ¼" name="check_gesture"/>
- <check_box label="ランドマーク" name="check_landmark"/>
+ <icon name="icon_gesture" tool_tip="ジェスãƒãƒ£ãƒ¼"/>
<check_box label="ノートカード" name="check_notecard"/>
+ <icon name="icon_notecard" tool_tip="ノートカード"/>
<check_box label="オブジェクト" name="check_object"/>
+ <icon name="icon_object" tool_tip="オブジェクト"/>
<check_box label="スクリプト" name="check_script"/>
+ <icon name="icon_script" tool_tip="スクリプト"/>
<check_box label="サウンド" name="check_sound"/>
+ <icon name="icon_sound" tool_tip="サウンド"/>
<check_box label="テクスãƒãƒ£ãƒ¼" name="check_texture"/>
- <button label="å…¨ã¦é¸æŠž" label_selected="å…¨ã¦" name="check_all"/>
- <button label="å…¨ã¦è§£é™¤" label_selected="ãªã—" name="check_none"/>
+ <icon name="icon_texture" tool_tip="テクスãƒãƒ£"/>
+ <button label="ã™ã¹ã¦ã« √" label_selected="å…¨ã¦" name="check_all"/>
+ <button label="クリア" label_selected="ãªã—" name="check_none"/>
<text name="newperms">
- æ–°ã—ã„権é™
+ æ–°ã—ã„コンテンツ権é™
+ </text>
+ <text name="GroupLabel">
+ グループ:
</text>
- <check_box label="グループã§å…±åŒç®¡ç†" name="share_with_group"/>
- <check_box label="誰ã«å¯¾ã—ã¦ã‚‚コピーを許å¯" name="everyone_copy"/>
+ <check_box label="共有" name="share_with_group"/>
+ <text name="AnyoneLabel">
+ 全員:
+ </text>
+ <check_box label="コピー" name="everyone_copy"/>
<text name="NextOwnerLabel">
- 次ã®ã‚ªãƒ¼ãƒŠãƒ¼ãŒã§ãã‚‹æ“作:
+ 次ã®æ‰€æœ‰è€…:
</text>
<check_box label="修正" name="next_owner_modify"/>
<check_box label="コピー" name="next_owner_copy"/>
- <check_box label="å†è²©/プレゼント" name="next_owner_transfer"/>
- <button label="ヘルプ" name="help"/>
- <button label="é©ç”¨" name="apply"/>
- <button label="é–‰ã˜ã‚‹" name="close"/>
- <string name="nothing_to_modify_text">
- é¸æŠžã—ãŸä¸­ã«ç·¨é›†ã§ããªã„コンテンツãŒå«ã¾ã‚Œã¦ã„ã¾ã™
- </string>
- <string name="status_text">
- [NAME]ã«æ¨©é™ã‚’設定中ã§ã™ã€‚
- </string>
- <string name="start_text">
- 権é™å¤‰æ›´ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’ã—ã¦ã„ã¾ã™
- </string>
- <string name="done_text">
- 権é™å¤‰æ›´ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒå®Œäº†ã—ã¾ã—ãŸ
- </string>
+ <check_box initial_value="true" label="å†è²©ãƒ»ãƒ—レゼント" name="next_owner_transfer" tool_tip="次ã®æ‰€æœ‰è€…ã¯ã“ã®ã‚ªãƒ–ジェクトを他人ã«ã‚ã’ãŸã‚Šå†è²©ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™"/>
+ <button label="Ok" name="apply"/>
+ <button label="キャンセル" name="close"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_bumps.xml b/indra/newview/skins/default/xui/ja/floater_bumps.xml
index cbd6a2f9e2..8a1e19b852 100644
--- a/indra/newview/skins/default/xui/ja/floater_bumps.xml
+++ b/indra/newview/skins/default/xui/ja/floater_bumps.xml
@@ -1,21 +1,24 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_bumps" title="è¡çªã®è¨˜éŒ²">
- <text name="none_detected">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_bumps" title="è¡çªãƒ»ãƒ—ッシュ・打撃">
+ <floater.string name="none_detected">
検出ãªã—
- </text>
- <text name="bump">
+ </floater.string>
+ <floater.string name="bump">
[TIME] [FIRST] [LAST]ãŒã€ã‚ãªãŸã«ã¶ã¤ã‹ã‚Šã¾ã—ãŸã€‚
- </text>
- <text name="llpushobject">
+ </floater.string>
+ <floater.string name="llpushobject">
[TIME] [FIRST] [LAST]ãŒã€ã‚¹ã‚¯ãƒªãƒ—トã§ã‚ãªãŸã‚’プッシュã—ã¾ã—ãŸã€‚
- </text>
- <text name="selected_object_collide">
+ </floater.string>
+ <floater.string name="selected_object_collide">
[TIME] [FIRST] [LAST]ãŒã€ã‚ªãƒ–ジェクトをã‚ãªãŸã«å½“ã¦ã¾ã—ãŸã€‚
- </text>
- <text name="scripted_object_collide">
+ </floater.string>
+ <floater.string name="scripted_object_collide">
[TIME] [FIRST] [LAST]ãŒã€ã‚¹ã‚¯ãƒªãƒ—ト・オブジェクトをã‚ãªãŸã«å½“ã¦ã¾ã—ãŸã€‚
- </text>
- <text name="physical_object_collide">
+ </floater.string>
+ <floater.string name="physical_object_collide">
[TIME] [FIRST] [LAST]ãŒã€ç‰©ç†ã‚ªãƒ–ジェクトをã‚ãªãŸã«å½“ã¦ã¾ã—ãŸã€‚
- </text>
+ </floater.string>
+ <floater.string name="timeStr">
+ [[hour,datetime,slt]:[min,datetime,slt]]
+ </floater.string>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_buy_contents.xml b/indra/newview/skins/default/xui/ja/floater_buy_contents.xml
index 1ea10324b3..53b7f24141 100644
--- a/indra/newview/skins/default/xui/ja/floater_buy_contents.xml
+++ b/indra/newview/skins/default/xui/ja/floater_buy_contents.xml
@@ -1,14 +1,15 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_buy_contents" title="コンテンツを購入">
- <text name="contains_text">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater min_width="340" name="floater_buy_contents" title="コンテンツã®è³¼å…¥" width="340">
+ <text name="contains_text" width="320">
[NAME]ã®å†…容:
</text>
- <text name="buy_text">
+ <scroll_list name="item_list" width="310"/>
+ <text name="buy_text" width="320">
コンテンツを[NAME]ã‹ã‚‰L$[AMOUNT]ã§è³¼å…¥ã—ã¾ã™ã‹ï¼Ÿ
</text>
- <button label="å–り消ã—" label_selected="å–り消ã—" name="cancel_btn" />
- <button label="購入" label_selected="購入" name="buy_btn" />
- <check_box label="今ã™ãæœã‚’ç€ã‚‹" name="wear_check" />
+ <button label="å–り消ã—" label_selected="å–り消ã—" name="cancel_btn" width="73"/>
+ <button label="購入" label_selected="購入" left_delta="-77" name="buy_btn" width="73"/>
+ <check_box label="今ã™ãæœã‚’ç€ã‚‹" left_delta="-125" name="wear_check"/>
<text name="no_copy_text">
(コピーãªã—)
</text>
diff --git a/indra/newview/skins/default/xui/ja/floater_buy_currency.xml b/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
index 9d5aea612b..ffdcf838d3 100644
--- a/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
@@ -1,68 +1,66 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="buy currency" title="貨幣購入">
- <text name="info_buying">
- 貨幣を購入:
- </text>
- <text name="info_cannot_buy">
- ç¾åœ¨è³¼å…¥ä¸å¯ï¼š
- </text>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="buy currency" title="L$ ã®è³¼å…¥">
+ <floater.string name="buy_currency">
+ 約 [LOCALAMOUNT] 㧠L$ [LINDENS] を購入
+ </floater.string>
<text name="info_need_more">
- ã•ã‚‰ã«ãŠé‡‘ãŒå¿…è¦ã§ã™ï¼š
+ L$ ãŒè¶³ã‚Šã¾ã›ã‚“
</text>
- <text name="error_message">
- 何ã‹å¤‰ã§ã™ã€‚
- </text>
- <button label="ウェブ・サイトã«ç§»å‹•" name="error_web" width="140"/>
<text name="contacting">
LindeXã¨ã‚³ãƒ³ã‚¿ã‚¯ãƒˆä¸­â€¦
</text>
- <text name="buy_action_unknown">
- LindeX通貨両替ã§L$を購入
+ <text name="info_buying">
+ L$ ã®è³¼å…¥
</text>
- <text name="buy_action">
- [NAME] L$ [PRICE]
+ <text name="balance_label">
+ 残高
+ </text>
+ <text name="balance_amount">
+ L$ [AMT]
</text>
<text name="currency_action">
- L$購入
+ 購入希望é¡
+ </text>
+ <text name="currency_label">
+ L$
</text>
- <line_editor name="currency_amt">
+ <line_editor label="L$" name="currency_amt">
1234
</line_editor>
- <text name="currency_est">
- ç´„US$ [USD]
- </text>
- <text name="getting_data" left_delta="3">
- データをå–å¾—ã—ã¦ã„ã¾ã™...
- </text>
- <text name="balance_label">
- ç¾åœ¨æ‰€æœ‰ã—ã¦ã„る金é¡
+ <text name="buying_label">
+ 価格
</text>
- <text name="balance_amount">
- L$ [AMT]
+ <text name="currency_est">
+ ç´„ [LOCALAMOUNT]
</text>
- <text name="buying_label">
- 購入ã™ã‚‹é‡‘é¡
+ <text left_delta="3" name="getting_data">
+ 見ç©ã‚‚り中...
</text>
- <text name="buying_amount">
- L$ [AMT]
+ <text name="buy_action">
+ [NAME] L$ [PRICE]
</text>
<text name="total_label">
- åˆè¨ˆæ®‹é«˜
+ æ–°ã—ã„残高
</text>
<text name="total_amount">
L$ [AMT]
</text>
+ <text name="currency_links">
+ [http://www.secondlife.com/my/account/payment_method_management.php?lang=ja-JP payment method] | [http://www.secondlife.com/my/account/currency.php?lang=ja-JP currency] | [http://www.secondlife.com/my/account/exchange_rates.php?lang=ja-JP exchange rate]
+ </text>
+ <text name="exchange_rate_note">
+ 金é¡ã‚’å†å…¥åŠ›ã—ã¦æœ€æ–°æ›ç®—レートを確èªã—ã¾ã™ã€‚
+ </text>
<text name="purchase_warning_repurchase">
- ã“ã®è³¼è²·ã®ç¢ºèªã§ã¯ã€é€šè²¨ã ã‘を購入ã—ã¾ã™ã€‚
-å†æ“作ãŒå¿…è¦ã«ãªã‚Šã¾ã™ã€‚
+ ã“ã®å–引を決定ã™ã‚‹ã¨ã€L$ を購入ã—ã¾ã™ã€‚オブジェクトã¯è³¼å…¥ã—ã¾ã›ã‚“。
</text>
<text name="purchase_warning_notenough">
- ã‚ãªãŸãŒè²·ã†ãƒªãƒ³ãƒ‡ãƒ³ãƒ»ãƒ‰ãƒ«ã§ã¯è¶³ã‚Šã¾ã›ã‚“。
-購入é¡ã‚’増やã—ã¦ãã ã•ã„。
+ 購入ã—よã†ã¨ã—ã¦ã„ã‚‹ L$ ãŒä¸è¶³ã—ã¦ã„ã¾ã™ã€‚ 金é¡ã‚’上ã’ã¦ãã ã•ã„。
</text>
- <button label="購入" name="buy_btn" />
- <button label="å–り消ã—" name="cancel_btn" />
- <text name="buy_currency">
- ç´„US$ [USD]ã§L$ [LINDENS]を購入
+ <button label="購入ã™ã‚‹" name="buy_btn"/>
+ <button label="å–り消ã—" name="cancel_btn"/>
+ <text name="info_cannot_buy">
+ 購入ã§ãã¾ã›ã‚“
</text>
+ <button label="Web サイトã«ç§»å‹•" name="error_web" width="140"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_buy_land.xml b/indra/newview/skins/default/xui/ja/floater_buy_land.xml
index ba51e7263d..13b43d1257 100644
--- a/indra/newview/skins/default/xui/ja/floater_buy_land.xml
+++ b/indra/newview/skins/default/xui/ja/floater_buy_land.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="buy land" title="土地を購入">
+<floater name="buy land" title="土地ã®è³¼å…¥">
<text name="region_name_label">
地域:
</text>
@@ -36,6 +36,7 @@
<text name="covenant_text">
ä¸å‹•ç”£ç´„款ã«åŒæ„ã—ã¦ãã ã•ã„:
</text>
+ <text left="470" name="covenant_timestamp_text"/>
<text_editor name="covenant_editor">
ロード中...
</text_editor>
@@ -50,15 +51,15 @@
サイズ:
</text>
<text bottom_delta="-37" height="48" name="info_size">
- 1024平方メートル
+ 1024 平方メートル
</text>
<text name="info_price_label">
価格:
</text>
<text name="info_price">
L$ 1500
- (L$ 1.1/平方メートル)
- オブジェクトも土地販売価格ã«å«ã¾ã‚Œã¾ã™
+(L$ 1.1/平方メートル)
+オブジェクトも土地販売価格ã«å«ã¾ã‚Œã¾ã™
</text>
<text name="info_action">
ã“ã®åœŸåœ°ã‚’è²·ã†ã¨ï¼š
@@ -74,22 +75,16 @@
土地をä¿æœ‰ã§ãã‚‹ã®ã¯ãƒ—レミアム・メンãƒãƒ¼ã ã‘ã§ã™
</text>
<combo_box name="account_level">
- <combo_item name="US$9.95/month,billedmonthly">
- 月é¡9.95米ドルã€æœˆæ‰•ã„
- </combo_item>
- <combo_item name="US$7.50/month,billedquarterly">
- 月é¡7.50米ドルã€å¹´4回払ã„
- </combo_item>
- <combo_item name="US$6.00/month,billedannually">
- 月é¡6.00米ドルã€å¹´æ‰•ã„
- </combo_item>
+ <combo_box.item label="æœˆé¡ 9.95米ドル〠月払ã„" name="US$9.95/month,billedmonthly"/>
+ <combo_box.item label="æœˆé¡ 7.50米ドル〠年4回3ヶ月毎" name="US$7.50/month,billedquarterly"/>
+ <combo_box.item label="æœˆé¡ 6.00米ドル〠年間一括払ã„" name="US$6.00/month,billedannually"/>
</combo_box>
<text name="land_use_action">
毎月ã®åœŸåœ°ä½¿ç”¨æ–™ã‚’US$40ã«å¼•ã上ã’ã¾ã™
</text>
<text name="land_use_reason">
- ã‚ãªãŸã¯1,309平方メートルã®åœŸåœ°ã‚’所有ã—ã¦ã„ã¾ã™ã€‚
-ã“ã®åŒºç”»ã¯512平方メートルã§ã™ã€‚
+ ã‚ãªãŸã¯ 1309 平方メートルã®åœŸåœ°ã‚’所有ã—ã¦ã„ã¾ã™ã€‚
+ã“ã®åŒºç”»ã®å¤§ãã•ã¯ã€512 平方メートルã§ã™ã€‚
</text>
<text name="purchase_action">
Joe Residentã«L$4000支払ã£ã¦åœŸåœ°ã‚’購入
@@ -104,12 +99,12 @@
1000
</line_editor>
<text name="currency_est">
- ç´„US$ [AMOUNT2]
+ ç´„ [LOCAL_AMOUNT]
</text>
<text name="currency_balance">
所æŒé‡‘㯠L$2,100ã§ã™ã€‚
</text>
- <check_box label="[AMOUNT]平方メートルã®è²¢çŒ®é¢ç©ã‚’グループã‹ã‚‰å–り除ã" name="remove_contribution"/>
+ <check_box label="グループã‹ã‚‰ [AMOUNT] 平方メートルã®è²¢çŒ®ã‚’å–り除ãã¾ã™ã€‚" name="remove_contribution"/>
<button label="購入" name="buy_btn"/>
<button label="å–り消ã—" name="cancel_btn"/>
<string name="can_resell">
@@ -186,16 +181,16 @@
ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã§åœŸåœ°ã‚’所有ã§ãã¾ã™
</string>
<string name="land_holdings">
- ã‚ãªãŸã¯ [BUYER] 平方メートルã®åœŸåœ°ã‚’所有ã—ã¦ã„ã¾ã™
+ ã‚ãªãŸã¯ã€[BUYER] 平方メートルã®åœŸåœ°ã‚’所有ã—ã¦ã„ã¾ã™ã€‚
</string>
<string name="pay_to_for_land">
ã“ã®åœŸåœ°ã®ä»£é‡‘ã¨ã—ã¦ã€[SELLER]ã«L$[AMOUNT]を支払ã†
</string>
<string name="buy_for_US">
- ç´„US$ [AMOUNT2]ã§L$ [AMOUNT]を購入
+ L$ [AMOUNT] ã‚’ã€ç´„ [LOCAL_AMOUNT] ã§è³¼å…¥ã—ã¾ã™ã€‚
</string>
<string name="parcel_meters">
- ã“ã®åŒºç”»ã¯ [AMOUNT] 平方メートルã‚ã‚Šã¾ã™
+ ã“ã®åŒºç”»ã¯ [AMOUNT] 平方メートルã§ã™ã€‚
</string>
<string name="premium_land">
ã“ã®åœŸåœ°ã¯å‰²ã‚Šå¢—ã—付ã§ã™ã€‚ [AMOUNT] 平方メートルã®æ–™é‡‘ãŒã‹ã‹ã‚Šã¾ã™ã€‚
@@ -204,9 +199,8 @@
ã“ã®åœŸåœ°ã¯ãƒ‡ã‚£ã‚¹ã‚«ã‚¦ãƒ³ãƒˆã•ã‚Œã¦ã„ã¾ã™ã€‚ [AMOUNT] 平方メートルã®æ–™é‡‘ãŒã‹ã‹ã‚Šã¾ã™ã€‚
</string>
<string name="meters_supports_object">
- [AMOUNT]平方メートルã§ã‚ã‚Œã°ã€
-[AMOUNT2]個ã®ã‚ªãƒ–ジェクトãŒã‚µãƒ
-ートã•ã‚Œã¾ã™
+ [AMOUNT] 平方メートル
+オブジェクト [AMOUNT2] 個サãƒãƒ¼ãƒˆ
</string>
<string name="sold_with_objects">
オブジェクトã¨å…±ã«è²©å£²æ¸ˆã¿
@@ -216,7 +210,7 @@
</string>
<string name="info_price_string">
L$ [PRICE]
-(L$ [PRICE_PER_SQM]/平方メートル)
+(L$[PRICE_PER_SQM]/平方メートル)
[SOLD_WITH_OBJECTS]
</string>
<string name="insufficient_land_credits">
diff --git a/indra/newview/skins/default/xui/ja/floater_buy_object.xml b/indra/newview/skins/default/xui/ja/floater_buy_object.xml
index 1b5dd8b979..f807e91573 100644
--- a/indra/newview/skins/default/xui/ja/floater_buy_object.xml
+++ b/indra/newview/skins/default/xui/ja/floater_buy_object.xml
@@ -1,13 +1,13 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="contents" title="オブジェクトã®ã‚³ãƒ”ーを購入">
<text name="contents_text">
- ãŠã‚ˆã³ãã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„:
+ 内容:
</text>
<text name="buy_text">
[NAME]ã‹ã‚‰L$[AMOUNT]ã§è³¼å…¥ã—ã¾ã™ã‹ï¼Ÿ
</text>
- <button label="å–消" label_selected="å–消" name="cancel_btn" />
- <button label="購入" label_selected="購入" name="buy_btn" />
+ <button label="å–消" label_selected="å–消" name="cancel_btn"/>
+ <button label="購入" label_selected="購入" name="buy_btn"/>
<text name="title_buy_text">
購入
</text>
diff --git a/indra/newview/skins/default/xui/ja/floater_camera.xml b/indra/newview/skins/default/xui/ja/floater_camera.xml
index 46e7b1990d..be118273fa 100644
--- a/indra/newview/skins/default/xui/ja/floater_camera.xml
+++ b/indra/newview/skins/default/xui/ja/floater_camera.xml
@@ -1,12 +1,31 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="move floater">
- <string name="rotate_tooltip">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="camera_floater">
+ <floater.string name="rotate_tooltip">
フォーカスを中心ã«ã‚«ãƒ¡ãƒ©ã‚’回転
- </string>
- <string name="zoom_tooltip">
+ </floater.string>
+ <floater.string name="zoom_tooltip">
フォーカスã«å‘ã‘ã¦ã‚«ãƒ¡ãƒ©ã‚’ズーム
- </string>
- <string name="move_tooltip">
+ </floater.string>
+ <floater.string name="move_tooltip">
カメラを上下左å³ã«ç§»å‹•
- </string>
+ </floater.string>
+ <panel name="controls">
+ <joystick_track name="cam_track_stick" tool_tip="カメラを上下左å³ã«å‹•ã‹ã—ã¾ã™"/>
+ <panel name="zoom" tool_tip="å‘ã„ã¦ã‚‹æ–¹æ³•ã«ã‚«ãƒ¡ãƒ©ã‚’ズーム">
+ <slider_bar name="zoom_slider" tool_tip="å‘ã„ã¦ã„ã‚‹æ–¹å‘ã«ã‚«ãƒ¡ãƒ©ã‚’ズーム"/>
+ </panel>
+ <joystick_rotate name="cam_rotate_stick" tool_tip="自分を軸ã«ã‚«ãƒ¡ãƒ©ã‚’回ã™"/>
+ <panel name="camera_presets">
+ <button name="rear_view" tool_tip="後方視界"/>
+ <button name="group_view" tool_tip="グループ視界"/>
+ <button name="front_view" tool_tip="å‰æ–¹è¦–ç•Œ"/>
+ <button name="mouselook_view" tool_tip="一人称視界"/>
+ </panel>
+ </panel>
+ <panel name="buttons">
+ <button label="" name="orbit_btn" tool_tip="カメラを回ã™"/>
+ <button label="" name="pan_btn" tool_tip="カメラを水平・垂直移動"/>
+ <button label="" name="avatarview_btn" tool_tip="ã‚¢ãƒã‚¿ãƒ¼è¦–点"/>
+ <button label="" name="freecamera_btn" tool_tip="オブジェクトを見る"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_choose_group.xml b/indra/newview/skins/default/xui/ja/floater_choose_group.xml
index 08c91f1895..7d91cb69ed 100644
--- a/indra/newview/skins/default/xui/ja/floater_choose_group.xml
+++ b/indra/newview/skins/default/xui/ja/floater_choose_group.xml
@@ -1,8 +1,8 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="groups" title="グループ">
<text name="groupdesc">
グループをé¸æŠžï¼š
</text>
- <button label="OK" label_selected="OK" name="OK" />
- <button label="å–り消ã—" label_selected="å–り消ã—" name="Cancel" />
+ <button label="OK" label_selected="OK" name="OK"/>
+ <button label="å–り消ã—" label_selected="å–り消ã—" name="Cancel"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_color_picker.xml b/indra/newview/skins/default/xui/ja/floater_color_picker.xml
index 8047e49b75..f6739d59e8 100644
--- a/indra/newview/skins/default/xui/ja/floater_color_picker.xml
+++ b/indra/newview/skins/default/xui/ja/floater_color_picker.xml
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="ColorPicker" title="カラー・ピッカー">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="ColorPicker" title="カラーピッカー">
<text name="r_val_text">
赤:
</text>
@@ -18,14 +18,14 @@
<text name="l_val_text">
è¼åº¦ï¼š
</text>
- <check_box label="ãŸã ã¡ã«é©ç”¨" name="apply_immediate" />
- <button label="" label_selected="" name="color_pipette" />
- <button label="å–り消ã—" label_selected="å–り消ã—" name="cancel_btn" />
- <button label="é¸æŠž" label_selected="é¸æŠž" name="select_btn" />
+ <check_box label="今ã™ãé©ç”¨" name="apply_immediate"/>
+ <button label="" label_selected="" name="color_pipette"/>
+ <button label="å–り消ã—" label_selected="å–り消ã—" name="cancel_btn"/>
+ <button label="Ok" label_selected="Ok" name="select_btn"/>
<text name="Current color:">
ç¾åœ¨ã®è‰²ï¼š
</text>
<text name="(Drag below to save.)">
- ドラッグã—ã¦ä¿å­˜
+ (下ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦ä¿å­˜ï¼‰
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_customize.xml b/indra/newview/skins/default/xui/ja/floater_customize.xml
index 27fa434963..61423fcf05 100644
--- a/indra/newview/skins/default/xui/ja/floater_customize.xml
+++ b/indra/newview/skins/default/xui/ja/floater_customize.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="floater customize" title="容姿">
<tab_container name="customize tab container">
- <panel label="身体部ä½" name="body_parts_placeholder"/>
+ <placeholder label="身体部ä½" name="body_parts_placeholder"/>
<panel label="シェイプ" name="Shape">
<button label="戻ã™" label_selected="戻ã™" name="Revert"/>
<button label="身体" label_selected="身体" name="Body"/>
@@ -14,33 +14,29 @@
<button label="胴体" label_selected="胴体" name="Torso"/>
<button label="両脚" label_selected="両脚" name="Legs"/>
<radio_group name="sex radio">
- <radio_item length="1" name="radio" type="string">
- 女性
- </radio_item>
- <radio_item length="1" name="radio2" type="string">
- 男性
- </radio_item>
+ <radio_item label="女性" name="radio"/>
+ <radio_item label="男性" name="radio2"/>
</radio_group>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: 修正ã§ãã¾ã›ã‚“。
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: ロード中...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: 未装ç€ã€‚
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
[PATH] ã«æ‰€åœ¨
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
æ–°ã—ã„シェイプ(体型)ã‚’æŒã¡ç‰©ã‹ã‚‰ã‚¢ãƒã‚¿ãƒ¼ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦è£…ç€ã—ã¾
ã—ょã†ã€‚完全ã«æ–°è¦ã®çŠ¶æ…‹ã‹ã‚‰ä½œæˆã—ã¦è£…ç€ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
ã‚ãªãŸã¯ã“ã®æœã®ä¿®æ­£ã‚’許ã•ã‚Œã¦ã„ã¾ã›ã‚“。
</text>
<text name="Item Action Label">
@@ -55,26 +51,26 @@
<button label="é¡”ã®ç´°éƒ¨" label_selected="é¡”ã®ç´°éƒ¨" name="Face Detail"/>
<button label="メイクアップ" label_selected="メイクアップ" name="Makeup"/>
<button label="身体細部" label_selected="身体細部" name="Body Detail"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: 修正ã§ãã¾ã›ã‚“。
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: ロード中...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: 未装ç€ã€‚
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
[PATH] ã«æ‰€åœ¨
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
æ–°ã—ã„スキンをæŒã¡ç‰©ã‹ã‚‰ã‚¢ãƒã‚¿ãƒ¼ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦è£…ç€ã—ã¾ã—ょã†ã€‚
完全ã«æ–°è¦ã®çŠ¶æ…‹ã‹ã‚‰ä½œæˆã—ã¦è£…ç€ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
ã‚ãªãŸã¯ã“ã®æœã®ä¿®æ­£ã‚’許ã•ã‚Œã¦ã„ã¾ã›ã‚“。
</text>
<text name="Item Action Label">
@@ -93,26 +89,26 @@
<button label="スタイル" label_selected="スタイル" name="Style"/>
<button label="眉毛" label_selected="眉毛" name="Eyebrows"/>
<button label="é¡”" label_selected="é¡”" name="Facial"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: 修正ã§ãã¾ã›ã‚“。
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: ロード中...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: 未装ç€ã€‚
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
[PATH] ã«æ‰€åœ¨
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
æ–°ã—ã„髪型をæŒã¡ç‰©ã‹ã‚‰ã‚¢ãƒã‚¿ãƒ¼ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦è£…ç€ã—ã¾ã—ょã†ã€‚
完全ã«æ–°è¦ã®çŠ¶æ…‹ã‹ã‚‰ä½œæˆã—ã¦è£…ç€ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
ã‚ãªãŸã¯ã“ã®æœã®ä¿®æ­£ã‚’許ã•ã‚Œã¦ã„ã¾ã›ã‚“。
</text>
<text name="Item Action Label">
@@ -125,26 +121,26 @@
<button label="戻ã™" label_selected="戻ã™" name="Revert"/>
</panel>
<panel label="眼" name="Eyes">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: 修正ã§ãã¾ã›ã‚“。
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: ロード中...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: 未装ç€ã€‚
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
[PATH] ã«æ‰€åœ¨
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
æ–°ã—ã„眼をæŒã¡ç‰©ã‹ã‚‰ã‚¢ãƒã‚¿ãƒ¼ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦è£…ç€ã—ã¾ã—ょã†ã€‚
完全ã«æ–°è¦ã®çŠ¶æ…‹ã‹ã‚‰ä½œæˆã—ã¦è£…ç€ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
ã‚ãªãŸã¯ã“ã®æœã®ä¿®æ­£ã‚’許ã•ã‚Œã¦ã„ã¾ã›ã‚“。
</text>
<text name="Item Action Label">
@@ -156,35 +152,35 @@
<button label="別åã§ä¿å­˜..." label_selected="別åã§ä¿å­˜..." name="Save As"/>
<button label="戻ã™" label_selected="戻ã™" name="Revert"/>
</panel>
- <panel label="æœ" name="clothes_placeholder"/>
+ <placeholder label="æœ" name="clothes_placeholder"/>
<panel label="シャツ" name="Shirt">
<texture_picker label="生地" name="Fabric" tool_tip="写真をクリックã—ã¦é¸æŠž"/>
- <color_swatch label="色ï¼æ˜Žæš—" name="Color/Tint" tool_tip="カラー・ピッカーをクリックã—ã¦é–‹ã"/>
+ <color_swatch label="色ï¼æ˜Žæš—" name="Color/Tint" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
<button label="æ–°ã—ã„シャツを作æˆ" label_selected="æ–°ã—ã„シャツを作æˆ" name="Create New"/>
<button label="å–り外ã™" label_selected="å–り外ã™" name="Take Off"/>
<button label="ä¿å­˜" label_selected="ä¿å­˜" name="Save"/>
<button label="別åã§ä¿å­˜..." label_selected="別åã§ä¿å­˜..." name="Save As"/>
<button label="戻ã™" label_selected="戻ã™" name="Revert"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: 修正ã§ãã¾ã›ã‚“。
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: ロード中...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: 未装ç€ã€‚
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
[PATH] ã«æ‰€åœ¨
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
æ–°ã—ã„シャツをæŒã¡ç‰©ã‹ã‚‰ã‚¢ãƒã‚¿ãƒ¼ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦è£…ç€ã—ã¾ã—ょã†ã€‚
完全ã«æ–°è¦ã®çŠ¶æ…‹ã‹ã‚‰ä½œæˆã—ã¦è£…ç€ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
ã‚ãªãŸã¯ã“ã®æœã®ä¿®æ­£ã‚’許ã•ã‚Œã¦ã„ã¾ã›ã‚“。
</text>
<text name="Item Action Label">
@@ -193,32 +189,32 @@
</panel>
<panel label="ズボン" name="Pants">
<texture_picker label="生地" name="Fabric" tool_tip="写真をクリックã—ã¦é¸æŠž"/>
- <color_swatch label="色ï¼æ˜Žæš—" name="Color/Tint" tool_tip="カラー・ピッカーをクリックã—ã¦é–‹ã"/>
+ <color_swatch label="色ï¼æ˜Žæš—" name="Color/Tint" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
<button label="æ–°ã—ã„ズボンを作æˆ" label_selected="æ–°ã—ã„ズボンを作æˆ" name="Create New"/>
<button label="å–り外ã™" label_selected="å–り外ã™" name="Take Off"/>
<button label="ä¿å­˜" label_selected="ä¿å­˜" name="Save"/>
<button label="別åã§ä¿å­˜..." label_selected="別åã§ä¿å­˜..." name="Save As"/>
<button label="戻ã™" label_selected="戻ã™" name="Revert"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: 修正ã§ãã¾ã›ã‚“。
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: ロード中...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: 未装ç€ã€‚
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
[PATH] ã«æ‰€åœ¨
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
æ–°ã—ã„ズボンをæŒã¡ç‰©ã‹ã‚‰ã‚¢ãƒã‚¿ãƒ¼ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦è£…ç€ã—ã¾ã—ょã†ã€‚
完全ã«æ–°è¦ã®çŠ¶æ…‹ã‹ã‚‰ä½œæˆã—ã¦è£…ç€ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
ã‚ãªãŸã¯ã“ã®æœã®ä¿®æ­£ã‚’許ã•ã‚Œã¦ã„ã¾ã›ã‚“。
</text>
<text name="Item Action Label">
@@ -226,33 +222,33 @@
</text>
</panel>
<panel label="é´" name="Shoes">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: 修正ã§ãã¾ã›ã‚“。
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: ロード中...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: 未装ç€ã€‚
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
[PATH] ã«æ‰€åœ¨
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
æ–°ã—ã„é´ã‚’æŒã¡ç‰©ã‹ã‚‰ã‚¢ãƒã‚¿ãƒ¼ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦è£…ç€ã—ã¾ã—ょã†ã€‚
完全ã«æ–°è¦ã®çŠ¶æ…‹ã‹ã‚‰ä½œæˆã—ã¦è£…ç€ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
ã‚ãªãŸã¯ã“ã®æœã®ä¿®æ­£ã‚’許ã•ã‚Œã¦ã„ã¾ã›ã‚“。
</text>
<text name="Item Action Label">
é´ï¼š
</text>
<texture_picker label="生地" name="Fabric" tool_tip="写真をクリックã—ã¦é¸æŠž"/>
- <color_swatch label="色ï¼æ˜Žæš—" name="Color/Tint" tool_tip="カラー・ピッカーをクリックã—ã¦é–‹ã"/>
+ <color_swatch label="色ï¼æ˜Žæš—" name="Color/Tint" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
<button label="æ–°ã—ã„é´ã‚’作æˆ" label_selected="æ–°ã—ã„é´ã‚’作æˆ" name="Create New"/>
<button label="å–り外ã™" label_selected="å–り外ã™" name="Take Off"/>
<button label="ä¿å­˜" label_selected="ä¿å­˜" name="Save"/>
@@ -260,33 +256,33 @@
<button label="戻ã™" label_selected="戻ã™" name="Revert"/>
</panel>
<panel label="é´ä¸‹" name="Socks">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: 修正ã§ãã¾ã›ã‚“。
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: ロード中...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: 未装ç€ã€‚
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
[PATH] ã«æ‰€åœ¨
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
æ–°ã—ã„é´ä¸‹ã‚’æŒã¡ç‰©ã‹ã‚‰ã‚¢ãƒã‚¿ãƒ¼ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦è£…ç€ã—ã¾ã—ょã†ã€‚
完全ã«æ–°è¦ã®çŠ¶æ…‹ã‹ã‚‰ä½œæˆã—ã¦è£…ç€ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
ã‚ãªãŸã¯ã“ã®æœã®ä¿®æ­£ã‚’許ã•ã‚Œã¦ã„ã¾ã›ã‚“。
</text>
<text name="Item Action Label">
é´ä¸‹ï¼š
</text>
<texture_picker label="生地" name="Fabric" tool_tip="写真をクリックã—ã¦é¸æŠž"/>
- <color_swatch label="色ï¼æ˜Žæš—" name="Color/Tint" tool_tip="カラー・ピッカーをクリックã—ã¦é–‹ã"/>
+ <color_swatch label="色ï¼æ˜Žæš—" name="Color/Tint" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
<button label="æ–°ã—ã„é´ä¸‹ã‚’作æˆ" label_selected="æ–°ã—ã„é´ä¸‹ã‚’作æˆ" name="Create New"/>
<button label="å–り外ã™" label_selected="å–り外ã™" name="Take Off"/>
<button label="ä¿å­˜" label_selected="ä¿å­˜" name="Save"/>
@@ -294,26 +290,26 @@
<button label="戻ã™" label_selected="戻ã™" name="Revert"/>
</panel>
<panel label="上ç€" name="Jacket">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: 修正ã§ãã¾ã›ã‚“。
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: ロード中...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: 未装ç€ã€‚
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
[PATH] ã«æ‰€åœ¨
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
æ–°ã—ã„上ç€ã‚’æŒã¡ç‰©ã‹ã‚‰ã‚¢ãƒã‚¿ãƒ¼ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦è£…ç€ã—ã¾ã—ょã†ã€‚
完全ã«æ–°è¦ã®çŠ¶æ…‹ã‹ã‚‰ä½œæˆã—ã¦è£…ç€ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
ã‚ãªãŸã¯ã“ã®æœã®ä¿®æ­£ã‚’許ã•ã‚Œã¦ã„ã¾ã›ã‚“。
</text>
<text name="Item Action Label">
@@ -321,7 +317,7 @@
</text>
<texture_picker label="上åŠèº«ã®ç”Ÿåœ°" name="Upper Fabric" tool_tip="写真をクリックã—ã¦é¸æŠž"/>
<texture_picker label="下層生地" name="Lower Fabric" tool_tip="写真をクリックã—ã¦é¸æŠž"/>
- <color_swatch label="色ï¼æ˜Žæš—" name="Color/Tint" tool_tip="カラー・ピッカーをクリックã—ã¦é–‹ã"/>
+ <color_swatch label="色ï¼æ˜Žæš—" name="Color/Tint" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
<button label="æ–°ã—ã„上ç€ã‚’作æˆ" label_selected="æ–°ã—ã„上ç€ã‚’作æˆ" name="Create New"/>
<button label="å–り外ã™" label_selected="å–り外ã™" name="Take Off"/>
<button label="ä¿å­˜" label_selected="ä¿å­˜" name="Save"/>
@@ -329,33 +325,33 @@
<button label="戻ã™" label_selected="戻ã™" name="Revert"/>
</panel>
<panel label="手袋" name="Gloves">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: 修正ã§ãã¾ã›ã‚“。
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: ロード中...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: 未装ç€ã€‚
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
[PATH] ã«æ‰€åœ¨
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
æ–°ã—ã„手袋をæŒã¡ç‰©ã‹ã‚‰ã‚¢ãƒã‚¿ãƒ¼ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦è£…ç€ã—ã¾ã—ょã†ã€‚
完全ã«æ–°è¦ã®çŠ¶æ…‹ã‹ã‚‰ä½œæˆã—ã¦è£…ç€ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
ã‚ãªãŸã¯ã“ã®æœã®ä¿®æ­£ã‚’許ã•ã‚Œã¦ã„ã¾ã›ã‚“。
</text>
<text name="Item Action Label">
手袋:
</text>
<texture_picker label="生地" name="Fabric" tool_tip="写真をクリックã—ã¦é¸æŠž"/>
- <color_swatch label="色ï¼æ˜Žæš—" name="Color/Tint" tool_tip="カラー・ピッカーをクリックã—ã¦é–‹ã"/>
+ <color_swatch label="色ï¼æ˜Žæš—" name="Color/Tint" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
<button label="æ–°ã—ã„手袋を作æˆ" label_selected="æ–°ã—ã„手袋を作æˆ" name="Create New"/>
<button label="å–り外ã™" label_selected="å–り外ã™" name="Take Off"/>
<button label="ä¿å­˜" label_selected="ä¿å­˜" name="Save"/>
@@ -363,33 +359,33 @@
<button label="戻ã™" label_selected="戻ã™" name="Revert"/>
</panel>
<panel label="下ç€ã‚·ãƒ£ãƒ„" name="Undershirt">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: 修正ã§ãã¾ã›ã‚“。
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: ロード中...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: 未装ç€ã€‚
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
[PATH] ã«æ‰€åœ¨
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
æ–°ã—ã„下ç€ã‚’æŒã¡ç‰©ã‹ã‚‰ã‚¢ãƒã‚¿ãƒ¼ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦è£…ç€ã—ã¾ã—ょã†ã€‚
完全ã«æ–°è¦ã®çŠ¶æ…‹ã‹ã‚‰ä½œæˆã—ã¦è£…ç€ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
ã‚ãªãŸã¯ã“ã®æœã®ä¿®æ­£ã‚’許ã•ã‚Œã¦ã„ã¾ã›ã‚“。
</text>
<text name="Item Action Label">
下ç€ã‚·ãƒ£ãƒ„:
</text>
<texture_picker label="生地" name="Fabric" tool_tip="写真をクリックã—ã¦é¸æŠž"/>
- <color_swatch label="色ï¼æ˜Žæš—" name="Color/Tint" tool_tip="カラー・ピッカーをクリックã—ã¦é–‹ã"/>
+ <color_swatch label="色ï¼æ˜Žæš—" name="Color/Tint" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
<button label="æ–°ã—ã„下ç€ã‚·ãƒ£ãƒ„を作æˆ" label_selected="æ–°ã—ã„下ç€ã‚·ãƒ£ãƒ„を作æˆ" name="Create New"/>
<button label="å–り外ã™" label_selected="å–り外ã™" name="Take Off"/>
<button label="ä¿å­˜" label_selected="ä¿å­˜" name="Save"/>
@@ -397,33 +393,33 @@
<button label="戻ã™" label_selected="戻ã™" name="Revert"/>
</panel>
<panel label="下ç€ãƒ‘ンツ" name="Underpants">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: 修正ã§ãã¾ã›ã‚“。
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: ロード中...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: 未装ç€ã€‚
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
[PATH] ã«æ‰€åœ¨
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
æ–°ã—ã„パンツをæŒã¡ç‰©ã‹ã‚‰ã‚¢ãƒã‚¿ãƒ¼ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦è£…ç€ã—ã¾ã—ょã†ã€‚
完全ã«æ–°è¦ã®çŠ¶æ…‹ã‹ã‚‰ä½œæˆã—ã¦è£…ç€ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
ã‚ãªãŸã¯ã“ã®æœã®ä¿®æ­£ã‚’許ã•ã‚Œã¦ã„ã¾ã›ã‚“。
</text>
<text name="Item Action Label">
下ç€ãƒ‘ンツ:
</text>
<texture_picker label="生地" name="Fabric" tool_tip="写真をクリックã—ã¦é¸æŠž"/>
- <color_swatch label="色ï¼æ˜Žæš—" name="Color/Tint" tool_tip="カラー・ピッカーをクリックã—ã¦é–‹ã"/>
+ <color_swatch label="色ï¼æ˜Žæš—" name="Color/Tint" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
<button label="æ–°ã—ã„パンツを作æˆ" label_selected="æ–°ã—ã„パンツを作æˆ" name="Create New"/>
<button label="å–り外ã™" label_selected="å–り外ã™" name="Take Off"/>
<button label="ä¿å­˜" label_selected="ä¿å­˜" name="Save"/>
@@ -431,41 +427,113 @@
<button label="戻ã™" label_selected="戻ã™" name="Revert"/>
</panel>
<panel label="スカート" name="Skirt">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: 修正ã§ãã¾ã›ã‚“。
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: ロード中...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: 未装ç€ã€‚
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
[PATH] ã«æ‰€åœ¨
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
æ–°ã—ã„スカートをæŒç‰©ã‹ã‚‰ã‚¢ãƒã‚¿ãƒ¼ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦è£…ç€ã—ã¾ã—ょã†ã€‚
完全ã«æ–°è¦ã®çŠ¶æ…‹ã‹ã‚‰ä½œæˆã—ã¦è£…ç€ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
ã‚ãªãŸã¯ã“ã®æœã®ä¿®æ­£ã‚’許ã•ã‚Œã¦ã„ã¾ã›ã‚“。
</text>
<text name="Item Action Label">
スカート:
</text>
<texture_picker label="生地" name="Fabric" tool_tip="写真をクリックã—ã¦é¸æŠž"/>
- <color_swatch label="色ï¼æ˜Žæš—" name="Color/Tint" tool_tip="カラー・ピッカーをクリックã—ã¦é–‹ã"/>
+ <color_swatch label="色ï¼æ˜Žæš—" name="Color/Tint" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
<button label="スカートを作æˆ" label_selected="スカートを作æˆ" name="Create New"/>
<button label="å–り外ã™" label_selected="å–り外ã™" name="Take Off"/>
<button label="ä¿å­˜" label_selected="ä¿å­˜" name="Save"/>
<button label="別åã§ä¿å­˜..." label_selected="別åã§ä¿å­˜..." name="Save As"/>
<button label="戻ã™" label_selected="戻ã™" name="Revert"/>
</panel>
+ <panel label="アルファ" name="Alpha">
+ <text name="title">
+ [DESC]
+ </text>
+ <text name="title_no_modify">
+ [DESC]: 修正ä¸å¯
+ </text>
+ <text name="title_loading">
+ [DESC]: ローディング...
+ </text>
+ <text name="title_not_worn">
+ [DESC]: 未ç€ç”¨
+ </text>
+ <text name="path">
+ å‚ç…§ [PATH]
+ </text>
+ <text name="not worn instructions">
+ ã‚ãªãŸã®æŒã¡ç‰©ã‹ã‚‰ã‚¢ãƒã‚¿ãƒ¼ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦ã€æ–°ã—ã„アルファマスクをã¤ã‘ã¾ã™ã€‚
+代ã‚ã‚Šã«ã€ã¯ã˜ã‚ã‹ã‚‰æ–°ã—ã作æˆã—ã¦ç€ç”¨ã§ãã¾ã™ã€‚
+ </text>
+ <text name="no modify instructions">
+ ã“ã®ç€ç”¨ç‰©ã‚’修正ã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“。
+ </text>
+ <text name="Item Action Label">
+ アルファ:
+ </text>
+ <texture_picker label="アルファ(下)" name="Lower Alpha" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <texture_picker label="アルファ(上)" name="Upper Alpha" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <texture_picker label="頭部ã®ã‚¢ãƒ«ãƒ•ã‚¡" name="Head Alpha" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <texture_picker label="ç›®ã®ã‚¢ãƒ«ãƒ•ã‚¡" name="Eye Alpha" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <texture_picker label="髪ã®ã‚¢ãƒ«ãƒ•ã‚¡" name="Hair Alpha" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <button label="æ–°ã—ã„アルファを作æˆ" label_selected="æ–°ã—ã„アルファを作æˆ" name="Create New"/>
+ <button label="å–り外ã™" label_selected="å–り外ã™" name="Take Off"/>
+ <button label="ä¿å­˜" label_selected="ä¿å­˜" name="Save"/>
+ <button label="別åã§ä¿å­˜..." label_selected="別åã§ä¿å­˜..." name="Save As"/>
+ <button label="å…ƒã«æˆ»ã™" label_selected="å…ƒã«æˆ»ã™" name="Revert"/>
+ </panel>
+ <panel label="タトゥ" name="Tattoo">
+ <text name="title">
+ [DESC]
+ </text>
+ <text name="title_no_modify">
+ [DESC]: 修正ä¸å¯
+ </text>
+ <text name="title_loading">
+ [DESC]: ローディング...
+ </text>
+ <text name="title_not_worn">
+ [DESC]: 未ç€ç”¨
+ </text>
+ <text name="path">
+ å‚ç…§ [PATH]
+ </text>
+ <text name="not worn instructions">
+ ã‚ãªãŸã®æŒã¡ç‰©ã‹ã‚‰ã‚¢ãƒã‚¿ãƒ¼ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦ã€æ–°ã—ã„タトゥをã¤ã‘ã¾ã™ã€‚
+代ã‚ã‚Šã«ã€ã¯ã˜ã‚ã‹ã‚‰æ–°ã—ã作æˆã—ã¦ç€ç”¨ã§ãã¾ã™ã€‚
+ </text>
+ <text name="no modify instructions">
+ ã“ã®ç€ç”¨ç‰©ã‚’修正ã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“。
+ </text>
+ <text name="Item Action Label">
+ タトゥ:
+ </text>
+ <texture_picker label="頭部ã®ã‚¿ãƒˆã‚¥ãƒ¼" name="Head Tattoo" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <texture_picker label="上部ã®ã‚¿ãƒˆã‚¥ãƒ¼" name="Upper Tattoo" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <texture_picker label="下部ã®ã‚¿ãƒˆã‚¥ãƒ¼" name="Lower Tattoo" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <button label="æ–°ã—ã„タトゥを作æˆ" label_selected="æ–°ã—ã„タトゥを作æˆ" name="Create New"/>
+ <button label="å–り外ã™" label_selected="å–り外ã™" name="Take Off"/>
+ <button label="ä¿å­˜" label_selected="ä¿å­˜" name="Save"/>
+ <button label="別åã§ä¿å­˜..." label_selected="別åã§ä¿å­˜..." name="Save As"/>
+ <button label="å…ƒã«æˆ»ã™" label_selected="å…ƒã«æˆ»ã™" name="Revert"/>
+ </panel>
</tab_container>
+ <button label="アウトフィット作æˆ" label_selected="アウトフィット作æˆ" name="make_outfit_btn"/>
<button label="キャンセル" label_selected="キャンセル" name="Cancel"/>
<button label="OK" label_selected="OK" name="Ok"/>
- <button label="æœè£…を作æˆ..." label_selected="æœè£…を作æˆ..." name="Make Outfit"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_device_settings.xml b/indra/newview/skins/default/xui/ja/floater_device_settings.xml
index 5c258df9fd..3ae7356fb6 100644
--- a/indra/newview/skins/default/xui/ja/floater_device_settings.xml
+++ b/indra/newview/skins/default/xui/ja/floater_device_settings.xml
@@ -1,2 +1,2 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_device_settings" title="ボイスãƒãƒ£ãƒƒãƒˆæ©Ÿå™¨ã®è¨­å®š" /> \ No newline at end of file
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_device_settings" title="ボイスãƒãƒ£ãƒƒãƒˆæ©Ÿå™¨ã®è¨­å®š"/>
diff --git a/indra/newview/skins/default/xui/ja/floater_env_settings.xml b/indra/newview/skins/default/xui/ja/floater_env_settings.xml
index 48c22323f8..1d5f26a6eb 100644
--- a/indra/newview/skins/default/xui/ja/floater_env_settings.xml
+++ b/indra/newview/skins/default/xui/ja/floater_env_settings.xml
@@ -1,5 +1,8 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Environment Editor Floater" title="環境編集">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Environment Editor Floater" title="自然環境エディター">
+ <floater.string name="timeStr">
+ [hour12,datetime,utc]:[min,datetime,utc] [ampm,datetime,utc]
+ </floater.string>
<text name="EnvTimeText">
時刻
</text>
@@ -12,13 +15,11 @@
<text name="EnvWaterColorText">
æ°´ã®è‰²
</text>
- <color_swatch name="EnvWaterColor"
- tool_tip="カラー・ピッカーをクリックã—ã¦é–‹ã" />
+ <color_swatch name="EnvWaterColor" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
<text name="EnvWaterFogText">
水中照度
</text>
- <button label="ä¸å‹•ç”£ã®æ™‚刻を使用" name="EnvUseEstateTimeButton" />
- <button label="空ã®é«˜åº¦ãªè¨­å®š" name="EnvAdvancedSkyButton" />
- <button label="æ°´ã®é«˜åº¦ãªè¨­å®š" name="EnvAdvancedWaterButton" />
- <button label="?" name="EnvSettingsHelpButton" />
+ <button label="ä¸å‹•ç”£ã®æ™‚刻を使用" name="EnvUseEstateTimeButton"/>
+ <button label="空ã®é«˜åº¦ãªè¨­å®š" name="EnvAdvancedSkyButton"/>
+ <button label="æ°´ã®é«˜åº¦ãªè¨­å®š" name="EnvAdvancedWaterButton"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_first_time_tip.xml b/indra/newview/skins/default/xui/ja/floater_first_time_tip.xml
new file mode 100644
index 0000000000..fce9185b8a
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_first_time_tip.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="set_name_in_the_cladd">
+ <check_box label="クイックヒントをオフã«ã™ã‚‹" name="DontShowFirstTimeTip_checkbox"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_gesture.xml b/indra/newview/skins/default/xui/ja/floater_gesture.xml
index 66be1f7d84..a79854bcef 100644
--- a/indra/newview/skins/default/xui/ja/floater_gesture.xml
+++ b/indra/newview/skins/default/xui/ja/floater_gesture.xml
@@ -1,17 +1,27 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="gestures" title="アクティブ・ジェスãƒãƒ£ãƒ¼">
- <text name="help_label">
- ジェスãƒãƒ£ãƒ¼ã‚’ダブルクリックã—ã¦ã€&#10;アニメーションã¨ã‚µã‚¦ãƒ³ãƒ‰ã‚’å†ç”Ÿã€‚
- </text>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater label="場所" name="gestures" title="ジェスãƒãƒ£ãƒ¼">
+ <floater.string name="loading">
+ ローディング...
+ </floater.string>
+ <floater.string name="playing">
+ (å†ç”Ÿä¸­ï¼‰
+ </floater.string>
+ <floater.string name="copy_name">
+ [COPY_NAME] ã®ã‚³ãƒ”ー
+ </floater.string>
<scroll_list bottom_delta="-385" height="360" name="gesture_list">
- <column label="トリガ" name="trigger" />
- <column label="キー" name="shortcut" />
- <column label="" name="key" />
- <column label="åå‰" name="name" />
+ <scroll_list.columns label="åå‰" name="name"/>
+ <scroll_list.columns label="ãƒãƒ£ãƒƒãƒˆ" name="trigger"/>
+ <scroll_list.columns label="" name="key"/>
+ <scroll_list.columns label="キー" name="shortcut"/>
</scroll_list>
- <button label="æ–°è¦" name="new_gesture_btn" />
- <button label="æŒã¡ç‰©" name="inventory_btn" />
- <button label="編集" name="edit_btn" />
- <button label="å†ç”Ÿ" name="play_btn" />
- <button label="åœæ­¢" name="stop_btn" />
+ <panel label="bottom_panel" name="bottom_panel">
+ <menu_button name="gear_btn" tool_tip="詳細オプション"/>
+ <button name="new_gesture_btn" tool_tip="æ–°è¦ã‚¸ã‚§ã‚¹ãƒãƒ£ãƒ¼ã‚’作æˆ"/>
+ <button name="activate_btn" tool_tip="é¸æŠžã—ãŸã‚¸ã‚§ã‚¹ãƒãƒ£ãƒ¼ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ™ãƒ¼ãƒˆã®æœ‰ç„¡"/>
+ <button name="del_btn" tool_tip="ã“ã®ã‚¸ã‚§ã‚¹ãƒãƒ£ãƒ¼ã‚’削除"/>
+ </panel>
+ <button label="編集" name="edit_btn"/>
+ <button label="å†ç”Ÿ" name="play_btn"/>
+ <button label="åœæ­¢" name="stop_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_god_tools.xml b/indra/newview/skins/default/xui/ja/floater_god_tools.xml
index d91744c391..25de45c094 100644
--- a/indra/newview/skins/default/xui/ja/floater_god_tools.xml
+++ b/indra/newview/skins/default/xui/ja/floater_god_tools.xml
@@ -1,57 +1,37 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="godtools floater" title="ゴッド・ツール">
<tab_container name="GodTools Tabs">
<panel label="グリッド" name="grid">
- <button label="ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’追ã„出ã™"
- label_selected="ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’追ã„出ã™"
- name="Kick all users" />
- <button label="ã“ã®åœ°åŸŸã®åœ°å›³ã®è¡¨ç¤ºã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’消去"
- label_selected="ã“ã®åœ°åŸŸã®åœ°å›³ã®è¡¨ç¤ºã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’消去"
- name="Flush This Region&apos;s Map Visibility Caches" />
+ <button label="ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’追ã„出ã™" label_selected="ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’追ã„出ã™" name="Kick all users"/>
+ <button label="ã“ã®åœ°åŸŸã®åœ°å›³ã®è¡¨ç¤ºã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’消去" label_selected="ã“ã®åœ°åŸŸã®åœ°å›³ã®è¡¨ç¤ºã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’消去" name="Flush This Region&apos;s Map Visibility Caches"/>
</panel>
<panel label="地域" name="region">
<text name="Sim Name:">
シムå:
</text>
- <check_box label="準備" name="check prelude"
- tool_tip="ã“ã®è¨­å®šã«ã‚ˆã‚Šã€ã“ã®åœ°åŸŸã®æº–備をã—ã¾ã™ã€‚" />
- <check_box label="太陽固定" name="check fixed sun"
- tool_tip="太陽ä½ç½®ã‚’固定([地域ï¼ä¸å‹•ç”£]>[地形]ã®å ´åˆã¨åŒæ§˜ï¼‰" />
- <check_box label="テレãƒãƒ¼ãƒˆã®ãƒ›ãƒ¼ãƒ ã‚’リセット" name="check reset home"
- tool_tip="ä½äººãŒãƒ†ãƒ¬ãƒãƒ¼ãƒˆã§åŽ»ã£ãŸã¨ãã€å½¼ã‚‰ã®ãƒ›ãƒ¼ãƒ ã‚’目的地ã«ãƒªã‚»ãƒƒãƒˆã™ã‚‹ã€‚" />
- <check_box label="å¯è¦–" name="check visible"
- tool_tip="ã“ã®è¨­å®šã«ã‚ˆã‚Šã€ã“ã®åœ°åŸŸã‚’ゴッド・モード以外ã§ã‚‚å¯è¦–ã«ã—ã¾ã™ã€‚" />
- <check_box label="ダメージ" name="check damage"
- tool_tip="ã“ã®è¨­å®šã«ã‚ˆã‚Šã€ã“ã®åœ°åŸŸå†…ã§ãƒ€ãƒ¡ãƒ¼ã‚¸ã‚’有効化ã—ã¾ã™ã€‚" />
- <check_box label="トラフィック・トラッキングをブロック"
- name="block dwell"
- tool_tip="ã“ã®è¨­å®šã«ã‚ˆã‚Šã€ã“ã®åœ°åŸŸå†…ã®ãƒˆãƒ©ãƒ•ã‚£ãƒƒã‚¯è¨ˆç®—をオフã«ã—ã¾ã™ã€‚" />
- <check_box label="土地整備をブロック" name="block terraform"
- tool_tip="ã“ã®è¨­å®šã«ã‚ˆã‚Šã€ã“ã®åœ°åŸŸå†…ã§ã®åœŸåœ°æ•´å‚™ã‚’ç¦æ­¢" />
- <check_box label="サンドボックス" name="is sandbox"
- tool_tip="ã“ã‚ŒãŒã‚µãƒ³ãƒ‰ãƒœãƒƒã‚¯ã‚¹åœ°åŸŸã§ã‚‚切り替ãˆ" />
- <button label="地形を構築ã™ã‚‹" label_selected="地形を構築ã™ã‚‹"
- name="Bake Terrain"
- tool_tip="ç¾åœ¨ã®åœ°å½¢ã‚’デフォルトã¨ã—ã¦ä¿å­˜ã—ã¾ã™ã€‚" />
- <button label="地形を元ã«æˆ»ã™" label_selected="地形を元ã«æˆ»ã™"
- name="Revert Terrain"
- tool_tip="ç¾åœ¨ã®åœ°å½¢ã‚’デフォルトã«ç½®æ›ã—ã¾ã™ã€‚" />
- <button label="地形を交æ›" label_selected="地形を交æ›" name="Swap Terrain"
- tool_tip="ç¾åœ¨ã®åœ°å½¢ã‚’デフォルトã¨å…¥ã‚Œæ›¿ãˆã¾ã™ã€‚" />
+ <check_box label="準備" name="check prelude" tool_tip="ã“ã®è¨­å®šã«ã‚ˆã‚Šã€ã“ã®åœ°åŸŸã®æº–備をã—ã¾ã™ã€‚"/>
+ <check_box label="太陽固定" name="check fixed sun" tool_tip="太陽ä½ç½®ã‚’固定([地域ï¼ä¸å‹•ç”£]>[地形]ã®å ´åˆã¨åŒæ§˜ï¼‰"/>
+ <check_box label="テレãƒãƒ¼ãƒˆã®ãƒ›ãƒ¼ãƒ ã‚’リセット" name="check reset home" tool_tip="ä½äººãŒãƒ†ãƒ¬ãƒãƒ¼ãƒˆã§åŽ»ã£ãŸã¨ãã€å½¼ã‚‰ã®ãƒ›ãƒ¼ãƒ ã‚’目的地ã«ãƒªã‚»ãƒƒãƒˆã™ã‚‹ã€‚"/>
+ <check_box label="å¯è¦–" name="check visible" tool_tip="ã“ã®è¨­å®šã«ã‚ˆã‚Šã€ã“ã®åœ°åŸŸã‚’ゴッド・モード以外ã§ã‚‚å¯è¦–ã«ã—ã¾ã™ã€‚"/>
+ <check_box label="ダメージ" name="check damage" tool_tip="ã“ã®è¨­å®šã«ã‚ˆã‚Šã€ã“ã®åœ°åŸŸå†…ã§ãƒ€ãƒ¡ãƒ¼ã‚¸ã‚’有効化ã—ã¾ã™ã€‚"/>
+ <check_box label="トラフィック・トラッキングをブロック" name="block dwell" tool_tip="ã“ã®è¨­å®šã«ã‚ˆã‚Šã€ã“ã®åœ°åŸŸå†…ã®ãƒˆãƒ©ãƒ•ã‚£ãƒƒã‚¯è¨ˆç®—をオフã«ã—ã¾ã™ã€‚"/>
+ <check_box label="土地整備をブロック" name="block terraform" tool_tip="ã“ã®è¨­å®šã«ã‚ˆã‚Šã€ã“ã®åœ°åŸŸå†…ã§ã®åœŸåœ°æ•´å‚™ã‚’ç¦æ­¢"/>
+ <check_box label="サンドボックス" name="is sandbox" tool_tip="ã“ã‚ŒãŒã‚µãƒ³ãƒ‰ãƒœãƒƒã‚¯ã‚¹åœ°åŸŸã§ã‚‚切り替ãˆ"/>
+ <button label="地形を構築ã™ã‚‹" label_selected="地形を構築ã™ã‚‹" name="Bake Terrain" tool_tip="ç¾åœ¨ã®åœ°å½¢ã‚’デフォルトã¨ã—ã¦ä¿å­˜ã—ã¾ã™ã€‚"/>
+ <button label="地形を元ã«æˆ»ã™" label_selected="地形を元ã«æˆ»ã™" name="Revert Terrain" tool_tip="ç¾åœ¨ã®åœ°å½¢ã‚’デフォルトã«ç½®æ›ã—ã¾ã™ã€‚"/>
+ <button label="地形を交æ›" label_selected="地形を交æ›" name="Swap Terrain" tool_tip="ç¾åœ¨ã®åœ°å½¢ã‚’デフォルトã¨å…¥ã‚Œæ›¿ãˆã¾ã™ã€‚"/>
<text name="estate id">
ä¸å‹•ç”£ID:
</text>
<text name="parent id">
親ID:
</text>
- <line_editor name="parentestate" tool_tip="ã“ã‚Œã¯ã€ã“ã®åœ°åŸŸã®è¦ªä¸å‹•ç”£ã§ã™ã€‚" />
+ <line_editor name="parentestate" tool_tip="ã“ã‚Œã¯ã€ã“ã®åœ°åŸŸã®è¦ªä¸å‹•ç”£ã§ã™ã€‚"/>
<text name="Grid Pos: ">
グリッドä½ç½®ï¼š
</text>
- <line_editor name="gridposx"
- tool_tip="ã“ã‚Œã¯ã€ã“ã®åœ°åŸŸã®ã‚°ãƒªãƒƒãƒ‰xã®ä½ç½®ã§ã™ã€‚" />
- <line_editor name="gridposy"
- tool_tip="ã“ã‚Œã¯ã€ã“ã®åœ°åŸŸã®ã‚°ãƒªãƒƒãƒ‰yã®ä½ç½®ã§ã™ã€‚" />
+ <line_editor name="gridposx" tool_tip="ã“ã‚Œã¯ã€ã“ã®åœ°åŸŸã®ã‚°ãƒªãƒƒãƒ‰xã®ä½ç½®ã§ã™ã€‚"/>
+ <line_editor name="gridposy" tool_tip="ã“ã‚Œã¯ã€ã“ã®åœ°åŸŸã®ã‚°ãƒªãƒƒãƒ‰yã®ä½ç½®ã§ã™ã€‚"/>
<text name="Redirect to Grid: ">
グリッドã«ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆï¼š
</text>
@@ -61,96 +41,57 @@
<text name="land cost text">
平方メートル当ãŸã‚ŠL$:
</text>
- <button label="æ›´æ–°" label_selected="æ›´æ–°" name="Refresh"
- tool_tip="上記ã®æƒ…報を更新ã™ã‚‹ã«ã¯ã€ã“ã“をクリックã—ã¾ã™ã€‚" />
- <button label="é©ç”¨" label_selected="é©ç”¨" name="Apply"
- tool_tip="上記ã®å¤‰æ›´ã‚’é©ç”¨ã™ã‚‹ã«ã¯ã€ã“ã“をクリックã—ã¾ã™ã€‚" />
- <button label="地域をé¸æŠž" label_selected="地域をé¸æŠž" name="Select Region"
- tool_tip="土地ツールã§åœ°åŸŸå…¨ä½“ã‚’é¸æŠžã—ã¦ãã ã•ã„。" />
- <button label="ãŸã ã¡ã«è‡ªå‹•ä¿å­˜ã™ã‚‹"
- label_selected="ãŸã ã¡ã«è‡ªå‹•ä¿å­˜ã™ã‚‹" name="Autosave now"
- tool_tip="Gzip状態を自動ä¿å­˜ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ä¿å­˜ã—ã¾ã™ã€‚" />
+ <button label="æ›´æ–°" label_selected="æ›´æ–°" name="Refresh" tool_tip="上記ã®æƒ…報を更新ã™ã‚‹ã«ã¯ã€ã“ã“をクリックã—ã¾ã™ã€‚"/>
+ <button label="é©ç”¨" label_selected="é©ç”¨" name="Apply" tool_tip="上記ã®å¤‰æ›´ã‚’é©ç”¨ã™ã‚‹ã«ã¯ã€ã“ã“をクリックã—ã¾ã™ã€‚"/>
+ <button label="地域をé¸æŠž" label_selected="地域をé¸æŠž" name="Select Region" tool_tip="土地ツールã§åœ°åŸŸå…¨ä½“ã‚’é¸æŠžã—ã¦ãã ã•ã„。"/>
+ <button label="ãŸã ã¡ã«è‡ªå‹•ä¿å­˜ã™ã‚‹" label_selected="ãŸã ã¡ã«è‡ªå‹•ä¿å­˜ã™ã‚‹" name="Autosave now" tool_tip="Gzip状態を自動ä¿å­˜ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ä¿å­˜ã—ã¾ã™ã€‚"/>
</panel>
<panel label="オブジェクト" name="objects">
+ <panel.string name="no_target">
+ (ターゲットãªã—)
+ </panel.string>
<text name="Sim Name:">
シムå:
</text>
<text name="region name">
ウェルシュ
</text>
- <check_box label="スクリプトを無効化" name="disable scripts"
- tool_tip="ã“ã®è¨­å®šã«ã‚ˆã‚Šã€ã“ã®åœ°åŸŸå†…ã®ã‚¹ã‚¯ãƒªãƒ—トをã™ã¹ã¦ç„¡åŠ¹åŒ–" />
- <check_box label="è¡çªã‚’無効化" name="disable collisions"
- tool_tip="ã“ã®è¨­å®šã«ã‚ˆã‚Šã€ã“ã®åœ°åŸŸå†…ã®éžã‚¨ãƒ¼ã‚¸ã‚§ãƒ³ãƒˆè¡çªã‚’無効化" />
- <check_box label="物ç†ä½œç”¨ã‚’無効化" name="disable physics"
- tool_tip="ã“ã®è¨­å®šã«ã‚ˆã‚Šã€ã“ã®åœ°åŸŸå†…ã®ç‰©ç†çš„作用をã™ã¹ã¦ç„¡åŠ¹åŒ–" />
- <button label="é©ç”¨" label_selected="é©ç”¨" name="Apply"
- tool_tip="上記ã®å¤‰æ›´ã‚’é©ç”¨ã™ã‚‹ã«ã¯ã€ã“ã“をクリックã—ã¾ã™ã€‚" />
- <button label="対象ã®è¨­å®š" label_selected="対象ã®è¨­å®š" name="Set Target"
- tool_tip="オブジェクト削除ã®å¯¾è±¡ã¨ãªã‚‹ã‚¢ãƒã‚¿ãƒ¼ã‚’設定ã—ã¦ãã ã•ã„。" />
+ <check_box label="スクリプトを無効化" name="disable scripts" tool_tip="ã“ã®è¨­å®šã«ã‚ˆã‚Šã€ã“ã®åœ°åŸŸå†…ã®ã‚¹ã‚¯ãƒªãƒ—トをã™ã¹ã¦ç„¡åŠ¹åŒ–"/>
+ <check_box label="è¡çªã‚’無効化" name="disable collisions" tool_tip="ã“ã®è¨­å®šã«ã‚ˆã‚Šã€ã“ã®åœ°åŸŸå†…ã®éžã‚¨ãƒ¼ã‚¸ã‚§ãƒ³ãƒˆè¡çªã‚’無効化"/>
+ <check_box label="物ç†ä½œç”¨ã‚’無効化" name="disable physics" tool_tip="ã“ã®è¨­å®šã«ã‚ˆã‚Šã€ã“ã®åœ°åŸŸå†…ã®ç‰©ç†çš„作用をã™ã¹ã¦ç„¡åŠ¹åŒ–"/>
+ <button label="é©ç”¨" label_selected="é©ç”¨" name="Apply" tool_tip="上記ã®å¤‰æ›´ã‚’é©ç”¨ã™ã‚‹ã«ã¯ã€ã“ã“をクリックã—ã¾ã™ã€‚"/>
+ <button label="対象ã®è¨­å®š" label_selected="対象ã®è¨­å®š" name="Set Target" tool_tip="オブジェクト削除ã®å¯¾è±¡ã¨ãªã‚‹ã‚¢ãƒã‚¿ãƒ¼ã‚’設定ã—ã¦ãã ã•ã„。"/>
<text name="target_avatar_name">
(対象ãªã—)
</text>
- <button
- label="ä»–ã®åœŸåœ°ã«ãŠã‘る対象ã®ã‚¹ã‚¯ãƒªãƒ—ト・オブジェクトを削除"
- label_selected="ä»–ã®åœŸåœ°ã«ãŠã‘る対象ã®ã‚¹ã‚¯ãƒªãƒ—ト・オブジェクトを削除"
- name="Delete Target&apos;s Scripted Objects On Others Land"
- tool_tip="ã“ã®åœ°åŸŸã«ãŠã„ã¦å¯¾è±¡ãŒæ‰€æœ‰ã—ã¦ã„ãªã„スクリプト・オブジェクトをã™ã¹ã¦å‰Šé™¤ã—ã¾ã™ã€‚ (コピーç¦æ­¢ï¼‰ã‚ªãƒ–ジェクトã¯è¿”å´ã•ã‚Œã¾ã™ã€‚" />
- <button
- label="「ã™ã¹ã¦ã®ã€åœŸåœ°ã«ãŠã‘る対象ã®ã‚¹ã‚¯ãƒªãƒ—ト・オブジェクトを削除"
- label_selected="「ã™ã¹ã¦ã®ã€åœŸåœ°ã«ãŠã‘る対象ã®ã‚¹ã‚¯ãƒªãƒ—ト・オブジェクトを削除"
- name="Delete Target&apos;s Scripted Objects On *Any* Land"
- tool_tip="ã“ã®åœ°åŸŸã«ãŠã„ã¦å¯¾è±¡ãŒæ‰€æœ‰ã—ã¦ã„るスクリプト・オブジェクトをã™ã¹ã¦å‰Šé™¤ã—ã¾ã™ã€‚ (コピーç¦æ­¢ï¼‰ã‚ªãƒ–ジェクトã¯è¿”å´ã•ã‚Œã¾ã™ã€‚" />
- <button label="対象ã®ã‚ªãƒ–ジェクトを「ã™ã¹ã¦ã€å‰Šé™¤"
- label_selected="対象ã®ã‚ªãƒ–ジェクトを「ã™ã¹ã¦ã€å‰Šé™¤"
- name="Delete *ALL* Of Target&apos;s Objects"
- tool_tip="ã“ã®åœ°åŸŸã«ãŠã„ã¦å¯¾è±¡ãŒæ‰€æœ‰ã—ã¦ã„るオブジェクトをã™ã¹ã¦å‰Šé™¤ã—ã¾ã™ã€‚ (コピーç¦æ­¢ï¼‰ã‚ªãƒ–ジェクトã¯è¿”å´ã•ã‚Œã¾ã™ã€‚" />
- <button label="トップ・コライダーをå–å¾—"
- label_selected="トップ・コライダーをå–å¾—"
- name="Get Top Colliders"
- tool_tip="最も段階ã®ç‹­ã„コールãƒãƒƒã‚¯ãŒç™ºç”Ÿã—ãŸã‚ªãƒ–ジェクトã®ãƒªã‚¹ãƒˆã‚’å–å¾—ã—ã¾ã™ã€‚" />
- <button label="トップ・スクリプトをå–å¾—"
- label_selected="トップ・スクリプトをå–å¾—"
- name="Get Top Scripts"
- tool_tip="スクリプトã®èµ·å‹•ã«æœ€ã‚‚時間を費やã—ã¦ã„るオブジェクトã®ãƒªã‚¹ãƒˆã‚’å–å¾—ã—ã¾ã™ã€‚" />
- <button label="スクリプト・ダイジェスト"
- label_selected="スクリプト・ダイジェスト" name="Scripts digest"
- tool_tip="ã™ã¹ã¦ã®ã‚¹ã‚¯ãƒªãƒ—トã¨ãれらã®ä½¿ç”¨å›žæ•°ã®ãƒªã‚¹ãƒˆã‚’å–å¾—ã—ã¾ã™ã€‚" />
+ <button label="ä»–ã®åœŸåœ°ã«ãŠã‘る対象ã®ã‚¹ã‚¯ãƒªãƒ—ト・オブジェクトを削除" label_selected="ä»–ã®åœŸåœ°ã«ãŠã‘る対象ã®ã‚¹ã‚¯ãƒªãƒ—ト・オブジェクトを削除" name="Delete Target&apos;s Scripted Objects On Others Land" tool_tip="ã“ã®åœ°åŸŸã«ãŠã„ã¦å¯¾è±¡ãŒæ‰€æœ‰ã—ã¦ã„ãªã„スクリプト・オブジェクトをã™ã¹ã¦å‰Šé™¤ã—ã¾ã™ã€‚ (コピーç¦æ­¢ï¼‰ã‚ªãƒ–ジェクトã¯è¿”å´ã•ã‚Œã¾ã™ã€‚"/>
+ <button label="「ã™ã¹ã¦ã®ã€åœŸåœ°ã«ãŠã‘る対象ã®ã‚¹ã‚¯ãƒªãƒ—ト・オブジェクトを削除" label_selected="「ã™ã¹ã¦ã®ã€åœŸåœ°ã«ãŠã‘る対象ã®ã‚¹ã‚¯ãƒªãƒ—ト・オブジェクトを削除" name="Delete Target&apos;s Scripted Objects On *Any* Land" tool_tip="ã“ã®åœ°åŸŸã«ãŠã„ã¦å¯¾è±¡ãŒæ‰€æœ‰ã—ã¦ã„るスクリプト・オブジェクトをã™ã¹ã¦å‰Šé™¤ã—ã¾ã™ã€‚ (コピーç¦æ­¢ï¼‰ã‚ªãƒ–ジェクトã¯è¿”å´ã•ã‚Œã¾ã™ã€‚"/>
+ <button label="対象ã®ã‚ªãƒ–ジェクトを「ã™ã¹ã¦ã€å‰Šé™¤" label_selected="対象ã®ã‚ªãƒ–ジェクトを「ã™ã¹ã¦ã€å‰Šé™¤" name="Delete *ALL* Of Target&apos;s Objects" tool_tip="ã“ã®åœ°åŸŸã«ãŠã„ã¦å¯¾è±¡ãŒæ‰€æœ‰ã—ã¦ã„るオブジェクトをã™ã¹ã¦å‰Šé™¤ã—ã¾ã™ã€‚ (コピーç¦æ­¢ï¼‰ã‚ªãƒ–ジェクトã¯è¿”å´ã•ã‚Œã¾ã™ã€‚"/>
+ <button label="トップ・コライダーをå–å¾—" label_selected="トップ・コライダーをå–å¾—" name="Get Top Colliders" tool_tip="最も段階ã®ç‹­ã„コールãƒãƒƒã‚¯ãŒç™ºç”Ÿã—ãŸã‚ªãƒ–ジェクトã®ãƒªã‚¹ãƒˆã‚’å–å¾—ã—ã¾ã™ã€‚"/>
+ <button label="トップ・スクリプトをå–å¾—" label_selected="トップ・スクリプトをå–å¾—" name="Get Top Scripts" tool_tip="スクリプトã®èµ·å‹•ã«æœ€ã‚‚時間を費やã—ã¦ã„るオブジェクトã®ãƒªã‚¹ãƒˆã‚’å–å¾—ã—ã¾ã™ã€‚"/>
+ <button label="スクリプト・ダイジェスト" label_selected="スクリプト・ダイジェスト" name="Scripts digest" tool_tip="ã™ã¹ã¦ã®ã‚¹ã‚¯ãƒªãƒ—トã¨ãれらã®ä½¿ç”¨å›žæ•°ã®ãƒªã‚¹ãƒˆã‚’å–å¾—ã—ã¾ã™ã€‚"/>
</panel>
<panel label="è¦æ±‚" name="request">
<text name="Destination:">
目的地:
</text>
<combo_box name="destination">
- <combo_item name="Selection">
- é¸æŠž
- </combo_item>
- <combo_item name="AgentRegion">
- エージェント地域
- </combo_item>
+ <combo_box.item label="é¸æŠž" name="item1"/>
+ <combo_box.item label="エージェント地域" name="item2"/>
</combo_box>
<text name="Request:">
è¦æ±‚:
</text>
<combo_box name="request">
- <combo_item name="colliders&lt;steps&gt;">
- コライダー<ステップ>
- </combo_item>
- <combo_item name="scripts&lt;count&gt;,&lt;optionalpattern&gt;">
- スクリプト<回数>ã€ï¼œã‚ªãƒ—ション・パターン>
- </combo_item>
- <combo_item name="objects&lt;pattern&gt;">
- オブジェクト<パターン>
- </combo_item>
- <combo_item name="rez&lt;asset_id&gt;">
- rez <asset_id>
- </combo_item>
+ <combo_box.item label="コライダー<ステップ>" name="item1"/>
+ <combo_box.item label="スクリプト<回数>ã€ï¼œã‚ªãƒ—ション・パターン>" name="item2"/>
+ <combo_box.item label="オブジェクト<パターン>" name="item3"/>
+ <combo_box.item label="rez <asset_id>" name="item4"/>
</combo_box>
<text name="Parameter:">
パラメーター:
</text>
- <button label="リクエストã™ã‚‹" label_selected="リクエストã™ã‚‹"
- name="Make Request" />
+ <button label="リクエストã™ã‚‹" label_selected="リクエストã™ã‚‹" name="Make Request"/>
</panel>
</tab_container>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_hardware_settings.xml b/indra/newview/skins/default/xui/ja/floater_hardware_settings.xml
index 2466dd5943..c5a2800e0e 100644
--- a/indra/newview/skins/default/xui/ja/floater_hardware_settings.xml
+++ b/indra/newview/skins/default/xui/ja/floater_hardware_settings.xml
@@ -1,42 +1,28 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Hardware Settings Floater" title="ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢è¨­å®š">
<text name="Filtering:">
フィルタリング:
</text>
- <check_box
- label="異方的フィルタリング(有効ã«ã™ã‚‹ã¨é€Ÿåº¦ãŒä½Žä¸‹ã—ã¾ã™ï¼‰"
- name="ani" />
+ <check_box label="異方的フィルタリング(有効ã«ã™ã‚‹ã¨é€Ÿåº¦ãŒä½Žä¸‹ã—ã¾ã™ï¼‰" name="ani"/>
<text name="Antialiasing:">
アンãƒã‚¨ã‚¤ãƒªã‚¢ã‚·ãƒ³ã‚°:
</text>
<combo_box label="アンãƒã‚¨ã‚¤ãƒªã‚¢ã‚·ãƒ³ã‚°" name="fsaa">
- <combo_item name="FSAADisabled">
- 無効
- </combo_item>
- <combo_item name="2x">
- 2x
- </combo_item>
- <combo_item name="4x">
- 4x
- </combo_item>
- <combo_item name="8x">
- 8x
- </combo_item>
- <combo_item name="16x">
- 16x
- </combo_item>
+ <combo_box.item label="無効" name="FSAADisabled"/>
+ <combo_box.item label="2x" name="2x"/>
+ <combo_box.item label="4x" name="4x"/>
+ <combo_box.item label="8x" name="8x"/>
+ <combo_box.item label="16x" name="16x"/>
</combo_box>
- <spinner label="ガンマ:" name="gamma" />
+ <spinner label="ガンマ:" name="gamma"/>
<text name="(brightness, lower is brighter)">
- (è¼åº¦ï¼šä½Žã„ï¼é«˜è¼åº¦ã€0ï¼ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆå€¤ï¼‰
+ (0 ã§ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã€ä½Žã„ã»ã©æ˜Žã‚‹ã„)
</text>
<text name="Enable VBO:">
VBO を有効化:
</text>
- <check_box label="OpenGL Vertex Buffer Objectsを有効化" name="vbo"
- tool_tip="最新ã®ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã§ã“ã®è¨­å®šã‚’有効ã«ã™ã‚‹ã¨ã€ãƒ‘フォーマンスãŒå‘上ã—ã¾ã™ã€‚ ã—ã‹ã—ã€æ—§åž‹ã®ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã§ã¯ VBO ã®å®Ÿè£…ãŒè²§å¼±ãªå ´åˆãŒå¤šãã€ã“ã®è¨­å®šã‚’有効ã«ã™ã‚‹ã“ã¨ã§ã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã«ã¤ãªãŒã‚‹ãŠãã‚ŒãŒã‚ã‚Šã¾ã™ã€‚" />
- <slider label="テクスãƒãƒ£ï¾’モリ(MB):" name="GrapicsCardTextureMemory"
- tool_tip="テクスãƒãƒ£ãƒ¼ã«å‰²ã‚Šå½“ã¦ã‚‹ãƒ¡ãƒ¢ãƒªã®åˆè¨ˆã€‚ ビデオ・カード・メモリをデフォルトã«ã—ã¾ã™ã€‚ ã“ã®æ•°å€¤ã‚’減らã™ã¨ã€ãƒ‘フォーマンスãŒæ”¹å–„ã•ã‚Œã¾ã™ãŒã€ãƒ†ã‚¯ã‚¹ãƒãƒ£ãƒ¼ãŒã¼ã‚„ã‘ãŸæ„Ÿã˜ã«ãªã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚" />
- <spinner label="フォグã®è·é›¢æ¯”率:" name="fog" />
- <button label="OK" label_selected="OK" name="OK" />
+ <check_box initial_value="true" label="OpenGL Vertex Buffer Objectsを有効化" name="vbo" tool_tip="最新ã®ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã§ã“ã®è¨­å®šã‚’有効ã«ã™ã‚‹ã¨ã€ãƒ‘フォーマンスãŒå‘上ã—ã¾ã™ã€‚ ã—ã‹ã—ã€æ—§åž‹ã®ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã§ã¯ VBO ã®å®Ÿè£…ãŒè²§å¼±ãªå ´åˆãŒå¤šãã€ã“ã®è¨­å®šã‚’有効ã«ã™ã‚‹ã“ã¨ã§ã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã«ã¤ãªãŒã‚‹ãŠãã‚ŒãŒã‚ã‚Šã¾ã™ã€‚"/>
+ <slider label="テクスãƒãƒ£ãƒ¡ãƒ¢ãƒªï¼ˆMB):" name="GraphicsCardTextureMemory" tool_tip="テクスãƒãƒ£ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚ŒãŸãƒ¡ãƒ¢ãƒªã®é‡ã€‚ ビデオカードã®ãƒ¡ãƒ¢ãƒªã«æ—¢å®šã€‚ 数値を下ã’ã‚‹ã¨ãƒ‘フォーマンスãŒå‘上ã—ã¾ã™ãŒã€ãƒ†ã‚¯ã‚¹ãƒãƒ£ã®ç²¾åº¦ãŒè½ã¡ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚"/>
+ <spinner label="フォグã®è·é›¢æ¯”率:" name="fog"/>
+ <button label="OK" label_selected="OK" name="OK"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_help_browser.xml b/indra/newview/skins/default/xui/ja/floater_help_browser.xml
new file mode 100644
index 0000000000..0a783713d5
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_help_browser.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_help_browser" title="ヘルプブラウザ">
+ <floater.string name="home_page_url">
+ http://jp.secondlife.com
+ </floater.string>
+ <floater.string name="support_page_url">
+ http://jp.secondlife.com/support
+ </floater.string>
+ <layout_stack name="stack1">
+ <layout_panel name="external_controls">
+ <button label="Web ブラウザã§é–‹ã" name="open_browser"/>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_hud.xml b/indra/newview/skins/default/xui/ja/floater_hud.xml
index a1970ebbd5..e3841c2cd9 100644
--- a/indra/newview/skins/default/xui/ja/floater_hud.xml
+++ b/indra/newview/skins/default/xui/ja/floater_hud.xml
@@ -1,2 +1,2 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_hud" title="ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_hud" title="ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«"/>
diff --git a/indra/newview/skins/default/xui/ja/floater_im.xml b/indra/newview/skins/default/xui/ja/floater_im.xml
index eec644715d..9c323f25e6 100644
--- a/indra/newview/skins/default/xui/ja/floater_im.xml
+++ b/indra/newview/skins/default/xui/ja/floater_im.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<multi_floater name="im_floater" title="インスタント・メッセージ">
<string name="only_user_message">
ã“ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«ã„るユーザーã¯ã‚ãªãŸã ã‘ã§ã™ã€‚
@@ -10,7 +10,7 @@
ã“ã®ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆã«å¿œç­”/接続ã™ã‚‹å ´åˆã¯ã€[BUTTON NAME]をクリックã—ã¦ãã ã•ã„。
</string>
<string name="muted_message">
- ã‚ãªãŸã¯ã“ã®ä½äººã‚’無視ã—ã¦ã„ã¾ã™ã€‚ メッセージをé€ä¿¡ã™ã‚‹ã¨ã€ç„¡è¦–設定ã¯è‡ªå‹•çš„ã«è§£é™¤ã•ã‚Œã¾ã™ã€‚
+ ã“ã®ä½äººã‚’ブロックã—ã¦ã„ã¾ã™ã€‚ メッセージをé€ã‚‹ã¨ã€ãƒ–ロックãŒè‡ªå‹•çš„ã«è§£é™¤ã•ã‚Œã¾ã™ã€‚
</string>
<string name="generic_request_error">
è¦æ±‚中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚後ã§ã‚‚ã†ä¸€åº¦è©¦ã—ã¦ãã ã•ã„。
diff --git a/indra/newview/skins/default/xui/ja/floater_im_container.xml b/indra/newview/skins/default/xui/ja/floater_im_container.xml
new file mode 100644
index 0000000000..24cef14ee0
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_im_container.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<multi_floater name="floater_im_box" title="インスタントメッセージ"/>
diff --git a/indra/newview/skins/default/xui/ja/floater_im_session.xml b/indra/newview/skins/default/xui/ja/floater_im_session.xml
new file mode 100644
index 0000000000..6646cc0b25
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_im_session.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="panel_im">
+ <layout_stack name="im_panels">
+ <layout_panel label="IM コントロールパãƒãƒ«" name="panel_im_control_panel"/>
+ <layout_panel>
+ <line_editor label="宛先" name="chat_editor"/>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_image_preview.xml b/indra/newview/skins/default/xui/ja/floater_image_preview.xml
index be8e5c6416..57ed139e54 100644
--- a/indra/newview/skins/default/xui/ja/floater_image_preview.xml
+++ b/indra/newview/skins/default/xui/ja/floater_image_preview.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Image Preview" title="">
<text name="name_label">
åå‰ï¼š
@@ -10,43 +10,23 @@
イメージã®ï¾Œï¾Ÿï¾šï¾‹ï¾žï½­ï½°ï¼š
</text>
<combo_box label="æœã®ç¨®é¡ž" name="clothing_type_combo">
- <combo_item name="Image">
- ç”»åƒ
- </combo_item>
- <combo_item name="Hair">
- 髪
- </combo_item>
- <combo_item name="FemaleHead">
- 女性ã®é ­
- </combo_item>
- <combo_item name="FemaleUpperBody">
- 女性ã®ä¸ŠåŠèº«
- </combo_item>
- <combo_item name="FemaleLowerBody">
- 女性ã®ä¸‹åŠèº«
- </combo_item>
- <combo_item name="MaleHead">
- 男性ã®é ­
- </combo_item>
- <combo_item name="MaleUpperBody">
- 男性ã®ä¸ŠåŠèº«
- </combo_item>
- <combo_item name="MaleLowerBody">
- 男性ã®ä¸‹åŠèº«
- </combo_item>
- <combo_item name="Skirt">
- スカート
- </combo_item>
- <combo_item name="SculptedPrim">
- 変形ã•ã‚ŒãŸãƒ—リム
- </combo_item>
+ <combo_box.item label="ç”»åƒ" name="Image"/>
+ <combo_box.item label="髪" name="Hair"/>
+ <combo_box.item label="女性ã®é ­" name="FemaleHead"/>
+ <combo_box.item label="女性ã®ä¸ŠåŠèº«" name="FemaleUpperBody"/>
+ <combo_box.item label="女性ã®ä¸‹åŠèº«" name="FemaleLowerBody"/>
+ <combo_box.item label="男性ã®é ­" name="MaleHead"/>
+ <combo_box.item label="男性ã®ä¸ŠåŠèº«" name="MaleUpperBody"/>
+ <combo_box.item label="男性ã®ä¸‹åŠèº«" name="MaleLowerBody"/>
+ <combo_box.item label="スカート" name="Skirt"/>
+ <combo_box.item label="スカルプトプリム" name="SculptedPrim"/>
</combo_box>
<text name="bad_image_text">
イメージを読ã¿å–ã‚Œã¾ã›ã‚“。
24bitTarga(.tga)ã§ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’ä¿å­˜ã—ã¦ãã ã•ã„。
</text>
- <check_box label="ロスã®ãªã„圧縮を使用" name="lossless_check" />
- <button label="å–り消ã—" name="cancel_btn" />
- <button label="アップロードL$[AMOUNT]" name="ok_btn" />
+ <check_box label="ロスã®ãªã„圧縮を使用" name="lossless_check"/>
+ <button label="å–り消ã—" name="cancel_btn"/>
+ <button label="アップロードL$[AMOUNT]" name="ok_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_incoming_call.xml b/indra/newview/skins/default/xui/ja/floater_incoming_call.xml
new file mode 100644
index 0000000000..32793faa6d
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_incoming_call.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="incoming call" title="ä¸æ˜Žã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‹ã‚‰ã®ã‚³ãƒ¼ãƒ«">
+ <floater.string name="localchat">
+ è¿‘ãã®ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆ
+ </floater.string>
+ <floater.string name="anonymous">
+ 匿åユーザー
+ </floater.string>
+ <floater.string name="VoiceInviteP2P">
+ ãŒã‚³ãƒ¼ãƒ«ã—ã¦ã„ã¾ã™ã€‚
+ </floater.string>
+ <floater.string name="VoiceInviteAdHoc">
+ ãŒã‚³ãƒ³ãƒ•ã‚¡ãƒ¬ãƒ³ã‚¹ãƒãƒ£ãƒƒãƒˆã§ã€ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆã«å‚加ã—ã¾ã—ãŸã€‚
+ </floater.string>
+ <text name="question">
+ [CURRENT_CHAT] を退席ã—ã¦ã€ã“ã®ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆã«å‚加ã—ã¾ã™ã‹ï¼Ÿ
+ </text>
+ <button label="ã¯ã„" label_selected="ã¯ã„" name="Accept"/>
+ <button label="ã„ã„ãˆ" label_selected="ã„ã„ãˆ" name="Reject"/>
+ <button label="IM" name="Start IM"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_inspect.xml b/indra/newview/skins/default/xui/ja/floater_inspect.xml
index 3ada48ef8e..b7c657c2f9 100644
--- a/indra/newview/skins/default/xui/ja/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/ja/floater_inspect.xml
@@ -1,14 +1,14 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="inspect" title="オブジェクト検査" min_width="450" >
- <scroll_list name="object_list"
- tool_tip="ã“ã®ãƒªã‚¹ãƒˆã‹ã‚‰ã‚ªãƒ–ジェクトをé¸æŠžã—ã€ã“ã®ä¸–ç•Œã§å¼·èª¿è¡¨ç¤ºã—ã¾ã™ã€‚">
- <column label="オブジェクトå" name="object_name" />
- <column label="所有者å" name="owner_name" />
- <column label="制作者å" name="creator_name" />
- <column label="作æˆæ—¥" name="creation_date" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater min_width="450" name="inspect" title="オブジェクトã®ãƒã‚§ãƒƒã‚¯">
+ <floater.string name="timeStamp">
+ [year,datetime,local] [mth,datetime,local] [day,datetime,local] [wkday,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local]
+ </floater.string>
+ <scroll_list name="object_list" tool_tip="ã“ã®ãƒªã‚¹ãƒˆã‹ã‚‰ã‚ªãƒ–ジェクトをé¸æŠžã—ã€ã“ã®ä¸–ç•Œã§å¼·èª¿è¡¨ç¤ºã—ã¾ã™ã€‚">
+ <scroll_list.columns label="オブジェクトå" name="object_name"/>
+ <scroll_list.columns label="所有者å" name="owner_name"/>
+ <scroll_list.columns label="制作者å" name="creator_name"/>
+ <scroll_list.columns label="作æˆæ—¥" name="creation_date"/>
</scroll_list>
- <button label="所有者ã®ãƒ—ロフィールを表示..." name="button owner"
- tool_tip="é¸æŠžã•ã‚ŒãŸã‚ªãƒ–ジェクトã®æ‰€æœ‰è€…ã®ãƒ—ロフィールを見る" />
- <button label="制作者ã®ãƒ—ロフィールを表示..." name="button creator"
- tool_tip="é¸æŠžã•ã‚ŒãŸã‚ªãƒ–ジェクトã®åˆ¶ä½œè€…ã®ãƒ—ロフィールを見る" />
+ <button label="所有者ã®ãƒ—ロフィールを表示..." name="button owner" tool_tip="é¸æŠžã•ã‚ŒãŸã‚ªãƒ–ジェクトã®æ‰€æœ‰è€…ã®ãƒ—ロフィールを見る"/>
+ <button label="制作者ã®ãƒ—ロフィールを表示..." name="button creator" tool_tip="é¸æŠžã•ã‚ŒãŸã‚ªãƒ–ジェクトã®åˆ¶ä½œè€…ã®ãƒ—ロフィールを見る"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_inventory.xml b/indra/newview/skins/default/xui/ja/floater_inventory.xml
index 680496839a..7cf16b8ff2 100644
--- a/indra/newview/skins/default/xui/ja/floater_inventory.xml
+++ b/indra/newview/skins/default/xui/ja/floater_inventory.xml
@@ -1,51 +1,16 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Inventory" title="æŒã¡ç‰©">
- <search_editor label="ã“ã“ã«å…¥åŠ›ã—ã¦æ¤œç´¢" name="inventory search editor" />
- <tab_container name="inventory filter tabs">
- <inventory_panel label="ã™ã¹ã¦" name="All Items" />
- <inventory_panel label="最近ã®å…¥æ‰‹ã‚¢ã‚¤ãƒ†ãƒ " name="Recent Items" />
- </tab_container>
- <menu_bar name="Inventory Menu">
- <menu label="ファイル" name="File">
- <menu_item_call label="é–‹ã" name="Open" />
- <menu_item_call label="æ–°ã—ã„ウィンドウ" name="New Window" />
- <menu_item_call label="フィルタを表示" name="Show Filters" />
- <menu_item_call label="フィルターã®ãƒªã‚»ãƒƒãƒˆ" name="Reset Current" />
- <menu_item_call label="ã™ã¹ã¦ã®ãƒ•ã‚©ãƒ«ãƒ€ã‚’é–‰ã˜ã‚‹" name="Close All Folders" />
- <menu_item_call label="ゴミ箱を空ã«ã™ã‚‹" name="Empty Trash" />
- </menu>
- <menu label="作æˆ" name="Create">
- <menu_item_call label="æ–°ã—ã„フォルダ" name="New Folder" />
- <menu_item_call label="æ–°ã—ã„スクリプト" name="New Script" />
- <menu_item_call label="æ–°ã—ã„ノート" name="New Note" />
- <menu_item_call label="æ–°ã—ã„ジェスãƒãƒ£ãƒ¼" name="New Gesture" />
- <menu name="New Clothes">
- <menu_item_call label="æ–°ã—ã„シャツ" name="New Shirt" />
- <menu_item_call label="æ–°ã—ã„ズボン" name="New Pants" />
- <menu_item_call label="æ–°ã—ã„é´" name="New Shoes" />
- <menu_item_call label="æ–°ã—ã„é´ä¸‹" name="New Socks" />
- <menu_item_call label="æ–°ã—ã„ジャケット" name="New Jacket" />
- <menu_item_call label="æ–°ã—ã„スカート" name="New Skirt" />
- <menu_item_call label="æ–°ã—ã„手袋" name="New Gloves" />
- <menu_item_call label="æ–°ã—ã„下ç€" name="New Undershirt" />
- <menu_item_call label="æ–°ã—ã„パンツ" name="New Underpants" />
- </menu>
- <menu name="New Body Parts">
- <menu_item_call label="æ–°ã—ã„シェイプ(体型)" name="New Shape" />
- <menu_item_call label="æ–°ã—ã„スキン" name="New Skin" />
- <menu_item_call label="æ–°ã—ã„髪" name="New Hair" />
- <menu_item_call label="æ–°ã—ã„眼" name="New Eyes" />
- </menu>
- </menu>
- <menu label="並ã¹æ›¿ãˆ" name="Sort">
- <menu_item_check label="åå‰" name="By Name" />
- <menu_item_check label="日付" name="By Date" />
- <menu_item_check label="フォルダã¯å¸¸ã«åå‰é †" name="Folders Always By Name" />
- <menu_item_check label="システムフォルダをトップã¸" name="System Folders To Top" />
- </menu>
- <menu label="フィルタ" name="Filters">
- <menu_item_check label="ç¾çŠ¶ã‚’修正" name="Modify Current" />
- <menu_item_call label="ç¾çŠ¶ã‚’リセット" name="Reset Current" />
- </menu>
- </menu_bar>
+ <floater.string name="Title">
+ インベントリ
+ </floater.string>
+ <floater.string name="TitleFetching">
+ æŒã¡ç‰© ( [ITEM_COUNT] アイテムをå–得中...) [FILTER]
+ </floater.string>
+ <floater.string name="TitleCompleted">
+ æŒã¡ç‰© ( [ITEM_COUNT] アイテム) [FILTER]
+ </floater.string>
+ <floater.string name="Fetched">
+ å–得済
+ </floater.string>
+ <panel label="æŒã¡ç‰©ãƒ‘ãƒãƒ«" name="Inventory Panel"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/ja/floater_inventory_item_properties.xml
index 9a408b92a9..7480b04856 100644
--- a/indra/newview/skins/default/xui/ja/floater_inventory_item_properties.xml
+++ b/indra/newview/skins/default/xui/ja/floater_inventory_item_properties.xml
@@ -1,5 +1,20 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="item properties" title="æŒã¡ç‰©ã‚¢ã‚¤ãƒ†ãƒ ã®ãƒ—ロパティ">
+ <floater.string name="unknown">
+ (ä¸æ˜Žï¼‰
+ </floater.string>
+ <floater.string name="public">
+ (公共)
+ </floater.string>
+ <floater.string name="you_can">
+ ã§ãã‚‹ã“ã¨ï¼š
+ </floater.string>
+ <floater.string name="owner_can">
+ オーナーã¯æ¬¡ã®ã“ã¨ãŒã§ãã¾ã™ï¼š
+ </floater.string>
+ <floater.string name="acquiredDate">
+ [year,datetime,local] [mth,datetime,local] [day,datetime,local] [wkday,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local]
+ </floater.string>
<text name="LabelItemNameTitle">
åå‰ï¼š
</text>
@@ -12,14 +27,14 @@
<text name="LabelCreatorName">
Nicole Linden
</text>
- <button label="情報" label_selected="" name="BtnCreator" />
+ <button label="情報" label_selected="" name="BtnCreator"/>
<text name="LabelOwnerTitle">
オーナー:
</text>
<text name="LabelOwnerName">
Thrax Linden
</text>
- <button label="情報" label_selected="" name="BtnOwner" />
+ <button label="情報" label_selected="" name="BtnOwner"/>
<text name="LabelAcquiredTitle">
入手日時:
</text>
@@ -27,59 +42,32 @@
2006年5月24日水曜日12:50:46
</text>
<text name="OwnerLabel">
- ã§ãã‚‹ã“ã¨ï¼š
+ ã‚ãªãŸï¼š
</text>
- <check_box label="修正" name="CheckOwnerModify" />
- <check_box label="コピー" name="CheckOwnerCopy" />
- <check_box label="å†è²©ï¼ãƒ—レゼント" name="CheckOwnerTransfer" />
- <text name="BaseMaskDebug">
- B:
+ <check_box label="編集" name="CheckOwnerModify"/>
+ <check_box label="コピー" name="CheckOwnerCopy"/>
+ <check_box label="å†è²©ãƒ»ãƒ—レゼント" name="CheckOwnerTransfer"/>
+ <text name="AnyoneLabel">
+ 全員:
</text>
- <text name="OwnerMaskDebug">
- O:
+ <check_box label="コピー" name="CheckEveryoneCopy"/>
+ <text name="GroupLabel">
+ グループ:
</text>
- <text name="GroupMaskDebug">
- G:
- </text>
- <text name="EveryoneMaskDebug">
- E:
- </text>
- <text name="NextMaskDebug">
- N:
- </text>
- <check_box label="グループ分担" name="CheckShareWithGroup" />
- <check_box label="誰ã«å¯¾ã—ã¦ã‚‚コピーを許å¯" name="CheckEveryoneCopy" />
+ <check_box label="共有" name="CheckShareWithGroup"/>
<text name="NextOwnerLabel" width="158">
- 次ã®ã‚ªãƒ¼ãƒŠãƒ¼ãŒã§ãã‚‹ã“ã¨ï¼š
- </text>
- <check_box label="修正" name="CheckNextOwnerModify" />
- <check_box label="コピー" name="CheckNextOwnerCopy" />
- <check_box label="å†è²©ï¼ãƒ—レゼント" name="CheckNextOwnerTransfer" />
- <text name="SaleLabel">
- アイテムã«ãƒžãƒ¼ã‚¯ï¼š
- </text>
- <check_box label="売り出ã—中" name="CheckPurchase" />
- <radio_group name="RadioSaleType">
- <radio_item name="radio">
- オリジナル
- </radio_item>
- <radio_item name="radio2">
- コピー
- </radio_item>
- </radio_group>
- <text name="TextPrice">
- 料金:L$
- </text>
- <text name="unknown">
- (ä¸æ˜Žï¼‰
- </text>
- <text name="public">
- (公共)
- </text>
- <text name="you_can">
- ã§ãã‚‹ã“ã¨ï¼š
- </text>
- <text name="owner_can">
- オーナーã¯æ¬¡ã®ã“ã¨ãŒã§ãã¾ã™ï¼š
+ 次ã®æ‰€æœ‰è€…:
+ </text>
+ <check_box label="編集" name="CheckNextOwnerModify"/>
+ <check_box label="コピー" name="CheckNextOwnerCopy"/>
+ <check_box label="å†è²©ãƒ»ãƒ—レゼント" name="CheckNextOwnerTransfer"/>
+ <check_box label="売り出ã—中" name="CheckPurchase"/>
+ <combo_box name="combobox sale copy">
+ <combo_box.item label="コピー" name="Copy"/>
+ <combo_box.item label="オリジナル" name="Original"/>
+ </combo_box>
+ <spinner label="価格:" name="Edit Cost"/>
+ <text name="CurrencySymbol">
+ L$
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/ja/floater_inventory_view_finder.xml
index 92475aacf4..86bb5dcf62 100644
--- a/indra/newview/skins/default/xui/ja/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/ja/floater_inventory_view_finder.xml
@@ -1,24 +1,24 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Inventory Finder" title="inventory_recent_items">
- <check_box label="アニメーション" name="check_animation" />
- <check_box label="コーリング・カード" name="check_calling_card" />
- <check_box label="æœ" name="check_clothing" />
- <check_box label="ジェスãƒãƒ£ãƒ¼" name="check_gesture" />
- <check_box label="ランドマーク" name="check_landmark" />
- <check_box label="ノートカード" name="check_notecard" />
- <check_box label="オブジェクト" name="check_object" />
- <check_box label="スクリプト" name="check_script" />
- <check_box label="サウンド" name="check_sound" />
- <check_box label="テクスãƒãƒ£ãƒ¼" name="check_texture" />
- <check_box label="スナップショット" name="check_snapshot" />
- <button label="ã™ã¹ã¦" label_selected="ã™ã¹ã¦" name="All" />
- <button label="ãªã—" label_selected="ãªã—" name="None" />
- <check_box label="常ã«ãƒ•ã‚©ãƒ«ãƒ€ã‚’表示" name="check_show_empty" />
- <check_box label="ログオフ以é™" name="check_since_logoff" />
- <text type="string" length="1" name="- OR -">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Inventory Finder" title="最近å–å¾—ã—ãŸæŒã¡ç‰©ã‚¢ã‚¤ãƒ†ãƒ ">
+ <check_box label="アニメーション" name="check_animation"/>
+ <check_box label="コーリング・カード" name="check_calling_card"/>
+ <check_box label="æœ" name="check_clothing"/>
+ <check_box label="ジェスãƒãƒ£ãƒ¼" name="check_gesture"/>
+ <check_box label="ランドマーク" name="check_landmark"/>
+ <check_box label="ノートカード" name="check_notecard"/>
+ <check_box label="オブジェクト" name="check_object"/>
+ <check_box label="スクリプト" name="check_script"/>
+ <check_box label="サウンド" name="check_sound"/>
+ <check_box label="テクスãƒãƒ£ãƒ¼" name="check_texture"/>
+ <check_box label="スナップショット" name="check_snapshot"/>
+ <button label="ã™ã¹ã¦" label_selected="ã™ã¹ã¦" name="All"/>
+ <button label="ãªã—" label_selected="ãªã—" name="None"/>
+ <check_box label="常ã«ãƒ•ã‚©ãƒ«ãƒ€ã‚’表示" name="check_show_empty"/>
+ <check_box label="ログオフ以é™" name="check_since_logoff"/>
+ <text name="- OR -">
ï¼ã¾ãŸã¯ï¼
</text>
- <spinner label="経éŽæ™‚é–“" name="spin_hours_ago" />
- <spinner label="経éŽæ—¥æ•°" name="spin_days_ago" />
- <button label="é–‰ã˜ã‚‹" label_selected="é–‰ã˜ã‚‹" name="Close" />
+ <spinner label="経éŽæ™‚é–“" name="spin_hours_ago"/>
+ <spinner label="経éŽæ—¥æ•°" name="spin_days_ago"/>
+ <button label="é–‰ã˜ã‚‹" label_selected="é–‰ã˜ã‚‹" name="Close"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_joystick.xml b/indra/newview/skins/default/xui/ja/floater_joystick.xml
index 5029a781f6..9d91fe8db9 100644
--- a/indra/newview/skins/default/xui/ja/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/ja/floater_joystick.xml
@@ -1,8 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Joystick" title="ジョイスティックã®è¨­å®š">
- <check_box name="enable_joystick" width="120">
- ジョイスティックを使ã†ï¼š
- </check_box>
+ <check_box label="ジョイスティックを使ã†ï¼š" name="enable_joystick" width="120"/>
<text left="180" name="joystick_type" width="320"/>
<spinner label="X軸マッピング" name="JoystickAxis1"/>
<spinner label="Y軸マッピング" name="JoystickAxis2"/>
@@ -17,15 +15,9 @@
<text name="Control Modes:">
制御モード:
</text>
- <check_box left="131" name="JoystickAvatarEnabled">
- ã‚¢ãƒã‚¿ãƒ¼
- </check_box>
- <check_box left="201" name="JoystickBuildEnabled">
- 造る
- </check_box>
- <check_box left="271" name="JoystickFlycamEnabled">
- フライ・カメラ
- </check_box>
+ <check_box label="ã‚¢ãƒã‚¿ãƒ¼" left="131" name="JoystickAvatarEnabled"/>
+ <check_box label="造る" left="201" name="JoystickBuildEnabled"/>
+ <check_box label="フライ・カメラ" left="271" name="JoystickFlycamEnabled"/>
<text left="5" name="XScale" width="120">
Xスケール
</text>
@@ -113,12 +105,14 @@
<button label="SpaceNavigatorã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆè¨­å®š" left="330" name="SpaceNavigatorDefaults" width="210"/>
<button label="OK" label_selected="OK" name="ok_btn"/>
<button label="å–り消ã—" label_selected="å–り消ã—" name="cancel_btn"/>
- <string name="JoystickMonitor">
- ジョイスティック・モニター
- </string>
- <string name="Axis">
- 軸 [NUM]
- </string>
+ <stat_view label="ジョイスティック・モニター" name="axis_view">
+ <stat_bar label="軸 0" name="axis0"/>
+ <stat_bar label="軸 1" name="axis1"/>
+ <stat_bar label="軸 2" name="axis2"/>
+ <stat_bar label="軸 3" name="axis3"/>
+ <stat_bar label="軸 4" name="axis4"/>
+ <stat_bar label="軸 5" name="axis5"/>
+ </stat_view>
<string name="NoDevice">
デãƒã‚¤ã‚¹ã¯æ¤œå‡ºã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ
</string>
diff --git a/indra/newview/skins/default/xui/ja/floater_lagmeter.xml b/indra/newview/skins/default/xui/ja/floater_lagmeter.xml
index e25771ea72..e3546cd837 100644
--- a/indra/newview/skins/default/xui/ja/floater_lagmeter.xml
+++ b/indra/newview/skins/default/xui/ja/floater_lagmeter.xml
@@ -1,152 +1,151 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_lagmeter" title="ラグ メーター">
- <button name="client_lagmeter" tool_tip="クライアント ラグ ステータス" />
- <text name="client">
- クライアント:
- </text>
- <text name="client_text">
- ノーマル
- </text>
- <button name="network_lagmeter" tool_tip="ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ ラグ ステータス" />
- <text name="network">
- ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯:
- </text>
- <text name="network_text">
- ノーマル
- </text>
- <button name="server_lagmeter" tool_tip="サーãƒãƒ¼ ラグ ステータス" />
- <text name="server">
- サーãƒãƒ¼:
- </text>
- <text name="server_text">
- ノーマル
- </text>
- <button label="?" name="server_help" />
- <button label="&gt;&gt; " name="minimize" />
- <text name="max_title_msg">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_lagmeter" title="ラグメーター">
+ <floater.string name="max_title_msg">
ラグ メーター
- </text>
- <text name="max_width_px">
+ </floater.string>
+ <floater.string name="max_width_px">
350
- </text>
- <text name="min_title_msg">
+ </floater.string>
+ <floater.string name="min_title_msg">
ラグ
- </text>
- <text name="min_width_px">
+ </floater.string>
+ <floater.string name="min_width_px">
90
- </text>
- <text name="client_text_msg">
+ </floater.string>
+ <floater.string name="client_text_msg">
クライアント
- </text>
- <text name="client_frame_rate_critical_fps">
+ </floater.string>
+ <floater.string name="client_frame_rate_critical_fps">
10
- </text>
- <text name="client_frame_rate_warning_fps">
+ </floater.string>
+ <floater.string name="client_frame_rate_warning_fps">
15
- </text>
- <text name="client_frame_time_window_bg_msg">
+ </floater.string>
+ <floater.string name="client_frame_time_window_bg_msg">
ノーマルã€ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã¯èƒŒæ™¯ã«
- </text>
- <text name="client_frame_time_critical_msg">
+ </floater.string>
+ <floater.string name="client_frame_time_critical_msg">
クライアント フレームレート < [CLIENT_FRAME_RATE_CRITICAL]
- </text>
- <text name="client_frame_time_warning_msg">
+ </floater.string>
+ <floater.string name="client_frame_time_warning_msg">
クライアント フレームレート: [CLIENT_FRAME_RATE_CRITICAL] ~ [CLIENT_FRAME_RATE_WARNING]
- </text>
- <text name="client_frame_time_normal_msg">
+ </floater.string>
+ <floater.string name="client_frame_time_normal_msg">
ノーマル
- </text>
- <text name="client_draw_distance_cause_msg">
+ </floater.string>
+ <floater.string name="client_draw_distance_cause_msg">
考ãˆã‚‰ã‚Œã‚‹åŽŸå› : æç”»è·é›¢ã®è¨­å®šãŒå¤§ãã™ãŽã‚‹
- </text>
- <text name="client_texture_loading_cause_msg">
+ </floater.string>
+ <floater.string name="client_texture_loading_cause_msg">
考ãˆã‚‰ã‚Œã‚‹åŽŸå› : ç”»åƒã®ãƒ­ãƒ¼ãƒ‰ä¸­
- </text>
- <text name="client_texture_memory_cause_msg">
+ </floater.string>
+ <floater.string name="client_texture_memory_cause_msg">
考ãˆã‚‰ã‚Œã‚‹åŽŸå› : メモリ内ã®ç”»åƒæ•°ãŒå¤šã™ãŽã‚‹
- </text>
- <text name="client_complex_objects_cause_msg">
+ </floater.string>
+ <floater.string name="client_complex_objects_cause_msg">
考ãˆã‚‰ã‚Œã‚‹åŽŸå› : ç”»é¢ã«å«ã¾ã‚Œã‚‹è¤‡é›‘ãªã‚ªãƒ–ジェクトãŒå¤šã™ãŽã‚‹
- </text>
- <text name="network_text_msg">
+ </floater.string>
+ <floater.string name="network_text_msg">
ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯
- </text>
- <text name="network_packet_loss_critical_pct">
+ </floater.string>
+ <floater.string name="network_packet_loss_critical_pct">
10
- </text>
- <text name="network_packet_loss_warning_pct">
+ </floater.string>
+ <floater.string name="network_packet_loss_warning_pct">
5
- </text>
- <text name="network_packet_loss_critical_msg">
+ </floater.string>
+ <floater.string name="network_packet_loss_critical_msg">
接続ã§ãƒ‰ãƒ­ãƒƒãƒ—ã•ã‚Œã‚‹ãƒ‘ケットã®å‰²åˆ: > [NETWORK_PACKET_LOSS_CRITICAL]
- </text>
- <text name="network_packet_loss_warning_msg">
+ </floater.string>
+ <floater.string name="network_packet_loss_warning_msg">
接続ã§ãƒ‰ãƒ­ãƒƒãƒ—ã•ã‚Œã‚‹ãƒ‘ケットã®å‰²åˆ:[NETWORK_PACKET_LOSS_WARNING] ~ [NETWORK_PACKET_LOSS_CRITICAL]
- </text>
- <text name="network_performance_normal_msg">
+ </floater.string>
+ <floater.string name="network_performance_normal_msg">
ノーマル
- </text>
- <text name="network_ping_critical_ms">
+ </floater.string>
+ <floater.string name="network_ping_critical_ms">
600
- </text>
- <text name="network_ping_warning_ms">
+ </floater.string>
+ <floater.string name="network_ping_warning_ms">
300
- </text>
- <text name="network_ping_critical_msg">
+ </floater.string>
+ <floater.string name="network_ping_critical_msg">
接続㮠ping 時間: > [NETWORK_PING_CRITICAL] ミリ秒
- </text>
- <text name="network_ping_warning_msg">
+ </floater.string>
+ <floater.string name="network_ping_warning_msg">
接続㮠ping 時間: [NETWORK_PING_WARNING] ~ [NETWORK_PING_CRITICAL] ミリ秒
- </text>
- <text name="network_packet_loss_cause_msg">
+ </floater.string>
+ <floater.string name="network_packet_loss_cause_msg">
接続ä¸è‰¯ã«ãªã£ã¦ã„ã‚‹ã‹ã€å¸¯åŸŸå¹…設定ãŒé«˜ã™ãŽã¾ã™ã€‚
- </text>
- <text name="network_ping_cause_msg">
+ </floater.string>
+ <floater.string name="network_ping_cause_msg">
接続ä¸è‰¯ã«ãªã£ã¦ã„ã‚‹ã‹ã€ãƒ•ã‚¡ã‚¤ãƒ«å…±æœ‰ã‚¢ãƒ—リケーションã«å•é¡ŒãŒã‚ã‚Šã¾ã™ã€‚
- </text>
- <text name="server_text_msg">
+ </floater.string>
+ <floater.string name="server_text_msg">
サーãƒãƒ¼
- </text>
- <text name="server_frame_rate_critical_fps">
+ </floater.string>
+ <floater.string name="server_frame_rate_critical_fps">
20
- </text>
- <text name="server_frame_rate_warning_fps">
+ </floater.string>
+ <floater.string name="server_frame_rate_warning_fps">
30
- </text>
- <text name="server_single_process_max_time_ms">
+ </floater.string>
+ <floater.string name="server_single_process_max_time_ms">
20
- </text>
- <text name="server_frame_time_critical_msg">
+ </floater.string>
+ <floater.string name="server_frame_time_critical_msg">
シミュレーターã®ãƒ•ãƒ¬ãƒ¼ãƒ ãƒ¬ãƒ¼ãƒˆ: < [SERVER_FRAME_RATE_CRITICAL]
- </text>
- <text name="server_frame_time_warning_msg">
+ </floater.string>
+ <floater.string name="server_frame_time_warning_msg">
シミュレーターã®ãƒ•ãƒ¬ãƒ¼ãƒ ãƒ¬ãƒ¼ãƒˆ: [SERVER_FRAME_RATE_CRITICAL] ~ [SERVER_FRAME_RATE_WARNING]
- </text>
- <text name="server_frame_time_normal_msg">
+ </floater.string>
+ <floater.string name="server_frame_time_normal_msg">
ノーマル
- </text>
- <text name="server_physics_cause_msg">
+ </floater.string>
+ <floater.string name="server_physics_cause_msg">
考ãˆã‚‰ã‚Œã‚‹åŽŸå› : 物ç†çš„オブジェクトãŒå¤šã™ãŽã‚‹
- </text>
- <text name="server_scripts_cause_msg">
+ </floater.string>
+ <floater.string name="server_scripts_cause_msg">
考ãˆã‚‰ã‚Œã‚‹åŽŸå› : スクリプトをå«ã‚€ã‚ªãƒ–ジェクトãŒå¤šã™ãŽã‚‹
- </text>
- <text name="server_net_cause_msg">
+ </floater.string>
+ <floater.string name="server_net_cause_msg">
考ãˆã‚‰ã‚Œã‚‹åŽŸå› : ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ トラフィックéŽå¤§
- </text>
- <text name="server_agent_cause_msg">
+ </floater.string>
+ <floater.string name="server_agent_cause_msg">
考ãˆã‚‰ã‚Œã‚‹åŽŸå› : 地域内ã«ã¦å‹•ã„ã¦ã„ã‚‹ã‚¢ãƒã‚¿ãƒ¼ãŒå¤šã™ãŽã‚‹
- </text>
- <text name="server_images_cause_msg">
+ </floater.string>
+ <floater.string name="server_images_cause_msg">
考ãˆã‚‰ã‚Œã‚‹åŽŸå› : ç”»åƒè¨ˆç®—ãŒå¤šã™ãŽã‚‹
- </text>
- <text name="server_generic_cause_msg">
+ </floater.string>
+ <floater.string name="server_generic_cause_msg">
考ãˆã‚‰ã‚Œã‚‹åŽŸå› : シミュレーターã®éŽè² è·
+ </floater.string>
+ <floater.string name="smaller_label">
+ &gt;&gt;
+ </floater.string>
+ <floater.string name="bigger_label">
+ &lt;&lt;
+ </floater.string>
+ <button name="client_lagmeter" tool_tip="クライアント ラグ ステータス"/>
+ <text name="client">
+ クライアント
</text>
- <text name="smaller_label">
- &gt;&gt; 
+ <text name="client_text">
+ ノーマル
+ </text>
+ <button name="network_lagmeter" tool_tip="ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ ラグ ステータス"/>
+ <text name="network">
+ ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯
</text>
- <text name="bigger_label">
- &lt;&lt; 
+ <text name="network_text">
+ ノーマル
+ </text>
+ <button name="server_lagmeter" tool_tip="サーãƒãƒ¼ ラグ ステータス"/>
+ <text name="server">
+ サーãƒãƒ¼
+ </text>
+ <text name="server_text">
+ ノーマル
</text>
+ <button label="&gt;&gt; " name="minimize" tool_tip="フローターã®ã‚µã‚¤ã‚ºã‚’トグル"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_land_holdings.xml b/indra/newview/skins/default/xui/ja/floater_land_holdings.xml
index cb87dafb49..474bd32cb0 100644
--- a/indra/newview/skins/default/xui/ja/floater_land_holdings.xml
+++ b/indra/newview/skins/default/xui/ja/floater_land_holdings.xml
@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="land holdings floater" title="自分ã®åœŸåœ°">
<scroll_list name="parcel list">
- <column label="区画å" name="name"/>
+ <column label="区画" name="name"/>
<column label="地域(リージョン)" name="location"/>
<column label="種類" name="type"/>
<column label="é¢ç©" name="area"/>
<column label="" name="hidden"/>
</scroll_list>
<button label="テレãƒãƒ¼ãƒˆ" label_selected="テレãƒãƒ¼ãƒˆ" name="Teleport" tool_tip="ã“ã®åœŸåœ°ã®ä¸­å¿ƒã«ãƒ†ãƒ¬ãƒãƒ¼ãƒˆ"/>
- <button label="地図上ã«è¡¨ç¤º" label_selected="地図上ã«è¡¨ç¤º" name="Show on Map" tool_tip="ã“ã®åœŸåœ°ã‚’世界地図ã«è¡¨ç¤ºã—ã¾ã™ã€‚"/>
+ <button label="地図" label_selected="地図" name="Show on Map" tool_tip="ã“ã®åœŸåœ°ã‚’世界地図ã«è¡¨ç¤ºã—ã¾ã™"/>
<text name="contrib_label">
ã‚ãªãŸã®ã‚°ãƒ«ãƒ¼ãƒ—ã¸ã®è²¢çŒ®ï¼š
</text>
@@ -20,21 +20,21 @@
ç¾åœ¨ã®æ”¯æ‰•ã„プランã§ã®è¨±å¯ã•ã‚ŒãŸä¿æœ‰åœ°ï¼š
</text>
<text name="allowed_text">
- [AREA]平方メートル
+ [AREA] 平方メートル
</text>
<text name="current_label">
ç¾åœ¨ã®ä¿æœ‰åœ°ï¼š
</text>
<text name="current_text">
- [AREA]平方メートル
+ [AREA] 平方メートル
</text>
<text name="available_label">
土地購入å¯ï¼š
</text>
<text name="available_text">
- [AREA]平方メートル
+ [AREA] 平方メートル
</text>
<string name="area_string">
- [AREA]平方メートル
+ [AREA] 平方メートル
</string>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/ja/floater_live_lsleditor.xml
index 79942738ea..5a155c9f12 100644
--- a/indra/newview/skins/default/xui/ja/floater_live_lsleditor.xml
+++ b/indra/newview/skins/default/xui/ja/floater_live_lsleditor.xml
@@ -1,12 +1,15 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script ed float" title="スクリプト:新ã—ã„スクリプト">
- <button label="リセット" label_selected="リセット" name="Reset" />
- <check_box label="実行中" name="running" />
- <check_box label="Mono" name="mono" />
- <text name="not_allowed">
- ã‚ãªãŸã¯ã“ã®ã‚¹ã‚¯ãƒªãƒ—トを見るã“ã¨ãŒã§ãã¾ã›ã‚“。
- </text>
- <string name="script_running">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="script ed float" title="スクリプト: æ–°ã—ã„スクリプト">
+ <floater.string name="not_allowed">
+ ã“ã®ã‚¹ã‚¯ãƒªãƒ—トã¯ã€Œã‚³ãƒ”ーä¸å¯ã€ã®ãŸã‚ã€è¡¨ç¤ºãƒ»ç·¨é›†ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。 オブジェクト内ã®ã‚¹ã‚¯ãƒªãƒ—トã®è¡¨ç¤ºãƒ»ç·¨é›†ã«ã¯ã€å…¨æ¨©é™ãŒå¿…è¦ã§ã™ã€‚
+ </floater.string>
+ <floater.string name="script_running">
実行中
- </string>
+ </floater.string>
+ <floater.string name="Title">
+ スクリプト: [NAME]
+ </floater.string>
+ <button label="リセット" label_selected="リセット" name="Reset"/>
+ <check_box initial_value="true" label="実行中" name="running"/>
+ <check_box initial_value="true" label="Mono" name="mono"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_lsl_guide.xml b/indra/newview/skins/default/xui/ja/floater_lsl_guide.xml
index 55eba966dc..2af693be64 100644
--- a/indra/newview/skins/default/xui/ja/floater_lsl_guide.xml
+++ b/indra/newview/skins/default/xui/ja/floater_lsl_guide.xml
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script ed float" title="LSL Wiki">
- <check_box label="カーソルを追ã†" name="lock_check" />
- <combo_box label="ロック" name="history_combo" />
- <button label="戻る" name="back_btn" />
- <button label="進む" name="fwd_btn" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="script ed float" title="LSL WIKI">
+ <check_box label="カーソルを追ã†" name="lock_check"/>
+ <combo_box label="ロック" name="history_combo"/>
+ <button label="戻る" name="back_btn"/>
+ <button label="進む" name="fwd_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_map.xml b/indra/newview/skins/default/xui/ja/floater_map.xml
new file mode 100644
index 0000000000..f3cba7e674
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_map.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Map">
+ <floater.string name="mini_map_north">
+ 北
+ </floater.string>
+ <floater.string name="mini_map_east">
+ æ±
+ </floater.string>
+ <floater.string name="mini_map_west">
+ 西
+ </floater.string>
+ <floater.string name="mini_map_south">
+ å—
+ </floater.string>
+ <floater.string name="mini_map_southeast">
+ å—æ±
+ </floater.string>
+ <floater.string name="mini_map_northeast">
+ 北æ±
+ </floater.string>
+ <floater.string name="mini_map_southwest">
+ å—西
+ </floater.string>
+ <floater.string name="mini_map_northwest">
+ 北西
+ </floater.string>
+ <floater.string name="ToolTipMsg">
+ [AGENT][REGION] (ダブルクリックã§åœ°å›³ã‚’é–‹ã)
+ </floater.string>
+ <text label="北" name="floater_map_north" text="北">
+ 北
+ </text>
+ <text label="æ±" name="floater_map_east" text="æ±">
+ æ±
+ </text>
+ <text label="西" name="floater_map_west" text="西">
+ 西
+ </text>
+ <text label="å—" name="floater_map_south" text="å—">
+ å—
+ </text>
+ <text label="å—æ±" name="floater_map_southeast" text="å—æ±">
+ å—æ±
+ </text>
+ <text label="北æ±" name="floater_map_northeast" text="北æ±">
+ 北æ±
+ </text>
+ <text label="å—西" name="floater_map_southwest" text="å—西">
+ å—西
+ </text>
+ <text label="北西" name="floater_map_northwest" text="北西">
+ 北西
+ </text>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_media_browser.xml b/indra/newview/skins/default/xui/ja/floater_media_browser.xml
index 6877cc7f53..5a6f2121f8 100644
--- a/indra/newview/skins/default/xui/ja/floater_media_browser.xml
+++ b/indra/newview/skins/default/xui/ja/floater_media_browser.xml
@@ -1,19 +1,30 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_about" title="メディア・ブラウザ">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_about" title="メディアブラウザ">
+ <floater.string name="home_page_url">
+ http://jp.secondlife.com
+ </floater.string>
+ <floater.string name="support_page_url">
+ http://jp.secondlife.com/support
+ </floater.string>
<layout_stack name="stack1">
<layout_panel name="nav_controls">
- <button label="戻る" name="back" />
- <button label="進む" name="forward" />
- <button label="æ›´æ–°" name="reload" />
- <button label="閲覧" name="go" />
+ <button label="戻る" name="back"/>
+ <button label="進む" name="forward"/>
+ <button label="æ›´æ–°" name="reload"/>
+ <button label="閲覧" name="go"/>
+ </layout_panel>
+ <layout_panel name="time_controls">
+ <button label="å·»ã戻ã—" name="rewind"/>
+ <button label="åœæ­¢" name="stop"/>
+ <button label="æ—©é€ã‚Š" name="seek"/>
</layout_panel>
<layout_panel name="parcel_owner_controls">
- <button label="ç¾åœ¨ã® URL を区画ã«é€ä¿¡" name="assign" />
+ <button label="ç¾åœ¨ã® URL を区画ã«é€ä¿¡" name="assign"/>
</layout_panel>
<layout_panel name="external_controls">
- <button label="外部ウェブ・ブラウザã§é–‹ã" name="open_browser" />
- <check_box label="常ã«å¤–部ã®ã‚¦ã‚§ãƒ–・ブラウザã§é–‹ã" name="open_always" />
- <button label="é–‰ã˜ã‚‹" name="close" />
+ <button label="外部ウェブ・ブラウザã§é–‹ã" name="open_browser"/>
+ <check_box label="常ã«å¤–部ã®ã‚¦ã‚§ãƒ–・ブラウザã§é–‹ã" name="open_always"/>
+ <button label="é–‰ã˜ã‚‹" name="close"/>
</layout_panel>
</layout_stack>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_media_settings.xml b/indra/newview/skins/default/xui/ja/floater_media_settings.xml
new file mode 100644
index 0000000000..46ac1a8dfd
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_media_settings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="media_settings" title="メディアã®è¨­å®š">
+ <button label="OK" label_selected="OK" name="OK"/>
+ <button label="キャンセル" label_selected="キャンセル" name="Cancel"/>
+ <button label="é©ç”¨" label_selected="é©ç”¨" name="Apply"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_mem_leaking.xml b/indra/newview/skins/default/xui/ja/floater_mem_leaking.xml
index 4d6b6ca70a..6167b6db91 100644
--- a/indra/newview/skins/default/xui/ja/floater_mem_leaking.xml
+++ b/indra/newview/skins/default/xui/ja/floater_mem_leaking.xml
@@ -1,8 +1,7 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="MemLeak" title="メモリ・リーク・シミュレーション">
- <spinner label="リークスピード(1フレームã”ã¨ã®ãƒã‚¤ãƒˆæ•°):"
- name="leak_speed" label_width="244" />
- <spinner label="リークã—ãŸæœ€å¤§ãƒ¡ãƒ¢ãƒªæ•°(MB):" name="max_leak" label_width="244" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="MemLeak" title="メモリリークã®ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ãƒˆ">
+ <spinner label="リークスピード(1フレームã”ã¨ã®ãƒã‚¤ãƒˆæ•°):" label_width="244" name="leak_speed"/>
+ <spinner label="リークã—ãŸæœ€å¤§ãƒ¡ãƒ¢ãƒªæ•°(MB):" label_width="244" name="max_leak"/>
<text name="total_leaked_label">
ç¾åœ¨ã®ãƒªãƒ¼ã‚¯ãƒ¡ãƒ¢ãƒªã‚µã‚¤ã‚ºï¼š [SIZE] KB
</text>
@@ -12,8 +11,8 @@
<text name="note_label_2">
[NOTE2]
</text>
- <button label="開始" name="start_btn" />
- <button label="åœæ­¢" name="stop_btn" />
- <button label="解放" name="release_btn" />
- <button label="é–‰ã˜ã‚‹" name="close_btn" />
+ <button label="開始" name="start_btn"/>
+ <button label="åœæ­¢" name="stop_btn"/>
+ <button label="解放" name="release_btn"/>
+ <button label="é–‰ã˜ã‚‹" name="close_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_moveview.xml b/indra/newview/skins/default/xui/ja/floater_moveview.xml
index c40a1d93f4..8ba297c7a0 100644
--- a/indra/newview/skins/default/xui/ja/floater_moveview.xml
+++ b/indra/newview/skins/default/xui/ja/floater_moveview.xml
@@ -1,15 +1,35 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="move floater" title="">
- <button label="" label_selected="" name="turn left btn" tool_tip="å·¦ã«æ›²ãŒã‚‹" />
- <button label="" label_selected="" name="turn right btn" tool_tip="å³ã«æ›²ãŒã‚‹" />
- <button label="" label_selected="" name="move up btn"
- tool_tip="ジャンプã¾ãŸã¯ä¸Šæ˜‡" />
- <button label="" label_selected="" name="move down btn"
- tool_tip="ã—ゃãŒã‚€ã¾ãŸã¯ä¸‹é™" />
- <button label="飛行" label_selected="飛行" name="fly btn"
- tool_tip="飛行を開始ã¾ãŸã¯åœæ­¢" />
- <joystick_slide name="slide left btn" tool_tip="å·¦ã«ç§»å‹•" />
- <joystick_slide name="slide right btn" tool_tip="å³ã«ç§»å‹•" />
- <joystick_turn name="forward btn" tool_tip="å‰ã«ç§»å‹•" />
- <joystick_turn name="backward btn" tool_tip="後ã‚ã«ç§»å‹•" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="move_floater">
+ <string name="walk_forward_tooltip">
+ å‰ã«é€²ã‚€ï¼ˆä¸ŠçŸ¢å°ã‹ W を押ã™ï¼‰
+ </string>
+ <string name="walk_back_tooltip">
+ 後ã‚ã«æ­©ã(下矢å°ã‹ S を押ã™ï¼‰
+ </string>
+ <string name="run_forward_tooltip">
+ å‰ã«èµ°ã‚‹ï¼ˆä¸ŠçŸ¢å°ã‹ W を押ã™ï¼‰
+ </string>
+ <string name="run_back_tooltip">
+ 後ã‚ã«èµ°ã‚‹ï¼ˆä¸‹çŸ¢å°ã‹ S を押ã™ï¼‰
+ </string>
+ <string name="fly_forward_tooltip">
+ å‰ã«é£›ã¶ï¼ˆä¸ŠçŸ¢å°ã‹ W を押ã™ï¼‰
+ </string>
+ <string name="fly_back_tooltip">
+ 後ã‚ã«é£›ã¶ï¼ˆä¸‹çŸ¢å°ã‹ S を押ã™ï¼‰
+ </string>
+ <panel name="panel_actions">
+ <button label="" label_selected="" name="turn left btn" tool_tip="左をå‘ã(左矢å°ã‹ A を押ã™ï¼‰"/>
+ <button label="" label_selected="" name="turn right btn" tool_tip="å³ã‚’å‘ã(å³çŸ¢å°ã‹ D を押ã™ï¼‰"/>
+ <button label="" label_selected="" name="move up btn" tool_tip="飛ã¶ãƒ»E を押ã™"/>
+ <button label="" label_selected="" name="move down btn" tool_tip="ç€åœ°ãƒ»C を押ã™"/>
+ <joystick_turn name="forward btn" tool_tip="å‰ã«é€²ã‚€ï¼ˆä¸ŠçŸ¢å°ã‹ W を押ã™ï¼‰"/>
+ <joystick_turn name="backward btn" tool_tip="後ã‚ã«æ­©ã(下矢å°ã‹ S を押ã™ï¼‰"/>
+ </panel>
+ <panel name="panel_modes">
+ <button label="" name="mode_walk_btn" tool_tip="歩行モード"/>
+ <button label="" name="mode_run_btn" tool_tip="走行モード"/>
+ <button label="" name="mode_fly_btn" tool_tip="飛行モード"/>
+ <button label="飛行åœæ­¢" name="stop_fly_btn" tool_tip="飛行åœæ­¢"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_mute_object.xml b/indra/newview/skins/default/xui/ja/floater_mute_object.xml
index 072bb4a576..04ffd5254d 100644
--- a/indra/newview/skins/default/xui/ja/floater_mute_object.xml
+++ b/indra/newview/skins/default/xui/ja/floater_mute_object.xml
@@ -1,12 +1,14 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="mute by name" title="オブジェクトåã§ç„¡è¦–ã™ã‚‹">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="mute by name" title="åå‰ã§ã‚ªãƒ–ジェクトをブロック">
<text name="message">
- テキストã®ã¿ã«å½±éŸ¿ã—ã€ï½»ï½³ï¾ï¾„゙(環境音ãªã©)ã«ã¯å½±éŸ¿ã—ã¾ã›ã‚“。
-正確ãªã‚ªãƒ–ジェクトåを入力ã—ã¦ãã ã•ã„。
+ オブジェクトをブロックã—ã¾ã™ï¼š
</text>
<line_editor name="object_name">
オブジェクトå
</line_editor>
- <button label="OK" name="OK" />
- <button label="キャï¾ï½¾ï¾™" name="Cancel" />
+ <text name="note">
+ * ブロックã•ã‚Œã‚‹ã®ã¯ã‚ªãƒ–ジェクトã®æ–‡å­—ã ã‘ã§ã€éŸ³ã¯ãƒ–ロックã•ã‚Œã¾ã›ã‚“。
+ </text>
+ <button label="OK" name="OK"/>
+ <button label="キャï¾ï½¾ï¾™" name="Cancel"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_my_friends.xml b/indra/newview/skins/default/xui/ja/floater_my_friends.xml
index 10e55f0655..b55cdde5b5 100644
--- a/indra/newview/skins/default/xui/ja/floater_my_friends.xml
+++ b/indra/newview/skins/default/xui/ja/floater_my_friends.xml
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_my_friends" title="連絡先" min_width="500">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater min_width="500" name="floater_my_friends" title="連絡先">
<tab_container name="friends_and_groups">
- <panel label="フレンド" name="friends_panel" />
- <panel label="グループ" name="groups_panel" />
+ <panel label="フレンド" name="friends_panel"/>
+ <panel label="グループ" name="groups_panel"/>
</tab_container>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_nearby_chat.xml b/indra/newview/skins/default/xui/ja/floater_nearby_chat.xml
new file mode 100644
index 0000000000..a3cc105048
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_nearby_chat.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="nearby_chat" title="è¿‘ãã®ãƒãƒ£ãƒƒãƒˆ"/>
diff --git a/indra/newview/skins/default/xui/ja/floater_openobject.xml b/indra/newview/skins/default/xui/ja/floater_openobject.xml
index 3abda50f18..bd1b650f98 100644
--- a/indra/newview/skins/default/xui/ja/floater_openobject.xml
+++ b/indra/newview/skins/default/xui/ja/floater_openobject.xml
@@ -1,10 +1,8 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="objectcontents" title="オブジェクト・コンテンツ">
- <text type="string" length="1" name="object_name">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="objectcontents" title="オブジェクトã®ä¸­èº«">
+ <text name="object_name">
[DESC]:
</text>
- <button label="æŒã¡ç‰©ã«ã‚³ãƒ”ー" label_selected="æŒã¡ç‰©ã«ã‚³ãƒ”ー"
- name="copy_to_inventory_button" />
- <button label="コピーã—ã¦è£…ç€" label_selected="コピーã—ã¦è£…ç€"
- name="copy_and_wear_button" />
+ <button label="æŒã¡ç‰©ã«ã‚³ãƒ”ー" label_selected="æŒã¡ç‰©ã«ã‚³ãƒ”ー" name="copy_to_inventory_button"/>
+ <button label="コピーã—ã¦è£…ç€" label_selected="コピーã—ã¦è£…ç€" name="copy_and_wear_button"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_outgoing_call.xml b/indra/newview/skins/default/xui/ja/floater_outgoing_call.xml
new file mode 100644
index 0000000000..416d104586
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_outgoing_call.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="outgoing call" title="コール中">
+ <floater.string name="localchat">
+ è¿‘ãã®ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆ
+ </floater.string>
+ <floater.string name="anonymous">
+ 匿åユーザー
+ </floater.string>
+ <floater.string name="VoiceInviteP2P">
+ ãŒã‚³ãƒ¼ãƒ«ã—ã¦ã„ã¾ã™ã€‚
+ </floater.string>
+ <floater.string name="VoiceInviteAdHoc">
+ ãŒã‚³ãƒ³ãƒ•ã‚¡ãƒ¬ãƒ³ã‚¹ãƒãƒ£ãƒƒãƒˆã§ã€ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆã«å‚加ã—ã¾ã—ãŸã€‚
+ </floater.string>
+ <text name="connecting">
+ [CALLEE_NAME] ã«æŽ¥ç¶šä¸­
+ </text>
+ <text name="calling">
+ [CALLEE_NAME] ã«ã‚³ãƒ¼ãƒ«ä¸­
+ </text>
+ <text name="noanswer">
+ 繋ãŒã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚ ã‚ã¨ã§ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。
+ </text>
+ <text name="leaving">
+ [CURRENT_CHAT] を終了ã—ã¾ã™ã€‚
+ </text>
+ <button label="キャンセル" label_selected="キャンセル" name="Cancel"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_pay.xml b/indra/newview/skins/default/xui/ja/floater_pay.xml
index 114cb90bf2..4564354899 100644
--- a/indra/newview/skins/default/xui/ja/floater_pay.xml
+++ b/indra/newview/skins/default/xui/ja/floater_pay.xml
@@ -1,21 +1,25 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Give Money" title="">
- <button label="L$1" label_selected="L$1" name="fastpay 1" />
- <button label="L$5" label_selected="L$5" name="fastpay 5" />
- <button label="L$10" label_selected="L$10" name="fastpay 10" />
- <button label="L$20" label_selected="L$20" name="fastpay 20" />
- <button label="支払ã„" label_selected="支払ã„" name="pay btn" />
- <button label="å–り消ã—" label_selected="å–り消ã—" name="cancel btn" />
- <text type="string" length="1" name="payee_label">
- 支払ã„先:
+ <string name="payee_group">
+ グループã«æ”¯æ‰•ã†
+ </string>
+ <string name="payee_resident">
+ ä½äººã«æ”¯æ‰•ã†
+ </string>
+ <text name="payee_label">
+ 支払ã„:
</text>
- <text type="string" length="1" name="payee_name">
+ <icon name="icon_person" tool_tip="ä½äºº"/>
+ <text name="payee_name">
[FIRST] [LAST]
</text>
- <text type="string" length="1" name="fastpay text">
- 一括払ã„:
- </text>
- <text type="string" length="1" name="amount text">
- 金é¡ï¼š
+ <button label="L$1" label_selected="L$1" name="fastpay 1"/>
+ <button label="L$5" label_selected="L$5" name="fastpay 5"/>
+ <button label="L$10" label_selected="L$10" name="fastpay 10"/>
+ <button label="L$20" label_selected="L$20" name="fastpay 20"/>
+ <text name="amount text">
+ 金é¡ã‚’指定:
</text>
+ <button label="支払ã„" label_selected="支払ã„" name="pay btn"/>
+ <button label="å–り消ã—" label_selected="å–り消ã—" name="cancel btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_pay_object.xml b/indra/newview/skins/default/xui/ja/floater_pay_object.xml
index 6ad9c7c2b8..ffd57ab67b 100644
--- a/indra/newview/skins/default/xui/ja/floater_pay_object.xml
+++ b/indra/newview/skins/default/xui/ja/floater_pay_object.xml
@@ -1,30 +1,29 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Give Money" title="">
- <text type="string" length="1" name="payee_group">
- グループã¸ã®æ”¯æ‰•ã„:
- </text>
- <text type="string" length="1" name="payee_resident">
- ä½äººã¸ã®æ”¯æ‰•ã„:
- </text>
- <text type="string" length="1" name="payee_name">
+ <string name="payee_group">
+ グループã«æ”¯æ‰•ã†
+ </string>
+ <string name="payee_resident">
+ ä½äººã«æ”¯æ‰•ã†
+ </string>
+ <icon name="icon_person" tool_tip="ä½äºº"/>
+ <text name="payee_name">
[FIRST] [LAST]
</text>
- <text type="string" length="1" name="object_name_label">
+ <text name="object_name_label">
オブジェクトを介ã—ã¦ï¼š
</text>
- <text type="string" length="1" name="object_name_text">
+ <icon name="icon_object" tool_tip="オブジェクト"/>
+ <text name="object_name_text">
...
</text>
- <text type="string" length="1" name="fastpay text">
- 一括払ã„:
- </text>
- <text type="string" length="1" name="amount text">
- 金é¡ï¼š
+ <button label="L$1" label_selected="L$1" name="fastpay 1"/>
+ <button label="L$5" label_selected="L$5" name="fastpay 5"/>
+ <button label="L$10" label_selected="L$10" name="fastpay 10"/>
+ <button label="L$20" label_selected="L$20" name="fastpay 20"/>
+ <text name="amount text">
+ 金é¡ã‚’指定:
</text>
- <button label="L$1" label_selected="L$1" name="fastpay 1" />
- <button label="L$5" label_selected="L$5" name="fastpay 5" />
- <button label="L$10" label_selected="L$10" name="fastpay 10" />
- <button label="L$20" label_selected="L$20" name="fastpay 20" />
- <button label="支払ã„" label_selected="支払ã„" name="pay btn" />
- <button label="å–り消ã—" label_selected="å–り消ã—" name="cancel btn" />
+ <button label="支払ã„" label_selected="支払ã„" name="pay btn"/>
+ <button label="å–り消ã—" label_selected="å–り消ã—" name="cancel btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_postcard.xml b/indra/newview/skins/default/xui/ja/floater_postcard.xml
index 65c4f65185..b2ca059ccd 100644
--- a/indra/newview/skins/default/xui/ja/floater_postcard.xml
+++ b/indra/newview/skins/default/xui/ja/floater_postcard.xml
@@ -1,40 +1,37 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Postcard" title="スナップショットをEメールã§é€ä¿¡">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Postcard" title="スナップショットをメール">
<text name="to_label">
ä½äººã®Eメール:
</text>
- <line_editor left="145" name="to_form" width="125" />
+ <line_editor left="145" name="to_form" width="125"/>
<text name="from_label">
ã‚ãªãŸã®Eメール:
</text>
- <line_editor left="145" name="from_form" width="125" />
+ <line_editor left="145" name="from_form" width="125"/>
<text name="name_label">
ã‚ãªãŸã®åå‰ï¼š
</text>
- <line_editor left="145" name="name_form" width="125" />
+ <line_editor left="145" name="name_form" width="125"/>
<text name="subject_label">
件å:
</text>
- <line_editor label="件åã‚’ã“ã“ã«å…¥åŠ›" left="145" name="subject_form"
- width="125" />
+ <line_editor label="件åã‚’ã“ã“ã«å…¥åŠ›" left="145" name="subject_form" width="125"/>
<text name="msg_label">
メッセージ:
</text>
<text_editor bottom_delta="-120" height="110" name="msg_form">
メッセージをã“ã“ã«å…¥åŠ›ã—ã¦ãã ã•ã„。
</text_editor>
- <check_box label="ウェブ上ã§å…¬é–‹" name="allow_publish_check"
- tool_tip="ã“ã®ãƒã‚¹ãƒˆã‚«ãƒ¼ãƒ‰ã‚’ウェブ上ã§å…¬é–‹ã—ã¾ã™ã€‚" />
- <check_box label="æˆäººå‘ã‘コンテンツ" name="mature_check"
- tool_tip="ã“ã®ãƒã‚¹ãƒˆã‚«ãƒ¼ãƒ‰ã«ã¯æˆäººå‘ã‘内容ãŒå«ã¾ã‚Œã¾ã™ã€‚" />
- <button label="?" left="300" name="publish_help_btn" />
+ <check_box label="ウェブ上ã§å…¬é–‹" name="allow_publish_check" tool_tip="ã“ã®ãƒã‚¹ãƒˆã‚«ãƒ¼ãƒ‰ã‚’ウェブ上ã§å…¬é–‹ã—ã¾ã™ã€‚"/>
+ <check_box label="æˆäººå‘ã‘コンテンツ" name="mature_check" tool_tip="ã“ã®ãƒã‚¹ãƒˆã‚«ãƒ¼ãƒ‰ã«ã¯æˆäººå‘ã‘内容ãŒå«ã¾ã‚Œã¾ã™ã€‚"/>
+ <button label="?" left="300" name="publish_help_btn"/>
<text name="fine_print">
ã“ã®å—信者ãŒSLã«å‚加ã™ã‚‹ã¨ã€ã‚ãªãŸã«ç´¹ä»‹ãƒœãƒ¼ãƒŠã‚¹ãŒå…¥ã‚Šã¾ã™
</text>
- <button bottom_delta="-52" label="å–り消ã—" name="cancel_btn" />
- <button label="é€ä¿¡" name="send_btn" />
+ <button bottom_delta="-52" label="å–り消ã—" name="cancel_btn"/>
+ <button label="é€ä¿¡" name="send_btn"/>
<text name="default_subject">
- Second Life ã‹ã‚‰ã®ãƒã‚¹ãƒˆã‚«ãƒ¼ãƒ‰
+ [SECOND_LIFE] ã‹ã‚‰ã®ãƒã‚¹ãƒˆã‚«ãƒ¼ãƒ‰ã§ã™ã€‚
</text>
<text name="default_message">
ã“ã‚Œã¯çµ¶å¯¾ãƒã‚§ãƒƒã‚¯ï¼
diff --git a/indra/newview/skins/default/xui/ja/floater_preferences.xml b/indra/newview/skins/default/xui/ja/floater_preferences.xml
index 3d0c82bd41..7c9a8b61bd 100644
--- a/indra/newview/skins/default/xui/ja/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/ja/floater_preferences.xml
@@ -1,8 +1,15 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Preferences" title="環境設定">
- <button label="OK" label_selected="OK" name="OK" />
- <button label="å–り消ã—" label_selected="å–り消ã—" name="Cancel" />
- <button label="é©ç”¨" label_selected="é©ç”¨" name="Apply" />
- <button label="概è¦" label_selected="概è¦" name="About..." />
- <button label="ヘルプ" label_selected="ヘルプ" name="Help" />
+ <button label="OK" label_selected="OK" name="OK"/>
+ <button label="å–り消ã—" label_selected="å–り消ã—" name="Cancel"/>
+ <tab_container name="pref core">
+ <panel label="一般" name="general"/>
+ <panel label="グラフィック" name="display"/>
+ <panel label="プライãƒã‚·ãƒ¼" name="im"/>
+ <panel label="サウンド" name="audio"/>
+ <panel label="ãƒãƒ£ãƒƒãƒˆ" name="chat"/>
+ <panel label="警告" name="msgs"/>
+ <panel label="セットアップ" name="input"/>
+ <panel label="詳細" name="advanced1"/>
+ </tab_container>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_preview_animation.xml b/indra/newview/skins/default/xui/ja/floater_preview_animation.xml
index dfb90f2c20..fb2f2c7433 100644
--- a/indra/newview/skins/default/xui/ja/floater_preview_animation.xml
+++ b/indra/newview/skins/default/xui/ja/floater_preview_animation.xml
@@ -1,10 +1,11 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="preview_anim">
- <text type="string" length="1" name="desc txt">
+ <floater.string name="Title">
+ アニメーション: [NAME]
+ </floater.string>
+ <text name="desc txt">
説明:
</text>
- <button label="世界ã§å†ç”Ÿ" label_selected="åœæ­¢" name="Anim play btn"
- tool_tip="ã“ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’ä»–ã®äººã‚‚見るã“ã¨ãŒã§ãるよã†ã«å†ç”Ÿã—ã¾ã™ã€‚" />
- <button label="ローカルã«å†ç”Ÿ" label_selected="åœæ­¢" name="Anim audition btn"
- tool_tip="ã“ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’自分専用ã«å†ç”Ÿã—ã¾ã™ã€‚" />
+ <button label="世界ã§å†ç”Ÿ" label_selected="åœæ­¢" name="Anim play btn" tool_tip="他人ã«è¦‹ãˆã‚‹ã‚ˆã†ã«å†ç”Ÿ"/>
+ <button label="ローカルã«å†ç”Ÿ" label_selected="åœæ­¢" name="Anim audition btn" tool_tip="自分ã ã‘ãŒè¦‹ãˆã‚‹ã‚ˆã†ã«å†ç”Ÿ"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_preview_classified.xml b/indra/newview/skins/default/xui/ja/floater_preview_classified.xml
index f0770b2ed5..ba3bb028b2 100644
--- a/indra/newview/skins/default/xui/ja/floater_preview_classified.xml
+++ b/indra/newview/skins/default/xui/ja/floater_preview_classified.xml
@@ -1,2 +1,6 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="classified_preview" title="クラシファイド広告情報" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="classified_preview" title="クラシファイド広告情報">
+ <floater.string name="Title">
+ クラシファイド広告: [NAME]
+ </floater.string>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_preview_event.xml b/indra/newview/skins/default/xui/ja/floater_preview_event.xml
index 9ecabfabb0..21f57ca7a3 100644
--- a/indra/newview/skins/default/xui/ja/floater_preview_event.xml
+++ b/indra/newview/skins/default/xui/ja/floater_preview_event.xml
@@ -1,2 +1,6 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="event_preview" title="イベント情報" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="event_preview" title="イベント情報">
+ <floater.string name="Title">
+ イベント: [NAME]
+ </floater.string>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_preview_gesture.xml b/indra/newview/skins/default/xui/ja/floater_preview_gesture.xml
index 9ddf537fee..4b4df98348 100644
--- a/indra/newview/skins/default/xui/ja/floater_preview_gesture.xml
+++ b/indra/newview/skins/default/xui/ja/floater_preview_gesture.xml
@@ -1,14 +1,29 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="gesture_preview">
- <string name="stop_txt">
+ <floater.string name="step_anim">
+ プレイã™ã‚‹ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ï¼š
+ </floater.string>
+ <floater.string name="step_sound">
+ プレイã™ã‚‹ã‚µã‚¦ãƒ³ãƒ‰ï¼š
+ </floater.string>
+ <floater.string name="step_chat">
+ 発言ã™ã‚‹ãƒãƒ£ãƒƒãƒˆï¼š
+ </floater.string>
+ <floater.string name="step_wait">
+ 待機:
+ </floater.string>
+ <floater.string name="stop_txt">
æ­¢ã¾ã‚‹
- </string>
- <string name="preview_txt">
+ </floater.string>
+ <floater.string name="preview_txt">
プレビュー
- </string>
- <string name="none_text">
+ </floater.string>
+ <floater.string name="none_text">
-- ãªã— --
- </string>
+ </floater.string>
+ <floater.string name="Title">
+ ジェスãƒãƒ£ãƒ¼ï¼š [NAME]
+ </floater.string>
<text name="desc_label">
説明:
</text>
@@ -22,39 +37,28 @@
<text name="key_label">
ショートカット・キー:
</text>
- <combo_box label="ãªã—" name="modifier_combo" left="160"/>
+ <combo_box label="ãªã—" left="160" name="modifier_combo"/>
<combo_box label="ãªã—" name="key_combo"/>
<text name="library_label">
ライブラリ:
</text>
+ <scroll_list name="library_list"/>
+ <button label="追加>>" name="add_btn"/>
<text name="steps_label">
手順:
</text>
- <scroll_list name="library_list">
- アニメーション
-サウンド
-ãƒãƒ£ãƒƒãƒˆ
-å¾…æ©Ÿ
- </scroll_list>
- <button label="追加>>" name="add_btn"/>
- <button label="上ã«ç§»å‹•" name="up_btn"/>
- <button label="下ã«ç§»å‹•" name="down_btn"/>
+ <button label="上" name="up_btn"/>
+ <button label="下" name="down_btn"/>
<button label="削除" name="delete_btn"/>
- <text name="help_label">
- 待機ステップを追加ã—ãªã„é™ã‚Šã€
-ã™ã¹ã¦ã®ã‚¹ãƒ†ãƒƒãƒ—ãŒåŒæ™‚ã«è¡Œã‚ã‚Œ
-ã¾ã™ã€‚
- </text>
<radio_group name="animation_trigger_type">
- <radio_item name="start">
- 開始
- </radio_item>
- <radio_item name="stop">
- åœæ­¢
- </radio_item>
+ <radio_item label="開始" name="start"/>
+ <radio_item label="åœæ­¢" name="stop"/>
</radio_group>
<check_box label="アニメーションãŒå®Œäº†ã™ã‚‹ã¾ã§" name="wait_anim_check"/>
<check_box label="秒表示ã®æ™‚é–“" name="wait_time_check"/>
+ <text name="help_label">
+ 待機ステップを入れãªã„é™ã‚Šã¯ã€ã™ã¹ã¦ã®ã‚¹ãƒ†ãƒƒãƒ—ãŒåŒæ™‚ã«èµ·ã“ã‚Šã¾ã™ã€‚
+ </text>
<check_box label="アクティブ" left="120" name="active_check" tool_tip="アクティブ・ジェスãƒãƒ£ãƒ¼ã¯ã€ãƒˆãƒªã‚¬ãƒ¼ãƒ»ãƒ•ãƒ¬ãƒ¼ã‚ºã‚’使ã†ã‹ã€ã¾ãŸã¯ãƒ›ãƒƒãƒˆãƒ»ã‚­ãƒ¼ã‚’押ã™ã“ã¨ã«ã‚ˆã£ã¦ãƒˆãƒªã‚¬ãƒ¼ã§ãã¾ã™ã€‚ 1ã¤ã®ã‚·ãƒ§ãƒ¼ãƒˆã‚«ãƒƒãƒˆãƒ»ã‚­ãƒ¼ã«2ã¤ä»¥ä¸Šã®ã‚¸ã‚§ã‚¹ãƒãƒ£ãƒ¼ãŒå‰²ã‚Šå½“ã¦ã‚‰ã‚ŒãŸå ´åˆã€ãã®ã‚¸ã‚§ã‚¹ãƒãƒ£ãƒ¼ã¯ä¸¡æ–¹ã¨ã‚‚アクティブã§ã¯ãªããªã‚Šã¾ã™ã€‚"/>
<button label="プレビュー" name="preview_btn"/>
<button label="ä¿å­˜" name="save_btn"/>
diff --git a/indra/newview/skins/default/xui/ja/floater_preview_gesture_info.xml b/indra/newview/skins/default/xui/ja/floater_preview_gesture_info.xml
new file mode 100644
index 0000000000..682b295a14
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_preview_gesture_info.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Gesture" title="ジェスãƒãƒ£ãƒ¼ã®ã‚·ãƒ§ãƒ¼ãƒˆã‚«ãƒƒãƒˆ"/>
diff --git a/indra/newview/skins/default/xui/ja/floater_preview_gesture_shortcut.xml b/indra/newview/skins/default/xui/ja/floater_preview_gesture_shortcut.xml
new file mode 100644
index 0000000000..596699d6c1
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_preview_gesture_shortcut.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Gesture" title="ジェスãƒãƒ£ãƒ¼ã®ã‚·ãƒ§ãƒ¼ãƒˆã‚«ãƒƒãƒˆ">
+ <text name="trigger_label">
+ ãƒãƒ£ãƒƒãƒˆï¼š
+ </text>
+ <text name="key_label">
+ キーボード:
+ </text>
+ <combo_box label="ãªã—" name="modifier_combo"/>
+ <combo_box label="ãªã—" name="key_combo"/>
+ <text name="replace_text" tool_tip="ã“れらã®å˜èªžã«ãƒˆãƒªã‚¬ãƒ¼ã¨ãªã‚‹å˜èªžã‚’ç½®ãæ›ãˆã¾ã™ã€‚ 例ãˆã°ã€ã€Œhowdyã€ã¨ã€Œhelloã€ã‚’ç½®ãæ›ãˆã‚‹ã¨ã€ã€ŒI wanted to say helloã€ã¨ã„ã†ãƒãƒ£ãƒƒãƒˆã¯ã€ã‚¸ã‚§ã‚¹ãƒãƒ£ãƒ¼ã‚’交ãˆãªãŒã‚‰ã®ã€ŒI wanted to say howdyã€ã«å¤‰ã‚ã‚Šã¾ã™ã€‚">
+ ç½®ãæ›ãˆï¼š
+ </text>
+ <line_editor name="replace_editor" tool_tip="ã“れらã®å˜èªžã«ãƒˆãƒªã‚¬ãƒ¼ã¨ãªã‚‹å˜èªžã‚’ç½®ãæ›ãˆã¾ã™ã€‚ 例ãˆã°ã€ã€Œhowdyã€ã¨ã€Œhelloã€ã‚’ç½®ãæ›ãˆã‚‹ã¨ã€ã€ŒI wanted to say helloã€ã¨ã„ã†ãƒãƒ£ãƒƒãƒˆã¯ã€ã‚¸ã‚§ã‚¹ãƒãƒ£ãƒ¼ã‚’交ãˆãªãŒã‚‰ã®ã€ŒI wanted to say howdyã€ã«å¤‰ã‚ã‚Šã¾ã™ã€‚"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_preview_gesture_steps.xml b/indra/newview/skins/default/xui/ja/floater_preview_gesture_steps.xml
new file mode 100644
index 0000000000..682b295a14
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_preview_gesture_steps.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Gesture" title="ジェスãƒãƒ£ãƒ¼ã®ã‚·ãƒ§ãƒ¼ãƒˆã‚«ãƒƒãƒˆ"/>
diff --git a/indra/newview/skins/default/xui/ja/floater_preview_notecard.xml b/indra/newview/skins/default/xui/ja/floater_preview_notecard.xml
index 2fb42d1fae..0ab1efd127 100644
--- a/indra/newview/skins/default/xui/ja/floater_preview_notecard.xml
+++ b/indra/newview/skins/default/xui/ja/floater_preview_notecard.xml
@@ -1,16 +1,22 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="preview notecard" title="メモ:">
- <button label="ä¿å­˜" label_selected="ä¿å­˜" name="Save" />
- <text type="string" length="1" name="desc txt">
+ <floater.string name="no_object">
+ ã“ã®ãƒŽãƒ¼ãƒˆã‚’å«ã‚“ã ã‚ªãƒ–ジェクトãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="not_allowed">
+ ã“ã®ãƒŽãƒ¼ãƒˆã‚’見る権é™ãŒã‚ã‚Šã¾ã›ã‚“。
+ </floater.string>
+ <floater.string name="Title">
+ ノートカード: [NAME]
+ </floater.string>
+ <floater.string label="ä¿å­˜" label_selected="ä¿å­˜" name="Save">
+ ä¿å­˜
+ </floater.string>
+ <text name="desc txt">
説明:
</text>
- <text_editor type="string" length="1" name="Notecard Editor">
+ <text_editor name="Notecard Editor">
ローディング...
</text_editor>
- <text name="no_object">
- ã“ã®ãƒŽãƒ¼ãƒˆã‚’å«ã‚“ã ã‚ªãƒ–ジェクトãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
- </text>
- <text name="not_allowed">
- ã‚ãªãŸã¯ã“ã®ãƒŽãƒ¼ãƒˆã‚’見るã“ã¨ãŒã§ãã¾ã›ã‚“。
- </text>
+ <button label="ä¿å­˜" label_selected="ä¿å­˜" name="Save"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_preview_sound.xml b/indra/newview/skins/default/xui/ja/floater_preview_sound.xml
index d455d4cea9..d3c06cbef4 100644
--- a/indra/newview/skins/default/xui/ja/floater_preview_sound.xml
+++ b/indra/newview/skins/default/xui/ja/floater_preview_sound.xml
@@ -1,11 +1,11 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="preview_sound">
- <text type="string" length="1" name="desc txt">
+ <floater.string name="Title">
+ サウンド: [NAME]
+ </floater.string>
+ <text name="desc txt">
説明:
</text>
- <button label="世界ã§å†ç”Ÿ" label_selected="世界ã§å†ç”Ÿ" name="Sound play btn"
- tool_tip="ã“ã®ã‚µã‚¦ãƒ³ãƒ‰ã‚’ä»–ã®äººã‚‚èžãã“ã¨ãŒã§ãるよã†ã«å†ç”Ÿã—ã¾ã™ã€‚" />
- <button label="ローカルã«å†ç”Ÿ" label_selected="ローカルã«å†ç”Ÿ"
- name="Sound audition btn"
- tool_tip="ã“ã®ã‚µã‚¦ãƒ³ãƒ‰ã‚’自分専用ã«å†ç”Ÿã—ã¾ã™ã€‚" />
+ <button label="世界ã§å†ç”Ÿ" label_selected="世界ã§å†ç”Ÿ" name="Sound play btn" tool_tip="他人ãŒèžã“ãˆã‚‹ã‚ˆã†ã«å†ç”Ÿ"/>
+ <button label="ローカルã«å†ç”Ÿ" label_selected="ローカルã«å†ç”Ÿ" name="Sound audition btn" tool_tip="自分ã ã‘ãŒèžã“ãˆã‚‹ã‚ˆã†ã«å†ç”Ÿ"/>
</floater>
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 affcc51b0b..3313ae84b9 100644
--- a/indra/newview/skins/default/xui/ja/floater_preview_texture.xml
+++ b/indra/newview/skins/default/xui/ja/floater_preview_texture.xml
@@ -1,9 +1,46 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="preview_texture">
- <text type="string" length="1" name="desc txt">
+ <floater.string name="Title">
+ テクスãƒãƒ£ï¼š [NAME]
+ </floater.string>
+ <floater.string name="Copy">
+ æŒã¡ç‰©ã«ã‚³ãƒ”ー
+ </floater.string>
+ <text name="desc txt">
説明:
</text>
- <text type="string" length="1" name="dimensions">
- 寸法:[HEIGHT]x[WIDTH]
+ <button label="OK" name="Keep"/>
+ <button label="キャンセル" name="Discard"/>
+ <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>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_region_info.xml b/indra/newview/skins/default/xui/ja/floater_region_info.xml
index 7ac7facce5..d08c51c61e 100644
--- a/indra/newview/skins/default/xui/ja/floater_region_info.xml
+++ b/indra/newview/skins/default/xui/ja/floater_region_info.xml
@@ -1,2 +1,2 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="regioninfo" title="地域/ä¸å‹•ç”£" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="regioninfo" title="地域 / ä¸å‹•ç”£"/>
diff --git a/indra/newview/skins/default/xui/ja/floater_report_abuse.xml b/indra/newview/skins/default/xui/ja/floater_report_abuse.xml
index b523023e6e..599cd5d98d 100644
--- a/indra/newview/skins/default/xui/ja/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/ja/floater_report_abuse.xml
@@ -1,12 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="floater_report_abuse" title="å«ŒãŒã‚‰ã›ã®å ±å‘Š">
- <texture_picker label="" name="screenshot"/>
- <check_box label="スクリーï¾ï½¼ï½®ï½¯ï¾„ã‚’å«ã‚ã‚‹" name="screen_check"/>
+ <floater.string name="Screenshot">
+ スクリーンショット
+ </floater.string>
+ <check_box label="ã“ã®ã‚¹ã‚¯ãƒªãƒ¼ãƒ³ã‚·ãƒ§ãƒƒãƒˆã‚’使用" name="screen_check"/>
<text name="reporter_title">
報告者:
</text>
<text name="reporter_field">
- Loremipsum Dolorsitamut
+ Loremipsum Dolorsitamut Longnamez
</text>
<text name="sim_title">
地域:
@@ -21,11 +23,11 @@
{128.1, 128.1, 15.4}
</text>
<text name="select_object_label">
- ボタンを使ã£ã¦ã‚ªãƒ–ジェクトをé¸æŠžï¼š
+ ボタンをクリックã—ã¦ã‹ã‚‰ã€æ‚ªæ„ã®ã‚るオブジェクトをクリック:
</text>
<button label="" label_selected="" name="pick_btn" tool_tip="オブジェクト・ピッカー - ã“ã®å ±å‘Šã®ä¸»é¡Œã¨ãªã‚‹ã‚ªãƒ–ジェクトを特定"/>
<text name="object_name_label">
- åå‰ï¼š
+ オブジェクト:
</text>
<text name="object_name">
Consetetur Sadipscing
@@ -34,132 +36,53 @@
オーナー:
</text>
<text name="owner_name">
- Hendrerit Vulputate
+ Hendrerit Vulputate Kamawashi Longname
</text>
<combo_box name="category_combo" tool_tip="カテゴリー -- ã“ã®å ±å‘Šã«æœ€ã‚‚é©ã—ãŸã‚«ãƒ†ã‚´ãƒªãƒ¼ã‚’é¸æŠžã—ã¦ãã ã•ã„">
- <combo_item name="Select_category">
- カテゴリーをé¸æŠž
- </combo_item>
- <combo_item name="Age__Age_play">
- 年齢>年齢å½è¨¼
- </combo_item>
- <combo_item name="Age__Adult_resident_on_Teen_Second_Life">
- 年齢>æˆäººã®ä½äººãŒTeen Second Life上ã«ã„ã‚‹
- </combo_item>
- <combo_item name="Age__Underage_resident_outside_of_Teen_Second_Life">
- 年齢>未æˆå¹´ãªä½äººãŒTeen Second Lifeã®å¤–ã«ã„ã‚‹
- </combo_item>
- <combo_item name="Assault__Combat_sandbox___unsafe_area">
- 攻撃>コンãƒãƒƒãƒˆãƒ»ã‚µãƒ³ãƒ‰ãƒœãƒƒã‚¯ã‚¹/å±é™ºãªã‚¨ãƒªã‚¢
- </combo_item>
- <combo_item name="Assault__Safe_area">
- 攻撃>安全ãªã‚¨ãƒªã‚¢
- </combo_item>
- <combo_item name="Assault__Weapons_testing_sandbox">
- 攻撃>武器テスト用サンドボックス
- </combo_item>
- <combo_item name="Commerce__Failure_to_deliver_product_or_service">
- 商å–引>製å“ã¾ãŸã¯ã‚µãƒ¼ãƒ“スã®æä¾›ãŒè¡Œã‚ã‚Œãªã„
- </combo_item>
- <combo_item name="Disclosure__Real_world_information">
- 開示>リアルワールドã®æƒ…å ±
- </combo_item>
- <combo_item name="Disclosure__Remotely_monitoring chat">
- 開示>離れãŸã¨ã“ã‚ã‹ã‚‰ãƒãƒ£ãƒƒãƒˆã‚’モニターã—ã¦ã„ã‚‹
- </combo_item>
- <combo_item name="Disclosure__Second_Life_information_chat_IMs">
- 開示>Second Lifeã®æƒ…å ±/ãƒãƒ£ãƒƒãƒˆ/IM
- </combo_item>
- <combo_item name="Disturbing_the_peace__Unfair_use_of_region_resources">
- å¹³ç©ã‚’ä¹±ã™è¡Œç‚ºï¼žåœ°åŸŸãƒªã‚½ãƒ¼ã‚¹ã®ä½¿ç”¨ãŒä¸å…¬å¹³
- </combo_item>
- <combo_item name="Disturbing_the_peace__Excessive_scripted_objects">
- å¹³ç©ã‚’ä¹±ã™è¡Œç‚ºï¼žã‚¹ã‚¯ãƒªãƒ—ト・オブジェクトã®ä¹±ç”¨
- </combo_item>
- <combo_item name="Disturbing_the_peace__Object_littering">
- å¹³ç©ã‚’ä¹±ã™è¡Œç‚ºï¼žã‚ªãƒ–ジェクトã®æ¨ã¦ç½®ã
- </combo_item>
- <combo_item name="Disturbing_the_peace__Repetitive_spam">
- å¹³ç©ã‚’ä¹±ã™è¡Œç‚ºï¼žç¹°ã‚Šè¿”ã—スパム
- </combo_item>
- <combo_item name="Disturbing_the_peace__Unwanted_advert_spam">
- å¹³ç©ã‚’ä¹±ã™è¡Œç‚ºï¼žä¸è¦ãªåºƒå‘Šã‚¹ãƒ‘ム
- </combo_item>
- <combo_item name="Fraud__L$">
- è©æ¬ºï¼ž L$
- </combo_item>
- <combo_item name="Fraud__Land">
- è©æ¬ºï¼žåœŸåœ°
- </combo_item>
- <combo_item name="Fraud__Pyramid_scheme_or_chain_letter">
- è©æ¬ºï¼žãƒžãƒ«ãƒå•†æ³•ã¾ãŸã¯ãƒã‚§ãƒ¼ãƒ³ãƒ»ãƒ¡ãƒ¼ãƒ«
- </combo_item>
- <combo_item name="Fraud__US$">
- è©æ¬ºï¼ž US$
- </combo_item>
- <combo_item name="Harassment__Advert_farms___visual_spam">
- å«ŒãŒã‚‰ã›ï¼žåºƒå‘Šå§”託/視覚的ãªã‚¹ãƒ‘ム
- </combo_item>
- <combo_item name="Harassment__Defaming_individuals_or_groups">
- å«ŒãŒã‚‰ã›ï¼žå€‹äººã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—ã®ä¸­å‚·
- </combo_item>
- <combo_item name="Harassment__Impeding_movement">
- å«ŒãŒã‚‰ã›ï¼žç§»å‹•ã®å¦¨å®³
- </combo_item>
- <combo_item name="Harassment__Sexual_harassment">
- å«ŒãŒã‚‰ã›ï¼žæ€§çš„ãªå«ŒãŒã‚‰ã›
- </combo_item>
- <combo_item name="Harassment__Solicting_inciting_others_to_violate_ToS">
- å«ŒãŒã‚‰ã›ï¼žåˆ©ç”¨è¦ç´„(ToS)ã«é•åã™ã‚‹è¡Œç‚ºã‚’è¡Œã†ã‚ˆã†ä»–者を勧誘/扇動
- </combo_item>
- <combo_item name="Harassment__Verbal_abuse">
- å«ŒãŒã‚‰ã›ï¼žæš´è¨€
- </combo_item>
- <combo_item name="Indecency__Broadly_offensive_content_or_conduct">
- ã‚ã„ã›ã¤ï¼žè‘—ã—ãä¸å¿«ã§ã‚ã‚‹ã¨è¦‹ãªã•ã‚Œã‚‹ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã¾ãŸã¯è¡Œç‚º
- </combo_item>
- <combo_item name="Indecency__Inappropriate_avatar_name">
- ã‚ã„ã›ã¤ï¼žä¸é©åˆ‡ãªã‚¢ãƒã‚¿ãƒ¼å
- </combo_item>
- <combo_item name="Indecency__Mature_content_in_PG_region">
- ã‚ã„ã›ã¤ï¼žPG地域ã§ã®ä¸é©åˆ‡ãªã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã¾ãŸã¯è¡Œç‚º
- </combo_item>
- <combo_item name="Indecency__Inappropriate_content_in_Mature_region">
- ã‚ã„ã›ã¤ï¼žMature地域ã§ã®ä¸é©åˆ‡ãªã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã¾ãŸã¯è¡Œç‚º
- </combo_item>
- <combo_item name="Intellectual_property_infringement_Content_Removal">
- 知的財産ã®ä¾µå®³ï¼žã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã®æ’¤åŽ»
- </combo_item>
- <combo_item name="Intellectual_property_infringement_CopyBot_or_Permissions_Exploit">
- 知的財産ã®ä¾µå®³ï¼žã‚³ãƒ”ーBotåŠã³æ¨©é™ã®æ‚ªç”¨
- </combo_item>
- <combo_item name="Intolerance">
- ä¸å¯›å®¹
- </combo_item>
- <combo_item name="Land__Abuse_of_sandbox_resources">
- 土地>サンドボックス・リソースã®ä¹±ç”¨
- </combo_item>
- <combo_item name="Land__Encroachment__Objects_textures">
- 土地>ä¸æ³•ä¾µå…¥ï¼žã‚ªãƒ–ジェクト/テクスãƒãƒ£ãƒ¼
- </combo_item>
- <combo_item name="Land__Encroachment__Particles">
- 土地>ä¸æ³•ä¾µå…¥ï¼žãƒ‘ーティクル
- </combo_item>
- <combo_item name="Land__Encroachment__Trees_plants">
- 土地>ä¸æ³•ä¾µå…¥ï¼žæ¨¹æœ¨/æ¤ç‰©
- </combo_item>
- <combo_item name="Wagering_gambling">
- è³­ã‘/ギャンブル
- </combo_item>
- <combo_item name="Other">
- ãã®ä»–
- </combo_item>
+ <combo_box.item label="カテゴリーをé¸æŠž" name="Select_category"/>
+ <combo_box.item label="年齢>年齢å½è¨¼" name="Age__Age_play"/>
+ <combo_box.item label="年齢>æˆäººã®ä½äººãŒTeen Second Life上ã«ã„ã‚‹" name="Age__Adult_resident_on_Teen_Second_Life"/>
+ <combo_box.item label="年齢>未æˆå¹´ãªä½äººãŒTeen Second Lifeã®å¤–ã«ã„ã‚‹" name="Age__Underage_resident_outside_of_Teen_Second_Life"/>
+ <combo_box.item label="攻撃>コンãƒãƒƒãƒˆãƒ»ã‚µãƒ³ãƒ‰ãƒœãƒƒã‚¯ã‚¹/å±é™ºãªã‚¨ãƒªã‚¢" name="Assault__Combat_sandbox___unsafe_area"/>
+ <combo_box.item label="攻撃>安全ãªã‚¨ãƒªã‚¢" name="Assault__Safe_area"/>
+ <combo_box.item label="攻撃>武器テスト用サンドボックス" name="Assault__Weapons_testing_sandbox"/>
+ <combo_box.item label="商å–引>製å“ã¾ãŸã¯ã‚µãƒ¼ãƒ“スã®æä¾›ãŒè¡Œã‚ã‚Œãªã„" name="Commerce__Failure_to_deliver_product_or_service"/>
+ <combo_box.item label="開示>リアルワールドã®æƒ…å ±" name="Disclosure__Real_world_information"/>
+ <combo_box.item label="開示>離れãŸã¨ã“ã‚ã‹ã‚‰ãƒãƒ£ãƒƒãƒˆã‚’モニターã—ã¦ã„ã‚‹" name="Disclosure__Remotely_monitoring chat"/>
+ <combo_box.item label="開示>Second Lifeã®æƒ…å ±/ãƒãƒ£ãƒƒãƒˆ/IM" name="Disclosure__Second_Life_information_chat_IMs"/>
+ <combo_box.item label="å¹³ç©ã‚’ä¹±ã™è¡Œç‚ºï¼žåœ°åŸŸãƒªã‚½ãƒ¼ã‚¹ã®ä½¿ç”¨ãŒä¸å…¬å¹³" name="Disturbing_the_peace__Unfair_use_of_region_resources"/>
+ <combo_box.item label="å¹³ç©ã‚’ä¹±ã™è¡Œç‚ºï¼žã‚¹ã‚¯ãƒªãƒ—ト・オブジェクトã®ä¹±ç”¨" name="Disturbing_the_peace__Excessive_scripted_objects"/>
+ <combo_box.item label="å¹³ç©ã‚’ä¹±ã™è¡Œç‚ºï¼žã‚ªãƒ–ジェクトã®æ¨ã¦ç½®ã" name="Disturbing_the_peace__Object_littering"/>
+ <combo_box.item label="å¹³ç©ã‚’ä¹±ã™è¡Œç‚ºï¼žç¹°ã‚Šè¿”ã—スパム" name="Disturbing_the_peace__Repetitive_spam"/>
+ <combo_box.item label="å¹³ç©ã‚’ä¹±ã™è¡Œç‚ºï¼žä¸è¦ãªåºƒå‘Šã‚¹ãƒ‘ム" name="Disturbing_the_peace__Unwanted_advert_spam"/>
+ <combo_box.item label="è©æ¬ºï¼ž L$" name="Fraud__L$"/>
+ <combo_box.item label="è©æ¬ºï¼žåœŸåœ°" name="Fraud__Land"/>
+ <combo_box.item label="è©æ¬ºï¼žãƒžãƒ«ãƒå•†æ³•ã¾ãŸã¯ãƒã‚§ãƒ¼ãƒ³ãƒ»ãƒ¡ãƒ¼ãƒ«" name="Fraud__Pyramid_scheme_or_chain_letter"/>
+ <combo_box.item label="è©æ¬ºï¼ž US$" name="Fraud__US$"/>
+ <combo_box.item label="å«ŒãŒã‚‰ã›ï¼žåºƒå‘Šå§”託/視覚的ãªã‚¹ãƒ‘ム" name="Harassment__Advert_farms___visual_spam"/>
+ <combo_box.item label="å«ŒãŒã‚‰ã›ï¼žå€‹äººã¾ãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—ã®ä¸­å‚·" name="Harassment__Defaming_individuals_or_groups"/>
+ <combo_box.item label="å«ŒãŒã‚‰ã›ï¼žç§»å‹•ã®å¦¨å®³" name="Harassment__Impeding_movement"/>
+ <combo_box.item label="å«ŒãŒã‚‰ã›ï¼žæ€§çš„ãªå«ŒãŒã‚‰ã›" name="Harassment__Sexual_harassment"/>
+ <combo_box.item label="å«ŒãŒã‚‰ã›ï¼žåˆ©ç”¨è¦ç´„(ToS)ã«é•åã™ã‚‹è¡Œç‚ºã‚’è¡Œã†ã‚ˆã†ä»–者を勧誘/扇動" name="Harassment__Solicting_inciting_others_to_violate_ToS"/>
+ <combo_box.item label="å«ŒãŒã‚‰ã›ï¼žæš´è¨€" name="Harassment__Verbal_abuse"/>
+ <combo_box.item label="ã‚ã„ã›ã¤ï¼žè‘—ã—ãä¸å¿«ã§ã‚ã‚‹ã¨è¦‹ãªã•ã‚Œã‚‹ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã¾ãŸã¯è¡Œç‚º" name="Indecency__Broadly_offensive_content_or_conduct"/>
+ <combo_box.item label="ã‚ã„ã›ã¤ï¼žä¸é©åˆ‡ãªã‚¢ãƒã‚¿ãƒ¼å" name="Indecency__Inappropriate_avatar_name"/>
+ <combo_box.item label="ã‚ã„ã›ã¤ï¼žPG地域ã§ã®ä¸é©åˆ‡ãªã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã¾ãŸã¯è¡Œç‚º" name="Indecency__Mature_content_in_PG_region"/>
+ <combo_box.item label="ã‚ã„ã›ã¤ï¼žMature地域ã§ã®ä¸é©åˆ‡ãªã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã¾ãŸã¯è¡Œç‚º" name="Indecency__Inappropriate_content_in_Mature_region"/>
+ <combo_box.item label="知的財産ã®ä¾µå®³ï¼žã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã®æ’¤åŽ»" name="Intellectual_property_infringement_Content_Removal"/>
+ <combo_box.item label="知的財産ã®ä¾µå®³ï¼žã‚³ãƒ”ーBotåŠã³æ¨©é™ã®æ‚ªç”¨" name="Intellectual_property_infringement_CopyBot_or_Permissions_Exploit"/>
+ <combo_box.item label="ä¸å¯›å®¹" name="Intolerance"/>
+ <combo_box.item label="土地>サンドボックス・リソースã®ä¹±ç”¨" name="Land__Abuse_of_sandbox_resources"/>
+ <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="Other"/>
</combo_box>
<text name="abuser_name_title">
迷惑ユーザーã®åå‰ï¼š
</text>
- <button label="ä½äººã‚’é¸æŠž" label_selected="" name="select_abuser" tool_tip="å«ŒãŒã‚‰ã›ã‚’ã—ãŸäººã®åå‰ã‚’リストã‹ã‚‰é¸æŠžã—ã¦ãã ã•ã„。"/>
- <check_box label="å«ŒãŒã‚‰ã›ã‚’ã—ãŸäººã®åå‰ãŒä¸æ˜Ž" name="omit_abuser_name" tool_tip="å«ŒãŒã‚‰ã›ã‚’ã—ãŸäººã®åå‰ã‚’æä¾›ã§ããªã„ã‹ã«ã¤ã„ã¦ã€ã“れを確èª"/>
+ <button label="é¸æŠž" label_selected="" name="select_abuser" tool_tip="å«ŒãŒã‚‰ã›ã‚’ã—ãŸäººã®åå‰ã‚’リストã‹ã‚‰é¸æŠžã—ã¦ãã ã•ã„。"/>
<text name="abuser_name_title2">
å«ŒãŒã‚‰ã›ã®èµ·ããŸå ´æ‰€ï¼š
</text>
@@ -170,13 +93,11 @@
詳細:
</text>
<text name="bug_aviso">
- 日付ã€å ´æ‰€ã€å«ŒãŒã‚‰ã›ã®ç‰¹å¾´ã€é–¢é€£ã™ã‚‹ä¼šè©±ï¼IMテキス
-トã«é–¢ã—明確ã«è¨˜å…¥ã—ã€å¯èƒ½ã§ã‚ã‚Œã°ã‚ªãƒ–ジェクトをé¸
-択ã—ã¦ãã ã•ã„。
+ ã§ãã‚‹ã ã‘具体的ã«è©³ã—ã記入ã—ã¦ãã ã•ã„。
</text>
<text name="incomplete_title">
- 注æ„:ä¸å®Œå…¨ãªãƒ¬ãƒãƒ¼ãƒˆã¯èª¿æŸ»ã•ã‚Œã¾ã›ã‚“。
+ * ä¸å®Œå…¨ãªå ±å‘Šã¯èª¿æŸ»å¯¾è±¡ã«ãªã‚Šã¾ã›ã‚“。
</text>
- <button label="å–り消ã—" label_selected="å–り消ã—" name="cancel_btn"/>
<button label="å«ŒãŒã‚‰ã›ã®å ±å‘Š" label_selected="å«ŒãŒã‚‰ã›ã®å ±å‘Š" name="send_btn"/>
+ <button label="å–り消ã—" label_selected="å–り消ã—" name="cancel_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_script_debug.xml b/indra/newview/skins/default/xui/ja/floater_script_debug.xml
index dd934e3592..0ac7a988e0 100644
--- a/indra/newview/skins/default/xui/ja/floater_script_debug.xml
+++ b/indra/newview/skins/default/xui/ja/floater_script_debug.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<multi_floater name="script debug floater" title="スクリプト警告ï¼ã‚¨ãƒ©ãƒ¼">
<tab_container name="Preview Tabs">
- <floater label="スクリプト" name="all_scripts" title="[All scripts]" />
+ <floater label="スクリプト" name="all_scripts" title="[ALL SCRIPTS]" />
</tab_container>
</multi_floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_script_debug_panel.xml b/indra/newview/skins/default/xui/ja/floater_script_debug_panel.xml
new file mode 100644
index 0000000000..e70a30fa24
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_script_debug_panel.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="script" short_title="[ALL SCRIPTS]" title="[ALL SCRIPTS]"/>
diff --git a/indra/newview/skins/default/xui/ja/floater_script_preview.xml b/indra/newview/skins/default/xui/ja/floater_script_preview.xml
index 4cf485155a..656357aa17 100644
--- a/indra/newview/skins/default/xui/ja/floater_script_preview.xml
+++ b/indra/newview/skins/default/xui/ja/floater_script_preview.xml
@@ -1,6 +1,9 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="preview lsl text" title="スクリプト:回転スクリプト">
- <text type="string" length="1" name="desc txt">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="preview lsl text" title="スクリプト: 回転スクリプト">
+ <floater.string name="Title">
+ スクリプト: [NAME]
+ </floater.string>
+ <text name="desc txt">
説明:
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_script_queue.xml b/indra/newview/skins/default/xui/ja/floater_script_queue.xml
index 7c4979a033..97e79fb483 100644
--- a/indra/newview/skins/default/xui/ja/floater_script_queue.xml
+++ b/indra/newview/skins/default/xui/ja/floater_script_queue.xml
@@ -1,4 +1,19 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="queue" title="進æ—ã®ãƒªã‚»ãƒƒãƒˆ">
- <button label="é–‰ã˜ã‚‹" label_selected="é–‰ã˜ã‚‹" name="close" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="queue" title="進行ã®ãƒªã‚»ãƒƒãƒˆ">
+ <floater.string name="Starting">
+ [COUNT] アイテム㮠[START] を開始ã—ã¾ã™ã€‚
+ </floater.string>
+ <floater.string name="Done">
+ 完了。
+ </floater.string>
+ <floater.string name="Resetting">
+ リセット中
+ </floater.string>
+ <floater.string name="Running">
+ 実行中
+ </floater.string>
+ <floater.string name="NotRunning">
+ 実行ã•ã‚Œã¦ã„ã¾ã›ã‚“
+ </floater.string>
+ <button label="é–‰ã˜ã‚‹" label_selected="é–‰ã˜ã‚‹" name="close"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_script_search.xml b/indra/newview/skins/default/xui/ja/floater_script_search.xml
index 2accc0f1e4..bc4f48c995 100644
--- a/indra/newview/skins/default/xui/ja/floater_script_search.xml
+++ b/indra/newview/skins/default/xui/ja/floater_script_search.xml
@@ -1,13 +1,13 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script search" title="スクリプト検索">
- <check_box label="大文字ã¨å°æ–‡å­—を区別ã—ãªã„" name="case_text" />
- <button label="検索" label_selected="検索" name="search_btn" />
- <button label="ç½®æ›" label_selected="ç½®æ›" name="replace_btn" />
- <button label="ã™ã¹ã¦ç½®æ›" label_selected="ã™ã¹ã¦ç½®æ›" name="replace_all_btn" />
- <text type="string" length="1" name="txt">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="script search" title="スクリプトã®æ¤œç´¢">
+ <check_box label="大文字ã¨å°æ–‡å­—を区別ã—ãªã„" name="case_text"/>
+ <button label="検索" label_selected="検索" name="search_btn"/>
+ <button label="ç½®æ›" label_selected="ç½®æ›" name="replace_btn"/>
+ <button label="ã™ã¹ã¦ç½®æ›" label_selected="ã™ã¹ã¦ç½®æ›" name="replace_all_btn"/>
+ <text name="txt">
検索
</text>
- <text type="string" length="1" name="txt2">
+ <text name="txt2">
ç½®æ›
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_search.xml b/indra/newview/skins/default/xui/ja/floater_search.xml
new file mode 100644
index 0000000000..9d65e84072
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_search.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_search" title="検索">
+ <floater.string name="loading_text">
+ ローディング...
+ </floater.string>
+ <floater.string name="done_text">
+ 完了
+ </floater.string>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_sell_land.xml b/indra/newview/skins/default/xui/ja/floater_sell_land.xml
index 90c83c2103..951499d0e3 100644
--- a/indra/newview/skins/default/xui/ja/floater_sell_land.xml
+++ b/indra/newview/skins/default/xui/ja/floater_sell_land.xml
@@ -1,72 +1,65 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="sell land" title="土地を販売" height="496" min_height="496" >
- <text name="info_parcel_label">
- 区画:
- </text>
- <text name="info_parcel">
- 区画å
- </text>
- <text name="info_size_label">
- サイズ:
- </text>
- <text name="info_size">
- [AREA]平方メートル
- </text>
- <text name="info_action" bottom_delta="-57">
- ã“ã®åŒºç”»ã‚’販売ã™
-ã‚‹ã«ã¯:
- </text>
- <icon bottom_delta="-86" name="step_price" />
- <text name="price_label">
- 価格を設定:
- </text>
- <text name="price_text">
- ã“ã®åœŸåœ°ã«å¯¾ã™ã‚‹é©åˆ‡ãªä¾¡æ ¼ã‚’é¸æŠžã—ã¦ãã ã•ã„
- </text>
- <text name="price_ld">
- L$
- </text>
- <text name="price_per_m" width="230" left_delta="106">
- (1平方メートル当ãŸã‚ŠL$ [PER_METER])
- </text>
- <text name="sell_to_label">
- 土地ã®è²©å£²å…ˆï¼š
- </text>
- <text name="sell_to_text" right="-6">
- 誰ã«ã§ã‚‚販売ã™ã‚‹ã‹ã€ç‰¹å®šã®äººã«ã®ã¿è²©å£²ã™ã‚‹ã‹ã‚’é¸æŠžã—ã¦ãã ã•ã„
- </text>
- <combo_box name="sell_to">
- <combo_item name="--selectone--">
- ï¼ï¼1ã¤é¸æŠžï¼ï¼
- </combo_item>
- <combo_item name="Anyone">
- 誰ã§ã‚‚
- </combo_item>
- <combo_item name="Specificuser:">
- 特定ユーザー:
- </combo_item>
- </combo_box>
- <button label="é¸æŠž..." name="sell_to_select_agent" />
- <text name="sell_objects_label">
- 土地ã¨å…±ã«ã‚ªãƒ–ジェクトを販売ã—ã¾ã™ã‹ï¼Ÿ
- </text>
- <text name="sell_objects_text">
- 区画上ã«ã‚る譲渡å¯èƒ½ãªã‚ªãƒ–ジェクトã¯æ‰€æœ‰æ¨©ãŒå¤‰æ›´ã•ã‚Œã¾ã™
- </text>
- <radio_group name="sell_objects" height="72" bottom_delta="-76">
- <radio_item name="no">
- ã„ã„ãˆã€ã‚ªãƒ–ジェクト所有権
-ã‚’ä¿æŒã—ã¾ã™
- </radio_item>
- <radio_item name="yes" bottom="-56">
- ã¯ã„ã€åœŸåœ°ã¨ä¸€ç·’ã«ã‚ªãƒ–ジェ
-クトを売りã¾ã™
- </radio_item>
- </radio_group>
- <button label="オブジェクトを表示" name="show_objects" width="138"/>
- <text name="nag_message_label">
- 注æ„:返å“や交æ›ã¯ã§ãã¾ã›ã‚“
- </text>
- <button label="販売を決定" name="sell_btn" bottom="-489"/>
- <button label="å–り消ã—" name="cancel_btn" />
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater height="496" min_height="496" name="sell land" title="土地ã®è²©å£²">
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <text name="info_parcel_label">
+ 区画:
+ </text>
+ <text name="info_parcel">
+ PARCEL NAME
+ </text>
+ <text name="info_size_label">
+ サイズ:
+ </text>
+ <text name="info_size">
+ [AREA] 平方メートル
+ </text>
+ <text bottom_delta="-57" name="info_action">
+ ã“ã®åŒºç”»ã‚’販売:
+ </text>
+ <text name="price_label">
+ 1. 価格ã®è¨­å®šï¼š
+ </text>
+ <text name="price_text">
+ é©æ­£ä¾¡æ ¼ã‚’設定ã—ã¦ãã ã•ã„。
+ </text>
+ <text name="price_ld">
+ L$
+ </text>
+ <line_editor name="price">
+ 0
+ </line_editor>
+ <text left_delta="106" name="price_per_m" width="230">
+ (1平方メートルã‚ãŸã‚Š L$[PER_METER])
+ </text>
+ <text name="sell_to_label">
+ 2. 特定ã®äººã«è²©å£²ï¼š
+ </text>
+ <text name="sell_to_text" right="-6">
+ 販売先ã®æŒ‡å®šãªã—ã‹ã€ç‰¹å®šã®äººã«è²©å£²ã™ã‚‹ã‹é¸æŠžã—ã¦ãã ã•ã„。
+ </text>
+ <combo_box name="sell_to">
+ <combo_box.item label="-- 1ã¤é¸æŠž --" name="--selectone--"/>
+ <combo_box.item label="指定ãªã—・誰ã«ã§ã‚‚販売" name="Anyone"/>
+ <combo_box.item label="特定ã®äººï¼š" name="Specificuser:"/>
+ </combo_box>
+ <button label="é¸æŠž" name="sell_to_select_agent"/>
+ <text name="sell_objects_label">
+ 3. オブジェクトも土地ã¨ä¸€ç·’ã«è²©å£²ã—ã¾ã™ã‹ï¼Ÿ
+ </text>
+ <text name="sell_objects_text">
+ 区画上ã«ã‚ã‚‹ã€åœŸåœ°æ‰€æœ‰è€…ã®è­²æ¸¡å¯èƒ½ãªã‚ªãƒ–ジェクトã¯ã€æ‰€æœ‰æ¨©ãŒå¤‰æ›´ã•ã‚Œã¾ã™ã€‚
+ </text>
+ <radio_group bottom_delta="-76" height="72" name="sell_objects">
+ <radio_item label="ã„ã„ãˆã€ã‚ªãƒ–ジェクトã®æ‰€æœ‰æ¨©ã‚’ä¿æŒã—ã¾ã™" name="no"/>
+ <radio_item bottom="-56" label="ã¯ã„ã€ã‚ªãƒ–ジェクトã¨åœŸåœ°ã‚’一緒ã«è²©å£²ã—ã¾ã™" name="yes"/>
+ </radio_group>
+ <button label="オブジェクトを表示" name="show_objects" width="138"/>
+ <text name="nag_message_label">
+ 注æ„: è¿”å“・交æ›ã¯ã§ãã¾ã›ã‚“。
+ </text>
+ <button bottom="-489" label="土地を販売" name="sell_btn"/>
+ <button label="キャンセル" name="cancel_btn"/>
+ </panel>
+ </scroll_container>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_settings_debug.xml b/indra/newview/skins/default/xui/ja/floater_settings_debug.xml
index 1de3763f79..cb7950bf53 100644
--- a/indra/newview/skins/default/xui/ja/floater_settings_debug.xml
+++ b/indra/newview/skins/default/xui/ja/floater_settings_debug.xml
@@ -1,17 +1,13 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="settings_debug" title="デãƒãƒƒã‚°è¨­å®š">
<combo_box name="boolean_combo">
- <combo_item name="TRUE">
- æ­£
- </combo_item>
- <combo_item name="FALSE">
- 誤
- </combo_item>
+ <combo_box.item label="TRUE" name="TRUE"/>
+ <combo_box.item label="FALSE" name="FALSE"/>
</combo_box>
- <color_swatch label="色" name="color_swatch" />
- <spinner label="x" name="val_spinner_1" />
- <spinner label="x" name="val_spinner_2" />
- <spinner label="x" name="val_spinner_3" />
- <spinner label="x" name="val_spinner_4" />
- <button label="デフォルトã«ãƒªã‚»ãƒƒãƒˆ" name="default_btn" />
+ <color_swatch label="色" name="val_color_swatch"/>
+ <spinner label="x" name="val_spinner_1"/>
+ <spinner label="x" name="val_spinner_2"/>
+ <spinner label="x" name="val_spinner_3"/>
+ <spinner label="x" name="val_spinner_4"/>
+ <button label="デフォルトã«ãƒªã‚»ãƒƒãƒˆ" name="default_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_snapshot.xml b/indra/newview/skins/default/xui/ja/floater_snapshot.xml
index 7937de117c..22f21b0b16 100644
--- a/indra/newview/skins/default/xui/ja/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/ja/floater_snapshot.xml
@@ -1,18 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Snapshot" title="プレビュー">
+<floater name="Snapshot" title="スナップショットã®ãƒ—レビュー">
<text name="type_label">
スナップショットã®é€ã‚Šå…ˆ
</text>
<radio_group label="スナップショット・タイプ" name="snapshot_type_radio">
- <radio_item name="postcard">
- Eメールã§é€ä¿¡
- </radio_item>
- <radio_item name="texture">
- æŒã¡ç‰©ã«ä¿å­˜ï¼ˆL$[AMOUNT])
- </radio_item>
- <radio_item name="local">
- ãƒãƒ¼ãƒ‰ãƒ‡ã‚£ã‚¹ã‚¯ã«ä¿å­˜
- </radio_item>
+ <radio_item label="Eメールã§é€ä¿¡" name="postcard"/>
+ <radio_item label="æŒã¡ç‰©ã«ä¿å­˜ï¼ˆL$[AMOUNT])" name="texture"/>
+ <radio_item label="ãƒãƒ¼ãƒ‰ãƒ‡ã‚£ã‚¹ã‚¯ã«ä¿å­˜" name="local"/>
</radio_group>
<text name="file_size_label">
ファイル・サイズ: [SIZE] KB
@@ -21,16 +15,12 @@
<button label="é€ä¿¡" name="send_btn"/>
<button label="ä¿å­˜ï¼ˆL$[AMOUNT])" name="upload_btn"/>
<flyout_button label="ä¿å­˜" name="save_btn" tool_tip="ç”»åƒã‚’ファイルã«ä¿å­˜">
- <flyout_button_item name="save_item">
- ä¿å­˜
- </flyout_button_item>
- <flyout_button_item name="saveas_item">
- åå‰ã‚’付ã‘ã¦ä¿å­˜
- </flyout_button_item>
+ <flyout_button.item label="ä¿å­˜" name="save_item"/>
+ <flyout_button.item label="åå‰ã‚’付ã‘ã¦ä¿å­˜" name="saveas_item"/>
</flyout_button>
<button label="キャンセル" name="discard_btn"/>
- <button label="全表示 &gt;&gt;" name="more_btn" tool_tip="高度ãªã‚ªãƒ—ション"/>
- <button label="&lt;&lt; 簡易" name="less_btn" tool_tip="高度ãªã‚ªãƒ—ション"/>
+ <button label="全表示 &gt;&gt;" name="more_btn" tool_tip="詳ã—ã„設定"/>
+ <button label="&lt;&lt; 簡易" name="less_btn" tool_tip="詳ã—ã„設定"/>
<text name="type_label2">
サイズ
</text>
@@ -38,93 +28,45 @@
å½¢å¼
</text>
<combo_box label="解åƒåº¦" name="postcard_size_combo">
- <combo_item name="CurrentWindow">
- ç¾åœ¨ã®ï½³ï½¨ï¾ï¾„゙ウ
- </combo_item>
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
- <combo_item name="Custom">
- カスタム
- </combo_item>
+ <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="カスタム" name="Custom"/>
</combo_box>
<combo_box label="解åƒåº¦" name="texture_size_combo">
- <combo_item name="CurrentWindow">
- ç¾åœ¨ã®ï½³ï½¨ï¾ï¾„゙ウ
- </combo_item>
- <combo_item name="Small(128x128)">
- å°ï¼ˆ128x128)
- </combo_item>
- <combo_item name="Medium(256x256)">
- 中(256x256)
- </combo_item>
- <combo_item name="Large(512x512)">
- 大(512x512)
- </combo_item>
- <combo_item name="Custom">
- カスタム
- </combo_item>
+ <combo_box.item label="ç¾åœ¨ã®ï½³ï½¨ï¾ï¾„゙ウ" name="CurrentWindow"/>
+ <combo_box.item label="å°ï¼ˆ128x128)" name="Small(128x128)"/>
+ <combo_box.item label="中(256x256)" name="Medium(256x256)"/>
+ <combo_box.item label="大(512x512)" name="Large(512x512)"/>
+ <combo_box.item label="カスタム" name="Custom"/>
</combo_box>
<combo_box label="解åƒåº¦" name="local_size_combo">
- <combo_item name="CurrentWindow">
- ç¾åœ¨ã®ï½³ï½¨ï¾ï¾„゙ウ
- </combo_item>
- <combo_item name="320x240">
- 320x240
- </combo_item>
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
- <combo_item name="1280x1024">
- 1280x1024
- </combo_item>
- <combo_item name="1600x1200">
- 1600x1200
- </combo_item>
- <combo_item name="Custom">
- カスタム
- </combo_item>
+ <combo_box.item label="ç¾åœ¨ã®ï½³ï½¨ï¾ï¾„゙ウ" name="CurrentWindow"/>
+ <combo_box.item label="320x240" name="320x240"/>
+ <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="1280x1024" name="1280x1024"/>
+ <combo_box.item label="1600x1200" name="1600x1200"/>
+ <combo_box.item label="カスタム" name="Custom"/>
</combo_box>
<combo_box label="å½¢å¼" name="local_format_combo">
- <combo_item name="PNG">
- PNG
- </combo_item>
- <combo_item name="JPEG">
- JPEG
- </combo_item>
- <combo_item name="BMP">
- BMP
- </combo_item>
+ <combo_box.item label="PNG" name="PNG"/>
+ <combo_box.item label="JPEG" name="JPEG"/>
+ <combo_box.item label="BMP" name="BMP"/>
</combo_box>
- <spinner label="å¹…" name="snapshot_width" label_width="25" width="90"/>
- <spinner label="高ã•" name="snapshot_height" label_width="30" left="115" width="90"/>
+ <spinner label="å¹…" label_width="25" name="snapshot_width" width="90"/>
+ <spinner label="高ã•" label_width="30" left="115" name="snapshot_height" width="90"/>
<check_box label="縦横比ã®å›ºå®š" name="keep_aspect_check"/>
<slider label="画質" name="image_quality_slider"/>
<text name="layer_type_label">
キャプï¾ï½¬ï¼š
</text>
<combo_box label="ç”»åƒãƒ¬ã‚¤ãƒ¤ãƒ¼" name="layer_types">
- <combo_item name="Colors">
- 色
- </combo_item>
- <combo_item name="Depth">
- æ·±ã•
- </combo_item>
- <combo_item name="ObjectMattes">
- オグジェクトã®ã¤ã‚„消ã—
- </combo_item>
+ <combo_box.item label="色" name="Colors"/>
+ <combo_box.item label="æ·±ã•" name="Depth"/>
+ <combo_box.item label="オグジェクトã®ã¤ã‚„消ã—" name="ObjectMattes"/>
</combo_box>
<check_box label="インタフェースを表示" name="ui_check"/>
<check_box label="HUD オブジェクトを表示" name="hud_check"/>
diff --git a/indra/newview/skins/default/xui/ja/floater_sound_preview.xml b/indra/newview/skins/default/xui/ja/floater_sound_preview.xml
index 6bc259536f..a24ba6e075 100644
--- a/indra/newview/skins/default/xui/ja/floater_sound_preview.xml
+++ b/indra/newview/skins/default/xui/ja/floater_sound_preview.xml
@@ -1,28 +1,20 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Sound Preview" title="sound.wav">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Sound Preview" title="SOUND.WAV">
<text name="name_label">
åå‰ï¼š
</text>
<text name="description_label">
説明:
</text>
- <button label="å–り消ã—" label_selected="å–り消ã—" name="cancel_btn" />
+ <button label="å–り消ã—" label_selected="å–り消ã—" name="cancel_btn"/>
<button label="アップロード (L$[AMOUNT])" label_selected="アップロード (L$[AMOUNT])" name="ok_btn"/>
<text name="text">
ビットレート(kbps):
</text>
<radio_group name="bitrate">
- <radio_item name="32">
- 32
- </radio_item>
- <radio_item name="64">
- 64
- </radio_item>
- <radio_item name="96">
- 96
- </radio_item>
- <radio_item name="128">
- 128
- </radio_item>
+ <radio_item label="32" name="32"/>
+ <radio_item label="64" name="64"/>
+ <radio_item label="96" name="96"/>
+ <radio_item label="128" name="128"/>
</radio_group>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_stats.xml b/indra/newview/skins/default/xui/ja/floater_stats.xml
new file mode 100644
index 0000000000..97927776c7
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_stats.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Statistics" title="統計">
+ <scroll_container name="statistics_scroll">
+ <container_view name="statistics_view">
+ <stat_view label="ベーシック" name="basic">
+ <stat_bar label="FPS" name="fps"/>
+ <stat_bar label="帯域幅" name="bandwidth"/>
+ <stat_bar label="パケットロス" name="packet_loss"/>
+ <stat_bar label="Pingシム" name="ping"/>
+ </stat_view>
+ <stat_view label="アドãƒãƒ³ã‚¹" name="advanced">
+ <stat_view label="æç”»" name="render">
+ <stat_bar label="KTris æç”»" name="ktrisframe"/>
+ <stat_bar label="KTris æç”»" name="ktrissec"/>
+ <stat_bar label="オブジェクトåˆè¨ˆ" name="objs"/>
+ <stat_bar label="æ–°è¦ã‚ªãƒ–ジェクト" name="newobjs"/>
+ </stat_view>
+ <stat_view label="テクスãƒãƒ£" name="texture">
+ <stat_bar label="カウント" name="numimagesstat"/>
+ <stat_bar label="Raw カウント" name="numrawimagesstat"/>
+ <stat_bar label="GL メモリ" name="gltexmemstat"/>
+ <stat_bar label="フォーマット済メモリ" name="formattedmemstat"/>
+ <stat_bar label="Raw メモリ" name="rawmemstat"/>
+ <stat_bar label="çµ±åˆãƒ¡ãƒ¢ãƒª" name="glboundmemstat"/>
+ </stat_view>
+ <stat_view label="ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯" name="network">
+ <stat_bar label="パケットイン" name="packetsinstat"/>
+ <stat_bar label="パケットアウト" name="packetsoutstat"/>
+ <stat_bar label="オブジェクト" name="objectkbitstat"/>
+ <stat_bar label="テクスãƒãƒ£" name="texturekbitstat"/>
+ <stat_bar label="アセット" name="assetkbitstat"/>
+ <stat_bar label="レイヤー" name="layerskbitstat"/>
+ <stat_bar label="実際ã®å—ä¿¡" name="actualinkbitstat"/>
+ <stat_bar label="実際ã®é€ä¿¡" name="actualoutkbitstat"/>
+ <stat_bar label="VFS ä¿ç•™ä¸­ã®æ“作" name="vfspendingoperations"/>
+ </stat_view>
+ </stat_view>
+ <stat_view label="シミュレーター" name="sim">
+ <stat_bar label="時間ã®é…ã‚Œ" name="simtimedilation"/>
+ <stat_bar label="シム FPS" name="simfps"/>
+ <stat_bar label="物ç†ä½œç”¨ FPS" name="simphysicsfps"/>
+ <stat_view label="物ç†ä½œç”¨ã®è©³ç´°" name="physicsdetail">
+ <stat_bar label="ピン留ã‚オブジェクト" name="physicspinnedtasks"/>
+ <stat_bar label="低 LOD オブジェクト" name="physicslodtasks"/>
+ <stat_bar label="メモリé…分" name="physicsmemoryallocated"/>
+ </stat_view>
+ <stat_bar label="エージェントã®æ›´æ–°/秒" name="simagentups"/>
+ <stat_bar label="メインエージェント" name="simmainagents"/>
+ <stat_bar label="ãƒãƒ£ã‚¤ãƒ«ãƒ‰ã‚¨ãƒ¼ã‚¸ã‚§ãƒ³ãƒˆ" name="simchildagents"/>
+ <stat_bar label="オブジェクト" name="simobjects"/>
+ <stat_bar label="アクティブãªã‚ªãƒ–ジェクト" name="simactiveobjects"/>
+ <stat_bar label="アクティブãªã‚¹ã‚¯ãƒªãƒ—ト" name="simactivescripts"/>
+ <stat_bar label="スクリプトイベント" name="simscripteps"/>
+ <stat_bar label="パケットイン" name="siminpps"/>
+ <stat_bar label="パケットアウト" name="simoutpps"/>
+ <stat_bar label="ä¿ç•™ä¸­ã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰" name="simpendingdownloads"/>
+ <stat_bar label="ä¿ç•™ä¸­ã®ã‚¢ãƒƒãƒ—ロード" name="simpendinguploads"/>
+ <stat_bar label="未é€ä¿¡ãƒã‚¤ãƒˆåˆè¨ˆ" name="simtotalunackedbytes"/>
+ <stat_view label="時間(ms)" name="simperf">
+ <stat_bar label="フレーム時間åˆè¨ˆ" name="simframemsec"/>
+ <stat_bar label="ç·æ™‚é–“æ•°" name="simnetmsec"/>
+ <stat_bar label="物ç†çš„作用時間" name="simsimphysicsmsec"/>
+ <stat_bar label="シミュレーション時間" name="simsimothermsec"/>
+ <stat_bar label="エージェント時間" name="simagentmsec"/>
+ <stat_bar label="イメージ時間" name="simimagesmsec"/>
+ <stat_bar label="スクリプト時間" name="simscriptmsec"/>
+ </stat_view>
+ </stat_view>
+ </container_view>
+ </scroll_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_sys_well.xml b/indra/newview/skins/default/xui/ja/floater_sys_well.xml
new file mode 100644
index 0000000000..91e29fd595
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_sys_well.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="notification_chiclet" title="通知"/>
diff --git a/indra/newview/skins/default/xui/ja/floater_telehub.xml b/indra/newview/skins/default/xui/ja/floater_telehub.xml
index cd590abe3c..fea497b622 100644
--- a/indra/newview/skins/default/xui/ja/floater_telehub.xml
+++ b/indra/newview/skins/default/xui/ja/floater_telehub.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="telehub" title="テレãƒãƒ–">
<text name="status_text_connected">
物体[OBJECT]ã«æŽ¥ç¶šã•ã‚ŒãŸãƒ†ãƒ¬ãƒãƒ–
@@ -12,13 +12,13 @@
<text name="help_text_not_connected">
物体をé¸æŠžã—「テレãƒãƒ–ã®æŽ¥ç¶šã€ã‚’クリックã™ã‚‹
</text>
- <button label="テレãƒãƒ–ã®æŽ¥ç¶š" name="connect_btn" />
- <button label="切断" name="disconnect_btn" />
+ <button label="テレãƒãƒ–ã®æŽ¥ç¶š" name="connect_btn"/>
+ <button label="切断" name="disconnect_btn"/>
<text name="spawn_points_text">
出ç¾åœ°ç‚¹ï¼ˆç‰©ä½“ã§ã¯ãªãä½ç½®ï¼‰
</text>
- <button label="出ç¾ä½ç½®ã‚’追加" name="add_spawn_point_btn" />
- <button label="出ç¾åœ°ç‚¹ã‚’削除" name="remove_spawn_point_btn" />
+ <button label="出ç¾ä½ç½®ã‚’追加" name="add_spawn_point_btn"/>
+ <button label="出ç¾åœ°ç‚¹ã‚’削除" name="remove_spawn_point_btn"/>
<text name="spawn_point_help">
物体をé¸æŠžã—「追加ã€ã‚’クリックã—ä½ç½®ã‚’指定。
物体を移動ã¾ãŸã¯å‰Šé™¤ã§ãる。
diff --git a/indra/newview/skins/default/xui/ja/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/ja/floater_texture_ctrl.xml
index 79af253bdc..c93f315628 100644
--- a/indra/newview/skins/default/xui/ja/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/ja/floater_texture_ctrl.xml
@@ -1,23 +1,23 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="texture picker" title="é¸æŠžï¼šãƒ†ã‚¯ã‚¹ãƒãƒ£ãƒ¼">
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="texture picker" title="é¸æŠžï¼š テクスãƒãƒ£">
<string name="choose_picture">
クリックã—ã¦å†™çœŸã‚’é¸æŠž
</string>
- <text type="string" length="1" name="Multiple">
- 複数
+ <text name="Multiple">
+ 複数ã®ãƒ†ã‚¯ã‚¹ãƒãƒ£
</text>
- <text type="string" length="1" name="unknown">
- 寸法: [DIMENSIONS]
+ <text name="unknown">
+ サイズ: [DIMENSIONS]
</text>
- <button label="デフォルト" label_selected="デフォルト" name="Default" />
- <button label="ãªã—" label_selected="ãªã—" name="None" />
- <button label="ブランク" label_selected="ブランク" name="Blank" />
- <check_box label="フォルダを表示" name="show_folders_check" />
- <search_editor label="ã“ã“ã«ã‚¿ã‚¤ãƒ—ã—ã¦æ¤œç´¢" name="inventory search editor" />
- <check_box label="ãŸã ã¡ã«é©ç”¨" name="apply_immediate_check" />
- <button label="" label_selected="" name="Pipette" />
- <button label="å–り消ã—" label_selected="å–り消ã—" name="Cancel" />
- <button label="é¸æŠž" label_selected="é¸æŠž" name="Select" />
+ <button label="デフォルト" label_selected="デフォルト" name="Default"/>
+ <button label="ãªã—" label_selected="ãªã—" name="None"/>
+ <button label="ブランク" label_selected="ブランク" name="Blank"/>
+ <check_box label="フォルダを表示" name="show_folders_check"/>
+ <search_editor label="テクスãƒãƒ£ã‚’フィルター" name="inventory search editor"/>
+ <check_box label="今ã™ãé©ç”¨" name="apply_immediate_check"/>
+ <button label="" label_selected="" name="Pipette"/>
+ <button label="å–り消ã—" label_selected="å–り消ã—" name="Cancel"/>
+ <button label="Ok" label_selected="Ok" name="Select"/>
<text name="pick title">
ピック:
</text>
diff --git a/indra/newview/skins/default/xui/ja/floater_tools.xml b/indra/newview/skins/default/xui/ja/floater_tools.xml
index 0b03a04f3e..cbb062dea3 100644
--- a/indra/newview/skins/default/xui/ja/floater_tools.xml
+++ b/indra/newview/skins/default/xui/ja/floater_tools.xml
@@ -1,42 +1,81 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="toolbox floater" title="">
+<floater name="toolbox floater" short_title="制作ツール" title="">
+ <floater.string name="status_rotate">
+ 色ã®ä»˜ã„ãŸãƒãƒ³ãƒ‰ã‚’ドラッグã—ã¦ã‚ªãƒ–ジェクトを回転
+ </floater.string>
+ <floater.string name="status_scale">
+ é¸æŠžã—ãŸå´ã‚’クリックã—ã€ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦å¼•ã伸ã°ã™
+ </floater.string>
+ <floater.string name="status_move">
+ 移動:ドラッグã€ã‚³ãƒ”ー:Shiftを押ã—ãªãŒã‚‰ï¾„゙ラッグ
+ </floater.string>
+ <floater.string name="status_modifyland">
+ 土地をクリックã—ã€ãƒœã‚¿ãƒ³ã‚’押ã—ãŸã¾ã¾å…¥åŠ›ã—ã¦ä¿®æ­£å¤‰æ›´
+ </floater.string>
+ <floater.string name="status_camera">
+ クリック・ドラッグã§è¦–界移動
+ </floater.string>
+ <floater.string name="status_grab">
+ ドラッグã§ç§»å‹•ã€Ctrlã§æŒã¡ä¸Šã’ã€Ctrl+Shiftã§å›žè»¢
+ </floater.string>
+ <floater.string name="status_place">
+ インワールドã§ã‚¯ãƒªãƒƒã‚¯ã—ã¦ä½œæˆ
+ </floater.string>
+ <floater.string name="status_selectland">
+ 土地をクリックã—ã€ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦é¸æŠž
+ </floater.string>
+ <floater.string name="grid_screen_text">
+ ç”»é¢
+ </floater.string>
+ <floater.string name="grid_local_text">
+ ローカル
+ </floater.string>
+ <floater.string name="grid_world_text">
+ 世界
+ </floater.string>
+ <floater.string name="grid_reference_text">
+ å‚ç…§
+ </floater.string>
+ <floater.string name="grid_attachment_text">
+ アタッãƒãƒ¡ãƒ³ãƒˆ
+ </floater.string>
<button label="" label_selected="" name="button focus" tool_tip="フォーカス"/>
<button label="" label_selected="" name="button move" tool_tip="å‹•ã‹ã™"/>
<button label="" label_selected="" name="button edit" tool_tip="編集"/>
<button label="" label_selected="" name="button create" tool_tip="作æˆ"/>
<button label="" label_selected="" name="button land" tool_tip="土地"/>
- <check_box label="ズーム" name="radio zoom"/>
- <check_box label="軌跡(Ctrl)" name="radio orbit"/>
- <check_box label="パン(Ctrl+Shift)" name="radio pan"/>
- <check_box label="移動" name="radio move"/>
- <check_box label="æŒã¡ä¸Šã’る(Ctrl)" name="radio lift"/>
- <check_box label="スピン(Ctrl+Shift)" name="radio spin"/>
- <check_box label="ä½ç½®" name="radio position"/>
- <check_box label="回転(Ctrl)" name="radio rotate"/>
- <check_box label="引伸ã°ã™ï¼ˆCtrl+Shift)" name="radio stretch"/>
- <check_box label="テクスãƒãƒ£ãƒ¼ã‚’é¸æŠž" name="radio select face"/>
- <check_box label="リンク部ä½ã‚’編集" name="checkbox edit linked parts"/>
- <text name="text ruler mode" width="88">
- ルーラー:
- </text>
- <combo_box left_delta="60" name="combobox grid mode" width="76">
- <combo_item name="World">
- 世界
- </combo_item>
- <combo_item name="Local">
- ローカル
- </combo_item>
- <combo_item name="Reference">
- リファレンス
- </combo_item>
- </combo_box>
- <check_box label="両å´ã‚’引伸ã°ã™" left="116" name="checkbox uniform"/>
- <check_box label="テクスãƒãƒ£ãƒ¼ã‚’引伸ã°ã™" name="checkbox stretch textures"/>
- <check_box label="グリッド使用" left_delta="27" name="checkbox snap to grid"/>
- <button label="オプション" label_selected="オプション" name="Options..."/>
<text name="text status">
移動ã™ã‚‹ã«ã¯ãƒ‰ãƒ©ãƒƒã‚°ã€ã‚³ãƒ”ーã™ã‚‹ã«ã¯Shiftキーを押ã—ãªãŒã‚‰ãƒ‰ãƒ©ãƒƒã‚°
</text>
+ <radio_group name="focus_radio_group">
+ <radio_item label="ズーム" name="radio zoom"/>
+ <radio_item label="軌跡(Ctrl)" name="radio orbit"/>
+ <radio_item label="水平・垂直移動 (Ctrl+Shift)" name="radio pan"/>
+ </radio_group>
+ <radio_group name="move_radio_group">
+ <radio_item label="移動" name="radio move"/>
+ <radio_item label="æŒã¡ä¸Šã’る(Ctrl)" name="radio lift"/>
+ <radio_item label="回転 (Ctrl+Shift)" name="radio spin"/>
+ </radio_group>
+ <radio_group name="edit_radio_group">
+ <radio_item label="移動" name="radio position"/>
+ <radio_item label="回転(Ctrl)" name="radio rotate"/>
+ <radio_item label="引ã延ã°ã™ (Ctrl+Shift)" name="radio stretch"/>
+ <radio_item label="é¢ã‚’é¸æŠž" name="radio select face"/>
+ </radio_group>
+ <check_box label="リンク部分を編集" name="checkbox edit linked parts"/>
+ <text name="RenderingCost" tool_tip="ã“ã®ã‚ªãƒ–ジェクトã«ã‹ã‹ã‚‹ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ã‚³ã‚¹ãƒˆã‚’表示">
+ þ: [COUNT]
+ </text>
+ <check_box label="両å´ã‚’引伸ã°ã™" left="116" name="checkbox uniform"/>
+ <check_box initial_value="true" label="テクスãƒãƒ£ãƒ¼ã‚’引伸ã°ã™" name="checkbox stretch textures"/>
+ <check_box initial_value="true" label="グリッドãƒã‚¤ãƒ³ãƒˆã«ã‚¹ãƒŠãƒƒãƒ—" left_delta="27" name="checkbox snap to grid"/>
+ <combo_box left_delta="60" name="combobox grid mode" tool_tip="オブジェクトã®é…ç½®ã«ä½¿ã†ã‚°ãƒªãƒƒãƒ‰ãƒ«ãƒ¼ãƒ©ã‚’é¸æŠž" width="76">
+ <combo_box.item label="ワールドグリッド" name="World"/>
+ <combo_box.item label="ローカルグリッド" name="Local"/>
+ <combo_box.item label="リファレンスグリッド" name="Reference"/>
+ </combo_box>
+ <button label="オプション" label_selected="オプション" name="Options..." tool_tip="グリッドオプションをもã£ã¨è¦‹ã‚‹"/>
<button label="" label_selected="" name="ToolCube" tool_tip="キューブ"/>
<button label="" label_selected="" name="ToolPrism" tool_tip="プリズム"/>
<button label="" label_selected="" name="ToolPyramid" tool_tip="ピラミッド"/>
@@ -52,18 +91,19 @@
<button label="" label_selected="" name="ToolRing" tool_tip="リング"/>
<button label="" label_selected="" name="ToolTree" tool_tip="樹木"/>
<button label="" label_selected="" name="ToolGrass" tool_tip="è‰åœ°"/>
- <check_box label="é¸æŠžã—ãŸã‚‚ã®ã‚’ä¿æŒ" name="checkbox sticky"/>
+ <check_box label="é¸æŠžã—ãŸãƒ„ールを維æŒ" name="checkbox sticky"/>
<check_box label="é¸æŠžã—ãŸã‚‚ã®ã‚’コピー" name="checkbox copy selection"/>
- <check_box label="中央ã«ä½ç½®" name="checkbox copy centers"/>
+ <check_box initial_value="true" label="中央ã«ä½ç½®" name="checkbox copy centers"/>
<check_box label="回転" name="checkbox copy rotates"/>
- <check_box label="土地をé¸æŠž" name="radio select land"/>
- <check_box label="ãªã‚‰ã™" name="radio flatten"/>
- <check_box label="隆起" name="radio raise"/>
- <check_box label="低ãã™ã‚‹" name="radio lower"/>
- <check_box label="滑らã‹ã«ã™ã‚‹" name="radio smooth"/>
- <check_box label="凸凹ã«ã™ã‚‹" name="radio noise"/>
- <check_box label="å…ƒã«æˆ»ã™" name="radio revert"/>
- <button label="é©ç”¨" label_selected="é©ç”¨" name="button apply to selection" tool_tip="é¸æŠžã—ãŸåœŸåœ°ã‚’修正"/>
+ <radio_group name="land_radio_group">
+ <radio_item label="土地をé¸æŠž" name="radio select land"/>
+ <radio_item label="ãªã‚‰ã™" name="radio flatten"/>
+ <radio_item label="隆起" name="radio raise"/>
+ <radio_item label="低ãã™ã‚‹" name="radio lower"/>
+ <radio_item label="滑らã‹ã«ã™ã‚‹" name="radio smooth"/>
+ <radio_item label="凸凹ã«ã™ã‚‹" name="radio noise"/>
+ <radio_item label="å…ƒã«æˆ»ã™" name="radio revert"/>
+ </radio_group>
<text name="Bulldozer:">
ブルドーザー:
</text>
@@ -73,14 +113,51 @@
<text name="Strength:">
強度
</text>
+ <button label="é©ç”¨" label_selected="é©ç”¨" name="button apply to selection" tool_tip="é¸æŠžã—ãŸåœŸåœ°ã‚’修正"/>
<text name="obj_count">
- é¸æŠžã‚ªãƒ–ジェクト:[COUNT]
+ オブジェクト: [COUNT]
</text>
<text name="prim_count">
- プリム:[COUNT]
+ プリム: [COUNT]
</text>
<tab_container name="Object Info Tabs" tab_max_width="150" tab_min_width="30">
<panel label="一般" name="General">
+ <panel.string name="text deed continued">
+ 譲渡
+ </panel.string>
+ <panel.string name="text deed">
+ 譲渡
+ </panel.string>
+ <panel.string name="text modify info 1">
+ ã“ã®ã‚ªãƒ–ジェクトを修正ã§ãã¾ã™
+ </panel.string>
+ <panel.string name="text modify info 2">
+ ã“れらã®ã‚ªãƒ–ジェクトを修正ã§ãã¾ã™
+ </panel.string>
+ <panel.string name="text modify info 3">
+ ã“ã®ã‚ªãƒ–ジェクトを修正ã§ãã¾ã›ã‚“
+ </panel.string>
+ <panel.string name="text modify info 4">
+ ã“れらã®ã‚ªãƒ–ジェクトを修正ã§ãã¾ã›ã‚“
+ </panel.string>
+ <panel.string name="text modify warning">
+ オブジェクト全体をé¸æŠžã—ã¦æ¨©é™ã®è¨­å®šã‚’è¡Œã£ã¦ãã ã•ã„。
+ </panel.string>
+ <panel.string name="Cost Default">
+ 価格: L$
+ </panel.string>
+ <panel.string name="Cost Total">
+ åˆè¨ˆï¼š L$
+ </panel.string>
+ <panel.string name="Cost Per Unit">
+ Price Per: L$
+ </panel.string>
+ <panel.string name="Cost Mixed">
+ æ··åˆä¾¡æ ¼
+ </panel.string>
+ <panel.string name="Sale Mixed">
+ æ··åˆè²©å£²
+ </panel.string>
<text name="Name:">
åå‰ï¼š
</text>
@@ -91,146 +168,79 @@
クリエーター
</text>
<text name="Creator Name">
- Thrax Linden
+ Esbee Linden
</text>
- <button label="情報..." label_selected="情報..." name="button creator profile"/>
<text name="Owner:">
オーナー:
</text>
<text name="Owner Name">
- Thrax Linden
+ Erica Linden
</text>
- <button label="情報..." label_selected="情報..." name="button owner profile"/>
<text name="Group:">
グループ:
</text>
- <text name="Group Name Proxy">
- Linden家
- </text>
- <button label="設定..." label_selected="設定..." name="button set group"/>
- <text name="Permissions:">
- 権é™
- </text>
- <text name="perm_modify">
- ã“ã®ã‚ªãƒ–ジェクトã¯ä¿®æ­£ã§ãã¾ã™ã€‚
- </text>
- <check_box label="グループã§å…±åŒç®¡ç†" name="checkbox share with group" tool_tip="設定ã—ãŸã‚°ãƒ«ãƒ¼ãƒ—ã«å±žã™ã‚‹ã™ã¹ã¦ã®ãƒ¡ãƒ³ãƒãƒ¼ã¨ã“ã®ã‚ªãƒ–ジェクトã®æ¨©é™ã‚’共有ã—ã¾ã™ã€‚ 役割制é™ã‚’有効ã«ã™ã‚‹ã«ã¯ã€è­²æ¸¡ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"/>
- <string name="text deed continued">
- 譲渡...
- </string>
- <string name="text deed">
- 譲渡
- </string>
- <button label="譲渡..." label_selected="譲渡..." name="button deed" tool_tip="グループ共有ã®ã‚ªãƒ–ジェクトã¯ã€ã‚°ãƒ«ãƒ¼ãƒ—・オフィサーã«ã‚ˆã‚Šè­²æ¸¡å¯èƒ½ã§ã™ã€‚"/>
- <check_box label="誰ã«å¯¾ã—ã¦ã‚‚移動を許å¯" name="checkbox allow everyone move"/>
- <check_box label="誰ã«å¯¾ã—ã¦ã‚‚コピーを許å¯" name="checkbox allow everyone copy"/>
- <check_box label="検索ã«è¡¨ç¤º" name="search_check" tool_tip="検索çµæžœã§ã€ã“ã®ã‚ªãƒ–ジェクトを人ã«è¦‹ã›ã‚‹"/>
- <check_box label="売り出ã—中" name="checkbox for sale"/>
- <text name="Cost">
- 価格: L$
- </text>
- <radio_group left="30" name="sale type">
- <radio_item name="Original">
- オリジナル
- </radio_item>
- <radio_item left="82" name="Copy">
- コピー
- </radio_item>
- <radio_item left="148" name="Contents">
- コンテンツ
- </radio_item>
- </radio_group>
- <text name="Next owner can:">
- 次ã®ã‚ªãƒ¼ãƒŠãƒ¼ãŒå®Ÿè¡Œã§ãã‚‹æ“作:
- </text>
- <check_box label="修正" name="checkbox next owner can modify"/>
- <check_box label="コピー" name="checkbox next owner can copy"/>
- <check_box label="å†è²©ï¼ãƒ—レゼント" name="checkbox next owner can transfer"/>
+ <button label="設定..." label_selected="設定..." name="button set group" tool_tip="ã“ã®ã‚ªãƒ–ジェクト権é™ã‚’共有ã™ã‚‹ã‚°ãƒ«ãƒ¼ãƒ—ã‚’é¸æŠž"/>
+ <name_box initial_value="ローディング..." name="Group Name Proxy"/>
+ <button label="譲渡" label_selected="譲渡" name="button deed" tool_tip="ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’譲渡ã™ã‚‹ã¨ã€Œæ¬¡ã®æ‰€æœ‰è€…ã€ã®æ¨©é™ãŒé©ç”¨ã•ã‚Œã¾ã™ã€‚ グループ共有オブジェクトã¯ã€ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚ªãƒ•ã‚£ã‚µãƒ¼ãŒè­²æ¸¡ã§ãã¾ã™ã€‚"/>
+ <check_box label="共有" name="checkbox share with group" tool_tip="設定ã—ãŸã‚°ãƒ«ãƒ¼ãƒ—ã®ãƒ¡ãƒ³ãƒãƒ¼å…¨å“¡ã«ã“ã®ã‚ªãƒ–ジェクトã®ä¿®æ­£æ¨©é™ã‚’与ãˆã¾ã™ã€‚ 譲渡ã—ãªã„é™ã‚Šã€å½¹å‰²åˆ¶é™ã‚’有効ã«ã¯ã§ãã¾ã›ã‚“。"/>
<text name="label click action">
- 左クリックã™ã‚‹ã¨ï¼š
+ クリックã§ï¼š
</text>
<combo_box name="clickaction">
- <combo_item name="Touch/grab(default)">
- 触るï¼ã¤ã‹ã‚€ (デフォルト)
- </combo_item>
- <combo_item name="Sitonobject">
- オブジェクトã«åº§ã‚‹
- </combo_item>
- <combo_item name="Buyobject">
- オブジェクトを購入
- </combo_item>
- <combo_item name="Payobject">
- オブジェクトã¸ã®æ”¯æ‰•ã„
- </combo_item>
- <combo_item name="Open">
- é–‹ã
- </combo_item>
- <combo_item name="Play">
- 区画メディアをå†ç”Ÿ
- </combo_item>
- <combo_item name="Opemmedia">
- 区画メディアを開ã
- </combo_item>
+ <combo_box.item label="触る(デフォルト)" name="Touch/grab(default)"/>
+ <combo_box.item label="オブジェクトã«åº§ã‚‹" name="Sitonobject"/>
+ <combo_box.item label="オブジェクトを購入" name="Buyobject"/>
+ <combo_box.item label="オブジェクトã¸ã®æ”¯æ‰•ã„" name="Payobject"/>
+ <combo_box.item label="é–‹ã" name="Open"/>
+ <combo_box.item label="ズーム" name="Zoom"/>
</combo_box>
- <text name="B:">
- B:
- </text>
- <text name="O:">
- O;
- </text>
- <text name="G:">
- G:
- </text>
- <text name="E:">
- E:
- </text>
- <text name="N:">
- N:
- </text>
- <text name="F:">
- F:
- </text>
- <string name="text modify info 1">
- ã“ã®ã‚ªãƒ–ジェクトã¯ä¿®æ­£ã§ãã¾ã™ã€‚
- </string>
- <string name="text modify info 2">
- ã“れらã®ã‚ªãƒ–ジェクトã¯ä¿®æ­£ã§ãã¾ã™ã€‚
- </string>
- <string name="text modify info 3">
- ã“ã®ã‚ªãƒ–ジェクトã¯ä¿®æ­£ã§ãã¾ã›ã‚“。
- </string>
- <string name="text modify info 4">
- ã“れらã®ã‚ªãƒ–ジェクトã¯ä¿®æ­£ã§ãã¾ã›ã‚“。
- </string>
- <string name="text modify warning">
- 権é™ã‚’設定ã™ã‚‹ã«ã¯ã€ã‚ªãƒ–ジェクト全体をé¸æŠžã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
- </string>
- <string name="Cost Default">
- 価格: L$
- </string>
- <string name="Cost Total">
- åˆè¨ˆä¾¡æ ¼ï¼š L$
- </string>
- <string name="Cost Per Unit">
- å˜ä¾¡ï¼š L$
- </string>
- <string name="Cost Mixed">
- æ··åˆä¾¡æ ¼
- </string>
- <string name="Sale Mixed">
- æ··åˆè²©å£²
- </string>
+ <check_box label="販売対象:" name="checkbox for sale"/>
+ <combo_box name="sale type">
+ <combo_box.item label="コピー" name="Copy"/>
+ <combo_box.item label="コンテンツ" name="Contents"/>
+ <combo_box.item label="オリジナル" name="Original"/>
+ </combo_box>
+ <spinner label="価格: L$" name="Edit Cost"/>
+ <check_box label="検索ã«è¡¨ç¤º" name="search_check" tool_tip="検索çµæžœã§ã€ã“ã®ã‚ªãƒ–ジェクトを人ã«è¦‹ã›ã‚‹"/>
+ <panel name="perms_build">
+ <text name="perm_modify">
+ ã‚ãªãŸã¯ã“ã®ã‚ªãƒ–ジェクトを修正ã§ãã¾ã™
+ </text>
+ <text name="Anyone can:">
+ 全員:
+ </text>
+ <check_box label="移動" name="checkbox allow everyone move"/>
+ <check_box label="コピー" name="checkbox allow everyone copy"/>
+ <text name="Next owner can:">
+ 次ã®æ‰€æœ‰è€…:
+ </text>
+ <check_box label="修正" name="checkbox next owner can modify"/>
+ <check_box label="コピー" name="checkbox next owner can copy"/>
+ <check_box label="å†è²©ãƒ»ãƒ—レゼント" name="checkbox next owner can transfer" tool_tip="次ã®æ‰€æœ‰è€…ã¯ã“ã®ã‚ªãƒ–ジェクトを他人ã«ã‚ã’ãŸã‚Šå†è²©ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™"/>
+ <text name="B:">
+ B:
+ </text>
+ <text name="O:">
+ O:
+ </text>
+ <text name="G:">
+ G:
+ </text>
+ <text name="E:">
+ E:
+ </text>
+ <text name="N:">
+ N:
+ </text>
+ <text name="F:">
+ F:
+ </text>
+ </panel>
</panel>
<panel label="形状" name="Object">
- <text name="select_single">
- プリムを1ã¤ã ã‘é¸æŠžã—ã¦ç·¨é›†ã—ã¦ãã ã•ã„
- </text>
- <text name="edit_object">
- オブジェクトã®ãƒ‘ラメーターを編集:
- </text>
<check_box label="ロック済ã¿" name="checkbox locked" tool_tip="オブジェクトã®ç§»å‹•ã¨å‰Šé™¤ã‚’ç¦æ­¢ã—ã¾ã™ã€‚ ã“ã®æ©Ÿèƒ½ã‚’使ã†ã¨ã€æ§‹ç¯‰ä¸­ã«æ„図ã—ãªã„編集を防ãã“ã¨ãŒã§ãã¾ã™ã€‚"/>
<check_box label="物ç†" name="Physical Checkbox Ctrl" tool_tip="オブジェクトã«å¯¾ã™ã‚‹é‡åŠ›ã®ä½œç”¨ã¨å½±éŸ¿ã‚’有効ã«ã™ã‚‹"/>
- <check_box label="臨時" name="Temporary Checkbox Ctrl" tool_tip="作æˆ1分後ã«ã‚ªãƒ–ジェクトを削除"/>
+ <check_box label="臨時" name="Temporary Checkbox Ctrl" tool_tip="制作後 1 分ã§ã‚ªãƒ–ジェクトã¯å‰Šé™¤ã•ã‚Œã¾ã™"/>
<check_box label="ファントム" name="Phantom Checkbox Ctrl" tool_tip="オブジェクトåŒå£«ã®è¡çªã¾ãŸã¯ã‚ªãƒ–ジェクトã¨ã‚¢ãƒã‚¿ãƒ¼ã®è¡çªã‚’回é¿"/>
<text name="label position">
ä½ç½®ï¼ˆãƒ¡ãƒ¼ãƒˆãƒ«ï¼‰
@@ -250,68 +260,32 @@
<spinner label="X" name="Rot X"/>
<spinner label="Y" name="Rot Y"/>
<spinner label="Z" name="Rot Z"/>
- <text name="label material">
- ç´ æ
- </text>
- <combo_box name="material">
- <combo_item name="Stone">
- 石æ
- </combo_item>
- <combo_item name="Metal">
- 金属
- </combo_item>
- <combo_item name="Glass">
- ガラス
- </combo_item>
- <combo_item name="Wood">
- 木æ
- </combo_item>
- <combo_item name="Flesh">
- 肌
- </combo_item>
- <combo_item name="Plastic">
- プラスãƒãƒƒã‚¯
- </combo_item>
- <combo_item name="Rubber">
- ゴム
- </combo_item>
- </combo_box>
- <text name="label basetype">
- 建造物ブロック・タイプ
- </text>
<combo_box name="comboBaseType">
- <combo_item name="Box">
- ボックス
- </combo_item>
- <combo_item name="Cylinder">
- シリンダー
- </combo_item>
- <combo_item name="Prism">
- プリズム
- </combo_item>
- <combo_item name="Sphere">
- çƒå½¢
- </combo_item>
- <combo_item name="Torus">
- トーラス
- </combo_item>
- <combo_item name="Tube">
- ãƒãƒ¥ãƒ¼ãƒ–
- </combo_item>
- <combo_item name="Ring">
- リング
- </combo_item>
- <combo_item name="Sculpted">
- スカルプト
- </combo_item>
+ <combo_box.item label="ボックス" name="Box"/>
+ <combo_box.item label="シリンダー" name="Cylinder"/>
+ <combo_box.item label="プリズム" name="Prism"/>
+ <combo_box.item label="çƒå½¢" name="Sphere"/>
+ <combo_box.item label="トーラス" name="Torus"/>
+ <combo_box.item label="ãƒãƒ¥ãƒ¼ãƒ–" name="Tube"/>
+ <combo_box.item label="リング" name="Ring"/>
+ <combo_box.item label="スカルプト" name="Sculpted"/>
+ </combo_box>
+ <combo_box name="material">
+ <combo_box.item label="石æ" name="Stone"/>
+ <combo_box.item label="金属" name="Metal"/>
+ <combo_box.item label="ガラス" name="Glass"/>
+ <combo_box.item label="木æ" name="Wood"/>
+ <combo_box.item label="肌" name="Flesh"/>
+ <combo_box.item label="プラスãƒãƒƒã‚¯" name="Plastic"/>
+ <combo_box.item label="ゴム" name="Rubber"/>
</combo_box>
<text name="text cut">
- パス・カットã®å§‹ç‚¹ã¨çµ‚点
+ パスカット (始点/終点)
</text>
<spinner label="B" name="cut begin"/>
<spinner label="E" name="cut end"/>
<text name="text hollow">
- 中空(空洞)
+ 中空(空洞)
</text>
<text name="text skew">
傾斜
@@ -320,21 +294,13 @@
中空(空洞)ã®å½¢
</text>
<combo_box name="hole">
- <combo_item name="Default">
- デフォルト
- </combo_item>
- <combo_item name="Circle">
- サークル
- </combo_item>
- <combo_item name="Square">
- 正方形
- </combo_item>
- <combo_item name="Triangle">
- 三角形
- </combo_item>
+ <combo_box.item label="デフォルト" name="Default"/>
+ <combo_box.item label="サークル" name="Circle"/>
+ <combo_box.item label="正方形" name="Square"/>
+ <combo_box.item label="三角形" name="Triangle"/>
</combo_box>
<text name="text twist">
- ã²ã­ã‚Šã®å§‹ã¾ã‚Šã¨çµ‚ã‚ã‚Š
+ ã²ã­ã‚Š (始点/終点)
</text>
<spinner label="B" name="Twist Begin"/>
<spinner label="E" name="Twist End"/>
@@ -352,13 +318,13 @@
<spinner label="X" name="Shear X"/>
<spinner label="Y" name="Shear Y"/>
<text name="advanced_cut">
- プロフィール・カットã®å§‹ç‚¹ã¨çµ‚点
+ プロフィールカット (始点/終点)
</text>
<text name="advanced_dimple">
- ãã¼ã¿ã®å§‹ç‚¹ã¨çµ‚点
+ ãã¼ã¿ (始点/終点)
</text>
<text name="advanced_slice">
- 切りå–ã‚Šã®å§‹ç‚¹ã¨çµ‚点
+ 切りå–ã‚Š (始点/終点)
</text>
<spinner label="B" name="Path Limit Begin"/>
<spinner label="E" name="Path Limit End"/>
@@ -374,27 +340,17 @@
回転体
</text>
<texture_picker label="スカルプトテクスãƒãƒ£ãƒ¼" name="sculpt texture control" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¦ãã ã•ã„。"/>
- <check_box label="ミラー" name="sculpt mirror control" tool_tip="スカルプトã•ã‚ŒãŸãƒ—リムをX軸上ã§å転"/>
- <check_box label="è£è¿”ã—" name="sculpt invert control" tool_tip="スカルプトã•ã‚ŒãŸãƒ—リムã®ãƒŽãƒ¼ãƒžãƒ«ã‚’逆転ã•ã›ã€è£è¿”ã—ã«è¡¨ç¤º"/>
+ <check_box label="ミラー" name="sculpt mirror control" tool_tip="スカルプトプリムを X 軸上ã§å転ã•ã›ã‚‹"/>
+ <check_box label="è£è¿”ã—" name="sculpt invert control" tool_tip="スカルプトプリムをå転ã•ã›ã¦è£è¿”ã™"/>
<text name="label sculpt type">
縫ã„ç›®ã®ã‚¿ã‚¤ãƒ—
</text>
<combo_box name="sculpt type control">
- <combo_item name="None">
- (ãªã—)
- </combo_item>
- <combo_item name="Sphere">
- çƒå½¢
- </combo_item>
- <combo_item name="Torus">
- トーラス
- </combo_item>
- <combo_item name="Plane">
- å¹³é¢
- </combo_item>
- <combo_item name="Cylinder">
- シリンダー
- </combo_item>
+ <combo_box.item label="(ãªã—)" name="None"/>
+ <combo_box.item label="çƒå½¢" name="Sphere"/>
+ <combo_box.item label="トーラス" name="Torus"/>
+ <combo_box.item label="å¹³é¢" name="Plane"/>
+ <combo_box.item label="シリンダー" name="Cylinder"/>
</combo_box>
</panel>
<panel label="特徴" name="Features">
@@ -404,27 +360,34 @@
<text name="edit_object">
オブジェクトã®ç‰¹å¾´ã‚’編集:
</text>
- <check_box label="フレキシブル・パス" name="Flexible1D Checkbox Ctrl" tool_tip="Z軸を中心ã¨ã™ã‚‹ã‚ªãƒ–ジェクトã®æŠ˜ã‚Œæ›²ãŒã‚Šã‚’有効ã«ã™ã‚‹ (クライアントå´ã®ã¿ï¼‰"/>
- <spinner label="柔軟性" name="FlexNumSections" width="135" label_width="72"/>
- <spinner label="é‡åŠ›" name="FlexGravity" width="135" label_width="72"/>
- <spinner label="ドラッグ" name="FlexFriction" width="135" label_width="72"/>
- <spinner label="風" name="FlexWind" width="135" label_width="72"/>
- <spinner label="ç·Šå¼µ" name="FlexTension" width="135" label_width="72"/>
- <spinner label="X軸方å‘ã®åŠ›" name="FlexForceX" width="135" label_width="72"/>
- <spinner label="Y軸方å‘ã®åŠ›" name="FlexForceY" width="135" label_width="72"/>
- <spinner label="Z軸方å‘ã®åŠ›" name="FlexForceZ" width="135" label_width="72"/>
+ <check_box label="フレキシブル・パス" name="Flexible1D Checkbox Ctrl" tool_tip="Z 軸を中心ã«ã‚ªãƒ–ジェクトã®å±ˆæ›²ã‚’有効ã«ã™ã‚‹ï¼ˆã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆå´ã®ã¿ï¼‰"/>
+ <spinner label="柔軟性" label_width="72" name="FlexNumSections" width="135"/>
+ <spinner label="é‡åŠ›" label_width="72" name="FlexGravity" width="135"/>
+ <spinner label="ドラッグ" label_width="72" name="FlexFriction" width="135"/>
+ <spinner label="風" label_width="72" name="FlexWind" width="135"/>
+ <spinner label="ç·Šå¼µ" label_width="72" name="FlexTension" width="135"/>
+ <spinner label="X軸方å‘ã®åŠ›" label_width="72" name="FlexForceX" width="135"/>
+ <spinner label="Y軸方å‘ã®åŠ›" label_width="72" name="FlexForceY" width="135"/>
+ <spinner label="Z軸方å‘ã®åŠ›" label_width="72" name="FlexForceZ" width="135"/>
<check_box label="å…‰" name="Light Checkbox Ctrl" tool_tip="オブジェクトãŒç™ºå…‰"/>
- <text name="label color">
- 色
- </text>
- <color_swatch label="" name="colorswatch" tool_tip="カラー・ピッカーをクリックã—ã¦é–‹ã" left_delta="74"/>
- <spinner label="è¼åº¦" name="Light Intensity" width="135" label_width="72"/>
- <spinner label="åŠå¾„" name="Light Radius" width="135" label_width="72"/>
- <spinner label="å¼±ã¾ã‚‹" name="Light Falloff" width="135" label_width="72"/>
+ <color_swatch label="" left_delta="74" name="colorswatch" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
+ <texture_picker label="" name="light texture control" tool_tip="クリックã§æŠ•å½±ç”»ã‚’é¸æŠžï¼ˆé…延レンダリング有効時ã®ã¿ï¼‰"/>
+ <spinner label="è¼åº¦" label_width="72" name="Light Intensity" width="135"/>
+ <spinner label="FOV" name="Light FOV"/>
+ <spinner label="åŠå¾„" label_width="72" name="Light Radius" width="135"/>
+ <spinner label="焦点" name="Light Focus"/>
+ <spinner label="å¼±ã¾ã‚‹" label_width="72" name="Light Falloff" width="135"/>
+ <spinner label="環境" name="Light Ambiance"/>
</panel>
<panel label="æ質" name="Texture">
+ <panel.string name="string repeats per meter">
+ メートルã”ã¨ã«ç¹°è¿”ã™
+ </panel.string>
+ <panel.string name="string repeats per face">
+ é¢ã”ã¨ã«ç¹°ã‚Šè¿”ã™
+ </panel.string>
<texture_picker label="テクスãƒãƒ£ãƒ¼" name="texture control" tool_tip="写真をクリックã—ã¦é¸æŠž"/>
- <color_swatch label="色" name="colorswatch" tool_tip="カラー・ピッカーをクリックã—ã¦é–‹ã"/>
+ <color_swatch label="色" name="colorswatch" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
<text name="color trans">
é€éŽåº¦ %
</text>
@@ -436,123 +399,69 @@
マッピング
</text>
<combo_box name="combobox texgen">
- <combo_item name="Default">
- デフォルト
- </combo_item>
- <combo_item name="Planar">
- å¹³é¢
- </combo_item>
+ <combo_box.item label="デフォルト" name="Default"/>
+ <combo_box.item label="å¹³é¢" name="Planar"/>
</combo_box>
<text name="label shininess">
è¼ã
</text>
<combo_box name="combobox shininess">
- <combo_item name="None">
- ãªã—
- </combo_item>
- <combo_item name="Low">
- 低
- </combo_item>
- <combo_item name="Medium">
- 中
- </combo_item>
- <combo_item name="High">
- 高
- </combo_item>
+ <combo_box.item label="ãªã—" name="None"/>
+ <combo_box.item label="低" name="Low"/>
+ <combo_box.item label="中" name="Medium"/>
+ <combo_box.item label="高" name="High"/>
</combo_box>
<text name="label bumpiness">
凹凸
</text>
<combo_box name="combobox bumpiness">
- <combo_item name="None">
- ãªã—
- </combo_item>
- <combo_item name="Brightness">
- 明るã•
- </combo_item>
- <combo_item name="Darkness">
- æš—ã•
- </combo_item>
- <combo_item name="woodgrain">
- 木目調
- </combo_item>
- <combo_item name="bark">
- 木ã®çš®
- </combo_item>
- <combo_item name="bricks">
- レンガ
- </combo_item>
- <combo_item name="checker">
- ãƒã‚§ãƒƒã‚«ãƒ¼
- </combo_item>
- <combo_item name="concrete">
- コンクリート
- </combo_item>
- <combo_item name="crustytile">
- クラスティ・タイル
- </combo_item>
- <combo_item name="cutstone">
- カットストーン
- </combo_item>
- <combo_item name="discs">
- ディスク
- </combo_item>
- <combo_item name="gravel">
- 砂利
- </combo_item>
- <combo_item name="petridish">
- ペトリ
- </combo_item>
- <combo_item name="siding">
- 羽目æ¿
- </combo_item>
- <combo_item name="stonetile">
- ストーン・タイル
- </combo_item>
- <combo_item name="stucco">
- ã—ã£ãã„
- </combo_item>
- <combo_item name="suction">
- å¸ã„è¾¼ã¿
- </combo_item>
- <combo_item name="weave">
- 織目
- </combo_item>
+ <combo_box.item label="ãªã—" name="None"/>
+ <combo_box.item label="明るã•" name="Brightness"/>
+ <combo_box.item label="æš—ã•" name="Darkness"/>
+ <combo_box.item label="木目調" name="woodgrain"/>
+ <combo_box.item label="木ã®çš®" name="bark"/>
+ <combo_box.item label="レンガ" name="bricks"/>
+ <combo_box.item label="ãƒã‚§ãƒƒã‚«ãƒ¼" name="checker"/>
+ <combo_box.item label="コンクリート" name="concrete"/>
+ <combo_box.item label="クラスティ・タイル" name="crustytile"/>
+ <combo_box.item label="カットストーン" name="cutstone"/>
+ <combo_box.item label="ディスク" name="discs"/>
+ <combo_box.item label="砂利" name="gravel"/>
+ <combo_box.item label="ペトリ" name="petridish"/>
+ <combo_box.item label="羽目æ¿" name="siding"/>
+ <combo_box.item label="ストーン・タイル" name="stonetile"/>
+ <combo_box.item label="ã—ã£ãã„" name="stucco"/>
+ <combo_box.item label="å¸ã„è¾¼ã¿" name="suction"/>
+ <combo_box.item label="織目" name="weave"/>
</combo_box>
<text name="tex scale">
- é¢ã”ã¨ã«ç¹°ã‚Šè¿”ã™
+ å復 / é¢
</text>
<spinner label="水平(U)" name="TexScaleU"/>
<check_box label="å転" name="checkbox flip s"/>
- <spinner label="åž‚ç›´ (V)" name="TexScaleV"/>
+ <spinner label="垂直(V)" name="TexScaleV"/>
<check_box label="å転" name="checkbox flip t"/>
- <text name="tex rotate">
- 回転(度)
- </text>
- <string name="string repeats per meter">
- メートルã”ã¨ã«ç¹°è¿”ã™
- </string>
- <string name="string repeats per face">
- é¢ã”ã¨ã«ç¹°ã‚Šè¿”ã™
- </string>
- <text name="rpt">
- メートルã”ã¨ã«ç¹°è¿”ã™
- </text>
+ <spinner label="回転˚" name="TexRot"/>
+ <spinner label="å復 / メーター" name="rptctrl"/>
<button label="é©ç”¨" label_selected="é©ç”¨" name="button apply"/>
<text name="tex offset">
- ãšã‚Œ
+ テクスãƒãƒ£ã®ã‚ºãƒ¬
</text>
<spinner label="水平(U)" name="TexOffsetU"/>
- <spinner label="åž‚ç›´ (V)" name="TexOffsetV"/>
- <text name="textbox autofix" width="190">
- メディア・テクスãƒãƒ£ãƒ¼ã‚’æƒãˆã‚‹
-(最åˆã«ãƒ­ãƒ¼ãƒ‰ã™ã‚‹ã“ã¨ï¼‰
- </text>
- <button bottom="-365" label="æƒãˆã‚‹" label_selected="æƒãˆã‚‹" left="155" name="button align"/>
+ <spinner label="垂直(V)" name="TexOffsetV"/>
+ <panel name="Add_Media">
+ <text name="media_tex">
+ メディア URL
+ </text>
+ <button name="add_media" tool_tip="メディアを追加"/>
+ <button name="delete_media" tool_tip="ã“ã®ãƒ¡ãƒ‡ã‚£ã‚¢ãƒ†ã‚¯ã‚¹ãƒãƒ£ã‚’削除"/>
+ <button name="edit_media" tool_tip="ã“ã®ãƒ¡ãƒ‡ã‚£ã‚¢ã‚’編集"/>
+ <button label="æƒãˆã‚‹" label_selected="メディアを一列ã«æƒãˆã‚‹" name="button align"/>
+ </panel>
</panel>
<panel label="中身" name="Contents">
- <button label="æ–°ã—ã„スクリプト" label_selected="æ–°ã—ã„スクリプト" name="button new script" width="120"/>
- <button label="権é™..." name="button permissions" left_delta="130" width="80"/>
+ <button label="æ–°ã—ã„スクリプト" label_selected="æ–°è¦ã‚¹ã‚¯ãƒªãƒ—ト" name="button new script" width="120"/>
+ <button label="権é™" left_delta="130" name="button permissions" width="80"/>
</panel>
</tab_container>
<panel name="land info panel">
@@ -560,62 +469,29 @@
区画情報
</text>
<text name="label_area_price" width="200">
- 価格:[AREA]平方メートルã‚ãŸã‚ŠL$[PRICE]
+ 価格: [AREA] 平方メートル L$ [PRICE]
</text>
<text name="label_area" width="200">
- é¢ç©ï¼š[AREA]平方メートル
+ é¢ç©ï¼š [AREA] 平方メートル
</text>
- <button label="土地情報..." label_selected="土地情報..." name="button about land"/>
- <check_box label="オーナーを表示" name="checkbox show owners" tool_tip="所有権別ã«åŒºç”»ã‚’色分ã‘ã—ã¾ã™"/>
- <button label="?" label_selected="?" name="button show owners help" left_delta="114"/>
+ <button label="土地情報" label_selected="土地情報" name="button about land"/>
+ <check_box label="オーナーを表示" name="checkbox show owners" tool_tip="所有者ã®ç¨®é¡žåˆ¥ã«åŒºç”»ã‚’色ã¥ã‘:
+
+ç·‘ = ã‚ãªãŸã®åœŸåœ°
+アクア = ã‚ãªãŸã®ã‚°ãƒ«ãƒ¼ãƒ—所有地
+赤 = 他人ãŒæ‰€æœ‰ã™ã‚‹åœŸåœ°
+黄色 = 売り出ã—中
+紫 = オークション
+グレー = パブリック"/>
<text name="label_parcel_modify">
区画ã®ç·¨é›†
</text>
- <button label="å†åˆ†å‰²..." label_selected="å†åˆ†å‰²..." name="button subdivide land"/>
- <button label="çµ±åˆã™ã‚‹..." label_selected="çµ±åˆã™ã‚‹..." name="button join land"/>
+ <button label="å†åˆ†å‰²" label_selected="å†åˆ†å‰²" name="button subdivide land"/>
+ <button label="çµ±åˆ" label_selected="çµ±åˆ" name="button join land"/>
<text name="label_parcel_trans">
土地å–引
</text>
- <button label="土地を購入..." label_selected="土地を購入..." name="button buy land"/>
- <button label="土地を放棄..." label_selected="土地を放棄..." name="button abandon land"/>
+ <button label="土地ã®è³¼å…¥" label_selected="土地ã®è³¼å…¥" name="button buy land"/>
+ <button label="土地ã®æ”¾æ£„" label_selected="土地ã®æ”¾æ£„" name="button abandon land"/>
</panel>
- <string name="status_rotate">
- 色ã®ä»˜ã„ãŸãƒãƒ³ãƒ‰ã‚’ドラッグã—ã¦ã‚ªãƒ–ジェクトを回転
- </string>
- <string name="status_scale">
- é¸æŠžã—ãŸå´ã‚’クリックã—ã€ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦å¼•ã伸ã°ã™
- </string>
- <string name="status_move">
- 移動:ドラッグã€ã‚³ãƒ”ー:Shiftを押ã—ãªãŒã‚‰ï¾„゙ラッグ
- </string>
- <string name="status_modifyland">
- 土地をクリックã—ã€ãƒœã‚¿ãƒ³ã‚’押ã—ãŸã¾ã¾å…¥åŠ›ã—ã¦ä¿®æ­£å¤‰æ›´
- </string>
- <string name="status_camera">
- クリックã—ドラッグã—ã¦è¦–界を調整
- </string>
- <string name="status_grab">
- 移動:ドラッグã€æŒã¡ä¸Šã’:Ctrlã€å›žè»¢ï¼šCtrl+Shift
- </string>
- <string name="status_place">
- インワールドã§ã‚¯ãƒªãƒƒã‚¯ã—ã¦ä½œæˆ
- </string>
- <string name="status_selectland">
- 土地をクリックã—ã€ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦é¸æŠž
- </string>
- <string name="grid_screen_text">
- ç”»é¢
- </string>
- <string name="grid_local_text">
- ローカル
- </string>
- <string name="grid_world_text">
- 世界
- </string>
- <string name="grid_reference_text">
- å‚ç…§
- </string>
- <string name="grid_attachment_text">
- アタッãƒãƒ¡ãƒ³ãƒˆ
- </string>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_top_objects.xml b/indra/newview/skins/default/xui/ja/floater_top_objects.xml
index e59f72bf30..e5d1fc5f03 100644
--- a/indra/newview/skins/default/xui/ja/floater_top_objects.xml
+++ b/indra/newview/skins/default/xui/ja/floater_top_objects.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="top_objects" title="ロード中...">
+<floater name="top_objects" title="ローディング...">
<text name="title_text">
ロード中...
</text>
diff --git a/indra/newview/skins/default/xui/ja/floater_tos.xml b/indra/newview/skins/default/xui/ja/floater_tos.xml
index 31e3a24045..85ac102885 100644
--- a/indra/newview/skins/default/xui/ja/floater_tos.xml
+++ b/indra/newview/skins/default/xui/ja/floater_tos.xml
@@ -1,22 +1,17 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="modal container" title=" ">
- <button label="続行" label_selected="続行" name="Continue" />
- <button label="å–り消ã—" label_selected="å–り消ã—" name="Cancel" />
+ <button label="続行" label_selected="続行" name="Continue"/>
+ <button label="å–り消ã—" label_selected="å–り消ã—" name="Cancel"/>
<radio_group name="tos_agreement">
- <radio_item name="radio_disagree">
- 利用è¦ç´„ã«åŒæ„ã—ã¾ã›ã‚“
- </radio_item>
- <radio_item name="radio_agree">
- 利用è¦ç´„ã«åŒæ„ã—ã¾ã™
- </radio_item>
+ <radio_item label="利用è¦ç´„ã«åŒæ„ã—ã¾ã›ã‚“" name="radio_disagree"/>
+ <radio_item label="利用è¦ç´„ã«åŒæ„ã—ã¾ã™" name="radio_agree"/>
</radio_group>
<text name="tos_title">
利用è¦ç´„
</text>
- <check_box label="利用è¦ç´„ã«åŒæ„ã—ã¾ã™" name="agree_chk" />
+ <check_box label="利用è¦ç´„ã«åŒæ„ã—ã¾ã™" name="agree_chk"/>
<text name="tos_heading">
- 以下ã®åˆ©ç”¨è¦ç´„を注æ„æ·±ããŠèª­ã¿ãã ã•ã„。 SecondLifeã¸ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹ã«ã¯ã€
-è¦ç´„ã«åŒæ„ã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。
+ 次ã®åˆ©ç”¨è¦ç´„をよããŠèª­ã¿ãã ã•ã„。 [SECOND_LIFE] ã¸ã®ãƒ­ã‚°ã‚¤ãƒ³ã‚’続ã‘ã‚‹ã«ã¯ã€è¦ç´„ã«åŒæ„ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
</text>
<text_editor name="tos_text">
TOS_TEXT
diff --git a/indra/newview/skins/default/xui/ja/floater_voice_controls.xml b/indra/newview/skins/default/xui/ja/floater_voice_controls.xml
new file mode 100644
index 0000000000..5d52144265
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_voice_controls.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_voice_controls" title="ボイスコントロール">
+ <panel name="control_panel">
+ <panel name="my_panel">
+ <text name="user_text" value="Mya Avatar:"/>
+ </panel>
+ <layout_stack>
+ <layout_panel>
+ <slider_bar name="volume_slider_bar" tool_tip="音é‡"/>
+ </layout_panel>
+ </layout_stack>
+ </panel>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_water.xml b/indra/newview/skins/default/xui/ja/floater_water.xml
index 054b003197..52cd91a08a 100644
--- a/indra/newview/skins/default/xui/ja/floater_water.xml
+++ b/indra/newview/skins/default/xui/ja/floater_water.xml
@@ -1,66 +1,52 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Water Floater" title="æ°´ã®é«˜åº¦ãªç·¨é›†">
+ <floater.string name="WLDefaultWaterNames">
+ Default:Glassy:Pond:Murky:Second Plague:SNAKE!!!:Valdez
+ </floater.string>
<text name="KeyFramePresetsText">
æ°´ã®äº‹å‰è¨­å®šï¼š
</text>
- <button label="æ–°è¦" label_selected="æ–°è¦" name="WaterNewPreset" />
- <button label="ä¿å­˜" label_selected="ä¿å­˜" name="WaterSavePreset" />
- <button label="削除" label_selected="削除" name="WaterDeletePreset" />
+ <button label="æ–°è¦" label_selected="æ–°è¦" name="WaterNewPreset"/>
+ <button label="ä¿å­˜" label_selected="ä¿å­˜" name="WaterSavePreset"/>
+ <button label="削除" label_selected="削除" name="WaterDeletePreset"/>
<tab_container name="Water Tabs">
<panel label="設定" name="Settings">
<text name="BHText">
水中ã®ãƒ•ã‚©ã‚°åŠ¹æžœã®è‰²
</text>
- <button label="?" name="WaterFogColorHelp" />
- <color_swatch name="WaterFogColor"
- tool_tip="カラー・ピッカーをクリックã—ã¦é–‹ã" />
+ <color_swatch name="WaterFogColor" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
<text name="WaterFogDensText">
水中ã®é€æ˜Žåº¦æŒ‡æ•°
</text>
- <button label="?" name="WaterFogDensityHelp" />
<text name="WaterUnderWaterFogModText">
水中ã®ãƒ•ã‚©ã‚°åŠ¹æžœåŠ æ¸›
</text>
- <button label="?" name="WaterUnderWaterFogModHelp" />
<text name="BDensText">
ã•ã–æ³¢ã®å射スケール
</text>
- <button label="?" name="WaterNormalScaleHelp" />
- <text name="BHText2">
- 1
- </text>
- <text name="BHText3">
- 2
- </text>
- <text name="BHText4">
- 3
- </text>
+ <slider label="1" name="WaterNormalScaleX"/>
+ <slider label="2" name="WaterNormalScaleY"/>
+ <slider label="3" name="WaterNormalScaleZ"/>
<text name="HDText">
フレãƒãƒ«ãƒ»ã‚¹ã‚±ãƒ¼ãƒ«
</text>
- <button label="?" name="WaterFresnelScaleHelp" />
<text name="FresnelOffsetText">
フレãƒãƒ«ãƒ»ã‚ªãƒ•ã‚»ãƒƒãƒˆ
</text>
- <button label="?" name="WaterFresnelOffsetHelp" />
<text name="DensMultText">
æ°´é¢ã®å±ˆæŠ˜ã‚¹ã‚±ãƒ¼ãƒ«
</text>
- <button label="?" name="WaterScaleAboveHelp" />
<text name="WaterScaleBelowText">
水中ã®å±ˆæŠ˜ã‚¹ã‚±ãƒ¼ãƒ«
</text>
- <button label="?" name="WaterScaleBelowHelp" />
<text name="MaxAltText">
ä¸é€æ˜Žåº¦ã®å¢—å¹…
</text>
- <button label="?" name="WaterBlurMultiplierHelp" />
</panel>
<panel label="ç”»åƒ" name="Waves">
<text name="BHText">
大波ã®æ–¹å‘
</text>
- <button label="?" name="WaterWave1Help" />
<text name="WaterWave1DirXText">
X
</text>
@@ -70,7 +56,6 @@
<text name="BHText2">
å°æ³¢ã®æ–¹å‘
</text>
- <button label="?" name="WaterWave2Help" />
<text name="WaterWave2DirXText">
X
</text>
@@ -80,10 +65,6 @@
<text name="BHText3">
ノーマル・マップ
</text>
- <button label="?" name="WaterNormalMapHelp" />
</panel>
</tab_container>
- <string name="WLDefaultWaterNames">
- Default:Glassy:Pond:Murky:Second Plague:SNAKE!!!:Valdez
- </string>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_wearable_save_as.xml b/indra/newview/skins/default/xui/ja/floater_wearable_save_as.xml
index 8286d29973..fc9ddf5096 100644
--- a/indra/newview/skins/default/xui/ja/floater_wearable_save_as.xml
+++ b/indra/newview/skins/default/xui/ja/floater_wearable_save_as.xml
@@ -2,10 +2,10 @@
<floater name="modal container" title=" ">
<button label="ä¿å­˜" label_selected="ä¿å­˜" name="Save" />
<button label="å–り消ã—" label_selected="å–り消ã—" name="Cancel" />
- <text type="string" length="1" name="Save item as:">
+ <text name="Save item as:">
アイテムを別åã§ä¿å­˜ï¼š
</text>
<line_editor name="name ed">
- æ–°è¦[DESC]
+ New [DESC]
</line_editor>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_whitelist_entry.xml b/indra/newview/skins/default/xui/ja/floater_whitelist_entry.xml
new file mode 100644
index 0000000000..b518d87477
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_whitelist_entry.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="whitelist_entry">
+ <text name="media_label">
+ URL ã‹ URL パターンを入力ã—ã¦ã€è¨±å¯ã™ã‚‹ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’リストã«è¿½åŠ ã—ã¾ã™ã€‚
+ </text>
+ <line_editor name="whitelist_entry" tool_tip="URL ã‹ URL パターンをホワイトリストã«å…¥åŠ›ã—ã¾ã™"/>
+ <button label="OK" name="ok_btn"/>
+ <button label="キャンセル" name="cancel_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_windlight_options.xml b/indra/newview/skins/default/xui/ja/floater_windlight_options.xml
index fa70de054f..feb94ef73e 100644
--- a/indra/newview/skins/default/xui/ja/floater_windlight_options.xml
+++ b/indra/newview/skins/default/xui/ja/floater_windlight_options.xml
@@ -1,19 +1,18 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="WindLight floater" title="空ã®é«˜åº¦ãªç·¨é›†">
<text name="KeyFramePresetsText">
空ã®äº‹å‰è¨­å®šï¼š
</text>
- <button label="æ–°è¦" label_selected="æ–°è¦" name="WLNewPreset" />
- <button label="ä¿å­˜" label_selected="ä¿å­˜" name="WLSavePreset" />
- <button label="削除" label_selected="削除" name="WLDeletePreset" />
- <button label="デイサイクル編集"
- label_selected="デイサイクル編集" name="WLDayCycleMenuButton" />
+ <button label="æ–°è¦" label_selected="æ–°è¦" name="WLNewPreset"/>
+ <button label="ä¿å­˜" label_selected="ä¿å­˜" name="WLSavePreset"/>
+ <button label="削除" label_selected="削除" name="WLDeletePreset"/>
+ <button label="デイサイクル編集" label_selected="デイサイクル編集" name="WLDayCycleMenuButton"/>
<tab_container name="WindLight Tabs">
<panel label="大気" name="Atmosphere">
<text name="BHText">
空ã®é…色
</text>
- <button label="?" name="WLBlueHorizonHelp" />
+ <button label="?" name="WLBlueHorizonHelp"/>
<text name="BHText2">
R
</text>
@@ -29,11 +28,11 @@
<text name="BDensText">
空ã¨é æ™¯ã®éœ²å…‰
</text>
- <button label="?" name="WLHazeHorizonHelp" />
+ <button label="?" name="WLHazeHorizonHelp"/>
<text name="BDensText2">
空ã®é…色ã¨æ¿ƒåº¦
</text>
- <button label="?" name="WLBlueDensityHelp" />
+ <button label="?" name="WLBlueDensityHelp"/>
<text name="BHText6">
R
</text>
@@ -49,25 +48,25 @@
<text name="HDText">
大気ã®ä¸é€æ˜Žåº¦
</text>
- <button label="?" name="WLHazeDensityHelp" />
+ <button label="?" name="WLHazeDensityHelp"/>
<text name="DensMultText">
大気ã®ä¸é€æ˜Žåº¦ã®å¢—å¹…
</text>
- <button label="?" name="WLDensityMultHelp" />
+ <button label="?" name="WLDensityMultHelp"/>
<text name="WLDistanceMultText">
視界ã®å¢—å¹…
</text>
- <button label="?" name="WLDistanceMultHelp" />
+ <button label="?" name="WLDistanceMultHelp"/>
<text name="MaxAltText">
最大高度
</text>
- <button label="?" name="WLMaxAltitudeHelp" />
+ <button label="?" name="WLMaxAltitudeHelp"/>
</panel>
<panel label="ライティング" name="Lighting">
<text name="SLCText">
太陽/月ã®è‰²
</text>
- <button label="?" name="WLSunlightColorHelp" />
+ <button label="?" name="WLSunlightColorHelp"/>
<text name="BHText">
R
</text>
@@ -83,11 +82,11 @@
<text name="TODText">
太陽/月ã®ä½ç½®
</text>
- <button label="?" name="WLTimeOfDayHelp" />
+ <button label="?" name="WLTimeOfDayHelp"/>
<text name="WLAmbientText">
アンビエント
</text>
- <button label="?" name="WLAmbientHelp" />
+ <button label="?" name="WLAmbientHelp"/>
<text name="BHText5">
R
</text>
@@ -103,27 +102,27 @@
<text name="WLEastAngleText">
æ±ã®è§’度
</text>
- <button label="?" name="WLEastAngleHelp" />
+ <button label="?" name="WLEastAngleHelp"/>
<text name="SunGlowText">
太陽ã®è¼ã
</text>
- <button label="?" name="WLSunGlowHelp" />
- <slider label="フォーカス " name="WLGlowB" />
- <slider label="サイズ " name="WLGlowR" />
+ <button label="?" name="WLSunGlowHelp"/>
+ <slider label="フォーカス " name="WLGlowB"/>
+ <slider label="サイズ " name="WLGlowR"/>
<text name="SceneGammaText">
風景ガンマ
</text>
- <button label="?" name="WLSceneGammaHelp" />
+ <button label="?" name="WLSceneGammaHelp"/>
<text name="WLStarText">
星ã®è¼ã
</text>
- <button label="?" name="WLStarBrightnessHelp" />
+ <button label="?" name="WLStarBrightnessHelp"/>
</panel>
<panel label="雲" name="Clouds">
<text name="WLCloudColorText">
雲ã®è‰²
</text>
- <button label="?" name="WLCloudColorHelp" />
+ <button label="?" name="WLCloudColorHelp"/>
<text name="BHText">
R
</text>
@@ -139,7 +138,7 @@
<text name="WLCloudColorText2">
雲㮠XY/密度
</text>
- <button label="?" name="WLCloudDensityHelp" />
+ <button label="?" name="WLCloudDensityHelp"/>
<text name="BHText5">
X
</text>
@@ -152,15 +151,15 @@
<text name="WLCloudCoverageText">
雲ã®é‡
</text>
- <button label="?" name="WLCloudCoverageHelp" />
+ <button label="?" name="WLCloudCoverageHelp"/>
<text name="WLCloudScaleText">
雲ã®ã‚¹ã‚±ãƒ¼ãƒ«
</text>
- <button label="?" name="WLCloudScaleHelp" />
+ <button label="?" name="WLCloudScaleHelp"/>
<text name="WLCloudDetailText">
雲ã®è©³ç´° (XY/密度)
</text>
- <button label="?" name="WLCloudDetailHelp" />
+ <button label="?" name="WLCloudDetailHelp"/>
<text name="BHText8">
X
</text>
@@ -173,15 +172,15 @@
<text name="WLCloudScrollXText">
雲ã®ç§»å‹•é€Ÿåº¦ (X æ–¹å‘)
</text>
- <button label="?" name="WLCloudScrollXHelp" />
- <check_box label="ロック" name="WLCloudLockX" />
+ <button label="?" name="WLCloudScrollXHelp"/>
+ <check_box label="ロック" name="WLCloudLockX"/>
<text name="WLCloudScrollYText">
雲ã®ç§»å‹•é€Ÿåº¦ (Y æ–¹å‘)
</text>
- <button label="?" name="WLCloudScrollYHelp" />
- <check_box label="ロック" name="WLCloudLockY" />
- <check_box label="従æ¥ã®é›²ã‚’æç”»" name="DrawClassicClouds" />
- <button label="?" name="WLClassicCloudsHelp" />
+ <button label="?" name="WLCloudScrollYHelp"/>
+ <check_box label="ロック" name="WLCloudLockY"/>
+ <check_box label="従æ¥ã®é›²ã‚’æç”»" name="DrawClassicClouds"/>
+ <button label="?" name="WLClassicCloudsHelp"/>
</panel>
</tab_container>
<string name="WLDefaultSkyNames">
diff --git a/indra/newview/skins/default/xui/ja/floater_world_map.xml b/indra/newview/skins/default/xui/ja/floater_world_map.xml
index a7a6e305ae..370c95530a 100644
--- a/indra/newview/skins/default/xui/ja/floater_world_map.xml
+++ b/indra/newview/skins/default/xui/ja/floater_world_map.xml
@@ -1,9 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="worldmap" title="世界地図">
- <tab_container name="maptab">
- <panel label="オブジェクト" name="objects_mapview"/>
- <panel label="地形" name="terrain_mapview"/>
- </tab_container>
<text name="you_label">
ã‚ãªãŸ
</text>
@@ -20,23 +16,19 @@
<button label="ホームã¸" label_selected="ホームã¸" name="Go Home" tool_tip="自分ã®ãƒ›ãƒ¼ãƒ ã«ãƒ†ãƒ¬ãƒãƒ¼ãƒˆ"/>
<check_box label="ä½äºº" name="people_chk"/>
<check_box label="インフォãƒãƒ–" name="infohub_chk"/>
- <check_box label="テレãƒãƒ–" name="telehubchk"/>
+ <check_box label="テレãƒãƒ–" name="telehub_chk"/>
<check_box label="売り地" name="land_for_sale_chk"/>
<text name="events_label">
イベント:
</text>
<check_box label="PG" name="event_chk"/>
- <check_box label="Mature" name="event_mature_chk"/>
+ <check_box initial_value="true" label="Mature" name="event_mature_chk"/>
<check_box label="Adult" name="event_adult_chk"/>
- <combo_box label="オンラインã®ãƒ•ãƒ¬ãƒ³ãƒ‰" name="friend combo" tool_tip="地図ã«è¡¨ç¤ºã•ã‚ŒãŸãƒ•ãƒ¬ãƒ³ãƒ‰">
- <combo_item name="none_selected">
- オンラインã®ãƒ•ãƒ¬ãƒ³ãƒ‰
- </combo_item>
+ <combo_box label="オンラインã®ãƒ•ãƒ¬ãƒ³ãƒ‰" name="friend combo" tool_tip="地図ã«è¡¨ç¤ºã™ã‚‹ãƒ•ãƒ¬ãƒ³ãƒ‰">
+ <combo_box.item label="オンラインã®ãƒ•ãƒ¬ãƒ³ãƒ‰" name="item1"/>
</combo_box>
- <combo_box label="ランドマーク" name="landmark combo" tool_tip="地図ã«è¡¨ç¤ºã•ã‚ŒãŸãƒ©ãƒ³ãƒ‰ãƒžãƒ¼ã‚¯">
- <combo_item name="none_selected">
- ランドマーク
- </combo_item>
+ <combo_box label="ランドマーク" name="landmark combo" tool_tip="地図ã«è¡¨ç¤ºã™ã‚‹ãƒ©ãƒ³ãƒ‰ãƒžãƒ¼ã‚¯">
+ <combo_box.item label="ランドマーク" name="item1"/>
</combo_box>
<line_editor label="地域åã§æ¤œç´¢" name="location" tool_tip="地域åを入力ã—ã¦ãã ã•ã„。"/>
<button label="検索" name="DoSearch" tool_tip="地域検索"/>
@@ -44,8 +36,8 @@
検索çµæžœï¼š
</text>
<scroll_list name="search_results">
- <column label="" name="icon"/>
- <column label="" name="sim_name"/>
+ <scroll_list.columns label="" name="icon"/>
+ <scroll_list.columns label="" name="sim_name"/>
</scroll_list>
<text name="location_label">
ä½ç½®ï¼š
@@ -57,6 +49,6 @@
<button label="目的地を表示" label_selected="目的地を表示" name="Show Destination" tool_tip="é¸æŠžã—ãŸãƒ­ã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã‚’地図ã®ä¸­å¿ƒã«ã™ã‚‹"/>
<button label="クリア" label_selected="クリア" name="Clear" tool_tip="トラッキングをåœæ­¢"/>
<button label="ç¾åœ¨åœ°ã‚’表示" label_selected="ç¾åœ¨åœ°ã‚’表示" name="Show My Location" tool_tip="ã‚ãªãŸã®ã‚¢ãƒã‚¿ãƒ¼ã®ãƒ­ã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã‚’地図ã®ä¸­å¿ƒã«ã™ã‚‹"/>
- <button label="SLURLをクリップボードã«ã‚³ãƒ”ー" name="copy_slurl" tool_tip="ç¾åœ¨åœ°ã‚’SLURLã¨ã—ã¦ã‚³ãƒ”ーã—ã€ã‚¦ã‚§ãƒ–ã§ä½¿ç”¨"/>
+ <button label="SLurl をクリップボードã«ã‚³ãƒ”ー" name="copy_slurl" tool_tip="ç¾åœ¨åœ°ã‚’ SLurl ã¨ã—ã¦ã‚³ãƒ”ーã—ã¦ã€Webã§ä½¿ç”¨ã—ã¾ã™ã€‚"/>
<slider label="ズーム" name="zoom slider"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/inspect_avatar.xml b/indra/newview/skins/default/xui/ja/inspect_avatar.xml
new file mode 100644
index 0000000000..df3f6d0cd0
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/inspect_avatar.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater name="inspect_avatar">
+ <string name="Subtitle">
+ [AGE]
+ </string>
+ <string name="Details">
+ [SL_PROFILE]
+ </string>
+ <string name="Partner">
+ パートナー: [PARTNER]
+ </string>
+ <text name="user_name" value="Grumpity ProductEngine"/>
+ <text name="user_subtitle" value="11 Months, 3 days old"/>
+ <text name="user_details">
+ This is my second life description and I really think it is great.
+ </text>
+ <text name="user_partner">
+ Erica Linden
+ </text>
+ <slider name="volume_slider" tool_tip="ボイス音é‡" value="0.5"/>
+ <button label="フレンド登録" name="add_friend_btn"/>
+ <button label="IM" name="im_btn"/>
+ <button label="詳細" name="view_profile_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/inspect_group.xml b/indra/newview/skins/default/xui/ja/inspect_group.xml
new file mode 100644
index 0000000000..b292d4b525
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/inspect_group.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater name="inspect_group">
+ <string name="PrivateGroup">
+ プライベートグループ
+ </string>
+ <string name="FreeToJoin">
+ å‚加費無料
+ </string>
+ <string name="CostToJoin">
+ å‚加費 L$[AMOUNT]
+ </string>
+ <string name="YouAreMember">
+ ã‚ãªãŸã¯ãƒ¡ãƒ³ãƒãƒ¼ã§ã™
+ </string>
+ <text name="group_name">
+ Grumpity&apos;s Grumpy Group of Moose
+ </text>
+ <text name="group_subtitle">
+ 123 メートル
+ </text>
+ <text name="group_details">
+ A group of folks charged with creating a room with a moose.
+Fear the moose! Fear it! And the mongoose too!
+ </text>
+ <text name="group_cost">
+ L$123 to join
+ </text>
+ <button label="å‚加" name="join_btn"/>
+ <button label="脱退" name="leave_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/inspect_object.xml b/indra/newview/skins/default/xui/ja/inspect_object.xml
new file mode 100644
index 0000000000..842030c39a
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/inspect_object.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater name="inspect_object">
+ <string name="Creator">
+ 制作者: [CREATOR]
+ </string>
+ <string name="CreatorAndOwner">
+ 制作者: [CREATOR]
+所有者: [OWNER]
+ </string>
+ <string name="Price">
+ L$[AMOUNT]
+ </string>
+ <string name="PriceFree">
+ ç„¡æ–™ã§ã™ï¼
+ </string>
+ <string name="Touch">
+ 触る
+ </string>
+ <string name="Sit">
+ 座る
+ </string>
+ <text name="object_name" value="Test Object Name That Is Really Long"/>
+ <text name="object_creator">
+ by secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
+owner secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
+ </text>
+ <text name="price_text">
+ L$300,000
+ </text>
+ <text name="object_description">
+ This is a really long description for an object being as how it is at least 80 characters in length and maybe more like 120 at this point. Who knows, really?
+ </text>
+ <text name="object_media_url">
+ http://www.superdupertest.com
+ </text>
+ <button label="è²·ã†" name="buy_btn"/>
+ <button label="支払ã†" name="pay_btn"/>
+ <button label="コピーをå–ã‚‹" name="take_free_copy_btn"/>
+ <button label="触る" name="touch_btn"/>
+ <button label="座る" name="sit_btn"/>
+ <button label="é–‹ã" name="open_btn"/>
+ <icon name="secure_browsing" tool_tip="安全ãªé–²è¦§"/>
+ <button label="詳細" name="more_info_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/inspect_remote_object.xml b/indra/newview/skins/default/xui/ja/inspect_remote_object.xml
new file mode 100644
index 0000000000..483d3fec52
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/inspect_remote_object.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater name="inspect_remote_object">
+ <text name="object_name">
+ Test Object Name That Is Really Long
+ </text>
+ <text name="object_owner_label">
+ 所有者:
+ </text>
+ <text name="object_owner">
+ Longavatarname Johnsonlongstonnammer
+ </text>
+ <text name="object_slurl_label">
+ ä½ç½®ï¼š
+ </text>
+ <text name="object_slurl">
+ http://slurl.com/Ahern/50/50/50
+ </text>
+ <button label="地図" name="map_btn"/>
+ <button label="ブロック" name="block_btn"/>
+ <button label="é–‰ã˜ã‚‹" name="close_btn"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/language_settings.xml b/indra/newview/skins/default/xui/ja/language_settings.xml
new file mode 100644
index 0000000000..71418d446a
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/language_settings.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- This file contains strings that used to be hardcoded in the source.-->
+<strings>
+
+ <!-- Locale Information -->
+ <string name="MicrosoftLocale">english</string>
+ <string name="DarwinLocale">C</string>
+ <string name="LinuxLocale">C</string>
+
+ <!--
+ datetimeToCodes["wkday"] = "%a"; // Thu
+ datetimeToCodes["weekday"] = "%A"; // Thursday
+ datetimeToCodes["year4"] = "%Y"; // 2009
+ datetimeToCodes["year"] = "%Y"; // 2009
+ datetimeToCodes["year2"] = "%y"; // 09
+ datetimeToCodes["mth"] = "%b"; // Aug
+ datetimeToCodes["month"] = "%B"; // August
+ datetimeToCodes["mthnum"] = "%m"; // 08
+ datetimeToCodes["day"] = "%d"; // 31
+ datetimeToCodes["hour24"] = "%H"; // 14
+ datetimeToCodes["hour"] = "%H"; // 14
+ datetimeToCodes["hour12"] = "%I"; // 02
+ datetimeToCodes["min"] = "%M"; // 59
+ datetimeToCodes["ampm"] = "%p"; // AM
+ datetimeToCodes["second"] = "%S"; // 59
+ datetimeToCodes["timezone"] = "%Z"; // PST
+ -->
+
+ <string name="TimeHour">hour,datetime,slt</string>
+ <string name="TimeMin">min,datetime,slt</string>
+ <string name="TimeYear">year,datetime,slt</string>
+ <string name="TimeDay">day,datetime,slt</string>
+ <string name="TimeMonth">mthnum,datetime,slt</string>
+ <string name="TimeWeek">wkday,datetime,slt</string>
+ <string name="TimeAMPM">ampm,datetime,slt</string>
+ <string name="TimeHour12">hour12,datetime,slt</string>
+
+ <string name="LTimeMthNum">mthnum,datetime,local</string>
+ <string name="LTimeWeek">wkday,datetime,local</string>
+ <string name="LTimeMonth">mth,datetime,local</string>
+ <string name="LTimeDay">day,datetime,local</string>
+ <string name="LTimeSec">second,datetime,local</string>
+ <string name="LTimeHour">hour,datetime,local</string>
+ <string name="LTimeMin">min,datetime,local</string>
+ <string name="LTimeYear">year,datetime,local</string>
+
+ <string name="UTCTimeWeek">weekday,datetime,utc</string>
+ <string name="UTCTimeDay">day,datetime,utc</string>
+ <string name="UTCTimeMth">mth,datetime,utc</string>
+ <string name="UTCTimeYr">year,datetime,utc</string>
+ <string name="UTCTimeHr">hour,datetime,utc</string>
+ <string name="UTCTimeMin">min,datetime,utc</string>
+ <string name="UTCTimeSec">second,datetime,utc</string>
+ <string name="UTCTimeTimezone">timezone,datetime,utc</string>
+</strings>
diff --git a/indra/newview/skins/default/xui/ja/menu_avatar_icon.xml b/indra/newview/skins/default/xui/ja/menu_avatar_icon.xml
new file mode 100644
index 0000000000..ef63f3f4e0
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_avatar_icon.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Avatar Icon Menu">
+ <menu_item_call label="プロフィールを表示..." name="Show Profile"/>
+ <menu_item_call label="IMã‚’é€ä¿¡..." name="Send IM"/>
+ <menu_item_call label="フレンドを追加..." name="Add Friend"/>
+ <menu_item_call label="フレンドを削除..." name="Remove Friend"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_bottomtray.xml b/indra/newview/skins/default/xui/ja/menu_bottomtray.xml
new file mode 100644
index 0000000000..3ca2de247e
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_bottomtray.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="hide_camera_move_controls_menu">
+ <menu_item_check label="ジェスãƒãƒ£ãƒ¼ãƒœã‚¿ãƒ³" name="ShowGestureButton"/>
+ <menu_item_check label="移動ボタン" name="ShowMoveButton"/>
+ <menu_item_check label="視界ボタン" name="ShowCameraButton"/>
+ <menu_item_check label="スナップショットボタン" name="ShowSnapshotButton"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_favorites.xml b/indra/newview/skins/default/xui/ja/menu_favorites.xml
new file mode 100644
index 0000000000..4708b1446c
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_favorites.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Popup">
+ <menu_item_call label="テレãƒãƒ¼ãƒˆ" name="Teleport To Landmark"/>
+ <menu_item_call label="ランドマークを表示・編集" name="Landmark Open"/>
+ <menu_item_call label="SLurl をコピー" name="Copy slurl"/>
+ <menu_item_call label="地図ã«è¡¨ç¤º" name="Show On Map"/>
+ <menu_item_call label="コピー" name="Landmark Copy"/>
+ <menu_item_call label="貼り付ã‘" name="Landmark Paste"/>
+ <menu_item_call label="削除" name="Delete"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_gesture_gear.xml b/indra/newview/skins/default/xui/ja/menu_gesture_gear.xml
new file mode 100644
index 0000000000..abf490a247
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_gesture_gear.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_gesture_gear">
+ <menu_item_call label="ãŠæ°—ã«å…¥ã‚Šã‹ã‚‰ã®è¿½åŠ ãƒ»å‰Šé™¤" name="activate"/>
+ <menu_item_call label="コピー" name="copy_gesture"/>
+ <menu_item_call label="貼り付ã‘" name="paste"/>
+ <menu_item_call label="UUID をコピー" name="copy_uuid"/>
+ <menu_item_call label="ç¾åœ¨ã®ã‚¢ã‚¦ãƒˆãƒ•ã‚£ãƒƒãƒˆã«ä¿å­˜" name="save_to_outfit"/>
+ <menu_item_call label="編集" name="edit_gesture"/>
+ <menu_item_call label="調ã¹ã‚‹" name="inspect"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_group_plus.xml b/indra/newview/skins/default/xui/ja/menu_group_plus.xml
new file mode 100644
index 0000000000..3787f7d645
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_group_plus.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_call label="グループã«å‚加..." name="item_join"/>
+ <menu_item_call label="æ–°ã—ã„グループ..." name="item_new"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_hide_navbar.xml b/indra/newview/skins/default/xui/ja/menu_hide_navbar.xml
new file mode 100644
index 0000000000..09e70b0d1f
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_hide_navbar.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="hide_navbar_menu">
+ <menu_item_check label="ナビゲーションãƒãƒ¼ã‚’表示" name="ShowNavbarNavigationPanel"/>
+ <menu_item_check label="ãŠæ°—ã«å…¥ã‚Šãƒãƒ¼ã‚’表示" name="ShowNavbarFavoritesPanel"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_imchiclet_group.xml b/indra/newview/skins/default/xui/ja/menu_imchiclet_group.xml
new file mode 100644
index 0000000000..5bcb96f083
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_imchiclet_group.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="IMChiclet Group Menu">
+ <menu_item_call label="グループ情報" name="Show Profile"/>
+ <menu_item_call label="セッションを表示" name="Chat"/>
+ <menu_item_call label="セッション終了" name="End Session"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_imchiclet_p2p.xml b/indra/newview/skins/default/xui/ja/menu_imchiclet_p2p.xml
new file mode 100644
index 0000000000..0887001992
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_imchiclet_p2p.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="IMChiclet P2P Menu">
+ <menu_item_call label="プロフィールを表示" name="Show Profile"/>
+ <menu_item_call label="フレンド登録" name="Add Friend"/>
+ <menu_item_call label="セッションを表示" name="Send IM"/>
+ <menu_item_call label="セッション終了" name="End Session"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_inspect_avatar_gear.xml b/indra/newview/skins/default/xui/ja/menu_inspect_avatar_gear.xml
new file mode 100644
index 0000000000..64e1505440
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_inspect_avatar_gear.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu name="Gear Menu">
+ <menu_item_call label="プロフィールã®è¡¨ç¤º" name="view_profile"/>
+ <menu_item_call label="フレンド登録" name="add_friend"/>
+ <menu_item_call label="IM" name="im"/>
+ <menu_item_call label="コール" name="call"/>
+ <menu_item_call label="テレãƒãƒ¼ãƒˆ" name="teleport"/>
+ <menu_item_call label="グループã«æ‹›å¾…" name="invite_to_group"/>
+ <menu_item_call label="ブロック" name="block"/>
+ <menu_item_call label="報告" name="report"/>
+ <menu_item_call label="フリーズ" name="freeze"/>
+ <menu_item_call label="追放" name="eject"/>
+ <menu_item_call label="デãƒãƒƒã‚°" name="debug"/>
+ <menu_item_call label="地図ã§æŽ¢ã™" name="find_on_map"/>
+ <menu_item_call label="ズームイン" name="zoom_in"/>
+ <menu_item_call label="支払ã†" name="pay"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/ja/menu_inspect_object_gear.xml
new file mode 100644
index 0000000000..506614316e
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_inspect_object_gear.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu name="Gear Menu">
+ <menu_item_call label="触る" name="touch"/>
+ <menu_item_call label="座る" name="sit"/>
+ <menu_item_call label="支払ã†" name="pay"/>
+ <menu_item_call label="è²·ã†" name="buy"/>
+ <menu_item_call label="å–ã‚‹" name="take"/>
+ <menu_item_call label="コピーをå–ã‚‹" name="take_copy"/>
+ <menu_item_call label="é–‹ã" name="open"/>
+ <menu_item_call label="編集" name="edit"/>
+ <menu_item_call label="装ç€" name="wear"/>
+ <menu_item_call label="報告" name="report"/>
+ <menu_item_call label="ブロック" name="block"/>
+ <menu_item_call label="ズームイン" name="zoom_in"/>
+ <menu_item_call label="削除" name="remove"/>
+ <menu_item_call label="詳細" name="more_info"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_inspect_self_gear.xml b/indra/newview/skins/default/xui/ja/menu_inspect_self_gear.xml
new file mode 100644
index 0000000000..76c01d6109
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_inspect_self_gear.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu name="Gear Menu">
+ <menu_item_call label="ç«‹ã¡ä¸ŠãŒã‚‹" name="stand_up"/>
+ <menu_item_call label="マイ 容姿" name="my_appearance"/>
+ <menu_item_call label="プロフィール" name="my_profile"/>
+ <menu_item_call label="フレンド" name="my_friends"/>
+ <menu_item_call label="グループ" name="my_groups"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_inventory.xml b/indra/newview/skins/default/xui/ja/menu_inventory.xml
index 37c52f173c..623a0cdb06 100644
--- a/indra/newview/skins/default/xui/ja/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/ja/menu_inventory.xml
@@ -12,7 +12,7 @@
<menu_item_call label="æ–°ã—ã„スクリプト" name="New Script"/>
<menu_item_call label="æ–°ã—ã„ノート" name="New Note"/>
<menu_item_call label="æ–°ã—ã„ジェスãƒãƒ£ãƒ¼" name="New Gesture"/>
- <menu name="New Clothes">
+ <menu label="æ–°ã—ã„衣類" name="New Clothes">
<menu_item_call label="æ–°ã—ã„シャツ" name="New Shirt"/>
<menu_item_call label="æ–°ã—ã„ズボン" name="New Pants"/>
<menu_item_call label="æ–°ã—ã„é´" name="New Shoes"/>
@@ -22,31 +22,47 @@
<menu_item_call label="æ–°ã—ã„手袋" name="New Gloves"/>
<menu_item_call label="æ–°ã—ã„下ç€" name="New Undershirt"/>
<menu_item_call label="æ–°ã—ã„パンツ" name="New Underpants"/>
+ <menu_item_call label="æ–°ã—ã„アルファマスク" name="New Alpha Mask"/>
+ <menu_item_call label="æ–°ã—ã„タトゥ" name="New Tattoo"/>
</menu>
- <menu name="New Body Parts">
+ <menu label="æ–°ã—ã„身体部ä½" name="New Body Parts">
<menu_item_call label="æ–°ã—ã„シェイプ(体型)" name="New Shape"/>
<menu_item_call label="æ–°ã—ã„スキン" name="New Skin"/>
<menu_item_call label="æ–°ã—ã„髪" name="New Hair"/>
<menu_item_call label="æ–°ã—ã„眼" name="New Eyes"/>
</menu>
+ <menu label="種類を変更" name="Change Type">
+ <menu_item_call label="デフォルト" name="Default"/>
+ <menu_item_call label="手袋" name="Gloves"/>
+ <menu_item_call label="ジャケット" name="Jacket"/>
+ <menu_item_call label="パンツ" name="Pants"/>
+ <menu_item_call label="シェイプ" name="Shape"/>
+ <menu_item_call label="é´" name="Shoes"/>
+ <menu_item_call label="シャツ" name="Shirt"/>
+ <menu_item_call label="スカート" name="Skirt"/>
+ <menu_item_call label="下ç€ãƒ‘ンツ" name="Underpants"/>
+ <menu_item_call label="下ç€ã‚·ãƒ£ãƒ„" name="Undershirt"/>
+ </menu>
<menu_item_call label="テレãƒãƒ¼ãƒˆ" name="Landmark Open"/>
<menu_item_call label="é–‹ã" name="Animation Open"/>
<menu_item_call label="é–‹ã" name="Sound Open"/>
<menu_item_call label="アイテムを除外" name="Purge Item"/>
<menu_item_call label="アイテムを復元" name="Restore Item"/>
+ <menu_item_call label="オリジナルを探ã™" name="Find Original"/>
<menu_item_call label="é–‹ã" name="Open"/>
<menu_item_call label="プロパティ" name="Properties"/>
<menu_item_call label="åå‰ã®å¤‰æ›´" name="Rename"/>
<menu_item_call label="UUIDをコピー" name="Copy Asset UUID"/>
<menu_item_call label="コピー" name="Copy"/>
<menu_item_call label="貼り付ã‘" name="Paste"/>
+ <menu_item_call label="リンクã®è²¼ã‚Šä»˜ã‘" name="Paste As Link"/>
<menu_item_call label="削除" name="Delete"/>
- <menu_item_call label="アイテムをå–り外ã™" name="Take Off Items"/>
+ <menu_item_call label="アウトフィットã‹ã‚‰å–り除ã" name="Remove From Outfit"/>
<menu_item_call label="æœè£…ã«è¿½åŠ " name="Add To Outfit"/>
<menu_item_call label="æœè£…ã‚’ç½®æ›" name="Replace Outfit"/>
<menu_item_call label="会議ãƒãƒ£ãƒƒãƒˆé–‹å§‹" name="Conference Chat Folder"/>
<menu_item_call label="å†ç”Ÿ" name="Sound Play"/>
- <menu_item_call label="ランドマーク情報" name="Teleport To Landmark"/>
+ <menu_item_call label="ランドマークã®æƒ…å ±" name="About Landmark"/>
<menu_item_call label="世界ã§å†ç”Ÿ" name="Animation Play"/>
<menu_item_call label="ローカルã«å†ç”Ÿ" name="Animation Audition"/>
<menu_item_call label="インスタント・メッセージをé€ä¿¡" name="Send Instant Message"/>
@@ -54,8 +70,8 @@
<menu_item_call label="会議ãƒãƒ£ãƒƒãƒˆé–‹å§‹" name="Conference Chat"/>
<menu_item_call label="アクティブ" name="Activate"/>
<menu_item_call label="éžã‚¢ã‚¯ãƒ†ã‚£ãƒ–" name="Deactivate"/>
+ <menu_item_call label="別åã§ä¿å­˜" name="Save As"/>
<menu_item_call label="自分ã‹ã‚‰å–り外ã™" name="Detach From Yourself"/>
- <menu_item_call label="å‰å›žã‚ã£ãŸä½ç½®ã«æˆ»ã™" name="Restore to Last Position"/>
<menu_item_call label="装ç€" name="Object Wear"/>
<menu label="装ç€å…ˆ" name="Attach To"/>
<menu label="HUD装ç€å…ˆ" name="Attach To HUD"/>
diff --git a/indra/newview/skins/default/xui/ja/menu_inventory_add.xml b/indra/newview/skins/default/xui/ja/menu_inventory_add.xml
new file mode 100644
index 0000000000..8b18f6bfe8
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_inventory_add.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_inventory_add">
+ <menu label="アップロード" name="upload">
+ <menu_item_call label="ç”»åƒ ï¼ˆL$ [COST] )..." name="Upload Image"/>
+ <menu_item_call label="サウンド (L$[COST] )..." name="Upload Sound"/>
+ <menu_item_call label="アニメーション (L$ [COST] )..." name="Upload Animation"/>
+ <menu_item_call label="一括 (ファイルã«ã¤ã L$[COST] )..." name="Bulk Upload"/>
+ </menu>
+ <menu_item_call label="æ–°è¦ãƒ•ã‚©ãƒ«ãƒ€" name="New Folder"/>
+ <menu_item_call label="æ–°è¦ã‚¹ã‚¯ãƒªãƒ—ト" name="New Script"/>
+ <menu_item_call label="æ–°è¦ãƒŽãƒ¼ãƒˆ" name="New Note"/>
+ <menu_item_call label="æ–°è¦ã‚¸ã‚§ã‚¹ãƒãƒ£ãƒ¼" name="New Gesture"/>
+ <menu label="æ–°ã—ã„衣類" name="New Clothes">
+ <menu_item_call label="æ–°ã—ã„シャツ" name="New Shirt"/>
+ <menu_item_call label="æ–°ã—ã„パンツ" name="New Pants"/>
+ <menu_item_call label="æ–°ã—ã„é´" name="New Shoes"/>
+ <menu_item_call label="æ–°ã—ã„é´ä¸‹" name="New Socks"/>
+ <menu_item_call label="æ–°ã—ã„ジャケット" name="New Jacket"/>
+ <menu_item_call label="æ–°ã—ã„スカート" name="New Skirt"/>
+ <menu_item_call label="æ–°ã—ã„手袋" name="New Gloves"/>
+ <menu_item_call label="æ–°ã—ã„下ç€ï¼ˆä¸Šï¼‰" name="New Undershirt"/>
+ <menu_item_call label="æ–°ã—ã„下ç€ï¼ˆä¸‹ï¼‰" name="New Underpants"/>
+ <menu_item_call label="æ–°ã—ã„アルファ" name="New Alpha"/>
+ <menu_item_call label="æ–°ã—ã„タトゥー" name="New Tattoo"/>
+ </menu>
+ <menu label="æ–°ã—ã„身体部ä½" name="New Body Parts">
+ <menu_item_call label="æ–°ã—ã„シェイプ(体型)" name="New Shape"/>
+ <menu_item_call label="æ–°ã—ã„スキン" name="New Skin"/>
+ <menu_item_call label="æ–°ã—ã„髪" name="New Hair"/>
+ <menu_item_call label="æ–°ã—ã„ç›®" name="New Eyes"/>
+ </menu>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_inventory_gear_default.xml b/indra/newview/skins/default/xui/ja/menu_inventory_gear_default.xml
new file mode 100644
index 0000000000..2bac5ebaa6
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_inventory_gear_default.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_gear_default">
+ <menu_item_call label="æ–°ã—ã„æŒã¡ç‰©ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦" name="new_window"/>
+ <menu_item_call label="åå‰ã§ä¸¦ã¹æ›¿ãˆ" name="sort_by_name"/>
+ <menu_item_call label="æ–°ã—ã„é †ã«ä¸¦ã¹æ›¿ãˆ" name="sort_by_recent"/>
+ <menu_item_call label="フィルターを表示" name="show_filters"/>
+ <menu_item_call label="フィルターをリセット" name="reset_filters"/>
+ <menu_item_call label="ã™ã¹ã¦ã®ãƒ•ã‚©ãƒ«ãƒ€ã‚’é–‰ã˜ã‚‹" name="close_folders"/>
+ <menu_item_call label="ã”ã¿ç®±ã‚’空ã«ã™ã‚‹" name="empty_trash"/>
+ <menu_item_call label="紛失物を空ã«ã™ã‚‹" name="empty_lostnfound"/>
+ <menu_item_call label="別åã§ãƒ†ã‚¯ã‚¹ãƒãƒ£ã‚’ä¿å­˜" name="Save Texture As"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_landmark.xml b/indra/newview/skins/default/xui/ja/menu_landmark.xml
new file mode 100644
index 0000000000..c134422955
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_landmark.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="landmark_overflow_menu">
+ <menu_item_call label="SLurl をコピー" name="copy"/>
+ <menu_item_call label="削除" name="delete"/>
+ <menu_item_call label="ピックを作æˆ" name="pick"/>
+ <menu_item_call label="ãŠæ°—ã«å…¥ã‚Šãƒãƒ¼ã«è¿½åŠ " name="add_to_favbar"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_login.xml b/indra/newview/skins/default/xui/ja/menu_login.xml
index 906822e54b..5db56ae76b 100644
--- a/indra/newview/skins/default/xui/ja/menu_login.xml
+++ b/indra/newview/skins/default/xui/ja/menu_login.xml
@@ -1,13 +1,34 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<menu_bar name="Login Menu">
- <menu label="ファイル" name="File">
- <menu_item_call label="終了" name="Quit" />
- </menu>
- <menu label="編集" name="Edit">
- <menu_item_call label="環境設定..." name="Preferences..." />
+ <menu label="ミー" name="File">
+ <menu_item_call label="環境設定" name="Preferences..."/>
+ <menu_item_call label="[APP_NAME] を終了" name="Quit"/>
</menu>
<menu label="ヘルプ" name="Help">
- <menu_item_call label="Second Lifeヘルプ" name="Second Life Help" />
- <menu_item_call label="Second Lifeã«ã¤ã„ã¦..." name="About Second Life..." />
+ <menu_item_call label="[SECOND_LIFE] ヘルプ" name="Second Life Help"/>
+ <menu_item_call label="[APP_NAME] ã«ã¤ã„ã¦" name="About Second Life"/>
+ </menu>
+ <menu label="デãƒãƒƒã‚°" name="Debug">
+ <menu label="編集" name="Edit">
+ <menu_item_call label="å…ƒã«æˆ»ã™" name="Undo"/>
+ <menu_item_call label="ã‚„ã‚Šç›´ã—" name="Redo"/>
+ <menu_item_call label="切りå–ã‚Š" name="Cut"/>
+ <menu_item_call label="コピー" name="Copy"/>
+ <menu_item_call label="貼り付ã‘" name="Paste"/>
+ <menu_item_call label="削除" name="Delete"/>
+ <menu_item_call label="複製" name="Duplicate"/>
+ <menu_item_call label="ã™ã¹ã¦é¸æŠž" name="Select All"/>
+ <menu_item_call label="é¸æŠžè§£é™¤" name="Deselect"/>
+ </menu>
+ <menu_item_call label="デãƒãƒƒã‚°è¨­å®šã‚’表示" name="Debug Settings"/>
+ <menu_item_call label="UI/色ã®è¨­å®š" name="UI/Color Settings"/>
+ <menu_item_call label="XUI プレビューツール" name="UI Preview Tool"/>
+ <menu_item_call label="サイドトレイを表示" name="Show Side Tray"/>
+ <menu_item_call label="ウィジェットテスト" name="Widget Test"/>
+ <menu_item_call label="インスペクターテスト" name="Inspectors Test"/>
+ <menu_item_check label="Reg In Client Test (restart)" name="Reg In Client Test (restart)"/>
+ <menu_item_call label="利用è¦ç´„を表示" name="TOS"/>
+ <menu_item_call label="クリティカルメッセージを表示" name="Critical"/>
+ <menu_item_call label="Web ブラウザã®ãƒ†ã‚¹ãƒˆ" name="Web Browser Test"/>
</menu>
</menu_bar>
diff --git a/indra/newview/skins/default/xui/ja/menu_mini_map.xml b/indra/newview/skins/default/xui/ja/menu_mini_map.xml
index c8828a50be..ec49c3a98d 100644
--- a/indra/newview/skins/default/xui/ja/menu_mini_map.xml
+++ b/indra/newview/skins/default/xui/ja/menu_mini_map.xml
@@ -3,6 +3,7 @@
<menu_item_call label="ズーム(近)" name="Zoom Close"/>
<menu_item_call label="ズーム(中)" name="Zoom Medium"/>
<menu_item_call label="ズーム(é ï¼‰" name="Zoom Far"/>
+ <menu_item_check label="地図を回転" name="Rotate Map"/>
<menu_item_call label="追跡をやã‚ã‚‹" name="Stop Tracking"/>
- <menu_item_call label="プロフィール..." name="Profile"/>
+ <menu_item_call label="世界地図" name="World Map"/>
</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_navbar.xml b/indra/newview/skins/default/xui/ja/menu_navbar.xml
new file mode 100644
index 0000000000..9ae2e58198
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_navbar.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Navbar Menu">
+ <menu_item_check label="座標を表示" name="Show Coordinates"/>
+ <menu_item_check label="区画ã®ãƒ—ロパティを表示" name="Show Parcel Properties"/>
+ <menu_item_call label="ランドマーク" name="Landmark"/>
+ <menu_item_call label="切りå–ã‚Š" name="Cut"/>
+ <menu_item_call label="コピー" name="Copy"/>
+ <menu_item_call label="貼り付ã‘" name="Paste"/>
+ <menu_item_call label="削除" name="Delete"/>
+ <menu_item_call label="ã™ã¹ã¦é¸æŠž" name="Select All"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_nearby_chat.xml b/indra/newview/skins/default/xui/ja/menu_nearby_chat.xml
new file mode 100644
index 0000000000..c2e4a27686
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_nearby_chat.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="NearBy Chat Menu">
+ <menu_item_call label="è¿‘ãã®äººã‚’表示ã™ã‚‹..." name="nearby_people"/>
+ <menu_item_check label="ブロックã•ã‚ŒãŸæ–‡å­—を表示" name="muted_text"/>
+ <menu_item_check label="ãƒãƒ‡ã‚£ã‚¢ã‚¤ã‚³ãƒ³ã‚’表示" name="show_buddy_icons"/>
+ <menu_item_check label="åå‰ã‚’表示" name="show_names"/>
+ <menu_item_check label="アイコンã¨åå‰ã‚’表示" name="show_icons_and_names"/>
+ <menu_item_call label="文字ã®å¤§ãã•" name="font_size"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_object_icon.xml b/indra/newview/skins/default/xui/ja/menu_object_icon.xml
new file mode 100644
index 0000000000..8c4f328661
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_object_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Object Icon Menu">
+ <menu_item_call label="オブジェクトã®ãƒ—ロフィール..." name="Object Profile"/>
+ <menu_item_call label="ブロック..." name="Block"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_participant_list.xml b/indra/newview/skins/default/xui/ja/menu_participant_list.xml
new file mode 100644
index 0000000000..0bc51ecde1
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_participant_list.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Participant List Context Menu">
+ <menu_item_check label="文字をミュート" name="MuteText"/>
+ <menu_item_check label="文字ãƒãƒ£ãƒƒãƒˆã‚’許å¯" name="AllowTextChat"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_people_friends_view_sort.xml b/indra/newview/skins/default/xui/ja/menu_people_friends_view_sort.xml
new file mode 100644
index 0000000000..e4ccbf43ad
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_people_friends_view_sort.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="åå‰ã§ä¸¦ã¹æ›¿ãˆ" name="sort_name"/>
+ <menu_item_check label="オンライン状æ³ã§ä¸¦ã¹æ›¿ãˆ" name="sort_status"/>
+ <menu_item_check label="人ã®ã‚¢ã‚¤ã‚³ãƒ³è¡¨ç¤º" name="view_icons"/>
+ <menu_item_call label="ブロックã•ã‚ŒãŸä½äººã¨ã‚ªãƒ–ジェクトを表示" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_people_groups_view_sort.xml b/indra/newview/skins/default/xui/ja/menu_people_groups_view_sort.xml
new file mode 100644
index 0000000000..bfc7d15017
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_people_groups_view_sort.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="グループアイコンを表示" name="Display Group Icons"/>
+ <menu_item_call label="é¸æŠžã—ãŸã‚°ãƒ«ãƒ¼ãƒ—ã‹ã‚‰è„±é€€" name="Leave Selected Group"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_people_nearby.xml b/indra/newview/skins/default/xui/ja/menu_people_nearby.xml
new file mode 100644
index 0000000000..a577523754
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_people_nearby.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Avatar Context Menu">
+ <menu_item_call label="プロフィールã®è¡¨ç¤º" name="View Profile"/>
+ <menu_item_call label="フレンド登録" name="Add Friend"/>
+ <menu_item_call label="IM" name="IM"/>
+ <menu_item_call label="コール" name="Call"/>
+ <menu_item_call label="共有" name="Share"/>
+ <menu_item_call label="支払ã†" name="Pay"/>
+ <menu_item_check label="ブロック・ブロック解除" name="Block/Unblock"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_people_nearby_multiselect.xml b/indra/newview/skins/default/xui/ja/menu_people_nearby_multiselect.xml
new file mode 100644
index 0000000000..bcd562e3ed
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_people_nearby_multiselect.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Multi-Selected People Context Menu">
+ <menu_item_call label="フレンド登録" name="Add Friends"/>
+ <menu_item_call label="IM" name="IM"/>
+ <menu_item_call label="コール" name="Call"/>
+ <menu_item_call label="共有" name="Share"/>
+ <menu_item_call label="支払ã†" name="Pay"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_people_nearby_view_sort.xml b/indra/newview/skins/default/xui/ja/menu_people_nearby_view_sort.xml
new file mode 100644
index 0000000000..a31480158a
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_people_nearby_view_sort.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="最近ã®ç™ºè¨€è€…ã§ä¸¦ã¹æ›¿ãˆ" name="sort_by_recent_speakers"/>
+ <menu_item_check label="åå‰ã§ä¸¦ã¹æ›¿ãˆ" name="sort_name"/>
+ <menu_item_check label="è·é›¢ã§ä¸¦ã¹æ›¿ãˆ" name="sort_distance"/>
+ <menu_item_check label="人ã®ã‚¢ã‚¤ã‚³ãƒ³è¡¨ç¤º" name="view_icons"/>
+ <menu_item_call label="ブロックã•ã‚ŒãŸä½äººã¨ã‚ªãƒ–ジェクトを表示" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_people_recent_view_sort.xml b/indra/newview/skins/default/xui/ja/menu_people_recent_view_sort.xml
new file mode 100644
index 0000000000..b4f177a068
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_people_recent_view_sort.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="æ–°ã—ã„é †ã«ä¸¦ã¹æ›¿ãˆ" name="sort_most"/>
+ <menu_item_check label="åå‰ã§ä¸¦ã¹æ›¿ãˆ" name="sort_name"/>
+ <menu_item_check label="人ã®ã‚¢ã‚¤ã‚³ãƒ³è¡¨ç¤º" name="view_icons"/>
+ <menu_item_call label="ブロックã•ã‚ŒãŸä½äººã¨ã‚ªãƒ–ジェクトを表示" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_picks.xml b/indra/newview/skins/default/xui/ja/menu_picks.xml
new file mode 100644
index 0000000000..011d3d2526
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_picks.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Picks">
+ <menu_item_call label="情報" name="pick_info"/>
+ <menu_item_call label="編集" name="pick_edit"/>
+ <menu_item_call label="テレãƒãƒ¼ãƒˆ" name="pick_teleport"/>
+ <menu_item_call label="地図" name="pick_map"/>
+ <menu_item_call label="削除" name="pick_delete"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_picks_plus.xml b/indra/newview/skins/default/xui/ja/menu_picks_plus.xml
new file mode 100644
index 0000000000..84bf90fea0
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_picks_plus.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="picks_plus_menu">
+ <menu_item_call label="æ–°ã—ã„ピック" name="create_pick"/>
+ <menu_item_call label="æ–°ã—ã„クラシファイド広告" name="create_classified"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_place.xml b/indra/newview/skins/default/xui/ja/menu_place.xml
new file mode 100644
index 0000000000..a9f05e126d
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_place.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="place_overflow_menu">
+ <menu_item_call label="ランドマークを作æˆ" name="landmark"/>
+ <menu_item_call label="ピックを作æˆ" name="pick"/>
+ <menu_item_call label="入場許å¯ã‚’購入" name="pass"/>
+ <menu_item_call label="編集" name="edit"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_place_add_button.xml b/indra/newview/skins/default/xui/ja/menu_place_add_button.xml
new file mode 100644
index 0000000000..d5ce88b055
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_place_add_button.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_folder_gear">
+ <menu_item_call label="フォルダを追加" name="add_folder"/>
+ <menu_item_call label="ランドマークを追加" name="add_landmark"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_places_gear_folder.xml b/indra/newview/skins/default/xui/ja/menu_places_gear_folder.xml
new file mode 100644
index 0000000000..6f91a3ebf9
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_places_gear_folder.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_folder_gear">
+ <menu_item_call label="ランドマークを追加" name="add_landmark"/>
+ <menu_item_call label="フォルダを追加" name="add_folder"/>
+ <menu_item_call label="切りå–ã‚Š" name="cut"/>
+ <menu_item_call label="コピー" name="copy_folder"/>
+ <menu_item_call label="貼り付ã‘" name="paste"/>
+ <menu_item_call label="åå‰ã®å¤‰æ›´" name="rename"/>
+ <menu_item_call label="削除" name="delete"/>
+ <menu_item_call label="拡大" name="expand"/>
+ <menu_item_call label="戻ã™" name="collapse"/>
+ <menu_item_call label="フォルダをã™ã¹ã¦é–‹ã" name="expand_all"/>
+ <menu_item_call label="フォルダをã™ã¹ã¦é–‰ã˜ã‚‹" name="collapse_all"/>
+ <menu_item_check label="日付ã§ä¸¦ã¹æ›¿ãˆ" name="sort_by_date"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_places_gear_landmark.xml b/indra/newview/skins/default/xui/ja/menu_places_gear_landmark.xml
new file mode 100644
index 0000000000..5a135e5f56
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_places_gear_landmark.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_ladmark_gear">
+ <menu_item_call label="テレãƒãƒ¼ãƒˆ" name="teleport"/>
+ <menu_item_call label="ã‚‚ã£ã¨è©³ã—ã" name="more_info"/>
+ <menu_item_call label="地図ã«è¡¨ç¤º" name="show_on_map"/>
+ <menu_item_call label="ランドマークを追加" name="add_landmark"/>
+ <menu_item_call label="フォルダを追加" name="add_folder"/>
+ <menu_item_call label="切りå–ã‚Š" name="cut"/>
+ <menu_item_call label="ランドマークをコピー" name="copy_landmark"/>
+ <menu_item_call label="SLurl をコピー" name="copy_slurl"/>
+ <menu_item_call label="貼り付ã‘" name="paste"/>
+ <menu_item_call label="åå‰ã®å¤‰æ›´" name="rename"/>
+ <menu_item_call label="削除" name="delete"/>
+ <menu_item_call label="フォルダをã™ã¹ã¦é–‹ã" name="expand_all"/>
+ <menu_item_call label="フォルダをã™ã¹ã¦é–‰ã˜ã‚‹" name="collapse_all"/>
+ <menu_item_check label="日付ã§ä¸¦ã¹æ›¿ãˆ" name="sort_by_date"/>
+ <menu_item_call label="ピックを作æˆ" name="create_pick"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_profile_overflow.xml b/indra/newview/skins/default/xui/ja/menu_profile_overflow.xml
new file mode 100644
index 0000000000..a34086bdbf
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_profile_overflow.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="profile_overflow_menu">
+ <menu_item_call label="支払ã†" name="pay"/>
+ <menu_item_call label="共有" name="share"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_slurl.xml b/indra/newview/skins/default/xui/ja/menu_slurl.xml
index 6d15563382..2e06c53494 100644
--- a/indra/newview/skins/default/xui/ja/menu_slurl.xml
+++ b/indra/newview/skins/default/xui/ja/menu_slurl.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<menu name="Popup">
- <menu_item_call label="URLã«ã¤ã„ã¦" name="about_url" />
- <menu_item_call label="URLã¸ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã™ã‚‹" name="teleport_to_url" />
- <menu_item_call label="地図上ã«è¡¨ç¤º" name="show_on_map" />
+ <menu_item_call label="URLã«ã¤ã„ã¦" name="about_url"/>
+ <menu_item_call label="URLã¸ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã™ã‚‹" name="teleport_to_url"/>
+ <menu_item_call label="地図" name="show_on_map"/>
</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_teleport_history_gear.xml b/indra/newview/skins/default/xui/ja/menu_teleport_history_gear.xml
new file mode 100644
index 0000000000..901eab9166
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_teleport_history_gear.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Teleport History Gear Context Menu">
+ <menu_item_call label="フォルダをã™ã¹ã¦é–‹ã" name="Expand all folders"/>
+ <menu_item_call label="フォルダをã™ã¹ã¦é–‰ã˜ã‚‹" name="Collapse all folders"/>
+ <menu_item_call label="テレãƒãƒ¼ãƒˆã®å±¥æ­´ã‚’クリア" name="Clear Teleport History"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/ja/menu_teleport_history_item.xml
new file mode 100644
index 0000000000..66bc32214f
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_teleport_history_item.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Teleport History Item Context Menu">
+ <menu_item_call label="テレãƒãƒ¼ãƒˆ" name="Teleport"/>
+ <menu_item_call label="ã‚‚ã£ã¨è©³ã—ã" name="More Information"/>
+ <menu_item_call label="クリップボードã«ã‚³ãƒ”ー" name="CopyToClipboard"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_teleport_history_tab.xml b/indra/newview/skins/default/xui/ja/menu_teleport_history_tab.xml
new file mode 100644
index 0000000000..4dd44d2ec8
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_teleport_history_tab.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Teleport History Item Context Menu">
+ <menu_item_call label="é–‹ã" name="TabOpen"/>
+ <menu_item_call label="é–‰ã˜ã‚‹" name="TabClose"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_text_editor.xml b/indra/newview/skins/default/xui/ja/menu_text_editor.xml
new file mode 100644
index 0000000000..fcb1038a6a
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_text_editor.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Text editor context menu">
+ <menu_item_call label="切りå–ã‚Š" name="Cut"/>
+ <menu_item_call label="コピー" name="Copy"/>
+ <menu_item_call label="貼り付ã‘" name="Paste"/>
+ <menu_item_call label="削除" name="Delete"/>
+ <menu_item_call label="ã™ã¹ã¦é¸æŠž" name="Select All"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_url_agent.xml b/indra/newview/skins/default/xui/ja/menu_url_agent.xml
new file mode 100644
index 0000000000..92d118a5ae
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_url_agent.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="ä½äººã®ãƒ—ロフィールを表示" name="show_agent"/>
+ <menu_item_call label="åå‰ã‚’クリップボードã«ã‚³ãƒ”ー" name="url_copy_label"/>
+ <menu_item_call label="SLurl をクリップボードã«ã‚³ãƒ”ー" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_url_group.xml b/indra/newview/skins/default/xui/ja/menu_url_group.xml
new file mode 100644
index 0000000000..1dd3d79438
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_url_group.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="グループ情報を表示" name="show_group"/>
+ <menu_item_call label="グループをクリップボードã«ã‚³ãƒ”ー" name="url_copy_label"/>
+ <menu_item_call label="SLurl をクリップボードã«ã‚³ãƒ”ー" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_url_http.xml b/indra/newview/skins/default/xui/ja/menu_url_http.xml
new file mode 100644
index 0000000000..c2f4f24db6
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_url_http.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Web ページを開ã" name="url_open"/>
+ <menu_item_call label="インターãƒãƒƒãƒˆãƒ–ラウザã§é–‹ã" name="url_open_internal"/>
+ <menu_item_call label="外部ブラウザã§é–‹ã" name="url_open_external"/>
+ <menu_item_call label="URLをクリップボードã«ã‚³ãƒ”ー" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_url_inventory.xml b/indra/newview/skins/default/xui/ja/menu_url_inventory.xml
new file mode 100644
index 0000000000..7af2f9e2cd
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_url_inventory.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="æŒã¡ç‰©ã‚¢ã‚¤ãƒ†ãƒ ã‚’表示" name="show_item"/>
+ <menu_item_call label="åå‰ã‚’クリップボードã«ã‚³ãƒ”ー" name="url_copy_label"/>
+ <menu_item_call label="SLurl をクリップボードã«ã‚³ãƒ”ー" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_url_map.xml b/indra/newview/skins/default/xui/ja/menu_url_map.xml
new file mode 100644
index 0000000000..8d41e1a571
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_url_map.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="地図ã«è¡¨ç¤º" name="show_on_map"/>
+ <menu_item_call label="ç¾åœ°ã«ãƒ†ãƒ¬ãƒãƒ¼ãƒˆ" name="teleport_to_location"/>
+ <menu_item_call label="SLurl をクリップボードã«ã‚³ãƒ”ー" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_url_objectim.xml b/indra/newview/skins/default/xui/ja/menu_url_objectim.xml
new file mode 100644
index 0000000000..d6a048dcfc
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_url_objectim.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="オブジェクトã®æƒ…報を表示" name="show_object"/>
+ <menu_item_call label="地図ã«è¡¨ç¤º" name="show_on_map"/>
+ <menu_item_call label="オブジェクトã®å ´æ‰€ã«ãƒ†ãƒ¬ãƒãƒ¼ãƒˆ" name="teleport_to_object"/>
+ <menu_item_call label="オブジェクトåをクリップボードã«ã‚³ãƒ”ー" name="url_copy_label"/>
+ <menu_item_call label="SLurl をクリップボードã«ã‚³ãƒ”ー" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_url_parcel.xml b/indra/newview/skins/default/xui/ja/menu_url_parcel.xml
new file mode 100644
index 0000000000..8d264059d3
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_url_parcel.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="区画情報を表示" name="show_parcel"/>
+ <menu_item_call label="地図ã«è¡¨ç¤º" name="show_on_map"/>
+ <menu_item_call label="SLurl をクリップボードã«ã‚³ãƒ”ー" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_url_slapp.xml b/indra/newview/skins/default/xui/ja/menu_url_slapp.xml
new file mode 100644
index 0000000000..a516c5a075
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_url_slapp.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行" name="run_slapp"/>
+ <menu_item_call label="SLurl をクリップボードã«ã‚³ãƒ”ー" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_url_slurl.xml b/indra/newview/skins/default/xui/ja/menu_url_slurl.xml
new file mode 100644
index 0000000000..2c857ec915
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_url_slurl.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="場所ã®æƒ…報を表示" name="show_place"/>
+ <menu_item_call label="地図ã«è¡¨ç¤º" name="show_on_map"/>
+ <menu_item_call label="ç¾åœ°ã«ãƒ†ãƒ¬ãƒãƒ¼ãƒˆ" name="teleport_to_location"/>
+ <menu_item_call label="SLurl をクリップボードã«ã‚³ãƒ”ー" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_url_teleport.xml b/indra/newview/skins/default/xui/ja/menu_url_teleport.xml
new file mode 100644
index 0000000000..c3507a9a33
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_url_teleport.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="ã“ã®å ´æ‰€ã«ãƒ†ãƒ¬ãƒãƒ¼ãƒˆ" name="teleport"/>
+ <menu_item_call label="地図ã«è¡¨ç¤º" name="show_on_map"/>
+ <menu_item_call label="SLurl をクリップボードã«ã‚³ãƒ”ー" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_viewer.xml b/indra/newview/skins/default/xui/ja/menu_viewer.xml
index c994995ed2..fc0a5592dd 100644
--- a/indra/newview/skins/default/xui/ja/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/ja/menu_viewer.xml
@@ -1,217 +1,426 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<menu_bar name="Main Menu">
- <menu label="ファイル" name="File">
- <tearoff_menu label="~~~~~~~~~~~" name="~~~~~~~~~~~"/>
- <menu label="アップロード" name="upload">
- <menu_item_call label="ç”»åƒ ï¼ˆL$[COST])..." name="Upload Image"/>
- <menu_item_call label="サウンド (L$[COST])..." name="Upload Sound"/>
- <menu_item_call label="アニメーション (L$[COST])..." name="Upload Animation"/>
- <menu_item_call label="一括 (ファイルã«ã¤ãL$[COST])..." name="Bulk Upload"/>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_call label="デフォルト権é™ã®è¨­å®š..." name="perm prefs"/>
- </menu>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_call label="ウィンドウを閉ã˜ã‚‹" name="Close Window"/>
- <menu_item_call label="å…¨ã¦ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’é–‰ã˜ã‚‹" name="Close All Windows"/>
- <menu_item_separator label="-----------" name="separator2"/>
- <menu_item_call label="テクスãƒãƒ£ãƒ¼ã‚’別åã§ä¿å­˜..." name="Save Texture As..."/>
- <menu_item_separator label="-----------" name="separator3"/>
- <menu_item_call label="スナップショットを撮る" name="Take Snapshot"/>
- <menu_item_call label="スナップショットをディスクã«ä¿å­˜" name="Snapshot to Disk"/>
- <menu_item_separator label="-----------" name="separator4"/>
- <menu_item_call label="終了" name="Quit"/>
- </menu>
- <menu label="編集" name="Edit">
- <menu_item_call label="å…ƒã«æˆ»ã™" name="Undo"/>
- <menu_item_call label="ã‚„ã‚Šç›´ã—" name="Redo"/>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_call label="カット" name="Cut"/>
- <menu_item_call label="コピー" name="Copy"/>
- <menu_item_call label="貼り付ã‘" name="Paste"/>
- <menu_item_call label="削除" name="Delete"/>
- <menu_item_separator label="-----------" name="separator2"/>
- <menu_item_call label="検索..." name="Search..."/>
- <menu_item_separator label="-----------" name="separator3"/>
- <menu_item_call label="ã™ã¹ã¦ã‚’é¸æŠž" name="Select All"/>
- <menu_item_call label="é¸æŠžè§£é™¤" name="Deselect"/>
- <menu_item_separator label="-----------" name="separator4"/>
- <menu_item_call label="複製" name="Duplicate"/>
- <menu_item_separator label="-----------" name="separator5"/>
- <menu label="オブジェクトを装ç€" name="Attach Object"/>
- <menu label="オブジェクトをå–り外ã™" name="Detach Object"/>
- <menu label="æœã‚’脱ã" name="Take Off Clothing">
- <menu_item_call label="シャツ" name="Shirt"/>
- <menu_item_call label="ズボン" name="Pants"/>
- <menu_item_call label="é´" name="Shoes"/>
- <menu_item_call label="é´ä¸‹" name="Socks"/>
- <menu_item_call label="ジャケット" name="Jacket"/>
- <menu_item_call label="手袋" name="Gloves"/>
- <menu_item_call label="(下ç€ã®ï¼‰ã‚·ãƒ£ãƒ„" name="Menu Undershirt"/>
- <menu_item_call label="(下ç€ã®ï¼‰ãƒ‘ンツ" name="Menu Underpants"/>
- <menu_item_call label="スカート" name="Skirt"/>
- <menu_item_call label="ã™ã¹ã¦ã®æœ" name="All Clothes"/>
- </menu>
- <menu_item_separator label="-----------" name="separator6"/>
- <menu_item_call label="ジェスãƒãƒ£ãƒ¼â€¦" name="Gestures..."/>
- <menu_item_call label="プロフィール..." name="Profile..."/>
- <menu_item_call label="容姿..." name="Appearance..."/>
- <menu_item_separator label="-----------" name="separator7"/>
- <menu_item_check label="フレンド..." name="Friends..."/>
- <menu_item_call label="グループ..." name="Groups..."/>
- <menu_item_separator label="-----------" name="separator8"/>
- <menu_item_call label="環境設定..." name="Preferences..."/>
+ <menu label="ミー" name="Me">
+ <menu_item_call label="環境設定" name="Preferences"/>
+ <menu_item_call label="マイアカウント" name="Manage My Account">
+ <menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=ja"/>
+ </menu_item_call>
+ <menu_item_call label="L$ã®è³¼å…¥" name="Buy and Sell L$"/>
+ <menu_item_call label="マイ プロフィール" name="Profile"/>
+ <menu_item_call label="マイ 容姿" name="Appearance"/>
+ <menu_item_check label="マイ æŒã¡ç‰©" name="Inventory"/>
+ <menu_item_call label="サイドトレイã§æŒã¡ç‰©ã‚’表示" name="ShowSidetrayInventory"/>
+ <menu_item_call label="マイ ジェスãƒãƒ£ãƒ¼" name="Gestures"/>
+ <menu label="マイ ログイン状態" name="Status">
+ <menu_item_call label="一時退席中" name="Set Away"/>
+ <menu_item_call label="å–ã‚Šè¾¼ã¿ä¸­" name="Set Busy"/>
+ </menu>
+ <menu_item_call label="管ç†è€…権é™ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆ" name="Request Admin Options"/>
+ <menu_item_call label="管ç†è€…ステータス解除" name="Leave Admin Options"/>
+ <menu_item_call label="[APP_NAME] を終了" name="Quit"/>
</menu>
- <menu label="表示" name="View">
- <tearoff_menu label="~~~~~~~~~~~" name="~~~~~~~~~~~"/>
- <menu_item_call label="一人称視点(マウスルック)" name="Mouselook"/>
- <menu_item_check label="制作ツール" name="Build"/>
- <menu_item_check label="ジョイスティックæ“作" name="Joystick Flycam"/>
- <menu_item_call label="表示をリセット" name="Reset View"/>
- <menu_item_call label="最後ã®ãƒãƒ£ãƒƒãƒˆã‚’閲覧" name="Look at Last Chatter"/>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_check label="ツールãƒãƒ¼" name="Toolbar"/>
- <menu_item_check label="ローカル・ãƒãƒ£ãƒƒãƒˆ" name="Chat History"/>
- <menu_item_check label="コミュニケーション" name="Instant Message"/>
- <menu_item_check label="æŒã¡ç‰©" name="Inventory"/>
- <menu_item_check label="ボイスãƒãƒ£ãƒƒãƒˆãƒ»ãƒ¦ãƒ¼ã‚¶ãƒ¼ä¸€è¦§" name="Active Speakers"/>
- <menu_item_check label="無視リスト" name="Mute List"/>
- <menu_item_separator label="-----------" name="separator2"/>
- <menu_item_check label="カメラ・コントロール" name="Camera Controls"/>
- <menu_item_check label="移動コントロール" name="Movement Controls"/>
- <menu_item_check label="世界地図" name="World Map"/>
- <menu_item_check label="ミニマップ" name="Mini-Map"/>
- <menu_item_separator label="-----------" name="separator3"/>
- <menu_item_check label="地域ã®çµ±è¨ˆæƒ…å ±" name="Statistics Bar"/>
- <menu_item_check label="土地ã®å¢ƒç•Œç·š" name="Property Lines"/>
- <menu_item_check label="ç«‹å…¥ç¦æ­¢ãƒ©ã‚¤ãƒ³" name="Banlines"/>
- <menu_item_check label="土地オーナー" name="Land Owners"/>
- <menu_item_separator label="-----------" name="separator4"/>
- <menu label="ヒントã®ãƒãƒƒãƒ—アップ" name="Hover Tips">
- <menu_item_check label="ヒントを表示" name="Show Tips"/>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_check label="土地ã®ãƒ’ント" name="Land Tips"/>
- <menu_item_check label="ã™ã¹ã¦ã®ã‚ªãƒ–ジェクトã«é–¢ã™ã‚‹ãƒ’ント" name="Tips On All Objects"/>
- </menu>
- <menu_item_check label="é€æ˜Žã‚ªãƒ–ジェクトを強調表示" name="Highlight Transparent"/>
- <menu_item_check label="ビーコン(標識)" name="beacons"/>
- <menu_item_check label="パーティクルをéžè¡¨ç¤º" name="Hide Particles"/>
- <menu_item_check label="HUD装ç€ç‰©ã‚’表示" name="Show HUD Attachments"/>
- <menu_item_separator label="-----------" name="separator5"/>
- <menu_item_call label="カメラ・ズームイン" name="Zoom In"/>
- <menu_item_call label="カメラ・デフォルト" name="Zoom Default"/>
- <menu_item_call label="カメラ・ズームアウト" name="Zoom Out"/>
- <menu_item_separator label="-----------" name="separator6"/>
- <menu_item_call label="[全画é¢è¡¨ç¤º]" name="Toggle Fullscreen"/>
- <menu_item_call label="UIサイズを標準設定ã«æˆ»ã™" name="Set UI Size to Default"/>
+ <menu label="コミュニケーション" name="Communicate">
+ <menu_item_call label="フレンド" name="My Friends"/>
+ <menu_item_call label="所属グループ" name="My Groups"/>
+ <menu_item_check label="è¿‘ãã®ãƒãƒ£ãƒƒãƒˆ" name="Nearby Chat"/>
+ <menu_item_call label="è¿‘ãã«ã„る人" name="Active Speakers"/>
+ <menu_item_check label="è¿‘ãã®ãƒ¡ãƒ‡ã‚£ã‚¢" name="Nearby Media"/>
+ <menu_item_check label="(レガシー) コミュニケーション" name="Instant Message"/>
+ <menu_item_call label="(一時)メディアリモコン" name="Preferences"/>
</menu>
<menu label="世界" name="World">
- <menu_item_call label="ãƒãƒ£ãƒƒãƒˆ" name="Chat"/>
- <menu_item_check label="常ã«èµ°ã‚‹" name="Always Run"/>
- <menu_item_check label="飛行" name="Fly"/>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_call label="ã“ã®å ´æ‰€ã®ãƒ©ãƒ³ãƒ‰ãƒžãƒ¼ã‚¯ã‚’作æˆ" name="Create Landmark Here"/>
- <menu_item_call label="ホームをã“ã“ã«è¨­å®š" name="Set Home to Here"/>
- <menu_item_separator label="-----------" name="separator2"/>
- <menu_item_call label="ホームã«ãƒ†ãƒ¬ãƒãƒ¼ãƒˆ" name="Teleport Home"/>
- <menu_item_separator label="-----------" name="separator3"/>
- <menu_item_call label="離席中ã«è¨­å®š" name="Set Away"/>
- <menu_item_call label="å–ã‚Šè¾¼ã¿ä¸­ã«è¨­å®š" name="Set Busy"/>
- <menu_item_call label="自分ã®ã‚¢ãƒã‚¿ãƒ¼ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’åœæ­¢" name="Stop Animating My Avatar"/>
- <menu_item_call label="キー制御を解除" name="Release Keys"/>
- <menu_item_separator label="-----------" name="separator4"/>
- <menu_item_call label="アカウントã®å±¥æ­´..." name="Account History...">
- <on_click name="AccountHistory_url" userdata="WebLaunchAccountHistory,http://secondlife.com/account/transactions.php?lang=ja"/>
- </menu_item_call>
- <menu_item_call label="マイアカウントã®ç®¡ç†..." name="Manage My Account...">
- <on_click name="ManageMyAccount_url" userdata="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=ja"/>
- </menu_item_call>
- <menu_item_call label="L$(リンデン・ドル)を購入" name="Buy and Sell L$..."/>
- <menu_item_separator label="-----------" name="separator5"/>
- <menu_item_call label="自分ã®åœŸåœ°..." name="My Land..."/>
- <menu_item_call label="土地情報..." name="About Land..."/>
- <menu_item_call label="土地を購入..." name="Buy Land..."/>
- <menu_item_call label="地域ï¼ä¸å‹•ç”£..." name="Region/Estate..."/>
- <menu_item_separator label="-----------" name="separator6"/>
- <menu label="環境ã®è¨­å®š" name="Environment Settings">
+ <menu_item_check label="移動" name="Movement Controls"/>
+ <menu_item_check label="視界" name="Camera Controls"/>
+ <menu_item_call label="土地ã«ã¤ã„ã¦" name="About Land"/>
+ <menu_item_call label="地域 / ä¸å‹•ç”£" name="Region/Estate"/>
+ <menu_item_call label="土地ã®è³¼å…¥" name="Buy Land"/>
+ <menu_item_call label="自分ã®åœŸåœ°" name="My Land"/>
+ <menu label="表示" name="Land">
+ <menu_item_check label="ç«‹å…¥ç¦æ­¢ãƒ©ã‚¤ãƒ³" name="Ban Lines"/>
+ <menu_item_check label="ビーコン(標識)" name="beacons"/>
+ <menu_item_check label="敷地境界線" name="Property Lines"/>
+ <menu_item_check label="土地所有者" name="Land Owners"/>
+ </menu>
+ <menu label="ランドマーク" name="Landmarks">
+ <menu_item_call label="ã“ã“ã®ãƒ©ãƒ³ãƒ‰ãƒžãƒ¼ã‚¯ã‚’作æˆ" name="Create Landmark Here"/>
+ <menu_item_call label="ç¾åœ¨åœ°ã‚’ホームã«è¨­å®š" name="Set Home to Here"/>
+ </menu>
+ <menu_item_call label="ホーム" name="Teleport Home"/>
+ <menu_item_check label="ミニマップ" name="Mini-Map"/>
+ <menu_item_check label="世界地図" name="World Map"/>
+ <menu_item_call label="スナップショット" name="Take Snapshot"/>
+ <menu label="太陽" name="Environment Settings">
<menu_item_call label="æ—¥ã®å‡º" name="Sunrise"/>
<menu_item_call label="æ­£åˆ" name="Noon"/>
<menu_item_call label="日没" name="Sunset"/>
<menu_item_call label="深夜" name="Midnight"/>
- <menu_item_call label="地域ã®æ¨™æº–設定ã«æˆ»ã™" name="Revert to Region Default"/>
- <menu_item_separator label="-----------" name="separator"/>
+ <menu_item_call label="エステートタイムを使用" name="Revert to Region Default"/>
<menu_item_call label="環境編集" name="Environment Editor"/>
</menu>
</menu>
- <menu label="ツール" name="Tools">
- <menu label="ツールをé¸ã¶" name="Select Tool">
- <menu_item_call label="フォーカス" name="Focus"/>
- <menu_item_call label="移動" name="Move"/>
- <menu_item_call label="編集" name="Edit"/>
- <menu_item_call label="作æˆ" name="Create"/>
- <menu_item_call label="土地" name="Land"/>
- </menu>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_check label="自分ã®ã‚ªãƒ–ジェクトã®ã¿é¸æŠž" name="Select Only My Objects"/>
- <menu_item_check label="移動å¯èƒ½ãªã‚ªãƒ–ジェクトã®ã¿é¸æŠž" name="Select Only Movable Objects"/>
- <menu_item_check label="環境ã§é¸æŠž" name="Select By Surrounding"/>
- <menu_item_check label="éš ã‚ŒãŸä½ç½®ã®é¸æŠžã‚‚表示" name="Show Hidden Selection"/>
- <menu_item_check label="é¸æŠžã—ãŸã‚‚ã®ã®å…‰æºç¯„囲を表示" name="Show Light Radius for Selection"/>
- <menu_item_check label="é¸æŠžãƒ“ームを表示" name="Show Selection Beam"/>
- <menu_item_separator label="-----------" name="separator2"/>
- <menu_item_check label="グリッドã«ã‚¹ãƒŠãƒƒãƒ—" name="Snap to Grid"/>
- <menu_item_call label="オブジェクトã®XY移動をグリッドã«åˆã‚ã›ã‚‹" name="Snap Object XY to Grid"/>
- <menu_item_call label="グリッドをオブジェクトã®ä½ç½®åŸºæº–ã§å†è¨­å®š" name="Use Selection for Grid"/>
- <menu_item_call label="グリッドã®ã‚ªãƒ—ション..." name="Grid Options..."/>
- <menu_item_separator label="-----------" name="separator3"/>
- <menu_item_check label="リンクã•ã‚ŒãŸä¸€éƒ¨ã‚’編集" name="Edit Linked Parts"/>
+ <menu label="制作" name="BuildTools">
+ <menu_item_check label="制作" name="Show Build Tools"/>
+ <menu label="制作ツールをé¸æŠž" name="Select Tool">
+ <menu_item_call label="フォーカスツール" name="Focus"/>
+ <menu_item_call label="移動ツール" name="Move"/>
+ <menu_item_call label="編集ツール" name="Edit"/>
+ <menu_item_call label="クリエーションツール" name="Create"/>
+ <menu_item_call label="土地ツール" name="Land"/>
+ </menu>
+ <menu label="編集" name="Edit">
+ <menu_item_call label="å…ƒã«æˆ»ã™" name="Undo"/>
+ <menu_item_call label="ã‚„ã‚Šç›´ã—" name="Redo"/>
+ <menu_item_call label="切りå–ã‚Š" name="Cut"/>
+ <menu_item_call label="コピー" name="Copy"/>
+ <menu_item_call label="貼り付ã‘" name="Paste"/>
+ <menu_item_call label="削除" name="Delete"/>
+ <menu_item_call label="複製" name="Duplicate"/>
+ <menu_item_call label="ã™ã¹ã¦é¸æŠž" name="Select All"/>
+ <menu_item_call label="é¸æŠžè§£é™¤" name="Deselect"/>
+ </menu>
<menu_item_call label="リンク" name="Link"/>
- <menu_item_call label="リンク解除" name="Unlink"/>
- <menu_item_separator label="-----------" name="separator4"/>
- <menu_item_call label="é¸æŠžå¯¾è±¡ã«è¦–点移動" name="Focus on Selection"/>
- <menu_item_call label="é¸æŠžç¯„囲ã«ã‚ºãƒ¼ãƒ ã‚¤ãƒ³" name="Zoom to Selection"/>
- <menu_item_call label="オブジェクトを購入" name="Menu Object Take"/>
- <menu_item_call label="コピーをå–ã‚‹" name="Take Copy"/>
- <menu_item_call label="オブジェクトをオブジェクト・コンテンツã«æˆ»ã—ã¦ä¿å­˜" name="Save Object Back to Object Contents"/>
- <menu_item_separator label="-----------" name="separator6"/>
- <menu_item_call label="スクリプト警告ï¼ã‚¨ãƒ©ãƒ¼ãƒ»ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’表示" name="Show Script Warning/Error Window"/>
- <menu label="é¸æŠžã—ãŸã‚ªãƒ–ジェクトã®ä¸­ã®ã‚¹ã‚¯ãƒªãƒ—トをå†ã‚³ãƒ³ãƒ‘イル" name="Recompile Scripts in Selection">
- <menu_item_call label="Mono" name="Mono"/>
- <menu_item_call label="LSL" name="LSL"/>
- </menu>
- <menu_item_call label="é¸æŠžã—ãŸã‚ªãƒ–ジェクトã®ä¸­ã®ã‚¹ã‚¯ãƒªãƒ—トをリセット" name="Reset Scripts in Selection"/>
- <menu_item_call label="é¸æŠžã—ãŸã‚ªãƒ–ジェクトã®ä¸­ã®ã‚¹ã‚¯ãƒªãƒ—トを起動ã™ã‚‹" name="Set Scripts to Running in Selection"/>
- <menu_item_call label="é¸æŠžã—ãŸã‚ªãƒ–ジェクトã®ä¸­ã®ã‚¹ã‚¯ãƒªãƒ—トをåœæ­¢ã™ã‚‹" name="Set Scripts to Not Running in Selection"/>
+ <menu_item_call label="リンクを外ã™" name="Unlink"/>
+ <menu_item_call label="é¸æŠžã—ãŸã‚‚ã®ã«ç„¦ç‚¹ã‚’åˆã‚ã›ã‚‹" name="Focus on Selection"/>
+ <menu_item_call label="é¸æŠžã—ãŸã‚‚ã®ã‚’ズームã™ã‚‹" name="Zoom to Selection"/>
+ <menu label="オブジェクト" name="Object">
+ <menu_item_call label="è²·ã†" name="Menu Object Take"/>
+ <menu_item_call label="コピーをå–ã‚‹" name="Take Copy"/>
+ <menu_item_call label="「マイ æŒã¡ç‰©ã€ã«ä¿å­˜" name="Save Object Back to My Inventory"/>
+ <menu_item_call label="オブジェクトã®ä¸­èº«ã«ä¿å­˜" name="Save Object Back to Object Contents"/>
+ </menu>
+ <menu label="スクリプト" name="Scripts">
+ <menu_item_call label="スクリプトã®ãƒªã‚³ãƒ³ãƒ‘イル(Mono)" name="Mono"/>
+ <menu_item_call label="スクリプトã®ãƒªã‚³ãƒ³ãƒ‘イル(LSL)" name="LSL"/>
+ <menu_item_call label="スクリプトã®ãƒªã‚»ãƒƒãƒˆ" name="Reset Scripts"/>
+ <menu_item_call label="スクリプトを実行中ã«ã™ã‚‹" name="Set Scripts to Running"/>
+ <menu_item_call label="スクリプトを実行åœæ­¢ã«ã™ã‚‹" name="Set Scripts to Not Running"/>
+ </menu>
+ <menu label="オプション" name="Options">
+ <menu_item_check label="リンク部ä½ã‚’編集" name="Edit Linked Parts"/>
+ <menu_item_call label="デフォルトã®ã‚¢ãƒƒãƒ—ロード権é™ã‚’設定" name="perm prefs"/>
+ <menu_item_check label="権é™ã®è©³ç´°ã‚’表示" name="DebugPermissions"/>
+ <menu label="é¸æŠž" name="Selection">
+ <menu_item_check label="ç§ã®ã‚ªãƒ–ジェクトã ã‘ã‚’é¸æŠž" name="Select Only My Objects"/>
+ <menu_item_check label="動的オブジェクトã®ã¿é¸æŠž" name="Select Only Movable Objects"/>
+ <menu_item_check label="環境ã§é¸æŠž" name="Select By Surrounding"/>
+ </menu>
+ <menu label="表示" name="Show">
+ <menu_item_check label="éžè¡¨ç¤ºã®é¸æŠžã‚’表示" name="Show Hidden Selection"/>
+ <menu_item_check label="é¸æŠžã—ãŸå…‰ã®åŠå¾„範囲を表示" name="Show Light Radius for Selection"/>
+ <menu_item_check label="é¸æŠžãƒ“ームを表示" name="Show Selection Beam"/>
+ </menu>
+ <menu label="グリッド" name="Grid">
+ <menu_item_check label="グリッドãƒã‚¤ãƒ³ãƒˆã«ã‚¹ãƒŠãƒƒãƒ—" name="Snap to Grid"/>
+ <menu_item_call label="オブジェクトã®XY軸をグリッドã«ã‚¹ãƒŠãƒƒãƒ—" name="Snap Object XY to Grid"/>
+ <menu_item_call label="é¸æŠžã‚’グリッドã«ä½¿ç”¨" name="Use Selection for Grid"/>
+ <menu_item_call label="グリッドオプション" name="Grid Options"/>
+ </menu>
+ </menu>
+ <menu label="リンクã—ãŸéƒ¨åˆ†ã‚’é¸æŠž" name="Select Linked Parts">
+ <menu_item_call label="次ã®éƒ¨ä½ã‚’é¸æŠž" name="Select Next Part"/>
+ <menu_item_call label="å‰å›žã®éƒ¨ä½ã‚’é¸æŠž" name="Select Previous Part"/>
+ <menu_item_call label="次ã®éƒ¨ä½ã‚’å«ã‚ã‚‹" name="Include Next Part"/>
+ <menu_item_call label="å‰å›žã®éƒ¨ä½ã‚’å«ã‚ã‚‹" name="Include Previous Part"/>
+ </menu>
</menu>
<menu label="ヘルプ" name="Help">
- <menu_item_call label="Second Life ヘルプ" name="Second Life Help"/>
+ <menu_item_call label="[SECOND_LIFE] ヘルプ" name="Second Life Help"/>
<menu_item_call label="ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«" name="Tutorial"/>
- <menu_item_separator label="-----------" name="separator"/>
- <menu_item_call label="Lindenå…¬å¼ãƒ–ログ..." name="Official Linden Blog..."/>
- <menu_item_separator label="-----------" name="separator2"/>
- <menu_item_call label="スクリプト・ãƒãƒ¼ã‚¿ãƒ«..." name="Scripting Portal...">
- <on_click name="ScriptingPortal_url" userdata="WebLaunchLSLWiki,http://wiki.secondlife.com/wiki/LSL_Portal/ja" />
- </menu_item_call>
- <menu_item_separator label="-----------" name="separator3"/>
- <menu_item_call label="å«ŒãŒã‚‰ã›ã®å ±å‘Š..." name="Report Abuse..."/>
- <menu_item_call label="è¡çªã®è¨˜éŒ²..." name="Bumps, Pushes &amp;amp; Hits..."/>
- <menu_item_call label="ラグ メーター" name="Lag Meter"/>
- <menu_item_separator label="-----------" name="separator7"/>
- <menu label="ãƒã‚°ã®å ±å‘Š" name="Bug Reporting">
- <menu_item_call label="パブリックå•é¡Œãƒˆãƒ©ãƒƒã‚«ãƒ¼..." name="Public Issue Tracker..."/>
- <menu_item_call label="パブリックå•é¡Œãƒˆãƒ©ãƒƒã‚«ãƒ¼ ヘルプ..." name="Publc Issue Tracker Help...">
- <on_click name="PublicIssueTrackerHelp_url" userdata="WebLaunchPublicIssueHelp,http://wiki.secondlife.com/wiki/Issue_tracker/ja" />
- </menu_item_call>
- <menu_item_separator label="-----------" name="separator7"/>
- <menu_item_call label="ãƒã‚°ã®å ±å‘Š 101..." name="Bug Reporing 101...">
- <on_click name="BugReporting101_url" userdata="WebLaunchBugReport101,http://wiki.secondlife.com/wiki/Bug_Reporting_101"/>
- </menu_item_call>
- <menu_item_call label="セキュリティå•é¡Œ..." name="Security Issues...">
- <on_click name="SecurityIssues_url" userdata="WebLaunchSecurityIssues,http://wiki.secondlife.com/wiki/Security_issues/ja"/>
- </menu_item_call>
- <menu_item_call label="å“質ä¿è¨¼é–¢é€£Wiki..." name="QA Wiki..."/>
- <menu_item_separator label="-----------" name="separator9"/>
- <menu_item_call label="ãƒã‚°ã®å ±å‘Š..." name="Report Bug..."/>
- </menu>
- <menu_item_call label="Second Lifeã«ã¤ã„ã¦" name="About Second Life..."/>
+ <menu_item_call label="å«ŒãŒã‚‰ã›ã‚’報告" name="Report Abuse"/>
+ <menu_item_call label="[APP_NAME] ã«ã¤ã„ã¦" name="About Second Life"/>
+ </menu>
+ <menu label="アドãƒãƒ³ã‚¹" name="Advanced">
+ <menu_item_check label="30分経éŽã§ AFK ã«è¨­å®š" name="Go Away/AFK When Idle"/>
+ <menu_item_call label="ç§ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’åœæ­¢ã™ã‚‹" name="Stop Animating My Avatar"/>
+ <menu_item_call label="テクスãƒãƒ£ã®ãƒªãƒ™ãƒ¼ã‚¯" name="Rebake Texture"/>
+ <menu_item_call label="UI ã®ã‚µã‚¤ã‚ºã‚’デフォルトã«è¨­å®šã™ã‚‹" name="Set UI Size to Default"/>
+ <menu_item_check label="é ãã®ã‚ªãƒ–ジェクトをé¸æŠžã—ãªã„" name="Limit Select Distance"/>
+ <menu_item_check label="カメラã®è·é›¢ç§»å‹•ã‚’制é™ã—ãªã„" name="Disable Camera Distance"/>
+ <menu_item_check label="高解åƒåº¦ã‚¹ãƒŠãƒƒãƒ—ショット" name="HighResSnapshot"/>
+ <menu_item_check label="シャッター音ã¨ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ãªã—ã§ã‚¹ãƒŠãƒƒãƒ—ショットをディスクã«ä¿å­˜" name="QuietSnapshotsToDisk"/>
+ <menu_item_check label="圧縮ã—ã¦ã‚¹ãƒŠãƒƒãƒ—ショットをディスクã«ä¿å­˜ã™ã‚‹" name="CompressSnapshotsToDisk"/>
+ <menu_item_call label="別åã§ãƒ†ã‚¯ã‚¹ãƒãƒ£ã‚’ä¿å­˜" name="Save Texture As"/>
+ <menu label="パフォーマンスツール" name="Performance Tools">
+ <menu_item_call label="ラグ計測器" name="Lag Meter"/>
+ <menu_item_check label="統計ãƒãƒ¼" name="Statistics Bar"/>
+ <menu_item_check label="ã‚¢ãƒã‚¿ãƒ¼ã®ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ã‚³ã‚¹ãƒˆã‚’表示" name="Avatar Rendering Cost"/>
+ </menu>
+ <menu label="ãƒã‚¤ãƒ©ã‚¤ãƒˆã¨ç›®ã«è¦‹ãˆã‚‹ã‚‚ã®" name="Highlighting and Visibility">
+ <menu_item_check label="ãƒãƒ¼ã‚¸ãƒ¼ãƒ“ーコン" name="Cheesy Beacon"/>
+ <menu_item_check label="パーティクルをéžè¡¨ç¤ºã«ã™ã‚‹" name="Hide Particles"/>
+ <menu_item_check label="é¸æŠžã—ãŸã‚‚ã®ã‚’éžè¡¨ç¤ºã«ã™ã‚‹" name="Hide Selected"/>
+ <menu_item_check label="é€æ˜Žéƒ¨åˆ†ã‚’ãƒã‚¤ãƒ©ã‚¤ãƒˆ" name="Highlight Transparent"/>
+ <menu_item_check label="HUD を表示" name="Show HUD Attachments"/>
+ <menu_item_check label="一人称視点ã®ã¨ãã«å字線を表示" name="ShowCrosshairs"/>
+ <menu_item_check label="土地ã®ãƒ„ールãƒãƒƒãƒ—を表示" name="Land Tips"/>
+ </menu>
+ <menu label="レンダリング(種類)" name="Rendering Types">
+ <menu_item_check label="シンプル" name="Simple"/>
+ <menu_item_check label="アルファ" name="Alpha"/>
+ <menu_item_check label="木" name="Tree"/>
+ <menu_item_check label="ã‚¢ãƒã‚¿ãƒ¼" name="Character"/>
+ <menu_item_check label="地表" name="SurfacePath"/>
+ <menu_item_check label="空" name="Sky"/>
+ <menu_item_check label="æ°´" name="Water"/>
+ <menu_item_check label="地é¢" name="Ground"/>
+ <menu_item_check label="ボリューム" name="Volume"/>
+ <menu_item_check label="è‰" name="Grass"/>
+ <menu_item_check label="雲" name="Clouds"/>
+ <menu_item_check label="パーティクル" name="Particles"/>
+ <menu_item_check label="è¡çª" name="Bump"/>
+ </menu>
+ <menu label="レンダリング(機能)" name="Rendering Features">
+ <menu_item_check label="UI" name="UI"/>
+ <menu_item_check label="é¸æŠžæ¸ˆ" name="Selected"/>
+ <menu_item_check label="ãƒã‚¤ãƒ©ã‚¤ãƒˆ" name="Highlighted"/>
+ <menu_item_check label="ダイナミックテクスãƒãƒ£" name="Dynamic Textures"/>
+ <menu_item_check label="足ã®å½±" name="Foot Shadows"/>
+ <menu_item_check label="ãã‚‚ã‚Š" name="Fog"/>
+ <menu_item_check label="FRInfo ã®ãƒ†ã‚¹ãƒˆ" name="Test FRInfo"/>
+ <menu_item_check label="フレキシブルオブジェクト" name="Flexible Objects"/>
+ </menu>
+ <menu_item_check label="マルãƒã‚¹ãƒ¬ãƒƒãƒ‰å‡¦ç†" name="Run Multiple Threads"/>
+ <menu_item_call label="グループキャッシュã®ã‚¯ãƒªã‚¢" name="ClearGroupCache"/>
+ <menu_item_check label="マウスã®å¹³æ»‘化" name="Mouse Smoothing"/>
+ <menu_item_check label="è¿‘ãã®ãƒãƒ£ãƒƒãƒˆã« IM を表示" name="IMInChat"/>
+ <menu label="ショートカット" name="Shortcuts">
+ <menu_item_check label="検索" name="Search"/>
+ <menu_item_call label="キーをリリース" name="Release Keys"/>
+ <menu_item_call label="UI ã®ã‚µã‚¤ã‚ºã‚’デフォルトã«è¨­å®š" name="Set UI Size to Default"/>
+ <menu_item_check label="常ã«èµ°ã‚‹" name="Always Run"/>
+ <menu_item_check label="飛行" name="Fly"/>
+ <menu_item_call label="ウィンドウを閉ã˜ã‚‹" name="Close Window"/>
+ <menu_item_call label="å…¨ã¦ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’é–‰ã˜ã‚‹" name="Close All Windows"/>
+ <menu_item_call label="スナップショットをディスクã«ä¿å­˜" name="Snapshot to Disk"/>
+ <menu_item_call label="一人称視点" name="Mouselook"/>
+ <menu_item_check label="ジョイスティック・フライカム" name="Joystick Flycam"/>
+ <menu_item_call label="表示をリセット" name="Reset View"/>
+ <menu_item_call label="最後ã®ç™ºè¨€è€…を見る" name="Look at Last Chatter"/>
+ <menu label="制作ツールをé¸æŠž" name="Select Tool">
+ <menu_item_call label="焦点ツール" name="Focus"/>
+ <menu_item_call label="移動ツール" name="Move"/>
+ <menu_item_call label="編集ツール" name="Edit"/>
+ <menu_item_call label="作æˆãƒ„ール" name="Create"/>
+ <menu_item_call label="土地ツール" name="Land"/>
+ </menu>
+ <menu_item_call label="ズームイン" name="Zoom In"/>
+ <menu_item_call label="ズーム・デフォルト" name="Zoom Default"/>
+ <menu_item_call label="ズームアウト" name="Zoom Out"/>
+ <menu_item_call label="全画é¢è¡¨ç¤º" name="Toggle Fullscreen"/>
+ </menu>
+ <menu_item_call label="デãƒãƒƒã‚°è¨­å®šã‚’表示ã™ã‚‹" name="Debug Settings"/>
+ <menu_item_check label="開発メニューを表示" name="Debug Mode"/>
+ </menu>
+ <menu label="開発" name="Develop">
+ <menu label="コンソール" name="Consoles">
+ <menu_item_check label="テクスãƒãƒ£ã®ã‚³ãƒ³ã‚½ãƒ¼ãƒ«" name="Texture Console"/>
+ <menu_item_check label="デãƒãƒƒã‚°ã‚³ãƒ³ã‚½ãƒ¼ãƒ«" name="Debug Console"/>
+ <menu_item_call label="通知コンソール" name="Notifications"/>
+ <menu_item_check label="テクスãƒãƒ£ã‚µã‚¤ã‚ºã®ã‚³ãƒ³ã‚½ãƒ¼ãƒ«" name="Texture Size"/>
+ <menu_item_check label="テクスãƒãƒ£ã‚«ãƒ†ã‚´ãƒªãƒ»ã‚³ãƒ³ã‚½ãƒ¼ãƒ«" name="Texture Category"/>
+ <menu_item_check label="ファーストタイマー" name="Fast Timers"/>
+ <menu_item_check label="メモリ" name="Memory"/>
+ <menu_item_call label="リージョン情報をデãƒãƒƒã‚°ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã¸" name="Region Info to Debug Console"/>
+ <menu_item_call label="グループ情報をデãƒãƒƒã‚°ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã¸" name="Group Info to Debug Console"/>
+ <menu_item_call label="性能情報をデãƒãƒƒã‚°ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã¸" name="Capabilities Info to Debug Console"/>
+ <menu_item_check label="カメラ" name="Camera"/>
+ <menu_item_check label="風" name="Wind"/>
+ <menu_item_check label="FOV" name="FOV"/>
+ </menu>
+ <menu label="情報を表示" name="Display Info">
+ <menu_item_check label="時間を表示" name="Show Time"/>
+ <menu_item_check label="æ画情報を表示" name="Show Render Info"/>
+ <menu_item_check label="マトリックスを表示" name="Show Matrices"/>
+ <menu_item_check label="カーソルを乗ã›ãŸå ´æ‰€ã®è‰²ã‚’表示" name="Show Color Under Cursor"/>
+ <menu_item_check label="オブジェクトã®ã‚¢ãƒƒãƒ—デートを表示" name="Show Updates"/>
+ </menu>
+ <menu label="エラーを実行" name="Force Errors">
+ <menu_item_call label="ブレークãƒã‚¤ãƒ³ãƒˆ" name="Force Breakpoint"/>
+ <menu_item_call label="LLError ã¨ã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã‚’実行" name="Force LLError And Crash"/>
+ <menu_item_call label="ãƒãƒƒãƒ‰ãƒ¡ãƒ¢ãƒªã‚¢ã‚¯ã‚»ã‚¹ã‚’実行" name="Force Bad Memory Access"/>
+ <menu_item_call label="ç„¡é™ãƒ«ãƒ¼ãƒ—" name="Force Infinite Loop"/>
+ <menu_item_call label="ドライãƒã®ã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã‚’実行" name="Force Driver Carsh"/>
+ <menu_item_call label="ソフトウェア例外エラーã®å®Ÿè¡Œ" name="Force Software Exception"/>
+ <menu_item_call label="ビューワã®æŽ¥ç¶šé®æ–­ã‚’実行" name="Force Disconnect Viewer"/>
+ <menu_item_call label="メモリリークã®ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ãƒˆ" name="Memory Leaking Simulation"/>
+ </menu>
+ <menu label="レンダーテスト" name="Render Tests">
+ <menu_item_check label="カメラオフセット" name="Camera Offset"/>
+ <menu_item_check label="フレームレートをランダム化" name="Randomize Framerate"/>
+ <menu_item_check label="Periodic Slow Frame" name="Periodic Slow Frame"/>
+ <menu_item_check label="フレームテスト" name="Frame Test"/>
+ </menu>
+ <menu label="メタデータã®ãƒ¬ãƒ³ãƒ€ãƒ¼" name="Render Metadata">
+ <menu_item_check label="ãƒã‚¦ãƒ³ãƒ‡ã‚£ãƒ³ã‚°ãƒœãƒƒã‚¯ã‚¹" name="Bounding Boxes"/>
+ <menu_item_check label="オクトリー" name="Octree"/>
+ <menu_item_check label="シャドウ円éŒ" name="Shadow Frusta"/>
+ <menu_item_check label="オクルージョン" name="Occlusion"/>
+ <menu_item_check label="ãƒãƒƒãƒã®æç”»" name="Render Batches"/>
+ <menu_item_check label="アニメーション部分をテクスãƒãƒ£ã§è¡¨ç¤º" name="Texture Anim"/>
+ <menu_item_check label="テクスãƒãƒ£å„ªå…ˆåº¦" name="Texture Priority"/>
+ <menu_item_check label="テクスãƒãƒ£ã®ç¯„囲" name="Texture Area"/>
+ <menu_item_check label="Face Area" name="Face Area"/>
+ <menu_item_check label="å…‰" name="Lights"/>
+ <menu_item_check label="骨組ã¿ã®è¡çªåˆ¤å®š" name="Collision Skeleton"/>
+ <menu_item_check label="Raycast" name="Raycast"/>
+ </menu>
+ <menu label="レンダリング" name="Rendering">
+ <menu_item_check label="軸" name="Axes"/>
+ <menu_item_check label="接線基底" name="Tangent Basis"/>
+ <menu_item_call label="é¸æŠžã—ãŸãƒ†ã‚¯ã‚¹ãƒãƒ£æƒ…報基底" name="Selected Texture Info Basis"/>
+ <menu_item_check label="ワイヤーフレーム" name="Wireframe"/>
+ <menu_item_check label="オブジェクト間オクルージョン" name="Object-Object Occlusion"/>
+ <menu_item_check label="フレームãƒãƒƒãƒ•ã‚¡ãƒ»ã‚ªãƒ–ジェクト" name="Framebuffer Objects"/>
+ <menu_item_check label="é…延レンダリング" name="Deferred Rendering"/>
+ <menu_item_check label="グローãƒãƒ«ã‚¤ãƒ«ãƒŸãƒãƒ¼ã‚·ãƒ§ãƒ³" name="Global Illumination"/>
+ <menu_item_check label="GLデãƒãƒƒã‚°" name="Debug GL"/>
+ <menu_item_check label="経路をデãƒãƒƒã‚°" name="Debug Pipeline"/>
+ <menu_item_check label="ファーストアルファ" name="Fast Alpha"/>
+ <menu_item_check label="アニメーションテクスãƒãƒ£" name="Animation Textures"/>
+ <menu_item_check label="テクスãƒãƒ£ã‚’無効ã«ã™ã‚‹" name="Disable Textures"/>
+ <menu_item_check label="フル解åƒåº¦ãƒ†ã‚¯ã‚¹ãƒãƒ£" name="Rull Res Textures"/>
+ <menu_item_check label="テクスãƒãƒ£ã®æ¤œæŸ»" name="Audit Textures"/>
+ <menu_item_check label="テクスãƒãƒ£ã‚¢ãƒˆãƒ©ã‚¹" name="Texture Atlas"/>
+ <menu_item_check label="装ç€ã•ã‚ŒãŸå…‰æºã‚’æç”»ã™ã‚‹" name="Render Attached Lights"/>
+ <menu_item_check label="å–り付ã‘られãŸãƒ‘ーティクルをæç”»ã™ã‚‹" name="Render Attached Particles"/>
+ <menu_item_check label="Hover Glow Objects" name="Hover Glow Objects"/>
+ </menu>
+ <menu label="ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯" name="Network">
+ <menu_item_check label="エージェントを一時åœæ­¢" name="AgentPause"/>
+ <menu_item_call label="メッセージログを有効ã«ã™ã‚‹" name="Enable Message Log"/>
+ <menu_item_call label="メッセージログを使用ä¸å¯ã«ã™ã‚‹" name="Disable Message Log"/>
+ <menu_item_check label="速力ãŒæŒ¿å…¥ã•ã‚ŒãŸã‚ªãƒ–ジェクト" name="Velocity Interpolate Objects"/>
+ <menu_item_check label="挿入ã•ã‚ŒãŸã‚ªãƒ–ジェクトã®ä½ç½®ã® Ping" name="Ping Interpolate Object Positions"/>
+ <menu_item_call label="パケットドロップ" name="Drop a Packet"/>
+ </menu>
+ <menu_item_call label="スクリプト付ãカメラをダンプ" name="Dump Scripted Camera"/>
+ <menu_item_call label="è¡çªãƒ»ãƒ—ッシュ・打撃" name="Bumps, Pushes &amp;amp; Hits"/>
+ <menu label="レコーダー" name="Recorder">
+ <menu_item_call label="å†ç”Ÿé–‹å§‹" name="Start Playback"/>
+ <menu_item_call label="å†ç”Ÿåœæ­¢" name="Stop Playback"/>
+ <menu_item_check label="å†ç”Ÿã‚’ループ" name="Loop Playback"/>
+ <menu_item_call label="記録開始" name="Start Record"/>
+ <menu_item_call label="記録åœæ­¢" name="Stop Record"/>
+ </menu>
+ <menu label="世界" name="World">
+ <menu_item_check label="シムã®å¤ªé™½ã®è¨­å®šã‚’無視ã™ã‚‹" name="Sim Sun Override"/>
+ <menu_item_check label="ビーコンã®å¼·èª¿è¡¨ç¤º" name="Cheesy Beacon"/>
+ <menu_item_check label="固定ã•ã‚ŒãŸå¤©æ°—" name="Fixed Weather"/>
+ <menu_item_call label="リージョンオブジェクトã®ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’ダンプ" name="Dump Region Object Cache"/>
+ </menu>
+ <menu label="UI" name="UI">
+ <menu_item_call label="Web ブラウザã®ãƒ†ã‚¹ãƒˆ" name="Web Browser Test"/>
+ <menu_item_call label="SelectMgr をダンプ" name="Dump SelectMgr"/>
+ <menu_item_call label="æŒã¡ç‰©ã®å‡ºåŠ›" name="Dump Inventory"/>
+ <menu_item_call label="タイマーをダンプ" name="Dump Timers"/>
+ <menu_item_call label="フォーカスホールダーをダンプ" name="Dump Focus Holder"/>
+ <menu_item_call label="é¸æŠžã—ãŸã‚ªãƒ–ジェクト情報をプリント" name="Print Selected Object Info"/>
+ <menu_item_call label="エージェント情報をプリント" name="Print Agent Info"/>
+ <menu_item_call label="メモリ使用状æ³" name="Memory Stats"/>
+ <menu_item_check label="ダブルクリックã—ãŸå ´æ‰€ã«è‡ªå‹•æ“作ã§ç§»å‹•" name="Double-ClickAuto-Pilot"/>
+ <menu_item_check label="SelectMgr ã®ãƒ‡ãƒãƒƒã‚°" name="Debug SelectMgr"/>
+ <menu_item_check label="ダブルクリック" name="Debug Clicks"/>
+ <menu_item_check label="デãƒãƒƒã‚°è¡¨ç¤º" name="Debug Views"/>
+ <menu_item_check label="デãƒãƒƒã‚°åツールãƒãƒƒãƒ—" name="Debug Name Tooltips"/>
+ <menu_item_check label="マウスæ“作ã§ç™ºç”Ÿã™ã‚‹ã‚‚ã®ã®ãƒ‡ãƒãƒƒã‚°" name="Debug Mouse Events"/>
+ <menu_item_check label="デãƒãƒƒã‚°ã‚­ãƒ¼" name="Debug Keys"/>
+ <menu_item_check label="WindowProc ã®ãƒ‡ãƒãƒƒã‚°" name="Debug WindowProc"/>
+ </menu>
+ <menu label="XUI" name="XUI">
+ <menu_item_call label="色ã®è¨­å®šã‚’æ›´æ–°" name="Reload Color Settings"/>
+ <menu_item_call label="フォントテストを表示" name="Show Font Test"/>
+ <menu_item_call label="XML ã‹ã‚‰èª­ã¿è¾¼ã‚€" name="Load from XML"/>
+ <menu_item_call label="XML ã§ä¿å­˜" name="Save to XML"/>
+ <menu_item_check label="XUI ãƒãƒ¼ãƒ ã‚’表示" name="Show XUI Names"/>
+ <menu_item_call label="テスト用 IM ã‚’é€ä¿¡" name="Send Test IMs"/>
+ <menu_item_call label="インスペクターテスト" name="Test Inspectors"/>
+ </menu>
+ <menu label="ã‚¢ãƒã‚¿ãƒ¼" name="Character">
+ <menu label="ベークドテクスãƒãƒ£ã‚’å–å¾—" name="Grab Baked Texture">
+ <menu_item_call label="çž³" name="Iris"/>
+ <menu_item_call label="é ­" name="Head"/>
+ <menu_item_call label="上åŠèº«" name="Upper Body"/>
+ <menu_item_call label="下åŠèº«" name="Lower Body"/>
+ <menu_item_call label="スカート" name="Skirt"/>
+ </menu>
+ <menu label="キャラクターテスト" name="Character Tests">
+ <menu_item_call label="容姿を XML ã«ä¿å­˜" name="Appearance To XML"/>
+ <menu_item_call label="キャラクタジオメトリã®åˆ‡ã‚Šæ›¿ãˆ" name="Toggle Character Geometry"/>
+ <menu_item_call label="男性アãƒã‚¿ãƒ¼ã®ãƒ†ã‚¹ãƒˆ" name="Test Male"/>
+ <menu_item_call label="女性アãƒã‚¿ãƒ¼ã®ãƒ†ã‚¹ãƒˆ" name="Test Female"/>
+ <menu_item_call label="PG ã®ãƒˆã‚°ãƒ«" name="Toggle PG"/>
+ <menu_item_check label="é¸æŠžã‚¢ãƒã‚¿ãƒ¼è¨±å¯" name="Allow Select Avatar"/>
+ </menu>
+ <menu_item_call label="Params をデフォルトã«å®Ÿè¡Œ" name="Force Params to Default"/>
+ <menu_item_check label="アニメーション情報" name="Animation Info"/>
+ <menu_item_check label="アニメーションをスローモーション" name="Slow Motion Animations"/>
+ <menu_item_check label="見ã¦ã„ã‚‹ã‚‚ã®ã‚’表示ã™ã‚‹" name="Show Look At"/>
+ <menu_item_check label="クリックã—ãŸå ´æ‰€ã‚’表示ã™ã‚‹" name="Show Point At"/>
+ <menu_item_check label="çµåˆéƒ¨ã®ã‚¢ãƒƒãƒ—デートã®ãƒ‡ãƒãƒƒã‚°" name="Debug Joint Updates"/>
+ <menu_item_check label="LOD を無効ã«ã™ã‚‹" name="Disable LOD"/>
+ <menu_item_check label="キャラクター Vis ã®ãƒ‡ãƒãƒƒã‚°" name="Debug Character Vis"/>
+ <menu_item_check label="骨組ã¿ã®è¡çªåˆ¤å®šã‚’表示" name="Show Collision Skeleton"/>
+ <menu_item_check label="エージェントã®ã‚¿ãƒ¼ã‚²ãƒƒãƒˆã‚’表示" name="Display Agent Target"/>
+ --&gt;
+ <menu_item_call label="アタッãƒãƒ¡ãƒ³ãƒˆã‚’ダンプ" name="Dump Attachments"/>
+ <menu_item_call label="ã‚¢ãƒã‚¿ãƒ¼ãƒ†ã‚¯ã‚¹ãƒãƒ£ã‚’デãƒãƒƒã‚°" name="Debug Avatar Textures"/>
+ <menu_item_call label="ローカルテクスãƒãƒ£ã‚’ダンプ" name="Dump Local Textures"/>
+ </menu>
+ <menu_item_call label="圧縮画åƒ" name="Compress Images"/>
+ <menu_item_check label="Output Debug Minidump" name="Output Debug Minidump"/>
+ <menu_item_check label="次回ã®èµ·å‹•æ™‚ã«ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’表示" name="Console Window"/>
+ <menu_item_check label="管ç†è€…メニューを表示" name="View Admin Options"/>
+ <menu_item_call label="管ç†è€…ステータスã®å‘¼ã³å‡ºã—" name="Request Admin Options"/>
+ <menu_item_call label="管ç†è€…ステータス解除" name="Leave Admin Options"/>
+ </menu>
+ <menu label="管ç†è€…" name="Admin">
+ <menu label="Object">
+ <menu_item_call label="コピーをå–ã‚‹" name="Take Copy"/>
+ <menu_item_call label="ç§ã‚’所有者ã«ã™ã‚‹" name="Force Owner To Me"/>
+ <menu_item_call label="所有者権é™ã®å®Ÿè¡Œ" name="Force Owner Permissive"/>
+ <menu_item_call label="削除" name="Delete"/>
+ <menu_item_call label="ロック" name="Lock"/>
+ <menu_item_call label="アセット ID ã‚’å–å¾—" name="Get Assets IDs"/>
+ </menu>
+ <menu label="区画" name="Parcel">
+ <menu_item_call label="ç§ã‚’所有者ã«ã™ã‚‹" name="Owner To Me"/>
+ <menu_item_call label="リンデンコンテンツã«è¨­å®š" name="Set to Linden Content"/>
+ <menu_item_call label="パブリックã®åœŸåœ°ã‚’å–å¾—" name="Claim Public Land"/>
+ </menu>
+ <menu label="リージョン/地域" name="Region">
+ <menu_item_call label="一時アセットデータをダンプ" name="Dump Temp Asset Data"/>
+ <menu_item_call label="リージョンã®çŠ¶æ…‹ã‚’ä¿å­˜" name="Save Region State"/>
+ </menu>
+ <menu_item_call label="グリッドツール" name="God Tools"/>
+ </menu>
+ <menu label="管ç†è€…" name="Deprecated">
+ <menu label="オブジェクトをå–り付ã‘ã‚‹" name="Attach Object"/>
+ <menu label="オブジェクトをå–り外ã™" name="Detach Object"/>
+ <menu label="衣類を脱ã" name="Take Off Clothing">
+ <menu_item_call label="シャツ" name="Shirt"/>
+ <menu_item_call label="パンツ" name="Pants"/>
+ <menu_item_call label="é´" name="Shoes"/>
+ <menu_item_call label="é´ä¸‹" name="Socks"/>
+ <menu_item_call label="ジャケット" name="Jacket"/>
+ <menu_item_call label="手袋" name="Gloves"/>
+ <menu_item_call label="下ç€ã‚·ãƒ£ãƒ„" name="Menu Undershirt"/>
+ <menu_item_call label="下ç€ãƒ‘ンツ" name="Menu Underpants"/>
+ <menu_item_call label="スカート" name="Skirt"/>
+ <menu_item_call label="アルファ" name="Alpha"/>
+ <menu_item_call label="タトゥ" name="Tattoo"/>
+ <menu_item_call label="ã™ã¹ã¦ã®è¡£é¡ž" name="All Clothes"/>
+ </menu>
+ <menu_item_check label="ツールãƒãƒ¼ã‚’表示" name="Show Toolbar"/>
+ <menu label="ヘルプ" name="Help">
+ <menu_item_call label="リンデン公å¼ãƒ–ログ" name="Official Linden Blog"/>
+ <menu_item_call label="スクリプトãƒãƒ¼ã‚¿ãƒ«" name="Scripting Portal"/>
+ <menu label="ãƒã‚°ã®å ±å‘Š" name="Bug Reporting">
+ <menu_item_call label="パブリックå•é¡Œãƒˆãƒ©ãƒƒã‚«ãƒ¼" name="Public Issue Tracker"/>
+ <menu_item_call label="パブリックå•é¡Œãƒˆãƒ©ãƒƒã‚«ãƒ¼ãƒ˜ãƒ«ãƒ—" name="Publc Issue Tracker Help"/>
+ <menu_item_call label="ãƒã‚°å ±å‘Šã®åŸºç¤ŽçŸ¥è­˜" name="Bug Reporing 101"/>
+ <menu_item_call label="セキュリティå•é¡Œ" name="Security Issues"/>
+ <menu_item_call label="QA Wiki" name="QA Wiki"/>
+ </menu>
+ </menu>
</menu>
</menu_bar>
diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml
index c20a4f50b4..33ccc579a7 100644
--- a/indra/newview/skins/default/xui/ja/notifications.xml
+++ b/indra/newview/skins/default/xui/ja/notifications.xml
@@ -6,73 +6,34 @@
<global name="alwayschoose">
常ã«ã“ã®ã‚ªãƒ—ションをé¸æŠž
</global>
- <template name="okbutton">
- <form>
- <button
- name="OK"
- text="$yestext"/>
- </form>
- </template>
-
- <template name="okignore">
- <form>
- <button
- name="OK"
- text="$yestext"/>
- <ignore text="$ignoretext"/>
- </form>
- </template>
-
- <template name="okcancelbuttons">
- <form>
- <button
- name="OK"
- text="$yestext"/>
- <button
- name="Cancel"
- text="$notext"/>
- </form>
- </template>
-
- <template name="okcancelignore">
- <form>
- <button
- name="OK"
- text="$yestext"/>
- <button
- name="Cancel"
- text="$notext"/>
- <ignore text="$ignoretext"/>
- </form>
- </template>
-
- <template name="okhelpbuttons">
- <form>
- <button
- name="OK"
- text="$yestext"/>
- <button
- name="Help"
- text="$helptext"/>
- </form>
- </template>
-
- <template name="yesnocancelbuttons">
- <form>
- <button
- name="Yes"
- text="$yestext"/>
- <button
- name="No"
- text="$notext"/>
- <button
- name="Cancel"
- text="$canceltext"/>
- </form>
- </template>
+ <global name="implicitclosebutton">
+ é–‰ã˜ã‚‹
+ </global>
+ <template name="okbutton">
+ <form>
+ <button name="OK" text="$yestext"/>
+ </form>
+ </template>
+ <template name="okignore"/>
+ <template name="okcancelbuttons">
+ <form>
+ <button name="Cancel" text="$notext"/>
+ </form>
+ </template>
+ <template name="okcancelignore"/>
+ <template name="okhelpbuttons">
+ <form>
+ <button name="Help" text="$helptext"/>
+ </form>
+ </template>
+ <template name="yesnocancelbuttons">
+ <form>
+ <button name="Yes" text="$yestext"/>
+ <button name="No" text="$notext"/>
+ </form>
+ </template>
<notification functor="GenericAcknowledge" label="ä¸æ˜Žãªè­¦å‘Šãƒ¡ãƒƒã‚»ãƒ¼ã‚¸" name="MissingAlert">
- ã‚ãªãŸã® Second Life ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã¯ã€
-今å—ã‘å–ã£ãŸè­¦å‘Šãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
+ ã‚ãªãŸã® [APP_NAME] ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã¯ä»Šå—ã‘å–ã£ãŸè­¦å‘Šãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。 最新ビューワãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã‚‹ã‹ã”確èªãã ã•ã„。
エラー詳細: 「[_NAME]ã€ã¨ã„ã†è­¦å‘Šã¯ notifications.xml ã«ã‚ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚
<usetemplate name="okbutton" yestext="OK"/>
@@ -94,13 +55,13 @@
<usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="ã¯ã„"/>
</notification>
<notification name="BadInstallation">
- Second Life をアップデート中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ secondlife.com ã‹ã‚‰æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ダウンロードã—ã¦ãã ã•ã„。
+ [APP_NAME] をアップデート中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ ビューワ㮠[http://get.secondlife.com 最新ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ダウンロード] ã—ã¦ãã ã•ã„。
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="LoginFailedNoNetwork">
- ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚¨ãƒ©ãƒ¼ï¼š 接続ãŒç¢ºç«‹ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚
+ [SECOND_LIFE_GRID] ã«æŽ¥ç¶šã§ãã¾ã›ã‚“ã§ã—ãŸã€‚
「[DIAGNOSTIC]ã€
-ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯æŽ¥ç¶šã‚’確èªã—ã¦ãã ã•ã„。
+インターãƒãƒƒãƒˆæŽ¥ç¶šãŒæ­£å¸¸ã‹ã”確èªãã ã•ã„。
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="MessageTemplateNotFound">
@@ -170,7 +131,7 @@
任命ã•ã‚ŒãŸãƒ¡ãƒ³ãƒãƒ¼ãŒè‡ªã‚‰é€€ä»»ã—ãªã„é™ã‚Šã€
彼らを役柄ã‹ã‚‰å‰Šé™¤ã§ãã¾ã›ã‚“。
æ“作を続行ã—ã¾ã™ã‹ï¼Ÿ
- <usetemplate ignoretext="オーナーã®å½¹å‰²ã«ã‚°ãƒ«ãƒ¼ãƒ—・メンãƒãƒ¼ã‚’加ãˆã‚‹ã¨ã" name="okcancelignore" notext="ã„ã„ãˆ" yestext="ã¯ã„"/>
+ <usetemplate ignoretext="グループオーナーを新ã—ã追加ã™ã‚‹å‰ã«ç¢ºèª" name="okcancelignore" notext="ã„ã„ãˆ" yestext="ã¯ã„"/>
</notification>
<notification name="AssignDangerousActionWarning">
ã‚ãªãŸã¯[ROLE_NAME]ã« [ACTION_NAME]ã®èƒ½åŠ›ã‚’
@@ -198,54 +159,8 @@
ã“ã®èƒ½åŠ›ã‚’[ROLE_NAME]ã«å‰²ã‚Šå½“ã¦ã¾ã™ã‹ï¼Ÿ
<usetemplate name="okcancelbuttons" notext="ã„ã„ãˆ" yestext="ã¯ã„"/>
</notification>
- <notification name="ClickPublishHelpLand">
- 「検索ã§å…¬é–‹ã€ã‚’é¸æŠž
-ã“ã®ãƒœãƒƒã‚¯ã‚¹ã«ãƒã‚§ãƒƒã‚¯ã™ã‚‹ã¨è¡¨ç¤ºï¼š
-- 検索çµæžœã«ãŠã‘ã‚‹ã“ã®åŒºç”»
-- ã“ã®åŒºç”»ã®ãƒ‘ブリック・オブジェクト
-- ウェブ検索ã«ãŠã‘ã‚‹ã“ã®åŒºç”»
- </notification>
- <notification name="ClickSoundHelpLand">
- メディアã¨éŸ³æ¥½ã¯ã“ã®åŒºç”»å†…ã§ã®ã¿ãŠæ¥½ã—ã¿ã„ãŸã ã‘ã¾ã™ã€‚ サウンドã¨ãƒœã‚¤ã‚¹ã¯åŒºç”»å†…é™å®šã‹ã€å„自ã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†ã«ã‚ˆã£ã¦ã¯åŒºç”»å¤–ã§ã‚‚èžãã“ã¨ãŒã§ãã¾ã™ã€‚ ナレッジベースを開ã„ã¦è¨­å®šã®ä»•æ–¹ã‚’å­¦ã³ã¾ã™ã‹ï¼Ÿ
- <url name="url">
- http://wiki.secondlife.com/wiki/区画上ã®ãƒ¡ãƒ‡ã‚£ã‚¢_(KB)
- </url>
- <usetemplate name="okcancelbuttons" notext="é–‰ã˜ã‚‹" yestext="ナレッジベースを開ã"/>
- </notification>
- <notification name="ClickSearchHelpAll">
- 検索çµæžœã¯ä»Šè¦‹ã¦ã„るタブã€ã‚ãªãŸã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†ã€é¸æŠžã—ãŸã‚«ãƒ†ã‚´ãƒªãã®ä»–ã‚’å…ƒã«ç·¨æˆã•ã‚Œã¦ã„ã¾ã™ã€‚ 詳細ã¯ãƒŠãƒ¬ãƒƒã‚¸ãƒ™ãƒ¼ã‚¹ã‚’ã”覧ãã ã•ã„。
- <url name="url">
- http://wiki.secondlife.com/wiki/検索ã«é–¢ã™ã‚‹ã‚ˆãã‚る質å•é›†_(KB)
- </url>
- <usetemplate name="okcancelbuttons" notext="é–‰ã˜ã‚‹" yestext="ナレッジベースを開ã"/>
- </notification>
- <notification name="ClickPublishHelpLandDisabled">
- ã“ã®åŒºç”»ã¯æ¤œç´¢ã‚’ç¦ãšã‚‹åœ°åŸŸã«ã‚ã‚‹ãŸã‚ã€
-ã“ã®åŒºç”»ã‚’検索ã«è¡¨ç¤ºã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
- </notification>
- <notification name="ClickPublishHelpAvatar">
- 「検索ã«è¡¨ç¤ºã€ã‚’é¸æŠžã™ã‚‹ã¨è¡¨ç¤ºï¼š
-- 検索çµæžœã«ãŠã‘る自分ã®ãƒ—ロフィール
-- 公開グループ・ページã«ãŠã‘る自分ã®ãƒ—ロフィールã¸ã®ãƒªãƒ³ã‚¯
- </notification>
- <notification name="ClickPartnerHelpAvatar">
- [SECOND_LIFE]ã®ã‚¦ã‚§ãƒ–・サイトã‹ã‚‰ã€
-ä»–ã®ä½äººã¸ã®ãƒ—ロãƒãƒ¼ã‚ºã€ãƒ‘ートナー解消手続ããŒã§ãã¾ã™ã€‚
-
-ウェブ・サイトã«è¡Œã£ã¦ パートナーã«é–¢ã™ã‚‹æƒ…報をå–å¾—ã—ã¾ã™ã‹ï¼Ÿ
- <usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="ページã«ç§»å‹•"/>
- </notification>
- <notification name="ClickUploadHelpPermissions">
- ã‚ãªãŸã®æŒã¤ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®æ¨©é™ã¯å¤ã„地域ã§ã¯ä½¿ãˆã¾ã›ã‚“。
- </notification>
- <notification name="ClickWebProfileHelpAvatar">
- ã“ã®ä½äººãŒã‚¦ã‚§ãƒ–・プロフィールURLを設定ã—ã¦ã„ã‚‹å ´åˆã¯ã€ä»¥ä¸‹ã®ã“ã¨ãŒå¯èƒ½ã§ã™ã€‚
- * 「ロードã€ã‚’クリックã—ã€ã“ã®ã‚¦ã‚§ãƒ–・タブ内ã§ãƒšãƒ¼ã‚¸ã‚’表示
- * 「ロードã€ï¼žã€Œå¤–部ブラウザ〠をクリックã—ã€ãƒ‡ã‚£ãƒ•ã‚©ãƒ«ãƒˆã®ã‚¦ã‚§ãƒ–・ブラウザã§ãƒšãƒ¼ã‚¸ã‚’表示
- * 「ロードã€ï¼žã€Œãƒ›ãƒ¼ãƒ URL〠をクリックã—ã€ä»–ã®ãƒšãƒ¼ã‚¸ã‹ã‚‰ã“ã®ä½äººã®ã‚¦ã‚§ãƒ–・プロフィールã«æˆ»ã‚‹
-
-自分ã®ãƒ—ロフィールã«ä»»æ„ã®URLを入力ã—OKをクリックã—ã¦ã€ã‚¦ã‚§ãƒ–・プロフィールã¨ã—ã¦è¨­å®šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
-ãれを見ãŸä»–ã®ä½äººãŒãã®ã‚µã‚¤ãƒˆã‚’訪れるã“ã¨ãŒã§ãã¾ã™ã€‚
+ <notification name="ClickUnimplemented">
+ 申ã—訳ã‚ã‚Šã¾ã›ã‚“ãŒã€ã¾ã æœªå®Ÿè£…ã§ã™ã€‚
</notification>
<notification name="JoinGroupCanAfford">
ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚加ã™ã‚‹ã«ã¯ã€L$[COST]ã‹ã‹ã‚Šã¾ã™ã€‚
@@ -256,6 +171,12 @@
ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«åŠ å…¥ã™ã‚‹ã«ã¯ã€L$[COST]å¿…è¦ã§ã™ã€‚
L$ãŒä¸è¶³ã—ã¦ã„ã‚‹ã®ã§ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚加ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
</notification>
+ <notification name="CreateGroupCost">
+ ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—を作るã«ã¯ L$100 ã‹ã‹ã‚Šã¾ã™ã€‚
+一人ã§ã¯ã‚°ãƒ«ãƒ¼ãƒ—ã«ãªã‚‰ãªã„ã®ã§ã€æ°¸ä¹…ã«å‰Šé™¤ã•ã‚Œã¦ã—ã¾ã„ã¾ã™ã€‚
+48 時間以内ã«ãƒ¡ãƒ³ãƒãƒ¼ã‚’勧誘ã—ã€å…¥ä¼šã—ã¦ã‚‚らã£ã¦ãã ã•ã„。
+ <usetemplate canceltext="キャンセル" name="okcancelbuttons" notext="キャンセル" yestext="L$100 ã§ã‚°ãƒ«ãƒ¼ãƒ—を作æˆ"/>
+ </notification>
<notification name="LandBuyPass">
L$[COST]㧠[TIME]時間ã“ã®åœŸåœ°[PARCEL_NAME]ã«å…¥ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
入場許å¯ã‚’購入ã—ã¾ã™ã‹ï¼Ÿ
@@ -273,13 +194,10 @@ L$ãŒä¸è¶³ã—ã¦ã„ã‚‹ã®ã§ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚加ã™ã‚‹ã“ã¨ãŒã§ãã¾
<usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="OK"/>
</notification>
<notification name="ConfirmLandSaleToAnyoneChange">
- 注:「誰ã«ã§ã‚‚売å´ã™ã‚‹ã€ã‚’クリックã™ã‚‹ã¨ã€
-ã‚ãªãŸã®åœŸåœ°ã¯Second Life ã®ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã®ã©ã“ã‹ã‚‰ã§ã‚‚
-(ã“ã®åœ°åŸŸã«ãªã„コミュニティをå«ã‚€ï¼‰è³¼å…¥ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚
+ 注æ„: 「誰ã«ã§ã‚‚販売ã€ã‚’クリックã™ã‚‹ã“ã¨ã§ã€ã‚ãªãŸã®åœŸåœ°ã¯ã“ã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã«ã„る人ã«é™ã‚‰ãš [SECOND_LIFE] コミュニティ全体ã§åˆ©ç”¨å¯èƒ½ã¨ãªã‚Šã¾ã™ã€‚
-é¸æŠžã•ã‚ŒãŸ[LAND_SIZE]平方メートルã®åœŸåœ°ã¯ã€
-売り出ã—中ã«è¨­å®šã•ã‚Œã¦ã„ã¾ã™ã€‚
-売å´ä¾¡æ ¼L$[SALE_PRICE]ã§ã€[NAME]ã«å£²å´ã‚’èªå¯ã—ã¾ã™ã€‚
+é¸æŠžã—㟠[LAND_SIZE] 平方メートルã®åœŸåœ°ã¯ã€è²©å£²å¯¾è±¡ã«è¨­å®šã•ã‚Œã¾ã—ãŸã€‚
+販売価格 L$[SALE_PRICE] ã§ã€[NAME] ãŒè²©å£²å¯¾è±¡è€…ã¨ãªã‚Šã¾ã™ã€‚
<usetemplate name="okcancelbuttons" notext="キャンセル" yestext="OK"/>
</notification>
<notification name="ReturnObjectsDeededToGroup">
@@ -347,6 +265,18 @@ L$ãŒä¸è¶³ã—ã¦ã„ã‚‹ã®ã§ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚加ã™ã‚‹ã“ã¨ãŒã§ãã¾
ã“ã®åœ°åŸŸå…¨ä½“ãŒã€Œãƒ€ãƒ¡ãƒ¼ã‚¸æœ‰åŠ¹ã€ã«è¨­å®šã•ã‚Œã¦ã„ã¾ã™ã€‚
武器を使用ã™ã‚‹ã«ã¯ã‚¹ã‚¯ãƒªãƒ—トã®å®Ÿè¡Œã‚’許å¯ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
</notification>
+ <notification name="MultipleFacesSelected">
+ ç¾åœ¨è¤‡æ•°ã®é¢ãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã™ã€‚
+ã“ã®ã¾ã¾ç¶šã‘ãŸå ´åˆã€ãƒ¡ãƒ‡ã‚£ã‚¢ã®åˆ¥ã€…ã®æ®µéšŽãŒã‚ªãƒ–ジェクトã®è¤‡æ•°ã®é¢ã«è¨­å®šã•ã‚Œã¾ã™ã€‚
+メディアを 1 ã¤ã®é¢ã ã‘ã«å–り付ã‘ã‚‹ã«ã¯ã€ã€Œãƒ†ã‚¯ã‚¹ãƒãƒ£ã‚’é¸æŠžã€ã‚’é¸ã³ã€ã‚ªãƒ–ジェクトã®å¸Œæœ›ã™ã‚‹é¢ã‚’クリックã€ãã‚Œã‹ã‚‰ã€Œè¿½åŠ ã€ã‚’クリックã—ã¦ãã ã•ã„。
+ <usetemplate ignoretext="メディアã¯é¸æŠžã—ãŸè¤‡æ•°ã®é¢ã«ã‚»ãƒƒãƒˆã•ã‚Œã¾ã™ã€‚" name="okcancelignore" notext="キャンセル" yestext="OK"/>
+ </notification>
+ <notification name="WhiteListInvalidatesHomeUrl">
+ ã“ã®å…¥åŠ›ã‚’ホワイトリストã«è¿½åŠ ã™ã‚‹ã¨ã€ã“ã®ãƒ¡ãƒ‡ã‚£ã‚¢å‘ã‘ã«ç‰¹å®šã—ãŸ
+ホーム URL を無効ã¨ã—ã¾ã™ã€‚ ã‚ãªãŸã«ã¯ã“れを実行ã™ã‚‹è¨±å¯ãŒãªã„ã®ã§ã€
+入力ã¯ãƒ›ãƒ¯ã‚¤ãƒˆãƒªã‚¹ãƒˆã«ã¯è¿½åŠ ã•ã‚Œã¾ã›ã‚“。
+ <usetemplate name="okbutton" yestext="Ok"/>
+ </notification>
<notification name="MustBeInParcel">
ç€åœ°ç‚¹ã‚’設定ã™ã‚‹ã«ã¯ã€ã“ã®åŒºç”»ã®å†…å´ã«
ç«‹ã£ã¦ãã ã•ã„。
@@ -383,6 +313,10 @@ L$ãŒä¸è¶³ã—ã¦ã„ã‚‹ã®ã§ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚加ã™ã‚‹ã“ã¨ãŒã§ãã¾
<notification name="CannotWearTrash">
ゴミ箱ã«ã‚ã‚‹æœã‚„ボディーパーツã®ç€ç”¨ã¯ã§ãã¾ã›ã‚“。
</notification>
+ <notification name="MaxAttachmentsOnOutfit">
+ オブジェクトを付ã‘られã¾ã›ã‚“ã§ã—ãŸã€‚
+最大数㮠[MAX_ATTACHMENTS] 個を越ãˆã¦ã„ã¾ã™ã€‚ ã©ã‚Œã‹å–り外ã—ã¦ã‹ã‚‰ãŠè©¦ã—ãã ã•ã„。
+ </notification>
<notification name="CannotWearInfoNotComplete">
ã¾ã èª­ã¿è¾¼ã¾ã‚Œã¦ã„ãªã„ãŸã‚ã€ãã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’装ç€ã§ãã¾ã›ã‚“。後ã§ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。
</notification>
@@ -391,23 +325,28 @@ L$ãŒä¸è¶³ã—ã¦ã„ã‚‹ã®ã§ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚加ã™ã‚‹ã“ã¨ãŒã§ãã¾
ã‚¢ãƒã‚¿ãƒ¼ã®ãƒ•ã‚¡ãƒ¼ã‚¹ãƒˆãƒãƒ¼ãƒ ã¨ãƒ©ã‚¹ãƒˆãƒãƒ¼ãƒ ã®ä¸¡æ–¹ã‚’入力ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
[SECOND_LIFE]ã«å…¥ã‚‹ã«ã¯ã€ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒå¿…è¦ã§ã™ã€‚ アカウントを作æˆã—ã¾ã™ã‹ï¼Ÿ
+ <url name="url">
+ https://join.secondlife.com/index.php?lang=ja-JP
+ </url>
<usetemplate name="okcancelbuttons" notext="ã‚‚ã†ä¸€åº¦è©¦ã™" yestext="æ–°ã—ã„アカウントを作æˆ"/>
</notification>
<notification name="AddClassified">
- 検索ディレクトリã®ã€Œã‚¯ãƒ©ã‚·ãƒ•ã‚¡ã‚¤ãƒ‰ã€ã‚»ã‚¯ã‚·ãƒ§ãƒ³ã«ã€
-クラシファイド広告ãŒ1週間掲載ã•ã‚Œã¾ã™ã€‚
-広告を記入後ã€ã€Œå…¬é–‹ã€ã‚’クリックã—ã€ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«
-追加ã—ã¾ã™ã€‚
-「公開ã€ã‚’クリックã™ã‚‹ã¨ã€æ”¯æ‰•é‡‘é¡ã‚’å°‹ã­ã‚‰ã‚Œã¾ã™ã€‚
-多ã払ã†ã»ã©ã€åºƒå‘ŠãŒã‚¯ãƒ©ã‚·ãƒ•ã‚¡ã‚¤ãƒ‰ãƒ»ãƒªã‚¹ãƒˆã¨ã‚­ãƒ¼ãƒ¯ãƒ¼ãƒ‰æ¤œç´¢
-ã®ä¸Šä½ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
- <usetemplate ignoretext="æ–°ã—ã„クラシファイド広告を加ãˆã‚‹ã¨ã" name="okcancelignore" notext="å–り消ã—" yestext="OK"/>
+ クラシファイド広告ã¯ã€æ¤œç´¢ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã¨ [http://secondlife.com/community/classifieds secondlife.com] ã®ã€Œã‚¯ãƒ©ã‚·ãƒ•ã‚¡ã‚¤ãƒ‰åºƒå‘Šã€ã‚»ã‚¯ã‚·ãƒ§ãƒ³ã«ä¸€é€±é–“掲載ã•ã‚Œã¾ã™ã€‚
+広告を記入ã—ãŸã‚‰ã€ã€ŒæŽ²è¼‰...ã€ã‚’クリックã—ã¦ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«è¿½åŠ ã—ã¦ãã ã•ã„。
+「掲載ã€ã‚’クリックã™ã‚‹ã¨ã€æ”¯æ‰•ã„ãŸã„金é¡ã‚’å°‹ã­ã‚‰ã‚Œã¾ã™ã€‚
+支払金é¡ãŒå¤šã„ã»ã©ã‚ãªãŸã®åºƒå‘Šã¯ä¸€è¦§ã¨ã‚­ãƒ¼ãƒ¯ãƒ¼ãƒ‰æ¤œç´¢ã§ä¸Šä½ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+ <usetemplate ignoretext="æ–°è¦ã‚¯ãƒ©ã‚·ãƒ•ã‚¡ã‚¤ãƒ‰åºƒå‘Šä½œæˆæ–¹æ³•" name="okcancelignore" notext="å–り消ã—" yestext="OK"/>
</notification>
<notification name="DeleteClassified">
クラシファイド広告[NAME]ã®å‰Šé™¤ã‚’ã—ã¾ã™ã‹ï¼Ÿ
支払ã„済ã¿ã®æ–™é‡‘ã¯è¿”金ã•ã‚Œã¾ã›ã‚“。
<usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="OK"/>
</notification>
+ <notification name="DeleteMedia">
+ ã“ã®é¢ã«ã‚るメディアを削除ã™ã‚‹é¸æŠžã‚’ã—ã¾ã—ãŸã€‚
+続ã‘ã¾ã™ã‹ï¼Ÿ
+ <usetemplate ignoretext="オブジェクトã‹ã‚‰ãƒ¡ãƒ‡ã‚£ã‚¢ã‚’削除ã™ã‚‹å‰ã«ç¢ºèªã™ã‚‹" name="okcancelignore" notext="ã„ã„ãˆ" yestext="ã¯ã„"/>
+ </notification>
<notification name="ClassifiedSave">
クラシファイド広告[NAME]ã¸ã®å¤‰æ›´ã‚’ä¿å­˜ã—ã¾ã™ã‹ï¼Ÿ
<usetemplate canceltext="キャンセル" name="yesnocancelbuttons" notext="ä¿å­˜ã—ãªã„" yestext="ä¿å­˜"/>
@@ -418,6 +357,9 @@ L$ãŒä¸è¶³ã—ã¦ã„ã‚‹ã®ã§ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚加ã™ã‚‹ã“ã¨ãŒã§ãã¾
</notification>
<notification name="PromptGoToEventsPage">
[SECOND_LIFE]イベント・ウェブ・ページã«ç§»å‹•ã—ã¾ã™ã‹ï¼Ÿ
+ <url name="url">
+ http://secondlife.com/events/?lang=ja-JP
+ </url>
<usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="OK"/>
</notification>
<notification name="SelectProposalToView">
@@ -435,20 +377,23 @@ L$ãŒä¸è¶³ã—ã¦ã„ã‚‹ã®ã§ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚加ã™ã‚‹ã“ã¨ãŒã§ãã¾
<usetemplate name="okcancelbuttons" notext="キャンセル" yestext="OK"/>
</notification>
<notification name="CacheWillClear">
- [SECOND_LIFE]ã®å†èµ·å‹•å¾Œã«ã‚­ãƒ£ãƒƒã‚·ãƒ¥ãŒã‚¯ãƒªã‚¢ã•ã‚Œã¾ã™ã€‚
+ [APP_NAME] ã‚’å†èµ·å‹•å¾Œã«ã‚­ãƒ£ãƒƒã‚·ãƒ¥ãŒã‚¯ãƒªã‚¢ã•ã‚Œã¾ã™ã€‚
</notification>
<notification name="CacheWillBeMoved">
- [SECOND_LIFE]ã®å†èµ·å‹•å¾Œã«ã‚­ãƒ£ãƒƒã‚·ãƒ¥ãŒç§»å‹•ã•ã‚Œã¾ã™ã€‚
-注æ„:ã“ã‚Œã«ã‚ˆã‚Šã‚­ãƒ£ãƒƒã‚·ãƒ¥ãŒã‚¯ãƒªã‚¢ã•ã‚Œã¾ã™ã€‚
+ [APP_NAME] ã‚’å†èµ·å‹•å¾Œã«ã‚­ãƒ£ãƒƒã‚·ãƒ¥ãŒç§»å‹•ã•ã‚Œã¾ã™ã€‚
+ã”注æ„: キャッシュãŒã‚¯ãƒªã‚¢ã•ã‚Œã¾ã™ã€‚
</notification>
<notification name="ChangeConnectionPort">
- ãƒãƒ¼ãƒˆã®è¨­å®šã¯ã€[SECOND_LIFE]ã®å†èµ·å‹•å¾Œã«æœ‰åŠ¹ã«ãªã‚Šã¾ã™ã€‚
+ ãƒãƒ¼ãƒˆã®è¨­å®šã¯ [APP_NAME] ã‚’å†èµ·å‹•å¾Œã«å映ã•ã‚Œã¾ã™ã€‚
</notification>
<notification name="ChangeSkin">
- æ–°ã—ã„スキンã¯[SECOND_LIFE]ã‚’å†èµ·å‹•ã™ã‚‹ã¨ç¾ã‚Œã¾ã™
+ æ–°ã—ã„スキン㯠[APP_NAME] ã‚’å†èµ·å‹•å¾Œã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
</notification>
<notification name="GoToAuctionPage">
[SECOND_LIFE]ウェブ・ページã«ç§»å‹•ã—〠入札ã‚ã‚‹ã„ã¯ã‚ªãƒ¼ã‚¯ã‚·ãƒ§ãƒ³ã®è©³ç´°ã‚’確èªã—ã¾ã™ã‹ï¼Ÿ
+ <url name="url">
+ http://secondlife.com/auctions/auction-detail.php?id=[AUCTION_ID]
+ </url>
<usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="OK"/>
</notification>
<notification name="SaveChanges">
@@ -493,6 +438,11 @@ L$ãŒä¸è¶³ã—ã¦ã„ã‚‹ã®ã§ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚加ã™ã‚‹ã“ã¨ãŒã§ãã¾
<notification name="SaveBytecodeFailReason">
次ã®ç†ç”±ã§ã€ã‚³ãƒ³ãƒ‘イルã—ãŸã‚¹ã‚¯ãƒªãƒ—トã®ä¿å­˜æ™‚ã«å•é¡ŒãŒèµ·ã“ã‚Šã¾ã—ãŸã€‚ [REASON]。 後ã§ã‚‚ã†ä¸€åº¦è©¦ã—ã¦ãã ã•ã„。
</notification>
+ <notification name="StartRegionEmpty">
+ ログインä½ç½®ãŒæŒ‡å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。
+ログインä½ç½®ã®æ¬„ã«ãƒªãƒ¼ã‚¸ãƒ§ãƒ³åを入力ã™ã‚‹ã‹ã€ã€Œæœ€å¾Œã«ãƒ­ã‚°ã‚¢ã‚¦ãƒˆã—ãŸå ´æ‰€ã€ã‹ã€Œè‡ªå®…(ホーム)ã€ã‚’é¸æŠžã—ã¦ãã ã•ã„。
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
<notification name="CouldNotStartStopScript">
スクリプトã®èµ·å‹•ã¾ãŸã¯åœæ­¢ã«å¤±æ•—ã—ã¾ã—ãŸã€‚スクリプトãŒæ ¼ç´ã•ã‚Œã¦ã„るオブジェクトãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
オブジェクトãŒç¯„囲内ã«å­˜åœ¨ã—ãªã„ã‹ã€ã¾ãŸã¯å‰Šé™¤ã•ã‚ŒãŸå¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
@@ -504,34 +454,28 @@ L$ãŒä¸è¶³ã—ã¦ã„ã‚‹ã®ã§ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚加ã™ã‚‹ã“ã¨ãŒã§ãã¾
ファイル[[FILE]]を書ãè¾¼ã‚ã¾ã›ã‚“。
</notification>
<notification name="UnsupportedHardware">
- 警告: ã‚ãªãŸã®ã‚·ã‚¹ãƒ†ãƒ ã¯ Second Life を使用ã™ã‚‹ãŸã‚ã«å¿…è¦ãªå¿…須動作環境ã®æ¡ä»¶ã‚’満ãŸã—ã¦ã„ã¾ã›ã‚“。
-Second Life ã‚’ã“ã®ã¾ã¾ã”使用ã«ãªã‚‹ã¨ã€ä¸å分ãªãƒ‘フォーマンスã—ã‹å¾—られãªã„ãŠãã‚ŒãŒã‚ã‚Šã¾ã™ã€‚
-ã¾ãŸã€ã‚µãƒãƒ¼ãƒˆå¤–ã®ã‚·ã‚¹ãƒ†ãƒ æ§‹æˆã§ã”使用ã®å ´åˆã€ãƒ†ã‚¯ãƒ‹ã‚«ãƒ«ã‚µãƒãƒ¼ãƒˆã‚’ã”利用ã„ãŸã ãã“ã¨ãŒã§ãã¾ã›ã‚“。
+ 警告: ãŠä½¿ã„ã®ã‚·ã‚¹ãƒ†ãƒ ã¯ [APP_NAME] ã®å¿…è¦æœ€ä½Žé™ã®å‹•ä½œç’°å¢ƒã‚’満ãŸã—ã¦ã„ã¾ã›ã‚“。 ã“ã®ã¾ã¾ [APP_NAME] を使用ã™ã‚‹ã¨ã€ãƒ‘フォーマンスã®ä½Žä¸‹ã‚’æ„Ÿã˜ã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。 æれ入りã¾ã™ãŒ [SUPPORT_SITE] ã§ã¯ã‚µãƒãƒ¼ãƒˆå¯¾è±¡å¤–ã®ã‚·ã‚¹ãƒ†ãƒ ã«é–¢ã™ã‚‹æŠ€è¡“的サãƒãƒ¼ãƒˆã¯è¡Œã£ã¦ãŠã‚Šã¾ã›ã‚“。
- 必須動作環境ã®æ¡ä»¶
-[_URL] ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã€ã•ã‚‰ã«è©³ã—ã„情報をã”覧ã«ãªã‚Šã¾ã™ã‹ï¼Ÿ
+最低動作環境
+[_URL] ã‚’é–‹ã„ã¦è©³ã—ã„情報を確èªã—ã¾ã™ã‹ï¼Ÿ
<url name="url" option="0">
http://secondlife.com/support/sysreqs.php?lang=ja
</url>
- <usetemplate ignoretext="サãƒãƒ¼ãƒˆå¤–ã®ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã®æ¤œå‡ºæ™‚" name="okcancelignore" notext="ã„ã„ãˆ" yestext="ã¯ã„"/>
+ <usetemplate ignoretext="使用ã—ã¦ã„るコンピューターã®ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãŒã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“" name="okcancelignore" notext="ã„ã„ãˆ" yestext="ã¯ã„"/>
</notification>
<notification name="UnknownGPU">
- ãŠä½¿ã„ã®ã‚·ã‚¹ãƒ†ãƒ ã«ã¯ã€ç¾æ™‚点ã§ã¯ä¸æ˜Žãªã‚°ãƒ©ãƒ•ã‚£ãƒƒã‚¯ãƒ»ã‚«ãƒ¼ãƒ‰ãŒæ­è¼‰ã•ã‚Œã¦ã„ã¾ã™ã€‚
-ã“ã‚Œã¯ã€å½“社ã«ã‚ˆã‚‹å‹•ä½œãƒ†ã‚¹ãƒˆãŒè¡Œã‚ã‚Œã¦ã„ãªã„æ–°ã—ã„ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãŒä½¿ç”¨ã•ã‚Œã¦ã„ã‚‹å ´åˆãŒã»ã¨ã‚“ã©ã§ã™ã€‚
-Second Life ã¯ã»ã¼é–“é•ã„ãªã正常ã«å‹•ä½œã—ã¾ã™ãŒã€
-å¿…è¦ã«å¿œã˜ãŸã‚°ãƒ©ãƒ•ã‚£ãƒƒã‚¯è¨­å®šã®èª¿æ•´ãŒå¿…è¦ã«ãªã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚
-(「編集ã€ï¼žã€Œç’°å¢ƒè¨­å®šã€ï¼žã€Œè¡¨ç¤ºã€ï¼‰
+ ãŠä½¿ã„ã®ã‚·ã‚¹ãƒ†ãƒ ã«ã¯ã€ç¾åœ¨ [APP_NAME] ãŒèªè­˜ã§ããªã„グラフィックカードãŒæ­è¼‰ã•ã‚Œã¦ã„ã¾ã™ã€‚
+[APP_NAME] ã§ã¾ã ãƒ†ã‚¹ãƒˆã•ã‚Œã¦ã„ãªã„最新ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã®ãŸã‚ã ã¨è€ƒãˆã‚‰ã‚Œã¾ã™ã€‚ [APP_NAME] ã¯æ­£å¸¸ã«å®Ÿè¡Œã•ã‚Œã‚‹å¯èƒ½æ€§ãŒé«˜ã„ã§ã™ãŒã€è¡¨ç¤ºè¨­å®šã‚’調整ã™ã‚‹å¿…è¦ãŒã‚ã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。
+(ミー > 環境設定 > グラフィック)
<form name="form">
- <ignore name="ignore" text="ä¸æ˜Žãªã‚°ãƒ©ãƒ•ã‚£ãƒƒã‚¯ãƒ»ã‚«ãƒ¼ãƒ‰ã®æ¤œå‡ºæ™‚"/>
+ <ignore name="ignore" text="使用中ã®ã‚°ãƒ©ãƒ•ãƒƒã‚¯ã‚«ãƒ¼ãƒ‰ãŒèªè­˜ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ"/>
</form>
</notification>
<notification name="DisplaySettingsNoShaders">
- [SECOND_LIFE] ã¯ã€
-グラフィック・ドライãƒã®åˆæœŸåŒ–中ã«ã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã—ã¾ã—ãŸã€‚
-一般的ãªãƒ‰ãƒ©ã‚¤ãƒãƒ»ã‚¨ãƒ©ãƒ¼ã‚’回é¿ã™ã‚‹ãŸã‚ã€ã€Œå“質ãŠã‚ˆã³ãƒ‘フォーマンスã€ã¯ã€Œä½Žã€ã«è¨­å®šã•ã‚Œã¾ã™ã€‚
-ã“ã‚Œã«ã‚ˆã‚Šã€ã„ãã¤ã‹ã®ã‚°ãƒ©ãƒ•ã‚£ãƒƒã‚¯ã‚¹æ©Ÿèƒ½ã¯ç„¡åŠ¹ã«ãªã‚Šã¾ã™ã€‚
-グラフィックカード・ドライãƒã®ã‚¢ãƒƒãƒ—デートをãŠå‹§ã‚ã—ã¾ã™ã€‚
-「グラフィックã®å“質ã€ã¯ã€Œç’°å¢ƒè¨­å®šã€ï¼žã€Œè¡¨ç¤ºã€ã‹ã‚‰ä¸Šã’ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+ グラフィックドライãƒã‚’åˆæœŸåŒ–中㫠[APP_NAME] ãŒã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã—ã¾ã—ãŸã€‚
+ドライãƒã®ä¸€èˆ¬çš„ãªã‚¨ãƒ©ãƒ¼ã‚’防ããŸã‚ã«ã€ã‚°ãƒ©ãƒ•ã‚£ãƒƒã‚¯ã®ã‚¯ã‚ªãƒªãƒ†ã‚£ãŒä½Žã«è¨­å®šã•ã‚Œã¾ã™ã€‚ ãã®ãŸã‚ã€ä¸€éƒ¨ã®ã‚°ãƒ©ãƒ•ã‚£ãƒƒã‚¯ç‰¹æ€§ã«åˆ¶é™ãŒå‡ºã¾ã™ã€‚
+ãŠä½¿ã„ã®ã‚°ãƒ©ãƒ•ã‚£ãƒƒã‚¯ã‚«ãƒ¼ãƒ‰ã®ãƒ‰ãƒ©ã‚¤ãƒã‚’アップデートã™ã‚‹ã‚ˆã†ãŠã™ã™ã‚ã—ã¾ã™ã€‚
+グラフィックã®ã‚¯ã‚ªãƒªãƒ†ã‚£ã¯ã€ç’°å¢ƒè¨­å®š > グラフィック ã§è¨­å®šã§ãã¾ã™ã€‚
</notification>
<notification name="RegionNoTerraforming">
ã“ã®åœ°åŸŸ[REGION] ã¯ã€ãƒ†ãƒ©ãƒ•ã‚©ãƒ¼ãƒŸãƒ³ã‚°ãŒã§ãã¾ã›ã‚“。
@@ -588,6 +532,9 @@ Second Life ã¯ã»ã¼é–“é•ã„ãªã正常ã«å‹•ä½œã—ã¾ã™ãŒã€
[AVATAR_NAME] ã‚’ã‚ãªãŸã®åœŸåœ°ã‹ã‚‰è¿½æ”¾ã—ã¾ã™ã‹ï¼Ÿ
<usetemplate name="okcancelbuttons" notext="キャンセル" yestext="追放"/>
</notification>
+ <notification name="EjectAvatarFromGroup">
+ [GROUP_NAME] ã‹ã‚‰ [AVATAR_NAME] を追放ã—ã¾ã—ãŸ
+ </notification>
<notification name="AcquireErrorTooManyObjects">
å–得エラー:é¸æŠžã—ãŸã‚ªãƒ–ジェクトã®æ•°ãŒå¤šã™ãŽã¾ã™ã€‚
</notification>
@@ -600,7 +547,10 @@ Second Life ã¯ã»ã¼é–“é•ã„ãªã正常ã«å‹•ä½œã—ã¾ã™ãŒã€
<notification name="PromptGoToCurrencyPage">
[EXTRA]
-[URL]ã«ç§»å‹•ã—ã¦è²¨å¹£è³¼å…¥ã«é–¢ã™ã‚‹æƒ…報を確èªã—ã¾ã™ã‹ï¼Ÿ
+[_URL] ã«ç§»å‹•ã—ã¦ãƒªãƒ³ãƒ‡ãƒ³ãƒ‰ãƒ«è³¼å…¥ã«é–¢ã™ã‚‹æƒ…報を確èªã—ã¾ã™ã‹ï¼Ÿ
+ <url name="url">
+ http://secondlife.com/app/currency/?lang=ja-JP
+ </url>
<usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="OK"/>
</notification>
<notification name="UnableToLinkObjects">
@@ -689,12 +639,15 @@ Second Life ã¯ã»ã¼é–“é•ã„ãªã正常ã«å‹•ä½œã—ã¾ã™ãŒã€
æœè£…ファイルを作æˆã§ãã¾ã›ã‚“: [FILE]
</notification>
<notification name="DoNotSupportBulkAnimationUpload">
- アニメーションファイルã®ãƒãƒ«ã‚¯ã‚¢ãƒƒãƒ—ロードã¯ç¾åœ¨ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“。
+ ç¾åœ¨ [APP_NAME] ã§ã¯ã€ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã®ä¸€æ‹¬ã‚¢ãƒƒãƒ—ロードã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“。
</notification>
<notification name="CannotUploadReason">
次ã®ç†ç”±ã§ã€[FILE] をアップロードã§ãã¾ã›ã‚“: [REASON]
ã‚ã¨ã§ã‚‚ã†ä¸€åº¦è©¦ã—ã¦ãã ã•ã„。
</notification>
+ <notification name="LandmarkCreated">
+ 「 [LANDMARK_NAME] ã€ã‚’「 [FOLDER_NAME] ã€ãƒ•ã‚©ãƒ«ãƒ€ã«è¿½åŠ ã—ã¾ã—ãŸã€‚
+ </notification>
<notification name="CannotCreateLandmarkNotOwner">
土地ã®æ‰€æœ‰è€…ãŒè¨±å¯ã—ã¦ã„ãªã„ãŸã‚ã€
ランドマークを作æˆã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
@@ -720,6 +673,9 @@ Second Life ã¯ã»ã¼é–“é•ã„ãªã正常ã«å‹•ä½œã—ã¾ã™ãŒã€
変更修正権é™ã®ã‚ã‚‹
スクリプト化ã•ã‚ŒãŸã‚ªãƒ–ジェクトをé¸æŠžã—ã¦ãã ã•ã„。
</notification>
+ <notification name="CannotOpenScriptObjectNoMod">
+ 編集権é™ã®ãªã„オブジェクトã®ã‚¹ã‚¯ãƒªãƒ—トを開ãã“ã¨ã¯ã§ãã¾ã›ã‚“。
+ </notification>
<notification name="CannotSetRunningSelectObjectsNoScripts">
スクリプトã®ã€Œå®Ÿè¡Œã€ã®è¨­å®šãŒã§ãã¾ã›ã‚“。
@@ -746,12 +702,12 @@ Second Life ã¯ã»ã¼é–“é•ã„ãªã正常ã«å‹•ä½œã—ã¾ã™ãŒã€
[REASON]
</notification>
<notification name="invalid_tport">
- テレãƒãƒ¼ãƒˆãƒ»ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®å‡¦ç†ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚テレãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ã€å†åº¦ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
-ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒå¼•ã続ã表示ã•ã‚Œã‚‹å ´åˆã¯ã€æŠ€è¡“サãƒãƒ¼ãƒˆFAQ(www.secondlife.com/support)をå‚ç…§ã—ã¦ãã ã•ã„。
+ テレãƒãƒ¼ãƒˆå‡¦ç†ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ ログインã—ç›´ã™å¿…è¦ãŒã‚ã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。
+ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒä½•åº¦ã‚‚出る場åˆã¯ã€[SUPPORT_SITE] ã‚’ã”確èªãã ã•ã„。
</notification>
<notification name="invalid_region_handoff">
- 地域間ã®ç§»å‹•ã®å‡¦ç†ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚地域間を移動ã™ã‚‹ã«ã¯ã€å†åº¦ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
-ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒå¼•ã続ã表示ã•ã‚Œã‚‹å ´åˆã¯ã€æŠ€è¡“サãƒãƒ¼ãƒˆFAQ(www.secondlife.com/support)をå‚ç…§ã—ã¦ãã ã•ã„。
+ リージョン間ã®ç§»å‹•ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ ログインã—ç›´ã™å¿…è¦ãŒã‚ã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。
+ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒä½•åº¦ã‚‚出る場åˆã¯ã€[SUPPORT_SITE] ã‚’ã”確èªãã ã•ã„。
</notification>
<notification name="blocked_tport">
申ã—訳ã”ã–ã„ã¾ã›ã‚“。テレãƒãƒ¼ãƒˆã¯ç¾åœ¨ã€ãƒ–ロックã•ã‚Œã¦ã„ã¾ã™ã€‚ã‚‚ã†å°‘ã—後ã§ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。
@@ -828,8 +784,7 @@ Second Life ã¯ã»ã¼é–“é•ã„ãªã正常ã«å‹•ä½œã—ã¾ã™ãŒã€
ã“ã®åœŸåœ°ãŒã‚る地域を見ã¤ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“
</notification>
<notification name="CannotCloseFloaterBuyLand">
- Second Lifeã«ã‚ˆã‚‹ã€
-ã“ã®å–引ã®è¦‹ç©ã‚ŠãŒå®Œäº†ã™ã‚‹ã¾ã§ã€ŒåœŸåœ°ã‚’購入ã€ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’é–‰ã˜ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
+ [APP_NAME] ãŒã“ã®å–引価格を見ç©ã‚‚ã‚‹ã¾ã§ã¯ã€åœŸåœ°ã®è³¼å…¥ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’é–‰ã˜ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
</notification>
<notification name="CannotDeedLandNothingSelected">
土地を譲渡ã§ãã¾ã›ã‚“:
@@ -841,8 +796,7 @@ Second Life ã¯ã»ã¼é–“é•ã„ãªã正常ã«å‹•ä½œã—ã¾ã™ãŒã€
</notification>
<notification name="CannotDeedLandNoRegion">
土地を譲渡ã§ãã¾ã›ã‚“:
-ã“ã®åœŸåœ°ãŒã‚る地域ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
-「ツールã€ï¼žã€Œãƒã‚°ã‚’報告ã™ã‚‹ã€ã‚’使ã£ã¦å ±å‘Šã—ã¦ãã ã•ã„。
+ã“ã®åœŸåœ°ãŒã‚るリージョンãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
</notification>
<notification name="CannotDeedLandMultipleSelected">
土地を譲渡ã§ãã¾ã›ã‚“:
@@ -886,10 +840,8 @@ Second Life ã¯ã»ã¼é–“é•ã„ãªã正常ã«å‹•ä½œã—ã¾ã™ãŒã€
ã‚ãªãŸã®åŒºç”»ã¯ç·‘色ã§è¡¨ç¤ºã•ã‚Œã¦ã„ã¾ã™ã€‚
</notification>
<notification name="CannotReleaseLandRegionNotFound">
- 土地を破棄ã§ãã¾ã›ã‚“:
-ã“ã®åœŸåœ°ãŒã‚る地域ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
-
-「ツールã€ï¼žã€Œãƒã‚°ã‚’報告ã™ã‚‹ã€ã‚’使ã£ã¦å ±å‘Šã—ã¦ãã ã•ã„。
+ 土地を放棄ã§ãã¾ã›ã‚“:
+ã“ã®åœŸåœ°ãŒã‚るリージョンãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
</notification>
<notification name="CannotReleaseLandNoTransfer">
土地を破棄ã§ãã¾ã›ã‚“:
@@ -929,15 +881,11 @@ L$ã¯è¿”金ã•ã‚Œã¾ã›ã‚“。
</notification>
<notification name="CannotDivideLandNoRegion">
土地を分割ã§ãã¾ã›ã‚“:
-ã“ã®åœŸåœ°ãŒã‚る地域ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
-
-「ツールã€ï¼žã€Œãƒã‚°ã‚’報告ã™ã‚‹ã€ã‚’使ã£ã¦å ±å‘Šã—ã¦ãã ã•ã„。
+ã“ã®åœŸåœ°ãŒã‚るリージョンãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
</notification>
<notification name="CannotJoinLandNoRegion">
土地を統åˆã§ãã¾ã›ã‚“:
-ã“ã®åœŸåœ°ãŒã‚る地域ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
-
-「ツールã€ï¼žã€Œãƒã‚°ã‚’報告ã™ã‚‹ã€ã‚’使ã£ã¦å ±å‘Šã—ã¦ãã ã•ã„。
+ã“ã®åœŸåœ°ãŒã‚るリージョンãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
</notification>
<notification name="CannotJoinLandNothingSelected">
土地を統åˆã§ãã¾ã›ã‚“ã§ã—ãŸï¼š
@@ -963,17 +911,6 @@ L$ã¯è¿”金ã•ã‚Œã¾ã›ã‚“。
土地を統åˆã—ã¾ã™ã‹ï¼Ÿ
<usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="OK"/>
</notification>
- <notification name="ShowOwnersHelp">
- オーナーを表示:
-区画ã«è‰²ã‚’付ã‘ã¦ã‚ªãƒ¼ãƒŠãƒ¼ã®ç¨®é¡žã‚’表示
-
-ç·‘ = ã‚ãªãŸã®åœŸåœ°
-アクア = ã‚ãªãŸã®ã‚°ãƒ«ãƒ¼ãƒ—所有地
-赤 = 他人ãŒæ‰€æœ‰ã™ã‚‹åœŸåœ°
-黄色 = 売り出ã—中
-紫 = オークション
-グレー = パブリック
- </notification>
<notification name="ConfirmNotecardSave">
ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’コピーã€è¡¨ç¤ºã™ã‚‹å‰ã«ã€ãƒŽãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã®ä¿å­˜ãŒå¿…è¦ã§ã™ã€‚ ä¿å­˜ã—ã¾ã™ã‹ï¼Ÿ
<usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="OK"/>
@@ -997,19 +934,13 @@ L$ã¯è¿”金ã•ã‚Œã¾ã›ã‚“。
ä¿å­˜ã—ã¦ã¿ã¦ãã ã•ã„。
</notification>
<notification name="CannotSaveToAssetStore">
- [NAME]を中央資産格ç´åº«ã«ä¿å­˜ã§ãã¾ã›ã‚“。
-ã“ã‚Œã¯ä¸€æ™‚çš„ãªä¸å…·åˆã§ã™ã€‚
-æœé£¾å“ãªã©ã‚’カスタマイズã—ã€æ•°åˆ†å¾Œã«ã‚‚ã†ä¸€åº¦ä¿å­˜ã—ã¦ãã ã•ã„。
-
-ã“ã®å•é¡ŒãŒç¶šãよã†ãªã‚‰ã€ã€Œãƒ„ールã€ï¼žã€Œãƒã‚°ã‚’報告ã™ã‚‹ã€ã‚’クリックã—ã€ãŠä½¿ã„ã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯è¨­å®šã®è©³ç´°ã‚’報告ã—ã¦ãã ã•ã„。
+ [NAME] ã‚’ä¿å­˜ã§ãã¾ã›ã‚“。
+通常ã“ã‚Œã¯ä¸€æ™‚çš„ãªã‚¨ãƒ©ãƒ¼ã§ã™ã€‚ 数分後ã«ã‚‚ã†ä¸€åº¦ç€ç”¨ç‰©ã‚’カスタマイズ・ä¿å­˜ã—ã¦ãã ã•ã„。
</notification>
<notification name="YouHaveBeenLoggedOut">
- ã‚ãªãŸã¯[SECOND_LIFE]ã‹ã‚‰ãƒ­ã‚°ã‚¢ã‚¦ãƒˆã•ã‚Œã¾ã—ãŸã€‚
+ [SECOND_LIFE] ã‹ã‚‰ãƒ­ã‚°ã‚¢ã‚¦ãƒˆã—ã¾ã—ãŸï¼š
[MESSAGE]
-「IMã¨ãƒãƒ£ãƒƒãƒˆã‚’表示ã€ã‚’クリックã™ã‚‹ã¨ã€
-ç¾åœ¨ã‚ã‚‹IMã¨ãƒãƒ£ãƒƒãƒˆã‚’確èªã§ãã¾ã™ã€‚
-確èªã—ãªã„å ´åˆã¯ã€Œçµ‚了ã€ã‚’クリックã—ã€
-ã™ãã«[SECOND_LIFE]を終了ã—ã¦ãã ã•ã„。
+「IMã¨ãƒãƒ£ãƒƒãƒˆã‚’見るã€ã‚’クリックã™ã‚‹ã¨ã€å¼•ã続ãæ—¢ã«é–‹ã„ã¦ã„ã‚‹ IM ã¨ãƒãƒ£ãƒƒãƒˆã‚’見るã“ã¨ãŒã§ãã¾ã™ã€‚ 「終了ã€ã‚’クリックã™ã‚‹ã¨ [APP_NAME] ã‚’ã™ãã«çµ‚了ã—ã¾ã™ã€‚
<usetemplate name="okcancelbuttons" notext="終了" yestext="IMã¨ãƒãƒ£ãƒƒãƒˆã‚’表示"/>
</notification>
<notification name="OnlyOfficerCanBuyLand">
@@ -1027,7 +958,7 @@ L$ã¯è¿”金ã•ã‚Œã¾ã›ã‚“。
[NAME] ã«ãƒ•ãƒ¬ãƒ³ãƒ‰ã‚·ãƒƒãƒ—ã®ã‚ªãƒ•ã‚¡ãƒ¼ã‚’ã—ã¾ã™ã‹ï¼Ÿ
<form name="form">
- <input name="message" type="text">
+ <input name="message">
フレンドã¨ã—ã¦ç™»éŒ²ã—ã¦ãã‚Œã¾ã™ã‹ï¼Ÿ
</input>
<button name="Offer" text="OK"/>
@@ -1174,30 +1105,40 @@ L$ã¯è¿”金ã•ã‚Œã¾ã›ã‚“。
<notification name="ErrorMessage">
[ERROR_MESSAGE]
</notification>
- <notification name="AvatarMoved">
- ã‚ãªãŸãŒè¨ªã‚ŒãŸã„[TYPE]ã®ãƒ­ã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã¯ç¾åœ¨ã”利用ã§ãã¾ã›ã‚“。 [HELP]
-è¿‘ãã®åœ°åŸŸã«ç§»å‹•ã—ã¾ã—ãŸã€‚
+ <notification name="AvatarMovedDesired">
+ 目的地ã¯ç¾åœ¨ã”利用ã„ãŸã ã‘ã¾ã›ã‚“。
+è¿‘ãã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã«ç§»å‹•ã—ã¾ã—ãŸã€‚
+ </notification>
+ <notification name="AvatarMovedLast">
+ å‰å›žã„ãŸå ´æ‰€ã¯ç¾åœ¨ã”利用ã„ãŸã ã‘ã¾ã›ã‚“。
+è¿‘ãã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã«ç§»å‹•ã—ã¾ã—ãŸã€‚
+ </notification>
+ <notification name="AvatarMovedHome">
+ ホームロケーションã¯ç¾åœ¨ã”利用ã„ãŸã ã‘ã¾ã›ã‚“。
+è¿‘ãã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã«ç§»å‹•ã—ã¾ã—ãŸã€‚
+æ–°ãŸã«ãƒ›ãƒ¼ãƒ ã‚’設定ã—ãªãŠã—ãŸã»ã†ãŒã„ã„ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。
</notification>
<notification name="ClothingLoading">
- ã‚ãªãŸã®æœã‚’ダウンロード中ã§ã™ã€‚
-通常ã©ãŠã‚Šã«[SECOND_LIFE]を使ãˆã€
-ä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚‚ã‚ãªãŸã‚’正常ã«è¦‹ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+ ç¾åœ¨è¡£é¡žã‚’ダウンロード中ã§ã™ã€‚
+ã“ã®ã¾ã¾ [SECOND_LIFE] を通常通りã”使用ã„ãŸã ã‘ã¾ã™ã€‚他人ã‹ã‚‰ã¯ã‚ãªãŸã¯æ­£ã—ã表示ã•ã‚Œã¾ã™ã€‚
<form name="form">
- <ignore name="ignore" text="æœã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã«é•·ã„時間ãŒã‹ã‹ã‚‹å ´åˆ"/>
+ <ignore name="ignore" text="衣類ãŒãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã•ã‚Œã‚‹ã¾ã§æ™‚é–“ãŒã‹ã‹ã£ã¦ã„ã¾ã™"/>
</form>
</notification>
<notification name="FirstRun">
- [SECOND_LIFE]ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãŒå®Œäº†ã—ã¾ã—ãŸã€‚
+ [APP_NAME] ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãŒå®Œäº†ã—ã¾ã—ãŸã€‚
-[SECOND_LIFE] ã®ä½¿ç”¨ãŒåˆã‚ã¦ã®æ–¹ã¯ã€
-ログインå‰ã«ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ä½œæˆãŒå¿…è¦ã§ã™ã€‚
-www.secondlife.comã«ç§»å‹•ã—ã€æ–°è¦ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ä½œæˆã‚’è¡Œã„ã¾ã™ã‹ï¼Ÿ
+[SECOND_LIFE] を使ã£ãŸã“ã¨ãŒãªã„å ´åˆã¯ã€ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹å‰ã«ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ä½œæˆã‚’è¡Œã£ã¦ãã ã•ã„。
+[http://join.secondlife.com/?lang=ja-JP] ã§æ–°ã—ã„アカウントを作æˆã—ã¾ã™ã‹ï¼Ÿ
<usetemplate name="okcancelbuttons" notext="続行" yestext="æ–°è¦ã‚¢ã‚«ã‚¦ãƒ³ãƒˆ..."/>
</notification>
<notification name="LoginPacketNeverReceived">
- 接続ã«å•é¡ŒãŒç”Ÿã˜ã¦ã„ã¾ã™ã€‚ ã‚ãªãŸã®ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆæŽ¥ç¶šã€ã¾ãŸã¯Second Life サーãƒãƒ¼ã«å•é¡ŒãŒã‚ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
+ 接続ãŒãªã‹ãªã‹ã§ãã¾ã›ã‚“。 ãŠä½¿ã„ã®ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆæŽ¥ç¶šã‹ã€[SECOND_LIFE_GRID] ã®å•é¡Œã¨è€ƒãˆã‚‰ã‚Œã¾ã™ã€‚
-インターãƒãƒƒãƒˆæŽ¥ç¶šã‚’確èªã—ã¦æ•°åˆ†å¾Œã«ã‚‚ã†ä¸€åº¦è©¦ã¿ã‚‹ã‹ã€ã€Œãƒ˜ãƒ«ãƒ—ã€ã‚’クリックã—ã¦å½“社ã®ã‚µãƒãƒ¼ãƒˆã‚µã‚¤ãƒˆã«æŽ¥ç¶šã—ã¦ãã ã•ã„。ã¾ãŸã¯ã€ã€Œãƒ†ãƒ¬ãƒãƒ¼ãƒˆã€ã‚’クリックã—ã¦ãƒ›ãƒ¼ãƒ ã«ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã—ã¦ã¿ã¦ãã ã•ã„。
+インターãƒãƒƒãƒˆæŽ¥ç¶šã‚’確èªã—ã¦ã‹ã‚‰æ•°åˆ†å¾Œã«å†æŽ¥ç¶šã™ã‚‹ã‹ã€ãƒ˜ãƒ«ãƒ—をクリックã—㦠[SUPPORT_SITE] ã‚’ã”覧ã«ãªã‚‹ã‹ã€ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã‚’クリックã—ã¦ãƒ›ãƒ¼ãƒ ã«ç§»å‹•ã—ã¦ã¿ã¦ãã ã•ã„。
+ <url name="url">
+ http://jp.secondlife.com/support/
+ </url>
<form name="form">
<button name="OK" text="OK"/>
<button name="Help" text="ヘルプ"/>
@@ -1218,13 +1159,10 @@ F1キーを押ã—ã¦ãã ã•ã„。
[NAME] L$[PRICE] 残高ä¸è¶³ã®ãŸã‚実行ä¸å¯ã§ã™ã€‚
</notification>
<notification name="GrantedModifyRights">
- ã‚ãªãŸã«ã¯ã€
-[FIRST_NAME] [LAST_NAME]
-ã®ã‚ªãƒ–ジェクトを修正ã™ã‚‹æ¨©é™ãŒä¸Žãˆã‚‰ã‚Œã¦ã„ã¾ã™ã€‚
+ [NAME] ã¯ã€ã‚ãªãŸã«ã‚ªãƒ–ジェクトã®ç·¨é›†æ¨©é™ã‚’与ãˆã¾ã—ãŸã€‚
</notification>
<notification name="RevokedModifyRights">
- [FIRST_NAME] [LAST_NAME]
-ã®ã‚ªãƒ–ジェクトを修正ã™ã‚‹æ¨©é™ãŒå–り消ã•ã‚Œã¾ã—ãŸã€‚
+ [NAME] ã®ã‚ªãƒ–ジェクトを編集ã™ã‚‹æ¨©é™ã¯å–り消ã•ã‚Œã¾ã—ãŸ
</notification>
<notification name="FlushMapVisibilityCaches">
ã“ã®æ‰‹é †ã¯ã€ã“ã®åœ°åŸŸã®åœ°å›³ã®ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’消去ã—ã¾ã™ã€‚
@@ -1306,96 +1244,103 @@ F1キーを押ã—ã¦ãã ã•ã„。
[DOWNLOAD_PATH]。
</notification>
<notification name="DownloadWindowsMandatory">
- [SECOND_LIFE]ã®æ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒåˆ©ç”¨å¯èƒ½ã§ã™ã€‚
+ [APP_NAME] ã®æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã”利用å¯èƒ½ã§ã™ã€‚
[MESSAGE]
-[SECOND_LIFE]を使用ã™ã‚‹ãŸã‚ã«ã¯ã€
-ã“ã®ã‚¢ãƒƒãƒ—デートをダウンロードã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+[APP_NAME] ã‚’ã”利用ã«ãªã‚‹ã«ã¯ã“ã®ã‚¢ãƒƒãƒ—デートã¯å¿…é ˆã§ã™ã€‚
<usetemplate name="okcancelbuttons" notext="終了" yestext="ダウンロード"/>
</notification>
<notification name="DownloadWindows">
- [SECOND_LIFE]ã®ã‚¢ãƒƒãƒ—デート・ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒåˆ©ç”¨å¯èƒ½ã§ã™ã€‚
+ [APP_NAME] ã®ã‚¢ãƒƒãƒ—デートãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã”利用å¯èƒ½ã§ã™ã€‚
[MESSAGE]
-ã“ã®ã‚¢ãƒƒãƒ—デートã¯å¿…é ˆã§ã¯ã‚ã‚Šã¾ã›ã‚“ãŒã€ãƒ‘フォーマンスã¨å®‰å®šæ€§ã‚’å‘上ã•ã›ã‚‹ãŸã‚ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚
+ã“ã®ã‚¢ãƒƒãƒ—デートã¯å¿…é ˆã§ã¯ã‚ã‚Šã¾ã›ã‚“ãŒã€ãƒ‘フォーマンスå‘上ã®ãŸã‚ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’ãŠã™ã™ã‚ã—ã¾ã™ã€‚
<usetemplate name="okcancelbuttons" notext="続行" yestext="ダウンロード"/>
</notification>
<notification name="DownloadWindowsReleaseForDownload">
- [SECOND_LIFE]ã®ã‚¢ãƒƒãƒ—デート・ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒåˆ©ç”¨å¯èƒ½ã§ã™ã€‚
+ [APP_NAME] ã®ã‚¢ãƒƒãƒ—デートãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã”利用å¯èƒ½ã§ã™ã€‚
[MESSAGE]
-ã“ã®ã‚¢ãƒƒãƒ—デートã¯å¿…é ˆã§ã¯ã‚ã‚Šã¾ã›ã‚“ãŒã€ãƒ‘フォーマンスã¨å®‰å®šæ€§ã‚’å‘上ã•ã›ã‚‹ãŸã‚ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚
+ã“ã®ã‚¢ãƒƒãƒ—デートã¯å¿…é ˆã§ã¯ã‚ã‚Šã¾ã›ã‚“ãŒã€ãƒ‘フォーマンスå‘上ã®ãŸã‚ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’ãŠã™ã™ã‚ã—ã¾ã™ã€‚
<usetemplate name="okcancelbuttons" notext="続行" yestext="ダウンロード"/>
</notification>
+ <notification name="DownloadLinuxMandatory">
+ [APP_NAME] ã®æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã”利用å¯èƒ½ã§ã™ã€‚
+[MESSAGE]
+[APP_NAME] ã‚’ã”利用ã«ãªã‚‹ã«ã¯ã“ã®ã‚¢ãƒƒãƒ—デートã¯å¿…é ˆã§ã™ã€‚
+ <usetemplate name="okcancelbuttons" notext="終了" yestext="ダウンロード"/>
+ </notification>
+ <notification name="DownloadLinux">
+ [APP_NAME] ã®ã‚¢ãƒƒãƒ—デートãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã”利用å¯èƒ½ã§ã™ã€‚
+[MESSAGE]
+ã“ã®ã‚¢ãƒƒãƒ—デートã¯å¿…é ˆã§ã¯ã‚ã‚Šã¾ã›ã‚“ãŒã€ãƒ‘フォーマンスå‘上ã®ãŸã‚ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’ãŠã™ã™ã‚ã—ã¾ã™ã€‚
+ <usetemplate name="okcancelbuttons" notext="続ã‘ã‚‹" yestext="ダウンロード"/>
+ </notification>
+ <notification name="DownloadLinuxReleaseForDownload">
+ [APP_NAME] ã®ã‚¢ãƒƒãƒ—デートãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã”利用å¯èƒ½ã§ã™ã€‚
+[MESSAGE]
+ã“ã®ã‚¢ãƒƒãƒ—デートã¯å¿…é ˆã§ã¯ã‚ã‚Šã¾ã›ã‚“ãŒã€ãƒ‘フォーマンスå‘上ã®ãŸã‚ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’ãŠã™ã™ã‚ã—ã¾ã™ã€‚
+ <usetemplate name="okcancelbuttons" notext="続ã‘ã‚‹" yestext="ダウンロード"/>
+ </notification>
<notification name="DownloadMacMandatory">
- [SECOND_LIFE]ã®æ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒåˆ©ç”¨å¯èƒ½ã§ã™ã€‚
+ [APP_NAME] ã®æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã”利用å¯èƒ½ã§ã™ã€‚
[MESSAGE]
-[SECOND_LIFE]を使用ã™ã‚‹ãŸã‚ã«ã€
-ã“ã®ã‚¢ãƒƒãƒ—デートをダウンロードã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+[APP_NAME] ã‚’ã”利用ã«ãªã‚‹ã«ã¯ã“ã®ã‚¢ãƒƒãƒ—デートã¯å¿…é ˆã§ã™ã€‚
-アプリケーションãŒã‚るフォルダã«ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ã¾ã™ã‹ï¼Ÿ
+ã‚ãªãŸã®ã‚¢ãƒ—リケーションフォルダã«ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ã¾ã™ã‹ï¼Ÿ
<usetemplate name="okcancelbuttons" notext="終了" yestext="ダウンロード"/>
</notification>
<notification name="DownloadMac">
- [SECOND_LIFE]ã®ã‚¢ãƒƒãƒ—デート・ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒåˆ©ç”¨å¯èƒ½ã§ã™ã€‚
+ [APP_NAME] ã®ã‚¢ãƒƒãƒ—デートãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã”利用å¯èƒ½ã§ã™ã€‚
[MESSAGE]
-ã“ã®ã‚¢ãƒƒãƒ—デートã¯å¿…é ˆã§ã¯ã‚ã‚Šã¾ã›ã‚“ãŒã€ãƒ‘フォーマンスã¨å®‰å®šæ€§ã‚’å‘上ã•ã›ã‚‹ãŸã‚ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚
+ã“ã®ã‚¢ãƒƒãƒ—デートã¯å¿…é ˆã§ã¯ã‚ã‚Šã¾ã›ã‚“ãŒã€ãƒ‘フォーマンスå‘上ã®ãŸã‚ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’ãŠã™ã™ã‚ã—ã¾ã™ã€‚
-アプリケーションãŒã‚るフォルダã«ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ã¾ã™ã‹ï¼Ÿ
+ã‚ãªãŸã®ã‚¢ãƒ—リケーションフォルダã«ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ã¾ã™ã‹ï¼Ÿ
<usetemplate name="okcancelbuttons" notext="続行" yestext="ダウンロード"/>
</notification>
<notification name="DownloadMacReleaseForDownload">
- [SECOND_LIFE]ã®ã‚¢ãƒƒãƒ—デート・ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒåˆ©ç”¨å¯èƒ½ã§ã™ã€‚
+ [APP_NAME] ã®ã‚¢ãƒƒãƒ—デートãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã”利用å¯èƒ½ã§ã™ã€‚
[MESSAGE]
-ã“ã®ã‚¢ãƒƒãƒ—デートã¯å¿…é ˆã§ã¯ã‚ã‚Šã¾ã›ã‚“ãŒã€ãƒ‘フォーマンスã¨å®‰å®šæ€§ã‚’å‘上ã•ã›ã‚‹ãŸã‚ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚
+ã“ã®ã‚¢ãƒƒãƒ—デートã¯å¿…é ˆã§ã¯ã‚ã‚Šã¾ã›ã‚“ãŒã€ãƒ‘フォーマンスå‘上ã®ãŸã‚ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’ãŠã™ã™ã‚ã—ã¾ã™ã€‚
-アプリケーションãŒã‚るフォルダã«ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ã¾ã™ã‹ï¼Ÿ
+ã‚ãªãŸã®ã‚¢ãƒ—リケーションフォルダã«ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ã¾ã™ã‹ï¼Ÿ
<usetemplate name="okcancelbuttons" notext="続行" yestext="ダウンロード"/>
</notification>
<notification name="DeedObjectToGroup">
ã“ã®ã‚ªãƒ–ジェクトを譲渡ã™ã‚‹ã¨ã‚°ãƒ«ãƒ¼ãƒ—ã¯ä»¥ä¸‹ã®ã“ã¨ãŒå¯èƒ½ã§ã™ï¼š
* オブジェクトã«æ”¯æ‰•ã‚ã‚ŒãŸL$ã‚’å—é ˜ã—ã¾ã™ã€‚
- <usetemplate ignoretext="オブジェクトをグループã«è­²æ¸¡ã™ã‚‹ã¨ã" name="okcancelignore" notext="å–り消ã—" yestext="譲渡"/>
+ <usetemplate ignoretext="オブジェクトをグループã«è­²æ¸¡ã™ã‚‹å‰ã«ç¢ºèªã™ã‚‹" name="okcancelignore" notext="å–り消ã—" yestext="譲渡"/>
</notification>
<notification name="WebLaunchExternalTarget">
- ãŠä½¿ã„ã®ã‚·ã‚¹ãƒ†ãƒ ã®ã‚¦ã‚§ãƒ–・ブラウザを開ã„ã¦ã€ã“ã®å†…容を表示ã—ã¾ã™ã‹ï¼Ÿ
- <usetemplate ignoretext="ãŠä½¿ã„ã®ã‚·ã‚¹ãƒ†ãƒ ã®ãƒ–ラウザを開ã„ã¦ã‚¦ã‚§ãƒ–・ページを表示ã—よã†ã¨ã—ãŸã¨ã" name="okcancelignore" notext="キャンセル" yestext="OK"/>
+ Web ブラウザを開ã„ã¦ã“ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„を表示ã—ã¾ã™ã‹ï¼Ÿ
+ <usetemplate ignoretext="ブラウザを起動ã—㦠Web ページを見る" name="okcancelignore" notext="キャンセル" yestext="OK"/>
</notification>
<notification name="WebLaunchJoinNow">
- www.secondlife.comã«ç§»å‹•ã—ã¦ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’管ç†ã—ã¾ã™ã‹ï¼Ÿ
- <usetemplate ignoretext="アカウントを管ç†ã™ã‚‹ãŸã‚ã€ã‚¦ã‚§ãƒ–・ブラウザを起動ã™ã‚‹ã¨ã" name="okcancelignore" notext="å–り消ã—" yestext="OK"/>
- </notification>
- <notification name="WebLaunchBugReport101">
- [SECOND_LIFE]Wikiã§ã€ãƒã‚°ã‚’報告ã™ã‚‹æ­£ã—ã„方法をã”覧ãã ã•ã„。
- <usetemplate ignoretext="ãƒã‚°ãƒ¬ãƒãƒ¼ãƒˆ101 Wikiを閲覧ã™ã‚‹ãŸã‚ã®ãƒ–ラウザを開ãã«ã‚ãŸã£ã¦" name="okcancelignore" notext="キャンセル" yestext="OK"/>
+ [http://jp.secondlife.com/account/ マイアカウント] ページã«ç§»å‹•ã—ã¦ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’管ç†ã—ã¾ã™ã‹ï¼Ÿ
+ <usetemplate ignoretext="ブラウザを起動ã—ã¦ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’管ç†ã™ã‚‹" name="okcancelignore" notext="å–り消ã—" yestext="OK"/>
</notification>
<notification name="WebLaunchSecurityIssues">
[SECOND_LIFE] Wikiã§ã€
セキュリティå•é¡Œã‚’報告ã™ã‚‹æ–¹æ³•ã‚’ã”覧ãã ã•ã„。
- <usetemplate ignoretext="セキュリティå•é¡ŒWikiを閲覧ã™ã‚‹ãŸã‚ã«ã‚¦ã‚§ãƒ–・ブラウザを起動ã™ã‚‹ã«ã‚ãŸã£ã¦" name="okcancelignore" notext="キャンセル" yestext="OK"/>
+ <usetemplate ignoretext="ブラウザを起動ã—ã¦ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£å•é¡Œã®å ±å‘Šã®ä»•æ–¹ã‚’確èªã™ã‚‹" name="okcancelignore" notext="キャンセル" yestext="OK"/>
</notification>
<notification name="WebLaunchQAWiki">
[SECOND_LIFE] å“質ä¿è¨¼é–¢é€£Wikiã‚’ã”覧ãã ã•ã„。
- <usetemplate ignoretext="å“質ä¿è¨¼é–¢é€£Wikiを閲覧ã™ã‚‹ãŸã‚ã«ã‚¦ã‚§ãƒ–・ブラウザを起動ã™ã‚‹ã«ã‚ãŸã£ã¦" name="okcancelignore" notext="キャンセル" yestext="OK"/>
+ <usetemplate ignoretext="ブラウザを起動ã—㦠QA Wiki を見る" name="okcancelignore" notext="キャンセル" yestext="OK"/>
</notification>
<notification name="WebLaunchPublicIssue">
[SECOND_LIFE]ã®ãƒ‘ブリックå•é¡Œãƒˆãƒ©ãƒƒã‚«ãƒ¼ã§ã€
ãƒã‚°ã‚„ãã®ä»–ã®å•é¡Œã‚’報告ã§ãã¾ã™ã€‚
- <usetemplate ignoretext="パブリックå•é¡Œãƒˆãƒ©ãƒƒã‚«ãƒ¼ã‚’閲覧ã™ã‚‹ãŸã‚ã«ã‚¦ã‚§ãƒ–・ブラウザを起動ã™ã‚‹ã«ã‚ãŸã£ã¦" name="okcancelignore" notext="キャンセル" yestext="ページã¸è¡Œã"/>
- </notification>
- <notification name="WebLaunchPublicIssueHelp">
- [SECOND_LIFE] Wikiã§ã€
-パブリックå•é¡Œãƒˆãƒ©ãƒƒã‚«ãƒ¼ã®ä½¿ç”¨æ–¹æ³•ã‚’ã”覧ãã ã•ã„。
- <usetemplate ignoretext="パブリックå•é¡Œãƒˆãƒ©ãƒƒã‚«ãƒ¼Wikiを閲覧ã™ã‚‹ãŸã‚ã«ã‚¦ã‚§ãƒ–・ブラウザを起動ã™ã‚‹ã«ã‚ãŸã£ã¦" name="okcancelignore" notext="キャンセル" yestext="ページã¸è¡Œã"/>
+ <usetemplate ignoretext="ブラウザを確èªã—ã¦ãƒ‘ブリックå•é¡Œãƒˆãƒ©ãƒƒã‚«ãƒ¼ã‚’使用ã™ã‚‹" name="okcancelignore" notext="キャンセル" yestext="ページã¸è¡Œã"/>
</notification>
<notification name="WebLaunchSupportWiki">
Lindenå…¬å¼ãƒ–ログã§ã€æœ€æ–°ã®ãƒ‹ãƒ¥ãƒ¼ã‚¹ã‚„情報を入手ã—ã¦ãã ã•ã„。
- <usetemplate ignoretext="ブログを表示ã™ã‚‹ãŸã‚ã€ã‚¦ã‚§ãƒ–・ブラウザを起動ã™ã‚‹ã¨ã" name="okcancelignore" notext="å–り消ã—" yestext="OK"/>
+ <usetemplate ignoretext="ブラウザを起動ã—ã¦å…¬å¼ãƒ–ログを見る" name="okcancelignore" notext="å–り消ã—" yestext="OK"/>
</notification>
<notification name="WebLaunchLSLGuide">
- スクリプトガイドを開ã„ã¦ã€ã‚¹ã‚¯ãƒªãƒ—トã®ãƒ˜ãƒ«ãƒ—ã‚’å‚ç…§ã—ã¾ã™ã‹ï¼Ÿ
- <usetemplate ignoretext="LSLガイドを表示ã™ã‚‹ãŸã‚ã€ã‚¦ã‚§ãƒ–・ブラウザを起動ã™ã‚‹ã¨ã" name="okcancelignore" notext="å–り消ã—" yestext="OK"/>
+ スクリプトガイドを開ãã¾ã™ã‹ï¼Ÿ
+ <usetemplate ignoretext="ブラウザを起動ã—ã¦ã‚¹ã‚¯ãƒªãƒ—トガイドを見る" name="okcancelignore" notext="å–り消ã—" yestext="OK"/>
</notification>
<notification name="WebLaunchLSLWiki">
- LSLãƒãƒ¼ã‚¿ãƒ«ã‚’é–‹ã„ã¦ã‚¹ã‚¯ãƒªãƒ—トã®ãƒ˜ãƒ«ãƒ—ã‚’å‚ç…§ã—ã¾ã™ã‹ï¼Ÿ
- <usetemplate ignoretext="LSLãƒãƒ¼ã‚¿ãƒ«ã‚’表示ã™ã‚‹ãŸã‚ã«ã€ã‚¦ã‚§ãƒ–・ブラウザを起動ã™ã‚‹ã¨ã" name="okcancelignore" notext="å–り消ã—" yestext="ページã«ç§»å‹•"/>
+ LSL ãƒãƒ¼ã‚¿ãƒ«ã§ã‚¹ã‚¯ãƒªãƒ—トã«é–¢ã™ã‚‹æƒ…報を確èªã—ã¾ã™ã‹ï¼Ÿ
+ <usetemplate ignoretext="ブラウザを起動ã—㦠LSL ãƒãƒ¼ã‚¿ãƒ«ã‚’見る" name="okcancelignore" notext="å–り消ã—" yestext="ページã«ç§»å‹•"/>
</notification>
<notification name="ReturnToOwner">
é¸æŠžã—ãŸã‚ªãƒ–ジェクトをã€æ‰€æœ‰è€…ã«è¿”å´ã—ã¾ã™ã‹ï¼Ÿ
@@ -1403,7 +1348,7 @@ F1キーを押ã—ã¦ãã ã•ã„。
以å‰ã®æ‰€æœ‰è€…ã«è¿”å´ã•ã‚Œã¾ã™ã€‚
*警告* 移転ãŒä¸å¯èƒ½ã®è­²æ¸¡ã•ã‚ŒãŸã‚ªãƒ–ジェクトã¯å‰Šé™¤ã•ã‚Œã¾ã™ï¼
- <usetemplate ignoretext="オブジェクトをæŒã¡ä¸»ã«è¿”å´ã™ã‚‹ã¨ã" name="okcancelignore" notext="å–り消ã—" yestext="OK"/>
+ <usetemplate ignoretext="オブジェクトを所有者ã«è¿”å´ã™ã‚‹å‰ã«ç¢ºèªã™ã‚‹" name="okcancelignore" notext="å–り消ã—" yestext="OK"/>
</notification>
<notification name="GroupLeaveConfirmMember">
ç¾åœ¨ã‚ãªãŸã¯ [GROUP]ã®ãƒ¡ãƒ³ãƒãƒ¼ã§ã™ã€‚
@@ -1415,14 +1360,14 @@ F1キーを押ã—ã¦ãã ã•ã„。
<usetemplate name="okcancelbuttons" notext="キャンセル" yestext="å…¨ã¦ã®ãƒ¦ãƒ¼ã‚¶ã‚’追ã„出ã™"/>
</notification>
<notification name="MuteLinden">
- 残念ãªãŒã‚‰Lindenを無視設定ã«å…¥ã‚Œã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
+ リンデンをブロックã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="CannotStartAuctionAlreadyForSale">
æ—¢ã«å£²ã‚Šå‡ºã—中ã®åŒºç”»ãªã®ã§ã‚ªãƒ¼ã‚¯ã‚·ãƒ§ãƒ³ã«ã‹ã‘ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。 オークションã«ã‹ã‘ãŸã„å ´åˆã¯å£²ã‚Šå‡ºã—設定を解除ã—ã¦ã‹ã‚‰è¡Œã£ã¦ãã ã•ã„。
</notification>
- <notification label="オブジェクトをåå‰ã§ãƒŸãƒ¥ãƒ¼ãƒˆã§ãã¾ã›ã‚“ã§ã—ãŸ" name="MuteByNameFailed">
- ã‚ãªãŸã¯ã™ã§ã«ã“ã®åå‰ã‚’ミュートã—ã¦ã„ã¾ã™ã€‚
+ <notification label="åå‰ã§ã®ã‚ªãƒ–ジェクトã®ãƒ–ロックã«å¤±æ•—ã—ã¾ã—ãŸ" name="MuteByNameFailed">
+ ã“ã®åå‰ã¯æ—¢ã«ãƒ–ロック済ã¿ã§ã™ã€‚
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="RemoveItemWarn">
@@ -1439,24 +1384,20 @@ F1キーを押ã—ã¦ãã ã•ã„。
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="BusyModeSet">
- å–ã‚Šè¾¼ã¿ä¸­ã«è¨­å®šã•ã‚Œã¾ã—ãŸã€‚
-ãƒãƒ£ãƒƒãƒˆã¨ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ãƒˆãƒ»ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ï¼ˆIM)ãŒéš ã‚Œã¾ã™ã€‚
-相手ã¯ã€Œå–ã‚Šè¾¼ã¿ä¸­å¿œç­”メッセージã€ã‚’IMã§å—ã‘å–ã‚Šã¾ã™ã€‚
-テレãƒãƒ¼ãƒˆã®ã‚ªãƒ•ã‚¡ãƒ¼ã¯å…¨ã¦æ‹’å¦ã•ã‚Œã€æŒã¡ç‰©ã®ã‚ªãƒ•ã‚¡ãƒ¼ã¯å…¨ã¦ã‚´ãƒŸç®±ã«é€ã‚‰ã‚Œã¾ã™ã€‚
- <usetemplate ignoretext="å–ã‚Šè¾¼ã¿ä¸­ã®è¨­å®šã‚’ã™ã‚‹ã¨ã" name="okignore" yestext="OK"/>
+ å–ã‚Šè¾¼ã¿ä¸­ãƒ¢ãƒ¼ãƒ‰ã«ãªã‚Šã¾ã—ãŸã€‚
+ãƒãƒ£ãƒƒãƒˆã¨ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ãƒˆãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã¯è¡¨ç¤ºã•ã‚Œã¾ã›ã‚“。 å—ä¿¡ã™ã‚‹ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ãƒˆãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã«ã¯å–ã‚Šè¾¼ã¿ä¸­è¿”答メッセージãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ テレãƒãƒ¼ãƒˆã®ã‚ªãƒ•ã‚¡ãƒ¼ã¯å—ã‘å–ã‚Šæ‹’å¦ã¨ãªã‚Šã¾ã™ã€‚ アイテムã®ã‚ªãƒ•ã‚¡ãƒ¼ã¯ã™ã¹ã¦ã”ã¿ç®±ã«å…¥ã‚Šã¾ã™ã€‚
+ <usetemplate ignoretext="ログイン状態をå–ã‚Šè¾¼ã¿ä¸­ãƒ¢ãƒ¼ãƒ‰ã«å¤‰æ›´ã™ã‚‹" name="okignore" yestext="OK"/>
</notification>
<notification name="JoinedTooManyGroupsMember">
- ã‚ãªãŸã¯ç¾åœ¨ãƒ¡ãƒ³ãƒãƒ¼ã«ãªã£ã¦ã„るグループãŒå¤šã™ãŽã‚‹ãŸã‚ã€
-ä»–ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚加ã§ãã¾ã›ã‚“。少ãªãã¨ã‚‚1ã¤ã®ã‚°ãƒ«ãƒ¼ãƒ—を脱退ã—ã¦ã‹ã‚‰ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚加ã™ã‚‹ã‹ã€ã“ã®æ‹›å¾…ã‚’æ–­ã£ã¦ãã ã•ã„。
-グループを抜ã‘ã‚‹ã«ã¯ã€ç·¨é›†ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‹ã‚‰ã€Œã‚°ãƒ«ãƒ¼ãƒ—...ã€ã‚ªãƒ—ションををé¸æŠžã—ã¾ã™ã€‚
-[NAME]ã¯ã€ã‚ãªãŸã‚’メンãƒãƒ¼ã¨ã—ã¦ã‚°ãƒ«ãƒ¼ãƒ—ã«æ‹›å¾…ã—ã¦ã„ã¾ã™ã€‚
+ 加入ã§ãるグループã®æœ€å¤§é™ã«é”ã—ã¾ã—ãŸã€‚ ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«åŠ å…¥ã™ã‚‹ãŸã‚ã«ä»–ã®ã‚°ãƒ«ãƒ¼ãƒ—を脱退ã™ã‚‹ã‹ã€ã“ã®ç”³ã—入れを断ã£ã¦ãã ã•ã„。
+[NAME] ãŒã‚ãªãŸã‚’グループã®ãƒ¡ãƒ³ãƒãƒ¼ã¨ã—ã¦å‹§èª˜ã—ã¦ã„ã¾ã™ã€‚
[INVITE]
<usetemplate name="okcancelbuttons" notext="辞退" yestext="å‚加"/>
</notification>
<notification name="KickUser">
ã©ã‚“ãªãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã—ã¦ã€ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’追ã„出ã—ã¾ã™ã‹ï¼Ÿ
<form name="form">
- <input name="message" type="text">
+ <input name="message">
ã‚ãªãŸã¯ç®¡ç†è€…ã«ã‚ˆã‚Šãƒ­ã‚°ã‚ªãƒ•ã•ã‚Œã¾ã—ãŸã€‚
</input>
<button name="OK" text="OK"/>
@@ -1466,7 +1407,7 @@ F1キーを押ã—ã¦ãã ã•ã„。
<notification name="KickAllUsers">
ã©ã‚“ãªãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã—ã¦ã€ã‚°ãƒªãƒƒãƒ‰ã«ã„る全員を追ã„出ã—ã¾ã™ã‹ï¼Ÿ
<form name="form">
- <input name="message" type="text">
+ <input name="message">
ã‚ãªãŸã¯ç®¡ç†è€…ã«ã‚ˆã‚Šãƒ­ã‚°ã‚ªãƒ•ã•ã‚Œã¾ã—ãŸã€‚
</input>
<button name="OK" text="OK"/>
@@ -1476,7 +1417,7 @@ F1キーを押ã—ã¦ãã ã•ã„。
<notification name="FreezeUser">
ã©ã‚“ãªãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã—ã¦ã€ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’フリーズã—ã¾ã™ã‹ï¼Ÿ
<form name="form">
- <input name="message" type="text">
+ <input name="message">
ã‚ãªãŸã¯ãƒ•ãƒªãƒ¼ã‚ºã•ã‚Œã¦ã„ã¾ã™ã€‚ å‹•ãã“ã¨ã‚‚ãƒãƒ£ãƒƒãƒˆã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã›ã‚“。 管ç†è€…ãŒIMを通ã˜ã¦ã‚ãªãŸã«é€£çµ¡ã—ã¾ã™ã€‚
</input>
<button name="OK" text="OK"/>
@@ -1486,7 +1427,7 @@ F1キーを押ã—ã¦ãã ã•ã„。
<notification name="UnFreezeUser">
ã©ã‚“ãªãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’表示ã—ã¦ã€ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ•ãƒªãƒ¼ã‚ºã‚’解除ã—ã¾ã™ã‹ï¼Ÿ
<form name="form">
- <input name="message" type="text">
+ <input name="message">
ã‚‚ã†ãƒ•ãƒªãƒ¼ã‚ºã•ã‚Œã¦ã„ã¾ã›ã‚“。
</input>
<button name="OK" text="OK"/>
@@ -1496,7 +1437,7 @@ F1キーを押ã—ã¦ãã ã•ã„。
<notification name="OfferTeleport">
次ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’æ·»ãˆã¦ã‚ãªãŸãŒä»Šã„る場所ã¸ã®ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã‚’é€ã‚Šã¾ã™ã‹ï¼Ÿ
<form name="form">
- <input name="message" type="text">
+ <input name="message">
[REGION]ã«æ¥ã¾ã›ã‚“ã‹ï¼Ÿ
</input>
<button name="OK" text="OK"/>
@@ -1506,7 +1447,7 @@ F1キーを押ã—ã¦ãã ã•ã„。
<notification name="OfferTeleportFromGod">
ユーザーをゴッド・コールã§å‘¼ã³å¯„ã›ã¾ã™ã‹ï¼Ÿ
<form name="form">
- <input name="message" type="text">
+ <input name="message">
[REGION]ã«æ¥ã¾ã›ã‚“ã‹ï¼Ÿ
</input>
<button name="OK" text="OK"/>
@@ -1515,13 +1456,21 @@ F1キーを押ã—ã¦ãã ã•ã„。
</notification>
<notification name="TeleportFromLandmark">
本当ã«ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã—ã¾ã™ã‹ï¼Ÿ
- <usetemplate ignoretext="æŒã¡ç‰©ã®ãƒ©ãƒ³ãƒ‰ãƒžãƒ¼ã‚¯ã‹ã‚‰ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã™ã‚‹æ™‚" name="okcancelignore" notext="キャンセル" yestext="テレãƒãƒ¼ãƒˆ"/>
+ <usetemplate ignoretext="ランドマークã«ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã—ãŸã„ã‹ç¢ºèªã™ã‚‹" name="okcancelignore" notext="キャンセル" yestext="テレãƒãƒ¼ãƒˆ"/>
+ </notification>
+ <notification name="TeleportToPick">
+ [PICK] ã«ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã—ã¾ã™ã‹ï¼Ÿ
+ <usetemplate ignoretext="ピックã®å ´æ‰€ã«ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã—ãŸã„ã‹ç¢ºèªã™ã‚‹" name="okcancelignore" notext="キャンセル" yestext="テレãƒãƒ¼ãƒˆ"/>
+ </notification>
+ <notification name="TeleportToClassified">
+ [CLASSIFIED] ã«ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã—ã¾ã™ã‹ï¼Ÿ
+ <usetemplate ignoretext="クラシファイド広告ã®å ´æ‰€ã«ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã—ãŸã„ã‹ç¢ºèªã™ã‚‹" name="okcancelignore" notext="キャンセル" yestext="テレãƒãƒ¼ãƒˆ"/>
</notification>
<notification label="ã‚ãªãŸã®ä¸å‹•ç”£å†…ã®å…¨å“¡ã«ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’é€ä¿¡" name="MessageEstate">
今ã‚ãªãŸã®ä¸å‹•ç”£ã«ã„る人全員ã«é€ã‚‹
短ã„メッセージを入力ã—ã¦ãã ã•ã„。
<form name="form">
- <input name="message" type="text"/>
+ <input name="message"/>
<button name="OK" text="OK"/>
<button name="Cancel" text="å–り消ã—"/>
</form>
@@ -1592,9 +1541,9 @@ F1キーを押ã—ã¦ãã ã•ã„。
ナレッジベースを開ãレーティング区分ã«ã¤ã„ã¦å­¦ã³ã¾ã™ã‹ï¼Ÿ
<url name="url">
- http://wiki.secondlife.com/wiki/レーティング区分概è¦_(KB)
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview/ja
</url>
- <usetemplate ignoretext="レーティング区分ã«ã‚ˆã£ã¦åœ°åŸŸï¼ˆãƒªãƒ¼ã‚¸ãƒ§ãƒ³ï¼‰ã«å…¥ã‚Œãªã„ã¨ã" name="okcancelignore" notext="é–‰ã˜ã‚‹" yestext="ナレッジベースを開ã"/>
+ <usetemplate ignoretext="レーティング区分ã®åˆ¶é™ã®ãŸã‚ã€ã“ã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã«å…¥ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“" name="okcancelignore" notext="é–‰ã˜ã‚‹" yestext="ナレッジベースを開ã"/>
</notification>
<notification name="RegionEntryAccessBlocked_Notify">
ã‚ãªãŸã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†ã«ã‚ˆã‚Šã€ãã®åœ°åŸŸï¼ˆãƒªãƒ¼ã‚¸ãƒ§ãƒ³ï¼‰ã¸ã¯å…¥ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
@@ -1602,18 +1551,12 @@ F1キーを押ã—ã¦ãã ã•ã„。
<notification name="RegionEntryAccessBlocked_Change">
ã‚ãªãŸã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†è¨­å®šã«ã‚ˆã‚Šã€ãã®åœ°åŸŸï¼ˆãƒªãƒ¼ã‚¸ãƒ§ãƒ³ï¼‰ã¸ã¯å…¥ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
-「設定を変更ã€ã‚’クリックã™ã‚‹ã¨ã‚ãªãŸã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†ãŒä¸ŠãŒã‚Šã€å…¥ã‚Œã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚ ã‚ãªãŸã¯ä»Šå¾Œ [REGIONMATURITY] コンテンツã®æ¤œç´¢åŠã³ã‚¢ã‚¯ã‚»ã‚¹ãŒå¯èƒ½ã¨ãªã‚Šã¾ã™ã€‚
-ã‚ã¨ã§è¨­å®šã‚’å…ƒã«æˆ»ã—ãŸã„å ´åˆã¯ã€ã€Œç·¨é›†ã€ï¼žã€Œç’°å¢ƒè¨­å®šã€ï¼žã€Œä¸€èˆ¬ã€ã‚’ã”覧ãã ã•ã„。
- <form name="form">
- <button
- name="OK"
- text="設定ã®å¤‰æ›´"/>
- <button
- default="true"
- name="Cancel"
- text="é–‰ã˜ã‚‹"/>
- <ignore name="ignore" text="レーティング区分設定ã«ã‚ˆã£ã¦åœ°åŸŸï¼ˆãƒªãƒ¼ã‚¸ãƒ§ãƒ³ï¼‰ã«å…¥ã‚Œãªã„ã¨ã"/>
- </form>
+「設定を変更ã€ã‚’クリックã—ã¦ã‚ãªãŸã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†ã‚’上ã’ã‚‹ã¨ã€å…¥ã‚Œã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚ ã‚ãªãŸã¯ä»Šå¾Œ [REGIONMATURITY] コンテンツã®æ¤œç´¢åŠã³ã‚¢ã‚¯ã‚»ã‚¹ãŒå¯èƒ½ã¨ãªã‚Šã¾ã™ã€‚ ã‚ã¨ã§è¨­å®šã‚’å…ƒã«æˆ»ã—ãŸã„å ´åˆã¯ã€ã€Œç·¨é›†ã€ï¼žã€Œç’°å¢ƒè¨­å®šã€ã‚’ã”覧ãã ã•ã„。
+ <form name="form">
+ <button name="OK" text="環境設定ã®å¤‰æ›´"/>
+ <button default="true" name="Cancel" text="é–‰ã˜ã‚‹"/>
+ <ignore name="ignore" text="é¸æŠžã—ãŸãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†ãŒåŽŸå› ã§ã€ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã«å…¥ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“"/>
+ </form>
</notification>
<notification name="LandClaimAccessBlocked">
ã‚ãªãŸã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†ã«ã‚ˆã‚Šã€ã“ã®åœŸåœ°ã‚’å–å¾—ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。 年齢を確èªã™ã‚‹éš›ã®æƒ…å ±ã«ä¸è¶³ãŒã‚ã£ãŸãŸã‚ã¨è€ƒãˆã‚‰ã‚Œã¾ã™ã€‚
@@ -1626,9 +1569,9 @@ F1キーを押ã—ã¦ãã ã•ã„。
ナレッジベースを開ãレーティング区分ã«ã¤ã„ã¦å­¦ã³ã¾ã™ã‹ï¼Ÿ
<url name="url">
- http://wiki.secondlife.com/wiki/レーティング区分概è¦_(KB)
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview/ja
</url>
- <usetemplate ignoretext="レーティング区分ã«ã‚ˆã£ã¦åœŸåœ°ã‚’å–å¾—ã§ããªã„ã¨ã" name="okcancelignore" notext="é–‰ã˜ã‚‹" yestext="ナレッジベースを開ã"/>
+ <usetemplate ignoretext="レーティング区分ã®åˆ¶é™ã®ãŸã‚ã€ã“ã®åœŸåœ°ã‚’å–å¾—ã§ãã¾ã›ã‚“" name="okcancelignore" notext="é–‰ã˜ã‚‹" yestext="ナレッジベースを開ã"/>
</notification>
<notification name="LandClaimAccessBlocked_Notify">
ã‚ãªãŸã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†ã«ã‚ˆã‚Šã€ã“ã®åœŸåœ°ã‚’å–å¾—ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
@@ -1636,9 +1579,8 @@ F1キーを押ã—ã¦ãã ã•ã„。
<notification name="LandClaimAccessBlocked_Change">
ã‚ãªãŸã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†è¨­å®šã«ã‚ˆã‚Šã€ã“ã®åœŸåœ°ã‚’å–å¾—ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
-「設定を変更ã€ã‚’クリックã™ã‚‹ã¨ã‚ãªãŸã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†ãŒä¸ŠãŒã‚Šã€å…¥ã‚Œã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚ ã‚ãªãŸã¯ä»Šå¾Œ [REGIONMATURITY] コンテンツã®æ¤œç´¢åŠã³ã‚¢ã‚¯ã‚»ã‚¹ãŒå¯èƒ½ã¨ãªã‚Šã¾ã™ã€‚
-ã‚ã¨ã§è¨­å®šã‚’å…ƒã«æˆ»ã—ãŸã„å ´åˆã¯ã€ã€Œç·¨é›†ã€ï¼žã€Œç’°å¢ƒè¨­å®šã€ï¼žã€Œä¸€èˆ¬ã€ã‚’ã”覧ãã ã•ã„。
- <usetemplate ignoretext="レーティング区分設定ã«ã‚ˆã£ã¦åœŸåœ°ã‚’å–å¾—ã§ããªã„ã¨ã" name="okcancelignore" notext="é–‰ã˜ã‚‹" yestext="設定ã®å¤‰æ›´"/>
+「設定を変更ã€ã‚’クリックã—ã¦ã‚ãªãŸã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†ã‚’上ã’ã‚‹ã¨ã€å…¥ã‚Œã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚ ã‚ãªãŸã¯ä»Šå¾Œ [REGIONMATURITY] コンテンツã®æ¤œç´¢åŠã³ã‚¢ã‚¯ã‚»ã‚¹ãŒå¯èƒ½ã¨ãªã‚Šã¾ã™ã€‚ ã‚ã¨ã§è¨­å®šã‚’å…ƒã«æˆ»ã—ãŸã„å ´åˆã¯ã€ã€Œç·¨é›†ã€ï¼žã€Œç’°å¢ƒè¨­å®šã€ã‚’ã”覧ãã ã•ã„。
+ <usetemplate ignoretext="é¸æŠžã—ãŸãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†ãŒåŽŸå› ã§ã€åœŸåœ°ã‚’å–å¾—ã§ãã¾ã›ã‚“" name="okcancelignore" notext="é–‰ã˜ã‚‹" yestext="設定ã®å¤‰æ›´"/>
</notification>
<notification name="LandBuyAccessBlocked">
ã‚ãªãŸã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†ã«ã‚ˆã‚Šã€ã“ã®åœŸåœ°ã‚’購入ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。 年齢を確èªã™ã‚‹éš›ã®æƒ…å ±ã«ä¸è¶³ãŒã‚ã£ãŸãŸã‚ã¨è€ƒãˆã‚‰ã‚Œã¾ã™ã€‚
@@ -1651,9 +1593,9 @@ F1キーを押ã—ã¦ãã ã•ã„。
ナレッジベースを開ãレーティング区分ã«ã¤ã„ã¦å­¦ã³ã¾ã™ã‹ï¼Ÿ
<url name="url">
- http://wiki.secondlife.com/wiki/レーティング区分概è¦_(KB)
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview/ja
</url>
- <usetemplate ignoretext="レーティング区分ã«ã‚ˆã£ã¦åœŸåœ°ã‚’購入ã§ããªã„ã¨ã" name="okcancelignore" notext="é–‰ã˜ã‚‹" yestext="ナレッジベースを開ã"/>
+ <usetemplate ignoretext="レーティング区分ã®åˆ¶é™ã®ãŸã‚ã€ã“ã®åœŸåœ°ã‚’購入ã§ãã¾ã›ã‚“" name="okcancelignore" notext="é–‰ã˜ã‚‹" yestext="ナレッジベースを開ã"/>
</notification>
<notification name="LandBuyAccessBlocked_Notify">
ã‚ãªãŸã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†ã«ã‚ˆã‚Šã€ã“ã®åœŸåœ°ã‚’購入ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
@@ -1661,14 +1603,12 @@ F1キーを押ã—ã¦ãã ã•ã„。
<notification name="LandBuyAccessBlocked_Change">
ã‚ãªãŸã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†è¨­å®šã«ã‚ˆã‚Šã€ã“ã®åœŸåœ°ã‚’購入ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
-「設定を変更ã€ã‚’クリックã™ã‚‹ã¨ã‚ãªãŸã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†ãŒä¸ŠãŒã‚Šã€å…¥ã‚Œã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚ ã‚ãªãŸã¯ä»Šå¾Œ [REGIONMATURITY] コンテンツã®æ¤œç´¢åŠã³ã‚¢ã‚¯ã‚»ã‚¹ãŒå¯èƒ½ã¨ãªã‚Šã¾ã™ã€‚
-ã‚ã¨ã§è¨­å®šã‚’å…ƒã«æˆ»ã—ãŸã„å ´åˆã¯ã€ã€Œç·¨é›†ã€ï¼žã€Œç’°å¢ƒè¨­å®šã€ï¼žã€Œä¸€èˆ¬ã€ã‚’ã”覧ãã ã•ã„。
- <usetemplate ignoretext="レーティング区分設定ã«ã‚ˆã£ã¦åœŸåœ°ã‚’購入ã§ããªã„ã¨ã" name="okcancelignore" notext="é–‰ã˜ã‚‹" yestext="設定ã®å¤‰æ›´"/>
+「設定を変更ã€ã‚’クリックã—ã¦ã‚ãªãŸã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†ã‚’上ã’ã‚‹ã¨ã€å…¥ã‚Œã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚ ã‚ãªãŸã¯ä»Šå¾Œ [REGIONMATURITY] コンテンツã®æ¤œç´¢åŠã³ã‚¢ã‚¯ã‚»ã‚¹ãŒå¯èƒ½ã¨ãªã‚Šã¾ã™ã€‚ ã‚ã¨ã§è¨­å®šã‚’å…ƒã«æˆ»ã—ãŸã„å ´åˆã¯ã€ã€Œç·¨é›†ã€ï¼žã€Œç’°å¢ƒè¨­å®šã€ã‚’ã”覧ãã ã•ã„。
+ <usetemplate ignoretext="é¸æŠžã—ãŸãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†ãŒåŽŸå› ã§ã€åœŸåœ°ã‚’購入ã§ãã¾ã›ã‚“" name="okcancelignore" notext="é–‰ã˜ã‚‹" yestext="設定ã®å¤‰æ›´"/>
</notification>
<notification name="TooManyPrimsSelected">
- é¸æŠžã—ãŸãƒ—リムãŒå¤šã™ãŽã¾ã™ã€‚
-[MAX_PRIM_COUNT] ã‚’é¸æŠžã™ã‚‹ã‹ã€
-プリム数を減らã—ã¦ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。
+ é¸æŠžã—ãŸãƒ—リムãŒå¤šã™ãŽã¾ã™ã€‚ [MAX_PRIM_COUNT] 個é¸æŠžã™ã‚‹ã‹ã€ãƒ—リム数を減らã—ã¦ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。
+ <usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="ProblemImportingEstateCovenant">
ä¸å‹•ç”£ç´„款ã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆæ™‚ã«å•é¡Œç™ºç”Ÿã€‚
@@ -1684,6 +1624,7 @@ F1キーを押ã—ã¦ãã ã•ã„。
</notification>
<notification name="UnableToLoadNotecardAsset">
ç¾åœ¨ãƒŽãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã®è³‡ç”£IDを読ã¿è¾¼ã‚€ã“ã¨ãŒã§ãã¾ã›ã‚“。
+ <usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="NotAllowedToViewNotecard">
è¦æ±‚ã•ã‚ŒãŸè³‡ç”£IDã«é–¢ã™ã‚‹ãƒŽãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã‚’閲覧ã™ã‚‹ã«ã¯æ¨©é™ãŒä¸å分ã§ã™ã€‚
@@ -1716,321 +1657,17 @@ L$[AMOUNT]ã§ã€ã“ã®ã‚¯ãƒ©ã‚·ãƒ•ã‚¡ã‚¤ãƒ‰åºƒå‘Šã‚’今ã™ã公開ã—ã¾ã™ã‹ï
ã“ã®åœ°åŸŸã«ã„る人全員ã«é€ã‚‹
短ã„メッセージを入力ã—ã¦ãã ã•ã„。
<form name="form">
- <input name="message" type="text"/>
+ <input name="message"/>
<button name="OK" text="OK"/>
<button name="Cancel" text="å–り消ã—"/>
</form>
</notification>
- <notification label="土地整備をブロック" name="HelpRegionBlockTerraform">
- ã“ã®ãƒœãƒƒã‚¯ã‚¹ãŒãƒã‚§ãƒƒã‚¯ã•ã‚Œã¦ã„ã‚‹å ´åˆã€
-区画ã”ã¨ã®ã€Œé ˜åŸŸã‚’編集ã€ã®è¨­å®šã«ã‹ã‹ã‚らãšã€åœŸåœ°ã‚ªãƒ¼ãƒŠãƒ¼ã¯åœŸåœ°æ•´å‚™ãŒã§ãã¾ã›ã‚“。
-
-デフォルト:オフ
- </notification>
- <notification label="飛行をブロック" name="HelpRegionBlockFly">
- ã“ã®ãƒœãƒƒã‚¯ã‚¹ã‚’ãƒã‚§ãƒƒã‚¯ã™ã‚‹ã¨ã€åŒºç”»ã”ã¨ã®ã€Œé£›è¡Œã€è¨­å®šã«é–¢ã‚らãšé£›è¡ŒãŒã§ããªããªã‚Šã¾ã™ã€‚
-
-デフォルト:オフ
- </notification>
- <notification label="コンテンツ権é™ã®ä¸€æ‹¬å¤‰æ›´" name="HelpBulkPermission">
- 権é™ã®ä¸€æ‹¬å¤‰æ›´ãƒ„ールã§ã¯ã€é¸æŠžã—ãŸè¤‡æ•°ã®ã‚¢ã‚¤ãƒ†ãƒ ã®æ¨©é™ã‚’ç´ æ—©ã変更ã™ã‚‹ã“ã¨ãŒå¯èƒ½ã§ã™ã€‚
-ã—ã‹ã—é¸æŠžã—ãŸã‚ªãƒ–ジェクトã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã®ä¸­èº«ã®æ¨©é™è¨­å®šã‚’ã™ã‚‹ã ã‘ã§ã€ã‚ªãƒ–ジェクトãã®ã‚‚ã®ã§ã¯ãªã„ã“ã¨ã«ã”注æ„ãã ã•ã„。
-
-ã¾ãŸã€æ¨©é™ã¯ä¸­ã«ã‚るアイテムã®ãã®ä¸­èº«ã«ã¯é©ç”¨ã•ã‚Œãªã„ã“ã¨ã‚‚ã”注æ„ãã ã•ã„。 1段階層ã®ã‚¢ã‚¤ãƒ†ãƒ ã®ã¿ã¸ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¨ãªã‚Šã¾ã™ã€‚
-
-「コンテンツã®ç¨®é¡žã€ã«ã‚ã‚‹ãƒã‚§ãƒƒã‚¯ãƒªã‚¹ãƒˆã‚’使ã£ã¦ã€ä¿®æ­£ã™ã‚‹ã‚¢ã‚¤ãƒ†ãƒ ã®ç¨®é¡žã‚’é¸æŠžã—ã¾ã™ã€‚ テクスãƒãƒ£ãƒ¼ã‚’é¸æŠžã™ã‚‹ã¨ã€ã‚¹ãƒŠãƒƒãƒ—ショットもå«ã¾ã‚Œã¾ã™ã€‚
-
-* ã“ã®ãƒ„ールã®ä½¿ç”¨ã¯ã€
-ã‚ãªãŸãŒå¤‰æ›´ã™ã‚‹ã“ã¨ã®ã§ãるアイテムã«ã®ã¿æœ‰åŠ¹ã§ã™ã€‚
-* 次ã®ã‚ªãƒ¼ãƒŠãƒ¼ã®æ¨©é™ãŒã‚ãªãŸã«ãªã„å ´åˆã¯ã€é©ç”¨ã•ã‚Œã¾ã›ã‚“。
-* 次ã®ã‚ªãƒ¼ãƒŠãƒ¼ã®æ¨©é™ã¯å˜ã«ãƒªã‚¯ã‚¨ã‚¹ãƒˆã«ã™ãŽã¾ã›ã‚“。 ã©ã‚Œã‹ä¸€ã¤ã®ã‚¢ã‚¤ãƒ†ãƒ ã§ã‚‚æ–°ã—ã„権é™ã®è¨­å®šã‚’å—ã‘付ã‘ãªã„å ´åˆã€ã™ã¹ã¦ã®æ¨©é™ã®è¨­å®šã¯ãã®ã¾ã¾ç¶­æŒã•ã‚Œã¾ã™ã€‚
-
-一括変更ã®æº–å‚™ãŒã§ããŸã‚‰ã€ã€Œé©ç”¨ã€ã‚’クリックã—ã¦çµæžœãŒè¡¨ç¤ºã•ã‚Œã‚‹ã®ã‚’ãŠå¾…ã¡ãã ã•ã„。
-
-権é™å¤‰æ›´ä¸­ã«æ¨©é™ã®ä¸€æ‹¬å¤‰æ›´ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’é–‰ã˜ãŸå ´åˆã€å‡¦ç†ã¯åœæ­¢ã•ã‚Œã¾ã™ã€‚
- </notification>
- <notification label="ダメージ許å¯" name="HelpRegionAllowDamage">
- ã“ã®ãƒœãƒƒã‚¯ã‚¹ã‚’ãƒã‚§ãƒƒã‚¯ã™ã‚‹ã¨ã€
-å„区画ã®å€‹åˆ¥ã®è¨­å®šã«ã‹ã‹ã‚らãšã€å…¨ã¦ã®åŒºç”»ã«ãŠã‘るヘルスシステムを有効ã«ã—ã¾ã™ã€‚
-ã“ã®ãƒœãƒƒã‚¯ã‚¹ãŒãƒã‚§ãƒƒã‚¯ã•ã‚Œã¦ã„ãªã„å ´åˆã§ã‚‚ã€
-個別ã®åŒºç”»ã®ã‚ªãƒ¼ãƒŠãƒ¼ã¯ã€è‡ªåˆ†ã®åŒºç”»ã«å¯¾ã™ã‚‹ãƒ˜ãƒ«ã‚¹ã‚·ã‚¹ãƒ†ãƒ ã‚’有効ã«ã§ãã¾ã™ã€‚
-
-デフォルト: オフ
- </notification>
- <notification label="人物ã®åˆ¶é™" name="HelpRegionAgentLimit">
- ã“ã®åœ°åŸŸã«è¨±å¯ã•ã‚Œã‚‹ã‚¢ãƒã‚¿ãƒ¼ã®æœ€å¤§æ•°ã‚’設定ã—ã¾ã™ã€‚
-1ã¤ã®åœ°åŸŸã«ã‚¢ãƒã‚¿ãƒ¼ãŒå¤šã„ã¨ãƒ‘フォーマンスãŒ
-低下ã™ã‚‹åŽŸå› ã«ãªã‚‹ã®ã§æ³¨æ„ã—ã¦ãã ã•ã„。
-
-デフォルト: 40
- </notification>
- <notification label="物体ボーナス" name="HelpRegionObjectBonus">
- オブジェクトボーナスã¯ã€åŒºç”»ã«ãŠã„ã¦è¨±å¯ã•ã‚Œã¦ã„るプリムã®å€çŽ‡æ•°ã‚’æ„味ã—ã¾ã™ã€‚
-èªå¯ã•ã‚Œã¦ã„る範囲ã¯1ã‹ã‚‰10ã§ã™ã€‚
-ã—ãŸãŒã£ã¦ã€ã€Œ1ã€ã«è¨­å®šã™ã‚‹ã¨ã€512 m²ã®åœŸåœ°ã«ã¯ã€117ã®ã‚ªãƒ–ジェクトãŒè¨±å¯ã•ã‚Œã¾ã™ã€‚
-「2ã€ã«è¨­å®šã™ã‚‹ã¨ã€åŒã˜512 m²ã®åœŸåœ°ã«ã¯ã€1ã®ã¨ãã®2å€ã«ã‚ãŸã‚‹234ã®ã‚ªãƒ–ジェクトãŒè¨±å¯ã•ã‚Œã€3以é™ã‚‚åŒæ§˜ã«å¢—ãˆã¦ã„ãã¾ã™ã€‚
-全地域ã®æœ€é«˜ã‚ªãƒ–ジェクト数ã¯ã€ã‚ªãƒ–ジェクトボーナスã®å€¤ã«å½±éŸ¿ã•ã‚Œãšã€
-15,000ã®ã¾ã¾å¤‰ã‚ã‚Šã¾ã›ã‚“。
-ã„ã£ãŸã‚“決定ã—ãŸå¾Œã§ã‚ªãƒ–ジェクトボーナスã®å€¤ã‚’下ã’ã‚‹ã¨ã€ã‚ªãƒ–ジェクトãŒè¿”å´ã¾ãŸã¯å‰Šé™¤ã•ã‚Œã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã®ã§ã”注æ„ãã ã•ã„。
-ディフォルト: 1.0
- </notification>
- <notification label="レーティング区分" name="HelpRegionMaturity">
- ä½äººã®ãƒ“ューワ上部ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ãƒãƒ¼ã«è¡¨ç¤ºã•ã‚Œã‚‹ã€åœ°åŸŸï¼ˆãƒªãƒ¼ã‚¸ãƒ§ãƒ³ï¼‰ã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†ã‚’設定ã—ã¾ã™ã€‚
-世界地図上ã§ã‚«ãƒ¼ã‚½ãƒ«ã‚’ã“ã®åœ°åŸŸã«ä¹—ã›ã‚‹ã¨ãƒ„ールãƒãƒƒãƒ—ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
-ã“ã®è¨­å®šã¯ã“ã®åœ°åŸŸå…¨ä½“ã¨æ¤œç´¢çµæžœã«å映ã•ã‚Œã¾ã™ã€‚
-ä»–ã®ä½äººã¯ç’°å¢ƒè¨­å®šã§é¸æŠžã—ãŸãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†ã«åˆã£ãŸåœ°åŸŸã«å…¥ã‚‹ã“ã¨ãŒã§ãã€æ¤œç´¢çµæžœã‚’見るã“ã¨ãŒã§ãã¾ã™ã€‚
-
-地図ã«ã“ã®å¤‰æ›´ãŒå映ã™ã‚‹ã«ã¯æ•°åˆ†ã‹ã‹ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚
- </notification>
- <notification label="プッシュを制é™" name="HelpRegionRestrictPushObject">
- ã“ã®ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹ã¯ã€åˆ¶é™ã•ã‚ŒãŸãƒ—ッシュ権é™ã‚’全地域ã«é©ç”¨ã—ã¾ã™ã€‚
-有効ã«ãªã£ã¦ã„ã‚‹å ´åˆã€ä½äººã¯è‡ªåˆ†è‡ªèº«ã§ã®ãƒ—ッシュã€
-ã‚ã‚‹ã„ã¯åŒºç”»ã®æ‰€æœ‰è€…ã«ã‚ˆã‚‹ãƒ—ッシュã ã‘ã«åˆ¶é™ã§ãã¾ã™ã€‚
-(プッシュã¯ã€LSLã® llPushObject() 機能をå‚ç…§ã—ã¾ã™ã€‚)
-
-デフォルト: オフ
- </notification>
- <notification label="区画統åˆï¼å†åˆ†å‰²" name="HelpParcelChanges">
- ã“ã®ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹ã¯ã€ä¸å‹•ç”£ã‚ªãƒ¼ãƒŠãƒ¼ãŒæ‰€æœ‰ã—ã¦ã„ãªã„区画を統åˆã¾ãŸã¯å†åˆ†å‰²ã§ãã‚‹ã‹ã©ã†ã‹ã‚’設定ã—ã¾ã™ã€‚
-本オプションãŒç„¡åŠ¹ãªå ´åˆï¼š
-*ä¸å‹•ç”£ã‚ªãƒ¼ãƒŠãƒ¼ã€ã¾ãŸã¯ç®¡ç†è€…ã®ã¿ãŒã€çµ±åˆï¼å†åˆ†å‰²ã‚’è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚
-*オーナーã€ã¾ãŸã¯ã€é©åˆ‡ãªæ¨©é™ã‚’æŒã¤ã‚°ãƒ«ãƒ¼ãƒ—ã«å±žã™ã‚‹åŒºç”»ã®ã¿ã‚’
-çµ±åˆï¼å†åˆ†å‰²ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
-本オプションãŒæœ‰åŠ¹ãªå ´åˆï¼š
-*å…¨ã¦ã®åŒºç”»ã‚ªãƒ¼ãƒŠãƒ¼ã¯ã€æ‰€æœ‰ã™ã‚‹åŒºç”»ã®çµ±åˆï¼å†åˆ†å‰²ãŒã§ãã¾ã™ã€‚
-*グループ所有ã®åŒºç”»ã¯ã€é©åˆ‡ãªæ¨©é™ã‚’æŒã¤ã‚°ãƒ«ãƒ¼ãƒ—ã«å±žã™ã‚‹åŒºç”»ã‚’çµ±åˆï¼å†åˆ†å‰²ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
-
-デフォルト:ãƒã‚§ãƒƒã‚¯ã‚ã‚Š
- </notification>
- <notification label="検索ã§è¡¨ç¤ºã—ãªã„" name="HelpRegionSearch">
- ã“ã®ãƒœãƒƒã‚¯ã‚¹ã‚’ãƒã‚§ãƒƒã‚¯ã™ã‚‹ã¨ã€åŒºç”»ã®ã‚ªãƒ¼ãƒŠãƒ¼ã¯ã€è‡ªåˆ†ã®åŒºç”»ãŒæ¤œç´¢çµæžœã«ãƒªã‚¹ãƒˆã•ã‚Œã‚‹ã“ã¨ã‚’阻止ã§ãã¾ã™ã€‚
-デフォルト:オフ
- </notification>
<notification label="地域ã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†æŒ‡å®šå¤‰æ›´æ¸ˆã¿" name="RegionMaturityChange">
ã“ã®åœ°åŸŸã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†æŒ‡å®šãŒã‚¢ãƒƒãƒ—デートã•ã‚Œã¾ã—ãŸã€‚
ã“ã®å¤‰æ›´ãŒåœ°å›³ã«å映ã•ã‚Œã‚‹ã¾ã§ã«ã¯ã—ã°ã‚‰ã時間ãŒã‹ã‹ã‚Šã¾ã™ã€‚
</notification>
- <notification label="土地ã®å†è²©" name="HelpRegionLandResell">
- ä¸å‹•ç”£ã®ã‚ªãƒ¼ãƒŠãƒ¼ã¨ç®¡ç†è€…ã¯ã€ä¸å‹•ç”£ã‚ªãƒ¼ãƒŠãƒ¼ã®åœŸåœ°ã‚’販売ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
-ã“ã®ã‚ªãƒ—ションをãƒã‚§ãƒƒã‚¯ã—ãªã„å ´åˆã€è³¼å…¥è€…ãŒæœ¬åœ°åŸŸã«ãŠã‘る土地をå†è²©ã™ã‚‹ã“ã¨ã¯ã§ããªããªã‚Šã¾ã™ã€‚
-ã“ã®ã‚ªãƒ—ションをãƒã‚§ãƒƒã‚¯ã—ãŸå ´åˆã€è³¼å…¥è€…ã¯æœ¬åœ°åŸŸã«ãŠã‘る土地をå†è²©ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
-
-デフォルト:許å¯ã—ãªã„
- </notification>
- <notification label="スクリプトを無効化" name="HelpRegionDisableScripts">
- スクリプトãŒåŽŸå› ã§ã‚·ãƒ ã®çŠ¶æ³ãŒæ‚ªããªã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚
-統計グラフをã ã—ã¦ï¼ˆCtrl-Shift-1)ã€
-シミュレーターフィジックスFPSを見ã¦ãã ã•ã„。
-45より数ãŒä½Žã‘ã‚Œã°ã€ä¸€ç•ªä¸‹ã«ä½ç½®ã—ã¦ã„るタイムパãƒãƒ«ã‚’é–‹ã„ã¦ãã ã•ã„。
-スクリプト時間ãŒ25ms以上ã§ã‚ã‚Œã°ã€
-「トップスクリプトをå–å¾—ã€ãƒœã‚¿ãƒ³ã‚’クリックã—ã¾ã™ã€‚
-悪影響をåŠã¼ã—ã¦ã„るスクリプトã®åå‰ã¨ä½ç½®ãŒç¾ã‚Œã¾ã™ã€‚
-
-「スクリプトを無効ã«ã™ã‚‹ã€ã‚’ãƒã‚§ãƒƒã‚¯ã—「é©ç”¨ã€ã‚’クリックã™ã‚‹ã¨ã€åœ°åŸŸå†…ã®å…¨ã¦ã®ã‚¹ã‚¯ãƒªãƒ—トãŒä¸€æ™‚çš„ã«ç„¡åŠ¹ã«ãªã‚Šã¾ã™ã€‚
-トップスクリプトã§æ¤œç´¢ã—ãŸã‚¹ã‚¯ãƒªãƒ—トã®ä½ç½®ã¾ã§åˆ°é”ã™ã‚‹ã«ã¯ã€
-ã“ã®ã‚¹ãƒ†ãƒƒãƒ—ãŒå¿…è¦ã«ãªã‚‹å ´åˆã‚‚ã‚ã‚Šã¾ã™ã€‚
-スクリプトä½ç½®ã«åˆ°ç€å¾Œã€ã‚¹ã‚¯ãƒªãƒ—トを見ã¦æ‚ªå½±éŸ¿ã‚’与ãˆã¦ã„ã‚‹ã‹èª¿æŸ»ã—ã¦ãã ã•ã„。
-スクリプトã®æ‰€æœ‰è€…ã«é€£çµ¡ã™ã‚‹ã‹ã€ã‚ã‚‹ã„ã¯ã‚ªãƒ–ジェクトã®å‰Šé™¤ã¾ãŸã¯è¿”å´ã‚‚考ãˆã‚‰ã‚Œã¾ã™ã€‚
-「スクリプトを無効ã«ã™ã‚‹ã€ã®ãƒã‚§ãƒƒã‚¯ã‚’外ã—ã€ã€Œé©ç”¨ã€ã‚’クリックã—ã¦åœ°åŸŸå…¨ä½“ã®ã‚¹ã‚¯ãƒªãƒ—トを有効ã«æˆ»ã—ã¦ãã ã•ã„。
-
-デフォルト:オフ
- </notification>
- <notification label="è¡çªã‚’無効化" name="HelpRegionDisableCollisions">
- 物ç†çš„オブジェクトãŒåŽŸå› ã§ã€
-シムã®å‡¦ç†ãŒé‡ããªã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚
-統計グラフを開ã„ã¦ï¼ˆCtrl-Shift-1)ã€
-シミュレーターフィジックスFPSを見ã¦ãã ã•ã„。
-数値ãŒ45より低ã‘ã‚Œã°ã€çµ±è¨ˆãƒãƒ¼ã®ä¸‹ã«ä½ç½®ã—ã¦ã„るタイムパãƒãƒ«ã‚’é–‹ã„ã¦ãã ã•ã„。
-ã‚‚ã—シムタイム(物ç†çš„作用)ãŒ20 msより長ã„å ´åˆã¯ã€
-「トップ・コライダーをå–å¾—ã€ã‚’クリックã—ã¦ãã ã•ã„。
-悪影響をåŠã¼ã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚る物ç†ã‚ªãƒ–ジェクトã®åå‰ã¨ä½ç½®ãŒç¾ã‚Œã¾ã™ã€‚
-
-「è¡çªã‚’無効ã«ã™ã‚‹ã€ã‚’ãƒã‚§ãƒƒã‚¯ã—「é©ç”¨ã€ã‚’クリックã™ã‚‹ã¨ã€
-オブジェクトåŒå£«ã®è¡çªãŒä¸€æ™‚çš„ã«ç„¡åŠ¹ã«ãªã‚Šã¾ã™ã€‚
-当該ã®ãƒˆãƒƒãƒ—・コライダーã®ä½ç½®ã¾ã§åˆ°é”ã™ã‚‹ã«ã¯
-上記ã®ã‚¹ãƒ†ãƒƒãƒ—ãŒå¿…è¦ã«ãªã‚‹å ´åˆã‚‚ã‚ã‚Šã¾ã™ã€‚
-到ç€å¾Œã€ã‚ªãƒ–ジェクトを見ã¦å¸¸æ™‚ä»–ã®ã‚ªãƒ–ジェクトã¨è¡çªã—ã¦ã„ã‚‹ã‹èª¿æŸ»ã—ã¦ãã ã•ã„。
-オブジェクトã®æ‰€æœ‰è€…ã«é€£çµ¡ã™ã‚‹ã‹ã€ã‚ã‚‹ã„ã¯ã‚ªãƒ–ジェクトã®å‰Šé™¤ã¾ãŸã¯è¿”å´ã‚’考慮ã™ã¹ãã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。
-「è¡çªã‚’無効ã«ã™ã‚‹ã€ã®ãƒã‚§ãƒƒã‚¯ã‚’外ã—ã€ã€Œé©ç”¨ã€ã‚’クリックã—ã¦
-地域全体ã®è¡çªã‚’有効ã«æˆ»ã—ã¦ãã ã•ã„。
-
-デフォルト:オフ
- </notification>
- <notification label="物ç†ä½œç”¨ã‚’無効化" name="HelpRegionDisablePhysics">
- 物ç†çš„作用を無効ã«ã™ã‚‹ã“ã¨ã¯ã€ç‰©ç†çš„シミュレーション全ã¦ã®ç„¡åŠ¹ã‚’除ã„ã¦ã€è¡çªã‚’無効ã«ã™ã‚‹ã“ã¨ã¨ä¼¼ã¦ã„ã¾ã™ã€‚
-ã“ã‚Œã¯ã€ã‚ªãƒ–ジェクトã®è¡çªã‚’æ­¢ã‚ã‚‹ã®ã¿ãªã‚‰ãšã€ã‚¢ãƒã‚¿ãƒ¼ã®ç§»å‹•ãŒã§ããªããªã‚‹ã“ã¨ã‚’æ„味ã—ã¾ã™ã€‚
-
-ã“ã®æ©Ÿèƒ½ã¯ã€ç‰©ç†çš„ãªå•é¡Œãªã®ã‹ã€ã¾ãŸã¯ãƒˆãƒƒãƒ—・コライダーãªã®ã‹ã‚’調査ã™ã‚‹ã«ã‚ãŸã‚Šã€è¡çªã®ç„¡åŠ¹ãŒåœ°åŸŸã«å¯¾ã—ã¦å分ãªãƒ‘フォーマンスを発æ®ã—ãªã„å ´åˆã«ã®ã¿ä½¿ç”¨ã—ã¦ãã ã•ã„。
-
-終了ã™ã‚‹æ™‚ã«ã¯ã€ç‰©ç†çš„作用をå†åº¦å¯èƒ½ã«è¨­å®šã—ã¦ãã ã•ã„。
-ãã®ã¾ã¾ã ã¨ã€ã‚¢ãƒã‚¿ãƒ¼ã¯ãšã£ã¨å‹•ã‘ã¾ã›ã‚“。
-
-デフォルト:オフ
- </notification>
- <notification label="トップ・コライダー" name="HelpRegionTopColliders">
- オブジェクトåŒå£«ã®è¡çªãŒæœ€ã‚‚多ã„å¯èƒ½æ€§ã®ã‚ã‚‹
-オブジェクトã®ãƒªã‚¹ãƒˆã‚’表示ã—ã¾ã™ã€‚ã“れらã®ã‚ªãƒ–ジェクトã¯ã€
-パフォーマンスを低下ã•ã›ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
-ビューã‹ã‚‰çµ±è¨ˆãƒãƒ¼ã‚’é¸æŠžã—ã€
-シミュレータ>時間>シム時間 (物ç†çš„作用) ã§ã€
-物ç†çš„作用ã«20 ms以上を費ã—ã¦ã„ã‚‹ã‹ã‚’確èªã—ã¦ãã ã•ã„。
- </notification>
- <notification label="トップ・スクリプト" name="HelpRegionTopScripts">
- LSLスクリプトã®å®Ÿè¡Œã«ä¸€ç•ªæ™‚間を費やã—ã¦ã„るオブジェクトã®ãƒªã‚¹ãƒˆã‚’入手ã—ã¾ã™ã€‚
-ã“れらã®ã‚ªãƒ–ジェクトã¯ã€ãƒ‘フォーマンスを低下ã•ã›ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
-ビューã‹ã‚‰çµ±è¨ˆãƒãƒ¼ã‚’é¸æŠžã—ã€
-ミュレータ>時間>スクリプト時間ã§ã€
-スクリプトã«25 ms以上を費ã—ã¦ã„ã‚‹ã‹ã‚’確èªã—ã¦ãã ã•ã„。
- </notification>
- <notification label="地域をå†èµ·å‹•" name="HelpRegionRestart">
- 2分後ã«ã‚µãƒ¼ãƒãƒ¼ãŒå†èµ·å‹•ã•ã‚Œã‚‹ã¨ã„ã†è­¦å‘Šãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã®å¾Œã«ã€
-ã“ã®åœ°åŸŸã®ã‚µãƒ¼ãƒãƒ¼ãƒ—ロセスをå†èµ·å‹•ã—ã¾ã™ã€‚
-ã“ã®åœ°åŸŸã®ã™ã¹ã¦ã®ä½äººã®æŽ¥ç¶šãŒåˆ‡æ–­ã•ã‚Œã¾ã™ã€‚
-地域ã®ãƒ‡ãƒ¼ã‚¿ã¯ä¿å­˜ã•ã‚Œã€90秒以内ã«å›žå¾©ã—ã¾ã™ã€‚
-
-ã“ã®åœ°åŸŸã‚’å†èµ·å‹•ã—ã¦ã‚‚ã€ã»ã¨ã‚“ã©ã®ãƒ‘フォーマンスã®å•é¡Œã«å¤‰åŒ–ã¯ã‚ã‚Šã¾ã›ã‚“。
-指示ã•ã‚ŒãŸæ™‚ã ã‘利用ã—ã¦ãã ã•ã„。
- </notification>
- <notification label="æ°´é¢ã®é«˜ã•" name="HelpRegionWaterHeight">
- ã“ã‚Œã¯ã€æ°´ãŒç¾ã‚Œã‚‹é«˜ã•ï¼ˆå˜ä½ï¼šãƒ¡ãƒ¼ãƒˆãƒ«ï¼‰ã§ã™ã€‚
-ã“ã®è¨­å®šãŒ20以外ã§ã€æ°´ãŒä¸–ç•Œã®
-端やã€ã€Œç©ºã®ã€æ°´ã«è¿‘ã‘ã‚Œã°ã€
-æºãŒè¦‹ãˆã‚‹ã§ã—ょã†ã€‚
-
-デフォルト: 20
- </notification>
- <notification label="地形ã®ä¸Šæ˜‡" name="HelpRegionTerrainRaise">
- ã“ã®æ•°å€¤ã¯ã€ã€Œãƒ™ãƒ¼ã‚¯ã€åœ°å½¢ã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®é«˜ã•ä»¥ä¸Šã«ã€
-区画所有者ãŒåœŸåœ°ã‚’上ã’ã‚‹ã“ã¨ã®ã§ãるメートル値ã§ã™ã€‚
-
-デフォルト: 4
- </notification>
- <notification label="地形ã®ä¸‹é™" name="HelpRegionTerrainLower">
- ã“ã®æ•°å€¤ã¯ã€ã€Œãƒ™ãƒ¼ã‚¯ã€åœ°å½¢ã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®é«˜ã•ä»¥ä¸‹ã«ã€
-区画所有者ãŒåœŸåœ°ã‚’下ã’られるメートル値ã§ã™ã€‚
-
-デフォルト: -4
- </notification>
- <notification label="RAW地形をアップロード" name="HelpRegionUploadRaw">
- ã“ã®ãƒœã‚¿ãƒ³ã‚’使ã£ã¦ã€.RAW ファイルを
-ç¾åœ¨ã‚ãªãŸãŒå±…る地域ã«ã‚¢ãƒƒãƒ—ロードã—ã¾ã™ã€‚
-ファイルãŒå¿…ãšæ­£ã—ã„サイズã®256x256ã€RGBã€
-ã¾ãŸã€ãƒãƒ£ãƒ³ãƒãƒ«æ•°ãŒ13ã§ã‚ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。
-地形(Terrain) ファイルを作æˆã™ã‚‹æœ€è‰¯ã®æ–¹æ³•ã¯ã€
-既存ã®RAWファイルをダウンロードã™ã‚‹ã“ã¨ã§ã™ã€‚
-ã¾ãšæœ€åˆã®ãƒãƒ£ãƒ³ãƒãƒ«ï¼ˆåœŸåœ°ã®é«˜ã•ï¼‰ã‚’変更ã—ã€
-アップロードã™ã‚‹ã“ã¨ã‹ã‚‰å§‹ã‚られã¾ã™ã€‚
-
-アップロードã«ã¯45秒ã»ã©ã‹ã‹ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚
-ã“ã“ã§æ³¨æ„ã™ã‚‹ã“ã¨ã¯ã€åœ°å½¢ãƒ•ã‚¡ã‚¤ãƒ«ã®ã‚¢ãƒƒãƒ—ロードã«ã‚ˆã£ã¦ã€åœŸåœ°ã«é…ç½®ã•ã‚Œã¦ã„るオブジェクトã¯ã€Œå‹•ã‹ãªã„ã€ã¨ã„ã†ã“ã¨ã§ã™ã€‚
-影響ãŒã‚ã‚‹ã®ã¯ã€åœ°å½¢è‡ªä½“ã¨ã€åœŸåœ°ã«é–¢ä¿‚ã™ã‚‹è¨±å¯ã®ã¿ã§ã™ã€‚
-よã£ã¦ã€ã‚ªãƒ–ジェクトãŒåœ°ä¸‹ã«åŸ‹ã¾ã£ã¦ã—ã¾ã†ã“ã¨ãŒã‚ã‚‹ã®ã§ã”注æ„ãã ã•ã„。
-
-地形設定編集ã®æƒ…å ±ã¨è©³ç´°ã«ã¤ã„ã¦ã¯ã€F1ヘルプをã”覧ãã ã•ã„。
- </notification>
- <notification label="RAW地形をダウンロード" name="HelpRegionDownloadRaw">
- ã“ã®ãƒœã‚¿ãƒ³ã‚’押ã™ã¨ã€æ¨™é«˜ãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰ãƒ‡ãƒ¼ã‚¿ã€
-区画寸法ã€å£²ã‚Šå‡ºã—区画ステータスã€ã“ã®åœ°åŸŸã«ãŠã‘る許å¯ã‚’
-å«ã‚€ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ダウンロードã—ã¾ã™ã€‚フォトショップã®ã‚ˆã†ãªãƒ—ログラムã§ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é–‹ãã«ã¯ã€
-以下ã®ã‚ˆã†ãªãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ï¼š
-RGBã€256x256ã§ã€ãƒãƒ£ãƒ³ãƒãƒ«æ•°ãŒ13
-ã“ã®åœ°å½¢ãƒ•ã‚¡ã‚¤ãƒ«ã¯ã€ä»–ã®æ–¹æ³•ã§ã¯é–‹ãã“ã¨ã¯ã§ãã¾ã›ã‚“。
-
-地形ã«ãŠã‘る標高フィールドã®ç·¨é›†ã«é–¢ã™ã‚‹è©³ç´°ã«ã¤ã„ã¦ã¯ã€F1ヘルプをã”覧ãã ã•ã„。
- </notification>
- <notification label="ä¸å‹•ç”£ã®å¤ªé™½ã‚’使用" name="HelpRegionUseEstateSun">
- ã“ã®ãƒœãƒƒã‚¯ã‚¹ãŒãƒã‚§ãƒƒã‚¯ã•ã‚Œã¦ã„ã‚‹ã¨ã€ã“ã®åœ°åŸŸã®å¤ªé™½ã¯
-ä¸å‹•ç”£ã®ä»–ã®å ´æ‰€ã«ãŠã‘る太陽ã¨ä½ç½®ãŒåŒã˜ã«ãªã‚Šã¾ã™ã€‚
-
-デフォルト: オン
- </notification>
- <notification label="太陽固定" name="HelpRegionFixedSun">
- ã“ã®ãƒœãƒƒã‚¯ã‚¹ã‚’ãƒã‚§ãƒƒã‚¯ã™ã‚‹ã¨ã€å¤ªé™½ã®ä½ç½®ã¯æ®µéšŽã‚¹ãƒ©ã‚¤ãƒ€ãƒ¼å†…ã«
-設定ã•ã‚Œã€å‹•ã‹ãªããªã‚Šã¾ã™ã€‚
-デフォルト: オフ
- </notification>
- <notification label="地形を構築ã™ã‚‹" name="HelpRegionBakeTerrain">
- ã“ã®ãƒœã‚¿ãƒ³ã«ã‚ˆã‚Šã€ç¾åœ¨ã®åœ°å½¢ã®å½¢çŠ¶ã‚’æ–°ãŸãªãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã¨ã—ã¦ä¿å­˜ã—ã¾ã™ã€‚
-一度ベークã•ã‚Œã‚‹ã¨ã€ã‚ãªãŸã‚„ä»–ã®äººãŒåœ°å½¢ç·¨é›†ã®ã€Œå¾©å¸°ã€ã‚ªãƒ—ションï¼ãƒ„ールを使用ã—ãŸéš›ã«ã€ä¿å­˜ã•ã‚ŒãŸå½¢çŠ¶ã«å›žå¾©ã§ãã¾ã™ã€‚
-ベークã•ã‚ŒãŸåœ°å½¢ã¯ã€åœ°å½¢ä¸Šæ˜‡ãŠã‚ˆã³ä¸‹é™å¢ƒç•Œã®ä¸­é–“点ã§ã‚‚ã‚ã‚Šã¾ã™ã€‚
- </notification>
- <notification label="ä¸å‹•ç”£ãƒžãƒãƒ¼ã‚¸ãƒ£ãƒ¼" name="HelpEstateEstateManager">
- ä¸å‹•ç”£ãƒžãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã¨ã¯ã€åœ°åŸŸã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«ã¨
-ä¸å‹•ç”£è¨­å®šãŒå§”ä»»ã•ã‚ŒãŸä½äººã‚’ã•ã—ã¾ã™ã€‚ä¸å‹•ç”£ãƒžãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã¯ã€
-アップロードã€ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã€ãŠã‚ˆã³åœ°å½¢æ§‹ç¯‰ã‚’除ã„ãŸãƒ‘ãƒãƒ«å†…ã®
-設定を変更ã§ãã¾ã™ã€‚特筆ã™ã¹ãã¯ã€
-ä½äººã®ã‚¢ã‚¯ã‚»ã‚¹è¨±å¯ã¾ãŸã¯ç¦æ­¢ã®è¨­å®šãŒã§ãã‚‹ã“ã¨ã§ã™ã€‚
-
-ä¸å‹•ç”£ãƒžãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã®è¿½åŠ ã¨å‰Šé™¤ã¯ã€ä¸å‹•ç”£ã‚ªãƒ¼ãƒŠãƒ¼ã®ã¿ãŒè¡Œã†ã“ã¨ãŒã§ãã€ãƒžãƒãƒ¼ã‚¸ãƒ£ãƒ¼åŒå£«ã§ã¯ä¸å¯èƒ½ã§ã™ã€‚
-ä¿¡é ¼ã§ãã‚‹ä½äººã®ã¿ä¸å‹•ç”£ãƒžãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã«ä»»å‘½ã—ã¦ãã ã•ã„。
-彼らã®è¡Œå‹•ã®å…¨è²¬ä»»ã¯ã€æœ€çµ‚çš„ã«ã¯ã‚ãªãŸã«ã‚ã‚Šã¾ã™ã€‚
- </notification>
- <notification label="グローãƒãƒ«ãƒ»ã‚¿ã‚¤ãƒ ã‚’使用" name="HelpEstateUseGlobalTime">
- ã“ã®ãƒœãƒƒã‚¯ã‚¹ãŒãƒã‚§ãƒƒã‚¯ã•ã‚Œã¦ã„ã‚‹ã¨ã€
-ã‚ãªãŸã®æ‰€æœ‰åœ°ã®å¤ªé™½ã¯Linden社所有ã®ãƒ¡ã‚¤ãƒ³ãƒ©ãƒ³ãƒ‰ã®ä¸å‹•ç”£ã§ã®å¤ªé™½ã®ä½ç½®ã«æº–ã˜ã¾ã™ã€‚
-
-デフォルト: オン
- </notification>
- <notification label="太陽固定" name="HelpEstateFixedSun">
- ã“ã®ãƒœãƒƒã‚¯ã‚¹ãŒãƒã‚§ãƒƒã‚¯ã•ã‚Œã¦ã„ã‚‹ã¨ã€
-太陽ã®ä½ç½®ã¯æ®µéšŽã‚¹ãƒ©ã‚¤ãƒ€ãƒ¼å†…ã«è¨­å®šã•ã‚Œã€å‹•ã‹ãªããªã‚Šã¾ã™ã€‚
- </notification>
- <notification label="パブリック・アクセス" name="HelpEstateExternallyVisible">
- ã“ã®ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹ã¯ã€
-ä»–ã®ä¸å‹•ç”£ã«ã„ã‚‹ä½äººãŒã€ã‚¢ã‚¯ã‚»ã‚¹ãƒªã‚¹ãƒˆã«ç™»éŒ²ã•ã‚Œã¦ã„ãªãã¦ã‚‚ã“ã®ä¸å‹•ç”£ã«ç«‹ã¡å…¥ã‚‹ã“ã¨ãŒã§ãã‚‹ã‹ã©ã†ã‹ã‚’設定ã—ã¾ã™ã€‚
-
-デフォルト: オン
- </notification>
- <notification label="直接テレãƒãƒ¼ãƒˆã‚’許å¯" name="HelpEstateAllowDirectTeleport">
- ãƒã‚§ãƒƒã‚¯ã•ã‚Œã¦ã„ã‚‹ã¨ã€ä¸å‹•ç”£ã®ã©ã“ã«ã§ã‚‚直接テレãƒãƒ¼ãƒˆãŒ
-å¯èƒ½ã«ãªã‚Šã¾ã™ã€‚ãƒã‚§ãƒƒã‚¯ã•ã‚Œã¦ã„ãªã„ã¨ã€æœ€ã‚‚è¿‘ã„テレãƒãƒ–ã«
-テレãƒãƒ¼ãƒˆã—ã¾ã™ã€‚
-
-デフォルト: オフ
- </notification>
- <notification label="アクセスを許å¯" name="HelpEstateAllowResident">
- ã“ã®ä¸å‹•ç”£ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã¯ã€ã“ã“ã«ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹ä½äººã¨
-下記ã§ç‰¹åˆ¥ã«ç™»éŒ²ã•ã‚ŒãŸã‚°ãƒ«ãƒ¼ãƒ—ã®ã¿ã«è¨±å¯ã•ã‚Œã¾ã™ã€‚
-ã“ã®è¨­å®šã¯ã€Œãƒ‘ブリック・アクセスã€ãŒã‚ªãƒ•ã«ãªã£ã¦ã‚‹ã¨ãã®ã¿ä½¿ç”¨å¯èƒ½ã§ã™ã€‚
- </notification>
- <notification label="グループ・アクセスを許å¯" name="HelpEstateAllowGroup">
- ã“ã®ä¸å‹•ç”£ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã¯ã€ã“ã“ã«ç™»éŒ²ã•ã‚Œã¦ã„るグループã¨
-下記ã§ç‰¹åˆ¥ã«ç™»éŒ²ã•ã‚ŒãŸä½äººã®ã¿ã«è¨±å¯ã•ã‚Œã¾ã™ã€‚
-ã“ã®è¨­å®šã¯ã€Œãƒ‘ブリック・アクセスã€ãŒã‚ªãƒ•ã«ãªã£ã¦ã‚‹ã¨ãã®ã¿ä½¿ç”¨å¯èƒ½ã§ã™ã€‚
- </notification>
- <notification label="å«ŒãŒã‚‰ã›ã«é–¢ã™ã‚‹ãƒ¡ãƒ¼ãƒ«å…ˆ" name="HelpEstateAbuseEmailAddress">
- ã“れを有効ãªãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã«è¨­å®šã™ã‚‹ã¨ã€ãã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã«ã“ã®ä¸å‹•ç”£ã«ãŠã„ã¦è¡Œã‚ã‚ŒãŸ
-å«ŒãŒã‚‰ã›ã®å ±å‘ŠãŒé€ä¿¡ã•ã‚Œã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚
-設定を行ã‚ãªã„å ´åˆï¼ˆç©ºç™½ï¼‰ã€å«ŒãŒã‚‰ã›å ±å‘Šã¯ Linden Lab ã«ã®ã¿
-é€ä¿¡ã•ã‚Œã¾ã™ã€‚
- </notification>
- <notification label="アクセス拒å¦" name="HelpEstateBanResident">
- ã“ã®ãƒªã‚¹ãƒˆã®ä½äººã¯ã€ä»–ã®è¨­å®šã«ã‹ã‹ã‚らãšã€ã‚ãªãŸã®ä¸å‹•ç”£ã¸ã®
-アクセスãŒç¦æ­¢ã•ã‚Œã¦ã„ã¾ã™ã€‚
- </notification>
- <notification label="ボイスãƒãƒ£ãƒƒãƒˆã‚’許å¯" name="HelpEstateVoiceChat">
- ã“ã®ä¸å‹•ç”£ã®åŒºç”»ã¯ã€ä½äººãŒè¿‘所ã®äººã¨å¯¾è©±ã§ãã‚‹
-独自ã®ãƒœã‚¤ã‚¹ãƒãƒ£ãƒ³ãƒãƒ«ã‚’æŒã¤ã“ã¨ãŒã§ãã¾ã™ã€‚
-
-デフォルト: オフ
- </notification>
<notification label="ボイスãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ä¸ä¸€è‡´" name="VoiceVersionMismatch">
- ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã® Second Life ã¯ã€
-ã“ã®åœ°åŸŸã®ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆæ©Ÿèƒ½ã«å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“。
-ボイスãƒãƒ£ãƒƒãƒˆã‚’æ­£ã—ã使用ã™ã‚‹ã«ã¯ã€
-Second Life ã®ã‚¢ãƒƒãƒ—デートãŒå¿…è¦ã§ã™ã€‚
- </notification>
- <notification label="ä¸å‹•ç”£ç´„款" name="HelpEstateCovenant">
- ä¸å‹•ç”£ç´„款を定ã‚ã‚‹ã¨ã€è‡ªåˆ†ã®ä¸å‹•ç”£å†…ã®åŒºç”»ã‚’販売ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚
-約款を定ã‚ã¦ã„ãªã„ã¨åœŸåœ°ã¯å£²ã‚Œã¾ã›ã‚“。
-土地ã«é–¢ã™ã‚‹è¦å‰‡ã‚’é©ç”¨ã—ãŸããªã‹ã£ãŸã‚Šã€è³¼å…¥å‰ã«åœŸåœ°ã«é–¢ã™ã‚‹æƒ…報を購入者ã«çŸ¥ã‚‰ã›ãŸããªã„å ´åˆã€ã‚ãªãŸã®ç´„款ã®ãƒŽãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã¯ç™½ç´™ã§ã‹ã¾ã„ã¾ã›ã‚“。
-
-約款ã¯è³¼å…¥ã‚’考ãˆã¦ã„る人ã«ã€è¦å‰‡ã€ã‚¬ã‚¤ãƒ‰ãƒ©ã‚¤ãƒ³ã€æ–‡åŒ–的情報や
-å˜ã«ã‚ãªãŸãŒæœŸå¾…ã™ã‚‹ã“ã¨ã‚’ä¼ãˆã‚‹ãŸã‚ã«ã‚‚使ãˆã¾ã™ã€‚
-ã“ã“ã«ã¯ã€åŒºç”»è¦åˆ¶ã€å»ºé€ ç‰©è¦åˆ¶ã€æ”¯æ‰•ã„オプションã€ãã‚Œã‹ã‚‰è³¼å…¥è€…ãŒäº‹å‰ã«ç›®ã‚’通ã—ã¦åŒæ„ã—ã¦ãŠãã¹ãã ã¨ã‚ãªãŸãŒæ€ã†é‡è¦ãªæƒ…報をã™ã¹ã¦å…¥ã‚Œã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
-
-購入者ãŒãƒœãƒƒã‚¯ã‚¹ã‚’ãƒã‚§ãƒƒã‚¯ã—ã¦ç´„款ã«åŒæ„ã—ãªã„ã‹ãŽã‚Šã€è³¼å…¥ã®æ‰‹ç¶šãã¯å®Œäº†ã—ã¾ã›ã‚“。
-ä¸å‹•ç”£ç´„款ãŒå®šã‚られã¦ã„る区画ã§ã‚ã‚Œã°ã€ã€ŒåœŸåœ°æƒ…å ±ã€ã‹ã‚‰ç´„款をã„ã¤ã§ã‚‚閲覧ã§ãã¾ã™ã€‚
+ [APP_NAME] ã®ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã¯ã€ã“ã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã«ãŠã‘るボイスãƒãƒ£ãƒƒãƒˆã®äº’æ›æ€§ãŒã‚ã‚Šã¾ã›ã‚“。 ボイスãƒãƒ£ãƒƒãƒˆã‚’正常ã«è¡Œã†ãŸã‚ã«ã¯ã€[APP_NAME] ã®ã‚¢ãƒƒãƒ—デートãŒå¿…è¦ã§ã™ã€‚
</notification>
<notification label="オブジェクトを購入ã§ãã¾ã›ã‚“" name="BuyObjectOneOwner">
複数ã®ã‚ªãƒ¼ãƒŠãƒ¼ã‹ã‚‰åŒæ™‚ã«ã‚ªãƒ–ジェクトを購入ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
@@ -2091,14 +1728,14 @@ Second Life ã®ã‚¢ãƒƒãƒ—デートãŒå¿…è¦ã§ã™ã€‚
ã“ã®è³¼å…¥ã‚’続行ã—ã¾ã™ã‹ï¼Ÿ
<usetemplate name="okcancelbuttons" notext="å–り消ã—" yestext="OK"/>
</notification>
- <notification name="ConfirmPurchasePassword" type="password">
+ <notification name="ConfirmPurchasePassword">
ã“ã®å–引ã¯ä»¥ä¸‹ã®ã¨ãŠã‚Šè¡Œã‚ã‚Œã¾ã™ï¼š
[ACTION]
ã“ã®è³¼å…¥ã‚’続行ã—ã¾ã™ã‹ï¼Ÿ
パスワードをå†å…¥åŠ›ã—ã€ã€ŒOKã€ã‚’クリックã—ã¦ãã ã•ã„。
<form name="form">
- <input name="message" type="password"/>
+ <input name="message"/>
<button name="ConfirmPurchase" text="OK"/>
<button name="Cancel" text="å–り消ã—"/>
</form>
@@ -2115,7 +1752,7 @@ Second Life ã®ã‚¢ãƒƒãƒ—デートãŒå¿…è¦ã§ã™ã€‚
アイテムを動ã‹ã—ã¾ã™ã‹ï¼Ÿ
- <usetemplate ignoretext="コピーç¦æ­¢ã®æŒã¡ç‰©ã‚’オブジェクトã‹ã‚‰ç§»å‹•ã•ã›ã‚‹ã¨ã" name="okcancelignore" notext="キャンセル" yestext="OK"/>
+ <usetemplate ignoretext="「コピーä¸å¯ã€ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’オブジェクトã‹ã‚‰å‹•ã‹ã™å‰ã«è­¦å‘Šã™ã‚‹" name="okcancelignore" notext="キャンセル" yestext="OK"/>
</notification>
<notification name="MoveInventoryFromScriptedObject">
「コピーç¦æ­¢ã€ã®æŒã¡ç‰©ã‚¢ã‚¤ãƒ†ãƒ ãŒé¸æŠžã•ã‚Œã¾ã—ãŸã€‚
@@ -2124,79 +1761,44 @@ Second Life ã®ã‚¢ãƒƒãƒ—デートãŒå¿…è¦ã§ã™ã€‚
スクリプトã«èª¤å‹•ä½œãŒèµ·ãã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
æŒã¡ç‰©ã‚¢ã‚¤ãƒ†ãƒ ã‚’移動ã—ã¾ã™ã‹ï¼Ÿ
- <usetemplate ignoretext="コピーç¦æ­¢ã®æŒã¡ç‰©ã‚’スクリプト付ãオブジェクトã‹ã‚‰ç§»å‹•ã•ã›ã‚‹ã¨ã" name="okcancelignore" notext="キャンセル" yestext="OK"/>
+ <usetemplate ignoretext="スクリプト入りã®ã‚ªãƒ–ジェクトを壊ã™æã‚Œã®ã‚る「コピーä¸å¯ã€ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’å‹•ã‹ã™å‰ã«è­¦å‘Šã™ã‚‹" name="okcancelignore" notext="キャンセル" yestext="OK"/>
</notification>
<notification name="ClickActionNotPayable">
- 警告:「クリックã§ã‚ªãƒ–ジェクトã«æ”¯æ‰•ã„ã€ã®è¨­å®šãŒã•ã‚Œã¾ã—ãŸã€‚
-ãŸã ã—ã€ã“ã‚Œã¯ã‚¹ã‚¯ãƒªãƒ—トãŒé‡‘銭money() イベントã«è¿½åŠ ã•ã‚ŒãŸå ´åˆã«ã®ã¿ä½œå‹•ã—ã¾ã™ã€‚
+ 警告: クリックã§ã€Œã‚ªãƒ–ジェクトã«æ”¯æ‰•ã†ã€è¨­å®šã‚’ã—ã¾ã—ãŸã€‚スクリプト㫠money()イベントãŒè¿½åŠ ã•ã‚Œã‚‹ã¨å‹•ä½œã—ã¾ã™ã€‚
<form name="form">
- <ignore name="ignore" text="money()イベントãªã—ã«ã€Œã‚ªãƒ–ジェクトã«æ”¯æ‰•ã†ã€ã‚’設定ã™ã‚‹ã¨ã"/>
+ <ignore name="ignore" text="money() スクリプトを入れãšã«ã‚ªãƒ–ジェクトを制作中ã«ã€ã€Œã‚ªãƒ–ジェクトã«æ”¯æ‰•ã†ã€ã‚¢ã‚¯ã‚·ãƒ§ãƒ³ã‚’設定"/>
</form>
</notification>
<notification name="OpenObjectCannotCopy">
ã“ã®ã‚ªãƒ–ジェクトã«ã¯ã€ã‚ãªãŸãŒã‚³ãƒ”ーã§ãるアイテムã¯ã‚ã‚Šã¾ã›ã‚“。
</notification>
<notification name="WebLaunchAccountHistory">
- Second Life ウェブ・ページを開ã„ã¦
-アカウント履歴を確èªã—ã¾ã™ã‹ï¼Ÿ
- <usetemplate ignoretext="アカウント履歴ã®ã‚¦ã‚§ãƒ–・ページをロードã™ã‚‹ã¨ã" name="okcancelignore" notext="å–り消ã—" yestext="ページã«ç§»å‹•"/>
- </notification>
- <notification name="ClickOpenF1Help">
- Second Life ã®ã‚µãƒãƒ¼ãƒˆã‚¦ã‚§ãƒ–サイトを利用ã—ã¾ã™ã‹ï¼Ÿ
- <usetemplate ignoretext="Second Life ã®ã‚µãƒãƒ¼ãƒˆã‚¦ã‚§ãƒ–サイトを閲覧ã™ã‚‹ã«ã‚ãŸã£ã¦ã€‚" name="okcancelignore" notext="キャンセル" yestext="è¡Œã"/>
+ [http://jp.secondlife.com/account/ マイアカウント] ページã«ç§»å‹•ã—ã¦ã‚¢ã‚«ã‚¦ãƒ³ãƒˆå±¥æ­´ã‚’確èªã—ã¾ã™ã‹ï¼Ÿ
+ <usetemplate ignoretext="ブラウザを起動ã—ã¦ã‚¢ã‚«ã‚¦ãƒ³ãƒˆå±¥æ­´ã‚’見る" name="okcancelignore" notext="å–り消ã—" yestext="ページã«ç§»å‹•"/>
</notification>
<notification name="ConfirmQuit">
終了ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚æ“作を続行ã—ã¾ã™ã‹ï¼Ÿ
- <usetemplate ignoretext="Second Life ã®çµ‚了ã«ã‚ãŸã£ã¦ã€‚" name="okcancelignore" notext="継続" yestext="終了"/>
+ <usetemplate ignoretext="終了時ã«ç¢ºèªã™ã‚‹" name="okcancelignore" notext="終了ã—ãªã„" yestext="終了"/>
</notification>
<notification name="HelpReportAbuseEmailLL">
- 利用è¦ç´„é•åã¨ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ãƒ¼ã‚¹ã‚¿ãƒ³ãƒ€ãƒ¼ãƒ‰é•åã®å ±å‘Šã«ã“ã®ãƒ„ールをã”使用ãã ã•ã„。 å‚照:
+ ã“ã®ãƒ„ールを利用ã—㦠[http://secondlife.com/corporate/tos.php 利用è¦ç´„] ã‚„ [http://jp.secondlife.com/corporate/cs.php コミュニティスタンダード] ã®é•åを報告ã—ã¦ãã ã•ã„。
-http://secondlife.com/corporate/tos.php
-http://secondlife.com/corporate/cs.php
-
-利用è¦ç´„é•åã¨ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ãƒ¼ã‚¹ã‚¿ãƒ³ãƒ€ãƒ¼ãƒ‰é•åã«é–¢ã™ã‚‹å…¨ã¦ã®ãƒ¬ãƒãƒ¼ãƒˆã¯ã€èª¿æŸ»ã•ã‚Œã€è§£æ±ºã•ã‚Œã¾ã™ã€‚
-以下ã®ãƒªãƒ³ã‚¯å…ˆã®è¢«å®³å ±å‘Šã«ã¦ãã®ç¢ºèªã‚’ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
-
-http://secondlife.com/support/incidentreport.php
+報告ã•ã‚ŒãŸå«ŒãŒã‚‰ã›ã¯ã™ã¹ã¦èª¿æŸ»ãƒ»è§£æ±ºã•ã‚Œã¾ã™ã€‚ 解決ã•ã‚ŒãŸã‚‚ã®ã¯ [http://secondlife.com/support/incidentreport.php Incident Report] ã§è¦‹ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
</notification>
<notification name="HelpReportAbuseEmailEO">
- é‡è¦ï¼š ã“ã®ãƒ¬ãƒãƒ¼ãƒˆã¯Linden Lab 社ã§ã¯ãªãã€
-ã‚ãªãŸãŒç¾åœ¨ã„る地域ã®ã‚ªãƒ¼ãƒŠãƒ¼ã«é€ã‚‰ã‚Œã¾ã™ã€‚
--
-ã‚ãªãŸãŒä»Šã„る地域ã®ã‚ªãƒ¼ãƒŠãƒ¼ã¯ã€
-ä½äººã¨è¨ªå•è€…ã¸ã®ã‚µãƒ¼ãƒ“スã®ä¸€ç’°ã¨ã—ã¦ã€ã“ã®åœ°åŸŸã‹ã‚‰ã®ãƒ¬ãƒãƒ¼ãƒˆã‚’ã™ã¹ã¦å—ã‘付ã‘ã€è§£æ±ºã™ã‚‹ã“ã¨ã«åŒæ„ã—ã¦ã„ã¾ã™ã€‚
-よã£ã¦Linden Lab 社ãŒã€
-ã‚ãªãŸãŒã“ã“ã‹ã‚‰æ出ã™ã‚‹ãƒ¬ãƒãƒ¼ãƒˆã‚’調査ã™ã‚‹ã“ã¨ã¯ã‚ã‚Šã¾ã›ã‚“。
-地域ã®ã‚ªãƒ¼ãƒŠãƒ¼ã¯ã€ä¸å‹•ç”£ç´„款ã§æŒ‡å®šã—ã¦ã„る地元ã®è¦å‰‡ã‚’基ã«ã€å ±å‘Šã•ã‚ŒãŸå•é¡Œã‚’解決ã—ã¾ã™ã€‚
-(「世界ã€ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‹ã‚‰ã€ŒåœŸåœ°æƒ…å ±ã€ã‚’é¸ã¶ã¨ã€ç´„款を閲覧ã§ãã¾ã™ï¼‰
--
-ã“ã®ãƒ¬ãƒãƒ¼ãƒˆã«é–¢ã™ã‚‹è§£æ±ºç­–ã¯ã€ã“ã®åœ°åŸŸã«ã ã‘当ã¦ã¯ã¾ã‚Šã¾ã™ã€‚
-ä½äººãŒSecond Life ã®ä»–ã®åœ°åŸŸã¸ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹éš›ã€
-ã“ã®ãƒ¬ãƒãƒ¼ãƒˆã®çµæžœã«å½±éŸ¿ã•ã‚Œã‚‹ã“ã¨ã¯ã‚ã‚Šã¾ã›ã‚“。
-Linden Lab 社ã ã‘ãŒSecond Life 全域ã«ãŠã‘ã‚‹
-アクセス制é™æ¨©ã‚’æŒã£ã¦ã„ã¾ã™ã€‚
- </notification>
- <notification name="HelpReportBug">
- ã“ã®ãƒ„ールã¯ã€èª¬æ˜Žã©ãŠã‚Šã«å‹•ä½œã—ãªã„ãªã©ã®ãƒ†ã‚¯ãƒ‹ã‚«ãƒ«ãªãƒ•ã‚£ãƒ¼ãƒãƒ£ãƒ¼ã®ãƒ¬ãƒãƒ¼ãƒˆã®ã¿ã«ä½¿ç”¨ã—ã¦ãã ã•ã„。
-ã§ãã‚‹ã ã‘詳ã—ã„情報をæä¾›ã—ã¦ãã ã•ã„。
-自動返答メールã«ã€ã‚ˆã‚Šè©³ã—ã„情報を付ã‘加ãˆã¦è¿”ä¿¡ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
-ãƒã‚°ãƒ¬ãƒãƒ¼ãƒˆã¯å…¨ã¦èª¿æŸ»ã•ã‚Œè§£æ±ºã•ã‚Œã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã£ã¦Eメールã§è¿”ç­”ãŒé€ã‚‰ã‚Œã¦ãã‚‹ã“ã¨ã¯ã‚ã‚Šã¾ã›ã‚“。
--
-テクニカルãªå•é¡ŒãŒç”Ÿã˜ãŸå ´åˆã¯ã€
-次ã®ã‚µãƒãƒ¼ãƒˆã«é€£çµ¡ã—ã¦ãã ã•ã„:
-http://secondlife.com/community/support.php
--
-注æ„:未完æˆã®å ±å‘Šã¯èª¿æŸ»ã•ã‚Œã¾ã›ã‚“。
+ é‡è¦ï¼š ã“ã®å ±å‘Šã¯ Linden Lab ã«ã¯é€ä¿¡ã•ã‚Œãšã€ç¾åœ¨ã‚ãªãŸãŒã„るリージョンã®æ‰€æœ‰è€…ã«é€ä¿¡ã•ã‚Œã¾ã™ã€‚
+
+ä½äººã‚„訪å•è€…ã¸ã®ã‚µãƒ¼ãƒ“スã®ä¸€ç’°ã¨ã—ã¦ã€ç¾åœ¨ã„るリージョンã®æ‰€æœ‰è€…ã¯ã€ã“ã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³å†…ã®ã™ã¹ã¦ã®å ±å‘Šã‚’自らå—ã‘å–ã‚Šã€è§£æ±ºã™ã‚‹ã‚ˆã†è¨­å®šã—ã¦ã„ã¾ã™ã€‚ Linden Lab ã¯ã“ã“ã‹ã‚‰é€ä¿¡ã•ã‚ŒãŸå ±å‘Šã®èª¿æŸ»ã‚’è¡Œã„ã¾ã›ã‚“。
+
+リージョンã®æ‰€æœ‰è€…ã¯ã€ã“ã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã®ä¸å‹•ç”£ç´„款ã«è¨˜è¼‰ã•ã‚ŒãŸãƒ­ãƒ¼ã‚«ãƒ«ãƒ«ãƒ¼ãƒ«ã«å‰‡ã£ã¦å ±å‘Šã«å¯¾å¿œã—ã¾ã™ã€‚
+(「世界ã€ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã®ã€ŒåœŸåœ°æƒ…å ±ã€ã§ç´„款を確èªã§ãã¾ã™ã€‚)
+
+ã“ã®å ±å‘Šã¸ã®è§£æ±ºç­–ã¯ã€ã“ã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã§ã®ã¿é©ç”¨ã•ã‚Œã¾ã™ã€‚ [SECOND_LIFE] ã®ãã®ä»–ã®ã‚¨ãƒªã‚¢ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ä½äººã«ã¯ã€ã“ã®å ±å‘Šã®çµæžœã«ã¯å½±éŸ¿ãŒã‚ã‚Šã¾ã›ã‚“。 [SECOND_LIFE] ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’制é™ã§ãã‚‹ã®ã¯ã€Linden Lab ã ã‘ã§ã™ã€‚
</notification>
<notification name="HelpReportAbuseSelectCategory">
å«ŒãŒã‚‰ã›å ±å‘Šã®ã‚«ãƒ†ã‚´ãƒªã‚’é¸æŠžã—ã¦ãã ã•ã„。
カテゴリをé¸æŠžã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€å«ŒãŒã‚‰ã›å ±å‘Šã®å‡¦ç†ã‚„ä¿ç®¡ã«å¤§å¤‰å½¹ç«‹ã¡ã¾ã™ã€‚
</notification>
- <notification name="HelpReportBugSelectCategory">
- ãƒã‚°ã®ã‚«ãƒ†ã‚´ãƒªã‚’é¸æŠžã—ã¦ãã ã•ã„。
-カテゴリをé¸æŠžã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šã€ãƒã‚°å ±å‘Šã®å‡¦ç†ã‚„ä¿ç®¡ã«å¤§å¤‰å½¹ç«‹ã¡ã¾ã™ã€‚
- </notification>
<notification name="HelpReportAbuseAbuserNameEmpty">
å«ŒãŒã‚‰ã›è¡Œç‚ºã‚’ã—ãŸäººã®åå‰ã‚’入力ã—ã¦ãã ã•ã„。
正確ãªæƒ…å ±ã®å…¥åŠ›ã«ã‚ˆã‚Šã€å«ŒãŒã‚‰ã›å ±å‘Šã®å‡¦ç†ã‚„ä¿ç®¡ã«å¤§å¤‰å½¹ç«‹ã¡ã¾ã™ã€‚
@@ -2210,10 +1812,6 @@ http://secondlife.com/community/support.php
正確ãªæ¦‚è¦ã®å…¥åŠ›ã«ã‚ˆã‚Šã€
å«ŒãŒã‚‰ã›å ±å‘Šã®å‡¦ç†ã‚„ä¿ç®¡ã«å¤§å¤‰å½¹ç«‹ã¡ã¾ã™ã€‚
</notification>
- <notification name="HelpReportBugSummaryEmpty">
- ãƒã‚°ã®æ¦‚è¦ã‚’入力ã—ã¦ãã ã•ã„。
-正確ãªæ¦‚è¦ã®å…¥åŠ›ã«ã‚ˆã‚Šã€ãƒã‚°å ±å‘Šã®å‡¦ç†ã‚„ä¿ç®¡ã«å¤§å¤‰å½¹ç«‹ã¡ã¾ã™ã€‚
- </notification>
<notification name="HelpReportAbuseDetailsEmpty">
å«ŒãŒã‚‰ã›ã®è©³ç´°ãªèª¬æ˜Žã‚’入力ã—ã¦ãã ã•ã„。
åå‰ã‚„å«ŒãŒã‚‰ã›ã®è©³ç´°ã‚’ã€ã§ãã‚‹ã ã‘具体的ã«å…¥åŠ›ã—ã¦ãã ã•ã„。
@@ -2221,35 +1819,18 @@ http://secondlife.com/community/support.php
正確ãªèª¬æ˜Žã®å…¥åŠ›ã«ã‚ˆã‚Šã€
å«ŒãŒã‚‰ã›å ±å‘Šã®å‡¦ç†ã‚„ä¿ç®¡ã«å¤§å¤‰å½¹ç«‹ã¡ã¾ã™ã€‚
</notification>
- <notification name="HelpReportBugDetailsEmpty">
- ãƒã‚°ã®è©³ç´°ãªèª¬æ˜Žã‚’入力ã—ã¦ãã ã•ã„。
-ãƒã‚°ãŒã©ã®ã‚ˆã†ãªæ¡ä»¶ã§å†ç¾ã™ã‚‹ã‹ãªã©ã‚’ã€ã§ãã‚‹ã ã‘具体的ã«å…¥åŠ›ã—ã¦ãã ã•ã„。
-
-正確ãªèª¬æ˜Žã®å…¥åŠ›ã«ã‚ˆã‚Šã€ãƒã‚°å ±å‘Šã®å‡¦ç†ã‚„ä¿ç®¡ã«å¤§å¤‰å½¹ç«‹ã¡ã¾ã™ã€‚
- </notification>
<notification name="HelpReportAbuseContainsCopyright">
- ä½äººã®çš†æ§˜ã¸ã€
+ ã“ã‚“ã«ã¡ã¯ã€
-知的財産ã®ä¾µå®³ã«é–¢ã™ã‚‹å ±å‘Šã‚’è¡Œã†éš›ã«ã¯ã€ä»¥ä¸‹ã®ç‚¹ã«æ³¨æ„ã—ã¦ãã ã•ã„。
+知的財産権ã®ä¾µå®³ã‚’報告ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ 正確ã«å ±å‘Šã™ã‚‹ãŸã‚ã«ã€ä»¥ä¸‹ã‚’ã”確èªãã ã•ã„:
-(1) å«ŒãŒã‚‰ã›ã®å ±å‘Šã®ãƒ—ロセス
-Second Life ã®æ¨©é™ã‚·ã‚¹ãƒ†ãƒ ã‚’悪用ã—ã¦ã„ã‚‹ä½äººã‚’見ã¤ã‘ãŸã‚‰ã€
-å«ŒãŒã‚‰ã›ã®å ±å‘Šã‚’è¡Œã£ã¦ãã ã•ã„。
-例ãˆã°ã‚³ãƒ”ーBotã®ä½¿ç”¨ã€ãã‚Œã«ä¼¼ãŸãƒ„ールã®ä½¿ç”¨ã«ã‚ˆã‚‹çŸ¥çš„財産権ã®ä¾µå®³ãŒã‚ã‚Šã¾ã™ã€‚
-アビューズãƒãƒ¼ãƒ ã¯èª¿æŸ»ã«åŸºã¥ãã€
-Second Life ã®ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ãƒ¼ã‚¹ã‚¿ãƒ³ãƒ€ãƒ¼ãƒ‰ã‚„
-利用è¦ç´„ã«é•åã™ã‚‹è¡Œç‚ºã¨åˆ¤æ–­ã•ã‚ŒãŸå ´åˆã«ã¯é©åˆ‡ãªå‡¦ç½®ã‚’è¡Œã£ã¦ã„ã¾ã™ã€‚
-ãŸã ã—ã€ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã‚’Second Life ã‹ã‚‰æ’¤åŽ»ã—ã¦ã»ã—ã„ã€
-ã¨ã„ã£ãŸè¦æœ›ã«ã¯ã‚¢ãƒ“ューズãƒãƒ¼ãƒ ã¯å¿œãˆã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
+(1) å«ŒãŒã‚‰ã›ã®å ±å‘Šã®æ‰‹é † ä½äººãŒ [SECOND_LIFE] ã®æ¨©é™ã‚·ã‚¹ãƒ†ãƒ ã‚’悪用ã—ã¦ã„ã‚‹ã®ã‚’見ã¤ã‘ãŸã‚‰ã€å«ŒãŒã‚‰ã›ã®å ±å‘Šã‚’ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚例ãˆã°ã€CopyBot ã‚„ä¼¼ãŸã‚ˆã†ãªã‚³ãƒ”ーツールを使用ã—ã¦çŸ¥çš„財産権を侵害ã—ã¦ã„ã‚‹å ´åˆã§ã™ã€‚ 担当ãƒãƒ¼ãƒ ã¯èª¿æŸ»ã‚’è¡Œã„ã€[SECOND_LIFE] [http://secondlife.com/corporate/tos.php 利用è¦ç´„] ã‚„ [http://jp.secondlife.com/corporate/cs.php コミュニティスタンダード] ã«é•åã™ã‚‹è¡Œç‚ºã«å¯¾ã™ã‚‹é©åˆ‡ãªå‡¦ç½°ã‚’下ã—ã¾ã™ã€‚ ãŸã ã—ã€æ‹…当ãƒãƒ¼ãƒ ã¯ [SECOND_LIFE] ã®ä¸–ç•Œã‹ã‚‰ã‚³ãƒ³ãƒ†ãƒ³ãƒ„を削除ã—ã¦æ¬²ã—ã„ã¨ã„ã†ãƒªã‚¯ã‚¨ã‚¹ãƒˆã«ã¯å¿œã˜ã¾ã›ã‚“。
-(2) DMCA(デジタルミレニアム著作権法)åŠã³ã‚³ãƒ³ãƒ†ãƒ³ãƒ„撤去プロセス
-Second Life ã‹ã‚‰ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã®æ’¤åŽ»ã‚’リクエストã™ã‚‹ã«ã¯ã€
-著作権侵害通知ã®æ出を行ã†å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
-å‚照: http://secondlife.com/corporate/dmca.php
+(2) DMCA ã¾ãŸã¯ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã®æ’¤åŽ»ã®æ‰‹é † コンテンツを [SECOND_LIFE] ã‹ã‚‰å‰Šé™¤ã—ã¦æ¬²ã—ã„ã¨ã„ã†ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’ã™ã‚‹ã«ã¯ã€å¼Šç¤¾ [http://secondlife.com/corporate/dmca.php DMCA ãƒãƒªã‚·ãƒ¼] ã§æ示ã•ã‚Œã¦ã„ã‚‹ã¨ãŠã‚Šã€æœ‰åŠ¹ãªä¾µå®³ã®é€šçŸ¥ã‚’æ出ã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。.
-ã“ã®ä»¶ã«é–¢ã™ã‚‹å«ŒãŒã‚‰ã›ã®å ±å‘Šã‚’続ã‘ã‚‹éš›ã¯ã€ã“ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’é–‰ã˜ã¦ãã ã•ã„。é¸æŠžã™ã¹ãカテゴリã¯ã€ŒçŸ¥çš„財産ã®ä¾µå®³ï¼žã‚³ãƒ”ーBotåŠã³æ¨©é™ã®æ‚ªç”¨ã€ã®ã»ã†ãŒé©ã—ã¦ã„ã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“ã®ã§ã”確èªãã ã•ã„。
+ã“ã®ã¾ã¾å«ŒãŒã‚‰ã›ã®å ±å‘Šã‚’続ã‘ãŸã„å ´åˆã¯ã€ã“ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’é–‰ã˜ã¦å ±å‘Šã‚’é€ã£ã¦ãã ã•ã„。 「コピーBotåŠã³æ¨©é™ã®æ‚ªç”¨ã€ã®ã‚«ãƒ†ã‚´ãƒªã‚’é¸ã‚“ã æ–¹ãŒé©åˆ‡ã®å ´åˆãŒã‚ã‚Šã¾ã™ã€‚
-よã‚ã—ããŠé¡˜ã„ã—ã¾ã™ã€‚
+ã”å”力ã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ã€‚
Linden Lab
</notification>
@@ -2261,7 +1842,7 @@ Linden Lab
体ã®ã“ã®éƒ¨ä½ã«ã¯ã‚ªãƒ–ジェクトãŒè£…ç€ã•ã‚Œã¦ã„ã¾ã™ã€‚
é¸æŠžã•ã‚ŒãŸã‚ªãƒ–ジェクトã¨ç½®ãæ›ãˆã¾ã™ã‹ï¼Ÿ
<form name="form">
- <ignore name="ignore" save_option="true" text="ç¾åœ¨ã€è£…ç€ã—ã¦ã„ã‚‹ã‚‚ã®ã‚’ç½®æ›ã™ã‚‹ã¨ã"/>
+ <ignore name="ignore" save_option="true" text="装ç€ã—ã¦ã„るアイテムã¨é¸æŠžã—ãŸã‚¢ã‚¤ãƒ†ãƒ ã‚’入れ替ãˆã‚‹"/>
<button ignore="自動的ã«äº¤æ›" name="Yes" text="OK"/>
<button ignore="交æ›ã—ãªã„" name="No" text="キャンセル"/>
</form>
@@ -2273,18 +1854,22 @@ Linden Lab
ã“ã®å–引を完了ã™ã‚‹å‰ã«ã€å–ã‚Šè¾¼ã¿ä¸­ã®è¨­å®šã‚’解除ã—ã¾ã™ã‹ï¼Ÿ
<form name="form">
- <ignore name="ignore" save_option="true" text="å–ã‚Šè¾¼ã¿ä¸­ã®äººã¾ãŸã¯ã‚ªãƒ–ジェクトã«æ”¯æ‰•ã†ã¨ã"/>
+ <ignore name="ignore" save_option="true" text="å–ã‚Šè¾¼ã¿ä¸­ãƒ¢ãƒ¼ãƒ‰ã®æ™‚ã«æ”¯æ‰•ã‚’ã™ã‚‹"/>
<button ignore="常ã«å–ã‚Šè¾¼ã¿ä¸­ã®è¨­å®š" name="Yes" text="OK"/>
<button ignore="å–ã‚Šè¾¼ã¿ä¸­ã®è¨­å®šã«ã—ãªã„" name="No" text="キャンセル"/>
</form>
</notification>
+ <notification name="ConfirmDeleteProtectedCategory">
+ 「 [FOLDERNAME] 〠ã¯ã€ã‚·ã‚¹ãƒ†ãƒ ãƒ•ã‚©ãƒ«ãƒ€ã§ã™ã€‚ システムフォルダを削除ã™ã‚‹ã¨ä¸å®‰å®šã«ãªã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚ 続ã‘ã¾ã™ã‹ï¼Ÿ
+ <usetemplate ignoretext="システムフォルダを削除ã™ã‚‹å‰ã«ç¢ºèªã™ã‚‹" name="okcancelignore" notext="キャンセル" yestext="OK"/>
+ </notification>
<notification name="ConfirmEmptyTrash">
- ゴミ箱フォルダã®ä¸­èº«ã‚’完全ã«å‰Šé™¤ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚æ“作を続行ã—ã¾ã™ã‹ï¼Ÿ
- <usetemplate ignoretext="æŒã¡ç‰©å†…ã®ã€Œã”ã¿ç®±ã€ãƒ•ã‚©ãƒ«ãƒ€ã‚’空ã«ã™ã‚‹ã¨ã" name="okcancelignore" notext="キャンセル" yestext="OK"/>
+ ã”ã¿ç®±ã®é …目をã™ã¹ã¦å‰Šé™¤ã—ã¾ã™ã‹ï¼Ÿ
+ <usetemplate ignoretext="æŒã¡ç‰©ã®ã”ã¿ç®±ãƒ•ã‚©ãƒ«ãƒ€ã‚’空ã«ã™ã‚‹å‰ã«ç¢ºèªã™ã‚‹" name="okcancelignore" notext="キャンセル" yestext="OK"/>
</notification>
<notification name="ConfirmClearBrowserCache">
- 本当ã«ãƒ–ラウザã®ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’クリアã—ã¾ã™ã‹ï¼Ÿ
- <usetemplate name="okcancelbuttons" notext="キャンセル" yestext="ã¯ã„"/>
+ トラベルã€Webã€æ¤œç´¢ã®å±¥æ­´ã‚’ã™ã¹ã¦å‰Šé™¤ã—ã¾ã™ã‹ï¼Ÿ
+ <usetemplate name="okcancelbuttons" notext="キャンセル" yestext="OK"/>
</notification>
<notification name="ConfirmClearCookies">
本当ã«ã‚¯ãƒƒã‚­ãƒ¼ã‚’クリアã—ã¾ã™ã‹ï¼Ÿ
@@ -2295,40 +1880,18 @@ Linden Lab
<usetemplate name="okcancelbuttons" notext="キャンセル" yestext="ã¯ã„"/>
</notification>
<notification name="ConfirmEmptyLostAndFound">
- éºå¤±ç‰©ãƒ•ã‚©ãƒ«ãƒ€ã®ä¸­èº«ã‚’完全ã«å‰Šé™¤ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚æ“作を続行ã—ã¾ã™ã‹ï¼Ÿ
- <usetemplate ignoretext="æŒã¡ç‰©å†…ã®ã€Œéºå¤±ç‰©ã€ãƒ•ã‚©ãƒ«ãƒ€ã‚’空ã«ã™ã‚‹ã¨ã" name="okcancelignore" notext="ã„ã„ãˆ" yestext="ã¯ã„"/>
+ 紛失物ã®é …目をã™ã¹ã¦å‰Šé™¤ã—ã¾ã™ã‹ï¼Ÿ
+ <usetemplate ignoretext="紛失物フォルダを空ã«ã™ã‚‹å‰ã«ç¢ºèªã™ã‚‹" name="okcancelignore" notext="ã„ã„ãˆ" yestext="ã¯ã„"/>
</notification>
<notification name="CopySLURL">
- 以下ã®SLURLãŒã‚¯ãƒªãƒƒãƒ—ボードã«ã‚³ãƒ”ーã•ã‚Œã¾ã—ãŸã€‚
+ 次㮠SLurl ãŒã‚¯ãƒªãƒƒãƒ—ボードã«ã‚³ãƒ”ーã•ã‚Œã¾ã—ãŸï¼š
[SLURL]
-ä»–ã®äººãŒã‚¢ã‚¯ã‚»ã‚¹ã—ã‚„ã™ã„よã†ã«ã‚¦ã‚§ãƒ–・ページã«è¼‰ã›ãŸã‚Šã€
-ブラウザã®ã‚¢ãƒ‰ãƒ¬ã‚¹ãƒ»ãƒãƒ¼ã«è²¼ã‚Šä»˜ã‘ã¦ã€è‡ªåˆ†ã§ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã¿ã¾ã—ょã†ã€‚
+Webページã«ã“れをリンクã™ã‚‹ã¨ã€ä»–人ãŒã“ã®å ´æ‰€ã«ç°¡å˜ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚Webブラウザã®ã‚¢ãƒ‰ãƒ¬ã‚¹ãƒãƒ¼ã«è²¼ã‚Šä»˜ã‘ã¦è©¦ã—ã¦ã¿ã¦ãã ã•ã„。
<form name="form">
- <ignore name="ignore" text="SLURLをクリップボードã«ã‚³ãƒ”ーã™ã‚‹ã¨ã"/>
+ <ignore name="ignore" text="クリップボード㫠SLurl ãŒã‚³ãƒ”ーã•ã‚Œã‚‹"/>
</form>
</notification>
- <notification name="GraphicsPreferencesHelp">
- ã“ã®ãƒ‘ãƒãƒ«ã§ã¯ã€ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã®ã‚µã‚¤ã‚ºã¨è§£åƒåº¦ã€ãŠã‚ˆã³ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã®ã‚°ãƒ©ãƒ•ã‚£ãƒƒã‚¯ã®å“質を設定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚「環境設定ã€ï¼žã€Œè¡¨ç¤ºã€ã®ã‚¤ãƒ³ã‚¿ãƒ•ã‚§ãƒ¼ã‚¹ã§ã¯ã€ä½Žã€ä¸­ã€é«˜ã€è¶…高ã®4ã¤ã®ä¸­ã‹ã‚‰ã‚°ãƒ©ãƒ•ã‚£ãƒƒã‚¯ãƒ»ãƒ¬ãƒ™ãƒ«ã‚’é¸æŠžã§ãã¾ã™ã€‚ã¾ãŸã€ã€Œã‚«ã‚¹ã‚¿ãƒ ã€ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹ã‚’クリックã—ã€ä»¥ä¸‹ã®ã‚°ãƒ©ãƒ•ã‚£ãƒƒã‚¯ã‚¹ã®è¨­å®šã‚’カスタマイズã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
-
-シェーダー:ピクセル・シェーダーã®ã•ã¾ã–ã¾ãªç¨®é¡žã‚’有効ã¾ãŸã¯ç„¡åŠ¹ã«ã—ã¾ã™ã€‚
-
-å射詳細:水ãŒåå°„ã™ã‚‹ã‚ªãƒ–ジェクトã®ç¨®é¡žã‚’設定ã—ã¾ã™ã€‚
-
-ã‚¢ãƒã‚¿ãƒ¼ãƒ»ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ï¼šã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã«ã‚ˆã‚‹ã‚¢ãƒã‚¿ãƒ¼ã®ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°æ–¹æ³•ã«å½±éŸ¿ã™ã‚‹ã‚ªãƒ—ションを設定ã—ã¾ã™ã€‚
-
-æç”»è·é›¢ï¼šã‚ãªãŸã®è¦–点ã‹ã‚‰è¦–ç•Œã®ã©ã®ãらã„ã®è·é›¢ã¾ã§ã€ã‚ªãƒ–ジェクトãŒãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ã•ã‚Œã‚‹ã‹ã«å½±éŸ¿ã—ã¾ã™ã€‚
-
-最大パーティクル数:画é¢ã«ä¸€åº¦ã«è¦‹ã‚‹ã“ã¨ãŒã§ãるパーティクルã®æœ€å¤§æ•°ã‚’設定ã—ã¾ã™ã€‚
-
-ãƒã‚¹ãƒˆãƒ—ロセスå“質:グロー効果(è¼ã)ãŒãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ã•ã‚Œã‚‹éš›ã®è§£åƒåº¦ã‚’設定ã—ã¾ã™ã€‚
-
-メッシュ詳細: 特定ã®ã‚ªãƒ–ジェクトã®ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°æ™‚ã®ç´°éƒ¨è¡¨ç¾ã€ã¾ãŸã¯ä¸‰è§’å½¢ã®æ•°ã‚’設定ã—ã¾ã™ã€‚ 値を大ããã™ã‚‹ã»ã©ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ã«æ™‚é–“ãŒã‹ã‹ã‚Šã¾ã™ãŒã€ã‚ªãƒ–ジェクトãŒã‚ˆã‚Šè©³ç´°ã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
-
-ライティング詳細:レンダリングã™ã‚‹å…‰æºã®ç¨®é¡žã‚’é¸æŠžã—ã¾ã™ã€‚
-
-地形詳細: 地形テクスãƒãƒ£ã®ç´°éƒ¨è¡¨ç¾ã‚’設定ã—ã¾ã™ã€‚
- </notification>
<notification name="WLSavePresetAlert">
ä¿å­˜ã•ã‚ŒãŸäº‹å‰è¨­å®šã‚’上書ãã—ã¾ã™ã‹ï¼Ÿ
<usetemplate name="okcancelbuttons" notext="ã„ã„ãˆ" yestext="ã¯ã„"/>
@@ -2347,184 +1910,10 @@ Linden Lab
ãƒã‚¹ãƒˆãƒ—ロセス効果ãŒå­˜åœ¨ã—ã¾ã™ã€‚ 上書ãã—ã¾ã™ã‹ï¼Ÿ
<usetemplate name="okcancelbuttons" notext="ã„ã„ãˆ" yestext="ã¯ã„"/>
</notification>
- <notification name="HelpEditSky">
- ウィンドライトã®å„種スライダーを編集ã—ã¦ç©ºã‚’作æˆãŠã‚ˆã³ä¿å­˜ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpEditDayCycle">
- 1 日を通ã—ã¦å¤‰åŒ–ã™ã‚‹ç©ºã®æ§˜å­ã‚’設定ã—ã¾ã™ã€‚
- </notification>
- <notification name="EnvSettingsHelpButton">
- 次ã®å„設定ã¯ã‚³ãƒ³ãƒ”ュータ上ã§ã‚¤ãƒ³ãƒ¯ãƒ¼ãƒ«ãƒ‰ã®ç’°å¢ƒãŒã©ã®ã‚ˆã†ã«è¡¨ç¤ºã•ã‚Œã‚‹ã‹ã‚’調整ã—ã¾ã™ã€‚ 設定ã®ã™ã¹ã¦ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã«ã¯ãŠä½¿ã„ã®ã‚°ãƒ©ãƒ•ã‚£ãƒƒã‚¯ãƒ»ã‚«ãƒ¼ãƒ‰ãŒå‘¨å›²ï¼ˆå¤§æ°—)シェーダー (atmospheric shaders) をサãƒãƒ¼ãƒˆã—ã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
-
-「時間帯ã€ã‚¹ãƒ©ã‚¤ãƒ€ãƒ¼ã‚’調整ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šãƒ“ューワã§å®Ÿéš›ã«ä½¿ç”¨ã™ã‚‹æ™‚間帯を変更ã§ãã¾ã™ã€‚
-
-「雲ã®é‡ã€ã‚¹ãƒ©ã‚¤ãƒ€ãƒ¼ã‚’調整ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šç©ºã‚’ãŠãŠã†é›²ã®é‡ã‚’制御ã§ãã¾ã™ã€‚
-
-「水ã®è‰²ã€ã‚«ãƒ©ãƒ¼ãƒ»ãƒ”ッカーã§è‰²ã‚’é¸æŠžã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šæ°´ã®è‰²ã‚’変更ã§ãã¾ã™ã€‚
-
-「水中ã®ãƒ•ã‚©ã‚°åŠ¹æžœã€ã‚¹ãƒ©ã‚¤ãƒ€ãƒ¼ã‚’調整ã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šæ°´ã®é€æ˜Žåº¦ã‚’制御ã§ãã¾ã™ã€‚
-
-「ä¸å‹•ç”£ã®æ™‚刻を使用ã€ã‚’クリックã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šæ™‚刻ã¯ãƒªã‚»ãƒƒãƒˆã•ã‚Œåœ°åŸŸã®ç¾åœ¨æ™‚刻ã«é€£å‹•ã•ã›ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
-
-「空ã®é«˜åº¦ãªè¨­å®šã€ã‚’クリックã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šç©ºã®ã‚ˆã‚Šé«˜åº¦ãªè¨­å®šã‚’è¡Œã†ãŸã‚ã®ç·¨é›†ãƒ—ログラムを起動ã§ãã¾ã™ã€‚
-
-「水ã®é«˜åº¦ãªè¨­å®šã€ã‚’クリックã™ã‚‹ã“ã¨ã«ã‚ˆã‚Šæ°´ã®ã‚ˆã‚Šé«˜åº¦ãªè¨­å®šã‚’è¡Œã†ãŸã‚ã®ç·¨é›†ãƒ—ログラムを起動ã§ãã¾ã™ã€‚
- </notification>
- <notification name="HelpDayCycle">
- 「デイ・サイクル編集ã€ã§ã¯ã€
-Second Life ã§ã®æ˜¼ã¨å¤œã®ç©ºã®å¤‰åŒ–を制御ã§ãã¾ã™ã€‚
-ã“ã‚Œã¯ã€ŒåŸºæœ¬ç’°å¢ƒç·¨é›†ã€ã®ã€Œæ™‚間帯ã€ã‚¹ãƒ©ã‚¤ãƒ€ãƒ¼ã§ä½¿ç”¨ã•ã‚Œã‚‹ã‚µã‚¤ã‚¯ãƒ«ã§ã™ã€‚
-
-「デイ・サイクル編集ã€ã¯ã‚­ãƒ¼ãƒ•ãƒ¬ãƒ¼ãƒ ã‚’設定ã™ã‚‹ã“ã¨ã§æ©Ÿèƒ½ã—ã¾ã™ã€‚
-å„キーフレームã«ã¯ãƒ—リセットã•ã‚ŒãŸç©ºã®è¨­å®šãŒé–¢é€£ä»˜ã‘られã¦ã„ã¾ã™ã€‚(時間グラフã«ç°è‰²ã®ç¯€ã¨ã—ã¦è¡¨ç¤ºã•ã‚Œã¾ã™ï¼‰
-ウィンドライト( WindLight )ã¯ã‚­ãƒ¼ãƒ•ãƒ¬ãƒ¼ãƒ é–“をデータ補間ã—ã€
-時間ã®çµŒéŽã¨ã¨ã‚‚ã«ç©ºã®è‡ªç„¶ãªã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’作り出ã—ã¾ã™ã€‚
-
-時間グラフã®ä¸Šã«è¡¨ç¤ºã•ã‚Œã‚‹é»„色ã®çŸ¢å°ã¯ã€æ™‚刻をもã¨ã«ã—ãŸç¾åœ¨ã®çœºã‚を表ã—ã¦ã„ã¾ã™ã€‚
-黄色ã®çŸ¢å°ã‚’クリック&ドラッグã™ã‚‹ã“ã¨ã§ã€
-1 æ—¥ã®ç§»ã‚Šå¤‰ã‚りを見るã“ã¨ãŒã§ãã¾ã™ã€‚
-「キーã®è¿½åŠ ã€ãƒœã‚¿ãƒ³ã¾ãŸã¯ã€Œã‚­ãƒ¼ã®å‰Šé™¤ã€ãƒœã‚¿ãƒ³ã‚’押ã—ã¦ã€
-時間グラフã®å³å´ã«ã‚­ãƒ¼ãƒ•ãƒ¬ãƒ¼ãƒ ã‚’追加ã‚ã‚‹ã„ã¯å‰Šé™¤ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
-
-キーフレームã®æ™‚刻を指定ã™ã‚‹ã«ã¯ã€
-時間グラフã«æ²¿ã£ã¦ãƒ‰ãƒ©ãƒƒã‚°ã™ã‚‹ã‹ã€Œã‚­ãƒ¼ãƒ•ãƒ¬ãƒ¼ãƒ ã®è¨­å®šã€ã®ãƒ•ãƒ¬ãƒ¼ãƒ å†…ã§å€¤ã‚’直接入力ã—ã¾ã™ã€‚
-「キーフレームã®è¨­å®šã€ã®ãƒ•ãƒ¬ãƒ¼ãƒ å†…ã§ã¯ã‚­ãƒ¼ãƒ•ãƒ¬ãƒ¼ãƒ ã«ã‚¦ã‚£ãƒ³ãƒ‰ãƒ©ã‚¤ãƒˆï¼ˆ WindLight )ã®äº‹å‰è¨­å®šã‚’関連付ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
-
-「サイクルã®é•·ã•ã€ã§ã¯1 日全体ã®æ™‚間を指定ã§ãã¾ã™ã€‚
-ã“ã®å€¤ã‚’低ã設定ã™ã‚‹ã¨ï¼ˆä¾‹ãˆã°2分)ã€24 時間ã®æ™‚間グラフã¯
-実時間㮠2 分間ã«ç›¸å½“ã™ã‚‹ã“ã¨ã‚’æ„味ã—ã¾ã™ã€‚
-時間グラフã¨ã‚­ãƒ¼ãƒ•ãƒ¬ãƒ¼ãƒ ãƒ»ã‚µã‚¤ã‚¯ãƒ«ã®è¨­å®šãŒå®Œäº†ã—ãŸã‚‰ã€
-「å†ç”Ÿã€ãƒœã‚¿ãƒ³ã¨ã€Œåœæ­¢ã€ãƒœã‚¿ãƒ³ã‚’使用ã—ã¦çµæžœã‚’プレビューã—ã¦ã¿ã¾ã—ょã†ã€‚
-ã¾ãŸã€æ™‚間グラフ上ã®é»„色ã„時刻表示矢å°ã‚’移動ã™ã‚‹ã“ã¨ã«ã‚ˆã£ã¦ã‚‚サイクルã®å¤‰åŒ–をインタラクティブã«ç¢ºèªã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ 「ä¸å‹•ç”£ã®æ™‚刻を使用ã€ãƒœã‚¿ãƒ³ã‚’使用ã™ã‚‹ã“ã¨ã§æ—¥ã®é•·ã•ã¨æ™‚刻ãŒä¸å‹•ç”£ã®ãƒ‡ã‚¤ãƒ»ã‚µã‚¤ã‚¯ãƒ«ã«åŒæœŸã•ã‚Œã¾ã™ã€‚
-
-デイ・サイクルã®è¨­å®šãŒå®Œäº†ã—ãŸã‚‰ã€ã€Œãƒ‡ã‚¤ãƒ»ãƒ†ã‚¹ãƒˆã‚’ä¿å­˜ã€ãƒœã‚¿ãƒ³ãŠã‚ˆã³ã€Œãƒ‡ã‚¤ãƒ»ãƒ†ã‚¹ãƒˆã‚’ロードã€ãƒœã‚¿ãƒ³ã‚’使用ã—ã¦ãƒ‡ã‚¤ãƒ»ã‚µã‚¤ã‚¯ãƒ«ã‚’ä¿å­˜ãŠã‚ˆã³ãƒ­ãƒ¼ãƒ‰ã—ã¾ã™ã€‚
-å°šã€ç¾åœ¨ã®ä»•æ§˜ã§ã¯ãƒ‡ã‚¤ãƒ»ã‚µã‚¤ã‚¯ãƒ«ã§æŒ‡å®šã§ãã‚‹ã®ã¯
-1 日分ã ã‘ã§ã™ã€‚
- </notification>
- <notification name="HelpBlueHorizon">
- 空ã®è‰²ã‚’調整ã™ã‚‹ã«ã¯ 「R〠(赤)ã€ã€ŒG〠(緑)ã€ã€ŒB〠(é’) ã®å„スライダーを使用ã—ã¾ã™ã€‚  「I〠スライダーを使用ã™ã‚‹ã¨ã€3 ã¤ã® RGB スライダーを一斉ã«å‹•ã‹ã™ã“ã¨ãŒã§ãã¾ã™ã€‚
- </notification>
- <notification name="HelpHazeHorizon">
- 「空ã¨é æ™¯ã®éœ²å…‰ã€ã¯é¢¨æ™¯ã®éœ²å…‰é‡å…¨ä½“を調整ã™ã‚‹ä¸Šã§æœ€ã‚‚便利ãªãƒ‘ラメーター㮠1 ã¤ã§ã™ã€‚ 太陽光ã«ã‚ˆã‚‹ãƒ›ãƒ¯ã‚¤ãƒˆã‚¢ã‚¦ãƒˆç¾è±¡ã‚„æš—ã絞り込んã è¨­å®šãªã©ã€ã•ã¾ã–ã¾ãªéœ²å‡ºè¨­å®šã‚’シミュレーションã§ãã¾ã™ã€‚
- </notification>
- <notification name="HelpBlueDensity">
- 「空ã®é…色ã¨æ¿ƒåº¦ã€ã¯ç©ºã¨éœ§ã®å½©åº¦å…¨ä½“ã«å½±éŸ¿ã—ã¾ã™ã€‚ 「I〠スライダーをå³ã«ç§»å‹•ã™ã‚‹ã¨è‰²ã¯æ˜Žã‚‹ããã£ãã‚Šã¨ãªã‚Šã¾ã™ã€‚
-ã“ã®ã‚¹ãƒ©ã‚¤ãƒ€ãƒ¼ã‚’左端ã«ç§»å‹•ã™ã‚‹ã¨ã€è‰²ã¯å½©ã‚Šã‚’失ã„ã€ç™½é»’ã«é€€è‰²ã—ã¾ã™ã€‚ 空ã®è‰²ã‚’微調整ã™ã‚‹å ´åˆã¯ã€
-「R〠(赤)〠「G〠(緑)〠「B〠(é’)
-ã®å„スライダーを使用ã—ã¦å½©åº¦ã‚’個別ã«åˆ¶å¾¡ã§ãã¾ã™ã€‚
- </notification>
- <notification name="HelpHazeDensity">
- 「大気ã®ä¸é€æ˜Žåº¦ã€ã¯å¤§æ°—中ã®ã©ã‚“よりã¨ã—ãŸç©ºã®é›°å›²æ°—ã€ã‚°ãƒ¬ãƒ¼ãŒã‹ã£ãŸéœ§ã®ãƒ¬ãƒ™ãƒ«ã‚’制御ã—ã¾ã™ã€‚ 濃ã„煙や大気汚染ãªã©
-を表ç¾ã™ã‚‹ã®ã«é©ã—ã¦ã„ã¾ã™ã€‚ 霧やもやãªã©ã®è¡¨ç¾æ‰‹æ®µã¨ã—ã¦ã‚‚効果的ã§ã™ã€‚
- </notification>
- <notification name="HelpDensityMult">
- 「大気ã®ä¸é€æ˜Žåº¦ã®å¢—å¹…ã€ã¯ç©ºæ°—ã®æ¿ƒåº¦å…¨ä½“を制御ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã§ãã¾ã™ã€‚ ã“ã®å€¤ã‚’低ã設定ã™ã‚‹ã¨ã€Œå¤§æ°—ã®è–„ã„状態ã€ã‚’演出ã—ã€é«˜ã„数値ã«è¨­å®šã™ã‚‹ã¨ã¨ã¦ã‚‚ã©ã‚“よりã¨ã—ãŸã‚¹ãƒ¢ãƒƒã‚°ã®ã‹ã‹ã£ãŸé›°å›²æ°—を表ç¾ã§ãã¾ã™ã€‚
- </notification>
- <notification name="HelpDistanceMult">
- ウィンドライトã®è¦–覚的è·é›¢ã‚’調整ã—ã¾ã™ã€‚ 値ã¨ã—ã¦ã‚¼ãƒ­ã‚’設定ã™ã‚‹ã¨ã€åœ°å½¢ãŠã‚ˆã³ã‚ªãƒ–ジェクトã«å¯¾ã™ã‚‹
-ウィンドライトã®å½±éŸ¿ã‚’効果的ã«å–り消ã™ã“ã¨ãŒã§ãã¾ã™ã€‚ 1 より大ããªå€¤ã‚’設定ã™ã‚‹å ´åˆã€å€¤ãŒå¤§ãããªã‚‹ã«ã¤ã‚Œã¦
-大気ãŒæ¬¡ç¬¬ã«æ¿ƒããªã‚‹ã‚ˆã†ãªåŠ¹æžœãŒå¾—られã¾ã™ã€‚
- </notification>
- <notification name="HelpMaxAltitude">
- 「最大高度ã€ã§ã¯å¤§æ°—中ã®å…‰ã®é‡ã‚’算出ã™ã‚‹ã¨ãã«
-ウィンドライトãŒç®—出ã—ãŸé«˜åº¦ã‚’調整ã—ã¾ã™ã€‚
-1æ—¥ã®çµ‚ã‚ã‚Šã«å¤•ç„¼ã‘ã®åº¦åˆã„を調整ã™ã‚‹ã¨ãã«å½¹ç«‹ã¡ã¾ã™ã€‚
- </notification>
- <notification name="HelpSunlightColor">
- 風景ã®ä¸­ã§ç›´å°„日光ã®è‰²ã‚„å¼·ã•ã‚’調整ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpSunAmbient">
- 風景ã®ä¸­ã§å‘¨å›²ã‚’ã¨ã‚Šã¾ã大気中ã®ã‚¢ãƒ³ãƒ“エント光ã®è‰²ã‚„å¼·ã•ã‚’調整ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpSunGlow">
- 「サイズã€ã‚¹ãƒ©ã‚¤ãƒ€ãƒ¼ã¯å¤ªé™½ã®å¤§ãã•ã‚’制御ã—ã¾ã™ã€‚
-「フォーカスã€ã‚¹ãƒ©ã‚¤ãƒ€ãƒ¼ã¯ç©ºã‚’背ã«ã—ãŸå¤ªé™½ã®ã‹ã™ã¿å…·åˆã‚’制御ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpSceneGamma">
- 風景ã®ä¸­ã§æ˜Žæš—ã®é…分を調整ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpStarBrightness">
- 空ã®æ˜Ÿã®è¼ãを調整ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpTimeOfDay">
- 空ã®å¤ªé™½ã®å ´æ‰€ã‚’調整ã—ã¾ã™ã€‚
-標高ã«ä¼¼ã¦ã„ã¾ã™ã€‚
- </notification>
- <notification name="HelpEastAngle">
- 空ã®å¤ªé™½ã®å ´æ‰€ã‚’調整ã—ã¾ã™ã€‚
-æ–¹ä½è§’ã«ä¼¼ã¦ã„ã¾ã™ã€‚
- </notification>
- <notification name="HelpCloudColor">
- 雲ã®è‰²ã‚’編集ã—ã¾ã™ã€‚ 通常ã¯ç™½ã£ã½ã„色をãŠå‹§ã‚ã—ã¾ã™ãŒã€ã‚‚ã¡ã‚ã‚“
-ãŠå¥½ã¿ã®è‰²ã‚’設定ã—ã¦ãã ã•ã„。
- </notification>
- <notification name="HelpCloudDetail">
- 主è¦ãªé›²ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã®ä¸Šã«ãƒ¬ã‚¤ãƒ¤ãƒ¼ã•ã‚ŒãŸè©³ç´°ãªã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’制御ã—ã¾ã™ã€‚ X 㨠Y ã§ãã®ä½ç½®ã‚’制御ã—ã¾ã™ã€‚
-「Dã€ï¼ˆæ¿ƒåº¦ï¼‰ã¯çœŸç¶¿ã®ã‚ˆã†ãªæ§˜å­ã‚„ã€
-雲ã®å‰²ã‚Œç›®ã®æ§˜å­ãªã©é›²ã®å¤–観を制御ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpCloudDensity">
- 「X〠㨠「Y〠ã®ã‚¹ãƒ©ã‚¤ãƒ€ãƒ¼ã§é›²ã®ä½ç½®ã‚’ã€
-「Dã€ã®ã‚¹ãƒ©ã‚¤ãƒ€ãƒ¼ã§ãã®å¯†åº¦ã‚’制御ã§ãã¾ã™ã€‚
- </notification>
- <notification name="HelpCloudCoverage">
- 空を覆ã†é›²ã®é‡ã‚’制御ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpCloudScale">
- 空ã«æµ®ã‹ã¶é›²ã®ã‚¤ãƒ¡ãƒ¼ã‚¸ã®ç¸®å°ºã‚’制御ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpCloudScrollX">
- 「X〠ã®æ–¹å‘ã«é›²ãŒç§»å‹•ã™ã‚‹éš›ã®é€Ÿåº¦ã‚’制御ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpCloudScrollY">
- 「Y〠ã®æ–¹å‘ã«é›²ãŒç§»å‹•ã™ã‚‹éš›ã®é€Ÿåº¦ã‚’制御ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpClassicClouds">
- ã“ã®ãƒœãƒƒã‚¯ã‚¹ã‚’有効ã«ã™ã‚‹ã¨ã€WindLight ã®é›²ã«åŠ ãˆã¦ã€Second Life ã®å¾“æ¥ã®é›²ã‚‚レンダリングã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚
- </notification>
- <notification name="HelpWaterFogColor">
- 水中ã®ãƒ•ã‚©ã‚°åŠ¹æžœã«è‰²ã‚’ã¤ã‘ã¾ã™ã€‚
- </notification>
- <notification name="HelpWaterFogDensity">
- 水中ã®ãƒ•ã‚©ã‚°åŠ¹æžœã®å¼·å¼±ã€æ°´ä¸­ã§ã©ã®ãらã„ã®è·é›¢ã¾ã§è¦‹æ¸¡ã›ã‚‹ã‹ã‚’制御ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpUnderWaterFogMod">
- 「水中ã®ãƒ•ã‚©ã‚°æ¿ƒåº¦æŒ‡æ•°ã€ã®åŠ¹æžœã‚’加減ã—ã¦ã€ã‚ãªãŸã®ã‚¢ãƒã‚¿ãƒ¼ãŒæ°´ä¸­ã«ã„ã‚‹ã¨ãã€ã©ã®ãらã„é ãã¾ã§è¦‹ã‚‹ã“ã¨ãŒã§ãã‚‹ã‹ã‚’制御ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpWaterGlow">
- æ°´é¢ã®è¼ãã®åº¦åˆã„を制御ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpWaterNormalScale">
- æ°´é¢ã‚’表ç¾ã™ã‚‹ 3 種類ã®ã•ã–æ³¢ã®ç¸®å°ºã‚’制御ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpWaterFresnelScale">
- ã•ã¾ã–ã¾ãªè§’度ã§ã€åå°„ã™ã‚‹å…‰ã®é‡ã‚’制御ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpWaterFresnelOffset">
- åå°„ã™ã‚‹å…‰åº¦ã®é‡ã‚’制御ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpWaterScaleAbove">
- 上ã‹ã‚‰æ°´ä¸­ã‚’見ãŸã¨ãã®å…‰ã®å±ˆæŠ˜å…·åˆã‚’制御ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpWaterScaleBelow">
- 水中ã‹ã‚‰è¦‹ãŸã¨ãã®å…‰ã®å±ˆæŠ˜å…·åˆã‚’制御ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpWaterBlurMultiplier">
- æ³¢ã¨åå°„ã®æ··ã–ã‚Šå…·åˆã‚’制御ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpWaterNormalMap">
- å射や屈折を決定ã™ã‚‹ãŸã‚ã«æ°´ã«é‡ã­ã‚‰ã‚Œã‚‹ãƒŽãƒ¼ãƒžãƒ«ãƒ»ãƒžãƒƒãƒ—を制御ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpWaterWave1">
- 拡大ã•ã‚ŒãŸãƒŽãƒ¼ãƒžãƒ«ãƒ»ãƒžãƒƒãƒ—ãŒç§»å‹•ã™ã‚‹æ–¹å‘(X 軸㨠Y 軸ã§è¡¨ç¾ï¼‰ã¨é€Ÿåº¦ã‚’制御ã—ã¾ã™ã€‚
- </notification>
- <notification name="HelpWaterWave2">
- 縮å°ã•ã‚ŒãŸãƒŽãƒ¼ãƒžãƒ«ãƒ»ãƒžãƒƒãƒ—ãŒç§»å‹•ã™ã‚‹æ–¹å‘(X 軸㨠Y 軸ã§è¡¨ç¾ï¼‰ã¨é€Ÿåº¦ã‚’制御ã—ã¾ã™ã€‚
- </notification>
<notification name="NewSkyPreset">
æ–°ã—ã„空ã®åå‰ã‚’指定ã—ã¦ãã ã•ã„。
<form name="form">
- <input name="message" type="text">
+ <input name="message">
æ–°ã—ã„事å‰è¨­å®š
</input>
<button name="OK" text="OK"/>
@@ -2537,7 +1926,7 @@ Second Life ã§ã®æ˜¼ã¨å¤œã®ç©ºã®å¤‰åŒ–を制御ã§ãã¾ã™ã€‚
<notification name="NewWaterPreset">
æ–°ã—ã„æ°´ã®äº‹å‰è¨­å®šã®åå‰ã‚’指定ã—ã¦ãã ã•ã„。
<form name="form">
- <input name="message" type="text">
+ <input name="message">
æ–°ã—ã„事å‰è¨­å®š
</input>
<button name="OK" text="OK"/>
@@ -2566,8 +1955,7 @@ Second Life ã§ã®æ˜¼ã¨å¤œã®ç©ºã®å¤‰åŒ–を制御ã§ãã¾ã™ã€‚
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="Cannot_Purchase_an_Attachment">
- アイテムãŒæ·»ä»˜ç‰©ã®ä¸€éƒ¨ã§ã‚ã‚‹é–“ã¯ã€
-アイテムを購入ã§ãã¾ã›ã‚“。
+ オブジェクトãŒå–り付ã‘られã¦ã„ã‚‹ã¨ãã¯è³¼å…¥ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
</notification>
<notification label="デビット許å¯ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã«ã¤ã„ã¦" name="DebitPermissionDetails">
ã“ã®è¦æ±‚を許å¯ã™ã‚‹ã¨ã€ã‚¹ã‚¯ãƒªãƒ—トã‹ã‚‰ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ãƒªãƒ³ãƒ‡ãƒ³ãƒ‰ãƒ«ã‚’課金ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚
@@ -2575,30 +1963,26 @@ Second Life ã§ã®æ˜¼ã¨å¤œã®ç©ºã®å¤‰åŒ–を制御ã§ãã¾ã™ã€‚
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="AutoWearNewClothing">
- ã‚ãªãŸãŒä½œæˆã—ãŸæœã‚¢ã‚¤ãƒ†ãƒ ã‚’自動的ã«è£…ç€ã—ã¾ã™ã‹ï¼Ÿ
- <usetemplate ignoretext="æ–°ã—ã„æœã‚’自動的ã«è£…ç€ã™ã‚‹" name="okcancelignore" notext="ã„ã„ãˆ" yestext="ã¯ã„"/>
+ 作æˆã—よã†ã¨ã—ã¦ã„る衣類を自動的ã«è£…ç€ã—ã¾ã™ã‹ï¼Ÿ
+ <usetemplate ignoretext="「マイ 容姿ã€ã‚’編集中ã«ã€ä½œæˆã™ã‚‹è¡£é¡žã‚’装ç€ã™ã‚‹" name="okcancelignore" notext="ã„ã„ãˆ" yestext="ã¯ã„"/>
</notification>
<notification name="NotAgeVerified">
- ã“ã®åŒºç”»ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ãŸã‚ã«ã¯ã€
-年齢確èªã‚’è¡Œã†å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
-Second Life ã®ã‚¦ã‚§ãƒ–サイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã€
-年齢確èªã‚’è¡Œã„ã¾ã™ã‹ï¼Ÿ
+ 年齢確èªã‚’済ã¾ã›ã¦ã„ãªã„ã¨ã“ã®åŒºç”»ã‚’訪れるã“ã¨ãŒã§ãã¾ã›ã‚“。 [SECOND_LIFE] サイトã§å¹´é½¢ã®ç¢ºèªã‚’è¡Œã„ã¾ã™ã‹ï¼Ÿ
[_URL]
<url name="url" option="0">
https://secondlife.com/account/verification.php?lang=ja
</url>
- <usetemplate ignoretext="å¹´é½¢ã®æœªç¢ºèªã«ã¤ã„ã¦è­¦å‘Šã™ã‚‹" name="okcancelignore" notext="ã„ã„ãˆ" yestext="ã¯ã„"/>
+ <usetemplate ignoretext="å¹´é½¢ã®ç¢ºèªã‚’済ã¾ã›ã¦ã„ã¾ã›ã‚“" name="okcancelignore" notext="ã„ã„ãˆ" yestext="ã¯ã„"/>
</notification>
<notification name="Cannot enter parcel: no payment info on file">
- ã“ã®åŒºç”»ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã«ã¯ã€æ”¯æ‰•ã„情報ãŒäº‹å‰ã«ç™»éŒ²ã•ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
-Second Life ã®ã‚¦ã‚§ãƒ–サイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã€è¨­å®šã—ã¾ã™ã‹ï¼Ÿ
+ 支払情報ãŒç™»éŒ²ã•ã‚Œã¦ã„ãªã„ã¨ã“ã®ã‚¨ãƒªã‚¢ã‚’訪れるã“ã¨ãŒã§ãã¾ã›ã‚“。 [SECOND_LIFE] サイトã§ç™»éŒ²ã‚’è¡Œã„ã¾ã™ã‹ï¼Ÿ
[_URL]
<url name="url" option="0">
https://secondlife.com/account/index.php?lang=ja
</url>
- <usetemplate ignoretext="支払ã„情報ã®æœªç™»éŒ²ã«ã¤ã„ã¦è­¦å‘Šã™ã‚‹" name="okcancelignore" notext="ã„ã„ãˆ" yestext="ã¯ã„"/>
+ <usetemplate ignoretext="支払情報ãŒç™»éŒ²ã•ã‚Œã¦ã„ã¾ã›ã‚“" name="okcancelignore" notext="ã„ã„ãˆ" yestext="ã¯ã„"/>
</notification>
<notification name="MissingString">
文字列[STRING_NAME]ãŒstrings.xmlã«å«ã¾ã‚Œã¦ã„ã¾ã›ã‚“
@@ -2628,7 +2012,7 @@ Second Life ã®ã‚¦ã‚§ãƒ–サイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã€è¨­å®šã—ã¾ã™ã‹ï¼Ÿ
[FIRST] [LAST] ã¯ã‚ªãƒ•ãƒ©ã‚¤ãƒ³ã§ã™ã€‚
</notification>
<notification name="AddSelfFriend">
- 自分自身をフレンドã«ã¯ã§ãã¾ã›ã‚“。
+ 残念ãªãŒã‚‰è‡ªåˆ†è‡ªèº«ã‚’フレンド登録ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
</notification>
<notification name="UploadingAuctionSnapshot">
インワールドã¨ã‚¦ã‚§ãƒ–・サイトã®ã‚¹ãƒŠãƒƒãƒ—ショットをアップロード中ã§ã™...
@@ -2647,7 +2031,7 @@ Second Life ã®ã‚¦ã‚§ãƒ–サイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã€è¨­å®šã—ã¾ã™ã‹ï¼Ÿ
raw地形ãŒãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã•ã‚Œã¾ã—ãŸ
</notification>
<notification name="GestureMissing">
- ジェスãƒãƒ£ãƒ¼[NAME] ãŒãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ã‚ã‚Šã¾ã›ã‚“。
+ ジェスãƒãƒ£ãƒ¼ã® [NAME] ãŒãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
</notification>
<notification name="UnableToLoadGesture">
ジェスãƒãƒ£ãƒ¼[NAME] を読ã¿è¾¼ã‚€ã“ã¨ãŒã§ãã¾ã›ã‚“。
@@ -2660,15 +2044,14 @@ Second Life ã®ã‚¦ã‚§ãƒ–サイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã€è¨­å®šã—ã¾ã™ã‹ï¼Ÿ
ランドマークをロードã§ãã¾ã›ã‚“。 ã‚‚ã†ä¸€åº¦è©¦ã—ã¦ãã ã•ã„。
</notification>
<notification name="CapsKeyOn">
- コンピューター㮠Caps LockキーãŒ
-有効ã«ãªã£ã¦ã„ã¾ã™ã€‚パスワード入力ã«
-影響ã™ã‚‹ã®ã§è§£é™¤ã—ã¾ã—ょã†ã€‚
+ CapsLock キーãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã™ã€‚
+パスワードã«å½±éŸ¿ãŒã‚ã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。
</notification>
<notification name="NotecardMissing">
ノートカードãŒãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ã‚ã‚Šã¾ã›ã‚“。
</notification>
<notification name="NotecardNoPermissions">
- ノートカードを閲覧ã™ã‚‹ã«ã¯æ¨©é™ãŒä¸å分ã§ã™
+ ã“ã®ãƒŽãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã‚’見る権é™ãŒã‚ã‚Šã¾ã›ã‚“。
</notification>
<notification name="RezItemNoPermissions">
オブジェクトをrezã™ã‚‹ã«ã¯ãƒ‘ーミッション(承èªï¼‰ãŒä¸è¶³ã—ã¦ã¾ã™ã€‚
@@ -2708,23 +2091,23 @@ Second Life ã®ã‚¦ã‚§ãƒ–サイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã€è¨­å®šã—ã¾ã™ã‹ï¼Ÿ
ã‚‚ã†ä¸€åº¦è©¦ã—ã¦ãã ã•ã„。
</notification>
<notification name="CannotBuyObjectsFromDifferentOwners">
- 複数ã®ã‚ªãƒ¼ãƒŠãƒ¼ã‹ã‚‰åŒæ™‚ã«ã‚ªãƒ–ジェクトを購入ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
-å˜ä¸€ã®ã‚ªãƒ–ジェクトをé¸æŠžã—ã¦ãã ã•ã„。
+ オブジェクトã¯ä¸€åº¦ã«ã¤ã一人ã®æ‰€æœ‰è€…ã‹ã‚‰è³¼å…¥ã§ãã¾ã™ã€‚
+オブジェクトを 1 ã¤ã ã‘é¸ã‚“ã§ãã ã•ã„。
</notification>
<notification name="ObjectNotForSale">
- オブジェクトã¯è²©å£²å¯¾è±¡ã§ã¯ã‚ã‚Šã¾ã›ã‚“。
+ ã“ã®ã‚ªãƒ–ジェクトã¯è²©å£²å¯¾è±¡ã§ã¯ã‚ã‚Šã¾ã›ã‚“。
</notification>
<notification name="EnteringGodMode">
レベル[LEVEL]ã®ã‚´ãƒƒãƒ‰ãƒ»ãƒ¢ãƒ¼ãƒ‰ã«å…¥ã‚Šã¾ã™
</notification>
<notification name="LeavingGodMode">
- レベル[LEVEL]ã®ã‚´ãƒƒãƒ‰ãƒ»ãƒ¢ãƒ¼ãƒ‰ã‚’解除
+ レベル [LEVEL] ã®ã‚´ãƒƒãƒ‰ãƒ¢ãƒ¼ãƒ‰ã‚’解除ã—ã¾ã™
</notification>
<notification name="CopyFailed">
- コピー権é™ãŒãªã„ãŸã‚ã€ã‚³ãƒ”ーã«å¤±æ•—ã—ã¾ã—ãŸ
+ ã“れをコピーã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“。
</notification>
<notification name="InventoryAccepted">
- [NAME]ã¯ã€æŒã¡ç‰©ã®æ供をå—ã‘入れã¾ã—ãŸã€‚
+ [NAME] ãŒã‚ãªãŸãŒæ¸¡ã—ãŸã‚¢ã‚¤ãƒ†ãƒ ã‚’å—ã‘å–ã‚Šã¾ã—ãŸã€‚
</notification>
<notification name="InventoryDeclined">
[NAME]ã¯ã€æŒã¡ç‰©ã®æ供を断りã¾ã—ãŸã€‚
@@ -2739,14 +2122,14 @@ Second Life ã®ã‚¦ã‚§ãƒ–サイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã€è¨­å®šã—ã¾ã™ã‹ï¼Ÿ
コーリング・カードãŒæ‹’å¦ã•ã‚Œã¾ã—ãŸã€‚
</notification>
<notification name="TeleportToLandmark">
- 本土ã«åˆ°é”ã—ã¾ã—ãŸã€‚
-[NAME]ãªã©ã®å ´æ‰€ã«ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ã€ç”»é¢å³ä¸‹ã«ã‚る「æŒã¡ç‰©ã€ãƒœã‚¿ãƒ³ã‚’クリックã—ã€ãƒ©ãƒ³ãƒ‰ãƒžãƒ¼ã‚¯ï¼ˆLandmarks)フォルダをé¸æŠžã—ã¦ãã ã•ã„。
-ランドマークをダブルクリックã—ãŸå¾Œã€Œãƒ†ãƒ¬ãƒãƒ¼ãƒˆã€ã‚’クリックã™ã‚‹ã¨ãã®å ´æ‰€ã¸ç§»å‹•ã—ã¾ã™ã€‚
+ ç”»é¢å³ã®ã€Œå ´æ‰€ã€ãƒ‘ãƒãƒ«ã‚’é–‹ã„ã¦ã€ã€Œãƒ©ãƒ³ãƒ‰ãƒžãƒ¼ã‚¯ã€ã‚¿ãƒ–ã‚’é¸ã¶ã¨ã€[NAME] ã¨ã„ã£ãŸå ´æ‰€ã«ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã§ãã¾ã™ã€‚
+好ããªãƒ©ãƒ³ãƒ‰ãƒžãƒ¼ã‚¯ã‚’クリックã—ã¦é¸ã³ã€æ¬¡ã«ãƒ‘ãƒãƒ«ä¸‹ã®ã€Œãƒ†ãƒ¬ãƒãƒ¼ãƒˆã€ã‚’クリックã—ã¾ã™ã€‚
+(ランドマークをダブルクリックã€ã¾ãŸã¯å³ã‚¯ãƒªãƒƒã‚¯ã—ã¦ã€Œãƒ†ãƒ¬ãƒãƒ¼ãƒˆã€ã‚’é¸ã‚“ã§ã‚‚åŒã˜ã§ã™ã€‚)
</notification>
<notification name="TeleportToPerson">
- 本土ã«åˆ°é”ã—ã¾ã—ãŸã€‚
-ä½äººã®[NAME]ã¨æŽ¥è§¦ã™ã‚‹ã«ã¯ã€ç”»é¢å³ä¸‹ã«ã‚る「æŒã¡ç‰©ã€ãƒœã‚¿ãƒ³ã‚’クリックã—ã€ã‚³ãƒ¼ãƒªãƒ³ã‚°ã‚«ãƒ¼ãƒ‰ï¼ˆCalling Cards)フォルダをé¸æŠžã—ã¦ãã ã•ã„。
-カードをダブルクリックã—ã€ã€ŒIMã‚’é€ã‚‹ã€ã‚’クリックã—ã€ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’é€ä¿¡ã—ã¦ãã ã•ã„。
+ ç”»é¢å³ã®ã€Œäººã€ãƒ‘ãƒãƒ«ã‚’é–‹ã„ã¦ã€[NAME] ã¨ã„ã£ãŸä½äººã«é€£çµ¡ã‚’å–ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+リストã‹ã‚‰ä½äººã‚’é¸æŠžã—ã¦ã€ãƒ‘ãƒãƒ«ä¸‹ã®ã€ŒIMã€ã‚’クリックã—ã¾ã™ã€‚
+(リストã®åå‰ã‚’ダブルクリックã€ã¾ãŸã¯å³ã‚¯ãƒªãƒƒã‚¯ã—ã¦ã€ŒIMã€ã‚’é¸ã‚“ã§ã‚‚åŒã˜ã§ã™ã€‚)
</notification>
<notification name="CantSelectLandFromMultipleRegions">
サーãƒãƒ¼ã®å¢ƒç•Œã‚’越ãˆã¦åœŸåœ°ã‚’é¸æŠžã™ã‚‹ã“ã¨ã§ãã¾ã›ã‚“。
@@ -2794,8 +2177,20 @@ Second Life ã®ã‚¦ã‚§ãƒ–サイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã€è¨­å®šã—ã¾ã™ã‹ï¼Ÿ
[NAMES]
</notification>
<notification name="NoQuickTime">
- Apple社ã®QuickTimeãŒã‚·ã‚¹ãƒ†ãƒ ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ãªã„ã¨æ€ã‚ã‚Œã¾ã™ã€‚
-ストリーミング・メディアã®å†ç”Ÿã‚’è¡Œã„ãŸã„å ´åˆã¯ã€QuickTimeã®ã‚µã‚¤ãƒˆï¼ˆhttp://www.apple.com/quicktime)ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã€QuickTime Player をインストールã—ã¦ãã ã•ã„。
+ Apple ã® QuickTime ソフトウェアãŒãŠä½¿ã„ã®ã‚·ã‚¹ãƒ†ãƒ ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ãªã„よã†ã§ã™ã€‚
+ストリーミングメディアをサãƒãƒ¼ãƒˆã™ã‚‹åŒºç”»ã§è¦‹ãŸã„å ´åˆã¯ã€[http://www.apple.com/jp/quicktime QuickTime サイト] ã‹ã‚‰ QuickTime プレイヤーをインストールã—ã¦ãã ã•ã„。
+ </notification>
+ <notification name="NoPlugin">
+ 「 [MIME_TYPE] ã€ã® MIME タイプを扱ã†ãƒ¡ãƒ‡ã‚£ã‚¢ãƒ—ラグインãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚ ã“ã®ã‚¿ã‚¤ãƒ—ã®ãƒ¡ãƒ‡ã‚£ã‚¢ã¯ã”利用ã„ãŸã ã‘ã¾ã›ã‚“。
+ </notification>
+ <notification name="MediaPluginFailed">
+ 次ã®ãƒ¡ãƒ‡ã‚£ã‚¢ãƒ—ラグインãŒå®Ÿè¡Œã§ãã¾ã›ã‚“ã§ã—ãŸï¼š
+ [PLUGIN]
+
+プラグインをインストールã—ãªãŠã™ã‹ã€å•é¡ŒãŒè§£æ±ºã—ãªã„å ´åˆã¯ãƒ¡ãƒ¼ã‚«ãƒ¼ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。
+ <form name="form">
+ <ignore name="ignore" text="メディアプラグインã®å®Ÿè¡Œã«å¤±æ•—"/>
+ </form>
</notification>
<notification name="OwnedObjectsReturned">
é¸æŠžã—ãŸåœŸåœ°ã®åŒºç”»ä¸Šã«ã‚ã£ãŸã‚ãªãŸã®ã‚ªãƒ–ジェクトã¯ã€ã‚ãªãŸã®æŒã¡ç‰©ã«è¿”å´ã•ã‚Œã¾ã—ãŸã€‚
@@ -2817,24 +2212,27 @@ Second Life ã®ã‚¦ã‚§ãƒ–サイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã€è¨­å®šã—ã¾ã™ã‹ï¼Ÿ
<notification name="UnOwnedObjectsReturned">
é¸æŠžã•ã‚ŒãŸåœŸåœ°ã®åŒºç”»ä¸Šã«ã‚ã‚Šã€ã‚ãªãŸã®æ‰€æœ‰ã§ã€Œãªã‹ã£ãŸã€ã‚ªãƒ–ジェクトã¯ã€æœ¬æ¥ã®ã‚ªãƒ¼ãƒŠãƒ¼ã«è¿”å´ã•ã‚Œã¾ã—ãŸã€‚
</notification>
+ <notification name="ServerObjectMessage">
+ [NAME] ã‹ã‚‰ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ï¼š
+[MSG]
+ <usetemplate name="okcancelbuttons" notext="OK" yestext="調ã¹ã‚‹"/>
+ </notification>
<notification name="NotSafe">
- ã“ã®åœŸåœ°ã¯ãƒ€ãƒ¡ãƒ¼ã‚¸ãŒæœ‰åŠ¹ï¼ˆã€Œå®‰å…¨ã§ã¯ãªã„ã€ï¼‰ã«è¨­å®šã•ã‚Œã¦ã„ã¾ã™ã€‚
-ケガをã™ã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。 命をè½ã¨ã—ãŸå ´åˆã¯ã€ãƒ›ãƒ¼ãƒ ã«ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã•ã‚Œã¾ã™ã€‚
+ ã“ã®åœŸåœ°ã§ã¯ãƒ€ãƒ¡ãƒ¼ã‚¸ãŒæœ‰åŠ¹ã§ã™ã€‚
+ケガをã™ã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。 死んã§ã—ã¾ã£ãŸå ´åˆã¯ãƒ›ãƒ¼ãƒ ã«ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã•ã‚Œã¾ã™ã€‚
</notification>
<notification name="NoFly">
- ã“ã®åœŸåœ°ã¯é£›è¡ŒãŒç„¡åŠ¹ï¼ˆã€Œé£›è¡Œç¦æ­¢ã€ï¼‰ã«è¨­å®šã•ã‚Œã¦ã„ã¾ã™ã€‚
-ã“ã“ã§é£›ã¶ã“ã¨ã¯ã§ãã¾ã›ã‚“。
+ ã“ã®ã‚¨ãƒªã‚¢ã§ã¯é£›è¡ŒãŒç¦æ­¢ã•ã‚Œã¦ã„ã¾ã™ã€‚
+ã“ã“ã§ã¯é£›ã¹ã¾ã›ã‚“。
</notification>
<notification name="PushRestricted">
- ã“ã®åœŸåœ°ã§ã¯ã€Œãƒ—ッシングç¦æ­¢ã€ã§ã™ã€‚
-土地所有者以外ã¯ã“ã“ã§ä»–人をプッシュã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
+ ã“ã®ã‚¨ãƒªã‚¢ã§ã¯ãƒ—ッシュãŒåˆ¶é™ã•ã‚Œã¦ã„ã¾ã™ã€‚ 土地所有者以外ã¯ä»–人をプッシュã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
</notification>
<notification name="NoVoice">
- ã“ã®åœŸåœ°ã¯ãƒœã‚¤ã‚¹ãŒç„¡åŠ¹ã«è¨­å®šã•ã‚Œã¦ã„ã¾ã™ã€‚
+ ã“ã®ã‚¨ãƒªã‚¢ã§ã¯ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆãŒç„¡åŠ¹ã§ã™ã€‚ 誰ã‹ãŒè©±ã—ã¦ã„ã‚‹ã®ã‚’èžãã“ã¨ã¯ã§ãã¾ã›ã‚“。
</notification>
<notification name="NoBuild">
- ã“ã®åœŸåœ°ã¯ã‚ªãƒ–ジェクトã®ä½œæˆç¦æ­¢ã«è¨­å®šã•ã‚Œã¦ã„ã¾ã™ã€‚
-ã“ã“ã§ã‚ªãƒ–ジェクトを作るã“ã¨ã¯ã§ãã¾ã›ã‚“。
+ ã“ã®ã‚¨ãƒªã‚¢ã§ã¯åˆ¶ä½œãŒç¦æ­¢ã•ã‚Œã¦ã„ã¾ã™ã€‚ オブジェクトを制作ã—ãŸã‚Š Rez ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
</notification>
<notification name="ScriptsStopped">
管ç†è€…ãŒã“ã®åœ°åŸŸå†…ã®ã‚¹ã‚¯ãƒªãƒ—トを一時åœæ­¢ã•ã›ã¾ã—ãŸã€‚
@@ -2843,12 +2241,12 @@ Second Life ã®ã‚¦ã‚§ãƒ–サイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã€è¨­å®šã—ã¾ã™ã‹ï¼Ÿ
ã“ã®åœ°åŸŸã§ã¯ã‚¹ã‚¯ãƒªãƒ—トã®ä½¿ç”¨ãŒç¦æ­¢ã•ã‚Œã¦ã„ã¾ã™
</notification>
<notification name="NoOutsideScripts">
- ã“ã®åœŸåœ°ã§ã¯å¤–部スクリプトãŒç„¡åŠ¹ã«è¨­å®šã•ã‚Œã¦ã„ã¾ã™ã€‚
-(「外部スクリプトç¦æ­¢ã€ï¼‰
-土地所有者以外ã®ã‚¹ã‚¯ãƒªãƒ—トã¯èµ·å‹•ã§ãã¾ã›ã‚“
+ ã“ã®åœŸåœ°ã§ã¯ã€å¤–部ã®ã‚¹ã‚¯ãƒªãƒ—トãŒç¦æ­¢ã•ã‚Œã¦ã„ã¾ã™ã€‚
+
+土地所有者ã®ã‚‚ã®ä»¥å¤–ã¯ã‚¹ã‚¯ãƒªãƒ—トã¯å®Ÿè¡Œã•ã‚Œã¾ã›ã‚“。
</notification>
<notification name="ClaimPublicLand">
- 自分ãŒã„る地域ã§ã®ã¿å…¬å…±ã®åœŸåœ°ã‚’ç²å¾—ã§ãã¾ã™ã€‚
+ ãã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã«ã„ãªã„ã¨å…¬å…±ã®åœŸåœ°ã‚’å–å¾—ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
</notification>
<notification name="RegionTPAccessBlocked">
ã‚ãªãŸã®ãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°åŒºåˆ†ã«ã‚ˆã‚Šãã®åœ°åŸŸï¼ˆãƒªãƒ¼ã‚¸ãƒ§ãƒ³ï¼‰ã¸ã¯å…¥ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。 年齢確èªã‚’è¡Œã†ã‹ã€æœ€æ–°ãƒ“ューワをインストールã—ã¦ãã ã•ã„。
@@ -2861,16 +2259,11 @@ Second Life ã®ã‚¦ã‚§ãƒ–サイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã€è¨­å®šã—ã¾ã™ã‹ï¼Ÿ
<notification name="NoTeenGridAccess">
ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã§ã¯ãƒ†ã‚£ãƒ¼ãƒ³ã‚°ãƒªãƒƒãƒ‰ã«æŽ¥ç¶šã§ãã¾ã›ã‚“。
</notification>
- <notification name="NoHelpIslandTP">
- Help Islandã«ã¯æˆ»ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
-「Help Island Publicã€ã«è¡Œãã€
-å†åº¦ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«ã‚’è¡Œã£ã¦ãã ã•ã„。
- </notification>
<notification name="ImproperPaymentStatus">
ã“ã®åœ°åŸŸï¼ˆãƒªãƒ¼ã‚¸ãƒ§ãƒ³ï¼‰ã«å…¥ã‚‹ãŸã‚ã«é©ã—ãŸæ”¯æ‰•ã„ステータスãŒã‚ã‚Šã¾ã›ã‚“。
</notification>
<notification name="MustGetAgeRgion">
- ã“ã®åœ°åŸŸï¼ˆãƒªãƒ¼ã‚¸ãƒ§ãƒ³ï¼‰ã«å…¥ã‚‹ã«ã¯å¹´é½¢ç¢ºèªæ¸ˆã¿ã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+ ã“ã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã«å…¥ã‚‹ã«ã¯å¹´é½¢ç¢ºèªæ¸ˆã¿ã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
</notification>
<notification name="MustGetAgeParcel">
ã“ã®åŒºç”»ã«å…¥ã‚‹ã«ã¯å¹´é½¢ç¢ºèªæ¸ˆã¿ã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
@@ -2934,34 +2327,35 @@ Second Life ã®ã‚¦ã‚§ãƒ–サイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã€è¨­å®šã—ã¾ã™ã‹ï¼Ÿ
有効ãªåŒºç”»ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚
</notification>
<notification name="ObjectGiveItem">
- [FIRST] [LAST]所有ã®ã€
-[OBJECTFROMNAME]ã‹ã‚‰ã€
-[OBJECTNAME]ã¨ã„ã†[OBJECTTYPE]ãŒé€ã‚‰ã‚Œã¦ãã¾ã—ãŸã€‚
+ [NAME_SLURL] ãŒæ‰€æœ‰ã™ã‚‹ [OBJECTFROMNAME] ãŒã€ã‚ãªãŸã« [OBJECTTYPE] :
+[ITEM_SLURL] を渡ã—ã¾ã—ãŸ
<form name="form">
<button name="Keep" text="å—ã‘å–ã‚‹"/>
<button name="Discard" text="破棄"/>
- <button name="Mute" text="無視リストã¸"/>
+ <button name="Mute" text="ブロック"/>
</form>
</notification>
<notification name="ObjectGiveItemUnknownUser">
- (未知ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ï¼‰ 所有ã®[OBJECTFROMNAME]ã‹ã‚‰ã€
-ã‚ãªãŸã«[OBJECTNAME]ã¨ã„ã†[OBJECTTYPE]ãŒé€ã‚‰ã‚Œã¦ãã¾ã—ãŸã€‚
+ (ä¸æ˜Žã®ä½äººï¼‰ãŒæ‰€æœ‰ã™ã‚‹ [OBJECTFROMNAME] ãŒã€ã‚ãªãŸã« [OBJECTTYPE] :
+[ITEM_SLURL] を渡ã—ã¾ã—ãŸ
<form name="form">
<button name="Keep" text="å—ã‘å–ã‚‹"/>
<button name="Discard" text="破棄"/>
- <button name="Mute" text="無視リストã¸"/>
+ <button name="Mute" text="ブロック"/>
</form>
</notification>
<notification name="UserGiveItem">
- [NAME]ã¯ã€ã‚ãªãŸã«[OBJECTNAME]ã¨ã„ã†åå‰ã®[OBJECTTYPE]を渡ã—ã¾ã—ãŸã€‚
+ [NAME_SLURL] ãŒã‚ãªãŸã« [OBJECTTYPE]:
+[ITEM_SLURL] を渡ã—ã¾ã—ãŸ
<form name="form">
<button name="Keep" text="å—ã‘å–ã‚‹"/>
+ <button name="Show" text="表示"/>
<button name="Discard" text="破棄"/>
- <button name="Mute" text="無視リストã¸"/>
</form>
</notification>
<notification name="GodMessage">
[NAME]
+
[MESSAGE]
</notification>
<notification name="JoinGroup">
@@ -2973,7 +2367,7 @@ Second Life ã®ã‚¦ã‚§ãƒ–サイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã€è¨­å®šã—ã¾ã™ã‹ï¼Ÿ
</form>
</notification>
<notification name="TeleportOffered">
- [NAME]ã¯ã‚ãªãŸã‚’テレãƒãƒ¼ãƒˆã§å‘¼ã³å¯„ã›ã‚ˆã†ã¨ã—ã¦ã„ã¾ã™ï¼š
+ [NAME] ã¯ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã§ã‚ãªãŸã‚’呼んã§ã„ã¾ã™ã€‚
[MESSAGE]
<form name="form">
@@ -3027,12 +2421,12 @@ Second Life ã®ã‚¦ã‚§ãƒ–サイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã€è¨­å®šã—ã¾ã™ã‹ï¼Ÿ
</form>
</notification>
<notification name="RegionRestartMinutes">
- ã“ã®åœ°åŸŸã¯[MINUTES]分後ã«å†èµ·å‹•ã•ã‚Œã¾ã™ã€‚
-強制ログアウトã¨ãªã‚Šã¾ã™ã®ã§ã€ã“ã®åœ°åŸŸã®å¤–ã«å‡ºã¦ãã ã•ã„。
+ ã“ã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã¯ [SECONDS] 分後ã«å†èµ·å‹•ã•ã‚Œã¾ã™ã€‚
+ã“ã®ã¾ã¾ã“ã“ã«ã„ã‚‹ã¨ãƒ­ã‚°ã‚¢ã‚¦ãƒˆã•ã‚Œã¾ã™ã€‚
</notification>
<notification name="RegionRestartSeconds">
- ã“ã®åœ°åŸŸã¯[SECONDS]秒後ã«å†èµ·å‹•ã•ã‚Œã¾ã™ã€‚
-強制ログアウトã¨ãªã‚Šã¾ã™ã®ã§ã€ã“ã®åœ°åŸŸã®å¤–ã«å‡ºã¦ãã ã•ã„。
+ ã“ã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã¯ [SECONDS] 秒後ã«å†èµ·å‹•ã•ã‚Œã¾ã™ã€‚.
+ã“ã®ã¾ã¾ã“ã“ã«ã„ã‚‹ã¨ãƒ­ã‚°ã‚¢ã‚¦ãƒˆã•ã‚Œã¾ã™ã€‚
</notification>
<notification name="LoadWebPage">
ウェブ・ページ[URL]をロードã—ã¾ã™ã‹ï¼Ÿ
@@ -3052,7 +2446,7 @@ Second Life ã®ã‚¦ã‚§ãƒ–サイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã€è¨­å®šã—ã¾ã™ã‹ï¼Ÿ
データベースã«[DESC]ã¨ã„ã†åå‰ã®[TYPE]ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚
</notification>
<notification name="InvalidWearable">
- ç€ç”¨ã—よã†ã¨ã—ã¦ã„るアイテムã¯ã‚ãªãŸã®ãƒ“ューワã§ã¯èª­ã¿è¾¼ã‚€ã“ã¨ãŒã§ãã¾ã›ã‚“。 Second Lifeビューワを最新ã®ã‚‚ã®ã«ã‚¢ãƒƒãƒ—グレードã—ã¦ã‹ã‚‰ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’ç€ç”¨ã—ã¦ãã ã•ã„。
+ ç€ç”¨ã—よã†ã¨ã—ã¦ã„るアイテムã¯ã‚ãªãŸã®ãƒ“ューワã§ã¯èª­ã¿è¾¼ã‚€ã“ã¨ãŒã§ãã¾ã›ã‚“。 [APP_NAME] ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’アップグレードã—ã¦ã‹ã‚‰ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’ç€ç”¨ã—ã¦ãã ã•ã„。
</notification>
<notification name="ScriptQuestion">
「[NAME]ã€ãŒæ‰€æœ‰ã™ã‚‹ã‚ªãƒ–ジェクト「[OBJECTNAME]ã€ã‚’:
@@ -3062,16 +2456,16 @@ Second Life ã®ã‚¦ã‚§ãƒ–サイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã€è¨­å®šã—ã¾ã™ã‹ï¼Ÿ
<form name="form">
<button name="Yes" text="ã¯ã„"/>
<button name="No" text="ã„ã„ãˆ"/>
- <button name="Mute" text="無視リストã«è¿½åŠ "/>
+ <button name="Mute" text="ブロック"/>
</form>
</notification>
<notification name="ScriptQuestionCaution">
- 「[OBJECTNAME]ã€ãŒæ‰€æœ‰ã™ã‚‹ã‚ªãƒ–ジェクト「[NAME]ã€ã¯ã€æ¬¡ã®ã“ã¨ã‚’求ã‚ã¦ã„ã¾ã™ï¼š
+ [NAME] ãŒæ‰€æœ‰ã™ã‚‹ã€Œ [OBJECTNAME] 〠ã¨ã„ã†ã‚ªãƒ–ジェクトãŒã€æ¬¡ã®ã“ã¨ã‚’ã—よã†ã¨ã—ã¦ã„ã¾ã™ï¼š
[QUESTIONS]
-ã“ã®ã‚ªãƒ–ジェクトã¨åˆ¶ä½œè€…ãŒä¿¡ç”¨ã§ããªã„å ´åˆã¯ã€ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’æ‹’å¦ã—ã¦ãã ã•ã„。追加情報ã¯ã€è©³ç´°ãƒœã‚¿ãƒ³ã‚’クリックã—ã¦ãã ã•ã„。
+ã“ã®ã‚ªãƒ–ジェクトや制作者を信用ã§ããªã„å ´åˆã¯ã€ã“ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’æ‹’å¦ã—ã¦ãã ã•ã„。
-ã“ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’許å¯ã—ã¾ã™ã‹ï¼Ÿ
+リクエストをå—ã‘ã¾ã™ã‹ï¼Ÿ
<form name="form">
<button name="Grant" text="許å¯"/>
<button name="Deny" text="æ‹’å¦"/>
@@ -3092,43 +2486,44 @@ Second Life ã®ã‚¦ã‚§ãƒ–サイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã€è¨­å®šã—ã¾ã™ã‹ï¼Ÿ
<button name="Ignore" text="無視ã™ã‚‹"/>
</form>
</notification>
+ <notification name="ScriptToast">
+ [FIRST] [LAST] ã®ã€Œ [TITLE] ã€ã¯ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚¤ãƒ³ãƒ—ットをリクエストã—ã¦ã„ã¾ã™ã€‚
+ <form name="form">
+ <button name="Open" text="ダイアログを開ã"/>
+ <button name="Ignore" text="無視"/>
+ <button name="Block" text="ブロック"/>
+ </form>
+ </notification>
<notification name="FirstBalanceIncrease">
- L$[AMOUNT]ã‚’å—ã‘å–ã‚Šã¾ã—ãŸã€‚
-オブジェクトãŠã‚ˆã³ä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒã‚ãªãŸã«ãŠé‡‘を支払ã£ãŸã‚ˆã†ã§ã™ã€‚
-ã‚ãªãŸã®æ®‹é«˜ã¯ç”»é¢ã®å³ä¸Šã«è¡¨ç¤ºã•ã‚Œã¦ ã„ã¾ã™ã€‚
+ L$ [AMOUNT] ã‚’å—ã‘å–ã‚Šã¾ã—ãŸã€‚
+ã‚ãªãŸã® L$ 残高ã¯ç”»é¢å³ä¸Šã«è¡¨ç¤ºã•ã‚Œã¦ã„ã¾ã™ã€‚
</notification>
<notification name="FirstBalanceDecrease">
- L$[AMOUNT]を支払ã„ã¾ã—ãŸã€‚
-ã‚ãªãŸã®æ®‹é«˜ã¯ç”»é¢ã®å³ä¸Šã«è¡¨ç¤ºã•ã‚Œã¦ ã„ã¾ã™ã€‚
+ L$ [AMOUNT] を支払ã„ã¾ã—ãŸã€‚
+ã‚ãªãŸã® L$ 残高ã¯ç”»é¢å³ä¸Šã«è¡¨ç¤ºã•ã‚Œã¦ã„ã¾ã™ã€‚
+ </notification>
+ <notification name="BuyLindenDollarSuccess">
+ ãŠæ”¯æ‰•ã‚ã‚ŠãŒã¨ã†ã”ã–ã„ã¾ã™ã€‚
+
+ã‚ãªãŸã® L$ 残高ã¯ã€å‡¦ç†ãŒå®Œäº†ã™ã‚‹ã¨ã‚¢ãƒƒãƒ—デートã•ã‚Œã¾ã™ã€‚ 処ç†ã« 20 分以上ã‹ã‹ã£ãŸå ´åˆã€ãŠå–り引ããŒã‚­ãƒ£ãƒ³ã‚»ãƒ«ã•ã‚Œã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚ ãã®å ´åˆã¯ã€è³¼å…¥é‡‘é¡ã¯ã‚ãªãŸã® US$ 残高ã«è¿½åŠ ã•ã‚Œã¾ã™ã€‚
+
+[http://secondlife.com/account/ マイアカウント] ã®å–引履歴ページã§ã€æ”¯æ‰•çŠ¶æ³ã‚’確èªã§ãã¾ã™ã€‚
</notification>
<notification name="FirstSit">
- ã‚ãªãŸã¯åº§ã£ã¦ã„ã¾ã™ã€‚
-矢å°ï¼ˆã¾ãŸã¯ AWSD)ã®ã‚­ãƒ¼ã‚’使ã£ã¦
-視点を変ãˆã¾ã™ã€‚
-ç«‹ã¡ä¸ŠãŒã‚‹ã«ã¯ã€Œç«‹ã¡ä¸ŠãŒã‚‹ã€ã‚’クリックã—ã¾ã™ã€‚
+ ç€å¸­ä¸­ã§ã™ã€‚
+周囲を見るã«ã¯çŸ¢å°ã‚­ãƒ¼ã‹ AWSD キーを使ã£ã¦ãã ã•ã„。
+ç«‹ã¤ã¨ãã«ã¯ã€Œç«‹ã¡ä¸ŠãŒã‚‹ã€ãƒœã‚¿ãƒ³ã‚’クリックã—ã¦ãã ã•ã„。
</notification>
<notification name="FirstMap">
- 地図をスクロールã™ã‚‹ã«ã¯ã€ã‚¯ãƒªãƒƒã‚¯ã—ã¦ãƒ‰ãƒ©ãƒƒã‚°ã—ã¾ã™ã€‚
-テレãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ã€ãƒ€ãƒ–ルクリックã—ã¾ã™ã€‚
-å³å´ã®ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«ã‚’使用ã™ã‚‹ã¨ã€ç‰©ã‚’見ã¤ã‘ãŸã‚Šã€åˆ¥ã®èƒŒæ™¯ã‚’表示ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+ 地図をクリック・ドラッグã—ã¦å‘¨å›²ã‚’見ã¦ãã ã•ã„。
+ダブルクリックã™ã‚‹ã¨ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã—ã¾ã™ã€‚
+å³å´ã®ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«ã§å ´æ‰€ã‚’探ã—ãŸã‚ŠèƒŒæ™¯ã‚’変更ã—ã¦ãã ã•ã„。
</notification>
<notification name="FirstBuild">
- [SECOND_LIFE] ã«ã¯ã€
-æ–°ã—ã„オブジェクトを作るã“ã¨ãŒã§ãる地域ãŒã‚ã‚Šã¾ã™ã€‚
-作æˆã«ã¯ç”»é¢ä¸Šéƒ¨å·¦ã®ãƒ„ールãŒä½¿ãˆã€
-CtrlキーやAltキーを押ã—ãŸã¾ã¾ã«ã™ã‚Œã°
-ç´ æ—©ãツールを切り替ãˆã‚‰ã‚Œã¾ã™ã€‚
-Escキーを押ã™ã¨ã€ä½œæˆã¯çµ‚了ã—ã¾ã™ã€‚
- </notification>
- <notification name="FirstLeftClickNoHit">
- 左クリックã§ç‰¹åˆ¥ãªã‚ªãƒ–ジェクトをæ“作ã§ãã¾ã™ã€‚
-マウス・ãƒã‚¤ãƒ³ã‚¿ãŒæ‰‹ã®ãƒžãƒ¼ã‚¯ã«å¤‰ã‚ã‚‹ã¨ã€ãƒã‚¤ãƒ³ãƒˆã—ã¦ã„るオブジェクトをæ“作ã§ãã¾ã™ã€‚
-å³ã‚¯ãƒªãƒƒã‚¯ã§å®Ÿè¡Œå¯èƒ½ãªæ“作ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+ 制作ツールを開ãã¾ã—ãŸã€‚ 見るもã®ã™ã¹ã¦ãŒã“ã®ãƒ„ールã§ä½œæˆã•ã‚ŒãŸã‚‚ã®ã§ã™ã€‚
</notification>
<notification name="FirstTeleport">
- ã“ã®åœ°åŸŸã§ã¯ã€ãƒã‚¤ãƒ³ãƒˆé–“ã®ãƒ†ãƒ¬ãƒãƒ¼ãƒˆãŒèªã‚られã¦ã„ã¾ã›ã‚“ã®ã§ã€æœ€ã‚‚è¿‘ã„テレãƒãƒ–周辺ã«ç§»å‹•ã—ã¾ã—ãŸã€‚
-ã‚ãªãŸã®ç›®çš„地ã¯ã€å¤§ããªæ¨™è­˜ï¼ˆãƒ“ーコン)ã§è¡¨ç¤ºã•ã‚Œã¦ã„ã¾ã™ã€‚赤ã„矢å°ã«å‘ã‹ã£ã¦é€²ã‚€ã¨æ¨™è­˜ï¼ˆãƒ“ーコン)ã¸è¾¿ã‚Šç€ãã¾ã™ã€‚
-矢å°ã‚’クリックã™ã‚‹ã¨æ¨™è­˜ï¼ˆãƒ“ーコン)を消ã›ã¾ã™
+ ã“ã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã§ã¯ç‰¹å®šã®ã‚¨ãƒªã‚¢ã«ã®ã¿ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã§ãã¾ã™ã€‚ 矢å°ãŒç›®çš„地を指ã—ã¦ã„ã¾ã™ã€‚ 矢å°ã‚’クリックã™ã‚‹ã¨æ¶ˆãˆã¾ã™ã€‚
</notification>
<notification name="FirstOverrideKeys">
ã‚ãªãŸã®ç§»å‹•ã‚­ãƒ¼ã‚’オブジェクトãŒæ“作ã—ã¦ã„ã¾ã™ã€‚
@@ -3137,93 +2532,81 @@ Escキーを押ã™ã¨ã€ä½œæˆã¯çµ‚了ã—ã¾ã™ã€‚
Mキーを押ã—ã¦å¤‰æ›´ã—ã¾ã™ã€‚
</notification>
<notification name="FirstAppearance">
- ã‚ãªãŸã¯å®¹å§¿ã‚’編集中ã§ã™ã€‚
-回転ã€ã‚ºãƒ¼ãƒ ã™ã‚‹ã«ã¯çŸ¢å°ã‚­ãƒ¼ã‚’使ã„ã¾ã™ã€‚
-編集ãŒçµ‚ã‚ã£ãŸã‚‰ã€Œã™ã¹ã¦ä¿å­˜ã€ã‚’クリックã—ã¦å®¹å§¿ã‚’ä¿å­˜ã—ã€çµ‚了ã—ã¾ã™ã€‚
-容姿ã®ç·¨é›†ã¯ä½•åº¦ã§ã‚‚è¡Œãˆã¾ã™ã€‚
+ 容姿を編集中ã§ã™ã€‚
+周囲を見るã«ã¯çŸ¢å°ã‚­ãƒ¼ã‚’使ã£ã¦ãã ã•ã„。
+終ã‚ã£ãŸã‚‰ã€Œã™ã¹ã¦ä¿å­˜ã€ã‚’押ã—ã¦ãã ã•ã„。
</notification>
<notification name="FirstInventory">
- ã“ã‚Œã¯ã€ã‚ªãƒ–ジェクトã€ãƒŽãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã€æœã€ãã®ä»–ã‚ãªãŸã®æ‰€æœ‰ç‰©ãŒã™ã¹ã¦å…¥ã£ãŸã€ŒæŒã¡ç‰©ã€ã§ã™ã€‚
-*マウスã§ã‚¢ãƒã‚¿ãƒ¼ã«ã‚ªãƒ–ジェクトやæœè£…フォルダをドラッグã—ã¦è£…ç€ã—ã¾ã™ã€‚
-*オブジェクトを地é¢ã®ä¸Šã«ãƒ‰ãƒ©ãƒƒã‚°ã™ã‚‹ã¨ã€å‘¨å›²ã®ä¸–ç•Œã«è¡¨ç¤ºã•ã›ã¾ã™ã€‚(Rez)
-*ノートカードを読むã«ã¯ã€ãƒ€ãƒ–ルクリックã—ã¾ã™ã€‚
+ ã“ã‚Œã¯ã‚ãªãŸã®æŒã¡ç‰©ã§ã™ã€‚所有ã—ã¦ã„るアイテムãŒå…¥ã£ã¦ã„ã¾ã™ã€‚
+
+* アイテムを自分ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦è£…ç€ã—ã¦ãã ã•ã„。
+* アイテムを地é¢ã«ãƒ‰ãƒ©ãƒƒã‚°ã—㦠Rez ã—ã¦ãã ã•ã„。
+* ノートカードをダブルクリックã—ã¦é–‹ã„ã¦ãã ã•ã„。
</notification>
<notification name="FirstSandbox">
- ã“ã“ã¯ã‚µãƒ³ãƒ‰ãƒœãƒƒã‚¯ã‚¹ã§ã™ã€‚
-ã‚ãªãŸãŒã“ã“ã§ä½œã£ãŸã‚ªãƒ–ジェクトã¯ã‚ãªãŸãŒç«‹ã¡åŽ»ã£ãŸå¾Œã€å‰Šé™¤ã•ã‚Œã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。サンドボックスã¯å®šæœŸçš„ã«æ¸…掃ã•ã‚Œã¾ã™ã€‚詳細ã«ã¤ã„ã¦ã¯ã€ç”»é¢ä¸Šéƒ¨ã€åœ°åŸŸåã®éš£ã®æƒ…報をå‚ç…§ã—ã¦ãã ã•ã„。
+ ã“ã“ã¯ã‚µãƒ³ãƒ‰ãƒœãƒƒã‚¯ã‚¹ã‚¨ãƒªã‚¢ã§ã™ã€‚ä½äººãŒåˆ¶ä½œã‚’å­¦ã¶ã“ã¨ãŒã§ãã¾ã™ã€‚
-サンドボックスã¯ç‰¹åˆ¥ãªã‚¨ãƒªã‚¢ã§ã€ç›®å°ã®ã‚µã‚¤ãƒ³ãŒã¤ã„ã¦ã„ã¾ã™ã€‚
+ã“ã“ã§åˆ¶ä½œã•ã‚ŒãŸã‚‚ã®ã¯æ™‚é–“ãŒçµŒã¤ã¨å‰Šé™¤ã•ã‚Œã¾ã™ã€‚制作ã—ãŸã‚¢ã‚¤ãƒ†ãƒ ã‚’å³ã‚¯ãƒªãƒƒã‚¯ã—ã¦ã€Œå–ã‚‹ã€ã‚’é¸ã³ã€æŒã¡ç‰©ã«å…¥ã‚Œã¦ãŠæŒã¡å¸°ã‚Šã™ã‚‹ã®ã‚’ãŠå¿˜ã‚Œãªã。
</notification>
<notification name="FirstFlexible">
- ã“ã®ã‚ªãƒ–ジェクト㯠フレキシブルã§ã™ã€‚
-フレキシブル・ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹ã®ãƒã‚§ãƒƒã‚¯ãŒå¤–ã•ã‚Œã‚‹ã¾ã§ã¯ã€ã‚ªãƒ–ジェクトã¯ç‰©ç†çš„ã§ãªãファントムã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。
+ ã“ã®ã‚ªãƒ–ジェクトã¯ãƒ•ãƒ¬ã‚­ã‚·ãƒ–ルã§ã™ã€‚ フレキシスã¯ã€ã€Œç‰©ç†ã€ã§ã¯ãªã「ファントムã€ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。
</notification>
<notification name="FirstDebugMenus">
- 高度ãªè¨­å®šã‚’有効ã«ã—ã¾ã—ãŸã€‚
-ã“ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã«ã¯ã€
-Second Life をデãƒãƒƒã‚°ã™ã‚‹ãƒ‡ãƒ™ãƒ­ãƒƒãƒ‘ーã«ã¨ã£ã¦
-有用ãªæ©Ÿèƒ½ãŒã‚ã‚Šã¾ã™ã€‚
-ã“ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‚’切り替ãˆã‚‹ã«ã¯ã€
-Windowsã§ã¯Ctrl-Alt-Dを押ã—ã¾ã™ã€‚
-Macã®å ´åˆã¯ã€Cmd-Opt-Shift-Dを押ã—ã¦ãã ã•ã„。
+ アドãƒãƒ³ã‚¹ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‚’é–‹ãã¾ã—ãŸã€‚
+
+ã“ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã®æœ‰åŠ¹ãƒ»ç„¡åŠ¹è¨­å®š
+ Windows: Ctrl+Alt+D
+ Mac: &#8997;&#8984;D
</notification>
<notification name="FirstSculptedPrim">
- スカルプトプリムを編集ã—ã¦ã„ã¾ã™ã€‚
-スカルプトプリムã¯ã€å½¢çŠ¶ã‚’指定ã™ã‚‹ãŸã‚ã®ç‰¹åˆ¥ãªãƒ†ã‚¯ã‚¹ãƒãƒ£ãƒ¼ãŒå¿…è¦ã§ã™ã€‚
-æŒã¡ç‰©ãƒ©ã‚¤ãƒ–ラリã§ã€ã‚¹ã‚«ãƒ«ãƒ—トテクスãƒãƒ£ãƒ¼ã®ã‚µãƒ³ãƒ—ルをå‚ç…§ã§ãã¾ã™ã€‚
- </notification>
- <notification name="FirstMedia">
- メディアã®å†ç”Ÿã‚’開始ã—ã¾ã—ãŸã€‚
-オーディオ/ビデオã®ç’°å¢ƒè¨­å®šã§ã€è‡ªå‹•çš„ã«ãƒ¡ãƒ‡ã‚£ã‚¢ã‚’å†ç”Ÿã™ã‚‹ã‚ˆã†ã«è¨­å®šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
-注: ã“ã®è¨­å®šã«ã‚ˆã‚Šã€ä¿¡é ¼ã—ãªã„メディア・サイトã«æŽ¥ç¶šã•ã‚Œã‚‹ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒ»ãƒªã‚¹ã‚¯ãŒä¼´ã„ã¾ã™ã€‚
+ スカルプトプリムを編集中ã§ã™ã€‚ スカルプトã«ã¯å½¢çŠ¶ã®è¼ªéƒ­ã‚’指定ã™ã‚‹ãŸã‚ã®ç‰¹åˆ¥ãªãƒ†ã‚¯ã‚¹ãƒãƒ£ãŒå¿…è¦ã§ã™ã€‚
</notification>
<notification name="MaxListSelectMessage">
ã“ã®ãƒªã‚¹ãƒˆã‹ã‚‰[MAX_SELECT]個ã¾ã§ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’é¸æŠžã§ãã¾ã™ã€‚
</notification>
<notification name="VoiceInviteP2P">
- [NAME]ãŒã€ã‚ãªãŸã‚’ボイスãƒãƒ£ãƒƒãƒˆã‚³ãƒ¼ãƒ«ã«æ‹›å¾…ã—ã¦ã„ã¾ã™ã€‚
-コールã«å‚加ã™ã‚‹ã«ã¯ã€Œå—ã‘入れるã€ã‚’クリックã—ã€æ‹›å¾…ã‚’æ–­ã‚‹ã¨ãã¯ã€Œæ‹’å¦ã€ã‚’クリックã—ã¦ãã ã•ã„。ã“ã®ã‚³ãƒ¼ãƒ«ã‚’ã—ã¦ã„る人をミュートã«ã™ã‚‹å ´åˆã¯ã€ŒãƒŸãƒ¥ãƒ¼ãƒˆã€ã‚’クリックã—ã¦ãã ã•ã„。
+ [NAME] ãŒã‚ãªãŸã‚’ボイスãƒãƒ£ãƒƒãƒˆã‚³ãƒ¼ãƒ«ã«æ‹›å¾…ã—ã¦ã„ã¾ã™ã€‚
+å—ã‘入れるをクリックã™ã‚‹ã‹ã€æ–­ã‚‹å ´åˆã¯æ‹’å¦ã‚’クリックã—ã¦ãã ã•ã„。 ブロックをクリックã™ã‚‹ã¨ã€ã“ã®ç™ºä¿¡è€…をブロックã—ã¾ã™ã€‚
<form name="form">
<button name="Accept" text="å—ã‘入れる"/>
<button name="Decline" text="æ‹’å¦"/>
- <button name="Mute" text="ミュート"/>
+ <button name="Mute" text="ブロック"/>
</form>
</notification>
<notification name="AutoUnmuteByIM">
- [FIRST] [LAST]ã«
-インスタント・メッセージãŒé€ä¿¡ã•ã‚Œã€ç„¡è¦–設定ã¯è‡ªå‹•çš„ã«è§£é™¤ã•ã‚Œã¾ã—ãŸã€‚
+ [FIRST] [LAST] ã¯ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ãƒˆãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’å—ã‘å–ã‚Šã€è‡ªå‹•çš„ã«ãƒ–ロックãŒè§£é™¤ã•ã‚Œã¾ã—ãŸã€‚
</notification>
<notification name="AutoUnmuteByMoney">
- [FIRST] [LAST]ã«ãŠé‡‘を渡ã—ãŸãŸã‚〠無視設定ãŒè‡ªå‹•çš„ã«è§£é™¤ã•ã‚Œã¾ã—ãŸã€‚
+ [FIRST] [LAST] ã¯ãŠé‡‘ã‚’å—ã‘å–ã‚Šã€è‡ªå‹•çš„ã«ãƒ–ロックãŒè§£é™¤ã•ã‚Œã¾ã—ãŸã€‚
</notification>
<notification name="AutoUnmuteByInventory">
- [FIRST] [LAST]ã«æŒã¡ç‰©ã‚’渡ã—ãŸãŸã‚〠無視設定ãŒè‡ªå‹•çš„ã«è§£é™¤ã•ã‚Œã¾ã—ãŸã€‚
+ [FIRST] [LAST] ã¯ã‚¢ã‚¤ãƒ†ãƒ ã‚’å—ã‘å–ã‚Šã€è‡ªå‹•çš„ã«ãƒ–ロックãŒè§£é™¤ã•ã‚Œã¾ã—ãŸã€‚
</notification>
<notification name="VoiceInviteGroup">
- [NAME]ãŒã€ã‚°ãƒ«ãƒ¼ãƒ—[GROUP]ã¨ã®ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆã‚³ãƒ¼ãƒ«ã«å‚加ã—ã¾ã—ãŸã€‚
-コールã«å‚加ã™ã‚‹ã«ã¯ã€Œå—ã‘入れるã€ã‚’クリックã—ã€æ‹›å¾…ã‚’æ–­ã‚‹ã¨ãã¯ã€Œæ‹’å¦ã€ã‚’クリックã—ã¦ãã ã•ã„。ã“ã®ã‚³ãƒ¼ãƒ«ã‚’ã—ã¦ã„る人をミュートã«ã™ã‚‹å ´åˆã¯ã€ŒãƒŸãƒ¥ãƒ¼ãƒˆã€ã‚’クリックã—ã¦ãã ã•ã„。
+ [NAME] 㯠[GROUP]. ã®ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆã‚³ãƒ¼ãƒ«ã«å‚加ã—ã¾ã—ãŸã€‚
+å—ã‘入れるをクリックã™ã‚‹ã‹ã€æ–­ã‚‹å ´åˆã¯æ‹’å¦ã‚’クリックã—ã¦ãã ã•ã„。 ブロックをクリックã™ã‚‹ã¨ã€ã“ã®ç™ºä¿¡è€…をブロックã—ã¾ã™ã€‚
<form name="form">
<button name="Accept" text="å—ã‘入れる"/>
<button name="Decline" text="æ‹’å¦"/>
- <button name="Mute" text="ミュート"/>
+ <button name="Mute" text="ブロック"/>
</form>
</notification>
<notification name="VoiceInviteAdHoc">
- [NAME]ãŒã€ä¼šè­°ãƒãƒ£ãƒƒãƒˆã§ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆã‚³ãƒ¼ãƒ«ã«å‚加ã—ã¾ã—ãŸã€‚
-コールã«å‚加ã™ã‚‹ã«ã¯ã€Œå—ã‘入れるã€ã‚’クリックã—ã€æ‹›å¾…ã‚’æ–­ã‚‹ã¨ãã¯ã€Œæ‹’å¦ã€ã‚’クリックã—ã¦ãã ã•ã„。 ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’ミュート(消声)ã™ã‚‹å ´åˆã¯ã€ŒãƒŸãƒ¥ãƒ¼ãƒˆã€ã‚’クリックã—ã¦ãã ã•ã„。
+ [NAME] 㯠コンファレンスãƒãƒ£ãƒƒãƒˆã®ã®ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆã‚³ãƒ¼ãƒ«ã«å‚加ã—ã¾ã—ãŸã€‚
+å—ã‘入れるをクリックã™ã‚‹ã‹ã€æ–­ã‚‹å ´åˆã¯æ‹’å¦ã‚’クリックã—ã¦ãã ã•ã„。 ブロックをクリックã™ã‚‹ã¨ã€ã“ã®ç™ºä¿¡è€…をブロックã—ã¾ã™ã€‚
<form name="form">
<button name="Accept" text="å—ã‘入れる"/>
<button name="Decline" text="æ‹’å¦"/>
- <button name="Mute" text="ミュート"/>
+ <button name="Mute" text="ブロック"/>
</form>
</notification>
<notification name="InviteAdHoc">
- [NAME]ãŒã€ã‚ãªãŸã‚’会議ãƒãƒ£ãƒƒãƒˆã«æ‹›å¾…ã—ã¦ã„ã¾ã™ã€‚
-ãƒãƒ£ãƒƒãƒˆã«å‚加ã™ã‚‹ã«ã¯ã€Œå—ã‘入れるã€ã‚’クリックã—ã€æ‹›å¾…ã‚’æ–­ã‚‹ã¨ãã¯ã€Œæ‹’å¦ã€ã‚’クリックã—ã¦ãã ã•ã„。ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’ミュート(消声)ã™ã‚‹å ´åˆã¯ã€ŒãƒŸãƒ¥ãƒ¼ãƒˆã€ã‚’クリックã—ã¦ãã ã•ã„。
+ [NAME] ãŒã‚ãªãŸã‚’コンファレンスãƒãƒ£ãƒƒãƒˆã«æ‹›å¾…ã—ã¦ã„ã¾ã™ã€‚
+å—ã‘入れるをクリックã™ã‚‹ã‹ã€æ–­ã‚‹å ´åˆã¯æ‹’å¦ã‚’クリックã—ã¦ãã ã•ã„。 ブロックをクリックã™ã‚‹ã¨ã€ã“ã®ç™ºä¿¡è€…をブロックã—ã¾ã™ã€‚
<form name="form">
<button name="Accept" text="å—ã‘入れる"/>
<button name="Decline" text="æ‹’å¦"/>
- <button name="Mute" text="ミュート"/>
+ <button name="Mute" text="ブロック"/>
</form>
</notification>
<notification name="VoiceChannelFull">
@@ -3233,25 +2616,25 @@ Macã®å ´åˆã¯ã€Cmd-Opt-Shift-Dを押ã—ã¦ãã ã•ã„。
ã“ã®ã‚¨ãƒªã‚¢ã®ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆã¯ã€æ··é›‘ã®ãŸã‚容é‡ã‚’超ãˆã¦ã—ã¾ã£ã¦ã„ã¾ã™ã€‚申ã—訳ã‚ã‚Šã¾ã›ã‚“ãŒã€ä»–ã®ã‚¨ãƒªã‚¢ã§ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆã‚’ãŠè©¦ã—ãã ã•ã„。
</notification>
<notification name="VoiceChannelDisconnected">
- [VOICE_CHANNEL_NAME]ã¸ã®æŽ¥ç¶šãŒåˆ‡æ–­ã•ã‚Œã¾ã—ãŸã€‚空間ボイスãƒãƒ£ãƒƒãƒˆã«å†æŽ¥ç¶šã•ã‚Œã¾ã™ã€‚
+ [VOICE_CHANNEL_NAME] ã¸ã®æŽ¥ç¶šãŒåˆ‡ã‚Œã¾ã—ãŸã€‚ 「近ãã®ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆã€ã«å†æŽ¥ç¶šã•ã‚Œã¾ã™ã€‚
</notification>
<notification name="VoiceChannelDisconnectedP2P">
- [VOICE_CHANNEL_NAME]ã¯ã€ã‚³ãƒ¼ãƒ«ã‚’終了ã—ã¾ã—ãŸã€‚空間ボイスãƒãƒ£ãƒƒãƒˆã«å†æŽ¥ç¶šã•ã‚Œã¾ã™ã€‚
+ [VOICE_CHANNEL_NAME] ãŒã‚³ãƒ¼ãƒ«ã‚’終了ã—ã¾ã—ãŸã€‚ 「近ãã®ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆã€ã«å†æŽ¥ç¶šã•ã‚Œã¾ã™ã€‚
</notification>
<notification name="P2PCallDeclined">
- [VOICE_CHANNEL_NAME]ã¯ã€ã‚ãªãŸã®ã‚³ãƒ¼ãƒ«ã‚’æ‹’å¦ã—ã¾ã—ãŸã€‚空間ボイスãƒãƒ£ãƒƒãƒˆã«å†æŽ¥ç¶šã•ã‚Œã¾ã™ã€‚
+ [VOICE_CHANNEL_NAME] ãŒã‚ãªãŸã®ã‚³ãƒ¼ãƒ«ã‚’æ‹’å¦ã—ã¾ã—ãŸã€‚ 「近ãã®ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆã€ã«å†æŽ¥ç¶šã•ã‚Œã¾ã™ã€‚
</notification>
<notification name="P2PCallNoAnswer">
- [VOICE_CHANNEL_NAME]ã¯ã€ã‚ãªãŸã®ã‚³ãƒ¼ãƒ«ã‚’å—ã‘å–ã‚Œã¾ã›ã‚“。空間ボイスãƒãƒ£ãƒƒãƒˆã«å†æŽ¥ç¶šã•ã‚Œã¾ã™ã€‚
+ [VOICE_CHANNEL_NAME] ã¯ã‚ãªãŸã®ã‚³ãƒ¼ãƒ«ã‚’å—ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。 「近ãã®ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆã€ã«å†æŽ¥ç¶šã•ã‚Œã¾ã™ã€‚
</notification>
<notification name="VoiceChannelJoinFailed">
- [VOICE_CHANNEL_NAME]ã¸ã®æŽ¥ç¶šã«å¤±æ•—ã—ã¾ã—ãŸã€‚時間をãŠã„ã¦ã€å†åº¦ã€è©¦ã¿ã¦ãã ã•ã„。空間ボイスãƒãƒ£ãƒƒãƒˆã«å†æŽ¥ç¶šã•ã‚Œã¾ã™ã€‚
+ [VOICE_CHANNEL_NAME] ã¸ã®æŽ¥ç¶šã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚ã¨ã§å†åº¦ãŠè©¦ã—ãã ã•ã„。 「近ãã®ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆã€ã«å†æŽ¥ç¶šã•ã‚Œã¾ã™ã€‚
</notification>
<notification name="VoiceLoginRetry">
ã‚ãªãŸç”¨ã®ãƒœã‚¤ã‚¹ãƒãƒ£ãƒ³ãƒãƒ«ã‚’作æˆã—ã¦ã„ã¾ã™ã€‚1分ã»ã©ã‹ã‹ã‚Šã¾ã™ã€‚
</notification>
<notification name="Cannot enter parcel: not a group member">
- é©åˆ‡ãªã‚°ãƒ«ãƒ¼ãƒ—ã®ãƒ¡ãƒ³ãƒãƒ¼ã§ã¯ãªã„ãŸã‚ã€åŒºç”»ã«å…¥ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
+ 特定ã®ã‚°ãƒ«ãƒ¼ãƒ—メンãƒãƒ¼ã®ã¿ã“ã®ã‚¨ãƒªã‚¢ã‚’訪å•ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
</notification>
<notification name="Cannot enter parcel: banned">
ç«‹å…¥ç¦æ­¢ã•ã‚Œã¦ã„ã‚‹ãŸã‚ã€åŒºç”»ã«å…¥ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
@@ -3266,18 +2649,43 @@ Macã®å ´åˆã¯ã€Cmd-Opt-Shift-Dを押ã—ã¦ãã ã•ã„。
[VOICE_CHANNEL_NAME]ã®ãƒœã‚¤ã‚¹ãƒ»ãƒãƒ£ãƒƒãƒˆã«æŽ¥ç¶šä¸­ã«ã€ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚後ã§ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。
</notification>
<notification name="ServerVersionChanged">
- 到ç€ã—ãŸåœ°åŸŸã¯ç•°ãªã‚‹ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿ãƒ¼ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§å®Ÿè¡Œã•ã‚Œã¦ã„ã¾ã™ã€‚ 詳細ã«ã¤ã„ã¦ã¯ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’クリックã—ã¦ãã ã•ã„。
+ ç•°ãªã‚‹ã‚µãƒ¼ãƒãƒ¼ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã«æ¥ã¾ã—ãŸã€‚パフォーマンスã«å½±éŸ¿ã™ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚ [[URL] リリースノートを確èª]
</notification>
- <notification name="UnableToOpenCommandURL">
- クリックã—ãŸURLã¯ã“ã®ã‚¦ã‚§ãƒ–ブラウザã§ã¯é–‹ã‘ã¾ã›ã‚“
+ <notification name="UnsupportedCommandSLURL">
+ クリックã—㟠SLurl ã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“。
+ </notification>
+ <notification name="IMToast">
+ [MESSAGE]
+ <form name="form">
+ <button name="respondbutton" text="返答"/>
+ </form>
+ </notification>
+ <notification name="AttachmentSaved">
+ アタッãƒãƒ¡ãƒ³ãƒˆãŒä¿å­˜ã•ã‚Œã¾ã—ãŸã€‚
+ </notification>
+ <notification name="UnableToFindHelpTopic">
+ ヘルプトピックãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚
+ </notification>
+ <notification name="ObjectMediaFailure">
+ サーãƒãƒ¼ã‚¨ãƒ©ãƒ¼ï¼š メディアã®ã‚¢ãƒƒãƒ—デートã¾ãŸã¯å¤±æ•—。
+「[ERROR]ã€
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="ConfirmClearTeleportHistory">
+ テレãƒãƒ¼ãƒˆå±¥æ­´ã‚’削除ã—ã¾ã™ã‹ï¼Ÿ
+ <usetemplate name="okcancelbuttons" notext="キャンセル" yestext="OK"/>
+ </notification>
+ <notification name="BottomTrayButtonCanNotBeShown">
+ é¸æŠžã—ãŸãƒœã‚¿ãƒ³ã‚’ç¾åœ¨è¡¨ç¤ºã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
+ã˜ã‚…ã†ã¶ã‚“ãªã‚¹ãƒšãƒ¼ã‚¹ãŒã§ãã‚Œã°ãƒœã‚¿ãƒ³ã¯è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
</notification>
<global name="UnsupportedCPU">
- ã‚ãªãŸã® CPU ã®é€Ÿåº¦ã¯å¿…須動作環境ã®æ¡ä»¶ã‚’満ãŸã—ã¦ã„ã¾ã›ã‚“。
</global>
<global name="UnsupportedGLRequirements">
- Second Life ã®ä½¿ç”¨ã«å¿…è¦ãªãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã®ç’°å¢ƒãŒæº€ãŸã•ã‚Œã¦ã„ãªã„よã†ã§ã™ã€‚ Second Life ã§ã¯ãƒžãƒ«ãƒãƒ†ã‚¯ã‚¹ãƒãƒ£ãƒ¼ã«å¯¾å¿œã—ãŸOpenGLグラフィック・カードãŒå¿…è¦ã§ã™ã€‚ ã“ã®å ´åˆã€ã‚°ãƒ©ãƒ•ã‚£ãƒƒã‚¯ãƒ»ã‚«ãƒ¼ãƒ‰ã®æœ€æ–°ãƒ‰ãƒ©ã‚¤ãƒãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã‚‹ã“ã¨ã€ãŠã‚ˆã³ã‚ªãƒšãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ãƒ»ã‚·ã‚¹ãƒ†ãƒ ã«ã‚µãƒ¼ãƒ“ス・パックã¨ä¿®æ­£ãƒ—ログラムãŒé©ç”¨ã•ã‚Œã¦ã„ã‚‹ã“ã¨ã‚’ã”確èªãã ã•ã„。
+ [APP_NAME] ã«å¿…è¦ãªãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãŒãªã„よã†ã§ã™ã€‚ [APP_NAME] ã«ã¯ãƒžãƒ«ãƒãƒ†ã‚¯ã‚¹ãƒãƒ£ã‚’サãƒãƒ¼ãƒˆã™ã‚‹ OpenGL グラフィックカードãŒå¿…è¦ã§ã™ã€‚ ãŠä½¿ã„ã®ã‚°ãƒ©ãƒ•ã‚£ãƒƒã‚¯ã‚«ãƒ¼ãƒ‰ã®æœ€æ–°ãƒ‰ãƒ©ã‚¤ãƒãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã‚‹ã‹ã©ã†ã‹ã€ã‚ªãƒšãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚·ã‚¹ãƒ†ãƒ ã®ã‚µãƒ¼ãƒ“スパックã¨ãƒ‘ッãƒãŒå…¥ã£ã¦ã„ã‚‹ã‹ã‚’ã”確èªãã ã•ã„。
-å•é¡ŒãŒè§£æ±ºã•ã‚Œãªã„å ´åˆã«ã¯ã€æ¬¡ã®ã‚µã‚¤ãƒˆã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ãã ã•ã„。 http://www.secondlife.com/support
+ã“ã®å•é¡ŒãŒä½•åº¦ã‚‚èµ·ãã‚‹å ´åˆã¯ã€[SUPPORT_SITE] ã‚’ã”確èªãã ã•ã„。
</global>
<global name="UnsupportedCPUAmount">
796
@@ -3291,10 +2699,8 @@ Macã®å ´åˆã¯ã€Cmd-Opt-Shift-Dを押ã—ã¦ãã ã•ã„。
<global name="UnsupportedRAM">
- ã‚ãªãŸã®ã‚·ã‚¹ãƒ†ãƒ ãƒ»ãƒ¡ãƒ¢ãƒªã¯å¿…須動作環境ã®æ¡ä»¶ã‚’満ãŸã—ã¦ã„ã¾ã›ã‚“。
</global>
- <global name="PermYes">
- ã¯ã„
- </global>
- <global name="PermNo">
- ã„ã„ãˆ
+ <global name="You can only set your &apos;Home Location&apos; on your land or at a mainland Infohub.">
+ 自分ã®åœŸåœ°ã‚’ãŠæŒã¡ã®å ´åˆã€ãƒ›ãƒ¼ãƒ ãƒ­ã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã«è¨­å®šã§ãã¾ã™ã€‚
+ãŠæŒã¡ã§ãªã„å ´åˆã¯ã€åœ°å›³ã§ã€Œã‚¤ãƒ³ãƒ•ã‚©ãƒãƒ–ã€ã‚’探ã—ã¦ãã ã•ã„。
</global>
</notifications>
diff --git a/indra/newview/skins/default/xui/ja/panel_activeim_row.xml b/indra/newview/skins/default/xui/ja/panel_activeim_row.xml
new file mode 100644
index 0000000000..84272752cf
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_activeim_row.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_activeim_row">
+ <text name="contact_name">
+ Grumpity ProductEngine
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_adhoc_control_panel.xml b/indra/newview/skins/default/xui/ja/panel_adhoc_control_panel.xml
new file mode 100644
index 0000000000..364ba76763
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_adhoc_control_panel.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_im_control_panel">
+ <panel name="panel_call_buttons">
+ <button label="コール" name="call_btn"/>
+ <button label="コール終了" name="end_call_btn"/>
+ <button label="ボイスコントロール" name="voice_ctrls_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/ja/panel_avatar_list_item.xml
new file mode 100644
index 0000000000..2efcb9f723
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_avatar_list_item.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="avatar_list_item">
+ <string name="FormatSeconds">
+ [COUNT] 秒
+ </string>
+ <string name="FormatMinutes">
+ [COUNT] 分
+ </string>
+ <string name="FormatHours">
+ [COUNT] 時間
+ </string>
+ <string name="FormatDays">
+ [COUNT] æ—¥
+ </string>
+ <string name="FormatWeeks">
+ [COUNT] 週間
+ </string>
+ <string name="FormatMonths">
+ [COUNT] ヶ月
+ </string>
+ <string name="FormatYears">
+ [COUNT] å¹´
+ </string>
+ <text name="avatar_name" value="ä¸æ˜Ž"/>
+ <text name="last_interaction" value="0 秒"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_avatar_tag.xml b/indra/newview/skins/default/xui/ja/panel_avatar_tag.xml
new file mode 100644
index 0000000000..fd91ea97d1
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_avatar_tag.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="avatar_tag_notification">
+ <panel name="msg_caption">
+ <text name="sender_tag_name">
+ Angela Tester
+ </text>
+ <text name="tag_time" value="23:30"/>
+ </panel>
+ <text_editor name="msg_text">
+ The quick brown fox jumps over the lazy dog.
+ </text_editor>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/ja/panel_block_list_sidetray.xml
new file mode 100644
index 0000000000..58ef8c3107
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_block_list_sidetray.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="block_list_panel">
+ <text name="title_text">
+ ブロックリスト
+ </text>
+ <scroll_list name="blocked" tool_tip="ç¾åœ¨ãƒ–ロックã•ã‚Œã¦ã„ã‚‹ä½äººä¸€è¦§"/>
+ <button label="ä½äººã‚’ブロック..." label_selected="ä½äººã‚’ブロック..." name="Block resident..." tool_tip="ブロックã—ãŸã„ä½äººã‚’é¸ã‚“ã§ãã ã•ã„"/>
+ <button label="åå‰ã§ã‚ªãƒ–ジェクトをブロック..." label_selected="åå‰ã§ã‚ªãƒ–ジェクトをブロック..." name="Block object by name..." tool_tip="åå‰ã§ãƒ–ロックã—ãŸã„オブジェクトをé¸ã‚“ã§ãã ã•ã„"/>
+ <button label="ブロック解除" label_selected="ブロック解除" name="Unblock" tool_tip="ブロックリストã‹ã‚‰ä½äººãƒ»ã‚ªãƒ–ジェクトを削除"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_bottomtray.xml b/indra/newview/skins/default/xui/ja/panel_bottomtray.xml
new file mode 100644
index 0000000000..5edc1b651d
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_bottomtray.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="bottom_tray">
+ <string name="SpeakBtnToolTip">
+ マイクã®ã‚ªãƒ³ãƒ»ã‚ªãƒ•
+ </string>
+ <string name="VoiceControlBtnToolTip">
+ ボイスコントロールパãƒãƒ«ã®è¡¨ç¤ºãƒ»éžè¡¨ç¤º
+ </string>
+ <layout_stack name="toolbar_stack">
+ <layout_panel name="gesture_panel">
+ <gesture_combo_box label="ジェスãƒãƒ£ãƒ¼" name="Gesture" tool_tip="ジェスãƒãƒ£ãƒ¼ã®è¡¨ç¤ºãƒ»éžè¡¨ç¤º"/>
+ </layout_panel>
+ <layout_panel name="movement_panel">
+ <button label="移動" name="movement_btn" tool_tip="移動コントロールã®è¡¨ç¤ºãƒ»éžè¡¨ç¤º"/>
+ </layout_panel>
+ <layout_panel name="cam_panel">
+ <button label="視界" name="camera_btn" tool_tip="カメラコントロールã®è¡¨ç¤ºãƒ»éžè¡¨ç¤º"/>
+ </layout_panel>
+ <layout_panel name="snapshot_panel">
+ <button label="" name="snapshots" tool_tip="スナップショットを撮る"/>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_chat_header.xml b/indra/newview/skins/default/xui/ja/panel_chat_header.xml
new file mode 100644
index 0000000000..babbff3132
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_chat_header.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="im_header" name="im_header">
+ <text_editor name="user_name" value="Ericag Vader"/>
+ <text name="time_box" value="23:30"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_classified_info.xml b/indra/newview/skins/default/xui/ja/panel_classified_info.xml
new file mode 100644
index 0000000000..1a5933a4e9
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_classified_info.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_classified_info">
+ <panel.string name="type_mature">
+ Mature
+ </panel.string>
+ <panel.string name="type_pg">
+ PG コンテンツ
+ </panel.string>
+ <text name="title" value="クラシファイド広告情報"/>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <text name="classified_name" value="[name]"/>
+ <text name="classified_location" value="[loading...]"/>
+ <text name="content_type" value="[content type]"/>
+ <text name="category" value="[category]"/>
+ <check_box label="毎週自動更新" name="auto_renew"/>
+ <text name="price_for_listing" tool_tip="掲載価格">
+ L$ [PRICE]
+ </text>
+ <text name="classified_desc" value="[description]"/>
+ </panel>
+ </scroll_container>
+ <panel name="buttons">
+ <button label="テレãƒãƒ¼ãƒˆ" name="teleport_btn"/>
+ <button label="地図" name="show_on_map_btn"/>
+ <button label="編集" name="edit_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_alpha.xml b/indra/newview/skins/default/xui/ja/panel_edit_alpha.xml
new file mode 100644
index 0000000000..7825d81c53
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_edit_alpha.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_alpha_panel">
+ <panel name="avatar_alpha_color_panel">
+ <texture_picker label="アルファ(下)" name="Lower Alpha" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <texture_picker label="アルファ(上)" name="Upper Alpha" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <texture_picker label="頭部ã®ã‚¢ãƒ«ãƒ•ã‚¡" name="Head Alpha" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <texture_picker label="ç›®ã®ã‚¢ãƒ«ãƒ•ã‚¡" name="Eye Alpha" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <texture_picker label="髪ã®ã‚¢ãƒ«ãƒ•ã‚¡" name="Hair Alpha" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_classified.xml b/indra/newview/skins/default/xui/ja/panel_edit_classified.xml
new file mode 100644
index 0000000000..ca065113d3
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_edit_classified.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="クラシファイド広告ã®ç·¨é›†" name="panel_edit_classified">
+ <panel.string name="location_notice">
+ (掲載後更新)
+ </panel.string>
+ <text name="title">
+ クラシファイド広告ã®ç·¨é›†
+ </text>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <icon label="" name="edit_icon" tool_tip="クリックã—ã¦ç”»åƒã‚’é¸æŠž"/>
+ <text name="Name:">
+ タイトル:
+ </text>
+ <text name="description_label">
+ 説明:
+ </text>
+ <text name="location_label">
+ ä½ç½®ï¼š
+ </text>
+ <text name="classified_location">
+ ローディング...
+ </text>
+ <button label="ç¾åœ¨åœ°ã«è¨­å®š" name="set_to_curr_location_btn"/>
+ <combo_box name="content_type">
+ <combo_item name="mature_ci">
+ Matureコンテンツ
+ </combo_item>
+ <combo_item name="pg_ci">
+ PGコンテンツ
+ </combo_item>
+ </combo_box>
+ <spinner label="L$" name="price_for_listing" tool_tip="掲載価格" value="50"/>
+ <check_box label="毎週自動更新" name="auto_renew"/>
+ </panel>
+ </scroll_container>
+ <panel label="bottom_panel" name="bottom_panel">
+ <button label="ä¿å­˜" name="save_changes_btn"/>
+ <button label="キャンセル" name="cancel_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_eyes.xml b/indra/newview/skins/default/xui/ja/panel_edit_eyes.xml
new file mode 100644
index 0000000000..0cee85f685
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_edit_eyes.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_eyes_panel">
+ <panel name="avatar_eye_color_panel">
+ <texture_picker label="çž³" name="Iris" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="eyes_main_tab" title="ç›®"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_gloves.xml b/indra/newview/skins/default/xui/ja/panel_edit_gloves.xml
new file mode 100644
index 0000000000..393bd15236
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_edit_gloves.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_gloves_panel">
+ <panel name="avatar_gloves_color_panel">
+ <texture_picker label="生地" name="Fabric" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <color_swatch label="色・色彩é…åˆ" name="Color/Tint" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="gloves_main_tab" title="手袋"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_hair.xml b/indra/newview/skins/default/xui/ja/panel_edit_hair.xml
new file mode 100644
index 0000000000..065771df16
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_edit_hair.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_hair_panel">
+ <panel name="avatar_hair_color_panel">
+ <texture_picker label="テクスãƒãƒ£" name="Texture" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠž"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="hair_color_tab" title="色"/>
+ <accordion_tab name="hair_style_tab" title="スタイル"/>
+ <accordion_tab name="hair_eyebrows_tab" title="眉毛"/>
+ <accordion_tab name="hair_facial_tab" title="フェイシャル"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_jacket.xml b/indra/newview/skins/default/xui/ja/panel_edit_jacket.xml
new file mode 100644
index 0000000000..96a851cc4c
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_edit_jacket.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_jacket_panel">
+ <panel name="avatar_jacket_color_panel">
+ <texture_picker label="生地・上" name="Upper Fabric" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <texture_picker label="生地・下" name="Lower Fabric" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <color_swatch label="色・色彩é…åˆ" name="Color/Tint" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="jacket_main_tab" title="ジャケット"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_pants.xml b/indra/newview/skins/default/xui/ja/panel_edit_pants.xml
new file mode 100644
index 0000000000..f93d3d6b14
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_edit_pants.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_pants_panel">
+ <panel name="avatar_pants_color_panel">
+ <texture_picker label="生地" name="Fabric" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <color_swatch label="色・色彩é…åˆ" name="Color/Tint" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="pants_main_tab" title="パンツ"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_pick.xml b/indra/newview/skins/default/xui/ja/panel_edit_pick.xml
new file mode 100644
index 0000000000..88c05fbae7
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_edit_pick.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="ピック編集" name="panel_edit_pick">
+ <text name="title">
+ ピック編集
+ </text>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <icon label="" name="edit_icon" tool_tip="クリックã—ã¦ç”»åƒã‚’é¸æŠž"/>
+ <text name="Name:">
+ タイトル:
+ </text>
+ <text name="description_label">
+ 説明:
+ </text>
+ <text name="location_label">
+ 場所:
+ </text>
+ <text name="pick_location">
+ ローディング...
+ </text>
+ <button label="ç¾åœ¨åœ°ã«è¨­å®š" name="set_to_curr_location_btn"/>
+ </panel>
+ </scroll_container>
+ <panel label="bottom_panel" name="bottom_panel">
+ <button label="[WHAT] ã‚’ä¿å­˜" name="save_changes_btn"/>
+ <button label="キャンセル" name="cancel_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_profile.xml b/indra/newview/skins/default/xui/ja/panel_edit_profile.xml
new file mode 100644
index 0000000000..b232a8db61
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_edit_profile.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="プロフィールã®ç·¨é›†" name="edit_profile_panel">
+ <string name="CaptionTextAcctInfo">
+ [ACCTTYPE]
+[PAYMENTINFO] [AGEVERIFICATION]
+ </string>
+ <string name="RegisterDateFormat">
+ [REG_DATE] ([AGE])
+ </string>
+ <string name="AcctTypeResident" value="ä½äºº"/>
+ <string name="AcctTypeTrial" value="トライアル"/>
+ <string name="AcctTypeCharterMember" value="創立メンãƒãƒ¼"/>
+ <string name="AcctTypeEmployee" value="Linden Lab 従業員"/>
+ <string name="PaymentInfoUsed" value="支払情報使用履歴ã‚ã‚Š"/>
+ <string name="PaymentInfoOnFile" value="支払情報登録済"/>
+ <string name="NoPaymentInfoOnFile" value="支払情報未登録"/>
+ <string name="AgeVerified" value="年齢確èªæ¸ˆ"/>
+ <string name="NotAgeVerified" value="年齢未確èª"/>
+ <string name="partner_edit_link_url">
+ http://www.secondlife.com/account/partners.php?lang=ja
+ </string>
+ <string name="no_partner_text" value="ãªã—"/>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <panel name="data_panel">
+ <panel name="lifes_images_panel">
+ <panel name="second_life_image_panel">
+ <text name="second_life_photo_title_text" value="[SECOND_LIFE]:"/>
+ </panel>
+ <icon label="" name="2nd_life_edit_icon" tool_tip="クリックã—ã¦ç”»åƒã‚’é¸æŠž"/>
+ </panel>
+ <panel name="first_life_image_panel">
+ <text name="real_world_photo_title_text" value="ç¾å®Ÿä¸–界:"/>
+ </panel>
+ <icon label="" name="real_world_edit_icon" tool_tip="クリックã—ã¦ç”»åƒã‚’é¸æŠž"/>
+ <text name="title_homepage_text">
+ Web サイト:
+ </text>
+ <line_editor name="homepage_edit" value="http://"/>
+ <check_box label="検索çµæžœã«è¡¨ç¤º" name="show_in_search_checkbox"/>
+ <text name="title_acc_status_text" value="マイアカウント:"/>
+ <text name="my_account_link" value="[[URL] マイアカウントã«ç§»å‹•]"/>
+ <text name="acc_status_text" value="ä½äººã€‚ 支払情報未登録。"/>
+ <text name="title_partner_text" value="マイパートナー:"/>
+ <text name="partner_edit_link" value="[[URL] 編集]"/>
+ <panel name="partner_data_panel">
+ <text name="partner_text" value="[FIRST] [LAST]"/>
+ </panel>
+ </panel>
+ </panel>
+ </scroll_container>
+ <panel name="profile_me_buttons_panel">
+ <button label="変更をä¿å­˜" name="save_btn"/>
+ <button label="キャンセル" name="cancel_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_shape.xml b/indra/newview/skins/default/xui/ja/panel_edit_shape.xml
new file mode 100644
index 0000000000..1e20eb26b6
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_edit_shape.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_shape_panel">
+ <panel name="avatar_sex_panel">
+ <text name="gender_text">
+ 性別:
+ </text>
+ <radio_group name="sex_radio">
+ <radio_item label="女性" name="radio"/>
+ <radio_item label="男性" name="radio2"/>
+ </radio_group>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="shape_body_tab" title="身体"/>
+ <accordion_tab name="shape_head_tab" title="é ­"/>
+ <accordion_tab name="shape_eyes_tab" title="ç›®"/>
+ <accordion_tab name="shape_ears_tab" title="耳"/>
+ <accordion_tab name="shape_nose_tab" title="é¼»"/>
+ <accordion_tab name="shape_mouth_tab" title="å£"/>
+ <accordion_tab name="shape_chin_tab" title="ã‚ã”"/>
+ <accordion_tab name="shape_torso_tab" title="é ­"/>
+ <accordion_tab name="shape_legs_tab" title="è„š"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_shirt.xml b/indra/newview/skins/default/xui/ja/panel_edit_shirt.xml
new file mode 100644
index 0000000000..b2eb8fa18e
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_edit_shirt.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_shirt_panel">
+ <panel name="avatar_shirt_color_panel">
+ <texture_picker label="生地" name="Fabric" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠž"/>
+ <color_swatch label="色・色彩é…åˆ" name="Color/Tint" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="shirt_main_tab" title="シャツ"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_shoes.xml b/indra/newview/skins/default/xui/ja/panel_edit_shoes.xml
new file mode 100644
index 0000000000..83e302f8f9
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_edit_shoes.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_shoes_panel">
+ <panel name="avatar_shoes_color_panel">
+ <texture_picker label="生地" name="Fabric" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <color_swatch label="色・色彩é…åˆ" name="Color/Tint" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="shoes_main_tab" title="é´"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_skin.xml b/indra/newview/skins/default/xui/ja/panel_edit_skin.xml
new file mode 100644
index 0000000000..cd7efbec68
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_edit_skin.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_skin_panel">
+ <panel name="avatar_skin_color_panel">
+ <texture_picker label="頭部ã®ã‚¿ãƒˆã‚¥ãƒ¼" name="Head Tattoos" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠž"/>
+ <texture_picker label="上部ã®ã‚¿ãƒˆã‚¥ãƒ¼" name="Upper Tattoos" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠž"/>
+ <texture_picker label="下部ã®ã‚¿ãƒˆã‚¥ãƒ¼" name="Lower Tattoos" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠž"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="skin_color_tab" title="è‚Œã®è‰²"/>
+ <accordion_tab name="skin_face_tab" title="é¡”ã®è©³ç´°"/>
+ <accordion_tab name="skin_makeup_tab" title="メイクアップ"/>
+ <accordion_tab name="skin_body_tab" title="身体ã®è©³ç´°"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_skirt.xml b/indra/newview/skins/default/xui/ja/panel_edit_skirt.xml
new file mode 100644
index 0000000000..0a0936a3a9
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_edit_skirt.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_skirt_panel">
+ <panel name="avatar_skirt_color_panel">
+ <texture_picker label="生地" name="Fabric" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠž"/>
+ <color_swatch label="色・色彩é…åˆ" name="Color/Tint" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="skirt_main_tab" title="スカート"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_socks.xml b/indra/newview/skins/default/xui/ja/panel_edit_socks.xml
new file mode 100644
index 0000000000..7cbc75624f
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_edit_socks.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_socks_panel">
+ <panel name="avatar_socks_color_panel">
+ <texture_picker label="生地" name="Fabric" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <color_swatch label="色・色彩é…åˆ" name="Color/Tint" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="socks_main_tab" title="é´ä¸‹"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/ja/panel_edit_tattoo.xml
new file mode 100644
index 0000000000..d6aec87b45
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_edit_tattoo.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_tattoo_panel">
+ <panel name="avatar_tattoo_color_panel">
+ <texture_picker label="頭部ã®ã‚¿ãƒˆã‚¥ãƒ¼" name="Head Tattoo" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠž"/>
+ <texture_picker label="上部ã®ã‚¿ãƒˆã‚¥ãƒ¼" name="Upper Tattoo" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠž"/>
+ <texture_picker label="下部ã®ã‚¿ãƒˆã‚¥ãƒ¼" name="Lower Tattoo" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠž"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_underpants.xml b/indra/newview/skins/default/xui/ja/panel_edit_underpants.xml
new file mode 100644
index 0000000000..9287463b2c
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_edit_underpants.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_underpants_panel">
+ <panel name="avatar_underpants_color_panel">
+ <texture_picker label="生地" name="Fabric" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <color_swatch label="色・色彩é…åˆ" name="Color/Tint" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="underpants_main_tab" title="下ç€ãƒ‘ンツ"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_undershirt.xml b/indra/newview/skins/default/xui/ja/panel_edit_undershirt.xml
new file mode 100644
index 0000000000..085ad97384
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_edit_undershirt.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_undershirt_panel">
+ <panel name="avatar_undershirt_color_panel">
+ <texture_picker label="生地" name="Fabric" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <color_swatch label="色・色彩é…åˆ" name="Color/Tint" tool_tip="クリックã—ã¦ã‚«ãƒ©ãƒ¼ãƒ”ッカーを開ãã¾ã™"/>
+ </panel>
+ <accordion name="wearable_accordion">
+ <accordion_tab name="undershirt_main_tab" title="下ç€ã‚·ãƒ£ãƒ„"/>
+ </accordion>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_wearable.xml b/indra/newview/skins/default/xui/ja/panel_edit_wearable.xml
new file mode 100644
index 0000000000..2ae8e1863e
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_edit_wearable.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="ç€ç”¨å¯èƒ½ãªã‚‚ã®" name="panel_edit_wearable">
+ <string name="edit_shape_title">
+ シェイプを編集中
+ </string>
+ <string name="edit_skin_title">
+ スキンを編集中
+ </string>
+ <string name="edit_hair_title">
+ 髪を編集中
+ </string>
+ <string name="edit_eyes_title">
+ 目を編集中
+ </string>
+ <string name="edit_shirt_title">
+ シャツを編集中
+ </string>
+ <string name="edit_pants_title">
+ パンツを編集中
+ </string>
+ <string name="edit_shoes_title">
+ é´ã‚’編集中
+ </string>
+ <string name="edit_socks_title">
+ é´ä¸‹ã‚’編集中
+ </string>
+ <string name="edit_jacket_title">
+ ジャケットを編集中
+ </string>
+ <string name="edit_skirt_title">
+ スカートを編集中
+ </string>
+ <string name="edit_gloves_title">
+ 手袋を編集中
+ </string>
+ <string name="edit_undershirt_title">
+ 下ç€ï¼ˆä¸Šï¼‰ã‚’編集中
+ </string>
+ <string name="edit_underpants_title">
+ 下ç€ï¼ˆä¸‹ï¼‰ã‚’編集中
+ </string>
+ <string name="edit_alpha_title">
+ アルファマスクを編集中
+ </string>
+ <string name="edit_tattoo_title">
+ タトゥーを編集中
+ </string>
+ <string name="shape_desc_text">
+ シェイプ:
+ </string>
+ <string name="skin_desc_text">
+ スキン:
+ </string>
+ <string name="hair_desc_text">
+ 髪:
+ </string>
+ <string name="eyes_desc_text">
+ 目:
+ </string>
+ <string name="shirt_desc_text">
+ シャツ:
+ </string>
+ <string name="pants_desc_text">
+ パンツ:
+ </string>
+ <string name="shoes_desc_text">
+ é´ï¼š
+ </string>
+ <string name="socks_desc_text">
+ é´ä¸‹ï¼š
+ </string>
+ <string name="jacket_desc_text">
+ ジャケット:
+ </string>
+ <string name="skirt_skirt_desc_text">
+ スカート:
+ </string>
+ <string name="gloves_desc_text">
+ 手袋:
+ </string>
+ <string name="undershirt_desc_text">
+ 下ç€ã‚·ãƒ£ãƒ„:
+ </string>
+ <string name="underpants_desc_text">
+ 下ç€ãƒ‘ンツ:
+ </string>
+ <string name="alpha_desc_text">
+ アルファマスク:
+ </string>
+ <string name="tattoo_desc_text">
+ タトゥ:
+ </string>
+ <text name="edit_wearable_title" value="シェイプを編集中"/>
+ <panel label="シャツ" name="wearable_type_panel">
+ <text name="description_text" value="シェイプ:"/>
+ </panel>
+ <panel name="button_panel">
+ <button label="別åã§ä¿å­˜" name="save_as_button"/>
+ <button label="å…ƒã«æˆ»ã™" name="revert_button"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_group_control_panel.xml b/indra/newview/skins/default/xui/ja/panel_group_control_panel.xml
new file mode 100644
index 0000000000..5369daed03
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_group_control_panel.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_im_control_panel">
+ <button label="グループ情報" name="group_info_btn"/>
+ <panel name="panel_call_buttons">
+ <button label="グループã«ã‚³ãƒ¼ãƒ«" name="call_btn"/>
+ <button label="コール終了" name="end_call_btn"/>
+ <button label="ボイスコントロールを開ã" name="voice_ctrls_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_group_general.xml b/indra/newview/skins/default/xui/ja/panel_group_general.xml
index ea2953038e..98b118f58f 100644
--- a/indra/newview/skins/default/xui/ja/panel_group_general.xml
+++ b/indra/newview/skins/default/xui/ja/panel_group_general.xml
@@ -1,80 +1,37 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="一般" name="general_tab">
- <string name="help_text">
- 「一般ã€ã‚¿ãƒ–ã«ã¯ã€ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«é–¢ã™ã‚‹
-一般情報ã€ã‚ªãƒ¼ãƒŠãƒ¼ã¨è¡¨ç¤ºå¯èƒ½ãªãƒ¡ãƒ³ãƒãƒ¼ã®ãƒªã‚¹ãƒˆ
-一般的ãªã€Œã‚°ãƒ«ãƒ¼ãƒ—環境設定ã€ã€ãƒ¡ãƒ³ãƒãƒ¼ã®ã‚ªãƒ—ションãŒå«ã¾ã‚Œã¾ã™ã€‚
+ <panel.string name="help_text">
+ 「一般ã€ã‚¿ãƒ–ã«ã¯ã€ãƒ¡ãƒ³ãƒãƒ¼ä¸€è¦§ã€è¨­å®šã€ãƒ¡ãƒ³ãƒãƒ¼ã®ã‚ªãƒ—ションãªã©ã€ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«é–¢ã™ã‚‹ä¸€èˆ¬çš„ãªæƒ…å ±ãŒè¨˜ã•ã‚Œã¦ã„ã¾ã™ã€‚
-オプションã®ä¸Šã§ãƒžã‚¦ã‚¹ã‚«ãƒ¼ã‚½ãƒ«ã‚’å‹•ã‹ã™ã¨ã€ãƒ˜ãƒ«ãƒ—情報を得られã¾ã™ã€‚
- </string>
- <string name="group_info_unchanged">
- グループ設定ãŒå¤‰æ›´ã•ã‚Œã¾ã—ãŸã€‚
- </string>
- <button label="?" label_selected="?" name="help_button"/>
- <line_editor label="æ–°ã—ã„グループåã‚’ã“ã“ã«å…¥åŠ›ã—ã¦ãã ã•ã„。" name="group_name_editor" width="330"/>
- <text name="group_name" width="330">
- æ–°ã—ã„グループåã‚’ã“ã“ã«å…¥åŠ›ã—ã¦ãã ã•ã„。
- </text>
- <text name="prepend_founded_by">
- 創設者
- </text>
- <text name="founder_name">
- (待機中)
- </text>
- <text name="group_charter_label">
- グループç†å¿µ
- </text>
- <texture_picker label="グループ記章" name="insignia" tool_tip="写真をクリックã—ã¦é¸æŠž"/>
+オプションã«ãƒžã‚¦ã‚¹ã‚«ãƒ¼ã‚½ãƒ«ã‚’当ã¦ã‚‹ã¨è©³ã—ã„説明ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
+ </panel.string>
+ <panel.string name="group_info_unchanged">
+ 一般的ãªã‚°ãƒ«ãƒ¼ãƒ—情報ãŒå¤‰æ›´ã•ã‚Œã¾ã—ãŸã€‚
+ </panel.string>
+ <panel.string name="incomplete_member_data_str">
+ メンãƒãƒ¼ãƒ»ãƒ‡ãƒ¼ã‚¿ã‚’検索
+ </panel.string>
<text_editor name="charter">
グループã®ç†å¿µã€æŒ‡é‡ã‚’記入ã—ã¦ãã ã•ã„
</text_editor>
- <button label="å‚加ã™ã‚‹ï¼ˆL$0)" label_selected="å‚加ã™ã‚‹ï¼ˆL$0)" name="join_button"/>
- <button label="詳細表示" label_selected="詳細表示" name="info_button"/>
- <text name="text_owners_and_visible_members">
- オーナーã¨å…¬é–‹ãƒ¡ãƒ³ãƒãƒ¼
- </text>
- <text name="text_owners_are_shown_in_bold">
- (オーナーã¯å¤ªå­—ã§è¡¨ç¤ºã•ã‚Œã¦ã„ã¾ã™ï¼‰
- </text>
<name_list name="visible_members">
- <column label="メンãƒãƒ¼å" name="name"/>
- <column label="タイトル" name="title"/>
- <column label="最終ログイン" name="online"/>
+ <name_list.columns label="メンãƒãƒ¼" name="name"/>
+ <name_list.columns label="タイトル" name="title"/>
</name_list>
- <text name="text_group_preferences">
- グループ環境設定
+ <text name="active_title_label">
+ ç§ã®ã‚¿ã‚¤ãƒˆãƒ«
</text>
+ <combo_box name="active_title" tool_tip="ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—をアクティブã«ã—ãŸã¨ãã«ã€ã‚¢ãƒã‚¿ãƒ¼åã®ä¸Šã«è¡¨ç¤ºã•ã‚Œã‚‹ã‚¿ã‚¤ãƒˆãƒ«ã‚’設定ã—ã¾ã™ã€‚"/>
+ <check_box label="通知をå—ä¿¡" name="receive_notices" tool_tip="ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‹ã‚‰ã®é€šçŸ¥ã‚’å—ä¿¡ã™ã‚‹ã‹ã©ã†ã‹ã®è¨­å®šã‚’è¡Œã„ã¾ã™ã€‚ グループã‹ã‚‰ã‚¹ãƒ‘ムãŒé€ã‚‰ã‚Œã¦ãã‚‹å ´åˆã¯ã“ã®ãƒœãƒƒã‚¯ã‚¹ã®ãƒã‚§ãƒƒã‚¯ã‚’外ã—ã¦ãã ã•ã„。"/>
+ <check_box label="プロフィールã«è¡¨ç¤º" name="list_groups_in_profile" tool_tip="ã‚ãªãŸã®ãƒ—ロフィールã«ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—を表示ã™ã‚‹ã‹ã©ã†ã‹ã®è¨­å®šã‚’è¡Œã„ã¾ã™ã€‚"/>
<panel name="preferences_container">
- <check_box label="検索ã«è¡¨ç¤º" name="show_in_group_list" tool_tip="ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—を検索çµæžœã«è¡¨ç¤ºã•ã›ã¾ã™"/>
- <check_box label="会員募集" name="open_enrollement" tool_tip="招待状ãªã—ã«è‡ªç”±ã«ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«åŠ å…¥ã™ã‚‹ã“ã¨ã‚’許å¯ã™ã‚‹ã‹ã©ã†ã‹ã‚’指定ã—ã¾ã™"/>
- <check_box label="入会費:L$" name="check_enrollment_fee" tool_tip="ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã¸ã®å‚加ã«å…¥ä¼šè²»ã‚’å¿…é ˆã¨ã™ã‚‹ã‹ã©ã†ã‹ã‚’指定ã—ã¾ã™"/>
- <spinner name="spin_enrollment_fee" tool_tip="「入会費ã€ãŒãƒã‚§ãƒƒã‚¯ã•ã‚Œã¦ã„ã‚‹å ´åˆã€æ–°è¦ä¼šå“¡ã¯å…¥ä¼šæ™‚ã«ã“ã“ã«æŒ‡å®šã•ã‚ŒãŸé‡‘é¡ã‚’支払ã†å¿…è¦ãŒã‚ã‚Šã¾ã™"/>
- <combo_box name="group_mature_check" tool_tip="グループ情報ãŒMatureå‘ã‘ã‹ã©ã†ã‹ã®è¨­å®šã‚’ã—ã¾ã™ã€‚">
- <combo_item name="select_mature">
- - Matureã®é¸æŠž -
- </combo_item>
- <combo_item name="mature">
- Matureコンテンツ
- </combo_item>
- <combo_item name="pg">
- PGコンテンツ
- </combo_item>
+ <check_box label="会員募集" name="open_enrollement" tool_tip="招待ã•ã‚Œãªãã¦ã‚‚æ–°è¦ãƒ¡ãƒ³ãƒãƒ¼ãŒåŠ å…¥ã§ãã‚‹ã‹ã©ã†ã‹ã‚’設定ã—ã¾ã™ã€‚"/>
+ <check_box label="入会費" name="check_enrollment_fee" tool_tip="入会費ãŒå¿…è¦ã‹ã©ã†ã‹ã‚’設定ã—ã¾ã™ã€‚"/>
+ <spinner label="L$" name="spin_enrollment_fee" tool_tip="「入会費ã€ã«ãƒã‚§ãƒƒã‚¯ãŒå…¥ã£ã¦ã„ã‚‹å ´åˆã€æ–°è¦ãƒ¡ãƒ³ãƒãƒ¼ã¯æŒ‡å®šã•ã‚ŒãŸå…¥ä¼šè²»ã‚’支払ã‚ãªã‘ã‚Œã°ã‚°ãƒ«ãƒ¼ãƒ—ã«å…¥ã‚Œã¾ã›ã‚“。"/>
+ <check_box initial_value="true" label="検索ã«è¡¨ç¤º" name="show_in_group_list" tool_tip="ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—を検索çµæžœã«è¡¨ç¤ºã•ã›ã¾ã™"/>
+ <combo_box name="group_mature_check" tool_tip="グループ情報㌠Mature å‘ã‘ã‹ã©ã†ã‹ã®è¨­å®šã‚’ã—ã¾ã™ã€‚">
+ <combo_box.item label="PGコンテンツ" name="pg"/>
+ <combo_box.item label="Matureコンテンツ" name="mature"/>
</combo_box>
- <panel name="title_container">
- <text name="active_title_label">
- ç§ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ–・タイトル
- </text>
- <combo_box name="active_title" tool_tip="ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—をアクティブ設定ã«ã—ãŸéš›ã‚¢ãƒã‚¿ãƒ¼ã®ãƒãƒ¼ãƒ ã‚¿ã‚°ã«è¡¨ç¤ºã•ã‚Œã‚‹ã‚¿ã‚¤ãƒˆãƒ«ã®è¨­å®š"/>
- </panel>
- <check_box label="グループ通知をå—ä¿¡" name="receive_notices" tool_tip="グループã‹ã‚‰ã®é€šçŸ¥ã‚’å—ä¿¡ã™ã‚‹ã‹ã©ã†ã‹ã‚’指定ã—ã¾ã™ã€‚ ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ãŒã‚¹ãƒ‘ム行為をã—ã¦ã„ã‚‹å ´åˆã¯ã€ã“ã®ãƒœãƒƒã‚¯ã‚¹ã®ãƒã‚§ãƒƒã‚¯ã‚’外ã—ã¦ãã ã•ã„"/>
- <check_box label="プロフィールã«è¡¨ç¤º" name="list_groups_in_profile" tool_tip="ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‚’ã‚ãªãŸã®ãƒ—ロフィールã«è¡¨ç¤ºã™ã‚‹ã‹ã©ã†ã‹ã‚’設定ã—ã¾ã™"/>
</panel>
- <string name="incomplete_member_data_str">
- メンãƒãƒ¼ãƒ»ãƒ‡ãƒ¼ã‚¿ã‚’検索
- </string>
- <string name="confirm_group_create_str">
- ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã®ä½œæˆã«ã¯L$100ã‹ã‹ã‚Šã¾ã™ã€‚
-ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã®ä½œæˆã«L$100ã‚‚ã®ãŠé‡‘ã‚’ã‹ã‘ã¦ã‚‚ã‹ã¾ã„ã¾ã›ã‚“ã‹ï¼Ÿ æ…Žé‡ã«åˆ¤æ–­ã—ã¦ãã ã•ã„。
-48時間以内ã«èª°ã‚‚ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å‚加ã—ãªã‹ã£ãŸå ´åˆã€ã‚°ãƒ«ãƒ¼ãƒ—ã¯è§£ä½“ã•ã‚Œã€ã‚°ãƒ«ãƒ¼ãƒ—ã®åå‰ã¯ä»Šå¾Œä½¿ç”¨ã§ããªããªã‚Šã¾ã™ã€‚
- </string>
</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/ja/panel_group_info_sidetray.xml
new file mode 100644
index 0000000000..7c8cb85990
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_group_info_sidetray.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="グループ情報" name="GroupInfo">
+ <panel.string name="default_needs_apply_text">
+ ç¾åœ¨ã®ã‚¿ãƒ–ã«ã¯ã€ä¿å­˜ã•ã‚Œã¦ã„ãªã„変更ãŒã‚ã‚Šã¾ã™ã€‚
+ </panel.string>
+ <panel.string name="want_apply_text">
+ 変更をä¿å­˜ã—ã¾ã™ã‹ï¼Ÿ
+ </panel.string>
+ <panel.string name="group_join_btn">
+ å‚加 (L$[AMOUNT])
+ </panel.string>
+ <panel.string name="group_join_free">
+ ç„¡æ–™
+ </panel.string>
+ <text name="group_name" value="(ローディング...)"/>
+ <line_editor label="æ–°ã—ã„グループã®åå‰ã‚’入力" name="group_name_editor"/>
+ <texture_picker label="" name="insignia" tool_tip="クリックã—ã¦å†™çœŸã‚’é¸æŠžã—ã¾ã™"/>
+ <text name="prepend_founded_by">
+ 創始者:
+ </text>
+ <name_box initial_value="(å–得中)" name="founder_name"/>
+ <text name="join_cost_text">
+ ç„¡æ–™
+ </text>
+ <button label="å‚加ã—ã¾ã™ï¼" name="btn_join"/>
+ <accordion name="groups_accordion">
+ <accordion_tab name="group_general_tab" title="一般"/>
+ <accordion_tab name="group_roles_tab" title="役割"/>
+ <accordion_tab name="group_notices_tab" title="通知"/>
+ <accordion_tab name="group_land_tab" title="土地・資産"/>
+ </accordion>
+ <panel name="button_row">
+ <button label="作æˆ" label_selected="æ–°ã—ã„グループ" name="btn_create"/>
+ <button label="ä¿å­˜" label_selected="ä¿å­˜" name="btn_apply"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_group_invite.xml b/indra/newview/skins/default/xui/ja/panel_group_invite.xml
index 14009f2972..eddb0c3612 100644
--- a/indra/newview/skins/default/xui/ja/panel_group_invite.xml
+++ b/indra/newview/skins/default/xui/ja/panel_group_invite.xml
@@ -1,30 +1,30 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="メンãƒãƒ¼ã‚’招待" name="invite_panel">
- <text name="help_text" font="SansSerifSmall" height="72" bottom_delta="-96">
+ <panel.string name="confirm_invite_owner_str">
+ 本当ã«æ–°ã—ã„所有者を招待ã—ã¾ã™ã‹?ã“ã®æ“作ã¯å–り消ã—ã§ãã¾ã›ã‚“。
+ </panel.string>
+ <panel.string name="loading">
+ (ローディング...)
+ </panel.string>
+ <panel.string name="already_in_group">
+ 何人ã‹ã®ã‚¢ãƒã‚¿ãƒ¼ã¯æ—¢ã«ã‚°ãƒ«ãƒ¼ãƒ—加入済ã¿ã®ãŸã‚ã€æ‹›å¾…ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸã€‚
+ </panel.string>
+ <text bottom_delta="-96" font="SansSerifSmall" height="72" name="help_text">
ã‚ãªãŸã®ã‚°ãƒ«ãƒ¼ãƒ—ã«ä¸€åº¦ã«è¤‡æ•°ã®
ä½äººã‚’招待ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
「リストã‹ã‚‰ä½äººã‚’é¸æŠžã€
をクリックã—ã¦ãã ã•ã„。
</text>
<button bottom_delta="-10" label="リストã‹ã‚‰ä½äººã‚’é¸æŠž" name="add_button" tool_tip=""/>
- <name_list name="invitee_list" height="156" bottom_delta="-160"
- tool_tip="複数ã®ä½äººã‚’é¸æŠžã™ã‚‹ã«ã¯ã€Ctrlキーを押ã—ãªãŒã‚‰ä½äººåをクリックã—ã¾ã™ã€‚" />
- <button label="リストã‹ã‚‰é¸æŠžã—ãŸã‚‚ã®ã‚’削除" name="remove_button"
- tool_tip="上ã§é¸æŠžã—ãŸå±…ä½è€…を招待リストã‹ã‚‰å‰Šé™¤ã—ã¾ã™ã€‚" />
- <text>
- 割り当ã¦å…ˆã®å½¹å‰²ã‚’é¸æŠžï¼š
- </text>
+ <name_list bottom_delta="-160" height="156" name="invitee_list" tool_tip="Ctrl キーを押ã—ãªãŒã‚‰è¤‡æ•°ã®ä½äººã‚’クリックã§ãã¾ã™"/>
+ <button label="リストã‹ã‚‰é¸æŠžã—ãŸã‚‚ã®ã‚’削除" name="remove_button" tool_tip="招待リストã‹ã‚‰ä¸Šã§é¸æŠžã—ãŸä½äººã‚’削除ã—ã¾ã™"/>
<text name="role_text">
割り当ã¦å…ˆã®å½¹å‰²ã‚’é¸æŠžï¼š
</text>
- <combo_box name="role_name"
- tool_tip="メンãƒãƒ¼ã«å‰²ã‚Šå½“ã¦å¯èƒ½ãªå½¹å‰²ã‚’リストã‹ã‚‰é¸æŠžã€‚" />
- <button label="招待をé€ä¿¡" name="ok_button" />
- <button label="å–り消ã—" name="cancel_button" />
- <string name="confirm_invite_owner_str">
- 本当ã«æ–°ã—ã„所有者を招待ã—ã¾ã™ã‹?ã“ã®æ“作ã¯å–り消ã—ã§ãã¾ã›ã‚“。
+ <combo_box name="role_name" tool_tip="メンãƒãƒ¼ã«å‰²ã‚Šå½“ã¦ãŸã„役割をリストã‹ã‚‰é¸ã‚“ãã ã•ã„"/>
+ <button label="招待をé€ä¿¡" name="ok_button"/>
+ <button label="å–り消ã—" name="cancel_button"/>
+ <string name="GroupInvitation">
+ グループã¸ã®æ‹›å¾…
</string>
- <text name="loading">
- (ローディング...)
- </text>
</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_group_land_money.xml b/indra/newview/skins/default/xui/ja/panel_group_land_money.xml
index f55dbf9009..cfbc51a44e 100644
--- a/indra/newview/skins/default/xui/ja/panel_group_land_money.xml
+++ b/indra/newview/skins/default/xui/ja/panel_group_land_money.xml
@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="土地ã¨L$" name="land_money_tab">
<string name="help_text">
- グループ所有地一覧ã¯ã€å¯„付ã«é–¢ã™ã‚‹è©³ç´°ã¨ä¸€ç·’ã«è¡¨ç¤ºã•ã‚Œã¦ã„ã¾ã™ã€‚ 「土地利用ã®åˆè¨ˆã€ãŒã€Œå¯„付ç·é¡ã€ä»¥ä¸‹ã€ã¾ãŸã¯åŒã˜ã«ãªã‚‹ã¾ã§è­¦å‘ŠãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ 「計画ã€ã€ã€Œè©³ç´°ã€ã€ã€Œè²©å£²ã€ã‚¿ãƒ–ã«ã¯ã‚°ãƒ«ãƒ¼ãƒ—ã®è³‡é‡‘ã«é–¢ã™ã‚‹æƒ…å ±ãŒæŽ²è¼‰ã•ã‚Œã¦ã„ã¾ã™ã€‚
+ 「土地利用ã®åˆè¨ˆã€ãŒã€Œå¯„付ç·é¡ã€ä»¥ä¸‹ã€ã¾ãŸã¯åŒã˜ã«ãªã‚‹ã¾ã§è­¦å‘ŠãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
</string>
<button label="?" name="help_button"/>
<string name="cant_view_group_land_text">
- ã‚ãªãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—所有ã®åœŸåœ°è¡¨ç¤ºã‚’許ã•ã‚Œã¦ã„ã¾ã›ã‚“。
+ グループ所有地を確èªã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“。
</string>
<string name="cant_view_group_accounting_text">
- ã‚ãªãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—ã®ä¼šè¨ˆæƒ…å ±ã®è¡¨ç¤ºã‚’許ã•ã‚Œã¦ã„ã¾ã›ã‚“。
+ グループã®ä¼šè¨ˆæƒ…報を確èªã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“。
</string>
<string name="loading_txt">
ロード中...
@@ -17,42 +17,45 @@
グループã®ä¿æœ‰åœ°
</text>
<scroll_list name="group_parcel_list">
- <column label="区画å" name="name"/>
+ <column label="区画" name="name"/>
<column label="地域(リージョン)" name="location"/>
<column label="種類" name="type"/>
<column label="é¢ç©" name="area"/>
<column label="" name="hidden"/>
</scroll_list>
- <button label="地図上ã«è¡¨ç¤º" label_selected="地図上ã«è¡¨ç¤º" name="map_button"/>
+ <button label="地図" label_selected="地図" name="map_button"/>
<text name="total_contributed_land_label">
- 寄付ç·é¡ï¼š
+ 寄付åˆè¨ˆï¼š
</text>
<text name="total_contributed_land_value" width="150">
- [AREA]平方メートル
+ [AREA] 平方メートル
</text>
<text name="total_land_in_use_label">
土地利用ã®åˆè¨ˆï¼š
</text>
<text name="total_land_in_use_value" width="150">
- [AREA]平方メートル
+ [AREA] 平方メートル
</text>
<text name="land_available_label">
- 利用å¯ã®åœŸåœ°ï¼š
+ 利用å¯èƒ½ã®åœŸåœ°ï¼š
</text>
<text name="land_available_value" width="150">
- [AREA]平方メートル
+ [AREA] 平方メートル
</text>
<text name="your_contribution_label">
ã‚ãªãŸã®è²¢çŒ®ï¼š
</text>
<string name="land_contrib_error">
- 土地ã®å‡ºè³‡è¨­å®šã‚’è¡Œã†ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚
+ 土地ã®è²¢çŒ®ã‚’設定ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“
</string>
+ <text name="your_contribution_units">
+ 平方メートル
+ </text>
<text name="your_contribution_max_value">
- 平方メートル ([AMOUNT]最大)
+ (最大 [AMOUNT])
</text>
<text name="group_over_limit_text">
- 使用中ã®åœŸåœ°ã‚’サãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ã€ã‚°ãƒ«ãƒ¼ãƒ—・メンãƒãƒ¼ãŒã•ã‚‰ã«å¤šãã®åœŸåœ°ã‚¯ãƒ¬ã‚¸ãƒƒãƒˆã‚’æä¾›ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
+ 土地を使用ã™ã‚‹ã«ã¯ã€åœŸåœ°ã‚¯ãƒ¬ã‚¸ãƒƒãƒˆãŒã‚‚ã£ã¨å¿…è¦ã§ã™
</text>
<text name="group_money_heading">
グループL$
@@ -60,22 +63,22 @@
<tab_container name="group_money_tab_container">
<panel label="計画" name="group_money_planning_tab">
<text_editor name="group_money_planning_text">
- 計算中...
+ ローディング...
</text_editor>
</panel>
<panel label="詳細" name="group_money_details_tab">
<text_editor name="group_money_details_text">
- 計算中…
+ ローディング...
</text_editor>
- <button label="å‰ã®é€±" label_selected="å‰ã®é€±" name="earlier_details_button" tool_tip="å‰ã®é€±ã®å±¥æ­´"/>
- <button label="次ã®é€±" label_selected="次ã®é€±" name="later_details_button" tool_tip="次ã®é€±ã®å±¥æ­´"/>
+ <button label="å‰ã®é€±" label_selected="å‰ã®é€±" name="earlier_details_button" tool_tip="å‰ã®é€±"/>
+ <button label="次ã®é€±" label_selected="次ã®é€±" name="later_details_button" tool_tip="次ã®é€±"/>
</panel>
- <panel label="販売" name="group_money_sales_tab">
+ <panel label="販売å–引" name="group_money_sales_tab">
<text_editor name="group_money_sales_text">
- 計算中…
+ ローディング...
</text_editor>
- <button label="å‰ã®é€±" label_selected="å‰ã®é€±" name="earlier_sales_button" tool_tip="å‰ã®é€±ã®å±¥æ­´"/>
- <button label="次ã®é€±" label_selected="次ã®é€±" name="later_sales_button" tool_tip="次ã®é€±ã®å±¥æ­´"/>
+ <button label="å‰ã®é€±" label_selected="å‰ã®é€±" name="earlier_sales_button" tool_tip="å‰ã®é€±"/>
+ <button label="次ã®é€±" label_selected="次ã®é€±" name="later_sales_button" tool_tip="次ã®é€±"/>
</panel>
</tab_container>
</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_group_list_item.xml b/indra/newview/skins/default/xui/ja/panel_group_list_item.xml
new file mode 100644
index 0000000000..a652e3bf11
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_group_list_item.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="group_list_item">
+ <text name="group_name" value="ä¸æ˜Ž"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_group_notices.xml b/indra/newview/skins/default/xui/ja/panel_group_notices.xml
index 090ae2e329..684e22a4da 100644
--- a/indra/newview/skins/default/xui/ja/panel_group_notices.xml
+++ b/indra/newview/skins/default/xui/ja/panel_group_notices.xml
@@ -1,45 +1,34 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="通知" name="notices_tab">
- <string name="help_text">
- 通知機能を使ã†ã¨ã€ã‚°ãƒ«ãƒ¼ãƒ—内ã§ã™ã°ã‚„ã情報をä¼é”ã§ãã¾ã™ã€‚
-複数ã®ã‚ã¦å…ˆã«ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’é€ä¿¡ã§ãã‚‹ã»ã‹ã€
-å¿…è¦ã«å¿œã˜ã¦ã‚¢ã‚¤ãƒ†ãƒ ã‚’メッセージã«æ·»ä»˜ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
-通知ã¯ã€å—信アビリティãŒã‚る役割ã®ã‚°ãƒ«ãƒ¼ãƒ—・メンãƒãƒ¼ã«ã®ã¿é…ä¿¡ã•ã‚Œã¾ã™ã€‚
-通知をオフã«ã™ã‚‹ã«ã¯ã€ä¸€èˆ¬ã‚¿ãƒ–を使ã„ã¾ã™ã€‚
- </string>
- <string name="no_notices_text">
- éŽåŽ»ã®é€šçŸ¥ã¯ã‚ã‚Šã¾ã›ã‚“。
- </string>
- <button label="?" label_selected="?" name="help_button"/>
- <text name="lbl">
- グループ通知アーカイブ
- </text>
+ <panel.string name="help_text">
+ 通知ã§ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã¨
+アイテムを添付ã—ã¦é€ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ 通知をå—ã‘å–る権é™ã®ã‚る役割ã®
+グループメンãƒãƒ¼ãŒ
+å—ã‘å–ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ 通知をå—ã‘å–ã‚ŠãŸããªã„å ´åˆã¯
+一般タブã‹ã‚‰è¨­å®šã—ã¦ãã ã•ã„。
+ </panel.string>
+ <panel.string name="no_notices_text">
+ éŽåŽ»ã®é€šçŸ¥ã¯ã‚ã‚Šã¾ã›ã‚“
+ </panel.string>
<text name="lbl2">
- 通知ã¯14日間ä¿å­˜ã•ã‚Œã¾ã™ã€‚閲覧ã—ãŸã„通知をクリックã—ã¦ãã ã•ã„。
-æ–°ç€ã®é€šçŸ¥ã‚’ãƒã‚§ãƒƒã‚¯ã™ã‚‹ã«ã¯ã€ã€Œæ›´æ–°ã€ãƒœã‚¿ãƒ³ã‚’クリックã—ã¾ã™ã€‚
-ãŸã ã—ã€å„グループã®é€šçŸ¥ãƒªã‚¹ãƒˆã¯1æ—¥ã‚ãŸã‚Š200通ã«åˆ¶é™ã•ã‚Œã¾ã™ã€‚
+ 通知㯠14 日間ä¿å­˜ã•ã‚Œã¾ã™ã€‚
+1 æ—¥ã®åˆ¶é™æ•°ã¯ 200 通ã§ã™ã€‚
</text>
<scroll_list name="notice_list">
- <column label="" name="icon"/>
- <column label="件å" name="subject"/>
- <column label="é€ã‚Šä¸»" name="from"/>
- <column label="日付" name="date"/>
+ <scroll_list.columns label="" name="icon"/>
+ <scroll_list.columns label="件å" name="subject"/>
+ <scroll_list.columns label="é€ã‚Šä¸»" name="from"/>
+ <scroll_list.columns label="日付" name="date"/>
</scroll_list>
<text name="notice_list_none_found">
- 何も見ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚
+ 見ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ
</text>
- <button label="æ–°ã—ã„通知を作æˆ" label_selected="æ–°ã—ã„通知を作æˆ" name="create_new_notice"/>
+ <button label="æ–°ã—ã„通知を作æˆ" label_selected="æ–°ã—ã„通知を作æˆ" name="create_new_notice" tool_tip="æ–°ã—ã„通知を作æˆ"/>
<button label="更新" label_selected="リスト更新" name="refresh_notices"/>
<panel label="æ–°ã—ã„通知を作æˆ" name="panel_create_new_notice">
<text name="lbl">
通知を作æˆ
</text>
- <text name="lbl2">
- 件åを入力ã—ã¦é€šçŸ¥ã‚’é€ã‚Šã¾ã™ã€‚
-æŒã¡ç‰©ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’1ã¤ã“ã®ãƒ‘ãƒãƒ«ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦ã€
-通知ã«æ·»ä»˜ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ 添付ã§ãã‚‹ã®ã¯ã‚³ãƒ”ーã€
-譲渡ãŒå¯èƒ½ãªã‚¢ã‚¤ãƒ†ãƒ ã§ã€ãƒ•ã‚©ãƒ«ãƒ€ã‚’é€ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
- </text>
<text name="lbl3">
件å:
</text>
@@ -49,16 +38,19 @@
<text name="lbl5">
添付:
</text>
- <button label="添付物を削除" label_selected="添付物を削除" name="remove_attachment"/>
- <button label="通知をé€ä¿¡" label_selected="通知をé€ä¿¡" name="send_notice"/>
- <panel name="drop_target" tool_tip="æŒã¡ç‰©ã‹ã‚‰ã‚¢ã‚¤ãƒ†ãƒ ã‚’メッセージ欄ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦ãã ã•ã„。通知ã¨ä¸€ç·’ã«é€ä¿¡ã•ã‚Œã¾ã™ã€‚é€ä¿¡ã™ã‚‹ã«ã¯ã‚³ãƒ”ーã€è­²æ¸¡ãŒå¯èƒ½ãªã‚ªãƒ–ジェクトã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"/>
+ <text name="string">
+ 添付ã™ã‚‹ã‚¢ã‚¤ãƒ†ãƒ ã‚’ã“ã“ã«ãƒ‰ãƒ©ãƒƒã‚° -- &gt;
+ </text>
+ <button label="å–り外ã™" label_selected="添付物を削除" name="remove_attachment"/>
+ <button label="é€ä¿¡" label_selected="é€ä¿¡" name="send_notice"/>
+ <group_drop_target name="drop_target" tool_tip="æŒã¡ç‰©ã‹ã‚‰ã‚¢ã‚¤ãƒ†ãƒ ã‚’メッセージ欄ã«ãƒ‰ãƒ©ãƒƒã‚°ã—ã¦ãã ã•ã„。通知ã¨ä¸€ç·’ã«é€ä¿¡ã•ã‚Œã¾ã™ã€‚é€ä¿¡ã™ã‚‹ã«ã¯ã‚³ãƒ”ーã€è­²æ¸¡ãŒå¯èƒ½ãªã‚ªãƒ–ジェクトã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"/>
</panel>
<panel label="éŽåŽ»ã®é€šçŸ¥ã‚’表示" name="panel_view_past_notice">
<text name="lbl">
アーカイブ通知
</text>
<text name="lbl2">
- æ–°ã—ã„通知ã®é€ä¿¡ã¯ã€ä¸Šã®[æ–°ã—ã„通知を作æˆã™ã‚‹]をクリックã—ã¦ãã ã•ã„。
+ æ–°ã—ã„通知をé€ä¿¡ã™ã‚‹ã«ã¯ã€+ ボタンを押ã—ã¦ãã ã•ã„
</text>
<text name="lbl3">
件å:
@@ -66,6 +58,6 @@
<text name="lbl4">
メッセージ:
</text>
- <button label="添付物を開ã" label_selected="添付物を開ã" name="open_attachment"/>
+ <button label="添付アイテムを開ã" label_selected="添付物を開ã" name="open_attachment"/>
</panel>
</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_group_notify.xml b/indra/newview/skins/default/xui/ja/panel_group_notify.xml
new file mode 100644
index 0000000000..2edd054180
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_group_notify.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="instant_message" name="panel_group_notify">
+ <string name="message_max_lines_count" value="7"/>
+ <string name="subject_font" value="SANSSERIF_BIG"/>
+ <string name="date_font" value="SANSSERIF"/>
+ <panel label="header" name="header">
+ <text name="title" value="é€ä¿¡è€…ã®åå‰ / グループå"/>
+ </panel>
+ <text_editor name="message" value="message"/>
+ <text name="attachment" value="添付アイテム"/>
+ <button label="Ok" name="btn_ok"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_group_roles.xml b/indra/newview/skins/default/xui/ja/panel_group_roles.xml
index 2d39938b53..1f2d28ca4f 100644
--- a/indra/newview/skins/default/xui/ja/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/ja/panel_group_roles.xml
@@ -1,157 +1,115 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="メンãƒãƒ¼ã¨å½¹å‰²" name="roles_tab">
- <string name="default_needs_apply_text">
- ç¾åœ¨ã®ã‚µãƒ–タブã«ã€æœªé©ç”¨ã®å¤‰æ›´ãŒã‚ã‚Šã¾ã™ã€‚
- </string>
- <string name="want_apply_text">
- ã“れらã®å¤‰æ›´ã‚’é©ç”¨ã—ã¾ã™ã‹ï¼Ÿ
- </string>
- <button label="?" name="help_button"/>
- <panel name="members_header">
- <text name="static">
- メンãƒãƒ¼ã¨å½¹å‰²
- </text>
- <text name="static2">
- グループ・メンãƒãƒ¼ã«ã¯ã€å½¹å‰²ã¨èƒ½åŠ›ãŒå‰²ã‚Šå½“ã¦ã‚‰ã‚Œã¾ã™ã€‚ ã“ã®è¨­å®šã¯ã€
-組織ã®è¦æ¨¡ã«å¿œã˜ã¦æŸ”軟ã‹ã¤å®¹æ˜“ã«ã‚«ã‚¹ã‚¿ãƒžã‚¤ã‚ºã§ãã¾ã™ã€‚
- </text>
- </panel>
- <panel name="roles_header">
- <text name="static">
- 役割
- </text>
- <text name="role_properties_modifiable">
- 下ã«ã‚る役割をé¸æŠžã—ã¦ãã ã•ã„。 役割ã®åå‰ã€èª¬æ˜Žã€ãƒ¡ãƒ³ãƒãƒ¼ãƒ»ã‚¿ã‚¤ãƒˆãƒ«ã‚’修正ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
- </text>
- <text name="role_properties_not_modifiable">
- 役割åã‚’é¸æŠžã™ã‚‹ã¨ï½¤èª¬æ˜Žã€ãƒ¡ãƒ³ãƒãƒ¼ã€èƒ½åŠ›ã‚’確èªã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
- </text>
- <text name="role_actions_modifiable">
- ã‚ãªãŸã¯å½¹å‰²ã«èƒ½åŠ›ã‚’割り当ã¦ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
- </text>
- <text name="role_actions_not_modifiable">
- 能力ã®è¡¨ç¤ºã¯ã§ãã¾ã™ãŒï½¤ä¿®æ­£ã‚„割り当ã¦ãªã©ã¯ã§ãã¾ã›ã‚“。
- </text>
- </panel>
- <panel name="actions_header">
- <text name="static">
- 能力
- </text>
- <text name="static2">
- 能力ã®èª¬æ˜Žã€ã©ã®å½¹å‰²ã¨ãƒ¡ãƒ³ãƒãƒ¼ãŒãã®èƒ½åŠ›ã‚’実行ã§ãã‚‹ã‹ã‚’
-表示ã§ãã¾ã™ã€‚
- </text>
- </panel>
+ <panel.string name="default_needs_apply_text">
+ ç¾åœ¨ã®ã‚¿ãƒ–ã«ã¯ã€ä¿å­˜ã•ã‚Œã¦ã„ãªã„変更ãŒã‚ã‚Šã¾ã™ã€‚
+ </panel.string>
+ <panel.string name="want_apply_text">
+ 変更をä¿å­˜ã—ã¾ã™ã‹ï¼Ÿ
+ </panel.string>
<tab_container name="roles_tab_container">
<panel label="メンãƒãƒ¼" name="members_sub_tab" tool_tip="メンãƒãƒ¼">
- <button label="検索" name="search_button"/>
- <button label="å…¨ã¦ã‚’表示" name="show_all_button"/>
- <name_list name="member_list">
- <column label="メンãƒãƒ¼å" name="name"/>
- <column label="寄付ã•ã‚ŒãŸTier" name="donated"/>
- <column label="最終ログイン" name="online"/>
- </name_list>
- <button label="æ–°ã—ã„メンãƒãƒ¼ã‚’招待" name="member_invite"/>
- <button label="グループã‹ã‚‰è¿½æ”¾" name="member_eject"/>
- <string name="help_text">
+ <panel.string name="help_text">
ã‚ãªãŸã¯ãƒ¡ãƒ³ãƒãƒ¼ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚ŒãŸå½¹å‰²ã‚’付加ã€å‰Šé™¤ã§ãã¾ã™ã€‚
Ctrl キーを押ã—ãªãŒã‚‰ãƒ¡ãƒ³ãƒãƒ¼åをクリックã™ã‚‹ã¨
複数ã®äººã‚’é¸æŠžã§ãã¾ã™ã€‚
- </string>
+ </panel.string>
+ <filter_editor label="メンãƒãƒ¼ã‚’é¸åˆ¥" name="filter_input"/>
+ <name_list name="member_list">
+ <name_list.columns label="メンãƒãƒ¼" name="name"/>
+ <name_list.columns label="寄付" name="donated"/>
+ <name_list.columns label="ステータス" name="online"/>
+ </name_list>
+ <button label="招待" name="member_invite"/>
+ <button label="追放" name="member_eject"/>
</panel>
<panel label="役割" name="roles_sub_tab">
- <button label="検索" name="search_button"/>
- <button label="ã™ã¹ã¦ã‚’表示" name="show_all_button"/>
+ <panel.string name="help_text">
+ 役割ã«ã¯ã€ã‚¿ã‚¤ãƒˆãƒ«ã¨è¨±å¯ã•ã‚ŒãŸèƒ½åŠ›ãŒ
+割り当ã¦ã‚‰ã‚Œã¦ã„ã¾ã™ã€‚ メンãƒãƒ¼ã¯
+1ã¤ä»¥ä¸Šã®å½¹å‰²ã‚’æŒã¤ã“ã¨ãŒã§ãã¾ã™ã€‚ グループã§ä½¿ãˆã‚‹å½¹å‰²ã¯10ã¤ã¾ã§ã§ã€
+「全員(Everyone)ã€ã¨ã€Œã‚ªãƒ¼ãƒŠãƒ¼ï¼ˆOwner)ã€ãŒãã‚Œã«å«ã¾ã‚Œã¦ã„ã¾ã™ã€‚
+ </panel.string>
+ <panel.string name="cant_delete_role">
+ 「全員(Everyone)ã€ã¨ã€Œã‚ªãƒ¼ãƒŠãƒ¼ï¼ˆOwner)ã€ã®å½¹å‰²ã¯å‰Šé™¤ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
+ </panel.string>
+ <panel.string name="power_folder_icon">
+ Inv_FolderClosed
+ </panel.string>
+ <panel.string name="power_all_have_icon">
+ Checkbox_On
+ </panel.string>
+ <panel.string name="power_partial_icon">
+ Checkbox_Off
+ </panel.string>
+ <filter_editor label="役割をé¸åˆ¥" name="filter_input"/>
<scroll_list name="role_list">
- <column label="役割å" name="name"/>
- <column label="肩書ã" name="title"/>
- <column label="メンãƒãƒ¼" name="members"/>
+ <scroll_list.columns label="役割" name="name"/>
+ <scroll_list.columns label="肩書ã" name="title"/>
+ <scroll_list.columns label="#" name="members"/>
</scroll_list>
- <button label="æ–°ã—ã„役割を作æˆ..." name="role_create"/>
+ <button label="æ–°ã—ã„役割" name="role_create"/>
<button label="役割を削除" name="role_delete"/>
- <string name="help_text">
- 役割ã«ã¯ã‚¿ã‚¤ãƒˆãƒ«ãŒã‚ã‚Šã€ãƒ¡ãƒ³ãƒãƒ¼ãŒè¡Œä½¿å¯èƒ½ãª
-能力ã®ãƒªã‚¹ãƒˆãŒå®šç¾©ã•ã‚Œã¾ã™ã€‚ メンãƒãƒ¼ã¯ã€
-1ã¤ã¾ãŸã¯è¤‡æ•°ã®å½¹å‰²ã«å±žã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ 1ã¤ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å¯¾ã—ã€
-「全員ã€ã¨ã€Œã‚ªãƒ¼ãƒŠãƒ¼ã€ã®å½¹å‰²ã‚’å«ã‚ã¦æœ€é«˜ã§10ã®å½¹å‰²ã‚’æŒãŸã›ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
- </string>
- <string name="cant_delete_role">
- 「全員ã€ã¨ã€Œã‚ªãƒ¼ãƒŠãƒ¼ã€ã¯ç‰¹åˆ¥ãªå½¹å‰²ãªã®ã§ã€å‰Šé™¤ã§ãã¾ã›ã‚“。
- </string>
</panel>
- <panel label="能力" name="actions_sub_tab">
- <button label="検索" name="search_button"/>
- <button label="ã™ã¹ã¦ã‚’表示" name="show_all_button"/>
- <scroll_list name="action_list" tool_tip="能力をé¸æŠžã—ã¦è©³ç´°ã‚’表示ã—ã¾ã™ã€‚">
- <column label="" name="icon"/>
- <column label="" name="action"/>
- </scroll_list>
- <string name="help_text">
+ <panel label="能力" name="actions_sub_tab" tool_tip="能力ã®èª¬æ˜Žæ–‡ã«ã¯ã€ã©ã®å½¹å‰²ãƒ»ãƒ¡ãƒ³ãƒãƒ¼ãŒãã®èƒ½åŠ›ã‚’æŒã¤ã‹ãŒæ›¸ã‹ã‚Œã¦ã„ã¾ã™ã€‚">
+ <panel.string name="help_text">
ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—内ã§å½¹å‰²ã‚’与ãˆã‚‰ã‚Œã¦ã„るメンãƒãƒ¼ãŒå®Ÿè¡Œã§ãã‚‹æ“作ã¯ã€
能力ã«ã‚ˆã£ã¦æ±ºã¾ã‚Šã¾ã™ã€‚ ã•ã¾ã–ã¾ãªèƒ½åŠ›ãŒç”¨æ„ã•ã‚Œã¦ã„ã¾ã™ã€‚
- </string>
+ </panel.string>
+ <filter_editor label="能力をé¸åˆ¥" name="filter_input"/>
+ <scroll_list name="action_list" tool_tip="詳細を見るã«ã¯ã€èƒ½åŠ›ã‚’é¸ã‚“ã§ãã ã•ã„。">
+ <scroll_list.columns label="" name="action"/>
+ </scroll_list>
</panel>
</tab_container>
<panel name="members_footer">
<text name="static">
割当られãŸå½¹å‰²
</text>
+ <scroll_list name="member_assigned_roles">
+ <scroll_list.columns label="" name="checkbox"/>
+ <scroll_list.columns label="" name="role"/>
+ </scroll_list>
<text name="static2">
許å¯ã•ã‚ŒãŸèƒ½åŠ›
</text>
- <scroll_list name="member_assigned_roles">
- <column label="" name="checkbox"/>
- <column label="" name="role"/>
- </scroll_list>
- <scroll_list name="member_allowed_actions" tool_tip="許å¯ã•ã‚ŒãŸèƒ½åŠ›ã®è©³ç´°ã¯ã€Œèƒ½åŠ›ã€ã‚¿ãƒ–ã‚’ã”覧ãã ã•ã„。">
- <column label="" name="icon"/>
- <column label="" name="action"/>
+ <scroll_list name="member_allowed_actions" tool_tip="å„能力ã®è©³ç´°ã¯ã€èƒ½åŠ›ã®ã‚¿ãƒ–ã‚’ã”覧ãã ã•ã„。">
+ <scroll_list.columns label="" name="action"/>
</scroll_list>
</panel>
<panel name="roles_footer">
<text name="static">
- åå‰
+ 役割å
</text>
+ <line_editor name="role_name"/>
+ <text name="static3">
+ 役割タイトル
+ </text>
+ <line_editor name="role_title"/>
<text name="static2">
説明
</text>
- <line_editor name="role_name">
- 従業員
- </line_editor>
- <text name="static3">
- 肩書ã
- </text>
- <line_editor name="role_title">
- (待機中)
- </line_editor>
- <text_editor name="role_description">
- (待機中)
- </text_editor>
+ <text_editor name="role_description"/>
<text name="static4">
割当られãŸãƒ¡ãƒ³ãƒãƒ¼
</text>
+ <check_box label="Reveal members" name="role_visible_in_list" tool_tip="グループ外ã®äººãŒä¸€èˆ¬ã‚¿ãƒ–を見ãŸã¨ãã«ã€ã“ã®å½¹å‰²ã®ãƒ¡ãƒ³ãƒãƒ¼ãŒè¡¨ç¤ºã•ã‚Œã‚‹ã‹ã©ã†ã‹ã‚’設定ã—ã¾ã™ã€‚"/>
<text name="static5" tool_tip="ç¾åœ¨é¸æŠžã•ã‚Œã¦ã„る役割ã§å®Ÿè¡Œã§ãる能力ã®ãƒªã‚¹ãƒˆ">
許å¯ã•ã‚ŒãŸèƒ½åŠ›
</text>
- <check_box label="メンãƒãƒ¼ãŒå…¬é–‹çŠ¶æ…‹" name="role_visible_in_list" tool_tip="ã“ã®å½¹å‰²ã®ãƒ¡ãƒ³ãƒãƒ¼ã‚’グループ外ã®äººã®ä¸€èˆ¬ã‚¿ãƒ–ã«è¡¨ç¤ºã™ã‚‹ã‹ã©ã†ã‹ã‚’設定ã—ã¾ã™ã€‚"/>
- <scroll_list name="role_allowed_actions" tool_tip="許å¯ã•ã‚ŒãŸèƒ½åŠ›ã®è©³ç´°ã¯ã€Œèƒ½åŠ›ã€ã‚¿ãƒ–ã‚’ã”覧ãã ã•ã„。">
- <column label="" name="icon"/>
- <column label="" name="checkbox"/>
- <column label="" name="action"/>
+ <scroll_list name="role_allowed_actions" tool_tip="å„能力ã®è©³ç´°ã¯ã€èƒ½åŠ›ã®ã‚¿ãƒ–ã‚’ã”覧ãã ã•ã„。">
+ <scroll_list.columns label="" name="checkbox"/>
+ <scroll_list.columns label="" name="action"/>
</scroll_list>
</panel>
<panel name="actions_footer">
- <text name="static">
- 説明
- </text>
<text_editor name="action_description">
ã“ã‚Œã¯ã€Œã‚°ãƒ«ãƒ¼ãƒ—ã‹ã‚‰ãƒ¡ãƒ³ãƒãƒ¼ã‚’追放ã™ã‚‹ã€èƒ½åŠ›ã§ã™ã€‚ オーナーを追放ã§ãã‚‹ã®ã¯ã€åˆ¥ã®ã‚ªãƒ¼ãƒŠãƒ¼ã ã‘ã§ã™ã€‚
</text_editor>
<text name="static2">
- 役割ã¨èƒ½åŠ›
+ ã“ã®èƒ½åŠ›ã‚’æŒã¤å½¹å‰²
</text>
<text name="static3">
- 能力ã®ã‚るメンãƒãƒ¼
+ ã“ã®èƒ½åŠ›ã‚’æŒã¤ãƒ¡ãƒ³ãƒãƒ¼
</text>
</panel>
</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_im_control_panel.xml b/indra/newview/skins/default/xui/ja/panel_im_control_panel.xml
new file mode 100644
index 0000000000..138a9c6360
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_im_control_panel.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_im_control_panel">
+ <text name="avatar_name" value="ä¸æ˜Ž"/>
+ <button label="プロフィール" name="view_profile_btn"/>
+ <button label="フレンド登録" name="add_friend_btn"/>
+ <button label="テレãƒãƒ¼ãƒˆ" name="teleport_btn"/>
+ <button label="共有" name="share_btn"/>
+ <panel name="panel_call_buttons">
+ <button label="コール" name="call_btn"/>
+ <button label="コール終了" name="end_call_btn"/>
+ <button label="ボイスコントロール" name="voice_ctrls_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_instant_message.xml b/indra/newview/skins/default/xui/ja/panel_instant_message.xml
new file mode 100644
index 0000000000..9fd0cb3b0d
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_instant_message.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="im_panel" name="im_panel">
+ <string name="message_max_lines_count">
+ 6
+ </string>
+ <panel label="im_header" name="im_header">
+ <text name="user_name" value="Erica Vader"/>
+ <text name="time_box" value="23:30"/>
+ </panel>
+ <button label="返信" name="reply"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_landmark_info.xml b/indra/newview/skins/default/xui/ja/panel_landmark_info.xml
new file mode 100644
index 0000000000..0f1e9b4962
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_landmark_info.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="landmark_info">
+ <string name="title_create_landmark" value="ランドマークを作æˆ"/>
+ <string name="title_edit_landmark" value="ランドマークを編集"/>
+ <string name="title_landmark" value="ランドマーク"/>
+ <string name="not_available" value="(該当ãªã—)"/>
+ <string name="unknown" value="(ä¸æ˜Žï¼‰"/>
+ <string name="public" value="(公開)"/>
+ <string name="server_update_text">
+ 場所ã®æƒ…å ±ã¯ã‚µãƒ¼ãƒãƒ¼ãŒã‚¢ãƒƒãƒ—デートã•ã‚Œã‚‹ã¾ã§ã”利用ã„ãŸã ã‘ã¾ã›ã‚“。
+ </string>
+ <string name="server_error_text">
+ ã“ã®ä½ç½®ã®æƒ…å ±ã¯ç¾åœ¨ã”利用ã„ãŸã ã‘ã¾ã›ã‚“。ã‚ã¨ã§ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。
+ </string>
+ <string name="server_forbidden_text">
+ ã“ã®ä½ç½®ã®æƒ…å ±ã¯ã€ã‚¢ã‚¯ã‚»ã‚¹åˆ¶é™ã®ãŸã‚ã”利用ã„ãŸã ã‘ã¾ã›ã‚“。 許å¯ã«ã¤ã„ã¦ã¯åŒºç”»æ‰€æœ‰è€…ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。
+ </string>
+ <string name="acquired_date">
+ [year,datetime,local] [mth,datetime,local] [day,datetime,local] [wkday,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local]
+ </string>
+ <string name="icon_PG" value="parcel_drk_PG"/>
+ <string name="icon_M" value="parcel_drk_M"/>
+ <string name="icon_R" value="parcel_drk_R"/>
+ <text name="title" value="場所ã®ãƒ—ロフィール"/>
+ <scroll_container name="place_scroll">
+ <panel name="scrolling_panel">
+ <text name="region_title" value="SampleRegion"/>
+ <text name="parcel_title" value="SampleParcel, Name Long (145, 228, 26)"/>
+ <expandable_text name="description" value="Du waltz die spritz"/>
+ <text name="maturity_value" value="ä¸æ˜Ž"/>
+ <panel name="landmark_info_panel">
+ <text name="owner_label" value="所有者:"/>
+ <text name="creator_label" value="制作者:"/>
+ <text name="created_label" value="制作日:"/>
+ </panel>
+ <panel name="landmark_edit_panel">
+ <text name="title_label" value="タイトル:"/>
+ <text name="notes_label" value="個人的メモ:"/>
+ <text name="folder_label" value="ランドマークã®ä½ç½®ï¼š"/>
+ </panel>
+ </panel>
+ </scroll_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_landmarks.xml b/indra/newview/skins/default/xui/ja/panel_landmarks.xml
new file mode 100644
index 0000000000..45767e8c50
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_landmarks.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="Landmarks">
+ <accordion name="landmarks_accordion">
+ <accordion_tab name="tab_favorites" title="ãŠæ°—ã«å…¥ã‚Šãƒãƒ¼"/>
+ <accordion_tab name="tab_landmarks" title="ランドマーク"/>
+ <accordion_tab name="tab_inventory" title="æŒã¡ç‰©"/>
+ <accordion_tab name="tab_library" title="ライブラリ"/>
+ </accordion>
+ <panel name="bottom_panel">
+ <button name="options_gear_btn" tool_tip="ãã®ä»–ã®ã‚ªãƒ—ションを表示"/>
+ <button name="add_btn" tool_tip="æ–°ã—ã„ランドマークを追加"/>
+ <dnd_button name="trash_btn" tool_tip="é¸æŠžã—ãŸãƒ©ãƒ³ãƒ‰ãƒžãƒ¼ã‚¯ã‚’削除"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_login.xml b/indra/newview/skins/default/xui/ja/panel_login.xml
index c93aeacc95..0c1505255e 100644
--- a/indra/newview/skins/default/xui/ja/panel_login.xml
+++ b/indra/newview/skins/default/xui/ja/panel_login.xml
@@ -1,51 +1,41 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="panel_login">
- <text name="first_name_text" left="20">
- ファーストãƒãƒ¼ãƒ ï¼š
- </text>
- <line_editor left="20" name="first_name_edit" width="126" />
- <text name="last_name_text" left="158">
- ラストãƒãƒ¼ãƒ ï¼š
- </text>
- <line_editor left="158" name="last_name_edit" width="126" />
- <text name="password_text">
- パスワード:
- </text>
- <text name="start_location_text" left="20" >
- ログインä½ç½®ï¼š
- </text>
- <combo_box name="start_location_combo" left_delta="92" width="172">
- <combo_item name="MyHome">
- 自宅(ホーム)
- </combo_item>
- <combo_item name="MyLastLocation">
- 最後ã«ãƒ­ã‚°ã‚¢ã‚¦ãƒˆã—ãŸå ´æ‰€
- </combo_item>
- <combo_item name="Typeregionname">
- &lt; 地域ã®åå‰å…¥åŠ› &gt;
- </combo_item>
- </combo_box>
- <check_box label="パスワードを記憶" name="remember_check" left_delta="180"/>
- <text name="full_screen_text">
- ログイン時ã«ã¯ãƒ•ãƒ«ã‚¹ã‚¯ãƒªãƒ¼ãƒ³è¡¨ç¤ºã«ãªã‚Šã¾ã™
- </text>
- <button label="æ–°è¦ã‚¢ã‚«ã‚¦ãƒ³ãƒˆ..." label_selected="æ–°è¦ã‚¢ã‚«ã‚¦ãƒ³ãƒˆ..." name="new_account_btn"/>
- <button label="環境設定..." label_selected="環境設定..." name="preferences_btn"/>
- <button label="ログイン" label_selected="ログイン" name="connect_btn"/>
- <button label="終了" label_selected="終了" name="quit_btn"/>
- <text name="version_text">
- 1.23.4 (5)
- </text>
- <text name="create_new_account_text">
- アカウントを申ã—込む
- </text>
- <text name="channel_text">
- [VERSION]
- </text>
- <text name="forgot_password_text" left="-230" width="220">
- åå‰ã¾ãŸã¯ãƒ‘スワードをãŠå¿˜ã‚Œã§ã™ã‹?
- </text>
- <text name="forgot_password_url">
- http://secondlife.com/account/request.php
- </text>
+ <panel.string name="create_account_url">
+ http://jp.secondlife.com/registration/
+ </panel.string>
+ <panel.string name="forgot_password_url">
+ http://secondlife.com/account/request.php?lang=ja
+ </panel.string>
+ <panel name="login_widgets">
+ <text name="first_name_text">
+ ファーストãƒãƒ¼ãƒ ï¼š
+ </text>
+ <line_editor name="first_name_edit" tool_tip="[SECOND_LIFE] ファーストãƒãƒ¼ãƒ "/>
+ <text name="last_name_text">
+ ラストãƒãƒ¼ãƒ ï¼š
+ </text>
+ <line_editor name="last_name_edit" tool_tip="[SECOND_LIFE] ラストãƒãƒ¼ãƒ "/>
+ <text name="password_text">
+ パスワード:
+ </text>
+ <button label="ログイン" label_selected="ログイン" name="connect_btn"/>
+ <text name="start_location_text">
+ ログインä½ç½®ï¼š
+ </text>
+ <combo_box name="start_location_combo">
+ <combo_box.item label="最後ã«ãƒ­ã‚°ã‚¢ã‚¦ãƒˆã—ãŸå ´æ‰€" name="MyLastLocation"/>
+ <combo_box.item label="自宅(ホーム)" name="MyHome"/>
+ <combo_box.item label="<地域åを入力>" name="Typeregionname"/>
+ </combo_box>
+ <check_box label="パスワードを記憶" name="remember_check"/>
+ <text name="create_new_account_text">
+ æ–°è¦ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’作æˆ
+ </text>
+ <text name="forgot_password_text">
+ åå‰ã¾ãŸã¯ãƒ‘スワードをãŠå¿˜ã‚Œã§ã™ã‹ï¼Ÿ
+ </text>
+ <text name="channel_text">
+ [VERSION]
+ </text>
+ </panel>
</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_main_inventory.xml b/indra/newview/skins/default/xui/ja/panel_main_inventory.xml
new file mode 100644
index 0000000000..8f8e113e64
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_main_inventory.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="ã‚‚ã®" name="main inventory panel">
+ <panel.string name="Title">
+ ã‚‚ã®
+ </panel.string>
+ <filter_editor label="フィルター" name="inventory search editor"/>
+ <tab_container name="inventory filter tabs">
+ <inventory_panel label="ã™ã¹ã¦" name="All Items"/>
+ <inventory_panel label="最近ã®å…¥æ‰‹ã‚¢ã‚¤ãƒ†ãƒ " name="Recent Items"/>
+ </tab_container>
+ <panel name="bottom_panel">
+ <button name="options_gear_btn" tool_tip="ãã®ä»–ã®ã‚ªãƒ—ションを表示"/>
+ <button name="add_btn" tool_tip="æ–°ã—ã„アイテムã®è¿½åŠ "/>
+ <dnd_button name="trash_btn" tool_tip="é¸æŠžã—ãŸã‚¢ã‚¤ãƒ†ãƒ ã‚’削除"/>
+ </panel>
+ <menu_bar name="Inventory Menu">
+ <menu label="ファイル" name="File">
+ <menu_item_call label="é–‹ã" name="Open"/>
+ <menu label="アップロード" name="upload">
+ <menu_item_call label="ç”»åƒ ï¼ˆL$ [COST] )..." name="Upload Image"/>
+ <menu_item_call label="サウンド (L$[COST] )..." name="Upload Sound"/>
+ <menu_item_call label="アニメーション (L$ [COST] )..." name="Upload Animation"/>
+ <menu_item_call label="一括 (ファイルã«ã¤ã L$[COST] )..." name="Bulk Upload"/>
+ </menu>
+ <menu_item_call label="æ–°ã—ã„ウィンドウ" name="New Window"/>
+ <menu_item_call label="フィルターを表示" name="Show Filters"/>
+ <menu_item_call label="フィルターをリセット" name="Reset Current"/>
+ <menu_item_call label="ã™ã¹ã¦ã®ãƒ•ã‚©ãƒ«ãƒ€ã‚’é–‰ã˜ã‚‹" name="Close All Folders"/>
+ <menu_item_call label="ã”ã¿ç®±ã‚’空ã«ã™ã‚‹" name="Empty Trash"/>
+ <menu_item_call label="紛失物を空ã«ã™ã‚‹" name="Empty Lost And Found"/>
+ </menu>
+ <menu label="æ–°è¦ä½œæˆ" name="Create">
+ <menu_item_call label="フォルダ" name="New Folder"/>
+ <menu_item_call label="スクリプト" name="New Script"/>
+ <menu_item_call label="ノート" name="New Note"/>
+ <menu_item_call label="ジェスãƒãƒ£ãƒ¼" name="New Gesture"/>
+ <menu label="衣類" name="New Clothes">
+ <menu_item_call label="シャツ" name="New Shirt"/>
+ <menu_item_call label="パンツ" name="New Pants"/>
+ <menu_item_call label="é´" name="New Shoes"/>
+ <menu_item_call label="é´ä¸‹" name="New Socks"/>
+ <menu_item_call label="ジャケット" name="New Jacket"/>
+ <menu_item_call label="シャツ" name="New Skirt"/>
+ <menu_item_call label="手袋" name="New Gloves"/>
+ <menu_item_call label="下ç€ï¼ˆä¸Šï¼‰" name="New Undershirt"/>
+ <menu_item_call label="下ç€ï¼ˆä¸‹ï¼‰" name="New Underpants"/>
+ <menu_item_call label="アルファ" name="New Alpha"/>
+ <menu_item_call label="タトゥ" name="New Tattoo"/>
+ </menu>
+ <menu label="身体部ä½" name="New Body Parts">
+ <menu_item_call label="シェイプ(体型)" name="New Shape"/>
+ <menu_item_call label="スキン" name="New Skin"/>
+ <menu_item_call label="髪" name="New Hair"/>
+ <menu_item_call label="ç›®" name="New Eyes"/>
+ </menu>
+ </menu>
+ <menu label="並ã¹æ›¿ãˆ" name="Sort">
+ <menu_item_check label="åå‰é †" name="By Name"/>
+ <menu_item_check label="日付順" name="By Date"/>
+ <menu_item_check label="フォルダを常ã«åå‰é †ã«ä¸¦ã¹ã‚‹" name="Folders Always By Name"/>
+ <menu_item_check label="システムフォルダを上ã«ä¸¦ã¹ã‚‹" name="System Folders To Top"/>
+ </menu>
+ </menu_bar>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_me.xml b/indra/newview/skins/default/xui/ja/panel_me.xml
new file mode 100644
index 0000000000..fe51d8507d
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_me.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="マイ プロフィール" name="panel_me">
+ <tab_container name="tabs">
+ <panel label="プロフィール" name="panel_profile"/>
+ <panel label="ピック" name="panel_picks"/>
+ </tab_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_media_settings_general.xml b/indra/newview/skins/default/xui/ja/panel_media_settings_general.xml
new file mode 100644
index 0000000000..18c270e43d
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_media_settings_general.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="一般" name="Media Settings General">
+ <text name="home_label">
+ ホーム URL:
+ </text>
+ <line_editor name="home_url" tool_tip="ã“ã®ãƒ¡ãƒ‡ã‚£ã‚¢ã‚½ãƒ¼ã‚¹ã® URL"/>
+ <text name="preview_label">
+ プレビュー
+ </text>
+ <text name="current_url_label">
+ ç¾åœ¨ã® URL:
+ </text>
+ <line_editor name="current_url" tool_tip="ç¾åœ¨ã®ãƒ¡ãƒ‡ã‚£ã‚¢ã‚½ãƒ¼ã‚¹ã® URL" value=""/>
+ <button label="リセット" name="current_url_reset_btn"/>
+ <text name="controls_label">
+ コントロール:
+ </text>
+ <combo_box name="controls">
+ <combo_item name="Standard">
+ 標準
+ </combo_item>
+ <combo_item name="Mini">
+ ミニ
+ </combo_item>
+ </combo_box>
+ <check_box initial_value="false" label="自動ループ" name="auto_loop"/>
+ <check_box initial_value="false" label="最åˆã®ã‚¯ãƒªãƒƒã‚¯" name="first_click_interact"/>
+ <check_box initial_value="false" label="自動ズーム" name="auto_zoom"/>
+ <check_box initial_value="false" label="自動メディアå†ç”Ÿ" name="auto_play"/>
+ <text name="media_setting_note">
+ 注: ä½äººã¯ã“ã®è¨­å®šã‚’無視ã§ãã¾ã™
+ </text>
+ <check_box initial_value="false" label="オブジェクトã®è¡¨é¢ã®ãƒ¡ãƒ‡ã‚£ã‚¢ã®è‡ªå‹•ã‚¹ã‚±ãƒ¼ãƒ«" name="auto_scale"/>
+ <text name="size_label">
+ サイズ:
+ </text>
+ <text name="X_label">
+ X
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_media_settings_permissions.xml b/indra/newview/skins/default/xui/ja/panel_media_settings_permissions.xml
new file mode 100644
index 0000000000..357cbe372a
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_media_settings_permissions.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="コントロール" name="Media settings for controls">
+ <check_box initial_value="false" label="ナビゲーションã¨ç›¸äº’作用力を無効ã«ã™ã‚‹" name="perms_owner_interact"/>
+ <check_box initial_value="false" label="コントロールãƒãƒ¼ã‚’éžè¡¨ç¤ºã«ã™ã‚‹" name="perms_owner_control"/>
+ <check_box initial_value="false" label="ナビゲーションã¨ç›¸äº’作用力を無効ã«ã™ã‚‹" name="perms_group_interact"/>
+ <check_box initial_value="false" label="コントロールãƒãƒ¼ã‚’éžè¡¨ç¤ºã«ã™ã‚‹" name="perms_group_control"/>
+ <check_box initial_value="false" label="ナビゲーションã¨ç›¸äº’作用力を無効ã«ã™ã‚‹" name="perms_anyone_interact"/>
+ <check_box initial_value="false" label="コントロールãƒãƒ¼ã‚’éžè¡¨ç¤ºã«ã™ã‚‹" name="perms_anyone_control"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_media_settings_security.xml b/indra/newview/skins/default/xui/ja/panel_media_settings_security.xml
new file mode 100644
index 0000000000..ed0ac0d417
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_media_settings_security.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="セキュリティ" name="Media Settings Security">
+ <check_box initial_value="false" label="指定ã—㟠URL ã«ã®ã¿ã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ï¼ˆæŽ¥é ­è¾žï¼‰" name="whitelist_enable"/>
+ <button label="追加" name="whitelist_add"/>
+ <button label="削除" name="whitelist_del"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_my_profile.xml b/indra/newview/skins/default/xui/ja/panel_my_profile.xml
new file mode 100644
index 0000000000..5f773a1378
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_my_profile.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="プロフィール" name="panel_profile">
+ <string name="CaptionTextAcctInfo">
+ [ACCTTYPE]
+[PAYMENTINFO] [AGEVERIFICATION]
+ </string>
+ <string name="no_partner_text" value="ãªã—"/>
+ <string name="RegisterDateFormat">
+ [REG_DATE] ([AGE])
+ </string>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <panel name="second_life_image_panel">
+ <icon label="" name="2nd_life_edit_icon" tool_tip="下ã®ã€Œãƒ—ロフィールã®ç·¨é›†ã€ãƒœã‚¿ãƒ³ã‚’押ã—ã¦ç”»åƒã‚’変更ã—ã¾ã™"/>
+ <text name="title_sl_descr_text" value="[SECOND_LIFE]:"/>
+ <expandable_text name="sl_description_edit">
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ <panel name="first_life_image_panel">
+ <icon label="" name="real_world_edit_icon" tool_tip="下ã®ã€Œãƒ—ロフィールã®ç·¨é›†ã€ãƒœã‚¿ãƒ³ã‚’押ã—ã¦ç”»åƒã‚’変更ã—ã¾ã™"/>
+ <text name="title_rw_descr_text" value="ç¾å®Ÿä¸–界:"/>
+ <expandable_text name="fl_description_edit">
+ Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ <text name="me_homepage_text">
+ Web サイト:
+ </text>
+ <text name="title_member_text" value="メンãƒãƒ¼ç™»éŒ²ï¼š"/>
+ <text name="register_date" value="05/31/1976"/>
+ <text name="title_acc_status_text" value="アカウントã®çŠ¶æ…‹ï¼š"/>
+ <text name="acc_status_text" value="ä½äººã€‚ 支払情報未登録。"/>
+ <text name="title_partner_text" value="パートナー:"/>
+ <panel name="partner_data_panel">
+ <text name="partner_text" value="[FIRST] [LAST]"/>
+ </panel>
+ <text name="title_groups_text" value="グループ:"/>
+ <expandable_text name="sl_groups">
+ Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ </scroll_container>
+ <panel name="profile_buttons_panel">
+ <button label="フレンド登録" name="add_friend"/>
+ <button label="IM" name="im"/>
+ <button label="コール" name="call"/>
+ <button label="地図" name="show_on_map_btn"/>
+ <button label="テレãƒãƒ¼ãƒˆ" name="teleport"/>
+ </panel>
+ <panel name="profile_me_buttons_panel">
+ <button label="プロフィールã®ç·¨é›†" name="edit_profile_btn"/>
+ <button label="容姿ã®ç·¨é›†" name="edit_appearance_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_navigation_bar.xml b/indra/newview/skins/default/xui/ja/panel_navigation_bar.xml
new file mode 100644
index 0000000000..ecfde1bfc6
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_navigation_bar.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="navigation_bar">
+ <panel name="navigation_panel">
+ <button name="back_btn" tool_tip="å‰ã®å ´æ‰€"/>
+ <button name="forward_btn" tool_tip="次ã®å ´æ‰€"/>
+ <button name="home_btn" tool_tip="「ホームã€ã«ãƒ†ãƒ¬ãƒãƒ¼ãƒˆ"/>
+ <location_input label="場所" name="location_combo"/>
+ <search_combo_box label="検索" name="search_combo_box" tool_tip="検索">
+ <combo_editor label="[SECOND_LIFE] を検索:" name="search_combo_editor"/>
+ </search_combo_box>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_nearby_chat.xml b/indra/newview/skins/default/xui/ja/panel_nearby_chat.xml
new file mode 100644
index 0000000000..c0549c8ae9
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_nearby_chat.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- All our XML is utf-8 encoded. -->
+<panel name="nearby_chat">
+ <panel name="chat_caption">
+ <text name="sender_name">
+ è¿‘ãã®ãƒãƒ£ãƒƒãƒˆ
+ </text>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/ja/panel_nearby_chat_bar.xml
new file mode 100644
index 0000000000..3dbabc62be
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_nearby_chat_bar.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="chat_bar">
+ <string name="min_width">
+ 192
+ </string>
+ <string name="max_width">
+ 320
+ </string>
+ <line_editor label="ã“ã“をクリックã—ã¦ãƒãƒ£ãƒƒãƒˆã‚’開始ã—ã¾ã™ã€‚" name="chat_box" tool_tip="Enter キーを押ã—ã¦ç™ºè¨€ã—ã€Ctrl + Enter キーã§å«ã³ã¾ã™ã€‚"/>
+ <button name="show_nearby_chat" tool_tip="è¿‘ãã®ãƒãƒ£ãƒƒãƒˆãƒ­ã‚°ã‚’表示・éžè¡¨ç¤º"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_notes.xml b/indra/newview/skins/default/xui/ja/panel_notes.xml
new file mode 100644
index 0000000000..5feee6e280
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_notes.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="メモã¨ãƒ—ライãƒã‚·ãƒ¼" name="panel_notes">
+ <layout_stack name="layout">
+ <panel name="notes_stack">
+ <scroll_container name="profile_scroll">
+ <panel name="profile_scroll_panel">
+ <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>
+ </scroll_container>
+ </panel>
+ <panel name="notes_buttons_panel">
+ <button label="追加" name="add_friend"/>
+ <button label="IM" name="im"/>
+ <button label="コール" name="call"/>
+ <button label="地図" name="show_on_map_btn"/>
+ <button label="テレãƒãƒ¼ãƒˆ" name="teleport"/>
+ </panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/ja/panel_outfits_inventory.xml
new file mode 100644
index 0000000000..9ce0156bd4
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_outfits_inventory.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="Outfits">
+ <accordion name="outfits_accordion">
+ <accordion_tab name="tab_outfits" title="アウトフィットãƒãƒ¼"/>
+ <accordion_tab name="tab_cof" title="ç¾åœ¨ã®ã‚¢ã‚¦ãƒˆãƒ•ã‚£ãƒƒãƒˆãƒãƒ¼"/>
+ </accordion>
+ <button label="&gt;" name="selector" tool_tip="アウトフィットã®ãƒ—ロパティを表示"/>
+ <panel name="bottom_panel">
+ <button name="options_gear_btn" tool_tip="ãã®ä»–ã®ã‚ªãƒ—ションを表示"/>
+ <button name="add_btn" tool_tip="æ–°ã—ã„アイテムã®è¿½åŠ "/>
+ <dnd_button name="trash_btn" tool_tip="é¸æŠžã—ãŸã‚¢ã‚¤ãƒ†ãƒ ã‚’削除"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_outfits_inventory_gear_default.xml b/indra/newview/skins/default/xui/ja/panel_outfits_inventory_gear_default.xml
new file mode 100644
index 0000000000..dfcd9d0932
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_outfits_inventory_gear_default.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_gear_default">
+ <menu_item_call label="æ–°ã—ã„アウトフィット" name="new"/>
+ <menu_item_call label="アウトフィットをç€ã‚‹" name="wear"/>
+ <menu_item_call label="アウトフィットを削除ã™ã‚‹" name="delete"/>
+</menu>
diff --git a/indra/newview/skins/default/xui/ja/panel_people.xml b/indra/newview/skins/default/xui/ja/panel_people.xml
new file mode 100644
index 0000000000..5dffbb33ea
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_people.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- Side tray panel -->
+<panel label="人" name="people_panel">
+ <string name="no_people" value="誰もã„ã¾ã›ã‚“"/>
+ <string name="no_one_near" value="è¿‘ãã«èª°ã‚‚ã„ã¾ã›ã‚“"/>
+ <string name="no_friends_online" value="オンラインã®ãƒ•ãƒ¬ãƒ³ãƒ‰ã¯ã„ã¾ã›ã‚“"/>
+ <string name="no_friends" value="フレンドã¯ã„ã¾ã›ã‚“"/>
+ <string name="no_groups" value="グループã¯ã‚ã‚Šã¾ã›ã‚“"/>
+ <string name="people_filter_label" value="人をフィルター"/>
+ <string name="groups_filter_label" value="グループをフィルター"/>
+ <filter_editor label="フィルター" name="filter_input"/>
+ <tab_container name="tabs">
+ <panel label="è¿‘ã" name="nearby_panel">
+ <panel label="bottom_panel" name="bottom_panel">
+ <button name="nearby_view_sort_btn" tool_tip="オプション"/>
+ <button name="add_friend_btn" tool_tip="é¸æŠžã—ãŸä½äººã‚’フレンドリストã«ç™»éŒ²"/>
+ </panel>
+ </panel>
+ <panel label="フレンド" name="friends_panel">
+ <accordion name="friends_accordion">
+ <accordion_tab name="tab_online" title="オンライン"/>
+ <accordion_tab name="tab_all" title="全員"/>
+ </accordion>
+ <panel label="bottom_panel" name="bottom_panel">
+ <button name="friends_viewsort_btn" tool_tip="オプション"/>
+ <button name="add_btn" tool_tip="フレンド登録を申ã—出る"/>
+ <button name="del_btn" tool_tip="é¸æŠžã—ãŸäººã‚’フレンドリストã‹ã‚‰å‰Šé™¤"/>
+ </panel>
+ </panel>
+ <panel label="グループ" name="groups_panel">
+ <panel label="bottom_panel" name="bottom_panel">
+ <button name="groups_viewsort_btn" tool_tip="オプション"/>
+ <button name="plus_btn" tool_tip="グループã«å‚加 / æ–°è¦ã‚°ãƒ«ãƒ¼ãƒ—を作æˆ"/>
+ <button name="activate_btn" tool_tip="é¸æŠžã—ãŸã‚°ãƒ«ãƒ¼ãƒ—をアクティベート"/>
+ </panel>
+ </panel>
+ <panel label="最新" name="recent_panel">
+ <panel label="bottom_panel" name="bottom_panel">
+ <button name="recent_viewsort_btn" tool_tip="オプション"/>
+ <button name="add_friend_btn" tool_tip="é¸æŠžã—ãŸä½äººã‚’フレンドリストã«ç™»éŒ²"/>
+ </panel>
+ </panel>
+ </tab_container>
+ <panel name="button_bar">
+ <button label="プロフィール" name="view_profile_btn" tool_tip="写真ã€ã‚°ãƒ«ãƒ¼ãƒ—ã€ãã®ä»–ä½äººæƒ…報を表示"/>
+ <button label="IM" name="im_btn" tool_tip="インスタントメッセージを開ã"/>
+ <button label="コール" name="call_btn" tool_tip="ã“ã®ä½äººã«ã‚³ãƒ¼ãƒ«ã™ã‚‹"/>
+ <button label="共有" name="share_btn"/>
+ <button label="テレãƒãƒ¼ãƒˆ" name="teleport_btn" tool_tip="テレãƒãƒ¼ãƒˆã‚’é€ã‚‹"/>
+ <button label="グループ情報" name="group_info_btn" tool_tip="グループ情報を表示"/>
+ <button label="グループãƒãƒ£ãƒƒãƒˆ" name="chat_btn" tool_tip="ãƒãƒ£ãƒƒãƒˆã‚’開始"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_pick_info.xml b/indra/newview/skins/default/xui/ja/panel_pick_info.xml
new file mode 100644
index 0000000000..30fd8d1adc
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_pick_info.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_pick_info">
+ <text name="title" value="ピックã®æƒ…å ±"/>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <text name="pick_name" value="[name]"/>
+ <text name="pick_location" value="[loading...]"/>
+ <text name="pick_desc" value="[description]"/>
+ </panel>
+ </scroll_container>
+ <panel name="buttons">
+ <button label="テレãƒãƒ¼ãƒˆ" name="teleport_btn"/>
+ <button label="地図" name="show_on_map_btn"/>
+ <button label="編集" name="edit_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_picks.xml b/indra/newview/skins/default/xui/ja/panel_picks.xml
new file mode 100644
index 0000000000..3d3b8bb3dc
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_picks.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="ピック" name="panel_picks">
+ <string name="no_picks" value="ピックãªã—"/>
+ <string name="no_classifieds" value="クラシファイド広告ãªã—"/>
+ <text name="empty_picks_panel_text">
+ ã“ã“ã«ã¯ãƒ”ック・クラシファイド広告ã¯ã‚ã‚Šã¾ã›ã‚“。
+ </text>
+ <accordion name="accordion">
+ <accordion_tab name="tab_picks" title="ピック"/>
+ <accordion_tab name="tab_classifieds" title="クラシファイド広告"/>
+ </accordion>
+ <panel label="bottom_panel" name="edit_panel">
+ <button name="new_btn" tool_tip="ç¾åœ¨åœ°ã®ãƒ”ックを新è¦ä½œæˆ"/>
+ </panel>
+ <panel name="buttons_cucks">
+ <button label="情報" name="info_btn"/>
+ <button label="テレãƒãƒ¼ãƒˆ" name="teleport_btn"/>
+ <button label="地図" name="show_on_map_btn"/>
+ <button label="â–¼" name="overflow_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_place_profile.xml b/indra/newview/skins/default/xui/ja/panel_place_profile.xml
new file mode 100644
index 0000000000..3ec5a3a294
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_place_profile.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="place_profile">
+ <string name="on" value="オン"/>
+ <string name="off" value="オフ"/>
+ <string name="anyone" value="全員"/>
+ <string name="available" value="利用å¯"/>
+ <string name="allocated" value="割り当ã¦æ¸ˆ"/>
+ <string name="title_place" value="場所ã®ãƒ—ロフィール"/>
+ <string name="title_teleport_history" value="テレãƒãƒ¼ãƒˆå±¥æ­´ã®å ´æ‰€"/>
+ <string name="not_available" value="(該当ãªã—)"/>
+ <string name="unknown" value="(ä¸æ˜Žï¼‰"/>
+ <string name="public" value="(公開)"/>
+ <string name="none_text" value="(ãªã—)"/>
+ <string name="sale_pending_text" value="(販売処ç†ä¸­ï¼‰"/>
+ <string name="group_owned_text" value="(グループ所有)"/>
+ <string name="price_text" value="L$"/>
+ <string name="area_text" value="平方メートル"/>
+ <string name="all_residents_text" value="ã™ã¹ã¦ã®ä½äºº"/>
+ <string name="group_text" value="グループ"/>
+ <string name="can_resell">
+ ã“ã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã§è³¼å…¥ã—ãŸåœŸåœ°ã¯ã€å†è²©ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+ </string>
+ <string name="can_not_resell">
+ ã“ã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã§è³¼å…¥ã—ãŸåœŸåœ°ã¯ã€å†è²©ã§ãã¾ã›ã‚“。
+ </string>
+ <string name="can_change">
+ ã“ã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã§è³¼å…¥ã—ãŸåœŸåœ°ã¯ã€çµ±åˆãƒ»åˆ†å‰²ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+ </string>
+ <string name="can_not_change">
+ ã“ã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã§è³¼å…¥ã—ãŸåœŸåœ°ã¯ã€çµ±åˆãƒ»åˆ†å‰²ã§ãã¾ã›ã‚“。
+ </string>
+ <string name="server_update_text">
+ 場所ã®æƒ…å ±ã¯ã€ã‚µãƒ¼ãƒãƒ¼ãŒã‚¢ãƒƒãƒ—デートã•ã‚Œã‚‹ã¾ã§ã”利用ã„ãŸã ã‘ã¾ã›ã‚“。
+ </string>
+ <string name="server_error_text">
+ ã“ã®å ´æ‰€ã®æƒ…å ±ã¯ç¾åœ¨ã”利用ã„ãŸã ã‘ã¾ã›ã‚“。ã‚ã¨ã§ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。
+ </string>
+ <string name="server_forbidden_text">
+ ã“ã®å ´æ‰€ã®æƒ…å ±ã¯ã€ã‚¢ã‚¯ã‚»ã‚¹åˆ¶é™ã®ãŸã‚ã”利用ã„ãŸã ã‘ã¾ã›ã‚“。 許å¯ã«ã¤ã„ã¦ã¯åŒºç”»æ‰€æœ‰è€…ã«ãŠå•ã„åˆã‚ã›ãã ã•ã„。
+ </string>
+ <string name="acquired_date">
+ [year,datetime,local] [mth,datetime,local] [day,datetime,local] [wkday,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local]
+ </string>
+ <string name="icon_PG" value="parcel_drk_PG"/>
+ <string name="icon_M" value="parcel_drk_M"/>
+ <string name="icon_R" value="parcel_drk_R"/>
+ <string name="icon_Voice" value="parcel_drk_Voice"/>
+ <string name="icon_VoiceNo" value="parcel_drk_VoiceNo"/>
+ <string name="icon_Fly" value="parcel_drk_Fly"/>
+ <string name="icon_FlyNo" value="parcel_drk_FlyNo"/>
+ <string name="icon_Push" value="parcel_drk_Push"/>
+ <string name="icon_PushNo" value="parcel_drk_PushNo"/>
+ <string name="icon_Build" value="parcel_drk_Build"/>
+ <string name="icon_BuildNo" value="parcel_drk_BuildNo"/>
+ <string name="icon_Scripts" value="parcel_drk_Scripts"/>
+ <string name="icon_ScriptsNo" value="parcel_drk_ScriptsNo"/>
+ <string name="icon_Damage" value="parcel_drk_Damage"/>
+ <string name="icon_DamageNo" value="parcel_drk_DamageNo"/>
+ <text name="title" value="場所ã®ãƒ—ロフィール"/>
+ <scroll_container name="place_scroll">
+ <panel name="scrolling_panel">
+ <text name="region_title" value="SampleRegion"/>
+ <text name="parcel_title" value="SampleParcel, Name Long (145, 228, 26)"/>
+ <expandable_text name="description" value="Du waltz die spritz"/>
+ <text name="owner_label" value="所有者:"/>
+ <text name="owner_value" value="Alex Superduperlongenamenton"/>
+ <text name="maturity_value" value="ä¸æ˜Ž"/>
+ <accordion name="advanced_info_accordion">
+ <accordion_tab name="parcel_characteristics_tab" title="区画">
+ <panel>
+ <text name="rating_label" value="レーティング区分:"/>
+ <text name="rating_value" value="ä¸æ˜Ž"/>
+ <text name="voice_label" value="ボイス:"/>
+ <text name="voice_value" value="オン"/>
+ <text name="fly_label" value="飛行:"/>
+ <text name="fly_value" value="オン"/>
+ <text name="push_label" value="プッシュ:"/>
+ <text name="push_value" value="オフ"/>
+ <text name="build_label" value="制作:"/>
+ <text name="build_value" value="オン"/>
+ <text name="scripts_label" value="スクリプト:"/>
+ <text name="scripts_value" value="オン"/>
+ <text name="damage_label" value="ダメージ:"/>
+ <text name="damage_value" value="オフ"/>
+ <button label="土地情報" name="about_land_btn"/>
+ </panel>
+ </accordion_tab>
+ <accordion_tab name="region_information_tab" title="リージョン">
+ <panel>
+ <text name="region_name_label" value="リージョン:"/>
+ <text name="region_name" value="Mooseland"/>
+ <text name="region_type_label" value="種類:"/>
+ <text name="region_type" value="Moose"/>
+ <text name="region_rating_label" value="レーティング区分:"/>
+ <text name="region_rating" value="Explicit"/>
+ <text name="region_owner_label" value="所有者:"/>
+ <text name="region_owner" value="moose Van Moose"/>
+ <text name="region_group_label" value="グループ:"/>
+ <text name="region_group">
+ The Mighty Moose of mooseville soundvillemoose
+ </text>
+ <button label="地域 / ä¸å‹•ç”£" name="region_info_btn"/>
+ </panel>
+ </accordion_tab>
+ <accordion_tab name="estate_information_tab" title="エステート(ä¸å‹•ç”£ï¼‰">
+ <panel>
+ <text name="estate_name_label" value="エステート(ä¸å‹•ç”£ï¼‰ï¼š"/>
+ <text name="estate_rating_label" value="レーティング区分:"/>
+ <text name="estate_owner_label" value="所有者:"/>
+ <text name="covenant_label" value="約款:"/>
+ </panel>
+ </accordion_tab>
+ <accordion_tab name="sales_tab" title="販売中">
+ <panel>
+ <text name="sales_price_label" value="価格:"/>
+ <text name="area_label" value="é¢ç©ï¼š"/>
+ <text name="traffic_label" value="トラフィック:"/>
+ <text name="primitives_label" value="プリム:"/>
+ <text name="parcel_scripts_label" value="スクリプト:"/>
+ <text name="terraform_limits_label" value="地形編集制é™ï¼š"/>
+ <text name="subdivide_label" value="分割・統åˆè¨±å¯ï¼š"/>
+ <text name="resale_label" value="å†ç‰ˆè¨±å¯ï¼š"/>
+ <text name="sale_to_label" value="販売先:"/>
+ </panel>
+ </accordion_tab>
+ </accordion>
+ </panel>
+ </scroll_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_places.xml b/indra/newview/skins/default/xui/ja/panel_places.xml
new file mode 100644
index 0000000000..f74b1e52e8
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_places.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="場所" name="places panel">
+ <string name="landmarks_tab_title" value="マイ ランドマーク"/>
+ <string name="teleport_history_tab_title" value="テレãƒãƒ¼ãƒˆã®å±¥æ­´"/>
+ <filter_editor label="フィルター" name="Filter"/>
+ <panel name="button_panel">
+ <button label="テレãƒãƒ¼ãƒˆ" name="teleport_btn"/>
+ <button label="地図" name="map_btn"/>
+ <button label="編集" name="edit_btn"/>
+ <button label="é–‰ã˜ã‚‹" name="close_btn"/>
+ <button label="キャンセル" name="cancel_btn"/>
+ <button label="ä¿å­˜" name="save_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/ja/panel_preferences_advanced.xml
new file mode 100644
index 0000000000..d444cccd2d
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_advanced.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<panel name="advanced">
+ <panel.string name="resolution_format">
+ [RES_X] x [RES_Y]
+ </panel.string>
+ <panel.string name="aspect_ratio_text">
+ [NUM]:[DEN]
+ </panel.string>
+ <check_box label="å¹ã出ã—ãƒãƒ£ãƒƒãƒˆ" name="bubble_text_chat"/>
+ <color_swatch name="background" tool_tip="å¹ã出ã—ãƒãƒ£ãƒƒãƒˆã®è‰²ã‚’é¸æŠžã—ã¾ã™"/>
+ <slider label="é€æ˜Žåº¦" name="bubble_chat_opacity"/>
+ <text name="AspectRatioLabel1" tool_tip="(幅/高ã•ï¼‰">
+ 縦横比
+ </text>
+ <combo_box name="aspect_ratio" tool_tip="(幅/高ã•ï¼‰">
+ <combo_box.item label="4:3(標準CRT)" name="item1"/>
+ <combo_box.item label="5:4(1280x1024 LCD)" name="item2"/>
+ <combo_box.item label="8:5(ワイドスクリï¼ãƒ³ï¼‰" name="item3"/>
+ <combo_box.item label="16:9(ワイドスクリï¼ãƒ³ï¼‰" name="item4"/>
+ </combo_box>
+ <check_box label="自動検出" name="aspect_auto_detect"/>
+ <text name="heading1">
+ カメラ:
+ </text>
+ <slider label="視界角" name="camera_fov"/>
+ <slider label="è·é›¢" name="camera_offset_scale"/>
+ <text name="heading2">
+ 自動ãƒã‚¸ã‚·ãƒ§ãƒ³ï¼š
+ </text>
+ <check_box label="制作・編集" name="edit_camera_movement" tool_tip="編集モードã®ã‚ªãƒ³ãƒ»ã‚ªãƒ•ã®åˆ‡ã‚Šæ›¿ãˆã«ã€è‡ªå‹•ã‚«ãƒ¡ãƒ©ãƒã‚¸ã‚·ãƒ§ãƒ³ã‚’使ã„ã¾ã™"/>
+ <check_box label="容姿" name="appearance_camera_movement" tool_tip="編集モードã«å…¥ã£ãŸã¨ãã«ã€è‡ªå‹•ã‚«ãƒ¡ãƒ©ãƒã‚¸ã‚·ãƒ§ãƒ³ã‚’使ã„ã¾ã™"/>
+ <text name="heading3">
+ ã‚¢ãƒã‚¿ãƒ¼ï¼š
+ </text>
+ <check_box label="一人称視点ã§è¡¨ç¤ºã™ã‚‹" name="first_person_avatar_visible"/>
+ <check_box label="常ã«ã‚­ãƒ¼æ“作ã§å‹•ãよã†ã«ã™ã‚‹" name="arrow_keys_move_avatar_check"/>
+ <check_box label="上矢å°ã‚­ãƒ¼2度押ã—+長押ã—ã§èµ°ã‚‹" name="tap_tap_hold_to_run"/>
+ <check_box label="話ã™ã¨ãã«ã‚¢ãƒã‚¿ãƒ¼ã®å£ã‚’å‹•ã‹ã™" name="enable_lip_sync"/>
+ <check_box label="スクリプトã®ã‚¨ãƒ©ãƒ¼ã‚’表示ã™ã‚‹" name="show_script_errors"/>
+ <radio_group name="show_location">
+ <radio_item label="ãƒãƒ£ãƒƒãƒˆ" name="0"/>
+ <radio_item label="ウィンドウ" name="1"/>
+ </radio_group>
+ <check_box label="トリガーキーを押ã—ãŸã¨ãã«ã€ãƒžã‚¤ã‚¯ã‚’切り替ãˆã‚‹ï¼š" name="push_to_talk_toggle_check" tool_tip="トグルモードã®æ™‚ã«ãƒˆãƒªã‚¬ãƒ¼ã‚­ãƒ¼ã‚’1度押ã—ã¦æ”¾ã™ã¨ã€ãƒžã‚¤ã‚¯ã®ã‚ªãƒ³ãƒ»ã‚ªãƒ•è¨­å®šã‚’切り替ãˆã¾ã™ã€‚ トグルモードã§ã¯ãªã„ã¨ãã¯ã€ãƒˆãƒªã‚¬ãƒ¼ã‚­ãƒ¼ã‚’押ã—ãŸçŠ¶æ…‹ã®æ™‚ã®ã¿ã‚ãªãŸã®å£°ãŒç›¸æ‰‹ã«èžã“ãˆã¾ã™ã€‚"/>
+ <line_editor label="プッシュ・トゥ・スピークã®ãƒˆãƒªã‚¬ãƒ¼" name="modifier_combo"/>
+ <button label="キー設定" name="set_voice_hotkey_button"/>
+ <button label="マウスã®ä¸­å¤®ãƒœã‚¿ãƒ³" name="set_voice_middlemouse_button"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_preferences_alerts.xml b/indra/newview/skins/default/xui/ja/panel_preferences_alerts.xml
new file mode 100644
index 0000000000..3cd13948d2
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_alerts.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="ãƒãƒƒãƒ—アップ" name="popups" title="ãƒãƒƒãƒ—アップ">
+ <text name="tell_me_label">
+ 知らã›ã‚‹ï¼š
+ </text>
+ <check_box label="リンデンドルを使用・å—ã‘å–ã‚‹ã¨ã" name="notify_money_change_checkbox"/>
+ <check_box label="フレンドãŒãƒ­ã‚°ã‚¢ã‚¦ãƒˆãƒ»ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹ã¨ã" name="friends_online_notify_checkbox"/>
+ <text name="show_label" width="300">
+ 常ã«è¡¨ç¤ºã™ã‚‹è­¦å‘Šãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ï¼š
+ </text>
+ <text name="dont_show_label">
+ 表示ã—ãªã„警告メッセージ:
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_preferences_chat.xml b/indra/newview/skins/default/xui/ja/panel_preferences_chat.xml
index cc2421c9e9..7abeb36168 100644
--- a/indra/newview/skins/default/xui/ja/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_chat.xml
@@ -1,58 +1,43 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="ãƒãƒ£ãƒƒãƒˆ" name="chat">
- <text length="1" name="text_box" type="string">
- ãƒãƒ£ãƒƒãƒˆã®ãƒ•ã‚©ãƒ³ãƒˆï¼š
- </text>
<radio_group name="chat_font_size">
- <radio_item length="1" name="radio" type="string">
- å°
- </radio_item>
- <radio_item length="1" name="radio2" type="string">
- 中
- </radio_item>
- <radio_item length="1" name="radio3" type="string">
- 大
- </radio_item>
+ <radio_item label="å°" name="radio"/>
+ <radio_item label="中" name="radio2"/>
+ <radio_item label="大" name="radio3"/>
</radio_group>
- <text length="1" name="text_box2" type="string">
- ãƒãƒ£ãƒƒãƒˆãƒ»ã‚«ãƒ©ãƒ¼ï¼š
+ <color_swatch label="自分" name="user"/>
+ <text name="text_box1">
+ ミー
+ </text>
+ <color_swatch label="ãã®ä»–" name="agent"/>
+ <text name="text_box2">
+ ãã®ä»–
</text>
- <color_swatch label="自分" name="user" width="56"/>
- <color_swatch label="ãã®ä»–" name="agent" left_delta="60"/>
<color_swatch label="IM" name="im"/>
+ <text name="text_box3">
+ IM
+ </text>
<color_swatch label="システム" name="system"/>
- <color_swatch label="ãƒãƒ£ãƒƒãƒˆ" name="users"/>
- <color_swatch label="オブジェクト" name="objects" width="56"/>
- <color_swatch label="所有者" name="owner" left_delta="60"/>
- <color_swatch label="å¹å‡ºã—" name="background"/>
- <color_swatch label="URL" name="links"/>
- <text length="1" name="text_box3" type="string">
- ãƒãƒ£ãƒƒãƒˆãƒ»ã‚³ãƒ³ã‚½ãƒ¼ãƒ«ï¼š
- </text>
- <spinner label="フェード" name="fade_chat_time"/>
- <text length="1" name="text_box4" type="string">
- (秒後)
- </text>
- <text length="1" name="text_box5" type="string">
- (行数)
- </text>
- <slider label="ä¸é€æ˜Žåº¦" name="console_opacity"/>
- <text length="1" name="text_box6" type="string">
- ãƒãƒ£ãƒƒãƒˆãƒ»ã‚ªãƒ—ション:
- </text>
- <check_box label="全画é¢å¹…を使用 (å†èµ·å‹•ãŒå¿…è¦)" name="chat_full_width_check"/>
- <check_box label="Enterキーを押ã—ãŸå¾Œãƒãƒ£ãƒƒãƒˆ ãƒãƒ¼ã‚’é–‰ã˜ã‚‹" name="close_chat_on_return_check"/>
- <check_box label="ãƒãƒ£ãƒƒãƒˆä¸­ã¯ã€ã„ã¤ã§ã‚‚矢å°ã‚­ãƒ¼ã§ã‚¢ãƒã‚¿ãƒ¼ã‚’移動å¯èƒ½" name="arrow_keys_move_avatar_check"/>
- <check_box label="ローカルãƒãƒ£ãƒƒãƒˆã«ã‚¿ã‚¤ãƒ ã‚¹ã‚¿ãƒ³ãƒ—を表示" name="show_timestamps_check"/>
- <check_box label="ãƒãƒ£ãƒƒãƒˆä¸­ã¯ã‚¿ã‚¤ãƒ”ング動作ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’å†ç”Ÿ" name="play_typing_animation"/>
- <text length="1" name="text_box7" type="string">
- ãƒãƒ£ãƒƒãƒˆã®å¹ã出ã—:
- </text>
- <check_box label="ãƒãƒ£ãƒƒãƒˆã®å¹ã出ã—を表示" name="bubble_text_chat"/>
- <slider label="ä¸é€æ˜Žåº¦" name="bubble_chat_opacity"/>
- <text length="1" name="text_box8" type="string">
- スクリプト・エラー:
- </text>
- <check_box label="スクリプト・エラーã¨è­¦å‘Šã‚’ãƒãƒ£ãƒƒãƒˆåŒæ§˜ã«è¡¨ç¤º" name="script_errors_as_chat"/>
+ <text name="text_box4">
+ システム
+ </text>
<color_swatch label="エラー" name="script_error"/>
+ <text name="text_box5">
+ エラー
+ </text>
+ <color_swatch label="オブジェクト" name="objects"/>
+ <text name="text_box6">
+ オブジェクト
+ </text>
+ <color_swatch label="所有者" name="owner"/>
+ <text name="text_box7">
+ 所有者
+ </text>
+ <color_swatch label="URL" name="links"/>
+ <text name="text_box9">
+ URL
+ </text>
+ <check_box initial_value="true" label="ãƒãƒ£ãƒƒãƒˆä¸­ã¯ã‚¿ã‚¤ãƒ”ング動作ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’å†ç”Ÿ" name="play_typing_animation"/>
+ <check_box label="オフライン時ã«å—ã‘å–ã£ãŸ IM をメールã§é€ä¿¡" name="send_im_to_email"/>
+ <check_box label="文字ãƒãƒ£ãƒƒãƒˆã®å±¥æ­´ã‚’有効ã«ã™ã‚‹" name="plain_text_chat_history"/>
</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_preferences_general.xml b/indra/newview/skins/default/xui/ja/panel_preferences_general.xml
index 83b21b87d2..387558af73 100644
--- a/indra/newview/skins/default/xui/ja/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_general.xml
@@ -1,146 +1,68 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="一般" name="general_panel">
- <radio_group name="default_start_location">
- <radio_item name="MyHome" tool_tip="常ã«è‡ªå®…(ホーム)ã«ãƒ­ã‚°ã‚¤ãƒ³">
- 自宅(ホーム)
- </radio_item>
- <radio_item name="MyLastLocation" tool_tip="常ã«æœ€å¾Œã«ã„ãŸå ´æ‰€ã«ãƒ­ã‚°ã‚¤ãƒ³">
- 最後ã«ãƒ­ã‚°ã‚¢ã‚¦ãƒˆã—ãŸå ´æ‰€
- </radio_item>
- </radio_group>
- <check_box label="ログイン画é¢ã«ãƒ­ã‚°ã‚¤ãƒ³ä½ç½®ã‚’表示" name="show_location_checkbox"/>
- <combo_box name="fade_out_combobox">
- <combo_item name="Never">
- ãªã—
- </combo_item>
- <combo_item name="Show Temporarily">
- 一時的ã«è¡¨ç¤º
- </combo_item>
- <combo_item name="Always">
- ã„ã¤ã‚‚
- </combo_item>
- </combo_box>
- <check_box label="å°ã•ãªã‚¢ãƒã‚¿ãƒ¼å" name="small_avatar_names_checkbox"/>
- <check_box label="ç”»é¢ä¸Šã§è‡ªåˆ†ã®åå‰ã‚’éš ã™" name="show_my_name_checkbox"/>
- <text name="group_titles_textbox">
- グループ・タイトル:
- </text>
- <check_box label="グループ・タイトルをã™ã¹ã¦éžè¡¨ç¤º" name="show_all_title_checkbox"/>
- <check_box label="ç”»é¢ä¸Šã§è‡ªåˆ†ã®ã‚°ãƒ«ãƒ¼ãƒ—・タイトルを隠ã™" name="show_my_title_checkbox"/>
- <color_swatch label="" name="effect_color_swatch" tool_tip="カラー・ピッカーをクリックã—ã¦é–‹ã"/>
- <text name="UI Size:">
- UI サイズ:
+ <text name="language_textbox">
+ 言語:
</text>
- <check_box label="解åƒåº¦ç‹¬ç«‹ã‚¹ã‚±ãƒ¼ãƒ«ã‚’使用" name="ui_auto_scale"/>
- <spinner label="退席ã¾ã§ã®æ™‚間:" name="afk_timeout_spinner"/>
- <check_box label="リンデン・ドル(L$)ã®æ”¯æ‰•ã„/å—ã‘å–りを通知" name="notify_money_change_checkbox"/>
- <text name="maturity_desired_label">
- レーティング区分:
+ <combo_box name="language_combobox">
+ <combo_box.item label="システムデフォルト" name="System Default Language"/>
+ <combo_box.item label="English (英語)" name="English"/>
+ <combo_box.item label="Dansk (デンマーク語) – ベータ" name="Danish"/>
+ <combo_box.item label="Deutsch (ドイツ語) – ベータ" name="Deutsch(German)"/>
+ <combo_box.item label="Español (スペイン語) – ベータ" name="Spanish"/>
+ <combo_box.item label="Français (フランス語) – ベータ" name="French"/>
+ <combo_box.item label="Italiano (イタリア語) - ベータ" name="Italian"/>
+ <combo_box.item label="Nederlands (オランダ語) - ベータ" name="Dutch"/>
+ <combo_box.item label="Polski (ãƒãƒ¼ãƒ©ãƒ³ãƒ‰èªžï¼‰ - ベータ" name="Polish"/>
+ <combo_box.item label="Português (ãƒãƒ«ãƒˆã‚¬ãƒ«èªžï¼‰ – ベータ" name="Portugese"/>
+ <combo_box.item label="日本語 – ベータ" name="(Japanese)"/>
+ <combo_box.item label="テスト言語" name="TestLanguage"/>
+ </combo_box>
+ <text name="language_textbox2">
+ (å†èµ·å‹•å¾Œã«å映)
</text>
<text name="maturity_desired_prompt">
アクセスã—ãŸã„コンテンツ:
</text>
+ <text name="maturity_desired_textbox"/>
<combo_box name="maturity_desired_combobox">
- <combo_item name="Desired_Adult">
- PGã€Mature〠Adult
- </combo_item>
- <combo_item name="Desired_Mature">
- PGã¨Mature
- </combo_item>
- <combo_item name="Desired_PG">
- PGé™å®š
- </combo_item>
+ <combo_box.item label="PGã€Matureã€Adult" name="Desired_Adult"/>
+ <combo_box.item label="PGã¨Mature" name="Desired_Mature"/>
+ <combo_box.item label="PG" name="Desired_PG"/>
</combo_box>
- <text name="maturity_desired_textbox">
- PGé™å®š
- </text>
- <text length="1" name="start_location_textbox" type="string">
+ <text name="start_location_textbox">
ログインä½ç½®ï¼š
</text>
- <text length="1" name="show_names_textbox" type="string">
- åå‰ã‚’表示:
- </text>
- <text length="1" name="effects_color_textbox" type="string">
- 自分ã®åŠ¹æžœã®è‰²ï¼š
+ <combo_box name="start_location_combo">
+ <combo_box.item label="最後ã«ãƒ­ã‚°ã‚¢ã‚¦ãƒˆã—ãŸå ´æ‰€" name="MyLastLocation" tool_tip="常ã«æœ€å¾Œã«ã„ãŸå ´æ‰€ã«ãƒ­ã‚°ã‚¤ãƒ³"/>
+ <combo_box.item label="自宅(ホーム)" name="MyHome" tool_tip="常ã«è‡ªå®…(ホーム)ã«ãƒ­ã‚°ã‚¤ãƒ³"/>
+ </combo_box>
+ <check_box initial_value="true" label="ログイン画é¢ã«è¡¨ç¤ºã™ã‚‹" name="show_location_checkbox"/>
+ <text name="name_tags_textbox">
+ åå‰ã®è¡¨ç¤ºï¼š
</text>
- <text length="1" name="seconds_textbox" type="string">
- 秒
+ <radio_group name="Name_Tag_Preference">
+ <radio_item label="オフ" name="radio"/>
+ <radio_item label="オン" name="radio2"/>
+ <radio_item label="一時的ã«è¡¨ç¤º" name="radio3"/>
+ </radio_group>
+ <check_box label="ç§ã®åå‰ã‚’表示" name="show_my_name_checkbox1"/>
+ <check_box initial_value="true" label="å°ã•ã„ã‚¢ãƒã‚¿ãƒ¼å" name="small_avatar_names_checkbox"/>
+ <check_box label="グループタイトルを表示" name="show_all_title_checkbox1"/>
+ <text name="effects_color_textbox">
+ ç§ã®ãƒ“ームã®è‰²ï¼š
</text>
- <text length="1" name="crash_report_textbox" type="string">
- クラッシュ報告:
+ <color_swatch label="" name="effect_color_swatch" tool_tip="カラー・ピッカーをクリックã—ã¦é–‹ã"/>
+ <text name="title_afk_text">
+ 一時退席ã¾ã§ã®æ™‚間:
</text>
- <text length="1" name="language_textbox" type="string">
- 言語:
+ <spinner label="" name="afk_timeout_spinner"/>
+ <text name="seconds_textbox">
+ 秒
</text>
- <text length="1" name="language_textbox2" type="string">
- (å†èµ·å‹•ã«ã¦å映)
+ <text name="text_box3">
+ å–ã‚Šè¾¼ã¿ä¸­ãƒ¢ãƒ¼ãƒ‰æ™‚ã®è¿”事:
</text>
- <string name="region_name_prompt">
- &lt;地域ã®åå‰å…¥åŠ›&gt;
- </string>
- <combo_box name="crash_behavior_combobox">
- <combo_item length="1" name="Askbeforesending" type="string">
- é€ã‚‹å‰ã«ç¢ºèªã™ã‚‹
- </combo_item>
- <combo_item length="1" name="Alwayssend" type="string">
- 常ã«é€ä¿¡
- </combo_item>
- <combo_item length="1" name="Neversend" type="string">
- é€ä¿¡ã—ãªã„
- </combo_item>
- </combo_box>
- <combo_box name="language_combobox">
- <combo_item length="1" name="System Default Language" type="string">
- システム・デフォルト
- </combo_item>
- <combo_item length="1" name="English" type="string">
- English (英語)
- </combo_item>
- <combo_item length="1" name="Danish" type="string">
- Dansk (デンマーク語) – ベータ
- </combo_item>
- <combo_item length="1" name="Deutsch(German)" type="string">
- Deutsch (ドイツ語) – ベータ
- </combo_item>
- <combo_item length="1" name="Spanish" type="string">
- Español (スペイン語) – ベータ
- </combo_item>
- <combo_item length="1" name="French" type="string">
- Français (フランス語) – ベータ
- </combo_item>
- <combo_item name="Italian">
- Italiano (イタリア語) - ベータ
- </combo_item>
- <combo_item name="Hungarian">
- Magyar (ãƒãƒ³ã‚¬ãƒªãƒ¼èªž) - ベータ
- </combo_item>
- <combo_item name="Dutch">
- Nederlands (オランダ語) - ベータ
- </combo_item>
- <combo_item name="Polish">
- Polski (ãƒãƒ¼ãƒ©ãƒ³ãƒ‰èªž) - ベータ
- </combo_item>
- <combo_item length="1" name="Portugese" type="string">
- Português (ãƒãƒ«ãƒˆã‚¬ãƒ«èªž) – ベータ
- </combo_item>
- <combo_item name="Russian">
- РуÑÑкий (ロシア語) - ベータ
- </combo_item>
- <combo_item name="Turkish">
- Türkçe (トルコ語) - ベータ
- </combo_item>
- <combo_item name="Ukrainian">
- УкраїнÑька (ウクライナ語) - ベータ
- </combo_item>
- <combo_item length="1" name="Chinese" type="string">
- 中文 (简体) (中国語) - ベータ
- </combo_item>
- <combo_item length="1" name="(Japanese)" type="string">
- 日本語 – ベータ
- </combo_item>
- <combo_item length="1" name="(Korean)" type="string">
- 한국어 (韓国語) – ベータ
- </combo_item>
- </combo_box>
- <check_box label="言語をオブジェクトã¨å…±æœ‰" name="language_is_public" tool_tip="優先言語をインワールドã®ã‚ªãƒ–ジェクトãŒèªè­˜ã™ã‚‹"/>
+ <text_editor name="busy_response">
+ log_in_to_change
+ </text_editor>
</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/ja/panel_preferences_graphics1.xml
index 167bc2a1ce..191748fe91 100644
--- a/indra/newview/skins/default/xui/ja/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_graphics1.xml
@@ -1,84 +1,28 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="表示" name="Display panel">
- <text type="string" length="1" name="text">
- 表示解åƒåº¦ï¼š
- </text>
- <button label="?" name="GraphicsPreferencesHelpButton" />
- <check_box label="ウィンドウ内㧠Second Life を起動" name="windowed mode" />
- <text_editor name="voice_chat_description">
- ãƒã‚§ãƒƒã‚¯ç„¡ã—ã®å ´åˆã¯ã€ãƒ­ã‚°ã‚¤ãƒ³æ™‚ã«ãƒ•ãƒ«ã‚¹ã‚¯ãƒªãƒ¼ãƒ³è¡¨ç¤º
- </text_editor>
- <text type="string" length="1" name="Fullscreen Aspect Ratio:">
- 全画é¢ã®ç¸¦æ¨ªæ¯”:
- </text>
- <text type="string" length="1" name="(width / height)">
- (幅ï¼é«˜ã•ï¼‰
- </text>
- <text_editor bottom="-56" height="40" name="FullScreenInfo" width="480">
- ãƒã‚§ãƒƒã‚¯ã•ã‚Œã¦ã„ãªã„å ´åˆã¯ã€ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹ã¨ãƒ“ューワãŒãƒ•ãƒ«ã‚¹ã‚¯ãƒªãƒ¼ãƒ³ã§è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚
- </text_editor>
<text name="WindowSizeLabel">
ウィンドウ・サイズ:
</text>
+ <check_box label="全画é¢" name="windowed mode"/>
<combo_box name="windowsize combo">
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="720x480">
- 720x480 (NTSC)
- </combo_item>
- <combo_item name="768x576">
- 768x576 (PAL)
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
- </combo_box>
- <text name="DisplayResLabel">
- 表示解åƒåº¦ï¼š
- </text>
- <text name="AspectRatioLabel1" tool_tip="(幅/高ã•ï¼‰">
- 縦横比:
- </text>
- <combo_box name="aspect_ratio" tool_tip="(幅/高ã•ï¼‰">
- <combo_item type="string" length="1" name="4:3(StandardCRT)">
- 4:3(標準CRT)
- </combo_item>
- <combo_item type="string" length="1" name="5:4(1280x1024LCD)">
- 5:4(1280x1024 LCD)
- </combo_item>
- <combo_item name="8:5(Widescreen)">
- 8:5(ワイドスクリï¼ãƒ³ï¼‰
- </combo_item>
- <combo_item type="string" length="1" name="16:9(Widescreen)">
- 16:9(ワイドスクリï¼ãƒ³ï¼‰
- </combo_item>
+ <combo_box.item label="640x480" name="640x480"/>
+ <combo_box.item label="800x600" name="800x600"/>
+ <combo_box.item label="720x480 (NTSC)" name="720x480"/>
+ <combo_box.item label="768x576 (PAL)" name="768x576"/>
+ <combo_box.item label="1024x768" name="1024x768"/>
</combo_box>
- <check_box label="自動検出率" name="aspect_auto_detect" />
- <text type="string" length="1" name="UI Size:">
- UIサイズ:
+ <text name="UI Size:">
+ UI サイズ:
</text>
- <text type="string" length="1" name="(meters, lower is faster)">
- (メートルã€ä½Žã„ã»ã©é€Ÿã„)
- </text>
- <text type="string" length="1" name="text2">
- 表示オプション:
- </text>
- <check_box label="解åƒåº¦å˜ç‹¬ã‚¹ã‚±ãƒ¼ãƒ«ã‚’使用" name="ui_auto_scale" />
- <spinner label="æç”»è·é›¢ï¼š" name="draw_distance" />
- <check_box label="ã‚¢ãƒã‚¿ãƒ¼ã‚’一人称視点(マウスルック)ã§è¡¨ç¤º" name="avfp" />
- <text name="HigherText">
- å“質ãŠã‚ˆã³
- </text>
- <text name="QualityText">
- パフォーマンス:
+ <text name="QualitySpeed">
+ クオリティã¨ã‚¹ãƒ”ード:
</text>
<text name="FasterText">
速ã„
</text>
+ <text name="BetterText">
+ é…ã„
+ </text>
<text name="ShadersPrefText">
低
</text>
@@ -91,113 +35,82 @@
<text name="ShadersPrefText4">
超高
</text>
- <text name="HigherText2">
- 高ã„
- </text>
- <text name="QualityText2">
- å“質
- </text>
- <check_box label="カスタム" name="CustomSettings" />
- <text name="ShadersText">
- シェーダー:
- </text>
- <check_box label="ãƒãƒ³ãƒ—・マッピングã¨å…‰æ²¢" name="BumpShiny" />
- <check_box label="基本シェーダー" name="BasicShaders"
- tool_tip="ã“ã®ã‚ªãƒ—ションを無効ã«ã™ã‚‹ã¨ã‚°ãƒ©ãƒ•ã‚£ãƒƒã‚¯ãƒ»ã‚«ãƒ¼ãƒ‰ãƒ»ãƒ‰ãƒ©ã‚¤ãƒã®ç¨®é¡žã«ã‚ˆã£ã¦ã¯ã‚¯ãƒ©ãƒƒã‚·ãƒ¥é˜²æ­¢ã«ãªã‚Šã¾ã™ã€‚" />
- <check_box label="周囲(大気)シェーダー" name="WindLightUseAtmosShaders" />
- <check_box label="æ°´ã®åå°„" name="Reflections" />
- <text name="ReflectionDetailText">
- å射詳細:
- </text>
- <radio_group name="ReflectionDetailRadio">
- <radio_item name="0">
- 地形ã¨æ¨¹æœ¨
- </radio_item>
- <radio_item name="1">
- ã™ã¹ã¦ã®é™çš„オブジェクト
- </radio_item>
- <radio_item name="2">
- ã™ã¹ã¦ã®ã‚¢ãƒã‚¿ãƒ¼ã¨ã‚ªãƒ–ジェクト
- </radio_item>
- <radio_item name="3">
- ã™ã¹ã¦
- </radio_item>
- </radio_group>
- <text name="AvatarRenderingText">
- ã‚¢ãƒã‚¿ãƒ¼è¡¨ç¤ºï¼š
- </text>
- <check_box label="ã‚¢ãƒã‚¿ãƒ¼ã®ç²¾åº¦ã‚’下ã’ã‚‹" name="AvatarImpostors" />
- <check_box label="ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãƒ»ã‚¹ã‚­ãƒ‹ãƒ³ã‚°" name="AvatarVertexProgram" />
- <check_box label="ã‚¢ãƒã‚¿ãƒ¼ã®æœ" name="AvatarCloth" />
- <text name="DrawDistanceMeterText1">
- m
- </text>
- <text name="DrawDistanceMeterText2">
- m
- </text>
- <slider label="æç”»è·é›¢ï¼š" name="DrawDistance" />
- <slider label="最大パーティクル数:" name="MaxParticleCount" />
- <slider label="ãƒã‚¹ãƒˆãƒ—ロセスå“質:" name="RenderPostProcess" />
- <text name="MeshDetailText">
- メッシュ詳細:
- </text>
- <slider label=" オブジェクト:" name="ObjectMeshDetail" />
- <slider label=" フレキシプリム:" name="FlexibleMeshDetail" />
- <slider label=" 樹木:" name="TreeMeshDetail" />
- <slider label=" ã‚¢ãƒã‚¿ãƒ¼ï¼š" name="AvatarMeshDetail" />
- <slider label=" 地形:" name="TerrainMeshDetail" />
- <slider label=" 空:" name="SkyMeshDetail" />
- <text name="PostProcessText">
- 低
- </text>
- <text name="ObjectMeshDetailText">
- 低
- </text>
- <text name="FlexibleMeshDetailText">
- 低
- </text>
- <text name="TreeMeshDetailText">
- 低
- </text>
- <text name="AvatarMeshDetailText">
- 低
- </text>
- <text name="TerrainMeshDetailText">
- 低
- </text>
- <text name="SkyMeshDetailText">
- 低
- </text>
- <text name="LightingDetailText">
- ライティング詳細:
- </text>
- <radio_group name="LightingDetailRadio">
- <radio_item name="SunMoon">
- 太陽ã¨æœˆã®ã¿
- </radio_item>
- <radio_item name="LocalLights">
- 近隣ã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒ»ãƒ©ã‚¤ãƒˆ
- </radio_item>
- </radio_group>
- <text name="TerrainDetailText">
- 地形詳細:
- </text>
- <radio_group name="TerrainDetailRadio">
- <radio_item name="0">
+ <panel label="カスタムグラフィック" name="CustomGraphics Panel">
+ <text name="ShadersText">
+ シェーダー:
+ </text>
+ <check_box initial_value="true" label="ãƒãƒ³ãƒ—マッピングã¨å…‰æ²¢" name="BumpShiny"/>
+ <check_box initial_value="true" label="基本シェーダー" name="BasicShaders" tool_tip="ã“ã®ã‚ªãƒ—ションを無効ã«ã™ã‚‹ã¨ã€ã‚°ãƒ©ãƒ•ã‚£ãƒƒã‚¯ã‚«ãƒ¼ãƒ‰ã®ãƒ‰ãƒ©ã‚¤ãƒã®ç¨®é¡žã«ã‚ˆã£ã¦ã¯ã€ã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã™ã‚‹ã®ã‚’防ãŽã¾ã™ã€‚"/>
+ <check_box initial_value="true" label="周囲(大気)シェーダー" name="WindLightUseAtmosShaders"/>
+ <check_box initial_value="true" label="æ°´ã®åå°„" name="Reflections"/>
+ <text name="ReflectionDetailText">
+ å射詳細:
+ </text>
+ <radio_group name="ReflectionDetailRadio">
+ <radio_item label="地形ã¨æ¨¹æœ¨" name="0"/>
+ <radio_item label="ã™ã¹ã¦ã®é™æ­¢ã‚ªãƒ–ジェクト" name="1"/>
+ <radio_item label="ã™ã¹ã¦ã®ã‚¢ãƒã‚¿ãƒ¼ã¨ã‚ªãƒ–ジェクト" name="2"/>
+ <radio_item label="ã™ã¹ã¦" name="3"/>
+ </radio_group>
+ <text name="AvatarRenderingText">
+ ã‚¢ãƒã‚¿ãƒ¼è¡¨ç¤ºï¼š
+ </text>
+ <check_box initial_value="true" label="ã‚¢ãƒã‚¿ãƒ¼ã®ç²¾åº¦ã‚’上ã’ã‚‹" name="AvatarImpostors"/>
+ <check_box initial_value="true" label="ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã‚¹ã‚­ãƒ‹ãƒ³ã‚°" name="AvatarVertexProgram"/>
+ <check_box initial_value="true" label="ã‚¢ãƒã‚¿ãƒ¼ã®å¸ƒ" name="AvatarCloth"/>
+ <slider label="æç”»è·é›¢ï¼š" name="DrawDistance"/>
+ <text name="DrawDistanceMeterText2">
+ m
+ </text>
+ <slider label="最大パーティクル数:" name="MaxParticleCount"/>
+ <slider label="ãƒã‚¹ãƒˆãƒ—ロセスå“質:" name="RenderPostProcess"/>
+ <text name="MeshDetailText">
+ メッシュ詳細:
+ </text>
+ <slider label=" オブジェクト:" name="ObjectMeshDetail"/>
+ <slider label=" フレキシプリム:" name="FlexibleMeshDetail"/>
+ <slider label=" 樹木:" name="TreeMeshDetail"/>
+ <slider label=" ã‚¢ãƒã‚¿ãƒ¼ï¼š" name="AvatarMeshDetail"/>
+ <slider label=" 地形:" name="TerrainMeshDetail"/>
+ <slider label=" 空:" name="SkyMeshDetail"/>
+ <text name="PostProcessText">
低
- </radio_item>
- <radio_item name="2">
- 高
- </radio_item>
- </radio_group>
- <button label="推奨ã•ã‚ŒãŸè¨­å®š" name="Defaults" />
- <button label="ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãƒ»ã‚ªãƒ—ション"
- label_selected="ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ãƒ»ã‚ªãƒ—ション"
- name="GraphicsHardwareButton" />
- <text name="resolution_format">
- [RES_X] x [RES_Y]
- </text>
- <text name="aspect_ratio_text">
- [NUM]:[DEN]
- </text>
+ </text>
+ <text name="ObjectMeshDetailText">
+ 低
+ </text>
+ <text name="FlexibleMeshDetailText">
+ 低
+ </text>
+ <text name="TreeMeshDetailText">
+ 低
+ </text>
+ <text name="AvatarMeshDetailText">
+ 低
+ </text>
+ <text name="TerrainMeshDetailText">
+ 低
+ </text>
+ <text name="SkyMeshDetailText">
+ 低
+ </text>
+ <text name="LightingDetailText">
+ ライティング詳細:
+ </text>
+ <radio_group name="LightingDetailRadio">
+ <radio_item label="太陽ã¨æœˆã®ã¿" name="SunMoon"/>
+ <radio_item label="è¿‘ãã®ãƒ­ãƒ¼ã‚«ãƒ«ã‚µã‚¤ãƒˆ" name="LocalLights"/>
+ </radio_group>
+ <text name="TerrainDetailText">
+ 地形詳細:
+ </text>
+ <radio_group name="TerrainDetailRadio">
+ <radio_item label="低" name="0"/>
+ <radio_item label="高" name="2"/>
+ </radio_group>
+ </panel>
+ <button label="é©ç”¨" label_selected="é©ç”¨" name="Apply"/>
+ <button label="リセット" name="Defaults"/>
+ <button label="詳ã—ã„設定" name="Advanced"/>
+ <button label="ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢" label_selected="ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢" name="GraphicsHardwareButton"/>
</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/ja/panel_preferences_privacy.xml
new file mode 100644
index 0000000000..80c0c85420
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_privacy.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="ãƒãƒ£ãƒƒãƒˆè¨­å®š" name="im">
+ <panel.string name="log_in_to_change">
+ ログインã—ã¦å¤‰æ›´
+ </panel.string>
+ <button label="履歴ã®æ¶ˆåŽ»" name="clear_cache"/>
+ <text name="cache_size_label_l">
+ (ä½ç½®ã€ç”»åƒã€webã€æ¤œç´¢å±¥æ­´ï¼‰
+ </text>
+ <check_box label="ç§ã®ã‚ªãƒ³ãƒ©ã‚¤ãƒ³çŠ¶æ³ã‚’確èªã§ãã‚‹ã®ã¯ã€ãƒ•ãƒ¬ãƒ³ãƒ‰ã¨ã‚°ãƒ«ãƒ¼ãƒ—ã ã‘" name="online_visibility"/>
+ <check_box label="フレンドã¨ã‚°ãƒ«ãƒ¼ãƒ—以外ã‹ã‚‰ã¯ã‚³ãƒ¼ãƒ«ã¨IMã‚’å—ä¿¡ã—ãªã„" name="voice_call_friends_only_check"/>
+ <check_box label="コールãŒçµ‚了ã—ãŸã‚‰ãƒžã‚¤ã‚¯ã®ã‚¹ã‚¤ãƒƒãƒã‚’切る" name="auto_disengage_mic_check"/>
+ <check_box label="Cookieã‚’å—ã‘入れる" name="cookies_enabled"/>
+ <check_box label="メディアã®è‡ªå‹•å†ç”Ÿã‚’許å¯ã™ã‚‹" name="autoplay_enabled"/>
+ <check_box label="自動的ã«åŒºç”»ãƒ¡ãƒ‡ã‚£ã‚¢ã‚’å†ç”Ÿã™ã‚‹" name="parcel_autoplay_enabled"/>
+ <text name="Logs:">
+ ログ:
+ </text>
+ <check_box label="コンピューターã«è¿‘ãã®ãƒãƒ£ãƒƒãƒˆãƒ­ã‚°ã‚’ä¿å­˜ã™ã‚‹" name="log_nearby_chat"/>
+ <check_box label="コンピューター㫠IM ログをä¿å­˜ã™ã‚‹" name="log_instant_messages"/>
+ <check_box label="タイムスタンプを追加ã™ã‚‹" name="show_timestamps_check_im"/>
+ <text name="log_path_desc">
+ ログã®ä¿å­˜å ´æ‰€
+ </text>
+ <button label="å‚ç…§" label_selected="å‚ç…§" name="log_path_button"/>
+ <button label="ブロックリスト" name="block_list"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_preferences_setup.xml b/indra/newview/skins/default/xui/ja/panel_preferences_setup.xml
new file mode 100644
index 0000000000..5911727c67
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_setup.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="æ“作ã¨ã‚«ãƒ¡ãƒ©" name="Input panel">
+ <button label="ãã®ä»–ã®ãƒ‡ã‚£ãƒã‚¤ã‚¹" name="joystick_setup_button"/>
+ <text name="Mouselook:">
+ 一人称視点:
+ </text>
+ <text name=" Mouse Sensitivity">
+ マウスã®ç²¾åº¦
+ </text>
+ <check_box label="切り替ãˆ" name="invert_mouse"/>
+ <text name="Network:">
+ ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ï¼š
+ </text>
+ <text name="Maximum bandwidth">
+ 最大帯域幅
+ </text>
+ <text name="text_box2">
+ kbps
+ </text>
+ <check_box label="カスタムãƒãƒ¼ãƒˆ" name="connection_port_enabled"/>
+ <spinner label="ãƒãƒ¼ãƒˆç•ªå·ï¼š" name="web_proxy_port"/>
+ <text name="cache_size_label_l">
+ キャッシュサイズ
+ </text>
+ <text name="text_box5">
+ MB
+ </text>
+ <button label="å‚ç…§" label_selected="å‚ç…§" name="set_cache"/>
+ <button label="リセット" label_selected="設定" name="reset_cache"/>
+ <text name="Cache location">
+ キャッシュã®ä¿å­˜å ´æ‰€
+ </text>
+ <text name="Web:">
+ Web:
+ </text>
+ <radio_group name="use_external_browser">
+ <radio_item label="内蔵ブラウザを使用" name="internal" tool_tip="内蔵ブラウザã§ãƒ˜ãƒ«ãƒ—ã‚„Webリンクãªã©ã‚’見ã¾ã™ã€‚[APP_NAME] 内ã«æ–°ã—ã„ウィンドウã§ã“ã®ãƒ–ラウザãŒé–‹ãã¾ã™ã€‚"/>
+ <radio_item label="外部ブラウザ(IEã‚„Firefox)を使用" name="external" tool_tip="デフォルトã®ã‚·ã‚¹ãƒ†ãƒ Webブラウザã§ãƒ˜ãƒ«ãƒ—ã‚„Webリンク先ãªã©ã‚’見ã¾ã™ã€‚全画é¢ã§èµ·å‹•ä¸­ã«ã¯ãŠã™ã™ã‚ã—ã¾ã›ã‚“。"/>
+ </radio_group>
+ <check_box initial_value="false" label="Webプロキシ" name="web_proxy_enabled"/>
+ <line_editor name="web_proxy_editor" tool_tip="使用ã™ã‚‹ãƒ—ロキシåã¾ãŸã¯IPアドレス"/>
+ <button label="å‚ç…§" label_selected="å‚ç…§" name="set_proxy"/>
+ <text name="Proxy location">
+ プロキシ
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_preferences_sound.xml b/indra/newview/skins/default/xui/ja/panel_preferences_sound.xml
new file mode 100644
index 0000000000..9c8bda4c76
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_sound.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="サウンド" name="Preference Media panel">
+ <slider label="全体ã®éŸ³é‡" name="System Volume"/>
+ <check_box initial_value="true" label="最å°åŒ–ã§ãƒŸãƒ¥ãƒ¼ãƒˆ" name="mute_when_minimized"/>
+ <slider label="風" name="Wind Volume"/>
+ <slider label="ボタン" name="UI Volume"/>
+ <slider label="メディア" name="Media Volume"/>
+ <slider label="効果音" name="SFX Volume"/>
+ <slider label="ストリーミング音楽" name="Music Volume"/>
+ <check_box label="ボイス" name="enable_voice_check"/>
+ <slider label="ボイス" name="Voice Volume"/>
+ <text name="Listen from">
+ æ–¹å‘:
+ </text>
+ <radio_group name="ear_location">
+ <radio_item label="カメラã®ä½ç½®ã‹ã‚‰èžã" name="0"/>
+ <radio_item label="ã‚¢ãƒã‚¿ãƒ¼ã®ä½ç½®ã‹ã‚‰èžã" name="1"/>
+ </radio_group>
+ <button label="入力・出力機器" name="device_settings_btn"/>
+ <panel label="機器ã®è¨­å®š" name="device_settings_panel">
+ <panel.string name="default_text">
+ デフォルト
+ </panel.string>
+ <text name="Input">
+ 入力
+ </text>
+ <text name="My volume label">
+ ç§ã®éŸ³é‡ï¼š
+ </text>
+ <slider_bar initial_value="1.0" name="mic_volume_slider" tool_tip="スライダーを使ã£ã¦éŸ³é‡ã‚’調節ã—ã¾ã™"/>
+ <text name="wait_text">
+ ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„。
+ </text>
+ <text name="Output">
+ 出力
+ </text>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/ja/panel_prim_media_controls.xml
new file mode 100644
index 0000000000..629070a18a
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_prim_media_controls.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="MediaControls">
+ <string name="control_background_image_name">
+ Inspector_Background
+ </string>
+ <string name="skip_step">
+ 0.2
+ </string>
+ <layout_stack name="media_controls">
+ <layout_panel name="media_address">
+ <line_editor name="media_address_url" tool_tip="メディア URL"/>
+ <layout_stack name="media_address_url_icons">
+ <layout_panel>
+ <icon name="media_whitelist_flag" tool_tip="ホワイトリスト有効"/>
+ </layout_panel>
+ <layout_panel>
+ <icon name="media_secure_lock_flag" tool_tip="安全ãªé–²è¦§"/>
+ </layout_panel>
+ </layout_stack>
+ </layout_panel>
+ <layout_panel name="media_play_position">
+ <slider_bar initial_value="0.5" name="media_play_slider" tool_tip="ムービーå†ç”Ÿé€²è¡Œ"/>
+ </layout_panel>
+ <layout_panel name="media_volume">
+ <button name="media_volume_button" tool_tip="ミュート"/>
+ </layout_panel>
+ </layout_stack>
+ <layout_stack>
+ <panel name="media_progress_indicator">
+ <progress_bar name="media_progress_bar" tool_tip="ローディング"/>
+ </panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_profile.xml b/indra/newview/skins/default/xui/ja/panel_profile.xml
new file mode 100644
index 0000000000..767e26af4c
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_profile.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="プロフィール" name="panel_profile">
+ <string name="CaptionTextAcctInfo">
+ [ACCTTYPE]
+[PAYMENTINFO] [AGEVERIFICATION]
+ </string>
+ <string name="payment_update_link_url">
+ http://www.secondlife.com/account/billing.php?lang=ja-JP
+ </string>
+ <string name="partner_edit_link_url">
+ http://www.secondlife.com/account/partners.php?lang=ja
+ </string>
+ <string name="my_account_link_url" value="http://secondlife.com/my/account/index.php?lang=ja-JP"/>
+ <string name="no_partner_text" value="ãªã—"/>
+ <string name="RegisterDateFormat">
+ [REG_DATE] ([AGE])
+ </string>
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
+ <panel name="second_life_image_panel">
+ <text name="title_sl_descr_text" value="[SECOND_LIFE]:"/>
+ <expandable_text name="sl_description_edit">
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ <panel name="first_life_image_panel">
+ <text name="title_rw_descr_text" value="ç¾å®Ÿä¸–界:"/>
+ <expandable_text name="fl_description_edit">
+ Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ <text name="me_homepage_text">
+ Web サイト:
+ </text>
+ <text name="title_member_text" value="メンãƒãƒ¼ç™»éŒ²ï¼š"/>
+ <text name="register_date" value="05/31/1976"/>
+ <text name="title_acc_status_text" value="アカウントã®çŠ¶æ…‹ï¼š"/>
+ <text name="acc_status_text" value="ä½äººã€‚ 支払情報未登録"/>
+ <text name="title_partner_text" value="パートナー:"/>
+ <panel name="partner_data_panel">
+ <text name="partner_text" value="[FIRST] [LAST]"/>
+ </panel>
+ <text name="title_groups_text" value="グループ:"/>
+ <expandable_text name="sl_groups">
+ Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
+ </expandable_text>
+ </panel>
+ </scroll_container>
+ <panel name="profile_buttons_panel">
+ <button label="フレンド登録" name="add_friend"/>
+ <button label="IM" name="im"/>
+ <button label="コール" name="call"/>
+ <button label="地図" name="show_on_map_btn"/>
+ <button label="テレãƒãƒ¼ãƒˆ" name="teleport"/>
+ <button label="â–¼" name="overflow_btn"/>
+ </panel>
+ <panel name="profile_me_buttons_panel">
+ <button label="プロフィールã®ç·¨é›†" name="edit_profile_btn"/>
+ <button label="容姿ã®ç·¨é›†" name="edit_appearance_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_profile_view.xml b/indra/newview/skins/default/xui/ja/panel_profile_view.xml
new file mode 100644
index 0000000000..5666a93cf0
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_profile_view.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_target_profile">
+ <string name="status_online">
+ オンライン
+ </string>
+ <string name="status_offline">
+ オフライン
+ </string>
+ <text_editor name="user_name" value="(ローディング...)"/>
+ <text name="status" value="オンライン"/>
+ <tab_container name="tabs">
+ <panel label="プロフィール" name="panel_profile"/>
+ <panel label="ピック" name="panel_picks"/>
+ <panel label="メモã¨ãƒ—ライãƒã‚·ãƒ¼" name="panel_notes"/>
+ </tab_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_region_covenant.xml b/indra/newview/skins/default/xui/ja/panel_region_covenant.xml
index 169f922149..5f43f93113 100644
--- a/indra/newview/skins/default/xui/ja/panel_region_covenant.xml
+++ b/indra/newview/skins/default/xui/ja/panel_region_covenant.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="約款" name="Covenant">
<text font="SansSerifLarge" name="estate_section_lbl">
- ä¸å‹•ç”£ï¼š
+ エステート(ä¸å‹•ç”£ï¼‰
</text>
<text name="estate_name_lbl">
åå‰ï¼š
@@ -30,17 +30,16 @@
約款ã®å¤‰æ›´ã¯ä¸å‹•ç”£å…¨åŒºç”»ã«é©ç”¨ã¨ãªã‚Šã¾ã™ã€‚
</text>
<text name="covenant_instructions">
- ã“ã®ä¸å‹•ç”£ã®ç´„款ã®å¤‰æ›´ã™ã‚‹ã«ã¯ã€
-ノートカードをドラッグ&amp;ドロップã—ã¦ãã ã•ã„。
+ ã“ã®ä¸å‹•ç”£ç´„款ã®å¤‰æ›´ã‚’ã™ã‚‹éš›ã¯ã€ãƒŽãƒ¼ãƒˆã‚«ãƒ¼ãƒ‰ã‚’ドラッグ&ドロップã—ã¦ãã ã•ã„。
</text>
<text bottom_delta="-34" font="SansSerifLarge" name="region_section_lbl">
- 地域:
+ リージョン(地域)
</text>
<text name="region_name_lbl">
åå‰ï¼š
</text>
<text name="region_name_text">
- leyla
+ Erica
</text>
<text name="region_landtype_lbl">
種類:
diff --git a/indra/newview/skins/default/xui/ja/panel_region_debug.xml b/indra/newview/skins/default/xui/ja/panel_region_debug.xml
index 4e6bae7172..4209fb17e5 100644
--- a/indra/newview/skins/default/xui/ja/panel_region_debug.xml
+++ b/indra/newview/skins/default/xui/ja/panel_region_debug.xml
@@ -13,7 +13,7 @@
<check_box label="物ç†ä½œç”¨ã‚’無効化" name="disable_physics_check" tool_tip="ã“ã®åœ°åŸŸã®ç‰©ç†ä½œç”¨ã‚’ã™ã¹ã¦ç„¡åŠ¹åŒ–"/>
<button label="?" name="disable_physics_help"/>
<button label="é©ç”¨" name="apply_btn"/>
- <text name="objret_text_lbl" width="120" >
+ <text name="objret_text_lbl" width="120">
オブジェクトã®è¿”å´
</text>
<text name="resident_text_lbl">
@@ -22,13 +22,13 @@
<line_editor name="target_avatar_name">
(ãªã—)
</line_editor>
- <button label="é¸æŠž..." name="choose_avatar_btn"/>
+ <button label="é¸æŠž" name="choose_avatar_btn"/>
<text name="options_text_lbl">
オプション:
</text>
- <check_box label="スクリプトã®ã‚るオブジェクトã®ã¿ã‚’è¿”å´" name="return_scripts" tool_tip="スクリプトãŒã‚るオブジェクトã®ã¿ã‚’è¿”å´"/>
- <check_box label="他人ã®åœŸåœ°ã«ã‚るオブジェクトã®ã¿ã‚’è¿”å´" name="return_other_land" tool_tip="他人ã«å±žã™ã‚‹åœŸåœ°ã«ã‚るオブジェクトã®ã¿ã‚’è¿”å´"/>
- <check_box label="ã“ã®ä¸å‹•ç”£ã®å„地域ã®ã‚ªãƒ–ジェクトを返å´" name="return_estate_wide" tool_tip="ã“ã®ä¸å‹•ç”£ã«å«ã¾ã‚Œã¦ã„ã‚‹ã™ã¹ã¦ã®åœ°åŸŸã®ã‚ªãƒ–ジェクトを返å´"/>
+ <check_box label="スクリプト付ãã®ã‚‚ã®" name="return_scripts" tool_tip="スクリプトã®ã‚ªãƒ–ジェクトã ã‘è¿”å´ã—ã¾ã™"/>
+ <check_box label="他人ã®åœŸåœ°ã«ã‚ã‚‹ã‚‚ã®" name="return_other_land" tool_tip="他人ã«å±žã™ã‚‹åœŸåœ°ã«ã‚るオブジェクトã®ã¿ã‚’è¿”å´"/>
+ <check_box label="ã“ã®ä¸å‹•ç”£ã«å±žã™ã‚‹ã™ã¹ã¦ã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã®ã‚‚ã®" name="return_estate_wide" tool_tip="ã“ã®ä¸å‹•ç”£ã«å«ã¾ã‚Œã¦ã„ã‚‹ã™ã¹ã¦ã®åœ°åŸŸã®ã‚ªãƒ–ジェクトを返å´"/>
<button label="è¿”å´" name="return_btn"/>
<button label="上部コライダーå–å¾—" name="top_colliders_btn" tool_tip="è¡çªã™ã‚‹å¯èƒ½æ€§ãŒæœ€ã‚‚高ã„オブジェクトã®ãƒªã‚¹ãƒˆ"/>
<button label="?" name="top_colliders_help"/>
diff --git a/indra/newview/skins/default/xui/ja/panel_region_estate.xml b/indra/newview/skins/default/xui/ja/panel_region_estate.xml
index 186820f00a..348878a35e 100644
--- a/indra/newview/skins/default/xui/ja/panel_region_estate.xml
+++ b/indra/newview/skins/default/xui/ja/panel_region_estate.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="ä¸å‹•ç”£" name="Estate">
<text name="estate_help_text">
ã“ã®ã‚¿ãƒ–ã®è¨­å®šã‚’変更ã™ã‚‹ã¨ã“ã®ä¸å‹•ç”£å†…
@@ -19,60 +19,57 @@
<text name="Only Allow">
次ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’制é™ï¼š
</text>
- <check_box label="支払ã„情報登録済ã¿ã®ä½äºº" name="limit_payment"
- tool_tip="支払ã„情報未登録ã®ä½äººã‚’排除ã™ã‚‹" />
- <check_box label="年齢確èªæ¸ˆã¿ã®æˆäºº" name="limit_age_verified"
- tool_tip="年齢確èªã‚’済ã¾ã›ã¦ã„ãªã„ä½äººã‚’排除ã™ã‚‹è©³ç´°ã«ã¤ã„ã¦ã¯ã€support.secondlife.comã‚’å‚ç…§ã—ã¦ãã ã•ã„。" />
- <check_box label="ボイスãƒãƒ£ãƒƒãƒˆã‚’許å¯" name="voice_chat_check" />
- <button label="?" name="voice_chat_help" />
+ <check_box label="支払ã„情報登録済ã¿ã®ä½äºº" name="limit_payment" tool_tip="未確èªã®ä½äººã®ç«‹å…¥ã‚’ç¦æ­¢ã—ã¾ã™"/>
+ <check_box label="年齢確èªæ¸ˆã¿ã®æˆäºº" name="limit_age_verified" tool_tip="年齢確èªã‚’済ã¾ã›ã¦ã„ãªã„ä½äººã‚’ç«‹å…¥ç¦æ­¢ã«ã—ã¾ã™ã€‚ 詳ã—ã„情報㯠[SUPPORT_SITE] ã‚’ã”覧下ã•ã„。"/>
+ <check_box label="ボイスãƒãƒ£ãƒƒãƒˆã‚’許å¯" name="voice_chat_check"/>
+ <button label="?" name="voice_chat_help"/>
<text name="abuse_email_text">
å«ŒãŒã‚‰ã›ã«é–¢ã™ã‚‹ãƒ¡ãƒ¼ãƒ«å…ˆ:
</text>
<string name="email_unsupported">
サãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ãªã„機能
</string>
- <button label="?" name="abuse_email_address_help" />
+ <button label="?" name="abuse_email_address_help"/>
<text name="estate_manager_label">
ä¸å‹•ç”£ãƒžãƒãƒ¼ã‚¸ãƒ£ãƒ¼ï¼š
</text>
- <button label="?" name="estate_manager_help" />
- <button label="追加..." name="add_estate_manager_btn" />
- <button label="削除..." name="remove_estate_manager_btn" />
- <check_box label="世界時間を使用" name="use_global_time_check" />
- <button label="?" name="use_global_time_help" />
- <check_box label="太陽固定" name="fixed_sun_check" />
- <button label="?" name="fixed_sun_help" />
- <slider label="段階" name="sun_hour_slider" />
- <check_box label="パブリック・アクセスを許å¯" name="externally_visible_check" />
- <button label="?" name="externally_visible_help" />
- <check_box label="直接テレãƒãƒ¼ãƒˆã‚’許å¯" name="allow_direct_teleport" />
- <button label="?" name="allow_direct_teleport_help" />
+ <button label="?" name="estate_manager_help"/>
+ <button label="追加..." name="add_estate_manager_btn"/>
+ <button label="削除..." name="remove_estate_manager_btn"/>
+ <check_box label="世界時間を使用" name="use_global_time_check"/>
+ <button label="?" name="use_global_time_help"/>
+ <check_box label="太陽固定" name="fixed_sun_check"/>
+ <button label="?" name="fixed_sun_help"/>
+ <slider label="段階" name="sun_hour_slider"/>
+ <check_box label="パブリック・アクセスを許å¯" name="externally_visible_check"/>
+ <button label="?" name="externally_visible_help"/>
+ <check_box label="直接テレãƒãƒ¼ãƒˆã‚’許å¯" name="allow_direct_teleport"/>
+ <button label="?" name="allow_direct_teleport_help"/>
<text name="region_text_lbl">
支払ã„状æ³ã«ã‚ˆã‚Šã‚¢ã‚¯ã‚»ã‚¹ã‚’æ‹’å¦ï¼š
</text>
- <check_box label="支払情報登録ãŒãªã„ã‚‚ã®ã‚’æ‹’å¦" name="deny_anonymous" />
- <check_box label="支払情報登録ãŒã‚ã‚‹ã‚‚ã®ã‚’æ‹’å¦" name="deny_identified" />
- <check_box label="使用ã•ã‚Œã¦ã„る支払情報を拒å¦" name="deny_transacted" />
- <button label="é©ç”¨" name="apply_btn" />
+ <check_box label="支払情報登録ãŒãªã„ã‚‚ã®ã‚’æ‹’å¦" name="deny_anonymous"/>
+ <check_box label="支払情報登録ãŒã‚ã‚‹ã‚‚ã®ã‚’æ‹’å¦" name="deny_identified"/>
+ <check_box label="使用ã•ã‚Œã¦ã„る支払情報を拒å¦" name="deny_transacted"/>
+ <button label="é©ç”¨" name="apply_btn"/>
<text name="allow_resident_label">
許å¯ã•ã‚ŒãŸä½äºº:
</text>
- <button label="?" name="allow_resident_help" />
- <button label="追加..." name="add_allowed_avatar_btn" />
- <button label="削除..." name="remove_allowed_avatar_btn" />
+ <button label="?" name="allow_resident_help"/>
+ <button label="追加..." name="add_allowed_avatar_btn"/>
+ <button label="削除..." name="remove_allowed_avatar_btn"/>
<text name="allow_group_label">
許å¯ã•ã‚ŒãŸã‚°ãƒ«ãƒ¼ãƒ—:
</text>
- <button label="?" name="allow_group_help" />
- <button label="追加..." name="add_allowed_group_btn" />
- <button label="削除..." name="remove_allowed_group_btn" />
+ <button label="?" name="allow_group_help"/>
+ <button label="追加..." name="add_allowed_group_btn"/>
+ <button label="削除..." name="remove_allowed_group_btn"/>
<text name="ban_resident_label">
ç¦æ­¢ã•ã‚ŒãŸä½äºº:
</text>
- <button label="?" name="ban_resident_help" />
- <button label="追加..." name="add_banned_avatar_btn" />
- <button label="削除..." name="remove_banned_avatar_btn" />
- <button label="メッセージをä¸å‹•ç”£ã¸é€ä¿¡..." name="message_estate_btn" />
- <button label="土地ã‹ã‚‰ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’追ã„出ã™..."
- name="kick_user_from_estate_btn" />
+ <button label="?" name="ban_resident_help"/>
+ <button label="追加..." name="add_banned_avatar_btn"/>
+ <button label="削除..." name="remove_banned_avatar_btn"/>
+ <button label="メッセージをä¸å‹•ç”£ã¸é€ä¿¡..." name="message_estate_btn"/>
+ <button label="土地ã‹ã‚‰ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’追ã„出ã™..." name="kick_user_from_estate_btn"/>
</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_region_general.xml b/indra/newview/skins/default/xui/ja/panel_region_general.xml
index 73d2025446..690cf3f33d 100644
--- a/indra/newview/skins/default/xui/ja/panel_region_general.xml
+++ b/indra/newview/skins/default/xui/ja/panel_region_general.xml
@@ -40,15 +40,9 @@
区分:
</text>
<combo_box label="Mature" name="access_combo">
- <combo_item name="Adult">
- Adult
- </combo_item>
- <combo_item name="Mature">
- Mature
- </combo_item>
- <combo_item name="PG">
- PG
- </combo_item>
+ <combo_box.item label="Adult" name="Adult"/>
+ <combo_box.item label="Mature" name="Mature"/>
+ <combo_box.item label="PG" name="PG"/>
</combo_box>
<button label="?" name="access_help"/>
<button label="é©ç”¨" name="apply_btn"/>
diff --git a/indra/newview/skins/default/xui/ja/panel_region_texture.xml b/indra/newview/skins/default/xui/ja/panel_region_texture.xml
index 6527f0fbe6..d32d8f9e5d 100644
--- a/indra/newview/skins/default/xui/ja/panel_region_texture.xml
+++ b/indra/newview/skins/default/xui/ja/panel_region_texture.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="地é¢ãƒ†ã‚¯ã‚¹ãƒãƒ£ãƒ¼" name="Textures">
<text name="region_text_lbl">
地域:
@@ -36,22 +36,23 @@
<text name="height_text_lbl9">
北æ±
</text>
- <spinner label="低" name="height_start_spin_0" />
- <spinner label="低" name="height_start_spin_1" />
- <spinner label="低" name="height_start_spin_2" />
- <spinner label="低" name="height_start_spin_3" />
- <spinner label="高" name="height_range_spin_0" />
- <spinner label="高" name="height_range_spin_1" />
- <spinner label="高" name="height_range_spin_2" />
- <spinner label="高" name="height_range_spin_3" />
+ <spinner label="低" name="height_start_spin_0"/>
+ <spinner label="低" name="height_start_spin_1"/>
+ <spinner label="低" name="height_start_spin_2"/>
+ <spinner label="低" name="height_start_spin_3"/>
+ <spinner label="高" name="height_range_spin_0"/>
+ <spinner label="高" name="height_range_spin_1"/>
+ <spinner label="高" name="height_range_spin_2"/>
+ <spinner label="高" name="height_range_spin_3"/>
<text name="height_text_lbl10">
- ã“れらã®æ•°å­—ã¯ã€ä¸Šè¨˜ã®ãƒ†ã‚¯ã‚¹ãƒãƒ£ãƒ¼ã‚’ブレンドã™ã‚‹ç¯„囲を表ã—ã¾ã™ã€‚
+ 数値ã¯ä¸Šã®ãƒ†ã‚¯ã‚¹ãƒãƒ£ã®ãƒ–レンド範囲を示ã—ã¾ã™
</text>
<text name="height_text_lbl11">
- 計測ã®å˜ä½ã¯ãƒ¡ãƒ¼ãƒˆãƒ«ã§ã€ã€Œä½Žã€ã®å€¤ã¯ãƒ†ã‚¯ã‚¹ãƒãƒ£ãƒ¼#1ã®è¡¨ç¤ºé«˜ã•ã®æœ€å¤§å€¤ã§ã™ã€‚
+ 計測å˜ä½ã¯ãƒ¡ãƒ¼ãƒˆãƒ«ã§ã€ã€Œä½Žã€ã®å€¤ã¯ 1 番ã®ãƒ†ã‚¯ã‚¹ãƒãƒ£ã®é«˜ã•ã®æœ€å¤§å€¤ã§ã™ã€‚
+「高ã€ã®å€¤ã¯ã€4 番ã®ãƒ†ã‚¯ã‚¹ãƒãƒ£ã®é«˜ã•ã®æœ€ä½Žå€¤ã§ã™ã€‚
</text>
<text name="height_text_lbl12">
ãã—ã¦ã€Œé«˜ã€ã®å€¤ã¯ãƒ†ã‚¯ã‚¹ãƒãƒ£ãƒ¼#4ã®é«˜ã•ã®ä¸‹é™ã¨ãªã‚Šã¾ã™ã€‚
</text>
- <button label="é©ç”¨" name="apply_btn" />
+ <button label="é©ç”¨" name="apply_btn"/>
</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_script_ed.xml b/indra/newview/skins/default/xui/ja/panel_script_ed.xml
new file mode 100644
index 0000000000..a7305fa763
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_script_ed.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="script panel">
+ <panel.string name="loading">
+ ローディング...
+ </panel.string>
+ <panel.string name="can_not_view">
+ ã“ã®ã‚¹ã‚¯ãƒªãƒ—トã¯ã€Œã‚³ãƒ”ーä¸å¯ã€ã®ãŸã‚ã€è¡¨ç¤ºãƒ»ç·¨é›†ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。 オブジェクト内ã®ã‚¹ã‚¯ãƒªãƒ—トã®è¡¨ç¤ºãƒ»ç·¨é›†ã«ã¯ã€å…¨æ¨©é™ãŒå¿…è¦ã§ã™ã€‚
+ </panel.string>
+ <panel.string name="public_objects_can_not_run">
+ 公共ã®ã‚ªãƒ–ジェクトã§ã¯ã‚¹ã‚¯ãƒªãƒ—トを実行ã§ãã¾ã›ã‚“
+ </panel.string>
+ <panel.string name="script_running">
+ 実行中
+ </panel.string>
+ <panel.string name="Title">
+ スクリプト: [NAME]
+ </panel.string>
+ <text_editor name="Script Editor">
+ ローディング...
+ </text_editor>
+ <button label="ä¿å­˜" label_selected="ä¿å­˜" name="Save_btn"/>
+ <combo_box label="挿入..." name="Insert..."/>
+ <menu_bar name="script_menu">
+ <menu label="ファイル" name="File">
+ <menu_item_call label="ä¿å­˜" name="Save"/>
+ <menu_item_call label="変更を元ã«æˆ»ã™" name="Revert All Changes"/>
+ </menu>
+ <menu label="編集" name="Edit">
+ <menu_item_call label="å…ƒã«æˆ»ã™" name="Undo"/>
+ <menu_item_call label="ã‚„ã‚Šç›´ã—" name="Redo"/>
+ <menu_item_call label="切りå–ã‚Š" name="Cut"/>
+ <menu_item_call label="コピー" name="Copy"/>
+ <menu_item_call label="貼り付ã‘" name="Paste"/>
+ <menu_item_call label="ã™ã¹ã¦é¸æŠž" name="Select All"/>
+ <menu_item_call label="é¸æŠžè§£é™¤" name="Deselect"/>
+ <menu_item_call label="検索 / å†é…ç½®..." name="Search / Replace..."/>
+ </menu>
+ <menu label="ヘルプ" name="Help">
+ <menu_item_call label="ヘルプ..." name="Help..."/>
+ <menu_item_call label="キーワードヘルプ..." name="Keyword Help..."/>
+ </menu>
+ </menu_bar>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_scrolling_param.xml b/indra/newview/skins/default/xui/ja/panel_scrolling_param.xml
index b7e334df10..b698fa762d 100644
--- a/indra/newview/skins/default/xui/ja/panel_scrolling_param.xml
+++ b/indra/newview/skins/default/xui/ja/panel_scrolling_param.xml
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="LLScrollingPanelParam">
- <text type="string" length="1" name="Loading...">
+ <text name="Loading...">
ロード中...
</text>
- <text type="string" length="1" name="Loading...2">
+ <text name="Loading...2">
ロード中...
</text>
<button label="" label_selected="" name="less" />
diff --git a/indra/newview/skins/default/xui/ja/panel_side_tray.xml b/indra/newview/skins/default/xui/ja/panel_side_tray.xml
new file mode 100644
index 0000000000..6ec6b3422e
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_side_tray.xml
@@ -0,0 +1,26 @@
+<?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="ホーム。" name="sidebar_home">
+ <panel label="ホーム" name="panel_home"/>
+ </sidetray_tab>
+ <sidetray_tab description="フレンドã€é€£çµ¡å…ˆã€è¿‘ãã®äººã‚’探ã—ã¦ãã ã•ã„。" name="sidebar_people">
+ <panel_container name="panel_container">
+ <panel label="グループ情報" name="panel_group_info_sidetray"/>
+ <panel label="ブロックã•ã‚ŒãŸä½äººã¨ã‚ªãƒ–ジェクト" name="panel_block_list_sidetray"/>
+ </panel_container>
+ </sidetray_tab>
+ <sidetray_tab description="è¡ŒããŸã„場所ã€è¡Œã£ãŸã“ã¨ã®ã‚る場所を探ã—ã¦ãã ã•ã„。" label="場所" name="sidebar_places">
+ <panel label="場所" name="panel_places"/>
+ </sidetray_tab>
+ <sidetray_tab description="ã‚ãªãŸã®å…¬é–‹ãƒ—ロフィールã¨ãƒ”ックを編集ã—ã¦ãã ã•ã„。" name="sidebar_me">
+ <panel label="ミー" name="panel_me"/>
+ </sidetray_tab>
+ <sidetray_tab description="ã‚ãªãŸã®å®¹å§¿ã‚„ç¾åœ¨ã®è¦‹ãŸç›®ã‚’変更ã—ã¦ãã ã•ã„。" name="sidebar_appearance">
+ <panel label="容姿ã®ç·¨é›†" name="sidepanel_appearance"/>
+ </sidetray_tab>
+ <sidetray_tab description="ã‚ãªãŸã®æŒã¡ç‰©ã‚’眺ã‚ã¦ãã ã•ã„。" name="sidebar_inventory">
+ <panel label="æŒã¡ç‰©ã‚’編集" name="sidepanel_inventory"/>
+ </sidetray_tab>
+</side_tray>
diff --git a/indra/newview/skins/default/xui/ja/panel_side_tray_tab_caption.xml b/indra/newview/skins/default/xui/ja/panel_side_tray_tab_caption.xml
new file mode 100644
index 0000000000..8f4a76fd43
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_side_tray_tab_caption.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="sidetray_tab_panel">
+ <text name="sidetray_tab_title" value="サイドパãƒãƒ«"/>
+ <button name="show_help" tool_tip="ヘルプを表示"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_sidetray_home_tab.xml b/indra/newview/skins/default/xui/ja/panel_sidetray_home_tab.xml
new file mode 100644
index 0000000000..aef1f90298
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_sidetray_home_tab.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- Part of side tray, see that XML file for panel config -->
+<panel label="home_tab" name="home_tab">
+ <scroll_container name="profile_scroll">
+ <panel name="profile_scroll_panel">
+ <panel name="sidebar_people">
+ <text name="tab_name" value="人"/>
+ <text name="tab_description">
+ ã‚ãªãŸã®ãƒ•ãƒ¬ãƒ³ãƒ‰ã€ã‚°ãƒ«ãƒ¼ãƒ—ã€é€£çµ¡å…ˆã€è¿‘ãã®äººã‚’探ã—ã¾ã™ã€‚
+ </text>
+ </panel>
+ <panel name="sidebar_places">
+ <text name="tab_name" value="場所"/>
+ <text name="tab_description">
+ è¡ŒããŸã„場所ã€è¡Œã£ãŸã“ã¨ã®ã‚る場所を探ã—ã¾ã™ã€‚
+ </text>
+ </panel>
+ <panel name="sidebar_me">
+ <text name="tab_name" value="マイ プロフィール"/>
+ <text name="tab_description">
+ ã‚ãªãŸã®å…¬é–‹ãƒ—ロフィールを編集ã—ã¾ã™ã€‚
+ </text>
+ </panel>
+ <panel name="sidebar_appearance">
+ <text name="tab_name" value="マイ 容姿"/>
+ <text name="tab_description">
+ ã‚ãªãŸã®å®¹å§¿ã‚„ç¾åœ¨ã®è¦‹ãŸç›®ã‚’変更ã—ã¾ã™ã€‚
+ </text>
+ </panel>
+ <panel name="sidebar_inventory">
+ <text name="tab_name" value="マイ æŒã¡ç‰©"/>
+ <text name="tab_description">
+ ã‚ãªãŸã®æŒã¡ç‰©ã‚’眺ã‚ã¾ã™ã€‚
+ </text>
+ </panel>
+ </panel>
+ </scroll_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_stand_stop_flying.xml b/indra/newview/skins/default/xui/ja/panel_stand_stop_flying.xml
new file mode 100644
index 0000000000..2308aff19b
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_stand_stop_flying.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- Width and height of this panel should be synchronized with "panel_modes" in the floater_moveview.xml-->
+<panel name="panel_stand_stop_flying">
+ <button label="ç«‹ã¡ä¸ŠãŒã‚‹" name="stand_btn" tool_tip="ã“ã“をクリックã—ã¦ç«‹ã¡ä¸ŠãŒã‚Šã¾ã™ã€‚"/>
+ <button label="飛行åœæ­¢" name="stop_fly_btn" tool_tip="飛行åœæ­¢"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_status_bar.xml b/indra/newview/skins/default/xui/ja/panel_status_bar.xml
index 08c66182c4..5d122cb8cd 100644
--- a/indra/newview/skins/default/xui/ja/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/ja/panel_status_bar.xml
@@ -1,42 +1,29 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="status">
- <text length="1" name="ParcelNameText" tool_tip="ã‚ãªãŸãŒç«‹ã£ã¦ã„る土地区画ã®å å‰ã€‚クリックã™ã‚‹ã¨ã€ŒåœŸåœ°æƒ…å ±ã€ãŒé–‹ãã¾ã™ã€‚" type="string">
- 区画åã¯ã“ã“ã§ã™
- </text>
- <text length="1" name="BalanceText" tool_tip="å£åº§æ®‹é«˜" type="string">
- ローディング...
- </text>
- <button label="" label_selected="" name="buycurrency" tool_tip="貨幣ã®è³¼å…¥"/>
- <text length="12" name="TimeText" tool_tip="ç¾åœ¨æ™‚刻(太平洋時)" type="string">
- 12:00 AM
- </text>
- <text name="StatBarDaysOfWeek">
+ <panel.string name="StatBarDaysOfWeek">
日曜日:月曜日:ç«æ›œæ—¥:水曜日:木曜日:金曜日:土曜日
- </text>
- <text name="StatBarMonthsOfYear">
+ </panel.string>
+ <panel.string name="StatBarMonthsOfYear">
1月:2月:3月:4月:5月:6月:7月:8月:9月:10月:11月:12月
- </text>
- <button label="" label_selected="" name="scriptout" tool_tip="スクリプト警告ãŠã‚ˆã³ã‚¨ãƒ©ãƒ¼"/>
- <button label="" label_selected="" name="health" tool_tip="å¥åº·çŠ¶æ…‹"/>
- <text length="1" name="HealthText" tool_tip="å¥åº·çŠ¶æ…‹" type="string">
- 100%
- </text>
- <button label="" label_selected="" name="fly" tool_tip="飛行ç¦æ­¢"/>
- <button label="" label_selected="" name="build" tool_tip="作æˆç¦æ­¢"/>
- <button label="" label_selected="" name="scripts" tool_tip="スクリプトãªã—"/>
- <button name="no_fly" tool_tip="飛行ç¦æ­¢"/>
- <button name="no_build" tool_tip="制作ï¼Rezç¦æ­¢"/>
- <button name="no_scripts" tool_tip="スクリプトç¦æ­¢"/>
- <button label="" label_selected="" name="restrictpush" tool_tip="プッシングを制é™"/>
- <button name="status_voice" tool_tip="ボイス有効"/>
- <button name="status_no_voice" tool_tip="ã“ã“ã§ã¯ãƒœã‚¤ã‚¹ã‚’使用ã§ãã¾ã›ã‚“。"/>
- <button label="" label_selected="" name="buyland" tool_tip="ã“ã®åŒºç”»ã‚’購入"/>
- <text name="packet_loss_tooltip">
+ </panel.string>
+ <panel.string name="packet_loss_tooltip">
パケットæ失
- </text>
- <text name="bandwidth_tooltip">
+ </panel.string>
+ <panel.string name="bandwidth_tooltip">
帯域幅
+ </panel.string>
+ <panel.string name="time">
+ [hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]
+ </panel.string>
+ <panel.string name="timeTooltip">
+ [year, datetime, slt] [month, datetime, slt] [day, datetime, slt] ([weekday, datetime, slt])
+ </panel.string>
+ <panel.string name="buycurrencylabel">
+ L$ [AMT]
+ </panel.string>
+ <button label="" label_selected="" name="buycurrency" tool_tip="ç§ã®æ®‹é«˜ï¼š クリックã—㦠L$ を購入ã—ã¾ã™"/>
+ <text name="TimeText" tool_tip="ç¾åœ¨æ™‚刻(太平洋)">
+ 12:00 AM
</text>
- <line_editor label="検索" name="search_editor" tool_tip="Second Lifeを検索"/>
- <button name="search_btn" tool_tip="Second Lifeを検索"/>
+ <button name="volume_btn" tool_tip="グローãƒãƒ«éŸ³é‡è¨­å®š"/>
</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_sys_well_item.xml b/indra/newview/skins/default/xui/ja/panel_sys_well_item.xml
new file mode 100644
index 0000000000..81db7c8989
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_sys_well_item.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- All our XML is utf-8 encoded. -->
+<panel name="sys_well_item" title="sys_well_item">
+ <text name="title">
+ Beware the trout. BEWARE! THE! TROUT!
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_teleport_history.xml b/indra/newview/skins/default/xui/ja/panel_teleport_history.xml
new file mode 100644
index 0000000000..70969f7ac0
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_teleport_history.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="Teleport History">
+ <accordion name="history_accordion">
+ <accordion_tab name="today" title="今日"/>
+ <accordion_tab name="yesterday" title="昨日"/>
+ <accordion_tab name="2_days_ago" title="2æ—¥å‰"/>
+ <accordion_tab name="3_days_ago" title="3æ—¥å‰"/>
+ <accordion_tab name="4_days_ago" title="4æ—¥å‰"/>
+ <accordion_tab name="5_days_ago" title="5æ—¥å‰"/>
+ <accordion_tab name="6_days_and_older" title="6日以上å‰"/>
+ <accordion_tab name="1_month_and_older" title="1ヶ月以上å‰"/>
+ <accordion_tab name="6_months_and_older" title="åŠå¹´ä»¥ä¸Šå‰"/>
+ </accordion>
+ <panel label="bottom_panel" name="bottom_panel"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_teleport_history_item.xml b/indra/newview/skins/default/xui/ja/panel_teleport_history_item.xml
new file mode 100644
index 0000000000..9d18c52442
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_teleport_history_item.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="teleport_history_item">
+ <text name="region" value="..."/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_world_map.xml b/indra/newview/skins/default/xui/ja/panel_world_map.xml
new file mode 100644
index 0000000000..2f5c2bf6a1
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_world_map.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="world_map">
+ <panel.string name="Loading">
+ ローディング...
+ </panel.string>
+ <panel.string name="InvalidLocation">
+ 無効ãªä½ç½®
+ </panel.string>
+ <panel.string name="world_map_north">
+ 北
+ </panel.string>
+ <panel.string name="world_map_east">
+ æ±
+ </panel.string>
+ <panel.string name="world_map_west">
+ 西
+ </panel.string>
+ <panel.string name="world_map_south">
+ å—
+ </panel.string>
+ <panel.string name="world_map_southeast">
+ å—æ±
+ </panel.string>
+ <panel.string name="world_map_northeast">
+ 北æ±
+ </panel.string>
+ <panel.string name="world_map_southwest">
+ å—西
+ </panel.string>
+ <panel.string name="world_map_northwest">
+ 北西
+ </panel.string>
+ <text label="北" name="floater_map_north" text="北">
+ 北
+ </text>
+ <text label="æ±" name="floater_map_east" text="æ±">
+ æ±
+ </text>
+ <text label="西" name="floater_map_west" text="西">
+ 西
+ </text>
+ <text label="å—" name="floater_map_south" text="å—">
+ å—
+ </text>
+ <text label="å—æ±" name="floater_map_southeast" text="å—æ±">
+ å—æ±
+ </text>
+ <text label="北æ±" name="floater_map_northeast" text="北æ±">
+ 北æ±
+ </text>
+ <text label="å—西" name="floater_map_southwest" text="å—西">
+ å—西
+ </text>
+ <text label="北西" name="floater_map_northwest" text="北西">
+ 北西
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/sidepanel_appearance.xml b/indra/newview/skins/default/xui/ja/sidepanel_appearance.xml
new file mode 100644
index 0000000000..ac41d7ce2b
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/sidepanel_appearance.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="容姿" name="appearance panel">
+ <string name="No Outfit" value="アウトフィットãªã—"/>
+ <panel name="panel_currentlook">
+ <button label="編集" name="editappearance_btn"/>
+ <text name="currentlook_title">
+ ç€ç”¨ä¸­ã®ã‚¢ã‚¦ãƒˆãƒ•ã‚£ãƒƒãƒˆï¼š
+ </text>
+ <text name="currentlook_name">
+ マイ アウトフィット
+ </text>
+ </panel>
+ <filter_editor label="フィルター" name="Filter"/>
+ <button label="装ç€" name="wear_btn"/>
+ <button label="æ–°ã—ã„アウトフィット" name="newlook_btn"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/sidepanel_inventory.xml b/indra/newview/skins/default/xui/ja/sidepanel_inventory.xml
new file mode 100644
index 0000000000..c2a61f738f
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/sidepanel_inventory.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="ã‚‚ã®" name="objects panel">
+ <panel label="" name="sidepanel__inventory_panel">
+ <panel name="button_panel">
+ <button label="情報" name="info_btn"/>
+ <button label="装ç€" name="wear_btn"/>
+ <button label="プレイ" name="play_btn"/>
+ <button label="テレãƒãƒ¼ãƒˆ" name="teleport_btn"/>
+ </panel>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/sidepanel_item_info.xml b/indra/newview/skins/default/xui/ja/sidepanel_item_info.xml
new file mode 100644
index 0000000000..9544e7756c
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/sidepanel_item_info.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="item properties" title="æŒã¡ç‰©ã‚¢ã‚¤ãƒ†ãƒ ã®ãƒ—ロパティ">
+ <panel.string name="unknown">
+ (ä¸æ˜Žï¼‰
+ </panel.string>
+ <panel.string name="public">
+ (公開)
+ </panel.string>
+ <panel.string name="you_can">
+ ã‚ãªãŸãŒã§ãã‚‹ã“ã¨ï¼š
+ </panel.string>
+ <panel.string name="owner_can">
+ 所有者ãŒã§ãã‚‹ã“ã¨ï¼š
+ </panel.string>
+ <panel.string name="acquiredDate">
+ [year,datetime,local] [mth,datetime,local] [day,datetime,local] [wkday,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local]
+ </panel.string>
+ <panel label="">
+ <text name="LabelItemNameTitle">
+ åå‰ï¼š
+ </text>
+ <text name="LabelItemDescTitle">
+ 説明:
+ </text>
+ <text name="LabelCreatorTitle">
+ 制作者:
+ </text>
+ <text name="LabelCreatorName">
+ Nicole Linden
+ </text>
+ <button label="プロフィール..." name="BtnCreator"/>
+ <text name="LabelOwnerTitle">
+ 所有者:
+ </text>
+ <text name="LabelOwnerName">
+ Thrax Linden
+ </text>
+ <button label="プロフィール..." name="BtnOwner"/>
+ <text name="LabelAcquiredTitle">
+ å–得:
+ </text>
+ <text name="LabelAcquiredDate">
+ Wed May 24 12:50:46 2006
+ </text>
+ <text name="OwnerLabel">
+ ã‚ãªãŸï¼š
+ </text>
+ <check_box label="編集" name="CheckOwnerModify"/>
+ <check_box label="コピー" name="CheckOwnerCopy"/>
+ <check_box label="å†è²©ãƒ»ãƒ—レゼント" name="CheckOwnerTransfer"/>
+ <text name="AnyoneLabel">
+ 全員:
+ </text>
+ <check_box label="コピー" name="CheckEveryoneCopy"/>
+ <text name="GroupLabel">
+ グループ:
+ </text>
+ <check_box label="共有" name="CheckShareWithGroup"/>
+ <text name="NextOwnerLabel">
+ 次ã®æ‰€æœ‰è€…:
+ </text>
+ <check_box label="編集" name="CheckNextOwnerModify"/>
+ <check_box label="コピー" name="CheckNextOwnerCopy"/>
+ <check_box label="å†è²©ãƒ»ãƒ—レゼント" name="CheckNextOwnerTransfer"/>
+ <check_box label="販売ã™ã‚‹" name="CheckPurchase"/>
+ <combo_box name="combobox sale copy">
+ <combo_box.item label="コピー" name="Copy"/>
+ <combo_box.item label="オリジナル" name="Original"/>
+ </combo_box>
+ <spinner label="価格:" name="Edit Cost"/>
+ <text name="CurrencySymbol">
+ L$
+ </text>
+ </panel>
+ <panel name="button_panel">
+ <button label="編集" name="edit_btn"/>
+ <button label="キャンセル" name="cancel_btn"/>
+ <button label="ä¿å­˜" name="save_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/sidepanel_task_info.xml b/indra/newview/skins/default/xui/ja/sidepanel_task_info.xml
new file mode 100644
index 0000000000..5bf37954c5
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/sidepanel_task_info.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="object properties" title="オブジェクトã®ãƒ—ロパティ">
+ <panel.string name="text deed continued">
+ 譲渡
+ </panel.string>
+ <panel.string name="text deed">
+ 譲渡
+ </panel.string>
+ <panel.string name="text modify info 1">
+ ã“ã®ã‚ªãƒ–ジェクトを修正ã§ãã¾ã™
+ </panel.string>
+ <panel.string name="text modify info 2">
+ ã“れらã®ã‚ªãƒ–ジェクトを修正ã§ãã¾ã™
+ </panel.string>
+ <panel.string name="text modify info 3">
+ ã“ã®ã‚ªãƒ–ジェクトを修正ã§ãã¾ã›ã‚“
+ </panel.string>
+ <panel.string name="text modify info 4">
+ ã“れらã®ã‚ªãƒ–ジェクトを修正ã§ãã¾ã›ã‚“
+ </panel.string>
+ <panel.string name="text modify warning">
+ ã“ã®ã‚ªãƒ–ジェクトã«ã¯ã€ãƒ‘ーツãŒãƒªãƒ³ã‚¯ã•ã‚Œã¦ã„ã¾ã™
+ </panel.string>
+ <panel.string name="Cost Default">
+ 価格: L$
+ </panel.string>
+ <panel.string name="Cost Total">
+ åˆè¨ˆï¼š L$
+ </panel.string>
+ <panel.string name="Cost Per Unit">
+ Price Per: L$
+ </panel.string>
+ <panel.string name="Cost Mixed">
+ Mixed Price
+ </panel.string>
+ <panel.string name="Sale Mixed">
+ Mixed Sale
+ </panel.string>
+ <panel label="">
+ <text name="Name:">
+ åå‰ï¼š
+ </text>
+ <text name="Description:">
+ 説明:
+ </text>
+ <text name="Creator:">
+ 制作者:
+ </text>
+ <text name="Creator Name">
+ Esbee Linden
+ </text>
+ <text name="Owner:">
+ 所有者:
+ </text>
+ <text name="Owner Name">
+ Erica Linden
+ </text>
+ <text name="Group:">
+ グループ:
+ </text>
+ <button name="button set group" tool_tip="ã“ã®ã‚ªãƒ–ジェクト権é™ã‚’共有ã™ã‚‹ã‚°ãƒ«ãƒ¼ãƒ—ã‚’é¸æŠž"/>
+ <name_box initial_value="ローディング..." name="Group Name Proxy"/>
+ <button label="譲渡" label_selected="譲渡" name="button deed" tool_tip="ã“ã®ã‚¢ã‚¤ãƒ†ãƒ ã‚’譲渡ã™ã‚‹ã¨ã€Œæ¬¡ã®æ‰€æœ‰è€…ã€ã®æ¨©é™ãŒé©ç”¨ã•ã‚Œã¾ã™ã€‚ グループ共有オブジェクトã¯ã€ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚ªãƒ•ã‚£ã‚µãƒ¼ãŒè­²æ¸¡ã§ãã¾ã™ã€‚"/>
+ <check_box label="共有" name="checkbox share with group" tool_tip="設定ã—ãŸã‚°ãƒ«ãƒ¼ãƒ—ã®ãƒ¡ãƒ³ãƒãƒ¼å…¨å“¡ã«ã“ã®ã‚ªãƒ–ジェクトã®ä¿®æ­£æ¨©é™ã‚’与ãˆã¾ã™ã€‚ 譲渡ã—ãªã„é™ã‚Šã€å½¹å‰²åˆ¶é™ã‚’有効ã«ã¯ã§ãã¾ã›ã‚“。"/>
+ <text name="label click action">
+ クリックã§ï¼š
+ </text>
+ <combo_box name="clickaction">
+ <combo_box.item label="触る(デフォルト)" name="Touch/grab(default)"/>
+ <combo_box.item label="オブジェクトã«åº§ã‚‹" name="Sitonobject"/>
+ <combo_box.item label="オブジェクトを買ã†" name="Buyobject"/>
+ <combo_box.item label="オブジェクトã«æ”¯æ‰•ã†" name="Payobject"/>
+ <combo_box.item label="é–‹ã" name="Open"/>
+ </combo_box>
+ <check_box label="販売対象:" name="checkbox for sale"/>
+ <combo_box name="sale type">
+ <combo_box.item label="コピー" name="Copy"/>
+ <combo_box.item label="中身" name="Contents"/>
+ <combo_box.item label="オリジナル" name="Original"/>
+ </combo_box>
+ <spinner label="価格: L$" name="Edit Cost"/>
+ <check_box label="検索ã«è¡¨ç¤º" name="search_check" tool_tip="ã“ã®ã‚ªãƒ–ジェクトを検索çµæžœã«è¡¨ç¤ºã—ã¾ã™"/>
+ <panel name="perms_build">
+ <text name="perm_modify">
+ ã‚ãªãŸã¯ã“ã®ã‚ªãƒ–ジェクトを修正ã§ãã¾ã™
+ </text>
+ <text name="Anyone can:">
+ 全員:
+ </text>
+ <check_box label="移動" name="checkbox allow everyone move"/>
+ <check_box label="コピー" name="checkbox allow everyone copy"/>
+ <text name="Next owner can:">
+ 次ã®æ‰€æœ‰è€…:
+ </text>
+ <check_box label="修正" name="checkbox next owner can modify"/>
+ <check_box label="コピー" name="checkbox next owner can copy"/>
+ <check_box label="å†è²©ãƒ»ãƒ—レゼント" name="checkbox next owner can transfer" tool_tip="次ã®æ‰€æœ‰è€…ã¯ã“ã®ã‚ªãƒ–ジェクトを他人ã«ã‚ã’ãŸã‚Šå†è²©ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™"/>
+ <text name="B:">
+ B.
+ </text>
+ <text name="O:">
+ O:
+ </text>
+ <text name="G:">
+ G:
+ </text>
+ <text name="E:">
+ E:
+ </text>
+ <text name="N:">
+ N:
+ </text>
+ <text name="F:">
+ F:
+ </text>
+ </panel>
+ </panel>
+ <panel name="button_panel">
+ <button label="編集" name="edit_btn"/>
+ <button label="é–‹ã" name="open_btn"/>
+ <button label="支払ã†" name="pay_btn"/>
+ <button label="è²·ã†" name="buy_btn"/>
+ <button label="キャンセル" name="cancel_btn"/>
+ <button label="ä¿å­˜" name="save_btn"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml
index 5432c116a7..2006d1cbdc 100644
--- a/indra/newview/skins/default/xui/ja/strings.xml
+++ b/indra/newview/skins/default/xui/ja/strings.xml
@@ -1,12 +1,36 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- This file contains strings that used to be hardcoded in the source.
It is only for those strings which do not belong in a floater.
- For example, the strings used in avatar chat bubbles, and strings
+ For example, the strings used in avatar chat bubbles, and strings
that are returned from one component and may appear in many places-->
<strings>
+ <string name="SECOND_LIFE">
+ Second Life
+ </string>
+ <string name="APP_NAME">
+ Second Life
+ </string>
+ <string name="SECOND_LIFE_GRID">
+ Second Life Grid
+ </string>
+ <string name="SUPPORT_SITE">
+ Second Life サãƒãƒ¼ãƒˆãƒãƒ¼ã‚¿ãƒ«
+ </string>
+ <string name="StartupDetectingHardware">
+ ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã®æ¤œå‡ºä¸­ã§ã™...
+ </string>
+ <string name="StartupLoading">
+ ローディング
+ </string>
+ <string name="Fullbright">
+ 明るã•å…¨é–‹ï¼ˆãƒ¬ã‚¬ã‚·ãƒ¼ï¼‰
+ </string>
<string name="LoginInProgress">
ログイン中ã§ã™ã€‚[APP_NAME]ã®è¡¨ç¤ºãŒãƒ•ãƒªãƒ¼ã‚ºã™ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚ ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„。
</string>
+ <string name="LoginInProgressNoFrozen">
+ ログイン中ã§ã™...
+ </string>
<string name="LoginAuthenticating">
èªè¨¼ã—ã¦ã„ã¾ã™...
</string>
@@ -55,8 +79,14 @@
<string name="LoginDownloadingClothing">
æœã‚’ダウンロードã—ã¦ã„ã¾ã™...
</string>
+ <string name="Quit">
+ 終了
+ </string>
+ <string name="create_account_url">
+ http://join.secondlife.com/index.php?lang=ja-JP
+ </string>
<string name="AgentLostConnection">
- ã“ã®åœ°åŸŸã«ã¯ã€å•é¡ŒãŒç™ºç”Ÿã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ インターãƒãƒƒãƒˆæŽ¥ç¶šã‚’確èªã—ã¦ãã ã•ã„。
+ ã“ã®ãƒªãƒ¼ã‚¸ãƒ§ãƒ³ã«ä¸éƒ½åˆãŒç™ºç”Ÿã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ ã”使用ã®ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆæŽ¥ç¶šã‚’ã”確èªãã ã•ã„。
</string>
<string name="TooltipPerson">
人
@@ -73,39 +103,9 @@
<string name="TooltipIsGroup">
(グループ)
</string>
- <string name="TooltipFlagScript">
- スクリプト
- </string>
- <string name="TooltipFlagPhysics">
- 物ç†ä½œç”¨
- </string>
- <string name="TooltipFlagTouch">
- 触る
- </string>
- <string name="TooltipFlagL$">
- L$
- </string>
- <string name="TooltipFlagDropInventory">
- æŒã¡ç‰©ã‚’ドロップã™ã‚‹
- </string>
- <string name="TooltipFlagPhantom">
- ファントム
- </string>
- <string name="TooltipFlagTemporary">
- 一時的
- </string>
- <string name="TooltipFlagRightClickMenu">
- (å³ã‚¯ãƒªãƒƒã‚¯ã§ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‚’表示)
- </string>
- <string name="TooltipFreeToCopy">
- コピーå¯èƒ½
- </string>
<string name="TooltipForSaleL$">
売り出ã—中:L$[AMOUNT]
</string>
- <string name="TooltipForSaleMsg">
- 売り出ã—中: [MESSAGE]
- </string>
<string name="TooltipFlagGroupBuild">
グループ作æˆ
</string>
@@ -133,71 +133,216 @@
<string name="TooltipMustSingleDrop">
1ã¤ã®ã‚¢ã‚¤ãƒ†ãƒ ã®ã¿ã‚’ã“ã“ã«ãƒ‰ãƒ©ãƒƒã‚°ã§ãã¾ã™
</string>
- <string name="RetrievingData">
+ <string name="TooltipHttpUrl">
+ クリックã—ã¦ã“ã®Webページを見る
+ </string>
+ <string name="TooltipSLURL">
+ クリックã—ã¦ã“ã®å ´æ‰€ã®æƒ…報を見る
+ </string>
+ <string name="TooltipAgentUrl">
+ クリックã—ã¦ã“ã®ä½äººã®ãƒ—ロフィールを見る
+ </string>
+ <string name="TooltipGroupUrl">
+ クリックã—ã¦ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã®èª¬æ˜Žæ–‡ã‚’見る
+ </string>
+ <string name="TooltipEventUrl">
+ クリックã—ã¦ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã®èª¬æ˜Žæ–‡ã‚’見る
+ </string>
+ <string name="TooltipClassifiedUrl">
+ クリックã—ã¦ã“ã®ã‚¯ãƒ©ã‚·ãƒ•ã‚¡ã‚¤ãƒ‰åºƒå‘Šã‚’見る
+ </string>
+ <string name="TooltipParcelUrl">
+ クリックã—ã¦ã“ã®åŒºç”»ã®èª¬æ˜Žæ–‡ã‚’見る
+ </string>
+ <string name="TooltipTeleportUrl">
+ クリックã—ã¦ã“ã®å ´æ‰€ã«ãƒ†ãƒ¬ãƒãƒ¼ãƒˆã™ã‚‹
+ </string>
+ <string name="TooltipObjectIMUrl">
+ クリックã—ã¦ã“ã®ã‚ªãƒ–ジェクトã®èª¬æ˜Žæ–‡ã‚’見る
+ </string>
+ <string name="TooltipMapUrl">
+ クリックã—ã¦ã“ã®å ´æ‰€ã‚’地図ã«è¡¨ç¤ºã™ã‚‹
+ </string>
+ <string name="TooltipSLAPP">
+ クリックã—㦠secondlife:// コマンドを出ã™
+ </string>
+ <string name="CurrentURL" value=" ç¾åœ¨ã®URL: [CurrentURL]"/>
+ <string name="SLurlLabelTeleport">
+ テレãƒãƒ¼ãƒˆ
+ </string>
+ <string name="SLurlLabelShowOnMap">
+ 地図ã«è¡¨ç¤º
+ </string>
+ <string name="BUTTON_CLOSE_DARWIN">
+ é–‰ã˜ã‚‹ (&#8984;W)
+ </string>
+ <string name="BUTTON_CLOSE_WIN">
+ é–‰ã˜ã‚‹ (Ctrl+W)
+ </string>
+ <string name="BUTTON_RESTORE">
+ 復元
+ </string>
+ <string name="BUTTON_MINIMIZE">
+ å…ƒã«æˆ»ã™ï¼ˆç¸®å°ï¼‰
+ </string>
+ <string name="BUTTON_TEAR_OFF">
+ 別ウィンドウã§é–‹ã
+ </string>
+ <string name="BUTTON_DOCK">
+ ドッキング
+ </string>
+ <string name="BUTTON_UNDOCK">
+ 切り離ã™
+ </string>
+ <string name="BUTTON_HELP">
+ ヘルプを表示
+ </string>
+ <string name="Searching">
検索中...
</string>
+ <string name="NoneFound">
+ 見ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚
+ </string>
+ <string name="RetrievingData">
+ å–得中...
+ </string>
<string name="ReleaseNotes">
リリースノート
</string>
<string name="LoadingData">
- ロード中...
+ ローディング...
</string>
<string name="AvatarNameNobody">
- (無人)
+ (ãªã—)
</string>
<string name="AvatarNameWaiting">
- (待機中)
+ (待機中)
+ </string>
+ <string name="AvatarNameMultiple">
+ (複数)
</string>
<string name="AvatarNameHippos">
- (ã‚«ãƒ)
+ (hippos)
</string>
<string name="GroupNameNone">
- (ãªã—)
+ (ãªã—)
</string>
<string name="AssetErrorNone">
エラーãªã—
</string>
<string name="AssetErrorRequestFailed">
- 資産ã®è¦æ±‚: 失敗
+ アセットリクエスト: 失敗
</string>
<string name="AssetErrorNonexistentFile">
- 資産ã®è¦æ±‚: 存在ã—ãªã„ファイル
+ アセットリクエスト: 存在ã—ãªã„ファイル
</string>
<string name="AssetErrorNotInDatabase">
- 資産ã®è¦æ±‚: データベースã§ã¯è¦‹ã¤ã‹ã‚‰ãªã„資産
+ アセットリクエスト: データベースã«è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ
</string>
<string name="AssetErrorEOF">
- ファイルã®çµ‚ã‚ã‚Š
+ 終了
</string>
<string name="AssetErrorCannotOpenFile">
- ファイルを開ãã“ã¨ãŒã§ãã¾ã›ã‚“
+ ファイルを開ã‘ã¾ã›ã‚“
</string>
<string name="AssetErrorFileNotFound">
ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“
</string>
<string name="AssetErrorTCPTimeout">
- ファイル転é€ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã§ã™
+ ファイルã®è»¢é€ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆ
</string>
<string name="AssetErrorCircuitGone">
- 接続ãŒè§£é™¤ã•ã‚Œã¾ã—ãŸ
+ サーキットエラー
</string>
<string name="AssetErrorPriceMismatch">
ビューワã¨ã‚µãƒ¼ãƒãƒ¼ã®ä¾¡æ ¼ãŒä¸€è‡´ã—ã¦ã„ã¾ã›ã‚“
</string>
<string name="AssetErrorUnknownStatus">
- ステータスãŒä¸æ˜Žã§ã™
+ ä¸æ˜Žã®ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹
+ </string>
+ <string name="texture">
+ テクスãƒãƒ£
+ </string>
+ <string name="sound">
+ サウンド
+ </string>
+ <string name="calling card">
+ コーリングカード
+ </string>
+ <string name="landmark">
+ ランドマーク
+ </string>
+ <string name="legacy script">
+ レガシースクリプト
+ </string>
+ <string name="clothing">
+ 衣類
+ </string>
+ <string name="object">
+ オブジェクト
+ </string>
+ <string name="note card">
+ ノートカード
</string>
- <string name="AvatarEditingApparance">
- (容姿ã®ç·¨é›†)
+ <string name="folder">
+ フォルダ
+ </string>
+ <string name="root">
+ ルート
+ </string>
+ <string name="lsl2 script">
+ LSL2 スクリプト
+ </string>
+ <string name="lsl bytecode">
+ LSL ãƒã‚¤ãƒˆã‚³ãƒ¼ãƒ‰
+ </string>
+ <string name="tga texture">
+ tga テクスãƒãƒ£
+ </string>
+ <string name="body part">
+ 身体部ä½
+ </string>
+ <string name="snapshot">
+ スナップショット
+ </string>
+ <string name="lost and found">
+ 紛失物
+ </string>
+ <string name="targa image">
+ targa ç”»åƒ
+ </string>
+ <string name="trash">
+ ã”ã¿ç®±
+ </string>
+ <string name="jpeg image">
+ jpeg ç”»åƒ
+ </string>
+ <string name="animation">
+ アニメーション
+ </string>
+ <string name="gesture">
+ ジェスãƒãƒ£ãƒ¼
+ </string>
+ <string name="simstate">
+ 統計
+ </string>
+ <string name="favorite">
+ ãŠæ°—ã«å…¥ã‚Š
+ </string>
+ <string name="symbolic link">
+ リンク
+ </string>
+ <string name="AvatarEditingAppearance">
+ (容姿ã®ç·¨é›†ï¼‰
</string>
<string name="AvatarAway">
- 退席中
+ 一時退席中
</string>
<string name="AvatarBusy">
å–ã‚Šè¾¼ã¿ä¸­
</string>
<string name="AvatarMuted">
- ミュート
+ ブロック中
</string>
<string name="anim_express_afraid">
怖れ
@@ -407,17 +552,80 @@
é ·ã
</string>
<string name="texture_loading">
- ロード中...
+ ローディング...
</string>
<string name="worldmap_offline">
オフライン
</string>
+ <string name="worldmap_results_none_found">
+ 見ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚
+ </string>
+ <string name="Ok">
+ OK
+ </string>
+ <string name="Premature end of file">
+ ä¸å®Œå…¨ãªãƒ•ã‚¡ã‚¤ãƒ«
+ </string>
+ <string name="ST_NO_JOINT">
+ ROOT ã¾ãŸã¯ JOINT ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“
+ </string>
<string name="whisper">
ã®ã•ã•ã‚„ã:
</string>
<string name="shout">
ã®å«ã³:
</string>
+ <string name="ringing">
+ インワールドボイスãƒãƒ£ãƒƒãƒˆã«æŽ¥ç¶šä¸­...
+ </string>
+ <string name="connected">
+ 接続ã—ã¾ã—ãŸ
+ </string>
+ <string name="unavailable">
+ ã‚ãªãŸã®ç¾åœ¨ã®ãƒ­ã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã§ã¯ã€ãƒœã‚¤ã‚¹ã‚’利用ã§ãã¾ã›ã‚“。
+ </string>
+ <string name="hang_up">
+ インワールドボイスãƒãƒ£ãƒƒãƒˆã®é€šè©±ãŒåˆ‡æ–­ã•ã‚Œã¾ã—ãŸ
+ </string>
+ <string name="ScriptQuestionCautionChatGranted">
+ [REGIONNAME]ã®[REGIONPOS]ã¨ã„ã†å ´æ‰€ã«ã‚る「[OWNERNAME]ã€æ‰€æœ‰ã®ã€Œ[OBJECTNAME]ã€ã¨ã„ã†ã‚ªãƒ–ジェクトã¯ã€æ¬¡ã®æ¨©é™ã‚’許å¯ã—ã¾ã—ãŸï¼š [PERMISSIONS]
+ </string>
+ <string name="ScriptQuestionCautionChatDenied">
+ [REGIONNAME]ã®[REGIONPOS]ã¨ã„ã†å ´æ‰€ã«ã‚る「[OWNERNAME]ã€æ‰€æœ‰ã®ã€Œ[OBJECTNAME]ã€ã¨ã„ã†ã‚ªãƒ–ジェクトã¯ã€æ¬¡ã®æ¨©é™ã‚’æ‹’å¦ã—ã¾ã—ãŸï¼š [PERMISSIONS]
+ </string>
+ <string name="ScriptTakeMoney">
+ リンデンドル(L$)を支払ã†
+ </string>
+ <string name="ActOnControlInputs">
+ 制御入力ã«åŸºã¥ã„ã¦è¡Œå‹•
+ </string>
+ <string name="RemapControlInputs">
+ 制御入力ã®ãƒªãƒžãƒƒãƒ—
+ </string>
+ <string name="AnimateYourAvatar">
+ ã‚¢ãƒã‚¿ãƒ¼ã¸ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³å‹•ä½œ
+ </string>
+ <string name="AttachToYourAvatar">
+ ã‚¢ãƒã‚¿ãƒ¼ã«è£…ç€
+ </string>
+ <string name="ReleaseOwnership">
+ 所有権を解放ã—å…¬ã®ã‚‚ã®ã¨ã™ã‚‹
+ </string>
+ <string name="LinkAndDelink">
+ ä»–ã®ã‚ªãƒ–ジェクトã®ãƒªãƒ³ã‚¯ã¨ãƒªãƒ³ã‚¯è§£é™¤
+ </string>
+ <string name="AddAndRemoveJoints">
+ ä»–ã®ã‚ªãƒ–ジェクトã¨ã®ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã®è¿½åŠ ã¨å‰Šé™¤
+ </string>
+ <string name="ChangePermissions">
+ 権é™ã®å¤‰æ›´
+ </string>
+ <string name="TrackYourCamera">
+ カメラ追従
+ </string>
+ <string name="ControlYourCamera">
+ カメラã®ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«
+ </string>
<string name="SIM_ACCESS_PG">
PG
</string>
@@ -436,12 +644,6 @@
<string name="land_type_unknown">
(ä¸æ˜Žï¼‰
</string>
- <string name="covenant_never_modified">
- 最終修正: (無)
- </string>
- <string name="covenant_modified">
- 最終修正:
- </string>
<string name="all_files">
å…¨ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ«
</string>
@@ -487,4 +689,2432 @@
<string name="choose_the_directory">
å‚ç…§
</string>
+ <string name="AvatarSetNotAway">
+ 一時退席中解除
+ </string>
+ <string name="AvatarSetAway">
+ 一時退席中
+ </string>
+ <string name="AvatarSetNotBusy">
+ å–ã‚Šè¾¼ã¿ä¸­è§£é™¤
+ </string>
+ <string name="AvatarSetBusy">
+ å–ã‚Šè¾¼ã¿ä¸­
+ </string>
+ <string name="shape">
+ シェイプ
+ </string>
+ <string name="skin">
+ スキン
+ </string>
+ <string name="hair">
+ 髪
+ </string>
+ <string name="eyes">
+ ç›®
+ </string>
+ <string name="shirt">
+ シャツ
+ </string>
+ <string name="pants">
+ パンツ
+ </string>
+ <string name="shoes">
+ é´
+ </string>
+ <string name="socks">
+ é´ä¸‹
+ </string>
+ <string name="jacket">
+ ジャケット
+ </string>
+ <string name="gloves">
+ 手袋
+ </string>
+ <string name="undershirt">
+ 下ç€ã‚·ãƒ£ãƒ„
+ </string>
+ <string name="underpants">
+ 下ç€ãƒ‘ンツ
+ </string>
+ <string name="skirt">
+ スカート
+ </string>
+ <string name="alpha">
+ アルファ
+ </string>
+ <string name="tattoo">
+ タトゥ
+ </string>
+ <string name="invalid">
+ 無効
+ </string>
+ <string name="next">
+ 次ã¸
+ </string>
+ <string name="ok">
+ OK
+ </string>
+ <string name="GroupNotifyGroupNotice">
+ グループ通知
+ </string>
+ <string name="GroupNotifyGroupNotices">
+ グループ通知
+ </string>
+ <string name="GroupNotifySentBy">
+ é€ä¿¡è€…
+ </string>
+ <string name="GroupNotifyAttached">
+ 添付:
+ </string>
+ <string name="GroupNotifyViewPastNotices">
+ ã“ã“ã§éŽåŽ»ã®é€šçŸ¥ã‚’表示ã™ã‚‹ã‹ã€ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’å—ã‘å–らãªã„設定をã—ã¾ã™ã€‚
+ </string>
+ <string name="GroupNotifyOpenAttachment">
+ 添付アイテムを開ã
+ </string>
+ <string name="GroupNotifySaveAttachment">
+ 添付アイテムをä¿å­˜
+ </string>
+ <string name="TeleportOffer">
+ テレãƒãƒ¼ãƒˆã‚’渡ã™
+ </string>
+ <string name="StartUpNotifications">
+ ä¸åœ¨ä¸­ã«æ–°ã—ã„通知ãŒå±Šãã¾ã—ãŸã€‚
+ </string>
+ <string name="OverflowInfoChannelString">
+ You have %d more notification
+ </string>
+ <string name="BodyPartsRightArm">
+ å³è…•
+ </string>
+ <string name="BodyPartsHead">
+ é ­
+ </string>
+ <string name="BodyPartsLeftArm">
+ 左腕
+ </string>
+ <string name="BodyPartsLeftLeg">
+ 左脚
+ </string>
+ <string name="BodyPartsTorso">
+ é ­
+ </string>
+ <string name="BodyPartsRightLeg">
+ å³è„š
+ </string>
+ <string name="GraphicsQualityLow">
+ 低
+ </string>
+ <string name="GraphicsQualityMid">
+ 中
+ </string>
+ <string name="GraphicsQualityHigh">
+ 高
+ </string>
+ <string name="LeaveMouselook">
+ ESC キーを押ã—ã¦ãƒ¯ãƒ¼ãƒ«ãƒ‰ãƒ“ューã«æˆ»ã‚‹
+ </string>
+ <string name="InventoryNoMatchingItems">
+ 一致ã™ã‚‹ã‚¢ã‚¤ãƒ†ãƒ ãŒæŒã¡ç‰©ã«ã‚ã‚Šã¾ã›ã‚“ã§ã—ãŸ
+ </string>
+ <string name="InventoryNoTexture">
+ æŒã¡ç‰©å†…ã«ã“ã®ãƒ†ã‚¯ã‚¹ãƒãƒ£ã®ã‚³ãƒ”ーãŒã‚ã‚Šã¾ã›ã‚“
+ </string>
+ <string name="no_transfer" value=" (å†è²©/プレゼントä¸å¯ï¼‰"/>
+ <string name="no_modify" value=" (編集ä¸å¯ï¼‰"/>
+ <string name="no_copy" value=" (コピーä¸å¯ï¼‰"/>
+ <string name="worn" value=" (ç€ç”¨ä¸­ï¼‰"/>
+ <string name="link" value=" (リンク)"/>
+ <string name="broken_link" value=" (壊れãŸãƒªãƒ³ã‚¯ï¼‰"/>
+ <string name="LoadingContents">
+ コンテンツをロード中ã§ã™...
+ </string>
+ <string name="NoContents">
+ コンテンツãªã—
+ </string>
+ <string name="WornOnAttachmentPoint" value=" ([ATTACHMENT_POINT] ã«è£…ç€ä¸­ï¼‰"/>
+ <string name="PermYes">
+ ã¯ã„
+ </string>
+ <string name="PermNo">
+ ã„ã„ãˆ
+ </string>
+ <string name="Chat" value=" ãƒãƒ£ãƒƒãƒˆï¼š"/>
+ <string name="Sound" value=" サウンド:"/>
+ <string name="Wait" value=" --- 待機::"/>
+ <string name="AnimFlagStop" value=" アニメーションをåœæ­¢ï¼š"/>
+ <string name="AnimFlagStart" value=" アニメーションを開始:"/>
+ <string name="Wave" value=" 手を振る"/>
+ <string name="HelloAvatar" value=" ã‚„ã‚ã€ã‚¢ãƒã‚¿ãƒ¼ï¼"/>
+ <string name="ViewAllGestures" value=" ã™ã¹ã¦è¡¨ç¤º &gt;&gt;"/>
+ <string name="Animations" value="アニメーションã€"/>
+ <string name="Calling Cards" value="コーリングカードã€"/>
+ <string name="Clothing" value="衣類ã€"/>
+ <string name="Gestures" value="ジェスãƒãƒ£ãƒ¼ã€"/>
+ <string name="Landmarks" value="ランドマークã€"/>
+ <string name="Notecards" value="ノートカードã€"/>
+ <string name="Objects" value="オブジェクトã€"/>
+ <string name="Scripts" value="スクリプトã€"/>
+ <string name="Sounds" value="サウンドã€"/>
+ <string name="Textures" value="テクスãƒãƒ£ã€"/>
+ <string name="Snapshots" value="スナップショットã€"/>
+ <string name="No Filters" value="ã„ã„㈠"/>
+ <string name="Since Logoff" value=" - ログオフ以æ¥"/>
+ <string name="InvFolder My Inventory">
+ マイ æŒã¡ç‰©
+ </string>
+ <string name="InvFolder My Favorites">
+ ãŠæ°—ã«å…¥ã‚Š
+ </string>
+ <string name="InvFolder Library">
+ ライブラリ
+ </string>
+ <string name="InvFolder Textures">
+ テクスãƒãƒ£
+ </string>
+ <string name="InvFolder Sounds">
+ サウンド
+ </string>
+ <string name="InvFolder Calling Cards">
+ コーリングカード
+ </string>
+ <string name="InvFolder Landmarks">
+ ランドマーク
+ </string>
+ <string name="InvFolder Scripts">
+ スクリプト
+ </string>
+ <string name="InvFolder Clothing">
+ 衣類
+ </string>
+ <string name="InvFolder Objects">
+ オブジェクト
+ </string>
+ <string name="InvFolder Notecards">
+ ノートカード
+ </string>
+ <string name="InvFolder New Folder">
+ æ–°è¦ãƒ•ã‚©ãƒ«ãƒ€
+ </string>
+ <string name="InvFolder Inventory">
+ インベントリ
+ </string>
+ <string name="InvFolder Uncompressed Images">
+ 圧縮ã•ã‚Œã¦ã„ãªã„ç”»åƒ
+ </string>
+ <string name="InvFolder Body Parts">
+ 身体部ä½
+ </string>
+ <string name="InvFolder Trash">
+ ã”ã¿ç®±
+ </string>
+ <string name="InvFolder Photo Album">
+ フォトアルãƒãƒ 
+ </string>
+ <string name="InvFolder Lost And Found">
+ 紛失物
+ </string>
+ <string name="InvFolder Uncompressed Sounds">
+ 圧縮ã•ã‚Œã¦ã„ãªã„サウンド
+ </string>
+ <string name="InvFolder Animations">
+ アニメーション
+ </string>
+ <string name="InvFolder Gestures">
+ ジェスãƒãƒ£ãƒ¼
+ </string>
+ <string name="InvFolder favorite">
+ ãŠæ°—ã«å…¥ã‚Š
+ </string>
+ <string name="InvFolder Current Outfit">
+ ç€ç”¨ä¸­ã®ã‚¢ã‚¦ãƒˆãƒ•ã‚£ãƒƒãƒˆ
+ </string>
+ <string name="InvFolder My Outfits">
+ マイ アウトフィット
+ </string>
+ <string name="InvFolder Friends">
+ フレンド
+ </string>
+ <string name="InvFolder All">
+ 全員
+ </string>
+ <string name="Buy">
+ è²·ã†
+ </string>
+ <string name="BuyforL$">
+ Buy for L$
+ </string>
+ <string name="Stone">
+ 石
+ </string>
+ <string name="Metal">
+ 金属
+ </string>
+ <string name="Glass">
+ ガラス
+ </string>
+ <string name="Wood">
+ 木
+ </string>
+ <string name="Flesh">
+ 肌
+ </string>
+ <string name="Plastic">
+ プラスãƒãƒƒã‚¯
+ </string>
+ <string name="Rubber">
+ ゴム
+ </string>
+ <string name="Light">
+ ライト
+ </string>
+ <string name="KBShift">
+ Shift
+ </string>
+ <string name="KBCtrl">
+ Ctrl
+ </string>
+ <string name="Chest">
+ 胸部
+ </string>
+ <string name="Skull">
+ é ­è“‹
+ </string>
+ <string name="Left Shoulder">
+ 左肩
+ </string>
+ <string name="Right Shoulder">
+ å³è‚©
+ </string>
+ <string name="Left Hand">
+ 左手
+ </string>
+ <string name="Right Hand">
+ å³æ‰‹
+ </string>
+ <string name="Left Foot">
+ 左足
+ </string>
+ <string name="Right Foot">
+ å³è¶³
+ </string>
+ <string name="Spine">
+ 背骨
+ </string>
+ <string name="Pelvis">
+ 骨盤
+ </string>
+ <string name="Mouth">
+ å£
+ </string>
+ <string name="Chin">
+ ã‚ã”
+ </string>
+ <string name="Left Ear">
+ 左耳
+ </string>
+ <string name="Right Ear">
+ å³è€³
+ </string>
+ <string name="Left Eyeball">
+ 左目眼çƒ
+ </string>
+ <string name="Right Eyeball">
+ å³ç›®çœ¼çƒ
+ </string>
+ <string name="Nose">
+ é¼»
+ </string>
+ <string name="R Upper Arm">
+ å³ä¸Šè…•
+ </string>
+ <string name="R Forearm">
+ å³å‰è…•
+ </string>
+ <string name="L Upper Arm">
+ 左上腕
+ </string>
+ <string name="L Forearm">
+ å·¦å‰è…•
+ </string>
+ <string name="Right Hip">
+ å³è…°
+ </string>
+ <string name="R Upper Leg">
+ å³ä¸Šè„š
+ </string>
+ <string name="R Lower Leg">
+ å³ä¸‹è„š
+ </string>
+ <string name="Left Hip">
+ 左腰
+ </string>
+ <string name="L Upper Leg">
+ 左上脚
+ </string>
+ <string name="L Lower Leg">
+ 左下脚
+ </string>
+ <string name="Stomach">
+ è…¹
+ </string>
+ <string name="Left Pec">
+ 左胸筋
+ </string>
+ <string name="Right Pec">
+ å³èƒ¸ç­‹
+ </string>
+ <string name="YearsMonthsOld">
+ [AGEYEARS] [AGEMONTHS]
+ </string>
+ <string name="YearsOld">
+ [AGEYEARS]
+ </string>
+ <string name="MonthsOld">
+ [AGEMONTHS]
+ </string>
+ <string name="WeeksOld">
+ [AGEWEEKS]
+ </string>
+ <string name="DaysOld">
+ [AGEDAYS]
+ </string>
+ <string name="TodayOld">
+ 今日å‚加
+ </string>
+ <string name="AgeYearsA">
+ [COUNT] å¹´
+ </string>
+ <string name="AgeYearsB">
+ [COUNT] å¹´
+ </string>
+ <string name="AgeYearsC">
+ [COUNT] å¹´
+ </string>
+ <string name="AgeMonthsA">
+ [COUNT] ヶ月
+ </string>
+ <string name="AgeMonthsB">
+ [COUNT] ヶ月
+ </string>
+ <string name="AgeMonthsC">
+ [COUNT] ヶ月
+ </string>
+ <string name="AgeWeeksA">
+ [COUNT] 週間
+ </string>
+ <string name="AgeWeeksB">
+ [COUNT] 週間
+ </string>
+ <string name="AgeWeeksC">
+ [COUNT] 週間
+ </string>
+ <string name="AgeDaysA">
+ [COUNT] 日間
+ </string>
+ <string name="AgeDaysB">
+ [COUNT] 日間
+ </string>
+ <string name="AgeDaysC">
+ [COUNT] 日間
+ </string>
+ <string name="GroupMembersA">
+ [COUNT] 人
+ </string>
+ <string name="GroupMembersB">
+ [COUNT] 人
+ </string>
+ <string name="GroupMembersC">
+ [COUNT] 人
+ </string>
+ <string name="AcctTypeResident">
+ ä½äºº
+ </string>
+ <string name="AcctTypeTrial">
+ トライアル
+ </string>
+ <string name="AcctTypeCharterMember">
+ 創立メンãƒãƒ¼
+ </string>
+ <string name="AcctTypeEmployee">
+ Linden Lab 従業員
+ </string>
+ <string name="PaymentInfoUsed">
+ 支払情報使用履歴ã‚ã‚Š
+ </string>
+ <string name="PaymentInfoOnFile">
+ 支払情報登録済
+ </string>
+ <string name="NoPaymentInfoOnFile">
+ 支払情報未登録
+ </string>
+ <string name="AgeVerified">
+ 年齢確èªæ¸ˆ
+ </string>
+ <string name="NotAgeVerified">
+ 年齢未確èª
+ </string>
+ <string name="Center 2">
+ 中心 2
+ </string>
+ <string name="Top Right">
+ å³ä¸Š
+ </string>
+ <string name="Top">
+ 上部
+ </string>
+ <string name="Top Left">
+ 左上
+ </string>
+ <string name="Center">
+ 中心
+ </string>
+ <string name="Bottom Left">
+ 左下
+ </string>
+ <string name="Bottom">
+ 下部
+ </string>
+ <string name="Bottom Right">
+ å³ä¸‹
+ </string>
+ <string name="CompileQueueDownloadedCompiling">
+ ダウンロード完了ã€ã‚³ãƒ³ãƒ‘イル中
+ </string>
+ <string name="CompileQueueScriptNotFound">
+ サーãƒãƒ¼ä¸Šã«ã‚¹ã‚¯ãƒªãƒ—トãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。
+ </string>
+ <string name="CompileQueueProblemDownloading">
+ ダウンロードã«å•é¡ŒãŒã‚ã‚Šã¾ã™
+ </string>
+ <string name="CompileQueueInsufficientPermDownload">
+ 権é™ä¸è¶³ã®ãŸã‚スクリプトをダウンロードã§ãã¾ã›ã‚“。
+ </string>
+ <string name="CompileQueueInsufficientPermFor">
+ 権é™ä¸è¶³ï¼š
+ </string>
+ <string name="CompileQueueUnknownFailure">
+ 原因ä¸æ˜Žã®å¤±æ•—ã«ã‚ˆã‚Šãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ãŒã§ãã¾ã›ã‚“
+ </string>
+ <string name="CompileQueueTitle">
+ リコンパイル進行
+ </string>
+ <string name="CompileQueueStart">
+ リコンパイル
+ </string>
+ <string name="ResetQueueTitle">
+ 進行をリセット
+ </string>
+ <string name="ResetQueueStart">
+ リセット
+ </string>
+ <string name="RunQueueTitle">
+ 実行を続ã‘るよã†è¨­å®š
+ </string>
+ <string name="RunQueueStart">
+ 実行中ã«è¨­å®š
+ </string>
+ <string name="NotRunQueueTitle">
+ 実行をåœæ­¢ã™ã‚‹ã‚ˆã†è¨­å®š
+ </string>
+ <string name="NotRunQueueStart">
+ 実行åœæ­¢ã«è¨­å®š
+ </string>
+ <string name="CompileSuccessful">
+ コンパイルãŒå®Œäº†ã—ã¾ã—ãŸï¼
+ </string>
+ <string name="CompileSuccessfulSaving">
+ コンパイル完了ã€ä¿å­˜ä¸­ã§ã™...
+ </string>
+ <string name="SaveComplete">
+ ä¿å­˜å®Œäº†ã€‚
+ </string>
+ <string name="ObjectOutOfRange">
+ スクリプト(オブジェクトãŒç¯„囲外ã«ã‚ã‚Šã¾ã™ï¼‰
+ </string>
+ <string name="GodToolsObjectOwnedBy">
+ [OWNER] 所有ã®ã‚ªãƒ–ジェクト「[OBJECT]ã€
+ </string>
+ <string name="GroupsNone">
+ ãªã—
+ </string>
+ <string name="Group" value=" (グループ)"/>
+ <string name="Unknown">
+ (ä¸æ˜Žï¼‰
+ </string>
+ <string name="SummaryForTheWeek" value="今週ã®ã¾ã¨ã‚。開始日ã¯"/>
+ <string name="NextStipendDay" value="次回ã®ãŠå°é£ã„支給日ã¯"/>
+ <string name="GroupIndividualShare" value=" グループ 個人ã®å‰²ã‚Šå½“ã¦"/>
+ <string name="Balance">
+ 残高
+ </string>
+ <string name="Credits">
+ åŽå…¥
+ </string>
+ <string name="Debits">
+ 支出
+ </string>
+ <string name="Total">
+ åˆè¨ˆ
+ </string>
+ <string name="NoGroupDataFound">
+ グループã®ãƒ‡ãƒ¼ã‚¿ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ
+ </string>
+ <string name="IMParentEstate">
+ parent estate
+ </string>
+ <string name="IMMainland">
+ メインランド
+ </string>
+ <string name="IMTeen">
+ ティーン
+ </string>
+ <string name="RegionInfoError">
+ エラー
+ </string>
+ <string name="RegionInfoAllEstatesOwnedBy">
+ [OWNER] ãŒæ‰€æœ‰ã™ã‚‹ã™ã¹ã¦ã®ä¸å‹•ç”£
+ </string>
+ <string name="RegionInfoAllEstatesYouOwn">
+ ã‚ãªãŸãŒæ‰€æœ‰ã™ã‚‹ã™ã¹ã¦ã®ä¸å‹•ç”£
+ </string>
+ <string name="RegionInfoAllEstatesYouManage">
+ ã‚ãªãŸãŒ [OWNER] ã®ãŸã‚ã«ç®¡ç†ã™ã‚‹ã™ã¹ã¦ã®ä¸å‹•ç”£
+ </string>
+ <string name="RegionInfoAllowedResidents">
+ 許å¯ã•ã‚ŒãŸä½äººï¼š ([ALLOWEDAGENTS] 人ã€æœ€å¤§ [MAXACCESS] 人)
+ </string>
+ <string name="RegionInfoAllowedGroups">
+ 許å¯ã•ã‚ŒãŸã‚°ãƒ«ãƒ¼ãƒ—: ([ALLOWEDGROUPS]ã€æœ€å¤§ [MAXACCESS] グループ)
+ </string>
+ <string name="CursorPos">
+ [LINE] 行目ã€[COLUMN] 列目
+ </string>
+ <string name="PanelDirCountFound">
+ [COUNT] 件見ã¤ã‹ã‚Šã¾ã—ãŸ
+ </string>
+ <string name="PanelDirTimeStr">
+ [hour12,datetime,utc]:[min,datetime,utc] [ampm,datetime,utc]
+ </string>
+ <string name="PanelDirEventsDateText">
+ [mthnum,datetime,slt]/[day,datetime,slt]
+ </string>
+ <string name="PanelContentsNewScript">
+ æ–°è¦ã‚¹ã‚¯ãƒªãƒ—ト
+ </string>
+ <string name="MuteByName">
+ (å称別)
+ </string>
+ <string name="MuteAgent">
+ (ä½äººï¼‰
+ </string>
+ <string name="MuteObject">
+ (オブジェクト)
+ </string>
+ <string name="MuteGroup">
+ (グループ)
+ </string>
+ <string name="RegionNoCovenant">
+ ã“ã®ä¸å‹•ç”£ã«ã¯ç´„款ãŒã‚ã‚Šã¾ã›ã‚“。
+ </string>
+ <string name="RegionNoCovenantOtherOwner">
+ ã“ã®ä¸å‹•ç”£ã«ã¯ç´„款ãŒã‚ã‚Šã¾ã›ã‚“。 ã“ã®ä¸å‹•ç”£ä¸Šã®åœŸåœ°ã¯ä¸å‹•ç”£æ‰€æœ‰è€…ã«ã‚ˆã‚Šè²©å£²ã•ã‚Œã€Linden Lab ã¯è²©å£²ã—ã¾ã›ã‚“。 販売ã«é–¢ã™ã‚‹ãŠå•ã„åˆã‚ã›ã¯ã€ä¸å‹•ç”£æ‰€æœ‰è€…ã¾ã§ãŠé¡˜ã„致ã—ã¾ã™ã€‚
+ </string>
+ <string name="covenant_last_modified">
+ 最終修正日:
+ </string>
+ <string name="none_text" value=" (ãªã—)"/>
+ <string name="never_text" value=" (無)"/>
+ <string name="GroupOwned">
+ グループ所有
+ </string>
+ <string name="Public">
+ パブリック
+ </string>
+ <string name="ClassifiedClicksTxt">
+ クリック数: [TELEPORT] テレãƒãƒ¼ãƒˆã€ [MAP] 地図〠[PROFILE] プロフィール
+ </string>
+ <string name="ClassifiedUpdateAfterPublish">
+ (掲載後更新)
+ </string>
+ <string name="MultiPreviewTitle">
+ プレビュー
+ </string>
+ <string name="MultiPropertiesTitle">
+ プロパティ
+ </string>
+ <string name="InvOfferAnObjectNamed">
+ オブジェクトå
+ </string>
+ <string name="InvOfferOwnedByGroup">
+ 所有グループ
+ </string>
+ <string name="InvOfferOwnedByUnknownGroup">
+ ä¸æ˜Žãªã‚°ãƒ«ãƒ¼ãƒ—所有
+ </string>
+ <string name="InvOfferOwnedBy">
+ 所有者
+ </string>
+ <string name="InvOfferOwnedByUnknownUser">
+ ä¸æ˜Žãªãƒ¦ãƒ¼ã‚¶ãƒ¼æ‰€æœ‰
+ </string>
+ <string name="InvOfferGaveYou">
+ ãŒæ¸¡ã—ã¾ã—ãŸ
+ </string>
+ <string name="InvOfferYouDecline">
+ You decline
+ </string>
+ <string name="InvOfferFrom">
+ from
+ </string>
+ <string name="GroupMoneyTotal">
+ åˆè¨ˆ
+ </string>
+ <string name="GroupMoneyBought">
+ ã¯è³¼å…¥ã—ã¾ã—ãŸ
+ </string>
+ <string name="GroupMoneyPaidYou">
+ ãŒã‚ãªãŸã«æ”¯æ‰•ã„ã¾ã—ãŸ
+ </string>
+ <string name="GroupMoneyPaidInto">
+ paid into
+ </string>
+ <string name="GroupMoneyBoughtPassTo">
+ bought pass to
+ </string>
+ <string name="GroupMoneyPaidFeeForEvent">
+ ãŒã‚¤ãƒ™ãƒ³ãƒˆç”¨ã®è²»ç”¨ã‚’支払ã„ã¾ã—ãŸ
+ </string>
+ <string name="GroupMoneyPaidPrizeForEvent">
+ ãŒã‚¤ãƒ™ãƒ³ãƒˆç”¨ã®è³žé‡‘を支払ã„ã¾ã—ãŸ
+ </string>
+ <string name="GroupMoneyBalance">
+ 残高
+ </string>
+ <string name="GroupMoneyCredits">
+ åŽå…¥
+ </string>
+ <string name="GroupMoneyDebits">
+ 支出
+ </string>
+ <string name="ViewerObjectContents">
+ 内容
+ </string>
+ <string name="AcquiredItems">
+ å–得アイテム
+ </string>
+ <string name="Cancel">
+ キャンセル
+ </string>
+ <string name="UploadingCosts">
+ %s ã®ã‚¢ãƒƒãƒ—ロード代金:
+ </string>
+ <string name="UnknownFileExtension">
+ ä¸æ˜Žã®æ‹¡å¼µå­ï¼š %s
+使用å¯èƒ½ãªæ‹¡å¼µå­ï¼š .wav, .tga, .bmp, .jpg, .jpeg, or .bvh
+ </string>
+ <string name="AddLandmarkNavBarMenu">
+ ランドマークを追加...
+ </string>
+ <string name="EditLandmarkNavBarMenu">
+ ランドマークを編集...
+ </string>
+ <string name="accel-mac-control">
+ &#8963;
+ </string>
+ <string name="accel-mac-command">
+ &#8984;
+ </string>
+ <string name="accel-mac-option">
+ &#8997;
+ </string>
+ <string name="accel-mac-shift">
+ &#8679;
+ </string>
+ <string name="accel-win-control">
+ Ctrl+
+ </string>
+ <string name="accel-win-alt">
+ Alt+
+ </string>
+ <string name="accel-win-shift">
+ Shift+
+ </string>
+ <string name="FileSaved">
+ ファイルãŒä¿å­˜ã•ã‚Œã¾ã—ãŸ
+ </string>
+ <string name="Receiving">
+ å–得中
+ </string>
+ <string name="AM">
+ AM
+ </string>
+ <string name="PM">
+ PM
+ </string>
+ <string name="PST">
+ 太平洋標準時
+ </string>
+ <string name="PDT">
+ 太平洋å¤æ™‚é–“
+ </string>
+ <string name="Forward">
+ å‰
+ </string>
+ <string name="Left">
+ å·¦
+ </string>
+ <string name="Right">
+ å³
+ </string>
+ <string name="Back">
+ 後ã‚
+ </string>
+ <string name="North">
+ 北
+ </string>
+ <string name="South">
+ å—
+ </string>
+ <string name="West">
+ 西
+ </string>
+ <string name="East">
+ æ±
+ </string>
+ <string name="Up">
+ 上
+ </string>
+ <string name="Down">
+ 下
+ </string>
+ <string name="Any Category">
+ 全カテゴリ
+ </string>
+ <string name="Shopping">
+ ショッピング
+ </string>
+ <string name="Land Rental">
+ 土地ã®ãƒ¬ãƒ³ã‚¿ãƒ«
+ </string>
+ <string name="Property Rental">
+ 建物ã®ãƒ¬ãƒ³ã‚¿ãƒ«
+ </string>
+ <string name="Special Attraction">
+ 特別アトラクション
+ </string>
+ <string name="New Products">
+ 新製å“
+ </string>
+ <string name="Employment">
+ 雇用
+ </string>
+ <string name="Wanted">
+ 求む
+ </string>
+ <string name="Service">
+ サービス
+ </string>
+ <string name="Personal">
+ パーソナル
+ </string>
+ <string name="None">
+ ãªã—
+ </string>
+ <string name="Linden Location">
+ Linden 所在地
+ </string>
+ <string name="Adult">
+ Adult
+ </string>
+ <string name="Arts&amp;Culture">
+ アートã¨ã‚«ãƒ«ãƒãƒ£ãƒ¼
+ </string>
+ <string name="Business">
+ ビジãƒã‚¹
+ </string>
+ <string name="Educational">
+ 教育的
+ </string>
+ <string name="Gaming">
+ ゲーム
+ </string>
+ <string name="Hangout">
+ ãŸã¾ã‚Šå ´
+ </string>
+ <string name="Newcomer Friendly">
+ æ–°ä½äººã«å„ªã—ã„
+ </string>
+ <string name="Parks&amp;Nature">
+ 公園ã¨è‡ªç„¶
+ </string>
+ <string name="Residential">
+ ä½å®…用
+ </string>
+ <string name="Stage">
+ ステージ
+ </string>
+ <string name="Other">
+ ãã®ä»–
+ </string>
+ <string name="Any">
+ 全員
+ </string>
+ <string name="You">
+ ã‚ãªãŸ
+ </string>
+ <string name=":">
+ :
+ </string>
+ <string name=",">
+ ,
+ </string>
+ <string name="...">
+ ...
+ </string>
+ <string name="***">
+ ***
+ </string>
+ <string name="(">
+ (
+ </string>
+ <string name=")">
+ )
+ </string>
+ <string name=".">
+ .
+ </string>
+ <string name="&apos;">
+ &apos;
+ </string>
+ <string name="---">
+ ---
+ </string>
+ <string name="Multiple Media">
+ 複数ã®ãƒ¡ãƒ‡ã‚£ã‚¢
+ </string>
+ <string name="Play Media">
+ メディアをå†ç”Ÿ/一時åœæ­¢
+ </string>
+ <string name="MBCmdLineError">
+ コマンドラインã«ã‚¨ãƒ©ãƒ¼ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸã€‚
+リンク先をå‚ç…§ã—ã¦ãã ã•ã„: http://wiki.secondlife.com/wiki/Client_parameters
+エラー:
+ </string>
+ <string name="MBCmdLineUsg">
+ [APP_NAME] コマンドライン使用:
+ </string>
+ <string name="MBUnableToAccessFile">
+ [APP_NAME] ã¯å¿…è¦ãªãƒ•ã‚¡ã‚¤ãƒ«ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“。
+
+複数ã®ã‚³ãƒ”ーを実行中ã‹ã€ãƒ•ã‚¡ã‚¤ãƒ«ãŒæ—¢ã«é–‹ã„ã¦ã„ã‚‹ã¨ã‚ãªãŸã®ã‚·ã‚¹ãƒ†ãƒ ãŒèª¤èªè­˜ã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
+ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒä½•åº¦ã‚‚出る場åˆã¯ã€ã‚³ãƒ³ãƒ”ューターをå†èµ·å‹•ã—ã¦ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。
+ãã‚Œã§ã‚‚å•é¡ŒãŒç¶šãå ´åˆã€[APP_NAME] を完全ã«ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã—ã¦ã€å†ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’ã—ã¦ãã ã•ã„。
+ </string>
+ <string name="MBFatalError">
+ 致命的ãªã‚¨ãƒ©ãƒ¼
+ </string>
+ <string name="MBRequiresAltiVec">
+ [APP_NAME] ã¯ã€AltiVecæ­è¼‰ã®ãƒ—ロセッサãŒå¿…è¦ã§ã™ã€‚(G4 以é™ï¼‰
+ </string>
+ <string name="MBAlreadyRunning">
+ [APP_NAME] ã¯ã™ã§ã«å®Ÿè¡Œä¸­ã§ã™ã€‚
+最å°åŒ–ã•ã‚ŒãŸãƒ—ログラムã®ã‚³ãƒ”ーをタスクãƒãƒ¼ã§ç¢ºèªã—ã¦ãã ã•ã„。
+ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒä½•åº¦ã‚‚出る場åˆã¯ã‚³ãƒ³ãƒ”ューターをå†èµ·å‹•ã—ã¦ãã ã•ã„。
+ </string>
+ <string name="MBFrozenCrashed">
+ [APP_NAME] ã¯å‰å›žã®å®Ÿè¡Œæ™‚ã«ãƒ•ãƒªãƒ¼ã‚ºã—ã¦ã„ã¾ã™ã€‚
+クラッシュ報告をé€ä¿¡ã—ã¾ã™ã‹ï¼Ÿ
+ </string>
+ <string name="MBAlert">
+ 警告
+ </string>
+ <string name="MBNoDirectX">
+ [APP_NAME] 㯠DirectX 9.0b åŠã³ãれ以é™ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’検出ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“ã§ã—ãŸã€‚
+[APP_NAME] 㯠DirectX を使用ã—ã¦å®‰å®šæ€§ã®å•é¡Œã€ä½Žãƒ‘フォーマンスã€ã‚¯ãƒ©ãƒƒã‚·ãƒ¥ç­‰æ‚ªå½±éŸ¿ã‚’与ãˆã‚‹ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢ã‚„å¤ã„ドライãƒã‚’検出ã—ã¾ã™ã€‚ DirectX 9.0b ãŒãªãã¦ã‚‚ [APP_NAME] を実行ã§ãã¾ã™ãŒã€DirectX 9.0bã¨ã®ã”使用を強ã推奨ã—ã¾ã™ã€‚
+
+続ã‘ã¾ã™ã‹ï¼Ÿ
+ </string>
+ <string name="MBWarning">
+ 警告
+ </string>
+ <string name="MBNoAutoUpdate">
+ 自動更新ã¯ç¾åœ¨ Linux ã«ã¯å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“。
+www.secondlife.com ã‹ã‚‰æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ダウンロードã—ã¦ãã ã•ã„。
+ </string>
+ <string name="MBRegClassFailed">
+ RegisterClass 失敗
+ </string>
+ <string name="MBError">
+ エラー
+ </string>
+ <string name="MBFullScreenErr">
+ [WIDTH] x [HEIGHT] ã§ã¯å…¨ç”»é¢ã§å®Ÿè¡Œã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。
+ウィンドウモードã§å®Ÿè¡Œä¸­ã§ã™ã€‚
+ </string>
+ <string name="MBDestroyWinFailed">
+ シャットダウンエラー(DestroyWindow() 失敗)
+ </string>
+ <string name="MBShutdownErr">
+ シャットダウンエラー
+ </string>
+ <string name="MBDevContextErr">
+ GL ディãƒã‚¤ã‚¹ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆãŒä½œã‚Œã¾ã›ã‚“
+ </string>
+ <string name="MBPixelFmtErr">
+ é©åˆ‡ãªãƒ”クセル形å¼ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“
+ </string>
+ <string name="MBPixelFmtDescErr">
+ ピクセル形å¼æƒ…å ±ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“
+ </string>
+ <string name="MBTrueColorWindow">
+ [APP_NAME] を実行ã™ã‚‹ã«ã¯ã€True Color(32ビット)ãŒå¿…è¦ã§ã™ã€‚
+ãŠä½¿ã„ã®ã‚³ãƒ³ãƒ”ューターã®ã€Œã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«ãƒ‘ãƒãƒ«ã€ï¼žã€Œç”»é¢ã€ï¼žã€Œè¨­å®šã€ã«è¡Œãã€ã€Œæœ€é«˜ (32 ビット)ã€ã«è¨­å®šã—ã¦ãã ã•ã„。
+ </string>
+ <string name="MBAlpha">
+ [APP_NAME] 㯠8 ビットã®ã‚¢ãƒ«ãƒ•ã‚¡ãƒãƒ£ãƒ³ãƒãƒ«ã‚’å–å¾—ã§ããªã„ãŸã‚実行ã§ãã¾ã›ã‚“。 通常ビデオカードã®ãƒ‰ãƒ©ã‚¤ãƒã®å•é¡Œã§èµ·ã“ã‚Šã¾ã™ã€‚
+ãŠä½¿ã„ã®ã‚³ãƒ³ãƒ”ューターã«æœ€æ–°ã®ãƒ“デオカードドライãƒãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã‚‹ã‹ã”確èªãã ã•ã„。
+ã¾ãŸã€ã€Œã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«ãƒ‘ãƒãƒ«ã€ï¼žã€Œç”»é¢ã€ï¼žã€Œè¨­å®šã€å†…ã§ã€ãƒ¢ãƒ‹ã‚¿ãƒ¼ãŒã€Œæœ€é«˜ (32ビット)ã€ã«è¨­å®šã•ã‚Œã¦ã„ã‚‹ã“ã¨ã‚‚ã”確èªãã ã•ã„。
+ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒä½•åº¦ã‚‚出る場åˆã¯ã€[SUPPORT_SITE] ã¸ã”連絡ãã ã•ã„。
+ </string>
+ <string name="MBPixelFmtSetErr">
+ ピクセル形å¼ãŒè¨­å®šã§ãã¾ã›ã‚“
+ </string>
+ <string name="MBGLContextErr">
+ GL レンダーコンテキストãŒä½œã‚Œã¾ã›ã‚“
+ </string>
+ <string name="MBGLContextActErr">
+ GL レンダーコンテキストをアクティベートã§ãã¾ã›ã‚“
+ </string>
+ <string name="MBVideoDrvErr">
+ ãŠä½¿ã„ã®ã‚³ãƒ³ãƒ”ューターã®ãƒ“デオカードドライãƒãŒæ­£å¸¸ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã§ããªã‹ã£ãŸã€ã¾ãŸã¯å¤ã„ã‹ã‚µãƒãƒ¼ãƒˆå¯¾è±¡å¤–ã®ãŸã‚ã€[APP_NAME] ã¯å®Ÿè¡Œã§ãã¾ã›ã‚“。 最新ã®ãƒ“デオカードドライãƒãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¦ã„ã‚‹ã®ã‚’確èªã—ã€ã•ã‚Œã¦ã„ã‚‹å ´åˆã¯å†ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’ãŠè©¦ã—ãã ã•ã„。
+
+ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒä½•åº¦ã‚‚出る場åˆã¯ã€[SUPPORT_SITE] ã¸ã”連絡ãã ã•ã„。
+ </string>
+ <string name="5 O&apos;Clock Shadow">
+ ã†ã£ã™ã‚‰ã¨ã—ãŸãƒ’ゲ
+ </string>
+ <string name="All White">
+ 真ã£ç™½
+ </string>
+ <string name="Anime Eyes">
+ アニメ風ã®ç›®
+ </string>
+ <string name="Arced">
+ アーãƒ
+ </string>
+ <string name="Arm Length">
+ è…•ã®é•·ã•
+ </string>
+ <string name="Attached">
+ å°
+ </string>
+ <string name="Attached Earlobes">
+ 耳ãŸã¶
+ </string>
+ <string name="Back Fringe">
+ 後ã‚髪ã®æ¯›å…ˆ
+ </string>
+ <string name="Baggy">
+ ãŸã‚‹ã‚“ã§ã„ã‚‹
+ </string>
+ <string name="Bangs">
+ å‰é«ª
+ </string>
+ <string name="Beady Eyes">
+ ビーズã®ã‚ˆã†ãªç›®
+ </string>
+ <string name="Belly Size">
+ ãŠè…¹ã®å¤§ãã•
+ </string>
+ <string name="Big">
+ 大
+ </string>
+ <string name="Big Butt">
+ 大
+ </string>
+ <string name="Big Hair Back">
+ 髪ã®å¤§éƒ¨åˆ†ï¼š 後ã‚
+ </string>
+ <string name="Big Hair Front">
+ 髪ã®å¤§éƒ¨åˆ†ï¼š å‰
+ </string>
+ <string name="Big Hair Top">
+ 髪ã®å¤§éƒ¨åˆ†ï¼š 上部
+ </string>
+ <string name="Big Head">
+ 大
+ </string>
+ <string name="Big Pectorals">
+ 大
+ </string>
+ <string name="Big Spikes">
+ ã¨ã’ã‚ã‚Š
+ </string>
+ <string name="Black">
+ é»’
+ </string>
+ <string name="Blonde">
+ ブロンド
+ </string>
+ <string name="Blonde Hair">
+ ブロンドã®é«ª
+ </string>
+ <string name="Blush">
+ ãƒãƒ¼ã‚¯
+ </string>
+ <string name="Blush Color">
+ ãƒãƒ¼ã‚¯ã‚«ãƒ©ãƒ¼
+ </string>
+ <string name="Blush Opacity">
+ ãƒãƒ¼ã‚¯ã®æ¿ƒã•
+ </string>
+ <string name="Body Definition">
+ 体ã®ç²¾ç´°åº¦
+ </string>
+ <string name="Body Fat">
+ 体脂肪
+ </string>
+ <string name="Body Freckles">
+ 体ã®ã—ã¿ãƒ»ãã°ã‹ã™
+ </string>
+ <string name="Body Thick">
+ 骨太
+ </string>
+ <string name="Body Thickness">
+ 体ã®åŽšã¿
+ </string>
+ <string name="Body Thin">
+ ç´°ã‚
+ </string>
+ <string name="Bow Legged">
+ 外股
+ </string>
+ <string name="Breast Buoyancy">
+ 胸ã®é‡åŠ›
+ </string>
+ <string name="Breast Cleavage">
+ 胸ã®è°·é–“
+ </string>
+ <string name="Breast Size">
+ 胸ã®å¤§ãã•
+ </string>
+ <string name="Bridge Width">
+ 両目ã®é–“ã®å¹…
+ </string>
+ <string name="Broad">
+ 広
+ </string>
+ <string name="Brow Size">
+ 眉毛ã®å¤§ãã•
+ </string>
+ <string name="Bug Eyes">
+ Bug Eyes
+ </string>
+ <string name="Bugged Eyes">
+ çªã出ãŸç›®
+ </string>
+ <string name="Bulbous">
+ ã ã‚“ã”
+ </string>
+ <string name="Bulbous Nose">
+ ã ã‚“ã”é¼»
+ </string>
+ <string name="Bushy Eyebrows">
+ 太
+ </string>
+ <string name="Bushy Hair">
+ ã¼ã•ã¼ã•ãƒ˜ã‚¢
+ </string>
+ <string name="Butt Size">
+ ãŠå°»ã®å¤§ãã•
+ </string>
+ <string name="bustle skirt">
+ 後ã‚ã®è†¨ã‚‰ã¿
+ </string>
+ <string name="no bustle">
+ 膨らã¿ãªã—
+ </string>
+ <string name="more bustle">
+ 膨らã¿å¤§
+ </string>
+ <string name="Chaplin">
+ Chaplin
+ </string>
+ <string name="Cheek Bones">
+ ã»ãŠéª¨
+ </string>
+ <string name="Chest Size">
+ 胸部ã®å¤§ãã•
+ </string>
+ <string name="Chin Angle">
+ ã‚ã”ã®è§’度
+ </string>
+ <string name="Chin Cleft">
+ ã‚ã”ã®å…ˆã®å‰²ã‚Œ
+ </string>
+ <string name="Chin Curtains">
+ ã‚ã”ã«æ²¿ã£ãŸã²ã’
+ </string>
+ <string name="Chin Depth">
+ ã‚ã”ã®é•·ã•
+ </string>
+ <string name="Chin Heavy">
+ ã‚ã”ã«é‡ç‚¹
+ </string>
+ <string name="Chin In">
+ ã²ã„ãŸã‚ã”
+ </string>
+ <string name="Chin Out">
+ çªã出ãŸã‚ã”
+ </string>
+ <string name="Chin-Neck">
+ ã‚ã”ã¨é¦–
+ </string>
+ <string name="Clear">
+ クリア
+ </string>
+ <string name="Cleft">
+ 割れãŸ
+ </string>
+ <string name="Close Set Eyes">
+ é¡”ã®ä¸­å¿ƒå¯„ã‚Šã®ç›®
+ </string>
+ <string name="Closed">
+ クローズ
+ </string>
+ <string name="Closed Back">
+ 後ã‚ã¨ã˜
+ </string>
+ <string name="Closed Front">
+ å‰ã¨ã˜
+ </string>
+ <string name="Closed Left">
+ å·¦ã¨ã˜
+ </string>
+ <string name="Closed Right">
+ å³ã¨ã˜
+ </string>
+ <string name="Coin Purse">
+ コイン入れ
+ </string>
+ <string name="Collar Back">
+ 後ã‚ãˆã‚Š
+ </string>
+ <string name="Collar Front">
+ å‰ãˆã‚Š
+ </string>
+ <string name="Corner Down">
+ ダウン
+ </string>
+ <string name="Corner Up">
+ アップ
+ </string>
+ <string name="Creased">
+ é‡ã„ã¾ã¶ãŸ
+ </string>
+ <string name="Crooked Nose">
+ 曲ãŒã£ãŸé¼»
+ </string>
+ <string name="Cuff Flare">
+ 袖å£ã®ãƒ•ãƒ¬ã‚¢
+ </string>
+ <string name="Dark">
+ ダーク
+ </string>
+ <string name="Dark Green">
+ ダークグリーン
+ </string>
+ <string name="Darker">
+ ダーク
+ </string>
+ <string name="Deep">
+ å°–ã£ãŸ
+ </string>
+ <string name="Default Heels">
+ デフォルトã®ã‹ã‹ã¨
+ </string>
+ <string name="Dense">
+ 濃
+ </string>
+ <string name="Double Chin">
+ 二é‡ã‚ã”
+ </string>
+ <string name="Downturned">
+ 下å‘ã
+ </string>
+ <string name="Duffle Bag">
+ ダッフルãƒãƒƒã‚°
+ </string>
+ <string name="Ear Angle">
+ 耳ã®è§’度
+ </string>
+ <string name="Ear Size">
+ 耳ã®å¤§ãã•
+ </string>
+ <string name="Ear Tips">
+ 耳ã®å…ˆ
+ </string>
+ <string name="Egg Head">
+ ãŸã¾ã”é ­
+ </string>
+ <string name="Eye Bags">
+ 下ã¾ã¶ãŸ
+ </string>
+ <string name="Eye Color">
+ çž³ã®è‰²
+ </string>
+ <string name="Eye Depth">
+ ç›®ã®ãã¼ã¿
+ </string>
+ <string name="Eye Lightness">
+ çž³ã®æ˜Žã‚‹ã•
+ </string>
+ <string name="Eye Opening">
+ 見開ãå…·åˆ
+ </string>
+ <string name="Eye Pop">
+ 両目ã®å¤§ãã•ã®å¯¾ç§°
+ </string>
+ <string name="Eye Size">
+ ç›®ã®å¤§ãã•
+ </string>
+ <string name="Eye Spacing">
+ ç›®ã¨ç›®ã®ã‚ã„ã ã®å¹…
+ </string>
+ <string name="Eyebrow Arc">
+ 眉毛ã®ã‚¢ãƒ¼ãƒ
+ </string>
+ <string name="Eyebrow Density">
+ 眉毛ã®å¯†é›†åº¦
+ </string>
+ <string name="Eyebrow Height">
+ 眉毛ã®é«˜ã•
+ </string>
+ <string name="Eyebrow Points">
+ 眉毛ã®è§’
+ </string>
+ <string name="Eyebrow Size">
+ 眉毛ã®å¤§ãã•
+ </string>
+ <string name="Eyelash Length">
+ ã¾ã¤ã’ã®é•·ã•
+ </string>
+ <string name="Eyeliner">
+ アイライナー
+ </string>
+ <string name="Eyeliner Color">
+ アイライナーã®è‰²
+ </string>
+ <string name="Eyes Bugged">
+ 下ã¾ã¶ãŸãŒãŸã‚‹ã‚“ã ç›®
+ </string>
+ <string name="Eyes Shear Left Up">
+ å·¦å´ã‚’上ã«
+ </string>
+ <string name="Eyes Shear Right Up">
+ å³å´ã‚’上ã«
+ </string>
+ <string name="Face Shear">
+ é¡”ã®ã‚†ãŒã¿
+ </string>
+ <string name="Facial Definition">
+ é¡”ã®ç²¾ç´°åº¦
+ </string>
+ <string name="Far Set Eyes">
+ 離れãŸç›®
+ </string>
+ <string name="Fat Lips">
+ 大
+ </string>
+ <string name="Female">
+ 女性
+ </string>
+ <string name="Fingerless">
+ 指ãªã—
+ </string>
+ <string name="Fingers">
+ 指ã‚ã‚Š
+ </string>
+ <string name="Flared Cuffs">
+ 広ãŒã£ãŸè¢–å£
+ </string>
+ <string name="Flat">
+ 平ら
+ </string>
+ <string name="Flat Butt">
+ å°
+ </string>
+ <string name="Flat Head">
+ 絶å£é ­
+ </string>
+ <string name="Flat Toe">
+ フラット
+ </string>
+ <string name="Foot Size">
+ 足ã®å¤§ãã•
+ </string>
+ <string name="Forehead Angle">
+ ã²ãŸã„ã®è§’度
+ </string>
+ <string name="Forehead Heavy">
+ ã²ãŸã„ã«é‡ç‚¹
+ </string>
+ <string name="Freckles">
+ ã—ã¿ãƒ»ãã°ã‹ã™
+ </string>
+ <string name="Front Fringe">
+ å‰é«ªã®æ¯›å…ˆ
+ </string>
+ <string name="Full Back">
+ 刈られã¦ã„ãªã„髪
+ </string>
+ <string name="Full Eyeliner">
+ ã‚ã‚Š
+ </string>
+ <string name="Full Front">
+ 刈られã¦ã„ãªã„髪
+ </string>
+ <string name="Full Hair Sides">
+ サイドã®é«ª
+ </string>
+ <string name="Full Sides">
+ 生ãˆæƒã£ãŸã‚µã‚¤ãƒ‰
+ </string>
+ <string name="Glossy">
+ ã‚ã‚Š
+ </string>
+ <string name="Glove Fingers">
+ 手袋ã®æŒ‡
+ </string>
+ <string name="Glove Length">
+ 手袋ã®é•·ã•
+ </string>
+ <string name="Hair">
+ 髪
+ </string>
+ <string name="Hair Back">
+ 髪: 後ã‚
+ </string>
+ <string name="Hair Front">
+ 髪: å‰
+ </string>
+ <string name="Hair Sides">
+ 髪: サイド
+ </string>
+ <string name="Hair Sweep">
+ æµã™
+ </string>
+ <string name="Hair Thickess">
+ 髪ã®é‡
+ </string>
+ <string name="Hair Thickness">
+ 髪ã®é‡
+ </string>
+ <string name="Hair Tilt">
+ 髪ã®å‘ã
+ </string>
+ <string name="Hair Tilted Left">
+ å·¦å‘ã
+ </string>
+ <string name="Hair Tilted Right">
+ å³å‘ã
+ </string>
+ <string name="Hair Volume">
+ 髪: ボリューム
+ </string>
+ <string name="Hand Size">
+ 手ã®å¤§ãã•
+ </string>
+ <string name="Handlebars">
+ ãƒãƒ³ãƒ‰ãƒ«ãƒãƒ¼
+ </string>
+ <string name="Head Length">
+ é ­ã®é•·ã•
+ </string>
+ <string name="Head Shape">
+ é ­ã®å½¢
+ </string>
+ <string name="Head Size">
+ é ­ã®å¤§ãã•
+ </string>
+ <string name="Head Stretch">
+ é ­ã®ä¼¸ã³
+ </string>
+ <string name="Heel Height">
+ ヒールã®é«˜ã•
+ </string>
+ <string name="Heel Shape">
+ ヒールã®å½¢
+ </string>
+ <string name="Height">
+ 身長
+ </string>
+ <string name="High">
+ 高
+ </string>
+ <string name="High Heels">
+ ãƒã‚¤ãƒ’ール
+ </string>
+ <string name="High Jaw">
+ 高
+ </string>
+ <string name="High Platforms">
+ 厚底
+ </string>
+ <string name="High and Tight">
+ 高ã‚ã§ã‚¿ã‚¤ãƒˆ
+ </string>
+ <string name="Higher">
+ 高
+ </string>
+ <string name="Hip Length">
+ è…°ã®é•·ã•
+ </string>
+ <string name="Hip Width">
+ è…°ã®å¹…
+ </string>
+ <string name="In">
+ 内å‘ã
+ </string>
+ <string name="In Shdw Color">
+ 内å´ã®ã‚·ãƒ£ãƒ‰ã‚¦ã‚«ãƒ©ãƒ¼
+ </string>
+ <string name="In Shdw Opacity">
+ 内å´ã®ã‚·ãƒ£ãƒ‰ã‚¦ã®æ¿ƒã•
+ </string>
+ <string name="Inner Eye Corner">
+ 目頭
+ </string>
+ <string name="Inner Eye Shadow">
+ 内å´ã®ã‚¢ã‚¤ã‚·ãƒ£ãƒ‰ã‚¦
+ </string>
+ <string name="Inner Shadow">
+ 内å´ã®ã‚·ãƒ£ãƒ‰ã‚¦
+ </string>
+ <string name="Jacket Length">
+ ジャケット丈
+ </string>
+ <string name="Jacket Wrinkles">
+ ジャケットã®ã—ã‚
+ </string>
+ <string name="Jaw Angle">
+ ã‚ã”ã®è§’度
+ </string>
+ <string name="Jaw Jut">
+ ã‚ã”ã®çªå‡º
+ </string>
+ <string name="Jaw Shape">
+ ã‚ã”ã®å½¢
+ </string>
+ <string name="Join">
+ 寄ã›ãŸ
+ </string>
+ <string name="Jowls">
+ ãˆã‚‰
+ </string>
+ <string name="Knee Angle">
+ è†ã®è§’度
+ </string>
+ <string name="Knock Kneed">
+ 内股
+ </string>
+ <string name="Large">
+ 大
+ </string>
+ <string name="Large Hands">
+ 大
+ </string>
+ <string name="Left Part">
+ 左分ã‘
+ </string>
+ <string name="Leg Length">
+ è„šã®é•·ã•
+ </string>
+ <string name="Leg Muscles">
+ è„šã®ç­‹è‚‰
+ </string>
+ <string name="Less">
+ å°
+ </string>
+ <string name="Less Body Fat">
+ å°‘ãªã‚
+ </string>
+ <string name="Less Curtains">
+ å°‘ãªã‚
+ </string>
+ <string name="Less Freckles">
+ å°‘ãªã‚
+ </string>
+ <string name="Less Full">
+ è–„ã„
+ </string>
+ <string name="Less Gravity">
+ å°‘
+ </string>
+ <string name="Less Love">
+ å°‘
+ </string>
+ <string name="Less Muscles">
+ å°‘ãªã‚
+ </string>
+ <string name="Less Muscular">
+ å°‘ãªã‚
+ </string>
+ <string name="Less Rosy">
+ å°‘ãªç›®
+ </string>
+ <string name="Less Round">
+ 丸ã¿å°‘ãªç›®
+ </string>
+ <string name="Less Saddle">
+ å°
+ </string>
+ <string name="Less Square">
+ å°
+ </string>
+ <string name="Less Volume">
+ ボリューム少ãªç›®
+ </string>
+ <string name="Less soul">
+ å°
+ </string>
+ <string name="Lighter">
+ ライト
+ </string>
+ <string name="Lip Cleft">
+ 唇ã®å±±
+ </string>
+ <string name="Lip Cleft Depth">
+ 唇ã®å±±ã®é«˜ã•
+ </string>
+ <string name="Lip Fullness">
+ 唇ã®åŽšã¿
+ </string>
+ <string name="Lip Pinkness">
+ 唇ã®èµ¤ã¿
+ </string>
+ <string name="Lip Ratio">
+ 上下唇ã®å¤§ãã•
+ </string>
+ <string name="Lip Thickness">
+ 唇ã®å‰å¾Œå¹…
+ </string>
+ <string name="Lip Width">
+ å£ã®å¤§ãã•
+ </string>
+ <string name="Lipgloss">
+ リップグロス
+ </string>
+ <string name="Lipstick">
+ å£ç´…
+ </string>
+ <string name="Lipstick Color">
+ å£ç´…ã®è‰²
+ </string>
+ <string name="Long">
+ é•·
+ </string>
+ <string name="Long Head">
+ å‰å¾Œå¹…ãŒåºƒã„é ­
+ </string>
+ <string name="Long Hips">
+ é•·
+ </string>
+ <string name="Long Legs">
+ é•·
+ </string>
+ <string name="Long Neck">
+ é•·
+ </string>
+ <string name="Long Pigtails">
+ é•·
+ </string>
+ <string name="Long Ponytail">
+ é•·
+ </string>
+ <string name="Long Torso">
+ é•·
+ </string>
+ <string name="Long arms">
+ é•·
+ </string>
+ <string name="Loose Pants">
+ ゆã£ãŸã‚Š
+ </string>
+ <string name="Loose Shirt">
+ ゆるã‚
+ </string>
+ <string name="Loose Sleeves">
+ ゆるã‚
+ </string>
+ <string name="Love Handles">
+ ウエスト周り
+ </string>
+ <string name="Low">
+ 低
+ </string>
+ <string name="Low Heels">
+ ローヒール
+ </string>
+ <string name="Low Jaw">
+ 低
+ </string>
+ <string name="Low Platforms">
+ 低ã‚
+ </string>
+ <string name="Low and Loose">
+ 低ã‚ã§ã‚†ã£ãŸã‚Š
+ </string>
+ <string name="Lower">
+ 低
+ </string>
+ <string name="Lower Bridge">
+ 鼻筋
+ </string>
+ <string name="Lower Cheeks">
+ ã»ãŠã®ä¸‹éƒ¨
+ </string>
+ <string name="Male">
+ 男性
+ </string>
+ <string name="Middle Part">
+ 真ん中分ã‘
+ </string>
+ <string name="More">
+ 大
+ </string>
+ <string name="More Blush">
+ ãã¤ã‚
+ </string>
+ <string name="More Body Fat">
+ 多ã‚
+ </string>
+ <string name="More Curtains">
+ 多ã‚
+ </string>
+ <string name="More Eyeshadow">
+ ã‚ã‚Š
+ </string>
+ <string name="More Freckles">
+ 多ã‚
+ </string>
+ <string name="More Full">
+ 厚ã„
+ </string>
+ <string name="More Gravity">
+ 大
+ </string>
+ <string name="More Lipstick">
+ ã‚ã‚Š
+ </string>
+ <string name="More Love">
+ 大
+ </string>
+ <string name="More Lower Lip">
+ 大
+ </string>
+ <string name="More Muscles">
+ 多ã‚
+ </string>
+ <string name="More Muscular">
+ 筋骨隆々
+ </string>
+ <string name="More Rosy">
+ 多ã‚
+ </string>
+ <string name="More Round">
+ ã¾ã‚‹
+ </string>
+ <string name="More Saddle">
+ 大
+ </string>
+ <string name="More Sloped">
+ ãªã ã‚‰ã‹
+ </string>
+ <string name="More Square">
+ 四角
+ </string>
+ <string name="More Upper Lip">
+ 大
+ </string>
+ <string name="More Vertical">
+ åž‚ç›´
+ </string>
+ <string name="More Volume">
+ 大
+ </string>
+ <string name="More soul">
+ 大
+ </string>
+ <string name="Moustache">
+ å£ã²ã’
+ </string>
+ <string name="Mouth Corner">
+ å£è§’
+ </string>
+ <string name="Mouth Position">
+ å£ã®ä½ç½®
+ </string>
+ <string name="Mowhawk">
+ モヒカン
+ </string>
+ <string name="Muscular">
+ 筋骨ãŸãã¾ã—ã„
+ </string>
+ <string name="Mutton Chops">
+ マトンãƒãƒ§ãƒƒãƒ—ス
+ </string>
+ <string name="Nail Polish">
+ マニキュア
+ </string>
+ <string name="Nail Polish Color">
+ マニキュアã®è‰²
+ </string>
+ <string name="Narrow">
+ ç‹­
+ </string>
+ <string name="Narrow Back">
+ ç‹­
+ </string>
+ <string name="Narrow Front">
+ ç‹­
+ </string>
+ <string name="Narrow Lips">
+ ãŠã¡ã‚‡ã¼å£
+ </string>
+ <string name="Natural">
+ ナãƒãƒ¥ãƒ©ãƒ«
+ </string>
+ <string name="Neck Length">
+ 首ã®é•·ã•
+ </string>
+ <string name="Neck Thickness">
+ 首ã®å¤ªã•
+ </string>
+ <string name="No Blush">
+ ãªã—
+ </string>
+ <string name="No Eyeliner">
+ ãªã—
+ </string>
+ <string name="No Eyeshadow">
+ ãªã—
+ </string>
+ <string name="No Lipgloss">
+ ãªã—
+ </string>
+ <string name="No Lipstick">
+ ãªã—
+ </string>
+ <string name="No Part">
+ ãªã—
+ </string>
+ <string name="No Polish">
+ ãªã—
+ </string>
+ <string name="No Red">
+ ãªã—
+ </string>
+ <string name="No Spikes">
+ ãªã—
+ </string>
+ <string name="No White">
+ ãªã—
+ </string>
+ <string name="No Wrinkles">
+ ãªã—
+ </string>
+ <string name="Normal Lower">
+ 下
+ </string>
+ <string name="Normal Upper">
+ 上
+ </string>
+ <string name="Nose Left">
+ 左曲ãŒã‚Š
+ </string>
+ <string name="Nose Right">
+ å³æ›²ãŒã‚Š
+ </string>
+ <string name="Nose Size">
+ é¼»ã®å¤§ãã•
+ </string>
+ <string name="Nose Thickness">
+ é¼»ã®åŽšã¿
+ </string>
+ <string name="Nose Tip Angle">
+ 鼻先ã®è§’度
+ </string>
+ <string name="Nose Tip Shape">
+ 鼻先ã®å½¢
+ </string>
+ <string name="Nose Width">
+ é¼»ã®å¹…
+ </string>
+ <string name="Nostril Division">
+ é¼»ã®ç©´ã®é«˜ã•
+ </string>
+ <string name="Nostril Width">
+ é¼»ã®ç©´ã®å¹…
+ </string>
+ <string name="Opaque">
+ 濃ã„ã‚
+ </string>
+ <string name="Open">
+ オープン
+ </string>
+ <string name="Open Back">
+ 後ã‚ã‚ã
+ </string>
+ <string name="Open Front">
+ å‰ã‚ã
+ </string>
+ <string name="Open Left">
+ å·¦ã‚ã
+ </string>
+ <string name="Open Right">
+ å³ã‚ã
+ </string>
+ <string name="Orange">
+ オレンジ
+ </string>
+ <string name="Out">
+ 外å‘ã
+ </string>
+ <string name="Out Shdw Color">
+ 外å´ã®ã‚·ãƒ£ãƒ‰ã‚¦ã‚«ãƒ©ãƒ¼
+ </string>
+ <string name="Out Shdw Opacity">
+ 外å´ã®ã‚·ãƒ£ãƒ‰ã‚¦ã®æ¿ƒã•
+ </string>
+ <string name="Outer Eye Corner">
+ 目尻
+ </string>
+ <string name="Outer Eye Shadow">
+ 外å´ã®ã‚¢ã‚¤ã‚·ãƒ£ãƒ‰ã‚¦
+ </string>
+ <string name="Outer Shadow">
+ 外å´ã®ã‚·ãƒ£ãƒ‰ã‚¦
+ </string>
+ <string name="Overbite">
+ 出ã£æ­¯
+ </string>
+ <string name="Package">
+ パッケージ
+ </string>
+ <string name="Painted Nails">
+ ã‚ã‚Š
+ </string>
+ <string name="Pale">
+ 悪ã„
+ </string>
+ <string name="Pants Crotch">
+ パンツã®è‚¡
+ </string>
+ <string name="Pants Fit">
+ パンツã®ãƒ•ã‚£ãƒƒãƒˆæ„Ÿ
+ </string>
+ <string name="Pants Length">
+ パンツ丈
+ </string>
+ <string name="Pants Waist">
+ ウエスト
+ </string>
+ <string name="Pants Wrinkles">
+ パンツã®ã—ã‚
+ </string>
+ <string name="Part">
+ ã‚ã‚Š
+ </string>
+ <string name="Part Bangs">
+ 分ã‘ãŸå‰é«ª
+ </string>
+ <string name="Pectorals">
+ 胸筋
+ </string>
+ <string name="Pigment">
+ 色素
+ </string>
+ <string name="Pigtails">
+ 下ã’髪
+ </string>
+ <string name="Pink">
+ ピンク
+ </string>
+ <string name="Pinker">
+ ピンク
+ </string>
+ <string name="Platform Height">
+ é´åº•ã®é«˜ã•
+ </string>
+ <string name="Platform Width">
+ é´åº•ã®å¹…
+ </string>
+ <string name="Pointy">
+ å°–ã£ãŸ
+ </string>
+ <string name="Pointy Heels">
+ å¹…ç‹­
+ </string>
+ <string name="Ponytail">
+ ãƒãƒ‹ãƒ¼ãƒ†ãƒ¼ãƒ«
+ </string>
+ <string name="Poofy Skirt">
+ ãµã‚“ã‚ã‚Š
+ </string>
+ <string name="Pop Left Eye">
+ 左目を大ãã
+ </string>
+ <string name="Pop Right Eye">
+ å³ç›®ã‚’大ãã
+ </string>
+ <string name="Puffy">
+ ãµã£ãら
+ </string>
+ <string name="Puffy Eyelids">
+ ç›®ã®å‘¨ã‚Šã®è†¨ã‚‰ã¿
+ </string>
+ <string name="Rainbow Color">
+ 虹色
+ </string>
+ <string name="Red Hair">
+ 赤毛
+ </string>
+ <string name="Regular">
+ å‡æ•´ã®ã¨ã‚ŒãŸ
+ </string>
+ <string name="Right Part">
+ å³åˆ†ã‘
+ </string>
+ <string name="Rosy Complexion">
+ ã»ãŠã®èµ¤ã‚‰ã¿
+ </string>
+ <string name="Round">
+ ã¾ã‚‹ã£ã“ã„
+ </string>
+ <string name="Ruddiness">
+ 血色
+ </string>
+ <string name="Ruddy">
+ 良ã„
+ </string>
+ <string name="Rumpled Hair">
+ ãã—ゃãã—ゃヘア
+ </string>
+ <string name="Saddle Bags">
+ 腰回りã®è‚‰ä»˜ã
+ </string>
+ <string name="Scrawny Leg">
+ 骨張ã£ãŸè„š
+ </string>
+ <string name="Separate">
+ 離れãŸ
+ </string>
+ <string name="Shallow">
+ ãªã ã‚‰ã‹
+ </string>
+ <string name="Shear Back">
+ 後方を刈る
+ </string>
+ <string name="Shear Face">
+ é¡”ã®ã‚†ãŒã¿
+ </string>
+ <string name="Shear Front">
+ å‰æ–¹ã‚’刈る
+ </string>
+ <string name="Shear Left Up">
+ å·¦åŠåˆ†ã‚’上ã«
+ </string>
+ <string name="Shear Right Up">
+ å³åŠåˆ†ã‚’上ã«
+ </string>
+ <string name="Sheared Back">
+ 後ã‚を刈られãŸé«ª
+ </string>
+ <string name="Sheared Front">
+ å‰ã‚’刈られãŸé«ª
+ </string>
+ <string name="Shift Left">
+ å·¦å‘ã
+ </string>
+ <string name="Shift Mouth">
+ å£ã®å‘ã
+ </string>
+ <string name="Shift Right">
+ å³å‘ã
+ </string>
+ <string name="Shirt Bottom">
+ シャツã®è£¾
+ </string>
+ <string name="Shirt Fit">
+ シャツã®ãƒ•ã‚£ãƒƒãƒˆæ„Ÿ
+ </string>
+ <string name="Shirt Wrinkles">
+ シャツã®ã—ã‚
+ </string>
+ <string name="Shoe Height">
+ é´ã®é•·ã•
+ </string>
+ <string name="Short">
+ 短
+ </string>
+ <string name="Short Arms">
+ 短
+ </string>
+ <string name="Short Legs">
+ 短
+ </string>
+ <string name="Short Neck">
+ 短
+ </string>
+ <string name="Short Pigtails">
+ 短
+ </string>
+ <string name="Short Ponytail">
+ 短
+ </string>
+ <string name="Short Sideburns">
+ 短ã‚
+ </string>
+ <string name="Short Torso">
+ 短
+ </string>
+ <string name="Short hips">
+ 短
+ </string>
+ <string name="Shoulders">
+ è‚©
+ </string>
+ <string name="Side Fringe">
+ サイドã®æ¯›å…ˆ
+ </string>
+ <string name="Sideburns">
+ ã‚‚ã¿ã‚ã’
+ </string>
+ <string name="Sides Hair">
+ サイドã®é«ª
+ </string>
+ <string name="Sides Hair Down">
+ ダウン
+ </string>
+ <string name="Sides Hair Up">
+ アップ
+ </string>
+ <string name="Skinny Neck">
+ ç´°
+ </string>
+ <string name="Skirt Fit">
+ スカートã®ãƒ•ã‚£ãƒƒãƒˆæ„Ÿ
+ </string>
+ <string name="Skirt Length">
+ スカート丈
+ </string>
+ <string name="Slanted Forehead">
+ 傾斜ã—ãŸé¡
+ </string>
+ <string name="Sleeve Length">
+ 袖丈
+ </string>
+ <string name="Sleeve Looseness">
+ 袖ã®ãƒ•ã‚£ãƒƒãƒˆæ„Ÿ
+ </string>
+ <string name="Slit Back">
+ スリット: 後ã‚
+ </string>
+ <string name="Slit Front">
+ スリット: å‰
+ </string>
+ <string name="Slit Left">
+ スリット: 左
+ </string>
+ <string name="Slit Right">
+ スリット: å³
+ </string>
+ <string name="Small">
+ å°
+ </string>
+ <string name="Small Hands">
+ å°
+ </string>
+ <string name="Small Head">
+ å°
+ </string>
+ <string name="Smooth">
+ 滑らã‹
+ </string>
+ <string name="Smooth Hair">
+ スムーズ
+ </string>
+ <string name="Socks Length">
+ é´ä¸‹ä¸ˆ
+ </string>
+ <string name="Soulpatch">
+ ソウルパッãƒ
+ </string>
+ <string name="Sparse">
+ è–„
+ </string>
+ <string name="Spiked Hair">
+ ã¨ã’ã¨ã’ヘア
+ </string>
+ <string name="Square">
+ 角張ã£ãŸ
+ </string>
+ <string name="Square Toe">
+ スクエアトゥ
+ </string>
+ <string name="Squash Head">
+ カボãƒãƒ£åž‹
+ </string>
+ <string name="Stretch Head">
+ 縦長
+ </string>
+ <string name="Sunken">
+ ã“ã‘ãŸ
+ </string>
+ <string name="Sunken Chest">
+ å°
+ </string>
+ <string name="Sunken Eyes">
+ ãã¼ã‚“ã ç›®
+ </string>
+ <string name="Sweep Back">
+ 後ã‚ã¸
+ </string>
+ <string name="Sweep Forward">
+ å‰ã¸
+ </string>
+ <string name="Tall">
+ 高
+ </string>
+ <string name="Taper Back">
+ 後ã‚ã«å…ˆç´°
+ </string>
+ <string name="Taper Front">
+ å‰ã«å…ˆç´°
+ </string>
+ <string name="Thick Heels">
+ 幅広
+ </string>
+ <string name="Thick Neck">
+ 太
+ </string>
+ <string name="Thick Toe">
+ 厚ã‚
+ </string>
+ <string name="Thin">
+ è–„ã„
+ </string>
+ <string name="Thin Eyebrows">
+ ç´°
+ </string>
+ <string name="Thin Lips">
+ å°
+ </string>
+ <string name="Thin Nose">
+ ç´°ã„é¼»
+ </string>
+ <string name="Tight Chin">
+ ã²ãã—ã¾ã£ãŸã‚ã”
+ </string>
+ <string name="Tight Cuffs">
+ タイト
+ </string>
+ <string name="Tight Pants">
+ タイト
+ </string>
+ <string name="Tight Shirt">
+ タイト
+ </string>
+ <string name="Tight Skirt">
+ タイト
+ </string>
+ <string name="Tight Sleeves">
+ タイト
+ </string>
+ <string name="Toe Shape">
+ ã¤ã¾å…ˆã®å½¢
+ </string>
+ <string name="Toe Thickness">
+ ã¤ã¾å…ˆã®åŽšã¿
+ </string>
+ <string name="Torso Length">
+ 上åŠèº«ã®é•·ã•
+ </string>
+ <string name="Torso Muscles">
+ 上åŠèº«ã®ç­‹è‚‰
+ </string>
+ <string name="Torso Scrawny">
+ 上åŠèº«ã®éª¨å¼µã‚Š
+ </string>
+ <string name="Unattached">
+ 大
+ </string>
+ <string name="Uncreased">
+ 軽ã„ã¾ã¶ãŸ
+ </string>
+ <string name="Underbite">
+ å—ã‘å£
+ </string>
+ <string name="Unnatural">
+ ユニーク
+ </string>
+ <string name="Upper Bridge">
+ 両目ã®ã‚ã„ã 
+ </string>
+ <string name="Upper Cheeks">
+ ã»ãŠã®ä¸Šéƒ¨
+ </string>
+ <string name="Upper Chin Cleft">
+ ã‚ã”上部ã®å‰²ã‚Œå…·åˆ
+ </string>
+ <string name="Upper Eyelid Fold">
+ 二é‡ã®å¹…
+ </string>
+ <string name="Upturned">
+ 上å‘ã
+ </string>
+ <string name="Very Red">
+ 真ã£èµ¤
+ </string>
+ <string name="Waist Height">
+ ウエストã®é«˜ã•
+ </string>
+ <string name="Well-Fed">
+ ã¤ã¾ã£ãŸ
+ </string>
+ <string name="White Hair">
+ 白髪
+ </string>
+ <string name="Wide">
+ 広
+ </string>
+ <string name="Wide Back">
+ 広
+ </string>
+ <string name="Wide Front">
+ 広
+ </string>
+ <string name="Wide Lips">
+ 大ãã„å£
+ </string>
+ <string name="Wild">
+ ワイルド
+ </string>
+ <string name="Wrinkles">
+ ã—ã‚ã‚ã‚Š
+ </string>
+ <string name="LocationCtrlAddLandmarkTooltip">
+ マイ ランドマークã«è¿½åŠ 
+ </string>
+ <string name="LocationCtrlEditLandmarkTooltip">
+ マイ ランドマークを編集
+ </string>
+ <string name="LocationCtrlInfoBtnTooltip">
+ ç¾åœ¨åœ°ã®è©³ç´°ã‚’見る
+ </string>
+ <string name="LocationCtrlComboBtnTooltip">
+ マイロケーション履歴
+ </string>
+ <string name="UpdaterWindowTitle">
+ [APP_NAME] アップデート
+ </string>
+ <string name="UpdaterNowUpdating">
+ åªä»Š [APP_NAME] をアップデート中ã§ã™...
+ </string>
+ <string name="UpdaterNowInstalling">
+ [APP_NAME] をインストール中ã§ã™...
+ </string>
+ <string name="UpdaterUpdatingDescriptive">
+ ãŠä½¿ã„ã® [APP_NAME] ビューワãŒæœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ã‚¢ãƒƒãƒ—デートã•ã‚Œã¦ã„ã¾ã™ã€‚ 数分ã‹ã‹ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã®ã§ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„。
+ </string>
+ <string name="UpdaterProgressBarTextWithEllipses">
+ アップデートをダウンロード中ã§ã™...
+ </string>
+ <string name="UpdaterProgressBarText">
+ アップデートをダウンロード中
+ </string>
+ <string name="UpdaterFailDownloadTitle">
+ アップデートã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã«å¤±æ•—ã—ã¾ã—ãŸ
+ </string>
+ <string name="UpdaterFailUpdateDescriptive">
+ [APP_NAME] をアップデート中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ www.secondlife.com ã‹ã‚‰æœ€æ–°ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’ダウンロードã—ã¦ãã ã•ã„。
+ </string>
+ <string name="UpdaterFailInstallTitle">
+ アップデートã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã«å¤±æ•—ã—ã¾ã—ãŸ
+ </string>
+ <string name="UpdaterFailStartTitle">
+ ビューワã®èµ·å‹•ã«å¤±æ•—ã—ã¾ã—ãŸ
+ </string>
+ <string name="IM_logging_string">
+ -- インスタントメッセージã®ä¿å­˜é–‹å§‹ --
+ </string>
+ <string name="IM_typing_start_string">
+ [NAME] ã¯å…¥åŠ›ä¸­...
+ </string>
+ <string name="Unnamed">
+ (åå‰ãªã—)
+ </string>
+ <string name="IM_moderated_chat_label">
+ (モデレート: デフォルトã§ãƒœã‚¤ã‚¹ã¯ã‚ªãƒ•ï¼‰
+ </string>
+ <string name="IM_unavailable_text_label">
+ ã“ã®ã‚³ãƒ¼ãƒ«ã§ã¯æ–‡å­—ãƒãƒ£ãƒƒãƒˆãŒåˆ©ç”¨ã§ãã¾ã›ã‚“。
+ </string>
+ <string name="IM_muted_text_label">
+ グループã®ãƒ¢ãƒ‡ãƒ¬ãƒ¼ã‚¿ãŒã€ã‚ãªãŸã®æ–‡å­—ãƒãƒ£ãƒƒãƒˆã‚’使用ç¦æ­¢ã«ã—ã¾ã—ãŸã€‚
+ </string>
+ <string name="IM_default_text_label">
+ ã“ã“をクリックã—ã¦ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ãƒˆãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’開始。
+ </string>
+ <string name="IM_to_label">
+ 宛先
+ </string>
+ <string name="IM_moderator_label">
+ (モデレータ)
+ </string>
+ <string name="only_user_message">
+ ã“ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«ã„るユーザーã¯ã‚ãªãŸã ã‘ã§ã™ã€‚
+ </string>
+ <string name="offline_message">
+ [FIRST] [LAST]ã¯ã‚ªãƒ•ãƒ©ã‚¤ãƒ³ã§ã™ã€‚
+ </string>
+ <string name="invite_message">
+ ã“ã®ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆã«å¿œç­”/接続ã™ã‚‹å ´åˆã¯ã€[BUTTON NAME]をクリックã—ã¦ãã ã•ã„。
+ </string>
+ <string name="generic_request_error">
+ è¦æ±‚中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚後ã§ã‚‚ã†ä¸€åº¦è©¦ã—ã¦ãã ã•ã„。
+ </string>
+ <string name="insufficient_perms_error">
+ ã‚ãªãŸã«ã¯å……分ãªæ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“。
+ </string>
+ <string name="session_does_not_exist_error">
+ ã“ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã¯æ—¢ã«åˆ‡æ–­ã•ã‚Œã¦ã„ã¾ã™ã€‚
+ </string>
+ <string name="no_ability_error">
+ ã‚ãªãŸã«ã¯ãã®èƒ½åŠ›ãŒã‚ã‚Šã¾ã›ã‚“。
+ </string>
+ <string name="no_ability">
+ ã‚ãªãŸã«ã¯ãã®èƒ½åŠ›ãŒã‚ã‚Šã¾ã›ã‚“。
+ </string>
+ <string name="not_a_mod_error">
+ ã‚ãªãŸã¯ã‚»ãƒƒã‚·ãƒ§ãƒ³ãƒ»ãƒ¢ãƒ‡ãƒ¬ãƒ¼ã‚¿ã§ã¯ã‚ã‚Šã¾ã›ã‚“。
+ </string>
+ <string name="muted_error">
+ グループモデレータãŒã‚ãªãŸã®ãƒ†ã‚­ã‚¹ãƒˆãƒãƒ£ãƒƒãƒˆã‚’無効化ã—ã¾ã—ãŸ
+ </string>
+ <string name="add_session_event">
+ [RECIPIENT] ã¨ã®ãƒãƒ£ãƒƒãƒˆãƒ»ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’追加ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“
+ </string>
+ <string name="message_session_event">
+ [RECIPIENT] ã¨ã®ãƒãƒ£ãƒƒãƒˆãƒ»ã‚»ãƒƒã‚·ãƒ§ãƒ³ã«ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’é€ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“
+ </string>
+ <string name="removed_from_group">
+ ã‚ãªãŸã¯ã‚°ãƒ«ãƒ¼ãƒ—ã‹ã‚‰å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚
+ </string>
+ <string name="close_on_no_ability">
+ ã“ã®ãƒãƒ£ãƒƒãƒˆãƒ»ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’継続ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“
+ </string>
</strings>
diff --git a/indra/newview/skins/default/xui/ja/teleport_strings.xml b/indra/newview/skins/default/xui/ja/teleport_strings.xml
index 7e99d2562e..72c183d03b 100644
--- a/indra/newview/skins/default/xui/ja/teleport_strings.xml
+++ b/indra/newview/skins/default/xui/ja/teleport_strings.xml
@@ -1,13 +1,13 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<teleport_messages name="">
<message_set name="errors">
<message name="invalid_tport">
- テレãƒãƒ¼ãƒˆãƒ»ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®å‡¦ç†ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚テレãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ã€å†åº¦ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
-ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒå¼•ã続ã表示ã•ã‚Œã‚‹å ´åˆã¯ã€æŠ€è¡“サãƒãƒ¼ãƒˆFAQ(www.secondlife.com/support)をå‚ç…§ã—ã¦ãã ã•ã„。
+ テレãƒãƒ¼ãƒˆå‡¦ç†ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ ログインã—ç›´ã™å¿…è¦ãŒã‚ã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。
+ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒä½•åº¦ã‚‚出る場åˆã¯ã€[SUPPORT_SITE] ã‚’ã”確èªãã ã•ã„。
</message>
<message name="invalid_region_handoff">
- 地域間ã®ç§»å‹•ã®å‡¦ç†ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚地域間を移動ã™ã‚‹ã«ã¯ã€å†åº¦ãƒ­ã‚°ã‚¤ãƒ³ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚
-ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒå¼•ã続ã表示ã•ã‚Œã‚‹å ´åˆã¯ã€æŠ€è¡“サãƒãƒ¼ãƒˆFAQ(www.secondlife.com/support)をå‚ç…§ã—ã¦ãã ã•ã„。
+ リージョン間ã®ç§»å‹•ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ ログインã—ç›´ã™å¿…è¦ãŒã‚ã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。
+ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒä½•åº¦ã‚‚出る場åˆã¯ã€[SUPPORT_SITE] ã‚’ã”確èªãã ã•ã„。
</message>
<message name="blocked_tport">
申ã—訳ã”ã–ã„ã¾ã›ã‚“。テレãƒãƒ¼ãƒˆã¯ç¾åœ¨ã€ãƒ–ロックã•ã‚Œã¦ã„ã¾ã™ã€‚ã‚‚ã†å°‘ã—後ã§ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。
diff --git a/indra/newview/skins/default/xui/nl/floater_about.xml b/indra/newview/skins/default/xui/nl/floater_about.xml
index d981ac2c8c..10c30eb361 100644
--- a/indra/newview/skins/default/xui/nl/floater_about.xml
+++ b/indra/newview/skins/default/xui/nl/floater_about.xml
@@ -1,10 +1,19 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_about" title="Over Second Life">
+<floater name="floater_about" title="OVER [CAPITALIZED_APP_NAME]">
+<tab_container name="about_tab">
+ <panel name="credits_panel">
<text_editor name="credits_editor">
- Second Life wordt u aangeboden door Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les and many others.
+ Second Life wordt u aangeboden door Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, Michon, Jenelle, Geo, Siz, Shapiro, Pete, Calyle, Selene, Allen, Phoebe, Goldin, Kimmora, Dakota, Slaton, Lindquist, Zoey, Hari, Othello, Rohit, Sheldon, Petra, Viale, Gordon, Kaye, Pink, Ferny, Emerson, Davy, Bri, Chan, Juan, Robert, Terrence, Nathan, Carl and many others.
-Een &apos;Dank u&apos; voor de volgende bewoners voor het helpen zorgdragen dat dit de beste versie tot nu toe is:
+Een &apos;Dank u&apos; voor de volgende bewoners voor het helpen zorgdragen dat dit de beste versie tot nu toe is: able whitman, Adeon Writer, adonaira aabye, Aeron Kohime, Agathos Frascati, Aimee Trescothick, Aleric Inglewood, Alissa Sabre, Aminom Marvin, Angela Talamasca, Aralara Rajal, Armin Weatherwax, Ashrilyn Hayashida, Athanasius Skytower, Aura Dirval, Barney Boomslang, Biancaluce Robbiani, Biker Offcourse, Borg Capalini, Bulli Schumann, catherine pfeffer, Chalice Yao, Corre Porta, Court Goodman, Cummere Mayo, Dale Innis, Darien Caldwell, Darjeeling Schoonhoven, Daten Thielt, dimentox travanti, Dirk Talamasca, Drew Dwi, Duckless Vandyke, Elanthius Flagstaff, Electro Burnstein, emiley tomsen, Escort DeFarge, Eva Rau, Ezian Ecksol, Fire Centaur, Fluf Fredriksson, Francisco Koolhoven, Frontera Thor, Frungi Stastny, Gally Young, gearsawe stonecutter, Gigs Taggart, Gordon Wendt, Gudmund Shepherd, Gypsy Paz, Harleen Gretzky, Henri Beauchamp, Inma Rau, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Jessicka Graves, Joeseph Albanese, Joshua Philgarlic, Khyota Wulluf, kirstenlee Cinquetti, Latif Khalifa, Lex Neva, Lilibeth Andree, Lisa Lowe, Lunita Savira, Loosey Demonia, lum pfohl, Marcos Fonzarelli, MartinRJ Fayray, Marusame Arai, Matthew Dowd, Maya Remblai, McCabe Maxsted, Meghan Dench, Melchoir Tokhes, Menos Short, Michelle2 Zenovka, Mimika Oh, Minerva Memel, Mm Alder, Ochi Wolfe, Omei Turnbull, Pesho Replacement, Phantom Ninetails, phoenixflames kukulcan, Polo Gufler, prez pessoa, princess niven, Prokofy Neva, Qie Niangao, Rem Beattie, RodneyLee Jessop, Saijanai Kuhn, Seg Baphomet, Sergen Davies, Shirley Marquez, SignpostMarv Martin, Sindy Tsure, Sira Arbizu, Skips Jigsaw, Sougent Harrop, Spritely Pixel, Squirrel Wood, StarSong Bright, Subversive Writer, Sugarcult Dagger, Sylumm Grigorovich, Tammy Nowotny, Tanooki Darkes, Tayra Dagostino, Theoretical Chemistry, Thickbrick Sleaford, valerie rosewood, Vex Streeter, Vixen Heron, Whoops Babii, Winter Ventura, Xiki Luik, Yann Dufaux, Yina Yao, Yukinoroh Kamachi, Zolute Infinity, Zwagoth Klaar
+
+
+To be a success in business, be daring, be first, be different. --Henry Marchant
+ </text_editor>
+ </panel>
+ <panel name="licenses_panel">
+ <text_editor name="credits_editor">
3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
APR Copyright (C) 2000-2004 The Apache Software Foundation
cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
@@ -26,9 +35,9 @@ google-perftools Copyright (c) 2005, Google Inc.
All rights reserved. See licenses.txt for details.
Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
-
-To be a success in business, be daring, be first, be different. --Henry Marchant
</text_editor>
+ </panel>
+</tab_container>
<string name="you_are_at">
U bent op [POSITION]
</string>
diff --git a/indra/newview/skins/default/xui/nl/floater_about_land.xml b/indra/newview/skins/default/xui/nl/floater_about_land.xml
index a3e3b246fe..3a77de70d2 100644
--- a/indra/newview/skins/default/xui/nl/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/nl/floater_about_land.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterland" title="Over land">
+<floater name="floaterland" title="OVER LAND">
<tab_container name="landtab">
<panel label="Algemeen" name="land_general_panel">
<text name="Name:">
@@ -79,45 +79,45 @@
<button label="Land Afstaan..." label_selected="Land Afstaan..." name="Abandon Land..."/>
<button label="Land terugvorderen..." label_selected="Land terugvorderen..." name="Reclaim Land..."/>
<button label="Lindenverkoop..." label_selected="Lindenverkoop..." name="Linden Sale..." tool_tip="Land moet in bezit zijn, de inhoud moet ingesteld zijn en niet al ter veiling zijn aangeboden."/>
- <string name="new users only">
+ <panel.string name="new users only">
Alleen nieuwe gebruikers
- </string>
- <string name="anyone">
+ </panel.string>
+ <panel.string name="anyone">
Iedereen
- </string>
- <string name="area_text">
+ </panel.string>
+ <panel.string name="area_text">
Gebied
- </string>
- <string name="area_size_text">
+ </panel.string>
+ <panel.string name="area_size_text">
[AREA] m²
- </string>
- <string name="auction_id_text">
+ </panel.string>
+ <panel.string name="auction_id_text">
Veiling ID: [ID]
- </string>
- <string name="need_tier_to_modify">
+ </panel.string>
+ <panel.string name="need_tier_to_modify">
U dient uw aankoop te goedkeuren voor u dit land kunt wijzigen.
- </string>
- <string name="group_owned_text">
+ </panel.string>
+ <panel.string name="group_owned_text">
(Groepseigendom)
- </string>
- <string name="profile_text">
+ </panel.string>
+ <panel.string name="profile_text">
Profiel...
- </string>
- <string name="info_text">
+ </panel.string>
+ <panel.string name="info_text">
Informatie...
- </string>
- <string name="public_text">
+ </panel.string>
+ <panel.string name="public_text">
(public)
- </string>
- <string name="none_text">
+ </panel.string>
+ <panel.string name="none_text">
(none)
- </string>
- <string name="sale_pending_text">
+ </panel.string>
+ <panel.string name="sale_pending_text">
(Verkoop bezig)
- </string>
- <string name="no_selection_text">
+ </panel.string>
+ <panel.string name="no_selection_text">
Geen perceel geselecteerd. Ga naar Wereld menu &gt; Over land of selecteer een ander perceel om zijn details te tonen.
- </string>
+ </panel.string>
</panel>
<panel label="Convenant" name="land_covenant_panel">
<text name="estate_section_lbl">
@@ -147,47 +147,47 @@
<text name="region_name_lbl">
Naam:
</text>
- <text name="region_name_text">
+ <text name="region_name_text" left="114">
leyla
</text>
<text name="region_landtype_lbl">
Type:
</text>
- <text name="region_landtype_text">
+ <text name="region_landtype_text" left="114">
Mainland / Homestead
</text>
<text name="region_maturity_lbl">
Inhoudscategorie:
</text>
- <text name="region_maturity_text">
+ <text name="region_maturity_text" left="114">
Adult
</text>
<text name="resellable_lbl">
Doorverkopen:
</text>
- <text name="resellable_clause">
+ <text name="resellable_clause" left="114">
Land in deze regio mag niet worden doorverkocht.
</text>
<text name="changeable_lbl">
Opsplitsen:
</text>
- <text name="changeable_clause">
+ <text name="changeable_clause" left="114" width="340">
Land in deze regio mag niet worden samengevoegd/opgesplitst.
</text>
- <string name="can_resell">
+ <panel.string name="can_resell">
Aangekocht land in deze regio mag worden doorverkocht.
- </string>
- <string name="can_not_resell">
+ </panel.string>
+ <panel.string name="can_not_resell">
Aangekocht land in deze regio mag niet worden doorverkocht.
- </string>
- <string name="can_change">
+ </panel.string>
+ <panel.string name="can_change">
Aangekocht land in deze regio mag worden samengevoegd of
opgedeeld.
- </string>
- <string name="can_not_change">
+ </panel.string>
+ <panel.string name="can_not_change">
Aangekocht land in deze regio mag niet worden samengevoegd
of opgedeeld.
- </string>
+ </panel.string>
</panel>
<panel label="Objecten" name="land_objects_panel">
<text name="parcel_object_bonus">
@@ -199,12 +199,12 @@ of opgedeeld.
<text name="objects_available" left="214" width="230">
[COUNT] van [MAX] ([AVAILABLE] beschikbaar)
</text>
- <string name="objects_available_text">
+ <panel.string name="objects_available_text">
[COUNT] van [MAX] ([AVAILABLE] beschikbaar)
- </string>
- <string name="objects_deleted_text">
+ </panel.string>
+ <panel.string name="objects_deleted_text">
[COUNT] van [MAX] ([DELETED] zullen worden verwijderd)
- </string>
+ </panel.string>
<text name="Primitives parcel supports:" width="200">
Primitieven ondersteund door perceel:
</text>
@@ -292,108 +292,83 @@ of opgedeeld.
<check_box label="Veilig (geen letsel)" name="check safe" tool_tip="Indien aangevinkt, wordt het land op Veilig ingesteld, waarmee letselgevechten worden uitgeschakeld. Indien niet aangevinkt, is letsel ingeschakeld."/>
<check_box label="Niet duwen" name="PushRestrictCheck" tool_tip="Weerhoudt scripts van duwen. Het aanvinken van deze optie kan handig zijn om storend gedrag op uw land te voorkomen."/>
<check_box label="Toon plaats in Zoeken (L$30/week) onder" name="ShowDirectoryCheck" tool_tip="Laat mensen dit perceel zien in zoekresultaten."/>
- <string name="search_enabled_tooltip">
+ <panel.string name="search_enabled_tooltip">
Laat mensen dit perceel zien in zoekresultaten
- </string>
- <string name="search_disabled_small_tooltip">
+ </panel.string>
+ <panel.string name="search_disabled_small_tooltip">
Deze optie is uitgeschakeld, omdat dit gebied 128 m² of kleiner is. Alleen grote percelen kunnen worden opgenomen in Zoeken.
- </string>
- <string name="search_disabled_permissions_tooltip">
+ </panel.string>
+ <panel.string name="search_disabled_permissions_tooltip">
Deze optie is uitgeschakeld omdat u de opties van dit perceel niet kunt wijzigen.
- </string>
+ </panel.string>
<combo_box name="land category with adult">
- <combo_item name="AnyCategory">
- Alle Categorieën
- </combo_item>
- <combo_item name="LindenLocation">
- Linden locatie
- </combo_item>
- <combo_item name="Adult">
- Adult
- </combo_item>
- <combo_item name="Arts&amp;Culture">
- Kunst &amp; Cultuur
- </combo_item>
- <combo_item name="Business">
- Zakelijk
- </combo_item>
- <combo_item name="Educational">
- Educatief
- </combo_item>
- <combo_item name="Gaming">
- Spellen
- </combo_item>
- <combo_item name="Hangout">
- Ontmoetingsplaats
- </combo_item>
- <combo_item name="NewcomerFriendly">
- Nieuwkomervriendelijk
- </combo_item>
- <combo_item name="Parks&amp;Nature">
- Parken &amp; natuur
- </combo_item>
- <combo_item name="Residential">
- Woongebied
- </combo_item>
- <combo_item name="Shopping">
- Winkelen
- </combo_item>
- <combo_item name="Other">
- Anders
- </combo_item>
+ <combo_box.item name="item0" label="Alle Categorieën"
+ />
+ <combo_box.item name="item1" label="Linden locatie"
+ />
+ <combo_box.item name="item2" label="Adult"
+ />
+ <combo_box.item name="item3" label="Kunst &amp; Cultuur"
+ />
+ <combo_box.item name="item4" label="Zakelijk"
+ />
+ <combo_box.item name="item5" label="Educatief"
+ />
+ <combo_box.item name="item6" label="Spelen"
+ />
+ <combo_box.item name="item7" label="Ontmoetingsplaats"
+ />
+ <combo_box.item name="item8" label="Nieuwkomervriendelijk"
+ />
+ <combo_box.item name="item9" label="Parken &amp; natuur"
+ />
+ <combo_box.item name="item10" label="Woongebied"
+ />
+ <combo_box.item name="item11" label="Winkelen"
+ />
+ <combo_box.item name="item12" label="Anders"
+ />
</combo_box>
<combo_box name="land category">
- <combo_item name="AnyCategory">
- Alle categorieën
- </combo_item>
- <combo_item name="LindenLocation">
- Linden Locatie
- </combo_item>
- <combo_item name="Arts&amp;Culture">
- Kunst &amp; Cultuur
- </combo_item>
- <combo_item name="Business">
- Zakelijk
- </combo_item>
- <combo_item name="Educational">
- Educatief
- </combo_item>
- <combo_item name="Gaming">
- Spelen
- </combo_item>
- <combo_item name="Hangout">
- Ontmoetingsplaats
- </combo_item>
- <combo_item name="NewcomerFriendly">
- Nieuwkomervriendelijk
- </combo_item>
- <combo_item name="Parks&amp;Nature">
- Parken &amp; Natuur
- </combo_item>
- <combo_item name="Residential">
- Woongebied
- </combo_item>
- <combo_item name="Shopping">
- Winkelen
- </combo_item>
- <combo_item name="Other">
- Anders
- </combo_item>
+ <combo_box.item name="item0" label="Alle categorieën"
+ />
+ <combo_box.item name="item1" label="Linden Locatie"
+ />
+ <combo_box.item name="item3" label="Kunst &amp; Cultuur"
+ />
+ <combo_box.item name="item4" label="Zakelijk"
+ />
+ <combo_box.item name="item5" label="Educatief"
+ />
+ <combo_box.item name="item6" label="Spelen"
+ />
+ <combo_box.item name="item7" label="Ontmoetingsplaats"
+ />
+ <combo_box.item name="item8" label="Nieuwkomervriendelijk"
+ />
+ <combo_box.item name="item9" label="Parken &amp; Natuur"
+ />
+ <combo_box.item name="item10" label="Woongebied"
+ />
+ <combo_box.item name="item11" label="Winkelen"
+ />
+ <combo_box.item name="item12" label="Anders"
+ />
</combo_box>
<button label="?" label_selected="?" name="?"/>
<check_box label="Mature inhoud" name="MatureCheck" tool_tip=" "/>
- <string name="mature_check_mature">
+ <panel.string name="mature_check_mature">
Mature inhoud
- </string>
- <string name="mature_check_adult">
+ </panel.string>
+ <panel.string name="mature_check_adult">
Adult inhoud
- </string>
- <string name="mature_check_mature_tooltip">
+ </panel.string>
+ <panel.string name="mature_check_mature_tooltip">
Uw perceelinformatie of -inhoud wordt beschouwd als mature.
- </string>
- <string name="mature_check_adult_tooltip">
+ </panel.string>
+ <panel.string name="mature_check_adult_tooltip">
Uw perceelinformatie of -inhoud wordt beschouwd als adult.
- </string>
+ </panel.string>
<text name="Snapshot:">
Foto:
</text>
@@ -401,31 +376,28 @@ of opgedeeld.
<text name="landing_point">
Landingsplaats: [LANDING]
</text>
- <string name="landing_point_none">
+ <panel.string name="landing_point_none">
(none)
- </string>
+ </panel.string>
<button width="70" label="Instellen" label_selected="Instellen" name="Set" tool_tip="Stelt het landingspunt in waar bezoekers arriveren. Wordt ingesteld op uw avatar&apos;s positie binnen dit perceel."/>
- <button width="70" left="311" label="Opschonen" label_selected="Opschonen" name="Clear" tool_tip="Landingspunt leegmaken"/>
+ <button width="80" left="311" label="Opschonen" label_selected="Opschonen" name="Clear" tool_tip="Landingspunt leegmaken"/>
<text name="Teleport Routing: ">
Teleport routering:
</text>
<combo_box name="landing type" tool_tip="Teleport routering -- selecteer hoe teleports naar uw land moeten worden afgehandeld.">
- <combo_item name="Blocked">
- Geblokkeerd
- </combo_item>
- <combo_item name="LandingPoint">
- Landingsplaats
- </combo_item>
- <combo_item name="Anywhere">
- Overal
- </combo_item>
+ <combo_box.item name="Blocked" label="Geblokkeerd"
+ />
+ <combo_box.item name="LandingPoint" label="Landingsplaats"
+ />
+ <combo_box.item name="Anywhere" label="Overal"
+ />
</combo_box>
- <string name="push_restrict_text">
+ <panel.string name="push_restrict_text">
Niet duwen
- </string>
- <string name="push_restrict_region_text">
+ </panel.string>
+ <panel.string name="push_restrict_region_text">
Niet duwen (ingesteld op regio)
- </string>
+ </panel.string>
</panel>
<panel label="Media" name="land_media_panel">
<text name="with media:">
@@ -490,18 +462,16 @@ hebt geklikt.)
</text>
<check_box label="Inwoners die geen betalingsinformatie hebben gegeven aan Linden Lab" name="limit_payment" tool_tip="Verban ongeïdentificeerde inwoners."/>
<check_box label="Inwoners die geen leeftijdgeverifieerde volwassenen zijn" name="limit_age_verified" tool_tip="Verban inwoners die hun leeftijd niet geverifieerd hebben. Zie support.secondlife.com voor meer informatie."/>
- <string name="estate_override">
+ <panel.string name="estate_override">
Een of meer van deze opties is op estate-niveau ingesteld
- </string>
+ </panel.string>
<check_box label="Groepstoegang toestaan: [GROUP]" name="GroupCheck" tool_tip="Stel de groep in op het tabblad Algemeen"/>
<check_box label="Verkoop toegangspassen aan:" name="PassCheck" tool_tip="Tijdelijke toegang tot dit perceel toestaan"/>
<combo_box name="pass_combo" left_delta="190">
- <combo_item name="Anyone">
- Iedereen
- </combo_item>
- <combo_item name="Group">
- Groep
- </combo_item>
+ <combo_box.item name="Anyone" label="Iedereen"
+ />
+ <combo_box.item name="Group" label="Groep"
+ />
</combo_box>
<spinner label="Prijs in L$:" name="PriceSpin" label_width="168" width="228" />
<spinner label="Toegangsuren" name="HoursSpin" label_width="168" width="228" />
diff --git a/indra/newview/skins/default/xui/nl/floater_auction.xml b/indra/newview/skins/default/xui/nl/floater_auction.xml
index eb061e028d..611024699b 100644
--- a/indra/newview/skins/default/xui/nl/floater_auction.xml
+++ b/indra/newview/skins/default/xui/nl/floater_auction.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_auction" title="Start Linden Land Verkoop">
+<floater name="floater_auction" title="START LINDEN LAND VERKOOP">
<check_box label="Voeg geel selectie kader toe" name="fence_check"/>
<button label="Foto" label_selected="Foto" name="snapshot_btn"/>
<button label="OK" label_selected="OK" name="ok_btn"/>
diff --git a/indra/newview/skins/default/xui/nl/floater_beacons.xml b/indra/newview/skins/default/xui/nl/floater_beacons.xml
index 84196ac14f..ecc485e354 100644
--- a/indra/newview/skins/default/xui/nl/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/nl/floater_beacons.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="beacons" title="Bakens">
+<floater name="beacons" title="BAKENS">
<panel name="beacons_panel">
<check_box label="Gescripte objecten met alleen Aanraken" name="touch_only"/>
<check_box label="Gescripte objecten" name="scripted"/>
diff --git a/indra/newview/skins/default/xui/nl/floater_bulk_perms.xml b/indra/newview/skins/default/xui/nl/floater_bulk_perms.xml
index 7f35ec45a9..5374ffc26a 100644
--- a/indra/newview/skins/default/xui/nl/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/nl/floater_bulk_perms.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterbulkperms" title="Bulk wijzigen inhoud permissies">
+<floater name="floaterbulkperms" title="BULK WIJZIGEN INHOUD PERMISSIES">
<text name="applyto">
Inhoud Typen
</text>
diff --git a/indra/newview/skins/default/xui/nl/floater_bumps.xml b/indra/newview/skins/default/xui/nl/floater_bumps.xml
index 9dbfe405aa..df9a99d62e 100644
--- a/indra/newview/skins/default/xui/nl/floater_bumps.xml
+++ b/indra/newview/skins/default/xui/nl/floater_bumps.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_bumps" title="Botsingen, duwen &amp; slaan">
+<floater name="floater_bumps" title="BOTSINGEN, DUWEN &amp; SLAAN">
<string name="none_detected">
Geen gedetecteerd
</string>
diff --git a/indra/newview/skins/default/xui/nl/floater_buy_contents.xml b/indra/newview/skins/default/xui/nl/floater_buy_contents.xml
index 0c513c923a..4c0ff7d04a 100644
--- a/indra/newview/skins/default/xui/nl/floater_buy_contents.xml
+++ b/indra/newview/skins/default/xui/nl/floater_buy_contents.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_buy_contents" title="Koop inhoud">
+<floater name="floater_buy_contents" title="KOOP INHOUD">
<text name="contains_text">
[NAME] bevat:
</text>
<text name="buy_text">
Koop voor L$[AMOUNT] van [NAME]?
</text>
- <button label="Annuleren" label_selected="Annuleren" name="cancel_btn"/>
+ <button label="Annuleren" label_selected="Annuleren" name="cancel_btn" width="73"/>
<button label="Koop" label_selected="Koop" name="buy_btn"/>
<check_box label="Draag kleding nu" name="wear_check"/>
<string name="no_copy_text">
diff --git a/indra/newview/skins/default/xui/nl/floater_buy_currency.xml b/indra/newview/skins/default/xui/nl/floater_buy_currency.xml
index 9f740b86c8..6ee5cc5341 100644
--- a/indra/newview/skins/default/xui/nl/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/nl/floater_buy_currency.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="buy currency" title="Koop valuta">
+<floater name="buy currency" title="KOOP VALUTA">
<text name="info_buying">
Valuta kopen
</text>
@@ -29,7 +29,7 @@
1234
</line_editor>
<text name="currency_est" left_delta="80">
- voor ong. US$ [USD]
+ voor ong. [LOCALAMOUNT]
</text>
<text name="getting_data">
Data ophalen…
@@ -63,6 +63,6 @@ Verhoog de hoeveelheid die gekocht moet worden.
<button label="Annuleren" name="cancel_btn"/>
<button label="Kopen" name="buy_btn"/>
<string name="buy_currency">
- Koop L$ [LINDENS] voor ong. US$ [USD]
+ Koop L$ [LINDENS] voor ong. [LOCALAMOUNT]
</string>
</floater>
diff --git a/indra/newview/skins/default/xui/nl/floater_buy_land.xml b/indra/newview/skins/default/xui/nl/floater_buy_land.xml
index 69726fc2c8..04990e78db 100644
--- a/indra/newview/skins/default/xui/nl/floater_buy_land.xml
+++ b/indra/newview/skins/default/xui/nl/floater_buy_land.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="buy land" title="Koop land">
+<floater name="buy land" title="KOOP LAND">
<text name="region_name_label">
Regio:
</text>
@@ -36,10 +36,11 @@
<text name="covenant_text">
U moet instemmen met het estate convenant:
</text>
+ <text left="470" name="covenant_timestamp_text"/>
<text_editor name="covenant_editor">
Laden...
</text_editor>
- <check_box label="Ik ga akkoord met het hierboven beschreven convenant." name="agree_covenant"/>
+ <check_box label="Ik ga akkoord met het hierboven &#10;beschreven convenant." name="agree_covenant"/>
<text name="info_parcel_label">
Perceel:
</text>
@@ -74,15 +75,9 @@ verkocht met objecten
Alleen premiumleden kunnen land bezitten.
</text>
<combo_box name="account_level">
- <combo_item name="US$9.95/month,billedmonthly">
- US$9.95/maand, gefactureerd per maand
- </combo_item>
- <combo_item name="US$7.50/month,billedquarterly">
- US$7.50/maand, gefactureerd per kwartaal
- </combo_item>
- <combo_item name="US$6.00/month,billedannually">
- US$6.00/maand, gefactureerd per jaar
- </combo_item>
+ <combo_box.item name="US$9.95/month,billedmonthly" label="US$9.95/maand, gefactureerd per maand"/>
+ <combo_box.item name="US$7.50/month,billedquarterly" label="US$7.50/maand, gefactureerd per kwartaal"/>
+ <combo_box.item name="US$6.00/month,billedannually" label="US$6.00/maand, gefactureerd per jaar"/>
</combo_box>
<text name="land_use_action">
Verhoog uw maandelijkse landgebruikskosten tot US$ 40/maand
diff --git a/indra/newview/skins/default/xui/nl/floater_buy_object.xml b/indra/newview/skins/default/xui/nl/floater_buy_object.xml
index c83f2008c6..5d2d9dd3d0 100644
--- a/indra/newview/skins/default/xui/nl/floater_buy_object.xml
+++ b/indra/newview/skins/default/xui/nl/floater_buy_object.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="contents" title="Koop een kopie van object">
+<floater name="contents" title="KOOP EEN KOPIE VAN OBJECT">
<text name="contents_text">
en zijn inhoud:
</text>
diff --git a/indra/newview/skins/default/xui/nl/floater_camera.xml b/indra/newview/skins/default/xui/nl/floater_camera.xml
index a6b843a0a2..81a3ed8a58 100644
--- a/indra/newview/skins/default/xui/nl/floater_camera.xml
+++ b/indra/newview/skins/default/xui/nl/floater_camera.xml
@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move floater" title="">
- <string name="rotate_tooltip">
+<floater name="camera_floater" title="">
+ <floater.string name="rotate_tooltip">
Roteer camera rond focus
- </string>
- <string name="zoom_tooltip">
+ </floater.string>
+ <floater.string name="zoom_tooltip">
Zoom camera naar focus
- </string>
- <string name="move_tooltip">
+ </floater.string>
+ <floater.string name="move_tooltip">
Beweeg camera omhoog en omlaag, links en rechts
- </string>
+ </floater.string>
+ <panel name="controls">
+ <joystick_track name="cam_track_stick" tool_tip="Beweeg camera omhoog en omlaag, links en rechts"/>
+ <joystick_zoom name="zoom" tool_tip="Zoom camera naar focus"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/nl/floater_choose_group.xml b/indra/newview/skins/default/xui/nl/floater_choose_group.xml
index 3f6ce44cfd..8d54d62d2d 100644
--- a/indra/newview/skins/default/xui/nl/floater_choose_group.xml
+++ b/indra/newview/skins/default/xui/nl/floater_choose_group.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="groups" title="Groepen">
+<floater name="groups" title="GROEPEN">
<text name="groupdesc">
Kies een groep:
</text>
diff --git a/indra/newview/skins/default/xui/nl/floater_color_picker.xml b/indra/newview/skins/default/xui/nl/floater_color_picker.xml
index 24b242e15c..9b61af0710 100644
--- a/indra/newview/skins/default/xui/nl/floater_color_picker.xml
+++ b/indra/newview/skins/default/xui/nl/floater_color_picker.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="ColorPicker" title="Kleurkiezer">
+<floater name="ColorPicker" title="KLEURKIEZER">
<text name="r_val_text">
Rood:
</text>
@@ -18,13 +18,14 @@
<text name="l_val_text">
Lum:
</text>
- <check_box label="Meteen toepassen" name="apply_immediate"/>
+ <check_box label="Direct toepassen" name="apply_immediate"/>
<button label="Annuleren" label_selected="Annuleren" name="cancel_btn"/>
<button label="Selecteer" label_selected="Selecteer" name="select_btn"/>
<text name="Current color:">
Huidige kleur:
</text>
<text name="(Drag below to save.)">
- (Sleep naar beneden om op te slaan.)
+ (Sleep naar beneden
+ om op te slaan)
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/nl/floater_customize.xml b/indra/newview/skins/default/xui/nl/floater_customize.xml
index 7354c91047..4de26347e1 100644
--- a/indra/newview/skins/default/xui/nl/floater_customize.xml
+++ b/indra/newview/skins/default/xui/nl/floater_customize.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater customize" title="Uiterlijk" width="504">
- <tab_container name="customize tab container" tab_min_width="106" width="502">
- <panel label="Lichaamsdelen" name="body_parts_placeholder"/>
- <panel label="Postuur" name="Shape" left="112" width="389">
+<floater name="floater customize" title="UITERLIJK" width="551">
+ <tab_container name="customize tab container" tab_min_width="120" width="549">
+ <placeholder label="Lichaamsdelen" name="body_parts_placeholder"/>
+ <panel label="Postuur" name="Shape" left="124" width="389">
<button label="Herstel" label_selected="Herstel" name="Revert"/>
<button label="Lichaam" label_selected="Lichaam" name="Body"/>
<button label="Hoofd" label_selected="Hoofd" name="Head"/>
@@ -14,12 +14,8 @@
<button label="Torso" label_selected="Torso" name="Torso"/>
<button label="Benen" label_selected="Benen" name="Legs"/>
<radio_group name="sex radio">
- <radio_item name="radio">
- Vrouw
- </radio_item>
- <radio_item name="radio2">
- Man
- </radio_item>
+ <radio_item name="radio" label="Vrouw" />
+ <radio_item name="radio2" label="Man" />
</radio_group>
<text name="title">
[DESC]
@@ -51,10 +47,10 @@ te slepen. Ook kunt u zelf van begin af aan een nieuwe creëren en dragen.
<button label="Opslaan als..." label_selected="Opslaan als..." name="Save As"/>
</panel>
<panel label="Huid" name="Skin">
- <button width="88" label="Huidskleur" label_selected="Huidskleur" name="Skin Color"/>
- <button width="88" label="Gezichtsdetail" label_selected="Gezichtsdetail" name="Face Detail"/>
- <button width="88" label="Make-up" label_selected="Make-up" name="Makeup"/>
- <button width="88" label="Lichaam detail" label_selected="Lichaam detail" name="Body Detail"/>
+ <button width="104" label="Huidskleur" label_selected="Huidskleur" name="Skin Color"/>
+ <button width="104" label="Gezichtsdetail" label_selected="Gezichtsdetail" name="Face Detail"/>
+ <button width="104" label="Make-up" label_selected="Make-up" name="Makeup"/>
+ <button width="104" label="Lichaam detail" label_selected="Lichaam detail" name="Body Detail"/>
<text name="title">
[DESC]
</text>
@@ -80,9 +76,9 @@ slepen. Ook kunt u zelf van begin af aan een nieuwe creëren en dragen.
<text name="Item Action Label">
Huid:
</text>
- <texture_picker width="88" label="Hoofd tatoeages" name="Head Tattoos" tool_tip="Klik om een afbeelding te kiezen"/>
- <texture_picker width="88" label="Bovenste tatoeage" name="Upper Tattoos" tool_tip="Klik om een afbeelding te kiezen"/>
- <texture_picker width="88" label="Onderste tatoeages" name="Lower Tattoos" tool_tip="Klik om een afbeelding te kiezen"/>
+ <texture_picker width="104" label="Hoofd tatoeages" name="Head Tattoos" tool_tip="Klik om een afbeelding te kiezen"/>
+ <texture_picker width="104" label="Bovenste tatoeage" name="Upper Tattoos" tool_tip="Klik om een afbeelding te kiezen"/>
+ <texture_picker width="104" label="Onderste tatoeages" name="Lower Tattoos" tool_tip="Klik om een afbeelding te kiezen"/>
<button label="Nieuwe huid maken" label_selected="Nieuwe huid maken" name="Create New"/>
<button label="Opslaan" label_selected="Opslaan" name="Save"/>
<button label="Opslaan als..." label_selected="Opslaan als..." name="Save As"/>
@@ -356,7 +352,7 @@ te slepen. Ook kunt u zelf van begin af aan nieuwe creëren en dragen.
</text>
<texture_picker label="Stof" name="Fabric" tool_tip="Klik om een afbeelding te kiezen"/>
<color_swatch label="Kleur/tint" name="Color/Tint" tool_tip="Klik om de kleurkiezer te openen"/>
- <button label="Nieuwe handschoenen maken" label_selected="Nieuwe handschoenen maken" name="Create New" width="180"/>
+ <button label="Nieuwe handschoenen maken" label_selected="Nieuwe handschoenen maken" name="Create New" width="190"/>
<button label="Uitdoen" label_selected="Uitdoen" name="Take Off"/>
<button label="Opslaan" label_selected="Opslaan" name="Save"/>
<button label="Opslaan als..." label_selected="Opslaan als..." name="Save As"/>
@@ -466,7 +462,7 @@ slepen. Ook kunt u zelf van begin af aan een nieuwe creëren en dragen.
<button label="Herstel" label_selected="Herstel" name="Revert"/>
</panel>
</tab_container>
- <scroll_container left="207" name="panel_container"/>
+ <scroll_container left="254" name="panel_container"/>
<button label="Annuleren" label_selected="Annuleren" name="Cancel"/>
<button label="OK" label_selected="OK" name="Ok"/>
<button label="Maak kleding..." label_selected="Maak kleding..." name="Make Outfit" left="110"/>
diff --git a/indra/newview/skins/default/xui/nl/floater_env_settings.xml b/indra/newview/skins/default/xui/nl/floater_env_settings.xml
index d212f544c5..3c207040d2 100644
--- a/indra/newview/skins/default/xui/nl/floater_env_settings.xml
+++ b/indra/newview/skins/default/xui/nl/floater_env_settings.xml
@@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Environment Editor Floater" title="Omgeving editor">
- <text name="EnvTimeText">
- Tijd van de dag
+<floater name="Environment Editor Floater" title="OMGEVING EDITOR">
+ <text bottom="-42" name="EnvTimeText">
+ Tijd van de
+dag
</text>
- <text name="EnvTimeText2">
+ <text bottom_delta="-36" name="EnvTimeText2">
0:00
</text>
<text name="EnvCloudText">
diff --git a/indra/newview/skins/default/xui/nl/floater_font_test.xml b/indra/newview/skins/default/xui/nl/floater_font_test.xml
index 8e8b07ee1a..31e53e7fba 100644
--- a/indra/newview/skins/default/xui/nl/floater_font_test.xml
+++ b/indra/newview/skins/default/xui/nl/floater_font_test.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="contents" title="Lettertypetest">
+<floater name="contents" title="LETTERTYPETEST">
<text name="linea">
Overschrijf test, zou hier moeten verschijnen als Times (vanuit default/xui/en-us).
</text>
diff --git a/indra/newview/skins/default/xui/nl/floater_gesture.xml b/indra/newview/skins/default/xui/nl/floater_gesture.xml
index d38972d5fe..4fa994c69e 100644
--- a/indra/newview/skins/default/xui/nl/floater_gesture.xml
+++ b/indra/newview/skins/default/xui/nl/floater_gesture.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="gestures" title="Actieve gebaren">
+<floater name="gestures" title="ACTIEVE GEBAREN">
<text name="help_label">
Dubbelklik een gebaar om animaties en geluiden af te spelen
</text>
diff --git a/indra/newview/skins/default/xui/nl/floater_hud.xml b/indra/newview/skins/default/xui/nl/floater_hud.xml
index 9da732ff2f..8ef7de1b02 100644
--- a/indra/newview/skins/default/xui/nl/floater_hud.xml
+++ b/indra/newview/skins/default/xui/nl/floater_hud.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_hud" title="Handleiding"/>
+<floater name="floater_hud" title="HANDLEIDING"/>
diff --git a/indra/newview/skins/default/xui/nl/floater_inspect.xml b/indra/newview/skins/default/xui/nl/floater_inspect.xml
index d4fa75d94f..6a0885b57f 100644
--- a/indra/newview/skins/default/xui/nl/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/nl/floater_inspect.xml
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="inspect" title="Objecten inspecteren">
+<floater name="inspect" title="OBJECTEN INSPECTEREN">
<scroll_list name="object_list" tool_tip="Selecteer een object van deze lijst om het in-wereld te markeren">
<column label="Objectnaam" name="object_name"/>
- <column label="Eigenaarnaam" name="owner_name"/>
- <column label="Makernaam:" name="creator_name"/>
+ <column label="Eigenaar" name="owner_name"/>
+ <column label="Maker" name="creator_name"/>
<column label="Aanmaakdatum" name="creation_date"/>
</scroll_list>
- <button label="Bekijk eigenaarprofiel..." label_selected="" name="button owner" tool_tip="Bekijk het profiel van de eigenaar van het gemarkeerde object"/>
- <button label="Bekijk makerprofiel..." label_selected="" name="button creator" tool_tip="Bekijk het profiel van de originele maker van het gemarkeerde object"/>
+ <button label="Toon profiel eigenaar..." label_selected="" name="button owner" tool_tip="Bekijk het profiel van de eigenaar van het gemarkeerde object"/>
+ <button label="Toon profiel maker..." label_selected="" name="button creator" tool_tip="Bekijk het profiel van de originele maker van het gemarkeerde object"/>
</floater>
diff --git a/indra/newview/skins/default/xui/nl/floater_inventory.xml b/indra/newview/skins/default/xui/nl/floater_inventory.xml
index 272fa3c899..a69039d811 100644
--- a/indra/newview/skins/default/xui/nl/floater_inventory.xml
+++ b/indra/newview/skins/default/xui/nl/floater_inventory.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Inventory" title="Inventaris">
+<floater name="Inventory" title="INVENTARIS">
<search_editor label="Typ hier om te zoeken" name="inventory search editor"/>
<tab_container name="inventory filter tabs">
<inventory_panel label="Alle items" name="All Items"/>
diff --git a/indra/newview/skins/default/xui/nl/floater_joystick.xml b/indra/newview/skins/default/xui/nl/floater_joystick.xml
index 27556a89f8..505e3cd719 100644
--- a/indra/newview/skins/default/xui/nl/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/nl/floater_joystick.xml
@@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Joystick" title="Joystick configuratie">
- <check_box name="enable_joystick">
- Joystick inschakelen
- </check_box>
+<floater name="Joystick" title="JOYSTICK CONFIGURATIE">
+ <check_box name="enable_joystick" width="80" label="Joystick inschakelen:"/>
+ <text left="146" name="joystick_type" width="360"/>
<spinner label="X-as mapping" name="JoystickAxis1"/>
<spinner label="Y-as mapping" name="JoystickAxis2"/>
<spinner label="Z-as mapping" name="JoystickAxis0"/>
@@ -16,15 +15,9 @@
<text name="Control Modes:">
Besturingsmodi:
</text>
- <check_box name="JoystickAvatarEnabled">
- Avatar
- </check_box>
- <check_box name="JoystickBuildEnabled">
- Bouwen
- </check_box>
- <check_box name="JoystickFlycamEnabled">
- Vliegcamera
- </check_box>
+ <check_box name="JoystickAvatarEnabled" label="Avatar"/>
+ <check_box name="JoystickBuildEnabled" label="Bouwen"/>
+ <check_box name="JoystickFlycamEnabled" label="Vliegcamera"/>
<text name="XScale">
X schaal
</text>
@@ -52,7 +45,7 @@
<text name="ZDeadZone">
Z dode zone
</text>
- <text name="PitchDeadZone">
+ <text name="PitchDeadZone" left="4" width="110">
Stampen dode zone
</text>
<text name="YawDeadZone">
@@ -70,15 +63,17 @@
<text name="ZoomDeadZone">
Zoom dode zone
</text>
- <button label="SpaceNavigator standaardwaarden" name="SpaceNavigatorDefaults"/>
+ <button label="SpaceNavigator standaardwaarden" name="SpaceNavigatorDefaults" width="200" font="SansSerifSmall"/>
<button label="OK" label_selected="OK" name="ok_btn"/>
- <button label="Annuleren" label_selected="Annuleren" name="cancel_btn"/>
- <string name="JoystickMonitor">
- Joystick monitor
- </string>
- <string name="Axis">
- As [NUM]
- </string>
+ <button label="Annuleren" label_selected="Annuleren" name="cancel_btn" left_delta="110"/>
+ <stat_view label="Joystick monitor" name="axis_view">
+ <stat_bar label="As 0" name="axis0"/>
+ <stat_bar label="As 1" name="axis1"/>
+ <stat_bar label="As 2" name="axis2"/>
+ <stat_bar label="As 3" name="axis3"/>
+ <stat_bar label="As 4" name="axis4"/>
+ <stat_bar label="As 5" name="axis5"/>
+ </stat_view>
<string name="NoDevice">
Geen apparaat gedetecteerd
</string>
diff --git a/indra/newview/skins/default/xui/nl/floater_lagmeter.xml b/indra/newview/skins/default/xui/nl/floater_lagmeter.xml
index e8b1fb14bc..e3943c2470 100644
--- a/indra/newview/skins/default/xui/nl/floater_lagmeter.xml
+++ b/indra/newview/skins/default/xui/nl/floater_lagmeter.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_lagmeter" title="Lag meter">
+<floater name="floater_lagmeter" title="LAG METER">
<button label="" label_selected="" name="client_lagmeter" tool_tip="Client lag status"/>
<text name="client">
Client:
diff --git a/indra/newview/skins/default/xui/nl/floater_lsl_guide.xml b/indra/newview/skins/default/xui/nl/floater_lsl_guide.xml
index 556d151c8c..27b3ff834e 100644
--- a/indra/newview/skins/default/xui/nl/floater_lsl_guide.xml
+++ b/indra/newview/skins/default/xui/nl/floater_lsl_guide.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="script ed float" title="LSL Wiki">
+<floater name="script ed float" title="LSL WIKI">
<check_box label="Volg cursor" name="lock_check"/>
<combo_box label="Vergrendelen" name="history_combo"/>
<button label="Terug" name="back_btn"/>
diff --git a/indra/newview/skins/default/xui/nl/floater_map.xml b/indra/newview/skins/default/xui/nl/floater_map.xml
new file mode 100644
index 0000000000..29af36e50c
--- /dev/null
+++ b/indra/newview/skins/default/xui/nl/floater_map.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Map">
+ <floater.string name="mini_map_north">
+ N
+ </floater.string>
+ <floater.string name="mini_map_east">
+ O
+ </floater.string>
+ <floater.string name="mini_map_west">
+ W
+ </floater.string>
+ <floater.string name="mini_map_south">
+ Z
+ </floater.string>
+ <floater.string name="mini_map_southeast">
+ ZO
+ </floater.string>
+ <floater.string name="mini_map_northeast">
+ NO
+ </floater.string>
+ <floater.string name="mini_map_southwest">
+ ZW
+ </floater.string>
+ <floater.string name="mini_map_northwest">
+ NW
+ </floater.string>
+ <text label="N" name="floater_map_north" text="N">
+ N
+ </text>
+ <text label="O" name="floater_map_east" text="O">
+ O
+ </text>
+ <text label="W" name="floater_map_west" text="W">
+ W
+ </text>
+ <text label="Z" name="floater_map_south" text="Z">
+ Z
+ </text>
+ <text label="ZO" name="floater_map_southeast" text="ZO">
+ ZO
+ </text>
+ <text label="NO" name="floater_map_northeast" text="NO">
+ NO
+ </text>
+ <text label="ZW" name="floater_map_southwest" text="ZW">
+ ZW
+ </text>
+ <text label="NW" name="floater_map_northwest" text="NW">
+ NW
+ </text>
+</floater>
diff --git a/indra/newview/skins/default/xui/nl/floater_mem_leaking.xml b/indra/newview/skins/default/xui/nl/floater_mem_leaking.xml
index 1c7e070e4a..d0b25587b6 100644
--- a/indra/newview/skins/default/xui/nl/floater_mem_leaking.xml
+++ b/indra/newview/skins/default/xui/nl/floater_mem_leaking.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="MemLeak" title="Geheugenlek simulatie">
+<floater name="MemLeak" title="GEHEUGENLEK SIMULATIE">
<spinner label="Leksnelheid (bytes per frame):" name="leak_speed"/>
<spinner label="Max gelekt geheugen (MB):" name="max_leak"/>
<text name="total_leaked_label">
diff --git a/indra/newview/skins/default/xui/nl/floater_moveview.xml b/indra/newview/skins/default/xui/nl/floater_moveview.xml
index 9b0b95b99a..8a6a874e49 100644
--- a/indra/newview/skins/default/xui/nl/floater_moveview.xml
+++ b/indra/newview/skins/default/xui/nl/floater_moveview.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move floater" title="">
+<floater name="move_floater">
+<panel name="panel_actions">
<button label="" label_selected="" name="turn left btn" tool_tip="Draai links"/>
<button label="" label_selected="" name="turn right btn" tool_tip="Draai rechts"/>
<button label="" label_selected="" name="move up btn" tool_tip="Spring of vlieg omhoog"/>
@@ -8,4 +9,5 @@
<joystick_slide name="slide right btn" tool_tip="Verplaats rechts"/>
<joystick_turn name="forward btn" tool_tip="Verplaats vooruit"/>
<joystick_turn name="backward btn" tool_tip="Verplaats achteruit"/>
+</panel>
</floater>
diff --git a/indra/newview/skins/default/xui/nl/floater_mute_object.xml b/indra/newview/skins/default/xui/nl/floater_mute_object.xml
index efc12f29e2..7a34be1bd7 100644
--- a/indra/newview/skins/default/xui/nl/floater_mute_object.xml
+++ b/indra/newview/skins/default/xui/nl/floater_mute_object.xml
@@ -1,9 +1,11 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="mute by name" title="Negeer object op naam">
- <text name="message">
- Negeer op naam heeft alleen invloed op object chat en IM, niet op geluiden. U dient de naam van het object exact te typen.
+<floater name="mute by name" title="NEGEER OBJECT OP NAAM">
+ <text name="message" bottom_delta="-40">
+ Negeer op naam heeft alleen invloed op object chat
+en IM, niet op geluiden. U dient de naam van het object
+exact te typen.
</text>
- <line_editor name="object_name">
+ <line_editor name="object_name" bottom_delta="-58">
Object naam
</line_editor>
<button label="Ok" name="OK"/>
diff --git a/indra/newview/skins/default/xui/nl/floater_my_friends.xml b/indra/newview/skins/default/xui/nl/floater_my_friends.xml
index ed81e6baf9..8d709d3c00 100644
--- a/indra/newview/skins/default/xui/nl/floater_my_friends.xml
+++ b/indra/newview/skins/default/xui/nl/floater_my_friends.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_my_friends" title="Contacten">
+<floater name="floater_my_friends" title="CONTACTEN">
<tab_container name="friends_and_groups">
<panel label="Vrienden" name="friends_panel"/>
<panel label="Groepen" name="groups_panel"/>
diff --git a/indra/newview/skins/default/xui/nl/floater_openobject.xml b/indra/newview/skins/default/xui/nl/floater_openobject.xml
index 58ca71505a..832c63403d 100644
--- a/indra/newview/skins/default/xui/nl/floater_openobject.xml
+++ b/indra/newview/skins/default/xui/nl/floater_openobject.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="objectcontents" title="Object inhoud">
+<floater name="objectcontents" title="OBJECT INHOUD">
<text name="object_name">
[DESC]:
</text>
- <button label="Kopiëren naar inventaris" label_selected="Kopiëren naar inventaris" name="copy_to_inventory_button"/>
- <button label="Kopiëren en dragen" label_selected="Kopiëren en dragen" name="copy_and_wear_button"/>
+ <button label="Kopiëren naar inventaris" label_selected="Kopiëren naar inventaris" name="copy_to_inventory_button" width="140"/>
+ <button label="Kopiëren en dragen" label_selected="Kopiëren en dragen" name="copy_and_wear_button" left="164"/>
</floater>
diff --git a/indra/newview/skins/default/xui/nl/floater_pay.xml b/indra/newview/skins/default/xui/nl/floater_pay.xml
index 3255412439..4018ebdc93 100644
--- a/indra/newview/skins/default/xui/nl/floater_pay.xml
+++ b/indra/newview/skins/default/xui/nl/floater_pay.xml
@@ -6,10 +6,10 @@
<button label="L$20" label_selected="L$20" name="fastpay 20"/>
<button label="Betaal" label_selected="Betaal" name="pay btn"/>
<button label="Annuleren" label_selected="Annuleren" name="cancel btn"/>
- <text name="payee_label">
+ <text name="payee_label" width="100">
Betaal inwoner:
</text>
- <text name="payee_name">
+ <text name="payee_name" left="110">
[FIRST] [LAST]
</text>
<text name="fastpay text">
diff --git a/indra/newview/skins/default/xui/nl/floater_pay_object.xml b/indra/newview/skins/default/xui/nl/floater_pay_object.xml
index 23a161ac14..d3826648f2 100644
--- a/indra/newview/skins/default/xui/nl/floater_pay_object.xml
+++ b/indra/newview/skins/default/xui/nl/floater_pay_object.xml
@@ -1,21 +1,21 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="Give Money" title="">
- <text name="payee_group">
+ <text name="payee_group" left="5" width="90" halign="left">
Betaal groep:
</text>
- <text name="payee_resident">
+ <text name="payee_resident" left="5" width="90" halign="left">
Betaal inwoner:
</text>
- <text name="payee_name">
+ <text name="payee_name" left="100" width="200">
[FIRST] [LAST]
</text>
- <text name="object_name_label">
+ <text name="object_name_label" left="5" width="90" halign="left">
Via object:
</text>
- <text name="object_name_text">
+ <text name="object_name_text" left="100" width="200">
...
</text>
- <text name="fastpay text">
+ <text name="fastpay text" halign="left">
Snel betalen:
</text>
<text name="amount text">
diff --git a/indra/newview/skins/default/xui/nl/floater_perm_prefs.xml b/indra/newview/skins/default/xui/nl/floater_perm_prefs.xml
index d19b5523f5..f946c42678 100644
--- a/indra/newview/skins/default/xui/nl/floater_perm_prefs.xml
+++ b/indra/newview/skins/default/xui/nl/floater_perm_prefs.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="perm prefs" title="Standaard upload Permissies">
+<floater name="perm prefs" title="STANDAARD UPLOAD PERMISSIES">
<panel label="Permissies" name="permissions">
<button label="?" label_selected="?" name="help"/>
<check_box label="Delen met groep" name="share_with_group"/>
@@ -9,7 +9,7 @@
</text>
<check_box label="Wijzigen" name="next_owner_modify"/>
<check_box label="Kopiëren" name="next_owner_copy"/>
- <check_box label="Verkopen/weggeven" name="next_owner_transfer"/>
+ <check_box label="Verkopen/weggeven" name="next_owner_transfer" left_delta="80"/>
</panel>
<button label="OK" label_selected="OK" name="ok"/>
<button label="Annuleren" label_selected="Annuleren" name="cancel"/>
diff --git a/indra/newview/skins/default/xui/nl/floater_post_process.xml b/indra/newview/skins/default/xui/nl/floater_post_process.xml
index 45fc211aeb..e627f81a70 100644
--- a/indra/newview/skins/default/xui/nl/floater_post_process.xml
+++ b/indra/newview/skins/default/xui/nl/floater_post_process.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Post-Process Floater" title="Nabewerkinginstellingen">
+<floater name="Post-Process Floater" title="NABEWERKINGINSTELLINGEN">
<tab_container name="Post-Process Tabs">
<panel label="Kleurfilter" name="wmiColorFilterPanel">
<check_box label="Inschakelen" name="wmiColorFilterToggle"/>
diff --git a/indra/newview/skins/default/xui/nl/floater_postcard.xml b/indra/newview/skins/default/xui/nl/floater_postcard.xml
index f31b479576..c2d092fdd4 100644
--- a/indra/newview/skins/default/xui/nl/floater_postcard.xml
+++ b/indra/newview/skins/default/xui/nl/floater_postcard.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Postcard" title="Email foto">
+<floater name="Postcard" title="EMAIL FOTO">
<text name="to_label">
Ontvanger e-mail:
</text>
@@ -25,12 +25,12 @@
<button label="Annuleren" name="cancel_btn"/>
<button label="Verzenden" name="send_btn"/>
<string name="default_subject">
- Ansichtkaart uit Second Life
+ Ansichtkaart uit [SECOND_LIFE]
</string>
<string name="default_message">
Kom dit zien!
</string>
<string name="upload_message">
- &quot;Verzenden…&quot;
+ Verzenden...
</string>
</floater>
diff --git a/indra/newview/skins/default/xui/nl/floater_preferences.xml b/indra/newview/skins/default/xui/nl/floater_preferences.xml
index 25984ee65a..6fc8005fd2 100644
--- a/indra/newview/skins/default/xui/nl/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/nl/floater_preferences.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Preferences" title="Voorkeuren">
+<floater name="Preferences" title="VOORKEUREN">
<button label="OK" label_selected="OK" name="OK"/>
<button label="Annuleren" label_selected="Annuleren" name="Cancel"/>
<button label="Toepassen" label_selected="Toepassen" name="Apply"/>
diff --git a/indra/newview/skins/default/xui/nl/floater_region_info.xml b/indra/newview/skins/default/xui/nl/floater_region_info.xml
index 3d4386bc16..0a98da3b4e 100644
--- a/indra/newview/skins/default/xui/nl/floater_region_info.xml
+++ b/indra/newview/skins/default/xui/nl/floater_region_info.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="regioninfo" title="Regio/estate"/>
+<floater name="regioninfo" title="REGIO/ESTATE"/>
diff --git a/indra/newview/skins/default/xui/nl/floater_report_abuse.xml b/indra/newview/skins/default/xui/nl/floater_report_abuse.xml
index 98027a8132..19b11ede0a 100644
--- a/indra/newview/skins/default/xui/nl/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/nl/floater_report_abuse.xml
@@ -1,22 +1,22 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_report_abuse" title="Misbruik rapporteren">
+<floater name="floater_report_abuse" title="MISBRUIK RAPPORTEREN">
<check_box label="Voeg schermafbeelding toe" name="screen_check"/>
- <text name="reporter_title">
+ <text name="reporter_title" width="110">
Rapporteur:
</text>
- <text name="reporter_field">
+ <text name="reporter_field" left_delta="70">
Loremipsum Dolorsitamut
</text>
<text name="sim_title">
Regio:
</text>
- <text name="sim_field">
+ <text name="sim_field" left_delta="70">
Regionaam
</text>
<text name="pos_title">
Positie:
</text>
- <text name="pos_field">
+ <text name="pos_field" left_delta="70">
{128.1, 128.1, 15.4}
</text>
<text name="select_object_label">
@@ -26,7 +26,7 @@
<text name="object_name_label">
Naam:
</text>
- <text name="object_name">
+ <text name="object_name" width="120">
Consetetur Sadipscing
</text>
<text name="owner_name_label">
@@ -36,123 +36,45 @@
Hendrerit Vulputate
</text>
<combo_box name="category_combo" tool_tip="Categorie -- selecteer de categorie die dit rapport het best beschrijft">
- <combo_item name="Select_category">
- Selecteer categorie
- </combo_item>
- <combo_item name="Age__Age_play">
- Leeftijd &gt; Leeftijd spelen
- </combo_item>
- <combo_item name="Age__Adult_resident_on_Teen_Second_Life">
- Leeftijd &gt; Volwassen inwoner in Teen Second Life
- </combo_item>
- <combo_item name="Age__Underage_resident_outside_of_Teen_Second_Life">
- Leeftijd &gt; Minderjarige inwoner buiten Teen Second Life
- </combo_item>
- <combo_item name="Assault__Combat_sandbox___unsafe_area">
- Aanval &gt; Gevechtszandbak / onveilig gebied
- </combo_item>
- <combo_item name="Assault__Safe_area">
- Aanval &gt; Veilig gebied
- </combo_item>
- <combo_item name="Assault__Weapons_testing_sandbox">
- Aanval &gt; Zandbak voor het testen van wapens
- </combo_item>
- <combo_item name="Commerce__Failure_to_deliver_product_or_service">
- Handel &gt; Product of dienst is niet geleverd
- </combo_item>
- <combo_item name="Disclosure__Real_world_information">
- Openbaring &gt; Echte wereld informatie
- </combo_item>
- <combo_item name="Disclosure__Remotely_monitoring chat">
- Openbaring &gt; Op afstand chat afluisteren
- </combo_item>
- <combo_item name="Disclosure__Second_Life_information_chat_IMs">
- Openbaring &gt; Second Life informatie/chat/IMs
- </combo_item>
- <combo_item name="Disturbing_the_peace__Unfair_use_of_region_resources">
- Vredebreuk &gt; Oneerlijk gebruik van regiomiddelen
- </combo_item>
- <combo_item name="Disturbing_the_peace__Excessive_scripted_objects">
- Vredebreuk &gt; Excessieve gescripte objecten
- </combo_item>
- <combo_item name="Disturbing_the_peace__Object_littering">
- Vredebreuk &gt; Objecten laten rondslingeren
- </combo_item>
- <combo_item name="Disturbing_the_peace__Repetitive_spam">
- Vredebreuk &gt; Herhaalde spam
- </combo_item>
- <combo_item name="Disturbing_the_peace__Unwanted_advert_spam">
- Vredebreuk &gt; Ongewenste reclame-spam
- </combo_item>
- <combo_item name="Fraud__L$">
- Fraude &gt; L$
- </combo_item>
- <combo_item name="Fraud__Land">
- Fraude &gt; Land
- </combo_item>
- <combo_item name="Fraud__Pyramid_scheme_or_chain_letter">
- Fraude &gt; Piramideschema of kettingbrief
- </combo_item>
- <combo_item name="Fraud__US$">
- Fraude &gt; US$
- </combo_item>
- <combo_item name="Harassment__Advert_farms___visual_spam">
- Intimidatie &gt; Reclameverzamelingen / visuele spam
- </combo_item>
- <combo_item name="Harassment__Defaming_individuals_or_groups">
- Intimidatie &gt; Individuen of groepen in diskrediet brengen
- </combo_item>
- <combo_item name="Harassment__Impeding_movement">
- Intimidatie &gt; Beweging verhinderen
- </combo_item>
- <combo_item name="Harassment__Sexual_harassment">
- Intimidatie &gt; Seksuele intimidatie
- </combo_item>
- <combo_item name="Harassment__Solicting_inciting_others_to_violate_ToS">
- Intimidatie &gt; Anderen uitnodigen/aanzetten tot het schenden van de ToS
- </combo_item>
- <combo_item name="Harassment__Verbal_abuse">
- Intimidatie &gt; Verbaal misbruik
- </combo_item>
- <combo_item name="Indecency__Broadly_offensive_content_or_conduct">
- Onfatsoenlijkheid &gt; Globaal beledigende inhoud of gedrag
- </combo_item>
- <combo_item name="Indecency__Inappropriate_avatar_name">
- Onfatsoenlijkheid &gt; Ongepaste avatar naam
- </combo_item>
- <combo_item name="Indecency__Mature_content_in_PG_region">
- Onfatsoenlijkheid &gt; Ongepaste inhoud of gedrag in een PG regio
- </combo_item>
- <combo_item name="Indecency__Inappropriate_content_in_Mature_region">
- Onfatsoenlijkheid &gt; Ongepaste inhoud of gedrag in een Mature regio
- </combo_item>
- <combo_item name="Intellectual_property_infringement_Content_Removal">
- Inbreuk op intellectueel eigendom &gt; Verwijderen van inhoud
- </combo_item>
- <combo_item name="Intellectual_property_infringement_CopyBot_or_Permissions_Exploit">
- Inbreuk op intellectueel eigendom &gt; CopyBot of misbruik van permissies
- </combo_item>
- <combo_item name="Intolerance">
- Intolerantie
- </combo_item>
- <combo_item name="Land__Abuse_of_sandbox_resources">
- Land &gt; Misbruik van zandbakmiddelen
- </combo_item>
- <combo_item name="Land__Encroachment__Objects_textures">
- Land &gt; Indringing &gt; Objecten/texturen
- </combo_item>
- <combo_item name="Land__Encroachment__Particles">
- Land &gt; Indringing &gt; Particles
- </combo_item>
- <combo_item name="Land__Encroachment__Trees_plants">
- Land &gt; Indringing &gt; Bomen/planten
- </combo_item>
- <combo_item name="Wagering_gambling">
- Weddenschappen/gokken
- </combo_item>
- <combo_item name="Other">
- Anders
- </combo_item>
+ <combo_box.item name="Select_category" label="Selecteer categorie"/>
+ <combo_box.item name="Age__Age_play" label="Leeftijd &gt; Leeftijd spelen"/>
+ <combo_box.item name="Age__Adult_resident_on_Teen_Second_Life" label="Leeftijd &gt; Volwassen inwoner in Teen Second Life"/>
+ <combo_box.item name="Age__Underage_resident_outside_of_Teen_Second_Life" label="Leeftijd &gt; Minderjarige inwoner buiten Teen Second Life"/>
+ <combo_box.item name="Assault__Combat_sandbox___unsafe_area" label="Aanval &gt; Gevechtszandbak / onveilig gebied"/>
+ <combo_box.item name="Assault__Safe_area" label="Aanval &gt; Veilig gebied"/>
+ <combo_box.item name="Assault__Weapons_testing_sandbox" label="Aanval &gt; Zandbak voor het testen van wapens"/>
+ <combo_box.item name="Commerce__Failure_to_deliver_product_or_service" label="Handel &gt; Product of dienst is niet geleverd"/>
+ <combo_box.item name="Disclosure__Real_world_information" label="Openbaring &gt; Echte wereld informatie"/>
+ <combo_box.item name="Disclosure__Remotely_monitoring chat" label="Openbaring &gt; Op afstand chat afluisteren"/>
+ <combo_box.item name="Disclosure__Second_Life_information_chat_IMs" label="Openbaring &gt; Second Life informatie/chat/IMs"/>
+ <combo_box.item name="Disturbing_the_peace__Unfair_use_of_region_resources" label="Vredebreuk &gt; Oneerlijk gebruik van regiomiddelen"/>
+ <combo_box.item name="Disturbing_the_peace__Excessive_scripted_objects" label="Vredebreuk &gt; Excessieve gescripte objecten"/>
+ <combo_box.item name="Disturbing_the_peace__Object_littering" label="Vredebreuk &gt; Objecten laten rondslingeren"/>
+ <combo_box.item name="Disturbing_the_peace__Repetitive_spam" label="Vredebreuk &gt; Herhaalde spam"/>
+ <combo_box.item name="Disturbing_the_peace__Unwanted_advert_spam" label="Vredebreuk &gt; Ongewenste reclame-spam"/>
+ <combo_box.item name="Fraud__L$" label="Fraude &gt; L$"/>
+ <combo_box.item name="Fraud__Land" label="Fraude &gt; Land"/>
+ <combo_box.item name="Fraud__Pyramid_scheme_or_chain_letter" label="Fraude &gt; Piramideschema of kettingbrief"/>
+ <combo_box.item name="Fraud__US$" label="Fraude &gt; US$"/>
+ <combo_box.item name="Harassment__Advert_farms___visual_spam" label="Intimidatie &gt; Reclameverzamelingen / visuele spam"/>
+ <combo_box.item name="Harassment__Defaming_individuals_or_groups" label="Intimidatie &gt; Individuen of groepen in diskrediet brengen"/>
+ <combo_box.item name="Harassment__Impeding_movement" label="Intimidatie &gt; Beweging verhinderen"/>
+ <combo_box.item name="Harassment__Sexual_harassment" label="Intimidatie &gt; Seksuele intimidatie"/>
+ <combo_box.item name="Harassment__Solicting_inciting_others_to_violate_ToS" label="Intimidatie &gt; Anderen uitnodigen/aanzetten tot het schenden van de ToS"/>
+ <combo_box.item name="Harassment__Verbal_abuse" label="Intimidatie &gt; Verbaal misbruik"/>
+ <combo_box.item name="Indecency__Broadly_offensive_content_or_conduct" label="Onfatsoenlijkheid &gt; Globaal beledigende inhoud of gedrag"/>
+ <combo_box.item name="Indecency__Inappropriate_avatar_name" label="Onfatsoenlijkheid &gt; Ongepaste avatar naam"/>
+ <combo_box.item name="Indecency__Mature_content_in_PG_region" label="Onfatsoenlijkheid &gt; Ongepaste inhoud of gedrag in een PG regio"/>
+ <combo_box.item name="Indecency__Inappropriate_content_in_Mature_region" label="Onfatsoenlijkheid &gt; Ongepaste inhoud of gedrag in een Mature regio"/>
+ <combo_box.item name="Intellectual_property_infringement_Content_Removal" label="Inbreuk op intellectueel eigendom &gt; Verwijderen van inhoud"/>
+ <combo_box.item name="Intellectual_property_infringement_CopyBot_or_Permissions_Exploit" label="Inbreuk op intellectueel eigendom &gt; CopyBot of misbruik van permissies"/>
+ <combo_box.item name="Intolerance" label="Intolerantie"/>
+ <combo_box.item name="Land__Abuse_of_sandbox_resources" label="Land &gt; Misbruik van zandbakmiddelen"/>
+ <combo_box.item name="Land__Encroachment__Objects_textures" label="Land &gt; Indringing &gt; Objecten/texturen"/>
+ <combo_box.item name="Land__Encroachment__Particles" label="Land &gt; Indringing &gt; Particles"/>
+ <combo_box.item name="Land__Encroachment__Trees_plants" label="Land &gt; Indringing &gt; Bomen/planten"/>
+ <combo_box.item name="Wagering_gambling" label="Weddenschappen/gokken"/>
+ <combo_box.item name="Other" label="Anders"/>
</combo_box>
<text name="abuser_name_title">
Misbruikernaam:
@@ -169,7 +91,9 @@
Details:
</text>
<text name="bug_aviso">
- Wees alstublieft zo specifiek mogelijk m.b.t. datum, locatie, aard van het misbruik, relevante chat/IM tekst, en selecteer het object indien mogelijk.
+ Wees alstublieft zo specifiek mogelijk m.b.t. datum, locatie,
+aard van het misbruik, relevante chat/IM tekst, en selecteer
+het object indien mogelijk.
</text>
<text name="incomplete_title">
Let op: onvolledige rapporten zullen niet worden onderzocht.
diff --git a/indra/newview/skins/default/xui/nl/floater_script_debug.xml b/indra/newview/skins/default/xui/nl/floater_script_debug.xml
index 306ad5d1a3..15e57f30d6 100644
--- a/indra/newview/skins/default/xui/nl/floater_script_debug.xml
+++ b/indra/newview/skins/default/xui/nl/floater_script_debug.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<multi_floater name="script debug floater" title="Script waarschuwing/fout">
<tab_container name="Preview Tabs">
- <floater label="Script" name="all_scripts" title="[Alle scripts]"/>
+ <floater label="Script" name="all_scripts" title="[ALL SCRIPTS]"/>
</tab_container>
</multi_floater>
diff --git a/indra/newview/skins/default/xui/nl/floater_script_queue.xml b/indra/newview/skins/default/xui/nl/floater_script_queue.xml
index 38c227e53c..f79ad8faf3 100644
--- a/indra/newview/skins/default/xui/nl/floater_script_queue.xml
+++ b/indra/newview/skins/default/xui/nl/floater_script_queue.xml
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="queue" title="Voortgang opnieuw instellen">
+<floater name="queue" title="VOORTGANG OPNIEUW INSTELLEN">
<button label="Sluiten" label_selected="Sluiten" name="close"/>
</floater>
diff --git a/indra/newview/skins/default/xui/nl/floater_select_key.xml b/indra/newview/skins/default/xui/nl/floater_select_key.xml
index da97c03a6c..c8daa10ab6 100644
--- a/indra/newview/skins/default/xui/nl/floater_select_key.xml
+++ b/indra/newview/skins/default/xui/nl/floater_select_key.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="modal container" title="">
<button label="Annuleren" label_selected="Annuleren" name="Cancel"/>
- <text name="Save item as:">
- Druk een toets om te selecteren
+ <text name="Save item as:" left="12" width="220">
+ Druk op een toets om die te selecteren
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/nl/floater_sell_land.xml b/indra/newview/skins/default/xui/nl/floater_sell_land.xml
index 0208886813..468a383cfc 100644
--- a/indra/newview/skins/default/xui/nl/floater_sell_land.xml
+++ b/indra/newview/skins/default/xui/nl/floater_sell_land.xml
@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="sell land" title="Verkoop land">
+<floater name="sell land" title="VERKOOP LAND">
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
<text name="info_parcel_label">
Perceel:
</text>
@@ -36,15 +38,9 @@ verkopen:
Kies of u aan iedereen wil verkopen of een specifieke koper.
</text>
<combo_box name="sell_to">
- <combo_item name="--selectone--">
- -- selecteer een --
- </combo_item>
- <combo_item name="Anyone">
- Iedereen
- </combo_item>
- <combo_item name="Specificuser:">
- Specifieke gebruiker:
- </combo_item>
+ <combo_box.item name="--selectone--" label="selecteer een --"/>
+ <combo_box.item name="Anyone" label="Iedereen"/>
+ <combo_box.item name="Specificuser:" label="Specifieke gebruiker:"/>
</combo_box>
<button label="Selecteren..." name="sell_to_select_agent"/>
<text name="sell_objects_label">
@@ -55,12 +51,8 @@ verkopen:
zullen van eigenaar veranderen.
</text>
<radio_group name="sell_objects" bottom_delta="-58">
- <radio_item name="no">
- Nee, behoud het eigendom van objecten
- </radio_item>
- <radio_item name="yes">
- Ja, verkoop objecten met het land
- </radio_item>
+ <radio_item name="no" label="Nee, behoud het eigendom van objecten" />
+ <radio_item name="yes" label="Ja, verkoop objecten met het land" />
</radio_group>
<button label="Toon objecten" name="show_objects"/>
<text name="nag_message_label">
@@ -68,4 +60,6 @@ zullen van eigenaar veranderen.
</text>
<button label="Zet het land te koop" name="sell_btn"/>
<button label="Annuleren" name="cancel_btn"/>
+ </panel>
+ </scroll_container>
</floater>
diff --git a/indra/newview/skins/default/xui/nl/floater_snapshot.xml b/indra/newview/skins/default/xui/nl/floater_snapshot.xml
index 44447dd153..251f3690da 100644
--- a/indra/newview/skins/default/xui/nl/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/nl/floater_snapshot.xml
@@ -1,18 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Snapshot" title="Fotovoorbeeld">
+<floater name="Snapshot" title="FOTOVOORBEELD">
<text name="type_label">
Fotobestemming
</text>
<radio_group label="Fototype" name="snapshot_type_radio">
- <radio_item name="postcard">
- Verzend via e-mail
- </radio_item>
- <radio_item name="texture">
- Opslaan in uw inventaris (L$[AMOUNT])
- </radio_item>
- <radio_item name="local">
- Opslaan op uw harde schijf
- </radio_item>
+ <radio_item name="postcard" label="Verzend via e-mail" />
+ <radio_item name="texture" label="Opslaan in uw inventaris (L$[AMOUNT])" />
+ <radio_item name="local" label="Opslaan op uw harde schijf" />
</radio_group>
<text name="file_size_label">
Bestandsgrootte: [SIZE] KB
@@ -21,12 +15,8 @@
<button label="Verzenden" name="send_btn"/>
<button label="Opslaan (L$[AMOUNT])" name="upload_btn"/>
<flyout_button label="Opslaan" name="save_btn" tool_tip="Afbeelding in een bestand opslaan">
- <flyout_button_item name="save_item">
- Opslaan
- </flyout_button_item>
- <flyout_button_item name="saveas_item">
- Opslaan als...
- </flyout_button_item>
+ <flyout_button_item name="save_item" label="Opslaan"/>
+ <flyout_button_item name="saveas_item" label="Opslaan als..."/>
</flyout_button>
<button label="Annuleren" name="discard_btn"/>
<button label="Meer &gt;&gt;" name="more_btn" tool_tip="Geavanceerde opties"/>
@@ -38,98 +28,50 @@
Formaat
</text>
<combo_box label="Resolutie" name="postcard_size_combo">
- <combo_item name="CurrentWindow">
- Huidig venster
- </combo_item>
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
- <combo_item name="Custom">
- Aangepast
- </combo_item>
+ <combo_box.item name="CurrentWindow" label="Huidig venster"/>
+ <combo_box.item name="640x480" label="640x480"/>
+ <combo_box.item name="800x600" label="800x600"/>
+ <combo_box.item name="1024x768" label="1024x768"/>
+ <combo_box.item name="Custom" label="Aangepast"/>
</combo_box>
<combo_box label="Resolutie" name="texture_size_combo">
- <combo_item name="CurrentWindow">
- Huidig venster
- </combo_item>
- <combo_item name="Small(128x128)">
- Klein (128x128)
- </combo_item>
- <combo_item name="Medium(256x256)">
- Middel (256x256)
- </combo_item>
- <combo_item name="Large(512x512)">
- Groot (512x512)
- </combo_item>
- <combo_item name="Custom">
- Aangepast
- </combo_item>
+ <combo_box.item name="CurrentWindow" label="Huidig venster"/>
+ <combo_box.item name="Small(128x128)" label="Klein (128x128)"/>
+ <combo_box.item name="Medium(256x256)" label="Middel (256x256)"/>
+ <combo_box.item name="Large(512x512)" label="Groot (512x512)"/>
+ <combo_box.item name="Custom" label="Aangepast"/>
</combo_box>
<combo_box label="Resolutie" name="local_size_combo">
- <combo_item name="CurrentWindow">
- Huidig venster
- </combo_item>
- <combo_item name="320x240">
- 320x240
- </combo_item>
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
- <combo_item name="1280x1024">
- 1280x1024
- </combo_item>
- <combo_item name="1600x1200">
- 1600x1200
- </combo_item>
- <combo_item name="Custom">
- Aangepast
- </combo_item>
+ <combo_box.item name="CurrentWindow" label="Huidig venster"/>
+ <combo_box.item name="320x240" label="320x240"/>
+ <combo_box.item name="640x480" label="640x480"/>
+ <combo_box.item name="800x600" label="800x600"/>
+ <combo_box.item name="1024x768" label="1024x768"/>
+ <combo_box.item name="1280x1024" label="1280x1024"/>
+ <combo_box.item name="1600x1200" label="1600x1200"/>
+ <combo_box.item name="Custom" label="Aangepast"/>
</combo_box>
<combo_box label="Formaat" name="local_format_combo">
- <combo_item name="PNG">
- PNG
- </combo_item>
- <combo_item name="JPEG">
- JPEG
- </combo_item>
- <combo_item name="BMP">
- BMP
- </combo_item>
+ <combo_box.item name="PNG" label="PNG"/>
+ <combo_box.item name="JPEG" label="JPEG"/>
+ <combo_box.item name="BMP" label="BMP"/>
</combo_box>
- <spinner label="Breedte" name="snapshot_width"/>
- <spinner label="Hoogte" name="snapshot_height"/>
+ <spinner label="Breedte" name="snapshot_width" label_width="48" width="100"/>
+ <spinner label="Hoogte" name="snapshot_height" label_width="41" width="95" left="114"/>
<check_box label="Beperk verhoudingen" name="keep_aspect_check"/>
<slider label="Afbeeldingkwaliteit" name="image_quality_slider"/>
- <text name="layer_type_label">
+ <text name="layer_type_label" width="100">
Vastleggen:
</text>
- <combo_box label="Afbeeldingslagen" name="layer_types">
- <combo_item name="Colors">
- Kleuren
- </combo_item>
- <combo_item name="Depth">
- Diepte
- </combo_item>
- <combo_item name="ObjectMattes">
- Object matheid
- </combo_item>
+ <combo_box label="Afbeeldingslagen" name="layer_types" width="130" left="76">
+ <combo_box.item name="Colors" label="Kleuren"/>
+ <combo_box.item name="Depth" label="Diepte"/>
+ <combo_box.item name="ObjectMattes" label="Object matheid"/>
</combo_box>
<check_box label="Toon interface in foto" name="ui_check"/>
<check_box label="Toon HUD objecten in foto" name="hud_check"/>
<check_box label="Open houden na opslaan" name="keep_open_check"/>
- <check_box label="Frame bevriezen (volledig scherm voorbeeld)" name="freeze_frame_check"/>
+ <check_box label="Frame bevriezen" name="freeze_frame_check"/>
<check_box label="Automatisch verversen" name="auto_snapshot_check"/>
<string name="unknown">
onbekend
diff --git a/indra/newview/skins/default/xui/nl/floater_statistics.xml b/indra/newview/skins/default/xui/nl/floater_statistics.xml
index b899c32a56..7684a73663 100644
--- a/indra/newview/skins/default/xui/nl/floater_statistics.xml
+++ b/indra/newview/skins/default/xui/nl/floater_statistics.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="stats floater" title="Statistieken"/>
+<floater name="stats floater" title="STATISTIEKEN"/>
diff --git a/indra/newview/skins/default/xui/nl/floater_telehub.xml b/indra/newview/skins/default/xui/nl/floater_telehub.xml
index b1fc80cf3c..7b745d967c 100644
--- a/indra/newview/skins/default/xui/nl/floater_telehub.xml
+++ b/indra/newview/skins/default/xui/nl/floater_telehub.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="telehub" title="Telehub">
+<floater name="telehub" title="TELEHUB" width="292">
<text name="status_text_connected">
Telehub verbonden met object [OBJECT]
</text>
@@ -13,13 +13,21 @@
Selecteer objecten klik Verbind telehub
</text>
<button label="Verbind telehub" name="connect_btn"/>
- <button label="Verbinding verbreken" name="disconnect_btn"/>
+ <button label="Verbinding verbreken" name="disconnect_btn" width="128"/>
<text name="spawn_points_text">
Spawnpunten (posities, niet objecten):
</text>
+ <scroll_list bottom_delta="-44" draw_border="true" follows="left|top"
+ height="40" left="10" multi_select="false" name="spawn_points_list"
+ width="230" />
+
<button label="Spawn toevoegen" name="add_spawn_point_btn"/>
<button label="Verwijder Spawn" name="remove_spawn_point_btn"/>
- <text name="spawn_point_help">
- Selecteer object en klik Toevoegen om positie te specificeren. U kunt het object daarna verplaatsen of verwijderen. Posities zijn relatief ten opzichte van het middelpunt van de telehub. Selecteer een item in de lijst om de positie in de wereld te tonen.
+ <text name="spawn_point_help" width="290">
+ Selecteer object en klik Toevoegen om positie
+te specificeren. U kunt het object daarna verplaatsen
+of verwijderen. Posities zijn relatief ten opzichte
+van het middelpunt van de telehub. Selecteer een
+item in de lijst om de positie in de wereld te tonen.
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/nl/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/nl/floater_texture_ctrl.xml
index 440a31097d..c8caa8caf4 100644
--- a/indra/newview/skins/default/xui/nl/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/nl/floater_texture_ctrl.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="texture picker" title="Kies: Textuur">
+<floater name="texture picker" title="KIES: TEXTUUR">
<string name="choose_picture">
Klik om een afbeelding te kiezen
</string>
@@ -9,12 +9,12 @@
<text name="unknown">
Afmetingen: [DIMENSIONS]
</text>
- <button label="Standaard" label_selected="Standaard" name="Default"/>
- <button label="Geen" label_selected="Geen" name="None"/>
+ <button label="Standaard" label_selected="Standaard" name="Default" width="70"/>
+ <button label="Geen" label_selected="Geen" name="None" left="80"/>
<button label="Blanco" label_selected="Blanco" name="Blank"/>
<check_box label="Toon mappen" name="show_folders_check"/>
<search_editor label="Type hier om te zoeken" name="inventory search editor"/>
- <check_box label="Meteen toepassen" name="apply_immediate_check"/>
+ <check_box label="Direct toepassen" name="apply_immediate_check"/>
<button label="Annuleren" label_selected="Annuleren" name="Cancel"/>
<button label="Selecteren" label_selected="Selecteren" name="Select"/>
<string name="pick title">
diff --git a/indra/newview/skins/default/xui/nl/floater_tools.xml b/indra/newview/skins/default/xui/nl/floater_tools.xml
index c7f99195dd..f79d3dbd6b 100644
--- a/indra/newview/skins/default/xui/nl/floater_tools.xml
+++ b/indra/newview/skins/default/xui/nl/floater_tools.xml
@@ -1,47 +1,50 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="toolbox floater" title="">
+<floater name="toolbox floater" title="" short_title="BOUWEN" width="288">
<button label="" label_selected="" name="button focus" tool_tip="Focus"/>
<button label="" label_selected="" name="button move" tool_tip="Verplaats"/>
<button label="" label_selected="" name="button edit" tool_tip="Bewerk"/>
<button label="" label_selected="" name="button create" tool_tip="Maak"/>
<button label="" label_selected="" name="button land" tool_tip="Land"/>
- <check_box label="Zoom" name="radio zoom"/>
- <check_box label="Draaien (Ctrl)" name="radio orbit"/>
- <check_box label="Verplaatsen (Ctrl-Shift)" name="radio pan"/>
- <check_box label="Verplaatsen" name="radio move"/>
- <check_box label="Optillen (Ctrl)" name="radio lift"/>
- <check_box label="Draaien (Ctrl-Shift)" name="radio spin"/>
- <check_box label="Positie" name="radio position"/>
- <check_box label="Draaien (Ctrl)" name="radio rotate"/>
- <check_box label="Uitrekken (Ctrl-Shift)" name="radio stretch"/>
- <check_box label="Selecteer textuur" name="radio select face"/>
+ <radio_group name="focus_radio_group">
+ <radio_item label="Zoom" name="radio zoom"/>
+ <radio_item label="Roteren (Ctrl)" name="radio orbit"/>
+ <radio_item label="Verplaatsen (Ctrl-Shift)" name="radio pan"/>
+ </radio_group>
+ <radio_group name="move_radio_group">
+ <radio_item label="Verplaatsen" name="radio move"/>
+ <radio_item label="Optillen (Ctrl)" name="radio lift"/>
+ <radio_item label="Roteren (Ctrl-Shift)" name="radio spin"/>
+ </radio_group>
+ <radio_group name="edit_radio_group">
+ <radio_item label="Positie" name="radio position"/>
+ <radio_item label="Roteren (Ctrl)" name="radio rotate"/>
+ <radio_item label="Uitrekken (Ctrl-Shift)" name="radio stretch"/>
+ <radio_item label="Selecteer textuur" name="radio select face"/>
+ </radio_group>
<check_box label="Bewerk gekoppelde onderdelen" name="checkbox edit linked parts"/>
<text name="text ruler mode">
Liniaal:
</text>
- <combo_box name="combobox grid mode">
- <combo_item name="World">
- Wereld
- </combo_item>
- <combo_item name="Local">
- Lokaal
- </combo_item>
- <combo_item name="Reference">
- Referentie
- </combo_item>
+ <combo_box name="combobox grid mode" width="78" left_delta="38">
+ <combo_box.item name="World" label="Wereld"
+ />
+ <combo_box.item name="Local" label="Lokaal"
+ />
+ <combo_box.item name="Reference" label="Referentie"
+ />
</combo_box>
- <check_box label="Beide zijden uitrekken" name="checkbox uniform"/>
- <check_box label="Texturen uitrekken" name="checkbox stretch textures"/>
- <check_box label="Gebruik grid" name="checkbox snap to grid"/>
- <button label="Opties..." label_selected="Opties..." name="Options..."/>
- <text name="text status">
+ <check_box left="136" label="Beide zijden uitrekken" name="checkbox uniform"/>
+ <check_box left="136" label="Texturen uitrekken" name="checkbox stretch textures"/>
+ <check_box left="136" label="Gebruik grid" name="checkbox snap to grid"/>
+ <button label="Opties..." label_selected="Opties..." name="Options..." height="18" bottom_delta="-15"/>
+ <text name="text status" width="280">
Sleep om te verplaatsen, Shift-slepen om te kopiëren
</text>
<button label="" label_selected="" name="ToolCube" tool_tip="Kubus"/>
<button label="" label_selected="" name="ToolPrism" tool_tip="Prisma"/>
<button label="" label_selected="" name="ToolPyramid" tool_tip="Piramide"/>
<button label="" label_selected="" name="ToolTetrahedron" tool_tip="Tetrahedron"/>
- <button label="" label_selected="" name="ToolCylinder" tool_tip="Cylinder"/>
+ <button label="" label_selected="" name="ToolCylinder" tool_tip="Cilinder"/>
<button label="" label_selected="" name="ToolHemiCylinder" tool_tip="Halve cilinder"/>
<button label="" label_selected="" name="ToolCone" tool_tip="Kegel"/>
<button label="" label_selected="" name="ToolHemiCone" tool_tip="Halve kegel"/>
@@ -56,13 +59,15 @@
<check_box label="Kopiëer Selectie" name="checkbox copy selection"/>
<check_box label="Middelpunt" name="checkbox copy centers"/>
<check_box label="Roteer" name="checkbox copy rotates"/>
- <check_box label="Selecteer land" name="radio select land"/>
- <check_box label="Vlak maken" name="radio flatten"/>
- <check_box label="Verhogen" name="radio raise"/>
- <check_box label="Verlagen" name="radio lower"/>
- <check_box label="Egaliseren" name="radio smooth"/>
- <check_box label="Opruwen" name="radio noise"/>
- <check_box label="Herstellen" name="radio revert"/>
+ <radio_group name="land_radio_group">
+ <radio_item label="Selecteer land" name="radio select land"/>
+ <radio_item label="Vlak maken" name="radio flatten"/>
+ <radio_item label="Verhogen" name="radio raise"/>
+ <radio_item label="Verlagen" name="radio lower"/>
+ <radio_item label="Egaliseren" name="radio smooth"/>
+ <radio_item label="Opruwen" name="radio noise"/>
+ <radio_item label="Herstellen" name="radio revert"/>
+ </radio_group>
<button label="Toepassen" label_selected="Toepassen" name="button apply to selection" tool_tip="Wijzig geselecteerd land"/>
<text name="Bulldozer:">
Bulldozer:
@@ -73,13 +78,13 @@
<text name="Strength:">
Sterkte
</text>
- <text name="obj_count">
+ <text name="obj_count" left="134">
Geselecteerde objecten: [COUNT]
</text>
- <text name="prim_count">
+ <text name="prim_count" left="134">
primitieven: [COUNT]
</text>
- <tab_container name="Object Info Tabs">
+ <tab_container name="Object Info Tabs" tab_max_width="62" tab_min_width="30" width="288">
<panel label="Algemeen" name="General">
<text name="Name:">
Naam:
@@ -95,7 +100,7 @@
</text>
<button label="Profiel..." label_selected="Profiel..." name="button creator profile"/>
<text name="Owner:">
- Eigenaar
+ Eigenaar:
</text>
<text name="Owner Name">
Thrax Linden
@@ -111,9 +116,7 @@
<text name="Permissions:">
Permissies:
</text>
- <text name="perm_modify">
- U kunt dit object wijzigen
- </text>
+
<check_box label="Deel met groep" name="checkbox share with group" tool_tip="Alle leden van de ingestelde groep toestaan om te delen en uw permissies voor dit object te gebruiken. U moet &apos;Overdragen&apos; om rolbeperkingen in te schakelen."/>
<string name="text deed continued">
Overdragen...
@@ -129,49 +132,35 @@
<text name="Cost">
Prijs: L$
</text>
- <radio_group name="sale type">
- <radio_item name="Original">
- Origineel
- </radio_item>
- <radio_item name="Copy">
- Kopie
- </radio_item>
- <radio_item name="Contents">
- Inhoud
- </radio_item>
- </radio_group>
- <text name="Next owner can:">
- Volgende eigenaar kan:
- </text>
- <check_box label="Wijzigen" name="checkbox next owner can modify"/>
- <check_box label="Kopiëren" name="checkbox next owner can copy"/>
- <check_box label="Verkopen/weggeven" name="checkbox next owner can transfer"/>
+ <combo_box name="sale type">
+ <combo_box.item label="Kopie" name="Copy"/>
+ <combo_box.item label="Inhoud" name="Contents"/>
+ <combo_box.item label="Origineel" name="Original"/>
+ </combo_box>
+
<text name="label click action">
Wanneer links-geklikt:
</text>
- <combo_box name="clickaction">
- <combo_item name="Touch/grab(default)">
- Aanraken/pakken (standaard)
- </combo_item>
- <combo_item name="Sitonobject">
- Zit op object
- </combo_item>
- <combo_item name="Buyobject">
- Koop object
- </combo_item>
- <combo_item name="Payobject">
- Betaal object
- </combo_item>
- <combo_item name="Open">
- Open
- </combo_item>
- <combo_item name="Play">
- Perceelmedia afspelen
- </combo_item>
- <combo_item name="Opemmedia">
- Perceelmedia openen
- </combo_item>
+ <combo_box name="clickaction" width="178">
+ <combo_box.item name="Touch/grab(default)" label="Aanraken/pakken (standaard)"
+ />
+ <combo_box.item name="Sitonobject" label="Zit op object"
+ />
+ <combo_box.item name="Buyobject" label="Koop object"
+ />
+ <combo_box.item name="Payobject" label="Betaal object"
+ />
+ <combo_box.item name="Open" label="Open"
+ />
+ <combo_box.item name="Play" label="Perceelmedia afspelen"
+ />
+ <combo_box.item name="Opemmedia" label="Perceelmedia openen"
+ />
</combo_box>
+ <panel name="perms_build">
+ <text name="perm_modify">
+ U kunt dit object wijzigen
+ </text>
<text name="B:">
B:
</text>
@@ -190,6 +179,13 @@
<text name="F:">
F:
</text>
+ <text name="Next owner can:">
+ Volgende eigenaar kan:
+ </text>
+ <check_box label="Wijzigen" name="checkbox next owner can modify"/>
+ <check_box label="Kopiëren" name="checkbox next owner can copy" left_delta="80"/>
+ <check_box name="checkbox next owner can transfer" left_delta="67"/>
+ </panel>
<string name="text modify info 1">
U kunt dit object wijzigen
</string>
@@ -206,13 +202,13 @@
U moet het hele object selecteren om permissies in te stellen
</string>
<string name="Cost Default">
- Prijs: L$
+ Prijs: L$
</string>
<string name="Cost Total">
- Totale Prijs: L$
+ Totale Prijs: L$
</string>
<string name="Cost Per Unit">
- Prijs per: L$
+ Prijs per: L$
</string>
<string name="Cost Mixed">
Gemengde prijs
@@ -254,56 +250,41 @@
Materiaal
</text>
<combo_box name="material">
- <combo_item name="Stone">
- Steen
- </combo_item>
- <combo_item name="Metal">
- Metaal
- </combo_item>
- <combo_item name="Glass">
- Glas
- </combo_item>
- <combo_item name="Wood">
- Hout
- </combo_item>
- <combo_item name="Flesh">
- Vlees
- </combo_item>
- <combo_item name="Plastic">
- Plastic
- </combo_item>
- <combo_item name="Rubber">
- Rubber
- </combo_item>
+ <combo_box.item name="Stone" label="Steen"
+ />
+ <combo_box.item name="Metal" label="Metaal"
+ />
+ <combo_box.item name="Glass" label="Glas"
+ />
+ <combo_box.item name="Wood" label="Hout"
+ />
+ <combo_box.item name="Flesh" label="Vlees"
+ />
+ <combo_box.item name="Plastic" label="Plastic"
+ />
+ <combo_box.item name="Rubber" label="Rubber"
+ />
</combo_box>
<text name="label basetype">
Bouwbloktype
</text>
<combo_box name="comboBaseType">
- <combo_item name="Box">
- Kubus
- </combo_item>
- <combo_item name="Cylinder">
- Cilinder
- </combo_item>
- <combo_item name="Prism">
- Prisma
- </combo_item>
- <combo_item name="Sphere">
- Bol
- </combo_item>
- <combo_item name="Torus">
- Torus
- </combo_item>
- <combo_item name="Tube">
- Buis
- </combo_item>
- <combo_item name="Ring">
- Ring
- </combo_item>
- <combo_item name="Sculpted">
- Sculpted
- </combo_item>
+ <combo_box.item name="Box" label="Kubus"
+ />
+ <combo_box.item name="Cylinder" label="Cilinder"
+ />
+ <combo_box.item name="Prism" label="Prisma"
+ />
+ <combo_box.item name="Sphere" label="Bol"
+ />
+ <combo_box.item name="Torus" label="Torus"
+ />
+ <combo_box.item name="Tube" label="Buis"
+ />
+ <combo_box.item name="Ring" label="Ring"
+ />
+ <combo_box.item name="Sculpted" label="Sculpted"
+ />
</combo_box>
<text name="text cut">
Uitsnede begin en einde
@@ -320,18 +301,14 @@
Holtevorm
</text>
<combo_box name="hole">
- <combo_item name="Default">
- Standaard
- </combo_item>
- <combo_item name="Circle">
- Cirkel
- </combo_item>
- <combo_item name="Square">
- Vierkant
- </combo_item>
- <combo_item name="Triangle">
- Driehoek
- </combo_item>
+ <combo_box.item name="Default" label="Standaard"
+ />
+ <combo_box.item name="Circle" label="Cirkel"
+ />
+ <combo_box.item name="Square" label="Vierkant"
+ />
+ <combo_box.item name="Triangle" label="Driehoek"
+ />
</combo_box>
<text name="text twist">
Verdraai begin en einde
@@ -358,7 +335,7 @@
Deuk begin en einde
</text>
<text name="advanced_slice">
- Uitsnede Begin en Einde
+ Uitsnede begin en einde
</text>
<spinner label="B" name="Path Limit Begin"/>
<spinner label="E" name="Path Limit End"/>
@@ -370,7 +347,7 @@
<text name="text radius delta">
Straal
</text>
- <text name="text revolutions">
+ <text name="text revolutions" width="84">
Omwentelingen
</text>
<texture_picker label="Sculpt textuur" name="sculpt texture control" tool_tip="Klik om een afbeelding te kiezen"/>
@@ -380,21 +357,16 @@
Hechtingstype
</text>
<combo_box name="sculpt type control">
- <combo_item name="None">
- (none)
- </combo_item>
- <combo_item name="Sphere">
- Bol
- </combo_item>
- <combo_item name="Torus">
- Torus
- </combo_item>
- <combo_item name="Plane">
- Vlak
- </combo_item>
- <combo_item name="Cylinder">
- Cilinder
- </combo_item>
+ <combo_box.item name="None" label="(geen)"
+ />
+ <combo_box.item name="Sphere" label="Bol"
+ />
+ <combo_box.item name="Torus" label="Torus"
+ />
+ <combo_box.item name="Plane" label="Vlak"
+ />
+ <combo_box.item name="Cylinder" label="Cilinder"
+ />
</combo_box>
</panel>
<panel label="Kenmerken" name="Features">
@@ -405,14 +377,14 @@
Bewerk objectkenmerken:
</text>
<check_box label="Flexibiliteit" name="Flexible1D Checkbox Ctrl" tool_tip="Staat toe dat objecten kunnen buigen om de Z-as. (alleen aan de client kant)"/>
- <spinner label="Zachtheid" name="FlexNumSections"/>
- <spinner label="Zwaartekracht" name="FlexGravity"/>
- <spinner label="Slepen" name="FlexFriction"/>
- <spinner label="Wind" name="FlexWind"/>
- <spinner label="Spanning" name="FlexTension"/>
- <spinner label="Kracht X" name="FlexForceX"/>
- <spinner label="Kracht Y" name="FlexForceY"/>
- <spinner label="Kracht Z" name="FlexForceZ"/>
+ <spinner label="Zachtheid" name="FlexNumSections" width="143" label_width="80"/>
+ <spinner label="Zwaartekracht" name="FlexGravity" width="143" label_width="80"/>
+ <spinner label="Slepen" name="FlexFriction" width="143" label_width="80"/>
+ <spinner label="Wind" name="FlexWind" width="143" label_width="80"/>
+ <spinner label="Spanning" name="FlexTension" width="143" label_width="80"/>
+ <spinner label="Kracht X" name="FlexForceX" width="143" label_width="80"/>
+ <spinner label="Kracht Y" name="FlexForceY" width="143" label_width="80"/>
+ <spinner label="Kracht Z" name="FlexForceZ" width="143" label_width="80"/>
<check_box label="Licht" name="Light Checkbox Ctrl" tool_tip="Zorgt dat het object licht uitstraalt"/>
<text name="label color">
Kleur
@@ -425,99 +397,75 @@
<panel label="Textuur" name="Texture">
<texture_picker label="Textuur" name="texture control" tool_tip="Klik om een afbeelding te kiezen"/>
<color_swatch label="Kleur" name="colorswatch" tool_tip="Klik om kleurkiezer to openen"/>
- <text name="color trans">
+ <text name="color trans" width="100">
Transparantie %
</text>
<text name="glow label">
Gloed
</text>
- <check_box label="Volledige helderheid" name="checkbox fullbright"/>
+ <check_box label="Volledige &#10;helderheid" name="checkbox fullbright" bottom_delta="-21"/>
<text name="tex gen">
Mapping
</text>
<combo_box name="combobox texgen">
- <combo_item name="Default">
- Standaard
- </combo_item>
- <combo_item name="Planar">
- Vlak
- </combo_item>
+ <combo_box.item name="Default" label="Standaard"
+ />
+ <combo_box.item name="Planar" label="Vlak"
+ />
</combo_box>
<text name="label shininess">
Glans
</text>
<combo_box name="combobox shininess">
- <combo_item name="None">
- Geen
- </combo_item>
- <combo_item name="Low">
- Laag
- </combo_item>
- <combo_item name="Medium">
- Middel
- </combo_item>
- <combo_item name="High">
- Hoog
- </combo_item>
+ <combo_box.item name="None" label="Geen"
+ />
+ <combo_box.item name="Low" label="Laag"
+ />
+ <combo_box.item name="Medium" label="Middel"
+ />
+ <combo_box.item name="High" label="Hoog"
+ />
</combo_box>
<text name="label bumpiness">
Bumpiness
</text>
<combo_box name="combobox bumpiness">
- <combo_item name="None">
- Geen
- </combo_item>
- <combo_item name="Brightness">
- Helderheid
- </combo_item>
- <combo_item name="Darkness">
- Donkerheid
- </combo_item>
- <combo_item name="woodgrain">
- Houtnerf
- </combo_item>
- <combo_item name="bark">
- Schors
- </combo_item>
- <combo_item name="bricks">
- Stenen
- </combo_item>
- <combo_item name="checker">
- Dambord
- </combo_item>
- <combo_item name="concrete">
- Beton
- </combo_item>
- <combo_item name="crustytile">
- gebarsten tegels
- </combo_item>
- <combo_item name="cutstone">
- natuursteen
- </combo_item>
- <combo_item name="discs">
- schijven
- </combo_item>
- <combo_item name="gravel">
- grind
- </combo_item>
- <combo_item name="petridish">
- petrischaal
- </combo_item>
- <combo_item name="siding">
- wandpaneel
- </combo_item>
- <combo_item name="stonetile">
- plavuizen
- </combo_item>
- <combo_item name="stucco">
- stucwerk
- </combo_item>
- <combo_item name="suction">
- zuignappen
- </combo_item>
- <combo_item name="weave">
- weven
- </combo_item>
+ <combo_box.item name="None" label="Geen"
+ />
+ <combo_box.item name="Brightness" label="Helderheid"
+ />
+ <combo_box.item name="Darkness" label="Donkerheid"
+ />
+ <combo_box.item name="woodgrain" label="Houtnerf"
+ />
+ <combo_box.item name="bark" label="Schors"
+ />
+ <combo_box.item name="bricks" label="Stenen"
+ />
+ <combo_box.item name="checker" label="Dambord"
+ />
+ <combo_box.item name="concrete" label="Beton"
+ />
+ <combo_box.item name="crustytile" label="gebarsten tegels"
+ />
+ <combo_box.item name="cutstone" label="natuursteen"
+ />
+ <combo_box.item name="discs" label="schijven"
+ />
+ <combo_box.item name="gravel" label="grind"
+ />
+ <combo_box.item name="petridish" label="petrischaal"
+ />
+ <combo_box.item name="siding" label="wandpaneel"
+ />
+ <combo_box.item name="stonetile" label="plavuizen"
+ />
+ <combo_box.item name="stucco" label="stucwerk"
+ />
+ <combo_box.item name="suction" label="zuignappen"
+ />
+ <combo_box.item name="weave" label="weven"
+ />
</combo_box>
<text name="tex scale">
Herhalingen per zijde
@@ -536,7 +484,7 @@
Herhalingen per zijde
</string>
<text name="rpt">
- Herhalingen per meter
+ Herhalingen per m
</text>
<button label="Toepassen" label_selected="Toepassen" name="button apply"/>
<text name="tex offset">
@@ -545,13 +493,15 @@
<spinner label="Horizontaal (U)" name="TexOffsetU"/>
<spinner label="Verticaal (V)" name="TexOffsetV"/>
<text name="textbox autofix">
- Mediatextuur uitlijnen (moet eerst laden)
+ Mediatextuur uitlijnen
+(moet eerst laden)
</text>
- <button label="Uitlijnen" label_selected="Uitlijnen" name="button align"/>
+ <button label="Uitlijnen" label_selected="Uitlijnen" name="button align" left="155" />
</panel>
<panel label="Inhoud" name="Contents">
- <button label="Nieuw script" label_selected="Nieuw script..." name="button new script"/>
- <button label="Permissies..." name="button permissions"/>
+ <button label="Nieuw script" label_selected="Nieuw script" name="button new script"/>
+ <button label="Permissies" name="button permissions"/>
+ <panel name="ContentsInventory" width="272" />
</panel>
</tab_container>
<panel name="land info panel">
@@ -559,62 +509,62 @@
Perceel Informatie
</text>
<text name="label_area_price">
- Prijs: L$[PRICE] voor [AREA] m2.
+ Prijs: L$[PRICE] voor [AREA] m².
</text>
<text name="label_area">
- Gebied: [AREA] m2.
+ Gebied: [AREA] m².
</text>
<button label="Over land..." label_selected="Over land..." name="button about land"/>
- <check_box label="Toon Eigenaren" name="checkbox show owners" tool_tip="Kleur percelen op basis van hun eigendom"/>
- <button label="?" label_selected="?" name="button show owners help"/>
+ <check_box label="Toon Eigenaren" name="checkbox show owners" tool_tip="Kleur percelen op basis van hun eigendom: &#10;&#10;Groen = Uw land &#10;Aqua = Land van uw groep &#10;Rood = Eigendom van anderen &#10;Geel = Te koop &#10;Paars = Ter veiling &#10;Grijs = Openbaar"/>
+ <button label="?" label_selected="?" name="button show owners help" left_delta="105"/>
<text name="label_parcel_modify">
Wijzig Perceel
</text>
- <button label="Opdelen..." label_selected="Opdelen..." name="button subdivide land"/>
- <button label="Samenvoegen..." label_selected="Samenvoegen..." name="button join land"/>
+ <button label="Opdelen" label_selected="Opdelen" name="button subdivide land"/>
+ <button label="Samenvoegen" label_selected="Samenvoegen" name="button join land"/>
<text name="label_parcel_trans">
Landtransacties
</text>
- <button label="Koop land..." label_selected="Koop land..." name="button buy land"/>
- <button label="Land Afstaan..." label_selected="Land Afstaan..." name="button abandon land"/>
+ <button label="Koop land" label_selected="Koop land" name="button buy land"/>
+ <button label="Land Afstaan" label_selected="Land Afstaan" name="button abandon land"/>
</panel>
- <string name="status_rotate">
+ <floater.string name="status_rotate">
Sleep de gekleurde banden om het object te roteren
- </string>
- <string name="status_scale">
+ </floater.string>
+ <floater.string name="status_scale">
Klik en sleep om de geselecteerde zijde uit te rekken.
- </string>
- <string name="status_move">
+ </floater.string>
+ <floater.string name="status_move">
Sleep om te verplaatsen, Shift-slepen om te kopiëren
- </string>
- <string name="status_modifyland">
+ </floater.string>
+ <floater.string name="status_modifyland">
Klik en houd vast om land te wijzigen
- </string>
- <string name="status_camera">
+ </floater.string>
+ <floater.string name="status_camera">
Klik en sleep om beeld te wijzigen
- </string>
- <string name="status_grab">
+ </floater.string>
+ <floater.string name="status_grab">
Sleep om te verplaatsen, Ctrl om op te tillen, Ctrl-Shift om te roteren.
- </string>
- <string name="status_place">
+ </floater.string>
+ <floater.string name="status_place">
Klik in-wereld om te bouwen
- </string>
- <string name="status_selectland">
+ </floater.string>
+ <floater.string name="status_selectland">
Klik en sleep om land te selecteren
- </string>
- <string name="grid_screen_text">
+ </floater.string>
+ <floater.string name="grid_screen_text">
Scherm
- </string>
- <string name="grid_local_text">
+ </floater.string>
+ <floater.string name="grid_local_text">
Lokaal
- </string>
- <string name="grid_world_text">
+ </floater.string>
+ <floater.string name="grid_world_text">
Wereld
- </string>
- <string name="grid_reference_text">
+ </floater.string>
+ <floater.string name="grid_reference_text">
Referentie
- </string>
- <string name="grid_attachment_text">
+ </floater.string>
+ <floater.string name="grid_attachment_text">
Bevestiging
- </string>
+ </floater.string>
</floater>
diff --git a/indra/newview/skins/default/xui/nl/floater_top_objects.xml b/indra/newview/skins/default/xui/nl/floater_top_objects.xml
index e79ee4ea56..2bbb701df8 100644
--- a/indra/newview/skins/default/xui/nl/floater_top_objects.xml
+++ b/indra/newview/skins/default/xui/nl/floater_top_objects.xml
@@ -1,32 +1,32 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="top_objects" title="laden…">
+<floater name="top_objects" title="LADEN…">
<text name="title_text">
Laden…
</text>
<scroll_list name="objects_list">
- <column label="Score" name="score"/>
- <column label="Naam" name="name"/>
- <column label="Eigenaar" name="owner"/>
- <column label="Locatie" name="location"/>
- <column label="Tijd" name="time"/>
- <column label="Mono tijd" name="mono_time"/>
+ <column label="Score" name="score" width="84"/>
+ <column label="Naam" name="name" width="84"/>
+ <column label="Eigenaar" name="owner" width="84"/>
+ <column label="Locatie" name="location" width="84"/>
+ <column label="Tijd" name="time" width="84"/>
+ <column label="Mono tijd" name="mono_time" width="84"/>
</scroll_list>
- <text name="id_text">
+ <text name="id_text" left="2">
Object ID:
</text>
<button label="Toon baken" name="show_beacon_btn"/>
- <text name="obj_name_text">
+ <text name="obj_name_text" left="2">
Object naam:
</text>
<button label="Filter" name="filter_object_btn"/>
- <text name="owner_name_text">
+ <text name="owner_name_text" left="2">
Eigenaar naam:
</text>
<button label="Filter" name="filter_owner_btn"/>
- <button label="Geselecteerde retourneren" name="return_selected_btn"/>
- <button label="Alles retourneren" name="return_all_btn"/>
- <button label="Geselecteerde uitschakelen" name="disable_selected_btn"/>
- <button label="Alles uitschakelen" name="disable_all_btn"/>
+ <button label="Geselecteerde retourneren" name="return_selected_btn" width="170"/>
+ <button label="Alles retourneren" name="return_all_btn" left="190"/>
+ <button label="Geselecteerde uitschakelen" name="disable_selected_btn" width="170"/>
+ <button label="Alles uitschakelen" name="disable_all_btn" left="190"/>
<button label="Verversen" name="refresh_btn"/>
<string name="top_scripts_title">
Top scripts
diff --git a/indra/newview/skins/default/xui/nl/floater_tos.xml b/indra/newview/skins/default/xui/nl/floater_tos.xml
index b9a162be4a..d71412664c 100644
--- a/indra/newview/skins/default/xui/nl/floater_tos.xml
+++ b/indra/newview/skins/default/xui/nl/floater_tos.xml
@@ -4,7 +4,8 @@
<button label="Annuleren" label_selected="Annuleren" name="Cancel"/>
<check_box label="Ik ga akkoord met de voorwaarden van service" name="agree_chk"/>
<text name="tos_heading">
- Leest u alstublieft de volgende voorwaarden van service door. Om door te gaan met inloggen in Second Life dient u de overeenkomst te accepteren.
+ Leest u alstublieft de volgende voorwaarden van service door. Om door te gaan met inloggen in
+[SECOND_LIFE] dient u de overeenkomst te accepteren.
</text>
<text_editor name="tos_text">
TOS_TEXT
diff --git a/indra/newview/skins/default/xui/nl/floater_url_entry.xml b/indra/newview/skins/default/xui/nl/floater_url_entry.xml
index 23ea21bcc5..6926f09390 100644
--- a/indra/newview/skins/default/xui/nl/floater_url_entry.xml
+++ b/indra/newview/skins/default/xui/nl/floater_url_entry.xml
@@ -4,8 +4,8 @@
Media URL:
</text>
<button label="OK" name="ok_btn"/>
- <button label="Annuleren" name="cancel_btn"/>
- <button label="Leegmaken" name="clear_btn"/>
+ <button label="Annuleren" name="cancel_btn" width="80"/>
+ <button label="Leegmaken" name="clear_btn" width="80"/>
<text name="loading_label">
Laden…
</text>
diff --git a/indra/newview/skins/default/xui/nl/floater_water.xml b/indra/newview/skins/default/xui/nl/floater_water.xml
index 38ec15d1a0..1fb1ca241b 100644
--- a/indra/newview/skins/default/xui/nl/floater_water.xml
+++ b/indra/newview/skins/default/xui/nl/floater_water.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Water Floater" title="Geavanceerde water editor">
+<floater name="Water Floater" title="GEAVANCEERDE WATER EDITOR">
+ <combo_box bottom="-50" height="18" left_delta="116" name="WaterPresetsCombo" width="150" />
<text name="KeyFramePresetsText">
Watervoorinstellingen
</text>
- <button label="Nieuw" label_selected="Nieuw" name="WaterNewPreset"/>
+ <button label="Nieuw" label_selected="Nieuw" name="WaterNewPreset" left_delta="190"/>
<button label="Opslaan" label_selected="Opslaan" name="WaterSavePreset"/>
- <button label="Verwijderen" label_selected="Verwijderen" name="WaterDeletePreset"/>
+ <button label="Verwijderen" label_selected="Verwijderen" name="WaterDeletePreset" width="80"/>
<tab_container name="Water Tabs">
<panel label="Instellingen" name="Settings">
<text name="BHText">
diff --git a/indra/newview/skins/default/xui/nl/floater_world_map.xml b/indra/newview/skins/default/xui/nl/floater_world_map.xml
index a13eba4dc7..bc14f92126 100644
--- a/indra/newview/skins/default/xui/nl/floater_world_map.xml
+++ b/indra/newview/skins/default/xui/nl/floater_world_map.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="worldmap" title="Wereldkaart">
+<floater name="worldmap" title="WERELDKAART">
<tab_container name="maptab">
<panel label="Objecten" name="objects_mapview"/>
<panel label="Terrein" name="terrain_mapview"/>
@@ -29,14 +29,10 @@
<check_box label="Mature" name="event_mature_chk"/>
<check_box label="Adult" name="event_adult_chk"/>
<combo_box label="Online vrienden" name="friend combo" tool_tip="Vriend die op kaart getoond wordt">
- <combo_item name="none_selected">
- Online vrienden
- </combo_item>
+ <combo_box.item name="item1" label="Online vrienden"/>
</combo_box>
<combo_box label="Landmarkeringen" name="landmark combo" tool_tip="Landmarkering die op kaart getoond wordt">
- <combo_item name="none_selected">
- Landmarkeringen
- </combo_item>
+ <combo_box.item name="item1" label="Landmarkeringen"/>
</combo_box>
<line_editor label="Zoek op regionaam" name="location" tool_tip="Type de naam van een regio"/>
<button label="Zoeken" name="DoSearch" tool_tip="Zoek naar regio"/>
@@ -53,6 +49,6 @@
<button label="Toon bestemming" label_selected="Toon bestemming" name="Show Destination" tool_tip="Centreer kaart op geselecteerde locatie"/>
<button label="Verwijder" label_selected="Verwijder" name="Clear" tool_tip="Stop volgen"/>
<button label="Toon mijn locatie" label_selected="Toon mijn locatie" name="Show My Location" tool_tip="Centreer kaart op de locatie van uw avatar"/>
- <button label="Kopieer SLURL naar klembord" name="copy_slurl" tool_tip="Kopieert huidige locatie als SLURL, zodat deze op het web gebruikt kan worden."/>
+ <button label="Kopieer SLurl naar klembord" name="copy_slurl" tool_tip="Kopieert huidige locatie als SLurl, zodat deze op het web gebruikt kan worden."/>
<slider label="Zoom" name="zoom slider"/>
</floater>
diff --git a/indra/newview/skins/default/xui/nl/language_settings.xml b/indra/newview/skins/default/xui/nl/language_settings.xml
new file mode 100644
index 0000000000..71418d446a
--- /dev/null
+++ b/indra/newview/skins/default/xui/nl/language_settings.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- This file contains strings that used to be hardcoded in the source.-->
+<strings>
+
+ <!-- Locale Information -->
+ <string name="MicrosoftLocale">english</string>
+ <string name="DarwinLocale">C</string>
+ <string name="LinuxLocale">C</string>
+
+ <!--
+ datetimeToCodes["wkday"] = "%a"; // Thu
+ datetimeToCodes["weekday"] = "%A"; // Thursday
+ datetimeToCodes["year4"] = "%Y"; // 2009
+ datetimeToCodes["year"] = "%Y"; // 2009
+ datetimeToCodes["year2"] = "%y"; // 09
+ datetimeToCodes["mth"] = "%b"; // Aug
+ datetimeToCodes["month"] = "%B"; // August
+ datetimeToCodes["mthnum"] = "%m"; // 08
+ datetimeToCodes["day"] = "%d"; // 31
+ datetimeToCodes["hour24"] = "%H"; // 14
+ datetimeToCodes["hour"] = "%H"; // 14
+ datetimeToCodes["hour12"] = "%I"; // 02
+ datetimeToCodes["min"] = "%M"; // 59
+ datetimeToCodes["ampm"] = "%p"; // AM
+ datetimeToCodes["second"] = "%S"; // 59
+ datetimeToCodes["timezone"] = "%Z"; // PST
+ -->
+
+ <string name="TimeHour">hour,datetime,slt</string>
+ <string name="TimeMin">min,datetime,slt</string>
+ <string name="TimeYear">year,datetime,slt</string>
+ <string name="TimeDay">day,datetime,slt</string>
+ <string name="TimeMonth">mthnum,datetime,slt</string>
+ <string name="TimeWeek">wkday,datetime,slt</string>
+ <string name="TimeAMPM">ampm,datetime,slt</string>
+ <string name="TimeHour12">hour12,datetime,slt</string>
+
+ <string name="LTimeMthNum">mthnum,datetime,local</string>
+ <string name="LTimeWeek">wkday,datetime,local</string>
+ <string name="LTimeMonth">mth,datetime,local</string>
+ <string name="LTimeDay">day,datetime,local</string>
+ <string name="LTimeSec">second,datetime,local</string>
+ <string name="LTimeHour">hour,datetime,local</string>
+ <string name="LTimeMin">min,datetime,local</string>
+ <string name="LTimeYear">year,datetime,local</string>
+
+ <string name="UTCTimeWeek">weekday,datetime,utc</string>
+ <string name="UTCTimeDay">day,datetime,utc</string>
+ <string name="UTCTimeMth">mth,datetime,utc</string>
+ <string name="UTCTimeYr">year,datetime,utc</string>
+ <string name="UTCTimeHr">hour,datetime,utc</string>
+ <string name="UTCTimeMin">min,datetime,utc</string>
+ <string name="UTCTimeSec">second,datetime,utc</string>
+ <string name="UTCTimeTimezone">timezone,datetime,utc</string>
+</strings>
diff --git a/indra/newview/skins/default/xui/nl/menu_inventory.xml b/indra/newview/skins/default/xui/nl/menu_inventory.xml
index f406bcf6bc..6a514422b9 100644
--- a/indra/newview/skins/default/xui/nl/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/nl/menu_inventory.xml
@@ -12,7 +12,7 @@
<menu_item_call label="Nieuw script" name="New Script"/>
<menu_item_call label="Nieuwe notitie" name="New Note"/>
<menu_item_call label="Nieuw gebaar" name="New Gesture"/>
- <menu name="New Clothes">
+ <menu name="New Clothes" label="Nieuwe Kleding">
<menu_item_call label="Nieuw shirt" name="New Shirt"/>
<menu_item_call label="Nieuwe broek" name="New Pants"/>
<menu_item_call label="Nieuwe schoenen" name="New Shoes"/>
@@ -23,7 +23,7 @@
<menu_item_call label="Nieuw onderhemd" name="New Undershirt"/>
<menu_item_call label="Nieuwe onderbroek" name="New Underpants"/>
</menu>
- <menu name="New Body Parts">
+ <menu name="New Body Parts" label="Nieuwe Lichaamsdelen">
<menu_item_call label="Nieuwe postuur" name="New Shape"/>
<menu_item_call label="Nieuwe huid" name="New Skin"/>
<menu_item_call label="Nieuw haar" name="New Hair"/>
diff --git a/indra/newview/skins/default/xui/nl/menu_login.xml b/indra/newview/skins/default/xui/nl/menu_login.xml
index 188418e34c..987b82b128 100644
--- a/indra/newview/skins/default/xui/nl/menu_login.xml
+++ b/indra/newview/skins/default/xui/nl/menu_login.xml
@@ -7,7 +7,7 @@
<menu_item_call label="Voorkeuren..." name="Preferences..."/>
</menu>
<menu label="Help" name="Help">
- <menu_item_call label="Second Life Help" name="Second Life Help"/>
- <menu_item_call label="Over Second Life..." name="About Second Life..."/>
+ <menu_item_call label="[SECOND_LIFE] Help" name="Second Life Help"/>
+ <menu_item_call label="Over [APP_NAME]..." name="About Second Life..."/>
</menu>
</menu_bar>
diff --git a/indra/newview/skins/default/xui/nl/menu_viewer.xml b/indra/newview/skins/default/xui/nl/menu_viewer.xml
index 0827858d68..6d5c833610 100644
--- a/indra/newview/skins/default/xui/nl/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/nl/menu_viewer.xml
@@ -165,7 +165,9 @@
<menu_item_separator label="-----------" name="separator4"/>
<menu_item_call label="Focus op selectie" name="Focus on Selection"/>
<menu_item_call label="Zoom naar selectie" name="Zoom to Selection"/>
- <menu_item_call label="Koop object" name="Menu Object Take"/>
+ <menu_item_call label="Koop object" name="Menu Object Take">
+ <on_enable userdata="Koop,Neem" name="EnableBuyOrTake"/>
+ </menu_item_call>
<menu_item_call label="Neem kopie" name="Take Copy"/>
<menu_item_call label="Object terug opslaan in objectinhoud" name="Save Object Back to Object Contents"/>
<menu_item_separator label="-----------" name="separator6"/>
@@ -179,7 +181,7 @@
<menu_item_call label="Scripts in selectie instellen op niet uitvoeren" name="Set Scripts to Not Running in Selection"/>
</menu>
<menu label="Help" name="Help">
- <menu_item_call label="Second Life Help" name="Second Life Help"/>
+ <menu_item_call label="[SECOND_LIFE] Help" name="Second Life Help"/>
<menu_item_call label="Handleiding" name="Tutorial"/>
<menu_item_separator label="-----------" name="separator"/>
<menu_item_call label="Officiële Linden blog..." name="Official Linden Blog..."/>
@@ -200,6 +202,6 @@
<menu_item_separator label="-----------" name="separator9"/>
<menu_item_call label="Rapporteer bug..." name="Report Bug..."/>
</menu>
- <menu_item_call label="Over Second Life..." name="About Second Life..."/>
+ <menu_item_call label="Over [APP_NAME]..." name="About Second Life..."/>
</menu>
</menu_bar>
diff --git a/indra/newview/skins/default/xui/nl/notifications.xml b/indra/newview/skins/default/xui/nl/notifications.xml
index c64c2cd021..a282c267a1 100644
--- a/indra/newview/skins/default/xui/nl/notifications.xml
+++ b/indra/newview/skins/default/xui/nl/notifications.xml
@@ -6,6 +6,9 @@
<global name="alwayschoose">
Kies altijd deze optie
</global>
+ <global name="implicitclosebutton">
+ Sluiten
+ </global>
<template name="okbutton">
<form>
<button
@@ -71,7 +74,7 @@
</form>
</template>
<notification functor="GenericAcknowledge" label="Onbekende waarschuwingsboodschap" name="MissingAlert">
- Uw versie van Second Life weet niet hoe het de waarschuwingsboodschap die zojuist ontvangen is moet weergeven.
+ Uw versie van [APP_NAME] weet niet hoe het de waarschuwingsboodschap die zojuist ontvangen is moet weergeven.
Foutdetails: De waarschuwing genaamd &apos;[_NAME]&apos; is niet gevonden in notifications.xml.
<usetemplate name="okbutton" yestext="OK"/>
@@ -94,7 +97,7 @@ Foutdetails: De waarschuwing genaamd &apos;[_NAME]&apos; is niet gevonden in not
<usetemplate name="okcancelbuttons" notext="Annuleren" yestext="Ja"/>
</notification>
<notification name="BadInstallation">
- Er is een fout opgetreden tijdens het bijwerken van Second Life. Download alstublieft de meest recente versie van secondlife.com
+ Er is een fout opgetreden tijdens het bijwerken van [APP_NAME]. Download alstublieft de meest recente versie van secondlife.com
<usetemplate
name="okbutton"
yestext="OK"/>
@@ -232,7 +235,7 @@ Het aan vinken van deze optie zal:
<notification name="ClickPartnerHelpAvatar">
U kunt een andere Inwoner ten huwelijk vragen of een bestaand partner schap verbreken via de [SECOND_LIFE] website.
-Naar de Second Life website gaan voor meer informatie over partner schap?
+Naar de [SECOND_LIFE] website gaan voor meer informatie over partner schap?
<usetemplate name="okcancelbuttons" notext="Annuleren" yestext="Ga naar Pagina"/>
</notification>
<notification name="ClickUploadHelpPermissions">
@@ -245,7 +248,7 @@ Naar de Second Life website gaan voor meer informatie over partner schap?
* Klik op Laden &gt; &apos;Thuis pagina URL&apos; om terug te keren naar het web profiel van deze Inwoner indien U verder genavigeerd bent.
Indien u uw eigen profiel bekijkt, kunt U elke willekeurige URL opgeven als uw web profiel en op OK klikken om het in te stellen.
-Andere Inwoners kunnen de door U opgegeven URL bezoeken indien zijn uw profiel bekijken.
+Andere Inwoners kunnen de door U opgegeven URL bezoeken indien zij uw profiel bekijken.
</notification>
<notification name="JoinGroupCanAfford">
Deelname aan deze groep kost L$[COST].
@@ -272,7 +275,7 @@ Uw verkoopprijs is L$[SALE_PRICE] en zal geautoriseerd worden voor verkoop door
<usetemplate name="okcancelbuttons" notext="Annuleren" yestext="OK"/>
</notification>
<notification name="ConfirmLandSaleToAnyoneChange">
- ATTENTIE: Het aanklikken van &apos;verkoop aan iedereen&apos; zal uw land beschikbaar maken aan de gehele Second Life gemeenschap, zo ook diegenen niet in deze regio!
+ ATTENTIE: Het aanklikken van &apos;verkoop aan iedereen&apos; zal uw land beschikbaar maken aan de gehele [SECOND_LIFE] gemeenschap, zo ook diegenen niet in deze regio!
De geselecteerde [LAND_SIZE] m² land is te koop gezet.
Uw verkoopprijs is L$[SALE_PRICE] en zal geautoriseerd worden voor verkoop door [NAME].
@@ -377,6 +380,9 @@ De outfit folder bevat geen kleding, lichaamsdelen of externe bevestigingen.
U moet zowel de voornaam als de achternaam van uw avatar opgeven.
U heeft een account nodig om [SECOND_LIFE] binnen te gaan. Wilt u er nu een maken?
+ <url name="url">
+ https://join.secondlife.com/index.php?lang=nl-NL
+ </url>
<usetemplate name="okcancelbuttons" notext="Probeer het opnieuw" yestext="Maak een nieuw account"/>
</notification>
<notification name="AddClassified">
@@ -418,17 +424,17 @@ Betaalde advertentiekosten zullen niet worden terug gestort.
<usetemplate name="okcancelbuttons" notext="Annuleren" yestext="OK"/>
</notification>
<notification name="CacheWillClear">
- De Cache zal geleegd worden als u [SECOND_LIFE] opnieuw start.
+ De cache zal geleegd worden als u [APP_NAME] opnieuw start.
</notification>
<notification name="CacheWillBeMoved">
- De Cache zal verplaatst worden als u [SECOND_LIFE] opnieuw start.
+ De cache zal verplaatst worden als u [APP_NAME] opnieuw start.
Opmerking: Dit zal de Cache legen.
</notification>
<notification name="ChangeConnectionPort">
- Poort instelling zullen effect hebben nadat u [SECOND_LIFE] opnieuw start.
+ Poort instelling zullen effect hebben nadat u [APP_NAME] opnieuw start.
</notification>
<notification name="ChangeSkin">
- De nieuwe skin zal verschijnen nadat u [SECOND_LIFE] opnieuw start.
+ De nieuwe skin zal verschijnen nadat u [APP_NAME] opnieuw start.
</notification>
<notification name="GoToAuctionPage">
Ga naar de [SECOND_LIFE] web pagina om de veiling details te zien of een bod uit te brengen.
@@ -489,7 +495,7 @@ Het object kan buiten bereik of mogelijk verwijderd zijn.
Kan niet naar bestand [[FILE]] schrijven
</notification>
<notification name="UnsupportedHardware">
- Waarschuwing: Uw systeem voldoet niet aan de Second Life minimum systeem eisen. Indien u Second Life gebruikt, ervaart u mogelijk slechte prestaties. Helaas kunnen we geen technische ondersteuning geven voor niet ondersteunde configuraties.
+ Waarschuwing: Uw systeem voldoet niet aan de [APP_NAME] minimum systeem eisen. Indien u [APP_NAME] gebruikt, ervaart u mogelijk slechte prestaties. Helaas kunnen we geen technische ondersteuning geven voor niet ondersteunde configuraties.
MINSPECS
Wilt u [_URL] bezoeken voor meer informatie?
@@ -501,14 +507,14 @@ Wilt u [_URL] bezoeken voor meer informatie?
<notification name="UnknownGPU">
Uw systeem heeft een grafische kaart die bij ons nog niet bekend is op dit moment.
-Dit is vaak het geval met nieuwe hardware waarbij wij nog niet de kans gehad hebben om het te testen. Second Life zal mogelijk naar behoren functioneren, doch het kan zijn dat u uw grafische instellingen naar geschiktere waarden zult moeten instellen.
+Dit is vaak het geval met nieuwe hardware waarbij wij nog niet de kans gehad hebben om het te testen. [APP_NAME] zal mogelijk naar behoren functioneren, doch het kan zijn dat u uw grafische instellingen naar geschiktere waarden zult moeten instellen.
(Bewerken menu &gt; Voorkeuren &gt; Grafisch).
<form name="form">
<ignore name="ignore" text="Indien een onbekende grafische kaart gedetecteerd"/>
</form>
</notification>
<notification name="DisplaySettingsNoShaders">
- [SECOND_LIFE] is gestopt bij het initialiseren van de grafische stuurprogramma&apos;s.
+ [APP_NAME] is gestopt bij het initialiseren van de grafische stuurprogramma&apos;s.
Grafische kwaliteit zal op zijn laagst worden ingesteld om veel voorkomende fouten met stuurprogramma&apos;s te vermijden.
Dit zal sommige grafische opties uitschakelen.
Wij adviseren u de stuurprogramma&apos;s van uw grafische kaart bij te werken.
@@ -573,7 +579,7 @@ Verplaats alstublieft alle objecten die u wilt verwerven naar dezelfde regio.
<notification name="PromptGoToCurrencyPage">
[EXTRA]
-Naar [URL] gaan voor informatie over de aankoop valuta?
+Naar [_URL] gaan voor informatie over de aankoop L$?
<usetemplate name="okcancelbuttons" notext="Annuleren" yestext="OK"/>
</notification>
<notification name="UnableToLinkObjects">
@@ -789,7 +795,7 @@ Geen perceel geselecteerd.
Kan de regio niet vinden waar dit land zich bevind.
</notification>
<notification name="CannotCloseFloaterBuyLand">
- U kunt het Koop Land venster niet sluiten totdat Second Life de prijs van de transactie geschat heeft.
+ U kunt het Koop Land venster niet sluiten totdat [APP_NAME] de prijs van de transactie geschat heeft.
</notification>
<notification name="CannotDeedLandNothingSelected">
Kan land niet toekennen:
@@ -802,7 +808,6 @@ Geen groep geselecteerd.
<notification name="CannotDeedLandNoRegion">
Kan land niet toekennen:
Kan de regio niet vinden waar dit land zich bevind.
-Gebruik alstublieft Gereedschappen -&gt; Report Bug om het te rapporteren.
</notification>
<notification name="CannotDeedLandMultipleSelected">
Kan land niet toekennen:
@@ -849,8 +854,6 @@ Percelen in uw eigendom verschijnen in groen.
<notification name="CannotReleaseLandRegionNotFound">
Kan land niet afstaan:
Kan de regio niet vinden waar dit land zich bevind.
-
-Gebruik alstublieft Gereedschappen &gt; Report Bug om het te rapporteren.
</notification>
<notification name="CannotReleaseLandNoTransfer">
Kan land niet afstaan:
@@ -889,14 +892,10 @@ Land opdelen?
<notification name="CannotDivideLandNoRegion">
Kan het land niet opdelen:
Kan de regio niet vinden waar dit land zich bevind.
-
-Gebruik alstublieft Gereedschappen &gt; Report Bug om het te rapporteren.
</notification>
<notification name="CannotJoinLandNoRegion">
Kan land niet verbinden:
Kan de regio niet vinden waar dit land zich bevind.
-
-Gebruik alstublieft Gereedschappen &gt; Report Bug om het te rapporteren.
</notification>
<notification name="CannotJoinLandNothingSelected">
Kan land niet verbinden:
@@ -956,13 +955,11 @@ Grijs = Openbaar
Kon [NAME] niet opslaan in centrale (asset) opslag.
Meestal is dit een tijdelijk probleem.
Wijzig en sla het draagbaar item over een paar minuten opnieuw op.
-
-Indien dit probleem aanhoudt, klik dan alstublieft op &apos;Gereedschap &gt; Rapporteer Bug&apos; in het menu en voeg informatie toe over uw netwerk instellingen.
</notification>
<notification name="YouHaveBeenLoggedOut">
U bent uitgelogd uit [SECOND_LIFE]:
[MESSAGE]
-U kunt uw bestaande IM en chat bekijken door te klikken op &apos;Toon IM &amp; Chat&apos;. Anders, klik op Afsluiten om [SECOND_LIFE] direct te verlaten.
+U kunt uw bestaande IM en chat bekijken door te klikken op &apos;Toon IM &amp; Chat&apos;. Anders, klik op Afsluiten om [APP_NAME] direct te verlaten.
<usetemplate name="okcancelbuttons" notext="Afsluiten" yestext="Toon IM &amp; Chat"/>
</notification>
<notification name="OnlyOfficerCanBuyLand">
@@ -980,7 +977,7 @@ Vriendschap aanbieden aan [NAME]?
Vriendschap aanbieden aan [NAME]?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Wilt U mijn vriend zijn?
</input>
<button name="Offer" text="OK"/>
@@ -1134,14 +1131,14 @@ U kunt [SECOND_LIFE] normaal gebruiken en anderen zullen u correct zien.
</form>
</notification>
<notification name="FirstRun">
- [SECOND_LIFE] installatie compleet.
+ [APP_NAME] installatie compleet.
Als dit de eerste keer is dat u [SECOND_LIFE] gebruikt, zult u een account aan moeten maken voordat u in kan loggen.
-Terugkeren naar www.secondlife.com om een nieuw account aan te maken?
+Terugkeren naar [https://join.secondlife.com/index.php?lang=nl-NL secondlife.com] om een nieuw account aan te maken?
<usetemplate name="okcancelbuttons" notext="Doorgaan" yestext="Nieuw Account..."/>
</notification>
<notification name="LoginPacketNeverReceived">
- Wij hebben problemen verbinding te maken. Er zou een probleem kunnen zijn met uw internet verbinding of met de Second Life servers.
+ Wij hebben problemen verbinding te maken. Er zou een probleem kunnen zijn met uw internet verbinding of met de [SECOND_LIFE] servers.
U kunt uw internet verbinding controleren en het over een paar minuten opnieuw proberen, op Help klikken om verbinding te maken met onze support website, of klik op Teleporteren om een poging te doen naar uw thuis locatie te teleporteren.
<form name="form">
@@ -1245,33 +1242,33 @@ Zet het object alstublieft te koop en probeer het opnieuw.
[DOWNLOAD_PATH].
</notification>
<notification name="DownloadWindowsMandatory">
- Een nieuwe versie van [SECOND_LIFE] is beschikbaar.
+ Een nieuwe versie van [APP_NAME] is beschikbaar.
[MESSAGE]
-U moet deze update downloaden om [SECOND_LIFE] te kunnen gebruiken.
+U moet deze update downloaden om [APP_NAME] te kunnen gebruiken.
<usetemplate name="okcancelbuttons" notext="Afsluiten" yestext="Download"/>
</notification>
<notification name="DownloadWindows">
- Een bijgewerkte versie van [SECOND_LIFE] is beschikbaar.
+ Een bijgewerkte versie van [APP_NAME] is beschikbaar.
[MESSAGE]
Deze update is niet vereist, maar wij raden aan dat u het installeert om de prestaties en stabiliteit te verbeteren.
<usetemplate name="okcancelbuttons" notext="Doorgaan" yestext="Download"/>
</notification>
<notification name="DownloadWindowsReleaseForDownload">
- Een bijgewerkte versie van [SECOND_LIFE] is beschikbaar.
+ Een bijgewerkte versie van [APP_NAME] is beschikbaar.
[MESSAGE]
Deze update is niet vereist, maar wij raden aan dat u het installeert om de prestaties en stabiliteit te verbeteren.
<usetemplate name="okcancelbuttons" notext="Doorgaan" yestext="Download"/>
</notification>
<notification name="DownloadMacMandatory">
- Een nieuwe versie van [SECOND_LIFE] is beschikbaar.
+ Een nieuwe versie van [APP_NAME] is beschikbaar.
[MESSAGE]
-U moet deze update downloaden om [SECOND_LIFE] te kunnen gebruiken.
+U moet deze update downloaden om [APP_NAME] te kunnen gebruiken.
Downloaden naar uw Applicatie Data map?
<usetemplate name="okcancelbuttons" notext="Afsluiten" yestext="Download"/>
</notification>
<notification name="DownloadMac">
- Een bijgewerkte versie van [SECOND_LIFE] is beschikbaar.
+ Een bijgewerkte versie van [APP_NAME] is beschikbaar.
[MESSAGE]
Deze update is niet vereist, maar wij raden aan dat u het installeert om de prestaties en stabiliteit te verbeteren.
@@ -1279,7 +1276,7 @@ Downloaden naar uw Applicatie Data map?
<usetemplate name="okcancelbuttons" notext="Doorgaan" yestext="Download"/>
</notification>
<notification name="DownloadMacReleaseForDownload">
- Een bijgewerkte versie van [SECOND_LIFE] is beschikbaar.
+ Een bijgewerkte versie van [APP_NAME] is beschikbaar.
[MESSAGE]
Deze update is niet vereist, maar wij raden aan dat u het installeert om de prestaties en stabiliteit te verbeteren.
@@ -1299,10 +1296,6 @@ Downloaden naar uw Applicatie Data map?
Naar www.secondlife.com gaan om uw account te beheren?
<usetemplate ignoretext="Bij openen van webbrowser om uw account te beheren" name="okcancelignore" notext="Annuleren" yestext="OK"/>
</notification>
- <notification name="WebLaunchBugReport101">
- Bezoek de [SECOND_LIFE] Wiki en leer hoe Bugs correct gerapporteerd kunnen worden.
- <usetemplate ignoretext="Bij openen webbrowser om de Bug Reporting 101 Wiki te bekijken" name="okcancelignore" notext="Annuleren" yestext="OK"/>
- </notification>
<notification name="WebLaunchSecurityIssues">
Bezoek de [SECOND_LIFE] Wiki voor details over hoe een Veiligheids Probleem (Security Issue) te rapporteren.
<usetemplate ignoretext="Bij openen webbrowser om de Veiligheids Problemen Wiki (Security Issues Wiki) te bekijken" name="okcancelignore" notext="Annuleren" yestext="OK"/>
@@ -1388,7 +1381,7 @@ Om een groep te verlaten, selecteer de &apos;Groep..&apos; optie via het &apos;B
<notification name="KickUser">
Verwijder deze gebruiker met welk bericht?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Een administrator heeft u uitgelogd.
</input>
<button name="OK" text="OK"/>
@@ -1398,7 +1391,7 @@ Om een groep te verlaten, selecteer de &apos;Groep..&apos; optie via het &apos;B
<notification name="KickAllUsers">
Verwijder iedereen momenteel op het grid met welk bericht?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Een administrator heeft u uitgelogd.
</input>
<button name="OK" text="OK"/>
@@ -1408,7 +1401,7 @@ Om een groep te verlaten, selecteer de &apos;Groep..&apos; optie via het &apos;B
<notification name="FreezeUser">
Bevries deze gebruiker met welk bericht?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
U bent bevroren. U kunt zich niet verplaatsen of praten. Een administrator zal contact met u opnemen via instant message (IM).
</input>
<button name="OK" text="OK"/>
@@ -1418,7 +1411,7 @@ Om een groep te verlaten, selecteer de &apos;Groep..&apos; optie via het &apos;B
<notification name="UnFreezeUser">
Ontdooi deze gebruiker met welk bericht?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
U bent niet langer bevroren.
</input>
<button name="OK" text="OK"/>
@@ -1428,7 +1421,7 @@ Om een groep te verlaten, selecteer de &apos;Groep..&apos; optie via het &apos;B
<notification name="OfferTeleport">
Een Teleport aanbieden naar uw locatie met welk bericht?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Voeg u bij mij in [REGION]
</input>
<button name="OK" text="OK"/>
@@ -1438,7 +1431,7 @@ Om een groep te verlaten, selecteer de &apos;Groep..&apos; optie via het &apos;B
<notification name="OfferTeleportFromGod">
God beveel gebruiker naar uw locatie?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Voeg u bij mij in [REGION]
</input>
<button name="OK" text="OK"/>
@@ -1452,7 +1445,7 @@ Om een groep te verlaten, selecteer de &apos;Groep..&apos; optie via het &apos;B
<notification label="Bericht iedereen in uw Estate" name="MessageEstate">
Type een kort bericht om naar iedereen sturen die momenteel in uw Estate aanwezig is.
<form name="form">
- <input name="message" type="text"/>
+ <input name="message"/>
<button name="OK" text="OK"/>
<button name="Cancel" text="Annuleren"/>
</form>
@@ -1541,7 +1534,7 @@ Ga naar de kennisbank voor meer informatie over inhoudscategorieën?
U wordt niet in die regio toegelaten vanwege uw inhoudscategorie.
U kunt klikken op &apos;Wijzig voorkeur&apos; om uw inhoudscategorie voorkeur nu te verhogen en toegelaten te worden. U zult in staat zijn om [REGIONMATURITY] inhoud te zoeken en benaderen vanaf dit moment. Wanneer u later deze instelling wilt wijzigen, ga dan naar Bewerken &gt; Voorkeuren... &gt; Algemeen.
- <form>
+ <form name="form">
<button
name="OK"
text="Wijzig voorkeur"/>
@@ -1549,7 +1542,7 @@ U kunt klikken op &apos;Wijzig voorkeur&apos; om uw inhoudscategorie voorkeur nu
default="true"
name="Cancel"
text="Sluiten"/>
- <ignore text="Wanneer regiotoegang wordt geblokkeerd vanwege de inhoudscategorie voorkeur"/>
+ <ignore name="ignore" text="Wanneer regiotoegang wordt geblokkeerd vanwege de inhoudscategorie voorkeur"/>
</form>
</notification>
<notification name="LandClaimAccessBlocked">
@@ -1675,7 +1668,7 @@ Advertentie nu Publiceren voor L$[AMOUNT]?
<notification label="Bericht iedereen in deze regio" name="MessageRegion">
Type een kort bericht om naar iedereen sturen die momenteel in regio aanwezig is.
<form name="form">
- <input name="message" type="text"/>
+ <input name="message"/>
<button name="OK" text="OK"/>
<button name="Cancel" text="Annuleren"/>
</form>
@@ -1766,7 +1759,7 @@ Indien deze optie is aan gevinkt, kunnen kopers hun land in deze regio verkopen.
Standaard: Niet toestaan
</notification>
<notification label="Scripts Uitschakelen" name="HelpRegionDisableScripts">
- Indien de sim prestaties slecht zijn, kan een script de oorzaak zijn. Open de Statistieken balk (Ctrl-Shift-1). Kijk naar de Simulator Fysieke FPS. Indien het lager is dan 45, open dan het Tijd paneel onderaan de Statistieken balk. Indien de Script Tijd 25 ms of hoger is, klik dan op de Top Scripts knop. U krijgt dan een naam en lokatie van scripts die mogelijk de slechte prestaties veroorzaken.
+ Indien de sim prestaties slecht zijn, kan een script de oorzaak zijn. Open de Statistieken balk (Ctrl+Shift+1). Kijk naar de Simulator Fysieke FPS. Indien het lager is dan 45, open dan het Tijd paneel onderaan de Statistieken balk. Indien de Script Tijd 25 ms of hoger is, klik dan op de Top Scripts knop. U krijgt dan een naam en lokatie van scripts die mogelijk de slechte prestaties veroorzaken.
Het aan vinken van Scripts Uitschakelen en vervolgens op de Toepassen knop drukken, zal tijdelijk alle scripts in deze regio uitschakelen. U zult dit mogelijk moeten doen om naar de lokatie te gaan van het &apos;top script&apos;. Eenmaal aangekomen, onderzoek dan of het script het probleem veroorzaakt. U zult mogelijk de eigenaar willen contacteren of het object willen retourneren c.q. verwijderen.
Verwijder het vinkje van Scripts Uitschakelen en klik op Toepassen om scripts weer te reactiveren in de regio.
@@ -1774,7 +1767,7 @@ Verwijder het vinkje van Scripts Uitschakelen en klik op Toepassen om scripts we
Standaard: Uitgeschakeld
</notification>
<notification label="Botsingen Uitschakelen" name="HelpRegionDisableCollisions">
- Indien de sim prestaties slecht zijn, kunnen fysieke objecten de oorzaak zijn. Open de Statistieken balk (Ctrl-Shift-1). Kijk naar de Simulator Fysieke FPS. Indien het lager is dan 45, open dan het Tijd paneel onderaan de Statistieken balk. Indien de Sim Tijd (Fysiek) 20 ms of hoger is, klik dan op de Toon Top Botsingen knop. U krijgt dan een naam en lokatie van de fysieke objecten die mogelijk de slecht prestaties veroorzaken.
+ Indien de sim prestaties slecht zijn, kunnen fysieke objecten de oorzaak zijn. Open de Statistieken balk (Ctrl+Shift+1). Kijk naar de Simulator Fysieke FPS. Indien het lager is dan 45, open dan het Tijd paneel onderaan de Statistieken balk. Indien de Sim Tijd (Fysiek) 20 ms of hoger is, klik dan op de Toon Top Botsingen knop. U krijgt dan een naam en lokatie van de fysieke objecten die mogelijk de slecht prestaties veroorzaken.
Het aan vinken van de Botsingen Uitschakelen knop en vervolgens op de Toepassen knop drukken, zal tijdelijk object-object botsingen uitschakelen. U zult dit mogelijk moeten doen om naar de lokatie te gaan van de &apos;top botsingen&apos;. Eenmaal aangekomen, onderzoek dan het object. Botst het constant met andere objecten? U zult mogelijk de eigenaar willen contacteren of het object willen retourneren c.q. verwijderen.
Verwijder het vinkje van Botsingen Uitschakelen en klik op Toepassen om botsingen weer te reactiveren in de regio.
@@ -1890,7 +1883,7 @@ Indien u het leeg laat, zullen misbruik rapporten alleen verzonden worden naar L
Standaard: Uitgeschakeld
</notification>
<notification label="Voice Versie Ongelijkheid" name="VoiceVersionMismatch">
- Deze versie van Second Life is niet compatibel met de Voice spraak optie in deze regio. Om Voice Chat goed te laten functioneren, moet u Second Life bijwerken.
+ Deze versie van [APP_NAME] is niet compatibel met de Voice spraak optie in deze regio. Om Voice Chat goed te laten functioneren, moet u [APP_NAME] bijwerken.
</notification>
<notification label="Estate Convenant" name="HelpEstateCovenant">
Het instellen van een Estate Convenant maakt het u mogelijk om percelen in het Estate te verkopen. Indien de Convenant niet is ingesteld kunt u het niet verkopen. Een notitiekaart voor uw Convenant kan leeg zijn indien u geen regels wilt instellen, advies aan kopers wilt geven of iets anders in relatie tot het land wilt mededelen voor als men het koopt.
@@ -1968,14 +1961,14 @@ De inhoud zal naar uw inventaris gekopieerd worden.
Weet u zeker dat u verder wilt gaan met deze aankoop?
<usetemplate name="okcancelbuttons" notext="Annuleren" yestext="OK"/>
</notification>
- <notification name="ConfirmPurchasePassword" type="password">
+ <notification name="ConfirmPurchasePassword">
Deze transactie zal:
[ACTION]
Weet u zeker dat u verder wilt gaan met deze aankoop?
Voer alstublieft opnieuw uw wachtwoord in en klik op OK.
<form name="form">
- <input name="message" type="password"/>
+ <input name="message"/>
<button name="ConfirmPurchase" text="OK"/>
<button name="Cancel" text="Annuleren"/>
</form>
@@ -2001,7 +1994,7 @@ inventaris item(s) verplaatsen?
<usetemplate ignoretext="Indien verplaatsen &apos;niet kopieerbare&apos; inventaris van gescripte objecten" name="okcancelignore" notext="Annuleren" yestext="OK"/>
</notification>
<notification name="ClickActionNotPayable">
- Waarschuwing: Het Betaal Object aan klik actie is ingesteld, maar het zal alleen werken als er een script is toegevoegd met een money() event.
+ Waarschuwing: Het &apos;Betaal object&apos; aan klik actie is ingesteld, maar het zal alleen werken als er een script is toegevoegd met een money() event.
<form name="form">
<ignore name="ignore" text="Indien instellen &apos;Betaal&apos; op objecten zonder money() events"/>
</form>
@@ -2010,16 +2003,16 @@ inventaris item(s) verplaatsen?
Er zitten geen items in dit object die u kunt kopiëren.
</notification>
<notification name="WebLaunchAccountHistory">
- Naar de Second Life web site gaan om uw account geschiedenis te bekijken?
+ Naar de [SECOND_LIFE] web site gaan om uw account geschiedenis te bekijken?
<usetemplate ignoretext="Bij laden van de account geschiedenis webpagina" name="okcancelignore" notext="Annuleren" yestext="Ga naar pagina"/>
</notification>
<notification name="ClickOpenF1Help">
- De Second Life Support Web site bezoeken?
- <usetemplate ignoretext="Bij bezoeken van de Second Life Support Website." name="okcancelignore" notext="Annuleren" yestext="Ga"/>
+ De [SECOND_LIFE] Support Web site bezoeken?
+ <usetemplate ignoretext="Bij bezoeken van de [SECOND_LIFE] Support Website." name="okcancelignore" notext="Annuleren" yestext="Ga"/>
</notification>
<notification name="ConfirmQuit">
Weet u zeker dat u wilt afsluiten?
- <usetemplate ignoretext="Bij afsluiten Second Life." name="okcancelignore" notext="Doorgaan" yestext="Afsluiten"/>
+ <usetemplate ignoretext="Bij afsluiten [APP_NAME]." name="okcancelignore" notext="Doorgaan" yestext="Afsluiten"/>
</notification>
<notification name="HelpReportAbuseEmailLL">
Gebruik dit gereedschap om overtredingen van de Voorwaarden voor Service (Terms of Service) en Gemeenschaps Standaarden (Community Standards)te rapporteren. Zie:
@@ -2039,28 +2032,13 @@ Als een service aan Inwoners en bezoekers heeft de eigenaar van deze regio er vo
De regio eigenaar zal de rapporten afhandelen op basis van de regels geldend voor deze regio zoals weergegeven in het Estate Convenant (Bekijk Convenants door naar Wereld te gaan in het menu en te kiezen voor Over Land).
De afhandeling van dit rapport is alleen van toepassing op deze regio.
-Toegang van Inwoners tot andere gebieden van Second Life zullen niet beïnvloed worden door de uitkomst van dit rapport. Alleen Linden Lab kan de toegang tot geheel Second Life beperken.
- </notification>
- <notification name="HelpReportBug">
- Gebruik dit gereedschap *alleen* voor het rapporteren van technische opties die niet functioneren als verwacht. Geef alstublieft zoveel mogelijk technische details als mogelijk. U kunt de automatische-antwoord email gebruiken om op te reageren om aanvullende gegevens toe te voegen aan uw rapport.
-
-Alle bug rapporten worden onderzocht en ingeschat. Er zal geen antwoord per email worden verzonden.
-
-Als u technische problemen heeft, neem dan contact op met Support op:
-http://secondlife.com/community/support.php
-
-Opmerking: Onvolledige rapporten zullen niet worden onderzocht.
+Toegang van Inwoners tot andere gebieden van [SECOND_LIFE] zullen niet beïnvloed worden door de uitkomst van dit rapport. Alleen Linden Lab kan de toegang tot geheel [SECOND_LIFE] beperken.
</notification>
<notification name="HelpReportAbuseSelectCategory">
Selecteer alstublieft een categorie voor dit misbruik rapport.
Het selecteren van een categorie helpt ons met het archiveren en verwerken van misbruik rapporten.
</notification>
- <notification name="HelpReportBugSelectCategory">
- Selecteer alstublieft een categorie voor dit bug rapport.
-
-Het selecteren van een categorie helpt ons met het archiveren en verwerken van bug rapporten.
- </notification>
<notification name="HelpReportAbuseAbuserNameEmpty">
Geef alstublieft een naam op van de misbruiker.
@@ -2076,11 +2054,6 @@ Een accurate waarde opgeven helpt ons met het archiveren en verwerken van misbru
Een accurate waarde opgeven helpt ons met het archiveren en verwerken van misbruik rapporten.
</notification>
- <notification name="HelpReportBugSummaryEmpty">
- Geef alstublieft een korte samenvatting van de bug.
-
-Een accurate samenvatting opgeven helpt ons met het archiveren en verwerken van bug rapporten.
- </notification>
<notification name="HelpReportAbuseDetailsEmpty">
Geef alstublieft een gedetailleerde omschrijving van het misbruik dat plaats vond.
@@ -2088,21 +2061,14 @@ Wees zo specifiek als mogelijk, inclusief namen en details van het incident waar
Het opgeven van een accurate omschrijving helpt ons met het archiveren en verwerken van misbruik rapporten.
</notification>
- <notification name="HelpReportBugDetailsEmpty">
- Geef alstublieft een gedetailleerde omschrijving van de bug.
-
-Wees zo specifiek als mogelijk, inclusief stappen om de bug te reproduceren, indien mogelijk.
-
-Het opgeven van een accurate omschrijving helpt ons met het archiveren en verwerken van misbruik rapporten.
- </notification>
<notification name="HelpReportAbuseContainsCopyright">
Beste Inwoner,
Het lijkt er op dat u intellectueel eigendoms misbruik rapporteert. Wees er alstublieft van overtuigd dat u dit correct rapporteert:
-(1) Het Misbruik Proces. U kunt een misbruik rapport indienen als u er van overtuigd bent dat een Inwoner het Second Life permissie systeem uitbuit, bijvoorbeeld door gebruik van CopyBot of soortgelijke gereedschappen, daarmee de intellectuele eigendoms rechten overtredend. Het Abuse Team onderzoekt en zal passende maatregelen uitvaardigen tegen gedrag dat de Second Life Gemeenschaps Standaarden overtreedt. Echter, het Abuse Team zal geen actie ondernemen en niet reageren op verzoeken om inhoud te verwijderen uit de Second Life wereld.
+(1) Het Misbruik Proces. U kunt een misbruik rapport indienen als u er van overtuigd bent dat een Inwoner het [SECOND_LIFE] permissie systeem uitbuit, bijvoorbeeld door gebruik van CopyBot of soortgelijke gereedschappen, daarmee de intellectuele eigendoms rechten overtredend. Het Abuse Team onderzoekt en zal passende maatregelen uitvaardigen tegen gedrag dat de [SECOND_LIFE] Gemeenschaps Standaarden overtreedt. Echter, het Abuse Team zal geen actie ondernemen en niet reageren op verzoeken om inhoud te verwijderen uit de [SECOND_LIFE] wereld.
-(2) Het DMCA of Inhoud Verwijder Proces. Voor een verzoek tot verwijdering van inhoud in Second Life, MOET u een geldige berichtgeving van misbruik indienen zoals voorzien in onze DMCA beleid op http://secondlife.com/corporate/dmca.php.
+(2) Het DMCA of Inhoud Verwijder Proces. Voor een verzoek tot verwijdering van inhoud in [SECOND_LIFE], MOET u een geldige berichtgeving van misbruik indienen zoals voorzien in onze DMCA beleid op http://secondlife.com/corporate/dmca.php.
Indien u nog steeds door wilt gaan met het misbruik proces, sluit dan alstublieft dit venster en maak het indienen van uw rapport af. U zult mogelijk een specifieke catagorie moeten kiezen &apos;CopyBot of Permissie Uitbuiting&apos;.
@@ -2137,7 +2103,7 @@ Wilt u de Niet Storen Modus verlaten voordat u deze transactie completeert?
<usetemplate ignoretext="Bij verwijderen van de inhoud uit de inventaris vuilnisbak map" name="okcancelignore" notext="Annuleren" yestext="OK"/>
</notification>
<notification name="ConfirmClearBrowserCache">
- Weet u zeker dat u uw browser cache wilt legen?
+ Weet u zeker dat u uw browsercache wilt legen?
<usetemplate name="okcancelbuttons" notext="Annuleren" yestext="Ja"/>
</notification>
<notification name="ConfirmClearCookies">
@@ -2153,34 +2119,34 @@ Wilt u de Niet Storen Modus verlaten voordat u deze transactie completeert?
<usetemplate ignoretext="Bij legen van uw inventaris Verloren en Gevonden map" name="okcancelignore" notext="Nee" yestext="Ja"/>
</notification>
<notification name="CopySLURL">
- De volgende SLURL is gekopieerd naar uw klem bord:
+ De volgende SLurl is gekopieerd naar uw klem bord:
[SLURL]
Plaats het in een web pagina om anderen eenvoudig toegang te verschaffen naar de locatie of test het zelf door het te plakken in de adres balk van uw web browser.
<form name="form">
- <ignore name="ignore" text="Bij kopiëren van een SLURL naar het klem bord"/>
+ <ignore name="ignore" text="Bij kopiëren van een SLurl naar het klem bord"/>
</form>
</notification>
<notification name="GraphicsPreferencesHelp">
- Dit venster bepaald de venster afmetingen, resolutie en kwaliteit van de client&apos;s grafische weergave. De Voorkeuren &gt; Grafische interface laat u kiezen uit vier grafische niveaus: Laag, Middel, Hoog en Ultra. U kunt ook uw grafische instellingen aanpassen met het aan vinken van het Custom vakje en de volgende instellingen manipuleren:
+ Dit venster bepaald de venster afmetingen, resolutie en kwaliteit van de client&apos;s grafische weergave. De Voorkeuren &gt; Grafische interface laat u kiezen uit vier grafische niveaus: Laag, Middel, Hoog en Ultra. U kunt ook uw grafische instellingen aanpassen met het aan vinken van het Aangepast vakje en de volgende instellingen manipuleren:
Shaders: In of uitschakelen van de verschillende typen pixel shaders.
-Reflectie Detail: Stelt het type objecten in hetgeen water kan reflecteren.
+Reflectiedetail: Stelt het type objecten in hetgeen water kan reflecteren.
-Avatar Weergave: Stelt de opties in die van invloed zijn op hoe de client een avatar zal renderen.
+Avatarweergave: Stelt de opties in die van invloed zijn op hoe de client een avatar zal renderen.
-Zicht bereik: Beïnvloed tot hoe ver objecten vanaf uw zichtpunt worden weergegeven in de scène.
+Zichtbereik: Beïnvloed tot hoe ver objecten vanaf uw zichtpunt worden weergegeven in de scène.
Maximaal Aantal Particles: Stelt het maximaal aantal particles in die u tegelijk kunt zien op uw scherm.
-Nabewerking Kwaliteit: Stelt de resolutie in waarmee Gloei wordt weergegeven.
+Nabewerkingskwaliteit: Stelt de resolutie in waarmee Gloei wordt weergegeven.
-Maas Detail: Stelt de hoeveelheid detail of het aantal driehoeken in gebruikt voor de weergave van bepaalde objecten. Een hogere waarde zal langer nemen om weer te gegeven, maar zorgen voor objecten met meer detail.
+Maasdetail: Stelt de hoeveelheid detail of het aantal driehoeken in gebruikt voor de weergave van bepaalde objecten. Een hogere waarde zal langer nemen om weer te gegeven, maar zorgen voor objecten met meer detail.
-Licht Detail: Bepaald welke typen lichten u wenst weer te geven.
+Lichtdetail: Bepaald welke typen lichten u wenst weer te geven.
-Terrein Detail: Stelt de hoeveelheid detail in die u wilt zien voor het terrein textuur.
+Terreindetail: Stelt de hoeveelheid detail in die u wilt zien voor het terrein textuur.
</notification>
<notification name="WLSavePresetAlert">
Wilt u de opgeslagen voor instellingen overschrijven?
@@ -2224,7 +2190,7 @@ Klik op &quot;Geavanceerde Lucht&quot; om de editor op te roepen voor geavanceer
Klik op &quot;Geavanceerd Water&quot; om de editor op te roepen voor geavanceerde instellingen voor water.
</notification>
<notification name="HelpDayCycle">
- De Dag Cyclus Editor geeft u controle over de lucht gedurende de Second Life&apos;s dag/nacht cyclus. Dit is de cyclus die gebruikt wordt in de Basis Omgeving Editor&apos;s Tijd van de Dag schuif knop.
+ De Dag Cyclus Editor geeft u controle over de lucht gedurende de [SECOND_LIFE]&apos;s dag/nacht cyclus. Dit is de cyclus die gebruikt wordt in de Basis Omgeving Editor&apos;s Tijd van de Dag schuif knop.
De Dag Cyclus Editor werkt beter met het instellen van gemarkeerde frames. Dit zijn nodes (weergegeven als grijze blips in de tijd weergave) die Hemel voorinstelling met zich geassocieerd hebben. Als de Tijd van de Dag voortschrijdt, &quot;animeert&quot; de WindLight Hemel als het interpoleert tussen de gemarkeerde frames.
@@ -2304,7 +2270,7 @@ Gelijkwaardig aan azimut.
Bepaald de snelheid van de wolken terwijl zij in Y richting bewegen.
</notification>
<notification name="HelpClassicClouds">
- Vink dit aan voor weergave van Second Life&apos;s oudere klassieke wolken als toevoeging op WindLight&apos;s wolken.
+ Vink dit aan voor weergave van [SECOND_LIFE]&apos;s oudere klassieke wolken als toevoeging op WindLight&apos;s wolken.
</notification>
<notification name="HelpWaterFogColor">
Kiest de kleur van de onder water nevel.
@@ -2348,7 +2314,7 @@ Gelijkwaardig aan azimut.
<notification name="NewSkyPreset">
Geef een naam op voor de nieuwe lucht.
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Nieuwe Voorinstelling
</input>
<button name="OK" text="OK"/>
@@ -2361,7 +2327,7 @@ Gelijkwaardig aan azimut.
<notification name="NewWaterPreset">
Geef een naam voor de nieuwe voorinstelling van water.
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Nieuwe Voorinstelling
</input>
<button name="OK" text="OK"/>
@@ -2403,7 +2369,7 @@ Om dit recht in te trekken, moet de object eigenaar het object verwijderen of de
</notification>
<notification name="NotAgeVerified">
U moet leeftijd geverifieerd zijn om toegang te verkrijgen tot dit perceel.
-Wilt u de Second Life website bezoeken om uw leeftijd te verifiëren?
+Wilt u de [SECOND_LIFE] website bezoeken om uw leeftijd te verifiëren?
[_URL]
<url name="url" option="0">
@@ -2413,7 +2379,7 @@ Wilt u de Second Life website bezoeken om uw leeftijd te verifiëren?
</notification>
<notification name="Cannot enter parcel: no payment info on file">
Dit perceel verlangd dat u betaal informatie geregistreerd hebt staan alvorens toegang te verkrijgen.
-Wilt u de Second Life website bezoeken om dit in te stellen?
+Wilt u de [SECOND_LIFE] website bezoeken om dit in te stellen?
[_URL]
<url name="url" option="0">
@@ -2671,7 +2637,7 @@ Gaat u alstublieft naar de kennisbank voor details over het betreden van gebiede
<notification name="ImproperPaymentStatus">
U heeft niet de juiste betalingstatus om deze regio binnen te gaan.
</notification>
- <notification name="MustGetAgeRgion">
+ <notification name="MustGetAgeRegion">
U moet leeftijd geverifieerd zijn om deze regio binnen te gaan.
</notification>
<notification name="MustGetAgeParcel">
@@ -2721,13 +2687,13 @@ Probeer het alstublieft opnieuw over enkele ogenblikken.
Kan wachtende verbinding niet maken.
</notification>
<notification name="InternalUsherError">
- Er is een interne fout opgetreden terwijl geprobeerd werd u naar uw teleportbestemming te begeleiden. Second Life heeft op dit moment mogelijk problemen met de dienstverlening.
+ Er is een interne fout opgetreden terwijl geprobeerd werd u naar uw teleportbestemming te begeleiden. [SECOND_LIFE] heeft op dit moment mogelijk problemen met de dienstverlening.
</notification>
<notification name="NoGoodTPDestination">
Kan geen goede teleportbestemming vinden in deze regio.
</notification>
<notification name="InternalErrorRegionResolver">
- Er is een interne fout opgetreden terwijl de globale coördinaten voor uw teleportverzoek werden bepaald. Second Life heeft op dit moment mogelijk problemen met de dienstverlening.
+ Er is een interne fout opgetreden terwijl de globale coördinaten voor uw teleportverzoek werden bepaald. [SECOND_LIFE] heeft op dit moment mogelijk problemen met de dienstverlening.
</notification>
<notification name="NoValidLanding">
Er kon geen geldig landingspunt worden gevonden.
@@ -2848,7 +2814,7 @@ Van object: [OBJECTNAME], eigenaar: [NAME]?
Kon [TYPE] genaamd [DESC] niet in de database vinden.
</notification>
<notification name="InvalidWearable">
- Het item dat u probeert te dragen gebruikt een kenmerk dat uw viewer niet kan lezen. Upgrade u alstublieft uw versie van Second Life om dit item te dragen.
+ Het item dat u probeert te dragen gebruikt een kenmerk dat uw viewer niet kan lezen. Upgrade u alstublieft uw versie van [APP_NAME] om dit item te dragen.
</notification>
<notification name="ScriptQuestion">
[OBJECTNAME]&apos;, een object van &apos;[NAME]&apos;, wil graag:
@@ -2952,8 +2918,8 @@ Flexibele objecten mogen niet fysiek zijn en moeten fantoom zijn tot de &apos;fl
</notification>
<notification name="FirstDebugMenus">
U heeft het menu Geavanceerd geactiveerd.
-Dit menu bevat opties die handig zijn voor ontwikkelaars tijdens het debuggen van Second Life.
-Om dit menu in en uit te schakelen drukt u binnen Windows Ctrl-Alt-D. Met een Mac drukt u Cmd-Opt-Shift-D.
+Dit menu bevat opties die handig zijn voor ontwikkelaars tijdens het debuggen van [SECOND_LIFE].
+Om dit menu in en uit te schakelen drukt u binnen Windows Ctrl+Alt+D. Met een Mac drukt u &#8997;&#8984;D.
</notification>
<notification name="FirstSculptedPrim">
U bent een sculpted prim aan het bewerken.
@@ -3060,7 +3026,7 @@ Klik Accepteren om deel te nemen aan de chat of Afwijzen om de uitnodiging af te
- Uw Processor snelheid (CPU) voldoet niet aan de minimale eisen.
</global>
<global name="UnsupportedGLRequirements">
- U heeft mogelijk niet de vereiste hardware voor Second Life. Second Life verlangd een OpenGL grafische kaart die multi-texture ondersteund. Indien dat het geval is, overtuig u er dan van dat u de laatste stuurprogramma&apos;s voor uw grafische kaart, service packs en patches voor uw Operating systeem heeft.
+ U heeft mogelijk niet de vereiste hardware voor [APP_NAME]. [APP_NAME] verlangd een OpenGL grafische kaart die multi-texture ondersteund. Indien dat het geval is, overtuig u er dan van dat u de laatste stuurprogramma&apos;s voor uw grafische kaart, service packs en patches voor uw Operating systeem heeft.
Indien u problemen blijft houden, bezoek dan: http://www.secondlife.com/support
</global>
diff --git a/indra/newview/skins/default/xui/nl/panel_edit_profile.xml b/indra/newview/skins/default/xui/nl/panel_edit_profile.xml
new file mode 100644
index 0000000000..172395e20a
--- /dev/null
+++ b/indra/newview/skins/default/xui/nl/panel_edit_profile.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel name="edit_profile_panel">
+ <string name="CaptionTextAcctInfo">
+ [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION]
+ </string>
+ <string name="AcctTypeResident"
+ value="Inwoner" />
+ <string name="AcctTypeTrial"
+ value="Proef" />
+ <string name="AcctTypeCharterMember"
+ value="Charter lid" />
+ <string name="AcctTypeEmployee"
+ value="Linden Lab werknemer" />
+ <string name="PaymentInfoUsed"
+ value="Betalingsinformatie gebruikt" />
+ <string name="PaymentInfoOnFile"
+ value="Betalingsinformatie aanwezig" />
+ <string name="NoPaymentInfoOnFile"
+ value="Geen betalingsinfo aanwezig" />
+ <string name="AgeVerified"
+ value="Leeftijd geverifieerd" />
+ <string name="NotAgeVerified"
+ value="Leeftijd niet geverifieerd" />
+ <string name="partner_edit_link_url">
+ http://www.secondlife.com/account/partners.php?lang=nl
+ </string>
+ <panel name="scroll_content_panel">
+ <panel name="data_panel" >
+ <panel name="lifes_images_panel">
+ <panel name="second_life_image_panel">
+ <text name="second_life_photo_title_text">
+ [SECOND_LIFE]:
+ </text>
+ </panel>
+ </panel>
+ <text name="title_partner_text" value="Partner:"/>
+ <panel name="partner_data_panel">
+ <text name="partner_text" value="[FIRST] [LAST]"/>
+ </panel>
+ <text name="text_box3">
+ Antwoord bij Niet Storen:
+ </text>
+ </panel>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/nl/panel_friends.xml b/indra/newview/skins/default/xui/nl/panel_friends.xml
index 2f43ee0a53..eaf6e5d55b 100644
--- a/indra/newview/skins/default/xui/nl/panel_friends.xml
+++ b/indra/newview/skins/default/xui/nl/panel_friends.xml
@@ -11,10 +11,10 @@
<column name="icon_edit_mine" tool_tip="Vriend kan objecten wijzigen, verwijderen of oppakken"/>
<column name="icon_edit_theirs" tool_tip="U kunt de objecten van deze vriend bewerken"/>
</scroll_list>
- <button label="IM/Oproepen" name="im_btn" tool_tip="Open Instant Message sessie"/>
- <button label="Profiel" name="profile_btn" tool_tip="Toon afbeelding, groepen en andere informatie"/>
- <button label="Teleport..." name="offer_teleport_btn" tool_tip="Bied deze vriend een teleport naar uw huidige locatie aan"/>
- <button label="Betaal..." name="pay_btn" tool_tip="Geef Linden dollars (L$) aan deze vriend"/>
- <button label="Verwijderen..." name="remove_btn" tool_tip="Verwijder deze persoon van uw vriendenlijst"/>
- <button label="Toevoegen..." name="add_btn" tool_tip="Bied vriendschap aan een inwoner aan"/>
+ <button label="IM/Oproepen" name="im_btn" tool_tip="Open Instant Message sessie" width="86"/>
+ <button label="Profiel" name="profile_btn" tool_tip="Toon afbeelding, groepen en andere informatie" width="86"/>
+ <button label="Teleport..." name="offer_teleport_btn" tool_tip="Bied deze vriend een teleport naar uw huidige locatie aan" width="86"/>
+ <button label="Betaal..." name="pay_btn" tool_tip="Geef Linden dollars (L$) aan deze vriend" width="86"/>
+ <button label="Verwijderen..." name="remove_btn" tool_tip="Verwijder deze persoon van uw vriendenlijst" width="86"/>
+ <button label="Toevoegen..." name="add_btn" tool_tip="Bied vriendschap aan een inwoner aan" width="86"/>
</panel>
diff --git a/indra/newview/skins/default/xui/nl/panel_group_general.xml b/indra/newview/skins/default/xui/nl/panel_group_general.xml
index 9982a527f4..2a0fe03232 100644
--- a/indra/newview/skins/default/xui/nl/panel_group_general.xml
+++ b/indra/newview/skins/default/xui/nl/panel_group_general.xml
@@ -16,18 +16,18 @@ Laat uw muis boven de opties zweven voor meer help.
<text name="prepend_founded_by">
Opgericht door
</text>
- <text name="founder_name">
+ <text name="founder_name" left_delta="84">
(wachten)
</text>
- <text name="group_charter_label">
+ <text name="group_charter_label" width="244">
Groepcharter
</text>
<texture_picker label="Groepinsigne" name="insignia" tool_tip="Klik om een afbeelding te kiezen"/>
- <text_editor name="charter">
+ <text_editor name="charter" width="244">
Groepcharter
</text_editor>
<button label="Deelnemen (L$0)" label_selected="Deelnemen (L$0)" name="join_button"/>
- <button label="Gedetailleerde weergave" label_selected="Gedetailleerde weergave" name="info_button"/>
+ <button label="Gedetailleerde weergave" label_selected="Gedetailleerde weergave" name="info_button" width="154"/>
<text name="text_owners_and_visible_members">
Eigenaren en zichtbare leden
</text>
@@ -35,28 +35,22 @@ Laat uw muis boven de opties zweven voor meer help.
(Eigenaren worden vet getoond)
</text>
<name_list name="visible_members">
- <column label="Lidnaam" name="name"/>
- <column label="Titel" name="title"/>
- <column label="Laatste login" name="online"/>
+ <name_list.columns label="Lidnaam" name="name"/>
+ <name_list.columns label="Titel" name="title"/>
+ <name_list.columns label="Laatste login" name="online"/>
</name_list>
<text name="text_group_preferences">
Groepvoorkeuren
</text>
<panel name="preferences_container">
- <check_box label="Toon in zoeken" name="show_in_group_list" tool_tip="Laat mensen deze groep zien in zoekresultaten."/>
+ <check_box label="Toon in zoeken" name="show_in_group_list" tool_tip="Stelt in of deze groep zichtbaar is in de zoekresultaten."/>
<check_box label="Vrije toegang" name="open_enrollement" tool_tip="Stelt in of deze groep toestaat dat nieuwe leden lid kunnen worden zonder uitgenodigd te zijn."/>
- <check_box label="Contributiebijdrage: L$" name="check_enrollment_fee" tool_tip="Stelt in of er een contributiebijdrage vereist is om lid te worden van de groep."/>
- <spinner name="spin_enrollment_fee" tool_tip="Nieuwe leden moeten deze bijdrage betalen om deel te nemen aan de groep wanneer &quot;Contributie bijdrage&quot; is aangevinkt."/>
+ <check_box label="Contributiebijdrage:" name="check_enrollment_fee" tool_tip="Stelt in of er een contributiebijdrage vereist is om lid te worden van de groep."/>
+ <spinner name="spin_enrollment_fee" tool_tip="Nieuwe leden moeten deze bijdrage betalen om deel te nemen aan de groep wanneer &quot;Contributie bijdrage&quot; is aangevinkt." width="58" left_delta="142"/>
<combo_box name="group_mature_check" tool_tip="Stelt in of uw groepsinformatie als mature beschouwd wordt.">
- <combo_item name="select_mature">
- - Selecteer -
- </combo_item>
- <combo_item name="mature">
- Mature inhoud
- </combo_item>
- <combo_item name="pg">
- PG inhoud
- </combo_item>
+ <combo_box.item name="select_mature" label="- Selecteer -"/>
+ <combo_box.item name="mature" label="Mature inhoud"/>
+ <combo_box.item name="pg" label="PG inhoud"/>
</combo_box>
<panel name="title_container">
<text name="active_title_label">
@@ -64,14 +58,15 @@ Laat uw muis boven de opties zweven voor meer help.
</text>
<combo_box name="active_title" tool_tip="Stelt de titel in die in uw avatar&apos;s naamlabel verschijnt wanneer deze groep actief is."/>
</panel>
- <check_box label="Ontvang groepsberichten" name="receive_notices" tool_tip="Stelt in of u berichten van deze groep wilt ontvangen. Verwijder het vinkje wanneer u spam ontvangt van deze groep."/>
+ <check_box label="Ontvang groepsberichten" name="receive_notices" tool_tip="Stelt in of u berichten van deze groep wilt ontvangen. Verwijder het vinkje wanneer u spam ontvangt van deze groep." left_delta="-4"/>
<check_box label="Toon deze groep in mijn profiel" name="list_groups_in_profile" tool_tip="Stelt in of u deze groep in uw profiel wil laten zien"/>
</panel>
<string name="incomplete_member_data_str">
Ledendata ophalen
</string>
<string name="confirm_group_create_str">
- Het maken van deze groep zal u L$100 kosten. Weet u echt, echt, ECHT zeker dat u L$100 wil besteden om deze groep te maken?
-Wees u ervan bewust dat, indien niemand anders binnen 48 uur lid wordt van deze groep, deze ontmanteld zal worden, waarbij de groepsnaam onbeschikbaar zal blijven voor toekomstig gebruik.
+ Het maken van deze groep zal u L$ 100 kosten. Weet u ECHT héél zeker dat u L$ 100 wilt betalen om deze groep te maken?
+
+WEES U ER VAN BEWUST, dat als er niemand binnen 48 uur lid wordt van deze groep, deze weer ontmanteld zal worden. Hierbij zal ook de groepsnaam onbeschikbaar blijven voor toekomstig gebruik!
</string>
</panel>
diff --git a/indra/newview/skins/default/xui/nl/panel_group_invite.xml b/indra/newview/skins/default/xui/nl/panel_group_invite.xml
index 004fdc4bee..e012d88ff5 100644
--- a/indra/newview/skins/default/xui/nl/panel_group_invite.xml
+++ b/indra/newview/skins/default/xui/nl/panel_group_invite.xml
@@ -1,15 +1,18 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Nodig een lid uit" name="invite_panel">
<text name="help_text">
- U kunt meerdere inwoners selecteren om voor uw groep uit te nodigen. Klik &apos;Open inwonerkiezer&apos; om te starten.
+ U kunt meerdere inwoners selecteren
+om voor uw groep uit te nodigen. Klik
+&apos;Open inwonerkiezer&apos; om te starten.
</text>
<button label="Open inwonerkiezer" name="add_button" tool_tip=""/>
<name_list name="invitee_list" tool_tip="Houd de Ctrl-toets vast en klik de namen van de inwoners om meerdere te selecteren."/>
<button label="Verwijder geselecteerden van lijst" name="remove_button" tool_tip="Verwijderd hierboven geselecteerde inwoners van de uitnodigingslijst."/>
<text name="role_text">
- Kies welke rol aan hen wordt toegewezen:
+ Kies welke rol aan hen wordt
+toegewezen:
</text>
- <combo_box name="role_name" tool_tip="Kies uit de lijst met rollen waarvoor u toestemming heeft om leden toe te wijzen."/>
+ <combo_box name="role_name" tool_tip="Kies uit de lijst met rollen waarvoor u toestemming heeft om leden toe te wijzen." bottom_delta="-30"/>
<button label="Verzend uitnodigingen" name="ok_button"/>
<button label="Annuleren" name="cancel_button"/>
<string name="confirm_invite_owner_str">
diff --git a/indra/newview/skins/default/xui/nl/panel_group_notices.xml b/indra/newview/skins/default/xui/nl/panel_group_notices.xml
index 41aff527dd..134261197a 100644
--- a/indra/newview/skins/default/xui/nl/panel_group_notices.xml
+++ b/indra/newview/skins/default/xui/nl/panel_group_notices.xml
@@ -11,7 +11,7 @@
Groepsberichtenarchief
</text>
<text name="lbl2">
- Berichten worden 14 dagen bewaard. Klik hieronder het bericht dat u wilt bekijken. Klik de &apos;Verversen&apos; knop om te controleren of nieuwe berichten zijn ontvangen. Berichtenlijsten zijn gelimiteerd tot 200 berichten groep per dag.
+ Berichten worden 14 dagen bewaard. Berichtenlijsten zijn gelimiteerd tot 200 berichten groep per dag.
</text>
<scroll_list name="notice_list">
<column label="Onderwerp" name="subject"/>
@@ -28,18 +28,21 @@
Maak een bericht
</text>
<text name="lbl2">
- U dient een onderwerp in te voeren om een bericht te versturen. U kunt een enkel item aan een bericht toevoegen door het van uw inventaris naar dit paneel te slepen. Bevestigde items moeten kopieerbaar en overdraagbaar zijn en u kunt geen mappen versturen.
+ U kunt een enkel item aan een bericht toevoegen door het van uw inventaris naar dit paneel te slepen. Bevestigde items moeten kopieerbaar en overdraagbaar zijn en u kunt geen mappen versturen.
</text>
- <text name="lbl3">
+ <text bottom_delta="-79" halign="right" left="10" name="lbl3" width="60">
Onderwerp:
</text>
- <text name="lbl4">
+ <line_editor name="create_subject" width="331" left_delta="71"/>
+ <text bottom_delta="-18" halign="right" left="10" name="lbl4" width="60">
Bericht:
</text>
- <text name="lbl5">
+ <text_editor name="create_message" bottom_delta="-90" height="104" left_delta="71" width="330"/>
+ <line_editor name="create_inventory_name" width="190" left_delta="71"/>
+ <text name="lbl5" left="10">
Bevestig:
</text>
- <button label="Verwijder bevestiging:" label_selected="Verwijder bevestiging:" name="remove_attachment"/>
+ <button label="Verwijder bevestiging" label_selected="Verwijder bevestiging" name="remove_attachment"/>
<button label="Verzend bericht" label_selected="Verzend bericht" name="send_notice"/>
<panel name="drop_target" tool_tip="Sleep een inventarisitem op het berichtvenster om het met het bericht mee te sturen. U dient permissie te hebben om het object te kopiëren en over te dragen wilt u het met het bericht mee kunnen sturen."/>
</panel>
@@ -56,6 +59,7 @@
<text name="lbl4">
Bericht:
</text>
- <button label="Open bevestiging" label_selected="Open bevestiging" name="open_attachment"/>
+ <button label="Open bevestiging" label_selected="Open bevestiging" name="open_attachment" width="118"/>
+ <line_editor left="128" name="view_inventory_name" width="256"/>
</panel>
</panel>
diff --git a/indra/newview/skins/default/xui/nl/panel_group_roles.xml b/indra/newview/skins/default/xui/nl/panel_group_roles.xml
index 50aabb0433..ffaaa8137a 100644
--- a/indra/newview/skins/default/xui/nl/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/nl/panel_group_roles.xml
@@ -12,7 +12,9 @@
Leden &amp; Rollen
</text>
<text name="static2">
- Groepsleden krijgen Rollen met Mogelijkheden toegekend. Deze instellingen kunnen eenvoudig aangepast worden, zodat meer organisatie en flexibiliteit mogelijk is.
+ Groepsleden krijgen Rollen met Mogelijkheden toegekend. Deze instellingen
+kunnen eenvoudig aangepast worden, zodat meer organisatie en flexibiliteit
+mogelijk is.
</text>
</panel>
<panel name="roles_header">
@@ -20,12 +22,14 @@
Rollen
</text>
<text name="role_properties_modifiable">
- Selecteer een Rol hieronder. U kunt zijn Naam, Omschrijving en Lid Titel wijzigen.
+ Selecteer een Rol hieronder. U kunt zijn Naam, Omschrijving en
+Lid Titel wijzigen.
</text>
<text name="role_properties_not_modifiable">
- Selecteer een Rol hieronder om zijn eigenschappen, Leden en toegestane Mogelijkheden te bekijken.
+ Selecteer een Rol hieronder om zijn eigenschappen, Leden en
+toegestane Mogelijkheden te bekijken.
</text>
- <text name="role_actions_modifiable">
+ <text bottom_delta="-28" name="role_actions_modifiable">
U kunt ook Mogelijkheden aan de Rol toekennen.
</text>
<text name="role_actions_not_modifiable">
@@ -37,14 +41,16 @@
Mogelijkheden
</text>
<text name="static2">
- U kunt de Omschrijving van een Mogelijkheid bekijken en welke Rollen en Leden de Mogelijkheid kunnen uitvoeren.
+ U kunt de Omschrijving van een Mogelijkheid bekijken en welke Rollen en
+Leden de Mogelijkheid kunnen uitvoeren.
</text>
</panel>
- <tab_container name="roles_tab_container">
- <panel label="Leden" name="members_sub_tab" tool_tip="Leden">
+ <tab_container height="164" name="roles_tab_container">
+ <panel height="148" label="Leden" name="members_sub_tab" tool_tip="Leden">
+ <line_editor bottom="127" name="search_text"/>
<button label="Zoeken" name="search_button"/>
<button label="Alles Tonen" name="show_all_button"/>
- <name_list name="member_list">
+ <name_list bottom_delta="-105" height="104" name="member_list">
<column label="Lid Naam" name="name"/>
<column label="Gedoneerde Tier" name="donated"/>
<column label="Laatste Login" name="online"/>
@@ -55,15 +61,16 @@
U kunt Rollen aan Leden toewijzen of van Leden afnemen. Selecteer meerdere Leden door de Ctrl toets ingedrukt te houden en op hun namen te klikken.
</string>
</panel>
- <panel label="Rollen" name="roles_sub_tab">
+ <panel height="148" label="Rollen" name="roles_sub_tab">
+ <line_editor bottom="127" name="search_text"/>
<button label="Zoeken" name="search_button"/>
<button label="Alles Tonen" name="show_all_button"/>
- <scroll_list name="role_list">
+ <scroll_list bottom_delta="-104" height="104" name="role_list">
<column label="Rol Naam" name="name"/>
<column label="Titel" name="title"/>
<column label="Leden" name="members"/>
</scroll_list>
- <button label="Nieuwe Rol Maken ..." name="role_create"/>
+ <button label="Nieuwe Rol Maken..." name="role_create"/>
<button label="Rol Verwijderen" name="role_delete"/>
<string name="help_text">
Rollen hebben een titel en een toegestane lijst met Mogelijkheden die Leden kunnen uitvoeren. Leden kunnen tot 1 of meer Rollen behoren. Een groep kan tot 10 Rollen bevatten, inclusief de Iedereen en Eigenaren Rollen.
@@ -72,10 +79,11 @@
De &apos;Iedereen&apos; en &apos;Eigenaren&apos; Rollen zijn speciaal en kunnen niet verwijderd worden.
</string>
</panel>
- <panel label="Mogelijkheden" name="actions_sub_tab">
+ <panel height="148" label="Mogelijkheden" name="actions_sub_tab">
+ <line_editor bottom="127" name="search_text"/>
<button label="Zoeken" name="search_button"/>
<button label="Alles Tonen" name="show_all_button"/>
- <scroll_list name="action_list" tool_tip="Selecteer een Mogelijkheid om meer details te bekijken."/>
+ <scroll_list bottom_delta="-120" height="118" name="action_list" tool_tip="Selecteer een Mogelijkheid om meer details te bekijken."/>
<string name="help_text">
Mogelijkheden stellen leden in staat om specifieke dingen in een groep te doen. Er is een brede variëteit aan Mogelijkheden.
</string>
diff --git a/indra/newview/skins/default/xui/nl/panel_groups.xml b/indra/newview/skins/default/xui/nl/panel_groups.xml
index 5b66eddb73..a0c77b83ff 100644
--- a/indra/newview/skins/default/xui/nl/panel_groups.xml
+++ b/indra/newview/skins/default/xui/nl/panel_groups.xml
@@ -3,13 +3,13 @@
<text name="groupdesc">
Uw huidige actieve groep wordt vet getoond.
</text>
- <text name="groupcount">
+ <text name="groupcount" width="300">
U behoort tot [COUNT] groepen (maximaal [MAX]).
</text>
- <button label="IM/Oproepen" name="IM" tool_tip="Open Instant Message sessie"/>
- <button label="Info" name="Info"/>
- <button label="Activeren" name="Activate"/>
- <button label="Verlaten" name="Leave"/>
- <button label="Maak…" name="Create"/>
- <button label="Zoeken…" name="Search..."/>
+ <button label="IM/Oproepen" name="IM" tool_tip="Open Instant Message sessie" width="86"/>
+ <button label="Info" name="Info" width="86"/>
+ <button label="Activeren" name="Activate" width="86"/>
+ <button label="Verlaten" name="Leave" width="86"/>
+ <button label="Maak…" name="Create" width="86"/>
+ <button label="Zoeken…" name="Search..." width="86"/>
</panel>
diff --git a/indra/newview/skins/default/xui/nl/panel_login.xml b/indra/newview/skins/default/xui/nl/panel_login.xml
index fcf79982c7..235e15e7fb 100644
--- a/indra/newview/skins/default/xui/nl/panel_login.xml
+++ b/indra/newview/skins/default/xui/nl/panel_login.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="panel_login">
- <string name="real_url">
- http://secondlife.com/app/login/
- </string>
- <string name="forgot_password_url">
- http://secondlife.com/account/request.php
- </string>
+ <panel.string name="create_account_url">
+ http://join.secondlife.com/index.php?lang=nl-NL
+ </panel.string>
+ <panel.string name="forgot_password_url">
+ http://secondlife.com/account/request.php?lang=nl-NL
+ </panel.string>
+<panel name="login_widgets">
<text name="first_name_text">
Voornaam:
</text>
@@ -16,18 +17,12 @@
Wachtwoord:
</text>
<text name="start_location_text">
- Start Locatie:
+ Startlocatie:
</text>
<combo_box name="start_location_combo">
- <combo_item name="MyHome">
- Mijn Thuis
- </combo_item>
- <combo_item name="MyLastLocation">
- Mijn Laatste Locatie
- </combo_item>
- <combo_item name="Typeregionname">
- &lt; Type regio naam &gt;
- </combo_item>
+ <combo_box.item name="MyHome" label="Mijn Thuis"/>
+ <combo_box.item name="MyLastLocation" label="Mijn Laatste Locatie"/>
+ <combo_box.item name="Typeregionname" label="&lt; Type regio naam &gt;"/>
</combo_box>
<check_box label="Onthoud wachtwoord" name="remember_check"/>
<button label="Inloggen" label_selected="Inloggen" name="connect_btn"/>
@@ -41,3 +36,4 @@
[VERSION]
</text>
</panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/nl/panel_region_estate.xml b/indra/newview/skins/default/xui/nl/panel_region_estate.xml
index 731887dc5d..7a5fa801d9 100644
--- a/indra/newview/skins/default/xui/nl/panel_region_estate.xml
+++ b/indra/newview/skins/default/xui/nl/panel_region_estate.xml
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Estate" name="Estate">
<text name="estate_help_text">
- Wijzigingen van instellingen op dit tabblad zullen alle regio&apos;s in de estate beïnvloeden.
+ Wijzigingen van instellingen op dit tabblad
+zullen alle regio&apos;s in de estate beïnvloeden.
</text>
<text name="estate_text">
Estate:
@@ -10,7 +11,7 @@
(onbekend)
</text>
<text name="owner_text">
- Eigenaar
+ Eigenaar:
</text>
<text name="estate_owner">
(onbekend)
@@ -25,21 +26,22 @@
<text name="Only Allow">
Beperk toegang tot:
</text>
- <check_box label="Inwoners met betalingsinformatie opgeslagen" name="limit_payment" tool_tip="Verban ongeïdentificeerde inwoners."/>
- <check_box label="Leeftijdgeverifieerde volwassenen" name="limit_age_verified" tool_tip="Verban inwoners die hun leeftijd niet geverifieerd hebben. Zie support.secondlife.com voor meer informatie."/>
+ <check_box label="Inwoners met betalingsinformatie &#10;opgeslagen" name="limit_payment" tool_tip="Verban ongeïdentificeerde inwoners."/>
+ <check_box label="Leeftijdgeverifieerde volwassenen" name="limit_age_verified" tool_tip="Verban inwoners die hun leeftijd niet geverifieerd hebben. Zie support.secondlife.com voor meer informatie." bottom_delta="-30"/>
<check_box label="Voice chat toestaan" name="voice_chat_check"/>
<button label="?" name="voice_chat_help"/>
<check_box label="Directe teleport toestaan" name="allow_direct_teleport"/>
<button label="?" name="allow_direct_teleport_help"/>
- <text name="abuse_email_text">
+ <text name="abuse_email_text" bottom_delta="-23">
Misbruik e-mail adres:
</text>
+ <line_editor bottom_delta="-14" name="abuse_email_address" />
<string name="email_unsupported">
Optie niet ondersteund
</string>
<button label="?" name="abuse_email_address_help"/>
- <button label="Toepassen" name="apply_btn"/>
- <button label="Gebruiker verwijderen van estate" name="kick_user_from_estate_btn"/>
+ <button label="Toepassen" name="apply_btn" bottom_delta="-22"/>
+ <button label="Gebruiker verwijderen van estate..." name="kick_user_from_estate_btn"/>
<button label="Zend bericht naar estate..." name="message_estate_btn"/>
<text name="estate_manager_label">
Estate beheerders:
diff --git a/indra/newview/skins/default/xui/nl/panel_region_general.xml b/indra/newview/skins/default/xui/nl/panel_region_general.xml
index 9ed822ac13..74480ed0a4 100644
--- a/indra/newview/skins/default/xui/nl/panel_region_general.xml
+++ b/indra/newview/skins/default/xui/nl/panel_region_general.xml
@@ -29,9 +29,9 @@
<check_box label="Landverkoop toestaan" name="allow_land_resell_check"/>
<button label="?" name="land_resell_help"/>
<check_box label="Samenvoegen/opsplitsen land toestaan" name="allow_parcel_changes_check"/>
- <button label="?" name="parcel_changes_help"/>
+ <button label="?" name="parcel_changes_help" left="240"/>
<check_box label="Blokkeer zichtbaarheid land in zoeken" name="block_parcel_search_check" tool_tip="Laat mensen deze regio en zijn percelen in zoekresultaten zien"/>
- <button label="?" name="parcel_search_help"/>
+ <button label="?" name="parcel_search_help" left="240"/>
<spinner label="Agent limiet" name="agent_limit_spin"/>
<button label="?" name="agent_limit_help"/>
<spinner label="Object bonus" name="object_bonus_spin"/>
@@ -40,15 +40,9 @@
Inhoudscategorie:
</text>
<combo_box label="Mature" name="access_combo">
- <combo_item name="Adult">
- Adult
- </combo_item>
- <combo_item name="Mature">
- Mature
- </combo_item>
- <combo_item name="PG">
- PG
- </combo_item>
+ <combo_box.item label="Adult" name="Adult"/>
+ <combo_box.item label="Mature" name="Mature"/>
+ <combo_box.item label="PG" name="PG"/>
</combo_box>
<button label="?" name="access_help"/>
<button label="Toepassen" name="apply_btn"/>
diff --git a/indra/newview/skins/default/xui/nl/panel_status_bar.xml b/indra/newview/skins/default/xui/nl/panel_status_bar.xml
index d499ef5af0..1d68d25f66 100644
--- a/indra/newview/skins/default/xui/nl/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/nl/panel_status_bar.xml
@@ -27,8 +27,8 @@
<button label="" label_selected="" name="restrictpush" tool_tip="Niet duwen"/>
<button label="" label_selected="" name="status_no_voice" tool_tip="Voice is niet beschikbaar hier"/>
<button label="" label_selected="" name="buyland" tool_tip="Koop dit perceel"/>
- <line_editor label="Zoeken" name="search_editor" tool_tip="Doorzoek Second Life"/>
- <button label="" label_selected="" name="search_btn" tool_tip="Doorzoek Second Life"/>
+ <line_editor label="Zoeken" name="search_editor" tool_tip="Doorzoek [SECOND_LIFE]"/>
+ <button label="" label_selected="" name="search_btn" tool_tip="Doorzoek [SECOND_LIFE]"/>
<string name="packet_loss_tooltip">
Pakketten verlies
</string>
diff --git a/indra/newview/skins/default/xui/nl/panel_world_map.xml b/indra/newview/skins/default/xui/nl/panel_world_map.xml
new file mode 100644
index 0000000000..11855b7fc1
--- /dev/null
+++ b/indra/newview/skins/default/xui/nl/panel_world_map.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="world_map">
+ <panel.string name="world_map_north">
+ N
+ </panel.string>
+ <panel.string name="world_map_east">
+ O
+ </panel.string>
+ <panel.string name="world_map_west">
+ W
+ </panel.string>
+ <panel.string name="world_map_south">
+ Z
+ </panel.string>
+ <panel.string name="world_map_southeast">
+ ZO
+ </panel.string>
+ <panel.string name="world_map_northeast">
+ NO
+ </panel.string>
+ <panel.string name="world_map_southwest">
+ ZW
+ </panel.string>
+ <panel.string name="world_map_northwest">
+ NW
+ </panel.string>
+ <text label="N" name="floater_map_north" text="N">
+ N
+ </text>
+ <text label="O" name="floater_map_east" text="O">
+ O
+ </text>
+ <text label="W" name="floater_map_west" text="W">
+ W
+ </text>
+ <text label="Z" name="floater_map_south" text="Z">
+ Z
+ </text>
+ <text label="ZO" name="floater_map_southeast" text="ZO">
+ ZO
+ </text>
+ <text label="NO" name="floater_map_northeast" text="NO">
+ NO
+ </text>
+ <text label="ZW" name="floater_map_southwest" text="ZW">
+ ZW
+ </text>
+ <text label="NW" name="floater_map_northwest" text="NW">
+ NW
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/nl/role_actions.xml b/indra/newview/skins/default/xui/nl/role_actions.xml
new file mode 100644
index 0000000000..1f0a6e4235
--- /dev/null
+++ b/indra/newview/skins/default/xui/nl/role_actions.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<role_actions>
+ <action_set description="Deze Mogelijkheden regelen het toevoegen en verwijderen van Groepsleden, en om aan te geven dat nieuwe Leden lid kunnen worden zonder uitnodiging." name="Membership">
+ <action description="Personen uitnodigen voor deze Groep" longdescription="Personen uitnodigen voor deze Groep door de 'Uitnodigen Nieuwe Leden...' knop in de leden &amp; Rollen tab &gt; Leden sub-tab." name="member invite"/>
+ <action description="Leden uit deze Groep zetten" longdescription="Leden uit deze Groep zetten door de 'Uit Groep Zetten' knop in de leden tab &amp; Rollen tab &gt; Leden sub-tab. Een Eigenaar kan iedereen uit de groep zetten behalve een andere Eigenaar. Als je geen Eigenaar bent, kan een Lid worden uitgezet als, en alleen als, het Lid deel uitmaakt van de Iedereen Rol, en NIET van andere Rollen. Om Leden uit Rollen te verwijderen, moet je de 'Leden uit Rollen Verwijderen' mogelijkheid hebben." name="member eject"/>
+ <action description="Selecteer 'Vrije Toegang' en wijzig 'Contibutie Bijdrage'" longdescription="Selecteer 'Vrije Toegang' zodat nieuwe Leden lid kunnen worden zonder uitnodiging, en wijzig 'Contributie Bijdrage' in de Groep Voorkeuren sectie van de Algemene tab." name="member options"/>
+ </action_set>
+ <action_set description="Deze Mogelijkheden regelen het toevoegen, verwijderen, en wijzigen van Groepsrollen, toevoegen en verwijderen van Leden in Rollen, en toewijzen van Mogelijkheden aan Rollen." name="Roles">
+ <action description="Creëren nieuwe Rollen" longdescription="Creëren nieuwe Rollen in de Leden &amp; Rollen tab &gt; Rollen sub-tab." name="role create"/>
+ <action description="Verwijderen Rollen" longdescription="Verwijderen Rollen in de Leden &amp; Rollen tab &gt; Rollen sub-tab." name="role delete"/>
+ <action description="Wijzigen Rol-naam, titel, beschrijving, en of de Rol leden publiekelijk zichtbaar zijn" longdescription="Wijzigen Rol-naam, titel, beschrijving, en of de Rol leden publiekelijk zichtbaar zijn. Dit kan worden gedaan onderaan de de Leden &amp; Rollen tab &gt; Rollen sub-tab na de selectie van een rol." name="role properties"/>
+ <action description="Toewijzen Leden aan Toewijzers Rollen" longdescription="Toewijzen Leden aan Rollen in de Toegewezen Rollen sectie van de Leden &amp; Rol tab &gt; Leden sub-tab. Een Lid met deze Mogelijkheid kan alleen Leden toevoegen aan een Rol waartoe men zelf al behoort." name="role assign member limited"/>
+ <action description="Toewijzen Leden aan Alle Rollen" longdescription="Toewijzen van Leden aan Alle Rollen in the Toegewezen Rollen sectie van de Leden &amp; Rollen tab &gt; Leden sub-tab. *WAARSCHUWING* Ieder Lid in een Rol met deze Mogelijkheid kan zichzelf--en ieder ander niet-Eigenaar Lid--toewijzen aan rollen met meer rechten dan zijzelf op dat moment hebben, hierdoor ontstaat de mogelijkheid om zichzelf bijna-Eigenaar rechten toewijzen. Wees er zeker van en controleer voordat deze Mogelijkheid wordt toegekend." name="role assign member"/>
+ <action description="Verwijderen Leden uit Rollen" longdescription="Verwijderen Leden uit Rollen in the Toegewezen Rollen sectie van de Leden &amp; Rollen tab &gt; Leden sub-tab. Eigenaars kunnen niet worcen verwijderd." name="role remove member"/>
+ <action description="Toewijzen en Verwijderen Mogelijkheden in Rollen" longdescription="Toewijzen en Verwijderen Mogelijkheden in Rollen in de Toegestane Mogelijkheden van de Leden &amp; Rollen tab &gt; Leden sub-tab. *WAARSCHUWING* Ieder Lid in een Rol met deze Mogelijkheid kan kan zichzelf--en ieder ander niet-Eigenaar Lid--toewijzen aan rollen met meer rechten dan zijzelf op dat moment hebben, hierdoor ontstaat de mogelijkheid om zichzelf bijna-Eigenaar rechten toewijzen. Wees er zeker van en controleer voordat deze Mogelijkheid wordt toegekend." name="role change actions"/>
+ </action_set>
+ <action_set description="Deze Mogelijkheden regelen het wijzigen van de Groepsidentiteit, zoals het veranderen van publieke zichtbaarheid, charter en insigne." name="Group Identity">
+ <action description="Wijzigen Charter, Insigne, en 'Toon in zoeken'" longdescription="Wijzigen Charter, Insigne, en 'Toon in zoeken'. Dit kan worden gedaan in de Algemeen tab." name="group change identity"/>
+ </action_set>
+ <action_set description="Deze Mogelijkheden regelen het overdragen, wijzigen, en verkopen van land dat in bezit is van deze groep. Om naar het Over Land venster te gaan, rechts-klik de grond selecteer 'Over Land...', of klik op de perceel info in de menubalk." name="Parcel Management">
+ <action description="Land overdragen en land kopen voor groep" longdescription="Land overdragen en land kopen voor groep. Dit kan worden gedaan in Over Land &gt; Algemeen tab." name="land deed"/>
+ <action description="Land overdragen aan Govenor Linden" longdescription="Land overdragen aan Govenor Linden. *WAARSCHUWING* Ieder Lid in een Rol met deze Mogelijkheid kan land in eigendom van de groep laten vervallen in Over Land &gt; Algemeen tab, teruggeven in Linden eigendom zonder verkoop! Wees er zeker van en controleer voordat deze Mogelijkheid wordt toegekend." name="land release"/>
+ <action description="Activeer land te koop info" longdescription="Activeer land te koop info. *WAARSCHUWING* Ieder Lid in een Rol met deze Mogelijkheid kan land in eigendom van de groep verkopen in Over Land &gt; Algemeen tab als ze dat willen! Wees er zeker van en controleer voordat deze Mogelijkheid wordt toegekend." name="land set sale info"/>
+ <action description="Opdelen en samenvoegen van percelen" longdescription="Opdelen en samenvoegen van percelen. Dit kan worden gedaan door rechts klikken op de grond, 'Terrein Bewerken, en de muis te slepen naar het land om een selectie te maken. Om te verdelen, selecteer wat je wil splitsen en klik 'Opdelen...'. Om samen te voegen, selecteer twee of meer aaneengesloten percelen en klik 'Samenvoegen...'." name="land divide join"/>
+ </action_set>
+ <action_set description="Deze Mogelijkheden regelen het veranderen van de perceelnaam en publicatie instelling, zichtbaarheid in 'Tonen in zoeken', en landingspunt &amp; TP routering." name="Parcel Identity">
+ <action description="Selecteer 'Tonen in zoeken' en instellen categorie" longdescription="Selecteer 'Tonen in zoeken' en instellen van de categorie voor een perceel in Over Land &gt; Opties tab." name="land find places"/>
+ <action description="Veranderen perceel naam, omschrijving, en 'Tonen in zoeken' instellingen" longdescription="Veranderen perceel naam, omschrijving en 'Tonen in zoeken' instellingen. Dit kan worden gedaan in Overland &gt; Opties tab." name="land change identity"/>
+ <action description="Instellen landingsplaats en instellen teleport routering" longdescription="Op een perceel in groepseigendom, Leden in een Rol met die mogelijkheid kunnen een landingsplaats instellen om te bepalen waar inkomende teleports aankomen, en ook een teleport routering instelling voor meer controle. Dit kan worden gedaan in About Land &gt; Opties tab." name="land set landing point"/>
+ </action_set>
+ <action_set description="Deze Mogelijkheden regelen het aanpassen van perceel opties, zoals 'Maak Objecten', 'Bewerken Terrein', en muziek &amp; media instellingen." name="Parcel Settings">
+ <action description="Veranderen muziek &amp; media instellingen" longdescription="Veranderen streaming muziek en film instellingen in Over Land&gt; Media tab." name="land change media"/>
+ <action description="Instellen 'Bewerken Terrein'" longdescription="Instellen 'Bewerken Terrein'. *WAARSCHUWING* Over Land &gt; Opties tab &gt; Bewerken Terrein staat toe dat iedereen de vorm van het terrein kan aanpassen, en Linden planten kan plaatsen en verplaatsen. Wees er zeker van en controleer voordat deze Mogelijkheid wordt toegekend. Bewerken terrein kan worden aangezet in Over Land&gt; Opties tab." name="land edit"/>
+ <action description="Instellen diversen Over Land &gt; Optie instellingen" longdescription="Instellen 'Veilig (geen letsel)', 'Vliegen' and andere Inwoners toestaan om: 'Objecten te maken', 'Terrein te bewerken', en 'Scripts uit te voeren' op land in groepseigendom in Over Land &gt; Opties tab." name="land options"/>
+ </action_set>
+ <action_set description="Deze Mogelijkheden regelend de toestemming voor leden om beperkingen te omzeilen op percelen in groepseigendom." name="Parcel Powers">
+ <action description="'Bewerken Terrein' altijd toestaan" longdescription="Leden in een Rol met deze Mogelijkheid kunnen terrein bewerken op een perceel in groepseigendom, zelfs als de optie uitstaat in Over Land &gt; Opties tab." name="land allow edit land"/>
+ <action description="'Vliegen' altijd toestaan" longdescription="Leden in een Rol met deze Mogelijkheid kunnen vliegen op een perceel in groepseigendom, zelfs als de optie uitstaat in Over Land &gt; Opties tab." name="land allow fly"/>
+ <action description="'Maak Objecten' altijd toestaan" longdescription="Leden in een Rol met deze Mogelijkheid kunnen objecten maken op een perceel in groepseigendom, zelfs als de optie uitstaat in Over Land &gt; Opties tab." name="land allow create"/>
+ <action description="'Maak Landmarkering' altijd toestaan" longdescription="Leden in een Rol met deze Mogelijkheid kunnen een landmarkering maken op een perceel in groepseigendom, zelfs als de optie uitstaat in Over Land &gt; Opties tab." name="land allow landmark"/>
+ <action description="Toestaan 'Thuis hier Instellen' op land in groepseigendom" longdescription="Leden in een Rol met deze Mogelijkheid kunnen gebruik maken van Wereld menu &gt; Thuis hier Instellen op een perceel afgestaan aan deze groep." name="land allow set home"/>
+ </action_set>
+ <action_set description="Deze Mogelijkheden regelen het toestaan of beperken van toegang van percelen in groepseigendom, inclusief het bevriezen en verbannen van Inwoners." name="Parcel Access">
+ <action description="Beheren perceel Toegang lijsten" longdescription="Beheren perceel Toegang lijsten in Over Land &gt; Toegang tab." name="land manage allowed"/>
+ <action description="Beheren perceel Verbannen lijst" longdescription="Beheren perceel Verbannen lijst in Over Land &gt; Verbannen tab." name="land manage banned"/>
+ <action description="Veranderen perceel 'Verkoop toegangspassen...' instellingen" longdescription="Verandere perceel 'Verkoop toegangspassen...'instellingen" name="land manage passes"/>
+ <action description="Uitwerpen en bevriezen Inwoners op percelen" longdescription="Leden in een Rol met deze mogelijkheid kunnen een onwelkome Inwoners aanpakken op een perceel in groepseigendom door een rechter-klik op deze inwoner &gt; en 'Uitwerpen...'of 'Bevriezen...'te selecteren." name="land admin"/>
+ </action_set>
+ <action_set description="Deze Mogelijkheden regelen de toestemming voor leden om objecten te retourneren en Linden planten te plaatsen en te verplaatsen. Dit is nuttig voor Leden om rommel op te ruimen en landschappen te maken, echter het moet ook met omzichtigheid worden gebruikt, omdat er geen herstelfunktie is voor retourneren objecten." name="Parcel Content">
+ <action description="Retourneren objecten in groepseigendom" longdescription="Retourneren van objecten die in eigendom zijn van de groep op percelen in groepseigendom in Over Land &gt; Objecten tab." name="land return group owned"/>
+ <action description="Retourneren objecten toegewezen aan de groep" longdescriotion="Retourneren van objecten die aan de groep zijn toegewezen op percelen in groepseigendom in Over Land &gt; Objecten tab." name="land return group set"/>
+ <action description="Retourneren objecten die niet van de groep zijn" longdescription="Retourneren objecten die niet van de groep zijn op percelen in groepeigendom in Over Land &gt; Objecten tab." name="land return non group"/>
+ <action description="Landschappen maken met Linden planten" longdescription="Landschappen maken om Linden bomen, planten en grassen te plaatsen en te verplaatsen. Deze opties zijn te vinden in de inventaris Library &gt; Objects folder of ze kunnen worden gemaakt via de Bouwen knop." name="land gardening"/>
+ </action_set>
+ <action_set description="Deze Mogelijkheden regelen het afstaan, wijzigen, en verkopen van objecten in groepseigendom. Deze veranderingen worden gedaan in Bewerken Gereedschap &gt; Algemeen tab. Rechts-klik een object en selecteer Bewerken om de instellingen ervan te bekijken." name="Object Management">
+ <action description="Overdragen objecten aan groep" longdescription="Overdragen objecten aan groep in de Bewerkings Hulpmiddelen &gt; Algemeen tab." name="object deed"/>
+ <action description="Manipuleren (verplaatsen, copieren, wijzigen) van objecten in groepseigendom" longdescription="Manipuleren (verplaatsen, copieren, wijzigen) van objecten in groepseigendom in de Bewerkings Hulpmiddelen &gt; Algemeen tab." name="object manipulate"/>
+ <action description="Te koop zetten van objecten in groepseigendom" longdescription="Te koop zetten van objecten in groepseigendom in de Bewerkings Hulpmiddelen &gt; Algemeen tab." name="object set sale"/>
+ </action_set>
+ <action_set description="Deze Mogelijkheden regelen dat Leden groepsverplichtingen betalen en groepsdividenden ontvangen, en toegang beperken tot de financiele historie van de groep." name="Accounting">
+ <action description="Betalen groepsverplichtingen en ontvangen van groepsdividenden" longdescription="Leden in een Rol met deze mogelijkheid betalen groepsverplichtingen en ontvangen groepsdividenden automatisch. Dit betekent dat ze een deel ontvangen van de verkoop van land in groepseigendom die dagelijks worden verdeeld, maar ook dat ze bijdragen aan zaken zoals lijstbijdrage voor het perceel." name="accounting accountable"/>
+ </action_set>
+ <action_set description="Deze Mogelijkheden regelen de toestemming dat Leden Groepsberichten kunnen versturen, ontvangen en inzien." name="Notices">
+ <action description="Versturen Berichten" longdescription="Leden in een Rol met deze Mogelijkheid kunnen Berichten versturen in Groep Informatie &gt; Berichten tab." name="notices send"/>
+ <action description="Ontvangen Berichten en inzien van oude Berichten" longdescription="Leden in een Rol met deze Mogelijkheid kunnen Berichten ontvangen en oude Berichten inzien in Groep Informatie &gt; Berichten tab." name="notices receive"/>
+ </action_set>
+ <action_set description="Deze Mogelijkheden regelen de toestemming dat Leden Voorstellen kunnen maken, Voorstellen kunnen inzien, en het stemverloop kunnen bekijken." name="Proposals">
+ <action description="Maken Voorstellen" longdescription="Leden in een Rol met deze Mogelijkheid kunnen Voorstellen maken waarop kan worden gestemd in Groep Informatie &gt; Voorstellen tab." name="proposal start"/>
+ <action description="Stemmen op Voorstellen" longdescription="Leden in een Rol met deze Mogelijkheid kunnen stemmen op Voorstellen in Groep Informatie &gt; Voorstellen tab." name="proposal vote"/>
+ </action_set>
+ <action_set description="Deze Mogelijkheden regelen de toegang (en de beperking ervan) tot groep chat sessies en groep voice chat." name="Chat">
+ <action description="Deelname aan Groep Chat" longdescription="Leden in een Rol met deze Mogelijkheid kunnen deelnemen aan groep chat sessies, zowel voor tekst als voice." name="join group chat"/>
+ <action description="Deelname aan Groep Voice Chat" longdescription="Leden in een Rol met deze Mogelijkheid kunnen deelnemen aan groep voice chat sessies. OPMERKING: De Deelname Group Chat is vereist om toegang te krijgen to de voice chat sessie." name="join voice chat"/>
+ <action description="Modereren Groep Chat" longdescription="Leden in een Rol met deze Mogelijkheid kunnen toegang en deelname controleren in groep voice en tekst chat sessies." name="moderate group chat"/>
+ </action_set>
+</role_actions> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/nl/strings.xml b/indra/newview/skins/default/xui/nl/strings.xml
index 4b64586887..0be5ec9e86 100644
--- a/indra/newview/skins/default/xui/nl/strings.xml
+++ b/indra/newview/skins/default/xui/nl/strings.xml
@@ -4,6 +4,7 @@
For example, the strings used in avatar chat bubbles, and strings
that are returned from one component and may appear in many places-->
<strings>
+ <string name="create_account_url">http://join.secondlife.com/index.php?lang=nl-NL</string>
<string name="LoginInProgress">
Inloggen. Het kan lijken dat [APP_NAME] is vastgelopen. Wacht u alstublieft... .
</string>
@@ -55,6 +56,9 @@
<string name="LoginDownloadingClothing">
Kleding downloaden...
</string>
+ <string name="Quit">
+ Afsluiten
+ </string>
<string name="AgentLostConnection">
Deze regio kan problemen ondervinden. Controleer alstublieft uw verbinding met het internet.
</string>
@@ -483,4 +487,170 @@
<string name="choose_the_directory">
Kies folder
</string>
+ <string name="accel-mac-control">
+ &#8963;
+ </string>
+ <string name="accel-mac-command">
+ &#8984;
+ </string>
+ <string name="accel-mac-option">
+ &#8997;
+ </string>
+ <string name="accel-mac-shift">
+ &#8679;
+ </string>
+ <string name="accel-win-control">
+ Ctrl+
+ </string>
+ <string name="accel-win-alt">
+ Alt+
+ </string>
+ <string name="accel-win-shift">
+ Shift+
+ </string>
+ <string name="GraphicsQualityLow">
+ Laag
+ </string>
+ <string name="GraphicsQualityMid">
+ Middel
+ </string>
+ <string name="GraphicsQualityHigh">
+ Hoog
+ </string>
+
+ <!-- PARCEL_CATEGORY_UI_STRING -->
+ <string name="Linden Location">Linden locatie</string>
+ <string name="Adult">Adult</string>
+ <string name="Arts&amp;Culture">Kunst &amp; Cultuur</string>
+ <string name="Business">Zakelijk</string>
+ <string name="Educational">Educatief</string>
+ <string name="Gaming">Spelen</string>
+ <string name="Hangout">Ontmoetingsplaats</string>
+ <string name="Newcomer Friendly">Nieuwkomervriendelijk</string>
+ <string name="Parks&amp;Nature">Parken &amp; natuur</string>
+ <string name="Residential">Woongebied</string>
+ <string name="Shopping">Winkelen</string>
+ <string name="Other">Anders</string>
+
+ <string name="ringing">
+ Verbinden met in-wereld voice chat...
+ </string>
+ <string name="connected">
+ Verbonden
+ </string>
+ <string name="unavailable">
+ Voice is niet beschikbaar op uw huidige locatie
+ </string>
+ <string name="hang_up">
+ Verbinding met in-wereld voicechat verbroken
+ </string>
+ <string name="ScriptQuestionCautionChatGranted">
+ &apos;[OBJECTNAME]&apos;, een object van &apos;[OWNERNAME]&apos;, gevestigd in [REGIONNAME] op [REGIONPOS], is toestemming verleend om te: [PERMISSIONS].
+ </string>
+ <string name="ScriptQuestionCautionChatDenied">
+ &apos;[OBJECTNAME]&apos;, een object van &apos;[OWNERNAME]&apos;, gevestigd in [REGIONNAME] op [REGIONPOS], is toestemming geweigerd om te: [PERMISSIONS].
+ </string>
+ <string name="ScriptTakeMoney">
+ Linden dollars (L$) van u wegnemen
+ </string>
+ <string name="ActOnControlInputs">
+ Acteren op uw bedieningsinvoer
+ </string>
+ <string name="RemapControlInputs">
+ Uw bedieningsinvoer herdefiniëren
+ </string>
+ <string name="AnimateYourAvatar">
+ Animeer uw avatar
+ </string>
+ <string name="AttachToYourAvatar">
+ Bevestig aan uw avatar
+ </string>
+ <string name="ReleaseOwnership">
+ Eigendom vrijgeven en openbaar worden
+ </string>
+ <string name="LinkAndDelink">
+ Koppelen met en ontkoppelen van andere objecten
+ </string>
+ <string name="AddAndRemoveJoints">
+ Toevoegen en verwijderen koppelingen met andere objecten
+ </string>
+ <string name="ChangePermissions">
+ Wijzig zijn permissies
+ </string>
+ <string name="TrackYourCamera">
+ Volg uw camera
+ </string>
+ <string name="ControlYourCamera">
+ Bedien uw camera
+ </string>
+
+ <string name="only_user_message">
+ U bent de enige gebruiker in deze sessie.
+ </string>
+ <string name="offline_message">
+ [FIRST] [LAST] is offline.
+ </string>
+ <string name="invite_message">
+ Klik de [BUTTON NAME] knop om deze voicechat te accepteren/verbinden.
+ </string>
+ <string name="generic_request_error">
+ Fout tijdens het maken van het verzoek, probeer het later nog een keer.
+ </string>
+ <string name="insufficient_perms_error">
+ U heeft niet voldoende permissies.
+ </string>
+ <string name="session_does_not_exist_error">
+ De sessie bestaat niet meer
+ </string>
+ <string name="no_ability_error">
+ U beschikt niet over die mogelijkheid.
+ </string>
+ <string name="no_ability">
+ U beschikt niet over die mogelijkheid.
+ </string>
+ <string name="not_a_mod_error">
+ U bent geen sessie moderateur
+ </string>
+ <string name="muted_error">
+ Een groepsmoderator heeft uw textchat uitgeschakeld.
+ </string>
+ <string name="add_session_event">
+ Kan geen gebruikers toevoegen aan chatsessie met [RECIPIENT].
+ </string>
+ <string name="message_session_event">
+ Kan uw bericht niet versturen naar de chatsessie met [RECIPIENT].
+ </string>
+ <string name="removed_from_group">
+ U bent verwijderd uit de groep.
+ </string>
+ <string name="close_on_no_ability">
+ U heeft niet langer de mogelijkheid om in deze chatsessie te zijn.
+ </string>
+ <string name="AcctTypeResident">
+ Inwoner
+ </string>
+ <string name="AcctTypeTrial">
+ Proef
+ </string>
+ <string name="AcctTypeCharterMember">
+ Charter lid
+ </string>
+ <string name="AcctTypeEmployee">
+ Linden Lab werknemer
+ </string>
+ <string name="PaymentInfoUsed">
+ Betalingsinformatie gebruikt
+ </string>
+ <string name="PaymentInfoOnFile">
+ Betalingsinformatie aanwezig
+ </string>
+ <string name="NoPaymentInfoOnFile">
+ Geen betalingsinfo aanwezig
+ </string>
+ <string name="AgeVerified">
+ Leeftijd geverifieerd
+ </string>
+ <string name="NotAgeVerified">
+ Leeftijd niet geverifieerd
+ </string>
</strings>
diff --git a/indra/newview/skins/default/xui/pl/floater_about.xml b/indra/newview/skins/default/xui/pl/floater_about.xml
index c013d3cb76..f59630edc7 100755
--- a/indra/newview/skins/default/xui/pl/floater_about.xml
+++ b/indra/newview/skins/default/xui/pl/floater_about.xml
@@ -1,10 +1,19 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_about" title="O Second Life">
+<floater name="floater_about" title="O [CAPITALIZED_APP_NAME]">
+<tab_container name="about_tab">
+ <panel name="credits_panel">
<text_editor name="credits_editor">
- Second Life zostało stworzone dla Was przez: Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les i wielu innych.
+ Second Life zostało stworzone dla Was przez: Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, Michon, Jenelle, Geo, Siz, Shapiro, Pete, Calyle, Selene, Allen, Phoebe, Goldin, Kimmora, Dakota, Slaton, Lindquist, Zoey, Hari, Othello, Rohit, Sheldon, Petra, Viale, Gordon, Kaye, Pink, Ferny, Emerson, Davy, Bri, Chan, Juan, Robert, Terrence, Nathan, Carl i wielu innych.
- Podziękowania dla następujących rezydentów za pomoc w pracy nad obecną wersją Second Life: afon shepherd, Aimee Trescothick, Alexandrea Fride, Alissa Sabre, Amber DeCuir, Asuka Neely, Auron Forcella, Blue Revolution, Bocan Undercroft, Boroondas Gupte, Brandon Shinobu, Bri Gufler, Buckaroo Mu, Celierra Darling, Christos Atlantis, Coder Kas, Cummere Mayo, dakota schwade, Dirk Talamasca, Dizzy Banjo, Drew Dwi, Duckling Kwak, Ellla McMahon, Erikah Jameson, Erinyse Planer, Eyana Yohkoh, Ezian Ecksol, Faron Karu, Fenoe Lowey, Fox Hwasung, Francisca Biedermann, Gally Young, Gellan Glenelg, Geneko Nemeth, Glenn Rotaru, Hagar Qinan, Harleen Gretzky, Holger Gilruth, hotrodjohnny gears, IAm Zabelin, Inigo Catteneo, Iustinian Tomsen, Jacek Antonell, James Benedek, Jim Kupferberg, Joeseph Albanese, JPT62089 Agnon, Kardargo Adamczyk, Kirstenlee Cinquetti, Latif Khalifa, lea Parnall, Lex Neva, Lillith Anatine, Lilly Zenovka, Lim Catteneo, Lindal Kidd, Mark Rosenbaum, MasterJ Chaplin, McCabe Maxsted, Melvin Starbrook, Meni Kaiousei, Mero Collas, Minakothegothicgeisha Kamachi, Moon Metty, neofilo aabye, Neutron Chesnokov, Nomad Ingwer, norritt Xi, Opensource Obscure, Oracle Weatherwax, Ourasi Ferraris, Pabl0 Roffo, Peyton Aleixandre, Phli Foxchase, Psi Merlin, r2d2 Wunderlich, Regi Yifu, Saijanai Kuhn, Sandor Balczo, Sarkan Dreamscape, Scree Raymaker, Sedona Mills, Selena Beale, Sheet Spotter, Shibari Twine, Silver Key, Simon Kline, SLB Wirefly, Stacy Wombat, Sugarcult Dagger, Tayra Dagostino, Tetsuryu Vlodovic, ThaBiGGDoGG Richez, Timo Gufler, tx Oh, wayfinder wishbringer, Wizzytoe McCullough, Wundur Primbee, Yann Dufaux, Yuu Nakamichi, Aminom Marvin, Andred Qinan, arminasx saiman, caroline apollo, Iskar Ariantho, Jenika Connolly, Maghnus Balogh, Nefertiti Nefarious, RodneyLee Jessop
+ Podziękowania dla następujących rezydentów za pomoc w pracy nad obecną wersją Second Life: able whitman, Adeon Writer, adonaira aabye, Aeron Kohime, Agathos Frascati, Aimee Trescothick, Aleric Inglewood, Alissa Sabre, Aminom Marvin, Angela Talamasca, Aralara Rajal, Armin Weatherwax, Ashrilyn Hayashida, Athanasius Skytower, Aura Dirval, Barney Boomslang, Biancaluce Robbiani, Biker Offcourse, Borg Capalini, Bulli Schumann, catherine pfeffer, Chalice Yao, Corre Porta, Court Goodman, Cummere Mayo, Dale Innis, Darien Caldwell, Darjeeling Schoonhoven, Daten Thielt, dimentox travanti, Dirk Talamasca, Drew Dwi, Duckless Vandyke, Elanthius Flagstaff, Electro Burnstein, emiley tomsen, Escort DeFarge, Eva Rau, Ezian Ecksol, Fire Centaur, Fluf Fredriksson, Francisco Koolhoven, Frontera Thor, Frungi Stastny, Gally Young, gearsawe stonecutter, Gigs Taggart, Gordon Wendt, Gudmund Shepherd, Gypsy Paz, Harleen Gretzky, Henri Beauchamp, Inma Rau, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Jessicka Graves, Joeseph Albanese, Joshua Philgarlic, Khyota Wulluf, kirstenlee Cinquetti, Latif Khalifa, Lex Neva, Lilibeth Andree, Lisa Lowe, Lunita Savira, Loosey Demonia, lum pfohl, Marcos Fonzarelli, MartinRJ Fayray, Marusame Arai, Matthew Dowd, Maya Remblai, McCabe Maxsted, Meghan Dench, Melchoir Tokhes, Menos Short, Michelle2 Zenovka, Mimika Oh, Minerva Memel, Mm Alder, Ochi Wolfe, Omei Turnbull, Pesho Replacement, Phantom Ninetails, phoenixflames kukulcan, Polo Gufler, prez pessoa, princess niven, Prokofy Neva, Qie Niangao, Rem Beattie, RodneyLee Jessop, Saijanai Kuhn, Seg Baphomet, Sergen Davies, Shirley Marquez, SignpostMarv Martin, Sindy Tsure, Sira Arbizu, Skips Jigsaw, Sougent Harrop, Spritely Pixel, Squirrel Wood, StarSong Bright, Subversive Writer, Sugarcult Dagger, Sylumm Grigorovich, Tammy Nowotny, Tanooki Darkes, Tayra Dagostino, Theoretical Chemistry, Thickbrick Sleaford, valerie rosewood, Vex Streeter, Vixen Heron, Whoops Babii, Winter Ventura, Xiki Luik, Yann Dufaux, Yina Yao, Yukinoroh Kamachi, Zolute Infinity, Zwagoth Klaar
+
+
+ I get by with a little help from my friends. --Richard Starkey
+ </text_editor>
+ </panel>
+ <panel name="licenses_panel">
+ <text_editor name="credits_editor">
3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
APR Copyright (C) 2000-2004 The Apache Software Foundation
cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
@@ -25,12 +34,9 @@
Wszystkie prawa zastrzeżone. Szczegóły w pliku licenses.txt.
Programowanie dźwięku czatu: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
-
- Polska wersja klienta: Maciek Marksman, Malwina Dollinger, Magnus Balczo
- IMy z sugestiami, komentarzami i poprawkami mile widziane
-
- I get by with a little help from my friends. --Richard Starkey
</text_editor>
+ </panel>
+</tab_container>
<string name="you_are_at">
Położenie: [POSITION]
</string>
diff --git a/indra/newview/skins/default/xui/pl/floater_about_land.xml b/indra/newview/skins/default/xui/pl/floater_about_land.xml
index 5f4bf4ece6..d456ea26b4 100755
--- a/indra/newview/skins/default/xui/pl/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/pl/floater_about_land.xml
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterland" title="O Posiadłości">
+<floater name="floaterland" title="O POSIADÅOÅšCI">
<tab_container name="landtab">
<panel label="Ogólne" name="land_general_panel">
- <text length="1" name="Name:" type="string">
+ <text name="Name:">
Nazwa:
</text>
- <text length="1" name="Description:" type="string">
+ <text name="Description:">
Opis:
</text>
<text name="LandType">
@@ -20,56 +20,56 @@
<text name="ContentRatingText">
&apos;Adult&apos;
</text>
- <text length="1" name="Owner:" type="string">
+ <text name="Owner:">
Właściciel:
</text>
- <text length="1" name="OwnerText" type="string">
+ <text name="OwnerText">
Leyla Linden
</text>
<button label="Profile..." label_selected="Profile..." name="Profile..."/>
- <text length="1" name="Group:" type="string">
+ <text name="Group:">
Grupa:
</text>
<button label="Ustaw..." label_selected="Ustaw..." name="Set..."/>
<check_box label="Udostępnij przypisywanie na grupę" name="check deed" tool_tip="Oficer grupy ma prawo przepisać prawo własności posiadłości na grupę. Posiadłość wspierana jest przez przydziały pochodzące od członków grupy."/>
<button label="Przypisz..." label_selected="Przypisz..." name="Deed..." tool_tip="Prawo przypisania posiadłości na grupę może dokonać jedynie oficer grupy."/>
<check_box label="Właścicel dokonuje wpłat związanych z posiadłością" name="check contrib" tool_tip="Kiedy posiadłość zostaje przypisana na grupę, poprzedni właściciel realizuje wpłaty z nią związane w celu jej utrzymania."/>
- <text length="1" name="For Sale:" type="string">
+ <text name="For Sale:">
Na Sprzedaż:
</text>
- <text length="1" name="Not for sale." type="string">
+ <text name="Not for sale.">
Nie
</text>
- <text length="1" name="For Sale: Price L$[PRICE]." type="string">
+ <text name="For Sale: Price L$[PRICE].">
Cena: L$[PRICE] (L$[PRICE_PER_SQM]/m²).
</text>
<button label="Sprzedaj Posiadłość..." label_selected="Sprzedaj Posiadłość..." name="Sell Land..."/>
- <text length="1" name="For sale to" type="string">
+ <text name="For sale to">
Na sprzedaż dla: [BUYER]
</text>
- <text length="1" name="Sell with landowners objects in parcel." type="string">
+ <text name="Sell with landowners objects in parcel.">
Obiekty są zawarte w sprzedaży.
</text>
- <text length="1" name="Selling with no objects in parcel." type="string">
+ <text name="Selling with no objects in parcel.">
Obiekty nie są zawarte w sprzedaży.
</text>
<button label="Anuluj Sprzedaż" label_selected="Anuluj Sprzedaż" name="Cancel Land Sale"/>
- <text length="1" name="Claimed:" type="string">
+ <text name="Claimed:">
Data:
</text>
- <text length="1" name="DateClaimText" type="string">
+ <text name="DateClaimText">
Tue Aug 15 13:47:25 2006
</text>
- <text length="1" name="PriceLabel" type="string">
+ <text name="PriceLabel">
Obszar:
</text>
- <text length="1" name="PriceText" type="string">
+ <text name="PriceText">
4048 m²
</text>
- <text length="1" name="Traffic:" type="string">
+ <text name="Traffic:">
Ruch:
</text>
- <text length="1" name="DwellText" type="string">
+ <text name="DwellText">
0
</text>
<button label="Kup Posiadłość..." label_selected="Kup Posiadłość..." left="130" name="Buy Land..." width="125"/>
@@ -78,76 +78,76 @@
<button label="Porzuć z Posiadłości..." label_selected="Porzuć z Posiadłości..." name="Abandon Land..."/>
<button label="Odzyskaj Posiadłość..." label_selected="Odzyskaj Posiadłość..." name="Reclaim Land..."/>
<button label="Sprzedaż przez Lindenów..." label_selected="Sprzedaż przez Lindenów..." name="Linden Sale..." tool_tip="Posiadłość musi mieć właściciela, zawartość oraz nie może być wystawiona na aukcę."/>
- <string name="new users only">
+ <panel.string name="new users only">
Tylko nowi użytkownicy
- </string>
- <string name="anyone">
+ </panel.string>
+ <panel.string name="anyone">
Każdy
- </string>
- <string name="area_text">
+ </panel.string>
+ <panel.string name="area_text">
Obszar:
- </string>
- <string name="area_size_text">
+ </panel.string>
+ <panel.string name="area_size_text">
[AREA] m²
- </string>
- <string name="auction_id_text">
+ </panel.string>
+ <panel.string name="auction_id_text">
Numer aukcji: [ID]
- </string>
- <string name="need_tier_to_modify">
+ </panel.string>
+ <panel.string name="need_tier_to_modify">
Musisz zaakceptować zakup by móc modyfikować posiadłość.
- </string>
- <string name="group_owned_text">
+ </panel.string>
+ <panel.string name="group_owned_text">
(Własność Grupy)
- </string>
- <string name="profile_text">
+ </panel.string>
+ <panel.string name="profile_text">
Profil...
- </string>
- <string name="info_text">
+ </panel.string>
+ <panel.string name="info_text">
Info...
- </string>
- <string name="public_text">
+ </panel.string>
+ <panel.string name="public_text">
(publiczne)
- </string>
- <string name="none_text">
+ </panel.string>
+ <panel.string name="none_text">
(brak)
- </string>
- <string name="sale_pending_text">
+ </panel.string>
+ <panel.string name="sale_pending_text">
(Sprzedaż w Toku Realizacji)
- </string>
- <string name="no_selection_text">
+ </panel.string>
+ <panel.string name="no_selection_text">
Posiadłość nie wybrana.
Idź do Świat &gt; O Posiadłości albo wybierz inną posiadłość żeby pokazać jej dane.
- </string>
+ </panel.string>
</panel>
<panel label="Umowa" name="land_covenant_panel">
<text name="estate_section_lbl">
MajÄ…tek:
</text>
- <text length="1" name="estate_name_lbl" type="string">
+ <text name="estate_name_lbl">
Nazwa:
</text>
- <text length="1" name="estate_name_text" type="string" left="115">
+ <text name="estate_name_text" left="115">
Główne
</text>
- <text length="1" name="estate_owner_lbl" type="string">
+ <text name="estate_owner_lbl">
Właściciel:
</text>
- <text length="1" name="estate_owner_text" type="string" left="115">
+ <text name="estate_owner_text" left="115">
(brak)
</text>
- <text_editor length="1" name="covenant_editor" type="string" left="115">
+ <text_editor name="covenant_editor" left="115">
Ta posiadłość nie wymaga żadej umowy.
</text_editor>
- <text length="1" name="covenant_timestamp_text" type="string" left="115">
+ <text name="covenant_timestamp_text" left="115">
Ostatnia Modyfikacja Wed Dec 31 16:00:00 1969
</text>
<text name="region_section_lbl">
Region:
</text>
- <text length="1" name="region_name_lbl" type="string">
+ <text name="region_name_lbl">
Nazwa:
</text>
- <text length="1" name="region_name_text" type="string" left="115">
+ <text name="region_name_text" left="115">
leyla
</text>
<text name="region_landtype_lbl">
@@ -165,92 +165,92 @@ Idź do Świat &gt; O Posiadłości albo wybierz inną posiadłość żeby pokaz
<text name="resellable_lbl">
Odsprzedaj:
</text>
- <text length="1" name="resellable_clause" type="string" width="338" left="115">
+ <text name="resellable_clause" width="338" left="115">
Posiadłość zakupiona w tym regionie nie może być odsprzedana.
</text>
<text name="changeable_lbl">
Podziel:
</text>
- <text length="1" name="changeable_clause" type="string" width="338" left="115">
+ <text name="changeable_clause" width="338" left="115">
Posiadłość zakupiona w tym regionie nie może być
Å‚Ä…czona/dzielona.
</text>
- <string name="can_resell">
+ <panel.string name="can_resell">
Posiadłość zakupiona w tym regionie może być odsprzedana.
- </string>
- <string name="can_not_resell">
+ </panel.string>
+ <panel.string name="can_not_resell">
Posiadłość zakupiona w tym regionie nie może być odsprzedana.
- </string>
- <string name="can_change">
+ </panel.string>
+ <panel.string name="can_change">
Posiadłość zakupiona w tym regionie może być łączona/dzielona.
- </string>
- <string name="can_not_change">
+ </panel.string>
+ <panel.string name="can_not_change">
Posiadłość zakupiona w tym regionie nie może być
Å‚Ä…czona/dzielona.
- </string>
+ </panel.string>
</panel>
<panel label="Obiekty" name="land_objects_panel">
- <text length="1" name="parcel_object_bonus" type="string">
+ <text name="parcel_object_bonus">
Ilość Ekstra Obiektów: [BONUS]
</text>
- <text length="1" name="Simulator primitive usage:" type="string">
+ <text name="Simulator primitive usage:">
Ilość używanych primóww:
</text>
- <text length="1" name="objects_available" type="string" width="230">
+ <text name="objects_available" width="230">
[COUNT] z [MAX] ([AVAILABLE] jest dostępne)
</text>
- <string name="objects_available_text">
+ <panel.string name="objects_available_text">
[COUNT] z [MAX] ([AVAILABLE] jest dostępne)
- </string>
- <string name="objects_deleted_text">
+ </panel.string>
+ <panel.string name="objects_deleted_text">
[COUNT] z [MAX] ([DELETED] zostanie usunięte)
- </string>
- <text length="1" name="Primitives parcel supports:" type="string">
+ </panel.string>
+ <text name="Primitives parcel supports:">
Maksymalna ilość primów:
</text>
- <text length="1" name="object_contrib_text" type="string">
+ <text name="object_contrib_text">
[COUNT]
</text>
- <text length="1" name="Primitives on parcel:" type="string">
+ <text name="Primitives on parcel:">
Primy na posiadłości:
</text>
- <text length="1" name="total_objects_text" type="string">
+ <text name="total_objects_text">
[COUNT]
</text>
- <text length="1" name="Owned by parcel owner:" type="string">
+ <text name="Owned by parcel owner:">
Właściciela posiadłości:
</text>
- <text length="1" name="owner_objects_text" type="string">
+ <text name="owner_objects_text">
[COUNT]
</text>
<button label="Pokaż" label_selected="Pokaż" name="ShowOwner"/>
<button label="Zwróć..." label_selected="Zwróć..." name="ReturnOwner..." tool_tip="Zwróć obiekty do ich właścicieli."/>
- <text length="1" name="Set to group:" type="string">
+ <text name="Set to group:">
Grupy:
</text>
- <text length="1" name="group_objects_text" type="string">
+ <text name="group_objects_text">
[COUNT]
</text>
<button label="Pokaż" label_selected="Pokaż" name="ShowGroup"/>
<button label="Zwróć..." label_selected="Zwróć..." name="ReturnGroup..." tool_tip="Zwróć obiekty do ich właścicieli.."/>
- <text length="1" name="Owned by others:" type="string">
+ <text name="Owned by others:">
Innych Rezydentów:
</text>
- <text length="1" name="other_objects_text" type="string">
+ <text name="other_objects_text">
[COUNT]
</text>
<button label="Pokaż" label_selected="Pokaż" name="ShowOther"/>
<button label="Zwróć..." label_selected="Zwróć..." name="ReturnOther..." tool_tip="Zwróć obiekty do ich właścicieli."/>
- <text length="1" name="Selected / sat upon:" type="string">
+ <text name="Selected / sat upon:">
Wybranych:
</text>
- <text length="1" name="selected_objects_text" type="string">
+ <text name="selected_objects_text">
[COUNT]
</text>
- <text length="1" name="Autoreturn" type="string">
+ <text name="Autoreturn">
Zwracaj obiekty innych Rezydentów (minut, 0 = wyłącz):
</text>
- <text length="1" name="Object Owners:" type="string" width="108">
+ <text name="Object Owners:" width="108">
Właściciel Obiektów:
</text>
<button label="Odśwież Listę" label_selected="Odśwież Listę" left="112" name="Refresh List"/>
@@ -264,183 +264,155 @@ Idź do Świat &gt; O Posiadłości albo wybierz inną posiadłość żeby pokaz
</name_list>
</panel>
<panel label="Opcje" name="land_options_panel">
- <text length="1" name="allow_label" type="string">
+ <text name="allow_label">
Udostępnij innym Rezydentom:
</text>
<check_box label="Edytowanie Terenu" name="edit land check" tool_tip="Wybrana - każdy może kształtować Twój teren. Najlepiej jest zostawić tą opcję nie wybraną, Ty zawsze możesz kształtowć Twój teren."/>
<check_box label="Zapisywania Miejsca" name="check landmark"/>
<check_box label="Latanie" name="check fly" tool_tip="Wybrana - Rezydenci mogą latać na Twojej posiadłości. Nie wybrana - mogą tylko wlatywać do lub latać ponad Twoją posiadłością."/>
- <text length="1" name="allow_label2" type="string">
+ <text name="allow_label2">
Budowanie:
</text>
<check_box label="Wszyscy" name="edit objects check"/>
<check_box label="Grupa" name="edit group objects check"/>
- <text length="1" name="allow_label3" type="string">
+ <text name="allow_label3">
Nowe Obiekty:
</text>
<check_box label="Wszyscy" name="all object entry check"/>
<check_box label="Grupa" name="group object entry check"/>
- <text length="1" name="allow_label4" type="string">
+ <text name="allow_label4">
Skrypty:
</text>
<check_box label="Wszyscy" name="check other scripts"/>
<check_box label="Grupa" name="check group scripts"/>
- <text length="1" name="land_options_label" type="string">
+ <text name="land_options_label">
Opcje Posiadłości:
</text>
<check_box label="Bezpieczna (brak zniszczeń)" name="check safe" tool_tip="Wybrana - posiadłość jest bezpieczna - zniszczenia w walce są zablokowane. Nie wybrana - zniszczenia w walce są włączone."/>
<check_box label="Popychanie niedozwolone" name="PushRestrictCheck" tool_tip="Nie pozwalaj skryptom na popychanie. Wybranie tej opcji może być przydatne do ograniczenia zakłóceń spokoju w Twojej posiadłości."/>
<check_box label="Wyświetlaj w wyszukiwarce (30L$/tyg.)" name="ShowDirectoryCheck" tool_tip="Udostępnij ukazywanie się nazwy posiadłości w wyszukiwarce"/>
- <string name="search_enabled_tooltip">
+ <panel.string name="search_enabled_tooltip">
Udostępnij wyświetlanie tej posiadłości w wyszukiwarce
- </string>
- <string name="search_disabled_small_tooltip">
+ </panel.string>
+ <panel.string name="search_disabled_small_tooltip">
Wybrana opcja jest wyłączona ze względu iż wielkość posiadłości wynosi 128 m² bądź mniej.
Jedynie większe posiadłości mogą być umieszczone w bazie wyszukiwarki.
- </string>
- <string name="search_disabled_permissions_tooltip">
+ </panel.string>
+ <panel.string name="search_disabled_permissions_tooltip">
Wybrana opcja jest wyłączona ponieważ nie posiadasz prawa do modyfikacji posiadłości.
- </string>
+ </panel.string>
<combo_box name="land category with adult">
- <combo_item name="AnyCategory">
- Każda Kategoria
- </combo_item>
- <combo_item name="LindenLocation">
- Linden Lokacja
- </combo_item>
- <combo_item name="Adult">
- &apos;Adult&apos;
- </combo_item>
- <combo_item name="Arts&amp;Culture">
- Sztuka i Kultura
- </combo_item>
- <combo_item name="Business">
- Biznes
- </combo_item>
- <combo_item name="Educational">
- Edukacja
- </combo_item>
- <combo_item name="Gaming">
- Gra
- </combo_item>
- <combo_item name="Hangout">
- Poznawanie ludzi
- </combo_item>
- <combo_item name="NewcomerFriendly">
- Przyjazne dla nowych
- </combo_item>
- <combo_item name="Parks&amp;Nature">
- Park i Natura
- </combo_item>
- <combo_item name="Residential">
- Mieszkalna
- </combo_item>
- <combo_item name="Shopping">
- Zakupy
- </combo_item>
- <combo_item name="Other">
- Inne
- </combo_item>
+ <combo_box.item name="item0" label="Każda Kategoria"
+ />
+ <combo_box.item name="item1" label="Linden Lokacja"
+ />
+ <combo_box.item name="item2" label="&apos;Adult&apos;"
+ />
+ <combo_box.item name="item3" label="Sztuka i Kultura"
+ />
+ <combo_box.item name="item4" label="Biznes"
+ />
+ <combo_box.item name="item5" label="Edukacyjna"
+ />
+ <combo_box.item name="item6" label="Gra"
+ />
+ <combo_box.item name="item7" label="Poznawanie ludzi"
+ />
+ <combo_box.item name="item8" label="Przyjazne dla nowych"
+ />
+ <combo_box.item name="item9" label="Park i Natura"
+ />
+ <combo_box.item name="item10" label="Mieszkalna"
+ />
+ <combo_box.item name="item11" label="Zakupy"
+ />
+ <combo_box.item name="item12" label="Inna"
+ />
</combo_box>
<combo_box name="land category">
- <combo_item name="AnyCategory">
- Każda
- </combo_item>
- <combo_item name="LindenLocation">
- Linden Lokacja
- </combo_item>
- <combo_item name="Arts&amp;Culture">
- Sztuka i Kultura
- </combo_item>
- <combo_item name="Business">
- Biznes
- </combo_item>
- <combo_item name="Educational">
- Edukacyjna
- </combo_item>
- <combo_item name="Gaming">
- Gra
- </combo_item>
- <combo_item name="Hangout">
- Poznawanie ludzi
- </combo_item>
- <combo_item name="NewcomerFriendly">
- Przyjazna dla nowych
- </combo_item>
- <combo_item name="Parks&amp;Nature">
- Parki i Natura
- </combo_item>
- <combo_item name="Residential">
- Mieszkalna
- </combo_item>
- <combo_item name="Shopping">
- Komercja/Sklepy
- </combo_item>
- <combo_item name="Other">
- Inna
- </combo_item>
+ <combo_box.item name="item0" label="Każda Kategoria"
+ />
+ <combo_box.item name="item1" label="Linden Lokacja"
+ />
+ <combo_box.item name="item3" label="Sztuka i Kultura"
+ />
+ <combo_box.item name="item4" label="Biznes"
+ />
+ <combo_box.item name="item5" label="Edukacyjna"
+ />
+ <combo_box.item name="item6" label="Gra"
+ />
+ <combo_box.item name="item7" label="Poznawanie ludzi"
+ />
+ <combo_box.item name="item8" label="Przyjazna dla nowych"
+ />
+ <combo_box.item name="item9" label="Parki i Natura"
+ />
+ <combo_box.item name="item10" label="Mieszkalna"
+ />
+ <combo_box.item name="item11" label="Zakupy"
+ />
+ <combo_box.item name="item12" label="Inna"
+ />
</combo_box>
<button label="?" label_selected="?" name="?"/>
<check_box label="Treść &apos;Mature&apos;" name="MatureCheck" tool_tip=""/>
- <string name="mature_check_mature">
+ <panel.string name="mature_check_mature">
Treść &apos;Mature&apos;
- </string>
- <string name="mature_check_adult">
+ </panel.string>
+ <panel.string name="mature_check_adult">
Treść &apos;Adult&apos;
- </string>
- <string name="mature_check_mature_tooltip">
+ </panel.string>
+ <panel.string name="mature_check_mature_tooltip">
Twoja posiadłość bądź treść jaką zawiera klasyfikowana jest jako &apos;Mature&apos;.
- </string>
- <string name="mature_check_adult_tooltip">
+ </panel.string>
+ <panel.string name="mature_check_adult_tooltip">
Informacje o Twojej posiadłości i treści jaką zawiera klasyfikowane są jako &apos;Adult&apos;.
- </string>
- <text length="1" name="Snapshot:" type="string">
+ </panel.string>
+ <text name="Snapshot:">
Zdjęcie:
</text>
<texture_picker label="" name="snapshot_ctrl" tool_tip="Kliknij by wybrać zdjęce"/>
- <text length="1" name="landing_point" type="string">
+ <text name="landing_point">
Punkt LÄ…dowania: [LANDING]
</text>
- <string name="landing_point_none">
+ <panel.string name="landing_point_none">
(brak)
- </string>
+ </panel.string>
<button label="Ustaw" label_selected="Ustaw" name="Set" tool_tip="Ustal miejsce lądowania dla przybywających gości. Używa położenia Twojego awatara na tej posiadłości."/>
<button label="Nowy" label_selected="Nowy" name="Clear" tool_tip="Clear the landing point."/>
- <text length="1" name="Teleport Routing: " type="string">
+ <text name="Teleport Routing: ">
Trasa Teleportacji:
</text>
<combo_box name="landing type" tool_tip="Trasa Teleportacj-ustaw w jaki sposób będzie sę odbywać proces telportacji w posiadłości.">
- <combo_item length="1" name="Blocked" type="string">
- Zablokowana
- </combo_item>
- <combo_item length="1" name="LandingPoint" type="string">
- Punkt LÄ…dowania
- </combo_item>
- <combo_item length="1" name="Anywhere" type="string">
- Gdziekolwiek
- </combo_item>
+ <combo_box.item name="Blocked" label="Zablokowana"
+ />
+ <combo_box.item name="LandingPoint" label="Punkt LÄ…dowania"
+ />
+ <combo_box.item name="Anywhere" label="Gdziekolwiek"
+ />
</combo_box>
- <string name="push_restrict_text">
+ <panel.string name="push_restrict_text">
Popychanie niedozwolone
- </string>
- <string name="push_restrict_region_text">
+ </panel.string>
+ <panel.string name="push_restrict_region_text">
Popychanie niedozwolone (Ustawienie Regionu)
- </string>
+ </panel.string>
</panel>
<panel label="Media" name="land_media_panel">
- <text length="1" name="with media:" type="string">
+ <text name="with media:">
Typ Mediów:
</text>
<combo_box name="media type" tool_tip=""/>
- <text length="1" name="at URL:" type="string">
+ <text name="at URL:">
URL Mediów:
</text>
<button label="Ustaw..." label_selected="Ustaw..." name="set_media_url"/>
- <text length="1" name="Description:" type="string">
+ <text name="Description:">
Opis:
</text>
<line_editor name="url_description" tool_tip="Text displayed next to play/load button"/>
- <text length="1" name="Media texture:" type="string">
+ <text name="Media texture:">
Zmień
TeksturÄ™:
</text>
@@ -450,7 +422,7 @@ TeksturÄ™:
film lub stronę internetową po naciśnięciu
przycisku odtwarzania.)
</text>
- <text length="1" name="Options:" type="string">
+ <text name="Options:">
Opcje
Mediów:
</text>
@@ -458,23 +430,23 @@ Mediów:
<check_box label="Powtórka Odtwarzania" name="media_loop" tool_tip="Odtwarzaj media z powtórką. Po wyświetleniu materialu, rozpocznie się odtwarzanie od początku."/>
<check_box label="Ukryj URL Mediów" name="hide_media_url" tool_tip="Wybranie tej opcji, zablokuje widok adresu do medów wszystkim nieautoryzowanym użytkownikom. Nie dotyczy to jednak typów HTML."/>
<check_box label="Ukryj URL Muzyki" name="hide_music_url" tool_tip="Wybranie tej opcji, zablokuje widok adresu do medów muzycznych w posiadłości wszystkim nieautoryzowanym użytkownikom"/>
- <text length="1" name="media_size" tool_tip="Rozmiar dla ładowania mediów internetowych. Zostaw 0 dla ustawień domyślnych." type="string">
+ <text name="media_size" tool_tip="Rozmiar dla ładowania mediów internetowych. Zostaw 0 dla ustawień domyślnych.">
Rozmiar:
</text>
<spinner name="media_size_width" tool_tip="Rozmiar dla ładowania mediów internetowych. Zostaw 0 dla ustawień domyślnych."/>
<spinner name="media_size_height" tool_tip="Rozmiar dla ładowania mediów internetowych. Zostaw 0 dla ustawień domyślnych."/>
- <text length="1" name="pixels" type="string">
+ <text name="pixels">
pixeli
</text>
- <text length="1" name="MusicURL:" type="string">
+ <text name="MusicURL:">
URL Muzyki:
</text>
- <text length="1" name="Sound:" type="string">
+ <text name="Sound:">
Dźwięk:
</text>
<check_box label="Restrykcja obiektów oraz gestur dozwolonych w tej posiadłości" name="check sound local"/>
<button label="?" label_selected="?" name="?" left="432"/>
- <text length="1" name="Voice settings:" type="string">
+ <text name="Voice settings:">
GÅ‚os:
</text>
<check_box label="Rozmowy Dozwolone" name="parcel_enable_voice_channel"/>
@@ -482,27 +454,25 @@ Mediów:
<check_box label="Ogranicz komunikację głosową w tej posiadłości." name="parcel_enable_voice_channel_parcel"/>
</panel>
<panel label="Dostęp" name="land_access_panel">
- <text length="1" name="Limit access to this parcel to:" type="string">
+ <text name="Limit access to this parcel to:">
Dostęp do tej posiadłości:
</text>
<check_box label="Publiczny" name="public_access"/>
- <text length="1" name="Only Allow" type="string">
+ <text name="Only Allow">
Zablokuj dostęp dla:
</text>
<check_box label="Rezydentów niezarejestrowanych w systemie płatniczym z Linden Lab" name="limit_payment" tool_tip="Ban unidentified residents."/>
<check_box label="Rezydentów z brakiem weryfikacji wieku " name="limit_age_verified" tool_tip="Zbanuj Rezydetów bez weryfikacji wieku. Odwiedź support.secondlife.com po więcej informacji."/>
- <string name="estate_override">
+ <panel.string name="estate_override">
Jedna lub więcej z tych opcji ustawiona jest z poziomu posiadłości
- </string>
+ </panel.string>
<check_box label="Udostępnij wejście grupie: [GROUP]" name="GroupCheck" tool_tip="Ustaw grupę w głównej zakładce"/>
<check_box label="Sprzedaj wejściówki:" name="PassCheck" tool_tip="Otwórz tymczasowy dostęp do tej posiadłości"/>
<combo_box name="pass_combo">
- <combo_item name="Anyone">
- Każdemu
- </combo_item>
- <combo_item name="Group">
- Grupie
- </combo_item>
+ <combo_box.item name="Anyone" label="Każdemu"
+ />
+ <combo_box.item name="Group" label="Grupie"
+ />
</combo_box>
<spinner label="Cena w L$:" name="PriceSpin"/>
<spinner label="Ilość godzin dostępu:" name="HoursSpin"/>
diff --git a/indra/newview/skins/default/xui/pl/floater_auction.xml b/indra/newview/skins/default/xui/pl/floater_auction.xml
index 65a1bb85ea..37e35ed1e9 100755
--- a/indra/newview/skins/default/xui/pl/floater_auction.xml
+++ b/indra/newview/skins/default/xui/pl/floater_auction.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_auction" title="Rozpocznij Sprzedaż Posiadłości">
+<floater name="floater_auction" title="ROZPOCZNIJ SPRZEDAÅ» POSIADÅOÅšCI">
<check_box label="Zawierając żółte ogrodzenie" name="fence_check" />
<button label="Zdjęce" label_selected="Zdjęce" name="snapshot_btn" />
<button label="OK" label_selected="OK" name="ok_btn" />
diff --git a/indra/newview/skins/default/xui/pl/floater_avatar_picker.xml b/indra/newview/skins/default/xui/pl/floater_avatar_picker.xml
index cf4dcb91bf..8c09f7294c 100755
--- a/indra/newview/skins/default/xui/pl/floater_avatar_picker.xml
+++ b/indra/newview/skins/default/xui/pl/floater_avatar_picker.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="avatarpicker" title="Wybierz Rezydenta">
+<floater name="avatarpicker" title="WYBIERZ REZYDENTA">
<tab_container name="ResidentChooserTabs">
<panel label="Znajdź" name="SearchPanel">
<text name="InstructSearchResidentName">
diff --git a/indra/newview/skins/default/xui/pl/floater_avatar_textures.xml b/indra/newview/skins/default/xui/pl/floater_avatar_textures.xml
index b27c90b8f2..dce2330807 100755
--- a/indra/newview/skins/default/xui/pl/floater_avatar_textures.xml
+++ b/indra/newview/skins/default/xui/pl/floater_avatar_textures.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="avatar_texture_debug" title="Tekstury Awatara">
+<floater name="avatar_texture_debug" title="TEKSTURY AWATARA">
<text name="baked_label">
Tekstury Renderowane
</text>
diff --git a/indra/newview/skins/default/xui/pl/floater_beacons.xml b/indra/newview/skins/default/xui/pl/floater_beacons.xml
index fd12d13595..6e7013f2d7 100644
--- a/indra/newview/skins/default/xui/pl/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/pl/floater_beacons.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="beacons" title="Emitery">
+<floater name="beacons" title="EMITERY">
<panel name="beacons_panel">
<check_box label="Obiekty Dotykalne" name="touch_only"/>
<check_box label="Obiekty Skryptowane" name="scripted"/>
diff --git a/indra/newview/skins/default/xui/pl/floater_build_options.xml b/indra/newview/skins/default/xui/pl/floater_build_options.xml
index 7cbc410614..f538be218c 100755
--- a/indra/newview/skins/default/xui/pl/floater_build_options.xml
+++ b/indra/newview/skins/default/xui/pl/floater_build_options.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="build options floater" title="Opcje Siatki">
+<floater name="build options floater" title="OPCJE SIATKI">
<spinner label="Jednostka Siatki (metry)" name="GridResolution" />
<spinner label="Rozmiary Siatki (metry)" name="GridDrawSize" />
<check_box label="Udostępnij Podjednostkowe Dopasowywanie" name="GridSubUnit" />
diff --git a/indra/newview/skins/default/xui/pl/floater_bulk_perms.xml b/indra/newview/skins/default/xui/pl/floater_bulk_perms.xml
index a99acdb238..f06615642e 100644
--- a/indra/newview/skins/default/xui/pl/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/pl/floater_bulk_perms.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterbulkperms" title="Hurtowa zmiana praw zawartości">
+<floater name="floaterbulkperms" title="HURTOWA ZMIANA PRAW ZAWARTOÅšCI">
<text name="applyto">
Rodzaj Zawartości
</text>
diff --git a/indra/newview/skins/default/xui/pl/floater_bumps.xml b/indra/newview/skins/default/xui/pl/floater_bumps.xml
index 365268dbd6..10f9d73284 100755
--- a/indra/newview/skins/default/xui/pl/floater_bumps.xml
+++ b/indra/newview/skins/default/xui/pl/floater_bumps.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_bumps" title="Zderzenia, Popchnięcia, Uderzenia">
+<floater name="floater_bumps" title="ZDERZENIA, POPCHNIĘCIA, UDERZENIA">
<string name="none_detected">
Brak
</string>
diff --git a/indra/newview/skins/default/xui/pl/floater_buy_contents.xml b/indra/newview/skins/default/xui/pl/floater_buy_contents.xml
index 395bcb4ea9..ebe1c9dfd8 100755
--- a/indra/newview/skins/default/xui/pl/floater_buy_contents.xml
+++ b/indra/newview/skins/default/xui/pl/floater_buy_contents.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_buy_contents" title="Kup Zawartość">
+<floater name="floater_buy_contents" title="KUP ZAWARTOŚĆ">
<text name="contains_text">
[NAME] zawiera:
</text>
diff --git a/indra/newview/skins/default/xui/pl/floater_buy_currency.xml b/indra/newview/skins/default/xui/pl/floater_buy_currency.xml
index a5c0a2498a..5e59482883 100755
--- a/indra/newview/skins/default/xui/pl/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/pl/floater_buy_currency.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="buy currency" title="Kup $L">
+<floater name="buy currency" title="KUP $L">
<text name="info_buying">
Kup L$:
</text>
@@ -29,7 +29,7 @@
1234
</line_editor>
<text name="currency_est">
- L$ za [USD]US$
+ za [LOCALAMOUNT]
</text>
<text name="getting_data">
Otrzymywanie danych...
@@ -64,6 +64,6 @@ Proszę zwiększyć ilość.
<button label="Anuluj" name="cancel_btn" />
<button label="Kup" name="buy_btn" />
<string name="buy_currency">
- Kup [LINDENS]L$ za [USD]US$
+ Kup [LINDENS]L$ za [LOCALAMOUNT]
</string>
</floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_buy_land.xml b/indra/newview/skins/default/xui/pl/floater_buy_land.xml
index 1103606569..648888828b 100755
--- a/indra/newview/skins/default/xui/pl/floater_buy_land.xml
+++ b/indra/newview/skins/default/xui/pl/floater_buy_land.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="buy land" title="Buy Land">
+<floater name="buy land" title="BUY LAND">
<text name="region_name_label">
Region:
</text>
@@ -74,15 +74,9 @@ sprzedaż z obiektami
Tylko członkowie z kontem Premium mogą mieć Posiadłosci.
</text>
<combo_box name="account_level">
- <combo_item name="US$9.95/month,billedmonthly">
- 9.95US$/miesiąc, płatne miesięcznie
- </combo_item>
- <combo_item name="US$7.50/month,billedquarterly">
- 7.50US$/miesiąc, płatne kwartalnie
- </combo_item>
- <combo_item name="US$6.00/month,billedannually">
- 6.00US$/miesiąc, płatne rocznie
- </combo_item>
+ <combo_box.item name="US$9.95/month,billedmonthly" label="9.95US$/miesiąc, płatne miesięcznie" />
+ <combo_box.item name="US$7.50/month,billedquarterly" label="7.50US$/miesiąc, płatne kwartalnie" />
+ <combo_box.item name="US$6.00/month,billedannually" label="6.00US$/miesiąc, płatne rocznie" />
</combo_box>
<text name="land_use_action">
Zwiększ opłatę za używanie Posiadłości do 40US$/miesiąc.
diff --git a/indra/newview/skins/default/xui/pl/floater_buy_object.xml b/indra/newview/skins/default/xui/pl/floater_buy_object.xml
index b0868a46a2..bad7982228 100755
--- a/indra/newview/skins/default/xui/pl/floater_buy_object.xml
+++ b/indra/newview/skins/default/xui/pl/floater_buy_object.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="contents" title="Kup kopiÄ™ obiektu">
+<floater name="contents" title="KUP KOPIĘ OBIEKTU">
<text name="contents_text">
i jej zawartość:
</text>
diff --git a/indra/newview/skins/default/xui/pl/floater_camera.xml b/indra/newview/skins/default/xui/pl/floater_camera.xml
index 24da91c081..5957018144 100755
--- a/indra/newview/skins/default/xui/pl/floater_camera.xml
+++ b/indra/newview/skins/default/xui/pl/floater_camera.xml
@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="move floater" title="">
- <string name="rotate_tooltip">
+<floater name="camera_floater" title="">
+ <floater.string name="rotate_tooltip">
Obracaj kamerę wokół obiektu
- </string>
- <string name="zoom_tooltip">
+ </floater.string>
+ <floater.string name="zoom_tooltip">
Najedź kamerą w kierunku obiektu
- </string>
- <string name="move_tooltip">
+ </floater.string>
+ <floater.string name="move_tooltip">
Poruszaj kamerą w dół/górę oraz w prawo/lewo
- </string>
+ </floater.string>
+ <panel name="controls">
+ <joystick_track name="cam_track_stick" tool_tip="Poruszaj kamerą w dół/górę oraz w prawo/lewo"/>
+ <joystick_zoom name="zoom" tool_tip="Najedź kamerą w kierunku obiektu"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_choose_group.xml b/indra/newview/skins/default/xui/pl/floater_choose_group.xml
index 789c40e48c..72b6617094 100755
--- a/indra/newview/skins/default/xui/pl/floater_choose_group.xml
+++ b/indra/newview/skins/default/xui/pl/floater_choose_group.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="groups" title="Grupy">
+<floater name="groups" title="GRUPY">
<text name="groupdesc">
Wybierz grupÄ™:
</text>
diff --git a/indra/newview/skins/default/xui/pl/floater_color_picker.xml b/indra/newview/skins/default/xui/pl/floater_color_picker.xml
index a380423cdf..904a2cc270 100755
--- a/indra/newview/skins/default/xui/pl/floater_color_picker.xml
+++ b/indra/newview/skins/default/xui/pl/floater_color_picker.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="ColorPicker" title="Wybór Koloru">
+<floater name="ColorPicker" title="WYBÓR KOLORU">
<text name="r_val_text">
Czerwony:
</text>
@@ -26,6 +26,6 @@
Obecny Kolor:
</text>
<text name="(Drag below to save.)">
- (PrzeciÄ…gnij tutaj.)
+ (PrzeciÄ…gnij tutaj)
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_customize.xml b/indra/newview/skins/default/xui/pl/floater_customize.xml
index 83c7c5c87d..0c01d15faf 100755
--- a/indra/newview/skins/default/xui/pl/floater_customize.xml
+++ b/indra/newview/skins/default/xui/pl/floater_customize.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater customize" title="WyglÄ…d">
+<floater name="floater customize" title="WYGLÄ„D">
<tab_container name="customize tab container">
- <panel label="Części Ciała" name="body_parts_placeholder"/>
+ <placeholder label="Części Ciała" name="body_parts_placeholder"/>
<panel label="Kształt" name="Shape">
<button label="Wróć" label_selected="Wróć" name="Revert"/>
<button label="Ciało" label_selected="Ciało" name="Body"/>
@@ -14,34 +14,30 @@
<button label="Tułów" label_selected="Tułów" name="Torso"/>
<button label="Nogi" label_selected="Nogi" name="Legs"/>
<radio_group name="sex radio">
- <radio_item length="1" name="radio" type="string">
- Kobieta
- </radio_item>
- <radio_item length="1" name="radio2" type="string">
- Mężczyzna
- </radio_item>
+ <radio_item name="radio" label="Kobieta"/>
+ <radio_item name="radio2" label="Mężczyzna"/>
</radio_group>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: zabroniona modyfikacja
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: Å‚adowanie...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: niezałożone
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Zapisane w [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Załóż nowy kształt poprzez przeciągnięcie go ze swojej szafy
na awatara. Alternatywnie, możesz także stworzyć własny kształt
z plików roboczych.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Nie posiadasz prawa do modyfikowania tego kształtu.
</text>
<text name="Item Action Label">
@@ -56,27 +52,27 @@ z plików roboczych.
<button label="Detale Twarzy" label_selected="Detale Twarzy" name="Face Detail"/>
<button label="Makijaż" label_selected="Makijaż" name="Makeup"/>
<button label="Detale Ciała" label_selected="Detale Ciała" name="Body Detail"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: modyfikacja zabroniona
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: Å‚adowanie...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: niezałożone
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Zapisane w [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Załóż nową skórkę poprzez przeciągnięcie jej ze swojej szafy
na awatara. Alternatywnie, możesz także stworzyć własną skórkę
z plików roboczych.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Nie posiadasz prawa do modyfikowania tej skórki.
</text>
<text name="Item Action Label">
@@ -95,27 +91,27 @@ z plików roboczych.
<button label="Styl" label_selected="Styl" name="Style"/>
<button label="Brwi" label_selected="Brwi" name="Eyebrows"/>
<button label="Twarzy" label_selected="Twarzy" name="Facial"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: modyfikacja zabroniona
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: Å‚adowanie...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: niezałożone
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Zapisane w [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Załóż nowe włosy poprzez przeciągnięcie ich ze swojej szafy
na awatara. Alternatywnie, możesz także stworzyć własne włosy
z plików roboczych.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Nie posiadasz prawa do modyfikowania tych włosów.
</text>
<text name="Item Action Label">
@@ -128,27 +124,27 @@ z plików roboczych.
<button label="Wróć" label_selected="Wróć" name="Revert"/>
</panel>
<panel label="Oczy" name="Eyes">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: modyfikacja zabroniona
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: Å‚adowanie...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: niezałożone
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Zapisane w [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Załóż nowe oczy poprzez przeciągnięcie ich ze swojej szafy
na awatara. Alternatywnie, możesz także stworzyć własne oczy
z plików roboczych.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Nie posiadasz prawa do modyfikowania tych oczów.
</text>
<text name="Item Action Label">
@@ -169,27 +165,27 @@ z plików roboczych.
<button label="Zapisz" label_selected="Zapisz" name="Save"/>
<button label="Zapisz Jako..." label_selected="Zapisz Jako..." name="Save As"/>
<button label="Wróć" label_selected="Wróć" name="Revert"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: modyfikowanie zabronione
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: Å‚adowanie...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: niezałożone
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Zapisane w [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Załóż nową koszulę poprzez przeciągnięcie jej ze swojej szafy
na awatara. Alternatywnie, możesz także stworzyć własną koszulę
z plików roboczych.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Nie posiadasz prawa do modyfikowania tej koszuli.
</text>
<text name="Item Action Label">
@@ -204,27 +200,27 @@ z plików roboczych.
<button label="Zapisz" label_selected="Zapisz" name="Save"/>
<button label="Zapisz Jako..." label_selected="Zapisz Jako..." name="Save As"/>
<button label="Wróć" label_selected="Wróć" name="Revert"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: modyfikcja zabroniona
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: Å‚adowanie...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: niezałożone
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Zapisane w [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Załóż nowe spodnie poprzez przeciągnięcie ich ze swojej szafy
na awatara. Alternatywnie, możesz także stworzyć własne spodnie
z plików roboczych.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Nie posiadasz prawa do modyfikowania tych spodni.
</text>
<text name="Item Action Label">
@@ -232,27 +228,27 @@ z plików roboczych.
</text>
</panel>
<panel label="Buty" name="Shoes">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: modyfikacja zabroniona
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: Å‚adwanie...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: niezałożone
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Zapisane w [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Załóż nowe buty poprzez przeciągnięcie ich ze swojej szafy
na awatara. Alternatywnie, możesz także stworzyć własne buty
z plików roboczych.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Nie posiadasz prawa do modyfikowania tych butów.
</text>
<text name="Item Action Label">
@@ -267,27 +263,27 @@ z plików roboczych.
<button label="Wróć" label_selected="Wróć" name="Revert"/>
</panel>
<panel label="Skarpety" name="Socks">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: modyfikacja zabroniona
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: Å‚adowanie...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: niezałożone
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Zapisane w [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Załóż nowe skarpety poprzez przeciągnięcie ich ze swojej szafy
na awatara. Alternatywnie, możesz także stworzyć własne skarpety
z plików roboczych.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Nie posiadasz prawa do modyfikowania tych skarpet.
</text>
<text name="Item Action Label">
@@ -302,27 +298,27 @@ z plików roboczych.
<button label="Wróć" label_selected="Wróć" name="Revert"/>
</panel>
<panel label="Kurtka" name="Jacket">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: modyfikacja zabroniona
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: Å‚adowanie...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: niezałożone
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Zapisane w [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Załóż nową kurtkę poprzez przeciągnięcie jej ze swojej szafy
na awatara. Alternatywnie, możesz także stworzyć własną kurtkę
z plików roboczych.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Nie posiadasz prawa do modyfikowania tej kurtki.
</text>
<text name="Item Action Label">
@@ -338,27 +334,27 @@ z plików roboczych.
<button label="Wróć" label_selected="Wróć" name="Revert"/>
</panel>
<panel label="Rękawiczki" name="Gloves">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: modyfikacja zabroniona
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: Å‚adowanie...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: niezałożone
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Zapisane w [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Załóż nowe rękawiczki poprzez przeciągnięcie ich ze swojej szafy
na awatara. Alternatywnie, możesz także stworzyć własne rękawiczki
z plików roboczych.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Nie posiadasz prawa do modyfikowania tych rękawiczek
</text>
<text name="Item Action Label">
@@ -373,27 +369,27 @@ z plików roboczych.
<button label="Wróć" label_selected="Wróć" name="Revert"/>
</panel>
<panel label="Podkoszulek" name="Undershirt">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: modyfikacja zabroniona
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: Å‚adowanie...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: niezałożone
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Zapisane w [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Załóż nowy podkoszulek poprzez przeciągnięcie ich ze swojej szafy
na awatara. Alternatywnie, możesz także stworzyć własny podkoszulek
z plików roboczych.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Nie posiadasz prawa do modyfikowania tego podkoszulka.
</text>
<text name="Item Action Label">
@@ -408,27 +404,27 @@ z plików roboczych.
<button label="Wróć" label_selected="Wróć" name="Revert"/>
</panel>
<panel label="Bielizna" name="Underpants">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: modyfikacja zabroniona
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: Å‚adowanie...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: niezałożone
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Zapisane w [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Załóż nową bieliznę poprzez przeciągnięcie jej ze swojej szafy
na awatara. Alternatywnie, możesz także stworzyć własną bieliznę
z plików roboczych.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Nie posiadasz prawa do modyfikowania tej bielizny.
</text>
<text name="Item Action Label">
@@ -443,27 +439,27 @@ z plików roboczych.
<button label="Wróć" label_selected="Wróć" name="Revert"/>
</panel>
<panel label="Spódnica" name="Skirt">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: modyfikacja zabroniona
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: Å‚adowanie...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: niezałożone
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Zapisane w [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Załóż nową spódnicę poprzez przeciągnięcie jej ze swojej szafy
na awatara. Alternatywnie, możesz także stworzyć własną spódnicę
z plików roboczych.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Nie posiadasz prawa do modyfikowania tej spódnicy.
</text>
<text name="Item Action Label">
diff --git a/indra/newview/skins/default/xui/pl/floater_day_cycle_options.xml b/indra/newview/skins/default/xui/pl/floater_day_cycle_options.xml
index 6f2dc69d8e..6671bb853e 100755
--- a/indra/newview/skins/default/xui/pl/floater_day_cycle_options.xml
+++ b/indra/newview/skins/default/xui/pl/floater_day_cycle_options.xml
@@ -1,89 +1,89 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Day Cycle Floater" title="Edytor Cyklu Dnia">
+<floater name="Day Cycle Floater" title="EDYTOR CYKLU DNIA">
<tab_container name="Day Cycle Tabs">
<panel label="Cykl Dnia" name="Day Cycle">
<button label="?" name="WLDayCycleHelp" />
<multi_slider label="" name="WLTimeSlider" />
<multi_slider label="" name="WLDayCycleKeys" />
- <text type="string" length="1" name="WL12am">
+ <text name="WL12am">
12am
</text>
- <text type="string" length="1" name="WL3am">
+ <text name="WL3am">
3am
</text>
- <text type="string" length="1" name="WL6am">
+ <text name="WL6am">
6am
</text>
- <text type="string" length="1" name="WL9amHash">
+ <text name="WL9amHash">
9am
</text>
- <text type="string" length="1" name="WL12pmHash">
+ <text name="WL12pmHash">
12pm
</text>
- <text type="string" length="1" name="WL3pm">
+ <text name="WL3pm">
3pm
</text>
- <text type="string" length="1" name="WL6pm">
+ <text name="WL6pm">
6pm
</text>
- <text type="string" length="1" name="WL9pm">
+ <text name="WL9pm">
9pm
</text>
- <text type="string" length="1" name="WL12am2">
+ <text name="WL12am2">
12am
</text>
- <text type="string" length="1" name="WL12amHash">
+ <text name="WL12amHash">
|
</text>
- <text type="string" length="1" name="WL3amHash">
+ <text name="WL3amHash">
I
</text>
- <text type="string" length="1" name="WL6amHash">
+ <text name="WL6amHash">
|
</text>
- <text type="string" length="1" name="WL9amHash2">
+ <text name="WL9amHash2">
I
</text>
- <text type="string" length="1" name="WL12pmHash2">
+ <text name="WL12pmHash2">
|
</text>
- <text type="string" length="1" name="WL3pmHash">
+ <text name="WL3pmHash">
I
</text>
- <text type="string" length="1" name="WL6pmHash">
+ <text name="WL6pmHash">
|
</text>
- <text type="string" length="1" name="WL9pmHash">
+ <text name="WL9pmHash">
I
</text>
- <text type="string" length="1" name="WL12amHash2">
+ <text name="WL12amHash2">
|
</text>
<button label="Dodaj" label_selected="Dodaj" name="WLAddKey" />
<button label="Usuń" label_selected="Usuń" name="WLDeleteKey" />
- <text type="string" length="1" name="WLCurKeyFrameText">
+ <text name="WLCurKeyFrameText">
Preferencje Czasu:
</text>
- <text type="string" length="1" name="WLCurKeyTimeText">
+ <text name="WLCurKeyTimeText">
Czas:
</text>
<spinner label="Godz" name="WLCurKeyHour" />
<spinner label="Min" name="WLCurKeyMin" />
- <text type="string" length="1" name="WLCurKeyTimeText2">
+ <text name="WLCurKeyTimeText2">
Ustawienia:
</text>
<combo_box label="Preset" name="WLKeyPresets" />
- <text type="string" length="1" name="DayCycleText">
+ <text name="DayCycleText">
Przerwij:
</text>
<combo_box label="5 min" name="WLSnapOptions" />
- <text type="string" length="1" name="DayCycleText2">
+ <text name="DayCycleText2">
Długość Cyklu:
</text>
<spinner label="Godz" name="WLLengthOfDayHour" />
<spinner label="Min" name="WLLengthOfDayMin" />
<spinner label="Sek" name="WLLengthOfDaySec" />
- <text type="string" length="1" name="DayCycleText3">
+ <text name="DayCycleText3">
WyglÄ…d:
</text>
<button label="Start" label_selected="Start" name="WLAnimSky" />
diff --git a/indra/newview/skins/default/xui/pl/floater_device_settings.xml b/indra/newview/skins/default/xui/pl/floater_device_settings.xml
index 0122aa819e..e79478731d 100755
--- a/indra/newview/skins/default/xui/pl/floater_device_settings.xml
+++ b/indra/newview/skins/default/xui/pl/floater_device_settings.xml
@@ -1,3 +1,3 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="floater_device_settings"
- title="Ustawienia Urządzeń Komunikacji Głosowej" />
+ title="USTAWIENIA URZÄ„DZEŃ KOMUNIKACJI GÅOSOWEJ" />
diff --git a/indra/newview/skins/default/xui/pl/floater_env_settings.xml b/indra/newview/skins/default/xui/pl/floater_env_settings.xml
index fbb8eca70e..e197d94b27 100755
--- a/indra/newview/skins/default/xui/pl/floater_env_settings.xml
+++ b/indra/newview/skins/default/xui/pl/floater_env_settings.xml
@@ -1,21 +1,21 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Environment Editor Floater" title="Edytor Åšrodowiska">
- <text type="string" length="1" name="EnvTimeText">
+<floater name="Environment Editor Floater" title="EDYTOR ÅšRODOWISKA">
+ <text name="EnvTimeText">
Czas
</text>
- <text type="string" length="1" name="EnvTimeText2">
+ <text name="EnvTimeText2">
12:00 PM
</text>
<slider label="" name="EnvTimeSlider" />
- <text type="string" length="1" name="EnvCloudText">
+ <text name="EnvCloudText">
Chmury:
</text>
<slider label="" name="EnvCloudSlider" />
- <text type="string" length="1" name="EnvWaterColorText">
+ <text name="EnvWaterColorText">
Kolor Wody
</text>
<color_swatch label="" name="EnvWaterColor" tool_tip="Kliknij by wybrać kolor" />
- <text type="string" length="1" name="EnvWaterFogText">
+ <text name="EnvWaterFogText">
Zamglenie:
</text>
<slider label="" name="EnvWaterFogSlider" />
diff --git a/indra/newview/skins/default/xui/pl/floater_font_test.xml b/indra/newview/skins/default/xui/pl/floater_font_test.xml
index 586d2690b3..019cee3e1e 100644
--- a/indra/newview/skins/default/xui/pl/floater_font_test.xml
+++ b/indra/newview/skins/default/xui/pl/floater_font_test.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="contents" title="Czcionka Tekstu">
+<floater name="contents" title="CZCIONKA TEKSTU">
<text name="linea">
OverrideTest, powinno wyświetlać się jako Times. (From default/xui/en-us)
</text>
diff --git a/indra/newview/skins/default/xui/pl/floater_gesture.xml b/indra/newview/skins/default/xui/pl/floater_gesture.xml
index a05408dfc5..4685eb6afe 100755
--- a/indra/newview/skins/default/xui/pl/floater_gesture.xml
+++ b/indra/newview/skins/default/xui/pl/floater_gesture.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="gestures" title="Aktywne Gesty">
+<floater name="gestures" title="AKTYWNE GESTY">
<text name="help_label">
Kliknij podwójnie by aktywować głos i animację gestu.
</text>
diff --git a/indra/newview/skins/default/xui/pl/floater_god_tools.xml b/indra/newview/skins/default/xui/pl/floater_god_tools.xml
index f46cbaa862..a3ccffac03 100755
--- a/indra/newview/skins/default/xui/pl/floater_god_tools.xml
+++ b/indra/newview/skins/default/xui/pl/floater_god_tools.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="godtools floater" title="Boskie Narzędzia">
+<floater name="godtools floater" title="BOSKIE NARZĘDZIA">
<tab_container name="GodTools Tabs">
<panel label="Grid" name="grid">
<button width="205" label="Usuń wszystkich użytkowników" label_selected="Usuń wszystkich użytkowników" name="Kick all users"/>
@@ -42,11 +42,11 @@
<line_editor left_delta="45" name="redirecty" width="35" />
<spinner name="billable factor"/>
<text name="billable factor text">
- Czynnik Płatnośći:
+ Czynnik Płatności:
</text>
<spinner name="land cost"/>
<text name="land cost text">
- L$/m:
+ L$/m²:
</text>
<button label="Odśwież" label_selected="Odśwież" name="Refresh" />
<button label="Zastosuj" label_selected="Zastosuj" name="Apply" />
@@ -68,8 +68,8 @@
<text name="target_avatar_name">
(brak)
</text>
- <button label="Usuń cel &apos;s skryptowane obiekty na innych posiadłościach" label_selected="Usuń cel &apos;s skryptowane obiekty na innych posiadłościach" name="Delete Target&apos;s Scripted Objects On Others Land" />
- <button label="Usuń cel &apos;s skryptowane obiekty na jakichkolwiek posiadłościach" label_selected="Usuń cel &apos;s skryptowane obiekty na jakichkolwiek posiadłościach" name="Delete Target&apos;s Scripted Objects On *Any* Land" />
+ <button label="Usuń cel z oskryptowanych obiektów na innych posiadłościach" label_selected="Usuń cel &apos;s skryptowane obiekty na innych posiadłościach" name="Delete Target&apos;s Scripted Objects On Others Land" />
+ <button label="Usuń cel z oskryptowanych obiektów na jakichkolwiek posiadłościach" label_selected="Usuń cel &apos;s skryptowane obiekty na jakichkolwiek posiadłościach" name="Delete Target&apos;s Scripted Objects On *Any* Land" />
<button label="Usuń wszystkie cele i obiekty" label_selected="Usuń wszystkie cele i obiekty" name="Delete *ALL* Of Target&apos;s Objects" />
<button label="Główne Kolizje" label_selected="Główne Kolizje" name="Get Top Colliders" />
<button label="Główne Skrypty" label_selected="Główne Skrypty" name="Get Top Scripts" />
@@ -80,29 +80,17 @@
Cel:
</text>
<combo_box name="destination">
- <combo_item name="Selection">
- Selekcja
- </combo_item>
- <combo_item name="AgentRegion">
- Agent Regionu
- </combo_item>
+ <combo_box.item name="item1" label="Selekcja" />
+ <combo_box.item name="item2" label="Agent Regionu" />
</combo_box>
<text name="Request:">
Żądanie:
</text>
<combo_box name="request">
- <combo_item name="colliders&lt;steps&gt;">
- kolidery &lt;kroki&gt;
- </combo_item>
- <combo_item name="scripts&lt;count&gt;,&lt;optionalpattern&gt;">
- skrypty &lt;policz&gt;,&lt;opcjonalnie powtórzenie&gt;
- </combo_item>
- <combo_item name="objects&lt;pattern&gt;">
- obiekty &lt;powtórzenia&gt;
- </combo_item>
- <combo_item name="rez&lt;asset_id&gt;">
- rez &lt;asset_id&gt;
- </combo_item>
+ <combo_box.item name="item1" label="kolidery &lt;kroki&gt;" />
+ <combo_box.item name="item2" label="skrypty &lt;policz&gt;,&lt;opcjonalnie powtórzenie&gt;" />
+ <combo_box.item name="item3" label="obiekty &lt;powtórzenia&gt;" />
+ <combo_box.item name="item4" label="rez &lt;asset_id&gt;" />
</combo_box>
<text name="Parameter:">
Parameter:
diff --git a/indra/newview/skins/default/xui/pl/floater_hardware_settings.xml b/indra/newview/skins/default/xui/pl/floater_hardware_settings.xml
index 010537d555..39695a67b6 100755
--- a/indra/newview/skins/default/xui/pl/floater_hardware_settings.xml
+++ b/indra/newview/skins/default/xui/pl/floater_hardware_settings.xml
@@ -1,34 +1,24 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Hardware Settings Floater" title="Ustawienia Sprzętowe">
- <text type="string" length="1" name="Filtering:">
+<floater name="Hardware Settings Floater" title="USTAWIENIA SPRZĘTOWE">
+ <text name="Filtering:">
Filtrowanie:
</text>
<check_box label="Filtrowanie Anizotropowe" name="ani" />
- <text type="string" length="1" name="Antialiasing:">
+ <text name="Antialiasing:">
Antialiasing:
</text>
<combo_box label="Antialiasing" name="fsaa" width="84">
- <combo_item name="FSAADisabled">
- Wyłączone
- </combo_item>
- <combo_item name="2x">
- 2x
- </combo_item>
- <combo_item name="4x">
- 4x
- </combo_item>
- <combo_item name="8x">
- 8x
- </combo_item>
- <combo_item name="16x">
- 16x
- </combo_item>
+ <combo_box.item name="FSAADisabled" label="Wyłączone" />
+ <combo_box.item name="2x" label="2x" />
+ <combo_box.item name="4x" label="4x" />
+ <combo_box.item name="8x" label="8x" />
+ <combo_box.item name="16x" label="16x" />
</combo_box>
<spinner label="Gamma:" name="gamma" />
- <text type="string" length="1" name="(brightness, lower is brighter)">
+ <text name="(brightness, lower is brighter)">
(jaskrawość, mniej jest jaśniej, 0=domyślny)
</text>
- <text type="string" length="1" name="Enable VBO:">
+ <text name="Enable VBO:">
WÅ‚Ä…cz VBO:
</text>
<check_box label="Włącz Bufor Vertexów OpenGL" name="vbo" tool_tip="" />
diff --git a/indra/newview/skins/default/xui/pl/floater_hud.xml b/indra/newview/skins/default/xui/pl/floater_hud.xml
index 916473f063..ff2d702132 100755
--- a/indra/newview/skins/default/xui/pl/floater_hud.xml
+++ b/indra/newview/skins/default/xui/pl/floater_hud.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_hud" title="Samouczek" />
+<floater name="floater_hud" title="SAMOUCZEK" />
diff --git a/indra/newview/skins/default/xui/pl/floater_image_preview.xml b/indra/newview/skins/default/xui/pl/floater_image_preview.xml
index 9772dc7808..27f898a66b 100755
--- a/indra/newview/skins/default/xui/pl/floater_image_preview.xml
+++ b/indra/newview/skins/default/xui/pl/floater_image_preview.xml
@@ -10,36 +10,16 @@
Wyświetl obraz jako:
</text>
<combo_box label="Rodzaj Ubrania" name="clothing_type_combo">
- <combo_item name="Image">
- Obraz
- </combo_item>
- <combo_item name="Hair">
- WÅ‚osy
- </combo_item>
- <combo_item name="FemaleHead">
- Damska GÅ‚owa
- </combo_item>
- <combo_item name="FemaleUpperBody">
- Damska Górna Część Ciała
- </combo_item>
- <combo_item name="FemaleLowerBody">
- Damska Górna Część Ciała
- </combo_item>
- <combo_item name="MaleHead">
- Męska Głowa
- </combo_item>
- <combo_item name="MaleUpperBody">
- Męska Górna Część Ciała
- </combo_item>
- <combo_item name="MaleLowerBody">
- Męska Dolna Część Ciała
- </combo_item>
- <combo_item name="Skirt">
- Spódnica
- </combo_item>
- <combo_item name="SculptedPrim">
- Sculpt
- </combo_item>
+ <combo_box.item name="Image" label="Obraz" />
+ <combo_box.item name="Hair" label="WÅ‚osy" />
+ <combo_box.item name="FemaleHead" label="Damska GÅ‚owa" />
+ <combo_box.item name="FemaleUpperBody" label="Damska Górna Część Ciała" />
+ <combo_box.item name="FemaleLowerBody" label="Damska Górna Część Ciała" />
+ <combo_box.item name="MaleHead" label="Męska Głowa" />
+ <combo_box.item name="MaleUpperBody" label="Męska Górna Część Ciała" />
+ <combo_box.item name="MaleLowerBody" label="Męska Dolna Część Ciała" />
+ <combo_box.item name="Skirt" label="Spódnica" />
+ <combo_box.item name="SculptedPrim" label="Sculpt" />
</combo_box>
<text name="bad_image_text">
Nie można wczytać obrazu.
diff --git a/indra/newview/skins/default/xui/pl/floater_inspect.xml b/indra/newview/skins/default/xui/pl/floater_inspect.xml
index 1efdced527..c98e0541d8 100755
--- a/indra/newview/skins/default/xui/pl/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/pl/floater_inspect.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="inspect" title="Inspekcja Obiektów">
+<floater name="inspect" title="INSPEKCJA OBIEKTÓW">
<scroll_list name="object_list" tool_tip="">
<column label="Nazwa" name="object_name" />
<column label="Właściciel" name="owner_name" />
diff --git a/indra/newview/skins/default/xui/pl/floater_inventory.xml b/indra/newview/skins/default/xui/pl/floater_inventory.xml
index 6df978de69..157be76c4d 100755
--- a/indra/newview/skins/default/xui/pl/floater_inventory.xml
+++ b/indra/newview/skins/default/xui/pl/floater_inventory.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Inventory" title="Moja Szafa">
+<floater name="Inventory" title="MOJA SZAFA">
<search_editor label="Wyszukiwarka" name="inventory search editor"/>
<tab_container name="inventory filter tabs">
<inventory_panel label="Wszystkie Obiekty" name="All Items"/>
diff --git a/indra/newview/skins/default/xui/pl/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/pl/floater_inventory_item_properties.xml
index f754610ee3..665172dd49 100755
--- a/indra/newview/skins/default/xui/pl/floater_inventory_item_properties.xml
+++ b/indra/newview/skins/default/xui/pl/floater_inventory_item_properties.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="item properties" title="Właściwości Obiektów w Szafie">
+<floater name="item properties" title="WÅAÅšCIWOÅšCI OBIEKTÓW W SZAFIE">
<text name="LabelItemNameTitle">
Nazwa:
</text>
@@ -60,12 +60,8 @@
</text>
<check_box label="Sprzedaż" name="CheckPurchase" />
<radio_group name="RadioSaleType">
- <radio_item name="radio">
- Oryginał
- </radio_item>
- <radio_item name="radio2">
- Kopia
- </radio_item>
+ <radio_item name="radio" label="Oryginał" />
+ <radio_item name="radio2" label="Kopia" />
</radio_group>
<text name="TextPrice">
Cena: L$
diff --git a/indra/newview/skins/default/xui/pl/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/pl/floater_inventory_view_finder.xml
index fb4e30d2a3..9204262304 100755
--- a/indra/newview/skins/default/xui/pl/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/pl/floater_inventory_view_finder.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Inventory Finder" title="Nowe Obiekty">
+<floater name="Inventory Finder" title="NOWE OBIEKTY">
<check_box label="Animacje" name="check_animation" />
<check_box label="Wizytówki" name="check_calling_card" />
<check_box label="Ubrania" name="check_clothing" />
@@ -15,7 +15,7 @@
<button label="Żadne" label_selected="Żadne" name="None" />
<check_box label="Zawsze pokazuj foldery" name="check_show_empty" />
<check_box label="Od czasu wylogowania" name="check_since_logoff" />
- <text type="string" length="1" name="- OR -">
+ <text name="- OR -">
- LUB -
</text>
<spinner label="Od godzin" name="spin_hours_ago" />
diff --git a/indra/newview/skins/default/xui/pl/floater_joystick.xml b/indra/newview/skins/default/xui/pl/floater_joystick.xml
index 8ce113514b..22ac458b85 100755
--- a/indra/newview/skins/default/xui/pl/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/pl/floater_joystick.xml
@@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Joystick" width="590" title="Konfiguracja Joysticka">
- <check_box name="enable_joystick">
- Aktywuj Joystick:
- </check_box>
+<floater name="Joystick" width="590" title="KONFIGURACJA JOYSTICKA">
+ <check_box name="enable_joystick" label="Aktywuj Joystick:"/>
+ <text left="130" name="joystick_type" width="360"/>
<spinner label="Kalibracja Osi X" left="20" width="170" label_width="130" name="JoystickAxis1"/>
<spinner label="Kalibracja Osi Y" left="210" width="170" label_width="130" name="JoystickAxis2" />
<spinner label="Kalibracja Osi Z" left="400" width="170" label_width="130" name="JoystickAxis0" />
@@ -13,112 +12,108 @@
<check_box label="Bezpośrednie" left="205" name="ZoomDirect" />
<check_box label="Kursor 3D" left="340" name="Cursor3D" />
<check_box label="Automatyczne" left="450" name="AutoLeveling" />
- <text length="1" left="42" name="Control Modes:" type="string">
+ <text left="22" name="Control Modes:">
Kontroluj:
</text>
- <check_box left="150" width="90" name="JoystickAvatarEnabled">
- Awatara
- </check_box>
- <check_box left="249" width="90" name="JoystickBuildEnabled">
- Budowanie
- </check_box>
- <check_box left="340" width="90" name="JoystickFlycamEnabled">
- KamerÄ™ podczas latania
- </check_box>
- <text width="124" name="XScale">
+ <check_box left="130" width="90" name="JoystickAvatarEnabled" label="Awatara"/>
+ <check_box left="205" width="90" name="JoystickBuildEnabled" label="Budowanie"/>
+ <check_box left="282" width="90" name="JoystickFlycamEnabled" label="KamerÄ™ podczas latania"/>
+ <text width="104" name="XScale">
Skala X
</text>
- <spinner left="153" name="AvatarAxisScale1" />
- <spinner left="218" name="BuildAxisScale1" />
+ <spinner left="133" name="AvatarAxisScale1" />
+ <spinner left="208" name="BuildAxisScale1" />
<spinner left="283" name="FlycamAxisScale1" />
- <text width="124" name="YScale">
+ <text width="104" name="YScale">
Skala Y
</text>
- <spinner left="153" name="AvatarAxisScale2" />
- <spinner left="218" name="BuildAxisScale2" />
+ <spinner left="133" name="AvatarAxisScale2" />
+ <spinner left="208" name="BuildAxisScale2" />
<spinner left="283" name="FlycamAxisScale2" />
- <text width="124" name="ZScale">
+ <text width="104" name="ZScale">
Skala Z
</text>
- <spinner left="153" name="AvatarAxisScale0" />
- <spinner left="218" name="BuildAxisScale0" />
+ <spinner left="133" name="AvatarAxisScale0" />
+ <spinner left="208" name="BuildAxisScale0" />
<spinner left="283" name="FlycamAxisScale0" />
- <text width="124" name="PitchScale">
+ <text width="104" name="PitchScale">
Skala Wznoszenia
</text>
- <spinner left="153" name="AvatarAxisScale4" />
- <spinner left="218" name="BuildAxisScale4" />
+ <spinner left="133" name="AvatarAxisScale4" />
+ <spinner left="208" name="BuildAxisScale4" />
<spinner left="283" name="FlycamAxisScale4" />
- <text width="124" name="YawScale">
+ <text width="104" name="YawScale">
Skala Odchylania
</text>
- <spinner left="153" name="AvatarAxisScale5" />
- <spinner left="218" name="BuildAxisScale5" />
+ <spinner left="133" name="AvatarAxisScale5" />
+ <spinner left="208" name="BuildAxisScale5" />
<spinner left="283" name="FlycamAxisScale5" />
- <text width="124" name="RollScale">
+ <text width="104" name="RollScale">
Skala Obrotu
</text>
- <spinner left="218" name="BuildAxisScale3" />
+ <spinner left="208" name="BuildAxisScale3" />
<spinner left="283" name="FlycamAxisScale3" />
- <text width="124" name="XDeadZone">
+ <text width="104" name="XDeadZone">
Tolerancja Osi X
</text>
- <spinner left="153" name="AvatarAxisDeadZone1" />
- <spinner left="218" name="BuildAxisDeadZone1" />
+ <spinner left="133" name="AvatarAxisDeadZone1" />
+ <spinner left="208" name="BuildAxisDeadZone1" />
<spinner left="283" name="FlycamAxisDeadZone1" />
- <text width="124" name="YDeadZone">
+ <text width="104" name="YDeadZone">
Tolerancja Osi Y
</text>
- <spinner left="153" name="AvatarAxisDeadZone2" />
- <spinner left="218" name="BuildAxisDeadZone2" />
+ <spinner left="133" name="AvatarAxisDeadZone2" />
+ <spinner left="208" name="BuildAxisDeadZone2" />
<spinner left="283" name="FlycamAxisDeadZone2" />
- <text width="124" name="ZDeadZone">
+ <text width="104" name="ZDeadZone">
Tolerancja Osi Z
</text>
- <spinner left="153" name="AvatarAxisDeadZone0" />
- <spinner left="218" name="BuildAxisDeadZone0" />
+ <spinner left="133" name="AvatarAxisDeadZone0" />
+ <spinner left="208" name="BuildAxisDeadZone0" />
<spinner left="283" name="FlycamAxisDeadZone0" />
- <text width="124" name="PitchDeadZone">
+ <text width="104" name="PitchDeadZone">
Tolerancja Wznoszenia
</text>
- <spinner left="153" name="AvatarAxisDeadZone4" />
- <spinner left="218" name="BuildAxisDeadZone4" />
+ <spinner left="133" name="AvatarAxisDeadZone4" />
+ <spinner left="208" name="BuildAxisDeadZone4" />
<spinner left="283" name="FlycamAxisDeadZone4" />
- <text width="124" name="YawDeadZone">
+ <text width="104" name="YawDeadZone">
Tolerancja Odchylania
</text>
- <spinner left="153" name="AvatarAxisDeadZone5" />
- <spinner left="218" name="BuildAxisDeadZone5" />
+ <spinner left="133" name="AvatarAxisDeadZone5" />
+ <spinner left="208" name="BuildAxisDeadZone5" />
<spinner left="283" name="FlycamAxisDeadZone5" />
- <text width="124" name="RollDeadZone">
+ <text width="104" name="RollDeadZone">
Tolerancja Obrotu
</text>
- <spinner left="218" name="BuildAxisDeadZone3" />
+ <spinner left="208" name="BuildAxisDeadZone3" />
<spinner left="283" name="FlycamAxisDeadZone3" />
- <text width="124" name="Feathering">
+ <text width="104" name="Feathering">
Przenikanie
</text>
- <slider left="145" label="" name="AvatarFeathering" />
- <slider left="210" label="" name="BuildFeathering" />
+ <slider left="125" label="" name="AvatarFeathering" />
+ <slider left="200" label="" name="BuildFeathering" />
<slider left="275" label="" name="FlycamFeathering" />
- <text width="124" name="ZoomScale2">
+ <text width="104" name="ZoomScale2">
Skala Powiększania
</text>
<spinner left="283" label="" name="FlycamAxisScale6" />
- <text width="124" name="ZoomDeadZone">
+ <text width="104" name="ZoomDeadZone">
Tolerancja Powiększania
</text>
<spinner left="283" label="" name="FlycamAxisDeadZone6" />
<button left="366" label="Ustawienia Domyślne" name="SpaceNavigatorDefaults" />
- <button label="OK" label_selected="OK" name="ok_btn" />
+ <button left="366" label="OK" label_selected="OK" name="ok_btn" />
<button label="Anuluj" label_selected="Anuluj" name="cancel_btn" />
- <string name="JoystickMonitor">
- Monitor Joysticka
- </string>
- <string name="Axis">
- OÅ› [NUM]
- </string>
+ <stat_view label="Monitor Joysticka" name="axis_view">
+ <stat_bar label="OÅ› 0" name="axis0"/>
+ <stat_bar label="OÅ› 1" name="axis1"/>
+ <stat_bar label="OÅ› 2" name="axis2"/>
+ <stat_bar label="OÅ› 3" name="axis3"/>
+ <stat_bar label="OÅ› 4" name="axis4"/>
+ <stat_bar label="OÅ› 5" name="axis5"/>
+ </stat_view>
<string name="NoDevice">
brak podłącznego urządzenia
</string>
-</floater> \ No newline at end of file
+</floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_lagmeter.xml b/indra/newview/skins/default/xui/pl/floater_lagmeter.xml
index 949289594e..69d563bdba 100755
--- a/indra/newview/skins/default/xui/pl/floater_lagmeter.xml
+++ b/indra/newview/skins/default/xui/pl/floater_lagmeter.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_lagmeter" title="Pomiar Lagów">
+<floater name="floater_lagmeter" title="POMIAR LAGÓW">
<button label="" label_selected="" name="client_lagmeter"
tool_tip="Status lagów klienta" />
<text name="client">
diff --git a/indra/newview/skins/default/xui/pl/floater_land_holdings.xml b/indra/newview/skins/default/xui/pl/floater_land_holdings.xml
index 29268f0e97..13e6a8b16d 100755
--- a/indra/newview/skins/default/xui/pl/floater_land_holdings.xml
+++ b/indra/newview/skins/default/xui/pl/floater_land_holdings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="land holdings floater" title="Moja posiadłość">
+<floater name="land holdings floater" title="MOJA POSIADÅOŚĆ">
<scroll_list name="parcel list">
<column label="Nazwa posiadłości" name="name"/>
<column label="Region" name="location"/>
diff --git a/indra/newview/skins/default/xui/pl/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/pl/floater_live_lsleditor.xml
index 94efd7afcb..8120ff8c77 100755
--- a/indra/newview/skins/default/xui/pl/floater_live_lsleditor.xml
+++ b/indra/newview/skins/default/xui/pl/floater_live_lsleditor.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script ed float" title="Skrypt: Nowy Skrypt">
+<floater name="script ed float" title="SKRYPT: NOWY SKRYPT">
<button label="Zresetuj" label_selected="Zresetuj" name="Reset" />
<check_box label="WÅ‚Ä…cz" name="running" />
<check_box label="Mono" name="mono" />
diff --git a/indra/newview/skins/default/xui/pl/floater_lsl_guide.xml b/indra/newview/skins/default/xui/pl/floater_lsl_guide.xml
index a0fa00dffe..5601aa4464 100755
--- a/indra/newview/skins/default/xui/pl/floater_lsl_guide.xml
+++ b/indra/newview/skins/default/xui/pl/floater_lsl_guide.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script ed float" title="LSL Wiki">
+<floater name="script ed float" title="LSL WIKI">
<check_box label="Idź za kursorem" name="lock_check" />
<combo_box label="Zablokuj" name="history_combo" />
<button label="Wróć" name="back_btn" />
diff --git a/indra/newview/skins/default/xui/pl/floater_map.xml b/indra/newview/skins/default/xui/pl/floater_map.xml
new file mode 100644
index 0000000000..6eabde7c52
--- /dev/null
+++ b/indra/newview/skins/default/xui/pl/floater_map.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Map">
+ <floater.string name="mini_map_north">
+ N
+ </floater.string>
+ <floater.string name="mini_map_east">
+ E
+ </floater.string>
+ <floater.string name="mini_map_west">
+ W
+ </floater.string>
+ <floater.string name="mini_map_south">
+ S
+ </floater.string>
+ <floater.string name="mini_map_southeast">
+ SE
+ </floater.string>
+ <floater.string name="mini_map_northeast">
+ NE
+ </floater.string>
+ <floater.string name="mini_map_southwest">
+ SW
+ </floater.string>
+ <floater.string name="mini_map_northwest">
+ NW
+ </floater.string>
+ <text label="N" name="floater_map_north" text="N">
+ N
+ </text>
+ <text label="E" name="floater_map_east" text="E">
+ E
+ </text>
+ <text label="W" name="floater_map_west" text="W">
+ W
+ </text>
+ <text label="S" name="floater_map_south" text="S">
+ S
+ </text>
+ <text label="SE" name="floater_map_southeast" text="SE">
+ SE
+ </text>
+ <text label="NE" name="floater_map_northeast" text="NE">
+ NE
+ </text>
+ <text label="SW" name="floater_map_southwest" text="SW">
+ SW
+ </text>
+ <text label="NW" name="floater_map_northwest" text="NW">
+ NW
+ </text>
+</floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_media_browser.xml b/indra/newview/skins/default/xui/pl/floater_media_browser.xml
index 2fb4287d90..74210c75e5 100755
--- a/indra/newview/skins/default/xui/pl/floater_media_browser.xml
+++ b/indra/newview/skins/default/xui/pl/floater_media_browser.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_about" title="Przeglądarka Mediów">
+<floater name="floater_about" title="PRZEGLĄDARKA MEDIÓW">
<layout_stack name="stack1">
<layout_panel name="nav_controls">
<button label="Wróć" name="back" />
diff --git a/indra/newview/skins/default/xui/pl/floater_mem_leaking.xml b/indra/newview/skins/default/xui/pl/floater_mem_leaking.xml
index fe977e96c5..88a878af72 100755
--- a/indra/newview/skins/default/xui/pl/floater_mem_leaking.xml
+++ b/indra/newview/skins/default/xui/pl/floater_mem_leaking.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="MemLeak" title="Symulacja Przecieków Alokacji Pamięci">
+<floater name="MemLeak" title="SYMULACJA PRZECIEKÓW ALOKACJI PAMIĘCI">
<spinner label="Prędkość Przecieków (byty na klatkę):" name="leak_speed" />
<spinner label="Max Przecieki (MB):" name="max_leak" />
<text name="total_leaked_label">
diff --git a/indra/newview/skins/default/xui/pl/floater_moveview.xml b/indra/newview/skins/default/xui/pl/floater_moveview.xml
index 715fec0bae..e28cfd589d 100755
--- a/indra/newview/skins/default/xui/pl/floater_moveview.xml
+++ b/indra/newview/skins/default/xui/pl/floater_moveview.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="move floater" title="">
+<floater name="move_floater">
+<panel name="panel_actions">
<button label="" label_selected="" name="turn left btn" tool_tip="Obróć w lewo" />
<button label="" label_selected="" name="turn right btn" tool_tip="Obroć w Prawo" />
<button label="" label_selected="" name="move up btn"
@@ -10,4 +11,5 @@
<joystick_slide name="slide right btn" tool_tip="Przesuń w prawo" />
<joystick_turn name="forward btn" tool_tip="Przesuń do przodu" />
<joystick_turn name="backward btn" tool_tip="Przesuń do tyłu" />
+</panel>
</floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_mute_object.xml b/indra/newview/skins/default/xui/pl/floater_mute_object.xml
index 310810db76..dd30f749e3 100755
--- a/indra/newview/skins/default/xui/pl/floater_mute_object.xml
+++ b/indra/newview/skins/default/xui/pl/floater_mute_object.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="mute by name" title="Wycisz Obiekt Według Nazwy" height="160" min_height="160" >
+<floater name="mute by name" title="WYCISZ OBIEKT WEDÅUG NAZWY" height="160" min_height="160" >
<text name="message">
Wyciszenie obiektu jest skuteczne jedynie na czacie oraz w
wiadomościach IM. Nie obejmuje natomiast dźwięków.
diff --git a/indra/newview/skins/default/xui/pl/floater_my_friends.xml b/indra/newview/skins/default/xui/pl/floater_my_friends.xml
index cc5f1f2a01..0bcf6ba4d5 100755
--- a/indra/newview/skins/default/xui/pl/floater_my_friends.xml
+++ b/indra/newview/skins/default/xui/pl/floater_my_friends.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_my_friends" title="Kontakty">
+<floater name="floater_my_friends" title="KONTAKTY">
<tab_container name="friends_and_groups">
<panel label="Znajomi" name="friends_panel" />
<panel label="Grupy" name="groups_panel" />
diff --git a/indra/newview/skins/default/xui/pl/floater_openobject.xml b/indra/newview/skins/default/xui/pl/floater_openobject.xml
index 9969d661a0..fbbed0f11d 100755
--- a/indra/newview/skins/default/xui/pl/floater_openobject.xml
+++ b/indra/newview/skins/default/xui/pl/floater_openobject.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="objectcontents" title="Zawartość Obiektu">
- <text type="string" length="1" name="object_name">
+<floater name="objectcontents" title="ZAWARTOŚĆ OBIEKTU">
+ <text name="object_name">
[DESC]:
</text>
<button label="Kopiuj do Szafy" label_selected="Kopiuj do Szafy"
diff --git a/indra/newview/skins/default/xui/pl/floater_pay.xml b/indra/newview/skins/default/xui/pl/floater_pay.xml
index 70358909f2..dfb1b6616c 100755
--- a/indra/newview/skins/default/xui/pl/floater_pay.xml
+++ b/indra/newview/skins/default/xui/pl/floater_pay.xml
@@ -6,16 +6,16 @@
<button label="L$20" label_selected="L$20" name="fastpay 20" />
<button label="Zapłać" label_selected="Zapłać" name="pay btn" />
<button label="Anuluj" label_selected="Anuluj" name="cancel btn" />
- <text type="string" length="1" name="payee_label">
+ <text name="payee_label">
Zapłata dla:
</text>
- <text type="string" length="1" name="payee_name">
+ <text name="payee_name">
[FIRST] [LAST]
</text>
- <text type="string" length="1" name="fastpay text" halign="left" left="12">
+ <text name="fastpay text" halign="left" left="12">
Szybka Zapłata:
</text>
- <text type="string" length="1" name="amount text">
+ <text name="amount text">
Suma:
</text>
<line_editor left="52" name="amount" />
diff --git a/indra/newview/skins/default/xui/pl/floater_pay_object.xml b/indra/newview/skins/default/xui/pl/floater_pay_object.xml
index 97c87d55d3..376f517aaa 100755
--- a/indra/newview/skins/default/xui/pl/floater_pay_object.xml
+++ b/indra/newview/skins/default/xui/pl/floater_pay_object.xml
@@ -1,24 +1,24 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="Give Money" title="">
- <text type="string" length="1" name="payee_group" width="100" halign="left">
+ <text name="payee_group" width="100" halign="left">
Zapłać Grupie:
</text>
- <text type="string" length="1" name="payee_resident" width="120" halign="left" >
+ <text name="payee_resident" width="120" halign="left" >
Zapłać Rezydentowi:
</text>
- <text type="string" length="1" name="payee_name" left="125">
+ <text name="payee_name" left="125">
[FIRST] [LAST]
</text>
- <text type="string" length="1" name="object_name_label" left="5" width="95" halign="left">
+ <text name="object_name_label" left="5" width="95" halign="left">
Poprzez Obiekt:
</text>
- <text type="string" length="1" name="object_name_text" left="105" >
+ <text name="object_name_text" left="105" >
...
</text>
- <text type="string" length="1" name="fastpay text" width="95" halign="left">
+ <text name="fastpay text" width="95" halign="left">
Szybka Zapłata:
</text>
- <text type="string" length="1" name="amount text" left="5" halign="left">
+ <text name="amount text" left="5" halign="left">
Suma:
</text>
<button label="L$1" label_selected="L$1" name="fastpay 1" left="105"/>
diff --git a/indra/newview/skins/default/xui/pl/floater_perm_prefs.xml b/indra/newview/skins/default/xui/pl/floater_perm_prefs.xml
index dd7cbe1f79..834552e2b0 100644
--- a/indra/newview/skins/default/xui/pl/floater_perm_prefs.xml
+++ b/indra/newview/skins/default/xui/pl/floater_perm_prefs.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="perm prefs" title="Prawa Domyślne">
+<floater name="perm prefs" title="PRAWA DOMYÅšLNE">
<panel label="Prawa" name="permissions">
<button label="?" label_selected="?" name="help"/>
<check_box label="Udostępnij grupie" name="share_with_group"/>
diff --git a/indra/newview/skins/default/xui/pl/floater_post_process.xml b/indra/newview/skins/default/xui/pl/floater_post_process.xml
index a86e1bcfa5..6bd91f97b1 100755
--- a/indra/newview/skins/default/xui/pl/floater_post_process.xml
+++ b/indra/newview/skins/default/xui/pl/floater_post_process.xml
@@ -1,21 +1,21 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Post-Process Floater" title="Ustawienia Przetwarzania Końcowego">
+<floater name="Post-Process Floater" title="USTAWIENIA PRZETWARZANIA KOŃCOWEGO">
<tab_container name="Post-Process Tabs">
<panel label="Kolor Filtru" name="wmiColorFilterPanel">
<check_box label="Udostępnij" name="wmiColorFilterToggle" />
- <text type="string" length="1" name="wmiColorFilterBrightnessText">
+ <text name="wmiColorFilterBrightnessText">
Jasność
</text>
<slider label="" name="wmiColorFilterBrightness" />
- <text type="string" length="1" name="wmiColorFilterSaturationText">
+ <text name="wmiColorFilterSaturationText">
Nasycenie
</text>
<slider label="" name="wmiColorFilterSaturation" />
- <text type="string" length="1" name="wmiColorFilterContrastText">
+ <text name="wmiColorFilterContrastText">
Kontrast
</text>
<slider label="" name="wmiColorFilterContrast" />
- <text type="string" length="1" name="wmiColorFilterBaseText">
+ <text name="wmiColorFilterBaseText">
Kontrast Koloru Podstawowego
</text>
<slider label="R" name="wmiColorFilterBaseR" />
@@ -25,30 +25,30 @@
</panel>
<panel label="Wizja Nocna" name="wmiNightVisionPanel">
<check_box label="Udostępnij" name="wmiNightVisionToggle" />
- <text type="string" length="1" name="wmiNightVisionBrightMultText">
+ <text name="wmiNightVisionBrightMultText">
Wielokrotne Wzmocnienie Światła
</text>
<slider label="" name="wmiNightVisionBrightMult" />
- <text type="string" length="1" name="wmiNightVisionNoiseSizeText">
+ <text name="wmiNightVisionNoiseSizeText">
Rozmiar Szumu
</text>
<slider label="" name="wmiNightVisionNoiseSize" />
- <text type="string" length="1" name="wmiNightVisionNoiseStrengthText">
+ <text name="wmiNightVisionNoiseStrengthText">
Moc Szumu
</text>
<slider label="" name="wmiNightVisionNoiseStrength" />
</panel>
<panel label="Bloom" name="wmiBloomPanel">
<check_box label="Udostępnij" name="wmiBloomToggle" />
- <text type="string" length="1" name="wmiBloomExtractText">
+ <text name="wmiBloomExtractText">
Ekstracja Luminacji
</text>
<slider label="" name="wmiBloomExtract" />
- <text type="string" length="1" name="wmiBloomSizeText">
+ <text name="wmiBloomSizeText">
Rozmiar Rozmazania Obrazu
</text>
<slider label="" name="wmiBloomSize" />
- <text type="string" length="1" name="wmiBloomStrengthText">
+ <text name="wmiBloomStrengthText">
Moc Rozmazania Obrazu
</text>
<slider label="" name="wmiBloomStrength" />
diff --git a/indra/newview/skins/default/xui/pl/floater_postcard.xml b/indra/newview/skins/default/xui/pl/floater_postcard.xml
index 080edd5623..8f4018924d 100755
--- a/indra/newview/skins/default/xui/pl/floater_postcard.xml
+++ b/indra/newview/skins/default/xui/pl/floater_postcard.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Postcard" title="Wyślij Pocztówkę">
+<floater name="Postcard" title="WYŚLIJ POCZTÓWKĘ">
<text name="to_label">
Email Odbiorcy:
</text>
@@ -20,17 +20,17 @@
Wpisz treść swojej wiadomości tutaj
</text_editor>
<text name="fine_print">
- Jeżeli odbiorca tej pocztówki dołączy do Second Life, otrzymasz bonusa.
+ Jeżeli odbiorca tej pocztówki dołączy do [SECOND_LIFE], otrzymasz bonusa.
</text>
<button label="Anuluj" name="cancel_btn"/>
<button label="Wyślij" name="send_btn"/>
<string name="default_subject">
- Pocztówki z Second Life.
+ Pocztówki z [SECOND_LIFE]
</string>
<string name="default_message">
Sprawdź i przekonaj się sam!
</string>
<string name="upload_message">
- &quot;Wysyłanie...&quot;
+ Wysyłanie...
</string>
</floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_preferences.xml b/indra/newview/skins/default/xui/pl/floater_preferences.xml
index 380738425e..2be663283f 100755
--- a/indra/newview/skins/default/xui/pl/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/pl/floater_preferences.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Preferences" title="Ustawienia">
+<floater name="Preferences" title="USTAWIENIA">
<button label="OK" label_selected="OK" name="OK" />
<button label="Anuluj" label_selected="Anuluj" name="Cancel" />
<button label="Zastosuj" label_selected="Zastosuj" name="Apply" />
diff --git a/indra/newview/skins/default/xui/pl/floater_preview_animation.xml b/indra/newview/skins/default/xui/pl/floater_preview_animation.xml
index d6752223f9..7139c470a4 100755
--- a/indra/newview/skins/default/xui/pl/floater_preview_animation.xml
+++ b/indra/newview/skins/default/xui/pl/floater_preview_animation.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="preview_anim">
- <text type="string" length="1" name="desc txt">
+ <text name="desc txt">
Opis:
</text>
<button label="Używaj w Świecie" label_selected="Stop" name="Anim play btn"
diff --git a/indra/newview/skins/default/xui/pl/floater_preview_classified.xml b/indra/newview/skins/default/xui/pl/floater_preview_classified.xml
index cc7d276117..eae9ba2690 100755
--- a/indra/newview/skins/default/xui/pl/floater_preview_classified.xml
+++ b/indra/newview/skins/default/xui/pl/floater_preview_classified.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="classified_preview" title="Reklama" />
+<floater name="classified_preview" title="REKLAMA" />
diff --git a/indra/newview/skins/default/xui/pl/floater_preview_event.xml b/indra/newview/skins/default/xui/pl/floater_preview_event.xml
index 75e17f6fa2..9fc0ff4da6 100755
--- a/indra/newview/skins/default/xui/pl/floater_preview_event.xml
+++ b/indra/newview/skins/default/xui/pl/floater_preview_event.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="event_preview" title="Informacje o Imprezie" />
+<floater name="event_preview" title="INFORMACJE O IMPREZIE" />
diff --git a/indra/newview/skins/default/xui/pl/floater_preview_gesture.xml b/indra/newview/skins/default/xui/pl/floater_preview_gesture.xml
index 02c6e1ef8a..1c7a3f6631 100755
--- a/indra/newview/skins/default/xui/pl/floater_preview_gesture.xml
+++ b/indra/newview/skins/default/xui/pl/floater_preview_gesture.xml
@@ -45,12 +45,8 @@ Wstrzymaj
chyba, że dodasz pauzy.
</text>
<radio_group name="animation_trigger_type">
- <radio_item name="start">
- Start
- </radio_item>
- <radio_item name="stop">
- Stop
- </radio_item>
+ <radio_item name="start" label="Start" />
+ <radio_item name="stop" label="Stop" />
</radio_group>
<check_box label="do końca animacji" name="wait_anim_check"/>
<check_box label="czas w sekundach" name="wait_time_check"/>
diff --git a/indra/newview/skins/default/xui/pl/floater_preview_notecard.xml b/indra/newview/skins/default/xui/pl/floater_preview_notecard.xml
index c67d9a9206..b9f80490ab 100755
--- a/indra/newview/skins/default/xui/pl/floater_preview_notecard.xml
+++ b/indra/newview/skins/default/xui/pl/floater_preview_notecard.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="preview notecard" title="Nota:">
+<floater name="preview notecard" title="NOTA:">
<button label="Zapisz" label_selected="Zapisz" name="Save" />
- <text type="string" length="1" name="desc txt">
+ <text name="desc txt">
Opis:
</text>
- <text_editor type="string" length="1" name="Notecard Editor">
+ <text_editor name="Notecard Editor">
Åadowanie...
</text_editor>
<string name="no_object">
diff --git a/indra/newview/skins/default/xui/pl/floater_preview_sound.xml b/indra/newview/skins/default/xui/pl/floater_preview_sound.xml
index c9dd20128d..656b9bec38 100755
--- a/indra/newview/skins/default/xui/pl/floater_preview_sound.xml
+++ b/indra/newview/skins/default/xui/pl/floater_preview_sound.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="preview_sound">
- <text type="string" length="1" name="desc txt">
+ <text name="desc txt">
Opis:
</text>
<button label="Odtwarzaj Lokalnie" label_selected="Odtwarzaj Lokalnie"
@@ -8,5 +8,5 @@
tool_tip="Dźwięk będzie słyszalny tylko dla Ciebie." />
<button label="Odtwarzaj w Åšwiecie" label_selected="Odtwarzaj w Åšwiecie"
name="Sound play btn"
- tool_tip="Dźwięk będzie słyszalny przez wszystkich." />
+ tool_tip="Dźwięk będzie słyszalny przez wszystkich." width="130" left_delta="-136"/>
</floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_preview_texture.xml b/indra/newview/skins/default/xui/pl/floater_preview_texture.xml
index 860feee9b1..8bcd800411 100755
--- a/indra/newview/skins/default/xui/pl/floater_preview_texture.xml
+++ b/indra/newview/skins/default/xui/pl/floater_preview_texture.xml
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="preview_texture">
- <text type="string" length="1" name="desc txt">
+ <text name="desc txt">
Opis:
</text>
- <text type="string" length="1" name="dimensions">
+ <text name="dimensions">
Wymiary: [WIDTH] x [HEIGHT]
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_region_info.xml b/indra/newview/skins/default/xui/pl/floater_region_info.xml
index 6e632fd9c3..ca3c1391db 100755
--- a/indra/newview/skins/default/xui/pl/floater_region_info.xml
+++ b/indra/newview/skins/default/xui/pl/floater_region_info.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="regioninfo" title="Region/MajÄ…tek" />
+<floater name="regioninfo" title="REGION/MAJÄ„TEK" />
diff --git a/indra/newview/skins/default/xui/pl/floater_report_abuse.xml b/indra/newview/skins/default/xui/pl/floater_report_abuse.xml
index d4ad72a3e1..c1efcffb1e 100755
--- a/indra/newview/skins/default/xui/pl/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/pl/floater_report_abuse.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_report_abuse" title="Raport o Nadużyciu">
+<floater name="floater_report_abuse" title="RAPORT O NADUŻYCIU">
<texture_picker label="" name="screenshot"/>
<check_box label="Załącz zdjęcie ekranu" name="screen_check"/>
<text name="reporter_title">
@@ -37,123 +37,45 @@
Hendrerit Vulputate
</text>
<combo_box name="category_combo" tool_tip="Wybór kategorii - wybierz kategorię, której dotyczy raport">
- <combo_item name="Select_category">
- Wybierz KategoriÄ™:
- </combo_item>
- <combo_item name="Age__Age_play">
- Wiek &gt; Udawanie Nieletniej Osoby
- </combo_item>
- <combo_item name="Age__Adult_resident_on_Teen_Second_Life">
- Wiek &gt; Dorosły Rezydent w Teen Second Life
- </combo_item>
- <combo_item name="Age__Underage_resident_outside_of_Teen_Second_Life">
- Wiek &gt; Nieletni Rezydent poza Teen Second Life
- </combo_item>
- <combo_item name="Assault__Combat_sandbox___unsafe_area">
- Napaść &gt; Strefa Militarna / Niebezpieczny Obszar
- </combo_item>
- <combo_item name="Assault__Safe_area">
- Napaść &gt; Bezpieczny Obszar
- </combo_item>
- <combo_item name="Assault__Weapons_testing_sandbox">
- Napaść &gt; Obszar do Testowania Broni
- </combo_item>
- <combo_item name="Commerce__Failure_to_deliver_product_or_service">
- Handel &gt; Niedostarczenie Produktu lub Usługi
- </combo_item>
- <combo_item name="Disclosure__Real_world_information">
- Naruszenie Prywatności &gt; Dane Osobiste
- </combo_item>
- <combo_item name="Disclosure__Remotely_monitoring chat">
- Ujawnienie &gt; Monitorowanie Czatu
- </combo_item>
- <combo_item name="Disclosure__Second_Life_information_chat_IMs">
- Ujawnienie &gt; Dane z Second Life / Czatu / IM
- </combo_item>
- <combo_item name="Disturbing_the_peace__Unfair_use_of_region_resources">
- Zakłócanie Spokoju &gt; Nieuczciwe Używanie Zasobów Regionu
- </combo_item>
- <combo_item name="Disturbing_the_peace__Excessive_scripted_objects">
- Zakłócanie Spokoju &gt; Przesadnie Skryptowane Obiekty
- </combo_item>
- <combo_item name="Disturbing_the_peace__Object_littering">
- Zakłócanie Spokoju &gt; Śmiecenie Obiektami
- </combo_item>
- <combo_item name="Disturbing_the_peace__Repetitive_spam">
- Zakłócanie Spokoju &gt; Ciągły Spam
- </combo_item>
- <combo_item name="Disturbing_the_peace__Unwanted_advert_spam">
- Zakłócanie Spokoju &gt; Nieporządany Spam Reklamowy
- </combo_item>
- <combo_item name="Fraud__L$">
- Oszustwo &gt; L$
- </combo_item>
- <combo_item name="Fraud__Land">
- Oszustwo &gt; Posiadłości
- </combo_item>
- <combo_item name="Fraud__Pyramid_scheme_or_chain_letter">
- Oszustwo &gt; Piramidy albo Listy ÅaÅ„cuchowe
- </combo_item>
- <combo_item name="Fraud__US$">
- Oszustwo &gt; US$
- </combo_item>
- <combo_item name="Harassment__Advert_farms___visual_spam">
- Prześladowanie &gt; Farmy Reklamowe / Wizualny Spam
- </combo_item>
- <combo_item name="Harassment__Defaming_individuals_or_groups">
- Prześladowanie &gt; Zniesławianie Jedostek lub Grup
- </combo_item>
- <combo_item name="Harassment__Impeding_movement">
- Prześladowanie &gt; Ograniczanie Ruchu
- </combo_item>
- <combo_item name="Harassment__Sexual_harassment">
- Prześladowanie &gt; Molestowanie Seksualne
- </combo_item>
- <combo_item name="Harassment__Solicting_inciting_others_to_violate_ToS">
- PrzeÅ›ladowanie &gt; Namawianie/ZachÄ™canie Innych do Åamania Warunków Umowy (ToS)
- </combo_item>
- <combo_item name="Harassment__Verbal_abuse">
- Prześladowanie &gt; Znieważanie Słowne
- </combo_item>
- <combo_item name="Indecency__Broadly_offensive_content_or_conduct">
- Nieprzyzwoitość &gt; Obraźliwa Treść lub Postępowanie
- </combo_item>
- <combo_item name="Indecency__Inappropriate_avatar_name">
- Nieprzyzwoitość &gt; Niestosowne Imię Awatara
- </combo_item>
- <combo_item name="Indecency__Mature_content_in_PG_region">
- Nieprzyzwoitość &gt; Obraźliwa treść i postępowanie w regionie &apos;PG&apos;
- </combo_item>
- <combo_item name="Indecency__Inappropriate_content_in_Mature_region">
- Nieprzyzwoitość &gt; Obraźliwa treść i postępowanie w regionie &apos;Mature&apos;
- </combo_item>
- <combo_item name="Intellectual_property_infringement_Content_Removal">
- Naruszenie Własności Intelektualnej &gt; Usunięcie Treści
- </combo_item>
- <combo_item name="Intellectual_property_infringement_CopyBot_or_Permissions_Exploit">
- Naruszenie Własności Intelektualnej &gt; CopyBot albo Nadużycie Przywilejów
- </combo_item>
- <combo_item name="Intolerance">
- Nietolerancja
- </combo_item>
- <combo_item name="Land__Abuse_of_sandbox_resources">
- Posiadłości &gt; Nadużywanie Piaskownicy
- </combo_item>
- <combo_item name="Land__Encroachment__Objects_textures">
- Posiadłości &gt; Naruszenie &gt; Obiekty/Tekstury
- </combo_item>
- <combo_item name="Land__Encroachment__Particles">
- Posiadłości &gt; Naruszenie &gt; Cząsteczki
- </combo_item>
- <combo_item name="Land__Encroachment__Trees_plants">
- Posiadłości &gt; Naruszenie &gt; Drzewa/Rośliny
- </combo_item>
- <combo_item name="Wagering_gambling">
- Zakłady/Hazard
- </combo_item>
- <combo_item name="Other">
- Inne
- </combo_item>
+ <combo_box.item name="Select_category" label="Wybierz KategoriÄ™:"/>
+ <combo_box.item name="Age__Age_play" label="Wiek &gt; Udawanie Nieletniej Osoby"/>
+ <combo_box.item name="Age__Adult_resident_on_Teen_Second_Life" label="Wiek &gt; Dorosły Rezydent w Teen Second Life"/>
+ <combo_box.item name="Age__Underage_resident_outside_of_Teen_Second_Life" label="Wiek &gt; Nieletni Rezydent poza Teen Second Life"/>
+ <combo_box.item name="Assault__Combat_sandbox___unsafe_area" label="Napaść &gt; Strefa Militarna / Niebezpieczny Obszar"/>
+ <combo_box.item name="Assault__Safe_area" label="Napaść &gt; Bezpieczny Obszar"/>
+ <combo_box.item name="Assault__Weapons_testing_sandbox" label="Napaść &gt; Obszar do Testowania Broni"/>
+ <combo_box.item name="Commerce__Failure_to_deliver_product_or_service" label="Handel &gt; Niedostarczenie Produktu lub Usługi"/>
+ <combo_box.item name="Disclosure__Real_world_information" label="Naruszenie Prywatności &gt; Dane Osobiste"/>
+ <combo_box.item name="Disclosure__Remotely_monitoring chat" label="Ujawnienie &gt; Monitorowanie Czatu"/>
+ <combo_box.item name="Disclosure__Second_Life_information_chat_IMs" label="Ujawnienie &gt; Dane z Second Life / Czatu / IM"/>
+ <combo_box.item name="Disturbing_the_peace__Unfair_use_of_region_resources" label="Zakłócanie Spokoju &gt; Nieuczciwe Używanie Zasobów Regionu"/>
+ <combo_box.item name="Disturbing_the_peace__Excessive_scripted_objects" label="Zakłócanie Spokoju &gt; Przesadnie Skryptowane Obiekty"/>
+ <combo_box.item name="Disturbing_the_peace__Object_littering" label="Zakłócanie Spokoju &gt; Śmiecenie Obiektami"/>
+ <combo_box.item name="Disturbing_the_peace__Repetitive_spam" label="Zakłócanie Spokoju &gt; Ciągły Spam"/>
+ <combo_box.item name="Disturbing_the_peace__Unwanted_advert_spam" label="Zakłócanie Spokoju &gt; Nieporządany Spam Reklamowy"/>
+ <combo_box.item name="Fraud__L$" label="Oszustwo &gt; L$"/>
+ <combo_box.item name="Fraud__Land" label="Oszustwo &gt; Posiadłości"/>
+ <combo_box.item name="Fraud__Pyramid_scheme_or_chain_letter" label="Oszustwo &gt; Piramidy albo Listy ÅaÅ„cuchowe"/>
+ <combo_box.item name="Fraud__US$" label="Oszustwo &gt; US$"/>
+ <combo_box.item name="Harassment__Advert_farms___visual_spam" label="Prześladowanie &gt; Farmy Reklamowe / Wizualny Spam"/>
+ <combo_box.item name="Harassment__Defaming_individuals_or_groups" label="Prześladowanie &gt; Zniesławianie Jedostek lub Grup"/>
+ <combo_box.item name="Harassment__Impeding_movement" label="Prześladowanie &gt; Ograniczanie Ruchu"/>
+ <combo_box.item name="Harassment__Sexual_harassment" label="Prześladowanie &gt; Molestowanie Seksualne"/>
+ <combo_box.item name="Harassment__Solicting_inciting_others_to_violate_ToS" label="PrzeÅ›ladowanie &gt; Namawianie/ZachÄ™canie Innych do Åamania Warunków Umowy (ToS)"/>
+ <combo_box.item name="Harassment__Verbal_abuse" label="Prześladowanie &gt; Znieważanie Słowne"/>
+ <combo_box.item name="Indecency__Broadly_offensive_content_or_conduct" label="Nieprzyzwoitość &gt; Obraźliwa Treść lub Postępowanie"/>
+ <combo_box.item name="Indecency__Inappropriate_avatar_name" label="Nieprzyzwoitość &gt; Niestosowne Imię Awatara"/>
+ <combo_box.item name="Indecency__Mature_content_in_PG_region" label="Nieprzyzwoitość &gt; Obraźliwa treść i postępowanie w regionie &apos;PG&apos;"/>
+ <combo_box.item name="Indecency__Inappropriate_content_in_Mature_region" label="Nieprzyzwoitość &gt; Obraźliwa treść i postępowanie w regionie &apos;Mature&apos;"/>
+ <combo_box.item name="Intellectual_property_infringement_Content_Removal" label="Naruszenie Własności Intelektualnej &gt; Usunięcie Treści"/>
+ <combo_box.item name="Intellectual_property_infringement_CopyBot_or_Permissions_Exploit" label="Naruszenie Własności Intelektualnej &gt; CopyBot albo Nadużycie Przywilejów"/>
+ <combo_box.item name="Intolerance" label="Nietolerancja"/>
+ <combo_box.item name="Land__Abuse_of_sandbox_resources" label="Posiadłości &gt; Nadużywanie Piaskownicy"/>
+ <combo_box.item name="Land__Encroachment__Objects_textures" label="Posiadłości &gt; Naruszenie &gt; Obiekty/Tekstury"/>
+ <combo_box.item name="Land__Encroachment__Particles" label="Posiadłości &gt; Naruszenie &gt; Cząsteczki"/>
+ <combo_box.item name="Land__Encroachment__Trees_plants" label="Posiadłości &gt; Naruszenie &gt; Drzewa/Rośliny"/>
+ <combo_box.item name="Wagering_gambling" label="Zakłady/Hazard"/>
+ <combo_box.item name="Other" label="Inne"/>
</combo_box>
<text name="abuser_name_title">
Dane osobowe:
diff --git a/indra/newview/skins/default/xui/pl/floater_script_debug.xml b/indra/newview/skins/default/xui/pl/floater_script_debug.xml
index b41add8246..714a600262 100755
--- a/indra/newview/skins/default/xui/pl/floater_script_debug.xml
+++ b/indra/newview/skins/default/xui/pl/floater_script_debug.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<multi_floater name="script debug floater" title="Ostrzeżenie/Błąd Skryptu">
<tab_container name="Preview Tabs">
- <floater label="Skrypt" name="all_scripts" title="[All scripts]" />
+ <floater label="Skrypt" name="all_scripts" title="[ALL SCRIPTS]" />
</tab_container>
</multi_floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_script_preview.xml b/indra/newview/skins/default/xui/pl/floater_script_preview.xml
index 55a18be148..e3e72e15a3 100755
--- a/indra/newview/skins/default/xui/pl/floater_script_preview.xml
+++ b/indra/newview/skins/default/xui/pl/floater_script_preview.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="preview lsl text" title="Skrypt: Skrypt Obrotu">
- <text type="string" length="1" name="desc txt">
+<floater name="preview lsl text" title="SKRYPT: SKRYPT OBROTU">
+ <text name="desc txt">
Opis:
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_script_queue.xml b/indra/newview/skins/default/xui/pl/floater_script_queue.xml
index 70d4669a07..7655f5fcac 100755
--- a/indra/newview/skins/default/xui/pl/floater_script_queue.xml
+++ b/indra/newview/skins/default/xui/pl/floater_script_queue.xml
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="queue" title="Zresetuj PracÄ™ w Toku">
+<floater name="queue" title="ZRESETUJ PRACĘ W TOKU">
<button label="Zamknij" label_selected="Zamknij" name="close" />
</floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_script_search.xml b/indra/newview/skins/default/xui/pl/floater_script_search.xml
index d00f1c267a..255ab4264c 100755
--- a/indra/newview/skins/default/xui/pl/floater_script_search.xml
+++ b/indra/newview/skins/default/xui/pl/floater_script_search.xml
@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script search" title="Szukaj Skryptu">
+<floater name="script search" title="SZUKAJ SKRYPTU">
<check_box label="CapsLoock Nieaktywny" name="case_text" />
<button label="Szukaj" label_selected="Szukaj" name="search_btn" />
<button label="Zamień" label_selected="Zamień" name="replace_btn" />
<button label="Zamień Wszystko" label_selected="Zamień Wszystko"
name="replace_all_btn" />
- <text type="string" length="1" name="txt">
+ <text name="txt">
Szukaj
</text>
- <text type="string" length="1" name="txt2">
+ <text name="txt2">
Zamień
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_select_key.xml b/indra/newview/skins/default/xui/pl/floater_select_key.xml
index aa9e577738..194a6da1bd 100755
--- a/indra/newview/skins/default/xui/pl/floater_select_key.xml
+++ b/indra/newview/skins/default/xui/pl/floater_select_key.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="modal container" title="">
<button label="Anuluj" label_selected="Anuluj" name="Cancel" />
- <text type="string" length="1" name="Save item as:">
+ <text name="Save item as:">
By wybrać wciśnij klawisz
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_sell_land.xml b/indra/newview/skins/default/xui/pl/floater_sell_land.xml
index 94500d0295..a306ec2c34 100755
--- a/indra/newview/skins/default/xui/pl/floater_sell_land.xml
+++ b/indra/newview/skins/default/xui/pl/floater_sell_land.xml
@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="sell land" title="Sell Land">
+<floater name="sell land" title="SELL LAND">
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
<text name="info_parcel_label">
Posiadłość:
</text>
@@ -34,15 +36,9 @@
Wybierz sprzedaż dla kogokolwiek albo dla wybranego kupca.
</text>
<combo_box name="sell_to">
- <combo_item name="--selectone--">
- -- wybierz --
- </combo_item>
- <combo_item name="Anyone">
- Ktokolwiek
- </combo_item>
- <combo_item name="Specificuser:">
- Wybrany kupiec:
- </combo_item>
+ <combo_box.item name="--selectone--" label="wybierz --" />
+ <combo_box.item name="Anyone" label="Ktokolwiek" />
+ <combo_box.item name="Specificuser:" label="Wybrany kupiec:" />
</combo_box>
<button label="Wybierz..." name="sell_to_select_agent" />
<text name="sell_objects_label">
@@ -52,12 +48,8 @@
Przekazywalne obiekty właściciela Posiadłości zmienią właściciela.
</text>
<radio_group name="sell_objects">
- <radio_item name="no">
- Nie, zatrzymaj obiekty
- </radio_item>
- <radio_item name="yes">
- Tak, sprzedaj obiekty razem z Posiadłością
- </radio_item>
+ <radio_item name="no" label="Nie, zatrzymaj obiekty" />
+ <radio_item name="yes" label="Tak, sprzedaj obiekty razem z Posiadłością" />
</radio_group>
<button label="Pokaż Obiekty" name="show_objects" />
<text name="nag_message_label">
@@ -65,4 +57,6 @@
</text>
<button label="Wystaw Ziemię na Sprzedaż" name="sell_btn" />
<button label="Anuluj" name="cancel_btn" />
+ </panel>
+ </scroll_container>
</floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_settings_debug.xml b/indra/newview/skins/default/xui/pl/floater_settings_debug.xml
index 496f8af2db..f87e2edecc 100755
--- a/indra/newview/skins/default/xui/pl/floater_settings_debug.xml
+++ b/indra/newview/skins/default/xui/pl/floater_settings_debug.xml
@@ -1,12 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="settings_debug" title="Ustawienia Usuwania Błędów">
+<floater name="settings_debug" title="USTAWIENIA USUWANIA BÅĘDÓW">
<combo_box name="boolean_combo">
- <combo_item name="TRUE">
- PRAWDA
- </combo_item>
- <combo_item name="FALSE">
- NIEPRAWDA
- </combo_item>
+ <combo_box.item name="TRUE" label="PRAWDA" />
+ <combo_box.item name="FALSE" label="NIEPRAWDA" />
</combo_box>
<color_swatch label="Kolor" name="color_swatch"/>
<spinner label="x" name="val_spinner_1"/>
diff --git a/indra/newview/skins/default/xui/pl/floater_snapshot.xml b/indra/newview/skins/default/xui/pl/floater_snapshot.xml
index 9c011b9a64..c807087170 100755
--- a/indra/newview/skins/default/xui/pl/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/pl/floater_snapshot.xml
@@ -1,18 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Snapshot" title="Wygląd Zdjęcia">
+<floater name="Snapshot" title="WYGLĄD ZDJĘCIA">
<text name="type_label">
Lokacja zapisu
</text>
<radio_group label="Rodzaje zdjęć" name="snapshot_type_radio">
- <radio_item name="postcard">
- Wyślij (email) pocztówkę
- </radio_item>
- <radio_item name="texture">
- Załaduj do szafy ([AMOUNT]L$)
- </radio_item>
- <radio_item name="local">
- Zapisz na dysk
- </radio_item>
+ <radio_item name="postcard" label="Wyślij (email) pocztówkę" />
+ <radio_item name="texture" label="Załaduj do szafy ([AMOUNT]L$)" />
+ <radio_item name="local" label="Zapisz na dysk" />
</radio_group>
<text name="file_size_label">
Rozmiar pliku: [SIZE] KB
@@ -21,12 +15,8 @@
<button label="Wyślij" name="send_btn"/>
<button label="Załaduj (L$[AMOUNT])" name="upload_btn"/>
<flyout_button label="Zapisz" name="save_btn" tool_tip="Zapisz zdjęcie na dysk">
- <flyout_button_item name="save_item">
- Zapisz
- </flyout_button_item>
- <flyout_button_item name="saveas_item">
- Zapisz Jako...
- </flyout_button_item>
+ <flyout_button.item name="save_item" label="Zapisz"/>
+ <flyout_button.item name="saveas_item" label="Zapisz Jako..."/>
</flyout_button>
<button label="Anuluj" name="discard_btn"/>
<button label="Więcej &gt;&gt;" name="more_btn" tool_tip="Ustawienia Zaawansowane"/>
@@ -38,75 +28,33 @@
Format
</text>
<combo_box label="Rozdzielczość" name="postcard_size_combo">
- <combo_item name="CurrentWindow">
- Obecne Okno
- </combo_item>
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
- <combo_item name="Custom">
- Wybierz
- </combo_item>
+ <combo_box.item name="CurrentWindow" label="Obecne Okno" />
+ <combo_box.item name="640x480" label="640x480" />
+ <combo_box.item name="800x600" label="800x600" />
+ <combo_box.item name="1024x768" label="1024x768" />
+ <combo_box.item name="Custom" label="Wybierz" />
</combo_box>
<combo_box label="Rozdzielczość" name="texture_size_combo">
- <combo_item name="CurrentWindow">
- Obecne Okno
- </combo_item>
- <combo_item name="Small(128x128)">
- Mały (128x128)
- </combo_item>
- <combo_item name="Medium(256x256)">
- Åšredni (256x256)
- </combo_item>
- <combo_item name="Large(512x512)">
- Duży (512x512)
- </combo_item>
- <combo_item name="Custom">
- Wybierz
- </combo_item>
+ <combo_box.item name="CurrentWindow" label="Obecne Okno" />
+ <combo_box.item name="Small(128x128)" label="Mały (128x128)" />
+ <combo_box.item name="Medium(256x256)" label="Åšredni (256x256)" />
+ <combo_box.item name="Large(512x512)" label="Duży (512x512)" />
+ <combo_box.item name="Custom" label="Wybierz" />
</combo_box>
<combo_box label="Rozdzielczość" name="local_size_combo">
- <combo_item name="CurrentWindow">
- Obecne Okno
- </combo_item>
- <combo_item name="320x240">
- 320x240
- </combo_item>
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
- <combo_item name="1280x1024">
- 1280x1024
- </combo_item>
- <combo_item name="1600x1200">
- 1600x1200
- </combo_item>
- <combo_item name="Custom">
- Wybierz
- </combo_item>
+ <combo_box.item name="CurrentWindow" label="Obecne Okno" />
+ <combo_box.item name="320x240" label="320x240" />
+ <combo_box.item name="640x480" label="640x480" />
+ <combo_box.item name="800x600" label="800x600" />
+ <combo_box.item name="1024x768" label="1024x768" />
+ <combo_box.item name="1280x1024" label="1280x1024" />
+ <combo_box.item name="1600x1200" label="1600x1200" />
+ <combo_box.item name="Custom" label="Wybierz" />
</combo_box>
<combo_box label="Format" name="local_format_combo">
- <combo_item name="PNG">
- PNG
- </combo_item>
- <combo_item name="JPEG">
- JPEG
- </combo_item>
- <combo_item name="BMP">
- BMP
- </combo_item>
+ <combo_box.item name="PNG" label="PNG" />
+ <combo_box.item name="JPEG" label="JPEG" />
+ <combo_box.item name="BMP" label="BMP" />
</combo_box>
<spinner label="Szer." name="snapshot_width"/>
<spinner label="Wys." name="snapshot_height"/>
@@ -116,15 +64,9 @@
Zapisz:
</text>
<combo_box label="Warstwy Obrazu" name="layer_types">
- <combo_item name="Colors">
- Kolory
- </combo_item>
- <combo_item name="Depth">
- Głębokość
- </combo_item>
- <combo_item name="ObjectMattes">
- Obiekty Åšlepe
- </combo_item>
+ <combo_box.item name="Colors" label="Kolory" />
+ <combo_box.item name="Depth" label="Głębokość" />
+ <combo_box.item name="ObjectMattes" label="Obiekty Åšlepe" />
</combo_box>
<check_box label="Pokaż interfejs na zdjęciu" name="ui_check"/>
<check_box label="Pokaż obiekty HUD na zdjęciu" name="hud_check"/>
diff --git a/indra/newview/skins/default/xui/pl/floater_sound_preview.xml b/indra/newview/skins/default/xui/pl/floater_sound_preview.xml
index 2461aebbcf..0826508fd6 100755
--- a/indra/newview/skins/default/xui/pl/floater_sound_preview.xml
+++ b/indra/newview/skins/default/xui/pl/floater_sound_preview.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Sound Preview" title="dźwięk.wav">
+<floater name="Sound Preview" title="DŹWIĘK.WAV">
<text name="name_label">
Opis:
</text>
diff --git a/indra/newview/skins/default/xui/pl/floater_statistics.xml b/indra/newview/skins/default/xui/pl/floater_statistics.xml
index 933801bbda..b7025e484d 100644
--- a/indra/newview/skins/default/xui/pl/floater_statistics.xml
+++ b/indra/newview/skins/default/xui/pl/floater_statistics.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="stats floater" title="Statystyki"/>
+<floater name="stats floater" title="STATYSTYKI"/>
diff --git a/indra/newview/skins/default/xui/pl/floater_telehub.xml b/indra/newview/skins/default/xui/pl/floater_telehub.xml
index b4cf098878..9f564452a9 100755
--- a/indra/newview/skins/default/xui/pl/floater_telehub.xml
+++ b/indra/newview/skins/default/xui/pl/floater_telehub.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="telehub" title="Obsługa Teleportera" min_height="300" height="300" >
+<floater name="telehub" title="OBSÅUGA TELEPORTERA" min_height="300" height="300" >
<text name="status_text_connected" width="250">
Teleporter połączony z obiektem [OBJECT]
</text>
@@ -12,8 +12,8 @@
<text name="help_text_not_connected">
Wybierz obiekt i kliknij Połącz z teleporterem
</text>
- <button label="Połącz z teleporterem" name="connect_btn" width="122" />
- <button label="Rozłącz" name="disconnect_btn" left="142" width="98"/>
+ <button label="Połącz z teleporterem" name="connect_btn" width="132" />
+ <button label="Rozłącz" name="disconnect_btn" left="152" width="88"/>
<text name="spawn_points_text" width="250">
Punkty Składowe (pozycje - nie obiekty!):
</text>
diff --git a/indra/newview/skins/default/xui/pl/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/pl/floater_texture_ctrl.xml
index 702422f1ba..48366e2b64 100755
--- a/indra/newview/skins/default/xui/pl/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/pl/floater_texture_ctrl.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="texture picker" title="Wybór Tekstury">
+<floater name="texture picker" title="WYBÓR TEKSTURY">
<string name="choose_picture">
Kliknij by wybrać obraz
</string>
- <text length="1" name="Multiple" type="string">
+ <text name="Multiple">
Wiele
</text>
- <text length="1" name="unknown" type="string">
+ <text name="unknown">
Wymiary: [DIMENSIONS]
</text>
<button label="Domyślna" label_selected="Domyślna" name="Default"/>
diff --git a/indra/newview/skins/default/xui/pl/floater_tools.xml b/indra/newview/skins/default/xui/pl/floater_tools.xml
index 380943f4ad..e898c283c5 100755
--- a/indra/newview/skins/default/xui/pl/floater_tools.xml
+++ b/indra/newview/skins/default/xui/pl/floater_tools.xml
@@ -1,35 +1,37 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="toolbox floater" title="">
+<floater name="toolbox floater" title="" short_title="BUDUJ">
<button label="" label_selected="" name="button focus" tool_tip="Zbliżenie"/>
<button label="" label_selected="" name="button move" tool_tip="Przesunięcie"/>
<button label="" label_selected="" name="button edit" tool_tip="Edycja"/>
<button label="" label_selected="" name="button create" tool_tip="Stwórz"/>
<button label="" label_selected="" name="button land" tool_tip="Teren"/>
- <check_box label="Zbliżenie" name="radio zoom"/>
- <volume_slider name="slider zoom"/>
- <check_box label="Obracanie (Ctrl)" name="radio orbit"/>
- <check_box label="Przesunięcie (Ctrl-Shift)" name="radio pan"/>
- <check_box label="Przesuń" name="radio move"/>
- <check_box label="PodnieÅ› (Ctrl)" name="radio lift"/>
- <check_box label="Obróć (Ctrl-Shift)" name="radio spin"/>
- <check_box label="Pozycja" name="radio position"/>
- <check_box label="Obróć (Ctrl)" name="radio rotate"/>
- <check_box label="RozciÄ…gnij (Ctrl-Shift)" name="radio stretch"/>
- <check_box label="Wybierz TeksturÄ™" name="radio select face"/>
+ <radio_group name="focus_radio_group">
+ <radio_item label="Zbliżenie" name="radio zoom"/>
+ <radio_item label="Obracanie (Ctrl)" name="radio orbit"/>
+ <radio_item label="Przesunięcie (Ctrl-Shift)" name="radio pan"/>
+ </radio_group>
+ <radio_group name="move_radio_group">
+ <radio_item label="Przesuń" name="radio move"/>
+ <radio_item label="PodnieÅ› (Ctrl)" name="radio lift"/>
+ <radio_item label="Obróć (Ctrl-Shift)" name="radio spin"/>
+ </radio_group>
+ <radio_group name="edit_radio_group">
+ <radio_item label="Pozycja" name="radio position"/>
+ <radio_item label="Obróć (Ctrl)" name="radio rotate"/>
+ <radio_item label="RozciÄ…gnij (Ctrl-Shift)" name="radio stretch"/>
+ <radio_item label="Wybierz TeksturÄ™" name="radio select face"/>
+ </radio_group>
<check_box label="Edytuj Połączone Części" name="checkbox edit linked parts"/>
<text name="text ruler mode">
Linijka:
</text>
<combo_box name="combobox grid mode">
- <combo_item name="World">
- Åšwiat
- </combo_item>
- <combo_item name="Local">
- Lokalna
- </combo_item>
- <combo_item name="Reference">
- Względna
- </combo_item>
+ <combo_box.item name="World" label="Åšwiat"
+ />
+ <combo_box.item name="Local" label="Lokalna"
+ />
+ <combo_box.item name="Reference" label="Względna"
+ />
</combo_box>
<check_box label="RozciÄ…gnij 2 Strony" name="checkbox uniform"/>
<check_box label="RozciÄ…gnij TeksturÄ™" name="checkbox stretch textures"/>
@@ -57,13 +59,15 @@
<check_box label="Kopiuj zaznaczone" name="checkbox copy selection"/>
<check_box label="Åšrodek" name="checkbox copy centers"/>
<check_box label="Obróć" name="checkbox copy rotates"/>
- <check_box label="Zaznaczanie" name="radio select land"/>
- <check_box label="Prostowanie" name="radio flatten"/>
- <check_box label="Podnoszenie" name="radio raise"/>
- <check_box label="Obniżanie" name="radio lower"/>
- <check_box label="Wygładzanie" name="radio smooth"/>
- <check_box label="Fałdowanie" name="radio noise"/>
- <check_box label="Cofnij modyfikacjÄ™" name="radio revert"/>
+ <radio_group name="land_radio_group">
+ <radio_item label="Zaznaczanie" name="radio select land"/>
+ <radio_item label="Prostowanie" name="radio flatten"/>
+ <radio_item label="Podnoszenie" name="radio raise"/>
+ <radio_item label="Obniżanie" name="radio lower"/>
+ <radio_item label="Wygładzanie" name="radio smooth"/>
+ <radio_item label="Fałdowanie" name="radio noise"/>
+ <radio_item label="Cofnij modyfikacjÄ™" name="radio revert"/>
+ </radio_group>
<button label="Zastosuj" label_selected="Zastosuj" name="button apply to selection" tool_tip="Modyfikuj zaznaczony teren"/>
<text name="Bulldozer:">
Burzenie:
@@ -71,7 +75,7 @@
<text name="Dozer Size:">
Rozmiar
</text>
- <text length="1" name="Strength:" type="string">
+ <text name="Strength:">
Siła
</text>
<volume_slider name="slider force"/>
@@ -115,9 +119,7 @@
<text name="Permissions:">
Prawa:
</text>
- <text name="perm_modify">
- Nie masz prawda do modyfikacji tego obiektu
- </text>
+
<check_box label="Udostępnij grupie" name="checkbox share with group" tool_tip="Pozwól członkom grupy przesuwać, modyfikować, kopiować i usuwać."/>
<string name="text deed continued">
Przypisz...
@@ -134,49 +136,35 @@
Cena: L$
</text>
<line_editor name="Edit Cost"/>
- <radio_group name="sale type">
- <radio_item name="Original">
- Orginał
- </radio_item>
- <radio_item name="Copy">
- Kopia
- </radio_item>
- <radio_item name="Contents">
- Zawartość
- </radio_item>
- </radio_group>
- <text name="Next owner can:">
- Następny właściciel:
- </text>
- <check_box label="Zmienia" name="checkbox next owner can modify"/>
- <check_box label="Kopiuje" name="checkbox next owner can copy"/>
- <check_box label="Oddaje/Sprzedaje" name="checkbox next owner can transfer"/>
+ <combo_box name="sale type">
+ <combo_box.item label="Kopia" name="Copy"/>
+ <combo_box.item label="Zawartość" name="Contents"/>
+ <combo_box.item label="Orginał" name="Original"/>
+ </combo_box>
+
<text name="label click action">
Lewe Kliknięcie:
</text>
<combo_box name="clickaction">
- <combo_item name="Touch/grab(default)">
- Dotknij (domyślne)
- </combo_item>
- <combo_item name="Sitonobject">
- Usiądź na Obiekcie
- </combo_item>
- <combo_item name="Buyobject">
- Kup Obiekt
- </combo_item>
- <combo_item name="Payobject">
- Zapłać Obiektowi
- </combo_item>
- <combo_item name="Open">
- Otwórz
- </combo_item>
- <combo_item name="Play">
- Odtwarzaj Media
- </combo_item>
- <combo_item name="Opemmedia">
- Otwrórz Media
- </combo_item>
+ <combo_box.item name="Touch/grab(default)" label="Dotknij (domyślne)"
+ />
+ <combo_box.item name="Sitonobject" label="Usiądź na Obiekcie"
+ />
+ <combo_box.item name="Buyobject" label="Kup Obiekt"
+ />
+ <combo_box.item name="Payobject" label="Zapłać Obiektowi"
+ />
+ <combo_box.item name="Open" label="Otwórz"
+ />
+ <combo_box.item name="Play" label="Odtwarzaj Media"
+ />
+ <combo_box.item name="Opemmedia" label="Otwrórz Media"
+ />
</combo_box>
+ <panel name="perms_build">
+ <text name="perm_modify">
+ Nie masz prawda do modyfikacji tego obiektu
+ </text>
<text name="B:">
B:
</text>
@@ -195,29 +183,36 @@
<text name="F:">
F:
</text>
+ <text name="Next owner can:">
+ Następny właściciel:
+ </text>
+ <check_box label="Zmienia" name="checkbox next owner can modify"/>
+ <check_box label="Kopiuje" name="checkbox next owner can copy"/>
+ <check_box name="checkbox next owner can transfer"/>
+ </panel>
<string name="text modify info 1">
- Możesz modyfikować ten obiekt.
+ Możesz modyfikować ten obiekt
</string>
<string name="text modify info 2">
- Możesz modyfikować te obiekty.
+ Możesz modyfikować te obiekty
</string>
<string name="text modify info 3">
- Nie możesz modyfikować tego obiektu.
+ Nie możesz modyfikować tego obiektu
</string>
<string name="text modify info 4">
- Nie możesz modyfikować tych obieków.
+ Nie możesz modyfikować tych obieków
</string>
<string name="text modify warning">
- Musisz zaznaczyć cały obiekt by ustawić prawa.
+ Musisz zaznaczyć cały obiekt by ustawić prawa
</string>
<string name="Cost Default">
- Cena: L$
+ Cena: L$
</string>
<string name="Cost Total">
- Cena Całości: L$
+ Cena Całości: L$
</string>
<string name="Cost Per Unit">
- Cena Za: L$
+ Cena Za: L$
</string>
<string name="Cost Mixed">
Cena Mieszana
@@ -259,62 +254,47 @@
Materiał
</text>
<combo_box name="material">
- <combo_item name="Stone">
- Kamień
- </combo_item>
- <combo_item name="Metal">
- Metal
- </combo_item>
- <combo_item name="Glass">
- Szkło
- </combo_item>
- <combo_item name="Wood">
- Drewno
- </combo_item>
- <combo_item name="Flesh">
- Ciało
- </combo_item>
- <combo_item name="Plastic">
- Plastik
- </combo_item>
- <combo_item name="Rubber">
- Guma
- </combo_item>
+ <combo_box.item name="Stone" label="Kamień"
+ />
+ <combo_box.item name="Metal" label="Metal"
+ />
+ <combo_box.item name="Glass" label="Szkło"
+ />
+ <combo_box.item name="Wood" label="Drewno"
+ />
+ <combo_box.item name="Flesh" label="Ciało"
+ />
+ <combo_box.item name="Plastic" label="Plastik"
+ />
+ <combo_box.item name="Rubber" label="Guma"
+ />
</combo_box>
<text name="label basetype">
Rodzaj Bloku Budowalnego
</text>
<combo_box name="comboBaseType">
- <combo_item name="Box">
- Klocek
- </combo_item>
- <combo_item name="Cylinder">
- Walec
- </combo_item>
- <combo_item name="Prism">
- Graniastosłup
- </combo_item>
- <combo_item name="Sphere">
- Kula
- </combo_item>
- <combo_item name="Torus">
- Torus
- </combo_item>
- <combo_item name="Tube">
- Rura
- </combo_item>
- <combo_item name="Ring">
- Pierścień
- </combo_item>
- <combo_item name="Sculpted">
- Skulpty
- </combo_item>
+ <combo_box.item name="Box" label="Klocek"
+ />
+ <combo_box.item name="Cylinder" label="Walec"
+ />
+ <combo_box.item name="Prism" label="Graniastosłup"
+ />
+ <combo_box.item name="Sphere" label="Kula"
+ />
+ <combo_box.item name="Torus" label="Torus"
+ />
+ <combo_box.item name="Tube" label="Rura"
+ />
+ <combo_box.item name="Ring" label="Pierścień"
+ />
+ <combo_box.item name="Sculpted" label="Skulpty"
+ />
</combo_box>
<text name="text cut">
- Wykrój
+ Wykrój początek i koniec
</text>
- <spinner label="B" name="cut begin"/>
- <spinner label="E" name="cut end"/>
+ <spinner label="P" name="cut begin"/>
+ <spinner label="K" name="cut end"/>
<text name="text hollow">
Wydrążenie
</text>
@@ -327,24 +307,20 @@
Kształt Wydrążenia
</text>
<combo_box name="hole">
- <combo_item name="Default">
- Domyślny
- </combo_item>
- <combo_item name="Circle">
- Koło
- </combo_item>
- <combo_item name="Square">
- Kwadrat
- </combo_item>
- <combo_item name="Triangle">
- Trójkąt
- </combo_item>
+ <combo_box.item name="Default" label="Domyślny"
+ />
+ <combo_box.item name="Circle" label="Koło"
+ />
+ <combo_box.item name="Square" label="Kwadrat"
+ />
+ <combo_box.item name="Triangle" label="Trójkąt"
+ />
</combo_box>
<text name="text twist">
Skręcenie
</text>
- <spinner label="B" name="Twist Begin"/>
- <spinner label="E" name="Twist End"/>
+ <spinner label="P" name="Twist Begin"/>
+ <spinner label="K" name="Twist End"/>
<text name="scale_taper">
Zwężenie
</text>
@@ -367,8 +343,8 @@
<text name="advanced_slice">
Przetnij poczÄ…tek i koniec
</text>
- <spinner label="B" name="Path Limit Begin"/>
- <spinner label="E" name="Path Limit End"/>
+ <spinner label="P" name="Path Limit Begin"/>
+ <spinner label="K" name="Path Limit End"/>
<text name="text taper2">
Zwężenie
</text>
@@ -389,21 +365,16 @@
Typ Ścięgna
</text>
<combo_box name="sculpt type control">
- <combo_item name="None">
- (żadne)
- </combo_item>
- <combo_item name="Sphere">
- Kula
- </combo_item>
- <combo_item name="Torus">
- Torus
- </combo_item>
- <combo_item name="Plane">
- PÅ‚aczyzna
- </combo_item>
- <combo_item name="Cylinder">
- Walec
- </combo_item>
+ <combo_box.item name="None" label="(żadne)"
+ />
+ <combo_box.item name="Sphere" label="Kula"
+ />
+ <combo_box.item name="Torus" label="Torus"
+ />
+ <combo_box.item name="Plane" label="PÅ‚aczyzna"
+ />
+ <combo_box.item name="Cylinder" label="Walec"
+ />
</combo_box>
</panel>
<panel label="Atrybuty" name="Features">
@@ -434,101 +405,77 @@
<panel label="Tekstura" name="Texture">
<texture_picker label="Tekstura" name="texture control" tool_tip="Kliknij by wybrać obraz"/>
<color_swatch label="Kolor" name="colorswatch" tool_tip="Kliknij by wybrać kolor"/>
- <text name="color trans">
- Przezroczystość %
+ <text name="color trans" left="170" width="99">
+ Przezroczystość%
</text>
- <spinner name="ColorTrans"/>
- <text name="glow label">
+ <spinner left="170" name="ColorTrans"/>
+ <text name="glow label" left="170">
Blask
</text>
- <spinner name="glow"/>
- <check_box label="Jaskrawość" name="checkbox fullbright"/>
+ <spinner left="170" name="glow"/>
+ <check_box label="Jaskrawość" name="checkbox fullbright" left="170"/>
<text name="tex gen">
Mapowanie
</text>
<combo_box name="combobox texgen">
- <combo_item name="Default">
- Domyślne
- </combo_item>
- <combo_item name="Planar">
- Planarne
- </combo_item>
+ <combo_box.item name="Default" label="Domyślne"
+ />
+ <combo_box.item name="Planar" label="Planarne"
+ />
</combo_box>
<text name="label shininess">
Połysk
</text>
<combo_box name="combobox shininess">
- <combo_item name="None">
- Żadny
- </combo_item>
- <combo_item name="Low">
- Niski
- </combo_item>
- <combo_item name="Medium">
- Åšredni
- </combo_item>
- <combo_item name="High">
- Wysoki
- </combo_item>
+ <combo_box.item name="None" label="Żadny"
+ />
+ <combo_box.item name="Low" label="Niski"
+ />
+ <combo_box.item name="Medium" label="Åšredni"
+ />
+ <combo_box.item name="High" label="Wysoki"
+ />
</combo_box>
<text name="label bumpiness">
Powierzchnia
</text>
<combo_box name="combobox bumpiness">
- <combo_item name="None">
- Żadna
- </combo_item>
- <combo_item name="Brightness">
- Najjaśniejsza
- </combo_item>
- <combo_item name="Darkness">
- Najciemniejsza
- </combo_item>
- <combo_item name="woodgrain">
- Drewniano-ziarnista
- </combo_item>
- <combo_item name="bark">
- Kory Drzewa
- </combo_item>
- <combo_item name="bricks">
- Cegieł
- </combo_item>
- <combo_item name="checker">
- Planszy Szachowej
- </combo_item>
- <combo_item name="concrete">
- Betonu
- </combo_item>
- <combo_item name="crustytile">
- PÅ‚ytki/Kafelki
- </combo_item>
- <combo_item name="cutstone">
- Kamienia
- </combo_item>
- <combo_item name="discs">
- Dysku CD
- </combo_item>
- <combo_item name="gravel">
- Żwiru
- </combo_item>
- <combo_item name="petridish">
- Skamieliny
- </combo_item>
- <combo_item name="siding">
- Brzegu
- </combo_item>
- <combo_item name="stonetile">
- PÅ‚ytki Kamiennej
- </combo_item>
- <combo_item name="stucco">
- Stucco
- </combo_item>
- <combo_item name="suction">
- Suction
- </combo_item>
- <combo_item name="weave">
- Fali
- </combo_item>
+ <combo_box.item name="None" label="Żadna"
+ />
+ <combo_box.item name="Brightness" label="Najjaśniejsza"
+ />
+ <combo_box.item name="Darkness" label="Najciemniejsza"
+ />
+ <combo_box.item name="woodgrain" label="Drewniano-ziarnista"
+ />
+ <combo_box.item name="bark" label="Kory Drzewa"
+ />
+ <combo_box.item name="bricks" label="Cegieł"
+ />
+ <combo_box.item name="checker" label="Planszy Szachowej"
+ />
+ <combo_box.item name="concrete" label="Betonu"
+ />
+ <combo_box.item name="crustytile" label="PÅ‚ytki/Kafelki"
+ />
+ <combo_box.item name="cutstone" label="Kamienia"
+ />
+ <combo_box.item name="discs" label="Dysku CD"
+ />
+ <combo_box.item name="gravel" label="Żwiru"
+ />
+ <combo_box.item name="petridish" label="Skamieliny"
+ />
+ <combo_box.item name="siding" label="Brzegu"
+ />
+ <combo_box.item name="stonetile" label="PÅ‚ytki Kamiennej"
+ />
+ <combo_box.item name="stucco" label="Stucco"
+ />
+ <combo_box.item name="suction" label="Suction"
+ />
+ <combo_box.item name="weave" label="Fali"
+ />
</combo_box>
<text name="tex scale">
Ilość powtórzeń
@@ -561,11 +508,11 @@
Dopasuj Teksturę Mediów
(najpierw załaduj)
</text>
- <button label="Dopasuj" label_selected="Dopasuj" name="button align"/>
+ <button label="Dopasuj" label_selected="Dopasuj" name="button align" left="160"/>
</panel>
<panel label="Treść" name="Contents">
- <button label="Nowy Skrypt" label_selected="Nowy Skrypt..." name="button new script"/>
- <button label="Prawa..." name="button permissions"/>
+ <button label="Nowy Skrypt" label_selected="Nowy Skrypt" name="button new script"/>
+ <button label="Prawa" name="button permissions"/>
</panel>
</tab_container>
<panel name="land info panel">
@@ -579,56 +526,56 @@
Obszar: [AREA] m
</text>
<button label="O Posiadłości..." label_selected="O Posiadłości..." name="button about land"/>
- <check_box label="Pokaż Właścicieli" name="checkbox show owners" tool_tip="Pokoloruj posiadłości zgodnie z przynależnością do właściciela"/>
+ <check_box label="Pokaż Właścicieli" name="checkbox show owners" tool_tip="Pokoloruj posiadłości zgodnie z przynależnością do właściciela: &#10;&#10;Zielony = Twoja Posiadłość &#10;Morski = Posiadłość Twojej Grupy &#10;Czerwony = Posiadłości Innych &#10;Żółty = Na Sprzedaż &#10;Fioletowy = Na Aukcję &#10;Szary = Publiczna"/>
<button label="?" label_selected="?" name="button show owners help" left_delta="120"/>
<text name="label_parcel_modify">
Modyfikuj Posiadłość
</text>
- <button label="Podziel..." label_selected="Podziel..." name="button subdivide land"/>
- <button label="ZÅ‚Ä…cz..." label_selected="ZÅ‚Ä…cz..." name="button join land"/>
+ <button label="Podziel" label_selected="Podziel" name="button subdivide land"/>
+ <button label="ZÅ‚Ä…cz" label_selected="ZÅ‚Ä…cz" name="button join land"/>
<text name="label_parcel_trans">
Transakcje na posiadłości
</text>
- <button label="Kup..." label_selected="Kup..." name="button buy land"/>
- <button label="Anuluj..." label_selected="Anuluj..." name="button abandon land"/>
+ <button label="Kup" label_selected="Kup" name="button buy land"/>
+ <button label="Anuluj" label_selected="Anuluj" name="button abandon land"/>
</panel>
- <string name="status_rotate">
+ <floater.string name="status_rotate">
Przeciągaj kolorowe pierścienie żeby obracać obiekt
- </string>
- <string name="status_scale">
+ </floater.string>
+ <floater.string name="status_scale">
Kliknij i przeciągaj żeby rozciągnąć wybraną stronę
- </string>
- <string name="status_move">
+ </floater.string>
+ <floater.string name="status_move">
Wybierz opcjÄ™:
- </string>
- <string name="status_modifyland">
+ </floater.string>
+ <floater.string name="status_modifyland">
Kliknij i przytrzymaj żeby modyfikować teren
- </string>
- <string name="status_camera">
+ </floater.string>
+ <floater.string name="status_camera">
Kliknij i przeciągnij żeby zmienić widok
- </string>
- <string name="status_grab">
+ </floater.string>
+ <floater.string name="status_grab">
Przeciągnij by przesunąć, wybierz Ctrl by podnieść, wybierz Ctrl-Shift by obrócić
- </string>
- <string name="status_place">
+ </floater.string>
+ <floater.string name="status_place">
Kliknij in-world by zacząć budować
- </string>
- <string name="status_selectland">
+ </floater.string>
+ <floater.string name="status_selectland">
Edytowanie Terenu:
- </string>
- <string name="grid_screen_text">
+ </floater.string>
+ <floater.string name="grid_screen_text">
Widok
- </string>
- <string name="grid_local_text">
+ </floater.string>
+ <floater.string name="grid_local_text">
Lokalna
- </string>
- <string name="grid_world_text">
+ </floater.string>
+ <floater.string name="grid_world_text">
Åšwiat
- </string>
- <string name="grid_reference_text">
+ </floater.string>
+ <floater.string name="grid_reference_text">
Względa
- </string>
- <string name="grid_attachment_text">
+ </floater.string>
+ <floater.string name="grid_attachment_text">
Załączniki
- </string>
+ </floater.string>
</floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_top_objects.xml b/indra/newview/skins/default/xui/pl/floater_top_objects.xml
index 44d838035d..e7299b0abb 100755
--- a/indra/newview/skins/default/xui/pl/floater_top_objects.xml
+++ b/indra/newview/skins/default/xui/pl/floater_top_objects.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="top_objects" title="Åadowanie...">
+<floater name="top_objects" title="ÅADOWANIE...">
<text name="title_text">
Åadowanie...
</text>
diff --git a/indra/newview/skins/default/xui/pl/floater_tos.xml b/indra/newview/skins/default/xui/pl/floater_tos.xml
index d05a3c246a..b9a146df22 100755
--- a/indra/newview/skins/default/xui/pl/floater_tos.xml
+++ b/indra/newview/skins/default/xui/pl/floater_tos.xml
@@ -5,7 +5,7 @@
<check_box label="Zgadzam siÄ™ na Warunki Serwisu (Terms of Service)" name="agree_chk" />
<text name="tos_heading">
Proszę dokładnie przeczytać następujące Warunki Serwisu (Terms of Service). Musisz
-zaakceptować umową żeby kontynuować logowanie do Second Life.
+zaakceptować umowę żeby kontynuować logowanie do [SECOND_LIFE].
</text>
<text_editor name="tos_text">
TOS_TEXT
diff --git a/indra/newview/skins/default/xui/pl/floater_water.xml b/indra/newview/skins/default/xui/pl/floater_water.xml
index 61ffce4177..7333633c1d 100755
--- a/indra/newview/skins/default/xui/pl/floater_water.xml
+++ b/indra/newview/skins/default/xui/pl/floater_water.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Water Floater" title="Zaawansowany Edytor Wody">
- <text type="string" length="1" name="KeyFramePresetsText">
+<floater name="Water Floater" title="ZAAWANSOWANY EDYTOR WODY">
+ <text name="KeyFramePresetsText">
Ustawienia Wody:
</text>
<button label="Nowe" label_selected="Nowe" name="WaterNewPreset" />
@@ -8,89 +8,89 @@
<button label="Usuń" label_selected="Usuń" name="WaterDeletePreset" />
<tab_container name="Water Tabs">
<panel label="Ustawienia" name="Settings">
- <text type="string" length="1" name="BHText">
+ <text name="BHText">
Kolor Podwodnej Mgły
</text>
<button label="?" name="WaterFogColorHelp" />
<color_swatch label="" name="WaterFogColor" tool_tip="Kliknij by wybrać kolor" />
- <text type="string" length="1" name="WaterFogDensText">
+ <text name="WaterFogDensText">
Wykładnik Gęstości Mgły
</text>
<button label="?" name="WaterFogDensityHelp" />
<slider label="" name="WaterFogDensity" />
- <text type="string" length="1" name="WaterUnderWaterFogModText">
+ <text name="WaterUnderWaterFogModText">
Modyfikator Mgły
</text>
<button label="?" name="WaterUnderWaterFogModHelp" />
<slider label="" name="WaterUnderWaterFogMod" />
- <text type="string" length="1" name="BDensText">
+ <text name="BDensText">
Skala Zmarszczeń
</text>
<button label="?" name="WaterNormalScaleHelp" />
- <text type="string" length="1" name="BHText2">
+ <text name="BHText2">
1
</text>
- <text type="string" length="1" name="BHText3">
+ <text name="BHText3">
2
</text>
- <text type="string" length="1" name="BHText4">
+ <text name="BHText4">
3
</text>
<slider label="" name="WaterNormalScaleX" />
<slider label="" name="WaterNormalScaleY" />
<slider label="" name="WaterNormalScaleZ" />
- <text type="string" length="1" name="HDText">
+ <text name="HDText">
Skala Fresnela
</text>
<button label="?" name="WaterFresnelScaleHelp" />
<slider label="" name="WaterFresnelScale" />
- <text type="string" length="1" name="FresnelOffsetText">
+ <text name="FresnelOffsetText">
Przesunięcie Fresnela
</text>
<button label="?" name="WaterFresnelOffsetHelp" />
<slider label="" name="WaterFresnelOffset" />
- <text type="string" length="1" name="DensMultText">
+ <text name="DensMultText">
Górna Refrakcja
</text>
<button label="?" name="WaterScaleAboveHelp" />
<slider label="" name="WaterScaleAbove" />
- <text type="string" length="1" name="WaterScaleBelowText">
+ <text name="WaterScaleBelowText">
Dolna Refrakcja
</text>
<button label="?" name="WaterScaleBelowHelp" />
<slider label="" name="WaterScaleBelow" />
- <text type="string" length="1" name="MaxAltText">
+ <text name="MaxAltText">
Mnożnik Rozmycia
</text>
<button label="?" name="WaterBlurMultiplierHelp" />
<slider label="" name="WaterBlurMult" />
</panel>
<panel label="Rysowanie" name="Waves">
- <text type="string" length="1" name="BHText">
+ <text name="BHText">
Kierunek Dużych Fal
</text>
<button label="?" name="WaterWave1Help" />
- <text type="string" length="1" name="WaterWave1DirXText">
+ <text name="WaterWave1DirXText">
X
</text>
- <text type="string" length="1" name="WaterWave1DirYText">
+ <text name="WaterWave1DirYText">
Y
</text>
<slider label="" name="WaterWave1DirX" />
<slider label="" name="WaterWave1DirY" />
- <text type="string" length="1" name="BHText2">
+ <text name="BHText2">
Kierunek Małych Fal
</text>
<button label="?" name="WaterWave2Help" />
- <text type="string" length="1" name="WaterWave2DirXText">
+ <text name="WaterWave2DirXText">
X
</text>
- <text type="string" length="1" name="WaterWave2DirYText">
+ <text name="WaterWave2DirYText">
Y
</text>
<slider label="" name="WaterWave2DirX" />
<slider label="" name="WaterWave2DirY" />
- <text type="string" length="1" name="BHText3">
+ <text name="BHText3">
Mapa Normalnych
</text>
<button label="?" name="WaterNormalMapHelp" />
diff --git a/indra/newview/skins/default/xui/pl/floater_wearable_save_as.xml b/indra/newview/skins/default/xui/pl/floater_wearable_save_as.xml
index b9071c0df9..2d4582392c 100755
--- a/indra/newview/skins/default/xui/pl/floater_wearable_save_as.xml
+++ b/indra/newview/skins/default/xui/pl/floater_wearable_save_as.xml
@@ -2,7 +2,7 @@
<floater name="modal container" title="">
<button label="Zapisz" label_selected="Zapisz" name="Save" />
<button label="Anuluj" label_selected="Anuluj" name="Cancel" />
- <text type="string" length="1" name="Save item as:">
+ <text name="Save item as:">
Zachowaj jako:
</text>
<line_editor name="name ed">
diff --git a/indra/newview/skins/default/xui/pl/floater_windlight_options.xml b/indra/newview/skins/default/xui/pl/floater_windlight_options.xml
index 2a9d1dff24..86ef9300da 100755
--- a/indra/newview/skins/default/xui/pl/floater_windlight_options.xml
+++ b/indra/newview/skins/default/xui/pl/floater_windlight_options.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="WindLight floater" title="Zaawansowany Edytor Nieba">
- <text type="string" length="1" name="KeyFramePresetsText">
+<floater name="WindLight floater" title="ZAAWANSOWANY EDYTOR NIEBA">
+ <text name="KeyFramePresetsText">
Ustawienia Nieba:
</text>
<button label="Nowe" label_selected="Nowe" name="WLNewPreset" />
@@ -10,210 +10,210 @@
name="WLDayCycleMenuButton" />
<tab_container name="WindLight Tabs">
<panel label="Atmosfera" name="Atmosphere">
- <text type="string" length="1" name="BHText">
+ <text name="BHText">
Horyzont Błękitu
</text>
<button label="?" name="WLBlueHorizonHelp" />
- <text type="string" length="1" name="BHText2">
+ <text name="BHText2">
R
</text>
- <text type="string" length="1" name="BHText3">
+ <text name="BHText3">
G
</text>
- <text type="string" length="1" name="BHText4">
+ <text name="BHText4">
B
</text>
- <text type="string" length="1" name="BHText5">
+ <text name="BHText5">
I
</text>
<slider label="" name="WLBlueHorizonR" />
<slider label="" name="WLBlueHorizonG" />
<slider label="" name="WLBlueHorizonB" />
<slider label="" name="WLBlueHorizonI" />
- <text type="string" length="1" name="BDensText">
+ <text name="BDensText">
Horyzont Zamglenia
</text>
<button label="?" name="WLHazeHorizonHelp" />
<slider label="" name="WLHazeHorizon" />
- <text type="string" length="1" name="BDensText2">
+ <text name="BDensText2">
Gęstość Błękitu
</text>
<button label="?" name="WLBlueDensityHelp" />
- <text type="string" length="1" name="BHText6">
+ <text name="BHText6">
R
</text>
- <text type="string" length="1" name="BHText7">
+ <text name="BHText7">
G
</text>
- <text type="string" length="1" name="BHText8">
+ <text name="BHText8">
B
</text>
- <text type="string" length="1" name="BHText9">
+ <text name="BHText9">
I
</text>
<slider label="" name="WLBlueDensityR" />
<slider label="" name="WLBlueDensityG" />
<slider label="" name="WLBlueDensityB" />
<slider label="" name="WLBlueDensityI" />
- <text type="string" length="1" name="HDText">
+ <text name="HDText">
Gęstość Zamglenia
</text>
<button label="?" name="WLHazeDensityHelp" />
<slider label="" name="WLHazeDensity" />
- <text type="string" length="1" name="DensMultText">
+ <text name="DensMultText">
Mnożnik Gęsości
</text>
<button label="?" name="WLDensityMultHelp" />
<slider label="" name="WLDensityMult" />
- <text type="string" length="1" name="WLDistanceMultText">
+ <text name="WLDistanceMultText">
Mnożnik Dystansu
</text>
<button label="?" name="WLDistanceMultHelp" />
<slider label="" name="WLDistanceMult" />
- <text type="string" length="1" name="MaxAltText">
+ <text name="MaxAltText">
Max Wysokość
</text>
<button label="?" name="WLMaxAltitudeHelp" />
<slider label="" name="WLMaxAltitude" />
</panel>
<panel label="Światło" name="Lighting">
- <text type="string" length="1" name="SLCText">
+ <text name="SLCText">
Kolor Słońca/Księżyca
</text>
<button label="?" name="WLSunlightColorHelp" />
- <text type="string" length="1" name="BHText">
+ <text name="BHText">
R
</text>
- <text type="string" length="1" name="BHText2">
+ <text name="BHText2">
G
</text>
- <text type="string" length="1" name="BHText3">
+ <text name="BHText3">
B
</text>
- <text type="string" length="1" name="BHText4">
+ <text name="BHText4">
I
</text>
<slider label="" name="WLSunlightR" />
<slider label="" name="WLSunlightG" />
<slider label="" name="WLSunlightB" />
<slider label="" name="WLSunlightI" />
- <text type="string" length="1" name="TODText">
+ <text name="TODText">
Pozycja Słońca/Księżyca
</text>
<button label="?" name="WLTimeOfDayHelp" />
<slider label="" name="WLSunAngle" />
- <text type="string" length="1" name="WLAmbientText">
+ <text name="WLAmbientText">
Otoczenie
</text>
<button label="?" name="WLAmbientHelp" />
- <text type="string" length="1" name="BHText5">
+ <text name="BHText5">
R
</text>
- <text type="string" length="1" name="BHText6">
+ <text name="BHText6">
G
</text>
- <text type="string" length="1" name="BHText7">
+ <text name="BHText7">
B
</text>
- <text type="string" length="1" name="BHText8">
+ <text name="BHText8">
I
</text>
<slider label="" name="WLAmbientR" />
<slider label="" name="WLAmbientG" />
<slider label="" name="WLAmbientB" />
<slider label="" name="WLAmbientI" />
- <text type="string" length="1" name="WLEastAngleText">
+ <text name="WLEastAngleText">
Pozycja Wschodu
</text>
<button label="?" name="WLEastAngleHelp" />
<slider label="" name="WLEastAngle" />
- <text type="string" length="1" name="SunGlowText">
+ <text name="SunGlowText">
Blask Słońca
</text>
<button label="?" name="WLSunGlowHelp" />
<slider label="Ostrość" name="WLGlowB" />
<slider label="Rozmiar" name="WLGlowR" />
- <text type="string" length="1" name="SceneGammaText">
+ <text name="SceneGammaText">
Jasność Obrazu
</text>
<button label="?" name="WLSceneGammaHelp" />
<slider label="" name="WLGamma" />
- <text type="string" length="1" name="WLStarText">
+ <text name="WLStarText">
Blask Gwiazd
</text>
<button label="?" name="WLStarBrightnessHelp" />
<slider label="" name="WLStarAlpha" />
</panel>
<panel label="Chmury" name="Clouds">
- <text type="string" length="1" name="WLCloudColorText">
+ <text name="WLCloudColorText">
Kolor Chmur
</text>
<button label="?" name="WLCloudColorHelp" />
- <text type="string" length="1" name="BHText">
+ <text name="BHText">
R
</text>
- <text type="string" length="1" name="BHText2">
+ <text name="BHText2">
G
</text>
- <text type="string" length="1" name="BHText3">
+ <text name="BHText3">
B
</text>
- <text type="string" length="1" name="BHText4">
+ <text name="BHText4">
I
</text>
<slider label="" name="WLCloudColorR" />
<slider label="" name="WLCloudColorG" />
<slider label="" name="WLCloudColorB" />
<slider label="" name="WLCloudColorI" />
- <text type="string" length="1" name="WLCloudColorText2">
+ <text name="WLCloudColorText2">
Chmury (XY/Gęstość)
</text>
<button label="?" name="WLCloudDensityHelp" />
- <text type="string" length="1" name="BHText5">
+ <text name="BHText5">
X
</text>
- <text type="string" length="1" name="BHText6">
+ <text name="BHText6">
Y
</text>
- <text type="string" length="1" name="BHText7">
+ <text name="BHText7">
G
</text>
<slider label="" name="WLCloudX" />
<slider label="" name="WLCloudY" />
<slider label="" name="WLCloudDensity" />
- <text type="string" length="1" name="WLCloudCoverageText">
+ <text name="WLCloudCoverageText">
Pokrycie Chmur
</text>
<button label="?" name="WLCloudCoverageHelp" />
<slider label="" name="WLCloudCoverage" />
- <text type="string" length="1" name="WLCloudScaleText">
+ <text name="WLCloudScaleText">
Skala Chmur
</text>
<button label="?" name="WLCloudScaleHelp" />
<slider label="" name="WLCloudScale" />
- <text type="string" length="1" name="WLCloudDetailText">
+ <text name="WLCloudDetailText">
Szczegóły (XY/Gęstość)
</text>
<button label="?" name="WLCloudDetailHelp" />
- <text type="string" length="1" name="BHText8">
+ <text name="BHText8">
X
</text>
- <text type="string" length="1" name="BHText9">
+ <text name="BHText9">
Y
</text>
- <text type="string" length="1" name="BHText10">
+ <text name="BHText10">
G
</text>
<slider label="" name="WLCloudDetailX" />
<slider label="" name="WLCloudDetailY" />
<slider label="" name="WLCloudDetailDensity" />
- <text type="string" length="1" name="WLCloudScrollXText">
+ <text name="WLCloudScrollXText">
Przewijanie Chmur X
</text>
<button label="?" name="WLCloudScrollXHelp" />
<check_box label="Zablokuj" name="WLCloudLockX" />
<slider label="" name="WLCloudScrollX" />
- <text type="string" length="1" name="WLCloudScrollYText">
+ <text name="WLCloudScrollYText">
Przewijanie Chmur Y
</text>
<button label="?" name="WLCloudScrollYHelp" />
diff --git a/indra/newview/skins/default/xui/pl/floater_world_map.xml b/indra/newview/skins/default/xui/pl/floater_world_map.xml
index 46e6091b33..36e3b0651b 100755
--- a/indra/newview/skins/default/xui/pl/floater_world_map.xml
+++ b/indra/newview/skins/default/xui/pl/floater_world_map.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="worldmap" title="Mapa Åšwiata">
+<floater name="worldmap" title="MAPA ÅšWIATA">
<tab_container name="maptab">
<panel label="Obiekty" name="objects_mapview"/>
<panel label="Teren" name="terrain_mapview"/>
@@ -30,14 +30,10 @@
<check_box label="&apos;Adult&apos;" name="event_adult_chk"/>
<icon bottom="-196" name="avatar_icon"/>
<combo_box label="Dostępni Znajomi" name="friend combo" tool_tip="Znajomi na mapie">
- <combo_item name="none_selected">
- Dostępni Znajomi
- </combo_item>
+ <combo_box.item name="item1" label="Dostępni Znajomi" />
</combo_box>
<combo_box label="Zapisane Miejsca" name="landmark combo" tool_tip="Zapisane miejsca na mapie">
- <combo_item name="none_selected">
- Zapisane Miejsca
- </combo_item>
+ <combo_box.item name="item1" label="Zapisane Miejsca" />
</combo_box>
<line_editor label="Szukaj po nazwie regionu" name="location" tool_tip="Wpisz nazwÄ™ regionu"/>
<button label="Szukaj" name="DoSearch" tool_tip="Wyszukiwaie regionu"/>
@@ -58,6 +54,6 @@
<button label="Pokaż Cel" label_selected="Pokaż Cel" name="Show Destination" tool_tip="Wycentruj miejsce celu na mapie"/>
<button label="Wyczyść" label_selected="Wyczyść" name="Clear" tool_tip="Stop tracking"/>
<button label="Pokaż moje miejsce" label_selected="Pokaż moje miejsce" name="Show My Location" tool_tip="Wycentruj pozcję awatara na mapie"/>
- <button label="Kopiuj SLURL do schowka" name="copy_slurl" tool_tip="Kopie SLURL obecnego miejsca będę mogły zostać użyte na stronie internetowej."/>
+ <button label="Kopiuj SLurl do schowka" name="copy_slurl" tool_tip="Kopie SLurl obecnego miejsca będę mogły zostać użyte na stronie internetowej."/>
<slider label="Skala" name="zoom slider"/>
</floater>
diff --git a/indra/newview/skins/default/xui/pl/language_settings.xml b/indra/newview/skins/default/xui/pl/language_settings.xml
new file mode 100644
index 0000000000..71418d446a
--- /dev/null
+++ b/indra/newview/skins/default/xui/pl/language_settings.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- This file contains strings that used to be hardcoded in the source.-->
+<strings>
+
+ <!-- Locale Information -->
+ <string name="MicrosoftLocale">english</string>
+ <string name="DarwinLocale">C</string>
+ <string name="LinuxLocale">C</string>
+
+ <!--
+ datetimeToCodes["wkday"] = "%a"; // Thu
+ datetimeToCodes["weekday"] = "%A"; // Thursday
+ datetimeToCodes["year4"] = "%Y"; // 2009
+ datetimeToCodes["year"] = "%Y"; // 2009
+ datetimeToCodes["year2"] = "%y"; // 09
+ datetimeToCodes["mth"] = "%b"; // Aug
+ datetimeToCodes["month"] = "%B"; // August
+ datetimeToCodes["mthnum"] = "%m"; // 08
+ datetimeToCodes["day"] = "%d"; // 31
+ datetimeToCodes["hour24"] = "%H"; // 14
+ datetimeToCodes["hour"] = "%H"; // 14
+ datetimeToCodes["hour12"] = "%I"; // 02
+ datetimeToCodes["min"] = "%M"; // 59
+ datetimeToCodes["ampm"] = "%p"; // AM
+ datetimeToCodes["second"] = "%S"; // 59
+ datetimeToCodes["timezone"] = "%Z"; // PST
+ -->
+
+ <string name="TimeHour">hour,datetime,slt</string>
+ <string name="TimeMin">min,datetime,slt</string>
+ <string name="TimeYear">year,datetime,slt</string>
+ <string name="TimeDay">day,datetime,slt</string>
+ <string name="TimeMonth">mthnum,datetime,slt</string>
+ <string name="TimeWeek">wkday,datetime,slt</string>
+ <string name="TimeAMPM">ampm,datetime,slt</string>
+ <string name="TimeHour12">hour12,datetime,slt</string>
+
+ <string name="LTimeMthNum">mthnum,datetime,local</string>
+ <string name="LTimeWeek">wkday,datetime,local</string>
+ <string name="LTimeMonth">mth,datetime,local</string>
+ <string name="LTimeDay">day,datetime,local</string>
+ <string name="LTimeSec">second,datetime,local</string>
+ <string name="LTimeHour">hour,datetime,local</string>
+ <string name="LTimeMin">min,datetime,local</string>
+ <string name="LTimeYear">year,datetime,local</string>
+
+ <string name="UTCTimeWeek">weekday,datetime,utc</string>
+ <string name="UTCTimeDay">day,datetime,utc</string>
+ <string name="UTCTimeMth">mth,datetime,utc</string>
+ <string name="UTCTimeYr">year,datetime,utc</string>
+ <string name="UTCTimeHr">hour,datetime,utc</string>
+ <string name="UTCTimeMin">min,datetime,utc</string>
+ <string name="UTCTimeSec">second,datetime,utc</string>
+ <string name="UTCTimeTimezone">timezone,datetime,utc</string>
+</strings>
diff --git a/indra/newview/skins/default/xui/pl/menu_login.xml b/indra/newview/skins/default/xui/pl/menu_login.xml
index 4d44af19fb..2445d69ac0 100755
--- a/indra/newview/skins/default/xui/pl/menu_login.xml
+++ b/indra/newview/skins/default/xui/pl/menu_login.xml
@@ -7,7 +7,7 @@
<menu_item_call label="Ustawienia..." name="Preferences..." />
</menu>
<menu label="Pomoc" name="Help">
- <menu_item_call label="Second Life: Pomoc" name="Second Life Help" />
- <menu_item_call label="O Second Life..." name="About Second Life..." />
+ <menu_item_call label="[SECOND_LIFE]: Pomoc" name="Second Life Help" />
+ <menu_item_call label="O [APP_NAME]..." name="About Second Life..." />
</menu>
</menu_bar>
diff --git a/indra/newview/skins/default/xui/pl/menu_viewer.xml b/indra/newview/skins/default/xui/pl/menu_viewer.xml
index 8a86086e54..1898906d9f 100755
--- a/indra/newview/skins/default/xui/pl/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/pl/menu_viewer.xml
@@ -165,7 +165,9 @@
<menu_item_separator label="-----------" name="separator4"/>
<menu_item_call label="OglÄ…daj SelekcjÄ™" name="Focus on Selection"/>
<menu_item_call label="Przybliż do Selekcji" name="Zoom to Selection"/>
- <menu_item_call label="Kup Obiekt" name="Menu Object Take"/>
+ <menu_item_call label="Kup Obiekt" name="Menu Object Take">
+ <on_enable userdata="Kup,Weź" name="EnableBuyOrTake"/>
+ </menu_item_call>
<menu_item_call label="Weź Kopię" name="Take Copy"/>
<menu_item_call label="Zapisz Obiekt z Poprawkami" name="Save Object Back to Object Contents"/>
<menu_item_separator label="-----------" name="separator6"/>
@@ -179,10 +181,10 @@
<menu_item_call label="Wstrzymaj Działanie Skryptów w Selekcji" name="Set Scripts to Not Running in Selection"/>
</menu>
<menu label="Pomoc" name="Help">
- <menu_item_call label="Second Life: Pomoc" name="Second Life Help"/>
+ <menu_item_call label="[SECOND_LIFE]: Pomoc" name="Second Life Help"/>
<menu_item_call label="Samouczek" name="Tutorial"/>
<menu_item_separator label="-----------" name="separator"/>
- <menu_item_call label="Oficjalny Blog Second Life..." name="Official Linden Blog..."/>
+ <menu_item_call label="Oficjalny Blog [SECOND_LIFE]..." name="Official Linden Blog..."/>
<menu_item_separator label="-----------" name="separator2"/>
<menu_item_call label="Portal dla Skrypterów..." name="Scripting Portal..."/>
<menu_item_separator label="-----------" name="separator3"/>
@@ -200,6 +202,6 @@
<menu_item_separator label="-----------" name="separator9"/>
<menu_item_call label="Wyślij Raport Błędu..." name="Report Bug..."/>
</menu>
- <menu_item_call label="O Second Life..." name="About Second Life..."/>
+ <menu_item_call label="O [APP_NAME]..." name="About Second Life..."/>
</menu>
</menu_bar>
diff --git a/indra/newview/skins/default/xui/pl/notifications.xml b/indra/newview/skins/default/xui/pl/notifications.xml
index e2b26bf0d1..3cf9be507d 100644
--- a/indra/newview/skins/default/xui/pl/notifications.xml
+++ b/indra/newview/skins/default/xui/pl/notifications.xml
@@ -6,6 +6,9 @@
<global name="alwayschoose">
Pozwalaj na wybór tej opcji
</global>
+ <global name="implicitclosebutton">
+ Zamknij
+ </global>
<template name="okbutton">
<form>
<button
@@ -71,7 +74,7 @@
</form>
</template>
<notification functor="GenericAcknowledge" label="Nieznany rodzaj komunikatu" name="MissingAlert">
- Twoja wersja klienta Second Life nie może wyświetlić odebranej wiadomości.
+ Twoja wersja klienta [APP_NAME] nie może wyświetlić odebranej wiadomości.
Szczegóły błędu: Błąd o nazwie &apos;[_NAME]&apos; nie został odnaleziony w pliku notifications.xml.
<usetemplate name="okbutton" yestext="OK"/>
@@ -94,7 +97,7 @@ Szczegóły błędu: Błąd o nazwie &apos;[_NAME]&apos; nie został odnaleziony
<usetemplate name="okcancelbuttons" notext="Anuluj" yestext="Tak"/>
</notification>
<notification name="BadInstallation">
- Podczas aktualizacji klienta Second Life wystąpił błąd. Proszę odwiedzić stronę secondlife.com by ściągnąć najnowszą wersje klienta.
+ Podczas aktualizacji klienta [APP_NAME] wystąpił błąd. Proszę odwiedzić stronę secondlife.com by ściągnąć najnowszą wersje klienta.
<usetemplate
name="okbutton"
yestext="OK"/>
@@ -205,23 +208,23 @@ Dodać ten przywilej do funkcji [ROLE_NAME]?
- tej posiadłości w przeglądarce internetowej
</notification>
<notification name="ClickSoundHelpLand">
- Media oraz muzyka są aktywne według ustawień posiadłości dla mediów. Dźwięk oraz komunikacja głosowa mogą być ograniczone w danej posiadłości, w zależności od ustawień rodzaju treści jaką zawiera. Skorzystaj z Second Life:Pomoc by uzyskać więcej informacji na temat dostępu do regionów z podanym rodzajem treści jaką zawiera.
+ Media oraz muzyka są aktywne według ustawień posiadłości dla mediów. Dźwięk oraz komunikacja głosowa mogą być ograniczone w danej posiadłości, w zależności od ustawień rodzaju treści jaką zawiera. Skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać więcej informacji na temat dostępu do regionów z podanym rodzajem treści jaką zawiera.
<url name="url">
https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=5046
</url>
<usetemplate
name="okcancelbuttons"
- yestext="Second Life:Pomoc"
+ yestext="[SECOND_LIFE]:Pomoc"
notext="Zamknij" />
</notification>
<notification name="ClickSearchHelpAll">
- Wyniki wyszukiwania wyświetlają się na podstawie rodzaju zakładki wyszukiwarki, z której korzystasz, rodzaju statusu Twojego wieku, wybranej kategorii, oraz innych czynników. By uzyskać wiecej szczegółów skorzystaj z Second Life: Pomoc.
+ Wyniki wyszukiwania wyświetlają się na podstawie rodzaju zakładki wyszukiwarki, z której korzystasz, rodzaju statusu Twojego wieku, wybranej kategorii, oraz innych czynników. By uzyskać wiecej szczegółów skorzystaj z [SECOND_LIFE]:Pomoc.
<url name="url">
https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=4722
</url>
<usetemplate
name="okcancelbuttons"
- yestext="Second Life:Pomoc"
+ yestext="[SECOND_LIFE]:Pomoc"
notext="Zamknij" />
</notification>
<notification name="ClickPublishHelpLandDisabled">
@@ -235,7 +238,7 @@ Dodać ten przywilej do funkcji [ROLE_NAME]?
<notification name="ClickPartnerHelpAvatar">
Możesz zaproponować związek innemu Rezydentowi lub rozwiązać istniejący związek na stronie internetowej [SECOND_LIFE].
-Chcesz dowiedzieć się więcej na temat związków w Second Life?
+Chcesz dowiedzieć się więcej na temat związków w [SECOND_LIFE]?
<usetemplate name="okcancelbuttons" notext="Anuluj" yestext="Idź na stronę"/>
</notification>
<notification name="ClickUploadHelpPermissions">
@@ -273,7 +276,7 @@ Cena wynosi [SALE_PRICE]L$ i sprzedaż będzie autoryzowana dla [NAME].
<usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/>
</notification>
<notification name="ConfirmLandSaleToAnyoneChange">
- UWAGA: Wybierając Sprzedaż dla Kogokolwiek umożliwiasz zakup posiadłości wszystkim Rezydentom Second Life.
+ UWAGA: Wybierając Sprzedaż dla Kogokolwiek umożliwiasz zakup posiadłości wszystkim Rezydentom [SECOND_LIFE].
Posiadłość o powierzchni [LAND_SIZE] m zostaje wystawiona na sprzedaż.
Cena wynosi [SALE_PRICE]L$ i sprzedaż będzie autoryzowana dla [NAME].
@@ -417,17 +420,17 @@ Pamiętaj! Nie ma rekompensaty za poniesione koszta.
<usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/>
</notification>
<notification name="CacheWillClear">
- Bufor danych na dysku zostanie zresetowany po relogu do [SECOND_LIFE].
+ Bufor danych na dysku zostanie zresetowany po relogu do [APP_NAME].
</notification>
<notification name="CacheWillBeMoved">
- Bufor danych na dysku zostanie przemieszczony po relogu do [SECOND_LIFE].
+ Bufor danych na dysku zostanie przemieszczony po relogu do [APP_NAME].
Bufor będzie również wyczyszczony.
</notification>
<notification name="ChangeConnectionPort">
- Ustawienia portu zostanÄ… wprowadzone po relogu do [SECOND_LIFE].
+ Ustawienia portu zostanÄ… wprowadzone po relogu do [APP_NAME].
</notification>
<notification name="ChangeSkin">
- Nowa skórka zostanie wprowadzona po relogu do [SECOND_LIFE].
+ Nowa skórka zostanie wprowadzona po relogu do [APP_NAME].
</notification>
<notification name="GoToAuctionPage">
Odwiedzić stronę internetową [SECOND_LIFE] żeby zobaczyć szczgóły aukcji lub zrobić ofertę?
@@ -486,7 +489,7 @@ Obiekt może znajdować się zbyt daleko albo został usuniety.
Nie można zapisać pliku [[FILE]]
</notification>
<notification name="UnsupportedHardware">
- Uwaga: Twój system nie spełnia minimalnych wymagań sprzętowych Second Life. Jakość i prędkość Second Life mogą być pogorszone. Niestety, nie będziemy w stanie udzielić Ci technicznej pomocy, ponieważ konfiguracja Twojego systemu nie spełnia wymagań sprzętowych.
+ Uwaga: Twój system nie spełnia minimalnych wymagań sprzętowych [APP_NAME]. Jakość i prędkość [APP_NAME] mogą być pogorszone. Niestety, nie będziemy w stanie udzielić Ci technicznej pomocy, ponieważ konfiguracja Twojego systemu nie spełnia wymagań sprzętowych.
MINSPECS
Czy chcesz odwiedzić stronę [_URL] po dodatkowe informacje?
@@ -498,14 +501,14 @@ Czy chcesz odwiedzić stronę [_URL] po dodatkowe informacje?
<notification name="UnknownGPU">
Twój system jest wyposażony w kartę graficzną której jeszcze nie znamy.
To się często zdarza z nowym sprzętem, którego jeszcze nie testowaliśmy.
-Second Life najprawdopodobniej będzie działało poprawnie. Możliwe, że będziesz musiał wyregulować ustawienia grafiki.
+[APP_NAME] najprawdopodobniej będzie działało poprawnie. Możliwe, że będziesz musiał wyregulować ustawienia grafiki.
(Edycja &gt; Ustawienia &gt; Grafika).
<form name="form">
<ignore name="ignore" text="Zignoruj ostrzeżenie"/>
</form>
</notification>
<notification name="DisplaySettingsNoShaders">
- [SECOND_LIFE] zawiesił się podczas inicjalizacji sterowników graficznych. Jakość grafiki została zmniejszona - może pomoże. Pewne funkcje graficzne zostały wyłączone. Zalecamy aktualizcje strerowników grapicznych.
+ [APP_NAME] zawiesił się podczas inicjalizacji sterowników graficznych. Jakość grafiki została zmniejszona - może pomoże. Pewne funkcje graficzne zostały wyłączone. Zalecamy aktualizcje strerowników grapicznych.
Możesz podnieść jakość grafiki pod Ustawienia &gt; Grafika.
</notification>
<notification name="RegionNoTerraforming">
@@ -559,7 +562,7 @@ Ta osoba tymczasowo nie będzie mógła się poruszać, nie będzie mógł używ
<notification name="PromptGoToCurrencyPage">
[EXTRA]
-Iść na stronę [URL] po informacje dotyczące zakupu gotówki?
+Iść na stronę [_URL] po informacje dotyczące zakupu L$?
<usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/>
</notification>
<notification name="UnableToLinkObjects">
@@ -776,7 +779,7 @@ Posiadłość nie została wybrana.
Region nie znaleziony.
</notification>
<notification name="CannotCloseFloaterBuyLand">
- Dialog Kup Posiadłość nie może zostać zamknięty dopóki Second Life nie oszacuje ceny tej tranzakcji.
+ Dialog Kup Posiadłość nie może zostać zamknięty dopóki [APP_NAME] nie oszacuje ceny tej tranzakcji.
</notification>
<notification name="CannotDeedLandNothingSelected">
Nie można przekazać posiadłości:
@@ -789,8 +792,6 @@ Grupa nie została wybrana.
<notification name="CannotDeedLandNoRegion">
Nie można przekazać posiadłości:
Region nie znaleziony.
-
-Zgłoś ten problem pod Pomoc &gt; Zgłoś Błędy Klienta
</notification>
<notification name="CannotDeedLandMultipleSelected">
Nie można przekazać posiadłości:
@@ -837,8 +838,6 @@ Twoje posiadłości są podkreślone na zielono.
<notification name="CannotReleaseLandRegionNotFound">
Nie można porzucić posiadłości:
Region nie znaleziony.
-
-Zgłoś ten problem pod Pomoc &gt; Zgłoś Błędy Klienta
</notification>
<notification name="CannotReleaseLandNoTransfer">
Nie możesz porzucić posiadłości:
@@ -878,14 +877,10 @@ Podzielić posiadłość?
<notification name="CannotDivideLandNoRegion">
Nie można podzielić posiadłości:
Region nie znaleziony.
-
-Zgłoś ten problem pod Pomoc &gt; Zgłoś Błędy Klienta
</notification>
<notification name="CannotJoinLandNoRegion">
Nie można połączyć posiadłości:
Region nie znaleziony.
-
-Zgłoś ten problem pod Pomoc &gt; Zgłoś Błędy Klienta
</notification>
<notification name="CannotJoinLandNothingSelected">
Nie można połączyć posiadłości:
@@ -941,16 +936,15 @@ Szary = Publiczna
Nie można zapisać &apos;[NAME]&apos; do pliku stroju. Musisz zwolnić trochę miejsca na Twoim komputerze i zapisać strój jeszcze raz.
</notification>
<notification name="CannotSaveToAssetStore">
- Nie można zapisać [NAME] w centralnym zbiorze danych. Zazwyczaj jest to tymczasowy problem. Możesz kontynuować modyfikacje i zapisać strój ponownie za kilka minut.
-
-Jeżeli wciąż masz ten problem, wybierz Pomoc &gt; Zgłoś Błędy Klienta i podaj szczegóły dotyczące konfiguracji sieci.
+ Nie można zapisać [NAME] w centralnym zbiorze danych.
+Zazwyczaj jest to tymczasowy problem. Możesz kontynuować modyfikacje i zapisać strój ponownie za kilka minut.
</notification>
<notification name="YouHaveBeenLoggedOut">
Twoja sesja [SECOND_LIFE] została zakończona:
[MESSAGE]
Kliknij Kontynuuj żeby zobaczyć IMy i czat.
-Żadne inne operacje nie będą dozwolone. Kliknij Wyłącz w celu natychmiastowego opuszczenia [SECOND_LIFE].
+Żadne inne operacje nie będą dozwolone. Kliknij Wyłącz w celu natychmiastowego opuszczenia [APP_NAME].
<usetemplate name="okcancelbuttons" notext="Wyłącz" yestext="Kontynuuj"/>
</notification>
<notification name="OnlyOfficerCanBuyLand">
@@ -968,7 +962,7 @@ Zaproponować znajomość [NAME]?
Zaproponować znajomość [NAME]?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Chcesz zawrzeć znajomość?
</input>
<button name="Offer" text="OK"/>
@@ -1116,14 +1110,14 @@ Możesz normalnie używać [SECOND_LIFE], inni użytkownicy będą Cię widzieli
</form>
</notification>
<notification name="FirstRun">
- Instalacja [SECOND_LIFE] zakończona.
+ Instalacja [APP_NAME] zakończona.
Jeżeli używasz [SECOND_LIFE] po raz pierwszy to musisz stworzyć konto żeby móc się zalogować.
Przejść na stronę www.secondlife.com żeby stworzyć nowe konto?
<usetemplate name="okcancelbuttons" notext="Kontynuuj" yestext="Nowe Konto..."/>
</notification>
<notification name="LoginPacketNeverReceived">
- Problemy z połączeniem. Problem może być spowodowany Twoim połączeniem z Internetem albo może istnieć po stronie serwerów Second Life.
+ Problemy z połączeniem. Problem może być spowodowany Twoim połączeniem z Internetem albo może istnieć po stronie serwerów [SECOND_LIFE].
Możesz sprawdzić swoje połączenie z Internetem i spróbować ponownie za kilka minut albo kliknij Pomoc żeby połączyć się ze stroną pomocy technicznej albo wybierz Teleportuj żeby spróbować teleportacji do Twojego miejsca startu.
<form name="form">
@@ -1225,33 +1219,33 @@ Wybierz obiekt na sprzedaż i spróbuj jeszcze raz.
[DOWNLOAD_PATH].
</notification>
<notification name="DownloadWindowsMandatory">
- Nowa wersja [SECOND_LIFE] została opublikowana.
+ Nowa wersja [APP_NAME] została opublikowana.
[MESSAGE]
-Musisz zainstalować nową wersję żeby używać [SECOND_LIFE].
+Musisz zainstalować nową wersję żeby używać [APP_NAME].
<usetemplate name="okcancelbuttons" notext="Wyłącz program" yestext="Załaduj"/>
</notification>
<notification name="DownloadWindows">
- Uaktualniona wersja [SECOND_LIFE] została opublikowana.
+ Uaktualniona wersja [APP_NAME] została opublikowana.
[MESSAGE]
Aktualizacja nie jest wymagana ale jest zalecana w celu poprawy prędkości i stabilności.
<usetemplate name="okcancelbuttons" notext="Kontynuuj" yestext="Załaduj"/>
</notification>
<notification name="DownloadWindowsReleaseForDownload">
- Uaktualniona wersja [SECOND_LIFE] została opublikowana.
+ Uaktualniona wersja [APP_NAME] została opublikowana.
[MESSAGE]
Aktualizacja nie jest wymagana ale jest zalecana w celu poprawy prędkości i stabilności.
<usetemplate name="okcancelbuttons" notext="Kontynuuj" yestext="Załaduj"/>
</notification>
<notification name="DownloadMacMandatory">
- Nowa wersja [SECOND_LIFE] została opublikowana.
+ Nowa wersja [APP_NAME] została opublikowana.
[MESSAGE]
-Musisz zainstalować nową wersję żeby używać [SECOND_LIFE].
+Musisz zainstalować nową wersję żeby używać [APP_NAME].
Załadować do foldera Aplikacji?
<usetemplate name="okcancelbuttons" notext="Wyłącz program" yestext="Załaduj"/>
</notification>
<notification name="DownloadMac">
- Uaktualniona wersja [SECOND_LIFE] została opublikowana.
+ Uaktualniona wersja [APP_NAME] została opublikowana.
[MESSAGE]
Aktualizacja nie jest wymagana ale jest zalecana w celu poprawy prędkości i stabilności.
@@ -1259,7 +1253,7 @@ Załadować do foldera Aplikacji?
<usetemplate name="okcancelbuttons" notext="Kontynuuj" yestext="Załaduj"/>
</notification>
<notification name="DownloadMacReleaseForDownload">
- Uaktualniona wersja [SECOND_LIFE] została opublikowana.
+ Uaktualniona wersja [APP_NAME] została opublikowana.
[MESSAGE]
Aktualizacja nie jest wymagana ale jest zalecana w celu poprawy prędkości i stabilności.
@@ -1279,10 +1273,6 @@ Załadować do foldera Aplikacji?
Otworzyć stronę www.secondlife.com żeby zarządzać Twoim kontem?
<usetemplate ignoretext="Otwierając systemową przeglądarkę żeby zarządzać Twoim kontem" name="okcancelignore" notext="Anuluj" yestext="OK"/>
</notification>
- <notification name="WebLaunchBugReport101">
- Odwiedź [SECOND_LIFE] Wiki i zobacz jak zgłaszać błędy.
- <usetemplate ignoretext="Otwierając przeglądarkę żeby zobaczyć Wiki zgłaszania błędów" name="okcancelignore" notext="Anuluj" yestext="OK"/>
- </notification>
<notification name="WebLaunchSecurityIssues">
Odwiedź [SECOND_LIFE] Wiki i zobacz jak zgłaszać problemy z bezpieczeństwem danych.
<usetemplate ignoretext="Otwierając przeglądarkę żeby zobaczyć Wiki kwestii bezpieczeństwa danych" name="okcancelignore" notext="Anuluj" yestext="OK"/>
@@ -1365,7 +1355,7 @@ Musisz opuścić przynajmniej jedną grupę żeby przyjąć członkostwo w tej g
<notification name="KickUser">
Z jakim komunikatem wyrzucić tego użytkownia?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Administrator wylogował Cię.
</input>
<button name="OK" text="OK"/>
@@ -1375,7 +1365,7 @@ Musisz opuścić przynajmniej jedną grupę żeby przyjąć członkostwo w tej g
<notification name="KickAllUsers">
Z jakim komunikatem wyrzucić wszystkich użytkowników z regionu?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Administrator wylogował Cię.
</input>
<button name="OK" text="OK"/>
@@ -1385,7 +1375,7 @@ Musisz opuścić przynajmniej jedną grupę żeby przyjąć członkostwo w tej g
<notification name="FreezeUser">
Z jakim komunikatem unieruchomić tego użytkownia?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Unieruchomiono Cię. Nie możesz się ruszać ani rozmawiać. Administrator skontaktuje się z Tobą poprzez IM.
</input>
<button name="OK" text="OK"/>
@@ -1395,7 +1385,7 @@ Musisz opuścić przynajmniej jedną grupę żeby przyjąć członkostwo w tej g
<notification name="UnFreezeUser">
Z jakim komunikatem odblokować tego użytkownia?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Odblokowano CiÄ™.
</input>
<button name="OK" text="OK"/>
@@ -1405,7 +1395,7 @@ Musisz opuścić przynajmniej jedną grupę żeby przyjąć członkostwo w tej g
<notification name="OfferTeleport">
Zaproponować teleportację do miejsca Twojego pobytu z tą wiadomością?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Zapraszam do siebie. Region: [REGION]
</input>
<button name="OK" text="OK"/>
@@ -1415,7 +1405,7 @@ Musisz opuścić przynajmniej jedną grupę żeby przyjąć członkostwo w tej g
<notification name="OfferTeleportFromGod">
Wymusić przeniesienie użytkownika do miejsca Twojego pobytu?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Zapraszam do siebie. Region: [REGION]
</input>
<button name="OK" text="OK"/>
@@ -1429,7 +1419,7 @@ Musisz opuścić przynajmniej jedną grupę żeby przyjąć członkostwo w tej g
<notification label="Wiadomość do Wszystkich w Twoim Majątku" name="MessageEstate">
Wpisz krótką wiadomość która zostanie wysłana do wszystkich osób w Twoim majątku.
<form name="form">
- <input name="message" type="text"/>
+ <input name="message"/>
<button name="OK" text="OK"/>
<button name="Cancel" text="Anuluj"/>
</form>
@@ -1494,7 +1484,7 @@ Kontynuować?
<notification name="RegionEntryAccessBlocked">
Ze względu na Twój wiek, nie jesteś uprawniony do przebywania w tym regionie. Może być to wynikiem braku informacji na temat weryfikacji Twojego wieku.
-Upewnij się, że masz zainstalowaną najnowszą wersję klienta i skorzystaj z Second Life:Pomoc by uzyskać więcej informacji na temat dostępu do regionów z podanym rodzajem treści jaką zawiera.
+Upewnij się, że masz zainstalowaną najnowszą wersję klienta i skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać więcej informacji na temat dostępu do regionów z podanym rodzajem treści jaką zawiera.
<usetemplate
name="okbutton"
yestext="OK"/>
@@ -1502,13 +1492,13 @@ Upewnij się, że masz zainstalowaną najnowszą wersję klienta i skorzystaj z
<notification name="RegionEntryAccessBlocked_KB">
Ze względu na Twój wiek, nie jesteś uprawniony do przebywania w tym regionie.
-Skorzystaj z Second Life:Pomoc by uzyskać więcej informacji na temat dostępu do regionów z podanym rodzajem treści jaką zawiera.
+Skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać więcej informacji na temat dostępu do regionów z podanym rodzajem treści jaką zawiera.
<url name="url">
https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=6010
</url>
<usetemplate
name="okcancelignore"
- yestext="Second Life:Pomoc"
+ yestext="[SECOND_LIFE]:Pomoc"
notext="Zamknij"
ignoretext="Dostęp do posiadłości jest zablokowany ze względu na rodzaj treści jaką zawiera"/>
</notification>
@@ -1533,7 +1523,7 @@ Możeszy wybrać &apos;Zmień Ustawienia&apos; by dokonać zmian w ustawieniach
<notification name="LandClaimAccessBlocked">
W związku ze statusem ustawień Twojego wieku, nie możesz odzyskać tej posiadłości. Możesz potrzebować weryfikacji wieku bądź instalacji najnowszej wersji klienta.
-Upewnij się, że masz zainstalowaną najnowszą wersję klienta i skorzystaj z Second Life:Pomoc by uzyskać więcej informacji na temat dostępu do regionów z podanym rodzajem treści jaką zawiera.
+Upewnij się, że masz zainstalowaną najnowszą wersję klienta i skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać więcej informacji na temat dostępu do regionów z podanym rodzajem treści jaką zawiera.
<usetemplate
name="okbutton"
yestext="OK"/>
@@ -1541,13 +1531,13 @@ Upewnij się, że masz zainstalowaną najnowszą wersję klienta i skorzystaj z
<notification name="LandClaimAccessBlocked_KB">
Ze względu na Twój wiek, nie możesz odzyskać tej posiadłości.
-Skorzystaj z Second Life:Pomoc by uzyskać więcej informacji na temat dostępu do regionów z podanym rodzajem treści jaką zawiera.
+Skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać więcej informacji na temat dostępu do regionów z podanym rodzajem treści jaką zawiera.
<url name="url">
https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=6010
</url>
<usetemplate
name="okcancelignore"
- yestext="Second Life:Pomoc"
+ yestext="[SECOND_LIFE]:Pomoc"
notext="Zamknij"
ignoretext="Odzyskanie posiadłości jest zablokowane ze względu na rodzaj treści jaką zwiera"/>
</notification>
@@ -1567,7 +1557,7 @@ Możeszy wybrać &apos;Zmień Ustawienia&apos; by dokonać zmian w ustawieniach
<notification name="LandBuyAccessBlocked">
Ze względu na Twój wiek, nie możesz kupić tej posiadłości. Może być to wynikiem braku informacji na temat weryfikacji Twojego wieku.
-Upewnij się, że masz zainstalowaną najnowszą wersję klienta i skorzystaj z Second Life:Pomoc by uzyskać więcej informacji na temat dostępu do regionów z podanym rodzajem treści jaką zawiera.
+Upewnij się, że masz zainstalowaną najnowszą wersję klienta i skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać więcej informacji na temat dostępu do regionów z podanym rodzajem treści jaką zawiera.
<usetemplate
name="okbutton"
yestext="OK"/>
@@ -1575,13 +1565,13 @@ Upewnij się, że masz zainstalowaną najnowszą wersję klienta i skorzystaj z
<notification name="LandBuyAccessBlocked_KB">
Ze względu na Twój wiek, nie możesz kupić tej posiadłości.
-Skorzystaj z Second Life:Pomoc by uzyskać więcej informacji na temat dostępu do regionów z podanym rodzajem treści jaką zawiera.
+Skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać więcej informacji na temat dostępu do regionów z podanym rodzajem treści jaką zawiera.
<url name="url">
https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=6010
</url>
<usetemplate
name="okcancelignore"
- yestext="Second Life:Pomoc"
+ yestext="[SECOND_LIFE]:Pomoc"
notext="Zamknij"
ignoretext="Zakup posiadłości jest zablokowany ze względu na rodzaj treści jaką zawiera"/>
</notification>
@@ -1651,7 +1641,7 @@ Zamieścić tą reklamę za [AMOUNT]L$?
<notification label="Wiadomość do Wszystkich w tym Regionie" name="MessageRegion">
Wpisz krótką wiadomość która zostanie wysłana do wszystkich osób w tym regionie.
<form name="form">
- <input name="message" type="text"/>
+ <input name="message"/>
<button name="OK" text="OK"/>
<button name="Cancel" text="Anuluj"/>
</form>
@@ -1723,7 +1713,7 @@ Jeżeli ta opcja jest wybrana kupujący będą mogli odsprzedać posiadłości w
Domyślinie: nie pozwalaj
</notification>
<notification label="Wyłącz Skrypty" name="HelpRegionDisableScripts">
- Słaba wydajność / prędkość symulatora może być spowodowana przez skrypt. Otwórz panel Statystyki (Ctrl-Shift-1). Sprawdź ilość klatek na sekundę (FPS) w Fizyce Symulatora. Jeżeli jest mniej niż 45 wybierz panel Czas znajdujący się na dole panelu Statystyki. Jeżeli Czas Skryptów wynosi 25 ms lub więcej kliknij na Główne Skrypty. Zobaczysz listę nazw i lokacji skryptów które mogą być odpowiedzialne za pogorszenie wydajności.
+ Słaba wydajność / prędkość symulatora może być spowodowana przez skrypt. Otwórz panel Statystyki (Ctrl+Shift+1). Sprawdź ilość klatek na sekundę (FPS) w Fizyce Symulatora. Jeżeli jest mniej niż 45 wybierz panel Czas znajdujący się na dole panelu Statystyki. Jeżeli Czas Skryptów wynosi 25 ms lub więcej kliknij na Główne Skrypty. Zobaczysz listę nazw i lokacji skryptów które mogą być odpowiedzialne za pogorszenie wydajności.
Wybranie opcji Wyłącz Skrypty i naciśnięcie Zastosuj tymczasowo wyłączy wszystkie skrypty w tym regionie. Wybranie tej opcji może być niezbędne w celu umożliwienia podróży do lokacji wymienionego Głównego Skryptu.
Po przebyciu na miejsce zobacz skrypt i sprawdź czy jest on źródłem problemu. W razie potrzeby skontaktuj się z właścicielem skryptu albo usuń lub zwróć obiekt.
@@ -1732,7 +1722,7 @@ Wyłączenie opcji Wyłącz Skrypty i naciśnięcie Zastosuj ponownie włączy s
Domyślnie: nie wybrana
</notification>
<notification label="Wyłącz Kolizje" name="HelpRegionDisableCollisions">
- Słaba wydajność / prędkość symulatora może być spowodowana przez fizyczne obiekty. Otwórz panel Statystyki (Ctrl-Shift-1). Sprawdź ilość klatek na sekundę (FPS) w Fizyce Symulatora. Jeżeli jest mniej niż 45 wybierz panel Czas znajdujący się na dole panelu Statystyki. Jeżeli Czas Symulatora (Fizyka) wynosi 20 ms lub więcej kliknij na Główne Kolizje. Zobaczysz listę nazw i lokacji fizycznych obiektów które mogą być odpowiedzialne za pogorszenie wydajności.
+ Słaba wydajność / prędkość symulatora może być spowodowana przez fizyczne obiekty. Otwórz panel Statystyki (Ctrl+Shift+1). Sprawdź ilość klatek na sekundę (FPS) w Fizyce Symulatora. Jeżeli jest mniej niż 45 wybierz panel Czas znajdujący się na dole panelu Statystyki. Jeżeli Czas Symulatora (Fizyka) wynosi 20 ms lub więcej kliknij na Główne Kolizje. Zobaczysz listę nazw i lokacji fizycznych obiektów które mogą być odpowiedzialne za pogorszenie wydajności.
Wybranie opcji Wyłącz Kolizje i naciśnięcie Zastosuj tymczasowo wyłączy kolizje obiektów. Wybranie tej opcji może być niezbędne w celu umożliwienia podróży do lokacji wymienionych Główneych Kolizji.
Po przebyciu na miejsce zobacz obiekt i sprawdź czy jest on źródłem kolizji z innymi obiektami. W razie potrzeby skontaktuj się z właścicielem obiektu albo usuń lub zwróć obiekt.
@@ -1841,7 +1831,7 @@ Domyślnie: nie włączona
Domyślnie: nie włączone
</notification>
<notification label="Wersja Niezgodna z Systemem Rozmów" name="VoiceVersionMismatch">
- Ta wersja Second Life nie jest kompatybilna z systemem Rozmów w tym regionie. Musisz zainstalować aktualną wersję Second Life żeby Rozmowy działały porawnie.
+ Ta wersja [APP_NAME] nie jest kompatybilna z systemem Rozmów w tym regionie. Musisz zainstalować aktualną wersję [APP_NAME] żeby Rozmowy działały porawnie.
</notification>
<notification label="Umowa MajÄ…tku" name="HelpEstateCovenant">
Włączenie opcji umowy majątku jest wymagane w celu umożliwienia sprzedaży posiadłości w obrębie majątku.
@@ -1913,14 +1903,14 @@ Zawartość zostanie skopiowana do Twojej szafy.
Na pewno chcesz dokonać tego zakupu?
<usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/>
</notification>
- <notification name="ConfirmPurchasePassword" type="password">
+ <notification name="ConfirmPurchasePassword">
Ta transakcja spowoduje:
[ACTION]
Na pewno chcesz dokonać tego zakupu?
Wpisz hasło ponownie i kliknij OK.
<form name="form">
- <input name="message" type="password"/>
+ <input name="message"/>
<button name="ConfirmPurchase" text="OK"/>
<button name="Cancel" text="Anuluj"/>
</form>
@@ -1946,7 +1936,7 @@ Przenieść obiekty szafy?
<usetemplate ignoretext="Przenosząc szafę bez praw kopiowania ze skryptowanych obiektów" name="okcancelignore" notext="Anuluj" yestext="OK"/>
</notification>
<notification name="ClickActionNotPayable">
- Uwaga: Opcja Zapłać Obiektowi została wybrana, ale żeby ta opcja działała musi być dodany skrypt z funkcją money().
+ Uwaga: Opcja &apos;Zapłać Obiektowi&apos; została wybrana, ale żeby ta opcja działała musi być dodany skrypt z funkcją money().
<form name="form">
<ignore name="ignore" text="Wybierając opcję Zapłać Obiektowi dla obiektów bez funkcji money()"/>
</form>
@@ -1955,16 +1945,16 @@ Przenieść obiekty szafy?
W tym obiekcie nie ma elementów które możesz skopiować.
</notification>
<notification name="WebLaunchAccountHistory">
- Przejść na stronę Second Life żeby zobaczyć historię konta?
+ Przejść na stronę [SECOND_LIFE] żeby zobaczyć historię konta?
<usetemplate ignoretext="ÅadujÄ…c stronÄ™ historii konta." name="okcancelignore" notext="Anuluj" yestext="Idź na stronÄ™"/>
</notification>
<notification name="ClickOpenF1Help">
- Przejść na stronę Second Life?
- <usetemplate ignoretext="Odwiedzając stronę Second Life." name="okcancelignore" notext="Anuluj" yestext="Idź"/>
+ Przejść na stronę [SECOND_LIFE]?
+ <usetemplate ignoretext="Odwiedzając stronę [SECOND_LIFE]." name="okcancelignore" notext="Anuluj" yestext="Idź"/>
</notification>
<notification name="ConfirmQuit">
Na pewno chcesz skończyć?
- <usetemplate ignoretext="Wyłączając Second Life." name="okcancelignore" notext="Kontynuuj" yestext="Wyłącz"/>
+ <usetemplate ignoretext="Wyłączając [APP_NAME]." name="okcancelignore" notext="Kontynuuj" yestext="Wyłącz"/>
</notification>
<notification name="HelpReportAbuseEmailLL">
Używaj tej opcji do zgłaszania nadużyć Warunków Umowy (Terms of Service) i Standardów Społeczeństwa (Community Standards). Zobacz:
@@ -1983,27 +1973,12 @@ W ramach serwisu dla Rezydentów i gości właściciel tego regionu postanowił
Właściciel regionu będzie rozpatrywał raporty w oparciu o lokalne prawa tego regionu zdefiniowane w umowie majątku. (Możesz zobaczyć umowę wybierając opcję O Posiadłości z menu Świat.)
-Rozwiązanie tego raportu odnosi się wyłącznie do tego regionu; konkluzja tego raportu nie będzie miała wpływu na dostęp Rezydentów do innych regionów w Second Life. Wyłącznie Linden Lab może całkowicie odebrać dostęp do Second Life.
- </notification>
- <notification name="HelpReportBug">
- Używaj tej opcji *wyłącznie* w celu zgłaszania technicznych problemów, dołączając szczegółowy opis problemu. Możesz odpowiedzieć na automatyczną email z odpowiedzią żeby dodać więcej szczegółów do Twojego raportu.
-
-Wszystkie raporty błędów są analizowane i oceniane. Kontakt przez email nie będzie nawiązany.
-
-Jeżeli masz techniczne problemy, skontaktuj się z pomocą techniczną pod:
-
-http://secondlife.com/community/support.php
-
-Uwaga: Niekompletne raporty nie będą analizowane.
+Rozwiązanie tego raportu odnosi się wyłącznie do tego regionu; konkluzja tego raportu nie będzie miała wpływu na dostęp Rezydentów do innych regionów w [SECOND_LIFE]. Wyłącznie Linden Lab może całkowicie odebrać dostęp do [SECOND_LIFE].
</notification>
<notification name="HelpReportAbuseSelectCategory">
Wybierz kategorię dla tego raportu o nadużyciu.
Określenie kategorii pomoże nam w klasyfikacji i prztwarzaniu raportu.
</notification>
- <notification name="HelpReportBugSelectCategory">
- Wybierz kategorię dla tego błędu.
-Określenie kategorii pomoże nam w klasyfikacji i prztwarzaniu raportu.
- </notification>
<notification name="HelpReportAbuseAbuserNameEmpty">
Wprowadź imię i nazwisko osoby popełniającej nadużycie.
Dokładne dane pomogą nam w klasyfikacji i prztwarzaniu raportu.
@@ -2016,27 +1991,19 @@ Dokładne dane pomogą nam w klasyfikacji i prztwarzaniu raportu.
Wprowadź opis popełnionego nadużycia.
Dokładne dane pomogą nam w klasyfikacji i prztwarzaniu raportu.
</notification>
- <notification name="HelpReportBugSummaryEmpty">
- Wprowadź opis błędu.
-Dokładne dane pomogą nam w klasyfikacji i prztwarzaniu raportu.
- </notification>
<notification name="HelpReportAbuseDetailsEmpty">
Wprowadź szczgółowy opis popełnionego nadużycia.
Podaj maksymalną ilość szczgółów oraz imiona i nazwiska osób związanych z nadużyciem które zgłaszasz.
Dokładne dane pomogą nam w klasyfikacji i prztwarzaniu raportu.
</notification>
- <notification name="HelpReportBugDetailsEmpty">
- Wprowadź szczgółowy opis błędu. Podaj maksymalną ilość szczgółów oraz, jeżeli to możliwe, kroki niezbędne do odtworzenia problemu.
-Dokładne dane pomogą nam w klasyfikacji i prztwarzaniu raportu.
- </notification>
<notification name="HelpReportAbuseContainsCopyright">
Szanowny Rezydencie,
Jeżeli składasz raport dotyczący naruszenia praw autorskich proszę się upewnić, że robisz to poprawnie:
-(1) Przypadek Nadużycia. Możesz złożyć raport jeżeli sądzisz, że Rezydent narusza system przywilejów Second Life, na przykład używając CopyBot lub podobnych narzędzi robiących kopie, naruszając prawa autorskie. Komisja Nadużyć bada wykrocznia i stosuje akcje dyscyplinarne za zachowania sprzeczne z zasadami Warunków Umowy (Terms of Service) i Standardów Społeczeństwa (Community Standards) Second Life. Komisja Nadużyć nie zajmuje się i nie odpowiada na żądania usunięcia treści ze środowiska Second Life.
+(1) Przypadek Nadużycia. Możesz złożyć raport jeżeli sądzisz, że Rezydent narusza system przywilejów [SECOND_LIFE], na przykład używając CopyBot lub podobnych narzędzi robiących kopie, naruszając prawa autorskie. Komisja Nadużyć bada wykrocznia i stosuje akcje dyscyplinarne za zachowania sprzeczne z zasadami Warunków Umowy (Terms of Service) i Standardów Społeczeństwa (Community Standards) [SECOND_LIFE]. Komisja Nadużyć nie zajmuje się i nie odpowiada na żądania usunięcia treści ze środowiska [SECOND_LIFE].
-(2) Przypadek DMCA lub Usuwanie Treści. Aby wystąpić z żądaniem o usunięcie treści ze środowiska Second Life MUSISZ przedłożyć ważne zawiadomienie o nadużyciu zgodne z naszą polisą DMCA pod http://secondlife.com/corporate/dmca.php.
+(2) Przypadek DMCA lub Usuwanie Treści. Aby wystąpić z żądaniem o usunięcie treści ze środowiska [SECOND_LIFE] MUSISZ przedłożyć ważne zawiadomienie o nadużyciu zgodne z naszą polisą DMCA pod http://secondlife.com/corporate/dmca.php.
Jeżeli chcesz kontynuować dalej zamknij to okno i dokończ wysyłanie raportu. Może być potrzebny wybór kategorii &apos;CopyBot albo Nadużycie Przywilejów&apos;.
@@ -2088,12 +2055,12 @@ Chcesz wyłączyć Tryb Pracy przed zakończeniem tej tranzakcji?
<usetemplate ignoretext="UsuwajÄ…c szafÄ™ z Twojego foldera Zgubione i Znalezione" name="okcancelignore" notext="Nie" yestext="Tak"/>
</notification>
<notification name="CopySLURL">
- Następujący link SLURL został skopiowany do pamięci podręcznej:
+ Następujący link SLurl został skopiowany do pamięci podręcznej:
[SLURL]
Zamieść go na stronie Internetowej żeby umożliwić innym łatwy dostęp do tego miejsca, albo wklej go do panela adresu Twojej przeglądarki żeby go wypróbować.
<form name="form">
- <ignore name="ignore" text="Kopiując SLURL do pamięci podręcznej"/>
+ <ignore name="ignore" text="Kopiując SLurl do pamięci podręcznej"/>
</form>
</notification>
<notification name="GraphicsPreferencesHelp">
@@ -2159,7 +2126,7 @@ Kliknij &quot;Zaawansowane Niebo&quot; żeby wybrać bardziej szczegółowy edyt
Kliknij &quot;Zaawansowana Woda&quot; żeby wybrać bardziej szczegółowy edytor ustawień wody.
</notification>
<notification name="HelpDayCycle">
- Edytor Cyklu Dnia pozwala na kontrolę nieba podczas cyklu dnia/nocy w Second Life. Ten cykl jest używany przez suwak Pora Dnia w podstawowym Edytorze Środowiska.
+ Edytor Cyklu Dnia pozwala na kontrolę nieba podczas cyklu dnia/nocy w [SECOND_LIFE]. Ten cykl jest używany przez suwak Pora Dnia w podstawowym Edytorze Środowiska.
Edytor Cyklu Dnia ustala klatki odniesienia. Są to punkty (widoczne jako szare plamki na wykresie czasu) które mają przypisane Ustawienia Nieba. W miarę upływu czasu niebo jest animowane używając średnich pomiędzy klatkami odniesienia.
@@ -2240,7 +2207,7 @@ Suwak G (Gęstość) kontroluje gęstość chmur.
Kontroluje prędkość przemieszczania chmur wzdłuż osi Y.
</notification>
<notification name="HelpClassicClouds">
- Wybierz tą opcję w celu używania dodatkowo starszej, klasycznej wersji chmur Second Life.
+ Wybierz tą opcję w celu używania dodatkowo starszej, klasycznej wersji chmur [SECOND_LIFE].
</notification>
<notification name="HelpWaterFogColor">
Kontroluje kolor podwodnej mgły.
@@ -2284,7 +2251,7 @@ Suwak G (Gęstość) kontroluje gęstość chmur.
<notification name="NewSkyPreset">
Nazwij nowe niebo.
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Nowe Ustawienie
</input>
<button name="OK" text="OK"/>
@@ -2297,7 +2264,7 @@ Suwak G (Gęstość) kontroluje gęstość chmur.
<notification name="NewWaterPreset">
Nazwij nowe ustawienie wody.
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Nowe Ustawienie
</input>
<button name="OK" text="OK"/>
@@ -2339,7 +2306,7 @@ Suwak G (Gęstość) kontroluje gęstość chmur.
</notification>
<notification name="NotAgeVerified">
Nie masz dostępu do tej posiadłości ze względu na brak weryfikacji Twojego wieku.
-Czy chcesz odwiedzić stronę Second Life żeby to zmienić?
+Czy chcesz odwiedzić stronę [SECOND_LIFE] żeby to zmienić?
[_URL]
<url name="url" option="0">
@@ -2349,7 +2316,7 @@ Czy chcesz odwiedzić stronę Second Life żeby to zmienić?
</notification>
<notification name="Cannot enter parcel: no payment info on file">
Nie masz dostępu do tej posiadłości ze względu na brak danych o Twoim koncie.
-Czy chcesz odwiedzić stronę Second Life żeby to zmienić?
+Czy chcesz odwiedzić stronę [SECOND_LIFE] żeby to zmienić?
[_URL]
<url name="url" option="0">
@@ -2379,10 +2346,10 @@ Czy chcesz odwiedzić stronę Second Life żeby to zmienić?
Temat: [SUBJECT], Treść: [MESSAGE]
</notification>
<notification name="FriendOnline">
- [FIRST] [LAST] jest w Second Life
+ [FIRST] [LAST] jest w [SECOND_LIFE]
</notification>
<notification name="FriendOffline">
- [FIRST] [LAST] opuszcza Second Life
+ [FIRST] [LAST] opuszcza [SECOND_LIFE]
</notification>
<notification name="AddSelfFriend">
Nie możesz dodać siebie do listy znajomych.
@@ -2602,7 +2569,7 @@ Nie możesz tworzyć tutaj obiektów.
<notification name="RegionTPAccessBlocked">
Ze względu na Twój wiek, nie jesteś uprawniony do przebywania w tym regionie. Możesz potrzebować weryfikacji wieku bądź instalacji najnowszej wersji klienta.
-Skorzystaj z Second Life:Pomoc by uzyskać więcej informacji na temat dostępu do regionów z podanym rodzajem treści jaką zawiera.
+Skorzystaj z [SECOND_LIFE]:Pomoc by uzyskać więcej informacji na temat dostępu do regionów z podanym rodzajem treści jaką zawiera.
</notification>
<notification name="URBannedFromRegion">
Zostałeś zbanowany w regionie.
@@ -2617,7 +2584,7 @@ Odwiedź &apos;Help Island Public&apos; by powtórzyć szkolenie.
<notification name="ImproperPaymentStatus">
Nie posiadasz odpowiedniego statusu płatniczego by uzyskać dostęp do regionu.
</notification>
- <notification name="MustGetAgeRgion">
+ <notification name="MustGetAgeRegion">
By odwiedzić ten region, Twoje konto musi zostać poddane weryfikacji wieku.
</notification>
<notification name="MustGetAgeParcel">
@@ -2718,7 +2685,7 @@ Spróbuj ponowanie za kilka minut.
</form>
</notification>
<notification name="TeleportOffered">
- [NAME] proponuje Ci teleportcjÄ™ do siebie:
+ [NAME] proponuje Ci teleportacjÄ™ do siebie:
[MESSAGE]
<form name="form">
@@ -2794,7 +2761,7 @@ Obiekt: [OBJECTNAME], właściciel: [NAME]?
[TYPE] [DESC] - nie znaleziono w bazie danych.
</notification>
<notification name="InvalidWearable">
- Obiekt, który chcesz założyć używa narzędzia nieobecnego w wersji klienta, którą używasz. By go założyć ściągnij najnowszą wersję klienta Second Life.
+ Obiekt, który chcesz założyć używa narzędzia nieobecnego w wersji klienta, którą używasz. By go założyć ściągnij najnowszą wersję klienta [APP_NAME].
</notification>
<notification name="ScriptQuestion">
&apos;[OBJECTNAME]&apos;, właściciel: &apos;[NAME]&apos;, chciał by:
@@ -2899,8 +2866,8 @@ Obiekty elastyczne nie mogą być fizyczne i muszą być typu fantom.
</notification>
<notification name="FirstDebugMenus">
Zaawansowane menu zostało włączone.
-To menu zawiera funkcje użyteczne dla programistów analizujących Secon Life.
-To menu jest włączne przez Ctrl-Alt-D pod Windows. Mac używa Cmd-Opt-Shift-D.
+To menu zawiera funkcje użyteczne dla programistów analizujących [SECOND_LIFE].
+To menu jest aktywowane dzięki kombinacji klawiszy Ctrl+Alt+D (Windows) lub &#8997;&#8984;D (Mac).
</notification>
<notification name="FirstSculptedPrim">
Edytujesz sculpt.
@@ -3012,7 +2979,7 @@ Wybierz Wycisz żeby wyciszyć tą osobę.
- Prędkość Twojego CPU nie spełnia minimalnych wymagań.
</global>
<global name="UnsupportedGLRequirements">
- Wygląda na to, że Twój system nie spełnia wymagań sprzętowych Second Life. Second Life wymaga karty graficznej kompatybilnej z OpenGL z multiteksturami. Jeżeli masz taką kartę zainstaluj najnowsze sterowniki do niej i uaktualnienia systemu operacyjnego.
+ Wygląda na to, że Twój system nie spełnia wymagań sprzętowych [APP_NAME]. [APP_NAME] wymaga karty graficznej kompatybilnej z OpenGL z multiteksturami. Jeżeli masz taką kartę zainstaluj najnowsze sterowniki do niej i uaktualnienia systemu operacyjnego.
Jeżeli wciąż masz problemy sprawdź: http://www.secondlife.com/support
</global>
diff --git a/indra/newview/skins/default/xui/pl/panel_audio_device.xml b/indra/newview/skins/default/xui/pl/panel_audio_device.xml
index ad30dfbacb..fc3b3776f0 100755
--- a/indra/newview/skins/default/xui/pl/panel_audio_device.xml
+++ b/indra/newview/skins/default/xui/pl/panel_audio_device.xml
@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="device_settings">
- <text type="string" length="1" name="Audio Devices">
+ <text name="Audio Devices">
UrzÄ…dzenia Audio
</text>
- <text type="string" length="1" name="Input device (microphone):">
+ <text name="Input device (microphone):">
Urządzenia Wejściowe (mikrofon):
</text>
- <text type="string" length="1" name="Output device (speakers):">
+ <text name="Output device (speakers):">
Urządzenia Wyjściowe (głośniki):
</text>
- <text type="string" length="1" name="Input level:">
+ <text name="Input level:">
Poziom Wejścia
</text>
- <text_editor type="string" length="1" name="voice_intro_text1">
+ <text_editor name="voice_intro_text1">
Użyj suwaka by dostosować jak głośno Cię słychać dla innych Rezydentów. By przetestować poziom wejścia, zacznij mówić do mikrofonu.
</text_editor>
<volume_slider name="mic_volume_slider"
diff --git a/indra/newview/skins/default/xui/pl/panel_edit_profile.xml b/indra/newview/skins/default/xui/pl/panel_edit_profile.xml
new file mode 100644
index 0000000000..97fa3118f8
--- /dev/null
+++ b/indra/newview/skins/default/xui/pl/panel_edit_profile.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel name="edit_profile_panel">
+ <string name="CaptionTextAcctInfo">
+ [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION]
+ </string>
+ <string name="AcctTypeResident"
+ value="Rezydent" />
+ <string name="AcctTypeTrial"
+ value="Próbne" />
+ <string name="AcctTypeCharterMember"
+ value="Członek-zalożyciel" />
+ <string name="AcctTypeEmployee"
+ value="Pracownik Linden Lab" />
+ <string name="PaymentInfoUsed"
+ value="Dane Konta Używane" />
+ <string name="PaymentInfoOnFile"
+ value="Dane Konta Dostępne" />
+ <string name="NoPaymentInfoOnFile"
+ value="Brak Danych Konta" />
+ <string name="AgeVerified"
+ value="Wiek Zweryfikowany" />
+ <string name="NotAgeVerified"
+ value="Brak Weryfikacji Wieku" />
+ <string name="partner_edit_link_url">
+ http://www.secondlife.com/account/partners.php?lang=pl
+ </string>
+ <panel name="scroll_content_panel">
+ <panel name="data_panel" >
+ <panel name="lifes_images_panel">
+ <panel name="second_life_image_panel">
+ <text name="second_life_photo_title_text">
+ [SECOND_LIFE]:
+ </text>
+ </panel>
+ </panel>
+ <text name="title_partner_text" value="Partner:"/>
+ <panel name="partner_data_panel">
+ <text name="partner_text" value="[FIRST] [LAST]"/>
+ </panel>
+ <text name="text_box3">
+ Pracuś Mówi:
+ </text>
+ </panel>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/pl/panel_group_general.xml b/indra/newview/skins/default/xui/pl/panel_group_general.xml
index 6f6d524cd9..d09ff72226 100755
--- a/indra/newview/skins/default/xui/pl/panel_group_general.xml
+++ b/indra/newview/skins/default/xui/pl/panel_group_general.xml
@@ -1,9 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Ogólne" name="general_tab">
<string name="help_text">
- Zakładka Ogólne zawiera informacje na temat tej grupy,
-listę właścicieli, widocznych członków,
-ustawienia grupy oraz opcje członkostwa.
+ Zakładka Ogólne zawiera informacje na temat tej grupy, listę właścicieli, widocznych członków, ustawienia grupy oraz opcje członkostwa.
</string>
<string name="group_info_unchanged">
Ogólne informacje na temat grupy uległy zmianie.
@@ -35,9 +33,9 @@ ustawienia grupy oraz opcje członkostwa.
(Właściciele wyświetlają się pogrubioną czcionką)
</text>
<name_list name="visible_members">
- <column label="ImiÄ™" name="name"/>
- <column label="Tytuł" name="title"/>
- <column label="Ostatnio w SL" name="online"/>
+ <name_list.columns label="ImiÄ™" name="name"/>
+ <name_list.columns label="Tytuł" name="title"/>
+ <name_list.columns label="Ostatnio w SL" name="online"/>
</name_list>
<text name="text_group_preferences">
Ustawienia Grupy
@@ -45,24 +43,18 @@ ustawienia grupy oraz opcje członkostwa.
<panel name="preferences_container">
<check_box label="Wyświetlaj w wyszukiwarce" name="show_in_group_list" tool_tip="Udostępnij info o grupie w wyszukiwarce"/>
<check_box label="Wolny Wstęp" name="open_enrollement" tool_tip="Sprawdź czy grupa oferuje wolny wstęp i nie wymaga zaproszenia."/>
- <check_box label="Opłata Wstępu: L$" name="check_enrollment_fee" tool_tip="Ustaw opłatę za przyłączenie się do grupy."/>
+ <check_box label="Opłata Wstępu:" name="check_enrollment_fee" tool_tip="Ustaw opłatę za przyłączenie się do grupy."/>
<spinner name="spin_enrollment_fee" tool_tip="Nowi członkowie grupy muszą zapłacić wymaganą opłatę by dołączyć do grupy."/>
<combo_box name="group_mature_check" tool_tip="Wybierz jeżeli uważasz, iż Twoja grupa klasyfikowana jest jako &apos;Mature&apos;.">
- <combo_item name="select_mature">
- - Wybierz Treść -
- </combo_item>
- <combo_item name="mature">
- Treść &apos;Mature&apos;
- </combo_item>
- <combo_item name="pg">
- Treść &apos;PG&apos;
- </combo_item>
+ <combo_box.item name="select_mature" label="- Wybierz Treść -"/>
+ <combo_box.item name="mature" label="Treść &apos;Mature&apos;"/>
+ <combo_box.item name="pg" label="Treść &apos;PG&apos;"/>
</combo_box>
<panel name="title_container">
<text name="active_title_label">
Mój Aktywny Tytuł
</text>
- <combo_box length="150" name="active_title" tool_tip="Ustaw tytuł który wyświetla się kiedy grupa jest aktywna."/>
+ <combo_box name="active_title" tool_tip="Ustaw tytuł który wyświetla się kiedy grupa jest aktywna."/>
</panel>
<check_box label="Otrzymuj grupowe ogłoszenia" name="receive_notices" tool_tip="Zaznacz jeżeli chcesz otrzymywać ogłoszenia z tej grupy. Anuluj z zaznaczenia, jeżeli nie chcesz otrzymywać żadnych ogłoszeń z tej grupy."/>
<check_box label="Wyświetl grupę w profilu" name="list_groups_in_profile" tool_tip="Zaznacz jeżeli chcesz by grupa wyświetlała się w Twoim profilu"/>
diff --git a/indra/newview/skins/default/xui/pl/panel_group_land_money.xml b/indra/newview/skins/default/xui/pl/panel_group_land_money.xml
index 5080b0963a..dbfa8e3122 100755
--- a/indra/newview/skins/default/xui/pl/panel_group_land_money.xml
+++ b/indra/newview/skins/default/xui/pl/panel_group_land_money.xml
@@ -48,8 +48,11 @@
<string name="land_contrib_error">
Nie można ustalić Twoich kontrybucji.
</string>
+ <text name="your_contribution_units">
+ ( m )
+ </text>
<text name="your_contribution_max_value">
- metrów ([AMOUNT] maksimum)
+ ([AMOUNT] maksimum)
</text>
<text name="group_over_limit_text">
Członkowie Grupy muszą zwiększyć kredyt na używanie Posiadłości.
diff --git a/indra/newview/skins/default/xui/pl/panel_group_notices.xml b/indra/newview/skins/default/xui/pl/panel_group_notices.xml
index 7a3b6fbcec..1c19571ec0 100755
--- a/indra/newview/skins/default/xui/pl/panel_group_notices.xml
+++ b/indra/newview/skins/default/xui/pl/panel_group_notices.xml
@@ -12,8 +12,6 @@
</text>
<text name="lbl2">
Ogłoszenia przechowywane są przez 14 dni.
-Kliknij tutaj by zobaczyć ogłoszenie.
-Użyj Odswież by zobaczyć czy nowe ogloszenia zostały wysłane.
Limit dzienny ogłoszeń dla grupy wynosi 200.
</text>
<scroll_list name="notice_list">
@@ -33,10 +31,7 @@ Limit dzienny ogłoszeń dla grupy wynosi 200.
Stwórz Ogłoszenie
</text>
<text name="lbl2">
- By wysłać ogłoszenie musisz nadać mu tytuł.
-Możesz także dołączyć pojedynczy załącznik ze swojej
-szafy. Załącznik musi mieć prawo modyfikacyjne
-do kopiowania oraz transferu.
+ Możesz także dołączyć pojedynczy załącznik ze swojej szafy. Załącznik musi mieć prawo modyfikacyjne do kopiowania oraz transferu.
</text>
<text name="lbl3">
Temat:
diff --git a/indra/newview/skins/default/xui/pl/panel_groups.xml b/indra/newview/skins/default/xui/pl/panel_groups.xml
index 58106a6105..9df90fc797 100755
--- a/indra/newview/skins/default/xui/pl/panel_groups.xml
+++ b/indra/newview/skins/default/xui/pl/panel_groups.xml
@@ -3,10 +3,10 @@
<scroll_list name="group list">
<column label="" name="name" />
</scroll_list>
- <text type="string" length="1" name="groupdesc">
+ <text name="groupdesc">
Twoja aktywna grupa jest pogrubiona.
</text>
- <text type="string" length="1" name="groupcount">
+ <text name="groupcount">
Należysz do [COUNT] grup (maksimum to [MAX]).
</text>
<button label="Czat/IM" name="IM" tool_tip="Rozpocznij sesjÄ™ czatu (IM)" />
diff --git a/indra/newview/skins/default/xui/pl/panel_login.xml b/indra/newview/skins/default/xui/pl/panel_login.xml
index 08a768d44f..3caf9338a2 100755
--- a/indra/newview/skins/default/xui/pl/panel_login.xml
+++ b/indra/newview/skins/default/xui/pl/panel_login.xml
@@ -18,16 +18,10 @@
<text name="start_location_text">
Miejsce Startu:
</text>
- <combo_box name="start_location_combo">
- <combo_item name="MyHome">
- Mój Start
- </combo_item>
- <combo_item name="MyLastLocation">
- Ostatnie Miejsce
- </combo_item>
- <combo_item name="Typeregionname">
- &lt;Wpisz Region&gt;
- </combo_item>
+ <combo_box name="start_location_combo">
+ <combo_box.item name="MyHome" label="Mój Start" />
+ <combo_box.item name="MyLastLocation" label="Ostatnie Miejsce" />
+ <combo_box.item name="Typeregionname" label="&lt;Wpisz Region&gt;" />
</combo_box>
<check_box label="Zapamiętaj Hasło" name="remember_check" />
<button label="Połącz" label_selected="Połącz" name="connect_btn" />
diff --git a/indra/newview/skins/default/xui/pl/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/pl/panel_preferences_advanced.xml
new file mode 100644
index 0000000000..2b70a728fa
--- /dev/null
+++ b/indra/newview/skins/default/xui/pl/panel_preferences_advanced.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<panel name="advanced">
+ <text name="AspectRatioLabel1" tool_tip="width / height">
+ Proporcje:
+ </text>
+ <combo_box name="aspect_ratio" tool_tip="width / height">
+ <combo_box.item label="4:3 (Standardowy CRT)" name="item1"/>
+ <combo_box.item label="5:4 (1280x1024 LCD)" name="item2"/>
+ <combo_box.item label="8:5 (Panoramiczny)" name="item3"/>
+ <combo_box.item label="16:9 (Panoramiczny)" name="item4"/>
+ </combo_box>
+</panel>
diff --git a/indra/newview/skins/default/xui/pl/panel_preferences_alerts.xml b/indra/newview/skins/default/xui/pl/panel_preferences_alerts.xml
new file mode 100755
index 0000000000..7826af8b03
--- /dev/null
+++ b/indra/newview/skins/default/xui/pl/panel_preferences_alerts.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel label="Informacje" name="popups" title="Popups">
+ <text name="dont_show_label">
+ Ukryj te informacje:
+ </text>
+ <button label="Pokazuj TÄ™ InformacjÄ™" name="enable_popup" />
+ <button label="Pokazuj Wszystko..." name="reset_dialogs_btn"
+ tool_tip="Wyświetlaj wszystkie opcjonalne i &apos;Użyte pierwszy raz&apos; informacje." />
+ <text name="show_label">
+ Pokazuj te informacje:
+ </text>
+ <button label="Ukryj TÄ™ InformacjÄ™..." name="skip_dialogs_btn"
+ tool_tip="Nie wyświetlaj żadnych opcjonalnych i &apos;Użyte pierwszy raz&apos; informacji" />
+ <text name="text_box2">
+ Oferty notek, obrazów i miejsc (LM):
+ </text>
+ <check_box label="Akceptuj automatycznie" name="accept_new_inventory" />
+ <check_box label="Wyświetlaj automatycznie po akceptacji" name="show_new_inventory" />
+ <check_box label="Automatycznie pokazuj nowe obiekty w szafie po akceptacji"
+ name="show_in_inventory" />
+</panel>
diff --git a/indra/newview/skins/default/xui/pl/panel_preferences_chat.xml b/indra/newview/skins/default/xui/pl/panel_preferences_chat.xml
index 5e397c2b06..13b66ed242 100755
--- a/indra/newview/skins/default/xui/pl/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/pl/panel_preferences_chat.xml
@@ -1,57 +1,57 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Czat/IM" name="chat">
- <text type="string" length="1" name="text_box">
+ <text name="text_box">
Rozmiar Czcionki Czatu:
</text>
<radio_group name="chat_font_size">
- <radio_item type="string" length="1" name="radio">
- Mała
- </radio_item>
- <radio_item type="string" length="1" name="radio2">
- Åšrednia
- </radio_item>
- <radio_item type="string" length="1" name="radio3">
- Duża
- </radio_item>
+ <radio_item name="radio" label="Mała" />
+ <radio_item name="radio2" label="Åšrednia" />
+ <radio_item name="radio3" label="Duża" />
</radio_group>
- <text type="string" length="1" name="text_box2">
- Kolor Czatu:
- </text>
- <color_swatch label="Ty" name="user" />
- <color_swatch label="Inni" name="agent" />
- <color_swatch label="IM" name="im" />
- <color_swatch label="System" name="system" />
- <color_swatch label="Błędy" name="script_error" />
- <color_swatch label="Obiekty" name="objects" />
- <color_swatch label="Właściciel" name="owner" />
- <color_swatch label="Chmurka" name="background" />
- <color_swatch label="Linki" name="links" />
- <text type="string" length="1" name="text_box8">
- Błędy Skryptu:
+ <color_swatch label="Ty" name="user"/>
+ <text name="text_box1">
+ Ty
</text>
- <check_box label="Pokazuj ostrzeżenia i błędy skryptu w czacie" name="script_errors_as_chat" />
- <text type="string" length="1" name="text_box3">
- Konsola Czatu:
+ <color_swatch label="Inni" name="agent"/>
+ <text name="text_box2">
+ Inni
</text>
- <spinner label="Zamykaj czat w" name="fade_chat_time" />
- <text type="string" length="1" name="text_box4">
- (sekund)
+ <color_swatch label="IM" name="im"/>
+ <text name="text_box3">
+ IM
+ </text>
+ <color_swatch label="System" name="system"/>
+ <text name="text_box4">
+ System
+ </text>
+ <color_swatch label="Błędy" name="script_error"/>
+ <text name="text_box5">
+ Błędy
+ </text>
+ <color_swatch label="Obiekty" name="objects"/>
+ <text name="text_box6">
+ Obiekty
+ </text>
+ <color_swatch label="Właściciel" name="owner"/>
+ <text name="text_box7">
+ Właściciel
</text>
- <text type="string" length="1" name="text_box5">
- (linii)
+ <color_swatch label="Chmurka" name="background"/>
+ <text name="text_box8">
+ Chmurka
</text>
+ <color_swatch label="Linki" name="links"/>
+ <text name="text_box9">
+ Linki
+ </text>
+ <check_box label="Pokazuj ostrzeżenia i błędy skryptu w czacie" name="script_errors_as_chat" />
+ <spinner label="Zamykaj czat w" name="fade_chat_time" />
<slider label="Przeźroczystość" name="console_opacity" />
<check_box label="Używaj pełnej szerokość ekranu (restart wymagany)" name="chat_full_width_check" />
- <text type="string" length="1" name="text_box6">
- Ustawienia Czatu:
- </text>
<check_box label="Zamknij panel czatu po naciśnięciu Wróć" name="close_chat_on_return_check" />
<check_box label="Strzałki sterują awatarem podczas czatu" name="arrow_keys_move_avatar_check" />
<check_box label="Pokazuj czas w czacie" name="show_timestamps_check" />
<check_box label="Używaj animacji podczas pisania" name="play_typing_animation" />
- <text type="string" length="1" name="text_box7">
- Czat z Chmurkami:
- </text>
<check_box label="Pokazuj chmurki w czacie" name="bubble_text_chat" />
<slider label="Przeźroczystość" name="bubble_chat_opacity" />
</panel>
diff --git a/indra/newview/skins/default/xui/pl/panel_preferences_general.xml b/indra/newview/skins/default/xui/pl/panel_preferences_general.xml
index 1199f0622f..97b4975f29 100755
--- a/indra/newview/skins/default/xui/pl/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/pl/panel_preferences_general.xml
@@ -1,148 +1,91 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Ogólne" name="general_panel">
- <radio_group name="default_start_location">
- <radio_item name="MyHome" tool_tip="Domyślnie loguj mnie do mojego miejsca startu.">
- Mój Start
- </radio_item>
- <radio_item name="MyLastLocation" tool_tip="Domyślnie loguj mnie do ostatnio odwiedzonego miejsca.">
- Ostatnie Miejsce
- </radio_item>
- </radio_group>
+ <combo_box name="start_location_combo">
+ <combo_box.item name="MyHome" tool_tip="Domyślnie loguj mnie do mojego miejsca startu." label="Mój Start"/>
+ <combo_box.item name="MyLastLocation" tool_tip="Domyślnie loguj mnie do ostatnio odwiedzonego miejsca." label="Ostatnie Miejsce"/>
+ </combo_box>
<check_box label="Pokaż Miejsce Startu podczas Logowania" name="show_location_checkbox"/>
<combo_box name="fade_out_combobox">
- <combo_item name="Never">
- Nigdy
- </combo_item>
- <combo_item name="Show Temporarily">
- Tymczasowo
- </combo_item>
- <combo_item name="Always">
- Zawsze
- </combo_item>
+ <combo_box.item name="Never" label="Nigdy"/>
+ <combo_box.item name="Show Temporarily" label="Tymczasowo"/>
+ <combo_box.item name="Always" label="Zawsze"/>
</combo_box>
<check_box label="Używaj Małych Imion Awatarów" name="small_avatar_names_checkbox"/>
<check_box label="Nie Wyświetlaj Mojego Imienia" name="show_my_name_checkbox"/>
- <text length="1" name="group_titles_textbox" type="string">
+ <text name="group_titles_textbox">
Tytuły Grupowe:
</text>
<check_box label="Nie Wyświetlaj Żadnych Tytułów Grupowych" name="show_all_title_checkbox"/>
<check_box label="Nie Wyświetlaj Mojego Tytułu Grupowego" name="show_my_title_checkbox"/>
<color_swatch label="" name="effect_color_swatch" tool_tip="Selekcja koloru"/>
- <text length="1" name="UI Size:" type="string">
+ <text name="UI Size:">
Wymiar Interfejsu (UI):
</text>
<slider name="ui_scale_slider"/>
<check_box label="Używaj Skali Nizależnej od Rozdzielczości" name="ui_auto_scale"/>
<spinner label="Zasypiaj w:" name="afk_timeout_spinner"/>
<check_box label="Powiadamiaj o Wydatkach i Zarobkach (L$)" name="notify_money_change_checkbox"/>
- <text name="maturity_desired_label" bottom="-312">
+ <text name="maturity_desired_label">
Treść:
</text>
- <text name="maturity_desired_prompt" bottom="-312">
- Chcę uzyskać dostęp do
-miejsc zakwalifikowanych jako:
+ <text name="maturity_desired_prompt">
+ Chcę uzyskać dostęp do miejsc zakwalifikowanych jako:
</text>
- <combo_box name="maturity_desired_combobox" bottom="-330" left="322" width="162" >
- <combo_item name="Desired_Adult">
- &apos;PG&apos;, &apos;Mature&apos; oraz &apos;Adult&apos;
- </combo_item>
- <combo_item name="Desired_Mature">
- &apos;PG&apos; i &apos;Mature&apos;
- </combo_item>
- <combo_item name="Desired_PG">
- tylko &apos;PG&apos;
- </combo_item>
+ <combo_box name="maturity_desired_combobox">
+ <combo_box.item name="Desired_Adult" label="&apos;PG&apos;, &apos;Mature&apos; oraz &apos;Adult&apos;"/>
+ <combo_box.item name="Desired_Mature" label="&apos;PG&apos; i &apos;Mature&apos;"/>
+ <combo_box.item name="Desired_PG" label="&apos;PG&apos;"/>
</combo_box>
- <text name="maturity_desired_textbox" bottom="-324" left="322">
- tylko &apos;PG&apos;
+ <text name="maturity_desired_textbox">
+ &apos;PG&apos;
</text>
- <text length="1" name="start_location_textbox" type="string">
+ <text name="start_location_textbox">
Miejsce Startu:
</text>
- <text length="1" name="show_names_textbox" type="string">
+ <text name="show_names_textbox">
Imiona:
</text>
- <text length="1" name="effects_color_textbox" type="string">
+ <text name="effects_color_textbox">
Kolor dla Moich Efektów:
</text>
- <text length="1" name="seconds_textbox" type="string">
+ <text name="seconds_textbox">
sekund
</text>
- <text length="1" name="crash_report_textbox" type="string">
+ <text name="crash_report_textbox">
Zgłaszanie Błędów:
</text>
- <text length="1" name="language_textbox" type="string">
+ <text name="language_textbox">
Język:
</text>
- <text length="1" name="language_textbox2" type="string">
+ <text name="language_textbox2">
(Restart wymagany)
</text>
<string name="region_name_prompt">
&lt;Wpisz Region&gt;
</string>
<combo_box name="crash_behavior_combobox">
- <combo_item length="1" name="Askbeforesending" type="string">
- Pytaj przed wysłaniem
- </combo_item>
- <combo_item length="1" name="Alwayssend" type="string">
- Zawsze wysyłaj
- </combo_item>
- <combo_item length="1" name="Neversend" type="string">
- Nigdy nie wysyłaj
- </combo_item>
+ <combo_box.item name="Askbeforesending" label="Pytaj przed wysłaniem"/>
+ <combo_box.item name="Alwayssend" label="Zawsze wysyłaj"/>
+ <combo_box.item name="Neversend" label="Nigdy nie wysyłaj"/>
</combo_box>
<combo_box name="language_combobox">
- <combo_item length="1" name="System Default Language" type="string">
- Domyślny
- </combo_item>
- <combo_item length="1" name="English" type="string">
- English (Angielski)
- </combo_item>
- <combo_item name="Danish">
- Dansk (Duński) - Beta
- </combo_item>
- <combo_item length="1" name="Deutsch(German)" type="string">
- Deutsch (Niemiecki) - Beta
- </combo_item>
- <combo_item length="1" name="Spanish" type="string">
- Español (Hiszpański) - Beta
- </combo_item>
- <combo_item length="1" name="French" type="string">
- Français (Francuski) - Beta
- </combo_item>
- <combo_item name="Italian">
- Italiano (WÅ‚oski) - Beta
- </combo_item>
- <combo_item name="Hungarian">
- Magyar (Węgierski) - Beta
- </combo_item>
- <combo_item name="Dutch">
- Nederlands (Niderlandzki) - Beta
- </combo_item>
- <combo_item length="1" name="Polish" type="string">
- Polski - Beta
- </combo_item>
- <combo_item length="1" name="Portugese" type="string">
- Portugués (Portugalski) - Beta
- </combo_item>
- <combo_item name="Russian">
- РуÑÑкий (Rosyjski) - Beta
- </combo_item>
- <combo_item name="Turkish">
- Türkçe (Turecki) - Beta
- </combo_item>
- <combo_item name="Ukrainian">
- УкраїнÑька (UkraiÅ„ski) - Beta
- </combo_item>
- <combo_item length="1" name="Chinese" type="string">
- 中文 (简体) (Chiński) - Beta
- </combo_item>
- <combo_item length="1" name="(Japanese)" type="string">
- 日本語 (Japoński) - Beta
- </combo_item>
- <combo_item length="1" name="(Korean)" type="string">
- 한국어 (Koreański) - Beta
- </combo_item>
+ <combo_box.item name="System Default Language" label="Domyślny"/>
+ <combo_box.item name="English" label="English (Angielski)"/>
+ <combo_box.item name="Danish" label="Dansk (Duński) - Beta"/>
+ <combo_box.item name="Deutsch(German)" label="Deutsch (Niemiecki) - Beta"/>
+ <combo_box.item name="Spanish" label="Español (Hiszpański) - Beta"/>
+ <combo_box.item name="French" label="Français (Francuski) - Beta"/>
+ <combo_box.item name="Italian" label="Italiano (WÅ‚oski) - Beta"/>
+ <combo_box.item name="Hungarian" label="Magyar (Węgierski) - Beta"/>
+ <combo_box.item name="Dutch" label="Nederlands (Niderlandzki) - Beta"/>
+ <combo_box.item name="Polish" label="Polski - Beta"/>
+ <combo_box.item name="Portugese" label="Portugués (Portugalski) - Beta"/>
+ <combo_box.item name="Russian" label="РуÑÑкий (Rosyjski) - Beta"/>
+ <combo_box.item name="Turkish" label="Türkçe (Turecki) - Beta"/>
+ <combo_box.item name="Ukrainian" label="УкраїнÑька (UkraiÅ„ski) - Beta"/>
+ <combo_box.item name="Chinese" label="中文 (简体) (Chiński) - Beta"/>
+ <combo_box.item name="(Japanese)" label="日本語 (Japoński) - Beta"/>
+ <combo_box.item name="(Korean)" label="한국어 (Koreański) - Beta"/>
</combo_box>
<check_box label="Język znany publicznie" name="language_is_public" tool_tip="Pozwala obiektom w świecie poznać Twój wybór język."/>
</panel>
diff --git a/indra/newview/skins/default/xui/pl/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/pl/panel_preferences_graphics1.xml
index 302501ef33..ddd4c736d6 100755
--- a/indra/newview/skins/default/xui/pl/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/pl/panel_preferences_graphics1.xml
@@ -2,80 +2,63 @@
<panel label="Grafika" name="Display panel">
<button label="?" name="GraphicsPreferencesHelpButton" />
<check_box label="Uruchom Second Life w oknie" name="windowed mode" />
- <text_editor type="string" length="1" name="FullScreenInfo">
+ <text_editor name="FullScreenInfo">
Wyłączone = klient uruchamiany w trybie pełnoekranowym.
</text_editor>
- <text type="string" length="1" name="WindowSizeLabel">
+ <text name="WindowSizeLabel">
Wymiary Okna:
</text>
<combo_box name="windowsize combo">
- <combo_item type="string" length="1" name="640x480">
- 640x480
- </combo_item>
- <combo_item type="string" length="1" name="800x600">
- 800x600
- </combo_item>
- <combo_item type="string" length="1" name="720x480">
- 720x480 (NTSC)
- </combo_item>
- <combo_item type="string" length="1" name="768x576">
- 768x576 (PAL)
- </combo_item>
- <combo_item type="string" length="1" name="1024x768">
- 1024x768
- </combo_item>
+ <combo_box.item name="640x480" label="640x480" />
+ <combo_box.item name="800x600" label="800x600" />
+ <combo_box.item name="720x480" label="720x480 (NTSC)" />
+ <combo_box.item name="768x576" label="768x576 (PAL)" />
+ <combo_box.item name="1024x768" label="1024x768" />
</combo_box>
- <text type="string" length="1" name="DisplayResLabel">
+ <text name="DisplayResLabel">
Rozdzielczość:
</text>
- <text type="string" length="1" name="AspectRatioLabel1" tool_tip="width / height">
+ <text name="AspectRatioLabel1" tool_tip="width / height">
Proporcje:
</text>
<combo_box name="aspect_ratio" tool_tip="width / height">
- <combo_item type="string" length="1" name="4:3(StandardCRT)">
- 4:3 (Standardowy CRT)
- </combo_item>
- <combo_item type="string" length="1" name="5:4(1280x1024LCD)">
- 5:4 (1280x1024 LCD)
- </combo_item>
- <combo_item type="string" length="1" name="8:5(Widescreen)">
- 8:5 (Panoramiczny)
- </combo_item>
- <combo_item type="string" length="1" name="16:9(Widescreen)">
- 16:9 (Panoramiczny)
- </combo_item>
+ <combo_box.item name="4:3(StandardCRT)" label="4:3 (Standardowy CRT)" />
+ <combo_box.item name="5:4(1280x1024LCD)" label="5:4 (1280x1024 LCD)" />
+ <combo_box.item name="8:5(Widescreen)" label="8:5 (Panoramiczny)" />
+ <combo_box.item name="16:9(Widescreen)" label="16:9 (Panoramiczny)" />
</combo_box>
<check_box label="Detekcja proporcji" name="aspect_auto_detect" />
- <text type="string" length="1" name="HigherText">
+ <text name="HigherText">
Jakość i
</text>
- <text type="string" length="1" name="QualityText">
+ <text name="QualityText">
Prędkość:
</text>
- <text type="string" length="1" name="FasterText">
+ <text name="FasterText">
Prędkość
</text>
- <text type="string" length="1" name="ShadersPrefText">
+ <text name="ShadersPrefText">
Niska
</text>
- <text type="string" length="1" name="ShadersPrefText2">
+ <text name="ShadersPrefText2">
Åšrednia
</text>
- <text type="string" length="1" name="ShadersPrefText3">
+ <text name="ShadersPrefText3">
Wysoka
</text>
- <text type="string" length="1" name="ShadersPrefText4">
+ <text name="ShadersPrefText4">
Super
</text>
- <text type="string" length="1" name="HigherText2">
+ <text name="HigherText2">
Wyższa
</text>
- <text type="string" length="1" name="QualityText2">
+ <text name="QualityText2">
Jakość
</text>
<slider label="" name="QualityPerformanceSelection" />
<check_box label="Zaawansowane" name="CustomSettings" />
- <text type="string" length="1" name="ShadersText">
+ <panel name="CustomGraphics Panel">
+ <text name="ShadersText">
Shadery:
</text>
<check_box label="Mapowanie Wypukłości i Połysk" name="BumpShiny" />
@@ -83,39 +66,31 @@
tool_tip="Wyłączenie tej opcji może naprawić błędy niektórych sterowników graficznych." />
<check_box label="Shadery Atmosfery" name="WindLightUseAtmosShaders" />
<check_box label="Odbicia w Wodzie" name="Reflections" />
- <text type="string" length="1" name="ReflectionDetailText">
+ <text name="ReflectionDetailText">
Ustawienia Odbić:
</text>
<radio_group name="ReflectionDetailRadio">
- <radio_item type="string" length="1" name="0">
- Teren i Drzewa
- </radio_item>
- <radio_item type="string" length="1" name="1">
- Obiekty Statyczne
- </radio_item>
- <radio_item type="string" length="1" name="2">
- Awatary i Obiekty
- </radio_item>
- <radio_item type="string" length="1" name="3">
- Wszystko
- </radio_item>
+ <radio_item name="0" label="Teren i Drzewa" />
+ <radio_item name="1" label="Obiekty Statyczne" />
+ <radio_item name="2" label="Awatary i Obiekty" />
+ <radio_item name="3" label="Wszystko" />
</radio_group>
- <text type="string" length="1" name="AvatarRenderingText">
+ <text name="AvatarRenderingText">
Prezentacja Awatarów:
</text>
<check_box label="Impostoryzacja Awatarowa" name="AvatarImpostors" />
<check_box label="Skinning" name="AvatarVertexProgram" />
<check_box label="Ubranie Awatarów" name="AvatarCloth" />
- <text type="string" length="1" name="DrawDistanceMeterText1">
+ <text name="DrawDistanceMeterText1">
m
</text>
- <text type="string" length="1" name="DrawDistanceMeterText2">
+ <text name="DrawDistanceMeterText2">
m
</text>
<slider label="Głębia Rysowania:" name="DrawDistance" />
<slider label="Liczba CzÄ…steczek:" name="MaxParticleCount" />
<slider label="Jakość Post-Procesu:" name="RenderPostProcess" />
- <text type="string" length="1" name="MeshDetailText">
+ <text name="MeshDetailText">
Szczegóły Meszu:
</text>
<slider label=" Obiekty:" name="ObjectMeshDetail" />
@@ -124,56 +99,49 @@
<slider label=" Awatary:" name="AvatarMeshDetail" />
<slider label=" Teren:" name="TerrainMeshDetail" />
<slider label=" Niebo:" name="SkyMeshDetail" />
- <text type="string" length="1" name="PostProcessText">
+ <text name="PostProcessText">
Mało
</text>
- <text type="string" length="1" name="ObjectMeshDetailText">
+ <text name="ObjectMeshDetailText">
Mało
</text>
- <text type="string" length="1" name="FlexibleMeshDetailText">
+ <text name="FlexibleMeshDetailText">
Mało
</text>
- <text type="string" length="1" name="TreeMeshDetailText">
+ <text name="TreeMeshDetailText">
Mało
</text>
- <text type="string" length="1" name="AvatarMeshDetailText">
+ <text name="AvatarMeshDetailText">
Mało
</text>
- <text type="string" length="1" name="TerrainMeshDetailText">
+ <text name="TerrainMeshDetailText">
Mało
</text>
- <text type="string" length="1" name="SkyMeshDetailText">
+ <text name="SkyMeshDetailText">
Mało
</text>
- <text type="string" length="1" name="LightingDetailText">
+ <text name="LightingDetailText">
Ustawienia Światła:
</text>
<radio_group name="LightingDetailRadio">
- <radio_item type="string" length="1" name="SunMoon">
- Tylko Słońce i Księżyc
- </radio_item>
- <radio_item type="string" length="1" name="LocalLights">
- Tylko Bliskie Światła
- </radio_item>
+ <radio_item name="SunMoon" label="Tylko Słońce i Księżyc" />
+ <radio_item name="LocalLights" label="Tylko Bliskie Światła" />
</radio_group>
- <text type="string" length="1" name="TerrainDetailText">
+ <text name="TerrainDetailText">
Szczgóły Terenu:
</text>
<radio_group name="TerrainDetailRadio">
- <radio_item type="string" length="1" name="0">
- Mało
- </radio_item>
- <radio_item type="string" length="1" name="2">
- Dużo
- </radio_item>
+ <radio_item name="0" label="Mało" />
+ <radio_item name="2" label="Dużo" />
</radio_group>
+ </panel>
<button label="Ustawienia Domyślne" name="Defaults" />
<button label="Ustawnia Sprzętowe" label_selected="Ustawienia Sprzętowe"
name="GraphicsHardwareButton" />
- <string name="resolution_format">
+ <panel.string name="resolution_format">
[RES_X] x [RES_Y]
- </string>
- <string name="aspect_ratio_text">
+ </panel.string>
+ <panel.string name="aspect_ratio_text">
[NUM]:[DEN]
- </string>
+ </panel.string>
</panel>
diff --git a/indra/newview/skins/default/xui/pl/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/pl/panel_preferences_privacy.xml
new file mode 100755
index 0000000000..e3cdaae840
--- /dev/null
+++ b/indra/newview/skins/default/xui/pl/panel_preferences_privacy.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel label="Komunikacja" name="im">
+ <text name="text_box">
+ Mój Status Online:
+ </text>
+ <check_box label="Mój status online jest dostepny tylko dla Znajomych i Grup"
+ name="online_visibility" />
+ <text name="text_box2">
+ Ustawienia IM:
+ </text>
+ <string name="log_in_to_change">
+ zaloguj się żeby zmienić
+ </string>
+ <check_box label="Wysyłaj IMy na email ([EMAIL])" name="send_im_to_email" />
+ <check_box label="Dołącz IMy do Konsola Czatu" name="include_im_in_chat_console" />
+ <check_box label="Pokazuj czas w IM" name="show_timestamps_check" />
+ <check_box label="Powiadamiaj o zalogowanych znajomych"
+ name="friends_online_notify_checkbox" />
+ <text name="text_box3">
+ Pracuś Mówi:
+ </text>
+ <text name="text_box4">
+ Ustawienia Zapisu:
+ </text>
+ <check_box label="Zapisuj IMy" name="log_instant_messages" />
+ <check_box label="Pokazuj czas w zapisie IM" name="log_instant_messages_timestamp" />
+ <check_box label="Pokazuj koniec ostatniego dialogu IM" name="log_show_history" />
+ <check_box label="Zapisuj czat" name="log_chat" />
+ <check_box label="Pokazuj czas w zapisie czatu" name="log_chat_timestamp" />
+ <check_box label="Pokazuj nowe IMy w zapisie czatu" name="log_chat_IM" />
+ <check_box label="Pokazuj czas Å‚Ä…cznie z datÄ…" name="log_date_timestamp" />
+ <button label="Lokacja" label_selected="Lokacja" name="log_path_button" />
+</panel>
diff --git a/indra/newview/skins/default/xui/pl/panel_preferences_setup.xml b/indra/newview/skins/default/xui/pl/panel_preferences_setup.xml
new file mode 100755
index 0000000000..1e2289b496
--- /dev/null
+++ b/indra/newview/skins/default/xui/pl/panel_preferences_setup.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Joystick i Kamera" name="Input panel">
+ <text name=" Mouselook Options:">
+ Widok Panoramiczny:
+ </text>
+ <text name=" Mouse Sensitivity:">
+ Czułość Myszki:
+ </text>
+ <slider_bar name="mouse_sensitivity"/>
+ <check_box label="Zamień klawisze myszy" name="invert_mouse"/>
+ <text name=" Auto Fly Options:">
+ Automatczne Latanie:
+ </text>
+ <check_box label="Lataj/Ląduj Używając Klawiszy PgUp/PgDn" name="automatic_fly"/>
+ <text name=" Camera Options:">
+ Ustawienia Kamery:
+ </text>
+ <text name="camera_fov_label">
+ KÄ…t Widoku Kamery:
+ </text>
+ <text name="Camera Follow Distance:">
+ Dystans Kamery:
+ </text>
+ <check_box label="Edycja - Automatyczny Ruch Kamery" name="edit_camera_movement" tool_tip="Używaj automatycznego ustawienia kamery podczas włączania i wyłączania trybu edycji"/>
+ <check_box label="Wygląd - Automatyczny Ruch Kamery" name="appearance_camera_movement" tool_tip="Używaj automatycznego ustawienia kamery w trybu edycji"/>
+ <text name="text2">
+ Wyświetlanie Awatara:
+ </text>
+ <check_box label="Awatar Widoczny w Trybie Panoramicznym" name="first_person_avatar_visible"/>
+ <button label="Ustawienia Joysticka" name="joystick_setup_button"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/pl/panel_preferences_sound.xml b/indra/newview/skins/default/xui/pl/panel_preferences_sound.xml
new file mode 100755
index 0000000000..64e3acfcde
--- /dev/null
+++ b/indra/newview/skins/default/xui/pl/panel_preferences_sound.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel label="Audio i Video" name="Preference Media panel">
+ <slider label="Master" name="System Volume"/>
+ <slider label="Otoczenie" name="Wind Volume"/>
+ <slider label="Dźwięki" name="SFX Volume"/>
+ <slider label="Media" name="Media Volume"/>
+ <slider label="UI" name="UI Volume"/>
+ <slider label="Muzyka" name="Music Volume"/>
+ <slider label="GÅ‚os" name="Voice Volume"/>
+ <text_editor name="voice_unavailable">
+ Rozmowy są Niedostępne
+ </text_editor>
+ <check_box label="Pozwól na Rozmowy" name="enable_voice_check"/>
+ <radio_group name="ear_location">
+ <radio_item name="0" label="Odtwarzaj głos z pozycji kamery" />
+ <radio_item name="1" label="Odtwarzaj głos z pozycji awatara" />
+ </radio_group>
+ <button label="Ustawienia Sprzętowe" name="device_settings_btn"/>
+ <text name="muting_text">
+ Głośność:
+ </text>
+ <text name="streaming_prefs_text">
+ Ustawienia Strumieni:
+ </text>
+ <text name="audio_prefs_text">
+ Ustawienia Audio:
+ </text>
+ <panel label="Głośność" name="Volume Panel" />
+ <check_box label="Odtwarzaj Strumienie Muzyki"
+ name="streaming_music" />
+ <check_box label="Odtwarzaj Strumienie Video"
+ name="streaming_video" />
+ <check_box label="Automatycznie Odtwarzaj Media" name="auto_streaming_video" />
+ <check_box label="Wyciszaj Audio Podczas Minimalizacji Okna" name="mute_when_minimized" />
+ <slider label="Efekt Dopplera" name="Doppler Effect" />
+ <slider label="Wpływ Dystansu" name="Distance Factor" />
+ <slider label="Wyciszanie" name="Rolloff Factor" />
+ <spinner label="Próg Zmiany L$" name="L$ Change Threshold" />
+ <spinner label="Próg Zmiany Statusu" name="Health Change Threshold" />
+</panel>
diff --git a/indra/newview/skins/default/xui/pl/panel_region_estate.xml b/indra/newview/skins/default/xui/pl/panel_region_estate.xml
index 5ef94baaa5..4275f3f647 100755
--- a/indra/newview/skins/default/xui/pl/panel_region_estate.xml
+++ b/indra/newview/skins/default/xui/pl/panel_region_estate.xml
@@ -23,7 +23,7 @@ do wszystkich Regionów w tym Majątku.
<slider label="Pora Doby" name="sun_hour_slider"/>
<check_box label="Dostęp Publiczny" name="externally_visible_check"/>
<button label="?" name="externally_visible_help"/>
- <text length="1" name="Only Allow" type="string">
+ <text name="Only Allow">
Dostęp Ograniczony do:
</text>
<check_box label="Rezydenci z danymi o koncie" name="limit_payment" tool_tip="Zablokuj niepożądanych Rezydentów."/>
diff --git a/indra/newview/skins/default/xui/pl/panel_region_general.xml b/indra/newview/skins/default/xui/pl/panel_region_general.xml
index 36cff9c2d0..20296dac71 100755
--- a/indra/newview/skins/default/xui/pl/panel_region_general.xml
+++ b/indra/newview/skins/default/xui/pl/panel_region_general.xml
@@ -40,15 +40,9 @@
Rodzaj:
</text>
<combo_box label="&apos;Mature&apos;" name="access_combo">
- <combo_item name="Adult">
- &apos;Adult&apos;
- </combo_item>
- <combo_item name="Mature">
- &apos;Mature&apos;
- </combo_item>
- <combo_item name="PG">
- &apos;PG&apos;
- </combo_item>
+ <combo_box.item label="&apos;Adult&apos;" name="Adult"/>
+ <combo_box.item label="&apos;Mature&apos;" name="Mature"/>
+ <combo_box.item label="&apos;PG&apos;" name="PG"/>
</combo_box>
<button label="?" name="access_help"/>
<button label="Zastosuj" name="apply_btn"/>
diff --git a/indra/newview/skins/default/xui/pl/panel_scrolling_param.xml b/indra/newview/skins/default/xui/pl/panel_scrolling_param.xml
index f057c824ac..70a6e39412 100755
--- a/indra/newview/skins/default/xui/pl/panel_scrolling_param.xml
+++ b/indra/newview/skins/default/xui/pl/panel_scrolling_param.xml
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="LLScrollingPanelParam">
- <text type="string" length="1" name="Loading...">
+ <text name="Loading...">
Åadowanie...
</text>
- <text type="string" length="1" name="Loading...2">
+ <text name="Loading...2">
Åadowanie...
</text>
<button label="" label_selected="" name="less" />
diff --git a/indra/newview/skins/default/xui/pl/panel_status_bar.xml b/indra/newview/skins/default/xui/pl/panel_status_bar.xml
index bdf22fa66d..9226e67dff 100755
--- a/indra/newview/skins/default/xui/pl/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/pl/panel_status_bar.xml
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="status">
- <text type="string" length="1" name="ParcelNameText" tool_tip="Nazwa posiadłości w której się znajdujesz. Po więcej informacji kliknij O Posiadłości.">
+ <text name="ParcelNameText" tool_tip="Nazwa posiadłości w której się znajdujesz. Po więcej informacji kliknij O Posiadłości.">
Nazwa Posiadłości
</text>
- <text type="string" length="1" name="BalanceText" tool_tip="Stan Konta">
+ <text name="BalanceText" tool_tip="Stan Konta">
Åadowanie...
</text>
<button label="" label_selected="" name="buycurrency" tool_tip="Kup $L" />
- <text type="string" length="12" name="TimeText" tool_tip="Obecny Czas (Pacyficzny)">
+ <text name="TimeText" tool_tip="Obecny Czas (Pacyficzny)">
12:00 AM
</text>
<string name="StatBarDaysOfWeek">
@@ -18,7 +18,7 @@
</string>
<button label="" label_selected="" name="scriptout" tool_tip="Błędy i Ostrzeżenia Skryptów" />
<button label="" label_selected="" name="health" tool_tip="Stan" />
- <text type="string" length="1" name="HealthText" tool_tip="Stan">
+ <text name="HealthText" tool_tip="Stan">
100%
</text>
<button label="" label_selected="" name="no_fly" tool_tip="Latanie jest niedozwolone" />
@@ -28,8 +28,8 @@
<button label="" label_selected="" name="status_no_voice" tool_tip="Używanie komunikacji głosowej jest niedozwolone" />
<button label="" label_selected="" name="buyland" tool_tip="Kup tą posiadłość" />
<button label="" name="menubar_search_bevel_bg" />
- <line_editor label="Szukaj" name="search_editor" tool_tip="Szukaj w Second Life" />
- <button label="" label_selected="" name="search_btn" tool_tip="Szukaj w Second Life" />
+ <line_editor label="Szukaj" name="search_editor" tool_tip="Szukaj w [SECOND_LIFE]" />
+ <button label="" label_selected="" name="search_btn" tool_tip="Szukaj w [SECOND_LIFE]" />
<string name="packet_loss_tooltip">
Utracone Pakiety
</string>
diff --git a/indra/newview/skins/default/xui/pl/panel_world_map.xml b/indra/newview/skins/default/xui/pl/panel_world_map.xml
new file mode 100644
index 0000000000..608f102dc9
--- /dev/null
+++ b/indra/newview/skins/default/xui/pl/panel_world_map.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="world_map">
+ <panel.string name="world_map_north">
+ N
+ </panel.string>
+ <panel.string name="world_map_east">
+ E
+ </panel.string>
+ <panel.string name="world_map_west">
+ W
+ </panel.string>
+ <panel.string name="world_map_south">
+ S
+ </panel.string>
+ <panel.string name="world_map_southeast">
+ SE
+ </panel.string>
+ <panel.string name="world_map_northeast">
+ NE
+ </panel.string>
+ <panel.string name="world_map_southwest">
+ SW
+ </panel.string>
+ <panel.string name="world_map_northwest">
+ NW
+ </panel.string>
+ <text label="N" name="floater_map_north" text="N">
+ N
+ </text>
+ <text label="E" name="floater_map_east" text="E">
+ E
+ </text>
+ <text label="W" name="floater_map_west" text="W">
+ W
+ </text>
+ <text label="S" name="floater_map_south" text="S">
+ S
+ </text>
+ <text label="SE" name="floater_map_southeast" text="SE">
+ SE
+ </text>
+ <text label="NE" name="floater_map_northeast" text="NE">
+ NE
+ </text>
+ <text label="SW" name="floater_map_southwest" text="SW">
+ SW
+ </text>
+ <text label="NW" name="floater_map_northwest" text="NW">
+ NW
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/pl/strings.xml b/indra/newview/skins/default/xui/pl/strings.xml
index 5067f044e0..1f67944f86 100755
--- a/indra/newview/skins/default/xui/pl/strings.xml
+++ b/indra/newview/skins/default/xui/pl/strings.xml
@@ -55,6 +55,9 @@
<string name="LoginDownloadingClothing">
Åadowanie ubrania...
</string>
+ <string name="Quit">
+ Wyjdź
+ </string>
<string name="AgentLostConnection">
Ten region może mieć problemy. Sprawdź podłączenie do Internetu.
</string>
@@ -483,4 +486,169 @@
<string name="choose_the_directory">
Wybierz Katalog
</string>
+ <string name="accel-mac-control">
+ &#8963;
+ </string>
+ <string name="accel-mac-command">
+ &#8984;
+ </string>
+ <string name="accel-mac-option">
+ &#8997;
+ </string>
+ <string name="accel-mac-shift">
+ &#8679;
+ </string>
+ <string name="accel-win-control">
+ Ctrl+
+ </string>
+ <string name="accel-win-alt">
+ Alt+
+ </string>
+ <string name="accel-win-shift">
+ Shift+
+ </string>
+ <string name="GraphicsQualityLow">
+ Niska
+ </string>
+ <string name="GraphicsQualityMid">
+ Åšrednia
+ </string>
+ <string name="GraphicsQualityHigh">
+ Wysoka
+ </string>
+
+ <!-- PARCEL_CATEGORY_UI_STRING -->
+ <string name="Linden Location">Linden Lokacja</string>
+ <string name="Adult">&apos;Adult&apos;</string>
+ <string name="Arts&amp;Culture">Sztuka i Kultura</string>
+ <string name="Business">Biznes</string>
+ <string name="Educational">Edukacyjna</string>
+ <string name="Gaming">Gra</string>
+ <string name="Hangout">Poznawanie ludzi</string>
+ <string name="Newcomer Friendly">Przyjazne dla nowych</string>
+ <string name="Parks&amp;Nature">Park i Natura</string>
+ <string name="Residential">Mieszkalna</string>
+ <string name="Shopping">Zakupy</string>
+ <string name="Other">Inna</string>
+
+ <string name="ringing">
+ ÅÄ…czenie z rozmowami gÅ‚osem w Å›wiecie...
+ </string>
+ <string name="connected">
+ Połączenie uzyskane.
+ </string>
+ <string name="unavailable">
+ Niestety, rozmowy głosem są niedozwolone w tym miejscu.
+ </string>
+ <string name="hang_up">
+ Połączenie rozmowy utracone.
+ </string>
+ <string name="ScriptQuestionCautionChatGranted">
+ &apos;[OBJECTNAME]&apos;, właściciel: &apos;[OWNERNAME]&apos;, położenie: [REGIONNAME] [REGIONPOS], pozwala Ci na: [PERMISSIONS].
+ </string>
+ <string name="ScriptQuestionCautionChatDenied">
+ &apos;[OBJECTNAME]&apos;, właściciel: &apos;[OWNERNAME]&apos;, położenie: [REGIONNAME] [REGIONPOS], nie pozwala Ci na: [PERMISSIONS].
+ </string>
+ <string name="ScriptTakeMoney">
+ Zabiera Lindeny (L$) od Ciebie
+ </string>
+ <string name="ActOnControlInputs">
+ Używaj klawiszy sterowania
+ </string>
+ <string name="RemapControlInputs">
+ Zmień klawisze sterowania
+ </string>
+ <string name="AnimateYourAvatar">
+ Animuj Awatara
+ </string>
+ <string name="AttachToYourAvatar">
+ Dołącz do Awatara
+ </string>
+ <string name="ReleaseOwnership">
+ Usuń prawo własności (zmień na publiczne)
+ </string>
+ <string name="LinkAndDelink">
+ ÅÄ…cz / odÅ‚Ä…cz z innymi obiektów
+ </string>
+ <string name="AddAndRemoveJoints">
+ Dodaj / usuń połączenia z innymi obiektami
+ </string>
+ <string name="ChangePermissions">
+ Ustaw zezwolenia
+ </string>
+ <string name="TrackYourCamera">
+ Chodź za kamerą
+ </string>
+ <string name="ControlYourCamera">
+ Kontroluj kamerÄ™
+ </string>
+ <string name="only_user_message">
+ JesteÅ› jedynÄ… osobÄ… w tej konferencji.
+ </string>
+ <string name="offline_message">
+ [FIRST] [LAST] - ta osoba jest obecnie niedostępna.
+ </string>
+ <string name="invite_message">
+ Kliknij na [BUTTON NAME] przycisk by zaakceptować/dołączyć do tej rozmowy.
+ </string>
+ <string name="generic_request_error">
+ Błąd. Spróbuj ponownie za kilka minut.
+ </string>
+ <string name="insufficient_perms_error">
+ Nie posiadasz praw do kontynuacji.
+ </string>
+ <string name="session_does_not_exist_error">
+ Ta konferencja jest już zakończona.
+ </string>
+ <string name="no_ability_error">
+ Nie posiadesz tego przywileju.
+ </string>
+ <string name="no_ability">
+ Nie posiadesz tego przywileju.
+ </string>
+ <string name="not_a_mod_error">
+ Nie jesteÅ› moderatorem konferencji.
+ </string>
+ <string name="muted_error">
+ Moderator wyciszył Cię.
+ </string>
+ <string name="add_session_event">
+ Nie można dodać nikogo do czatu z [RECIPIENT].
+ </string>
+ <string name="message_session_event">
+ Nie można wysłać Twojej wiadomości do sesji czatu z [RECIPIENT].
+ </string>
+ <string name="removed_from_group">
+ Usunięto Cię z grupy.
+ </string>
+ <string name="close_on_no_ability">
+ Nie posiadasz praw by uczestniczyć w tej konferencji.
+ </string>
+ <string name="AcctTypeResident">
+ Rezydent
+ </string>
+ <string name="AcctTypeTrial">
+ Próbne
+ </string>
+ <string name="AcctTypeCharterMember">
+ Członek-zalożyciel
+ </string>
+ <string name="AcctTypeEmployee">
+ Pracownik Linden Lab
+ </string>
+ <string name="PaymentInfoUsed">
+ Dane Konta Używane
+ </string>
+ <string name="PaymentInfoOnFile">
+ Dane Konta Dostępne
+ </string>
+ <string name="NoPaymentInfoOnFile">
+ Brak Danych Konta
+ </string>
+ <string name="AgeVerified">
+ Wiek Zweryfikowany
+ </string>
+ <string name="NotAgeVerified">
+ Brak Weryfikacji Wieku
+ </string>
</strings>
diff --git a/indra/newview/skins/default/xui/pt/floater_about.xml b/indra/newview/skins/default/xui/pt/floater_about.xml
index 4186e5e207..704e2f4107 100644
--- a/indra/newview/skins/default/xui/pt/floater_about.xml
+++ b/indra/newview/skins/default/xui/pt/floater_about.xml
@@ -1,10 +1,18 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_about" title="Sobre o Second Life">
+<floater name="floater_about" title="SOBRE O [CAPITALIZED_APP_NAME]">
+<tab_container name="about_tab">
+ <panel name="credits_panel">
<text_editor name="credits_editor">
- Second Life é oferecido a você por Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les e muitos outros.
+ Second Life é oferecido a você por Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, Michon, Jenelle, Geo, Siz, Shapiro, Pete, Calyle, Selene, Allen, Phoebe, Goldin, Kimmora, Dakota, Slaton, Lindquist, Zoey, Hari, Othello, Rohit, Sheldon, Petra, Viale, Gordon, Kaye, Pink, Ferny, Emerson, Davy, Bri, Chan, Juan, Robert, Terrence, Nathan, Carl e muitos outros.
- Obrigado aos seguintes residentes por ajudar a garantir para que esta versão seja ainda melhor: (in progress)
+ Obrigado aos seguintes residentes por ajudar a garantir para que esta versão seja ainda melhor: able whitman, Adeon Writer, adonaira aabye, Aeron Kohime, Agathos Frascati, Aimee Trescothick, Aleric Inglewood, Alissa Sabre, Aminom Marvin, Angela Talamasca, Aralara Rajal, Armin Weatherwax, Ashrilyn Hayashida, Athanasius Skytower, Aura Dirval, Barney Boomslang, Biancaluce Robbiani, Biker Offcourse, Borg Capalini, Bulli Schumann, catherine pfeffer, Chalice Yao, Corre Porta, Court Goodman, Cummere Mayo, Dale Innis, Darien Caldwell, Darjeeling Schoonhoven, Daten Thielt, dimentox travanti, Dirk Talamasca, Drew Dwi, Duckless Vandyke, Elanthius Flagstaff, Electro Burnstein, emiley tomsen, Escort DeFarge, Eva Rau, Ezian Ecksol, Fire Centaur, Fluf Fredriksson, Francisco Koolhoven, Frontera Thor, Frungi Stastny, Gally Young, gearsawe stonecutter, Gigs Taggart, Gordon Wendt, Gudmund Shepherd, Gypsy Paz, Harleen Gretzky, Henri Beauchamp, Inma Rau, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Jessicka Graves, Joeseph Albanese, Joshua Philgarlic, Khyota Wulluf, kirstenlee Cinquetti, Latif Khalifa, Lex Neva, Lilibeth Andree, Lisa Lowe, Lunita Savira, Loosey Demonia, lum pfohl, Marcos Fonzarelli, MartinRJ Fayray, Marusame Arai, Matthew Dowd, Maya Remblai, McCabe Maxsted, Meghan Dench, Melchoir Tokhes, Menos Short, Michelle2 Zenovka, Mimika Oh, Minerva Memel, Mm Alder, Ochi Wolfe, Omei Turnbull, Pesho Replacement, Phantom Ninetails, phoenixflames kukulcan, Polo Gufler, prez pessoa, princess niven, Prokofy Neva, Qie Niangao, Rem Beattie, RodneyLee Jessop, Saijanai Kuhn, Seg Baphomet, Sergen Davies, Shirley Marquez, SignpostMarv Martin, Sindy Tsure, Sira Arbizu, Skips Jigsaw, Sougent Harrop, Spritely Pixel, Squirrel Wood, StarSong Bright, Subversive Writer, Sugarcult Dagger, Sylumm Grigorovich, Tammy Nowotny, Tanooki Darkes, Tayra Dagostino, Theoretical Chemistry, Thickbrick Sleaford, valerie rosewood, Vex Streeter, Vixen Heron, Whoops Babii, Winter Ventura, Xiki Luik, Yann Dufaux, Yina Yao, Yukinoroh Kamachi, Zolute Infinity, Zwagoth Klaar
+
+ Para ter sucesso nos negócios, seja ousado, seja o primeiro, seja diferente. --Henry Marchant
+ </text_editor>
+ </panel>
+ <panel name="licenses_panel">
+ <text_editor name="credits_editor">
3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
APR Copyright (C) 2000-2004 The Apache Software Foundation
cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
@@ -26,10 +34,9 @@
Todos os direitos reservados. Veja licenças.txt para detalhes.
Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
-
-
- Para ter sucesso nos negócios, seja ousado, seja o primeiro, seja diferente. --Henry Marchant
</text_editor>
+ </panel>
+</tab_container>
<string name="you_are_at">
Você está em [POSITION]
</string>
diff --git a/indra/newview/skins/default/xui/pt/floater_about_land.xml b/indra/newview/skins/default/xui/pt/floater_about_land.xml
index 4426378075..19981cf48c 100644
--- a/indra/newview/skins/default/xui/pt/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/pt/floater_about_land.xml
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterland" title="Sobre o Terreno">
+<floater name="floaterland" title="SOBRE O TERRENO">
<tab_container name="landtab">
<panel label="Geral" name="land_general_panel">
- <text length="1" name="Name:" type="string">
+ <text name="Name:">
Nome:
</text>
- <text length="1" name="Description:" type="string">
+ <text name="Description:">
Descrição:
</text>
<text name="LandType">
@@ -20,56 +20,56 @@
<text name="ContentRatingText">
Adult
</text>
- <text length="1" name="Owner:" type="string">
+ <text name="Owner:">
Proprietário:
</text>
- <text length="1" name="OwnerText" type="string">
+ <text name="OwnerText">
Leyla Linden
</text>
<button label="Perfil..." label_selected="Perfil..." name="Profile..."/>
- <text length="1" name="Group:" type="string">
+ <text name="Group:">
Grupo:
</text>
<button label="Ajustar..." label_selected="Ajustar..." name="Set..."/>
<check_box label="Permitir posse para o grupo" name="check deed" tool_tip="O gerente do grupo pode acionar essa terra ao grupo, então esta será mantida pelo gestor da ilha"/>
<button label="Passar..." label_selected="Passar..." name="Deed..." tool_tip="Você só pode delegar esta terra se você for um gerente selecionado pelo grupo."/>
<check_box label="Proprietário faz contribuição com delegação" name="check contrib" tool_tip="Quando a terra é delegada ao grupo, o proprietário anterior contribui alocando terra suficiente para mantê-la."/>
- <text length="1" name="For Sale:" type="string">
+ <text name="For Sale:">
À Venda:
</text>
- <text length="1" name="Not for sale." type="string">
+ <text name="Not for sale.">
Não está à Venda.
</text>
- <text length="1" name="For Sale: Price L$[PRICE]." type="string">
+ <text name="For Sale: Price L$[PRICE].">
Preço: L$[PRICE] (L$[PRICE_PER_SQM]/m²).
</text>
<button label="Vender Terra..." label_selected="Vender Terra..." name="Sell Land..."/>
- <text length="1" name="For sale to" type="string">
+ <text name="For sale to">
À venda para: [BUYER]
</text>
- <text length="1" name="Sell with landowners objects in parcel." type="string">
+ <text name="Sell with landowners objects in parcel.">
À venda (Objetos incluídos).
</text>
- <text length="1" name="Selling with no objects in parcel." type="string">
+ <text name="Selling with no objects in parcel.">
À venda (Objetos não incluídos).
</text>
<button label="Cancelar venda do terreno" label_selected="Cancelar venda do terreno" left="275" name="Cancel Land Sale" width="165"/>
- <text length="1" name="Claimed:" type="string">
+ <text name="Claimed:">
Reclamado:
</text>
- <text length="1" name="DateClaimText" type="string">
+ <text name="DateClaimText">
Ter Ago 15 13:47:25 2006
</text>
- <text length="1" name="PriceLabel" type="string">
+ <text name="PriceLabel">
Ãrea:
</text>
- <text length="1" name="PriceText" type="string">
+ <text name="PriceText">
4048 m²
</text>
- <text length="1" name="Traffic:" type="string">
+ <text name="Traffic:">
Tráfego:
</text>
- <text length="1" name="DwellText" type="string">
+ <text name="DwellText">
0
</text>
<button label="Comprar Terra..." label_selected="Comprar Terra..." left="130" name="Buy Land..." width="125"/>
@@ -78,76 +78,76 @@
<button label="Abandonar Terra.." label_selected="Abandonar Terra.." name="Abandon Land..."/>
<button label="Reclamar Terra..." label_selected="Reclamar Terra..." name="Reclaim Land..."/>
<button label="Venda Linden..." label_selected="Venda Linden..." name="Linden Sale..." tool_tip="A terra precisa ser possuída, estar com o conteúdo configurado e não estar pronta para leilão."/>
- <string name="new users only">
+ <panel.string name="new users only">
Somente novos usuários
- </string>
- <string name="anyone">
+ </panel.string>
+ <panel.string name="anyone">
Qualquer um
- </string>
- <string name="area_text">
+ </panel.string>
+ <panel.string name="area_text">
Ãrea
- </string>
- <string name="area_size_text">
+ </panel.string>
+ <panel.string name="area_size_text">
[AREA] m²
- </string>
- <string name="auction_id_text">
+ </panel.string>
+ <panel.string name="auction_id_text">
ID do Leilão: [ID]
- </string>
- <string name="need_tier_to_modify">
+ </panel.string>
+ <panel.string name="need_tier_to_modify">
Você deve ter sua compra aprovada para modificar este terreno.
- </string>
- <string name="group_owned_text">
+ </panel.string>
+ <panel.string name="group_owned_text">
(Possuído pelo Grupo)
- </string>
- <string name="profile_text">
+ </panel.string>
+ <panel.string name="profile_text">
Perfil...
- </string>
- <string name="info_text">
+ </panel.string>
+ <panel.string name="info_text">
Informação...
- </string>
- <string name="public_text">
+ </panel.string>
+ <panel.string name="public_text">
(público)
- </string>
- <string name="none_text">
+ </panel.string>
+ <panel.string name="none_text">
(nenhum)
- </string>
- <string name="sale_pending_text">
+ </panel.string>
+ <panel.string name="sale_pending_text">
(Venda Pendente)
- </string>
- <string name="no_selection_text">
+ </panel.string>
+ <panel.string name="no_selection_text">
Nenhum lote selecionado.
Vá para o menu Mundo &gt; Sobre a Terra ou selecione outro lote para mostrar seus detalhes.
- </string>
+ </panel.string>
</panel>
<panel label="Corretor" name="land_covenant_panel">
<text name="estate_section_lbl">
Propriedade:
</text>
- <text length="1" name="estate_name_lbl" type="string">
+ <text name="estate_name_lbl">
Nome:
</text>
- <text length="1" name="estate_name_text" type="string">
+ <text name="estate_name_text">
mainland
</text>
- <text length="1" name="estate_owner_lbl" type="string">
+ <text name="estate_owner_lbl">
Dono:
</text>
- <text length="1" name="estate_owner_text" type="string">
+ <text name="estate_owner_text">
(nenhum)
</text>
- <text_editor length="1" name="covenant_editor" type="string">
+ <text_editor name="covenant_editor">
Não há corretor para esta Propriedade.
</text_editor>
- <text length="1" name="covenant_timestamp_text" type="string">
+ <text name="covenant_timestamp_text">
Última Alteração: Qua, Dez 31 16:00:00 1969
</text>
<text name="region_section_lbl">
Região:
</text>
- <text length="1" name="region_name_lbl" type="string">
+ <text name="region_name_lbl">
Nome:
</text>
- <text length="1" name="region_name_text" type="string">
+ <text name="region_name_text">
leyla
</text>
<text name="region_landtype_lbl">
@@ -165,93 +165,93 @@ Vá para o menu Mundo &gt; Sobre a Terra ou selecione outro lote para mostrar se
<text name="resellable_lbl">
Revender:
</text>
- <text length="1" name="resellable_clause" type="string">
+ <text name="resellable_clause">
Terra nesta região não pode ser revendida.
</text>
<text name="changeable_lbl">
Subdividir:
</text>
- <text length="1" name="changeable_clause" type="string">
+ <text name="changeable_clause">
Terra nesta região não pode ser unida/sub-dividida.
</text>
- <string name="can_resell">
+ <panel.string name="can_resell">
Terra comprada nesta região pode ser revendida.
- </string>
- <string name="can_not_resell">
+ </panel.string>
+ <panel.string name="can_not_resell">
Terra comprada nesta região não pode ser revendida.
- </string>
- <string name="can_change">
+ </panel.string>
+ <panel.string name="can_change">
Terra comprada nesta região pode ser compartilhada
ou sub-dividida.
- </string>
- <string name="can_not_change">
+ </panel.string>
+ <panel.string name="can_not_change">
Terra comprada nesta região não pode ser compartilhada
ou sub-dividida.
- </string>
+ </panel.string>
</panel>
<panel label="Objetos" name="land_objects_panel">
<text name="parcel_object_bonus">
Fator de Bonus para Objetos na Região: [BONUS]
</text>
- <text length="1" name="Simulator primitive usage:" type="string">
+ <text name="Simulator primitive usage:">
Uso do simulador de primitivas:
</text>
<text left="214" name="objects_available" width="230">
[COUNT] de [MAX] ([AVAILABLE] disponíveis)
</text>
- <string name="objects_available_text">
+ <panel.string name="objects_available_text">
[COUNT] de [MAX] ([AVAILABLE] disponíveis)
- </string>
- <string name="objects_deleted_text">
+ </panel.string>
+ <panel.string name="objects_deleted_text">
[COUNT] de [MAX] ([DELETED] serão deletados)
- </string>
- <text length="1" name="Primitives parcel supports:" type="string" width="200">
+ </panel.string>
+ <text name="Primitives parcel supports:" width="200">
Primitivas suportadas pelo lote:
</text>
- <text left="214" length="1" name="object_contrib_text" type="string" width="152">
+ <text left="214" name="object_contrib_text" width="152">
[COUNT]
</text>
- <text length="1" name="Primitives on parcel:" type="string">
+ <text name="Primitives on parcel:">
Primitivas no Lote:
</text>
- <text left="214" length="1" name="total_objects_text" type="string" width="48">
+ <text left="214" name="total_objects_text" width="48">
[COUNT]
</text>
- <text left="14" length="1" name="Owned by parcel owner:" type="string" width="180">
+ <text left="14" name="Owned by parcel owner:" width="180">
Pertencentes ao dono do lote:
</text>
- <text left="214" length="1" name="owner_objects_text" type="string" width="48">
+ <text left="214" name="owner_objects_text" width="48">
[COUNT]
</text>
<button label="Mostrar" label_selected="Mostrar" name="ShowOwner" right="-135" width="60"/>
<button label="Retornar..." label_selected="Retornar..." name="ReturnOwner..." right="-10" tool_tip="Retornar os objetos aos seus donos." width="119"/>
- <text left="14" length="1" name="Set to group:" type="string" width="180">
+ <text left="14" name="Set to group:" width="180">
Configurados ao grupo:
</text>
- <text left="214" length="1" name="group_objects_text" type="string" width="48">
+ <text left="214" name="group_objects_text" width="48">
[COUNT]
</text>
<button label="Mostrar" label_selected="Mostrar" name="ShowGroup" right="-135" width="60"/>
<button label="Retornar..." label_selected="Retornar..." name="ReturnGroup..." right="-10" tool_tip="Retornar os objetos para seus donos." width="119"/>
- <text left="14" length="1" name="Owned by others:" type="string" width="128">
+ <text left="14" name="Owned by others:" width="128">
Propriedade de Outros:
</text>
- <text left="214" length="1" name="other_objects_text" type="string" width="48">
+ <text left="214" name="other_objects_text" width="48">
[COUNT]
</text>
<button label="Mostrar" label_selected="Mostrar" name="ShowOther" right="-135" width="60"/>
<button label="Retornar..." label_selected="Retornar..." name="ReturnOther..." right="-10" tool_tip="Retornar os objetos aos seus donos." width="119"/>
- <text left="14" length="1" name="Selected / sat upon:" type="string" width="193">
+ <text left="14" name="Selected / sat upon:" width="193">
Selecionado/Sentado:
</text>
- <text left="214" length="1" name="selected_objects_text" type="string" width="48">
+ <text left="214" name="selected_objects_text" width="48">
[COUNT]
</text>
- <text left="4" length="1" name="Autoreturn" type="string" width="412">
+ <text left="4" name="Autoreturn" width="412">
Auto-retornar objetos dos outros residentes (minutos, 0 para desligado):
</text>
<line_editor name="clean other time" right="-10"/>
- <text length="1" name="Object Owners:" type="string">
+ <text name="Object Owners:">
Donos dos Objetos:
</text>
<button label="Atualizar Lista" label_selected="Atualizar Lista" name="Refresh List" left="118"/>
@@ -264,168 +264,140 @@ ou sub-dividida.
</name_list>
</panel>
<panel label="Opções" name="land_options_panel">
- <text length="1" name="allow_label" type="string">
+ <text name="allow_label">
Permitir outros residentes a:
</text>
<check_box label="Editar Terreno" name="edit land check" tool_tip="Se ativado, qualquer um pode modificar a forma da sua terra. É melhor deixar esta opção desativada, uma vez que você sempre pode editar seu próprio terreno."/>
<check_box label="Criar Landmarks" name="check landmark"/>
<check_box label="Voar" name="check fly" tool_tip="Se ativado, os Residentes podem voar na sua terra. Se desativado, eles podem voar apenas para dentro e por cima de sua terra."/>
- <text length="1" name="allow_label2" type="string" left="172">
+ <text name="allow_label2" left="172">
Criar Objetos:
</text>
<check_box label="Residentes" name="edit objects check"/>
<check_box label="Grupo" name="edit group objects check"/>
- <text length="1" name="allow_label3" type="string" left="172">
+ <text name="allow_label3" left="172">
Entrada do Objeto:
</text>
<check_box label="Residentes" name="all object entry check"/>
<check_box label="Grupo" name="group object entry check"/>
- <text length="1" name="allow_label4" type="string" left="172">
+ <text name="allow_label4" left="172">
Executar Scripts:
</text>
<check_box label="Residentes" name="check other scripts"/>
<check_box label="Grupo" name="check group scripts"/>
- <text length="1" name="land_options_label" type="string">
+ <text name="land_options_label">
Opções de Terra:
</text>
<check_box label="Salvo (sem dano)" name="check safe" tool_tip="Se ativado, ajusta o terreno para Seguro, desabilitando combate com danos. Se não ativado, o combate com danos é habilitado."/>
<check_box label="Sem Empurrar" name="PushRestrictCheck" tool_tip="Evita scripts que empurram. A ativação dessa opção pode ser útil para prevenir comportamentos desordeiros na sua terra."/>
<check_box label="Mostra o Lugar na Busca (L$30/semana) sob" name="ShowDirectoryCheck" tool_tip="Permitir que as pessoas vejam este terreno nos resultados de busca"/>
- <string name="search_enabled_tooltip">
+ <panel.string name="search_enabled_tooltip">
Permitir que as pessoas vejam este lote nos resultados de busca
- </string>
- <string name="search_disabled_small_tooltip">
+ </panel.string>
+ <panel.string name="search_disabled_small_tooltip">
Esta opção está desabilitada porque a área deste lote tem 128 m² ou menos.
Apenas lotes maiores podem ser listados na busca.
- </string>
- <string name="search_disabled_permissions_tooltip">
+ </panel.string>
+ <panel.string name="search_disabled_permissions_tooltip">
Esta opção está desabilitada porque você não pode modificar as opções deste lote.
- </string>
- <combo_box name="land category with adult">
- <combo_item name="AnyCategory">
- Qualquer Categoria
- </combo_item>
- <combo_item name="LindenLocation">
- Local da Linden
- </combo_item>
- <combo_item name="Adult">
- Adult
- </combo_item>
- <combo_item name="Arts&amp;Culture">
- Artes &amp; Cultura
- </combo_item>
- <combo_item name="Business">
- Negócios
- </combo_item>
- <combo_item name="Educational">
- Educacional
- </combo_item>
- <combo_item name="Gaming">
- Jogos
- </combo_item>
- <combo_item name="Hangout">
- Moradia
- </combo_item>
- <combo_item name="NewcomerFriendly">
- Amigável a Novos Usuários
- </combo_item>
- <combo_item name="Parks&amp;Nature">
- Parques &amp; Natureza
- </combo_item>
- <combo_item name="Residential">
- Residencial
- </combo_item>
- <combo_item name="Shopping">
- Shopping
- </combo_item>
- <combo_item name="Other">
- Outros
- </combo_item>
+ </panel.string>
+ <combo_box name="land category with adult" left="265" width="155">
+ <combo_box.item name="item0" label="Qualquer Categoria"
+ />
+ <combo_box.item name="item1" label="Locação Linden"
+ />
+ <combo_box.item name="item2" label="Adult"
+ />
+ <combo_box.item name="item3" label="Artes e Cultura"
+ />
+ <combo_box.item name="item4" label="Negócios"
+ />
+ <combo_box.item name="item5" label="Educacional"
+ />
+ <combo_box.item name="item6" label="Jogos"
+ />
+ <combo_box.item name="item7" label="Moradia"
+ />
+ <combo_box.item name="item8" label="Amigável a Novos Usuários"
+ />
+ <combo_box.item name="item9" label="Parques &amp; Natureza"
+ />
+ <combo_box.item name="item10" label="Residencial"
+ />
+ <combo_box.item name="item11" label="Compras"
+ />
+ <combo_box.item name="item12" label="Outros"
+ />
</combo_box>
- <combo_box left="276" name="land category" width="146">
- <combo_item name="AnyCategory">
- Qualquer Categoria
- </combo_item>
- <combo_item name="LindenLocation">
- Locação Linden
- </combo_item>
- <combo_item name="Arts&amp;Culture">
- Artes e Cultura
- </combo_item>
- <combo_item name="Business">
- Negócios
- </combo_item>
- <combo_item name="Educational">
- Educacional
- </combo_item>
- <combo_item name="Gaming">
- Jogo
- </combo_item>
- <combo_item name="Hangout">
- Lazer
- </combo_item>
- <combo_item name="NewcomerFriendly">
- Amigável para novatos
- </combo_item>
- <combo_item name="Parks&amp;Nature">
- Parques e Natureza
- </combo_item>
- <combo_item name="Residential">
- Residencial
- </combo_item>
- <combo_item name="Shopping">
- Compras
- </combo_item>
- <combo_item name="Other">
- Outros
- </combo_item>
+ <combo_box name="land category" left="265" width="155">
+ <combo_box.item name="item0" label="Qualquer Categoria"
+ />
+ <combo_box.item name="item1" label="Locação Linden"
+ />
+ <combo_box.item name="item3" label="Artes e Cultura"
+ />
+ <combo_box.item name="item4" label="Negócios"
+ />
+ <combo_box.item name="item5" label="Educacional"
+ />
+ <combo_box.item name="item6" label="Jogos"
+ />
+ <combo_box.item name="item7" label="Moradia"
+ />
+ <combo_box.item name="item8" label="Amigável a Novos Usuários"
+ />
+ <combo_box.item name="item9" label="Parques e Natureza"
+ />
+ <combo_box.item name="item10" label="Residencial"
+ />
+ <combo_box.item name="item11" label="Compras"
+ />
+ <combo_box.item name="item12" label="Outros"
+ />
</combo_box>
<button label="?" label_selected="?" left="426" name="?"/>
<check_box label="Conteúdo Mature" name="MatureCheck" tool_tip=""/>
- <string name="mature_check_mature">
+ <panel.string name="mature_check_mature">
Conteúdo Mature
- </string>
- <string name="mature_check_adult">
+ </panel.string>
+ <panel.string name="mature_check_adult">
Conteúdo Adult
- </string>
- <string name="mature_check_mature_tooltip">
+ </panel.string>
+ <panel.string name="mature_check_mature_tooltip">
A informação do seu lote ou seu conteúdo são considerados mature.
- </string>
- <string name="mature_check_adult_tooltip">
+ </panel.string>
+ <panel.string name="mature_check_adult_tooltip">
A informação do seu lote ou seu conteúdo são considerados adult.
- </string>
- <text length="1" name="Snapshot:" type="string">
+ </panel.string>
+ <text name="Snapshot:">
Foto:
</text>
<texture_picker label="" name="snapshot_ctrl" tool_tip="Clique para escolher uma imagem"/>
<text name="landing_point">
Ponto de Aterrissagem: [LANDING]
</text>
- <string name="landing_point_none">
+ <panel.string name="landing_point_none">
(nenhum)
- </string>
+ </panel.string>
<button label="Definir" label_selected="Definir" name="Set" tool_tip="Define o ponto de aterrissagem aonde o visitante chega. Define para o ponto em que seu avatar se encontra neste lote."/>
<button label="Limpar" label_selected="Limpar" name="Clear" tool_tip="Limpar o ponto de aterrissagem."/>
- <text length="1" name="Teleport Routing: " type="string">
+ <text name="Teleport Routing: ">
Rota de Tele-transporte:
</text>
- <combo_box left="140" name="landing type" tool_tip="Rota de Teletransporte -- Selecione como tratar os tele-transportes no seu lote." width="140">
- <combo_item length="1" name="Blocked" type="string">
- Bloqueado
- </combo_item>
- <combo_item length="1" name="LandingPoint" type="string">
- Ponto de Aterrissagem
- </combo_item>
- <combo_item length="1" name="Anywhere" type="string">
- Qualquer lugar
- </combo_item>
+ <combo_box width="160" left="140" name="landing type" tool_tip="Rota de Teletransporte -- Selecione como tratar os tele-transportes no seu lote.">
+ <combo_box.item name="Blocked" label="Bloqueado"
+ />
+ <combo_box.item name="LandingPoint" label="Ponto de Aterrissagem"
+ />
+ <combo_box.item name="Anywhere" label="Qualquer lugar"
+ />
</combo_box>
- <string name="push_restrict_text">
+ <panel.string name="push_restrict_text">
Sem Empurrar
- </string>
- <string name="push_restrict_region_text">
+ </panel.string>
+ <panel.string name="push_restrict_region_text">
Sem Empurrar (Imposição na Região)
- </string>
+ </panel.string>
</panel>
<panel label="Mídia" name="land_media_panel">
<text name="with media:" width="85">
@@ -441,7 +413,7 @@ Apenas lotes maiores podem ser listados na busca.
Descrição:
</text>
<line_editor left="97" name="url_description" tool_tip="Texto mostrado ao lado do botão reproduzir/carregar"/>
- <text length="1" name="Media texture:" type="string">
+ <text name="Media texture:">
Substituir
Textura:
</text>
@@ -484,7 +456,7 @@ Mídia:
<check_box left="117" label="Restringir Voz a este lote" name="parcel_enable_voice_channel_parcel"/>
</panel>
<panel label="Acesso" name="land_access_panel">
- <text length="1" name="Limit access to this parcel to:" type="string">
+ <text name="Limit access to this parcel to:">
Acesso a Este Lote
</text>
<check_box label="Permitir Acesso Público" name="public_access"/>
@@ -493,18 +465,16 @@ Mídia:
</text>
<check_box label="Residentes que não forneceram informações de pagamento para a Linden Lab" name="limit_payment" tool_tip="Banir residentes não identificados."/>
<check_box label="Residentes que não tiveram a idade de adulto confirmada" name="limit_age_verified" tool_tip="Banir residentes que não tiveram sua idade verificada. Veja support.secondlife.com para maiores informações."/>
- <string name="estate_override">
+ <panel.string name="estate_override">
Uma ou mais destas opções está definida no nível de propriedade.
- </string>
+ </panel.string>
<check_box label="Permitir Acesso do Grupo: [GROUP]" name="GroupCheck" tool_tip="Definir grupo na aba Geral."/>
<check_box label="Vender passes para:" name="PassCheck" tool_tip="Permite acesso temporário a este terreno"/>
<combo_box name="pass_combo">
- <combo_item name="Anyone">
- Qualquer um
- </combo_item>
- <combo_item name="Group">
- Grupo
- </combo_item>
+ <combo_box.item name="Anyone" label="Qualquer um"
+ />
+ <combo_box.item name="Group" label="Grupo"
+ />
</combo_box>
<spinner label="Preço em L$:" name="PriceSpin"/>
<spinner label="Horas de Acesso:" name="HoursSpin"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_animation_preview.xml b/indra/newview/skins/default/xui/pt/floater_animation_preview.xml
index f258e23bc4..f3297ea5ee 100644
--- a/indra/newview/skins/default/xui/pt/floater_animation_preview.xml
+++ b/indra/newview/skins/default/xui/pt/floater_animation_preview.xml
@@ -6,142 +6,71 @@
<text name="description_label">
Descrição:
</text>
- <spinner label="Prioridade" name="priority" tool_tip="Controla quais animações podem se sobrepor a esta animação."/>
+ <spinner label_width="72" width="110" label="Prioridade" name="priority" tool_tip="Controla quais animações podem se sobrepor a esta animação."/>
<check_box label="Loop" name="loop_check" tool_tip="Executa a animação repetidamente."/>
- <spinner label="Dentro(%)" name="loop_in_point" tool_tip="Ajusta o ponto da animação onde a repetição começa."/>
- <spinner label="Fora(%)" name="loop_out_point" tool_tip="Ajusta o ponto da animação onde a repetição termina."/>
+ <spinner label_width="56" left="65" width="116" label="Dentro(%)" name="loop_in_point" tool_tip="Ajusta o ponto da animação onde a repetição começa."/>
+ <spinner label_width="40" left="185" label="Fora(%)" name="loop_out_point" tool_tip="Ajusta o ponto da animação onde a repetição termina."/>
<text name="hand_label">
Pose de Mão
</text>
- <combo_box label="" name="hand_pose_combo" tool_tip="Controla o que as mãos fazem durante a animação">
- <combo_item name="Spread">
- Espreguiçar
- </combo_item>
- <combo_item name="Relaxed">
- Relaxado
- </combo_item>
- <combo_item name="PointBoth">
- Apontar Ambos
- </combo_item>
- <combo_item name="Fist">
- Punho
- </combo_item>
- <combo_item name="RelaxedLeft">
- Relaxado para Esquerda
- </combo_item>
- <combo_item name="PointLeft">
- Apontar à Esquerda
- </combo_item>
- <combo_item name="FistLeft">
- Punho Esquerdo
- </combo_item>
- <combo_item name="RelaxedRight">
- Relaxado para Direita
- </combo_item>
- <combo_item name="PointRight">
- Apontar à Direita
- </combo_item>
- <combo_item name="FistRight">
- Punho Direito
- </combo_item>
- <combo_item name="SaluteRight">
- Saudar à Direita
- </combo_item>
- <combo_item name="Typing">
- Digitando
- </combo_item>
- <combo_item name="PeaceRight">
- Pacífico à Direita
- </combo_item>
+ <combo_box left_delta="100" width="184" name="hand_pose_combo" tool_tip="Controla o que as mãos fazem durante a animação">
+ <combo_box.item name="Spread" label="Espreguiçar" />
+ <combo_box.item name="Relaxed" label="Relaxado" />
+ <combo_box.item name="PointBoth" label="Apontar Ambos" />
+ <combo_box.item name="Fist" label="Punho" />
+ <combo_box.item name="RelaxedLeft" label="Relaxado para Esquerda" />
+ <combo_box.item name="PointLeft" label="Apontar à Esquerda" />
+ <combo_box.item name="FistLeft" label="Punho Esquerdo" />
+ <combo_box.item name="RelaxedRight" label="Relaxado para Direita" />
+ <combo_box.item name="PointRight" label="Apontar à Direita" />
+ <combo_box.item name="FistRight" label="Punho Direito" />
+ <combo_box.item name="SaluteRight" label="Saudar à Direita" />
+ <combo_box.item name="Typing" label="Digitando" />
+ <combo_box.item name="PeaceRight" label="Pacífico à Direita" />
</combo_box>
<text name="emote_label">
Expressão
</text>
- <combo_box label="" name="emote_combo" tool_tip="Controla o que a face faz durante a animação.">
- <combo_item name="[None]">
- [None]
- </combo_item>
- <combo_item name="Aaaaah">
- Aaaaah
- </combo_item>
- <combo_item name="Afraid">
- Temeroso
- </combo_item>
- <combo_item name="Angry">
- Raivoso
- </combo_item>
- <combo_item name="BigSmile">
- Sorrisão
- </combo_item>
- <combo_item name="Bored">
- Entediado
- </combo_item>
- <combo_item name="Cry">
- Chorar
- </combo_item>
- <combo_item name="Disdain">
- Desprezar
- </combo_item>
- <combo_item name="Embarrassed">
- Envergonhado
- </combo_item>
- <combo_item name="Frown">
- Franzir a testa
- </combo_item>
- <combo_item name="Kiss">
- Beijar
- </combo_item>
- <combo_item name="Laugh">
- Rir
- </combo_item>
- <combo_item name="Plllppt">
- Plllppt
- </combo_item>
- <combo_item name="Repulsed">
- Enojado
- </combo_item>
- <combo_item name="Sad">
- Triste
- </combo_item>
- <combo_item name="Shrug">
- Indiferença
- </combo_item>
- <combo_item name="Smile">
- Sorriso
- </combo_item>
- <combo_item name="Surprise">
- Surpreso
- </combo_item>
- <combo_item name="Wink">
- Piscar
- </combo_item>
- <combo_item name="Worry">
- Preocupado
- </combo_item>
+ <combo_box left_delta="100" width="184" name="emote_combo" tool_tip="Controla o que a face faz durante a animação.">
+ <combo_box.item name="[None]" label="None]" />
+ <combo_box.item name="Aaaaah" label="Aaaaah" />
+ <combo_box.item name="Afraid" label="Temeroso" />
+ <combo_box.item name="Angry" label="Raivoso" />
+ <combo_box.item name="BigSmile" label="Sorrisão" />
+ <combo_box.item name="Bored" label="Entediado" />
+ <combo_box.item name="Cry" label="Chorar" />
+ <combo_box.item name="Disdain" label="Desprezar" />
+ <combo_box.item name="Embarrassed" label="Envergonhado" />
+ <combo_box.item name="Frown" label="Franzir a testa" />
+ <combo_box.item name="Kiss" label="Beijar" />
+ <combo_box.item name="Laugh" label="Rir" />
+ <combo_box.item name="Plllppt" label="Plllppt" />
+ <combo_box.item name="Repulsed" label="Enojado" />
+ <combo_box.item name="Sad" label="Triste" />
+ <combo_box.item name="Shrug" label="Indiferença" />
+ <combo_box.item name="Smile" label="Sorriso" />
+ <combo_box.item name="Surprise" label="Surpreso" />
+ <combo_box.item name="Wink" label="Piscar" />
+ <combo_box.item name="Worry" label="Preocupado" />
</combo_box>
- <text name="preview_label">
+ <text name="preview_label" width="250">
Prever enquanto
</text>
- <combo_box label="" name="preview_base_anim" tool_tip="Use isto para testar o comportamento de sua animação enquanto seu avatar executa ações comuns.">
- <combo_item name="Standing">
- Parado
- </combo_item>
- <combo_item name="Walking">
- Andando
- </combo_item>
- <combo_item name="Sitting">
- Sentando
- </combo_item>
- <combo_item name="Flying">
- Voando
- </combo_item>
+ <combo_box left_delta="100" width="130" name="preview_base_anim" tool_tip="Use isto para testar o comportamento de sua animação enquanto seu avatar executa ações comuns.">
+ <combo_box.item name="Standing" label="Parado" />
+ <combo_box.item name="Walking" label="Andando" />
+ <combo_box.item name="Sitting" label="Sentando" />
+ <combo_box.item name="Flying" label="Voando" />
</combo_box>
- <spinner label="Facilitar a entrada (sec)" name="ease_in_time" tool_tip="Quantidade de tempo (em segundos) para que as animações se mesclem."/>
- <spinner label="Facilitar a saída (sec)" name="ease_out_time" tool_tip="Quantidade de tempo (em segundos) para que a animações se mesclem."/>
- <button label="" name="play_btn" tool_tip="Executa/pausa sua animação."/>
+ <spinner label_width="125" width="192" label="Facilitar a entrada (sec)" name="ease_in_time" tool_tip="Quantidade de tempo (em segundos) para que as animações se mesclem."/>
+ <spinner bottom_delta="-20" label_width="125" left="10" width="192" label="Facilitar a saída (sec)" name="ease_out_time" tool_tip="Quantidade de tempo (em segundos) para que a animações se mesclem."/>
+ <button bottom_delta="-32" name="play_btn" tool_tip="Executa/pausa sua animação."/>
<button label="" name="stop_btn" tool_tip="Interrompe a execução da animação."/>
<text name="bad_animation_text">
- Incapaz de ler o arquivo de animação. Nós recomendamos exportar arquivos BVH do Poser 4.
+ Incapaz de ler o arquivo de animação.
+
+Nós recomendamos exportar arquivos BVH do
+Poser 4.
</text>
<button label="Cancelar" name="cancel_btn"/>
<button label="Carregar (L$[AMOUNT])" name="ok_btn"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_auction.xml b/indra/newview/skins/default/xui/pt/floater_auction.xml
index 48e0b92400..34cd17d781 100644
--- a/indra/newview/skins/default/xui/pt/floater_auction.xml
+++ b/indra/newview/skins/default/xui/pt/floater_auction.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_auction" title="Iniciar a venda de terrenos da Linden">
+<floater name="floater_auction" title="INICIAR A VENDA DE TERRENOS DA LINDEN">
<check_box label="Incluir marcador de seleção amarelo" name="fence_check"/>
<button label="Foto" label_selected="Foto" name="snapshot_btn"/>
<button label="OK" label_selected="OK" name="ok_btn"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_avatar_picker.xml b/indra/newview/skins/default/xui/pt/floater_avatar_picker.xml
index 8f433a635d..186ef30e1b 100644
--- a/indra/newview/skins/default/xui/pt/floater_avatar_picker.xml
+++ b/indra/newview/skins/default/xui/pt/floater_avatar_picker.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="avatarpicker" title="Escolha o Residente">
- <tab_container name="ResidentChooserTabs">
+<floater name="avatarpicker" title="ESCOLHA O RESIDENTE" min_width="285" width="285">
+ <tab_container name="ResidentChooserTabs" width="275">
<panel label="Buscar" name="SearchPanel">
<text name="InstructSearchResidentName">
Digite parte do nome do Residente:
@@ -14,13 +14,15 @@
</panel>
<panel label="Próximo a Mim" name="NearMePanel">
<text name="InstructSelectResident">
- Selecione residente próximo:
+ Selecione residente
+próximo:
</text>
- <button label="Atualizar Lista" label_selected="Atualizar Lista" name="Refresh"/>
- <slider label="Faixa" name="near_me_range"/>
+ <button font="SansSerifSmall" left_delta="1" width="115" label="Atualizar Lista" label_selected="Atualizar Lista" name="Refresh"/>
+ <slider label="Faixa" name="near_me_range" bottom_delta="-36"/>
<text name="meters">
Metros
</text>
+ <scroll_list bottom_delta="-169" height="159" name="NearMe" />
</panel>
</tab_container>
<button label="Selecionar" label_selected="Selecionar" name="Select"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_avatar_textures.xml b/indra/newview/skins/default/xui/pt/floater_avatar_textures.xml
index db0023d748..04a78efb12 100644
--- a/indra/newview/skins/default/xui/pt/floater_avatar_textures.xml
+++ b/indra/newview/skins/default/xui/pt/floater_avatar_textures.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="avatar_texture_debug" title="Texturas do Avatar">
+<floater name="avatar_texture_debug" title="TEXTURAS DO AVATAR">
<text name="baked_label">
Texturas sobrepostas
</text>
diff --git a/indra/newview/skins/default/xui/pt/floater_beacons.xml b/indra/newview/skins/default/xui/pt/floater_beacons.xml
index edd1e08094..82f055745f 100644
--- a/indra/newview/skins/default/xui/pt/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/pt/floater_beacons.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="beacons" title="Balizas">
+<floater name="beacons" title="BALIZAS">
<panel name="beacons_panel">
<check_box label="Objetos programados com toque apenas" name="touch_only"/>
<check_box label="Objetos programados" name="scripted"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_build_options.xml b/indra/newview/skins/default/xui/pt/floater_build_options.xml
index 4dfebc3abd..bce78fad21 100644
--- a/indra/newview/skins/default/xui/pt/floater_build_options.xml
+++ b/indra/newview/skins/default/xui/pt/floater_build_options.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="build options floater" title="Opções de grade">
- <spinner label="Uni. Grade (metros)" name="GridResolution"/>
- <spinner label="Ext. da Grade (metros)" name="GridDrawSize"/>
+<floater name="build options floater" title="OPÇÕES DE GRADE">
+ <spinner label="Uni. Grade (metros)" name="GridResolution" width="180" label_width="122"/>
+ <spinner label="Ext. da Grade (metros)" name="GridDrawSize" width="180" label_width="122"/>
<check_box label="Habilitar ajuste de sub-grade" name="GridSubUnit"/>
<check_box label="Mostrar as seções de cruzamento" name="GridCrossSection"/>
- <slider label="Opacidade da grade" name="GridOpacity"/>
+ <slider label="Opacidade da grade" name="GridOpacity" width="220"/>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_bulk_perms.xml b/indra/newview/skins/default/xui/pt/floater_bulk_perms.xml
index c064d24f96..7443e19721 100644
--- a/indra/newview/skins/default/xui/pt/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/pt/floater_bulk_perms.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterbulkperms" title="Mudança conjunta das permissões de conteúdo">
+<floater name="floaterbulkperms" title="MUDANÇA CONJUNTA DAS PERMISSÕES DE CONTEÚDO">
<text name="applyto">
Tipos de Conteúdo
</text>
diff --git a/indra/newview/skins/default/xui/pt/floater_bumps.xml b/indra/newview/skins/default/xui/pt/floater_bumps.xml
index 0bc2546275..1833cd4335 100644
--- a/indra/newview/skins/default/xui/pt/floater_bumps.xml
+++ b/indra/newview/skins/default/xui/pt/floater_bumps.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_bumps" title="Colisões, impulsos e batidas">
+<floater name="floater_bumps" title="COLISÕES, IMPULSOS E BATIDAS">
<text name="none_detected">
Nada detectado
</text>
diff --git a/indra/newview/skins/default/xui/pt/floater_buy_contents.xml b/indra/newview/skins/default/xui/pt/floater_buy_contents.xml
index 0c1fb77a08..322a07575a 100644
--- a/indra/newview/skins/default/xui/pt/floater_buy_contents.xml
+++ b/indra/newview/skins/default/xui/pt/floater_buy_contents.xml
@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_buy_contents" title="Comprar conteúdo">
+<floater name="floater_buy_contents" title="COMPRAR CONTEÚDO">
<text name="contains_text">
[NAME] contém:
</text>
<text name="buy_text">
Comprar por L$[AMOUNT] de(a) [NAME]?
</text>
- <button label="Cancelar" label_selected="Cancelar" name="cancel_btn"/>
- <button label="Comprar" label_selected="Comprar" name="buy_btn"/>
- <check_box label="Vestir roupa agora" name="wear_check"/>
+ <button label="Cancelar" label_selected="Cancelar" name="cancel_btn" width="73"/>
+ <button label="Comprar" label_selected="Comprar" name="buy_btn" width="73" left_delta="-77"/>
+ <check_box label="Vestir roupa agora" name="wear_check" left_delta="-130"/>
<string name="no_copy_text">
(sem copiar)
</string>
diff --git a/indra/newview/skins/default/xui/pt/floater_buy_currency.xml b/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
index 42ba205475..f17c069ecf 100644
--- a/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="buy currency" title="Comprar Dinheiro">
+<floater name="buy currency" title="COMPRAR DINHEIRO">
<text name="info_buying">
Comprando Dinheiro:
</text>
@@ -29,7 +29,7 @@
1234
</line_editor>
<text name="currency_est" left_delta="72">
- por aproxim. US$ [USD]
+ por aproxim. [LOCALAMOUNT]
</text>
<text name="getting_data">
Obtendo dados...
@@ -52,6 +52,9 @@
<text name="total_amount">
L$ [AMT]
</text>
+ <text name="currency_links">
+ [http://www.secondlife.com/my/account/payment_method_management.php?lang=pt-BR payment method] | [http://www.secondlife.com/my/account/currency.php?lang=pt-BR currency] | [http://www.secondlife.com/my/account/exchange_rates.php?lang=pt-BR exchange rate]
+ </text>
<text name="purchase_warning_repurchase">
Confirmando esta compra só compra a moeda.
Você precisará tentar novamente a operação.
@@ -63,6 +66,6 @@ Aumente a quantidade de compra.
<button label="Fechar" name="cancel_btn"/>
<button label="Adquirir" name="buy_btn"/>
<string name="buy_currency">
- Comprar L$ [LINDENS] por aproximadamente US$ [USD]
+ Comprar L$ [LINDENS] por aproxim. [LOCALAMOUNT]
</string>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_buy_land.xml b/indra/newview/skins/default/xui/pt/floater_buy_land.xml
index 25716d0257..6e502ad6e5 100644
--- a/indra/newview/skins/default/xui/pt/floater_buy_land.xml
+++ b/indra/newview/skins/default/xui/pt/floater_buy_land.xml
@@ -1,27 +1,27 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="buy land" title="Comprar terra">
+<floater name="buy land" title="COMPRAR TERRA">
<text name="region_name_label">
Região:
</text>
- <text name="region_name_text">
+ <text name="region_name_text" left="560">
(desconhecido)
</text>
<text name="region_type_label">
Tipo:
</text>
- <text name="region_type_text">
+ <text name="region_type_text" left="560">
(desconhecido)
</text>
<text name="estate_name_label">
Propriedade:
</text>
- <text name="estate_name_text">
+ <text name="estate_name_text" left="560">
(desconhecido)
</text>
- <text name="estate_owner_label">
+ <text name="estate_owner_label" width="105" right="565">
Dono da propriedade:
</text>
- <text name="estate_owner_text">
+ <text name="estate_owner_text" left="560" >
(desconhecido)
</text>
<text name="resellable_changeable_label">
@@ -36,10 +36,11 @@
<text name="covenant_text">
Você deve concordar com o Corretor da Propriedade:
</text>
+ <text left="470" name="covenant_timestamp_text"/>
<text_editor name="covenant_editor">
Carregando...
</text_editor>
- <check_box label="Eu concordo com as definições do Corretor feitas acima." name="agree_covenant"/>
+ <check_box label="Eu concordo com as definições do &#10;Corretor feitas acima." name="agree_covenant"/>
<text name="info_parcel_label">
Lote:
</text>
@@ -66,7 +67,7 @@ vendido com os objetos
<text name="error_message">
Algo ainda não está correto.
</text>
- <button label="Ir para a página da web" name="error_web"/>
+ <button label="Ir para a página da web" name="error_web" width="150" />
<text name="account_action">
Evoluir sua conta para membro Premium
</text>
@@ -74,15 +75,9 @@ vendido com os objetos
Somente membros Premium podem possuir terra.
</text>
<combo_box name="account_level">
- <combo_item name="US$9.95/month,billedmonthly">
- US$9.95/mês, debitado mensalmente
- </combo_item>
- <combo_item name="US$7.50/month,billedquarterly">
- US$7.50/mês, debitado trimestralmente
- </combo_item>
- <combo_item name="US$6.00/month,billedannually">
- US$6.00/mês, debitado anualmente
- </combo_item>
+ <combo_box.item name="US$9.95/month,billedmonthly" label="US$9.95/mês, debitado mensalmente" />
+ <combo_box.item name="US$7.50/month,billedquarterly" label="US$7.50/mês, debitado trimestralmente" />
+ <combo_box.item name="US$6.00/month,billedannually" label="US$6.00/mês, debitado anualmente" />
</combo_box>
<text name="land_use_action">
Aumente sua taxa de locação de terra para US$ 40/mês.
@@ -97,10 +92,10 @@ Este lote tem 512 m² de terra.
<text name="currency_reason">
Você tem L$2,100.
</text>
- <text name="currency_action">
+ <text name="currency_action" width="116">
Compre L$ adicionais
</text>
- <line_editor name="currency_amt">
+ <line_editor name="currency_amt" left="190" width="65">
1000
</line_editor>
<text name="currency_est">
diff --git a/indra/newview/skins/default/xui/pt/floater_buy_object.xml b/indra/newview/skins/default/xui/pt/floater_buy_object.xml
index b8e1085471..e9968ed8f8 100644
--- a/indra/newview/skins/default/xui/pt/floater_buy_object.xml
+++ b/indra/newview/skins/default/xui/pt/floater_buy_object.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="contents" title="Comprar cópia do objeto">
+<floater name="contents" title="COMPRAR CÓPIA DO OBJETO">
<text name="contents_text">
e seus conteúdos:
</text>
diff --git a/indra/newview/skins/default/xui/pt/floater_camera.xml b/indra/newview/skins/default/xui/pt/floater_camera.xml
index 4dc6997606..b61e261148 100644
--- a/indra/newview/skins/default/xui/pt/floater_camera.xml
+++ b/indra/newview/skins/default/xui/pt/floater_camera.xml
@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move floater" title="">
- <string name="rotate_tooltip">
+<floater name="camera_floater" title="">
+ <floater.string name="rotate_tooltip">
Girar a Câmera ao redor do Foco
- </string>
- <string name="zoom_tooltip">
+ </floater.string>
+ <floater.string name="zoom_tooltip">
Aproximar a Câmera in direção ao Foco
- </string>
- <string name="move_tooltip">
- Mover a Câmera Para Cima e Para Baixo, Para a Esquerda e Para a Direita
- </string>
+ </floater.string>
+ <floater.string name="move_tooltip">
+ Mover a Câmera para Cima e para Baixo, para a Esquerda e para a Direita
+ </floater.string>
+ <panel name="controls">
+ <joystick_track name="cam_track_stick" tool_tip="Mover a Câmera para Cima e para Baixo, para a Esquerda e para a Direita"/>
+ <joystick_zoom name="zoom" tool_tip="Aproximar a Câmera in direção ao Foco"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_choose_group.xml b/indra/newview/skins/default/xui/pt/floater_choose_group.xml
index 449d578716..ae395734e9 100644
--- a/indra/newview/skins/default/xui/pt/floater_choose_group.xml
+++ b/indra/newview/skins/default/xui/pt/floater_choose_group.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="groups" title="Grupos">
+<floater name="groups" title="GRUPOS">
<text name="groupdesc">
Escolha um grupo:
</text>
diff --git a/indra/newview/skins/default/xui/pt/floater_color_picker.xml b/indra/newview/skins/default/xui/pt/floater_color_picker.xml
index 475280b013..6a4263f4ff 100644
--- a/indra/newview/skins/default/xui/pt/floater_color_picker.xml
+++ b/indra/newview/skins/default/xui/pt/floater_color_picker.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="ColorPicker" title="Seletor de Cor">
+<floater name="ColorPicker" title="SELETOR DE COR">
<text name="r_val_text">
Vermelho:
</text>
@@ -19,12 +19,14 @@
Lum:
</text>
<check_box label="Aplicar imediatamente" name="apply_immediate"/>
- <button label="Cancelar" label_selected="Cancelar" name="cancel_btn"/>
+ <button left_delta="150" name="color_pipette" />
+ <button left_delta="55" label="Cancelar" label_selected="Cancelar" name="cancel_btn"/>
<button label="Selecionar" label_selected="Selecionar" name="select_btn"/>
<text name="Current color:">
Cor atual:
</text>
<text name="(Drag below to save.)">
- (Arraste abaixo para salvar.)
+ (Arraste abaixo
+ para salvar)
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_customize.xml b/indra/newview/skins/default/xui/pt/floater_customize.xml
index 31f3f3d59c..55946933e7 100644
--- a/indra/newview/skins/default/xui/pt/floater_customize.xml
+++ b/indra/newview/skins/default/xui/pt/floater_customize.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater customize" title="Aparência" width="546">
+<floater name="floater customize" title="APARÊNCIA" width="546">
<tab_container name="customize tab container" tab_min_width="115" width="544">
- <panel label="Partes de corpo" name="body_parts_placeholder"/>
+ <placeholder label="Partes de corpo" name="body_parts_placeholder"/>
<panel label="Forma" name="Shape">
<button label="Reverter" label_selected="Reverter" name="Revert"/>
<button label="Corpo" label_selected="Corpo" name="Body"/>
@@ -14,33 +14,29 @@
<button label="Tórax" label_selected="Tórax" name="Torso"/>
<button label="Pernas" label_selected="Pernas" name="Legs"/>
<radio_group name="sex radio">
- <radio_item length="1" name="radio" type="string">
- Feminino
- </radio_item>
- <radio_item length="1" name="radio2" type="string">
- Masculino
- </radio_item>
+ <radio_item name="radio" label="Feminino" />
+ <radio_item name="radio2" label="Masculino" />
</radio_group>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: não foi possível modificar
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: carregando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: não vestido
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Localizado em [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Coloque uma nova forma arrastando uma do seu inventário para seu avatar.
Alternativamente, você pode criar uma nova de um esboço e usá-la.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Você não tem permissão para modificar esta vestimenta.
</text>
<text name="Item Action Label">
@@ -55,27 +51,27 @@ Alternativamente, você pode criar uma nova de um esboço e usá-la.
<button width="115" label="Detalhes Faciais" label_selected="Detalhes Faciais" name="Face Detail"/>
<button width="115" label="Maquiagem" label_selected="Maquiagem" name="Makeup"/>
<button width="115" label="Detalhes do Corpo" label_selected="Detalhes do Corpo" name="Body Detail"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: não foi possível modificar
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: carregando..
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: não vestido
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Localizada em [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Coloque uma nova pele arrastando uma de seu inventário para seu avatar.
Alternativamente, você pode criar uma nova forma a partir de um esboço
e usá-la.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Você não tem permissão para modificar esta vestimenta.
</text>
<text name="Item Action Label">
@@ -94,27 +90,27 @@ e usá-la.
<button width="115" label="Estilo" label_selected="Estilo" name="Style"/>
<button width="115" label="Sombrancelhas" label_selected="Sombrancelhas" name="Eyebrows"/>
<button width="115" label="Rosto" label_selected="Rosto" name="Facial"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: não foi possível modificar
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: carregando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: não vestido
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Localizado em [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Ponha um novo cabelo em seu avatar arrastando um do seu inventário.
Alternativamente, você pode criar um novo modelo a partir de um esboço
e usá-lo.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Você não ter permissão para modificar essa vestimenta.
</text>
<text name="Item Action Label">
@@ -127,26 +123,26 @@ e usá-lo.
<button label="Reverter" label_selected="Reverter" name="Revert"/>
</panel>
<panel label="Olhos" name="Eyes">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: não foi possível modificar
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: carregando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: não vestido
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Localizado em [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Para colocar novos olhos, arraste um do seu inventário para seu avatar.
Alternativamente, você pode criar um novo modelo de um esboço e usá-lo.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Você não tem permissão para alterar esta vestimenta.
</text>
<text name="Item Action Label">
@@ -167,27 +163,27 @@ Alternativamente, você pode criar um novo modelo de um esboço e usá-lo.
<button label="Salvar" label_selected="Salvar" name="Save"/>
<button label="Salvar como..." label_selected="Salvar como..." name="Save As"/>
<button label="Reverter" label_selected="Reverter" name="Revert"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: não foi possível modificar
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: carregando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: não vestido
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Localizado em [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Para por uma nova camisa em seu avatar, arraste uma do seu inventário para
seu avatar. Alternativamente, você pode criar um novo modelo a partir de
um esboço e usá-lo.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Você não ter permissão para modificar esta vestimenta.
</text>
<text name="Item Action Label">
@@ -202,27 +198,27 @@ um esboço e usá-lo.
<button label="Salvar" label_selected="Salvar" name="Save"/>
<button label="Salvar como..." label_selected="Salvar como..." name="Save As"/>
<button label="Reverter" label_selected="Reverter" name="Revert"/>
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: não foi possível modificar
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: carregando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: não vestindo
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Localizado em [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Para por uma nova calça em seu avatar, basta arrastar uma outra do seu
inventário. Alternativamente, você pode criar um novo modelo a partir
de um esboço e usá-lo.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Você não tem permissão para modificar esta vestimenta.
</text>
<text name="Item Action Label">
@@ -230,27 +226,27 @@ de um esboço e usá-lo.
</text>
</panel>
<panel label="Sapatos" name="Shoes">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: não foi possível modificar
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: carregando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: não vestido
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Localizado em [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Para por novos sapatos em seu avatar, basta arrastar um novo do seu
inventário. Alternativamente, você pode criar um novo modelo a partir
de um esboço e usá-lo.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Você não tem permissão para modificar esta vestimenta.
</text>
<text name="Item Action Label">
@@ -265,27 +261,27 @@ de um esboço e usá-lo.
<button label="Reverter" label_selected="Reverter" name="Revert"/>
</panel>
<panel label="Meias" name="Socks">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: não foi possível modificar
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: carregando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: não vestido.
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Localizado em [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Para por novas meias em seu avatar, basta arrastar uma nova do seu
inventário. Alternativamente, você pode criar novas meias a partir de
um esboço e usá-las.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Você não tem permissão para modificar essa vestimenta.
</text>
<text name="Item Action Label">
@@ -300,27 +296,27 @@ um esboço e usá-las.
<button label="Reverter" label_selected="Reverter" name="Revert"/>
</panel>
<panel label="Jaqueta" name="Jacket">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: Não foi possível modificar
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: carregando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: não vestido
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Localizado em [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Para por uma nova jaqueta em seu avatar, basta arrastar um novo modelo
do seu inventário. Alternativamente, você pode criar um novo modelo a
partir de um esboço e usá-lo.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Você não tem permissão para modificar esta vestimenta.
</text>
<text name="Item Action Label">
@@ -336,27 +332,27 @@ partir de um esboço e usá-lo.
<button label="Reverter" label_selected="Reverter" name="Revert"/>
</panel>
<panel label="Luvas" name="Gloves">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: não foi possível modificar
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: carregando....
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: não vestido
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Localizado em [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Para colocar uma nova jaqueta em seu avatar, basta arrastar um novo modelo
do seu inventário. Alternativamente, você pode criar uma novo modelo a
partir de um esboço e usá-lo.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Você não tem permissão para modificar essa vestimenta.
</text>
<text name="Item Action Label">
@@ -371,27 +367,27 @@ partir de um esboço e usá-lo.
<button label="Reverter" label_selected="Reverter" name="Revert"/>
</panel>
<panel label="Camiseta" name="Undershirt">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: não foi possível modificar
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: carregando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: não vestido
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Localizado em [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Para por uma nova Camiseta em seu avatar, basta arrastar um novo modelo
de seu inventário. Alternativamente, você pode criar um novo modelo a
partir de um esboço e usá-lo.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Você não ter permissão para modificar essa vestimenta.
</text>
<text name="Item Action Label">
@@ -406,27 +402,27 @@ partir de um esboço e usá-lo.
<button label="Reverter" label_selected="Reverter" name="Revert"/>
</panel>
<panel label="Roupas de Baixo" name="Underpants">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: não foi possível modificar
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: carregando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: não vestido
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Localizado em [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Para por novas roupas de baixo em seu avatar, basta arrastar um novo
modelo do seu inventário. Alternativamente, você pode criar um novo
modelo a partir de um esboço e usá-lo.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Você não tem permissão para modificar essa vestimenta.
</text>
<text name="Item Action Label">
@@ -441,27 +437,27 @@ modelo a partir de um esboço e usá-lo.
<button label="Reverter" label_selected="Reverter" name="Revert"/>
</panel>
<panel label="Saia" name="Skirt">
- <text length="1" name="title" type="string">
+ <text name="title">
[DESC]
</text>
- <text length="1" name="title_no_modify" type="string">
+ <text name="title_no_modify">
[DESC]: não foi possível modificar
</text>
- <text length="1" name="title_loading" type="string">
+ <text name="title_loading">
[DESC]: carregando...
</text>
- <text length="1" name="title_not_worn" type="string">
+ <text name="title_not_worn">
[DESC]: não vestido
</text>
- <text length="1" name="path" type="string">
+ <text name="path">
Localizado em [PATH]
</text>
- <text length="1" name="not worn instructions" type="string">
+ <text name="not worn instructions">
Para por uma nova saia em seu avatar, basta arrastar um novo modelo
do seu inventário. Alternativamente, você pode criar um novo modelo a
partir de um esboço e usá-lo.
</text>
- <text length="1" name="no modify instructions" type="string">
+ <text name="no modify instructions">
Você não tem permissão para modificar esta vestimenta.
</text>
<text name="Item Action Label">
diff --git a/indra/newview/skins/default/xui/pt/floater_day_cycle_options.xml b/indra/newview/skins/default/xui/pt/floater_day_cycle_options.xml
index 5049b87a56..42f34a3d82 100644
--- a/indra/newview/skins/default/xui/pt/floater_day_cycle_options.xml
+++ b/indra/newview/skins/default/xui/pt/floater_day_cycle_options.xml
@@ -1,38 +1,38 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Day Cycle Floater" title="Editor de ciclo de dia">
+<floater name="Day Cycle Floater" title="EDITOR DE CICLO DE DIA">
<tab_container name="Day Cycle Tabs">
<panel label="Ciclo do dia" name="Day Cycle">
<button label="?" name="WLDayCycleHelp"/>
<text name="WL12am">
- 12:00 meia-noite
+ 0:00
</text>
<text name="WL3am">
- 3:00 da manhã
+ 3:00
</text>
<text name="WL6am">
- 6:00 da manhã
+ 6:00
</text>
<text name="WL9amHash">
- 9:00 da manhã
+ 9:00
</text>
<text name="WL12pmHash">
- 12:00 meio dia
+ 12:00
</text>
<text name="WL3pm">
- 3:00 da tarde
+ 15:00
</text>
<text name="WL6pm">
- 6:00 da tarde
+ 18:00
</text>
<text name="WL9pm">
- 9:00 da noite
+ 21:00
</text>
<text name="WL12am2">
- 12:00 meia noite
+ 24:00
</text>
- <button label="Add Key" label_selected="Adicionar chave" name="WLAddKey"/>
- <button label="Apagar chave" label_selected="Apagar chave" name="WLDeleteKey"/>
- <text name="WLCurKeyFrameText">
+ <button font="SansSerifSmall" width="96" left="546" label="Adicionar chave" label_selected="Adicionar chave" name="WLAddKey"/>
+ <button font="SansSerifSmall" width="96" left="546" label="Apagar chave" label_selected="Apagar chave" name="WLDeleteKey"/>
+ <text name="WLCurKeyFrameText" width="190" left="17">
Configurações de Quadro-chave:
</text>
<text name="WLCurKeyTimeText">
@@ -47,7 +47,7 @@
<text name="DayCycleText">
Grudar:
</text>
- <combo_box label="5 minutos" name="WLSnapOptions"/>
+ <combo_box label="5 minutos" name="WLSnapOptions" width="85"/>
<text name="DayCycleText2">
Duração do Ciclo:
</text>
@@ -59,7 +59,7 @@
</text>
<button label="Tocar" label_selected="Tocar" name="WLAnimSky"/>
<button label="Pare!" label_selected="Pare" name="WLStopAnimSky"/>
- <button label="Usar o horário da Propriedade" label_selected="Ir para o horário da Propriedade" name="WLUseLindenTime"/>
+ <button width="175" font="SansSerifSmall" label="Usar o horário da Propriedade" label_selected="Ir para o horário da Propriedade" name="WLUseLindenTime"/>
<button label="Salvar o Dia teste" label_selected="Salvar o Dia teste" name="WLSaveDayCycle"/>
<button label="Carregar o Dia teste" label_selected="Carregar o Dia teste" name="WLLoadDayCycle"/>
</panel>
diff --git a/indra/newview/skins/default/xui/pt/floater_device_settings.xml b/indra/newview/skins/default/xui/pt/floater_device_settings.xml
index 9ce773116c..fa4da834b8 100644
--- a/indra/newview/skins/default/xui/pt/floater_device_settings.xml
+++ b/indra/newview/skins/default/xui/pt/floater_device_settings.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_device_settings" title="Ajustes do Dispositivo de Conversa por Voz"/>
+<floater name="floater_device_settings" title="AJUSTES DO DISPOSITIVO DE CONVERSA POR VOZ"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_env_settings.xml b/indra/newview/skins/default/xui/pt/floater_env_settings.xml
index b1c85a32b7..4a43801b48 100644
--- a/indra/newview/skins/default/xui/pt/floater_env_settings.xml
+++ b/indra/newview/skins/default/xui/pt/floater_env_settings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Environment Editor Floater" title="Editor do Ambiente">
+<floater name="Environment Editor Floater" title="EDITOR DO AMBIENTE">
<text name="EnvTimeText">
Hora do Dia
</text>
@@ -7,17 +7,19 @@
12:00 PM
</text>
<text name="EnvCloudText">
- Cobertura de Nuvens
+ Cobertura de
+Nuvens
</text>
<text name="EnvWaterColorText">
Cor da água
</text>
<color_swatch label="" name="EnvWaterColor" tool_tip="Clique para abrir o Editor de cores"/>
<text name="EnvWaterFogText">
- Névoa da água
+ Névoa da
+água
</text>
- <button label="Usar hora da propriedade" name="EnvUseEstateTimeButton"/>
- <button label="Céu Avançado" name="EnvAdvancedSkyButton"/>
- <button label="Ãgua Avançada" name="EnvAdvancedWaterButton"/>
+ <button bottom="-144" label="Usar hora da propriedade" name="EnvUseEstateTimeButton" width="155"/>
+ <button label="Céu Avançado" name="EnvAdvancedSkyButton" width="155" left="167"/>
+ <button label="Ãgua Avançada" name="EnvAdvancedWaterButton" width="155" left="326"/>
<button label="?" name="EnvSettingsHelpButton"/>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_font_test.xml b/indra/newview/skins/default/xui/pt/floater_font_test.xml
index eb52d3341d..c506cdb12d 100644
--- a/indra/newview/skins/default/xui/pt/floater_font_test.xml
+++ b/indra/newview/skins/default/xui/pt/floater_font_test.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="contents" title="Teste de Fonte">
+<floater name="contents" title="TESTE DE FONTE">
<text name="linea">
OverrideTest, deveria aparecer aqui como Times. (De default/xui/en-us)
</text>
diff --git a/indra/newview/skins/default/xui/pt/floater_gesture.xml b/indra/newview/skins/default/xui/pt/floater_gesture.xml
index ac50f32dd1..b0bc42685d 100644
--- a/indra/newview/skins/default/xui/pt/floater_gesture.xml
+++ b/indra/newview/skins/default/xui/pt/floater_gesture.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="gestures" title="Gestos Ativos">
+<floater name="gestures" title="GESTOS ATIVOS">
<text name="help_label">
Clicar duas vezes no gesto para executar animações e sons.
</text>
diff --git a/indra/newview/skins/default/xui/pt/floater_god_tools.xml b/indra/newview/skins/default/xui/pt/floater_god_tools.xml
index 86c6b087f8..4b7b2eb34e 100644
--- a/indra/newview/skins/default/xui/pt/floater_god_tools.xml
+++ b/indra/newview/skins/default/xui/pt/floater_god_tools.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="godtools floater" title="Ferramentas de Deus">
+<floater name="godtools floater" title="FERRAMENTAS DE DEUS">
<tab_container name="GodTools Tabs">
<panel label="Grade" name="grid">
<button label="Desconectar todos os usuários" label_selected="Desconectar todos os usuários" name="Kick all users"/>
@@ -39,7 +39,7 @@
Fator cobrança:
</text>
<text name="land cost text">
- L$ por metros quadrados
+ L$ por m²:
</text>
<button label="Atualizar" label_selected="Atualizar" name="Refresh" tool_tip="Clique aqui para atualizar a informação acima."/>
<button label="Aplicar" label_selected="Aplicar" name="Apply" tool_tip="Clique aqui para aplicar qualquer mudança acima"/>
@@ -73,29 +73,17 @@
Destino:
</text>
<combo_box name="destination">
- <combo_item name="Selection">
- Seleção
- </combo_item>
- <combo_item name="AgentRegion">
- Região do Agente
- </combo_item>
+ <combo_box.item name="item1" label="Seleção" />
+ <combo_box.item name="item2" label="Região do Agente" />
</combo_box>
<text name="Request:">
Requisição:
</text>
<combo_box name="request">
- <combo_item name="colliders&lt;steps&gt;">
- Passos de Colisão
- </combo_item>
- <combo_item name="scripts&lt;count&gt;,&lt;optionalpattern&gt;">
- Contagem de scripts, padrão opcional
- </combo_item>
- <combo_item name="objects&lt;pattern&gt;">
- Padrão de Objetos
- </combo_item>
- <combo_item name="rez&lt;asset_id&gt;">
- rez &lt;asset_id&gt;
- </combo_item>
+ <combo_box.item name="item1" label="Passos de Colisão" />
+ <combo_box.item name="item2" label="Contagem de scripts, padrão opcional" />
+ <combo_box.item name="item3" label="Padrão de Objetos" />
+ <combo_box.item name="item4" label="rez &lt;asset_id&gt;" />
</combo_box>
<text name="Parameter:">
Parametro:
diff --git a/indra/newview/skins/default/xui/pt/floater_hardware_settings.xml b/indra/newview/skins/default/xui/pt/floater_hardware_settings.xml
index 10ed0339a3..8921e6ea12 100644
--- a/indra/newview/skins/default/xui/pt/floater_hardware_settings.xml
+++ b/indra/newview/skins/default/xui/pt/floater_hardware_settings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Hardware Settings Floater" title="Ajustes de Hardware">
+<floater name="Hardware Settings Floater" title="AJUSTES DE HARDWARE">
<text name="Filtering:">
Filtragem:
</text>
@@ -8,21 +8,11 @@
Suavização:
</text>
<combo_box label="Suavização" name="fsaa" width="94">
- <combo_item name="FSAADisabled">
- Desabilitado
- </combo_item>
- <combo_item name="2x">
- 2x
- </combo_item>
- <combo_item name="4x">
- 4x
- </combo_item>
- <combo_item name="8x">
- 8x
- </combo_item>
- <combo_item name="16x">
- 16x
- </combo_item>
+ <combo_box.item name="FSAADisabled" label="Desabilitado"/>
+ <combo_box.item name="2x" label="2x"/>
+ <combo_box.item name="4x" label="4x"/>
+ <combo_box.item name="8x" label="8x"/>
+ <combo_box.item name="16x" label="16x"/>
</combo_box>
<spinner label="Gama:" name="gamma"/>
<text name="(brightness, lower is brighter)">
diff --git a/indra/newview/skins/default/xui/pt/floater_hud.xml b/indra/newview/skins/default/xui/pt/floater_hud.xml
index d31bcedf05..e458913452 100644
--- a/indra/newview/skins/default/xui/pt/floater_hud.xml
+++ b/indra/newview/skins/default/xui/pt/floater_hud.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_hud" title="Tutorial"/>
+<floater name="floater_hud" title="TUTORIAL"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_image_preview.xml b/indra/newview/skins/default/xui/pt/floater_image_preview.xml
index 414f9bcae3..a0d8c02ef0 100644
--- a/indra/newview/skins/default/xui/pt/floater_image_preview.xml
+++ b/indra/newview/skins/default/xui/pt/floater_image_preview.xml
@@ -7,39 +7,20 @@
Descrição:
</text>
<text name="preview_label">
- Prévia da Imagem como:
+ Prévia da
+imagem como:
</text>
- <combo_box label="Tipo de Roupas" name="clothing_type_combo">
- <combo_item name="Image">
- Imagem
- </combo_item>
- <combo_item name="Hair">
- Cabelo
- </combo_item>
- <combo_item name="FemaleHead">
- Cabeça Feminina
- </combo_item>
- <combo_item name="FemaleUpperBody">
- Parte Superior do Corpo Feminino
- </combo_item>
- <combo_item name="FemaleLowerBody">
- Parte Inferior do Corpo Feminino
- </combo_item>
- <combo_item name="MaleHead">
- Cabeça Masculina
- </combo_item>
- <combo_item name="MaleUpperBody">
- Parte Superior do Corpo Masculino
- </combo_item>
- <combo_item name="MaleLowerBody">
- Parte Inferiro do Corpo Masculino
- </combo_item>
- <combo_item name="Skirt">
- Saia
- </combo_item>
- <combo_item name="SculptedPrim">
- Primitiva Esculpida
- </combo_item>
+ <combo_box label="Tipo de Roupas" name="clothing_type_combo" left="100" width="186">
+ <combo_box.item name="Image" label="Imagem" />
+ <combo_box.item name="Hair" label="Cabelo" />
+ <combo_box.item name="FemaleHead" label="Cabeça Feminina" />
+ <combo_box.item name="FemaleUpperBody" label="Parte Superior do Corpo Feminino" />
+ <combo_box.item name="FemaleLowerBody" label="Parte Inferior do Corpo Feminino" />
+ <combo_box.item name="MaleHead" label="Cabeça Masculina" />
+ <combo_box.item name="MaleUpperBody" label="Parte Superior do Corpo Masculino" />
+ <combo_box.item name="MaleLowerBody" label="Parte Inferiro do Corpo Masculino" />
+ <combo_box.item name="Skirt" label="Saia" />
+ <combo_box.item name="SculptedPrim" label="Primitiva Esculpida" />
</combo_box>
<text name="bad_image_text">
Incapaz de ler a imagem.
diff --git a/indra/newview/skins/default/xui/pt/floater_inspect.xml b/indra/newview/skins/default/xui/pt/floater_inspect.xml
index f3d4b0f33f..97c2c6eaeb 100644
--- a/indra/newview/skins/default/xui/pt/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/pt/floater_inspect.xml
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="inspect" title="Inspecionar Objeto">
+<floater name="inspect" title="INSPECIONAR OBJETO" min_width="450">
<scroll_list name="object_list" tool_tip="Selecione um objeto nesta lista para destacá-lo in-world">
<column label="Nome do Objeto" name="object_name"/>
- <column label="Nome do Proprietário" name="owner_name"/>
- <column label="Nome do Criador" name="creator_name"/>
+ <column label="Proprietário" name="owner_name"/>
+ <column label="Criador" name="creator_name"/>
<column label="Data de Criação" name="creation_date"/>
</scroll_list>
- <button label="Ver Perfil do Proprietário..." label_selected="" name="button owner" tool_tip="Veja o perfil do proprietário do objeto destacado"/>
- <button label="Ver perfil do criador..." label_selected="" name="button creator" tool_tip="Veja o perfil do criador original do objeto destacado"/>
+ <button width="185" label="Ver Perfil do Proprietário..." label_selected="" name="button owner" tool_tip="Veja o perfil do proprietário do objeto destacado"/>
+ <button width="165" left="205" label="Ver perfil do criador..." label_selected="" name="button creator" tool_tip="Veja o perfil do criador original do objeto destacado"/>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_inventory.xml b/indra/newview/skins/default/xui/pt/floater_inventory.xml
index 8a06fefe3c..1c2a3a9233 100644
--- a/indra/newview/skins/default/xui/pt/floater_inventory.xml
+++ b/indra/newview/skins/default/xui/pt/floater_inventory.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Inventory" title="Inventário">
+<floater name="Inventory" title="INVENTÃRIO">
<search_editor label="Escreva aqui para busca" name="inventory search editor"/>
<tab_container name="inventory filter tabs">
<inventory_panel label="Todos os Itens" name="All Items"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_inventory_item_properties.xml b/indra/newview/skins/default/xui/pt/floater_inventory_item_properties.xml
index 3711a4c871..2a6b02f9c2 100644
--- a/indra/newview/skins/default/xui/pt/floater_inventory_item_properties.xml
+++ b/indra/newview/skins/default/xui/pt/floater_inventory_item_properties.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="item properties" title="Propriedades do Item de Inventário">
+<floater name="item properties" title="PROPRIEDADES DO ITEM DE INVENTÃRIO">
<text name="LabelItemNameTitle">
Nome:
</text>
@@ -49,7 +49,7 @@
</text>
<check_box label="Compartilhar com o grupo" name="CheckShareWithGroup"/>
<check_box label="Permitir qualquer um copiar" name="CheckEveryoneCopy"/>
- <text name="NextOwnerLabel">
+ <text name="NextOwnerLabel" width="230">
Próximo dono pode:
</text>
<check_box label="Modificar" name="CheckNextOwnerModify"/>
@@ -60,12 +60,8 @@
</text>
<check_box label="À venda" name="CheckPurchase"/>
<radio_group name="RadioSaleType">
- <radio_item name="radio">
- Original
- </radio_item>
- <radio_item name="radio2">
- Cópia
- </radio_item>
+ <radio_item name="radio" label="Original" />
+ <radio_item name="radio2" label="Cópia" />
</radio_group>
<text name="TextPrice">
Price: L$
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 634e236650..57cdd50dcc 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
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Inventory Finder" title="itens_de_inventário_recentes">
+<floater name="Inventory Finder" title="ITENS_DE_INVENTÃRIO_RECENTES" width="165">
<check_box label="Animação" name="check_animation"/>
<check_box label="Cartões de chamadas" name="check_calling_card"/>
<check_box label="Roupas" name="check_clothing"/>
@@ -13,9 +13,9 @@
<check_box label="Fotos" name="check_snapshot"/>
<button label="Tudo" label_selected="Tudo" name="All"/>
<button label="Nenhum" label_selected="Nenhum" name="None"/>
- <check_box label="Sempre mostrar as pastas" name="check_show_empty"/>
- <check_box label="Desde o Logoff" name="check_since_logoff"/>
- <text length="1" name="- OR -" type="string">
+ <check_box label="Sempre mostrar as pastas" name="check_show_empty" left="3"/>
+ <check_box label="Desde o Logoff" name="check_since_logoff" left="3"/>
+ <text name="- OR -">
- OU -
</text>
<spinner label="Horas Atrás" name="spin_hours_ago"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_joystick.xml b/indra/newview/skins/default/xui/pt/floater_joystick.xml
index 6c2e4a5144..0793a0b161 100644
--- a/indra/newview/skins/default/xui/pt/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/pt/floater_joystick.xml
@@ -1,30 +1,23 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Joystick" title="Configuração do Joystick">
- <check_box name="enable_joystick">
- Habilitar Joystick:
- </check_box>
- <spinner label="Mapeamento do eixo X" name="JoystickAxis1"/>
- <spinner label="Mapeamento do eixo Y" name="JoystickAxis2"/>
- <spinner label="Mapeamento do Eixo Z" name="JoystickAxis0"/>
- <spinner label="Mapeamento da Elevação" name="JoystickAxis4"/>
- <spinner label="Mapeamento da Guinada" name="JoystickAxis5"/>
- <spinner label="Mapeamento da Rolagem" name="JoystickAxis3"/>
- <spinner label="Mapeamento do Zoom" name="JoystickAxis6"/>
- <check_box label="Zoom Direto" name="ZoomDirect"/>
+<floater name="Joystick" title="CONFIGURAÇÃO DO JOYSTICK">
+ <check_box name="enable_joystick" label="Habilitar Joystick:"/>
+ <text left="135" name="joystick_type" width="360"/>
+ <spinner label="Mapeamento: eixo X" name="JoystickAxis1" label_width="124" width="164"/>
+ <spinner label="Mapeamento: eixo Y" name="JoystickAxis2" label_width="124" width="164"/>
+ <spinner label="Mapeamento: eixo Z" name="JoystickAxis0" label_width="124" width="164"/>
+ <spinner label="Mapeamento: Elevação" name="JoystickAxis4" label_width="124" width="164"/>
+ <spinner label="Mapeamento: Guinada" name="JoystickAxis5" label_width="124" width="164"/>
+ <spinner label="Mapeamento: Rolagem" name="JoystickAxis3" label_width="124" width="164"/>
+ <spinner label="Mapeamento: Zoom" name="JoystickAxis6" label_width="124" width="164"/>
+ <check_box label="Zoom Direto" name="ZoomDirect" left="194"/>
<check_box label="Cursor 3D" name="Cursor3D"/>
<check_box label="Nível Automático" name="AutoLeveling"/>
<text name="Control Modes:">
Modos de Controle:
</text>
- <check_box name="JoystickAvatarEnabled">
- Avatar
- </check_box>
- <check_box name="JoystickBuildEnabled">
- Construir
- </check_box>
- <check_box name="JoystickFlycamEnabled">
- Camera aérea
- </check_box>
+ <check_box name="JoystickAvatarEnabled" label="Avatar"/>
+ <check_box name="JoystickBuildEnabled" left="192" label="Construir"/>
+ <check_box name="JoystickFlycamEnabled" label="Camera aérea"/>
<text name="XScale">
Escala X
</text>
@@ -34,13 +27,13 @@
<text name="ZScale">
Escala Z
</text>
- <text name="PitchScale">
+ <text name="PitchScale" left="3" width="115">
Escala de Elevação
</text>
- <text name="YawScale">
+ <text name="YawScale" left="3" width="115">
Escala da Guinada
</text>
- <text name="RollScale">
+ <text name="RollScale" left="3" width="115">
Escala de Rolagem
</text>
<text name="XDeadZone">
@@ -52,14 +45,14 @@
<text name="ZDeadZone">
Zona Morta Z
</text>
- <text name="PitchDeadZone">
- Zona Morta da Elevação
+ <text name="PitchDeadZone" left="3" width="115">
+ Zona Morta: Elevação
</text>
- <text name="YawDeadZone">
- Zona Morta da Guinada
+ <text name="YawDeadZone" left="3" width="115">
+ Zona Morta: Guinada
</text>
- <text name="RollDeadZone">
- Zona Morta de Rolagem
+ <text name="RollDeadZone" left="3" width="115">
+ Zona Morta: Rolagem
</text>
<text name="Feathering">
Alisar
@@ -67,18 +60,20 @@
<text name="ZoomScale2">
Escala de Zoom
</text>
- <text name="ZoomDeadZone">
+ <text name="ZoomDeadZone" width="110" left="4">
Zona Morta de Zoom
</text>
- <button label="Padrões do Navegador Espacial" name="SpaceNavigatorDefaults"/>
+ <button label="Padrões do SpaceNavigator" name="SpaceNavigatorDefaults" font="SansSerifSmall"/>
<button label="OK" label_selected="OK" name="ok_btn"/>
<button label="Cancelar" label_selected="Cancelar" name="cancel_btn"/>
- <string name="JoystickMonitor">
- Monitor do Joystick
- </string>
- <string name="Axis">
- Eixo [NUM]
- </string>
+ <stat_view label="Monitor do Joystick" name="axis_view">
+ <stat_bar label="Eixo 0" name="axis0"/>
+ <stat_bar label="Eixo 1" name="axis1"/>
+ <stat_bar label="Eixo 2" name="axis2"/>
+ <stat_bar label="Eixo 3" name="axis3"/>
+ <stat_bar label="Eixo 4" name="axis4"/>
+ <stat_bar label="Eixo 5" name="axis5"/>
+ </stat_view>
<string name="NoDevice">
nenhum dispositivo detectado
</string>
diff --git a/indra/newview/skins/default/xui/pt/floater_lagmeter.xml b/indra/newview/skins/default/xui/pt/floater_lagmeter.xml
index 9dbad7099e..2728633438 100644
--- a/indra/newview/skins/default/xui/pt/floater_lagmeter.xml
+++ b/indra/newview/skins/default/xui/pt/floater_lagmeter.xml
@@ -1,24 +1,27 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_lagmeter" title="Medidor de Atraso">
+<floater name="floater_lagmeter" title="MEDIDOR DE ATRASO">
<button label="" label_selected="" name="client_lagmeter" tool_tip="Status de atraso no Cliente"/>
+ <text left="30" name="client_lag_cause" right="-10" />
+ <text left="30" name="network_lag_cause" right="-10" />
+ <text left="30" name="server_lag_cause" right="-32" />
<text name="client">
Cliente:
</text>
- <text name="client_text">
+ <text name="client_text" font="SansSerifSmall">
Normal
</text>
<button label="" label_selected="" name="network_lagmeter" tool_tip="Status de atraso na rede"/>
<text name="network">
Rede:
</text>
- <text name="network_text">
+ <text name="network_text" font="SansSerifSmall">
Normal
</text>
<button label="" label_selected="" name="server_lagmeter" tool_tip="Status de atraso no servidor"/>
<text name="server">
Servidor:
</text>
- <text name="server_text">
+ <text name="server_text" font="SansSerifSmall">
Normal
</text>
<button label="?" name="server_help"/>
@@ -117,10 +120,10 @@
20
</string>
<string name="server_frame_time_critical_msg">
- Taxa de quadros do simulador abaixo de [SERVER_FRAME_RATE_CRITICAL]
+ Taxa de quadros abaixo de [SERVER_FRAME_RATE_CRITICAL]
</string>
<string name="server_frame_time_warning_msg">
- Taxa de quadros do simulador entre [SERVER_FRAME_RATE_CRITICAL] e [SERVER_FRAME_RATE_WARNING]
+ Taxa de quadros entre [SERVER_FRAME_RATE_CRITICAL] e [SERVER_FRAME_RATE_WARNING]
</string>
<string name="server_frame_time_normal_msg">
Normal
diff --git a/indra/newview/skins/default/xui/pt/floater_land_holdings.xml b/indra/newview/skins/default/xui/pt/floater_land_holdings.xml
index 1a640c9793..d8588e2f05 100644
--- a/indra/newview/skins/default/xui/pt/floater_land_holdings.xml
+++ b/indra/newview/skins/default/xui/pt/floater_land_holdings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="land holdings floater" title="Meu terreno">
+<floater name="land holdings floater" title="MEU TERRENO">
<scroll_list name="parcel list">
<column label="Nome do Lote" name="name"/>
<column label="Região" name="location"/>
@@ -7,7 +7,7 @@
<column label="Ãrea" name="area"/>
</scroll_list>
<button label="Teletransporte" label_selected="Teletransporte" name="Teleport" tool_tip="Teletransportar para o centro do terreno."/>
- <button label="Mostrar no mapa" label_selected="Mostrar no mapa" name="Show on Map" tool_tip="Mostrar esse terreno no mapa do mundo."/>
+ <button width="130" label="Mostrar no mapa" label_selected="Mostrar no mapa" name="Show on Map" tool_tip="Mostrar esse terreno no mapa do mundo."/>
<text name="contrib_label">
Contribuições para os seus grupos:
</text>
@@ -15,22 +15,22 @@
<column label="Grupo" name="group"/>
<column label="Ãrea" name="area"/>
</scroll_list>
- <text name="allowed_label">
+ <text name="allowed_label" width="380">
Propriedades de terreno permitidas com o plano de pagamento atual:
</text>
- <text name="allowed_text">
+ <text name="allowed_text" left_delta="390">
[AREA] m²
</text>
<text name="current_label">
Propriedades de terrenos atuais:
</text>
- <text name="current_text">
+ <text name="current_text" left_delta="390">
[AREA] m²
</text>
<text name="available_label">
Disponível para compra de terras:
</text>
- <text name="available_text">
+ <text name="available_text" left_delta="390">
[AREA] m²
</text>
<string name="area_string">
diff --git a/indra/newview/skins/default/xui/pt/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/pt/floater_live_lsleditor.xml
index af45fa5873..c0b726c476 100644
--- a/indra/newview/skins/default/xui/pt/floater_live_lsleditor.xml
+++ b/indra/newview/skins/default/xui/pt/floater_live_lsleditor.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="script ed float" title="Script: Novo Script">
+<floater name="script ed float" title="SCRIPT: NOVO SCRIPT">
<button label="Resetar" label_selected="Resetar" name="Reset"/>
<check_box label="Correndo" name="running"/>
- <check_box label="Mono" name="mono"/>
+ <check_box label="Mono" name="mono" left="86"/>
<string name="not_allowed">
Você não tem permissão para visualizar este script.
</string>
diff --git a/indra/newview/skins/default/xui/pt/floater_lsl_guide.xml b/indra/newview/skins/default/xui/pt/floater_lsl_guide.xml
index e7e4a22937..49a9e7fcf5 100644
--- a/indra/newview/skins/default/xui/pt/floater_lsl_guide.xml
+++ b/indra/newview/skins/default/xui/pt/floater_lsl_guide.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script ed float" title="LSL Wiki">
+<floater name="script ed float" title="LSL WIKI">
<check_box label="Seguir o Cursor" name="lock_check" />
- <combo_box label="Bloquear" name="history_combo" />
- <button label="Anterior" name="back_btn" />
+ <combo_box label="Bloquear" name="history_combo" left_delta="120" width="70"/>
+ <button label="Anterior" name="back_btn" left_delta="75"/>
<button label="Posterior" name="fwd_btn" />
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_map.xml b/indra/newview/skins/default/xui/pt/floater_map.xml
new file mode 100644
index 0000000000..ff60f77c4b
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/floater_map.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Map">
+ <floater.string name="mini_map_north">
+ N
+ </floater.string>
+ <floater.string name="mini_map_east">
+ L
+ </floater.string>
+ <floater.string name="mini_map_west">
+ O
+ </floater.string>
+ <floater.string name="mini_map_south">
+ S
+ </floater.string>
+ <floater.string name="mini_map_southeast">
+ SE
+ </floater.string>
+ <floater.string name="mini_map_northeast">
+ NE
+ </floater.string>
+ <floater.string name="mini_map_southwest">
+ SO
+ </floater.string>
+ <floater.string name="mini_map_northwest">
+ NO
+ </floater.string>
+ <text label="N" name="floater_map_north" text="N">
+ N
+ </text>
+ <text label="L" name="floater_map_east" text="L">
+ L
+ </text>
+ <text label="O" name="floater_map_west" text="O">
+ O
+ </text>
+ <text label="S" name="floater_map_south" text="S">
+ S
+ </text>
+ <text label="SE" name="floater_map_southeast" text="SE">
+ SE
+ </text>
+ <text label="NE" name="floater_map_northeast" text="NE">
+ NE
+ </text>
+ <text label="SO" name="floater_map_southwest" text="SO">
+ SO
+ </text>
+ <text label="NO" name="floater_map_northwest" text="NO">
+ NO
+ </text>
+</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_media_browser.xml b/indra/newview/skins/default/xui/pt/floater_media_browser.xml
index cfaec5b410..1cd6d5662c 100644
--- a/indra/newview/skins/default/xui/pt/floater_media_browser.xml
+++ b/indra/newview/skins/default/xui/pt/floater_media_browser.xml
@@ -1,5 +1,11 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater min_width="477" name="floater_about" title="Navegador de Mídia" width="570">
+<floater min_width="477" name="floater_about" title="NAVEGADOR DE MÃDIA" width="570">
+ <floater.string name="home_page_url">
+ http://br.secondlife.com
+ </floater.string>
+ <floater.string name="support_page_url">
+ http://br.secondlife.com/support
+ </floater.string>
<layout_stack name="stack1" width="550">
<layout_panel name="nav_controls">
<button label="Para trás" name="back" width="75"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_mem_leaking.xml b/indra/newview/skins/default/xui/pt/floater_mem_leaking.xml
index 374592f0e2..4f93eb90e5 100644
--- a/indra/newview/skins/default/xui/pt/floater_mem_leaking.xml
+++ b/indra/newview/skins/default/xui/pt/floater_mem_leaking.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="MemLeak" title="Simulação de Perda de Memória">
+<floater name="MemLeak" title="SIMULAÇÃO DE PERDA DE MEMÓRIA">
<spinner label="Velocidade da Perda (bytes por quadro):" name="leak_speed"/>
<spinner label="Máximo de Memória Perdida (MB):" name="max_leak"/>
<text name="total_leaked_label">
diff --git a/indra/newview/skins/default/xui/pt/floater_moveview.xml b/indra/newview/skins/default/xui/pt/floater_moveview.xml
index fde1c16454..996a974254 100644
--- a/indra/newview/skins/default/xui/pt/floater_moveview.xml
+++ b/indra/newview/skins/default/xui/pt/floater_moveview.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move floater" title="">
+<floater name="move_floater">
+<panel name="panel_actions">
<button label="" label_selected="" name="turn left btn" tool_tip="Virar à esquerda"/>
<button label="" label_selected="" name="turn right btn" tool_tip="Virar à direita"/>
<button label="" label_selected="" name="move up btn" tool_tip="Pular ou Voar"/>
@@ -8,4 +9,5 @@
<joystick_slide name="slide right btn" tool_tip="Mover para a direita"/>
<joystick_turn name="forward btn" tool_tip="Mover para a frente."/>
<joystick_turn name="backward btn" tool_tip="Mover para trás"/>
+</panel>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_mute_object.xml b/indra/newview/skins/default/xui/pt/floater_mute_object.xml
index d967f527ae..cc669951c3 100644
--- a/indra/newview/skins/default/xui/pt/floater_mute_object.xml
+++ b/indra/newview/skins/default/xui/pt/floater_mute_object.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="mute by name" title="Silenciar objeto pelo nome">
+<floater name="mute by name" title="SILENCIAR OBJETO PELO NOME">
<text name="message">
- Silenciar pelo nome afeta apenas conversa de objeto e MI, não sons. Você deve digitar o nome exato do objeto.
+ Silenciar pelo nome afeta apenas conversa de objeto e MI,
+não sons. Você deve digitar o nome exato do objeto.
</text>
<line_editor name="object_name">
Nome do objeto
</line_editor>
- <button label="Ok" name="OK"/>
+ <button label="OK" name="OK"/>
<button label="Cancelar" name="Cancel"/>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_my_friends.xml b/indra/newview/skins/default/xui/pt/floater_my_friends.xml
index a78b255f8a..68f2a19998 100644
--- a/indra/newview/skins/default/xui/pt/floater_my_friends.xml
+++ b/indra/newview/skins/default/xui/pt/floater_my_friends.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_my_friends" title="Contatos">
+<floater name="floater_my_friends" title="CONTATOS">
<tab_container name="friends_and_groups">
<panel label="Amigos" name="friends_panel"/>
<panel label="Grupos" name="groups_panel"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_openobject.xml b/indra/newview/skins/default/xui/pt/floater_openobject.xml
index 78fe3398be..0dc2852bac 100644
--- a/indra/newview/skins/default/xui/pt/floater_openobject.xml
+++ b/indra/newview/skins/default/xui/pt/floater_openobject.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="objectcontents" title="Conteúdo do objeto">
- <text length="1" name="object_name" type="string">
+<floater name="objectcontents" title="CONTEÚDO DO OBJETO">
+ <text name="object_name">
[DESC]:
</text>
<button label="Copiar para Inventário" label_selected="Copiar para Inventário" name="copy_to_inventory_button" width="132"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_pay.xml b/indra/newview/skins/default/xui/pt/floater_pay.xml
index 6b094d07f6..187df8fd18 100644
--- a/indra/newview/skins/default/xui/pt/floater_pay.xml
+++ b/indra/newview/skins/default/xui/pt/floater_pay.xml
@@ -6,16 +6,16 @@
<button label="L$20" label_selected="L$20" name="fastpay 20" />
<button label="Pagar" label_selected="Pagar" name="pay btn" />
<button label="Cancelar" label_selected="Cancelar" name="cancel btn" />
- <text type="string" length="1" name="payee_label" width="110" left="5">
+ <text name="payee_label" width="110" left="5">
Pagar residente:
</text>
- <text type="string" length="1" name="payee_name" left="110">
+ <text name="payee_name" left="115">
[FIRST] [LAST]
</text>
- <text type="string" length="1" name="fastpay text" width="120" halign="left">
+ <text name="fastpay text" width="120" halign="left">
Pagamento rápido:
</text>
- <text type="string" length="1" name="amount text" left="4" >
+ <text name="amount text" left="4" >
Quantia:
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_pay_object.xml b/indra/newview/skins/default/xui/pt/floater_pay_object.xml
index ad76cf805c..3a3dd9e52e 100644
--- a/indra/newview/skins/default/xui/pt/floater_pay_object.xml
+++ b/indra/newview/skins/default/xui/pt/floater_pay_object.xml
@@ -1,24 +1,24 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="Give Money" title="">
- <text type="string" length="1" name="payee_group" width="100" halign="left">
+ <text name="payee_group" width="100" halign="left">
Pagar Grupo:
</text>
- <text type="string" length="1" name="payee_resident" width="120" halign="left" >
+ <text name="payee_resident" width="120" halign="left" >
Pagar residente:
</text>
- <text type="string" length="1" name="payee_name" left="105">
+ <text name="payee_name" left="105">
[FIRST] [LAST]
</text>
- <text type="string" length="1" name="object_name_label" left="5" width="95" halign="left">
+ <text name="object_name_label" left="5" width="95" halign="left">
Via objeto:
</text>
- <text type="string" length="1" name="object_name_text" left="105" >
+ <text name="object_name_text" left="105" >
...
</text>
- <text type="string" length="1" name="fastpay text" width="115" halign="left">
+ <text name="fastpay text" width="115" halign="left">
Pagamento Rápido:
</text>
- <text type="string" length="1" name="amount text" left="5" halign="left">
+ <text name="amount text" left="5" halign="left">
Quantia:
</text>
<button label="L$1" label_selected="L$1" name="fastpay 1" left="125" width="70"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_perm_prefs.xml b/indra/newview/skins/default/xui/pt/floater_perm_prefs.xml
index 9bb7f04256..33a0d6a456 100644
--- a/indra/newview/skins/default/xui/pt/floater_perm_prefs.xml
+++ b/indra/newview/skins/default/xui/pt/floater_perm_prefs.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="perm prefs" title="Permissões Padrão de Upload">
+<floater name="perm prefs" title="PERMISSÕES PADRÃO DE UPLOAD">
<panel label="Permissões" name="permissions">
<button label="?" label_selected="?" name="help"/>
<check_box label="Compartilhar com o grupo" name="share_with_group"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_post_process.xml b/indra/newview/skins/default/xui/pt/floater_post_process.xml
index 8f5f5db743..d4f2e96539 100644
--- a/indra/newview/skins/default/xui/pt/floater_post_process.xml
+++ b/indra/newview/skins/default/xui/pt/floater_post_process.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Post-Process Floater" title="Ajustes de Pós-processamento">
+<floater name="Post-Process Floater" title="AJUSTES DE PÓS-PROCESSAMENTO">
<tab_container name="Post-Process Tabs">
<panel label="Filtro de Cor" name="wmiColorFilterPanel">
<check_box label="Habilitar" name="wmiColorFilterToggle"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_postcard.xml b/indra/newview/skins/default/xui/pt/floater_postcard.xml
index fe90cb3165..cf63726df2 100644
--- a/indra/newview/skins/default/xui/pt/floater_postcard.xml
+++ b/indra/newview/skins/default/xui/pt/floater_postcard.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Postcard" title="Foto por email">
+<floater name="Postcard" title="FOTO POR EMAIL">
<text name="to_label" width="135">
Email do Destinatário:
</text>
@@ -24,17 +24,17 @@
Digite sua mensagem aqui.
</text_editor>
<text name="fine_print">
- Se seu indicado entrar no SL, você receberá um bônus pela indicação.
+ Se seu indicado entrar no [SECOND_LIFE], você receberá um bônus pela indicação.
</text>
<button label="Cancelar" name="cancel_btn"/>
<button label="Enviar" name="send_btn"/>
<string name="default_subject">
- Cartão postal do Second Life.
+ Cartão postal do [SECOND_LIFE]
</string>
<string name="default_message">
Dá uma olhada nisto!
</string>
<string name="upload_message">
- &quot;Enviando...&quot;
+ Enviando...
</string>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_preferences.xml b/indra/newview/skins/default/xui/pt/floater_preferences.xml
index eb28e99713..d2c3c79160 100644
--- a/indra/newview/skins/default/xui/pt/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/pt/floater_preferences.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Preferences" title="Preferências">
+<floater name="Preferences" title="PREFERÊNCIAS" min_width="332" width="628">
<button label="OK" label_selected="OK" name="OK"/>
<button label="Cancelar" label_selected="Cancelar" name="Cancel"/>
<button label="Aplicar" label_selected="Aplicar" name="Apply"/>
<button label="Sobre" label_selected="Sobre" name="About..."/>
<button label="Ajuda" label_selected="Ajuda" name="Help"/>
+ <tab_container name="pref core" tab_width="128" width="628" />
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_preview_animation.xml b/indra/newview/skins/default/xui/pt/floater_preview_animation.xml
index f9b590b8c2..26ca8f87e0 100644
--- a/indra/newview/skins/default/xui/pt/floater_preview_animation.xml
+++ b/indra/newview/skins/default/xui/pt/floater_preview_animation.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="preview_anim">
- <text length="1" name="desc txt" type="string">
+ <text name="desc txt">
Descrição:
</text>
<button label="Executar in World" label_selected="Parar" left="20" name="Anim play btn" tool_tip="Executar esta animação para que outros vejam." width="131"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_preview_classified.xml b/indra/newview/skins/default/xui/pt/floater_preview_classified.xml
index 4c583c28fb..0e8814b9f8 100644
--- a/indra/newview/skins/default/xui/pt/floater_preview_classified.xml
+++ b/indra/newview/skins/default/xui/pt/floater_preview_classified.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="classified_preview" title="Informação do Anúncio Classificado"/>
+<floater name="classified_preview" title="INFORMAÇÃO DO ANÚNCIO CLASSIFICADO"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_preview_event.xml b/indra/newview/skins/default/xui/pt/floater_preview_event.xml
index 3c8ebcf95a..c03feacf0c 100644
--- a/indra/newview/skins/default/xui/pt/floater_preview_event.xml
+++ b/indra/newview/skins/default/xui/pt/floater_preview_event.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="event_preview" title="Informação do Evento"/>
+<floater name="event_preview" title="INFORMAÇÃO DO EVENTO"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_preview_gesture.xml b/indra/newview/skins/default/xui/pt/floater_preview_gesture.xml
index 416d65fde4..87bf86c282 100644
--- a/indra/newview/skins/default/xui/pt/floater_preview_gesture.xml
+++ b/indra/newview/skins/default/xui/pt/floater_preview_gesture.xml
@@ -22,37 +22,37 @@
<text name="key_label">
Tecla de Atalho:
</text>
- <combo_box label="Nenhum" name="modifier_combo"/>
- <combo_box label="Nenhum" name="key_combo"/>
+ <combo_box label="Nenhum" name="modifier_combo" left="116" width="76"/>
+ <combo_box label="Nenhum" name="key_combo" width="76" left_delta="80"/>
<text name="library_label">
Biblioteca:
</text>
<text name="steps_label">
Passos:
</text>
- <scroll_list name="library_list">
+ <scroll_list name="library_list" width="84">
Animação
Som
Bate Papo
Esperar
</scroll_list>
- <button label="Incluir" name="add_btn"/>
- <button label="Mover Para Cima" name="up_btn"/>
- <button label="Mover Para Baixo" name="down_btn"/>
- <button label="Remover" name="delete_btn"/>
+ <button label="Incluir" name="add_btn" left="118" width="87"/>
+ <button label="Mover Para Cima" name="up_btn" width="114" left_delta="-13"/>
+ <button label="Mover Para Baixo" name="down_btn" width="114"/>
+ <button label="Remover" name="delete_btn" width="84" left_delta="13"/>
+ <scroll_list left="226" name="step_list" width="205" />
<text name="help_label">
- Todos os passos acontecem simultaneamente, a menos que você inclua passos de espera.
+ Todos os passos acontecem
+simultaneamente, a menos que
+você inclua passos de espera.
</text>
<radio_group name="animation_trigger_type">
- <radio_item name="start">
- Iniciar
- </radio_item>
- <radio_item name="stop">
- Parar
- </radio_item>
+ <radio_item name="start" label="Iniciar" />
+ <radio_item name="stop" label="Parar" />
</radio_group>
- <check_box label="até que as animações estejam concluídas" name="wait_anim_check"/>
- <check_box label="tempo em segundos" name="wait_time_check"/>
+ <check_box bottom_delta="34" label="até que as animações estejam &#10;concluídas" name="wait_anim_check"/>
+ <check_box bottom_delta="-30" label="tempo em segundos" name="wait_time_check"/>
+ <line_editor left_delta="130" name="wait_time_editor" />
<check_box label="Ativar" name="active_check" tool_tip="Gestos ativos podem ser gatilhados escrevendo suas frases de gatilho no chat ou através de suas teclas de atalho. Gestos normalmente ficam inativos quando existe um conflito nas teclas de atalho."/>
<button label="Prévia" name="preview_btn"/>
<button label="Salvar" name="save_btn"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_preview_notecard.xml b/indra/newview/skins/default/xui/pt/floater_preview_notecard.xml
index e7d3144292..6f8944942a 100644
--- a/indra/newview/skins/default/xui/pt/floater_preview_notecard.xml
+++ b/indra/newview/skins/default/xui/pt/floater_preview_notecard.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="preview notecard" title="Nota:">
+<floater name="preview notecard" title="NOTA:">
<button label="Salvar" label_selected="Salvar" name="Save"/>
- <text length="1" name="desc txt" type="string">
+ <text name="desc txt">
Descrição:
</text>
- <text_editor length="1" name="Notecard Editor" type="string">
+ <text_editor name="Notecard Editor">
Carregando...
</text_editor>
<string name="no_object">
diff --git a/indra/newview/skins/default/xui/pt/floater_preview_sound.xml b/indra/newview/skins/default/xui/pt/floater_preview_sound.xml
index b61508480d..3dd2f84f91 100644
--- a/indra/newview/skins/default/xui/pt/floater_preview_sound.xml
+++ b/indra/newview/skins/default/xui/pt/floater_preview_sound.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="preview_sound">
- <text length="1" name="desc txt" type="string">
+ <text name="desc txt">
Descrição:
</text>
- <button label="Executar in-World" label_selected="Executar in-World" name="Sound play btn" tool_tip="Executar este som para que todos possam ouvi-lo."/>
- <button label="Executar Localmente" label_selected="Executar Localmente" name="Sound audition btn" tool_tip="Executar este som somente para você ouvir."/>
+ <button left_delta="-132" label="Executar in-World" label_selected="Executar in-World" name="Sound play btn" tool_tip="Executar este som para que todos possam ouvi-lo."/>
+ <button width="135" left="152" label="Executar Localmente" label_selected="Executar Localmente" name="Sound audition btn" tool_tip="Executar este som somente para você ouvir."/>
</floater>
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 43f8497cbd..72bc42fa19 100644
--- a/indra/newview/skins/default/xui/pt/floater_preview_texture.xml
+++ b/indra/newview/skins/default/xui/pt/floater_preview_texture.xml
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="preview_texture">
- <text type="string" length="1" name="desc txt">
+ <text name="desc txt">
Descrição:
</text>
- <text type="string" length="1" name="dimensions">
+ <text name="dimensions">
Dimensões: [WIDTH] x [HEIGHT]
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_region_info.xml b/indra/newview/skins/default/xui/pt/floater_region_info.xml
index fe228ab405..cc5e0d59d4 100644
--- a/indra/newview/skins/default/xui/pt/floater_region_info.xml
+++ b/indra/newview/skins/default/xui/pt/floater_region_info.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="regioninfo" title="Região/Propriedade"/>
+<floater name="regioninfo" title="REGIÃO/PROPRIEDADE"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_report_abuse.xml b/indra/newview/skins/default/xui/pt/floater_report_abuse.xml
index 9091386681..0d226a9502 100644
--- a/indra/newview/skins/default/xui/pt/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/pt/floater_report_abuse.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_report_abuse" title="Reportar abuso">
+<floater name="floater_report_abuse" title="REPORTAR ABUSO">
<check_box label="Incluir cópia da tela" name="screen_check"/>
<text name="reporter_title">
Denunciador:
@@ -36,123 +36,45 @@
Hendrerit Vulputate
</text>
<combo_box name="category_combo" tool_tip="Categoria -- Selecione a categoria que melhor descreve este report">
- <combo_item name="Select_category">
- Selecionar categoria
- </combo_item>
- <combo_item name="Age__Age_play">
- Idade &gt; Idade no jogo
- </combo_item>
- <combo_item name="Age__Adult_resident_on_Teen_Second_Life">
- Idade &gt; Residente adulto no Second Life Jovem
- </combo_item>
- <combo_item name="Age__Underage_resident_outside_of_Teen_Second_Life">
- Idade &gt; Residente menor de idade fora do Second Life Teen
- </combo_item>
- <combo_item name="Assault__Combat_sandbox___unsafe_area">
- Assalto &gt; Sandbox de combate / área não segura
- </combo_item>
- <combo_item name="Assault__Safe_area">
- Assalto &gt; Ãrea segura
- </combo_item>
- <combo_item name="Assault__Weapons_testing_sandbox">
- Assalto &gt; Testando armas em sandbox
- </combo_item>
- <combo_item name="Commerce__Failure_to_deliver_product_or_service">
- Comércio &gt; Falha em enviar produto ou serviço
- </combo_item>
- <combo_item name="Disclosure__Real_world_information">
- Revelar &gt; Informação do mundo real
- </combo_item>
- <combo_item name="Disclosure__Remotely_monitoring chat">
- Revelar &gt; Conversa monitorada remotamente
- </combo_item>
- <combo_item name="Disclosure__Second_Life_information_chat_IMs">
- Revelar &gt; Informação do Second Life/conversa/MIs
- </combo_item>
- <combo_item name="Disturbing_the_peace__Unfair_use_of_region_resources">
- Distúrbio da paz &gt; Uso injusto dos recursos da região
- </combo_item>
- <combo_item name="Disturbing_the_peace__Excessive_scripted_objects">
- Distúrbio da paz &gt; Objetos com excesso de scripts
- </combo_item>
- <combo_item name="Disturbing_the_peace__Object_littering">
- Distúrbio da paz &gt; Objeto despejando lixo
- </combo_item>
- <combo_item name="Disturbing_the_peace__Repetitive_spam">
- Distúrbio da paz &gt; Spam repetitivo
- </combo_item>
- <combo_item name="Disturbing_the_peace__Unwanted_advert_spam">
- Distúrbio da paz &gt; Spam de anúncio indesejado
- </combo_item>
- <combo_item name="Fraud__L$">
- Fraude &gt; L$
- </combo_item>
- <combo_item name="Fraud__Land">
- Fraude &gt; Terra
- </combo_item>
- <combo_item name="Fraud__Pyramid_scheme_or_chain_letter">
- Fraude &gt; Esquema de pirâmide ou cartas encadeadas
- </combo_item>
- <combo_item name="Fraud__US$">
- Fraude &gt; R$
- </combo_item>
- <combo_item name="Harassment__Advert_farms___visual_spam">
- Perturbação &gt; Fazendas de Anúncios / spam visual
- </combo_item>
- <combo_item name="Harassment__Defaming_individuals_or_groups">
- Perturbação &gt; Difamação de indivíduos ou grupos
- </combo_item>
- <combo_item name="Harassment__Impeding_movement">
- Perturbação &gt; Impedindo movimentos
- </combo_item>
- <combo_item name="Harassment__Sexual_harassment">
- Perturbação &gt; Perturbação sexual
- </combo_item>
- <combo_item name="Harassment__Solicting_inciting_others_to_violate_ToS">
- Perturbação &gt; Solicitando/incitando outros a violarem o ToS
- </combo_item>
- <combo_item name="Harassment__Verbal_abuse">
- Perturbação &gt; Abuso verbal
- </combo_item>
- <combo_item name="Indecency__Broadly_offensive_content_or_conduct">
- Indecência &gt; Conteúdo ou conduta amplamente ofensivos
- </combo_item>
- <combo_item name="Indecency__Inappropriate_avatar_name">
- Indecência &gt; Nome de avatar inapropriado
- </combo_item>
- <combo_item name="Indecency__Mature_content_in_PG_region">
- Indecência &gt; Conduta ou conteúdo inapropriados numa região PG
- </combo_item>
- <combo_item name="Indecency__Inappropriate_content_in_Mature_region">
- Indecência &gt; Conduta ou conteúdo inapropriados numa região Mature
- </combo_item>
- <combo_item name="Intellectual_property_infringement_Content_Removal">
- Violação de propriedade intelectual &gt; Remoção de Conteúdo
- </combo_item>
- <combo_item name="Intellectual_property_infringement_CopyBot_or_Permissions_Exploit">
- Violação de Propriedade intelectual &gt; Cópia Ilegal ou Aproveitar-se de Permissões
- </combo_item>
- <combo_item name="Intolerance">
- Intolerância
- </combo_item>
- <combo_item name="Land__Abuse_of_sandbox_resources">
- Terra &gt; Abuso dos recursos da sandbox
- </combo_item>
- <combo_item name="Land__Encroachment__Objects_textures">
- Terra &gt; Invasão &gt; Objetos/texturas
- </combo_item>
- <combo_item name="Land__Encroachment__Particles">
- Terra &gt; Invasão &gt; Partículas
- </combo_item>
- <combo_item name="Land__Encroachment__Trees_plants">
- Terra &gt; Violação &gt; Ãrvores/plantas
- </combo_item>
- <combo_item name="Wagering_gambling">
- Apostas/jogos de azar
- </combo_item>
- <combo_item name="Other">
- Outro
- </combo_item>
+ <combo_box.item name="Select_category" label="Selecionar categoria"/>
+ <combo_box.item name="Age__Age_play" label="Idade &gt; Idade no jogo"/>
+ <combo_box.item name="Age__Adult_resident_on_Teen_Second_Life" label="Idade &gt; Residente adulto no Second Life Jovem"/>
+ <combo_box.item name="Age__Underage_resident_outside_of_Teen_Second_Life" label="Idade &gt; Residente menor de idade fora do Second Life Teen"/>
+ <combo_box.item name="Assault__Combat_sandbox___unsafe_area" label="Assalto &gt; Sandbox de combate / área não segura"/>
+ <combo_box.item name="Assault__Safe_area" label="Assalto &gt; Ãrea segura"/>
+ <combo_box.item name="Assault__Weapons_testing_sandbox" label="Assalto &gt; Testando armas em sandbox"/>
+ <combo_box.item name="Commerce__Failure_to_deliver_product_or_service" label="Comércio &gt; Falha em enviar produto ou serviço"/>
+ <combo_box.item name="Disclosure__Real_world_information" label="Revelar &gt; Informação do mundo real"/>
+ <combo_box.item name="Disclosure__Remotely_monitoring chat" label="Revelar &gt; Conversa monitorada remotamente"/>
+ <combo_box.item name="Disclosure__Second_Life_information_chat_IMs" label="Revelar &gt; Informação do Second Life/conversa/MIs"/>
+ <combo_box.item name="Disturbing_the_peace__Unfair_use_of_region_resources" label="Distúrbio da paz &gt; Uso injusto dos recursos da região"/>
+ <combo_box.item name="Disturbing_the_peace__Excessive_scripted_objects" label="Distúrbio da paz &gt; Objetos com excesso de scripts"/>
+ <combo_box.item name="Disturbing_the_peace__Object_littering" label="Distúrbio da paz &gt; Objeto despejando lixo"/>
+ <combo_box.item name="Disturbing_the_peace__Repetitive_spam" label="Distúrbio da paz &gt; Spam repetitivo"/>
+ <combo_box.item name="Disturbing_the_peace__Unwanted_advert_spam" label="Distúrbio da paz &gt; Spam de anúncio indesejado"/>
+ <combo_box.item name="Fraud__L$" label="Fraude &gt; L$"/>
+ <combo_box.item name="Fraud__Land" label="Fraude &gt; Terra"/>
+ <combo_box.item name="Fraud__Pyramid_scheme_or_chain_letter" label="Fraude &gt; Esquema de pirâmide ou cartas encadeadas"/>
+ <combo_box.item name="Fraud__US$" label="Fraude &gt; R$"/>
+ <combo_box.item name="Harassment__Advert_farms___visual_spam" label="Perturbação &gt; Fazendas de Anúncios / spam visual"/>
+ <combo_box.item name="Harassment__Defaming_individuals_or_groups" label="Perturbação &gt; Difamação de indivíduos ou grupos"/>
+ <combo_box.item name="Harassment__Impeding_movement" label="Perturbação &gt; Impedindo movimentos"/>
+ <combo_box.item name="Harassment__Sexual_harassment" label="Perturbação &gt; Perturbação sexual"/>
+ <combo_box.item name="Harassment__Solicting_inciting_others_to_violate_ToS" label="Perturbação &gt; Solicitando/incitando outros a violarem o ToS"/>
+ <combo_box.item name="Harassment__Verbal_abuse" label="Perturbação &gt; Abuso verbal"/>
+ <combo_box.item name="Indecency__Broadly_offensive_content_or_conduct" label="Indecência &gt; Conteúdo ou conduta amplamente ofensivos"/>
+ <combo_box.item name="Indecency__Inappropriate_avatar_name" label="Indecência &gt; Nome de avatar inapropriado"/>
+ <combo_box.item name="Indecency__Mature_content_in_PG_region" label="Indecência &gt; Conduta ou conteúdo inapropriados numa região PG"/>
+ <combo_box.item name="Indecency__Inappropriate_content_in_Mature_region" label="Indecência &gt; Conduta ou conteúdo inapropriados numa região Mature"/>
+ <combo_box.item name="Intellectual_property_infringement_Content_Removal" label="Violação de propriedade intelectual &gt; Remoção de Conteúdo"/>
+ <combo_box.item name="Intellectual_property_infringement_CopyBot_or_Permissions_Exploit" label="Violação de Propriedade intelectual &gt; Cópia Ilegal ou Aproveitar-se de Permissões"/>
+ <combo_box.item name="Intolerance" label="Intolerância"/>
+ <combo_box.item name="Land__Abuse_of_sandbox_resources" label="Terra &gt; Abuso dos recursos da sandbox"/>
+ <combo_box.item name="Land__Encroachment__Objects_textures" label="Terra &gt; Invasão &gt; Objetos/texturas"/>
+ <combo_box.item name="Land__Encroachment__Particles" label="Terra &gt; Invasão &gt; Partículas"/>
+ <combo_box.item name="Land__Encroachment__Trees_plants" label="Terra &gt; Violação &gt; Ãrvores/plantas"/>
+ <combo_box.item name="Wagering_gambling" label="Apostas/jogos de azar"/>
+ <combo_box.item name="Other" label="Outro"/>
</combo_box>
<text name="abuser_name_title">
Nome do Denunciado:
@@ -170,8 +92,8 @@
</text>
<text name="bug_aviso">
Por favor, seja específico(a) sobre data, localidade,
-natureza do abuso, texto relevante de conversa/MI e selecione o objeto,
-se possível.
+natureza do abuso, texto relevante de conversa/MI e
+selecione o objeto, se possível.
</text>
<text name="incomplete_title">
Nota: Relatos incompletos não serão investigados.
diff --git a/indra/newview/skins/default/xui/pt/floater_script_debug.xml b/indra/newview/skins/default/xui/pt/floater_script_debug.xml
index 48c73b93a3..6d1d981ca7 100644
--- a/indra/newview/skins/default/xui/pt/floater_script_debug.xml
+++ b/indra/newview/skins/default/xui/pt/floater_script_debug.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<multi_floater name="script debug floater" title="Aviso de script/erro">
<tab_container name="Preview Tabs">
- <floater label="Script" name="all_scripts" title="[Todos os scripts]"/>
+ <floater label="Script" name="all_scripts" title="[ALL SCRIPTS]"/>
</tab_container>
</multi_floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_script_preview.xml b/indra/newview/skins/default/xui/pt/floater_script_preview.xml
index d014e040a2..3c0570791c 100644
--- a/indra/newview/skins/default/xui/pt/floater_script_preview.xml
+++ b/indra/newview/skins/default/xui/pt/floater_script_preview.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="preview lsl text" title="Script: Rotation Script">
- <text type="string" length="1" name="desc txt">
+<floater name="preview lsl text" title="SCRIPT: ROTATION SCRIPT">
+ <text name="desc txt">
Descrição:
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_script_queue.xml b/indra/newview/skins/default/xui/pt/floater_script_queue.xml
index 7b35226bdb..6e0e174c07 100644
--- a/indra/newview/skins/default/xui/pt/floater_script_queue.xml
+++ b/indra/newview/skins/default/xui/pt/floater_script_queue.xml
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="queue" title="Resetar Progresso">
+<floater name="queue" title="RESETAR PROGRESSO">
<button label="Fechar" label_selected="Fechar" name="close"/>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_script_search.xml b/indra/newview/skins/default/xui/pt/floater_script_search.xml
index aaf1ea4339..3a62f1711f 100644
--- a/indra/newview/skins/default/xui/pt/floater_script_search.xml
+++ b/indra/newview/skins/default/xui/pt/floater_script_search.xml
@@ -1,13 +1,15 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="script search" title="Busca de Script">
- <check_box label="Não diferenciar Maiúsculas de Minúsculas" name="case_text"/>
- <button label="Buscar" label_selected="Buscar" name="search_btn"/>
- <button label="Substituir" label_selected="Substituir" name="replace_btn"/>
- <button label="Substituir Tudo" label_selected="Substituir Tudo" name="replace_all_btn"/>
- <text length="1" name="txt" type="string">
+<floater name="script search" title="BUSCA DE SCRIPT" width="320">
+ <check_box label="Não diferenciar Maiúsculas de Minúsculas" name="case_text" left="75"/>
+ <button label="Buscar" label_selected="Buscar" name="search_btn" width="85"/>
+ <button label="Substituir" label_selected="Substituir" name="replace_btn" left="100" width="85"/>
+ <button label="Substituir Tudo" label_selected="Substituir Tudo" name="replace_all_btn" left="190" width="122"/>
+ <text name="txt" width="65">
Buscar
</text>
- <text length="1" name="txt2" type="string">
+ <text name="txt2" width="65">
Substituir
</text>
+ <line_editor left="75" name="search_text" width="240" />
+ <line_editor left="75" name="replace_text" width="240" />
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_sell_land.xml b/indra/newview/skins/default/xui/pt/floater_sell_land.xml
index 4236d2a465..f58c4098ef 100644
--- a/indra/newview/skins/default/xui/pt/floater_sell_land.xml
+++ b/indra/newview/skins/default/xui/pt/floater_sell_land.xml
@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="sell land" title="Vender terreno">
+<floater name="sell land" title="VENDER TERRENO">
+ <scroll_container name="profile_scroll">
+ <panel name="scroll_content_panel">
<text name="info_parcel_label">
Lote:
</text>
@@ -36,15 +38,9 @@
particular.
</text>
<combo_box name="sell_to" bottom_delta="-32">
- <combo_item name="--selectone--">
- -- Selecione um --
- </combo_item>
- <combo_item name="Anyone">
- Qualquer um
- </combo_item>
- <combo_item name="Specificuser:">
- Usuário Específico:
- </combo_item>
+ <combo_box.item name="--selectone--" label="Selecione um --" />
+ <combo_box.item name="Anyone" label="Qualquer um" />
+ <combo_box.item name="Specificuser:" label="Usuário Específico:" />
</combo_box>
<button label="Selecione..." name="sell_to_select_agent"/>
<text name="sell_objects_label">
@@ -55,12 +51,8 @@ particular.
lote irão mudar de propriedade.
</text>
<radio_group name="sell_objects" bottom_delta="-58">
- <radio_item name="no">
- Não, manter a propriedade sobre os objetos
- </radio_item>
- <radio_item name="yes">
- Sim, vender objetos com a terra
- </radio_item>
+ <radio_item name="no" label="Não, manter a propriedade sobre os objetos" />
+ <radio_item name="yes" label="Sim, vender objetos com a terra" />
</radio_group>
<button label="Mostrar Objetos" name="show_objects"/>
<text name="nag_message_label">
@@ -68,4 +60,6 @@ lote irão mudar de propriedade.
</text>
<button label="Definir Terra para Venda" name="sell_btn"/>
<button label="Cancelar" name="cancel_btn"/>
+ </panel>
+ </scroll_container>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_settings_debug.xml b/indra/newview/skins/default/xui/pt/floater_settings_debug.xml
index 2109c311e3..394a9771e0 100644
--- a/indra/newview/skins/default/xui/pt/floater_settings_debug.xml
+++ b/indra/newview/skins/default/xui/pt/floater_settings_debug.xml
@@ -1,12 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="settings_debug" title="Configurações de Debug">
+<floater name="settings_debug" title="CONFIGURAÇÕES DE DEBUG">
<combo_box name="boolean_combo">
- <combo_item name="TRUE">
- VERDADEIRO
- </combo_item>
- <combo_item name="FALSE">
- FALSO
- </combo_item>
+ <combo_box.item name="TRUE" label="VERDADEIRO" />
+ <combo_box.item name="FALSE" label="FALSO" />
</combo_box>
<color_swatch label="Cor" name="color_swatch"/>
<spinner label="x" name="val_spinner_1"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_snapshot.xml b/indra/newview/skins/default/xui/pt/floater_snapshot.xml
index f0e9d4b92c..c3c4c73a89 100644
--- a/indra/newview/skins/default/xui/pt/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/pt/floater_snapshot.xml
@@ -1,18 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Snapshot" title="Prévia da foto">
+<floater name="Snapshot" title="PRÉVIA DA FOTO">
<text name="type_label">
Destino da foto
</text>
<radio_group label="Tipo de Foto" name="snapshot_type_radio">
- <radio_item name="postcard">
- Enviar por email
- </radio_item>
- <radio_item name="texture">
- Salvar no seu inventário (L$[AMOUNT])
- </radio_item>
- <radio_item name="local">
- Salvar no seu disco rígido
- </radio_item>
+ <radio_item name="postcard" label="Enviar por email" />
+ <radio_item name="texture" label="Salvar no seu inventário (L$[AMOUNT])" />
+ <radio_item name="local" label="Salvar no seu disco rígido" />
</radio_group>
<text name="file_size_label">
Tamanho do arquivo: [SIZE] KB
@@ -21,12 +15,8 @@
<button label="Enviar" name="send_btn"/>
<button label="Salvar (L$[AMOUNT])" name="upload_btn"/>
<flyout_button label="Salvar" name="save_btn" tool_tip="Salvar imagem em um arquivo">
- <flyout_button_item name="save_item">
- Salvar
- </flyout_button_item>
- <flyout_button_item name="saveas_item">
- Salvar como...
- </flyout_button_item>
+ <flyout_button.item name="save_item" label="Salvar"/>
+ <flyout_button.item name="saveas_item" label="Salvar como..."/>
</flyout_button>
<button label="Cancelar" name="discard_btn"/>
<button label="Mais &gt;" name="more_btn" tool_tip="Opções Avançadas"/>
@@ -38,99 +28,51 @@
Formato
</text>
<combo_box label="Resolução" name="postcard_size_combo">
- <combo_item name="CurrentWindow">
- Janela Atual
- </combo_item>
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
- <combo_item name="Custom">
- Customizado
- </combo_item>
+ <combo_box.item name="CurrentWindow" label="Janela Atual" />
+ <combo_box.item name="640x480" label="640x480" />
+ <combo_box.item name="800x600" label="800x600" />
+ <combo_box.item name="1024x768" label="1024x768" />
+ <combo_box.item name="Custom" label="Customizado" />
</combo_box>
<combo_box label="Resolução" name="texture_size_combo">
- <combo_item name="CurrentWindow">
- Janela Atual
- </combo_item>
- <combo_item name="Small(128x128)">
- Pequeno (128x128)
- </combo_item>
- <combo_item name="Medium(256x256)">
- Médio (256x256)
- </combo_item>
- <combo_item name="Large(512x512)">
- Grande (512x512)
- </combo_item>
- <combo_item name="Custom">
- Customizado
- </combo_item>
+ <combo_box.item name="CurrentWindow" label="Janela Atual" />
+ <combo_box.item name="Small(128x128)" label="Pequeno (128x128)" />
+ <combo_box.item name="Medium(256x256)" label="Médio (256x256)" />
+ <combo_box.item name="Large(512x512)" label="Grande (512x512)" />
+ <combo_box.item name="Custom" label="Customizado" />
</combo_box>
<combo_box label="Resolução" name="local_size_combo">
- <combo_item name="CurrentWindow">
- Janela Atual
- </combo_item>
- <combo_item name="320x240">
- 320x240
- </combo_item>
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
- <combo_item name="1280x1024">
- 1280x1024
- </combo_item>
- <combo_item name="1600x1200">
- 1600x1200
- </combo_item>
- <combo_item name="Custom">
- Customizado
- </combo_item>
+ <combo_box.item name="CurrentWindow" label="Janela Atual" />
+ <combo_box.item name="320x240" label="320x240" />
+ <combo_box.item name="640x480" label="640x480" />
+ <combo_box.item name="800x600" label="800x600" />
+ <combo_box.item name="1024x768" label="1024x768" />
+ <combo_box.item name="1280x1024" label="1280x1024" />
+ <combo_box.item name="1600x1200" label="1600x1200" />
+ <combo_box.item name="Custom" label="Customizado" />
</combo_box>
<combo_box label="Formato" name="local_format_combo">
- <combo_item name="PNG">
- PNG
- </combo_item>
- <combo_item name="JPEG">
- JPEG
- </combo_item>
- <combo_item name="BMP">
- BMP
- </combo_item>
+ <combo_box.item name="PNG" label="PNG" />
+ <combo_box.item name="JPEG" label="JPEG" />
+ <combo_box.item name="BMP" label="BMP" />
</combo_box>
- <spinner label="Largura" name="snapshot_width"/>
- <spinner label="Altura" name="snapshot_height"/>
+ <spinner label="Largura" name="snapshot_width" label_width="41" width="101"/>
+ <spinner label="Altura" name="snapshot_height" label_width="31" width="91" left="119"/>
<check_box label="Restringir proporções" name="keep_aspect_check"/>
<slider label="Qualidade da Imagem" name="image_quality_slider"/>
<text name="layer_type_label">
Capturar:
</text>
<combo_box label="Camadas da Imagem" name="layer_types">
- <combo_item name="Colors">
- Cores
- </combo_item>
- <combo_item name="Depth">
- Formato
- </combo_item>
- <combo_item name="ObjectMattes">
- Decoração do Objeto
- </combo_item>
+ <combo_box.item name="Colors" label="Cores" />
+ <combo_box.item name="Depth" label="Formato" />
+ <combo_box.item name="ObjectMattes" label="Decoração do Objeto" />
</combo_box>
<check_box label="Mostrar interface na Foto" name="ui_check"/>
- <check_box label="Mostrar Objetos HUD na Foto" name="hud_check"/>
- <check_box label="Manter aberto após salvar" name="keep_open_check"/>
- <check_box label="Quadro Congelado (prévia da tela inteira)" name="freeze_frame_check"/>
- <check_box label="Auto-atualizar" name="auto_snapshot_check"/>
+ <check_box bottom_delta="-17" label="Mostrar Objetos HUD na Foto" name="hud_check"/>
+ <check_box bottom_delta="-17" label="Manter aberto após salvar" name="keep_open_check"/>
+ <check_box bottom_delta="-17" label="Quadro Congelado&#10; (prévia da tela inteira)" name="freeze_frame_check"/>
+ <check_box bottom_delta="-29" label="Auto-atualizar" name="auto_snapshot_check"/>
<string name="unknown">
desconhecido
</string>
diff --git a/indra/newview/skins/default/xui/pt/floater_sound_preview.xml b/indra/newview/skins/default/xui/pt/floater_sound_preview.xml
index df76499f42..d5d252c0dd 100644
--- a/indra/newview/skins/default/xui/pt/floater_sound_preview.xml
+++ b/indra/newview/skins/default/xui/pt/floater_sound_preview.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Sound Preview" title="sound.wav">
+<floater name="Sound Preview" title="SOUND.WAV">
<text name="name_label">
Nome:
</text>
diff --git a/indra/newview/skins/default/xui/pt/floater_statistics.xml b/indra/newview/skins/default/xui/pt/floater_statistics.xml
index d26c7081cc..c56c9fb2e0 100644
--- a/indra/newview/skins/default/xui/pt/floater_statistics.xml
+++ b/indra/newview/skins/default/xui/pt/floater_statistics.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="stats floater" title="Statística"/>
+<floater name="stats floater" title="STATÃSTICA"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_telehub.xml b/indra/newview/skins/default/xui/pt/floater_telehub.xml
index f2634be852..5c775ab45d 100644
--- a/indra/newview/skins/default/xui/pt/floater_telehub.xml
+++ b/indra/newview/skins/default/xui/pt/floater_telehub.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="telehub" title="Telehub">
+<floater name="telehub" title="TELEHUB" min_height="310" height="310" width="286">
<text name="status_text_connected">
Telehub conectado ao objeto [OBJECT]
</text>
@@ -14,15 +14,19 @@
</text>
<button label="Conectar Telehub" name="connect_btn"/>
<button label="Desconectar" name="disconnect_btn"/>
- <text name="spawn_points_text">
+ <text name="spawn_points_text" width="265">
Pontos de Nascimento (posições, não objetos):
</text>
- <button label="Adicionar Nascimento" name="add_spawn_point_btn"/>
- <button label="Remover Nascimento" name="remove_spawn_point_btn"/>
+ <scroll_list name="spawn_points_list" width="265" />
+ <button width="135" label="Adicionar Nascimento" name="add_spawn_point_btn"/>
+ <button width="130" label="Remover Nascimento" name="remove_spawn_point_btn" left="150"/>
<text name="spawn_point_help">
- Selecione um objeto e clique Adicionar para especificar
-a posição. Em seguida, você pode mover ou apagar o objeto.
+ Selecione um objeto e clique Adicionar para
+especificar a posição.
+Em seguida, você pode mover ou apagar o objeto.
As posições são relativas ao centro do telehub.
-Selecione um item na lista para mostrar a posição in-world.
+
+Selecione um item na lista para mostrar a posição
+in-world.
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml
index 3fd0d6103e..b63c4a9bbf 100644
--- a/indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="texture picker" title="Pegar: Textura">
+<floater name="texture picker" title="PEGAR: TEXTURA">
<string name="choose_picture">
Clique para escolher uma imagem
</string>
- <text length="1" name="Multiple" type="string">
+ <text name="Multiple">
Multiplo
</text>
- <text length="1" name="unknown" type="string">
+ <text name="unknown">
Dimensões: [DIMENSIONS]
</text>
<button label="Padrão" label_selected="Padrão" name="Default"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_tools.xml b/indra/newview/skins/default/xui/pt/floater_tools.xml
index 9a3d14c0ea..b9ab018606 100644
--- a/indra/newview/skins/default/xui/pt/floater_tools.xml
+++ b/indra/newview/skins/default/xui/pt/floater_tools.xml
@@ -1,40 +1,43 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="toolbox floater" title="">
+<floater name="toolbox floater" title="" short_title="CONSTRUIR" width="288">
<button label="" label_selected="" name="button focus" tool_tip="Foco"/>
<button label="" label_selected="" name="button move" tool_tip="Mover"/>
<button label="" label_selected="" name="button edit" tool_tip="Editar"/>
<button label="" label_selected="" name="button create" tool_tip="Criar"/>
<button label="" label_selected="" name="button land" tool_tip="Terra"/>
- <check_box label="Zoom" name="radio zoom"/>
- <check_box label="Órbita (Ctrl)" name="radio orbit"/>
- <check_box label="Pan (Ctrl-Shift)" name="radio pan"/>
- <check_box label="Mover" name="radio move"/>
- <check_box label="Suspender (Ctrl)" name="radio lift"/>
- <check_box label="Girar (Ctrl-Shift)" name="radio spin"/>
- <check_box label="Posição" name="radio position"/>
- <check_box label="Rotacionar (Ctrl)" name="radio rotate"/>
- <check_box label="Esticar (Ctrl-Shift)" name="radio stretch"/>
- <check_box label="Selecionar Textura" name="radio select face"/>
+ <radio_group name="focus_radio_group">
+ <radio_item label="Zoom" name="radio zoom"/>
+ <radio_item label="Órbita (Ctrl)" name="radio orbit"/>
+ <radio_item label="Pan (Ctrl-Shift)" name="radio pan"/>
+ </radio_group>
+ <radio_group name="move_radio_group">
+ <radio_item label="Mover" name="radio move"/>
+ <radio_item label="Suspender (Ctrl)" name="radio lift"/>
+ <radio_item label="Girar (Ctrl-Shift)" name="radio spin"/>
+ </radio_group>
+ <radio_group name="edit_radio_group">
+ <radio_item label="Posição" name="radio position"/>
+ <radio_item label="Rotacionar (Ctrl)" name="radio rotate"/>
+ <radio_item label="Esticar (Ctrl-Shift)" name="radio stretch"/>
+ <radio_item label="Selecionar Textura" name="radio select face"/>
+ </radio_group>
<check_box label="Editar partes unidas" name="checkbox edit linked parts"/>
<text name="text ruler mode">
Régua:
</text>
<combo_box name="combobox grid mode">
- <combo_item name="World">
- Mundo
- </combo_item>
- <combo_item name="Local">
- Local
- </combo_item>
- <combo_item name="Reference">
- Referência
- </combo_item>
+ <combo_box.item name="World" label="Mundo"
+ />
+ <combo_box.item name="Local" label="Local"
+ />
+ <combo_box.item name="Reference" label="Referência"
+ />
</combo_box>
<check_box label="Esticar ambos os lados" name="checkbox uniform"/>
<check_box label="Esticar Texturas" name="checkbox stretch textures"/>
<check_box label="Usar Grade" name="checkbox snap to grid"/>
<button label="Opções..." label_selected="Opções..." name="Options..."/>
- <text name="text status">
+ <text name="text status" width="280">
Arraste para mover, shift+Arrastar para Copiar
</text>
<button label="" label_selected="" name="ToolCube" tool_tip="Cubo"/>
@@ -56,13 +59,15 @@
<check_box label="Copiar selecionado" name="checkbox copy selection"/>
<check_box label="Centro" name="checkbox copy centers"/>
<check_box label="Rotacionar" name="checkbox copy rotates"/>
- <check_box label="Selecionar Terra" name="radio select land"/>
- <check_box label="Aplainar" name="radio flatten"/>
- <check_box label="Subir" name="radio raise"/>
- <check_box label="Abaixar" name="radio lower"/>
- <check_box label="Suavizar" name="radio smooth"/>
- <check_box label="Endurecer" name="radio noise"/>
- <check_box label="Reverter" name="radio revert"/>
+ <radio_group name="land_radio_group">
+ <radio_item label="Selecionar Terra" name="radio select land"/>
+ <radio_item label="Aplainar" name="radio flatten"/>
+ <radio_item label="Subir" name="radio raise"/>
+ <radio_item label="Abaixar" name="radio lower"/>
+ <radio_item label="Suavizar" name="radio smooth"/>
+ <radio_item label="Endurecer" name="radio noise"/>
+ <radio_item label="Reverter" name="radio revert"/>
+ </radio_group>
<button label="Aplicar" label_selected="Aplicar" name="button apply to selection" tool_tip="Modificar Terra Selecionada"/>
<text name="Bulldozer:">
Escavadeira:
@@ -73,13 +78,13 @@
<text name="Strength:">
Força
</text>
- <text name="obj_count">
+ <text name="obj_count" left="134">
Objetos selecionados: [COUNT]
</text>
- <text name="prim_count">
+ <text name="prim_count" left="134">
primitivas: [COUNT]
</text>
- <tab_container name="Object Info Tabs">
+ <tab_container name="Object Info Tabs" tab_max_width="60" tab_min_width="30" width="288">
<panel label="Comum" name="General">
<text name="Name:">
Nome:
@@ -105,15 +110,13 @@
Grupo:
</text>
<text name="Group Name Proxy">
- Os Lindens
+ The Lindens
</text>
<button label="Definir..." label_selected="Definir..." name="button set group"/>
<text name="Permissions:">
Permissões:
</text>
- <text name="perm_modify">
- Você pode modificar este objeto.
- </text>
+
<check_box label="Compartilhar com o Grupo" name="checkbox share with group" tool_tip="Permite que todos os membros do grupo definido compartilhem e usem suas permissões para este objeto. Você precisa Doar ao Grupo para habilitar as restrições de função."/>
<string name="text deed continued">
Doar...
@@ -129,54 +132,40 @@
<text name="Cost">
Preço: L$
</text>
- <radio_group name="sale type">
- <radio_item name="Original">
- Original
- </radio_item>
- <radio_item name="Copy">
- Cópia
- </radio_item>
- <radio_item name="Contents">
- Conteúdo
- </radio_item>
- </radio_group>
- <text name="Next owner can:">
- Próximo Proprietário pode:
- </text>
- <check_box label="Modificar" name="checkbox next owner can modify"/>
- <check_box label="Copiar" name="checkbox next owner can copy"/>
- <check_box label="Revender/Dar" name="checkbox next owner can transfer"/>
- <text name="label click action">
+ <combo_box name="sale type">
+ <combo_box.item label="Cópia" name="Copy"/>
+ <combo_box.item label="Conteúdo" name="Contents"/>
+ <combo_box.item label="Original" name="Original"/>
+ </combo_box>
+
+ <text name="label click action" width="220">
Quando clicado com o botão esquerdo:
</text>
- <combo_box name="clickaction">
- <combo_item name="Touch/grab(default)">
- Tocar/Pegar (padrão)
- </combo_item>
- <combo_item name="Sitonobject">
- Sentar no objeto
- </combo_item>
- <combo_item name="Buyobject">
- Comprar objeto
- </combo_item>
- <combo_item name="Payobject">
- Pagar Objeto
- </combo_item>
- <combo_item name="Open">
- Abrir
- </combo_item>
- <combo_item name="Play">
- Executar a mídia do lote
- </combo_item>
- <combo_item name="Opemmedia">
- Abrir a mídia do lote
- </combo_item>
+ <combo_box name="clickaction" width="192">
+ <combo_box.item name="Touch/grab(default)" label="Tocar/Pegar (padrão)"
+ />
+ <combo_box.item name="Sitonobject" label="Sentar no objeto"
+ />
+ <combo_box.item name="Buyobject" label="Comprar objeto"
+ />
+ <combo_box.item name="Payobject" label="Pagar Objeto"
+ />
+ <combo_box.item name="Open" label="Abrir"
+ />
+ <combo_box.item name="Play" label="Executar a mídia do lote"
+ />
+ <combo_box.item name="Opemmedia" label="Abrir a mídia do lote"
+ />
</combo_box>
+ <panel name="perms_build">
+ <text name="perm_modify">
+ Você pode modificar este objeto
+ </text>
<text name="B:">
B:
</text>
<text name="O:">
- O;
+ O:
</text>
<text name="G:">
G:
@@ -190,29 +179,36 @@
<text name="F:">
F:
</text>
+ <text name="Next owner can:">
+ Próximo Proprietário pode:
+ </text>
+ <check_box label="Modificar" name="checkbox next owner can modify"/>
+ <check_box label="Copiar" name="checkbox next owner can copy" left_delta="80"/>
+ <check_box name="checkbox next owner can transfer" left_delta="67"/>
+ </panel>
<string name="text modify info 1">
- Você pode modificar este objeto.
+ Você pode modificar este objeto
</string>
<string name="text modify info 2">
- Você pode modificar estes objetos.
+ Você pode modificar estes objetos
</string>
<string name="text modify info 3">
- Você não pode modificar este objeto.
+ Você não pode modificar este objeto
</string>
<string name="text modify info 4">
- Você não pode modificar estes objetos.
+ Você não pode modificar estes objetos
</string>
<string name="text modify warning">
- Você precisa selecionar o objeto todo para ajustar as permissões.
+ Você precisa selecionar o objeto todo para ajustar as permissões
</string>
<string name="Cost Default">
- Preço: L$
+ Preço: L$
</string>
<string name="Cost Total">
- Preço Total: L$
+ Preço Total: L$
</string>
<string name="Cost Per Unit">
- Preço Por: L$
+ Preço Por: L$
</string>
<string name="Cost Mixed">
Preço Misturado
@@ -222,7 +218,7 @@
</string>
</panel>
<panel label="Objeto" name="Object">
- <text name="select_single">
+ <text name="select_single" width="272">
Selecione apenas uma primitiva para editar os parâmetros.
</text>
<text name="edit_object">
@@ -254,62 +250,47 @@
Material
</text>
<combo_box name="material">
- <combo_item name="Stone">
- Pedra
- </combo_item>
- <combo_item name="Metal">
- Metal
- </combo_item>
- <combo_item name="Glass">
- Vidro
- </combo_item>
- <combo_item name="Wood">
- Madeira
- </combo_item>
- <combo_item name="Flesh">
- Carne
- </combo_item>
- <combo_item name="Plastic">
- Plástico
- </combo_item>
- <combo_item name="Rubber">
- Couro
- </combo_item>
+ <combo_box.item name="Stone" label="Pedra"
+ />
+ <combo_box.item name="Metal" label="Metal"
+ />
+ <combo_box.item name="Glass" label="Vidro"
+ />
+ <combo_box.item name="Wood" label="Madeira"
+ />
+ <combo_box.item name="Flesh" label="Carne"
+ />
+ <combo_box.item name="Plastic" label="Plástico"
+ />
+ <combo_box.item name="Rubber" label="Couro"
+ />
</combo_box>
<text name="label basetype">
Forma básica
</text>
<combo_box name="comboBaseType">
- <combo_item name="Box">
- Caixa
- </combo_item>
- <combo_item name="Cylinder">
- Cilindro
- </combo_item>
- <combo_item name="Prism">
- Prisma
- </combo_item>
- <combo_item name="Sphere">
- Esfera
- </combo_item>
- <combo_item name="Torus">
- Toróide
- </combo_item>
- <combo_item name="Tube">
- Tubo
- </combo_item>
- <combo_item name="Ring">
- Anel
- </combo_item>
- <combo_item name="Sculpted">
- Esculpida
- </combo_item>
+ <combo_box.item name="Box" label="Caixa"
+ />
+ <combo_box.item name="Cylinder" label="Cilindro"
+ />
+ <combo_box.item name="Prism" label="Prisma"
+ />
+ <combo_box.item name="Sphere" label="Esfera"
+ />
+ <combo_box.item name="Torus" label="Toróide"
+ />
+ <combo_box.item name="Tube" label="Tubo"
+ />
+ <combo_box.item name="Ring" label="Anel"
+ />
+ <combo_box.item name="Sculpted" label="Esculpida"
+ />
</combo_box>
<text name="text cut">
- Recorte inicial e final
+ Recorte Início e final
</text>
- <spinner label="B" name="cut begin"/>
- <spinner label="E" name="cut end"/>
+ <spinner label="I" name="cut begin"/>
+ <spinner label="F" name="cut end"/>
<text name="text hollow">
Vazio
</text>
@@ -320,24 +301,20 @@
Forma Vazia
</text>
<combo_box name="hole">
- <combo_item name="Default">
- Padrão
- </combo_item>
- <combo_item name="Circle">
- Circulo
- </combo_item>
- <combo_item name="Square">
- Quadrado
- </combo_item>
- <combo_item name="Triangle">
- Triâgulo
- </combo_item>
+ <combo_box.item name="Default" label="Padrão"
+ />
+ <combo_box.item name="Circle" label="Circulo"
+ />
+ <combo_box.item name="Square" label="Quadrado"
+ />
+ <combo_box.item name="Triangle" label="Triâgulo"
+ />
</combo_box>
<text name="text twist">
Torcer no Início e final
</text>
- <spinner label="B" name="Twist Begin"/>
- <spinner label="E" name="Twist End"/>
+ <spinner label="I" name="Twist Begin"/>
+ <spinner label="F" name="Twist End"/>
<text name="scale_taper">
Afinar
</text>
@@ -351,17 +328,17 @@
</text>
<spinner label="X" name="Shear X"/>
<spinner label="Y" name="Shear Y"/>
- <text name="advanced_cut">
- Perfil Recortado no Início e Final
+ <text name="advanced_cut" width="156">
+ Perfil Recortado no Início e fim
</text>
<text name="advanced_dimple">
- Cova Início e Final
+ Cova Início e final
</text>
<text name="advanced_slice">
- Pedaço Início (B) e Fim (E)
+ Pedaço Início e fim
</text>
- <spinner label="B" name="Path Limit Begin"/>
- <spinner label="E" name="Path Limit End"/>
+ <spinner label="I" name="Path Limit Begin"/>
+ <spinner label="F" name="Path Limit End"/>
<text name="text taper2">
Afinar
</text>
@@ -380,25 +357,20 @@
Tipo costura
</text>
<combo_box name="sculpt type control">
- <combo_item name="None">
- (nenhum)
- </combo_item>
- <combo_item name="Sphere">
- Esfera
- </combo_item>
- <combo_item name="Torus">
- Toróide
- </combo_item>
- <combo_item name="Plane">
- Plano
- </combo_item>
- <combo_item name="Cylinder">
- Cilindro
- </combo_item>
+ <combo_box.item name="None" label="(nenhum)"
+ />
+ <combo_box.item name="Sphere" label="Esfera"
+ />
+ <combo_box.item name="Torus" label="Toróide"
+ />
+ <combo_box.item name="Plane" label="Plano"
+ />
+ <combo_box.item name="Cylinder" label="Cilindro"
+ />
</combo_box>
</panel>
<panel label="Recursos" name="Features">
- <text name="select_single">
+ <text name="select_single" width="272">
Selecione apenas uma primitiva para editar suas características.
</text>
<text name="edit_object">
@@ -425,7 +397,7 @@
<panel label="Textura" name="Texture">
<texture_picker label="Textura" name="texture control" tool_tip="Clique para escolher uma imagem"/>
<color_swatch label="Cor" name="colorswatch" tool_tip="Clique para abrir o Seletor de Cores"/>
- <text name="color trans">
+ <text name="color trans" width="100">
Transparência %
</text>
<text name="glow label">
@@ -436,88 +408,64 @@
Mapeamento
</text>
<combo_box name="combobox texgen">
- <combo_item name="Default">
- Padrão
- </combo_item>
- <combo_item name="Planar">
- Planar
- </combo_item>
+ <combo_box.item name="Default" label="Padrão"
+ />
+ <combo_box.item name="Planar" label="Planar"
+ />
</combo_box>
<text name="label shininess">
Brilho
</text>
<combo_box name="combobox shininess">
- <combo_item name="None">
- Nenhum
- </combo_item>
- <combo_item name="Low">
- Baixo
- </combo_item>
- <combo_item name="Medium">
- Médio
- </combo_item>
- <combo_item name="High">
- Alto
- </combo_item>
+ <combo_box.item name="None" label="Nenhum"
+ />
+ <combo_box.item name="Low" label="Baixo"
+ />
+ <combo_box.item name="Medium" label="Médio"
+ />
+ <combo_box.item name="High" label="Alto"
+ />
</combo_box>
<text name="label bumpiness">
Ondulação
</text>
- <combo_box name="combobox bumpiness">
- <combo_item name="None">
- Nenhum
- </combo_item>
- <combo_item name="Brightness">
- Claridade
- </combo_item>
- <combo_item name="Darkness">
- Escuridão
- </combo_item>
- <combo_item name="woodgrain">
- Granulação
- </combo_item>
- <combo_item name="bark">
- casca
- </combo_item>
- <combo_item name="bricks">
- Tijolos
- </combo_item>
- <combo_item name="checker">
- Caixa
- </combo_item>
- <combo_item name="concrete">
- Concreto
- </combo_item>
- <combo_item name="crustytile">
- Encaroçado
- </combo_item>
- <combo_item name="cutstone">
- Pedra Cortante
- </combo_item>
- <combo_item name="discs">
- Discos
- </combo_item>
- <combo_item name="gravel">
- Cascalho
- </combo_item>
- <combo_item name="petridish">
- Pedrisco
- </combo_item>
- <combo_item name="siding">
- Revestimento
- </combo_item>
- <combo_item name="stonetile">
- empedrado
- </combo_item>
- <combo_item name="stucco">
- Grafiato
- </combo_item>
- <combo_item name="suction">
- Sulcos
- </combo_item>
- <combo_item name="weave">
- weave
- </combo_item>
+ <combo_box name="combobox bumpiness" width="100" >
+ <combo_box.item name="None" label="Nenhum"
+ />
+ <combo_box.item name="Brightness" label="Claridade"
+ />
+ <combo_box.item name="Darkness" label="Escuridão"
+ />
+ <combo_box.item name="woodgrain" label="Granulação"
+ />
+ <combo_box.item name="bark" label="Casca"
+ />
+ <combo_box.item name="bricks" label="Tijolos"
+ />
+ <combo_box.item name="checker" label="Caixa"
+ />
+ <combo_box.item name="concrete" label="Concreto"
+ />
+ <combo_box.item name="crustytile" label="Encaroçado"
+ />
+ <combo_box.item name="cutstone" label="Pedra Cortante"
+ />
+ <combo_box.item name="discs" label="Discos"
+ />
+ <combo_box.item name="gravel" label="Cascalho"
+ />
+ <combo_box.item name="petridish" label="Pedrisco"
+ />
+ <combo_box.item name="siding" label="Revestimento"
+ />
+ <combo_box.item name="stonetile" label="Empedrado"
+ />
+ <combo_box.item name="stucco" label="Grafiato"
+ />
+ <combo_box.item name="suction" label="Sulcos"
+ />
+ <combo_box.item name="weave" label="Weave"
+ />
</combo_box>
<text name="tex scale">
Repetir por Face
@@ -550,8 +498,9 @@
<button label="Alinhar" label_selected="Alinhar" name="button align"/>
</panel>
<panel label="Conteúdo" name="Contents">
- <button label="Novo Script" label_selected="Novo Script..." name="button new script"/>
- <button label="Permissões..." name="button permissions"/>
+ <button label="Novo Script" label_selected="Novo Script" name="button new script"/>
+ <button label="Permissões" name="button permissions"/>
+ <panel name="ContentsInventory" width="272" />
</panel>
</tab_container>
<panel name="land info panel">
@@ -565,56 +514,56 @@
Ãrea: [AREA] m².
</text>
<button label="Sobre a Terra..." label_selected="Sobre a Terra..." name="button about land"/>
- <check_box label="Mostrar donos" name="checkbox show owners" tool_tip="Colorir lotes de acordo com seus donos"/>
- <button label="?" label_selected="?" name="button show owners help"/>
+ <check_box label="Mostrar donos" name="checkbox show owners" tool_tip="Colorir lotes de acordo com seus donos: &#10;&#10;Green = Sua terra &#10;Aqua = Terra do seu grupo &#10;Red = Possuída por outros &#10;Yellow = À venda &#10;Purple = A leilão &#10;Grey = Pública"/>
+ <button label="?" label_selected="?" name="button show owners help" left_delta="100"/>
<text name="label_parcel_modify">
Modificar Lote
</text>
- <button label="Sub-Dividir..." label_selected="Sub-Dividir..." name="button subdivide land"/>
- <button label="Unir..." label_selected="Unir..." name="button join land"/>
+ <button label="Sub-Dividir" label_selected="Sub-Dividir" name="button subdivide land"/>
+ <button label="Unir" label_selected="Unir" name="button join land"/>
<text name="label_parcel_trans">
Transações com a Terra
</text>
- <button label="Comprar Terra..." label_selected="Comprar Terra.." name="button buy land"/>
- <button label="Abandonar Terra..." label_selected="Abandonar Terra..." name="button abandon land"/>
+ <button label="Comprar Terra" label_selected="Comprar Terra" name="button buy land"/>
+ <button label="Abandonar Terra" label_selected="Abandonar Terra" name="button abandon land"/>
</panel>
- <string name="status_rotate">
+ <floater.string name="status_rotate">
Arrastar as bandas coloridas para girar o objeto
- </string>
- <string name="status_scale">
+ </floater.string>
+ <floater.string name="status_scale">
Clicar e arrastar para esticar o lado selecionado
- </string>
- <string name="status_move">
+ </floater.string>
+ <floater.string name="status_move">
Arrastar para mover, Shift-arrastar para copiar
- </string>
- <string name="status_modifyland">
+ </floater.string>
+ <floater.string name="status_modifyland">
Clicar e reter para modificar a terra
- </string>
- <string name="status_camera">
+ </floater.string>
+ <floater.string name="status_camera">
Clicar e arrastar para mudar a vista
- </string>
- <string name="status_grab">
+ </floater.string>
+ <floater.string name="status_grab">
Arrastar para mover, Ctrl para levantar, Ctrl-Shift para rotacionar
- </string>
- <string name="status_place">
+ </floater.string>
+ <floater.string name="status_place">
Clique no mundo para construir
- </string>
- <string name="status_selectland">
+ </floater.string>
+ <floater.string name="status_selectland">
Clicar e arrastar para selecionar a terra
- </string>
- <string name="grid_screen_text">
+ </floater.string>
+ <floater.string name="grid_screen_text">
Tela
- </string>
- <string name="grid_local_text">
+ </floater.string>
+ <floater.string name="grid_local_text">
Local
- </string>
- <string name="grid_world_text">
+ </floater.string>
+ <floater.string name="grid_world_text">
Mundo
- </string>
- <string name="grid_reference_text">
+ </floater.string>
+ <floater.string name="grid_reference_text">
Referência
- </string>
- <string name="grid_attachment_text">
+ </floater.string>
+ <floater.string name="grid_attachment_text">
Anexo
- </string>
+ </floater.string>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_top_objects.xml b/indra/newview/skins/default/xui/pt/floater_top_objects.xml
index 694100297d..15e69c450c 100644
--- a/indra/newview/skins/default/xui/pt/floater_top_objects.xml
+++ b/indra/newview/skins/default/xui/pt/floater_top_objects.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="top_objects" title="Carregando...">
+<floater name="top_objects" title="CARREGANDO...">
<text name="title_text">
Carregando...
</text>
@@ -19,14 +19,17 @@
Nome do Objeto:
</text>
<button label="Filtro" name="filter_object_btn"/>
- <text name="owner_name_text">
+ <text name="owner_name_text" width="130">
Nome do Proprietário:
</text>
+ <line_editor font="SansSerifSmall" left="140" name="id_editor" width="280"/>
+ <line_editor font="SansSerifSmall" left="140" name="object_name_editor" width="280"/>
+ <line_editor font="SansSerifSmall" left="140" name="owner_name_editor" width="280"/>
<button label="Filtro" name="filter_owner_btn"/>
- <button label="Retornar Selecionado" name="return_selected_btn"/>
- <button label="Retornar Tudo" name="return_all_btn"/>
- <button label="Desabilitar Selecionado" name="disable_selected_btn"/>
- <button label="Desabilitar Tudo" name="disable_all_btn"/>
+ <button label="Retornar Selecionado" name="return_selected_btn" width="170"/>
+ <button label="Retornar Tudo" name="return_all_btn" left="190"/>
+ <button label="Desabilitar Selecionado" name="disable_selected_btn" width="170"/>
+ <button label="Desabilitar Tudo" name="disable_all_btn" left="190"/>
<button label="Atualizar" name="refresh_btn"/>
<string name="top_scripts_title">
Principais Scripts
diff --git a/indra/newview/skins/default/xui/pt/floater_tos.xml b/indra/newview/skins/default/xui/pt/floater_tos.xml
index 5da34d2de7..7a0c187517 100644
--- a/indra/newview/skins/default/xui/pt/floater_tos.xml
+++ b/indra/newview/skins/default/xui/pt/floater_tos.xml
@@ -4,7 +4,8 @@
<button label="Cancelar" label_selected="Cancelar" name="Cancel"/>
<check_box label="Eu concordo com os Termos do Serviço" name="agree_chk"/>
<text name="tos_heading">
- Por favor, leia os seguintes Termos de Serviço cuidadosamente. Para continuar acessando o Second Life, você precisa aceitar o acordo.
+ Por favor, leia os seguintes Termos de Serviço cuidadosamente. Para continuar acessando o
+[SECOND_LIFE], você precisa aceitar o acordo.
</text>
<text_editor name="tos_text">
TOS_TEXT
diff --git a/indra/newview/skins/default/xui/pt/floater_url_entry.xml b/indra/newview/skins/default/xui/pt/floater_url_entry.xml
index a4ae5e2e3d..48af8de363 100644
--- a/indra/newview/skins/default/xui/pt/floater_url_entry.xml
+++ b/indra/newview/skins/default/xui/pt/floater_url_entry.xml
@@ -3,6 +3,7 @@
<text name="media_label">
URL da Mídia:
</text>
+ <combo_box left="100" name="media_entry" width="360" />
<button label="OK" name="ok_btn"/>
<button label="Cancelar" name="cancel_btn"/>
<button label="Limpar" name="clear_btn"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_water.xml b/indra/newview/skins/default/xui/pt/floater_water.xml
index 007eb3f6ba..bad9aa0943 100644
--- a/indra/newview/skins/default/xui/pt/floater_water.xml
+++ b/indra/newview/skins/default/xui/pt/floater_water.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Water Floater" title="Editor de Ãgua Avançado">
- <text name="KeyFramePresetsText">
+<floater name="Water Floater" title="EDITOR DE ÃGUA AVANÇADO">
+ <text name="KeyFramePresetsText" width="154">
Pré-configurações da Ãgua:
</text>
+ <combo_box left_delta="160" name="WaterPresetsCombo" width="150" />
<button label="Novo" label_selected="Novo" name="WaterNewPreset"/>
<button label="Salvar" label_selected="Salvar" name="WaterSavePreset"/>
<button label="Deletar" label_selected="Deletar" name="WaterDeletePreset"/>
@@ -16,15 +17,15 @@
<text name="WaterFogDensText">
Expoente da Densidade de névoa
</text>
- <button label="?" name="WaterFogDensityHelp"/>
+ <button label="?" name="WaterFogDensityHelp" left="209"/>
<text name="WaterUnderWaterFogModText">
Modificador da névoa Subaquática
</text>
- <button label="?" name="WaterUnderWaterFogModHelp"/>
+ <button label="?" name="WaterUnderWaterFogModHelp" left="209"/>
<text name="BDensText">
Escala da Marola de Reflexão
</text>
- <button label="?" name="WaterNormalScaleHelp"/>
+ <button label="?" name="WaterNormalScaleHelp" left="415"/>
<text name="BHText2">
1
</text>
@@ -37,29 +38,29 @@
<text name="HDText">
Escala de Fresnel
</text>
- <button label="?" name="WaterFresnelScaleHelp"/>
+ <button label="?" name="WaterFresnelScaleHelp" left="415"/>
<text name="FresnelOffsetText">
Deslocamento de Fresnel
</text>
- <button label="?" name="WaterFresnelOffsetHelp"/>
+ <button label="?" name="WaterFresnelOffsetHelp" left="415"/>
<text name="DensMultText">
Refratar a Escala para Cima
</text>
- <button label="?" name="WaterScaleAboveHelp"/>
+ <button label="?" name="WaterScaleAboveHelp" left="640"/>
<text name="WaterScaleBelowText">
Refratar a Escala para Baixo
</text>
- <button label="?" name="WaterScaleBelowHelp"/>
+ <button label="?" name="WaterScaleBelowHelp" left="640"/>
<text name="MaxAltText">
Multiplicador de Difusão
</text>
- <button label="?" name="WaterBlurMultiplierHelp"/>
+ <button label="?" name="WaterBlurMultiplierHelp" left="640"/>
</panel>
<panel label="Imagem" name="Waves">
<text name="BHText">
Direção da Onda Maior
</text>
- <button label="?" name="WaterWave1Help"/>
+ <button label="?" name="WaterWave1Help" left="170"/>
<text name="WaterWave1DirXText">
X
</text>
@@ -69,7 +70,7 @@
<text name="BHText2">
Direção da Onda Pequena
</text>
- <button label="?" name="WaterWave2Help"/>
+ <button label="?" name="WaterWave2Help" left="170"/>
<text name="WaterWave2DirXText">
X
</text>
diff --git a/indra/newview/skins/default/xui/pt/floater_wearable_save_as.xml b/indra/newview/skins/default/xui/pt/floater_wearable_save_as.xml
index 3f08b4b992..2b2c669a18 100644
--- a/indra/newview/skins/default/xui/pt/floater_wearable_save_as.xml
+++ b/indra/newview/skins/default/xui/pt/floater_wearable_save_as.xml
@@ -2,7 +2,7 @@
<floater name="modal container" title=" ">
<button label="Salvar" label_selected="Salvar" name="Save"/>
<button label="Cancelar" label_selected="Cancelar" name="Cancel"/>
- <text length="1" name="Save item as:" type="string">
+ <text name="Save item as:">
Salvar item como:
</text>
<line_editor name="name ed">
diff --git a/indra/newview/skins/default/xui/pt/floater_windlight_options.xml b/indra/newview/skins/default/xui/pt/floater_windlight_options.xml
index f86775c770..951e37a1a6 100644
--- a/indra/newview/skins/default/xui/pt/floater_windlight_options.xml
+++ b/indra/newview/skins/default/xui/pt/floater_windlight_options.xml
@@ -1,12 +1,13 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="WindLight floater" title="Editor de Céu Avançado">
- <text name="KeyFramePresetsText">
+<floater name="WindLight floater" title="EDITOR DE CÉU AVANÇADO">
+ <text name="KeyFramePresetsText" width="130">
Pré-definições de Céu:
</text>
+ <combo_box left_delta="130" name="WLPresetsCombo"/>
<button label="Novo" label_selected="Novo" name="WLNewPreset"/>
- <button label="Salvar" label_selected="Salvar" name="WLSavePreset"/>
- <button label="Deletar" label_selected="Deletar" name="WLDeletePreset"/>
- <button label="Editor de Ciclos do Dia" label_selected="Editor de Ciclos do Dia" name="WLDayCycleMenuButton" width="150" left_delta="95" />
+ <button label="Salvar" label_selected="Salvar" name="WLSavePreset" left_delta="72"/>
+ <button label="Deletar" label_selected="Deletar" name="WLDeletePreset" left_delta="72"/>
+ <button label="Editor de Ciclos do Dia" label_selected="Editor de Ciclos do Dia" name="WLDayCycleMenuButton" width="150" left_delta="84" />
<tab_container name="WindLight Tabs">
<panel label="Atmosfera" name="Atmosphere">
<text name="BHText">
@@ -52,15 +53,15 @@
<text name="DensMultText">
Multiplicador de Densidade
</text>
- <button label="?" name="WLDensityMultHelp"/>
+ <button label="?" name="WLDensityMultHelp" left="635"/>
<text name="WLDistanceMultText">
Multiplicador de Distância
</text>
- <button label="?" name="WLDistanceMultHelp"/>
+ <button label="?" name="WLDistanceMultHelp" left="635"/>
<text name="MaxAltText">
Altitude Máxima
</text>
- <button label="?" name="WLMaxAltitudeHelp"/>
+ <button label="?" name="WLMaxAltitudeHelp" left="635"/>
</panel>
<panel label="Iluminação" name="Lighting">
<text name="SLCText">
@@ -156,10 +157,10 @@
Escala da Nuvem
</text>
<button label="?" name="WLCloudScaleHelp"/>
- <text name="WLCloudDetailText">
- Detalhe da Nuvem (XY/Densidade)
+ <text name="WLCloudDetailText" font="SansSerifSmall">
+ Detalhe da Nuvem (XY/Densidade)
</text>
- <button label="?" name="WLCloudDetailHelp"/>
+ <button label="?" name="WLCloudDetailHelp" left="421"/>
<text name="BHText8">
X
</text>
@@ -180,7 +181,7 @@
<button label="?" name="WLCloudScrollYHelp"/>
<check_box label="Travar" name="WLCloudLockY"/>
<check_box label="Desenhar Nuvens Clássicas" name="DrawClassicClouds"/>
- <button label="?" name="WLClassicCloudsHelp"/>
+ <button label="?" name="WLClassicCloudsHelp" left="645"/>
</panel>
</tab_container>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_world_map.xml b/indra/newview/skins/default/xui/pt/floater_world_map.xml
index 66279e82d3..034602d6ea 100644
--- a/indra/newview/skins/default/xui/pt/floater_world_map.xml
+++ b/indra/newview/skins/default/xui/pt/floater_world_map.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="worldmap" title="Mapa Mundi">
+<floater name="worldmap" title="MAPA MUNDI">
<tab_container name="maptab">
<panel label="Objetos" name="objects_mapview"/>
<panel label="Terreno" name="terrain_mapview"/>
@@ -28,14 +28,10 @@
<check_box label="Mature" name="event_mature_chk"/>
<check_box label="Adult" name="event_adult_chk"/>
<combo_box label="Amigos Conectados" name="friend combo" tool_tip="Amigos para mostrar no Mapa">
- <combo_item name="none_selected">
- Amigos Conectados
- </combo_item>
+ <combo_box.item name="item1" label="Amigos Conectados" />
</combo_box>
<combo_box label="Landmarks" name="landmark combo" tool_tip="Landmark para mostrar no Mapa">
- <combo_item name="none_selected">
- Landmarks
- </combo_item>
+ <combo_box.item name="item1" label="Landmarks" />
</combo_box>
<line_editor label="Procurar por nome de região" name="location" tool_tip="Digite o nome de uma Região"/>
<button label="Procurar" name="DoSearch" tool_tip="Procurar por região"/>
@@ -52,6 +48,6 @@
<button font="SansSerifSmall" left_delta="91" width="135" label="Mostrar destino" label_selected="Mostrar Destino" name="Show Destination" tool_tip="Centralizar mapa na posição selecionada"/>
<button font="SansSerifSmall" label="Limpar" label_selected="Limpar" name="Clear" tool_tip="Parar de percorrer"/>
<button font="SansSerifSmall" left_delta="91" width="135" label="Mostra minha localização" label_selected="Mostra minha localização" name="Show My Location" tool_tip="Centraliza o mapa na posição do seu Avatar"/>
- <button font="SansSerifSmall" label="Copiar SLURL para área de transferência" name="copy_slurl" tool_tip="Copia a posição atual como SLURL para ser usada na Web"/>
+ <button font="SansSerifSmall" label="Copiar SLurl para área de transferência" name="copy_slurl" tool_tip="Copia a posição atual como SLurl para ser usada na Web"/>
<slider label="Zoom" name="zoom slider"/>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/language_settings.xml b/indra/newview/skins/default/xui/pt/language_settings.xml
new file mode 100644
index 0000000000..71418d446a
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/language_settings.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- This file contains strings that used to be hardcoded in the source.-->
+<strings>
+
+ <!-- Locale Information -->
+ <string name="MicrosoftLocale">english</string>
+ <string name="DarwinLocale">C</string>
+ <string name="LinuxLocale">C</string>
+
+ <!--
+ datetimeToCodes["wkday"] = "%a"; // Thu
+ datetimeToCodes["weekday"] = "%A"; // Thursday
+ datetimeToCodes["year4"] = "%Y"; // 2009
+ datetimeToCodes["year"] = "%Y"; // 2009
+ datetimeToCodes["year2"] = "%y"; // 09
+ datetimeToCodes["mth"] = "%b"; // Aug
+ datetimeToCodes["month"] = "%B"; // August
+ datetimeToCodes["mthnum"] = "%m"; // 08
+ datetimeToCodes["day"] = "%d"; // 31
+ datetimeToCodes["hour24"] = "%H"; // 14
+ datetimeToCodes["hour"] = "%H"; // 14
+ datetimeToCodes["hour12"] = "%I"; // 02
+ datetimeToCodes["min"] = "%M"; // 59
+ datetimeToCodes["ampm"] = "%p"; // AM
+ datetimeToCodes["second"] = "%S"; // 59
+ datetimeToCodes["timezone"] = "%Z"; // PST
+ -->
+
+ <string name="TimeHour">hour,datetime,slt</string>
+ <string name="TimeMin">min,datetime,slt</string>
+ <string name="TimeYear">year,datetime,slt</string>
+ <string name="TimeDay">day,datetime,slt</string>
+ <string name="TimeMonth">mthnum,datetime,slt</string>
+ <string name="TimeWeek">wkday,datetime,slt</string>
+ <string name="TimeAMPM">ampm,datetime,slt</string>
+ <string name="TimeHour12">hour12,datetime,slt</string>
+
+ <string name="LTimeMthNum">mthnum,datetime,local</string>
+ <string name="LTimeWeek">wkday,datetime,local</string>
+ <string name="LTimeMonth">mth,datetime,local</string>
+ <string name="LTimeDay">day,datetime,local</string>
+ <string name="LTimeSec">second,datetime,local</string>
+ <string name="LTimeHour">hour,datetime,local</string>
+ <string name="LTimeMin">min,datetime,local</string>
+ <string name="LTimeYear">year,datetime,local</string>
+
+ <string name="UTCTimeWeek">weekday,datetime,utc</string>
+ <string name="UTCTimeDay">day,datetime,utc</string>
+ <string name="UTCTimeMth">mth,datetime,utc</string>
+ <string name="UTCTimeYr">year,datetime,utc</string>
+ <string name="UTCTimeHr">hour,datetime,utc</string>
+ <string name="UTCTimeMin">min,datetime,utc</string>
+ <string name="UTCTimeSec">second,datetime,utc</string>
+ <string name="UTCTimeTimezone">timezone,datetime,utc</string>
+</strings>
diff --git a/indra/newview/skins/default/xui/pt/menu_login.xml b/indra/newview/skins/default/xui/pt/menu_login.xml
index f60946fcce..7ec324cb3f 100644
--- a/indra/newview/skins/default/xui/pt/menu_login.xml
+++ b/indra/newview/skins/default/xui/pt/menu_login.xml
@@ -7,7 +7,7 @@
<menu_item_call label="Preferências..." name="Preferences..."/>
</menu>
<menu label="Ajuda" name="Help">
- <menu_item_call label="Ajuda do Second Life" name="Second Life Help"/>
- <menu_item_call label="Sobre o Second Life..." name="About Second Life..."/>
+ <menu_item_call label="Ajuda do [SECOND_LIFE]" name="Second Life Help"/>
+ <menu_item_call label="Sobre o [APP_NAME]..." name="About Second Life..."/>
</menu>
</menu_bar>
diff --git a/indra/newview/skins/default/xui/pt/menu_viewer.xml b/indra/newview/skins/default/xui/pt/menu_viewer.xml
index 08ccdc043f..2c887fa50c 100644
--- a/indra/newview/skins/default/xui/pt/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/pt/menu_viewer.xml
@@ -1,5 +1,11 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<menu_bar name="Main Menu">
+ <menu name="Me">
+ <menu_item_call label="Preferências" name="Preferences"/>
+ <menu_item_call name="Manage My Account">
+ <menu_item_call.on_click name="ManageMyAccount_url" parameter="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=pt" />
+ </menu_item_call>
+ </menu>
<menu label="Arquivo" name="File">
<tearoff_menu label="~~~~~~~~~~~" name="~~~~~~~~~~~"/>
<menu label="Upload" name="upload">
@@ -119,8 +125,12 @@
<menu_item_call label="Parar Animação do Meu Avatar" name="Stop Animating My Avatar"/>
<menu_item_call label="Liberar teclas" name="Release Keys"/>
<menu_item_separator label="-----------" name="separator4"/>
- <menu_item_call label="Histórico de conta..." name="Account History..."/>
- <menu_item_call label="Gerenciar minha conta..." name="Manage My Account..."/>
+ <menu_item_call label="Histórico de conta..." name="Account History...">
+ <on_click name="AccountHistory_url" userdata="WebLaunchAccountHistory,http://secondlife.com/account/transactions.php?lang=pt"/>
+ </menu_item_call>
+ <menu_item_call label="Gerenciar minha conta..." name="Manage My Account...">
+ <on_click name="ManageMyAccount_url" userdata="WebLaunchJoinNow,http://secondlife.com/account/index.php?lang=pt"/>
+ </menu_item_call>
<menu_item_call label="Comprar L$..." name="Buy and Sell L$..."/>
<menu_item_separator label="-----------" name="separator5"/>
<menu_item_call label="Meu terreno..." name="My Land..."/>
@@ -165,7 +175,9 @@
<menu_item_separator label="-----------" name="separator4"/>
<menu_item_call label="Foco na seleção" name="Focus on Selection"/>
<menu_item_call label="Zoom na Seleção" name="Zoom to Selection"/>
- <menu_item_call label="Comprar objetos" name="Menu Object Take"/>
+ <menu_item_call label="Comprar el objeto" name="Menu Object Take">
+ <on_enable userdata="Comprar,Pegar" name="EnableBuyOrTake"/>
+ </menu_item_call>
<menu_item_call label="Pegar cópia" name="Take Copy"/>
<menu_item_call label="Salvar objeto de volta aos conteúdos do objeto" name="Save Object Back to Object Contents"/>
<menu_item_separator label="-----------" name="separator6"/>
@@ -179,7 +191,7 @@
<menu_item_call label="Ajustar scripts para não rodar na seleção" name="Set Scripts to Not Running in Selection"/>
</menu>
<menu label="Ajuda" name="Help">
- <menu_item_call label="Ajuda Second Life" name="Second Life Help"/>
+ <menu_item_call label="Ajuda [SECOND_LIFE]" name="Second Life Help"/>
<menu_item_call label="Tutorial" name="Tutorial"/>
<menu_item_separator label="-----------" name="separator"/>
<menu_item_call label="Blog oficial da Linden..." name="Official Linden Blog..."/>
@@ -200,6 +212,6 @@
<menu_item_separator label="-----------" name="separator9"/>
<menu_item_call label="Reportar Bug..." name="Report Bug..."/>
</menu>
- <menu_item_call label="Sobre Second Life..." name="About Second Life..."/>
+ <menu_item_call label="Sobre [APP_NAME]..." name="About Second Life..."/>
</menu>
</menu_bar>
diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml
index a88ab65c7a..c3ce53861f 100644
--- a/indra/newview/skins/default/xui/pt/notifications.xml
+++ b/indra/newview/skins/default/xui/pt/notifications.xml
@@ -6,6 +6,9 @@
<global name="alwayschoose">
Sempre escolher esta opção
</global>
+ <global name="implicitclosebutton">
+ Fechar
+ </global>
<template name="okbutton">
<form>
<button
@@ -71,7 +74,7 @@
</form>
</template>
<notification functor="GenericAcknowledge" label="Mensagem de Alerta Desconhecida" name="MissingAlert">
- Sua versão do Second Life não sabe como mostrar a mensagem de alerta que acabou de receber.
+ Sua versão do [APP_NAME] não sabe como mostrar a mensagem de alerta que acabou de receber.
Detalhes do erro: O alerta chamado &apos;[_NAME]&apos; não foi encontrado em notifications.xml.
<usetemplate name="okbutton" yestext="OK"/>
@@ -93,7 +96,7 @@ Detalhes do erro: O alerta chamado &apos;[_NAME]&apos; não foi encontrado em no
<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Sim"/>
</notification>
<notification name="BadInstallation">
- Ocorreu um erro atualizando o Second Life. Por favor, faça o download da última versão em secondlife.com.
+ Ocorreu um erro atualizando o [APP_NAME]. Por favor, faça o download da última versão em secondlife.com.
<usetemplate
name="okbutton"
yestext="OK"/>
@@ -174,7 +177,7 @@ Você deseja permitir que os residentes selecionados tenham direito de edição?
Membros não podem ser removidos dessa função.
Os membros podem, eles próprios, recusar a função.
Deseja continuar?
- <usetemplate ignoretext="Quando adcionar membro ao grupo como dono" name="okcancelignore" notext="Não" yestext="Sim"/>
+ <usetemplate ignoretext="Quando adicionar membro ao grupo como dono" name="okcancelignore" notext="Não" yestext="Sim"/>
</notification>
<notification name="AssignDangerousActionWarning">
Você está prestes a adicionar a habilidade &apos;[ACTION_NAME]&apos; para a função &apos;[ROLE_NAME]&apos;
@@ -232,7 +235,7 @@ Clicando neste Box, será mostrado:
<notification name="ClickPartnerHelpAvatar">
Você pode propor a outro Residente ou dissolver uma parceria existente através do website [SECOND_LIFE].
-Ir para o site do Second Life para mais informações sobre parceria?
+Ir para o site do [SECOND_LIFE] para mais informações sobre parceria?
<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Ir para a Página"/>
</notification>
<notification name="ClickUploadHelpPermissions">
@@ -270,7 +273,7 @@ Seu preço de venda será L$[SALE_PRICE] e está autorizado para venda para [NA
<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Continuar"/>
</notification>
<notification name="ConfirmLandSaleToAnyoneChange">
- ATENÇÃO: Ao clicar em &apos;vender para qualquer um&apos; torna a sua terra disponível para toda a comunidade Second Life, mesmo aqueles que não estão nesta região.
+ ATENÇÃO: Ao clicar em &apos;vender para qualquer um&apos; torna a sua terra disponível para toda a comunidade [SECOND_LIFE], mesmo aqueles que não estão nesta região.
A área de [LAND_SIZE] m² de terra selecionada está posta para venda.
Seu preço de venda será L$ [SALE_PRICE] e está autorizado para [NAME].
@@ -374,10 +377,13 @@ Scripts devem ser permitidos para fazer as armas funcionarem.
Você precisa entrar com ambos os Nome e Sobrenome do seu avatar.
Você precisa de uma conta para entrar no [SECOND_LIFE]. Você gostaria de criar uma conta agora?
+ <url name="url">
+ https://join.secondlife.com/index.php?lang=pt-BR
+ </url>
<usetemplate name="okcancelbuttons" notext="Tentar novamente" yestext="Criar uma nova conta"/>
</notification>
<notification name="AddClassified">
- Anúncios classificados aparecem na seção &apos;Classificados&apos; do diretório de Busca e no www.secondlife.com por uma semana.
+ Anúncios classificados aparecem na seção &apos;Classificados&apos; do diretório de Busca e no [http://secondlife.com/community/classifieds/?lang=pt-BR secondlife.com] por uma semana.
Preencha seu anúncio e então clique &apos;Publicar...&apos; para adicioná-lo ao diretório.
Será solicitado a você um preço a ser pago, quando você clicar Publicar.
Pagando mais, faz com que seu anúncio apareça em posição mais alta na lista e também em posição mais alta, quando as pessoas buscarem por palavras-chave.
@@ -398,6 +404,9 @@ Não há reembolso por taxas já pagas.
</notification>
<notification name="PromptGoToEventsPage">
Ir até a página web de enventos [SECOND_LIFE] ?
+ <url name="url">
+ http://secondlife.com/events/?lang=pt-BR
+ </url>
<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Ir à página"/>
</notification>
<notification name="SelectProposalToView">
@@ -415,17 +424,17 @@ Não há reembolso por taxas já pagas.
<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/>
</notification>
<notification name="CacheWillClear">
- O cache será limpo quando você reiniciar [SECOND_LIFE].
+ O cache será limpo quando você reiniciar [APP_NAME].
</notification>
<notification name="CacheWillBeMoved">
- O Cache será removido após reiniciar [SECOND_LIFE].
+ O Cache será removido após reiniciar [APP_NAME].
Nota: Isto limpará o cache.
</notification>
<notification name="ChangeConnectionPort">
- Configuração de porta terá efeito após reiniciar [SECOND_LIFE].
+ Configuração de porta terá efeito após reiniciar [APP_NAME].
</notification>
<notification name="ChangeSkin">
- A nova pele será exibida após reiniciar [SECOND_LIFE].
+ A nova pele será exibida após reiniciar [APP_NAME].
</notification>
<notification name="GoToAuctionPage">
Ir para a página do [SECOND_LIFE] para ver os detalhes do leilão ou fazer um lance?
@@ -484,25 +493,25 @@ O objeto pode estar fora de alcance ou ter sido deletado.
Não foi possível escrever o arquivo [[FILE]]
</notification>
<notification name="UnsupportedHardware">
- Aviso: Seu sistema não é compatível com os requisitos mínimos exigidos pelo Second Life. Se você continuar usando o Second Life pode experimentar uma performance ruim. Infelizmente não podemos oferecer suporte técnico para configurações de sistema não suportado.
+ Aviso: Seu sistema não é compatível com os requisitos mínimos exigidos pelo [APP_NAME]. Se você continuar usando o [APP_NAME] pode experimentar uma performance ruim. Infelizmente não podemos oferecer suporte técnico para configurações de sistema não suportado.
MINSPECS
Você deseja visitar [_URL] para maiores informações?
<url name="url" option="0">
- http://www.secondlife.com/corporate/sysreqs.php
+ http://secondlife.com/support/sysreqs.php?lang=pt
</url>
<usetemplate ignoretext="Ao detectar hardware não suportado" name="okcancelignore" notext="Não" yestext="Sim"/>
</notification>
<notification name="UnknownGPU">
Seu sistema possui uma placa gráfica que nos é desconhecido neste momento.
-Este é normalmente o caso de um novo hardware que nós não tivemos a chance de testar. Second Life vai muito provavelmente executar corretamente, mas talvez seja necessário ajustar suas configurações de gráficos para algo mais apropriado.
+Este é normalmente o caso de um novo hardware que nós não tivemos a chance de testar. [APP_NAME] vai muito provavelmente executar corretamente, mas talvez seja necessário ajustar suas configurações de gráficos para algo mais apropriado.
(Menu Editar &gt; Preferências &gt; Gráficos).
<form name="form">
<ignore name="ignore" text="Ao detectar uma placa de vídeo desconhecida"/>
</form>
</notification>
<notification name="DisplaySettingsNoShaders">
- [SECOND_LIFE] travou quando inicializava os drivers gráficos.
+ [APP_NAME] travou quando inicializava os drivers gráficos.
A Qualidade Gráfica será ajustada para baixa, para evitar alguns erros comuns de drivers.
Isto irá desabilitar alguns atributos gráficos.
Nós recomendamos a atualização dos drivers de sua placa gráfica.
@@ -567,7 +576,10 @@ Por favor, mova todos os objetos a serem adquiridos para uma mesma região.
<notification name="PromptGoToCurrencyPage">
[EXTRA]
-Vá para [URL] para informação sobre compra de dinheiro.
+Vá para [_URL] para informação sobre compra de L$.
+ <url name="url">
+ http://secondlife.com/app/currency/?lang=pt-BR
+ </url>
<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Ir até a página"/>
</notification>
<notification name="UnableToLinkObjects">
@@ -782,7 +794,7 @@ Nenhum lote selecionado.
Não é possível achar a região em que este terreno se encontra.
</notification>
<notification name="CannotCloseFloaterBuyLand">
- Você não pode fechar a janela de Compra de Terreno até que o Second Life calcule o preço desta transação.
+ Você não pode fechar a janela de Compra de Terreno até que o [APP_NAME] calcule o preço desta transação.
</notification>
<notification name="CannotDeedLandNothingSelected">
Não é possível transferir posse do terreno:
@@ -795,7 +807,6 @@ Nenhum grupo selecionado.
<notification name="CannotDeedLandNoRegion">
Não é possível transferir posse do terreno:
Não é possível se achar a região em que este terreno se encontra.
-Por favor, use Ferramentas &gt; Reporte de Bug para reportar isto.
</notification>
<notification name="CannotDeedLandMultipleSelected">
Impossibilitado de passar a propriedade da terra:
@@ -841,8 +852,6 @@ Os lotes que você possui estão em verde.
<notification name="CannotReleaseLandRegionNotFound">
Impossibilitado de abandonar a terra:
Não consegue achar a região em que esta terra se encontra.
-
-Por favor, usar Ferramentas &gt; Reportar Bug, para reportar este erro.
</notification>
<notification name="CannotReleaseLandNoTransfer">
Não é possível abandonar terreno:
@@ -881,14 +890,10 @@ Quer dividir o terreno?
<notification name="CannotDivideLandNoRegion">
Impossibilitado de dividir a terra:
Não consegue achar a região em que esta terra se encontra.
-
-Por favor, usar Ferramentas &gt; Reportar Bug, para reportar este erro.
</notification>
<notification name="CannotJoinLandNoRegion">
Impossibilitado de unir a terra:
Não consegue achar a região em que esta terra se encontra.
-
-Por favor, usar Ferramentas &gt; Reportar Bug, para reportar este erro.
</notification>
<notification name="CannotJoinLandNothingSelected">
Não é possível unir terreno:
@@ -947,14 +952,12 @@ Grey = Pública
<notification name="CannotSaveToAssetStore">
Impossibilitado de salvar [NAME] no armazenamento central de ativos.
Isso é geralmente uma falha temporária. Por favor personalize e salve novamente a vestimenta em poucos minutos.
-
-Se o problema persistir, por favor clicar sobre &apos;Ferramentas &gt; Bug Report&apos; no menu superior e forneça detalhes sobre a configuração de sua rede.
</notification>
<notification name="YouHaveBeenLoggedOut">
Você foi deslogado do [SECOND_LIFE]:
[MESSAGE]
-Você ainda pode olhar o bate-papo e as mensagens instantâneas existentes, clicando em &apos;Exibir IM &amp; bate-papo&apos;. Caso contrário, clique em &apos;Sair&apos; para sair do [SECOND_LIFE] imediatamente.
- <usetemplate name="okcancelbuttons" notext="Sair" yestext="Ver Mensagem Instantânea &amp; Bate- Papo"/>
+Você ainda pode olhar o bate-papo e as mensagens instantâneas existentes, clicando em &apos;Exibir IM &amp; bate-papo&apos;. Caso contrário, clique em &apos;Sair&apos; para sair do [APP_NAME] imediatamente.
+ <usetemplate name="okcancelbuttons" notext="Sair" yestext="Exibir IM &amp; bate-papo"/>
</notification>
<notification name="OnlyOfficerCanBuyLand">
Não é possível comprar o terreno para o grupo:
@@ -971,7 +974,7 @@ Oferecer amizade para [NAME]?
Oferecer amizade para [NAME]?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Quer ser meu amigo?
</input>
<button name="Offer" text="Oferecer"/>
@@ -1100,7 +1103,7 @@ Transferir propriedade destes [AREA] m² de terreno para o grupo &apos;[GROUP_NA
Configurações de display foram ajustadas para níveis de segurança porque você especificou -- opção de segurança.
</notification>
<notification name="DisplaySetToRecommended">
- Configurações de display foram ajustadas para nível recomendado basedo na configuração do seu sistema.
+ Configurações de display foram ajustadas para nível recomendado baseado na configuração do seu sistema.
</notification>
<notification name="ErrorMessage">
[ERROR_MESSAGE]
@@ -1118,16 +1121,19 @@ Você pode usar o [SECOND_LIFE] normalmente e os outros o visualizarão corretam
</form>
</notification>
<notification name="FirstRun">
- A instalação do [SECOND_LIFE] está completa.
+ A instalação do [APP_NAME] está completa.
Se esta é a primeira vez usando o[SECOND_LIFE], será necessário que você crie uma conta antes de poder se logar.
-Retornar a www.secondlife.com para criar uma nova conta?
+Retornar a [https://join.secondlife.com/index.php?lang=pt-BR secondlife.com] para criar uma nova conta?
<usetemplate name="okcancelbuttons" notext="Continuar" yestext="Nova conta.."/>
</notification>
<notification name="LoginPacketNeverReceived">
- Estamos com problemas de conexão. Pode ser problema com a conexão de sua internet ou com os servidores do Second Life.
+ Estamos com problemas de conexão. Pode ser problema com a conexão de sua internet ou com os servidores do [SECOND_LIFE].
Voce tanto pode checar a conexão de sua internet e tentar novamente em alguns minutos, ou clicar em Teletransporte para tentar teletransportar-se para sua casa.
+ <url name="url">
+ http://br.secondlife.com/support/
+ </url>
<form name="form">
<button name="OK" text="OK"/>
<button name="Help" text="Ajuda"/>
@@ -1138,7 +1144,7 @@ Voce tanto pode checar a conexão de sua internet e tentar novamente em alguns m
Seu personagem irá aparecer num momento.
Use as teclas de seta para andar.
-Pressione a tecla F1 para ajuda ou aprender mais sobre [SECOND_LIFE].
+Pressione a tecla F1 para ajuda ou aprender mais sobre [SECOND_LIFE].
Por favor, escolha se o seu avatar é feminino ou masculino. Você pode mudar de idéia depois.
<usetemplate name="okcancelbuttons" notext="Feminino" yestext="Masculino"/>
</notification>
@@ -1226,33 +1232,33 @@ Por favor, ponha o objeto à venda e tente novamente.
[DOWNLOAD_PATH]
</notification>
<notification name="DownloadWindowsMandatory">
- Uma nova versão do [SECOND_LIFE] está disponível.
+ Uma nova versão do [APP_NAME] está disponível.
[MESSAGE]
-Você deve baixar essa atualização para utilizar o [SECOND_LIFE].
+Você deve baixar essa atualização para utilizar o [APP_NAME].
<usetemplate name="okcancelbuttons" notext="Sair" yestext="Atualizar"/>
</notification>
<notification name="DownloadWindows">
- Uma versão atualizada do [SECOND_LIFE] está disponível.
+ Uma versão atualizada do [APP_NAME] está disponível.
[MESSAGE]
Essa atualização não é mandatória, mas sugerimos que você a instale para melhorar a performance e a estabilidade.
<usetemplate name="okcancelbuttons" notext="Continuar" yestext="Atualizar"/>
</notification>
<notification name="DownloadWindowsReleaseForDownload">
- Uma versão atualizada do [SECOND_LIFE] está disponível.
+ Uma versão atualizada do [APP_NAME] está disponível.
[MESSAGE]
Essa atualização não é mandatória, mas sugerimos que você a instale para melhorar a performance e a estabilidade.
<usetemplate name="okcancelbuttons" notext="Continuar" yestext="Atualizar"/>
</notification>
<notification name="DownloadMacMandatory">
- Uma nova versão do [SECOND_LIFE] está disponível.
+ Uma nova versão do [APP_NAME] está disponível.
[MESSAGE]
-Você deve baixar esta atualização para utilizar o [SECOND_LIFE].
+Você deve baixar esta atualização para utilizar o [APP_NAME].
Baixar para sua pasta de Aplicativos?
<usetemplate name="okcancelbuttons" notext="Sair" yestext="Atualizar"/>
</notification>
<notification name="DownloadMac">
- Uma nova versão do [SECOND_LIFE] está disponível.
+ Uma nova versão do [APP_NAME] está disponível.
[MESSAGE]
Essa atualização não é mandatória, mas sugerimos que você a instale para melhorar a performance e a estabilidade.
@@ -1260,7 +1266,7 @@ Baixar para a sua pasta de Aplicativos?
<usetemplate name="okcancelbuttons" notext="Continuar" yestext="Atualizar"/>
</notification>
<notification name="DownloadMacReleaseForDownload">
- Uma nova versão do [SECOND_LIFE] está disponível.
+ Uma nova versão do [APP_NAME] está disponível.
[MESSAGE]
Essa atualização não é mandatória, mas sugerimos que você a instale para melhorar a performance e a estabilidade.
@@ -1281,10 +1287,6 @@ Baixar para sua pasta de Aplicativos?
Ir ao www.secondlife.com para gerenciar sua conta?
<usetemplate ignoretext="Ao abrir o navegador web para gerenciar sua conta" name="okcancelignore" notext="Cancelar" yestext="OK"/>
</notification>
- <notification name="WebLaunchBugReport101">
- Visite a Wiki [SECOND_LIFE] para aprender como reportar bugs corretamente.
- <usetemplate ignoretext="Ao abrir o web browser para visualizar o report de Bug 101 na Wiki" name="okcancelignore" notext="Cancelar" yestext="OK"/>
- </notification>
<notification name="WebLaunchSecurityIssues">
Visite a Wiki do [SECOND_LIFE] para detalhes de como Reportar um Problema de Segurança.
<usetemplate ignoretext="Ao abrir o navegador da web para visualizar a Wiki de Problemas de Segurança" name="okcancelignore" notext="Cancelar" yestext="OK"/>
@@ -1365,7 +1367,7 @@ Bate-papo e mensagens instantâneas serão escondidas. Mensagens instantâneas i
<notification name="KickUser">
Expulsar este usuário com qual mensagem?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Um administrador desligou você.
</input>
<button name="OK" text="OK"/>
@@ -1375,7 +1377,7 @@ Bate-papo e mensagens instantâneas serão escondidas. Mensagens instantâneas i
<notification name="KickAllUsers">
Expulsar todo mundo atualmente do grid com qual mensagem?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Um administrador deslogou você.
</input>
<button name="OK" text="OK"/>
@@ -1385,7 +1387,7 @@ Bate-papo e mensagens instantâneas serão escondidas. Mensagens instantâneas i
<notification name="FreezeUser">
Paralise este usuário com qual mensagem?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Você foi congelado. Você não pode se mover ou conversar. Um administrador irá contatá-lo via mensagem instantânea (MI).
</input>
<button name="OK" text="OK"/>
@@ -1395,7 +1397,7 @@ Bate-papo e mensagens instantâneas serão escondidas. Mensagens instantâneas i
<notification name="UnFreezeUser">
Liberar este usuário com qual mensagem?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Você não está mais congelado.
</input>
<button name="OK" text="OK"/>
@@ -1405,7 +1407,7 @@ Bate-papo e mensagens instantâneas serão escondidas. Mensagens instantâneas i
<notification name="OfferTeleport">
Oferecer um teletransporte para sua localização com qual mensagem?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Junte-se a mim em [REGION]
</input>
<button name="OK" text="OK"/>
@@ -1415,7 +1417,7 @@ Bate-papo e mensagens instantâneas serão escondidas. Mensagens instantâneas i
<notification name="OfferTeleportFromGod">
God user convocou para a sua localização?
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Junte-se a mim em [REGION]
</input>
<button name="OK" text="OK"/>
@@ -1429,7 +1431,7 @@ Bate-papo e mensagens instantâneas serão escondidas. Mensagens instantâneas i
<notification label="Mensagem para todos na sua Propriedade" name="MessageEstate">
Digite um breve anúncio que será enviado para todos que estejam atualmente na sua propriedade.
<form name="form">
- <input name="message" type="text"/>
+ <input name="message"/>
<button name="OK" text="OK"/>
<button name="Cancel" text="Cancelar"/>
</form>
@@ -1502,7 +1504,7 @@ Por favor, verifique se você está com o último Visualizador instalado e vá a
Ir para o Banco de Conhecimento para maiores informações sobre Classificações de maturidade?
<url name="url">
- https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=6010
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview/pt
</url>
<usetemplate
name="okcancelignore"
@@ -1517,7 +1519,7 @@ Ir para o Banco de Conhecimento para maiores informações sobre Classificaçõe
Você não é permitido nessa região devido à sua preferência de Classificação de maturidade.
Você pode clicar em &apos;Mudar Preferência&apos; para aumentar sua preferência de Classificação de maturidade agora e permitir sua entrada. Você estará habilitado a buscar e acessar conteúdo [REGIONMATURITY] a partir de agora. Se você desejar mais tarde voltar à configuração anterior, vá para Editar &gt; Preferencias... &gt; Geral.
- <form>
+ <form name="form">
<button
name="OK"
text="Mudar Preferência"/>
@@ -1525,7 +1527,7 @@ Você pode clicar em &apos;Mudar Preferência&apos; para aumentar sua preferên
default="true"
name="Cancel"
text="Fechar"/>
- <ignore text="Quando a entrada na Região está bloqueada devido à preferência de Classificação de maturidade"/>
+ <ignore name="ignore" text="Quando a entrada na Região está bloqueada devido à preferência de Classificação de maturidade"/>
</form>
</notification>
<notification name="LandClaimAccessBlocked">
@@ -1541,7 +1543,7 @@ Por favor, verifique se você tem o último Visualizador instalado e vá para o
Ir para a o Banco de Conhecimento para maiores informações sobre Classificações de maturidade?
<url name="url">
- https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=6010
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview/pt
</url>
<usetemplate
name="okcancelignore"
@@ -1575,7 +1577,7 @@ Por favor, verifique se você tem o último Visualizador instalado e vá para o
Ir para o Banco de Conhecimento para maiores informações sobre Classificações de Maturidade?
<url name="url">
- https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=6010
+ http://wiki.secondlife.com/wiki/Linden_Lab_Official:Maturity_ratings:_an_overview/pt
</url>
<usetemplate
name="okcancelignore"
@@ -1651,7 +1653,7 @@ Publicar este classificado agora por L$ [AMOUNT]?
<notification label="Mensagem para todos desta Região" name="MessageRegion">
Digite um breve aviso que será enviado para todos nesta região.
<form name="form">
- <input name="message" type="text"/>
+ <input name="message"/>
<button name="OK" text="OK"/>
<button name="Cancel" text="Cancelar"/>
</form>
@@ -1740,10 +1742,10 @@ Se esta opção estiver marcada, compradores podem vender seus terrenos nesta re
Padrão: Desabilitada.
</notification>
<notification label="Desabilitar Scripts" name="HelpRegionDisableScripts">
- Quando a performance do simulador está ruim, um script pode ser o culpado. Abra a Barra de Estatísticas (Ctrl-Shift-1). Olhe no Simulador de Física FPS. Se estiver abaixo de 45, então abra o painel &apos;Tempo&apos; localizado na parte de baixo da Barra de Estatísticas. Se o Tempo de Script indicar 25 ms ou mais, clique no botão &apos;Get Top CScripts&apos;. Será dado o nome e a localização do script que pode estar causando uma performance ruim. Marque a caixa &apos;Desabilitar Scripts&apos; e aperte o botão &apos;Aplicar&apos;. Isto temporariamente desabilitará todos os scripts nesta região. Uma vez que você chegar ao local, investigue o script para determinar se ele está causando o problema. Você pode querer entrar em contato com o proprietário do script, excluir ou devolver o objeto. Desmarque a caixa &apos;Desabilitar Script&apos; e então clique em &apos;Aplicar&apos; para reativar os scripts na região. Padrão: desligado.
+ Quando a performance do simulador está ruim, um script pode ser o culpado. Abra a Barra de Estatísticas (Ctrl+Shift+1). Olhe no Simulador de Física FPS. Se estiver abaixo de 45, então abra o painel &apos;Tempo&apos; localizado na parte de baixo da Barra de Estatísticas. Se o Tempo de Script indicar 25 ms ou mais, clique no botão &apos;Get Top CScripts&apos;. Será dado o nome e a localização do script que pode estar causando uma performance ruim. Marque a caixa &apos;Desabilitar Scripts&apos; e aperte o botão &apos;Aplicar&apos;. Isto temporariamente desabilitará todos os scripts nesta região. Uma vez que você chegar ao local, investigue o script para determinar se ele está causando o problema. Você pode querer entrar em contato com o proprietário do script, excluir ou devolver o objeto. Desmarque a caixa &apos;Desabilitar Script&apos; e então clique em &apos;Aplicar&apos; para reativar os scripts na região. Padrão: desligado.
</notification>
<notification label="Desabilitar Colisões" name="HelpRegionDisableCollisions">
- Quando a performance do simulador é pobre, os objetos físicos podem ser os culpados.Abra a a Barra de Estatísticas (Ctrl-Shift-1).
+ Quando a performance do simulador é pobre, os objetos físicos podem ser os culpados.Abra a a Barra de Estatísticas (Ctrl+Shift+1).
Olhe a taxa de quadros por segundos (FPS) dos objetos físicos.
Se ela estiver abaixo de 45, abra o painel de Tempo, localizado na parte inferior da Barra de Estatísticas. Se o Tempo (Físicos) do Simulador mostrar 20 ms ou mais, clique o botão &apos;Pegue os Maiores Colidentes&apos;. Será fornecido a você o nome e a localidade dos objetos físicos que podem estar causando uma performance pobre.
@@ -1859,7 +1861,7 @@ Definí-lo em branco fará com que os relatórios de abuso sejam enviados apenas
Padrão: desligado
</notification>
<notification label="Discordância de Versão de Voz" name="VoiceVersionMismatch">
- Esta versão do Second Life não é compatível com as características do Canal de Voz desta região. Para que a Conversa por Voz funcione corretamente, você precisará atualizar o Second Life.
+ Esta versão do [APP_NAME] não é compatível com as características do Canal de Voz desta região. Para que a Conversa por Voz funcione corretamente, você precisará atualizar o [APP_NAME].
</notification>
<notification label="Corretor da Propriedade" name="HelpEstateCovenant">
Definir um corretor da propriedade lhe permite vender lotes nesta propriedade. Se um corretor não for definido, você não pode vender terras. O cartão do seu corretor pode ficar vazio se você não desejar aplicar quaisquer regras ou avisar os compradores sobre qualquer coisa em relação ao lote antes da compra.
@@ -1933,14 +1935,14 @@ Eles serão copiados para o seu inventário.
Você tem certeza de que deseja prosseguir com esta compra?
<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Confirmar"/>
</notification>
- <notification name="ConfirmPurchasePassword" type="password">
+ <notification name="ConfirmPurchasePassword">
Esta transação fará:
[ACTION]
Você tem certeza de que deseja prosseguir com esta compra?
Por favor, re-insira sua senha e clique &apos;Confirmar Compra&apos;.
<form name="form">
- <input name="message" type="password"/>
+ <input name="message"/>
<button name="ConfirmPurchase" text="Confirmar Compra"/>
<button name="Cancel" text="Cancelar"/>
</form>
@@ -1964,7 +1966,7 @@ Mover para o inventário o(s) item(s)?
<usetemplate ignoretext="Quando movendo objetos com scripts não copiáveis ao inventário" name="okcancelignore" notext="Não mover" yestext="Mover"/>
</notification>
<notification name="ClickActionNotPayable">
- Aviso: A ação de Pagar ao Objeto com clique foi definida, mas funcionará apenas se for adicionado um script com o evento money().
+ Aviso: A ação de &apos;Pagar Objeto&apos; com clique foi definida, mas funcionará apenas se for adicionado um script com o evento money().
<form name="form">
<ignore name="ignore" text="Quando Definindo &apos;Pagar&apos; em objetos sem eventos money()"/>
</form>
@@ -1973,22 +1975,19 @@ Mover para o inventário o(s) item(s)?
Não há itens neste objeto que você está autorizado a copiar.
</notification>
<notification name="WebLaunchAccountHistory">
- Ir para o site do Second Life para visualizar o histórico de sua conta?
+ Ir para o site do [SECOND_LIFE] para visualizar o histórico de sua conta?
<usetemplate ignoretext="Ao abrir a página web de histórico de conta" name="okcancelignore" notext="Cancelar" yestext="Ir para a página"/>
</notification>
<notification name="ClickOpenF1Help">
- Visitar o website de Suporte do Second Life?
- <usetemplate ignoretext="Quando visitando o website de Suporte do Second Life" name="okcancelignore" notext="Cancelar" yestext="Ir"/>
+ Visitar o website de Suporte do [SECOND_LIFE]?
+ <usetemplate ignoretext="Quando visitando o website de Suporte do [SECOND_LIFE]" name="okcancelignore" notext="Cancelar" yestext="Ir"/>
</notification>
<notification name="ConfirmQuit">
Tem certeza que deseja sair?
- <usetemplate ignoretext="Quando Saindo do Second Life." name="okcancelignore" notext="Continuar" yestext="Sair"/>
+ <usetemplate ignoretext="Quando Saindo do [APP_NAME]." name="okcancelignore" notext="Continuar" yestext="Sair"/>
</notification>
<notification name="HelpReportAbuseEmailLL">
- Use esta ferramenta para reportar violações aos Termos de Serviço e aos Padrões da Comunidade. Veja:
-
-http://secondlife.com/corporate/tos.php
-http://secondlife.com/corporate/cs.php
+ Use esta ferramenta para reportar violações aos [http://secondlife.com/corporate/tos.php?lang=pt-BR Termos de Serviço] e aos [http://secondlife.com/corporate/cs.php?lang=pt-BR Padrões da Comunidade].
Todos os abusos aos Termos de Serviço e aos Padrões da Comunidade reportados, são investigados e resolvidos. Você pode ver a resolução do incidente na Reportagem de Incidentes em:
@@ -2002,30 +2001,13 @@ Como um serviço aos residentes e visitantes, o dono da região em que você se
O dono da região resolverá as reportagens baseado nas regras locais desta região, como definido na Declaração da propriedade.
(Veja as declarações indo ao menu Mundo e selecionando Sobre a Terra.)
-A resolução desta reportagem se aplica apenas a esta região; o acesso de Residentes às outras áreas do Second Life não será afetado pelas decisões desta reportagem.
-Apenas a Linden Lab pode restringir acesso a todo o Second Life.
- </notification>
- <notification name="HelpReportBug">
- Use esta ferramenta para reportar *apenas* características técnicas que não atuem como descrito ou esperado.
-Por favor, forneça tantos detalhes quanto possível.
-Você pode responder ao e-mail de resposta automática para adicionar mais detalhes à sua reportagem.
-
-Todas as reportagens de bugs são investigadas e avaliadas.
-Nenhum e-mail de resposta será enviado.
-
-Se você estiver tendo uma dificuldade técnica, por favor contate o Suporte em:
-http://secondlife.com/community/support.php
-
-Nota: reportagens incompletas não serão investigadas
+A resolução desta reportagem se aplica apenas a esta região; o acesso de Residentes às outras áreas do [SECOND_LIFE] não será afetado pelas decisões desta reportagem.
+Apenas a Linden Lab pode restringir acesso a todo o [SECOND_LIFE].
</notification>
<notification name="HelpReportAbuseSelectCategory">
Por favor, selecione uma categoria para a reportagem deste abuso.
A seleção de uma categoria nos ajuda a arquivar e processar as reportagens de abuso.
</notification>
- <notification name="HelpReportBugSelectCategory">
- Por favor, selecione uma categoria para este bug.
-A seleção de uma categoria nos ajuda a arquivar e processar as reportagens de bugs.
- </notification>
<notification name="HelpReportAbuseAbuserNameEmpty">
Por favor, entre com o nome do perturbador.
Entrando com um valor preciso, nos ajuda a arquivar e processar as reportagens de abuso.
@@ -2038,27 +2020,19 @@ Entrando com um valor preciso, nos ajuda a arquivar e processar as reportagens d
Por favor, digite um resumo de como ocorreu o abuso.
Fazer um resumo detalhado nos ajuda a arquivar e processar as reportagens de abuso.
</notification>
- <notification name="HelpReportBugSummaryEmpty">
- Por favor, digite um resumo do bug. Realizar um resumo detalhado nos ajuda a arquivar e processar as reportagens de abuso.
- </notification>
<notification name="HelpReportAbuseDetailsEmpty">
Por favor, digite uma descrição detalhada do abuso que ocorreu.
Seja tão específico quanto você puder, incluindo nomes e os detalhes do incidente que está denunciando.
Fazer uma descrição precisa nos ajuda a arquivar e processar as reportagens de abuso.
</notification>
- <notification name="HelpReportBugDetailsEmpty">
- Por favor, digite uma descrição detalhada do bug.
-Seja tão específico quanto você puder, incluindo as etapas para reproduzir o bug, se possível.
-Fazer uma descrição precisa nos ajuda a arquivar e processar os relatórios de bugs.
- </notification>
<notification name="HelpReportAbuseContainsCopyright">
Caro Residente,
Você parece estar relatando violação de propriedade intelectual. Por favor, certifique-se de que está relatando corretamente:
-(1) O Processo de abuso. Você pode apresentar um relatório de abuso se você acredita que um Residente está infringindo o sistema de permissões do Second Life, por exemplo, utilizando ferramentas CopyBot para copiar ou similar, para violar os direitos de propriedade intelectual. A Equipe de Abuso investiga e divulga a ação disciplinar adequada para o comportamento que viola o Estatuto da Comunidade do Second Life ou os Termos de Serviço. No entanto, a mesma não controla e não irá responder aos pedidos para remover o conteúdo do mundo Second Life.
+(1) O Processo de abuso. Você pode apresentar um relatório de abuso se você acredita que um Residente está infringindo o sistema de permissões do [SECOND_LIFE], por exemplo, utilizando ferramentas CopyBot para copiar ou similar, para violar os direitos de propriedade intelectual. A Equipe de Abuso investiga e divulga a ação disciplinar adequada para o comportamento que viola o Estatuto da Comunidade do [SECOND_LIFE] ou os Termos de Serviço. No entanto, a mesma não controla e não irá responder aos pedidos para remover o conteúdo do mundo [SECOND_LIFE].
-(2) O processo de remoção de conteúdo ou DMCA. Para solicitar a remoção de conteúdo do Second Life, você deve enviar uma notificação válida de infração, conforme previsto em nossa Política de DMCA em http://secondlife.com/corporate/dmca.php.
+(2) O processo de remoção de conteúdo ou DMCA. Para solicitar a remoção de conteúdo do [SECOND_LIFE], você deve enviar uma notificação válida de infração, conforme previsto em nossa Política de DMCA em http://secondlife.com/corporate/dmca.php.
Se você ainda deseja prosseguir com o processo de abuso, por favor, feche esta janela e termine de enviar seu relatório. Pode ser necessário selecionar a categoria específica &apos;CopyBot Infração de Permissões&apos;.
@@ -2109,7 +2083,7 @@ Você gostaria de deixar o modo Ocupado antes de completar esta transação?
<usetemplate ignoretext="Ao esvaziar pasta Achados e Perdidos do seu inventário" name="okcancelignore" notext="Não" yestext="Sim"/>
</notification>
<notification name="CopySLURL">
- A seguinte SLURL foi copiada para o seu clipboard:
+ A seguinte SLurl foi copiada para o seu clipboard:
[SLURL]
Coloque-a em uma página web para dar aos outros um fácil acesso a este local ou tente você, colando-a na barra de endereços do seu navegador.
@@ -2118,9 +2092,9 @@ Coloque-a em uma página web para dar aos outros um fácil acesso a este local o
</form>
</notification>
<notification name="GraphicsPreferencesHelp">
- Este painel controla o tamanho da janela, resolução e a qualidade dos gráficos do computador cliente. O Preferências &gt; Interface Gráfica permite escolher entre quatro níveis gráficos: Baixo, Médio, Alto e Ultra. Você também pode personalizar suas configurações de gráficos selecionando a opção Custom e manipulando as seguintes definições:
+ Este painel controla o tamanho da janela, resolução e a qualidade dos gráficos do computador cliente. O Preferências &gt; Interface Gráfica permite escolher entre quatro níveis gráficos: Baixo, Médio, Alto e Ultra. Você também pode personalizar suas configurações de gráficos selecionando a opção Personalizar e manipulando as seguintes definições:
-Sombreamento: Ativar ou desativar vários tipos de sobreadores de pixel.
+Sombreamento: Ativar ou desativar vários tipos de sombreadores de pixel.
Detalhes de Reflexão: Define os tipos de objetos que a água pode refletir.
@@ -2180,7 +2154,7 @@ Clique &quot;Céu Avançado &quot; para abrir um editor com configurações mais
Clique &quot;Ãgua Avançada &quot; para abrir um editor com configurações mais avançadas para a água.
</notification>
<notification name="HelpDayCycle">
- O editor de Ciclo do Dia dá a você o controle do céu durante um ciclo de dia/noite do Second Life. Este é o ciclo usado pelo controle gradual da hora do dia do editor de ambiente básico.
+ O editor de Ciclo do Dia dá a você o controle do céu durante um ciclo de dia/noite do [SECOND_LIFE]. Este é o ciclo usado pelo controle gradual da hora do dia do editor de ambiente básico.
O editor do ciclo de dia trabalha configurando quadros-chave. Estes são pontos (representados pelos ícones cinza no gráfico de horário) que possuem um pré-ajuste de céu associado a eles. Conforme o dia passa, o céu do Windlight &quot; anima &quot; a interpolação entre esses quadros-chave.
@@ -2258,7 +2232,7 @@ Similar ao azimute.
Controla a velocidade que as núvens se movem na direção Y.
</notification>
<notification name="HelpClassicClouds">
- Marque esta check box para permitir a reprodução das nuvens clássicas mais velhas do Second Life, além das nuvens WindLight.
+ Marque esta check box para permitir a reprodução das nuvens clássicas mais velhas do [SECOND_LIFE], além das nuvens WindLight.
</notification>
<notification name="HelpWaterFogColor">
Escolhe a cor da neblina subaquática.
@@ -2302,7 +2276,7 @@ Similar ao azimute.
<notification name="NewSkyPreset">
Me dê o nome para o novo céu.
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Novo padrão
</input>
<button name="OK" text="OK"/>
@@ -2315,7 +2289,7 @@ Similar ao azimute.
<notification name="NewWaterPreset">
Dê o nome para o novo padrão de água.
<form name="form">
- <input name="message" type="text">
+ <input name="message">
Nova Apresentação
</input>
<button name="OK" text="OK"/>
@@ -2356,21 +2330,21 @@ Similar ao azimute.
</notification>
<notification name="NotAgeVerified">
Você precisa ter a idade verificada para acessar este lote.
-Gostaria de visitar o site do Second Life para verificação de idade?
+Gostaria de visitar o site do [SECOND_LIFE] para verificação de idade?
[_URL]
<url name="url" option="0">
- https://secondlife.com/account/verification.php
+ https://secondlife.com/account/verification.php?lang=pt
</url>
<usetemplate ignoretext="Alertar sobre a falta de verificação de idade" name="okcancelignore" notext="Não" yestext="Sim"/>
</notification>
<notification name="Cannot enter parcel: no payment info on file">
Este lote exige que você tenha informações de pagamento no arquivo antes de poder acessá-lo.
-Gostaria de visitar o site do Second Life para configurá-lo?
+Gostaria de visitar o site do [SECOND_LIFE] para configurá-lo?
[_URL]
<url name="url" option="0">
- https://secondlife.com/account/
+ https://secondlife.com/account/index.php?lang=pt
</url>
<usetemplate ignoretext="Avisar sobre a falta de informação de pagamento." name="okcancelignore" notext="Não" yestext="Sim"/>
</notification>
@@ -2627,7 +2601,7 @@ Vá para a Ilha de Ajuda Pública para repetir este tutorial.
<notification name="ImproperPaymentStatus">
Você não tem o status de pagamento adequado para entrar nesta região.
</notification>
- <notification name="MustGetAgeRgion">
+ <notification name="MustGetAgeRegion">
Você precisa ter sua idade verificada para entrar nesta região.
</notification>
<notification name="MustGetAgeParcel">
@@ -2677,13 +2651,13 @@ Por favor, tente novamente em alguns instantes.
Impossível criar a conexão pendente.
</notification>
<notification name="InternalUsherError">
- Um erro interno ocorreu enquanto se tentava direcioná-lo para seu destino de Tele-transporte. O Second Life pode estar passando por problemas no serviço, neste momento.
+ Um erro interno ocorreu enquanto se tentava direcioná-lo para seu destino de Tele-transporte. O [SECOND_LIFE] pode estar passando por problemas no serviço, neste momento.
</notification>
<notification name="NoGoodTPDestination">
Impossível encontrar um bom destino para tele-transporte nesta região.
</notification>
<notification name="InternalErrorRegionResolver">
- Um erro interno ocorreu enquanto tentava-se definir as coordenadas globais da sua solicitação de tele-transporte. O Second Life pode estar passando por problemas no serviço, no momento.
+ Um erro interno ocorreu enquanto tentava-se definir as coordenadas globais da sua solicitação de tele-transporte. O [SECOND_LIFE] pode estar passando por problemas no serviço, no momento.
</notification>
<notification name="NoValidLanding">
Não se achou um ponto de aterrissagem válido.
@@ -2804,7 +2778,7 @@ Do objeto: [OBJECTNAME], dono: [NAME]?
Falhou ao procurar [TYPE] nomeado [DESC] no banco de dados.
</notification>
<notification name="InvalidWearable">
- O item que você está tentando vestir usa uma característica que seu Visualizador não lê. Por favor, atualize sua versão do Second Life para vestir este item.
+ O item que você está tentando vestir usa uma característica que seu Visualizador não lê. Por favor, atualize sua versão do [APP_NAME] para vestir este item.
</notification>
<notification name="ScriptQuestion">
&apos;[OBJECTNAME]&apos;, um objeto pertencente a &apos;[NAME]&apos;, gostaria de:
@@ -2909,8 +2883,8 @@ Objetos flexíveis não podem ser físicos e devem ser fantasmas até que a caix
</notification>
<notification name="FirstDebugMenus">
Você ativou o menu Avançado.
-Este menu contém funcionalidades úteis para desenvolvedores debugarem o Second Life.
-Para mostrar esse menu no Windows pressione Ctrl-Alt-D. No Mac pressione Cmd-Opt-Shift-D.
+Este menu contém funcionalidades úteis para desenvolvedores debugarem o [SECOND_LIFE].
+Para mostrar esse menu no Windows pressione Ctrl+Alt+D. No Mac pressione &#8997;&#8984;D.
</notification>
<notification name="FirstSculptedPrim">
Você está editando uma primitiva esculpida.
@@ -3017,7 +2991,7 @@ Clique Aceitar para juntar-se à chamada ou Recusar para recusar o convite. Cliq
- A velocidade da sua CPU não suporta os requisitos mínimos exigidos.
</global>
<global name="UnsupportedGLRequirements">
- Você não parece ter os requisitos de hardware recomendados para rodar o Second Life. O Second Life exige uma placa gráfica OpenGL que tem apoio a multi- texturas. Se este for o caso, você pode se certificar de que tem os drivers mais recentes para sua placa gráfica, e os patches e pacotes de serviços para seu sistema operacional.
+ Você não parece ter os requisitos de hardware recomendados para rodar o [APP_NAME]. O [APP_NAME] exige uma placa gráfica OpenGL que tem apoio a multi- texturas. Se este for o caso, você pode se certificar de que tem os drivers mais recentes para sua placa gráfica, e os patches e pacotes de serviços para seu sistema operacional.
Se continuar com problemas, por favor visite: http://www.secondlife.com/support
</global>
diff --git a/indra/newview/skins/default/xui/pt/panel_edit_profile.xml b/indra/newview/skins/default/xui/pt/panel_edit_profile.xml
new file mode 100644
index 0000000000..a989cab167
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_edit_profile.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel name="edit_profile_panel">
+ <string name="CaptionTextAcctInfo">
+ [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION]
+ </string>
+ <string name="AcctTypeResident"
+ value="Residente" />
+ <string name="AcctTypeTrial"
+ value="Teste" />
+ <string name="AcctTypeCharterMember"
+ value="Estatuto do membro" />
+ <string name="AcctTypeEmployee"
+ value="Contratado da Linden Lab" />
+ <string name="PaymentInfoUsed"
+ value="Infor. de pagamento utilizadas" />
+ <string name="PaymentInfoOnFile"
+ value="Infor. de pagamento no arquivo" />
+ <string name="NoPaymentInfoOnFile"
+ value="Sem infor. de pagamento no arquivo" />
+ <string name="AgeVerified"
+ value="Idade Verificada" />
+ <string name="NotAgeVerified"
+ value="Idade não Verificada" />
+ <string name="partner_edit_link_url">
+ http://www.secondlife.com/account/partners.php?lang=pt
+ </string>
+ <panel name="scroll_content_panel">
+ <panel name="data_panel" >
+ <panel name="lifes_images_panel">
+ <panel name="second_life_image_panel">
+ <text name="second_life_photo_title_text">
+ [SECOND_LIFE]:
+ </text>
+ </panel>
+ </panel>
+ <text name="title_partner_text" value="Parceiro:"/>
+ <panel name="partner_data_panel">
+ <text name="partner_text" value="[FIRST] [LAST]"/>
+ </panel>
+ <text name="text_box3">
+ Resposta no Modo Ocupado:
+ </text>
+ </panel>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_friends.xml b/indra/newview/skins/default/xui/pt/panel_friends.xml
index afd7b79eaa..d430d637ad 100644
--- a/indra/newview/skins/default/xui/pt/panel_friends.xml
+++ b/indra/newview/skins/default/xui/pt/panel_friends.xml
@@ -11,10 +11,10 @@
<column name="icon_edit_mine" tool_tip="Amigo pode editar, apagar ou pegar seus objetos"/>
<column name="icon_edit_theirs" tool_tip="Você pode editar os objetos deste amigo"/>
</scroll_list>
- <button label="MI/Chamar" name="im_btn" tool_tip="Abrir sessão de Mensagem Instantânea"/>
- <button label="Perfil" name="profile_btn" tool_tip="Mostrar foto, grupos e outras informações"/>
- <button label="Teletransporte..." name="offer_teleport_btn" tool_tip="Oferecer a este amigo o teletransporte para sua localização atual"/>
- <button label="Pagar..." name="pay_btn" tool_tip="Dar Linden dólares (L$) a este amigo"/>
- <button label="Remover..." name="remove_btn" tool_tip="Remover esta pessoa de sua lista de amigos"/>
- <button label="Adicionar..." name="add_btn" tool_tip="Oferecer amizade a um residente"/>
+ <button width="86" label="MI/Chamar" name="im_btn" tool_tip="Abrir sessão de Mensagem Instantânea"/>
+ <button width="86" label="Perfil" name="profile_btn" tool_tip="Mostrar foto, grupos e outras informações"/>
+ <button width="86" label="Teletransp..." name="offer_teleport_btn" tool_tip="Oferecer a este amigo o teletransporte para sua localização atual"/>
+ <button width="86" label="Pagar..." name="pay_btn" tool_tip="Dar Linden dólares (L$) a este amigo"/>
+ <button width="86" label="Remover..." name="remove_btn" tool_tip="Remover esta pessoa de sua lista de amigos"/>
+ <button width="86" label="Adicionar..." name="add_btn" tool_tip="Oferecer amizade a um residente"/>
</panel>
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 f4941eabd9..226011c138 100644
--- a/indra/newview/skins/default/xui/pt/panel_group_general.xml
+++ b/indra/newview/skins/default/xui/pt/panel_group_general.xml
@@ -14,7 +14,7 @@
<text name="prepend_founded_by">
Fundado por:
</text>
- <text name="founder_name">
+ <text name="founder_name" left_delta="74" >
(espera)
</text>
<text name="group_charter_label">
@@ -33,9 +33,9 @@
(Proprietários são mostrados em negrito )
</text>
<name_list name="visible_members">
- <column label="Nome do membro" name="name"/>
- <column label="Título" name="title"/>
- <column label="Último login" name="online"/>
+ <name_list.columns label="Nome do membro" name="name"/>
+ <name_list.columns label="Título" name="title"/>
+ <name_list.columns label="Último login" name="online"/>
</name_list>
<text name="text_group_preferences">
Preferências do Grupo
@@ -43,18 +43,12 @@
<panel name="preferences_container">
<check_box label="Mostre na busca" name="show_in_group_list" tool_tip="Deixe as pessoas verem este grupo nos resultados de busca."/>
<check_box label="Adesão aberta" name="open_enrollement" tool_tip="Definir se este grupo permite que novos membros entrem sem serem convidados"/>
- <check_box label="Taxa de adesão: L$" name="check_enrollment_fee" tool_tip="Define se é necessária uma taxa de adesão para se unir ao grupo."/>
- <spinner name="spin_enrollment_fee" tool_tip="Os novos membros devem pagar esta taxa para se unir ao grupo quando a Taxa de Adesão está marcada."/>
- <combo_box name="group_mature_check" tool_tip="Define se a informação do seu grupo é considerada mature.">
- <combo_item name="select_mature">
- - Selecionar Maturidade -
- </combo_item>
- <combo_item name="mature">
- Conteúdo Mature
- </combo_item>
- <combo_item name="pg">
- Conteúdo PG
- </combo_item>
+ <check_box label="Taxa de adesão:" name="check_enrollment_fee" tool_tip="Define se é necessária uma taxa de adesão para se unir ao grupo."/>
+ <spinner width="60" left_delta="120" name="spin_enrollment_fee" tool_tip="Os novos membros devem pagar esta taxa para se unir ao grupo quando a Taxa de Adesão está marcada."/>
+ <combo_box width="170" name="group_mature_check" tool_tip="Define se a informação do seu grupo é considerada mature.">
+ <combo_box.item name="select_mature" label="- Selecionar Maturidade -"/>
+ <combo_box.item name="mature" label="Conteúdo Mature"/>
+ <combo_box.item name="pg" label="Conteúdo PG"/>
</combo_box>
<panel name="title_container">
<text name="active_title_label">
diff --git a/indra/newview/skins/default/xui/pt/panel_group_invite.xml b/indra/newview/skins/default/xui/pt/panel_group_invite.xml
index e9c7bab3db..a02a17139b 100644
--- a/indra/newview/skins/default/xui/pt/panel_group_invite.xml
+++ b/indra/newview/skins/default/xui/pt/panel_group_invite.xml
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<panel label="Convidar um membro" name="invite_panel">
- <text name="help_text">
+<panel label="Convidar um membro" name="invite_panel" width="224">
+ <text name="help_text" width="214">
Voce pode selecionar vários residentes
-para convidar ao seu grupo. Clique &apos;Abrir
-Seletor de Residente&apos; para iniciar.
+para convidar ao seu grupo. Clique
+&apos;Abrir Seletor de Residente&apos; para iniciar.
</text>
<button label="Abrir Seletor de Residente" name="add_button" tool_tip=""/>
<name_list name="invitee_list" tool_tip="Mantenha apertada a tecla Control e clique nos nomes dos residentes para uma seleção múltipla."/>
- <button label="Remove Selected from List" name="remove_button" tool_tip="Remove os residentes selecionados acima da lista de convite."/>
+ <button left_delta="-7" width="214" label="Remove os selecionados acima da lista" name="remove_button" tool_tip="Remove os residentes selecionados acima da lista de convite."/>
<text name="role_text">
Escolha que Função atribuir a eles:
</text>
diff --git a/indra/newview/skins/default/xui/pt/panel_group_land_money.xml b/indra/newview/skins/default/xui/pt/panel_group_land_money.xml
index f5e96869d7..5b09363e3c 100644
--- a/indra/newview/skins/default/xui/pt/panel_group_land_money.xml
+++ b/indra/newview/skins/default/xui/pt/panel_group_land_money.xml
@@ -13,7 +13,7 @@
<string name="loading_txt">
Carregando...
</string>
- <text name="group_land_heading">
+ <text name="group_land_heading" width="250">
Terra percentente ao grupo
</text>
<scroll_list name="group_parcel_list">
@@ -22,7 +22,7 @@
<column label="Tipo" name="type"/>
<column label="Ãrea" name="area"/>
</scroll_list>
- <button label="Mostrar no Mapa" label_selected="Mostrar no Mapa" name="map_button"/>
+ <button label="Mostrar no Mapa" label_selected="Mostrar no Mapa" name="map_button" left="282" width="130"/>
<text name="total_contributed_land_label">
Contribuição Total:
</text>
@@ -47,11 +47,15 @@
<string name="land_contrib_error">
Não é possível definir sua contribuição para o terreno.
</string>
+ <text name="your_contribution_units">
+ ( m² )
+ </text>
<text name="your_contribution_max_value">
- m² ([AMOUNT] máxima)
+ ([AMOUNT] máxima)
</text>
<text name="group_over_limit_text">
- Membros do grupo precisam contribuir com mais créditos de Terra para garantir a terra em uso.
+ Membros do grupo precisam contribuir com mais créditos de Terra para
+garantir a terra em uso.
</text>
<text name="group_money_heading">
Grupo L$
@@ -66,8 +70,8 @@
<text_editor name="group_money_details_text">
Computando...
</text_editor>
- <button label="&lt; Cedo" label_selected="&lt; Cedo" name="earlier_details_button" tool_tip="Voltar no Tempo"/>
- <button label="Tarde &gt;" label_selected="Tarde &gt;" name="later_details_button" tool_tip="Adiantar o Tempo"/>
+ <button label="&lt; Mais Cedo" label_selected="&lt; Cedo" name="earlier_details_button" tool_tip="Voltar no Tempo"/>
+ <button label="Mais Tarde &gt;" label_selected="Tarde &gt;" name="later_details_button" tool_tip="Adiantar o Tempo"/>
</panel>
<panel label="Vendas" name="group_money_sales_tab">
<text_editor name="group_money_sales_text">
diff --git a/indra/newview/skins/default/xui/pt/panel_group_notices.xml b/indra/newview/skins/default/xui/pt/panel_group_notices.xml
index 1285a24ace..d5c0f01e33 100644
--- a/indra/newview/skins/default/xui/pt/panel_group_notices.xml
+++ b/indra/newview/skins/default/xui/pt/panel_group_notices.xml
@@ -1,11 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Notícias" name="notices_tab">
<text name="help_text">
- As notícias são uma maneira rápida de
-comunicar-se através de um grupo transmitindo uma mensagem e
-entregando um item anexo, opcionalmente. As notícias vão apenas a membros
-do grupo que têm a função habilitada para receber notícias. Você pode desligar
-Notícias na aba Geral.
+ As notícias são uma maneira rápida de comunicar-se através de um grupo transmitindo uma mensagem e entregando um item anexo, opcionalmente. As notícias vão apenas a membros do grupo que têm a função habilitada para receber notícias. Você pode desligar Notícias na aba Geral.
</text>
<text name="no_notices_text">
Não existem notícias anteriores.
@@ -15,8 +11,7 @@ Notícias na aba Geral.
Arquivo de notícias do grupo
</text>
<text name="lbl2">
- As notícias são mantidas por 14 dias. Clique na notícia abaixo que você deseja ver.
-Clique no botão “Atualizar†para verificar se novas notícias foram recebidas.
+ As notícias são mantidas por 14 dias.
Listas de aviso estão limitadas a 200 por grupo, diariamente.
</text>
<scroll_list name="notice_list">
@@ -34,22 +29,22 @@ Listas de aviso estão limitadas a 200 por grupo, diariamente.
Criar uma notícia
</text>
<text name="lbl2">
- Você deve colocar um assunto para enviar uma notícia. Você pode
-adicionar um item simples à notícia, arrastando-o do seu
-Inventário para o painel. Itens anexados devem ser copiáveis
-e transferíveis e você não pode mandar uma pasta.
+ Você pode adicionar um item simples à notícia, arrastando-o do seu Inventário para o painel. Itens anexados devem ser copiáveis e transferíveis e você não pode mandar uma pasta.
</text>
- <text name="lbl3">
+ <text name="lbl3" left="20">
Assunto:
</text>
- <text name="lbl4">
+ <line_editor name="create_subject" width="251" left_delta="61"/>
+ <text name="lbl4" left="15" width="60">
Mensagem:
</text>
- <text name="lbl5">
+ <text_editor name="create_message" left_delta="66" width="330"/>
+ <text name="lbl5" width="68">
Anexo:
</text>
+ <line_editor name="create_inventory_name" width="190" left_delta="74"/>
<button label="Remover o anexo" label_selected="Remover o anexo" name="remove_attachment"/>
- <button label="Enviar notícia" label_selected="Enviar notícia" name="send_notice"/>
+ <button label="Enviar" label_selected="Enviar" name="send_notice"/>
<panel name="drop_target" tool_tip="Arraste um item do inventário para dentro da caixa de mensagem para enviá-lo com a notícia. Você deve ter permissão para copiar e transferir o objeto, para enviá-lo com a notícia."/>
</panel>
<panel label="Visualizar Notícia Anterior" name="panel_view_past_notice">
diff --git a/indra/newview/skins/default/xui/pt/panel_group_roles.xml b/indra/newview/skins/default/xui/pt/panel_group_roles.xml
index 32ed839bd8..087cf0c107 100644
--- a/indra/newview/skins/default/xui/pt/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/pt/panel_group_roles.xml
@@ -13,7 +13,8 @@
</text>
<text name="static2">
São atribuídas funções com habilidades aos membros do grupo.
-Estes ajustes podem ser facilmente customizados para uma flexibilidade e organização maiores.
+Estes ajustes podem ser facilmente customizados para uma flexibilidade
+e organização maiores.
</text>
</panel>
<panel name="roles_header">
@@ -21,12 +22,14 @@ Estes ajustes podem ser facilmente customizados para uma flexibilidade e organiz
Funções
</text>
<text name="role_properties_modifiable">
- Selecionar uma função abaixo. Você pode modificar o nome, a descrição e o título do membro.
+ Selecionar uma função abaixo. Você pode modificar o nome, a descrição
+e o título do membro.
</text>
<text name="role_properties_not_modifiable">
- Selecione uma função abaixo para ver suas propriedades, membros e habilidades permitidas.
+ Selecione uma função abaixo para ver suas propriedades, membros e
+habilidades permitidas.
</text>
- <text name="role_actions_modifiable">
+ <text bottom_delta="-28" name="role_actions_modifiable">
Você também pode atribuir habilidades à função.
</text>
<text name="role_actions_not_modifiable">
@@ -38,28 +41,31 @@ Estes ajustes podem ser facilmente customizados para uma flexibilidade e organiz
Habilidades
</text>
<text name="static2">
- Você pode ver a descrição de uma habilidade e quais funções e membros podem executar essa habilidade.
+ Você pode ver a descrição de uma habilidade e quais funções e membros
+podem executar essa habilidade.
</text>
</panel>
- <tab_container name="roles_tab_container">
- <panel label="Membros" name="members_sub_tab" tool_tip="Membros">
- <button label="Pesquisar" name="search_button"/>
- <button label="Mostrar todos" name="show_all_button"/>
- <name_list name="member_list">
+ <tab_container height="164" name="roles_tab_container">
+ <panel height="148" label="Membros" name="members_sub_tab" tool_tip="Membros">
+ <line_editor bottom="127" name="search_text"/>
+ <button label="Pesquisar" name="search_button" width="75"/>
+ <button label="Mostrar todos" name="show_all_button" left_delta="80"/>
+ <name_list name="member_list" bottom_delta="-105" height="104" >
<column label="Nome do membro" name="name"/>
<column label="Tarifa doada" name="donated"/>
<column label="Último login" name="online"/>
</name_list>
- <button label="Convidar Novo Membro ..." name="member_invite"/>
+ <button label="Convidar Novo Membro..." name="member_invite" width="165"/>
<button label="Ejetar do Grupo" name="member_eject"/>
<string name="help_text">
Você pode adicionar ou remover as funções designadas aos membros. Selecione vários membros, segurando a tecla Ctrl e clicando em seus nomes.
</string>
</panel>
- <panel label="Funções" name="roles_sub_tab">
- <button label="Busca" name="search_button"/>
- <button label="Mostrar todos" name="show_all_button"/>
- <scroll_list name="role_list">
+ <panel height="148" label="Funções" name="roles_sub_tab">
+ <line_editor bottom="127" name="search_text"/>
+ <button label="Busca" name="search_button" width="75"/>
+ <button label="Mostrar todos" name="show_all_button" left_delta="80"/>
+ <scroll_list name="role_list" bottom_delta="-104" height="104">
<column label="Nome da função" name="name"/>
<column label="Título" name="title"/>
<column label="Membro" name="members"/>
@@ -75,10 +81,11 @@ permitidas que os membros podem executar. Os membros poderão ter um ou mais fun
As funções &apos;todos&apos; e &apos;donos&apos; são especiais e não podem ser deletadas.
</string>
</panel>
- <panel label="Habilidades" name="actions_sub_tab">
- <button label="Busca" name="search_button"/>
- <button label="Mostrar todos" name="show_all_button"/>
- <scroll_list name="action_list" tool_tip="Selecione uma habilidade para ver mais detalhes."/>
+ <panel height="148" label="Habilidades" name="actions_sub_tab">
+ <line_editor bottom="127" name="search_text"/>
+ <button label="Busca" name="search_button" width="75"/>
+ <button label="Mostrar todos" name="show_all_button" left_delta="80"/>
+ <scroll_list bottom_delta="-120" height="118" name="action_list" tool_tip="Selecione uma habilidade para ver mais detalhes."/>
<string name="help_text">
As habilidades permitem que os membros nas funções façam coisas específicas dentro do grupo.
Há uma grande variedade de habilidades.
diff --git a/indra/newview/skins/default/xui/pt/panel_groups.xml b/indra/newview/skins/default/xui/pt/panel_groups.xml
index 8a886ef8b1..aaea1178a6 100644
--- a/indra/newview/skins/default/xui/pt/panel_groups.xml
+++ b/indra/newview/skins/default/xui/pt/panel_groups.xml
@@ -1,16 +1,15 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="groups">
- <text name="groupdesc">
+ <text name="groupdesc" width="268">
Seu grupo ativo atual es&apos;ta mostrado em negrito.
</text>
- <text name="groupcount">
+ <text name="groupcount" width="300">
Você pertence a [COUNT] grupos (de no máximo [MAX]).
-aximo
</text>
- <button label="MI/Chamada" name="IM" tool_tip="Abrir sessão de Mensagem Instantânea"/>
- <button label="Informações" name="Info"/>
- <button label="Ativar" name="Activate"/>
- <button label="Deixar" name="Leave"/>
- <button label="Criar..." name="Create"/>
- <button label="Buscar..." name="Search..."/>
+ <button width="86" label="MI/Chamada" name="IM" tool_tip="Abrir sessão de Mensagem Instantânea"/>
+ <button width="86" label="Informações" name="Info"/>
+ <button width="86" label="Ativar" name="Activate"/>
+ <button width="86" label="Deixar" name="Leave"/>
+ <button width="86" label="Criar..." name="Create"/>
+ <button width="86" label="Buscar..." name="Search..."/>
</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_login.xml b/indra/newview/skins/default/xui/pt/panel_login.xml
index bee5dd1328..d7ff3f29df 100644
--- a/indra/newview/skins/default/xui/pt/panel_login.xml
+++ b/indra/newview/skins/default/xui/pt/panel_login.xml
@@ -1,5 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="panel_login">
+ <panel.string name="create_account_url">
+ http://join.secondlife.com/index.php?lang=pt-BR
+ </panel.string>
+ <panel.string name="forgot_password_url">
+ http://secondlife.com/account/request.php?lang=pt
+ </panel.string>
+<panel name="login_widgets">
<text name="first_name_text">
Primeiro nome:
</text>
@@ -10,28 +17,23 @@
Senha:
</text>
<text name="start_location_text">
- Localização inicial:
+ Posição inicial:
</text>
<combo_box name="start_location_combo">
- <combo_item name="MyHome">
- Minha casa
- </combo_item>
- <combo_item name="MyLastLocation">
- Minha última localização
- </combo_item>
- <combo_item name="Typeregionname">
- &lt; Digite o nome da região;
- </combo_item>
+ <combo_box.item name="MyHome" label="Minha casa" />
+ <combo_box.item name="MyLastLocation" label="Minha última localização" />
+ <combo_box.item name="Typeregionname" label="&lt; Digite o nome da região &gt;" />
</combo_box>
<check_box label="Lembrar senha" name="remember_check"/>
<button label="Entrar" label_selected="Entrar" name="connect_btn"/>
<text name="create_new_account_text">
Registrar-se para uma conta
</text>
- <text name="forgot_password_text">
+ <text name="forgot_password_text" left="-240" width="230">
Esqueceu seu nome de usuário ou senha?
</text>
<text name="channel_text">
[VERSION]
</text>
</panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/pt/panel_preferences_advanced.xml
new file mode 100644
index 0000000000..5ca80bd74d
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_preferences_advanced.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<panel name="advanced">
+ <text name="AspectRatioLabel1" tool_tip="largura / altura">
+ Relação de Aspecto:
+ </text>
+ <combo_box name="aspect_ratio" tool_tip="largura / altura">
+ <combo_box.item label="4:3 (CRT Padrão)" name="item1"/>
+ <combo_box.item label="5:4 (1280x1024 LCD)" name="item2"/>
+ <combo_box.item label="8:5 (tela ampla)" name="item3"/>
+ <combo_box.item label="16:9 (tela ampla)" name="item4"/>
+ </combo_box>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_alerts.xml b/indra/newview/skins/default/xui/pt/panel_preferences_alerts.xml
new file mode 100644
index 0000000000..e060d784da
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_preferences_alerts.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Popups" name="popups" title="Popups">
+ <text name="dont_show_label">
+ Não mostrar estas popups:
+ </text>
+ <button label="Habilitar esta popup" label_selected="Habilitar este popup" name="enable_popup"/>
+ <button label="Habilitar todas as popups..." label_selected="Reiniciar Dialogos que serão mostrados na próxima vez..." name="reset_dialogs_btn" tool_tip="Habilitar todas as popups opcionais e notificações de “primeiro usoâ€." width="200"/>
+ <text name="show_label">
+ Mostrar estas popups:
+ </text>
+ <button label="Desabilitar todas estas popups..." name="skip_dialogs_btn" tool_tip="Desabilitar todas as popups opcionais e notificações de “primeiro usoâ€." width="200"/>
+ <text name="text_box2">
+ Ofertas de notecards, texturas e landmarks:
+ </text>
+ <check_box label="Aceitar automaticamente" name="accept_new_inventory"/>
+ <check_box label="Visualizar automaticamente após aceitar" name="show_new_inventory"/>
+ <check_box label="Mostrar automaticamente objetos aceitos recentemente no inventário." name="show_in_inventory"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml b/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml
index 8ae635bbae..aa40f97fe3 100644
--- a/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml
@@ -1,59 +1,59 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Chat" name="chat">
- <text length="1" name="text_box" type="string">
+ <text name="text_box">
Tamanho da Fonte
do Chat:
</text>
<radio_group name="chat_font_size">
- <radio_item name="radio">
- Pequeno
- </radio_item>
- <radio_item name="radio2">
- Médio
- </radio_item>
- <radio_item name="radio3">
- Grande
- </radio_item>
+ <radio_item name="radio" label="Pequeno" />
+ <radio_item name="radio2" label="Médio" />
+ <radio_item name="radio3" label="Grande" />
</radio_group>
- <text length="1" name="text_box2" type="string">
- Cor do Chat:
- </text>
<color_swatch label="Você" name="user"/>
+ <text name="text_box1">
+ Você
+ </text>
<color_swatch label="Outros" name="agent"/>
+ <text name="text_box2">
+ Outros
+ </text>
<color_swatch label="MI" name="im"/>
+ <text name="text_box3">
+ MI
+ </text>
<color_swatch label="Sistema" name="system"/>
+ <text name="text_box4">
+ Sistema
+ </text>
<color_swatch label="Erros" name="script_error"/>
+ <text name="text_box5">
+ Erros
+ </text>
<color_swatch label="Objetos" name="objects"/>
+ <text name="text_box6">
+ Objetos
+ </text>
<color_swatch label="Dono" name="owner"/>
+ <text name="text_box7">
+ Dono
+ </text>
<color_swatch label="Bolha" name="background"/>
+ <text name="text_box8">
+ Bolha
+ </text>
<color_swatch label="URLs" name="links"/>
- <text length="1" name="text_box8" type="string">
- Erros de Script:
+ <text name="text_box9">
+ URLs
</text>
<check_box label="Mostrar Erros de Script e avisos como chat comum" name="script_errors_as_chat"/>
- <text length="1" name="text_box3" type="string">
- Console do Chat:
- </text>
- <spinner label="Ocultar Chat depois" label_width="112" name="fade_chat_time" width="162"/>
- <text left="310" length="1" name="text_box4" type="string">
- (segundos)
- </text>
+ <spinner label="Ocultar Chat depois" label_width="108" name="fade_chat_time" width="160"/>
<spinner left="373" name="max_chat_count"/>
- <text left="435" length="1" name="text_box5" type="string" width="94">
- (# linhas)
- </text>
<slider label="Opacidade" name="console_opacity"/>
<check_box label="Use a largura total da tela (Precisa reiniciar)" name="chat_full_width_check"/>
- <text length="1" name="text_box6" type="string">
- Opções do Chat:
- </text>
<check_box label="Feche a barra de conversa após pressionar retornar" name="close_chat_on_return_check"/>
<check_box label="Teclas de Setas sempre movem o avatar durante a conversa" name="arrow_keys_move_avatar_check"/>
<check_box label="Mostrar a hora na conversa local" name="show_timestamps_check"/>
<check_box label="Executar animação digitada quando estiver conversando" name="play_typing_animation"/>
- <text length="1" name="text_box7" type="string">
- Chat com bolha:
- </text>
<check_box label="Mostrar bolhas do chat" name="bubble_text_chat"/>
<slider label="Opacidade" name="bubble_chat_opacity"/>
</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_general.xml b/indra/newview/skins/default/xui/pt/panel_preferences_general.xml
index fde3551b8b..8bde39545c 100644
--- a/indra/newview/skins/default/xui/pt/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/pt/panel_preferences_general.xml
@@ -1,24 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel label="Geral" name="general_panel">
- <radio_group name="default_start_location">
- <radio_item name="MyHome" tool_tip="Como padrão, registrar na minha casa.">
- Minha Casa
- </radio_item>
- <radio_item name="MyLastLocation" tool_tip="Por padrão, registrar na minha última localidade.">
- Minha Última Localidade
- </radio_item>
- </radio_group>
+ <combo_box name="start_location_combo">
+ <combo_box.item name="MyHome" tool_tip="Como padrão, registrar na minha casa." label="Minha Casa"/>
+ <combo_box.item name="MyLastLocation" tool_tip="Por padrão, registrar na minha última localidade." label="Minha Última Localidade"/>
+ </combo_box>
<check_box label="Mostrar Posição Inicial na Tela de Login" name="show_location_checkbox"/>
- <combo_box name="fade_out_combobox" width="166">
- <combo_item name="Never">
- Nunca
- </combo_item>
- <combo_item name="Show Temporarily">
- Mostrar Temporariamente
- </combo_item>
- <combo_item name="Always">
- Sempre
- </combo_item>
+ <combo_box name="fade_out_combobox">
+ <combo_box.item name="Never" label="Nunca"/>
+ <combo_box.item name="Show Temporarily" label="Mostrar Temporariamente"/>
+ <combo_box.item name="Always" label="Sempre"/>
</combo_box>
<check_box label="Avatar com Nomes Pequenos" name="small_avatar_names_checkbox"/>
<check_box label="Ocultar meu Nome na minha Tela" name="show_my_name_checkbox"/>
@@ -34,114 +24,67 @@
<check_box label="Usar escala independente da resolução" name="ui_auto_scale"/>
<spinner label="Tempo para ficar Ausente:" name="afk_timeout_spinner"/>
<check_box label="Avisar quando receber ou gastar Linden dollars (L$)" name="notify_money_change_checkbox"/>
- <text name="maturity_desired_label" bottom="-312">
+ <text name="maturity_desired_label">
Classificação:
</text>
- <text name="maturity_desired_prompt" bottom="-312">
- Eu quero acessar
-conteúdo classificado:
+ <text name="maturity_desired_prompt">
+ Eu quero acessar conteúdo classificado:
</text>
- <combo_box name="maturity_desired_combobox" bottom="-330" left="278">
- <combo_item name="Desired_Adult">
- PG, Mature e Adult
- </combo_item>
- <combo_item name="Desired_Mature">
- PG e Mature
- </combo_item>
- <combo_item name="Desired_PG">
- apenas PG
- </combo_item>
+ <combo_box name="maturity_desired_combobox">
+ <combo_box.item name="Desired_Adult" label="PG, Mature e Adult"/>
+ <combo_box.item name="Desired_Mature" label="PG e Mature"/>
+ <combo_box.item name="Desired_PG" label="PG"/>
</combo_box>
- <text name="maturity_desired_textbox" bottom="-324" left="278">
- apenas PG
+ <text name="maturity_desired_textbox">
+ PG
</text>
- <text length="1" name="start_location_textbox" type="string">
+ <text name="start_location_textbox">
Posição Inicial:
</text>
- <text length="1" name="show_names_textbox" type="string">
+ <text name="show_names_textbox">
Mostrar Nomes:
</text>
- <text length="1" name="effects_color_textbox" type="string">
+ <text name="effects_color_textbox">
Cores para Meus Efeitos:
</text>
- <text length="1" name="seconds_textbox" type="string">
+ <text name="seconds_textbox">
segundos
</text>
- <text length="1" name="crash_report_textbox" type="string">
+ <text name="crash_report_textbox">
Relatórios de Falhas:
</text>
<text name="language_textbox">
Linguagem:
</text>
- <text left_delta="313" length="1" name="language_textbox2" type="string">
+ <text name="language_textbox2">
(Precisa de reinício para efetivar)
</text>
<string name="region_name_prompt">
Digite o nome da Região
</string>
- <combo_box name="crash_behavior_combobox" width="166">
- <combo_item length="1" name="Askbeforesending" type="string">
- Perguntar antes de enviar
- </combo_item>
- <combo_item length="1" name="Alwayssend" type="string">
- Sempre enviar
- </combo_item>
- <combo_item length="1" name="Neversend" type="string">
- Nunca Enviar
- </combo_item>
+ <combo_box name="crash_behavior_combobox">
+ <combo_box.item name="Askbeforesending" label="Perguntar antes de enviar"/>
+ <combo_box.item name="Alwayssend" label="Sempre enviar"/>
+ <combo_box.item name="Neversend" label="Nunca Enviar"/>
</combo_box>
- <combo_box name="language_combobox" width="166">
- <combo_item name="System Default Language">
- Padrão do Sistema
- </combo_item>
- <combo_item name="English">
- English (Inglês)
- </combo_item>
- <combo_item name="Danish">
- Dansk (Dinamarquês) - Beta
- </combo_item>
- <combo_item name="Deutsch(German)">
- Deutsch (Alemão) - Beta
- </combo_item>
- <combo_item name="Spanish">
- Español (Espanhol) - Beta
- </combo_item>
- <combo_item name="French">
- Français (Francês) - Beta
- </combo_item>
- <combo_item name="Italian">
- Italiano - Beta
- </combo_item>
- <combo_item name="Hungarian">
- Magyar (Húngaro) - Beta
- </combo_item>
- <combo_item name="Dutch">
- Nederlands (Holandês) - Beta
- </combo_item>
- <combo_item name="Polish">
- Polski (Polonês) - Beta
- </combo_item>
- <combo_item name="Portugese">
- Português - Beta
- </combo_item>
- <combo_item name="Russian">
- РуÑÑкий (Russo) - Beta
- </combo_item>
- <combo_item name="Turkish">
- Türkçe (Turco) - Beta
- </combo_item>
- <combo_item name="Ukrainian">
- УкраїнÑька (Ucraniano) - Beta
- </combo_item>
- <combo_item name="Chinese">
- 中文 (简体) (Chinês) - Beta
- </combo_item>
- <combo_item name="(Japanese)">
- 日本語 (Japonês) - Beta
- </combo_item>
- <combo_item name="(Korean)">
- 한국어 (Coreano) - Beta
- </combo_item>
+ <combo_box name="language_combobox">
+ <combo_box.item name="System Default Language" label="Padrão do Sistema"/>
+ <combo_box.item name="English" label="English (Inglês)"/>
+ <combo_box.item name="Danish" label="Dansk (Dinamarquês) - Beta"/>
+ <combo_box.item name="Deutsch(German)" label="Deutsch (Alemão) - Beta"/>
+ <combo_box.item name="Spanish" label="Español (Espanhol) - Beta"/>
+ <combo_box.item name="French" label="Français (Francês) - Beta"/>
+ <combo_box.item name="Italian" label="Italiano - Beta"/>
+ <combo_box.item name="Hungarian" label="Magyar (Húngaro) - Beta"/>
+ <combo_box.item name="Dutch" label="Nederlands (Holandês) - Beta"/>
+ <combo_box.item name="Polish" label="Polski (Polonês) - Beta"/>
+ <combo_box.item name="Portugese" label="Português - Beta"/>
+ <combo_box.item name="Russian" label="РуÑÑкий (Russo) - Beta"/>
+ <combo_box.item name="Turkish" label="Türkçe (Turco) - Beta"/>
+ <combo_box.item name="Ukrainian" label="УкраїнÑька (Ucraniano) - Beta"/>
+ <combo_box.item name="Chinese" label="中文 (简体) (Chinês) - Beta"/>
+ <combo_box.item name="(Japanese)" label="日本語 (Japonês) - Beta"/>
+ <combo_box.item name="(Korean)" label="한국어 (Coreano) - Beta"/>
</combo_box>
<check_box label="Compartilhar a linguagem com objetos" name="language_is_public" tool_tip="Isto permite que os objetos no mundo conheçam sua linguagem preferida."/>
</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml
index 44bfb2d18e..d7982ab940 100644
--- a/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml
@@ -3,27 +3,17 @@
<button label="?" name="GraphicsPreferencesHelpButton"/>
<check_box label="Execute Second Life em uma janela" name="windowed mode"/>
<text_editor bottom="-56" height="40" name="FullScreenInfo" width="480">
- Se desmarcado, o visualizador irá exibir em tela inteira quando fizer o acesso.
+ Se desmarcado, o visualizador exibirá tela inteira quando fizer o acesso.
</text_editor>
<text name="WindowSizeLabel">
Tamanho da Janela:
</text>
<combo_box name="windowsize combo">
- <combo_item name="640x480">
- 640x480
- </combo_item>
- <combo_item name="800x600">
- 800x600
- </combo_item>
- <combo_item name="720x480">
- 720x480 (NTSC)
- </combo_item>
- <combo_item name="768x576">
- 768x576 (PAL)
- </combo_item>
- <combo_item name="1024x768">
- 1024x768
- </combo_item>
+ <combo_box.item name="640x480" label="640x480" />
+ <combo_box.item name="800x600" label="800x600" />
+ <combo_box.item name="720x480" label="720x480 (NTSC)" />
+ <combo_box.item name="768x576" label="768x576 (PAL)" />
+ <combo_box.item name="1024x768" label="1024x768" />
</combo_box>
<text name="DisplayResLabel">
Resolução de Display:
@@ -32,18 +22,10 @@
Relação de Aspecto:
</text>
<combo_box name="aspect_ratio" tool_tip="largura / altura">
- <combo_item length="1" name="4:3(StandardCRT)" type="string">
- 4:3 (CRT Padrão)
- </combo_item>
- <combo_item length="1" name="5:4(1280x1024LCD)" type="string">
- 5:4 (1280x1024 LCD)
- </combo_item>
- <combo_item name="8:5(Widescreen)">
- 8:5 (tela ampla)
- </combo_item>
- <combo_item length="1" name="16:9(Widescreen)" type="string">
- 16:9 (tela ampla)
- </combo_item>
+ <combo_box.item name="4:3(StandardCRT)" label="4:3 (CRT Padrão)" />
+ <combo_box.item name="5:4(1280x1024LCD)" label="5:4 (1280x1024 LCD)" />
+ <combo_box.item name="8:5(Widescreen)" label="8:5 (tela ampla)" />
+ <combo_box.item name="16:9(Widescreen)" label="16:9 (tela ampla)" />
</combo_box>
<check_box label="Auto-detectar a relação" name="aspect_auto_detect"/>
<text name="HigherText">
@@ -74,7 +56,8 @@ rápido
<text name="QualityText2">
Qualidade
</text>
- <check_box label="Padrão" left="395" name="CustomSettings"/>
+ <check_box label="Personalizar" left="395" name="CustomSettings"/>
+ <panel name="CustomGraphics Panel">
<text name="ShadersText">
Sombreadores:
</text>
@@ -86,18 +69,10 @@ rápido
Detalhes de Reflexão:
</text>
<radio_group name="ReflectionDetailRadio">
- <radio_item name="0">
- Terreno e Ãrvores
- </radio_item>
- <radio_item name="1">
- Todos os objetos estáticos
- </radio_item>
- <radio_item name="2">
- Todos os avatares e Objetos
- </radio_item>
- <radio_item name="3">
- Tudo
- </radio_item>
+ <radio_item name="0" label="Terreno e Ãrvores" />
+ <radio_item name="1" label="Todos os objetos estáticos" />
+ <radio_item name="2" label="Todos os avatares e Objetos" />
+ <radio_item name="3" label="Tudo" />
</radio_group>
<text name="AvatarRenderingText">
Renderização de Avatar:
@@ -111,18 +86,18 @@ rápido
<text name="DrawDistanceMeterText2">
m
</text>
- <slider label="Distancia de desenho:" label_width="146" name="DrawDistance" width="255"/>
- <slider label="Contador máx. de partículas:" label_width="146" name="MaxParticleCount" width="262"/>
- <slider label="Qualidade de Pós-processamento:" label_width="146" name="RenderPostProcess" width="223"/>
+ <slider label="Distancia de desenho:" label_width="150" name="DrawDistance" width="255"/>
+ <slider label="Contador máx. de partículas:" label_width="150" name="MaxParticleCount" width="262"/>
+ <slider label="Qualidade de Pós-processamento:" label_width="178" name="RenderPostProcess" width="223"/>
<text name="MeshDetailText">
Detalhes de Malha:
</text>
- <slider label="Objetos:" name="ObjectMeshDetail"/>
- <slider label="Primitivas Flexiveis:" name="FlexibleMeshDetail"/>
- <slider label="Ãrvores:" name="TreeMeshDetail"/>
- <slider label="Avatares:" name="AvatarMeshDetail"/>
- <slider label="Terreno:" name="TerrainMeshDetail"/>
- <slider label="Céu:" name="SkyMeshDetail"/>
+ <slider label=" Objetos:" name="ObjectMeshDetail"/>
+ <slider label=" Primitivas Flexiveis:" name="FlexibleMeshDetail"/>
+ <slider label=" Ãrvores:" name="TreeMeshDetail"/>
+ <slider label=" Avatares:" name="AvatarMeshDetail"/>
+ <slider label=" Terreno:" name="TerrainMeshDetail"/>
+ <slider label=" Céu:" name="SkyMeshDetail"/>
<text name="PostProcessText">
Baixo
</text>
@@ -148,30 +123,23 @@ rápido
Detalhes de Iluminação:
</text>
<radio_group name="LightingDetailRadio">
- <radio_item name="SunMoon">
- Sol e Lua apenas
- </radio_item>
- <radio_item name="LocalLights">
- Luzes locais nas proximidades
- </radio_item>
+ <radio_item name="SunMoon" label="Sol e Lua apenas" />
+ <radio_item name="LocalLights" label="Luzes locais nas proximidades" />
</radio_group>
<text name="TerrainDetailText">
Detalhe do Terreno:
</text>
<radio_group left_delta="45" name="TerrainDetailRadio" width="276">
- <radio_item name="0">
- Baixo
- </radio_item>
- <radio_item name="2">
- Alto
- </radio_item>
+ <radio_item name="0" label="Baixo" />
+ <radio_item name="2" label="Alto" />
</radio_group>
- <button label="Configurações Recomendadas" name="Defaults"/>
+ </panel>
+ <button label="Configurações Recomendadas" name="Defaults" width="190" left="110"/>
<button label="Opções de Hardware" label_selected="Opções de Hardware" name="GraphicsHardwareButton"/>
- <string name="resolution_format">
+ <panel.string name="resolution_format">
[RES_X] x [RES_Y]
- </string>
- <string name="aspect_ratio_text">
+ </panel.string>
+ <panel.string name="aspect_ratio_text">
[NUM]:[DEN]
- </string>
+ </panel.string>
</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/pt/panel_preferences_privacy.xml
new file mode 100644
index 0000000000..84c6c934c8
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_preferences_privacy.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Comunicação" name="im">
+ <text name="text_box">
+ Minha situação online:
+ </text>
+ <check_box label="Apenas meus Amigos e Grupos podem me ver online" name="online_visibility"/>
+ <text name="text_box2">
+ Opções MI:
+ </text>
+ <string name="log_in_to_change">
+ Logar para Alterar
+ </string>
+ <check_box label="Enviar MI para o e-mail ([EMAIL])" name="send_im_to_email"/>
+ <check_box label="Incluir MIs no console do chat" name="include_im_in_chat_console"/>
+ <check_box label="Mostrar data e hora na MI" name="show_timestamps_check"/>
+ <check_box label="Mostrar notificação de Amigo online" name="friends_online_notify_checkbox"/>
+ <text name="text_box3" width="134">
+ Resposta no Modo
+Ocupado:
+ </text>
+ <text name="text_box4">
+ Opções de Registro:
+ </text>
+ <check_box label="Salvar um registro das MIs em meu computador" name="log_instant_messages"/>
+ <check_box label="Mostrar a hora nas MIs" name="log_instant_messages_timestamp"/>
+ <check_box label="Mostrar o final da última conversa em MI" name="log_show_history"/>
+ <check_box label="Salvar um registro da Conversa local em meu computador" name="log_chat"/>
+ <check_box label="Mostrar a hora no registro da Conversa local" name="log_chat_timestamp"/>
+ <check_box label="Mostrar MIs recebidas no registro de Conversa local" name="log_chat_IM"/>
+ <check_box label="Incluir data e hora" name="log_date_timestamp"/>
+ <button label="Mudar Local" label_selected="Alterar Caminho" name="log_path_button" width="120"/>
+ <line_editor left="278" name="log_path_string" right="-20"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_setup.xml b/indra/newview/skins/default/xui/pt/panel_preferences_setup.xml
new file mode 100644
index 0000000000..3c94090131
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_preferences_setup.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Câmera" name="Input panel">
+ <text name=" Mouselook Options:">
+ Mouselook:
+ </text>
+ <text name=" Mouse Sensitivity:">
+ Sensibilidade do Mouse:
+ </text>
+ <check_box label="Inverter o Mouse" name="invert_mouse"/>
+ <text name=" Auto Fly Options:">
+ Vôo Automático:
+ </text>
+ <check_box label="Voar/Aterrissar pressionando teclas para cima/baixo" name="automatic_fly"/>
+ <text name=" Camera Options:">
+ Opções de Câmera:
+ </text>
+ <text name="camera_fov_label" width="218">
+ Angulo de Visão da Câmera:
+ </text>
+ <slider bottom_delta="-6" width="128" left="360" name="camera_fov" />
+ <text name="Camera Follow Distance:" width="218">
+ Distância de Acompanhamento da Camêra:
+ </text>
+ <slider bottom_delta="-6" width="128" left="360" name="camera_offset_scale" />
+ <check_box label="Edição automática do movimento da câmera" name="edit_camera_movement" tool_tip="Usar posicionamento automático da câmera quando entrar e sair do modo de edição"/>
+ <check_box label="Movimento Automático da Câmera na edição de aparência" name="appearance_camera_movement" tool_tip="Usar posicionamento automático da câmera em modo de edição"/>
+ <text name="text2">
+ Opções de Exibição
+do Avatar:
+ </text>
+ <check_box label="Mostra o avatar em primeira pessoa" name="first_person_avatar_visible"/>
+ <button bottom_delta="-40" label="Configuração do Joystick" name="joystick_setup_button" width="165"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_sound.xml b/indra/newview/skins/default/xui/pt/panel_preferences_sound.xml
new file mode 100644
index 0000000000..5574679cde
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_preferences_sound.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Ãudio &amp; Vídeo" name="Preference Media panel">
+ <slider label="Mestre" name="System Volume"/>
+ <slider label="Ambiente" name="Wind Volume"/>
+ <slider label="Sons" name="SFX Volume"/>
+ <slider label="Mídia" name="Media Volume"/>
+ <slider label="UI" name="UI Volume"/>
+ <slider label="Música" name="Music Volume"/>
+ <slider label="Voz" name="Voice Volume"/>
+ <text_editor name="voice_unavailable">
+ Bate-papo de Voz nâo está disponível
+ </text_editor>
+ <check_box label="Habilitar bate-papo de Voz" name="enable_voice_check"/>
+ <radio_group name="ear_location">
+ <radio_item name="0" label="Ouvir o bate-papo de voz pela posição de câmera" />
+ <radio_item name="1" label="Ouvir o bate-papo de voz pela posição do avatar" />
+ </radio_group>
+ <button label="Configurações do dispositivo" name="device_settings_btn" width="180"/>
+ <text name="muting_text">
+ Volume:
+ </text>
+ <text name="streaming_prefs_text">
+ Preferências de
+Streaming:
+ </text>
+ <text name="audio_prefs_text">
+ Preferências de Ãudio:
+ </text>
+ <panel label="Volume" name="Volume Panel"/>
+ <check_box label="Tocar música em streaming" name="streaming_music"/>
+ <check_box label="Tocar streaming de Mídia" name="streaming_video"/>
+ <check_box label="Tocar mídia automaticamente" name="auto_streaming_video"/>
+ <check_box label="Silenciar Ãudio quando minimizar janela" name="mute_when_minimized"/>
+ <slider label="Efeito Doppler" name="Doppler Effect"/>
+ <slider label="Fator Distância" name="Distance Factor"/>
+ <slider label="Fator Rolloff" name="Rolloff Factor"/>
+ <spinner label="Mudar nível de alerta de L$" name="L$ Change Threshold" label_width="165" width="229"/>
+ <spinner label="Mudar nível de alerta de Saúde" name="Health Change Threshold" label_width="165" width="229"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_profile.xml b/indra/newview/skins/default/xui/pt/panel_profile.xml
new file mode 100644
index 0000000000..ff53aa6a41
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_profile.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_profile">
+ <string name="CaptionTextAcctInfo">
+ [ACCTTYPE]
+[PAYMENTINFO] [AGEVERIFICATION]
+ </string>
+ <string name="payment_update_link_url">
+ http://www.secondlife.com/account/billing.php?lang=pt-BR
+ </string>
+ <string name="partner_edit_link_url">
+ http://www.secondlife.com/account/partners.php?lang=pt
+ </string>
+ <string name="my_account_link_url" value="http://secondlife.com/my/account/index.php?lang=pt-BR"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_region_covenant.xml b/indra/newview/skins/default/xui/pt/panel_region_covenant.xml
index 6218e4eafb..4977a1fac9 100644
--- a/indra/newview/skins/default/xui/pt/panel_region_covenant.xml
+++ b/indra/newview/skins/default/xui/pt/panel_region_covenant.xml
@@ -22,20 +22,22 @@
Última modificação: Quarta, 31 de dezembro de 1969 às 16:00:00 horas
</text>
<button label="?" name="covenant_help"/>
- <text_editor name="covenant_editor">
+ <text_editor name="covenant_editor" bottom="-247" height="162" >
Não há nenhuma regra fornecida para esta Propriedade.
</text_editor>
<button label="Resetar" name="reset_covenant"/>
<text bottom="-25" name="covenant_help_text">
- As mudanças das regras serão mostradas em todos os lotes da propriedade.
+ As mudanças das regras serão mostradas em todos os lotes
+ da propriedade.
</text>
- <text name="covenant_instructions">
- Arraste e solte um notecard, para mudar as Regras desta Propriedade.
+ <text bottom_delta="-36" name="covenant_instructions">
+ Arraste e solte um notecard, para mudar as Regras desta
+ Propriedade.
</text>
- <text name="region_section_lbl">
+ <text bottom_delta="-36" name="region_section_lbl">
Região:
</text>
- <text bottom_delta="-31" name="region_name_lbl">
+ <text name="region_name_lbl">
Nome:
</text>
<text name="region_name_text">
@@ -72,9 +74,11 @@
Terras compradas na região não poderão ser revendidas.
</string>
<string name="can_change">
- O terreno comprado nesta região pode ser compartilhado ou subdividido.
+ O terreno comprado nesta região pode ser compartilhado ou
+subdividido.
</string>
<string name="can_not_change">
- O terreno comprado nesta região não pode ser compartilhado ou subdividido.
+ O terreno comprado nesta região não pode ser compartilhado
+ou subdividido.
</string>
</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_region_debug.xml b/indra/newview/skins/default/xui/pt/panel_region_debug.xml
index 93c5d27648..724df20155 100644
--- a/indra/newview/skins/default/xui/pt/panel_region_debug.xml
+++ b/indra/newview/skins/default/xui/pt/panel_region_debug.xml
@@ -13,7 +13,7 @@
<check_box label="Desabilitar física" name="disable_physics_check" tool_tip="Desabilitar toda a físíca nesta região"/>
<button label="?" name="disable_physics_help"/>
<button label="Aplicar" name="apply_btn"/>
- <text name="objret_text_lbl">
+ <text name="objret_text_lbl" width="130">
Retornar objeto
</text>
<text name="resident_text_lbl">
@@ -30,10 +30,10 @@
<check_box label="Retornar apenas aqueles objetos na terra de alguém" name="return_other_land" tool_tip="Retornar apenas objetos que estejam na terra pertencente a alguém"/>
<check_box label="Retornar objetos em cada região desta propriedade" name="return_estate_wide" tool_tip="Retornar objetos em todas as regiões que constituem esta propriedade"/>
<button label="Retornar" name="return_btn"/>
- <button label="Pegar os principais colidentes..." name="top_colliders_btn" tool_tip="Lista dos objetos que experimentam as mais potenciais colisões"/>
- <button label="?" name="top_colliders_help"/>
- <button label="Pegar Principais Scripts..." name="top_scripts_btn" tool_tip="Lista de objetos gastando mais tempo rodando scripts"/>
- <button label="?" name="top_scripts_help"/>
+ <button width="280" label="Pegar os principais colidentes..." name="top_colliders_btn" tool_tip="Lista dos objetos que experimentam as mais potenciais colisões"/>
+ <button label="?" name="top_colliders_help" left="297"/>
+ <button width="280" label="Pegar Principais Scripts..." name="top_scripts_btn" tool_tip="Lista de objetos gastando mais tempo rodando scripts"/>
+ <button label="?" name="top_scripts_help" left="297"/>
<button label="Reiniciar a Região" name="restart_btn" tool_tip="Dar 2 minutos de contagem regressiva e reiniciar a região"/>
<button label="?" name="restart_help"/>
<button label="Atrasar o Reinicio" name="cancel_restart_btn" tool_tip="Atrasar o reinicio da região por uma hora"/>
diff --git a/indra/newview/skins/default/xui/pt/panel_region_estate.xml b/indra/newview/skins/default/xui/pt/panel_region_estate.xml
index c236b95ca1..f43402be15 100644
--- a/indra/newview/skins/default/xui/pt/panel_region_estate.xml
+++ b/indra/newview/skins/default/xui/pt/panel_region_estate.xml
@@ -24,9 +24,9 @@ todas as regiões desta propriedade.
<check_box label="Permitir acesso público" name="externally_visible_check"/>
<button label="?" name="externally_visible_help"/>
<text name="Only Allow">
- Acesso restrito a:
+ Acesso restrito a Residentes...
</text>
- <check_box label="Residentes com informações de pagamento em arquivo" name="limit_payment" tool_tip="Banir residentes não identificados."/>
+ <check_box label="com info. de pagamento em arquivo" name="limit_payment" tool_tip="Banir residentes não identificados."/>
<check_box label="Adultos com idade verificada" name="limit_age_verified" tool_tip="Banir residentes que não tenham confirmado a sua idade. Ver support.secondlife.com para mais informações."/>
<check_box label="Permitir conversa de voz" name="voice_chat_check"/>
<button label="?" name="voice_chat_help"/>
diff --git a/indra/newview/skins/default/xui/pt/panel_region_general.xml b/indra/newview/skins/default/xui/pt/panel_region_general.xml
index 6873d4ac98..1a06d91aa8 100644
--- a/indra/newview/skins/default/xui/pt/panel_region_general.xml
+++ b/indra/newview/skins/default/xui/pt/panel_region_general.xml
@@ -40,15 +40,9 @@
Classificação:
</text>
<combo_box label="Mature" name="access_combo">
- <combo_item name="Adult">
- Adult
- </combo_item>
- <combo_item name="Mature">
- Mature
- </combo_item>
- <combo_item name="PG">
- PG
- </combo_item>
+ <combo_box.item label="Adult" name="Adult"/>
+ <combo_box.item label="Mature" name="Mature"/>
+ <combo_box.item label="PG" name="PG"/>
</combo_box>
<button label="?" name="access_help"/>
<button label="Aplicar" name="apply_btn"/>
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 9b8fc48fb9..b9b0e9d90f 100644
--- a/indra/newview/skins/default/xui/pt/panel_region_terrain.xml
+++ b/indra/newview/skins/default/xui/pt/panel_region_terrain.xml
@@ -8,9 +8,9 @@
</text>
<spinner label="Altura da água" name="water_height_spin"/>
<button label="?" name="water_height_help"/>
- <spinner label="Limite do aumento do terreno" name="terrain_raise_spin"/>
+ <spinner label="Limite do aumento do &#10;terreno" name="terrain_raise_spin"/>
<button label="?" name="terrain_raise_help"/>
- <spinner label="Limite mais baixo do terreno" name="terrain_lower_spin"/>
+ <spinner label="Limite mais baixo do &#10;terreno" name="terrain_lower_spin" bottom_delta="-34"/>
<button label="?" name="terrain_lower_help"/>
<check_box label="Usar o sol da propriedade" name="use_estate_sun_check"/>
<button label="?" name="use_estate_sun_help"/>
@@ -18,10 +18,10 @@
<button label="?" name="fixed_sun_help"/>
<slider label="Fase" name="sun_hour_slider"/>
<button label="Aplicar" name="apply_btn"/>
- <button label="Download de terreno RAW ..." name="download_raw_btn" tool_tip="Não disponível aos gerentes, somente aos proprietários."/>
+ <button label="Download de terreno RAW..." name="download_raw_btn" tool_tip="Não disponível aos gerentes, somente aos proprietários."/>
<button label="?" name="download_raw_help"/>
<button label="Upload de terreno RAW..." name="upload_raw_btn" tool_tip="Não disponível aos gerentes, somente aos proprietários."/>
<button label="?" name="upload_raw_help"/>
- <button label="Nivelar o terreno" name="bake_terrain_btn" tool_tip="Ajustar terreno atual como o ponto médio para os limites de aumento/decréscimo"/>
- <button label="?" name="bake_terrain_help"/>
+ <button width="170" label="Nivelar o terreno" name="bake_terrain_btn" tool_tip="Ajustar terreno atual como o ponto médio para os limites de aumento/decréscimo"/>
+ <button left="190" label="?" name="bake_terrain_help"/>
</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_region_texture.xml b/indra/newview/skins/default/xui/pt/panel_region_texture.xml
index 8d7bdfe97b..4787b59a8d 100644
--- a/indra/newview/skins/default/xui/pt/panel_region_texture.xml
+++ b/indra/newview/skins/default/xui/pt/panel_region_texture.xml
@@ -6,7 +6,7 @@
<text name="region_text">
desconhecido
</text>
- <text name="detail_texture_text">
+ <text name="detail_texture_text" width="380">
Texturas de Terreno (requer 512x512, arquivos 24 bit .tga )
</text>
<text name="height_text_lbl">
diff --git a/indra/newview/skins/default/xui/pt/panel_scrolling_param.xml b/indra/newview/skins/default/xui/pt/panel_scrolling_param.xml
index d5b67884c9..87e6d16056 100644
--- a/indra/newview/skins/default/xui/pt/panel_scrolling_param.xml
+++ b/indra/newview/skins/default/xui/pt/panel_scrolling_param.xml
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="LLScrollingPanelParam">
- <text length="1" name="Loading..." type="string">
+ <text name="Loading...">
Carregando...
</text>
- <text length="1" name="Loading...2" type="string">
+ <text name="Loading...2">
Carregando...
</text>
<slider label="[DESC]" name="param slider"/>
diff --git a/indra/newview/skins/default/xui/pt/panel_status_bar.xml b/indra/newview/skins/default/xui/pt/panel_status_bar.xml
index 2a5108b4cb..7f3d2b34a6 100644
--- a/indra/newview/skins/default/xui/pt/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/pt/panel_status_bar.xml
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="status">
- <text length="1" name="ParcelNameText" tool_tip="Nome do pedaço de terra em que você está. Clique Sobre a Terra para informações." type="string">
+ <text name="ParcelNameText" tool_tip="Nome do pedaço de terra em que você está. Clique Sobre a Terra para informações.">
Nome do pedaço de terra vai aqui
</text>
- <text length="1" name="BalanceText" tool_tip="Saldo" type="string">
+ <text name="BalanceText" tool_tip="Saldo">
Carregando...
</text>
<button label="" label_selected="" name="buycurrency" tool_tip="Comprar dinheiro"/>
- <text length="12" name="TimeText" tool_tip="Hora atual (do Pacífico)" type="string">
+ <text name="TimeText" tool_tip="Hora atual (do Pacífico)">
12:00 AM
</text>
<string name="StatBarDaysOfWeek">
@@ -18,7 +18,7 @@
</string>
<button label="" label_selected="" name="scriptout" tool_tip="Erros e avisos do Script"/>
<button label="" label_selected="" name="health" tool_tip="Saúde"/>
- <text length="1" name="HealthText" tool_tip="Saúde" type="string">
+ <text name="HealthText" tool_tip="Saúde">
100%
</text>
<button label="" label_selected="" name="no_fly" tool_tip="Não é permitido Voar"/>
@@ -27,8 +27,8 @@
<button label="" label_selected="" name="restrictpush" tool_tip="Não Empurrar"/>
<button label="" label_selected="" name="status_no_voice" tool_tip="Voz não disponível aqui"/>
<button label="" label_selected="" name="buyland" tool_tip="Comprar este lote"/>
- <line_editor label="Buscar" name="search_editor" tool_tip="Buscar no Second Life"/>
- <button label="" label_selected="" name="search_btn" tool_tip="Buscar no Second Life"/>
+ <line_editor label="Buscar" name="search_editor" tool_tip="Buscar no [SECOND_LIFE]"/>
+ <button label="" label_selected="" name="search_btn" tool_tip="Buscar no [SECOND_LIFE]"/>
<string name="packet_loss_tooltip">
Perda de pacote
</string>
diff --git a/indra/newview/skins/default/xui/pt/panel_world_map.xml b/indra/newview/skins/default/xui/pt/panel_world_map.xml
new file mode 100644
index 0000000000..2fda713ec7
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_world_map.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="world_map">
+ <panel.string name="world_map_north">
+ N
+ </panel.string>
+ <panel.string name="world_map_east">
+ L
+ </panel.string>
+ <panel.string name="world_map_west">
+ O
+ </panel.string>
+ <panel.string name="world_map_south">
+ S
+ </panel.string>
+ <panel.string name="world_map_southeast">
+ SE
+ </panel.string>
+ <panel.string name="world_map_northeast">
+ NE
+ </panel.string>
+ <panel.string name="world_map_southwest">
+ SO
+ </panel.string>
+ <panel.string name="world_map_northwest">
+ NO
+ </panel.string>
+ <text label="N" name="floater_map_north" text="N">
+ N
+ </text>
+ <text label="L" name="floater_map_east" text="L">
+ L
+ </text>
+ <text label="O" name="floater_map_west" text="O">
+ O
+ </text>
+ <text label="S" name="floater_map_south" text="S">
+ S
+ </text>
+ <text label="SE" name="floater_map_southeast" text="SE">
+ SE
+ </text>
+ <text label="NE" name="floater_map_northeast" text="NE">
+ NE
+ </text>
+ <text label="SO" name="floater_map_southwest" text="SO">
+ SO
+ </text>
+ <text label="NO" name="floater_map_northwest" text="NO">
+ NO
+ </text>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml
index 8542fc6c0e..9acfce99dd 100644
--- a/indra/newview/skins/default/xui/pt/strings.xml
+++ b/indra/newview/skins/default/xui/pt/strings.xml
@@ -4,6 +4,7 @@
For example, the strings used in avatar chat bubbles, and strings
that are returned from one component and may appear in many places-->
<strings>
+ <string name="create_account_url">http://join.secondlife.com/index.php?lang=pt-BR</string>
<string name="LoginInProgress">
Fazendo Login. [APP_NAME] pode parecer congelado. Por favor, aguarde.
</string>
@@ -483,4 +484,168 @@
<string name="choose_the_directory">
Escolher Diretório
</string>
+ <string name="accel-mac-control">
+ &#8963;
+ </string>
+ <string name="accel-mac-command">
+ &#8984;
+ </string>
+ <string name="accel-mac-option">
+ &#8997;
+ </string>
+ <string name="accel-mac-shift">
+ &#8679;
+ </string>
+ <string name="accel-win-control">
+ Ctrl+
+ </string>
+ <string name="accel-win-alt">
+ Alt+
+ </string>
+ <string name="accel-win-shift">
+ Shift+
+ </string>
+ <string name="GraphicsQualityLow">
+ Baixo
+ </string>
+ <string name="GraphicsQualityMid">
+ Meio
+ </string>
+ <string name="GraphicsQualityHigh">
+ Alto
+ </string>
+
+ <!-- PARCEL_CATEGORY_UI_STRING -->
+ <string name="Linden Location">Locação Linden</string>
+ <string name="Adult">Adult</string>
+ <string name="Arts&amp;Culture">Artes e Cultura</string>
+ <string name="Business">Negócios</string>
+ <string name="Educational">Educacional</string>
+ <string name="Gaming">Jogos</string>
+ <string name="Hangout">Moradia</string>
+ <string name="Newcomer Friendly">Amigável a Novos Usuários</string>
+ <string name="Parks&amp;Nature">Parques &amp; Natureza</string>
+ <string name="Residential">Residencial</string>
+ <string name="Shopping">Compras</string>
+ <string name="Other">Outros</string>
+ <string name="ringing">
+ Conectando à conversa de Voz no mundo
+ </string>
+ <string name="connected">
+ Conectado
+ </string>
+ <string name="unavailable">
+ Voz não disponível na sua localização atual
+ </string>
+ <string name="hang_up">
+ Desconectado da conversa de Voz no mundo
+ </string>
+ <string name="ScriptQuestionCautionChatGranted">
+ &apos;[OBJECTNAME]&apos;, um objeto de &apos;[OWNERNAME]&apos;, localizado em [REGIONNAME] a [REGIONPOS], obteve permissão para: [PERMISSIONS].
+ </string>
+ <string name="ScriptQuestionCautionChatDenied">
+ &apos;[OBJECTNAME]&apos;, um objeto de &apos;[OWNERNAME]&apos;, localizado em [REGIONNAME] a [REGIONPOS], teve permissão negada para: [PERMISSIONS].
+ </string>
+ <string name="ScriptTakeMoney">
+ Tomar linden dólares (L$) de você
+ </string>
+ <string name="ActOnControlInputs">
+ Atue nas suas entradas de controle
+ </string>
+ <string name="RemapControlInputs">
+ Remapeie suas entradas de controle
+ </string>
+ <string name="AnimateYourAvatar">
+ Faça uma animação para o seu avatar
+ </string>
+ <string name="AttachToYourAvatar">
+ Anexe ao seu avatar
+ </string>
+ <string name="ReleaseOwnership">
+ Libere a propriedade e torne-a pública
+ </string>
+ <string name="LinkAndDelink">
+ Una e desuna de outros objetos
+ </string>
+ <string name="AddAndRemoveJoints">
+ Adicione e remova junções com outros objetos
+ </string>
+ <string name="ChangePermissions">
+ Modifique as permissões
+ </string>
+ <string name="TrackYourCamera">
+ Acompanhe sua câmera
+ </string>
+ <string name="ControlYourCamera">
+ Controle sua camera
+ </string>
+ <string name="only_user_message">
+ Você é o único usuário desta sessão.
+ </string>
+ <string name="offline_message">
+ [FIRST] [LAST] está offline.
+ </string>
+ <string name="invite_message">
+ Clique no botão [BUTTON NAME] para aceitar/ conectar a este bate-papo em voz.
+ </string>
+ <string name="generic_request_error">
+ Erro na requisição, por favor, tente novamente.
+ </string>
+ <string name="insufficient_perms_error">
+ Você não tem permissões suficientes.
+ </string>
+ <string name="session_does_not_exist_error">
+ A sessão deixou de existir
+ </string>
+ <string name="no_ability_error">
+ Você não possui esta habilidade.
+ </string>
+ <string name="no_ability">
+ Você não possui esta habilidade.
+ </string>
+ <string name="not_a_mod_error">
+ Você não é um moderador de sessão.
+ </string>
+ <string name="muted_error">
+ Um moderador do grupo desabilitou seu bate-papo em texto.
+ </string>
+ <string name="add_session_event">
+ Não foi possível adicionar usuários na sessão de bate-papo com [RECIPIENT].
+ </string>
+ <string name="message_session_event">
+ Não foi possível enviar sua mensagem na sessão de bate- papo com [RECIPIENT].
+ </string>
+ <string name="removed_from_group">
+ Você foi removido do grupo.
+ </string>
+ <string name="close_on_no_ability">
+ Você não possui mais a habilidade de estar na sessão de bate-papo.
+ </string>
+ <string name="AcctTypeResident">
+ Residente
+ </string>
+ <string name="AcctTypeTrial">
+ Teste
+ </string>
+ <string name="AcctTypeCharterMember">
+ Estatuto do membro
+ </string>
+ <string name="AcctTypeEmployee">
+ Contratado da Linden Lab
+ </string>
+ <string name="PaymentInfoUsed">
+ Infor. de pagamento utilizadas
+ </string>
+ <string name="PaymentInfoOnFile">
+ Infor. de pagamento no arquivo
+ </string>
+ <string name="NoPaymentInfoOnFile">
+ Sem infor. de pagamento no arquivo
+ </string>
+ <string name="AgeVerified">
+ Idade Verificada
+ </string>
+ <string name="NotAgeVerified">
+ Idade não Verificada
+ </string>
</strings>
diff --git a/indra/newview/skins/paths.xml b/indra/newview/skins/paths.xml
index 949cc145d9..3b91a904b0 100644
--- a/indra/newview/skins/paths.xml
+++ b/indra/newview/skins/paths.xml
@@ -1,4 +1,4 @@
<paths>
- <directory>xui/en-us</directory>
+ <directory>xui/en</directory>
<directory>xui/[LANGUAGE]</directory>
</paths> \ No newline at end of file
diff --git a/indra/newview/tests/llagentaccess_test.cpp b/indra/newview/tests/llagentaccess_test.cpp
index fc18f10e7d..e08193f785 100644
--- a/indra/newview/tests/llagentaccess_test.cpp
+++ b/indra/newview/tests/llagentaccess_test.cpp
@@ -3,59 +3,75 @@
* @brief LLAgentAccess tests
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
* Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
+
+#include "linden_common.h"
#include "../test/lltut.h"
#include "../llagentaccess.h"
-#include "llcontrolgroupreader.h"
+#include "llcontrol.h"
#include "indra_constants.h"
#include <iostream>
-class LLControlGroupReader_Test : public LLControlGroupReader
+//----------------------------------------------------------------------------
+// Implementation of enough of LLControlGroup to support the tests:
+
+static U32 test_preferred_maturity = SIM_ACCESS_PG;
+
+LLControlGroup::LLControlGroup(const std::string& name)
+ : LLInstanceTracker<LLControlGroup, std::string>(name)
{
-public:
- LLControlGroupReader_Test() : test_preferred_maturity(SIM_ACCESS_PG) {}
-
- virtual std::string getString(const std::string& name)
- {
- return "";
- }
- virtual std::string getText(const std::string& name)
- {
- return "";
- }
- virtual BOOL getBOOL(const std::string& name)
- {
- return false;
- }
- virtual S32 getS32(const std::string& name)
- {
- return 0;
- }
- virtual F32 getF32(const std::string& name)
- {
- return 0;
- }
- virtual U32 getU32(const std::string& name)
- {
- return test_preferred_maturity;
- }
-
- //--------------------------------------
- // Everything from here down is test code and not part of the interface
- void setPreferredMaturity(U32 m)
- {
- test_preferred_maturity = m;
- }
-private:
- U32 test_preferred_maturity;
-
-};
+}
+LLControlGroup::~LLControlGroup()
+{
+}
+
+// Implementation of just the LLControlGroup methods we requre
+BOOL LLControlGroup::declareU32(const std::string& name, U32 initial_val, const std::string& comment, BOOL persist)
+{
+ test_preferred_maturity = initial_val;
+ return true;
+}
+
+void LLControlGroup::setU32(const std::string& name, U32 val)
+{
+ test_preferred_maturity = val;
+}
+
+U32 LLControlGroup::getU32(const std::string& name)
+{
+ return test_preferred_maturity;
+}
+//----------------------------------------------------------------------------
+
namespace tut
{
struct agentaccess
@@ -69,20 +85,21 @@ namespace tut
template<> template<>
void agentaccess_object_t::test<1>()
{
- LLControlGroupReader_Test cgr;
+ LLControlGroup cgr("test");
+ cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE);
LLAgentAccess aa(cgr);
- cgr.setPreferredMaturity(SIM_ACCESS_PG);
+ cgr.setU32("PreferredMaturity", SIM_ACCESS_PG);
ensure("1 prefersPG", aa.prefersPG());
ensure("1 prefersMature", !aa.prefersMature());
ensure("1 prefersAdult", !aa.prefersAdult());
- cgr.setPreferredMaturity(SIM_ACCESS_MATURE);
+ cgr.setU32("PreferredMaturity", SIM_ACCESS_MATURE);
ensure("2 prefersPG", !aa.prefersPG());
ensure("2 prefersMature", aa.prefersMature());
ensure("2 prefersAdult", !aa.prefersAdult());
- cgr.setPreferredMaturity(SIM_ACCESS_ADULT);
+ cgr.setU32("PreferredMaturity", SIM_ACCESS_ADULT);
ensure("3 prefersPG", !aa.prefersPG());
ensure("3 prefersMature", aa.prefersMature());
ensure("3 prefersAdult", aa.prefersAdult());
@@ -91,7 +108,8 @@ namespace tut
template<> template<>
void agentaccess_object_t::test<2>()
{
- LLControlGroupReader_Test cgr;
+ LLControlGroup cgr("test");
+ cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE);
LLAgentAccess aa(cgr);
// make sure default is PG
@@ -140,7 +158,8 @@ namespace tut
template<> template<>
void agentaccess_object_t::test<3>()
{
- LLControlGroupReader_Test cgr;
+ LLControlGroup cgr("test");
+ cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE);
LLAgentAccess aa(cgr);
ensure("starts normal", !aa.isGodlike());
@@ -163,7 +182,8 @@ namespace tut
template<> template<>
void agentaccess_object_t::test<4>()
{
- LLControlGroupReader_Test cgr;
+ LLControlGroup cgr("test");
+ cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE);
LLAgentAccess aa(cgr);
ensure("1 pg to start", aa.wantsPGOnly());
@@ -188,12 +208,12 @@ namespace tut
ensure("2 mature pref pg", !aa.canAccessMature());
ensure("3 mature pref pg", !aa.canAccessAdult());
- cgr.setPreferredMaturity(SIM_ACCESS_MATURE);
+ cgr.setU32("PreferredMaturity", SIM_ACCESS_MATURE);
ensure("1 mature", !aa.wantsPGOnly());
ensure("2 mature", aa.canAccessMature());
ensure("3 mature", !aa.canAccessAdult());
- cgr.setPreferredMaturity(SIM_ACCESS_PG);
+ cgr.setU32("PreferredMaturity", SIM_ACCESS_PG);
ensure("1 mature pref pg", aa.wantsPGOnly());
ensure("2 mature pref pg", !aa.canAccessMature());
ensure("3 mature pref pg", !aa.canAccessAdult());
@@ -203,14 +223,14 @@ namespace tut
ensure("2 adult pref pg", !aa.canAccessMature());
ensure("3 adult pref pg", !aa.canAccessAdult());
- cgr.setPreferredMaturity(SIM_ACCESS_ADULT);
+ cgr.setU32("PreferredMaturity", SIM_ACCESS_ADULT);
ensure("1 adult", !aa.wantsPGOnly());
ensure("2 adult", aa.canAccessMature());
ensure("3 adult", aa.canAccessAdult());
// make sure that even if pref is high, if access is low we block access
// this shouldn't occur in real life but we want to be safe
- cgr.setPreferredMaturity(SIM_ACCESS_ADULT);
+ cgr.setU32("PreferredMaturity", SIM_ACCESS_ADULT);
aa.setMaturity('P');
ensure("1 pref adult, actual pg", aa.wantsPGOnly());
ensure("2 pref adult, actual pg", !aa.canAccessMature());
@@ -221,7 +241,8 @@ namespace tut
template<> template<>
void agentaccess_object_t::test<5>()
{
- LLControlGroupReader_Test cgr;
+ LLControlGroup cgr("test");
+ cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE);
LLAgentAccess aa(cgr);
ensure("1 transition starts false", !aa.isInTransition());
@@ -229,6 +250,20 @@ namespace tut
ensure("2 transition now true", aa.isInTransition());
}
+ template<> template<>
+ void agentaccess_object_t::test<6>()
+ {
+ LLControlGroup cgr("test");
+ cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE);
+ LLAgentAccess aa(cgr);
+
+ cgr.setU32("PreferredMaturity", SIM_ACCESS_ADULT);
+ aa.setMaturity('M');
+ ensure("1 preferred maturity pegged to M when maturity is M", cgr.getU32("PreferredMaturity") == SIM_ACCESS_MATURE);
+
+ aa.setMaturity('P');
+ ensure("1 preferred maturity pegged to P when maturity is P", cgr.getU32("PreferredMaturity") == SIM_ACCESS_PG);
+ }
}
diff --git a/indra/newview/tests/llcapabilitylistener_test.cpp b/indra/newview/tests/llcapabilitylistener_test.cpp
new file mode 100644
index 0000000000..ca7d02fc68
--- /dev/null
+++ b/indra/newview/tests/llcapabilitylistener_test.cpp
@@ -0,0 +1,276 @@
+/**
+ * @file llcapabilitylistener_test.cpp
+ * @author Nat Goodspeed
+ * @date 2008-12-31
+ * @brief Test for llcapabilitylistener.cpp.
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "../llviewerprecompiledheaders.h"
+// Own header
+#include "../llcapabilitylistener.h"
+// STL headers
+#include <stdexcept>
+#include <map>
+#include <vector>
+// std headers
+// external library headers
+#include "boost/bind.hpp"
+// other Linden headers
+#include "../test/lltut.h"
+#include "../llcapabilityprovider.h"
+#include "lluuid.h"
+#include "tests/networkio.h"
+#include "tests/commtest.h"
+#include "tests/wrapllerrs.h"
+#include "message.h"
+#include "stringize.h"
+
+#if defined(LL_WINDOWS)
+#pragma warning(disable: 4355) // using 'this' in base-class ctor initializer expr
+#endif
+
+/*****************************************************************************
+* TestCapabilityProvider
+*****************************************************************************/
+struct TestCapabilityProvider: public LLCapabilityProvider
+{
+ TestCapabilityProvider(const LLHost& host):
+ mHost(host)
+ {}
+
+ std::string getCapability(const std::string& cap) const
+ {
+ CapMap::const_iterator found = mCaps.find(cap);
+ if (found != mCaps.end())
+ return found->second;
+ // normal LLViewerRegion lookup failure mode
+ return "";
+ }
+ void setCapability(const std::string& cap, const std::string& url)
+ {
+ mCaps[cap] = url;
+ }
+ LLHost getHost() const { return mHost; }
+ std::string getDescription() const { return "TestCapabilityProvider"; }
+
+ LLHost mHost;
+ typedef std::map<std::string, std::string> CapMap;
+ CapMap mCaps;
+};
+
+/*****************************************************************************
+* Dummy LLMessageSystem methods
+*****************************************************************************/
+/*==========================================================================*|
+// This doesn't work because we're already linking in llmessage.a, and we get
+// duplicate-symbol errors from the linker. Perhaps if I wanted to go through
+// the exercise of providing dummy versions of every single symbol defined in
+// message.o -- maybe some day.
+typedef std::vector< std::pair<std::string, std::string> > StringPairVector;
+StringPairVector call_history;
+
+S32 LLMessageSystem::sendReliable(const LLHost& host)
+{
+ call_history.push_back(StringPairVector::value_type("sendReliable", stringize(host)));
+ return 0;
+}
+|*==========================================================================*/
+
+/*****************************************************************************
+* TUT
+*****************************************************************************/
+namespace tut
+{
+ struct llcapears_data: public commtest_data
+ {
+ TestCapabilityProvider provider;
+ LLCapabilityListener regionListener;
+ LLEventPump& regionPump;
+
+ llcapears_data():
+ provider(host),
+ regionListener("testCapabilityListener", NULL, provider, LLUUID(), LLUUID()),
+ regionPump(regionListener.getCapAPI())
+ {
+ provider.setCapability("good", server + "capability-test");
+ provider.setCapability("fail", server + "fail");
+ }
+ };
+ typedef test_group<llcapears_data> llcapears_group;
+ typedef llcapears_group::object llcapears_object;
+ llcapears_group llsdmgr("llcapabilitylistener");
+
+ template<> template<>
+ void llcapears_object::test<1>()
+ {
+ LLSD request, body;
+ body["data"] = "yes";
+ request["payload"] = body;
+ request["reply"] = replyPump.getName();
+ request["error"] = errorPump.getName();
+ std::string threw;
+ try
+ {
+ WrapLL_ERRS capture;
+ regionPump.post(request);
+ }
+ catch (const WrapLL_ERRS::FatalException& e)
+ {
+ threw = e.what();
+ }
+ ensure_contains("missing capability name", threw, "without 'message' key");
+ }
+
+ template<> template<>
+ void llcapears_object::test<2>()
+ {
+ LLSD request, body;
+ body["data"] = "yes";
+ request["message"] = "good";
+ request["payload"] = body;
+ request["reply"] = replyPump.getName();
+ request["error"] = errorPump.getName();
+ regionPump.post(request);
+ ensure("got response", netio.pump());
+ ensure("success response", success);
+ ensure_equals(result.asString(), "success");
+
+ body["status"] = 499;
+ body["reason"] = "custom error message";
+ request["message"] = "fail";
+ request["payload"] = body;
+ regionPump.post(request);
+ ensure("got response", netio.pump());
+ ensure("failure response", ! success);
+ ensure_equals(result["status"].asInteger(), body["status"].asInteger());
+ ensure_equals(result["reason"].asString(), body["reason"].asString());
+ }
+
+ template<> template<>
+ void llcapears_object::test<3>()
+ {
+ LLSD request, body;
+ body["data"] = "yes";
+ request["message"] = "unknown";
+ request["payload"] = body;
+ request["reply"] = replyPump.getName();
+ request["error"] = errorPump.getName();
+ std::string threw;
+ try
+ {
+ WrapLL_ERRS capture;
+ regionPump.post(request);
+ }
+ catch (const WrapLL_ERRS::FatalException& e)
+ {
+ threw = e.what();
+ }
+ ensure_contains("bad capability name", threw, "unsupported capability");
+ }
+
+ struct TestMapper: public LLCapabilityListener::CapabilityMapper
+ {
+ // Instantiator gets to specify whether mapper expects a reply.
+ // I'd really like to be able to test CapabilityMapper::buildMessage()
+ // functionality, too, but -- even though LLCapabilityListener accepts
+ // the LLMessageSystem* that it passes to CapabilityMapper --
+ // LLMessageSystem::sendReliable(const LLHost&) isn't virtual, so it's
+ // not helpful to pass a subclass instance. I suspect that making any
+ // LLMessageSystem methods virtual would provoke howls of outrage,
+ // given how heavily it's used. Nor can I just provide a local
+ // definition of LLMessageSystem::sendReliable(const LLHost&) because
+ // we're already linking in the rest of message.o via llmessage.a, and
+ // that produces duplicate-symbol link errors.
+ TestMapper(const std::string& replyMessage = std::string()):
+ LLCapabilityListener::CapabilityMapper("test", replyMessage)
+ {}
+ virtual void buildMessage(LLMessageSystem* msg,
+ const LLUUID& agentID,
+ const LLUUID& sessionID,
+ const std::string& capabilityName,
+ const LLSD& payload) const
+ {
+ msg->newMessageFast(_PREHASH_SetStartLocationRequest);
+ msg->nextBlockFast( _PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, agentID);
+ msg->addUUIDFast(_PREHASH_SessionID, sessionID);
+ msg->nextBlockFast( _PREHASH_StartLocationData);
+ // corrected by sim
+ msg->addStringFast(_PREHASH_SimName, "");
+ msg->addU32Fast(_PREHASH_LocationID, payload["HomeLocation"]["LocationId"].asInteger());
+/*==========================================================================*|
+ msg->addVector3Fast(_PREHASH_LocationPos,
+ ll_vector3_from_sdmap(payload["HomeLocation"]["LocationPos"]));
+ msg->addVector3Fast(_PREHASH_LocationLookAt,
+ ll_vector3_from_sdmap(payload["HomeLocation"]["LocationLookAt"]));
+|*==========================================================================*/
+ }
+ };
+
+ template<> template<>
+ void llcapears_object::test<4>()
+ {
+ TestMapper testMapper("WantReply");
+ LLSD request, body;
+ body["data"] = "yes";
+ request["message"] = "test";
+ request["payload"] = body;
+ request["reply"] = replyPump.getName();
+ request["error"] = errorPump.getName();
+ std::string threw;
+ try
+ {
+ WrapLL_ERRS capture;
+ regionPump.post(request);
+ }
+ catch (const WrapLL_ERRS::FatalException& e)
+ {
+ threw = e.what();
+ }
+ ensure_contains("capability mapper wants reply", threw, "unimplemented support for reply message");
+ }
+
+ template<> template<>
+ void llcapears_object::test<5>()
+ {
+ TestMapper testMapper;
+ std::string threw;
+ try
+ {
+ TestMapper testMapper2;
+ }
+ catch (const std::runtime_error& e)
+ {
+ threw = e.what();
+ }
+ ensure_contains("no dup cap mapper", threw, "DupCapMapper");
+ }
+}
diff --git a/indra/newview/tests/lldateutil_test.cpp b/indra/newview/tests/lldateutil_test.cpp
new file mode 100644
index 0000000000..7ba82fbd2c
--- /dev/null
+++ b/indra/newview/tests/lldateutil_test.cpp
@@ -0,0 +1,192 @@
+/**
+ * @file lldateutil_test.cpp
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../test/lltut.h"
+
+#include "../lldateutil.h"
+
+#include "lldate.h"
+#include "llstring.h" // LLStringUtil::format()
+#include "lltrans.h"
+#include "llui.h"
+
+#include <map>
+
+
+// Baked-in return values for getString()
+std::map< std::string, std::string > gString;
+
+// Baked-in return values for getCountString()
+// map of pairs of input xml_desc and integer count
+typedef std::pair< std::string, int > count_string_t;
+std::map< count_string_t, std::string > gCountString;
+
+std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args)
+{
+ std::string text = gString[xml_desc];
+ LLStringUtil::format(text, args);
+ return text;
+}
+
+std::string LLTrans::getCountString(const std::string& language, const std::string& xml_desc, S32 count)
+{
+ count_string_t key(xml_desc, count);
+ if (gCountString.find(key) == gCountString.end())
+ {
+ return std::string("Couldn't find ") + xml_desc;
+ }
+ return gCountString[ count_string_t(xml_desc, count) ];
+}
+
+std::string LLUI::getLanguage()
+{
+ return "en";
+}
+
+namespace tut
+{
+ struct dateutil
+ {
+ // Hard-code a "now" date so unit test doesn't change with
+ // current time. Because server strings are in Pacific time
+ // roll this forward 8 hours to compensate. This represents
+ // 2009-12-31T00:00:00Z UTC.
+ dateutil()
+ : mNow(std::string("2009-12-31T08:00:00Z"))
+ {
+ // copied from strings.xml
+ gString["YearsMonthsOld"] = "[AGEYEARS] [AGEMONTHS] old";
+ gString["YearsOld"] = "[AGEYEARS] old";
+ gString["MonthsOld"] = "[AGEMONTHS] old";
+ gString["WeeksOld"] = "[AGEWEEKS] old";
+ gString["DaysOld"] = "[AGEDAYS] old";
+ gString["TodayOld"] = "Joined today";
+
+ gCountString[ count_string_t("AgeYears", 1) ] = "1 year";
+ gCountString[ count_string_t("AgeYears", 2) ] = "2 years";
+ gCountString[ count_string_t("AgeMonths", 1) ] = "1 month";
+ gCountString[ count_string_t("AgeMonths", 2) ] = "2 months";
+ gCountString[ count_string_t("AgeMonths", 11) ]= "11 months";
+ gCountString[ count_string_t("AgeWeeks", 1) ] = "1 week";
+ gCountString[ count_string_t("AgeWeeks", 2) ] = "2 weeks";
+ gCountString[ count_string_t("AgeWeeks", 3) ] = "3 weeks";
+ gCountString[ count_string_t("AgeWeeks", 4) ] = "4 weeks";
+ gCountString[ count_string_t("AgeDays", 1) ] = "1 day";
+ gCountString[ count_string_t("AgeDays", 2) ] = "2 days";
+ }
+ LLDate mNow;
+ };
+
+ typedef test_group<dateutil> dateutil_t;
+ typedef dateutil_t::object dateutil_object_t;
+ tut::dateutil_t tut_dateutil("dateutil");
+
+ template<> template<>
+ void dateutil_object_t::test<1>()
+ {
+ set_test_name("Years");
+ ensure_equals("years + months",
+ LLDateUtil::ageFromDate("10/30/2007", mNow),
+ "2 years 2 months old" );
+ ensure_equals("years",
+ LLDateUtil::ageFromDate("12/31/2007", mNow),
+ "2 years old" );
+ ensure_equals("years",
+ LLDateUtil::ageFromDate("1/1/2008", mNow),
+ "1 year 11 months old" );
+ ensure_equals("single year + one month",
+ LLDateUtil::ageFromDate("11/30/2008", mNow),
+ "1 year 1 month old" );
+ ensure_equals("single year + a bit",
+ LLDateUtil::ageFromDate("12/12/2008", mNow),
+ "1 year old" );
+ ensure_equals("single year",
+ LLDateUtil::ageFromDate("12/31/2008", mNow),
+ "1 year old" );
+ }
+
+ template<> template<>
+ void dateutil_object_t::test<2>()
+ {
+ set_test_name("Months");
+ ensure_equals("months",
+ LLDateUtil::ageFromDate("10/30/2009", mNow),
+ "2 months old" );
+ ensure_equals("months 2",
+ LLDateUtil::ageFromDate("10/31/2009", mNow),
+ "2 months old" );
+ ensure_equals("single month",
+ LLDateUtil::ageFromDate("11/30/2009", mNow),
+ "1 month old" );
+ }
+
+ template<> template<>
+ void dateutil_object_t::test<3>()
+ {
+ set_test_name("Weeks");
+ ensure_equals("4 weeks",
+ LLDateUtil::ageFromDate("12/1/2009", mNow),
+ "4 weeks old" );
+ ensure_equals("weeks",
+ LLDateUtil::ageFromDate("12/17/2009", mNow),
+ "2 weeks old" );
+ ensure_equals("single week",
+ LLDateUtil::ageFromDate("12/24/2009", mNow),
+ "1 week old" );
+ }
+
+ template<> template<>
+ void dateutil_object_t::test<4>()
+ {
+ set_test_name("Days");
+ ensure_equals("days",
+ LLDateUtil::ageFromDate("12/29/2009", mNow),
+ "2 days old" );
+ ensure_equals("single day",
+ LLDateUtil::ageFromDate("12/30/2009", mNow),
+ "1 day old" );
+ ensure_equals("today",
+ LLDateUtil::ageFromDate("12/31/2009", mNow),
+ "Joined today" );
+ }
+
+ template<> template<>
+ void dateutil_object_t::test<5>()
+ {
+ set_test_name("2010 rollover");
+ LLDate now(std::string("2010-01-04T12:00:00Z"));
+ ensure_equals("days",
+ LLDateUtil::ageFromDate("12/13/2009", now),
+ "3 weeks old" );
+ }
+}
diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp
new file mode 100644
index 0000000000..7b28a3b72c
--- /dev/null
+++ b/indra/newview/tests/lllogininstance_test.cpp
@@ -0,0 +1,424 @@
+/**
+ * @file lllogininstance_test.cpp
+ * @brief Test for lllogininstance.cpp.
+ *
+ * $LicenseInfo:firstyear=2008&license=internal$
+ * Copyright (c) 2008, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "../llviewerprecompiledheaders.h"
+// Own header
+#include "../lllogininstance.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "../test/lltut.h"
+#include "llevents.h"
+
+#if defined(LL_WINDOWS)
+#pragma warning(disable: 4355) // using 'this' in base-class ctor initializer expr
+#endif
+
+// Constants
+const std::string VIEWERLOGIN_URI("viewerlogin_uri");
+const std::string VIEWERLOGIN_GRIDLABEL("viewerlogin_grid");
+
+const std::string APPVIEWER_SERIALNUMBER("appviewer_serialno");
+
+// Link seams.
+
+//-----------------------------------------------------------------------------
+static LLEventStream gTestPump("test_pump");
+
+#include "lllogin.h"
+static std::string gLoginURI;
+static LLSD gLoginCreds;
+static bool gDisconnectCalled = false;
+class LLLogin::Impl
+{
+};
+LLLogin::LLLogin() {}
+LLLogin::~LLLogin() {}
+LLEventPump& LLLogin::getEventPump() { return gTestPump; }
+void LLLogin::connect(const std::string& uri, const LLSD& credentials)
+{
+ gLoginURI = uri;
+ gLoginCreds = credentials;
+}
+
+void LLLogin::disconnect()
+{
+ gDisconnectCalled = true;
+}
+
+//-----------------------------------------------------------------------------
+#include "../llviewernetwork.h"
+unsigned char gMACAddress[MAC_ADDRESS_BYTES] = {'1','2','3','4','5','6'}; /* Flawfinder: ignore */
+
+LLViewerLogin::LLViewerLogin() {}
+LLViewerLogin::~LLViewerLogin() {}
+void LLViewerLogin::getLoginURIs(std::vector<std::string>& uris) const
+{
+ uris.push_back(VIEWERLOGIN_URI);
+}
+std::string LLViewerLogin::getGridLabel() const { return VIEWERLOGIN_GRIDLABEL; }
+
+//-----------------------------------------------------------------------------
+#include "../llviewercontrol.h"
+LLControlGroup gSavedSettings("Global");
+std::string gCurrentVersion = "invalid_version";
+
+LLControlGroup::LLControlGroup(const std::string& name) :
+ LLInstanceTracker<LLControlGroup, std::string>(name){}
+LLControlGroup::~LLControlGroup() {}
+void LLControlGroup::setBOOL(const std::string& name, BOOL val) {}
+BOOL LLControlGroup::getBOOL(const std::string& name) { return FALSE; }
+F32 LLControlGroup::getF32(const std::string& name) { return 0.0f; }
+U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only) { return 1; }
+void LLControlGroup::setString(const std::string& name, const std::string& val) {}
+std::string LLControlGroup::getString(const std::string& name) { return "test_string"; }
+BOOL LLControlGroup::declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, BOOL persist) { return TRUE; }
+BOOL LLControlGroup::declareString(const std::string& name, const std::string &initial_val, const std::string& comment, BOOL persist) { return TRUE; }
+
+#include "lluicolortable.h"
+void LLUIColorTable::saveUserSettings(void)const {}
+
+//-----------------------------------------------------------------------------
+#include "../llurlsimstring.h"
+LLURLSimString LLURLSimString::sInstance;
+bool LLURLSimString::parse() { return true; }
+
+//-----------------------------------------------------------------------------
+#include "llnotifications.h"
+#include "llfloaterreg.h"
+static std::string gTOSType;
+static LLEventPump * gTOSReplyPump = NULL;
+
+//static
+LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key, BOOL focus)
+{
+ gTOSType = name;
+ gTOSReplyPump = &LLEventPumps::instance().obtain(key["reply_pump"]);
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// LLNotifications
+class MockNotifications : public LLNotificationsInterface
+{
+ boost::function<void (const LLSD&, const LLSD&)> mResponder;
+ int mAddedCount;
+
+public:
+ MockNotifications() :
+ mResponder(0),
+ mAddedCount(0)
+ {
+ }
+
+ virtual ~MockNotifications() {}
+
+ /* virtual */ LLNotificationPtr add(
+ const std::string& name,
+ const LLSD& substitutions,
+ const LLSD& payload,
+ LLNotificationFunctorRegistry::ResponseFunctor functor)
+ {
+ mResponder = functor;
+ mAddedCount++;
+ return LLNotificationPtr((LLNotification*)NULL);
+ }
+
+ void sendYesResponse()
+ {
+ LLSD notification;
+ LLSD response;
+ response = 1;
+ mResponder(notification, response);
+ }
+
+ void sendNoResponse()
+ {
+ LLSD notification;
+ LLSD response;
+ response = 2;
+ mResponder(notification, response);
+ }
+
+ void sendBogusResponse()
+ {
+ LLSD notification;
+ LLSD response;
+ response = 666;
+ mResponder(notification, response);
+ }
+
+ int addedCount() { return mAddedCount; }
+};
+
+S32 LLNotification::getSelectedOption(const LLSD& notification, const LLSD& response)
+{
+ return response.asInteger();
+}
+
+// misc
+std::string xml_escape_string(const std::string& in)
+{
+ return in;
+}
+
+/*****************************************************************************
+* TUT
+*****************************************************************************/
+namespace tut
+{
+ struct lllogininstance_data
+ {
+ lllogininstance_data() : logininstance(LLLoginInstance::getInstance())
+ {
+ // Global initialization
+ gLoginURI.clear();
+ gLoginCreds.clear();
+ gDisconnectCalled = false;
+
+ gTOSType = ""; // Set to invalid value.
+ gTOSReplyPump = 0; // clear the callback.
+
+
+ gSavedSettings.declareBOOL("NoInventoryLibrary", FALSE, "", FALSE);
+ gSavedSettings.declareBOOL("ConnectAsGod", FALSE, "", FALSE);
+ gSavedSettings.declareBOOL("UseDebugMenus", FALSE, "", FALSE);
+ gSavedSettings.declareBOOL("ForceMandatoryUpdate", FALSE, "", FALSE);
+ gSavedSettings.declareString("ClientSettingsFile", "test_settings.xml", "", FALSE);
+ gSavedSettings.declareString("VersionChannelName", "test_version_string", "", FALSE);
+ gSavedSettings.declareString("NextLoginLocation", "", "", FALSE);
+ gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", FALSE);
+
+ credentials["first"] = "testfirst";
+ credentials["last"] = "testlast";
+ credentials["passwd"] = "testpass";
+
+ logininstance->setNotificationsInterface(&notifications);
+ }
+
+ LLLoginInstance* logininstance;
+ LLSD credentials;
+ MockNotifications notifications;
+ };
+
+ typedef test_group<lllogininstance_data> lllogininstance_group;
+ typedef lllogininstance_group::object lllogininstance_object;
+ lllogininstance_group llsdmgr("lllogininstance");
+
+ template<> template<>
+ void lllogininstance_object::test<1>()
+ {
+ set_test_name("Test Simple Success And Disconnect");
+
+ // Test default connect.
+ logininstance->connect(credentials);
+
+ ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);
+
+ // Dummy success response.
+ LLSD response;
+ response["state"] = "online";
+ response["change"] = "connect";
+ response["progress"] = 1.0;
+ response["transfer_rate"] = 7;
+ response["data"] = "test_data";
+
+ gTestPump.post(response);
+
+ ensure("Success response", logininstance->authSuccess());
+ ensure_equals("Test Response Data", logininstance->getResponse().asString(), "test_data");
+
+ logininstance->disconnect();
+
+ ensure_equals("Called Login Module Disconnect", gDisconnectCalled, true);
+
+ response.clear();
+ response["state"] = "offline";
+ response["change"] = "disconnect";
+ response["progress"] = 0.0;
+ response["transfer_rate"] = 0;
+ response["data"] = "test_data";
+
+ gTestPump.post(response);
+
+ ensure("Disconnected", !(logininstance->authSuccess()));
+ }
+
+ template<> template<>
+ void lllogininstance_object::test<2>()
+ {
+ set_test_name("Test User TOS/Critical message Interaction");
+
+ const std::string test_uri = "testing-uri";
+
+ // Test default connect.
+ logininstance->connect(test_uri, credentials);
+
+ // connect should call LLLogin::connect to init gLoginURI and gLoginCreds.
+ ensure_equals("Default connect uri", gLoginURI, "testing-uri");
+ ensure_equals("Default for agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), false);
+ ensure_equals("Default for read critical", gLoginCreds["params"]["read_critical"].asBoolean(), false);
+
+ // TOS failure response.
+ LLSD response;
+ response["state"] = "offline";
+ response["change"] = "fail.login";
+ response["progress"] = 0.0;
+ response["transfer_rate"] = 7;
+ response["data"]["reason"] = "tos";
+ gTestPump.post(response);
+
+ ensure_equals("TOS Dialog type", gTOSType, "message_tos");
+ ensure("TOS callback given", gTOSReplyPump != 0);
+ gTOSReplyPump->post(false); // Call callback denying TOS.
+ ensure("No TOS, failed auth", logininstance->authFailure());
+
+ // Start again.
+ logininstance->connect(test_uri, credentials);
+ gTestPump.post(response); // Fail for tos again.
+ gTOSReplyPump->post(true); // Accept tos, should reconnect w/ agree_to_tos.
+ ensure_equals("Accepted agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), true);
+ ensure("Incomplete login status", !logininstance->authFailure() && !logininstance->authSuccess());
+
+ // Fail connection, attempt connect again.
+ // The new request should have reset agree to tos to default.
+ response["data"]["reason"] = "key"; // bad creds.
+ gTestPump.post(response);
+ ensure("TOS auth failure", logininstance->authFailure());
+
+ logininstance->connect(test_uri, credentials);
+ ensure_equals("Reset to default for agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), false);
+
+ // Critical Message failure response.
+ logininstance->connect(test_uri, credentials);
+ response["data"]["reason"] = "critical"; // Change response to "critical message"
+ gTestPump.post(response);
+
+ ensure_equals("TOS Dialog type", gTOSType, "message_critical");
+ ensure("TOS callback given", gTOSReplyPump != 0);
+ gTOSReplyPump->post(true);
+ ensure_equals("Accepted read critical message", gLoginCreds["params"]["read_critical"].asBoolean(), true);
+ ensure("Incomplete login status", !logininstance->authFailure() && !logininstance->authSuccess());
+
+ // Fail then attempt new connection
+ response["data"]["reason"] = "key"; // bad creds.
+ gTestPump.post(response);
+ ensure("TOS auth failure", logininstance->authFailure());
+ logininstance->connect(test_uri, credentials);
+ ensure_equals("Default for agree to tos", gLoginCreds["params"]["read_critical"].asBoolean(), false);
+ }
+
+ template<> template<>
+ void lllogininstance_object::test<3>()
+ {
+ set_test_name("Test Mandatory Update User Accepts");
+
+ // Part 1 - Mandatory Update, with User accepts response.
+ // Test connect with update needed.
+ logininstance->connect(credentials);
+
+ ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);
+
+ // Update needed failure response.
+ LLSD response;
+ response["state"] = "offline";
+ response["change"] = "fail.login";
+ response["progress"] = 0.0;
+ response["transfer_rate"] = 7;
+ response["data"]["reason"] = "update";
+ gTestPump.post(response);
+
+ ensure_equals("Notification added", notifications.addedCount(), 1);
+
+ notifications.sendYesResponse();
+
+ ensure("Disconnected", !(logininstance->authSuccess()));
+ }
+
+ template<> template<>
+ void lllogininstance_object::test<4>()
+ {
+ set_test_name("Test Mandatory Update User Decline");
+
+ // Test connect with update needed.
+ logininstance->connect(credentials);
+
+ ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);
+
+ // Update needed failure response.
+ LLSD response;
+ response["state"] = "offline";
+ response["change"] = "fail.login";
+ response["progress"] = 0.0;
+ response["transfer_rate"] = 7;
+ response["data"]["reason"] = "update";
+ gTestPump.post(response);
+
+ ensure_equals("Notification added", notifications.addedCount(), 1);
+ notifications.sendNoResponse();
+
+ ensure("Disconnected", !(logininstance->authSuccess()));
+ }
+
+ template<> template<>
+ void lllogininstance_object::test<6>()
+ {
+ set_test_name("Test Optional Update User Accept");
+
+ // Part 3 - Mandatory Update, with bogus response.
+ // Test connect with update needed.
+ logininstance->connect(credentials);
+
+ ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);
+
+ // Update needed failure response.
+ LLSD response;
+ response["state"] = "offline";
+ response["change"] = "fail.login";
+ response["progress"] = 0.0;
+ response["transfer_rate"] = 7;
+ response["data"]["reason"] = "optional";
+ gTestPump.post(response);
+
+ ensure_equals("Notification added", notifications.addedCount(), 1);
+ notifications.sendYesResponse();
+
+ ensure("Disconnected", !(logininstance->authSuccess()));
+ }
+
+ template<> template<>
+ void lllogininstance_object::test<7>()
+ {
+ set_test_name("Test Optional Update User Denies");
+
+ // Part 3 - Mandatory Update, with bogus response.
+ // Test connect with update needed.
+ logininstance->connect(credentials);
+
+ ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI);
+
+ // Update needed failure response.
+ LLSD response;
+ response["state"] = "offline";
+ response["change"] = "fail.login";
+ response["progress"] = 0.0;
+ response["transfer_rate"] = 7;
+ response["data"]["reason"] = "optional";
+ gTestPump.post(response);
+
+ ensure_equals("Notification added", notifications.addedCount(), 1);
+ notifications.sendNoResponse();
+
+ // User skips, should be reconnecting.
+ ensure_equals("reconnect uri", gLoginURI, VIEWERLOGIN_URI);
+ ensure_equals("skipping optional update", gLoginCreds["params"]["skipoptional"].asBoolean(), true);
+ }
+}
diff --git a/indra/newview/tests/llmediadataclient_test.cpp b/indra/newview/tests/llmediadataclient_test.cpp
new file mode 100644
index 0000000000..33d413bd21
--- /dev/null
+++ b/indra/newview/tests/llmediadataclient_test.cpp
@@ -0,0 +1,938 @@
+/**
+ * @file llmediadataclient_test.cpp
+ * @brief LLMediaDatClient tests
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../llviewerprecompiledheaders.h"
+
+#include <iostream>
+#include "../test/lltut.h"
+
+#include "llsdserialize.h"
+#include "llsdutil.h"
+#include "llerrorcontrol.h"
+#include "llhttpstatuscodes.h"
+
+#include "../llmediadataclient.h"
+#include "../llvovolume.h"
+
+#include "../../llprimitive/llmediaentry.cpp"
+#include "../../llprimitive/lltextureentry.cpp"
+#include "../../llmessage/tests/llcurl_stub.cpp"
+
+#if LL_WINDOWS
+#pragma warning (push)
+#pragma warning (disable : 4702) // boost::lexical_cast generates this warning
+#endif
+#include <boost/lexical_cast.hpp>
+#if LL_WINDOWS
+#pragma warning (pop)
+#endif
+
+#define VALID_OBJECT_ID "3607d5c4-644b-4a8a-871a-8b78471af2a2"
+#define VALID_OBJECT_ID_1 "11111111-1111-1111-1111-111111111111"
+#define VALID_OBJECT_ID_2 "22222222-2222-2222-2222-222222222222"
+#define VALID_OBJECT_ID_3 "33333333-3333-3333-3333-333333333333"
+#define VALID_OBJECT_ID_4 "44444444-4444-4444-4444-444444444444"
+
+#define FAKE_OBJECT_MEDIA_CAP_URL "foo_ObjectMedia"
+#define FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL "foo_ObjectMediaNavigate"
+#define FAKE_OBJECT_MEDIA_CAP_URL_503 "foo_ObjectMedia_503"
+#define FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR "foo_ObjectMediaNavigate_ERROR"
+
+#define MEDIA_DATA "\
+<array> \
+<string>foo</string> \
+<string>bar</string> \
+<string>baz</string> \
+</array>"
+
+#define _DATA_URLS(ID,INTEREST,NEW,URL1,URL2) " \
+<llsd> \
+ <map> \
+ <key>uuid</key> \
+ <string>" ID "</string> \
+ <key>interest</key> \
+ <real>" INTEREST "</real> \
+ <key>cap_urls</key> \
+ <map> \
+ <key>ObjectMedia</key> \
+ <string>" URL1 "</string> \
+ <key>ObjectMediaNavigate</key> \
+ <string>" URL2 "</string> \
+ </map> \
+ <key>media_data</key> \
+ " MEDIA_DATA " \
+ <key>is_dead</key> \
+ <boolean>false</boolean> \
+ <key>is_new</key> \
+ <boolean>" NEW "</boolean> \
+ </map> \
+</llsd>"
+
+#define _DATA(ID,INTEREST,NEW) _DATA_URLS(ID,INTEREST,NEW,FAKE_OBJECT_MEDIA_CAP_URL,FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL)
+
+const char *DATA = _DATA(VALID_OBJECT_ID,"1.0","true");
+
+#define STR(I) boost::lexical_cast<std::string>(I)
+
+#define LOG_TEST(N) LL_DEBUGS("LLMediaDataClient") << "\n" << \
+"================================================================================\n" << \
+"==================================== TEST " #N " ===================================\n" << \
+"================================================================================\n" << LL_ENDL;
+
+LLSD *gPostRecords = NULL;
+F64 gMinimumInterestLevel = (F64)0.0;
+
+// stubs:
+void LLHTTPClient::post(
+ const std::string& url,
+ const LLSD& body,
+ LLHTTPClient::ResponderPtr responder,
+ const LLSD& headers,
+ const F32 timeout)
+{
+ LLSD record;
+ record["url"] = url;
+ record["body"] = body;
+ record["headers"] = headers;
+ record["timeout"] = timeout;
+ gPostRecords->append(record);
+
+ // Magic URL that triggers a 503:
+ LLSD result;
+ result[LLTextureEntry::OBJECT_ID_KEY] = body[LLTextureEntry::OBJECT_ID_KEY];
+ if ( url == FAKE_OBJECT_MEDIA_CAP_URL_503 )
+ {
+ responder->error(HTTP_SERVICE_UNAVAILABLE, "fake reason");
+ return;
+ }
+ else if (url == FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR)
+ {
+ LLSD error;
+ error["code"] = LLObjectMediaNavigateClient::ERROR_PERMISSION_DENIED_CODE;
+ result["error"] = error;
+ }
+ responder->result(result);
+}
+
+const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f;
+
+class LLMediaDataClientObjectTest : public LLMediaDataClientObject
+{
+public:
+ LLMediaDataClientObjectTest(const char *data)
+ {
+ std::istringstream d(data);
+ LLSDSerialize::fromXML(mRep, d);
+ mNumBounceBacks = 0;
+
+ // std::cout << ll_pretty_print_sd(mRep) << std::endl;
+ // std::cout << "ID: " << getID() << std::endl;
+ }
+ LLMediaDataClientObjectTest(const LLSD &rep)
+ : mRep(rep), mNumBounceBacks(0) {}
+ ~LLMediaDataClientObjectTest()
+ { LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClientObjectTest" << LL_ENDL; }
+
+ virtual U8 getMediaDataCount() const
+ { return mRep["media_data"].size(); }
+ virtual LLSD getMediaDataLLSD(U8 index) const
+ { return mRep["media_data"][(LLSD::Integer)index]; }
+ virtual LLUUID getID() const
+ { return mRep["uuid"]; }
+ virtual void mediaNavigateBounceBack(U8 index)
+ { mNumBounceBacks++; }
+
+ virtual bool hasMedia() const
+ { return mRep.has("media_data"); }
+
+ virtual void updateObjectMediaData(LLSD const &media_data_array, const std::string &media_version)
+ { mRep["media_data"] = media_data_array; mRep["media_version"] = media_version; }
+
+ virtual F64 getMediaInterest() const
+ { return (LLSD::Real)mRep["interest"]; }
+
+ virtual bool isInterestingEnough() const
+ { return getMediaInterest() > gMinimumInterestLevel; }
+
+ virtual std::string getCapabilityUrl(const std::string &name) const
+ { return mRep["cap_urls"][name]; }
+
+ virtual bool isDead() const
+ { return mRep["is_dead"]; }
+
+ virtual U32 getMediaVersion() const
+ { return (LLSD::Integer)mRep["media_version"]; }
+
+ virtual bool isNew() const
+ { return mRep["is_new"]; }
+
+ void setMediaInterest(F64 val)
+ { mRep["interest"] = val; }
+
+ int getNumBounceBacks() const
+ { return mNumBounceBacks; }
+
+ void markDead()
+ { mRep["is_dead"] = true; }
+
+ void markOld()
+ { mRep["is_new"] = false; }
+
+private:
+ LLSD mRep;
+ int mNumBounceBacks;
+};
+
+// This special timer delay should ensure that the timer will fire on the very
+// next pump, no matter what (though this does make an assumption about the
+// implementation of LLEventTimer::updateClass()):
+const F32 NO_PERIOD = -1000.0f;
+
+static void pump_timers()
+{
+ LLEventTimer::updateClass();
+}
+
+namespace tut
+{
+ struct mediadataclient
+ {
+ mediadataclient() {
+ gPostRecords = &mLLSD;
+ gMinimumInterestLevel = (F64)0.0;
+
+// LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
+// LLError::setClassLevel("LLMediaDataClient", LLError::LEVEL_DEBUG);
+// LLError::setTagLevel("MediaOnAPrim", LLError::LEVEL_DEBUG);
+ }
+ LLSD mLLSD;
+ };
+
+ typedef test_group<mediadataclient> mediadataclient_t;
+ typedef mediadataclient_t::object mediadataclient_object_t;
+ tut::mediadataclient_t tut_mediadataclient("mediadataclient");
+
+ void ensure(const std::string &msg, int value, int expected)
+ {
+ std::string m = msg;
+ m += " value: " + STR(value);
+ m += ", expected: " + STR(expected);
+ ensure(m, value == expected);
+ }
+
+ void ensure(const std::string &msg, const std::string & value, const std::string & expected)
+ {
+ std::string m = msg;
+ m += " value: " + value;
+ m += ", expected: " + expected;
+ ensure(m, value == expected);
+ }
+
+ void ensure(const std::string &msg, const LLUUID & value, const LLUUID & expected)
+ {
+ std::string m = msg;
+ m += " value: " + value.asString();
+ m += ", expected: " + expected.asString();
+ ensure(m, value == expected);
+ }
+
+ void ensure_llsd(const std::string &msg, const LLSD & value, const char *expected)
+ {
+ LLSD expected_llsd;
+ std::istringstream e(expected);
+ LLSDSerialize::fromXML(expected_llsd, e);
+
+ std::string value_str = ll_pretty_print_sd(value);
+ std::string expected_str = ll_pretty_print_sd(expected_llsd);
+ std::string m = msg;
+ m += " value: " + value_str;
+ m += ", expected: " + expected_str;
+ ensure(m, value_str == expected_str);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ template<> template<>
+ void mediadataclient_object_t::test<1>()
+ {
+ //
+ // Test fetchMedia()
+ //
+ LOG_TEST(1);
+
+ LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA);
+ int num_refs_start = o->getNumRefs();
+ {
+ LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
+ mdc->fetchMedia(o);
+
+ // Make sure no posts happened yet...
+ ensure("post records", gPostRecords->size(), 0);
+
+ ::pump_timers();
+
+ ensure("post records", gPostRecords->size(), 1);
+ ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_CAP_URL);
+ ensure("post GET", (*gPostRecords)[0]["body"]["verb"], "GET");
+ ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
+ ensure("queue empty", mdc->isEmpty());
+ }
+
+ // Make sure everyone's destroyed properly
+ ensure("REF COUNT", o->getNumRefs(), num_refs_start);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ template<> template<>
+ void mediadataclient_object_t::test<2>()
+ {
+ //
+ // Test updateMedia()
+ //
+ LOG_TEST(2);
+
+ LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA);
+ {
+ // queue time w/ no delay ensures that ::pump_timers() will hit the tick()
+ LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
+ mdc->updateMedia(o);
+ ensure("post records", gPostRecords->size(), 0);
+ ::pump_timers();
+
+ ensure("post records", gPostRecords->size(), 1);
+ ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_CAP_URL);
+ ensure("post UPDATE", (*gPostRecords)[0]["body"]["verb"], "UPDATE");
+ ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
+ ensure_llsd("post data llsd", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_MEDIA_DATA_KEY],
+ "<llsd>" MEDIA_DATA "</llsd>");
+ ensure("queue empty", mdc->isEmpty());
+ }
+
+ ensure("REF COUNT", o->getNumRefs(), 1);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ template<> template<>
+ void mediadataclient_object_t::test<3>()
+ {
+ //
+ // Test navigate()
+ //
+ LOG_TEST(3);
+
+ LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA);
+ {
+ LLPointer<LLObjectMediaNavigateClient> mdc = new LLObjectMediaNavigateClient(NO_PERIOD,NO_PERIOD);
+ const char *TEST_URL = "http://example.com";
+ mdc->navigate(o, 0, TEST_URL);
+ ensure("post records", gPostRecords->size(), 0);
+ ::pump_timers();
+
+ // ensure no bounce back
+ ensure("bounce back", dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o))->getNumBounceBacks(), 0);
+
+ ensure("post records", gPostRecords->size(), 1);
+ ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL);
+ ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
+ ensure("post data", (*gPostRecords)[0]["body"][LLTextureEntry::TEXTURE_INDEX_KEY], 0);
+ ensure("post data", (*gPostRecords)[0]["body"][LLMediaEntry::CURRENT_URL_KEY], TEST_URL);
+ ensure("queue empty", mdc->isEmpty());
+ }
+ ensure("REF COUNT", o->getNumRefs(), 1);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ template<> template<>
+ void mediadataclient_object_t::test<4>()
+ {
+ //
+ // Test queue ordering
+ //
+ LOG_TEST(4);
+
+ LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(
+ _DATA(VALID_OBJECT_ID_1,"1.0","true"));
+ LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(
+ _DATA(VALID_OBJECT_ID_2,"3.0","true"));
+ LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(
+ _DATA(VALID_OBJECT_ID_3,"2.0","true"));
+ {
+ LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
+ const char *ORDERED_OBJECT_IDS[] = { VALID_OBJECT_ID_2, VALID_OBJECT_ID_3, VALID_OBJECT_ID_1 };
+ mdc->fetchMedia(o1);
+ mdc->fetchMedia(o2);
+ mdc->fetchMedia(o3);
+
+ // Make sure no posts happened yet...
+ ensure("post records", gPostRecords->size(), 0);
+
+ // tick 3 times...
+ ::pump_timers();
+ ensure("post records", gPostRecords->size(), 1);
+ ::pump_timers();
+ ensure("post records", gPostRecords->size(), 2);
+ ::pump_timers();
+ ensure("post records", gPostRecords->size(), 3);
+
+ for( int i=0; i < 3; i++ )
+ {
+ ensure("[" + STR(i) + "] post url", (*gPostRecords)[i]["url"], FAKE_OBJECT_MEDIA_CAP_URL);
+ ensure("[" + STR(i) + "] post GET", (*gPostRecords)[i]["body"]["verb"], "GET");
+ ensure("[" + STR(i) + "] post object id", (*gPostRecords)[i]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(),
+ LLUUID(ORDERED_OBJECT_IDS[i]));
+ }
+
+ ensure("queue empty", mdc->isEmpty());
+ }
+ ensure("refcount of o1", o1->getNumRefs(), 1);
+ ensure("refcount of o2", o2->getNumRefs(), 1);
+ ensure("refcount of o3", o3->getNumRefs(), 1);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ template<> template<>
+ void mediadataclient_object_t::test<5>()
+ {
+ //
+ // Test fetchMedia() getting a 503 error
+ //
+ LOG_TEST(5);
+
+ LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(
+ _DATA_URLS(VALID_OBJECT_ID,
+ "1.0","true",
+ FAKE_OBJECT_MEDIA_CAP_URL_503,
+ FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL));
+ int num_refs_start = o->getNumRefs();
+ {
+ const int NUM_RETRIES = 5;
+ LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD,NUM_RETRIES);
+
+ // This should generate a retry
+ mdc->fetchMedia(o);
+
+ // Make sure no posts happened yet...
+ ensure("post records before", gPostRecords->size(), 0);
+
+ // Once, causes retry
+ // Second, fires retry timer
+ // Third, fires queue timer again
+ for (int i=0; i<NUM_RETRIES; ++i)
+ {
+ ::pump_timers(); // Should pump (fire) the queue timer, causing a retry timer to be scheduled
+ // XXX This ensure is not guaranteed, because scheduling a timer might actually get it pumped in the same loop
+ //ensure("post records " + STR(i), gPostRecords->size(), i+1);
+ ::pump_timers(); // Should pump (fire) the retry timer, scheduling the queue timer
+ }
+
+ // Do some extra pumps to make sure no other timer work occurs.
+ ::pump_timers();
+ ::pump_timers();
+ ::pump_timers();
+
+ // Make sure there were 2 posts
+ ensure("post records after", gPostRecords->size(), NUM_RETRIES);
+ for (int i=0; i<NUM_RETRIES; ++i)
+ {
+ ensure("[" + STR(i) + "] post url", (*gPostRecords)[i]["url"], FAKE_OBJECT_MEDIA_CAP_URL_503);
+ ensure("[" + STR(i) + "] post GET", (*gPostRecords)[i]["body"]["verb"], "GET");
+ ensure("[" + STR(i) + "] post object id", (*gPostRecords)[i]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
+ }
+ ensure("queue empty", mdc->isEmpty());
+ }
+
+ // Make sure everyone's destroyed properly
+ ensure("REF COUNT", o->getNumRefs(), num_refs_start);
+ }
+
+ template<> template<>
+ void mediadataclient_object_t::test<6>()
+ {
+ //
+ // Test navigate() with a bounce back
+ //
+ LOG_TEST(6);
+
+ LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(
+ _DATA_URLS(VALID_OBJECT_ID,
+ "1.0","true",
+ FAKE_OBJECT_MEDIA_CAP_URL,
+ FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR));
+ {
+ LLPointer<LLObjectMediaNavigateClient> mdc = new LLObjectMediaNavigateClient(NO_PERIOD,NO_PERIOD);
+ const char *TEST_URL = "http://example.com";
+ mdc->navigate(o, 0, TEST_URL);
+ ensure("post records", gPostRecords->size(), 0);
+ ::pump_timers();
+
+ // ensure bounce back
+ ensure("bounce back",
+ dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o))->getNumBounceBacks(),
+ 1);
+
+ ensure("post records", gPostRecords->size(), 1);
+ ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR);
+ ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
+ ensure("post data", (*gPostRecords)[0]["body"][LLTextureEntry::TEXTURE_INDEX_KEY], 0);
+ ensure("post data", (*gPostRecords)[0]["body"][LLMediaEntry::CURRENT_URL_KEY], TEST_URL);
+ ensure("queue empty", mdc->isEmpty());
+ }
+ ensure("REF COUNT", o->getNumRefs(), 1);
+ }
+
+ template<> template<>
+ void mediadataclient_object_t::test<7>()
+ {
+ // Test LLMediaDataClient::isInQueue()
+ LOG_TEST(7);
+
+ LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(
+ _DATA(VALID_OBJECT_ID_1,"3.0","true"));
+ LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(
+ _DATA(VALID_OBJECT_ID_2,"1.0","true"));
+ int num_refs_start = o1->getNumRefs();
+ {
+ LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
+
+ ensure("not in queue yet 1", ! mdc->isInQueue(o1));
+ ensure("not in queue yet 2", ! mdc->isInQueue(o2));
+
+ mdc->fetchMedia(o1);
+
+ ensure("is in queue", mdc->isInQueue(o1));
+ ensure("is not in queue", ! mdc->isInQueue(o2));
+
+ ::pump_timers();
+
+ ensure("not in queue anymore", ! mdc->isInQueue(o1));
+ ensure("still is not in queue", ! mdc->isInQueue(o2));
+
+ ensure("queue empty", mdc->isEmpty());
+ }
+
+ // Make sure everyone's destroyed properly
+ ensure("REF COUNT", o1->getNumRefs(), num_refs_start);
+
+ }
+
+ template<> template<>
+ void mediadataclient_object_t::test<8>()
+ {
+ // Test queue handling of objects that are marked dead.
+ LOG_TEST(8);
+
+ LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"4.0","true"));
+ LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"3.0","true"));
+ LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"2.0","true"));
+ LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"1.0","true"));
+ {
+ LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
+
+ // queue up all 4 objects
+ mdc->fetchMedia(o1);
+ mdc->fetchMedia(o2);
+ mdc->fetchMedia(o3);
+ mdc->fetchMedia(o4);
+
+ // and mark the second and fourth ones dead.
+ dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o2))->markDead();
+ dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o4))->markDead();
+
+ ensure("is in queue 1", mdc->isInQueue(o1));
+ ensure("is in queue 2", mdc->isInQueue(o2));
+ ensure("is in queue 3", mdc->isInQueue(o3));
+ ensure("is in queue 4", mdc->isInQueue(o4));
+ ensure("post records", gPostRecords->size(), 0);
+
+ ::pump_timers();
+
+ // The first tick should remove the first one
+ ensure("is not in queue 1", !mdc->isInQueue(o1));
+ ensure("is in queue 2", mdc->isInQueue(o2));
+ ensure("is in queue 3", mdc->isInQueue(o3));
+ ensure("is in queue 4", mdc->isInQueue(o4));
+ ensure("post records", gPostRecords->size(), 1);
+
+ ::pump_timers();
+
+ // The second tick should skip the second and remove the third
+ ensure("is not in queue 2", !mdc->isInQueue(o2));
+ ensure("is not in queue 3", !mdc->isInQueue(o3));
+ ensure("is in queue 4", mdc->isInQueue(o4));
+ ensure("post records", gPostRecords->size(), 2);
+
+ ::pump_timers();
+
+ // The third tick should skip the fourth one and empty the queue.
+ ensure("is not in queue 4", !mdc->isInQueue(o4));
+ ensure("post records", gPostRecords->size(), 2);
+
+ ensure("queue empty", mdc->isEmpty());
+ }
+ ensure("refcount of o1", o1->getNumRefs(), 1);
+ ensure("refcount of o2", o2->getNumRefs(), 1);
+ ensure("refcount of o3", o3->getNumRefs(), 1);
+ ensure("refcount of o4", o4->getNumRefs(), 1);
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ template<> template<>
+ void mediadataclient_object_t::test<9>()
+ {
+ //
+ // Test queue re-ordering
+ //
+ LOG_TEST(9);
+
+ LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"40.0","true"));
+ LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"30.0","true"));
+ LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"20.0","true"));
+ LLMediaDataClientObjectTest *object4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"10.0","true"));
+ LLMediaDataClientObject::ptr_t o4 = object4;
+ {
+ LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
+
+ // queue up all 4 objects. They should now be in the queue in
+ // order 1 through 4, with 4 being at the front of the queue
+ mdc->fetchMedia(o1);
+ mdc->fetchMedia(o2);
+ mdc->fetchMedia(o3);
+ mdc->fetchMedia(o4);
+
+ int tick_num = 0;
+
+ ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
+ ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+ ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+ ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
+ ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0);
+
+ ::pump_timers();
+ ++tick_num;
+
+ // The first tick should remove the first one
+ ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
+ ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+ ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+ ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
+ ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1);
+
+ // Now, pretend that object 4 moved relative to the avatar such
+ // that it is now closest
+ object4->setMediaInterest(50.0);
+
+ ::pump_timers();
+ ++tick_num;
+
+ // The second tick should still pick off item 2, but then re-sort
+ // have picked off object 4
+ ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+ ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+ ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
+ ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);
+
+ ::pump_timers();
+ ++tick_num;
+
+ // The third tick should pick off object 2
+ ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
+ ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+ ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3);
+
+ // The fourth tick should pick off object 3
+ ::pump_timers();
+ ++tick_num;
+
+ ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
+ ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4);
+
+ ensure("queue empty", mdc->isEmpty());
+ }
+ ensure("refcount of o1", o1->getNumRefs(), 1);
+ ensure("refcount of o2", o2->getNumRefs(), 1);
+ ensure("refcount of o3", o3->getNumRefs(), 1);
+ ensure("refcount of o4", o4->getNumRefs(), 1);
+ }
+
+
+ template<> template<>
+ void mediadataclient_object_t::test<10>()
+ {
+ //
+ // Test using the "round-robin" queue
+ //
+ LOG_TEST(10);
+
+ LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","true"));
+ LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"2.0","true"));
+ LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"3.0","false"));
+ LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"4.0","false"));
+ {
+ LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
+
+ // queue up all 4 objects. The first two should be in the sorted
+ // queue [2 1], the second in the round-robin queue. The queues
+ // are serviced interleaved, so we should expect:
+ // 2, 4, 1, 3
+ mdc->fetchMedia(o1);
+ mdc->fetchMedia(o2);
+ mdc->fetchMedia(o3);
+ mdc->fetchMedia(o4);
+
+ int tick_num = 0;
+
+ // 0
+ ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
+ ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+ ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+ ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
+ ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0);
+
+ ::pump_timers();
+ ++tick_num;
+
+ // 1 The first tick should remove object 2
+ ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
+ ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
+ ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+ ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
+ ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1);
+ ensure(STR(tick_num) + ". post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_2));
+
+ ::pump_timers();
+ ++tick_num;
+
+ // 2 The second tick should send object 4, but it will still be
+ // "in the queue"
+ ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
+ ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
+ ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+ ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
+ ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);
+ ensure(STR(tick_num) + ". post object id", (*gPostRecords)[1]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_4));
+
+ ::pump_timers();
+ ++tick_num;
+
+ // 3 The third tick should remove object 1
+ ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
+ ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
+ ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+ ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
+ ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3);
+ ensure(STR(tick_num) + ". post object id", (*gPostRecords)[2]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_1));
+
+ ::pump_timers();
+ ++tick_num;
+
+ // 4 The fourth tick should send object 3, but it will still be
+ // "in the queue"
+ ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
+ ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
+ ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+ ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
+ ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4);
+ ensure(STR(tick_num) + ". post object id", (*gPostRecords)[3]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_3));
+
+ ::pump_timers();
+ ++tick_num;
+
+ // 5 The fifth tick should now identify objects 3 and 4 as no longer
+ // needing "updating", and remove them from the queue
+ ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
+ ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
+ ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
+ ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
+ ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4);
+
+ ::pump_timers();
+
+ // Whew....better be empty
+ ensure("queue empty", mdc->isEmpty());
+ }
+ ensure("refcount of o1", o1->getNumRefs(), 1);
+ ensure("refcount of o2", o2->getNumRefs(), 1);
+ ensure("refcount of o3", o3->getNumRefs(), 1);
+ ensure("refcount of o4", o4->getNumRefs(), 1);
+ }
+
+
+ template<> template<>
+ void mediadataclient_object_t::test<11>()
+ {
+ //
+ // Test LLMediaDataClient's destructor
+ //
+ LOG_TEST(11);
+
+ LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA);
+ int num_refs_start = o->getNumRefs();
+ {
+ LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
+ mdc->fetchMedia(o);
+ // must tick enough times to clear refcount of mdc
+ ::pump_timers();
+ }
+ // Make sure everyone's destroyed properly
+ ensure("REF COUNT", o->getNumRefs(), num_refs_start);
+ }
+
+ template<> template<>
+ void mediadataclient_object_t::test<12>()
+ {
+ //
+ // Test the "not interesting enough" call
+ //
+ LOG_TEST(12);
+
+ LLMediaDataClientObjectTest *object1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","true"));
+ LLMediaDataClientObject::ptr_t o1 = object1;
+ LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"2.0","true"));
+ LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"3.0","true"));
+ LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"4.0","true"));
+ {
+ LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
+
+ // queue up all 4 objects. The first two are "interesting enough".
+ // Firing the timer 4 times should therefore leave them.
+ // Note that they should be sorted 4,3,2,1
+ // Then, we'll make one "interesting enough", fire the timer a few
+ // times, and make sure only it gets pulled off the queue
+ gMinimumInterestLevel = 2.5;
+ mdc->fetchMedia(o1);
+ mdc->fetchMedia(o2);
+ mdc->fetchMedia(o3);
+ mdc->fetchMedia(o4);
+
+ int tick_num = 0;
+
+ // 0
+ ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
+ ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+ ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+ ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
+ ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0);
+
+ ::pump_timers();
+ ++tick_num;
+
+ // 1 The first tick should remove object 4
+ ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
+ ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+ ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+ ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
+ ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1);
+ ensure(STR(tick_num) + ". post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_4));
+
+ ::pump_timers();
+ ++tick_num;
+
+ // 2 The second tick should send object 3
+ ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
+ ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+ ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
+ ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
+ ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);
+ ensure(STR(tick_num) + ". post object id", (*gPostRecords)[1]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_3));
+
+ ::pump_timers();
+ ++tick_num;
+
+ // 3 The third tick should not pull off anything
+ ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
+ ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+ ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
+ ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
+ ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);
+
+ ::pump_timers();
+ ++tick_num;
+
+ // 4 The fourth tick (for good measure) should not pull off anything
+ ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
+ ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+ ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
+ ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
+ ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);
+
+ // Okay, now futz with object 1's interest, such that it is now
+ // "interesting enough"
+ object1->setMediaInterest((F64)5.0);
+
+ // This should sort so that the queue is now [1 2]
+ ::pump_timers();
+ ++tick_num;
+
+ // 5 The fifth tick should now identify objects 3 and 4 as no longer
+ // needing "updating", and remove them from the queue
+ ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
+ ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+ ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
+ ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
+ ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3);
+ ensure(STR(tick_num) + ". post object id", (*gPostRecords)[2]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_1));
+
+ ::pump_timers();
+ ++tick_num;
+
+ // 6 The sixth tick should not pull off anything
+ ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
+ ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+ ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
+ ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
+ ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3);
+
+ ::pump_timers();
+ ++tick_num;
+
+ // Whew....better NOT be empty ... o2 should still be there
+ ensure("queue not empty", !mdc->isEmpty());
+
+ // But, we need to clear the queue, or else we won't destroy MDC...
+ // this is a strange interplay between the queue timer and the MDC
+ ensure("o2 couldn't be removed from queue", mdc->removeFromQueue(o2));
+ // tick
+ ::pump_timers();
+ }
+ ensure("refcount of o1", o1->getNumRefs(), 1);
+ ensure("refcount of o2", o2->getNumRefs(), 1);
+ ensure("refcount of o3", o3->getNumRefs(), 1);
+ ensure("refcount of o4", o4->getNumRefs(), 1);
+ }
+}
diff --git a/indra/newview/tests/lltextureinfo_test.cpp b/indra/newview/tests/lltextureinfo_test.cpp
new file mode 100644
index 0000000000..8dfba46262
--- /dev/null
+++ b/indra/newview/tests/lltextureinfo_test.cpp
@@ -0,0 +1,284 @@
+/**
+ * @file llwtextureinfo_test.cpp
+ * @author Si & Gabriel
+ * @date 2009-03-30
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ *
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header: almost always required for newview cpp files
+#include "../llviewerprecompiledheaders.h"
+// Class to test
+#include "../lltextureinfo.h"
+// Dependencies
+#include "../lltextureinfodetails.cpp"
+
+// Tut header
+#include "../test/lltut.h"
+
+// -------------------------------------------------------------------------------------------
+// Stubbing: Declarations required to link and run the class being tested
+// Notes:
+// * Add here stubbed implementation of the few classes and methods used in the class to be tested
+// * Add as little as possible (let the link errors guide you)
+// * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code)
+// * A simulator for a class can be implemented here. Please comment and document thoroughly.
+
+
+// End Stubbing
+// -------------------------------------------------------------------------------------------
+
+// -------------------------------------------------------------------------------------------
+// TUT
+// -------------------------------------------------------------------------------------------
+
+namespace tut
+{
+ // Test wrapper declarations
+ struct textureinfo_test
+ {
+ // Constructor and destructor of the test wrapper
+ textureinfo_test()
+ {
+ }
+ ~textureinfo_test()
+ {
+ }
+ };
+
+ // Tut templating thingamagic: test group, object and test instance
+ typedef test_group<textureinfo_test> textureinfo_t;
+ typedef textureinfo_t::object textureinfo_object_t;
+ tut::textureinfo_t tut_textureinfo("textureinfo");
+
+
+ // ---------------------------------------------------------------------------------------
+ // Test functions
+ // Notes:
+ // * Test as many as you possibly can without requiring a full blown simulation of everything
+ // * The tests are executed in sequence so the test instance state may change between calls
+ // * Remember that you cannot test private methods with tut
+ // ---------------------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------------------
+ // Test the LLTextureInfo
+ // ---------------------------------------------------------------------------------------
+
+
+ // Test instantiation
+ template<> template<>
+ void textureinfo_object_t::test<1>()
+ {
+ LLTextureInfo tex_info;
+ tex_info.setUpLogging(true, true);
+ ensure("have we crashed?", true);
+ }
+
+ // Check lltextureinfo does not contain UUIDs we haven't added
+ template<> template<>
+ void textureinfo_object_t::test<2>()
+ {
+ LLTextureInfo tex_info;
+ tex_info.setUpLogging(true, true);
+
+ LLUUID nonExistant("3a0efa3b-84dc-4e17-9b8c-79ea028850c1");
+ ensure(!tex_info.has(nonExistant));
+ }
+
+ // Check we can add a request time for a texture
+ template<> template<>
+ void textureinfo_object_t::test<3>()
+ {
+ LLTextureInfo tex_info;
+ tex_info.setUpLogging(true, true);
+
+ LLUUID id("10e65d70-46fd-429f-841a-bf698e9424d3");
+ tex_info.setRequestStartTime(id, 200);
+
+ ensure_equals(tex_info.getRequestStartTime(id), 200);
+ }
+
+ // Check time for non-existant texture
+ template<> template<>
+ void textureinfo_object_t::test<4>()
+ {
+ LLTextureInfo tex_info;
+ tex_info.setUpLogging(true, true);
+
+ LLUUID nonExistant("3a0efa3b-84dc-4e17-9b8c-79ea028850c1");
+ ensure_equals(tex_info.getRequestStartTime(nonExistant), 0);
+ }
+
+ // Check download complete time for non existant texture
+ template<> template<>
+ void textureinfo_object_t::test<5>()
+ {
+ LLTextureInfo tex_info;
+ tex_info.setUpLogging(true, true);
+
+ LLUUID nonExistant("3a0efa3b-84dc-4e17-9b8c-79ea028850c1");
+ ensure_equals(tex_info.getRequestCompleteTime(nonExistant), 0);
+ }
+
+ // requested size is passed in correctly
+ template<> template<>
+ void textureinfo_object_t::test<6>()
+ {
+ LLTextureInfo tex_info;
+ tex_info.setUpLogging(true, true);
+
+ LLUUID id("10e65d70-46fd-429f-841a-bf698e9424d3");
+ tex_info.setRequestSize(id, 600);
+
+ ensure_equals(tex_info.getRequestSize(id), 600);
+ }
+
+ // transport type is recorded correctly (http)
+ template<> template<>
+ void textureinfo_object_t::test<7>()
+ {
+ LLTextureInfo tex_info;
+ tex_info.setUpLogging(true, true);
+
+ LLUUID id("10e65d70-46fd-429f-841a-bf698e9424d3");
+ tex_info.setRequestType(id, LLTextureInfoDetails::REQUEST_TYPE_HTTP);
+
+ ensure_equals(tex_info.getRequestType(id), LLTextureInfoDetails::REQUEST_TYPE_HTTP);
+ }
+
+ // transport type is recorded correctly (udp)
+ template<> template<>
+ void textureinfo_object_t::test<8>()
+ {
+ LLTextureInfo tex_info;
+ tex_info.setUpLogging(true, true);
+
+ LLUUID id("10e65d70-46fd-429f-841a-bf698e9424d3");
+ tex_info.setRequestType(id, LLTextureInfoDetails::REQUEST_TYPE_UDP);
+
+ ensure_equals(tex_info.getRequestType(id), LLTextureInfoDetails::REQUEST_TYPE_UDP);
+ }
+
+ // request offset is recorded correctly
+ template<> template<>
+ void textureinfo_object_t::test<9>()
+ {
+ LLTextureInfo tex_info;
+ tex_info.setUpLogging(true, true);
+
+ LLUUID id("10e65d70-46fd-429f-841a-bf698e9424d3");
+ tex_info.setRequestOffset(id, 1234);
+
+ ensure_equals(tex_info.getRequestOffset(id), 1234);
+ }
+
+ // ask for averages gives us correct figure
+ template<> template<>
+ void textureinfo_object_t::test<10>()
+ {
+ LLTextureInfo tex_info;
+ tex_info.setUpLogging(true, true);
+
+ S32 requestStartTimeOne = 200;
+ S32 requestEndTimeOne = 400;
+ S32 requestSizeOne = 1024;
+ S32 requestSizeOneBits = requestSizeOne * 8;
+ LLUUID id1("10e65d70-46fd-429f-841a-bf698e9424d3");
+ tex_info.setRequestStartTime(id1, requestStartTimeOne);
+ tex_info.setRequestSize(id1, requestSizeOne);
+ tex_info.setRequestType(id1, LLTextureInfoDetails::REQUEST_TYPE_HTTP);
+ tex_info.setRequestCompleteTimeAndLog(id1, requestEndTimeOne);
+
+ U32 requestStartTimeTwo = 100;
+ U32 requestEndTimeTwo = 500;
+ U32 requestSizeTwo = 2048;
+ S32 requestSizeTwoBits = requestSizeTwo * 8;
+ LLUUID id2("10e65d70-46fd-429f-841a-bf698e9424d4");
+ tex_info.setRequestStartTime(id2, requestStartTimeTwo);
+ tex_info.setRequestSize(id2, requestSizeTwo);
+ tex_info.setRequestType(id2, LLTextureInfoDetails::REQUEST_TYPE_HTTP);
+ tex_info.setRequestCompleteTimeAndLog(id2, requestEndTimeTwo);
+
+ S32 averageBitRate = ((requestSizeOneBits/(requestEndTimeOne - requestStartTimeOne)) +
+ (requestSizeTwoBits/(requestEndTimeTwo - requestStartTimeTwo))) / 2;
+
+ S32 totalBytes = requestSizeOne + requestSizeTwo;
+
+ LLSD results = tex_info.getAverages();
+ ensure_equals("is average bits per second correct", results["bits_per_second"].asInteger(), averageBitRate);
+ ensure_equals("is total bytes is correct", results["bytes_downloaded"].asInteger(), totalBytes);
+ ensure_equals("is transport correct", results["transport"].asString(), std::string("HTTP"));
+ }
+
+ // make sure averages cleared when reset is called
+ template<> template<>
+ void textureinfo_object_t::test<11>()
+ {
+ LLTextureInfo tex_info;
+ tex_info.setUpLogging(true, true);
+
+ S32 requestStartTimeOne = 200;
+ S32 requestEndTimeOne = 400;
+ S32 requestSizeOne = 1024;
+ LLUUID id1("10e65d70-46fd-429f-841a-bf698e9424d3");
+ tex_info.setRequestStartTime(id1, requestStartTimeOne);
+ tex_info.setRequestSize(id1, requestSizeOne);
+ tex_info.setRequestType(id1, LLTextureInfoDetails::REQUEST_TYPE_HTTP);
+ tex_info.setRequestCompleteTimeAndLog(id1, requestEndTimeOne);
+
+ tex_info.getAverages();
+ tex_info.reset();
+ LLSD results = tex_info.getAverages();
+ ensure_equals("is average bits per second correct", results["bits_per_second"].asInteger(), 0);
+ ensure_equals("is total bytes is correct", results["bytes_downloaded"].asInteger(), 0);
+ ensure_equals("is transport correct", results["transport"].asString(), std::string("NONE"));
+ }
+
+ // make sure map item removed when expired
+ template<> template<>
+ void textureinfo_object_t::test<12>()
+ {
+ LLTextureInfo tex_info;
+ tex_info.setUpLogging(true, true);
+
+ S32 requestStartTimeOne = 200;
+ S32 requestEndTimeOne = 400;
+ S32 requestSizeOne = 1024;
+ LLUUID id1("10e65d70-46fd-429f-841a-bf698e9424d3");
+ tex_info.setRequestStartTime(id1, requestStartTimeOne);
+ tex_info.setRequestSize(id1, requestSizeOne);
+ tex_info.setRequestType(id1, LLTextureInfoDetails::REQUEST_TYPE_HTTP);
+
+ ensure_equals("map item created", tex_info.getTextureInfoMapSize(), 1);
+
+ tex_info.setRequestCompleteTimeAndLog(id1, requestEndTimeOne);
+
+ ensure_equals("map item removed when consumed", tex_info.getTextureInfoMapSize(), 0);
+ }
+}
+
diff --git a/indra/newview/tests/lltextureinfodetails_test.cpp b/indra/newview/tests/lltextureinfodetails_test.cpp
new file mode 100644
index 0000000000..aa2697fb8e
--- /dev/null
+++ b/indra/newview/tests/lltextureinfodetails_test.cpp
@@ -0,0 +1,98 @@
+/**
+ * @file llwtextureinfodetails_test.cpp
+ * @author Si & Gabriel
+ * @date 2009-03-30
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ *
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header: almost always required for newview cpp files
+#include "../llviewerprecompiledheaders.h"
+// Class to test
+#include "../lltextureinfodetails.h"
+// Dependencies
+
+// Tut header
+#include "../test/lltut.h"
+
+// -------------------------------------------------------------------------------------------
+// Stubbing: Declarations required to link and run the class being tested
+// Notes:
+// * Add here stubbed implementation of the few classes and methods used in the class to be tested
+// * Add as little as possible (let the link errors guide you)
+// * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code)
+// * A simulator for a class can be implemented here. Please comment and document thoroughly.
+
+
+// End Stubbing
+// -------------------------------------------------------------------------------------------
+
+// -------------------------------------------------------------------------------------------
+// TUT
+// -------------------------------------------------------------------------------------------
+
+namespace tut
+{
+ // Test wrapper declarations
+ struct textureinfodetails_test
+ {
+ // Constructor and destructor of the test wrapper
+ textureinfodetails_test()
+ {
+ }
+ ~textureinfodetails_test()
+ {
+ }
+ };
+
+ // Tut templating thingamagic: test group, object and test instance
+ typedef test_group<textureinfodetails_test> textureinfodetails_t;
+ typedef textureinfodetails_t::object textureinfodetails_object_t;
+ tut::textureinfodetails_t tut_textureinfodetails("textureinfodetails");
+
+
+ // ---------------------------------------------------------------------------------------
+ // Test functions
+ // Notes:
+ // * Test as many as you possibly can without requiring a full blown simulation of everything
+ // * The tests are executed in sequence so the test instance state may change between calls
+ // * Remember that you cannot test private methods with tut
+ // ---------------------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------------------
+ // Test the LLTextureInfo
+ // ---------------------------------------------------------------------------------------
+
+
+ // Test instantiation
+ template<> template<>
+ void textureinfodetails_object_t::test<1>()
+ {
+ ensure("have we crashed?", true);
+ }
+}
diff --git a/indra/newview/tests/lltexturestatsuploader_test.cpp b/indra/newview/tests/lltexturestatsuploader_test.cpp
new file mode 100644
index 0000000000..77a3e2c3d8
--- /dev/null
+++ b/indra/newview/tests/lltexturestatsuploader_test.cpp
@@ -0,0 +1,156 @@
+/**
+ * @file lltexturestatsuploader_test.cpp
+ * @author Si
+ * @date 2009-05-27
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ *
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header: almost always required for newview cpp files
+#include "../llviewerprecompiledheaders.h"
+// Class to test
+#include "../lltexturestatsuploader.h"
+// Dependencies
+
+// Tut header
+#include "../test/lltut.h"
+
+// -------------------------------------------------------------------------------------------
+// Stubbing: Declarations required to link and run the class being tested
+// Notes:
+// * Add here stubbed implementation of the few classes and methods used in the class to be tested
+// * Add as little as possible (let the link errors guide you)
+// * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code)
+// * A simulator for a class can be implemented here. Please comment and document thoroughly.
+
+#include "boost/intrusive_ptr.hpp"
+void boost::intrusive_ptr_add_ref(LLCurl::Responder*){}
+void boost::intrusive_ptr_release(LLCurl::Responder* p){}
+const F32 HTTP_REQUEST_EXPIRY_SECS = 0.0f;
+
+static std::string most_recent_url;
+static LLSD most_recent_body;
+
+void LLHTTPClient::post(
+ const std::string& url,
+ const LLSD& body,
+ ResponderPtr,
+ const LLSD& headers,
+ const F32 timeout)
+{
+ // set some sensor code
+ most_recent_url = url;
+ most_recent_body = body;
+ return;
+}
+
+// End Stubbing
+// -------------------------------------------------------------------------------------------
+
+// -------------------------------------------------------------------------------------------
+// TUT
+// -------------------------------------------------------------------------------------------
+
+namespace tut
+{
+ // Test wrapper declarations
+ struct texturestatsuploader_test
+ {
+ // Constructor and destructor of the test wrapper
+ texturestatsuploader_test()
+ {
+ most_recent_url = "some sort of default text that should never match anything the tests are expecting!";
+ LLSD blank_llsd;
+ most_recent_body = blank_llsd;
+ }
+ ~texturestatsuploader_test()
+ {
+ }
+ };
+
+ // Tut templating thingamagic: test group, object and test instance
+ typedef test_group<texturestatsuploader_test> texturestatsuploader_t;
+ typedef texturestatsuploader_t::object texturestatsuploader_object_t;
+ tut::texturestatsuploader_t tut_texturestatsuploader("texturestatsuploader");
+
+
+ // ---------------------------------------------------------------------------------------
+ // Test functions
+ // Notes:
+ // * Test as many as you possibly can without requiring a full blown simulation of everything
+ // * The tests are executed in sequence so the test instance state may change between calls
+ // * Remember that you cannot test private methods with tut
+ // ---------------------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------------------
+ // Test the LLTextureInfo
+ // ---------------------------------------------------------------------------------------
+
+
+ // Test instantiation
+ template<> template<>
+ void texturestatsuploader_object_t::test<1>()
+ {
+ LLTextureStatsUploader tsu;
+ llinfos << &tsu << llendl;
+ ensure("have we crashed?", true);
+ }
+
+ // does it call out to the provided url if we ask it to?
+ template<> template<>
+ void texturestatsuploader_object_t::test<2>()
+ {
+ LLTextureStatsUploader tsu;
+ std::string url = "http://blahblahblah";
+ LLSD texture_stats;
+ tsu.uploadStatsToSimulator(url, texture_stats);
+ ensure_equals("did the right url get called?", most_recent_url, url);
+ ensure_equals("did the right body get sent?", most_recent_body, texture_stats);
+ }
+
+ // does it not call out to the provided url if we send it an ungranted cap?
+ template<> template<>
+ void texturestatsuploader_object_t::test<3>()
+ {
+ LLTextureStatsUploader tsu;
+
+ // this url left intentionally blank to mirror
+ // not getting a cap in the caller.
+ std::string url_for_ungranted_cap = "";
+
+ LLSD texture_stats;
+ std::string most_recent_url_before_test = most_recent_url;
+ tsu.uploadStatsToSimulator(url_for_ungranted_cap, texture_stats);
+
+ ensure_equals("hopefully no url got called!", most_recent_url, most_recent_url_before_test);
+ }
+
+ // does it call out if the data is empty?
+ // should it even do that?
+}
+
diff --git a/indra/newview/tests/llviewerhelputil_test.cpp b/indra/newview/tests/llviewerhelputil_test.cpp
new file mode 100644
index 0000000000..297d98ad8d
--- /dev/null
+++ b/indra/newview/tests/llviewerhelputil_test.cpp
@@ -0,0 +1,173 @@
+/**
+ * @file llviewerhelputil_test.cpp
+ * @brief LLViewerHelpUtil tests
+ * @author Tofu Linden
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+// Precompiled header
+#include "../llviewerprecompiledheaders.h"
+
+#include "../test/lltut.h"
+
+#include "../llviewerhelputil.h"
+#include "../llweb.h"
+#include "llcontrol.h"
+
+#include <iostream>
+
+// values for all of the supported substitutions parameters
+static std::string gHelpURL;
+static std::string gVersion;
+static std::string gChannel;
+static std::string gLanguage;
+static std::string gGrid;
+static std::string gOS;
+
+//----------------------------------------------------------------------------
+// Mock objects for the dependencies of the code we're testing
+
+LLControlGroup::LLControlGroup(const std::string& name)
+ : LLInstanceTracker<LLControlGroup, std::string>(name) {}
+LLControlGroup::~LLControlGroup() {}
+BOOL LLControlGroup::declareString(const std::string& name,
+ const std::string& initial_val,
+ const std::string& comment,
+ BOOL persist) {return TRUE;}
+void LLControlGroup::setString(const std::string& name, const std::string& val){}
+std::string LLControlGroup::getString(const std::string& name)
+{
+ if (name == "HelpURLFormat")
+ return gHelpURL;
+ return "";
+}
+LLControlGroup gSavedSettings("test");
+
+static void substitute_string(std::string &input, const std::string &search, const std::string &replace)
+{
+ size_t pos = input.find(search);
+ while (pos != std::string::npos)
+ {
+ input = input.replace(pos, search.size(), replace);
+ pos = input.find(search);
+ }
+}
+
+class LLAgent
+{
+public:
+ LLAgent() {}
+ ~LLAgent() {}
+#ifdef __GNUC__
+ __attribute__ ((noinline))
+#endif
+ BOOL isGodlike() const { return FALSE; }
+private:
+ int dummy;
+};
+LLAgent gAgent;
+
+std::string LLWeb::expandURLSubstitutions(const std::string &url,
+ const LLSD &default_subs)
+{
+ (void)gAgent.isGodlike(); // ref symbol to stop compiler from stripping it
+ std::string new_url = url;
+ substitute_string(new_url, "[TOPIC]", default_subs["TOPIC"].asString());
+ substitute_string(new_url, "[VERSION]", gVersion);
+ substitute_string(new_url, "[CHANNEL]", gChannel);
+ substitute_string(new_url, "[LANGUAGE]", gLanguage);
+ substitute_string(new_url, "[GRID]", gGrid);
+ substitute_string(new_url, "[OS]", gOS);
+ return new_url;
+}
+
+
+//----------------------------------------------------------------------------
+
+namespace tut
+{
+ struct viewerhelputil
+ {
+ };
+
+ typedef test_group<viewerhelputil> viewerhelputil_t;
+ typedef viewerhelputil_t::object viewerhelputil_object_t;
+ tut::viewerhelputil_t tut_viewerhelputil("viewerhelputil");
+
+ template<> template<>
+ void viewerhelputil_object_t::test<1>()
+ {
+ std::string topic("test_topic");
+ std::string subresult;
+
+ gHelpURL = "fooformat";
+ subresult = LLViewerHelpUtil::buildHelpURL(topic);
+ ensure_equals("no substitution tags", subresult, "fooformat");
+
+ gHelpURL = "";
+ subresult = LLViewerHelpUtil::buildHelpURL(topic);
+ ensure_equals("blank substitution format", subresult, "");
+
+ gHelpURL = "[TOPIC]";
+ subresult = LLViewerHelpUtil::buildHelpURL(topic);
+ ensure_equals("topic name", subresult, "test_topic");
+
+ gHelpURL = "[LANGUAGE]";
+ gLanguage = "";
+ subresult = LLViewerHelpUtil::buildHelpURL(topic);
+ ensure_equals("simple substitution with blank", subresult, "");
+
+ gHelpURL = "[LANGUAGE]";
+ gLanguage = "Esperanto";
+ subresult = LLViewerHelpUtil::buildHelpURL(topic);
+ ensure_equals("simple substitution", subresult, "Esperanto");
+
+ gHelpURL = "http://secondlife.com/[LANGUAGE]";
+ gLanguage = "Gaelic";
+ subresult = LLViewerHelpUtil::buildHelpURL(topic);
+ ensure_equals("simple substitution with url", subresult, "http://secondlife.com/Gaelic");
+
+ gHelpURL = "[XXX]";
+ subresult = LLViewerHelpUtil::buildHelpURL(topic);
+ ensure_equals("unknown substitution", subresult, "[XXX]");
+
+ gHelpURL = "[LANGUAGE]/[LANGUAGE]";
+ gLanguage = "Esperanto";
+ subresult = LLViewerHelpUtil::buildHelpURL(topic);
+ ensure_equals("multiple substitution", subresult, "Esperanto/Esperanto");
+
+ gHelpURL = "http://[CHANNEL]/[VERSION]/[LANGUAGE]/[OS]/[GRID]/[XXX]";
+ gChannel = "Second Life Test";
+ gVersion = "2.0";
+ gLanguage = "gaelic";
+ gOS = "AmigaOS 2.1";
+ gGrid = "mysim";
+ subresult = LLViewerHelpUtil::buildHelpURL(topic);
+ ensure_equals("complex substitution", subresult, "http://Second Life Test/2.0/gaelic/AmigaOS 2.1/mysim/[XXX]");
+ }
+}
diff --git a/indra/newview/tests/llworldmap_test.cpp b/indra/newview/tests/llworldmap_test.cpp
new file mode 100644
index 0000000000..56cf86f6df
--- /dev/null
+++ b/indra/newview/tests/llworldmap_test.cpp
@@ -0,0 +1,523 @@
+/**
+ * @file llworldmap_test.cpp
+ * @author Merov Linden
+ * @date 2009-03-09
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ *
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header: almost always required for newview cpp files
+#include "../llviewerprecompiledheaders.h"
+// Class to test
+#include "../llworldmap.h"
+// Dependencies
+#include "../llviewerimagelist.h"
+#include "../llworldmapmessage.h"
+// Tut header
+#include "../test/lltut.h"
+
+// -------------------------------------------------------------------------------------------
+// Stubbing: Declarations required to link and run the class being tested
+// Notes:
+// * Add here stubbed implementation of the few classes and methods used in the class to be tested
+// * Add as little as possible (let the link errors guide you)
+// * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code)
+// * A simulator for a class can be implemented here. Please comment and document thoroughly.
+
+// Stub image calls
+LLViewerImageList::LLViewerImageList() { }
+LLViewerImageList::~LLViewerImageList() { }
+LLViewerImageList gImageList;
+LLViewerImage* LLViewerImageList::getImage(const LLUUID &image_id,
+ BOOL usemipmaps,
+ BOOL level_immediate,
+ LLGLint internal_format,
+ LLGLenum primary_format,
+ LLHost request_from_host)
+{ return NULL; }
+void LLViewerImage::setBoostLevel(S32 level) { }
+void LLImageGL::setAddressMode(LLTexUnit::eTextureAddressMode mode) { }
+
+// Stub related map calls
+LLWorldMapMessage::LLWorldMapMessage() { }
+LLWorldMapMessage::~LLWorldMapMessage() { }
+void LLWorldMapMessage::sendItemRequest(U32 type, U64 handle) { }
+void LLWorldMapMessage::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent) { }
+LLWorldMipmap::LLWorldMipmap() { }
+LLWorldMipmap::~LLWorldMipmap() { }
+void LLWorldMipmap::reset() { }
+void LLWorldMipmap::dropBoostLevels() { }
+void LLWorldMipmap::equalizeBoostLevels() { }
+LLPointer<LLViewerImage> LLWorldMipmap::getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load)
+{ return NULL; }
+
+// Stub other stuff
+BOOL gPacificDaylightTime;
+
+// End Stubbing
+// -------------------------------------------------------------------------------------------
+
+// -------------------------------------------------------------------------------------------
+// TUT
+// -------------------------------------------------------------------------------------------
+
+const F32 X_WORLD_TEST = 1000.0f * REGION_WIDTH_METERS;
+const F32 Y_WORLD_TEST = 2000.0f * REGION_WIDTH_METERS;
+const F32 Z_WORLD_TEST = 240.0f;
+const std::string ITEM_NAME_TEST = "Item Foo";
+const std::string TOOLTIP_TEST = "Tooltip Foo";
+
+const std::string SIM_NAME_TEST = "Sim Foo";
+
+namespace tut
+{
+ // Test wrapper declarations
+ struct iteminfo_test
+ {
+ // Instance to be tested
+ LLItemInfo* mItem;
+
+ // Constructor and destructor of the test wrapper
+ iteminfo_test()
+ {
+ LLUUID id;
+ mItem = new LLItemInfo(X_WORLD_TEST, Y_WORLD_TEST, ITEM_NAME_TEST, id);
+ }
+ ~iteminfo_test()
+ {
+ delete mItem;
+ }
+ };
+
+ struct siminfo_test
+ {
+ // Instance to be tested
+ LLSimInfo* mSim;
+
+ // Constructor and destructor of the test wrapper
+ siminfo_test()
+ {
+ U64 handle = to_region_handle_global(X_WORLD_TEST, Y_WORLD_TEST);
+ mSim = new LLSimInfo(handle);
+ }
+ ~siminfo_test()
+ {
+ delete mSim;
+ }
+ };
+
+ struct worldmap_test
+ {
+ // Instance to be tested
+ LLWorldMap* mWorld;
+
+ // Constructor and destructor of the test wrapper
+ worldmap_test()
+ {
+ mWorld = LLWorldMap::getInstance();
+ }
+ ~worldmap_test()
+ {
+ mWorld = NULL;
+ }
+ };
+
+ // Tut templating thingamagic: test group, object and test instance
+ typedef test_group<iteminfo_test> iteminfo_t;
+ typedef iteminfo_t::object iteminfo_object_t;
+ tut::iteminfo_t tut_iteminfo("iteminfo");
+
+ typedef test_group<siminfo_test> siminfo_t;
+ typedef siminfo_t::object siminfo_object_t;
+ tut::siminfo_t tut_siminfo("siminfo");
+
+ typedef test_group<worldmap_test> worldmap_t;
+ typedef worldmap_t::object worldmap_object_t;
+ tut::worldmap_t tut_worldmap("worldmap");
+
+ // ---------------------------------------------------------------------------------------
+ // Test functions
+ // Notes:
+ // * Test as many as you possibly can without requiring a full blown simulation of everything
+ // * The tests are executed in sequence so the test instance state may change between calls
+ // * Remember that you cannot test private methods with tut
+ // ---------------------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------------------
+ // Test the LLItemInfo interface
+ // ---------------------------------------------------------------------------------------
+ template<> template<>
+ void iteminfo_object_t::test<1>()
+ {
+ // Test 1 : setCount() / getCount()
+ mItem->setCount(10);
+ ensure("LLItemInfo::setCount() test failed", mItem->getCount() == 10);
+ // Test 2 : setTooltip() / getToolTip()
+ std::string tooltip = TOOLTIP_TEST;
+ mItem->setTooltip(tooltip);
+ ensure("LLItemInfo::setTooltip() test failed", mItem->getToolTip() == TOOLTIP_TEST);
+ // Test 3 : setElevation() / getGlobalPosition()
+ mItem->setElevation(Z_WORLD_TEST);
+ LLVector3d pos = mItem->getGlobalPosition();
+ LLVector3d ref(X_WORLD_TEST, Y_WORLD_TEST, Z_WORLD_TEST);
+ ensure("LLItemInfo::getGlobalPosition() test failed", pos == ref);
+ // Test 4 : getName()
+ std::string name = mItem->getName();
+ ensure("LLItemInfo::getName() test failed", name == ITEM_NAME_TEST);
+ // Test 5 : isName()
+ ensure("LLItemInfo::isName() test failed", mItem->isName(name));
+ // Test 6 : getUUID()
+ LLUUID id;
+ ensure("LLItemInfo::getUUID() test failed", mItem->getUUID() == id);
+ // Test 7 : getRegionHandle()
+ U64 handle = to_region_handle_global(X_WORLD_TEST, Y_WORLD_TEST);
+ ensure("LLItemInfo::getRegionHandle() test failed", mItem->getRegionHandle() == handle);
+ }
+ // ---------------------------------------------------------------------------------------
+ // Test the LLSimInfo interface
+ // ---------------------------------------------------------------------------------------
+ // Test Setters and Accessors methods
+ template<> template<>
+ void siminfo_object_t::test<1>()
+ {
+ // Test 1 : setName() / getName()
+ std::string name = SIM_NAME_TEST;
+ mSim->setName(name);
+ ensure("LLSimInfo::setName() test failed", mSim->getName() == SIM_NAME_TEST);
+ // Test 2 : isName()
+ ensure("LLSimInfo::isName() test failed", mSim->isName(name));
+ // Test 3 : getGlobalPos()
+ LLVector3 local;
+ LLVector3d ref(X_WORLD_TEST, Y_WORLD_TEST, 0.0f);
+ LLVector3d pos = mSim->getGlobalPos(local);
+ ensure("LLSimInfo::getGlobalPos() test failed", pos == ref);
+ // Test 4 : getGlobalOrigin()
+ pos = mSim->getGlobalOrigin();
+ ensure("LLSimInfo::getGlobalOrigin() test failed", pos == ref);
+ // Test 5 : clearImage()
+ try {
+ mSim->clearImage();
+ } catch (...) {
+ fail("LLSimInfo::clearImage() test failed");
+ }
+ // Test 6 : dropImagePriority()
+ try {
+ mSim->dropImagePriority();
+ } catch (...) {
+ fail("LLSimInfo::dropImagePriority() test failed");
+ }
+ // Test 7 : updateAgentCount()
+ try {
+ mSim->updateAgentCount(0.0f);
+ } catch (...) {
+ fail("LLSimInfo::updateAgentCount() test failed");
+ }
+ // Test 8 : getAgentCount()
+ S32 agents = mSim->getAgentCount();
+ ensure("LLSimInfo::getAgentCount() test failed", agents == 0);
+ // Test 9 : setLandForSaleImage() / getLandForSaleImage()
+ LLUUID id;
+ mSim->setLandForSaleImage(id);
+ LLPointer<LLViewerImage> image = mSim->getLandForSaleImage();
+ ensure("LLSimInfo::getLandForSaleImage() test failed", image.isNull());
+ // Test 10 : isPG()
+ mSim->setAccess(SIM_ACCESS_PG);
+ ensure("LLSimInfo::isPG() test failed", mSim->isPG());
+ // Test 11 : isDown()
+ mSim->setAccess(SIM_ACCESS_DOWN);
+ ensure("LLSimInfo::isDown() test failed", mSim->isDown());
+ // Test 12 : Access strings can't be accessed from unit test...
+ //ensure("LLSimInfo::getAccessString() test failed", mSim->getAccessString() == "Offline");
+ // Test 13 : Region strings can't be accessed from unit test...
+ //mSim->setRegionFlags(REGION_FLAGS_SANDBOX);
+ //ensure("LLSimInfo::setRegionFlags() test failed", mSim->getFlagsString() == "Sandbox");
+ }
+ // Test management of LLInfoItem lists
+ template<> template<>
+ void siminfo_object_t::test<2>()
+ {
+ // Test 14 : clearItems()
+ try {
+ mSim->clearItems();
+ } catch (...) {
+ fail("LLSimInfo::clearItems() at init test failed");
+ }
+
+ // Test 15 : Verify that all the lists are empty
+ LLSimInfo::item_info_list_t list;
+ list = mSim->getTeleHub();
+ ensure("LLSimInfo::getTeleHub() empty at init test failed", list.empty());
+ list = mSim->getInfoHub();
+ ensure("LLSimInfo::getInfoHub() empty at init test failed", list.empty());
+ list = mSim->getPGEvent();
+ ensure("LLSimInfo::getPGEvent() empty at init test failed", list.empty());
+ list = mSim->getMatureEvent();
+ ensure("LLSimInfo::getMatureEvent() empty at init test failed", list.empty());
+ list = mSim->getLandForSale();
+ ensure("LLSimInfo::getLandForSale() empty at init test failed", list.empty());
+ list = mSim->getAgentLocation();
+ ensure("LLSimInfo::getAgentLocation() empty at init test failed", list.empty());
+
+ // Create an item to be inserted
+ LLUUID id;
+ LLItemInfo item(X_WORLD_TEST, Y_WORLD_TEST, ITEM_NAME_TEST, id);
+
+ // Insert the item in each list
+ mSim->insertTeleHub(item);
+ mSim->insertInfoHub(item);
+ mSim->insertPGEvent(item);
+ mSim->insertMatureEvent(item);
+ mSim->insertLandForSale(item);
+ mSim->insertAgentLocation(item);
+
+ // Test 16 : Verify that the lists contain 1 item each
+ list = mSim->getTeleHub();
+ ensure("LLSimInfo::insertTeleHub() test failed", list.size() == 1);
+ list = mSim->getInfoHub();
+ ensure("LLSimInfo::insertInfoHub() test failed", list.size() == 1);
+ list = mSim->getPGEvent();
+ ensure("LLSimInfo::insertPGEvent() test failed", list.size() == 1);
+ list = mSim->getMatureEvent();
+ ensure("LLSimInfo::insertMatureEvent() test failed", list.size() == 1);
+ list = mSim->getLandForSale();
+ ensure("LLSimInfo::insertLandForSale() test failed", list.size() == 1);
+ list = mSim->getAgentLocation();
+ ensure("LLSimInfo::insertAgentLocation() test failed", list.size() == 1);
+
+ // Test 17 : clearItems()
+ try {
+ mSim->clearItems();
+ } catch (...) {
+ fail("LLSimInfo::clearItems() at end test failed");
+ }
+
+ // Test 18 : Verify that all the lists are empty again... *except* agent which is persisted!! (on purpose)
+ list = mSim->getTeleHub();
+ ensure("LLSimInfo::getTeleHub() empty after clear test failed", list.empty());
+ list = mSim->getInfoHub();
+ ensure("LLSimInfo::getInfoHub() empty after clear test failed", list.empty());
+ list = mSim->getPGEvent();
+ ensure("LLSimInfo::getPGEvent() empty after clear test failed", list.empty());
+ list = mSim->getMatureEvent();
+ ensure("LLSimInfo::getMatureEvent() empty after clear test failed", list.empty());
+ list = mSim->getLandForSale();
+ ensure("LLSimInfo::getLandForSale() empty after clear test failed", list.empty());
+ list = mSim->getAgentLocation();
+ ensure("LLSimInfo::getAgentLocation() empty after clear test failed", list.size() == 1);
+ }
+
+ // ---------------------------------------------------------------------------------------
+ // Test the LLWorldMap interface
+ // ---------------------------------------------------------------------------------------
+ // Test Setters and Accessors methods
+ template<> template<>
+ void worldmap_object_t::test<1>()
+ {
+ // Test 1 : reset()
+ try {
+ mWorld->reset();
+ } catch (...) {
+ fail("LLWorldMap::reset() at init test failed");
+ }
+ // Test 2 : clearImageRefs()
+ try {
+ mWorld->clearImageRefs();
+ } catch (...) {
+ fail("LLWorldMap::clearImageRefs() test failed");
+ }
+ // Test 3 : dropImagePriorities()
+ try {
+ mWorld->dropImagePriorities();
+ } catch (...) {
+ fail("LLWorldMap::dropImagePriorities() test failed");
+ }
+ // Test 4 : reloadItems()
+ try {
+ mWorld->reloadItems(true);
+ } catch (...) {
+ fail("LLWorldMap::reloadItems() test failed");
+ }
+ // Test 5 : updateRegions()
+ try {
+ mWorld->updateRegions(1000, 1000, 1004, 1004);
+ } catch (...) {
+ fail("LLWorldMap::updateRegions() test failed");
+ }
+ // Test 6 : equalizeBoostLevels()
+ try {
+ mWorld->equalizeBoostLevels();
+ } catch (...) {
+ fail("LLWorldMap::equalizeBoostLevels() test failed");
+ }
+ // Test 7 : getObjectsTile()
+ try {
+ LLPointer<LLViewerImage> image = mWorld->getObjectsTile((U32)(X_WORLD_TEST/REGION_WIDTH_METERS), (U32)(Y_WORLD_TEST/REGION_WIDTH_METERS), 1);
+ ensure("LLWorldMap::getObjectsTile() failed", image.isNull());
+ } catch (...) {
+ fail("LLWorldMap::getObjectsTile() test failed with exception");
+ }
+ }
+ // Test management of LLSimInfo lists
+ template<> template<>
+ void worldmap_object_t::test<2>()
+ {
+ // Test 8 : reset()
+ try {
+ mWorld->reset();
+ } catch (...) {
+ fail("LLWorldMap::reset() at init test failed");
+ }
+
+ // Test 9 : Verify that all the region list is empty
+ LLWorldMap::sim_info_map_t list;
+ list = mWorld->getRegionMap();
+ ensure("LLWorldMap::getRegionMap() empty at init test failed", list.empty());
+
+ // Test 10 : Insert a region
+ bool success;
+ LLUUID id;
+ std::string name_sim = SIM_NAME_TEST;
+ success = mWorld->insertRegion( U32(X_WORLD_TEST),
+ U32(Y_WORLD_TEST),
+ name_sim,
+ id,
+ SIM_ACCESS_PG,
+ REGION_FLAGS_SANDBOX);
+ list = mWorld->getRegionMap();
+ ensure("LLWorldMap::insertRegion() failed", success && (list.size() == 1));
+
+ // Test 11 : Insert an item in the same region -> number of regions doesn't increase
+ std::string name_item = ITEM_NAME_TEST;
+ success = mWorld->insertItem( U32(X_WORLD_TEST + REGION_WIDTH_METERS/2),
+ U32(Y_WORLD_TEST + REGION_WIDTH_METERS/2),
+ name_item,
+ id,
+ MAP_ITEM_LAND_FOR_SALE,
+ 0, 0);
+ list = mWorld->getRegionMap();
+ ensure("LLWorldMap::insertItem() in existing region failed", success && (list.size() == 1));
+
+ // Test 12 : Insert an item in another region -> number of regions increases
+ success = mWorld->insertItem( U32(X_WORLD_TEST + REGION_WIDTH_METERS*2),
+ U32(Y_WORLD_TEST + REGION_WIDTH_METERS*2),
+ name_item,
+ id,
+ MAP_ITEM_LAND_FOR_SALE,
+ 0, 0);
+ list = mWorld->getRegionMap();
+ ensure("LLWorldMap::insertItem() in unexisting region failed", success && (list.size() == 2));
+
+ // Test 13 : simInfoFromPosGlobal() in region
+ LLVector3d pos1( X_WORLD_TEST + REGION_WIDTH_METERS*2 + REGION_WIDTH_METERS/2,
+ Y_WORLD_TEST + REGION_WIDTH_METERS*2 + REGION_WIDTH_METERS/2,
+ 0.0f);
+ LLSimInfo* sim;
+ sim = mWorld->simInfoFromPosGlobal(pos1);
+ ensure("LLWorldMap::simInfoFromPosGlobal() test on existing region failed", sim != NULL);
+
+ // Test 14 : simInfoFromPosGlobal() outside region
+ LLVector3d pos2( X_WORLD_TEST + REGION_WIDTH_METERS*4 + REGION_WIDTH_METERS/2,
+ Y_WORLD_TEST + REGION_WIDTH_METERS*4 + REGION_WIDTH_METERS/2,
+ 0.0f);
+ sim = mWorld->simInfoFromPosGlobal(pos2);
+ ensure("LLWorldMap::simInfoFromPosGlobal() test outside region failed", sim == NULL);
+
+ // Test 15 : simInfoFromName()
+ sim = mWorld->simInfoFromName(name_sim);
+ ensure("LLWorldMap::simInfoFromName() test on existing region failed", sim != NULL);
+
+ // Test 16 : simInfoFromHandle()
+ U64 handle = to_region_handle_global(X_WORLD_TEST, Y_WORLD_TEST);
+ sim = mWorld->simInfoFromHandle(handle);
+ ensure("LLWorldMap::simInfoFromHandle() test on existing region failed", sim != NULL);
+
+ // Test 17 : simNameFromPosGlobal()
+ LLVector3d pos3( X_WORLD_TEST + REGION_WIDTH_METERS/2,
+ Y_WORLD_TEST + REGION_WIDTH_METERS/2,
+ 0.0f);
+ success = mWorld->simNameFromPosGlobal(pos3, name_sim);
+ ensure("LLWorldMap::simNameFromPosGlobal() test on existing region failed", success && (name_sim == SIM_NAME_TEST));
+
+ // Test 18 : reset()
+ try {
+ mWorld->reset();
+ } catch (...) {
+ fail("LLWorldMap::reset() at end test failed");
+ }
+
+ // Test 19 : Verify that all the region list is empty
+ list = mWorld->getRegionMap();
+ ensure("LLWorldMap::getRegionMap() empty at end test failed", list.empty());
+ }
+ // Test tracking
+ template<> template<>
+ void worldmap_object_t::test<3>()
+ {
+ // Point to track
+ LLVector3d pos( X_WORLD_TEST + REGION_WIDTH_METERS/2, Y_WORLD_TEST + REGION_WIDTH_METERS/2, Z_WORLD_TEST);
+
+ // Test 20 : no tracking
+ mWorld->cancelTracking();
+ ensure("LLWorldMap::cancelTracking() at begin test failed", mWorld->isTracking() == false);
+
+ // Test 21 : set tracking
+ mWorld->setTracking(pos);
+ ensure("LLWorldMap::setTracking() failed", mWorld->isTracking() && !mWorld->isTrackingValidLocation());
+
+ // Test 22 : set click and commit flags
+ mWorld->setTrackingDoubleClick();
+ ensure("LLWorldMap::setTrackingDoubleClick() failed", mWorld->isTrackingDoubleClick());
+ mWorld->setTrackingCommit();
+ ensure("LLWorldMap::setTrackingCommit() failed", mWorld->isTrackingCommit());
+
+ // Test 23 : in rectangle test
+ bool inRect = mWorld->isTrackingInRectangle( X_WORLD_TEST, Y_WORLD_TEST,
+ X_WORLD_TEST + REGION_WIDTH_METERS,
+ Y_WORLD_TEST + REGION_WIDTH_METERS);
+ ensure("LLWorldMap::isTrackingInRectangle() in rectangle failed", inRect);
+ inRect = mWorld->isTrackingInRectangle( X_WORLD_TEST + REGION_WIDTH_METERS,
+ Y_WORLD_TEST + REGION_WIDTH_METERS,
+ X_WORLD_TEST + 2 * REGION_WIDTH_METERS,
+ Y_WORLD_TEST + 2 * REGION_WIDTH_METERS);
+ ensure("LLWorldMap::isTrackingInRectangle() outside rectangle failed", !inRect);
+
+ // Test 24 : set tracking to valid and invalid
+ mWorld->setTrackingValid();
+ ensure("LLWorldMap::setTrackingValid() failed", mWorld->isTrackingValidLocation() && !mWorld->isTrackingInvalidLocation());
+ mWorld->setTrackingInvalid();
+ ensure("LLWorldMap::setTrackingInvalid() failed", !mWorld->isTrackingValidLocation() && mWorld->isTrackingInvalidLocation());
+
+ // Test 25 : getTrackedPositionGlobal()
+ LLVector3d res = mWorld->getTrackedPositionGlobal();
+ ensure("LLWorldMap::getTrackedPositionGlobal() failed", res == pos);
+
+ // Test 26 : reset tracking
+ mWorld->cancelTracking();
+ ensure("LLWorldMap::cancelTracking() at end test failed", mWorld->isTracking() == false);
+ }
+}
diff --git a/indra/newview/tests/llworldmipmap_test.cpp b/indra/newview/tests/llworldmipmap_test.cpp
new file mode 100644
index 0000000000..9938175c55
--- /dev/null
+++ b/indra/newview/tests/llworldmipmap_test.cpp
@@ -0,0 +1,176 @@
+/**
+ * @file llworldmipmap_test.cpp
+ * @author Merov Linden
+ * @date 2009-02-03
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ *
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header: almost always required for newview cpp files
+#include "../llviewerprecompiledheaders.h"
+// Class to test
+#include "../llworldmipmap.h"
+// Dependencies
+#include "../llviewerimagelist.h"
+// Tut header
+#include "../test/lltut.h"
+
+// -------------------------------------------------------------------------------------------
+// Stubbing: Declarations required to link and run the class being tested
+// Notes:
+// * Add here stubbed implementation of the few classes and methods used in the class to be tested
+// * Add as little as possible (let the link errors guide you)
+// * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code)
+// * A simulator for a class can be implemented here. Please comment and document thoroughly.
+
+LLViewerImageList::LLViewerImageList() { }
+LLViewerImageList::~LLViewerImageList() { }
+
+LLViewerImageList gImageList;
+
+LLViewerImage* LLViewerImageList::getImageFromUrl(const std::string& url,
+ BOOL usemipmaps,
+ BOOL level_immediate,
+ LLGLint internal_format,
+ LLGLenum primary_format,
+ const LLUUID& force_id)
+{ return NULL; }
+void LLViewerImage::setBoostLevel(S32 level) { }
+
+// End Stubbing
+// -------------------------------------------------------------------------------------------
+
+// -------------------------------------------------------------------------------------------
+// TUT
+// -------------------------------------------------------------------------------------------
+namespace tut
+{
+ // Test wrapper declaration
+ struct worldmipmap_test
+ {
+ // Derived test class
+ class LLTestWorldMipmap : public LLWorldMipmap
+ {
+ // Put here stubbs of virtual methods we shouldn't call all the way down
+ };
+ // Instance to be tested
+ LLTestWorldMipmap* mMap;
+
+ // Constructor and destructor of the test wrapper
+ worldmipmap_test()
+ {
+ mMap = new LLTestWorldMipmap;
+ }
+ ~worldmipmap_test()
+ {
+ delete mMap;
+ }
+ };
+
+ // Tut templating thingamagic: test group, object and test instance
+ typedef test_group<worldmipmap_test> worldmipmap_t;
+ typedef worldmipmap_t::object worldmipmap_object_t;
+ tut::worldmipmap_t tut_worldmipmap("worldmipmap");
+
+ // ---------------------------------------------------------------------------------------
+ // Test functions
+ // Notes:
+ // * Test as many as you possibly can without requiring a full blown simulation of everything
+ // * The tests are executed in sequence so the test instance state may change between calls
+ // * Remember that you cannot test private methods with tut
+ // ---------------------------------------------------------------------------------------
+ // Test static methods
+ // Test 1 : scaleToLevel()
+ template<> template<>
+ void worldmipmap_object_t::test<1>()
+ {
+ S32 level = mMap->scaleToLevel(0.0);
+ ensure("scaleToLevel() test 1 failed", level == LLWorldMipmap::MAP_LEVELS);
+ level = mMap->scaleToLevel(LLWorldMipmap::MAP_TILE_SIZE);
+ ensure("scaleToLevel() test 2 failed", level == 1);
+ level = mMap->scaleToLevel(10 * LLWorldMipmap::MAP_TILE_SIZE);
+ ensure("scaleToLevel() test 3 failed", level == 1);
+ }
+ // Test 2 : globalToMipmap()
+ template<> template<>
+ void worldmipmap_object_t::test<2>()
+ {
+ U32 grid_x, grid_y;
+ mMap->globalToMipmap(1000.f*REGION_WIDTH_METERS, 1000.f*REGION_WIDTH_METERS, 1, &grid_x, &grid_y);
+ ensure("globalToMipmap() test 1 failed", (grid_x == 1000) && (grid_y == 1000));
+ mMap->globalToMipmap(0.0, 0.0, LLWorldMipmap::MAP_LEVELS, &grid_x, &grid_y);
+ ensure("globalToMipmap() test 2 failed", (grid_x == 0) && (grid_y == 0));
+ }
+ // Test 3 : getObjectsTile()
+ template<> template<>
+ void worldmipmap_object_t::test<3>()
+ {
+ // Depends on some inline methods in LLViewerImage... Thinking about how to make this work
+ // LLPointer<LLViewerImage> img = mMap->getObjectsTile(0, 0, 1);
+ // ensure("getObjectsTile() test failed", img.isNull());
+ }
+ // Test 4 : equalizeBoostLevels()
+ template<> template<>
+ void worldmipmap_object_t::test<4>()
+ {
+ try
+ {
+ mMap->equalizeBoostLevels();
+ }
+ catch (...)
+ {
+ fail("equalizeBoostLevels() test failed");
+ }
+ }
+ // Test 5 : dropBoostLevels()
+ template<> template<>
+ void worldmipmap_object_t::test<5>()
+ {
+ try
+ {
+ mMap->dropBoostLevels();
+ }
+ catch (...)
+ {
+ fail("dropBoostLevels() test failed");
+ }
+ }
+ // Test 6 : reset()
+ template<> template<>
+ void worldmipmap_object_t::test<6>()
+ {
+ try
+ {
+ mMap->reset();
+ }
+ catch (...)
+ {
+ fail("reset() test failed");
+ }
+ }
+}
diff --git a/indra/newview/tests/llxmlrpclistener_test.cpp b/indra/newview/tests/llxmlrpclistener_test.cpp
new file mode 100644
index 0000000000..c94ba0a3e8
--- /dev/null
+++ b/indra/newview/tests/llxmlrpclistener_test.cpp
@@ -0,0 +1,230 @@
+/*
+ * @file llxmlrpclistener_test.cpp
+ * @author Nat Goodspeed
+ * @date 2009-03-20
+ * @brief Test for llxmlrpclistener.
+ *
+ * $LicenseInfo:firstyear=2009&license=internal$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "../llviewerprecompiledheaders.h"
+// associated header
+#include "../llxmlrpclistener.h"
+// STL headers
+#include <iomanip>
+// std headers
+// external library headers
+// other Linden headers
+#include "../test/lltut.h"
+#include "../llxmlrpctransaction.h"
+#include "llevents.h"
+#include "lleventfilter.h"
+#include "llsd.h"
+#include "llcontrol.h"
+#include "tests/wrapllerrs.h"
+
+LLControlGroup gSavedSettings("Global");
+
+/*****************************************************************************
+* TUT
+*****************************************************************************/
+namespace tut
+{
+ struct data
+ {
+ data():
+ pumps(LLEventPumps::instance()),
+ uri("http://127.0.0.1:8000")
+ {
+ // These variables are required by machinery used by
+ // LLXMLRPCTransaction. The values reflect reality for this test
+ // executable; hopefully these values are correct.
+ gSavedSettings.declareBOOL("BrowserProxyEnabled", FALSE, "", FALSE); // don't persist
+ gSavedSettings.declareBOOL("NoVerifySSLCert", TRUE, "", FALSE); // don't persist
+ }
+
+ // LLEventPump listener signature
+ bool captureReply(const LLSD& r)
+ {
+ reply = r;
+ return false;
+ }
+
+ LLSD reply;
+ LLEventPumps& pumps;
+ std::string uri;
+ };
+ typedef test_group<data> llxmlrpclistener_group;
+ typedef llxmlrpclistener_group::object object;
+ llxmlrpclistener_group llxmlrpclistenergrp("llxmlrpclistener");
+
+ template<> template<>
+ void object::test<1>()
+ {
+ set_test_name("request validation");
+ WrapLL_ERRS capture;
+ LLSD request;
+ request["uri"] = uri;
+ std::string threw;
+ try
+ {
+ pumps.obtain("LLXMLRPCTransaction").post(request);
+ }
+ catch (const WrapLL_ERRS::FatalException& e)
+ {
+ threw = e.what();
+ }
+ ensure_contains("threw exception", threw, "missing params");
+ ensure_contains("identified missing", threw, "method");
+ ensure_contains("identified missing", threw, "reply");
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ set_test_name("param types validation");
+ WrapLL_ERRS capture;
+ LLSD request;
+ request["uri"] = uri;
+ request["method"] = "hello";
+ request["reply"] = "reply";
+ LLSD& params(request["params"]);
+ params["who"]["specifically"] = "world"; // LLXMLRPCListener only handles scalar params
+ std::string threw;
+ try
+ {
+ pumps.obtain("LLXMLRPCTransaction").post(request);
+ }
+ catch (const WrapLL_ERRS::FatalException& e)
+ {
+ threw = e.what();
+ }
+ ensure_contains("threw exception", threw, "unknown type");
+ }
+
+ template<> template<>
+ void object::test<3>()
+ {
+ set_test_name("success case");
+ LLSD request;
+ request["uri"] = uri;
+ request["method"] = "hello";
+ request["reply"] = "reply";
+ LLSD& params(request["params"]);
+ params["who"] = "world";
+ // Set up a timeout filter so we don't spin forever waiting.
+ LLEventTimeout watchdog;
+ // Connect the timeout filter to the reply pump.
+ LLTempBoundListener temp(
+ pumps.obtain("reply").
+ listen("watchdog", boost::bind(&LLEventTimeout::post, boost::ref(watchdog), _1)));
+ // Now connect our target listener to the timeout filter.
+ watchdog.listen("captureReply", boost::bind(&data::captureReply, this, _1));
+ // Kick off the request...
+ reply.clear();
+ pumps.obtain("LLXMLRPCTransaction").post(request);
+ // Set the timer
+ F32 timeout(10);
+ watchdog.eventAfter(timeout, LLSD().insert("timeout", 0));
+ // and pump "mainloop" until we get something, whether from
+ // LLXMLRPCListener or from the watchdog filter.
+ LLTimer timer;
+ F32 start = timer.getElapsedTimeF32();
+ LLEventPump& mainloop(pumps.obtain("mainloop"));
+ while (reply.isUndefined())
+ {
+ mainloop.post(LLSD());
+ }
+ ensure("timeout works", (timer.getElapsedTimeF32() - start) < (timeout + 1));
+ ensure_equals(reply["responses"]["hi_there"].asString(), "Hello, world!");
+ }
+
+ template<> template<>
+ void object::test<4>()
+ {
+ set_test_name("bogus method");
+ LLSD request;
+ request["uri"] = uri;
+ request["method"] = "goodbye";
+ request["reply"] = "reply";
+ LLSD& params(request["params"]);
+ params["who"] = "world";
+ // Set up a timeout filter so we don't spin forever waiting.
+ LLEventTimeout watchdog;
+ // Connect the timeout filter to the reply pump.
+ LLTempBoundListener temp(
+ pumps.obtain("reply").
+ listen("watchdog", boost::bind(&LLEventTimeout::post, boost::ref(watchdog), _1)));
+ // Now connect our target listener to the timeout filter.
+ watchdog.listen("captureReply", boost::bind(&data::captureReply, this, _1));
+ // Kick off the request...
+ reply.clear();
+ pumps.obtain("LLXMLRPCTransaction").post(request);
+ // Set the timer
+ F32 timeout(10);
+ watchdog.eventAfter(timeout, LLSD().insert("timeout", 0));
+ // and pump "mainloop" until we get something, whether from
+ // LLXMLRPCListener or from the watchdog filter.
+ LLTimer timer;
+ F32 start = timer.getElapsedTimeF32();
+ LLEventPump& mainloop(pumps.obtain("mainloop"));
+ while (reply.isUndefined())
+ {
+ mainloop.post(LLSD());
+ }
+ ensure("timeout works", (timer.getElapsedTimeF32() - start) < (timeout + 1));
+ ensure_equals("XMLRPC error", reply["status"].asString(), "XMLRPCError");
+ }
+
+ template<> template<>
+ void object::test<5>()
+ {
+ set_test_name("bad type");
+ LLSD request;
+ request["uri"] = uri;
+ request["method"] = "getdict";
+ request["reply"] = "reply";
+ (void)request["params"];
+ // Set up a timeout filter so we don't spin forever waiting.
+ LLEventTimeout watchdog;
+ // Connect the timeout filter to the reply pump.
+ LLTempBoundListener temp(
+ pumps.obtain("reply").
+ listen("watchdog", boost::bind(&LLEventTimeout::post, boost::ref(watchdog), _1)));
+ // Now connect our target listener to the timeout filter.
+ watchdog.listen("captureReply", boost::bind(&data::captureReply, this, _1));
+ // Kick off the request...
+ reply.clear();
+ pumps.obtain("LLXMLRPCTransaction").post(request);
+ // Set the timer
+ F32 timeout(10);
+ watchdog.eventAfter(timeout, LLSD().insert("timeout", 0));
+ // and pump "mainloop" until we get something, whether from
+ // LLXMLRPCListener or from the watchdog filter.
+ LLTimer timer;
+ F32 start = timer.getElapsedTimeF32();
+ LLEventPump& mainloop(pumps.obtain("mainloop"));
+ while (reply.isUndefined())
+ {
+ mainloop.post(LLSD());
+ }
+ ensure("timeout works", (timer.getElapsedTimeF32() - start) < (timeout + 1));
+ ensure_equals(reply["status"].asString(), "BadType");
+ ensure_contains("bad type", reply["responses"]["nested_dict"].asString(), "bad XMLRPC type");
+ }
+} // namespace tut
+
+/*****************************************************************************
+* Resolve link errors: use real machinery here, since we intend to exchange
+* actual XML with a peer process.
+*****************************************************************************/
+// Including llxmlrpctransaction.cpp drags in the static LLXMLRPCListener
+// instantiated there. That's why it works to post requests to the LLEventPump
+// named "LLXMLRPCTransaction".
+#include "../llxmlrpctransaction.cpp"
+#include "llcontrol.cpp"
+#include "llxmltree.cpp"
+#include "llxmlparser.cpp"
diff --git a/indra/newview/tests/test_llxmlrpc_peer.py b/indra/newview/tests/test_llxmlrpc_peer.py
new file mode 100644
index 0000000000..cb8f7d26c4
--- /dev/null
+++ b/indra/newview/tests/test_llxmlrpc_peer.py
@@ -0,0 +1,59 @@
+#!/usr/bin/python
+"""\
+@file test_llxmlrpc_peer.py
+@author Nat Goodspeed
+@date 2008-10-09
+@brief This script asynchronously runs the executable (with args) specified on
+ the command line, returning its result code. While that executable is
+ running, we provide dummy local services for use by C++ tests.
+
+$LicenseInfo:firstyear=2008&license=viewergpl$
+Copyright (c) 2008, Linden Research, Inc.
+$/LicenseInfo$
+"""
+
+import os
+import sys
+from threading import Thread
+from SimpleXMLRPCServer import SimpleXMLRPCServer
+
+mydir = os.path.dirname(__file__) # expected to be .../indra/newview/tests/
+sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python"))
+sys.path.insert(1, os.path.join(mydir, os.pardir, os.pardir, "llmessage", "tests"))
+from testrunner import run, debug
+
+class TestServer(SimpleXMLRPCServer):
+ def _dispatch(self, method, params):
+ try:
+ func = getattr(self, method)
+ except AttributeError:
+ raise Exception('method "%s" is not supported' % method)
+ else:
+ # LLXMLRPCListener constructs XMLRPC parameters that arrive as a
+ # 1-tuple containing a dict.
+ return func(**(params[0]))
+
+ def hello(self, who):
+ # LLXMLRPCListener expects a dict return.
+ return {"hi_there": "Hello, %s!" % who}
+
+ def getdict(self):
+ return dict(nested_dict=dict(a=17, b=5))
+
+ def log_request(self, code, size=None):
+ # For present purposes, we don't want the request splattered onto
+ # stderr, as it would upset devs watching the test run
+ pass
+
+ def log_error(self, format, *args):
+ # Suppress error output as well
+ pass
+
+class ServerRunner(Thread):
+ def run(self):
+ server = TestServer(('127.0.0.1', 8000))
+ debug("Starting XMLRPC server...\n")
+ server.serve_forever()
+
+if __name__ == "__main__":
+ sys.exit(run(server=ServerRunner(name="xmlrpc"), *sys.argv[1:]))
diff --git a/indra/newview/tr.lproj/language.txt b/indra/newview/tr.lproj/language.txt
new file mode 100644
index 0000000000..44266bf283
--- /dev/null
+++ b/indra/newview/tr.lproj/language.txt
@@ -0,0 +1 @@
+tr \ No newline at end of file
diff --git a/indra/newview/uk.lproj/language.txt b/indra/newview/uk.lproj/language.txt
new file mode 100644
index 0000000000..fbc658f6f9
--- /dev/null
+++ b/indra/newview/uk.lproj/language.txt
@@ -0,0 +1 @@
+uk \ No newline at end of file
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 599882500c..15a51bbe14 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -40,62 +40,73 @@ sys.path.append(os.path.join(viewer_dir, '../lib/python/indra/util'))
from llmanifest import LLManifest, main, proper_windows_path, path_ancestors
class ViewerManifest(LLManifest):
+ def is_packaging_viewer(self):
+ # This is overridden by the WindowsManifest sub-class,
+ # which has different behavior if it is not packaging the viewer.
+ return True
+
def construct(self):
super(ViewerManifest, self).construct()
self.exclude("*.svn*")
self.path(src="../../scripts/messages/message_template.msg", dst="app_settings/message_template.msg")
self.path(src="../../etc/message.xml", dst="app_settings/message.xml")
- if self.prefix(src="app_settings"):
- self.exclude("logcontrol.xml")
- self.exclude("logcontrol-dev.xml")
- self.path("*.pem")
- self.path("*.ini")
- self.path("*.xml")
- self.path("*.db2")
-
- # include the entire shaders directory recursively
- self.path("shaders")
- # ... and the entire windlight directory
- self.path("windlight")
- self.end_prefix("app_settings")
-
- if self.prefix(src="character"):
- self.path("*.llm")
- self.path("*.xml")
- self.path("*.tga")
- self.end_prefix("character")
-
- # Include our fonts
- if self.prefix(src="fonts"):
- self.path("*.ttf")
- self.path("*.txt")
- self.end_prefix("fonts")
-
- # skins
- if self.prefix(src="skins"):
- self.path("paths.xml")
- # include the entire textures directory recursively
- if self.prefix(src="*/textures"):
- self.path("*.tga")
- self.path("*.j2c")
- self.path("*.jpg")
- self.path("*.png")
- self.path("textures.xml")
- self.end_prefix("*/textures")
- self.path("*/xui/*/*.xml")
- self.path("*/*.xml")
-
- # Local HTML files (e.g. loading screen)
- if self.prefix(src="*/html"):
- self.path("*.png")
- self.path("*/*/*.html")
- self.path("*/*/*.gif")
- self.end_prefix("*/html")
- self.end_prefix("skins")
-
- # Files in the newview/ directory
- self.path("gpu_table.txt")
+ if self.is_packaging_viewer():
+ if self.prefix(src="app_settings"):
+ self.exclude("logcontrol.xml")
+ self.exclude("logcontrol-dev.xml")
+ self.path("*.pem")
+ self.path("*.ini")
+ self.path("*.xml")
+ self.path("*.db2")
+
+ # include the entire shaders directory recursively
+ self.path("shaders")
+ # ... and the entire windlight directory
+ self.path("windlight")
+ self.end_prefix("app_settings")
+
+ if self.prefix(src="character"):
+ self.path("*.llm")
+ self.path("*.xml")
+ self.path("*.tga")
+ self.end_prefix("character")
+
+ # Include our fonts
+ if self.prefix(src="fonts"):
+ self.path("*.ttf")
+ self.path("*.txt")
+ self.end_prefix("fonts")
+
+ # skins
+ if self.prefix(src="skins"):
+ self.path("paths.xml")
+ # include the entire textures directory recursively
+ if self.prefix(src="*/textures"):
+ self.path("*/*.tga")
+ self.path("*/*.j2c")
+ self.path("*/*.jpg")
+ self.path("*/*.png")
+ self.path("*.tga")
+ self.path("*.j2c")
+ self.path("*.jpg")
+ self.path("*.png")
+ self.path("textures.xml")
+ self.end_prefix("*/textures")
+ self.path("*/xui/*/*.xml")
+ self.path("*/xui/*/widgets/*.xml")
+ self.path("*/*.xml")
+
+ # Local HTML files (e.g. loading screen)
+ if self.prefix(src="*/html"):
+ self.path("*.png")
+ self.path("*/*/*.html")
+ self.path("*/*/*.gif")
+ self.end_prefix("*/html")
+ self.end_prefix("skins")
+
+ # Files in the newview/ directory
+ self.path("gpu_table.txt")
def login_channel(self):
"""Channel reported for login and upgrade purposes ONLY;
@@ -158,41 +169,120 @@ class WindowsManifest(ViewerManifest):
else:
return ''.join(self.channel().split()) + '.exe'
+ def is_packaging_viewer(self):
+ # Some commands, files will only be included
+ # if we are packaging the viewer on windows.
+ # This manifest is also used to copy
+ # files during the build.
+ return 'package' in self.args['actions']
+
+ def test_msvcrt_and_copy_action(self, src, dst):
+ # This is used to test a dll manifest.
+ # It is used as a temporary override during the construct method
+ from test_win32_manifest import test_assembly_binding
+ if src and (os.path.exists(src) or os.path.islink(src)):
+ # ensure that destination path exists
+ self.cmakedirs(os.path.dirname(dst))
+ self.created_paths.append(dst)
+ if not os.path.isdir(src):
+ if(self.args['configuration'].lower() == 'debug'):
+ test_assembly_binding(src, "Microsoft.VC80.DebugCRT", "8.0.50727.4053")
+ else:
+ test_assembly_binding(src, "Microsoft.VC80.CRT", "8.0.50727.4053")
+ self.ccopy(src,dst)
+ else:
+ raise Exception("Directories are not supported by test_CRT_and_copy_action()")
+ else:
+ print "Doesn't exist:", src
+
+ def test_for_no_msvcrt_manifest_and_copy_action(self, src, dst):
+ # This is used to test that no manifest for the msvcrt exists.
+ # It is used as a temporary override during the construct method
+ from test_win32_manifest import test_assembly_binding
+ from test_win32_manifest import NoManifestException, NoMatchingAssemblyException
+ if src and (os.path.exists(src) or os.path.islink(src)):
+ # ensure that destination path exists
+ self.cmakedirs(os.path.dirname(dst))
+ self.created_paths.append(dst)
+ if not os.path.isdir(src):
+ try:
+ if(self.args['configuration'].lower() == 'debug'):
+ test_assembly_binding(src, "Microsoft.VC80.DebugCRT", "")
+ else:
+ test_assembly_binding(src, "Microsoft.VC80.CRT", "")
+ raise Exception("Unknown condition")
+ except NoManifestException, err:
+ pass
+ except NoMatchingAssemblyException, err:
+ pass
+
+ self.ccopy(src,dst)
+ else:
+ raise Exception("Directories are not supported by test_CRT_and_copy_action()")
+ else:
+ print "Doesn't exist:", src
+
+ def enable_crt_manifest_check(self):
+ if self.is_packaging_viewer():
+ WindowsManifest.copy_action = WindowsManifest.test_msvcrt_and_copy_action
+
+ def enable_no_crt_manifest_check(self):
+ if self.is_packaging_viewer():
+ WindowsManifest.copy_action = WindowsManifest.test_for_no_msvcrt_manifest_and_copy_action
+
+ def disable_manifest_check(self):
+ if self.is_packaging_viewer():
+ del WindowsManifest.copy_action
def construct(self):
super(WindowsManifest, self).construct()
- # the final exe is complicated because we're not sure where it's coming from,
- # nor do we have a fixed name for the executable
- self.path(self.find_existing_file('debug/secondlife-bin.exe', 'release/secondlife-bin.exe', 'relwithdebinfo/secondlife-bin.exe'), dst=self.final_exe())
- # need to get the kdu dll from any of the build directories as well
- try:
- self.path(self.find_existing_file('../llkdu/%s/llkdu.dll' % self.args['configuration'],
- '../../libraries/i686-win32/lib/release/llkdu.dll'),
- dst='llkdu.dll')
- pass
- except:
- print "Skipping llkdu.dll"
- pass
- self.path(src="licenses-win32.txt", dst="licenses.txt")
- self.path("featuretable.txt")
-
- # For use in crash reporting (generates minidumps)
- self.path("dbghelp.dll")
+ self.enable_crt_manifest_check()
- # For using FMOD for sound... DJS
- self.path("fmod.dll")
+ if self.is_packaging_viewer():
+ # Find secondlife-bin.exe in the 'configuration' dir, then rename it to the result of final_exe.
+ self.path(src='%s/secondlife-bin.exe' % self.args['configuration'], dst=self.final_exe())
- # For textures
- if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""):
- self.path("openjpeg.dll")
- self.end_prefix()
+ # Plugin host application
+ self.path(os.path.join(os.pardir,
+ 'llplugin', 'slplugin', self.args['configuration'], "slplugin.exe"),
+ "slplugin.exe")
+
+ self.disable_manifest_check()
+
+ # Get shared libs from the shared libs staging directory
+ if self.prefix(src=os.path.join(os.pardir, 'sharedlibs', self.args['configuration']),
+ dst=""):
+
+ self.enable_crt_manifest_check()
+
+ # Get kdu dll, continue if missing.
+ try:
+ self.path('llkdu.dll', dst='llkdu.dll')
+ except RuntimeError:
+ print "Skipping llkdu.dll"
+
+ # Get llcommon and deps. If missing assume static linkage and continue.
+ try:
+ self.path('llcommon.dll')
+ self.path('libapr-1.dll')
+ self.path('libaprutil-1.dll')
+ self.path('libapriconv-1.dll')
+ except RuntimeError, err:
+ print err.message
+ print "Skipping llcommon.dll (assuming llcommon was linked statically)"
+
+ self.disable_manifest_check()
+
+ # For textures
+ if self.args['configuration'].lower() == 'debug':
+ self.path("openjpegd.dll")
+ else:
+ self.path("openjpeg.dll")
- # Mozilla appears to force a dependency on these files so we need to ship it (CP) - updated to vc8 versions (nyx)
- # These need to be installed as a SxS assembly, currently a 'private' assembly.
- # See http://msdn.microsoft.com/en-us/library/ms235291(VS.80).aspx
- if self.prefix(src=self.args['configuration'], dst=""):
- if self.args['configuration'] == 'Debug':
+ # These need to be installed as a SxS assembly, currently a 'private' assembly.
+ # See http://msdn.microsoft.com/en-us/library/ms235291(VS.80).aspx
+ if self.args['configuration'].lower() == 'debug':
self.path("msvcr80d.dll")
self.path("msvcp80d.dll")
self.path("Microsoft.VC80.DebugCRT.manifest")
@@ -200,65 +290,122 @@ class WindowsManifest(ViewerManifest):
self.path("msvcr80.dll")
self.path("msvcp80.dll")
self.path("Microsoft.VC80.CRT.manifest")
+
+ # Vivox runtimes
+ self.path("SLVoice.exe")
+ self.path("vivoxsdk.dll")
+ self.path("ortp.dll")
+ self.path("libsndfile-1.dll")
+ self.path("zlib1.dll")
+ self.path("vivoxplatform.dll")
+ self.path("vivoxoal.dll")
+
+ # For google-perftools tcmalloc allocator.
+ try:
+ if self.args['configuration'].lower() == 'debug':
+ self.path('libtcmalloc_minimal-debug.dll')
+ else:
+ self.path('libtcmalloc_minimal.dll')
+ except:
+ print "Skipping libtcmalloc_minimal.dll"
+
self.end_prefix()
- # Mozilla runtime DLLs (CP)
- if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""):
- self.path("freebl3.dll")
- self.path("js3250.dll")
- self.path("nspr4.dll")
- self.path("nss3.dll")
- self.path("nssckbi.dll")
- self.path("plc4.dll")
- self.path("plds4.dll")
- self.path("smime3.dll")
- self.path("softokn3.dll")
- self.path("ssl3.dll")
- self.path("xpcom.dll")
- self.path("xul.dll")
+ self.path(src="licenses-win32.txt", dst="licenses.txt")
+ self.path("featuretable.txt")
+
+ # For use in crash reporting (generates minidumps)
+ self.path("dbghelp.dll")
+
+ # For using FMOD for sound... DJS
+ self.path("fmod.dll")
+
+ self.enable_no_crt_manifest_check()
+
+ # Media plugins - QuickTime
+ if self.prefix(src='../media_plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"):
+ self.path("media_plugin_quicktime.dll")
self.end_prefix()
- # Mozilla runtime misc files (CP)
- if self.prefix(src="app_settings/mozilla"):
- self.path("chrome/*.*")
- self.path("components/*.*")
- self.path("greprefs/*.*")
- self.path("plugins/*.*")
- self.path("res/*.*")
- self.path("res/*/*")
+ # Media plugins - WebKit/Qt
+ if self.prefix(src='../media_plugins/webkit/%s' % self.args['configuration'], dst="llplugin"):
+ self.path("media_plugin_webkit.dll")
self.end_prefix()
- # Mozilla hack to get it to accept newer versions of msvc*80.dll than are listed in manifest
- # necessary as llmozlib2-vc80.lib refers to an old version of msvc*80.dll - can be removed when new version of llmozlib is built - Nyx
- # The config file name needs to match the exe's name.
- self.path("SecondLife.exe.config", dst=self.final_exe() + ".config")
+ if self.args['configuration'].lower() == 'debug':
+ if self.prefix(src=os.path.join(os.pardir, os.pardir, 'libraries', 'i686-win32', 'lib', 'debug'),
+ dst="llplugin"):
+ self.path("libeay32.dll")
+ self.path("qtcored4.dll")
+ self.path("qtguid4.dll")
+ self.path("qtnetworkd4.dll")
+ self.path("qtopengld4.dll")
+ self.path("qtwebkitd4.dll")
+ self.path("qtxmlpatternsd4.dll")
+ self.path("ssleay32.dll")
+
+ # For WebKit/Qt plugin runtimes (image format plugins)
+ if self.prefix(src="imageformats", dst="imageformats"):
+ self.path("qgifd4.dll")
+ self.path("qicod4.dll")
+ self.path("qjpegd4.dll")
+ self.path("qmngd4.dll")
+ self.path("qsvgd4.dll")
+ self.path("qtiffd4.dll")
+ self.end_prefix()
- # Vivox runtimes
- if self.prefix(src="vivox-runtime/i686-win32", dst=""):
- self.path("SLVoice.exe")
- self.path("alut.dll")
- self.path("vivoxsdk.dll")
- self.path("ortp.dll")
- self.path("wrap_oal.dll")
- self.end_prefix()
+ # For WebKit/Qt plugin runtimes (codec/character encoding plugins)
+ if self.prefix(src="codecs", dst="codecs"):
+ self.path("qcncodecsd4.dll")
+ self.path("qjpcodecsd4.dll")
+ self.path("qkrcodecsd4.dll")
+ self.path("qtwcodecsd4.dll")
+ self.end_prefix()
+
+ self.end_prefix()
+ else:
+ if self.prefix(src=os.path.join(os.pardir, os.pardir, 'libraries', 'i686-win32', 'lib', 'release'),
+ dst="llplugin"):
+ self.path("libeay32.dll")
+ self.path("qtcore4.dll")
+ self.path("qtgui4.dll")
+ self.path("qtnetwork4.dll")
+ self.path("qtopengl4.dll")
+ self.path("qtwebkit4.dll")
+ self.path("qtxmlpatterns4.dll")
+ self.path("ssleay32.dll")
+
+ # For WebKit/Qt plugin runtimes (image format plugins)
+ if self.prefix(src="imageformats", dst="imageformats"):
+ self.path("qgif4.dll")
+ self.path("qico4.dll")
+ self.path("qjpeg4.dll")
+ self.path("qmng4.dll")
+ self.path("qsvg4.dll")
+ self.path("qtiff4.dll")
+ self.end_prefix()
+
+ # For WebKit/Qt plugin runtimes (codec/character encoding plugins)
+ if self.prefix(src="codecs", dst="codecs"):
+ self.path("qcncodecs4.dll")
+ self.path("qjpcodecs4.dll")
+ self.path("qkrcodecs4.dll")
+ self.path("qtwcodecs4.dll")
+ self.end_prefix()
+
+ self.end_prefix()
+
+ self.disable_manifest_check()
# pull in the crash logger and updater from other projects
- self.path(src=self.find_existing_file( # tag:"crash-logger" here as a cue to the exporter
- "../win_crash_logger/debug/windows-crash-logger.exe",
- "../win_crash_logger/release/windows-crash-logger.exe",
- "../win_crash_logger/relwithdebinfo/windows-crash-logger.exe"),
+ # tag:"crash-logger" here as a cue to the exporter
+ self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'],
dst="win_crash_logger.exe")
- self.path(src=self.find_existing_file(
- "../win_updater/debug/windows-updater.exe",
- "../win_updater/release/windows-updater.exe",
- "../win_updater/relwithdebinfo/windows-updater.exe"),
+ self.path(src='../win_updater/%s/windows-updater.exe' % self.args['configuration'],
dst="updater.exe")
- # For google-perftools tcmalloc allocator.
- #if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""):
- # self.path("libtcmalloc_minimal.dll")
- # self.end_prefix()
-
+ if not self.is_packaging_viewer():
+ self.package_file = "copied_deps"
def nsi_file_commands(self, install=True):
def wpath(path):
@@ -379,13 +526,24 @@ class WindowsManifest(ViewerManifest):
# We use the Unicode version of NSIS, available from
# http://www.scratchpaper.com/
- NSIS_path = 'C:\\Program Files\\NSIS\\Unicode\\makensis.exe'
+ # Check two paths, one for Program Files, and one for Program Files (x86).
+ # Yay 64bit windows.
+ NSIS_path = os.path.expandvars('${ProgramFiles}\\NSIS\\Unicode\\makensis.exe')
+ if not os.path.exists(NSIS_path):
+ NSIS_path = os.path.expandvars('${ProgramFiles(x86)}\\NSIS\\Unicode\\makensis.exe')
self.run_command('"' + proper_windows_path(NSIS_path) + '" ' + self.dst_path_of(tempfile))
# self.remove(self.dst_path_of(tempfile))
# If we're on a build machine, sign the code using our Authenticode certificate. JC
- sign_py = 'C:\\buildscripts\\code-signing\\sign.py'
+ sign_py = os.path.expandvars("${SIGN}")
+ if not sign_py or sign_py == "${SIGN}":
+ sign_py = 'C:\\buildscripts\\code-signing\\sign.py'
+ else:
+ sign_py = sign_py.replace('\\', '\\\\\\\\')
+ python = os.path.expandvars("${PYTHON}")
+ if not python or python == "${PYTHON}":
+ python = 'python'
if os.path.exists(sign_py):
- self.run_command(sign_py + ' ' + self.dst_path_of(installer_file))
+ self.run_command("%s %s %s" % (python, sign_py, self.dst_path_of(installer_file).replace('\\', '\\\\\\\\')))
else:
print "Skipping code signing,", sign_py, "does not exist"
self.created_path(self.dst_path_of(installer_file))
@@ -398,21 +556,11 @@ class DarwinManifest(ViewerManifest):
self.path(self.args['configuration'] + "/Second Life.app", dst="")
if self.prefix(src="", dst="Contents"): # everything goes in Contents
- # Expand the tar file containing the assorted mozilla bits into
- # <bundle>/Contents/MacOS/
- self.contents_of_tar(self.args['source']+'/mozilla-universal-darwin.tgz', 'MacOS')
-
self.path("Info-SecondLife.plist", dst="Info.plist")
# copy additional libs in <bundle>/Contents/MacOS/
self.path("../../libraries/universal-darwin/lib_release/libndofdev.dylib", dst="MacOS/libndofdev.dylib")
- # replace the default theme with our custom theme (so scrollbars work).
- if self.prefix(src="mozilla-theme", dst="MacOS/chrome"):
- self.path("classic.jar")
- self.path("classic.manifest")
- self.end_prefix("MacOS/chrome")
-
# most everything goes in the Resources directory
if self.prefix(src="", dst="Resources"):
super(DarwinManifest, self).construct()
@@ -438,24 +586,52 @@ class DarwinManifest(ViewerManifest):
self.path("German.lproj")
self.path("Japanese.lproj")
self.path("Korean.lproj")
+ self.path("da.lproj")
+ self.path("es.lproj")
+ self.path("fr.lproj")
+ self.path("hu.lproj")
+ self.path("it.lproj")
+ self.path("nl.lproj")
+ self.path("pl.lproj")
+ self.path("pt.lproj")
+ self.path("ru.lproj")
+ self.path("tr.lproj")
+ self.path("uk.lproj")
+ self.path("zh-Hans.lproj")
# SLVoice and vivox lols
- self.path("vivox-runtime/universal-darwin/libalut.dylib", "libalut.dylib")
- self.path("vivox-runtime/universal-darwin/libopenal.dylib", "libopenal.dylib")
+ self.path("vivox-runtime/universal-darwin/libsndfile.dylib", "libsndfile.dylib")
+ self.path("vivox-runtime/universal-darwin/libvivoxoal.dylib", "libvivoxoal.dylib")
self.path("vivox-runtime/universal-darwin/libortp.dylib", "libortp.dylib")
self.path("vivox-runtime/universal-darwin/libvivoxsdk.dylib", "libvivoxsdk.dylib")
+ self.path("vivox-runtime/universal-darwin/libvivoxplatform.dylib", "libvivoxplatform.dylib")
self.path("vivox-runtime/universal-darwin/SLVoice", "SLVoice")
+ libdir = "../../libraries/universal-darwin/lib_release"
+ dylibs = {}
+
# need to get the kdu dll from any of the build directories as well
- try:
- self.path(self.find_existing_file('../llkdu/%s/libllkdu.dylib' % self.args['configuration'],
- "../../libraries/universal-darwin/lib_release/libllkdu.dylib"),
- dst='libllkdu.dylib')
- pass
- except:
- print "Skipping libllkdu.dylib"
- pass
-
+ for lib in "llkdu", "llcommon":
+ libfile = "lib%s.dylib" % lib
+ try:
+ self.path(self.find_existing_file(os.path.join(os.pardir,
+ lib,
+ self.args['configuration'],
+ libfile),
+ os.path.join(libdir, libfile)),
+ dst=libfile)
+ except RuntimeError:
+ print "Skipping %s" % libfile
+ dylibs[lib] = False
+ else:
+ dylibs[lib] = True
+
+ if dylibs["llcommon"]:
+ for libfile in ("libapr-1.0.3.7.dylib",
+ "libaprutil-1.0.3.8.dylib",
+ "libexpat.0.5.0.dylib"):
+ self.path(os.path.join(libdir, libfile), libfile)
+
#libfmodwrapper.dylib
self.path(self.args['configuration'] + "/libfmodwrapper.dylib", "libfmodwrapper.dylib")
@@ -463,6 +639,35 @@ class DarwinManifest(ViewerManifest):
self.path("../mac_crash_logger/" + self.args['configuration'] + "/mac-crash-logger.app", "mac-crash-logger.app")
self.path("../mac_updater/" + self.args['configuration'] + "/mac-updater.app", "mac-updater.app")
+ # our apps dependencies on shared libs
+ if dylibs["llcommon"]:
+ mac_crash_logger_res_path = self.dst_path_of("mac-crash-logger.app/Contents/Resources")
+ mac_updater_res_path = self.dst_path_of("mac-updater.app/Contents/Resources")
+ for libfile in ("libllcommon.dylib",
+ "libapr-1.0.3.7.dylib",
+ "libaprutil-1.0.3.8.dylib",
+ "libexpat.0.5.0.dylib"):
+ target_lib = os.path.join('../../..', libfile)
+ self.run_command("ln -sf %(target)r %(link)r" %
+ {'target': target_lib,
+ 'link' : os.path.join(mac_crash_logger_res_path, libfile)}
+ )
+ self.run_command("ln -sf %(target)r %(link)r" %
+ {'target': target_lib,
+ 'link' : os.path.join(mac_updater_res_path, libfile)}
+ )
+
+ # plugin launcher
+ self.path("../llplugin/slplugin/" + self.args['configuration'] + "/SLPlugin", "SLPlugin")
+
+ # plugins
+ if self.prefix(src="", dst="llplugin"):
+ self.path("../media_plugins/quicktime/" + self.args['configuration'] + "/media_plugin_quicktime.dylib", "media_plugin_quicktime.dylib")
+ self.path("../media_plugins/webkit/" + self.args['configuration'] + "/media_plugin_webkit.dylib", "media_plugin_webkit.dylib")
+ self.path("../../libraries/universal-darwin/lib_release/libllqtwebkit.dylib", "libllqtwebkit.dylib")
+
+ self.end_prefix("llplugin")
+
# command line arguments for connecting to the proper grid
self.put_in_file(self.flags_list(), 'arguments.txt')
@@ -476,7 +681,7 @@ class DarwinManifest(ViewerManifest):
# This may be desirable for the final release. Or not.
if ("package" in self.args['actions'] or
"unpacked" in self.args['actions']):
- self.run_command('strip -S "%(viewer_binary)s"' %
+ self.run_command('strip -S %(viewer_binary)r' %
{ 'viewer_binary' : self.dst_path_of('Contents/MacOS/Second Life')})
@@ -505,12 +710,12 @@ class DarwinManifest(ViewerManifest):
# make sure we don't have stale files laying about
self.remove(sparsename, finalname)
- self.run_command('hdiutil create "%(sparse)s" -volname "%(vol)s" -fs HFS+ -type SPARSE -megabytes 300 -layout SPUD' % {
+ self.run_command('hdiutil create %(sparse)r -volname %(vol)r -fs HFS+ -type SPARSE -megabytes 700 -layout SPUD' % {
'sparse':sparsename,
'vol':volname})
# mount the image and get the name of the mount point and device node
- hdi_output = self.run_command('hdiutil attach -private "' + sparsename + '"')
+ hdi_output = self.run_command('hdiutil attach -private %r' % sparsename)
devfile = re.search("/dev/disk([0-9]+)[^s]", hdi_output).group(0).strip()
volpath = re.search('HFS\s+(.+)', hdi_output).group(1).strip()
@@ -544,24 +749,25 @@ class DarwinManifest(ViewerManifest):
self.copy_action(self.src_path_of(s), os.path.join(volpath, d))
# Hide the background image, DS_Store file, and volume icon file (set their "visible" bit)
- self.run_command('SetFile -a V "' + os.path.join(volpath, ".VolumeIcon.icns") + '"')
- self.run_command('SetFile -a V "' + os.path.join(volpath, "background.jpg") + '"')
- self.run_command('SetFile -a V "' + os.path.join(volpath, ".DS_Store") + '"')
+ for f in ".VolumeIcon.icns", "background.jpg", ".DS_Store":
+ self.run_command('SetFile -a V %r' % os.path.join(volpath, f))
# Create the alias file (which is a resource file) from the .r
- self.run_command('rez "' + self.src_path_of("installers/darwin/release-dmg/Applications-alias.r") + '" -o "' + os.path.join(volpath, "Applications") + '"')
+ self.run_command('rez %r -o %r' %
+ (self.src_path_of("installers/darwin/release-dmg/Applications-alias.r"),
+ os.path.join(volpath, "Applications")))
# Set the alias file's alias and custom icon bits
- self.run_command('SetFile -a AC "' + os.path.join(volpath, "Applications") + '"')
+ self.run_command('SetFile -a AC %r' % os.path.join(volpath, "Applications"))
# Set the disk image root's custom icon bit
- self.run_command('SetFile -a C "' + volpath + '"')
+ self.run_command('SetFile -a C %r' % volpath)
# Unmount the image
- self.run_command('hdiutil detach -force "' + devfile + '"')
+ self.run_command('hdiutil detach -force %r' % devfile)
print "Converting temp disk image to final disk image"
- self.run_command('hdiutil convert "%(sparse)s" -format UDZO -imagekey zlib-level=9 -o "%(final)s"' % {'sparse':sparsename, 'final':finalname})
+ self.run_command('hdiutil convert %(sparse)r -format UDZO -imagekey zlib-level=9 -o %(final)r' % {'sparse':sparsename, 'final':finalname})
# get rid of the temp file
self.package_file = finalname
self.remove(sparsename)
@@ -576,12 +782,15 @@ class LinuxManifest(ViewerManifest):
self.path("client-readme-voice.txt","README-linux-voice.txt")
self.path("client-readme-joystick.txt","README-linux-joystick.txt")
self.path("wrapper.sh","secondlife")
- self.path("handle_secondlifeprotocol.sh")
- self.path("register_secondlifeprotocol.sh")
+ self.path("handle_secondlifeprotocol.sh", "etc/handle_secondlifeprotocol.sh")
+ self.path("register_secondlifeprotocol.sh", "etc/register_secondlifeprotocol.sh")
+ self.path("refresh_desktop_app_entry.sh", "etc/refresh_desktop_app_entry.sh")
+ self.path("launch_url.sh","etc/launch_url.sh")
+ self.path("install.sh")
self.end_prefix("linux_tools")
# Create an appropriate gridargs.dat for this package, denoting required grid.
- self.put_in_file(self.flags_list(), 'gridargs.dat')
+ self.put_in_file(self.flags_list(), 'etc/gridargs.dat')
def package_finish(self):
@@ -613,13 +822,15 @@ class LinuxManifest(ViewerManifest):
'dst': self.get_dst_prefix(),
'inst': self.build_path_of(installer_name)})
try:
- # --numeric-owner hides the username of the builder for
- # security etc.
- self.run_command('tar -C %(dir)s --numeric-owner -cjf '
- '%(inst_path)s.tar.bz2 %(inst_name)s' % {
- 'dir': self.get_build_prefix(),
- 'inst_name': installer_name,
- 'inst_path':self.build_path_of(installer_name)})
+ # only create tarball if it's a release build.
+ if self.args['buildtype'].lower() == 'release':
+ # --numeric-owner hides the username of the builder for
+ # security etc.
+ self.run_command('tar -C %(dir)s --numeric-owner -cjf '
+ '%(inst_path)s.tar.bz2 %(inst_name)s' % {
+ 'dir': self.get_build_prefix(),
+ 'inst_name': installer_name,
+ 'inst_path':self.build_path_of(installer_name)})
finally:
self.run_command("mv %(inst)s %(dst)s" % {
'dst': self.get_dst_prefix(),
@@ -631,44 +842,69 @@ class Linux_i686Manifest(LinuxManifest):
# install either the libllkdu we just built, or a prebuilt one, in
# decreasing order of preference. for linux package, this goes to bin/
- try:
- self.path(self.find_existing_file('../llkdu/libllkdu.so',
- '../../libraries/i686-linux/lib_release_client/libllkdu.so'),
- dst='bin/libllkdu.so')
- # keep this one to preserve syntax, open source mangling removes previous lines
- pass
- except:
- print "Skipping libllkdu.so - not found"
- pass
+ for lib, destdir in ("llkdu", "bin"), ("llcommon", "lib"):
+ libfile = "lib%s.so" % lib
+ try:
+ self.path(self.find_existing_file(os.path.join(os.pardir, lib, libfile),
+ '../../libraries/i686-linux/lib_release_client/%s' % libfile),
+ dst=os.path.join(destdir, libfile))
+ # keep this one to preserve syntax, open source mangling removes previous lines
+ pass
+ except RuntimeError:
+ print "Skipping %s - not found" % libfile
+ pass
+
+
+ if(self.args['buildtype'].lower() == 'release'):
+ print "* packaging stripped viewer binary."
+ self.path("secondlife-stripped","bin/do-not-directly-run-secondlife-bin")
+ else:
+ print "* packaging un-stripped viewer binary."
+ self.path("secondlife-bin","bin/do-not-directly-run-secondlife-bin")
- self.path("secondlife-stripped","bin/do-not-directly-run-secondlife-bin")
- self.path("../linux_crash_logger/linux-crash-logger-stripped","linux-crash-logger.bin")
- self.path("linux_tools/launch_url.sh","launch_url.sh")
+ self.path("../linux_crash_logger/linux-crash-logger-stripped","bin/linux-crash-logger.bin")
+ self.path("../linux_updater/linux-updater-stripped", "bin/linux-updater.bin")
+ self.path("../llplugin/slplugin/SLPlugin", "bin/SLPlugin")
if self.prefix("res-sdl"):
self.path("*")
# recurse
self.end_prefix("res-sdl")
+ # plugins
+ if self.prefix(src="", dst="bin/llplugin"):
+ self.path("../media_plugins/webkit/libmedia_plugin_webkit.so", "libmedia_plugin_webkit.so")
+ self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so")
+ self.end_prefix("bin/llplugin")
+
self.path("featuretable_linux.txt")
#self.path("secondlife-i686.supp")
- self.path("app_settings/mozilla-runtime-linux-i686")
-
if self.prefix("../../libraries/i686-linux/lib_release_client", dst="lib"):
- self.path("libkdu_v42R.so", "libkdu.so")
- self.path("libfmod-3.75.so")
self.path("libapr-1.so.0")
self.path("libaprutil-1.so.0")
self.path("libdb-4.2.so")
self.path("libcrypto.so.0.9.7")
self.path("libexpat.so.1")
self.path("libssl.so.0.9.7")
- self.path("libuuid.so", "libuuid.so.1")
+ self.path("libuuid.so.1")
self.path("libSDL-1.2.so.0")
self.path("libELFIO.so")
self.path("libopenjpeg.so.1.3.0", "libopenjpeg.so.1.3")
self.path("libalut.so")
self.path("libopenal.so", "libopenal.so.1")
+ self.path("libopenal.so", "libvivoxoal.so.1") # vivox's sdk expects this soname
+ try:
+ self.path("libkdu_v42R.so", "libkdu.so")
+ pass
+ except:
+ print "Skipping libkdu_v42R.so - not found"
+ pass
+ try:
+ self.path("libfmod-3.75.so")
+ pass
+ except:
+ print "Skipping libkdu_v42R.so - not found"
+ pass
self.end_prefix("lib")
# Vivox runtimes
@@ -677,7 +913,10 @@ class Linux_i686Manifest(LinuxManifest):
self.end_prefix()
if self.prefix(src="vivox-runtime/i686-linux", dst="lib"):
self.path("libortp.so")
+ self.path("libsndfile.so.1")
+ #self.path("libvivoxoal.so.1") # no - we'll re-use the viewer's own OAL lib
self.path("libvivoxsdk.so")
+ self.path("libvivoxplatform.so")
self.end_prefix("lib")
class Linux_x86_64Manifest(LinuxManifest):
@@ -685,7 +924,6 @@ class Linux_x86_64Manifest(LinuxManifest):
super(Linux_x86_64Manifest, self).construct()
self.path("secondlife-stripped","bin/do-not-directly-run-secondlife-bin")
self.path("../linux_crash_logger/linux-crash-logger-stripped","linux-crash-logger.bin")
- self.path("linux_tools/launch_url.sh","launch_url.sh")
if self.prefix("res-sdl"):
self.path("*")
# recurse
diff --git a/indra/newview/zh-Hans.lproj/language.txt b/indra/newview/zh-Hans.lproj/language.txt
new file mode 100644
index 0000000000..147d659917
--- /dev/null
+++ b/indra/newview/zh-Hans.lproj/language.txt
@@ -0,0 +1 @@
+zh \ No newline at end of file
diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt
index c8682c8ea7..c1360987a5 100644
--- a/indra/test/CMakeLists.txt
+++ b/indra/test/CMakeLists.txt
@@ -14,6 +14,8 @@ include(LScript)
include(Linking)
include(Tut)
+include(GoogleMock)
+
include_directories(
${LLCOMMON_INCLUDE_DIRS}
${LLDATABASE_INCLUDE_DIRS}
@@ -23,67 +25,44 @@ include_directories(
${LLVFS_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS}
${LSCRIPT_INCLUDE_DIRS}
+ ${GOOGLEMOCK_INCLUDE_DIRS}
)
set(test_SOURCE_FILES
- common.cpp
- inventory.cpp
io.cpp
# llapp_tut.cpp # Temporarily removed until thread issues can be solved
- llbase64_tut.cpp
llblowfish_tut.cpp
llbuffer_tut.cpp
- lldate_tut.cpp
- llerror_tut.cpp
- llhost_tut.cpp
+ lldoubledispatch_tut.cpp
+ llevents_tut.cpp
llhttpdate_tut.cpp
llhttpclient_tut.cpp
llhttpnode_tut.cpp
- llinventoryparcel_tut.cpp
lliohttpserver_tut.cpp
- lljoint_tut.cpp
- llmime_tut.cpp
llmessageconfig_tut.cpp
- llmodularmath_tut.cpp
- llnamevalue_tut.cpp
llpermissions_tut.cpp
llpipeutil.cpp
- llquaternion_tut.cpp
- llrandom_tut.cpp
llsaleinfo_tut.cpp
llscriptresource_tut.cpp
llsdmessagebuilder_tut.cpp
llsdmessagereader_tut.cpp
llsd_new_tut.cpp
- llsdserialize_tut.cpp
llsdutil_tut.cpp
llservicebuilder_tut.cpp
llstreamtools_tut.cpp
- llstring_tut.cpp
lltemplatemessagebuilder_tut.cpp
lltimestampcache_tut.cpp
- lltiming_tut.cpp
lltranscode_tut.cpp
lltut.cpp
- lluri_tut.cpp
lluuidhashmap_tut.cpp
- llxfer_tut.cpp
- math.cpp
message_tut.cpp
- reflection_tut.cpp
test.cpp
- v2math_tut.cpp
- v3color_tut.cpp
- v3dmath_tut.cpp
- v3math_tut.cpp
- v4color_tut.cpp
- v4coloru_tut.cpp
- v4math_tut.cpp
)
set(test_HEADER_FILES
CMakeLists.txt
+ debug.h
llpipeutil.h
llsdtraits.h
lltut.h
@@ -104,7 +83,7 @@ endif (NOT DARWIN)
set_source_files_properties(${test_HEADER_FILES}
PROPERTIES HEADER_FILE_ONLY TRUE)
-list(APPEND test_SOURC_FILES ${test_HEADER_FILES})
+list(APPEND test_SOURCE_FILES ${test_HEADER_FILES})
add_executable(test ${test_SOURCE_FILES})
@@ -117,10 +96,15 @@ target_link_libraries(test
${LLXML_LIBRARIES}
${LSCRIPT_LIBRARIES}
${LLCOMMON_LIBRARIES}
+ ${EXPAT_LIBRARIES}
+ ${GOOGLEMOCK_LIBRARIES}
${APRICONV_LIBRARIES}
${PTHREAD_LIBRARY}
${WINDOWS_LIBRARIES}
+ ${BOOST_PROGRAM_OPTIONS_LIBRARY}
+ ${BOOST_REGEX_LIBRARY}
${DL_LIBRARY}
+ ${GOOGLE_PERFTOOLS_LIBRARIES}
)
if (WINDOWS)
@@ -133,16 +117,23 @@ endif (WINDOWS)
get_target_property(TEST_EXE test LOCATION)
-add_custom_command(
+IF(WINDOWS)
+ set(LD_LIBRARY_PATH ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR})
+ELSEIF(DARWIN)
+ set(LD_LIBRARY_PATH ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/Resources:/usr/lib)
+ELSE(WINDOWS)
+ set(LD_LIBRARY_PATH ${SHARED_LIB_STAGING_DIR}:/usr/lib)
+ENDIF(WINDOWS)
+
+LL_TEST_COMMAND("${LD_LIBRARY_PATH}"
+ "${TEST_EXE}" "--output=${CMAKE_CURRENT_BINARY_DIR}/cpp_test_results.txt" "--touch=${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt")
+ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt
- COMMAND ${TEST_EXE}
- ARGS
- --output=${CMAKE_CURRENT_BINARY_DIR}/cpp_test_results.txt
- --touch=${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt
+ COMMAND ${LL_TEST_COMMAND_value}
DEPENDS test
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "C++ unit tests"
- )
+ )
set(test_results ${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt)
diff --git a/indra/test/debug.h b/indra/test/debug.h
new file mode 100644
index 0000000000..a00659d880
--- /dev/null
+++ b/indra/test/debug.h
@@ -0,0 +1,68 @@
+/**
+ * @file debug.h
+ * @author Nat Goodspeed
+ * @date 2009-05-28
+ * @brief Debug output for unit test code
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_DEBUG_H)
+#define LL_DEBUG_H
+
+#include <iostream>
+
+/*****************************************************************************
+* Debugging stuff
+*****************************************************************************/
+// This class is intended to illuminate entry to a given block, exit from the
+// same block and checkpoints along the way. It also provides a convenient
+// place to turn std::cout output on and off.
+class Debug
+{
+public:
+ Debug(const std::string& block):
+ mBlock(block)
+ {
+ (*this)("entry");
+ }
+
+ ~Debug()
+ {
+ (*this)("exit");
+ }
+
+ void operator()(const std::string& status)
+ {
+#if defined(DEBUG_ON)
+ std::cout << mBlock << ' ' << status << std::endl;
+#endif
+ }
+
+private:
+ const std::string mBlock;
+};
+
+// It's often convenient to use the name of the enclosing function as the name
+// of the Debug block.
+#define DEBUG Debug debug(__FUNCTION__)
+
+// These BEGIN/END macros are specifically for debugging output -- please
+// don't assume you must use such for coroutines in general! They only help to
+// make control flow (as well as exception exits) explicit.
+#define BEGIN \
+{ \
+ DEBUG; \
+ try
+
+#define END \
+ catch (...) \
+ { \
+ debug("*** exceptional "); \
+ throw; \
+ } \
+}
+
+#endif /* ! defined(LL_DEBUG_H) */
diff --git a/indra/test/lldoubledispatch_tut.cpp b/indra/test/lldoubledispatch_tut.cpp
new file mode 100755
index 0000000000..63ef4d4497
--- /dev/null
+++ b/indra/test/lldoubledispatch_tut.cpp
@@ -0,0 +1,245 @@
+/**
+ * @file lldoubledispatch_tut.cpp
+ * @author Nat Goodspeed
+ * @date 2008-11-13
+ * @brief Test for lldoubledispatch.h
+ *
+ * This program tests the DoubleDispatch class, using a variation on the example
+ * from Scott Meyers' "More Effective C++", Item 31.
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "lldoubledispatch.h"
+// STL headers
+// std headers
+#include <string>
+#include <iostream>
+#include <typeinfo>
+// external library headers
+// other Linden headers
+#include "lltut.h"
+
+
+/*---------------------------- Class hierarchy -----------------------------*/
+// All objects are GameObjects.
+class GameObject
+{
+public:
+ GameObject(const std::string& name): mName(name) {}
+ virtual ~GameObject() {}
+ virtual std::string stringize() { return std::string(typeid(*this).name()) + " " + mName; }
+
+protected:
+ std::string mName;
+};
+
+// SpaceStation, Asteroid and SpaceShip are peer GameObjects.
+struct SpaceStation: public GameObject
+{
+ SpaceStation(const std::string& name): GameObject(name) {}
+ // Only a dummy SpaceStation is constructed without a name
+ SpaceStation(): GameObject("dummy") {}
+};
+
+struct Asteroid: public GameObject
+{
+ Asteroid(const std::string& name): GameObject(name) {}
+ Asteroid(): GameObject("dummy") {}
+};
+
+struct SpaceShip: public GameObject
+{
+ SpaceShip(const std::string& name): GameObject(name) {}
+ SpaceShip(): GameObject("dummy") {}
+};
+
+// SpaceShip is specialized further into CommercialShip and MilitaryShip.
+struct CommercialShip: public SpaceShip
+{
+ CommercialShip(const std::string& name): SpaceShip(name) {}
+ CommercialShip(): SpaceShip("dummy") {}
+};
+
+struct MilitaryShip: public SpaceShip
+{
+ MilitaryShip(const std::string& name): SpaceShip(name) {}
+ MilitaryShip(): SpaceShip("dummy") {}
+};
+
+/*-------------------------- Collision functions ---------------------------*/
+// This mechanism permits us to overcome a limitation of Meyers' approach: we
+// can declare the parameter types exactly as we want, rather than having to
+// make them all GameObject& parameters.
+std::string shipAsteroid(SpaceShip& ship, Asteroid& rock)
+{
+// std::cout << rock.stringize() << " has pulverized " << ship.stringize() << std::endl;
+ return "shipAsteroid";
+}
+
+std::string militaryShipAsteroid(MilitaryShip& ship, Asteroid& rock)
+{
+// std::cout << rock.stringize() << " has severely damaged " << ship.stringize() << std::endl;
+ return "militaryShipAsteroid";
+}
+
+std::string shipStation(SpaceShip& ship, SpaceStation& dock)
+{
+// std::cout << ship.stringize() << " has docked at " << dock.stringize() << std::endl;
+ return "shipStation";
+}
+
+std::string asteroidStation(Asteroid& rock, SpaceStation& dock)
+{
+// std::cout << rock.stringize() << " has damaged " << dock.stringize() << std::endl;
+ return "asteroidStation";
+}
+
+/*------------------------------- Test code --------------------------------*/
+namespace tut
+{
+ struct dispatch_data
+ {
+ dispatch_data():
+ home(new SpaceStation("Terra Station")),
+ obstacle(new Asteroid("Ganymede")),
+ tug(new CommercialShip("Pilotfish")),
+ patrol(new MilitaryShip("Enterprise"))
+ {}
+
+ // Instantiate and populate the DoubleDispatch object.
+ typedef LLDoubleDispatch<std::string, GameObject> DD;
+ DD dispatcher;
+
+ // Instantiate a few GameObjects. Make sure we refer to them
+ // polymorphically, and don't let them leak.
+ std::auto_ptr<GameObject> home;
+ std::auto_ptr<GameObject> obstacle;
+ std::auto_ptr<GameObject> tug;
+ std::auto_ptr<GameObject> patrol;
+
+ // prototype objects
+ Asteroid dummyAsteroid;
+ SpaceShip dummyShip;
+ MilitaryShip dummyMilitary;
+ CommercialShip dummyCommercial;
+ SpaceStation dummyStation;
+ };
+ typedef test_group<dispatch_data> dispatch_group;
+ typedef dispatch_group::object dispatch_object;
+ tut::dispatch_group ddgr("double dispatch");
+
+ template<> template<>
+ void dispatch_object::test<1>()
+ {
+ // Describe param types using explicit DD::Type objects
+ // (order-sensitive add() variant)
+ dispatcher.add(DD::Type<SpaceShip>(), DD::Type<Asteroid>(), shipAsteroid, true);
+ // naive adding, won't work
+ dispatcher.add(DD::Type<MilitaryShip>(), DD::Type<Asteroid>(), militaryShipAsteroid, true);
+ dispatcher.add(DD::Type<SpaceShip>(), DD::Type<SpaceStation>(), shipStation, true);
+ dispatcher.add(DD::Type<Asteroid>(), DD::Type<SpaceStation>(), asteroidStation, true);
+
+ // Try colliding them.
+ ensure_equals(dispatcher(*home, *tug), // reverse params, SpaceShip subclass
+ "shipStation");
+ ensure_equals(dispatcher(*patrol, *home), // forward params, SpaceShip subclass
+ "shipStation");
+ ensure_equals(dispatcher(*obstacle, *home), // forward params
+ "asteroidStation");
+ ensure_equals(dispatcher(*home, *obstacle), // reverse params
+ "asteroidStation");
+ ensure_equals(dispatcher(*tug, *obstacle), // forward params, SpaceShip subclass
+ "shipAsteroid");
+ ensure_equals(dispatcher(*obstacle, *patrol), // reverse params, SpaceShip subclass
+ // won't use militaryShipAsteroid() because it was added
+ // in wrong order
+ "shipAsteroid");
+ }
+
+ template<> template<>
+ void dispatch_object::test<2>()
+ {
+ // Describe param types using explicit DD::Type objects
+ // (order-sensitive add() variant)
+ // adding in correct order
+ dispatcher.add(DD::Type<MilitaryShip>(), DD::Type<Asteroid>(), militaryShipAsteroid, true);
+ dispatcher.add(DD::Type<SpaceShip>(), DD::Type<Asteroid>(), shipAsteroid, true);
+ dispatcher.add(DD::Type<SpaceShip>(), DD::Type<SpaceStation>(), shipStation, true);
+ dispatcher.add(DD::Type<Asteroid>(), DD::Type<SpaceStation>(), asteroidStation, true);
+
+ ensure_equals(dispatcher(*patrol, *obstacle), "militaryShipAsteroid");
+ ensure_equals(dispatcher(*tug, *obstacle), "shipAsteroid");
+ }
+
+ template<> template<>
+ void dispatch_object::test<3>()
+ {
+ // Describe param types with actual prototype instances
+ // (order-insensitive add() variant)
+ dispatcher.add(dummyMilitary, dummyAsteroid, militaryShipAsteroid);
+ dispatcher.add(dummyShip, dummyAsteroid, shipAsteroid);
+ dispatcher.add(dummyShip, dummyStation, shipStation);
+ dispatcher.add(dummyAsteroid, dummyStation, asteroidStation);
+
+ ensure_equals(dispatcher(*patrol, *obstacle), "militaryShipAsteroid");
+ ensure_equals(dispatcher(*tug, *obstacle), "shipAsteroid");
+ ensure_equals(dispatcher(*obstacle, *patrol), "");
+ }
+
+ template<> template<>
+ void dispatch_object::test<4>()
+ {
+ // Describe param types with actual prototype instances
+ // (order-insensitive add() variant)
+ dispatcher.add(dummyShip, dummyAsteroid, shipAsteroid);
+ // Even if we add the militaryShipAsteroid in the wrong order, it
+ // should still work.
+ dispatcher.add(dummyMilitary, dummyAsteroid, militaryShipAsteroid);
+ dispatcher.add(dummyShip, dummyStation, shipStation);
+ dispatcher.add(dummyAsteroid, dummyStation, asteroidStation);
+
+ ensure_equals(dispatcher(*patrol, *obstacle), "militaryShipAsteroid");
+ ensure_equals(dispatcher(*tug, *obstacle), "shipAsteroid");
+ }
+
+ template<> template<>
+ void dispatch_object::test<5>()
+ {
+ dispatcher.add<SpaceShip, Asteroid>(shipAsteroid);
+ dispatcher.add<MilitaryShip, Asteroid>(militaryShipAsteroid);
+ dispatcher.add<SpaceShip, SpaceStation>(shipStation);
+ dispatcher.add<Asteroid, SpaceStation>(asteroidStation);
+
+ ensure_equals(dispatcher(*patrol, *obstacle), "militaryShipAsteroid");
+ ensure_equals(dispatcher(*tug, *obstacle), "shipAsteroid");
+ }
+} // namespace tut
diff --git a/indra/test/llevents_tut.cpp b/indra/test/llevents_tut.cpp
new file mode 100644
index 0000000000..e58b10ce07
--- /dev/null
+++ b/indra/test/llevents_tut.cpp
@@ -0,0 +1,722 @@
+/**
+ * @file llevents_tut.cpp
+ * @author Nat Goodspeed
+ * @date 2008-09-12
+ * @brief Test of llevents.h
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * Copyright (c) 2008, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if LL_WINDOWS
+#pragma warning (disable : 4675) // "resolved by ADL" -- just as I want!
+#endif
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+// UGLY HACK! We want to verify state internal to the classes without
+// providing public accessors.
+#define testable public
+#include "llevents.h"
+#undef testable
+#include "lllistenerwrapper.h"
+// STL headers
+// std headers
+#include <iostream>
+#include <typeinfo>
+// external library headers
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/assign/list_of.hpp>
+// other Linden headers
+#include "lltut.h"
+#include "stringize.h"
+#include "tests/listener.h"
+
+using boost::assign::list_of;
+
+template<typename T>
+T make(const T& value) { return value; }
+
+/*****************************************************************************
+* tut test group
+*****************************************************************************/
+namespace tut
+{
+ struct events_data
+ {
+ events_data():
+ pumps(LLEventPumps::instance()),
+ listener0("first"),
+ listener1("second")
+ {}
+ LLEventPumps& pumps;
+ Listener listener0;
+ Listener listener1;
+
+ void check_listener(const std::string& desc, const Listener& listener, LLSD::Integer got)
+ {
+ ensure_equals(STRINGIZE(listener << ' ' << desc),
+ listener.getLastEvent().asInteger(), got);
+ }
+ };
+ typedef test_group<events_data> events_group;
+ typedef events_group::object events_object;
+ tut::events_group evgr("events");
+
+ template<> template<>
+ void events_object::test<1>()
+ {
+ set_test_name("basic operations");
+ // Now there's a static constructor in llevents.cpp that registers on
+ // the "mainloop" pump to call LLEventPumps::flush().
+ // Actually -- having to modify this to track the statically-
+ // constructed pumps in other TUT modules in this giant monolithic test
+ // executable isn't such a hot idea.
+// ensure_equals("initial pump", pumps.mPumpMap.size(), 1);
+ size_t initial_pumps(pumps.mPumpMap.size());
+ LLEventPump& per_frame(pumps.obtain("per-frame"));
+ ensure_equals("first explicit pump", pumps.mPumpMap.size(), initial_pumps+1);
+ // Verify that per_frame was instantiated as an LLEventStream.
+ ensure("LLEventStream leaf class", dynamic_cast<LLEventStream*>(&per_frame));
+ ensure("enabled", per_frame.enabled());
+ // Trivial test, but posting an event to an EventPump with no
+ // listeners should not blow up. The test is relevant because defining
+ // a boost::signal with a non-void return signature, using the default
+ // combiner, blows up if there are no listeners. This is because the
+ // default combiner is defined to return the value returned by the
+ // last listener, which is meaningless if there were no listeners.
+ per_frame.post(0);
+ LLBoundListener connection = listener0.listenTo(per_frame);
+ ensure("connected", connection.connected());
+ ensure("not blocked", ! connection.blocked());
+ per_frame.post(1);
+ check_listener("received", listener0, 1);
+ { // block the connection
+ LLEventPump::Blocker block(connection);
+ ensure("blocked", connection.blocked());
+ per_frame.post(2);
+ check_listener("not updated", listener0, 1);
+ } // unblock
+ ensure("unblocked", ! connection.blocked());
+ per_frame.post(3);
+ check_listener("unblocked", listener0, 3);
+ LLBoundListener sameConnection = per_frame.getListener(listener0.getName());
+ ensure("still connected", sameConnection.connected());
+ ensure("still not blocked", ! sameConnection.blocked());
+ { // block it again
+ LLEventPump::Blocker block(sameConnection);
+ ensure("re-blocked", sameConnection.blocked());
+ per_frame.post(4);
+ check_listener("re-blocked", listener0, 3);
+ } // unblock
+ bool threw = false;
+ try
+ {
+ // NOTE: boost::bind() saves its arguments by VALUE! If you pass
+ // an object instance rather than a pointer, you'll end up binding
+ // to an internal copy of that instance! Use boost::ref() to
+ // capture a reference instead.
+ per_frame.listen(listener0.getName(), // note bug, dup name
+ boost::bind(&Listener::call, boost::ref(listener1), _1));
+ }
+ catch (const LLEventPump::DupListenerName& e)
+ {
+ threw = true;
+ ensure_equals(e.what(),
+ std::string("DupListenerName: "
+ "Attempt to register duplicate listener name '") +
+ listener0.getName() +
+ "' on " + typeid(per_frame).name() + " '" + per_frame.getName() + "'");
+ }
+ ensure("threw DupListenerName", threw);
+ // do it right this time
+ listener1.listenTo(per_frame);
+ per_frame.post(5);
+ check_listener("got", listener0, 5);
+ check_listener("got", listener1, 5);
+ per_frame.enable(false);
+ per_frame.post(6);
+ check_listener("didn't get", listener0, 5);
+ check_listener("didn't get", listener1, 5);
+ per_frame.enable();
+ per_frame.post(7);
+ check_listener("got", listener0, 7);
+ check_listener("got", listener1, 7);
+ per_frame.stopListening(listener0.getName());
+ ensure("disconnected 0", ! connection.connected());
+ ensure("disconnected 1", ! sameConnection.connected());
+ per_frame.post(8);
+ check_listener("disconnected", listener0, 7);
+ check_listener("still connected", listener1, 8);
+ per_frame.stopListening(listener1.getName());
+ per_frame.post(9);
+ check_listener("disconnected", listener1, 8);
+ }
+
+ template<> template<>
+ void events_object::test<2>()
+ {
+ set_test_name("callstop() returning true");
+ LLEventPump& per_frame(pumps.obtain("per-frame"));
+ listener0.reset(0);
+ listener1.reset(0);
+ LLBoundListener bound0 = listener0.listenTo(per_frame, &Listener::callstop);
+ LLBoundListener bound1 = listener1.listenTo(per_frame, &Listener::call,
+ // after listener0
+ make<LLEventPump::NameList>(list_of(listener0.getName())));
+ ensure("enabled", per_frame.enabled());
+ ensure("connected 0", bound0.connected());
+ ensure("unblocked 0", ! bound0.blocked());
+ ensure("connected 1", bound1.connected());
+ ensure("unblocked 1", ! bound1.blocked());
+ per_frame.post(1);
+ check_listener("got", listener0, 1);
+ // Because listener0.callstop() returns true, control never reaches listener1.call().
+ check_listener("got", listener1, 0);
+ }
+
+ bool chainEvents(Listener& someListener, const LLSD& event)
+ {
+ // Make this call so we can watch for side effects for test purposes.
+ someListener.call(event);
+ // This function represents a recursive event chain -- or some other
+ // scenario in which an event handler raises additional events.
+ int value = event.asInteger();
+ if (value)
+ {
+ LLEventPumps::instance().obtain("login").post(value - 1);
+ }
+ return false;
+ }
+
+ template<> template<>
+ void events_object::test<3>()
+ {
+ set_test_name("LLEventQueue delayed action");
+ // This access is NOT legal usage: we can do it only because we're
+ // hacking private for test purposes. Normally we'd either compile in
+ // a particular name, or (later) edit a config file.
+ pumps.mQueueNames.insert("login");
+ LLEventPump& login(pumps.obtain("login"));
+ // The "mainloop" pump is special: posting on that implicitly calls
+ // LLEventPumps::flush(), which in turn should flush our "login"
+ // LLEventQueue.
+ LLEventPump& mainloop(pumps.obtain("mainloop"));
+ ensure("LLEventQueue leaf class", dynamic_cast<LLEventQueue*>(&login));
+ listener0.listenTo(login);
+ listener0.reset(0);
+ login.post(1);
+ check_listener("waiting for queued event", listener0, 0);
+ mainloop.post(LLSD());
+ check_listener("got queued event", listener0, 1);
+ login.stopListening(listener0.getName());
+ // Verify that when an event handler posts a new event on the same
+ // LLEventQueue, it doesn't get processed in the same flush() call --
+ // it waits until the next flush() call.
+ listener0.reset(17);
+ login.listen("chainEvents", boost::bind(chainEvents, boost::ref(listener0), _1));
+ login.post(1);
+ check_listener("chainEvents(1) not yet called", listener0, 17);
+ mainloop.post(LLSD());
+ check_listener("chainEvents(1) called", listener0, 1);
+ mainloop.post(LLSD());
+ check_listener("chainEvents(0) called", listener0, 0);
+ mainloop.post(LLSD());
+ check_listener("chainEvents(-1) not called", listener0, 0);
+ login.stopListening("chainEvents");
+ }
+
+ template<> template<>
+ void events_object::test<4>()
+ {
+ set_test_name("explicitly-instantiated LLEventStream");
+ // Explicitly instantiate an LLEventStream, and verify that it
+ // self-registers with LLEventPumps
+ size_t registered = pumps.mPumpMap.size();
+ size_t owned = pumps.mOurPumps.size();
+ LLEventPump* localInstance;
+ {
+ LLEventStream myEventStream("stream");
+ localInstance = &myEventStream;
+ LLEventPump& stream(pumps.obtain("stream"));
+ ensure("found named LLEventStream instance", &stream == localInstance);
+ ensure_equals("registered new instance", pumps.mPumpMap.size(), registered + 1);
+ ensure_equals("explicit instance not owned", pumps.mOurPumps.size(), owned);
+ } // destroy myEventStream -- should unregister
+ ensure_equals("destroyed instance unregistered", pumps.mPumpMap.size(), registered);
+ ensure_equals("destroyed instance not owned", pumps.mOurPumps.size(), owned);
+ LLEventPump& stream(pumps.obtain("stream"));
+ ensure("new LLEventStream instance", &stream != localInstance);
+ ensure_equals("obtain()ed instance registered", pumps.mPumpMap.size(), registered + 1);
+ ensure_equals("obtain()ed instance owned", pumps.mOurPumps.size(), owned + 1);
+ }
+
+ template<> template<>
+ void events_object::test<5>()
+ {
+ set_test_name("stopListening()");
+ LLEventPump& login(pumps.obtain("login"));
+ listener0.listenTo(login);
+ login.stopListening(listener0.getName());
+ // should not throw because stopListening() should have removed name
+ listener0.listenTo(login, &Listener::callstop);
+ LLBoundListener wrong = login.getListener("bogus");
+ ensure("bogus connection disconnected", ! wrong.connected());
+ ensure("bogus connection blocked", wrong.blocked());
+ }
+
+ template<> template<>
+ void events_object::test<6>()
+ {
+ set_test_name("chaining LLEventPump instances");
+ LLEventPump& upstream(pumps.obtain("upstream"));
+ // One potentially-useful construct is to chain LLEventPumps together.
+ // Among other things, this allows you to turn subsets of listeners on
+ // and off in groups.
+ LLEventPump& filter0(pumps.obtain("filter0"));
+ LLEventPump& filter1(pumps.obtain("filter1"));
+ upstream.listen(filter0.getName(),
+ boost::bind(&LLEventPump::post, boost::ref(filter0), _1));
+ upstream.listen(filter1.getName(),
+ boost::bind(&LLEventPump::post, boost::ref(filter1), _1));
+ listener0.listenTo(filter0);
+ listener1.listenTo(filter1);
+ listener0.reset(0);
+ listener1.reset(0);
+ upstream.post(1);
+ check_listener("got unfiltered", listener0, 1);
+ check_listener("got unfiltered", listener1, 1);
+ filter0.enable(false);
+ upstream.post(2);
+ check_listener("didn't get filtered", listener0, 1);
+ check_listener("got filtered", listener1, 2);
+ }
+
+ template<> template<>
+ void events_object::test<7>()
+ {
+ set_test_name("listener dependency order");
+ typedef LLEventPump::NameList NameList;
+ typedef Collect::StringList StringList;
+ LLEventPump& button(pumps.obtain("button"));
+ Collect collector;
+ button.listen("Mary",
+ boost::bind(&Collect::add, boost::ref(collector), "Mary", _1),
+ // state that "Mary" must come after "checked"
+ make<NameList>(list_of("checked")));
+ button.listen("checked",
+ boost::bind(&Collect::add, boost::ref(collector), "checked", _1),
+ // "checked" must come after "spot"
+ make<NameList>(list_of("spot")));
+ button.listen("spot",
+ boost::bind(&Collect::add, boost::ref(collector), "spot", _1));
+ button.post(1);
+ ensure_equals(collector.result, make<StringList>(list_of("spot")("checked")("Mary")));
+ collector.clear();
+ button.stopListening("Mary");
+ button.listen("Mary",
+ boost::bind(&Collect::add, boost::ref(collector), "Mary", _1),
+ LLEventPump::empty, // no after dependencies
+ // now "Mary" must come before "spot"
+ make<NameList>(list_of("spot")));
+ button.post(2);
+ ensure_equals(collector.result, make<StringList>(list_of("Mary")("spot")("checked")));
+ collector.clear();
+ button.stopListening("spot");
+ std::string threw;
+ try
+ {
+ button.listen("spot",
+ boost::bind(&Collect::add, boost::ref(collector), "spot", _1),
+ // after "Mary" and "checked" -- whoops!
+ make<NameList>(list_of("Mary")("checked")));
+ }
+ catch (const LLEventPump::Cycle& e)
+ {
+ threw = e.what();
+// std::cout << "Caught: " << e.what() << '\n';
+ }
+ // Obviously the specific wording of the exception text can
+ // change; go ahead and change the test to match.
+ // Establish that it contains:
+ // - the name and runtime type of the LLEventPump
+ ensure_contains("LLEventPump type", threw, typeid(button).name());
+ ensure_contains("LLEventPump name", threw, "'button'");
+ // - the name of the new listener that caused the problem
+ ensure_contains("new listener name", threw, "'spot'");
+ // - a synopsis of the problematic dependencies.
+ ensure_contains("cyclic dependencies", threw,
+ "\"Mary\" -> before (\"spot\")");
+ ensure_contains("cyclic dependencies", threw,
+ "after (\"spot\") -> \"checked\"");
+ ensure_contains("cyclic dependencies", threw,
+ "after (\"Mary\", \"checked\") -> \"spot\"");
+ button.listen("yellow",
+ boost::bind(&Collect::add, boost::ref(collector), "yellow", _1),
+ make<NameList>(list_of("checked")));
+ button.listen("shoelaces",
+ boost::bind(&Collect::add, boost::ref(collector), "shoelaces", _1),
+ make<NameList>(list_of("checked")));
+ button.post(3);
+ ensure_equals(collector.result, make<StringList>(list_of("Mary")("checked")("yellow")("shoelaces")));
+ collector.clear();
+ threw.clear();
+ try
+ {
+ button.listen("of",
+ boost::bind(&Collect::add, boost::ref(collector), "of", _1),
+ make<NameList>(list_of("shoelaces")),
+ make<NameList>(list_of("yellow")));
+ }
+ catch (const LLEventPump::OrderChange& e)
+ {
+ threw = e.what();
+// std::cout << "Caught: " << e.what() << '\n';
+ }
+ // Same remarks about the specific wording of the exception. Just
+ // ensure that it contains enough information to clarify the
+ // problem and what must be done to resolve it.
+ ensure_contains("LLEventPump type", threw, typeid(button).name());
+ ensure_contains("LLEventPump name", threw, "'button'");
+ ensure_contains("new listener name", threw, "'of'");
+ ensure_contains("prev listener name", threw, "'yellow'");
+ ensure_contains("old order", threw, "was: Mary, checked, yellow, shoelaces");
+ ensure_contains("new order", threw, "now: Mary, checked, shoelaces, of, yellow");
+ button.post(4);
+ ensure_equals(collector.result, make<StringList>(list_of("Mary")("checked")("yellow")("shoelaces")));
+ }
+
+ template<> template<>
+ void events_object::test<8>()
+ {
+ set_test_name("tweaked and untweaked LLEventPump instance names");
+ { // nested scope
+ // Hand-instantiate an LLEventStream...
+ LLEventStream bob("bob");
+ bool threw = false;
+ try
+ {
+ // then another with a duplicate name.
+ LLEventStream bob2("bob");
+ }
+ catch (const LLEventPump::DupPumpName& /*e*/)
+ {
+ threw = true;
+// std::cout << "Caught: " << e.what() << '\n';
+ }
+ ensure("Caught DupPumpName", threw);
+ } // delete first 'bob'
+ LLEventStream bob("bob"); // should work, previous one unregistered
+ LLEventStream bob1("bob", true); // allowed to tweak name
+ ensure_equals("tweaked LLEventStream name", bob1.getName(), "bob1");
+ std::vector< boost::shared_ptr<LLEventStream> > streams;
+ for (int i = 2; i <= 10; ++i)
+ {
+ streams.push_back(boost::shared_ptr<LLEventStream>(new LLEventStream("bob", true)));
+ }
+ ensure_equals("last tweaked LLEventStream name", streams.back()->getName(), "bob10");
+ }
+
+ // Define a function that accepts an LLListenerOrPumpName
+ void eventSource(const LLListenerOrPumpName& listener)
+ {
+ // Pretend that some time has elapsed. Call listener immediately.
+ listener(17);
+ }
+
+ template<> template<>
+ void events_object::test<9>()
+ {
+ set_test_name("LLListenerOrPumpName");
+ // Passing a boost::bind() expression to LLListenerOrPumpName
+ listener0.reset(0);
+ eventSource(boost::bind(&Listener::call, boost::ref(listener0), _1));
+ check_listener("got by listener", listener0, 17);
+ // Passing a string LLEventPump name to LLListenerOrPumpName
+ listener0.reset(0);
+ LLEventStream random("random");
+ listener0.listenTo(random);
+ eventSource("random");
+ check_listener("got by pump name", listener0, 17);
+ bool threw = false;
+ try
+ {
+ LLListenerOrPumpName empty;
+ empty(17);
+ }
+ catch (const LLListenerOrPumpName::Empty&)
+ {
+ threw = true;
+ }
+ ensure("threw Empty", threw);
+ }
+
+ class TempListener: public Listener
+ {
+ public:
+ TempListener(const std::string& name, bool& liveFlag):
+ Listener(name),
+ mLiveFlag(liveFlag)
+ {
+ mLiveFlag = true;
+ }
+
+ virtual ~TempListener()
+ {
+ mLiveFlag = false;
+ }
+
+ private:
+ bool& mLiveFlag;
+ };
+
+ template<> template<>
+ void events_object::test<10>()
+ {
+ set_test_name("listen(boost::bind(...TempListener...))");
+ // listen() can't do anything about a plain TempListener instance:
+ // it's not managed with shared_ptr, nor is it an LLEventTrackable subclass
+ bool live = false;
+ LLEventPump& heaptest(pumps.obtain("heaptest"));
+ LLBoundListener connection;
+ {
+ TempListener tempListener("temp", live);
+ ensure("TempListener constructed", live);
+ connection = heaptest.listen(tempListener.getName(),
+ boost::bind(&Listener::call,
+ boost::ref(tempListener),
+ _1));
+ heaptest.post(1);
+ check_listener("received", tempListener, 1);
+ } // presumably this will make newListener go away?
+ // verify that
+ ensure("TempListener destroyed", ! live);
+ // This is the case against which we can't defend. Don't even try to
+ // post to heaptest -- that would engage Undefined Behavior.
+ // Cautiously inspect connection...
+ ensure("misleadingly connected", connection.connected());
+ // then disconnect by hand.
+ heaptest.stopListening("temp");
+ }
+
+ template<> template<>
+ void events_object::test<11>()
+ {
+ set_test_name("listen(boost::bind(...weak_ptr...))");
+ // listen() detecting weak_ptr<TempListener> in boost::bind() object
+ bool live = false;
+ LLEventPump& heaptest(pumps.obtain("heaptest"));
+ LLBoundListener connection;
+ ensure("default state", ! connection.connected());
+ {
+ boost::shared_ptr<TempListener> newListener(new TempListener("heap", live));
+ newListener->reset();
+ ensure("TempListener constructed", live);
+ connection = heaptest.listen(newListener->getName(),
+ boost::bind(&Listener::call, weaken(newListener), _1));
+ ensure("new connection", connection.connected());
+ heaptest.post(1);
+ check_listener("received", *newListener, 1);
+ } // presumably this will make newListener go away?
+ // verify that
+ ensure("TempListener destroyed", ! live);
+ ensure("implicit disconnect", ! connection.connected());
+ // now just make sure we don't blow up trying to access a freed object!
+ heaptest.post(2);
+ }
+
+ template<> template<>
+ void events_object::test<12>()
+ {
+ set_test_name("listen(boost::bind(...shared_ptr...))");
+/*==========================================================================*|
+ // DISABLED because I've made this case produce a compile error.
+ // Following the error leads the disappointed dev to a comment
+ // instructing her to use the weaken() function to bind a weak_ptr<T>
+ // instead of binding a shared_ptr<T>, and explaining why. I know of
+ // no way to use TUT to code a repeatable test in which the expected
+ // outcome is a compile error. The interested reader is invited to
+ // uncomment this block and build to see for herself.
+
+ // listen() detecting shared_ptr<TempListener> in boost::bind() object
+ bool live = false;
+ LLEventPump& heaptest(pumps.obtain("heaptest"));
+ LLBoundListener connection;
+ std::string listenerName("heap");
+ ensure("default state", ! connection.connected());
+ {
+ boost::shared_ptr<TempListener> newListener(new TempListener(listenerName, live));
+ ensure_equals("use_count", newListener.use_count(), 1);
+ newListener->reset();
+ ensure("TempListener constructed", live);
+ connection = heaptest.listen(newListener->getName(),
+ boost::bind(&Listener::call, newListener, _1));
+ ensure("new connection", connection.connected());
+ ensure_equals("use_count", newListener.use_count(), 2);
+ heaptest.post(1);
+ check_listener("received", *newListener, 1);
+ } // this should make newListener go away...
+ // Unfortunately, the fact that we've bound a shared_ptr by value into
+ // our LLEventPump means that copy will keep the referenced object alive.
+ ensure("TempListener still alive", live);
+ ensure("still connected", connection.connected());
+ // disconnecting explicitly should delete the TempListener...
+ heaptest.stopListening(listenerName);
+#if 0 // however, in my experience, it does not. I don't know why not.
+ // Ah: on 2009-02-19, Frank Mori Hess, author of the Boost.Signals2
+ // library, stated on the boost-users mailing list:
+ // http://www.nabble.com/Re%3A--signals2--review--The-review-of-the-signals2-library-(formerly-thread_safe_signals)-begins-today%2C-Nov-1st-p22102367.html
+ // "It will get destroyed eventually. The signal cleans up its slot
+ // list little by little during connect/invoke. It doesn't immediately
+ // remove disconnected slots from the slot list since other threads
+ // might be using the same slot list concurrently. It might be
+ // possible to make it immediately reset the shared_ptr owning the
+ // slot though, leaving an empty shared_ptr in the slot list, since
+ // that wouldn't invalidate any iterators."
+ ensure("TempListener destroyed", ! live);
+ ensure("implicit disconnect", ! connection.connected());
+#endif // 0
+ // now just make sure we don't blow up trying to access a freed object!
+ heaptest.post(2);
+|*==========================================================================*/
+ }
+
+ class TempTrackableListener: public TempListener, public LLEventTrackable
+ {
+ public:
+ TempTrackableListener(const std::string& name, bool& liveFlag):
+ TempListener(name, liveFlag)
+ {}
+ };
+
+ template<> template<>
+ void events_object::test<13>()
+ {
+ set_test_name("listen(boost::bind(...TempTrackableListener ref...))");
+ bool live = false;
+ LLEventPump& heaptest(pumps.obtain("heaptest"));
+ LLBoundListener connection;
+ {
+ TempTrackableListener tempListener("temp", live);
+ ensure("TempTrackableListener constructed", live);
+ connection = heaptest.listen(tempListener.getName(),
+ boost::bind(&TempTrackableListener::call,
+ boost::ref(tempListener), _1));
+ heaptest.post(1);
+ check_listener("received", tempListener, 1);
+ } // presumably this will make tempListener go away?
+ // verify that
+ ensure("TempTrackableListener destroyed", ! live);
+ ensure("implicit disconnect", ! connection.connected());
+ // now just make sure we don't blow up trying to access a freed object!
+ heaptest.post(2);
+ }
+
+ template<> template<>
+ void events_object::test<14>()
+ {
+ set_test_name("listen(boost::bind(...TempTrackableListener pointer...))");
+ bool live = false;
+ LLEventPump& heaptest(pumps.obtain("heaptest"));
+ LLBoundListener connection;
+ {
+ TempTrackableListener* newListener(new TempTrackableListener("temp", live));
+ ensure("TempTrackableListener constructed", live);
+ connection = heaptest.listen(newListener->getName(),
+ boost::bind(&TempTrackableListener::call,
+ newListener, _1));
+ heaptest.post(1);
+ check_listener("received", *newListener, 1);
+ // explicitly destroy newListener
+ delete newListener;
+ }
+ // verify that
+ ensure("TempTrackableListener destroyed", ! live);
+ ensure("implicit disconnect", ! connection.connected());
+ // now just make sure we don't blow up trying to access a freed object!
+ heaptest.post(2);
+ }
+
+ template<> template<>
+ void events_object::test<15>()
+ {
+ // This test ensures that using an LLListenerWrapper subclass doesn't
+ // block Boost.Signals2 from recognizing a bound LLEventTrackable
+ // subclass.
+ set_test_name("listen(llwrap<LLLogListener>(boost::bind(...TempTrackableListener ref...)))");
+ bool live = false;
+ LLEventPump& heaptest(pumps.obtain("heaptest"));
+ LLBoundListener connection;
+ {
+ TempTrackableListener tempListener("temp", live);
+ ensure("TempTrackableListener constructed", live);
+ connection = heaptest.listen(tempListener.getName(),
+ llwrap<LLLogListener>(
+ boost::bind(&TempTrackableListener::call,
+ boost::ref(tempListener), _1)));
+ heaptest.post(1);
+ check_listener("received", tempListener, 1);
+ } // presumably this will make tempListener go away?
+ // verify that
+ ensure("TempTrackableListener destroyed", ! live);
+ ensure("implicit disconnect", ! connection.connected());
+ // now just make sure we don't blow up trying to access a freed object!
+ heaptest.post(2);
+ }
+
+ class TempSharedListener: public TempListener,
+ public boost::enable_shared_from_this<TempSharedListener>
+ {
+ public:
+ TempSharedListener(const std::string& name, bool& liveFlag):
+ TempListener(name, liveFlag)
+ {}
+ };
+
+ template<> template<>
+ void events_object::test<16>()
+ {
+ set_test_name("listen(boost::bind(...TempSharedListener ref...))");
+#if 0
+ bool live = false;
+ LLEventPump& heaptest(pumps.obtain("heaptest"));
+ LLBoundListener connection;
+ {
+ // We MUST have at least one shared_ptr to an
+ // enable_shared_from_this subclass object before
+ // shared_from_this() can work.
+ boost::shared_ptr<TempSharedListener>
+ tempListener(new TempSharedListener("temp", live));
+ ensure("TempSharedListener constructed", live);
+ // However, we're not passing either the shared_ptr or its
+ // corresponding weak_ptr -- instead, we're passing a reference to
+ // the TempSharedListener.
+/*==========================================================================*|
+ std::cout << "Capturing const ref" << std::endl;
+ const boost::enable_shared_from_this<TempSharedListener>& cref(*tempListener);
+ std::cout << "Capturing const ptr" << std::endl;
+ const boost::enable_shared_from_this<TempSharedListener>* cp(&cref);
+ std::cout << "Capturing non-const ptr" << std::endl;
+ boost::enable_shared_from_this<TempSharedListener>* p(const_cast<boost::enable_shared_from_this<TempSharedListener>*>(cp));
+ std::cout << "Capturing shared_from_this()" << std::endl;
+ boost::shared_ptr<TempSharedListener> sp(p->shared_from_this());
+ std::cout << "Capturing weak_ptr" << std::endl;
+ boost::weak_ptr<TempSharedListener> wp(weaken(sp));
+ std::cout << "Binding weak_ptr" << std::endl;
+|*==========================================================================*/
+ connection = heaptest.listen(tempListener->getName(),
+ boost::bind(&TempSharedListener::call, *tempListener, _1));
+ heaptest.post(1);
+ check_listener("received", *tempListener, 1);
+ } // presumably this will make tempListener go away?
+ // verify that
+ ensure("TempSharedListener destroyed", ! live);
+ ensure("implicit disconnect", ! connection.connected());
+ // now just make sure we don't blow up trying to access a freed object!
+ heaptest.post(2);
+#endif // 0
+ }
+} // namespace tut
diff --git a/indra/test/llhttpclient_tut.cpp b/indra/test/llhttpclient_tut.cpp
index d1bf8ae5a9..c541997e89 100644
--- a/indra/test/llhttpclient_tut.cpp
+++ b/indra/test/llhttpclient_tut.cpp
@@ -59,8 +59,8 @@ namespace tut
class LLSDStorageNode : public LLHTTPNode
{
public:
- LLSD get() const { return storage; }
- LLSD put(const LLSD& value) const { storage = value; return LLSD(); }
+ LLSD simpleGet() const { return storage; }
+ LLSD simplePut(const LLSD& value) const { storage = value; return LLSD(); }
};
class ErrorNode : public LLHTTPNode
diff --git a/indra/test/llhttpdate_tut.cpp b/indra/test/llhttpdate_tut.cpp
index b764696dae..8762938186 100644
--- a/indra/test/llhttpdate_tut.cpp
+++ b/indra/test/llhttpdate_tut.cpp
@@ -37,6 +37,9 @@
#include "lldate.h"
#include "llframetimer.h"
+#include <time.h>
+#include <locale.h>
+
namespace tut
{
struct httpdate_data
@@ -50,6 +53,7 @@ namespace tut
template<> template<>
void httpdate_object::test<1>()
{
+
static std::string epoch_expected = "Thursday, 01 Jan 1970 00:00:00 GMT" ;
ensure("Check Epoch in RFC 1123", ( epoch_expected == some_date.asRFC1123()));
}
@@ -57,6 +61,7 @@ namespace tut
template<> template<>
void httpdate_object::test<2>()
{
+
static std::string expected = "Wednesday, 18 Jul 2007 22:17:24 GMT" ;
some_date = LLDate(1184797044.037586);
ensure("Check some timestamp in RFC 1123", ( expected == some_date.asRFC1123()));
@@ -66,6 +71,7 @@ namespace tut
template<> template<>
void httpdate_object::test<3>()
{
+
//F64 sometime = LLFrameTimer::getTotalSeconds();
time_t sometime;
time(&sometime);
@@ -91,4 +97,70 @@ namespace tut
// probably not a good idea to use strcmp but this is just a unit test
ensure("Current time in RFC 1123", (strcmp(expected, actual.c_str()) == 0));
}
+
+ void test_date_string(const std::string &locale, struct tm *t,
+ const std::string &fmt, const std::string &expected)
+ {
+ std::string result = LLDate::toHTTPDateString(t, fmt);
+ LLStringUtil::toLower(result);
+ std::string label = std::string("toHTTPDateString - ") + locale;
+ ensure_equals(label.c_str(), result, expected);
+ }
+
+ template<> template<>
+ void httpdate_object::test<4>()
+ {
+ // test localization of http dates
+#if LL_WINDOWS
+ const char *en_locale = "english";
+ const char *fr_locale = "french";
+#else
+ const char *en_locale = "en_GB.UTF-8";
+ const char *fr_locale = "fr_FR.UTF-8";
+#endif
+
+ std::string prev_locale = LLStringUtil::getLocale();
+ std::string prev_clocale = std::string(setlocale(LC_TIME, NULL));
+ time_t test_time = 1252374030; // 8 Sep 2009 01:40:01
+ struct tm *t = gmtime(&test_time);
+
+ setlocale(LC_TIME, en_locale);
+ if (strcmp(setlocale(LC_TIME, NULL), en_locale) != 0)
+ {
+ setlocale(LC_TIME, prev_clocale.c_str());
+ skip("Cannot set English locale");
+ }
+
+ LLStringUtil::setLocale(en_locale);
+ test_date_string(en_locale, t, "%d %B %Y - %H:%M", "08 september 2009 - 01:40");
+ test_date_string(en_locale, t, "%H", "01");
+ test_date_string(en_locale, t, "%M", "40");
+ test_date_string(en_locale, t, "%I", "01");
+ test_date_string(en_locale, t, "%d", "08");
+ test_date_string(en_locale, t, "%Y", "2009");
+ test_date_string(en_locale, t, "%p", "am");
+ test_date_string(en_locale, t, "%A", "tuesday");
+ test_date_string(en_locale, t, "%B", "september");
+
+ setlocale(LC_TIME, fr_locale);
+ if (strcmp(setlocale(LC_TIME, NULL), fr_locale) != 0)
+ {
+ LLStringUtil::setLocale(prev_locale);
+ setlocale(LC_TIME, prev_clocale.c_str());
+ skip("Cannot set French locale");
+ }
+
+ LLStringUtil::setLocale(fr_locale);
+ test_date_string(fr_locale, t, "%d %B %Y - %H:%M", "08 septembre 2009 - 01:40");
+ test_date_string(fr_locale, t, "%H", "01");
+ test_date_string(fr_locale, t, "%M", "40");
+ test_date_string(fr_locale, t, "%I", "01");
+ test_date_string(fr_locale, t, "%d", "08");
+ test_date_string(fr_locale, t, "%Y", "2009");
+ test_date_string(fr_locale, t, "%A", "mardi");
+ test_date_string(fr_locale, t, "%B", "septembre");
+
+ LLStringUtil::setLocale(prev_locale);
+ setlocale(LC_TIME, prev_clocale.c_str());
+ }
}
diff --git a/indra/test/llpermissions_tut.cpp b/indra/test/llpermissions_tut.cpp
index 9dbb9642dd..4eadc64b5a 100644
--- a/indra/test/llpermissions_tut.cpp
+++ b/indra/test/llpermissions_tut.cpp
@@ -485,15 +485,8 @@ namespace tut
template<> template<>
void permission_object_t::test<22>()
{
- LLPermissions perm,perm1;
- LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
- LLUUID owner("68edcf47-ccd7-45b8-9f90-1649d7f12806");
- LLUUID lastOwner("5e47a0dc-97bf-44e0-8b40-de06718cee9d");
- LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
- perm.init(creator,owner,lastOwner,group);
- LLXMLNode* xml_node = perm.exportFileXML();
- perm1.importXML(xml_node);
- ensure("exportFileXML()/importXML():failed to export and import the data ", perm1 == perm);
+ // Deleted LLPermissions::exportFileXML() and LLPermissions::importXML()
+ // because I can't find any non-test code references to it. 2009-05-04 JC
}
template<> template<>
diff --git a/indra/test/llsaleinfo_tut.cpp b/indra/test/llsaleinfo_tut.cpp
index 7f8219cdc8..fa5e047513 100644
--- a/indra/test/llsaleinfo_tut.cpp
+++ b/indra/test/llsaleinfo_tut.cpp
@@ -167,19 +167,8 @@ namespace tut
template<> template<>
void llsaleinfo_test_t::test<4>()
{
-// LLXMLNode is teh suck.
-#if 0
- S32 sale_price = 23445;
- LLSaleInfo saleinfo(LLSaleInfo::FS_CONTENTS, sale_price);
-
- LLXMLNode* x_node = saleinfo.exportFileXML();
-
- LLSaleInfo saleinfo1(LLSaleInfo::FS_NOT, 0);
-
- saleinfo1.importXML(x_node);
- ensure_equals("1.importXML() fn failed", saleinfo.getSalePrice(), saleinfo1.getSalePrice());
- ensure_equals("2.importXML() fn failed", saleinfo.getSaleType(), saleinfo1.getSaleType());
-#endif
+ // Deleted LLSaleInfo::exportFileXML() and LLSaleInfo::importXML()
+ // because I can't find any non-test code references to it. 2009-05-04 JC
}
template<> template<>
diff --git a/indra/test/llscriptresource_tut.cpp b/indra/test/llscriptresource_tut.cpp
index e384c275a3..705fdd16ae 100644
--- a/indra/test/llscriptresource_tut.cpp
+++ b/indra/test/llscriptresource_tut.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2006-2007, Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -12,12 +12,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
diff --git a/indra/test/llsdmessagebuilder_tut.cpp b/indra/test/llsdmessagebuilder_tut.cpp
index 27ab127772..ca15314e69 100755
--- a/indra/test/llsdmessagebuilder_tut.cpp
+++ b/indra/test/llsdmessagebuilder_tut.cpp
@@ -44,6 +44,8 @@
#include "v3dmath.h"
#include "v3math.h"
#include "v4math.h"
+#include "llsdutil.h"
+//#include "llsdutil.cpp"
#include "llsdutil_math.cpp"
#include "lltemplatemessagebuilder.h"
@@ -353,7 +355,7 @@ namespace tut
{
char binData[] = "abcdefghijklmnop";
- addValue(messageBlockData, "testBinData", &binData, MVT_FIXED, sizeof(binData));
+ addValue(messageBlockData, (char *)"testBinData", &binData, MVT_FIXED, sizeof(binData));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -393,7 +395,7 @@ namespace tut
{
U16 binData[] = {1,2,3,4,5,6,7,8,9}; //9 shorts
- addValue(messageBlockData, "testBinData", &binData, MVT_VARIABLE, sizeof(binData) >> 1, 2);
+ addValue(messageBlockData, (char *)"testBinData", &binData, MVT_VARIABLE, sizeof(binData) >> 1, 2);
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -413,7 +415,7 @@ namespace tut
{
U32 binData[] = {9,8,7,6,5,4,3,2,1};
- addValue(messageBlockData, "testBinData", &binData, MVT_VARIABLE, sizeof(binData) >> 2, 4);
+ addValue(messageBlockData, (char *)"testBinData", &binData, MVT_VARIABLE, sizeof(binData) >> 2, 4);
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -433,7 +435,7 @@ namespace tut
{
U8 data = 0xa5;
- addValue(messageBlockData, "testBinData", &data, MVT_U8, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_U8, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -450,7 +452,7 @@ namespace tut
{
U16 data = 0xa55a;
- addValue(messageBlockData, "testBinData", &data, MVT_U16, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_U16, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -467,7 +469,7 @@ namespace tut
{
U32 data = 0xa55a7117;
- addValue(messageBlockData, "testBinData", &data, MVT_U32, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_U32, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -483,7 +485,7 @@ namespace tut
void LLSDMessageBuilderTestObject::test<27>()
{
U64 data = U64L(0xa55a711711223344);
- addValue(messageBlockData, "testBinData", &data, MVT_U64, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_U64, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -500,7 +502,7 @@ namespace tut
{
S8 data = -31;
- addValue(messageBlockData, "testBinData", &data, MVT_S8, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_S8, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -517,7 +519,7 @@ namespace tut
{
S16 data = -31;
- addValue(messageBlockData, "testBinData", &data, MVT_S16, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_S16, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -534,7 +536,7 @@ namespace tut
{
S32 data = -3100;
- addValue(messageBlockData, "testBinData", &data, MVT_S32, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_S32, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -551,7 +553,7 @@ namespace tut
{
S64 data = -31003100;
- addValue(messageBlockData, "testBinData", &data, MVT_S64, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_S64, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -568,7 +570,7 @@ namespace tut
{
F32 data = 1234.1234f;
- addValue(messageBlockData, "testBinData", &data, MVT_F32, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_F32, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -585,7 +587,7 @@ namespace tut
{
F64 data = 1234.1234;
- addValue(messageBlockData, "testBinData", &data, MVT_F64, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_F64, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -602,7 +604,7 @@ namespace tut
{
LLVector3 data(1,2,3);
- addValue(messageBlockData, "testBinData", &data, MVT_LLVector3, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_LLVector3, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -619,7 +621,7 @@ namespace tut
{
LLVector3d data(1,2,3);
- addValue(messageBlockData, "testBinData", &data, MVT_LLVector3d, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_LLVector3d, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -637,7 +639,7 @@ namespace tut
LLVector4 data(1,2,3,4);
LLSD v = ll_sd_from_vector4(data);
- addValue(messageBlockData, "testBinData", &data, MVT_LLVector4, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_LLVector4, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -657,7 +659,7 @@ namespace tut
//we send a quaternion packed into a vec3 (w is infered) - so sizeof(vec) == 12 bytes not 16.
LLVector3 vec = data.packToVector3();
- addValue(messageBlockData, "testBinData", &vec, MVT_LLQuaternion, sizeof(vec));
+ addValue(messageBlockData, (char *)"testBinData", &vec, MVT_LLQuaternion, sizeof(vec));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -674,7 +676,7 @@ namespace tut
{
LLUUID data("01234567-0123-0123-0123-234567abcdef");
- addValue(messageBlockData, "testBinData", &data, MVT_LLUUID, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_LLUUID, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -696,8 +698,8 @@ namespace tut
LLMsgData* md = new LLMsgData("testMessage");
LLMsgBlkData* mbd = new LLMsgBlkData("testBlock", 0);
- addValue(mbd, "testBoolFalse", &valueFalse, MVT_BOOL, sizeof(BOOL));
- addValue(mbd, "testBoolTrue", &valueTrue, MVT_BOOL, sizeof(BOOL));
+ addValue(mbd, (char *)"testBoolFalse", &valueFalse, MVT_BOOL, sizeof(BOOL));
+ addValue(mbd, (char *)"testBoolTrue", &valueTrue, MVT_BOOL, sizeof(BOOL));
md->addBlock(mbd);
LLSDMessageBuilder builder = defaultBuilder();
@@ -715,7 +717,7 @@ namespace tut
U32 data(0xff887766);
LLSD v = ll_sd_from_ipaddr(data);
- addValue(messageBlockData, "testBinData", &data, MVT_IP_ADDR, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_IP_ADDR, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -732,7 +734,7 @@ namespace tut
{
U16 data = 0xff88;
- addValue(messageBlockData, "testBinData", &data, MVT_IP_PORT, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_IP_PORT, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -749,7 +751,7 @@ namespace tut
{
U16 data[3] = {0,1,2};
- addValue(messageBlockData, "testBinData", &data, MVT_U16Vec3, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_U16Vec3, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -769,7 +771,7 @@ namespace tut
{
U16 data[4] = {0,1,2,4};
- addValue(messageBlockData, "testBinData", &data, MVT_U16Quat, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_U16Quat, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
@@ -789,7 +791,7 @@ namespace tut
{
S16 data[19] = {0,-1,2,-4,5,-6,7,-8,9,-10,11,-12,13,-14,15,16,17,18};
- addValue(messageBlockData, "testBinData", &data, MVT_S16Array, sizeof(data));
+ addValue(messageBlockData, (char *)"testBinData", &data, MVT_S16Array, sizeof(data));
messageData->addBlock(messageBlockData);
LLSDMessageBuilder builder = defaultBuilder();
diff --git a/indra/test/llsdmessagereader_tut.cpp b/indra/test/llsdmessagereader_tut.cpp
index 36cfe5ebfc..f11e148cca 100755
--- a/indra/test/llsdmessagereader_tut.cpp
+++ b/indra/test/llsdmessagereader_tut.cpp
@@ -42,6 +42,7 @@
#include "message.h"
#include "llsdmessagereader.h"
#include "llsdutil.h"
+#include "llsdutil_math.h"
namespace tut
{
diff --git a/indra/test/llsdutil_tut.cpp b/indra/test/llsdutil_tut.cpp
index 0c4bbc2e62..aebb1f9770 100644
--- a/indra/test/llsdutil_tut.cpp
+++ b/indra/test/llsdutil_tut.cpp
@@ -44,12 +44,42 @@
#include "v4math.h"
#include "llquaternion.h"
#include "llsdutil.h"
-
+#include "llsdutil_math.h"
+#include "stringize.h"
+#include <set>
+#include <boost/range.hpp>
namespace tut
{
struct llsdutil_data
{
+ void test_matches(const std::string& proto_key, const LLSD& possibles,
+ const char** begin, const char** end)
+ {
+ std::set<std::string> succeed(begin, end);
+ LLSD prototype(possibles[proto_key]);
+ for (LLSD::map_const_iterator pi(possibles.beginMap()), pend(possibles.endMap());
+ pi != pend; ++pi)
+ {
+ std::string match(llsd_matches(prototype, pi->second));
+ std::set<std::string>::const_iterator found = succeed.find(pi->first);
+ if (found != succeed.end())
+ {
+ // This test is supposed to succeed. Comparing to the
+ // empty string ensures that if the test fails, it will
+ // display the string received so we can tell what failed.
+ ensure_equals("match", match, "");
+ }
+ else
+ {
+ // This test is supposed to fail. If we get a false match,
+ // the string 'match' will be empty, which doesn't tell us
+ // much about which case went awry. So construct a more
+ // detailed description string.
+ ensure(proto_key + " shouldn't match " + pi->first, ! match.empty());
+ }
+ }
+ }
};
typedef test_group<llsdutil_data> llsdutil_test;;
typedef llsdutil_test::object llsdutil_object;
@@ -159,4 +189,207 @@ namespace tut
LLSD sd1 = ll_sd_from_color4(c1);
ensure_equals("sd -> LLColor4 -> sd", sd, sd1);
}
+
+ template<> template<>
+ void llsdutil_object::test<9>()
+ {
+ set_test_name("llsd_matches");
+
+ // for this test, construct a map of all possible LLSD types
+ LLSD map;
+ map.insert("empty", LLSD());
+ map.insert("Boolean", LLSD::Boolean());
+ map.insert("Integer", LLSD::Integer(0));
+ map.insert("Real", LLSD::Real(0.0));
+ map.insert("String", LLSD::String("bah"));
+ map.insert("NumString", LLSD::String("1"));
+ map.insert("UUID", LLSD::UUID());
+ map.insert("Date", LLSD::Date());
+ map.insert("URI", LLSD::URI());
+ map.insert("Binary", LLSD::Binary());
+ map.insert("Map", LLSD().with("foo", LLSD()));
+ // Only an empty array can be constructed on the fly
+ LLSD array;
+ array.append(LLSD());
+ map.insert("Array", array);
+
+ // These iterators are declared outside our various for loops to avoid
+ // fatal MSVC warning: "I used to be broken, but I'm all better now!"
+ LLSD::map_const_iterator mi, mend(map.endMap());
+
+ /*-------------------------- llsd_matches --------------------------*/
+
+ // empty prototype matches anything
+ for (mi = map.beginMap(); mi != mend; ++mi)
+ {
+ ensure_equals(std::string("empty matches ") + mi->first, llsd_matches(LLSD(), mi->second), "");
+ }
+
+ LLSD proto_array, data_array;
+ for (int i = 0; i < 3; ++i)
+ {
+ proto_array.append(LLSD());
+ data_array.append(LLSD());
+ }
+
+ // prototype array matches only array
+ for (mi = map.beginMap(); mi != mend; ++mi)
+ {
+ ensure(std::string("array doesn't match ") + mi->first,
+ ! llsd_matches(proto_array, mi->second).empty());
+ }
+
+ // data array must be at least as long as prototype array
+ proto_array.append(LLSD());
+ ensure_equals("data array too short", llsd_matches(proto_array, data_array),
+ "Array size 4 required instead of Array size 3");
+ data_array.append(LLSD());
+ ensure_equals("data array just right", llsd_matches(proto_array, data_array), "");
+ data_array.append(LLSD());
+ ensure_equals("data array longer", llsd_matches(proto_array, data_array), "");
+
+ // array element matching
+ data_array[0] = LLSD::String();
+ ensure_equals("undefined prototype array entry", llsd_matches(proto_array, data_array), "");
+ proto_array[0] = LLSD::Binary();
+ ensure_equals("scalar prototype array entry", llsd_matches(proto_array, data_array),
+ "[0]: Binary required instead of String");
+ data_array[0] = LLSD::Binary();
+ ensure_equals("matching prototype array entry", llsd_matches(proto_array, data_array), "");
+
+ // build a coupla maps
+ LLSD proto_map, data_map;
+ data_map["got"] = LLSD();
+ data_map["found"] = LLSD();
+ for (LLSD::map_const_iterator dmi(data_map.beginMap()), dmend(data_map.endMap());
+ dmi != dmend; ++dmi)
+ {
+ proto_map[dmi->first] = dmi->second;
+ }
+ proto_map["foo"] = LLSD();
+ proto_map["bar"] = LLSD();
+
+ // prototype map matches only map
+ for (mi = map.beginMap(); mi != mend; ++mi)
+ {
+ ensure(std::string("map doesn't match ") + mi->first,
+ ! llsd_matches(proto_map, mi->second).empty());
+ }
+
+ // data map must contain all keys in prototype map
+ std::string error(llsd_matches(proto_map, data_map));
+ ensure_contains("missing keys", error, "missing keys");
+ ensure_contains("missing foo", error, "foo");
+ ensure_contains("missing bar", error, "bar");
+ ensure_does_not_contain("found found", error, "found");
+ ensure_does_not_contain("got got", error, "got");
+ data_map["bar"] = LLSD();
+ error = llsd_matches(proto_map, data_map);
+ ensure_contains("missing foo", error, "foo");
+ ensure_does_not_contain("got bar", error, "bar");
+ data_map["foo"] = LLSD();
+ ensure_equals("data map just right", llsd_matches(proto_map, data_map), "");
+ data_map["extra"] = LLSD();
+ ensure_equals("data map with extra", llsd_matches(proto_map, data_map), "");
+
+ // map element matching
+ data_map["foo"] = LLSD::String();
+ ensure_equals("undefined prototype map entry", llsd_matches(proto_map, data_map), "");
+ proto_map["foo"] = LLSD::Binary();
+ ensure_equals("scalar prototype map entry", llsd_matches(proto_map, data_map),
+ "['foo']: Binary required instead of String");
+ data_map["foo"] = LLSD::Binary();
+ ensure_equals("matching prototype map entry", llsd_matches(proto_map, data_map), "");
+
+ // String
+ {
+ static const char* matches[] = { "String", "NumString", "Boolean", "Integer",
+ "Real", "UUID", "Date", "URI" };
+ test_matches("String", map, boost::begin(matches), boost::end(matches));
+ }
+
+ // Boolean, Integer, Real
+ static const char* numerics[] = { "Boolean", "Integer", "Real" };
+ for (const char **ni = boost::begin(numerics), **nend = boost::end(numerics);
+ ni != nend; ++ni)
+ {
+ static const char* matches[] = { "Boolean", "Integer", "Real", "String", "NumString" };
+ test_matches(*ni, map, boost::begin(matches), boost::end(matches));
+ }
+
+ // UUID
+ {
+ static const char* matches[] = { "UUID", "String", "NumString" };
+ test_matches("UUID", map, boost::begin(matches), boost::end(matches));
+ }
+
+ // Date
+ {
+ static const char* matches[] = { "Date", "String", "NumString" };
+ test_matches("Date", map, boost::begin(matches), boost::end(matches));
+ }
+
+ // URI
+ {
+ static const char* matches[] = { "URI", "String", "NumString" };
+ test_matches("URI", map, boost::begin(matches), boost::end(matches));
+ }
+
+ // Binary
+ {
+ static const char* matches[] = { "Binary" };
+ test_matches("Binary", map, boost::begin(matches), boost::end(matches));
+ }
+
+ /*-------------------------- llsd_equals ---------------------------*/
+
+ // Cross-product of each LLSD type with every other
+ for (LLSD::map_const_iterator lmi(map.beginMap()), lmend(map.endMap());
+ lmi != lmend; ++lmi)
+ {
+ for (LLSD::map_const_iterator rmi(map.beginMap()), rmend(map.endMap());
+ rmi != rmend; ++rmi)
+ {
+ // Name this test based on the map keys naming the types of
+ // interest, e.g "String::Integer".
+ // We expect the values (xmi->second) to be equal if and only
+ // if the type names (xmi->first) are equal.
+ ensure(STRINGIZE(lmi->first << "::" << rmi->first),
+ bool(lmi->first == rmi->first) ==
+ bool(llsd_equals(lmi->second, rmi->second)));
+ }
+ }
+
+ // Array cases
+ LLSD rarray;
+ rarray.append(1.0);
+ rarray.append(2);
+ rarray.append("3");
+ LLSD larray(rarray);
+ ensure("llsd_equals(equal arrays)", llsd_equals(larray, rarray));
+ rarray[2] = "4";
+ ensure("llsd_equals(different [2])", ! llsd_equals(larray, rarray));
+ rarray = larray;
+ rarray.append(LLSD::Date());
+ ensure("llsd_equals(longer right array)", ! llsd_equals(larray, rarray));
+ rarray = larray;
+ rarray.erase(2);
+ ensure("llsd_equals(shorter right array)", ! llsd_equals(larray, rarray));
+
+ // Map cases
+ LLSD rmap;
+ rmap["San Francisco"] = 65;
+ rmap["Phoenix"] = 92;
+ rmap["Boston"] = 77;
+ LLSD lmap(rmap);
+ ensure("llsd_equals(equal maps)", llsd_equals(lmap, rmap));
+ rmap["Boston"] = 80;
+ ensure("llsd_equals(different [\"Boston\"])", ! llsd_equals(lmap, rmap));
+ rmap = lmap;
+ rmap["Atlanta"] = 95;
+ ensure("llsd_equals(superset right map)", ! llsd_equals(lmap, rmap));
+ rmap = lmap;
+ lmap["Seattle"] = 72;
+ ensure("llsd_equals(superset left map)", ! llsd_equals(lmap, rmap));
+ }
}
diff --git a/indra/test/lltimestampcache_tut.cpp b/indra/test/lltimestampcache_tut.cpp
index 9e0de0fe60..3b102a3366 100644
--- a/indra/test/lltimestampcache_tut.cpp
+++ b/indra/test/lltimestampcache_tut.cpp
@@ -5,7 +5,7 @@
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2008, Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -13,12 +13,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
diff --git a/indra/test/lltranscode_tut.cpp b/indra/test/lltranscode_tut.cpp
index 8abf9dc224..eb21979db0 100644
--- a/indra/test/lltranscode_tut.cpp
+++ b/indra/test/lltranscode_tut.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
- * Copyright (c) 2006-2007, Linden Research, Inc.
+ * Copyright (c) 2008-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -12,12 +12,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
diff --git a/indra/test/lltut.cpp b/indra/test/lltut.cpp
index 201e174f9c..e4e0de1ff1 100644
--- a/indra/test/lltut.cpp
+++ b/indra/test/lltut.cpp
@@ -76,9 +76,13 @@ namespace tut
void ensure_equals(const char* m, const LLSD& actual,
const LLSD& expected)
+ {
+ ensure_equals(std::string(m), actual, expected);
+ }
+
+ void ensure_equals(const std::string& msg, const LLSD& actual,
+ const LLSD& expected)
{
- const std::string& msg = m ? m : "";
-
ensure_equals(msg + " type", actual.type(), expected.type());
switch (actual.type())
{
@@ -128,7 +132,7 @@ namespace tut
{
ensure_equals(msg + " map keys",
actual_iter->first, expected_iter->first);
- ensure_equals((msg + "[" + actual_iter->first + "]").c_str(),
+ ensure_equals(msg + "[" + actual_iter->first + "]",
actual_iter->second, expected_iter->second);
++actual_iter;
++expected_iter;
@@ -141,7 +145,7 @@ namespace tut
for(int i = 0; i < actual.size(); ++i)
{
- ensure_equals((msg + llformat("[%d]", i)).c_str(),
+ ensure_equals(msg + llformat("[%d]", i),
actual[i], expected[i]);
}
return;
diff --git a/indra/test/lltut.h b/indra/test/lltut.h
index 47ea9d3f9e..6322753253 100644
--- a/indra/test/lltut.h
+++ b/indra/test/lltut.h
@@ -74,7 +74,7 @@ namespace tut
inline void ensure_memory_matches(const char* msg,const void* actual, U32 actual_len, const void* expected,U32 expected_len)
{
if((expected_len != actual_len) ||
- (memcmp(actual, expected, actual_len) != 0))
+ (std::memcmp(actual, expected, actual_len) != 0))
{
std::stringstream ss;
ss << (msg?msg:"") << (msg?": ":"") << "not equal";
@@ -121,6 +121,9 @@ namespace tut
void ensure_equals(const char* msg,
const LLSD& actual, const LLSD& expected);
+
+ void ensure_equals(const std::string& msg,
+ const LLSD& actual, const LLSD& expected);
void ensure_starts_with(const std::string& msg,
const std::string& actual, const std::string& expectedStart);
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index ba81c6e49e..7dfe8f40b7 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -54,6 +54,11 @@
# include "ctype_workaround.h"
#endif
+#ifndef LL_WINDOWS
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#endif
+
namespace tut
{
std::string sSourceDir;
@@ -136,34 +141,31 @@ public:
run_completed_(*mStream);
}
run_completed_(std::cout);
-
- if (mFailedTests > 0)
- {
- exit(1);
- }
}
+
+ int getFailedTests() const { return mFailedTests; }
private:
void run_completed_(std::ostream &stream)
{
+ stream << "\tTotal Tests:\t" << mTotalTests << std::endl;
+ stream << "\tPassed Tests:\t" << mPassedTests;
+ if (mPassedTests == mTotalTests)
+ {
+ stream << "\tYAY!! \\o/";
+ }
stream << std::endl;
- stream << "Total Tests: " << mTotalTests << std::endl;
- stream << "Passed Tests: " << mPassedTests << std::endl;
- stream << std::endl;
- stream << "Total Tests: " << mTotalTests << std::endl;
- stream << "Passed Tests: " << mPassedTests << std::endl;
-
if (mSkippedTests > 0)
{
- stream << "Skipped known failures: " << mSkippedTests
+ stream << "\tSkipped known failures:\t" << mSkippedTests
<< std::endl;
}
if(mFailedTests > 0)
{
stream << "*********************************" << std::endl;
- stream << "Failed Tests: " << mFailedTests << std::endl;
+ stream << "Failed Tests:\t" << mFailedTests << std::endl;
stream << "Please report or fix the problem." << std::endl;
stream << "*********************************" << std::endl;
}
@@ -238,6 +240,11 @@ void wouldHaveCrashed(const std::string& message)
int main(int argc, char **argv)
{
+ // The following line must be executed to initialize Google Mock
+ // (and Google Test) before running the tests.
+#ifndef LL_WINDOWS
+ ::testing::InitGoogleMock(&argc, argv);
+#endif
LLError::initForApplication(".");
LLError::setFatalFunction(wouldHaveCrashed);
LLError::setDefaultLevel(LLError::LEVEL_ERROR);
@@ -340,9 +347,11 @@ int main(int argc, char **argv)
tut::runner.get().run_tests(test_group);
}
+ bool success = (callback.getFailedTests() == 0);
+
if (wait_at_exit)
{
- std::cerr << "Waiting for input before exiting..." << std::endl;
+ std::cerr << "Press return to exit..." << std::endl;
std::cin.get();
}
@@ -352,7 +361,7 @@ int main(int argc, char **argv)
delete output;
}
- if (touch)
+ if (touch && success)
{
std::ofstream s;
s.open(touch);
@@ -361,5 +370,7 @@ int main(int argc, char **argv)
}
apr_terminate();
- return 0;
+
+ int retval = (success ? 0 : 1);
+ return retval;
}
diff --git a/indra/test/test.h b/indra/test/test.h
index 16ec4effcf..cee185140c 100644
--- a/indra/test/test.h
+++ b/indra/test/test.h
@@ -13,12 +13,13 @@
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
diff --git a/indra/test_apps/llplugintest/CMakeLists.txt b/indra/test_apps/llplugintest/CMakeLists.txt
new file mode 100644
index 0000000000..b4043b0fd9
--- /dev/null
+++ b/indra/test_apps/llplugintest/CMakeLists.txt
@@ -0,0 +1,539 @@
+# -*- cmake -*-
+
+project(llplugintest)
+
+include(00-Common)
+include(FindOpenGL)
+include(LLCommon)
+include(LLPlugin)
+include(Linking)
+include(LLSharedLibs)
+include(PluginAPI)
+include(LLImage)
+include(LLMath)
+include(LLMessage)
+include(LLRender)
+include(LLWindow)
+include(Glut)
+include(Glui)
+
+include_directories(
+ ${LLPLUGIN_INCLUDE_DIRS}
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LLIMAGE_INCLUDE_DIRS}
+ ${LLMATH_INCLUDE_DIRS}
+ ${LLMESSAGE_INCLUDE_DIRS}
+ ${LLRENDER_INCLUDE_DIRS}
+ ${LLWINDOW_INCLUDE_DIRS}
+)
+
+if (DARWIN)
+ include(CMakeFindFrameworks)
+ find_library(COREFOUNDATION_LIBRARY CoreFoundation)
+endif (DARWIN)
+
+### demo_plugin
+
+#set(demo_plugin_SOURCE_FILES
+# demo_plugin.cpp
+# )
+#
+#add_library(demo_plugin
+# SHARED
+# ${demo_plugin_SOURCE_FILES}
+#)
+#
+#target_link_libraries(demo_plugin
+# ${LLPLUGIN_LIBRARIES}
+# ${LLCOMMON_LIBRARIES}
+# ${PLUGIN_API_WINDOWS_LIBRARIES}
+#)
+#
+#add_dependencies(demo_plugin
+# ${LLPLUGIN_LIBRARIES}
+# ${LLCOMMON_LIBRARIES}
+#)
+#
+#if (DARWIN)
+# # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name
+# set_target_properties(
+# demo_plugin
+# PROPERTIES
+# PREFIX ""
+# BUILD_WITH_INSTALL_RPATH 1
+# INSTALL_NAME_DIR "@executable_path"
+# )
+#endif (DARWIN)
+
+### plugin_host
+
+#set(plugin_host_SOURCE_FILES
+# plugin_host.cpp
+# )
+#
+#add_executable(plugin_host
+# WIN32
+# ${plugin_host_SOURCE_FILES}
+#)
+#
+#set_target_properties(plugin_host
+# PROPERTIES
+# WIN32_EXECUTABLE
+# FALSE
+#)
+#
+#target_link_libraries(plugin_host
+# ${LLPLUGIN_LIBRARIES}
+# ${LLCOMMON_LIBRARIES}
+# ${PLUGIN_API_WINDOWS_LIBRARIES}
+#)
+#
+#add_dependencies(plugin_host
+# demo_plugin
+# ${LLPLUGIN_LIBRARIES}
+# ${LLCOMMON_LIBRARIES}
+#)
+
+### plugin_process_launcher
+
+#set(plugin_process_launcher_SOURCE_FILES
+# plugin_process_launcher.cpp
+# )
+#
+#add_executable(plugin_process_launcher
+# WIN32
+# ${plugin_process_launcher_SOURCE_FILES}
+#)
+#
+#set_target_properties(plugin_process_launcher
+# PROPERTIES
+# WIN32_EXECUTABLE
+# FALSE
+#)
+#
+#target_link_libraries(plugin_process_launcher
+# ${LLPLUGIN_LIBRARIES}
+# ${LLMESSAGE_LIBRARIES}
+# ${LLCOMMON_LIBRARIES}
+# ${PLUGIN_API_WINDOWS_LIBRARIES}
+#)
+#
+#add_dependencies(plugin_process_launcher
+# SLPlugin
+# demo_plugin
+# ${LLPLUGIN_LIBRARIES}
+# ${LLMESSAGE_LIBRARIES}
+# ${LLCOMMON_LIBRARIES}
+#)
+
+### media_simple_test
+
+#set(media_simple_test_SOURCE_FILES
+# media_simple_test.cpp
+# )
+#
+#add_executable(media_simple_test
+# WIN32
+# ${media_simple_test_SOURCE_FILES}
+#)
+#
+#add_dependencies(media_simple_test stage_third_party_libs)
+#
+#set_target_properties(media_simple_test
+# PROPERTIES
+# WIN32_EXECUTABLE
+# FALSE
+#)
+#
+#target_link_libraries(media_simple_test
+# ${GLUT_LIBRARY}
+# ${OPENGL_LIBRARIES}
+# ${LLCOMMON_LIBRARIES}
+#)
+
+### media_plugin_test
+
+#set(media_plugin_test_SOURCE_FILES
+# media_plugin_test.cpp
+# )
+#
+#add_executable(media_plugin_test
+# WIN32
+# ${media_plugin_test_SOURCE_FILES}
+#)
+#
+#set_target_properties(media_plugin_test
+# PROPERTIES
+# WIN32_EXECUTABLE
+# FALSE
+#)
+#
+#target_link_libraries(media_plugin_test
+# ${GLUT_LIBRARY}
+# ${OPENGL_LIBRARIES}
+# ${LLPLUGIN_LIBRARIES}
+# ${LLMESSAGE_LIBRARIES}
+# ${LLCOMMON_LIBRARIES}
+# ${PLUGIN_API_WINDOWS_LIBRARIES}
+#)
+#
+#add_dependencies(media_plugin_test
+# stage_third_party_libs
+# SLPlugin
+# demo_media_plugin
+# ${LLPLUGIN_LIBRARIES}
+# ${LLMESSAGE_LIBRARIES}
+# ${LLCOMMON_LIBRARIES}
+#)
+
+### demo_media_plugin
+
+#set(demo_media_plugin_SOURCE_FILES
+# demo_media_plugin.cpp
+# )
+#
+#add_library(demo_media_plugin
+# SHARED
+# ${demo_media_plugin_SOURCE_FILES}
+#)
+#
+#target_link_libraries(demo_media_plugin
+# ${LLPLUGIN_LIBRARIES}
+# ${LLCOMMON_LIBRARIES}
+# ${PLUGIN_API_WINDOWS_LIBRARIES}
+#)
+#
+#add_dependencies(demo_media_plugin
+# ${LLPLUGIN_LIBRARIES}
+# ${LLCOMMON_LIBRARIES}
+#)
+#
+#if (DARWIN)
+# # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name
+# set_target_properties(
+# demo_media_plugin
+# PROPERTIES
+# PREFIX ""
+# BUILD_WITH_INSTALL_RPATH 1
+# INSTALL_NAME_DIR "@executable_path"
+# )
+#endif (DARWIN)
+
+### demo_media_plugin_2
+
+#set(demo_media_plugin_2_SOURCE_FILES
+# demo_media_plugin_2.cpp
+# )
+#
+#add_library(demo_media_plugin_2
+# SHARED
+# ${demo_media_plugin_2_SOURCE_FILES}
+#)
+#
+#target_link_libraries(demo_media_plugin_2
+# ${LLPLUGIN_LIBRARIES}
+# ${LLCOMMON_LIBRARIES}
+# ${PLUGIN_API_WINDOWS_LIBRARIES}
+#)
+#
+#add_dependencies(demo_media_plugin_2
+# ${LLPLUGIN_LIBRARIES}
+# ${LLCOMMON_LIBRARIES}
+#)
+#
+#if (DARWIN)
+# # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name
+# set_target_properties(
+# demo_media_plugin_2
+# PROPERTIES
+# PREFIX ""
+# BUILD_WITH_INSTALL_RPATH 1
+# INSTALL_NAME_DIR "@executable_path"
+# )
+#endif (DARWIN)
+
+### llmediaplugintest
+
+set(llmediaplugintest_SOURCE_FILES
+ llmediaplugintest.cpp
+ llmediaplugintest.h
+ bookmarks.txt
+ )
+
+add_executable(llmediaplugintest
+ WIN32
+ MACOSX_BUNDLE
+ ${llmediaplugintest_SOURCE_FILES}
+)
+
+set_target_properties(llmediaplugintest
+ PROPERTIES
+ WIN32_EXECUTABLE
+ FALSE
+)
+
+target_link_libraries(llmediaplugintest
+ ${GLUT_LIBRARY}
+ ${GLUI_LIBRARY}
+ ${OPENGL_LIBRARIES}
+ ${LLPLUGIN_LIBRARIES}
+ ${LLMESSAGE_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+ ${PLUGIN_API_WINDOWS_LIBRARIES}
+)
+
+if (DARWIN)
+ # The testbed needs to use a couple of CoreFoundation calls now, to deal with being a bundled app.
+ target_link_libraries(llmediaplugintest
+ ${COREFOUNDATION_LIBRARY}
+ )
+endif (DARWIN)
+
+add_dependencies(llmediaplugintest
+ stage_third_party_libs
+ SLPlugin
+ media_plugin_quicktime
+ media_plugin_webkit
+ media_plugin_example
+ ${LLPLUGIN_LIBRARIES}
+ ${LLMESSAGE_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
+)
+
+# turn off weird GLUI pragma
+add_definitions(-DGLUI_NO_LIB_PRAGMA)
+
+if (DARWIN OR LINUX)
+ # glui.h contains code that triggers the "overloaded-virtual" warning in gcc.
+ set_source_files_properties(llmediaplugintest.cpp PROPERTIES COMPILE_FLAGS "-Wno-overloaded-virtual")
+endif (DARWIN OR LINUX)
+
+# Gather build products of the various dependencies into the build directory for the testbed.
+
+if (DARWIN)
+ # path inside the app bundle where we'll need to copy plugins and other related files
+ set(PLUGINS_DESTINATION_DIR
+ ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llmediaplugintest.app/Contents/Resources
+ )
+
+ # create the Contents/Resources directory
+ add_custom_command(
+ TARGET llmediaplugintest POST_BUILD
+ COMMAND ${CMAKE_COMMAND}
+ ARGS
+ -E
+ make_directory
+ ${PLUGINS_DESTINATION_DIR}
+ COMMENT "Creating Resources directory in app bundle."
+ )
+else (DARWIN)
+ set(PLUGINS_DESTINATION_DIR
+ ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/
+ )
+endif (DARWIN)
+
+get_target_property(BUILT_SLPLUGIN SLPlugin LOCATION)
+add_custom_command(TARGET llmediaplugintest POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_SLPLUGIN} ${PLUGINS_DESTINATION_DIR}
+ DEPENDS ${BUILT_SLPLUGIN}
+)
+
+get_target_property(BUILT_LLCOMMON llcommon LOCATION)
+add_custom_command(TARGET llmediaplugintest POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_LLCOMMON} ${PLUGINS_DESTINATION_DIR}
+ DEPENDS ${BUILT_LLCOMMON}
+)
+
+
+if (DARWIN OR WINDOWS)
+ get_target_property(BUILT_WEBKIT_PLUGIN media_plugin_webkit LOCATION)
+ add_custom_command(TARGET llmediaplugintest POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_WEBKIT_PLUGIN} ${PLUGINS_DESTINATION_DIR}
+ DEPENDS ${BUILT_WEBKIT_PLUGIN}
+ )
+
+ get_target_property(BUILT_QUICKTIME_PLUGIN media_plugin_quicktime LOCATION)
+ add_custom_command(TARGET llmediaplugintest POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_QUICKTIME_PLUGIN} ${PLUGINS_DESTINATION_DIR}
+ DEPENDS ${BUILT_QUICKTIME_PLUGIN}
+ )
+
+ get_target_property(BUILT_EXAMPLE_PLUGIN media_plugin_example LOCATION)
+ add_custom_command(TARGET llmediaplugintest POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_EXAMPLE_PLUGIN} ${PLUGINS_DESTINATION_DIR}
+ DEPENDS ${BUILT_EXAMPLE_PLUGIN}
+ )
+
+ # copy over bookmarks file if llmediaplugintest gets built
+ get_target_property(BUILT_LLMEDIAPLUGINTEST llmediaplugintest LOCATION)
+ add_custom_command(TARGET llmediaplugintest POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bookmarks.txt ${CMAKE_CURRENT_BINARY_DIR}/
+ DEPENDS ${BUILT_LLMEDIAPLUGINTEST}
+ )
+ # also copy it to the same place as SLPlugin, which is what the mac wants...
+ add_custom_command(TARGET llmediaplugintest POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bookmarks.txt ${PLUGINS_DESTINATION_DIR}
+ DEPENDS ${BUILT_LLMEDIAPLUGINTEST}
+ )
+endif (DARWIN OR WINDOWS)
+
+if (DARWIN)
+ add_custom_command(TARGET llmediaplugintest POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libllqtwebkit.dylib ${PLUGINS_DESTINATION_DIR}
+ DEPENDS ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libllqtwebkit.dylib
+ )
+endif (DARWIN)
+
+if(WINDOWS)
+ #********************
+ # Plugin test library deploy
+ #
+ # Debug config runtime files required for the plugin test mule
+ set(plugintest_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug")
+ set(plugintest_debug_files
+ libeay32.dll
+ libglib-2.0-0.dll
+ libgmodule-2.0-0.dll
+ libgobject-2.0-0.dll
+ libgthread-2.0-0.dll
+ qtcored4.dll
+ qtguid4.dll
+ qtnetworkd4.dll
+ qtopengld4.dll
+ qtwebkitd4.dll
+ ssleay32.dll
+ )
+ copy_if_different(
+ ${plugintest_debug_src_dir}
+ "${CMAKE_CURRENT_BINARY_DIR}/Debug"
+ out_targets
+ ${plugintest_debug_files}
+ )
+ set(plugin_test_targets ${plugin_test_targets} ${out_targets})
+
+ # Debug config runtime files required for the plugin test mule (Qt image format plugins)
+ set(plugintest_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug/imageformats")
+ set(plugintest_debug_files
+ qgifd4.dll
+ qicod4.dll
+ qjpegd4.dll
+ qmngd4.dll
+ qsvgd4.dll
+ qtiffd4.dll
+ )
+ copy_if_different(
+ ${plugintest_debug_src_dir}
+ "${CMAKE_CURRENT_BINARY_DIR}/Debug/imageformats"
+ out_targets
+ ${plugintest_debug_files}
+ )
+ set(plugin_test_targets ${plugin_test_targets} ${out_targets})
+
+ # Debug config runtime files required for the plugin test mule (Qt codec plugins)
+ set(plugintest_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug/codecs")
+ set(plugintest_debug_files
+ qcncodecsd4.dll
+ qjpcodecsd4.dll
+ qkrcodecsd4.dll
+ qtwcodecsd4.dll
+ )
+ copy_if_different(
+ ${plugintest_debug_src_dir}
+ "${CMAKE_CURRENT_BINARY_DIR}/Debug/codecs"
+ out_targets
+ ${plugintest_debug_files}
+ )
+ set(plugin_test_targets ${plugin_test_targets} ${out_targets})
+
+ # Release & ReleaseDebInfo config runtime files required for the plugin test mule
+ set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release")
+ set(plugintest_release_files
+ libeay32.dll
+ libglib-2.0-0.dll
+ libgmodule-2.0-0.dll
+ libgobject-2.0-0.dll
+ libgthread-2.0-0.dll
+ qtcore4.dll
+ qtgui4.dll
+ qtnetwork4.dll
+ qtopengl4.dll
+ qtwebkit4.dll
+ qtxmlpatterns4.dll
+ ssleay32.dll
+ )
+ copy_if_different(
+ ${plugintest_release_src_dir}
+ "${CMAKE_CURRENT_BINARY_DIR}/Release"
+ out_targets
+ ${plugintest_release_files}
+ )
+ set(plugin_test_targets ${plugin_test_targets} ${out_targets})
+
+ copy_if_different(
+ ${plugintest_release_src_dir}
+ "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo"
+ out_targets
+ ${plugintest_release_files}
+ )
+ set(plugin_test_targets ${plugin_test_targets} ${out_targets})
+
+ # Release & ReleaseDebInfo config runtime files required for the plugin test mule (Qt image format plugins)
+ set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release/imageformats")
+ set(plugintest_release_files
+ qgif4.dll
+ qico4.dll
+ qjpeg4.dll
+ qmng4.dll
+ qsvg4.dll
+ qtiff4.dll
+ )
+ copy_if_different(
+ ${plugintest_release_src_dir}
+ "${CMAKE_CURRENT_BINARY_DIR}/Release/imageformats"
+ out_targets
+ ${plugintest_release_files}
+ )
+ set(plugin_test_targets ${plugin_test_targets} ${out_targets})
+
+ copy_if_different(
+ ${plugintest_release_src_dir}
+ "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/imageformats"
+ out_targets
+ ${plugintest_release_files}
+ )
+ set(plugin_test_targets ${plugin_test_targets} ${out_targets})
+
+ # Release & ReleaseDebInfo config runtime files required for the plugin test mule (Qt codec plugins)
+ set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release/codecs")
+ set(plugintest_release_files
+ qcncodecs4.dll
+ qjpcodecs4.dll
+ qkrcodecs4.dll
+ qtwcodecs4.dll
+ )
+ copy_if_different(
+ ${plugintest_release_src_dir}
+ "${CMAKE_CURRENT_BINARY_DIR}/Release/codecs"
+ out_targets
+ ${plugintest_release_files}
+ )
+ set(plugin_test_targets ${plugin_test_targets} ${out_targets})
+
+ copy_if_different(
+ ${plugintest_release_src_dir}
+ "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/codecs"
+ out_targets
+ ${plugintest_release_files}
+ )
+ set(plugin_test_targets ${plugin_test_targets} ${out_targets})
+
+ add_custom_target(copy_plugintest_libs ALL
+ DEPENDS
+ ${plugin_test_targets}
+ )
+
+ add_dependencies(llmediaplugintest copy_plugintest_libs)
+
+endif(WINDOWS)
+
+ll_deploy_sharedlibs_command(llmediaplugintest)
diff --git a/indra/test_apps/llplugintest/bookmarks.txt b/indra/test_apps/llplugintest/bookmarks.txt
new file mode 100644
index 0000000000..b8b83df386
--- /dev/null
+++ b/indra/test_apps/llplugintest/bookmarks.txt
@@ -0,0 +1,37 @@
+# format is description, url (don't put ',' chars in description :)
+# if no ',' found, whole line is used for both description and url
+(WK) Google Home Page,http://www.google.com
+(WK) BBC News Home Page,http://news.bbc.co.uk
+(WK) Second Life,http://secondlife.com
+(WK) WebKit Home ,http://www.webkit.org
+(WK) Yahoo News,http://news.yahoo.com
+(WK) Canvas Paint (DHTML version of MS Paint),http://www.canvaspaint.org
+(WK) DHTML Lemmings!,http://www.elizium.nu/scripts/lemmings/
+(WK) DHTML graphics demos,http://www.dhteumeuleu.com/
+(WK) Shared paint app,http://colorillo.com/ac79?1l0q6cp
+(Flash) YouTube,http://youtube.com
+(Flash) Vimeo,http://www.vimeo.com/1778399
+(Flash) Simple whiteboard,http://www.imaginationcubed.com/
+(Flash) Dabble Board,http://www.dabbleboard.com/draw
+(Flash) Bubble Shooter game,http://www.wiicade.com/playGame.aspx?gameID=72&gameName=Bubble%20Shooter
+(Flash) Pixlr photo editor,http://pixlr.com/editor/
+(Flash) Scribd,http://www.scribd.com/doc/14427744/Second-Life-Quickstart-Guide
+(Flash) MAME,http://yvern.com/fMAME/fMAME.html
+(QT) Local sample,file:///C|/Program Files/QuickTime/Sample.mov
+(QT) Movie - Watchmen Trailer,http://movies.apple.com/movies/wb/watchmen/watchmen-tlr2_480p.mov
+(QT) Movie - Transformers - Revenge of the Fallen,http://movies.apple.com/movies/paramount/transformers2/transformersrevengeofthefallen-tlr1_h.320.mov
+(QT) Movie - Terminator Salvation,http://movies.apple.com/movies/wb/terminatorsalvation/terminatorsalvation-tlr3_h.320.mov
+(QT) Movie - Angels and Demons,http://movies.apple.com/movies/sony_pictures/angelsanddemons/angelsanddemons-video_h.320.mov
+(QT) Movie - Sin City Trailer,http://movies.apple.com/movies/miramax/sin_city/sin_city_480.mov
+(QT) Movie - The Incredibles Trailer,http://movies.apple.com/movies/disney/the_incredibles/the_incredibles-tlr_a480.mov
+(QT) Movie - Streaming Apple Event,http://stream.qtv.apple.com/events/mar/0903lajkszg/m_090374535329zdwg_650_ref.mov
+(QT) Movie - MPEG-4 from Amazon S3,http://s3.amazonaws.com/callum-linden/flashdemo/interactive_flash_demo.mp4
+(QT) Movie - Star Trek,http://movies.apple.com/movies/paramount/star_trek/startrek-tlr3_h.320.mov
+(QT) Movie - Ice Age 3,http://movies.apple.com/movies/fox/ice_age_iii/iceage3-tlrd_h.320.mov
+(QT) Movie - AstroBoy,http://movies.apple.com/movies/summit/astroboy/astroboy-tsr_h.320.mov
+(QT) Movie - Ante Up,http://movies.apple.com/movies/independent/anteup/anteup_h.320.mov
+(QT) Movie - Every Little Step,http://movies.apple.com/movies/sony/everylittlestep/everylittlestep-clip_h.320.mov
+(QT) Movie - The Informers,http://movies.apple.com/movies/independent/theinformers/theinformers_h.320.mov
+(QT) Animated GIF,http://upload.wikimedia.org/wikipedia/commons/4/44/Optical.greysquares.arp-animated.gif
+(QT) Apple Text Descriptors,http://ubrowser.com/tmp/apple_text.txt
+(EX) Example Plugin,example://blah
diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp
new file mode 100644
index 0000000000..d183aac208
--- /dev/null
+++ b/indra/test_apps/llplugintest/llmediaplugintest.cpp
@@ -0,0 +1,2207 @@
+/**
+ * @file LLMediaPluginTest.cpp
+ * @brief Primary test application for LLMedia (Separate Process) Plugin system
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "indra_constants.h"
+
+#include "llapr.h"
+#include "llerrorcontrol.h"
+
+#include <math.h>
+#include <iomanip>
+#include <sstream>
+#include <ctime>
+
+#include "llmediaplugintest.h"
+
+#if __APPLE__
+ #include <GLUT/glut.h>
+ #include <CoreFoundation/CoreFoundation.h>
+#else
+ #define FREEGLUT_STATIC
+ #include "GL/freeglut.h"
+ #define GLUI_FREEGLUT
+#endif
+
+#if LL_WINDOWS
+#pragma warning(disable: 4263)
+#pragma warning(disable: 4264)
+#endif
+#include "glui.h"
+
+
+LLMediaPluginTest* gApplication = 0;
+static void gluiCallbackWrapper( int control_id );
+
+////////////////////////////////////////////////////////////////////////////////
+//
+static bool isTexture( GLuint texture )
+{
+ bool result = false;
+
+ // glIsTexture will sometimes return false for real textures... do this instead.
+ if(texture != 0)
+ result = true;
+
+ return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+mediaPanel::mediaPanel()
+{
+ mMediaTextureHandle = 0;
+ mPickTextureHandle = 0;
+ mMediaSource = NULL;
+ mPickTexturePixels = NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+mediaPanel::~mediaPanel()
+{
+ // delete OpenGL texture handles
+ if ( isTexture( mPickTextureHandle ) )
+ {
+ std::cerr << "remMediaPanel: deleting pick texture " << mPickTextureHandle << std::endl;
+ glDeleteTextures( 1, &mPickTextureHandle );
+ mPickTextureHandle = 0;
+ }
+
+ if ( isTexture( mMediaTextureHandle ) )
+ {
+ std::cerr << "remMediaPanel: deleting media texture " << mMediaTextureHandle << std::endl;
+ glDeleteTextures( 1, &mMediaTextureHandle );
+ mMediaTextureHandle = 0;
+ }
+
+ if(mPickTexturePixels)
+ {
+ delete mPickTexturePixels;
+ }
+
+ if(mMediaSource)
+ {
+ delete mMediaSource;
+ }
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+LLMediaPluginTest::LLMediaPluginTest( int app_window, int window_width, int window_height ) :
+ mVersionMajor( 2 ),
+ mVersionMinor( 0 ),
+ mVersionPatch( 0 ),
+ mMaxPanels( 25 ),
+ mViewportAspect( 0 ),
+ mAppWindow( app_window ),
+ mCurMouseX( 0 ),
+ mCurMouseY( 0 ),
+ mFuzzyMedia( true ),
+ mSelectedPanel( 0 ),
+ mMediaBrowserControlEnableCookies( 0 ),
+ mMediaBrowserControlBackButton( 0 ),
+ mMediaBrowserControlForwardButton( 0 ),
+ mMediaTimeControlVolume( 100 ),
+ mMediaTimeControlSeekSeconds( 0 ),
+ mGluiMediaTimeControlWindowFlag( true ),
+ mGluiMediaBrowserControlWindowFlag( true ),
+ mMediaBrowserControlBackButtonFlag( true ),
+ mMediaBrowserControlForwardButtonFlag( true ),
+ mHomeWebUrl( "http://www.google.com/" )
+{
+ // debugging spam
+ std::cout << std::endl << " GLUT version: " << "3.7.6" << std::endl; // no way to get real version from GLUT
+ std::cout << std::endl << " GLUI version: " << GLUI_Master.get_version() << std::endl;
+ std::cout << std::endl << "Media Plugin Test version: " << mVersionMajor << "." << mVersionMinor << "." << mVersionPatch << std::endl;
+
+ // bookmark title
+ mBookmarks.push_back( std::pair< std::string, std::string >( "--- Bookmarks ---", "" ) );
+
+ // insert hardcoded URLs here as required for testing
+ //mBookmarks.push_back( std::pair< std::string, std::string >( "description", "url" ) );
+
+ // read bookmarks from file.
+ // note: uses command in ./CmakeLists.txt which copies bookmmarks file from source directory
+ // to app directory (WITHOUT build configuration dir) (this is cwd in Windows within MSVC)
+ // For example, test_apps\llplugintest and not test_apps\llplugintest\Release
+ // This may need to be changed for Mac/Linux builds.
+ // See https://jira.lindenlab.com/browse/DEV-31350 for large list of media URLs from AGNI
+ const std::string bookmarks_filename( "bookmarks.txt" );
+ std::ifstream file_handle( bookmarks_filename.c_str() );
+ if ( file_handle.is_open() )
+ {
+ std::cout << "Reading bookmarks for test" << std::endl;
+ while( ! file_handle.eof() )
+ {
+ std::string line;
+ std::getline( file_handle, line );
+ if ( file_handle.eof() )
+ break;
+
+ if ( line.substr( 0, 1 ) != "#" )
+ {
+ size_t comma_pos = line.find_first_of( ',' );
+ if ( comma_pos != std::string::npos )
+ {
+ std::string description = line.substr( 0, comma_pos );
+ std::string url = line.substr( comma_pos + 1 );
+ mBookmarks.push_back( std::pair< std::string, std::string >( description, url ) );
+ }
+ else
+ {
+ mBookmarks.push_back( std::pair< std::string, std::string >( line, line ) );
+ };
+ };
+ };
+ std::cout << "Read " << mBookmarks.size() << " bookmarks" << std::endl;
+ }
+ else
+ {
+ std::cout << "Unable to read bookmarks from file: " << bookmarks_filename << std::endl;
+ };
+
+ // initialize linden lab APR module
+ ll_init_apr();
+
+ // Set up llerror logging
+ {
+ LLError::initForApplication(".");
+ LLError::setDefaultLevel(LLError::LEVEL_INFO);
+ //LLError::setTagLevel("Plugin", LLError::LEVEL_DEBUG);
+ }
+
+ // lots of randomness in this app
+ srand( ( unsigned int )time( 0 ) );
+
+ // build GUI
+ makeChrome();
+
+ // OpenGL initialilzation
+ glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
+ glClearDepth( 1.0f );
+ glEnable( GL_DEPTH_TEST );
+ glEnable( GL_COLOR_MATERIAL );
+ glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
+ glDepthFunc( GL_LEQUAL );
+ glEnable( GL_TEXTURE_2D );
+ glDisable( GL_BLEND );
+ glColor3f( 1.0f, 1.0f, 1.0f );
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+ glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
+
+ // start with a sane view
+ resetView();
+
+ // initial media panel
+ const int num_initial_panels = 1;
+ for( int i = 0; i < num_initial_panels; ++i )
+ {
+ //addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second );
+ addMediaPanel( mHomeWebUrl );
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+LLMediaPluginTest::~LLMediaPluginTest()
+{
+ // delete all media panels
+ for( int i = 0; i < (int)mMediaPanels.size(); ++i )
+ {
+ remMediaPanel( mMediaPanels[ i ] );
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::reshape( int width, int height )
+{
+ // update viewport (the active window inside the chrome)
+ int viewport_x, viewport_y;
+ int viewport_height, viewport_width;
+ GLUI_Master.get_viewport_area( &viewport_x, &viewport_y, &viewport_width, &viewport_height );
+ mViewportAspect = (float)( viewport_width ) / (float)( viewport_height );
+ glViewport( viewport_x, viewport_y, viewport_width, viewport_height );
+
+ // save these as we'll need them later
+ mWindowWidth = width;
+ mWindowHeight = height;
+
+ // adjust size of URL bar so it doesn't get clipped
+ mUrlEdit->set_w( mWindowWidth - 360 );
+
+ // GLUI requires this
+ if ( glutGetWindow() != mAppWindow )
+ glutSetWindow( mAppWindow );
+
+ // trigger re-display
+ glutPostRedisplay();
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::bindTexture(GLuint texture, GLint row_length, GLint alignment)
+{
+ glEnable( GL_TEXTURE_2D );
+
+ glBindTexture( GL_TEXTURE_2D, texture );
+ glPixelStorei( GL_UNPACK_ROW_LENGTH, row_length );
+ glPixelStorei( GL_UNPACK_ALIGNMENT, alignment );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+bool LLMediaPluginTest::checkGLError(const char *name)
+{
+ bool result = false;
+ GLenum error = glGetError();
+
+ if(error != GL_NO_ERROR)
+ {
+ // For some reason, glGenTextures is returning GL_INVALID_VALUE...
+ std::cout << name << " ERROR 0x" << std::hex << error << std::dec << std::endl;
+ result = true;
+ }
+
+ return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::drawGeometry( int panel )
+{
+ // texture coordinates for each panel
+ GLfloat non_opengl_texture_coords[ 8 ] = { 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f };
+ GLfloat opengl_texture_coords[ 8 ] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f };
+
+ GLfloat *texture_coords = mMediaPanels[ panel ]->mAppTextureCoordsOpenGL?opengl_texture_coords:non_opengl_texture_coords;
+
+ // base coordinates for each panel
+ GLfloat base_vertex_pos[ 8 ] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f };
+
+ // calculate posiitons
+ const int num_panels = (int)mMediaPanels.size();
+ const int num_rows = (int)sqrt( (float)num_panels );
+ const int num_cols = num_panels / num_rows;
+ const int panel_x = ( panel / num_rows );
+ const int panel_y = ( panel % num_rows );
+
+ const float spacing = 0.1f;
+ const GLfloat offset_x = num_cols * ( 1.0 + spacing ) / 2;
+ const GLfloat offset_y = num_rows * ( 1.0 + spacing ) / 2;
+
+ // Adjust for media aspect ratios
+ {
+ float aspect = 1.0f;
+
+ if(mMediaPanels[ panel ]->mMediaHeight != 0)
+ {
+ aspect = (float)mMediaPanels[ panel ]->mMediaWidth / (float)mMediaPanels[ panel ]->mMediaHeight;
+ }
+
+ if(aspect > 1.0f)
+ {
+ // media is wider than it is high -- adjust the top and bottom in
+ for( int corner = 0; corner < 4; ++corner )
+ {
+ float temp = base_vertex_pos[corner * 2 + 1];
+
+ if(temp < 0.5f)
+ temp += 0.5 - (0.5f / aspect);
+ else
+ temp -= 0.5 - (0.5f / aspect);
+
+ base_vertex_pos[corner * 2 + 1] = temp;
+ }
+ }
+ else if(aspect < 1.0f)
+ {
+ // media is higher than it is wide -- adjust the left and right sides in
+ for( int corner = 0; corner < 4; ++corner )
+ {
+ float temp = base_vertex_pos[corner * 2];
+
+ if(temp < 0.5f)
+ temp += 0.5f - (0.5f * aspect);
+ else
+ temp -= 0.5f - (0.5f * aspect);
+
+ base_vertex_pos[corner * 2] = temp;
+ }
+ }
+ }
+
+ glBegin( GL_QUADS );
+ for( int corner = 0; corner < 4; ++corner )
+ {
+ glTexCoord2f( texture_coords[ corner * 2 ], texture_coords[ corner * 2 + 1 ] );
+ GLfloat x = base_vertex_pos[ corner * 2 ] + panel_x * ( 1.0 + spacing ) - offset_x + spacing / 2.0f;
+ GLfloat y = base_vertex_pos[ corner * 2 + 1 ] + panel_y * ( 1.0 + spacing ) - offset_y + spacing / 2.0f;
+
+ glVertex3f( x, y, 0.0f );
+ };
+ glEnd();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::startPanelHighlight( float red, float green, float blue, float line_width )
+{
+ glPushAttrib( GL_ALL_ATTRIB_BITS );
+ glEnable( GL_POLYGON_OFFSET_FILL );
+ glPolygonOffset( -2.5f, -2.5f );
+ glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
+ glLineWidth( line_width );
+ glColor3f( red, green, blue );
+ glDisable( GL_TEXTURE_2D );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::endPanelHighlight()
+{
+ glPopAttrib();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::draw( int draw_type )
+{
+ for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel )
+ {
+ // drawing pick texture
+ if ( draw_type == DrawTypePickTexture )
+ {
+ // only bother with pick if we have something to render
+ // Actually, we need to pick even if we're not ready to render.
+ // Otherwise you can't select and remove a panel which has gone bad.
+ //if ( mMediaPanels[ panel ]->mReadyToRender )
+ {
+ glMatrixMode( GL_TEXTURE );
+ glPushMatrix();
+
+ // pick texture is a power of 2 so no need to scale
+ glLoadIdentity();
+
+ // bind to media texture
+ glLoadIdentity();
+ bindTexture( mMediaPanels[ panel ]->mPickTextureHandle );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+
+ // draw geometry using pick texture
+ drawGeometry( panel );
+
+ glMatrixMode( GL_TEXTURE );
+ glPopMatrix();
+ };
+ }
+ else
+ if ( draw_type == DrawTypeMediaTexture )
+ {
+ bool texture_valid = false;
+ bool plugin_exited = false;
+
+ if(mMediaPanels[ panel ]->mMediaSource)
+ {
+ texture_valid = mMediaPanels[ panel ]->mMediaSource->textureValid();
+ plugin_exited = mMediaPanels[ panel ]->mMediaSource->isPluginExited();
+ }
+
+ // save texture matrix (changes for each panel)
+ glMatrixMode( GL_TEXTURE );
+ glPushMatrix();
+
+ // only process texture if the media is ready to draw
+ // (we still want to draw the geometry)
+ if ( mMediaPanels[ panel ]->mReadyToRender && texture_valid )
+ {
+ // bind to media texture
+ bindTexture( mMediaPanels[ panel ]->mMediaTextureHandle );
+
+ if ( mFuzzyMedia )
+ {
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ }
+ else
+ {
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+ }
+
+ // scale to fit panel
+ glScalef( mMediaPanels[ panel ]->mTextureScaleX,
+ mMediaPanels[ panel ]->mTextureScaleY,
+ 1.0f );
+ };
+
+ float intensity = plugin_exited?0.25f:1.0f;
+
+ // highlight the selected panel
+ if ( mSelectedPanel && ( mMediaPanels[ panel ]->mId == mSelectedPanel->mId ) )
+ {
+ startPanelHighlight( intensity, intensity, 0.0f, 5.0f );
+ drawGeometry( panel );
+ endPanelHighlight();
+ }
+ else
+ // this panel not able to render yet since it
+ // doesn't have enough information
+ if ( !mMediaPanels[ panel ]->mReadyToRender )
+ {
+ startPanelHighlight( intensity, 0.0f, 0.0f, 2.0f );
+ drawGeometry( panel );
+ endPanelHighlight();
+ }
+ else
+ // just display a border around the media
+ {
+ startPanelHighlight( 0.0f, intensity, 0.0f, 2.0f );
+ drawGeometry( panel );
+ endPanelHighlight();
+ };
+
+ if ( mMediaPanels[ panel ]->mReadyToRender && texture_valid )
+ {
+ // draw visual geometry
+ drawGeometry( panel );
+ }
+
+ // restore texture matrix (changes for each panel)
+ glMatrixMode( GL_TEXTURE );
+ glPopMatrix();
+ };
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::display()
+{
+ // GLUI requires this
+ if ( glutGetWindow() != mAppWindow )
+ glutSetWindow( mAppWindow );
+
+ // start with a clean slate
+ glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
+ // set up OpenGL view
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ glFrustum( -mViewportAspect * 0.04f, mViewportAspect * 0.04f, -0.04f, 0.04f, 0.1f, 50.0f );
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+ glTranslatef( 0.0, 0.0, 0.0f );
+ glTranslatef( mViewPos[ 0 ], mViewPos[ 1 ], -mViewPos[ 2 ] );
+ glMultMatrixf( mViewRotation );
+
+ // draw pick texture
+ draw( DrawTypePickTexture );
+
+ // read colors and get coordinate values
+ glReadPixels( mCurMouseX, mCurMouseY, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, mPixelReadColor );
+
+ // clear the pick render (otherwise it may depth-fight with the textures rendered later)
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
+ // draw visible geometry
+ draw( DrawTypeMediaTexture );
+
+ glutSwapBuffers();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::idle()
+{
+// checkGLError("LLMediaPluginTest::idle");
+
+ // GLUI requires this
+ if ( glutGetWindow() != mAppWindow )
+ glutSetWindow( mAppWindow );
+
+ // random creation/destruction of panels enabled?
+ const time_t panel_timeout_time = 5;
+ if ( mRandomPanelCount )
+ {
+ // time for a change
+ static time_t last_panel_time = 0;
+ if ( time( NULL ) - last_panel_time > panel_timeout_time )
+ {
+ if ( rand() % 2 == 0 )
+ {
+ if ( mMediaPanels.size() < 16 )
+ {
+ std::cout << "Randomly adding new panel" << std::endl;
+ addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second );
+ };
+ }
+ else
+ {
+ if ( mMediaPanels.size() > 0 )
+ {
+ std::cout << "Deleting selected panel" << std::endl;
+ remMediaPanel( mSelectedPanel );
+ };
+ };
+ time( &last_panel_time );
+ };
+ };
+
+ // random selection of bookmarks enabled?
+ const time_t bookmark_timeout_time = 5;
+ if ( mRandomBookmarks )
+ {
+ // time for a change
+ static time_t last_bookmark_time = 0;
+ if ( time( NULL ) - last_bookmark_time > bookmark_timeout_time )
+ {
+ // go to a different random bookmark on each panel
+ for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel )
+ {
+ std::string uri = mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second;
+
+ std::cout << "Random: navigating to : " << uri << std::endl;
+
+ std::string mime_type = mimeTypeFromUrl( uri );
+
+ if ( mime_type != mMediaPanels[ panel ]->mMimeType )
+ {
+ replaceMediaPanel( mMediaPanels[ panel ], uri );
+ }
+ else
+ {
+ mMediaPanels[ panel ]->mMediaSource->loadURI( uri );
+ mMediaPanels[ panel ]->mMediaSource->start();
+ };
+ };
+
+ time( &last_bookmark_time );
+ };
+ };
+
+ // update UI
+ if ( mSelectedPanel )
+ {
+ // set volume based on slider if we have time media
+ //if ( mGluiMediaTimeControlWindowFlag )
+ //{
+ // mSelectedPanel->mMediaSource->setVolume( (float)mMediaTimeControlVolume / 100.0f );
+ //};
+
+ // NOTE: it is absurd that we need cache the state of GLUI controls
+ // but enabling/disabling controls drags framerate from 500+
+ // down to 15. Not a problem for plugin system - only this test
+ // enable/disable time based UI controls based on type of plugin
+ if ( mSelectedPanel->mMediaSource->pluginSupportsMediaTime() )
+ {
+ if ( ! mGluiMediaTimeControlWindowFlag )
+ {
+ mGluiMediaTimeControlWindow->enable();
+ mGluiMediaTimeControlWindowFlag = true;
+ };
+ }
+ else
+ {
+ if ( mGluiMediaTimeControlWindowFlag )
+ {
+ mGluiMediaTimeControlWindow->disable();
+ mGluiMediaTimeControlWindowFlag = false;
+ };
+ };
+
+ // enable/disable browser based UI controls based on type of plugin
+ if ( mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser() )
+ {
+ if ( ! mGluiMediaBrowserControlWindowFlag )
+ {
+ mGluiMediaBrowserControlWindow->enable();
+ mGluiMediaBrowserControlWindowFlag = true;
+ };
+ }
+ else
+ {
+ if ( mGluiMediaBrowserControlWindowFlag )
+ {
+ mGluiMediaBrowserControlWindow->disable();
+ mGluiMediaBrowserControlWindowFlag = false;
+ };
+ };
+
+ // enable/disable browser back button depending on browser history
+ if ( mSelectedPanel->mMediaSource->getHistoryBackAvailable() )
+ {
+ if ( ! mMediaBrowserControlBackButtonFlag )
+ {
+ mMediaBrowserControlBackButton->enable();
+ mMediaBrowserControlBackButtonFlag = true;
+ };
+ }
+ else
+ {
+ if ( mMediaBrowserControlBackButtonFlag )
+ {
+ mMediaBrowserControlBackButton->disable();
+ mMediaBrowserControlBackButtonFlag = false;
+ };
+ };
+
+ // enable/disable browser forward button depending on browser history
+ if ( mSelectedPanel->mMediaSource->getHistoryForwardAvailable() )
+ {
+ if ( ! mMediaBrowserControlForwardButtonFlag )
+ {
+ mMediaBrowserControlForwardButton->enable();
+ mMediaBrowserControlForwardButtonFlag = true;
+ };
+ }
+ else
+ {
+ if ( mMediaBrowserControlForwardButtonFlag )
+ {
+ mMediaBrowserControlForwardButton->disable();
+ mMediaBrowserControlForwardButtonFlag = false;
+ };
+ };
+
+ // NOTE: This is *very* slow and not worth optimising
+ updateStatusBar();
+ };
+
+ // update all the panels
+ for( int panel_index = 0; panel_index < (int)mMediaPanels.size(); ++panel_index )
+ {
+ mediaPanel *panel = mMediaPanels[ panel_index ];
+
+ // call plugins idle function so it can potentially update itself
+ panel->mMediaSource->idle();
+
+ // update each media panel
+ updateMediaPanel( panel );
+
+ LLRect dirty_rect;
+ if ( ! panel->mMediaSource->textureValid() )
+ {
+ //std::cout << "texture invalid, skipping update..." << std::endl;
+ }
+ else
+ if ( panel &&
+ ( panel->mMediaWidth != panel->mMediaSource->getWidth() ||
+ panel->mMediaHeight != panel->mMediaSource->getHeight() ) )
+ {
+ //std::cout << "Resize in progress, skipping update..." << std::endl;
+ }
+ else
+ if ( panel->mMediaSource->getDirty( &dirty_rect ) )
+ {
+ const unsigned char* pixels = panel->mMediaSource->getBitsData();
+ if ( pixels && isTexture(panel->mMediaTextureHandle))
+ {
+ int x_offset = dirty_rect.mLeft;
+ int y_offset = dirty_rect.mBottom;
+ int width = dirty_rect.mRight - dirty_rect.mLeft;
+ int height = dirty_rect.mTop - dirty_rect.mBottom;
+
+ if((dirty_rect.mRight <= panel->mTextureWidth) && (dirty_rect.mTop <= panel->mTextureHeight))
+ {
+ // Offset the pixels pointer properly
+ pixels += ( y_offset * panel->mMediaSource->getTextureDepth() * panel->mMediaSource->getBitsWidth() );
+ pixels += ( x_offset * panel->mMediaSource->getTextureDepth() );
+
+ // set up texture
+ bindTexture( panel->mMediaTextureHandle, panel->mMediaSource->getBitsWidth() );
+ if ( mFuzzyMedia )
+ {
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ }
+ else
+ {
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+ };
+
+ checkGLError("glTexParameteri");
+
+ if(panel->mMediaSource->getTextureFormatSwapBytes())
+ {
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
+ checkGLError("glPixelStorei");
+ }
+
+ // draw portion that changes into texture
+ glTexSubImage2D( GL_TEXTURE_2D, 0,
+ x_offset,
+ y_offset,
+ width,
+ height,
+ panel->mMediaSource->getTextureFormatPrimary(),
+ panel->mMediaSource->getTextureFormatType(),
+ pixels );
+
+ if(checkGLError("glTexSubImage2D"))
+ {
+ std::cerr << " panel ID=" << panel->mId << std::endl;
+ std::cerr << " texture size = " << panel->mTextureWidth << " x " << panel->mTextureHeight << std::endl;
+ std::cerr << " media size = " << panel->mMediaWidth << " x " << panel->mMediaHeight << std::endl;
+ std::cerr << " dirty rect = " << dirty_rect.mLeft << ", " << dirty_rect.mBottom << ", " << dirty_rect.mRight << ", " << dirty_rect.mTop << std::endl;
+ std::cerr << " texture width = " << panel->mMediaSource->getBitsWidth() << std::endl;
+ std::cerr << " format primary = 0x" << std::hex << panel->mMediaSource->getTextureFormatPrimary() << std::dec << std::endl;
+ std::cerr << " format type = 0x" << std::hex << panel->mMediaSource->getTextureFormatType() << std::dec << std::endl;
+ std::cerr << " pixels = " << (void*)pixels << std::endl;
+ }
+
+ if(panel->mMediaSource->getTextureFormatSwapBytes())
+ {
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
+ checkGLError("glPixelStorei");
+ }
+
+ panel->mMediaSource->resetDirty();
+
+ panel->mReadyToRender = true;
+ }
+ else
+ {
+ std::cerr << "dirty rect is outside current media size, skipping update" << std::endl;
+ }
+ };
+ };
+ };
+
+ // GLUI requires this
+ if ( glutGetWindow() != mAppWindow )
+ glutSetWindow( mAppWindow );
+
+ // trigger re-display
+ glutPostRedisplay();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::windowPosToTexturePos( int window_x, int window_y,
+ int& media_x, int& media_y,
+ int& id )
+{
+ if ( ! mSelectedPanel )
+ {
+ media_x = 0;
+ media_y = 0;
+ id = 0;
+ return;
+ };
+
+ // record cursor poisiton for a readback next frame
+ mCurMouseX = window_x;
+ // OpenGL app == coordinate system this way
+ // NOTE: unrelated to settings in plugin - this
+ // is just for this app
+ mCurMouseY = mWindowHeight - window_y;
+
+ // extract x (0..1023, y (0..1023) and id (0..15) from RGB components
+ unsigned long pixel_read_color_bits = ( mPixelReadColor[ 0 ] << 16 ) | ( mPixelReadColor[ 1 ] << 8 ) | mPixelReadColor[ 2 ];
+ int texture_x = pixel_read_color_bits & 0x3ff;
+ int texture_y = ( pixel_read_color_bits >> 10 ) & 0x3ff;
+ id = ( pixel_read_color_bits >> 20 ) & 0x0f;
+
+ // scale to size of media (1024 because we use 10 bits for X and Y from 24)
+ media_x = (int)( ( (float)mSelectedPanel->mMediaWidth * (float)texture_x ) / 1024.0f );
+ media_y = (int)( ( (float)mSelectedPanel->mMediaHeight * (float)texture_y ) / 1024.0f );
+
+ // we assume the plugin uses an inverted coordinate scheme like OpenGL
+ // if not, the plugin code inverts the Y coordinate for us - we don't need to
+ media_y = mSelectedPanel->mMediaHeight - media_y;
+
+ if ( media_x > 0 && media_y > 0 )
+ {
+ //std::cout << " mouse coords: " << mCurMouseX << " x " << mCurMouseY << " and id = " << id << std::endl;
+ //std::cout << "raw texture coords: " << texture_x << " x " << texture_y << " and id = " << id << std::endl;
+ //std::cout << " media coords: " << media_x << " x " << media_y << " and id = " << id << std::endl;
+ //std::cout << std::endl;
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::selectPanelById( int id )
+{
+ for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel )
+ {
+ if ( mMediaPanels[ panel ]->mId == id )
+ {
+ selectPanel(mMediaPanels[ panel ]);
+ return;
+ };
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::selectPanel( mediaPanel* panel )
+{
+ if( mSelectedPanel == panel )
+ return;
+
+ // turn off volume before we delete it
+ if( mSelectedPanel && mSelectedPanel->mMediaSource )
+ {
+ mSelectedPanel->mMediaSource->setVolume( 0.0f );
+ mSelectedPanel->mMediaSource->setPriority( LLPluginClassMedia::PRIORITY_LOW );
+ };
+
+ mSelectedPanel = panel;
+
+ if( mSelectedPanel && mSelectedPanel->mMediaSource )
+ {
+ mSelectedPanel->mMediaSource->setVolume( (float)mMediaTimeControlVolume / 100.0f );
+ mSelectedPanel->mMediaSource->setPriority( LLPluginClassMedia::PRIORITY_NORMAL );
+
+ if(!mSelectedPanel->mStartUrl.empty())
+ {
+ mUrlEdit->set_text(const_cast<char*>(mSelectedPanel->mStartUrl.c_str()) );
+ }
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+mediaPanel* LLMediaPluginTest::findMediaPanel( LLPluginClassMedia* source )
+{
+ mediaPanel *result = NULL;
+
+ for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel )
+ {
+ if ( mMediaPanels[ panel ]->mMediaSource == source )
+ {
+ result = mMediaPanels[ panel ];
+ }
+ }
+
+ return result;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::navigateToNewURI( std::string uri )
+{
+ if ( uri.length() )
+ {
+ std::string mime_type = mimeTypeFromUrl( uri );
+
+ if ( !mSelectedPanel->mMediaSource->isPluginExited() && (mime_type == mSelectedPanel->mMimeType) )
+ {
+ std::cout << "MIME type is the same" << std::endl;
+ mSelectedPanel->mMediaSource->loadURI( uri );
+ mSelectedPanel->mMediaSource->start();
+ mBookmarkList->do_selection( 0 );
+ }
+ else
+ {
+ std::cout << "MIME type changed or plugin had exited" << std::endl;
+ replaceMediaPanel( mSelectedPanel, uri );
+ mBookmarkList->do_selection( 0 );
+ }
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::initUrlHistory( std::string uris )
+{
+ if ( uris.length() > 0 )
+ {
+ std::cout << "init URL : " << uris << std::endl;
+ LLSD historySD;
+
+ char *cstr, *p;
+ cstr = new char[uris.size()+1];
+ strcpy(cstr, uris.c_str());
+ const char *DELIMS = " ,;";
+ p = strtok(cstr, DELIMS);
+ while (p != NULL) {
+ historySD.insert(0, p);
+ p = strtok(NULL, DELIMS);
+ }
+ mSelectedPanel->mMediaSource->initializeUrlHistory(historySD);
+ delete[] cstr;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::gluiCallback( int control_id )
+{
+ if ( control_id == mIdBookmarks )
+ {
+ std::string uri = mBookmarks[ mSelBookmark ].second;
+
+ navigateToNewURI( uri );
+ }
+ else
+ if ( control_id == mIdUrlEdit)
+ {
+ std::string uri = mUrlEdit->get_text();
+
+ navigateToNewURI( uri );
+ }
+ else
+ if ( control_id == mIdUrlInitHistoryEdit )
+ {
+ std::string uri = mUrlInitHistoryEdit->get_text();
+
+ initUrlHistory( uri );
+ }
+ else
+ if ( control_id == mIdControlAddPanel )
+ {
+ addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second );
+ }
+ else
+ if ( control_id == mIdControlRemPanel )
+ {
+ remMediaPanel( mSelectedPanel );
+ }
+ else
+ if ( control_id == mIdDisableTimeout )
+ {
+ // Set the "disable timeout" flag for all active plugins.
+ for( int i = 0; i < (int)mMediaPanels.size(); ++i )
+ {
+ mMediaPanels[ i ]->mMediaSource->setDisableTimeout(mDisableTimeout);
+ }
+ }
+ else
+ if ( control_id == mIdControlCrashPlugin )
+ {
+ // send message to plugin and ask it to crash
+ // (switch out for ReleaseCandidate version :) )
+ if(mSelectedPanel && mSelectedPanel->mMediaSource)
+ {
+ mSelectedPanel->mMediaSource->crashPlugin();
+ }
+ }
+ else
+ if ( control_id == mIdControlHangPlugin )
+ {
+ // send message to plugin and ask it to hang
+ // (switch out for ReleaseCandidate version :) )
+ if(mSelectedPanel && mSelectedPanel->mMediaSource)
+ {
+ mSelectedPanel->mMediaSource->hangPlugin();
+ }
+ }
+ else
+ if ( control_id == mIdControlExitApp )
+ {
+ // text for exiting plugin system cleanly
+ delete this; // clean up
+ exit( 0 );
+ }
+ else
+ if ( control_id == mIdMediaTimeControlPlay )
+ {
+ if ( mSelectedPanel )
+ {
+ mSelectedPanel->mMediaSource->setLoop( false );
+ mSelectedPanel->mMediaSource->start();
+ };
+ }
+ else
+ if ( control_id == mIdMediaTimeControlLoop )
+ {
+ if ( mSelectedPanel )
+ {
+ mSelectedPanel->mMediaSource->setLoop( true );
+ mSelectedPanel->mMediaSource->start();
+ };
+ }
+ else
+ if ( control_id == mIdMediaTimeControlPause )
+ {
+ if ( mSelectedPanel )
+ mSelectedPanel->mMediaSource->pause();
+ }
+ else
+ if ( control_id == mIdMediaTimeControlStop )
+ {
+ if ( mSelectedPanel )
+ {
+ mSelectedPanel->mMediaSource->stop();
+ };
+ }
+ else
+ if ( control_id == mIdMediaTimeControlSeek )
+ {
+ if ( mSelectedPanel )
+ {
+ // get value from spinner
+ float seconds_to_seek = mMediaTimeControlSeekSeconds;
+ mSelectedPanel->mMediaSource->seek( seconds_to_seek );
+ mSelectedPanel->mMediaSource->start();
+ };
+ }
+ else
+ if ( control_id == mIdMediaTimeControlRewind )
+ {
+ if ( mSelectedPanel )
+ {
+ mSelectedPanel->mMediaSource->setLoop( false );
+ mSelectedPanel->mMediaSource->start(-2.0f);
+ };
+ }
+ else
+ if ( control_id == mIdMediaTimeControlFastForward )
+ {
+ if ( mSelectedPanel )
+ {
+ mSelectedPanel->mMediaSource->setLoop( false );
+ mSelectedPanel->mMediaSource->start(2.0f);
+ };
+ }
+ else
+ if ( control_id == mIdMediaBrowserControlBack )
+ {
+ if ( mSelectedPanel )
+ mSelectedPanel->mMediaSource->browse_back();
+ }
+ else
+ if ( control_id == mIdMediaBrowserControlStop )
+ {
+ if ( mSelectedPanel )
+ mSelectedPanel->mMediaSource->browse_stop();
+ }
+ else
+ if ( control_id == mIdMediaBrowserControlForward )
+ {
+ if ( mSelectedPanel )
+ mSelectedPanel->mMediaSource->browse_forward();
+ }
+ else
+ if ( control_id == mIdMediaBrowserControlHome )
+ {
+ if ( mSelectedPanel )
+ mSelectedPanel->mMediaSource->loadURI( mHomeWebUrl );
+ }
+ else
+ if ( control_id == mIdMediaBrowserControlReload )
+ {
+ if ( mSelectedPanel )
+ mSelectedPanel->mMediaSource->browse_reload( true );
+ }
+ else
+ if ( control_id == mIdMediaBrowserControlClearCache )
+ {
+ if ( mSelectedPanel )
+ mSelectedPanel->mMediaSource->clear_cache();
+ }
+ else
+ if ( control_id == mIdMediaBrowserControlClearCookies )
+ {
+ if ( mSelectedPanel )
+ mSelectedPanel->mMediaSource->clear_cookies();
+ }
+ else
+ if ( control_id == mIdMediaBrowserControlEnableCookies )
+ {
+ if ( mSelectedPanel )
+ {
+ if ( mMediaBrowserControlEnableCookies )
+ {
+ mSelectedPanel->mMediaSource->enable_cookies( true );
+ }
+ else
+ {
+ mSelectedPanel->mMediaSource->enable_cookies( false );
+ }
+ };
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::keyboard( int key )
+{
+ //if ( key == 'a' || key == 'A' )
+ // addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second );
+ //else
+ //if ( key == 'r' || key == 'R' )
+ // remMediaPanel( mSelectedPanel );
+ //else
+ //if ( key == 'd' || key == 'D' )
+ // dumpPanelInfo();
+ //else
+ if ( key == 27 )
+ {
+ std::cout << "Application finished - exiting..." << std::endl;
+ delete this;
+ exit( 0 );
+ };
+
+ mSelectedPanel->mMediaSource->keyEvent( LLPluginClassMedia::KEY_EVENT_DOWN, key, 0 );
+ mSelectedPanel->mMediaSource->keyEvent( LLPluginClassMedia::KEY_EVENT_UP, key, 0 );
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::mouseButton( int button, int state, int x, int y )
+{
+ if ( button == GLUT_LEFT_BUTTON )
+ {
+ if ( state == GLUT_DOWN )
+ {
+ int media_x, media_y, id;
+ windowPosToTexturePos( x, y, media_x, media_y, id );
+
+ if ( mSelectedPanel )
+ mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_DOWN, 0, media_x, media_y, 0 );
+ }
+ else
+ if ( state == GLUT_UP )
+ {
+ int media_x, media_y, id;
+ windowPosToTexturePos( x, y, media_x, media_y, id );
+
+ // only select a panel if we're on a panel
+ // (HACK: strictly speaking this rules out clicking on
+ // the origin of a panel but that's very unlikely)
+ if ( media_x > 0 && media_y > 0 )
+ {
+ selectPanelById( id );
+
+ if ( mSelectedPanel )
+ mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_UP, 0, media_x, media_y, 0 );
+ };
+ };
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::mousePassive( int x, int y )
+{
+ int media_x, media_y, id;
+ windowPosToTexturePos( x, y, media_x, media_y, id );
+
+ if ( mSelectedPanel )
+ mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, media_x, media_y, 0 );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::mouseMove( int x, int y )
+{
+ int media_x, media_y, id;
+ windowPosToTexturePos( x, y, media_x, media_y, id );
+
+ if ( mSelectedPanel )
+ mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, media_x, media_y, 0 );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::makeChrome()
+{
+ // IDs used by GLUI
+ int start_id = 0x1000;
+
+ // right side window - geometry manipulators
+#if __APPLE__
+ // the Apple GLUT implementation doesn't seem to set the graphic offset of subwindows correctly when they overlap in certain ways.
+ // Use a separate controls window in this case.
+ // GLUI window at right containing manipulation controls and other buttons
+ int x = glutGet(GLUT_WINDOW_X) + glutGet(GLUT_WINDOW_WIDTH) + 4;
+ int y = glutGet(GLUT_WINDOW_Y);
+ GLUI* right_glui_window = GLUI_Master.create_glui( "", 0, x, y );
+#else
+ GLUI* right_glui_window = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_RIGHT );
+#endif
+ mViewRotationCtrl = right_glui_window->add_rotation( "Rotation", mViewRotation );
+ mViewTranslationCtrl = right_glui_window->add_translation( "Translate", GLUI_TRANSLATION_XY, mViewPos );
+ mViewTranslationCtrl->set_speed( 0.01f );
+ mViewScaleCtrl = right_glui_window->add_translation( "Scale", GLUI_TRANSLATION_Z, &mViewPos[ 2 ] );
+ mViewScaleCtrl->set_speed( 0.05f );
+ right_glui_window->set_main_gfx_window( mAppWindow );
+
+ // right side window - app controls
+ mIdControlAddPanel = start_id++;
+ right_glui_window->add_statictext( "" );
+ right_glui_window->add_separator();
+ right_glui_window->add_statictext( "" );
+ right_glui_window->add_button( "Add panel", mIdControlAddPanel, gluiCallbackWrapper );
+ right_glui_window->add_statictext( "" );
+ mIdControlRemPanel = start_id++;
+ right_glui_window->add_button( "Rem panel", mIdControlRemPanel, gluiCallbackWrapper );
+ right_glui_window->add_statictext( "" );
+ right_glui_window->add_separator();
+ right_glui_window->add_statictext( "" );
+ mIdControlCrashPlugin = start_id++;
+ right_glui_window->add_button( "Crash plugin", mIdControlCrashPlugin, gluiCallbackWrapper );
+ mIdControlHangPlugin = start_id++;
+ right_glui_window->add_button( "Hang plugin", mIdControlHangPlugin, gluiCallbackWrapper );
+
+ right_glui_window->add_statictext( "" );
+ right_glui_window->add_separator();
+ right_glui_window->add_statictext( "" );
+ mIdControlExitApp = start_id++;
+ right_glui_window->add_button( "Exit app", mIdControlExitApp, gluiCallbackWrapper );
+
+ //// top window - holds bookmark UI
+ mIdBookmarks = start_id++;
+ mSelBookmark = 0;
+ GLUI* glui_window_top = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
+ mBookmarkList = glui_window_top->add_listbox( "", &mSelBookmark, mIdBookmarks, gluiCallbackWrapper );
+ // only add the first 50 bookmarks - list can be very long sometimes (30,000+)
+ // when testing list of media URLs from AGNI for example
+ for( unsigned int each = 0; each < mBookmarks.size() && each < 50; ++each )
+ mBookmarkList->add_item( each, const_cast< char* >( mBookmarks[ each ].first.c_str() ) );
+ glui_window_top->set_main_gfx_window( mAppWindow );
+
+ glui_window_top->add_column( false );
+ mIdUrlEdit = start_id++;
+ mUrlEdit = glui_window_top->add_edittext( "Url:", GLUI_EDITTEXT_TEXT, 0, mIdUrlEdit, gluiCallbackWrapper );
+ mUrlEdit->set_w( 600 );
+ GLUI* glui_window_top2 = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
+ mIdUrlInitHistoryEdit = start_id++;
+ mUrlInitHistoryEdit = glui_window_top2->add_edittext( "Init History (separate by commas or semicolons):",
+ GLUI_EDITTEXT_TEXT, 0, mIdUrlInitHistoryEdit, gluiCallbackWrapper );
+ mUrlInitHistoryEdit->set_w( 800 );
+
+ // top window - media controls for "time" media types (e.g. movies)
+ mGluiMediaTimeControlWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
+ mGluiMediaTimeControlWindow->set_main_gfx_window( mAppWindow );
+ mIdMediaTimeControlPlay = start_id++;
+ mGluiMediaTimeControlWindow->add_button( "PLAY", mIdMediaTimeControlPlay, gluiCallbackWrapper );
+ mGluiMediaTimeControlWindow->add_column( false );
+ mIdMediaTimeControlLoop = start_id++;
+ mGluiMediaTimeControlWindow->add_button( "LOOP", mIdMediaTimeControlLoop, gluiCallbackWrapper );
+ mGluiMediaTimeControlWindow->add_column( false );
+ mIdMediaTimeControlPause = start_id++;
+ mGluiMediaTimeControlWindow->add_button( "PAUSE", mIdMediaTimeControlPause, gluiCallbackWrapper );
+ mGluiMediaTimeControlWindow->add_column( false );
+
+ GLUI_Button *button;
+ mIdMediaTimeControlRewind = start_id++;
+ button = mGluiMediaTimeControlWindow->add_button( "<<", mIdMediaTimeControlRewind, gluiCallbackWrapper );
+ button->set_w(30);
+ mGluiMediaTimeControlWindow->add_column( false );
+ mIdMediaTimeControlFastForward = start_id++;
+ button = mGluiMediaTimeControlWindow->add_button( ">>", mIdMediaTimeControlFastForward, gluiCallbackWrapper );
+ button->set_w(30);
+
+ mGluiMediaTimeControlWindow->add_column( true );
+
+ mIdMediaTimeControlStop = start_id++;
+ mGluiMediaTimeControlWindow->add_button( "STOP", mIdMediaTimeControlStop, gluiCallbackWrapper );
+ mGluiMediaTimeControlWindow->add_column( false );
+ mIdMediaTimeControlVolume = start_id++;
+ GLUI_Spinner* spinner = mGluiMediaTimeControlWindow->add_spinner( "Volume", 2, &mMediaTimeControlVolume, mIdMediaTimeControlVolume, gluiCallbackWrapper);
+ spinner->set_float_limits( 0, 100 );
+ mGluiMediaTimeControlWindow->add_column( true );
+ mIdMediaTimeControlSeekSeconds = start_id++;
+ spinner = mGluiMediaTimeControlWindow->add_spinner( "", 2, &mMediaTimeControlSeekSeconds, mIdMediaTimeControlSeekSeconds, gluiCallbackWrapper);
+ spinner->set_float_limits( 0, 200 );
+ spinner->set_w( 32 );
+ spinner->set_speed( 0.025f );
+ mGluiMediaTimeControlWindow->add_column( false );
+ mIdMediaTimeControlSeek = start_id++;
+ mGluiMediaTimeControlWindow->add_button( "SEEK", mIdMediaTimeControlSeek, gluiCallbackWrapper );
+ mGluiMediaTimeControlWindow->add_column( false );
+
+
+ // top window - media controls for "browser" media types (e.g. web browser)
+ mGluiMediaBrowserControlWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
+ mGluiMediaBrowserControlWindow->set_main_gfx_window( mAppWindow );
+ mIdMediaBrowserControlBack = start_id++;
+ mMediaBrowserControlBackButton = mGluiMediaBrowserControlWindow->add_button( "BACK", mIdMediaBrowserControlBack, gluiCallbackWrapper );
+ mGluiMediaBrowserControlWindow->add_column( false );
+ mIdMediaBrowserControlStop = start_id++;
+ mGluiMediaBrowserControlWindow->add_button( "STOP", mIdMediaBrowserControlStop, gluiCallbackWrapper );
+ mGluiMediaBrowserControlWindow->add_column( false );
+ mIdMediaBrowserControlForward = start_id++;
+ mMediaBrowserControlForwardButton = mGluiMediaBrowserControlWindow->add_button( "FORWARD", mIdMediaBrowserControlForward, gluiCallbackWrapper );
+ mGluiMediaBrowserControlWindow->add_column( false );
+ mIdMediaBrowserControlHome = start_id++;
+ mGluiMediaBrowserControlWindow->add_button( "HOME", mIdMediaBrowserControlHome, gluiCallbackWrapper );
+ mGluiMediaBrowserControlWindow->add_column( false );
+ mIdMediaBrowserControlReload = start_id++;
+ mGluiMediaBrowserControlWindow->add_button( "RELOAD", mIdMediaBrowserControlReload, gluiCallbackWrapper );
+ mGluiMediaBrowserControlWindow->add_column( false );
+ mIdMediaBrowserControlClearCache = start_id++;
+ mGluiMediaBrowserControlWindow->add_button( "CLEAR CACHE", mIdMediaBrowserControlClearCache, gluiCallbackWrapper );
+ mGluiMediaBrowserControlWindow->add_column( false );
+ mIdMediaBrowserControlClearCookies = start_id++;
+ mGluiMediaBrowserControlWindow->add_button( "CLEAR COOKIES", mIdMediaBrowserControlClearCookies, gluiCallbackWrapper );
+ mGluiMediaBrowserControlWindow->add_column( false );
+ mIdMediaBrowserControlEnableCookies = start_id++;
+ mMediaBrowserControlEnableCookies = 0;
+ mGluiMediaBrowserControlWindow->add_checkbox( "Enable Cookies", &mMediaBrowserControlEnableCookies, mIdMediaBrowserControlEnableCookies, gluiCallbackWrapper );
+
+ // top window - misc controls
+ GLUI* glui_window_misc_control = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP );
+ mIdRandomPanelCount = start_id++;
+ mRandomPanelCount = 0;
+ glui_window_misc_control->add_checkbox( "Randomize panel count", &mRandomPanelCount, mIdRandomPanelCount, gluiCallbackWrapper );
+ glui_window_misc_control->set_main_gfx_window( mAppWindow );
+ glui_window_misc_control->add_column( true );
+ mIdRandomBookmarks = start_id++;
+ mRandomBookmarks = 0;
+ glui_window_misc_control->add_checkbox( "Randomize bookmarks", &mRandomBookmarks, mIdRandomBookmarks, gluiCallbackWrapper );
+ glui_window_misc_control->set_main_gfx_window( mAppWindow );
+ glui_window_misc_control->add_column( true );
+
+ mIdDisableTimeout = start_id++;
+ mDisableTimeout = 0;
+ glui_window_misc_control->add_checkbox( "Disable plugin timeout", &mDisableTimeout, mIdDisableTimeout, gluiCallbackWrapper );
+ glui_window_misc_control->set_main_gfx_window( mAppWindow );
+
+ // bottom window - status
+ mBottomGLUIWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_BOTTOM );
+ mStatusText = mBottomGLUIWindow->add_statictext( "" );
+ mBottomGLUIWindow->set_main_gfx_window( mAppWindow );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::resetView()
+{
+ mViewRotationCtrl->reset();
+
+ mViewScaleCtrl->set_x( 0.0f );
+ mViewScaleCtrl->set_y( 0.0f );
+ mViewScaleCtrl->set_z( 3.0f );
+
+ mViewTranslationCtrl->set_x( 0.0f );
+ mViewTranslationCtrl->set_y( 0.0f );
+ mViewTranslationCtrl->set_z( 0.0f );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::makePickTexture( int id, GLuint* texture_handle, unsigned char** texture_pixels )
+{
+ int pick_texture_width = 1024;
+ int pick_texture_height = 1024;
+ int pick_texture_depth = 3;
+ unsigned char* ptr = new unsigned char[ pick_texture_width * pick_texture_height * pick_texture_depth ];
+ for( int y = 0; y < pick_texture_height; ++y )
+ {
+ for( int x = 0; x < pick_texture_width * pick_texture_depth ; x += pick_texture_depth )
+ {
+ unsigned long bits = 0L;
+ bits |= ( id << 20 ) | ( y << 10 ) | ( x / 3 );
+ unsigned char r_component = ( bits >> 16 ) & 0xff;
+ unsigned char g_component = ( bits >> 8 ) & 0xff;
+ unsigned char b_component = bits & 0xff;
+
+ ptr[ y * pick_texture_width * pick_texture_depth + x + 0 ] = r_component;
+ ptr[ y * pick_texture_width * pick_texture_depth + x + 1 ] = g_component;
+ ptr[ y * pick_texture_width * pick_texture_depth + x + 2 ] = b_component;
+ };
+ };
+
+ glGenTextures( 1, texture_handle );
+
+ checkGLError("glGenTextures");
+ std::cout << "glGenTextures returned " << *texture_handle << std::endl;
+
+ bindTexture( *texture_handle );
+ glTexImage2D( GL_TEXTURE_2D, 0,
+ GL_RGB,
+ pick_texture_width, pick_texture_height,
+ 0, GL_RGB, GL_UNSIGNED_BYTE, ptr );
+
+ *texture_pixels = ptr;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+std::string LLMediaPluginTest::mimeTypeFromUrl( std::string& url )
+{
+ // default to web
+ std::string mime_type = "text/html";
+
+ // we may need a more advanced MIME type accessor later :-)
+ if ( url.find( ".mov" ) != std::string::npos ) // Movies
+ mime_type = "video/quicktime";
+ else
+ if ( url.find( ".txt" ) != std::string::npos ) // Apple Text descriptors
+ mime_type = "video/quicktime";
+ else
+ if ( url.find( ".mp3" ) != std::string::npos ) // Apple Text descriptors
+ mime_type = "video/quicktime";
+ else
+ if ( url.find( "example://" ) != std::string::npos ) // Example plugin
+ mime_type = "example/example";
+
+ return mime_type;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+std::string LLMediaPluginTest::pluginNameFromMimeType( std::string& mime_type )
+{
+#if LL_DARWIN
+ std::string plugin_name( "media_plugin_null.dylib" );
+ if ( mime_type == "video/quicktime" )
+ plugin_name = "media_plugin_quicktime.dylib";
+ else
+ if ( mime_type == "text/html" )
+ plugin_name = "media_plugin_webkit.dylib";
+
+#elif LL_WINDOWS
+ std::string plugin_name( "media_plugin_null.dll" );
+
+ if ( mime_type == "video/quicktime" )
+ plugin_name = "media_plugin_quicktime.dll";
+ else
+ if ( mime_type == "text/html" )
+ plugin_name = "media_plugin_webkit.dll";
+ else
+ if ( mime_type == "example/example" )
+ plugin_name = "media_plugin_example.dll";
+
+#elif LL_LINUX
+ std::string plugin_name( "libmedia_plugin_null.so" );
+
+ if ( mime_type == "video/quicktime" )
+ plugin_name = "libmedia_plugin_quicktime.so";
+ else
+ if ( mime_type == "text/html" )
+ plugin_name = "libmedia_plugin_webkit.so";
+#endif
+ return plugin_name;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::addMediaPanel( std::string url )
+{
+ // Get the plugin filename using the URL
+ std::string mime_type = mimeTypeFromUrl( url );
+ std::string plugin_name = pluginNameFromMimeType( mime_type );
+
+ // create a random size for the new media
+ int media_width;
+ int media_height;
+ getRandomMediaSize( media_width, media_height, mime_type );
+
+ // make a new plugin
+ LLPluginClassMedia* media_source = new LLPluginClassMedia(this);
+
+ // tell the plugin what size we asked for
+ media_source->setSize( media_width, media_height );
+
+ // Use the launcher start and initialize the plugin
+#if LL_DARWIN || LL_LINUX
+ std::string launcher_name( "SLPlugin" );
+#elif LL_WINDOWS
+ std::string launcher_name( "SLPlugin.exe" );
+#endif
+
+ // for this test app, use the cwd as the user data path (ugh).
+#if LL_WINDOWS
+ std::string user_data_path = ".\\";
+#else
+ char cwd[ FILENAME_MAX ];
+ if (NULL == getcwd( cwd, FILENAME_MAX - 1 ))
+ {
+ std::cerr << "Couldn't get cwd - probably too long - failing to init." << std::endl;
+ return;
+ }
+ std::string user_data_path = std::string( cwd ) + "/";
+#endif
+
+ media_source->init( launcher_name, plugin_name, false, user_data_path );
+ media_source->setDisableTimeout(mDisableTimeout);
+
+ // make a new panel and save parameters
+ mediaPanel* panel = new mediaPanel;
+ panel->mMediaSource = media_source;
+ panel->mStartUrl = url;
+ panel->mMimeType = mime_type;
+ panel->mMediaWidth = media_width;
+ panel->mMediaHeight = media_height;
+ panel->mTextureWidth = 0;
+ panel->mTextureHeight = 0;
+ panel->mTextureScaleX = 0;
+ panel->mTextureScaleY = 0;
+ panel->mMediaTextureHandle = 0;
+ panel->mPickTextureHandle = 0;
+ panel->mAppTextureCoordsOpenGL = false; // really need an 'undefined' state here too
+ panel->mReadyToRender = false;
+
+ // look through current media panels to find an unused index number
+ bool id_exists = true;
+ for( int nid = 0; nid < mMaxPanels; ++nid )
+ {
+ // does this id exist already?
+ id_exists = false;
+ for( int pid = 0; pid < (int)mMediaPanels.size(); ++pid )
+ {
+ if ( nid == mMediaPanels[ pid ]->mId )
+ {
+ id_exists = true;
+ break;
+ };
+ };
+
+ // id wasn't found so we can use it
+ if ( ! id_exists )
+ {
+ panel->mId = nid;
+ break;
+ };
+ };
+
+ // if we get here and this flag is set, there is no room for any more panels
+ if ( id_exists )
+ {
+ std::cout << "No room for any more panels" << std::endl;
+ }
+ else
+ {
+ // now we have the ID we can use it to make the
+ // pick texture (id is baked into texture pixels)
+ makePickTexture( panel->mId, &panel->mPickTextureHandle, &panel->mPickTexturePixels );
+
+ // save this in the list of panels
+ mMediaPanels.push_back( panel );
+
+ // select the panel that was just created
+ selectPanel( panel );
+
+ // load and start the URL
+ panel->mMediaSource->loadURI( url );
+ panel->mMediaSource->start();
+
+ std::cout << "Adding new media panel for " << url << "(" << media_width << "x" << media_height << ") with index " << panel->mId << " - total panels = " << mMediaPanels.size() << std::endl;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::updateMediaPanel( mediaPanel* panel )
+{
+// checkGLError("LLMediaPluginTest::updateMediaPanel");
+
+ if ( ! panel )
+ return;
+
+ if(!panel->mMediaSource || !panel->mMediaSource->textureValid())
+ {
+ panel->mReadyToRender = false;
+ return;
+ }
+
+ // take a reference copy of the plugin values since they
+ // might change during this lifetime of this function
+ int plugin_media_width = panel->mMediaSource->getWidth();
+ int plugin_media_height = panel->mMediaSource->getHeight();
+ int plugin_texture_width = panel->mMediaSource->getBitsWidth();
+ int plugin_texture_height = panel->mMediaSource->getBitsHeight();
+
+ // If the texture isn't created or the media or texture dimensions changed AND
+ // the sizes are valid then we need to delete the old media texture (if necessary)
+ // then make a new one.
+ if ((panel->mMediaTextureHandle == 0 ||
+ panel->mMediaWidth != plugin_media_width ||
+ panel->mMediaHeight != plugin_media_height ||
+ panel->mTextureWidth != plugin_texture_width ||
+ panel->mTextureHeight != plugin_texture_height) &&
+ ( plugin_media_width > 0 && plugin_media_height > 0 &&
+ plugin_texture_width > 0 && plugin_texture_height > 0 ) )
+ {
+ std::cout << "Valid media size (" << plugin_media_width << " x " << plugin_media_height
+ << ") and texture size (" << plugin_texture_width << " x " << plugin_texture_height
+ << ") for panel with ID=" << panel->mId << " - making texture" << std::endl;
+
+ // delete old GL texture
+ if ( isTexture( panel->mMediaTextureHandle ) )
+ {
+ std::cerr << "updateMediaPanel: deleting texture " << panel->mMediaTextureHandle << std::endl;
+ glDeleteTextures( 1, &panel->mMediaTextureHandle );
+ panel->mMediaTextureHandle = 0;
+ }
+
+ std::cerr << "before: pick texture is " << panel->mPickTextureHandle << ", media texture is " << panel->mMediaTextureHandle << std::endl;
+
+ // make a GL texture based on the dimensions the plugin told us
+ GLuint new_texture = 0;
+ glGenTextures( 1, &new_texture );
+
+ checkGLError("glGenTextures");
+
+ std::cout << "glGenTextures returned " << new_texture << std::endl;
+
+ panel->mMediaTextureHandle = new_texture;
+
+ bindTexture( panel->mMediaTextureHandle );
+
+ std::cout << "Setting texture size to " << plugin_texture_width << " x " << plugin_texture_height << std::endl;
+ glTexImage2D( GL_TEXTURE_2D, 0,
+ GL_RGB,
+ plugin_texture_width, plugin_texture_height,
+ 0, GL_RGB, GL_UNSIGNED_BYTE,
+ 0 );
+
+
+ std::cerr << "after: pick texture is " << panel->mPickTextureHandle << ", media texture is " << panel->mMediaTextureHandle << std::endl;
+ };
+
+ // update our record of the media and texture dimensions
+ // NOTE: do this after we we check for sizes changes
+ panel->mMediaWidth = plugin_media_width;
+ panel->mMediaHeight = plugin_media_height;
+ panel->mTextureWidth = plugin_texture_width;
+ panel->mTextureHeight = plugin_texture_height;
+ if ( plugin_texture_width > 0 )
+ {
+ panel->mTextureScaleX = (double)panel->mMediaWidth / (double)panel->mTextureWidth;
+ };
+ if ( plugin_texture_height > 0 )
+ {
+ panel->mTextureScaleY = (double)panel->mMediaHeight / (double)panel->mTextureHeight;
+ };
+
+ // update the flag which tells us if the media source uses OprnGL coords or not.
+ panel->mAppTextureCoordsOpenGL = panel->mMediaSource->getTextureCoordsOpenGL();
+
+ // Check to see if we have enough to render this panel.
+ // If we do, set a flag that the display functions use so
+ // they only render a panel with media if it's ready.
+ if ( panel->mMediaWidth < 0 ||
+ panel->mMediaHeight < 0 ||
+ panel->mTextureWidth < 1 ||
+ panel->mTextureHeight < 1 ||
+ panel->mMediaTextureHandle == 0 )
+ {
+ panel->mReadyToRender = false;
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::replaceMediaPanel( mediaPanel* panel, std::string url )
+{
+ // no media panels so we can't change anything - have to add
+ if ( mMediaPanels.size() == 0 )
+ return;
+
+ // sanity check
+ if ( ! panel )
+ return;
+
+ int index;
+ for(index = 0; index < (int)mMediaPanels.size(); index++)
+ {
+ if(mMediaPanels[index] == panel)
+ break;
+ }
+
+ if(index >= (int)mMediaPanels.size())
+ {
+ // panel isn't in mMediaPanels
+ return;
+ }
+
+ std::cout << "Replacing media panel with index " << panel->mId << std::endl;
+
+ int panel_id = panel->mId;
+
+ if(mSelectedPanel == panel)
+ mSelectedPanel = NULL;
+
+ delete panel;
+
+ // Get the plugin filename using the URL
+ std::string mime_type = mimeTypeFromUrl( url );
+ std::string plugin_name = pluginNameFromMimeType( mime_type );
+
+ // create a random size for the new media
+ int media_width;
+ int media_height;
+ getRandomMediaSize( media_width, media_height, mime_type );
+
+ // make a new plugin
+ LLPluginClassMedia* media_source = new LLPluginClassMedia(this);
+
+ // tell the plugin what size we asked for
+ media_source->setSize( media_width, media_height );
+
+ // Use the launcher start and initialize the plugin
+#if LL_DARWIN || LL_LINUX
+ std::string launcher_name( "SLPlugin" );
+#elif LL_WINDOWS
+ std::string launcher_name( "SLPlugin.exe" );
+#endif
+
+ // for this test app, use the cwd as the user data path (ugh).
+#if LL_WINDOWS
+ std::string user_data_path = ".\\";
+#else
+ char cwd[ FILENAME_MAX ];
+ if (NULL == getcwd( cwd, FILENAME_MAX - 1 ))
+ {
+ std::cerr << "Couldn't get cwd - probably too long - failing to init." << std::endl;
+ return;
+ }
+ std::string user_data_path = std::string( cwd ) + "/";
+#endif
+
+ media_source->init( launcher_name, plugin_name, false, user_data_path );
+ media_source->setDisableTimeout(mDisableTimeout);
+
+ // make a new panel and save parameters
+ panel = new mediaPanel;
+ panel->mMediaSource = media_source;
+ panel->mStartUrl = url;
+ panel->mMimeType = mime_type;
+ panel->mMediaWidth = media_width;
+ panel->mMediaHeight = media_height;
+ panel->mTextureWidth = 0;
+ panel->mTextureHeight = 0;
+ panel->mTextureScaleX = 0;
+ panel->mTextureScaleY = 0;
+ panel->mMediaTextureHandle = 0;
+ panel->mPickTextureHandle = 0;
+ panel->mAppTextureCoordsOpenGL = false; // really need an 'undefined' state here too
+ panel->mReadyToRender = false;
+
+ panel->mId = panel_id;
+
+ // Replace the entry in the panels array
+ mMediaPanels[index] = panel;
+
+ // now we have the ID we can use it to make the
+ // pick texture (id is baked into texture pixels)
+ makePickTexture( panel->mId, &panel->mPickTextureHandle, &panel->mPickTexturePixels );
+
+ // select the panel that was just created
+ selectPanel( panel );
+
+ // load and start the URL
+ panel->mMediaSource->loadURI( url );
+ panel->mMediaSource->start();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::getRandomMediaSize( int& width, int& height, std::string mime_type )
+{
+ // Make a new media source with a random size which we'll either
+ // directly or the media plugin will tell us what it wants later.
+ // Use a random size so we can test support for weird media sizes.
+ // (Almost everything else will get filled in later once the
+ // plugin responds)
+ // NB. Do we need to enforce that width is on 4 pixel boundary?
+ width = ( ( rand() % 170 ) + 30 ) * 4;
+ height = ( ( rand() % 170 ) + 30 ) * 4;
+
+ // adjust this random size if it's a browser so we get
+ // a more useful size for testing..
+ if ( mime_type == "text/html" || mime_type == "example/example" )
+ {
+ width = ( ( rand() % 100 ) + 100 ) * 4;
+ height = ( width * ( ( rand() % 400 ) + 1000 ) ) / 1000;
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::remMediaPanel( mediaPanel* panel )
+{
+ // always leave one panel
+ if ( mMediaPanels.size() == 1 )
+ return;
+
+ // sanity check - don't think this can happen but see above for a case where it might...
+ if ( ! panel )
+ return;
+
+ std::cout << "Removing media panel with index " << panel->mId << " - total panels = " << mMediaPanels.size() - 1 << std::endl;
+
+ if(mSelectedPanel == panel)
+ mSelectedPanel = NULL;
+
+ delete panel;
+
+ // remove from storage list
+ for( int i = 0; i < (int)mMediaPanels.size(); ++i )
+ {
+ if ( mMediaPanels[ i ] == panel )
+ {
+ mMediaPanels.erase( mMediaPanels.begin() + i );
+ break;
+ };
+ };
+
+ // select the first panel
+ selectPanel( mMediaPanels[ 0 ] );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::updateStatusBar()
+{
+ if ( ! mSelectedPanel )
+ return;
+
+ // cache results - this is a very slow function
+ static int cached_id = -1;
+ static int cached_media_width = -1;
+ static int cached_media_height = -1;
+ static int cached_texture_width = -1;
+ static int cached_texture_height = -1;
+ static bool cached_supports_browser_media = true;
+ static bool cached_supports_time_media = false;
+ static int cached_movie_time = -1;
+
+ static std::string cached_plugin_version = "";
+ if (
+ cached_id == mSelectedPanel->mId &&
+ cached_media_width == mSelectedPanel->mMediaWidth &&
+ cached_media_height == mSelectedPanel->mMediaHeight &&
+ cached_texture_width == mSelectedPanel->mTextureWidth &&
+ cached_texture_height == mSelectedPanel->mTextureHeight &&
+ cached_supports_browser_media == mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser() &&
+ cached_supports_time_media == mSelectedPanel->mMediaSource->pluginSupportsMediaTime() &&
+ cached_plugin_version == mSelectedPanel->mMediaSource->getPluginVersion() &&
+ cached_movie_time == (int)mSelectedPanel->mMediaSource->getCurrentTime()
+ )
+ {
+ // nothing changed so don't spend time in this shitty function
+ return;
+ };
+
+ std::ostringstream stream( "" );
+
+ stream.str( "" );
+ stream.clear();
+
+ stream << "Id: ";
+ stream << std::setw( 2 ) << std::setfill( '0' );
+ stream << mSelectedPanel->mId;
+ stream << " | ";
+ stream << "Media: ";
+ stream << std::setw( 3 ) << std::setfill( '0' );
+ stream << mSelectedPanel->mMediaWidth;
+ stream << " x ";
+ stream << std::setw( 3 ) << std::setfill( '0' );
+ stream << mSelectedPanel->mMediaHeight;
+ stream << " | ";
+ stream << "Texture: ";
+ stream << std::setw( 4 ) << std::setfill( '0' );
+ stream << mSelectedPanel->mTextureWidth;
+ stream << " x ";
+ stream << std::setw( 4 ) << std::setfill( '0' );
+ stream << mSelectedPanel->mTextureHeight;
+ stream << " | ";
+ if ( mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser() )
+ stream << "BROWSER";
+ else
+ if ( mSelectedPanel->mMediaSource->pluginSupportsMediaTime() )
+ stream << "TIME ";
+ stream << " | ";
+ stream << mSelectedPanel->mMediaSource->getPluginVersion();
+ stream << " | ";
+ if ( mSelectedPanel->mMediaSource->pluginSupportsMediaTime() )
+ {
+ stream << std::setw( 3 ) << std::setfill( '0' );
+ stream << (int)mSelectedPanel->mMediaSource->getCurrentTime();
+ stream << " / ";
+ stream << std::setw( 3 ) << std::setfill( '0' );
+ stream << (int)mSelectedPanel->mMediaSource->getDuration();
+ stream << " @ ";
+ stream << (int)mSelectedPanel->mMediaSource->getCurrentPlayRate();
+ stream << " | ";
+ };
+
+ glutSetWindow( mBottomGLUIWindow->get_glut_window_id() );
+ mStatusText->set_text( const_cast< char*>( stream.str().c_str() ) );
+ glutSetWindow( mAppWindow );
+
+ // caching
+ cached_id = mSelectedPanel->mId;
+ cached_media_width = mSelectedPanel->mMediaWidth;
+ cached_media_height = mSelectedPanel->mMediaHeight;
+ cached_texture_width = mSelectedPanel->mTextureWidth;
+ cached_texture_height = mSelectedPanel->mTextureHeight;
+ cached_supports_browser_media = mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser();
+ cached_supports_time_media = mSelectedPanel->mMediaSource->pluginSupportsMediaTime();
+ cached_plugin_version = mSelectedPanel->mMediaSource->getPluginVersion();
+ cached_movie_time = (int)mSelectedPanel->mMediaSource->getCurrentTime();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::dumpPanelInfo()
+{
+ std::cout << std::endl << "===== Media Panels =====" << std::endl;
+ for( int i = 0; i < (int)mMediaPanels.size(); ++i )
+ {
+ std::cout << std::setw( 2 ) << std::setfill( '0' );
+ std::cout << i + 1 << "> ";
+ std::cout << "Id: ";
+ std::cout << std::setw( 2 ) << std::setfill( '0' );
+ std::cout << mMediaPanels[ i ]->mId;
+ std::cout << " | ";
+ std::cout << "Media: ";
+ std::cout << std::setw( 3 ) << std::setfill( '0' );
+ std::cout << mMediaPanels[ i ]->mMediaWidth;
+ std::cout << " x ";
+ std::cout << std::setw( 3 ) << std::setfill( '0' );
+ std::cout << mMediaPanels[ i ]->mMediaHeight;
+ std::cout << " | ";
+ std::cout << "Texture: ";
+ std::cout << std::setw( 4 ) << std::setfill( '0' );
+ std::cout << mMediaPanels[ i ]->mTextureWidth;
+ std::cout << " x ";
+ std::cout << std::setw( 4 ) << std::setfill( '0' );
+ std::cout << mMediaPanels[ i ]->mTextureHeight;
+ std::cout << " | ";
+ if ( mMediaPanels[ i ] == mSelectedPanel )
+ std::cout << "(selected)";
+
+ std::cout << std::endl;
+ };
+ std::cout << "========================" << std::endl;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLMediaPluginTest::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
+{
+ // Uncomment this to make things much, much quieter.
+// return;
+
+ switch(event)
+ {
+ case MEDIA_EVENT_CONTENT_UPDATED:
+ // too spammy -- don't log these
+// std::cerr << "Media event: MEDIA_EVENT_CONTENT_UPDATED " << std::endl;
+ break;
+
+ case MEDIA_EVENT_TIME_DURATION_UPDATED:
+ // too spammy -- don't log these
+// std::cerr << "Media event: MEDIA_EVENT_TIME_DURATION_UPDATED, time is " << self->getCurrentTime() << " of " << self->getDuration() << std::endl;
+ break;
+
+ case MEDIA_EVENT_SIZE_CHANGED:
+ std::cerr << "Media event: MEDIA_EVENT_SIZE_CHANGED " << std::endl;
+ break;
+
+ case MEDIA_EVENT_CURSOR_CHANGED:
+ std::cerr << "Media event: MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << std::endl;
+ break;
+
+ case MEDIA_EVENT_NAVIGATE_BEGIN:
+ std::cerr << "Media event: MEDIA_EVENT_NAVIGATE_BEGIN " << std::endl;
+ break;
+
+ case MEDIA_EVENT_NAVIGATE_COMPLETE:
+ std::cerr << "Media event: MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << std::endl;
+ break;
+
+ case MEDIA_EVENT_PROGRESS_UPDATED:
+ std::cerr << "Media event: MEDIA_EVENT_PROGRESS_UPDATED, loading at " << self->getProgressPercent() << "%" << std::endl;
+ break;
+
+ case MEDIA_EVENT_STATUS_TEXT_CHANGED:
+ std::cerr << "Media event: MEDIA_EVENT_STATUS_TEXT_CHANGED, new status text is: " << self->getStatusText() << std::endl;
+ break;
+
+ case MEDIA_EVENT_NAME_CHANGED:
+ std::cerr << "Media event: MEDIA_EVENT_NAME_CHANGED, new name is: " << self->getMediaName() << std::endl;
+ glutSetWindowTitle( self->getMediaName().c_str() );
+ break;
+
+ case MEDIA_EVENT_LOCATION_CHANGED:
+ {
+ std::cerr << "Media event: MEDIA_EVENT_LOCATION_CHANGED, new uri is: " << self->getLocation() << std::endl;
+ mediaPanel* panel = findMediaPanel(self);
+ if(panel != NULL)
+ {
+ panel->mStartUrl = self->getLocation();
+ if(panel == mSelectedPanel)
+ {
+ mUrlEdit->set_text(const_cast<char*>(panel->mStartUrl.c_str()) );
+ }
+ }
+ }
+ break;
+
+ case MEDIA_EVENT_CLICK_LINK_HREF:
+ std::cerr << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, uri is " << self->getClickURL() << std::endl;
+ break;
+
+ case MEDIA_EVENT_CLICK_LINK_NOFOLLOW:
+ std::cerr << "Media event: MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is " << self->getClickURL() << std::endl;
+ break;
+
+ case MEDIA_EVENT_PLUGIN_FAILED:
+ std::cerr << "Media event: MEDIA_EVENT_PLUGIN_FAILED" << std::endl;
+ break;
+
+ case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
+ std::cerr << "Media event: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << std::endl;
+ break;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+static void gluiCallbackWrapper( int control_id )
+{
+ if ( gApplication )
+ gApplication->gluiCallback( control_id );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void glutReshape( int width, int height )
+{
+ if ( gApplication )
+ gApplication->reshape( width, height );
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void glutDisplay()
+{
+ if ( gApplication )
+ gApplication->display();
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void glutIdle(int update_ms)
+{
+ GLUI_Master.set_glutTimerFunc( update_ms, glutIdle, update_ms);
+
+ if ( gApplication )
+ gApplication->idle();
+
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void glutKeyboard( unsigned char key, int x, int y )
+{
+ if ( gApplication )
+ gApplication->keyboard( key );
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void glutMousePassive( int x, int y )
+{
+ if ( gApplication )
+ gApplication->mousePassive( x, y );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void glutMouseMove( int x , int y )
+{
+ if ( gApplication )
+ gApplication->mouseMove( x, y );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void glutMouseButton( int button, int state, int x, int y )
+{
+ if ( gApplication )
+ gApplication->mouseButton( button, state, x, y );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+int main( int argc, char* argv[] )
+{
+#if LL_DARWIN
+ // Set the current working directory to <application bundle>/Contents/Resources/
+ CFURLRef resources_url = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
+ if(resources_url != NULL)
+ {
+ CFStringRef resources_string = CFURLCopyFileSystemPath(resources_url, kCFURLPOSIXPathStyle);
+ CFRelease(resources_url);
+ if(resources_string != NULL)
+ {
+ char buffer[PATH_MAX] = "";
+ if(CFStringGetCString(resources_string, buffer, sizeof(buffer), kCFStringEncodingUTF8))
+ {
+ chdir(buffer);
+ }
+ CFRelease(resources_string);
+ }
+ }
+#endif
+
+ glutInit( &argc, argv );
+ glutInitDisplayMode( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB );
+
+ const int app_window_x = 80;
+ const int app_window_y = 0;
+ const int app_window_width = 960;
+ const int app_window_height = 960;
+
+ glutInitWindowPosition( app_window_x, app_window_y );
+ glutInitWindowSize( app_window_width, app_window_height );
+
+ int app_window_handle = glutCreateWindow( "LLMediaPluginTest" );
+
+ glutDisplayFunc( glutDisplay );
+
+ GLUI_Master.set_glutReshapeFunc( glutReshape );
+ GLUI_Master.set_glutKeyboardFunc( glutKeyboard );
+ GLUI_Master.set_glutMouseFunc( glutMouseButton );
+
+ glutPassiveMotionFunc( glutMousePassive );
+ glutMotionFunc( glutMouseMove );
+
+ glutSetWindow( app_window_handle );
+
+ gApplication = new LLMediaPluginTest( app_window_handle, app_window_width, app_window_height );
+
+ // update at approximately 60hz
+ int update_ms = 1000 / 60;
+
+ GLUI_Master.set_glutTimerFunc( update_ms, glutIdle, update_ms);
+
+ glutMainLoop();
+
+ delete gApplication;
+}
diff --git a/indra/test_apps/llplugintest/llmediaplugintest.h b/indra/test_apps/llplugintest/llmediaplugintest.h
new file mode 100644
index 0000000000..c2b2baba95
--- /dev/null
+++ b/indra/test_apps/llplugintest/llmediaplugintest.h
@@ -0,0 +1,201 @@
+/**
+ * @file LLMediaPluginTest.cpp
+ * @brief Primary test application for LLMedia (Separate Process) Plugin system
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_MEDIA_PLUGIN_TEST_H
+#define LL_MEDIA_PLUGIN_TEST_H
+
+#include <vector>
+#include <string>
+#include "llpluginclassmedia.h"
+#include "llgl.h"
+
+// Forward declarations
+class GLUI_Rotation;
+class GLUI_Translation;
+class GLUI_Listbox;
+class GLUI_EditText;
+class GLUI_StaticText;
+class GLUI;
+class GLUI_Button;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+struct mediaPanel
+{
+ public:
+ mediaPanel();
+ ~mediaPanel();
+ int mId;
+ std::string mStartUrl;
+ std::string mMimeType;
+ LLPluginClassMedia *mMediaSource;
+ int mMediaWidth;
+ int mMediaHeight;
+ int mTextureWidth;
+ int mTextureHeight;
+ double mTextureScaleX;
+ double mTextureScaleY;
+ GLuint mMediaTextureHandle;
+ GLuint mPickTextureHandle;
+ unsigned char* mPickTexturePixels;
+ bool mAppTextureCoordsOpenGL;
+ bool mReadyToRender;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+class LLMediaPluginTest : public LLPluginClassMediaOwner
+{
+ public:
+ LLMediaPluginTest( int app_window, int window_width, int window_height );
+ ~LLMediaPluginTest();
+
+ void reshape( int width, int height );
+ void display();
+ void idle();
+ void gluiCallback( int control_id );
+ void keyboard( int key );
+ void mousePassive( int x, int y );
+ void mouseButton( int button, int state, int x, int y );
+ void mouseMove( int x, int y );
+
+ void bindTexture(GLuint texture, GLint row_length = 0, GLint alignment = 1);
+ bool checkGLError(const char *name = "OpenGL");
+ void drawGeometry( int panel );
+ void startPanelHighlight( float red, float green, float blue, float line_width );
+ void endPanelHighlight();
+ enum { DrawTypePickTexture, DrawTypeMediaTexture };
+ void draw( int draw_type );
+ void windowPosToTexturePos( int window_x, int window_y, int& media_x, int& media_y, int& id );
+
+ void addMediaPanel( std::string url );
+ void updateMediaPanel( mediaPanel* panel );
+ void remMediaPanel( mediaPanel* panel );
+ void replaceMediaPanel( mediaPanel* panel, std::string url );
+ void getRandomMediaSize( int& width, int& height, std::string mime_type );
+ void navigateToNewURI( std::string uri );
+ void initUrlHistory( std::string uri );
+ void selectPanelById( int id );
+ void selectPanel( mediaPanel* panel );
+ mediaPanel* findMediaPanel( LLPluginClassMedia* panel );
+ void makePickTexture( int id, GLuint* texture_handle, unsigned char** texture_pixels );
+ void makeChrome();
+ void resetView();
+
+ void dumpPanelInfo();
+ void updateStatusBar();
+
+ // Inherited from LLPluginClassMediaOwner
+ /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent);
+
+ private:
+ const int mVersionMajor;
+ const int mVersionMinor;
+ const int mVersionPatch;
+ const int mMaxPanels;
+ int mAppWindow;
+ int mWindowWidth;
+ int mWindowHeight;
+ int mCurMouseX;
+ int mCurMouseY;
+ unsigned char mPixelReadColor[ 3 ];
+ bool mFuzzyMedia;
+ const std::string mHomeWebUrl;
+
+ std::vector< mediaPanel* > mMediaPanels;
+ mediaPanel* mSelectedPanel;
+ std::string mimeTypeFromUrl( std::string& url );
+ std::string pluginNameFromMimeType( std::string& mime_type );
+
+ GLUI_Rotation* mViewRotationCtrl;
+ GLUI_Translation* mViewScaleCtrl;
+ GLUI_Translation* mViewTranslationCtrl;
+ float mViewportAspect;
+ float mViewPos[ 3 ];
+ float mViewRotation[ 16 ];
+
+ int mIdControlAddPanel;
+ int mIdControlRemPanel;
+
+ std::vector< std::pair< std::string, std::string > > mBookmarks;
+ GLUI_Listbox* mBookmarkList;
+ int mIdBookmarks;
+ int mIdUrlEdit;
+ GLUI_EditText* mUrlEdit;
+ int mIdUrlInitHistoryEdit;
+ GLUI_EditText* mUrlInitHistoryEdit;
+ int mSelBookmark;
+ int mIdRandomPanelCount;
+ int mRandomPanelCount;
+ int mIdRandomBookmarks;
+ int mRandomBookmarks;
+ int mIdDisableTimeout;
+ int mDisableTimeout;
+ int mIdControlCrashPlugin;
+ int mIdControlHangPlugin;
+ int mIdControlExitApp;
+
+ GLUI* mGluiMediaTimeControlWindow;
+ int mIdMediaTimeControlPlay;
+ int mIdMediaTimeControlLoop;
+ int mIdMediaTimeControlPause;
+ int mIdMediaTimeControlStop;
+ int mIdMediaTimeControlSeek;
+ int mIdMediaTimeControlVolume;
+ int mMediaTimeControlVolume;
+ int mIdMediaTimeControlSeekSeconds;
+ int mMediaTimeControlSeekSeconds;
+ int mIdMediaTimeControlRewind;
+ int mIdMediaTimeControlFastForward;
+
+ GLUI* mGluiMediaBrowserControlWindow;
+ int mIdMediaBrowserControlBack;
+ GLUI_Button* mMediaBrowserControlBackButton;
+ int mIdMediaBrowserControlStop;
+ int mIdMediaBrowserControlForward;
+ GLUI_Button* mMediaBrowserControlForwardButton;
+ bool mGluiMediaTimeControlWindowFlag;
+ bool mGluiMediaBrowserControlWindowFlag;
+ bool mMediaBrowserControlBackButtonFlag;
+ bool mMediaBrowserControlForwardButtonFlag;
+ int mIdMediaBrowserControlHome;
+ int mIdMediaBrowserControlReload;
+ int mIdMediaBrowserControlClearCache;
+ int mIdMediaBrowserControlClearCookies;
+ int mIdMediaBrowserControlEnableCookies;
+ int mMediaBrowserControlEnableCookies;
+
+ GLUI* mBottomGLUIWindow;
+ GLUI_StaticText* mStatusText;
+};
+
+#endif // LL_MEDIA_PLUGIN_TEST_H
+
diff --git a/indra/viewer_components/CMakeLists.txt b/indra/viewer_components/CMakeLists.txt
new file mode 100644
index 0000000000..c95c854b7c
--- /dev/null
+++ b/indra/viewer_components/CMakeLists.txt
@@ -0,0 +1,5 @@
+# -*- cmake -*-
+
+add_subdirectory(login)
+add_subdirectory(eventhost)
+
diff --git a/indra/viewer_components/login/CMakeLists.txt b/indra/viewer_components/login/CMakeLists.txt
new file mode 100644
index 0000000000..fb65779eb7
--- /dev/null
+++ b/indra/viewer_components/login/CMakeLists.txt
@@ -0,0 +1,56 @@
+# -*- cmake -*-
+
+project(login)
+
+include(00-Common)
+include(LLAddBuildTest)
+include(LLCommon)
+include(LLMath)
+include(LLXML)
+include(Pth)
+
+include_directories(
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LLMATH_INCLUDE_DIRS}
+ ${LLXML_INCLUDE_DIRS}
+ ${PTH_INCLUDE_DIRS}
+ )
+
+set(login_SOURCE_FILES
+ lllogin.cpp
+ )
+
+set(login_HEADER_FILES
+ lllogin.h
+ )
+
+set_source_files_properties(${login_HEADER_FILES}
+ PROPERTIES HEADER_FILE_ONLY TRUE)
+
+list(APPEND
+ login_SOURCE_FILES
+ ${login_HEADER_FILES}
+ )
+
+add_library(lllogin
+ ${login_SOURCE_FILES}
+ )
+
+target_link_libraries(lllogin
+ ${LLCOMMON_LIBRARIES}
+ ${LLMATH_LIBRARIES}
+ ${LLXML_LIBRARIES}
+ ${PTH_LIBRARIES}
+ )
+
+SET(lllogin_TEST_SOURCE_FILES
+ lllogin.cpp
+ )
+
+set_source_files_properties(
+ lllogin.cpp
+ PROPERTIES
+ LL_TEST_ADDITIONAL_LIBRARIES "${PTH_LIBRARIES}"
+ )
+
+LL_ADD_PROJECT_UNIT_TESTS(lllogin "${lllogin_TEST_SOURCE_FILES}")
diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp
new file mode 100644
index 0000000000..b9f61ca7e1
--- /dev/null
+++ b/indra/viewer_components/login/lllogin.cpp
@@ -0,0 +1,423 @@
+/**
+ * @file lllogin.cpp
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include <boost/coroutine/coroutine.hpp>
+#include "linden_common.h"
+#include "llsd.h"
+#include "llsdutil.h"
+
+/*==========================================================================*|
+#ifdef LL_WINDOWS
+ // non-virtual destructor warning, boost::statechart does this intentionally.
+ #pragma warning (disable : 4265)
+#endif
+|*==========================================================================*/
+
+#include "lllogin.h"
+
+#include <boost/bind.hpp>
+
+#include "llcoros.h"
+#include "llevents.h"
+#include "lleventfilter.h"
+#include "lleventcoro.h"
+
+//*********************
+// LLLogin
+// *NOTE:Mani - Is this Impl needed now that the state machine runs the show?
+class LLLogin::Impl
+{
+public:
+ Impl():
+ mPump("login", true) // Create the module's event pump with a tweaked (unique) name.
+ {
+ mValidAuthResponse["status"] = LLSD();
+ mValidAuthResponse["errorcode"] = LLSD();
+ mValidAuthResponse["error"] = LLSD();
+ mValidAuthResponse["transfer_rate"] = LLSD();
+ }
+
+ void connect(const std::string& uri, const LLSD& credentials);
+ void disconnect();
+ LLEventPump& getEventPump() { return mPump; }
+
+private:
+ LLSD getProgressEventLLSD(const std::string& state, const std::string& change,
+ const LLSD& data = LLSD())
+ {
+ LLSD status_data;
+ status_data["state"] = state;
+ status_data["change"] = change;
+ status_data["progress"] = 0.0f;
+
+ if(mAuthResponse.has("transfer_rate"))
+ {
+ status_data["transfer_rate"] = mAuthResponse["transfer_rate"];
+ }
+
+ if(data.isDefined())
+ {
+ status_data["data"] = data;
+ }
+ return status_data;
+ }
+
+ void sendProgressEvent(const std::string& state, const std::string& change,
+ const LLSD& data = LLSD())
+ {
+ LLSD status_data = getProgressEventLLSD(state, change, data);
+ mPump.post(status_data);
+ }
+
+ LLSD validateResponse(const std::string& pumpName, const LLSD& response)
+ {
+ // Validate the response. If we don't recognize it, things
+ // could get ugly.
+ std::string mismatch(llsd_matches(mValidAuthResponse, response));
+ if (! mismatch.empty())
+ {
+ LL_ERRS("LLLogin") << "Received unrecognized event (" << mismatch << ") on "
+ << pumpName << "pump: " << response
+ << LL_ENDL;
+ return LLSD();
+ }
+
+ return response;
+ }
+
+ // In a coroutine's top-level function args, do NOT NOT NOT accept
+ // references (const or otherwise) to anything but the self argument! Pass
+ // by value only!
+ void login_(LLCoros::self& self, std::string uri, LLSD credentials);
+
+ LLEventStream mPump;
+ LLSD mAuthResponse, mValidAuthResponse;
+};
+
+void LLLogin::Impl::connect(const std::string& uri, const LLSD& credentials)
+{
+ // Launch a coroutine with our login_() method. Run the coroutine until
+ // its first wait; at that point, return here.
+ std::string coroname =
+ LLCoros::instance().launch("LLLogin::Impl::login_",
+ boost::bind(&Impl::login_, this, _1, uri, credentials));
+}
+
+void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credentials)
+{
+ LLSD printable_credentials = credentials;
+ if(printable_credentials.has("params")
+ && printable_credentials["params"].has("passwd"))
+ {
+ printable_credentials["params"]["passwd"] = "*******";
+ }
+ LL_DEBUGS("LLLogin") << "Entering coroutine " << LLCoros::instance().getName(self)
+ << " with uri '" << uri << "', credentials " << printable_credentials << LL_ENDL;
+
+ // Arriving in SRVRequest state
+ LLEventStream replyPump("SRVreply", true);
+ // Should be an array of one or more uri strings.
+ LLSD rewrittenURIs;
+ {
+ LLEventTimeout filter(replyPump);
+ sendProgressEvent("offline", "srvrequest");
+
+ // Request SRV record.
+ LL_DEBUGS("LLLogin") << "Requesting SRV record from " << uri << LL_ENDL;
+
+ // *NOTE:Mani - Completely arbitrary default timeout value for SRV request.
+ F32 seconds_to_timeout = 5.0f;
+ if(credentials.has("cfg_srv_timeout"))
+ {
+ seconds_to_timeout = credentials["cfg_srv_timeout"].asReal();
+ }
+
+ // If the SRV request times out (e.g. EXT-3934), simulate response: an
+ // array containing our original URI.
+ LLSD fakeResponse(LLSD::emptyArray());
+ fakeResponse.append(uri);
+ filter.eventAfter(seconds_to_timeout, fakeResponse);
+
+ std::string srv_pump_name = "LLAres";
+ if(credentials.has("cfg_srv_pump"))
+ {
+ srv_pump_name = credentials["cfg_srv_pump"].asString();
+ }
+
+ // Make request
+ LLSD request;
+ request["op"] = "rewriteURI";
+ request["uri"] = uri;
+ request["reply"] = replyPump.getName();
+ rewrittenURIs = postAndWait(self, request, srv_pump_name, filter);
+ } // we no longer need the filter
+
+ LLEventPump& xmlrpcPump(LLEventPumps::instance().obtain("LLXMLRPCTransaction"));
+ // EXT-4193: use a DIFFERENT reply pump than for the SRV request. We used
+ // to share them -- but the EXT-3934 fix made it possible for an abandoned
+ // SRV response to arrive just as we were expecting the XMLRPC response.
+ LLEventStream loginReplyPump("loginreply", true);
+
+ // Loop through the rewrittenURIs, counting attempts along the way.
+ // Because of possible redirect responses, we may make more than one
+ // attempt per rewrittenURIs entry.
+ LLSD::Integer attempts = 0;
+ for (LLSD::array_const_iterator urit(rewrittenURIs.beginArray()),
+ urend(rewrittenURIs.endArray());
+ urit != urend; ++urit)
+ {
+ LLSD request(credentials);
+ request["reply"] = loginReplyPump.getName();
+ request["uri"] = *urit;
+ std::string status;
+
+ // Loop back to here if login attempt redirects to a different
+ // request["uri"]
+ for (;;)
+ {
+ ++attempts;
+ LLSD progress_data;
+ progress_data["attempt"] = attempts;
+ progress_data["request"] = request;
+ if(progress_data["request"].has("params")
+ && progress_data["request"]["params"].has("passwd"))
+ {
+ progress_data["request"]["params"]["passwd"] = "*******";
+ }
+ sendProgressEvent("offline", "authenticating", progress_data);
+
+ // We expect zero or more "Downloading" status events, followed by
+ // exactly one event with some other status. Use postAndWait() the
+ // first time, because -- at least in unit-test land -- it's
+ // possible for the reply to arrive before the post() call
+ // returns. Subsequent responses, of course, must be awaited
+ // without posting again.
+ for (mAuthResponse = validateResponse(loginReplyPump.getName(),
+ postAndWait(self, request, xmlrpcPump, loginReplyPump, "reply"));
+ mAuthResponse["status"].asString() == "Downloading";
+ mAuthResponse = validateResponse(loginReplyPump.getName(),
+ waitForEventOn(self, loginReplyPump)))
+ {
+ // Still Downloading -- send progress update.
+ sendProgressEvent("offline", "downloading");
+ }
+
+ LL_DEBUGS("LLLogin") << "Auth Response: " << mAuthResponse << LL_ENDL;
+ status = mAuthResponse["status"].asString();
+
+ // Okay, we've received our final status event for this
+ // request. Unless we got a redirect response, break the retry
+ // loop for the current rewrittenURIs entry.
+ if (!(status == "Complete" &&
+ mAuthResponse["responses"]["login"].asString() == "indeterminate"))
+ {
+ break;
+ }
+
+ sendProgressEvent("offline", "indeterminate", mAuthResponse["responses"]);
+
+ // Here the login service at the current URI is redirecting us
+ // to some other URI ("indeterminate" -- why not "redirect"?).
+ // The response should contain another uri to try, with its
+ // own auth method.
+ request["uri"] = mAuthResponse["responses"]["next_url"].asString();
+ request["method"] = mAuthResponse["responses"]["next_method"].asString();
+ } // loop back to try the redirected URI
+
+ // Here we're done with redirects for the current rewrittenURIs
+ // entry.
+ if (status == "Complete")
+ {
+ // StatusComplete does not imply auth success. Check the
+ // actual outcome of the request. We've already handled the
+ // "indeterminate" case in the loop above.
+ if (mAuthResponse["responses"]["login"].asString() == "true")
+ {
+ sendProgressEvent("online", "connect", mAuthResponse["responses"]);
+ }
+ else
+ {
+ sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]);
+ }
+ return; // Done!
+ }
+ // If we don't recognize status at all, trouble
+ if (! (status == "CURLError"
+ || status == "XMLRPCError"
+ || status == "OtherError"))
+ {
+ LL_ERRS("LLLogin") << "Unexpected status from " << xmlrpcPump.getName() << " pump: "
+ << mAuthResponse << LL_ENDL;
+ return;
+ }
+
+ // Here status IS one of the errors tested above.
+ } // Retry if there are any more rewrittenURIs.
+
+ // Here we got through all the rewrittenURIs without succeeding. Tell
+ // caller this didn't work out so well. Of course, the only failure data
+ // we can reasonably show are from the last of the rewrittenURIs.
+
+ // *NOTE: The response from LLXMLRPCListener's Poller::poll method returns an
+ // llsd with no "responses" node. To make the output from an incomplete login symmetrical
+ // to success, add a data/message and data/reason fields.
+ LLSD error_response;
+ error_response["reason"] = mAuthResponse["status"];
+ error_response["message"] = mAuthResponse["error"];
+ sendProgressEvent("offline", "fail.login", error_response);
+}
+
+void LLLogin::Impl::disconnect()
+{
+ sendProgressEvent("offline", "disconnect");
+}
+
+//*********************
+// LLLogin
+LLLogin::LLLogin() :
+ mImpl(new LLLogin::Impl())
+{
+}
+
+LLLogin::~LLLogin()
+{
+}
+
+void LLLogin::connect(const std::string& uri, const LLSD& credentials)
+{
+ mImpl->connect(uri, credentials);
+}
+
+
+void LLLogin::disconnect()
+{
+ mImpl->disconnect();
+}
+
+LLEventPump& LLLogin::getEventPump()
+{
+ return mImpl->getEventPump();
+}
+
+// The following is the list of important functions that happen in the
+// current login process that we want to move to this login module.
+
+// The list associates to event with the original idle_startup() 'STATE'.
+
+// Rewrite URIs
+ // State_LOGIN_AUTH_INIT
+// Given a vector of login uris (usually just one), perform a dns lookup for the
+// SRV record from each URI. I think this is used to distribute login requests to
+// a single URI to multiple hosts.
+// This is currently a synchronous action. (See LLSRV::rewriteURI() implementation)
+// On dns lookup error the output uris == the input uris.
+//
+// Input: A vector of login uris
+// Output: A vector of login uris
+//
+// Code:
+// std::vector<std::string> uris;
+// LLViewerLogin::getInstance()->getLoginURIs(uris);
+// std::vector<std::string>::const_iterator iter, end;
+// for (iter = uris.begin(), end = uris.end(); iter != end; ++iter)
+// {
+// std::vector<std::string> rewritten;
+// rewritten = LLSRV::rewriteURI(*iter);
+// sAuthUris.insert(sAuthUris.end(),
+// rewritten.begin(), rewritten.end());
+// }
+// sAuthUriNum = 0;
+
+// Authenticate
+// STATE_LOGIN_AUTHENTICATE
+// Connect to the login server, presumably login.cgi, requesting the login
+// and a slew of related initial connection information.
+// This is an asynch action. The final response, whether success or error
+// is handled by STATE_LOGIN_PROCESS_REPONSE.
+// There is no immediate error or output from this call.
+//
+// Input:
+// URI
+// Credentials (first, last, password)
+// Start location
+// Bool Flags:
+// skip optional update
+// accept terms of service
+// accept critical message
+// Last exec event. (crash state of previous session)
+// requested optional data (inventory skel, initial outfit, etc.)
+// local mac address
+// viewer serial no. (md5 checksum?)
+
+//sAuthUriNum = llclamp(sAuthUriNum, 0, (S32)sAuthUris.size()-1);
+//LLUserAuth::getInstance()->authenticate(
+// sAuthUris[sAuthUriNum],
+// auth_method,
+// firstname,
+// lastname,
+// password, // web_login_key,
+// start.str(),
+// gSkipOptionalUpdate,
+// gAcceptTOS,
+// gAcceptCriticalMessage,
+// gLastExecEvent,
+// requested_options,
+// hashed_mac_string,
+// LLAppViewer::instance()->getSerialNumber());
+
+//
+// Download the Response
+// STATE_LOGIN_NO_REPONSE_YET and STATE_LOGIN_DOWNLOADING
+// I had assumed that this was default behavior of the message system. However...
+// During login, the message system is checked only by these two states in idle_startup().
+// I guess this avoids the overhead of checking network messages for those login states
+// that don't need to do so, but geez!
+// There are two states to do this one function just to update the login
+// status text from 'Logging In...' to 'Downloading...'
+//
+
+//
+// Handle Login Response
+// STATE_LOGIN_PROCESS_RESPONSE
+//
+// This state handle the result of the request to login. There is a metric ton of
+// code in this case. This state will transition to:
+// STATE_WORLD_INIT, on success.
+// STATE_AUTHENTICATE, on failure.
+// STATE_UPDATE_CHECK, to handle user during login interaction like TOS display.
+//
+// Much of the code in this case belongs on the viewer side of the fence and not in login.
+// Login should probably return with a couple of events, success and failure.
+// Failure conditions can be specified in the events data pacet to allow the viewer
+// to re-engauge login as is appropriate. (Or should there be multiple failure messages?)
+// Success is returned with the data requested from the login. According to OGP specs
+// there may be intermediate steps before reaching this result in future login
+// implementations.
diff --git a/indra/viewer_components/login/lllogin.h b/indra/viewer_components/login/lllogin.h
new file mode 100644
index 0000000000..0598b4e457
--- /dev/null
+++ b/indra/viewer_components/login/lllogin.h
@@ -0,0 +1,133 @@
+/**
+ * @file lllogin.h
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLLOGIN_H
+#define LL_LLLOGIN_H
+
+#include <boost/scoped_ptr.hpp>
+
+class LLSD;
+class LLEventPump;
+
+/**
+ * @class LLLogin
+ * @brief Class to encapsulate the action and state of grid login.
+ */
+class LLLogin
+{
+public:
+ LLLogin();
+ ~LLLogin();
+
+ /**
+ * Make a connection to a grid.
+ * @param uri The 'well known and published' authentication URL.
+ * @param credentials LLSD data that contians the credentials.
+ * *NOTE:Mani The credential data can vary depending upon the authentication
+ * method used. The current interface matches the values passed to
+ * the XMLRPC login request.
+ {
+ method : string,
+ first : string,
+ last : string,
+ passwd : string,
+ start : string,
+ skipoptional : bool,
+ agree_to_tos : bool,
+ read_critical : bool,
+ last_exec_event : int,
+ version : string,
+ channel : string,
+ mac : string,
+ id0 : string,
+ options : [ strings ]
+ }
+
+ */
+ void connect(const std::string& uri, const LLSD& credentials);
+
+ /**
+ * Disconnect from a the current connection.
+ */
+ void disconnect();
+
+ /**
+ * Retrieve the event pump from this login class.
+ */
+ LLEventPump& getEventPump();
+
+ /*
+ Event API
+
+ LLLogin will issue multiple events to it pump to indicate the
+ progression of states through login. The most important
+ states are "offline" and "online" which indicate auth failure
+ and auth success respectively.
+
+ pump: login (tweaked)
+ These are the events posted to the 'login'
+ event pump from the login module.
+ {
+ state : string, // See below for the list of states.
+ progress : real // for progress bar.
+ data : LLSD // Dependent upon state.
+ }
+
+ States for method 'login_to_simulator'
+ offline - set initially state and upon failure. data is the server response.
+ srvrequest - upon uri rewrite request. no data.
+ authenticating - upon auth request. data, 'attempt' number and 'request' llsd.
+ downloading - upon ack from auth server, before completion. no data
+ online - upon auth success. data is server response.
+
+
+ Dependencies:
+ pump: LLAres
+ LLLogin makes a request for a SRV record from the uri provided by the connect method.
+ The following event pump should exist to service that request.
+ pump name: LLAres
+ request = {
+ op : "rewriteURI"
+ uri : string
+ reply : string
+
+ pump: LLXMLRPCListener
+ The request merely passes the credentials LLSD along, with one additional
+ member, 'reply', which is the string name of the event pump to reply on.
+
+ */
+
+private:
+ class Impl;
+ boost::scoped_ptr<Impl> mImpl;
+};
+
+#endif // LL_LLLOGIN_H
diff --git a/indra/viewer_components/login/tests/lllogin_test.cpp b/indra/viewer_components/login/tests/lllogin_test.cpp
new file mode 100644
index 0000000000..51f5cd0692
--- /dev/null
+++ b/indra/viewer_components/login/tests/lllogin_test.cpp
@@ -0,0 +1,481 @@
+/**
+ * @file lllogin_test.cpp
+ * @author Mark Palange
+ * @date 2009-02-26
+ * @brief Tests of lllogin.cpp.
+ *
+ * $LicenseInfo:firstyear=2009&license=internal$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if LL_WINDOWS
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
+#endif
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "../lllogin.h"
+// STL headers
+// std headers
+#include <iostream>
+// external library headers
+// other Linden headers
+#include "llsd.h"
+#include "../../../test/lltut.h"
+//#define DEBUG_ON
+#include "../../../test/debug.h"
+#include "llevents.h"
+#include "stringize.h"
+
+#if LL_WINDOWS
+#define skipwin(arg) skip(arg)
+#define skipmac(arg)
+#define skiplinux(arg)
+#elif LL_DARWIN
+#define skipwin(arg)
+#define skipmac(arg) skip(arg)
+#define skiplinux(arg)
+#elif LL_LINUX
+#define skipwin(arg)
+#define skipmac(arg)
+#define skiplinux(arg) skip(arg)
+#endif
+
+/*****************************************************************************
+* Helper classes
+*****************************************************************************/
+// This is a listener to receive results from lllogin.
+class LoginListener: public LLEventTrackable
+{
+ std::string mName;
+ LLSD mLastEvent;
+ Debug mDebug;
+public:
+ LoginListener(const std::string& name) :
+ mName(name),
+ mDebug(stringize(*this))
+ {}
+
+ bool call(const LLSD& event)
+ {
+ mDebug(STRINGIZE("LoginListener called!: " << event));
+
+ mLastEvent = event;
+ return false;
+ }
+
+ LLBoundListener listenTo(LLEventPump& pump)
+ {
+ return pump.listen(mName, boost::bind(&LoginListener::call, this, _1));
+ }
+
+ LLSD lastEvent() const { return mLastEvent; }
+
+ friend std::ostream& operator<<(std::ostream& out, const LoginListener& listener)
+ {
+ return out << "LoginListener(" << listener.mName << ')';
+ }
+};
+
+class LLAresListener: public LLEventTrackable
+{
+ std::string mName;
+ LLSD mEvent;
+ bool mImmediateResponse;
+ bool mMultipleURIResponse;
+ Debug mDebug;
+
+public:
+ LLAresListener(const std::string& name,
+ bool i = false,
+ bool m = false
+ ) :
+ mName(name),
+ mImmediateResponse(i),
+ mMultipleURIResponse(m),
+ mDebug(stringize(*this))
+ {}
+
+ bool handle_event(const LLSD& event)
+ {
+ mDebug(STRINGIZE("LLAresListener called!: " << event));
+ mEvent = event;
+ if(mImmediateResponse)
+ {
+ sendReply();
+ }
+ return false;
+ }
+
+ void sendReply()
+ {
+ if(mEvent["op"].asString() == "rewriteURI")
+ {
+ LLSD result;
+ if(mMultipleURIResponse)
+ {
+ result.append(LLSD("login.foo.com"));
+ }
+ result.append(mEvent["uri"]);
+ LLEventPumps::instance().obtain(mEvent["reply"]).post(result);
+ }
+ }
+
+ LLBoundListener listenTo(LLEventPump& pump)
+ {
+ return pump.listen(mName, boost::bind(&LLAresListener::handle_event, this, _1));
+ }
+
+ friend std::ostream& operator<<(std::ostream& out, const LLAresListener& listener)
+ {
+ return out << "LLAresListener(" << listener.mName << ')';
+ }
+};
+
+class LLXMLRPCListener: public LLEventTrackable
+{
+ std::string mName;
+ LLSD mEvent;
+ bool mImmediateResponse;
+ LLSD mResponse;
+ Debug mDebug;
+
+public:
+ LLXMLRPCListener(const std::string& name,
+ bool i = false,
+ const LLSD& response = LLSD()
+ ) :
+ mName(name),
+ mImmediateResponse(i),
+ mResponse(response),
+ mDebug(stringize(*this))
+ {
+ if(mResponse.isUndefined())
+ {
+ mResponse["status"] = "Complete"; // StatusComplete
+ mResponse["errorcode"] = 0;
+ mResponse["error"] = "dummy response";
+ mResponse["transfer_rate"] = 0;
+ mResponse["responses"]["login"] = true;
+ }
+ }
+
+ void setResponse(const LLSD& r)
+ {
+ mResponse = r;
+ }
+
+ bool handle_event(const LLSD& event)
+ {
+ mDebug(STRINGIZE("LLXMLRPCListener called!: " << event));
+ mEvent = event;
+ if(mImmediateResponse)
+ {
+ sendReply();
+ }
+ return false;
+ }
+
+ void sendReply()
+ {
+ LLEventPumps::instance().obtain(mEvent["reply"]).post(mResponse);
+ }
+
+ LLBoundListener listenTo(LLEventPump& pump)
+ {
+ return pump.listen(mName, boost::bind(&LLXMLRPCListener::handle_event, this, _1));
+ }
+
+ friend std::ostream& operator<<(std::ostream& out, const LLXMLRPCListener& listener)
+ {
+ return out << "LLXMLRPCListener(" << listener.mName << ')';
+ }
+};
+
+/*****************************************************************************
+* TUT
+*****************************************************************************/
+namespace tut
+{
+ struct llviewerlogin_data
+ {
+ llviewerlogin_data() :
+ pumps(LLEventPumps::instance())
+ {}
+ LLEventPumps& pumps;
+ };
+
+ typedef test_group<llviewerlogin_data> llviewerlogin_group;
+ typedef llviewerlogin_group::object llviewerlogin_object;
+ llviewerlogin_group llviewerlogingrp("llviewerlogin");
+
+ template<> template<>
+ void llviewerlogin_object::test<1>()
+ {
+ DEBUG;
+ // Testing login with immediate responses from Ares and XMLPRC
+ // The response from both requests will come before the post request exits.
+ // This tests an edge case of the login state handling.
+ LLEventStream llaresPump("LLAres"); // Dummy LLAres pump.
+ LLEventStream xmlrpcPump("LLXMLRPCTransaction"); // Dummy XMLRPC pump
+
+ bool respond_immediately = true;
+ // Have 'dummy ares' respond immediately.
+ LLAresListener dummyLLAres("dummy_llares", respond_immediately);
+ dummyLLAres.listenTo(llaresPump);
+
+ // Have dummy XMLRPC respond immediately.
+ LLXMLRPCListener dummyXMLRPC("dummy_xmlrpc", respond_immediately);
+ dummyXMLRPC.listenTo(xmlrpcPump);
+
+ LLLogin login;
+
+ LoginListener listener("test_ear");
+ listener.listenTo(login.getEventPump());
+
+ LLSD credentials;
+ credentials["first"] = "foo";
+ credentials["last"] = "bar";
+ credentials["passwd"] = "secret";
+
+ login.connect("login.bar.com", credentials);
+
+ ensure_equals("Online state", listener.lastEvent()["state"].asString(), "online");
+ }
+
+ template<> template<>
+ void llviewerlogin_object::test<2>()
+ {
+ DEBUG;
+ // Tests a successful login in with delayed responses.
+ // Also includes 'failure' that cause the login module
+ // to re-attempt connection, once from a basic failure
+ // and once from the 'indeterminate' response.
+
+ set_test_name("LLLogin multiple srv uris w/ success");
+
+ // Testing normal login procedure.
+ LLEventStream llaresPump("LLAres"); // Dummy LLAres pump.
+ LLEventStream xmlrpcPump("LLXMLRPCTransaction"); // Dummy XMLRPC pump
+
+ bool respond_immediately = false;
+ bool multiple_addresses = true;
+ LLAresListener dummyLLAres("dummy_llares", respond_immediately, multiple_addresses);
+ dummyLLAres.listenTo(llaresPump);
+
+ LLXMLRPCListener dummyXMLRPC("dummy_xmlrpc");
+ dummyXMLRPC.listenTo(xmlrpcPump);
+
+ LLLogin login;
+
+ LoginListener listener("test_ear");
+ listener.listenTo(login.getEventPump());
+
+ LLSD credentials;
+ credentials["first"] = "foo";
+ credentials["last"] = "bar";
+ credentials["passwd"] = "secret";
+
+ login.connect("login.bar.com", credentials);
+
+ ensure_equals("SRV state", listener.lastEvent()["change"].asString(), "srvrequest");
+
+ dummyLLAres.sendReply();
+
+ // Test Authenticating State prior to first response.
+ ensure_equals("Auth state 1", listener.lastEvent()["change"].asString(), "authenticating");
+ ensure_equals("Attempt 1", listener.lastEvent()["data"]["attempt"].asInteger(), 1);
+ ensure_equals("URI 1", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.foo.com");
+
+ // First send emulated LLXMLRPCListener failure,
+ // this should return login to the authenticating step and increase the attempt
+ // count.
+ LLSD data;
+ data["status"] = "OtherError";
+ data["errorcode"] = 0;
+ data["error"] = "dummy response";
+ data["transfer_rate"] = 0;
+ dummyXMLRPC.setResponse(data);
+ dummyXMLRPC.sendReply();
+
+ ensure_equals("Fail back to authenticate 1", listener.lastEvent()["change"].asString(), "authenticating");
+ ensure_equals("Attempt 2", listener.lastEvent()["data"]["attempt"].asInteger(), 2);
+ ensure_equals("URI 2", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.bar.com");
+
+ // Now send the 'indeterminate' response.
+ data.clear();
+ data["status"] = "Complete"; // StatusComplete
+ data["errorcode"] = 0;
+ data["error"] = "dummy response";
+ data["transfer_rate"] = 0;
+ data["responses"]["login"] = "indeterminate";
+ data["responses"]["next_url"] = "login.indeterminate.com";
+ data["responses"]["next_method"] = "test_login_method";
+ dummyXMLRPC.setResponse(data);
+ dummyXMLRPC.sendReply();
+
+ ensure_equals("Fail back to authenticate 2", listener.lastEvent()["change"].asString(), "authenticating");
+ ensure_equals("Attempt 3", listener.lastEvent()["data"]["attempt"].asInteger(), 3);
+ ensure_equals("URI 3", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.indeterminate.com");
+ ensure_equals("Method 3", listener.lastEvent()["data"]["request"]["method"].asString(), "test_login_method");
+
+ // Finally let the auth succeed.
+ data.clear();
+ data["status"] = "Complete"; // StatusComplete
+ data["errorcode"] = 0;
+ data["error"] = "dummy response";
+ data["transfer_rate"] = 0;
+ data["responses"]["login"] = "true";
+ dummyXMLRPC.setResponse(data);
+ dummyXMLRPC.sendReply();
+
+ ensure_equals("Success state", listener.lastEvent()["state"].asString(), "online");
+
+ login.disconnect();
+
+ ensure_equals("Disconnected state", listener.lastEvent()["state"].asString(), "offline");
+ }
+
+ template<> template<>
+ void llviewerlogin_object::test<3>()
+ {
+ DEBUG;
+ // Test completed response, that fails to login.
+ set_test_name("LLLogin valid response, failure (eg. bad credentials)");
+
+ // Testing normal login procedure.
+ LLEventStream llaresPump("LLAres"); // Dummy LLAres pump.
+ LLEventStream xmlrpcPump("LLXMLRPCTransaction"); // Dummy XMLRPC pump
+
+ LLAresListener dummyLLAres("dummy_llares");
+ dummyLLAres.listenTo(llaresPump);
+
+ LLXMLRPCListener dummyXMLRPC("dummy_xmlrpc");
+ dummyXMLRPC.listenTo(xmlrpcPump);
+
+ LLLogin login;
+ LoginListener listener("test_ear");
+ listener.listenTo(login.getEventPump());
+
+ LLSD credentials;
+ credentials["first"] = "who";
+ credentials["last"] = "what";
+ credentials["passwd"] = "badpasswd";
+
+ login.connect("login.bar.com", credentials);
+
+ ensure_equals("SRV state", listener.lastEvent()["change"].asString(), "srvrequest");
+
+ dummyLLAres.sendReply();
+
+ ensure_equals("Auth state", listener.lastEvent()["change"].asString(), "authenticating");
+
+ // Send the failed auth request reponse
+ LLSD data;
+ data["status"] = "Complete";
+ data["errorcode"] = 0;
+ data["error"] = "dummy response";
+ data["transfer_rate"] = 0;
+ data["responses"]["login"] = "false";
+ dummyXMLRPC.setResponse(data);
+ dummyXMLRPC.sendReply();
+
+ ensure_equals("Failed to offline", listener.lastEvent()["state"].asString(), "offline");
+ }
+
+ template<> template<>
+ void llviewerlogin_object::test<4>()
+ {
+ DEBUG;
+ // Test incomplete response, that end the attempt.
+ set_test_name("LLLogin valid response, failure (eg. bad credentials)");
+
+ // Testing normal login procedure.
+ LLEventStream llaresPump("LLAres"); // Dummy LLAres pump.
+ LLEventStream xmlrpcPump("LLXMLRPCTransaction"); // Dummy XMLRPC pump
+
+ LLAresListener dummyLLAres("dummy_llares");
+ dummyLLAres.listenTo(llaresPump);
+
+ LLXMLRPCListener dummyXMLRPC("dummy_xmlrpc");
+ dummyXMLRPC.listenTo(xmlrpcPump);
+
+ LLLogin login;
+ LoginListener listener("test_ear");
+ listener.listenTo(login.getEventPump());
+
+ LLSD credentials;
+ credentials["first"] = "these";
+ credentials["last"] = "don't";
+ credentials["passwd"] = "matter";
+
+ login.connect("login.bar.com", credentials);
+
+ ensure_equals("SRV state", listener.lastEvent()["change"].asString(), "srvrequest");
+
+ dummyLLAres.sendReply();
+
+ ensure_equals("Auth state", listener.lastEvent()["change"].asString(), "authenticating");
+
+ // Send the failed auth request reponse
+ LLSD data;
+ data["status"] = "OtherError";
+ data["errorcode"] = 0;
+ data["error"] = "dummy response";
+ data["transfer_rate"] = 0;
+ dummyXMLRPC.setResponse(data);
+ dummyXMLRPC.sendReply();
+
+ ensure_equals("Failed to offline", listener.lastEvent()["state"].asString(), "offline");
+ }
+
+ template<> template<>
+ void llviewerlogin_object::test<5>()
+ {
+ DEBUG;
+ // Test SRV request timeout.
+ set_test_name("LLLogin SRV timeout testing");
+
+ // Testing normal login procedure.
+ LLEventStream llaresPump("LLAres"); // Dummy LLAres pump.
+
+ LLAresListener dummyLLAres("dummy_llares");
+ dummyLLAres.listenTo(llaresPump);
+
+ LLLogin login;
+ LoginListener listener("test_ear");
+ listener.listenTo(login.getEventPump());
+
+ LLSD credentials;
+ credentials["first"] = "these";
+ credentials["last"] = "don't";
+ credentials["passwd"] = "matter";
+ credentials["cfg_srv_timeout"] = 0.0f;
+
+ login.connect("login.bar.com", credentials);
+
+ ensure_equals("SRV State", listener.lastEvent()["change"].asString(), "srvrequest");
+
+ // Get the mainloop eventpump, which needs a pinging in order to drive the
+ // SRV timeout.
+ LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
+ LLSD frame_event;
+ mainloop.post(frame_event);
+
+ // In this state we have NOT sent a reply from LLAresListener -- in
+ // fact there's no such object. Nonetheless, we expect the timeout to
+ // have stepped the login module forward to try to authenticate with
+ // the original URI.
+ ensure_equals("Auth state", listener.lastEvent()["change"].asString(), "authenticating");
+ ensure_equals("Attempt", listener.lastEvent()["data"]["attempt"].asInteger(), 1);
+ ensure_equals("URI", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.bar.com");
+
+ // EXT-4193: if the SRV reply isn't lost but merely late, and if it
+ // arrives just at the moment we're expecting the XMLRPC reply, the
+ // original code got confused and crashed. Drive that case here. We
+ // observe that without the fix, this call DOES repro.
+ dummyLLAres.sendReply();
+ }
+}
diff --git a/indra/win_crash_logger/CMakeLists.txt b/indra/win_crash_logger/CMakeLists.txt
index 27022680b8..990dc6783e 100644
--- a/indra/win_crash_logger/CMakeLists.txt
+++ b/indra/win_crash_logger/CMakeLists.txt
@@ -11,6 +11,7 @@ include(LLVFS)
include(LLWindow)
include(LLXML)
include(Linking)
+include(LLSharedLibs)
include_directories(
${LLCOMMON_INCLUDE_DIRS}
@@ -72,6 +73,7 @@ target_link_libraries(windows-crash-logger
${LLCOMMON_LIBRARIES}
${WINDOWS_LIBRARIES}
${DXGUID_LIBRARY}
+ ${GOOGLE_PERFTOOLS_LIBRARIES}
user32
gdi32
ole32
@@ -86,3 +88,5 @@ if (WINDOWS)
LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\""
)
endif (WINDOWS)
+
+ll_deploy_sharedlibs_command(windows-crash-logger) \ No newline at end of file
diff --git a/indra/win_updater/CMakeLists.txt b/indra/win_updater/CMakeLists.txt
index dedb7cfcc7..82347adf20 100644
--- a/indra/win_updater/CMakeLists.txt
+++ b/indra/win_updater/CMakeLists.txt
@@ -33,3 +33,6 @@ set_target_properties(windows-updater
LINK_FLAGS "/NODEFAULTLIB:LIBCMT"
LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\""
)
+
+# The windows-updater doesn't link against anything non-system, apparently
+#ll_deploy_sharedlibs_command(windows-updater) \ No newline at end of file
diff --git a/install.xml b/install.xml
index 33875aee86..797bde5756 100644
--- a/install.xml
+++ b/install.xml
@@ -37,9 +37,9 @@
<key>windows</key>
<map>
<key>md5sum</key>
- <string>e6ba152b7edd4ad2c9db4f9ff7bd38e1</string>
+ <string>91155239b02f576384603795d41eb971</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/GL-windows-20080613.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/GL-windows-20090505.tar.bz2</uri>
</map>
</map>
</map>
@@ -48,31 +48,17 @@
<key>copyright</key>
<string>Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga</string>
<key>description</key>
- <string>The Simple DirectMedia Layer libraries are used for handling input and basic window/GL setup on the Linux client.</string>
+ <string>The Simple DirectMedia Layer libraries are used for handling input and basic window/GL setup on the Linux client. Packages also include cursors.</string>
<key>license</key>
<string>lgpl</string>
<key>packages</key>
<map>
- <key>darwin</key>
- <map>
- <key>md5sum</key>
- <string>7b07e7121a3623b2553ed36fb9024b40</string>
- <key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/SDL-1.2.5-darwin-20080818.tar.bz2</uri>
- </map>
<key>linux</key>
<map>
<key>md5sum</key>
- <string>25f8a8fc4ea94169fe6222571b8d5e55</string>
- <key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/SDL-1.2.12-linux-20081222c.tar.bz2</uri>
- </map>
- <key>windows</key>
- <map>
- <key>md5sum</key>
- <string>149626b0c10d7eb8b9f9be96b5318218</string>
+ <string>fce0ff7d2cdf0f36c1647e6a3916e29e</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/SDL-1.2.5-windows-20080613.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/SDL-1.2.12-linux-20090218.tar.bz2</uri>
</map>
</map>
</map>
@@ -85,9 +71,9 @@
<key>darwin</key>
<map>
<key>md5sum</key>
- <string>abd07d760cdc7d23da3b861f34b09c92</string>
+ <string>115d8ac44a91efdb173e9b3e478c46b6</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/apr_suite-1.2.8-darwin-20080812.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/apr_suite-1.3.7-darwin-20090805.tar.bz2</uri>
</map>
<key>linux</key>
<map>
@@ -106,9 +92,9 @@
<key>windows</key>
<map>
<key>md5sum</key>
- <string>b9d23a69a25fdeed96dcc3bf696b6514</string>
+ <string>a02619c1e30a3db02d3883bf1ad7a1e6</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/apr_suite-1.2.12-windows-20080806.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/apr_suite-1.3.8-windows-20090911.tar.bz2</uri>
</map>
</map>
</map>
@@ -146,9 +132,9 @@
<key>windows</key>
<map>
<key>md5sum</key>
- <string>6a53b02a07527de680f1336e20f74f08</string>
+ <string>f5cf8d121b26f2e7944f7e63cdbff04d</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/ares-1.4.0-windows-20080723.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/ares-1.6.0-windows-20091105.tar.bz2</uri>
</map>
</map>
</map>
@@ -207,30 +193,30 @@
<key>darwin</key>
<map>
<key>md5sum</key>
- <string>279834a12a0ed4531fd602594eac8509</string>
+ <string>609c469ee1857723260b5a9943b9c2c1</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.32.0-darwin-20080812.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.39.0-darwin-20091202.tar.bz2</uri>
</map>
<key>linux</key>
<map>
<key>md5sum</key>
- <string>b9a943052e5525da5417d6f471d70bc5</string>
+ <string>7085044567999489d82b9ed28f16e480</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.32.0-linux-20080812.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.39.0-linux-20091202.tar.bz2</uri>
</map>
<key>linux64</key>
<map>
<key>md5sum</key>
- <string>b97ae0855e77cc25b37ca63df093bb9b</string>
+ <string>b4aeefcba3d749f1e9f2a12c6f70192b</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.34.0-linux64-20080909.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.39.0-linux64-20091202.tar.bz2</uri>
</map>
<key>windows</key>
<map>
<key>md5sum</key>
- <string>d2b2ad9b46b9981c2a6be7c912bd17b4</string>
+ <string>6746ae9fd9aff98b15f7b9f0f40334ab</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.34.1-windows-20080723.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/boost-1.39.0-windows-20091204.tar.bz2</uri>
</map>
</map>
</map>
@@ -268,9 +254,9 @@
<key>windows</key>
<map>
<key>md5sum</key>
- <string>8c9d135f0e7cd1fae5681d4595942ee3</string>
+ <string>53e5ab7affff7121a5af2f82b4d58b54</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/curl-7.16.4-windows-20090306.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/curl-7.19.6-windows-20091016.tar.bz2</uri>
</map>
</map>
</map>
@@ -340,9 +326,9 @@
<key>darwin</key>
<map>
<key>md5sum</key>
- <string>9c5603e328e9f543e0a599d6b25be973</string>
+ <string>c457a0a041ac4946265889a503d26c3d</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/expat-1.95.8-darwin-20080812.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/expat-1.95.8-darwin-20090805.tar.bz2</uri>
</map>
<key>linux</key>
<map>
@@ -361,9 +347,9 @@
<key>windows</key>
<map>
<key>md5sum</key>
- <string>cca5ca3759f645d4a124d4b96df7f717</string>
+ <string>5dbbdb4a9b5bec86d180ef20a5f8ccfb</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/expat-1.95.8-windows-20080715.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/expat-1.95.8-windows-20090917.tar.bz2</uri>
</map>
</map>
</map>
@@ -415,6 +401,21 @@
</map>
</map>
</map>
+ <key>freeglut</key>
+ <map>
+ <key>license</key>
+ <string>mit</string>
+ <key>packages</key>
+ <map>
+ <key>windows</key>
+ <map>
+ <key>md5sum</key>
+ <string>fcbb695ff203775fad96d184bf5f34fc</string>
+ <key>url</key>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/freeglut-2.4.0-windows-20090608.tar.bz2</uri>
+ </map>
+ </map>
+ </map>
<key>freetype</key>
<map>
<key>copyright</key>
@@ -428,16 +429,16 @@
<key>darwin</key>
<map>
<key>md5sum</key>
- <string>694173293a483c01472a30cc7d895c5a</string>
+ <string>f00144dfb597140f328774c3244f0c3e</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/freetype-2.1.5-darwin-20080812.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/freetype-2.3.9-darwin-20090922.tar.bz2</uri>
</map>
<key>linux</key>
<map>
<key>md5sum</key>
- <string>eeffb03bd6672b6e7751448e5306d874</string>
+ <string>978ad7c67fe4a2419bfc841e2956ff9f</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/freetype-2.1.5-linux-20081201.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/freetype-2.3.9-linux-20090521c.tar.bz2</uri>
</map>
<key>linux64</key>
<map>
@@ -449,9 +450,9 @@
<key>windows</key>
<map>
<key>md5sum</key>
- <string>688944a961e16c2a89f81b60b2ff3acf</string>
+ <string>88980fd6d91ac541b62dea877ebe6ba6</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/freetype-2.1.5-windows-20080822.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/freetype-2.3.9-windows-20090917.tar.bz2</uri>
</map>
</map>
</map>
@@ -526,6 +527,28 @@
</map>
</map>
</map>
+ <key>glui</key>
+ <map>
+ <key>license</key>
+ <string>lgpl</string>
+ <key>packages</key>
+ <map>
+ <key>darwin</key>
+ <map>
+ <key>md5sum</key>
+ <string>84f792a860691d0fad6d1de6eeb31baa</string>
+ <key>url</key>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/glui-2.36-darwin-20090623a.tar.bz2</uri>
+ </map>
+ <key>windows</key>
+ <map>
+ <key>md5sum</key>
+ <string>5b8631fe510d4ebaeb965c673937e1e7</string>
+ <key>url</key>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/glui-2.3.6-windows-freeglut-20090608.tar.bz2</uri>
+ </map>
+ </map>
+ </map>
<key>google</key>
<map>
<key>license</key>
@@ -541,6 +564,58 @@
</map>
</map>
</map>
+ <key>google-perftools</key>
+ <map>
+ <key>copyright</key>
+ <string>Copyright (c) 2005, Google Inc.</string>
+ <key>description</key>
+ <string>Heap performance and validity checking tools from google. Includes TCMalloc, heap-checker, heap-profiler and cpu-profiler.</string>
+ <key>license</key>
+ <string>bsd</string>
+ <key>packages</key>
+ <map>
+ <key>windows</key>
+ <map>
+ <key>md5sum</key>
+ <string>32dba32ddd460a08e082898ebba6315c</string>
+ <key>url</key>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/google-perftools-1.0-windows-20090406.tar.bz2</uri>
+ </map>
+ </map>
+ </map>
+ <key>googlemock</key>
+ <map>
+ <key>copyright</key>
+ <string>Copyright 2008, Google Inc.</string>
+ <key>description</key>
+ <string>Google C++ Mocking Framework (or Google Mock for short) is a library for writing and using C++ mock classes.</string>
+ <key>license</key>
+ <string>bsd</string>
+ <key>packages</key>
+ <map>
+ <key>darwin</key>
+ <map>
+ <key>md5sum</key>
+ <string>4863e9fea433d0a4be761ea5d3e8346a</string>
+ <key>url</key>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/googlemock-1.1.0-darwin-20090626.tar.bz2</uri>
+ </map>
+ <key>linux</key>
+ <map>
+ <key>md5sum</key>
+ <string>877dabecf84339690191c6115c76366e</string>
+ <key>url</key>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/googlemock-1.1.0-linux32-20090527.tar.bz2</uri>
+ </map>
+ <key>windows</key>
+ <map>
+ <key>md5sum</key>
+ <string>f601a82ea91030974072da8924cae41e</string>
+ <key>url</key>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/googlemock-1.1.0-windows-20090921.tar.bz2</uri>
+ </map>
+ </map>
+ </map>
<key>gstreamer</key>
<map>
<key>license</key>
@@ -663,9 +738,9 @@
<key>windows</key>
<map>
<key>md5sum</key>
- <string>e40d2df9aaefb3bd57289fe96766353a</string>
+ <string>6a6bb0143a2561e3276dab4bcfa425ef</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/jpeglib-6b-windows-20080723.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/jpeglib-6b-windows-20090917a.tar.bz2</uri>
</map>
</map>
</map>
@@ -817,9 +892,9 @@ anguage Infrstructure (CLI) international standard</string>
<key>windows</key>
<map>
<key>md5sum</key>
- <string>a3975dcdb9a3ba0ca179b673b5e9b55e</string>
+ <string>c781cd9846cf20afb90ac40ad1a0ce9d</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/libpng-1.2.35-windows-20090306.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/libpng-1.2.35-windows-20090917.tar.bz2</uri>
</map>
</map>
</map>
@@ -864,39 +939,32 @@ anguage Infrstructure (CLI) international standard</string>
</map>
</map>
</map>
- <key>llmozlib</key>
+ <key>llqtwebkit</key>
<map>
<key>license</key>
- <string>mozillaPL</string>
+ <string>lgpl</string>
<key>packages</key>
<map>
<key>darwin</key>
<map>
<key>md5sum</key>
- <string>c951587726618d33646f2b169c290bd3</string>
+ <string>d97d843704514ae1b5f153fab2931920</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llmozlib-2_0_0_21-darwin-20090304.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-4.6-darwin-20100120.tar.bz2</uri>
</map>
<key>linux</key>
<map>
<key>md5sum</key>
- <string>b7ebcf0fb764ed4fa57c62d068b4a769</string>
- <key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llmozlib-linux-20090304prfhk.tar.bz2</uri>
- </map>
- <key>linux64</key>
- <map>
- <key>md5sum</key>
- <string>c2ae53462b56e0999ba386774ab0b789</string>
+ <string>c4c40fca14a8bd32096f8a27c75c526f</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llmozlib-linux64-20080909.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-linux-20100105c.tar.bz2</uri>
</map>
<key>windows</key>
<map>
<key>md5sum</key>
- <string>e9454e258b99668782d8570481b5eda1</string>
+ <string>18c1a4059bad1504a457e70c8c218033</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llmozlib-windows-20090306.tar.bz2</uri>
+ <uri>http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.6-20100120.tar.bz2</uri>
</map>
</map>
</map>
@@ -989,9 +1057,9 @@ anguage Infrstructure (CLI) international standard</string>
<key>windows</key>
<map>
<key>md5sum</key>
- <string>8ac100b5b711231b06be891c91cb68f3</string>
+ <string>f0df8a1e60991095e3adca1450b8c9c0</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/ndofdev-windows-20080723.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/ndofdev-windows-20090917.tar.bz2</uri>
</map>
</map>
</map>
@@ -1091,9 +1159,9 @@ anguage Infrstructure (CLI) international standard</string>
<key>linux</key>
<map>
<key>md5sum</key>
- <string>f0d9a8d1318b519cffe6c40c9cac4e21</string>
+ <string>75a7004ab14bea46594b1c652f1a6040</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/openal-linux-20081010c-59a71b14-plughw.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/openal-linux-20100120-3ad86a1c.tar.bz2</uri>
</map>
<key>linux64</key>
<map>
@@ -1151,10 +1219,57 @@ anguage Infrstructure (CLI) international standard</string>
</map>
</map>
</map>
+ <key>pth</key>
+ <map>
+ <key>copyright</key>
+ <string>Copyright (c) 1999-2006 Ralf S. Engelschall &lt;rse@gnu.org&gt;</string>
+ <key>description</key>
+ <string>Portable cooperative threads package, used to support Boost.Coroutine on Mac OS X 10.4</string>
+ <key>license</key>
+ <string>lgpl</string>
+ <key>packages</key>
+ <map>
+ <key>darwin</key>
+ <map>
+ <key>md5sum</key>
+ <string>216cb6217a06c64dfae30a55ab8b975c</string>
+ <key>url</key>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/pth-2.0.7-darwin-20090923.tar.bz2</uri>
+ </map>
+ <key>linux</key>
+ <map>
+ <key>md5sum</key>
+ <string>c5c2f73847c126e679d925beab48c7d4</string>
+ <key>url</key>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/pth-2.0.7-linux-20090427.tar.bz2</uri>
+ </map>
+ <key>linux32</key>
+ <map>
+ <key>md5sum</key>
+ <string>c5c2f73847c126e679d925beab48c7d4</string>
+ <key>url</key>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/pth-2.0.7-linux32-20090427.tar.bz2</uri>
+ </map>
+ <key>linux64</key>
+ <map>
+ <key>md5sum</key>
+ <string>c5c2f73847c126e679d925beab48c7d4</string>
+ <key>url</key>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/pth-2.0.7-linux64-20090427.tar.bz2</uri>
+ </map>
+ <key>windows</key>
+ <map>
+ <key>md5sum</key>
+ <string>c5c2f73847c126e679d925beab48c7d4</string>
+ <key>url</key>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/pth-2.0.7-windows-20090427.tar.bz2</uri>
+ </map>
+ </map>
+ </map>
<key>quicktime</key>
<map>
<key>copyright</key>
- <string>Copyright (C) 1990-2006 by Apple Computer, Inc., all rights reserved.</string>
+ <string>Copyright (C) 1990-2007 by Apple Computer, Inc., all rights reserved.</string>
<key>description</key>
<string>Separate download. Used to play in-world video clips on a prim. </string>
<key>license</key>
@@ -1164,9 +1279,9 @@ anguage Infrstructure (CLI) international standard</string>
<key>windows</key>
<map>
<key>md5sum</key>
- <string>7a2e6fc89b1ef027f3a36ebb46fb0c8a</string>
+ <string>be45825cc14ede53790ac93c58307dcb</string>
<key>url</key>
- <uri>scp:install-packages.lindenlab.com:/local/www/install-packages/doc/quicktime-windows-20080611.tar.bz2</uri>
+ <uri>scp:install-packages.lindenlab.com:/local/www/install-packages/doc/quicktime-sdk-windows-7.3-20091110.tar.bz2</uri>
</map>
</map>
</map>
@@ -1252,23 +1367,23 @@ anguage Infrstructure (CLI) international standard</string>
<key>darwin</key>
<map>
<key>md5sum</key>
- <string>8675b5eedef038b514338b17f0e55961</string>
+ <string>51f3fa1ab39563505df83b48ba432a3c</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/vivox-2.1.3010.6270-darwin-20090309.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/vivox-3.1.0001.7852-darwin-20100115.tar.bz2</uri>
</map>
<key>linux</key>
<map>
<key>md5sum</key>
- <string>01573510dce7f380f44e561ef2f3dd9f</string>
+ <string>ab9573d6aa2acdd79a553c144c9ecb09</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/vivox-2.1.3010.6270-linux-20090309.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/vivox-3.1.0001.7852-linux-20100115.tar.bz2</uri>
</map>
<key>windows</key>
<map>
<key>md5sum</key>
- <string>752daa90e07c05202d1f76980cb955eb</string>
+ <string>88ab785eebdc4f53a7dfc4e0b95f67ec</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/vivox-2.1.3010.6270-windows-20090309.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/vivox-3.1.0001.7852-windows-20100115.tar.bz2</uri>
</map>
</map>
</map>
@@ -1306,9 +1421,9 @@ anguage Infrstructure (CLI) international standard</string>
<key>windows</key>
<map>
<key>md5sum</key>
- <string>789988ea1fd8615137f843fbbe5b6bfa</string>
+ <string>262629bcaa39dcf7266caa50da01a599</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/xmlrpc-epi-0.51-windows-20080723.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/xmlrpc-epi-0.51-windows-20091016.tar.bz2</uri>
</map>
</map>
</map>
@@ -1332,9 +1447,9 @@ anguage Infrstructure (CLI) international standard</string>
<key>linux</key>
<map>
<key>md5sum</key>
- <string>80ee8d5a30563ce0f55d37fed6dfc744</string>
+ <string>26fe88213c213dc6153690ab142c25ca</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/zlib-1.2.3-linux-20090417.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/zlib-1.2.3dfsg-linux-20091208.tar.bz2</uri>
</map>
<key>linux64</key>
<map>
@@ -1346,9 +1461,9 @@ anguage Infrstructure (CLI) international standard</string>
<key>windows</key>
<map>
<key>md5sum</key>
- <string>9ad657cc5146fef77ffa8dd1c069018f</string>
+ <string>73baf52a740d151fddbc2a008369c462</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/zlib-1.2.3-windows-20080723.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/zlib-1.2.3-windows-20090921.tar.bz2</uri>
</map>
</map>
</map>
@@ -1550,7 +1665,7 @@ your work.
<key>glh_linear</key>
<map>
<key>text</key>
- <string>glh - is a platform-indepenedent C++ OpenGL helper library
+ <string>glh - is a platform-indepenedent C++ OpenGL helper library
Copyright (c) 2000 Cass Everitt
Copyright (c) 2000 NVIDIA Corporation
@@ -1562,14 +1677,14 @@ conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
-disclaimer.
+disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
-provided with the distribution.
+provided with the distribution.
The names of contributors to this software may not be used
to endorse or promote products derived from this software
-without specific prior written permission.
+without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
@@ -1580,13 +1695,18 @@ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
Cass Everitt - cass@r3.nu
</string>
</map>
+ <key>glut</key>
+ <map>
+ <key>url</key>
+ <string>http://www.xmission.com/~nate/glut/README-win32.txt</string>
+ </map>
<key>gpl</key>
<map>
<key>url</key>
@@ -1638,11 +1758,6 @@ Cass Everitt - cass@r3.nu
<key>text</key>
<string>http://www.jclark.com/xml/copying.txt</string>
</map>
- <key>mozillaPL</key>
- <map>
- <key>url</key>
- <string>http://www.mozilla.org/MPL/MPL-1.1.html</string>
- </map>
<key>ogg-vorbis</key>
<map>
<key>url</key>
@@ -1664,26 +1779,26 @@ Cass Everitt - cass@r3.nu
<string>ENGLISH
Apple Computer, Inc.
-QuickTime 7 Software Developer Kit (SDK)
+QuickTime 7 Software Developer Kit (SDK)
Software License Agreement
PLEASE READ THIS SOFTWARE LICENSE AGREEMENT ("LICENSE") BEFORE USING THE SOFTWARE. BY USING THE SOFTWARE, YOU ARE AGREEING TO BE BOUND BY THE TERMS OF THIS LICENSE. IF YOU ARE ACCESSING THE SOFTWARE ELECTRONICALLY, SIGNIFY YOUR AGREEMENT TO BE BOUND BY THE TERMS OF THIS LICENSE BY CLICKING THE "AGREE/ACCEPT" BUTTON. IF YOU DO NOT AGREE TO THE TERMS OF THIS LICENSE, RETURN THE APPLE SOFTWARE TO THE PLACE WHERE YOU OBTAINED IT FOR A REFUND OR, IF THE SOFTWARE WAS ACCESSED ELECTRONICALLY, CLICK "DISAGREE/DECLINE".
-IMPORTANT NOTE: To the extent this software may be used to reproduce materials, it is licensed to you only for reproduction of materials you are authorized or legally permitted to reproduce.
+IMPORTANT NOTE: To the extent this software may be used to reproduce materials, it is licensed to you only for reproduction of materials you are authorized or legally permitted to reproduce.
-1. License. Any software, tools, utilities, sample code, documentation, fonts, API?s, header files and other materials accompanying this License, whether on disk, print or electronic documentation, in read only memory, or any other media, (collectively, the "Apple Software") are licensed, not sold, to you by Apple Computer, Inc. ("Apple") for use only under the terms of this License, and Apple reserves all rights not expressly granted to you. The rights granted herein are limited to Apple's and its licensors' intellectual property rights in the Apple Software and do not include any other patents or intellectual property rights. You own the media on which the Apple Software is recorded but Apple and/or Apple's licensor(s) retain ownership of the Apple Software itself. The Apple Software in this package and any copies, modifications and derivative works that this License authorizes you to make are subject to this License.
+1. License. Any software, tools, utilities, sample code, documentation, fonts, API?s, header files and other materials accompanying this License, whether on disk, print or electronic documentation, in read only memory, or any other media, (collectively, the "Apple Software") are licensed, not sold, to you by Apple Computer, Inc. ("Apple") for use only under the terms of this License, and Apple reserves all rights not expressly granted to you. The rights granted herein are limited to Apple's and its licensors' intellectual property rights in the Apple Software and do not include any other patents or intellectual property rights. You own the media on which the Apple Software is recorded but Apple and/or Apple's licensor(s) retain ownership of the Apple Software itself. The Apple Software in this package and any copies, modifications and derivative works that this License authorizes you to make are subject to this License.
-2. Permitted Uses and Restrictions. You may use the Apple Software to develop application software that is compatible with, and runs only on Mac OS X and/or Windows platforms with QuickTime installed. Except for compiling header files and linking libraries as necessary to build your application software, you have no right to modify, incorporate into or include in combination with your own programs, license or otherwise redistribute any portion of the Apple Software. Your software application may not interfere with the functionality of QuickTime Player or the QuickTime Plug-in, including but not limited to file type or MIME type associations that are registered to QuickTime. You may make only as many internal use copies of the Apple Software as reasonably necessary to use the Apple Software as permitted in this paragraph and distribute such copies only to your employees whose job duties require them to so use the Apple Software. You must reproduce on each copy of the Apple Software or portion thereof, the Apple copyright notice and any other proprietary legends that were on the original copy of the Apple Software. Except as expressly permitted in this License, you may not decompile, reverse engineer, disassemble, modify, rent, lease, loan, sublicense, distribute or create derivative works based upon the Apple Software in whole or part. Your rights under this License will terminate automatically without notice from Apple if you fail to comply with any term(s) of this License. In addition, Apple reserves the right to terminate this License if a new version of Apple's operating system software or the Apple Software is released which is incompatible with the Apple Software.
+2. Permitted Uses and Restrictions. You may use the Apple Software to develop application software that is compatible with, and runs only on Mac OS X and/or Windows platforms with QuickTime installed. Except for compiling header files and linking libraries as necessary to build your application software, you have no right to modify, incorporate into or include in combination with your own programs, license or otherwise redistribute any portion of the Apple Software. Your software application may not interfere with the functionality of QuickTime Player or the QuickTime Plug-in, including but not limited to file type or MIME type associations that are registered to QuickTime. You may make only as many internal use copies of the Apple Software as reasonably necessary to use the Apple Software as permitted in this paragraph and distribute such copies only to your employees whose job duties require them to so use the Apple Software. You must reproduce on each copy of the Apple Software or portion thereof, the Apple copyright notice and any other proprietary legends that were on the original copy of the Apple Software. Except as expressly permitted in this License, you may not decompile, reverse engineer, disassemble, modify, rent, lease, loan, sublicense, distribute or create derivative works based upon the Apple Software in whole or part. Your rights under this License will terminate automatically without notice from Apple if you fail to comply with any term(s) of this License. In addition, Apple reserves the right to terminate this License if a new version of Apple's operating system software or the Apple Software is released which is incompatible with the Apple Software.
-3. Disclaimer Of Warranty. The Apple Software may be "alpha", "beta", "development", pre-release, untested, and/or not fully tested and may contain errors that could cause failures or loss of data, be incomplete or contain inaccuracies. YOU EXPRESSLY ACKNOWLEDGE AND AGREE THAT USE OF THE APPLE SOFTWARE IS AT YOUR SOLE RISK AND THAT THE ENTIRE RISK AS TO SATISFACTORY QUALITY, PERFORMANCE, ACCURACY AND EFFORT IS WITH YOU. EXCEPT FOR THE LIMITED WARRANTY ON MEDIA SET FORTH ABOVE AND TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE APPLE SOFTWARE IS PROVIDED "AS IS", WITH ALL FAULTS AND WITHOUT WARRANTY OF ANY KIND, AND APPLE AND APPLE'S LICENSORS (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE PURPOSES OF SECTIONS 4 AND 5) HEREBY DISCLAIM ALL WARRANTIES AND CONDITIONS WITH RESPECT TO THE APPLE SOFTWARE, EITHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NON-INFRINGEMENT OF THIRD PARTY RIGHTS. APPLE DOES NOT WARRANT AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE APPLE SOFTWARE, THAT THE FUNCTIONS CONTAINED IN THE APPLE SOFTWARE WILL MEET YOUR REQUIREMENTS, THAT THE OPERATION OF THE APPLE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE, OR THAT DEFECTS IN THE APPLE SOFTWARE WILL BE CORRECTED. NO ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE OR AN APPLE AUTHORIZED REPRESENTATIVE SHALL CREATE A WARRANTY. SHOULD THE APPLE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE ENTIRE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES OR LIMITATIONS ON APPLICABLE STATUTORY RIGHTS OF A CONSUMER, SO THE ABOVE EXCLUSION AND LIMITATIONS MAY NOT APPLY TO YOU.
+3. Disclaimer Of Warranty. The Apple Software may be "alpha", "beta", "development", pre-release, untested, and/or not fully tested and may contain errors that could cause failures or loss of data, be incomplete or contain inaccuracies. YOU EXPRESSLY ACKNOWLEDGE AND AGREE THAT USE OF THE APPLE SOFTWARE IS AT YOUR SOLE RISK AND THAT THE ENTIRE RISK AS TO SATISFACTORY QUALITY, PERFORMANCE, ACCURACY AND EFFORT IS WITH YOU. EXCEPT FOR THE LIMITED WARRANTY ON MEDIA SET FORTH ABOVE AND TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE APPLE SOFTWARE IS PROVIDED "AS IS", WITH ALL FAULTS AND WITHOUT WARRANTY OF ANY KIND, AND APPLE AND APPLE'S LICENSORS (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE PURPOSES OF SECTIONS 4 AND 5) HEREBY DISCLAIM ALL WARRANTIES AND CONDITIONS WITH RESPECT TO THE APPLE SOFTWARE, EITHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NON-INFRINGEMENT OF THIRD PARTY RIGHTS. APPLE DOES NOT WARRANT AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE APPLE SOFTWARE, THAT THE FUNCTIONS CONTAINED IN THE APPLE SOFTWARE WILL MEET YOUR REQUIREMENTS, THAT THE OPERATION OF THE APPLE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE, OR THAT DEFECTS IN THE APPLE SOFTWARE WILL BE CORRECTED. NO ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE OR AN APPLE AUTHORIZED REPRESENTATIVE SHALL CREATE A WARRANTY. SHOULD THE APPLE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE ENTIRE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES OR LIMITATIONS ON APPLICABLE STATUTORY RIGHTS OF A CONSUMER, SO THE ABOVE EXCLUSION AND LIMITATIONS MAY NOT APPLY TO YOU.
4. Limitation Of Liability. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT SHALL APPLE BE LIABLE FOR PERSONAL INJURY, OR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES WHATSOEVER, INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, LOSS OF DATA, BUSINESS INTERRUPTION OR ANY OTHER COMMERCIAL DAMAGES OR LOSSES, ARISING OUT OF OR RELATED TO YOUR USE OR INABILITY TO USE THE APPLE SOFTWARE, HOWEVER CAUSED, REGARDLESS OF THE THEORY OF LIABILITY (CONTRACT, TORT OR OTHERWISE) AND EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY FOR PERSONAL INJURY, OR OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY TO YOU. In no event shall Apple's total liability to you for all damages (other than as may be required by applicable law in cases involving personal injury) exceed the amount of fifty dollars ($50.00). The foregoing limitations will apply even if the above stated remedy fails of its essential purpose.
-5. Export Control. You may not use or otherwise export or reexport the Apple Product except as authorized by United States law and the laws of the jurisdiction in which the Apple Product was obtained. In particular, but without limitation, the Apple Product may not be exported or re-exported (a) into any U.S. embargoed countries or (b) to anyone on the U.S. Treasury Department's list of Specially Designated Nationals or the U.S. Department of Commerce Denied Person?s List or Entity List. By using the Apple Product, you represent and warrant that you are not located in any such country or on any such list.
+5. Export Control. You may not use or otherwise export or reexport the Apple Product except as authorized by United States law and the laws of the jurisdiction in which the Apple Product was obtained. In particular, but without limitation, the Apple Product may not be exported or re-exported (a) into any U.S. embargoed countries or (b) to anyone on the U.S. Treasury Department's list of Specially Designated Nationals or the U.S. Department of Commerce Denied Person?s List or Entity List. By using the Apple Product, you represent and warrant that you are not located in any such country or on any such list.
6. Government End Users. The Apple Software and related documentation are "Commercial Items", as that term is defined at 48 C.F.R. ?2.101, consisting of "Commercial Computer Software" and "Commercial Computer Software Documentation", as such terms are used in 48 C.F.R. ?12.212 or 48 C.F.R. ?227.7202, as applicable. Consistent with 48 C.F.R. ?12.212 or 48 C.F.R. ?227.7202-1through 227.7202-4, as applicable, the Commercial Computer Software and Commercial Computer Software Documentation are being licensed to U.S. Government end users (a) only as Commercial Items and (b) with only those rights as are granted to all other end users pursuant to the terms and conditions herein. Unpublished-rights reserved under the copyright laws of the United States.
-7. Controlling Law and Severability. This License will be governed by and construed in accordance with the laws of the State of California, as applied to agreements entered into and to be performed entirely within California between California residents. This License shall not be governed by the United Nations Convention on Contracts for the International Sale of Goods, the application of which is expressly excluded. If for any reason a court of competent jurisdiction finds any provision, or portion thereof, to be unenforceable, the remainder of this License shall continue in full force and effect.
+7. Controlling Law and Severability. This License will be governed by and construed in accordance with the laws of the State of California, as applied to agreements entered into and to be performed entirely within California between California residents. This License shall not be governed by the United Nations Convention on Contracts for the International Sale of Goods, the application of which is expressly excluded. If for any reason a court of competent jurisdiction finds any provision, or portion thereof, to be unenforceable, the remainder of this License shall continue in full force and effect.
8. Complete Agreement. This License constitutes the entire agreement between the parties with respect to the use of the Apple Software licensed hereunder and supersedes all prior or contemporaneous understandings regarding such subject matter. No amendment to or modification of this License will be binding unless in writing and signed by Apple. Any translation of this License is done for local requirements and in the event of a dispute between the English and any non-English versions, the English version of this License shall govern.
diff --git a/scripts/install.py b/scripts/install.py
index 6278fba16c..7368af0b37 100755
--- a/scripts/install.py
+++ b/scripts/install.py
@@ -64,7 +64,6 @@ def add_indra_lib_path():
base_dir = add_indra_lib_path()
import copy
-import md5
import optparse
import os
import platform
@@ -75,7 +74,12 @@ import tempfile
import urllib2
import urlparse
-from sets import Set as set, ImmutableSet as frozenset
+try:
+ # Python 2.6
+ from hashlib import md5
+except ImportError:
+ # Python 2.5 and earlier
+ from md5 import new as md5
from indra.base import llsd
from indra.util import helpformatter
@@ -106,7 +110,7 @@ class InstallFile(object):
return "ifile{%s:%s}" % (self.pkgname, self.url)
def _is_md5sum_match(self):
- hasher = md5.new(file(self.filename, 'rb').read())
+ hasher = md5(file(self.filename, 'rb').read())
if hasher.hexdigest() == self.md5sum:
return True
return False
@@ -789,8 +793,13 @@ def _getuser():
import getpass
return getpass.getuser()
except ImportError:
- import win32api
- return win32api.GetUserName()
+ import ctypes
+ MAX_PATH = 260 # according to a recent WinDef.h
+ name = ctypes.create_unicode_buffer(MAX_PATH)
+ namelen = ctypes.c_int(len(name)) # len in chars, NOT bytes
+ if not ctypes.windll.advapi32.GetUserNameW(name, ctypes.byref(namelen)):
+ raise ctypes.WinError()
+ return name.value
def _default_installable_cache():
"""In general, the installable files do not change much, so find a
diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg
index 23efd65c45..c50ae4ad80 100644
--- a/scripts/messages/message_template.msg
+++ b/scripts/messages/message_template.msg
@@ -53,7 +53,7 @@ version 2.0
// OpenCircuit - Tells the recipient's messaging system to open the descibed circuit
{
- OpenCircuit Fixed 0xFFFFFFFC NotTrusted Unencoded
+ OpenCircuit Fixed 0xFFFFFFFC NotTrusted Unencoded UDPBlackListed
{
CircuitInfo Single
{ IP IPADDR }
@@ -5288,6 +5288,10 @@ version 2.0
{ AgentLegacyAccess U8 }
{ AgentMaxAccess U8 }
}
+ {
+ AgentInfo Variable
+ { Flags U32 }
+ }
}
// ChildAgentAlive
@@ -8945,3 +8949,24 @@ version 2.0
{ CRC U32 }
}
}
+
+// Link inventory
+{
+ LinkInventoryItem Low 426 NotTrusted Zerocoded
+ {
+ AgentData Single
+ { AgentID LLUUID }
+ { SessionID LLUUID }
+ }
+ {
+ InventoryBlock Single
+ { CallbackID U32 } // Async Response
+ { FolderID LLUUID }
+ { TransactionID LLUUID } // Going to become TransactionID
+ { OldItemID LLUUID }
+ { Type S8 }
+ { InvType S8 }
+ { Name Variable 1 }
+ { Description Variable 1 }
+ }
+}
diff --git a/scripts/template_verifier.py b/scripts/template_verifier.py
index 8bb5e1d76d..d5fc119270 100755
--- a/scripts/template_verifier.py
+++ b/scripts/template_verifier.py
@@ -203,8 +203,13 @@ def getuser():
import getpass
return getpass.getuser()
except ImportError:
- import win32api
- return win32api.GetUserName()
+ import ctypes
+ MAX_PATH = 260 # according to a recent WinDef.h
+ name = ctypes.create_unicode_buffer(MAX_PATH)
+ namelen = ctypes.c_int(len(name)) # len in chars, NOT bytes
+ if not ctypes.windll.advapi32.GetUserNameW(name, ctypes.byref(namelen)):
+ raise ctypes.WinError()
+ return name.value
def local_master_cache_filename():
"""Returns the location of the master template cache (which is in the system tempdir)
diff --git a/scripts/update_version_files.py b/scripts/update_version_files.py
index 9081941521..da60fd105a 100755
--- a/scripts/update_version_files.py
+++ b/scripts/update_version_files.py
@@ -47,6 +47,9 @@ def usage():
Options:
--version
Specify the version string to replace current version.
+ --revision
+ Specify the revision to replace the last digit of the version.
+ By default, revision is computed from the version control system.
--skip-on-branch
Specify a regular expression against which the current branch
is matched. If it matches, then leave version strings alone.
@@ -161,6 +164,7 @@ def main():
opts, args = getopt.getopt(sys.argv[1:],
"",
['version=',
+ 'revision=',
'channel=',
'server_channel=',
'skip-on-branch=',
@@ -171,12 +175,15 @@ def main():
update_server = False
update_viewer = False
new_version = None
+ new_revision = None
new_viewer_channel = None
new_server_channel = None
skip_on_branch_re = None
for o,a in opts:
if o in ('--version'):
new_version = a
+ if o in ('--revision'):
+ new_revision = a
if o in ('--skip-on-branch'):
skip_on_branch_re = re.compile(a)
if o in ('--channel'):
@@ -241,23 +248,26 @@ def main():
if update_server:
server_version = new_version
else:
- # Assume we're updating just the build number
- cl = '%s info "%s"' % (svn, src_root)
- status, output = _getstatusoutput(cl)
- if verbose:
- print
- print "svn info output:"
- print "----------------"
- print output
-
- branch_match = svn_branch_re.search(output)
- revision_match = svn_revision_re.search(output)
- if not branch_match or not revision_match:
- print "Failed to execute svn info, output follows:"
- print output
+
+ if llversion.using_svn():
+ if new_revision:
+ revision = new_revision
+ else:
+ revision = llversion.get_svn_revision()
+ branch = llversion.get_svn_branch()
+ elif llversion.using_hg():
+ if new_revision:
+ revision = new_revision
+ else:
+ revision = llversion.get_hg_changeset()
+ branch = llversion.get_hg_repo()
+ elif new_revision:
+ revision = new_revision
+ branch = "unknown"
+ else:
+ print >>sys.stderr, "ERROR: could not determine revision and branch"
return -1
- branch = branch_match.group(1)
- revision = revision_match.group(1)
+
if skip_on_branch_re and skip_on_branch_re.match(branch):
print "Release Candidate Build, leaving version files untouched."
return 0